summaryrefslogtreecommitdiff
path: root/thirdparty
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty')
-rw-r--r--thirdparty/README.md245
-rw-r--r--thirdparty/assimp/contrib/utf8cpp/doc/ReleaseNotes12
-rw-r--r--thirdparty/assimp/contrib/utf8cpp/doc/utf8cpp.html1789
-rw-r--r--thirdparty/assimp/include/assimp/config.h (renamed from thirdparty/assimp/assimp/config.h)291
-rw-r--r--thirdparty/assimp/revision.h (renamed from thirdparty/assimp/code/revision.h)0
-rw-r--r--thirdparty/b2d_convexdecomp/b2Glue.h174
-rw-r--r--thirdparty/b2d_convexdecomp/b2Polygon.cpp1591
-rw-r--r--thirdparty/b2d_convexdecomp/b2Polygon.h133
-rw-r--r--thirdparty/b2d_convexdecomp/b2Triangle.cpp82
-rw-r--r--thirdparty/b2d_convexdecomp/b2Triangle.h41
-rw-r--r--thirdparty/basis_universal/LICENSE201
-rw-r--r--thirdparty/basis_universal/basisu_astc_decomp.cpp1550
-rw-r--r--thirdparty/basis_universal/basisu_astc_decomp.h43
-rw-r--r--thirdparty/basis_universal/basisu_backend.cpp1674
-rw-r--r--thirdparty/basis_universal/basisu_backend.h327
-rw-r--r--thirdparty/basis_universal/basisu_basis_file.cpp204
-rw-r--r--thirdparty/basis_universal/basisu_basis_file.h70
-rw-r--r--thirdparty/basis_universal/basisu_comp.cpp1206
-rw-r--r--thirdparty/basis_universal/basisu_comp.h430
-rw-r--r--thirdparty/basis_universal/basisu_enc.cpp1376
-rw-r--r--thirdparty/basis_universal/basisu_enc.h2806
-rw-r--r--thirdparty/basis_universal/basisu_etc.cpp1074
-rw-r--r--thirdparty/basis_universal/basisu_etc.h1046
-rw-r--r--thirdparty/basis_universal/basisu_frontend.cpp2432
-rw-r--r--thirdparty/basis_universal/basisu_frontend.h354
-rw-r--r--thirdparty/basis_universal/basisu_global_selector_palette_helpers.cpp71
-rw-r--r--thirdparty/basis_universal/basisu_global_selector_palette_helpers.h46
-rw-r--r--thirdparty/basis_universal/basisu_gpu_texture.cpp1451
-rw-r--r--thirdparty/basis_universal/basisu_gpu_texture.h154
-rw-r--r--thirdparty/basis_universal/basisu_pvrtc1_4.cpp269
-rw-r--r--thirdparty/basis_universal/basisu_pvrtc1_4.h363
-rw-r--r--thirdparty/basis_universal/basisu_resample_filters.cpp328
-rw-r--r--thirdparty/basis_universal/basisu_resampler.cpp852
-rw-r--r--thirdparty/basis_universal/basisu_resampler.h196
-rw-r--r--thirdparty/basis_universal/basisu_resampler_filters.h35
-rw-r--r--thirdparty/basis_universal/basisu_ssim.cpp408
-rw-r--r--thirdparty/basis_universal/basisu_ssim.h44
-rw-r--r--thirdparty/basis_universal/lodepng.cpp6006
-rw-r--r--thirdparty/basis_universal/lodepng.h1930
-rw-r--r--thirdparty/basis_universal/transcoder/basisu.h386
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_file_headers.h121
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_global_selector_cb.h272
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h673
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder.cpp10532
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder.h377
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_internal.h754
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_astc.inc481
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_astc_0_255.inc481
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_atc_55.inc481
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_atc_56.inc481
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m5_alpha.inc49
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m5_color.inc481
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m6.inc4383
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_dxt1_5.inc494
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_dxt1_6.inc494
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_pvrtc2_45.inc481
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_tables_pvrtc2_alpha_33.inc481
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Logging.h16
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Scalar.h34
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp2
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h2
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h2
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp4
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h7
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h176
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h13
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp4
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h6
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp22
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h1
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h8
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp4
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp7
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp6
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp93
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h3
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp15
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h4
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp14
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h39
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h2
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h2
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h2
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h8
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp40
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h4
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h3
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp36
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h10
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp5
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h7
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp2
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h18
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp11
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h1
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp863
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h124
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp12
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h18
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h3
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp27
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h86
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp2
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp277
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h35
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp34
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp215
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h7
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp953
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h17
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h247
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h83
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h2
-rw-r--r--thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h46
-rw-r--r--thirdparty/bullet/BulletSoftBody/btCGProjection.h106
-rw-r--r--thirdparty/bullet/BulletSoftBody/btConjugateGradient.h158
-rw-r--r--thirdparty/bullet/BulletSoftBody/btConjugateResidual.h188
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp4
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h4
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp227
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h173
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp485
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h162
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp575
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h266
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp634
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h100
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h127
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h107
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h373
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h340
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h301
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMousePickingForce.h145
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp143
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h61
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp808
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h311
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h421
-rw-r--r--thirdparty/bullet/BulletSoftBody/btPreconditioner.h288
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBody.cpp1288
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBody.h359
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp401
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h20
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h1203
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h7
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp3
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSparseSDF.h81
-rw-r--r--thirdparty/bullet/BulletSoftBody/poly34.cpp419
-rw-r--r--thirdparty/bullet/BulletSoftBody/poly34.h38
-rw-r--r--thirdparty/bullet/LinearMath/btImplicitQRSVD.h916
-rw-r--r--thirdparty/bullet/LinearMath/btMatrix3x3.h23
-rw-r--r--thirdparty/bullet/LinearMath/btMatrixX.h18
-rw-r--r--thirdparty/bullet/LinearMath/btModifiedGramSchmidt.h83
-rw-r--r--thirdparty/bullet/LinearMath/btReducedVector.cpp170
-rw-r--r--thirdparty/bullet/LinearMath/btReducedVector.h320
-rw-r--r--thirdparty/bullet/LinearMath/btScalar.h26
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer.cpp1198
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer.h2
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer64.cpp1197
-rw-r--r--thirdparty/bullet/btBulletCollisionAll.cpp1
-rw-r--r--thirdparty/bullet/btLinearMathAll.cpp1
-rw-r--r--thirdparty/enet/LICENSE2
-rw-r--r--thirdparty/enet/enet/enet.h24
-rw-r--r--thirdparty/enet/enet/godot.h4
-rw-r--r--thirdparty/enet/enet/utility.h1
-rw-r--r--thirdparty/enet/godot.cpp385
-rw-r--r--thirdparty/enet/patches/dtls_support.patch13
-rw-r--r--thirdparty/enet/patches/ipv6_support.patch105
-rw-r--r--thirdparty/enet/peer.c27
-rw-r--r--thirdparty/enet/protocol.c75
-rw-r--r--thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8.cpp24
-rw-r--r--thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8A1.cpp24
-rw-r--r--thirdparty/etc2comp/patches/fix-rgba8-max-channels.patch224
-rw-r--r--thirdparty/freetype/include/freetype/config/ftconfig.h2
-rw-r--r--thirdparty/freetype/include/freetype/config/ftheader.h2
-rw-r--r--thirdparty/freetype/include/freetype/config/ftoption.h22
-rw-r--r--thirdparty/freetype/include/freetype/config/ftstdlib.h2
-rw-r--r--thirdparty/freetype/include/freetype/freetype.h35
-rw-r--r--thirdparty/freetype/include/freetype/ftadvanc.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftbbox.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftbdf.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftbitmap.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftbzip2.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftcache.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftcid.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftcolor.h17
-rw-r--r--thirdparty/freetype/include/freetype/ftdriver.h2
-rw-r--r--thirdparty/freetype/include/freetype/fterrdef.h2
-rw-r--r--thirdparty/freetype/include/freetype/fterrors.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftfntfmt.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftgasp.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftglyph.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftgxval.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftgzip.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftimage.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftincrem.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftlcdfil.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftlist.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftlzw.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftmac.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftmm.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftmodapi.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftmoderr.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftotval.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftoutln.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftparams.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftpfr.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftrender.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftsizes.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftsnames.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftstroke.h36
-rw-r--r--thirdparty/freetype/include/freetype/ftsynth.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftsystem.h2
-rw-r--r--thirdparty/freetype/include/freetype/fttrigon.h2
-rw-r--r--thirdparty/freetype/include/freetype/fttypes.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftwinfnt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/autohint.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/cffotypes.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/cfftypes.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftcalc.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftdebug.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftdrv.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftgloadr.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftmemory.h18
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftobjs.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftpsprop.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftrfork.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftserv.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftstream.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/fttrace.h3
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftvalid.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/internal.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/psaux.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/pshints.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svbdf.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svcfftl.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svcid.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svfntfmt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svgldict.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svgxval.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svkern.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svmetric.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svmm.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svotval.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpfr.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpostnm.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svprop.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpscmap.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpsinfo.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svsfnt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svttcmap.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svtteng.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svttglyf.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svwinfnt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/sfnt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/t1types.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/tttypes.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/wofftypes.h203
-rw-r--r--thirdparty/freetype/include/freetype/t1tables.h2
-rw-r--r--thirdparty/freetype/include/freetype/ttnameid.h2
-rw-r--r--thirdparty/freetype/include/freetype/tttables.h2
-rw-r--r--thirdparty/freetype/include/freetype/tttags.h3
-rw-r--r--thirdparty/freetype/include/ft2build.h2
-rw-r--r--thirdparty/freetype/src/autofit/afangles.c2
-rw-r--r--thirdparty/freetype/src/autofit/afblue.c12
-rw-r--r--thirdparty/freetype/src/autofit/afblue.cin2
-rw-r--r--thirdparty/freetype/src/autofit/afblue.dat15
-rw-r--r--thirdparty/freetype/src/autofit/afblue.h88
-rw-r--r--thirdparty/freetype/src/autofit/afblue.hin2
-rw-r--r--thirdparty/freetype/src/autofit/afcjk.c4
-rw-r--r--thirdparty/freetype/src/autofit/afcjk.h2
-rw-r--r--thirdparty/freetype/src/autofit/afcover.h2
-rw-r--r--thirdparty/freetype/src/autofit/afdummy.c2
-rw-r--r--thirdparty/freetype/src/autofit/afdummy.h2
-rw-r--r--thirdparty/freetype/src/autofit/aferrors.h2
-rw-r--r--thirdparty/freetype/src/autofit/afglobal.c2
-rw-r--r--thirdparty/freetype/src/autofit/afglobal.h2
-rw-r--r--thirdparty/freetype/src/autofit/afhints.c2
-rw-r--r--thirdparty/freetype/src/autofit/afhints.h2
-rw-r--r--thirdparty/freetype/src/autofit/afindic.c2
-rw-r--r--thirdparty/freetype/src/autofit/afindic.h2
-rw-r--r--thirdparty/freetype/src/autofit/aflatin.c6
-rw-r--r--thirdparty/freetype/src/autofit/aflatin.h2
-rw-r--r--thirdparty/freetype/src/autofit/aflatin2.c3
-rw-r--r--thirdparty/freetype/src/autofit/aflatin2.h2
-rw-r--r--thirdparty/freetype/src/autofit/afloader.c2
-rw-r--r--thirdparty/freetype/src/autofit/afloader.h2
-rw-r--r--thirdparty/freetype/src/autofit/afmodule.c2
-rw-r--r--thirdparty/freetype/src/autofit/afmodule.h2
-rw-r--r--thirdparty/freetype/src/autofit/afranges.c14
-rw-r--r--thirdparty/freetype/src/autofit/afranges.h2
-rw-r--r--thirdparty/freetype/src/autofit/afscript.h8
-rw-r--r--thirdparty/freetype/src/autofit/afshaper.c2
-rw-r--r--thirdparty/freetype/src/autofit/afshaper.h2
-rw-r--r--thirdparty/freetype/src/autofit/afstyles.h9
-rw-r--r--thirdparty/freetype/src/autofit/aftypes.h2
-rw-r--r--thirdparty/freetype/src/autofit/afwarp.c2
-rw-r--r--thirdparty/freetype/src/autofit/afwarp.h2
-rw-r--r--thirdparty/freetype/src/autofit/afwrtsys.h2
-rw-r--r--thirdparty/freetype/src/autofit/autofit.c2
-rw-r--r--thirdparty/freetype/src/autofit/module.mk2
-rw-r--r--thirdparty/freetype/src/autofit/rules.mk2
-rw-r--r--thirdparty/freetype/src/base/ftadvanc.c2
-rw-r--r--thirdparty/freetype/src/base/ftbase.c2
-rw-r--r--thirdparty/freetype/src/base/ftbase.h2
-rw-r--r--thirdparty/freetype/src/base/ftbbox.c10
-rw-r--r--thirdparty/freetype/src/base/ftbdf.c2
-rw-r--r--thirdparty/freetype/src/base/ftbitmap.c2
-rw-r--r--thirdparty/freetype/src/base/ftcalc.c2
-rw-r--r--thirdparty/freetype/src/base/ftcid.c2
-rw-r--r--thirdparty/freetype/src/base/ftcolor.c2
-rw-r--r--thirdparty/freetype/src/base/ftdbgmem.c8
-rw-r--r--thirdparty/freetype/src/base/ftdebug.c2
-rw-r--r--thirdparty/freetype/src/base/fterrors.c2
-rw-r--r--thirdparty/freetype/src/base/ftfntfmt.c2
-rw-r--r--thirdparty/freetype/src/base/ftfstype.c2
-rw-r--r--thirdparty/freetype/src/base/ftgasp.c2
-rw-r--r--thirdparty/freetype/src/base/ftgloadr.c22
-rw-r--r--thirdparty/freetype/src/base/ftglyph.c2
-rw-r--r--thirdparty/freetype/src/base/ftgxval.c2
-rw-r--r--thirdparty/freetype/src/base/ftinit.c2
-rw-r--r--thirdparty/freetype/src/base/ftlcdfil.c2
-rw-r--r--thirdparty/freetype/src/base/ftmac.c2
-rw-r--r--thirdparty/freetype/src/base/ftmm.c2
-rw-r--r--thirdparty/freetype/src/base/ftobjs.c2
-rw-r--r--thirdparty/freetype/src/base/ftotval.c2
-rw-r--r--thirdparty/freetype/src/base/ftoutln.c4
-rw-r--r--thirdparty/freetype/src/base/ftpatent.c2
-rw-r--r--thirdparty/freetype/src/base/ftpfr.c2
-rw-r--r--thirdparty/freetype/src/base/ftpsprop.c6
-rw-r--r--thirdparty/freetype/src/base/ftrfork.c2
-rw-r--r--thirdparty/freetype/src/base/ftsnames.c2
-rw-r--r--thirdparty/freetype/src/base/ftstream.c4
-rw-r--r--thirdparty/freetype/src/base/ftstroke.c215
-rw-r--r--thirdparty/freetype/src/base/ftsynth.c2
-rw-r--r--thirdparty/freetype/src/base/ftsystem.c2
-rw-r--r--thirdparty/freetype/src/base/fttrigon.c2
-rw-r--r--thirdparty/freetype/src/base/fttype1.c2
-rw-r--r--thirdparty/freetype/src/base/ftutil.c2
-rw-r--r--thirdparty/freetype/src/base/ftver.rc8
-rw-r--r--thirdparty/freetype/src/base/ftwinfnt.c2
-rw-r--r--thirdparty/freetype/src/base/rules.mk2
-rw-r--r--thirdparty/freetype/src/bzip2/ftbzip2.c2
-rw-r--r--thirdparty/freetype/src/bzip2/rules.mk2
-rw-r--r--thirdparty/freetype/src/cache/ftcache.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcbasic.c2
-rw-r--r--thirdparty/freetype/src/cache/ftccache.c2
-rw-r--r--thirdparty/freetype/src/cache/ftccache.h2
-rw-r--r--thirdparty/freetype/src/cache/ftccback.h2
-rw-r--r--thirdparty/freetype/src/cache/ftccmap.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcerror.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcglyph.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcglyph.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcimage.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcimage.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcmanag.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcmanag.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcmru.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcmru.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcsbits.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcsbits.h2
-rw-r--r--thirdparty/freetype/src/cache/rules.mk2
-rw-r--r--thirdparty/freetype/src/cff/cff.c2
-rw-r--r--thirdparty/freetype/src/cff/cffcmap.c2
-rw-r--r--thirdparty/freetype/src/cff/cffcmap.h2
-rw-r--r--thirdparty/freetype/src/cff/cffdrivr.c2
-rw-r--r--thirdparty/freetype/src/cff/cffdrivr.h2
-rw-r--r--thirdparty/freetype/src/cff/cfferrs.h2
-rw-r--r--thirdparty/freetype/src/cff/cffgload.c2
-rw-r--r--thirdparty/freetype/src/cff/cffgload.h2
-rw-r--r--thirdparty/freetype/src/cff/cffload.c4
-rw-r--r--thirdparty/freetype/src/cff/cffload.h2
-rw-r--r--thirdparty/freetype/src/cff/cffobjs.c8
-rw-r--r--thirdparty/freetype/src/cff/cffobjs.h2
-rw-r--r--thirdparty/freetype/src/cff/cffparse.c2
-rw-r--r--thirdparty/freetype/src/cff/cffparse.h2
-rw-r--r--thirdparty/freetype/src/cff/cfftoken.h2
-rw-r--r--thirdparty/freetype/src/cff/module.mk2
-rw-r--r--thirdparty/freetype/src/cff/rules.mk2
-rw-r--r--thirdparty/freetype/src/cid/ciderrs.h2
-rw-r--r--thirdparty/freetype/src/cid/cidgload.c2
-rw-r--r--thirdparty/freetype/src/cid/cidgload.h2
-rw-r--r--thirdparty/freetype/src/cid/cidload.c4
-rw-r--r--thirdparty/freetype/src/cid/cidload.h2
-rw-r--r--thirdparty/freetype/src/cid/cidobjs.c2
-rw-r--r--thirdparty/freetype/src/cid/cidobjs.h2
-rw-r--r--thirdparty/freetype/src/cid/cidparse.c2
-rw-r--r--thirdparty/freetype/src/cid/cidparse.h2
-rw-r--r--thirdparty/freetype/src/cid/cidriver.c2
-rw-r--r--thirdparty/freetype/src/cid/cidriver.h2
-rw-r--r--thirdparty/freetype/src/cid/cidtoken.h2
-rw-r--r--thirdparty/freetype/src/cid/module.mk2
-rw-r--r--thirdparty/freetype/src/cid/rules.mk2
-rw-r--r--thirdparty/freetype/src/cid/type1cid.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/README2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvalid.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvalid.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvbsln.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvcommn.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvcommn.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxverror.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfeat.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfeat.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfgen.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvjust.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvkern.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvlcar.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmod.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmod.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort0.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort1.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort2.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort4.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort5.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx0.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx1.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx2.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx4.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx5.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvopbd.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvprop.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvtrak.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/module.mk2
-rw-r--r--thirdparty/freetype/src/gxvalid/rules.mk2
-rw-r--r--thirdparty/freetype/src/gzip/ftgzip.c12
-rw-r--r--thirdparty/freetype/src/gzip/infutil.h2
-rw-r--r--thirdparty/freetype/src/gzip/rules.mk2
-rw-r--r--thirdparty/freetype/src/lzw/ftlzw.c2
-rw-r--r--thirdparty/freetype/src/lzw/ftzopen.c2
-rw-r--r--thirdparty/freetype/src/lzw/ftzopen.h2
-rw-r--r--thirdparty/freetype/src/lzw/rules.mk2
-rw-r--r--thirdparty/freetype/src/otvalid/module.mk2
-rw-r--r--thirdparty/freetype/src/otvalid/otvalid.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvalid.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otvbase.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvcommn.c5
-rw-r--r--thirdparty/freetype/src/otvalid/otvcommn.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otverror.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otvgdef.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvgpos.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvgpos.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otvgsub.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvjstf.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvmath.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvmod.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvmod.h2
-rw-r--r--thirdparty/freetype/src/otvalid/rules.mk2
-rw-r--r--thirdparty/freetype/src/pfr/module.mk2
-rw-r--r--thirdparty/freetype/src/pfr/pfr.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrcmap.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrcmap.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrdrivr.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrdrivr.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrerror.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrgload.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrgload.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrload.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrload.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrobjs.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrobjs.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrsbit.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrsbit.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrtypes.h2
-rw-r--r--thirdparty/freetype/src/pfr/rules.mk2
-rw-r--r--thirdparty/freetype/src/psaux/afmparse.c2
-rw-r--r--thirdparty/freetype/src/psaux/afmparse.h2
-rw-r--r--thirdparty/freetype/src/psaux/cffdecode.c7
-rw-r--r--thirdparty/freetype/src/psaux/cffdecode.h2
-rw-r--r--thirdparty/freetype/src/psaux/module.mk2
-rw-r--r--thirdparty/freetype/src/psaux/psaux.c2
-rw-r--r--thirdparty/freetype/src/psaux/psauxerr.h2
-rw-r--r--thirdparty/freetype/src/psaux/psauxmod.c2
-rw-r--r--thirdparty/freetype/src/psaux/psauxmod.h2
-rw-r--r--thirdparty/freetype/src/psaux/psconv.c2
-rw-r--r--thirdparty/freetype/src/psaux/psconv.h2
-rw-r--r--thirdparty/freetype/src/psaux/psft.c8
-rw-r--r--thirdparty/freetype/src/psaux/psintrp.c22
-rw-r--r--thirdparty/freetype/src/psaux/psobjs.c6
-rw-r--r--thirdparty/freetype/src/psaux/psobjs.h2
-rw-r--r--thirdparty/freetype/src/psaux/rules.mk2
-rw-r--r--thirdparty/freetype/src/psaux/t1cmap.c2
-rw-r--r--thirdparty/freetype/src/psaux/t1cmap.h2
-rw-r--r--thirdparty/freetype/src/psaux/t1decode.c85
-rw-r--r--thirdparty/freetype/src/psaux/t1decode.h2
-rw-r--r--thirdparty/freetype/src/pshinter/module.mk2
-rw-r--r--thirdparty/freetype/src/pshinter/pshalgo.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshalgo.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshglob.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshglob.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshinter.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshmod.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshmod.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshnterr.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshrec.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshrec.h2
-rw-r--r--thirdparty/freetype/src/pshinter/rules.mk2
-rw-r--r--thirdparty/freetype/src/psnames/module.mk2
-rw-r--r--thirdparty/freetype/src/psnames/psmodule.c2
-rw-r--r--thirdparty/freetype/src/psnames/psmodule.h2
-rw-r--r--thirdparty/freetype/src/psnames/psnamerr.h2
-rw-r--r--thirdparty/freetype/src/psnames/psnames.c2
-rw-r--r--thirdparty/freetype/src/psnames/pstables.h2
-rw-r--r--thirdparty/freetype/src/psnames/rules.mk2
-rw-r--r--thirdparty/freetype/src/raster/ftmisc.h2
-rw-r--r--thirdparty/freetype/src/raster/ftraster.c2
-rw-r--r--thirdparty/freetype/src/raster/ftraster.h2
-rw-r--r--thirdparty/freetype/src/raster/ftrend1.c2
-rw-r--r--thirdparty/freetype/src/raster/ftrend1.h2
-rw-r--r--thirdparty/freetype/src/raster/module.mk2
-rw-r--r--thirdparty/freetype/src/raster/raster.c2
-rw-r--r--thirdparty/freetype/src/raster/rasterrs.h2
-rw-r--r--thirdparty/freetype/src/raster/rules.mk2
-rw-r--r--thirdparty/freetype/src/sfnt/module.mk2
-rw-r--r--thirdparty/freetype/src/sfnt/pngshim.c3
-rw-r--r--thirdparty/freetype/src/sfnt/pngshim.h2
-rw-r--r--thirdparty/freetype/src/sfnt/rules.mk30
-rw-r--r--thirdparty/freetype/src/sfnt/sfdriver.c2
-rw-r--r--thirdparty/freetype/src/sfnt/sfdriver.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sferrors.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sfnt.c4
-rw-r--r--thirdparty/freetype/src/sfnt/sfobjs.c38
-rw-r--r--thirdparty/freetype/src/sfnt/sfobjs.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sfwoff.c12
-rw-r--r--thirdparty/freetype/src/sfnt/sfwoff.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sfwoff2.c2328
-rw-r--r--thirdparty/freetype/src/sfnt/sfwoff2.h76
-rw-r--r--thirdparty/freetype/src/sfnt/ttbdf.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttbdf.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmap.c29
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmap.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmapc.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcolr.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcolr.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcpal.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcpal.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttkern.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttkern.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttload.c12
-rw-r--r--thirdparty/freetype/src/sfnt/ttload.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttmtx.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttmtx.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttpost.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttpost.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttsbit.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttsbit.h2
-rw-r--r--thirdparty/freetype/src/sfnt/woff2tags.c110
-rw-r--r--thirdparty/freetype/src/sfnt/woff2tags.h39
-rw-r--r--thirdparty/freetype/src/smooth/ftgrays.c2
-rw-r--r--thirdparty/freetype/src/smooth/ftgrays.h2
-rw-r--r--thirdparty/freetype/src/smooth/ftsmerrs.h2
-rw-r--r--thirdparty/freetype/src/smooth/ftsmooth.c9
-rw-r--r--thirdparty/freetype/src/smooth/ftsmooth.h2
-rw-r--r--thirdparty/freetype/src/smooth/module.mk2
-rw-r--r--thirdparty/freetype/src/smooth/rules.mk2
-rw-r--r--thirdparty/freetype/src/smooth/smooth.c2
-rw-r--r--thirdparty/freetype/src/truetype/module.mk2
-rw-r--r--thirdparty/freetype/src/truetype/rules.mk2
-rw-r--r--thirdparty/freetype/src/truetype/truetype.c2
-rw-r--r--thirdparty/freetype/src/truetype/ttdriver.c2
-rw-r--r--thirdparty/freetype/src/truetype/ttdriver.h2
-rw-r--r--thirdparty/freetype/src/truetype/tterrors.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttgload.c34
-rw-r--r--thirdparty/freetype/src/truetype/ttgload.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttgxvar.c133
-rw-r--r--thirdparty/freetype/src/truetype/ttgxvar.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttinterp.c33
-rw-r--r--thirdparty/freetype/src/truetype/ttinterp.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttobjs.c2
-rw-r--r--thirdparty/freetype/src/truetype/ttobjs.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttpload.c4
-rw-r--r--thirdparty/freetype/src/truetype/ttpload.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttsubpix.c2
-rw-r--r--thirdparty/freetype/src/truetype/ttsubpix.h2
-rw-r--r--thirdparty/freetype/src/type1/module.mk2
-rw-r--r--thirdparty/freetype/src/type1/rules.mk2
-rw-r--r--thirdparty/freetype/src/type1/t1afm.c2
-rw-r--r--thirdparty/freetype/src/type1/t1afm.h2
-rw-r--r--thirdparty/freetype/src/type1/t1driver.c2
-rw-r--r--thirdparty/freetype/src/type1/t1driver.h2
-rw-r--r--thirdparty/freetype/src/type1/t1errors.h2
-rw-r--r--thirdparty/freetype/src/type1/t1gload.c2
-rw-r--r--thirdparty/freetype/src/type1/t1gload.h2
-rw-r--r--thirdparty/freetype/src/type1/t1load.c44
-rw-r--r--thirdparty/freetype/src/type1/t1load.h2
-rw-r--r--thirdparty/freetype/src/type1/t1objs.c2
-rw-r--r--thirdparty/freetype/src/type1/t1objs.h2
-rw-r--r--thirdparty/freetype/src/type1/t1parse.c2
-rw-r--r--thirdparty/freetype/src/type1/t1parse.h2
-rw-r--r--thirdparty/freetype/src/type1/t1tokens.h2
-rw-r--r--thirdparty/freetype/src/type1/type1.c2
-rw-r--r--thirdparty/freetype/src/type42/module.mk2
-rw-r--r--thirdparty/freetype/src/type42/rules.mk2
-rw-r--r--thirdparty/freetype/src/type42/t42drivr.c2
-rw-r--r--thirdparty/freetype/src/type42/t42drivr.h2
-rw-r--r--thirdparty/freetype/src/type42/t42error.h2
-rw-r--r--thirdparty/freetype/src/type42/t42objs.c2
-rw-r--r--thirdparty/freetype/src/type42/t42objs.h2
-rw-r--r--thirdparty/freetype/src/type42/t42parse.c2
-rw-r--r--thirdparty/freetype/src/type42/t42parse.h2
-rw-r--r--thirdparty/freetype/src/type42/t42types.h2
-rw-r--r--thirdparty/freetype/src/type42/type42.c2
-rw-r--r--thirdparty/freetype/src/winfonts/fnterrs.h2
-rw-r--r--thirdparty/freetype/src/winfonts/module.mk2
-rw-r--r--thirdparty/freetype/src/winfonts/rules.mk2
-rw-r--r--thirdparty/freetype/src/winfonts/winfnt.c8
-rw-r--r--thirdparty/freetype/src/winfonts/winfnt.h2
-rw-r--r--thirdparty/glslang/LICENSE.txt108
-rw-r--r--thirdparty/glslang/OGLCompilersDLL/InitializeDll.cpp165
-rw-r--r--thirdparty/glslang/OGLCompilersDLL/InitializeDll.h49
-rw-r--r--thirdparty/glslang/SPIRV/GLSL.ext.AMD.h108
-rw-r--r--thirdparty/glslang/SPIRV/GLSL.ext.EXT.h39
-rw-r--r--thirdparty/glslang/SPIRV/GLSL.ext.KHR.h48
-rw-r--r--thirdparty/glslang/SPIRV/GLSL.ext.NV.h81
-rw-r--r--thirdparty/glslang/SPIRV/GLSL.std.450.h131
-rwxr-xr-xthirdparty/glslang/SPIRV/GlslangToSpv.cpp8361
-rwxr-xr-xthirdparty/glslang/SPIRV/GlslangToSpv.h61
-rw-r--r--thirdparty/glslang/SPIRV/InReadableOrder.cpp131
-rw-r--r--thirdparty/glslang/SPIRV/Logger.cpp72
-rw-r--r--thirdparty/glslang/SPIRV/Logger.h83
-rw-r--r--thirdparty/glslang/SPIRV/SPVRemapper.cpp1487
-rw-r--r--thirdparty/glslang/SPIRV/SPVRemapper.h304
-rw-r--r--thirdparty/glslang/SPIRV/SpvBuilder.cpp3094
-rw-r--r--thirdparty/glslang/SPIRV/SpvBuilder.h790
-rw-r--r--thirdparty/glslang/SPIRV/SpvPostProcess.cpp450
-rw-r--r--thirdparty/glslang/SPIRV/SpvTools.cpp216
-rw-r--r--thirdparty/glslang/SPIRV/SpvTools.h82
-rw-r--r--thirdparty/glslang/SPIRV/bitutils.h81
-rw-r--r--thirdparty/glslang/SPIRV/disassemble.cpp736
-rw-r--r--thirdparty/glslang/SPIRV/disassemble.h53
-rw-r--r--thirdparty/glslang/SPIRV/doc.cpp2764
-rw-r--r--thirdparty/glslang/SPIRV/doc.h258
-rw-r--r--thirdparty/glslang/SPIRV/hex_float.h1078
-rw-r--r--thirdparty/glslang/SPIRV/spirv.hpp1981
-rwxr-xr-xthirdparty/glslang/SPIRV/spvIR.h486
-rw-r--r--thirdparty/glslang/glslang/GenericCodeGen/CodeGen.cpp76
-rw-r--r--thirdparty/glslang/glslang/GenericCodeGen/Link.cpp91
-rw-r--r--thirdparty/glslang/glslang/Include/BaseTypes.h559
-rw-r--r--thirdparty/glslang/glslang/Include/Common.h294
-rw-r--r--thirdparty/glslang/glslang/Include/ConstantUnion.h974
-rw-r--r--thirdparty/glslang/glslang/Include/InfoSink.h144
-rw-r--r--thirdparty/glslang/glslang/Include/InitializeGlobals.h44
-rw-r--r--thirdparty/glslang/glslang/Include/PoolAlloc.h316
-rw-r--r--thirdparty/glslang/glslang/Include/ResourceLimits.h149
-rw-r--r--thirdparty/glslang/glslang/Include/ShHandle.h176
-rw-r--r--thirdparty/glslang/glslang/Include/Types.h2447
-rw-r--r--thirdparty/glslang/glslang/Include/arrays.h341
-rw-r--r--thirdparty/glslang/glslang/Include/intermediate.h1773
-rw-r--r--thirdparty/glslang/glslang/Include/revision.h3
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/Constant.cpp1419
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/InfoSink.cpp113
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp8875
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/Initialize.h112
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/IntermTraverse.cpp302
-rwxr-xr-xthirdparty/glslang/glslang/MachineIndependent/Intermediate.cpp3957
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/LiveTraverser.h138
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp638
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp8326
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/ParseHelper.h525
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp315
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/RemoveTree.cpp118
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/RemoveTree.h41
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/Scan.cpp1797
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/Scan.h276
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/ScanContext.h93
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp2110
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp444
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/SymbolTable.h885
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/Versions.cpp1173
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/Versions.h314
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/attribute.cpp346
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/attribute.h149
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/gl_types.h210
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/glslang.y3827
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp10439
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h512
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/intermOut.cpp1539
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/iomapper.cpp1249
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/iomapper.h299
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/limits.cpp200
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/linkValidate.cpp1723
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/localintermediate.h1001
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/parseConst.cpp204
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/parseVersions.h236
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/pch.cpp35
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/pch.h49
-rwxr-xr-xthirdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp1323
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp181
-rwxr-xr-xthirdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp119
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h702
-rwxr-xr-xthirdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp1245
-rwxr-xr-xthirdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp221
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h179
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp870
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/propagateNoContraction.h55
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/reflection.cpp1204
-rw-r--r--thirdparty/glslang/glslang/MachineIndependent/reflection.h223
-rw-r--r--thirdparty/glslang/glslang/OSDependent/Unix/ossource.cpp207
-rw-r--r--thirdparty/glslang/glslang/OSDependent/Web/glslang.after.js26
-rw-r--r--thirdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp269
-rw-r--r--thirdparty/glslang/glslang/OSDependent/Web/glslang.pre.js45
-rw-r--r--thirdparty/glslang/glslang/OSDependent/Windows/main.cpp74
-rw-r--r--thirdparty/glslang/glslang/OSDependent/Windows/ossource.cpp147
-rw-r--r--thirdparty/glslang/glslang/OSDependent/osinclude.h63
-rwxr-xr-xthirdparty/glslang/glslang/Public/ShaderLang.h903
-rw-r--r--thirdparty/glslang/patches/fix-mingw-snprintf.patch15
-rw-r--r--thirdparty/jpeg-compressor/jpgd.cpp6252
-rw-r--r--thirdparty/jpeg-compressor/jpgd.h634
-rw-r--r--thirdparty/jpeg-compressor/jpgd_idct.h462
-rw-r--r--thirdparty/libwebp/src/dec/frame_dec.c2
-rw-r--r--thirdparty/libwebp/src/dec/idec_dec.c11
-rw-r--r--thirdparty/libwebp/src/dec/vp8i_dec.h4
-rw-r--r--thirdparty/libwebp/src/dec/vp8l_dec.c10
-rw-r--r--thirdparty/libwebp/src/dec/vp8li_dec.h20
-rw-r--r--thirdparty/libwebp/src/demux/demux.c4
-rw-r--r--thirdparty/libwebp/src/dsp/dec_neon.c9
-rw-r--r--thirdparty/libwebp/src/dsp/dsp.h4
-rw-r--r--thirdparty/libwebp/src/dsp/lossless.c11
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_common.h2
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc_sse2.c3
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_sse2.c3
-rw-r--r--thirdparty/libwebp/src/dsp/upsampling_msa.c4
-rw-r--r--thirdparty/libwebp/src/dsp/upsampling_neon.c14
-rw-r--r--thirdparty/libwebp/src/enc/histogram_enc.c2
-rw-r--r--thirdparty/libwebp/src/enc/picture_csp_enc.c18
-rw-r--r--thirdparty/libwebp/src/enc/vp8i_enc.h6
-rw-r--r--thirdparty/libwebp/src/mux/muxi.h4
-rw-r--r--thirdparty/libwebp/src/mux/muxread.c2
-rw-r--r--thirdparty/libwebp/src/utils/color_cache_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/thread_utils.c2
-rw-r--r--thirdparty/libwebp/src/utils/utils.c9
-rw-r--r--thirdparty/libwebp/src/webp/decode.h5
-rw-r--r--thirdparty/libwebp/src/webp/encode.h9
-rw-r--r--thirdparty/libwebp/src/webp/mux.h12
-rw-r--r--thirdparty/libwebp/src/webp/mux_types.h10
-rw-r--r--thirdparty/libwebp/src/webp/types.h18
-rw-r--r--thirdparty/mbedtls/include/mbedtls/bignum.h20
-rw-r--r--thirdparty/mbedtls/include/mbedtls/check_config.h29
-rw-r--r--thirdparty/mbedtls/include/mbedtls/config.h14
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ctr_drbg.h218
-rw-r--r--thirdparty/mbedtls/include/mbedtls/hmac_drbg.h309
-rw-r--r--thirdparty/mbedtls/include/mbedtls/version.h8
-rw-r--r--thirdparty/mbedtls/library/aes.c24
-rw-r--r--thirdparty/mbedtls/library/bignum.c108
-rw-r--r--thirdparty/mbedtls/library/cipher.c14
-rw-r--r--thirdparty/mbedtls/library/ctr_drbg.c135
-rw-r--r--thirdparty/mbedtls/library/ecdsa.c5
-rw-r--r--thirdparty/mbedtls/library/ecp.c38
-rw-r--r--thirdparty/mbedtls/library/hmac_drbg.c25
-rw-r--r--thirdparty/mbedtls/library/pkparse.c120
-rw-r--r--thirdparty/mbedtls/library/rsa.c11
-rw-r--r--thirdparty/mbedtls/library/ssl_cli.c16
-rw-r--r--thirdparty/mbedtls/library/ssl_tls.c34
-rw-r--r--thirdparty/mbedtls/library/version_features.c3
-rw-r--r--thirdparty/mbedtls/library/x509.c2
-rw-r--r--thirdparty/mbedtls/library/x509write_csr.c4
-rw-r--r--thirdparty/miniupnpc/miniupnpc/minissdpc.c8
-rw-r--r--thirdparty/miniupnpc/miniupnpc/portlistingparse.c7
-rw-r--r--thirdparty/miniupnpc/miniupnpc/upnpc.c4
-rw-r--r--thirdparty/miniupnpc/windows_fix.diff16
-rw-r--r--thirdparty/misc/cubemap_coeffs.h28
-rw-r--r--thirdparty/misc/curl_hostcheck.c217
-rw-r--r--thirdparty/misc/curl_hostcheck.h39
-rw-r--r--thirdparty/misc/fastlz.c796
-rw-r--r--thirdparty/misc/fastlz.h60
-rw-r--r--thirdparty/misc/hq2x.cpp2636
-rw-r--r--thirdparty/misc/hq2x.h19
-rw-r--r--thirdparty/misc/ifaddrs-android.h19
-rw-r--r--thirdparty/misc/r128.c2
-rw-r--r--thirdparty/misc/r128.h2123
-rw-r--r--thirdparty/misc/stb_rect_pack.h628
-rw-r--r--thirdparty/misc/stb_vorbis.c219
-rw-r--r--thirdparty/oidn/0001-window.h-case-sensitive.patch13
-rw-r--r--thirdparty/oidn/LICENSE.txt202
-rw-r--r--thirdparty/oidn/common/barrier.h52
-rw-r--r--thirdparty/oidn/common/exception.h45
-rw-r--r--thirdparty/oidn/common/platform.cpp114
-rw-r--r--thirdparty/oidn/common/platform.h131
-rw-r--r--thirdparty/oidn/common/ref.h163
-rw-r--r--thirdparty/oidn/common/tensor.cpp83
-rw-r--r--thirdparty/oidn/common/tensor.h66
-rw-r--r--thirdparty/oidn/common/thread.cpp297
-rw-r--r--thirdparty/oidn/common/thread.h202
-rw-r--r--thirdparty/oidn/common/timer.h49
-rw-r--r--thirdparty/oidn/core/api.cpp408
-rw-r--r--thirdparty/oidn/core/autoencoder.cpp519
-rw-r--r--thirdparty/oidn/core/autoencoder.h116
-rw-r--r--thirdparty/oidn/core/buffer.h75
-rw-r--r--thirdparty/oidn/core/common.h133
-rw-r--r--thirdparty/oidn/core/device.cpp205
-rw-r--r--thirdparty/oidn/core/device.h78
-rw-r--r--thirdparty/oidn/core/filter.cpp27
-rw-r--r--thirdparty/oidn/core/filter.h52
-rw-r--r--thirdparty/oidn/core/image.h111
-rw-r--r--thirdparty/oidn/core/input_reorder.h232
-rw-r--r--thirdparty/oidn/core/math.h78
-rw-r--r--thirdparty/oidn/core/network.cpp434
-rw-r--r--thirdparty/oidn/core/network.h112
-rw-r--r--thirdparty/oidn/core/node.h142
-rw-r--r--thirdparty/oidn/core/output_reorder.h126
-rw-r--r--thirdparty/oidn/core/transfer_function.cpp95
-rw-r--r--thirdparty/oidn/core/transfer_function.h201
-rw-r--r--thirdparty/oidn/core/upsample.h92
-rw-r--r--thirdparty/oidn/core/weights_reorder.h99
-rw-r--r--thirdparty/oidn/include/OpenImageDenoise/oidn.h214
-rw-r--r--thirdparty/oidn/include/OpenImageDenoise/oidn.hpp468
-rw-r--r--thirdparty/oidn/include/OpenImageDenoise/version.h23
-rw-r--r--thirdparty/oidn/mkl-dnn/LICENSE214
-rw-r--r--thirdparty/oidn/mkl-dnn/include/mkldnn.h1771
-rw-r--r--thirdparty/oidn/mkl-dnn/include/mkldnn.hpp2615
-rw-r--r--thirdparty/oidn/mkl-dnn/include/mkldnn_debug.h98
-rw-r--r--thirdparty/oidn/mkl-dnn/include/mkldnn_types.h1415
-rw-r--r--thirdparty/oidn/mkl-dnn/include/mkldnn_version.h32
-rw-r--r--thirdparty/oidn/mkl-dnn/include/mkldnn_version.h.in32
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/batch_normalization.cpp104
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/batch_normalization_pd.hpp240
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/c_types_map.hpp550
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/concat.cpp86
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/concat_pd.hpp211
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/convolution.cpp200
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/convolution_pd.cpp56
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/convolution_pd.hpp348
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/deconvolution.cpp188
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/deconvolution_pd.hpp293
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/eltwise.cpp84
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/eltwise_pd.hpp161
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/engine.cpp75
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/engine.hpp119
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/inner_product.cpp106
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.cpp56
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.hpp321
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/lrn.cpp91
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/lrn_pd.hpp170
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/math_utils.hpp280
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/memory.cpp238
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/memory.hpp63
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.cpp212
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.hpp400
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/memory_tracking.hpp295
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug.cpp131
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug_autogenerated.cpp365
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread.hpp115
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread_parallel_nd.hpp277
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/mkldnn_traits.hpp77
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/nstl.hpp193
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/pooling.cpp114
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/pooling_pd.hpp238
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/primitive.cpp103
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/primitive.hpp76
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/primitive_attr.cpp290
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/primitive_attr.hpp183
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/primitive_desc.cpp78
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/primitive_desc.hpp174
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.cpp90
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.hpp68
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.cpp89
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.hpp79
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/query.cpp59
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/reorder.cpp68
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/reorder_pd.hpp85
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/rnn.cpp400
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/rnn_pd.hpp280
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/scratchpad.cpp112
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/scratchpad.hpp36
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/shuffle.cpp72
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/shuffle_pd.hpp121
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/softmax.cpp68
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/softmax_pd.hpp161
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/stream.cpp46
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/stream.hpp44
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/sum.cpp79
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/sum_pd.hpp143
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/tag_traits.hpp200
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/type_helpers.hpp348
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/utils.cpp135
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/utils.hpp370
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/verbose.cpp665
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/verbose.hpp62
-rw-r--r--thirdparty/oidn/mkl-dnn/src/common/z_magic.hpp46
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.cpp112
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.hpp60
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_pd.hpp40
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.cpp140
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.hpp43
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat.cpp51
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat_pd.hpp41
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_convolution_pd.hpp74
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_deconvolution_pd.hpp46
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_eltwise_pd.hpp45
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.cpp324
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.hpp70
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_inner_product_pd.hpp84
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_isa_traits.hpp151
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_lrn_pd.hpp42
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.cpp277
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.hpp89
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_pooling_pd.hpp40
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_primitive.hpp83
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.cpp544
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.hpp334
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder.cpp262
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder_pd.hpp48
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_shuffle_pd.hpp41
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_softmax_pd.hpp45
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum.cpp48
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum_pd.hpp39
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.cpp372
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.hpp72
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.cpp2131
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.hpp36
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.cpp2705
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.hpp37
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.cpp346
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.hpp36
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.cpp280
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.hpp58
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/os_blas.hpp86
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/common.hpp206
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/gemv.hpp28
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.cpp1409
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp38
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.cpp539
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.hpp101
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemv_s8u8s32.cpp290
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.cpp411
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp64
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_an_kern.cpp819
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_at_kern.cpp2209
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bn_kern.cpp564
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bt_kern.cpp501
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_an_kern.cpp1283
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_at_kern.cpp3163
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bn_kern.cpp821
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bt_kern.cpp647
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.cpp116
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.hpp38
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.cpp180
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.hpp37
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.cpp307
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.hpp250
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.cpp771
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.hpp66
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.cpp156
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.hpp157
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.cpp740
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.hpp266
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.cpp453
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.hpp166
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.cpp674
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.hpp110
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.cpp545
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.hpp344
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.cpp1501
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.hpp225
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.cpp410
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.hpp302
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.cpp1255
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.hpp108
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.cpp816
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.hpp344
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.cpp4539
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.hpp423
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.cpp1163
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.hpp179
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.cpp1526
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.hpp302
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.cpp1215
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.hpp318
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.cpp853
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.hpp96
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.cpp1103
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.hpp144
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.cpp1020
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.hpp386
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.cpp2596
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp291
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.cpp1284
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.hpp128
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.cpp820
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp131
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.cpp292
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.hpp159
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_deconvolution.hpp140
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.cpp1182
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.hpp239
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.cpp423
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.hpp115
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.cpp1034
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.hpp237
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_generator.hpp773
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_primitive_conf.hpp481
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.cpp677
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.hpp104
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.cpp134
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.hpp96
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.cpp497
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.hpp93
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.cpp136
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.hpp103
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.cpp1192
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.hpp145
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_1x1_conv_utils.hpp327
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.cpp1407
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.hpp100
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.cpp1302
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.hpp253
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.cpp427
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.hpp266
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.cpp1142
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.hpp193
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.cpp949
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.hpp89
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.cpp305
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.hpp103
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.cpp1487
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.hpp183
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.cpp699
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.hpp192
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.cpp264
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.hpp182
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.cpp1006
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.hpp127
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp313
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.cpp115
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.hpp32
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/LICENSE.BSD27
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/README.md1
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_config.h595
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_types.h94
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.c293
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.h673
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.cpp317
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.hpp147
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.cpp382
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.hpp160
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.cpp392
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.hpp210
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.cpp288
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.hpp169
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.cpp265
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.hpp127
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_concat.hpp97
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.cpp395
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.hpp194
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.cpp199
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.hpp502
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.cpp297
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.hpp168
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.cpp285
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.hpp159
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.cpp252
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.hpp136
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.cpp381
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.hpp119
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.cpp153
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.hpp111
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.cpp264
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.hpp186
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/ref_sum.hpp101
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_common.cpp90
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru.cpp180
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru_lbr.cpp170
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_lstm.cpp143
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_rnn.cpp113
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/cpu_rnn_pd.hpp191
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/jit_uni_rnn_postgemm.hpp401
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.cpp788
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.hpp328
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp380
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.cpp426
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.hpp225
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.cpp126
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp155
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/simple_q10n.hpp98
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/simple_reorder.hpp1022
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.cpp91
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.hpp74
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/wino_reorder.hpp376
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/xbyak/COPYRIGHT47
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak.h2658
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_bin2hex.h303
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_mnemonic.h2017
-rw-r--r--thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_util.h772
-rw-r--r--thirdparty/oidn/weights/rtlightmap_hdr.tzabin0 -> 5660131 bytes
-rw-r--r--thirdparty/opus/analysis.c777
-rw-r--r--thirdparty/opus/analysis.h38
-rw-r--r--thirdparty/opus/celt/_kiss_fft_guts.h16
-rw-r--r--thirdparty/opus/celt/arch.h52
-rwxr-xr-xthirdparty/opus/celt/arm/arm2gnu.pl4
-rw-r--r--thirdparty/opus/celt/arm/arm_celt_map.c21
-rw-r--r--thirdparty/opus/celt/arm/celt_ne10_fft.c (renamed from thirdparty/opus/celt/arm/celt_fft_ne10.c)3
-rw-r--r--thirdparty/opus/celt/arm/celt_ne10_mdct.c (renamed from thirdparty/opus/celt/arm/celt_mdct_ne10.c)2
-rw-r--r--thirdparty/opus/celt/arm/celt_neon_intr.c110
-rw-r--r--thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S14
-rw-r--r--thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s6
-rw-r--r--thirdparty/opus/celt/arm/fft_arm.h1
-rw-r--r--thirdparty/opus/celt/arm/fixed_armv4.h6
-rw-r--r--thirdparty/opus/celt/arm/fixed_armv5e.h4
-rw-r--r--thirdparty/opus/celt/arm/mdct_arm.h1
-rw-r--r--thirdparty/opus/celt/arm/pitch_arm.h56
-rw-r--r--thirdparty/opus/celt/arm/pitch_neon_intr.c290
-rw-r--r--thirdparty/opus/celt/bands.c323
-rw-r--r--thirdparty/opus/celt/bands.h9
-rw-r--r--thirdparty/opus/celt/celt.c25
-rw-r--r--thirdparty/opus/celt/celt.h32
-rw-r--r--thirdparty/opus/celt/celt_decoder.c190
-rw-r--r--thirdparty/opus/celt/celt_encoder.c399
-rw-r--r--thirdparty/opus/celt/celt_lpc.c62
-rw-r--r--thirdparty/opus/celt/celt_lpc.h5
-rw-r--r--thirdparty/opus/celt/cwrs.c2
-rw-r--r--thirdparty/opus/celt/entcode.h4
-rw-r--r--thirdparty/opus/celt/entdec.h2
-rw-r--r--thirdparty/opus/celt/entenc.h2
-rw-r--r--thirdparty/opus/celt/fixed_debug.h13
-rw-r--r--thirdparty/opus/celt/fixed_generic.h11
-rw-r--r--thirdparty/opus/celt/float_cast.h14
-rw-r--r--thirdparty/opus/celt/kiss_fft.c56
-rw-r--r--thirdparty/opus/celt/mathops.c5
-rw-r--r--thirdparty/opus/celt/mathops.h36
-rw-r--r--thirdparty/opus/celt/mdct.c16
-rw-r--r--thirdparty/opus/celt/mips/celt_mipsr1.h1
-rw-r--r--thirdparty/opus/celt/mips/vq_mipsr1.h11
-rw-r--r--thirdparty/opus/celt/modes.c2
-rw-r--r--thirdparty/opus/celt/pitch.c46
-rw-r--r--thirdparty/opus/celt/pitch.h14
-rw-r--r--thirdparty/opus/celt/quant_bands.c11
-rw-r--r--thirdparty/opus/celt/rate.c13
-rw-r--r--thirdparty/opus/celt/rate.h2
-rw-r--r--thirdparty/opus/celt/static_modes_fixed_arm_ne10.h2
-rw-r--r--thirdparty/opus/celt/static_modes_float_arm_ne10.h2
-rw-r--r--thirdparty/opus/celt/tests/test_unit_cwrs32.c161
-rw-r--r--thirdparty/opus/celt/tests/test_unit_dft.c189
-rw-r--r--thirdparty/opus/celt/tests/test_unit_entropy.c382
-rw-r--r--thirdparty/opus/celt/tests/test_unit_laplace.c93
-rw-r--r--thirdparty/opus/celt/tests/test_unit_mathops.c304
-rw-r--r--thirdparty/opus/celt/tests/test_unit_mdct.c230
-rw-r--r--thirdparty/opus/celt/tests/test_unit_rotation.c120
-rw-r--r--thirdparty/opus/celt/tests/test_unit_types.c (renamed from thirdparty/opus/celt/arm/armopts.s)33
-rw-r--r--thirdparty/opus/celt/vq.c118
-rw-r--r--thirdparty/opus/celt/vq.h20
-rw-r--r--thirdparty/opus/celt/x86/celt_lpc_sse.c (renamed from thirdparty/opus/celt/x86/celt_lpc_sse4_1.c)57
-rw-r--r--thirdparty/opus/celt/x86/celt_lpc_sse.h10
-rw-r--r--thirdparty/opus/celt/x86/vq_sse.h50
-rw-r--r--thirdparty/opus/celt/x86/vq_sse2.c217
-rw-r--r--thirdparty/opus/celt/x86/x86_celt_map.c14
-rw-r--r--thirdparty/opus/celt/x86/x86cpu.h4
-rw-r--r--thirdparty/opus/config.h132
-rw-r--r--thirdparty/opus/info.c75
-rw-r--r--thirdparty/opus/internal.h23
-rw-r--r--thirdparty/opus/mapping_matrix.c378
-rw-r--r--thirdparty/opus/mapping_matrix.h133
-rw-r--r--thirdparty/opus/mlp.c155
-rw-r--r--thirdparty/opus/mlp.h35
-rw-r--r--thirdparty/opus/mlp_data.c755
-rw-r--r--thirdparty/opus/opus.c4
-rw-r--r--thirdparty/opus/opus/opus.h2
-rw-r--r--thirdparty/opus/opus/opus_defines.h52
-rw-r--r--thirdparty/opus/opus/opus_multistream.h4
-rw-r--r--thirdparty/opus/opus/opus_projection.h568
-rw-r--r--thirdparty/opus/opus/opus_types.h27
-rw-r--r--thirdparty/opus/opus/opusfile.h59
-rw-r--r--thirdparty/opus/opus_compare.c3
-rw-r--r--thirdparty/opus/opus_decoder.c117
-rw-r--r--thirdparty/opus/opus_encoder.c1409
-rw-r--r--thirdparty/opus/opus_multistream_decoder.c90
-rw-r--r--thirdparty/opus/opus_multistream_encoder.c351
-rw-r--r--thirdparty/opus/opus_private.h85
-rw-r--r--thirdparty/opus/opus_projection_decoder.c258
-rw-r--r--thirdparty/opus/opus_projection_encoder.c468
-rw-r--r--thirdparty/opus/opusfile.c264
-rw-r--r--thirdparty/opus/repacketizer.c3
-rw-r--r--thirdparty/opus/silk/A2NLSF.c8
-rw-r--r--thirdparty/opus/silk/API.h3
-rw-r--r--thirdparty/opus/silk/CNG.c12
-rw-r--r--thirdparty/opus/silk/LPC_analysis_filter.c25
-rw-r--r--thirdparty/opus/silk/LPC_fit.c81
-rw-r--r--thirdparty/opus/silk/LPC_inv_pred_gain.c97
-rw-r--r--thirdparty/opus/silk/LP_variable_cutoff.c2
-rw-r--r--thirdparty/opus/silk/MacroCount.h10
-rw-r--r--thirdparty/opus/silk/MacroDebug.h3
-rw-r--r--thirdparty/opus/silk/NLSF2A.c59
-rw-r--r--thirdparty/opus/silk/NLSF_VQ.c44
-rw-r--r--thirdparty/opus/silk/NLSF_VQ_weights_laroia.c4
-rw-r--r--thirdparty/opus/silk/NLSF_decode.c22
-rw-r--r--thirdparty/opus/silk/NLSF_del_dec_quant.c8
-rw-r--r--thirdparty/opus/silk/NLSF_encode.c37
-rw-r--r--thirdparty/opus/silk/NSQ.c72
-rw-r--r--thirdparty/opus/silk/NSQ_del_dec.c93
-rw-r--r--thirdparty/opus/silk/PLC.c12
-rw-r--r--thirdparty/opus/silk/SigProc_FIX.h56
-rw-r--r--thirdparty/opus/silk/VAD.c22
-rw-r--r--thirdparty/opus/silk/VQ_WMat_EC.c129
-rw-r--r--thirdparty/opus/silk/arm/LPC_inv_pred_gain_arm.h57
-rw-r--r--thirdparty/opus/silk/arm/LPC_inv_pred_gain_neon_intr.c280
-rw-r--r--thirdparty/opus/silk/arm/NSQ_del_dec_arm.h100
-rw-r--r--thirdparty/opus/silk/arm/NSQ_del_dec_neon_intr.c1124
-rw-r--r--thirdparty/opus/silk/arm/NSQ_neon.h33
-rw-r--r--thirdparty/opus/silk/arm/arm_silk_map.c68
-rw-r--r--thirdparty/opus/silk/arm/biquad_alt_arm.h68
-rw-r--r--thirdparty/opus/silk/arm/biquad_alt_neon_intr.c156
-rw-r--r--thirdparty/opus/silk/arm/macros_armv4.h13
-rw-r--r--thirdparty/opus/silk/arm/macros_armv5e.h9
-rw-r--r--thirdparty/opus/silk/biquad_alt.c53
-rw-r--r--thirdparty/opus/silk/bwexpander.c2
-rw-r--r--thirdparty/opus/silk/check_control_input.c22
-rw-r--r--thirdparty/opus/silk/control.h8
-rw-r--r--thirdparty/opus/silk/control_SNR.c103
-rw-r--r--thirdparty/opus/silk/control_audio_bandwidth.c16
-rw-r--r--thirdparty/opus/silk/control_codec.c105
-rw-r--r--thirdparty/opus/silk/debug.h21
-rw-r--r--thirdparty/opus/silk/dec_API.c6
-rw-r--r--thirdparty/opus/silk/decode_core.c6
-rw-r--r--thirdparty/opus/silk/decode_frame.c7
-rw-r--r--thirdparty/opus/silk/decode_indices.c2
-rw-r--r--thirdparty/opus/silk/decode_parameters.c4
-rw-r--r--thirdparty/opus/silk/decode_pitch.c4
-rw-r--r--thirdparty/opus/silk/decode_pulses.c2
-rw-r--r--thirdparty/opus/silk/decoder_set_fs.c8
-rw-r--r--thirdparty/opus/silk/define.h17
-rw-r--r--thirdparty/opus/silk/enc_API.c47
-rw-r--r--thirdparty/opus/silk/encode_indices.c6
-rw-r--r--thirdparty/opus/silk/encode_pulses.c2
-rw-r--r--thirdparty/opus/silk/fixed/apply_sine_window_FIX.c8
-rw-r--r--thirdparty/opus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h68
-rw-r--r--thirdparty/opus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c260
-rw-r--r--thirdparty/opus/silk/fixed/burg_modified_FIX.c4
-rw-r--r--thirdparty/opus/silk/fixed/corrMatrix_FIX.c38
-rw-r--r--thirdparty/opus/silk/fixed/encode_frame_FIX.c123
-rw-r--r--thirdparty/opus/silk/fixed/find_LPC_FIX.c4
-rw-r--r--thirdparty/opus/silk/fixed/find_LTP_FIX.c238
-rw-r--r--thirdparty/opus/silk/fixed/find_pitch_lags_FIX.c20
-rw-r--r--thirdparty/opus/silk/fixed/find_pred_coefs_FIX.c27
-rw-r--r--thirdparty/opus/silk/fixed/k2a_FIX.c13
-rw-r--r--thirdparty/opus/silk/fixed/k2a_Q16_FIX.c15
-rw-r--r--thirdparty/opus/silk/fixed/main_FIX.h74
-rw-r--r--thirdparty/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h6
-rw-r--r--thirdparty/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h184
-rw-r--r--thirdparty/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h4
-rw-r--r--thirdparty/opus/silk/fixed/noise_shape_analysis_FIX.c160
-rw-r--r--thirdparty/opus/silk/fixed/pitch_analysis_core_FIX.c125
-rw-r--r--thirdparty/opus/silk/fixed/prefilter_FIX.c221
-rw-r--r--thirdparty/opus/silk/fixed/residual_energy16_FIX.c8
-rw-r--r--thirdparty/opus/silk/fixed/residual_energy_FIX.c2
-rw-r--r--thirdparty/opus/silk/fixed/schur64_FIX.c7
-rw-r--r--thirdparty/opus/silk/fixed/schur_FIX.c15
-rw-r--r--thirdparty/opus/silk/fixed/solve_LS_FIX.c249
-rw-r--r--thirdparty/opus/silk/fixed/structs_FIX.h22
-rw-r--r--thirdparty/opus/silk/fixed/warped_autocorrelation_FIX.c11
-rw-r--r--thirdparty/opus/silk/fixed/x86/burg_modified_FIX_sse.c (renamed from thirdparty/opus/silk/fixed/x86/burg_modified_FIX_sse4_1.c)2
-rw-r--r--thirdparty/opus/silk/fixed/x86/prefilter_FIX_sse.c160
-rw-r--r--thirdparty/opus/silk/fixed/x86/vector_ops_FIX_sse.c (renamed from thirdparty/opus/silk/fixed/x86/vector_ops_FIX_sse4_1.c)0
-rw-r--r--thirdparty/opus/silk/float/LPC_analysis_filter_FLP.c4
-rw-r--r--thirdparty/opus/silk/float/LPC_inv_pred_gain_FLP.c37
-rw-r--r--thirdparty/opus/silk/float/SigProc_FLP.h7
-rw-r--r--thirdparty/opus/silk/float/apply_sine_window_FLP.c4
-rw-r--r--thirdparty/opus/silk/float/burg_modified_FLP.c2
-rw-r--r--thirdparty/opus/silk/float/encode_frame_FLP.c105
-rw-r--r--thirdparty/opus/silk/float/energy_FLP.c5
-rw-r--r--thirdparty/opus/silk/float/find_LPC_FLP.c4
-rw-r--r--thirdparty/opus/silk/float/find_LTP_FLP.c108
-rw-r--r--thirdparty/opus/silk/float/find_pitch_lags_FLP.c2
-rw-r--r--thirdparty/opus/silk/float/find_pred_coefs_FLP.c14
-rw-r--r--thirdparty/opus/silk/float/inner_product_FLP.c5
-rw-r--r--thirdparty/opus/silk/float/k2a_FLP.c15
-rw-r--r--thirdparty/opus/silk/float/levinsondurbin_FLP.c81
-rw-r--r--thirdparty/opus/silk/float/main_FLP.h55
-rw-r--r--thirdparty/opus/silk/float/noise_shape_analysis_FLP.c149
-rw-r--r--thirdparty/opus/silk/float/pitch_analysis_core_FLP.c36
-rw-r--r--thirdparty/opus/silk/float/prefilter_FLP.c206
-rw-r--r--thirdparty/opus/silk/float/residual_energy_FLP.c2
-rw-r--r--thirdparty/opus/silk/float/schur_FLP.c16
-rw-r--r--thirdparty/opus/silk/float/solve_LS_FLP.c207
-rw-r--r--thirdparty/opus/silk/float/sort_FLP.c6
-rw-r--r--thirdparty/opus/silk/float/structs_FLP.h22
-rw-r--r--thirdparty/opus/silk/float/warped_autocorrelation_FLP.c6
-rw-r--r--thirdparty/opus/silk/float/wrappers_FLP.c49
-rw-r--r--thirdparty/opus/silk/gain_quant.c1
-rw-r--r--thirdparty/opus/silk/init_decoder.c1
-rw-r--r--thirdparty/opus/silk/interpolate.c4
-rw-r--r--thirdparty/opus/silk/lin2log.c2
-rw-r--r--thirdparty/opus/silk/macros.h8
-rw-r--r--thirdparty/opus/silk/main.h77
-rw-r--r--thirdparty/opus/silk/mips/NSQ_del_dec_mipsr1.h7
-rw-r--r--thirdparty/opus/silk/mips/sigproc_fix_mipsr1.h5
-rw-r--r--thirdparty/opus/silk/process_NLSFs.c10
-rw-r--r--thirdparty/opus/silk/quant_LTP_gains.c67
-rw-r--r--thirdparty/opus/silk/resampler.c10
-rw-r--r--thirdparty/opus/silk/resampler_down2.c4
-rw-r--r--thirdparty/opus/silk/resampler_private_down_FIR.c2
-rw-r--r--thirdparty/opus/silk/sort.c14
-rw-r--r--thirdparty/opus/silk/stereo_LR_to_MS.c2
-rw-r--r--thirdparty/opus/silk/stereo_encode_pred.c6
-rw-r--r--thirdparty/opus/silk/structs.h6
-rw-r--r--thirdparty/opus/silk/sum_sqr_shift.c51
-rw-r--r--thirdparty/opus/silk/tables.h8
-rw-r--r--thirdparty/opus/silk/tables_LTP.c2
-rw-r--r--thirdparty/opus/silk/tables_NLSF_CB_NB_MB.c36
-rw-r--r--thirdparty/opus/silk/tables_NLSF_CB_WB.c36
-rw-r--r--thirdparty/opus/silk/tables_other.c14
-rw-r--r--thirdparty/opus/silk/tuning_parameters.h28
-rw-r--r--thirdparty/opus/silk/x86/NSQ_del_dec_sse.c (renamed from thirdparty/opus/silk/x86/NSQ_del_dec_sse4_1.c)22
-rw-r--r--thirdparty/opus/silk/x86/NSQ_sse.c (renamed from thirdparty/opus/silk/x86/NSQ_sse4_1.c)5
-rw-r--r--thirdparty/opus/silk/x86/VAD_sse.c (renamed from thirdparty/opus/silk/x86/VAD_sse4_1.c)6
-rw-r--r--thirdparty/opus/silk/x86/VQ_WMat_EC_sse.c (renamed from thirdparty/opus/silk/x86/VQ_WMat_EC_sse4_1.c)0
-rw-r--r--thirdparty/opus/silk/x86/main_sse.h45
-rw-r--r--thirdparty/opus/silk/x86/x86_silk_map.c26
-rw-r--r--thirdparty/opus/stream.c6
-rw-r--r--thirdparty/pcre2/src/config.h6
-rw-r--r--thirdparty/pcre2/src/pcre2.h19
-rw-r--r--thirdparty/pcre2/src/pcre2_auto_possess.c7
-rw-r--r--thirdparty/pcre2/src/pcre2_compile.c535
-rw-r--r--thirdparty/pcre2/src/pcre2_context.c2
-rw-r--r--thirdparty/pcre2/src/pcre2_dfa_match.c129
-rw-r--r--thirdparty/pcre2/src/pcre2_error.c3
-rw-r--r--thirdparty/pcre2/src/pcre2_internal.h105
-rw-r--r--thirdparty/pcre2/src/pcre2_intmodedep.h10
-rw-r--r--thirdparty/pcre2/src/pcre2_jit_compile.c1857
-rw-r--r--thirdparty/pcre2/src/pcre2_jit_match.c1
-rw-r--r--thirdparty/pcre2/src/pcre2_jit_neon_inc.h321
-rw-r--r--thirdparty/pcre2/src/pcre2_jit_simd_inc.h993
-rw-r--r--thirdparty/pcre2/src/pcre2_maketables.c11
-rw-r--r--thirdparty/pcre2/src/pcre2_match.c603
-rw-r--r--thirdparty/pcre2/src/pcre2_match_data.c15
-rw-r--r--thirdparty/pcre2/src/pcre2_study.c306
-rw-r--r--thirdparty/pcre2/src/pcre2_tables.c316
-rw-r--r--thirdparty/pcre2/src/pcre2_ucd.c5623
-rw-r--r--thirdparty/pcre2/src/pcre2_ucp.h7
-rw-r--r--thirdparty/pcre2/src/sljit/sljitConfigInternal.h4
-rw-r--r--thirdparty/pcre2/src/sljit/sljitExecAllocator.c28
-rw-r--r--thirdparty/pcre2/src/sljit/sljitLir.c69
-rw-r--r--thirdparty/pcre2/src/sljit/sljitLir.h22
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeARM_32.c126
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeARM_64.c111
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c76
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c2
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c155
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativePPC_32.c2
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativePPC_64.c3
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativePPC_common.c214
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c2
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c102
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeX86_32.c4
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeX86_64.c54
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeX86_common.c125
-rw-r--r--thirdparty/pcre2/src/sljit/sljitUtils.c6
-rw-r--r--thirdparty/recastnavigation/Recast/Include/Recast.h8
-rw-r--r--thirdparty/recastnavigation/Recast/Include/RecastAlloc.h288
-rw-r--r--thirdparty/recastnavigation/Recast/Source/Recast.cpp165
-rw-r--r--thirdparty/recastnavigation/Recast/Source/RecastAlloc.cpp26
-rw-r--r--thirdparty/recastnavigation/Recast/Source/RecastContour.cpp2
-rw-r--r--thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp12
-rw-r--r--thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp198
-rw-r--r--thirdparty/rvo2/LICENSE202
-rw-r--r--thirdparty/rvo2/README.md32
-rw-r--r--thirdparty/rvo2/src/API.h45
-rw-r--r--thirdparty/rvo2/src/Agent.cpp425
-rw-r--r--thirdparty/rvo2/src/Agent.h121
-rw-r--r--thirdparty/rvo2/src/Definitions.h55
-rw-r--r--thirdparty/rvo2/src/KdTree.cpp152
-rw-r--r--thirdparty/rvo2/src/KdTree.h124
-rw-r--r--thirdparty/rvo2/src/Vector3.h335
-rw-r--r--thirdparty/spirv-reflect/include/spirv/unified1/spirv.h1077
-rw-r--r--thirdparty/spirv-reflect/spirv_reflect.c4442
-rw-r--r--thirdparty/spirv-reflect/spirv_reflect.h2045
-rw-r--r--thirdparty/tinyexr/tinyexr.h588
-rw-r--r--thirdparty/vhacd/0003-fix-musl-build.patch15
-rw-r--r--thirdparty/vhacd/0004-fix-uwp-arm-build.patch16
-rw-r--r--thirdparty/vhacd/0005-fix-scale-calculation.patch20
-rw-r--r--thirdparty/vhacd/inc/btScalar.h5
-rw-r--r--thirdparty/vhacd/inc/vhacdMutex.h4
-rw-r--r--thirdparty/vhacd/inc/vhacdVolume.h4
-rw-r--r--thirdparty/vulkan/LICENSE.txt207
-rw-r--r--thirdparty/vulkan/android/vk_mem_alloc.cpp8
-rw-r--r--thirdparty/vulkan/include/vulkan/vk_icd.h183
-rw-r--r--thirdparty/vulkan/include/vulkan/vk_layer.h202
-rw-r--r--thirdparty/vulkan/include/vulkan/vk_platform.h92
-rw-r--r--thirdparty/vulkan/include/vulkan/vk_sdk_platform.h69
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan.h86
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan.hpp71380
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_android.h122
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_core.h10722
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_fuchsia.h57
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_ggp.h68
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_ios.h57
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_macos.h57
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_metal.h64
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_vi.h57
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_wayland.h64
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_win32.h328
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_xcb.h65
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_xlib.h65
-rw-r--r--thirdparty/vulkan/include/vulkan/vulkan_xlib_xrandr.h55
-rw-r--r--thirdparty/vulkan/loader/adapters.h80
-rw-r--r--thirdparty/vulkan/loader/asm_offset.c94
-rw-r--r--thirdparty/vulkan/loader/cJSON.c1215
-rw-r--r--thirdparty/vulkan/loader/cJSON.h174
-rw-r--r--thirdparty/vulkan/loader/debug_utils.c996
-rw-r--r--thirdparty/vulkan/loader/debug_utils.h101
-rw-r--r--thirdparty/vulkan/loader/dev_ext_trampoline.c538
-rw-r--r--thirdparty/vulkan/loader/dirent_on_windows.c128
-rw-r--r--thirdparty/vulkan/loader/dirent_on_windows.h51
-rw-r--r--thirdparty/vulkan/loader/dxgi_loader.c23
-rw-r--r--thirdparty/vulkan/loader/dxgi_loader.h8
-rw-r--r--thirdparty/vulkan/loader/extension_manual.c462
-rw-r--r--thirdparty/vulkan/loader/extension_manual.h118
-rw-r--r--thirdparty/vulkan/loader/gpa_helper.h248
-rw-r--r--thirdparty/vulkan/loader/loader.c8100
-rw-r--r--thirdparty/vulkan/loader/loader.h533
-rw-r--r--thirdparty/vulkan/loader/murmurhash.c98
-rw-r--r--thirdparty/vulkan/loader/murmurhash.h52
-rw-r--r--thirdparty/vulkan/loader/phys_dev_ext.c1056
-rw-r--r--thirdparty/vulkan/loader/trampoline.c2593
-rw-r--r--thirdparty/vulkan/loader/unknown_ext_chain.c819
-rw-r--r--thirdparty/vulkan/loader/vk_dispatch_table_helper.h792
-rw-r--r--thirdparty/vulkan/loader/vk_layer_dispatch_table.h682
-rw-r--r--thirdparty/vulkan/loader/vk_loader_extensions.c4734
-rw-r--r--thirdparty/vulkan/loader/vk_loader_extensions.h457
-rw-r--r--thirdparty/vulkan/loader/vk_loader_layer.h46
-rw-r--r--thirdparty/vulkan/loader/vk_loader_platform.h386
-rw-r--r--thirdparty/vulkan/loader/vk_object_types.h383
-rw-r--r--thirdparty/vulkan/loader/wsi.c2023
-rw-r--r--thirdparty/vulkan/loader/wsi.h184
-rw-r--r--thirdparty/vulkan/patches/Vulkan-Loader-revert-pr260.patch57
-rw-r--r--thirdparty/vulkan/vk_enum_string_helper.h6414
-rw-r--r--thirdparty/vulkan/vk_mem_alloc.cpp7
-rw-r--r--thirdparty/vulkan/vk_mem_alloc.h17764
-rw-r--r--thirdparty/xatlas/LICENSE27
-rw-r--r--thirdparty/xatlas/xatlas.cpp5240
-rw-r--r--thirdparty/xatlas/xatlas.h11
1432 files changed, 445243 insertions, 33081 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 27cfe41238..5b24d2b96d 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -1,34 +1,50 @@
# Third party libraries
+Please keep categories (`##` level) listed alphabetically and matching their
+respective folder names. Use two empty lines to separate categories for
+readability.
+Subcategories (`###` level) where needed are separated by a single empty line.
+
## assimp
- Upstream: http://github.com/assimp/assimp
-- Version: git (308db73d0b3c2d1870cd3e465eaa283692a4cf23)
+- Version: git (308db73d0b3c2d1870cd3e465eaa283692a4cf23, 2019)
- License: BSD-3-Clause
+Files extracted from upstream source:
-## b2d_convexdecomp
+- Run `cmake .` in root folder to generate files
+- `code/{CApi,Common,FBX,Material,PostProcessing}/`
+- `contrib/utf8cpp/source/`
+- `include/`
+- `revision.h`
+- `CREDITS` and `LICENSE` files
+- `rm -f code/Common/ZipArchiveIOSystem.cpp include/assimp/ZipArchiveIOSystem.h
+ include/assimp/irrXMLWrapper.h`
-- Upstream: https://github.com/erincatto/Box2D/tree/master/Contributions/Utilities/ConvexDecomposition
-- Version: git (25615e0, 2015) with modifications
-- License: zlib
-The files were adapted to Godot by removing the dependency on b2Math (replacing
-it by b2Glue.h) and commenting out some verbose printf calls.
-Upstream code has not changed in 10 years, no need to keep track of changes.
+## basis_universal
-Important: Some files have Godot-made changes.
-They are marked with `// -- GODOT start --` and `// -- GODOT end --`
-comments.
+- Upstream: https://github.com/BinomialLLC/basis_universal
+- Version: git (895ee8ee7e04f22267f8d16d46de04d5a01d63ac, 2020)
+- License: Apache 2.0
+
+Files extracted from upstream source:
+
+- `.cpp` and `.h` files in root folder except for `basisu_tool.cpp` (contains `main` and can cause link error)
+- `.cpp`, `.h` and `.inc` files in `transcoder/`, keeping folder structure
+- `LICENSE`
## bullet
- Upstream: https://github.com/bulletphysics/bullet3
-- Version: git (5ec8339, 2019)
+- Version: git pre-2.90 (cd8cf7521cbb8b7808126a6adebd47bb83ea166a, 2020)
- License: zlib
+Important: Synced with a pre-release version of bullet 2.90 from the master branch.
+
Files extracted from upstream source:
- src/* apart from CMakeLists.txt and premake4.lua files
@@ -38,7 +54,7 @@ Files extracted from upstream source:
## certs
- Upstream: Mozilla, via https://apps.fedoraproject.org/packages/ca-certificates
-- Version: 2018.2.26
+- Version: 2018.2.26 (2018)
- License: MPL 2.0
File extracted from a recent Fedora install:
@@ -50,7 +66,7 @@ as it's generated on the user's system.)
## cvtt
- Upstream: https://github.com/elasota/cvtt
-- Version: 1.0.0-beta4
+- Version: 1.0.0-beta4 (2018)
- License: MIT
Files extracted from upstream source:
@@ -61,7 +77,7 @@ Files extracted from upstream source:
## enet
- Upstream: http://enet.bespin.org
-- Version: 1.3.13
+- Version: 1.3.15 (224f31101fc60939c02f6bbe8e8fc810a7db306b, 2020)
- License: MIT
Files extracted from upstream source:
@@ -71,19 +87,21 @@ Files extracted from upstream source:
- LICENSE file
Important: enet.h, host.c, protocol.c have been slightly modified
-to be usable by godot socket implementation and allow IPv6.
+to be usable by godot socket implementation and allow IPv6 and DTLS.
+Apply the patches in the `patches/` folder when syncing on newer upstream
+commits.
+
Two files (godot.cpp and enet/godot.h) have been added to provide
enet socket implementation using Godot classes.
+
It is still possible to build against a system wide ENet but doing so
-will limit it's functionality to IPv4 only.
-Check the diff of enet.h, protocol.c, and host.c with the 1.3.13
-tarball before the next update.
+will limit its functionality to IPv4 only.
## etc2comp
- Upstream: https://github.com/google/etc2comp
-- Version: git (9cd0f9c, 2017)
+- Version: git (9cd0f9cae0f32338943699bb418107db61bb66f2, 2017)
- License: Apache 2.0
Files extracted from upstream source:
@@ -101,7 +119,7 @@ comments.
### Noto Sans
- Upstream: https://github.com/googlei18n/noto-fonts
-- Version: 1.06
+- Version: 1.06 (2017)
- License: OFL-1.1
Use UI font variant if available, because it has tight vertical metrics and good for UI.
@@ -109,7 +127,7 @@ Use UI font variant if available, because it has tight vertical metrics and good
### Hack Regular
- Upstream: https://github.com/source-foundry/Hack
-- Version: 3.003
+- Version: 3.003 (2018)
- License: MIT + Bitstream Vera License
### DroidSans*.ttf
@@ -122,7 +140,7 @@ Use UI font variant if available, because it has tight vertical metrics and good
## freetype
- Upstream: https://www.freetype.org
-- Version: 2.10.1
+- Version: 2.10.2 (2020)
- License: FreeType License (BSD-like)
Files extracted from upstream source:
@@ -135,7 +153,7 @@ Files extracted from upstream source:
## glad
- Upstream: https://github.com/Dav1dde/glad
-- Version: 0.1.33
+- Version: 0.1.33 (2019)
- License: MIT
The files we package are automatically generated.
@@ -143,21 +161,41 @@ See the header of glad.c for instructions on how to generate them for
the GLES version Godot targets.
+## glslang
+
+- Upstream: https://github.com/KhronosGroup/glslang
+- Version: git (4fc7a33910fb8e40b970d160e1b38ab3f67fe0f3, 2020)
+- License: glslang
+
+Version should be kept in sync with the one of the used Vulkan SDK (see `vulkan`
+section). Check Vulkan-ValidationLayers at the matching SDK tag for the known
+good glslang commit: https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/scripts/known_good.json
+
+Files extracted from upstream source:
+
+- `glslang`, `OGLCompilersDLL`, `SPIRV`
+- `LICENSE.txt`
+- Unnecessary files like `CMakeLists.txt`, `revision.template` and
+ `updateGrammar` removed.
+
+Patches in the `patches` directory should be re-applied after updates.
+
+
## jpeg-compressor
- Upstream: https://github.com/richgel999/jpeg-compressor
-- Version: 1.04
+- Version: 2.00 (aeb7d3b463aa8228b87a28013c15ee50a7e6fcf3, 2020)
- License: Public domain
Files extracted from upstream source:
-- `jpgd.{c,h}`
+- `jpgd*.{c,h}`
## libogg
- Upstream: https://www.xiph.org/ogg
-- Version: git (c8fca6b, 2019)
+- Version: git (c8fca6b4a02d695b1ceea39b330d4406001c03ed, 2019)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -170,7 +208,7 @@ Files extracted from upstream source:
## libpng
- Upstream: http://libpng.org/pub/png/libpng.html
-- Version: 1.6.37
+- Version: 1.6.37 (2019)
- License: libpng/zlib
Files extracted from upstream source:
@@ -185,7 +223,7 @@ Files extracted from upstream source:
## libsimplewebm
- Upstream: https://github.com/zaps166/libsimplewebm
-- Version: git (fe57fd3, 2019)
+- Version: git (fe57fd3cfe6c0af4c6af110b1f84a90cf191d943, 2019)
- License: MIT (main), BSD-3-Clause (libwebm)
This contains libwebm, but the version in use is updated from the one used by libsimplewebm,
@@ -204,7 +242,7 @@ comments.
## libtheora
- Upstream: https://www.theora.org
-- Version: 1.1.1
+- Version: 1.1.1 (2010)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -220,7 +258,7 @@ on top of the 1.1.1 source (not included in any stable release yet).
## libvorbis
- Upstream: https://www.xiph.org/vorbis
-- Version: 1.3.6
+- Version: 1.3.6 (2018)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -233,7 +271,7 @@ Files extracted from upstream source:
## libvpx
- Upstream: https://chromium.googlesource.com/webm/libvpx/
-- Version: 1.6.0
+- Version: 1.6.0 (2016)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -250,7 +288,7 @@ from the Android NDK r18.
## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/
-- Version: 1.0.3
+- Version: 1.1.0 (2020)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -266,18 +304,19 @@ changes are marked with `// -- GODOT --` comments.
## mbedtls
- Upstream: https://tls.mbed.org/
-- Version: 2.16.3
+- Version: 2.16.6 (2020)
- License: Apache 2.0
File extracted from upstream release tarball (`-apache.tgz` variant):
+
- All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/`
- All `*.c` from `library/` to `thirdparty/mbedtls/library/`
- LICENSE and apache-2.0.txt files
- Applied the patch in `thirdparty/mbedtls/patches/1453.diff` (PR 1453).
Soon to be merged upstream. Check it out at next update.
-- Applied the patch in `thirdparty/mbedtls/patches/padlock.diff`. This disables VIA
- padlock support which defines a symbol `unsupported` which clashes with
- a symbol in libwebsockets.
+- Applied the patch in `thirdparty/mbedtls/patches/padlock.diff`. This disables
+ VIA padlock support which defines a symbol `unsupported` which clashes with
+ a pre-defined symbol.
- Added 2 files `godot_core_mbedtls_platform.{c,h}` providing configuration
for light bundling with core.
@@ -285,7 +324,7 @@ File extracted from upstream release tarball (`-apache.tgz` variant):
## miniupnpc
- Upstream: https://github.com/miniupnp/miniupnp/tree/master/miniupnpc
-- Version: git (0ab1d67, 2019)
+- Version: git (44366328661826603982d1e0d7ebb4062c5f2bfc, 2020)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -293,6 +332,7 @@ Files extracted from upstream source:
- All `*.c` and `*.h` files from `miniupnpc` to `thirdparty/miniupnpc/miniupnpc`
- Remove `test*`, `minihttptestserver.c` and `wingenminiupnpcstrings.c`
+The patch `windows_fix.diff` is applied to `minissdpc.c` to fix an upstream issue.
The only modified file is miniupnpcstrings.h, which was created for Godot
(it is usually autogenerated by cmake).
@@ -300,7 +340,7 @@ The only modified file is miniupnpcstrings.h, which was created for Godot
## minizip
- Upstream: http://www.zlib.net
-- Version: 1.2.11 (zlib contrib)
+- Version: 1.2.11 (zlib contrib, 2017)
- License: zlib
Files extracted from the upstream source:
@@ -320,11 +360,15 @@ Collection of single-file libraries used in Godot components.
- `clipper.{cpp,hpp}`
* Upstream: https://sourceforge.net/projects/polyclipping
- * Version: 6.4.2 + Godot changes (added optional exceptions handling)
+ * Version: 6.4.2 (2017) + Godot changes (added optional exceptions handling)
* License: BSL-1.0
+- `cubemap_coeffs.h`
+ * Upstream: https://research.activision.com/publications/archives/fast-filtering-of-reflection-probes
+ File coeffs_const_8.txt (retrieved April 2020)
+ * License: MIT
- `fastlz.{c,h}`
* Upstream: https://github.com/ariya/FastLZ
- * Version: git (f121734, 2007)
+ * Version: 0.5.0 (4f20f54d46f5a6dd4fae4def134933369b7602d2, 2020)
* License: MIT
- `hq2x.{cpp,h}`
* Upstream: https://github.com/brunexgeek/hqx
@@ -332,17 +376,25 @@ Collection of single-file libraries used in Godot components.
* License: Apache 2.0
- `open-simplex-noise.{c,h}`
* Upstream: https://github.com/smcameron/open-simplex-noise-in-c
- * Version: git (0d555e7, 2015)
+ * Version: git (0d555e7f40527d0870906fe9469a3b1bb4020b7f, 2015) + custom changes
* License: Unlicense
- `pcg.{cpp,h}`
* Upstream: http://www.pcg-random.org
* Version: minimal C implementation, http://www.pcg-random.org/download.html
* License: Apache 2.0
+- `r128.h`
+ * Upstream: https://github.com/fahickman/r128
+ * Version: git (423f693617faafd01de21e92818add4208eb8bd1, 2020)
+ * License: Public Domain
- `smaz.{c,h}`
* Upstream: https://github.com/antirez/smaz
- * Version: git (150e125, 2009)
+ * Version: git (150e125cbae2e8fd20dd332432776ce13395d4d4, 2009)
* License: BSD-3-Clause
* Modifications: use `const char*` instead of `char*` for input string
+- `stb_rect_pack.h`
+ * Upstream: https://github.com/nothings/stb
+ * Version: 1.00 (2019)
+ * License: Public Domain (Unlicense) or MIT
- `triangulator.{cpp,h}`
* Upstream: https://github.com/ivanfratric/polypartition (`src/polypartition.cpp`)
* Version: TBD, class was renamed
@@ -350,10 +402,6 @@ Collection of single-file libraries used in Godot components.
### modules
-- `curl_hostcheck.{c,h}`
- * Upstream: https://curl.haxx.se/
- * Version: ? (2013)
- * License: MIT
- `yuv2rgb.h`
* Upstream: http://wss.co.uk/pinknoise/yuv2rgb/ (to check)
* Version: ?
@@ -363,29 +411,30 @@ Collection of single-file libraries used in Godot components.
- `ifaddrs-android.{cc,h}`
* Upstream: https://chromium.googlesource.com/external/webrtc/stable/talk/+/master/base/ifaddrs-android.h
- * Version: git (5976650, 2013)
+ * Version: git (5976650443d68ccfadf1dea24999ee459dd2819d, 2013)
* License: BSD-3-Clause
### scene
- `easing_equations.cpp`
* Upstream: http://robertpenner.com/easing/ via https://github.com/jesusgollonet/ofpennereasing (modified to fit Godot types)
- * Version: git (af72c14, 2008) + Godot types and style changes
+ * Version: git (af72c147c3a74e7e872aa28c7e2abfcced04fdce, 2008) + Godot types and style changes
* License: BSD-3-Clause
- `mikktspace.{c,h}`
- * Upstream: https://wiki.blender.org/index.php/Dev:Shading/Tangent_Space_Normal_Maps
- * Version: 1.0
+ * Upstream: https://archive.blender.org/wiki/index.php/Dev:Shading/Tangent_Space_Normal_Maps/
+ * Version: 1.0 (2011)
* License: zlib
- `stb_vorbis.c`
* Upstream: https://github.com/nothings/stb
- * Version: 1.17
+ * Version: 1.19
* License: Public Domain (Unlicense) or MIT
+ * Modifications: `f->temp_offset += (sz+3)&~3;` changed to `f->temp_offset += (sz+7)&~7;` (needed until fixed upstream)
## nanosvg
- Upstream: https://github.com/memononen/nanosvg
-- Version: git (25241c5, 2019)
+- Version: git (25241c5a8f8451d41ab1b02ab2d865b01600d949, 2019)
- License: zlib
Files extracted from the upstream source:
@@ -394,36 +443,44 @@ Files extracted from the upstream source:
- LICENSE.txt
+## oidn
+
+- Upstream: https://github.com/OpenImageDenoise/oidn
+- Version: TBD
+- License: Apache 2.0
+
+Files extracted from upstream source:
+
+- TBD
+
+
## opus
- Upstream: https://opus-codec.org
-- Version: 1.3.1 (opus) and 0.11 (opusfile)
+- Version: 1.1.5 (opus) and 0.8 (opusfile) (2017)
- License: BSD-3-Clause
Files extracted from upstream source:
-- Run `opus/configure` and copy/sync changes to `config.h`
- (note that this file may have Godot-specific options enabled)
- all .c and .h files in src/ (both opus and opusfile)
- all .h files in include/ (both opus and opusfile) as opus/
- remove unused `opus_demo.c`,
- remove `http.c`, `wincerts.c` and `winerrno.h` (part of
unused libopusurl)
-- celt/ and silk/ subfolders (minus tests folders)
+- celt/ and silk/ subfolders
- COPYING
## pcre2
- Upstream: http://www.pcre.org
-- Version: 10.33
+- Version: 10.34 (2019)
- License: BSD-3-Clause
Files extracted from upstream source:
- Files listed in the file NON-AUTOTOOLS-BUILD steps 1-4
- All .h files in src/ apart from pcre2posix.h
-- src/pcre2_jit_compile.c
- src/pcre2_jit_match.c
- src/pcre2_jit_misc.c
- src/sljit/*
@@ -433,7 +490,7 @@ Files extracted from upstream source:
## pvrtccompressor
- Upstream: https://bitbucket.org/jthlim/pvrtccompressor
-- Version: hg (cf71777, 2015)
+- Version: hg (cf7177748ee0dcdccfe89716dc11a47d2dc81af5, 2015)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -445,19 +502,35 @@ Files extracted from upstream source:
## recastnavigation
- Upstream: https://github.com/recastnavigation/recastnavigation
-- version: git (ef3ea40f, 2017)
+- Version: git (57610fa6ef31b39020231906f8c5d40eaa8294ae, 2019)
- License: zlib
Files extracted from upstream source:
-- `Recast/` folder
+- `Recast/` folder without `CMakeLists.txt`
- License.txt
+## rvo2
+
+- Upstream: http://gamma.cs.unc.edu/RVO2/
+- Version: 3D - 1.0.1 (2016)
+- License: Apache 2.0
+
+Files extracted from upstream source:
+
+- All .cpp and .h files in the `src/` folder except for RVO.h, RVOSimulator.cpp and RVOSimulator.h
+- LICENSE
+
+Important: Some files have Godot-made changes; so to enrich the features
+originally proposed by this library and better integrate this library with
+Godot. Please check the file to know what's new.
+
+
## squish
- Upstream: https://sourceforge.net/projects/libsquish
-- Version: 1.15
+- Version: 1.15 (2017)
- License: MIT
Files extracted from upstream source:
@@ -472,7 +545,7 @@ comments and a patch is provided in the squish/ folder.
## tinyexr
- Upstream: https://github.com/syoyo/tinyexr
-- Version: git (656bb61, 2019)
+- Version: git (4dbd05a22f51a2d7462311569b8b0cba0bbe2ac5, 2020)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -483,7 +556,7 @@ Files extracted from upstream source:
## vhacd
- Upstream: https://github.com/kmammou/v-hacd
-- Version: git (b07958e, 2019)
+- Version: git (b07958e18e01d504e3af80eeaeb9f033226533d7, 2019)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -497,10 +570,40 @@ They can be reapplied using the patches included in the `vhacd`
folder.
+## vulkan
+
+- Upstream: https://github.com/KhronosGroup/Vulkan-Loader
+- Version: sdk-1.2.131.2 (2020)
+- License: Apache 2.0
+
+Unless there is a specific reason to package a more recent version, please stick
+to Vulkan SDK releases (prefixed by `sdk-`) for all components.
+
+NOTE: Use `scripts/update_deps.py --ref <version>` in the Loader git repository
+to retrieve the `Vulkan-Headers` repository matching the loader version.
+
+Files extracted from upstream source:
+
+- `Vulkan-Headers/include/` as `include/`
+- All `.c` and `.h` files in `loader/` and `loader/generated/`, put in a common
+ `loader/` folder
+- `LICENSE.txt`
+
+`vk_enum_string_helper.h` is taken from the matching `Vulkan-ValidationLayers`
+SDK release: https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/layers/generated/vk_enum_string_helper.h
+Includes custom change to disable MSVC pragma, might be upstreamed via:
+https://github.com/KhronosGroup/Vulkan-ValidationLayers/pull/1666
+
+`vk_mem_alloc.h` is taken from https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
+Version: 2.3.0 (2019)
+
+Patches in the `patches` directory should be re-applied after updates.
+
+
## wslay
- Upstream: https://github.com/tatsuhiro-t/wslay
-- Version: 1.1.0
+- Version: 1.1.0 (2018)
- License: MIT
File extracted from upstream release tarball:
@@ -513,21 +616,19 @@ File extracted from upstream release tarball:
## xatlas
- Upstream: https://github.com/jpcy/xatlas
-- Version: git (b4b5426, 2019)
+- Version: git (e12ea82, 2019)
- License: MIT
Files extracted from upstream source:
- `xatlas.{cpp,h}`
-
-Note: License is marked as Public Domain in the files, but it was
-later clarified upstream to MIT license.
+- `LICENSE`
## zlib
- Upstream: http://www.zlib.net
-- Version: 1.2.11
+- Version: 1.2.11 (2017)
- License: zlib
Files extracted from upstream source:
@@ -538,7 +639,7 @@ Files extracted from upstream source:
## zstd
- Upstream: https://github.com/facebook/zstd
-- Version: 1.4.4
+- Version: 1.4.4 (2019)
- License: BSD-3-Clause
Files extracted from upstream source:
diff --git a/thirdparty/assimp/contrib/utf8cpp/doc/ReleaseNotes b/thirdparty/assimp/contrib/utf8cpp/doc/ReleaseNotes
deleted file mode 100644
index 364411a23d..0000000000
--- a/thirdparty/assimp/contrib/utf8cpp/doc/ReleaseNotes
+++ /dev/null
@@ -1,12 +0,0 @@
-utf8 cpp library
-Release 2.3.4
-
-A minor bug fix release. Thanks to all who reported bugs.
-
-Note: Version 2.3.3 contained a regression, and therefore was removed.
-
-Changes from version 2.3.2
-- Bug fix [39]: checked.h Line 273 and unchecked.h Line 182 have an extra ';'
-- Bug fix [36]: replace_invalid() only works with back_inserter
-
-Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes
diff --git a/thirdparty/assimp/contrib/utf8cpp/doc/utf8cpp.html b/thirdparty/assimp/contrib/utf8cpp/doc/utf8cpp.html
deleted file mode 100644
index 6f2aacbe7b..0000000000
--- a/thirdparty/assimp/contrib/utf8cpp/doc/utf8cpp.html
+++ /dev/null
@@ -1,1789 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
- <head>
- <meta name="generator" content=
- "HTML Tidy for Linux/x86 (vers 1st November 2002), see www.w3.org">
- <meta name="description" content=
- "A simple, portable and lightweigt C++ library for easy handling of UTF-8 encoded strings">
- <meta name="keywords" content="UTF-8 C++ portable utf8 unicode generic templates">
- <meta name="author" content="Nemanja Trifunovic">
- <title>
- UTF8-CPP: UTF-8 with C++ in a Portable Way
- </title>
- <style type="text/css">
- <!--
- span.return_value {
- color: brown;
- }
- span.keyword {
- color: blue;
- }
- span.preprocessor {
- color: navy;
- }
- span.literal {
- color: olive;
- }
- span.comment {
- color: green;
- }
- code {
- font-weight: bold;
- }
- ul.toc {
- list-style-type: none;
- }
- p.version {
- font-size: small;
- font-style: italic;
- }
- -->
- </style>
- </head>
- <body>
- <h1>
- UTF8-CPP: UTF-8 with C++ in a Portable Way
- </h1>
- <p>
- <a href="https://sourceforge.net/projects/utfcpp">The Sourceforge project page</a>
- </p>
- <div id="toc">
- <h2>
- Table of Contents
- </h2>
- <ul class="toc">
- <li>
- <a href="#introduction">Introduction</a>
- </li>
- <li>
- <a href="#examples">Examples of Use</a>
- <ul class="toc">
- <li>
- <a href=#introsample>Introductionary Sample </a>
- </li>
- <li>
- <a href=#validfile>Checking if a file contains valid UTF-8 text</a>
- </li>
- <li>
- <a href=#fixinvalid>Ensure that a string contains valid UTF-8 text</a>
- </li>
- </ul>
- <li>
- <a href="#reference">Reference</a>
- <ul class="toc">
- <li>
- <a href="#funutf8">Functions From utf8 Namespace </a>
- </li>
- <li>
- <a href="#typesutf8">Types From utf8 Namespace </a>
- </li>
- <li>
- <a href="#fununchecked">Functions From utf8::unchecked Namespace </a>
- </li>
- <li>
- <a href="#typesunchecked">Types From utf8::unchecked Namespace </a>
- </li>
- </ul>
- </li>
- <li>
- <a href="#points">Points of Interest</a>
- </li>
- <li>
- <a href="#links">Links</a>
- </li>
- </ul>
- </div>
- <h2 id="introduction">
- Introduction
- </h2>
- <p>
- Many C++ developers miss an easy and portable way of handling Unicode encoded
- strings. The original C++ Standard (known as C++98 or C++03) is Unicode agnostic.
- C++11 provides some support for Unicode on core language and library level:
- u8, u, and U character and string literals, char16_t and char32_t character types,
- u16string and u32string library classes, and codecvt support for conversions
- between Unicode encoding forms.
- In the meantime, developers use third party libraries like ICU, OS specific capabilities, or simply
- roll out their own solutions.
- </p>
- <p>
- In order to easily handle UTF-8 encoded Unicode strings, I came up with a small
- generic library. For anybody used to work with STL algorithms and iterators, it should be
- easy and natural to use. The code is freely available for any purpose - check out
- the license at the beginning of the utf8.h file. If you run into
- bugs or performance issues, please let me know and I'll do my best to address them.
- </p>
- <p>
- The purpose of this article is not to offer an introduction to Unicode in general,
- and UTF-8 in particular. If you are not familiar with Unicode, be sure to check out
- <a href="http://www.unicode.org/">Unicode Home Page</a> or some other source of
- information for Unicode. Also, it is not my aim to advocate the use of UTF-8
- encoded strings in C++ programs; if you want to handle UTF-8 encoded strings from
- C++, I am sure you have good reasons for it.
- </p>
- <h2 id="examples">
- Examples of use
- </h2>
- <h3 id="introsample">
- Introductionary Sample
- </h3>
- <p>
- To illustrate the use of the library, let's start with a small but complete program
- that opens a file containing UTF-8 encoded text, reads it line by line, checks each line
- for invalid UTF-8 byte sequences, and converts it to UTF-16 encoding and back to UTF-8:
- </p>
-<pre>
-<span class="preprocessor">#include &lt;fstream&gt;</span>
-<span class="preprocessor">#include &lt;iostream&gt;</span>
-<span class="preprocessor">#include &lt;string&gt;</span>
-<span class="preprocessor">#include &lt;vector&gt;</span>
-<span class="preprocessor">#include "utf8.h"</span>
-<span class="keyword">using namespace</span> std;
-<span class="keyword">int</span> main(<span class="keyword">int</span> argc, <span class="keyword">char</span>** argv)
-{
- <span class="keyword">if</span> (argc != <span class="literal">2</span>) {
- cout &lt;&lt; <span class="literal">"\nUsage: docsample filename\n"</span>;
- <span class="keyword">return</span> <span class="literal">0</span>;
- }
-
- <span class="keyword">const char</span>* test_file_path = argv[1];
- <span class="comment">// Open the test file (contains UTF-8 encoded text)</span>
- ifstream fs8(test_file_path);
- <span class="keyword">if</span> (!fs8.is_open()) {
- cout &lt;&lt; <span class=
-"literal">"Could not open "</span> &lt;&lt; test_file_path &lt;&lt; endl;
- <span class="keyword">return</span> <span class="literal">0</span>;
- }
-
- <span class="keyword">unsigned</span> line_count = <span class="literal">1</span>;
- string line;
- <span class="comment">// Play with all the lines in the file</span>
- <span class="keyword">while</span> (getline(fs8, line)) {
- <span class="comment">// check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)</span>
- string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
- <span class="keyword">if</span> (end_it != line.end()) {
- cout &lt;&lt; <span class=
-"literal">"Invalid UTF-8 encoding detected at line "</span> &lt;&lt; line_count &lt;&lt; <span
- class="literal">"\n"</span>;
- cout &lt;&lt; <span class=
-"literal">"This part is fine: "</span> &lt;&lt; string(line.begin(), end_it) &lt;&lt; <span
- class="literal">"\n"</span>;
- }
-
- <span class="comment">// Get the line length (at least for the valid part)</span>
- <span class="keyword">int</span> length = utf8::distance(line.begin(), end_it);
- cout &lt;&lt; <span class=
-"literal">"Length of line "</span> &lt;&lt; line_count &lt;&lt; <span class=
-"literal">" is "</span> &lt;&lt; length &lt;&lt; <span class="literal">"\n"</span>;
-
- <span class="comment">// Convert it to utf-16</span>
- vector&lt;unsigned short&gt; utf16line;
- utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
-
- <span class="comment">// And back to utf-8</span>
- string utf8line;
- utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
-
- <span class="comment">// Confirm that the conversion went OK:</span>
- <span class="keyword">if</span> (utf8line != string(line.begin(), end_it))
- cout &lt;&lt; <span class=
-"literal">"Error in UTF-16 conversion at line: "</span> &lt;&lt; line_count &lt;&lt; <span
- class="literal">"\n"</span>;
-
- line_count++;
- }
- <span class="keyword">return</span> <span class="literal">0</span>;
-}
-</pre>
- <p>
- In the previous code sample, for each line we performed
- a detection of invalid UTF-8 sequences with <code>find_invalid</code>; the number
- of characters (more precisely - the number of Unicode code points, including the end
- of line and even BOM if there is one) in each line was
- determined with a use of <code>utf8::distance</code>; finally, we have converted
- each line to UTF-16 encoding with <code>utf8to16</code> and back to UTF-8 with
- <code>utf16to8</code>.
- </p>
- <h3 id="validfile">Checking if a file contains valid UTF-8 text</h3>
-<p>
-Here is a function that checks whether the content of a file is valid UTF-8 encoded text without
-reading the content into the memory:
-</p>
-<pre>
-<span class="keyword">bool</span> valid_utf8_file(i<span class="keyword">const char</span>* file_name)
-{
- ifstream ifs(file_name);
- <span class="keyword">if</span> (!ifs)
- <span class="keyword">return false</span>; <span class="comment">// even better, throw here</span>
-
- istreambuf_iterator&lt;<span class="keyword">char</span>&gt; it(ifs.rdbuf());
- istreambuf_iterator&lt;<span class="keyword">char</span>&gt; eos;
-
- <span class="keyword">return</span> utf8::is_valid(it, eos);
-}
-</pre>
-<p>
-Because the function <code>utf8::is_valid()</code> works with input iterators, we were able
-to pass an <code>istreambuf_iterator</code> to it and read the content of the file directly
-without loading it to the memory first.</p>
-<p>
-Note that other functions that take input iterator arguments can be used in a similar way. For
-instance, to read the content of a UTF-8 encoded text file and convert the text to UTF-16, just
-do something like:
-</p>
-<pre>
- utf8::utf8to16(it, eos, back_inserter(u16string));
-</pre>
- <h3 id="fixinvalid">Ensure that a string contains valid UTF-8 text</h3>
-<p>
-If we have some text that "probably" contains UTF-8 encoded text and we want to
-replace any invalid UTF-8 sequence with a replacement character, something like
-the following function may be used:
-</p>
-<pre>
-<span class="keyword">void</span> fix_utf8_string(std::string&amp; str)
-{
- std::string temp;
- utf8::replace_invalid(str.begin(), str.end(), back_inserter(temp));
- str = temp;
-}
-</pre>
-<p>The function will replace any invalid UTF-8 sequence with a Unicode replacement character.
-There is an overloaded function that enables the caller to supply their own replacement character.
-</p>
- <h2 id="reference">
- Reference
- </h2>
- <h3 id="funutf8">
- Functions From utf8 Namespace
- </h3>
- <h4>
- utf8::append
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence
- to a UTF-8 string.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-octet_iterator append(uint32_t cp, octet_iterator result);
-
-</pre>
- <p>
- <code>octet_iterator</code>: an output iterator.<br>
- <code>cp</code>: a 32 bit integer representing a code point to append to the
- sequence.<br>
- <code>result</code>: an output iterator to the place in the sequence where to
- append the code point.<br>
- <span class="return_value">Return value</span>: an iterator pointing to the place
- after the newly appended sequence.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">unsigned char</span> u[<span class="literal">5</span>] = {<span
-class="literal">0</span>,<span class="literal">0</span>,<span class=
-"literal">0</span>,<span class="literal">0</span>,<span class="literal">0</span>};
-<span class="keyword">unsigned char</span>* end = append(<span class=
-"literal">0x0448</span>, u);
-assert (u[<span class="literal">0</span>] == <span class=
-"literal">0xd1</span> &amp;&amp; u[<span class="literal">1</span>] == <span class=
-"literal">0x88</span> &amp;&amp; u[<span class="literal">2</span>] == <span class=
-"literal">0</span> &amp;&amp; u[<span class="literal">3</span>] == <span class=
-"literal">0</span> &amp;&amp; u[<span class="literal">4</span>] == <span class=
-"literal">0</span>);
-</pre>
- <p>
- Note that <code>append</code> does not allocate any memory - it is the burden of
- the caller to make sure there is enough memory allocated for the operation. To make
- things more interesting, <code>append</code> can add anywhere between 1 and 4
- octets to the sequence. In practice, you would most often want to use
- <code>std::back_inserter</code> to ensure that the necessary memory is allocated.
- </p>
- <p>
- In case of an invalid code point, a <code>utf8::invalid_code_point</code> exception
- is thrown.
- </p>
- <h4>
- utf8::next
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Given the iterator to the beginning of the UTF-8 sequence, it returns the code
- point and moves the iterator to the next position.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-uint32_t next(octet_iterator&amp; it, octet_iterator end);
-
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
- encoded code point. After the function returns, it is incremented to point to the
- beginning of the next code point.<br>
- <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
- gets equal to <code>end</code> during the extraction of a code point, an
- <code>utf8::not_enough_room</code> exception is thrown.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- processed UTF-8 code point.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-<span class="keyword">char</span>* w = twochars;
-<span class="keyword">int</span> cp = next(w, twochars + <span class="literal">6</span>);
-assert (cp == <span class="literal">0x65e5</span>);
-assert (w == twochars + <span class="literal">3</span>);
-</pre>
- <p>
- This function is typically used to iterate through a UTF-8 encoded string.
- </p>
- <p>
- In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
- thrown.
- </p>
- <h4>
- utf8::peek_next
- </h4>
- <p class="version">
- Available in version 2.1 and later.
- </p>
- <p>
- Given the iterator to the beginning of the UTF-8 sequence, it returns the code
- point for the following sequence without changing the value of the iterator.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-uint32_t peek_next(octet_iterator it, octet_iterator end);
-
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>it</code>: an iterator pointing to the beginning of an UTF-8
- encoded code point.<br>
- <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
- gets equal to <code>end</code> during the extraction of a code point, an
- <code>utf8::not_enough_room</code> exception is thrown.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- processed UTF-8 code point.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-<span class="keyword">char</span>* w = twochars;
-<span class="keyword">int</span> cp = peek_next(w, twochars + <span class="literal">6</span>);
-assert (cp == <span class="literal">0x65e5</span>);
-assert (w == twochars);
-</pre>
- <p>
- In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
- thrown.
- </p>
- <h4>
- utf8::prior
- </h4>
- <p class="version">
- Available in version 1.02 and later.
- </p>
- <p>
- Given a reference to an iterator pointing to an octet in a UTF-8 sequence, it
- decreases the iterator until it hits the beginning of the previous UTF-8 encoded
- code point and returns the 32 bits representation of the code point.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-uint32_t prior(octet_iterator&amp; it, octet_iterator start);
-
-</pre>
- <p>
- <code>octet_iterator</code>: a bidirectional iterator.<br>
- <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
- After the function returns, it is decremented to point to the beginning of the
- previous code point.<br>
- <code>start</code>: an iterator to the beginning of the sequence where the search
- for the beginning of a code point is performed. It is a
- safety measure to prevent passing the beginning of the string in the search for a
- UTF-8 lead octet.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- previous code point.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-<span class="keyword">unsigned char</span>* w = twochars + <span class=
-"literal">3</span>;
-<span class="keyword">int</span> cp = prior (w, twochars);
-assert (cp == <span class="literal">0x65e5</span>);
-assert (w == twochars);
-</pre>
- <p>
- This function has two purposes: one is two iterate backwards through a UTF-8
- encoded string. Note that it is usually a better idea to iterate forward instead,
- since <code>utf8::next</code> is faster. The second purpose is to find a beginning
- of a UTF-8 sequence if we have a random position within a string. Note that in that
- case <code>utf8::prior</code> may not detect an invalid UTF-8 sequence in some scenarios:
- for instance if there are superfluous trail octets, it will just skip them.
- </p>
- <p>
- <code>it</code> will typically point to the beginning of
- a code point, and <code>start</code> will point to the
- beginning of the string to ensure we don't go backwards too far. <code>it</code> is
- decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence
- beginning with that octet is decoded to a 32 bit representation and returned.
- </p>
- <p>
- In case <code>start</code> is reached before a UTF-8 lead octet is hit, or if an
- invalid UTF-8 sequence is started by the lead octet, an <code>invalid_utf8</code>
- exception is thrown.
- </p>
- <p>In case <code>start</code> equals <code>it</code>, a <code>not_enough_room</code>
- exception is thrown.
- <h4>
- utf8::previous
- </h4>
- <p class="version">
- Deprecated in version 1.02 and later.
- </p>
- <p>
- Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
- decreases the iterator until it hits the beginning of the previous UTF-8 encoded
- code point and returns the 32 bits representation of the code point.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-uint32_t previous(octet_iterator&amp; it, octet_iterator pass_start);
-
-</pre>
- <p>
- <code>octet_iterator</code>: a random access iterator.<br>
- <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
- After the function returns, it is decremented to point to the beginning of the
- previous code point.<br>
- <code>pass_start</code>: an iterator to the point in the sequence where the search
- for the beginning of a code point is aborted if no result was reached. It is a
- safety measure to prevent passing the beginning of the string in the search for a
- UTF-8 lead octet.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- previous code point.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-<span class="keyword">unsigned char</span>* w = twochars + <span class=
-"literal">3</span>;
-<span class="keyword">int</span> cp = previous (w, twochars - <span class=
-"literal">1</span>);
-assert (cp == <span class="literal">0x65e5</span>);
-assert (w == twochars);
-</pre>
- <p>
- <code>utf8::previous</code> is deprecated, and <code>utf8::prior</code> should
- be used instead, although the existing code can continue using this function.
- The problem is the parameter <code>pass_start</code> that points to the position
- just before the beginning of the sequence. Standard containers don't have the
- concept of "pass start" and the function can not be used with their iterators.
- </p>
- <p>
- <code>it</code> will typically point to the beginning of
- a code point, and <code>pass_start</code> will point to the octet just before the
- beginning of the string to ensure we don't go backwards too far. <code>it</code> is
- decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence
- beginning with that octet is decoded to a 32 bit representation and returned.
- </p>
- <p>
- In case <code>pass_start</code> is reached before a UTF-8 lead octet is hit, or if an
- invalid UTF-8 sequence is started by the lead octet, an <code>invalid_utf8</code>
- exception is thrown
- </p>
- <h4>
- utf8::advance
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Advances an iterator by the specified number of code points within an UTF-8
- sequence.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator, typename distance_type&gt;
-<span class=
-"keyword">void</span> advance (octet_iterator&amp; it, distance_type n, octet_iterator end);
-
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>distance_type</code>: an integral type convertible to <code>octet_iterator</code>'s difference type.<br>
- <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
- encoded code point. After the function returns, it is incremented to point to the
- nth following code point.<br>
- <code>n</code>: a positive integer that shows how many code points we want to
- advance.<br>
- <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
- gets equal to <code>end</code> during the extraction of a code point, an
- <code>utf8::not_enough_room</code> exception is thrown.<br>
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-<span class="keyword">unsigned char</span>* w = twochars;
-advance (w, <span class="literal">2</span>, twochars + <span class="literal">6</span>);
-assert (w == twochars + <span class="literal">5</span>);
-</pre>
- <p>
- This function works only "forward". In case of a negative <code>n</code>, there is
- no effect.
- </p>
- <p>
- In case of an invalid code point, a <code>utf8::invalid_code_point</code> exception
- is thrown.
- </p>
- <h4>
- utf8::distance
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Given the iterators to two UTF-8 encoded code points in a seqence, returns the
- number of code points between them.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-<span class=
-"keyword">typename</span> std::iterator_traits&lt;octet_iterator&gt;::difference_type distance (octet_iterator first, octet_iterator last);
-
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>first</code>: an iterator to a beginning of a UTF-8 encoded code point.<br>
- <code>last</code>: an iterator to a "post-end" of the last UTF-8 encoded code
- point in the sequence we are trying to determine the length. It can be the
- beginning of a new code point, or not.<br>
- <span class="return_value">Return value</span> the distance between the iterators,
- in code points.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-size_t dist = utf8::distance(twochars, twochars + <span class="literal">5</span>);
-assert (dist == <span class="literal">2</span>);
-</pre>
- <p>
- This function is used to find the length (in code points) of a UTF-8 encoded
- string. The reason it is called <em>distance</em>, rather than, say,
- <em>length</em> is mainly because developers are used that <em>length</em> is an
- O(1) function. Computing the length of an UTF-8 string is a linear operation, and
- it looked better to model it after <code>std::distance</code> algorithm.
- </p>
- <p>
- In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
- thrown. If <code>last</code> does not point to the past-of-end of a UTF-8 seqence,
- a <code>utf8::not_enough_room</code> exception is thrown.
- </p>
- <h4>
- utf8::utf16to8
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-16 encoded string to UTF-8.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> u16bit_iterator, <span class=
-"keyword">typename</span> octet_iterator&gt;
-octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
-
-</pre>
- <p>
- <code>u16bit_iterator</code>: an input iterator.<br>
- <code>octet_iterator</code>: an output iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-16 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-16 encoded
- string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-8 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-8 string.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">unsigned short</span> utf16string[] = {<span class=
-"literal">0x41</span>, <span class="literal">0x0448</span>, <span class=
-"literal">0x65e5</span>, <span class="literal">0xd834</span>, <span class=
-"literal">0xdd1e</span>};
-vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
-utf16to8(utf16string, utf16string + <span class=
-"literal">5</span>, back_inserter(utf8result));
-assert (utf8result.size() == <span class="literal">10</span>);
-</pre>
- <p>
- In case of invalid UTF-16 sequence, a <code>utf8::invalid_utf16</code> exception is
- thrown.
- </p>
- <h4>
- utf8::utf8to16
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts an UTF-8 encoded string to UTF-16
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> u16bit_iterator, typename octet_iterator&gt;
-u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
-
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>u16bit_iterator</code>: an output iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
- string to convert. &lt; br /&gt; <code>end</code>: an iterator pointing to
- pass-the-end of the UTF-8 encoded string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-16 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-16 string.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span> utf8_with_surrogates[] = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e"</span>;
-vector &lt;<span class="keyword">unsigned short</span>&gt; utf16result;
-utf8to16(utf8_with_surrogates, utf8_with_surrogates + <span class=
-"literal">9</span>, back_inserter(utf16result));
-assert (utf16result.size() == <span class="literal">4</span>);
-assert (utf16result[<span class="literal">2</span>] == <span class=
-"literal">0xd834</span>);
-assert (utf16result[<span class="literal">3</span>] == <span class=
-"literal">0xdd1e</span>);
-</pre>
- <p>
- In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
- thrown. If <code>end</code> does not point to the past-of-end of a UTF-8 seqence, a
- <code>utf8::not_enough_room</code> exception is thrown.
- </p>
- <h4>
- utf8::utf32to8
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-32 encoded string to UTF-8.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator, typename u32bit_iterator&gt;
-octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
-
-</pre>
- <p>
- <code>octet_iterator</code>: an output iterator.<br>
- <code>u32bit_iterator</code>: an input iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-32 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-32 encoded
- string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-8 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-8 string.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">int</span> utf32string[] = {<span class=
-"literal">0x448</span>, <span class="literal">0x65E5</span>, <span class=
-"literal">0x10346</span>, <span class="literal">0</span>};
-vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
-utf32to8(utf32string, utf32string + <span class=
-"literal">3</span>, back_inserter(utf8result));
-assert (utf8result.size() == <span class="literal">9</span>);
-</pre>
- <p>
- In case of invalid UTF-32 string, a <code>utf8::invalid_code_point</code> exception
- is thrown.
- </p>
- <h4>
- utf8::utf8to32
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-8 encoded string to UTF-32.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator, <span class=
-"keyword">typename</span> u32bit_iterator&gt;
-u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
-
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>u32bit_iterator</code>: an output iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 encoded string
- to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-32 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-32 string.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-vector&lt;<span class="keyword">int</span>&gt; utf32result;
-utf8to32(twochars, twochars + <span class=
-"literal">5</span>, back_inserter(utf32result));
-assert (utf32result.size() == <span class="literal">2</span>);
-</pre>
- <p>
- In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
- thrown. If <code>end</code> does not point to the past-of-end of a UTF-8 seqence, a
- <code>utf8::not_enough_room</code> exception is thrown.
- </p>
- <h4>
- utf8::find_invalid
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Detects an invalid sequence within a UTF-8 string.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-octet_iterator find_invalid(octet_iterator start, octet_iterator end);
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
- test for validity.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to test
- for validity.<br>
- <span class="return_value">Return value</span>: an iterator pointing to the first
- invalid octet in the UTF-8 string. In case none were found, equals
- <code>end</code>.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span> utf_invalid[] = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88\xfa"</span>;
-<span class=
-"keyword">char</span>* invalid = find_invalid(utf_invalid, utf_invalid + <span class=
-"literal">6</span>);
-assert (invalid == utf_invalid + <span class="literal">5</span>);
-</pre>
- <p>
- This function is typically used to make sure a UTF-8 string is valid before
- processing it with other functions. It is especially important to call it if before
- doing any of the <em>unchecked</em> operations on it.
- </p>
- <h4>
- utf8::is_valid
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Checks whether a sequence of octets is a valid UTF-8 string.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-<span class="keyword">bool</span> is_valid(octet_iterator start, octet_iterator end);
-
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
- test for validity.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to test
- for validity.<br>
- <span class="return_value">Return value</span>: <code>true</code> if the sequence
- is a valid UTF-8 string; <code>false</code> if not.
- </p>
- Example of use:
-<pre>
-<span class="keyword">char</span> utf_invalid[] = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88\xfa"</span>;
-<span class="keyword">bool</span> bvalid = is_valid(utf_invalid, utf_invalid + <span
-class="literal">6</span>);
-assert (bvalid == false);
-</pre>
- <p>
- <code>is_valid</code> is a shorthand for <code>find_invalid(start, end) ==
- end;</code>. You may want to use it to make sure that a byte seqence is a valid
- UTF-8 string without the need to know where it fails if it is not valid.
- </p>
- <h4>
- utf8::replace_invalid
- </h4>
- <p class="version">
- Available in version 2.0 and later.
- </p>
- <p>
- Replaces all invalid UTF-8 sequences within a string with a replacement marker.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator, <span class=
-"keyword">typename</span> output_iterator&gt;
-output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator, <span class=
-"keyword">typename</span> output_iterator&gt;
-output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
-
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>output_iterator</code>: an output iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
- look for invalid UTF-8 sequences.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to look
- for invalid UTF-8 sequences.<br>
- <code>out</code>: An output iterator to the range where the result of replacement
- is stored.<br>
- <code>replacement</code>: A Unicode code point for the replacement marker. The
- version without this parameter assumes the value <code>0xfffd</code><br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the UTF-8 string with replaced invalid sequences.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span> invalid_sequence[] = <span class=
-"literal">"a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z"</span>;
-vector&lt;<span class="keyword">char</span>&gt; replace_invalid_result;
-replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), <span
- class="literal">'?'</span>);
-bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
-assert (bvalid);
-<span class="keyword">char</span>* fixed_invalid_sequence = <span class=
-"literal">"a????z"</span>;
-assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
-</pre>
- <p>
- <code>replace_invalid</code> does not perform in-place replacement of invalid
- sequences. Rather, it produces a copy of the original string with the invalid
- sequences replaced with a replacement marker. Therefore, <code>out</code> must not
- be in the <code>[start, end]</code> range.
- </p>
- <p>
- If <code>end</code> does not point to the past-of-end of a UTF-8 sequence, a
- <code>utf8::not_enough_room</code> exception is thrown.
- </p>
- <h4>
- utf8::starts_with_bom
- </h4>
- <p class="version">
- Available in version 2.3 and later. Relaces deprecated <code>is_bom()</code> function.
- </p>
- <p>
- Checks whether an octet sequence starts with a UTF-8 byte order mark (BOM)
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-<span class="keyword">bool</span> starts_with_bom (octet_iterator it, octet_iterator end);
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>it</code>: beginning of the octet sequence to check<br>
- <code>end</code>: pass-end of the sequence to check<br>
- <span class="return_value">Return value</span>: <code>true</code> if the sequence
- starts with a UTF-8 byte order mark; <code>false</code> if not.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">unsigned char</span> byte_order_mark[] = {<span class=
-"literal">0xef</span>, <span class="literal">0xbb</span>, <span class=
-"literal">0xbf</span>};
-<span class="keyword">bool</span> bbom = starts_with_bom(byte_order_mark, byte_order_mark + <span class="keyword">sizeof</span>(byte_order_mark));
-assert (bbom == <span class="literal">true</span>);
-</pre>
- <p>
- The typical use of this function is to check the first three bytes of a file. If
- they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8
- encoded text.
- </p>
- <h4>
- utf8::is_bom
- </h4>
- <p class="version">
- Available in version 1.0 and later. Deprecated in version 2.3. <code>starts_with_bom()</code> should be used
- instead.
- </p>
- <p>
- Checks whether a sequence of three octets is a UTF-8 byte order mark (BOM)
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-<span class="keyword">bool</span> is_bom (octet_iterator it); <span class="comment"> // Deprecated</span>
-</pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>it</code>: beginning of the 3-octet sequence to check<br>
- <span class="return_value">Return value</span>: <code>true</code> if the sequence
- is UTF-8 byte order mark; <code>false</code> if not.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">unsigned char</span> byte_order_mark[] = {<span class=
-"literal">0xef</span>, <span class="literal">0xbb</span>, <span class=
-"literal">0xbf</span>};
-<span class="keyword">bool</span> bbom = is_bom(byte_order_mark);
-assert (bbom == <span class="literal">true</span>);
-</pre>
- <p>
- The typical use of this function is to check the first three bytes of a file. If
- they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8
- encoded text.
- </p>
- <p>
- If a sequence is
- shorter than three bytes, an invalid iterator will be dereferenced. Therefore, this function is deprecated
- in favor of <code>starts_with_bom()</code>that takes the end of sequence as an argument.
- </p>
- <h3 id="typesutf8">
- Types From utf8 Namespace
- </h3>
- <h4>utf8::exception
- </h4>
- <p class="version">
- Available in version 2.3 and later.
- </p>
- <p>
- Base class for the exceptions thrown by UTF CPP library functions.
- </p>
-<pre>
-<span class="keyword">class</span> exception : <span class="keyword">public</span> std::exception {};
-</pre>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">try</span> {
- code_that_uses_utf_cpp_library();
-}
-<span class="keyword">catch</span>(<span class="keyword">const</span> utf8::exception&amp; utfcpp_ex) {
- cerr &lt;&lt; utfcpp_ex.what();
-}
-</pre>
-
- <h4>utf8::invalid_code_point
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Thrown by UTF8 CPP functions such as <code>advance</code> and <code>next</code> if an UTF-8 sequence represents and invalid code point.
- </p>
-
-<pre>
-<span class="keyword">class</span> invalid_code_point : <span class="keyword">public</span> exception {
-<span class="keyword">public</span>:
- uint32_t code_point() <span class="keyword">const</span>;
-};
-
-</pre>
- <p>
- Member function <code>code_point()</code> can be used to determine the invalid code point that
- caused the exception to be thrown.
- </p>
- <h4>utf8::invalid_utf8
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Thrown by UTF8 CPP functions such as <code>next</code> and <code>prior</code> if an invalid UTF-8 sequence
- is detected during decoding.
- </p>
-
-<pre>
-<span class="keyword">class</span> invalid_utf8 : <span class="keyword">public</span> exception {
-<span class="keyword">public</span>:
- uint8_t utf8_octet() <span class="keyword">const</span>;
-};
-</pre>
-
- <p>
- Member function <code>utf8_octet()</code> can be used to determine the beginning of the byte
- sequence that caused the exception to be thrown.
- </p>
-</pre>
- <h4>utf8::invalid_utf16
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Thrown by UTF8 CPP function <code>utf16to8</code> if an invalid UTF-16 sequence
- is detected during decoding.
- </p>
-
-<pre>
-<span class="keyword">class</span> invalid_utf16 : <span class="keyword">public</span> exception {
-<span class="keyword">public</span>:
- uint16_t utf16_word() <span class="keyword">const</span>;
-};
-</pre>
-
- <p>
- Member function <code>utf16_word()</code> can be used to determine the UTF-16 code unit
- that caused the exception to be thrown.
- </p>
- <h4>utf8::not_enough_room
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Thrown by UTF8 CPP functions such as <code>next</code> if the end of the decoded UTF-8 sequence
- was reached before the code point was decoded.
- </p>
-
-<pre>
-<span class="keyword">class</span> not_enough_room : <span class="keyword">public</span> exception {};
-</pre>
- <h4>
- utf8::iterator
- </h4>
- <p class="version">
- Available in version 2.0 and later.
- </p>
- <p>
- Adapts the underlying octet iterator to iterate over the sequence of code points,
- rather than raw octets.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class="keyword">typename</span> octet_iterator&gt;
-<span class="keyword">class</span> iterator;
-</pre>
-
- <h5>Member functions</h5>
- <dl>
- <dt><code>iterator();</code> <dd> the deafult constructor; the underlying <code>octet_iterator</code> is
- constructed with its default constructor.
- <dt><code><span class="keyword">explicit</span> iterator (const octet_iterator&amp; octet_it,
- const octet_iterator&amp; range_start,
- const octet_iterator&amp; range_end);</code> <dd> a constructor
- that initializes the underlying <code>octet_iterator</code> with <code>octet_it</code>
- and sets the range in which the iterator is considered valid.
- <dt><code>octet_iterator base () <span class="keyword">const</span>;</code> <dd> returns the
- underlying <code>octet_iterator</code>.
- <dt><code>uint32_t operator * () <span class="keyword">const</span>;</code> <dd> decodes the utf-8 sequence
- the underlying <code>octet_iterator</code> is pointing to and returns the code point.
- <dt><code><span class="keyword">bool operator</span> == (const iterator&amp; rhs)
- <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
- if the two underlaying iterators are equal.
- <dt><code><span class="keyword">bool operator</span> != (const iterator&amp; rhs)
- <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
- if the two underlaying iterators are not equal.
- <dt><code>iterator&amp; <span class="keyword">operator</span> ++ (); </code> <dd> the prefix increment - moves
- the iterator to the next UTF-8 encoded code point.
- <dt><code>iterator <span class="keyword">operator</span> ++ (<span class="keyword">int</span>); </code> <dd>
- the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
- <dt><code>iterator&amp; <span class="keyword">operator</span> -- (); </code> <dd> the prefix decrement - moves
- the iterator to the previous UTF-8 encoded code point.
- <dt><code>iterator <span class="keyword">operator</span> -- (<span class="keyword">int</span>); </code> <dd>
- the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
- </dl>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* threechars = <span class="literal">"\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"</span>;
-utf8::iterator&lt;<span class="keyword">char</span>*&gt; it(threechars, threechars, threechars + <span class="literal">9</span>);
-utf8::iterator&lt;<span class="keyword">char</span>*&gt; it2 = it;
-assert (it2 == it);
-assert (*it == <span class="literal">0x10346</span>);
-assert (*(++it) == <span class="literal">0x65e5</span>);
-assert ((*it++) == <span class="literal">0x65e5</span>);
-assert (*it == <span class="literal">0x0448</span>);
-assert (it != it2);
-utf8::iterator&lt;<span class="keyword">char</span>*&gt; endit (threechars + <span class="literal">9</span>, threechars, threechars + <span class="literal">9</span>);
-assert (++it == endit);
-assert (*(--it) == <span class="literal">0x0448</span>);
-assert ((*it--) == <span class="literal">0x0448</span>);
-assert (*it == <span class="literal">0x65e5</span>);
-assert (--it == utf8::iterator&lt;<span class="keyword">char</span>*&gt;(threechars, threechars, threechars + <span class="literal">9</span>));
-assert (*it == <span class="literal">0x10346</span>);
-</pre>
- <p>
- The purpose of <code>utf8::iterator</code> adapter is to enable easy iteration as well as the use of STL
- algorithms with UTF-8 encoded strings. Increment and decrement operators are implemented in terms of
- <code>utf8::next()</code> and <code>utf8::prior()</code> functions.
- </p>
- <p>
- Note that <code>utf8::iterator</code> adapter is a checked iterator. It operates on the range specified in
- the constructor; any attempt to go out of that range will result in an exception. Even the comparison operators
- require both iterator object to be constructed against the same range - otherwise an exception is thrown. Typically,
- the range will be determined by sequence container functions <code>begin</code> and <code>end</code>, i.e.:
- </p>
-<pre>
-std::string s = <span class="literal">"example"</span>;
-utf8::iterator i (s.begin(), s.begin(), s.end());
-</pre>
- <h3 id="fununchecked">
- Functions From utf8::unchecked Namespace
- </h3>
- <h4>
- utf8::unchecked::append
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence
- to a UTF-8 string.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-octet_iterator append(uint32_t cp, octet_iterator result);
-
-</pre>
- <p>
- <code>cp</code>: A 32 bit integer representing a code point to append to the
- sequence.<br>
- <code>result</code>: An output iterator to the place in the sequence where to
- append the code point.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the newly appended sequence.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">unsigned char</span> u[<span class="literal">5</span>] = {<span
-class="literal">0</span>,<span class="literal">0</span>,<span class=
-"literal">0</span>,<span class="literal">0</span>,<span class="literal">0</span>};
-<span class="keyword">unsigned char</span>* end = unchecked::append(<span class=
-"literal">0x0448</span>, u);
-assert (u[<span class="literal">0</span>] == <span class=
-"literal">0xd1</span> &amp;&amp; u[<span class="literal">1</span>] == <span class=
-"literal">0x88</span> &amp;&amp; u[<span class="literal">2</span>] == <span class=
-"literal">0</span> &amp;&amp; u[<span class="literal">3</span>] == <span class=
-"literal">0</span> &amp;&amp; u[<span class="literal">4</span>] == <span class=
-"literal">0</span>);
-</pre>
- <p>
- This is a faster but less safe version of <code>utf8::append</code>. It does not
- check for validity of the supplied code point, and may produce an invalid UTF-8
- sequence.
- </p>
- <h4>
- utf8::unchecked::next
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Given the iterator to the beginning of a UTF-8 sequence, it returns the code point
- and moves the iterator to the next position.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-uint32_t next(octet_iterator&amp; it);
-
-</pre>
- <p>
- <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
- encoded code point. After the function returns, it is incremented to point to the
- beginning of the next code point.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- processed UTF-8 code point.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-<span class="keyword">char</span>* w = twochars;
-<span class="keyword">int</span> cp = unchecked::next(w);
-assert (cp == <span class="literal">0x65e5</span>);
-assert (w == twochars + <span class="literal">3</span>);
-</pre>
- <p>
- This is a faster but less safe version of <code>utf8::next</code>. It does not
- check for validity of the supplied UTF-8 sequence.
- </p>
- <h4>
- utf8::unchecked::peek_next
- </h4>
- <p class="version">
- Available in version 2.1 and later.
- </p>
- <p>
- Given the iterator to the beginning of a UTF-8 sequence, it returns the code point.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-uint32_t peek_next(octet_iterator it);
-
-</pre>
- <p>
- <code>it</code>: an iterator pointing to the beginning of an UTF-8
- encoded code point.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- processed UTF-8 code point.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-<span class="keyword">char</span>* w = twochars;
-<span class="keyword">int</span> cp = unchecked::peek_next(w);
-assert (cp == <span class="literal">0x65e5</span>);
-assert (w == twochars);
-</pre>
- <p>
- This is a faster but less safe version of <code>utf8::peek_next</code>. It does not
- check for validity of the supplied UTF-8 sequence.
- </p>
- <h4>
- utf8::unchecked::prior
- </h4>
- <p class="version">
- Available in version 1.02 and later.
- </p>
- <p>
- Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
- decreases the iterator until it hits the beginning of the previous UTF-8 encoded
- code point and returns the 32 bits representation of the code point.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-uint32_t prior(octet_iterator&amp; it);
-
-</pre>
- <p>
- <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
- After the function returns, it is decremented to point to the beginning of the
- previous code point.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- previous code point.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-<span class="keyword">char</span>* w = twochars + <span class="literal">3</span>;
-<span class="keyword">int</span> cp = unchecked::prior (w);
-assert (cp == <span class="literal">0x65e5</span>);
-assert (w == twochars);
-</pre>
- <p>
- This is a faster but less safe version of <code>utf8::prior</code>. It does not
- check for validity of the supplied UTF-8 sequence and offers no boundary checking.
- </p>
- <h4>
- utf8::unchecked::previous (deprecated, see utf8::unchecked::prior)
- </h4>
- <p class="version">
- Deprecated in version 1.02 and later.
- </p>
- <p>
- Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
- decreases the iterator until it hits the beginning of the previous UTF-8 encoded
- code point and returns the 32 bits representation of the code point.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-uint32_t previous(octet_iterator&amp; it);
-
-</pre>
- <p>
- <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
- After the function returns, it is decremented to point to the beginning of the
- previous code point.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- previous code point.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-<span class="keyword">char</span>* w = twochars + <span class="literal">3</span>;
-<span class="keyword">int</span> cp = unchecked::previous (w);
-assert (cp == <span class="literal">0x65e5</span>);
-assert (w == twochars);
-</pre>
- <p>
- The reason this function is deprecated is just the consistency with the "checked"
- versions, where <code>prior</code> should be used instead of <code>previous</code>.
- In fact, <code>unchecked::previous</code> behaves exactly the same as <code>
- unchecked::prior</code>
- </p>
- <p>
- This is a faster but less safe version of <code>utf8::previous</code>. It does not
- check for validity of the supplied UTF-8 sequence and offers no boundary checking.
- </p>
- <h4>
- utf8::unchecked::advance
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Advances an iterator by the specified number of code points within an UTF-8
- sequence.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator, typename distance_type&gt;
-<span class="keyword">void</span> advance (octet_iterator&amp; it, distance_type n);
-
-</pre>
- <p>
- <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
- encoded code point. After the function returns, it is incremented to point to the
- nth following code point.<br>
- <code>n</code>: a positive integer that shows how many code points we want to
- advance.<br>
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-<span class="keyword">char</span>* w = twochars;
-unchecked::advance (w, <span class="literal">2</span>);
-assert (w == twochars + <span class="literal">5</span>);
-</pre>
- <p>
- This function works only "forward". In case of a negative <code>n</code>, there is
- no effect.
- </p>
- <p>
- This is a faster but less safe version of <code>utf8::advance</code>. It does not
- check for validity of the supplied UTF-8 sequence and offers no boundary checking.
- </p>
- <h4>
- utf8::unchecked::distance
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Given the iterators to two UTF-8 encoded code points in a seqence, returns the
- number of code points between them.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator&gt;
-<span class=
-"keyword">typename</span> std::iterator_traits&lt;octet_iterator&gt;::difference_type distance (octet_iterator first, octet_iterator last);
-</pre>
- <p>
- <code>first</code>: an iterator to a beginning of a UTF-8 encoded code point.<br>
- <code>last</code>: an iterator to a "post-end" of the last UTF-8 encoded code
- point in the sequence we are trying to determine the length. It can be the
- beginning of a new code point, or not.<br>
- <span class="return_value">Return value</span> the distance between the iterators,
- in code points.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-size_t dist = utf8::unchecked::distance(twochars, twochars + <span class=
-"literal">5</span>);
-assert (dist == <span class="literal">2</span>);
-</pre>
- <p>
- This is a faster but less safe version of <code>utf8::distance</code>. It does not
- check for validity of the supplied UTF-8 sequence.
- </p>
- <h4>
- utf8::unchecked::utf16to8
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-16 encoded string to UTF-8.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> u16bit_iterator, <span class=
-"keyword">typename</span> octet_iterator&gt;
-octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
-
-</pre>
- <p>
- <code>start</code>: an iterator pointing to the beginning of the UTF-16 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-16 encoded
- string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-8 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-8 string.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">unsigned short</span> utf16string[] = {<span class=
-"literal">0x41</span>, <span class="literal">0x0448</span>, <span class=
-"literal">0x65e5</span>, <span class="literal">0xd834</span>, <span class=
-"literal">0xdd1e</span>};
-vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
-unchecked::utf16to8(utf16string, utf16string + <span class=
-"literal">5</span>, back_inserter(utf8result));
-assert (utf8result.size() == <span class="literal">10</span>);
-</pre>
- <p>
- This is a faster but less safe version of <code>utf8::utf16to8</code>. It does not
- check for validity of the supplied UTF-16 sequence.
- </p>
- <h4>
- utf8::unchecked::utf8to16
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts an UTF-8 encoded string to UTF-16
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> u16bit_iterator, typename octet_iterator&gt;
-u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
-
-</pre>
- <p>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
- string to convert. &lt; br /&gt; <code>end</code>: an iterator pointing to
- pass-the-end of the UTF-8 encoded string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-16 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-16 string.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span> utf8_with_surrogates[] = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e"</span>;
-vector &lt;<span class="keyword">unsigned short</span>&gt; utf16result;
-unchecked::utf8to16(utf8_with_surrogates, utf8_with_surrogates + <span class=
-"literal">9</span>, back_inserter(utf16result));
-assert (utf16result.size() == <span class="literal">4</span>);
-assert (utf16result[<span class="literal">2</span>] == <span class=
-"literal">0xd834</span>);
-assert (utf16result[<span class="literal">3</span>] == <span class=
-"literal">0xdd1e</span>);
-</pre>
- <p>
- This is a faster but less safe version of <code>utf8::utf8to16</code>. It does not
- check for validity of the supplied UTF-8 sequence.
- </p>
- <h4>
- utf8::unchecked::utf32to8
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-32 encoded string to UTF-8.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator, <span class=
-"keyword">typename</span> u32bit_iterator&gt;
-octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
-
-</pre>
- <p>
- <code>start</code>: an iterator pointing to the beginning of the UTF-32 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-32 encoded
- string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-8 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-8 string.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">int</span> utf32string[] = {<span class=
-"literal">0x448</span>, <span class="literal">0x65e5</span>, <span class=
-"literal">0x10346</span>, <span class="literal">0</span>};
-vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
-utf32to8(utf32string, utf32string + <span class=
-"literal">3</span>, back_inserter(utf8result));
-assert (utf8result.size() == <span class="literal">9</span>);
-</pre>
- <p>
- This is a faster but less safe version of <code>utf8::utf32to8</code>. It does not
- check for validity of the supplied UTF-32 sequence.
- </p>
- <h4>
- utf8::unchecked::utf8to32
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-8 encoded string to UTF-32.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class=
-"keyword">typename</span> octet_iterator, typename u32bit_iterator&gt;
-u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
-
-</pre>
- <p>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 encoded string
- to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-32 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-32 string.
- </p>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* twochars = <span class=
-"literal">"\xe6\x97\xa5\xd1\x88"</span>;
-vector&lt;<span class="keyword">int</span>&gt; utf32result;
-unchecked::utf8to32(twochars, twochars + <span class=
-"literal">5</span>, back_inserter(utf32result));
-assert (utf32result.size() == <span class="literal">2</span>);
-</pre>
- <p>
- This is a faster but less safe version of <code>utf8::utf8to32</code>. It does not
- check for validity of the supplied UTF-8 sequence.
- </p>
- <h3 id="typesunchecked">
- Types From utf8::unchecked Namespace
- </h3>
- <h4>
- utf8::iterator
- </h4>
- <p class="version">
- Available in version 2.0 and later.
- </p>
- <p>
- Adapts the underlying octet iterator to iterate over the sequence of code points,
- rather than raw octets.
- </p>
-<pre>
-<span class="keyword">template</span> &lt;<span class="keyword">typename</span> octet_iterator&gt;
-<span class="keyword">class</span> iterator;
-</pre>
-
- <h5>Member functions</h5>
- <dl>
- <dt><code>iterator();</code> <dd> the deafult constructor; the underlying <code>octet_iterator</code> is
- constructed with its default constructor.
- <dt><code><span class="keyword">explicit</span> iterator (const octet_iterator&amp; octet_it);
- </code> <dd> a constructor
- that initializes the underlying <code>octet_iterator</code> with <code>octet_it</code>
- <dt><code>octet_iterator base () <span class="keyword">const</span>;</code> <dd> returns the
- underlying <code>octet_iterator</code>.
- <dt><code>uint32_t operator * () <span class="keyword">const</span>;</code> <dd> decodes the utf-8 sequence
- the underlying <code>octet_iterator</code> is pointing to and returns the code point.
- <dt><code><span class="keyword">bool operator</span> == (const iterator&amp; rhs)
- <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
- if the two underlaying iterators are equal.
- <dt><code><span class="keyword">bool operator</span> != (const iterator&amp; rhs)
- <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
- if the two underlaying iterators are not equal.
- <dt><code>iterator&amp; <span class="keyword">operator</span> ++ (); </code> <dd> the prefix increment - moves
- the iterator to the next UTF-8 encoded code point.
- <dt><code>iterator <span class="keyword">operator</span> ++ (<span class="keyword">int</span>); </code> <dd>
- the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
- <dt><code>iterator&amp; <span class="keyword">operator</span> -- (); </code> <dd> the prefix decrement - moves
- the iterator to the previous UTF-8 encoded code point.
- <dt><code>iterator <span class="keyword">operator</span> -- (<span class="keyword">int</span>); </code> <dd>
- the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
- </dl>
- <p>
- Example of use:
- </p>
-<pre>
-<span class="keyword">char</span>* threechars = <span class="literal">"\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"</span>;
-utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_it(threechars);
-utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_it2 = un_it;
-assert (un_it2 == un_it);
-assert (*un_it == <span class="literal">0x10346</span>);
-assert (*(++un_it) == <span class="literal">0x65e5</span>);
-assert ((*un_it++) == <span class="literal">0x65e5</span>);
-assert (*un_it == <span class="literal">0x0448</span>);
-assert (un_it != un_it2);
-utf8::::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_endit (threechars + <span class="literal">9</span>);
-assert (++un_it == un_endit);
-assert (*(--un_it) == <span class="literal">0x0448</span>);
-assert ((*un_it--) == <span class="literal">0x0448</span>);
-assert (*un_it == <span class="literal">0x65e5</span>);
-assert (--un_it == utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt;(threechars));
-assert (*un_it == <span class="literal">0x10346</span>);
-</pre>
- <p>
- This is an unchecked version of <code>utf8::iterator</code>. It is faster in many cases, but offers
- no validity or range checks.
- </p>
- <h2 id="points">
- Points of interest
- </h2>
- <h4>
- Design goals and decisions
- </h4>
- <p>
- The library was designed to be:
- </p>
- <ol>
- <li>
- Generic: for better or worse, there are many C++ string classes out there, and
- the library should work with as many of them as possible.
- </li>
- <li>
- Portable: the library should be portable both accross different platforms and
- compilers. The only non-portable code is a small section that declares unsigned
- integers of different sizes: three typedefs. They can be changed by the users of
- the library if they don't match their platform. The default setting should work
- for Windows (both 32 and 64 bit), and most 32 bit and 64 bit Unix derivatives.
- </li>
- <li>
- Lightweight: follow the "pay only for what you use" guideline.
- </li>
- <li>
- Unintrusive: avoid forcing any particular design or even programming style on the
- user. This is a library, not a framework.
- </li>
- </ol>
- <h4>
- Alternatives
- </h4>
- <p>
- In case you want to look into other means of working with UTF-8 strings from C++,
- here is the list of solutions I am aware of:
- </p>
- <ol>
- <li>
- <a href="http://icu.sourceforge.net/">ICU Library</a>. It is very powerful,
- complete, feature-rich, mature, and widely used. Also big, intrusive,
- non-generic, and doesn't play well with the Standard Library. I definitelly
- recommend looking at ICU even if you don't plan to use it.
- </li>
- <li>
- C++11 language and library features. Still far from complete, and not widely
- supported by compiler vendors.
- </li>
- <li>
- <a href=
- "http://www.gtkmm.org/gtkmm2/docs/tutorial/html/ch03s04.html">Glib::ustring</a>.
- A class specifically made to work with UTF-8 strings, and also feel like
- <code>std::string</code>. If you prefer to have yet another string class in your
- code, it may be worth a look. Be aware of the licensing issues, though.
- </li>
- <li>
- Platform dependent solutions: Windows and POSIX have functions to convert strings
- from one encoding to another. That is only a subset of what my library offers,
- but if that is all you need it may be good enough.
- </li>
- </ol>
- <h2 id="links">
- Links
- </h2>
- <ol>
- <li>
- <a href="http://www.unicode.org/">The Unicode Consortium</a>.
- </li>
- <li>
- <a href="http://icu.sourceforge.net/">ICU Library</a>.
- </li>
- <li>
- <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8 at Wikipedia</a>
- </li>
- <li>
- <a href="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and Unicode FAQ for
- Unix/Linux</a>
- </li>
- </ol>
- </body>
-</html>
diff --git a/thirdparty/assimp/assimp/config.h b/thirdparty/assimp/include/assimp/config.h
index d0e4817349..48d61941ad 100644
--- a/thirdparty/assimp/assimp/config.h
+++ b/thirdparty/assimp/include/assimp/config.h
@@ -60,6 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_CONFIG_H_INC
#define AI_CONFIG_H_INC
+
// ###########################################################################
// LIBRARY SETTINGS
// General, global settings
@@ -75,8 +76,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Property type: bool. Default value: false.
*/
-#define AI_CONFIG_GLOB_MEASURE_TIME \
- "GLOB_MEASURE_TIME"
+#define AI_CONFIG_GLOB_MEASURE_TIME \
+ "GLOB_MEASURE_TIME"
+
// ---------------------------------------------------------------------------
/** @brief Global setting to disable generation of skeleton dummy meshes
@@ -87,9 +89,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// ---------------------------------------------------------------------------
#define AI_CONFIG_IMPORT_NO_SKELETON_MESHES \
- "IMPORT_NO_SKELETON_MESHES"
+ "IMPORT_NO_SKELETON_MESHES"
+
-#if 0 // not implemented yet
+
+# if 0 // not implemented yet
// ---------------------------------------------------------------------------
/** @brief Set Assimp's multithreading policy.
*
@@ -105,8 +109,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* For more information, see the @link threading Threading page@endlink.
* Property type: int, default value: -1.
*/
-#define AI_CONFIG_GLOB_MULTITHREADING \
- "GLOB_MULTITHREADING"
+#define AI_CONFIG_GLOB_MULTITHREADING \
+ "GLOB_MULTITHREADING"
#endif
// ###########################################################################
@@ -114,6 +118,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Various stuff to fine-tune the behavior of a specific post processing step.
// ###########################################################################
+
// ---------------------------------------------------------------------------
/** @brief Maximum bone count per mesh for the SplitbyBoneCount step.
*
@@ -124,13 +129,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// ---------------------------------------------------------------------------
#define AI_CONFIG_PP_SBBC_MAX_BONES \
- "PP_SBBC_MAX_BONES"
+ "PP_SBBC_MAX_BONES"
+
// default limit for bone count
#if (!defined AI_SBBC_DEFAULT_MAX_BONES)
-#define AI_SBBC_DEFAULT_MAX_BONES 60
+# define AI_SBBC_DEFAULT_MAX_BONES 60
#endif
+
// ---------------------------------------------------------------------------
/** @brief Specifies the maximum angle that may be between two vertex tangents
* that their tangents and bi-tangents are smoothed.
@@ -140,7 +147,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Property type: float. Default value: 45 degrees
*/
#define AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE \
- "PP_CT_MAX_SMOOTHING_ANGLE"
+ "PP_CT_MAX_SMOOTHING_ANGLE"
// ---------------------------------------------------------------------------
/** @brief Source UV channel for tangent space computation.
@@ -150,7 +157,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// ---------------------------------------------------------------------------
#define AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX \
- "PP_CT_TEXTURE_CHANNEL_INDEX"
+ "PP_CT_TEXTURE_CHANNEL_INDEX"
// ---------------------------------------------------------------------------
/** @brief Specifies the maximum angle that may be between two face normals
@@ -165,7 +172,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* the output quality may be reduced.
*/
#define AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE \
- "PP_GSN_MAX_SMOOTHING_ANGLE"
+ "PP_GSN_MAX_SMOOTHING_ANGLE"
+
// ---------------------------------------------------------------------------
/** @brief Sets the colormap (= palette) to be used to decode embedded
@@ -177,8 +185,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* a default palette (from Quake 1) is used.
* Property type: string.
*/
-#define AI_CONFIG_IMPORT_MDL_COLORMAP \
- "IMPORT_MDL_COLORMAP"
+#define AI_CONFIG_IMPORT_MDL_COLORMAP \
+ "IMPORT_MDL_COLORMAP"
// ---------------------------------------------------------------------------
/** @brief Configures the #aiProcess_RemoveRedundantMaterials step to
@@ -199,8 +207,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @note Linefeeds, tabs or carriage returns are treated as whitespace.
* Material names are case sensitive.
*/
-#define AI_CONFIG_PP_RRM_EXCLUDE_LIST \
- "PP_RRM_EXCLUDE_LIST"
+#define AI_CONFIG_PP_RRM_EXCLUDE_LIST \
+ "PP_RRM_EXCLUDE_LIST"
// ---------------------------------------------------------------------------
/** @brief Configures the #aiProcess_PreTransformVertices step to
@@ -214,8 +222,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* any transformations.
* Property type: bool. Default value: false.
*/
-#define AI_CONFIG_PP_PTV_KEEP_HIERARCHY \
- "PP_PTV_KEEP_HIERARCHY"
+#define AI_CONFIG_PP_PTV_KEEP_HIERARCHY \
+ "PP_PTV_KEEP_HIERARCHY"
// ---------------------------------------------------------------------------
/** @brief Configures the #aiProcess_PreTransformVertices step to normalize
@@ -224,8 +232,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* meshes are scaled appropriately (uniformly of course!).
* This might be useful if you don't know the spatial dimension of the input
* data*/
-#define AI_CONFIG_PP_PTV_NORMALIZE \
- "PP_PTV_NORMALIZE"
+#define AI_CONFIG_PP_PTV_NORMALIZE \
+ "PP_PTV_NORMALIZE"
// ---------------------------------------------------------------------------
/** @brief Configures the #aiProcess_PreTransformVertices step to use
@@ -233,8 +241,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* transforming vertices.
* Property type: bool. Default value: false.
*/
-#define AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION \
- "PP_PTV_ADD_ROOT_TRANSFORMATION"
+#define AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION \
+ "PP_PTV_ADD_ROOT_TRANSFORMATION"
// ---------------------------------------------------------------------------
/** @brief Configures the #aiProcess_PreTransformVertices step to use
@@ -243,8 +251,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* of the transformation matrix.
* Property type: aiMatrix4x4.
*/
-#define AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION \
- "PP_PTV_ROOT_TRANSFORMATION"
+#define AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION \
+ "PP_PTV_ROOT_TRANSFORMATION"
// ---------------------------------------------------------------------------
/** @brief Configures the #aiProcess_FindDegenerates step to
@@ -257,7 +265,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Property type: bool. Default value: false.
*/
#define AI_CONFIG_PP_FD_REMOVE \
- "PP_FD_REMOVE"
+ "PP_FD_REMOVE"
// ---------------------------------------------------------------------------
/**
@@ -266,7 +274,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* be removed if #AI_CONFIG_PP_FD_REMOVE is set to true.
*/
#define AI_CONFIG_PP_FD_CHECKAREA \
- "PP_FD_CHECKAREA"
+ "PP_FD_CHECKAREA"
// ---------------------------------------------------------------------------
/** @brief Configures the #aiProcess_OptimizeGraph step to preserve nodes
@@ -286,8 +294,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @note Linefeeds, tabs or carriage returns are treated as whitespace.
* Node names are case sensitive.
*/
-#define AI_CONFIG_PP_OG_EXCLUDE_LIST \
- "PP_OG_EXCLUDE_LIST"
+#define AI_CONFIG_PP_OG_EXCLUDE_LIST \
+ "PP_OG_EXCLUDE_LIST"
// ---------------------------------------------------------------------------
/** @brief Set the maximum number of triangles in a mesh.
@@ -298,11 +306,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Property type: integer.
*/
#define AI_CONFIG_PP_SLM_TRIANGLE_LIMIT \
- "PP_SLM_TRIANGLE_LIMIT"
+ "PP_SLM_TRIANGLE_LIMIT"
// default value for AI_CONFIG_PP_SLM_TRIANGLE_LIMIT
#if (!defined AI_SLM_DEFAULT_MAX_TRIANGLES)
-#define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
+# define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
#endif
// ---------------------------------------------------------------------------
@@ -314,11 +322,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Property type: integer.
*/
#define AI_CONFIG_PP_SLM_VERTEX_LIMIT \
- "PP_SLM_VERTEX_LIMIT"
+ "PP_SLM_VERTEX_LIMIT"
// default value for AI_CONFIG_PP_SLM_VERTEX_LIMIT
#if (!defined AI_SLM_DEFAULT_MAX_VERTICES)
-#define AI_SLM_DEFAULT_MAX_VERTICES 1000000
+# define AI_SLM_DEFAULT_MAX_VERTICES 1000000
#endif
// ---------------------------------------------------------------------------
@@ -327,12 +335,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This is used by the #aiProcess_LimitBoneWeights PostProcess-Step.
* @note The default value is AI_LMW_MAX_WEIGHTS
* Property type: integer.*/
-#define AI_CONFIG_PP_LBW_MAX_WEIGHTS \
- "PP_LBW_MAX_WEIGHTS"
+#define AI_CONFIG_PP_LBW_MAX_WEIGHTS \
+ "PP_LBW_MAX_WEIGHTS"
// default value for AI_CONFIG_PP_LBW_MAX_WEIGHTS
#if (!defined AI_LMW_MAX_WEIGHTS)
-#define AI_LMW_MAX_WEIGHTS 0x4
+# define AI_LMW_MAX_WEIGHTS 0x4
#endif // !! AI_LMW_MAX_WEIGHTS
// ---------------------------------------------------------------------------
@@ -342,11 +350,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @note The default value is AI_DEBONE_THRESHOLD
* Property type: float.*/
#define AI_CONFIG_PP_DB_THRESHOLD \
- "PP_DB_THRESHOLD"
+ "PP_DB_THRESHOLD"
// default value for AI_CONFIG_PP_LBW_MAX_WEIGHTS
#if (!defined AI_DEBONE_THRESHOLD)
-#define AI_DEBONE_THRESHOLD 1.0f
+# define AI_DEBONE_THRESHOLD 1.0f
#endif // !! AI_DEBONE_THRESHOLD
// ---------------------------------------------------------------------------
@@ -356,12 +364,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @note The default value is 0
* Property type: bool.*/
#define AI_CONFIG_PP_DB_ALL_OR_NONE \
- "PP_DB_ALL_OR_NONE"
+ "PP_DB_ALL_OR_NONE"
/** @brief Default value for the #AI_CONFIG_PP_ICL_PTCACHE_SIZE property
*/
#ifndef PP_ICL_PTCACHE_SIZE
-#define PP_ICL_PTCACHE_SIZE 12
+# define PP_ICL_PTCACHE_SIZE 12
#endif
// ---------------------------------------------------------------------------
@@ -375,7 +383,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* performance improvements for most nVidia/AMD cards since 2002.
* Property type: integer.
*/
-#define AI_CONFIG_PP_ICL_PTCACHE_SIZE "PP_ICL_PTCACHE_SIZE"
+#define AI_CONFIG_PP_ICL_PTCACHE_SIZE "PP_ICL_PTCACHE_SIZE"
// ---------------------------------------------------------------------------
/** @brief Enumerates components of the aiScene and aiMesh data structures
@@ -383,71 +391,73 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* See the documentation to #aiProcess_RemoveComponent for more details.
*/
-enum aiComponent {
-/** Normal vectors */
+enum aiComponent
+{
+ /** Normal vectors */
#ifdef SWIG
aiComponent_NORMALS = 0x2,
#else
- aiComponent_NORMALS = 0x2u,
+ aiComponent_NORMALS = 0x2u,
#endif
-/** Tangents and bitangents go always together ... */
+ /** Tangents and bitangents go always together ... */
#ifdef SWIG
aiComponent_TANGENTS_AND_BITANGENTS = 0x4,
#else
- aiComponent_TANGENTS_AND_BITANGENTS = 0x4u,
+ aiComponent_TANGENTS_AND_BITANGENTS = 0x4u,
#endif
- /** ALL color sets
+ /** ALL color sets
* Use aiComponent_COLORn(N) to specify the N'th set */
- aiComponent_COLORS = 0x8,
+ aiComponent_COLORS = 0x8,
- /** ALL texture UV sets
+ /** ALL texture UV sets
* aiComponent_TEXCOORDn(N) to specify the N'th set */
- aiComponent_TEXCOORDS = 0x10,
+ aiComponent_TEXCOORDS = 0x10,
- /** Removes all bone weights from all meshes.
+ /** Removes all bone weights from all meshes.
* The scenegraph nodes corresponding to the bones are NOT removed.
* use the #aiProcess_OptimizeGraph step to do this */
- aiComponent_BONEWEIGHTS = 0x20,
+ aiComponent_BONEWEIGHTS = 0x20,
- /** Removes all node animations (aiScene::mAnimations).
+ /** Removes all node animations (aiScene::mAnimations).
* The corresponding scenegraph nodes are NOT removed.
* use the #aiProcess_OptimizeGraph step to do this */
- aiComponent_ANIMATIONS = 0x40,
+ aiComponent_ANIMATIONS = 0x40,
- /** Removes all embedded textures (aiScene::mTextures) */
- aiComponent_TEXTURES = 0x80,
+ /** Removes all embedded textures (aiScene::mTextures) */
+ aiComponent_TEXTURES = 0x80,
- /** Removes all light sources (aiScene::mLights).
+ /** Removes all light sources (aiScene::mLights).
* The corresponding scenegraph nodes are NOT removed.
* use the #aiProcess_OptimizeGraph step to do this */
- aiComponent_LIGHTS = 0x100,
+ aiComponent_LIGHTS = 0x100,
- /** Removes all cameras (aiScene::mCameras).
+ /** Removes all cameras (aiScene::mCameras).
* The corresponding scenegraph nodes are NOT removed.
* use the #aiProcess_OptimizeGraph step to do this */
- aiComponent_CAMERAS = 0x200,
+ aiComponent_CAMERAS = 0x200,
- /** Removes all meshes (aiScene::mMeshes). */
- aiComponent_MESHES = 0x400,
+ /** Removes all meshes (aiScene::mMeshes). */
+ aiComponent_MESHES = 0x400,
- /** Removes all materials. One default material will
+ /** Removes all materials. One default material will
* be generated, so aiScene::mNumMaterials will be 1. */
- aiComponent_MATERIALS = 0x800,
+ aiComponent_MATERIALS = 0x800,
+
-/** This value is not used. It is just there to force the
+ /** This value is not used. It is just there to force the
* compiler to map this enum to a 32 Bit integer. */
#ifndef SWIG
- _aiComponent_Force32Bit = 0x9fffffff
+ _aiComponent_Force32Bit = 0x9fffffff
#endif
};
// Remove a specific color channel 'n'
-#define aiComponent_COLORSn(n) (1u << (n + 20u))
+#define aiComponent_COLORSn(n) (1u << (n+20u))
// Remove a specific UV channel 'n'
-#define aiComponent_TEXCOORDSn(n) (1u << (n + 25u))
+#define aiComponent_TEXCOORDSn(n) (1u << (n+25u))
// ---------------------------------------------------------------------------
/** @brief Input parameter to the #aiProcess_RemoveComponent step:
@@ -461,8 +471,8 @@ enum aiComponent {
* of the flags defined above) the import FAILS. Mainly because there is
* no data to work on anymore ...
*/
-#define AI_CONFIG_PP_RVC_FLAGS \
- "PP_RVC_FLAGS"
+#define AI_CONFIG_PP_RVC_FLAGS \
+ "PP_RVC_FLAGS"
// ---------------------------------------------------------------------------
/** @brief Input parameter to the #aiProcess_SortByPType step:
@@ -473,8 +483,8 @@ enum aiComponent {
* be to exclude all line and point meshes from the import. This
* is an integer property, its default value is 0.
*/
-#define AI_CONFIG_PP_SBP_REMOVE \
- "PP_SBP_REMOVE"
+#define AI_CONFIG_PP_SBP_REMOVE \
+ "PP_SBP_REMOVE"
// ---------------------------------------------------------------------------
/** @brief Input parameter to the #aiProcess_FindInvalidData step:
@@ -485,8 +495,16 @@ enum aiComponent {
* abs(n0-n1)>epsilon holds true for all vector respectively quaternion
* components. The default value is 0.f - comparisons are exact then.
*/
-#define AI_CONFIG_PP_FID_ANIM_ACCURACY \
- "PP_FID_ANIM_ACCURACY"
+#define AI_CONFIG_PP_FID_ANIM_ACCURACY \
+ "PP_FID_ANIM_ACCURACY"
+
+// ---------------------------------------------------------------------------
+/** @brief Input parameter to the #aiProcess_FindInvalidData step:
+ * Set to true to ignore texture coordinates. This may be useful if you have
+ * to assign different kind of textures like one for the summer or one for the winter.
+ */
+#define AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS \
+ "PP_FID_IGNORE_TEXTURECOORDS"
// TransformUVCoords evaluates UV scalings
#define AI_UVTRAFO_SCALING 0x1
@@ -501,14 +519,6 @@ enum aiComponent {
#define AI_UVTRAFO_ALL (AI_UVTRAFO_SCALING | AI_UVTRAFO_ROTATION | AI_UVTRAFO_TRANSLATION)
// ---------------------------------------------------------------------------
-/** @brief Input parameter to the #aiProcess_FindInvalidData step:
- * Set to true to ignore texture coordinates. This may be useful if you have
- * to assign different kind of textures like one for the summer or one for the winter.
- */
-#define AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS \
- "PP_FID_IGNORE_TEXTURECOORDS"
-
-// ---------------------------------------------------------------------------
/** @brief Input parameter to the #aiProcess_TransformUVCoords step:
* Specifies which UV transformations are evaluated.
*
@@ -516,8 +526,8 @@ enum aiComponent {
* property, of course). By default all transformations are enabled
* (AI_UVTRAFO_ALL).
*/
-#define AI_CONFIG_PP_TUV_EVALUATE \
- "PP_TUV_EVALUATE"
+#define AI_CONFIG_PP_TUV_EVALUATE \
+ "PP_TUV_EVALUATE"
// ---------------------------------------------------------------------------
/** @brief A hint to assimp to favour speed against import quality.
@@ -528,14 +538,16 @@ enum aiComponent {
* This property is expected to be an integer, != 0 stands for true.
* The default value is 0.
*/
-#define AI_CONFIG_FAVOUR_SPEED \
- "FAVOUR_SPEED"
+#define AI_CONFIG_FAVOUR_SPEED \
+ "FAVOUR_SPEED"
+
// ###########################################################################
// IMPORTER SETTINGS
// Various stuff to fine-tune the behaviour of specific importer plugins.
// ###########################################################################
+
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will merge all geometry layers present
* in the source file or take only the first.
@@ -544,7 +556,7 @@ enum aiComponent {
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS \
- "IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS"
+ "IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read all materials present in the
@@ -556,7 +568,7 @@ enum aiComponent {
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS \
- "IMPORT_FBX_READ_ALL_MATERIALS"
+ "IMPORT_FBX_READ_ALL_MATERIALS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read materials.
@@ -565,7 +577,7 @@ enum aiComponent {
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_MATERIALS \
- "IMPORT_FBX_READ_MATERIALS"
+ "IMPORT_FBX_READ_MATERIALS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read embedded textures.
@@ -574,7 +586,7 @@ enum aiComponent {
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_TEXTURES \
- "IMPORT_FBX_READ_TEXTURES"
+ "IMPORT_FBX_READ_TEXTURES"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read cameras.
@@ -583,7 +595,7 @@ enum aiComponent {
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_CAMERAS \
- "IMPORT_FBX_READ_CAMERAS"
+ "IMPORT_FBX_READ_CAMERAS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read light sources.
@@ -592,7 +604,7 @@ enum aiComponent {
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_LIGHTS \
- "IMPORT_FBX_READ_LIGHTS"
+ "IMPORT_FBX_READ_LIGHTS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will read animations.
@@ -601,7 +613,7 @@ enum aiComponent {
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS \
- "IMPORT_FBX_READ_ANIMATIONS"
+ "IMPORT_FBX_READ_ANIMATIONS"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will act in strict mode in which only
@@ -613,7 +625,7 @@ enum aiComponent {
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_STRICT_MODE \
- "IMPORT_FBX_STRICT_MODE"
+ "IMPORT_FBX_STRICT_MODE"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will preserve pivot points for
@@ -624,7 +636,7 @@ enum aiComponent {
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS \
- "IMPORT_FBX_PRESERVE_PIVOTS"
+ "IMPORT_FBX_PRESERVE_PIVOTS"
// ---------------------------------------------------------------------------
/** @brief Specifies whether the importer will drop empty animation curves or
@@ -635,26 +647,26 @@ enum aiComponent {
* Property type: bool
*/
#define AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES \
- "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES"
+ "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES"
// ---------------------------------------------------------------------------
/** @brief Set whether the fbx importer will use the legacy embedded texture naming.
-*
-* The default value is false (0)
-* Property type: bool
-*/
+ *
+ * The default value is false (0)
+ * Property type: bool
+ */
#define AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING \
"AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
// ---------------------------------------------------------------------------
-/** @brief Set wether the FBX importer shall not remove empty bones.
- *
+/** @brief Set wether the importer shall not remove empty bones.
*
* Empty bone are often used to define connections for other models.
*/
#define AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES \
"AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES"
+
// ---------------------------------------------------------------------------
/** @brief Set wether the FBX importer shall convert the unit from cm to m.
*/
@@ -674,14 +686,14 @@ enum aiComponent {
* want to override the global setting).
* Property type: integer.
*/
-#define AI_CONFIG_IMPORT_GLOBAL_KEYFRAME "IMPORT_GLOBAL_KEYFRAME"
+#define AI_CONFIG_IMPORT_GLOBAL_KEYFRAME "IMPORT_GLOBAL_KEYFRAME"
-#define AI_CONFIG_IMPORT_MD3_KEYFRAME "IMPORT_MD3_KEYFRAME"
-#define AI_CONFIG_IMPORT_MD2_KEYFRAME "IMPORT_MD2_KEYFRAME"
-#define AI_CONFIG_IMPORT_MDL_KEYFRAME "IMPORT_MDL_KEYFRAME"
-#define AI_CONFIG_IMPORT_MDC_KEYFRAME "IMPORT_MDC_KEYFRAME"
-#define AI_CONFIG_IMPORT_SMD_KEYFRAME "IMPORT_SMD_KEYFRAME"
-#define AI_CONFIG_IMPORT_UNREAL_KEYFRAME "IMPORT_UNREAL_KEYFRAME"
+#define AI_CONFIG_IMPORT_MD3_KEYFRAME "IMPORT_MD3_KEYFRAME"
+#define AI_CONFIG_IMPORT_MD2_KEYFRAME "IMPORT_MD2_KEYFRAME"
+#define AI_CONFIG_IMPORT_MDL_KEYFRAME "IMPORT_MDL_KEYFRAME"
+#define AI_CONFIG_IMPORT_MDC_KEYFRAME "IMPORT_MDC_KEYFRAME"
+#define AI_CONFIG_IMPORT_SMD_KEYFRAME "IMPORT_SMD_KEYFRAME"
+#define AI_CONFIG_IMPORT_UNREAL_KEYFRAME "IMPORT_UNREAL_KEYFRAME"
// ---------------------------------------------------------------------------
/** Smd load multiple animations
@@ -697,7 +709,7 @@ enum aiComponent {
* Property type: bool. Default value: true.
*/
#define AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL \
- "IMPORT_AC_SEPARATE_BFCULL"
+ "IMPORT_AC_SEPARATE_BFCULL"
// ---------------------------------------------------------------------------
/** @brief Configures whether the AC loader evaluates subdivision surfaces (
@@ -707,8 +719,8 @@ enum aiComponent {
*
* * Property type: bool. Default value: true.
*/
-#define AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION \
- "IMPORT_AC_EVAL_SUBDIVISION"
+#define AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION \
+ "IMPORT_AC_EVAL_SUBDIVISION"
// ---------------------------------------------------------------------------
/** @brief Configures the UNREAL 3D loader to separate faces with different
@@ -717,7 +729,7 @@ enum aiComponent {
* * Property type: bool. Default value: true.
*/
#define AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS \
- "UNREAL_HANDLE_FLAGS"
+ "UNREAL_HANDLE_FLAGS"
// ---------------------------------------------------------------------------
/** @brief Configures the terragen import plugin to compute uv's for
@@ -730,7 +742,7 @@ enum aiComponent {
* * Property type: bool. Default value: false.
*/
#define AI_CONFIG_IMPORT_TER_MAKE_UVS \
- "IMPORT_TER_MAKE_UVS"
+ "IMPORT_TER_MAKE_UVS"
// ---------------------------------------------------------------------------
/** @brief Configures the ASE loader to always reconstruct normal vectors
@@ -739,8 +751,8 @@ enum aiComponent {
* Some ASE files have carry invalid normals, other don't.
* * Property type: bool. Default value: true.
*/
-#define AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS \
- "IMPORT_ASE_RECONSTRUCT_NORMALS"
+#define AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS \
+ "IMPORT_ASE_RECONSTRUCT_NORMALS"
// ---------------------------------------------------------------------------
/** @brief Configures the M3D loader to detect and process multi-part
@@ -752,7 +764,7 @@ enum aiComponent {
* Property type: bool. Default value: true.
*/
#define AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART \
- "IMPORT_MD3_HANDLE_MULTIPART"
+ "IMPORT_MD3_HANDLE_MULTIPART"
// ---------------------------------------------------------------------------
/** @brief Tells the MD3 loader which skin files to load.
@@ -764,7 +776,7 @@ enum aiComponent {
* Property type: String. Default value: "default".
*/
#define AI_CONFIG_IMPORT_MD3_SKIN_NAME \
- "IMPORT_MD3_SKIN_NAME"
+ "IMPORT_MD3_SKIN_NAME"
// ---------------------------------------------------------------------------
/** @brief Specify the Quake 3 shader file to be used for a particular
@@ -782,7 +794,7 @@ enum aiComponent {
* Property type: String. Default value: n/a.
*/
#define AI_CONFIG_IMPORT_MD3_SHADER_SRC \
- "IMPORT_MD3_SHADER_SRC"
+ "IMPORT_MD3_SHADER_SRC"
// ---------------------------------------------------------------------------
/** @brief Configures the LWO loader to load just one layer from the model.
@@ -795,8 +807,8 @@ enum aiComponent {
* layer name may not be empty.<br>
* Property type: Integer. Default value: all layers are loaded.
*/
-#define AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY \
- "IMPORT_LWO_ONE_LAYER_ONLY"
+#define AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY \
+ "IMPORT_LWO_ONE_LAYER_ONLY"
// ---------------------------------------------------------------------------
/** @brief Configures the MD5 loader to not load the MD5ANIM file for
@@ -809,8 +821,8 @@ enum aiComponent {
*
* * Property type: bool. Default value: false.
*/
-#define AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD \
- "IMPORT_MD5_NO_ANIM_AUTOLOAD"
+#define AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD \
+ "IMPORT_MD5_NO_ANIM_AUTOLOAD"
// ---------------------------------------------------------------------------
/** @brief Defines the begin of the time range for which the LWS loader
@@ -828,10 +840,10 @@ enum aiComponent {
*
* @see AI_CONFIG_IMPORT_LWS_ANIM_END - end of the imported time range
*/
-#define AI_CONFIG_IMPORT_LWS_ANIM_START \
- "IMPORT_LWS_ANIM_START"
-#define AI_CONFIG_IMPORT_LWS_ANIM_END \
- "IMPORT_LWS_ANIM_END"
+#define AI_CONFIG_IMPORT_LWS_ANIM_START \
+ "IMPORT_LWS_ANIM_START"
+#define AI_CONFIG_IMPORT_LWS_ANIM_END \
+ "IMPORT_LWS_ANIM_END"
// ---------------------------------------------------------------------------
/** @brief Defines the output frame rate of the IRR loader.
@@ -841,8 +853,8 @@ enum aiComponent {
* are returned by the converter.<br>
* Property type: integer. Default value: 100
*/
-#define AI_CONFIG_IMPORT_IRR_ANIM_FPS \
- "IMPORT_IRR_ANIM_FPS"
+#define AI_CONFIG_IMPORT_IRR_ANIM_FPS \
+ "IMPORT_IRR_ANIM_FPS"
// ---------------------------------------------------------------------------
/** @brief Ogre Importer will try to find referenced materials from this file.
@@ -855,7 +867,7 @@ enum aiComponent {
* Property type: String. Default value: Scene.material.
*/
#define AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE \
- "IMPORT_OGRE_MATERIAL_FILE"
+ "IMPORT_OGRE_MATERIAL_FILE"
// ---------------------------------------------------------------------------
/** @brief Ogre Importer detect the texture usage from its filename.
@@ -875,15 +887,15 @@ enum aiComponent {
* Property type: Bool. Default value: false.
*/
#define AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME \
- "IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME"
+ "IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME"
-/** @brief Specifies whether the Android JNI asset extraction is supported.
+ /** @brief Specifies whether the Android JNI asset extraction is supported.
*
* Turn on this option if you want to manage assets in native
* Android application without having to keep the internal directory and asset
* manager pointer.
*/
-#define AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT "AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT"
+ #define AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT "AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT"
// ---------------------------------------------------------------------------
/** @brief Specifies whether the IFC loader skips over IfcSpace elements.
@@ -922,7 +934,7 @@ enum aiComponent {
// default value for AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE
#if (!defined AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE)
-#define AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE 10.0f
+# define AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE 10.0f
#endif
// ---------------------------------------------------------------------------
@@ -938,7 +950,7 @@ enum aiComponent {
// default value for AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION
#if (!defined AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION)
-#define AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION 32
+# define AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION 32
#endif
// ---------------------------------------------------------------------------
@@ -969,8 +981,12 @@ enum aiComponent {
#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
-/**
- *
+/** @brief Specifies whether the assimp export shall be able to export point clouds
+ *
+ * When this flag is not defined the render data has to contain valid faces.
+ * Point clouds are only a collection of vertices which have nor spatial organization
+ * by a face and the validation process will remove them. Enabling this feature will
+ * switch off the flag and enable the functionality to export pure point clouds.
*/
#define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS"
@@ -980,7 +996,7 @@ enum aiComponent {
#define AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY "GLOBAL_SCALE_FACTOR"
#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT)
-#define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
+# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
#endif // !! AI_DEBONE_THRESHOLD
#define AI_CONFIG_APP_SCALE_KEY "APP_SCALE_FACTOR"
@@ -997,7 +1013,6 @@ enum aiComponent {
* Property type: Bool. Default value: undefined.
*/
-/* #cmakedefine ASSIMP_DOUBLE_PRECISION 1 */
+/* #undef ASSIMP_DOUBLE_PRECISION */
#endif // !! AI_CONFIG_H_INC
-
diff --git a/thirdparty/assimp/code/revision.h b/thirdparty/assimp/revision.h
index 66eb875303..66eb875303 100644
--- a/thirdparty/assimp/code/revision.h
+++ b/thirdparty/assimp/revision.h
diff --git a/thirdparty/b2d_convexdecomp/b2Glue.h b/thirdparty/b2d_convexdecomp/b2Glue.h
deleted file mode 100644
index 175f75be75..0000000000
--- a/thirdparty/b2d_convexdecomp/b2Glue.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
-* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
-*
-* This software is provided 'as-is', without any express or implied
-* warranty. In no event will the authors be held liable for any damages
-* arising from the use of this software.
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-* 1. The origin of this software must not be misrepresented; you must not
-* claim that you wrote the original software. If you use this software
-* in a product, an acknowledgment in the product documentation would be
-* appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-* misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B2GLUE_H
-#define B2GLUE_H
-
-#include "core/math/vector2.h"
-
-#include <limits.h>
-
-namespace b2ConvexDecomp {
-
-typedef real_t float32;
-typedef int32_t int32;
-
-static inline float32 b2Sqrt(float32 val) { return Math::sqrt(val); }
-#define b2_maxFloat FLT_MAX
-#define b2_epsilon CMP_EPSILON
-#define b2_pi 3.14159265359f
-#define b2_maxPolygonVertices 16
-#define b2Max MAX
-#define b2Min MIN
-#define b2Clamp CLAMP
-#define b2Abs ABS
-/// A small length used as a collision and constraint tolerance. Usually it is
-/// chosen to be numerically significant, but visually insignificant.
-#define b2_linearSlop 0.005f
-
-/// A small angle used as a collision and constraint tolerance. Usually it is
-/// chosen to be numerically significant, but visually insignificant.
-#define b2_angularSlop (2.0f / 180.0f * b2_pi)
-
-/// A 2D column vector.
-struct b2Vec2
-{
- /// Default constructor does nothing (for performance).
- b2Vec2() {}
-
- /// Construct using coordinates.
- b2Vec2(float32 x, float32 y) : x(x), y(y) {}
-
- /// Set this vector to all zeros.
- void SetZero() { x = 0.0f; y = 0.0f; }
-
- /// Set this vector to some specified coordinates.
- void Set(float32 x_, float32 y_) { x = x_; y = y_; }
-
- /// Negate this vector.
- b2Vec2 operator -() const { b2Vec2 v; v.Set(-x, -y); return v; }
-
- /// Read from and indexed element.
- float32 operator () (int32 i) const
- {
- return (&x)[i];
- }
-
- /// Write to an indexed element.
- float32& operator () (int32 i)
- {
- return (&x)[i];
- }
-
- /// Add a vector to this vector.
- void operator += (const b2Vec2& v)
- {
- x += v.x; y += v.y;
- }
-
- /// Subtract a vector from this vector.
- void operator -= (const b2Vec2& v)
- {
- x -= v.x; y -= v.y;
- }
-
- /// Multiply this vector by a scalar.
- void operator *= (float32 a)
- {
- x *= a; y *= a;
- }
-
- /// Get the length of this vector (the norm).
- float32 Length() const
- {
- return b2Sqrt(x * x + y * y);
- }
-
- /// Get the length squared. For performance, use this instead of
- /// b2Vec2::Length (if possible).
- float32 LengthSquared() const
- {
- return x * x + y * y;
- }
-
- bool operator==(const b2Vec2& p_v) const {
- return x==p_v.x && y==p_v.y;
- }
- b2Vec2 operator+(const b2Vec2& p_v) const {
- return b2Vec2(x+p_v.x,y+p_v.y);
- }
- b2Vec2 operator-(const b2Vec2& p_v) const {
- return b2Vec2(x-p_v.x,y-p_v.y);
- }
-
- b2Vec2 operator*(float32 f) const {
- return b2Vec2(f*x,f*y);
- }
-
- /// Convert this vector into a unit vector. Returns the length.
- float32 Normalize()
- {
- float32 length = Length();
- if (length < b2_epsilon)
- {
- return 0.0f;
- }
- float32 invLength = 1.0f / length;
- x *= invLength;
- y *= invLength;
-
- return length;
- }
-
- /*
- /// Does this vector contain finite coordinates?
- bool IsValid() const
- {
- return b2IsValid(x) && b2IsValid(y);
- }
- */
-
- float32 x, y;
-};
-
-inline b2Vec2 operator*(float32 f,const b2Vec2& p_v) {
- return b2Vec2(f*p_v.x,f*p_v.y);
-}
-
-/// Perform the dot product on two vectors.
-inline float32 b2Dot(const b2Vec2& a, const b2Vec2& b)
-{
- return a.x * b.x + a.y * b.y;
-}
-
-/// Perform the cross product on two vectors. In 2D this produces a scalar.
-inline float32 b2Cross(const b2Vec2& a, const b2Vec2& b)
-{
- return a.x * b.y - a.y * b.x;
-}
-
-/// Perform the cross product on a vector and a scalar. In 2D this produces
-/// a vector.
-inline b2Vec2 b2Cross(const b2Vec2& a, float32 s)
-{
- return b2Vec2(s * a.y, -s * a.x);
-}
-
-}
-
-#endif
diff --git a/thirdparty/b2d_convexdecomp/b2Polygon.cpp b/thirdparty/b2d_convexdecomp/b2Polygon.cpp
deleted file mode 100644
index c80204ae21..0000000000
--- a/thirdparty/b2d_convexdecomp/b2Polygon.cpp
+++ /dev/null
@@ -1,1591 +0,0 @@
-/*
- * Copyright (c) 2007 Eric Jordan
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-// This utility works with Box2d version 2.0 (or higher), and not with 1.4.3
-
-#include "b2Triangle.h"
-#include "b2Polygon.h"
-
-#include <math.h>
-#include <limits.h>
-#include <assert.h>
-#define b2Assert assert
-
-namespace b2ConvexDecomp {
-
-
-//If you're using 1.4.3, b2_toiSlop won't exist, so set this equal to 0
-static const float32 toiSlop = 0.0f;
-
-/*
- * Check if the lines a0->a1 and b0->b1 cross.
- * If they do, intersectionPoint will be filled
- * with the point of crossing.
- *
- * Grazing lines should not return true.
- */
-bool intersect(const b2Vec2& a0, const b2Vec2& a1,
- const b2Vec2& b0, const b2Vec2& b1,
- b2Vec2& intersectionPoint) {
-
- if (a0 == b0 || a0 == b1 || a1 == b0 || a1 == b1) return false;
- float x1 = a0.x; float y1 = a0.y;
- float x2 = a1.x; float y2 = a1.y;
- float x3 = b0.x; float y3 = b0.y;
- float x4 = b1.x; float y4 = b1.y;
-
- //AABB early exit
- if (b2Max(x1,x2) < b2Min(x3,x4) || b2Max(x3,x4) < b2Min(x1,x2) ) return false;
- if (b2Max(y1,y2) < b2Min(y3,y4) || b2Max(y3,y4) < b2Min(y1,y2) ) return false;
-
- float ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3));
- float ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3));
- float denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
- if (b2Abs(denom) < CMP_EPSILON) {
- //Lines are too close to parallel to call
- return false;
- }
- ua /= denom;
- ub /= denom;
-
- if ((0 < ua) && (ua < 1) && (0 < ub) && (ub < 1)) {
- //if (intersectionPoint){
- intersectionPoint.x = (x1 + ua * (x2 - x1));
- intersectionPoint.y = (y1 + ua * (y2 - y1));
- //}
- //printf("%f, %f -> %f, %f crosses %f, %f -> %f, %f\n",x1,y1,x2,y2,x3,y3,x4,y4);
- return true;
- }
-
- return false;
-}
-
-/*
- * True if line from a0->a1 intersects b0->b1
- */
-bool intersect(const b2Vec2& a0, const b2Vec2& a1,
- const b2Vec2& b0, const b2Vec2& b1) {
- b2Vec2 myVec(0.0f,0.0f);
- return intersect(a0, a1, b0, b1, myVec);
-}
-
-b2Polygon::b2Polygon(float32* _x, float32* _y, int32 nVert) {
- nVertices = nVert;
- x = new float32[nVertices];
- y = new float32[nVertices];
- for (int32 i = 0; i < nVertices; ++i) {
- x[i] = _x[i];
- y[i] = _y[i];
- }
- areaIsSet = false;
-}
-
-b2Polygon::b2Polygon(b2Vec2* v, int32 nVert) {
- nVertices = nVert;
- x = new float32[nVertices];
- y = new float32[nVertices];
- for (int32 i = 0; i < nVertices; ++i) {
- x[i] = v[i].x;
- y[i] = v[i].y;
-
- }
- areaIsSet = false;
-}
-
-b2Polygon::b2Polygon() {
- x = NULL;
- y = NULL;
- nVertices = 0;
- areaIsSet = false;
-}
-
-b2Polygon::~b2Polygon() {
- //printf("About to delete poly with %d vertices\n",nVertices);
- delete[] x;
- delete[] y;
-}
-
-float32 b2Polygon::GetArea() {
- // TODO: fix up the areaIsSet caching so that it can be used
- //if (areaIsSet) return area;
- area = 0.0f;
-
- //First do wraparound
- area += x[nVertices-1]*y[0]-x[0]*y[nVertices-1];
- for (int i=0; i<nVertices-1; ++i){
- area += x[i]*y[i+1]-x[i+1]*y[i];
- }
- area *= .5f;
- areaIsSet = true;
- return area;
-}
-
-bool b2Polygon::IsCCW() {
- return (GetArea() > 0.0f);
-}
-
-void b2Polygon::MergeParallelEdges(float32 tolerance) {
- if (nVertices <= 3) return; //Can't do anything useful here to a triangle
- bool* mergeMe = new bool[nVertices];
- int32 newNVertices = nVertices;
- for (int32 i = 0; i < nVertices; ++i) {
- int32 lower = (i == 0) ? (nVertices - 1) : (i - 1);
- int32 middle = i;
- int32 upper = (i == nVertices - 1) ? (0) : (i + 1);
- float32 dx0 = x[middle] - x[lower];
- float32 dy0 = y[middle] - y[lower];
- float32 dx1 = x[upper] - x[middle];
- float32 dy1 = y[upper] - y[middle];
- float32 norm0 = sqrtf(dx0*dx0+dy0*dy0);
- float32 norm1 = sqrtf(dx1*dx1+dy1*dy1);
- if ( !(norm0 > 0.0f && norm1 > 0.0f) && newNVertices > 3 ) {
- //Merge identical points
- mergeMe[i] = true;
- --newNVertices;
- }
- dx0 /= norm0; dy0 /= norm0;
- dx1 /= norm1; dy1 /= norm1;
- float32 cross = dx0 * dy1 - dx1 * dy0;
- float32 dot = dx0 * dx1 + dy0 * dy1;
- if (fabs(cross) < tolerance && dot > 0 && newNVertices > 3) {
- mergeMe[i] = true;
- --newNVertices;
- } else {
- mergeMe[i] = false;
- }
- }
- if(newNVertices == nVertices || newNVertices == 0) {
- delete[] mergeMe;
- return;
- }
- float32* newx = new float32[newNVertices];
- float32* newy = new float32[newNVertices];
- int32 currIndex = 0;
- for (int32 i=0; i < nVertices; ++i) {
- if (mergeMe[i] || newNVertices == 0 || currIndex == newNVertices) continue;
- b2Assert(currIndex < newNVertices);
- newx[currIndex] = x[i];
- newy[currIndex] = y[i];
- ++currIndex;
- }
- delete[] x;
- delete[] y;
- delete[] mergeMe;
- x = newx;
- y = newy;
- nVertices = newNVertices;
- //printf("%d \n", newNVertices);
-}
-
- /*
- * Allocates and returns pointer to vector vertex array.
- * Length of array is nVertices.
- */
-b2Vec2* b2Polygon::GetVertexVecs() {
- b2Vec2* out = new b2Vec2[nVertices];
- for (int32 i = 0; i < nVertices; ++i) {
- out[i].Set(x[i], y[i]);
- }
- return out;
-}
-
-b2Polygon::b2Polygon(b2Triangle& t) {
- nVertices = 3;
- x = new float[nVertices];
- y = new float[nVertices];
- for (int32 i = 0; i < nVertices; ++i) {
- x[i] = t.x[i];
- y[i] = t.y[i];
- }
-}
-
-void b2Polygon::Set(const b2Polygon& p) {
- if (nVertices != p.nVertices){
- nVertices = p.nVertices;
- delete[] x;
- delete[] y;
- x = new float32[nVertices];
- y = new float32[nVertices];
- }
-
- for (int32 i = 0; i < nVertices; ++i) {
- x[i] = p.x[i];
- y[i] = p.y[i];
- }
- areaIsSet = false;
-}
-
- /*
- * Assuming the polygon is simple, checks if it is convex.
- */
-bool b2Polygon::IsConvex() {
- bool isPositive = false;
- for (int32 i = 0; i < nVertices; ++i) {
- int32 lower = (i == 0) ? (nVertices - 1) : (i - 1);
- int32 middle = i;
- int32 upper = (i == nVertices - 1) ? (0) : (i + 1);
- float32 dx0 = x[middle] - x[lower];
- float32 dy0 = y[middle] - y[lower];
- float32 dx1 = x[upper] - x[middle];
- float32 dy1 = y[upper] - y[middle];
- float32 cross = dx0 * dy1 - dx1 * dy0;
- // Cross product should have same sign
- // for each vertex if poly is convex.
- bool newIsP = (cross >= 0) ? true : false;
- if (i == 0) {
- isPositive = newIsP;
- }
- else if (isPositive != newIsP) {
- return false;
- }
- }
- return true;
-}
-
-/*
- * Pulled from b2Shape.cpp, assertions removed
- */
-static b2Vec2 PolyCentroid(const b2Vec2* vs, int32 count)
-{
- b2Vec2 c; c.Set(0.0f, 0.0f);
- float32 area = 0.0f;
-
- const float32 inv3 = 1.0f / 3.0f;
- b2Vec2 pRef(0.0f, 0.0f);
- for (int32 i = 0; i < count; ++i)
- {
- // Triangle vertices.
- b2Vec2 p1 = pRef;
- b2Vec2 p2 = vs[i];
- b2Vec2 p3 = i + 1 < count ? vs[i+1] : vs[0];
-
- b2Vec2 e1 = p2 - p1;
- b2Vec2 e2 = p3 - p1;
-
- float32 D = b2Cross(e1, e2);
-
- float32 triangleArea = 0.5f * D;
- area += triangleArea;
-
- // Area weighted centroid
- c += (p1 + p2 + p3) * triangleArea * inv3;
- }
-
- // Centroid
- c *= 1.0f / area;
- return c;
-}
-
-
-/*
- * Checks if polygon is valid for use in Box2d engine.
- * Last ditch effort to ensure no invalid polygons are
- * added to world geometry.
- *
- * Performs a full check, for simplicity, convexity,
- * orientation, minimum angle, and volume. This won't
- * be very efficient, and a lot of it is redundant when
- * other tools in this section are used.
- */
-bool b2Polygon::IsUsable(bool printErrors){
- int32 error = -1;
- bool noError = true;
- if (nVertices < 3 || nVertices > b2_maxPolygonVertices) {noError = false; error = 0;}
- if (!IsConvex()) {noError = false; error = 1;}
- if (!IsSimple()) {noError = false; error = 2;}
- if (GetArea() < CMP_EPSILON) {noError = false; error = 3;}
-
- //Compute normals
- b2Vec2* normals = new b2Vec2[nVertices];
- b2Vec2* vertices = new b2Vec2[nVertices];
- for (int32 i = 0; i < nVertices; ++i){
- vertices[i].Set(x[i],y[i]);
- int32 i1 = i;
- int32 i2 = i + 1 < nVertices ? i + 1 : 0;
- b2Vec2 edge(x[i2]-x[i1],y[i2]-y[i1]);
- normals[i] = b2Cross(edge, 1.0f);
- normals[i].Normalize();
- }
-
- //Required side checks
- for (int32 i=0; i<nVertices; ++i){
- int32 iminus = (i==0)?nVertices-1:i-1;
- //int32 iplus = (i==nVertices-1)?0:i+1;
-
- //Parallel sides check
- float32 cross = b2Cross(normals[iminus], normals[i]);
- cross = b2Clamp(cross, -1.0f, 1.0f);
- float32 angle = asinf(cross);
- if(angle <= b2_angularSlop){
- noError = false;
- error = 4;
- break;
- }
-
- //Too skinny check
- for (int32 j=0; j<nVertices; ++j){
- if (j == i || j == (i + 1) % nVertices){
- continue;
- }
- float32 s = b2Dot(normals[i], vertices[j] - vertices[i]);
- if (s >= -b2_linearSlop){
- noError = false;
- error = 5;
- }
- }
-
-
- b2Vec2 centroid = PolyCentroid(vertices,nVertices);
- b2Vec2 n1 = normals[iminus];
- b2Vec2 n2 = normals[i];
- b2Vec2 v = vertices[i] - centroid;
-
- b2Vec2 d;
- d.x = b2Dot(n1, v) - toiSlop;
- d.y = b2Dot(n2, v) - toiSlop;
-
- // Shifting the edge inward by b2_toiSlop should
- // not cause the plane to pass the centroid.
- if ((d.x < 0.0f)||(d.y < 0.0f)){
- noError = false;
- error = 6;
- }
-
- }
- delete[] vertices;
- delete[] normals;
-
- if (!noError && printErrors){
- printf("Found invalid polygon, ");
- switch(error){
- case 0:
- printf("must have between 3 and %d vertices.\n",b2_maxPolygonVertices);
- break;
- case 1:
- printf("must be convex.\n");
- break;
- case 2:
- printf("must be simple (cannot intersect itself).\n");
- break;
- case 3:
- printf("area is too small.\n");
- break;
- case 4:
- printf("sides are too close to parallel.\n");
- break;
- case 5:
- printf("polygon is too thin.\n");
- break;
- case 6:
- printf("core shape generation would move edge past centroid (too thin).\n");
- break;
- default:
- printf("don't know why.\n");
- }
- }
- return noError;
-}
-
-
-bool b2Polygon::IsUsable(){
- return IsUsable(B2_POLYGON_REPORT_ERRORS);
-}
-
-//Check for edge crossings
-bool b2Polygon::IsSimple() {
- for (int32 i=0; i<nVertices; ++i){
- int32 iplus = (i+1 > nVertices-1)?0:i+1;
- b2Vec2 a1(x[i],y[i]);
- b2Vec2 a2(x[iplus],y[iplus]);
- for (int32 j=i+1; j<nVertices; ++j){
- int32 jplus = (j+1 > nVertices-1)?0:j+1;
- b2Vec2 b1(x[j],y[j]);
- b2Vec2 b2(x[jplus],y[jplus]);
- if (intersect(a1,a2,b1,b2)){
- return false;
- }
- }
- }
- return true;
-}
-
- /*
- * Tries to add a triangle to the polygon. Returns null if it can't connect
- * properly, otherwise returns a pointer to the new Polygon. Assumes bitwise
- * equality of joined vertex positions.
- *
- * Remember to delete the pointer afterwards.
- * Todo: Make this return a b2Polygon instead
- * of a pointer to a heap-allocated one.
- *
- * For internal use.
- */
-b2Polygon* b2Polygon::Add(b2Triangle& t) {
- // First, find vertices that connect
- int32 firstP = -1;
- int32 firstT = -1;
- int32 secondP = -1;
- int32 secondT = -1;
- for (int32 i = 0; i < nVertices; i++) {
- if (t.x[0] == x[i] && t.y[0] == y[i]) {
- if (firstP == -1) {
- firstP = i;
- firstT = 0;
- }
- else {
- secondP = i;
- secondT = 0;
- }
- }
- else if (t.x[1] == x[i] && t.y[1] == y[i]) {
- if (firstP == -1) {
- firstP = i;
- firstT = 1;
- }
- else {
- secondP = i;
- secondT = 1;
- }
- }
- else if (t.x[2] == x[i] && t.y[2] == y[i]) {
- if (firstP == -1) {
- firstP = i;
- firstT = 2;
- }
- else {
- secondP = i;
- secondT = 2;
- }
- }
- else {
- }
- }
- // Fix ordering if first should be last vertex of poly
- if (firstP == 0 && secondP == nVertices - 1) {
- firstP = nVertices - 1;
- secondP = 0;
- }
-
- // Didn't find it
- if (secondP == -1) {
- return NULL;
- }
-
- // Find tip index on triangle
- int32 tipT = 0;
- if (tipT == firstT || tipT == secondT)
- tipT = 1;
- if (tipT == firstT || tipT == secondT)
- tipT = 2;
-
- float32* newx = new float[nVertices + 1];
- float32* newy = new float[nVertices + 1];
- int32 currOut = 0;
- for (int32 i = 0; i < nVertices; i++) {
- newx[currOut] = x[i];
- newy[currOut] = y[i];
- if (i == firstP) {
- ++currOut;
- newx[currOut] = t.x[tipT];
- newy[currOut] = t.y[tipT];
- }
- ++currOut;
- }
- b2Polygon* result = new b2Polygon(newx, newy, nVertices+1);
- delete[] newx;
- delete[] newy;
- return result;
-}
-
- /**
- * Adds this polygon to a PolyDef.
- */
-#if 0
-void b2Polygon::AddTo(b2FixtureDef& pd) {
- if (nVertices < 3) return;
-
- b2Assert(nVertices <= b2_maxPolygonVertices);
-
- b2Vec2* vecs = GetVertexVecs();
- b2Vec2* vecsToAdd = new b2Vec2[nVertices];
-
- int32 offset = 0;
-
- b2PolygonShape *polyShape = new b2PolygonShape;
- int32 ind;
-
- for (int32 i = 0; i < nVertices; ++i) {
-
- //Omit identical neighbors (including wraparound)
- ind = i - offset;
- if (vecs[i].x==vecs[remainder(i+1,nVertices)].x &&
- vecs[i].y==vecs[remainder(i+1,nVertices)].y){
- offset++;
- continue;
- }
-
- vecsToAdd[ind] = vecs[i];
-
- }
-
- polyShape->Set((const b2Vec2*)vecsToAdd, ind+1);
- pd.shape = polyShape;
-
- delete[] vecs;
- delete[] vecsToAdd;
-}
-#endif
- /**
- * Finds and fixes "pinch points," points where two polygon
- * vertices are at the same point.
- *
- * If a pinch point is found, pin is broken up into poutA and poutB
- * and true is returned; otherwise, returns false.
- *
- * Mostly for internal use.
- */
-bool ResolvePinchPoint(const b2Polygon& pin, b2Polygon& poutA, b2Polygon& poutB){
- if (pin.nVertices < 3) return false;
- float32 tol = .001f;
- bool hasPinchPoint = false;
- int32 pinchIndexA = -1;
- int32 pinchIndexB = -1;
- for (int i=0; i<pin.nVertices; ++i){
- for (int j=i+1; j<pin.nVertices; ++j){
- //Don't worry about pinch points where the points
- //are actually just dupe neighbors
- if (b2Abs(pin.x[i]-pin.x[j])<tol&&b2Abs(pin.y[i]-pin.y[j])<tol&&j!=i+1){
- pinchIndexA = i;
- pinchIndexB = j;
- //printf("pinch: %f, %f == %f, %f\n",pin.x[i],pin.y[i],pin.x[j],pin.y[j]);
- //printf("at indexes %d, %d\n",i,j);
- hasPinchPoint = true;
- break;
- }
- }
- if (hasPinchPoint) break;
- }
- if (hasPinchPoint){
- //printf("Found pinch point\n");
- int32 sizeA = pinchIndexB - pinchIndexA;
- if (sizeA == pin.nVertices) return false;//has dupe points at wraparound, not a problem here
- float32* xA = new float32[sizeA];
- float32* yA = new float32[sizeA];
- for (int32 i=0; i < sizeA; ++i){
- int32 ind = remainder(pinchIndexA+i,pin.nVertices);
- xA[i] = pin.x[ind];
- yA[i] = pin.y[ind];
- }
- b2Polygon tempA(xA,yA,sizeA);
- poutA.Set(tempA);
- delete[] xA;
- delete[] yA;
-
- int32 sizeB = pin.nVertices - sizeA;
- float32* xB = new float32[sizeB];
- float32* yB = new float32[sizeB];
- for (int32 i=0; i<sizeB; ++i){
- int32 ind = remainder(pinchIndexB+i,pin.nVertices);
- xB[i] = pin.x[ind];
- yB[i] = pin.y[ind];
- }
- b2Polygon tempB(xB,yB,sizeB);
- poutB.Set(tempB);
- //printf("Size of a: %d, size of b: %d\n",sizeA,sizeB);
- delete[] xB;
- delete[] yB;
- }
- return hasPinchPoint;
-}
-
- /**
- * Triangulates a polygon using simple ear-clipping algorithm. Returns
- * size of Triangle array unless the polygon can't be triangulated.
- * This should only happen if the polygon self-intersects,
- * though it will not _always_ return null for a bad polygon - it is the
- * caller's responsibility to check for self-intersection, and if it
- * doesn't, it should at least check that the return value is non-null
- * before using. You're warned!
- *
- * Triangles may be degenerate, especially if you have identical points
- * in the input to the algorithm. Check this before you use them.
- *
- * This is totally unoptimized, so for large polygons it should not be part
- * of the simulation loop.
- *
- * Returns:
- * -1 if algorithm fails (self-intersection most likely)
- * 0 if there are not enough vertices to triangulate anything.
- * Number of triangles if triangulation was successful.
- *
- * results will be filled with results - ear clipping always creates vNum - 2
- * or fewer (due to pinch point polygon snipping), so allocate an array of
- * this size.
- */
-
-int32 TriangulatePolygon(float32* xv, float32* yv, int32 vNum, b2Triangle* results) {
- if (vNum < 3)
- return 0;
-
- //Recurse and split on pinch points
- b2Polygon pA,pB;
- b2Polygon pin(xv,yv,vNum);
- if (ResolvePinchPoint(pin,pA,pB)){
- b2Triangle* mergeA = new b2Triangle[pA.nVertices];
- b2Triangle* mergeB = new b2Triangle[pB.nVertices];
- int32 nA = TriangulatePolygon(pA.x,pA.y,pA.nVertices,mergeA);
- int32 nB = TriangulatePolygon(pB.x,pB.y,pB.nVertices,mergeB);
- if (nA==-1 || nB==-1){
- delete[] mergeA;
- delete[] mergeB;
- return -1;
- }
- for (int32 i=0; i<nA; ++i){
- results[i].Set(mergeA[i]);
- }
- for (int32 i=0; i<nB; ++i){
- results[nA+i].Set(mergeB[i]);
- }
- delete[] mergeA;
- delete[] mergeB;
- return (nA+nB);
- }
-
- b2Triangle* buffer = new b2Triangle[vNum-2];
- int32 bufferSize = 0;
- float32* xrem = new float32[vNum];
- float32* yrem = new float32[vNum];
- for (int32 i = 0; i < vNum; ++i) {
- xrem[i] = xv[i];
- yrem[i] = yv[i];
- }
-
- int xremLength = vNum;
-
- while (vNum > 3) {
- // Find an ear
- int32 earIndex = -1;
- //float32 earVolume = -1.0f;
- float32 earMaxMinCross = -10.0f;
- for (int32 i = 0; i < vNum; ++i) {
- if (IsEar(i, xrem, yrem, vNum)) {
- int32 lower = remainder(i-1,vNum);
- int32 upper = remainder(i+1,vNum);
- b2Vec2 d1(xrem[upper]-xrem[i],yrem[upper]-yrem[i]);
- b2Vec2 d2(xrem[i]-xrem[lower],yrem[i]-yrem[lower]);
- b2Vec2 d3(xrem[lower]-xrem[upper],yrem[lower]-yrem[upper]);
-
- d1.Normalize();
- d2.Normalize();
- d3.Normalize();
- float32 cross12 = b2Abs( b2Cross(d1,d2) );
- float32 cross23 = b2Abs( b2Cross(d2,d3) );
- float32 cross31 = b2Abs( b2Cross(d3,d1) );
- //Find the maximum minimum angle
- float32 minCross = b2Min(cross12, b2Min(cross23,cross31));
- if (minCross > earMaxMinCross){
- earIndex = i;
- earMaxMinCross = minCross;
- }
-
- /*//This bit chooses the ear with greatest volume first
- float32 testVol = b2Abs( d1.x*d2.y-d2.x*d1.y );
- if (testVol > earVolume){
- earIndex = i;
- earVolume = testVol;
- }*/
- }
- }
-
- // If we still haven't found an ear, we're screwed.
- // Note: sometimes this is happening because the
- // remaining points are collinear. Really these
- // should just be thrown out without halting triangulation.
- if (earIndex == -1){
- if (B2_POLYGON_REPORT_ERRORS){
- b2Polygon dump(xrem,yrem,vNum);
- printf("Couldn't find an ear, dumping remaining poly:\n");
- dump.printFormatted();
- printf("Please submit this dump to ewjordan at Box2d forums\n");
- }
- for (int32 i = 0; i < bufferSize; i++) {
- results[i].Set(buffer[i]);
- }
-
- delete[] buffer;
-
- if (bufferSize > 0) return bufferSize;
- else return -1;
- }
-
- // Clip off the ear:
- // - remove the ear tip from the list
-
- --vNum;
- float32* newx = new float32[vNum];
- float32* newy = new float32[vNum];
- int32 currDest = 0;
- for (int32 i = 0; i < vNum; ++i) {
- if (currDest == earIndex) ++currDest;
- newx[i] = xrem[currDest];
- newy[i] = yrem[currDest];
- ++currDest;
- }
-
- // - add the clipped triangle to the triangle list
- int32 under = (earIndex == 0) ? (vNum) : (earIndex - 1);
- int32 over = (earIndex == vNum) ? 0 : (earIndex + 1);
- b2Triangle toAdd = b2Triangle(xrem[earIndex], yrem[earIndex], xrem[over], yrem[over], xrem[under], yrem[under]);
- buffer[bufferSize].Set(toAdd);
- ++bufferSize;
-
- // - replace the old list with the new one
- delete[] xrem;
- delete[] yrem;
- xrem = newx;
- yrem = newy;
- }
-
- b2Triangle toAdd = b2Triangle(xrem[1], yrem[1], xrem[2], yrem[2],
- xrem[0], yrem[0]);
- buffer[bufferSize].Set(toAdd);
- ++bufferSize;
-
- delete[] xrem;
- delete[] yrem;
-
- b2Assert(bufferSize == xremLength-2);
-
- for (int32 i = 0; i < bufferSize; i++) {
- results[i].Set(buffer[i]);
- }
-
- delete[] buffer;
-
- return bufferSize;
-}
-
- /**
- * Turns a list of triangles into a list of convex polygons. Very simple
- * method - start with a seed triangle, keep adding triangles to it until
- * you can't add any more without making the polygon non-convex.
- *
- * Returns an integer telling how many polygons were created. Will fill
- * polys array up to polysLength entries, which may be smaller or larger
- * than the return value.
- *
- * Takes O(N*P) where P is the number of resultant polygons, N is triangle
- * count.
- *
- * The final polygon list will not necessarily be minimal, though in
- * practice it works fairly well.
- */
-int32 PolygonizeTriangles(b2Triangle* triangulated, int32 triangulatedLength, b2Polygon* polys, int32 polysLength) {
- int32 polyIndex = 0;
-
- if (triangulatedLength <= 0) {
- return 0;
- }
- else {
- int* covered = new int[triangulatedLength];
- for (int32 i = 0; i < triangulatedLength; ++i) {
- covered[i] = 0;
- //Check here for degenerate triangles
- if ( ( (triangulated[i].x[0] == triangulated[i].x[1]) && (triangulated[i].y[0] == triangulated[i].y[1]) )
- || ( (triangulated[i].x[1] == triangulated[i].x[2]) && (triangulated[i].y[1] == triangulated[i].y[2]) )
- || ( (triangulated[i].x[0] == triangulated[i].x[2]) && (triangulated[i].y[0] == triangulated[i].y[2]) ) ) {
- covered[i] = 1;
- }
- }
-
- bool notDone = true;
- while (notDone) {
- int32 currTri = -1;
- for (int32 i = 0; i < triangulatedLength; ++i) {
- if (covered[i])
- continue;
- currTri = i;
- break;
- }
- if (currTri == -1) {
- notDone = false;
- }
- else {
- b2Polygon poly(triangulated[currTri]);
- covered[currTri] = 1;
- int32 index = 0;
- for (int32 i = 0; i < 2*triangulatedLength; ++i,++index) {
- while (index >= triangulatedLength) index -= triangulatedLength;
- if (covered[index]) {
- continue;
- }
- b2Polygon* newP = poly.Add(triangulated[index]);
- if (!newP) {
- continue;
- }
- if (newP->nVertices > b2Polygon::maxVerticesPerPolygon) {
- delete newP;
- newP = NULL;
- continue;
- }
- if (newP->IsConvex()) { //Or should it be IsUsable? Maybe re-write IsConvex to apply the angle threshold from Box2d
- poly.Set(*newP);
- delete newP;
- newP = NULL;
- covered[index] = 1;
- } else {
- delete newP;
- newP = NULL;
- }
- }
- if (polyIndex < polysLength){
- poly.MergeParallelEdges(b2_angularSlop);
- //If identical points are present, a triangle gets
- //borked by the MergeParallelEdges function, hence
- //the vertex number check
- if (poly.nVertices >= 3) polys[polyIndex].Set(poly);
- //else printf("Skipping corrupt poly\n");
- }
- if (poly.nVertices >= 3) polyIndex++; //Must be outside (polyIndex < polysLength) test
- }
- //printf("MEMCHECK: %d\n",_CrtCheckMemory());
- }
- delete[] covered;
- }
- return polyIndex;
-}
-
- /**
- * Checks if vertex i is the tip of an ear in polygon defined by xv[] and
- * yv[].
- *
- * Assumes clockwise orientation of polygon...ick
- */
-bool IsEar(int32 i, float32* xv, float32* yv, int32 xvLength) {
- float32 dx0, dy0, dx1, dy1;
- dx0 = dy0 = dx1 = dy1 = 0;
- if (i >= xvLength || i < 0 || xvLength < 3) {
- return false;
- }
- int32 upper = i + 1;
- int32 lower = i - 1;
- if (i == 0) {
- dx0 = xv[0] - xv[xvLength - 1];
- dy0 = yv[0] - yv[xvLength - 1];
- dx1 = xv[1] - xv[0];
- dy1 = yv[1] - yv[0];
- lower = xvLength - 1;
- }
- else if (i == xvLength - 1) {
- dx0 = xv[i] - xv[i - 1];
- dy0 = yv[i] - yv[i - 1];
- dx1 = xv[0] - xv[i];
- dy1 = yv[0] - yv[i];
- upper = 0;
- }
- else {
- dx0 = xv[i] - xv[i - 1];
- dy0 = yv[i] - yv[i - 1];
- dx1 = xv[i + 1] - xv[i];
- dy1 = yv[i + 1] - yv[i];
- }
- float32 cross = dx0 * dy1 - dx1 * dy0;
- if (cross > 0)
- return false;
- b2Triangle myTri(xv[i], yv[i], xv[upper], yv[upper],
- xv[lower], yv[lower]);
- for (int32 j = 0; j < xvLength; ++j) {
- if (j == i || j == lower || j == upper)
- continue;
- if (myTri.IsInside(xv[j], yv[j]))
- return false;
- }
- return true;
-}
-
-void ReversePolygon(b2Polygon& p){
- ReversePolygon(p.x,p.y,p.nVertices);
-}
-
-void ReversePolygon(float* x, float* y, int n) {
- if (n == 1)
- return;
- int32 low = 0;
- int32 high = n - 1;
- while (low < high) {
- float32 buffer = x[low];
- x[low] = x[high];
- x[high] = buffer;
- buffer = y[low];
- y[low] = y[high];
- y[high] = buffer;
- ++low;
- --high;
- }
-}
-
- /**
- * Decomposes a non-convex polygon into a number of convex polygons, up
- * to maxPolys (remaining pieces are thrown out, but the total number
- * is returned, so the return value can be greater than maxPolys).
- *
- * Each resulting polygon will have no more than maxVerticesPerPolygon
- * vertices (set to b2MaxPolyVertices by default, though you can change
- * this).
- *
- * Returns -1 if operation fails (usually due to self-intersection of
- * polygon).
- */
-int32 DecomposeConvex(b2Polygon* p, b2Polygon* results, int32 maxPolys) {
- if (p->nVertices < 3) return 0;
-
- b2Triangle* triangulated = new b2Triangle[p->nVertices - 2];
- int32 nTri;
- if (p->IsCCW()) {
- //printf("It is ccw \n");
- b2Polygon tempP;
- tempP.Set(*p);
- ReversePolygon(tempP.x, tempP.y, tempP.nVertices);
- nTri = TriangulatePolygon(tempP.x, tempP.y, tempP.nVertices, triangulated);
- //ReversePolygon(p->x, p->y, p->nVertices); //reset orientation
- } else {
- //printf("It is not ccw \n");
- nTri = TriangulatePolygon(p->x, p->y, p->nVertices, triangulated);
- }
- if (nTri < 1) {
- //Still no luck? Oh well...
- delete[] triangulated;
- return -1;
- }
- int32 nPolys = PolygonizeTriangles(triangulated, nTri, results, maxPolys);
- delete[] triangulated;
- return nPolys;
-}
-
- /**
- * Decomposes a polygon into convex polygons and adds all pieces to a b2BodyDef
- * using a prototype b2PolyDef. All fields of the prototype are used for every
- * shape except the vertices (friction, restitution, density, etc).
- *
- * If you want finer control, you'll have to add everything by hand.
- *
- * This is the simplest method to add a complicated polygon to a body.
- *
- * Until Box2D's b2BodyDef behavior changes, this method returns a pointer to
- * a heap-allocated array of b2PolyDefs, which must be deleted by the user
- * after the b2BodyDef is added to the world.
- */
-#if 0
-void DecomposeConvexAndAddTo(b2Polygon* p, b2Body* bd, b2FixtureDef* prototype) {
-
- if (p->nVertices < 3) return;
- b2Polygon* decomposed = new b2Polygon[p->nVertices - 2]; //maximum number of polys
- int32 nPolys = DecomposeConvex(p, decomposed, p->nVertices - 2);
- //printf("npolys: %d",nPolys);
- b2FixtureDef* pdarray = new b2FixtureDef[2*p->nVertices];//extra space in case of splits
- int32 extra = 0;
- for (int32 i = 0; i < nPolys; ++i) {
- b2FixtureDef* toAdd = &pdarray[i+extra];
- *toAdd = *prototype;
- //Hmm, shouldn't have to do all this...
- /*
- toAdd->type = prototype->type;
- toAdd->friction = prototype->friction;
- toAdd->restitution = prototype->restitution;
- toAdd->density = prototype->density;
- toAdd->userData = prototype->userData;
- toAdd->categoryBits = prototype->categoryBits;
- toAdd->maskBits = prototype->maskBits;
- toAdd->groupIndex = prototype->groupIndex;//*/
- //decomposed[i].print();
- b2Polygon curr = decomposed[i];
- //TODO ewjordan: move this triangle handling to a better place so that
- //it happens even if this convenience function is not called.
- if (curr.nVertices == 3){
- //Check here for near-parallel edges, since we can't
- //handle this in merge routine
- for (int j=0; j<3; ++j){
- int32 lower = (j == 0) ? (curr.nVertices - 1) : (j - 1);
- int32 middle = j;
- int32 upper = (j == curr.nVertices - 1) ? (0) : (j + 1);
- float32 dx0 = curr.x[middle] - curr.x[lower]; float32 dy0 = curr.y[middle] - curr.y[lower];
- float32 dx1 = curr.x[upper] - curr.x[middle]; float32 dy1 = curr.y[upper] - curr.y[middle];
- float32 norm0 = sqrtf(dx0*dx0+dy0*dy0); float32 norm1 = sqrtf(dx1*dx1+dy1*dy1);
- if ( !(norm0 > 0.0f && norm1 > 0.0f) ) {
- //Identical points, don't do anything!
- goto Skip;
- }
- dx0 /= norm0; dy0 /= norm0;
- dx1 /= norm1; dy1 /= norm1;
- float32 cross = dx0 * dy1 - dx1 * dy0;
- float32 dot = dx0*dx1 + dy0*dy1;
- if (fabs(cross) < b2_angularSlop && dot > 0) {
- //Angle too close, split the triangle across from this point.
- //This is guaranteed to result in two triangles that satify
- //the tolerance (one of the angles is 90 degrees)
- float32 dx2 = curr.x[lower] - curr.x[upper]; float32 dy2 = curr.y[lower] - curr.y[upper];
- float32 norm2 = sqrtf(dx2*dx2+dy2*dy2);
- if (norm2 == 0.0f) {
- goto Skip;
- }
- dx2 /= norm2; dy2 /= norm2;
- float32 thisArea = curr.GetArea();
- float32 thisHeight = 2.0f * thisArea / norm2;
- float32 buffer2 = dx2;
- dx2 = dy2; dy2 = -buffer2;
- //Make two new polygons
- //printf("dx2: %f, dy2: %f, thisHeight: %f, middle: %d\n",dx2,dy2,thisHeight,middle);
- float32 newX1[3] = { curr.x[middle]+dx2*thisHeight, curr.x[lower], curr.x[middle] };
- float32 newY1[3] = { curr.y[middle]+dy2*thisHeight, curr.y[lower], curr.y[middle] };
- float32 newX2[3] = { newX1[0], curr.x[middle], curr.x[upper] };
- float32 newY2[3] = { newY1[0], curr.y[middle], curr.y[upper] };
- b2Polygon p1(newX1,newY1,3);
- b2Polygon p2(newX2,newY2,3);
- if (p1.IsUsable()){
- p1.AddTo(*toAdd);
-
-
- bd->CreateFixture(toAdd);
- ++extra;
- } else if (B2_POLYGON_REPORT_ERRORS){
- printf("Didn't add unusable polygon. Dumping vertices:\n");
- p1.print();
- }
- if (p2.IsUsable()){
- p2.AddTo(pdarray[i+extra]);
-
- bd->CreateFixture(toAdd);
- } else if (B2_POLYGON_REPORT_ERRORS){
- printf("Didn't add unusable polygon. Dumping vertices:\n");
- p2.print();
- }
- goto Skip;
- }
- }
-
- }
- if (decomposed[i].IsUsable()){
- decomposed[i].AddTo(*toAdd);
-
- bd->CreateFixture((const b2FixtureDef*)toAdd);
- } else if (B2_POLYGON_REPORT_ERRORS){
- printf("Didn't add unusable polygon. Dumping vertices:\n");
- decomposed[i].print();
- }
-Skip:
- ;
- }
- delete[] pdarray;
- delete[] decomposed;
- return;// pdarray; //needs to be deleted after body is created
-}
-
-#endif
- /**
- * Find the convex hull of a point cloud using "Gift-wrap" algorithm - start
- * with an extremal point, and walk around the outside edge by testing
- * angles.
- *
- * Runs in O(N*S) time where S is number of sides of resulting polygon.
- * Worst case: point cloud is all vertices of convex polygon -> O(N^2).
- *
- * There may be faster algorithms to do this, should you need one -
- * this is just the simplest. You can get O(N log N) expected time if you
- * try, I think, and O(N) if you restrict inputs to simple polygons.
- *
- * Returns null if number of vertices passed is less than 3.
- *
- * Results should be passed through convex decomposition afterwards
- * to ensure that each shape has few enough points to be used in Box2d.
- *
- * FIXME?: May be buggy with colinear points on hull. Couldn't find a test
- * case that resulted in wrong behavior. If one turns up, the solution is to
- * supplement angle check with an equality resolver that always picks the
- * longer edge. I think the current solution is working, though it sometimes
- * creates an extra edge along a line.
- */
-
-b2Polygon ConvexHull(b2Vec2* v, int nVert) {
- float32* cloudX = new float32[nVert];
- float32* cloudY = new float32[nVert];
- for (int32 i = 0; i < nVert; ++i) {
- cloudX[i] = v[i].x;
- cloudY[i] = v[i].y;
- }
- b2Polygon result = ConvexHull(cloudX, cloudY, nVert);
- delete[] cloudX;
- delete[] cloudY;
- return result;
-}
-
-b2Polygon ConvexHull(float32* cloudX, float32* cloudY, int32 nVert) {
- b2Assert(nVert > 2);
- int32* edgeList = new int32[nVert];
- int32 numEdges = 0;
-
- float32 minY = 1e10;
- int32 minYIndex = nVert;
- for (int32 i = 0; i < nVert; ++i) {
- if (cloudY[i] < minY) {
- minY = cloudY[i];
- minYIndex = i;
- }
- }
-
- int32 startIndex = minYIndex;
- int32 winIndex = -1;
- float32 dx = -1.0f;
- float32 dy = 0.0f;
- while (winIndex != minYIndex) {
- float32 newdx = 0.0f;
- float32 newdy = 0.0f;
- float32 maxDot = -2.0f;
- for (int32 i = 0; i < nVert; ++i) {
- if (i == startIndex)
- continue;
- newdx = cloudX[i] - cloudX[startIndex];
- newdy = cloudY[i] - cloudY[startIndex];
- float32 nrm = sqrtf(newdx * newdx + newdy * newdy);
- nrm = (nrm == 0.0f) ? 1.0f : nrm;
- newdx /= nrm;
- newdy /= nrm;
-
- //Cross and dot products act as proxy for angle
- //without requiring inverse trig.
- //FIXED: don't need cross test
- //float32 newCross = newdx * dy - newdy * dx;
- float32 newDot = newdx * dx + newdy * dy;
- if (newDot > maxDot) {//newCross >= 0.0f && newDot > maxDot) {
- maxDot = newDot;
- winIndex = i;
- }
- }
- edgeList[numEdges++] = winIndex;
- dx = cloudX[winIndex] - cloudX[startIndex];
- dy = cloudY[winIndex] - cloudY[startIndex];
- float32 nrm = sqrtf(dx * dx + dy * dy);
- nrm = (nrm == 0.0f) ? 1.0f : nrm;
- dx /= nrm;
- dy /= nrm;
- startIndex = winIndex;
- }
-
- float32* xres = new float32[numEdges];
- float32* yres = new float32[numEdges];
- for (int32 i = 0; i < numEdges; i++) {
- xres[i] = cloudX[edgeList[i]];
- yres[i] = cloudY[edgeList[i]];
- //("%f, %f\n",xres[i],yres[i]);
- }
-
- b2Polygon returnVal(xres, yres, numEdges);
-
- delete[] xres;
- delete[] yres;
- delete[] edgeList;
- returnVal.MergeParallelEdges(b2_angularSlop);
- return returnVal;
-}
-
-
-/*
- * Given sines and cosines, tells if A's angle is less than B's on -Pi, Pi
- * (in other words, is A "righter" than B)
- */
-bool IsRighter(float32 sinA, float32 cosA, float32 sinB, float32 cosB){
- if (sinA < 0){
- if (sinB > 0 || cosA <= cosB) return true;
- else return false;
- } else {
- if (sinB < 0 || cosA <= cosB) return false;
- else return true;
- }
-}
-
-//Fix for obnoxious behavior for the % operator for negative numbers...
-int32 remainder(int32 x, int32 modulus){
- int32 rem = x % modulus;
- while (rem < 0){
- rem += modulus;
- }
- return rem;
-}
-
-/*
-Method:
-Start at vertex with minimum y (pick maximum x one if there are two).
-We aim our "lastDir" vector at (1.0, 0)
-We look at the two rays going off from our start vertex, and follow whichever
-has the smallest angle (in -Pi -> Pi) wrt lastDir ("rightest" turn)
-
-Loop until we hit starting vertex:
-
-We add our current vertex to the list.
-We check the seg from current vertex to next vertex for intersections
- - if no intersections, follow to next vertex and continue
- - if intersections, pick one with minimum distance
- - if more than one, pick one with "rightest" next point (two possibilities for each)
-
-*/
-
-b2Polygon TraceEdge(b2Polygon* p){
- b2PolyNode* nodes = new b2PolyNode[p->nVertices*p->nVertices];//overkill, but sufficient (order of mag. is right)
- int32 nNodes = 0;
-
- //Add base nodes (raw outline)
- for (int32 i=0; i < p->nVertices; ++i){
- b2Vec2 pos(p->x[i],p->y[i]);
- nodes[i].position = pos;
- ++nNodes;
- int32 iplus = (i==p->nVertices-1)?0:i+1;
- int32 iminus = (i==0)?p->nVertices-1:i-1;
- nodes[i].AddConnection(nodes[iplus]);
- nodes[i].AddConnection(nodes[iminus]);
- }
-
- //Process intersection nodes - horribly inefficient
- bool dirty = true;
- int counter = 0;
- while (dirty){
- dirty = false;
- for (int32 i=0; i < nNodes; ++i){
- for (int32 j=0; j < nodes[i].nConnected; ++j){
- for (int32 k=0; k < nNodes; ++k){
- if (k==i || &nodes[k] == nodes[i].connected[j]) continue;
- for (int32 l=0; l < nodes[k].nConnected; ++l){
-
- if ( nodes[k].connected[l] == nodes[i].connected[j] ||
- nodes[k].connected[l] == &nodes[i]) continue;
- //Check intersection
- b2Vec2 intersectPt;
- //if (counter > 100) printf("checking intersection: %d, %d, %d, %d\n",i,j,k,l);
- bool crosses = intersect(nodes[i].position,nodes[i].connected[j]->position,
- nodes[k].position,nodes[k].connected[l]->position,
- intersectPt);
- if (crosses){
- /*if (counter > 100) {
- printf("Found crossing at %f, %f\n",intersectPt.x, intersectPt.y);
- printf("Locations: %f,%f - %f,%f | %f,%f - %f,%f\n",
- nodes[i].position.x, nodes[i].position.y,
- nodes[i].connected[j]->position.x, nodes[i].connected[j]->position.y,
- nodes[k].position.x,nodes[k].position.y,
- nodes[k].connected[l]->position.x,nodes[k].connected[l]->position.y);
- printf("Memory addresses: %d, %d, %d, %d\n",(int)&nodes[i],(int)nodes[i].connected[j],(int)&nodes[k],(int)nodes[k].connected[l]);
- }*/
- dirty = true;
- //Destroy and re-hook connections at crossing point
- b2PolyNode* connj = nodes[i].connected[j];
- b2PolyNode* connl = nodes[k].connected[l];
- nodes[i].connected[j]->RemoveConnection(nodes[i]);
- nodes[i].RemoveConnection(*connj);
- nodes[k].connected[l]->RemoveConnection(nodes[k]);
- nodes[k].RemoveConnection(*connl);
- nodes[nNodes] = b2PolyNode(intersectPt);
- nodes[nNodes].AddConnection(nodes[i]);
- nodes[i].AddConnection(nodes[nNodes]);
- nodes[nNodes].AddConnection(nodes[k]);
- nodes[k].AddConnection(nodes[nNodes]);
- nodes[nNodes].AddConnection(*connj);
- connj->AddConnection(nodes[nNodes]);
- nodes[nNodes].AddConnection(*connl);
- connl->AddConnection(nodes[nNodes]);
- ++nNodes;
- goto SkipOut;
- }
- }
- }
- }
- }
- SkipOut:
- ++counter;
- //if (counter > 100) printf("Counter: %d\n",counter);
- }
-
- /*
- // Debugging: check for connection consistency
- for (int32 i=0; i<nNodes; ++i) {
- int32 nConn = nodes[i].nConnected;
- for (int32 j=0; j<nConn; ++j) {
- if (nodes[i].connected[j]->nConnected == 0) b2Assert(false);
- b2PolyNode* connect = nodes[i].connected[j];
- bool found = false;
- for (int32 k=0; k<connect->nConnected; ++k) {
- if (connect->connected[k] == &nodes[i]) found = true;
- }
- b2Assert(found);
- }
- }*/
-
- //Collapse duplicate points
- bool foundDupe = true;
- int nActive = nNodes;
- while (foundDupe){
- foundDupe = false;
- for (int32 i=0; i < nNodes; ++i){
- if (nodes[i].nConnected == 0) continue;
- for (int32 j=i+1; j < nNodes; ++j){
- if (nodes[j].nConnected == 0) continue;
- b2Vec2 diff = nodes[i].position - nodes[j].position;
- if (diff.LengthSquared() <= COLLAPSE_DIST_SQR){
- if (nActive <= 3) {
- // -- GODOT start --
- delete[] nodes;
- // -- GODOT end --
- return b2Polygon();
- }
- //printf("Found dupe, %d left\n",nActive);
- --nActive;
- foundDupe = true;
- b2PolyNode* inode = &nodes[i];
- b2PolyNode* jnode = &nodes[j];
- //Move all of j's connections to i, and orphan j
- int32 njConn = jnode->nConnected;
- for (int32 k=0; k < njConn; ++k){
- b2PolyNode* knode = jnode->connected[k];
- b2Assert(knode != jnode);
- if (knode != inode) {
- inode->AddConnection(*knode);
- knode->AddConnection(*inode);
- }
- knode->RemoveConnection(*jnode);
- //printf("knode %d on node %d now has %d connections\n",k,j,knode->nConnected);
- //printf("Found duplicate point.\n");
- }
- /*
- printf("Orphaning node at address %d\n",(int)jnode);
- for (int32 k=0; k<njConn; ++k) {
- if (jnode->connected[k]->IsConnectedTo(*jnode)) printf("Problem!!!\n");
- }
- for (int32 k=0; k < njConn; ++k){
- jnode->RemoveConnectionByIndex(k);
- }
- */
- jnode->nConnected = 0;
- }
- }
- }
- }
-
- /*
- // Debugging: check for connection consistency
- for (int32 i=0; i<nNodes; ++i) {
- int32 nConn = nodes[i].nConnected;
- printf("Node %d has %d connections\n",i,nConn);
- for (int32 j=0; j<nConn; ++j) {
- if (nodes[i].connected[j]->nConnected == 0) {
- printf("Problem with node %d connection at address %d\n",i,(int)(nodes[i].connected[j]));
- b2Assert(false);
- }
- b2PolyNode* connect = nodes[i].connected[j];
- bool found = false;
- for (int32 k=0; k<connect->nConnected; ++k) {
- if (connect->connected[k] == &nodes[i]) found = true;
- }
- if (!found) printf("Connection %d (of %d) on node %d (of %d) did not have reciprocal connection.\n",j,nConn,i,nNodes);
- b2Assert(found);
- }
- }//*/
-
- //Now walk the edge of the list
-
- //Find node with minimum y value (max x if equal)
- float32 minY = 1e10;
- float32 maxX = -1e10;
- int32 minYIndex = -1;
- for (int32 i = 0; i < nNodes; ++i) {
- if (nodes[i].position.y < minY && nodes[i].nConnected > 1) {
- minY = nodes[i].position.y;
- minYIndex = i;
- maxX = nodes[i].position.x;
- } else if (nodes[i].position.y == minY && nodes[i].position.x > maxX && nodes[i].nConnected > 1) {
- minYIndex = i;
- maxX = nodes[i].position.x;
- }
- }
-
- b2Vec2 origDir(1.0f,0.0f);
- b2Vec2* resultVecs = new b2Vec2[4*nNodes];// nodes may be visited more than once, unfortunately - change to growable array!
- int32 nResultVecs = 0;
- b2PolyNode* currentNode = &nodes[minYIndex];
- b2PolyNode* startNode = currentNode;
- b2Assert(currentNode->nConnected > 0);
- b2PolyNode* nextNode = currentNode->GetRightestConnection(origDir);
- if (!nextNode) goto CleanUp; // Borked, clean up our mess and return
- resultVecs[0] = startNode->position;
- ++nResultVecs;
- while (nextNode != startNode){
- if (nResultVecs > 4*nNodes){
- /*
- printf("%d, %d, %d\n",(int)startNode,(int)currentNode,(int)nextNode);
- printf("%f, %f -> %f, %f\n",currentNode->position.x,currentNode->position.y, nextNode->position.x, nextNode->position.y);
- p->printFormatted();
- printf("Dumping connection graph: \n");
- for (int32 i=0; i<nNodes; ++i) {
- printf("nodex[%d] = %f; nodey[%d] = %f;\n",i,nodes[i].position.x,i,nodes[i].position.y);
- printf("//connected to\n");
- for (int32 j=0; j<nodes[i].nConnected; ++j) {
- printf("connx[%d][%d] = %f; conny[%d][%d] = %f;\n",i,j,nodes[i].connected[j]->position.x, i,j,nodes[i].connected[j]->position.y);
- }
- }
- printf("Dumping results thus far: \n");
- for (int32 i=0; i<nResultVecs; ++i) {
- printf("x[%d]=map(%f,-3,3,0,width); y[%d] = map(%f,-3,3,height,0);\n",i,resultVecs[i].x,i,resultVecs[i].y);
- }
- //*/
- b2Assert(false); //nodes should never be visited four times apiece (proof?), so we've probably hit a loop...crap
- }
- resultVecs[nResultVecs++] = nextNode->position;
- b2PolyNode* oldNode = currentNode;
- currentNode = nextNode;
- //printf("Old node connections = %d; address %d\n",oldNode->nConnected, (int)oldNode);
- //printf("Current node connections = %d; address %d\n",currentNode->nConnected, (int)currentNode);
- nextNode = currentNode->GetRightestConnection(oldNode);
- if (!nextNode) goto CleanUp; // There was a problem, so jump out of the loop and use whatever garbage we've generated so far
- //printf("nextNode address: %d\n",(int)nextNode);
- }
-
- CleanUp:
-
- float32* xres = new float32[nResultVecs];
- float32* yres = new float32[nResultVecs];
- for (int32 i=0; i<nResultVecs; ++i){
- xres[i] = resultVecs[i].x;
- yres[i] = resultVecs[i].y;
- }
- b2Polygon retval(xres,yres,nResultVecs);
- delete[] resultVecs;
- delete[] yres;
- delete[] xres;
- delete[] nodes;
- return retval;
-}
-
-b2PolyNode::b2PolyNode(){
- nConnected = 0;
- visited = false;
-}
-b2PolyNode::b2PolyNode(b2Vec2& pos){
- position = pos;
- nConnected = 0;
- visited = false;
-}
-
-void b2PolyNode::AddConnection(b2PolyNode& toMe){
- b2Assert(nConnected < MAX_CONNECTED);
- // Ignore duplicate additions
- for (int32 i=0; i<nConnected; ++i) {
- if (connected[i] == &toMe) return;
- }
- connected[nConnected] = &toMe;
- ++nConnected;
-}
-
-void b2PolyNode::RemoveConnection(b2PolyNode& fromMe){
- bool isFound = false;
- int32 foundIndex = -1;
- for (int32 i=0; i<nConnected; ++i){
- if (&fromMe == connected[i]) {//.position == connected[i]->position){
- isFound = true;
- foundIndex = i;
- break;
- }
- }
- b2Assert(isFound);
- --nConnected;
- //printf("nConnected: %d\n",nConnected);
- for (int32 i=foundIndex; i < nConnected; ++i){
- connected[i] = connected[i+1];
- }
-}
-void b2PolyNode::RemoveConnectionByIndex(int32 index){
- --nConnected;
- //printf("New nConnected = %d\n",nConnected);
- for (int32 i=index; i < nConnected; ++i){
- connected[i] = connected[i+1];
- }
-}
-bool b2PolyNode::IsConnectedTo(b2PolyNode& me){
- bool isFound = false;
- for (int32 i=0; i<nConnected; ++i){
- if (&me == connected[i]) {//.position == connected[i]->position){
- isFound = true;
- break;
- }
- }
- return isFound;
-}
-b2PolyNode* b2PolyNode::GetRightestConnection(b2PolyNode* incoming){
- if (nConnected == 0) b2Assert(false); // This means the connection graph is inconsistent
- if (nConnected == 1) {
- //b2Assert(false);
- // Because of the possibility of collapsing nearby points,
- // we may end up with "spider legs" dangling off of a region.
- // The correct behavior here is to turn around.
- return incoming;
- }
- b2Vec2 inDir = position - incoming->position;
- float32 inLength = inDir.Normalize();
- b2Assert(inLength > CMP_EPSILON);
-
- b2PolyNode* result = NULL;
- for (int32 i=0; i<nConnected; ++i){
- if (connected[i] == incoming) continue;
- b2Vec2 testDir = connected[i]->position - position;
- float32 testLengthSqr = testDir.LengthSquared();
- testDir.Normalize();
- /*
- if (testLengthSqr < COLLAPSE_DIST_SQR) {
- printf("Problem with connection %d\n",i);
- printf("This node has %d connections\n",nConnected);
- printf("That one has %d\n",connected[i]->nConnected);
- if (this == connected[i]) printf("This points at itself.\n");
- }*/
- b2Assert (testLengthSqr >= COLLAPSE_DIST_SQR);
- float32 myCos = b2Dot(inDir,testDir);
- float32 mySin = b2Cross(inDir,testDir);
- if (result){
- b2Vec2 resultDir = result->position - position;
- resultDir.Normalize();
- float32 resCos = b2Dot(inDir,resultDir);
- float32 resSin = b2Cross(inDir,resultDir);
- if (IsRighter(mySin,myCos,resSin,resCos)){
- result = connected[i];
- }
- } else{
- result = connected[i];
- }
- }
- if (B2_POLYGON_REPORT_ERRORS && !result) {
- printf("nConnected = %d\n",nConnected);
- for (int32 i=0; i<nConnected; ++i) {
- printf("connected[%d] @ %d\n",i,0);//(int)connected[i]);
- }
- }
- b2Assert(result);
-
- return result;
-}
-
-b2PolyNode* b2PolyNode::GetRightestConnection(b2Vec2& incomingDir){
- b2Vec2 diff = position-incomingDir;
- b2PolyNode temp(diff);
- b2PolyNode* res = GetRightestConnection(&temp);
- b2Assert(res);
- return res;
-}
-}
diff --git a/thirdparty/b2d_convexdecomp/b2Polygon.h b/thirdparty/b2d_convexdecomp/b2Polygon.h
deleted file mode 100644
index c466e28f7e..0000000000
--- a/thirdparty/b2d_convexdecomp/b2Polygon.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2007 Eric Jordan
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef B2_POLYGON_H
-#define B2_POLYGON_H
-
-#include "b2Triangle.h"
-#include "stdio.h"
-#include <string.h>
-#include <limits.h>
-namespace b2ConvexDecomp {
-
-static bool B2_POLYGON_REPORT_ERRORS = false;
-
-class b2Polygon;
-
-int32 remainder(int32 x, int32 modulus);
-int32 TriangulatePolygon(float32* xv, float32* yv, int32 vNum, b2Triangle* results);
-bool IsEar(int32 i, float32* xv, float32* yv, int32 xvLength); //Not for external use
-int32 PolygonizeTriangles(b2Triangle* triangulated, int32 triangulatedLength, b2Polygon* polys, int32 polysLength);
-int32 DecomposeConvex(b2Polygon* p, b2Polygon* results, int32 maxPolys);
-//void DecomposeConvexAndAddTo(b2Polygon* p, b2Body* bd, b2FixtureDef* prototype);
-
-void ReversePolygon(float32* x, float32* y, int n);
-
-b2Polygon TraceEdge(b2Polygon* p); //For use with self-intersecting polygons, finds outline
-
-class b2Polygon {
-
-public:
- const static int32 maxVerticesPerPolygon = b2_maxPolygonVertices;
-
- float32* x; //vertex arrays
- float32* y;
- int32 nVertices;
-
- float32 area;
- bool areaIsSet;
-
- b2Polygon(float32* _x, float32* _y, int32 nVert);
- b2Polygon(b2Vec2* v, int32 nVert);
- b2Polygon();
- ~b2Polygon();
-
- float32 GetArea();
-
- void MergeParallelEdges(float32 tolerance);
- b2Vec2* GetVertexVecs();
- b2Polygon(b2Triangle& t);
- void Set(const b2Polygon& p);
- bool IsConvex();
- bool IsCCW();
- bool IsUsable(bool printError);
- bool IsUsable();
- bool IsSimple();
- // void AddTo(b2FixtureDef& pd);
-
- b2Polygon* Add(b2Triangle& t);
-
- void print(){
- printFormatted();
- /*
- for (int32 i=0; i<nVertices; ++i){
- printf("i: %d, x:%f, y:%f\n",i,x[i],y[i]);
- }
- */
- }
-
- void printFormatted(){
- printf("float xv[] = {");
- for (int32 i=0; i<nVertices; ++i){
- printf("%ff,",x[i]);
- }
- printf("};\nfloat yv[] = {");
- for (int32 i=0; i<nVertices; ++i){
- printf("%ff,",y[i]);
- }
- printf("};\n");
- }
-
- b2Polygon(const b2Polygon& p){
- nVertices = p.nVertices;
- area = p.area;
- areaIsSet = p.areaIsSet;
- x = new float32[nVertices];
- y = new float32[nVertices];
- memcpy(x, p.x, nVertices * sizeof(float32));
- memcpy(y, p.y, nVertices * sizeof(float32));
- }
-
-
-};
-
-const int32 MAX_CONNECTED = 32;
-const float32 COLLAPSE_DIST_SQR = CMP_EPSILON*CMP_EPSILON;//0.1f;//1000*CMP_EPSILON*1000*CMP_EPSILON;
-
-class b2PolyNode{
-public:
- b2Vec2 position;
- b2PolyNode* connected[MAX_CONNECTED];
- int32 nConnected;
- bool visited;
-
- b2PolyNode(b2Vec2& pos);
- b2PolyNode();
- void AddConnection(b2PolyNode& toMe);
- void RemoveConnection(b2PolyNode& fromMe);
- void RemoveConnectionByIndex(int32 index);
- bool IsConnectedTo(b2PolyNode& me);
- b2PolyNode* GetRightestConnection(b2PolyNode* incoming);
- b2PolyNode* GetRightestConnection(b2Vec2& incomingDir);
-};
-
-
-b2Polygon ConvexHull(b2Vec2* v, int nVert);
-b2Polygon ConvexHull(float32* cloudX, float32* cloudY, int32 nVert);
-}
-#endif
diff --git a/thirdparty/b2d_convexdecomp/b2Triangle.cpp b/thirdparty/b2d_convexdecomp/b2Triangle.cpp
deleted file mode 100644
index a0a30b9407..0000000000
--- a/thirdparty/b2d_convexdecomp/b2Triangle.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2007 Eric Jordan
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include "b2Triangle.h"
-
-namespace b2ConvexDecomp {
-
-//Constructor automatically fixes orientation to ccw
-b2Triangle::b2Triangle(float32 x1, float32 y1, float32 x2, float32 y2, float32 x3, float32 y3){
- x = new float32[3];
- y = new float32[3];
- float32 dx1 = x2-x1;
- float32 dx2 = x3-x1;
- float32 dy1 = y2-y1;
- float32 dy2 = y3-y1;
- float32 cross = dx1*dy2-dx2*dy1;
- bool ccw = (cross>0);
- if (ccw){
- x[0] = x1; x[1] = x2; x[2] = x3;
- y[0] = y1; y[1] = y2; y[2] = y3;
- } else{
- x[0] = x1; x[1] = x3; x[2] = x2;
- y[0] = y1; y[1] = y3; y[2] = y2;
- }
-}
-
-b2Triangle::b2Triangle(){
- x = new float32[3];
- y = new float32[3];
-}
-
-b2Triangle::~b2Triangle(){
- delete[] x;
- delete[] y;
-}
-
-void b2Triangle::Set(const b2Triangle& toMe) {
- for (int32 i=0; i<3; ++i) {
- x[i] = toMe.x[i];
- y[i] = toMe.y[i];
- }
-}
-
-bool b2Triangle::IsInside(float32 _x, float32 _y){
- if (_x < x[0] && _x < x[1] && _x < x[2]) return false;
- if (_x > x[0] && _x > x[1] && _x > x[2]) return false;
- if (_y < y[0] && _y < y[1] && _y < y[2]) return false;
- if (_y > y[0] && _y > y[1] && _y > y[2]) return false;
-
- float32 vx2 = _x-x[0]; float32 vy2 = _y-y[0];
- float32 vx1 = x[1]-x[0]; float32 vy1 = y[1]-y[0];
- float32 vx0 = x[2]-x[0]; float32 vy0 = y[2]-y[0];
-
- float32 dot00 = vx0*vx0+vy0*vy0;
- float32 dot01 = vx0*vx1+vy0*vy1;
- float32 dot02 = vx0*vx2+vy0*vy2;
- float32 dot11 = vx1*vx1+vy1*vy1;
- float32 dot12 = vx1*vx2+vy1*vy2;
- float32 invDenom = 1.0f / (dot00*dot11 - dot01*dot01);
- float32 u = (dot11*dot02 - dot01*dot12)*invDenom;
- float32 v = (dot00*dot12 - dot01*dot02)*invDenom;
-
- return ((u>=0)&&(v>=0)&&(u+v<=1));
-}
-
-
-}
diff --git a/thirdparty/b2d_convexdecomp/b2Triangle.h b/thirdparty/b2d_convexdecomp/b2Triangle.h
deleted file mode 100644
index 99ab5cba69..0000000000
--- a/thirdparty/b2d_convexdecomp/b2Triangle.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2007 Eric Jordan
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef B2_TRIANGLE_H
-#define B2_TRIANGLE_H
-
-#include "b2Glue.h"
-
-namespace b2ConvexDecomp {
-
-
-
-class b2Triangle{
-public:
- float* x;
- float* y;
- b2Triangle();
- b2Triangle(float32 x1, float32 y1, float32 x2, float32 y2, float32 x3, float32 y3);
- ~b2Triangle();
- bool IsInside(float32 _x, float32 _y);
- void Set(const b2Triangle& toMe);
-
-};
-
-}
-#endif
diff --git a/thirdparty/basis_universal/LICENSE b/thirdparty/basis_universal/LICENSE
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/thirdparty/basis_universal/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/thirdparty/basis_universal/basisu_astc_decomp.cpp b/thirdparty/basis_universal/basisu_astc_decomp.cpp
new file mode 100644
index 0000000000..cc0a6ced7a
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_astc_decomp.cpp
@@ -0,0 +1,1550 @@
+// basisu_astc_decomp.cpp: Only used for ASTC decompression, to validate the transcoder's output.
+// This version does not support HDR.
+
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * rg: Removed external dependencies, remarked out HDR support because
+ * we don't need it, minor fix to decompress() so it converts non-sRGB
+ * output to 8-bits correctly. I've compared this decoder's output
+ * vs. astc-codec with random inputs on 4x4 blocks, and after fixing a few obvious
+ * bugs in astc-codec where it didn't correctly follow the spec they match so
+ * I'm assuming they are both correct for 4x4 now.
+ * HDR support should be easily added back in, but as we don't need it
+ * I'm leaving this for someone else.
+ *
+ *//*!
+ * \file
+ * \brief ASTC Utilities.
+ *//*--------------------------------------------------------------------*/
+#include "basisu_astc_decomp.h"
+#include <assert.h>
+#include <algorithm>
+
+#define DE_LENGTH_OF_ARRAY(x) (sizeof(x)/sizeof(x[0]))
+#define DE_UNREF(x) (void)x
+
+typedef uint8_t deUint8;
+typedef int8_t deInt8;
+typedef uint32_t deUint32;
+typedef int32_t deInt32;
+typedef uint16_t deUint16;
+typedef int16_t deInt16;
+typedef int64_t deInt64;
+typedef uint64_t deUint64;
+
+#define DE_ASSERT assert
+
+namespace basisu_astc
+{
+ static bool inBounds(int v, int l, int h)
+ {
+ return (v >= l) && (v < h);
+ }
+
+ static bool inRange(int v, int l, int h)
+ {
+ return (v >= l) && (v <= h);
+ }
+
+ template<typename T>
+ static inline T max(T a, T b)
+ {
+ return (a > b) ? a : b;
+ }
+
+ template<typename T>
+ static inline T min(T a, T b)
+ {
+ return (a < b) ? a : b;
+ }
+
+ template<typename T>
+ static inline T clamp(T a, T l, T h)
+ {
+ if (a < l)
+ return l;
+ else if (a > h)
+ return h;
+ return a;
+ }
+
+ struct UVec4
+ {
+ uint32_t m_c[4];
+
+ UVec4()
+ {
+ m_c[0] = 0;
+ m_c[1] = 0;
+ m_c[2] = 0;
+ m_c[3] = 0;
+ }
+
+ UVec4(uint32_t x, uint32_t y, uint32_t z, uint32_t w)
+ {
+ m_c[0] = x;
+ m_c[1] = y;
+ m_c[2] = z;
+ m_c[3] = w;
+ }
+
+ uint32_t x() const { return m_c[0]; }
+ uint32_t y() const { return m_c[1]; }
+ uint32_t z() const { return m_c[2]; }
+ uint32_t w() const { return m_c[3]; }
+
+ uint32_t& x() { return m_c[0]; }
+ uint32_t& y() { return m_c[1]; }
+ uint32_t& z() { return m_c[2]; }
+ uint32_t& w() { return m_c[3]; }
+
+ uint32_t operator[] (uint32_t idx) const { assert(idx < 4); return m_c[idx]; }
+ uint32_t& operator[] (uint32_t idx) { assert(idx < 4); return m_c[idx]; }
+ };
+
+ struct IVec4
+ {
+ int32_t m_c[4];
+
+ IVec4()
+ {
+ m_c[0] = 0;
+ m_c[1] = 0;
+ m_c[2] = 0;
+ m_c[3] = 0;
+ }
+
+ IVec4(int32_t x, int32_t y, int32_t z, int32_t w)
+ {
+ m_c[0] = x;
+ m_c[1] = y;
+ m_c[2] = z;
+ m_c[3] = w;
+ }
+
+ int32_t x() const { return m_c[0]; }
+ int32_t y() const { return m_c[1]; }
+ int32_t z() const { return m_c[2]; }
+ int32_t w() const { return m_c[3]; }
+
+ int32_t& x() { return m_c[0]; }
+ int32_t& y() { return m_c[1]; }
+ int32_t& z() { return m_c[2]; }
+ int32_t& w() { return m_c[3]; }
+
+ UVec4 asUint() const
+ {
+ return UVec4(std::max(0, m_c[0]), std::max(0, m_c[1]), std::max(0, m_c[2]), std::max(0, m_c[3]));
+ }
+
+ int32_t operator[] (uint32_t idx) const { assert(idx < 4); return m_c[idx]; }
+ int32_t& operator[] (uint32_t idx) { assert(idx < 4); return m_c[idx]; }
+ };
+
+ struct IVec3
+ {
+ int32_t m_c[3];
+
+ IVec3()
+ {
+ m_c[0] = 0;
+ m_c[1] = 0;
+ m_c[2] = 0;
+ }
+
+ IVec3(int32_t x, int32_t y, int32_t z)
+ {
+ m_c[0] = x;
+ m_c[1] = y;
+ m_c[2] = z;
+ }
+
+ int32_t x() const { return m_c[0]; }
+ int32_t y() const { return m_c[1]; }
+ int32_t z() const { return m_c[2]; }
+
+ int32_t& x() { return m_c[0]; }
+ int32_t& y() { return m_c[1]; }
+ int32_t& z() { return m_c[2]; }
+
+ int32_t operator[] (uint32_t idx) const { assert(idx < 3); return m_c[idx]; }
+ int32_t& operator[] (uint32_t idx) { assert(idx < 3); return m_c[idx]; }
+ };
+
+ static uint32_t deDivRoundUp32(uint32_t a, uint32_t b)
+ {
+ return (a + b - 1) / b;
+ }
+
+ static bool deInBounds32(uint32_t v, uint32_t l, uint32_t h)
+ {
+ return (v >= l) && (v < h);
+ }
+
+namespace astc
+{
+using std::vector;
+namespace
+{
+// Common utilities
+enum
+{
+ MAX_BLOCK_WIDTH = 12,
+ MAX_BLOCK_HEIGHT = 12
+};
+inline deUint32 getBit (deUint32 src, int ndx)
+{
+ DE_ASSERT(basisu_astc::inBounds(ndx, 0, 32));
+ return (src >> ndx) & 1;
+}
+inline deUint32 getBits (deUint32 src, int low, int high)
+{
+ const int numBits = (high-low) + 1;
+ DE_ASSERT(basisu_astc::inRange(numBits, 1, 32));
+ if (numBits < 32)
+ return (deUint32)((src >> low) & ((1u<<numBits)-1));
+ else
+ return (deUint32)((src >> low) & 0xFFFFFFFFu);
+}
+inline bool isBitSet (deUint32 src, int ndx)
+{
+ return getBit(src, ndx) != 0;
+}
+inline deUint32 reverseBits (deUint32 src, int numBits)
+{
+ DE_ASSERT(basisu_astc::inRange(numBits, 0, 32));
+ deUint32 result = 0;
+ for (int i = 0; i < numBits; i++)
+ result |= ((src >> i) & 1) << (numBits-1-i);
+ return result;
+}
+inline deUint32 bitReplicationScale (deUint32 src, int numSrcBits, int numDstBits)
+{
+ DE_ASSERT(numSrcBits <= numDstBits);
+ DE_ASSERT((src & ((1<<numSrcBits)-1)) == src);
+ deUint32 dst = 0;
+ for (int shift = numDstBits-numSrcBits; shift > -numSrcBits; shift -= numSrcBits)
+ dst |= shift >= 0 ? src << shift : src >> -shift;
+ return dst;
+}
+
+inline deInt32 signExtend (deInt32 src, int numSrcBits)
+{
+ DE_ASSERT(basisu_astc::inRange(numSrcBits, 2, 31));
+ const bool negative = (src & (1 << (numSrcBits-1))) != 0;
+ return src | (negative ? ~((1 << numSrcBits) - 1) : 0);
+}
+
+//inline bool isFloat16InfOrNan (deFloat16 v)
+//{
+// return getBits(v, 10, 14) == 31;
+//}
+
+enum ISEMode
+{
+ ISEMODE_TRIT = 0,
+ ISEMODE_QUINT,
+ ISEMODE_PLAIN_BIT,
+ ISEMODE_LAST
+};
+struct ISEParams
+{
+ ISEMode mode;
+ int numBits;
+ ISEParams (ISEMode mode_, int numBits_) : mode(mode_), numBits(numBits_) {}
+};
+inline int computeNumRequiredBits (const ISEParams& iseParams, int numValues)
+{
+ switch (iseParams.mode)
+ {
+ case ISEMODE_TRIT: return deDivRoundUp32(numValues*8, 5) + numValues*iseParams.numBits;
+ case ISEMODE_QUINT: return deDivRoundUp32(numValues*7, 3) + numValues*iseParams.numBits;
+ case ISEMODE_PLAIN_BIT: return numValues*iseParams.numBits;
+ default:
+ DE_ASSERT(false);
+ return -1;
+ }
+}
+ISEParams computeMaximumRangeISEParams (int numAvailableBits, int numValuesInSequence)
+{
+ int curBitsForTritMode = 6;
+ int curBitsForQuintMode = 5;
+ int curBitsForPlainBitMode = 8;
+ while (true)
+ {
+ DE_ASSERT(curBitsForTritMode > 0 || curBitsForQuintMode > 0 || curBitsForPlainBitMode > 0);
+ const int tritRange = curBitsForTritMode > 0 ? (3 << curBitsForTritMode) - 1 : -1;
+ const int quintRange = curBitsForQuintMode > 0 ? (5 << curBitsForQuintMode) - 1 : -1;
+ const int plainBitRange = curBitsForPlainBitMode > 0 ? (1 << curBitsForPlainBitMode) - 1 : -1;
+ const int maxRange = basisu_astc::max(basisu_astc::max(tritRange, quintRange), plainBitRange);
+ if (maxRange == tritRange)
+ {
+ const ISEParams params(ISEMODE_TRIT, curBitsForTritMode);
+ if (computeNumRequiredBits(params, numValuesInSequence) <= numAvailableBits)
+ return ISEParams(ISEMODE_TRIT, curBitsForTritMode);
+ curBitsForTritMode--;
+ }
+ else if (maxRange == quintRange)
+ {
+ const ISEParams params(ISEMODE_QUINT, curBitsForQuintMode);
+ if (computeNumRequiredBits(params, numValuesInSequence) <= numAvailableBits)
+ return ISEParams(ISEMODE_QUINT, curBitsForQuintMode);
+ curBitsForQuintMode--;
+ }
+ else
+ {
+ const ISEParams params(ISEMODE_PLAIN_BIT, curBitsForPlainBitMode);
+ DE_ASSERT(maxRange == plainBitRange);
+ if (computeNumRequiredBits(params, numValuesInSequence) <= numAvailableBits)
+ return ISEParams(ISEMODE_PLAIN_BIT, curBitsForPlainBitMode);
+ curBitsForPlainBitMode--;
+ }
+ }
+}
+inline int computeNumColorEndpointValues (deUint32 endpointMode)
+{
+ DE_ASSERT(endpointMode < 16);
+ return (endpointMode/4 + 1) * 2;
+}
+// Decompression utilities
+enum DecompressResult
+{
+ DECOMPRESS_RESULT_VALID_BLOCK = 0, //!< Decompressed valid block
+ DECOMPRESS_RESULT_ERROR, //!< Encountered error while decompressing, error color written
+ DECOMPRESS_RESULT_LAST
+};
+// A helper for getting bits from a 128-bit block.
+class Block128
+{
+private:
+ typedef deUint64 Word;
+ enum
+ {
+ WORD_BYTES = sizeof(Word),
+ WORD_BITS = 8*WORD_BYTES,
+ NUM_WORDS = 128 / WORD_BITS
+ };
+ //DE_STATIC_ASSERT(128 % WORD_BITS == 0);
+public:
+ Block128 (const deUint8* src)
+ {
+ for (int wordNdx = 0; wordNdx < NUM_WORDS; wordNdx++)
+ {
+ m_words[wordNdx] = 0;
+ for (int byteNdx = 0; byteNdx < WORD_BYTES; byteNdx++)
+ m_words[wordNdx] |= (Word)src[wordNdx*WORD_BYTES + byteNdx] << (8*byteNdx);
+ }
+ }
+ deUint32 getBit (int ndx) const
+ {
+ DE_ASSERT(basisu_astc::inBounds(ndx, 0, 128));
+ return (m_words[ndx / WORD_BITS] >> (ndx % WORD_BITS)) & 1;
+ }
+ deUint32 getBits (int low, int high) const
+ {
+ DE_ASSERT(basisu_astc::inBounds(low, 0, 128));
+ DE_ASSERT(basisu_astc::inBounds(high, 0, 128));
+ DE_ASSERT(basisu_astc::inRange(high-low+1, 0, 32));
+ if (high-low+1 == 0)
+ return 0;
+ const int word0Ndx = low / WORD_BITS;
+ const int word1Ndx = high / WORD_BITS;
+ // \note "foo << bar << 1" done instead of "foo << (bar+1)" to avoid overflow, i.e. shift amount being too big.
+ if (word0Ndx == word1Ndx)
+ return (deUint32)((m_words[word0Ndx] & ((((Word)1 << high%WORD_BITS << 1) - 1))) >> ((Word)low % WORD_BITS));
+ else
+ {
+ DE_ASSERT(word1Ndx == word0Ndx + 1);
+ return (deUint32)(m_words[word0Ndx] >> (low%WORD_BITS)) |
+ (deUint32)((m_words[word1Ndx] & (((Word)1 << high%WORD_BITS << 1) - 1)) << (high-low - high%WORD_BITS));
+ }
+ }
+ bool isBitSet (int ndx) const
+ {
+ DE_ASSERT(basisu_astc::inBounds(ndx, 0, 128));
+ return getBit(ndx) != 0;
+ }
+private:
+ Word m_words[NUM_WORDS];
+};
+// A helper for sequential access into a Block128.
+class BitAccessStream
+{
+public:
+ BitAccessStream (const Block128& src, int startNdxInSrc, int length, bool forward)
+ : m_src (src)
+ , m_startNdxInSrc (startNdxInSrc)
+ , m_length (length)
+ , m_forward (forward)
+ , m_ndx (0)
+ {
+ }
+ // Get the next num bits. Bits at positions greater than or equal to m_length are zeros.
+ deUint32 getNext (int num)
+ {
+ if (num == 0 || m_ndx >= m_length)
+ return 0;
+ const int end = m_ndx + num;
+ const int numBitsFromSrc = basisu_astc::max(0, basisu_astc::min(m_length, end) - m_ndx);
+ const int low = m_ndx;
+ const int high = m_ndx + numBitsFromSrc - 1;
+ m_ndx += num;
+ return m_forward ? m_src.getBits(m_startNdxInSrc + low, m_startNdxInSrc + high)
+ : reverseBits(m_src.getBits(m_startNdxInSrc - high, m_startNdxInSrc - low), numBitsFromSrc);
+ }
+private:
+ const Block128& m_src;
+ const int m_startNdxInSrc;
+ const int m_length;
+ const bool m_forward;
+ int m_ndx;
+};
+struct ISEDecodedResult
+{
+ deUint32 m;
+ deUint32 tq; //!< Trit or quint value, depending on ISE mode.
+ deUint32 v;
+};
+// Data from an ASTC block's "block mode" part (i.e. bits [0,10]).
+struct ASTCBlockMode
+{
+ bool isError;
+ // \note Following fields only relevant if !isError.
+ bool isVoidExtent;
+ // \note Following fields only relevant if !isVoidExtent.
+ bool isDualPlane;
+ int weightGridWidth;
+ int weightGridHeight;
+ ISEParams weightISEParams;
+ ASTCBlockMode (void)
+ : isError (true)
+ , isVoidExtent (true)
+ , isDualPlane (true)
+ , weightGridWidth (-1)
+ , weightGridHeight (-1)
+ , weightISEParams (ISEMODE_LAST, -1)
+ {
+ }
+};
+inline int computeNumWeights (const ASTCBlockMode& mode)
+{
+ return mode.weightGridWidth * mode.weightGridHeight * (mode.isDualPlane ? 2 : 1);
+}
+struct ColorEndpointPair
+{
+ UVec4 e0;
+ UVec4 e1;
+};
+struct TexelWeightPair
+{
+ deUint32 w[2];
+};
+ASTCBlockMode getASTCBlockMode (deUint32 blockModeData)
+{
+ ASTCBlockMode blockMode;
+ blockMode.isError = true; // \note Set to false later, if not error.
+ blockMode.isVoidExtent = getBits(blockModeData, 0, 8) == 0x1fc;
+ if (!blockMode.isVoidExtent)
+ {
+ if ((getBits(blockModeData, 0, 1) == 0 && getBits(blockModeData, 6, 8) == 7) || getBits(blockModeData, 0, 3) == 0)
+ return blockMode; // Invalid ("reserved").
+ deUint32 r = (deUint32)-1; // \note Set in the following branches.
+ if (getBits(blockModeData, 0, 1) == 0)
+ {
+ const deUint32 r0 = getBit(blockModeData, 4);
+ const deUint32 r1 = getBit(blockModeData, 2);
+ const deUint32 r2 = getBit(blockModeData, 3);
+ const deUint32 i78 = getBits(blockModeData, 7, 8);
+ r = (r2 << 2) | (r1 << 1) | (r0 << 0);
+ if (i78 == 3)
+ {
+ const bool i5 = isBitSet(blockModeData, 5);
+ blockMode.weightGridWidth = i5 ? 10 : 6;
+ blockMode.weightGridHeight = i5 ? 6 : 10;
+ }
+ else
+ {
+ const deUint32 a = getBits(blockModeData, 5, 6);
+ switch (i78)
+ {
+ case 0: blockMode.weightGridWidth = 12; blockMode.weightGridHeight = a + 2; break;
+ case 1: blockMode.weightGridWidth = a + 2; blockMode.weightGridHeight = 12; break;
+ case 2: blockMode.weightGridWidth = a + 6; blockMode.weightGridHeight = getBits(blockModeData, 9, 10) + 6; break;
+ default: DE_ASSERT(false);
+ }
+ }
+ }
+ else
+ {
+ const deUint32 r0 = getBit(blockModeData, 4);
+ const deUint32 r1 = getBit(blockModeData, 0);
+ const deUint32 r2 = getBit(blockModeData, 1);
+ const deUint32 i23 = getBits(blockModeData, 2, 3);
+ const deUint32 a = getBits(blockModeData, 5, 6);
+ r = (r2 << 2) | (r1 << 1) | (r0 << 0);
+ if (i23 == 3)
+ {
+ const deUint32 b = getBit(blockModeData, 7);
+ const bool i8 = isBitSet(blockModeData, 8);
+ blockMode.weightGridWidth = i8 ? b+2 : a+2;
+ blockMode.weightGridHeight = i8 ? a+2 : b+6;
+ }
+ else
+ {
+ const deUint32 b = getBits(blockModeData, 7, 8);
+ switch (i23)
+ {
+ case 0: blockMode.weightGridWidth = b + 4; blockMode.weightGridHeight = a + 2; break;
+ case 1: blockMode.weightGridWidth = b + 8; blockMode.weightGridHeight = a + 2; break;
+ case 2: blockMode.weightGridWidth = a + 2; blockMode.weightGridHeight = b + 8; break;
+ default: DE_ASSERT(false);
+ }
+ }
+ }
+ const bool zeroDH = getBits(blockModeData, 0, 1) == 0 && getBits(blockModeData, 7, 8) == 2;
+ const bool h = zeroDH ? 0 : isBitSet(blockModeData, 9);
+ blockMode.isDualPlane = zeroDH ? 0 : isBitSet(blockModeData, 10);
+ {
+ ISEMode& m = blockMode.weightISEParams.mode;
+ int& b = blockMode.weightISEParams.numBits;
+ m = ISEMODE_PLAIN_BIT;
+ b = 0;
+ if (h)
+ {
+ switch (r)
+ {
+ case 2: m = ISEMODE_QUINT; b = 1; break;
+ case 3: m = ISEMODE_TRIT; b = 2; break;
+ case 4: b = 4; break;
+ case 5: m = ISEMODE_QUINT; b = 2; break;
+ case 6: m = ISEMODE_TRIT; b = 3; break;
+ case 7: b = 5; break;
+ default: DE_ASSERT(false);
+ }
+ }
+ else
+ {
+ switch (r)
+ {
+ case 2: b = 1; break;
+ case 3: m = ISEMODE_TRIT; break;
+ case 4: b = 2; break;
+ case 5: m = ISEMODE_QUINT; break;
+ case 6: m = ISEMODE_TRIT; b = 1; break;
+ case 7: b = 3; break;
+ default: DE_ASSERT(false);
+ }
+ }
+ }
+ }
+ blockMode.isError = false;
+ return blockMode;
+}
+inline void setASTCErrorColorBlock (void* dst, int blockWidth, int blockHeight, bool isSRGB)
+{
+ if (isSRGB)
+ {
+ deUint8* const dstU = (deUint8*)dst;
+ for (int i = 0; i < blockWidth*blockHeight; i++)
+ {
+ dstU[4*i + 0] = 0xff;
+ dstU[4*i + 1] = 0;
+ dstU[4*i + 2] = 0xff;
+ dstU[4*i + 3] = 0xff;
+ }
+ }
+ else
+ {
+ float* const dstF = (float*)dst;
+ for (int i = 0; i < blockWidth*blockHeight; i++)
+ {
+ dstF[4*i + 0] = 1.0f;
+ dstF[4*i + 1] = 0.0f;
+ dstF[4*i + 2] = 1.0f;
+ dstF[4*i + 3] = 1.0f;
+ }
+ }
+}
+DecompressResult decodeVoidExtentBlock (void* dst, const Block128& blockData, int blockWidth, int blockHeight, bool isSRGB, bool isLDRMode)
+{
+ const deUint32 minSExtent = blockData.getBits(12, 24);
+ const deUint32 maxSExtent = blockData.getBits(25, 37);
+ const deUint32 minTExtent = blockData.getBits(38, 50);
+ const deUint32 maxTExtent = blockData.getBits(51, 63);
+ const bool allExtentsAllOnes = minSExtent == 0x1fff && maxSExtent == 0x1fff && minTExtent == 0x1fff && maxTExtent == 0x1fff;
+ const bool isHDRBlock = blockData.isBitSet(9);
+ if ((isLDRMode && isHDRBlock) || (!allExtentsAllOnes && (minSExtent >= maxSExtent || minTExtent >= maxTExtent)))
+ {
+ setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
+ return DECOMPRESS_RESULT_ERROR;
+ }
+ const deUint32 rgba[4] =
+ {
+ blockData.getBits(64, 79),
+ blockData.getBits(80, 95),
+ blockData.getBits(96, 111),
+ blockData.getBits(112, 127)
+ };
+ if (isSRGB)
+ {
+ deUint8* const dstU = (deUint8*)dst;
+ for (int i = 0; i < blockWidth*blockHeight; i++)
+ for (int c = 0; c < 4; c++)
+ dstU[i*4 + c] = (deUint8)((rgba[c] & 0xff00) >> 8);
+ }
+ else
+ {
+ float* const dstF = (float*)dst;
+ if (isHDRBlock)
+ {
+ // rg - REMOVING HDR SUPPORT FOR NOW
+#if 0
+ for (int c = 0; c < 4; c++)
+ {
+ if (isFloat16InfOrNan((deFloat16)rgba[c]))
+ throw InternalError("Infinity or NaN color component in HDR void extent block in ASTC texture (behavior undefined by ASTC specification)");
+ }
+ for (int i = 0; i < blockWidth*blockHeight; i++)
+ for (int c = 0; c < 4; c++)
+ dstF[i*4 + c] = deFloat16To32((deFloat16)rgba[c]);
+#endif
+ }
+ else
+ {
+ for (int i = 0; i < blockWidth*blockHeight; i++)
+ for (int c = 0; c < 4; c++)
+ dstF[i*4 + c] = rgba[c] == 65535 ? 1.0f : (float)rgba[c] / 65536.0f;
+ }
+ }
+ return DECOMPRESS_RESULT_VALID_BLOCK;
+}
+void decodeColorEndpointModes (deUint32* endpointModesDst, const Block128& blockData, int numPartitions, int extraCemBitsStart)
+{
+ if (numPartitions == 1)
+ endpointModesDst[0] = blockData.getBits(13, 16);
+ else
+ {
+ const deUint32 highLevelSelector = blockData.getBits(23, 24);
+ if (highLevelSelector == 0)
+ {
+ const deUint32 mode = blockData.getBits(25, 28);
+ for (int i = 0; i < numPartitions; i++)
+ endpointModesDst[i] = mode;
+ }
+ else
+ {
+ for (int partNdx = 0; partNdx < numPartitions; partNdx++)
+ {
+ const deUint32 cemClass = highLevelSelector - (blockData.isBitSet(25 + partNdx) ? 0 : 1);
+ const deUint32 lowBit0Ndx = numPartitions + 2*partNdx;
+ const deUint32 lowBit1Ndx = numPartitions + 2*partNdx + 1;
+ const deUint32 lowBit0 = blockData.getBit(lowBit0Ndx < 4 ? 25+lowBit0Ndx : extraCemBitsStart+lowBit0Ndx-4);
+ const deUint32 lowBit1 = blockData.getBit(lowBit1Ndx < 4 ? 25+lowBit1Ndx : extraCemBitsStart+lowBit1Ndx-4);
+ endpointModesDst[partNdx] = (cemClass << 2) | (lowBit1 << 1) | lowBit0;
+ }
+ }
+ }
+}
+int computeNumColorEndpointValues (const deUint32* endpointModes, int numPartitions)
+{
+ int result = 0;
+ for (int i = 0; i < numPartitions; i++)
+ result += computeNumColorEndpointValues(endpointModes[i]);
+ return result;
+}
+void decodeISETritBlock (ISEDecodedResult* dst, int numValues, BitAccessStream& data, int numBits)
+{
+ DE_ASSERT(basisu_astc::inRange(numValues, 1, 5));
+ deUint32 m[5];
+ m[0] = data.getNext(numBits);
+ deUint32 T01 = data.getNext(2);
+ m[1] = data.getNext(numBits);
+ deUint32 T23 = data.getNext(2);
+ m[2] = data.getNext(numBits);
+ deUint32 T4 = data.getNext(1);
+ m[3] = data.getNext(numBits);
+ deUint32 T56 = data.getNext(2);
+ m[4] = data.getNext(numBits);
+ deUint32 T7 = data.getNext(1);
+ switch (numValues)
+ {
+ // \note Fall-throughs.
+ case 1: T23 = 0;
+ case 2: T4 = 0;
+ case 3: T56 = 0;
+ case 4: T7 = 0;
+ case 5: break;
+ default:
+ DE_ASSERT(false);
+ }
+ const deUint32 T = (T7 << 7) | (T56 << 5) | (T4 << 4) | (T23 << 2) | (T01 << 0);
+ static const deUint32 tritsFromT[256][5] =
+ {
+ { 0,0,0,0,0 }, { 1,0,0,0,0 }, { 2,0,0,0,0 }, { 0,0,2,0,0 }, { 0,1,0,0,0 }, { 1,1,0,0,0 }, { 2,1,0,0,0 }, { 1,0,2,0,0 }, { 0,2,0,0,0 }, { 1,2,0,0,0 }, { 2,2,0,0,0 }, { 2,0,2,0,0 }, { 0,2,2,0,0 }, { 1,2,2,0,0 }, { 2,2,2,0,0 }, { 2,0,2,0,0 },
+ { 0,0,1,0,0 }, { 1,0,1,0,0 }, { 2,0,1,0,0 }, { 0,1,2,0,0 }, { 0,1,1,0,0 }, { 1,1,1,0,0 }, { 2,1,1,0,0 }, { 1,1,2,0,0 }, { 0,2,1,0,0 }, { 1,2,1,0,0 }, { 2,2,1,0,0 }, { 2,1,2,0,0 }, { 0,0,0,2,2 }, { 1,0,0,2,2 }, { 2,0,0,2,2 }, { 0,0,2,2,2 },
+ { 0,0,0,1,0 }, { 1,0,0,1,0 }, { 2,0,0,1,0 }, { 0,0,2,1,0 }, { 0,1,0,1,0 }, { 1,1,0,1,0 }, { 2,1,0,1,0 }, { 1,0,2,1,0 }, { 0,2,0,1,0 }, { 1,2,0,1,0 }, { 2,2,0,1,0 }, { 2,0,2,1,0 }, { 0,2,2,1,0 }, { 1,2,2,1,0 }, { 2,2,2,1,0 }, { 2,0,2,1,0 },
+ { 0,0,1,1,0 }, { 1,0,1,1,0 }, { 2,0,1,1,0 }, { 0,1,2,1,0 }, { 0,1,1,1,0 }, { 1,1,1,1,0 }, { 2,1,1,1,0 }, { 1,1,2,1,0 }, { 0,2,1,1,0 }, { 1,2,1,1,0 }, { 2,2,1,1,0 }, { 2,1,2,1,0 }, { 0,1,0,2,2 }, { 1,1,0,2,2 }, { 2,1,0,2,2 }, { 1,0,2,2,2 },
+ { 0,0,0,2,0 }, { 1,0,0,2,0 }, { 2,0,0,2,0 }, { 0,0,2,2,0 }, { 0,1,0,2,0 }, { 1,1,0,2,0 }, { 2,1,0,2,0 }, { 1,0,2,2,0 }, { 0,2,0,2,0 }, { 1,2,0,2,0 }, { 2,2,0,2,0 }, { 2,0,2,2,0 }, { 0,2,2,2,0 }, { 1,2,2,2,0 }, { 2,2,2,2,0 }, { 2,0,2,2,0 },
+ { 0,0,1,2,0 }, { 1,0,1,2,0 }, { 2,0,1,2,0 }, { 0,1,2,2,0 }, { 0,1,1,2,0 }, { 1,1,1,2,0 }, { 2,1,1,2,0 }, { 1,1,2,2,0 }, { 0,2,1,2,0 }, { 1,2,1,2,0 }, { 2,2,1,2,0 }, { 2,1,2,2,0 }, { 0,2,0,2,2 }, { 1,2,0,2,2 }, { 2,2,0,2,2 }, { 2,0,2,2,2 },
+ { 0,0,0,0,2 }, { 1,0,0,0,2 }, { 2,0,0,0,2 }, { 0,0,2,0,2 }, { 0,1,0,0,2 }, { 1,1,0,0,2 }, { 2,1,0,0,2 }, { 1,0,2,0,2 }, { 0,2,0,0,2 }, { 1,2,0,0,2 }, { 2,2,0,0,2 }, { 2,0,2,0,2 }, { 0,2,2,0,2 }, { 1,2,2,0,2 }, { 2,2,2,0,2 }, { 2,0,2,0,2 },
+ { 0,0,1,0,2 }, { 1,0,1,0,2 }, { 2,0,1,0,2 }, { 0,1,2,0,2 }, { 0,1,1,0,2 }, { 1,1,1,0,2 }, { 2,1,1,0,2 }, { 1,1,2,0,2 }, { 0,2,1,0,2 }, { 1,2,1,0,2 }, { 2,2,1,0,2 }, { 2,1,2,0,2 }, { 0,2,2,2,2 }, { 1,2,2,2,2 }, { 2,2,2,2,2 }, { 2,0,2,2,2 },
+ { 0,0,0,0,1 }, { 1,0,0,0,1 }, { 2,0,0,0,1 }, { 0,0,2,0,1 }, { 0,1,0,0,1 }, { 1,1,0,0,1 }, { 2,1,0,0,1 }, { 1,0,2,0,1 }, { 0,2,0,0,1 }, { 1,2,0,0,1 }, { 2,2,0,0,1 }, { 2,0,2,0,1 }, { 0,2,2,0,1 }, { 1,2,2,0,1 }, { 2,2,2,0,1 }, { 2,0,2,0,1 },
+ { 0,0,1,0,1 }, { 1,0,1,0,1 }, { 2,0,1,0,1 }, { 0,1,2,0,1 }, { 0,1,1,0,1 }, { 1,1,1,0,1 }, { 2,1,1,0,1 }, { 1,1,2,0,1 }, { 0,2,1,0,1 }, { 1,2,1,0,1 }, { 2,2,1,0,1 }, { 2,1,2,0,1 }, { 0,0,1,2,2 }, { 1,0,1,2,2 }, { 2,0,1,2,2 }, { 0,1,2,2,2 },
+ { 0,0,0,1,1 }, { 1,0,0,1,1 }, { 2,0,0,1,1 }, { 0,0,2,1,1 }, { 0,1,0,1,1 }, { 1,1,0,1,1 }, { 2,1,0,1,1 }, { 1,0,2,1,1 }, { 0,2,0,1,1 }, { 1,2,0,1,1 }, { 2,2,0,1,1 }, { 2,0,2,1,1 }, { 0,2,2,1,1 }, { 1,2,2,1,1 }, { 2,2,2,1,1 }, { 2,0,2,1,1 },
+ { 0,0,1,1,1 }, { 1,0,1,1,1 }, { 2,0,1,1,1 }, { 0,1,2,1,1 }, { 0,1,1,1,1 }, { 1,1,1,1,1 }, { 2,1,1,1,1 }, { 1,1,2,1,1 }, { 0,2,1,1,1 }, { 1,2,1,1,1 }, { 2,2,1,1,1 }, { 2,1,2,1,1 }, { 0,1,1,2,2 }, { 1,1,1,2,2 }, { 2,1,1,2,2 }, { 1,1,2,2,2 },
+ { 0,0,0,2,1 }, { 1,0,0,2,1 }, { 2,0,0,2,1 }, { 0,0,2,2,1 }, { 0,1,0,2,1 }, { 1,1,0,2,1 }, { 2,1,0,2,1 }, { 1,0,2,2,1 }, { 0,2,0,2,1 }, { 1,2,0,2,1 }, { 2,2,0,2,1 }, { 2,0,2,2,1 }, { 0,2,2,2,1 }, { 1,2,2,2,1 }, { 2,2,2,2,1 }, { 2,0,2,2,1 },
+ { 0,0,1,2,1 }, { 1,0,1,2,1 }, { 2,0,1,2,1 }, { 0,1,2,2,1 }, { 0,1,1,2,1 }, { 1,1,1,2,1 }, { 2,1,1,2,1 }, { 1,1,2,2,1 }, { 0,2,1,2,1 }, { 1,2,1,2,1 }, { 2,2,1,2,1 }, { 2,1,2,2,1 }, { 0,2,1,2,2 }, { 1,2,1,2,2 }, { 2,2,1,2,2 }, { 2,1,2,2,2 },
+ { 0,0,0,1,2 }, { 1,0,0,1,2 }, { 2,0,0,1,2 }, { 0,0,2,1,2 }, { 0,1,0,1,2 }, { 1,1,0,1,2 }, { 2,1,0,1,2 }, { 1,0,2,1,2 }, { 0,2,0,1,2 }, { 1,2,0,1,2 }, { 2,2,0,1,2 }, { 2,0,2,1,2 }, { 0,2,2,1,2 }, { 1,2,2,1,2 }, { 2,2,2,1,2 }, { 2,0,2,1,2 },
+ { 0,0,1,1,2 }, { 1,0,1,1,2 }, { 2,0,1,1,2 }, { 0,1,2,1,2 }, { 0,1,1,1,2 }, { 1,1,1,1,2 }, { 2,1,1,1,2 }, { 1,1,2,1,2 }, { 0,2,1,1,2 }, { 1,2,1,1,2 }, { 2,2,1,1,2 }, { 2,1,2,1,2 }, { 0,2,2,2,2 }, { 1,2,2,2,2 }, { 2,2,2,2,2 }, { 2,1,2,2,2 }
+ };
+ const deUint32 (& trits)[5] = tritsFromT[T];
+ for (int i = 0; i < numValues; i++)
+ {
+ dst[i].m = m[i];
+ dst[i].tq = trits[i];
+ dst[i].v = (trits[i] << numBits) + m[i];
+ }
+}
+void decodeISEQuintBlock (ISEDecodedResult* dst, int numValues, BitAccessStream& data, int numBits)
+{
+ DE_ASSERT(basisu_astc::inRange(numValues, 1, 3));
+ deUint32 m[3];
+ m[0] = data.getNext(numBits);
+ deUint32 Q012 = data.getNext(3);
+ m[1] = data.getNext(numBits);
+ deUint32 Q34 = data.getNext(2);
+ m[2] = data.getNext(numBits);
+ deUint32 Q56 = data.getNext(2);
+ switch (numValues)
+ {
+ // \note Fall-throughs.
+ case 1: Q34 = 0;
+ case 2: Q56 = 0;
+ case 3: break;
+ default:
+ DE_ASSERT(false);
+ }
+ const deUint32 Q = (Q56 << 5) | (Q34 << 3) | (Q012 << 0);
+ static const deUint32 quintsFromQ[256][3] =
+ {
+ { 0,0,0 }, { 1,0,0 }, { 2,0,0 }, { 3,0,0 }, { 4,0,0 }, { 0,4,0 }, { 4,4,0 }, { 4,4,4 }, { 0,1,0 }, { 1,1,0 }, { 2,1,0 }, { 3,1,0 }, { 4,1,0 }, { 1,4,0 }, { 4,4,1 }, { 4,4,4 },
+ { 0,2,0 }, { 1,2,0 }, { 2,2,0 }, { 3,2,0 }, { 4,2,0 }, { 2,4,0 }, { 4,4,2 }, { 4,4,4 }, { 0,3,0 }, { 1,3,0 }, { 2,3,0 }, { 3,3,0 }, { 4,3,0 }, { 3,4,0 }, { 4,4,3 }, { 4,4,4 },
+ { 0,0,1 }, { 1,0,1 }, { 2,0,1 }, { 3,0,1 }, { 4,0,1 }, { 0,4,1 }, { 4,0,4 }, { 0,4,4 }, { 0,1,1 }, { 1,1,1 }, { 2,1,1 }, { 3,1,1 }, { 4,1,1 }, { 1,4,1 }, { 4,1,4 }, { 1,4,4 },
+ { 0,2,1 }, { 1,2,1 }, { 2,2,1 }, { 3,2,1 }, { 4,2,1 }, { 2,4,1 }, { 4,2,4 }, { 2,4,4 }, { 0,3,1 }, { 1,3,1 }, { 2,3,1 }, { 3,3,1 }, { 4,3,1 }, { 3,4,1 }, { 4,3,4 }, { 3,4,4 },
+ { 0,0,2 }, { 1,0,2 }, { 2,0,2 }, { 3,0,2 }, { 4,0,2 }, { 0,4,2 }, { 2,0,4 }, { 3,0,4 }, { 0,1,2 }, { 1,1,2 }, { 2,1,2 }, { 3,1,2 }, { 4,1,2 }, { 1,4,2 }, { 2,1,4 }, { 3,1,4 },
+ { 0,2,2 }, { 1,2,2 }, { 2,2,2 }, { 3,2,2 }, { 4,2,2 }, { 2,4,2 }, { 2,2,4 }, { 3,2,4 }, { 0,3,2 }, { 1,3,2 }, { 2,3,2 }, { 3,3,2 }, { 4,3,2 }, { 3,4,2 }, { 2,3,4 }, { 3,3,4 },
+ { 0,0,3 }, { 1,0,3 }, { 2,0,3 }, { 3,0,3 }, { 4,0,3 }, { 0,4,3 }, { 0,0,4 }, { 1,0,4 }, { 0,1,3 }, { 1,1,3 }, { 2,1,3 }, { 3,1,3 }, { 4,1,3 }, { 1,4,3 }, { 0,1,4 }, { 1,1,4 },
+ { 0,2,3 }, { 1,2,3 }, { 2,2,3 }, { 3,2,3 }, { 4,2,3 }, { 2,4,3 }, { 0,2,4 }, { 1,2,4 }, { 0,3,3 }, { 1,3,3 }, { 2,3,3 }, { 3,3,3 }, { 4,3,3 }, { 3,4,3 }, { 0,3,4 }, { 1,3,4 }
+ };
+ const deUint32 (& quints)[3] = quintsFromQ[Q];
+ for (int i = 0; i < numValues; i++)
+ {
+ dst[i].m = m[i];
+ dst[i].tq = quints[i];
+ dst[i].v = (quints[i] << numBits) + m[i];
+ }
+}
+inline void decodeISEBitBlock (ISEDecodedResult* dst, BitAccessStream& data, int numBits)
+{
+ dst[0].m = data.getNext(numBits);
+ dst[0].v = dst[0].m;
+}
+void decodeISE (ISEDecodedResult* dst, int numValues, BitAccessStream& data, const ISEParams& params)
+{
+ if (params.mode == ISEMODE_TRIT)
+ {
+ const int numBlocks = deDivRoundUp32(numValues, 5);
+ for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
+ {
+ const int numValuesInBlock = blockNdx == numBlocks-1 ? numValues - 5*(numBlocks-1) : 5;
+ decodeISETritBlock(&dst[5*blockNdx], numValuesInBlock, data, params.numBits);
+ }
+ }
+ else if (params.mode == ISEMODE_QUINT)
+ {
+ const int numBlocks = deDivRoundUp32(numValues, 3);
+ for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
+ {
+ const int numValuesInBlock = blockNdx == numBlocks-1 ? numValues - 3*(numBlocks-1) : 3;
+ decodeISEQuintBlock(&dst[3*blockNdx], numValuesInBlock, data, params.numBits);
+ }
+ }
+ else
+ {
+ DE_ASSERT(params.mode == ISEMODE_PLAIN_BIT);
+ for (int i = 0; i < numValues; i++)
+ decodeISEBitBlock(&dst[i], data, params.numBits);
+ }
+}
+void unquantizeColorEndpoints (deUint32* dst, const ISEDecodedResult* iseResults, int numEndpoints, const ISEParams& iseParams)
+{
+ if (iseParams.mode == ISEMODE_TRIT || iseParams.mode == ISEMODE_QUINT)
+ {
+ const int rangeCase = iseParams.numBits*2 - (iseParams.mode == ISEMODE_TRIT ? 2 : 1);
+ DE_ASSERT(basisu_astc::inRange(rangeCase, 0, 10));
+ static const deUint32 Ca[11] = { 204, 113, 93, 54, 44, 26, 22, 13, 11, 6, 5 };
+ const deUint32 C = Ca[rangeCase];
+ for (int endpointNdx = 0; endpointNdx < numEndpoints; endpointNdx++)
+ {
+ const deUint32 a = getBit(iseResults[endpointNdx].m, 0);
+ const deUint32 b = getBit(iseResults[endpointNdx].m, 1);
+ const deUint32 c = getBit(iseResults[endpointNdx].m, 2);
+ const deUint32 d = getBit(iseResults[endpointNdx].m, 3);
+ const deUint32 e = getBit(iseResults[endpointNdx].m, 4);
+ const deUint32 f = getBit(iseResults[endpointNdx].m, 5);
+ const deUint32 A = a == 0 ? 0 : (1<<9)-1;
+ const deUint32 B = rangeCase == 0 ? 0
+ : rangeCase == 1 ? 0
+ : rangeCase == 2 ? (b << 8) | (b << 4) | (b << 2) | (b << 1)
+ : rangeCase == 3 ? (b << 8) | (b << 3) | (b << 2)
+ : rangeCase == 4 ? (c << 8) | (b << 7) | (c << 3) | (b << 2) | (c << 1) | (b << 0)
+ : rangeCase == 5 ? (c << 8) | (b << 7) | (c << 2) | (b << 1) | (c << 0)
+ : rangeCase == 6 ? (d << 8) | (c << 7) | (b << 6) | (d << 2) | (c << 1) | (b << 0)
+ : rangeCase == 7 ? (d << 8) | (c << 7) | (b << 6) | (d << 1) | (c << 0)
+ : rangeCase == 8 ? (e << 8) | (d << 7) | (c << 6) | (b << 5) | (e << 1) | (d << 0)
+ : rangeCase == 9 ? (e << 8) | (d << 7) | (c << 6) | (b << 5) | (e << 0)
+ : rangeCase == 10 ? (f << 8) | (e << 7) | (d << 6) | (c << 5) | (b << 4) | (f << 0)
+ : (deUint32)-1;
+ DE_ASSERT(B != (deUint32)-1);
+ dst[endpointNdx] = (((iseResults[endpointNdx].tq*C + B) ^ A) >> 2) | (A & 0x80);
+ }
+ }
+ else
+ {
+ DE_ASSERT(iseParams.mode == ISEMODE_PLAIN_BIT);
+ for (int endpointNdx = 0; endpointNdx < numEndpoints; endpointNdx++)
+ dst[endpointNdx] = bitReplicationScale(iseResults[endpointNdx].v, iseParams.numBits, 8);
+ }
+}
+inline void bitTransferSigned (deInt32& a, deInt32& b)
+{
+ b >>= 1;
+ b |= a & 0x80;
+ a >>= 1;
+ a &= 0x3f;
+ if (isBitSet(a, 5))
+ a -= 0x40;
+}
+inline UVec4 clampedRGBA (const IVec4& rgba)
+{
+ return UVec4(basisu_astc::clamp(rgba.x(), 0, 0xff),
+ basisu_astc::clamp(rgba.y(), 0, 0xff),
+ basisu_astc::clamp(rgba.z(), 0, 0xff),
+ basisu_astc::clamp(rgba.w(), 0, 0xff));
+}
+inline IVec4 blueContract (int r, int g, int b, int a)
+{
+ return IVec4((r+b)>>1, (g+b)>>1, b, a);
+}
+inline bool isColorEndpointModeHDR (deUint32 mode)
+{
+ return mode == 2 ||
+ mode == 3 ||
+ mode == 7 ||
+ mode == 11 ||
+ mode == 14 ||
+ mode == 15;
+}
+void decodeHDREndpointMode7 (UVec4& e0, UVec4& e1, deUint32 v0, deUint32 v1, deUint32 v2, deUint32 v3)
+{
+ const deUint32 m10 = getBit(v1, 7) | (getBit(v2, 7) << 1);
+ const deUint32 m23 = getBits(v0, 6, 7);
+ const deUint32 majComp = m10 != 3 ? m10
+ : m23 != 3 ? m23
+ : 0;
+ const deUint32 mode = m10 != 3 ? m23
+ : m23 != 3 ? 4
+ : 5;
+ deInt32 red = (deInt32)getBits(v0, 0, 5);
+ deInt32 green = (deInt32)getBits(v1, 0, 4);
+ deInt32 blue = (deInt32)getBits(v2, 0, 4);
+ deInt32 scale = (deInt32)getBits(v3, 0, 4);
+ {
+#define SHOR(DST_VAR, SHIFT, BIT_VAR) (DST_VAR) |= (BIT_VAR) << (SHIFT)
+#define ASSIGN_X_BITS(V0,S0, V1,S1, V2,S2, V3,S3, V4,S4, V5,S5, V6,S6) do { SHOR(V0,S0,x0); SHOR(V1,S1,x1); SHOR(V2,S2,x2); SHOR(V3,S3,x3); SHOR(V4,S4,x4); SHOR(V5,S5,x5); SHOR(V6,S6,x6); } while (false)
+ const deUint32 x0 = getBit(v1, 6);
+ const deUint32 x1 = getBit(v1, 5);
+ const deUint32 x2 = getBit(v2, 6);
+ const deUint32 x3 = getBit(v2, 5);
+ const deUint32 x4 = getBit(v3, 7);
+ const deUint32 x5 = getBit(v3, 6);
+ const deUint32 x6 = getBit(v3, 5);
+ deInt32& R = red;
+ deInt32& G = green;
+ deInt32& B = blue;
+ deInt32& S = scale;
+ switch (mode)
+ {
+ case 0: ASSIGN_X_BITS(R,9, R,8, R,7, R,10, R,6, S,6, S,5); break;
+ case 1: ASSIGN_X_BITS(R,8, G,5, R,7, B,5, R,6, R,10, R,9); break;
+ case 2: ASSIGN_X_BITS(R,9, R,8, R,7, R,6, S,7, S,6, S,5); break;
+ case 3: ASSIGN_X_BITS(R,8, G,5, R,7, B,5, R,6, S,6, S,5); break;
+ case 4: ASSIGN_X_BITS(G,6, G,5, B,6, B,5, R,6, R,7, S,5); break;
+ case 5: ASSIGN_X_BITS(G,6, G,5, B,6, B,5, R,6, S,6, S,5); break;
+ default:
+ DE_ASSERT(false);
+ }
+#undef ASSIGN_X_BITS
+#undef SHOR
+ }
+ static const int shiftAmounts[] = { 1, 1, 2, 3, 4, 5 };
+ DE_ASSERT(mode < DE_LENGTH_OF_ARRAY(shiftAmounts));
+ red <<= shiftAmounts[mode];
+ green <<= shiftAmounts[mode];
+ blue <<= shiftAmounts[mode];
+ scale <<= shiftAmounts[mode];
+ if (mode != 5)
+ {
+ green = red - green;
+ blue = red - blue;
+ }
+ if (majComp == 1)
+ std::swap(red, green);
+ else if (majComp == 2)
+ std::swap(red, blue);
+ e0 = UVec4(basisu_astc::clamp(red - scale, 0, 0xfff),
+ basisu_astc::clamp(green - scale, 0, 0xfff),
+ basisu_astc::clamp(blue - scale, 0, 0xfff),
+ 0x780);
+ e1 = UVec4(basisu_astc::clamp(red, 0, 0xfff),
+ basisu_astc::clamp(green, 0, 0xfff),
+ basisu_astc::clamp(blue, 0, 0xfff),
+ 0x780);
+}
+void decodeHDREndpointMode11 (UVec4& e0, UVec4& e1, deUint32 v0, deUint32 v1, deUint32 v2, deUint32 v3, deUint32 v4, deUint32 v5)
+{
+ const deUint32 major = (getBit(v5, 7) << 1) | getBit(v4, 7);
+ if (major == 3)
+ {
+ e0 = UVec4(v0<<4, v2<<4, getBits(v4,0,6)<<5, 0x780);
+ e1 = UVec4(v1<<4, v3<<4, getBits(v5,0,6)<<5, 0x780);
+ }
+ else
+ {
+ const deUint32 mode = (getBit(v3, 7) << 2) | (getBit(v2, 7) << 1) | getBit(v1, 7);
+ deInt32 a = (deInt32)((getBit(v1, 6) << 8) | v0);
+ deInt32 c = (deInt32)(getBits(v1, 0, 5));
+ deInt32 b0 = (deInt32)(getBits(v2, 0, 5));
+ deInt32 b1 = (deInt32)(getBits(v3, 0, 5));
+ deInt32 d0 = (deInt32)(getBits(v4, 0, 4));
+ deInt32 d1 = (deInt32)(getBits(v5, 0, 4));
+ {
+#define SHOR(DST_VAR, SHIFT, BIT_VAR) (DST_VAR) |= (BIT_VAR) << (SHIFT)
+#define ASSIGN_X_BITS(V0,S0, V1,S1, V2,S2, V3,S3, V4,S4, V5,S5) do { SHOR(V0,S0,x0); SHOR(V1,S1,x1); SHOR(V2,S2,x2); SHOR(V3,S3,x3); SHOR(V4,S4,x4); SHOR(V5,S5,x5); } while (false)
+ const deUint32 x0 = getBit(v2, 6);
+ const deUint32 x1 = getBit(v3, 6);
+ const deUint32 x2 = getBit(v4, 6);
+ const deUint32 x3 = getBit(v5, 6);
+ const deUint32 x4 = getBit(v4, 5);
+ const deUint32 x5 = getBit(v5, 5);
+ switch (mode)
+ {
+ case 0: ASSIGN_X_BITS(b0,6, b1,6, d0,6, d1,6, d0,5, d1,5); break;
+ case 1: ASSIGN_X_BITS(b0,6, b1,6, b0,7, b1,7, d0,5, d1,5); break;
+ case 2: ASSIGN_X_BITS(a,9, c,6, d0,6, d1,6, d0,5, d1,5); break;
+ case 3: ASSIGN_X_BITS(b0,6, b1,6, a,9, c,6, d0,5, d1,5); break;
+ case 4: ASSIGN_X_BITS(b0,6, b1,6, b0,7, b1,7, a,9, a,10); break;
+ case 5: ASSIGN_X_BITS(a,9, a,10, c,7, c,6, d0,5, d1,5); break;
+ case 6: ASSIGN_X_BITS(b0,6, b1,6, a,11, c,6, a,9, a,10); break;
+ case 7: ASSIGN_X_BITS(a,9, a,10, a,11, c,6, d0,5, d1,5); break;
+ default:
+ DE_ASSERT(false);
+ }
+#undef ASSIGN_X_BITS
+#undef SHOR
+ }
+ static const int numDBits[] = { 7, 6, 7, 6, 5, 6, 5, 6 };
+ DE_ASSERT(mode < DE_LENGTH_OF_ARRAY(numDBits));
+ d0 = signExtend(d0, numDBits[mode]);
+ d1 = signExtend(d1, numDBits[mode]);
+ const int shiftAmount = (mode >> 1) ^ 3;
+ a <<= shiftAmount;
+ c <<= shiftAmount;
+ b0 <<= shiftAmount;
+ b1 <<= shiftAmount;
+ d0 <<= shiftAmount;
+ d1 <<= shiftAmount;
+ e0 = UVec4(basisu_astc::clamp(a-c, 0, 0xfff),
+ basisu_astc::clamp(a-b0-c-d0, 0, 0xfff),
+ basisu_astc::clamp(a-b1-c-d1, 0, 0xfff),
+ 0x780);
+ e1 = UVec4(basisu_astc::clamp(a, 0, 0xfff),
+ basisu_astc::clamp(a-b0, 0, 0xfff),
+ basisu_astc::clamp(a-b1, 0, 0xfff),
+ 0x780);
+ if (major == 1)
+ {
+ std::swap(e0.x(), e0.y());
+ std::swap(e1.x(), e1.y());
+ }
+ else if (major == 2)
+ {
+ std::swap(e0.x(), e0.z());
+ std::swap(e1.x(), e1.z());
+ }
+ }
+}
+void decodeHDREndpointMode15(UVec4& e0, UVec4& e1, deUint32 v0, deUint32 v1, deUint32 v2, deUint32 v3, deUint32 v4, deUint32 v5, deUint32 v6In, deUint32 v7In)
+{
+ decodeHDREndpointMode11(e0, e1, v0, v1, v2, v3, v4, v5);
+ const deUint32 mode = (getBit(v7In, 7) << 1) | getBit(v6In, 7);
+ deInt32 v6 = (deInt32)getBits(v6In, 0, 6);
+ deInt32 v7 = (deInt32)getBits(v7In, 0, 6);
+ if (mode == 3)
+ {
+ e0.w() = v6 << 5;
+ e1.w() = v7 << 5;
+ }
+ else
+ {
+ v6 |= (v7 << (mode+1)) & 0x780;
+ v7 &= (0x3f >> mode);
+ v7 ^= 0x20 >> mode;
+ v7 -= 0x20 >> mode;
+ v6 <<= 4-mode;
+ v7 <<= 4-mode;
+ v7 += v6;
+ v7 = basisu_astc::clamp(v7, 0, 0xfff);
+ e0.w() = v6;
+ e1.w() = v7;
+ }
+}
+void decodeColorEndpoints (ColorEndpointPair* dst, const deUint32* unquantizedEndpoints, const deUint32* endpointModes, int numPartitions)
+{
+ int unquantizedNdx = 0;
+ for (int partitionNdx = 0; partitionNdx < numPartitions; partitionNdx++)
+ {
+ const deUint32 endpointMode = endpointModes[partitionNdx];
+ const deUint32* v = &unquantizedEndpoints[unquantizedNdx];
+ UVec4& e0 = dst[partitionNdx].e0;
+ UVec4& e1 = dst[partitionNdx].e1;
+ unquantizedNdx += computeNumColorEndpointValues(endpointMode);
+ switch (endpointMode)
+ {
+ case 0:
+ e0 = UVec4(v[0], v[0], v[0], 0xff);
+ e1 = UVec4(v[1], v[1], v[1], 0xff);
+ break;
+ case 1:
+ {
+ const deUint32 L0 = (v[0] >> 2) | (getBits(v[1], 6, 7) << 6);
+ const deUint32 L1 = basisu_astc::min(0xffu, L0 + getBits(v[1], 0, 5));
+ e0 = UVec4(L0, L0, L0, 0xff);
+ e1 = UVec4(L1, L1, L1, 0xff);
+ break;
+ }
+ case 2:
+ {
+ const deUint32 v1Gr = v[1] >= v[0];
+ const deUint32 y0 = v1Gr ? v[0]<<4 : (v[1]<<4) + 8;
+ const deUint32 y1 = v1Gr ? v[1]<<4 : (v[0]<<4) - 8;
+ e0 = UVec4(y0, y0, y0, 0x780);
+ e1 = UVec4(y1, y1, y1, 0x780);
+ break;
+ }
+ case 3:
+ {
+ const bool m = isBitSet(v[0], 7);
+ const deUint32 y0 = m ? (getBits(v[1], 5, 7) << 9) | (getBits(v[0], 0, 6) << 2)
+ : (getBits(v[1], 4, 7) << 8) | (getBits(v[0], 0, 6) << 1);
+ const deUint32 d = m ? getBits(v[1], 0, 4) << 2
+ : getBits(v[1], 0, 3) << 1;
+ const deUint32 y1 = basisu_astc::min(0xfffu, y0+d);
+ e0 = UVec4(y0, y0, y0, 0x780);
+ e1 = UVec4(y1, y1, y1, 0x780);
+ break;
+ }
+ case 4:
+ e0 = UVec4(v[0], v[0], v[0], v[2]);
+ e1 = UVec4(v[1], v[1], v[1], v[3]);
+ break;
+ case 5:
+ {
+ deInt32 v0 = (deInt32)v[0];
+ deInt32 v1 = (deInt32)v[1];
+ deInt32 v2 = (deInt32)v[2];
+ deInt32 v3 = (deInt32)v[3];
+ bitTransferSigned(v1, v0);
+ bitTransferSigned(v3, v2);
+ e0 = clampedRGBA(IVec4(v0, v0, v0, v2));
+ e1 = clampedRGBA(IVec4(v0+v1, v0+v1, v0+v1, v2+v3));
+ break;
+ }
+ case 6:
+ e0 = UVec4((v[0]*v[3]) >> 8, (v[1]*v[3]) >> 8, (v[2]*v[3]) >> 8, 0xff);
+ e1 = UVec4(v[0], v[1], v[2], 0xff);
+ break;
+ case 7:
+ decodeHDREndpointMode7(e0, e1, v[0], v[1], v[2], v[3]);
+ break;
+ case 8:
+ if (v[1]+v[3]+v[5] >= v[0]+v[2]+v[4])
+ {
+ e0 = UVec4(v[0], v[2], v[4], 0xff);
+ e1 = UVec4(v[1], v[3], v[5], 0xff);
+ }
+ else
+ {
+ e0 = blueContract(v[1], v[3], v[5], 0xff).asUint();
+ e1 = blueContract(v[0], v[2], v[4], 0xff).asUint();
+ }
+ break;
+ case 9:
+ {
+ deInt32 v0 = (deInt32)v[0];
+ deInt32 v1 = (deInt32)v[1];
+ deInt32 v2 = (deInt32)v[2];
+ deInt32 v3 = (deInt32)v[3];
+ deInt32 v4 = (deInt32)v[4];
+ deInt32 v5 = (deInt32)v[5];
+ bitTransferSigned(v1, v0);
+ bitTransferSigned(v3, v2);
+ bitTransferSigned(v5, v4);
+ if (v1+v3+v5 >= 0)
+ {
+ e0 = clampedRGBA(IVec4(v0, v2, v4, 0xff));
+ e1 = clampedRGBA(IVec4(v0+v1, v2+v3, v4+v5, 0xff));
+ }
+ else
+ {
+ e0 = clampedRGBA(blueContract(v0+v1, v2+v3, v4+v5, 0xff));
+ e1 = clampedRGBA(blueContract(v0, v2, v4, 0xff));
+ }
+ break;
+ }
+ case 10:
+ e0 = UVec4((v[0]*v[3]) >> 8, (v[1]*v[3]) >> 8, (v[2]*v[3]) >> 8, v[4]);
+ e1 = UVec4(v[0], v[1], v[2], v[5]);
+ break;
+ case 11:
+ decodeHDREndpointMode11(e0, e1, v[0], v[1], v[2], v[3], v[4], v[5]);
+ break;
+ case 12:
+ if (v[1]+v[3]+v[5] >= v[0]+v[2]+v[4])
+ {
+ e0 = UVec4(v[0], v[2], v[4], v[6]);
+ e1 = UVec4(v[1], v[3], v[5], v[7]);
+ }
+ else
+ {
+ e0 = clampedRGBA(blueContract(v[1], v[3], v[5], v[7]));
+ e1 = clampedRGBA(blueContract(v[0], v[2], v[4], v[6]));
+ }
+ break;
+ case 13:
+ {
+ deInt32 v0 = (deInt32)v[0];
+ deInt32 v1 = (deInt32)v[1];
+ deInt32 v2 = (deInt32)v[2];
+ deInt32 v3 = (deInt32)v[3];
+ deInt32 v4 = (deInt32)v[4];
+ deInt32 v5 = (deInt32)v[5];
+ deInt32 v6 = (deInt32)v[6];
+ deInt32 v7 = (deInt32)v[7];
+ bitTransferSigned(v1, v0);
+ bitTransferSigned(v3, v2);
+ bitTransferSigned(v5, v4);
+ bitTransferSigned(v7, v6);
+ if (v1+v3+v5 >= 0)
+ {
+ e0 = clampedRGBA(IVec4(v0, v2, v4, v6));
+ e1 = clampedRGBA(IVec4(v0+v1, v2+v3, v4+v5, v6+v7));
+ }
+ else
+ {
+ e0 = clampedRGBA(blueContract(v0+v1, v2+v3, v4+v5, v6+v7));
+ e1 = clampedRGBA(blueContract(v0, v2, v4, v6));
+ }
+ break;
+ }
+ case 14:
+ decodeHDREndpointMode11(e0, e1, v[0], v[1], v[2], v[3], v[4], v[5]);
+ e0.w() = v[6];
+ e1.w() = v[7];
+ break;
+ case 15:
+ decodeHDREndpointMode15(e0, e1, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+ break;
+ default:
+ DE_ASSERT(false);
+ }
+ }
+}
+void computeColorEndpoints (ColorEndpointPair* dst, const Block128& blockData, const deUint32* endpointModes, int numPartitions, int numColorEndpointValues, const ISEParams& iseParams, int numBitsAvailable)
+{
+ const int colorEndpointDataStart = numPartitions == 1 ? 17 : 29;
+ ISEDecodedResult colorEndpointData[18];
+ {
+ BitAccessStream dataStream(blockData, colorEndpointDataStart, numBitsAvailable, true);
+ decodeISE(&colorEndpointData[0], numColorEndpointValues, dataStream, iseParams);
+ }
+ {
+ deUint32 unquantizedEndpoints[18];
+ unquantizeColorEndpoints(&unquantizedEndpoints[0], &colorEndpointData[0], numColorEndpointValues, iseParams);
+ decodeColorEndpoints(dst, &unquantizedEndpoints[0], &endpointModes[0], numPartitions);
+ }
+}
+void unquantizeWeights (deUint32 dst[64], const ISEDecodedResult* weightGrid, const ASTCBlockMode& blockMode)
+{
+ const int numWeights = computeNumWeights(blockMode);
+ const ISEParams& iseParams = blockMode.weightISEParams;
+ if (iseParams.mode == ISEMODE_TRIT || iseParams.mode == ISEMODE_QUINT)
+ {
+ const int rangeCase = iseParams.numBits*2 + (iseParams.mode == ISEMODE_QUINT ? 1 : 0);
+ if (rangeCase == 0 || rangeCase == 1)
+ {
+ static const deUint32 map0[3] = { 0, 32, 63 };
+ static const deUint32 map1[5] = { 0, 16, 32, 47, 63 };
+ const deUint32* const map = rangeCase == 0 ? &map0[0] : &map1[0];
+ for (int i = 0; i < numWeights; i++)
+ {
+ DE_ASSERT(weightGrid[i].v < (rangeCase == 0 ? 3u : 5u));
+ dst[i] = map[weightGrid[i].v];
+ }
+ }
+ else
+ {
+ DE_ASSERT(rangeCase <= 6);
+ static const deUint32 Ca[5] = { 50, 28, 23, 13, 11 };
+ const deUint32 C = Ca[rangeCase-2];
+ for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
+ {
+ const deUint32 a = getBit(weightGrid[weightNdx].m, 0);
+ const deUint32 b = getBit(weightGrid[weightNdx].m, 1);
+ const deUint32 c = getBit(weightGrid[weightNdx].m, 2);
+ const deUint32 A = a == 0 ? 0 : (1<<7)-1;
+ const deUint32 B = rangeCase == 2 ? 0
+ : rangeCase == 3 ? 0
+ : rangeCase == 4 ? (b << 6) | (b << 2) | (b << 0)
+ : rangeCase == 5 ? (b << 6) | (b << 1)
+ : rangeCase == 6 ? (c << 6) | (b << 5) | (c << 1) | (b << 0)
+ : (deUint32)-1;
+ dst[weightNdx] = (((weightGrid[weightNdx].tq*C + B) ^ A) >> 2) | (A & 0x20);
+ }
+ }
+ }
+ else
+ {
+ DE_ASSERT(iseParams.mode == ISEMODE_PLAIN_BIT);
+ for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
+ dst[weightNdx] = bitReplicationScale(weightGrid[weightNdx].v, iseParams.numBits, 6);
+ }
+ for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
+ dst[weightNdx] += dst[weightNdx] > 32 ? 1 : 0;
+ // Initialize nonexistent weights to poison values
+ for (int weightNdx = numWeights; weightNdx < 64; weightNdx++)
+ dst[weightNdx] = ~0u;
+}
+void interpolateWeights (TexelWeightPair* dst, const deUint32 (&unquantizedWeights) [64], int blockWidth, int blockHeight, const ASTCBlockMode& blockMode)
+{
+ const int numWeightsPerTexel = blockMode.isDualPlane ? 2 : 1;
+ const deUint32 scaleX = (1024 + blockWidth/2) / (blockWidth-1);
+ const deUint32 scaleY = (1024 + blockHeight/2) / (blockHeight-1);
+ DE_ASSERT(blockMode.weightGridWidth*blockMode.weightGridHeight*numWeightsPerTexel <= DE_LENGTH_OF_ARRAY(unquantizedWeights));
+ for (int texelY = 0; texelY < blockHeight; texelY++)
+ {
+ for (int texelX = 0; texelX < blockWidth; texelX++)
+ {
+ const deUint32 gX = (scaleX*texelX*(blockMode.weightGridWidth-1) + 32) >> 6;
+ const deUint32 gY = (scaleY*texelY*(blockMode.weightGridHeight-1) + 32) >> 6;
+ const deUint32 jX = gX >> 4;
+ const deUint32 jY = gY >> 4;
+ const deUint32 fX = gX & 0xf;
+ const deUint32 fY = gY & 0xf;
+ const deUint32 w11 = (fX*fY + 8) >> 4;
+ const deUint32 w10 = fY - w11;
+ const deUint32 w01 = fX - w11;
+ const deUint32 w00 = 16 - fX - fY + w11;
+ const deUint32 i00 = jY*blockMode.weightGridWidth + jX;
+ const deUint32 i01 = i00 + 1;
+ const deUint32 i10 = i00 + blockMode.weightGridWidth;
+ const deUint32 i11 = i00 + blockMode.weightGridWidth + 1;
+ // These addresses can be out of bounds, but respective weights will be 0 then.
+ DE_ASSERT(deInBounds32(i00, 0, blockMode.weightGridWidth*blockMode.weightGridHeight) || w00 == 0);
+ DE_ASSERT(deInBounds32(i01, 0, blockMode.weightGridWidth*blockMode.weightGridHeight) || w01 == 0);
+ DE_ASSERT(deInBounds32(i10, 0, blockMode.weightGridWidth*blockMode.weightGridHeight) || w10 == 0);
+ DE_ASSERT(deInBounds32(i11, 0, blockMode.weightGridWidth*blockMode.weightGridHeight) || w11 == 0);
+ for (int texelWeightNdx = 0; texelWeightNdx < numWeightsPerTexel; texelWeightNdx++)
+ {
+ // & 0x3f clamps address to bounds of unquantizedWeights
+ const deUint32 p00 = unquantizedWeights[(i00 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
+ const deUint32 p01 = unquantizedWeights[(i01 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
+ const deUint32 p10 = unquantizedWeights[(i10 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
+ const deUint32 p11 = unquantizedWeights[(i11 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
+ dst[texelY*blockWidth + texelX].w[texelWeightNdx] = (p00*w00 + p01*w01 + p10*w10 + p11*w11 + 8) >> 4;
+ }
+ }
+ }
+}
+void computeTexelWeights (TexelWeightPair* dst, const Block128& blockData, int blockWidth, int blockHeight, const ASTCBlockMode& blockMode)
+{
+ ISEDecodedResult weightGrid[64];
+ {
+ BitAccessStream dataStream(blockData, 127, computeNumRequiredBits(blockMode.weightISEParams, computeNumWeights(blockMode)), false);
+ decodeISE(&weightGrid[0], computeNumWeights(blockMode), dataStream, blockMode.weightISEParams);
+ }
+ {
+ deUint32 unquantizedWeights[64];
+ unquantizeWeights(&unquantizedWeights[0], &weightGrid[0], blockMode);
+ interpolateWeights(dst, unquantizedWeights, blockWidth, blockHeight, blockMode);
+ }
+}
+inline deUint32 hash52 (deUint32 v)
+{
+ deUint32 p = v;
+ p ^= p >> 15; p -= p << 17; p += p << 7; p += p << 4;
+ p ^= p >> 5; p += p << 16; p ^= p >> 7; p ^= p >> 3;
+ p ^= p << 6; p ^= p >> 17;
+ return p;
+}
+int computeTexelPartition (deUint32 seedIn, deUint32 xIn, deUint32 yIn, deUint32 zIn, int numPartitions, bool smallBlock)
+{
+ DE_ASSERT(zIn == 0);
+ const deUint32 x = smallBlock ? xIn << 1 : xIn;
+ const deUint32 y = smallBlock ? yIn << 1 : yIn;
+ const deUint32 z = smallBlock ? zIn << 1 : zIn;
+ const deUint32 seed = seedIn + 1024*(numPartitions-1);
+ const deUint32 rnum = hash52(seed);
+ deUint8 seed1 = (deUint8)( rnum & 0xf);
+ deUint8 seed2 = (deUint8)((rnum >> 4) & 0xf);
+ deUint8 seed3 = (deUint8)((rnum >> 8) & 0xf);
+ deUint8 seed4 = (deUint8)((rnum >> 12) & 0xf);
+ deUint8 seed5 = (deUint8)((rnum >> 16) & 0xf);
+ deUint8 seed6 = (deUint8)((rnum >> 20) & 0xf);
+ deUint8 seed7 = (deUint8)((rnum >> 24) & 0xf);
+ deUint8 seed8 = (deUint8)((rnum >> 28) & 0xf);
+ deUint8 seed9 = (deUint8)((rnum >> 18) & 0xf);
+ deUint8 seed10 = (deUint8)((rnum >> 22) & 0xf);
+ deUint8 seed11 = (deUint8)((rnum >> 26) & 0xf);
+ deUint8 seed12 = (deUint8)(((rnum >> 30) | (rnum << 2)) & 0xf);
+ seed1 = (deUint8)(seed1 * seed1 );
+ seed2 = (deUint8)(seed2 * seed2 );
+ seed3 = (deUint8)(seed3 * seed3 );
+ seed4 = (deUint8)(seed4 * seed4 );
+ seed5 = (deUint8)(seed5 * seed5 );
+ seed6 = (deUint8)(seed6 * seed6 );
+ seed7 = (deUint8)(seed7 * seed7 );
+ seed8 = (deUint8)(seed8 * seed8 );
+ seed9 = (deUint8)(seed9 * seed9 );
+ seed10 = (deUint8)(seed10 * seed10);
+ seed11 = (deUint8)(seed11 * seed11);
+ seed12 = (deUint8)(seed12 * seed12);
+ const int shA = (seed & 2) != 0 ? 4 : 5;
+ const int shB = numPartitions == 3 ? 6 : 5;
+ const int sh1 = (seed & 1) != 0 ? shA : shB;
+ const int sh2 = (seed & 1) != 0 ? shB : shA;
+ const int sh3 = (seed & 0x10) != 0 ? sh1 : sh2;
+ seed1 = (deUint8)(seed1 >> sh1);
+ seed2 = (deUint8)(seed2 >> sh2);
+ seed3 = (deUint8)(seed3 >> sh1);
+ seed4 = (deUint8)(seed4 >> sh2);
+ seed5 = (deUint8)(seed5 >> sh1);
+ seed6 = (deUint8)(seed6 >> sh2);
+ seed7 = (deUint8)(seed7 >> sh1);
+ seed8 = (deUint8)(seed8 >> sh2);
+ seed9 = (deUint8)(seed9 >> sh3);
+ seed10 = (deUint8)(seed10 >> sh3);
+ seed11 = (deUint8)(seed11 >> sh3);
+ seed12 = (deUint8)(seed12 >> sh3);
+ const int a = 0x3f & (seed1*x + seed2*y + seed11*z + (rnum >> 14));
+ const int b = 0x3f & (seed3*x + seed4*y + seed12*z + (rnum >> 10));
+ const int c = numPartitions >= 3 ? 0x3f & (seed5*x + seed6*y + seed9*z + (rnum >> 6)) : 0;
+ const int d = numPartitions >= 4 ? 0x3f & (seed7*x + seed8*y + seed10*z + (rnum >> 2)) : 0;
+ return a >= b && a >= c && a >= d ? 0
+ : b >= c && b >= d ? 1
+ : c >= d ? 2
+ : 3;
+}
+DecompressResult setTexelColors (void* dst, ColorEndpointPair* colorEndpoints, TexelWeightPair* texelWeights, int ccs, deUint32 partitionIndexSeed,
+ int numPartitions, int blockWidth, int blockHeight, bool isSRGB, bool isLDRMode, const deUint32* colorEndpointModes)
+{
+ const bool smallBlock = blockWidth*blockHeight < 31;
+ DecompressResult result = DECOMPRESS_RESULT_VALID_BLOCK;
+ bool isHDREndpoint[4];
+ for (int i = 0; i < numPartitions; i++)
+ {
+ isHDREndpoint[i] = isColorEndpointModeHDR(colorEndpointModes[i]);
+
+ // rg - REMOVING HDR SUPPORT FOR NOW
+ if (isHDREndpoint[i])
+ return DECOMPRESS_RESULT_ERROR;
+ }
+
+ for (int texelY = 0; texelY < blockHeight; texelY++)
+ for (int texelX = 0; texelX < blockWidth; texelX++)
+ {
+ const int texelNdx = texelY*blockWidth + texelX;
+ const int colorEndpointNdx = numPartitions == 1 ? 0 : computeTexelPartition(partitionIndexSeed, texelX, texelY, 0, numPartitions, smallBlock);
+ DE_ASSERT(colorEndpointNdx < numPartitions);
+ const UVec4& e0 = colorEndpoints[colorEndpointNdx].e0;
+ const UVec4& e1 = colorEndpoints[colorEndpointNdx].e1;
+ const TexelWeightPair& weight = texelWeights[texelNdx];
+ if (isLDRMode && isHDREndpoint[colorEndpointNdx])
+ {
+ if (isSRGB)
+ {
+ ((deUint8*)dst)[texelNdx*4 + 0] = 0xff;
+ ((deUint8*)dst)[texelNdx*4 + 1] = 0;
+ ((deUint8*)dst)[texelNdx*4 + 2] = 0xff;
+ ((deUint8*)dst)[texelNdx*4 + 3] = 0xff;
+ }
+ else
+ {
+ ((float*)dst)[texelNdx*4 + 0] = 1.0f;
+ ((float*)dst)[texelNdx*4 + 1] = 0;
+ ((float*)dst)[texelNdx*4 + 2] = 1.0f;
+ ((float*)dst)[texelNdx*4 + 3] = 1.0f;
+ }
+ result = DECOMPRESS_RESULT_ERROR;
+ }
+ else
+ {
+ for (int channelNdx = 0; channelNdx < 4; channelNdx++)
+ {
+ if (!isHDREndpoint[colorEndpointNdx] || (channelNdx == 3 && colorEndpointModes[colorEndpointNdx] == 14)) // \note Alpha for mode 14 is treated the same as LDR.
+ {
+ const deUint32 c0 = (e0[channelNdx] << 8) | (isSRGB ? 0x80 : e0[channelNdx]);
+ const deUint32 c1 = (e1[channelNdx] << 8) | (isSRGB ? 0x80 : e1[channelNdx]);
+ const deUint32 w = weight.w[ccs == channelNdx ? 1 : 0];
+ const deUint32 c = (c0*(64-w) + c1*w + 32) / 64;
+ if (isSRGB)
+ ((deUint8*)dst)[texelNdx*4 + channelNdx] = (deUint8)((c & 0xff00) >> 8);
+ else
+ ((float*)dst)[texelNdx*4 + channelNdx] = c == 65535 ? 1.0f : (float)c / 65536.0f;
+ }
+ else
+ {
+ //DE_STATIC_ASSERT((basisu_astc::meta::TypesSame<deFloat16, deUint16>::Value));
+ // rg - REMOVING HDR SUPPORT FOR NOW
+#if 0
+ const deUint32 c0 = e0[channelNdx] << 4;
+ const deUint32 c1 = e1[channelNdx] << 4;
+ const deUint32 w = weight.w[ccs == channelNdx ? 1 : 0];
+ const deUint32 c = (c0*(64-w) + c1*w + 32) / 64;
+ const deUint32 e = getBits(c, 11, 15);
+ const deUint32 m = getBits(c, 0, 10);
+ const deUint32 mt = m < 512 ? 3*m
+ : m >= 1536 ? 5*m - 2048
+ : 4*m - 512;
+ const deFloat16 cf = (deFloat16)((e << 10) + (mt >> 3));
+ ((float*)dst)[texelNdx*4 + channelNdx] = deFloat16To32(isFloat16InfOrNan(cf) ? 0x7bff : cf);
+#endif
+ }
+ }
+ }
+ }
+ return result;
+}
+DecompressResult decompressBlock (void* dst, const Block128& blockData, int blockWidth, int blockHeight, bool isSRGB, bool isLDR)
+{
+ DE_ASSERT(isLDR || !isSRGB);
+ // Decode block mode.
+ const ASTCBlockMode blockMode = getASTCBlockMode(blockData.getBits(0, 10));
+ // Check for block mode errors.
+ if (blockMode.isError)
+ {
+ setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
+ return DECOMPRESS_RESULT_ERROR;
+ }
+ // Separate path for void-extent.
+ if (blockMode.isVoidExtent)
+ return decodeVoidExtentBlock(dst, blockData, blockWidth, blockHeight, isSRGB, isLDR);
+ // Compute weight grid values.
+ const int numWeights = computeNumWeights(blockMode);
+ const int numWeightDataBits = computeNumRequiredBits(blockMode.weightISEParams, numWeights);
+ const int numPartitions = (int)blockData.getBits(11, 12) + 1;
+ // Check for errors in weight grid, partition and dual-plane parameters.
+ if (numWeights > 64 ||
+ numWeightDataBits > 96 ||
+ numWeightDataBits < 24 ||
+ blockMode.weightGridWidth > blockWidth ||
+ blockMode.weightGridHeight > blockHeight ||
+ (numPartitions == 4 && blockMode.isDualPlane))
+ {
+ setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
+ return DECOMPRESS_RESULT_ERROR;
+ }
+ // Compute number of bits available for color endpoint data.
+ const bool isSingleUniqueCem = numPartitions == 1 || blockData.getBits(23, 24) == 0;
+ const int numConfigDataBits = (numPartitions == 1 ? 17 : isSingleUniqueCem ? 29 : 25 + 3*numPartitions) +
+ (blockMode.isDualPlane ? 2 : 0);
+ const int numBitsForColorEndpoints = 128 - numWeightDataBits - numConfigDataBits;
+ const int extraCemBitsStart = 127 - numWeightDataBits - (isSingleUniqueCem ? -1
+ : numPartitions == 4 ? 7
+ : numPartitions == 3 ? 4
+ : numPartitions == 2 ? 1
+ : 0);
+ // Decode color endpoint modes.
+ deUint32 colorEndpointModes[4];
+ decodeColorEndpointModes(&colorEndpointModes[0], blockData, numPartitions, extraCemBitsStart);
+ const int numColorEndpointValues = computeNumColorEndpointValues(colorEndpointModes, numPartitions);
+ // Check for errors in color endpoint value count.
+ if (numColorEndpointValues > 18 || numBitsForColorEndpoints < (int)deDivRoundUp32(13*numColorEndpointValues, 5))
+ {
+ setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
+ return DECOMPRESS_RESULT_ERROR;
+ }
+ // Compute color endpoints.
+ ColorEndpointPair colorEndpoints[4];
+ computeColorEndpoints(&colorEndpoints[0], blockData, &colorEndpointModes[0], numPartitions, numColorEndpointValues,
+ computeMaximumRangeISEParams(numBitsForColorEndpoints, numColorEndpointValues), numBitsForColorEndpoints);
+ // Compute texel weights.
+ TexelWeightPair texelWeights[MAX_BLOCK_WIDTH*MAX_BLOCK_HEIGHT];
+ computeTexelWeights(&texelWeights[0], blockData, blockWidth, blockHeight, blockMode);
+ // Set texel colors.
+ const int ccs = blockMode.isDualPlane ? (int)blockData.getBits(extraCemBitsStart-2, extraCemBitsStart-1) : -1;
+ const deUint32 partitionIndexSeed = numPartitions > 1 ? blockData.getBits(13, 22) : (deUint32)-1;
+ return setTexelColors(dst, &colorEndpoints[0], &texelWeights[0], ccs, partitionIndexSeed, numPartitions, blockWidth, blockHeight, isSRGB, isLDR, &colorEndpointModes[0]);
+}
+
+} // anonymous
+
+bool decompress(uint8_t *pDst, const uint8_t * data, bool isSRGB, int blockWidth, int blockHeight)
+{
+ // rg - We only support LDR here, although adding back in HDR would be easy.
+ const bool isLDR = true;
+ DE_ASSERT(isLDR || !isSRGB);
+
+ float linear[MAX_BLOCK_WIDTH * MAX_BLOCK_HEIGHT * 4];
+
+ const Block128 blockData(data);
+ if (decompressBlock(isSRGB ? (void*)pDst : (void*)& linear[0],
+ blockData, blockWidth, blockHeight, isSRGB, isLDR) != DECOMPRESS_RESULT_VALID_BLOCK)
+ return false;
+
+ if (!isSRGB)
+ {
+ int pix = 0;
+ for (int i = 0; i < blockHeight; i++)
+ {
+ for (int j = 0; j < blockWidth; j++, pix++)
+ {
+ pDst[4 * pix + 0] = (uint8_t)(basisu_astc::clamp<int>((int)(linear[pix * 4 + 0] * 65536.0f + .5f), 0, 65535) >> 8);
+ pDst[4 * pix + 1] = (uint8_t)(basisu_astc::clamp<int>((int)(linear[pix * 4 + 1] * 65536.0f + .5f), 0, 65535) >> 8);
+ pDst[4 * pix + 2] = (uint8_t)(basisu_astc::clamp<int>((int)(linear[pix * 4 + 2] * 65536.0f + .5f), 0, 65535) >> 8);
+ pDst[4 * pix + 3] = (uint8_t)(basisu_astc::clamp<int>((int)(linear[pix * 4 + 3] * 65536.0f + .5f), 0, 65535) >> 8);
+ }
+ }
+ }
+
+ return true;
+}
+
+} // astc
+} // basisu_astc
diff --git a/thirdparty/basis_universal/basisu_astc_decomp.h b/thirdparty/basis_universal/basisu_astc_decomp.h
new file mode 100644
index 0000000000..6cd053b7b6
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_astc_decomp.h
@@ -0,0 +1,43 @@
+#ifndef _TCUASTCUTIL_HPP
+#define _TCUASTCUTIL_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief ASTC Utilities.
+ *//*--------------------------------------------------------------------*/
+
+#include "transcoder/basisu.h" // to pick up the iterator debug level madness
+#include <vector>
+#include <stdint.h>
+
+namespace basisu_astc
+{
+namespace astc
+{
+
+// Unpacks a single ASTC block to pDst
+// If isSRGB is true, the spec requires the decoder to scale the LDR 8-bit endpoints to 16-bit before interpolation slightly differently,
+// which will lead to different outputs. So be sure to set it correctly (ideally it should match whatever the encoder did).
+bool decompress(uint8_t* pDst, const uint8_t* data, bool isSRGB, int blockWidth, int blockHeight);
+
+} // astc
+} // basisu
+
+#endif
diff --git a/thirdparty/basis_universal/basisu_backend.cpp b/thirdparty/basis_universal/basisu_backend.cpp
new file mode 100644
index 0000000000..3a689e58d7
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_backend.cpp
@@ -0,0 +1,1674 @@
+// basisu_backend.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// TODO: This code originally supported full ETC1 and ETC1S, so there's some legacy stuff in here.
+//
+#include "basisu_backend.h"
+
+#define BASISU_FASTER_SELECTOR_REORDERING 0
+#define BASISU_BACKEND_VERIFY(c) verify(c, __LINE__);
+
+namespace basisu
+{
+ // TODO
+ static inline void verify(bool condition, int line)
+ {
+ if (!condition)
+ {
+ fprintf(stderr, "ERROR: basisu_backend: verify() failed at line %i!\n", line);
+ abort();
+ }
+ }
+
+ basisu_backend::basisu_backend()
+ {
+ clear();
+ }
+
+ void basisu_backend::clear()
+ {
+ m_pFront_end = NULL;
+ m_params.clear();
+ m_output.clear();
+ }
+
+ void basisu_backend::init(basisu_frontend* pFront_end, basisu_backend_params& params, const basisu_backend_slice_desc_vec& slice_descs, const basist::etc1_global_selector_codebook* pGlobal_sel_codebook)
+ {
+ m_pFront_end = pFront_end;
+ m_params = params;
+ m_slices = slice_descs;
+ m_pGlobal_sel_codebook = pGlobal_sel_codebook;
+
+ debug_printf("basisu_backend::Init: Slices: %u, ETC1S: %u, EndpointRDOQualityThresh: %f, SelectorRDOQualityThresh: %f, UseGlobalSelCodebook: %u, GlobalSelCodebookPalBits: %u, GlobalSelCodebookModBits: %u, Use hybrid selector codebooks: %u\n",
+ m_slices.size(),
+ params.m_etc1s,
+ params.m_endpoint_rdo_quality_thresh,
+ params.m_selector_rdo_quality_thresh,
+ params.m_use_global_sel_codebook,
+ params.m_global_sel_codebook_pal_bits,
+ params.m_global_sel_codebook_mod_bits,
+ params.m_use_hybrid_sel_codebooks);
+
+ debug_printf("Frontend endpoints: %u selectors: %u\n", m_pFront_end->get_total_endpoint_clusters(), m_pFront_end->get_total_selector_clusters());
+
+ for (uint32_t i = 0; i < m_slices.size(); i++)
+ {
+ debug_printf("Slice: %u, OrigWidth: %u, OrigHeight: %u, Width: %u, Height: %u, NumBlocksX: %u, NumBlocksY: %u, FirstBlockIndex: %u\n",
+ i,
+ m_slices[i].m_orig_width, m_slices[i].m_orig_height,
+ m_slices[i].m_width, m_slices[i].m_height,
+ m_slices[i].m_num_blocks_x, m_slices[i].m_num_blocks_y,
+ m_slices[i].m_first_block_index);
+ }
+ }
+
+ void basisu_backend::create_endpoint_palette()
+ {
+ const basisu_frontend& r = *m_pFront_end;
+
+ m_output.m_num_endpoints = r.get_total_endpoint_clusters();
+
+ m_endpoint_palette.resize(r.get_total_endpoint_clusters());
+ for (uint32_t i = 0; i < r.get_total_endpoint_clusters(); i++)
+ {
+ etc1_endpoint_palette_entry& e = m_endpoint_palette[i];
+
+ e.m_color5_valid = r.get_endpoint_cluster_color_is_used(i, false);
+ e.m_color5 = r.get_endpoint_cluster_unscaled_color(i, false);
+ e.m_inten5 = r.get_endpoint_cluster_inten_table(i, false);
+
+ BASISU_BACKEND_VERIFY(e.m_color5_valid);
+ }
+ }
+
+ void basisu_backend::create_selector_palette()
+ {
+ const basisu_frontend& r = *m_pFront_end;
+
+ m_output.m_num_selectors = r.get_total_selector_clusters();
+
+ m_selector_palette.resize(r.get_total_selector_clusters());
+
+ if (m_params.m_use_global_sel_codebook)
+ {
+ m_global_selector_palette_desc.resize(r.get_total_selector_clusters());
+
+ for (int i = 0; i < static_cast<int>(r.get_total_selector_clusters()); i++)
+ {
+ basist::etc1_selector_palette_entry& selector_pal_entry = m_selector_palette[i];
+
+ etc1_global_selector_cb_entry_desc& pal_entry_desc = m_global_selector_palette_desc[i];
+ pal_entry_desc.m_pal_index = r.get_selector_cluster_global_selector_entry_ids()[i].m_palette_index;
+ pal_entry_desc.m_mod_index = r.get_selector_cluster_global_selector_entry_ids()[i].m_modifier.get_index();
+
+ pal_entry_desc.m_was_used = true;
+ if (m_params.m_use_hybrid_sel_codebooks)
+ pal_entry_desc.m_was_used = r.get_selector_cluster_uses_global_cb_vec()[i];
+
+ if (pal_entry_desc.m_was_used)
+ {
+ const etc_block& selector_bits = r.get_selector_cluster_selector_bits(i);
+ (void)selector_bits;
+
+ basist::etc1_selector_palette_entry global_pal_entry(m_pGlobal_sel_codebook->get_entry(r.get_selector_cluster_global_selector_entry_ids()[i]));
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ selector_pal_entry(x, y) = global_pal_entry(x, y);
+
+ assert(selector_bits.get_selector(x, y) == global_pal_entry(x, y));
+ }
+ }
+ }
+ else
+ {
+ const etc_block& selector_bits = r.get_selector_cluster_selector_bits(i);
+
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ selector_pal_entry[y * 4 + x] = static_cast<uint8_t>(selector_bits.get_selector(x, y));
+ }
+ }
+ }
+ else
+ {
+ for (uint32_t i = 0; i < r.get_total_selector_clusters(); i++)
+ {
+ basist::etc1_selector_palette_entry& s = m_selector_palette[i];
+
+ const etc_block& selector_bits = r.get_selector_cluster_selector_bits(i);
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ s[y * 4 + x] = static_cast<uint8_t>(selector_bits.get_selector(x, y));
+ }
+ }
+ }
+ }
+ }
+
+ static const struct
+ {
+ int8_t m_dx, m_dy;
+ } g_endpoint_preds[] =
+ {
+ { -1, 0 },
+ { 0, -1 },
+ { -1, -1 }
+ };
+
+ void basisu_backend::reoptimize_and_sort_endpoints_codebook(uint32_t total_block_endpoints_remapped, uint_vec& all_endpoint_indices)
+ {
+ basisu_frontend& r = *m_pFront_end;
+ const bool is_video = r.get_params().m_tex_type == basist::cBASISTexTypeVideoFrames;
+
+ if ((total_block_endpoints_remapped) && (m_params.m_compression_level > 0))
+ {
+ // We're changed the block endpoint indices, so we need to go and adjust the endpoint codebook (remove unused entries, optimize existing entries that have changed)
+ uint_vec new_block_endpoints(get_total_blocks());
+
+ for (uint32_t slice_index = 0; slice_index < m_slices.size(); slice_index++)
+ {
+ const uint32_t first_block_index = m_slices[slice_index].m_first_block_index;
+ const uint32_t num_blocks_x = m_slices[slice_index].m_num_blocks_x;
+ const uint32_t num_blocks_y = m_slices[slice_index].m_num_blocks_y;
+
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ new_block_endpoints[first_block_index + block_x + block_y * num_blocks_x] = m_slice_encoder_blocks[slice_index](block_x, block_y).m_endpoint_index;
+ }
+
+ int_vec old_to_new_endpoint_indices;
+ r.reoptimize_remapped_endpoints(new_block_endpoints, old_to_new_endpoint_indices, true);
+
+ create_endpoint_palette();
+
+ for (uint32_t slice_index = 0; slice_index < m_slices.size(); slice_index++)
+ {
+ const uint32_t first_block_index = m_slices[slice_index].m_first_block_index;
+
+ const uint32_t width = m_slices[slice_index].m_width;
+ const uint32_t height = m_slices[slice_index].m_height;
+ const uint32_t num_blocks_x = m_slices[slice_index].m_num_blocks_x;
+ const uint32_t num_blocks_y = m_slices[slice_index].m_num_blocks_y;
+
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ {
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ {
+ const uint32_t block_index = first_block_index + block_x + block_y * num_blocks_x;
+
+ encoder_block& m = m_slice_encoder_blocks[slice_index](block_x, block_y);
+
+ m.m_endpoint_index = old_to_new_endpoint_indices[m.m_endpoint_index];
+ } // block_x
+ } // block_y
+ } // slice_index
+
+ for (uint32_t i = 0; i < all_endpoint_indices.size(); i++)
+ all_endpoint_indices[i] = old_to_new_endpoint_indices[all_endpoint_indices[i]];
+
+ } //if (total_block_endpoints_remapped)
+
+ // Sort endpoint codebook
+ palette_index_reorderer reorderer;
+ reorderer.init((uint32_t)all_endpoint_indices.size(), &all_endpoint_indices[0], r.get_total_endpoint_clusters(), nullptr, nullptr, 0);
+ m_endpoint_remap_table_old_to_new = reorderer.get_remap_table();
+
+ m_endpoint_remap_table_new_to_old.resize(r.get_total_endpoint_clusters());
+ for (uint32_t i = 0; i < m_endpoint_remap_table_old_to_new.size(); i++)
+ m_endpoint_remap_table_new_to_old[m_endpoint_remap_table_old_to_new[i]] = i;
+ }
+
+ void basisu_backend::sort_selector_codebook()
+ {
+ basisu_frontend& r = *m_pFront_end;
+
+ m_selector_remap_table_new_to_old.resize(r.get_total_selector_clusters());
+
+ if (m_params.m_compression_level == 0)
+ {
+ for (uint32_t i = 0; i < r.get_total_selector_clusters(); i++)
+ m_selector_remap_table_new_to_old[i] = i;
+ }
+ else
+ {
+ m_selector_remap_table_new_to_old[0] = 0;
+ uint32_t prev_selector_index = 0;
+
+ int_vec remaining_selectors;
+ remaining_selectors.reserve(r.get_total_selector_clusters() - 1);
+ for (uint32_t i = 1; i < r.get_total_selector_clusters(); i++)
+ remaining_selectors.push_back(i);
+
+ uint_vec selector_palette_bytes(m_selector_palette.size());
+ for (uint32_t i = 0; i < m_selector_palette.size(); i++)
+ selector_palette_bytes[i] = m_selector_palette[i].get_byte(0) | (m_selector_palette[i].get_byte(1) << 8) | (m_selector_palette[i].get_byte(2) << 16) | (m_selector_palette[i].get_byte(3) << 24);
+
+ // This is the traveling salesman problem.
+ for (uint32_t i = 1; i < r.get_total_selector_clusters(); i++)
+ {
+ uint32_t best_hamming_dist = 100;
+ uint32_t best_index = 0;
+
+#if BASISU_FASTER_SELECTOR_REORDERING
+ const uint32_t step = (remaining_selectors.size() > 16) ? 16 : 1;
+ for (uint32_t j = 0; j < remaining_selectors.size(); j += step)
+#else
+ for (uint32_t j = 0; j < remaining_selectors.size(); j++)
+#endif
+ {
+ int selector_index = remaining_selectors[j];
+
+ uint32_t k = selector_palette_bytes[prev_selector_index] ^ selector_palette_bytes[selector_index];
+ uint32_t hamming_dist = g_hamming_dist[k & 0xFF] + g_hamming_dist[(k >> 8) & 0xFF] + g_hamming_dist[(k >> 16) & 0xFF] + g_hamming_dist[k >> 24];
+
+ if (hamming_dist < best_hamming_dist)
+ {
+ best_hamming_dist = hamming_dist;
+ best_index = j;
+ if (best_hamming_dist <= 1)
+ break;
+ }
+ }
+
+ prev_selector_index = remaining_selectors[best_index];
+ m_selector_remap_table_new_to_old[i] = prev_selector_index;
+
+ remaining_selectors[best_index] = remaining_selectors.back();
+ remaining_selectors.resize(remaining_selectors.size() - 1);
+ }
+ }
+
+ m_selector_remap_table_old_to_new.resize(r.get_total_selector_clusters());
+ for (uint32_t i = 0; i < m_selector_remap_table_new_to_old.size(); i++)
+ m_selector_remap_table_old_to_new[m_selector_remap_table_new_to_old[i]] = i;
+ }
+ int basisu_backend::find_video_frame(int slice_index, int delta)
+ {
+ for (uint32_t s = 0; s < m_slices.size(); s++)
+ {
+ if ((int)m_slices[s].m_source_file_index != ((int)m_slices[slice_index].m_source_file_index + delta))
+ continue;
+ if (m_slices[s].m_mip_index != m_slices[slice_index].m_mip_index)
+ continue;
+
+ // Being super paranoid here.
+ if (m_slices[s].m_num_blocks_x != (m_slices[slice_index].m_num_blocks_x))
+ continue;
+ if (m_slices[s].m_num_blocks_y != (m_slices[slice_index].m_num_blocks_y))
+ continue;
+ if (m_slices[s].m_alpha != (m_slices[slice_index].m_alpha))
+ continue;
+ return s;
+ }
+
+ return -1;
+ }
+
+ void basisu_backend::check_for_valid_cr_blocks()
+ {
+ basisu_frontend& r = *m_pFront_end;
+ const bool is_video = r.get_params().m_tex_type == basist::cBASISTexTypeVideoFrames;
+
+ if (!is_video)
+ return;
+
+ uint32_t total_crs = 0;
+ uint32_t total_invalid_crs = 0;
+
+ for (uint32_t slice_index = 0; slice_index < m_slices.size(); slice_index++)
+ {
+ const bool is_iframe = m_slices[slice_index].m_iframe;
+ const uint32_t first_block_index = m_slices[slice_index].m_first_block_index;
+
+ const uint32_t width = m_slices[slice_index].m_width;
+ const uint32_t height = m_slices[slice_index].m_height;
+ const uint32_t num_blocks_x = m_slices[slice_index].m_num_blocks_x;
+ const uint32_t num_blocks_y = m_slices[slice_index].m_num_blocks_y;
+ const int prev_frame_slice_index = find_video_frame(slice_index, -1);
+
+ // If we don't have a previous frame, and we're not an i-frame, something is wrong.
+ if ((prev_frame_slice_index < 0) && (!is_iframe))
+ {
+ BASISU_BACKEND_VERIFY(0);
+ }
+
+ if ((is_iframe) || (prev_frame_slice_index < 0))
+ {
+ // Ensure no blocks use CR's
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ {
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ {
+ encoder_block& m = m_slice_encoder_blocks[slice_index](block_x, block_y);
+ BASISU_BACKEND_VERIFY(m.m_endpoint_predictor != basist::CR_ENDPOINT_PRED_INDEX);
+ }
+ }
+ }
+ else
+ {
+ // For blocks that use CR's, make sure the endpoints/selectors haven't really changed.
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ {
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ {
+ encoder_block& m = m_slice_encoder_blocks[slice_index](block_x, block_y);
+
+ if (m.m_endpoint_predictor == basist::CR_ENDPOINT_PRED_INDEX)
+ {
+ total_crs++;
+
+ encoder_block& prev_m = m_slice_encoder_blocks[prev_frame_slice_index](block_x, block_y);
+
+ if ((m.m_endpoint_index != prev_m.m_endpoint_index) || (m.m_selector_index != prev_m.m_selector_index))
+ {
+ total_invalid_crs++;
+ }
+ }
+ } // block_x
+ } // block_y
+
+ } // !slice_index
+
+ } // slice_index
+
+ debug_printf("Total CR's: %u, Total invalid CR's: %u\n", total_crs, total_invalid_crs);
+
+ BASISU_BACKEND_VERIFY(total_invalid_crs == 0);
+ }
+ void basisu_backend::create_encoder_blocks()
+ {
+ basisu_frontend& r = *m_pFront_end;
+ const bool is_video = r.get_params().m_tex_type == basist::cBASISTexTypeVideoFrames;
+
+ m_slice_encoder_blocks.resize(m_slices.size());
+
+ uint32_t total_endpoint_pred_missed = 0, total_endpoint_pred_hits = 0, total_block_endpoints_remapped = 0;
+
+ uint_vec all_endpoint_indices;
+ all_endpoint_indices.reserve(get_total_blocks());
+
+ for (uint32_t slice_index = 0; slice_index < m_slices.size(); slice_index++)
+ {
+ const int prev_frame_slice_index = is_video ? find_video_frame(slice_index, -1) : -1;
+ const bool is_iframe = m_slices[slice_index].m_iframe;
+ const uint32_t first_block_index = m_slices[slice_index].m_first_block_index;
+
+ const uint32_t width = m_slices[slice_index].m_width;
+ const uint32_t height = m_slices[slice_index].m_height;
+ const uint32_t num_blocks_x = m_slices[slice_index].m_num_blocks_x;
+ const uint32_t num_blocks_y = m_slices[slice_index].m_num_blocks_y;
+
+ m_slice_encoder_blocks[slice_index].resize(num_blocks_x, num_blocks_y);
+
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ {
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ {
+ const uint32_t block_index = first_block_index + block_x + block_y * num_blocks_x;
+
+ encoder_block& m = m_slice_encoder_blocks[slice_index](block_x, block_y);
+
+ m.m_endpoint_index = r.get_subblock_endpoint_cluster_index(block_index, 0);
+ BASISU_BACKEND_VERIFY(r.get_subblock_endpoint_cluster_index(block_index, 0) == r.get_subblock_endpoint_cluster_index(block_index, 1));
+
+ m.m_selector_index = r.get_block_selector_cluster_index(block_index);
+
+ m.m_endpoint_predictor = basist::NO_ENDPOINT_PRED_INDEX;
+
+ const uint32_t block_endpoint = m.m_endpoint_index;
+
+ uint32_t best_endpoint_pred = UINT32_MAX;
+
+ for (uint32_t endpoint_pred = 0; endpoint_pred < basist::NUM_ENDPOINT_PREDS; endpoint_pred++)
+ {
+ if ((is_video) && (endpoint_pred == basist::CR_ENDPOINT_PRED_INDEX))
+ {
+ if ((prev_frame_slice_index != -1) && (!is_iframe))
+ {
+ const uint32_t cur_endpoint = m_slice_encoder_blocks[slice_index](block_x, block_y).m_endpoint_index;
+ const uint32_t cur_selector = m_slice_encoder_blocks[slice_index](block_x, block_y).m_selector_index;
+ const uint32_t prev_endpoint = m_slice_encoder_blocks[prev_frame_slice_index](block_x, block_y).m_endpoint_index;
+ const uint32_t prev_selector = m_slice_encoder_blocks[prev_frame_slice_index](block_x, block_y).m_selector_index;
+ if ((cur_endpoint == prev_endpoint) && (cur_selector == prev_selector))
+ {
+ best_endpoint_pred = basist::CR_ENDPOINT_PRED_INDEX;
+ m_slice_encoder_blocks[prev_frame_slice_index](block_x, block_y).m_is_cr_target = true;
+ }
+ }
+ }
+ else
+ {
+ int pred_block_x = block_x + g_endpoint_preds[endpoint_pred].m_dx;
+ if ((pred_block_x < 0) || (pred_block_x >= (int)num_blocks_x))
+ continue;
+
+ int pred_block_y = block_y + g_endpoint_preds[endpoint_pred].m_dy;
+ if ((pred_block_y < 0) || (pred_block_y >= (int)num_blocks_y))
+ continue;
+
+ uint32_t pred_endpoint = m_slice_encoder_blocks[slice_index](pred_block_x, pred_block_y).m_endpoint_index;
+
+ if (pred_endpoint == block_endpoint)
+ {
+ if (endpoint_pred < best_endpoint_pred)
+ {
+ best_endpoint_pred = endpoint_pred;
+ }
+ }
+ }
+
+ } // endpoint_pred
+
+ if (best_endpoint_pred != UINT32_MAX)
+ {
+ m.m_endpoint_predictor = best_endpoint_pred;
+
+ total_endpoint_pred_hits++;
+ }
+ else if (m_params.m_endpoint_rdo_quality_thresh > 0.0f)
+ {
+ const pixel_block& src_pixels = r.get_source_pixel_block(block_index);
+
+ etc_block etc_blk(r.get_output_block(block_index));
+
+ uint64_t cur_err = etc_blk.evaluate_etc1_error(src_pixels.get_ptr(), r.get_params().m_perceptual);
+
+ if (cur_err)
+ {
+ const uint64_t thresh_err = (uint64_t)(cur_err * maximum(1.0f, m_params.m_endpoint_rdo_quality_thresh));
+
+ etc_block trial_etc_block(etc_blk);
+
+ uint64_t best_err = UINT64_MAX;
+ uint32_t best_endpoint_index = 0;
+
+ best_endpoint_pred = UINT32_MAX;
+
+ for (uint32_t endpoint_pred = 0; endpoint_pred < basist::NUM_ENDPOINT_PREDS; endpoint_pred++)
+ {
+ if ((is_video) && (endpoint_pred == basist::CR_ENDPOINT_PRED_INDEX))
+ continue;
+ int pred_block_x = block_x + g_endpoint_preds[endpoint_pred].m_dx;
+ if ((pred_block_x < 0) || (pred_block_x >= (int)num_blocks_x))
+ continue;
+
+ int pred_block_y = block_y + g_endpoint_preds[endpoint_pred].m_dy;
+ if ((pred_block_y < 0) || (pred_block_y >= (int)num_blocks_y))
+ continue;
+
+ uint32_t pred_endpoint_index = m_slice_encoder_blocks[slice_index](pred_block_x, pred_block_y).m_endpoint_index;
+
+ uint32_t pred_inten = r.get_endpoint_cluster_inten_table(pred_endpoint_index, false);
+ color_rgba pred_color = r.get_endpoint_cluster_unscaled_color(pred_endpoint_index, false);
+
+ trial_etc_block.set_block_color5(pred_color, pred_color);
+ trial_etc_block.set_inten_table(0, pred_inten);
+ trial_etc_block.set_inten_table(1, pred_inten);
+
+ color_rgba trial_colors[16];
+ unpack_etc1(trial_etc_block, trial_colors);
+
+ uint64_t trial_err = 0;
+ for (uint32_t p = 0; p < 16; p++)
+ {
+ trial_err += color_distance(r.get_params().m_perceptual, src_pixels.get_ptr()[p], trial_colors[p], false);
+ if (trial_err > thresh_err)
+ break;
+ }
+
+ if (trial_err <= thresh_err)
+ {
+ if ((trial_err < best_err) || ((trial_err == best_err) && (endpoint_pred < best_endpoint_pred)))
+ {
+ best_endpoint_pred = endpoint_pred;
+ best_err = trial_err;
+ best_endpoint_index = pred_endpoint_index;
+ }
+ }
+ } // endpoint_pred
+
+ if (best_endpoint_pred != UINT32_MAX)
+ {
+ m.m_endpoint_index = best_endpoint_index;
+ m.m_endpoint_predictor = best_endpoint_pred;
+
+ total_endpoint_pred_hits++;
+ total_block_endpoints_remapped++;
+ }
+ else
+ {
+ total_endpoint_pred_missed++;
+ }
+ }
+ }
+ else
+ {
+ total_endpoint_pred_missed++;
+ }
+
+ if (m.m_endpoint_predictor == basist::NO_ENDPOINT_PRED_INDEX)
+ {
+ all_endpoint_indices.push_back(m.m_endpoint_index);
+ }
+
+ } // block_x
+
+ } // block_y
+
+ } // slice
+
+ debug_printf("total_endpoint_pred_missed: %u (%3.2f%%) total_endpoint_pred_hit: %u (%3.2f%%), total_block_endpoints_remapped: %u (%3.2f%%)\n",
+ total_endpoint_pred_missed, total_endpoint_pred_missed * 100.0f / get_total_blocks(),
+ total_endpoint_pred_hits, total_endpoint_pred_hits * 100.0f / get_total_blocks(),
+ total_block_endpoints_remapped, total_block_endpoints_remapped * 100.0f / get_total_blocks());
+
+ reoptimize_and_sort_endpoints_codebook(total_block_endpoints_remapped, all_endpoint_indices);
+
+ sort_selector_codebook();
+ check_for_valid_cr_blocks();
+ }
+
+ void basisu_backend::compute_slice_crcs()
+ {
+ for (uint32_t slice_index = 0; slice_index < m_slices.size(); slice_index++)
+ {
+ const uint32_t first_block_index = m_slices[slice_index].m_first_block_index;
+ const uint32_t width = m_slices[slice_index].m_width;
+ const uint32_t height = m_slices[slice_index].m_height;
+ const uint32_t num_blocks_x = m_slices[slice_index].m_num_blocks_x;
+ const uint32_t num_blocks_y = m_slices[slice_index].m_num_blocks_y;
+
+ gpu_image gi;
+ gi.init(texture_format::cETC1, width, height);
+
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ {
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ {
+ const uint32_t block_index = first_block_index + block_x + block_y * num_blocks_x;
+
+ encoder_block& m = m_slice_encoder_blocks[slice_index](block_x, block_y);
+
+ {
+ etc_block& output_block = *(etc_block*)gi.get_block_ptr(block_x, block_y);
+
+ output_block.set_diff_bit(true);
+ output_block.set_flip_bit(true);
+
+ const uint32_t endpoint_index = m.m_endpoint_index;
+
+ output_block.set_block_color5_etc1s(m_endpoint_palette[endpoint_index].m_color5);
+ output_block.set_inten_tables_etc1s(m_endpoint_palette[endpoint_index].m_inten5);
+
+ const uint32_t selector_idx = m.m_selector_index;
+
+ const basist::etc1_selector_palette_entry& selectors = m_selector_palette[selector_idx];
+ for (uint32_t sy = 0; sy < 4; sy++)
+ for (uint32_t sx = 0; sx < 4; sx++)
+ output_block.set_selector(sx, sy, selectors(sx, sy));
+ }
+
+ } // block_x
+ } // block_y
+
+ m_output.m_slice_image_crcs[slice_index] = basist::crc16(gi.get_ptr(), gi.get_size_in_bytes(), 0);
+
+ if (m_params.m_debug_images)
+ {
+ image gi_unpacked;
+ gi.unpack(gi_unpacked);
+
+ char buf[256];
+#ifdef _WIN32
+ sprintf_s(buf, sizeof(buf), "basisu_backend_slice_%u.png", slice_index);
+#else
+ snprintf(buf, sizeof(buf), "basisu_backend_slice_%u.png", slice_index);
+#endif
+ save_png(buf, gi_unpacked);
+ }
+
+ } // slice_index
+ }
+
+ // TODO: Split this into multiple methods.
+ bool basisu_backend::encode_image()
+ {
+ basisu_frontend& r = *m_pFront_end;
+ const bool is_video = r.get_params().m_tex_type == basist::cBASISTexTypeVideoFrames;
+
+ uint32_t total_used_selector_history_buf = 0;
+ uint32_t total_selector_indices_remapped = 0;
+
+ basist::approx_move_to_front selector_history_buf(basist::MAX_SELECTOR_HISTORY_BUF_SIZE);
+ histogram selector_history_buf_histogram(basist::MAX_SELECTOR_HISTORY_BUF_SIZE);
+ histogram selector_histogram(r.get_total_selector_clusters() + basist::MAX_SELECTOR_HISTORY_BUF_SIZE + 1);
+ histogram selector_history_buf_rle_histogram(1 << basist::SELECTOR_HISTORY_BUF_RLE_COUNT_BITS);
+
+ std::vector<uint_vec> selector_syms(m_slices.size());
+
+ const uint32_t SELECTOR_HISTORY_BUF_FIRST_SYMBOL_INDEX = r.get_total_selector_clusters();
+ const uint32_t SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX = SELECTOR_HISTORY_BUF_FIRST_SYMBOL_INDEX + basist::MAX_SELECTOR_HISTORY_BUF_SIZE;
+
+ m_output.m_slice_image_crcs.resize(m_slices.size());
+
+ histogram delta_endpoint_histogram(r.get_total_endpoint_clusters());
+
+ histogram endpoint_pred_histogram(basist::ENDPOINT_PRED_TOTAL_SYMBOLS);
+ std::vector<uint_vec> endpoint_pred_syms(m_slices.size());
+
+ uint32_t total_endpoint_indices_remapped = 0;
+
+ uint_vec block_endpoint_indices, block_selector_indices;
+
+ for (uint32_t slice_index = 0; slice_index < m_slices.size(); slice_index++)
+ {
+ const int prev_frame_slice_index = is_video ? find_video_frame(slice_index, -1) : -1;
+ const int next_frame_slice_index = is_video ? find_video_frame(slice_index, 1) : -1;
+ const uint32_t first_block_index = m_slices[slice_index].m_first_block_index;
+ const uint32_t width = m_slices[slice_index].m_width;
+ const uint32_t height = m_slices[slice_index].m_height;
+ const uint32_t num_blocks_x = m_slices[slice_index].m_num_blocks_x;
+ const uint32_t num_blocks_y = m_slices[slice_index].m_num_blocks_y;
+
+ selector_history_buf.reset();
+
+ int selector_history_buf_rle_count = 0;
+
+ int prev_endpoint_pred_sym_bits = -1, endpoint_pred_repeat_count = 0;
+
+ uint32_t prev_endpoint_index = 0;
+
+ vector2D<uint8_t> block_endpoints_are_referenced(num_blocks_x, num_blocks_y);
+
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ {
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ {
+ const uint32_t block_index = first_block_index + block_x + block_y * num_blocks_x;
+
+ encoder_block& m = m_slice_encoder_blocks[slice_index](block_x, block_y);
+
+ if (m.m_endpoint_predictor == 0)
+ block_endpoints_are_referenced(block_x - 1, block_y) = true;
+ else if (m.m_endpoint_predictor == 1)
+ block_endpoints_are_referenced(block_x, block_y - 1) = true;
+ else if (m.m_endpoint_predictor == 2)
+ {
+ if (!is_video)
+ block_endpoints_are_referenced(block_x - 1, block_y - 1) = true;
+ }
+ if (is_video)
+ {
+ if (m.m_is_cr_target)
+ block_endpoints_are_referenced(block_x, block_y) = true;
+ }
+
+ } // block_x
+ } // block_y
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ {
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ {
+ const uint32_t block_index = first_block_index + block_x + block_y * num_blocks_x;
+
+ encoder_block& m = m_slice_encoder_blocks[slice_index](block_x, block_y);
+
+ if (((block_x & 1) == 0) && ((block_y & 1) == 0))
+ {
+ uint32_t endpoint_pred_cur_sym_bits = 0;
+
+ for (uint32_t y = 0; y < 2; y++)
+ {
+ for (uint32_t x = 0; x < 2; x++)
+ {
+ const uint32_t bx = block_x + x;
+ const uint32_t by = block_y + y;
+
+ uint32_t pred = basist::NO_ENDPOINT_PRED_INDEX;
+ if ((bx < num_blocks_x) && (by < num_blocks_y))
+ pred = m_slice_encoder_blocks[slice_index](bx, by).m_endpoint_predictor;
+
+ endpoint_pred_cur_sym_bits |= (pred << (x * 2 + y * 4));
+ }
+ }
+
+ if ((int)endpoint_pred_cur_sym_bits == prev_endpoint_pred_sym_bits)
+ {
+ endpoint_pred_repeat_count++;
+ }
+ else
+ {
+ if (endpoint_pred_repeat_count > 0)
+ {
+ if (endpoint_pred_repeat_count > (int)basist::ENDPOINT_PRED_MIN_REPEAT_COUNT)
+ {
+ endpoint_pred_histogram.inc(basist::ENDPOINT_PRED_REPEAT_LAST_SYMBOL);
+ endpoint_pred_syms[slice_index].push_back(basist::ENDPOINT_PRED_REPEAT_LAST_SYMBOL);
+
+ endpoint_pred_syms[slice_index].push_back(endpoint_pred_repeat_count);
+ }
+ else
+ {
+ for (int j = 0; j < endpoint_pred_repeat_count; j++)
+ {
+ endpoint_pred_histogram.inc(prev_endpoint_pred_sym_bits);
+ endpoint_pred_syms[slice_index].push_back(prev_endpoint_pred_sym_bits);
+ }
+ }
+
+ endpoint_pred_repeat_count = 0;
+ }
+
+ endpoint_pred_histogram.inc(endpoint_pred_cur_sym_bits);
+ endpoint_pred_syms[slice_index].push_back(endpoint_pred_cur_sym_bits);
+
+ prev_endpoint_pred_sym_bits = endpoint_pred_cur_sym_bits;
+ }
+ }
+
+ int new_endpoint_index = m_endpoint_remap_table_old_to_new[m.m_endpoint_index];
+
+ if (m.m_endpoint_predictor == basist::NO_ENDPOINT_PRED_INDEX)
+ {
+ int endpoint_delta = new_endpoint_index - prev_endpoint_index;
+
+ if ((m_params.m_endpoint_rdo_quality_thresh > 1.0f) && (iabs(endpoint_delta) > 1) && (!block_endpoints_are_referenced(block_x, block_y)))
+ {
+ const pixel_block& src_pixels = r.get_source_pixel_block(block_index);
+
+ etc_block etc_blk(r.get_output_block(block_index));
+
+ const uint64_t cur_err = etc_blk.evaluate_etc1_error(src_pixels.get_ptr(), r.get_params().m_perceptual);
+
+ if (cur_err)
+ {
+ const float endpoint_remap_thresh = maximum(1.0f, m_params.m_endpoint_rdo_quality_thresh);
+ const uint64_t thresh_err = (uint64_t)(cur_err * endpoint_remap_thresh);
+
+ uint64_t best_trial_err = UINT64_MAX;
+ int best_trial_idx = 0;
+
+ etc_block trial_etc_blk(etc_blk);
+
+ const int MAX_ENDPOINT_SEARCH_DIST = 32;
+ const int search_dist = minimum<int>(iabs(endpoint_delta) - 1, MAX_ENDPOINT_SEARCH_DIST);
+ for (int d = -search_dist; d < search_dist; d++)
+ {
+ int trial_idx = prev_endpoint_index + d;
+ if (trial_idx < 0)
+ trial_idx += (int)r.get_total_endpoint_clusters();
+ else if (trial_idx >= (int)r.get_total_endpoint_clusters())
+ trial_idx -= (int)r.get_total_endpoint_clusters();
+
+ if (trial_idx == new_endpoint_index)
+ continue;
+
+ const etc1_endpoint_palette_entry& p = m_endpoint_palette[m_endpoint_remap_table_new_to_old[trial_idx]];
+ trial_etc_blk.set_block_color5_etc1s(p.m_color5);
+ trial_etc_blk.set_inten_tables_etc1s(p.m_inten5);
+
+ uint64_t trial_err = trial_etc_blk.evaluate_etc1_error(src_pixels.get_ptr(), r.get_params().m_perceptual);
+
+ if (trial_err <= thresh_err)
+ {
+ if (trial_err < best_trial_err)
+ {
+ best_trial_err = trial_err;
+ best_trial_idx = trial_idx;
+ }
+ }
+ }
+
+ if (best_trial_err != UINT64_MAX)
+ {
+ m.m_endpoint_index = m_endpoint_remap_table_new_to_old[best_trial_idx];
+
+ new_endpoint_index = best_trial_idx;
+
+ endpoint_delta = new_endpoint_index - prev_endpoint_index;
+
+ total_endpoint_indices_remapped++;
+ }
+ }
+ }
+
+ if (endpoint_delta < 0)
+ endpoint_delta += (int)r.get_total_endpoint_clusters();
+
+ delta_endpoint_histogram.inc(endpoint_delta);
+ }
+
+ block_endpoint_indices.push_back(m_endpoint_remap_table_new_to_old[new_endpoint_index]);
+
+ prev_endpoint_index = new_endpoint_index;
+
+ if ((!is_video) || (m.m_endpoint_predictor != basist::CR_ENDPOINT_PRED_INDEX))
+ {
+ int new_selector_index = m_selector_remap_table_old_to_new[m.m_selector_index];
+
+ int selector_history_buf_index = -1;
+
+ if (m.m_is_cr_target)
+ {
+ for (uint32_t j = 0; j < selector_history_buf.size(); j++)
+ {
+ const int trial_idx = selector_history_buf[j];
+ if (trial_idx == new_selector_index)
+ {
+ total_used_selector_history_buf++;
+ selector_history_buf_index = j;
+ selector_history_buf_histogram.inc(j);
+ break;
+ }
+ }
+ }
+ else
+ {
+ const pixel_block& src_pixels = r.get_source_pixel_block(block_index);
+
+ etc_block etc_blk(r.get_output_block(block_index));
+
+ color_rgba etc_blk_unpacked[16];
+ unpack_etc1(etc_blk, etc_blk_unpacked);
+
+ uint64_t cur_err = 0;
+ for (uint32_t p = 0; p < 16; p++)
+ cur_err += color_distance(r.get_params().m_perceptual, src_pixels.get_ptr()[p], etc_blk_unpacked[p], false);
+
+ uint64_t best_trial_err = UINT64_MAX;
+ int best_trial_idx = 0;
+ uint32_t best_trial_history_buf_idx = 0;
+
+
+ const float selector_remap_thresh = maximum(1.0f, m_params.m_selector_rdo_quality_thresh); //2.5f;
+ const bool use_strict_search = (m_params.m_compression_level == 0) && (selector_remap_thresh == 1.0f);
+
+ for (uint32_t j = 0; j < selector_history_buf.size(); j++)
+ {
+ const int trial_idx = selector_history_buf[j];
+
+ if (use_strict_search)
+ {
+ if (trial_idx == new_selector_index)
+ {
+ best_trial_err = 0;
+ best_trial_idx = trial_idx;
+ best_trial_history_buf_idx = j;
+ break;
+ }
+ }
+ else
+ {
+ for (uint32_t sy = 0; sy < 4; sy++)
+ for (uint32_t sx = 0; sx < 4; sx++)
+ etc_blk.set_selector(sx, sy, m_selector_palette[m_selector_remap_table_new_to_old[trial_idx]](sx, sy));
+
+ // TODO: Optimize this
+ unpack_etc1(etc_blk, etc_blk_unpacked);
+
+ uint64_t trial_err = 0;
+ const uint64_t thresh_err = minimum((uint64_t)ceilf(cur_err * selector_remap_thresh), best_trial_err);
+ for (uint32_t p = 0; p < 16; p++)
+ {
+ trial_err += color_distance(r.get_params().m_perceptual, src_pixels.get_ptr()[p], etc_blk_unpacked[p], false);
+ if (trial_err > thresh_err)
+ break;
+ }
+
+ if (trial_err <= cur_err * selector_remap_thresh)
+ {
+ if (trial_err < best_trial_err)
+ {
+ best_trial_err = trial_err;
+ best_trial_idx = trial_idx;
+ best_trial_history_buf_idx = j;
+ }
+ }
+ }
+ }
+
+ if (best_trial_err != UINT64_MAX)
+ {
+ if (new_selector_index != best_trial_idx)
+ total_selector_indices_remapped++;
+
+ new_selector_index = best_trial_idx;
+
+ total_used_selector_history_buf++;
+
+ selector_history_buf_index = best_trial_history_buf_idx;
+
+ selector_history_buf_histogram.inc(best_trial_history_buf_idx);
+ }
+ } // if (m_params.m_selector_rdo_quality_thresh > 0.0f)
+
+ m.m_selector_index = m_selector_remap_table_new_to_old[new_selector_index];
+
+
+ if ((selector_history_buf_rle_count) && (selector_history_buf_index != 0))
+ {
+ if (selector_history_buf_rle_count >= (int)basist::SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH)
+ {
+ selector_syms[slice_index].push_back(SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX);
+ selector_syms[slice_index].push_back(selector_history_buf_rle_count);
+
+ int run_sym = selector_history_buf_rle_count - basist::SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH;
+ if (run_sym >= ((int)basist::SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL - 1))
+ selector_history_buf_rle_histogram.inc(basist::SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL - 1);
+ else
+ selector_history_buf_rle_histogram.inc(run_sym);
+
+ selector_histogram.inc(SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX);
+ }
+ else
+ {
+ for (int k = 0; k < selector_history_buf_rle_count; k++)
+ {
+ uint32_t sym_index = SELECTOR_HISTORY_BUF_FIRST_SYMBOL_INDEX + 0;
+
+ selector_syms[slice_index].push_back(sym_index);
+
+ selector_histogram.inc(sym_index);
+ }
+ }
+
+ selector_history_buf_rle_count = 0;
+ }
+
+ if (selector_history_buf_index >= 0)
+ {
+ if (selector_history_buf_index == 0)
+ selector_history_buf_rle_count++;
+ else
+ {
+ uint32_t history_buf_sym = SELECTOR_HISTORY_BUF_FIRST_SYMBOL_INDEX + selector_history_buf_index;
+
+ selector_syms[slice_index].push_back(history_buf_sym);
+
+ selector_histogram.inc(history_buf_sym);
+ }
+ }
+ else
+ {
+ selector_syms[slice_index].push_back(new_selector_index);
+
+ selector_histogram.inc(new_selector_index);
+ }
+
+ m.m_selector_history_buf_index = selector_history_buf_index;
+
+ if (selector_history_buf_index < 0)
+ selector_history_buf.add(new_selector_index);
+ else if (selector_history_buf.size())
+ selector_history_buf.use(selector_history_buf_index);
+ }
+ block_selector_indices.push_back(m.m_selector_index);
+
+ } // block_x
+
+ } // block_y
+
+ if (endpoint_pred_repeat_count > 0)
+ {
+ if (endpoint_pred_repeat_count > (int)basist::ENDPOINT_PRED_MIN_REPEAT_COUNT)
+ {
+ endpoint_pred_histogram.inc(basist::ENDPOINT_PRED_REPEAT_LAST_SYMBOL);
+ endpoint_pred_syms[slice_index].push_back(basist::ENDPOINT_PRED_REPEAT_LAST_SYMBOL);
+
+ endpoint_pred_syms[slice_index].push_back(endpoint_pred_repeat_count);
+ }
+ else
+ {
+ for (int j = 0; j < endpoint_pred_repeat_count; j++)
+ {
+ endpoint_pred_histogram.inc(prev_endpoint_pred_sym_bits);
+ endpoint_pred_syms[slice_index].push_back(prev_endpoint_pred_sym_bits);
+ }
+ }
+
+ endpoint_pred_repeat_count = 0;
+ }
+
+ if (selector_history_buf_rle_count)
+ {
+ if (selector_history_buf_rle_count >= (int)basist::SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH)
+ {
+ selector_syms[slice_index].push_back(SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX);
+ selector_syms[slice_index].push_back(selector_history_buf_rle_count);
+
+ int run_sym = selector_history_buf_rle_count - basist::SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH;
+ if (run_sym >= ((int)basist::SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL - 1))
+ selector_history_buf_rle_histogram.inc(basist::SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL - 1);
+ else
+ selector_history_buf_rle_histogram.inc(run_sym);
+
+ selector_histogram.inc(SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX);
+ }
+ else
+ {
+ for (int i = 0; i < selector_history_buf_rle_count; i++)
+ {
+ uint32_t sym_index = SELECTOR_HISTORY_BUF_FIRST_SYMBOL_INDEX + 0;
+
+ selector_syms[slice_index].push_back(sym_index);
+
+ selector_histogram.inc(sym_index);
+ }
+ }
+
+ selector_history_buf_rle_count = 0;
+ }
+
+ } // slice_index
+
+ debug_printf("Endpoint pred RDO total endpoint indices remapped: %u %3.2f%%\n",
+ total_endpoint_indices_remapped, total_endpoint_indices_remapped * 100.0f / get_total_blocks());
+
+ debug_printf("Selector history RDO total selector indices remapped: %u %3.2f%%, Used history buf: %u %3.2f%%\n",
+ total_selector_indices_remapped, total_selector_indices_remapped * 100.0f / get_total_blocks(),
+ total_used_selector_history_buf, total_used_selector_history_buf * 100.0f / get_total_blocks());
+
+ if ((total_endpoint_indices_remapped) && (m_params.m_compression_level > 0))
+ {
+ int_vec unused;
+ r.reoptimize_remapped_endpoints(block_endpoint_indices, unused, false, &block_selector_indices);
+
+ create_endpoint_palette();
+ }
+
+ check_for_valid_cr_blocks();
+ compute_slice_crcs();
+
+ double endpoint_pred_entropy = endpoint_pred_histogram.get_entropy() / endpoint_pred_histogram.get_total();
+ double delta_endpoint_entropy = delta_endpoint_histogram.get_entropy() / delta_endpoint_histogram.get_total();
+ double selector_entropy = selector_histogram.get_entropy() / selector_histogram.get_total();
+
+ debug_printf("Histogram entropy: EndpointPred: %3.3f DeltaEndpoint: %3.3f DeltaSelector: %3.3f\n", endpoint_pred_entropy, delta_endpoint_entropy, selector_entropy);
+
+ if (!endpoint_pred_histogram.get_total())
+ endpoint_pred_histogram.inc(0);
+ huffman_encoding_table endpoint_pred_model;
+ if (!endpoint_pred_model.init(endpoint_pred_histogram, 16))
+ {
+ error_printf("endpoint_pred_model.init() failed!");
+ return false;
+ }
+
+ if (!delta_endpoint_histogram.get_total())
+ delta_endpoint_histogram.inc(0);
+ huffman_encoding_table delta_endpoint_model;
+ if (!delta_endpoint_model.init(delta_endpoint_histogram, 16))
+ {
+ error_printf("delta_endpoint_model.init() failed!");
+ return false;
+ }
+ if (!selector_histogram.get_total())
+ selector_histogram.inc(0);
+
+ huffman_encoding_table selector_model;
+ if (!selector_model.init(selector_histogram, 16))
+ {
+ error_printf("selector_model.init() failed!");
+ return false;
+ }
+
+ if (!selector_history_buf_rle_histogram.get_total())
+ selector_history_buf_rle_histogram.inc(0);
+
+ huffman_encoding_table selector_history_buf_rle_model;
+ if (!selector_history_buf_rle_model.init(selector_history_buf_rle_histogram, 16))
+ {
+ error_printf("selector_history_buf_rle_model.init() failed!");
+ return false;
+ }
+
+ bitwise_coder coder;
+ coder.init(1024 * 1024 * 4);
+
+ uint32_t endpoint_pred_model_bits = coder.emit_huffman_table(endpoint_pred_model);
+ uint32_t delta_endpoint_bits = coder.emit_huffman_table(delta_endpoint_model);
+ uint32_t selector_model_bits = coder.emit_huffman_table(selector_model);
+ uint32_t selector_history_buf_run_sym_bits = coder.emit_huffman_table(selector_history_buf_rle_model);
+
+ coder.put_bits(basist::MAX_SELECTOR_HISTORY_BUF_SIZE, 13);
+
+ debug_printf("Model sizes: EndpointPred: %u bits %u bytes (%3.3f bpp) DeltaEndpoint: %u bits %u bytes (%3.3f bpp) Selector: %u bits %u bytes (%3.3f bpp) SelectorHistBufRLE: %u bits %u bytes (%3.3f bpp)\n",
+ endpoint_pred_model_bits, (endpoint_pred_model_bits + 7) / 8, endpoint_pred_model_bits / float(get_total_input_texels()),
+ delta_endpoint_bits, (delta_endpoint_bits + 7) / 8, delta_endpoint_bits / float(get_total_input_texels()),
+ selector_model_bits, (selector_model_bits + 7) / 8, selector_model_bits / float(get_total_input_texels()),
+ selector_history_buf_run_sym_bits, (selector_history_buf_run_sym_bits + 7) / 8, selector_history_buf_run_sym_bits / float(get_total_input_texels()));
+
+ coder.flush();
+
+ m_output.m_slice_image_tables = coder.get_bytes();
+
+ uint32_t total_endpoint_pred_bits = 0, total_delta_endpoint_bits = 0, total_selector_bits = 0;
+
+ uint32_t total_image_bytes = 0;
+
+ m_output.m_slice_image_data.resize(m_slices.size());
+
+ for (uint32_t slice_index = 0; slice_index < m_slices.size(); slice_index++)
+ {
+ const uint32_t width = m_slices[slice_index].m_width;
+ const uint32_t height = m_slices[slice_index].m_height;
+ const uint32_t num_blocks_x = m_slices[slice_index].m_num_blocks_x;
+ const uint32_t num_blocks_y = m_slices[slice_index].m_num_blocks_y;
+
+ coder.init(1024 * 1024 * 4);
+
+ uint32_t cur_selector_sym_ofs = 0;
+ uint32_t selector_rle_count = 0;
+
+ int endpoint_pred_repeat_count = 0;
+ uint32_t cur_endpoint_pred_sym_ofs = 0;
+// uint32_t prev_endpoint_pred_sym = 0;
+ uint32_t prev_endpoint_index = 0;
+
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ {
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ {
+ const encoder_block& m = m_slice_encoder_blocks[slice_index](block_x, block_y);
+
+ if (((block_x & 1) == 0) && ((block_y & 1) == 0))
+ {
+ if (endpoint_pred_repeat_count > 0)
+ {
+ endpoint_pred_repeat_count--;
+ }
+ else
+ {
+ uint32_t sym = endpoint_pred_syms[slice_index][cur_endpoint_pred_sym_ofs++];
+
+ if (sym == basist::ENDPOINT_PRED_REPEAT_LAST_SYMBOL)
+ {
+ total_endpoint_pred_bits += coder.put_code(sym, endpoint_pred_model);
+
+ endpoint_pred_repeat_count = endpoint_pred_syms[slice_index][cur_endpoint_pred_sym_ofs++];
+ assert(endpoint_pred_repeat_count >= (int)basist::ENDPOINT_PRED_MIN_REPEAT_COUNT);
+
+ total_endpoint_pred_bits += coder.put_vlc(endpoint_pred_repeat_count - basist::ENDPOINT_PRED_MIN_REPEAT_COUNT, basist::ENDPOINT_PRED_COUNT_VLC_BITS);
+
+ endpoint_pred_repeat_count--;
+ }
+ else
+ {
+ total_endpoint_pred_bits += coder.put_code(sym, endpoint_pred_model);
+
+ //prev_endpoint_pred_sym = sym;
+ }
+ }
+ }
+
+ const int new_endpoint_index = m_endpoint_remap_table_old_to_new[m.m_endpoint_index];
+
+ if (m.m_endpoint_predictor == basist::NO_ENDPOINT_PRED_INDEX)
+ {
+ int endpoint_delta = new_endpoint_index - prev_endpoint_index;
+ if (endpoint_delta < 0)
+ endpoint_delta += (int)r.get_total_endpoint_clusters();
+
+ total_delta_endpoint_bits += coder.put_code(endpoint_delta, delta_endpoint_model);
+ }
+
+ prev_endpoint_index = new_endpoint_index;
+
+ if ((!is_video) || (m.m_endpoint_predictor != basist::CR_ENDPOINT_PRED_INDEX))
+ {
+ if (!selector_rle_count)
+ {
+ uint32_t selector_sym_index = selector_syms[slice_index][cur_selector_sym_ofs++];
+
+ if (selector_sym_index == SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX)
+ selector_rle_count = selector_syms[slice_index][cur_selector_sym_ofs++];
+
+ total_selector_bits += coder.put_code(selector_sym_index, selector_model);
+
+ if (selector_sym_index == SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX)
+ {
+ int run_sym = selector_rle_count - basist::SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH;
+ if (run_sym >= ((int)basist::SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL - 1))
+ {
+ total_selector_bits += coder.put_code(basist::SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL - 1, selector_history_buf_rle_model);
+
+ uint32_t n = selector_rle_count - basist::SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH;
+ total_selector_bits += coder.put_vlc(n, 7);
+ }
+ else
+ total_selector_bits += coder.put_code(run_sym, selector_history_buf_rle_model);
+ }
+ }
+
+ if (selector_rle_count)
+ selector_rle_count--;
+ }
+
+ } // block_x
+
+ } // block_y
+
+ BASISU_BACKEND_VERIFY(cur_endpoint_pred_sym_ofs == endpoint_pred_syms[slice_index].size());
+ BASISU_BACKEND_VERIFY(cur_selector_sym_ofs == selector_syms[slice_index].size());
+
+ coder.flush();
+
+ m_output.m_slice_image_data[slice_index] = coder.get_bytes();
+
+ total_image_bytes += (uint32_t)coder.get_bytes().size();
+
+ debug_printf("Slice %u compressed size: %u bytes, %3.3f bits per slice texel\n", slice_index, m_output.m_slice_image_data[slice_index].size(), m_output.m_slice_image_data[slice_index].size() * 8.0f / (m_slices[slice_index].m_orig_width * m_slices[slice_index].m_orig_height));
+
+ } // slice_index
+
+ const double total_texels = static_cast<double>(get_total_input_texels());
+ const double total_blocks = static_cast<double>(get_total_blocks());
+
+ debug_printf("Total endpoint pred bits: %u bytes: %u bits/texel: %3.3f bits/block: %3.3f\n", total_endpoint_pred_bits, total_endpoint_pred_bits / 8, total_endpoint_pred_bits / total_texels, total_endpoint_pred_bits / total_blocks);
+ debug_printf("Total delta endpoint bits: %u bytes: %u bits/texel: %3.3f bits/block: %3.3f\n", total_delta_endpoint_bits, total_delta_endpoint_bits / 8, total_delta_endpoint_bits / total_texels, total_delta_endpoint_bits / total_blocks);
+ debug_printf("Total selector bits: %u bytes: %u bits/texel: %3.3f bits/block: %3.3f\n", total_selector_bits, total_selector_bits / 8, total_selector_bits / total_texels, total_selector_bits / total_blocks);
+
+ debug_printf("Total table bytes: %u, %3.3f bits/texel\n", m_output.m_slice_image_tables.size(), m_output.m_slice_image_tables.size() * 8.0f / total_texels);
+ debug_printf("Total image bytes: %u, %3.3f bits/texel\n", total_image_bytes, total_image_bytes * 8.0f / total_texels);
+
+ return true;
+ }
+
+ bool basisu_backend::encode_endpoint_palette()
+ {
+ const basisu_frontend& r = *m_pFront_end;
+
+ // Maps NEW to OLD endpoints
+ uint_vec endpoint_remap_table_inv(r.get_total_endpoint_clusters());
+ for (uint32_t old_endpoint_index = 0; old_endpoint_index < m_endpoint_remap_table_old_to_new.size(); old_endpoint_index++)
+ endpoint_remap_table_inv[m_endpoint_remap_table_old_to_new[old_endpoint_index]] = old_endpoint_index;
+
+ bool is_grayscale = true;
+ for (uint32_t old_endpoint_index = 0; old_endpoint_index < (uint32_t)m_endpoint_palette.size(); old_endpoint_index++)
+ {
+ int r5 = m_endpoint_palette[old_endpoint_index].m_color5[0];
+ int g5 = m_endpoint_palette[old_endpoint_index].m_color5[1];
+ int b5 = m_endpoint_palette[old_endpoint_index].m_color5[2];
+ if ((r5 != g5) || (r5 != b5))
+ {
+ is_grayscale = false;
+ break;
+ }
+ }
+
+ histogram color5_delta_hist0(32); // prev 0-9, delta is -9 to 31
+ histogram color5_delta_hist1(32); // prev 10-21, delta is -21 to 21
+ histogram color5_delta_hist2(32); // prev 22-31, delta is -31 to 9
+ histogram inten_delta_hist(8);
+
+ color_rgba prev_color5(16, 16, 16, 0);
+ uint32_t prev_inten = 0;
+
+ for (uint32_t new_endpoint_index = 0; new_endpoint_index < r.get_total_endpoint_clusters(); new_endpoint_index++)
+ {
+ const uint32_t old_endpoint_index = endpoint_remap_table_inv[new_endpoint_index];
+
+ int delta_inten = m_endpoint_palette[old_endpoint_index].m_inten5 - prev_inten;
+ inten_delta_hist.inc(delta_inten & 7);
+ prev_inten = m_endpoint_palette[old_endpoint_index].m_inten5;
+
+ for (uint32_t i = 0; i < (is_grayscale ? 1U : 3U); i++)
+ {
+ const int delta = (m_endpoint_palette[old_endpoint_index].m_color5[i] - prev_color5[i]) & 31;
+
+ if (prev_color5[i] <= basist::COLOR5_PAL0_PREV_HI)
+ color5_delta_hist0.inc(delta);
+ else if (prev_color5[i] <= basist::COLOR5_PAL1_PREV_HI)
+ color5_delta_hist1.inc(delta);
+ else
+ color5_delta_hist2.inc(delta);
+
+ prev_color5[i] = m_endpoint_palette[old_endpoint_index].m_color5[i];
+ }
+ }
+
+ if (!color5_delta_hist0.get_total()) color5_delta_hist0.inc(0);
+ if (!color5_delta_hist1.get_total()) color5_delta_hist1.inc(0);
+ if (!color5_delta_hist2.get_total()) color5_delta_hist2.inc(0);
+
+ huffman_encoding_table color5_delta_model0, color5_delta_model1, color5_delta_model2, inten_delta_model;
+ if (!color5_delta_model0.init(color5_delta_hist0, 16))
+ {
+ error_printf("color5_delta_model.init() failed!");
+ return false;
+ }
+
+ if (!color5_delta_model1.init(color5_delta_hist1, 16))
+ {
+ error_printf("color5_delta_model.init() failed!");
+ return false;
+ }
+
+ if (!color5_delta_model2.init(color5_delta_hist2, 16))
+ {
+ error_printf("color5_delta_model.init() failed!");
+ return false;
+ }
+
+ if (!inten_delta_model.init(inten_delta_hist, 16))
+ {
+ error_printf("inten3_model.init() failed!");
+ return false;
+ }
+
+ bitwise_coder coder;
+
+ coder.init(8192);
+
+ coder.emit_huffman_table(color5_delta_model0);
+ coder.emit_huffman_table(color5_delta_model1);
+ coder.emit_huffman_table(color5_delta_model2);
+ coder.emit_huffman_table(inten_delta_model);
+
+ coder.put_bits(is_grayscale, 1);
+
+ prev_color5.set(16, 16, 16, 0);
+ prev_inten = 0;
+
+ for (uint32_t new_endpoint_index = 0; new_endpoint_index < r.get_total_endpoint_clusters(); new_endpoint_index++)
+ {
+ const uint32_t old_endpoint_index = endpoint_remap_table_inv[new_endpoint_index];
+
+ int delta_inten = (m_endpoint_palette[old_endpoint_index].m_inten5 - prev_inten) & 7;
+ coder.put_code(delta_inten, inten_delta_model);
+ prev_inten = m_endpoint_palette[old_endpoint_index].m_inten5;
+
+ for (uint32_t i = 0; i < (is_grayscale ? 1U : 3U); i++)
+ {
+ const int delta = (m_endpoint_palette[old_endpoint_index].m_color5[i] - prev_color5[i]) & 31;
+
+ if (prev_color5[i] <= basist::COLOR5_PAL0_PREV_HI)
+ coder.put_code(delta, color5_delta_model0);
+ else if (prev_color5[i] <= basist::COLOR5_PAL1_PREV_HI)
+ coder.put_code(delta, color5_delta_model1);
+ else
+ coder.put_code(delta, color5_delta_model2);
+
+ prev_color5[i] = m_endpoint_palette[old_endpoint_index].m_color5[i];
+ }
+
+ } // q
+
+ coder.flush();
+
+ m_output.m_endpoint_palette = coder.get_bytes();
+
+ debug_printf("Endpoint codebook size: %u bits %u bytes, Bits per entry: %3.1f, Avg bits/texel: %3.3f\n",
+ 8 * (int)m_output.m_endpoint_palette.size(), (int)m_output.m_endpoint_palette.size(), m_output.m_endpoint_palette.size() * 8.0f / r.get_total_endpoint_clusters(), m_output.m_endpoint_palette.size() * 8.0f / get_total_input_texels());
+
+ return true;
+ }
+
+ bool basisu_backend::encode_selector_palette()
+ {
+ const basisu_frontend& r = *m_pFront_end;
+
+ if ((m_params.m_use_global_sel_codebook) && (!m_params.m_use_hybrid_sel_codebooks))
+ {
+ histogram global_mod_indices(1 << m_params.m_global_sel_codebook_mod_bits);
+
+ for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
+ global_mod_indices.inc(m_global_selector_palette_desc[q].m_mod_index);
+
+ huffman_encoding_table global_pal_model, global_mod_model;
+
+ if (!global_mod_model.init(global_mod_indices, 16))
+ {
+ error_printf("global_mod_model.init() failed!");
+ return false;
+ }
+
+ bitwise_coder coder;
+ coder.init(1024 * 1024);
+
+ coder.put_bits(1, 1); // use global codebook
+
+ coder.put_bits(m_params.m_global_sel_codebook_pal_bits, 4); // pal bits
+ coder.put_bits(m_params.m_global_sel_codebook_mod_bits, 4); // mod bits
+
+ uint32_t mod_model_bits = 0;
+ if (m_params.m_global_sel_codebook_mod_bits)
+ mod_model_bits = coder.emit_huffman_table(global_mod_model);
+
+ uint32_t total_pal_bits = 0;
+ uint32_t total_mod_bits = 0;
+ for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
+ {
+ const uint32_t i = m_selector_remap_table_new_to_old[q];
+
+ if (m_params.m_global_sel_codebook_pal_bits)
+ {
+ coder.put_bits(m_global_selector_palette_desc[i].m_pal_index, m_params.m_global_sel_codebook_pal_bits);
+ total_pal_bits += m_params.m_global_sel_codebook_pal_bits;
+ }
+
+ if (m_params.m_global_sel_codebook_mod_bits)
+ total_mod_bits += coder.put_code(m_global_selector_palette_desc[i].m_mod_index, global_mod_model);
+ }
+
+ coder.flush();
+
+ m_output.m_selector_palette = coder.get_bytes();
+
+ debug_printf("Modifier model bits: %u Avg per entry: %3.3f\n", mod_model_bits, mod_model_bits / float(r.get_total_selector_clusters()));
+ debug_printf("Palette bits: %u Avg per entry: %3.3f, Modifier bits: %u Avg per entry: %3.3f\n", total_pal_bits, total_pal_bits / float(r.get_total_selector_clusters()), total_mod_bits, total_mod_bits / float(r.get_total_selector_clusters()));
+ }
+ else if (m_params.m_use_hybrid_sel_codebooks)
+ {
+ huff2D used_global_cb_bitflag_huff2D(1, 8);
+
+ histogram global_mod_indices(1 << m_params.m_global_sel_codebook_mod_bits);
+
+ for (uint32_t s = 0; s < r.get_total_selector_clusters(); s++)
+ {
+ const uint32_t q = m_selector_remap_table_new_to_old[s];
+
+ const bool used_global_cb_flag = r.get_selector_cluster_uses_global_cb_vec()[q];
+
+ used_global_cb_bitflag_huff2D.emit(used_global_cb_flag);
+
+ global_mod_indices.inc(m_global_selector_palette_desc[q].m_mod_index);
+ }
+
+ huffman_encoding_table global_mod_indices_model;
+ if (!global_mod_indices_model.init(global_mod_indices, 16))
+ {
+ error_printf("global_mod_indices_model.init() failed!");
+ return false;
+ }
+
+ bitwise_coder coder;
+ coder.init(1024 * 1024);
+
+ coder.put_bits(0, 1); // use global codebook
+ coder.put_bits(1, 1); // uses hybrid codebooks
+
+ coder.put_bits(m_params.m_global_sel_codebook_pal_bits, 4); // pal bits
+ coder.put_bits(m_params.m_global_sel_codebook_mod_bits, 4); // mod bits
+
+ used_global_cb_bitflag_huff2D.start_encoding(16);
+ coder.emit_huffman_table(used_global_cb_bitflag_huff2D.get_encoding_table());
+
+ if (m_params.m_global_sel_codebook_mod_bits)
+ coder.emit_huffman_table(global_mod_indices_model);
+
+ uint32_t total_global_cb_entries = 0;
+ uint32_t total_pal_bits = 0;
+ uint32_t total_mod_bits = 0;
+ uint32_t total_selectors = 0;
+ uint32_t total_selector_bits = 0;
+ uint32_t total_flag_bits = 0;
+
+ for (uint32_t s = 0; s < r.get_total_selector_clusters(); s++)
+ {
+ const uint32_t q = m_selector_remap_table_new_to_old[s];
+
+ total_flag_bits += used_global_cb_bitflag_huff2D.emit_next_sym(coder);
+
+ const bool used_global_cb_flag = r.get_selector_cluster_uses_global_cb_vec()[q];
+
+ if (used_global_cb_flag)
+ {
+ total_global_cb_entries++;
+
+ total_pal_bits += coder.put_bits(r.get_selector_cluster_global_selector_entry_ids()[q].m_palette_index, m_params.m_global_sel_codebook_pal_bits);
+ total_mod_bits += coder.put_code(r.get_selector_cluster_global_selector_entry_ids()[q].m_modifier.get_index(), global_mod_indices_model);
+ }
+ else
+ {
+ total_selectors++;
+ total_selector_bits += 32;
+
+ for (uint32_t j = 0; j < 4; j++)
+ coder.put_bits(m_selector_palette[q].get_byte(j), 8);
+ }
+ }
+
+ coder.flush();
+
+ m_output.m_selector_palette = coder.get_bytes();
+
+ debug_printf("Total global CB entries: %u %3.2f%%\n", total_global_cb_entries, total_global_cb_entries * 100.0f / r.get_total_selector_clusters());
+ debug_printf("Total selector entries: %u %3.2f%%\n", total_selectors, total_selectors * 100.0f / r.get_total_selector_clusters());
+ debug_printf("Total pal bits: %u, mod bits: %u, selector bits: %u, flag bits: %u\n", total_pal_bits, total_mod_bits, total_selector_bits, total_flag_bits);
+ }
+ else
+ {
+ histogram delta_selector_pal_histogram(256);
+
+ for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
+ {
+ if (!q)
+ continue;
+
+ const basist::etc1_selector_palette_entry& cur = m_selector_palette[m_selector_remap_table_new_to_old[q]];
+ const basist::etc1_selector_palette_entry predictor(m_selector_palette[m_selector_remap_table_new_to_old[q - 1]]);
+
+ for (uint32_t j = 0; j < 4; j++)
+ delta_selector_pal_histogram.inc(cur.get_byte(j) ^ predictor.get_byte(j));
+ }
+
+ if (!delta_selector_pal_histogram.get_total())
+ delta_selector_pal_histogram.inc(0);
+
+ huffman_encoding_table delta_selector_pal_model;
+ if (!delta_selector_pal_model.init(delta_selector_pal_histogram, 16))
+ {
+ error_printf("delta_selector_pal_model.init() failed!");
+ return false;
+ }
+
+ bitwise_coder coder;
+ coder.init(1024 * 1024);
+
+ coder.put_bits(0, 1); // use global codebook
+ coder.put_bits(0, 1); // uses hybrid codebooks
+
+ coder.put_bits(0, 1); // raw bytes
+
+ coder.emit_huffman_table(delta_selector_pal_model);
+
+ for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
+ {
+ if (!q)
+ {
+ for (uint32_t j = 0; j < 4; j++)
+ coder.put_bits(m_selector_palette[m_selector_remap_table_new_to_old[q]].get_byte(j), 8);
+ continue;
+ }
+
+ const basist::etc1_selector_palette_entry& cur = m_selector_palette[m_selector_remap_table_new_to_old[q]];
+ const basist::etc1_selector_palette_entry predictor(m_selector_palette[m_selector_remap_table_new_to_old[q - 1]]);
+
+ for (uint32_t j = 0; j < 4; j++)
+ coder.put_code(cur.get_byte(j) ^ predictor.get_byte(j), delta_selector_pal_model);
+ }
+
+ coder.flush();
+
+ m_output.m_selector_palette = coder.get_bytes();
+
+ if (m_output.m_selector_palette.size() >= r.get_total_selector_clusters() * 4)
+ {
+ coder.init(1024 * 1024);
+
+ coder.put_bits(0, 1); // use global codebook
+ coder.put_bits(0, 1); // uses hybrid codebooks
+
+ coder.put_bits(1, 1); // raw bytes
+
+ for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
+ {
+ const uint32_t i = m_selector_remap_table_new_to_old[q];
+
+ for (uint32_t j = 0; j < 4; j++)
+ coder.put_bits(m_selector_palette[i].get_byte(j), 8);
+ }
+
+ coder.flush();
+
+ m_output.m_selector_palette = coder.get_bytes();
+ }
+
+ } // if (m_params.m_use_global_sel_codebook)
+
+ debug_printf("Selector codebook bits: %u bytes: %u, Bits per entry: %3.1f, Avg bits/texel: %3.3f\n",
+ (int)m_output.m_selector_palette.size() * 8, (int)m_output.m_selector_palette.size(),
+ m_output.m_selector_palette.size() * 8.0f / r.get_total_selector_clusters(), m_output.m_selector_palette.size() * 8.0f / get_total_input_texels());
+
+ return true;
+ }
+
+ uint32_t basisu_backend::encode()
+ {
+ const bool is_video = m_pFront_end->get_params().m_tex_type == basist::cBASISTexTypeVideoFrames;
+ m_output.m_slice_desc = m_slices;
+ m_output.m_etc1s = m_params.m_etc1s;
+
+ create_endpoint_palette();
+ create_selector_palette();
+
+ create_encoder_blocks();
+
+ if (!encode_image())
+ return 0;
+
+ if (!encode_endpoint_palette())
+ return 0;
+
+ if (!encode_selector_palette())
+ return 0;
+
+ uint32_t total_compressed_bytes = (uint32_t)(m_output.m_slice_image_tables.size() + m_output.m_endpoint_palette.size() + m_output.m_selector_palette.size());
+ for (uint32_t i = 0; i < m_output.m_slice_image_data.size(); i++)
+ total_compressed_bytes += (uint32_t)m_output.m_slice_image_data[i].size();
+
+ debug_printf("Wrote %u bytes, %3.3f bits/texel\n", total_compressed_bytes, total_compressed_bytes * 8.0f / get_total_input_texels());
+
+ return total_compressed_bytes;
+ }
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_backend.h b/thirdparty/basis_universal/basisu_backend.h
new file mode 100644
index 0000000000..1c72fa8cc8
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_backend.h
@@ -0,0 +1,327 @@
+// basisu_backend.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include "transcoder/basisu.h"
+#include "basisu_enc.h"
+#include "transcoder/basisu_transcoder_internal.h"
+#include "transcoder/basisu_global_selector_palette.h"
+#include "basisu_frontend.h"
+
+namespace basisu
+{
+ struct encoder_block
+ {
+ encoder_block()
+ {
+ clear();
+ }
+
+ uint32_t m_endpoint_predictor;
+
+ int m_endpoint_index;
+ int m_selector_index;
+
+ int m_selector_history_buf_index;
+
+ bool m_is_cr_target;
+ void clear()
+ {
+ m_endpoint_predictor = 0;
+
+ m_endpoint_index = 0;
+ m_selector_index = 0;
+
+ m_selector_history_buf_index = 0;
+ m_is_cr_target = false;
+ }
+ };
+
+ typedef std::vector<encoder_block> encoder_block_vec;
+ typedef vector2D<encoder_block> encoder_block_vec2D;
+
+ struct etc1_endpoint_palette_entry
+ {
+ etc1_endpoint_palette_entry()
+ {
+ clear();
+ }
+
+ color_rgba m_color5;
+ uint32_t m_inten5;
+ bool m_color5_valid;
+
+ void clear()
+ {
+ clear_obj(*this);
+ }
+ };
+
+ typedef std::vector<etc1_endpoint_palette_entry> etc1_endpoint_palette_entry_vec;
+
+ struct basisu_backend_params
+ {
+ bool m_etc1s;
+ bool m_debug, m_debug_images;
+ float m_endpoint_rdo_quality_thresh;
+ float m_selector_rdo_quality_thresh;
+ uint32_t m_compression_level;
+
+ bool m_use_global_sel_codebook;
+ uint32_t m_global_sel_codebook_pal_bits;
+ uint32_t m_global_sel_codebook_mod_bits;
+ bool m_use_hybrid_sel_codebooks;
+
+ basisu_backend_params()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ m_etc1s = false;
+ m_debug = false;
+ m_debug_images = false;
+ m_endpoint_rdo_quality_thresh = 0.0f;
+ m_selector_rdo_quality_thresh = 0.0f;
+ m_compression_level = 0;
+
+ m_use_global_sel_codebook = false;
+ m_global_sel_codebook_pal_bits = ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_PAL_BITS;
+ m_global_sel_codebook_mod_bits = basist::etc1_global_palette_entry_modifier::cTotalBits;
+ m_use_hybrid_sel_codebooks = false;
+ }
+ };
+
+ struct basisu_backend_slice_desc
+ {
+ basisu_backend_slice_desc()
+ {
+ clear();
+ }
+ void clear()
+ {
+ clear_obj(*this);
+ }
+ uint32_t m_first_block_index;
+
+ uint32_t m_orig_width;
+ uint32_t m_orig_height;
+
+ uint32_t m_width;
+ uint32_t m_height;
+
+ uint32_t m_num_blocks_x;
+ uint32_t m_num_blocks_y;
+
+ uint32_t m_num_macroblocks_x;
+ uint32_t m_num_macroblocks_y;
+
+ uint32_t m_source_file_index; // also the basis image index
+ uint32_t m_mip_index;
+ bool m_alpha;
+ bool m_iframe;
+ };
+
+ typedef std::vector<basisu_backend_slice_desc> basisu_backend_slice_desc_vec;
+
+ struct basisu_backend_output
+ {
+ bool m_etc1s;
+
+ uint32_t m_num_endpoints;
+ uint32_t m_num_selectors;
+
+ uint8_vec m_endpoint_palette;
+ uint8_vec m_selector_palette;
+
+ basisu_backend_slice_desc_vec m_slice_desc;
+
+ uint8_vec m_slice_image_tables;
+ std::vector<uint8_vec> m_slice_image_data;
+ uint16_vec m_slice_image_crcs;
+
+ basisu_backend_output()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ m_etc1s = false;
+
+ m_num_endpoints = 0;
+ m_num_selectors = 0;
+
+ m_endpoint_palette.clear();
+ m_selector_palette.clear();
+ m_slice_desc.clear();
+ m_slice_image_tables.clear();
+ m_slice_image_data.clear();
+ m_slice_image_crcs.clear();
+ }
+
+ uint32_t get_output_size_estimate() const
+ {
+ uint32_t total_compressed_bytes = (uint32_t)(m_slice_image_tables.size() + m_endpoint_palette.size() + m_selector_palette.size());
+ for (uint32_t i = 0; i < m_slice_image_data.size(); i++)
+ total_compressed_bytes += (uint32_t)m_slice_image_data[i].size();
+
+ return total_compressed_bytes;
+ }
+ };
+
+ class basisu_backend
+ {
+ BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(basisu_backend);
+
+ public:
+
+ basisu_backend();
+
+ void clear();
+
+ void init(basisu_frontend *pFront_end, basisu_backend_params &params, const basisu_backend_slice_desc_vec &slice_desc, const basist::etc1_global_selector_codebook *pGlobal_sel_codebook);
+
+ uint32_t encode();
+
+ const basisu_backend_output &get_output() const { return m_output; }
+
+ private:
+ basisu_frontend *m_pFront_end;
+ basisu_backend_params m_params;
+ basisu_backend_slice_desc_vec m_slices;
+ basisu_backend_output m_output;
+ const basist::etc1_global_selector_codebook *m_pGlobal_sel_codebook;
+
+ etc1_endpoint_palette_entry_vec m_endpoint_palette;
+ basist::etc1_selector_palette_entry_vec m_selector_palette;
+
+ struct etc1_global_selector_cb_entry_desc
+ {
+ uint32_t m_pal_index;
+ uint32_t m_mod_index;
+ bool m_was_used;
+ };
+
+ typedef std::vector<etc1_global_selector_cb_entry_desc> etc1_global_selector_cb_entry_desc_vec;
+
+ etc1_global_selector_cb_entry_desc_vec m_global_selector_palette_desc;
+
+ std::vector<encoder_block_vec2D> m_slice_encoder_blocks;
+
+ // Maps OLD to NEW endpoint/selector indices
+ uint_vec m_endpoint_remap_table_old_to_new;
+ uint_vec m_endpoint_remap_table_new_to_old;
+
+ uint_vec m_selector_remap_table_old_to_new;
+
+ // Maps NEW to OLD endpoint/selector indices
+ uint_vec m_selector_remap_table_new_to_old;
+
+ uint32_t get_total_slices() const
+ {
+ return (uint32_t)m_slices.size();
+ }
+
+ uint32_t get_total_slice_blocks() const
+ {
+ return m_pFront_end->get_total_output_blocks();
+ }
+
+ uint32_t get_block_index(uint32_t slice_index, uint32_t block_x, uint32_t block_y) const
+ {
+ const basisu_backend_slice_desc &slice = m_slices[slice_index];
+
+ assert((block_x < slice.m_num_blocks_x) && (block_y < slice.m_num_blocks_y));
+
+ return slice.m_first_block_index + block_y * slice.m_num_blocks_x + block_x;
+ }
+
+ uint32_t get_total_blocks(uint32_t slice_index) const
+ {
+ return m_slices[slice_index].m_num_blocks_x * m_slices[slice_index].m_num_blocks_y;
+ }
+
+ uint32_t get_total_blocks() const
+ {
+ uint32_t total_blocks = 0;
+ for (uint32_t i = 0; i < m_slices.size(); i++)
+ total_blocks += get_total_blocks(i);
+ return total_blocks;
+ }
+
+ // Returns the total number of input texels, not counting padding up to blocks/macroblocks.
+ uint32_t get_total_input_texels(uint32_t slice_index) const
+ {
+ return m_slices[slice_index].m_orig_width * m_slices[slice_index].m_orig_height;
+ }
+
+ uint32_t get_total_input_texels() const
+ {
+ uint32_t total_texels = 0;
+ for (uint32_t i = 0; i < m_slices.size(); i++)
+ total_texels += get_total_input_texels(i);
+ return total_texels;
+ }
+
+ int find_slice(uint32_t block_index, uint32_t *pBlock_x, uint32_t *pBlock_y) const
+ {
+ for (uint32_t i = 0; i < m_slices.size(); i++)
+ {
+ if ((block_index >= m_slices[i].m_first_block_index) && (block_index < (m_slices[i].m_first_block_index + m_slices[i].m_num_blocks_x * m_slices[i].m_num_blocks_y)))
+ {
+ const uint32_t ofs = block_index - m_slices[i].m_first_block_index;
+ const uint32_t x = ofs % m_slices[i].m_num_blocks_x;
+ const uint32_t y = ofs / m_slices[i].m_num_blocks_x;
+
+ if (pBlock_x) *pBlock_x = x;
+ if (pBlock_y) *pBlock_y = y;
+
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ void create_endpoint_palette();
+
+ void create_selector_palette();
+
+ // endpoint palette
+ // 5:5:5 and predicted 4:4:4 colors, 1 or 2 3-bit intensity table indices
+ // selector palette
+ // 4x4 2-bit selectors
+
+ // per-macroblock:
+ // 4 diff bits
+ // 4 flip bits
+ // Endpoint template index, 1-8 endpoint indices
+ // Alternately, if no template applies, we can send 4 ETC1S bits followed by 4-8 endpoint indices
+ // 4 selector indices
+
+ void reoptimize_and_sort_endpoints_codebook(uint32_t total_block_endpoints_remapped, uint_vec &all_endpoint_indices);
+ void sort_selector_codebook();
+ void create_encoder_blocks();
+ void compute_slice_crcs();
+ bool encode_image();
+ bool encode_endpoint_palette();
+ bool encode_selector_palette();
+ int find_video_frame(int slice_index, int delta);
+ void check_for_valid_cr_blocks();
+ };
+
+} // namespace basisu
+
diff --git a/thirdparty/basis_universal/basisu_basis_file.cpp b/thirdparty/basis_universal/basisu_basis_file.cpp
new file mode 100644
index 0000000000..3e6b1906b9
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_basis_file.cpp
@@ -0,0 +1,204 @@
+// basisu_basis_file.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_basis_file.h"
+#include "transcoder/basisu_transcoder.h"
+
+// The output file version. Keep in sync with BASISD_SUPPORTED_BASIS_VERSION.
+#define BASIS_FILE_VERSION (0x13)
+
+namespace basisu
+{
+ void basisu_file::create_header(const basisu_backend_output &encoder_output, basist::basis_texture_type tex_type, uint32_t userdata0, uint32_t userdata1, bool y_flipped, uint32_t us_per_frame)
+ {
+ m_header.m_header_size = sizeof(basist::basis_file_header);
+
+ m_header.m_data_size = m_total_file_size - sizeof(basist::basis_file_header);
+
+ m_header.m_total_slices = (uint32_t)encoder_output.m_slice_desc.size();
+
+ m_header.m_total_images = 0;
+ for (uint32_t i = 0; i < encoder_output.m_slice_desc.size(); i++)
+ m_header.m_total_images = maximum<uint32_t>(m_header.m_total_images, encoder_output.m_slice_desc[i].m_source_file_index + 1);
+
+ m_header.m_format = 0;// basist::block_format::cETC1;
+ m_header.m_flags = 0;
+
+ if (encoder_output.m_etc1s)
+ m_header.m_flags = m_header.m_flags | basist::cBASISHeaderFlagETC1S;
+
+ if (y_flipped)
+ m_header.m_flags = m_header.m_flags | basist::cBASISHeaderFlagYFlipped;
+
+ for (uint32_t i = 0; i < encoder_output.m_slice_desc.size(); i++)
+ {
+ if (encoder_output.m_slice_desc[i].m_alpha)
+ {
+ m_header.m_flags = m_header.m_flags | basist::cBASISHeaderFlagHasAlphaSlices;
+ break;
+ }
+ }
+
+ m_header.m_tex_type = static_cast<uint8_t>(tex_type);
+ m_header.m_us_per_frame = clamp<uint32_t>(us_per_frame, 0, basist::cBASISMaxUSPerFrame);
+
+ m_header.m_userdata0 = userdata0;
+ m_header.m_userdata1 = userdata1;
+
+ m_header.m_total_endpoints = encoder_output.m_num_endpoints;
+ m_header.m_endpoint_cb_file_ofs = m_endpoint_cb_file_ofs;
+ m_header.m_endpoint_cb_file_size = (uint32_t)encoder_output.m_endpoint_palette.size();
+
+ m_header.m_total_selectors = encoder_output.m_num_selectors;
+ m_header.m_selector_cb_file_ofs = m_selector_cb_file_ofs;
+ m_header.m_selector_cb_file_size = (uint32_t)encoder_output.m_selector_palette.size();
+
+ m_header.m_tables_file_ofs = m_tables_file_ofs;
+ m_header.m_tables_file_size = (uint32_t)encoder_output.m_slice_image_tables.size();
+
+ m_header.m_slice_desc_file_ofs = m_slice_descs_file_ofs;
+ }
+
+ bool basisu_file::create_image_descs(const basisu_backend_output &encoder_output)
+ {
+ const basisu_backend_slice_desc_vec &slice_descs = encoder_output.m_slice_desc;
+
+ m_images_descs.resize(slice_descs.size());
+
+ uint64_t cur_slice_file_ofs = m_first_image_file_ofs;
+ for (uint32_t i = 0; i < slice_descs.size(); i++)
+ {
+ clear_obj(m_images_descs[i]);
+
+ m_images_descs[i].m_image_index = slice_descs[i].m_source_file_index;
+ m_images_descs[i].m_level_index = slice_descs[i].m_mip_index;
+
+ if (slice_descs[i].m_alpha)
+ m_images_descs[i].m_flags = m_images_descs[i].m_flags | basist::cSliceDescFlagsIsAlphaData;
+ if (slice_descs[i].m_iframe)
+ m_images_descs[i].m_flags = m_images_descs[i].m_flags | basist::cSliceDescFlagsFrameIsIFrame;
+
+ m_images_descs[i].m_orig_width = slice_descs[i].m_orig_width;
+ m_images_descs[i].m_orig_height = slice_descs[i].m_orig_height;
+ m_images_descs[i].m_num_blocks_x = slice_descs[i].m_num_blocks_x;
+ m_images_descs[i].m_num_blocks_y = slice_descs[i].m_num_blocks_y;
+ m_images_descs[i].m_slice_data_crc16 = encoder_output.m_slice_image_crcs[i];
+
+ if (encoder_output.m_slice_image_data[i].size() > UINT32_MAX)
+ {
+ error_printf("basisu_file::create_image_descs: Basis file too large\n");
+ return false;
+ }
+
+ const uint32_t image_size = (uint32_t)encoder_output.m_slice_image_data[i].size();
+
+ m_images_descs[i].m_file_ofs = (uint32_t)cur_slice_file_ofs;
+ m_images_descs[i].m_file_size = image_size;
+
+ cur_slice_file_ofs += image_size;
+ if (cur_slice_file_ofs > UINT32_MAX)
+ {
+ error_printf("basisu_file::create_image_descs: Basis file too large\n");
+ return false;
+ }
+ }
+
+ assert(cur_slice_file_ofs == m_total_file_size);
+ return true;
+ }
+
+ void basisu_file::create_comp_data(const basisu_backend_output &encoder_output)
+ {
+ const basisu_backend_slice_desc_vec &slice_descs = encoder_output.m_slice_desc;
+
+ append_vector(m_comp_data, reinterpret_cast<const uint8_t *>(&m_header), sizeof(m_header));
+
+ assert(m_comp_data.size() == m_slice_descs_file_ofs);
+ append_vector(m_comp_data, reinterpret_cast<const uint8_t*>(&m_images_descs[0]), m_images_descs.size() * sizeof(m_images_descs[0]));
+
+ assert(m_comp_data.size() == m_endpoint_cb_file_ofs);
+ append_vector(m_comp_data, reinterpret_cast<const uint8_t*>(&encoder_output.m_endpoint_palette[0]), encoder_output.m_endpoint_palette.size());
+
+ assert(m_comp_data.size() == m_selector_cb_file_ofs);
+ append_vector(m_comp_data, reinterpret_cast<const uint8_t*>(&encoder_output.m_selector_palette[0]), encoder_output.m_selector_palette.size());
+
+ assert(m_comp_data.size() == m_tables_file_ofs);
+ append_vector(m_comp_data, reinterpret_cast<const uint8_t*>(&encoder_output.m_slice_image_tables[0]), encoder_output.m_slice_image_tables.size());
+
+ assert(m_comp_data.size() == m_first_image_file_ofs);
+ for (uint32_t i = 0; i < slice_descs.size(); i++)
+ append_vector(m_comp_data, &encoder_output.m_slice_image_data[i][0], encoder_output.m_slice_image_data[i].size());
+
+ assert(m_comp_data.size() == m_total_file_size);
+ }
+
+ void basisu_file::fixup_crcs()
+ {
+ basist::basis_file_header *pHeader = reinterpret_cast<basist::basis_file_header *>(&m_comp_data[0]);
+
+ pHeader->m_data_size = m_total_file_size - sizeof(basist::basis_file_header);
+ pHeader->m_data_crc16 = basist::crc16(&m_comp_data[0] + sizeof(basist::basis_file_header), m_total_file_size - sizeof(basist::basis_file_header), 0);
+
+ pHeader->m_header_crc16 = basist::crc16(&pHeader->m_data_size, sizeof(basist::basis_file_header) - BASISU_OFFSETOF(basist::basis_file_header, m_data_size), 0);
+
+ pHeader->m_sig = basist::basis_file_header::cBASISSigValue;
+ pHeader->m_ver = BASIS_FILE_VERSION;// basist::basis_file_header::cBASISFirstVersion;
+ }
+
+ bool basisu_file::init(const basisu_backend_output &encoder_output, basist::basis_texture_type tex_type, uint32_t userdata0, uint32_t userdata1, bool y_flipped, uint32_t us_per_frame)
+ {
+ clear();
+
+ const basisu_backend_slice_desc_vec &slice_descs = encoder_output.m_slice_desc;
+
+ // The Basis file uses 32-bit fields for lots of stuff, so make sure it's not too large.
+ uint64_t check_size = (uint64_t)sizeof(basist::basis_file_header) + (uint64_t)sizeof(basist::basis_slice_desc) * slice_descs.size() +
+ (uint64_t)encoder_output.m_endpoint_palette.size() + (uint64_t)encoder_output.m_selector_palette.size() + (uint64_t)encoder_output.m_slice_image_tables.size();
+ if (check_size >= 0xFFFF0000ULL)
+ {
+ error_printf("basisu_file::init: File is too large!\n");
+ return false;
+ }
+
+ m_header_file_ofs = 0;
+ m_slice_descs_file_ofs = sizeof(basist::basis_file_header);
+ m_endpoint_cb_file_ofs = m_slice_descs_file_ofs + sizeof(basist::basis_slice_desc) * (uint32_t)slice_descs.size();
+ m_selector_cb_file_ofs = m_endpoint_cb_file_ofs + (uint32_t)encoder_output.m_endpoint_palette.size();
+ m_tables_file_ofs = m_selector_cb_file_ofs + (uint32_t)encoder_output.m_selector_palette.size();
+ m_first_image_file_ofs = m_tables_file_ofs + (uint32_t)encoder_output.m_slice_image_tables.size();
+
+ uint64_t total_file_size = m_first_image_file_ofs;
+ for (uint32_t i = 0; i < encoder_output.m_slice_image_data.size(); i++)
+ total_file_size += encoder_output.m_slice_image_data[i].size();
+ if (total_file_size >= 0xFFFF0000ULL)
+ {
+ error_printf("basisu_file::init: File is too large!\n");
+ return false;
+ }
+
+ m_total_file_size = (uint32_t)total_file_size;
+
+ create_header(encoder_output, tex_type, userdata0, userdata1, y_flipped, us_per_frame);
+
+ if (!create_image_descs(encoder_output))
+ return false;
+
+ create_comp_data(encoder_output);
+
+ fixup_crcs();
+
+ return true;
+ }
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_basis_file.h b/thirdparty/basis_universal/basisu_basis_file.h
new file mode 100644
index 0000000000..df3abbdcfd
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_basis_file.h
@@ -0,0 +1,70 @@
+// basisu_basis_file.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "transcoder/basisu_file_headers.h"
+#include "basisu_backend.h"
+
+namespace basisu
+{
+ class basisu_file
+ {
+ BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(basisu_file);
+
+ public:
+ basisu_file()
+ {
+ }
+
+ void clear()
+ {
+ m_comp_data.clear();
+
+ clear_obj(m_header);
+ m_images_descs.clear();
+
+ m_header_file_ofs = 0;
+ m_slice_descs_file_ofs = 0;
+ m_endpoint_cb_file_ofs = 0;
+ m_selector_cb_file_ofs = 0;
+ m_tables_file_ofs = 0;
+ m_first_image_file_ofs = 0;
+ m_total_file_size = 0;
+ }
+
+ bool init(const basisu_backend_output& encoder_output, basist::basis_texture_type tex_type, uint32_t userdata0, uint32_t userdata1, bool y_flipped, uint32_t us_per_frame);
+
+ const uint8_vec &get_compressed_data() const { return m_comp_data; }
+
+ private:
+ basist::basis_file_header m_header;
+ std::vector<basist::basis_slice_desc> m_images_descs;
+
+ uint8_vec m_comp_data;
+
+ uint32_t m_header_file_ofs;
+ uint32_t m_slice_descs_file_ofs;
+ uint32_t m_endpoint_cb_file_ofs;
+ uint32_t m_selector_cb_file_ofs;
+ uint32_t m_tables_file_ofs;
+ uint32_t m_first_image_file_ofs;
+ uint32_t m_total_file_size;
+
+ void create_header(const basisu_backend_output& encoder_output, basist::basis_texture_type tex_type, uint32_t userdata0, uint32_t userdata1, bool y_flipped, uint32_t us_per_frame);
+ bool create_image_descs(const basisu_backend_output& encoder_output);
+ void create_comp_data(const basisu_backend_output& encoder_output);
+ void fixup_crcs();
+ };
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_comp.cpp b/thirdparty/basis_universal/basisu_comp.cpp
new file mode 100644
index 0000000000..1e4679311c
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_comp.cpp
@@ -0,0 +1,1206 @@
+// basisu_comp.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_comp.h"
+#include "basisu_enc.h"
+#include <unordered_set>
+
+#define BASISU_USE_STB_IMAGE_RESIZE_FOR_MIPMAP_GEN 0
+#define DEBUG_CROP_TEXTURE_TO_64x64 (0)
+#define DEBUG_RESIZE_TEXTURE (0)
+#define DEBUG_EXTRACT_SINGLE_BLOCK (0)
+
+namespace basisu
+{
+ basis_compressor::basis_compressor() :
+ m_total_blocks(0),
+ m_auto_global_sel_pal(false),
+ m_basis_file_size(0),
+ m_basis_bits_per_texel(0),
+ m_any_source_image_has_alpha(false)
+ {
+ debug_printf("basis_compressor::basis_compressor\n");
+ }
+
+ bool basis_compressor::init(const basis_compressor_params &params)
+ {
+ debug_printf("basis_compressor::init\n");
+
+ m_params = params;
+
+ if (m_params.m_debug)
+ {
+ debug_printf("basis_compressor::init:\n");
+
+#define PRINT_BOOL_VALUE(v) debug_printf("%s: %u %u\n", BASISU_STRINGIZE2(v), static_cast<int>(m_params.v), m_params.v.was_changed());
+#define PRINT_INT_VALUE(v) debug_printf("%s: %i %u\n", BASISU_STRINGIZE2(v), static_cast<int>(m_params.v), m_params.v.was_changed());
+#define PRINT_UINT_VALUE(v) debug_printf("%s: %u %u\n", BASISU_STRINGIZE2(v), static_cast<uint32_t>(m_params.v), m_params.v.was_changed());
+#define PRINT_FLOAT_VALUE(v) debug_printf("%s: %f %u\n", BASISU_STRINGIZE2(v), static_cast<float>(m_params.v), m_params.v.was_changed());
+
+ debug_printf("Has global selector codebook: %i\n", m_params.m_pSel_codebook != nullptr);
+
+ debug_printf("Source images: %u, source filenames: %u, source alpha filenames: %i\n",
+ (uint32_t)m_params.m_source_images.size(), (uint32_t)m_params.m_source_filenames.size(), (uint32_t)m_params.m_source_alpha_filenames.size());
+
+ PRINT_BOOL_VALUE(m_y_flip);
+ PRINT_BOOL_VALUE(m_debug);
+ PRINT_BOOL_VALUE(m_debug_images);
+ PRINT_BOOL_VALUE(m_global_sel_pal);
+ PRINT_BOOL_VALUE(m_auto_global_sel_pal);
+ PRINT_BOOL_VALUE(m_compression_level);
+ PRINT_BOOL_VALUE(m_no_hybrid_sel_cb);
+ PRINT_BOOL_VALUE(m_perceptual);
+ PRINT_BOOL_VALUE(m_no_endpoint_rdo);
+ PRINT_BOOL_VALUE(m_no_selector_rdo);
+ PRINT_BOOL_VALUE(m_read_source_images);
+ PRINT_BOOL_VALUE(m_write_output_basis_files);
+ PRINT_BOOL_VALUE(m_compute_stats);
+ PRINT_BOOL_VALUE(m_check_for_alpha)
+ PRINT_BOOL_VALUE(m_force_alpha)
+ PRINT_BOOL_VALUE(m_seperate_rg_to_color_alpha);
+ PRINT_BOOL_VALUE(m_multithreading);
+ PRINT_BOOL_VALUE(m_disable_hierarchical_endpoint_codebooks);
+
+ PRINT_FLOAT_VALUE(m_hybrid_sel_cb_quality_thresh);
+
+ PRINT_INT_VALUE(m_global_pal_bits);
+ PRINT_INT_VALUE(m_global_mod_bits);
+
+ PRINT_FLOAT_VALUE(m_endpoint_rdo_thresh);
+ PRINT_FLOAT_VALUE(m_selector_rdo_thresh);
+
+ PRINT_BOOL_VALUE(m_mip_gen);
+ PRINT_BOOL_VALUE(m_mip_renormalize);
+ PRINT_BOOL_VALUE(m_mip_wrapping);
+ PRINT_BOOL_VALUE(m_mip_srgb);
+ PRINT_FLOAT_VALUE(m_mip_premultiplied);
+ PRINT_FLOAT_VALUE(m_mip_scale);
+ PRINT_INT_VALUE(m_mip_smallest_dimension);
+ debug_printf("m_mip_filter: %s\n", m_params.m_mip_filter.c_str());
+
+ debug_printf("m_max_endpoint_clusters: %u\n", m_params.m_max_endpoint_clusters);
+ debug_printf("m_max_selector_clusters: %u\n", m_params.m_max_selector_clusters);
+ debug_printf("m_quality_level: %i\n", m_params.m_quality_level);
+
+ debug_printf("m_tex_type: %u\n", m_params.m_tex_type);
+ debug_printf("m_userdata0: 0x%X, m_userdata1: 0x%X\n", m_params.m_userdata0, m_params.m_userdata1);
+ debug_printf("m_us_per_frame: %i (%f fps)\n", m_params.m_us_per_frame, m_params.m_us_per_frame ? 1.0f / (m_params.m_us_per_frame / 1000000.0f) : 0);
+
+#undef PRINT_BOOL_VALUE
+#undef PRINT_INT_VALUE
+#undef PRINT_UINT_VALUE
+#undef PRINT_FLOAT_VALUE
+ }
+
+ if ((m_params.m_read_source_images) && (!m_params.m_source_filenames.size()))
+ {
+ assert(0);
+ return false;
+ }
+
+ return true;
+ }
+
+ basis_compressor::error_code basis_compressor::process()
+ {
+ debug_printf("basis_compressor::process\n");
+
+ if (!read_source_images())
+ return cECFailedReadingSourceImages;
+
+ if (!validate_texture_type_constraints())
+ return cECFailedValidating;
+
+ if (!process_frontend())
+ return cECFailedFrontEnd;
+
+ if (!extract_frontend_texture_data())
+ return cECFailedFontendExtract;
+
+ if (!process_backend())
+ return cECFailedBackend;
+
+ if (!create_basis_file_and_transcode())
+ return cECFailedCreateBasisFile;
+
+ if (!write_output_files_and_compute_stats())
+ return cECFailedWritingOutput;
+
+ return cECSuccess;
+ }
+
+ bool basis_compressor::generate_mipmaps(const image &img, std::vector<image> &mips, bool has_alpha)
+ {
+ debug_printf("basis_compressor::generate_mipmaps\n");
+
+ uint32_t total_levels = 1;
+ uint32_t w = img.get_width(), h = img.get_height();
+ while (maximum<uint32_t>(w, h) > (uint32_t)m_params.m_mip_smallest_dimension)
+ {
+ w = maximum(w >> 1U, 1U);
+ h = maximum(h >> 1U, 1U);
+ total_levels++;
+ }
+
+#if BASISU_USE_STB_IMAGE_RESIZE_FOR_MIPMAP_GEN
+ // Requires stb_image_resize
+ stbir_filter filter = STBIR_FILTER_DEFAULT;
+ if (m_params.m_mip_filter == "box")
+ filter = STBIR_FILTER_BOX;
+ else if (m_params.m_mip_filter == "triangle")
+ filter = STBIR_FILTER_TRIANGLE;
+ else if (m_params.m_mip_filter == "cubic")
+ filter = STBIR_FILTER_CUBICBSPLINE;
+ else if (m_params.m_mip_filter == "catmull")
+ filter = STBIR_FILTER_CATMULLROM;
+ else if (m_params.m_mip_filter == "mitchell")
+ filter = STBIR_FILTER_MITCHELL;
+
+ for (uint32_t level = 1; level < total_levels; level++)
+ {
+ const uint32_t level_width = maximum<uint32_t>(1, img.get_width() >> level);
+ const uint32_t level_height = maximum<uint32_t>(1, img.get_height() >> level);
+
+ image &level_img = *enlarge_vector(mips, 1);
+ level_img.resize(level_width, level_height);
+
+ int result = stbir_resize_uint8_generic(
+ (const uint8_t *)img.get_ptr(), img.get_width(), img.get_height(), img.get_pitch() * sizeof(color_rgba),
+ (uint8_t *)level_img.get_ptr(), level_img.get_width(), level_img.get_height(), level_img.get_pitch() * sizeof(color_rgba),
+ has_alpha ? 4 : 3, has_alpha ? 3 : STBIR_ALPHA_CHANNEL_NONE, m_params.m_mip_premultiplied ? STBIR_FLAG_ALPHA_PREMULTIPLIED : 0,
+ m_params.m_mip_wrapping ? STBIR_EDGE_WRAP : STBIR_EDGE_CLAMP, filter, m_params.m_mip_srgb ? STBIR_COLORSPACE_SRGB : STBIR_COLORSPACE_LINEAR,
+ nullptr);
+
+ if (result == 0)
+ {
+ error_printf("basis_compressor::generate_mipmaps: stbir_resize_uint8_generic() failed!\n");
+ return false;
+ }
+
+ if (m_params.m_mip_renormalize)
+ level_img.renormalize_normal_map();
+ }
+#else
+ for (uint32_t level = 1; level < total_levels; level++)
+ {
+ const uint32_t level_width = maximum<uint32_t>(1, img.get_width() >> level);
+ const uint32_t level_height = maximum<uint32_t>(1, img.get_height() >> level);
+
+ image &level_img = *enlarge_vector(mips, 1);
+ level_img.resize(level_width, level_height);
+
+ bool status = image_resample(img, level_img, m_params.m_mip_srgb, m_params.m_mip_filter.c_str(), m_params.m_mip_scale, m_params.m_mip_wrapping, 0, has_alpha ? 4 : 3);
+ if (!status)
+ {
+ error_printf("basis_compressor::generate_mipmaps: image_resample() failed!\n");
+ return false;
+ }
+
+ if (m_params.m_mip_renormalize)
+ level_img.renormalize_normal_map();
+ }
+#endif
+
+ return true;
+ }
+
+ bool basis_compressor::read_source_images()
+ {
+ debug_printf("basis_compressor::read_source_images\n");
+
+ const uint32_t total_source_files = m_params.m_read_source_images ? (uint32_t)m_params.m_source_filenames.size() : (uint32_t)m_params.m_source_images.size();
+ if (!total_source_files)
+ return false;
+
+ m_stats.resize(0);
+ m_slice_descs.resize(0);
+ m_slice_images.resize(0);
+
+ m_total_blocks = 0;
+ uint32_t total_macroblocks = 0;
+
+ m_any_source_image_has_alpha = false;
+
+ std::vector<image> source_images;
+ std::vector<std::string> source_filenames;
+
+ // First load all source images, and determine if any have an alpha channel.
+ for (uint32_t source_file_index = 0; source_file_index < total_source_files; source_file_index++)
+ {
+ const char *pSource_filename = "";
+
+ image file_image;
+
+ if (m_params.m_read_source_images)
+ {
+ pSource_filename = m_params.m_source_filenames[source_file_index].c_str();
+
+ // Load the source image
+ if (!load_png(pSource_filename, file_image))
+ {
+ error_printf("Failed reading source image: %s\n", pSource_filename);
+ return false;
+ }
+
+ printf("Read source image \"%s\", %ux%u\n", pSource_filename, file_image.get_width(), file_image.get_height());
+
+ // Optionally load another image and put a grayscale version of it into the alpha channel.
+ if ((source_file_index < m_params.m_source_alpha_filenames.size()) && (m_params.m_source_alpha_filenames[source_file_index].size()))
+ {
+ const char *pSource_alpha_image = m_params.m_source_alpha_filenames[source_file_index].c_str();
+
+ image alpha_data;
+
+ if (!load_png(pSource_alpha_image, alpha_data))
+ {
+ error_printf("Failed reading source image: %s\n", pSource_alpha_image);
+ return false;
+ }
+
+ printf("Read source alpha image \"%s\", %ux%u\n", pSource_alpha_image, alpha_data.get_width(), alpha_data.get_height());
+
+ alpha_data.crop(file_image.get_width(), file_image.get_height());
+
+ for (uint32_t y = 0; y < file_image.get_height(); y++)
+ for (uint32_t x = 0; x < file_image.get_width(); x++)
+ file_image(x, y).a = (uint8_t)alpha_data(x, y).get_709_luma();
+ }
+ }
+ else
+ {
+ file_image = m_params.m_source_images[source_file_index];
+ }
+
+ if (m_params.m_seperate_rg_to_color_alpha)
+ {
+ // Used for XY normal maps in RG - puts X in color, Y in alpha
+ for (uint32_t y = 0; y < file_image.get_height(); y++)
+ for (uint32_t x = 0; x < file_image.get_width(); x++)
+ {
+ const color_rgba &c = file_image(x, y);
+ file_image(x, y).set_noclamp_rgba(c.r, c.r, c.r, c.g);
+ }
+ }
+
+ bool has_alpha = false;
+ if ((m_params.m_force_alpha) || (m_params.m_seperate_rg_to_color_alpha))
+ has_alpha = true;
+ else if (!m_params.m_check_for_alpha)
+ file_image.set_alpha(255);
+ else if (file_image.has_alpha())
+ has_alpha = true;
+
+ if (has_alpha)
+ m_any_source_image_has_alpha = true;
+
+ debug_printf("Source image index %u filename %s %ux%u has alpha: %u\n", source_file_index, pSource_filename, file_image.get_width(), file_image.get_height(), has_alpha);
+
+ if (m_params.m_y_flip)
+ file_image.flip_y();
+
+#if DEBUG_EXTRACT_SINGLE_BLOCK
+ image block_image(4, 4);
+ const uint32_t block_x = 0;
+ const uint32_t block_y = 0;
+ block_image.blit(block_x * 4, block_y * 4, 4, 4, 0, 0, file_image, 0);
+ file_image = block_image;
+#endif
+
+#if DEBUG_CROP_TEXTURE_TO_64x64
+ file_image.resize(64, 64);
+#endif
+#if DEBUG_RESIZE_TEXTURE
+ image temp_img((file_image.get_width() + 1) / 2, (file_image.get_height() + 1) / 2);
+ image_resample(file_image, temp_img, m_params.m_perceptual, "kaiser");
+ temp_img.swap(file_image);
+#endif
+
+ if ((!file_image.get_width()) || (!file_image.get_height()))
+ {
+ error_printf("basis_compressor::read_source_images: Source image has a zero width and/or height!\n");
+ return false;
+ }
+
+ if ((file_image.get_width() > BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION) || (file_image.get_height() > BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION))
+ {
+ error_printf("basis_compressor::read_source_images: Source image is too large!\n");
+ return false;
+ }
+
+ source_images.push_back(file_image);
+ source_filenames.push_back(pSource_filename);
+ }
+
+ debug_printf("Any source image has alpha: %u\n", m_any_source_image_has_alpha);
+
+ for (uint32_t source_file_index = 0; source_file_index < total_source_files; source_file_index++)
+ {
+ image &file_image = source_images[source_file_index];
+ const std::string &source_filename = source_filenames[source_file_index];
+
+ std::vector<image> slices;
+
+ slices.reserve(32);
+ slices.push_back(file_image);
+
+ if (m_params.m_mip_gen)
+ {
+ if (!generate_mipmaps(file_image, slices, m_any_source_image_has_alpha))
+ return false;
+ }
+
+ uint_vec mip_indices(slices.size());
+ for (uint32_t i = 0; i < slices.size(); i++)
+ mip_indices[i] = i;
+
+ if (m_any_source_image_has_alpha)
+ {
+ // If source has alpha, then even mips will have RGB, and odd mips will have alpha in RGB.
+ std::vector<image> alpha_slices;
+ uint_vec new_mip_indices;
+
+ alpha_slices.reserve(slices.size() * 2);
+
+ for (uint32_t i = 0; i < slices.size(); i++)
+ {
+ image lvl_rgb(slices[i]);
+ image lvl_a(lvl_rgb);
+
+ for (uint32_t y = 0; y < lvl_a.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < lvl_a.get_width(); x++)
+ {
+ uint8_t a = lvl_a(x, y).a;
+ lvl_a(x, y).set_noclamp_rgba(a, a, a, 255);
+ }
+ }
+
+ lvl_rgb.set_alpha(255);
+
+ alpha_slices.push_back(lvl_rgb);
+ new_mip_indices.push_back(i);
+
+ alpha_slices.push_back(lvl_a);
+ new_mip_indices.push_back(i);
+ }
+
+ slices.swap(alpha_slices);
+ mip_indices.swap(new_mip_indices);
+ }
+
+ assert(slices.size() == mip_indices.size());
+
+ for (uint32_t slice_index = 0; slice_index < slices.size(); slice_index++)
+ {
+ const bool is_alpha_slice = m_any_source_image_has_alpha && ((slice_index & 1) != 0);
+
+ image &slice_image = slices[slice_index];
+ const uint32_t orig_width = slice_image.get_width();
+ const uint32_t orig_height = slice_image.get_height();
+
+ // Enlarge the source image to 4x4 block boundaries, duplicating edge pixels if necessary to avoid introducing extra colors into blocks.
+ slice_image.crop_dup_borders(slice_image.get_block_width(4) * 4, slice_image.get_block_height(4) * 4);
+
+ if (m_params.m_debug_images)
+ {
+ save_png(string_format("basis_debug_source_image_%u_%u.png", source_file_index, slice_index).c_str(), slice_image);
+ }
+
+ enlarge_vector(m_stats, 1);
+ enlarge_vector(m_slice_images, 1);
+ enlarge_vector(m_slice_descs, 1);
+
+ const uint32_t dest_image_index = (uint32_t)m_stats.size() - 1;
+
+ m_stats[dest_image_index].m_filename = source_filename.c_str();
+ m_stats[dest_image_index].m_width = orig_width;
+ m_stats[dest_image_index].m_height = orig_height;
+
+ m_slice_images[dest_image_index] = slice_image;
+
+ debug_printf("****** Slice %u: mip %u, alpha_slice: %u, filename: \"%s\", original: %ux%u actual: %ux%u\n", m_slice_descs.size() - 1, mip_indices[slice_index], is_alpha_slice, source_filename.c_str(), orig_width, orig_height, slice_image.get_width(), slice_image.get_height());
+
+ basisu_backend_slice_desc &slice_desc = m_slice_descs[dest_image_index];
+
+ slice_desc.m_first_block_index = m_total_blocks;
+
+ slice_desc.m_orig_width = orig_width;
+ slice_desc.m_orig_height = orig_height;
+
+ slice_desc.m_width = slice_image.get_width();
+ slice_desc.m_height = slice_image.get_height();
+
+ slice_desc.m_num_blocks_x = slice_image.get_block_width(4);
+ slice_desc.m_num_blocks_y = slice_image.get_block_height(4);
+
+ slice_desc.m_num_macroblocks_x = (slice_desc.m_num_blocks_x + 1) >> 1;
+ slice_desc.m_num_macroblocks_y = (slice_desc.m_num_blocks_y + 1) >> 1;
+
+ slice_desc.m_source_file_index = source_file_index;
+
+ slice_desc.m_mip_index = mip_indices[slice_index];
+
+ slice_desc.m_alpha = is_alpha_slice;
+ slice_desc.m_iframe = false;
+ if (m_params.m_tex_type == basist::cBASISTexTypeVideoFrames)
+ {
+ slice_desc.m_iframe = (source_file_index == 0);
+ }
+
+ m_total_blocks += slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y;
+ total_macroblocks += slice_desc.m_num_macroblocks_x * slice_desc.m_num_macroblocks_y;
+
+ } // slice_index
+
+ } // source_file_index
+
+ debug_printf("Total blocks: %u, Total macroblocks: %u\n", m_total_blocks, total_macroblocks);
+
+ // Make sure we don't have too many slices
+ if (m_slice_descs.size() > BASISU_MAX_SLICES)
+ {
+ error_printf("Too many slices!\n");
+ return false;
+ }
+
+ // Basic sanity check on the slices
+ for (uint32_t i = 1; i < m_slice_descs.size(); i++)
+ {
+ const basisu_backend_slice_desc &prev_slice_desc = m_slice_descs[i - 1];
+ const basisu_backend_slice_desc &slice_desc = m_slice_descs[i];
+
+ // Make sure images are in order
+ int image_delta = (int)slice_desc.m_source_file_index - (int)prev_slice_desc.m_source_file_index;
+ if (image_delta > 1)
+ return false;
+
+ // Make sure mipmap levels are in order
+ if (!image_delta)
+ {
+ int level_delta = (int)slice_desc.m_mip_index - (int)prev_slice_desc.m_mip_index;
+ if (level_delta > 1)
+ return false;
+ }
+ }
+
+ printf("Total basis file slices: %u\n", (uint32_t)m_slice_descs.size());
+
+ for (uint32_t i = 0; i < m_slice_descs.size(); i++)
+ {
+ const basisu_backend_slice_desc &slice_desc = m_slice_descs[i];
+
+ printf("Slice: %u, alpha: %u, orig width/height: %ux%u, width/height: %ux%u, first_block: %u, image_index: %u, mip_level: %u, iframe: %u\n",
+ i, slice_desc.m_alpha, slice_desc.m_orig_width, slice_desc.m_orig_height, slice_desc.m_width, slice_desc.m_height, slice_desc.m_first_block_index, slice_desc.m_source_file_index, slice_desc.m_mip_index, slice_desc.m_iframe);
+
+ if (m_any_source_image_has_alpha)
+ {
+ // Alpha slices must be at odd slice indices
+ if (slice_desc.m_alpha)
+ {
+ if ((i & 1) == 0)
+ return false;
+
+ const basisu_backend_slice_desc &prev_slice_desc = m_slice_descs[i - 1];
+
+ // Make sure previous slice has this image's color data
+ if (prev_slice_desc.m_source_file_index != slice_desc.m_source_file_index)
+ return false;
+ if (prev_slice_desc.m_alpha)
+ return false;
+ if (prev_slice_desc.m_mip_index != slice_desc.m_mip_index)
+ return false;
+ if (prev_slice_desc.m_num_blocks_x != slice_desc.m_num_blocks_x)
+ return false;
+ if (prev_slice_desc.m_num_blocks_y != slice_desc.m_num_blocks_y)
+ return false;
+ }
+ else if (i & 1)
+ return false;
+ }
+ else if (slice_desc.m_alpha)
+ {
+ return false;
+ }
+
+ if ((slice_desc.m_orig_width > slice_desc.m_width) || (slice_desc.m_orig_height > slice_desc.m_height))
+ return false;
+ if ((slice_desc.m_source_file_index == 0) && (m_params.m_tex_type == basist::cBASISTexTypeVideoFrames))
+ {
+ if (!slice_desc.m_iframe)
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // Do some basic validation for 2D arrays, cubemaps, video, and volumes.
+ bool basis_compressor::validate_texture_type_constraints()
+ {
+ debug_printf("basis_compressor::validate_texture_type_constraints\n");
+
+ // In 2D mode anything goes (each image may have a different resolution and # of mipmap levels).
+ if (m_params.m_tex_type == basist::cBASISTexType2D)
+ return true;
+
+ uint32_t total_basis_images = 0;
+
+ for (uint32_t slice_index = 0; slice_index < m_slice_images.size(); slice_index++)
+ {
+ const basisu_backend_slice_desc &slice_desc = m_slice_descs[slice_index];
+
+ total_basis_images = maximum<uint32_t>(total_basis_images, slice_desc.m_source_file_index + 1);
+ }
+
+ if (m_params.m_tex_type == basist::cBASISTexTypeCubemapArray)
+ {
+ // For cubemaps, validate that the total # of Basis images is a multiple of 6.
+ if ((total_basis_images % 6) != 0)
+ {
+ error_printf("basis_compressor::validate_texture_type_constraints: For cubemaps the total number of input images is not a multiple of 6!\n");
+ return false;
+ }
+ }
+
+ // Now validate that all the mip0's have the same dimensions, and that each image has the same # of mipmap levels.
+ uint_vec image_mipmap_levels(total_basis_images);
+
+ int width = -1, height = -1;
+ for (uint32_t slice_index = 0; slice_index < m_slice_images.size(); slice_index++)
+ {
+ const basisu_backend_slice_desc &slice_desc = m_slice_descs[slice_index];
+
+ image_mipmap_levels[slice_desc.m_source_file_index] = maximum(image_mipmap_levels[slice_desc.m_source_file_index], slice_desc.m_mip_index + 1);
+
+ if (slice_desc.m_mip_index != 0)
+ continue;
+
+ if (width < 0)
+ {
+ width = slice_desc.m_orig_width;
+ height = slice_desc.m_orig_height;
+ }
+ else if ((width != (int)slice_desc.m_orig_width) || (height != (int)slice_desc.m_orig_height))
+ {
+ error_printf("basis_compressor::validate_texture_type_constraints: The source image resolutions are not all equal!\n");
+ return false;
+ }
+ }
+
+ for (size_t i = 1; i < image_mipmap_levels.size(); i++)
+ {
+ if (image_mipmap_levels[0] != image_mipmap_levels[i])
+ {
+ error_printf("basis_compressor::validate_texture_type_constraints: Each image must have the same number of mipmap levels!\n");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool basis_compressor::process_frontend()
+ {
+ debug_printf("basis_compressor::process_frontend\n");
+
+ m_source_blocks.resize(m_total_blocks);
+
+ for (uint32_t slice_index = 0; slice_index < m_slice_images.size(); slice_index++)
+ {
+ const basisu_backend_slice_desc &slice_desc = m_slice_descs[slice_index];
+
+ const uint32_t num_blocks_x = slice_desc.m_num_blocks_x;
+ const uint32_t num_blocks_y = slice_desc.m_num_blocks_y;
+
+ const image &source_image = m_slice_images[slice_index];
+
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ source_image.extract_block_clamped(m_source_blocks[slice_desc.m_first_block_index + block_x + block_y * num_blocks_x].get_ptr(), block_x * 4, block_y * 4, 4, 4);
+ }
+
+#if 0
+ // TODO
+ basis_etc1_pack_params pack_params;
+ pack_params.m_quality = cETCQualityMedium;
+ pack_params.m_perceptual = m_params.m_perceptual;
+ pack_params.m_use_color4 = false;
+
+ pack_etc1_block_context pack_context;
+
+ std::unordered_set<uint64_t> endpoint_hash;
+ std::unordered_set<uint32_t> selector_hash;
+
+ for (uint32_t i = 0; i < m_source_blocks.size(); i++)
+ {
+ etc_block blk;
+ pack_etc1_block(blk, m_source_blocks[i].get_ptr(), pack_params, pack_context);
+
+ const color_rgba c0(blk.get_block_color(0, false));
+ endpoint_hash.insert((c0.r | (c0.g << 5) | (c0.b << 10)) | (blk.get_inten_table(0) << 16));
+
+ const color_rgba c1(blk.get_block_color(1, false));
+ endpoint_hash.insert((c1.r | (c1.g << 5) | (c1.b << 10)) | (blk.get_inten_table(1) << 16));
+
+ selector_hash.insert(blk.get_raw_selector_bits());
+ }
+
+ const uint32_t total_unique_endpoints = (uint32_t)endpoint_hash.size();
+ const uint32_t total_unique_selectors = (uint32_t)selector_hash.size();
+
+ if (m_params.m_debug)
+ {
+ debug_printf("Unique endpoints: %u, unique selectors: %u\n", total_unique_endpoints, total_unique_selectors);
+ }
+#endif
+
+ const double total_texels = m_total_blocks * 16.0f;
+
+ int endpoint_clusters = m_params.m_max_endpoint_clusters;
+ int selector_clusters = m_params.m_max_selector_clusters;
+
+ if (endpoint_clusters > basisu_frontend::cMaxEndpointClusters)
+ {
+ error_printf("Too many endpoint clusters! (%u but max is %u)\n", endpoint_clusters, basisu_frontend::cMaxEndpointClusters);
+ return false;
+ }
+ if (selector_clusters > basisu_frontend::cMaxSelectorClusters)
+ {
+ error_printf("Too many selector clusters! (%u but max is %u)\n", selector_clusters, basisu_frontend::cMaxSelectorClusters);
+ return false;
+ }
+
+ if (m_params.m_quality_level != -1)
+ {
+ const float quality = saturate(m_params.m_quality_level / 255.0f);
+
+ const float bits_per_endpoint_cluster = 14.0f;
+ const float max_desired_endpoint_cluster_bits_per_texel = 1.0f; // .15f
+ int max_endpoints = static_cast<int>((max_desired_endpoint_cluster_bits_per_texel * total_texels) / bits_per_endpoint_cluster);
+
+ const float mid = 128.0f / 255.0f;
+
+ float color_endpoint_quality = quality;
+
+ const float endpoint_split_point = 0.5f;
+ if (color_endpoint_quality <= mid)
+ {
+ color_endpoint_quality = lerp(0.0f, endpoint_split_point, powf(color_endpoint_quality / mid, .65f));
+
+ max_endpoints = clamp<int>(max_endpoints, 256, 3072);
+ max_endpoints = minimum<uint32_t>(max_endpoints, m_total_blocks);
+
+ if (max_endpoints < 64)
+ max_endpoints = 64;
+ endpoint_clusters = clamp<uint32_t>((uint32_t)(.5f + lerp<float>(32, static_cast<float>(max_endpoints), color_endpoint_quality)), 32, basisu_frontend::cMaxEndpointClusters);
+ }
+ else
+ {
+ color_endpoint_quality = powf((color_endpoint_quality - mid) / (1.0f - mid), 1.6f);
+
+ max_endpoints = clamp<int>(max_endpoints, 256, 8192);
+ max_endpoints = minimum<uint32_t>(max_endpoints, m_total_blocks);
+
+ if (max_endpoints < 3072)
+ max_endpoints = 3072;
+ endpoint_clusters = clamp<uint32_t>((uint32_t)(.5f + lerp<float>(3072, static_cast<float>(max_endpoints), color_endpoint_quality)), 32, basisu_frontend::cMaxEndpointClusters);
+ }
+
+ float bits_per_selector_cluster = m_params.m_global_sel_pal ? 21.0f : 14.0f;
+
+ const float max_desired_selector_cluster_bits_per_texel = 1.0f; // .15f
+ int max_selectors = static_cast<int>((max_desired_selector_cluster_bits_per_texel * total_texels) / bits_per_selector_cluster);
+ max_selectors = clamp<int>(max_selectors, 256, basisu_frontend::cMaxSelectorClusters);
+ max_selectors = minimum<uint32_t>(max_selectors, m_total_blocks);
+
+ float color_selector_quality = quality;
+ //color_selector_quality = powf(color_selector_quality, 1.65f);
+ color_selector_quality = powf(color_selector_quality, 2.62f);
+
+ if (max_selectors < 96)
+ max_selectors = 96;
+ selector_clusters = clamp<uint32_t>((uint32_t)(.5f + lerp<float>(96, static_cast<float>(max_selectors), color_selector_quality)), 8, basisu_frontend::cMaxSelectorClusters);
+
+ debug_printf("Max endpoints: %u, max selectors: %u\n", endpoint_clusters, selector_clusters);
+
+ if (m_params.m_quality_level >= 223)
+ {
+ if (!m_params.m_selector_rdo_thresh.was_changed())
+ {
+ if (!m_params.m_endpoint_rdo_thresh.was_changed())
+ m_params.m_endpoint_rdo_thresh *= .25f;
+
+ if (!m_params.m_selector_rdo_thresh.was_changed())
+ m_params.m_selector_rdo_thresh *= .25f;
+ }
+ }
+ else if (m_params.m_quality_level >= 192)
+ {
+ if (!m_params.m_endpoint_rdo_thresh.was_changed())
+ m_params.m_endpoint_rdo_thresh *= .5f;
+
+ if (!m_params.m_selector_rdo_thresh.was_changed())
+ m_params.m_selector_rdo_thresh *= .5f;
+ }
+ else if (m_params.m_quality_level >= 160)
+ {
+ if (!m_params.m_endpoint_rdo_thresh.was_changed())
+ m_params.m_endpoint_rdo_thresh *= .75f;
+
+ if (!m_params.m_selector_rdo_thresh.was_changed())
+ m_params.m_selector_rdo_thresh *= .75f;
+ }
+ else if (m_params.m_quality_level >= 129)
+ {
+ float l = (quality - 129 / 255.0f) / ((160 - 129) / 255.0f);
+
+ if (!m_params.m_endpoint_rdo_thresh.was_changed())
+ m_params.m_endpoint_rdo_thresh *= lerp<float>(1.0f, .75f, l);
+
+ if (!m_params.m_selector_rdo_thresh.was_changed())
+ m_params.m_selector_rdo_thresh *= lerp<float>(1.0f, .75f, l);
+ }
+ }
+
+ m_auto_global_sel_pal = false;
+ if (!m_params.m_global_sel_pal && m_params.m_auto_global_sel_pal)
+ {
+ const float bits_per_selector_cluster = 31.0f;
+ double selector_codebook_bpp_est = (bits_per_selector_cluster * selector_clusters) / total_texels;
+ debug_printf("selector_codebook_bpp_est: %f\n", selector_codebook_bpp_est);
+ const float force_global_sel_pal_bpp_threshold = .15f;
+ if ((total_texels <= 128.0f*128.0f) && (selector_codebook_bpp_est > force_global_sel_pal_bpp_threshold))
+ {
+ m_auto_global_sel_pal = true;
+ debug_printf("Auto global selector palette enabled\n");
+ }
+ }
+
+ basisu_frontend::params p;
+ p.m_num_source_blocks = m_total_blocks;
+ p.m_pSource_blocks = &m_source_blocks[0];
+ p.m_max_endpoint_clusters = endpoint_clusters;
+ p.m_max_selector_clusters = selector_clusters;
+ p.m_perceptual = m_params.m_perceptual;
+ p.m_debug_stats = m_params.m_debug;
+ p.m_debug_images = m_params.m_debug_images;
+ p.m_compression_level = m_params.m_compression_level;
+ p.m_tex_type = m_params.m_tex_type;
+ p.m_multithreaded = m_params.m_multithreading;
+ p.m_disable_hierarchical_endpoint_codebooks = m_params.m_disable_hierarchical_endpoint_codebooks;
+ p.m_pJob_pool = m_params.m_pJob_pool;
+
+ if ((m_params.m_global_sel_pal) || (m_auto_global_sel_pal))
+ {
+ p.m_pGlobal_sel_codebook = m_params.m_pSel_codebook;
+ p.m_num_global_sel_codebook_pal_bits = m_params.m_global_pal_bits;
+ p.m_num_global_sel_codebook_mod_bits = m_params.m_global_mod_bits;
+ p.m_use_hybrid_selector_codebooks = !m_params.m_no_hybrid_sel_cb;
+ p.m_hybrid_codebook_quality_thresh = m_params.m_hybrid_sel_cb_quality_thresh;
+ }
+
+ if (!m_frontend.init(p))
+ {
+ error_printf("basisu_frontend::init() failed!\n");
+ return false;
+ }
+
+ m_frontend.compress();
+
+ if (m_params.m_debug_images)
+ {
+ for (uint32_t i = 0; i < m_slice_descs.size(); i++)
+ {
+ char filename[1024];
+#ifdef _WIN32
+ sprintf_s(filename, sizeof(filename), "rdo_frontend_output_output_blocks_%u.png", i);
+#else
+ snprintf(filename, sizeof(filename), "rdo_frontend_output_output_blocks_%u.png", i);
+#endif
+ m_frontend.dump_debug_image(filename, m_slice_descs[i].m_first_block_index, m_slice_descs[i].m_num_blocks_x, m_slice_descs[i].m_num_blocks_y, true);
+
+#ifdef _WIN32
+ sprintf_s(filename, sizeof(filename), "rdo_frontend_output_api_%u.png", i);
+#else
+ snprintf(filename, sizeof(filename), "rdo_frontend_output_api_%u.png", i);
+#endif
+ m_frontend.dump_debug_image(filename, m_slice_descs[i].m_first_block_index, m_slice_descs[i].m_num_blocks_x, m_slice_descs[i].m_num_blocks_y, false);
+ }
+ }
+
+ return true;
+ }
+
+ bool basis_compressor::extract_frontend_texture_data()
+ {
+ debug_printf("basis_compressor::extract_frontend_texture_data\n");
+
+ m_frontend_output_textures.resize(m_slice_descs.size());
+ m_best_etc1s_images.resize(m_slice_descs.size());
+ m_best_etc1s_images_unpacked.resize(m_slice_descs.size());
+
+ for (uint32_t i = 0; i < m_slice_descs.size(); i++)
+ {
+ const basisu_backend_slice_desc &slice_desc = m_slice_descs[i];
+
+ const uint32_t num_blocks_x = slice_desc.m_num_blocks_x;
+ const uint32_t num_blocks_y = slice_desc.m_num_blocks_y;
+
+ const uint32_t width = num_blocks_x * 4;
+ const uint32_t height = num_blocks_y * 4;
+
+ m_frontend_output_textures[i].init(texture_format::cETC1, width, height);
+
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ memcpy(m_frontend_output_textures[i].get_block_ptr(block_x, block_y, 0), &m_frontend.get_output_block(slice_desc.m_first_block_index + block_x + block_y * num_blocks_x), sizeof(etc_block));
+
+#if 0
+ if (m_params.m_debug_images)
+ {
+ char filename[1024];
+ sprintf_s(filename, sizeof(filename), "rdo_etc_frontend_%u_", i);
+ write_etc1_vis_images(m_frontend_output_textures[i], filename);
+ }
+#endif
+
+ m_best_etc1s_images[i].init(texture_format::cETC1, width, height);
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ memcpy(m_best_etc1s_images[i].get_block_ptr(block_x, block_y, 0), &m_frontend.get_etc1s_block(slice_desc.m_first_block_index + block_x + block_y * num_blocks_x), sizeof(etc_block));
+
+ m_best_etc1s_images[i].unpack(m_best_etc1s_images_unpacked[i]);
+ }
+
+ return true;
+ }
+
+ bool basis_compressor::process_backend()
+ {
+ debug_printf("basis_compressor::process_backend\n");
+
+ basisu_backend_params backend_params;
+ backend_params.m_debug = m_params.m_debug;
+ backend_params.m_debug_images = m_params.m_debug_images;
+ backend_params.m_etc1s = true;
+ backend_params.m_compression_level = m_params.m_compression_level;
+
+ if (!m_params.m_no_endpoint_rdo)
+ backend_params.m_endpoint_rdo_quality_thresh = m_params.m_endpoint_rdo_thresh;
+
+ if (!m_params.m_no_selector_rdo)
+ backend_params.m_selector_rdo_quality_thresh = m_params.m_selector_rdo_thresh;
+
+ backend_params.m_use_global_sel_codebook = (m_frontend.get_params().m_pGlobal_sel_codebook != NULL);
+ backend_params.m_global_sel_codebook_pal_bits = m_frontend.get_params().m_num_global_sel_codebook_pal_bits;
+ backend_params.m_global_sel_codebook_mod_bits = m_frontend.get_params().m_num_global_sel_codebook_mod_bits;
+ backend_params.m_use_hybrid_sel_codebooks = m_frontend.get_params().m_use_hybrid_selector_codebooks;
+
+ m_backend.init(&m_frontend, backend_params, m_slice_descs, m_params.m_pSel_codebook);
+ uint32_t total_packed_bytes = m_backend.encode();
+
+ if (!total_packed_bytes)
+ {
+ error_printf("basis_compressor::encode() failed!\n");
+ return false;
+ }
+
+ debug_printf("Total packed bytes (estimated): %u\n", total_packed_bytes);
+
+ return true;
+ }
+
+ bool basis_compressor::create_basis_file_and_transcode()
+ {
+ debug_printf("basis_compressor::create_basis_file_and_transcode\n");
+
+ const basisu_backend_output &encoded_output = m_backend.get_output();
+
+ if (!m_basis_file.init(encoded_output, m_params.m_tex_type, m_params.m_userdata0, m_params.m_userdata1, m_params.m_y_flip, m_params.m_us_per_frame))
+ {
+ error_printf("basis_compressor::write_output_files_and_compute_stats: basisu_backend:init() failed!\n");
+ return false;
+ }
+
+ const uint8_vec &comp_data = m_basis_file.get_compressed_data();
+
+ m_output_basis_file = comp_data;
+
+ // Verify the compressed data by transcoding it to ETC1/BC1 and validating the CRC's.
+ basist::basisu_transcoder decoder(m_params.m_pSel_codebook);
+ if (!decoder.validate_file_checksums(&comp_data[0], (uint32_t)comp_data.size(), true))
+ {
+ error_printf("decoder.validate_file_checksums() failed!\n");
+ return false;
+ }
+
+ m_decoded_output_textures.resize(m_slice_descs.size());
+ m_decoded_output_textures_unpacked.resize(m_slice_descs.size());
+
+ m_decoded_output_textures_bc1.resize(m_slice_descs.size());
+ m_decoded_output_textures_unpacked_bc1.resize(m_slice_descs.size());
+
+ interval_timer tm;
+ tm.start();
+
+ if (!decoder.start_transcoding(&comp_data[0], (uint32_t)comp_data.size()))
+ {
+ error_printf("decoder.start_transcoding() failed!\n");
+ return false;
+ }
+
+ debug_printf("basisu_comppressor::start_transcoding() took %3.3fms\n", tm.get_elapsed_ms());
+
+ uint32_t total_orig_pixels = 0;
+ uint32_t total_texels = 0;
+
+ double total_time_etc1 = 0;
+
+ for (uint32_t i = 0; i < m_slice_descs.size(); i++)
+ {
+ gpu_image decoded_texture;
+ decoded_texture.init(texture_format::cETC1, m_slice_descs[i].m_width, m_slice_descs[i].m_height);
+
+ tm.start();
+
+ if (!decoder.transcode_slice(&comp_data[0], (uint32_t)comp_data.size(), i,
+ reinterpret_cast<etc_block *>(decoded_texture.get_ptr()), m_slice_descs[i].m_num_blocks_x * m_slice_descs[i].m_num_blocks_y, basist::block_format::cETC1, 8))
+ {
+ error_printf("Transcoding failed to ETC1 on slice %u!\n", i);
+ return false;
+ }
+
+ total_time_etc1 += tm.get_elapsed_secs();
+
+ uint32_t image_crc16 = basist::crc16(decoded_texture.get_ptr(), decoded_texture.get_size_in_bytes(), 0);
+ if (image_crc16 != m_backend.get_output().m_slice_image_crcs[i])
+ {
+ error_printf("Decoded image data CRC check failed on slice %u!\n", i);
+ return false;
+ }
+ debug_printf("Decoded image data CRC check succeeded on slice %i\n", i);
+
+ m_decoded_output_textures[i] = decoded_texture;
+
+ total_orig_pixels += m_slice_descs[i].m_orig_width * m_slice_descs[i].m_orig_height;
+ total_texels += m_slice_descs[i].m_width * m_slice_descs[i].m_height;
+ }
+
+ tm.start();
+
+ basist::basisu_transcoder_init();
+
+ debug_printf("basist::basisu_transcoder_init: Took %f ms\n", tm.get_elapsed_ms());
+
+ double total_time_bc1 = 0;
+
+ for (uint32_t i = 0; i < m_slice_descs.size(); i++)
+ {
+ gpu_image decoded_texture;
+ decoded_texture.init(texture_format::cBC1, m_slice_descs[i].m_width, m_slice_descs[i].m_height);
+
+ tm.start();
+
+ if (!decoder.transcode_slice(&comp_data[0], (uint32_t)comp_data.size(), i,
+ reinterpret_cast<etc_block *>(decoded_texture.get_ptr()), m_slice_descs[i].m_num_blocks_x * m_slice_descs[i].m_num_blocks_y, basist::block_format::cBC1, 8))
+ {
+ error_printf("Transcoding failed to BC1 on slice %u!\n", i);
+ return false;
+ }
+
+ total_time_bc1 += tm.get_elapsed_secs();
+
+ m_decoded_output_textures_bc1[i] = decoded_texture;
+ }
+
+ for (uint32_t i = 0; i < m_slice_descs.size(); i++)
+ {
+ m_decoded_output_textures[i].unpack(m_decoded_output_textures_unpacked[i]);
+ m_decoded_output_textures_bc1[i].unpack(m_decoded_output_textures_unpacked_bc1[i]);
+ }
+
+ debug_printf("Transcoded to ETC1 in %3.3fms, %f texels/sec\n", total_time_etc1 * 1000.0f, total_orig_pixels / total_time_etc1);
+
+ debug_printf("Transcoded to BC1 in %3.3fms, %f texels/sec\n", total_time_bc1 * 1000.0f, total_orig_pixels / total_time_bc1);
+
+ debug_printf("Total .basis output file size: %u, %3.3f bits/texel\n", comp_data.size(), comp_data.size() * 8.0f / total_orig_pixels);
+
+ m_output_blocks.resize(0);
+
+ uint32_t total_orig_texels = 0;
+ for (uint32_t slice_index = 0; slice_index < m_slice_descs.size(); slice_index++)
+ {
+ const basisu_backend_slice_desc &slice_desc = m_slice_descs[slice_index];
+
+ total_orig_texels += slice_desc.m_orig_width * slice_desc.m_orig_height;
+
+ const uint32_t total_blocks = slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y;
+
+ assert(m_decoded_output_textures[slice_index].get_total_blocks() == total_blocks);
+
+ memcpy(enlarge_vector(m_output_blocks, total_blocks), m_decoded_output_textures[slice_index].get_ptr(), sizeof(etc_block) * total_blocks);
+ }
+
+ m_basis_file_size = (uint32_t)comp_data.size();
+ m_basis_bits_per_texel = (comp_data.size() * 8.0f) / total_orig_texels;
+
+ return true;
+ }
+
+ bool basis_compressor::write_output_files_and_compute_stats()
+ {
+ debug_printf("basis_compressor::write_output_files_and_compute_stats\n");
+
+ if (m_params.m_write_output_basis_files)
+ {
+ const uint8_vec &comp_data = m_basis_file.get_compressed_data();
+
+ const std::string& basis_filename = m_params.m_out_filename;
+
+ if (!write_vec_to_file(basis_filename.c_str(), comp_data))
+ {
+ error_printf("Failed writing output data to file \"%s\"\n", basis_filename.c_str());
+ return false;
+ }
+
+ printf("Wrote output .basis file \"%s\"\n", basis_filename.c_str());
+ }
+
+ m_stats.resize(m_slice_descs.size());
+
+ uint32_t total_orig_texels = 0;
+
+ for (uint32_t slice_index = 0; slice_index < m_slice_descs.size(); slice_index++)
+ {
+ const basisu_backend_slice_desc &slice_desc = m_slice_descs[slice_index];
+
+ total_orig_texels += slice_desc.m_orig_width * slice_desc.m_orig_height;
+
+ if (m_params.m_compute_stats)
+ {
+ printf("Slice: %u\n", slice_index);
+
+ image_stats &s = m_stats[slice_index];
+
+ // TODO: We used to output SSIM (during heavy encoder development), but this slowed down compression too much. We'll be adding it back.
+
+ image_metrics em;
+
+ // ---- .basis ETC1S stats
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 0);
+ em.print(".basis ETC1S 709 Luma: ");
+
+ s.m_basis_etc1s_luma_709_psnr = static_cast<float>(em.m_psnr);
+ s.m_basis_etc1s_luma_709_ssim = static_cast<float>(em.m_ssim);
+
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 0, true, true);
+ em.print(".basis ETC1S 601 Luma: ");
+
+ s.m_basis_etc1s_luma_601_psnr = static_cast<float>(em.m_psnr);
+
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 3);
+ em.print(".basis ETC1S RGB Avg: ");
+
+ s.m_basis_etc1s_rgb_avg_psnr = em.m_psnr;
+
+ if (m_slice_descs.size() == 1)
+ {
+ debug_printf(".basis Luma 709 PSNR per bit/texel*10000: %3.3f\n", 10000.0f * s.m_basis_etc1s_luma_709_psnr / ((m_backend.get_output().get_output_size_estimate() * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
+ }
+
+ // ---- .basis BC1 stats
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc1[slice_index], 0, 0);
+ em.print(".basis BC1 709 Luma: ");
+
+ s.m_basis_bc1_luma_709_psnr = static_cast<float>(em.m_psnr);
+ s.m_basis_bc1_luma_709_ssim = static_cast<float>(em.m_ssim);
+
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc1[slice_index], 0, 0, true, true);
+ em.print(".basis BC1 601 Luma: ");
+
+ s.m_basis_bc1_luma_601_psnr = static_cast<float>(em.m_psnr);
+
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc1[slice_index], 0, 3);
+ em.print(".basis BC1 RGB Avg: ");
+
+ s.m_basis_bc1_rgb_avg_psnr = static_cast<float>(em.m_psnr);
+
+ // ---- Nearly best possible ETC1S stats
+ em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 0);
+ em.print("Unquantized ETC1S 709 Luma: ");
+
+ s.m_best_luma_709_psnr = static_cast<float>(em.m_psnr);
+ s.m_best_luma_709_ssim = static_cast<float>(em.m_ssim);
+
+ em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 0, true, true);
+ em.print("Unquantized ETC1S 601 Luma: ");
+
+ s.m_best_luma_601_psnr = static_cast<float>(em.m_psnr);
+
+ em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 3);
+ em.print("Unquantized ETC1S RGB Avg: ");
+
+ s.m_best_rgb_avg_psnr = static_cast<float>(em.m_psnr);
+ }
+
+ if (m_frontend.get_params().m_debug_images)
+ {
+ std::string out_basename;
+ if (m_params.m_out_filename.size())
+ string_get_filename(m_params.m_out_filename.c_str(), out_basename);
+ else if (m_params.m_source_filenames.size())
+ string_get_filename(m_params.m_source_filenames[slice_desc.m_source_file_index].c_str(), out_basename);
+
+ string_remove_extension(out_basename);
+ out_basename = "basis_debug_" + out_basename + string_format("_slice_%u", slice_index);
+
+ // Write "best" ETC1S debug images
+ {
+ gpu_image best_etc1s_gpu_image(m_best_etc1s_images[slice_index]);
+ best_etc1s_gpu_image.override_dimensions(slice_desc.m_orig_width, slice_desc.m_orig_height);
+ write_compressed_texture_file((out_basename + "_best_etc1s.ktx").c_str(), best_etc1s_gpu_image);
+
+ image best_etc1s_unpacked;
+ best_etc1s_gpu_image.unpack(best_etc1s_unpacked);
+ save_png(out_basename + "_best_etc1s.png", best_etc1s_unpacked);
+ }
+
+ // Write decoded ETC1S debug images
+ {
+ gpu_image decoded_etc1s(m_decoded_output_textures[slice_index]);
+ decoded_etc1s.override_dimensions(slice_desc.m_orig_width, slice_desc.m_orig_height);
+ write_compressed_texture_file((out_basename + "_decoded_etc1s.ktx").c_str(), decoded_etc1s);
+
+ image temp(m_decoded_output_textures_unpacked[slice_index]);
+ temp.crop(slice_desc.m_orig_width, slice_desc.m_orig_height);
+ save_png(out_basename + "_decoded_etc1s.png", temp);
+ }
+
+ // Write decoded BC1 debug images
+ {
+ gpu_image decoded_bc1(m_decoded_output_textures_bc1[slice_index]);
+ decoded_bc1.override_dimensions(slice_desc.m_orig_width, slice_desc.m_orig_height);
+ write_compressed_texture_file((out_basename + "_decoded_bc1.ktx").c_str(), decoded_bc1);
+
+ image temp(m_decoded_output_textures_unpacked_bc1[slice_index]);
+ temp.crop(slice_desc.m_orig_width, slice_desc.m_orig_height);
+ save_png(out_basename + "_decoded_bc1.png", temp);
+ }
+ }
+ }
+
+ return true;
+ }
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_comp.h b/thirdparty/basis_universal/basisu_comp.h
new file mode 100644
index 0000000000..1c201ddbed
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_comp.h
@@ -0,0 +1,430 @@
+// basisu_comp.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "basisu_frontend.h"
+#include "basisu_backend.h"
+#include "basisu_basis_file.h"
+#include "transcoder/basisu_global_selector_palette.h"
+#include "transcoder/basisu_transcoder.h"
+
+namespace basisu
+{
+ const uint32_t BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION = 16384;
+
+ // Allow block's color distance to increase by 1.5 while searching for an alternative nearby endpoint.
+ const float BASISU_DEFAULT_ENDPOINT_RDO_THRESH = 1.5f;
+
+ // Allow block's color distance to increase by 1.25 while searching the selector history buffer for a close enough match.
+ const float BASISU_DEFAULT_SELECTOR_RDO_THRESH = 1.25f;
+
+ const int BASISU_DEFAULT_QUALITY = 128;
+ const float BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH = 2.0f;
+
+ const uint32_t BASISU_MAX_IMAGE_DIMENSION = 16384;
+ const uint32_t BASISU_QUALITY_MIN = 1;
+ const uint32_t BASISU_QUALITY_MAX = 255;
+ const uint32_t BASISU_MAX_ENDPOINT_CLUSTERS = basisu_frontend::cMaxEndpointClusters;
+ const uint32_t BASISU_MAX_SELECTOR_CLUSTERS = basisu_frontend::cMaxSelectorClusters;
+
+ const uint32_t BASISU_MAX_SLICES = 0xFFFFFF;
+
+ struct image_stats
+ {
+ image_stats()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ m_filename.clear();
+ m_width = 0;
+ m_height = 0;
+
+ m_basis_etc1s_rgb_avg_psnr = 0.0f;
+ m_basis_etc1s_luma_709_psnr = 0.0f;
+ m_basis_etc1s_luma_601_psnr = 0.0f;
+ m_basis_etc1s_luma_709_ssim = 0.0f;
+
+ m_basis_bc1_rgb_avg_psnr = 0.0f;
+ m_basis_bc1_luma_709_psnr = 0.0f;
+ m_basis_bc1_luma_601_psnr = 0.0f;
+ m_basis_bc1_luma_709_ssim = 0.0f;
+
+ m_best_rgb_avg_psnr = 0.0f;
+ m_best_luma_709_psnr = 0.0f;
+ m_best_luma_601_psnr = 0.0f;
+ m_best_luma_709_ssim = 0.0f;
+ }
+
+ std::string m_filename;
+ uint32_t m_width;
+ uint32_t m_height;
+
+ // .basis compressed
+ float m_basis_etc1s_rgb_avg_psnr;
+ float m_basis_etc1s_luma_709_psnr;
+ float m_basis_etc1s_luma_601_psnr;
+ float m_basis_etc1s_luma_709_ssim;
+
+ float m_basis_bc1_rgb_avg_psnr;
+ float m_basis_bc1_luma_709_psnr;
+ float m_basis_bc1_luma_601_psnr;
+ float m_basis_bc1_luma_709_ssim;
+
+ // Normal (highest quality) compressed ETC1S
+ float m_best_rgb_avg_psnr;
+ float m_best_luma_709_psnr;
+ float m_best_luma_601_psnr;
+ float m_best_luma_709_ssim;
+ };
+
+ template<bool def>
+ struct bool_param
+ {
+ bool_param() :
+ m_value(def),
+ m_changed(false)
+ {
+ }
+
+ void clear()
+ {
+ m_value = def;
+ m_changed = false;
+ }
+
+ operator bool() const
+ {
+ return m_value;
+ }
+
+ bool operator= (bool v)
+ {
+ m_value = v;
+ m_changed = true;
+ return m_value;
+ }
+
+ bool was_changed() const { return m_changed; }
+ void set_changed(bool flag) { m_changed = flag; }
+
+ bool m_value;
+ bool m_changed;
+ };
+
+ template<typename T>
+ struct param
+ {
+ param(T def, T min_v, T max_v) :
+ m_value(def),
+ m_def(def),
+ m_min(min_v),
+ m_max(max_v),
+ m_changed(false)
+ {
+ }
+
+ void clear()
+ {
+ m_value = m_def;
+ m_changed = false;
+ }
+
+ operator T() const
+ {
+ return m_value;
+ }
+
+ T operator= (T v)
+ {
+ m_value = clamp<T>(v, m_min, m_max);
+ m_changed = true;
+ return m_value;
+ }
+
+ T operator *= (T v)
+ {
+ m_value *= v;
+ m_changed = true;
+ return m_value;
+ }
+
+ bool was_changed() const { return m_changed; }
+ void set_changed(bool flag) { m_changed = flag; }
+
+ T m_value;
+ T m_def;
+ T m_min;
+ T m_max;
+ bool m_changed;
+ };
+
+ struct basis_compressor_params
+ {
+ basis_compressor_params() :
+ m_hybrid_sel_cb_quality_thresh(BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH, 0.0f, 1e+10f),
+ m_global_pal_bits(8, 0, ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_PAL_BITS),
+ m_global_mod_bits(8, 0, basist::etc1_global_palette_entry_modifier::cTotalBits),
+ m_endpoint_rdo_thresh(BASISU_DEFAULT_ENDPOINT_RDO_THRESH, 0.0f, 1e+10f),
+ m_selector_rdo_thresh(BASISU_DEFAULT_SELECTOR_RDO_THRESH, 0.0f, 1e+10f),
+ m_pSel_codebook(NULL),
+ m_max_endpoint_clusters(512),
+ m_max_selector_clusters(512),
+ m_quality_level(-1),
+ m_mip_scale(1.0f, .000125f, 4.0f),
+ m_mip_smallest_dimension(1, 1, 16384),
+ m_compression_level((int)BASISU_DEFAULT_COMPRESSION_LEVEL, 0, (int)BASISU_MAX_COMPRESSION_LEVEL),
+ m_pJob_pool(nullptr)
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ m_pSel_codebook = NULL;
+
+ m_source_filenames.clear();
+ m_source_alpha_filenames.clear();
+
+ m_source_images.clear();
+
+ m_out_filename.clear();
+
+ m_y_flip.clear();
+ m_debug.clear();
+ m_debug_images.clear();
+ m_global_sel_pal.clear();
+ m_auto_global_sel_pal.clear();
+ m_no_hybrid_sel_cb.clear();
+ m_perceptual.clear();
+ m_no_selector_rdo.clear();
+ m_selector_rdo_thresh.clear();
+ m_read_source_images.clear();
+ m_write_output_basis_files.clear();
+ m_compression_level.clear();
+ m_compute_stats.clear();
+ m_check_for_alpha.clear();
+ m_force_alpha.clear();
+ m_multithreading.clear();
+ m_seperate_rg_to_color_alpha.clear();
+ m_hybrid_sel_cb_quality_thresh.clear();
+ m_global_pal_bits.clear();
+ m_global_mod_bits.clear();
+ m_disable_hierarchical_endpoint_codebooks.clear();
+
+ m_no_endpoint_rdo.clear();
+ m_endpoint_rdo_thresh.clear();
+
+ m_mip_gen.clear();
+ m_mip_scale.clear();
+ m_mip_filter = "kaiser";
+ m_mip_scale = 1.0f;
+ m_mip_srgb.clear();
+ m_mip_premultiplied.clear();
+ m_mip_renormalize.clear();
+ m_mip_wrapping.clear();
+ m_mip_smallest_dimension.clear();
+
+ m_max_endpoint_clusters = 0;
+ m_max_selector_clusters = 0;
+ m_quality_level = -1;
+
+ m_tex_type = basist::cBASISTexType2D;
+ m_userdata0 = 0;
+ m_userdata1 = 0;
+ m_us_per_frame = 0;
+
+ m_pJob_pool = nullptr;
+ }
+
+ // Pointer to the global selector codebook, or nullptr to not use a global selector codebook
+ const basist::etc1_global_selector_codebook *m_pSel_codebook;
+
+ // If m_read_source_images is true, m_source_filenames (and optionally m_source_alpha_filenames) contains the filenames of PNG images to read.
+ // Otherwise, the compressor processes the images in m_source_images.
+ std::vector<std::string> m_source_filenames;
+ std::vector<std::string> m_source_alpha_filenames;
+
+ std::vector<image> m_source_images;
+ // TODO: Allow caller to supply their own mipmaps
+
+ // Filename of the output basis file
+ std::string m_out_filename;
+
+ // The params are done this way so we can detect when the user has explictly changed them.
+
+ // Flip images across Y axis
+ bool_param<false> m_y_flip;
+
+ // Output debug information during compression
+ bool_param<false> m_debug;
+
+ // m_debug_images is pretty slow
+ bool_param<false> m_debug_images;
+
+ // Compression level, from 0 to BASISU_MAX_COMPRESSION_LEVEL (higher is slower)
+ param<int> m_compression_level;
+
+ bool_param<false> m_global_sel_pal;
+ bool_param<false> m_auto_global_sel_pal;
+
+ // Frontend/backend codec parameters
+ bool_param<false> m_no_hybrid_sel_cb;
+
+ // Use perceptual sRGB colorspace metrics (for normal maps, etc.)
+ bool_param<true> m_perceptual;
+
+ // Disable selector RDO, for faster compression but larger files
+ bool_param<false> m_no_selector_rdo;
+ param<float> m_selector_rdo_thresh;
+
+ bool_param<false> m_no_endpoint_rdo;
+ param<float> m_endpoint_rdo_thresh;
+
+ // Read source images from m_source_filenames/m_source_alpha_filenames
+ bool_param<false> m_read_source_images;
+
+ // Write the output basis file to disk using m_out_filename
+ bool_param<false> m_write_output_basis_files;
+
+ // Compute and display image metrics
+ bool_param<false> m_compute_stats;
+
+ // Check to see if any input image has an alpha channel, if so then the output basis file will have alpha channels
+ bool_param<true> m_check_for_alpha;
+
+ // Always put alpha slices in the output basis file, even when the input doesn't have alpha
+ bool_param<false> m_force_alpha;
+ bool_param<true> m_multithreading;
+
+ // Split the R channel to RGB and the G channel to alpha, then write a basis file with alpha channels
+ bool_param<false> m_seperate_rg_to_color_alpha;
+
+ bool_param<false> m_disable_hierarchical_endpoint_codebooks;
+
+ // Global/hybrid selector codebook parameters
+ param<float> m_hybrid_sel_cb_quality_thresh;
+ param<int> m_global_pal_bits;
+ param<int> m_global_mod_bits;
+
+ // mipmap generation parameters
+ bool_param<false> m_mip_gen;
+ param<float> m_mip_scale;
+ std::string m_mip_filter;
+ bool_param<false> m_mip_srgb;
+ bool_param<true> m_mip_premultiplied; // not currently supported
+ bool_param<false> m_mip_renormalize;
+ bool_param<true> m_mip_wrapping;
+ param<int> m_mip_smallest_dimension;
+
+ // Codebook size (quality) control.
+ // If m_quality_level != -1, it controls the quality level. It ranges from [0,255].
+ // Otherwise m_max_endpoint_clusters/m_max_selector_clusters controls the codebook sizes directly.
+ uint32_t m_max_endpoint_clusters;
+ uint32_t m_max_selector_clusters;
+ int m_quality_level;
+
+ // m_tex_type, m_userdata0, m_userdata1, m_framerate - These fields go directly into the Basis file header.
+ basist::basis_texture_type m_tex_type;
+ uint32_t m_userdata0;
+ uint32_t m_userdata1;
+ uint32_t m_us_per_frame;
+
+ job_pool *m_pJob_pool;
+ };
+
+ class basis_compressor
+ {
+ BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(basis_compressor);
+
+ public:
+ basis_compressor();
+
+ bool init(const basis_compressor_params &params);
+
+ enum error_code
+ {
+ cECSuccess = 0,
+ cECFailedReadingSourceImages,
+ cECFailedValidating,
+ cECFailedFrontEnd,
+ cECFailedFontendExtract,
+ cECFailedBackend,
+ cECFailedCreateBasisFile,
+ cECFailedWritingOutput
+ };
+
+ error_code process();
+
+ const uint8_vec &get_output_basis_file() const { return m_output_basis_file; }
+ const etc_block_vec &get_output_blocks() const { return m_output_blocks; }
+
+ const std::vector<image_stats> &get_stats() const { return m_stats; }
+
+ uint32_t get_basis_file_size() const { return m_basis_file_size; }
+ double get_basis_bits_per_texel() const { return m_basis_bits_per_texel; }
+
+ bool get_any_source_image_has_alpha() const { return m_any_source_image_has_alpha; }
+
+ private:
+ basis_compressor_params m_params;
+
+ std::vector<image> m_slice_images;
+
+ std::vector<image_stats> m_stats;
+
+ uint32_t m_basis_file_size;
+ double m_basis_bits_per_texel;
+
+ basisu_backend_slice_desc_vec m_slice_descs;
+
+ uint32_t m_total_blocks;
+ bool m_auto_global_sel_pal;
+
+ basisu_frontend m_frontend;
+ pixel_block_vec m_source_blocks;
+
+ std::vector<gpu_image> m_frontend_output_textures;
+
+ std::vector<gpu_image> m_best_etc1s_images;
+ std::vector<image> m_best_etc1s_images_unpacked;
+
+ basisu_backend m_backend;
+
+ basisu_file m_basis_file;
+
+ std::vector<gpu_image> m_decoded_output_textures;
+ std::vector<image> m_decoded_output_textures_unpacked;
+ std::vector<gpu_image> m_decoded_output_textures_bc1;
+ std::vector<image> m_decoded_output_textures_unpacked_bc1;
+
+ uint8_vec m_output_basis_file;
+ etc_block_vec m_output_blocks;
+
+ bool m_any_source_image_has_alpha;
+
+ bool read_source_images();
+ bool process_frontend();
+ bool extract_frontend_texture_data();
+ bool process_backend();
+ bool create_basis_file_and_transcode();
+ bool write_output_files_and_compute_stats();
+ bool generate_mipmaps(const image &img, std::vector<image> &mips, bool has_alpha);
+ bool validate_texture_type_constraints();
+ };
+
+} // namespace basisu
+
diff --git a/thirdparty/basis_universal/basisu_enc.cpp b/thirdparty/basis_universal/basisu_enc.cpp
new file mode 100644
index 0000000000..7057c65cf8
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_enc.cpp
@@ -0,0 +1,1376 @@
+// basisu_enc.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_enc.h"
+#include "lodepng.h"
+#include "basisu_resampler.h"
+#include "basisu_resampler_filters.h"
+#include "basisu_etc.h"
+#include "transcoder/basisu_transcoder.h"
+
+#if defined(_WIN32)
+// For QueryPerformanceCounter/QueryPerformanceFrequency
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+namespace basisu
+{
+ uint64_t interval_timer::g_init_ticks, interval_timer::g_freq;
+ double interval_timer::g_timer_freq;
+
+ uint8_t g_hamming_dist[256] =
+ {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+ };
+
+ // Encoder library initialization (just call once at startup)
+ void basisu_encoder_init()
+ {
+ basist::basisu_transcoder_init();
+ }
+
+ void error_printf(const char *pFmt, ...)
+ {
+ char buf[2048];
+
+ va_list args;
+ va_start(args, pFmt);
+#ifdef _WIN32
+ vsprintf_s(buf, sizeof(buf), pFmt, args);
+#else
+ vsnprintf(buf, sizeof(buf), pFmt, args);
+#endif
+ va_end(args);
+
+ fprintf(stderr, "ERROR: %s", buf);
+ }
+
+#if defined(_WIN32)
+ inline void query_counter(timer_ticks* pTicks)
+ {
+ QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(pTicks));
+ }
+ inline void query_counter_frequency(timer_ticks* pTicks)
+ {
+ QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(pTicks));
+ }
+#elif defined(__APPLE__)
+#include <sys/time.h>
+ inline void query_counter(timer_ticks* pTicks)
+ {
+ struct timeval cur_time;
+ gettimeofday(&cur_time, NULL);
+ *pTicks = static_cast<unsigned long long>(cur_time.tv_sec) * 1000000ULL + static_cast<unsigned long long>(cur_time.tv_usec);
+ }
+ inline void query_counter_frequency(timer_ticks* pTicks)
+ {
+ *pTicks = 1000000;
+ }
+#elif defined(__GNUC__)
+#include <sys/timex.h>
+ inline void query_counter(timer_ticks* pTicks)
+ {
+ struct timeval cur_time;
+ gettimeofday(&cur_time, NULL);
+ *pTicks = static_cast<unsigned long long>(cur_time.tv_sec) * 1000000ULL + static_cast<unsigned long long>(cur_time.tv_usec);
+ }
+ inline void query_counter_frequency(timer_ticks* pTicks)
+ {
+ *pTicks = 1000000;
+ }
+#else
+#error TODO
+#endif
+
+ interval_timer::interval_timer() : m_start_time(0), m_stop_time(0), m_started(false), m_stopped(false)
+ {
+ if (!g_timer_freq)
+ init();
+ }
+
+ void interval_timer::start()
+ {
+ query_counter(&m_start_time);
+ m_started = true;
+ m_stopped = false;
+ }
+
+ void interval_timer::stop()
+ {
+ assert(m_started);
+ query_counter(&m_stop_time);
+ m_stopped = true;
+ }
+
+ double interval_timer::get_elapsed_secs() const
+ {
+ assert(m_started);
+ if (!m_started)
+ return 0;
+
+ timer_ticks stop_time = m_stop_time;
+ if (!m_stopped)
+ query_counter(&stop_time);
+
+ timer_ticks delta = stop_time - m_start_time;
+ return delta * g_timer_freq;
+ }
+
+ void interval_timer::init()
+ {
+ if (!g_timer_freq)
+ {
+ query_counter_frequency(&g_freq);
+ g_timer_freq = 1.0f / g_freq;
+ query_counter(&g_init_ticks);
+ }
+ }
+
+ timer_ticks interval_timer::get_ticks()
+ {
+ if (!g_timer_freq)
+ init();
+ timer_ticks ticks;
+ query_counter(&ticks);
+ return ticks - g_init_ticks;
+ }
+
+ double interval_timer::ticks_to_secs(timer_ticks ticks)
+ {
+ if (!g_timer_freq)
+ init();
+ return ticks * g_timer_freq;
+ }
+
+ bool load_png(const char* pFilename, image& img)
+ {
+ std::vector<uint8_t> buffer;
+ unsigned err = lodepng::load_file(buffer, std::string(pFilename));
+ if (err)
+ return false;
+
+ unsigned w = 0, h = 0;
+
+ if (sizeof(void *) == sizeof(uint32_t))
+ {
+ // Inspect the image first on 32-bit builds, to see if the image would require too much memory.
+ lodepng::State state;
+ err = lodepng_inspect(&w, &h, &state, &buffer[0], buffer.size());
+ if ((err != 0) || (!w) || (!h))
+ return false;
+
+ const uint32_t exepected_alloc_size = w * h * sizeof(uint32_t);
+
+ // If the file is too large on 32-bit builds then just bail now, to prevent causing a memory exception.
+ const uint32_t MAX_ALLOC_SIZE = 250000000;
+ if (exepected_alloc_size >= MAX_ALLOC_SIZE)
+ {
+ error_printf("Image \"%s\" is too large (%ux%u) to process in a 32-bit build!\n", pFilename, w, h);
+ return false;
+ }
+
+ w = h = 0;
+ }
+
+ std::vector<uint8_t> out;
+ err = lodepng::decode(out, w, h, &buffer[0], buffer.size());
+ if ((err != 0) || (!w) || (!h))
+ return false;
+
+ if (out.size() != (w * h * 4))
+ return false;
+
+ img.resize(w, h);
+
+ memcpy(img.get_ptr(), &out[0], out.size());
+
+ return true;
+ }
+
+ bool save_png(const char* pFilename, const image & img, uint32_t image_save_flags, uint32_t grayscale_comp)
+ {
+ if (!img.get_total_pixels())
+ return false;
+
+ std::vector<uint8_t> out;
+ unsigned err = 0;
+
+ if (image_save_flags & cImageSaveGrayscale)
+ {
+ uint8_vec g_pixels(img.get_width() * img.get_height());
+ uint8_t *pDst = &g_pixels[0];
+
+ for (uint32_t y = 0; y < img.get_height(); y++)
+ for (uint32_t x = 0; x < img.get_width(); x++)
+ *pDst++ = img(x, y)[grayscale_comp];
+
+ err = lodepng::encode(out, (const uint8_t*)& g_pixels[0], img.get_width(), img.get_height(), LCT_GREY, 8);
+ }
+ else
+ {
+ bool has_alpha = img.has_alpha();
+ if ((!has_alpha) || ((image_save_flags & cImageSaveIgnoreAlpha) != 0))
+ {
+ uint8_vec rgb_pixels(img.get_width() * 3 * img.get_height());
+ uint8_t *pDst = &rgb_pixels[0];
+
+ for (uint32_t y = 0; y < img.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < img.get_width(); x++)
+ {
+ const color_rgba& c = img(x, y);
+ pDst[0] = c.r;
+ pDst[1] = c.g;
+ pDst[2] = c.b;
+ pDst += 3;
+ }
+ }
+
+ err = lodepng::encode(out, (const uint8_t*)& rgb_pixels[0], img.get_width(), img.get_height(), LCT_RGB, 8);
+ }
+ else
+ {
+ err = lodepng::encode(out, (const uint8_t*)img.get_ptr(), img.get_width(), img.get_height(), LCT_RGBA, 8);
+ }
+ }
+
+ err = lodepng::save_file(out, std::string(pFilename));
+ if (err)
+ return false;
+
+ return true;
+ }
+
+ bool read_file_to_vec(const char* pFilename, uint8_vec& data)
+ {
+ FILE* pFile = nullptr;
+#ifdef _WIN32
+ fopen_s(&pFile, pFilename, "rb");
+#else
+ pFile = fopen(pFilename, "rb");
+#endif
+ if (!pFile)
+ return false;
+
+ fseek(pFile, 0, SEEK_END);
+#ifdef _WIN32
+ int64_t filesize = _ftelli64(pFile);
+#else
+ int64_t filesize = ftello(pFile);
+#endif
+ if (filesize < 0)
+ {
+ fclose(pFile);
+ return false;
+ }
+ fseek(pFile, 0, SEEK_SET);
+
+ if (sizeof(size_t) == sizeof(uint32_t))
+ {
+ if (filesize > 0x70000000)
+ {
+ // File might be too big to load safely in one alloc
+ fclose(pFile);
+ return false;
+ }
+ }
+
+ data.resize((size_t)filesize);
+
+ if (filesize)
+ {
+ if (fread(&data[0], 1, (size_t)filesize, pFile) != (size_t)filesize)
+ {
+ fclose(pFile);
+ return false;
+ }
+ }
+
+ fclose(pFile);
+ return true;
+ }
+
+ bool write_data_to_file(const char* pFilename, const void* pData, size_t len)
+ {
+ FILE* pFile = nullptr;
+#ifdef _WIN32
+ fopen_s(&pFile, pFilename, "wb");
+#else
+ pFile = fopen(pFilename, "wb");
+#endif
+ if (!pFile)
+ return false;
+
+ if (len)
+ {
+ if (fwrite(pData, 1, len, pFile) != len)
+ {
+ fclose(pFile);
+ return false;
+ }
+ }
+
+ return fclose(pFile) != EOF;
+ }
+
+ float linear_to_srgb(float l)
+ {
+ assert(l >= 0.0f && l <= 1.0f);
+ if (l < .0031308f)
+ return saturate(l * 12.92f);
+ else
+ return saturate(1.055f * powf(l, 1.0f/2.4f) - .055f);
+ }
+
+ float srgb_to_linear(float s)
+ {
+ assert(s >= 0.0f && s <= 1.0f);
+ if (s < .04045f)
+ return saturate(s * (1.0f/12.92f));
+ else
+ return saturate(powf((s + .055f) * (1.0f/1.055f), 2.4f));
+ }
+
+ bool image_resample(const image &src, image &dst, bool srgb,
+ const char *pFilter, float filter_scale,
+ bool wrapping,
+ uint32_t first_comp, uint32_t num_comps)
+ {
+ assert((first_comp + num_comps) <= 4);
+
+ const int cMaxComps = 4;
+
+ const uint32_t src_w = src.get_width(), src_h = src.get_height();
+ const uint32_t dst_w = dst.get_width(), dst_h = dst.get_height();
+
+ if (maximum(src_w, src_h) > BASISU_RESAMPLER_MAX_DIMENSION)
+ {
+ printf("Image is too large!\n");
+ return false;
+ }
+
+ if (!src_w || !src_h || !dst_w || !dst_h)
+ return false;
+
+ if ((num_comps < 1) || (num_comps > cMaxComps))
+ return false;
+
+ if ((minimum(dst_w, dst_h) < 1) || (maximum(dst_w, dst_h) > BASISU_RESAMPLER_MAX_DIMENSION))
+ {
+ printf("Image is too large!\n");
+ return false;
+ }
+
+ if ((src_w == dst_w) && (src_h == dst_h))
+ {
+ dst = src;
+ return true;
+ }
+
+ float srgb_to_linear_table[256];
+ if (srgb)
+ {
+ for (int i = 0; i < 256; ++i)
+ srgb_to_linear_table[i] = srgb_to_linear((float)i * (1.0f/255.0f));
+ }
+
+ const int LINEAR_TO_SRGB_TABLE_SIZE = 8192;
+ uint8_t linear_to_srgb_table[LINEAR_TO_SRGB_TABLE_SIZE];
+
+ if (srgb)
+ {
+ for (int i = 0; i < LINEAR_TO_SRGB_TABLE_SIZE; ++i)
+ linear_to_srgb_table[i] = (uint8_t)clamp<int>((int)(255.0f * linear_to_srgb((float)i * (1.0f / (LINEAR_TO_SRGB_TABLE_SIZE - 1))) + .5f), 0, 255);
+ }
+
+ std::vector<float> samples[cMaxComps];
+ Resampler *resamplers[cMaxComps];
+
+ resamplers[0] = new Resampler(src_w, src_h, dst_w, dst_h,
+ wrapping ? Resampler::BOUNDARY_WRAP : Resampler::BOUNDARY_CLAMP, 0.0f, 1.0f,
+ pFilter, nullptr, nullptr, filter_scale, filter_scale, 0, 0);
+ samples[0].resize(src_w);
+
+ for (uint32_t i = 1; i < num_comps; ++i)
+ {
+ resamplers[i] = new Resampler(src_w, src_h, dst_w, dst_h,
+ wrapping ? Resampler::BOUNDARY_WRAP : Resampler::BOUNDARY_CLAMP, 0.0f, 1.0f,
+ pFilter, resamplers[0]->get_clist_x(), resamplers[0]->get_clist_y(), filter_scale, filter_scale, 0, 0);
+ samples[i].resize(src_w);
+ }
+
+ uint32_t dst_y = 0;
+
+ for (uint32_t src_y = 0; src_y < src_h; ++src_y)
+ {
+ const color_rgba *pSrc = &src(0, src_y);
+
+ // Put source lines into resampler(s)
+ for (uint32_t x = 0; x < src_w; ++x)
+ {
+ for (uint32_t c = 0; c < num_comps; ++c)
+ {
+ const uint32_t comp_index = first_comp + c;
+ const uint32_t v = (*pSrc)[comp_index];
+
+ if (!srgb || (comp_index == 3))
+ samples[c][x] = v * (1.0f / 255.0f);
+ else
+ samples[c][x] = srgb_to_linear_table[v];
+ }
+
+ pSrc++;
+ }
+
+ for (uint32_t c = 0; c < num_comps; ++c)
+ {
+ if (!resamplers[c]->put_line(&samples[c][0]))
+ {
+ for (uint32_t i = 0; i < num_comps; i++)
+ delete resamplers[i];
+ return false;
+ }
+ }
+
+ // Now retrieve any output lines
+ for (;;)
+ {
+ uint32_t c;
+ for (c = 0; c < num_comps; ++c)
+ {
+ const uint32_t comp_index = first_comp + c;
+
+ const float *pOutput_samples = resamplers[c]->get_line();
+ if (!pOutput_samples)
+ break;
+
+ const bool linear_flag = !srgb || (comp_index == 3);
+
+ color_rgba *pDst = &dst(0, dst_y);
+
+ for (uint32_t x = 0; x < dst_w; x++)
+ {
+ // TODO: Add dithering
+ if (linear_flag)
+ {
+ int j = (int)(255.0f * pOutput_samples[x] + .5f);
+ (*pDst)[comp_index] = (uint8_t)clamp<int>(j, 0, 255);
+ }
+ else
+ {
+ int j = (int)((LINEAR_TO_SRGB_TABLE_SIZE - 1) * pOutput_samples[x] + .5f);
+ (*pDst)[comp_index] = linear_to_srgb_table[clamp<int>(j, 0, LINEAR_TO_SRGB_TABLE_SIZE - 1)];
+ }
+
+ pDst++;
+ }
+ }
+ if (c < num_comps)
+ break;
+
+ ++dst_y;
+ }
+ }
+
+ for (uint32_t i = 0; i < num_comps; ++i)
+ delete resamplers[i];
+
+ return true;
+ }
+
+ void canonical_huffman_calculate_minimum_redundancy(sym_freq *A, int num_syms)
+ {
+ // See the paper "In-Place Calculation of Minimum Redundancy Codes" by Moffat and Katajainen
+ if (!num_syms)
+ return;
+
+ if (1 == num_syms)
+ {
+ A[0].m_key = 1;
+ return;
+ }
+
+ A[0].m_key += A[1].m_key;
+
+ int s = 2, r = 0, next;
+ for (next = 1; next < (num_syms - 1); ++next)
+ {
+ if ((s >= num_syms) || (A[r].m_key < A[s].m_key))
+ {
+ A[next].m_key = A[r].m_key;
+ A[r].m_key = static_cast<uint16_t>(next);
+ ++r;
+ }
+ else
+ {
+ A[next].m_key = A[s].m_key;
+ ++s;
+ }
+
+ if ((s >= num_syms) || ((r < next) && A[r].m_key < A[s].m_key))
+ {
+ A[next].m_key = static_cast<uint16_t>(A[next].m_key + A[r].m_key);
+ A[r].m_key = static_cast<uint16_t>(next);
+ ++r;
+ }
+ else
+ {
+ A[next].m_key = static_cast<uint16_t>(A[next].m_key + A[s].m_key);
+ ++s;
+ }
+ }
+ A[num_syms - 2].m_key = 0;
+
+ for (next = num_syms - 3; next >= 0; --next)
+ {
+ A[next].m_key = 1 + A[A[next].m_key].m_key;
+ }
+
+ int num_avail = 1, num_used = 0, depth = 0;
+ r = num_syms - 2;
+ next = num_syms - 1;
+ while (num_avail > 0)
+ {
+ for ( ; (r >= 0) && ((int)A[r].m_key == depth); ++num_used, --r )
+ ;
+
+ for ( ; num_avail > num_used; --next, --num_avail)
+ A[next].m_key = static_cast<uint16_t>(depth);
+
+ num_avail = 2 * num_used;
+ num_used = 0;
+ ++depth;
+ }
+ }
+
+ void canonical_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
+ {
+ int i;
+ uint32_t total = 0;
+ if (code_list_len <= 1)
+ return;
+
+ for (i = max_code_size + 1; i <= cHuffmanMaxSupportedInternalCodeSize; i++)
+ pNum_codes[max_code_size] += pNum_codes[i];
+
+ for (i = max_code_size; i > 0; i--)
+ total += (((uint32_t)pNum_codes[i]) << (max_code_size - i));
+
+ while (total != (1UL << max_code_size))
+ {
+ pNum_codes[max_code_size]--;
+ for (i = max_code_size - 1; i > 0; i--)
+ {
+ if (pNum_codes[i])
+ {
+ pNum_codes[i]--;
+ pNum_codes[i + 1] += 2;
+ break;
+ }
+ }
+
+ total--;
+ }
+ }
+
+ sym_freq *canonical_huffman_radix_sort_syms(uint32_t num_syms, sym_freq *pSyms0, sym_freq *pSyms1)
+ {
+ uint32_t total_passes = 2, pass_shift, pass, i, hist[256 * 2];
+ sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
+
+ clear_obj(hist);
+
+ for (i = 0; i < num_syms; i++)
+ {
+ uint32_t freq = pSyms0[i].m_key;
+ hist[freq & 0xFF]++;
+ hist[256 + ((freq >> 8) & 0xFF)]++;
+ }
+
+ while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
+ total_passes--;
+
+ for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
+ {
+ const uint32_t *pHist = &hist[pass << 8];
+ uint32_t offsets[256], cur_ofs = 0;
+ for (i = 0; i < 256; i++)
+ {
+ offsets[i] = cur_ofs;
+ cur_ofs += pHist[i];
+ }
+
+ for (i = 0; i < num_syms; i++)
+ pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
+
+ sym_freq *t = pCur_syms;
+ pCur_syms = pNew_syms;
+ pNew_syms = t;
+ }
+
+ return pCur_syms;
+ }
+
+ bool huffman_encoding_table::init(uint32_t num_syms, const uint16_t *pFreq, uint32_t max_code_size)
+ {
+ if (max_code_size > cHuffmanMaxSupportedCodeSize)
+ return false;
+ if ((!num_syms) || (num_syms > cHuffmanMaxSyms))
+ return false;
+
+ uint32_t total_used_syms = 0;
+ for (uint32_t i = 0; i < num_syms; i++)
+ if (pFreq[i])
+ total_used_syms++;
+
+ if (!total_used_syms)
+ return false;
+
+ std::vector<sym_freq> sym_freq0(total_used_syms), sym_freq1(total_used_syms);
+ for (uint32_t i = 0, j = 0; i < num_syms; i++)
+ {
+ if (pFreq[i])
+ {
+ sym_freq0[j].m_key = pFreq[i];
+ sym_freq0[j++].m_sym_index = static_cast<uint16_t>(i);
+ }
+ }
+
+ sym_freq *pSym_freq = canonical_huffman_radix_sort_syms(total_used_syms, &sym_freq0[0], &sym_freq1[0]);
+
+ canonical_huffman_calculate_minimum_redundancy(pSym_freq, total_used_syms);
+
+ int num_codes[cHuffmanMaxSupportedInternalCodeSize + 1];
+ clear_obj(num_codes);
+
+ for (uint32_t i = 0; i < total_used_syms; i++)
+ {
+ if (pSym_freq[i].m_key > cHuffmanMaxSupportedInternalCodeSize)
+ return false;
+
+ num_codes[pSym_freq[i].m_key]++;
+ }
+
+ canonical_huffman_enforce_max_code_size(num_codes, total_used_syms, max_code_size);
+
+ m_code_sizes.resize(0);
+ m_code_sizes.resize(num_syms);
+
+ m_codes.resize(0);
+ m_codes.resize(num_syms);
+
+ for (uint32_t i = 1, j = total_used_syms; i <= max_code_size; i++)
+ for (uint32_t l = num_codes[i]; l > 0; l--)
+ m_code_sizes[pSym_freq[--j].m_sym_index] = static_cast<uint8_t>(i);
+
+ uint32_t next_code[cHuffmanMaxSupportedInternalCodeSize + 1];
+
+ next_code[1] = 0;
+ for (uint32_t j = 0, i = 2; i <= max_code_size; i++)
+ next_code[i] = j = ((j + num_codes[i - 1]) << 1);
+
+ for (uint32_t i = 0; i < num_syms; i++)
+ {
+ uint32_t rev_code = 0, code, code_size;
+ if ((code_size = m_code_sizes[i]) == 0)
+ continue;
+ if (code_size > cHuffmanMaxSupportedInternalCodeSize)
+ return false;
+ code = next_code[code_size]++;
+ for (uint32_t l = code_size; l > 0; l--, code >>= 1)
+ rev_code = (rev_code << 1) | (code & 1);
+ m_codes[i] = static_cast<uint16_t>(rev_code);
+ }
+
+ return true;
+ }
+
+ bool huffman_encoding_table::init(uint32_t num_syms, const uint32_t *pSym_freq, uint32_t max_code_size)
+ {
+ if ((!num_syms) || (num_syms > cHuffmanMaxSyms))
+ return false;
+
+ uint16_vec sym_freq(num_syms);
+
+ uint32_t max_freq = 0;
+ for (uint32_t i = 0; i < num_syms; i++)
+ max_freq = maximum(max_freq, pSym_freq[i]);
+
+ if (max_freq < UINT16_MAX)
+ {
+ for (uint32_t i = 0; i < num_syms; i++)
+ sym_freq[i] = static_cast<uint16_t>(pSym_freq[i]);
+ }
+ else
+ {
+ for (uint32_t i = 0; i < num_syms; i++)
+ if (pSym_freq[i])
+ sym_freq[i] = static_cast<uint16_t>(maximum<uint32_t>((pSym_freq[i] * 65534U + (max_freq >> 1)) / max_freq, 1));
+ }
+
+ return init(num_syms, &sym_freq[0], max_code_size);
+ }
+
+ void bitwise_coder::end_nonzero_run(uint16_vec &syms, uint32_t &run_size, uint32_t len)
+ {
+ if (run_size)
+ {
+ if (run_size < cHuffmanSmallRepeatSizeMin)
+ {
+ while (run_size--)
+ syms.push_back(static_cast<uint16_t>(len));
+ }
+ else if (run_size <= cHuffmanSmallRepeatSizeMax)
+ {
+ syms.push_back(static_cast<uint16_t>(cHuffmanSmallRepeatCode | ((run_size - cHuffmanSmallRepeatSizeMin) << 6)));
+ }
+ else
+ {
+ assert((run_size >= cHuffmanBigRepeatSizeMin) && (run_size <= cHuffmanBigRepeatSizeMax));
+ syms.push_back(static_cast<uint16_t>(cHuffmanBigRepeatCode | ((run_size - cHuffmanBigRepeatSizeMin) << 6)));
+ }
+ }
+
+ run_size = 0;
+ }
+
+ void bitwise_coder::end_zero_run(uint16_vec &syms, uint32_t &run_size)
+ {
+ if (run_size)
+ {
+ if (run_size < cHuffmanSmallZeroRunSizeMin)
+ {
+ while (run_size--)
+ syms.push_back(0);
+ }
+ else if (run_size <= cHuffmanSmallZeroRunSizeMax)
+ {
+ syms.push_back(static_cast<uint16_t>(cHuffmanSmallZeroRunCode | ((run_size - cHuffmanSmallZeroRunSizeMin) << 6)));
+ }
+ else
+ {
+ assert((run_size >= cHuffmanBigZeroRunSizeMin) && (run_size <= cHuffmanBigZeroRunSizeMax));
+ syms.push_back(static_cast<uint16_t>(cHuffmanBigZeroRunCode | ((run_size - cHuffmanBigZeroRunSizeMin) << 6)));
+ }
+ }
+
+ run_size = 0;
+ }
+
+ uint32_t bitwise_coder::emit_huffman_table(const huffman_encoding_table &tab)
+ {
+ const uint64_t start_bits = m_total_bits;
+
+ const uint8_vec &code_sizes = tab.get_code_sizes();
+
+ uint32_t total_used = tab.get_total_used_codes();
+ put_bits(total_used, cHuffmanMaxSymsLog2);
+
+ if (!total_used)
+ return 0;
+
+ uint16_vec syms;
+ syms.reserve(total_used + 16);
+
+ uint32_t prev_code_len = UINT_MAX, zero_run_size = 0, nonzero_run_size = 0;
+
+ for (uint32_t i = 0; i <= total_used; ++i)
+ {
+ const uint32_t code_len = (i == total_used) ? 0xFF : code_sizes[i];
+ assert((code_len == 0xFF) || (code_len <= 16));
+
+ if (code_len)
+ {
+ end_zero_run(syms, zero_run_size);
+
+ if (code_len != prev_code_len)
+ {
+ end_nonzero_run(syms, nonzero_run_size, prev_code_len);
+ if (code_len != 0xFF)
+ syms.push_back(static_cast<uint16_t>(code_len));
+ }
+ else if (++nonzero_run_size == cHuffmanBigRepeatSizeMax)
+ end_nonzero_run(syms, nonzero_run_size, prev_code_len);
+ }
+ else
+ {
+ end_nonzero_run(syms, nonzero_run_size, prev_code_len);
+
+ if (++zero_run_size == cHuffmanBigZeroRunSizeMax)
+ end_zero_run(syms, zero_run_size);
+ }
+
+ prev_code_len = code_len;
+ }
+
+ histogram h(cHuffmanTotalCodelengthCodes);
+ for (uint32_t i = 0; i < syms.size(); i++)
+ h.inc(syms[i] & 63);
+
+ huffman_encoding_table ct;
+ if (!ct.init(h, 7))
+ return 0;
+
+ assert(cHuffmanTotalSortedCodelengthCodes == cHuffmanTotalCodelengthCodes);
+
+ uint32_t total_codelength_codes;
+ for (total_codelength_codes = cHuffmanTotalSortedCodelengthCodes; total_codelength_codes > 0; total_codelength_codes--)
+ if (ct.get_code_sizes()[g_huffman_sorted_codelength_codes[total_codelength_codes - 1]])
+ break;
+
+ assert(total_codelength_codes);
+
+ put_bits(total_codelength_codes, 5);
+ for (uint32_t i = 0; i < total_codelength_codes; i++)
+ put_bits(ct.get_code_sizes()[g_huffman_sorted_codelength_codes[i]], 3);
+
+ for (uint32_t i = 0; i < syms.size(); ++i)
+ {
+ const uint32_t l = syms[i] & 63, e = syms[i] >> 6;
+
+ put_code(l, ct);
+
+ if (l == cHuffmanSmallZeroRunCode)
+ put_bits(e, cHuffmanSmallZeroRunExtraBits);
+ else if (l == cHuffmanBigZeroRunCode)
+ put_bits(e, cHuffmanBigZeroRunExtraBits);
+ else if (l == cHuffmanSmallRepeatCode)
+ put_bits(e, cHuffmanSmallRepeatExtraBits);
+ else if (l == cHuffmanBigRepeatCode)
+ put_bits(e, cHuffmanBigRepeatExtraBits);
+ }
+
+ return (uint32_t)(m_total_bits - start_bits);
+ }
+
+ bool huffman_test(int rand_seed)
+ {
+ histogram h(19);
+
+ // Feed in a fibonacci sequence to force large codesizes
+ h[0] += 1; h[1] += 1; h[2] += 2; h[3] += 3;
+ h[4] += 5; h[5] += 8; h[6] += 13; h[7] += 21;
+ h[8] += 34; h[9] += 55; h[10] += 89; h[11] += 144;
+ h[12] += 233; h[13] += 377; h[14] += 610; h[15] += 987;
+ h[16] += 1597; h[17] += 2584; h[18] += 4181;
+
+ huffman_encoding_table etab;
+ etab.init(h, 16);
+
+ {
+ bitwise_coder c;
+ c.init(1024);
+
+ c.emit_huffman_table(etab);
+ for (int i = 0; i < 19; i++)
+ c.put_code(i, etab);
+
+ c.flush();
+
+ basist::bitwise_decoder d;
+ d.init(&c.get_bytes()[0], static_cast<uint32_t>(c.get_bytes().size()));
+
+ basist::huffman_decoding_table dtab;
+ bool success = d.read_huffman_table(dtab);
+ if (!success)
+ {
+ assert(0);
+ printf("Failure 5\n");
+ return false;
+ }
+
+ for (uint32_t i = 0; i < 19; i++)
+ {
+ uint32_t s = d.decode_huffman(dtab);
+ if (s != i)
+ {
+ assert(0);
+ printf("Failure 5\n");
+ return false;
+ }
+ }
+ }
+
+ basisu::rand r;
+ r.seed(rand_seed);
+
+ for (int iter = 0; iter < 500000; iter++)
+ {
+ printf("%u\n", iter);
+
+ uint32_t max_sym = r.irand(0, 8193);
+ uint32_t num_codes = r.irand(1, 10000);
+ uint_vec syms(num_codes);
+
+ for (uint32_t i = 0; i < num_codes; i++)
+ {
+ if (r.bit())
+ syms[i] = r.irand(0, max_sym);
+ else
+ {
+ int s = (int)(r.gaussian((float)max_sym / 2, (float)maximum<int>(1, max_sym / 2)) + .5f);
+ s = basisu::clamp<int>(s, 0, max_sym);
+
+ syms[i] = s;
+ }
+
+ }
+
+ histogram h1(max_sym + 1);
+ for (uint32_t i = 0; i < num_codes; i++)
+ h1[syms[i]]++;
+
+ huffman_encoding_table etab2;
+ if (!etab2.init(h1, 16))
+ {
+ assert(0);
+ printf("Failed 0\n");
+ return false;
+ }
+
+ bitwise_coder c;
+ c.init(1024);
+
+ c.emit_huffman_table(etab2);
+
+ for (uint32_t i = 0; i < num_codes; i++)
+ c.put_code(syms[i], etab2);
+
+ c.flush();
+
+ basist::bitwise_decoder d;
+ d.init(&c.get_bytes()[0], (uint32_t)c.get_bytes().size());
+
+ basist::huffman_decoding_table dtab;
+ bool success = d.read_huffman_table(dtab);
+ if (!success)
+ {
+ assert(0);
+ printf("Failed 2\n");
+ return false;
+ }
+
+ for (uint32_t i = 0; i < num_codes; i++)
+ {
+ uint32_t s = d.decode_huffman(dtab);
+ if (s != syms[i])
+ {
+ assert(0);
+ printf("Failed 4\n");
+ return false;
+ }
+ }
+
+ }
+ return true;
+ }
+
+ void palette_index_reorderer::init(uint32_t num_indices, const uint32_t *pIndices, uint32_t num_syms, pEntry_dist_func pDist_func, void *pCtx, float dist_func_weight)
+ {
+ assert((num_syms > 0) && (num_indices > 0));
+ assert((dist_func_weight >= 0.0f) && (dist_func_weight <= 1.0f));
+
+ clear();
+
+ m_remap_table.resize(num_syms);
+ m_entries_picked.reserve(num_syms);
+ m_total_count_to_picked.resize(num_syms);
+
+ if (num_indices <= 1)
+ return;
+
+ prepare_hist(num_syms, num_indices, pIndices);
+ find_initial(num_syms);
+
+ while (m_entries_to_do.size())
+ {
+ // Find the best entry to move into the picked list.
+ uint32_t best_entry;
+ double best_count;
+ find_next_entry(best_entry, best_count, pDist_func, pCtx, dist_func_weight);
+
+ // We now have chosen an entry to place in the picked list, now determine which side it goes on.
+ const uint32_t entry_to_move = m_entries_to_do[best_entry];
+
+ float side = pick_side(num_syms, entry_to_move, pDist_func, pCtx, dist_func_weight);
+
+ // Put entry_to_move either on the "left" or "right" side of the picked entries
+ if (side <= 0)
+ m_entries_picked.push_back(entry_to_move);
+ else
+ m_entries_picked.insert(m_entries_picked.begin(), entry_to_move);
+
+ // Erase best_entry from the todo list
+ m_entries_to_do.erase(m_entries_to_do.begin() + best_entry);
+
+ // We've just moved best_entry to the picked list, so now we need to update m_total_count_to_picked[] to factor the additional count to best_entry
+ for (uint32_t i = 0; i < m_entries_to_do.size(); i++)
+ m_total_count_to_picked[m_entries_to_do[i]] += get_hist(m_entries_to_do[i], entry_to_move, num_syms);
+ }
+
+ for (uint32_t i = 0; i < num_syms; i++)
+ m_remap_table[m_entries_picked[i]] = i;
+ }
+
+ void palette_index_reorderer::prepare_hist(uint32_t num_syms, uint32_t num_indices, const uint32_t *pIndices)
+ {
+ m_hist.resize(0);
+ m_hist.resize(num_syms * num_syms);
+
+ for (uint32_t i = 0; i < num_indices; i++)
+ {
+ const uint32_t idx = pIndices[i];
+ inc_hist(idx, (i < (num_indices - 1)) ? pIndices[i + 1] : -1, num_syms);
+ inc_hist(idx, (i > 0) ? pIndices[i - 1] : -1, num_syms);
+ }
+ }
+
+ void palette_index_reorderer::find_initial(uint32_t num_syms)
+ {
+ uint32_t max_count = 0, max_index = 0;
+ for (uint32_t i = 0; i < num_syms * num_syms; i++)
+ if (m_hist[i] > max_count)
+ max_count = m_hist[i], max_index = i;
+
+ uint32_t a = max_index / num_syms, b = max_index % num_syms;
+
+ m_entries_picked.push_back(a);
+ m_entries_picked.push_back(b);
+
+ for (uint32_t i = 0; i < num_syms; i++)
+ if ((i != b) && (i != a))
+ m_entries_to_do.push_back(i);
+
+ for (uint32_t i = 0; i < m_entries_to_do.size(); i++)
+ for (uint32_t j = 0; j < m_entries_picked.size(); j++)
+ m_total_count_to_picked[m_entries_to_do[i]] += get_hist(m_entries_to_do[i], m_entries_picked[j], num_syms);
+ }
+
+ void palette_index_reorderer::find_next_entry(uint32_t &best_entry, double &best_count, pEntry_dist_func pDist_func, void *pCtx, float dist_func_weight)
+ {
+ best_entry = 0;
+ best_count = 0;
+
+ for (uint32_t i = 0; i < m_entries_to_do.size(); i++)
+ {
+ const uint32_t u = m_entries_to_do[i];
+ double total_count = m_total_count_to_picked[u];
+
+ if (pDist_func)
+ {
+ float w = maximum<float>((*pDist_func)(u, m_entries_picked.front(), pCtx), (*pDist_func)(u, m_entries_picked.back(), pCtx));
+ assert((w >= 0.0f) && (w <= 1.0f));
+ total_count = (total_count + 1.0f) * lerp(1.0f - dist_func_weight, 1.0f + dist_func_weight, w);
+ }
+
+ if (total_count <= best_count)
+ continue;
+
+ best_entry = i;
+ best_count = total_count;
+ }
+ }
+
+ float palette_index_reorderer::pick_side(uint32_t num_syms, uint32_t entry_to_move, pEntry_dist_func pDist_func, void *pCtx, float dist_func_weight)
+ {
+ float which_side = 0;
+
+ int l_count = 0, r_count = 0;
+ for (uint32_t j = 0; j < m_entries_picked.size(); j++)
+ {
+ const int count = get_hist(entry_to_move, m_entries_picked[j], num_syms), r = ((int)m_entries_picked.size() + 1 - 2 * (j + 1));
+ which_side += static_cast<float>(r * count);
+ if (r >= 0)
+ l_count += r * count;
+ else
+ r_count += -r * count;
+ }
+
+ if (pDist_func)
+ {
+ float w_left = lerp(1.0f - dist_func_weight, 1.0f + dist_func_weight, (*pDist_func)(entry_to_move, m_entries_picked.front(), pCtx));
+ float w_right = lerp(1.0f - dist_func_weight, 1.0f + dist_func_weight, (*pDist_func)(entry_to_move, m_entries_picked.back(), pCtx));
+ which_side = w_left * l_count - w_right * r_count;
+ }
+ return which_side;
+ }
+
+ void image_metrics::calc(const image &a, const image &b, uint32_t first_chan, uint32_t total_chans, bool avg_comp_error, bool use_601_luma)
+ {
+ assert((first_chan < 4U) && (first_chan + total_chans <= 4U));
+
+ const uint32_t width = std::min(a.get_width(), b.get_width());
+ const uint32_t height = std::min(a.get_height(), b.get_height());
+
+ double hist[256];
+ clear_obj(hist);
+
+ for (uint32_t y = 0; y < height; y++)
+ {
+ for (uint32_t x = 0; x < width; x++)
+ {
+ const color_rgba &ca = a(x, y), &cb = b(x, y);
+
+ if (total_chans)
+ {
+ for (uint32_t c = 0; c < total_chans; c++)
+ hist[iabs(ca[first_chan + c] - cb[first_chan + c])]++;
+ }
+ else
+ {
+ if (use_601_luma)
+ hist[iabs(ca.get_601_luma() - cb.get_601_luma())]++;
+ else
+ hist[iabs(ca.get_709_luma() - cb.get_709_luma())]++;
+ }
+ }
+ }
+
+ m_max = 0;
+ double sum = 0.0f, sum2 = 0.0f;
+ for (uint32_t i = 0; i < 256; i++)
+ {
+ if (hist[i])
+ {
+ m_max = std::max<float>(m_max, (float)i);
+ double v = i * hist[i];
+ sum += v;
+ sum2 += i * v;
+ }
+ }
+
+ double total_values = (double)width * (double)height;
+ if (avg_comp_error)
+ total_values *= (double)clamp<uint32_t>(total_chans, 1, 4);
+
+ m_mean = (float)clamp<double>(sum / total_values, 0.0f, 255.0);
+ m_mean_squared = (float)clamp<double>(sum2 / total_values, 0.0f, 255.0 * 255.0);
+ m_rms = (float)sqrt(m_mean_squared);
+ m_psnr = m_rms ? (float)clamp<double>(log10(255.0 / m_rms) * 20.0, 0.0f, 300.0f) : 1e+10f;
+ }
+
+ void fill_buffer_with_random_bytes(void *pBuf, size_t size, uint32_t seed)
+ {
+ rand r(seed);
+
+ uint8_t *pDst = static_cast<uint8_t *>(pBuf);
+
+ while (size >= sizeof(uint32_t))
+ {
+ *(uint32_t *)pDst = r.urand32();
+ pDst += sizeof(uint32_t);
+ size -= sizeof(uint32_t);
+ }
+
+ while (size)
+ {
+ *pDst++ = r.byte();
+ size--;
+ }
+ }
+
+ uint32_t hash_hsieh(const uint8_t *pBuf, size_t len)
+ {
+ if (!pBuf || !len)
+ return 0;
+
+ uint32_t h = static_cast<uint32_t>(len);
+
+ const uint32_t bytes_left = len & 3;
+ len >>= 2;
+
+ while (len--)
+ {
+ const uint16_t *pWords = reinterpret_cast<const uint16_t *>(pBuf);
+
+ h += pWords[0];
+
+ const uint32_t t = (pWords[1] << 11) ^ h;
+ h = (h << 16) ^ t;
+
+ pBuf += sizeof(uint32_t);
+
+ h += h >> 11;
+ }
+
+ switch (bytes_left)
+ {
+ case 1:
+ h += *reinterpret_cast<const signed char*>(pBuf);
+ h ^= h << 10;
+ h += h >> 1;
+ break;
+ case 2:
+ h += *reinterpret_cast<const uint16_t *>(pBuf);
+ h ^= h << 11;
+ h += h >> 17;
+ break;
+ case 3:
+ h += *reinterpret_cast<const uint16_t *>(pBuf);
+ h ^= h << 16;
+ h ^= (static_cast<signed char>(pBuf[sizeof(uint16_t)])) << 18;
+ h += h >> 11;
+ break;
+ default:
+ break;
+ }
+
+ h ^= h << 3;
+ h += h >> 5;
+ h ^= h << 4;
+ h += h >> 17;
+ h ^= h << 25;
+ h += h >> 6;
+
+ return h;
+ }
+
+ job_pool::job_pool(uint32_t num_threads) :
+ m_kill_flag(false),
+ m_num_active_jobs(0)
+ {
+ assert(num_threads >= 1U);
+
+ debug_printf("job_pool::job_pool: %u total threads\n", num_threads);
+
+ if (num_threads > 1)
+ {
+ m_threads.resize(num_threads - 1);
+
+ for (int i = 0; i < ((int)num_threads - 1); i++)
+ m_threads[i] = std::thread([this, i] { job_thread(i); });
+ }
+ }
+
+ job_pool::~job_pool()
+ {
+ debug_printf("job_pool::~job_pool\n");
+
+ // Notify all workers that they need to die right now.
+ m_kill_flag = true;
+
+ m_has_work.notify_all();
+
+ // Wait for all workers to die.
+ for (uint32_t i = 0; i < m_threads.size(); i++)
+ m_threads[i].join();
+ }
+
+ void job_pool::add_job(const std::function<void()>& job)
+ {
+ std::unique_lock<std::mutex> lock(m_mutex);
+
+ m_queue.emplace_back(job);
+
+ const size_t queue_size = m_queue.size();
+
+ lock.unlock();
+
+ if (queue_size > 1)
+ m_has_work.notify_one();
+ }
+
+ void job_pool::add_job(std::function<void()>&& job)
+ {
+ std::unique_lock<std::mutex> lock(m_mutex);
+
+ m_queue.emplace_back(std::move(job));
+
+ const size_t queue_size = m_queue.size();
+
+ lock.unlock();
+
+ if (queue_size > 1)
+ m_has_work.notify_one();
+ }
+
+ void job_pool::wait_for_all()
+ {
+ std::unique_lock<std::mutex> lock(m_mutex);
+
+ // Drain the job queue on the calling thread.
+ while (!m_queue.empty())
+ {
+ std::function<void()> job(m_queue.back());
+ m_queue.pop_back();
+
+ lock.unlock();
+
+ job();
+
+ lock.lock();
+ }
+
+ // The queue is empty, now wait for all active jobs to finish up.
+ m_no_more_jobs.wait(lock, [this]{ return !m_num_active_jobs; } );
+ }
+
+ void job_pool::job_thread(uint32_t index)
+ {
+ debug_printf("job_pool::job_thread: starting %u\n", index);
+
+ while (true)
+ {
+ std::unique_lock<std::mutex> lock(m_mutex);
+
+ // Wait for any jobs to be issued.
+ m_has_work.wait(lock, [this] { return m_kill_flag || m_queue.size(); } );
+
+ // Check to see if we're supposed to exit.
+ if (m_kill_flag)
+ break;
+
+ // Get the job and execute it.
+ std::function<void()> job(m_queue.back());
+ m_queue.pop_back();
+
+ ++m_num_active_jobs;
+
+ lock.unlock();
+
+ job();
+
+ lock.lock();
+
+ --m_num_active_jobs;
+
+ // Now check if there are no more jobs remaining.
+ const bool all_done = m_queue.empty() && !m_num_active_jobs;
+
+ lock.unlock();
+
+ if (all_done)
+ m_no_more_jobs.notify_all();
+ }
+
+ debug_printf("job_pool::job_thread: exiting\n");
+ }
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_enc.h b/thirdparty/basis_universal/basisu_enc.h
new file mode 100644
index 0000000000..0a0c3c6fc0
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_enc.h
@@ -0,0 +1,2806 @@
+// basisu_enc.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "transcoder/basisu.h"
+#include "transcoder/basisu_transcoder_internal.h"
+
+#include <mutex>
+#include <atomic>
+#include <condition_variable>
+#include <functional>
+#include <thread>
+#include <unordered_map>
+#include <ostream>
+
+#if !defined(_WIN32) || defined(__MINGW32__)
+#include <libgen.h>
+#endif
+
+namespace basisu
+{
+ extern uint8_t g_hamming_dist[256];
+
+ // Encoder library initialization
+ void basisu_encoder_init();
+
+ void error_printf(const char *pFmt, ...);
+
+ // Helpers
+
+ inline uint8_t clamp255(int32_t i)
+ {
+ return (uint8_t)((i & 0xFFFFFF00U) ? (~(i >> 31)) : i);
+ }
+
+ // Hashing
+
+ inline uint32_t bitmix32c(uint32_t v)
+ {
+ v = (v + 0x7ed55d16) + (v << 12);
+ v = (v ^ 0xc761c23c) ^ (v >> 19);
+ v = (v + 0x165667b1) + (v << 5);
+ v = (v + 0xd3a2646c) ^ (v << 9);
+ v = (v + 0xfd7046c5) + (v << 3);
+ v = (v ^ 0xb55a4f09) ^ (v >> 16);
+ return v;
+ }
+
+ inline uint32_t bitmix32(uint32_t v)
+ {
+ v -= (v << 6);
+ v ^= (v >> 17);
+ v -= (v << 9);
+ v ^= (v << 4);
+ v -= (v << 3);
+ v ^= (v << 10);
+ v ^= (v >> 15);
+ return v;
+ }
+
+ uint32_t hash_hsieh(const uint8_t* pBuf, size_t len);
+
+ template <typename Key>
+ struct bit_hasher
+ {
+ std::size_t operator()(const Key& k) const
+ {
+ return hash_hsieh(reinterpret_cast<const uint8_t *>(&k), sizeof(k));
+ }
+ };
+
+ // Linear algebra
+
+ template <uint32_t N, typename T>
+ class vec
+ {
+ protected:
+ T m_v[N];
+
+ public:
+ enum { num_elements = N };
+
+ inline vec() { }
+ inline vec(eZero) { set_zero(); }
+
+ explicit inline vec(T val) { set(val); }
+ inline vec(T v0, T v1) { set(v0, v1); }
+ inline vec(T v0, T v1, T v2) { set(v0, v1, v2); }
+ inline vec(T v0, T v1, T v2, T v3) { set(v0, v1, v2, v3); }
+ inline vec(const vec &other) { for (uint32_t i = 0; i < N; i++) m_v[i] = other.m_v[i]; }
+ template <uint32_t OtherN, typename OtherT> inline vec(const vec<OtherN, OtherT> &other) { set(other); }
+
+ inline T operator[](uint32_t i) const { assert(i < N); return m_v[i]; }
+ inline T &operator[](uint32_t i) { assert(i < N); return m_v[i]; }
+
+ inline T getX() const { return m_v[0]; }
+ inline T getY() const { static_assert(N >= 2, "N too small"); return m_v[1]; }
+ inline T getZ() const { static_assert(N >= 3, "N too small"); return m_v[2]; }
+ inline T getW() const { static_assert(N >= 4, "N too small"); return m_v[3]; }
+
+ inline bool operator==(const vec &rhs) const { for (uint32_t i = 0; i < N; i++) if (m_v[i] != rhs.m_v[i]) return false; return true; }
+ inline bool operator<(const vec &rhs) const { for (uint32_t i = 0; i < N; i++) { if (m_v[i] < rhs.m_v[i]) return true; else if (m_v[i] != rhs.m_v[i]) return false; } return false; }
+
+ inline void set_zero() { for (uint32_t i = 0; i < N; i++) m_v[i] = 0; }
+
+ template <uint32_t OtherN, typename OtherT>
+ inline vec &set(const vec<OtherN, OtherT> &other)
+ {
+ uint32_t i;
+ if (static_cast<void *>(&other) == static_cast<void *>(this))
+ return *this;
+ const uint32_t m = minimum(OtherN, N);
+ for (i = 0; i < m; i++)
+ m_v[i] = static_cast<T>(other[i]);
+ for (; i < N; i++)
+ m_v[i] = 0;
+ return *this;
+ }
+
+ inline vec &set_component(uint32_t index, T val) { assert(index < N); m_v[index] = val; return *this; }
+ inline vec &set(T val) { for (uint32_t i = 0; i < N; i++) m_v[i] = val; return *this; }
+ inline void clear_elements(uint32_t s, uint32_t e) { assert(e <= N); for (uint32_t i = s; i < e; i++) m_v[i] = 0; }
+
+ inline vec &set(T v0, T v1)
+ {
+ m_v[0] = v0;
+ if (N >= 2)
+ {
+ m_v[1] = v1;
+ clear_elements(2, N);
+ }
+ return *this;
+ }
+
+ inline vec &set(T v0, T v1, T v2)
+ {
+ m_v[0] = v0;
+ if (N >= 2)
+ {
+ m_v[1] = v1;
+ if (N >= 3)
+ {
+ m_v[2] = v2;
+ clear_elements(3, N);
+ }
+ }
+ return *this;
+ }
+
+ inline vec &set(T v0, T v1, T v2, T v3)
+ {
+ m_v[0] = v0;
+ if (N >= 2)
+ {
+ m_v[1] = v1;
+ if (N >= 3)
+ {
+ m_v[2] = v2;
+
+ if (N >= 4)
+ {
+ m_v[3] = v3;
+ clear_elements(5, N);
+ }
+ }
+ }
+ return *this;
+ }
+
+ inline vec &operator=(const vec &rhs) { if (this != &rhs) for (uint32_t i = 0; i < N; i++) m_v[i] = rhs.m_v[i]; return *this; }
+ template <uint32_t OtherN, typename OtherT> inline vec &operator=(const vec<OtherN, OtherT> &rhs) { set(rhs); return *this; }
+
+ inline const T *get_ptr() const { return reinterpret_cast<const T *>(&m_v[0]); }
+ inline T *get_ptr() { return reinterpret_cast<T *>(&m_v[0]); }
+
+ inline vec operator- () const { vec res; for (uint32_t i = 0; i < N; i++) res.m_v[i] = -m_v[i]; return res; }
+ inline vec operator+ () const { return *this; }
+ inline vec &operator+= (const vec &other) { for (uint32_t i = 0; i < N; i++) m_v[i] += other.m_v[i]; return *this; }
+ inline vec &operator-= (const vec &other) { for (uint32_t i = 0; i < N; i++) m_v[i] -= other.m_v[i]; return *this; }
+ inline vec &operator/= (const vec &other) { for (uint32_t i = 0; i < N; i++) m_v[i] /= other.m_v[i]; return *this; }
+ inline vec &operator*=(const vec &other) { for (uint32_t i = 0; i < N; i++) m_v[i] *= other.m_v[i]; return *this; }
+ inline vec &operator/= (T s) { for (uint32_t i = 0; i < N; i++) m_v[i] /= s; return *this; }
+ inline vec &operator*= (T s) { for (uint32_t i = 0; i < N; i++) m_v[i] *= s; return *this; }
+
+ friend inline vec operator+(const vec &lhs, const vec &rhs) { vec res; for (uint32_t i = 0; i < N; i++) res.m_v[i] = lhs.m_v[i] + rhs.m_v[i]; return res; }
+ friend inline vec operator-(const vec &lhs, const vec &rhs) { vec res; for (uint32_t i = 0; i < N; i++) res.m_v[i] = lhs.m_v[i] - rhs.m_v[i]; return res; }
+ friend inline vec operator*(const vec &lhs, T val) { vec res; for (uint32_t i = 0; i < N; i++) res.m_v[i] = lhs.m_v[i] * val; return res; }
+ friend inline vec operator*(T val, const vec &rhs) { vec res; for (uint32_t i = 0; i < N; i++) res.m_v[i] = val * rhs.m_v[i]; return res; }
+ friend inline vec operator/(const vec &lhs, T val) { vec res; for (uint32_t i = 0; i < N; i++) res.m_v[i] = lhs.m_v[i] / val; return res; }
+ friend inline vec operator/(const vec &lhs, const vec &rhs) { vec res; for (uint32_t i = 0; i < N; i++) res.m_v[i] = lhs.m_v[i] / rhs.m_v[i]; return res; }
+
+ static inline T dot_product(const vec &lhs, const vec &rhs) { T res = lhs.m_v[0] * rhs.m_v[0]; for (uint32_t i = 1; i < N; i++) res += lhs.m_v[i] * rhs.m_v[i]; return res; }
+
+ inline T dot(const vec &rhs) const { return dot_product(*this, rhs); }
+
+ inline T norm() const { return dot_product(*this, *this); }
+ inline T length() const { return sqrt(norm()); }
+
+ inline T squared_distance(const vec &other) const { T d2 = 0; for (uint32_t i = 0; i < N; i++) { T d = m_v[i] - other.m_v[i]; d2 += d * d; } return d2; }
+ inline double squared_distance_d(const vec& other) const { double d2 = 0; for (uint32_t i = 0; i < N; i++) { double d = (double)m_v[i] - (double)other.m_v[i]; d2 += d * d; } return d2; }
+
+ inline T distance(const vec &other) const { return static_cast<T>(sqrt(squared_distance(other))); }
+ inline double distance_d(const vec& other) const { return sqrt(squared_distance_d(other)); }
+
+ inline vec &normalize_in_place() { T len = length(); if (len != 0.0f) *this *= (1.0f / len); return *this; }
+
+ inline vec &clamp(T l, T h)
+ {
+ for (uint32_t i = 0; i < N; i++)
+ m_v[i] = basisu::clamp(m_v[i], l, h);
+ return *this;
+ }
+
+ static vec component_min(const vec& a, const vec& b)
+ {
+ vec res;
+ for (uint32_t i = 0; i < N; i++)
+ res[i] = minimum(a[i], b[i]);
+ return res;
+ }
+
+ static vec component_max(const vec& a, const vec& b)
+ {
+ vec res;
+ for (uint32_t i = 0; i < N; i++)
+ res[i] = maximum(a[i], b[i]);
+ return res;
+ }
+ };
+
+ typedef vec<4, double> vec4D;
+ typedef vec<3, double> vec3D;
+ typedef vec<2, double> vec2D;
+ typedef vec<1, double> vec1D;
+
+ typedef vec<4, float> vec4F;
+ typedef vec<3, float> vec3F;
+ typedef vec<2, float> vec2F;
+ typedef vec<1, float> vec1F;
+
+ template <uint32_t Rows, uint32_t Cols, typename T>
+ class matrix
+ {
+ public:
+ typedef vec<Rows, T> col_vec;
+ typedef vec<Cols, T> row_vec;
+
+ typedef T scalar_type;
+
+ enum { rows = Rows, cols = Cols };
+
+ protected:
+ row_vec m_r[Rows];
+
+ public:
+ inline matrix() {}
+ inline matrix(eZero) { set_zero(); }
+ inline matrix(const matrix &other) { for (uint32_t i = 0; i < Rows; i++) m_r[i] = other.m_r[i]; }
+ inline matrix &operator=(const matrix &rhs) { if (this != &rhs) for (uint32_t i = 0; i < Rows; i++) m_r[i] = rhs.m_r[i]; return *this; }
+
+ inline T operator()(uint32_t r, uint32_t c) const { assert((r < Rows) && (c < Cols)); return m_r[r][c]; }
+ inline T &operator()(uint32_t r, uint32_t c) { assert((r < Rows) && (c < Cols)); return m_r[r][c]; }
+
+ inline const row_vec &operator[](uint32_t r) const { assert(r < Rows); return m_r[r]; }
+ inline row_vec &operator[](uint32_t r) { assert(r < Rows); return m_r[r]; }
+
+ inline matrix &set_zero()
+ {
+ for (uint32_t i = 0; i < Rows; i++)
+ m_r[i].set_zero();
+ return *this;
+ }
+
+ inline matrix &set_identity()
+ {
+ for (uint32_t i = 0; i < Rows; i++)
+ {
+ m_r[i].set_zero();
+ if (i < Cols)
+ m_r[i][i] = 1.0f;
+ }
+ return *this;
+ }
+ };
+
+ template<uint32_t N, typename VectorType>
+ inline VectorType compute_pca_from_covar(matrix<N, N, float> &cmatrix)
+ {
+ VectorType axis;
+ if (N == 1)
+ axis.set(1.0f);
+ else
+ {
+ for (uint32_t i = 0; i < N; i++)
+ axis[i] = lerp(.75f, 1.25f, i * (1.0f / maximum<int>(N - 1, 1)));
+ }
+
+ VectorType prev_axis(axis);
+
+ // Power iterations
+ for (uint32_t power_iter = 0; power_iter < 8; power_iter++)
+ {
+ VectorType trial_axis;
+ double max_sum = 0;
+
+ for (uint32_t i = 0; i < N; i++)
+ {
+ double sum = 0;
+ for (uint32_t j = 0; j < N; j++)
+ sum += cmatrix[i][j] * axis[j];
+
+ trial_axis[i] = static_cast<float>(sum);
+
+ max_sum = maximum(fabs(sum), max_sum);
+ }
+
+ if (max_sum != 0.0f)
+ trial_axis *= static_cast<float>(1.0f / max_sum);
+
+ VectorType delta_axis(prev_axis - trial_axis);
+
+ prev_axis = axis;
+ axis = trial_axis;
+
+ if (delta_axis.norm() < .0024f)
+ break;
+ }
+
+ return axis.normalize_in_place();
+ }
+
+ template<typename T> inline void indirect_sort(uint32_t num_indices, uint32_t* pIndices, const T* pKeys)
+ {
+ for (uint32_t i = 0; i < num_indices; i++)
+ pIndices[i] = i;
+
+ std::sort(
+ pIndices,
+ pIndices + num_indices,
+ [pKeys](uint32_t a, uint32_t b) { return pKeys[a] < pKeys[b]; }
+ );
+ }
+
+ // Very simple job pool with no dependencies.
+ class job_pool
+ {
+ BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(job_pool);
+
+ public:
+ job_pool(uint32_t num_threads);
+ ~job_pool();
+
+ void add_job(const std::function<void()>& job);
+ void add_job(std::function<void()>&& job);
+
+ void wait_for_all();
+
+ size_t get_total_threads() const { return 1 + m_threads.size(); }
+
+ private:
+ std::vector<std::thread> m_threads;
+ std::vector<std::function<void()> > m_queue;
+
+ std::mutex m_mutex;
+ std::condition_variable m_has_work;
+ std::condition_variable m_no_more_jobs;
+
+ uint32_t m_num_active_jobs;
+
+ std::atomic<bool> m_kill_flag;
+
+ void job_thread(uint32_t index);
+ };
+
+ // Simple 32-bit color class
+
+ class color_rgba_i16
+ {
+ public:
+ union
+ {
+ int16_t m_comps[4];
+
+ struct
+ {
+ int16_t r;
+ int16_t g;
+ int16_t b;
+ int16_t a;
+ };
+ };
+
+ inline color_rgba_i16()
+ {
+ static_assert(sizeof(*this) == sizeof(int16_t)*4, "sizeof(*this) == sizeof(int16_t)*4");
+ }
+
+ inline color_rgba_i16(int sr, int sg, int sb, int sa)
+ {
+ set(sr, sg, sb, sa);
+ }
+
+ inline color_rgba_i16 &set(int sr, int sg, int sb, int sa)
+ {
+ m_comps[0] = (int16_t)clamp<int>(sr, INT16_MIN, INT16_MAX);
+ m_comps[1] = (int16_t)clamp<int>(sg, INT16_MIN, INT16_MAX);
+ m_comps[2] = (int16_t)clamp<int>(sb, INT16_MIN, INT16_MAX);
+ m_comps[3] = (int16_t)clamp<int>(sa, INT16_MIN, INT16_MAX);
+ return *this;
+ }
+ };
+
+ class color_rgba
+ {
+ public:
+ union
+ {
+ uint8_t m_comps[4];
+
+ struct
+ {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+ uint8_t a;
+ };
+ };
+
+ inline color_rgba()
+ {
+ static_assert(sizeof(*this) == 4, "sizeof(*this) != 4");
+ }
+
+ inline color_rgba(int y)
+ {
+ set(y);
+ }
+
+ inline color_rgba(int y, int na)
+ {
+ set(y, na);
+ }
+
+ inline color_rgba(int sr, int sg, int sb, int sa)
+ {
+ set(sr, sg, sb, sa);
+ }
+
+ inline color_rgba(eNoClamp, int sr, int sg, int sb, int sa)
+ {
+ set_noclamp_rgba((uint8_t)sr, (uint8_t)sg, (uint8_t)sb, (uint8_t)sa);
+ }
+
+ inline color_rgba& set_noclamp_y(int y)
+ {
+ m_comps[0] = (uint8_t)y;
+ m_comps[1] = (uint8_t)y;
+ m_comps[2] = (uint8_t)y;
+ m_comps[3] = (uint8_t)255;
+ return *this;
+ }
+
+ inline color_rgba &set_noclamp_rgba(int sr, int sg, int sb, int sa)
+ {
+ m_comps[0] = (uint8_t)sr;
+ m_comps[1] = (uint8_t)sg;
+ m_comps[2] = (uint8_t)sb;
+ m_comps[3] = (uint8_t)sa;
+ return *this;
+ }
+
+ inline color_rgba &set(int y)
+ {
+ m_comps[0] = static_cast<uint8_t>(clamp<int>(y, 0, 255));
+ m_comps[1] = m_comps[0];
+ m_comps[2] = m_comps[0];
+ m_comps[3] = 255;
+ return *this;
+ }
+
+ inline color_rgba &set(int y, int na)
+ {
+ m_comps[0] = static_cast<uint8_t>(clamp<int>(y, 0, 255));
+ m_comps[1] = m_comps[0];
+ m_comps[2] = m_comps[0];
+ m_comps[3] = static_cast<uint8_t>(clamp<int>(na, 0, 255));
+ return *this;
+ }
+
+ inline color_rgba &set(int sr, int sg, int sb, int sa)
+ {
+ m_comps[0] = static_cast<uint8_t>(clamp<int>(sr, 0, 255));
+ m_comps[1] = static_cast<uint8_t>(clamp<int>(sg, 0, 255));
+ m_comps[2] = static_cast<uint8_t>(clamp<int>(sb, 0, 255));
+ m_comps[3] = static_cast<uint8_t>(clamp<int>(sa, 0, 255));
+ return *this;
+ }
+
+ inline color_rgba &set_rgb(int sr, int sg, int sb)
+ {
+ m_comps[0] = static_cast<uint8_t>(clamp<int>(sr, 0, 255));
+ m_comps[1] = static_cast<uint8_t>(clamp<int>(sg, 0, 255));
+ m_comps[2] = static_cast<uint8_t>(clamp<int>(sb, 0, 255));
+ return *this;
+ }
+
+ inline color_rgba &set_rgb(const color_rgba &other)
+ {
+ r = other.r;
+ g = other.g;
+ b = other.b;
+ return *this;
+ }
+
+ inline const uint8_t &operator[] (uint32_t index) const { assert(index < 4); return m_comps[index]; }
+ inline uint8_t &operator[] (uint32_t index) { assert(index < 4); return m_comps[index]; }
+
+ inline void clear()
+ {
+ m_comps[0] = 0;
+ m_comps[1] = 0;
+ m_comps[2] = 0;
+ m_comps[3] = 0;
+ }
+
+ inline bool operator== (const color_rgba &rhs) const
+ {
+ if (m_comps[0] != rhs.m_comps[0]) return false;
+ if (m_comps[1] != rhs.m_comps[1]) return false;
+ if (m_comps[2] != rhs.m_comps[2]) return false;
+ if (m_comps[3] != rhs.m_comps[3]) return false;
+ return true;
+ }
+
+ inline bool operator!= (const color_rgba &rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ inline bool operator<(const color_rgba &rhs) const
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ if (m_comps[i] < rhs.m_comps[i])
+ return true;
+ else if (m_comps[i] != rhs.m_comps[i])
+ return false;
+ }
+ return false;
+ }
+
+ inline int get_601_luma() const { return (19595U * m_comps[0] + 38470U * m_comps[1] + 7471U * m_comps[2] + 32768U) >> 16U; }
+ inline int get_709_luma() const { return (13938U * m_comps[0] + 46869U * m_comps[1] + 4729U * m_comps[2] + 32768U) >> 16U; }
+ inline int get_luma(bool luma_601) const { return luma_601 ? get_601_luma() : get_709_luma(); }
+ };
+
+ typedef std::vector<color_rgba> color_rgba_vec;
+
+ const color_rgba g_black_color(0, 0, 0, 255);
+ const color_rgba g_white_color(255, 255, 255, 255);
+
+ inline int color_distance(int r0, int g0, int b0, int r1, int g1, int b1)
+ {
+ int dr = r0 - r1, dg = g0 - g1, db = b0 - b1;
+ return dr * dr + dg * dg + db * db;
+ }
+
+ inline int color_distance(int r0, int g0, int b0, int a0, int r1, int g1, int b1, int a1)
+ {
+ int dr = r0 - r1, dg = g0 - g1, db = b0 - b1, da = a0 - a1;
+ return dr * dr + dg * dg + db * db + da * da;
+ }
+
+ inline int color_distance(const color_rgba &c0, const color_rgba &c1, bool alpha)
+ {
+ if (alpha)
+ return color_distance(c0.r, c0.g, c0.b, c0.a, c1.r, c1.g, c1.b, c1.a);
+ else
+ return color_distance(c0.r, c0.g, c0.b, c1.r, c1.g, c1.b);
+ }
+
+ // TODO: Allow user to control channel weightings.
+ inline uint32_t color_distance(bool perceptual, const color_rgba &e1, const color_rgba &e2, bool alpha)
+ {
+ if (perceptual)
+ {
+ const float l1 = e1.r * .2126f + e1.g * .715f + e1.b * .0722f;
+ const float l2 = e2.r * .2126f + e2.g * .715f + e2.b * .0722f;
+
+ const float cr1 = e1.r - l1;
+ const float cr2 = e2.r - l2;
+
+ const float cb1 = e1.b - l1;
+ const float cb2 = e2.b - l2;
+
+ const float dl = l1 - l2;
+ const float dcr = cr1 - cr2;
+ const float dcb = cb1 - cb2;
+
+ uint32_t d = static_cast<uint32_t>(32.0f*4.0f*dl*dl + 32.0f*2.0f*(.5f / (1.0f - .2126f))*(.5f / (1.0f - .2126f))*dcr*dcr + 32.0f*.25f*(.5f / (1.0f - .0722f))*(.5f / (1.0f - .0722f))*dcb*dcb);
+
+ if (alpha)
+ {
+ int da = static_cast<int>(e1.a) - static_cast<int>(e2.a);
+ d += static_cast<uint32_t>(128.0f*da*da);
+ }
+
+ return d;
+ }
+ else
+ return color_distance(e1, e2, alpha);
+ }
+
+ // String helpers
+
+ inline int string_find_right(const std::string& filename, char c)
+ {
+ size_t result = filename.find_last_of(c);
+ return (result == std::string::npos) ? -1 : (int)result;
+ }
+
+ inline std::string string_get_extension(const std::string &filename)
+ {
+ int sep = -1;
+#ifdef _WIN32
+ sep = string_find_right(filename, '\\');
+#endif
+ if (sep < 0)
+ sep = string_find_right(filename, '/');
+
+ int dot = string_find_right(filename, '.');
+ if (dot <= sep)
+ return "";
+
+ std::string result(filename);
+ result.erase(0, dot + 1);
+
+ return result;
+ }
+
+ inline bool string_remove_extension(std::string &filename)
+ {
+ int sep = -1;
+#ifdef _WIN32
+ sep = string_find_right(filename, '\\');
+#endif
+ if (sep < 0)
+ sep = string_find_right(filename, '/');
+
+ int dot = string_find_right(filename, '.');
+ if ((dot < sep) || (dot < 0))
+ return false;
+
+ filename.resize(dot);
+
+ return true;
+ }
+
+ inline std::string string_format(const char* pFmt, ...)
+ {
+ char buf[2048];
+
+ va_list args;
+ va_start(args, pFmt);
+#ifdef _WIN32
+ vsprintf_s(buf, sizeof(buf), pFmt, args);
+#else
+ vsnprintf(buf, sizeof(buf), pFmt, args);
+#endif
+ va_end(args);
+
+ return std::string(buf);
+ }
+
+ inline std::string string_tolower(const std::string& s)
+ {
+ std::string result(s);
+ for (size_t i = 0; i < result.size(); i++)
+ result[i] = (char)tolower((int)result[i]);
+ return result;
+ }
+
+ inline char *strcpy_safe(char *pDst, size_t dst_len, const char *pSrc)
+ {
+ assert(pDst && pSrc && dst_len);
+ if (!dst_len)
+ return pDst;
+
+ const size_t src_len = strlen(pSrc);
+ const size_t src_len_plus_terminator = src_len + 1;
+
+ if (src_len_plus_terminator <= dst_len)
+ memcpy(pDst, pSrc, src_len_plus_terminator);
+ else
+ {
+ if (dst_len > 1)
+ memcpy(pDst, pSrc, dst_len - 1);
+ pDst[dst_len - 1] = '\0';
+ }
+
+ return pDst;
+ }
+
+ inline bool string_ends_with(const std::string& s, char c)
+ {
+ return (s.size() != 0) && (s.back() == c);
+ }
+
+ inline bool string_split_path(const char *p, std::string *pDrive, std::string *pDir, std::string *pFilename, std::string *pExt)
+ {
+#ifdef _MSC_VER
+ char drive_buf[_MAX_DRIVE] = { 0 };
+ char dir_buf[_MAX_DIR] = { 0 };
+ char fname_buf[_MAX_FNAME] = { 0 };
+ char ext_buf[_MAX_EXT] = { 0 };
+
+ errno_t error = _splitpath_s(p,
+ pDrive ? drive_buf : NULL, pDrive ? _MAX_DRIVE : 0,
+ pDir ? dir_buf : NULL, pDir ? _MAX_DIR : 0,
+ pFilename ? fname_buf : NULL, pFilename ? _MAX_FNAME : 0,
+ pExt ? ext_buf : NULL, pExt ? _MAX_EXT : 0);
+ if (error != 0)
+ return false;
+
+ if (pDrive) *pDrive = drive_buf;
+ if (pDir) *pDir = dir_buf;
+ if (pFilename) *pFilename = fname_buf;
+ if (pExt) *pExt = ext_buf;
+ return true;
+#else
+ char dirtmp[1024], nametmp[1024];
+ strcpy_safe(dirtmp, sizeof(dirtmp), p);
+ strcpy_safe(nametmp, sizeof(nametmp), p);
+
+ if (pDrive)
+ pDrive->resize(0);
+
+ const char *pDirName = dirname(dirtmp);
+ const char* pBaseName = basename(nametmp);
+ if ((!pDirName) || (!pBaseName))
+ return false;
+
+ if (pDir)
+ {
+ *pDir = pDirName;
+ if ((pDir->size()) && (pDir->back() != '/'))
+ *pDir += "/";
+ }
+
+ if (pFilename)
+ {
+ *pFilename = pBaseName;
+ string_remove_extension(*pFilename);
+ }
+
+ if (pExt)
+ {
+ *pExt = pBaseName;
+ *pExt = string_get_extension(*pExt);
+ if (pExt->size())
+ *pExt = "." + *pExt;
+ }
+
+ return true;
+#endif
+ }
+
+ inline bool is_path_separator(char c)
+ {
+#ifdef _WIN32
+ return (c == '/') || (c == '\\');
+#else
+ return (c == '/');
+#endif
+ }
+
+ inline bool is_drive_separator(char c)
+ {
+#ifdef _WIN32
+ return (c == ':');
+#else
+ (void)c;
+ return false;
+#endif
+ }
+
+ inline void string_combine_path(std::string &dst, const char *p, const char *q)
+ {
+ std::string temp(p);
+ if (temp.size() && !is_path_separator(q[0]))
+ {
+ if (!is_path_separator(temp.back()))
+ temp.append(1, BASISU_PATH_SEPERATOR_CHAR);
+ }
+ temp += q;
+ dst.swap(temp);
+ }
+
+ inline void string_combine_path(std::string &dst, const char *p, const char *q, const char *r)
+ {
+ string_combine_path(dst, p, q);
+ string_combine_path(dst, dst.c_str(), r);
+ }
+
+ inline void string_combine_path_and_extension(std::string &dst, const char *p, const char *q, const char *r, const char *pExt)
+ {
+ string_combine_path(dst, p, q, r);
+ if ((!string_ends_with(dst, '.')) && (pExt[0]) && (pExt[0] != '.'))
+ dst.append(1, '.');
+ dst.append(pExt);
+ }
+
+ inline bool string_get_pathname(const char *p, std::string &path)
+ {
+ std::string temp_drive, temp_path;
+ if (!string_split_path(p, &temp_drive, &temp_path, NULL, NULL))
+ return false;
+ string_combine_path(path, temp_drive.c_str(), temp_path.c_str());
+ return true;
+ }
+
+ inline bool string_get_filename(const char *p, std::string &filename)
+ {
+ std::string temp_ext;
+ if (!string_split_path(p, nullptr, nullptr, &filename, &temp_ext))
+ return false;
+ filename += temp_ext;
+ return true;
+ }
+
+ class rand
+ {
+ std::mt19937 m_mt;
+
+ public:
+ rand() { }
+
+ rand(uint32_t s) { seed(s); }
+ void seed(uint32_t s) { m_mt.seed(s); }
+
+ // between [l,h]
+ int irand(int l, int h) { std::uniform_int_distribution<int> d(l, h); return d(m_mt); }
+
+ uint32_t urand32() { return static_cast<uint32_t>(irand(INT32_MIN, INT32_MAX)); }
+
+ bool bit() { return irand(0, 1) == 1; }
+
+ uint8_t byte() { return static_cast<uint8_t>(urand32()); }
+
+ // between [l,h)
+ float frand(float l, float h) { std::uniform_real_distribution<float> d(l, h); return d(m_mt); }
+
+ float gaussian(float mean, float stddev) { std::normal_distribution<float> d(mean, stddev); return d(m_mt); }
+ };
+
+ class priority_queue
+ {
+ public:
+ priority_queue() :
+ m_size(0)
+ {
+ }
+
+ void clear()
+ {
+ m_heap.clear();
+ m_size = 0;
+ }
+
+ void init(uint32_t max_entries, uint32_t first_index, float first_priority)
+ {
+ m_heap.resize(max_entries + 1);
+ m_heap[1].m_index = first_index;
+ m_heap[1].m_priority = first_priority;
+ m_size = 1;
+ }
+
+ inline uint32_t size() const { return m_size; }
+
+ inline uint32_t get_top_index() const { return m_heap[1].m_index; }
+ inline float get_top_priority() const { return m_heap[1].m_priority; }
+
+ inline void delete_top()
+ {
+ assert(m_size > 0);
+ m_heap[1] = m_heap[m_size];
+ m_size--;
+ if (m_size)
+ down_heap(1);
+ }
+
+ inline void add_heap(uint32_t index, float priority)
+ {
+ m_size++;
+
+ uint32_t k = m_size;
+
+ if (m_size >= m_heap.size())
+ m_heap.resize(m_size + 1);
+
+ for (;;)
+ {
+ uint32_t parent_index = k >> 1;
+ if ((!parent_index) || (m_heap[parent_index].m_priority > priority))
+ break;
+ m_heap[k] = m_heap[parent_index];
+ k = parent_index;
+ }
+
+ m_heap[k].m_index = index;
+ m_heap[k].m_priority = priority;
+ }
+
+ private:
+ struct entry
+ {
+ uint32_t m_index;
+ float m_priority;
+ };
+
+ std::vector<entry> m_heap;
+ uint32_t m_size;
+
+ // Push down entry at index
+ inline void down_heap(uint32_t heap_index)
+ {
+ uint32_t orig_index = m_heap[heap_index].m_index;
+ const float orig_priority = m_heap[heap_index].m_priority;
+
+ uint32_t child_index;
+ while ((child_index = (heap_index << 1)) <= m_size)
+ {
+ if ((child_index < m_size) && (m_heap[child_index].m_priority < m_heap[child_index + 1].m_priority)) ++child_index;
+ if (orig_priority > m_heap[child_index].m_priority)
+ break;
+ m_heap[heap_index] = m_heap[child_index];
+ heap_index = child_index;
+ }
+
+ m_heap[heap_index].m_index = orig_index;
+ m_heap[heap_index].m_priority = orig_priority;
+ }
+ };
+
+ // Tree structured vector quantization (TSVQ)
+
+ template <typename TrainingVectorType>
+ class tree_vector_quant
+ {
+ public:
+ typedef TrainingVectorType training_vec_type;
+ typedef std::pair<TrainingVectorType, uint64_t> training_vec_with_weight;
+ typedef std::vector< training_vec_with_weight > array_of_weighted_training_vecs;
+
+ tree_vector_quant() :
+ m_next_codebook_index(0)
+ {
+ }
+
+ void clear()
+ {
+ clear_vector(m_training_vecs);
+ clear_vector(m_nodes);
+ m_next_codebook_index = 0;
+ }
+
+ void add_training_vec(const TrainingVectorType &v, uint64_t weight) { m_training_vecs.push_back(std::make_pair(v, weight)); }
+
+ size_t get_total_training_vecs() const { return m_training_vecs.size(); }
+ const array_of_weighted_training_vecs &get_training_vecs() const { return m_training_vecs; }
+ array_of_weighted_training_vecs &get_training_vecs() { return m_training_vecs; }
+
+ void retrieve(std::vector< std::vector<uint32_t> > &codebook) const
+ {
+ for (uint32_t i = 0; i < m_nodes.size(); i++)
+ {
+ const tsvq_node &n = m_nodes[i];
+ if (!n.is_leaf())
+ continue;
+
+ codebook.resize(codebook.size() + 1);
+ codebook.back() = n.m_training_vecs;
+ }
+ }
+
+ void retrieve(std::vector<TrainingVectorType> &codebook) const
+ {
+ for (uint32_t i = 0; i < m_nodes.size(); i++)
+ {
+ const tsvq_node &n = m_nodes[i];
+ if (!n.is_leaf())
+ continue;
+
+ codebook.resize(codebook.size() + 1);
+ codebook.back() = n.m_origin;
+ }
+ }
+
+ void retrieve(uint32_t max_clusters, std::vector<uint_vec> &codebook) const
+ {
+ uint_vec node_stack;
+ node_stack.reserve(512);
+
+ codebook.resize(0);
+ codebook.reserve(max_clusters);
+
+ uint32_t node_index = 0;
+
+ while (true)
+ {
+ const tsvq_node& cur = m_nodes[node_index];
+
+ if (cur.is_leaf() || ((2 + cur.m_codebook_index) > (int)max_clusters))
+ {
+ codebook.resize(codebook.size() + 1);
+ codebook.back() = cur.m_training_vecs;
+
+ if (node_stack.empty())
+ break;
+
+ node_index = node_stack.back();
+ node_stack.pop_back();
+ continue;
+ }
+
+ node_stack.push_back(cur.m_right_index);
+ node_index = cur.m_left_index;
+ }
+ }
+
+ bool generate(uint32_t max_size)
+ {
+ if (!m_training_vecs.size())
+ return false;
+
+ m_next_codebook_index = 0;
+
+ clear_vector(m_nodes);
+ m_nodes.reserve(max_size * 2 + 1);
+
+ m_nodes.push_back(prepare_root());
+
+ priority_queue var_heap;
+ var_heap.init(max_size, 0, m_nodes[0].m_var);
+
+ std::vector<uint32_t> l_children, r_children;
+
+ // Now split the worst nodes
+ l_children.reserve(m_training_vecs.size() + 1);
+ r_children.reserve(m_training_vecs.size() + 1);
+
+ uint32_t total_leaf_nodes = 1;
+
+ while ((var_heap.size()) && (total_leaf_nodes < max_size))
+ {
+ const uint32_t node_index = var_heap.get_top_index();
+ const tsvq_node &node = m_nodes[node_index];
+
+ assert(node.m_var == var_heap.get_top_priority());
+ assert(node.is_leaf());
+
+ var_heap.delete_top();
+
+ if (node.m_training_vecs.size() > 1)
+ {
+ if (split_node(node_index, var_heap, l_children, r_children))
+ {
+ // This removes one leaf node (making an internal node) and replaces it with two new leaves, so +1 total.
+ total_leaf_nodes += 1;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private:
+ class tsvq_node
+ {
+ public:
+ inline tsvq_node() : m_weight(0), m_origin(cZero), m_left_index(-1), m_right_index(-1), m_codebook_index(-1) { }
+
+ // vecs is erased
+ inline void set(const TrainingVectorType &org, uint64_t weight, float var, std::vector<uint32_t> &vecs) { m_origin = org; m_weight = weight; m_var = var; m_training_vecs.swap(vecs); }
+
+ inline bool is_leaf() const { return m_left_index < 0; }
+
+ float m_var;
+ uint64_t m_weight;
+ TrainingVectorType m_origin;
+ int32_t m_left_index, m_right_index;
+ std::vector<uint32_t> m_training_vecs;
+ int m_codebook_index;
+ };
+
+ typedef std::vector<tsvq_node> tsvq_node_vec;
+ tsvq_node_vec m_nodes;
+
+ array_of_weighted_training_vecs m_training_vecs;
+
+ uint32_t m_next_codebook_index;
+
+ tsvq_node prepare_root() const
+ {
+ double ttsum = 0.0f;
+
+ // Prepare root node containing all training vectors
+ tsvq_node root;
+ root.m_training_vecs.reserve(m_training_vecs.size());
+
+ for (uint32_t i = 0; i < m_training_vecs.size(); i++)
+ {
+ const TrainingVectorType &v = m_training_vecs[i].first;
+ const uint64_t weight = m_training_vecs[i].second;
+
+ root.m_training_vecs.push_back(i);
+
+ root.m_origin += (v * static_cast<float>(weight));
+ root.m_weight += weight;
+
+ ttsum += v.dot(v) * weight;
+ }
+
+ root.m_var = static_cast<float>(ttsum - (root.m_origin.dot(root.m_origin) / root.m_weight));
+
+ root.m_origin *= (1.0f / root.m_weight);
+
+ return root;
+ }
+
+ bool split_node(uint32_t node_index, priority_queue &var_heap, std::vector<uint32_t> &l_children, std::vector<uint32_t> &r_children)
+ {
+ TrainingVectorType l_child_org, r_child_org;
+ uint64_t l_weight = 0, r_weight = 0;
+ float l_var = 0.0f, r_var = 0.0f;
+
+ // Compute initial left/right child origins
+ if (!prep_split(m_nodes[node_index], l_child_org, r_child_org))
+ return false;
+
+ // Use k-means iterations to refine these children vectors
+ if (!refine_split(m_nodes[node_index], l_child_org, l_weight, l_var, l_children, r_child_org, r_weight, r_var, r_children))
+ return false;
+
+ // Create children
+ const uint32_t l_child_index = (uint32_t)m_nodes.size(), r_child_index = (uint32_t)m_nodes.size() + 1;
+
+ m_nodes[node_index].m_left_index = l_child_index;
+ m_nodes[node_index].m_right_index = r_child_index;
+
+ m_nodes[node_index].m_codebook_index = m_next_codebook_index;
+ m_next_codebook_index++;
+
+ m_nodes.resize(m_nodes.size() + 2);
+
+ tsvq_node &l_child = m_nodes[l_child_index], &r_child = m_nodes[r_child_index];
+
+ l_child.set(l_child_org, l_weight, l_var, l_children);
+ r_child.set(r_child_org, r_weight, r_var, r_children);
+
+ if ((l_child.m_var <= 0.0f) && (l_child.m_training_vecs.size() > 1))
+ {
+ TrainingVectorType v(m_training_vecs[l_child.m_training_vecs[0]].first);
+
+ for (uint32_t i = 1; i < l_child.m_training_vecs.size(); i++)
+ {
+ if (!(v == m_training_vecs[l_child.m_training_vecs[i]].first))
+ {
+ l_child.m_var = 1e-4f;
+ break;
+ }
+ }
+ }
+
+ if ((r_child.m_var <= 0.0f) && (r_child.m_training_vecs.size() > 1))
+ {
+ TrainingVectorType v(m_training_vecs[r_child.m_training_vecs[0]].first);
+
+ for (uint32_t i = 1; i < r_child.m_training_vecs.size(); i++)
+ {
+ if (!(v == m_training_vecs[r_child.m_training_vecs[i]].first))
+ {
+ r_child.m_var = 1e-4f;
+ break;
+ }
+ }
+ }
+
+ if ((l_child.m_var > 0.0f) && (l_child.m_training_vecs.size() > 1))
+ var_heap.add_heap(l_child_index, l_child.m_var);
+
+ if ((r_child.m_var > 0.0f) && (r_child.m_training_vecs.size() > 1))
+ var_heap.add_heap(r_child_index, r_child.m_var);
+
+ return true;
+ }
+
+ TrainingVectorType compute_split_axis(const tsvq_node &node) const
+ {
+ const uint32_t N = TrainingVectorType::num_elements;
+
+ matrix<N, N, float> cmatrix(cZero);
+
+ // Compute covariance matrix from weighted input vectors
+ for (uint32_t i = 0; i < node.m_training_vecs.size(); i++)
+ {
+ const TrainingVectorType v(m_training_vecs[node.m_training_vecs[i]].first - node.m_origin);
+ const TrainingVectorType w(static_cast<float>(m_training_vecs[node.m_training_vecs[i]].second) * v);
+
+ for (uint32_t x = 0; x < N; x++)
+ for (uint32_t y = x; y < N; y++)
+ cmatrix[x][y] = cmatrix[x][y] + v[x] * w[y];
+ }
+
+ const float renorm_scale = 1.0f / node.m_weight;
+
+ for (uint32_t x = 0; x < N; x++)
+ for (uint32_t y = x; y < N; y++)
+ cmatrix[x][y] *= renorm_scale;
+
+ // Diagonal flip
+ for (uint32_t x = 0; x < (N - 1); x++)
+ for (uint32_t y = x + 1; y < N; y++)
+ cmatrix[y][x] = cmatrix[x][y];
+
+ return compute_pca_from_covar<N, TrainingVectorType>(cmatrix);
+ }
+
+ bool prep_split(const tsvq_node &node, TrainingVectorType &l_child_result, TrainingVectorType &r_child_result) const
+ {
+ const uint32_t N = TrainingVectorType::num_elements;
+
+ if (2 == node.m_training_vecs.size())
+ {
+ l_child_result = m_training_vecs[node.m_training_vecs[0]].first;
+ r_child_result = m_training_vecs[node.m_training_vecs[1]].first;
+ return true;
+ }
+
+ TrainingVectorType axis(compute_split_axis(node)), l_child(0.0f), r_child(0.0f);
+ double l_weight = 0.0f, r_weight = 0.0f;
+
+ // Compute initial left/right children
+ for (uint32_t i = 0; i < node.m_training_vecs.size(); i++)
+ {
+ const float weight = (float)m_training_vecs[node.m_training_vecs[i]].second;
+
+ const TrainingVectorType &v = m_training_vecs[node.m_training_vecs[i]].first;
+
+ double t = (v - node.m_origin).dot(axis);
+ if (t >= 0.0f)
+ {
+ r_child += v * weight;
+ r_weight += weight;
+ }
+ else
+ {
+ l_child += v * weight;
+ l_weight += weight;
+ }
+ }
+
+ if ((l_weight > 0.0f) && (r_weight > 0.0f))
+ {
+ l_child_result = l_child * static_cast<float>(1.0f / l_weight);
+ r_child_result = r_child * static_cast<float>(1.0f / r_weight);
+ }
+ else
+ {
+ TrainingVectorType l(1e+20f);
+ TrainingVectorType h(-1e+20f);
+ for (uint32_t i = 0; i < node.m_training_vecs.size(); i++)
+ {
+ const TrainingVectorType& v = m_training_vecs[node.m_training_vecs[i]].first;
+
+ l = TrainingVectorType::component_min(l, v);
+ h = TrainingVectorType::component_max(h, v);
+ }
+
+ TrainingVectorType r(h - l);
+
+ float largest_axis_v = 0.0f;
+ int largest_axis_index = -1;
+ for (uint32_t i = 0; i < TrainingVectorType::num_elements; i++)
+ {
+ if (r[i] > largest_axis_v)
+ {
+ largest_axis_v = r[i];
+ largest_axis_index = i;
+ }
+ }
+
+ if (largest_axis_index < 0)
+ return false;
+
+ std::vector<float> keys(node.m_training_vecs.size());
+ for (uint32_t i = 0; i < node.m_training_vecs.size(); i++)
+ keys[i] = m_training_vecs[node.m_training_vecs[i]].first[largest_axis_index];
+
+ uint_vec indices(node.m_training_vecs.size());
+ indirect_sort((uint32_t)node.m_training_vecs.size(), &indices[0], &keys[0]);
+
+ l_child.set_zero();
+ l_weight = 0;
+
+ r_child.set_zero();
+ r_weight = 0;
+
+ const uint32_t half_index = (uint32_t)node.m_training_vecs.size() / 2;
+ for (uint32_t i = 0; i < node.m_training_vecs.size(); i++)
+ {
+ const float weight = (float)m_training_vecs[node.m_training_vecs[i]].second;
+
+ const TrainingVectorType& v = m_training_vecs[node.m_training_vecs[i]].first;
+
+ if (i < half_index)
+ {
+ l_child += v * weight;
+ l_weight += weight;
+ }
+ else
+ {
+ r_child += v * weight;
+ r_weight += weight;
+ }
+ }
+
+ if ((l_weight > 0.0f) && (r_weight > 0.0f))
+ {
+ l_child_result = l_child * static_cast<float>(1.0f / l_weight);
+ r_child_result = r_child * static_cast<float>(1.0f / r_weight);
+ }
+ else
+ {
+ l_child_result = l;
+ r_child_result = h;
+ }
+ }
+
+ return true;
+ }
+
+ bool refine_split(const tsvq_node &node,
+ TrainingVectorType &l_child, uint64_t &l_weight, float &l_var, std::vector<uint32_t> &l_children,
+ TrainingVectorType &r_child, uint64_t &r_weight, float &r_var, std::vector<uint32_t> &r_children) const
+ {
+ l_children.reserve(node.m_training_vecs.size());
+ r_children.reserve(node.m_training_vecs.size());
+
+ float prev_total_variance = 1e+10f;
+
+ // Refine left/right children locations using k-means iterations
+ const uint32_t cMaxIters = 6;
+ for (uint32_t iter = 0; iter < cMaxIters; iter++)
+ {
+ l_children.resize(0);
+ r_children.resize(0);
+
+ TrainingVectorType new_l_child(cZero), new_r_child(cZero);
+
+ double l_ttsum = 0.0f, r_ttsum = 0.0f;
+
+ l_weight = 0;
+ r_weight = 0;
+
+ for (uint32_t i = 0; i < node.m_training_vecs.size(); i++)
+ {
+ const TrainingVectorType &v = m_training_vecs[node.m_training_vecs[i]].first;
+ const uint64_t weight = m_training_vecs[node.m_training_vecs[i]].second;
+
+ double left_dist2 = l_child.squared_distance_d(v), right_dist2 = r_child.squared_distance_d(v);
+
+ if (left_dist2 >= right_dist2)
+ {
+ new_r_child += (v * static_cast<float>(weight));
+ r_weight += weight;
+
+ r_ttsum += weight * v.dot(v);
+ r_children.push_back(node.m_training_vecs[i]);
+ }
+ else
+ {
+ new_l_child += (v * static_cast<float>(weight));
+ l_weight += weight;
+
+ l_ttsum += weight * v.dot(v);
+ l_children.push_back(node.m_training_vecs[i]);
+ }
+ }
+
+ if ((!l_weight) || (!r_weight))
+ {
+ TrainingVectorType firstVec;
+ for (uint32_t i = 0; i < node.m_training_vecs.size(); i++)
+ {
+ const TrainingVectorType& v = m_training_vecs[node.m_training_vecs[i]].first;
+ const uint64_t weight = m_training_vecs[node.m_training_vecs[i]].second;
+
+ if ((!i) || (v == firstVec))
+ {
+ firstVec = v;
+
+ new_r_child += (v * static_cast<float>(weight));
+ r_weight += weight;
+
+ r_ttsum += weight * v.dot(v);
+ r_children.push_back(node.m_training_vecs[i]);
+ }
+ else
+ {
+ new_l_child += (v * static_cast<float>(weight));
+ l_weight += weight;
+
+ l_ttsum += weight * v.dot(v);
+ l_children.push_back(node.m_training_vecs[i]);
+ }
+ }
+
+ if (!l_weight)
+ return false;
+ }
+
+ l_var = static_cast<float>(l_ttsum - (new_l_child.dot(new_l_child) / l_weight));
+ r_var = static_cast<float>(r_ttsum - (new_r_child.dot(new_r_child) / r_weight));
+
+ new_l_child *= (1.0f / l_weight);
+ new_r_child *= (1.0f / r_weight);
+
+ l_child = new_l_child;
+ r_child = new_r_child;
+
+ float total_var = l_var + r_var;
+ const float cGiveupVariance = .00001f;
+ if (total_var < cGiveupVariance)
+ break;
+
+ // Check to see if the variance has settled
+ const float cVarianceDeltaThresh = .00125f;
+ if (((prev_total_variance - total_var) / total_var) < cVarianceDeltaThresh)
+ break;
+
+ prev_total_variance = total_var;
+ }
+
+ return true;
+ }
+ };
+
+ struct weighted_block_group
+ {
+ uint64_t m_total_weight;
+ uint_vec m_indices;
+ };
+
+ template<typename Quantizer>
+ bool generate_hierarchical_codebook_threaded_internal(Quantizer& q,
+ uint32_t max_codebook_size, uint32_t max_parent_codebook_size,
+ std::vector<uint_vec>& codebook,
+ std::vector<uint_vec>& parent_codebook,
+ uint32_t max_threads, bool limit_clusterizers, job_pool *pJob_pool)
+ {
+ codebook.resize(0);
+ parent_codebook.resize(0);
+
+ if ((max_threads <= 1) || (q.get_training_vecs().size() < 256) || (max_codebook_size < max_threads * 16))
+ {
+ if (!q.generate(max_codebook_size))
+ return false;
+
+ q.retrieve(codebook);
+
+ if (max_parent_codebook_size)
+ q.retrieve(max_parent_codebook_size, parent_codebook);
+
+ return true;
+ }
+
+ const uint32_t cMaxThreads = 16;
+ if (max_threads > cMaxThreads)
+ max_threads = cMaxThreads;
+
+ if (!q.generate(max_threads))
+ return false;
+
+ std::vector<uint_vec> initial_codebook;
+
+ q.retrieve(initial_codebook);
+
+ if (initial_codebook.size() < max_threads)
+ {
+ codebook = initial_codebook;
+
+ if (max_parent_codebook_size)
+ q.retrieve(max_parent_codebook_size, parent_codebook);
+
+ return true;
+ }
+
+ Quantizer quantizers[cMaxThreads];
+
+ bool success_flags[cMaxThreads];
+ clear_obj(success_flags);
+
+ std::vector<uint_vec> local_clusters[cMaxThreads];
+ std::vector<uint_vec> local_parent_clusters[cMaxThreads];
+
+ for (uint32_t thread_iter = 0; thread_iter < max_threads; thread_iter++)
+ {
+ pJob_pool->add_job( [thread_iter, &local_clusters, &local_parent_clusters, &success_flags, &quantizers, &initial_codebook, &q, &limit_clusterizers, &max_codebook_size, &max_threads, &max_parent_codebook_size] {
+
+ Quantizer& lq = quantizers[thread_iter];
+ uint_vec& cluster_indices = initial_codebook[thread_iter];
+
+ uint_vec local_to_global(cluster_indices.size());
+
+ for (uint32_t i = 0; i < cluster_indices.size(); i++)
+ {
+ const uint32_t global_training_vec_index = cluster_indices[i];
+ local_to_global[i] = global_training_vec_index;
+
+ lq.add_training_vec(q.get_training_vecs()[global_training_vec_index].first, q.get_training_vecs()[global_training_vec_index].second);
+ }
+
+ const uint32_t max_clusters = limit_clusterizers ? ((max_codebook_size + max_threads - 1) / max_threads) : (uint32_t)lq.get_total_training_vecs();
+
+ success_flags[thread_iter] = lq.generate(max_clusters);
+
+ if (success_flags[thread_iter])
+ {
+ lq.retrieve(local_clusters[thread_iter]);
+
+ for (uint32_t i = 0; i < local_clusters[thread_iter].size(); i++)
+ {
+ for (uint32_t j = 0; j < local_clusters[thread_iter][i].size(); j++)
+ local_clusters[thread_iter][i][j] = local_to_global[local_clusters[thread_iter][i][j]];
+ }
+
+ if (max_parent_codebook_size)
+ {
+ lq.retrieve((max_parent_codebook_size + max_threads - 1) / max_threads, local_parent_clusters[thread_iter]);
+
+ for (uint32_t i = 0; i < local_parent_clusters[thread_iter].size(); i++)
+ {
+ for (uint32_t j = 0; j < local_parent_clusters[thread_iter][i].size(); j++)
+ local_parent_clusters[thread_iter][i][j] = local_to_global[local_parent_clusters[thread_iter][i][j]];
+ }
+ }
+ }
+
+ } );
+
+ } // thread_iter
+
+ pJob_pool->wait_for_all();
+
+ uint32_t total_clusters = 0, total_parent_clusters = 0;
+
+ for (int thread_iter = 0; thread_iter < (int)max_threads; thread_iter++)
+ {
+ if (!success_flags[thread_iter])
+ return false;
+ total_clusters += (uint32_t)local_clusters[thread_iter].size();
+ total_parent_clusters += (uint32_t)local_parent_clusters[thread_iter].size();
+ }
+
+ codebook.reserve(total_clusters);
+ parent_codebook.reserve(total_parent_clusters);
+
+ for (uint32_t thread_iter = 0; thread_iter < max_threads; thread_iter++)
+ {
+ for (uint32_t j = 0; j < local_clusters[thread_iter].size(); j++)
+ {
+ codebook.resize(codebook.size() + 1);
+ codebook.back().swap(local_clusters[thread_iter][j]);
+ }
+
+ for (uint32_t j = 0; j < local_parent_clusters[thread_iter].size(); j++)
+ {
+ parent_codebook.resize(parent_codebook.size() + 1);
+ parent_codebook.back().swap(local_parent_clusters[thread_iter][j]);
+ }
+ }
+
+ return true;
+ }
+
+ template<typename Quantizer>
+ bool generate_hierarchical_codebook_threaded(Quantizer& q,
+ uint32_t max_codebook_size, uint32_t max_parent_codebook_size,
+ std::vector<uint_vec>& codebook,
+ std::vector<uint_vec>& parent_codebook,
+ uint32_t max_threads, job_pool *pJob_pool)
+ {
+ typedef bit_hasher<typename Quantizer::training_vec_type> training_vec_bit_hasher;
+ typedef std::unordered_map < typename Quantizer::training_vec_type, weighted_block_group,
+ training_vec_bit_hasher> group_hash;
+
+ group_hash unique_vecs;
+
+ weighted_block_group g;
+ g.m_indices.resize(1);
+
+ for (uint32_t i = 0; i < q.get_training_vecs().size(); i++)
+ {
+ g.m_total_weight = q.get_training_vecs()[i].second;
+ g.m_indices[0] = i;
+
+ auto ins_res = unique_vecs.insert(std::make_pair(q.get_training_vecs()[i].first, g));
+
+ if (!ins_res.second)
+ {
+ (ins_res.first)->second.m_total_weight += g.m_total_weight;
+ (ins_res.first)->second.m_indices.push_back(i);
+ }
+ }
+
+ debug_printf("generate_hierarchical_codebook_threaded: %u training vectors, %u unique training vectors\n", q.get_total_training_vecs(), (uint32_t)unique_vecs.size());
+
+ Quantizer group_quant;
+ typedef typename group_hash::const_iterator group_hash_const_iter;
+ std::vector<group_hash_const_iter> unique_vec_iters;
+ unique_vec_iters.reserve(unique_vecs.size());
+
+ for (auto iter = unique_vecs.begin(); iter != unique_vecs.end(); ++iter)
+ {
+ group_quant.add_training_vec(iter->first, iter->second.m_total_weight);
+ unique_vec_iters.push_back(iter);
+ }
+
+ bool limit_clusterizers = true;
+ if (unique_vecs.size() <= max_codebook_size)
+ limit_clusterizers = false;
+
+ debug_printf("Limit clusterizers: %u\n", limit_clusterizers);
+
+ std::vector<uint_vec> group_codebook, group_parent_codebook;
+ bool status = generate_hierarchical_codebook_threaded_internal(group_quant,
+ max_codebook_size, max_parent_codebook_size,
+ group_codebook,
+ group_parent_codebook,
+ (unique_vecs.size() < 65536*4) ? 1 : max_threads, limit_clusterizers, pJob_pool);
+
+ if (!status)
+ return false;
+
+ codebook.resize(0);
+ for (uint32_t i = 0; i < group_codebook.size(); i++)
+ {
+ codebook.resize(codebook.size() + 1);
+
+ for (uint32_t j = 0; j < group_codebook[i].size(); j++)
+ {
+ const uint32_t group_index = group_codebook[i][j];
+
+ typename group_hash::const_iterator group_iter = unique_vec_iters[group_index];
+ const uint_vec& training_vec_indices = group_iter->second.m_indices;
+
+ append_vector(codebook.back(), training_vec_indices);
+ }
+ }
+
+ parent_codebook.resize(0);
+ for (uint32_t i = 0; i < group_parent_codebook.size(); i++)
+ {
+ parent_codebook.resize(parent_codebook.size() + 1);
+
+ for (uint32_t j = 0; j < group_parent_codebook[i].size(); j++)
+ {
+ const uint32_t group_index = group_parent_codebook[i][j];
+
+ typename group_hash::const_iterator group_iter = unique_vec_iters[group_index];
+ const uint_vec& training_vec_indices = group_iter->second.m_indices;
+
+ append_vector(parent_codebook.back(), training_vec_indices);
+ }
+ }
+
+ return true;
+ }
+
+ // Canonical Huffman coding
+
+ class histogram
+ {
+ std::vector<uint32_t> m_hist;
+
+ public:
+ histogram(uint32_t size = 0) { init(size); }
+
+ void clear()
+ {
+ clear_vector(m_hist);
+ }
+
+ void init(uint32_t size)
+ {
+ m_hist.resize(0);
+ m_hist.resize(size);
+ }
+
+ inline uint32_t size() const { return static_cast<uint32_t>(m_hist.size()); }
+
+ inline const uint32_t &operator[] (uint32_t index) const
+ {
+ return m_hist[index];
+ }
+
+ inline uint32_t &operator[] (uint32_t index)
+ {
+ return m_hist[index];
+ }
+
+ inline void inc(uint32_t index)
+ {
+ m_hist[index]++;
+ }
+
+ uint64_t get_total() const
+ {
+ uint64_t total = 0;
+ for (uint32_t i = 0; i < m_hist.size(); ++i)
+ total += m_hist[i];
+ return total;
+ }
+
+ double get_entropy() const
+ {
+ double total = static_cast<double>(get_total());
+ if (total == 0.0f)
+ return 0.0f;
+
+ const double inv_total = 1.0f / total;
+ const double neg_inv_log2 = -1.0f / log(2.0f);
+
+ double e = 0.0f;
+ for (uint32_t i = 0; i < m_hist.size(); i++)
+ if (m_hist[i])
+ e += log(m_hist[i] * inv_total) * neg_inv_log2 * static_cast<double>(m_hist[i]);
+
+ return e;
+ }
+ };
+
+ struct sym_freq
+ {
+ uint16_t m_key, m_sym_index;
+ };
+
+ sym_freq *canonical_huffman_radix_sort_syms(uint32_t num_syms, sym_freq *pSyms0, sym_freq *pSyms1);
+ void canonical_huffman_calculate_minimum_redundancy(sym_freq *A, int num_syms);
+ void canonical_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size);
+
+ class huffman_encoding_table
+ {
+ public:
+ huffman_encoding_table()
+ {
+ }
+
+ void clear()
+ {
+ clear_vector(m_codes);
+ clear_vector(m_code_sizes);
+ }
+
+ bool init(const histogram &h, uint32_t max_code_size = cHuffmanMaxSupportedCodeSize)
+ {
+ return init(h.size(), &h[0], max_code_size);
+ }
+
+ bool init(uint32_t num_syms, const uint16_t *pFreq, uint32_t max_code_size);
+ bool init(uint32_t num_syms, const uint32_t *pSym_freq, uint32_t max_code_size);
+
+ inline const uint16_vec &get_codes() const { return m_codes; }
+ inline const uint8_vec &get_code_sizes() const { return m_code_sizes; }
+
+ uint32_t get_total_used_codes() const
+ {
+ for (int i = static_cast<int>(m_code_sizes.size()) - 1; i >= 0; i--)
+ if (m_code_sizes[i])
+ return i + 1;
+ return 0;
+ }
+
+ private:
+ uint16_vec m_codes;
+ uint8_vec m_code_sizes;
+ };
+
+ class bitwise_coder
+ {
+ public:
+ bitwise_coder() :
+ m_bit_buffer(0),
+ m_bit_buffer_size(0),
+ m_total_bits(0)
+ {
+ }
+
+ inline void clear()
+ {
+ clear_vector(m_bytes);
+ m_bit_buffer = 0;
+ m_bit_buffer_size = 0;
+ m_total_bits = 0;
+ }
+
+ inline const uint8_vec &get_bytes() const { return m_bytes; }
+
+ inline uint64_t get_total_bits() const { return m_total_bits; }
+ inline void clear_total_bits() { m_total_bits = 0; }
+
+ inline void init(uint32_t reserve_size = 1024)
+ {
+ m_bytes.reserve(reserve_size);
+ m_bytes.resize(0);
+
+ m_bit_buffer = 0;
+ m_bit_buffer_size = 0;
+ m_total_bits = 0;
+ }
+
+ inline uint32_t flush()
+ {
+ if (m_bit_buffer_size)
+ {
+ m_total_bits += 8;
+ append_byte(static_cast<uint8_t>(m_bit_buffer));
+
+ m_bit_buffer = 0;
+ m_bit_buffer_size = 0;
+
+ return 8;
+ }
+
+ return 0;
+ }
+
+ inline uint32_t put_bits(uint32_t bits, uint32_t num_bits)
+ {
+ assert(num_bits <= 32);
+ assert(bits < (1ULL << num_bits));
+
+ if (!num_bits)
+ return 0;
+
+ m_total_bits += num_bits;
+
+ uint64_t v = (static_cast<uint64_t>(bits) << m_bit_buffer_size) | m_bit_buffer;
+ m_bit_buffer_size += num_bits;
+
+ while (m_bit_buffer_size >= 8)
+ {
+ append_byte(static_cast<uint8_t>(v));
+ v >>= 8;
+ m_bit_buffer_size -= 8;
+ }
+
+ m_bit_buffer = static_cast<uint8_t>(v);
+ return num_bits;
+ }
+
+ inline uint32_t put_code(uint32_t sym, const huffman_encoding_table &tab)
+ {
+ uint32_t code = tab.get_codes()[sym];
+ uint32_t code_size = tab.get_code_sizes()[sym];
+ assert(code_size >= 1);
+ put_bits(code, code_size);
+ return code_size;
+ }
+
+ inline uint32_t put_truncated_binary(uint32_t v, uint32_t n)
+ {
+ assert((n >= 2) && (v < n));
+
+ uint32_t k = floor_log2i(n);
+ uint32_t u = (1 << (k + 1)) - n;
+
+ if (v < u)
+ return put_bits(v, k);
+
+ uint32_t x = v + u;
+ assert((x >> 1) >= u);
+
+ put_bits(x >> 1, k);
+ put_bits(x & 1, 1);
+ return k + 1;
+ }
+
+ inline uint32_t put_rice(uint32_t v, uint32_t m)
+ {
+ assert(m);
+
+ const uint64_t start_bits = m_total_bits;
+
+ uint32_t q = v >> m, r = v & ((1 << m) - 1);
+
+ // rice coding sanity check
+ assert(q <= 64);
+
+ for (; q > 16; q -= 16)
+ put_bits(0xFFFF, 16);
+
+ put_bits((1 << q) - 1, q);
+ put_bits(r << 1, m + 1);
+
+ return (uint32_t)(m_total_bits - start_bits);
+ }
+
+ inline uint32_t put_vlc(uint32_t v, uint32_t chunk_bits)
+ {
+ assert(chunk_bits);
+
+ const uint32_t chunk_size = 1 << chunk_bits;
+ const uint32_t chunk_mask = chunk_size - 1;
+
+ uint32_t total_bits = 0;
+
+ for ( ; ; )
+ {
+ uint32_t next_v = v >> chunk_bits;
+
+ total_bits += put_bits((v & chunk_mask) | (next_v ? chunk_size : 0), chunk_bits + 1);
+ if (!next_v)
+ break;
+
+ v = next_v;
+ }
+
+ return total_bits;
+ }
+
+ uint32_t emit_huffman_table(const huffman_encoding_table &tab);
+
+ private:
+ uint8_vec m_bytes;
+ uint32_t m_bit_buffer, m_bit_buffer_size;
+ uint64_t m_total_bits;
+
+ void append_byte(uint8_t c)
+ {
+ m_bytes.resize(m_bytes.size() + 1);
+ m_bytes.back() = c;
+ }
+
+ static void end_nonzero_run(uint16_vec &syms, uint32_t &run_size, uint32_t len);
+ static void end_zero_run(uint16_vec &syms, uint32_t &run_size);
+ };
+
+ class huff2D
+ {
+ public:
+ huff2D() { }
+ huff2D(uint32_t bits_per_sym, uint32_t total_syms_per_group) { init(bits_per_sym, total_syms_per_group); }
+
+ inline const histogram &get_histogram() const { return m_histogram; }
+ inline const huffman_encoding_table &get_encoding_table() const { return m_encoding_table; }
+
+ inline void init(uint32_t bits_per_sym, uint32_t total_syms_per_group)
+ {
+ assert((bits_per_sym * total_syms_per_group) <= 16 && total_syms_per_group >= 1 && bits_per_sym >= 1);
+
+ m_bits_per_sym = bits_per_sym;
+ m_total_syms_per_group = total_syms_per_group;
+ m_cur_sym_bits = 0;
+ m_cur_num_syms = 0;
+ m_decode_syms_remaining = 0;
+ m_next_decoder_group_index = 0;
+
+ m_histogram.init(1 << (bits_per_sym * total_syms_per_group));
+ }
+
+ inline void clear()
+ {
+ m_group_bits.clear();
+
+ m_cur_sym_bits = 0;
+ m_cur_num_syms = 0;
+ m_decode_syms_remaining = 0;
+ m_next_decoder_group_index = 0;
+ }
+
+ inline void emit(uint32_t sym)
+ {
+ m_cur_sym_bits |= (sym << (m_cur_num_syms * m_bits_per_sym));
+ m_cur_num_syms++;
+
+ if (m_cur_num_syms == m_total_syms_per_group)
+ flush();
+ }
+
+ inline void flush()
+ {
+ if (m_cur_num_syms)
+ {
+ m_group_bits.push_back(m_cur_sym_bits);
+ m_histogram.inc(m_cur_sym_bits);
+
+ m_cur_sym_bits = 0;
+ m_cur_num_syms = 0;
+ }
+ }
+
+ inline bool start_encoding(uint32_t code_size_limit = 16)
+ {
+ flush();
+
+ if (!m_encoding_table.init(m_histogram, code_size_limit))
+ return false;
+
+ m_decode_syms_remaining = 0;
+ m_next_decoder_group_index = 0;
+
+ return true;
+ }
+
+ inline uint32_t emit_next_sym(bitwise_coder &c)
+ {
+ uint32_t bits = 0;
+
+ if (!m_decode_syms_remaining)
+ {
+ bits = c.put_code(m_group_bits[m_next_decoder_group_index++], m_encoding_table);
+ m_decode_syms_remaining = m_total_syms_per_group;
+ }
+
+ m_decode_syms_remaining--;
+ return bits;
+ }
+
+ inline void emit_flush()
+ {
+ m_decode_syms_remaining = 0;
+ }
+
+ private:
+ uint_vec m_group_bits;
+ huffman_encoding_table m_encoding_table;
+ histogram m_histogram;
+ uint32_t m_bits_per_sym, m_total_syms_per_group, m_cur_sym_bits, m_cur_num_syms, m_next_decoder_group_index, m_decode_syms_remaining;
+ };
+
+ bool huffman_test(int rand_seed);
+
+ // VQ index reordering
+
+ class palette_index_reorderer
+ {
+ public:
+ palette_index_reorderer()
+ {
+ }
+
+ void clear()
+ {
+ clear_vector(m_hist);
+ clear_vector(m_total_count_to_picked);
+ clear_vector(m_entries_picked);
+ clear_vector(m_entries_to_do);
+ clear_vector(m_remap_table);
+ }
+
+ // returns [0,1] distance of entry i to entry j
+ typedef float(*pEntry_dist_func)(uint32_t i, uint32_t j, void *pCtx);
+
+ void init(uint32_t num_indices, const uint32_t *pIndices, uint32_t num_syms, pEntry_dist_func pDist_func, void *pCtx, float dist_func_weight);
+
+ // Table remaps old to new symbol indices
+ inline const uint_vec &get_remap_table() const { return m_remap_table; }
+
+ private:
+ uint_vec m_hist, m_total_count_to_picked, m_entries_picked, m_entries_to_do, m_remap_table;
+
+ inline uint32_t get_hist(int i, int j, int n) const { return (i > j) ? m_hist[j * n + i] : m_hist[i * n + j]; }
+ inline void inc_hist(int i, int j, int n) { if ((i != j) && (i < j) && (i != -1) && (j != -1)) { assert(((uint32_t)i < (uint32_t)n) && ((uint32_t)j < (uint32_t)n)); m_hist[i * n + j]++; } }
+
+ void prepare_hist(uint32_t num_syms, uint32_t num_indices, const uint32_t *pIndices);
+ void find_initial(uint32_t num_syms);
+ void find_next_entry(uint32_t &best_entry, double &best_count, pEntry_dist_func pDist_func, void *pCtx, float dist_func_weight);
+ float pick_side(uint32_t num_syms, uint32_t entry_to_move, pEntry_dist_func pDist_func, void *pCtx, float dist_func_weight);
+ };
+
+ // Simple 32-bit 2D image class
+
+ class image
+ {
+ public:
+ image() :
+ m_width(0), m_height(0), m_pitch(0)
+ {
+ }
+
+ image(uint32_t w, uint32_t h, uint32_t p = UINT32_MAX) :
+ m_width(0), m_height(0), m_pitch(0)
+ {
+ resize(w, h, p);
+ }
+
+ image(const image &other) :
+ m_width(0), m_height(0), m_pitch(0)
+ {
+ *this = other;
+ }
+
+ image &swap(image &other)
+ {
+ std::swap(m_width, other.m_width);
+ std::swap(m_height, other.m_height);
+ std::swap(m_pitch, other.m_pitch);
+ m_pixels.swap(other.m_pixels);
+ return *this;
+ }
+
+ image &operator= (const image &rhs)
+ {
+ if (this != &rhs)
+ {
+ m_width = rhs.m_width;
+ m_height = rhs.m_height;
+ m_pitch = rhs.m_pitch;
+ m_pixels = rhs.m_pixels;
+ }
+ return *this;
+ }
+
+ image &clear()
+ {
+ m_width = 0;
+ m_height = 0;
+ m_pitch = 0;
+ clear_vector(m_pixels);
+ return *this;
+ }
+
+ image &resize(uint32_t w, uint32_t h, uint32_t p = UINT32_MAX, const color_rgba& background = g_black_color)
+ {
+ return crop(w, h, p, background);
+ }
+
+ image &set_all(const color_rgba &c)
+ {
+ for (uint32_t i = 0; i < m_pixels.size(); i++)
+ m_pixels[i] = c;
+ return *this;
+ }
+
+ image &fill_box(uint32_t x, uint32_t y, uint32_t w, uint32_t h, const color_rgba &c)
+ {
+ for (uint32_t iy = 0; iy < h; iy++)
+ for (uint32_t ix = 0; ix < w; ix++)
+ set_clipped(x + ix, y + iy, c);
+ return *this;
+ }
+
+ image &crop_dup_borders(uint32_t w, uint32_t h)
+ {
+ const uint32_t orig_w = m_width, orig_h = m_height;
+
+ crop(w, h);
+
+ if (orig_w && orig_h)
+ {
+ if (m_width > orig_w)
+ {
+ for (uint32_t x = orig_w; x < m_width; x++)
+ for (uint32_t y = 0; y < m_height; y++)
+ set_clipped(x, y, get_clamped(minimum(x, orig_w - 1U), minimum(y, orig_h - 1U)));
+ }
+
+ if (m_height > orig_h)
+ {
+ for (uint32_t y = orig_h; y < m_height; y++)
+ for (uint32_t x = 0; x < m_width; x++)
+ set_clipped(x, y, get_clamped(minimum(x, orig_w - 1U), minimum(y, orig_h - 1U)));
+ }
+ }
+ return *this;
+ }
+
+ image &crop(uint32_t w, uint32_t h, uint32_t p = UINT32_MAX, const color_rgba &background = g_black_color)
+ {
+ if (p == UINT32_MAX)
+ p = w;
+
+ if ((w == m_width) && (m_height == h) && (m_pitch == p))
+ return *this;
+
+ if ((!w) || (!h) || (!p))
+ {
+ clear();
+ return *this;
+ }
+
+ color_rgba_vec cur_state;
+ cur_state.swap(m_pixels);
+
+ m_pixels.resize(p * h);
+
+ for (uint32_t y = 0; y < h; y++)
+ {
+ for (uint32_t x = 0; x < w; x++)
+ {
+ if ((x < m_width) && (y < m_height))
+ m_pixels[x + y * p] = cur_state[x + y * m_pitch];
+ else
+ m_pixels[x + y * p] = background;
+ }
+ }
+
+ m_width = w;
+ m_height = h;
+ m_pitch = p;
+
+ return *this;
+ }
+
+ inline const color_rgba &operator() (uint32_t x, uint32_t y) const { assert(x < m_width && y < m_height); return m_pixels[x + y * m_pitch]; }
+ inline color_rgba &operator() (uint32_t x, uint32_t y) { assert(x < m_width && y < m_height); return m_pixels[x + y * m_pitch]; }
+
+ inline const color_rgba &get_clamped(int x, int y) const { return (*this)(clamp<int>(x, 0, m_width - 1), clamp<int>(y, 0, m_height - 1)); }
+ inline color_rgba &get_clamped(int x, int y) { return (*this)(clamp<int>(x, 0, m_width - 1), clamp<int>(y, 0, m_height - 1)); }
+
+ inline const color_rgba &get_clamped_or_wrapped(int x, int y, bool wrap_u, bool wrap_v) const
+ {
+ x = wrap_u ? posmod(x, m_width) : clamp<int>(x, 0, m_width - 1);
+ y = wrap_v ? posmod(y, m_height) : clamp<int>(y, 0, m_height - 1);
+ return m_pixels[x + y * m_pitch];
+ }
+
+ inline color_rgba &get_clamped_or_wrapped(int x, int y, bool wrap_u, bool wrap_v)
+ {
+ x = wrap_u ? posmod(x, m_width) : clamp<int>(x, 0, m_width - 1);
+ y = wrap_v ? posmod(y, m_height) : clamp<int>(y, 0, m_height - 1);
+ return m_pixels[x + y * m_pitch];
+ }
+
+ inline image &set_clipped(int x, int y, const color_rgba &c)
+ {
+ if ((static_cast<uint32_t>(x) < m_width) && (static_cast<uint32_t>(y) < m_height))
+ (*this)(x, y) = c;
+ return *this;
+ }
+
+ // Very straightforward blit with full clipping. Not fast, but it works.
+ image &blit(const image &src, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y)
+ {
+ for (int y = 0; y < src_h; y++)
+ {
+ const int sy = src_y + y;
+ if (sy < 0)
+ continue;
+ else if (sy >= (int)src.get_height())
+ break;
+
+ for (int x = 0; x < src_w; x++)
+ {
+ const int sx = src_x + x;
+ if (sx < 0)
+ continue;
+ else if (sx >= (int)src.get_height())
+ break;
+
+ set_clipped(dst_x + x, dst_y + y, src(sx, sy));
+ }
+ }
+
+ return *this;
+ }
+
+ const image &extract_block_clamped(color_rgba *pDst, uint32_t src_x, uint32_t src_y, uint32_t w, uint32_t h) const
+ {
+ for (uint32_t y = 0; y < h; y++)
+ for (uint32_t x = 0; x < w; x++)
+ *pDst++ = get_clamped(src_x + x, src_y + y);
+ return *this;
+ }
+
+ image &set_block_clipped(const color_rgba *pSrc, uint32_t dst_x, uint32_t dst_y, uint32_t w, uint32_t h)
+ {
+ for (uint32_t y = 0; y < h; y++)
+ for (uint32_t x = 0; x < w; x++)
+ set_clipped(dst_x + x, dst_y + y, *pSrc++);
+ return *this;
+ }
+
+ inline uint32_t get_width() const { return m_width; }
+ inline uint32_t get_height() const { return m_height; }
+ inline uint32_t get_pitch() const { return m_pitch; }
+ inline uint32_t get_total_pixels() const { return m_width * m_height; }
+
+ inline uint32_t get_block_width(uint32_t w) const { return (m_width + (w - 1)) / w; }
+ inline uint32_t get_block_height(uint32_t h) const { return (m_height + (h - 1)) / h; }
+ inline uint32_t get_total_blocks(uint32_t w, uint32_t h) const { return get_block_width(w) * get_block_height(h); }
+
+ inline const color_rgba_vec &get_pixels() const { return m_pixels; }
+ inline color_rgba_vec &get_pixels() { return m_pixels; }
+
+ inline const color_rgba *get_ptr() const { return &m_pixels[0]; }
+ inline color_rgba *get_ptr() { return &m_pixels[0]; }
+
+ bool has_alpha() const
+ {
+ for (uint32_t y = 0; y < m_height; ++y)
+ for (uint32_t x = 0; x < m_width; ++x)
+ if ((*this)(x, y).a < 255)
+ return true;
+
+ return false;
+ }
+
+ image &set_alpha(uint8_t a)
+ {
+ for (uint32_t y = 0; y < m_height; ++y)
+ for (uint32_t x = 0; x < m_width; ++x)
+ (*this)(x, y).a = a;
+ return *this;
+ }
+
+ image &flip_y()
+ {
+ for (uint32_t y = 0; y < m_height / 2; ++y)
+ for (uint32_t x = 0; x < m_width; ++x)
+ std::swap((*this)(x, y), (*this)(x, m_height - 1 - y));
+ return *this;
+ }
+
+ // TODO: There are many ways to do this, not sure this is the best way.
+ image &renormalize_normal_map()
+ {
+ for (uint32_t y = 0; y < m_height; y++)
+ {
+ for (uint32_t x = 0; x < m_width; x++)
+ {
+ color_rgba &c = (*this)(x, y);
+ if ((c.r == 128) && (c.g == 128) && (c.b == 128))
+ continue;
+
+ vec3F v(c.r, c.g, c.b);
+ v = (v * (2.0f / 255.0f)) - vec3F(1.0f);
+ v.clamp(-1.0f, 1.0f);
+
+ float length = v.length();
+ const float cValidThresh = .077f;
+ if (length < cValidThresh)
+ {
+ c.set(128, 128, 128, c.a);
+ }
+ else if (fabs(length - 1.0f) > cValidThresh)
+ {
+ if (length)
+ v /= length;
+
+ for (uint32_t i = 0; i < 3; i++)
+ c[i] = static_cast<uint8_t>(clamp<float>(floor((v[i] + 1.0f) * 255.0f * .5f + .5f), 0.0f, 255.0f));
+
+ if ((c.g == 128) && (c.r == 128))
+ {
+ if (c.b < 128)
+ c.b = 0;
+ else
+ c.b = 255;
+ }
+ }
+ }
+ }
+ return *this;
+ }
+
+ private:
+ uint32_t m_width, m_height, m_pitch; // all in pixels
+ color_rgba_vec m_pixels;
+ };
+
+ // Float images
+
+ typedef std::vector<vec4F> vec4F_vec;
+
+ class imagef
+ {
+ public:
+ imagef() :
+ m_width(0), m_height(0), m_pitch(0)
+ {
+ }
+
+ imagef(uint32_t w, uint32_t h, uint32_t p = UINT32_MAX) :
+ m_width(0), m_height(0), m_pitch(0)
+ {
+ resize(w, h, p);
+ }
+
+ imagef(const imagef &other) :
+ m_width(0), m_height(0), m_pitch(0)
+ {
+ *this = other;
+ }
+
+ imagef &swap(imagef &other)
+ {
+ std::swap(m_width, other.m_width);
+ std::swap(m_height, other.m_height);
+ std::swap(m_pitch, other.m_pitch);
+ m_pixels.swap(other.m_pixels);
+ return *this;
+ }
+
+ imagef &operator= (const imagef &rhs)
+ {
+ if (this != &rhs)
+ {
+ m_width = rhs.m_width;
+ m_height = rhs.m_height;
+ m_pitch = rhs.m_pitch;
+ m_pixels = rhs.m_pixels;
+ }
+ return *this;
+ }
+
+ imagef &clear()
+ {
+ m_width = 0;
+ m_height = 0;
+ m_pitch = 0;
+ clear_vector(m_pixels);
+ return *this;
+ }
+
+ imagef &set(const image &src, const vec4F &scale = vec4F(1), const vec4F &bias = vec4F(0))
+ {
+ const uint32_t width = src.get_width();
+ const uint32_t height = src.get_height();
+
+ resize(width, height);
+
+ for (int y = 0; y < (int)height; y++)
+ {
+ for (uint32_t x = 0; x < width; x++)
+ {
+ const color_rgba &src_pixel = src(x, y);
+ (*this)(x, y).set((float)src_pixel.r * scale[0] + bias[0], (float)src_pixel.g * scale[1] + bias[1], (float)src_pixel.b * scale[2] + bias[2], (float)src_pixel.a * scale[3] + bias[3]);
+ }
+ }
+
+ return *this;
+ }
+
+ imagef &resize(const imagef &other, uint32_t p = UINT32_MAX, const vec4F& background = vec4F(0,0,0,1))
+ {
+ return resize(other.get_width(), other.get_height(), p, background);
+ }
+
+ imagef &resize(uint32_t w, uint32_t h, uint32_t p = UINT32_MAX, const vec4F& background = vec4F(0,0,0,1))
+ {
+ return crop(w, h, p, background);
+ }
+
+ imagef &set_all(const vec4F &c)
+ {
+ for (uint32_t i = 0; i < m_pixels.size(); i++)
+ m_pixels[i] = c;
+ return *this;
+ }
+
+ imagef &fill_box(uint32_t x, uint32_t y, uint32_t w, uint32_t h, const vec4F &c)
+ {
+ for (uint32_t iy = 0; iy < h; iy++)
+ for (uint32_t ix = 0; ix < w; ix++)
+ set_clipped(x + ix, y + iy, c);
+ return *this;
+ }
+
+ imagef &crop(uint32_t w, uint32_t h, uint32_t p = UINT32_MAX, const vec4F &background = vec4F(0,0,0,1))
+ {
+ if (p == UINT32_MAX)
+ p = w;
+
+ if ((w == m_width) && (m_height == h) && (m_pitch == p))
+ return *this;
+
+ if ((!w) || (!h) || (!p))
+ {
+ clear();
+ return *this;
+ }
+
+ vec4F_vec cur_state;
+ cur_state.swap(m_pixels);
+
+ m_pixels.resize(p * h);
+
+ for (uint32_t y = 0; y < h; y++)
+ {
+ for (uint32_t x = 0; x < w; x++)
+ {
+ if ((x < m_width) && (y < m_height))
+ m_pixels[x + y * p] = cur_state[x + y * m_pitch];
+ else
+ m_pixels[x + y * p] = background;
+ }
+ }
+
+ m_width = w;
+ m_height = h;
+ m_pitch = p;
+
+ return *this;
+ }
+
+ inline const vec4F &operator() (uint32_t x, uint32_t y) const { assert(x < m_width && y < m_height); return m_pixels[x + y * m_pitch]; }
+ inline vec4F &operator() (uint32_t x, uint32_t y) { assert(x < m_width && y < m_height); return m_pixels[x + y * m_pitch]; }
+
+ inline const vec4F &get_clamped(int x, int y) const { return (*this)(clamp<int>(x, 0, m_width - 1), clamp<int>(y, 0, m_height - 1)); }
+ inline vec4F &get_clamped(int x, int y) { return (*this)(clamp<int>(x, 0, m_width - 1), clamp<int>(y, 0, m_height - 1)); }
+
+ inline const vec4F &get_clamped_or_wrapped(int x, int y, bool wrap_u, bool wrap_v) const
+ {
+ x = wrap_u ? posmod(x, m_width) : clamp<int>(x, 0, m_width - 1);
+ y = wrap_v ? posmod(y, m_height) : clamp<int>(y, 0, m_height - 1);
+ return m_pixels[x + y * m_pitch];
+ }
+
+ inline vec4F &get_clamped_or_wrapped(int x, int y, bool wrap_u, bool wrap_v)
+ {
+ x = wrap_u ? posmod(x, m_width) : clamp<int>(x, 0, m_width - 1);
+ y = wrap_v ? posmod(y, m_height) : clamp<int>(y, 0, m_height - 1);
+ return m_pixels[x + y * m_pitch];
+ }
+
+ inline imagef &set_clipped(int x, int y, const vec4F &c)
+ {
+ if ((static_cast<uint32_t>(x) < m_width) && (static_cast<uint32_t>(y) < m_height))
+ (*this)(x, y) = c;
+ return *this;
+ }
+
+ // Very straightforward blit with full clipping. Not fast, but it works.
+ imagef &blit(const imagef &src, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y)
+ {
+ for (int y = 0; y < src_h; y++)
+ {
+ const int sy = src_y + y;
+ if (sy < 0)
+ continue;
+ else if (sy >= (int)src.get_height())
+ break;
+
+ for (int x = 0; x < src_w; x++)
+ {
+ const int sx = src_x + x;
+ if (sx < 0)
+ continue;
+ else if (sx >= (int)src.get_height())
+ break;
+
+ set_clipped(dst_x + x, dst_y + y, src(sx, sy));
+ }
+ }
+
+ return *this;
+ }
+
+ const imagef &extract_block_clamped(vec4F *pDst, uint32_t src_x, uint32_t src_y, uint32_t w, uint32_t h) const
+ {
+ for (uint32_t y = 0; y < h; y++)
+ for (uint32_t x = 0; x < w; x++)
+ *pDst++ = get_clamped(src_x + x, src_y + y);
+ return *this;
+ }
+
+ imagef &set_block_clipped(const vec4F *pSrc, uint32_t dst_x, uint32_t dst_y, uint32_t w, uint32_t h)
+ {
+ for (uint32_t y = 0; y < h; y++)
+ for (uint32_t x = 0; x < w; x++)
+ set_clipped(dst_x + x, dst_y + y, *pSrc++);
+ return *this;
+ }
+
+ inline uint32_t get_width() const { return m_width; }
+ inline uint32_t get_height() const { return m_height; }
+ inline uint32_t get_pitch() const { return m_pitch; }
+ inline uint32_t get_total_pixels() const { return m_width * m_height; }
+
+ inline uint32_t get_block_width(uint32_t w) const { return (m_width + (w - 1)) / w; }
+ inline uint32_t get_block_height(uint32_t h) const { return (m_height + (h - 1)) / h; }
+ inline uint32_t get_total_blocks(uint32_t w, uint32_t h) const { return get_block_width(w) * get_block_height(h); }
+
+ inline const vec4F_vec &get_pixels() const { return m_pixels; }
+ inline vec4F_vec &get_pixels() { return m_pixels; }
+
+ inline const vec4F *get_ptr() const { return &m_pixels[0]; }
+ inline vec4F *get_ptr() { return &m_pixels[0]; }
+
+ private:
+ uint32_t m_width, m_height, m_pitch; // all in pixels
+ vec4F_vec m_pixels;
+ };
+
+ // Image metrics
+
+ class image_metrics
+ {
+ public:
+ // TODO: Add ssim
+ float m_max, m_mean, m_mean_squared, m_rms, m_psnr, m_ssim;
+
+ image_metrics()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ m_max = 0;
+ m_mean = 0;
+ m_mean_squared = 0;
+ m_rms = 0;
+ m_psnr = 0;
+ m_ssim = 0;
+ }
+
+ void print(const char *pPrefix = nullptr) { printf("%sMax: %3.0f Mean: %3.3f RMS: %3.3f PSNR: %2.3f dB\n", pPrefix ? pPrefix : "", m_max, m_mean, m_rms, m_psnr); }
+
+ void calc(const image &a, const image &b, uint32_t first_chan = 0, uint32_t total_chans = 0, bool avg_comp_error = true, bool use_601_luma = false);
+ };
+
+ // Image saving/loading/resampling
+
+ bool load_png(const char* pFilename, image& img);
+ inline bool load_png(const std::string &filename, image &img) { return load_png(filename.c_str(), img); }
+
+ enum
+ {
+ cImageSaveGrayscale = 1,
+ cImageSaveIgnoreAlpha = 2
+ };
+
+ bool save_png(const char* pFilename, const image& img, uint32_t image_save_flags = 0, uint32_t grayscale_comp = 0);
+ inline bool save_png(const std::string &filename, const image &img, uint32_t image_save_flags = 0, uint32_t grayscale_comp = 0) { return save_png(filename.c_str(), img, image_save_flags, grayscale_comp); }
+
+ bool read_file_to_vec(const char* pFilename, uint8_vec& data);
+
+ bool write_data_to_file(const char* pFilename, const void* pData, size_t len);
+
+ inline bool write_vec_to_file(const char* pFilename, const uint8_vec& v) { return v.size() ? write_data_to_file(pFilename, &v[0], v.size()) : write_data_to_file(pFilename, "", 0); }
+
+ float linear_to_srgb(float l);
+ float srgb_to_linear(float s);
+
+ bool image_resample(const image &src, image &dst, bool srgb = false,
+ const char *pFilter = "lanczos4", float filter_scale = 1.0f,
+ bool wrapping = false,
+ uint32_t first_comp = 0, uint32_t num_comps = 4);
+
+ // Timing
+
+ typedef uint64_t timer_ticks;
+
+ class interval_timer
+ {
+ public:
+ interval_timer();
+
+ void start();
+ void stop();
+
+ double get_elapsed_secs() const;
+ inline double get_elapsed_ms() const { return 1000.0f* get_elapsed_secs(); }
+
+ static void init();
+ static inline timer_ticks get_ticks_per_sec() { return g_freq; }
+ static timer_ticks get_ticks();
+ static double ticks_to_secs(timer_ticks ticks);
+ static inline double ticks_to_ms(timer_ticks ticks) { return ticks_to_secs(ticks) * 1000.0f; }
+
+ private:
+ static timer_ticks g_init_ticks, g_freq;
+ static double g_timer_freq;
+
+ timer_ticks m_start_time, m_stop_time;
+
+ bool m_started, m_stopped;
+ };
+
+ // 2D array
+
+ template<typename T>
+ class vector2D
+ {
+ typedef std::vector<T> TVec;
+
+ uint32_t m_width, m_height;
+ TVec m_values;
+
+ public:
+ vector2D() :
+ m_width(0),
+ m_height(0)
+ {
+ }
+
+ vector2D(uint32_t w, uint32_t h) :
+ m_width(0),
+ m_height(0)
+ {
+ resize(w, h);
+ }
+
+ vector2D(const vector2D &other)
+ {
+ *this = other;
+ }
+
+ vector2D &operator= (const vector2D &other)
+ {
+ if (this != &other)
+ {
+ m_width = other.m_width;
+ m_height = other.m_height;
+ m_values = other.m_values;
+ }
+ return *this;
+ }
+
+ inline bool operator== (const vector2D &rhs) const
+ {
+ return (m_width == rhs.m_width) && (m_height == rhs.m_height) && (m_values == rhs.m_values);
+ }
+
+ inline uint32_t size_in_bytes() const { return (uint32_t)m_values.size() * sizeof(m_values[0]); }
+
+ inline const T &operator() (uint32_t x, uint32_t y) const { assert(x < m_width && y < m_height); return m_values[x + y * m_width]; }
+ inline T &operator() (uint32_t x, uint32_t y) { assert(x < m_width && y < m_height); return m_values[x + y * m_width]; }
+
+ inline const T &operator[] (uint32_t i) const { return m_values[i]; }
+ inline T &operator[] (uint32_t i) { return m_values[i]; }
+
+ inline const T &at_clamped(int x, int y) const { return (*this)(clamp<int>(x, 0, m_width), clamp<int>(y, 0, m_height)); }
+ inline T &at_clamped(int x, int y) { return (*this)(clamp<int>(x, 0, m_width), clamp<int>(y, 0, m_height)); }
+
+ void clear()
+ {
+ m_width = 0;
+ m_height = 0;
+ m_values.clear();
+ }
+
+ void set_all(const T&val)
+ {
+ vector_set_all(m_values, val);
+ }
+
+ inline const T* get_ptr() const { return &m_values[0]; }
+ inline T* get_ptr() { return &m_values[0]; }
+
+ vector2D &resize(uint32_t new_width, uint32_t new_height)
+ {
+ if ((m_width == new_width) && (m_height == new_height))
+ return *this;
+
+ TVec oldVals(new_width * new_height);
+ oldVals.swap(m_values);
+
+ const uint32_t w = minimum(m_width, new_width);
+ const uint32_t h = minimum(m_height, new_height);
+
+ if ((w) && (h))
+ {
+ for (uint32_t y = 0; y < h; y++)
+ for (uint32_t x = 0; x < w; x++)
+ m_values[x + y * new_width] = oldVals[x + y * m_width];
+ }
+
+ m_width = new_width;
+ m_height = new_height;
+
+ return *this;
+ }
+ };
+
+ inline FILE *fopen_safe(const char *pFilename, const char *pMode)
+ {
+#ifdef _WIN32
+ FILE *pFile = nullptr;
+ fopen_s(&pFile, pFilename, pMode);
+ return pFile;
+#else
+ return fopen(pFilename, pMode);
+#endif
+ }
+
+ void fill_buffer_with_random_bytes(void *pBuf, size_t size, uint32_t seed = 1);
+
+} // namespace basisu
+
+
diff --git a/thirdparty/basis_universal/basisu_etc.cpp b/thirdparty/basis_universal/basisu_etc.cpp
new file mode 100644
index 0000000000..244f1d2e6b
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_etc.cpp
@@ -0,0 +1,1074 @@
+// basis_etc.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_etc.h"
+
+#define BASISU_DEBUG_ETC_ENCODER 0
+#define BASISU_DEBUG_ETC_ENCODER_DEEPER 0
+
+namespace basisu
+{
+ const uint32_t BASISU_ETC1_CLUSTER_FIT_ORDER_TABLE_SIZE = 165;
+
+ static const struct { uint8_t m_v[4]; } g_cluster_fit_order_tab[BASISU_ETC1_CLUSTER_FIT_ORDER_TABLE_SIZE] =
+ {
+ { { 0, 0, 0, 8 } },{ { 0, 5, 2, 1 } },{ { 0, 6, 1, 1 } },{ { 0, 7, 0, 1 } },{ { 0, 7, 1, 0 } },
+ { { 0, 0, 8, 0 } },{ { 0, 0, 3, 5 } },{ { 0, 1, 7, 0 } },{ { 0, 0, 4, 4 } },{ { 0, 0, 2, 6 } },
+ { { 0, 0, 7, 1 } },{ { 0, 0, 1, 7 } },{ { 0, 0, 5, 3 } },{ { 1, 6, 0, 1 } },{ { 0, 0, 6, 2 } },
+ { { 0, 2, 6, 0 } },{ { 2, 4, 2, 0 } },{ { 0, 3, 5, 0 } },{ { 3, 3, 1, 1 } },{ { 4, 2, 0, 2 } },
+ { { 1, 5, 2, 0 } },{ { 0, 5, 3, 0 } },{ { 0, 6, 2, 0 } },{ { 2, 4, 1, 1 } },{ { 5, 1, 0, 2 } },
+ { { 6, 1, 1, 0 } },{ { 3, 3, 0, 2 } },{ { 6, 0, 0, 2 } },{ { 0, 8, 0, 0 } },{ { 6, 1, 0, 1 } },
+ { { 0, 1, 6, 1 } },{ { 1, 6, 1, 0 } },{ { 4, 1, 3, 0 } },{ { 0, 2, 5, 1 } },{ { 5, 0, 3, 0 } },
+ { { 5, 3, 0, 0 } },{ { 0, 1, 5, 2 } },{ { 0, 3, 4, 1 } },{ { 2, 5, 1, 0 } },{ { 1, 7, 0, 0 } },
+ { { 0, 1, 4, 3 } },{ { 6, 0, 2, 0 } },{ { 0, 4, 4, 0 } },{ { 2, 6, 0, 0 } },{ { 0, 2, 4, 2 } },
+ { { 0, 5, 1, 2 } },{ { 0, 6, 0, 2 } },{ { 3, 5, 0, 0 } },{ { 0, 4, 3, 1 } },{ { 3, 4, 1, 0 } },
+ { { 4, 3, 1, 0 } },{ { 1, 5, 0, 2 } },{ { 0, 3, 3, 2 } },{ { 1, 4, 1, 2 } },{ { 0, 4, 2, 2 } },
+ { { 2, 3, 3, 0 } },{ { 4, 4, 0, 0 } },{ { 1, 2, 4, 1 } },{ { 0, 5, 0, 3 } },{ { 0, 1, 3, 4 } },
+ { { 1, 5, 1, 1 } },{ { 1, 4, 2, 1 } },{ { 1, 3, 2, 2 } },{ { 5, 2, 1, 0 } },{ { 1, 3, 3, 1 } },
+ { { 0, 1, 2, 5 } },{ { 1, 1, 5, 1 } },{ { 0, 3, 2, 3 } },{ { 2, 5, 0, 1 } },{ { 3, 2, 2, 1 } },
+ { { 2, 3, 0, 3 } },{ { 1, 4, 3, 0 } },{ { 2, 2, 1, 3 } },{ { 6, 2, 0, 0 } },{ { 1, 0, 6, 1 } },
+ { { 3, 3, 2, 0 } },{ { 7, 1, 0, 0 } },{ { 3, 1, 4, 0 } },{ { 0, 2, 3, 3 } },{ { 0, 4, 1, 3 } },
+ { { 0, 4, 0, 4 } },{ { 0, 1, 0, 7 } },{ { 2, 0, 5, 1 } },{ { 2, 0, 4, 2 } },{ { 3, 0, 2, 3 } },
+ { { 2, 2, 4, 0 } },{ { 2, 2, 3, 1 } },{ { 4, 0, 3, 1 } },{ { 3, 2, 3, 0 } },{ { 2, 3, 2, 1 } },
+ { { 1, 3, 4, 0 } },{ { 7, 0, 1, 0 } },{ { 3, 0, 4, 1 } },{ { 1, 0, 5, 2 } },{ { 8, 0, 0, 0 } },
+ { { 3, 0, 1, 4 } },{ { 4, 1, 1, 2 } },{ { 4, 0, 2, 2 } },{ { 1, 2, 5, 0 } },{ { 4, 2, 1, 1 } },
+ { { 3, 4, 0, 1 } },{ { 2, 0, 3, 3 } },{ { 5, 0, 1, 2 } },{ { 5, 0, 0, 3 } },{ { 2, 4, 0, 2 } },
+ { { 2, 1, 4, 1 } },{ { 4, 0, 1, 3 } },{ { 2, 1, 5, 0 } },{ { 4, 2, 2, 0 } },{ { 4, 0, 4, 0 } },
+ { { 1, 0, 4, 3 } },{ { 1, 4, 0, 3 } },{ { 3, 0, 3, 2 } },{ { 4, 3, 0, 1 } },{ { 0, 1, 1, 6 } },
+ { { 1, 3, 1, 3 } },{ { 0, 2, 2, 4 } },{ { 2, 0, 2, 4 } },{ { 5, 1, 1, 1 } },{ { 3, 0, 5, 0 } },
+ { { 2, 3, 1, 2 } },{ { 3, 0, 0, 5 } },{ { 0, 3, 1, 4 } },{ { 5, 0, 2, 1 } },{ { 2, 1, 3, 2 } },
+ { { 2, 0, 6, 0 } },{ { 3, 1, 3, 1 } },{ { 5, 1, 2, 0 } },{ { 1, 0, 3, 4 } },{ { 1, 1, 6, 0 } },
+ { { 4, 0, 0, 4 } },{ { 2, 0, 1, 5 } },{ { 0, 3, 0, 5 } },{ { 1, 3, 0, 4 } },{ { 4, 1, 2, 1 } },
+ { { 1, 2, 3, 2 } },{ { 3, 1, 0, 4 } },{ { 5, 2, 0, 1 } },{ { 1, 2, 2, 3 } },{ { 3, 2, 1, 2 } },
+ { { 2, 2, 2, 2 } },{ { 6, 0, 1, 1 } },{ { 1, 2, 1, 4 } },{ { 1, 1, 4, 2 } },{ { 3, 2, 0, 3 } },
+ { { 1, 2, 0, 5 } },{ { 1, 0, 7, 0 } },{ { 3, 1, 2, 2 } },{ { 1, 0, 2, 5 } },{ { 2, 0, 0, 6 } },
+ { { 2, 1, 1, 4 } },{ { 2, 2, 0, 4 } },{ { 1, 1, 3, 3 } },{ { 7, 0, 0, 1 } },{ { 1, 0, 0, 7 } },
+ { { 2, 1, 2, 3 } },{ { 4, 1, 0, 3 } },{ { 3, 1, 1, 3 } },{ { 1, 1, 2, 4 } },{ { 2, 1, 0, 5 } },
+ { { 1, 0, 1, 6 } },{ { 0, 2, 1, 5 } },{ { 0, 2, 0, 6 } },{ { 1, 1, 1, 5 } },{ { 1, 1, 0, 6 } }
+ };
+
+ const int g_etc1_inten_tables[cETC1IntenModifierValues][cETC1SelectorValues] =
+ {
+ { -8, -2, 2, 8 }, { -17, -5, 5, 17 }, { -29, -9, 9, 29 }, { -42, -13, 13, 42 },
+ { -60, -18, 18, 60 }, { -80, -24, 24, 80 }, { -106, -33, 33, 106 }, { -183, -47, 47, 183 }
+ };
+
+ const uint8_t g_etc1_to_selector_index[cETC1SelectorValues] = { 2, 3, 1, 0 };
+ const uint8_t g_selector_index_to_etc1[cETC1SelectorValues] = { 3, 2, 0, 1 };
+
+ // [flip][subblock][pixel_index]
+ const etc_coord2 g_etc1_pixel_coords[2][2][8] =
+ {
+ {
+ {
+ { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 },
+ { 1, 0 }, { 1, 1 }, { 1, 2 }, { 1, 3 }
+ },
+ {
+ { 2, 0 }, { 2, 1 }, { 2, 2 }, { 2, 3 },
+ { 3, 0 }, { 3, 1 }, { 3, 2 }, { 3, 3 }
+ }
+ },
+ {
+ {
+ { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 },
+ { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }
+ },
+ {
+ { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 },
+ { 0, 3 }, { 1, 3 }, { 2, 3 }, { 3, 3 }
+ },
+ }
+ };
+
+ // [flip][subblock][pixel_index]
+ const uint32_t g_etc1_pixel_indices[2][2][8] =
+ {
+ {
+ {
+ 0 + 4 * 0, 0 + 4 * 1, 0 + 4 * 2, 0 + 4 * 3,
+ 1 + 4 * 0, 1 + 4 * 1, 1 + 4 * 2, 1 + 4 * 3
+ },
+ {
+ 2 + 4 * 0, 2 + 4 * 1, 2 + 4 * 2, 2 + 4 * 3,
+ 3 + 4 * 0, 3 + 4 * 1, 3 + 4 * 2, 3 + 4 * 3
+ }
+ },
+ {
+ {
+ 0 + 4 * 0, 1 + 4 * 0, 2 + 4 * 0, 3 + 4 * 0,
+ 0 + 4 * 1, 1 + 4 * 1, 2 + 4 * 1, 3 + 4 * 1
+ },
+ {
+ 0 + 4 * 2, 1 + 4 * 2, 2 + 4 * 2, 3 + 4 * 2,
+ 0 + 4 * 3, 1 + 4 * 3, 2 + 4 * 3, 3 + 4 * 3
+ },
+ }
+ };
+
+ uint16_t etc_block::pack_color5(const color_rgba& color, bool scaled, uint32_t bias)
+ {
+ return pack_color5(color.r, color.g, color.b, scaled, bias);
+ }
+
+ uint16_t etc_block::pack_color5(uint32_t r, uint32_t g, uint32_t b, bool scaled, uint32_t bias)
+ {
+ if (scaled)
+ {
+ r = (r * 31U + bias) / 255U;
+ g = (g * 31U + bias) / 255U;
+ b = (b * 31U + bias) / 255U;
+ }
+
+ r = minimum(r, 31U);
+ g = minimum(g, 31U);
+ b = minimum(b, 31U);
+
+ return static_cast<uint16_t>(b | (g << 5U) | (r << 10U));
+ }
+
+ color_rgba etc_block::unpack_color5(uint16_t packed_color5, bool scaled, uint32_t alpha)
+ {
+ uint32_t b = packed_color5 & 31U;
+ uint32_t g = (packed_color5 >> 5U) & 31U;
+ uint32_t r = (packed_color5 >> 10U) & 31U;
+
+ if (scaled)
+ {
+ b = (b << 3U) | (b >> 2U);
+ g = (g << 3U) | (g >> 2U);
+ r = (r << 3U) | (r >> 2U);
+ }
+
+ return color_rgba(cNoClamp, r, g, b, minimum(alpha, 255U));
+ }
+
+ void etc_block::unpack_color5(color_rgba& result, uint16_t packed_color5, bool scaled)
+ {
+ result = unpack_color5(packed_color5, scaled, 255);
+ }
+
+ void etc_block::unpack_color5(uint32_t& r, uint32_t& g, uint32_t& b, uint16_t packed_color5, bool scaled)
+ {
+ color_rgba c(unpack_color5(packed_color5, scaled, 0));
+ r = c.r;
+ g = c.g;
+ b = c.b;
+ }
+
+ bool etc_block::unpack_color5(color_rgba& result, uint16_t packed_color5, uint16_t packed_delta3, bool scaled, uint32_t alpha)
+ {
+ color_rgba_i16 dc(unpack_delta3(packed_delta3));
+
+ int b = (packed_color5 & 31U) + dc.b;
+ int g = ((packed_color5 >> 5U) & 31U) + dc.g;
+ int r = ((packed_color5 >> 10U) & 31U) + dc.r;
+
+ bool success = true;
+ if (static_cast<uint32_t>(r | g | b) > 31U)
+ {
+ success = false;
+ r = clamp<int>(r, 0, 31);
+ g = clamp<int>(g, 0, 31);
+ b = clamp<int>(b, 0, 31);
+ }
+
+ if (scaled)
+ {
+ b = (b << 3U) | (b >> 2U);
+ g = (g << 3U) | (g >> 2U);
+ r = (r << 3U) | (r >> 2U);
+ }
+
+ result.set_noclamp_rgba(r, g, b, minimum(alpha, 255U));
+ return success;
+ }
+
+ bool etc_block::unpack_color5(uint32_t& r, uint32_t& g, uint32_t& b, uint16_t packed_color5, uint16_t packed_delta3, bool scaled, uint32_t alpha)
+ {
+ color_rgba result;
+ const bool success = unpack_color5(result, packed_color5, packed_delta3, scaled, alpha);
+ r = result.r;
+ g = result.g;
+ b = result.b;
+ return success;
+ }
+
+ uint16_t etc_block::pack_delta3(const color_rgba_i16& color)
+ {
+ return pack_delta3(color.r, color.g, color.b);
+ }
+
+ uint16_t etc_block::pack_delta3(int r, int g, int b)
+ {
+ assert((r >= cETC1ColorDeltaMin) && (r <= cETC1ColorDeltaMax));
+ assert((g >= cETC1ColorDeltaMin) && (g <= cETC1ColorDeltaMax));
+ assert((b >= cETC1ColorDeltaMin) && (b <= cETC1ColorDeltaMax));
+ if (r < 0) r += 8;
+ if (g < 0) g += 8;
+ if (b < 0) b += 8;
+ return static_cast<uint16_t>(b | (g << 3) | (r << 6));
+ }
+
+ color_rgba_i16 etc_block::unpack_delta3(uint16_t packed_delta3)
+ {
+ int r = (packed_delta3 >> 6) & 7;
+ int g = (packed_delta3 >> 3) & 7;
+ int b = packed_delta3 & 7;
+ if (r >= 4) r -= 8;
+ if (g >= 4) g -= 8;
+ if (b >= 4) b -= 8;
+ return color_rgba_i16(r, g, b, 255);
+ }
+
+ void etc_block::unpack_delta3(int& r, int& g, int& b, uint16_t packed_delta3)
+ {
+ r = (packed_delta3 >> 6) & 7;
+ g = (packed_delta3 >> 3) & 7;
+ b = packed_delta3 & 7;
+ if (r >= 4) r -= 8;
+ if (g >= 4) g -= 8;
+ if (b >= 4) b -= 8;
+ }
+
+ uint16_t etc_block::pack_color4(const color_rgba& color, bool scaled, uint32_t bias)
+ {
+ return pack_color4(color.r, color.g, color.b, scaled, bias);
+ }
+
+ uint16_t etc_block::pack_color4(uint32_t r, uint32_t g, uint32_t b, bool scaled, uint32_t bias)
+ {
+ if (scaled)
+ {
+ r = (r * 15U + bias) / 255U;
+ g = (g * 15U + bias) / 255U;
+ b = (b * 15U + bias) / 255U;
+ }
+
+ r = minimum(r, 15U);
+ g = minimum(g, 15U);
+ b = minimum(b, 15U);
+
+ return static_cast<uint16_t>(b | (g << 4U) | (r << 8U));
+ }
+
+ color_rgba etc_block::unpack_color4(uint16_t packed_color4, bool scaled, uint32_t alpha)
+ {
+ uint32_t b = packed_color4 & 15U;
+ uint32_t g = (packed_color4 >> 4U) & 15U;
+ uint32_t r = (packed_color4 >> 8U) & 15U;
+
+ if (scaled)
+ {
+ b = (b << 4U) | b;
+ g = (g << 4U) | g;
+ r = (r << 4U) | r;
+ }
+
+ return color_rgba(cNoClamp, r, g, b, minimum(alpha, 255U));
+ }
+
+ void etc_block::unpack_color4(uint32_t& r, uint32_t& g, uint32_t& b, uint16_t packed_color4, bool scaled)
+ {
+ color_rgba c(unpack_color4(packed_color4, scaled, 0));
+ r = c.r;
+ g = c.g;
+ b = c.b;
+ }
+
+ void etc_block::get_diff_subblock_colors(color_rgba* pDst, uint16_t packed_color5, uint32_t table_idx)
+ {
+ assert(table_idx < cETC1IntenModifierValues);
+ const int *pInten_modifer_table = &g_etc1_inten_tables[table_idx][0];
+
+ uint32_t r, g, b;
+ unpack_color5(r, g, b, packed_color5, true);
+
+ const int ir = static_cast<int>(r), ig = static_cast<int>(g), ib = static_cast<int>(b);
+
+ const int y0 = pInten_modifer_table[0];
+ pDst[0].set(ir + y0, ig + y0, ib + y0, 255);
+
+ const int y1 = pInten_modifer_table[1];
+ pDst[1].set(ir + y1, ig + y1, ib + y1, 255);
+
+ const int y2 = pInten_modifer_table[2];
+ pDst[2].set(ir + y2, ig + y2, ib + y2, 255);
+
+ const int y3 = pInten_modifer_table[3];
+ pDst[3].set(ir + y3, ig + y3, ib + y3, 255);
+ }
+
+ bool etc_block::get_diff_subblock_colors(color_rgba* pDst, uint16_t packed_color5, uint16_t packed_delta3, uint32_t table_idx)
+ {
+ assert(table_idx < cETC1IntenModifierValues);
+ const int *pInten_modifer_table = &g_etc1_inten_tables[table_idx][0];
+
+ uint32_t r, g, b;
+ bool success = unpack_color5(r, g, b, packed_color5, packed_delta3, true);
+
+ const int ir = static_cast<int>(r), ig = static_cast<int>(g), ib = static_cast<int>(b);
+
+ const int y0 = pInten_modifer_table[0];
+ pDst[0].set(ir + y0, ig + y0, ib + y0, 255);
+
+ const int y1 = pInten_modifer_table[1];
+ pDst[1].set(ir + y1, ig + y1, ib + y1, 255);
+
+ const int y2 = pInten_modifer_table[2];
+ pDst[2].set(ir + y2, ig + y2, ib + y2, 255);
+
+ const int y3 = pInten_modifer_table[3];
+ pDst[3].set(ir + y3, ig + y3, ib + y3, 255);
+
+ return success;
+ }
+
+ void etc_block::get_abs_subblock_colors(color_rgba* pDst, uint16_t packed_color4, uint32_t table_idx)
+ {
+ assert(table_idx < cETC1IntenModifierValues);
+ const int *pInten_modifer_table = &g_etc1_inten_tables[table_idx][0];
+
+ uint32_t r, g, b;
+ unpack_color4(r, g, b, packed_color4, true);
+
+ const int ir = static_cast<int>(r), ig = static_cast<int>(g), ib = static_cast<int>(b);
+
+ const int y0 = pInten_modifer_table[0];
+ pDst[0].set(ir + y0, ig + y0, ib + y0, 255);
+
+ const int y1 = pInten_modifer_table[1];
+ pDst[1].set(ir + y1, ig + y1, ib + y1, 255);
+
+ const int y2 = pInten_modifer_table[2];
+ pDst[2].set(ir + y2, ig + y2, ib + y2, 255);
+
+ const int y3 = pInten_modifer_table[3];
+ pDst[3].set(ir + y3, ig + y3, ib + y3, 255);
+ }
+
+ bool unpack_etc1(const etc_block& block, color_rgba *pDst, bool preserve_alpha)
+ {
+ const bool diff_flag = block.get_diff_bit();
+ const bool flip_flag = block.get_flip_bit();
+ const uint32_t table_index0 = block.get_inten_table(0);
+ const uint32_t table_index1 = block.get_inten_table(1);
+
+ color_rgba subblock_colors0[4];
+ color_rgba subblock_colors1[4];
+
+ if (diff_flag)
+ {
+ const uint16_t base_color5 = block.get_base5_color();
+ const uint16_t delta_color3 = block.get_delta3_color();
+ etc_block::get_diff_subblock_colors(subblock_colors0, base_color5, table_index0);
+
+ if (!etc_block::get_diff_subblock_colors(subblock_colors1, base_color5, delta_color3, table_index1))
+ return false;
+ }
+ else
+ {
+ const uint16_t base_color4_0 = block.get_base4_color(0);
+ etc_block::get_abs_subblock_colors(subblock_colors0, base_color4_0, table_index0);
+
+ const uint16_t base_color4_1 = block.get_base4_color(1);
+ etc_block::get_abs_subblock_colors(subblock_colors1, base_color4_1, table_index1);
+ }
+
+ if (preserve_alpha)
+ {
+ if (flip_flag)
+ {
+ for (uint32_t y = 0; y < 2; y++)
+ {
+ pDst[0].set_rgb(subblock_colors0[block.get_selector(0, y)]);
+ pDst[1].set_rgb(subblock_colors0[block.get_selector(1, y)]);
+ pDst[2].set_rgb(subblock_colors0[block.get_selector(2, y)]);
+ pDst[3].set_rgb(subblock_colors0[block.get_selector(3, y)]);
+ pDst += 4;
+ }
+
+ for (uint32_t y = 2; y < 4; y++)
+ {
+ pDst[0].set_rgb(subblock_colors1[block.get_selector(0, y)]);
+ pDst[1].set_rgb(subblock_colors1[block.get_selector(1, y)]);
+ pDst[2].set_rgb(subblock_colors1[block.get_selector(2, y)]);
+ pDst[3].set_rgb(subblock_colors1[block.get_selector(3, y)]);
+ pDst += 4;
+ }
+ }
+ else
+ {
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ pDst[0].set_rgb(subblock_colors0[block.get_selector(0, y)]);
+ pDst[1].set_rgb(subblock_colors0[block.get_selector(1, y)]);
+ pDst[2].set_rgb(subblock_colors1[block.get_selector(2, y)]);
+ pDst[3].set_rgb(subblock_colors1[block.get_selector(3, y)]);
+ pDst += 4;
+ }
+ }
+ }
+ else
+ {
+ if (flip_flag)
+ {
+ // 0000
+ // 0000
+ // 1111
+ // 1111
+ for (uint32_t y = 0; y < 2; y++)
+ {
+ pDst[0] = subblock_colors0[block.get_selector(0, y)];
+ pDst[1] = subblock_colors0[block.get_selector(1, y)];
+ pDst[2] = subblock_colors0[block.get_selector(2, y)];
+ pDst[3] = subblock_colors0[block.get_selector(3, y)];
+ pDst += 4;
+ }
+
+ for (uint32_t y = 2; y < 4; y++)
+ {
+ pDst[0] = subblock_colors1[block.get_selector(0, y)];
+ pDst[1] = subblock_colors1[block.get_selector(1, y)];
+ pDst[2] = subblock_colors1[block.get_selector(2, y)];
+ pDst[3] = subblock_colors1[block.get_selector(3, y)];
+ pDst += 4;
+ }
+ }
+ else
+ {
+ // 0011
+ // 0011
+ // 0011
+ // 0011
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ pDst[0] = subblock_colors0[block.get_selector(0, y)];
+ pDst[1] = subblock_colors0[block.get_selector(1, y)];
+ pDst[2] = subblock_colors1[block.get_selector(2, y)];
+ pDst[3] = subblock_colors1[block.get_selector(3, y)];
+ pDst += 4;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ inline int extend_6_to_8(uint32_t n)
+ {
+ return (n << 2) | (n >> 4);
+ }
+
+ inline int extend_7_to_8(uint32_t n)
+ {
+ return (n << 1) | (n >> 6);
+ }
+
+ inline int extend_4_to_8(uint32_t n)
+ {
+ return (n << 4) | n;
+ }
+
+ uint64_t etc_block::evaluate_etc1_error(const color_rgba* pBlock_pixels, bool perceptual, int subblock_index) const
+ {
+ color_rgba unpacked_block[16];
+
+ unpack_etc1(*this, unpacked_block);
+
+ uint64_t total_error = 0;
+
+ if (subblock_index < 0)
+ {
+ for (uint32_t i = 0; i < 16; i++)
+ total_error += color_distance(perceptual, pBlock_pixels[i], unpacked_block[i], false);
+ }
+ else
+ {
+ const bool flip_bit = get_flip_bit();
+
+ for (uint32_t i = 0; i < 8; i++)
+ {
+ const uint32_t idx = g_etc1_pixel_indices[flip_bit][subblock_index][i];
+
+ total_error += color_distance(perceptual, pBlock_pixels[idx], unpacked_block[idx], false);
+ }
+ }
+
+ return total_error;
+ }
+
+ void etc_block::get_subblock_pixels(color_rgba* pPixels, int subblock_index) const
+ {
+ if (subblock_index < 0)
+ unpack_etc1(*this, pPixels);
+ else
+ {
+ color_rgba unpacked_block[16];
+
+ unpack_etc1(*this, unpacked_block);
+
+ const bool flip_bit = get_flip_bit();
+
+ for (uint32_t i = 0; i < 8; i++)
+ {
+ const uint32_t idx = g_etc1_pixel_indices[flip_bit][subblock_index][i];
+
+ pPixels[i] = unpacked_block[idx];
+ }
+ }
+ }
+
+ bool etc1_optimizer::compute()
+ {
+ assert(m_pResult->m_pSelectors);
+
+ if ((m_pParams->m_pForce_selectors) || (m_pParams->m_pEval_solution_override))
+ {
+ assert(m_pParams->m_quality >= cETCQualitySlow);
+ }
+
+ const uint32_t n = m_pParams->m_num_src_pixels;
+
+ if (m_pParams->m_cluster_fit)
+ {
+ if (m_pParams->m_quality == cETCQualityFast)
+ compute_internal_cluster_fit(4);
+ else if (m_pParams->m_quality == cETCQualityMedium)
+ compute_internal_cluster_fit(32);
+ else if (m_pParams->m_quality == cETCQualitySlow)
+ compute_internal_cluster_fit(64);
+ else
+ compute_internal_cluster_fit(BASISU_ETC1_CLUSTER_FIT_ORDER_TABLE_SIZE);
+ }
+ else
+ compute_internal_neighborhood(m_br, m_bg, m_bb);
+
+ if (!m_best_solution.m_valid)
+ {
+ m_pResult->m_error = UINT32_MAX;
+ return false;
+ }
+
+ const uint8_t* pSelectors = &m_best_solution.m_selectors[0];
+
+#ifdef BASISU_BUILD_DEBUG
+ if (m_pParams->m_pEval_solution_override == nullptr)
+ {
+ color_rgba block_colors[4];
+ m_best_solution.m_coords.get_block_colors(block_colors);
+
+ const color_rgba* pSrc_pixels = m_pParams->m_pSrc_pixels;
+ uint64_t actual_error = 0;
+ for (uint32_t i = 0; i < n; i++)
+ {
+ if ((m_pParams->m_perceptual) && (m_pParams->m_quality >= cETCQualitySlow))
+ actual_error += color_distance(true, pSrc_pixels[i], block_colors[pSelectors[i]], false);
+ else
+ actual_error += color_distance(pSrc_pixels[i], block_colors[pSelectors[i]], false);
+ }
+ assert(actual_error == m_best_solution.m_error);
+ }
+#endif
+
+ m_pResult->m_error = m_best_solution.m_error;
+
+ m_pResult->m_block_color_unscaled = m_best_solution.m_coords.m_unscaled_color;
+ m_pResult->m_block_color4 = m_best_solution.m_coords.m_color4;
+
+ m_pResult->m_block_inten_table = m_best_solution.m_coords.m_inten_table;
+ memcpy(m_pResult->m_pSelectors, pSelectors, n);
+ m_pResult->m_n = n;
+
+ return true;
+ }
+
+ void etc1_optimizer::refine_solution(uint32_t max_refinement_trials)
+ {
+ // Now we have the input block, the avg. color of the input pixels, a set of trial selector indices, and the block color+intensity index.
+ // Now, for each component, attempt to refine the current solution by solving a simple linear equation. For example, for 4 colors:
+ // The goal is:
+ // pixel0 - (block_color+inten_table[selector0]) + pixel1 - (block_color+inten_table[selector1]) + pixel2 - (block_color+inten_table[selector2]) + pixel3 - (block_color+inten_table[selector3]) = 0
+ // Rearranging this:
+ // (pixel0 + pixel1 + pixel2 + pixel3) - (block_color+inten_table[selector0]) - (block_color+inten_table[selector1]) - (block_color+inten_table[selector2]) - (block_color+inten_table[selector3]) = 0
+ // (pixel0 + pixel1 + pixel2 + pixel3) - block_color - inten_table[selector0] - block_color-inten_table[selector1] - block_color-inten_table[selector2] - block_color-inten_table[selector3] = 0
+ // (pixel0 + pixel1 + pixel2 + pixel3) - 4*block_color - inten_table[selector0] - inten_table[selector1] - inten_table[selector2] - inten_table[selector3] = 0
+ // (pixel0 + pixel1 + pixel2 + pixel3) - 4*block_color - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3]) = 0
+ // (pixel0 + pixel1 + pixel2 + pixel3)/4 - block_color - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3])/4 = 0
+ // block_color = (pixel0 + pixel1 + pixel2 + pixel3)/4 - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3])/4
+ // So what this means:
+ // optimal_block_color = avg_input - avg_inten_delta
+ // So the optimal block color can be computed by taking the average block color and subtracting the current average of the intensity delta.
+ // Unfortunately, optimal_block_color must then be quantized to 555 or 444 so it's not always possible to improve matters using this formula.
+ // Also, the above formula is for unclamped intensity deltas. The actual implementation takes into account clamping.
+
+ const uint32_t n = m_pParams->m_num_src_pixels;
+
+ for (uint32_t refinement_trial = 0; refinement_trial < max_refinement_trials; refinement_trial++)
+ {
+ const uint8_t* pSelectors = &m_best_solution.m_selectors[0];
+ const int* pInten_table = g_etc1_inten_tables[m_best_solution.m_coords.m_inten_table];
+
+ int delta_sum_r = 0, delta_sum_g = 0, delta_sum_b = 0;
+ const color_rgba base_color(m_best_solution.m_coords.get_scaled_color());
+ for (uint32_t r = 0; r < n; r++)
+ {
+ const uint32_t s = *pSelectors++;
+ const int yd_temp = pInten_table[s];
+ // Compute actual delta being applied to each pixel, taking into account clamping.
+ delta_sum_r += clamp<int>(base_color.r + yd_temp, 0, 255) - base_color.r;
+ delta_sum_g += clamp<int>(base_color.g + yd_temp, 0, 255) - base_color.g;
+ delta_sum_b += clamp<int>(base_color.b + yd_temp, 0, 255) - base_color.b;
+ }
+
+ if ((!delta_sum_r) && (!delta_sum_g) && (!delta_sum_b))
+ break;
+
+ const float avg_delta_r_f = static_cast<float>(delta_sum_r) / n;
+ const float avg_delta_g_f = static_cast<float>(delta_sum_g) / n;
+ const float avg_delta_b_f = static_cast<float>(delta_sum_b) / n;
+ const int br1 = clamp<int>(static_cast<uint32_t>((m_avg_color[0] - avg_delta_r_f) * m_limit / 255.0f + .5f), 0, m_limit);
+ const int bg1 = clamp<int>(static_cast<uint32_t>((m_avg_color[1] - avg_delta_g_f) * m_limit / 255.0f + .5f), 0, m_limit);
+ const int bb1 = clamp<int>(static_cast<uint32_t>((m_avg_color[2] - avg_delta_b_f) * m_limit / 255.0f + .5f), 0, m_limit);
+
+#if BASISU_DEBUG_ETC_ENCODER_DEEPER
+ printf("Refinement trial %u, avg_delta %f %f %f\n", refinement_trial, avg_delta_r_f, avg_delta_g_f, avg_delta_b_f);
+#endif
+
+ if (!evaluate_solution(etc1_solution_coordinates(br1, bg1, bb1, 0, m_pParams->m_use_color4), m_trial_solution, &m_best_solution))
+ break;
+
+ } // refinement_trial
+ }
+
+ void etc1_optimizer::compute_internal_neighborhood(int scan_r, int scan_g, int scan_b)
+ {
+ if (m_best_solution.m_error == 0)
+ return;
+
+ const uint32_t n = m_pParams->m_num_src_pixels;
+ const int scan_delta_size = m_pParams->m_scan_delta_size;
+
+ // Scan through a subset of the 3D lattice centered around the avg block color trying each 3D (555 or 444) lattice point as a potential block color.
+ // Each time a better solution is found try to refine the current solution's block color based of the current selectors and intensity table index.
+ for (int zdi = 0; zdi < scan_delta_size; zdi++)
+ {
+ const int zd = m_pParams->m_pScan_deltas[zdi];
+ const int mbb = scan_b + zd;
+ if (mbb < 0) continue; else if (mbb > m_limit) break;
+
+ for (int ydi = 0; ydi < scan_delta_size; ydi++)
+ {
+ const int yd = m_pParams->m_pScan_deltas[ydi];
+ const int mbg = scan_g + yd;
+ if (mbg < 0) continue; else if (mbg > m_limit) break;
+
+ for (int xdi = 0; xdi < scan_delta_size; xdi++)
+ {
+ const int xd = m_pParams->m_pScan_deltas[xdi];
+ const int mbr = scan_r + xd;
+ if (mbr < 0) continue; else if (mbr > m_limit) break;
+
+ etc1_solution_coordinates coords(mbr, mbg, mbb, 0, m_pParams->m_use_color4);
+
+ if (!evaluate_solution(coords, m_trial_solution, &m_best_solution))
+ continue;
+
+ if (m_pParams->m_refinement)
+ {
+ refine_solution((m_pParams->m_quality == cETCQualityFast) ? 2 : (((xd | yd | zd) == 0) ? 4 : 2));
+ }
+
+ } // xdi
+ } // ydi
+ } // zdi
+ }
+
+ void etc1_optimizer::compute_internal_cluster_fit(uint32_t total_perms_to_try)
+ {
+ if ((!m_best_solution.m_valid) || ((m_br != m_best_solution.m_coords.m_unscaled_color.r) || (m_bg != m_best_solution.m_coords.m_unscaled_color.g) || (m_bb != m_best_solution.m_coords.m_unscaled_color.b)))
+ {
+ evaluate_solution(etc1_solution_coordinates(m_br, m_bg, m_bb, 0, m_pParams->m_use_color4), m_trial_solution, &m_best_solution);
+ }
+
+ if ((m_best_solution.m_error == 0) || (!m_best_solution.m_valid))
+ return;
+
+ for (uint32_t i = 0; i < total_perms_to_try; i++)
+ {
+ int delta_sum_r = 0, delta_sum_g = 0, delta_sum_b = 0;
+
+ const int *pInten_table = g_etc1_inten_tables[m_best_solution.m_coords.m_inten_table];
+ const color_rgba base_color(m_best_solution.m_coords.get_scaled_color());
+
+ const uint8_t *pNum_selectors = g_cluster_fit_order_tab[i].m_v;
+
+ for (uint32_t q = 0; q < 4; q++)
+ {
+ const int yd_temp = pInten_table[q];
+
+ delta_sum_r += pNum_selectors[q] * (clamp<int>(base_color.r + yd_temp, 0, 255) - base_color.r);
+ delta_sum_g += pNum_selectors[q] * (clamp<int>(base_color.g + yd_temp, 0, 255) - base_color.g);
+ delta_sum_b += pNum_selectors[q] * (clamp<int>(base_color.b + yd_temp, 0, 255) - base_color.b);
+ }
+
+ if ((!delta_sum_r) && (!delta_sum_g) && (!delta_sum_b))
+ continue;
+
+ const float avg_delta_r_f = static_cast<float>(delta_sum_r) / 8;
+ const float avg_delta_g_f = static_cast<float>(delta_sum_g) / 8;
+ const float avg_delta_b_f = static_cast<float>(delta_sum_b) / 8;
+
+ const int br1 = clamp<int>(static_cast<uint32_t>((m_avg_color[0] - avg_delta_r_f) * m_limit / 255.0f + .5f), 0, m_limit);
+ const int bg1 = clamp<int>(static_cast<uint32_t>((m_avg_color[1] - avg_delta_g_f) * m_limit / 255.0f + .5f), 0, m_limit);
+ const int bb1 = clamp<int>(static_cast<uint32_t>((m_avg_color[2] - avg_delta_b_f) * m_limit / 255.0f + .5f), 0, m_limit);
+
+#if BASISU_DEBUG_ETC_ENCODER_DEEPER
+ printf("Second refinement trial %u, avg_delta %f %f %f\n", i, avg_delta_r_f, avg_delta_g_f, avg_delta_b_f);
+#endif
+
+ evaluate_solution(etc1_solution_coordinates(br1, bg1, bb1, 0, m_pParams->m_use_color4), m_trial_solution, &m_best_solution);
+
+ if (m_best_solution.m_error == 0)
+ break;
+ }
+ }
+
+ void etc1_optimizer::init(const params& params, results& result)
+ {
+ m_pParams = &params;
+ m_pResult = &result;
+
+ const uint32_t n = m_pParams->m_num_src_pixels;
+
+ m_selectors.resize(n);
+ m_best_selectors.resize(n);
+ m_temp_selectors.resize(n);
+ m_trial_solution.m_selectors.resize(n);
+ m_best_solution.m_selectors.resize(n);
+
+ m_limit = m_pParams->m_use_color4 ? 15 : 31;
+
+ vec3F avg_color(0.0f);
+
+ m_luma.resize(n);
+ m_sorted_luma_indices.resize(n);
+ m_sorted_luma.resize(n);
+
+ for (uint32_t i = 0; i < n; i++)
+ {
+ const color_rgba& c = m_pParams->m_pSrc_pixels[i];
+ const vec3F fc(c.r, c.g, c.b);
+
+ avg_color += fc;
+
+ m_luma[i] = static_cast<uint16_t>(c.r + c.g + c.b);
+ m_sorted_luma_indices[i] = i;
+ }
+ avg_color /= static_cast<float>(n);
+ m_avg_color = avg_color;
+
+ m_br = clamp<int>(static_cast<uint32_t>(m_avg_color[0] * m_limit / 255.0f + .5f), 0, m_limit);
+ m_bg = clamp<int>(static_cast<uint32_t>(m_avg_color[1] * m_limit / 255.0f + .5f), 0, m_limit);
+ m_bb = clamp<int>(static_cast<uint32_t>(m_avg_color[2] * m_limit / 255.0f + .5f), 0, m_limit);
+
+#if BASISU_DEBUG_ETC_ENCODER_DEEPER
+ printf("Avg block color: %u %u %u\n", m_br, m_bg, m_bb);
+#endif
+
+ if (m_pParams->m_quality <= cETCQualityMedium)
+ {
+ indirect_sort(n, &m_sorted_luma_indices[0], &m_luma[0]);
+
+ m_pSorted_luma = &m_sorted_luma[0];
+ m_pSorted_luma_indices = &m_sorted_luma_indices[0];
+
+ for (uint32_t i = 0; i < n; i++)
+ m_pSorted_luma[i] = m_luma[m_pSorted_luma_indices[i]];
+ }
+
+ m_best_solution.m_coords.clear();
+ m_best_solution.m_valid = false;
+ m_best_solution.m_error = UINT64_MAX;
+
+ m_solutions_tried.clear();
+ }
+
+ bool etc1_optimizer::evaluate_solution_slow(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution)
+ {
+ uint32_t k = coords.m_unscaled_color.r | (coords.m_unscaled_color.g << 8) | (coords.m_unscaled_color.b << 16);
+ if (!m_solutions_tried.insert(k).second)
+ return false;
+
+#if BASISU_DEBUG_ETC_ENCODER_DEEPER
+ printf("Eval solution: %u %u %u\n", coords.m_unscaled_color.r, coords.m_unscaled_color.g, coords.m_unscaled_color.b);
+#endif
+
+ trial_solution.m_valid = false;
+
+ if (m_pParams->m_constrain_against_base_color5)
+ {
+ const int dr = (int)coords.m_unscaled_color.r - (int)m_pParams->m_base_color5.r;
+ const int dg = (int)coords.m_unscaled_color.g - (int)m_pParams->m_base_color5.g;
+ const int db = (int)coords.m_unscaled_color.b - (int)m_pParams->m_base_color5.b;
+
+ if ((minimum(dr, dg, db) < cETC1ColorDeltaMin) || (maximum(dr, dg, db) > cETC1ColorDeltaMax))
+ {
+#if BASISU_DEBUG_ETC_ENCODER_DEEPER
+ printf("Eval failed due to constraint from %u %u %u\n", m_pParams->m_base_color5.r, m_pParams->m_base_color5.g, m_pParams->m_base_color5.b);
+#endif
+ return false;
+ }
+ }
+
+ const color_rgba base_color(coords.get_scaled_color());
+
+ const uint32_t n = m_pParams->m_num_src_pixels;
+ assert(trial_solution.m_selectors.size() == n);
+
+ trial_solution.m_error = UINT64_MAX;
+
+ const uint8_t *pSelectors_to_use = m_pParams->m_pForce_selectors;
+
+ for (uint32_t inten_table = 0; inten_table < cETC1IntenModifierValues; inten_table++)
+ {
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ color_rgba block_colors[4];
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ const int yd = pInten_table[s];
+ block_colors[s].set(base_color.r + yd, base_color.g + yd, base_color.b + yd, 255);
+ }
+
+ uint64_t total_error = 0;
+
+ const color_rgba* pSrc_pixels = m_pParams->m_pSrc_pixels;
+ for (uint32_t c = 0; c < n; c++)
+ {
+ const color_rgba& src_pixel = *pSrc_pixels++;
+
+ uint32_t best_selector_index = 0;
+ uint32_t best_error = 0;
+
+ if (pSelectors_to_use)
+ {
+ best_selector_index = pSelectors_to_use[c];
+ best_error = color_distance(m_pParams->m_perceptual, src_pixel, block_colors[best_selector_index], false);
+ }
+ else
+ {
+ best_error = color_distance(m_pParams->m_perceptual, src_pixel, block_colors[0], false);
+
+ uint32_t trial_error = color_distance(m_pParams->m_perceptual, src_pixel, block_colors[1], false);
+ if (trial_error < best_error)
+ {
+ best_error = trial_error;
+ best_selector_index = 1;
+ }
+
+ trial_error = color_distance(m_pParams->m_perceptual, src_pixel, block_colors[2], false);
+ if (trial_error < best_error)
+ {
+ best_error = trial_error;
+ best_selector_index = 2;
+ }
+
+ trial_error = color_distance(m_pParams->m_perceptual, src_pixel, block_colors[3], false);
+ if (trial_error < best_error)
+ {
+ best_error = trial_error;
+ best_selector_index = 3;
+ }
+ }
+
+ m_temp_selectors[c] = static_cast<uint8_t>(best_selector_index);
+
+ total_error += best_error;
+ if ((m_pParams->m_pEval_solution_override == nullptr) && (total_error >= trial_solution.m_error))
+ break;
+ }
+
+ if (m_pParams->m_pEval_solution_override)
+ {
+ if (!(*m_pParams->m_pEval_solution_override)(total_error, *m_pParams, block_colors, &m_temp_selectors[0], coords))
+ return false;
+ }
+
+ if (total_error < trial_solution.m_error)
+ {
+ trial_solution.m_error = total_error;
+ trial_solution.m_coords.m_inten_table = inten_table;
+ trial_solution.m_selectors.swap(m_temp_selectors);
+ trial_solution.m_valid = true;
+ }
+ }
+ trial_solution.m_coords.m_unscaled_color = coords.m_unscaled_color;
+ trial_solution.m_coords.m_color4 = m_pParams->m_use_color4;
+
+#if BASISU_DEBUG_ETC_ENCODER_DEEPER
+ printf("Eval done: %u error: %I64u best error so far: %I64u\n", (trial_solution.m_error < pBest_solution->m_error), trial_solution.m_error, pBest_solution->m_error);
+#endif
+
+ bool success = false;
+ if (pBest_solution)
+ {
+ if (trial_solution.m_error < pBest_solution->m_error)
+ {
+ *pBest_solution = trial_solution;
+ success = true;
+ }
+ }
+
+ return success;
+ }
+
+ bool etc1_optimizer::evaluate_solution_fast(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution)
+ {
+ uint32_t k = coords.m_unscaled_color.r | (coords.m_unscaled_color.g << 8) | (coords.m_unscaled_color.b << 16);
+ if (!m_solutions_tried.insert(k).second)
+ return false;
+
+#if BASISU_DEBUG_ETC_ENCODER_DEEPER
+ printf("Eval solution fast: %u %u %u\n", coords.m_unscaled_color.r, coords.m_unscaled_color.g, coords.m_unscaled_color.b);
+#endif
+
+ if (m_pParams->m_constrain_against_base_color5)
+ {
+ const int dr = (int)coords.m_unscaled_color.r - (int)m_pParams->m_base_color5.r;
+ const int dg = (int)coords.m_unscaled_color.g - (int)m_pParams->m_base_color5.g;
+ const int db = (int)coords.m_unscaled_color.b - (int)m_pParams->m_base_color5.b;
+
+ if ((minimum(dr, dg, db) < cETC1ColorDeltaMin) || (maximum(dr, dg, db) > cETC1ColorDeltaMax))
+ {
+ trial_solution.m_valid = false;
+
+#if BASISU_DEBUG_ETC_ENCODER_DEEPER
+ printf("Eval failed due to constraint from %u %u %u\n", m_pParams->m_base_color5.r, m_pParams->m_base_color5.g, m_pParams->m_base_color5.b);
+#endif
+ return false;
+ }
+ }
+
+ const color_rgba base_color(coords.get_scaled_color());
+
+ const uint32_t n = m_pParams->m_num_src_pixels;
+ assert(trial_solution.m_selectors.size() == n);
+
+ trial_solution.m_error = UINT64_MAX;
+
+ for (int inten_table = cETC1IntenModifierValues - 1; inten_table >= 0; --inten_table)
+ {
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ uint32_t block_inten[4];
+ color_rgba block_colors[4];
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ const int yd = pInten_table[s];
+ color_rgba block_color(base_color.r + yd, base_color.g + yd, base_color.b + yd, 255);
+ block_colors[s] = block_color;
+ block_inten[s] = block_color.r + block_color.g + block_color.b;
+ }
+
+ // evaluate_solution_fast() enforces/assumesd a total ordering of the input colors along the intensity (1,1,1) axis to more quickly classify the inputs to selectors.
+ // The inputs colors have been presorted along the projection onto this axis, and ETC1 block colors are always ordered along the intensity axis, so this classification is fast.
+ // 0 1 2 3
+ // 01 12 23
+ const uint32_t block_inten_midpoints[3] = { block_inten[0] + block_inten[1], block_inten[1] + block_inten[2], block_inten[2] + block_inten[3] };
+
+ uint64_t total_error = 0;
+ const color_rgba* pSrc_pixels = m_pParams->m_pSrc_pixels;
+ if ((m_pSorted_luma[n - 1] * 2) < block_inten_midpoints[0])
+ {
+ if (block_inten[0] > m_pSorted_luma[n - 1])
+ {
+ const uint32_t min_error = iabs((int)block_inten[0] - (int)m_pSorted_luma[n - 1]);
+ if (min_error >= trial_solution.m_error)
+ continue;
+ }
+
+ memset(&m_temp_selectors[0], 0, n);
+
+ for (uint32_t c = 0; c < n; c++)
+ total_error += color_distance(block_colors[0], pSrc_pixels[c], false);
+ }
+ else if ((m_pSorted_luma[0] * 2) >= block_inten_midpoints[2])
+ {
+ if (m_pSorted_luma[0] > block_inten[3])
+ {
+ const uint32_t min_error = iabs((int)m_pSorted_luma[0] - (int)block_inten[3]);
+ if (min_error >= trial_solution.m_error)
+ continue;
+ }
+
+ memset(&m_temp_selectors[0], 3, n);
+
+ for (uint32_t c = 0; c < n; c++)
+ total_error += color_distance(block_colors[3], pSrc_pixels[c], false);
+ }
+ else
+ {
+ uint32_t cur_selector = 0, c;
+ for (c = 0; c < n; c++)
+ {
+ const uint32_t y = m_pSorted_luma[c];
+ while ((y * 2) >= block_inten_midpoints[cur_selector])
+ if (++cur_selector > 2)
+ goto done;
+ const uint32_t sorted_pixel_index = m_pSorted_luma_indices[c];
+ m_temp_selectors[sorted_pixel_index] = static_cast<uint8_t>(cur_selector);
+ total_error += color_distance(block_colors[cur_selector], pSrc_pixels[sorted_pixel_index], false);
+ }
+ done:
+ while (c < n)
+ {
+ const uint32_t sorted_pixel_index = m_pSorted_luma_indices[c];
+ m_temp_selectors[sorted_pixel_index] = 3;
+ total_error += color_distance(block_colors[3], pSrc_pixels[sorted_pixel_index], false);
+ ++c;
+ }
+ }
+
+ if (total_error < trial_solution.m_error)
+ {
+ trial_solution.m_error = total_error;
+ trial_solution.m_coords.m_inten_table = inten_table;
+ trial_solution.m_selectors.swap(m_temp_selectors);
+ trial_solution.m_valid = true;
+ if (!total_error)
+ break;
+ }
+ }
+ trial_solution.m_coords.m_unscaled_color = coords.m_unscaled_color;
+ trial_solution.m_coords.m_color4 = m_pParams->m_use_color4;
+
+#if BASISU_DEBUG_ETC_ENCODER_DEEPER
+ printf("Eval done: %u error: %I64u best error so far: %I64u\n", (trial_solution.m_error < pBest_solution->m_error), trial_solution.m_error, pBest_solution->m_error);
+#endif
+
+ bool success = false;
+ if (pBest_solution)
+ {
+ if (trial_solution.m_error < pBest_solution->m_error)
+ {
+ *pBest_solution = trial_solution;
+ success = true;
+ }
+ }
+
+ return success;
+ }
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_etc.h b/thirdparty/basis_universal/basisu_etc.h
new file mode 100644
index 0000000000..a202d01f6e
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_etc.h
@@ -0,0 +1,1046 @@
+// basis_etc.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "transcoder/basisu.h"
+#include "basisu_enc.h"
+#include <set>
+
+namespace basisu
+{
+ enum etc_constants
+ {
+ cETC1BytesPerBlock = 8U,
+
+ cETC1SelectorBits = 2U,
+ cETC1SelectorValues = 1U << cETC1SelectorBits,
+ cETC1SelectorMask = cETC1SelectorValues - 1U,
+
+ cETC1BlockShift = 2U,
+ cETC1BlockSize = 1U << cETC1BlockShift,
+
+ cETC1LSBSelectorIndicesBitOffset = 0,
+ cETC1MSBSelectorIndicesBitOffset = 16,
+
+ cETC1FlipBitOffset = 32,
+ cETC1DiffBitOffset = 33,
+
+ cETC1IntenModifierNumBits = 3,
+ cETC1IntenModifierValues = 1 << cETC1IntenModifierNumBits,
+ cETC1RightIntenModifierTableBitOffset = 34,
+ cETC1LeftIntenModifierTableBitOffset = 37,
+
+ // Base+Delta encoding (5 bit bases, 3 bit delta)
+ cETC1BaseColorCompNumBits = 5,
+ cETC1BaseColorCompMax = 1 << cETC1BaseColorCompNumBits,
+
+ cETC1DeltaColorCompNumBits = 3,
+ cETC1DeltaColorComp = 1 << cETC1DeltaColorCompNumBits,
+ cETC1DeltaColorCompMax = 1 << cETC1DeltaColorCompNumBits,
+
+ cETC1BaseColor5RBitOffset = 59,
+ cETC1BaseColor5GBitOffset = 51,
+ cETC1BaseColor5BBitOffset = 43,
+
+ cETC1DeltaColor3RBitOffset = 56,
+ cETC1DeltaColor3GBitOffset = 48,
+ cETC1DeltaColor3BBitOffset = 40,
+
+ // Absolute (non-delta) encoding (two 4-bit per component bases)
+ cETC1AbsColorCompNumBits = 4,
+ cETC1AbsColorCompMax = 1 << cETC1AbsColorCompNumBits,
+
+ cETC1AbsColor4R1BitOffset = 60,
+ cETC1AbsColor4G1BitOffset = 52,
+ cETC1AbsColor4B1BitOffset = 44,
+
+ cETC1AbsColor4R2BitOffset = 56,
+ cETC1AbsColor4G2BitOffset = 48,
+ cETC1AbsColor4B2BitOffset = 40,
+
+ cETC1ColorDeltaMin = -4,
+ cETC1ColorDeltaMax = 3,
+
+ // Delta3:
+ // 0 1 2 3 4 5 6 7
+ // 000 001 010 011 100 101 110 111
+ // 0 1 2 3 -4 -3 -2 -1
+ };
+
+ extern const int g_etc1_inten_tables[cETC1IntenModifierValues][cETC1SelectorValues];
+ extern const uint8_t g_etc1_to_selector_index[cETC1SelectorValues];
+ extern const uint8_t g_selector_index_to_etc1[cETC1SelectorValues];
+
+ struct etc_coord2
+ {
+ uint8_t m_x, m_y;
+ };
+ extern const etc_coord2 g_etc1_pixel_coords[2][2][8]; // [flipped][subblock][subblock_pixel]
+ extern const uint32_t g_etc1_pixel_indices[2][2][8]; // [flipped][subblock][subblock_pixel]
+
+ struct etc_block
+ {
+ // big endian uint64:
+ // bit ofs: 56 48 40 32 24 16 8 0
+ // byte ofs: b0, b1, b2, b3, b4, b5, b6, b7
+ union
+ {
+ uint64_t m_uint64;
+
+ uint8_t m_bytes[8];
+ };
+
+ inline void clear()
+ {
+ assert(sizeof(*this) == 8);
+ clear_obj(*this);
+ }
+
+ inline uint64_t get_all_bits() const
+ {
+ return read_be64(&m_uint64);
+ }
+
+ inline uint32_t get_general_bits(uint32_t ofs, uint32_t num) const
+ {
+ assert((ofs + num) <= 64U);
+ assert(num && (num < 32U));
+ return (read_be64(&m_uint64) >> ofs) & ((1UL << num) - 1UL);
+ }
+
+ inline void set_general_bits(uint32_t ofs, uint32_t num, uint32_t bits)
+ {
+ assert((ofs + num) <= 64U);
+ assert(num && (num < 32U));
+
+ uint64_t x = read_be64(&m_uint64);
+ uint64_t msk = ((1ULL << static_cast<uint64_t>(num)) - 1ULL) << static_cast<uint64_t>(ofs);
+ x &= ~msk;
+ x |= (static_cast<uint64_t>(bits) << static_cast<uint64_t>(ofs));
+ write_be64(&m_uint64, x);
+ }
+
+ inline uint32_t get_byte_bits(uint32_t ofs, uint32_t num) const
+ {
+ assert((ofs + num) <= 64U);
+ assert(num && (num <= 8U));
+ assert((ofs >> 3) == ((ofs + num - 1) >> 3));
+ const uint32_t byte_ofs = 7 - (ofs >> 3);
+ const uint32_t byte_bit_ofs = ofs & 7;
+ return (m_bytes[byte_ofs] >> byte_bit_ofs) & ((1 << num) - 1);
+ }
+
+ inline void set_byte_bits(uint32_t ofs, uint32_t num, uint32_t bits)
+ {
+ assert((ofs + num) <= 64U);
+ assert(num && (num < 32U));
+ assert((ofs >> 3) == ((ofs + num - 1) >> 3));
+ assert(bits < (1U << num));
+ const uint32_t byte_ofs = 7 - (ofs >> 3);
+ const uint32_t byte_bit_ofs = ofs & 7;
+ const uint32_t mask = (1 << num) - 1;
+ m_bytes[byte_ofs] &= ~(mask << byte_bit_ofs);
+ m_bytes[byte_ofs] |= (bits << byte_bit_ofs);
+ }
+
+ // false = left/right subblocks
+ // true = upper/lower subblocks
+ inline bool get_flip_bit() const
+ {
+ return (m_bytes[3] & 1) != 0;
+ }
+
+ inline void set_flip_bit(bool flip)
+ {
+ m_bytes[3] &= ~1;
+ m_bytes[3] |= static_cast<uint8_t>(flip);
+ }
+
+ inline bool get_diff_bit() const
+ {
+ return (m_bytes[3] & 2) != 0;
+ }
+
+ inline void set_diff_bit(bool diff)
+ {
+ m_bytes[3] &= ~2;
+ m_bytes[3] |= (static_cast<uint32_t>(diff) << 1);
+ }
+
+ // Returns intensity modifier table (0-7) used by subblock subblock_id.
+ // subblock_id=0 left/top (CW 1), 1=right/bottom (CW 2)
+ inline uint32_t get_inten_table(uint32_t subblock_id) const
+ {
+ assert(subblock_id < 2);
+ const uint32_t ofs = subblock_id ? 2 : 5;
+ return (m_bytes[3] >> ofs) & 7;
+ }
+
+ // Sets intensity modifier table (0-7) used by subblock subblock_id (0 or 1)
+ inline void set_inten_table(uint32_t subblock_id, uint32_t t)
+ {
+ assert(subblock_id < 2);
+ assert(t < 8);
+ const uint32_t ofs = subblock_id ? 2 : 5;
+ m_bytes[3] &= ~(7 << ofs);
+ m_bytes[3] |= (t << ofs);
+ }
+
+ inline void set_inten_tables_etc1s(uint32_t t)
+ {
+ set_inten_table(0, t);
+ set_inten_table(1, t);
+ }
+
+ inline bool is_etc1s() const
+ {
+ if (get_inten_table(0) != get_inten_table(1))
+ return false;
+
+ if (get_diff_bit())
+ {
+ if (get_delta3_color() != 0)
+ return false;
+ }
+ else
+ {
+ if (get_base4_color(0) != get_base4_color(1))
+ return false;
+ }
+
+ return true;
+ }
+
+ // Returned encoded selector value ranges from 0-3 (this is NOT a direct index into g_etc1_inten_tables, see get_selector())
+ inline uint32_t get_raw_selector(uint32_t x, uint32_t y) const
+ {
+ assert((x | y) < 4);
+
+ const uint32_t bit_index = x * 4 + y;
+ const uint32_t byte_bit_ofs = bit_index & 7;
+ const uint8_t *p = &m_bytes[7 - (bit_index >> 3)];
+ const uint32_t lsb = (p[0] >> byte_bit_ofs) & 1;
+ const uint32_t msb = (p[-2] >> byte_bit_ofs) & 1;
+ const uint32_t val = lsb | (msb << 1);
+
+ return val;
+ }
+
+ // Returned selector value ranges from 0-3 and is a direct index into g_etc1_inten_tables.
+ inline uint32_t get_selector(uint32_t x, uint32_t y) const
+ {
+ return g_etc1_to_selector_index[get_raw_selector(x, y)];
+ }
+
+ // Selector "val" ranges from 0-3 and is a direct index into g_etc1_inten_tables.
+ inline void set_selector(uint32_t x, uint32_t y, uint32_t val)
+ {
+ assert((x | y | val) < 4);
+ const uint32_t bit_index = x * 4 + y;
+
+ uint8_t *p = &m_bytes[7 - (bit_index >> 3)];
+
+ const uint32_t byte_bit_ofs = bit_index & 7;
+ const uint32_t mask = 1 << byte_bit_ofs;
+
+ const uint32_t etc1_val = g_selector_index_to_etc1[val];
+
+ const uint32_t lsb = etc1_val & 1;
+ const uint32_t msb = etc1_val >> 1;
+
+ p[0] &= ~mask;
+ p[0] |= (lsb << byte_bit_ofs);
+
+ p[-2] &= ~mask;
+ p[-2] |= (msb << byte_bit_ofs);
+ }
+
+ inline uint32_t get_raw_selector_bits() const
+ {
+ return m_bytes[4] | (m_bytes[5] << 8) | (m_bytes[6] << 16) | (m_bytes[7] << 24);
+ }
+
+ inline void set_raw_selector_bits(uint32_t bits)
+ {
+ m_bytes[4] = static_cast<uint8_t>(bits);
+ m_bytes[5] = static_cast<uint8_t>(bits >> 8);
+ m_bytes[6] = static_cast<uint8_t>(bits >> 16);
+ m_bytes[7] = static_cast<uint8_t>(bits >> 24);
+ }
+
+ inline void set_raw_selector_bits(uint8_t byte0, uint8_t byte1, uint8_t byte2, uint8_t byte3)
+ {
+ m_bytes[4] = byte0;
+ m_bytes[5] = byte1;
+ m_bytes[6] = byte2;
+ m_bytes[7] = byte3;
+ }
+
+ inline void set_base4_color(uint32_t idx, uint16_t c)
+ {
+ if (idx)
+ {
+ set_byte_bits(cETC1AbsColor4R2BitOffset, 4, (c >> 8) & 15);
+ set_byte_bits(cETC1AbsColor4G2BitOffset, 4, (c >> 4) & 15);
+ set_byte_bits(cETC1AbsColor4B2BitOffset, 4, c & 15);
+ }
+ else
+ {
+ set_byte_bits(cETC1AbsColor4R1BitOffset, 4, (c >> 8) & 15);
+ set_byte_bits(cETC1AbsColor4G1BitOffset, 4, (c >> 4) & 15);
+ set_byte_bits(cETC1AbsColor4B1BitOffset, 4, c & 15);
+ }
+ }
+
+ inline uint16_t get_base4_color(uint32_t idx) const
+ {
+ uint32_t r, g, b;
+ if (idx)
+ {
+ r = get_byte_bits(cETC1AbsColor4R2BitOffset, 4);
+ g = get_byte_bits(cETC1AbsColor4G2BitOffset, 4);
+ b = get_byte_bits(cETC1AbsColor4B2BitOffset, 4);
+ }
+ else
+ {
+ r = get_byte_bits(cETC1AbsColor4R1BitOffset, 4);
+ g = get_byte_bits(cETC1AbsColor4G1BitOffset, 4);
+ b = get_byte_bits(cETC1AbsColor4B1BitOffset, 4);
+ }
+ return static_cast<uint16_t>(b | (g << 4U) | (r << 8U));
+ }
+
+ inline void set_base5_color(uint16_t c)
+ {
+ set_byte_bits(cETC1BaseColor5RBitOffset, 5, (c >> 10) & 31);
+ set_byte_bits(cETC1BaseColor5GBitOffset, 5, (c >> 5) & 31);
+ set_byte_bits(cETC1BaseColor5BBitOffset, 5, c & 31);
+ }
+
+ inline uint16_t get_base5_color() const
+ {
+ const uint32_t r = get_byte_bits(cETC1BaseColor5RBitOffset, 5);
+ const uint32_t g = get_byte_bits(cETC1BaseColor5GBitOffset, 5);
+ const uint32_t b = get_byte_bits(cETC1BaseColor5BBitOffset, 5);
+ return static_cast<uint16_t>(b | (g << 5U) | (r << 10U));
+ }
+
+ void set_delta3_color(uint16_t c)
+ {
+ set_byte_bits(cETC1DeltaColor3RBitOffset, 3, (c >> 6) & 7);
+ set_byte_bits(cETC1DeltaColor3GBitOffset, 3, (c >> 3) & 7);
+ set_byte_bits(cETC1DeltaColor3BBitOffset, 3, c & 7);
+ }
+
+ inline uint16_t get_delta3_color() const
+ {
+ const uint32_t r = get_byte_bits(cETC1DeltaColor3RBitOffset, 3);
+ const uint32_t g = get_byte_bits(cETC1DeltaColor3GBitOffset, 3);
+ const uint32_t b = get_byte_bits(cETC1DeltaColor3BBitOffset, 3);
+ return static_cast<uint16_t>(b | (g << 3U) | (r << 6U));
+ }
+
+ uint64_t determine_selectors(const color_rgba* pSource_pixels, bool perceptual, uint32_t begin_subblock = 0, uint32_t end_subblock = 2)
+ {
+ uint64_t total_error = 0;
+
+ for (uint32_t subblock = begin_subblock; subblock < end_subblock; subblock++)
+ {
+ color_rgba block_colors[4];
+ get_block_colors(block_colors, subblock);
+
+ if (get_flip_bit())
+ {
+ for (uint32_t y = 0; y < 2; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t best_selector = 0;
+ uint64_t best_error = UINT64_MAX;
+
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ uint64_t err = color_distance(perceptual, block_colors[s], pSource_pixels[x + (subblock * 2 + y) * 4], false);
+ if (err < best_error)
+ {
+ best_error = err;
+ best_selector = s;
+ }
+ }
+
+ set_selector(x, subblock * 2 + y, best_selector);
+
+ total_error += best_error;
+ }
+ }
+ }
+ else
+ {
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 2; x++)
+ {
+ uint32_t best_selector = 0;
+ uint64_t best_error = UINT64_MAX;
+
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ uint64_t err = color_distance(perceptual, block_colors[s], pSource_pixels[(subblock * 2) + x + y * 4], false);
+ if (err < best_error)
+ {
+ best_error = err;
+ best_selector = s;
+ }
+ }
+
+ set_selector(subblock * 2 + x, y, best_selector);
+
+ total_error += best_error;
+ }
+ }
+ }
+ }
+
+ return total_error;
+ }
+
+ color_rgba get_block_color(uint32_t subblock_index, bool scaled) const
+ {
+ color_rgba b;
+
+ if (get_diff_bit())
+ {
+ if (subblock_index)
+ unpack_color5(b, get_base5_color(), get_delta3_color(), scaled);
+ else
+ unpack_color5(b, get_base5_color(), scaled);
+ }
+ else
+ {
+ b = unpack_color4(get_base4_color(subblock_index), scaled);
+ }
+
+ return b;
+ }
+
+ uint32_t get_subblock_index(uint32_t x, uint32_t y) const
+ {
+ if (get_flip_bit())
+ return y >= 2;
+ else
+ return x >= 2;
+ }
+
+ bool get_block_colors(color_rgba* pBlock_colors, uint32_t subblock_index) const
+ {
+ color_rgba b;
+
+ if (get_diff_bit())
+ {
+ if (subblock_index)
+ unpack_color5(b, get_base5_color(), get_delta3_color(), true);
+ else
+ unpack_color5(b, get_base5_color(), true);
+ }
+ else
+ {
+ b = unpack_color4(get_base4_color(subblock_index), true);
+ }
+
+ const int* pInten_table = g_etc1_inten_tables[get_inten_table(subblock_index)];
+
+ bool dc = false;
+
+ pBlock_colors[0].set(clamp255(b.r + pInten_table[0], dc), clamp255(b.g + pInten_table[0], dc), clamp255(b.b + pInten_table[0], dc), 255);
+ pBlock_colors[1].set(clamp255(b.r + pInten_table[1], dc), clamp255(b.g + pInten_table[1], dc), clamp255(b.b + pInten_table[1], dc), 255);
+ pBlock_colors[2].set(clamp255(b.r + pInten_table[2], dc), clamp255(b.g + pInten_table[2], dc), clamp255(b.b + pInten_table[2], dc), 255);
+ pBlock_colors[3].set(clamp255(b.r + pInten_table[3], dc), clamp255(b.g + pInten_table[3], dc), clamp255(b.b + pInten_table[3], dc), 255);
+
+ return dc;
+ }
+
+ void get_block_color(color_rgba& color, uint32_t subblock_index, uint32_t selector_index) const
+ {
+ color_rgba b;
+
+ if (get_diff_bit())
+ {
+ if (subblock_index)
+ unpack_color5(b, get_base5_color(), get_delta3_color(), true);
+ else
+ unpack_color5(b, get_base5_color(), true);
+ }
+ else
+ {
+ b = unpack_color4(get_base4_color(subblock_index), true);
+ }
+
+ const int* pInten_table = g_etc1_inten_tables[get_inten_table(subblock_index)];
+
+ color.set(clamp255(b.r + pInten_table[selector_index]), clamp255(b.g + pInten_table[selector_index]), clamp255(b.b + pInten_table[selector_index]), 255);
+ }
+
+ bool get_block_low_high_colors(color_rgba* pBlock_colors, uint32_t subblock_index) const
+ {
+ color_rgba b;
+
+ if (get_diff_bit())
+ {
+ if (subblock_index)
+ unpack_color5(b, get_base5_color(), get_delta3_color(), true);
+ else
+ unpack_color5(b, get_base5_color(), true);
+ }
+ else
+ {
+ b = unpack_color4(get_base4_color(subblock_index), true);
+ }
+
+ const int* pInten_table = g_etc1_inten_tables[get_inten_table(subblock_index)];
+
+ bool dc = false;
+
+ pBlock_colors[0].set(clamp255(b.r + pInten_table[0], dc), clamp255(b.g + pInten_table[0], dc), clamp255(b.b + pInten_table[0], dc), 255);
+ pBlock_colors[1].set(clamp255(b.r + pInten_table[3], dc), clamp255(b.g + pInten_table[3], dc), clamp255(b.b + pInten_table[3], dc), 255);
+
+ return dc;
+ }
+
+ static void get_block_colors5(color_rgba *pBlock_colors, const color_rgba &base_color5, uint32_t inten_table, bool scaled = false)
+ {
+ color_rgba b(base_color5);
+
+ if (!scaled)
+ {
+ b.r = (b.r << 3) | (b.r >> 2);
+ b.g = (b.g << 3) | (b.g >> 2);
+ b.b = (b.b << 3) | (b.b >> 2);
+ }
+
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ pBlock_colors[0].set(clamp255(b.r + pInten_table[0]), clamp255(b.g + pInten_table[0]), clamp255(b.b + pInten_table[0]), 255);
+ pBlock_colors[1].set(clamp255(b.r + pInten_table[1]), clamp255(b.g + pInten_table[1]), clamp255(b.b + pInten_table[1]), 255);
+ pBlock_colors[2].set(clamp255(b.r + pInten_table[2]), clamp255(b.g + pInten_table[2]), clamp255(b.b + pInten_table[2]), 255);
+ pBlock_colors[3].set(clamp255(b.r + pInten_table[3]), clamp255(b.g + pInten_table[3]), clamp255(b.b + pInten_table[3]), 255);
+ }
+
+ static void get_block_colors4(color_rgba *pBlock_colors, const color_rgba &base_color4, uint32_t inten_table, bool scaled = false)
+ {
+ color_rgba b(base_color4);
+
+ if (!scaled)
+ {
+ b.r = (b.r << 4) | b.r;
+ b.g = (b.g << 4) | b.g;
+ b.b = (b.b << 4) | b.b;
+ }
+
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ pBlock_colors[0].set(clamp255(b.r + pInten_table[0]), clamp255(b.g + pInten_table[0]), clamp255(b.b + pInten_table[0]), 255);
+ pBlock_colors[1].set(clamp255(b.r + pInten_table[1]), clamp255(b.g + pInten_table[1]), clamp255(b.b + pInten_table[1]), 255);
+ pBlock_colors[2].set(clamp255(b.r + pInten_table[2]), clamp255(b.g + pInten_table[2]), clamp255(b.b + pInten_table[2]), 255);
+ pBlock_colors[3].set(clamp255(b.r + pInten_table[3]), clamp255(b.g + pInten_table[3]), clamp255(b.b + pInten_table[3]), 255);
+ }
+
+ uint64_t evaluate_etc1_error(const color_rgba* pBlock_pixels, bool perceptual, int subblock_index = -1) const;
+ void get_subblock_pixels(color_rgba* pPixels, int subblock_index = -1) const;
+
+ void get_selector_range(uint32_t& low, uint32_t& high) const
+ {
+ low = 3;
+ high = 0;
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ const uint32_t s = get_selector(x, y);
+ low = minimum(low, s);
+ high = maximum(high, s);
+ }
+ }
+ }
+
+ void set_block_color4(const color_rgba &c0_unscaled, const color_rgba &c1_unscaled)
+ {
+ set_diff_bit(false);
+
+ set_base4_color(0, pack_color4(c0_unscaled, false));
+ set_base4_color(1, pack_color4(c1_unscaled, false));
+ }
+
+ void set_block_color5(const color_rgba &c0_unscaled, const color_rgba &c1_unscaled)
+ {
+ set_diff_bit(true);
+
+ set_base5_color(pack_color5(c0_unscaled, false));
+
+ int dr = c1_unscaled.r - c0_unscaled.r;
+ int dg = c1_unscaled.g - c0_unscaled.g;
+ int db = c1_unscaled.b - c0_unscaled.b;
+
+ set_delta3_color(pack_delta3(dr, dg, db));
+ }
+
+ void set_block_color5_etc1s(const color_rgba &c_unscaled)
+ {
+ set_diff_bit(true);
+
+ set_base5_color(pack_color5(c_unscaled, false));
+ set_delta3_color(pack_delta3(0, 0, 0));
+ }
+
+ bool set_block_color5_check(const color_rgba &c0_unscaled, const color_rgba &c1_unscaled)
+ {
+ set_diff_bit(true);
+
+ set_base5_color(pack_color5(c0_unscaled, false));
+
+ int dr = c1_unscaled.r - c0_unscaled.r;
+ int dg = c1_unscaled.g - c0_unscaled.g;
+ int db = c1_unscaled.b - c0_unscaled.b;
+
+ if (((dr < cETC1ColorDeltaMin) || (dr > cETC1ColorDeltaMax)) ||
+ ((dg < cETC1ColorDeltaMin) || (dg > cETC1ColorDeltaMax)) ||
+ ((db < cETC1ColorDeltaMin) || (db > cETC1ColorDeltaMax)))
+ return false;
+
+ set_delta3_color(pack_delta3(dr, dg, db));
+
+ return true;
+ }
+
+ color_rgba get_selector_color(uint32_t x, uint32_t y, uint32_t s) const
+ {
+ color_rgba block_colors[4];
+
+ get_block_colors(block_colors, get_subblock_index(x, y));
+
+ return block_colors[s];
+ }
+
+ // Base color 5
+ static uint16_t pack_color5(const color_rgba& color, bool scaled, uint32_t bias = 127U);
+ static uint16_t pack_color5(uint32_t r, uint32_t g, uint32_t b, bool scaled, uint32_t bias = 127U);
+
+ static color_rgba unpack_color5(uint16_t packed_color5, bool scaled, uint32_t alpha = 255U);
+ static void unpack_color5(uint32_t& r, uint32_t& g, uint32_t& b, uint16_t packed_color, bool scaled);
+ static void unpack_color5(color_rgba& result, uint16_t packed_color5, bool scaled);
+
+ static bool unpack_color5(color_rgba& result, uint16_t packed_color5, uint16_t packed_delta3, bool scaled, uint32_t alpha = 255U);
+ static bool unpack_color5(uint32_t& r, uint32_t& g, uint32_t& b, uint16_t packed_color5, uint16_t packed_delta3, bool scaled, uint32_t alpha = 255U);
+
+ // Delta color 3
+ // Inputs range from -4 to 3 (cETC1ColorDeltaMin to cETC1ColorDeltaMax)
+ static uint16_t pack_delta3(const color_rgba_i16& color);
+ static uint16_t pack_delta3(int r, int g, int b);
+
+ // Results range from -4 to 3 (cETC1ColorDeltaMin to cETC1ColorDeltaMax)
+ static color_rgba_i16 unpack_delta3(uint16_t packed_delta3);
+ static void unpack_delta3(int& r, int& g, int& b, uint16_t packed_delta3);
+
+ static bool try_pack_color5_delta3(const color_rgba *pColor5_unscaled)
+ {
+ int dr = pColor5_unscaled[1].r - pColor5_unscaled[0].r;
+ int dg = pColor5_unscaled[1].g - pColor5_unscaled[0].g;
+ int db = pColor5_unscaled[1].b - pColor5_unscaled[0].b;
+
+ if ((minimum(dr, dg, db) < cETC1ColorDeltaMin) || (maximum(dr, dg, db) > cETC1ColorDeltaMax))
+ return false;
+
+ return true;
+ }
+
+ // Abs color 4
+ static uint16_t pack_color4(const color_rgba& color, bool scaled, uint32_t bias = 127U);
+ static uint16_t pack_color4(uint32_t r, uint32_t g, uint32_t b, bool scaled, uint32_t bias = 127U);
+
+ static color_rgba unpack_color4(uint16_t packed_color4, bool scaled, uint32_t alpha = 255U);
+ static void unpack_color4(uint32_t& r, uint32_t& g, uint32_t& b, uint16_t packed_color4, bool scaled);
+
+ // subblock colors
+ static void get_diff_subblock_colors(color_rgba* pDst, uint16_t packed_color5, uint32_t table_idx);
+ static bool get_diff_subblock_colors(color_rgba* pDst, uint16_t packed_color5, uint16_t packed_delta3, uint32_t table_idx);
+ static void get_abs_subblock_colors(color_rgba* pDst, uint16_t packed_color4, uint32_t table_idx);
+
+ static inline void unscaled_to_scaled_color(color_rgba& dst, const color_rgba& src, bool color4)
+ {
+ if (color4)
+ {
+ dst.r = src.r | (src.r << 4);
+ dst.g = src.g | (src.g << 4);
+ dst.b = src.b | (src.b << 4);
+ }
+ else
+ {
+ dst.r = (src.r >> 2) | (src.r << 3);
+ dst.g = (src.g >> 2) | (src.g << 3);
+ dst.b = (src.b >> 2) | (src.b << 3);
+ }
+ dst.a = src.a;
+ }
+
+ private:
+ static uint8_t clamp255(int x, bool &did_clamp)
+ {
+ if (x < 0)
+ {
+ did_clamp = true;
+ return 0;
+ }
+ else if (x > 255)
+ {
+ did_clamp = true;
+ return 255;
+ }
+
+ return static_cast<uint8_t>(x);
+ }
+
+ static uint8_t clamp255(int x)
+ {
+ if (x < 0)
+ return 0;
+ else if (x > 255)
+ return 255;
+
+ return static_cast<uint8_t>(x);
+ }
+ };
+
+ typedef std::vector<etc_block> etc_block_vec;
+
+ // Returns false if the unpack fails (could be bogus data or ETC2)
+ bool unpack_etc1(const etc_block& block, color_rgba *pDst, bool preserve_alpha = false);
+
+ enum basis_etc_quality
+ {
+ cETCQualityFast,
+ cETCQualityMedium,
+ cETCQualitySlow,
+ cETCQualityUber,
+ cETCQualityTotal,
+ };
+
+ struct basis_etc1_pack_params
+ {
+ basis_etc_quality m_quality;
+ bool m_perceptual;
+ bool m_cluster_fit;
+ bool m_force_etc1s;
+ bool m_use_color4;
+ float m_flip_bias;
+
+ inline basis_etc1_pack_params()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ m_quality = cETCQualitySlow;
+ m_perceptual = true;
+ m_cluster_fit = true;
+ m_force_etc1s = false;
+ m_use_color4 = true;
+ m_flip_bias = 0.0f;
+ }
+ };
+
+ struct etc1_solution_coordinates
+ {
+ inline etc1_solution_coordinates() :
+ m_unscaled_color(0, 0, 0, 0),
+ m_inten_table(0),
+ m_color4(false)
+ {
+ }
+
+ inline etc1_solution_coordinates(uint32_t r, uint32_t g, uint32_t b, uint32_t inten_table, bool color4) :
+ m_unscaled_color((uint8_t)r, (uint8_t)g, (uint8_t)b, 255),
+ m_inten_table((uint8_t)inten_table),
+ m_color4(color4)
+ {
+ }
+
+ inline etc1_solution_coordinates(const color_rgba& c, uint32_t inten_table, bool color4) :
+ m_unscaled_color(c),
+ m_inten_table(inten_table),
+ m_color4(color4)
+ {
+ }
+
+ inline etc1_solution_coordinates(const etc1_solution_coordinates& other)
+ {
+ *this = other;
+ }
+
+ inline etc1_solution_coordinates& operator= (const etc1_solution_coordinates& rhs)
+ {
+ m_unscaled_color = rhs.m_unscaled_color;
+ m_inten_table = rhs.m_inten_table;
+ m_color4 = rhs.m_color4;
+ return *this;
+ }
+
+ inline void clear()
+ {
+ m_unscaled_color.clear();
+ m_inten_table = 0;
+ m_color4 = false;
+ }
+
+ inline void init(const color_rgba& c, uint32_t inten_table, bool color4)
+ {
+ m_unscaled_color = c;
+ m_inten_table = inten_table;
+ m_color4 = color4;
+ }
+
+ inline color_rgba get_scaled_color() const
+ {
+ int br, bg, bb;
+ if (m_color4)
+ {
+ br = m_unscaled_color.r | (m_unscaled_color.r << 4);
+ bg = m_unscaled_color.g | (m_unscaled_color.g << 4);
+ bb = m_unscaled_color.b | (m_unscaled_color.b << 4);
+ }
+ else
+ {
+ br = (m_unscaled_color.r >> 2) | (m_unscaled_color.r << 3);
+ bg = (m_unscaled_color.g >> 2) | (m_unscaled_color.g << 3);
+ bb = (m_unscaled_color.b >> 2) | (m_unscaled_color.b << 3);
+ }
+ return color_rgba((uint8_t)br, (uint8_t)bg, (uint8_t)bb, 255);
+ }
+
+ // returns true if anything was clamped
+ inline void get_block_colors(color_rgba* pBlock_colors)
+ {
+ int br, bg, bb;
+ if (m_color4)
+ {
+ br = m_unscaled_color.r | (m_unscaled_color.r << 4);
+ bg = m_unscaled_color.g | (m_unscaled_color.g << 4);
+ bb = m_unscaled_color.b | (m_unscaled_color.b << 4);
+ }
+ else
+ {
+ br = (m_unscaled_color.r >> 2) | (m_unscaled_color.r << 3);
+ bg = (m_unscaled_color.g >> 2) | (m_unscaled_color.g << 3);
+ bb = (m_unscaled_color.b >> 2) | (m_unscaled_color.b << 3);
+ }
+ const int* pInten_table = g_etc1_inten_tables[m_inten_table];
+ pBlock_colors[0].set((uint8_t)(br + pInten_table[0]), (uint8_t)(bg + pInten_table[0]), (uint8_t)(bb + pInten_table[0]), 255);
+ pBlock_colors[1].set((uint8_t)(br + pInten_table[1]), (uint8_t)(bg + pInten_table[1]), (uint8_t)(bb + pInten_table[1]), 255);
+ pBlock_colors[2].set((uint8_t)(br + pInten_table[2]), (uint8_t)(bg + pInten_table[2]), (uint8_t)(bb + pInten_table[2]), 255);
+ pBlock_colors[3].set((uint8_t)(br + pInten_table[3]), (uint8_t)(bg + pInten_table[3]), (uint8_t)(bb + pInten_table[3]), 255);
+ }
+
+ color_rgba m_unscaled_color;
+ uint32_t m_inten_table;
+ bool m_color4;
+ };
+
+ class etc1_optimizer
+ {
+ BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(etc1_optimizer);
+
+ public:
+ etc1_optimizer()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ m_pParams = nullptr;
+ m_pResult = nullptr;
+ m_pSorted_luma = nullptr;
+ m_pSorted_luma_indices = nullptr;
+ }
+
+ struct params;
+
+ typedef bool(*evaluate_solution_override_func)(uint64_t &error, const params &p, const color_rgba* pBlock_colors, const uint8_t* pSelectors, const etc1_solution_coordinates& coords);
+
+ struct params : basis_etc1_pack_params
+ {
+ params()
+ {
+ clear();
+ }
+
+ params(const basis_etc1_pack_params& base_params)
+ {
+ clear_optimizer_params();
+
+ *static_cast<basis_etc1_pack_params *>(this) = base_params;
+ }
+
+ void clear()
+ {
+ clear_optimizer_params();
+ }
+
+ void clear_optimizer_params()
+ {
+ basis_etc1_pack_params::clear();
+
+ m_num_src_pixels = 0;
+ m_pSrc_pixels = 0;
+
+ m_use_color4 = false;
+ static const int s_default_scan_delta[] = { 0 };
+ m_pScan_deltas = s_default_scan_delta;
+ m_scan_delta_size = 1;
+
+ m_base_color5.clear();
+ m_constrain_against_base_color5 = false;
+
+ m_refinement = true;
+
+ m_pForce_selectors = nullptr;
+
+ m_pEval_solution_override = nullptr;
+ m_pEval_solution_override_data = nullptr;
+ }
+
+ uint32_t m_num_src_pixels;
+ const color_rgba* m_pSrc_pixels;
+
+ bool m_use_color4;
+ const int* m_pScan_deltas;
+ uint32_t m_scan_delta_size;
+
+ color_rgba m_base_color5;
+ bool m_constrain_against_base_color5;
+
+ bool m_refinement;
+
+ const uint8_t* m_pForce_selectors;
+
+ evaluate_solution_override_func m_pEval_solution_override;
+ void *m_pEval_solution_override_data;
+ };
+
+ struct results
+ {
+ uint64_t m_error;
+ color_rgba m_block_color_unscaled;
+ uint32_t m_block_inten_table;
+ uint32_t m_n;
+ uint8_t* m_pSelectors;
+ bool m_block_color4;
+
+ inline results& operator= (const results& rhs)
+ {
+ m_block_color_unscaled = rhs.m_block_color_unscaled;
+ m_block_color4 = rhs.m_block_color4;
+ m_block_inten_table = rhs.m_block_inten_table;
+ m_error = rhs.m_error;
+ memcpy(m_pSelectors, rhs.m_pSelectors, minimum(rhs.m_n, m_n));
+ return *this;
+ }
+ };
+
+ void init(const params& params, results& result);
+ bool compute();
+
+ const params* get_params() const { return m_pParams; }
+
+ private:
+ struct potential_solution
+ {
+ potential_solution() : m_coords(), m_error(UINT64_MAX), m_valid(false)
+ {
+ }
+
+ etc1_solution_coordinates m_coords;
+ std::vector<uint8_t> m_selectors;
+ uint64_t m_error;
+ bool m_valid;
+
+ void clear()
+ {
+ m_coords.clear();
+ m_selectors.resize(0);
+ m_error = UINT64_MAX;
+ m_valid = false;
+ }
+
+ bool are_selectors_all_equal() const
+ {
+ if (!m_selectors.size())
+ return false;
+ const uint32_t s = m_selectors[0];
+ for (uint32_t i = 1; i < m_selectors.size(); i++)
+ if (m_selectors[i] != s)
+ return false;
+ return true;
+ }
+ };
+
+ const params* m_pParams;
+ results* m_pResult;
+
+ int m_limit;
+
+ vec3F m_avg_color;
+ int m_br, m_bg, m_bb;
+ std::vector<uint16_t> m_luma;
+ std::vector<uint32_t> m_sorted_luma;
+ std::vector<uint32_t> m_sorted_luma_indices;
+ const uint32_t* m_pSorted_luma_indices;
+ uint32_t* m_pSorted_luma;
+
+ std::vector<uint8_t> m_selectors;
+ std::vector<uint8_t> m_best_selectors;
+
+ potential_solution m_best_solution;
+ potential_solution m_trial_solution;
+ std::vector<uint8_t> m_temp_selectors;
+
+ std::set<uint32_t> m_solutions_tried;
+
+ void get_nearby_inten_tables(uint32_t idx, int &first_inten_table, int &last_inten_table)
+ {
+ first_inten_table = maximum<int>(idx - 1, 0);
+ last_inten_table = minimum<int>(cETC1IntenModifierValues, idx + 1);
+ }
+
+ bool evaluate_solution_slow(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution);
+ bool evaluate_solution_fast(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution);
+
+ inline bool evaluate_solution(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution)
+ {
+ if (m_pParams->m_quality >= cETCQualitySlow)
+ return evaluate_solution_slow(coords, trial_solution, pBest_solution);
+ else
+ return evaluate_solution_fast(coords, trial_solution, pBest_solution);
+ }
+
+ void refine_solution(uint32_t max_refinement_trials);
+ void compute_internal_neighborhood(int scan_r, int scan_g, int scan_b);
+ void compute_internal_cluster_fit(uint32_t total_perms_to_try);
+ };
+
+ struct pack_etc1_block_context
+ {
+ etc1_optimizer m_optimizer;
+ };
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_frontend.cpp b/thirdparty/basis_universal/basisu_frontend.cpp
new file mode 100644
index 0000000000..6f7a9bf889
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_frontend.cpp
@@ -0,0 +1,2432 @@
+// basisu_frontend.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// TODO:
+// This code originally supported full ETC1 and ETC1S, so there's some legacy stuff to be cleaned up in here.
+// Add endpoint tiling support (where we force adjacent blocks to use the same endpoints during quantization), for a ~10% or more increase in bitrate at same SSIM. The backend already supports this.
+//
+#include "transcoder/basisu.h"
+#include "basisu_frontend.h"
+#include <unordered_set>
+#include <unordered_map>
+
+#define BASISU_FRONTEND_VERIFY(c) do { if (!(c)) handle_verify_failure(__LINE__); } while(0)
+
+namespace basisu
+{
+ const uint32_t cMaxCodebookCreationThreads = 8;
+
+ const uint32_t BASISU_MAX_ENDPOINT_REFINEMENT_STEPS = 3;
+ const uint32_t BASISU_MAX_SELECTOR_REFINEMENT_STEPS = 3;
+
+ const uint32_t BASISU_ENDPOINT_PARENT_CODEBOOK_SIZE = 16;
+ const uint32_t BASISU_SELECTOR_PARENT_CODEBOOK_SIZE = 16;
+
+ // TODO - How to handle internal verifies in the basisu lib
+ static inline void handle_verify_failure(int line)
+ {
+ fprintf(stderr, "ERROR: basisu_frontend: verify check failed at line %i!\n", line);
+ abort();
+ }
+
+ bool basisu_frontend::init(const params &p)
+ {
+#if 0
+ // HACK HACK
+ FILE* pFile;
+ fopen_s(&pFile, "tv.bin", "rb");
+ if (pFile)
+ {
+ debug_printf("Using tv.bin\n");
+
+ fseek(pFile, 0, SEEK_END);
+ uint32_t size = ftell(pFile);
+ fseek(pFile, 0, SEEK_SET);
+
+ uint32_t tv = size / sizeof(vec6F_quantizer::training_vec_with_weight);
+
+ std::vector<vec6F_quantizer::training_vec_with_weight> v(tv);
+ fread(&v[0], 1, sizeof(v[0]) * tv, pFile);
+
+ for (uint32_t i = 0; i < tv; i++)
+ m_endpoint_clusterizer.add_training_vec(v[i].first, v[i].second);
+
+ m_endpoint_clusterizer.generate(16128);
+ std::vector<uint_vec> codebook;
+ m_endpoint_clusterizer.retrieve(codebook);
+
+ printf("Generated %u entries\n", (uint32_t)codebook.size());
+
+ fclose(pFile);
+ exit(0);
+ }
+#endif
+
+ if (p.m_use_hybrid_selector_codebooks)
+ {
+ if (!p.m_pGlobal_sel_codebook)
+ {
+ assert(0);
+ return false;
+ }
+ }
+
+ debug_printf("basisu_frontend::init: Multithreaded: %u, NumEndpointClusters: %u, NumSelectorClusters: %u, Perceptual: %u, CompressionLevel: %u\n",
+ p.m_multithreaded, p.m_max_endpoint_clusters, p.m_max_selector_clusters, p.m_perceptual, p.m_compression_level);
+
+ debug_printf("Global sel codebook pal bits: %u, Global sel codebook mod bits: %u, Use hybrid selector codebook: %u, Hybrid codebook quality thresh: %f\n",
+ p.m_num_global_sel_codebook_pal_bits,
+ p.m_num_global_sel_codebook_mod_bits,
+ p.m_use_hybrid_selector_codebooks,
+ p.m_hybrid_codebook_quality_thresh);
+
+ if ((p.m_max_endpoint_clusters < 1) || (p.m_max_endpoint_clusters > cMaxEndpointClusters))
+ return false;
+ if ((p.m_max_selector_clusters < 1) || (p.m_max_selector_clusters > cMaxSelectorClusters))
+ return false;
+
+ m_source_blocks.resize(0);
+ append_vector(m_source_blocks, p.m_pSource_blocks, p.m_num_source_blocks);
+
+ m_params = p;
+
+ m_encoded_blocks.resize(m_params.m_num_source_blocks);
+ memset(&m_encoded_blocks[0], 0, m_encoded_blocks.size() * sizeof(m_encoded_blocks[0]));
+
+ m_num_endpoint_codebook_iterations = 1;
+ m_num_selector_codebook_iterations = 1;
+
+ switch (p.m_compression_level)
+ {
+ case 0:
+ {
+ m_endpoint_refinement = false;
+ m_use_hierarchical_endpoint_codebooks = true;
+ m_use_hierarchical_selector_codebooks = true;
+ break;
+ }
+ case 1:
+ {
+ m_endpoint_refinement = true;
+ m_use_hierarchical_endpoint_codebooks = true;
+ m_use_hierarchical_selector_codebooks = true;
+
+ break;
+ }
+ case 2:
+ {
+ m_endpoint_refinement = true;
+ m_use_hierarchical_endpoint_codebooks = false;
+ m_use_hierarchical_selector_codebooks = false;
+ break;
+ }
+ case 3:
+ {
+ m_endpoint_refinement = true;
+ m_use_hierarchical_endpoint_codebooks = true;
+ m_use_hierarchical_selector_codebooks = true;
+ m_num_endpoint_codebook_iterations = BASISU_MAX_ENDPOINT_REFINEMENT_STEPS;
+ m_num_selector_codebook_iterations = BASISU_MAX_ENDPOINT_REFINEMENT_STEPS;
+ break;
+ }
+ case 4:
+ {
+ m_endpoint_refinement = true;
+ m_use_hierarchical_endpoint_codebooks = false;
+ m_use_hierarchical_selector_codebooks = false;
+ m_num_endpoint_codebook_iterations = BASISU_MAX_ENDPOINT_REFINEMENT_STEPS;
+ m_num_selector_codebook_iterations = BASISU_MAX_ENDPOINT_REFINEMENT_STEPS;
+ break;
+ }
+ case 5:
+ {
+ m_endpoint_refinement = true;
+ m_use_hierarchical_endpoint_codebooks = false;
+ m_use_hierarchical_selector_codebooks = false;
+ m_num_endpoint_codebook_iterations = BASISU_MAX_ENDPOINT_REFINEMENT_STEPS*2;
+ m_num_selector_codebook_iterations = BASISU_MAX_ENDPOINT_REFINEMENT_STEPS*2;
+ break;
+ }
+
+ }
+
+ if (m_params.m_disable_hierarchical_endpoint_codebooks)
+ m_use_hierarchical_endpoint_codebooks = false;
+
+ debug_printf("Endpoint refinement: %u, Hierarchical endpoint codebooks: %u, Hierarchical selector codebooks: %u, Endpoint codebook iters: %u, Selector codebook iters: %u\n",
+ m_endpoint_refinement, m_use_hierarchical_endpoint_codebooks, m_use_hierarchical_selector_codebooks, m_num_endpoint_codebook_iterations, m_num_selector_codebook_iterations);
+
+ return true;
+ }
+
+ bool basisu_frontend::compress()
+ {
+ debug_printf("basisu_frontend::compress\n");
+
+ m_total_blocks = m_params.m_num_source_blocks;
+ m_total_pixels = m_total_blocks * cPixelBlockTotalPixels;
+
+ init_etc1_images();
+
+ init_endpoint_training_vectors();
+
+ generate_endpoint_clusters();
+
+ for (uint32_t refine_endpoint_step = 0; refine_endpoint_step < m_num_endpoint_codebook_iterations; refine_endpoint_step++)
+ {
+ BASISU_FRONTEND_VERIFY(check_etc1s_constraints());
+
+ if (refine_endpoint_step)
+ {
+ introduce_new_endpoint_clusters();
+ }
+
+ generate_endpoint_codebook(refine_endpoint_step);
+
+ if ((m_params.m_debug_images) && (m_params.m_dump_endpoint_clusterization))
+ {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "endpoint_cluster_vis_pre_%u.png", refine_endpoint_step);
+ dump_endpoint_clusterization_visualization(buf, false);
+ }
+
+ bool early_out = false;
+
+ if (m_endpoint_refinement)
+ {
+ //dump_endpoint_clusterization_visualization("endpoint_clusters_before_refinement.png");
+
+ if (!refine_endpoint_clusterization())
+ early_out = true;
+
+ if ((m_params.m_tex_type == basist::cBASISTexTypeVideoFrames) && (!refine_endpoint_step) && (m_num_endpoint_codebook_iterations == 1))
+ {
+ eliminate_redundant_or_empty_endpoint_clusters();
+ generate_endpoint_codebook(refine_endpoint_step);
+ }
+
+ if ((m_params.m_debug_images) && (m_params.m_dump_endpoint_clusterization))
+ {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "endpoint_cluster_vis_post_%u.png", refine_endpoint_step);
+
+ dump_endpoint_clusterization_visualization(buf, false);
+ snprintf(buf, sizeof(buf), "endpoint_cluster_colors_vis_post_%u.png", refine_endpoint_step);
+
+ dump_endpoint_clusterization_visualization(buf, true);
+ }
+ }
+
+ eliminate_redundant_or_empty_endpoint_clusters();
+
+ if (m_params.m_debug_stats)
+ debug_printf("Total endpoint clusters: %u\n", (uint32_t)m_endpoint_clusters.size());
+
+ if (early_out)
+ break;
+ }
+
+ BASISU_FRONTEND_VERIFY(check_etc1s_constraints());
+
+ generate_block_endpoint_clusters();
+
+ create_initial_packed_texture();
+
+ generate_selector_clusters();
+
+ if (m_use_hierarchical_selector_codebooks)
+ compute_selector_clusters_within_each_parent_cluster();
+
+ if (m_params.m_compression_level == 0)
+ {
+ create_optimized_selector_codebook(0);
+
+ find_optimal_selector_clusters_for_each_block();
+
+ introduce_special_selector_clusters();
+ }
+ else
+ {
+ const uint32_t num_refine_selector_steps = m_params.m_pGlobal_sel_codebook ? 1 : m_num_selector_codebook_iterations;
+ for (uint32_t refine_selector_steps = 0; refine_selector_steps < num_refine_selector_steps; refine_selector_steps++)
+ {
+ create_optimized_selector_codebook(refine_selector_steps);
+
+ find_optimal_selector_clusters_for_each_block();
+
+ introduce_special_selector_clusters();
+
+ if ((m_params.m_compression_level >= 3) || (m_params.m_tex_type == basist::cBASISTexTypeVideoFrames))
+ {
+ if (!refine_block_endpoints_given_selectors())
+ break;
+ }
+ }
+ }
+
+ optimize_selector_codebook();
+
+ if (m_params.m_debug_stats)
+ debug_printf("Total selector clusters: %u\n", (uint32_t)m_selector_cluster_indices.size());
+
+ finalize();
+
+ if (m_params.m_validate)
+ {
+ if (!validate_output())
+ return false;
+ }
+
+ debug_printf("basisu_frontend::compress: Done\n");
+
+ return true;
+ }
+
+ void basisu_frontend::introduce_special_selector_clusters()
+ {
+ debug_printf("introduce_special_selector_clusters\n");
+
+ if (m_params.m_pGlobal_sel_codebook)
+ return;
+
+ uint32_t total_blocks_relocated = 0;
+ const uint32_t initial_selector_clusters = (uint32_t)m_selector_cluster_indices.size();
+
+ bool_vec block_relocated_flags(m_total_blocks);
+
+ // Make sure the selector codebook always has pure flat blocks for each possible selector, to avoid obvious artifacts.
+ // optimize_selector_codebook() will clean up any redundant clusters we create here.
+ for (uint32_t sel = 0; sel < 4; sel++)
+ {
+ etc_block blk;
+ clear_obj(blk);
+ for (uint32_t j = 0; j < 16; j++)
+ blk.set_selector(j & 3, j >> 2, sel);
+
+ int k;
+ for (k = 0; k < (int)m_optimized_cluster_selectors.size(); k++)
+ if (m_optimized_cluster_selectors[k].get_raw_selector_bits() == blk.get_raw_selector_bits())
+ break;
+ if (k < (int)m_optimized_cluster_selectors.size())
+ continue;
+
+ debug_printf("Introducing sel %u\n", sel);
+
+ const uint32_t new_selector_cluster_index = (uint32_t)m_optimized_cluster_selectors.size();
+
+ m_optimized_cluster_selectors.push_back(blk);
+
+ vector_ensure_element_is_valid(m_selector_cluster_indices, new_selector_cluster_index);
+
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ if (m_orig_encoded_blocks[block_index].get_raw_selector_bits() != blk.get_raw_selector_bits())
+ continue;
+
+ // See if using flat selectors actually decreases the block's error.
+ const uint32_t old_selector_cluster_index = m_block_selector_cluster_index[block_index];
+
+ etc_block cur_blk;
+ const uint32_t endpoint_cluster_index = get_subblock_endpoint_cluster_index(block_index, 0);
+ cur_blk.set_block_color5_etc1s(get_endpoint_cluster_unscaled_color(endpoint_cluster_index, false));
+ cur_blk.set_inten_tables_etc1s(get_endpoint_cluster_inten_table(endpoint_cluster_index, false));
+ cur_blk.set_raw_selector_bits(get_selector_cluster_selector_bits(old_selector_cluster_index).get_raw_selector_bits());
+ cur_blk.set_flip_bit(true);
+
+ const uint64_t cur_err = cur_blk.evaluate_etc1_error(get_source_pixel_block(block_index).get_ptr(), m_params.m_perceptual);
+
+ cur_blk.set_raw_selector_bits(blk.get_raw_selector_bits());
+
+ const uint64_t new_err = cur_blk.evaluate_etc1_error(get_source_pixel_block(block_index).get_ptr(), m_params.m_perceptual);
+
+ if (new_err >= cur_err)
+ continue;
+
+ // Change the block to use the new cluster
+ m_block_selector_cluster_index[block_index] = new_selector_cluster_index;
+
+ m_selector_cluster_indices[new_selector_cluster_index].push_back(block_index);
+
+ block_relocated_flags[block_index] = true;
+
+#if 0
+ int j = vector_find(m_selector_cluster_indices[old_selector_cluster_index], block_index);
+ if (j >= 0)
+ m_selector_cluster_indices[old_selector_cluster_index].erase(m_selector_cluster_indices[old_selector_cluster_index].begin() + j);
+#endif
+
+ total_blocks_relocated++;
+
+ m_encoded_blocks[block_index].set_raw_selector_bits(blk.get_raw_selector_bits());
+
+ } // block_index
+
+ } // sel
+
+ if (total_blocks_relocated)
+ {
+ debug_printf("Fixing selector codebook\n");
+
+ for (int selector_cluster_index = 0; selector_cluster_index < (int)initial_selector_clusters; selector_cluster_index++)
+ {
+ uint_vec& block_indices = m_selector_cluster_indices[selector_cluster_index];
+
+ uint32_t dst_ofs = 0;
+
+ for (uint32_t i = 0; i < block_indices.size(); i++)
+ {
+ const uint32_t block_index = block_indices[i];
+ if (!block_relocated_flags[block_index])
+ block_indices[dst_ofs++] = block_index;
+ }
+
+ block_indices.resize(dst_ofs);
+ }
+ }
+
+ debug_printf("Total blocks relocated to new flat selector clusters: %u\n", total_blocks_relocated);
+ }
+
+ void basisu_frontend::optimize_selector_codebook()
+ {
+ debug_printf("optimize_selector_codebook\n");
+
+ const uint32_t orig_total_selector_clusters = (uint32_t)m_optimized_cluster_selectors.size();
+
+ bool_vec selector_cluster_was_used(m_optimized_cluster_selectors.size());
+ for (uint32_t i = 0; i < m_total_blocks; i++)
+ selector_cluster_was_used[m_block_selector_cluster_index[i]] = true;
+
+ int_vec old_to_new(m_optimized_cluster_selectors.size());
+ int_vec new_to_old;
+ uint32_t total_new_entries = 0;
+
+ std::unordered_map<uint32_t, uint32_t> selector_hashmap;
+
+ for (int i = 0; i < static_cast<int>(m_optimized_cluster_selectors.size()); i++)
+ {
+ if (!selector_cluster_was_used[i])
+ {
+ old_to_new[i] = -1;
+ continue;
+ }
+
+ const uint32_t raw_selector_bits = m_optimized_cluster_selectors[i].get_raw_selector_bits();
+
+ auto find_res = selector_hashmap.insert(std::make_pair(raw_selector_bits, total_new_entries));
+ if (!find_res.second)
+ {
+ old_to_new[i] = (find_res.first)->second;
+ continue;
+ }
+
+ old_to_new[i] = total_new_entries++;
+ new_to_old.push_back(i);
+ }
+
+ for (uint32_t i = 0; i < m_block_selector_cluster_index.size(); i++)
+ {
+ BASISU_FRONTEND_VERIFY((old_to_new[m_block_selector_cluster_index[i]] >= 0) && (old_to_new[m_block_selector_cluster_index[i]] < (int)total_new_entries));
+ m_block_selector_cluster_index[i] = old_to_new[m_block_selector_cluster_index[i]];
+ }
+
+ std::vector<etc_block> new_optimized_cluster_selectors(m_optimized_cluster_selectors.size() ? total_new_entries : 0);
+ basist::etc1_global_selector_codebook_entry_id_vec new_optimized_cluster_selector_global_cb_ids(m_optimized_cluster_selector_global_cb_ids.size() ? total_new_entries : 0);
+ std::vector<uint_vec> new_selector_cluster_indices(m_selector_cluster_indices.size() ? total_new_entries : 0);
+ bool_vec new_selector_cluster_uses_global_cb(m_selector_cluster_uses_global_cb.size() ? total_new_entries : 0);
+
+ for (uint32_t i = 0; i < total_new_entries; i++)
+ {
+ if (m_optimized_cluster_selectors.size())
+ new_optimized_cluster_selectors[i] = m_optimized_cluster_selectors[new_to_old[i]];
+
+ if (m_optimized_cluster_selector_global_cb_ids.size())
+ new_optimized_cluster_selector_global_cb_ids[i] = m_optimized_cluster_selector_global_cb_ids[new_to_old[i]];
+
+ if (m_selector_cluster_indices.size())
+ new_selector_cluster_indices[i] = m_selector_cluster_indices[new_to_old[i]];
+
+ if (m_selector_cluster_uses_global_cb.size())
+ new_selector_cluster_uses_global_cb[i] = m_selector_cluster_uses_global_cb[new_to_old[i]];
+ }
+
+ m_optimized_cluster_selectors.swap(new_optimized_cluster_selectors);
+ m_optimized_cluster_selector_global_cb_ids.swap(new_optimized_cluster_selector_global_cb_ids);
+ m_selector_cluster_indices.swap(new_selector_cluster_indices);
+ m_selector_cluster_uses_global_cb.swap(new_selector_cluster_uses_global_cb);
+
+ debug_printf("optimize_selector_codebook: Before: %u After: %u\n", orig_total_selector_clusters, total_new_entries);
+ }
+
+ void basisu_frontend::init_etc1_images()
+ {
+ debug_printf("basisu_frontend::init_etc1_images\n");
+
+ m_etc1_blocks_etc1s.resize(m_total_blocks);
+
+ const uint32_t N = 4096;
+ for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ {
+ const uint32_t first_index = block_index_iter;
+ const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index] {
+
+ for (uint32_t block_index = first_index; block_index < last_index; block_index++)
+ {
+ const pixel_block &source_blk = get_source_pixel_block(block_index);
+
+ etc1_optimizer optimizer;
+ etc1_optimizer::params optimizer_params;
+ etc1_optimizer::results optimizer_results;
+
+ if (m_params.m_compression_level == 0)
+ optimizer_params.m_quality = cETCQualityFast;
+ else if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
+ optimizer_params.m_quality = cETCQualityUber;
+
+ optimizer_params.m_num_src_pixels = 16;
+ optimizer_params.m_pSrc_pixels = source_blk.get_ptr();
+ optimizer_params.m_perceptual = m_params.m_perceptual;
+
+ uint8_t selectors[16];
+ optimizer_results.m_pSelectors = selectors;
+ optimizer_results.m_n = 16;
+
+ optimizer.init(optimizer_params, optimizer_results);
+ optimizer.compute();
+
+ etc_block &blk = m_etc1_blocks_etc1s[block_index];
+
+ memset(&blk, 0, sizeof(blk));
+ blk.set_block_color5_etc1s(optimizer_results.m_block_color_unscaled);
+ blk.set_inten_tables_etc1s(optimizer_results.m_block_inten_table);
+ blk.set_flip_bit(true);
+
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ blk.set_selector(x, y, selectors[x + y * 4]);
+ }
+
+ } );
+ }
+
+ m_params.m_pJob_pool->wait_for_all();
+ }
+
+ void basisu_frontend::init_endpoint_training_vectors()
+ {
+ debug_printf("init_endpoint_training_vectors\n");
+
+ vec6F_quantizer::array_of_weighted_training_vecs &training_vecs = m_endpoint_clusterizer.get_training_vecs();
+
+ training_vecs.resize(m_total_blocks * 2);
+
+ const uint32_t N = 16384;
+ for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ {
+ const uint32_t first_index = block_index_iter;
+ const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index, &training_vecs] {
+
+ for (uint32_t block_index = first_index; block_index < last_index; block_index++)
+ {
+ const etc_block &blk = m_etc1_blocks_etc1s[block_index];
+
+ color_rgba block_colors[2];
+ blk.get_block_low_high_colors(block_colors, 0);
+
+ vec6F v;
+ v[0] = block_colors[0].r * (1.0f / 255.0f);
+ v[1] = block_colors[0].g * (1.0f / 255.0f);
+ v[2] = block_colors[0].b * (1.0f / 255.0f);
+ v[3] = block_colors[1].r * (1.0f / 255.0f);
+ v[4] = block_colors[1].g * (1.0f / 255.0f);
+ v[5] = block_colors[1].b * (1.0f / 255.0f);
+
+ training_vecs[block_index * 2 + 0] = std::make_pair(v, 1);
+ training_vecs[block_index * 2 + 1] = std::make_pair(v, 1);
+
+ } // block_index;
+
+ } );
+
+ } // block_index_iter
+
+ m_params.m_pJob_pool->wait_for_all();
+ }
+
+ void basisu_frontend::generate_endpoint_clusters()
+ {
+ debug_printf("Begin endpoint quantization\n");
+
+ const uint32_t parent_codebook_size = (m_params.m_max_endpoint_clusters >= 256) ? BASISU_ENDPOINT_PARENT_CODEBOOK_SIZE : 0;
+ uint32_t max_threads = 0;
+ max_threads = m_params.m_multithreaded ? minimum<int>(std::thread::hardware_concurrency(), cMaxCodebookCreationThreads) : 0;
+
+ debug_printf("Using %u threads to create codebook\n", max_threads);
+ bool status = generate_hierarchical_codebook_threaded(m_endpoint_clusterizer,
+ m_params.m_max_endpoint_clusters, m_use_hierarchical_endpoint_codebooks ? parent_codebook_size : 0,
+ m_endpoint_clusters,
+ m_endpoint_parent_clusters,
+ max_threads, m_params.m_pJob_pool);
+ BASISU_FRONTEND_VERIFY(status);
+
+ if (m_use_hierarchical_endpoint_codebooks)
+ {
+ if (!m_endpoint_parent_clusters.size())
+ {
+ m_endpoint_parent_clusters.resize(0);
+ m_endpoint_parent_clusters.resize(1);
+ for (uint32_t i = 0; i < m_total_blocks; i++)
+ {
+ m_endpoint_parent_clusters[0].push_back(i*2);
+ m_endpoint_parent_clusters[0].push_back(i*2+1);
+ }
+ }
+
+ BASISU_ASSUME(BASISU_ENDPOINT_PARENT_CODEBOOK_SIZE <= UINT8_MAX);
+
+ m_block_parent_endpoint_cluster.resize(0);
+ m_block_parent_endpoint_cluster.resize(m_total_blocks);
+ vector_set_all(m_block_parent_endpoint_cluster, 0xFF);
+ for (uint32_t parent_cluster_index = 0; parent_cluster_index < m_endpoint_parent_clusters.size(); parent_cluster_index++)
+ {
+ const uint_vec &cluster = m_endpoint_parent_clusters[parent_cluster_index];
+ for (uint32_t j = 0; j < cluster.size(); j++)
+ {
+ const uint32_t block_index = cluster[j] >> 1;
+ m_block_parent_endpoint_cluster[block_index] = static_cast<uint8_t>(parent_cluster_index);
+ }
+ }
+
+ for (uint32_t i = 0; i < m_total_blocks; i++)
+ {
+ BASISU_FRONTEND_VERIFY(m_block_parent_endpoint_cluster[i] != 0xFF);
+ }
+
+ // Ensure that all the blocks within each cluster are all in the same parent cluster, or something is very wrong.
+ for (uint32_t cluster_index = 0; cluster_index < m_endpoint_clusters.size(); cluster_index++)
+ {
+ const uint_vec &cluster = m_endpoint_clusters[cluster_index];
+
+ uint32_t parent_cluster_index = 0;
+ for (uint32_t j = 0; j < cluster.size(); j++)
+ {
+ const uint32_t block_index = cluster[j] >> 1;
+ if (!j)
+ {
+ parent_cluster_index = m_block_parent_endpoint_cluster[block_index];
+ }
+ else
+ {
+ BASISU_FRONTEND_VERIFY(m_block_parent_endpoint_cluster[block_index] == parent_cluster_index);
+ }
+ }
+ }
+ }
+
+ if (m_params.m_debug_stats)
+ debug_printf("Total endpoint clusters: %u, parent clusters: %u\n", (uint32_t)m_endpoint_clusters.size(), (uint32_t)m_endpoint_parent_clusters.size());
+ }
+
+ void basisu_frontend::generate_block_endpoint_clusters()
+ {
+ m_block_endpoint_clusters_indices.resize(m_total_blocks);
+
+ for (int cluster_index = 0; cluster_index < static_cast<int>(m_endpoint_clusters.size()); cluster_index++)
+ {
+ const std::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
+
+ for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
+ {
+ const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
+ const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
+
+ m_block_endpoint_clusters_indices[block_index][subblock_index] = cluster_index;
+
+ } // cluster_indices_iter
+ }
+
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ uint32_t cluster_0 = m_block_endpoint_clusters_indices[block_index][0];
+ uint32_t cluster_1 = m_block_endpoint_clusters_indices[block_index][1];
+ BASISU_FRONTEND_VERIFY(cluster_0 == cluster_1);
+ }
+ }
+
+ void basisu_frontend::compute_endpoint_clusters_within_each_parent_cluster()
+ {
+ generate_block_endpoint_clusters();
+
+ m_endpoint_clusters_within_each_parent_cluster.resize(0);
+ m_endpoint_clusters_within_each_parent_cluster.resize(m_endpoint_parent_clusters.size());
+
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ const uint32_t cluster_index = m_block_endpoint_clusters_indices[block_index][0];
+ const uint32_t parent_cluster_index = m_block_parent_endpoint_cluster[block_index];
+
+ m_endpoint_clusters_within_each_parent_cluster[parent_cluster_index].push_back(cluster_index);
+ }
+
+ for (uint32_t i = 0; i < m_endpoint_clusters_within_each_parent_cluster.size(); i++)
+ {
+ uint_vec &cluster_indices = m_endpoint_clusters_within_each_parent_cluster[i];
+
+ BASISU_FRONTEND_VERIFY(cluster_indices.size());
+
+ vector_sort(cluster_indices);
+
+ auto last = std::unique(cluster_indices.begin(), cluster_indices.end());
+ cluster_indices.erase(last, cluster_indices.end());
+ }
+ }
+
+ void basisu_frontend::compute_endpoint_subblock_error_vec()
+ {
+ m_subblock_endpoint_quant_err_vec.resize(0);
+
+ const uint32_t N = 512;
+ for (uint32_t cluster_index_iter = 0; cluster_index_iter < m_endpoint_clusters.size(); cluster_index_iter += N)
+ {
+ const uint32_t first_index = cluster_index_iter;
+ const uint32_t last_index = minimum<uint32_t>((uint32_t)m_endpoint_clusters.size(), cluster_index_iter + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index] {
+
+ for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
+ {
+ const std::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
+
+ assert(cluster_indices.size());
+
+ for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
+ {
+ std::vector<color_rgba> cluster_pixels(8);
+
+ const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
+ const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
+
+ const bool flipped = true;
+
+ const color_rgba *pSource_block_pixels = get_source_pixel_block(block_index).get_ptr();
+
+ for (uint32_t pixel_index = 0; pixel_index < 8; pixel_index++)
+ {
+ cluster_pixels[pixel_index] = pSource_block_pixels[g_etc1_pixel_indices[flipped][subblock_index][pixel_index]];
+ }
+
+ const endpoint_cluster_etc_params &etc_params = m_endpoint_cluster_etc_params[cluster_index];
+
+ assert(etc_params.m_valid);
+
+ color_rgba block_colors[4];
+ etc_block::get_block_colors5(block_colors, etc_params.m_color_unscaled[0], etc_params.m_inten_table[0], true);
+
+ uint64_t total_err = 0;
+
+ for (uint32_t i = 0; i < 8; i++)
+ {
+ const color_rgba &c = cluster_pixels[i];
+
+ uint64_t best_err = UINT64_MAX;
+ //uint32_t best_index = 0;
+
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ uint64_t err = color_distance(m_params.m_perceptual, c, block_colors[s], false);
+ if (err < best_err)
+ {
+ best_err = err;
+ //best_index = s;
+ }
+ }
+
+ total_err += best_err;
+ }
+
+ subblock_endpoint_quant_err quant_err;
+ quant_err.m_total_err = total_err;
+ quant_err.m_cluster_index = cluster_index;
+ quant_err.m_cluster_subblock_index = cluster_indices_iter;
+ quant_err.m_block_index = block_index;
+ quant_err.m_subblock_index = subblock_index;
+
+ {
+ std::lock_guard<std::mutex> lock(m_lock);
+
+ m_subblock_endpoint_quant_err_vec.push_back(quant_err);
+ }
+ }
+ } // cluster_index
+
+ } );
+ } // cluster_index_iter
+
+ m_params.m_pJob_pool->wait_for_all();
+
+ vector_sort(m_subblock_endpoint_quant_err_vec);
+ }
+
+ void basisu_frontend::introduce_new_endpoint_clusters()
+ {
+ debug_printf("introduce_new_endpoint_clusters\n");
+
+ generate_block_endpoint_clusters();
+
+ int num_new_endpoint_clusters = m_params.m_max_endpoint_clusters - (uint32_t)m_endpoint_clusters.size();
+ if (num_new_endpoint_clusters <= 0)
+ return;
+
+ compute_endpoint_subblock_error_vec();
+
+ const uint32_t num_orig_endpoint_clusters = (uint32_t)m_endpoint_clusters.size();
+
+ std::unordered_set<uint32_t> training_vector_was_relocated;
+
+ uint_vec cluster_sizes(num_orig_endpoint_clusters);
+ for (uint32_t i = 0; i < num_orig_endpoint_clusters; i++)
+ cluster_sizes[i] = (uint32_t)m_endpoint_clusters[i].size();
+
+ std::unordered_set<uint32_t> ignore_cluster;
+
+ while (num_new_endpoint_clusters)
+ {
+ if (m_subblock_endpoint_quant_err_vec.size() == 0)
+ break;
+
+ subblock_endpoint_quant_err subblock_to_move(m_subblock_endpoint_quant_err_vec.back());
+
+ m_subblock_endpoint_quant_err_vec.pop_back();
+
+ if (unordered_set_contains(ignore_cluster, subblock_to_move.m_cluster_index))
+ continue;
+
+ uint32_t training_vector_index = subblock_to_move.m_block_index * 2 + subblock_to_move.m_subblock_index;
+
+ if (cluster_sizes[subblock_to_move.m_cluster_index] <= 2)
+ continue;
+
+ if (unordered_set_contains(training_vector_was_relocated, training_vector_index))
+ continue;
+
+ if (unordered_set_contains(training_vector_was_relocated, training_vector_index ^ 1))
+ continue;
+
+#if 0
+ const uint32_t block_index = subblock_to_move.m_block_index;
+ const etc_block& blk = m_etc1_blocks_etc1s[block_index];
+ uint32_t ls, hs;
+ blk.get_selector_range(ls, hs);
+ if (ls != hs)
+ continue;
+#endif
+
+ const uint32_t new_endpoint_cluster_index = (uint32_t)m_endpoint_clusters.size();
+
+ enlarge_vector(m_endpoint_clusters, 1)->push_back(training_vector_index);
+ enlarge_vector(m_endpoint_cluster_etc_params, 1);
+
+ assert(m_endpoint_clusters.size() == m_endpoint_cluster_etc_params.size());
+
+ training_vector_was_relocated.insert(training_vector_index);
+
+ m_endpoint_clusters.back().push_back(training_vector_index ^ 1);
+ training_vector_was_relocated.insert(training_vector_index ^ 1);
+
+ BASISU_FRONTEND_VERIFY(cluster_sizes[subblock_to_move.m_cluster_index] >= 2);
+ cluster_sizes[subblock_to_move.m_cluster_index] -= 2;
+
+ ignore_cluster.insert(subblock_to_move.m_cluster_index);
+
+ num_new_endpoint_clusters--;
+ }
+
+ for (uint32_t i = 0; i < num_orig_endpoint_clusters; i++)
+ {
+ uint_vec &cluster_indices = m_endpoint_clusters[i];
+
+ uint_vec new_cluster_indices;
+ for (uint32_t j = 0; j < cluster_indices.size(); j++)
+ {
+ uint32_t training_vector_index = cluster_indices[j];
+
+ if (!unordered_set_contains(training_vector_was_relocated, training_vector_index))
+ new_cluster_indices.push_back(training_vector_index);
+ }
+
+ if (cluster_indices.size() != new_cluster_indices.size())
+ {
+ BASISU_FRONTEND_VERIFY(new_cluster_indices.size() > 0);
+ cluster_indices.swap(new_cluster_indices);
+ }
+ }
+
+ generate_block_endpoint_clusters();
+ }
+
+ // Given each endpoint cluster, gather all the block pixels which are in that cluster and compute optimized ETC1S endpoints for them.
+ // TODO: Don't optimize endpoint clusters which haven't changed.
+ void basisu_frontend::generate_endpoint_codebook(uint32_t step)
+ {
+ debug_printf("generate_endpoint_codebook\n");
+
+ m_endpoint_cluster_etc_params.resize(m_endpoint_clusters.size());
+
+ const uint32_t N = 128;
+ for (uint32_t cluster_index_iter = 0; cluster_index_iter < m_endpoint_clusters.size(); cluster_index_iter += N)
+ {
+ const uint32_t first_index = cluster_index_iter;
+ const uint32_t last_index = minimum<uint32_t>((uint32_t)m_endpoint_clusters.size(), cluster_index_iter + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index, step ] {
+
+ for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
+ {
+ const std::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
+
+ BASISU_FRONTEND_VERIFY(cluster_indices.size());
+
+ const uint32_t total_pixels = (uint32_t)cluster_indices.size() * 8;
+
+ std::vector<color_rgba> cluster_pixels(total_pixels);
+
+ for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
+ {
+ const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
+ const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
+
+ const bool flipped = true;
+
+ const color_rgba *pBlock_pixels = get_source_pixel_block(block_index).get_ptr();
+
+ for (uint32_t pixel_index = 0; pixel_index < 8; pixel_index++)
+ {
+ const color_rgba &c = pBlock_pixels[g_etc1_pixel_indices[flipped][subblock_index][pixel_index]];
+ cluster_pixels[cluster_indices_iter * 8 + pixel_index] = c;
+ }
+ }
+
+ endpoint_cluster_etc_params new_subblock_params;
+
+ {
+ etc1_optimizer optimizer;
+ etc1_solution_coordinates solutions[2];
+
+ etc1_optimizer::params cluster_optimizer_params;
+ cluster_optimizer_params.m_num_src_pixels = total_pixels;
+ cluster_optimizer_params.m_pSrc_pixels = &cluster_pixels[0];
+
+ cluster_optimizer_params.m_use_color4 = false;
+ cluster_optimizer_params.m_perceptual = m_params.m_perceptual;
+
+ if (m_params.m_compression_level == 0)
+ cluster_optimizer_params.m_quality = cETCQualityMedium;
+ else if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
+ cluster_optimizer_params.m_quality = cETCQualityUber;
+
+ etc1_optimizer::results cluster_optimizer_results;
+
+ std::vector<uint8_t> cluster_selectors(total_pixels);
+ cluster_optimizer_results.m_n = total_pixels;
+ cluster_optimizer_results.m_pSelectors = &cluster_selectors[0];
+
+ optimizer.init(cluster_optimizer_params, cluster_optimizer_results);
+
+ optimizer.compute();
+
+ new_subblock_params.m_color_unscaled[0] = cluster_optimizer_results.m_block_color_unscaled;
+ new_subblock_params.m_inten_table[0] = cluster_optimizer_results.m_block_inten_table;
+ new_subblock_params.m_color_error[0] = cluster_optimizer_results.m_error;
+ }
+
+ endpoint_cluster_etc_params &prev_etc_params = m_endpoint_cluster_etc_params[cluster_index];
+
+ bool use_new_subblock_params = false;
+ if ((!step) || (!prev_etc_params.m_valid))
+ use_new_subblock_params = true;
+ else
+ {
+ assert(prev_etc_params.m_valid);
+
+ uint64_t total_prev_err = 0;
+
+ {
+ color_rgba block_colors[4];
+
+ etc_block::get_block_colors5(block_colors, prev_etc_params.m_color_unscaled[0], prev_etc_params.m_inten_table[0], false);
+
+ uint64_t total_err = 0;
+
+ for (uint32_t i = 0; i < total_pixels; i++)
+ {
+ const color_rgba &c = cluster_pixels[i];
+
+ uint64_t best_err = UINT64_MAX;
+ //uint32_t best_index = 0;
+
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ uint64_t err = color_distance(m_params.m_perceptual, c, block_colors[s], false);
+ if (err < best_err)
+ {
+ best_err = err;
+ //best_index = s;
+ }
+ }
+
+ total_err += best_err;
+ }
+
+ total_prev_err += total_err;
+ }
+
+ // See if we should update this cluster's endpoints (if the error has actually fallen)
+ if (total_prev_err > new_subblock_params.m_color_error[0])
+ {
+ use_new_subblock_params = true;
+ }
+ }
+
+ if (use_new_subblock_params)
+ {
+ new_subblock_params.m_valid = true;
+
+ prev_etc_params = new_subblock_params;
+ }
+
+ } // cluster_index
+
+ } );
+
+ } // cluster_index_iter
+
+ m_params.m_pJob_pool->wait_for_all();
+ }
+
+ bool basisu_frontend::check_etc1s_constraints() const
+ {
+ std::vector<vec2U> block_clusters(m_total_blocks);
+
+ for (int cluster_index = 0; cluster_index < static_cast<int>(m_endpoint_clusters.size()); cluster_index++)
+ {
+ const std::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
+
+ for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
+ {
+ const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
+ const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
+
+ block_clusters[block_index][subblock_index] = cluster_index;
+
+ } // cluster_indices_iter
+ }
+
+ for (uint32_t i = 0; i < m_total_blocks; i++)
+ {
+ if (block_clusters[i][0] != block_clusters[i][1])
+ return false;
+ }
+
+ return true;
+ }
+
+ uint32_t basisu_frontend::refine_endpoint_clusterization()
+ {
+ debug_printf("refine_endpoint_clusterization\n");
+
+ if (m_use_hierarchical_endpoint_codebooks)
+ compute_endpoint_clusters_within_each_parent_cluster();
+
+ std::vector<vec2U> block_clusters(m_total_blocks);
+
+ for (int cluster_index = 0; cluster_index < static_cast<int>(m_endpoint_clusters.size()); cluster_index++)
+ {
+ const std::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
+
+ for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
+ {
+ const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
+ const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
+
+ block_clusters[block_index][subblock_index] = cluster_index;
+
+ } // cluster_indices_iter
+ }
+
+ //----------------------------------------------------------
+
+ // Create a new endpoint clusterization
+
+ uint_vec best_cluster_indices(m_total_blocks);
+
+ const uint32_t N = 1024;
+ for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ {
+ const uint32_t first_index = block_index_iter;
+ const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index, &best_cluster_indices, &block_clusters] {
+
+ for (uint32_t block_index = first_index; block_index < last_index; block_index++)
+ {
+ const bool is_flipped = true;
+
+ const uint32_t cluster_index = block_clusters[block_index][0];
+ BASISU_FRONTEND_VERIFY(cluster_index == block_clusters[block_index][1]);
+
+ const color_rgba *subblock_pixels = get_source_pixel_block(block_index).get_ptr();
+ const uint32_t num_subblock_pixels = 16;
+
+ uint64_t best_cluster_err = UINT64_MAX;
+ uint32_t best_cluster_index = 0;
+
+ const uint32_t block_parent_endpoint_cluster_index = m_block_parent_endpoint_cluster.size() ? m_block_parent_endpoint_cluster[block_index] : 0;
+ const uint_vec *pCluster_indices = m_endpoint_clusters_within_each_parent_cluster.size() ? &m_endpoint_clusters_within_each_parent_cluster[block_parent_endpoint_cluster_index] : nullptr;
+
+ const uint32_t total_clusters = m_use_hierarchical_endpoint_codebooks ? (uint32_t)pCluster_indices->size() : (uint32_t)m_endpoint_clusters.size();
+
+ for (uint32_t i = 0; i < total_clusters; i++)
+ {
+ const uint32_t cluster_iter = m_use_hierarchical_endpoint_codebooks ? (*pCluster_indices)[i] : i;
+
+ color_rgba cluster_etc_base_color(m_endpoint_cluster_etc_params[cluster_iter].m_color_unscaled[0]);
+ uint32_t cluster_etc_inten = m_endpoint_cluster_etc_params[cluster_iter].m_inten_table[0];
+
+ uint64_t total_err = 0;
+
+ const uint32_t low_selector = 0;//subblock_etc_params_vec[j].m_low_selectors[0];
+ const uint32_t high_selector = 3;//subblock_etc_params_vec[j].m_high_selectors[0];
+ color_rgba subblock_colors[4];
+ // Can't assign it here - may result in too much error when selector quant occurs
+ if (cluster_etc_inten > m_endpoint_cluster_etc_params[cluster_index].m_inten_table[0])
+ {
+ total_err = UINT64_MAX;
+ goto skip_cluster;
+ }
+
+ etc_block::get_block_colors5(subblock_colors, cluster_etc_base_color, cluster_etc_inten);
+
+ for (uint32_t p = 0; p < num_subblock_pixels; p++)
+ {
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t r = low_selector; r <= high_selector; r++)
+ {
+ uint64_t err = color_distance(m_params.m_perceptual, subblock_pixels[p], subblock_colors[r], false);
+ best_err = minimum(best_err, err);
+ if (!best_err)
+ break;
+ }
+
+ total_err += best_err;
+ if (total_err > best_cluster_err)
+ break;
+ } // p
+
+ skip_cluster:
+ if ((total_err < best_cluster_err) ||
+ ((cluster_iter == cluster_index) && (total_err == best_cluster_err)))
+ {
+ best_cluster_err = total_err;
+ best_cluster_index = cluster_iter;
+
+ if (!best_cluster_err)
+ break;
+ }
+ } // j
+
+ best_cluster_indices[block_index] = best_cluster_index;
+
+ } // block_index
+
+ } );
+
+ } // block_index_iter
+
+ m_params.m_pJob_pool->wait_for_all();
+
+ std::vector<typename std::vector<uint32_t> > optimized_endpoint_clusters(m_endpoint_clusters.size());
+ uint32_t total_subblocks_reassigned = 0;
+
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ const uint32_t training_vector_index = block_index * 2 + 0;
+
+ const uint32_t orig_cluster_index = block_clusters[block_index][0];
+ const uint32_t best_cluster_index = best_cluster_indices[block_index];
+
+ optimized_endpoint_clusters[best_cluster_index].push_back(training_vector_index);
+ optimized_endpoint_clusters[best_cluster_index].push_back(training_vector_index + 1);
+
+ if (best_cluster_index != orig_cluster_index)
+ {
+ total_subblocks_reassigned++;
+ }
+ }
+
+ debug_printf("total_subblocks_reassigned: %u\n", total_subblocks_reassigned);
+
+ m_endpoint_clusters = optimized_endpoint_clusters;
+
+ return total_subblocks_reassigned;
+ }
+
+ void basisu_frontend::eliminate_redundant_or_empty_endpoint_clusters()
+ {
+ debug_printf("eliminate_redundant_or_empty_endpoint_clusters\n");
+
+ // Step 1: Sort endpoint clusters by the base colors/intens
+
+ uint_vec sorted_endpoint_cluster_indices(m_endpoint_clusters.size());
+ for (uint32_t i = 0; i < m_endpoint_clusters.size(); i++)
+ sorted_endpoint_cluster_indices[i] = i;
+
+ indirect_sort((uint32_t)m_endpoint_clusters.size(), &sorted_endpoint_cluster_indices[0], &m_endpoint_cluster_etc_params[0]);
+
+ std::vector<std::vector<uint32_t> > new_endpoint_clusters(m_endpoint_clusters.size());
+ std::vector<endpoint_cluster_etc_params> new_subblock_etc_params(m_endpoint_clusters.size());
+
+ for (uint32_t i = 0; i < m_endpoint_clusters.size(); i++)
+ {
+ uint32_t j = sorted_endpoint_cluster_indices[i];
+ new_endpoint_clusters[i] = m_endpoint_clusters[j];
+ new_subblock_etc_params[i] = m_endpoint_cluster_etc_params[j];
+ }
+
+ new_endpoint_clusters.swap(m_endpoint_clusters);
+ new_subblock_etc_params.swap(m_endpoint_cluster_etc_params);
+
+ // Step 2: Eliminate redundant endpoint clusters, or empty endpoint clusters
+
+ new_endpoint_clusters.resize(0);
+ new_subblock_etc_params.resize(0);
+
+ for (int i = 0; i < (int)m_endpoint_clusters.size(); )
+ {
+ if (!m_endpoint_clusters[i].size())
+ {
+ i++;
+ continue;
+ }
+
+ int j;
+ for (j = i + 1; j < (int)m_endpoint_clusters.size(); j++)
+ {
+ if (!(m_endpoint_cluster_etc_params[i] == m_endpoint_cluster_etc_params[j]))
+ break;
+ }
+
+ new_endpoint_clusters.push_back(m_endpoint_clusters[i]);
+ new_subblock_etc_params.push_back(m_endpoint_cluster_etc_params[i]);
+
+ for (int k = i + 1; k < j; k++)
+ {
+ append_vector(new_endpoint_clusters.back(), m_endpoint_clusters[k]);
+ }
+
+ i = j;
+ }
+
+ if (m_endpoint_clusters.size() != new_endpoint_clusters.size())
+ {
+ if (m_params.m_debug_stats)
+ debug_printf("Eliminated %u redundant or empty clusters\n", (uint32_t)(m_endpoint_clusters.size() - new_endpoint_clusters.size()));
+
+ m_endpoint_clusters.swap(new_endpoint_clusters);
+
+ m_endpoint_cluster_etc_params.swap(new_subblock_etc_params);
+ }
+ }
+
+ void basisu_frontend::create_initial_packed_texture()
+ {
+ debug_printf("create_initial_packed_texture\n");
+
+ const uint32_t N = 4096;
+ for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ {
+ const uint32_t first_index = block_index_iter;
+ const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index] {
+
+ for (uint32_t block_index = first_index; block_index < last_index; block_index++)
+ {
+ uint32_t cluster0 = m_block_endpoint_clusters_indices[block_index][0];
+ uint32_t cluster1 = m_block_endpoint_clusters_indices[block_index][1];
+ BASISU_FRONTEND_VERIFY(cluster0 == cluster1);
+
+ const color_rgba *pSource_pixels = get_source_pixel_block(block_index).get_ptr();
+
+ etc_block &blk = m_encoded_blocks[block_index];
+
+ color_rgba unscaled[2] = { m_endpoint_cluster_etc_params[cluster0].m_color_unscaled[0], m_endpoint_cluster_etc_params[cluster1].m_color_unscaled[0] };
+ uint32_t inten[2] = { m_endpoint_cluster_etc_params[cluster0].m_inten_table[0], m_endpoint_cluster_etc_params[cluster1].m_inten_table[0] };
+
+ blk.set_block_color5(unscaled[0], unscaled[1]);
+ blk.set_flip_bit(true);
+
+ blk.set_inten_table(0, inten[0]);
+ blk.set_inten_table(1, inten[1]);
+
+ blk.determine_selectors(pSource_pixels, m_params.m_perceptual);
+
+ } // block_index
+
+ } );
+
+ } // block_index_iter
+
+ m_params.m_pJob_pool->wait_for_all();
+
+ m_orig_encoded_blocks = m_encoded_blocks;
+ }
+
+ void basisu_frontend::compute_selector_clusters_within_each_parent_cluster()
+ {
+ uint_vec block_selector_cluster_indices(m_total_blocks);
+
+ for (int cluster_index = 0; cluster_index < static_cast<int>(m_selector_cluster_indices.size()); cluster_index++)
+ {
+ const std::vector<uint32_t>& cluster_indices = m_selector_cluster_indices[cluster_index];
+
+ for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
+ {
+ const uint32_t block_index = cluster_indices[cluster_indices_iter];
+
+ block_selector_cluster_indices[block_index] = cluster_index;
+
+ } // cluster_indices_iter
+
+ } // cluster_index
+
+ m_selector_clusters_within_each_parent_cluster.resize(0);
+ m_selector_clusters_within_each_parent_cluster.resize(m_selector_parent_cluster_indices.size());
+
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ const uint32_t cluster_index = block_selector_cluster_indices[block_index];
+ const uint32_t parent_cluster_index = m_block_parent_selector_cluster[block_index];
+
+ m_selector_clusters_within_each_parent_cluster[parent_cluster_index].push_back(cluster_index);
+ }
+
+ for (uint32_t i = 0; i < m_selector_clusters_within_each_parent_cluster.size(); i++)
+ {
+ uint_vec &cluster_indices = m_selector_clusters_within_each_parent_cluster[i];
+
+ BASISU_FRONTEND_VERIFY(cluster_indices.size());
+
+ vector_sort(cluster_indices);
+
+ auto last = std::unique(cluster_indices.begin(), cluster_indices.end());
+ cluster_indices.erase(last, cluster_indices.end());
+ }
+ }
+
+ void basisu_frontend::generate_selector_clusters()
+ {
+ debug_printf("generate_selector_clusters\n");
+
+ typedef vec<16, float> vec16F;
+ typedef tree_vector_quant<vec16F> vec16F_clusterizer;
+
+ vec16F_clusterizer::array_of_weighted_training_vecs training_vecs(m_total_blocks);
+
+ const uint32_t N = 4096;
+ for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ {
+ const uint32_t first_index = block_index_iter;
+ const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index, &training_vecs] {
+
+ for (uint32_t block_index = first_index; block_index < last_index; block_index++)
+ {
+ const etc_block &blk = m_encoded_blocks[block_index];
+
+ vec16F v;
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ v[x + y * 4] = static_cast<float>(blk.get_selector(x, y));
+
+ const uint32_t subblock_index = (blk.get_inten_table(0) > blk.get_inten_table(1)) ? 0 : 1;
+
+ color_rgba block_colors[2];
+ blk.get_block_low_high_colors(block_colors, subblock_index);
+
+ const uint32_t dist = color_distance(m_params.m_perceptual, block_colors[0], block_colors[1], false);
+
+ const uint32_t cColorDistToWeight = 300;
+ const uint32_t cMaxWeight = 4096;
+ uint32_t weight = clamp<uint32_t>(dist / cColorDistToWeight, 1, cMaxWeight);
+
+ training_vecs[block_index].first = v;
+ training_vecs[block_index].second = weight;
+
+ } // block_index
+
+ } );
+
+ } // block_index_iter
+
+ m_params.m_pJob_pool->wait_for_all();
+
+ vec16F_clusterizer selector_clusterizer;
+ for (uint32_t i = 0; i < m_total_blocks; i++)
+ selector_clusterizer.add_training_vec(training_vecs[i].first, training_vecs[i].second);
+
+ const uint32_t parent_codebook_size = (m_params.m_max_selector_clusters >= 256) ? BASISU_SELECTOR_PARENT_CODEBOOK_SIZE : 0;
+
+ uint32_t max_threads = 0;
+ max_threads = m_params.m_multithreaded ? minimum<int>(std::thread::hardware_concurrency(), cMaxCodebookCreationThreads) : 0;
+
+ bool status = generate_hierarchical_codebook_threaded(selector_clusterizer,
+ m_params.m_max_selector_clusters, m_use_hierarchical_selector_codebooks ? parent_codebook_size : 0,
+ m_selector_cluster_indices,
+ m_selector_parent_cluster_indices,
+ max_threads, m_params.m_pJob_pool);
+ BASISU_FRONTEND_VERIFY(status);
+
+ if (m_use_hierarchical_selector_codebooks)
+ {
+ if (!m_selector_parent_cluster_indices.size())
+ {
+ m_selector_parent_cluster_indices.resize(0);
+ m_selector_parent_cluster_indices.resize(1);
+ for (uint32_t i = 0; i < m_total_blocks; i++)
+ m_selector_parent_cluster_indices[0].push_back(i);
+ }
+
+ BASISU_ASSUME(BASISU_SELECTOR_PARENT_CODEBOOK_SIZE <= UINT8_MAX);
+
+ m_block_parent_selector_cluster.resize(0);
+ m_block_parent_selector_cluster.resize(m_total_blocks);
+ vector_set_all(m_block_parent_selector_cluster, 0xFF);
+
+ for (uint32_t parent_cluster_index = 0; parent_cluster_index < m_selector_parent_cluster_indices.size(); parent_cluster_index++)
+ {
+ const uint_vec &cluster = m_selector_parent_cluster_indices[parent_cluster_index];
+ for (uint32_t j = 0; j < cluster.size(); j++)
+ m_block_parent_selector_cluster[cluster[j]] = static_cast<uint8_t>(parent_cluster_index);
+ }
+ for (uint32_t i = 0; i < m_total_blocks; i++)
+ {
+ BASISU_FRONTEND_VERIFY(m_block_parent_selector_cluster[i] != 0xFF);
+ }
+
+ // Ensure that all the blocks within each cluster are all in the same parent cluster, or something is very wrong.
+ for (uint32_t cluster_index = 0; cluster_index < m_selector_cluster_indices.size(); cluster_index++)
+ {
+ const uint_vec &cluster = m_selector_cluster_indices[cluster_index];
+
+ uint32_t parent_cluster_index = 0;
+ for (uint32_t j = 0; j < cluster.size(); j++)
+ {
+ const uint32_t block_index = cluster[j];
+ if (!j)
+ {
+ parent_cluster_index = m_block_parent_selector_cluster[block_index];
+ }
+ else
+ {
+ BASISU_FRONTEND_VERIFY(m_block_parent_selector_cluster[block_index] == parent_cluster_index);
+ }
+ }
+ }
+ }
+
+ debug_printf("Total selector clusters: %u, total parent selector clusters: %u\n", (uint32_t)m_selector_cluster_indices.size(), (uint32_t)m_selector_parent_cluster_indices.size());
+ }
+
+ void basisu_frontend::create_optimized_selector_codebook(uint32_t iter)
+ {
+ debug_printf("create_optimized_selector_codebook\n");
+
+ const uint32_t total_selector_clusters = (uint32_t)m_selector_cluster_indices.size();
+
+ m_optimized_cluster_selectors.resize(total_selector_clusters);
+
+ if ((m_params.m_pGlobal_sel_codebook) && (!m_params.m_use_hybrid_selector_codebooks))
+ {
+ uint32_t total_clusters_processed = 0;
+
+ m_optimized_cluster_selector_global_cb_ids.resize(total_selector_clusters);
+
+ const uint32_t N = 256;
+ for (uint32_t cluster_index_iter = 0; cluster_index_iter < total_selector_clusters; cluster_index_iter += N)
+ {
+ const uint32_t first_index = cluster_index_iter;
+ const uint32_t last_index = minimum<uint32_t>((uint32_t)total_selector_clusters, cluster_index_iter + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index, &total_clusters_processed, &total_selector_clusters] {
+
+ for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
+ {
+ const std::vector<uint32_t> &cluster_block_indices = m_selector_cluster_indices[cluster_index];
+
+ if (!cluster_block_indices.size())
+ continue;
+
+ etc_block_vec etc_blocks;
+ pixel_block_vec pixel_blocks;
+
+ for (uint32_t cluster_block_index = 0; cluster_block_index < cluster_block_indices.size(); cluster_block_index++)
+ {
+ const uint32_t block_index = cluster_block_indices[cluster_block_index];
+
+ etc_blocks.push_back(m_encoded_blocks[block_index]);
+
+ pixel_blocks.push_back(get_source_pixel_block(block_index));
+ }
+
+ uint32_t palette_index;
+ basist::etc1_global_palette_entry_modifier palette_modifier;
+
+ #if 0
+ m_params.m_pGlobal_sel_codebook->find_best_entry(etc_blocks.size(), pixel_blocks.get_ptr(), etc_blocks.get_ptr(),
+ palette_index, palette_modifier,
+ m_params.m_perceptual, 1 << m_params.m_num_global_sel_codebook_pal_bits, 1 << m_params.m_num_global_sel_codebook_mod_bits);
+ #else
+ etc1_global_selector_codebook_find_best_entry(*m_params.m_pGlobal_sel_codebook,
+ (uint32_t)etc_blocks.size(), &pixel_blocks[0], &etc_blocks[0],
+ palette_index, palette_modifier,
+ m_params.m_perceptual, 1 << m_params.m_num_global_sel_codebook_pal_bits, 1 << m_params.m_num_global_sel_codebook_mod_bits);
+ #endif
+
+ m_optimized_cluster_selector_global_cb_ids[cluster_index].set(palette_index, palette_modifier);
+
+ basist::etc1_selector_palette_entry pal_entry(m_params.m_pGlobal_sel_codebook->get_entry(palette_index, palette_modifier));
+
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ m_optimized_cluster_selectors[cluster_index].set_selector(x, y, pal_entry(x, y));
+
+ {
+ std::lock_guard<std::mutex> lock(m_lock);
+
+ total_clusters_processed++;
+ if ((total_clusters_processed % 63) == 0)
+ debug_printf("Global selector palette optimization: %3.1f%% complete\n", total_clusters_processed * 100.0f / total_selector_clusters);
+ }
+
+ } // cluster_index
+
+ } );
+
+ } // cluster_index_iter
+
+ m_params.m_pJob_pool->wait_for_all();
+ }
+ else
+ {
+ const bool uses_hybrid_sel_codebook = ((m_params.m_pGlobal_sel_codebook) && (m_params.m_use_hybrid_selector_codebooks));
+ if (uses_hybrid_sel_codebook)
+ {
+ m_selector_cluster_uses_global_cb.resize(total_selector_clusters);
+ m_optimized_cluster_selector_global_cb_ids.resize(total_selector_clusters);
+ }
+
+ uint32_t total_clusters_processed = 0;
+
+ // For each selector codebook entry, and for each of the 4x4 selectors, determine which selector minimizes the error across all the blocks that use that quantized selector.
+
+ const uint32_t N = 256;
+ for (uint32_t cluster_index_iter = 0; cluster_index_iter < total_selector_clusters; cluster_index_iter += N)
+ {
+ const uint32_t first_index = cluster_index_iter;
+ const uint32_t last_index = minimum<uint32_t>((uint32_t)total_selector_clusters, cluster_index_iter + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index, &uses_hybrid_sel_codebook, &total_clusters_processed, &total_selector_clusters] {
+
+ for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
+ {
+ const std::vector<uint32_t> &cluster_block_indices = m_selector_cluster_indices[cluster_index];
+
+ if (!cluster_block_indices.size())
+ continue;
+
+ uint64_t overall_best_err = 0;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint64_t best_err = UINT64_MAX;
+ uint32_t best_s = 0;
+
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ uint32_t total_err = 0;
+
+ for (uint32_t cluster_block_index = 0; cluster_block_index < cluster_block_indices.size(); cluster_block_index++)
+ {
+ const uint32_t block_index = cluster_block_indices[cluster_block_index];
+
+ const etc_block &blk = m_encoded_blocks[block_index];
+
+ const color_rgba &orig_color = get_source_pixel_block(block_index)(x, y);
+
+ color_rgba block_color;
+ blk.get_block_color(block_color, blk.get_subblock_index(x, y), s);
+ total_err += color_distance(m_params.m_perceptual, block_color, orig_color, false);
+
+ if (total_err > best_err)
+ break;
+
+ } // block_index
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_s = s;
+ if (!best_err)
+ break;
+ }
+
+ } // s
+
+ m_optimized_cluster_selectors[cluster_index].set_selector(x, y, best_s);
+
+ overall_best_err += best_err;
+
+ } // x
+ } // y
+
+ if (uses_hybrid_sel_codebook)
+ {
+ etc_block_vec etc_blocks;
+ pixel_block_vec pixel_blocks;
+
+ for (uint32_t cluster_block_index = 0; cluster_block_index < cluster_block_indices.size(); cluster_block_index++)
+ {
+ const uint32_t block_index = cluster_block_indices[cluster_block_index];
+
+ etc_blocks.push_back(m_encoded_blocks[block_index]);
+
+ pixel_blocks.push_back(get_source_pixel_block(block_index));
+ }
+
+ uint32_t palette_index;
+ basist::etc1_global_palette_entry_modifier palette_modifier;
+
+ #if 0
+ uint64_t best_global_cb_err = m_params.m_pGlobal_sel_codebook->find_best_entry(etc_blocks.size(), pixel_blocks.get_ptr(), etc_blocks.get_ptr(),
+ palette_index, palette_modifier,
+ m_params.m_perceptual, 1 << m_params.m_num_global_sel_codebook_pal_bits, 1 << m_params.m_num_global_sel_codebook_mod_bits);
+ #else
+ uint64_t best_global_cb_err = etc1_global_selector_codebook_find_best_entry(*m_params.m_pGlobal_sel_codebook, (uint32_t)etc_blocks.size(), &pixel_blocks[0], &etc_blocks[0],
+ palette_index, palette_modifier,
+ m_params.m_perceptual, 1 << m_params.m_num_global_sel_codebook_pal_bits, 1 << m_params.m_num_global_sel_codebook_mod_bits);
+ #endif
+
+ if (best_global_cb_err <= overall_best_err * m_params.m_hybrid_codebook_quality_thresh)
+ {
+ m_selector_cluster_uses_global_cb[cluster_index] = true;
+
+ m_optimized_cluster_selector_global_cb_ids[cluster_index].set(palette_index, palette_modifier);
+
+ basist::etc1_selector_palette_entry pal_entry(m_params.m_pGlobal_sel_codebook->get_entry(palette_index, palette_modifier));
+
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ m_optimized_cluster_selectors[cluster_index].set_selector(x, y, pal_entry(x, y));
+ }
+ else
+ {
+ m_optimized_cluster_selector_global_cb_ids[cluster_index].set(0, basist::etc1_global_palette_entry_modifier(0));
+
+ m_selector_cluster_uses_global_cb[cluster_index] = false;
+ }
+ }
+
+ if (uses_hybrid_sel_codebook)
+ {
+ std::lock_guard<std::mutex> lock(m_lock);
+
+ total_clusters_processed++;
+ if ((total_clusters_processed % 63) == 0)
+ debug_printf("Global selector palette optimization: %3.1f%% complete\n", total_clusters_processed * 100.0f / total_selector_clusters);
+ }
+
+ } // cluster_index
+
+ } );
+
+ } // cluster_index_iter
+
+ m_params.m_pJob_pool->wait_for_all();
+
+ } // if (m_params.m_pGlobal_sel_codebook)
+
+ if (m_params.m_debug_images)
+ {
+ uint32_t max_selector_cluster_size = 0;
+
+ for (uint32_t i = 0; i < m_selector_cluster_indices.size(); i++)
+ max_selector_cluster_size = maximum<uint32_t>(max_selector_cluster_size, (uint32_t)m_selector_cluster_indices[i].size());
+
+ if ((max_selector_cluster_size * 5) < 32768)
+ {
+ const uint32_t x_spacer_len = 16;
+ image selector_cluster_vis(x_spacer_len + max_selector_cluster_size * 5, (uint32_t)m_selector_cluster_indices.size() * 5);
+
+ for (uint32_t selector_cluster_index = 0; selector_cluster_index < m_selector_cluster_indices.size(); selector_cluster_index++)
+ {
+ const std::vector<uint32_t> &cluster_block_indices = m_selector_cluster_indices[selector_cluster_index];
+
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ selector_cluster_vis.set_clipped(x_spacer_len + x - 12, selector_cluster_index * 5 + y, color_rgba((m_optimized_cluster_selectors[selector_cluster_index].get_selector(x, y) * 255) / 3));
+
+ for (uint32_t i = 0; i < cluster_block_indices.size(); i++)
+ {
+ uint32_t block_index = cluster_block_indices[i];
+
+ const etc_block &blk = m_orig_encoded_blocks[block_index];
+
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ selector_cluster_vis.set_clipped(x_spacer_len + x + 5 * i, selector_cluster_index * 5 + y, color_rgba((blk.get_selector(x, y) * 255) / 3));
+ }
+ }
+
+ char buf[256];
+ snprintf(buf, sizeof(buf), "selector_cluster_vis_%u.png", iter);
+ save_png(buf, selector_cluster_vis);
+ }
+ }
+ }
+
+ void basisu_frontend::find_optimal_selector_clusters_for_each_block()
+ {
+ debug_printf("find_optimal_selector_clusters_for_each_block\n");
+
+ m_block_selector_cluster_index.resize(m_total_blocks);
+
+ if (m_params.m_compression_level == 0)
+ {
+ // Don't do anything, just leave the blocks in their original selector clusters.
+ for (uint32_t i = 0; i < m_selector_cluster_indices.size(); i++)
+ {
+ for (uint32_t j = 0; j < m_selector_cluster_indices[i].size(); j++)
+ m_block_selector_cluster_index[m_selector_cluster_indices[i][j]] = i;
+ }
+ }
+ else
+ {
+ std::vector< std::vector<uint32_t> > new_cluster_indices;
+
+ // For each block: Determine which quantized selectors best encode that block, given its quantized endpoints.
+
+ const uint32_t N = 1024;
+ for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ {
+ const uint32_t first_index = block_index_iter;
+ const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index, &new_cluster_indices] {
+
+ for (uint32_t block_index = first_index; block_index < last_index; block_index++)
+ {
+ const color_rgba* pBlock_pixels = get_source_pixel_block(block_index).get_ptr();
+
+ etc_block& blk = m_encoded_blocks[block_index];
+
+ color_rgba trial_block_colors[4];
+ blk.get_block_colors(trial_block_colors, 0);
+
+ uint64_t best_cluster_err = UINT64_MAX;
+ uint32_t best_cluster_index = 0;
+
+ const uint32_t parent_selector_cluster = m_block_parent_selector_cluster.size() ? m_block_parent_selector_cluster[block_index] : 0;
+ const uint_vec *pCluster_indices = m_selector_clusters_within_each_parent_cluster.size() ? &m_selector_clusters_within_each_parent_cluster[parent_selector_cluster] : nullptr;
+
+ const uint32_t total_clusters = m_use_hierarchical_selector_codebooks ? (uint32_t)pCluster_indices->size() : (uint32_t)m_selector_cluster_indices.size();
+
+ for (uint32_t cluster_iter = 0; cluster_iter < total_clusters; cluster_iter++)
+ {
+ const uint32_t cluster_index = m_use_hierarchical_selector_codebooks ? (*pCluster_indices)[cluster_iter] : cluster_iter;
+
+ const etc_block& cluster_blk = m_optimized_cluster_selectors[cluster_index];
+
+ uint64_t trial_err = 0;
+ for (int y = 0; y < 4; y++)
+ {
+ for (int x = 0; x < 4; x++)
+ {
+ const uint32_t sel = cluster_blk.get_selector(x, y);
+
+ trial_err += color_distance(m_params.m_perceptual, trial_block_colors[sel], pBlock_pixels[x + y * 4], false);
+ if (trial_err > best_cluster_err)
+ goto early_out;
+ }
+ }
+
+ if (trial_err < best_cluster_err)
+ {
+ best_cluster_err = trial_err;
+ best_cluster_index = cluster_index;
+ if (!best_cluster_err)
+ break;
+ }
+
+ early_out:
+ ;
+ }
+
+ blk.set_raw_selector_bits(m_optimized_cluster_selectors[best_cluster_index].get_raw_selector_bits());
+
+ m_block_selector_cluster_index[block_index] = best_cluster_index;
+
+ {
+ std::lock_guard<std::mutex> lock(m_lock);
+
+ vector_ensure_element_is_valid(new_cluster_indices, best_cluster_index);
+ new_cluster_indices[best_cluster_index].push_back(block_index);
+ }
+
+ } // block_index
+
+ } );
+
+ } // block_index_iter
+
+ m_params.m_pJob_pool->wait_for_all();
+
+ m_selector_cluster_indices.swap(new_cluster_indices);
+ }
+
+ for (uint32_t i = 0; i < m_selector_cluster_indices.size(); i++)
+ vector_sort(m_selector_cluster_indices[i]);
+ }
+
+ // TODO: Remove old ETC1 specific stuff, and thread this.
+ uint32_t basisu_frontend::refine_block_endpoints_given_selectors()
+ {
+ debug_printf("refine_block_endpoints_given_selectors\n");
+
+ for (int block_index = 0; block_index < static_cast<int>(m_total_blocks); block_index++)
+ {
+ //uint32_t selector_cluster = m_block_selector_cluster_index(block_x, block_y);
+ vec2U &endpoint_clusters = m_block_endpoint_clusters_indices[block_index];
+
+ m_endpoint_cluster_etc_params[endpoint_clusters[0]].m_subblocks.push_back(block_index * 2);
+
+ m_endpoint_cluster_etc_params[endpoint_clusters[1]].m_subblocks.push_back(block_index * 2 + 1);
+ }
+
+ uint32_t total_subblocks_refined = 0;
+ uint32_t total_subblocks_examined = 0;
+
+ for (uint32_t endpoint_cluster_index = 0; endpoint_cluster_index < m_endpoint_cluster_etc_params.size(); endpoint_cluster_index++)
+ {
+ endpoint_cluster_etc_params &subblock_params = m_endpoint_cluster_etc_params[endpoint_cluster_index];
+
+ const uint_vec &subblocks = subblock_params.m_subblocks;
+ //uint32_t total_pixels = subblock.m_subblocks.size() * 8;
+
+ std::vector<color_rgba> subblock_colors[2]; // [use_individual_mode]
+ uint8_vec subblock_selectors[2];
+
+ uint64_t cur_subblock_err[2] = { 0, 0 };
+
+ for (uint32_t subblock_iter = 0; subblock_iter < subblocks.size(); subblock_iter++)
+ {
+ uint32_t training_vector_index = subblocks[subblock_iter];
+
+ uint32_t block_index = training_vector_index >> 1;
+ uint32_t subblock_index = training_vector_index & 1;
+ const bool is_flipped = true;
+
+ const etc_block &blk = m_encoded_blocks[block_index];
+
+ const bool use_individual_mode = !blk.get_diff_bit();
+
+ const color_rgba *pSource_block_pixels = get_source_pixel_block(block_index).get_ptr();
+
+ color_rgba unpacked_block_pixels[16];
+ unpack_etc1(blk, unpacked_block_pixels);
+
+ for (uint32_t i = 0; i < 8; i++)
+ {
+ const uint32_t pixel_index = g_etc1_pixel_indices[is_flipped][subblock_index][i];
+ const etc_coord2 &coords = g_etc1_pixel_coords[is_flipped][subblock_index][i];
+
+ subblock_colors[use_individual_mode].push_back(pSource_block_pixels[pixel_index]);
+
+ cur_subblock_err[use_individual_mode] += color_distance(m_params.m_perceptual, pSource_block_pixels[pixel_index], unpacked_block_pixels[pixel_index], false);
+
+ subblock_selectors[use_individual_mode].push_back(static_cast<uint8_t>(blk.get_selector(coords.m_x, coords.m_y)));
+ }
+ } // subblock_iter
+
+ etc1_optimizer::results cluster_optimizer_results[2];
+ bool results_valid[2] = { false, false };
+
+ clear_obj(cluster_optimizer_results);
+
+ std::vector<uint8_t> cluster_selectors[2];
+
+ for (uint32_t use_individual_mode = 0; use_individual_mode < 2; use_individual_mode++)
+ {
+ const uint32_t total_pixels = (uint32_t)subblock_colors[use_individual_mode].size();
+
+ if (!total_pixels)
+ continue;
+
+ total_subblocks_examined += total_pixels / 8;
+
+ etc1_optimizer optimizer;
+ etc1_solution_coordinates solutions[2];
+
+ etc1_optimizer::params cluster_optimizer_params;
+ cluster_optimizer_params.m_num_src_pixels = total_pixels;
+ cluster_optimizer_params.m_pSrc_pixels = &subblock_colors[use_individual_mode][0];
+
+ cluster_optimizer_params.m_use_color4 = use_individual_mode != 0;
+ cluster_optimizer_params.m_perceptual = m_params.m_perceptual;
+
+ cluster_optimizer_params.m_pForce_selectors = &subblock_selectors[use_individual_mode][0];
+ cluster_optimizer_params.m_quality = cETCQualityUber;
+
+ cluster_selectors[use_individual_mode].resize(total_pixels);
+
+ cluster_optimizer_results[use_individual_mode].m_n = total_pixels;
+ cluster_optimizer_results[use_individual_mode].m_pSelectors = &cluster_selectors[use_individual_mode][0];
+
+ optimizer.init(cluster_optimizer_params, cluster_optimizer_results[use_individual_mode]);
+
+ if (!optimizer.compute())
+ continue;
+
+ if (cluster_optimizer_results[use_individual_mode].m_error < cur_subblock_err[use_individual_mode])
+ results_valid[use_individual_mode] = true;
+
+ } // use_individual_mode
+
+ for (uint32_t use_individual_mode = 0; use_individual_mode < 2; use_individual_mode++)
+ {
+ if (!results_valid[use_individual_mode])
+ continue;
+
+ uint32_t num_passes = use_individual_mode ? 1 : 2;
+
+ bool all_passed5 = true;
+
+ for (uint32_t pass = 0; pass < num_passes; pass++)
+ {
+ for (uint32_t subblock_iter = 0; subblock_iter < subblocks.size(); subblock_iter++)
+ {
+ const uint32_t training_vector_index = subblocks[subblock_iter];
+
+ const uint32_t block_index = training_vector_index >> 1;
+ const uint32_t subblock_index = training_vector_index & 1;
+ const bool is_flipped = true;
+
+ etc_block &blk = m_encoded_blocks[block_index];
+
+ if (!blk.get_diff_bit() != static_cast<bool>(use_individual_mode != 0))
+ continue;
+
+ if (use_individual_mode)
+ {
+ blk.set_base4_color(subblock_index, etc_block::pack_color4(cluster_optimizer_results[1].m_block_color_unscaled, false));
+ blk.set_inten_table(subblock_index, cluster_optimizer_results[1].m_block_inten_table);
+
+ subblock_params.m_color_error[1] = cluster_optimizer_results[1].m_error;
+ subblock_params.m_inten_table[1] = cluster_optimizer_results[1].m_block_inten_table;
+ subblock_params.m_color_unscaled[1] = cluster_optimizer_results[1].m_block_color_unscaled;
+
+ total_subblocks_refined++;
+ }
+ else
+ {
+ const uint16_t base_color5 = blk.get_base5_color();
+ const uint16_t delta_color3 = blk.get_delta3_color();
+
+ uint32_t r[2], g[2], b[2];
+ etc_block::unpack_color5(r[0], g[0], b[0], base_color5, false);
+ bool success = etc_block::unpack_color5(r[1], g[1], b[1], base_color5, delta_color3, false);
+ assert(success);
+ BASISU_NOTE_UNUSED(success);
+
+ r[subblock_index] = cluster_optimizer_results[0].m_block_color_unscaled.r;
+ g[subblock_index] = cluster_optimizer_results[0].m_block_color_unscaled.g;
+ b[subblock_index] = cluster_optimizer_results[0].m_block_color_unscaled.b;
+
+ color_rgba colors[2] = { color_rgba(r[0], g[0], b[0], 255), color_rgba(r[1], g[1], b[1], 255) };
+
+ if (!etc_block::try_pack_color5_delta3(colors))
+ {
+ all_passed5 = false;
+ break;
+ }
+
+ if ((pass == 1) && (all_passed5))
+ {
+ blk.set_block_color5(colors[0], colors[1]);
+ blk.set_inten_table(subblock_index, cluster_optimizer_results[0].m_block_inten_table);
+
+ subblock_params.m_color_error[0] = cluster_optimizer_results[0].m_error;
+ subblock_params.m_inten_table[0] = cluster_optimizer_results[0].m_block_inten_table;
+ subblock_params.m_color_unscaled[0] = cluster_optimizer_results[0].m_block_color_unscaled;
+
+ total_subblocks_refined++;
+ }
+ }
+
+ } // subblock_iter
+
+ } // pass
+
+ } // use_individual_mode
+
+ } // endpoint_cluster_index
+
+ if (m_params.m_debug_stats)
+ debug_printf("Total subblock endpoints refined: %u (%3.1f%%)\n", total_subblocks_refined, total_subblocks_refined * 100.0f / total_subblocks_examined);
+
+ return total_subblocks_refined;
+ }
+
+ void basisu_frontend::dump_endpoint_clusterization_visualization(const char *pFilename, bool vis_endpoint_colors)
+ {
+ debug_printf("dump_endpoint_clusterization_visualization\n");
+
+ uint32_t max_endpoint_cluster_size = 0;
+
+ std::vector<uint32_t> cluster_sizes(m_endpoint_clusters.size());
+ std::vector<uint32_t> sorted_cluster_indices(m_endpoint_clusters.size());
+ for (uint32_t i = 0; i < m_endpoint_clusters.size(); i++)
+ {
+ max_endpoint_cluster_size = maximum<uint32_t>(max_endpoint_cluster_size, (uint32_t)m_endpoint_clusters[i].size());
+ cluster_sizes[i] = (uint32_t)m_endpoint_clusters[i].size();
+ }
+
+ if (!max_endpoint_cluster_size)
+ return;
+
+ for (uint32_t i = 0; i < m_endpoint_clusters.size(); i++)
+ sorted_cluster_indices[i] = i;
+
+ //indexed_heap_sort(endpoint_clusters.size(), cluster_sizes.get_ptr(), sorted_cluster_indices.get_ptr());
+
+ image endpoint_cluster_vis(12 + minimum<uint32_t>(max_endpoint_cluster_size, 2048) * 5, (uint32_t)m_endpoint_clusters.size() * 3);
+
+ for (uint32_t unsorted_cluster_iter = 0; unsorted_cluster_iter < m_endpoint_clusters.size(); unsorted_cluster_iter++)
+ {
+ const uint32_t cluster_iter = sorted_cluster_indices[unsorted_cluster_iter];
+
+ etc_block blk;
+ blk.clear();
+ blk.set_flip_bit(false);
+ blk.set_diff_bit(true);
+ blk.set_inten_tables_etc1s(m_endpoint_cluster_etc_params[cluster_iter].m_inten_table[0]);
+ blk.set_base5_color(etc_block::pack_color5(m_endpoint_cluster_etc_params[cluster_iter].m_color_unscaled[0], false));
+
+ color_rgba blk_colors[4];
+ blk.get_block_colors(blk_colors, 0);
+ for (uint32_t i = 0; i < 4; i++)
+ endpoint_cluster_vis.fill_box(i * 2, 3 * unsorted_cluster_iter, 2, 2, blk_colors[i]);
+
+ for (uint32_t subblock_iter = 0; subblock_iter < m_endpoint_clusters[cluster_iter].size(); subblock_iter++)
+ {
+ uint32_t training_vector_index = m_endpoint_clusters[cluster_iter][subblock_iter];
+
+ const uint32_t block_index = training_vector_index >> 1;
+ const uint32_t subblock_index = training_vector_index & 1;
+
+ const etc_block& blk2 = m_etc1_blocks_etc1s[block_index];
+
+ const color_rgba *pBlock_pixels = get_source_pixel_block(block_index).get_ptr();
+
+ color_rgba subblock_pixels[8];
+
+ if (vis_endpoint_colors)
+ {
+ color_rgba colors[2];
+ blk2.get_block_low_high_colors(colors, subblock_index);
+ for (uint32_t i = 0; i < 8; i++)
+ subblock_pixels[i] = colors[subblock_index];
+ }
+ else
+ {
+ for (uint32_t i = 0; i < 8; i++)
+ subblock_pixels[i] = pBlock_pixels[g_etc1_pixel_indices[blk2.get_flip_bit()][subblock_index][i]];
+ }
+
+ endpoint_cluster_vis.set_block_clipped(subblock_pixels, 12 + 5 * subblock_iter, 3 * unsorted_cluster_iter, 4, 2);
+ }
+ }
+
+ save_png(pFilename, endpoint_cluster_vis);
+ debug_printf("Wrote debug visualization file %s\n", pFilename);
+ }
+
+ void basisu_frontend::finalize()
+ {
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ for (uint32_t subblock_index = 0; subblock_index < 2; subblock_index++)
+ {
+ const uint32_t endpoint_cluster_index = get_subblock_endpoint_cluster_index(block_index, subblock_index);
+
+ m_endpoint_cluster_etc_params[endpoint_cluster_index].m_color_used[0] = true;
+ }
+ }
+ }
+
+ // The backend has remapped the block endpoints while optimizing the output symbols for better rate distortion performance, so let's go and reoptimize the endpoint codebook.
+ // This is currently the only place where the backend actually goes and changes the quantization and calls the frontend to fix things up.
+ // This is basically a bottom up clusterization stage, where some leaves can be combined.
+ void basisu_frontend::reoptimize_remapped_endpoints(const uint_vec &new_block_endpoints, int_vec &old_to_new_endpoint_cluster_indices, bool optimize_final_codebook, uint_vec *pBlock_selector_indices)
+ {
+ debug_printf("reoptimize_remapped_endpoints\n");
+
+ std::vector<uint_vec> new_endpoint_cluster_block_indices(m_endpoint_clusters.size());
+ for (uint32_t i = 0; i < new_block_endpoints.size(); i++)
+ new_endpoint_cluster_block_indices[new_block_endpoints[i]].push_back(i);
+
+ std::vector<uint8_t> cluster_valid(new_endpoint_cluster_block_indices.size());
+ std::vector<uint8_t> cluster_improved(new_endpoint_cluster_block_indices.size());
+
+ const uint32_t N = 256;
+ for (uint32_t cluster_index_iter = 0; cluster_index_iter < new_endpoint_cluster_block_indices.size(); cluster_index_iter += N)
+ {
+ const uint32_t first_index = cluster_index_iter;
+ const uint32_t last_index = minimum<uint32_t>((uint32_t)new_endpoint_cluster_block_indices.size(), cluster_index_iter + N);
+
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index, &cluster_improved, &cluster_valid, &new_endpoint_cluster_block_indices, &pBlock_selector_indices ] {
+ for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
+ {
+ const std::vector<uint32_t>& cluster_block_indices = new_endpoint_cluster_block_indices[cluster_index];
+
+ if (!cluster_block_indices.size())
+ continue;
+
+ const uint32_t total_pixels = (uint32_t)cluster_block_indices.size() * 16;
+
+ std::vector<color_rgba> cluster_pixels(total_pixels);
+ uint8_vec force_selectors(total_pixels);
+
+ etc_block blk;
+ blk.set_block_color5_etc1s(get_endpoint_cluster_unscaled_color(cluster_index, false));
+ blk.set_inten_tables_etc1s(get_endpoint_cluster_inten_table(cluster_index, false));
+ blk.set_flip_bit(true);
+
+ uint64_t cur_err = 0;
+
+ for (uint32_t cluster_block_indices_iter = 0; cluster_block_indices_iter < cluster_block_indices.size(); cluster_block_indices_iter++)
+ {
+ const uint32_t block_index = cluster_block_indices[cluster_block_indices_iter];
+
+ const color_rgba *pBlock_pixels = get_source_pixel_block(block_index).get_ptr();
+
+ memcpy(&cluster_pixels[cluster_block_indices_iter * 16], pBlock_pixels, 16 * sizeof(color_rgba));
+
+ const uint32_t selector_cluster_index = pBlock_selector_indices ? (*pBlock_selector_indices)[block_index] : get_block_selector_cluster_index(block_index);
+
+ const etc_block &blk_selectors = get_selector_cluster_selector_bits(selector_cluster_index);
+
+ blk.set_raw_selector_bits(blk_selectors.get_raw_selector_bits());
+
+ cur_err += blk.evaluate_etc1_error(pBlock_pixels, m_params.m_perceptual);
+
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ force_selectors[cluster_block_indices_iter * 16 + x + y * 4] = static_cast<uint8_t>(blk_selectors.get_selector(x, y));
+ }
+
+ endpoint_cluster_etc_params new_endpoint_cluster_etc_params;
+
+ {
+ etc1_optimizer optimizer;
+ etc1_solution_coordinates solutions[2];
+
+ etc1_optimizer::params cluster_optimizer_params;
+ cluster_optimizer_params.m_num_src_pixels = total_pixels;
+ cluster_optimizer_params.m_pSrc_pixels = &cluster_pixels[0];
+
+ cluster_optimizer_params.m_use_color4 = false;
+ cluster_optimizer_params.m_perceptual = m_params.m_perceptual;
+ cluster_optimizer_params.m_pForce_selectors = &force_selectors[0];
+
+ if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
+ cluster_optimizer_params.m_quality = cETCQualityUber;
+
+ etc1_optimizer::results cluster_optimizer_results;
+
+ std::vector<uint8_t> cluster_selectors(total_pixels);
+ cluster_optimizer_results.m_n = total_pixels;
+ cluster_optimizer_results.m_pSelectors = &cluster_selectors[0];
+
+ optimizer.init(cluster_optimizer_params, cluster_optimizer_results);
+
+ optimizer.compute();
+
+ new_endpoint_cluster_etc_params.m_color_unscaled[0] = cluster_optimizer_results.m_block_color_unscaled;
+ new_endpoint_cluster_etc_params.m_inten_table[0] = cluster_optimizer_results.m_block_inten_table;
+ new_endpoint_cluster_etc_params.m_color_error[0] = cluster_optimizer_results.m_error;
+ new_endpoint_cluster_etc_params.m_color_used[0] = true;
+ new_endpoint_cluster_etc_params.m_valid = true;
+ }
+
+ if (new_endpoint_cluster_etc_params.m_color_error[0] < cur_err)
+ {
+ m_endpoint_cluster_etc_params[cluster_index] = new_endpoint_cluster_etc_params;
+
+ cluster_improved[cluster_index] = true;
+ }
+
+ cluster_valid[cluster_index] = true;
+
+ } // cluster_index
+ } );
+
+ } // cluster_index_iter
+
+ m_params.m_pJob_pool->wait_for_all();
+
+ uint32_t total_unused_clusters = 0;
+ uint32_t total_improved_clusters = 0;
+
+ old_to_new_endpoint_cluster_indices.resize(m_endpoint_clusters.size());
+ vector_set_all(old_to_new_endpoint_cluster_indices, -1);
+
+ int total_new_endpoint_clusters = 0;
+
+ for (uint32_t old_cluster_index = 0; old_cluster_index < m_endpoint_clusters.size(); old_cluster_index++)
+ {
+ if (!cluster_valid[old_cluster_index])
+ total_unused_clusters++;
+ else
+ old_to_new_endpoint_cluster_indices[old_cluster_index] = total_new_endpoint_clusters++;
+
+ if (cluster_improved[old_cluster_index])
+ total_improved_clusters++;
+ }
+
+ debug_printf("Total unused clusters: %u\n", total_unused_clusters);
+ debug_printf("Total improved_clusters: %u\n", total_improved_clusters);
+ debug_printf("Total endpoint clusters: %u\n", total_new_endpoint_clusters);
+
+ if (optimize_final_codebook)
+ {
+ cluster_subblock_etc_params_vec new_endpoint_cluster_etc_params(total_new_endpoint_clusters);
+
+ for (uint32_t old_cluster_index = 0; old_cluster_index < m_endpoint_clusters.size(); old_cluster_index++)
+ {
+ if (old_to_new_endpoint_cluster_indices[old_cluster_index] >= 0)
+ new_endpoint_cluster_etc_params[old_to_new_endpoint_cluster_indices[old_cluster_index]] = m_endpoint_cluster_etc_params[old_cluster_index];
+ }
+
+ debug_printf("basisu_frontend::reoptimize_remapped_endpoints: stage 1\n");
+
+ std::vector<uint_vec> new_endpoint_clusters(total_new_endpoint_clusters);
+
+ for (uint32_t block_index = 0; block_index < new_block_endpoints.size(); block_index++)
+ {
+ const uint32_t old_endpoint_cluster_index = new_block_endpoints[block_index];
+
+ const int new_endpoint_cluster_index = old_to_new_endpoint_cluster_indices[old_endpoint_cluster_index];
+ BASISU_FRONTEND_VERIFY(new_endpoint_cluster_index >= 0);
+
+ BASISU_FRONTEND_VERIFY(new_endpoint_cluster_index < (int)new_endpoint_clusters.size());
+
+ new_endpoint_clusters[new_endpoint_cluster_index].push_back(block_index * 2 + 0);
+ new_endpoint_clusters[new_endpoint_cluster_index].push_back(block_index * 2 + 1);
+
+ BASISU_FRONTEND_VERIFY(new_endpoint_cluster_index < (int)new_endpoint_cluster_etc_params.size());
+
+ new_endpoint_cluster_etc_params[new_endpoint_cluster_index].m_subblocks.push_back(block_index * 2 + 0);
+ new_endpoint_cluster_etc_params[new_endpoint_cluster_index].m_subblocks.push_back(block_index * 2 + 1);
+
+ m_block_endpoint_clusters_indices[block_index][0] = new_endpoint_cluster_index;
+ m_block_endpoint_clusters_indices[block_index][1] = new_endpoint_cluster_index;
+ }
+
+ debug_printf("basisu_frontend::reoptimize_remapped_endpoints: stage 2\n");
+
+ m_endpoint_clusters = new_endpoint_clusters;
+ m_endpoint_cluster_etc_params = new_endpoint_cluster_etc_params;
+
+ eliminate_redundant_or_empty_endpoint_clusters();
+
+ debug_printf("basisu_frontend::reoptimize_remapped_endpoints: stage 3\n");
+
+ for (uint32_t new_cluster_index = 0; new_cluster_index < m_endpoint_clusters.size(); new_cluster_index++)
+ {
+ for (uint32_t cluster_block_iter = 0; cluster_block_iter < m_endpoint_clusters[new_cluster_index].size(); cluster_block_iter++)
+ {
+ const uint32_t subblock_index = m_endpoint_clusters[new_cluster_index][cluster_block_iter];
+ const uint32_t block_index = subblock_index >> 1;
+
+ m_block_endpoint_clusters_indices[block_index][0] = new_cluster_index;
+ m_block_endpoint_clusters_indices[block_index][1] = new_cluster_index;
+
+ const uint32_t old_cluster_index = new_block_endpoints[block_index];
+
+ old_to_new_endpoint_cluster_indices[old_cluster_index] = new_cluster_index;
+ }
+ }
+
+ debug_printf("basisu_frontend::reoptimize_remapped_endpoints: stage 4\n");
+
+ for (uint32_t block_index = 0; block_index < m_encoded_blocks.size(); block_index++)
+ {
+ const uint32_t endpoint_cluster_index = get_subblock_endpoint_cluster_index(block_index, 0);
+
+ m_encoded_blocks[block_index].set_block_color5_etc1s(get_endpoint_cluster_unscaled_color(endpoint_cluster_index, false));
+ m_encoded_blocks[block_index].set_inten_tables_etc1s(get_endpoint_cluster_inten_table(endpoint_cluster_index, false));
+ }
+
+ debug_printf("Final (post-RDO) endpoint clusters: %u\n", m_endpoint_clusters.size());
+ }
+
+ //debug_printf("validate_output: %u\n", validate_output());
+ }
+
+ bool basisu_frontend::validate_output() const
+ {
+ debug_printf("validate_output\n");
+
+ if (!check_etc1s_constraints())
+ return false;
+
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+//#define CHECK(x) do { if (!(x)) { DebugBreak(); return false; } } while(0)
+#define CHECK(x) BASISU_FRONTEND_VERIFY(x);
+
+ CHECK(get_output_block(block_index).get_flip_bit() == true);
+
+ const bool diff_flag = get_diff_flag(block_index);
+ CHECK(diff_flag == true);
+
+ etc_block blk;
+ memset(&blk, 0, sizeof(blk));
+ blk.set_flip_bit(true);
+ blk.set_diff_bit(true);
+
+ const uint32_t endpoint_cluster0_index = get_subblock_endpoint_cluster_index(block_index, 0);
+ const uint32_t endpoint_cluster1_index = get_subblock_endpoint_cluster_index(block_index, 1);
+
+ // basisu only supports ETC1S, so these must be equal.
+ CHECK(endpoint_cluster0_index == endpoint_cluster1_index);
+
+ CHECK(blk.set_block_color5_check(get_endpoint_cluster_unscaled_color(endpoint_cluster0_index, false), get_endpoint_cluster_unscaled_color(endpoint_cluster1_index, false)));
+
+ CHECK(get_endpoint_cluster_color_is_used(endpoint_cluster0_index, false));
+
+ blk.set_inten_table(0, get_endpoint_cluster_inten_table(endpoint_cluster0_index, false));
+ blk.set_inten_table(1, get_endpoint_cluster_inten_table(endpoint_cluster1_index, false));
+
+ const uint32_t selector_cluster_index = get_block_selector_cluster_index(block_index);
+ CHECK(selector_cluster_index < get_total_selector_clusters());
+
+ CHECK(vector_find(get_selector_cluster_block_indices(selector_cluster_index), block_index) != -1);
+
+ blk.set_raw_selector_bits(get_selector_cluster_selector_bits(selector_cluster_index).get_raw_selector_bits());
+
+ const etc_block &rdo_output_block = get_output_block(block_index);
+
+ CHECK(rdo_output_block.get_flip_bit() == blk.get_flip_bit());
+ CHECK(rdo_output_block.get_diff_bit() == blk.get_diff_bit());
+ CHECK(rdo_output_block.get_inten_table(0) == blk.get_inten_table(0));
+ CHECK(rdo_output_block.get_inten_table(1) == blk.get_inten_table(1));
+ CHECK(rdo_output_block.get_base5_color() == blk.get_base5_color());
+ CHECK(rdo_output_block.get_delta3_color() == blk.get_delta3_color());
+ CHECK(rdo_output_block.get_raw_selector_bits() == blk.get_raw_selector_bits());
+
+ if (m_params.m_pGlobal_sel_codebook)
+ {
+ bool used_global_cb = true;
+ if (m_params.m_use_hybrid_selector_codebooks)
+ used_global_cb = m_selector_cluster_uses_global_cb[selector_cluster_index];
+
+ if (used_global_cb)
+ {
+ basist::etc1_global_selector_codebook_entry_id pal_id(get_selector_cluster_global_selector_entry_ids()[selector_cluster_index]);
+
+ basist::etc1_selector_palette_entry pal_entry(m_params.m_pGlobal_sel_codebook->get_entry(pal_id));
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ CHECK(pal_entry(x, y) == blk.get_selector(x, y));
+ }
+ }
+ }
+ }
+
+#undef CHECK
+ }
+
+ return true;
+ }
+
+ void basisu_frontend::dump_debug_image(const char *pFilename, uint32_t first_block, uint32_t num_blocks_x, uint32_t num_blocks_y, bool output_blocks)
+ {
+ gpu_image g;
+ g.init(texture_format::cETC1, num_blocks_x * 4, num_blocks_y * 4);
+
+ for (uint32_t y = 0; y < num_blocks_y; y++)
+ {
+ for (uint32_t x = 0; x < num_blocks_x; x++)
+ {
+ const uint32_t block_index = first_block + x + y * num_blocks_x;
+
+ etc_block &blk = *(etc_block *)g.get_block_ptr(x, y);
+
+ if (output_blocks)
+ blk = get_output_block(block_index);
+ else
+ {
+ const bool diff_flag = get_diff_flag(block_index);
+
+ blk.set_diff_bit(diff_flag);
+ blk.set_flip_bit(true);
+
+ const uint32_t endpoint_cluster0_index = get_subblock_endpoint_cluster_index(block_index, 0);
+ const uint32_t endpoint_cluster1_index = get_subblock_endpoint_cluster_index(block_index, 1);
+
+ if (diff_flag)
+ blk.set_block_color5(get_endpoint_cluster_unscaled_color(endpoint_cluster0_index, false), get_endpoint_cluster_unscaled_color(endpoint_cluster1_index, false));
+ else
+ blk.set_block_color4(get_endpoint_cluster_unscaled_color(endpoint_cluster0_index, true), get_endpoint_cluster_unscaled_color(endpoint_cluster1_index, true));
+
+ blk.set_inten_table(0, get_endpoint_cluster_inten_table(endpoint_cluster0_index, !diff_flag));
+ blk.set_inten_table(1, get_endpoint_cluster_inten_table(endpoint_cluster1_index, !diff_flag));
+
+ const uint32_t selector_cluster_index = get_block_selector_cluster_index(block_index);
+ blk.set_raw_selector_bits(get_selector_cluster_selector_bits(selector_cluster_index).get_raw_selector_bits());
+ }
+ }
+ }
+
+ image img;
+ g.unpack(img);
+
+ save_png(pFilename, img);
+ }
+
+} // namespace basisu
+
diff --git a/thirdparty/basis_universal/basisu_frontend.h b/thirdparty/basis_universal/basisu_frontend.h
new file mode 100644
index 0000000000..c3f5d23c71
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_frontend.h
@@ -0,0 +1,354 @@
+// basisu_frontend.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "basisu_enc.h"
+#include "basisu_etc.h"
+#include "basisu_gpu_texture.h"
+#include "basisu_global_selector_palette_helpers.h"
+#include "transcoder/basisu_file_headers.h"
+
+namespace basisu
+{
+ struct vec2U
+ {
+ uint32_t m_comps[2];
+
+ vec2U() { }
+ vec2U(uint32_t a, uint32_t b) { set(a, b); }
+
+ void set(uint32_t a, uint32_t b) { m_comps[0] = a; m_comps[1] = b; }
+
+ uint32_t operator[] (uint32_t i) const { assert(i < 2); return m_comps[i]; }
+ uint32_t &operator[] (uint32_t i) { assert(i < 2); return m_comps[i]; }
+ };
+
+ const uint32_t BASISU_DEFAULT_COMPRESSION_LEVEL = 1;
+ const uint32_t BASISU_MAX_COMPRESSION_LEVEL = 5;
+
+ class basisu_frontend
+ {
+ BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(basisu_frontend);
+
+ public:
+
+ basisu_frontend() :
+ m_total_blocks(0),
+ m_total_pixels(0),
+ m_endpoint_refinement(false),
+ m_use_hierarchical_endpoint_codebooks(false),
+ m_use_hierarchical_selector_codebooks(false),
+ m_num_endpoint_codebook_iterations(0),
+ m_num_selector_codebook_iterations(0)
+ {
+ }
+
+ enum
+ {
+ cMaxEndpointClusters = 16128,
+
+ cMaxSelectorClusters = 16128,
+ };
+
+ struct params
+ {
+ params() :
+ m_num_source_blocks(0),
+ m_pSource_blocks(NULL),
+ m_max_endpoint_clusters(256),
+ m_max_selector_clusters(256),
+ m_compression_level(BASISU_DEFAULT_COMPRESSION_LEVEL),
+ m_perceptual(true),
+ m_debug_stats(false),
+ m_debug_images(false),
+ m_dump_endpoint_clusterization(true),
+ m_pGlobal_sel_codebook(NULL),
+ m_num_global_sel_codebook_pal_bits(0),
+ m_num_global_sel_codebook_mod_bits(0),
+ m_use_hybrid_selector_codebooks(false),
+ m_hybrid_codebook_quality_thresh(0.0f),
+ m_validate(false),
+ m_tex_type(basist::cBASISTexType2D),
+ m_multithreaded(false),
+ m_disable_hierarchical_endpoint_codebooks(false),
+ m_pJob_pool(nullptr)
+ {
+ }
+
+ uint32_t m_num_source_blocks;
+ pixel_block *m_pSource_blocks;
+
+ uint32_t m_max_endpoint_clusters;
+ uint32_t m_max_selector_clusters;
+
+ uint32_t m_compression_level;
+
+ bool m_perceptual;
+ bool m_debug_stats;
+ bool m_debug_images;
+ bool m_dump_endpoint_clusterization;
+ bool m_validate;
+ bool m_multithreaded;
+ bool m_disable_hierarchical_endpoint_codebooks;
+
+ const basist::etc1_global_selector_codebook *m_pGlobal_sel_codebook;
+ uint32_t m_num_global_sel_codebook_pal_bits;
+ uint32_t m_num_global_sel_codebook_mod_bits;
+ bool m_use_hybrid_selector_codebooks;
+ float m_hybrid_codebook_quality_thresh;
+ basist::basis_texture_type m_tex_type;
+
+ job_pool *m_pJob_pool;
+ };
+
+ bool init(const params &p);
+
+ bool compress();
+
+ const params &get_params() const { return m_params; }
+
+ const pixel_block &get_source_pixel_block(uint32_t i) const { return m_source_blocks[i]; }
+
+ // RDO output blocks
+ uint32_t get_total_output_blocks() const { return static_cast<uint32_t>(m_encoded_blocks.size()); }
+
+ const etc_block &get_output_block(uint32_t block_index) const { return m_encoded_blocks[block_index]; }
+ const etc_block_vec &get_output_blocks() const { return m_encoded_blocks; }
+
+ // "Best" ETC1S blocks
+ const etc_block &get_etc1s_block(uint32_t block_index) const { return m_etc1_blocks_etc1s[block_index]; }
+
+ // Per-block flags
+ bool get_diff_flag(uint32_t block_index) const { return m_encoded_blocks[block_index].get_diff_bit(); }
+
+ // Endpoint clusters
+ uint32_t get_total_endpoint_clusters() const { return static_cast<uint32_t>(m_endpoint_clusters.size()); }
+ uint32_t get_subblock_endpoint_cluster_index(uint32_t block_index, uint32_t subblock_index) const { return m_block_endpoint_clusters_indices[block_index][subblock_index]; }
+
+ const color_rgba &get_endpoint_cluster_unscaled_color(uint32_t cluster_index, bool individual_mode) const { return m_endpoint_cluster_etc_params[cluster_index].m_color_unscaled[individual_mode]; }
+ uint32_t get_endpoint_cluster_inten_table(uint32_t cluster_index, bool individual_mode) const { return m_endpoint_cluster_etc_params[cluster_index].m_inten_table[individual_mode]; }
+
+ bool get_endpoint_cluster_color_is_used(uint32_t cluster_index, bool individual_mode) const { return m_endpoint_cluster_etc_params[cluster_index].m_color_used[individual_mode]; }
+
+ // Selector clusters
+ uint32_t get_total_selector_clusters() const { return static_cast<uint32_t>(m_selector_cluster_indices.size()); }
+ uint32_t get_block_selector_cluster_index(uint32_t block_index) const { return m_block_selector_cluster_index[block_index]; }
+ const etc_block &get_selector_cluster_selector_bits(uint32_t cluster_index) const { return m_optimized_cluster_selectors[cluster_index]; }
+
+ const basist::etc1_global_selector_codebook_entry_id_vec &get_selector_cluster_global_selector_entry_ids() const { return m_optimized_cluster_selector_global_cb_ids; }
+ const bool_vec &get_selector_cluster_uses_global_cb_vec() const { return m_selector_cluster_uses_global_cb; }
+
+ // Returns block indices using each selector cluster
+ const uint_vec &get_selector_cluster_block_indices(uint32_t selector_cluster_index) const { return m_selector_cluster_indices[selector_cluster_index]; }
+
+ void dump_debug_image(const char *pFilename, uint32_t first_block, uint32_t num_blocks_x, uint32_t num_blocks_y, bool output_blocks);
+
+ void reoptimize_remapped_endpoints(const uint_vec &new_block_endpoints, int_vec &old_to_new_endpoint_cluster_indices, bool optimize_final_codebook, uint_vec *pBlock_selector_indices = nullptr);
+
+ private:
+ params m_params;
+ uint32_t m_total_blocks;
+ uint32_t m_total_pixels;
+
+ bool m_endpoint_refinement;
+ bool m_use_hierarchical_endpoint_codebooks;
+ bool m_use_hierarchical_selector_codebooks;
+
+ uint32_t m_num_endpoint_codebook_iterations;
+ uint32_t m_num_selector_codebook_iterations;
+
+ // Source pixels for each blocks
+ pixel_block_vec m_source_blocks;
+
+ // The quantized ETC1S texture.
+ etc_block_vec m_encoded_blocks;
+
+ // Quantized blocks after endpoint quant, but before selector quant
+ etc_block_vec m_orig_encoded_blocks;
+
+ // Full quality ETC1S texture
+ etc_block_vec m_etc1_blocks_etc1s;
+
+ typedef vec<6, float> vec6F;
+
+ // Endpoint clusterizer
+ typedef tree_vector_quant<vec6F> vec6F_quantizer;
+ vec6F_quantizer m_endpoint_clusterizer;
+
+ // For each endpoint cluster: An array of which subblock indices (block_index*2+subblock) are located in that cluster.
+ // Array of block indices for each endpoint cluster
+ std::vector<uint_vec> m_endpoint_clusters;
+
+ // Array of block indices for each parent endpoint cluster
+ std::vector<uint_vec> m_endpoint_parent_clusters;
+
+ // Each block's parent cluster index
+ uint8_vec m_block_parent_endpoint_cluster;
+
+ // Array of endpoint cluster indices for each parent endpoint cluster
+ std::vector<uint_vec> m_endpoint_clusters_within_each_parent_cluster;
+
+ struct endpoint_cluster_etc_params
+ {
+ endpoint_cluster_etc_params()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ clear_obj(m_color_unscaled);
+ clear_obj(m_inten_table);
+ clear_obj(m_color_error);
+ m_subblocks.clear();
+
+ clear_obj(m_color_used);
+ m_valid = false;
+ }
+
+ // TODO: basisu doesn't use individual mode.
+ color_rgba m_color_unscaled[2]; // [use_individual_mode]
+ uint32_t m_inten_table[2];
+
+ uint64_t m_color_error[2];
+
+ uint_vec m_subblocks;
+
+ bool m_color_used[2];
+
+ bool m_valid;
+
+ bool operator== (const endpoint_cluster_etc_params &other) const
+ {
+ for (uint32_t i = 0; i < 2; i++)
+ {
+ if (m_color_unscaled[i] != other.m_color_unscaled[i])
+ return false;
+ }
+
+ if (m_inten_table[0] != other.m_inten_table[0])
+ return false;
+ if (m_inten_table[1] != other.m_inten_table[1])
+ return false;
+
+ return true;
+ }
+
+ bool operator< (const endpoint_cluster_etc_params &other) const
+ {
+ for (uint32_t i = 0; i < 2; i++)
+ {
+ if (m_color_unscaled[i] < other.m_color_unscaled[i])
+ return true;
+ else if (m_color_unscaled[i] != other.m_color_unscaled[i])
+ return false;
+ }
+
+ if (m_inten_table[0] < other.m_inten_table[0])
+ return true;
+ else if (m_inten_table[0] == other.m_inten_table[0])
+ {
+ if (m_inten_table[1] < other.m_inten_table[1])
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+ typedef std::vector<endpoint_cluster_etc_params> cluster_subblock_etc_params_vec;
+
+ // Each endpoint cluster's ETC1S parameters
+ cluster_subblock_etc_params_vec m_endpoint_cluster_etc_params;
+
+ // The endpoint cluster index used by each ETC1 subblock.
+ std::vector<vec2U> m_block_endpoint_clusters_indices;
+
+ // The block(s) within each selector cluster
+ // Note: If you add anything here that uses selector cluster indicies, be sure to update optimize_selector_codebook()!
+ std::vector<uint_vec> m_selector_cluster_indices;
+
+ // The selector bits for each selector cluster.
+ std::vector<etc_block> m_optimized_cluster_selectors;
+
+ // The block(s) within each parent selector cluster.
+ std::vector<uint_vec> m_selector_parent_cluster_indices;
+
+ // Each block's parent selector cluster
+ uint8_vec m_block_parent_selector_cluster;
+
+ // Array of selector cluster indices for each parent selector cluster
+ std::vector<uint_vec> m_selector_clusters_within_each_parent_cluster;
+
+ basist::etc1_global_selector_codebook_entry_id_vec m_optimized_cluster_selector_global_cb_ids;
+ bool_vec m_selector_cluster_uses_global_cb;
+
+ // Each block's selector cluster index
+ std::vector<uint32_t> m_block_selector_cluster_index;
+
+ struct subblock_endpoint_quant_err
+ {
+ uint64_t m_total_err;
+ uint32_t m_cluster_index;
+ uint32_t m_cluster_subblock_index;
+ uint32_t m_block_index;
+ uint32_t m_subblock_index;
+
+ bool operator< (const subblock_endpoint_quant_err &rhs) const
+ {
+ if (m_total_err < rhs.m_total_err)
+ return true;
+ else if (m_total_err == rhs.m_total_err)
+ {
+ if (m_block_index < rhs.m_block_index)
+ return true;
+ else if (m_block_index == rhs.m_block_index)
+ return m_subblock_index < rhs.m_subblock_index;
+ }
+ return false;
+ }
+ };
+
+ // The sorted subblock endpoint quant error for each endpoint cluster
+ std::vector<subblock_endpoint_quant_err> m_subblock_endpoint_quant_err_vec;
+
+ std::mutex m_lock;
+
+ //-----------------------------------------------------------------------------
+
+ void init_etc1_images();
+ void init_endpoint_training_vectors();
+ void dump_endpoint_clusterization_visualization(const char *pFilename, bool vis_endpoint_colors);
+ void generate_endpoint_clusters();
+ void compute_endpoint_subblock_error_vec();
+ void introduce_new_endpoint_clusters();
+ void generate_endpoint_codebook(uint32_t step);
+ uint32_t refine_endpoint_clusterization();
+ void eliminate_redundant_or_empty_endpoint_clusters();
+ void generate_block_endpoint_clusters();
+ void compute_endpoint_clusters_within_each_parent_cluster();
+ void compute_selector_clusters_within_each_parent_cluster();
+ void create_initial_packed_texture();
+ void generate_selector_clusters();
+ void create_optimized_selector_codebook(uint32_t iter);
+ void find_optimal_selector_clusters_for_each_block();
+ uint32_t refine_block_endpoints_given_selectors();
+ void finalize();
+ bool validate_output() const;
+ void introduce_special_selector_clusters();
+ void optimize_selector_codebook();
+ bool check_etc1s_constraints() const;
+ };
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_global_selector_palette_helpers.cpp b/thirdparty/basis_universal/basisu_global_selector_palette_helpers.cpp
new file mode 100644
index 0000000000..102fc24980
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_global_selector_palette_helpers.cpp
@@ -0,0 +1,71 @@
+// basiu_global_selector_palette_helpers.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_global_selector_palette_helpers.h"
+
+namespace basisu
+{
+ uint64_t etc1_global_selector_codebook_find_best_entry(const basist::etc1_global_selector_codebook &codebook,
+ uint32_t num_src_pixel_blocks, const pixel_block *pSrc_pixel_blocks, const etc_block *pBlock_endpoints,
+ uint32_t &palette_index, basist::etc1_global_palette_entry_modifier &palette_modifier,
+ bool perceptual, uint32_t max_pal_entries, uint32_t max_modifiers)
+ {
+ uint64_t best_err = UINT64_MAX;
+ uint32_t best_pal_index = 0;
+ basist::etc1_global_palette_entry_modifier best_pal_modifier;
+
+ if (!max_pal_entries)
+ max_pal_entries = codebook.size();
+
+ if (!max_modifiers)
+ max_modifiers = basist::etc1_global_palette_entry_modifier::cTotalValues;
+
+ for (uint32_t pal_index = 0; pal_index < max_pal_entries; pal_index++)
+ {
+ for (uint32_t mod_index = 0; mod_index < max_modifiers; mod_index++)
+ {
+ const basist::etc1_global_palette_entry_modifier pal_modifier(mod_index);
+
+ const basist::etc1_selector_palette_entry pal_entry(codebook.get_entry(pal_index, pal_modifier));
+
+ uint64_t trial_err = 0;
+ for (uint32_t block_index = 0; block_index < num_src_pixel_blocks; block_index++)
+ {
+ etc_block trial_block(pBlock_endpoints[block_index]);
+
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ trial_block.set_selector(x, y, pal_entry(x, y));
+
+ trial_err += trial_block.evaluate_etc1_error(reinterpret_cast<const basisu::color_rgba *>(pSrc_pixel_blocks[block_index].get_ptr()), perceptual);
+ if (trial_err >= best_err)
+ break;
+ }
+
+ if (trial_err < best_err)
+ {
+ best_err = trial_err;
+ best_pal_index = pal_index;
+ best_pal_modifier = pal_modifier;
+ }
+ } // mod_index
+ } // pal_index
+
+ palette_index = best_pal_index;
+ palette_modifier = best_pal_modifier;
+
+ return best_err;
+ }
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_global_selector_palette_helpers.h b/thirdparty/basis_universal/basisu_global_selector_palette_helpers.h
new file mode 100644
index 0000000000..32692c516b
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_global_selector_palette_helpers.h
@@ -0,0 +1,46 @@
+// File: basisu_global_selector_palette_helpers.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include "transcoder/basisu.h"
+#include "basisu_etc.h"
+#include "transcoder/basisu_global_selector_palette.h"
+
+namespace basisu
+{
+ const uint32_t cPixelBlockWidth = 4;
+ const uint32_t cPixelBlockHeight = 4;
+ const uint32_t cPixelBlockTotalPixels = cPixelBlockWidth * cPixelBlockHeight;
+
+ struct pixel_block
+ {
+ color_rgba m_pixels[cPixelBlockHeight][cPixelBlockWidth]; // [y][x]
+
+ const color_rgba &operator() (uint32_t x, uint32_t y) const { assert((x < cPixelBlockWidth) && (y < cPixelBlockHeight)); return m_pixels[y][x]; }
+ color_rgba &operator() (uint32_t x, uint32_t y) { assert((x < cPixelBlockWidth) && (y < cPixelBlockHeight)); return m_pixels[y][x]; }
+
+ const color_rgba *get_ptr() const { return &m_pixels[0][0]; }
+ color_rgba *get_ptr() { return &m_pixels[0][0]; }
+
+ void clear() { clear_obj(*this); }
+ };
+ typedef std::vector<pixel_block> pixel_block_vec;
+
+ uint64_t etc1_global_selector_codebook_find_best_entry(const basist::etc1_global_selector_codebook &codebook,
+ uint32_t num_src_pixel_blocks, const pixel_block *pSrc_pixel_blocks, const etc_block *pBlock_endpoints,
+ uint32_t &palette_index, basist::etc1_global_palette_entry_modifier &palette_modifier,
+ bool perceptual, uint32_t max_pal_entries, uint32_t max_modifiers);
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_gpu_texture.cpp b/thirdparty/basis_universal/basisu_gpu_texture.cpp
new file mode 100644
index 0000000000..117668c5e2
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_gpu_texture.cpp
@@ -0,0 +1,1451 @@
+// basisu_gpu_texture.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_gpu_texture.h"
+#include "basisu_enc.h"
+#include "basisu_pvrtc1_4.h"
+#include "basisu_astc_decomp.h"
+
+namespace basisu
+{
+ const int8_t g_etc2_eac_tables[16][8] =
+ {
+ { -3, -6, -9, -15, 2, 5, 8, 14 }, { -3, -7, -10, -13, 2, 6, 9, 12 }, { -2, -5, -8, -13, 1, 4, 7, 12 }, { -2, -4, -6, -13, 1, 3, 5, 12 },
+ { -3, -6, -8, -12, 2, 5, 7, 11 }, { -3, -7, -9, -11, 2, 6, 8, 10 }, { -4, -7, -8, -11, 3, 6, 7, 10 }, { -3, -5, -8, -11, 2, 4, 7, 10 },
+ { -2, -6, -8, -10, 1, 5, 7, 9 }, { -2, -5, -8, -10, 1, 4, 7, 9 }, { -2, -4, -8, -10, 1, 3, 7, 9 }, { -2, -5, -7, -10, 1, 4, 6, 9 },
+ { -3, -4, -7, -10, 2, 3, 6, 9 }, { -1, -2, -3, -10, 0, 1, 2, 9 }, { -4, -6, -8, -9, 3, 5, 7, 8 }, { -3, -5, -7, -9, 2, 4, 6, 8 }
+ };
+
+ struct eac_a8_block
+ {
+ uint16_t m_base : 8;
+ uint16_t m_table : 4;
+ uint16_t m_multiplier : 4;
+
+ uint8_t m_selectors[6];
+
+ inline uint32_t get_selector(uint32_t x, uint32_t y, uint64_t selector_bits) const
+ {
+ assert((x < 4) && (y < 4));
+ return static_cast<uint32_t>((selector_bits >> (45 - (y + x * 4) * 3)) & 7);
+ }
+
+ inline uint64_t get_selector_bits() const
+ {
+ uint64_t pixels = ((uint64_t)m_selectors[0] << 40) | ((uint64_t)m_selectors[1] << 32) | ((uint64_t)m_selectors[2] << 24) | ((uint64_t)m_selectors[3] << 16) | ((uint64_t)m_selectors[4] << 8) | m_selectors[5];
+ return pixels;
+ }
+ };
+
+ void unpack_etc2_eac(const void *pBlock_bits, color_rgba *pPixels)
+ {
+ static_assert(sizeof(eac_a8_block) == 8, "sizeof(eac_a8_block) == 8");
+
+ const eac_a8_block *pBlock = static_cast<const eac_a8_block *>(pBlock_bits);
+
+ const int8_t *pTable = g_etc2_eac_tables[pBlock->m_table];
+
+ const uint64_t selector_bits = pBlock->get_selector_bits();
+
+ const int32_t base = pBlock->m_base;
+ const int32_t mul = pBlock->m_multiplier;
+
+ pPixels[0].a = clamp255(base + pTable[pBlock->get_selector(0, 0, selector_bits)] * mul);
+ pPixels[1].a = clamp255(base + pTable[pBlock->get_selector(1, 0, selector_bits)] * mul);
+ pPixels[2].a = clamp255(base + pTable[pBlock->get_selector(2, 0, selector_bits)] * mul);
+ pPixels[3].a = clamp255(base + pTable[pBlock->get_selector(3, 0, selector_bits)] * mul);
+
+ pPixels[4].a = clamp255(base + pTable[pBlock->get_selector(0, 1, selector_bits)] * mul);
+ pPixels[5].a = clamp255(base + pTable[pBlock->get_selector(1, 1, selector_bits)] * mul);
+ pPixels[6].a = clamp255(base + pTable[pBlock->get_selector(2, 1, selector_bits)] * mul);
+ pPixels[7].a = clamp255(base + pTable[pBlock->get_selector(3, 1, selector_bits)] * mul);
+
+ pPixels[8].a = clamp255(base + pTable[pBlock->get_selector(0, 2, selector_bits)] * mul);
+ pPixels[9].a = clamp255(base + pTable[pBlock->get_selector(1, 2, selector_bits)] * mul);
+ pPixels[10].a = clamp255(base + pTable[pBlock->get_selector(2, 2, selector_bits)] * mul);
+ pPixels[11].a = clamp255(base + pTable[pBlock->get_selector(3, 2, selector_bits)] * mul);
+
+ pPixels[12].a = clamp255(base + pTable[pBlock->get_selector(0, 3, selector_bits)] * mul);
+ pPixels[13].a = clamp255(base + pTable[pBlock->get_selector(1, 3, selector_bits)] * mul);
+ pPixels[14].a = clamp255(base + pTable[pBlock->get_selector(2, 3, selector_bits)] * mul);
+ pPixels[15].a = clamp255(base + pTable[pBlock->get_selector(3, 3, selector_bits)] * mul);
+ }
+
+ struct bc1_block
+ {
+ enum { cTotalEndpointBytes = 2, cTotalSelectorBytes = 4 };
+
+ uint8_t m_low_color[cTotalEndpointBytes];
+ uint8_t m_high_color[cTotalEndpointBytes];
+ uint8_t m_selectors[cTotalSelectorBytes];
+
+ inline uint32_t get_high_color() const { return m_high_color[0] | (m_high_color[1] << 8U); }
+ inline uint32_t get_low_color() const { return m_low_color[0] | (m_low_color[1] << 8U); }
+
+ static void unpack_color(uint32_t c, uint32_t &r, uint32_t &g, uint32_t &b)
+ {
+ r = (c >> 11) & 31;
+ g = (c >> 5) & 63;
+ b = c & 31;
+
+ r = (r << 3) | (r >> 2);
+ g = (g << 2) | (g >> 4);
+ b = (b << 3) | (b >> 2);
+ }
+
+ inline uint32_t get_selector(uint32_t x, uint32_t y) const { assert((x < 4U) && (y < 4U)); return (m_selectors[y] >> (x * 2)) & 3; }
+ };
+
+ // Returns true if the block uses 3 color punchthrough alpha mode.
+ bool unpack_bc1(const void *pBlock_bits, color_rgba *pPixels, bool set_alpha)
+ {
+ static_assert(sizeof(bc1_block) == 8, "sizeof(bc1_block) == 8");
+
+ const bc1_block *pBlock = static_cast<const bc1_block *>(pBlock_bits);
+
+ const uint32_t l = pBlock->get_low_color();
+ const uint32_t h = pBlock->get_high_color();
+
+ color_rgba c[4];
+
+ uint32_t r0, g0, b0, r1, g1, b1;
+ bc1_block::unpack_color(l, r0, g0, b0);
+ bc1_block::unpack_color(h, r1, g1, b1);
+
+ bool used_punchthrough = false;
+
+ if (l > h)
+ {
+ c[0].set_noclamp_rgba(r0, g0, b0, 255);
+ c[1].set_noclamp_rgba(r1, g1, b1, 255);
+ c[2].set_noclamp_rgba((r0 * 2 + r1) / 3, (g0 * 2 + g1) / 3, (b0 * 2 + b1) / 3, 255);
+ c[3].set_noclamp_rgba((r1 * 2 + r0) / 3, (g1 * 2 + g0) / 3, (b1 * 2 + b0) / 3, 255);
+ }
+ else
+ {
+ c[0].set_noclamp_rgba(r0, g0, b0, 255);
+ c[1].set_noclamp_rgba(r1, g1, b1, 255);
+ c[2].set_noclamp_rgba((r0 + r1) / 2, (g0 + g1) / 2, (b0 + b1) / 2, 255);
+ c[3].set_noclamp_rgba(0, 0, 0, 0);
+ used_punchthrough = true;
+ }
+
+ if (set_alpha)
+ {
+ for (uint32_t y = 0; y < 4; y++, pPixels += 4)
+ {
+ pPixels[0] = c[pBlock->get_selector(0, y)];
+ pPixels[1] = c[pBlock->get_selector(1, y)];
+ pPixels[2] = c[pBlock->get_selector(2, y)];
+ pPixels[3] = c[pBlock->get_selector(3, y)];
+ }
+ }
+ else
+ {
+ for (uint32_t y = 0; y < 4; y++, pPixels += 4)
+ {
+ pPixels[0].set_rgb(c[pBlock->get_selector(0, y)]);
+ pPixels[1].set_rgb(c[pBlock->get_selector(1, y)]);
+ pPixels[2].set_rgb(c[pBlock->get_selector(2, y)]);
+ pPixels[3].set_rgb(c[pBlock->get_selector(3, y)]);
+ }
+ }
+
+ return used_punchthrough;
+ }
+
+ struct bc4_block
+ {
+ enum { cBC4SelectorBits = 3, cTotalSelectorBytes = 6, cMaxSelectorValues = 8 };
+ uint8_t m_endpoints[2];
+
+ uint8_t m_selectors[cTotalSelectorBytes];
+
+ inline uint32_t get_low_alpha() const { return m_endpoints[0]; }
+ inline uint32_t get_high_alpha() const { return m_endpoints[1]; }
+ inline bool is_alpha6_block() const { return get_low_alpha() <= get_high_alpha(); }
+
+ inline uint64_t get_selector_bits() const
+ {
+ return ((uint64_t)((uint32_t)m_selectors[0] | ((uint32_t)m_selectors[1] << 8U) | ((uint32_t)m_selectors[2] << 16U) | ((uint32_t)m_selectors[3] << 24U))) |
+ (((uint64_t)m_selectors[4]) << 32U) |
+ (((uint64_t)m_selectors[5]) << 40U);
+ }
+
+ inline uint32_t get_selector(uint32_t x, uint32_t y, uint64_t selector_bits) const
+ {
+ assert((x < 4U) && (y < 4U));
+ return (selector_bits >> (((y * 4) + x) * cBC4SelectorBits)) & (cMaxSelectorValues - 1);
+ }
+
+ static inline uint32_t get_block_values6(uint8_t *pDst, uint32_t l, uint32_t h)
+ {
+ pDst[0] = static_cast<uint8_t>(l);
+ pDst[1] = static_cast<uint8_t>(h);
+ pDst[2] = static_cast<uint8_t>((l * 4 + h) / 5);
+ pDst[3] = static_cast<uint8_t>((l * 3 + h * 2) / 5);
+ pDst[4] = static_cast<uint8_t>((l * 2 + h * 3) / 5);
+ pDst[5] = static_cast<uint8_t>((l + h * 4) / 5);
+ pDst[6] = 0;
+ pDst[7] = 255;
+ return 6;
+ }
+
+ static inline uint32_t get_block_values8(uint8_t *pDst, uint32_t l, uint32_t h)
+ {
+ pDst[0] = static_cast<uint8_t>(l);
+ pDst[1] = static_cast<uint8_t>(h);
+ pDst[2] = static_cast<uint8_t>((l * 6 + h) / 7);
+ pDst[3] = static_cast<uint8_t>((l * 5 + h * 2) / 7);
+ pDst[4] = static_cast<uint8_t>((l * 4 + h * 3) / 7);
+ pDst[5] = static_cast<uint8_t>((l * 3 + h * 4) / 7);
+ pDst[6] = static_cast<uint8_t>((l * 2 + h * 5) / 7);
+ pDst[7] = static_cast<uint8_t>((l + h * 6) / 7);
+ return 8;
+ }
+
+ static inline uint32_t get_block_values(uint8_t *pDst, uint32_t l, uint32_t h)
+ {
+ if (l > h)
+ return get_block_values8(pDst, l, h);
+ else
+ return get_block_values6(pDst, l, h);
+ }
+ };
+
+ void unpack_bc4(const void *pBlock_bits, uint8_t *pPixels, uint32_t stride)
+ {
+ static_assert(sizeof(bc4_block) == 8, "sizeof(bc4_block) == 8");
+
+ const bc4_block *pBlock = static_cast<const bc4_block *>(pBlock_bits);
+
+ uint8_t sel_values[8];
+ bc4_block::get_block_values(sel_values, pBlock->get_low_alpha(), pBlock->get_high_alpha());
+
+ const uint64_t selector_bits = pBlock->get_selector_bits();
+
+ for (uint32_t y = 0; y < 4; y++, pPixels += (stride * 4U))
+ {
+ pPixels[0] = sel_values[pBlock->get_selector(0, y, selector_bits)];
+ pPixels[stride * 1] = sel_values[pBlock->get_selector(1, y, selector_bits)];
+ pPixels[stride * 2] = sel_values[pBlock->get_selector(2, y, selector_bits)];
+ pPixels[stride * 3] = sel_values[pBlock->get_selector(3, y, selector_bits)];
+ }
+ }
+
+ // Returns false if the block uses 3-color punchthrough alpha mode, which isn't supported on some GPU's for BC3.
+ bool unpack_bc3(const void *pBlock_bits, color_rgba *pPixels)
+ {
+ bool success = true;
+
+ if (unpack_bc1((const uint8_t *)pBlock_bits + sizeof(bc4_block), pPixels, true))
+ success = false;
+
+ unpack_bc4(pBlock_bits, &pPixels[0].a, sizeof(color_rgba));
+
+ return success;
+ }
+
+ // writes RG
+ void unpack_bc5(const void *pBlock_bits, color_rgba *pPixels)
+ {
+ unpack_bc4(pBlock_bits, &pPixels[0].r, sizeof(color_rgba));
+ unpack_bc4((const uint8_t *)pBlock_bits + sizeof(bc4_block), &pPixels[0].g, sizeof(color_rgba));
+ }
+
+ // ATC isn't officially documented, so I'm assuming these references:
+ // http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf
+ // https://github.com/Triang3l/S3TConv/blob/master/s3tconv_atitc.c
+ // The paper incorrectly says the ATC lerp factors are 1/3 and 2/3, but they are actually 3/8 and 5/8.
+ void unpack_atc(const void* pBlock_bits, color_rgba* pPixels)
+ {
+ const uint8_t* pBytes = static_cast<const uint8_t*>(pBlock_bits);
+
+ const uint16_t color0 = pBytes[0] | (pBytes[1] << 8U);
+ const uint16_t color1 = pBytes[2] | (pBytes[3] << 8U);
+ uint32_t sels = pBytes[4] | (pBytes[5] << 8U) | (pBytes[6] << 16U) | (pBytes[7] << 24U);
+
+ const bool mode = (color0 & 0x8000) != 0;
+
+ color_rgba c[4];
+
+ c[0].set((color0 >> 10) & 31, (color0 >> 5) & 31, color0 & 31, 255);
+ c[0].r = (c[0].r << 3) | (c[0].r >> 2);
+ c[0].g = (c[0].g << 3) | (c[0].g >> 2);
+ c[0].b = (c[0].b << 3) | (c[0].b >> 2);
+
+ c[3].set((color1 >> 11) & 31, (color1 >> 5) & 63, color1 & 31, 255);
+ c[3].r = (c[3].r << 3) | (c[3].r >> 2);
+ c[3].g = (c[3].g << 2) | (c[3].g >> 4);
+ c[3].b = (c[3].b << 3) | (c[3].b >> 2);
+
+ if (mode)
+ {
+ c[1].set(std::max(0, c[0].r - (c[3].r >> 2)), std::max(0, c[0].g - (c[3].g >> 2)), std::max(0, c[0].b - (c[3].b >> 2)), 255);
+ c[2] = c[0];
+ c[0].set(0, 0, 0, 255);
+ }
+ else
+ {
+ c[1].r = (c[0].r * 5 + c[3].r * 3) >> 3;
+ c[1].g = (c[0].g * 5 + c[3].g * 3) >> 3;
+ c[1].b = (c[0].b * 5 + c[3].b * 3) >> 3;
+
+ c[2].r = (c[0].r * 3 + c[3].r * 5) >> 3;
+ c[2].g = (c[0].g * 3 + c[3].g * 5) >> 3;
+ c[2].b = (c[0].b * 3 + c[3].b * 5) >> 3;
+ }
+
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ const uint32_t s = sels & 3;
+
+ pPixels[i] = c[s];
+
+ sels >>= 2;
+ }
+ }
+
+ struct bc7_mode_6
+ {
+ struct
+ {
+ uint64_t m_mode : 7;
+ uint64_t m_r0 : 7;
+ uint64_t m_r1 : 7;
+ uint64_t m_g0 : 7;
+ uint64_t m_g1 : 7;
+ uint64_t m_b0 : 7;
+ uint64_t m_b1 : 7;
+ uint64_t m_a0 : 7;
+ uint64_t m_a1 : 7;
+ uint64_t m_p0 : 1;
+ } m_lo;
+
+ union
+ {
+ struct
+ {
+ uint64_t m_p1 : 1;
+ uint64_t m_s00 : 3;
+ uint64_t m_s10 : 4;
+ uint64_t m_s20 : 4;
+ uint64_t m_s30 : 4;
+
+ uint64_t m_s01 : 4;
+ uint64_t m_s11 : 4;
+ uint64_t m_s21 : 4;
+ uint64_t m_s31 : 4;
+
+ uint64_t m_s02 : 4;
+ uint64_t m_s12 : 4;
+ uint64_t m_s22 : 4;
+ uint64_t m_s32 : 4;
+
+ uint64_t m_s03 : 4;
+ uint64_t m_s13 : 4;
+ uint64_t m_s23 : 4;
+ uint64_t m_s33 : 4;
+
+ } m_hi;
+
+ uint64_t m_hi_bits;
+ };
+ };
+
+ static const uint32_t g_bc7_weights4[16] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
+
+ // The transcoder only outputs mode 6 at the moment, so this is easy.
+ bool unpack_bc7_mode6(const void *pBlock_bits, color_rgba *pPixels)
+ {
+ static_assert(sizeof(bc7_mode_6) == 16, "sizeof(bc7_mode_6) == 16");
+
+ const bc7_mode_6 &block = *static_cast<const bc7_mode_6 *>(pBlock_bits);
+
+ if (block.m_lo.m_mode != (1 << 6))
+ return false;
+
+ const uint32_t r0 = (uint32_t)((block.m_lo.m_r0 << 1) | block.m_lo.m_p0);
+ const uint32_t g0 = (uint32_t)((block.m_lo.m_g0 << 1) | block.m_lo.m_p0);
+ const uint32_t b0 = (uint32_t)((block.m_lo.m_b0 << 1) | block.m_lo.m_p0);
+ const uint32_t a0 = (uint32_t)((block.m_lo.m_a0 << 1) | block.m_lo.m_p0);
+ const uint32_t r1 = (uint32_t)((block.m_lo.m_r1 << 1) | block.m_hi.m_p1);
+ const uint32_t g1 = (uint32_t)((block.m_lo.m_g1 << 1) | block.m_hi.m_p1);
+ const uint32_t b1 = (uint32_t)((block.m_lo.m_b1 << 1) | block.m_hi.m_p1);
+ const uint32_t a1 = (uint32_t)((block.m_lo.m_a1 << 1) | block.m_hi.m_p1);
+
+ color_rgba vals[16];
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ const uint32_t w = g_bc7_weights4[i];
+ const uint32_t iw = 64 - w;
+ vals[i].set_noclamp_rgba(
+ (r0 * iw + r1 * w + 32) >> 6,
+ (g0 * iw + g1 * w + 32) >> 6,
+ (b0 * iw + b1 * w + 32) >> 6,
+ (a0 * iw + a1 * w + 32) >> 6);
+ }
+
+ pPixels[0] = vals[block.m_hi.m_s00];
+ pPixels[1] = vals[block.m_hi.m_s10];
+ pPixels[2] = vals[block.m_hi.m_s20];
+ pPixels[3] = vals[block.m_hi.m_s30];
+
+ pPixels[4] = vals[block.m_hi.m_s01];
+ pPixels[5] = vals[block.m_hi.m_s11];
+ pPixels[6] = vals[block.m_hi.m_s21];
+ pPixels[7] = vals[block.m_hi.m_s31];
+
+ pPixels[8] = vals[block.m_hi.m_s02];
+ pPixels[9] = vals[block.m_hi.m_s12];
+ pPixels[10] = vals[block.m_hi.m_s22];
+ pPixels[11] = vals[block.m_hi.m_s32];
+
+ pPixels[12] = vals[block.m_hi.m_s03];
+ pPixels[13] = vals[block.m_hi.m_s13];
+ pPixels[14] = vals[block.m_hi.m_s23];
+ pPixels[15] = vals[block.m_hi.m_s33];
+
+ return true;
+ }
+
+ static inline uint32_t get_block_bits(const uint8_t* pBytes, uint32_t bit_ofs, uint32_t bits_wanted)
+ {
+ assert(bits_wanted < 32);
+
+ uint32_t v = 0;
+ uint32_t total_bits = 0;
+
+ while (total_bits < bits_wanted)
+ {
+ uint32_t k = pBytes[bit_ofs >> 3];
+ k >>= (bit_ofs & 7);
+ uint32_t num_bits_in_byte = 8 - (bit_ofs & 7);
+
+ v |= (k << total_bits);
+ total_bits += num_bits_in_byte;
+ bit_ofs += num_bits_in_byte;
+ }
+
+ return v & ((1 << bits_wanted) - 1);
+ }
+
+ struct bc7_mode_5
+ {
+ union
+ {
+ struct
+ {
+ uint64_t m_mode : 6;
+ uint64_t m_rot : 2;
+
+ uint64_t m_r0 : 7;
+ uint64_t m_r1 : 7;
+ uint64_t m_g0 : 7;
+ uint64_t m_g1 : 7;
+ uint64_t m_b0 : 7;
+ uint64_t m_b1 : 7;
+ uint64_t m_a0 : 8;
+ uint64_t m_a1_0 : 6;
+
+ } m_lo;
+
+ uint64_t m_lo_bits;
+ };
+
+ union
+ {
+ struct
+ {
+ uint64_t m_a1_1 : 2;
+
+ // bit 2
+ uint64_t m_c00 : 1;
+ uint64_t m_c10 : 2;
+ uint64_t m_c20 : 2;
+ uint64_t m_c30 : 2;
+
+ uint64_t m_c01 : 2;
+ uint64_t m_c11 : 2;
+ uint64_t m_c21 : 2;
+ uint64_t m_c31 : 2;
+
+ uint64_t m_c02 : 2;
+ uint64_t m_c12 : 2;
+ uint64_t m_c22 : 2;
+ uint64_t m_c32 : 2;
+
+ uint64_t m_c03 : 2;
+ uint64_t m_c13 : 2;
+ uint64_t m_c23 : 2;
+ uint64_t m_c33 : 2;
+
+ // bit 33
+ uint64_t m_a00 : 1;
+ uint64_t m_a10 : 2;
+ uint64_t m_a20 : 2;
+ uint64_t m_a30 : 2;
+
+ uint64_t m_a01 : 2;
+ uint64_t m_a11 : 2;
+ uint64_t m_a21 : 2;
+ uint64_t m_a31 : 2;
+
+ uint64_t m_a02 : 2;
+ uint64_t m_a12 : 2;
+ uint64_t m_a22 : 2;
+ uint64_t m_a32 : 2;
+
+ uint64_t m_a03 : 2;
+ uint64_t m_a13 : 2;
+ uint64_t m_a23 : 2;
+ uint64_t m_a33 : 2;
+
+ } m_hi;
+
+ uint64_t m_hi_bits;
+ };
+
+ color_rgba get_low_color() const
+ {
+ return color_rgba(cNoClamp,
+ (int)((m_lo.m_r0 << 1) | (m_lo.m_r0 >> 6)),
+ (int)((m_lo.m_g0 << 1) | (m_lo.m_g0 >> 6)),
+ (int)((m_lo.m_b0 << 1) | (m_lo.m_b0 >> 6)),
+ m_lo.m_a0);
+ }
+
+ color_rgba get_high_color() const
+ {
+ return color_rgba(cNoClamp,
+ (int)((m_lo.m_r1 << 1) | (m_lo.m_r1 >> 6)),
+ (int)((m_lo.m_g1 << 1) | (m_lo.m_g1 >> 6)),
+ (int)((m_lo.m_b1 << 1) | (m_lo.m_b1 >> 6)),
+ (int)m_lo.m_a1_0 | ((int)m_hi.m_a1_1 << 6));
+ }
+
+ void get_block_colors(color_rgba* pColors) const
+ {
+ const color_rgba low_color(get_low_color());
+ const color_rgba high_color(get_high_color());
+
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ static const uint32_t s_bc7_weights2[4] = { 0, 21, 43, 64 };
+
+ pColors[i].set_noclamp_rgba(
+ (low_color.r * (64 - s_bc7_weights2[i]) + high_color.r * s_bc7_weights2[i] + 32) >> 6,
+ (low_color.g * (64 - s_bc7_weights2[i]) + high_color.g * s_bc7_weights2[i] + 32) >> 6,
+ (low_color.b * (64 - s_bc7_weights2[i]) + high_color.b * s_bc7_weights2[i] + 32) >> 6,
+ (low_color.a * (64 - s_bc7_weights2[i]) + high_color.a * s_bc7_weights2[i] + 32) >> 6);
+ }
+ }
+
+ uint32_t get_selector(uint32_t idx, bool alpha) const
+ {
+ const uint32_t size = (idx == 0) ? 1 : 2;
+
+ uint32_t ofs = alpha ? 97 : 66;
+
+ if (idx)
+ ofs += 1 + 2 * (idx - 1);
+
+ return get_block_bits(reinterpret_cast<const uint8_t*>(this), ofs, size);
+ }
+ };
+
+ bool unpack_bc7_mode5(const void* pBlock_bits, color_rgba* pPixels)
+ {
+ static_assert(sizeof(bc7_mode_5) == 16, "sizeof(bc7_mode_5) == 16");
+
+ const bc7_mode_5& block = *static_cast<const bc7_mode_5*>(pBlock_bits);
+
+ if (block.m_lo.m_mode != (1 << 5))
+ return false;
+
+ color_rgba block_colors[4];
+ block.get_block_colors(block_colors);
+
+ const uint32_t rot = block.m_lo.m_rot;
+
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ const uint32_t cs = block.get_selector(i, false);
+
+ color_rgba c(block_colors[cs]);
+
+ const uint32_t as = block.get_selector(i, true);
+ c.a = block_colors[as].a;
+
+ if (rot > 0)
+ std::swap(c[3], c[rot - 1]);
+
+ pPixels[i] = c;
+ }
+
+ return true;
+ }
+
+ struct fxt1_block
+ {
+ union
+ {
+ struct
+ {
+ uint64_t m_t00 : 2;
+ uint64_t m_t01 : 2;
+ uint64_t m_t02 : 2;
+ uint64_t m_t03 : 2;
+ uint64_t m_t04 : 2;
+ uint64_t m_t05 : 2;
+ uint64_t m_t06 : 2;
+ uint64_t m_t07 : 2;
+ uint64_t m_t08 : 2;
+ uint64_t m_t09 : 2;
+ uint64_t m_t10 : 2;
+ uint64_t m_t11 : 2;
+ uint64_t m_t12 : 2;
+ uint64_t m_t13 : 2;
+ uint64_t m_t14 : 2;
+ uint64_t m_t15 : 2;
+ uint64_t m_t16 : 2;
+ uint64_t m_t17 : 2;
+ uint64_t m_t18 : 2;
+ uint64_t m_t19 : 2;
+ uint64_t m_t20 : 2;
+ uint64_t m_t21 : 2;
+ uint64_t m_t22 : 2;
+ uint64_t m_t23 : 2;
+ uint64_t m_t24 : 2;
+ uint64_t m_t25 : 2;
+ uint64_t m_t26 : 2;
+ uint64_t m_t27 : 2;
+ uint64_t m_t28 : 2;
+ uint64_t m_t29 : 2;
+ uint64_t m_t30 : 2;
+ uint64_t m_t31 : 2;
+ } m_lo;
+ uint64_t m_lo_bits;
+ uint8_t m_sels[8];
+ };
+
+ union
+ {
+ struct
+ {
+#ifdef BASISU_USE_ORIGINAL_3DFX_FXT1_ENCODING
+ // This is the format that 3DFX's DECOMP.EXE tool expects, which I'm assuming is what the actual 3DFX hardware wanted.
+ // Unfortunately, color0/color1 and color2/color3 are flipped relative to the official OpenGL extension and Intel's documentation!
+ uint64_t m_b1 : 5;
+ uint64_t m_g1 : 5;
+ uint64_t m_r1 : 5;
+ uint64_t m_b0 : 5;
+ uint64_t m_g0 : 5;
+ uint64_t m_r0 : 5;
+ uint64_t m_b3 : 5;
+ uint64_t m_g3 : 5;
+ uint64_t m_r3 : 5;
+ uint64_t m_b2 : 5;
+ uint64_t m_g2 : 5;
+ uint64_t m_r2 : 5;
+#else
+ // Intel's encoding, and the encoding in the OpenGL FXT1 spec.
+ uint64_t m_b0 : 5;
+ uint64_t m_g0 : 5;
+ uint64_t m_r0 : 5;
+ uint64_t m_b1 : 5;
+ uint64_t m_g1 : 5;
+ uint64_t m_r1 : 5;
+ uint64_t m_b2 : 5;
+ uint64_t m_g2 : 5;
+ uint64_t m_r2 : 5;
+ uint64_t m_b3 : 5;
+ uint64_t m_g3 : 5;
+ uint64_t m_r3 : 5;
+#endif
+ uint64_t m_alpha : 1;
+ uint64_t m_glsb : 2;
+ uint64_t m_mode : 1;
+ } m_hi;
+
+ uint64_t m_hi_bits;
+ };
+ };
+
+ static color_rgba expand_565(const color_rgba& c)
+ {
+ return color_rgba((c.r << 3) | (c.r >> 2), (c.g << 2) | (c.g >> 4), (c.b << 3) | (c.b >> 2), 255);
+ }
+
+ // We only support CC_MIXED non-alpha blocks here because that's the only mode the transcoder uses at the moment.
+ bool unpack_fxt1(const void *p, color_rgba *pPixels)
+ {
+ const fxt1_block* pBlock = static_cast<const fxt1_block*>(p);
+
+ if (pBlock->m_hi.m_mode == 0)
+ return false;
+ if (pBlock->m_hi.m_alpha == 1)
+ return false;
+
+ color_rgba colors[4];
+
+ colors[0].r = pBlock->m_hi.m_r0;
+ colors[0].g = (uint8_t)((pBlock->m_hi.m_g0 << 1) | ((pBlock->m_lo.m_t00 >> 1) ^ (pBlock->m_hi.m_glsb & 1)));
+ colors[0].b = pBlock->m_hi.m_b0;
+ colors[0].a = 255;
+
+ colors[1].r = pBlock->m_hi.m_r1;
+ colors[1].g = (uint8_t)((pBlock->m_hi.m_g1 << 1) | (pBlock->m_hi.m_glsb & 1));
+ colors[1].b = pBlock->m_hi.m_b1;
+ colors[1].a = 255;
+
+ colors[2].r = pBlock->m_hi.m_r2;
+ colors[2].g = (uint8_t)((pBlock->m_hi.m_g2 << 1) | ((pBlock->m_lo.m_t16 >> 1) ^ (pBlock->m_hi.m_glsb >> 1)));
+ colors[2].b = pBlock->m_hi.m_b2;
+ colors[2].a = 255;
+
+ colors[3].r = pBlock->m_hi.m_r3;
+ colors[3].g = (uint8_t)((pBlock->m_hi.m_g3 << 1) | (pBlock->m_hi.m_glsb >> 1));
+ colors[3].b = pBlock->m_hi.m_b3;
+ colors[3].a = 255;
+
+ for (uint32_t i = 0; i < 4; i++)
+ colors[i] = expand_565(colors[i]);
+
+ color_rgba block0_colors[4];
+ block0_colors[0] = colors[0];
+ block0_colors[1] = color_rgba((colors[0].r * 2 + colors[1].r + 1) / 3, (colors[0].g * 2 + colors[1].g + 1) / 3, (colors[0].b * 2 + colors[1].b + 1) / 3, 255);
+ block0_colors[2] = color_rgba((colors[1].r * 2 + colors[0].r + 1) / 3, (colors[1].g * 2 + colors[0].g + 1) / 3, (colors[1].b * 2 + colors[0].b + 1) / 3, 255);
+ block0_colors[3] = colors[1];
+
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ const uint32_t sel = (pBlock->m_sels[i >> 2] >> ((i & 3) * 2)) & 3;
+
+ const uint32_t x = i & 3;
+ const uint32_t y = i >> 2;
+ pPixels[x + y * 8] = block0_colors[sel];
+ }
+
+ color_rgba block1_colors[4];
+ block1_colors[0] = colors[2];
+ block1_colors[1] = color_rgba((colors[2].r * 2 + colors[3].r + 1) / 3, (colors[2].g * 2 + colors[3].g + 1) / 3, (colors[2].b * 2 + colors[3].b + 1) / 3, 255);
+ block1_colors[2] = color_rgba((colors[3].r * 2 + colors[2].r + 1) / 3, (colors[3].g * 2 + colors[2].g + 1) / 3, (colors[3].b * 2 + colors[2].b + 1) / 3, 255);
+ block1_colors[3] = colors[3];
+
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ const uint32_t sel = (pBlock->m_sels[4 + (i >> 2)] >> ((i & 3) * 2)) & 3;
+
+ const uint32_t x = i & 3;
+ const uint32_t y = i >> 2;
+ pPixels[4 + x + y * 8] = block1_colors[sel];
+ }
+
+ return true;
+ }
+
+ struct pvrtc2_block
+ {
+ uint8_t m_modulation[4];
+
+ union
+ {
+ union
+ {
+ // Opaque mode: RGB colora=554 and colorb=555
+ struct
+ {
+ uint32_t m_mod_flag : 1;
+ uint32_t m_blue_a : 4;
+ uint32_t m_green_a : 5;
+ uint32_t m_red_a : 5;
+ uint32_t m_hard_flag : 1;
+ uint32_t m_blue_b : 5;
+ uint32_t m_green_b : 5;
+ uint32_t m_red_b : 5;
+ uint32_t m_opaque_flag : 1;
+
+ } m_opaque_color_data;
+
+ // Transparent mode: RGBA colora=4433 and colorb=4443
+ struct
+ {
+ uint32_t m_mod_flag : 1;
+ uint32_t m_blue_a : 3;
+ uint32_t m_green_a : 4;
+ uint32_t m_red_a : 4;
+ uint32_t m_alpha_a : 3;
+ uint32_t m_hard_flag : 1;
+ uint32_t m_blue_b : 4;
+ uint32_t m_green_b : 4;
+ uint32_t m_red_b : 4;
+ uint32_t m_alpha_b : 3;
+ uint32_t m_opaque_flag : 1;
+
+ } m_trans_color_data;
+ };
+
+ uint32_t m_color_data_bits;
+ };
+ };
+
+ static color_rgba convert_rgb_555_to_888(const color_rgba& col)
+ {
+ return color_rgba((col[0] << 3) | (col[0] >> 2), (col[1] << 3) | (col[1] >> 2), (col[2] << 3) | (col[2] >> 2), 255);
+ }
+
+ static color_rgba convert_rgba_5554_to_8888(const color_rgba& col)
+ {
+ return color_rgba((col[0] << 3) | (col[0] >> 2), (col[1] << 3) | (col[1] >> 2), (col[2] << 3) | (col[2] >> 2), (col[3] << 4) | col[3]);
+ }
+
+ // PVRTC2 is currently limited to only what our transcoder outputs (non-interpolated, hard_flag=1 modulation=0). In this mode, PVRTC2 looks much like BC1/ATC.
+ bool unpack_pvrtc2(const void *p, color_rgba *pPixels)
+ {
+ const pvrtc2_block* pBlock = static_cast<const pvrtc2_block*>(p);
+
+ if ((!pBlock->m_opaque_color_data.m_hard_flag) || (pBlock->m_opaque_color_data.m_mod_flag))
+ {
+ // This mode isn't supported by the transcoder, so we aren't bothering with it here.
+ return false;
+ }
+
+ color_rgba colors[4];
+
+ if (pBlock->m_opaque_color_data.m_opaque_flag)
+ {
+ // colora=554
+ color_rgba color_a(pBlock->m_opaque_color_data.m_red_a, pBlock->m_opaque_color_data.m_green_a, (pBlock->m_opaque_color_data.m_blue_a << 1) | (pBlock->m_opaque_color_data.m_blue_a >> 3), 255);
+
+ // colora=555
+ color_rgba color_b(pBlock->m_opaque_color_data.m_red_b, pBlock->m_opaque_color_data.m_green_b, pBlock->m_opaque_color_data.m_blue_b, 255);
+
+ colors[0] = convert_rgb_555_to_888(color_a);
+ colors[3] = convert_rgb_555_to_888(color_b);
+
+ colors[1].set((colors[0].r * 5 + colors[3].r * 3) / 8, (colors[0].g * 5 + colors[3].g * 3) / 8, (colors[0].b * 5 + colors[3].b * 3) / 8, 255);
+ colors[2].set((colors[0].r * 3 + colors[3].r * 5) / 8, (colors[0].g * 3 + colors[3].g * 5) / 8, (colors[0].b * 3 + colors[3].b * 5) / 8, 255);
+ }
+ else
+ {
+ // colora=4433
+ color_rgba color_a(
+ (pBlock->m_trans_color_data.m_red_a << 1) | (pBlock->m_trans_color_data.m_red_a >> 3),
+ (pBlock->m_trans_color_data.m_green_a << 1) | (pBlock->m_trans_color_data.m_green_a >> 3),
+ (pBlock->m_trans_color_data.m_blue_a << 2) | (pBlock->m_trans_color_data.m_blue_a >> 1),
+ pBlock->m_trans_color_data.m_alpha_a << 1);
+
+ //colorb=4443
+ color_rgba color_b(
+ (pBlock->m_trans_color_data.m_red_b << 1) | (pBlock->m_trans_color_data.m_red_b >> 3),
+ (pBlock->m_trans_color_data.m_green_b << 1) | (pBlock->m_trans_color_data.m_green_b >> 3),
+ (pBlock->m_trans_color_data.m_blue_b << 1) | (pBlock->m_trans_color_data.m_blue_b >> 3),
+ (pBlock->m_trans_color_data.m_alpha_b << 1) | 1);
+
+ colors[0] = convert_rgba_5554_to_8888(color_a);
+ colors[3] = convert_rgba_5554_to_8888(color_b);
+ }
+
+ colors[1].set((colors[0].r * 5 + colors[3].r * 3) / 8, (colors[0].g * 5 + colors[3].g * 3) / 8, (colors[0].b * 5 + colors[3].b * 3) / 8, (colors[0].a * 5 + colors[3].a * 3) / 8);
+ colors[2].set((colors[0].r * 3 + colors[3].r * 5) / 8, (colors[0].g * 3 + colors[3].g * 5) / 8, (colors[0].b * 3 + colors[3].b * 5) / 8, (colors[0].a * 3 + colors[3].a * 5) / 8);
+
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ const uint32_t sel = (pBlock->m_modulation[i >> 2] >> ((i & 3) * 2)) & 3;
+ pPixels[i] = colors[sel];
+ }
+
+ return true;
+ }
+
+ struct etc2_eac_r11
+ {
+ uint64_t m_base : 8;
+ uint64_t m_table : 4;
+ uint64_t m_mul : 4;
+ uint64_t m_sels_0 : 8;
+ uint64_t m_sels_1 : 8;
+ uint64_t m_sels_2 : 8;
+ uint64_t m_sels_3 : 8;
+ uint64_t m_sels_4 : 8;
+ uint64_t m_sels_5 : 8;
+
+ uint64_t get_sels() const
+ {
+ return ((uint64_t)m_sels_0 << 40U) | ((uint64_t)m_sels_1 << 32U) | ((uint64_t)m_sels_2 << 24U) | ((uint64_t)m_sels_3 << 16U) | ((uint64_t)m_sels_4 << 8U) | m_sels_5;
+ }
+
+ void set_sels(uint64_t v)
+ {
+ m_sels_0 = (v >> 40U) & 0xFF;
+ m_sels_1 = (v >> 32U) & 0xFF;
+ m_sels_2 = (v >> 24U) & 0xFF;
+ m_sels_3 = (v >> 16U) & 0xFF;
+ m_sels_4 = (v >> 8U) & 0xFF;
+ m_sels_5 = v & 0xFF;
+ }
+ };
+
+ struct etc2_eac_rg11
+ {
+ etc2_eac_r11 m_c[2];
+ };
+
+ static void unpack_etc2_eac_r(const etc2_eac_r11* p, color_rgba* pPixels, uint32_t c)
+ {
+ const uint64_t sels = p->get_sels();
+
+ const int base = (int)p->m_base * 8 + 4;
+ const int mul = p->m_mul ? ((int)p->m_mul * 8) : 1;
+ const int table = (int)p->m_table;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ const uint32_t shift = 45 - ((y + x * 4) * 3);
+
+ const uint32_t sel = (uint32_t)((sels >> shift) & 7);
+
+ int val = base + g_etc2_eac_tables[table][sel] * mul;
+ val = clamp<int>(val, 0, 2047);
+
+ // Convert to 8-bits with rounding
+ pPixels[x + y * 4].m_comps[c] = static_cast<uint8_t>((val * 255 + 1024) / 2047);
+
+ } // x
+ } // y
+ }
+
+ void unpack_etc2_eac_rg(const void* p, color_rgba* pPixels)
+ {
+ for (uint32_t c = 0; c < 2; c++)
+ {
+ const etc2_eac_r11* pBlock = &static_cast<const etc2_eac_rg11*>(p)->m_c[c];
+
+ unpack_etc2_eac_r(pBlock, pPixels, c);
+ }
+ }
+
+ // Unpacks to RGBA, R, RG, or A
+ bool unpack_block(texture_format fmt, const void* pBlock, color_rgba* pPixels)
+ {
+ switch (fmt)
+ {
+ case texture_format::cBC1:
+ {
+ unpack_bc1(pBlock, pPixels, true);
+ break;
+ }
+ case texture_format::cBC3:
+ {
+ return unpack_bc3(pBlock, pPixels);
+ }
+ case texture_format::cBC4:
+ {
+ // Unpack to R
+ unpack_bc4(pBlock, &pPixels[0].r, sizeof(color_rgba));
+ break;
+ }
+ case texture_format::cBC5:
+ {
+ unpack_bc5(pBlock, pPixels);
+ break;
+ }
+ case texture_format::cBC7:
+ {
+ // We only support modes 5 and 6.
+ if (!unpack_bc7_mode5(pBlock, pPixels))
+ {
+ if (!unpack_bc7_mode6(pBlock, pPixels))
+ return false;
+ }
+
+ break;
+ }
+ // Full ETC2 color blocks (planar/T/H modes) is currently unsupported in basisu, but we do support ETC2 with alpha (using ETC1 for color)
+ case texture_format::cETC2_RGB:
+ case texture_format::cETC1:
+ case texture_format::cETC1S:
+ {
+ return unpack_etc1(*static_cast<const etc_block*>(pBlock), pPixels);
+ }
+ case texture_format::cETC2_RGBA:
+ {
+ if (!unpack_etc1(static_cast<const etc_block*>(pBlock)[1], pPixels))
+ return false;
+ unpack_etc2_eac(pBlock, pPixels);
+ break;
+ }
+ case texture_format::cETC2_ALPHA:
+ {
+ // Unpack to A
+ unpack_etc2_eac(pBlock, pPixels);
+ break;
+ }
+ case texture_format::cASTC4x4:
+ {
+ const bool astc_srgb = false;
+ basisu_astc::astc::decompress(reinterpret_cast<uint8_t*>(pPixels), static_cast<const uint8_t*>(pBlock), astc_srgb, 4, 4);
+ break;
+ }
+ case texture_format::cATC_RGB:
+ {
+ unpack_atc(pBlock, pPixels);
+ break;
+ }
+ case texture_format::cATC_RGBA_INTERPOLATED_ALPHA:
+ {
+ unpack_atc(static_cast<const uint8_t*>(pBlock) + 8, pPixels);
+ unpack_bc4(pBlock, &pPixels[0].a, sizeof(color_rgba));
+ break;
+ }
+ case texture_format::cFXT1_RGB:
+ {
+ unpack_fxt1(pBlock, pPixels);
+ break;
+ }
+ case texture_format::cPVRTC2_4_RGBA:
+ {
+ unpack_pvrtc2(pBlock, pPixels);
+ break;
+ }
+ case texture_format::cETC2_R11_EAC:
+ {
+ unpack_etc2_eac_r(static_cast<const etc2_eac_r11 *>(pBlock), pPixels, 0);
+ break;
+ }
+ case texture_format::cETC2_RG11_EAC:
+ {
+ unpack_etc2_eac_rg(pBlock, pPixels);
+ break;
+ }
+ default:
+ {
+ assert(0);
+ // TODO
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool gpu_image::unpack(image& img) const
+ {
+ img.resize(get_pixel_width(), get_pixel_height());
+ img.set_all(g_black_color);
+
+ if (!img.get_width() || !img.get_height())
+ return true;
+
+ if ((m_fmt == texture_format::cPVRTC1_4_RGB) || (m_fmt == texture_format::cPVRTC1_4_RGBA))
+ {
+ pvrtc4_image pi(m_width, m_height);
+
+ if (get_total_blocks() != pi.get_total_blocks())
+ return false;
+
+ memcpy(&pi.get_blocks()[0], get_ptr(), get_size_in_bytes());
+
+ pi.deswizzle();
+
+ pi.unpack_all_pixels(img);
+
+ return true;
+ }
+
+ assert((m_block_width <= cMaxBlockSize) && (m_block_height <= cMaxBlockSize));
+ color_rgba pixels[cMaxBlockSize * cMaxBlockSize];
+ for (uint32_t i = 0; i < cMaxBlockSize * cMaxBlockSize; i++)
+ pixels[i] = g_black_color;
+
+ bool success = true;
+
+ for (uint32_t by = 0; by < m_blocks_y; by++)
+ {
+ for (uint32_t bx = 0; bx < m_blocks_x; bx++)
+ {
+ const void* pBlock = get_block_ptr(bx, by);
+
+ if (!unpack_block(m_fmt, pBlock, pixels))
+ success = false;
+
+ img.set_block_clipped(pixels, bx * m_block_width, by * m_block_height, m_block_width, m_block_height);
+ } // bx
+ } // by
+
+ return success;
+ }
+
+ static const uint8_t g_ktx_file_id[12] = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
+
+ // KTX/GL enums
+ enum
+ {
+ KTX_ENDIAN = 0x04030201,
+ KTX_OPPOSITE_ENDIAN = 0x01020304,
+ KTX_ETC1_RGB8_OES = 0x8D64,
+ KTX_RED = 0x1903,
+ KTX_RG = 0x8227,
+ KTX_RGB = 0x1907,
+ KTX_RGBA = 0x1908,
+ KTX_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0,
+ KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3,
+ KTX_COMPRESSED_RED_RGTC1_EXT = 0x8DBB,
+ KTX_COMPRESSED_RED_GREEN_RGTC2_EXT = 0x8DBD,
+ KTX_COMPRESSED_RGB8_ETC2 = 0x9274,
+ KTX_COMPRESSED_RGBA8_ETC2_EAC = 0x9278,
+ KTX_COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C,
+ KTX_COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 0x8E8D,
+ KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00,
+ KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02,
+ KTX_COMPRESSED_RGBA_ASTC_4x4_KHR = 0x93B0,
+ KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR = 0x93D0,
+ KTX_ATC_RGB_AMD = 0x8C92,
+ KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD = 0x87EE,
+ KTX_COMPRESSED_RGB_FXT1_3DFX = 0x86B0,
+ KTX_COMPRESSED_RGBA_FXT1_3DFX = 0x86B1,
+ KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG = 0x9138,
+ KTX_COMPRESSED_R11_EAC = 0x9270,
+ KTX_COMPRESSED_RG11_EAC = 0x9272
+ };
+
+ struct ktx_header
+ {
+ uint8_t m_identifier[12];
+ packed_uint<4> m_endianness;
+ packed_uint<4> m_glType;
+ packed_uint<4> m_glTypeSize;
+ packed_uint<4> m_glFormat;
+ packed_uint<4> m_glInternalFormat;
+ packed_uint<4> m_glBaseInternalFormat;
+ packed_uint<4> m_pixelWidth;
+ packed_uint<4> m_pixelHeight;
+ packed_uint<4> m_pixelDepth;
+ packed_uint<4> m_numberOfArrayElements;
+ packed_uint<4> m_numberOfFaces;
+ packed_uint<4> m_numberOfMipmapLevels;
+ packed_uint<4> m_bytesOfKeyValueData;
+
+ void clear() { clear_obj(*this); }
+ };
+
+ // Input is a texture array of mipmapped gpu_image's: gpu_images[array_index][level_index]
+ bool create_ktx_texture_file(uint8_vec &ktx_data, const std::vector<gpu_image_vec>& gpu_images, bool cubemap_flag)
+ {
+ if (!gpu_images.size())
+ {
+ assert(0);
+ return false;
+ }
+
+ uint32_t width = 0, height = 0, total_levels = 0;
+ basisu::texture_format fmt = texture_format::cInvalidTextureFormat;
+
+ if (cubemap_flag)
+ {
+ if ((gpu_images.size() % 6) != 0)
+ {
+ assert(0);
+ return false;
+ }
+ }
+
+ for (uint32_t array_index = 0; array_index < gpu_images.size(); array_index++)
+ {
+ const gpu_image_vec &levels = gpu_images[array_index];
+
+ if (!levels.size())
+ {
+ // Empty mip chain
+ assert(0);
+ return false;
+ }
+
+ if (!array_index)
+ {
+ width = levels[0].get_pixel_width();
+ height = levels[0].get_pixel_height();
+ total_levels = (uint32_t)levels.size();
+ fmt = levels[0].get_format();
+ }
+ else
+ {
+ if ((width != levels[0].get_pixel_width()) ||
+ (height != levels[0].get_pixel_height()) ||
+ (total_levels != levels.size()))
+ {
+ // All cubemap/texture array faces must be the same dimension
+ assert(0);
+ return false;
+ }
+ }
+
+ for (uint32_t level_index = 0; level_index < levels.size(); level_index++)
+ {
+ if (level_index)
+ {
+ if ( (levels[level_index].get_pixel_width() != maximum<uint32_t>(1, levels[0].get_pixel_width() >> level_index)) ||
+ (levels[level_index].get_pixel_height() != maximum<uint32_t>(1, levels[0].get_pixel_height() >> level_index)) )
+ {
+ // Malformed mipmap chain
+ assert(0);
+ return false;
+ }
+ }
+
+ if (fmt != levels[level_index].get_format())
+ {
+ // All input textures must use the same GPU format
+ assert(0);
+ return false;
+ }
+ }
+ }
+
+ uint32_t internal_fmt = KTX_ETC1_RGB8_OES, base_internal_fmt = KTX_RGB;
+
+ switch (fmt)
+ {
+ case texture_format::cBC1:
+ {
+ internal_fmt = KTX_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ break;
+ }
+ case texture_format::cBC3:
+ {
+ internal_fmt = KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ base_internal_fmt = KTX_RGBA;
+ break;
+ }
+ case texture_format::cBC4:
+ {
+ internal_fmt = KTX_COMPRESSED_RED_RGTC1_EXT;// KTX_COMPRESSED_LUMINANCE_LATC1_EXT;
+ base_internal_fmt = KTX_RED;
+ break;
+ }
+ case texture_format::cBC5:
+ {
+ internal_fmt = KTX_COMPRESSED_RED_GREEN_RGTC2_EXT;
+ base_internal_fmt = KTX_RG;
+ break;
+ }
+ case texture_format::cETC1:
+ case texture_format::cETC1S:
+ {
+ internal_fmt = KTX_ETC1_RGB8_OES;
+ break;
+ }
+ case texture_format::cETC2_RGB:
+ {
+ internal_fmt = KTX_COMPRESSED_RGB8_ETC2;
+ break;
+ }
+ case texture_format::cETC2_RGBA:
+ {
+ internal_fmt = KTX_COMPRESSED_RGBA8_ETC2_EAC;
+ base_internal_fmt = KTX_RGBA;
+ break;
+ }
+ case texture_format::cBC7:
+ {
+ internal_fmt = KTX_COMPRESSED_RGBA_BPTC_UNORM;
+ base_internal_fmt = KTX_RGBA;
+ break;
+ }
+ case texture_format::cPVRTC1_4_RGB:
+ {
+ internal_fmt = KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
+ break;
+ }
+ case texture_format::cPVRTC1_4_RGBA:
+ {
+ internal_fmt = KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
+ base_internal_fmt = KTX_RGBA;
+ break;
+ }
+ case texture_format::cASTC4x4:
+ {
+ internal_fmt = KTX_COMPRESSED_RGBA_ASTC_4x4_KHR;
+ base_internal_fmt = KTX_RGBA;
+ break;
+ }
+ case texture_format::cATC_RGB:
+ {
+ internal_fmt = KTX_ATC_RGB_AMD;
+ break;
+ }
+ case texture_format::cATC_RGBA_INTERPOLATED_ALPHA:
+ {
+ internal_fmt = KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD;
+ base_internal_fmt = KTX_RGBA;
+ break;
+ }
+ case texture_format::cETC2_R11_EAC:
+ {
+ internal_fmt = KTX_COMPRESSED_R11_EAC;
+ base_internal_fmt = KTX_RED;
+ break;
+ }
+ case texture_format::cETC2_RG11_EAC:
+ {
+ internal_fmt = KTX_COMPRESSED_RG11_EAC;
+ base_internal_fmt = KTX_RG;
+ break;
+ }
+ case texture_format::cFXT1_RGB:
+ {
+ internal_fmt = KTX_COMPRESSED_RGB_FXT1_3DFX;
+ break;
+ }
+ case texture_format::cPVRTC2_4_RGBA:
+ {
+ internal_fmt = KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG;
+ base_internal_fmt = KTX_RGBA;
+ break;
+ }
+ default:
+ {
+ // TODO
+ assert(0);
+ return false;
+ }
+ }
+
+ ktx_header header;
+ header.clear();
+ memcpy(&header.m_identifier, g_ktx_file_id, sizeof(g_ktx_file_id));
+ header.m_endianness = KTX_ENDIAN;
+
+ header.m_pixelWidth = width;
+ header.m_pixelHeight = height;
+
+ header.m_glInternalFormat = internal_fmt;
+ header.m_glBaseInternalFormat = base_internal_fmt;
+
+ header.m_numberOfArrayElements = (uint32_t)(cubemap_flag ? (gpu_images.size() / 6) : gpu_images.size());
+ if (header.m_numberOfArrayElements == 1)
+ header.m_numberOfArrayElements = 0;
+
+ header.m_numberOfMipmapLevels = total_levels;
+ header.m_numberOfFaces = cubemap_flag ? 6 : 1;
+
+ append_vector(ktx_data, (uint8_t *)&header, sizeof(header));
+
+ for (uint32_t level_index = 0; level_index < total_levels; level_index++)
+ {
+ uint32_t img_size = gpu_images[0][level_index].get_size_in_bytes();
+
+ if ((header.m_numberOfFaces == 1) || (header.m_numberOfArrayElements > 1))
+ {
+ img_size = img_size * header.m_numberOfFaces * maximum<uint32_t>(1, header.m_numberOfArrayElements);
+ }
+
+ assert(img_size && ((img_size & 3) == 0));
+
+ packed_uint<4> packed_img_size(img_size);
+ append_vector(ktx_data, (uint8_t *)&packed_img_size, sizeof(packed_img_size));
+
+ uint32_t bytes_written = 0;
+
+ for (uint32_t array_index = 0; array_index < maximum<uint32_t>(1, header.m_numberOfArrayElements); array_index++)
+ {
+ for (uint32_t face_index = 0; face_index < header.m_numberOfFaces; face_index++)
+ {
+ const gpu_image& img = gpu_images[cubemap_flag ? (array_index * 6 + face_index) : array_index][level_index];
+
+ append_vector(ktx_data, (uint8_t *)img.get_ptr(), img.get_size_in_bytes());
+
+ bytes_written += img.get_size_in_bytes();
+ }
+
+ } // array_index
+
+ } // level_index
+
+ return true;
+ }
+
+ bool write_compressed_texture_file(const char* pFilename, const std::vector<gpu_image_vec>& g, bool cubemap_flag)
+ {
+ std::string extension(string_tolower(string_get_extension(pFilename)));
+
+ uint8_vec filedata;
+ if (extension == "ktx")
+ {
+ if (!create_ktx_texture_file(filedata, g, cubemap_flag))
+ return false;
+ }
+ else if (extension == "pvr")
+ {
+ // TODO
+ return false;
+ }
+ else if (extension == "dds")
+ {
+ // TODO
+ return false;
+ }
+ else
+ {
+ // unsupported texture format
+ assert(0);
+ return false;
+ }
+
+ return basisu::write_vec_to_file(pFilename, filedata);
+ }
+
+ bool write_compressed_texture_file(const char* pFilename, const gpu_image& g)
+ {
+ std::vector<gpu_image_vec> v;
+ enlarge_vector(v, 1)->push_back(g);
+ return write_compressed_texture_file(pFilename, v, false);
+ }
+
+ const uint32_t OUT_FILE_MAGIC = 'TEXC';
+ struct out_file_header
+ {
+ packed_uint<4> m_magic;
+ packed_uint<4> m_pad;
+ packed_uint<4> m_width;
+ packed_uint<4> m_height;
+ };
+
+ // As no modern tool supports FXT1 format .KTX files, let's write .OUT files and make sure 3DFX's original tools shipped in 1999 can decode our encoded output.
+ bool write_3dfx_out_file(const char* pFilename, const gpu_image& gi)
+ {
+ out_file_header hdr;
+ hdr.m_magic = OUT_FILE_MAGIC;
+ hdr.m_pad = 0;
+ hdr.m_width = gi.get_blocks_x() * 8;
+ hdr.m_height = gi.get_blocks_y() * 4;
+
+ FILE* pFile = nullptr;
+#ifdef _WIN32
+ fopen_s(&pFile, pFilename, "wb");
+#else
+ pFile = fopen(pFilename, "wb");
+#endif
+ if (!pFile)
+ return false;
+
+ fwrite(&hdr, sizeof(hdr), 1, pFile);
+ fwrite(gi.get_ptr(), gi.get_size_in_bytes(), 1, pFile);
+
+ return fclose(pFile) != EOF;
+ }
+} // basisu
+
diff --git a/thirdparty/basis_universal/basisu_gpu_texture.h b/thirdparty/basis_universal/basisu_gpu_texture.h
new file mode 100644
index 0000000000..8a49757ca7
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_gpu_texture.h
@@ -0,0 +1,154 @@
+// basisu_gpu_texture.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "transcoder/basisu.h"
+#include "basisu_etc.h"
+
+namespace basisu
+{
+ // GPU texture image
+
+ class gpu_image
+ {
+ public:
+ enum { cMaxBlockSize = 12 };
+
+ gpu_image()
+ {
+ clear();
+ }
+
+ gpu_image(texture_format fmt, uint32_t width, uint32_t height)
+ {
+ init(fmt, width, height);
+ }
+
+ void clear()
+ {
+ m_fmt = texture_format::cInvalidTextureFormat;
+ m_width = 0;
+ m_height = 0;
+ m_block_width = 0;
+ m_block_height = 0;
+ m_blocks_x = 0;
+ m_blocks_y = 0;
+ m_qwords_per_block = 0;
+ m_blocks.clear();
+ }
+
+ inline texture_format get_format() const { return m_fmt; }
+
+ // Width/height in pixels
+ inline uint32_t get_pixel_width() const { return m_width; }
+ inline uint32_t get_pixel_height() const { return m_height; }
+
+ // Width/height in blocks, row pitch is assumed to be m_blocks_x.
+ inline uint32_t get_blocks_x() const { return m_blocks_x; }
+ inline uint32_t get_blocks_y() const { return m_blocks_y; }
+
+ // Size of each block in pixels
+ inline uint32_t get_block_width() const { return m_block_width; }
+ inline uint32_t get_block_height() const { return m_block_height; }
+
+ inline uint32_t get_qwords_per_block() const { return m_qwords_per_block; }
+ inline uint32_t get_total_blocks() const { return m_blocks_x * m_blocks_y; }
+ inline uint32_t get_bytes_per_block() const { return get_qwords_per_block() * sizeof(uint64_t); }
+ inline uint32_t get_row_pitch_in_bytes() const { return get_bytes_per_block() * get_blocks_x(); }
+
+ inline const uint64_vec &get_blocks() const { return m_blocks; }
+
+ inline const uint64_t *get_ptr() const { return &m_blocks[0]; }
+ inline uint64_t *get_ptr() { return &m_blocks[0]; }
+
+ inline uint32_t get_size_in_bytes() const { return get_total_blocks() * get_qwords_per_block() * sizeof(uint64_t); }
+
+ inline const void *get_block_ptr(uint32_t block_x, uint32_t block_y, uint32_t element_index = 0) const
+ {
+ assert(block_x < m_blocks_x && block_y < m_blocks_y);
+ return &m_blocks[(block_x + block_y * m_blocks_x) * m_qwords_per_block + element_index];
+ }
+
+ inline void *get_block_ptr(uint32_t block_x, uint32_t block_y, uint32_t element_index = 0)
+ {
+ assert(block_x < m_blocks_x && block_y < m_blocks_y && element_index < m_qwords_per_block);
+ return &m_blocks[(block_x + block_y * m_blocks_x) * m_qwords_per_block + element_index];
+ }
+
+ void init(texture_format fmt, uint32_t width, uint32_t height)
+ {
+ m_fmt = fmt;
+ m_width = width;
+ m_height = height;
+ m_block_width = basisu::get_block_width(m_fmt);
+ m_block_height = basisu::get_block_height(m_fmt);
+ m_blocks_x = (m_width + m_block_width - 1) / m_block_width;
+ m_blocks_y = (m_height + m_block_height - 1) / m_block_height;
+ m_qwords_per_block = basisu::get_qwords_per_block(m_fmt);
+
+ m_blocks.resize(0);
+ m_blocks.resize(m_blocks_x * m_blocks_y * m_qwords_per_block);
+ }
+
+ bool unpack(image& img) const;
+
+ void override_dimensions(uint32_t w, uint32_t h)
+ {
+ m_width = w;
+ m_height = h;
+ }
+
+ private:
+ texture_format m_fmt;
+ uint32_t m_width, m_height, m_blocks_x, m_blocks_y, m_block_width, m_block_height, m_qwords_per_block;
+ uint64_vec m_blocks;
+ };
+
+ typedef std::vector<gpu_image> gpu_image_vec;
+
+ // KTX file writing
+
+ bool create_ktx_texture_file(uint8_vec &ktx_data, const std::vector<gpu_image_vec>& gpu_images, bool cubemap_flag);
+
+ bool write_compressed_texture_file(const char *pFilename, const std::vector<gpu_image_vec>& g, bool cubemap_flag);
+
+ inline bool write_compressed_texture_file(const char *pFilename, const gpu_image_vec &g)
+ {
+ std::vector<gpu_image_vec> a;
+ a.push_back(g);
+ return write_compressed_texture_file(pFilename, a, false);
+ }
+
+ bool write_compressed_texture_file(const char *pFilename, const gpu_image &g);
+
+ bool write_3dfx_out_file(const char* pFilename, const gpu_image& gi);
+ // GPU texture block unpacking
+
+ void unpack_etc2_eac(const void *pBlock_bits, color_rgba *pPixels);
+ bool unpack_bc1(const void *pBlock_bits, color_rgba *pPixels, bool set_alpha);
+ void unpack_bc4(const void *pBlock_bits, uint8_t *pPixels, uint32_t stride);
+ bool unpack_bc3(const void *pBlock_bits, color_rgba *pPixels);
+ void unpack_bc5(const void *pBlock_bits, color_rgba *pPixels);
+ bool unpack_bc7_mode6(const void *pBlock_bits, color_rgba *pPixels);
+ bool unpack_bc7_mode5(const void* pBlock_bits, color_rgba* pPixels);
+ void unpack_atc(const void* pBlock_bits, color_rgba* pPixels);
+ bool unpack_fxt1(const void* p, color_rgba* pPixels);
+ bool unpack_pvrtc2(const void* p, color_rgba* pPixels);
+ void unpack_etc2_eac_rg(const void* p, color_rgba* pPixels);
+
+ // unpack_block() is only capable of unpacking texture data created by the transcoder.
+ // For some texture formats (like BC7, or ETC2) it's not a complete implementation.
+ bool unpack_block(texture_format fmt, const void *pBlock, color_rgba *pPixels);
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_pvrtc1_4.cpp b/thirdparty/basis_universal/basisu_pvrtc1_4.cpp
new file mode 100644
index 0000000000..f0122fcb6c
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_pvrtc1_4.cpp
@@ -0,0 +1,269 @@
+// basisu_pvrtc1_4.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_pvrtc1_4.h"
+
+namespace basisu
+{
+ uint32_t pvrtc4_swizzle_uv(uint32_t width, uint32_t height, uint32_t x, uint32_t y)
+ {
+ assert((x < width) && (y < height) && basisu::is_pow2(height) && basisu::is_pow2(width));
+
+ uint32_t min_d = width, max_v = y;
+ if (height < width)
+ {
+ min_d = height;
+ max_v = x;
+ }
+
+ // Interleave the XY LSB's
+ uint32_t shift_ofs = 0, swizzled = 0;
+ for (uint32_t s_bit = 1, d_bit = 1; s_bit < min_d; s_bit <<= 1, d_bit <<= 2, ++shift_ofs)
+ {
+ if (y & s_bit) swizzled |= d_bit;
+ if (x & s_bit) swizzled |= (2 * d_bit);
+ }
+
+ max_v >>= shift_ofs;
+
+ // OR in the rest of the bits from the largest dimension
+ swizzled |= (max_v << (2 * shift_ofs));
+
+ return swizzled;
+ }
+
+ color_rgba pvrtc4_block::get_endpoint(uint32_t endpoint_index, bool unpack) const
+ {
+ assert(endpoint_index < 2);
+ const uint32_t packed = m_endpoints >> (endpoint_index * 16);
+
+ uint32_t r, g, b, a;
+ if (packed & 0x8000)
+ {
+ // opaque 554 or 555
+ if (!endpoint_index)
+ {
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = (packed >> 1) & 15;
+
+ if (unpack)
+ {
+ b = (b << 1) | (b >> 3);
+ }
+ }
+ else
+ {
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = packed & 31;
+ }
+
+ a = unpack ? 255 : 7;
+ }
+ else
+ {
+ // translucent 4433 or 4443
+ if (!endpoint_index)
+ {
+ a = (packed >> 12) & 7;
+ r = (packed >> 8) & 15;
+ g = (packed >> 4) & 15;
+ b = (packed >> 1) & 7;
+
+ if (unpack)
+ {
+ a = (a << 1);
+ a = (a << 4) | a;
+
+ r = (r << 1) | (r >> 3);
+ g = (g << 1) | (g >> 3);
+ b = (b << 2) | (b >> 1);
+ }
+ }
+ else
+ {
+ a = (packed >> 12) & 7;
+ r = (packed >> 8) & 15;
+ g = (packed >> 4) & 15;
+ b = packed & 15;
+
+ if (unpack)
+ {
+ a = (a << 1);
+ a = (a << 4) | a;
+
+ r = (r << 1) | (r >> 3);
+ g = (g << 1) | (g >> 3);
+ b = (b << 1) | (b >> 3);
+ }
+ }
+ }
+
+ if (unpack)
+ {
+ r = (r << 3) | (r >> 2);
+ g = (g << 3) | (g >> 2);
+ b = (b << 3) | (b >> 2);
+ }
+
+ assert((r < 256) && (g < 256) && (b < 256) && (a < 256));
+
+ return color_rgba(r, g, b, a);
+ }
+
+ color_rgba pvrtc4_block::get_endpoint_5554(uint32_t endpoint_index) const
+ {
+ assert(endpoint_index < 2);
+ const uint32_t packed = m_endpoints >> (endpoint_index * 16);
+
+ uint32_t r, g, b, a;
+ if (packed & 0x8000)
+ {
+ // opaque 554 or 555
+ if (!endpoint_index)
+ {
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = (packed >> 1) & 15;
+
+ b = (b << 1) | (b >> 3);
+ }
+ else
+ {
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = packed & 31;
+ }
+
+ a = 15;
+ }
+ else
+ {
+ // translucent 4433 or 4443
+ if (!endpoint_index)
+ {
+ a = (packed >> 12) & 7;
+ r = (packed >> 8) & 15;
+ g = (packed >> 4) & 15;
+ b = (packed >> 1) & 7;
+
+ a = a << 1;
+
+ r = (r << 1) | (r >> 3);
+ g = (g << 1) | (g >> 3);
+ b = (b << 2) | (b >> 1);
+ }
+ else
+ {
+ a = (packed >> 12) & 7;
+ r = (packed >> 8) & 15;
+ g = (packed >> 4) & 15;
+ b = packed & 15;
+
+ a = a << 1;
+
+ r = (r << 1) | (r >> 3);
+ g = (g << 1) | (g >> 3);
+ b = (b << 1) | (b >> 3);
+ }
+ }
+
+ assert((r < 32) && (g < 32) && (b < 32) && (a < 16));
+
+ return color_rgba(r, g, b, a);
+ }
+
+ bool pvrtc4_image::get_interpolated_colors(uint32_t x, uint32_t y, color_rgba* pColors) const
+ {
+ assert((x < m_width) && (y < m_height));
+
+ int block_x0 = (static_cast<int>(x) - 2) >> 2;
+ int block_x1 = block_x0 + 1;
+ int block_y0 = (static_cast<int>(y) - 2) >> 2;
+ int block_y1 = block_y0 + 1;
+
+ block_x0 = posmod(block_x0, m_block_width);
+ block_x1 = posmod(block_x1, m_block_width);
+ block_y0 = posmod(block_y0, m_block_height);
+ block_y1 = posmod(block_y1, m_block_height);
+
+ pColors[0] = interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0));
+ pColors[3] = interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1));
+
+ if (get_block_uses_transparent_modulation(x >> 2, y >> 2))
+ {
+ for (uint32_t c = 0; c < 4; c++)
+ {
+ uint32_t m = (pColors[0][c] + pColors[3][c]) / 2;
+ pColors[1][c] = static_cast<uint8_t>(m);
+ pColors[2][c] = static_cast<uint8_t>(m);
+ }
+ pColors[2][3] = 0;
+ return true;
+ }
+
+ for (uint32_t c = 0; c < 4; c++)
+ {
+ pColors[1][c] = static_cast<uint8_t>((pColors[0][c] * 5 + pColors[3][c] * 3) / 8);
+ pColors[2][c] = static_cast<uint8_t>((pColors[0][c] * 3 + pColors[3][c] * 5) / 8);
+ }
+
+ return false;
+ }
+
+ color_rgba pvrtc4_image::get_pixel(uint32_t x, uint32_t y, uint32_t m) const
+ {
+ assert((x < m_width) && (y < m_height));
+
+ int block_x0 = (static_cast<int>(x) - 2) >> 2;
+ int block_x1 = block_x0 + 1;
+ int block_y0 = (static_cast<int>(y) - 2) >> 2;
+ int block_y1 = block_y0 + 1;
+
+ block_x0 = posmod(block_x0, m_block_width);
+ block_x1 = posmod(block_x1, m_block_width);
+ block_y0 = posmod(block_y0, m_block_height);
+ block_y1 = posmod(block_y1, m_block_height);
+
+ if (get_block_uses_transparent_modulation(x >> 2, y >> 2))
+ {
+ if (m == 0)
+ return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0));
+ else if (m == 3)
+ return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1));
+
+ color_rgba l(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0)));
+ color_rgba h(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1)));
+
+ return color_rgba((l[0] + h[0]) / 2, (l[1] + h[1]) / 2, (l[2] + h[2]) / 2, (m == 2) ? 0 : (l[3] + h[3]) / 2);
+ }
+ else
+ {
+ if (m == 0)
+ return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0));
+ else if (m == 3)
+ return interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1));
+
+ color_rgba l(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0)));
+ color_rgba h(interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1)));
+
+ if (m == 2)
+ return color_rgba((l[0] * 3 + h[0] * 5) / 8, (l[1] * 3 + h[1] * 5) / 8, (l[2] * 3 + h[2] * 5) / 8, (l[3] * 3 + h[3] * 5) / 8);
+ else
+ return color_rgba((l[0] * 5 + h[0] * 3) / 8, (l[1] * 5 + h[1] * 3) / 8, (l[2] * 5 + h[2] * 3) / 8, (l[3] * 5 + h[3] * 3) / 8);
+ }
+ }
+
+} // basisu
diff --git a/thirdparty/basis_universal/basisu_pvrtc1_4.h b/thirdparty/basis_universal/basisu_pvrtc1_4.h
new file mode 100644
index 0000000000..80b4413351
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_pvrtc1_4.h
@@ -0,0 +1,363 @@
+// basisu_pvrtc1_4.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "basisu_gpu_texture.h"
+
+namespace basisu
+{
+ enum
+ {
+ PVRTC2_MIN_WIDTH = 16,
+ PVRTC2_MIN_HEIGHT = 8,
+ PVRTC4_MIN_WIDTH = 8,
+ PVRTC4_MIN_HEIGHT = 8
+ };
+
+ struct pvrtc4_block
+ {
+ uint32_t m_modulation;
+ uint32_t m_endpoints;
+
+ pvrtc4_block() : m_modulation(0), m_endpoints(0) { }
+
+ inline bool operator== (const pvrtc4_block& rhs) const
+ {
+ return (m_modulation == rhs.m_modulation) && (m_endpoints == rhs.m_endpoints);
+ }
+
+ inline void clear()
+ {
+ m_modulation = 0;
+ m_endpoints = 0;
+ }
+
+ inline bool get_block_uses_transparent_modulation() const
+ {
+ return (m_endpoints & 1) != 0;
+ }
+
+ inline bool is_endpoint_opaque(uint32_t endpoint_index) const
+ {
+ static const uint32_t s_bitmasks[2] = { 0x8000U, 0x80000000U };
+ return (m_endpoints & s_bitmasks[open_range_check(endpoint_index, 2U)]) != 0;
+ }
+
+ // Returns raw endpoint or 8888
+ color_rgba get_endpoint(uint32_t endpoint_index, bool unpack) const;
+
+ color_rgba get_endpoint_5554(uint32_t endpoint_index) const;
+
+ static uint32_t get_component_precision_in_bits(uint32_t c, uint32_t endpoint_index, bool opaque_endpoint)
+ {
+ static const uint32_t s_comp_prec[4][4] =
+ {
+ // R0 G0 B0 A0 R1 G1 B1 A1
+ { 4, 4, 3, 3 }, { 4, 4, 4, 3 }, // transparent endpoint
+
+ { 5, 5, 4, 0 }, { 5, 5, 5, 0 } // opaque endpoint
+ };
+ return s_comp_prec[open_range_check(endpoint_index, 2U) + (opaque_endpoint * 2)][open_range_check(c, 4U)];
+ }
+
+ static color_rgba get_color_precision_in_bits(uint32_t endpoint_index, bool opaque_endpoint)
+ {
+ static const color_rgba s_color_prec[4] =
+ {
+ color_rgba(4, 4, 3, 3), color_rgba(4, 4, 4, 3), // transparent endpoint
+ color_rgba(5, 5, 4, 0), color_rgba(5, 5, 5, 0) // opaque endpoint
+ };
+ return s_color_prec[open_range_check(endpoint_index, 2U) + (opaque_endpoint * 2)];
+ }
+
+ inline uint32_t get_modulation(uint32_t x, uint32_t y) const
+ {
+ assert((x < 4) && (y < 4));
+ return (m_modulation >> ((y * 4 + x) * 2)) & 3;
+ }
+
+ // Scaled by 8
+ inline const uint32_t* get_scaled_modulation_values(bool block_uses_transparent_modulation) const
+ {
+ static const uint32_t s_block_scales[2][4] = { { 0, 3, 5, 8 }, { 0, 4, 4, 8 } };
+ return s_block_scales[block_uses_transparent_modulation];
+ }
+
+ // Scaled by 8
+ inline uint32_t get_scaled_modulation(uint32_t x, uint32_t y) const
+ {
+ return get_scaled_modulation_values(get_block_uses_transparent_modulation())[get_modulation(x, y)];
+ }
+
+ inline void byte_swap()
+ {
+ m_modulation = byteswap32(m_modulation);
+ m_endpoints = byteswap32(m_endpoints);
+ }
+
+ // opaque endpoints: 554, 555
+ // transparent endpoints: 3443 or 3444
+ inline void set_endpoint_raw(uint32_t endpoint_index, const color_rgba& c, bool opaque_endpoint)
+ {
+ assert(endpoint_index < 2);
+ const uint32_t m = m_endpoints & 1;
+ uint32_t r = c[0], g = c[1], b = c[2], a = c[3];
+
+ uint32_t packed;
+
+ if (opaque_endpoint)
+ {
+ if (!endpoint_index)
+ {
+ // 554
+ // 1RRRRRGGGGGBBBBM
+ assert((r < 32) && (g < 32) && (b < 16));
+ packed = 0x8000 | (r << 10) | (g << 5) | (b << 1) | m;
+ }
+ else
+ {
+ // 555
+ // 1RRRRRGGGGGBBBBB
+ assert((r < 32) && (g < 32) && (b < 32));
+ packed = 0x8000 | (r << 10) | (g << 5) | b;
+ }
+ }
+ else
+ {
+ if (!endpoint_index)
+ {
+ // 3443
+ // 0AAA RRRR GGGG BBBM
+ assert((r < 16) && (g < 16) && (b < 8) && (a < 8));
+ packed = (a << 12) | (r << 8) | (g << 4) | (b << 1) | m;
+ }
+ else
+ {
+ // 3444
+ // 0AAA RRRR GGGG BBBB
+ assert((r < 16) && (g < 16) && (b < 16) && (a < 8));
+ packed = (a << 12) | (r << 8) | (g << 4) | b;
+ }
+ }
+
+ assert(packed <= 0xFFFF);
+
+ if (endpoint_index)
+ m_endpoints = (m_endpoints & 0xFFFFU) | (packed << 16);
+ else
+ m_endpoints = (m_endpoints & 0xFFFF0000U) | packed;
+ }
+ };
+
+ typedef vector2D<pvrtc4_block> pvrtc4_block_vector2D;
+
+ uint32_t pvrtc4_swizzle_uv(uint32_t XSize, uint32_t YSize, uint32_t XPos, uint32_t YPos);
+
+ class pvrtc4_image
+ {
+ public:
+ inline pvrtc4_image() :
+ m_width(0), m_height(0), m_block_width(0), m_block_height(0), m_uses_alpha(false)
+ {
+ }
+
+ inline pvrtc4_image(uint32_t width, uint32_t height) :
+ m_width(0), m_height(0), m_block_width(0), m_block_height(0), m_uses_alpha(false)
+ {
+ resize(width, height);
+ }
+
+ inline void clear()
+ {
+ m_width = 0;
+ m_height = 0;
+ m_block_width = 0;
+ m_block_height = 0;
+ m_blocks.clear();
+ m_uses_alpha = false;
+ }
+
+ inline void resize(uint32_t width, uint32_t height)
+ {
+ if ((width == m_width) && (height == m_height))
+ return;
+
+ m_width = width;
+ m_height = height;
+
+ m_block_width = (width + 3) >> 2;
+ m_block_height = (height + 3) >> 2;
+
+ m_blocks.resize(m_block_width, m_block_height);
+ }
+
+ inline uint32_t get_width() const { return m_width; }
+ inline uint32_t get_height() const { return m_height; }
+
+ inline uint32_t get_block_width() const { return m_block_width; }
+ inline uint32_t get_block_height() const { return m_block_height; }
+
+ inline const pvrtc4_block_vector2D &get_blocks() const { return m_blocks; }
+ inline pvrtc4_block_vector2D &get_blocks() { return m_blocks; }
+
+ inline uint32_t get_total_blocks() const { return m_block_width * m_block_height; }
+
+ inline bool get_uses_alpha() const { return m_uses_alpha; }
+ inline void set_uses_alpha(bool uses_alpha) { m_uses_alpha = uses_alpha; }
+
+ inline bool are_blocks_equal(const pvrtc4_image& rhs) const
+ {
+ return m_blocks == rhs.m_blocks;
+ }
+
+ inline void set_to_black()
+ {
+ memset(m_blocks.get_ptr(), 0, m_blocks.size_in_bytes());
+ }
+
+ inline bool get_block_uses_transparent_modulation(uint32_t bx, uint32_t by) const
+ {
+ return m_blocks(bx, by).get_block_uses_transparent_modulation();
+ }
+
+ inline bool is_endpoint_opaque(uint32_t bx, uint32_t by, uint32_t endpoint_index) const
+ {
+ return m_blocks(bx, by).is_endpoint_opaque(endpoint_index);
+ }
+
+ color_rgba get_endpoint(uint32_t bx, uint32_t by, uint32_t endpoint_index, bool unpack) const
+ {
+ assert((bx < m_block_width) && (by < m_block_height));
+ return m_blocks(bx, by).get_endpoint(endpoint_index, unpack);
+ }
+
+ inline uint32_t get_modulation(uint32_t x, uint32_t y) const
+ {
+ assert((x < m_width) && (y < m_height));
+ return m_blocks(x >> 2, y >> 2).get_modulation(x & 3, y & 3);
+ }
+
+ // Returns true if the block uses transparent modulation.
+ bool get_interpolated_colors(uint32_t x, uint32_t y, color_rgba* pColors) const;
+
+ color_rgba get_pixel(uint32_t x, uint32_t y, uint32_t m) const;
+
+ inline color_rgba get_pixel(uint32_t x, uint32_t y) const
+ {
+ assert((x < m_width) && (y < m_height));
+ return get_pixel(x, y, m_blocks(x >> 2, y >> 2).get_modulation(x & 3, y & 3));
+ }
+
+ void deswizzle()
+ {
+ pvrtc4_block_vector2D temp(m_blocks);
+
+ for (uint32_t y = 0; y < m_block_height; y++)
+ for (uint32_t x = 0; x < m_block_width; x++)
+ m_blocks(x, y) = temp[pvrtc4_swizzle_uv(m_block_width, m_block_height, x, y)];
+ }
+
+ void swizzle()
+ {
+ pvrtc4_block_vector2D temp(m_blocks);
+
+ for (uint32_t y = 0; y < m_block_height; y++)
+ for (uint32_t x = 0; x < m_block_width; x++)
+ m_blocks[pvrtc4_swizzle_uv(m_block_width, m_block_height, x, y)] = temp(x, y);
+ }
+
+ void unpack_all_pixels(image& img) const
+ {
+ img.crop(m_width, m_height);
+
+ for (uint32_t y = 0; y < m_height; y++)
+ for (uint32_t x = 0; x < m_width; x++)
+ img(x, y) = get_pixel(x, y);
+ }
+
+ void unpack_block(image &dst, uint32_t block_x, uint32_t block_y)
+ {
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ dst(x, y) = get_pixel(block_x * 4 + x, block_y * 4 + y);
+ }
+
+ inline int wrap_x(int x) const
+ {
+ return posmod(x, m_width);
+ }
+
+ inline int wrap_y(int y) const
+ {
+ return posmod(y, m_height);
+ }
+
+ inline int wrap_block_x(int bx) const
+ {
+ return posmod(bx, m_block_width);
+ }
+
+ inline int wrap_block_y(int by) const
+ {
+ return posmod(by, m_block_height);
+ }
+
+ inline vec2F get_interpolation_factors(uint32_t x, uint32_t y) const
+ {
+ // 0 1 2 3
+ // 2 3 0 1
+ // .5 .75 0 .25
+ static const float s_interp[4] = { 2, 3, 0, 1 };
+ return vec2F(s_interp[x & 3], s_interp[y & 3]);
+ }
+
+ inline color_rgba interpolate(int x, int y,
+ const color_rgba& p, const color_rgba& q,
+ const color_rgba& r, const color_rgba& s) const
+ {
+ static const int s_interp[4] = { 2, 3, 0, 1 };
+ const int u_interp = s_interp[x & 3];
+ const int v_interp = s_interp[y & 3];
+
+ color_rgba result;
+
+ for (uint32_t c = 0; c < 4; c++)
+ {
+ int t = p[c] * 4 + u_interp * ((int)q[c] - (int)p[c]);
+ int b = r[c] * 4 + u_interp * ((int)s[c] - (int)r[c]);
+ int v = t * 4 + v_interp * (b - t);
+ if (c < 3)
+ {
+ v >>= 1;
+ v += (v >> 5);
+ }
+ else
+ {
+ v += (v >> 4);
+ }
+ assert((v >= 0) && (v < 256));
+ result[c] = static_cast<uint8_t>(v);
+ }
+
+ return result;
+ }
+
+ uint32_t m_width, m_height;
+ pvrtc4_block_vector2D m_blocks;
+ uint32_t m_block_width, m_block_height;
+
+ bool m_uses_alpha;
+ };
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_resample_filters.cpp b/thirdparty/basis_universal/basisu_resample_filters.cpp
new file mode 100644
index 0000000000..d0b2fd77bb
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_resample_filters.cpp
@@ -0,0 +1,328 @@
+// basisu_resampler_filters.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_resampler_filters.h"
+
+#ifndef M_PI
+ #define M_PI 3.14159265358979323846
+#endif
+
+namespace basisu
+{
+#define BOX_FILTER_SUPPORT (0.5f)
+ static float box_filter(float t) /* pulse/Fourier window */
+ {
+ // make_clist() calls the filter function with t inverted (pos = left, neg = right)
+ if ((t >= -0.5f) && (t < 0.5f))
+ return 1.0f;
+ else
+ return 0.0f;
+ }
+
+#define TENT_FILTER_SUPPORT (1.0f)
+ static float tent_filter(float t) /* box (*) box, bilinear/triangle */
+ {
+ if (t < 0.0f)
+ t = -t;
+
+ if (t < 1.0f)
+ return 1.0f - t;
+ else
+ return 0.0f;
+ }
+
+#define BELL_SUPPORT (1.5f)
+ static float bell_filter(float t) /* box (*) box (*) box */
+ {
+ if (t < 0.0f)
+ t = -t;
+
+ if (t < .5f)
+ return (.75f - (t * t));
+
+ if (t < 1.5f)
+ {
+ t = (t - 1.5f);
+ return (.5f * (t * t));
+ }
+
+ return (0.0f);
+ }
+
+#define B_SPLINE_SUPPORT (2.0f)
+ static float B_spline_filter(float t) /* box (*) box (*) box (*) box */
+ {
+ float tt;
+
+ if (t < 0.0f)
+ t = -t;
+
+ if (t < 1.0f)
+ {
+ tt = t * t;
+ return ((.5f * tt * t) - tt + (2.0f / 3.0f));
+ }
+ else if (t < 2.0f)
+ {
+ t = 2.0f - t;
+ return ((1.0f / 6.0f) * (t * t * t));
+ }
+
+ return (0.0f);
+ }
+
+ // Dodgson, N., "Quadratic Interpolation for Image Resampling"
+#define QUADRATIC_SUPPORT 1.5f
+ static float quadratic(float t, const float R)
+ {
+ if (t < 0.0f)
+ t = -t;
+ if (t < QUADRATIC_SUPPORT)
+ {
+ float tt = t * t;
+ if (t <= .5f)
+ return (-2.0f * R) * tt + .5f * (R + 1.0f);
+ else
+ return (R * tt) + (-2.0f * R - .5f) * t + (3.0f / 4.0f) * (R + 1.0f);
+ }
+ else
+ return 0.0f;
+ }
+
+ static float quadratic_interp_filter(float t)
+ {
+ return quadratic(t, 1.0f);
+ }
+
+ static float quadratic_approx_filter(float t)
+ {
+ return quadratic(t, .5f);
+ }
+
+ static float quadratic_mix_filter(float t)
+ {
+ return quadratic(t, .8f);
+ }
+
+ // Mitchell, D. and A. Netravali, "Reconstruction Filters in Computer Graphics."
+ // Computer Graphics, Vol. 22, No. 4, pp. 221-228.
+ // (B, C)
+ // (1/3, 1/3) - Defaults recommended by Mitchell and Netravali
+ // (1, 0) - Equivalent to the Cubic B-Spline
+ // (0, 0.5) - Equivalent to the Catmull-Rom Spline
+ // (0, C) - The family of Cardinal Cubic Splines
+ // (B, 0) - Duff's tensioned B-Splines.
+ static float mitchell(float t, const float B, const float C)
+ {
+ float tt;
+
+ tt = t * t;
+
+ if (t < 0.0f)
+ t = -t;
+
+ if (t < 1.0f)
+ {
+ t = (((12.0f - 9.0f * B - 6.0f * C) * (t * tt)) + ((-18.0f + 12.0f * B + 6.0f * C) * tt) + (6.0f - 2.0f * B));
+
+ return (t / 6.0f);
+ }
+ else if (t < 2.0f)
+ {
+ t = (((-1.0f * B - 6.0f * C) * (t * tt)) + ((6.0f * B + 30.0f * C) * tt) + ((-12.0f * B - 48.0f * C) * t) + (8.0f * B + 24.0f * C));
+
+ return (t / 6.0f);
+ }
+
+ return (0.0f);
+ }
+
+#define MITCHELL_SUPPORT (2.0f)
+ static float mitchell_filter(float t)
+ {
+ return mitchell(t, 1.0f / 3.0f, 1.0f / 3.0f);
+ }
+
+#define CATMULL_ROM_SUPPORT (2.0f)
+ static float catmull_rom_filter(float t)
+ {
+ return mitchell(t, 0.0f, .5f);
+ }
+
+ static double sinc(double x)
+ {
+ x = (x * M_PI);
+
+ if ((x < 0.01f) && (x > -0.01f))
+ return 1.0f + x * x * (-1.0f / 6.0f + x * x * 1.0f / 120.0f);
+
+ return sin(x) / x;
+ }
+
+ static float clean(double t)
+ {
+ const float EPSILON = .0000125f;
+ if (fabs(t) < EPSILON)
+ return 0.0f;
+ return (float)t;
+ }
+
+ //static double blackman_window(double x)
+ //{
+ // return .42f + .50f * cos(M_PI*x) + .08f * cos(2.0f*M_PI*x);
+ //}
+
+ static double blackman_exact_window(double x)
+ {
+ return 0.42659071f + 0.49656062f * cos(M_PI * x) + 0.07684867f * cos(2.0f * M_PI * x);
+ }
+
+#define BLACKMAN_SUPPORT (3.0f)
+ static float blackman_filter(float t)
+ {
+ if (t < 0.0f)
+ t = -t;
+
+ if (t < 3.0f)
+ //return clean(sinc(t) * blackman_window(t / 3.0f));
+ return clean(sinc(t) * blackman_exact_window(t / 3.0f));
+ else
+ return (0.0f);
+ }
+
+#define GAUSSIAN_SUPPORT (1.25f)
+ static float gaussian_filter(float t) // with blackman window
+ {
+ if (t < 0)
+ t = -t;
+ if (t < GAUSSIAN_SUPPORT)
+ return clean(exp(-2.0f * t * t) * sqrt(2.0f / M_PI) * blackman_exact_window(t / GAUSSIAN_SUPPORT));
+ else
+ return 0.0f;
+ }
+
+ // Windowed sinc -- see "Jimm Blinn's Corner: Dirty Pixels" pg. 26.
+#define LANCZOS3_SUPPORT (3.0f)
+ static float lanczos3_filter(float t)
+ {
+ if (t < 0.0f)
+ t = -t;
+
+ if (t < 3.0f)
+ return clean(sinc(t) * sinc(t / 3.0f));
+ else
+ return (0.0f);
+ }
+
+#define LANCZOS4_SUPPORT (4.0f)
+ static float lanczos4_filter(float t)
+ {
+ if (t < 0.0f)
+ t = -t;
+
+ if (t < 4.0f)
+ return clean(sinc(t) * sinc(t / 4.0f));
+ else
+ return (0.0f);
+ }
+
+#define LANCZOS6_SUPPORT (6.0f)
+ static float lanczos6_filter(float t)
+ {
+ if (t < 0.0f)
+ t = -t;
+
+ if (t < 6.0f)
+ return clean(sinc(t) * sinc(t / 6.0f));
+ else
+ return (0.0f);
+ }
+
+#define LANCZOS12_SUPPORT (12.0f)
+ static float lanczos12_filter(float t)
+ {
+ if (t < 0.0f)
+ t = -t;
+
+ if (t < 12.0f)
+ return clean(sinc(t) * sinc(t / 12.0f));
+ else
+ return (0.0f);
+ }
+
+ static double bessel0(double x)
+ {
+ const double EPSILON_RATIO = 1E-16;
+ double xh, sum, pow, ds;
+ int k;
+
+ xh = 0.5 * x;
+ sum = 1.0;
+ pow = 1.0;
+ k = 0;
+ ds = 1.0;
+ while (ds > sum * EPSILON_RATIO) // FIXME: Shouldn't this stop after X iterations for max. safety?
+ {
+ ++k;
+ pow = pow * (xh / k);
+ ds = pow * pow;
+ sum = sum + ds;
+ }
+
+ return sum;
+ }
+
+ static const float KAISER_ALPHA = 4.0;
+ static double kaiser(double alpha, double half_width, double x)
+ {
+ const double ratio = (x / half_width);
+ return bessel0(alpha * sqrt(1 - ratio * ratio)) / bessel0(alpha);
+ }
+
+#define KAISER_SUPPORT 3
+ static float kaiser_filter(float t)
+ {
+ if (t < 0.0f)
+ t = -t;
+
+ if (t < KAISER_SUPPORT)
+ {
+ // db atten
+ const float att = 40.0f;
+ const float alpha = (float)(exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886 * (att - 20.96));
+ //const float alpha = KAISER_ALPHA;
+ return (float)clean(sinc(t) * kaiser(alpha, KAISER_SUPPORT, t));
+ }
+
+ return 0.0f;
+ }
+
+ const resample_filter g_resample_filters[] =
+ {
+ { "box", box_filter, BOX_FILTER_SUPPORT }, { "tent", tent_filter, TENT_FILTER_SUPPORT }, { "bell", bell_filter, BELL_SUPPORT }, { "b-spline", B_spline_filter, B_SPLINE_SUPPORT },
+ { "mitchell", mitchell_filter, MITCHELL_SUPPORT }, { "lanczos3", lanczos3_filter, LANCZOS3_SUPPORT }, { "blackman", blackman_filter, BLACKMAN_SUPPORT }, { "lanczos4", lanczos4_filter, LANCZOS4_SUPPORT },
+ { "lanczos6", lanczos6_filter, LANCZOS6_SUPPORT }, { "lanczos12", lanczos12_filter, LANCZOS12_SUPPORT }, { "kaiser", kaiser_filter, KAISER_SUPPORT }, { "gaussian", gaussian_filter, GAUSSIAN_SUPPORT },
+ { "catmullrom", catmull_rom_filter, CATMULL_ROM_SUPPORT }, { "quadratic_interp", quadratic_interp_filter, QUADRATIC_SUPPORT }, { "quadratic_approx", quadratic_approx_filter, QUADRATIC_SUPPORT }, { "quadratic_mix", quadratic_mix_filter, QUADRATIC_SUPPORT },
+ };
+
+ const int g_num_resample_filters = BASISU_ARRAY_SIZE(g_resample_filters);
+
+ int find_resample_filter(const char *pName)
+ {
+ for (int i = 0; i < g_num_resample_filters; i++)
+ if (strcmp(pName, g_resample_filters[i].name) == 0)
+ return i;
+ return -1;
+ }
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_resampler.cpp b/thirdparty/basis_universal/basisu_resampler.cpp
new file mode 100644
index 0000000000..e193ce83ff
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_resampler.cpp
@@ -0,0 +1,852 @@
+// basisu_resampler.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_resampler.h"
+#include "basisu_resampler_filters.h"
+
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define RESAMPLER_DEBUG 0
+
+namespace basisu
+{
+ static inline int resampler_range_check(int v, int h)
+ {
+ BASISU_NOTE_UNUSED(h);
+ assert((v >= 0) && (v < h));
+ return v;
+ }
+
+ // Float to int cast with truncation.
+ static inline int cast_to_int(Resample_Real i)
+ {
+ return (int)i;
+ }
+
+ // Ensure that the contributing source sample is within bounds. If not, reflect, clamp, or wrap.
+ int Resampler::reflect(const int j, const int src_x, const Boundary_Op boundary_op)
+ {
+ int n;
+
+ if (j < 0)
+ {
+ if (boundary_op == BOUNDARY_REFLECT)
+ {
+ n = -j;
+
+ if (n >= src_x)
+ n = src_x - 1;
+ }
+ else if (boundary_op == BOUNDARY_WRAP)
+ n = posmod(j, src_x);
+ else
+ n = 0;
+ }
+ else if (j >= src_x)
+ {
+ if (boundary_op == BOUNDARY_REFLECT)
+ {
+ n = (src_x - j) + (src_x - 1);
+
+ if (n < 0)
+ n = 0;
+ }
+ else if (boundary_op == BOUNDARY_WRAP)
+ n = posmod(j, src_x);
+ else
+ n = src_x - 1;
+ }
+ else
+ n = j;
+
+ return n;
+ }
+
+ // The make_clist() method generates, for all destination samples,
+ // the list of all source samples with non-zero weighted contributions.
+ Resampler::Contrib_List * Resampler::make_clist(
+ int src_x, int dst_x, Boundary_Op boundary_op,
+ Resample_Real(*Pfilter)(Resample_Real),
+ Resample_Real filter_support,
+ Resample_Real filter_scale,
+ Resample_Real src_ofs)
+ {
+ struct Contrib_Bounds
+ {
+ // The center of the range in DISCRETE coordinates (pixel center = 0.0f).
+ Resample_Real center;
+ int left, right;
+ };
+
+ int i, j, k, n, left, right;
+ Resample_Real total_weight;
+ Resample_Real xscale, center, half_width, weight;
+ Contrib_List* Pcontrib;
+ Contrib* Pcpool;
+ Contrib* Pcpool_next;
+ Contrib_Bounds* Pcontrib_bounds;
+
+ if ((Pcontrib = (Contrib_List*)calloc(dst_x, sizeof(Contrib_List))) == NULL)
+ return NULL;
+
+ Pcontrib_bounds = (Contrib_Bounds*)calloc(dst_x, sizeof(Contrib_Bounds));
+ if (!Pcontrib_bounds)
+ {
+ free(Pcontrib);
+ return (NULL);
+ }
+
+ const Resample_Real oo_filter_scale = 1.0f / filter_scale;
+
+ const Resample_Real NUDGE = 0.5f;
+ xscale = dst_x / (Resample_Real)src_x;
+
+ if (xscale < 1.0f)
+ {
+ int total;
+ (void)total;
+
+ // Handle case when there are fewer destination samples than source samples (downsampling/minification).
+
+ // stretched half width of filter
+ half_width = (filter_support / xscale) * filter_scale;
+
+ // Find the range of source sample(s) that will contribute to each destination sample.
+
+ for (i = 0, n = 0; i < dst_x; i++)
+ {
+ // Convert from discrete to continuous coordinates, scale, then convert back to discrete.
+ center = ((Resample_Real)i + NUDGE) / xscale;
+ center -= NUDGE;
+ center += src_ofs;
+
+ left = cast_to_int((Resample_Real)floor(center - half_width));
+ right = cast_to_int((Resample_Real)ceil(center + half_width));
+
+ Pcontrib_bounds[i].center = center;
+ Pcontrib_bounds[i].left = left;
+ Pcontrib_bounds[i].right = right;
+
+ n += (right - left + 1);
+ }
+
+ // Allocate memory for contributors.
+
+ if ((n == 0) || ((Pcpool = (Contrib*)calloc(n, sizeof(Contrib))) == NULL))
+ {
+ free(Pcontrib);
+ free(Pcontrib_bounds);
+ return NULL;
+ }
+ total = n;
+
+ Pcpool_next = Pcpool;
+
+ // Create the list of source samples which contribute to each destination sample.
+
+ for (i = 0; i < dst_x; i++)
+ {
+ int max_k = -1;
+ Resample_Real max_w = -1e+20f;
+
+ center = Pcontrib_bounds[i].center;
+ left = Pcontrib_bounds[i].left;
+ right = Pcontrib_bounds[i].right;
+
+ Pcontrib[i].n = 0;
+ Pcontrib[i].p = Pcpool_next;
+ Pcpool_next += (right - left + 1);
+ assert((Pcpool_next - Pcpool) <= total);
+
+ total_weight = 0;
+
+ for (j = left; j <= right; j++)
+ total_weight += (*Pfilter)((center - (Resample_Real)j) * xscale * oo_filter_scale);
+ const Resample_Real norm = static_cast<Resample_Real>(1.0f / total_weight);
+
+ total_weight = 0;
+
+#if RESAMPLER_DEBUG
+ printf("%i: ", i);
+#endif
+
+ for (j = left; j <= right; j++)
+ {
+ weight = (*Pfilter)((center - (Resample_Real)j) * xscale * oo_filter_scale) * norm;
+ if (weight == 0.0f)
+ continue;
+
+ n = reflect(j, src_x, boundary_op);
+
+#if RESAMPLER_DEBUG
+ printf("%i(%f), ", n, weight);
+#endif
+
+ // Increment the number of source samples which contribute to the current destination sample.
+
+ k = Pcontrib[i].n++;
+
+ Pcontrib[i].p[k].pixel = (unsigned short)n; /* store src sample number */
+ Pcontrib[i].p[k].weight = weight; /* store src sample weight */
+
+ total_weight += weight; /* total weight of all contributors */
+
+ if (weight > max_w)
+ {
+ max_w = weight;
+ max_k = k;
+ }
+ }
+
+#if RESAMPLER_DEBUG
+ printf("\n\n");
+#endif
+
+ //assert(Pcontrib[i].n);
+ //assert(max_k != -1);
+ if ((max_k == -1) || (Pcontrib[i].n == 0))
+ {
+ free(Pcpool);
+ free(Pcontrib);
+ free(Pcontrib_bounds);
+ return NULL;
+ }
+
+ if (total_weight != 1.0f)
+ Pcontrib[i].p[max_k].weight += 1.0f - total_weight;
+ }
+ }
+ else
+ {
+ // Handle case when there are more destination samples than source samples (upsampling).
+
+ half_width = filter_support * filter_scale;
+
+ // Find the source sample(s) that contribute to each destination sample.
+
+ for (i = 0, n = 0; i < dst_x; i++)
+ {
+ // Convert from discrete to continuous coordinates, scale, then convert back to discrete.
+ center = ((Resample_Real)i + NUDGE) / xscale;
+ center -= NUDGE;
+ center += src_ofs;
+
+ left = cast_to_int((Resample_Real)floor(center - half_width));
+ right = cast_to_int((Resample_Real)ceil(center + half_width));
+
+ Pcontrib_bounds[i].center = center;
+ Pcontrib_bounds[i].left = left;
+ Pcontrib_bounds[i].right = right;
+
+ n += (right - left + 1);
+ }
+
+ /* Allocate memory for contributors. */
+
+ int total = n;
+ if ((total == 0) || ((Pcpool = (Contrib*)calloc(total, sizeof(Contrib))) == NULL))
+ {
+ free(Pcontrib);
+ free(Pcontrib_bounds);
+ return NULL;
+ }
+
+ Pcpool_next = Pcpool;
+
+ // Create the list of source samples which contribute to each destination sample.
+
+ for (i = 0; i < dst_x; i++)
+ {
+ int max_k = -1;
+ Resample_Real max_w = -1e+20f;
+
+ center = Pcontrib_bounds[i].center;
+ left = Pcontrib_bounds[i].left;
+ right = Pcontrib_bounds[i].right;
+
+ Pcontrib[i].n = 0;
+ Pcontrib[i].p = Pcpool_next;
+ Pcpool_next += (right - left + 1);
+ assert((Pcpool_next - Pcpool) <= total);
+
+ total_weight = 0;
+ for (j = left; j <= right; j++)
+ total_weight += (*Pfilter)((center - (Resample_Real)j) * oo_filter_scale);
+
+ const Resample_Real norm = static_cast<Resample_Real>(1.0f / total_weight);
+
+ total_weight = 0;
+
+#if RESAMPLER_DEBUG
+ printf("%i: ", i);
+#endif
+
+ for (j = left; j <= right; j++)
+ {
+ weight = (*Pfilter)((center - (Resample_Real)j) * oo_filter_scale) * norm;
+ if (weight == 0.0f)
+ continue;
+
+ n = reflect(j, src_x, boundary_op);
+
+#if RESAMPLER_DEBUG
+ printf("%i(%f), ", n, weight);
+#endif
+
+ // Increment the number of source samples which contribute to the current destination sample.
+
+ k = Pcontrib[i].n++;
+
+ Pcontrib[i].p[k].pixel = (unsigned short)n; /* store src sample number */
+ Pcontrib[i].p[k].weight = weight; /* store src sample weight */
+
+ total_weight += weight; /* total weight of all contributors */
+
+ if (weight > max_w)
+ {
+ max_w = weight;
+ max_k = k;
+ }
+ }
+
+#if RESAMPLER_DEBUG
+ printf("\n\n");
+#endif
+
+ //assert(Pcontrib[i].n);
+ //assert(max_k != -1);
+
+ if ((max_k == -1) || (Pcontrib[i].n == 0))
+ {
+ free(Pcpool);
+ free(Pcontrib);
+ free(Pcontrib_bounds);
+ return NULL;
+ }
+
+ if (total_weight != 1.0f)
+ Pcontrib[i].p[max_k].weight += 1.0f - total_weight;
+ }
+ }
+
+#if RESAMPLER_DEBUG
+ printf("*******\n");
+#endif
+
+ free(Pcontrib_bounds);
+
+ return Pcontrib;
+ }
+
+ void Resampler::resample_x(Sample * Pdst, const Sample * Psrc)
+ {
+ assert(Pdst);
+ assert(Psrc);
+
+ int i, j;
+ Sample total;
+ Contrib_List* Pclist = m_Pclist_x;
+ Contrib* p;
+
+ for (i = m_resample_dst_x; i > 0; i--, Pclist++)
+ {
+#if BASISU_RESAMPLER_DEBUG_OPS
+ total_ops += Pclist->n;
+#endif
+
+ for (j = Pclist->n, p = Pclist->p, total = 0; j > 0; j--, p++)
+ total += Psrc[p->pixel] * p->weight;
+
+ *Pdst++ = total;
+ }
+ }
+
+ void Resampler::scale_y_mov(Sample * Ptmp, const Sample * Psrc, Resample_Real weight, int dst_x)
+ {
+ int i;
+
+#if BASISU_RESAMPLER_DEBUG_OPS
+ total_ops += dst_x;
+#endif
+
+ // Not += because temp buf wasn't cleared.
+ for (i = dst_x; i > 0; i--)
+ * Ptmp++ = *Psrc++ * weight;
+ }
+
+ void Resampler::scale_y_add(Sample * Ptmp, const Sample * Psrc, Resample_Real weight, int dst_x)
+ {
+#if BASISU_RESAMPLER_DEBUG_OPS
+ total_ops += dst_x;
+#endif
+
+ for (int i = dst_x; i > 0; i--)
+ (*Ptmp++) += *Psrc++ * weight;
+ }
+
+ void Resampler::clamp(Sample * Pdst, int n)
+ {
+ while (n > 0)
+ {
+ Sample x = *Pdst;
+ *Pdst++ = clamp_sample(x);
+ n--;
+ }
+ }
+
+ void Resampler::resample_y(Sample * Pdst)
+ {
+ int i, j;
+ Sample* Psrc;
+ Contrib_List* Pclist = &m_Pclist_y[m_cur_dst_y];
+
+ Sample* Ptmp = m_delay_x_resample ? m_Ptmp_buf : Pdst;
+ assert(Ptmp);
+
+ /* Process each contributor. */
+
+ for (i = 0; i < Pclist->n; i++)
+ {
+ // locate the contributor's location in the scan buffer -- the contributor must always be found!
+ for (j = 0; j < MAX_SCAN_BUF_SIZE; j++)
+ if (m_Pscan_buf->scan_buf_y[j] == Pclist->p[i].pixel)
+ break;
+
+ assert(j < MAX_SCAN_BUF_SIZE);
+
+ Psrc = m_Pscan_buf->scan_buf_l[j];
+
+ if (!i)
+ scale_y_mov(Ptmp, Psrc, Pclist->p[i].weight, m_intermediate_x);
+ else
+ scale_y_add(Ptmp, Psrc, Pclist->p[i].weight, m_intermediate_x);
+
+ /* If this source line doesn't contribute to any
+ * more destination lines then mark the scanline buffer slot
+ * which holds this source line as free.
+ * (The max. number of slots used depends on the Y
+ * axis sampling factor and the scaled filter width.)
+ */
+
+ if (--m_Psrc_y_count[resampler_range_check(Pclist->p[i].pixel, m_resample_src_y)] == 0)
+ {
+ m_Psrc_y_flag[resampler_range_check(Pclist->p[i].pixel, m_resample_src_y)] = false;
+ m_Pscan_buf->scan_buf_y[j] = -1;
+ }
+ }
+
+ /* Now generate the destination line */
+
+ if (m_delay_x_resample) // Was X resampling delayed until after Y resampling?
+ {
+ assert(Pdst != Ptmp);
+ resample_x(Pdst, Ptmp);
+ }
+ else
+ {
+ assert(Pdst == Ptmp);
+ }
+
+ if (m_lo < m_hi)
+ clamp(Pdst, m_resample_dst_x);
+ }
+
+ bool Resampler::put_line(const Sample * Psrc)
+ {
+ int i;
+
+ if (m_cur_src_y >= m_resample_src_y)
+ return false;
+
+ /* Does this source line contribute
+ * to any destination line? if not,
+ * exit now.
+ */
+
+ if (!m_Psrc_y_count[resampler_range_check(m_cur_src_y, m_resample_src_y)])
+ {
+ m_cur_src_y++;
+ return true;
+ }
+
+ /* Find an empty slot in the scanline buffer. (FIXME: Perf. is terrible here with extreme scaling ratios.) */
+
+ for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
+ if (m_Pscan_buf->scan_buf_y[i] == -1)
+ break;
+
+ /* If the buffer is full, exit with an error. */
+
+ if (i == MAX_SCAN_BUF_SIZE)
+ {
+ m_status = STATUS_SCAN_BUFFER_FULL;
+ return false;
+ }
+
+ m_Psrc_y_flag[resampler_range_check(m_cur_src_y, m_resample_src_y)] = true;
+ m_Pscan_buf->scan_buf_y[i] = m_cur_src_y;
+
+ /* Does this slot have any memory allocated to it? */
+
+ if (!m_Pscan_buf->scan_buf_l[i])
+ {
+ if ((m_Pscan_buf->scan_buf_l[i] = (Sample*)malloc(m_intermediate_x * sizeof(Sample))) == NULL)
+ {
+ m_status = STATUS_OUT_OF_MEMORY;
+ return false;
+ }
+ }
+
+ // Resampling on the X axis first?
+ if (m_delay_x_resample)
+ {
+ assert(m_intermediate_x == m_resample_src_x);
+
+ // Y-X resampling order
+ memcpy(m_Pscan_buf->scan_buf_l[i], Psrc, m_intermediate_x * sizeof(Sample));
+ }
+ else
+ {
+ assert(m_intermediate_x == m_resample_dst_x);
+
+ // X-Y resampling order
+ resample_x(m_Pscan_buf->scan_buf_l[i], Psrc);
+ }
+
+ m_cur_src_y++;
+
+ return true;
+ }
+
+ const Resampler::Sample* Resampler::get_line()
+ {
+ int i;
+
+ /* If all the destination lines have been
+ * generated, then always return NULL.
+ */
+
+ if (m_cur_dst_y == m_resample_dst_y)
+ return NULL;
+
+ /* Check to see if all the required
+ * contributors are present, if not,
+ * return NULL.
+ */
+
+ for (i = 0; i < m_Pclist_y[m_cur_dst_y].n; i++)
+ if (!m_Psrc_y_flag[resampler_range_check(m_Pclist_y[m_cur_dst_y].p[i].pixel, m_resample_src_y)])
+ return NULL;
+
+ resample_y(m_Pdst_buf);
+
+ m_cur_dst_y++;
+
+ return m_Pdst_buf;
+ }
+
+ Resampler::~Resampler()
+ {
+ int i;
+
+#if BASISU_RESAMPLER_DEBUG_OPS
+ printf("actual ops: %i\n", total_ops);
+#endif
+
+ free(m_Pdst_buf);
+ m_Pdst_buf = NULL;
+
+ if (m_Ptmp_buf)
+ {
+ free(m_Ptmp_buf);
+ m_Ptmp_buf = NULL;
+ }
+
+ /* Don't deallocate a contibutor list
+ * if the user passed us one of their own.
+ */
+
+ if ((m_Pclist_x) && (!m_clist_x_forced))
+ {
+ free(m_Pclist_x->p);
+ free(m_Pclist_x);
+ m_Pclist_x = NULL;
+ }
+
+ if ((m_Pclist_y) && (!m_clist_y_forced))
+ {
+ free(m_Pclist_y->p);
+ free(m_Pclist_y);
+ m_Pclist_y = NULL;
+ }
+
+ free(m_Psrc_y_count);
+ m_Psrc_y_count = NULL;
+
+ free(m_Psrc_y_flag);
+ m_Psrc_y_flag = NULL;
+
+ if (m_Pscan_buf)
+ {
+ for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
+ free(m_Pscan_buf->scan_buf_l[i]);
+
+ free(m_Pscan_buf);
+ m_Pscan_buf = NULL;
+ }
+ }
+
+ void Resampler::restart()
+ {
+ if (STATUS_OKAY != m_status)
+ return;
+
+ m_cur_src_y = m_cur_dst_y = 0;
+
+ int i, j;
+ for (i = 0; i < m_resample_src_y; i++)
+ {
+ m_Psrc_y_count[i] = 0;
+ m_Psrc_y_flag[i] = false;
+ }
+
+ for (i = 0; i < m_resample_dst_y; i++)
+ {
+ for (j = 0; j < m_Pclist_y[i].n; j++)
+ m_Psrc_y_count[resampler_range_check(m_Pclist_y[i].p[j].pixel, m_resample_src_y)]++;
+ }
+
+ for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
+ {
+ m_Pscan_buf->scan_buf_y[i] = -1;
+
+ free(m_Pscan_buf->scan_buf_l[i]);
+ m_Pscan_buf->scan_buf_l[i] = NULL;
+ }
+ }
+
+ Resampler::Resampler(int src_x, int src_y,
+ int dst_x, int dst_y,
+ Boundary_Op boundary_op,
+ Resample_Real sample_low, Resample_Real sample_high,
+ const char* Pfilter_name,
+ Contrib_List * Pclist_x,
+ Contrib_List * Pclist_y,
+ Resample_Real filter_x_scale,
+ Resample_Real filter_y_scale,
+ Resample_Real src_x_ofs,
+ Resample_Real src_y_ofs)
+ {
+ int i, j;
+ Resample_Real support, (*func)(Resample_Real);
+
+ assert(src_x > 0);
+ assert(src_y > 0);
+ assert(dst_x > 0);
+ assert(dst_y > 0);
+
+#if BASISU_RESAMPLER_DEBUG_OPS
+ total_ops = 0;
+#endif
+
+ m_lo = sample_low;
+ m_hi = sample_high;
+
+ m_delay_x_resample = false;
+ m_intermediate_x = 0;
+ m_Pdst_buf = NULL;
+ m_Ptmp_buf = NULL;
+ m_clist_x_forced = false;
+ m_Pclist_x = NULL;
+ m_clist_y_forced = false;
+ m_Pclist_y = NULL;
+ m_Psrc_y_count = NULL;
+ m_Psrc_y_flag = NULL;
+ m_Pscan_buf = NULL;
+ m_status = STATUS_OKAY;
+
+ m_resample_src_x = src_x;
+ m_resample_src_y = src_y;
+ m_resample_dst_x = dst_x;
+ m_resample_dst_y = dst_y;
+
+ m_boundary_op = boundary_op;
+
+ if ((m_Pdst_buf = (Sample*)malloc(m_resample_dst_x * sizeof(Sample))) == NULL)
+ {
+ m_status = STATUS_OUT_OF_MEMORY;
+ return;
+ }
+
+ // Find the specified filter.
+
+ if (Pfilter_name == NULL)
+ Pfilter_name = BASISU_RESAMPLER_DEFAULT_FILTER;
+
+ for (i = 0; i < g_num_resample_filters; i++)
+ if (strcmp(Pfilter_name, g_resample_filters[i].name) == 0)
+ break;
+
+ if (i == g_num_resample_filters)
+ {
+ m_status = STATUS_BAD_FILTER_NAME;
+ return;
+ }
+
+ func = g_resample_filters[i].func;
+ support = g_resample_filters[i].support;
+
+ /* Create contributor lists, unless the user supplied custom lists. */
+
+ if (!Pclist_x)
+ {
+ m_Pclist_x = make_clist(m_resample_src_x, m_resample_dst_x, m_boundary_op, func, support, filter_x_scale, src_x_ofs);
+ if (!m_Pclist_x)
+ {
+ m_status = STATUS_OUT_OF_MEMORY;
+ return;
+ }
+ }
+ else
+ {
+ m_Pclist_x = Pclist_x;
+ m_clist_x_forced = true;
+ }
+
+ if (!Pclist_y)
+ {
+ m_Pclist_y = make_clist(m_resample_src_y, m_resample_dst_y, m_boundary_op, func, support, filter_y_scale, src_y_ofs);
+ if (!m_Pclist_y)
+ {
+ m_status = STATUS_OUT_OF_MEMORY;
+ return;
+ }
+ }
+ else
+ {
+ m_Pclist_y = Pclist_y;
+ m_clist_y_forced = true;
+ }
+
+ if ((m_Psrc_y_count = (int*)calloc(m_resample_src_y, sizeof(int))) == NULL)
+ {
+ m_status = STATUS_OUT_OF_MEMORY;
+ return;
+ }
+
+ if ((m_Psrc_y_flag = (unsigned char*)calloc(m_resample_src_y, sizeof(unsigned char))) == NULL)
+ {
+ m_status = STATUS_OUT_OF_MEMORY;
+ return;
+ }
+
+ // Count how many times each source line contributes to a destination line.
+
+ for (i = 0; i < m_resample_dst_y; i++)
+ for (j = 0; j < m_Pclist_y[i].n; j++)
+ m_Psrc_y_count[resampler_range_check(m_Pclist_y[i].p[j].pixel, m_resample_src_y)]++;
+
+ if ((m_Pscan_buf = (Scan_Buf*)malloc(sizeof(Scan_Buf))) == NULL)
+ {
+ m_status = STATUS_OUT_OF_MEMORY;
+ return;
+ }
+
+ for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
+ {
+ m_Pscan_buf->scan_buf_y[i] = -1;
+ m_Pscan_buf->scan_buf_l[i] = NULL;
+ }
+
+ m_cur_src_y = m_cur_dst_y = 0;
+ {
+ // Determine which axis to resample first by comparing the number of multiplies required
+ // for each possibility.
+ int x_ops = count_ops(m_Pclist_x, m_resample_dst_x);
+ int y_ops = count_ops(m_Pclist_y, m_resample_dst_y);
+
+ // Hack 10/2000: Weight Y axis ops a little more than X axis ops.
+ // (Y axis ops use more cache resources.)
+ int xy_ops = x_ops * m_resample_src_y +
+ (4 * y_ops * m_resample_dst_x) / 3;
+
+ int yx_ops = (4 * y_ops * m_resample_src_x) / 3 +
+ x_ops * m_resample_dst_y;
+
+#if BASISU_RESAMPLER_DEBUG_OPS
+ printf("src: %i %i\n", m_resample_src_x, m_resample_src_y);
+ printf("dst: %i %i\n", m_resample_dst_x, m_resample_dst_y);
+ printf("x_ops: %i\n", x_ops);
+ printf("y_ops: %i\n", y_ops);
+ printf("xy_ops: %i\n", xy_ops);
+ printf("yx_ops: %i\n", yx_ops);
+#endif
+
+ // Now check which resample order is better. In case of a tie, choose the order
+ // which buffers the least amount of data.
+ if ((xy_ops > yx_ops) ||
+ ((xy_ops == yx_ops) && (m_resample_src_x < m_resample_dst_x)))
+ {
+ m_delay_x_resample = true;
+ m_intermediate_x = m_resample_src_x;
+ }
+ else
+ {
+ m_delay_x_resample = false;
+ m_intermediate_x = m_resample_dst_x;
+ }
+#if BASISU_RESAMPLER_DEBUG_OPS
+ printf("delaying: %i\n", m_delay_x_resample);
+#endif
+ }
+
+ if (m_delay_x_resample)
+ {
+ if ((m_Ptmp_buf = (Sample*)malloc(m_intermediate_x * sizeof(Sample))) == NULL)
+ {
+ m_status = STATUS_OUT_OF_MEMORY;
+ return;
+ }
+ }
+ }
+
+ void Resampler::get_clists(Contrib_List * *ptr_clist_x, Contrib_List * *ptr_clist_y)
+ {
+ if (ptr_clist_x)
+ * ptr_clist_x = m_Pclist_x;
+
+ if (ptr_clist_y)
+ * ptr_clist_y = m_Pclist_y;
+ }
+
+ int Resampler::get_filter_num()
+ {
+ return g_num_resample_filters;
+ }
+
+ const char* Resampler::get_filter_name(int filter_num)
+ {
+ if ((filter_num < 0) || (filter_num >= g_num_resample_filters))
+ return NULL;
+ else
+ return g_resample_filters[filter_num].name;
+ }
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_resampler.h b/thirdparty/basis_universal/basisu_resampler.h
new file mode 100644
index 0000000000..c3f2e05c25
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_resampler.h
@@ -0,0 +1,196 @@
+// basisu_resampler.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "transcoder/basisu.h"
+
+#define BASISU_RESAMPLER_DEBUG_OPS (0)
+#define BASISU_RESAMPLER_DEFAULT_FILTER "lanczos4"
+#define BASISU_RESAMPLER_MAX_DIMENSION (16384)
+
+namespace basisu
+{
+ // float or double
+ typedef float Resample_Real;
+
+ class Resampler
+ {
+ public:
+ typedef Resample_Real Sample;
+
+ struct Contrib
+ {
+ Resample_Real weight;
+ uint16_t pixel;
+ };
+
+ struct Contrib_List
+ {
+ uint16_t n;
+ Contrib *p;
+ };
+
+ enum Boundary_Op
+ {
+ BOUNDARY_WRAP = 0,
+ BOUNDARY_REFLECT = 1,
+ BOUNDARY_CLAMP = 2
+ };
+
+ enum Status
+ {
+ STATUS_OKAY = 0,
+ STATUS_OUT_OF_MEMORY = 1,
+ STATUS_BAD_FILTER_NAME = 2,
+ STATUS_SCAN_BUFFER_FULL = 3
+ };
+
+ // src_x/src_y - Input dimensions
+ // dst_x/dst_y - Output dimensions
+ // boundary_op - How to sample pixels near the image boundaries
+ // sample_low/sample_high - Clamp output samples to specified range, or disable clamping if sample_low >= sample_high
+ // Pclist_x/Pclist_y - Optional pointers to contributor lists from another instance of a Resampler
+ // src_x_ofs/src_y_ofs - Offset input image by specified amount (fractional values okay)
+ Resampler(
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ Boundary_Op boundary_op = BOUNDARY_CLAMP,
+ Resample_Real sample_low = 0.0f, Resample_Real sample_high = 0.0f,
+ const char *Pfilter_name = BASISU_RESAMPLER_DEFAULT_FILTER,
+ Contrib_List *Pclist_x = NULL,
+ Contrib_List *Pclist_y = NULL,
+ Resample_Real filter_x_scale = 1.0f,
+ Resample_Real filter_y_scale = 1.0f,
+ Resample_Real src_x_ofs = 0.0f,
+ Resample_Real src_y_ofs = 0.0f);
+
+ ~Resampler();
+
+ // Reinits resampler so it can handle another frame.
+ void restart();
+
+ // false on out of memory.
+ bool put_line(const Sample *Psrc);
+
+ // NULL if no scanlines are currently available (give the resampler more scanlines!)
+ const Sample *get_line();
+
+ Status status() const
+ {
+ return m_status;
+ }
+
+ // Returned contributor lists can be shared with another Resampler.
+ void get_clists(Contrib_List **ptr_clist_x, Contrib_List **ptr_clist_y);
+ Contrib_List *get_clist_x() const
+ {
+ return m_Pclist_x;
+ }
+ Contrib_List *get_clist_y() const
+ {
+ return m_Pclist_y;
+ }
+
+ // Filter accessors.
+ static int get_filter_num();
+ static const char *get_filter_name(int filter_num);
+
+ static Contrib_List *make_clist(
+ int src_x, int dst_x, Boundary_Op boundary_op,
+ Resample_Real(*Pfilter)(Resample_Real),
+ Resample_Real filter_support,
+ Resample_Real filter_scale,
+ Resample_Real src_ofs);
+
+ private:
+ Resampler();
+ Resampler(const Resampler &o);
+ Resampler &operator=(const Resampler &o);
+
+#ifdef BASISU_RESAMPLER_DEBUG_OPS
+ int total_ops;
+#endif
+
+ int m_intermediate_x;
+
+ int m_resample_src_x;
+ int m_resample_src_y;
+ int m_resample_dst_x;
+ int m_resample_dst_y;
+
+ Boundary_Op m_boundary_op;
+
+ Sample *m_Pdst_buf;
+ Sample *m_Ptmp_buf;
+
+ Contrib_List *m_Pclist_x;
+ Contrib_List *m_Pclist_y;
+
+ bool m_clist_x_forced;
+ bool m_clist_y_forced;
+
+ bool m_delay_x_resample;
+
+ int *m_Psrc_y_count;
+ uint8_t *m_Psrc_y_flag;
+
+ // The maximum number of scanlines that can be buffered at one time.
+ enum
+ {
+ MAX_SCAN_BUF_SIZE = BASISU_RESAMPLER_MAX_DIMENSION
+ };
+
+ struct Scan_Buf
+ {
+ int scan_buf_y[MAX_SCAN_BUF_SIZE];
+ Sample *scan_buf_l[MAX_SCAN_BUF_SIZE];
+ };
+
+ Scan_Buf *m_Pscan_buf;
+
+ int m_cur_src_y;
+ int m_cur_dst_y;
+
+ Status m_status;
+
+ void resample_x(Sample *Pdst, const Sample *Psrc);
+ void scale_y_mov(Sample *Ptmp, const Sample *Psrc, Resample_Real weight, int dst_x);
+ void scale_y_add(Sample *Ptmp, const Sample *Psrc, Resample_Real weight, int dst_x);
+ void clamp(Sample *Pdst, int n);
+ void resample_y(Sample *Pdst);
+
+ static int reflect(const int j, const int src_x, const Boundary_Op boundary_op);
+
+ inline int count_ops(Contrib_List *Pclist, int k)
+ {
+ int i, t = 0;
+ for (i = 0; i < k; i++)
+ t += Pclist[i].n;
+ return (t);
+ }
+
+ Resample_Real m_lo;
+ Resample_Real m_hi;
+
+ inline Resample_Real clamp_sample(Resample_Real f) const
+ {
+ if (f < m_lo)
+ f = m_lo;
+ else if (f > m_hi)
+ f = m_hi;
+ return f;
+ }
+ };
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_resampler_filters.h b/thirdparty/basis_universal/basisu_resampler_filters.h
new file mode 100644
index 0000000000..5659c5fe86
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_resampler_filters.h
@@ -0,0 +1,35 @@
+// basisu_resampler_filters.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include "transcoder/basisu.h"
+
+namespace basisu
+{
+ typedef float (*resample_filter_func)(float t);
+
+ struct resample_filter
+ {
+ const char *name;
+ resample_filter_func func;
+ float support;
+ };
+
+ extern const resample_filter g_resample_filters[];
+ extern const int g_num_resample_filters;
+
+ int find_resample_filter(const char *pName);
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_ssim.cpp b/thirdparty/basis_universal/basisu_ssim.cpp
new file mode 100644
index 0000000000..cceb400b88
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_ssim.cpp
@@ -0,0 +1,408 @@
+// basisu_ssim.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_ssim.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+namespace basisu
+{
+ float gauss(int x, int y, float sigma_sqr)
+ {
+ float pow = expf(-((x * x + y * y) / (2.0f * sigma_sqr)));
+ float g = (1.0f / (sqrtf((float)(2.0f * M_PI * sigma_sqr)))) * pow;
+ return g;
+ }
+
+ // size_x/y should be odd
+ void compute_gaussian_kernel(float *pDst, int size_x, int size_y, float sigma_sqr, uint32_t flags)
+ {
+ assert(size_x & size_y & 1);
+
+ if (!(size_x | size_y))
+ return;
+
+ int mid_x = size_x / 2;
+ int mid_y = size_y / 2;
+
+ double sum = 0;
+ for (int x = 0; x < size_x; x++)
+ {
+ for (int y = 0; y < size_y; y++)
+ {
+ float g;
+ if ((x > mid_x) && (y < mid_y))
+ g = pDst[(size_x - x - 1) + y * size_x];
+ else if ((x < mid_x) && (y > mid_y))
+ g = pDst[x + (size_y - y - 1) * size_x];
+ else if ((x > mid_x) && (y > mid_y))
+ g = pDst[(size_x - x - 1) + (size_y - y - 1) * size_x];
+ else
+ g = gauss(x - mid_x, y - mid_y, sigma_sqr);
+
+ pDst[x + y * size_x] = g;
+ sum += g;
+ }
+ }
+
+ if (flags & cComputeGaussianFlagNormalizeCenterToOne)
+ {
+ sum = pDst[mid_x + mid_y * size_x];
+ }
+
+ if (flags & (cComputeGaussianFlagNormalizeCenterToOne | cComputeGaussianFlagNormalize))
+ {
+ double one_over_sum = 1.0f / sum;
+ for (int i = 0; i < size_x * size_y; i++)
+ pDst[i] = static_cast<float>(pDst[i] * one_over_sum);
+
+ if (flags & cComputeGaussianFlagNormalizeCenterToOne)
+ pDst[mid_x + mid_y * size_x] = 1.0f;
+ }
+
+ if (flags & cComputeGaussianFlagPrint)
+ {
+ printf("{\n");
+ for (int y = 0; y < size_y; y++)
+ {
+ printf(" ");
+ for (int x = 0; x < size_x; x++)
+ {
+ printf("%f, ", pDst[x + y * size_x]);
+ }
+ printf("\n");
+ }
+ printf("}");
+ }
+ }
+
+ void gaussian_filter(imagef &dst, const imagef &orig_img, uint32_t odd_filter_width, float sigma_sqr, bool wrapping, uint32_t width_divisor, uint32_t height_divisor)
+ {
+ assert(odd_filter_width && (odd_filter_width & 1));
+ odd_filter_width |= 1;
+
+ vector2D<float> kernel(odd_filter_width, odd_filter_width);
+ compute_gaussian_kernel(kernel.get_ptr(), odd_filter_width, odd_filter_width, sigma_sqr, cComputeGaussianFlagNormalize);
+
+ const int dst_width = orig_img.get_width() / width_divisor;
+ const int dst_height = orig_img.get_height() / height_divisor;
+
+ const int H = odd_filter_width / 2;
+ const int L = -H;
+
+ dst.crop(dst_width, dst_height);
+
+//#pragma omp parallel for
+ for (int oy = 0; oy < dst_height; oy++)
+ {
+ for (int ox = 0; ox < dst_width; ox++)
+ {
+ vec4F c(0.0f);
+
+ for (int yd = L; yd <= H; yd++)
+ {
+ int y = oy * height_divisor + (height_divisor >> 1) + yd;
+
+ for (int xd = L; xd <= H; xd++)
+ {
+ int x = ox * width_divisor + (width_divisor >> 1) + xd;
+
+ const vec4F &p = orig_img.get_clamped_or_wrapped(x, y, wrapping, wrapping);
+
+ float w = kernel(xd + H, yd + H);
+ c[0] += p[0] * w;
+ c[1] += p[1] * w;
+ c[2] += p[2] * w;
+ c[3] += p[3] * w;
+ }
+ }
+
+ dst(ox, oy).set(c[0], c[1], c[2], c[3]);
+ }
+ }
+ }
+
+ void pow_image(const imagef &src, imagef &dst, const vec4F &power)
+ {
+ dst.resize(src);
+
+//#pragma omp parallel for
+ for (int y = 0; y < (int)dst.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < dst.get_width(); x++)
+ {
+ const vec4F &p = src(x, y);
+
+ if ((power[0] == 2.0f) && (power[1] == 2.0f) && (power[2] == 2.0f) && (power[3] == 2.0f))
+ dst(x, y).set(p[0] * p[0], p[1] * p[1], p[2] * p[2], p[3] * p[3]);
+ else
+ dst(x, y).set(powf(p[0], power[0]), powf(p[1], power[1]), powf(p[2], power[2]), powf(p[3], power[3]));
+ }
+ }
+ }
+
+ void mul_image(const imagef &src, imagef &dst, const vec4F &mul)
+ {
+ dst.resize(src);
+
+//#pragma omp parallel for
+ for (int y = 0; y < (int)dst.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < dst.get_width(); x++)
+ {
+ const vec4F &p = src(x, y);
+ dst(x, y).set(p[0] * mul[0], p[1] * mul[1], p[2] * mul[2], p[3] * mul[3]);
+ }
+ }
+ }
+
+ void scale_image(const imagef &src, imagef &dst, const vec4F &scale, const vec4F &shift)
+ {
+ dst.resize(src);
+
+//#pragma omp parallel for
+ for (int y = 0; y < (int)dst.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < dst.get_width(); x++)
+ {
+ const vec4F &p = src(x, y);
+
+ vec4F d;
+
+ for (uint32_t c = 0; c < 4; c++)
+ d[c] = scale[c] * p[c] + shift[c];
+
+ dst(x, y).set(d[0], d[1], d[2], d[3]);
+ }
+ }
+ }
+
+ void add_weighted_image(const imagef &src1, const vec4F &alpha, const imagef &src2, const vec4F &beta, const vec4F &gamma, imagef &dst)
+ {
+ dst.resize(src1);
+
+//#pragma omp parallel for
+ for (int y = 0; y < (int)dst.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < dst.get_width(); x++)
+ {
+ const vec4F &s1 = src1(x, y);
+ const vec4F &s2 = src2(x, y);
+
+ dst(x, y).set(
+ s1[0] * alpha[0] + s2[0] * beta[0] + gamma[0],
+ s1[1] * alpha[1] + s2[1] * beta[1] + gamma[1],
+ s1[2] * alpha[2] + s2[2] * beta[2] + gamma[2],
+ s1[3] * alpha[3] + s2[3] * beta[3] + gamma[3]);
+ }
+ }
+ }
+
+ void add_image(const imagef &src1, const imagef &src2, imagef &dst)
+ {
+ dst.resize(src1);
+
+//#pragma omp parallel for
+ for (int y = 0; y < (int)dst.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < dst.get_width(); x++)
+ {
+ const vec4F &s1 = src1(x, y);
+ const vec4F &s2 = src2(x, y);
+
+ dst(x, y).set(s1[0] + s2[0], s1[1] + s2[1], s1[2] + s2[2], s1[3] + s2[3]);
+ }
+ }
+ }
+
+ void adds_image(const imagef &src, const vec4F &value, imagef &dst)
+ {
+ dst.resize(src);
+
+//#pragma omp parallel for
+ for (int y = 0; y < (int)dst.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < dst.get_width(); x++)
+ {
+ const vec4F &p = src(x, y);
+
+ dst(x, y).set(p[0] + value[0], p[1] + value[1], p[2] + value[2], p[3] + value[3]);
+ }
+ }
+ }
+
+ void mul_image(const imagef &src1, const imagef &src2, imagef &dst, const vec4F &scale)
+ {
+ dst.resize(src1);
+
+//#pragma omp parallel for
+ for (int y = 0; y < (int)dst.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < dst.get_width(); x++)
+ {
+ const vec4F &s1 = src1(x, y);
+ const vec4F &s2 = src2(x, y);
+
+ vec4F d;
+
+ for (uint32_t c = 0; c < 4; c++)
+ {
+ float v1 = s1[c];
+ float v2 = s2[c];
+ d[c] = v1 * v2 * scale[c];
+ }
+
+ dst(x, y) = d;
+ }
+ }
+ }
+
+ void div_image(const imagef &src1, const imagef &src2, imagef &dst, const vec4F &scale)
+ {
+ dst.resize(src1);
+
+//#pragma omp parallel for
+ for (int y = 0; y < (int)dst.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < dst.get_width(); x++)
+ {
+ const vec4F &s1 = src1(x, y);
+ const vec4F &s2 = src2(x, y);
+
+ vec4F d;
+
+ for (uint32_t c = 0; c < 4; c++)
+ {
+ float v = s2[c];
+ if (v == 0.0f)
+ d[c] = 0.0f;
+ else
+ d[c] = (s1[c] * scale[c]) / v;
+ }
+
+ dst(x, y) = d;
+ }
+ }
+ }
+
+ vec4F avg_image(const imagef &src)
+ {
+ vec4F avg(0.0f);
+
+ for (uint32_t y = 0; y < src.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < src.get_width(); x++)
+ {
+ const vec4F &s = src(x, y);
+
+ avg += vec4F(s[0], s[1], s[2], s[3]);
+ }
+ }
+
+ avg /= static_cast<float>(src.get_total_pixels());
+
+ return avg;
+ }
+
+ // Reference: https://ece.uwaterloo.ca/~z70wang/research/ssim/index.html
+ vec4F compute_ssim(const imagef &a, const imagef &b)
+ {
+ imagef axb, a_sq, b_sq, mu1, mu2, mu1_sq, mu2_sq, mu1_mu2, s1_sq, s2_sq, s12, smap, t1, t2, t3;
+
+ const float C1 = 6.50250f, C2 = 58.52250f;
+
+ pow_image(a, a_sq, vec4F(2));
+ pow_image(b, b_sq, vec4F(2));
+ mul_image(a, b, axb, vec4F(1.0f));
+
+ gaussian_filter(mu1, a, 11, 1.5f * 1.5f);
+ gaussian_filter(mu2, b, 11, 1.5f * 1.5f);
+
+ pow_image(mu1, mu1_sq, vec4F(2));
+ pow_image(mu2, mu2_sq, vec4F(2));
+ mul_image(mu1, mu2, mu1_mu2, vec4F(1.0f));
+
+ gaussian_filter(s1_sq, a_sq, 11, 1.5f * 1.5f);
+ add_weighted_image(s1_sq, vec4F(1), mu1_sq, vec4F(-1), vec4F(0), s1_sq);
+
+ gaussian_filter(s2_sq, b_sq, 11, 1.5f * 1.5f);
+ add_weighted_image(s2_sq, vec4F(1), mu2_sq, vec4F(-1), vec4F(0), s2_sq);
+
+ gaussian_filter(s12, axb, 11, 1.5f * 1.5f);
+ add_weighted_image(s12, vec4F(1), mu1_mu2, vec4F(-1), vec4F(0), s12);
+
+ scale_image(mu1_mu2, t1, vec4F(2), vec4F(0));
+ adds_image(t1, vec4F(C1), t1);
+
+ scale_image(s12, t2, vec4F(2), vec4F(0));
+ adds_image(t2, vec4F(C2), t2);
+
+ mul_image(t1, t2, t3, vec4F(1));
+
+ add_image(mu1_sq, mu2_sq, t1);
+ adds_image(t1, vec4F(C1), t1);
+
+ add_image(s1_sq, s2_sq, t2);
+ adds_image(t2, vec4F(C2), t2);
+
+ mul_image(t1, t2, t1, vec4F(1));
+
+ div_image(t3, t1, smap, vec4F(1));
+
+ return avg_image(smap);
+ }
+
+ vec4F compute_ssim(const image &a, const image &b, bool luma, bool luma_601)
+ {
+ image ta(a), tb(b);
+
+ if ((ta.get_width() != tb.get_width()) || (ta.get_height() != tb.get_height()))
+ {
+ debug_printf("compute_ssim: Cropping input images to equal dimensions\n");
+
+ const uint32_t w = minimum(a.get_width(), b.get_width());
+ const uint32_t h = minimum(a.get_height(), b.get_height());
+ ta.crop(w, h);
+ tb.crop(w, h);
+ }
+
+ if (!ta.get_width() || !ta.get_height())
+ {
+ assert(0);
+ return vec4F(0);
+ }
+
+ if (luma)
+ {
+ for (uint32_t y = 0; y < ta.get_height(); y++)
+ {
+ for (uint32_t x = 0; x < ta.get_width(); x++)
+ {
+ ta(x, y).set(ta(x, y).get_luma(luma_601), ta(x, y).a);
+ tb(x, y).set(tb(x, y).get_luma(luma_601), tb(x, y).a);
+ }
+ }
+ }
+
+ imagef fta, ftb;
+
+ fta.set(ta);
+ ftb.set(tb);
+
+ return compute_ssim(fta, ftb);
+ }
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/basisu_ssim.h b/thirdparty/basis_universal/basisu_ssim.h
new file mode 100644
index 0000000000..986ca3bbdf
--- /dev/null
+++ b/thirdparty/basis_universal/basisu_ssim.h
@@ -0,0 +1,44 @@
+// basisu_ssim.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "basisu_enc.h"
+
+namespace basisu
+{
+ float gauss(int x, int y, float sigma_sqr);
+
+ enum
+ {
+ cComputeGaussianFlagNormalize = 1,
+ cComputeGaussianFlagPrint = 2,
+ cComputeGaussianFlagNormalizeCenterToOne = 4
+ };
+
+ void compute_gaussian_kernel(float *pDst, int size_x, int size_y, float sigma_sqr, uint32_t flags = 0);
+
+ void scale_image(const imagef &src, imagef &dst, const vec4F &scale, const vec4F &shift);
+ void add_weighted_image(const imagef &src1, const vec4F &alpha, const imagef &src2, const vec4F &beta, const vec4F &gamma, imagef &dst);
+ void add_image(const imagef &src1, const imagef &src2, imagef &dst);
+ void adds_image(const imagef &src, const vec4F &value, imagef &dst);
+ void mul_image(const imagef &src1, const imagef &src2, imagef &dst, const vec4F &scale);
+ void div_image(const imagef &src1, const imagef &src2, imagef &dst, const vec4F &scale);
+ vec4F avg_image(const imagef &src);
+
+ void gaussian_filter(imagef &dst, const imagef &orig_img, uint32_t odd_filter_width, float sigma_sqr, bool wrapping = false, uint32_t width_divisor = 1, uint32_t height_divisor = 1);
+
+ vec4F compute_ssim(const imagef &a, const imagef &b);
+ vec4F compute_ssim(const image &a, const image &b, bool luma, bool luma_601);
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/lodepng.cpp b/thirdparty/basis_universal/lodepng.cpp
new file mode 100644
index 0000000000..cf964d0555
--- /dev/null
+++ b/thirdparty/basis_universal/lodepng.cpp
@@ -0,0 +1,6006 @@
+/*
+LodePNG version 20190210
+
+Copyright (c) 2005-2019 Lode Vandevenne
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+*/
+
+/*
+The manual and changelog are in the header file "lodepng.h"
+Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C.
+*/
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4201)
+
+#ifndef BASISU_NO_ITERATOR_DEBUG_LEVEL
+#if defined(_DEBUG) || defined(DEBUG)
+#define _ITERATOR_DEBUG_LEVEL 1
+#define _SECURE_SCL 1
+#else
+#define _SECURE_SCL 0
+#define _ITERATOR_DEBUG_LEVEL 0
+#endif
+#endif
+#endif
+
+#include "lodepng.h"
+
+#include <limits.h> /* LONG_MAX */
+#include <stdio.h> /* file handling */
+#include <stdlib.h> /* allocations */
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/
+#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/
+#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
+#endif /*_MSC_VER */
+
+const char* LODEPNG_VERSION_STRING = "20190210";
+
+/*
+This source file is built up in the following large parts. The code sections
+with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way.
+-Tools for C and common code for PNG and Zlib
+-C Code for Zlib (huffman, deflate, ...)
+-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...)
+-The C++ wrapper around all of the above
+*/
+
+/*The malloc, realloc and free functions defined here with "lodepng_" in front
+of the name, so that you can easily change them to others related to your
+platform if needed. Everything else in the code calls these. Pass
+-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out
+#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and
+define them in your own project's source files without needing to change
+lodepng source code. Don't forget to remove "static" if you copypaste them
+from here.*/
+
+#ifdef LODEPNG_COMPILE_ALLOCATORS
+static void* lodepng_malloc(size_t size) {
+#ifdef LODEPNG_MAX_ALLOC
+ if(size > LODEPNG_MAX_ALLOC) return 0;
+#endif
+ return malloc(size);
+}
+
+static void* lodepng_realloc(void* ptr, size_t new_size) {
+#ifdef LODEPNG_MAX_ALLOC
+ if(new_size > LODEPNG_MAX_ALLOC) return 0;
+#endif
+ return realloc(ptr, new_size);
+}
+
+static void lodepng_free(void* ptr) {
+ free(ptr);
+}
+#else /*LODEPNG_COMPILE_ALLOCATORS*/
+void* lodepng_malloc(size_t size);
+void* lodepng_realloc(void* ptr, size_t new_size);
+void lodepng_free(void* ptr);
+#endif /*LODEPNG_COMPILE_ALLOCATORS*/
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* ////////////////////////////////////////////////////////////////////////// */
+/* // Tools for C, and common code for PNG and Zlib. // */
+/* ////////////////////////////////////////////////////////////////////////// */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+#define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/*
+Often in case of an error a value is assigned to a variable and then it breaks
+out of a loop (to go to the cleanup phase of a function). This macro does that.
+It makes the error handling code shorter and more readable.
+
+Example: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83);
+*/
+#define CERROR_BREAK(errorvar, code){\
+ errorvar = code;\
+ break;\
+}
+
+/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/
+#define ERROR_BREAK(code) CERROR_BREAK(error, code)
+
+/*Set error var to the error code, and return it.*/
+#define CERROR_RETURN_ERROR(errorvar, code){\
+ errorvar = code;\
+ return code;\
+}
+
+/*Try the code, if it returns error, also return the error.*/
+#define CERROR_TRY_RETURN(call){\
+ unsigned error = call;\
+ if(error) return error;\
+}
+
+/*Set error var to the error code, and return from the void function.*/
+#define CERROR_RETURN(errorvar, code){\
+ errorvar = code;\
+ return;\
+}
+
+/*
+About uivector, ucvector and string:
+-All of them wrap dynamic arrays or text strings in a similar way.
+-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version.
+-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated.
+-They're not used in the interface, only internally in this file as static functions.
+-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor.
+*/
+
+#ifdef LODEPNG_COMPILE_ZLIB
+/*dynamic vector of unsigned ints*/
+typedef struct uivector {
+ unsigned* data;
+ size_t size; /*size in number of unsigned longs*/
+ size_t allocsize; /*allocated size in bytes*/
+} uivector;
+
+static void uivector_cleanup(void* p) {
+ ((uivector*)p)->size = ((uivector*)p)->allocsize = 0;
+ lodepng_free(((uivector*)p)->data);
+ ((uivector*)p)->data = NULL;
+}
+
+/*returns 1 if success, 0 if failure ==> nothing done*/
+static unsigned uivector_reserve(uivector* p, size_t allocsize) {
+ if(allocsize > p->allocsize) {
+ size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2);
+ void* data = lodepng_realloc(p->data, newsize);
+ if(data) {
+ p->allocsize = newsize;
+ p->data = (unsigned*)data;
+ }
+ else return 0; /*error: not enough memory*/
+ }
+ return 1;
+}
+
+/*returns 1 if success, 0 if failure ==> nothing done*/
+static unsigned uivector_resize(uivector* p, size_t size) {
+ if(!uivector_reserve(p, size * sizeof(unsigned))) return 0;
+ p->size = size;
+ return 1; /*success*/
+}
+
+/*resize and give all new elements the value*/
+static unsigned uivector_resizev(uivector* p, size_t size, unsigned value) {
+ size_t oldsize = p->size, i;
+ if(!uivector_resize(p, size)) return 0;
+ for(i = oldsize; i < size; ++i) p->data[i] = value;
+ return 1;
+}
+
+static void uivector_init(uivector* p) {
+ p->data = NULL;
+ p->size = p->allocsize = 0;
+}
+
+#ifdef LODEPNG_COMPILE_ENCODER
+/*returns 1 if success, 0 if failure ==> nothing done*/
+static unsigned uivector_push_back(uivector* p, unsigned c) {
+ if(!uivector_resize(p, p->size + 1)) return 0;
+ p->data[p->size - 1] = c;
+ return 1;
+}
+#endif /*LODEPNG_COMPILE_ENCODER*/
+#endif /*LODEPNG_COMPILE_ZLIB*/
+
+/* /////////////////////////////////////////////////////////////////////////// */
+
+/*dynamic vector of unsigned chars*/
+typedef struct ucvector {
+ unsigned char* data;
+ size_t size; /*used size*/
+ size_t allocsize; /*allocated size*/
+} ucvector;
+
+/*returns 1 if success, 0 if failure ==> nothing done*/
+static unsigned ucvector_reserve(ucvector* p, size_t allocsize) {
+ if(allocsize > p->allocsize) {
+ size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2);
+ void* data = lodepng_realloc(p->data, newsize);
+ if(data) {
+ p->allocsize = newsize;
+ p->data = (unsigned char*)data;
+ }
+ else return 0; /*error: not enough memory*/
+ }
+ return 1;
+}
+
+/*returns 1 if success, 0 if failure ==> nothing done*/
+static unsigned ucvector_resize(ucvector* p, size_t size) {
+ if(!ucvector_reserve(p, size * sizeof(unsigned char))) return 0;
+ p->size = size;
+ return 1; /*success*/
+}
+
+#ifdef LODEPNG_COMPILE_PNG
+
+static void ucvector_cleanup(void* p) {
+ ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0;
+ lodepng_free(((ucvector*)p)->data);
+ ((ucvector*)p)->data = NULL;
+}
+
+static void ucvector_init(ucvector* p) {
+ p->data = NULL;
+ p->size = p->allocsize = 0;
+}
+#endif /*LODEPNG_COMPILE_PNG*/
+
+#ifdef LODEPNG_COMPILE_ZLIB
+/*you can both convert from vector to buffer&size and vica versa. If you use
+init_buffer to take over a buffer and size, it is not needed to use cleanup*/
+static void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size) {
+ p->data = buffer;
+ p->allocsize = p->size = size;
+}
+#endif /*LODEPNG_COMPILE_ZLIB*/
+
+#if (defined(LODEPNG_COMPILE_PNG) && defined(LODEPNG_COMPILE_ANCILLARY_CHUNKS)) || defined(LODEPNG_COMPILE_ENCODER)
+/*returns 1 if success, 0 if failure ==> nothing done*/
+static unsigned ucvector_push_back(ucvector* p, unsigned char c) {
+ if(!ucvector_resize(p, p->size + 1)) return 0;
+ p->data[p->size - 1] = c;
+ return 1;
+}
+#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/
+
+
+/* ////////////////////////////////////////////////////////////////////////// */
+
+#ifdef LODEPNG_COMPILE_PNG
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+
+/*free string pointer and set it to NULL*/
+static void string_cleanup(char** out) {
+ lodepng_free(*out);
+ *out = NULL;
+}
+
+/* dynamically allocates a new string with a copy of the null terminated input text */
+static char* alloc_string(const char* in) {
+ size_t insize = strlen(in);
+ char* out = (char*)lodepng_malloc(insize + 1);
+ if(out) {
+ size_t i;
+ for(i = 0; i != insize; ++i) {
+ out[i] = in[i];
+ }
+ out[i] = 0;
+ }
+ return out;
+}
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+#endif /*LODEPNG_COMPILE_PNG*/
+
+/* ////////////////////////////////////////////////////////////////////////// */
+
+unsigned lodepng_read32bitInt(const unsigned char* buffer) {
+ return (unsigned)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]);
+}
+
+#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)
+/*buffer must have at least 4 allocated bytes available*/
+static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) {
+ buffer[0] = (unsigned char)((value >> 24) & 0xff);
+ buffer[1] = (unsigned char)((value >> 16) & 0xff);
+ buffer[2] = (unsigned char)((value >> 8) & 0xff);
+ buffer[3] = (unsigned char)((value ) & 0xff);
+}
+#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/
+
+#ifdef LODEPNG_COMPILE_ENCODER
+static void lodepng_add32bitInt(ucvector* buffer, unsigned value) {
+ ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/
+ lodepng_set32bitInt(&buffer->data[buffer->size - 4], value);
+}
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / File IO / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+#ifdef LODEPNG_COMPILE_DISK
+
+/* returns negative value on error. This should be pure C compatible, so no fstat. */
+static long lodepng_filesize(const char* filename) {
+ FILE* file;
+ long size;
+ file = fopen(filename, "rb");
+ if(!file) return -1;
+
+ if(fseek(file, 0, SEEK_END) != 0) {
+ fclose(file);
+ return -1;
+ }
+
+ size = ftell(file);
+ /* It may give LONG_MAX as directory size, this is invalid for us. */
+ if(size == LONG_MAX) size = -1;
+
+ fclose(file);
+ return size;
+}
+
+/* load file into buffer that already has the correct allocated size. Returns error code.*/
+static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) {
+ FILE* file;
+ size_t readsize;
+ file = fopen(filename, "rb");
+ if(!file) return 78;
+
+ readsize = fread(out, 1, size, file);
+ fclose(file);
+
+ if (readsize != size) return 78;
+ return 0;
+}
+
+unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) {
+ long size = lodepng_filesize(filename);
+ if (size < 0) return 78;
+ *outsize = (size_t)size;
+
+ *out = (unsigned char*)lodepng_malloc((size_t)size);
+ if(!(*out) && size > 0) return 83; /*the above malloc failed*/
+
+ return lodepng_buffer_file(*out, (size_t)size, filename);
+}
+
+/*write given buffer to the file, overwriting the file, it doesn't append to it.*/
+unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) {
+ FILE* file;
+ file = fopen(filename, "wb" );
+ if(!file) return 79;
+ fwrite(buffer, 1, buffersize, file);
+ fclose(file);
+ return 0;
+}
+
+#endif /*LODEPNG_COMPILE_DISK*/
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* ////////////////////////////////////////////////////////////////////////// */
+/* // End of common code and tools. Begin of Zlib related code. // */
+/* ////////////////////////////////////////////////////////////////////////// */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+#ifdef LODEPNG_COMPILE_ZLIB
+#ifdef LODEPNG_COMPILE_ENCODER
+/*TODO: this ignores potential out of memory errors*/
+#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit){\
+ /*add a new byte at the end*/\
+ if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\
+ /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\
+ (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\
+ ++(*bitpointer);\
+}
+
+static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) {
+ size_t i;
+ for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1));
+}
+
+static void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) {
+ size_t i;
+ for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1));
+}
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+#ifdef LODEPNG_COMPILE_DECODER
+
+#define READBIT(bitpointer, bitstream) ((bitstream[bitpointer >> 3] >> (bitpointer & 0x7)) & (unsigned char)1)
+
+static unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream) {
+ unsigned char result = (unsigned char)(READBIT(*bitpointer, bitstream));
+ ++(*bitpointer);
+ return result;
+}
+
+static unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) {
+ unsigned result = 0, i;
+ for(i = 0; i != nbits; ++i) {
+ result += ((unsigned)READBIT(*bitpointer, bitstream)) << i;
+ ++(*bitpointer);
+ }
+ return result;
+}
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / Deflate - Huffman / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+#define FIRST_LENGTH_CODE_INDEX 257
+#define LAST_LENGTH_CODE_INDEX 285
+/*256 literals, the end code, some length codes, and 2 unused codes*/
+#define NUM_DEFLATE_CODE_SYMBOLS 288
+/*the distance codes have their own symbols, 30 used, 2 unused*/
+#define NUM_DISTANCE_SYMBOLS 32
+/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/
+#define NUM_CODE_LENGTH_CODES 19
+
+/*the base lengths represented by codes 257-285*/
+static const unsigned LENGTHBASE[29]
+ = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
+ 67, 83, 99, 115, 131, 163, 195, 227, 258};
+
+/*the extra bits used by codes 257-285 (added to base length)*/
+static const unsigned LENGTHEXTRA[29]
+ = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 5, 5, 5, 5, 0};
+
+/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/
+static const unsigned DISTANCEBASE[30]
+ = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
+ 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
+
+/*the extra bits of backwards distances (added to base)*/
+static const unsigned DISTANCEEXTRA[30]
+ = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
+ 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
+
+/*the order in which "code length alphabet code lengths" are stored, out of this
+the huffman tree of the dynamic huffman tree lengths is generated*/
+static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES]
+ = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/* ////////////////////////////////////////////////////////////////////////// */
+
+/*
+Huffman tree struct, containing multiple representations of the tree
+*/
+typedef struct HuffmanTree {
+ unsigned* tree2d;
+ unsigned* tree1d;
+ unsigned* lengths; /*the lengths of the codes of the 1d-tree*/
+ unsigned maxbitlen; /*maximum number of bits a single code can get*/
+ unsigned numcodes; /*number of symbols in the alphabet = number of codes*/
+} HuffmanTree;
+
+/*function used for debug purposes to draw the tree in ascii art with C++*/
+/*
+static void HuffmanTree_draw(HuffmanTree* tree) {
+ std::cout << "tree. length: " << tree->numcodes << " maxbitlen: " << tree->maxbitlen << std::endl;
+ for(size_t i = 0; i != tree->tree1d.size; ++i) {
+ if(tree->lengths.data[i])
+ std::cout << i << " " << tree->tree1d.data[i] << " " << tree->lengths.data[i] << std::endl;
+ }
+ std::cout << std::endl;
+}*/
+
+static void HuffmanTree_init(HuffmanTree* tree) {
+ tree->tree2d = 0;
+ tree->tree1d = 0;
+ tree->lengths = 0;
+}
+
+static void HuffmanTree_cleanup(HuffmanTree* tree) {
+ lodepng_free(tree->tree2d);
+ lodepng_free(tree->tree1d);
+ lodepng_free(tree->lengths);
+}
+
+/*the tree representation used by the decoder. return value is error*/
+static unsigned HuffmanTree_make2DTree(HuffmanTree* tree) {
+ unsigned nodefilled = 0; /*up to which node it is filled*/
+ unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/
+ unsigned n, i;
+
+ tree->tree2d = (unsigned*)lodepng_malloc(tree->numcodes * 2 * sizeof(unsigned));
+ if(!tree->tree2d) return 83; /*alloc fail*/
+
+ /*
+ convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means
+ uninited, a value >= numcodes is an address to another bit, a value < numcodes
+ is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as
+ many columns as codes - 1.
+ A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes.
+ Here, the internal nodes are stored (what their 0 and 1 option point to).
+ There is only memory for such good tree currently, if there are more nodes
+ (due to too long length codes), error 55 will happen
+ */
+ for(n = 0; n < tree->numcodes * 2; ++n) {
+ tree->tree2d[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/
+ }
+
+ for(n = 0; n < tree->numcodes; ++n) /*the codes*/ {
+ for(i = 0; i != tree->lengths[n]; ++i) /*the bits for this code*/ {
+ unsigned char bit = (unsigned char)((tree->tree1d[n] >> (tree->lengths[n] - i - 1)) & 1);
+ /*oversubscribed, see comment in lodepng_error_text*/
+ if(treepos > 2147483647 || treepos + 2 > tree->numcodes) return 55;
+ if(tree->tree2d[2 * treepos + bit] == 32767) /*not yet filled in*/ {
+ if(i + 1 == tree->lengths[n]) /*last bit*/ {
+ tree->tree2d[2 * treepos + bit] = n; /*put the current code in it*/
+ treepos = 0;
+ } else {
+ /*put address of the next step in here, first that address has to be found of course
+ (it's just nodefilled + 1)...*/
+ ++nodefilled;
+ /*addresses encoded with numcodes added to it*/
+ tree->tree2d[2 * treepos + bit] = nodefilled + tree->numcodes;
+ treepos = nodefilled;
+ }
+ }
+ else treepos = tree->tree2d[2 * treepos + bit] - tree->numcodes;
+ }
+ }
+
+ for(n = 0; n < tree->numcodes * 2; ++n) {
+ if(tree->tree2d[n] == 32767) tree->tree2d[n] = 0; /*remove possible remaining 32767's*/
+ }
+
+ return 0;
+}
+
+/*
+Second step for the ...makeFromLengths and ...makeFromFrequencies functions.
+numcodes, lengths and maxbitlen must already be filled in correctly. return
+value is error.
+*/
+static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) {
+ uivector blcount;
+ uivector nextcode;
+ unsigned error = 0;
+ unsigned bits, n;
+
+ uivector_init(&blcount);
+ uivector_init(&nextcode);
+
+ tree->tree1d = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned));
+ if(!tree->tree1d) error = 83; /*alloc fail*/
+
+ if(!uivector_resizev(&blcount, tree->maxbitlen + 1, 0)
+ || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0))
+ error = 83; /*alloc fail*/
+
+ if(!error) {
+ /*step 1: count number of instances of each code length*/
+ for(bits = 0; bits != tree->numcodes; ++bits) ++blcount.data[tree->lengths[bits]];
+ /*step 2: generate the nextcode values*/
+ for(bits = 1; bits <= tree->maxbitlen; ++bits) {
+ nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1;
+ }
+ /*step 3: generate all the codes*/
+ for(n = 0; n != tree->numcodes; ++n) {
+ if(tree->lengths[n] != 0) tree->tree1d[n] = nextcode.data[tree->lengths[n]]++;
+ }
+ }
+
+ uivector_cleanup(&blcount);
+ uivector_cleanup(&nextcode);
+
+ if(!error) return HuffmanTree_make2DTree(tree);
+ else return error;
+}
+
+/*
+given the code lengths (as stored in the PNG file), generate the tree as defined
+by Deflate. maxbitlen is the maximum bits that a code in the tree can have.
+return value is error.
+*/
+static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen,
+ size_t numcodes, unsigned maxbitlen) {
+ unsigned i;
+ tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned));
+ if(!tree->lengths) return 83; /*alloc fail*/
+ for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i];
+ tree->numcodes = (unsigned)numcodes; /*number of symbols*/
+ tree->maxbitlen = maxbitlen;
+ return HuffmanTree_makeFromLengths2(tree);
+}
+
+#ifdef LODEPNG_COMPILE_ENCODER
+
+/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding",
+Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/
+
+/*chain node for boundary package merge*/
+typedef struct BPMNode {
+ int weight; /*the sum of all weights in this chain*/
+ unsigned index; /*index of this leaf node (called "count" in the paper)*/
+ struct BPMNode* tail; /*the next nodes in this chain (null if last)*/
+ int in_use;
+} BPMNode;
+
+/*lists of chains*/
+typedef struct BPMLists {
+ /*memory pool*/
+ unsigned memsize;
+ BPMNode* memory;
+ unsigned numfree;
+ unsigned nextfree;
+ BPMNode** freelist;
+ /*two heads of lookahead chains per list*/
+ unsigned listsize;
+ BPMNode** chains0;
+ BPMNode** chains1;
+} BPMLists;
+
+/*creates a new chain node with the given parameters, from the memory in the lists */
+static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) {
+ unsigned i;
+ BPMNode* result;
+
+ /*memory full, so garbage collect*/
+ if(lists->nextfree >= lists->numfree) {
+ /*mark only those that are in use*/
+ for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0;
+ for(i = 0; i != lists->listsize; ++i) {
+ BPMNode* node;
+ for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1;
+ for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1;
+ }
+ /*collect those that are free*/
+ lists->numfree = 0;
+ for(i = 0; i != lists->memsize; ++i) {
+ if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i];
+ }
+ lists->nextfree = 0;
+ }
+
+ result = lists->freelist[lists->nextfree++];
+ result->weight = weight;
+ result->index = index;
+ result->tail = tail;
+ return result;
+}
+
+/*sort the leaves with stable mergesort*/
+static void bpmnode_sort(BPMNode* leaves, size_t num) {
+ BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num);
+ size_t width, counter = 0;
+ for(width = 1; width < num; width *= 2) {
+ BPMNode* a = (counter & 1) ? mem : leaves;
+ BPMNode* b = (counter & 1) ? leaves : mem;
+ size_t p;
+ for(p = 0; p < num; p += 2 * width) {
+ size_t q = (p + width > num) ? num : (p + width);
+ size_t r = (p + 2 * width > num) ? num : (p + 2 * width);
+ size_t i = p, j = q, k;
+ for(k = p; k < r; k++) {
+ if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++];
+ else b[k] = a[j++];
+ }
+ }
+ counter++;
+ }
+ if(counter & 1) memcpy(leaves, mem, sizeof(*leaves) * num);
+ lodepng_free(mem);
+}
+
+/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/
+static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) {
+ unsigned lastindex = lists->chains1[c]->index;
+
+ if(c == 0) {
+ if(lastindex >= numpresent) return;
+ lists->chains0[c] = lists->chains1[c];
+ lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0);
+ } else {
+ /*sum of the weights of the head nodes of the previous lookahead chains.*/
+ int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight;
+ lists->chains0[c] = lists->chains1[c];
+ if(lastindex < numpresent && sum > leaves[lastindex].weight) {
+ lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail);
+ return;
+ }
+ lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]);
+ /*in the end we are only interested in the chain of the last list, so no
+ need to recurse if we're at the last one (this gives measurable speedup)*/
+ if(num + 1 < (int)(2 * numpresent - 2)) {
+ boundaryPM(lists, leaves, numpresent, c - 1, num);
+ boundaryPM(lists, leaves, numpresent, c - 1, num);
+ }
+ }
+}
+
+unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,
+ size_t numcodes, unsigned maxbitlen) {
+ unsigned error = 0;
+ unsigned i;
+ size_t numpresent = 0; /*number of symbols with non-zero frequency*/
+ BPMNode* leaves; /*the symbols, only those with > 0 frequency*/
+
+ if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/
+ if((1u << maxbitlen) < (unsigned)numcodes) return 80; /*error: represent all symbols*/
+
+ leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves));
+ if(!leaves) return 83; /*alloc fail*/
+
+ for(i = 0; i != numcodes; ++i) {
+ if(frequencies[i] > 0) {
+ leaves[numpresent].weight = (int)frequencies[i];
+ leaves[numpresent].index = i;
+ ++numpresent;
+ }
+ }
+
+ for(i = 0; i != numcodes; ++i) lengths[i] = 0;
+
+ /*ensure at least two present symbols. There should be at least one symbol
+ according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To
+ make these work as well ensure there are at least two symbols. The
+ Package-Merge code below also doesn't work correctly if there's only one
+ symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/
+ if(numpresent == 0) {
+ lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/
+ } else if(numpresent == 1) {
+ lengths[leaves[0].index] = 1;
+ lengths[leaves[0].index == 0 ? 1 : 0] = 1;
+ } else {
+ BPMLists lists;
+ BPMNode* node;
+
+ bpmnode_sort(leaves, numpresent);
+
+ lists.listsize = maxbitlen;
+ lists.memsize = 2 * maxbitlen * (maxbitlen + 1);
+ lists.nextfree = 0;
+ lists.numfree = lists.memsize;
+ lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory));
+ lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*));
+ lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));
+ lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));
+ if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/
+
+ if(!error) {
+ for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i];
+
+ bpmnode_create(&lists, leaves[0].weight, 1, 0);
+ bpmnode_create(&lists, leaves[1].weight, 2, 0);
+
+ for(i = 0; i != lists.listsize; ++i) {
+ lists.chains0[i] = &lists.memory[0];
+ lists.chains1[i] = &lists.memory[1];
+ }
+
+ /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/
+ for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i);
+
+ for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) {
+ for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index];
+ }
+ }
+
+ lodepng_free(lists.memory);
+ lodepng_free(lists.freelist);
+ lodepng_free(lists.chains0);
+ lodepng_free(lists.chains1);
+ }
+
+ lodepng_free(leaves);
+ return error;
+}
+
+/*Create the Huffman tree given the symbol frequencies*/
+static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies,
+ size_t mincodes, size_t numcodes, unsigned maxbitlen) {
+ unsigned error = 0;
+ while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/
+ tree->maxbitlen = maxbitlen;
+ tree->numcodes = (unsigned)numcodes; /*number of symbols*/
+ tree->lengths = (unsigned*)lodepng_realloc(tree->lengths, numcodes * sizeof(unsigned));
+ if(!tree->lengths) return 83; /*alloc fail*/
+ /*initialize all lengths to 0*/
+ memset(tree->lengths, 0, numcodes * sizeof(unsigned));
+
+ error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen);
+ if(!error) error = HuffmanTree_makeFromLengths2(tree);
+ return error;
+}
+
+static unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index) {
+ return tree->tree1d[index];
+}
+
+static unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index) {
+ return tree->lengths[index];
+}
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/
+static unsigned generateFixedLitLenTree(HuffmanTree* tree) {
+ unsigned i, error = 0;
+ unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));
+ if(!bitlen) return 83; /*alloc fail*/
+
+ /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/
+ for(i = 0; i <= 143; ++i) bitlen[i] = 8;
+ for(i = 144; i <= 255; ++i) bitlen[i] = 9;
+ for(i = 256; i <= 279; ++i) bitlen[i] = 7;
+ for(i = 280; i <= 287; ++i) bitlen[i] = 8;
+
+ error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15);
+
+ lodepng_free(bitlen);
+ return error;
+}
+
+/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/
+static unsigned generateFixedDistanceTree(HuffmanTree* tree) {
+ unsigned i, error = 0;
+ unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));
+ if(!bitlen) return 83; /*alloc fail*/
+
+ /*there are 32 distance codes, but 30-31 are unused*/
+ for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5;
+ error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15);
+
+ lodepng_free(bitlen);
+ return error;
+}
+
+#ifdef LODEPNG_COMPILE_DECODER
+
+/*
+returns the code, or (unsigned)(-1) if error happened
+inbitlength is the length of the complete buffer, in bits (so its byte length times 8)
+*/
+static unsigned huffmanDecodeSymbol(const unsigned char* in, size_t* bp,
+ const HuffmanTree* codetree, size_t inbitlength) {
+ unsigned treepos = 0, ct;
+ for(;;) {
+ if(*bp >= inbitlength) return (unsigned)(-1); /*error: end of input memory reached without endcode*/
+ /*
+ decode the symbol from the tree. The "readBitFromStream" code is inlined in
+ the expression below because this is the biggest bottleneck while decoding
+ */
+ ct = codetree->tree2d[(treepos << 1) + READBIT(*bp, in)];
+ ++(*bp);
+ if(ct < codetree->numcodes) return ct; /*the symbol is decoded, return it*/
+ else treepos = ct - codetree->numcodes; /*symbol not yet decoded, instead move tree position*/
+
+ if(treepos >= codetree->numcodes) return (unsigned)(-1); /*error: it appeared outside the codetree*/
+ }
+}
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+#ifdef LODEPNG_COMPILE_DECODER
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / Inflator (Decompressor) / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+/*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/
+static void getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) {
+ /*TODO: check for out of memory errors*/
+ generateFixedLitLenTree(tree_ll);
+ generateFixedDistanceTree(tree_d);
+}
+
+/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/
+static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
+ const unsigned char* in, size_t* bp, size_t inlength) {
+ /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/
+ unsigned error = 0;
+ unsigned n, HLIT, HDIST, HCLEN, i;
+ size_t inbitlength = inlength * 8;
+
+ /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/
+ unsigned* bitlen_ll = 0; /*lit,len code lengths*/
+ unsigned* bitlen_d = 0; /*dist code lengths*/
+ /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/
+ unsigned* bitlen_cl = 0;
+ HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/
+
+ if((*bp) + 14 > (inlength << 3)) return 49; /*error: the bit pointer is or will go past the memory*/
+
+ /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/
+ HLIT = readBitsFromStream(bp, in, 5) + 257;
+ /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/
+ HDIST = readBitsFromStream(bp, in, 5) + 1;
+ /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/
+ HCLEN = readBitsFromStream(bp, in, 4) + 4;
+
+ if((*bp) + HCLEN * 3 > (inlength << 3)) return 50; /*error: the bit pointer is or will go past the memory*/
+
+ HuffmanTree_init(&tree_cl);
+
+ while(!error) {
+ /*read the code length codes out of 3 * (amount of code length codes) bits*/
+
+ bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned));
+ if(!bitlen_cl) ERROR_BREAK(83 /*alloc fail*/);
+
+ for(i = 0; i != NUM_CODE_LENGTH_CODES; ++i) {
+ if(i < HCLEN) bitlen_cl[CLCL_ORDER[i]] = readBitsFromStream(bp, in, 3);
+ else bitlen_cl[CLCL_ORDER[i]] = 0; /*if not, it must stay 0*/
+ }
+
+ error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7);
+ if(error) break;
+
+ /*now we can use this tree to read the lengths for the tree that this function will return*/
+ bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));
+ bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));
+ if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/);
+ for(i = 0; i != NUM_DEFLATE_CODE_SYMBOLS; ++i) bitlen_ll[i] = 0;
+ for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen_d[i] = 0;
+
+ /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/
+ i = 0;
+ while(i < HLIT + HDIST) {
+ unsigned code = huffmanDecodeSymbol(in, bp, &tree_cl, inbitlength);
+ if(code <= 15) /*a length code*/ {
+ if(i < HLIT) bitlen_ll[i] = code;
+ else bitlen_d[i - HLIT] = code;
+ ++i;
+ } else if(code == 16) /*repeat previous*/ {
+ unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/
+ unsigned value; /*set value to the previous code*/
+
+ if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/
+
+ if((*bp + 2) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
+ replength += readBitsFromStream(bp, in, 2);
+
+ if(i < HLIT + 1) value = bitlen_ll[i - 1];
+ else value = bitlen_d[i - HLIT - 1];
+ /*repeat this value in the next lengths*/
+ for(n = 0; n < replength; ++n) {
+ if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/
+ if(i < HLIT) bitlen_ll[i] = value;
+ else bitlen_d[i - HLIT] = value;
+ ++i;
+ }
+ } else if(code == 17) /*repeat "0" 3-10 times*/ {
+ unsigned replength = 3; /*read in the bits that indicate repeat length*/
+ if((*bp + 3) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
+ replength += readBitsFromStream(bp, in, 3);
+
+ /*repeat this value in the next lengths*/
+ for(n = 0; n < replength; ++n) {
+ if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/
+
+ if(i < HLIT) bitlen_ll[i] = 0;
+ else bitlen_d[i - HLIT] = 0;
+ ++i;
+ }
+ } else if(code == 18) /*repeat "0" 11-138 times*/ {
+ unsigned replength = 11; /*read in the bits that indicate repeat length*/
+ if((*bp + 7) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
+ replength += readBitsFromStream(bp, in, 7);
+
+ /*repeat this value in the next lengths*/
+ for(n = 0; n < replength; ++n) {
+ if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/
+
+ if(i < HLIT) bitlen_ll[i] = 0;
+ else bitlen_d[i - HLIT] = 0;
+ ++i;
+ }
+ } else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ {
+ if(code == (unsigned)(-1)) {
+ /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
+ (10=no endcode, 11=wrong jump outside of tree)*/
+ error = (*bp) > inbitlength ? 10 : 11;
+ }
+ else error = 16; /*unexisting code, this can never happen*/
+ break;
+ }
+ }
+ if(error) break;
+
+ if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/
+
+ /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/
+ error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15);
+ if(error) break;
+ error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15);
+
+ break; /*end of error-while*/
+ }
+
+ lodepng_free(bitlen_cl);
+ lodepng_free(bitlen_ll);
+ lodepng_free(bitlen_d);
+ HuffmanTree_cleanup(&tree_cl);
+
+ return error;
+}
+
+/*inflate a block with dynamic of fixed Huffman tree*/
+static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp,
+ size_t* pos, size_t inlength, unsigned btype) {
+ unsigned error = 0;
+ HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
+ HuffmanTree tree_d; /*the huffman tree for distance codes*/
+ size_t inbitlength = inlength * 8;
+
+ HuffmanTree_init(&tree_ll);
+ HuffmanTree_init(&tree_d);
+
+ if(btype == 1) getTreeInflateFixed(&tree_ll, &tree_d);
+ else if(btype == 2) error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength);
+
+ while(!error) /*decode all symbols until end reached, breaks at end code*/ {
+ /*code_ll is literal, length or end code*/
+ unsigned code_ll = huffmanDecodeSymbol(in, bp, &tree_ll, inbitlength);
+ if(code_ll <= 255) /*literal symbol*/ {
+ /*ucvector_push_back would do the same, but for some reason the two lines below run 10% faster*/
+ if(!ucvector_resize(out, (*pos) + 1)) ERROR_BREAK(83 /*alloc fail*/);
+ out->data[*pos] = (unsigned char)code_ll;
+ ++(*pos);
+ } else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ {
+ unsigned code_d, distance;
+ unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/
+ size_t start, forward, backward, length;
+
+ /*part 1: get length base*/
+ length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX];
+
+ /*part 2: get extra bits and add the value of that to length*/
+ numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];
+ if((*bp + numextrabits_l) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
+ length += readBitsFromStream(bp, in, numextrabits_l);
+
+ /*part 3: get distance code*/
+ code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength);
+ if(code_d > 29) {
+ if(code_d == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ {
+ /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
+ (10=no endcode, 11=wrong jump outside of tree)*/
+ error = (*bp) > inlength * 8 ? 10 : 11;
+ }
+ else error = 18; /*error: invalid distance code (30-31 are never used)*/
+ break;
+ }
+ distance = DISTANCEBASE[code_d];
+
+ /*part 4: get extra bits from distance*/
+ numextrabits_d = DISTANCEEXTRA[code_d];
+ if((*bp + numextrabits_d) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
+ distance += readBitsFromStream(bp, in, numextrabits_d);
+
+ /*part 5: fill in all the out[n] values based on the length and dist*/
+ start = (*pos);
+ if(distance > start) ERROR_BREAK(52); /*too long backward distance*/
+ backward = start - distance;
+
+ if(!ucvector_resize(out, (*pos) + length)) ERROR_BREAK(83 /*alloc fail*/);
+ if (distance < length) {
+ for(forward = 0; forward < length; ++forward) {
+ out->data[(*pos)++] = out->data[backward++];
+ }
+ } else {
+ memcpy(out->data + *pos, out->data + backward, length);
+ *pos += length;
+ }
+ } else if(code_ll == 256) {
+ break; /*end code, break the loop*/
+ } else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ {
+ /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
+ (10=no endcode, 11=wrong jump outside of tree)*/
+ error = ((*bp) > inlength * 8) ? 10 : 11;
+ break;
+ }
+ }
+
+ HuffmanTree_cleanup(&tree_ll);
+ HuffmanTree_cleanup(&tree_d);
+
+ return error;
+}
+
+static unsigned inflateNoCompression(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength) {
+ size_t p;
+ unsigned LEN, NLEN, n, error = 0;
+
+ /*go to first boundary of byte*/
+ while(((*bp) & 0x7) != 0) ++(*bp);
+ p = (*bp) / 8; /*byte position*/
+
+ /*read LEN (2 bytes) and NLEN (2 bytes)*/
+ if(p + 4 >= inlength) return 52; /*error, bit pointer will jump past memory*/
+ LEN = in[p] + 256u * in[p + 1]; p += 2;
+ NLEN = in[p] + 256u * in[p + 1]; p += 2;
+
+ /*check if 16-bit NLEN is really the one's complement of LEN*/
+ if(LEN + NLEN != 65535) return 21; /*error: NLEN is not one's complement of LEN*/
+
+ if(!ucvector_resize(out, (*pos) + LEN)) return 83; /*alloc fail*/
+
+ /*read the literal data: LEN bytes are now stored in the out buffer*/
+ if(p + LEN > inlength) return 23; /*error: reading outside of in buffer*/
+ for(n = 0; n < LEN; ++n) out->data[(*pos)++] = in[p++];
+
+ (*bp) = p * 8;
+
+ return error;
+}
+
+static unsigned lodepng_inflatev(ucvector* out,
+ const unsigned char* in, size_t insize,
+ const LodePNGDecompressSettings* settings) {
+ /*bit pointer in the "in" data, current byte is bp >> 3, current bit is bp & 0x7 (from lsb to msb of the byte)*/
+ size_t bp = 0;
+ unsigned BFINAL = 0;
+ size_t pos = 0; /*byte position in the out buffer*/
+ unsigned error = 0;
+
+ (void)settings;
+
+ while(!BFINAL) {
+ unsigned BTYPE;
+ if(bp + 2 >= insize * 8) return 52; /*error, bit pointer will jump past memory*/
+ BFINAL = readBitFromStream(&bp, in);
+ BTYPE = 1u * readBitFromStream(&bp, in);
+ BTYPE += 2u * readBitFromStream(&bp, in);
+
+ if(BTYPE == 3) return 20; /*error: invalid BTYPE*/
+ else if(BTYPE == 0) error = inflateNoCompression(out, in, &bp, &pos, insize); /*no compression*/
+ else error = inflateHuffmanBlock(out, in, &bp, &pos, insize, BTYPE); /*compression, BTYPE 01 or 10*/
+
+ if(error) return error;
+ }
+
+ return error;
+}
+
+unsigned lodepng_inflate(unsigned char** out, size_t* outsize,
+ const unsigned char* in, size_t insize,
+ const LodePNGDecompressSettings* settings) {
+ unsigned error;
+ ucvector v;
+ ucvector_init_buffer(&v, *out, *outsize);
+ error = lodepng_inflatev(&v, in, insize, settings);
+ *out = v.data;
+ *outsize = v.size;
+ return error;
+}
+
+static unsigned inflate(unsigned char** out, size_t* outsize,
+ const unsigned char* in, size_t insize,
+ const LodePNGDecompressSettings* settings) {
+ if(settings->custom_inflate) {
+ return settings->custom_inflate(out, outsize, in, insize, settings);
+ } else {
+ return lodepng_inflate(out, outsize, in, insize, settings);
+ }
+}
+
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+#ifdef LODEPNG_COMPILE_ENCODER
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / Deflator (Compressor) / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258;
+
+/*bitlen is the size in bits of the code*/
+static void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen) {
+ addBitsToStreamReversed(bp, compressed, code, bitlen);
+}
+
+/*search the index in the array, that has the largest value smaller than or equal to the given value,
+given array must be sorted (if no value is smaller, it returns the size of the given array)*/
+static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) {
+ /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/
+ size_t left = 1;
+ size_t right = array_size - 1;
+
+ while(left <= right) {
+ size_t mid = (left + right) >> 1;
+ if (array[mid] >= value) right = mid - 1;
+ else left = mid + 1;
+ }
+ if(left >= array_size || array[left] > value) left--;
+ return left;
+}
+
+static void addLengthDistance(uivector* values, size_t length, size_t distance) {
+ /*values in encoded vector are those used by deflate:
+ 0-255: literal bytes
+ 256: end
+ 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits)
+ 286-287: invalid*/
+
+ unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length);
+ unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]);
+ unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance);
+ unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]);
+
+ uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX);
+ uivector_push_back(values, extra_length);
+ uivector_push_back(values, dist_code);
+ uivector_push_back(values, extra_distance);
+}
+
+/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3
+bytes as input because 3 is the minimum match length for deflate*/
+static const unsigned HASH_NUM_VALUES = 65536;
+static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/
+
+typedef struct Hash {
+ int* head; /*hash value to head circular pos - can be outdated if went around window*/
+ /*circular pos to prev circular pos*/
+ unsigned short* chain;
+ int* val; /*circular pos to hash value*/
+
+ /*TODO: do this not only for zeros but for any repeated byte. However for PNG
+ it's always going to be the zeros that dominate, so not important for PNG*/
+ int* headz; /*similar to head, but for chainz*/
+ unsigned short* chainz; /*those with same amount of zeros*/
+ unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/
+} Hash;
+
+static unsigned hash_init(Hash* hash, unsigned windowsize) {
+ unsigned i;
+ hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES);
+ hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize);
+ hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
+
+ hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
+ hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1));
+ hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
+
+ if(!hash->head || !hash->chain || !hash->val || !hash->headz|| !hash->chainz || !hash->zeros) {
+ return 83; /*alloc fail*/
+ }
+
+ /*initialize hash table*/
+ for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1;
+ for(i = 0; i != windowsize; ++i) hash->val[i] = -1;
+ for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/
+
+ for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1;
+ for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/
+
+ return 0;
+}
+
+static void hash_cleanup(Hash* hash) {
+ lodepng_free(hash->head);
+ lodepng_free(hash->val);
+ lodepng_free(hash->chain);
+
+ lodepng_free(hash->zeros);
+ lodepng_free(hash->headz);
+ lodepng_free(hash->chainz);
+}
+
+
+
+static unsigned getHash(const unsigned char* data, size_t size, size_t pos) {
+ unsigned result = 0;
+ if(pos + 2 < size) {
+ /*A simple shift and xor hash is used. Since the data of PNGs is dominated
+ by zeroes due to the filters, a better hash does not have a significant
+ effect on speed in traversing the chain, and causes more time spend on
+ calculating the hash.*/
+ result ^= (unsigned)(data[pos + 0] << 0u);
+ result ^= (unsigned)(data[pos + 1] << 4u);
+ result ^= (unsigned)(data[pos + 2] << 8u);
+ } else {
+ size_t amount, i;
+ if(pos >= size) return 0;
+ amount = size - pos;
+ for(i = 0; i != amount; ++i) result ^= (unsigned)(data[pos + i] << (i * 8u));
+ }
+ return result & HASH_BIT_MASK;
+}
+
+static unsigned countZeros(const unsigned char* data, size_t size, size_t pos) {
+ const unsigned char* start = data + pos;
+ const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH;
+ if(end > data + size) end = data + size;
+ data = start;
+ while(data != end && *data == 0) ++data;
+ /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/
+ return (unsigned)(data - start);
+}
+
+/*wpos = pos & (windowsize - 1)*/
+static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros) {
+ hash->val[wpos] = (int)hashval;
+ if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval];
+ hash->head[hashval] = (int)wpos;
+
+ hash->zeros[wpos] = numzeros;
+ if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros];
+ hash->headz[numzeros] = (int)wpos;
+}
+
+/*
+LZ77-encode the data. Return value is error code. The input are raw bytes, the output
+is in the form of unsigned integers with codes representing for example literal bytes, or
+length/distance pairs.
+It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a
+sliding window (of windowsize) is used, and all past bytes in that window can be used as
+the "dictionary". A brute force search through all possible distances would be slow, and
+this hash technique is one out of several ways to speed this up.
+*/
+static unsigned encodeLZ77(uivector* out, Hash* hash,
+ const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize,
+ unsigned minmatch, unsigned nicematch, unsigned lazymatching) {
+ size_t pos;
+ unsigned i, error = 0;
+ /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/
+ unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8;
+ unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64;
+
+ unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/
+ unsigned numzeros = 0;
+
+ unsigned offset; /*the offset represents the distance in LZ77 terminology*/
+ unsigned length;
+ unsigned lazy = 0;
+ unsigned lazylength = 0, lazyoffset = 0;
+ unsigned hashval;
+ unsigned current_offset, current_length;
+ unsigned prev_offset;
+ const unsigned char *lastptr, *foreptr, *backptr;
+ unsigned hashpos;
+
+ if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/
+ if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/
+
+ if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH;
+
+ for(pos = inpos; pos < insize; ++pos) {
+ size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/
+ unsigned chainlength = 0;
+
+ hashval = getHash(in, insize, pos);
+
+ if(usezeros && hashval == 0) {
+ if(numzeros == 0) numzeros = countZeros(in, insize, pos);
+ else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;
+ } else {
+ numzeros = 0;
+ }
+
+ updateHashChain(hash, wpos, hashval, numzeros);
+
+ /*the length and offset found for the current position*/
+ length = 0;
+ offset = 0;
+
+ hashpos = hash->chain[wpos];
+
+ lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH];
+
+ /*search for the longest string*/
+ prev_offset = 0;
+ for(;;) {
+ if(chainlength++ >= maxchainlength) break;
+ current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize);
+
+ if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/
+ prev_offset = current_offset;
+ if(current_offset > 0) {
+ /*test the next characters*/
+ foreptr = &in[pos];
+ backptr = &in[pos - current_offset];
+
+ /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/
+ if(numzeros >= 3) {
+ unsigned skip = hash->zeros[hashpos];
+ if(skip > numzeros) skip = numzeros;
+ backptr += skip;
+ foreptr += skip;
+ }
+
+ while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/ {
+ ++backptr;
+ ++foreptr;
+ }
+ current_length = (unsigned)(foreptr - &in[pos]);
+
+ if(current_length > length) {
+ length = current_length; /*the longest length*/
+ offset = current_offset; /*the offset that is related to this longest length*/
+ /*jump out once a length of max length is found (speed gain). This also jumps
+ out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/
+ if(current_length >= nicematch) break;
+ }
+ }
+
+ if(hashpos == hash->chain[hashpos]) break;
+
+ if(numzeros >= 3 && length > numzeros) {
+ hashpos = hash->chainz[hashpos];
+ if(hash->zeros[hashpos] != numzeros) break;
+ } else {
+ hashpos = hash->chain[hashpos];
+ /*outdated hash value, happens if particular value was not encountered in whole last window*/
+ if(hash->val[hashpos] != (int)hashval) break;
+ }
+ }
+
+ if(lazymatching) {
+ if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) {
+ lazy = 1;
+ lazylength = length;
+ lazyoffset = offset;
+ continue; /*try the next byte*/
+ }
+ if(lazy) {
+ lazy = 0;
+ if(pos == 0) ERROR_BREAK(81);
+ if(length > lazylength + 1) {
+ /*push the previous character as literal*/
+ if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/);
+ } else {
+ length = lazylength;
+ offset = lazyoffset;
+ hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/
+ hash->headz[numzeros] = -1; /*idem*/
+ --pos;
+ }
+ }
+ }
+ if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/);
+
+ /*encode it as length/distance pair or literal value*/
+ if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ {
+ if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
+ } else if(length < minmatch || (length == 3 && offset > 4096)) {
+ /*compensate for the fact that longer offsets have more extra bits, a
+ length of only 3 may be not worth it then*/
+ if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
+ } else {
+ addLengthDistance(out, length, offset);
+ for(i = 1; i < length; ++i) {
+ ++pos;
+ wpos = pos & (windowsize - 1);
+ hashval = getHash(in, insize, pos);
+ if(usezeros && hashval == 0) {
+ if(numzeros == 0) numzeros = countZeros(in, insize, pos);
+ else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;
+ } else {
+ numzeros = 0;
+ }
+ updateHashChain(hash, wpos, hashval, numzeros);
+ }
+ }
+ } /*end of the loop through each character of input*/
+
+ return error;
+}
+
+/* /////////////////////////////////////////////////////////////////////////// */
+
+static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) {
+ /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte,
+ 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/
+
+ size_t i, j, numdeflateblocks = (datasize + 65534) / 65535;
+ unsigned datapos = 0;
+ for(i = 0; i != numdeflateblocks; ++i) {
+ unsigned BFINAL, BTYPE, LEN, NLEN;
+ unsigned char firstbyte;
+
+ BFINAL = (i == numdeflateblocks - 1);
+ BTYPE = 0;
+
+ firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1));
+ ucvector_push_back(out, firstbyte);
+
+ LEN = 65535;
+ if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos;
+ NLEN = 65535 - LEN;
+
+ ucvector_push_back(out, (unsigned char)(LEN & 255));
+ ucvector_push_back(out, (unsigned char)(LEN >> 8));
+ ucvector_push_back(out, (unsigned char)(NLEN & 255));
+ ucvector_push_back(out, (unsigned char)(NLEN >> 8));
+
+ /*Decompressed data*/
+ for(j = 0; j < 65535 && datapos < datasize; ++j) {
+ ucvector_push_back(out, data[datapos++]);
+ }
+ }
+
+ return 0;
+}
+
+/*
+write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees.
+tree_ll: the tree for lit and len codes.
+tree_d: the tree for distance codes.
+*/
+static void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded,
+ const HuffmanTree* tree_ll, const HuffmanTree* tree_d) {
+ size_t i = 0;
+ for(i = 0; i != lz77_encoded->size; ++i) {
+ unsigned val = lz77_encoded->data[i];
+ addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_ll, val), HuffmanTree_getLength(tree_ll, val));
+ if(val > 256) /*for a length code, 3 more things have to be added*/ {
+ unsigned length_index = val - FIRST_LENGTH_CODE_INDEX;
+ unsigned n_length_extra_bits = LENGTHEXTRA[length_index];
+ unsigned length_extra_bits = lz77_encoded->data[++i];
+
+ unsigned distance_code = lz77_encoded->data[++i];
+
+ unsigned distance_index = distance_code;
+ unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index];
+ unsigned distance_extra_bits = lz77_encoded->data[++i];
+
+ addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits);
+ addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_d, distance_code),
+ HuffmanTree_getLength(tree_d, distance_code));
+ addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits);
+ }
+ }
+}
+
+/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/
+static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash,
+ const unsigned char* data, size_t datapos, size_t dataend,
+ const LodePNGCompressSettings* settings, unsigned final) {
+ unsigned error = 0;
+
+ /*
+ A block is compressed as follows: The PNG data is lz77 encoded, resulting in
+ literal bytes and length/distance pairs. This is then huffman compressed with
+ two huffman trees. One huffman tree is used for the lit and len values ("ll"),
+ another huffman tree is used for the dist values ("d"). These two trees are
+ stored using their code lengths, and to compress even more these code lengths
+ are also run-length encoded and huffman compressed. This gives a huffman tree
+ of code lengths "cl". The code lenghts used to describe this third tree are
+ the code length code lengths ("clcl").
+ */
+
+ /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/
+ uivector lz77_encoded;
+ HuffmanTree tree_ll; /*tree for lit,len values*/
+ HuffmanTree tree_d; /*tree for distance codes*/
+ HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/
+ uivector frequencies_ll; /*frequency of lit,len codes*/
+ uivector frequencies_d; /*frequency of dist codes*/
+ uivector frequencies_cl; /*frequency of code length codes*/
+ uivector bitlen_lld; /*lit,len,dist code lenghts (int bits), literally (without repeat codes).*/
+ uivector bitlen_lld_e; /*bitlen_lld encoded with repeat codes (this is a rudemtary run length compression)*/
+ /*bitlen_cl is the code length code lengths ("clcl"). The bit lengths of codes to represent tree_cl
+ (these are written as is in the file, it would be crazy to compress these using yet another huffman
+ tree that needs to be represented by yet another set of code lengths)*/
+ uivector bitlen_cl;
+ size_t datasize = dataend - datapos;
+
+ /*
+ Due to the huffman compression of huffman tree representations ("two levels"), there are some anologies:
+ bitlen_lld is to tree_cl what data is to tree_ll and tree_d.
+ bitlen_lld_e is to bitlen_lld what lz77_encoded is to data.
+ bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded.
+ */
+
+ unsigned BFINAL = final;
+ size_t numcodes_ll, numcodes_d, i;
+ unsigned HLIT, HDIST, HCLEN;
+
+ uivector_init(&lz77_encoded);
+ HuffmanTree_init(&tree_ll);
+ HuffmanTree_init(&tree_d);
+ HuffmanTree_init(&tree_cl);
+ uivector_init(&frequencies_ll);
+ uivector_init(&frequencies_d);
+ uivector_init(&frequencies_cl);
+ uivector_init(&bitlen_lld);
+ uivector_init(&bitlen_lld_e);
+ uivector_init(&bitlen_cl);
+
+ /*This while loop never loops due to a break at the end, it is here to
+ allow breaking out of it to the cleanup phase on error conditions.*/
+ while(!error) {
+ if(settings->use_lz77) {
+ error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,
+ settings->minmatch, settings->nicematch, settings->lazymatching);
+ if(error) break;
+ } else {
+ if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/);
+ for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/
+ }
+
+ if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83 /*alloc fail*/);
+ if(!uivector_resizev(&frequencies_d, 30, 0)) ERROR_BREAK(83 /*alloc fail*/);
+
+ /*Count the frequencies of lit, len and dist codes*/
+ for(i = 0; i != lz77_encoded.size; ++i) {
+ unsigned symbol = lz77_encoded.data[i];
+ ++frequencies_ll.data[symbol];
+ if(symbol > 256) {
+ unsigned dist = lz77_encoded.data[i + 2];
+ ++frequencies_d.data[dist];
+ i += 3;
+ }
+ }
+ frequencies_ll.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/
+
+ /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/
+ error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll.data, 257, frequencies_ll.size, 15);
+ if(error) break;
+ /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/
+ error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d.data, 2, frequencies_d.size, 15);
+ if(error) break;
+
+ numcodes_ll = tree_ll.numcodes; if(numcodes_ll > 286) numcodes_ll = 286;
+ numcodes_d = tree_d.numcodes; if(numcodes_d > 30) numcodes_d = 30;
+ /*store the code lengths of both generated trees in bitlen_lld*/
+ for(i = 0; i != numcodes_ll; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_ll, (unsigned)i));
+ for(i = 0; i != numcodes_d; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_d, (unsigned)i));
+
+ /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times),
+ 17 (3-10 zeroes), 18 (11-138 zeroes)*/
+ for(i = 0; i != (unsigned)bitlen_lld.size; ++i) {
+ unsigned j = 0; /*amount of repititions*/
+ while(i + j + 1 < (unsigned)bitlen_lld.size && bitlen_lld.data[i + j + 1] == bitlen_lld.data[i]) ++j;
+
+ if(bitlen_lld.data[i] == 0 && j >= 2) /*repeat code for zeroes*/ {
+ ++j; /*include the first zero*/
+ if(j <= 10) /*repeat code 17 supports max 10 zeroes*/ {
+ uivector_push_back(&bitlen_lld_e, 17);
+ uivector_push_back(&bitlen_lld_e, j - 3);
+ } else /*repeat code 18 supports max 138 zeroes*/ {
+ if(j > 138) j = 138;
+ uivector_push_back(&bitlen_lld_e, 18);
+ uivector_push_back(&bitlen_lld_e, j - 11);
+ }
+ i += (j - 1);
+ } else if(j >= 3) /*repeat code for value other than zero*/ {
+ size_t k;
+ unsigned num = j / 6, rest = j % 6;
+ uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]);
+ for(k = 0; k < num; ++k) {
+ uivector_push_back(&bitlen_lld_e, 16);
+ uivector_push_back(&bitlen_lld_e, 6 - 3);
+ }
+ if(rest >= 3) {
+ uivector_push_back(&bitlen_lld_e, 16);
+ uivector_push_back(&bitlen_lld_e, rest - 3);
+ }
+ else j -= rest;
+ i += j;
+ } else /*too short to benefit from repeat code*/ {
+ uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]);
+ }
+ }
+
+ /*generate tree_cl, the huffmantree of huffmantrees*/
+
+ if(!uivector_resizev(&frequencies_cl, NUM_CODE_LENGTH_CODES, 0)) ERROR_BREAK(83 /*alloc fail*/);
+ for(i = 0; i != bitlen_lld_e.size; ++i) {
+ ++frequencies_cl.data[bitlen_lld_e.data[i]];
+ /*after a repeat code come the bits that specify the number of repetitions,
+ those don't need to be in the frequencies_cl calculation*/
+ if(bitlen_lld_e.data[i] >= 16) ++i;
+ }
+
+ error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl.data,
+ frequencies_cl.size, frequencies_cl.size, 7);
+ if(error) break;
+
+ if(!uivector_resize(&bitlen_cl, tree_cl.numcodes)) ERROR_BREAK(83 /*alloc fail*/);
+ for(i = 0; i != tree_cl.numcodes; ++i) {
+ /*lenghts of code length tree is in the order as specified by deflate*/
+ bitlen_cl.data[i] = HuffmanTree_getLength(&tree_cl, CLCL_ORDER[i]);
+ }
+ while(bitlen_cl.data[bitlen_cl.size - 1] == 0 && bitlen_cl.size > 4) {
+ /*remove zeros at the end, but minimum size must be 4*/
+ if(!uivector_resize(&bitlen_cl, bitlen_cl.size - 1)) ERROR_BREAK(83 /*alloc fail*/);
+ }
+ if(error) break;
+
+ /*
+ Write everything into the output
+
+ After the BFINAL and BTYPE, the dynamic block consists out of the following:
+ - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN
+ - (HCLEN+4)*3 bits code lengths of code length alphabet
+ - HLIT + 257 code lenghts of lit/length alphabet (encoded using the code length
+ alphabet, + possible repetition codes 16, 17, 18)
+ - HDIST + 1 code lengths of distance alphabet (encoded using the code length
+ alphabet, + possible repetition codes 16, 17, 18)
+ - compressed data
+ - 256 (end code)
+ */
+
+ /*Write block type*/
+ addBitToStream(bp, out, BFINAL);
+ addBitToStream(bp, out, 0); /*first bit of BTYPE "dynamic"*/
+ addBitToStream(bp, out, 1); /*second bit of BTYPE "dynamic"*/
+
+ /*write the HLIT, HDIST and HCLEN values*/
+ HLIT = (unsigned)(numcodes_ll - 257);
+ HDIST = (unsigned)(numcodes_d - 1);
+ HCLEN = (unsigned)bitlen_cl.size - 4;
+ /*trim zeroes for HCLEN. HLIT and HDIST were already trimmed at tree creation*/
+ while(!bitlen_cl.data[HCLEN + 4 - 1] && HCLEN > 0) --HCLEN;
+ addBitsToStream(bp, out, HLIT, 5);
+ addBitsToStream(bp, out, HDIST, 5);
+ addBitsToStream(bp, out, HCLEN, 4);
+
+ /*write the code lenghts of the code length alphabet*/
+ for(i = 0; i != HCLEN + 4; ++i) addBitsToStream(bp, out, bitlen_cl.data[i], 3);
+
+ /*write the lenghts of the lit/len AND the dist alphabet*/
+ for(i = 0; i != bitlen_lld_e.size; ++i) {
+ addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_cl, bitlen_lld_e.data[i]),
+ HuffmanTree_getLength(&tree_cl, bitlen_lld_e.data[i]));
+ /*extra bits of repeat codes*/
+ if(bitlen_lld_e.data[i] == 16) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 2);
+ else if(bitlen_lld_e.data[i] == 17) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 3);
+ else if(bitlen_lld_e.data[i] == 18) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 7);
+ }
+
+ /*write the compressed data symbols*/
+ writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);
+ /*error: the length of the end code 256 must be larger than 0*/
+ if(HuffmanTree_getLength(&tree_ll, 256) == 0) ERROR_BREAK(64);
+
+ /*write the end code*/
+ addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256));
+
+ break; /*end of error-while*/
+ }
+
+ /*cleanup*/
+ uivector_cleanup(&lz77_encoded);
+ HuffmanTree_cleanup(&tree_ll);
+ HuffmanTree_cleanup(&tree_d);
+ HuffmanTree_cleanup(&tree_cl);
+ uivector_cleanup(&frequencies_ll);
+ uivector_cleanup(&frequencies_d);
+ uivector_cleanup(&frequencies_cl);
+ uivector_cleanup(&bitlen_lld_e);
+ uivector_cleanup(&bitlen_lld);
+ uivector_cleanup(&bitlen_cl);
+
+ return error;
+}
+
+static unsigned deflateFixed(ucvector* out, size_t* bp, Hash* hash,
+ const unsigned char* data,
+ size_t datapos, size_t dataend,
+ const LodePNGCompressSettings* settings, unsigned final) {
+ HuffmanTree tree_ll; /*tree for literal values and length codes*/
+ HuffmanTree tree_d; /*tree for distance codes*/
+
+ unsigned BFINAL = final;
+ unsigned error = 0;
+ size_t i;
+
+ HuffmanTree_init(&tree_ll);
+ HuffmanTree_init(&tree_d);
+
+ generateFixedLitLenTree(&tree_ll);
+ generateFixedDistanceTree(&tree_d);
+
+ addBitToStream(bp, out, BFINAL);
+ addBitToStream(bp, out, 1); /*first bit of BTYPE*/
+ addBitToStream(bp, out, 0); /*second bit of BTYPE*/
+
+ if(settings->use_lz77) /*LZ77 encoded*/ {
+ uivector lz77_encoded;
+ uivector_init(&lz77_encoded);
+ error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,
+ settings->minmatch, settings->nicematch, settings->lazymatching);
+ if(!error) writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);
+ uivector_cleanup(&lz77_encoded);
+ } else /*no LZ77, but still will be Huffman compressed*/ {
+ for(i = datapos; i < dataend; ++i) {
+ addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, data[i]), HuffmanTree_getLength(&tree_ll, data[i]));
+ }
+ }
+ /*add END code*/
+ if(!error) addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256));
+
+ /*cleanup*/
+ HuffmanTree_cleanup(&tree_ll);
+ HuffmanTree_cleanup(&tree_d);
+
+ return error;
+}
+
+static unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize,
+ const LodePNGCompressSettings* settings) {
+ unsigned error = 0;
+ size_t i, blocksize, numdeflateblocks;
+ size_t bp = 0; /*the bit pointer*/
+ Hash hash;
+
+ if(settings->btype > 2) return 61;
+ else if(settings->btype == 0) return deflateNoCompression(out, in, insize);
+ else if(settings->btype == 1) blocksize = insize;
+ else /*if(settings->btype == 2)*/ {
+ /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/
+ blocksize = insize / 8 + 8;
+ if(blocksize < 65536) blocksize = 65536;
+ if(blocksize > 262144) blocksize = 262144;
+ }
+
+ numdeflateblocks = (insize + blocksize - 1) / blocksize;
+ if(numdeflateblocks == 0) numdeflateblocks = 1;
+
+ error = hash_init(&hash, settings->windowsize);
+ if(error) return error;
+
+ for(i = 0; i != numdeflateblocks && !error; ++i) {
+ unsigned final = (i == numdeflateblocks - 1);
+ size_t start = i * blocksize;
+ size_t end = start + blocksize;
+ if(end > insize) end = insize;
+
+ if(settings->btype == 1) error = deflateFixed(out, &bp, &hash, in, start, end, settings, final);
+ else if(settings->btype == 2) error = deflateDynamic(out, &bp, &hash, in, start, end, settings, final);
+ }
+
+ hash_cleanup(&hash);
+
+ return error;
+}
+
+unsigned lodepng_deflate(unsigned char** out, size_t* outsize,
+ const unsigned char* in, size_t insize,
+ const LodePNGCompressSettings* settings) {
+ unsigned error;
+ ucvector v;
+ ucvector_init_buffer(&v, *out, *outsize);
+ error = lodepng_deflatev(&v, in, insize, settings);
+ *out = v.data;
+ *outsize = v.size;
+ return error;
+}
+
+static unsigned deflate(unsigned char** out, size_t* outsize,
+ const unsigned char* in, size_t insize,
+ const LodePNGCompressSettings* settings) {
+ if(settings->custom_deflate) {
+ return settings->custom_deflate(out, outsize, in, insize, settings);
+ } else {
+ return lodepng_deflate(out, outsize, in, insize, settings);
+ }
+}
+
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / Adler32 */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) {
+ unsigned s1 = adler & 0xffff;
+ unsigned s2 = (adler >> 16) & 0xffff;
+
+ while(len > 0) {
+ /*at least 5552 sums can be done before the sums overflow, saving a lot of module divisions*/
+ unsigned amount = len > 5552 ? 5552 : len;
+ len -= amount;
+ while(amount > 0) {
+ s1 += (*data++);
+ s2 += s1;
+ --amount;
+ }
+ s1 %= 65521;
+ s2 %= 65521;
+ }
+
+ return (s2 << 16) | s1;
+}
+
+/*Return the adler32 of the bytes data[0..len-1]*/
+static unsigned adler32(const unsigned char* data, unsigned len) {
+ return update_adler32(1L, data, len);
+}
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / Zlib / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+#ifdef LODEPNG_COMPILE_DECODER
+
+unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,
+ size_t insize, const LodePNGDecompressSettings* settings) {
+ unsigned error = 0;
+ unsigned CM, CINFO, FDICT;
+
+ if(insize < 2) return 53; /*error, size of zlib data too small*/
+ /*read information from zlib header*/
+ if((in[0] * 256 + in[1]) % 31 != 0) {
+ /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/
+ return 24;
+ }
+
+ CM = in[0] & 15;
+ CINFO = (in[0] >> 4) & 15;
+ /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/
+ FDICT = (in[1] >> 5) & 1;
+ /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/
+
+ if(CM != 8 || CINFO > 7) {
+ /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/
+ return 25;
+ }
+ if(FDICT != 0) {
+ /*error: the specification of PNG says about the zlib stream:
+ "The additional flags shall not specify a preset dictionary."*/
+ return 26;
+ }
+
+ error = inflate(out, outsize, in + 2, insize - 2, settings);
+ if(error) return error;
+
+ if(!settings->ignore_adler32) {
+ unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]);
+ unsigned checksum = adler32(*out, (unsigned)(*outsize));
+ if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/
+ }
+
+ return 0; /*no error*/
+}
+
+static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,
+ size_t insize, const LodePNGDecompressSettings* settings) {
+ if(settings->custom_zlib) {
+ return settings->custom_zlib(out, outsize, in, insize, settings);
+ } else {
+ return lodepng_zlib_decompress(out, outsize, in, insize, settings);
+ }
+}
+
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+#ifdef LODEPNG_COMPILE_ENCODER
+
+unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
+ size_t insize, const LodePNGCompressSettings* settings) {
+ /*initially, *out must be NULL and outsize 0, if you just give some random *out
+ that's pointing to a non allocated buffer, this'll crash*/
+ ucvector outv;
+ size_t i;
+ unsigned error;
+ unsigned char* deflatedata = 0;
+ size_t deflatesize = 0;
+
+ /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/
+ unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/
+ unsigned FLEVEL = 0;
+ unsigned FDICT = 0;
+ unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64;
+ unsigned FCHECK = 31 - CMFFLG % 31;
+ CMFFLG += FCHECK;
+
+ /*ucvector-controlled version of the output buffer, for dynamic array*/
+ ucvector_init_buffer(&outv, *out, *outsize);
+
+ ucvector_push_back(&outv, (unsigned char)(CMFFLG >> 8));
+ ucvector_push_back(&outv, (unsigned char)(CMFFLG & 255));
+
+ error = deflate(&deflatedata, &deflatesize, in, insize, settings);
+
+ if(!error) {
+ unsigned ADLER32 = adler32(in, (unsigned)insize);
+ for(i = 0; i != deflatesize; ++i) ucvector_push_back(&outv, deflatedata[i]);
+ lodepng_free(deflatedata);
+ lodepng_add32bitInt(&outv, ADLER32);
+ }
+
+ *out = outv.data;
+ *outsize = outv.size;
+
+ return error;
+}
+
+/* compress using the default or custom zlib function */
+static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
+ size_t insize, const LodePNGCompressSettings* settings) {
+ if(settings->custom_zlib) {
+ return settings->custom_zlib(out, outsize, in, insize, settings);
+ } else {
+ return lodepng_zlib_compress(out, outsize, in, insize, settings);
+ }
+}
+
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+#else /*no LODEPNG_COMPILE_ZLIB*/
+
+#ifdef LODEPNG_COMPILE_DECODER
+static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,
+ size_t insize, const LodePNGDecompressSettings* settings) {
+ if(!settings->custom_zlib) return 87; /*no custom zlib function provided */
+ return settings->custom_zlib(out, outsize, in, insize, settings);
+}
+#endif /*LODEPNG_COMPILE_DECODER*/
+#ifdef LODEPNG_COMPILE_ENCODER
+static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
+ size_t insize, const LodePNGCompressSettings* settings) {
+ if(!settings->custom_zlib) return 87; /*no custom zlib function provided */
+ return settings->custom_zlib(out, outsize, in, insize, settings);
+}
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+#endif /*LODEPNG_COMPILE_ZLIB*/
+
+/* ////////////////////////////////////////////////////////////////////////// */
+
+#ifdef LODEPNG_COMPILE_ENCODER
+
+/*this is a good tradeoff between speed and compression ratio*/
+#define DEFAULT_WINDOWSIZE 2048
+
+void lodepng_compress_settings_init(LodePNGCompressSettings* settings) {
+ /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/
+ settings->btype = 2;
+ settings->use_lz77 = 1;
+ settings->windowsize = DEFAULT_WINDOWSIZE;
+ settings->minmatch = 3;
+ settings->nicematch = 128;
+ settings->lazymatching = 1;
+
+ settings->custom_zlib = 0;
+ settings->custom_deflate = 0;
+ settings->custom_context = 0;
+}
+
+const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0};
+
+
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+#ifdef LODEPNG_COMPILE_DECODER
+
+void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) {
+ settings->ignore_adler32 = 0;
+
+ settings->custom_zlib = 0;
+ settings->custom_inflate = 0;
+ settings->custom_context = 0;
+}
+
+const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0};
+
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* ////////////////////////////////////////////////////////////////////////// */
+/* // End of Zlib related code. Begin of PNG related code. // */
+/* ////////////////////////////////////////////////////////////////////////// */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+#ifdef LODEPNG_COMPILE_PNG
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / CRC32 / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+
+#ifndef LODEPNG_NO_COMPILE_CRC
+/* CRC polynomial: 0xedb88320 */
+static unsigned lodepng_crc32_table[256] = {
+ 0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u,
+ 249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u,
+ 498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u,
+ 325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u,
+ 997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u,
+ 901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u,
+ 651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u,
+ 671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u,
+ 1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u,
+ 2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u,
+ 1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u,
+ 1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u,
+ 1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u,
+ 1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u,
+ 1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u,
+ 1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u,
+ 3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u,
+ 3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u,
+ 4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u,
+ 4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u,
+ 3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u,
+ 3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u,
+ 3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u,
+ 3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u,
+ 2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u,
+ 2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u,
+ 2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u,
+ 2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u,
+ 2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u,
+ 2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u,
+ 3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u,
+ 3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u
+};
+
+/*Return the CRC of the bytes buf[0..len-1].*/
+unsigned lodepng_crc32(const unsigned char* data, size_t length) {
+ unsigned r = 0xffffffffu;
+ size_t i;
+ for(i = 0; i < length; ++i) {
+ r = lodepng_crc32_table[(r ^ data[i]) & 0xff] ^ (r >> 8);
+ }
+ return r ^ 0xffffffffu;
+}
+#else /* !LODEPNG_NO_COMPILE_CRC */
+unsigned lodepng_crc32(const unsigned char* data, size_t length);
+#endif /* !LODEPNG_NO_COMPILE_CRC */
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / Reading and writing single bits and bytes from/to stream for LodePNG / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) {
+ unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1);
+ ++(*bitpointer);
+ return result;
+}
+
+static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) {
+ unsigned result = 0;
+ size_t i;
+ for(i = 0 ; i < nbits; ++i) {
+ result <<= 1;
+ result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream);
+ }
+ return result;
+}
+
+#ifdef LODEPNG_COMPILE_DECODER
+static void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) {
+ /*the current bit in bitstream must be 0 for this to work*/
+ if(bit) {
+ /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/
+ bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7)));
+ }
+ ++(*bitpointer);
+}
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) {
+ /*the current bit in bitstream may be 0 or 1 for this to work*/
+ if(bit == 0) bitstream[(*bitpointer) >> 3] &= (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7))));
+ else bitstream[(*bitpointer) >> 3] |= (1 << (7 - ((*bitpointer) & 0x7)));
+ ++(*bitpointer);
+}
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / PNG chunks / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+unsigned lodepng_chunk_length(const unsigned char* chunk) {
+ return lodepng_read32bitInt(&chunk[0]);
+}
+
+void lodepng_chunk_type(char type[5], const unsigned char* chunk) {
+ unsigned i;
+ for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i];
+ type[4] = 0; /*null termination char*/
+}
+
+unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type) {
+ if(strlen(type) != 4) return 0;
+ return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]);
+}
+
+unsigned char lodepng_chunk_ancillary(const unsigned char* chunk) {
+ return((chunk[4] & 32) != 0);
+}
+
+unsigned char lodepng_chunk_private(const unsigned char* chunk) {
+ return((chunk[6] & 32) != 0);
+}
+
+unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk) {
+ return((chunk[7] & 32) != 0);
+}
+
+unsigned char* lodepng_chunk_data(unsigned char* chunk) {
+ return &chunk[8];
+}
+
+const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk) {
+ return &chunk[8];
+}
+
+unsigned lodepng_chunk_check_crc(const unsigned char* chunk) {
+ unsigned length = lodepng_chunk_length(chunk);
+ unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]);
+ /*the CRC is taken of the data and the 4 chunk type letters, not the length*/
+ unsigned checksum = lodepng_crc32(&chunk[4], length + 4);
+ if(CRC != checksum) return 1;
+ else return 0;
+}
+
+void lodepng_chunk_generate_crc(unsigned char* chunk) {
+ unsigned length = lodepng_chunk_length(chunk);
+ unsigned CRC = lodepng_crc32(&chunk[4], length + 4);
+ lodepng_set32bitInt(chunk + 8 + length, CRC);
+}
+
+unsigned char* lodepng_chunk_next(unsigned char* chunk) {
+ if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47
+ && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) {
+ /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */
+ return chunk + 8;
+ } else {
+ unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
+ return chunk + total_chunk_length;
+ }
+}
+
+const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk) {
+ if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47
+ && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) {
+ /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */
+ return chunk + 8;
+ } else {
+ unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
+ return chunk + total_chunk_length;
+ }
+}
+
+unsigned char* lodepng_chunk_find(unsigned char* chunk, const unsigned char* end, const char type[5]) {
+ for(;;) {
+ if(chunk + 12 >= end) return 0;
+ if(lodepng_chunk_type_equals(chunk, type)) return chunk;
+ chunk = lodepng_chunk_next(chunk);
+ }
+}
+
+const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) {
+ for(;;) {
+ if(chunk + 12 >= end) return 0;
+ if(lodepng_chunk_type_equals(chunk, type)) return chunk;
+ chunk = lodepng_chunk_next_const(chunk);
+ }
+}
+
+unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk) {
+ unsigned i;
+ unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
+ unsigned char *chunk_start, *new_buffer;
+ size_t new_length = (*outlength) + total_chunk_length;
+ if(new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/
+
+ new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);
+ if(!new_buffer) return 83; /*alloc fail*/
+ (*out) = new_buffer;
+ (*outlength) = new_length;
+ chunk_start = &(*out)[new_length - total_chunk_length];
+
+ for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i];
+
+ return 0;
+}
+
+unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,
+ const char* type, const unsigned char* data) {
+ unsigned i;
+ unsigned char *chunk, *new_buffer;
+ size_t new_length = (*outlength) + length + 12;
+ if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/
+ new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);
+ if(!new_buffer) return 83; /*alloc fail*/
+ (*out) = new_buffer;
+ (*outlength) = new_length;
+ chunk = &(*out)[(*outlength) - length - 12];
+
+ /*1: length*/
+ lodepng_set32bitInt(chunk, (unsigned)length);
+
+ /*2: chunk name (4 letters)*/
+ chunk[4] = (unsigned char)type[0];
+ chunk[5] = (unsigned char)type[1];
+ chunk[6] = (unsigned char)type[2];
+ chunk[7] = (unsigned char)type[3];
+
+ /*3: the data*/
+ for(i = 0; i != length; ++i) chunk[8 + i] = data[i];
+
+ /*4: CRC (of the chunkname characters and the data)*/
+ lodepng_chunk_generate_crc(chunk);
+
+ return 0;
+}
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / Color types and such / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+/*return type is a LodePNG error code*/
+static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) /*bd = bitdepth*/ {
+ switch(colortype) {
+ case 0: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*gray*/
+ case 2: if(!( bd == 8 || bd == 16)) return 37; break; /*RGB*/
+ case 3: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; /*palette*/
+ case 4: if(!( bd == 8 || bd == 16)) return 37; break; /*gray + alpha*/
+ case 6: if(!( bd == 8 || bd == 16)) return 37; break; /*RGBA*/
+ default: return 31;
+ }
+ return 0; /*allowed color type / bits combination*/
+}
+
+static unsigned getNumColorChannels(LodePNGColorType colortype) {
+ switch(colortype) {
+ case 0: return 1; /*gray*/
+ case 2: return 3; /*RGB*/
+ case 3: return 1; /*palette*/
+ case 4: return 2; /*gray + alpha*/
+ case 6: return 4; /*RGBA*/
+ }
+ return 0; /*unexisting color type*/
+}
+
+static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) {
+ /*bits per pixel is amount of channels * bits per channel*/
+ return getNumColorChannels(colortype) * bitdepth;
+}
+
+/* ////////////////////////////////////////////////////////////////////////// */
+
+void lodepng_color_mode_init(LodePNGColorMode* info) {
+ info->key_defined = 0;
+ info->key_r = info->key_g = info->key_b = 0;
+ info->colortype = LCT_RGBA;
+ info->bitdepth = 8;
+ info->palette = 0;
+ info->palettesize = 0;
+}
+
+void lodepng_color_mode_cleanup(LodePNGColorMode* info) {
+ lodepng_palette_clear(info);
+}
+
+unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source) {
+ size_t i;
+ lodepng_color_mode_cleanup(dest);
+ *dest = *source;
+ if(source->palette) {
+ dest->palette = (unsigned char*)lodepng_malloc(1024);
+ if(!dest->palette && source->palettesize) return 83; /*alloc fail*/
+ for(i = 0; i != source->palettesize * 4; ++i) dest->palette[i] = source->palette[i];
+ }
+ return 0;
+}
+
+LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth) {
+ LodePNGColorMode result;
+ lodepng_color_mode_init(&result);
+ result.colortype = colortype;
+ result.bitdepth = bitdepth;
+ return result;
+}
+
+static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b) {
+ size_t i;
+ if(a->colortype != b->colortype) return 0;
+ if(a->bitdepth != b->bitdepth) return 0;
+ if(a->key_defined != b->key_defined) return 0;
+ if(a->key_defined) {
+ if(a->key_r != b->key_r) return 0;
+ if(a->key_g != b->key_g) return 0;
+ if(a->key_b != b->key_b) return 0;
+ }
+ if(a->palettesize != b->palettesize) return 0;
+ for(i = 0; i != a->palettesize * 4; ++i) {
+ if(a->palette[i] != b->palette[i]) return 0;
+ }
+ return 1;
+}
+
+void lodepng_palette_clear(LodePNGColorMode* info) {
+ if(info->palette) lodepng_free(info->palette);
+ info->palette = 0;
+ info->palettesize = 0;
+}
+
+unsigned lodepng_palette_add(LodePNGColorMode* info,
+ unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
+ unsigned char* data;
+ /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with
+ the max of 256 colors, it'll have the exact alloc size*/
+ if(!info->palette) /*allocate palette if empty*/ {
+ /*room for 256 colors with 4 bytes each*/
+ data = (unsigned char*)lodepng_realloc(info->palette, 1024);
+ if(!data) return 83; /*alloc fail*/
+ else info->palette = data;
+ }
+ info->palette[4 * info->palettesize + 0] = r;
+ info->palette[4 * info->palettesize + 1] = g;
+ info->palette[4 * info->palettesize + 2] = b;
+ info->palette[4 * info->palettesize + 3] = a;
+ ++info->palettesize;
+ return 0;
+}
+
+/*calculate bits per pixel out of colortype and bitdepth*/
+unsigned lodepng_get_bpp(const LodePNGColorMode* info) {
+ return lodepng_get_bpp_lct(info->colortype, info->bitdepth);
+}
+
+unsigned lodepng_get_channels(const LodePNGColorMode* info) {
+ return getNumColorChannels(info->colortype);
+}
+
+unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info) {
+ return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA;
+}
+
+unsigned lodepng_is_alpha_type(const LodePNGColorMode* info) {
+ return (info->colortype & 4) != 0; /*4 or 6*/
+}
+
+unsigned lodepng_is_palette_type(const LodePNGColorMode* info) {
+ return info->colortype == LCT_PALETTE;
+}
+
+unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info) {
+ size_t i;
+ for(i = 0; i != info->palettesize; ++i) {
+ if(info->palette[i * 4 + 3] < 255) return 1;
+ }
+ return 0;
+}
+
+unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) {
+ return info->key_defined
+ || lodepng_is_alpha_type(info)
+ || lodepng_has_palette_alpha(info);
+}
+
+size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) {
+ size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth);
+ size_t n = (size_t)w * (size_t)h;
+ return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8;
+}
+
+size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) {
+ return lodepng_get_raw_size_lct(w, h, color->colortype, color->bitdepth);
+}
+
+
+#ifdef LODEPNG_COMPILE_PNG
+#ifdef LODEPNG_COMPILE_DECODER
+
+/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer,
+and in addition has one extra byte per line: the filter byte. So this gives a larger
+result than lodepng_get_raw_size. */
+static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, const LodePNGColorMode* color) {
+ size_t bpp = lodepng_get_bpp(color);
+ /* + 1 for the filter byte, and possibly plus padding bits per line */
+ size_t line = ((size_t)(w / 8) * bpp) + 1 + ((w & 7) * bpp + 7) / 8;
+ return (size_t)h * line;
+}
+
+/* Safely check if multiplying two integers will overflow (no undefined
+behavior, compiler removing the code, etc...) and output result. */
+static int lodepng_mulofl(size_t a, size_t b, size_t* result) {
+ *result = a * b; /* Unsigned multiplication is well defined and safe in C90 */
+ return (a != 0 && *result / a != b);
+}
+
+/* Safely check if adding two integers will overflow (no undefined
+behavior, compiler removing the code, etc...) and output result. */
+static int lodepng_addofl(size_t a, size_t b, size_t* result) {
+ *result = a + b; /* Unsigned addition is well defined and safe in C90 */
+ return *result < a;
+}
+
+/*Safely checks whether size_t overflow can be caused due to amount of pixels.
+This check is overcautious rather than precise. If this check indicates no overflow,
+you can safely compute in a size_t (but not an unsigned):
+-(size_t)w * (size_t)h * 8
+-amount of bytes in IDAT (including filter, padding and Adam7 bytes)
+-amount of bytes in raw color model
+Returns 1 if overflow possible, 0 if not.
+*/
+static int lodepng_pixel_overflow(unsigned w, unsigned h,
+ const LodePNGColorMode* pngcolor, const LodePNGColorMode* rawcolor) {
+ size_t bpp = LODEPNG_MAX(lodepng_get_bpp(pngcolor), lodepng_get_bpp(rawcolor));
+ size_t numpixels, total;
+ size_t line; /* bytes per line in worst case */
+
+ if(lodepng_mulofl((size_t)w, (size_t)h, &numpixels)) return 1;
+ if(lodepng_mulofl(numpixels, 8, &total)) return 1; /* bit pointer with 8-bit color, or 8 bytes per channel color */
+
+ /* Bytes per scanline with the expression "(w / 8) * bpp) + ((w & 7) * bpp + 7) / 8" */
+ if(lodepng_mulofl((size_t)(w / 8), bpp, &line)) return 1;
+ if(lodepng_addofl(line, ((w & 7) * bpp + 7) / 8, &line)) return 1;
+
+ if(lodepng_addofl(line, 5, &line)) return 1; /* 5 bytes overhead per line: 1 filterbyte, 4 for Adam7 worst case */
+ if(lodepng_mulofl(line, h, &total)) return 1; /* Total bytes in worst case */
+
+ return 0; /* no overflow */
+}
+#endif /*LODEPNG_COMPILE_DECODER*/
+#endif /*LODEPNG_COMPILE_PNG*/
+
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+
+static void LodePNGUnknownChunks_init(LodePNGInfo* info) {
+ unsigned i;
+ for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0;
+ for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0;
+}
+
+static void LodePNGUnknownChunks_cleanup(LodePNGInfo* info) {
+ unsigned i;
+ for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]);
+}
+
+static unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src) {
+ unsigned i;
+
+ LodePNGUnknownChunks_cleanup(dest);
+
+ for(i = 0; i != 3; ++i) {
+ size_t j;
+ dest->unknown_chunks_size[i] = src->unknown_chunks_size[i];
+ dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]);
+ if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/
+ for(j = 0; j < src->unknown_chunks_size[i]; ++j) {
+ dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j];
+ }
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+
+static void LodePNGText_init(LodePNGInfo* info) {
+ info->text_num = 0;
+ info->text_keys = NULL;
+ info->text_strings = NULL;
+}
+
+static void LodePNGText_cleanup(LodePNGInfo* info) {
+ size_t i;
+ for(i = 0; i != info->text_num; ++i) {
+ string_cleanup(&info->text_keys[i]);
+ string_cleanup(&info->text_strings[i]);
+ }
+ lodepng_free(info->text_keys);
+ lodepng_free(info->text_strings);
+}
+
+static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
+ size_t i = 0;
+ dest->text_keys = 0;
+ dest->text_strings = 0;
+ dest->text_num = 0;
+ for(i = 0; i != source->text_num; ++i) {
+ CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));
+ }
+ return 0;
+}
+
+void lodepng_clear_text(LodePNGInfo* info) {
+ LodePNGText_cleanup(info);
+}
+
+unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str) {
+ char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1)));
+ char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1)));
+ if(!new_keys || !new_strings) {
+ lodepng_free(new_keys);
+ lodepng_free(new_strings);
+ return 83; /*alloc fail*/
+ }
+
+ ++info->text_num;
+ info->text_keys = new_keys;
+ info->text_strings = new_strings;
+
+ info->text_keys[info->text_num - 1] = alloc_string(key);
+ info->text_strings[info->text_num - 1] = alloc_string(str);
+
+ return 0;
+}
+
+/******************************************************************************/
+
+static void LodePNGIText_init(LodePNGInfo* info) {
+ info->itext_num = 0;
+ info->itext_keys = NULL;
+ info->itext_langtags = NULL;
+ info->itext_transkeys = NULL;
+ info->itext_strings = NULL;
+}
+
+static void LodePNGIText_cleanup(LodePNGInfo* info) {
+ size_t i;
+ for(i = 0; i != info->itext_num; ++i) {
+ string_cleanup(&info->itext_keys[i]);
+ string_cleanup(&info->itext_langtags[i]);
+ string_cleanup(&info->itext_transkeys[i]);
+ string_cleanup(&info->itext_strings[i]);
+ }
+ lodepng_free(info->itext_keys);
+ lodepng_free(info->itext_langtags);
+ lodepng_free(info->itext_transkeys);
+ lodepng_free(info->itext_strings);
+}
+
+static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
+ size_t i = 0;
+ dest->itext_keys = 0;
+ dest->itext_langtags = 0;
+ dest->itext_transkeys = 0;
+ dest->itext_strings = 0;
+ dest->itext_num = 0;
+ for(i = 0; i != source->itext_num; ++i) {
+ CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],
+ source->itext_transkeys[i], source->itext_strings[i]));
+ }
+ return 0;
+}
+
+void lodepng_clear_itext(LodePNGInfo* info) {
+ LodePNGIText_cleanup(info);
+}
+
+unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,
+ const char* transkey, const char* str) {
+ char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1)));
+ char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1)));
+ char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1)));
+ char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1)));
+ if(!new_keys || !new_langtags || !new_transkeys || !new_strings) {
+ lodepng_free(new_keys);
+ lodepng_free(new_langtags);
+ lodepng_free(new_transkeys);
+ lodepng_free(new_strings);
+ return 83; /*alloc fail*/
+ }
+
+ ++info->itext_num;
+ info->itext_keys = new_keys;
+ info->itext_langtags = new_langtags;
+ info->itext_transkeys = new_transkeys;
+ info->itext_strings = new_strings;
+
+ info->itext_keys[info->itext_num - 1] = alloc_string(key);
+ info->itext_langtags[info->itext_num - 1] = alloc_string(langtag);
+ info->itext_transkeys[info->itext_num - 1] = alloc_string(transkey);
+ info->itext_strings[info->itext_num - 1] = alloc_string(str);
+
+ return 0;
+}
+
+/* same as set but does not delete */
+static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) {
+ info->iccp_name = alloc_string(name);
+ info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size);
+
+ if(!info->iccp_name || !info->iccp_profile) return 83; /*alloc fail*/
+
+ memcpy(info->iccp_profile, profile, profile_size);
+ info->iccp_profile_size = profile_size;
+
+ return 0; /*ok*/
+}
+
+unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) {
+ if(info->iccp_name) lodepng_clear_icc(info);
+ info->iccp_defined = 1;
+
+ return lodepng_assign_icc(info, name, profile, profile_size);
+}
+
+void lodepng_clear_icc(LodePNGInfo* info) {
+ string_cleanup(&info->iccp_name);
+ lodepng_free(info->iccp_profile);
+ info->iccp_profile = NULL;
+ info->iccp_profile_size = 0;
+ info->iccp_defined = 0;
+}
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+
+void lodepng_info_init(LodePNGInfo* info) {
+ lodepng_color_mode_init(&info->color);
+ info->interlace_method = 0;
+ info->compression_method = 0;
+ info->filter_method = 0;
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ info->background_defined = 0;
+ info->background_r = info->background_g = info->background_b = 0;
+
+ LodePNGText_init(info);
+ LodePNGIText_init(info);
+
+ info->time_defined = 0;
+ info->phys_defined = 0;
+
+ info->gama_defined = 0;
+ info->chrm_defined = 0;
+ info->srgb_defined = 0;
+ info->iccp_defined = 0;
+ info->iccp_name = NULL;
+ info->iccp_profile = NULL;
+
+ LodePNGUnknownChunks_init(info);
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+}
+
+void lodepng_info_cleanup(LodePNGInfo* info) {
+ lodepng_color_mode_cleanup(&info->color);
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ LodePNGText_cleanup(info);
+ LodePNGIText_cleanup(info);
+
+ lodepng_clear_icc(info);
+
+ LodePNGUnknownChunks_cleanup(info);
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+}
+
+unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
+ lodepng_info_cleanup(dest);
+ *dest = *source;
+ lodepng_color_mode_init(&dest->color);
+ CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color));
+
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ CERROR_TRY_RETURN(LodePNGText_copy(dest, source));
+ CERROR_TRY_RETURN(LodePNGIText_copy(dest, source));
+ if(source->iccp_defined) {
+ CERROR_TRY_RETURN(lodepng_assign_icc(dest, source->iccp_name, source->iccp_profile, source->iccp_profile_size));
+ }
+
+ LodePNGUnknownChunks_init(dest);
+ CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source));
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ return 0;
+}
+
+/* ////////////////////////////////////////////////////////////////////////// */
+
+/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/
+static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) {
+ unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/
+ /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/
+ unsigned p = index & m;
+ in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/
+ in = in << (bits * (m - p));
+ if(p == 0) out[index * bits / 8] = in;
+ else out[index * bits / 8] |= in;
+}
+
+typedef struct ColorTree ColorTree;
+
+/*
+One node of a color tree
+This is the data structure used to count the number of unique colors and to get a palette
+index for a color. It's like an octree, but because the alpha channel is used too, each
+node has 16 instead of 8 children.
+*/
+struct ColorTree {
+ ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/
+ int index; /*the payload. Only has a meaningful value if this is in the last level*/
+};
+
+static void color_tree_init(ColorTree* tree) {
+ int i;
+ for(i = 0; i != 16; ++i) tree->children[i] = 0;
+ tree->index = -1;
+}
+
+static void color_tree_cleanup(ColorTree* tree) {
+ int i;
+ for(i = 0; i != 16; ++i) {
+ if(tree->children[i]) {
+ color_tree_cleanup(tree->children[i]);
+ lodepng_free(tree->children[i]);
+ }
+ }
+}
+
+/*returns -1 if color not present, its index otherwise*/
+static int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
+ int bit = 0;
+ for(bit = 0; bit < 8; ++bit) {
+ int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);
+ if(!tree->children[i]) return -1;
+ else tree = tree->children[i];
+ }
+ return tree ? tree->index : -1;
+}
+
+#ifdef LODEPNG_COMPILE_ENCODER
+static int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
+ return color_tree_get(tree, r, g, b, a) >= 0;
+}
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+/*color is not allowed to already exist.
+Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist")*/
+static void color_tree_add(ColorTree* tree,
+ unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) {
+ int bit;
+ for(bit = 0; bit < 8; ++bit) {
+ int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);
+ if(!tree->children[i]) {
+ tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree));
+ color_tree_init(tree->children[i]);
+ }
+ tree = tree->children[i];
+ }
+ tree->index = (int)index;
+}
+
+/*put a pixel, given its RGBA color, into image of any color type*/
+static unsigned rgba8ToPixel(unsigned char* out, size_t i,
+ const LodePNGColorMode* mode, ColorTree* tree /*for palette*/,
+ unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
+ if(mode->colortype == LCT_GREY) {
+ unsigned char gray = r; /*((unsigned short)r + g + b) / 3;*/
+ if(mode->bitdepth == 8) out[i] = gray;
+ else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = gray;
+ else {
+ /*take the most significant bits of gray*/
+ gray = (gray >> (8 - mode->bitdepth)) & ((1 << mode->bitdepth) - 1);
+ addColorBits(out, i, mode->bitdepth, gray);
+ }
+ } else if(mode->colortype == LCT_RGB) {
+ if(mode->bitdepth == 8) {
+ out[i * 3 + 0] = r;
+ out[i * 3 + 1] = g;
+ out[i * 3 + 2] = b;
+ } else {
+ out[i * 6 + 0] = out[i * 6 + 1] = r;
+ out[i * 6 + 2] = out[i * 6 + 3] = g;
+ out[i * 6 + 4] = out[i * 6 + 5] = b;
+ }
+ } else if(mode->colortype == LCT_PALETTE) {
+ int index = color_tree_get(tree, r, g, b, a);
+ if(index < 0) return 82; /*color not in palette*/
+ if(mode->bitdepth == 8) out[i] = index;
+ else addColorBits(out, i, mode->bitdepth, (unsigned)index);
+ } else if(mode->colortype == LCT_GREY_ALPHA) {
+ unsigned char gray = r; /*((unsigned short)r + g + b) / 3;*/
+ if(mode->bitdepth == 8) {
+ out[i * 2 + 0] = gray;
+ out[i * 2 + 1] = a;
+ } else if(mode->bitdepth == 16) {
+ out[i * 4 + 0] = out[i * 4 + 1] = gray;
+ out[i * 4 + 2] = out[i * 4 + 3] = a;
+ }
+ } else if(mode->colortype == LCT_RGBA) {
+ if(mode->bitdepth == 8) {
+ out[i * 4 + 0] = r;
+ out[i * 4 + 1] = g;
+ out[i * 4 + 2] = b;
+ out[i * 4 + 3] = a;
+ } else {
+ out[i * 8 + 0] = out[i * 8 + 1] = r;
+ out[i * 8 + 2] = out[i * 8 + 3] = g;
+ out[i * 8 + 4] = out[i * 8 + 5] = b;
+ out[i * 8 + 6] = out[i * 8 + 7] = a;
+ }
+ }
+
+ return 0; /*no error*/
+}
+
+/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/
+static void rgba16ToPixel(unsigned char* out, size_t i,
+ const LodePNGColorMode* mode,
+ unsigned short r, unsigned short g, unsigned short b, unsigned short a) {
+ if(mode->colortype == LCT_GREY) {
+ unsigned short gray = r; /*((unsigned)r + g + b) / 3;*/
+ out[i * 2 + 0] = (gray >> 8) & 255;
+ out[i * 2 + 1] = gray & 255;
+ } else if(mode->colortype == LCT_RGB) {
+ out[i * 6 + 0] = (r >> 8) & 255;
+ out[i * 6 + 1] = r & 255;
+ out[i * 6 + 2] = (g >> 8) & 255;
+ out[i * 6 + 3] = g & 255;
+ out[i * 6 + 4] = (b >> 8) & 255;
+ out[i * 6 + 5] = b & 255;
+ } else if(mode->colortype == LCT_GREY_ALPHA) {
+ unsigned short gray = r; /*((unsigned)r + g + b) / 3;*/
+ out[i * 4 + 0] = (gray >> 8) & 255;
+ out[i * 4 + 1] = gray & 255;
+ out[i * 4 + 2] = (a >> 8) & 255;
+ out[i * 4 + 3] = a & 255;
+ } else if(mode->colortype == LCT_RGBA) {
+ out[i * 8 + 0] = (r >> 8) & 255;
+ out[i * 8 + 1] = r & 255;
+ out[i * 8 + 2] = (g >> 8) & 255;
+ out[i * 8 + 3] = g & 255;
+ out[i * 8 + 4] = (b >> 8) & 255;
+ out[i * 8 + 5] = b & 255;
+ out[i * 8 + 6] = (a >> 8) & 255;
+ out[i * 8 + 7] = a & 255;
+ }
+}
+
+/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/
+static void getPixelColorRGBA8(unsigned char* r, unsigned char* g,
+ unsigned char* b, unsigned char* a,
+ const unsigned char* in, size_t i,
+ const LodePNGColorMode* mode) {
+ if(mode->colortype == LCT_GREY) {
+ if(mode->bitdepth == 8) {
+ *r = *g = *b = in[i];
+ if(mode->key_defined && *r == mode->key_r) *a = 0;
+ else *a = 255;
+ } else if(mode->bitdepth == 16) {
+ *r = *g = *b = in[i * 2 + 0];
+ if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;
+ else *a = 255;
+ } else {
+ unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/
+ size_t j = i * mode->bitdepth;
+ unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);
+ *r = *g = *b = (value * 255) / highest;
+ if(mode->key_defined && value == mode->key_r) *a = 0;
+ else *a = 255;
+ }
+ } else if(mode->colortype == LCT_RGB) {
+ if(mode->bitdepth == 8) {
+ *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2];
+ if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0;
+ else *a = 255;
+ } else {
+ *r = in[i * 6 + 0];
+ *g = in[i * 6 + 2];
+ *b = in[i * 6 + 4];
+ if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
+ && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
+ && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;
+ else *a = 255;
+ }
+ } else if(mode->colortype == LCT_PALETTE) {
+ unsigned index;
+ if(mode->bitdepth == 8) index = in[i];
+ else {
+ size_t j = i * mode->bitdepth;
+ index = readBitsFromReversedStream(&j, in, mode->bitdepth);
+ }
+
+ if(index >= mode->palettesize) {
+ /*This is an error according to the PNG spec, but common PNG decoders make it black instead.
+ Done here too, slightly faster due to no error handling needed.*/
+ *r = *g = *b = 0;
+ *a = 255;
+ } else {
+ *r = mode->palette[index * 4 + 0];
+ *g = mode->palette[index * 4 + 1];
+ *b = mode->palette[index * 4 + 2];
+ *a = mode->palette[index * 4 + 3];
+ }
+ } else if(mode->colortype == LCT_GREY_ALPHA) {
+ if(mode->bitdepth == 8) {
+ *r = *g = *b = in[i * 2 + 0];
+ *a = in[i * 2 + 1];
+ } else {
+ *r = *g = *b = in[i * 4 + 0];
+ *a = in[i * 4 + 2];
+ }
+ } else if(mode->colortype == LCT_RGBA) {
+ if(mode->bitdepth == 8) {
+ *r = in[i * 4 + 0];
+ *g = in[i * 4 + 1];
+ *b = in[i * 4 + 2];
+ *a = in[i * 4 + 3];
+ } else {
+ *r = in[i * 8 + 0];
+ *g = in[i * 8 + 2];
+ *b = in[i * 8 + 4];
+ *a = in[i * 8 + 6];
+ }
+ }
+}
+
+/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color
+mode test cases, optimized to convert the colors much faster, when converting
+to RGBA or RGB with 8 bit per cannel. buffer must be RGBA or RGB output with
+enough memory, if has_alpha is true the output is RGBA. mode has the color mode
+of the input buffer.*/
+static void getPixelColorsRGBA8(unsigned char* buffer, size_t numpixels,
+ unsigned has_alpha, const unsigned char* in,
+ const LodePNGColorMode* mode) {
+ unsigned num_channels = has_alpha ? 4 : 3;
+ size_t i;
+ if(mode->colortype == LCT_GREY) {
+ if(mode->bitdepth == 8) {
+ for(i = 0; i != numpixels; ++i, buffer += num_channels) {
+ buffer[0] = buffer[1] = buffer[2] = in[i];
+ if(has_alpha) buffer[3] = mode->key_defined && in[i] == mode->key_r ? 0 : 255;
+ }
+ } else if(mode->bitdepth == 16) {
+ for(i = 0; i != numpixels; ++i, buffer += num_channels) {
+ buffer[0] = buffer[1] = buffer[2] = in[i * 2];
+ if(has_alpha) buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255;
+ }
+ } else {
+ unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/
+ size_t j = 0;
+ for(i = 0; i != numpixels; ++i, buffer += num_channels) {
+ unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);
+ buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest;
+ if(has_alpha) buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255;
+ }
+ }
+ } else if(mode->colortype == LCT_RGB) {
+ if(mode->bitdepth == 8) {
+ for(i = 0; i != numpixels; ++i, buffer += num_channels) {
+ buffer[0] = in[i * 3 + 0];
+ buffer[1] = in[i * 3 + 1];
+ buffer[2] = in[i * 3 + 2];
+ if(has_alpha) buffer[3] = mode->key_defined && buffer[0] == mode->key_r
+ && buffer[1]== mode->key_g && buffer[2] == mode->key_b ? 0 : 255;
+ }
+ } else {
+ for(i = 0; i != numpixels; ++i, buffer += num_channels) {
+ buffer[0] = in[i * 6 + 0];
+ buffer[1] = in[i * 6 + 2];
+ buffer[2] = in[i * 6 + 4];
+ if(has_alpha) buffer[3] = mode->key_defined
+ && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
+ && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
+ && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255;
+ }
+ }
+ } else if(mode->colortype == LCT_PALETTE) {
+ unsigned index;
+ size_t j = 0;
+ for(i = 0; i != numpixels; ++i, buffer += num_channels) {
+ if(mode->bitdepth == 8) index = in[i];
+ else index = readBitsFromReversedStream(&j, in, mode->bitdepth);
+
+ if(index >= mode->palettesize) {
+ /*This is an error according to the PNG spec, but most PNG decoders make it black instead.
+ Done here too, slightly faster due to no error handling needed.*/
+ buffer[0] = buffer[1] = buffer[2] = 0;
+ if(has_alpha) buffer[3] = 255;
+ } else {
+ buffer[0] = mode->palette[index * 4 + 0];
+ buffer[1] = mode->palette[index * 4 + 1];
+ buffer[2] = mode->palette[index * 4 + 2];
+ if(has_alpha) buffer[3] = mode->palette[index * 4 + 3];
+ }
+ }
+ } else if(mode->colortype == LCT_GREY_ALPHA) {
+ if(mode->bitdepth == 8) {
+ for(i = 0; i != numpixels; ++i, buffer += num_channels) {
+ buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0];
+ if(has_alpha) buffer[3] = in[i * 2 + 1];
+ }
+ } else {
+ for(i = 0; i != numpixels; ++i, buffer += num_channels) {
+ buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0];
+ if(has_alpha) buffer[3] = in[i * 4 + 2];
+ }
+ }
+ } else if(mode->colortype == LCT_RGBA) {
+ if(mode->bitdepth == 8) {
+ for(i = 0; i != numpixels; ++i, buffer += num_channels) {
+ buffer[0] = in[i * 4 + 0];
+ buffer[1] = in[i * 4 + 1];
+ buffer[2] = in[i * 4 + 2];
+ if(has_alpha) buffer[3] = in[i * 4 + 3];
+ }
+ } else {
+ for(i = 0; i != numpixels; ++i, buffer += num_channels) {
+ buffer[0] = in[i * 8 + 0];
+ buffer[1] = in[i * 8 + 2];
+ buffer[2] = in[i * 8 + 4];
+ if(has_alpha) buffer[3] = in[i * 8 + 6];
+ }
+ }
+ }
+}
+
+/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with
+given color type, but the given color type must be 16-bit itself.*/
+static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a,
+ const unsigned char* in, size_t i, const LodePNGColorMode* mode) {
+ if(mode->colortype == LCT_GREY) {
+ *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1];
+ if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;
+ else *a = 65535;
+ } else if(mode->colortype == LCT_RGB) {
+ *r = 256u * in[i * 6 + 0] + in[i * 6 + 1];
+ *g = 256u * in[i * 6 + 2] + in[i * 6 + 3];
+ *b = 256u * in[i * 6 + 4] + in[i * 6 + 5];
+ if(mode->key_defined
+ && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
+ && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
+ && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;
+ else *a = 65535;
+ } else if(mode->colortype == LCT_GREY_ALPHA) {
+ *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1];
+ *a = 256u * in[i * 4 + 2] + in[i * 4 + 3];
+ } else if(mode->colortype == LCT_RGBA) {
+ *r = 256u * in[i * 8 + 0] + in[i * 8 + 1];
+ *g = 256u * in[i * 8 + 2] + in[i * 8 + 3];
+ *b = 256u * in[i * 8 + 4] + in[i * 8 + 5];
+ *a = 256u * in[i * 8 + 6] + in[i * 8 + 7];
+ }
+}
+
+unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
+ const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
+ unsigned w, unsigned h) {
+ size_t i;
+ ColorTree tree;
+ size_t numpixels = (size_t)w * (size_t)h;
+ unsigned error = 0;
+
+ if(lodepng_color_mode_equal(mode_out, mode_in)) {
+ size_t numbytes = lodepng_get_raw_size(w, h, mode_in);
+ for(i = 0; i != numbytes; ++i) out[i] = in[i];
+ return 0;
+ }
+
+ if(mode_out->colortype == LCT_PALETTE) {
+ size_t palettesize = mode_out->palettesize;
+ const unsigned char* palette = mode_out->palette;
+ size_t palsize = (size_t)1u << mode_out->bitdepth;
+ /*if the user specified output palette but did not give the values, assume
+ they want the values of the input color type (assuming that one is palette).
+ Note that we never create a new palette ourselves.*/
+ if(palettesize == 0) {
+ palettesize = mode_in->palettesize;
+ palette = mode_in->palette;
+ /*if the input was also palette with same bitdepth, then the color types are also
+ equal, so copy literally. This to preserve the exact indices that were in the PNG
+ even in case there are duplicate colors in the palette.*/
+ if (mode_in->colortype == LCT_PALETTE && mode_in->bitdepth == mode_out->bitdepth) {
+ size_t numbytes = lodepng_get_raw_size(w, h, mode_in);
+ for(i = 0; i != numbytes; ++i) out[i] = in[i];
+ return 0;
+ }
+ }
+ if(palettesize < palsize) palsize = palettesize;
+ color_tree_init(&tree);
+ for(i = 0; i != palsize; ++i) {
+ const unsigned char* p = &palette[i * 4];
+ color_tree_add(&tree, p[0], p[1], p[2], p[3], (unsigned)i);
+ }
+ }
+
+ if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16) {
+ for(i = 0; i != numpixels; ++i) {
+ unsigned short r = 0, g = 0, b = 0, a = 0;
+ getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
+ rgba16ToPixel(out, i, mode_out, r, g, b, a);
+ }
+ } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) {
+ getPixelColorsRGBA8(out, numpixels, 1, in, mode_in);
+ } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) {
+ getPixelColorsRGBA8(out, numpixels, 0, in, mode_in);
+ } else {
+ unsigned char r = 0, g = 0, b = 0, a = 0;
+ for(i = 0; i != numpixels; ++i) {
+ getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);
+ error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a);
+ if (error) break;
+ }
+ }
+
+ if(mode_out->colortype == LCT_PALETTE) {
+ color_tree_cleanup(&tree);
+ }
+
+ return error;
+}
+
+
+/* Converts a single rgb color without alpha from one type to another, color bits truncated to
+their bitdepth. In case of single channel (gray or palette), only the r channel is used. Slow
+function, do not use to process all pixels of an image. Alpha channel not supported on purpose:
+this is for bKGD, supporting alpha may prevent it from finding a color in the palette, from the
+specification it looks like bKGD should ignore the alpha values of the palette since it can use
+any palette index but doesn't have an alpha channel. Idem with ignoring color key. */
+unsigned lodepng_convert_rgb(
+ unsigned* r_out, unsigned* g_out, unsigned* b_out,
+ unsigned r_in, unsigned g_in, unsigned b_in,
+ const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in) {
+ unsigned r = 0, g = 0, b = 0;
+ unsigned mul = 65535 / ((1u << mode_in->bitdepth) - 1u); /*65535, 21845, 4369, 257, 1*/
+ unsigned shift = 16 - mode_out->bitdepth;
+
+ if(mode_in->colortype == LCT_GREY || mode_in->colortype == LCT_GREY_ALPHA) {
+ r = g = b = r_in * mul;
+ } else if(mode_in->colortype == LCT_RGB || mode_in->colortype == LCT_RGBA) {
+ r = r_in * mul;
+ g = g_in * mul;
+ b = b_in * mul;
+ } else if(mode_in->colortype == LCT_PALETTE) {
+ if(r_in >= mode_in->palettesize) return 82;
+ r = mode_in->palette[r_in * 4 + 0] * 257u;
+ g = mode_in->palette[r_in * 4 + 1] * 257u;
+ b = mode_in->palette[r_in * 4 + 2] * 257u;
+ } else {
+ return 31;
+ }
+
+ /* now convert to output format */
+ if(mode_out->colortype == LCT_GREY || mode_out->colortype == LCT_GREY_ALPHA) {
+ *r_out = r >> shift ;
+ } else if(mode_out->colortype == LCT_RGB || mode_out->colortype == LCT_RGBA) {
+ *r_out = r >> shift ;
+ *g_out = g >> shift ;
+ *b_out = b >> shift ;
+ } else if(mode_out->colortype == LCT_PALETTE) {
+ unsigned i;
+ /* a 16-bit color cannot be in the palette */
+ if((r >> 8) != (r & 255) || (g >> 8) != (g & 255) || (b >> 8) != (b & 255)) return 82;
+ for(i = 0; i < mode_out->palettesize; i++) {
+ unsigned j = i * 4;
+ if((r >> 8) == mode_out->palette[j + 0] && (g >> 8) == mode_out->palette[j + 1] &&
+ (b >> 8) == mode_out->palette[j + 2]) {
+ *r_out = i;
+ return 0;
+ }
+ }
+ return 82;
+ } else {
+ return 31;
+ }
+
+ return 0;
+}
+
+#ifdef LODEPNG_COMPILE_ENCODER
+
+void lodepng_color_profile_init(LodePNGColorProfile* profile) {
+ profile->colored = 0;
+ profile->key = 0;
+ profile->key_r = profile->key_g = profile->key_b = 0;
+ profile->alpha = 0;
+ profile->numcolors = 0;
+ profile->bits = 1;
+ profile->numpixels = 0;
+}
+
+/*function used for debug purposes with C++*/
+/*void printColorProfile(LodePNGColorProfile* p) {
+ std::cout << "colored: " << (int)p->colored << ", ";
+ std::cout << "key: " << (int)p->key << ", ";
+ std::cout << "key_r: " << (int)p->key_r << ", ";
+ std::cout << "key_g: " << (int)p->key_g << ", ";
+ std::cout << "key_b: " << (int)p->key_b << ", ";
+ std::cout << "alpha: " << (int)p->alpha << ", ";
+ std::cout << "numcolors: " << (int)p->numcolors << ", ";
+ std::cout << "bits: " << (int)p->bits << std::endl;
+}*/
+
+/*Returns how many bits needed to represent given value (max 8 bit)*/
+static unsigned getValueRequiredBits(unsigned char value) {
+ if(value == 0 || value == 255) return 1;
+ /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/
+ if(value % 17 == 0) return value % 85 == 0 ? 2 : 4;
+ return 8;
+}
+
+/*profile must already have been inited.
+It's ok to set some parameters of profile to done already.*/
+unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
+ const unsigned char* in, unsigned w, unsigned h,
+ const LodePNGColorMode* mode_in) {
+ unsigned error = 0;
+ size_t i;
+ ColorTree tree;
+ size_t numpixels = (size_t)w * (size_t)h;
+
+ /* mark things as done already if it would be impossible to have a more expensive case */
+ unsigned colored_done = lodepng_is_greyscale_type(mode_in) ? 1 : 0;
+ unsigned alpha_done = lodepng_can_have_alpha(mode_in) ? 0 : 1;
+ unsigned numcolors_done = 0;
+ unsigned bpp = lodepng_get_bpp(mode_in);
+ unsigned bits_done = (profile->bits == 1 && bpp == 1) ? 1 : 0;
+ unsigned sixteen = 0; /* whether the input image is 16 bit */
+ unsigned maxnumcolors = 257;
+ if(bpp <= 8) maxnumcolors = LODEPNG_MIN(257, profile->numcolors + (1u << bpp));
+
+ profile->numpixels += numpixels;
+
+ color_tree_init(&tree);
+
+ /*If the profile was already filled in from previous data, fill its palette in tree
+ and mark things as done already if we know they are the most expensive case already*/
+ if(profile->alpha) alpha_done = 1;
+ if(profile->colored) colored_done = 1;
+ if(profile->bits == 16) numcolors_done = 1;
+ if(profile->bits >= bpp) bits_done = 1;
+ if(profile->numcolors >= maxnumcolors) numcolors_done = 1;
+
+ if(!numcolors_done) {
+ for(i = 0; i < profile->numcolors; i++) {
+ const unsigned char* color = &profile->palette[i * 4];
+ color_tree_add(&tree, color[0], color[1], color[2], color[3], (unsigned int)i);
+ }
+ }
+
+ /*Check if the 16-bit input is truly 16-bit*/
+ if(mode_in->bitdepth == 16 && !sixteen) {
+ unsigned short r, g, b, a;
+ for(i = 0; i != numpixels; ++i) {
+ getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
+ if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) ||
+ (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/ {
+ profile->bits = 16;
+ sixteen = 1;
+ bits_done = 1;
+ numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/
+ break;
+ }
+ }
+ }
+
+ if(sixteen) {
+ unsigned short r = 0, g = 0, b = 0, a = 0;
+
+ for(i = 0; i != numpixels; ++i) {
+ getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
+
+ if(!colored_done && (r != g || r != b)) {
+ profile->colored = 1;
+ colored_done = 1;
+ }
+
+ if(!alpha_done) {
+ unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b);
+ if(a != 65535 && (a != 0 || (profile->key && !matchkey))) {
+ profile->alpha = 1;
+ profile->key = 0;
+ alpha_done = 1;
+ } else if(a == 0 && !profile->alpha && !profile->key) {
+ profile->key = 1;
+ profile->key_r = r;
+ profile->key_g = g;
+ profile->key_b = b;
+ } else if(a == 65535 && profile->key && matchkey) {
+ /* Color key cannot be used if an opaque pixel also has that RGB color. */
+ profile->alpha = 1;
+ profile->key = 0;
+ alpha_done = 1;
+ }
+ }
+ if(alpha_done && numcolors_done && colored_done && bits_done) break;
+ }
+
+ if(profile->key && !profile->alpha) {
+ for(i = 0; i != numpixels; ++i) {
+ getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
+ if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b) {
+ /* Color key cannot be used if an opaque pixel also has that RGB color. */
+ profile->alpha = 1;
+ profile->key = 0;
+ alpha_done = 1;
+ }
+ }
+ }
+ } else /* < 16-bit */ {
+ unsigned char r = 0, g = 0, b = 0, a = 0;
+ for(i = 0; i != numpixels; ++i) {
+ getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);
+
+ if(!bits_done && profile->bits < 8) {
+ /*only r is checked, < 8 bits is only relevant for grayscale*/
+ unsigned bits = getValueRequiredBits(r);
+ if(bits > profile->bits) profile->bits = bits;
+ }
+ bits_done = (profile->bits >= bpp);
+
+ if(!colored_done && (r != g || r != b)) {
+ profile->colored = 1;
+ colored_done = 1;
+ if(profile->bits < 8) profile->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/
+ }
+
+ if(!alpha_done) {
+ unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b);
+ if(a != 255 && (a != 0 || (profile->key && !matchkey))) {
+ profile->alpha = 1;
+ profile->key = 0;
+ alpha_done = 1;
+ if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
+ } else if(a == 0 && !profile->alpha && !profile->key) {
+ profile->key = 1;
+ profile->key_r = r;
+ profile->key_g = g;
+ profile->key_b = b;
+ } else if(a == 255 && profile->key && matchkey) {
+ /* Color key cannot be used if an opaque pixel also has that RGB color. */
+ profile->alpha = 1;
+ profile->key = 0;
+ alpha_done = 1;
+ if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
+ }
+ }
+
+ if(!numcolors_done) {
+ if(!color_tree_has(&tree, r, g, b, a)) {
+ color_tree_add(&tree, r, g, b, a, profile->numcolors);
+ if(profile->numcolors < 256) {
+ unsigned char* p = profile->palette;
+ unsigned n = profile->numcolors;
+ p[n * 4 + 0] = r;
+ p[n * 4 + 1] = g;
+ p[n * 4 + 2] = b;
+ p[n * 4 + 3] = a;
+ }
+ ++profile->numcolors;
+ numcolors_done = profile->numcolors >= maxnumcolors;
+ }
+ }
+
+ if(alpha_done && numcolors_done && colored_done && bits_done) break;
+ }
+
+ if(profile->key && !profile->alpha) {
+ for(i = 0; i != numpixels; ++i) {
+ getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);
+ if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b) {
+ /* Color key cannot be used if an opaque pixel also has that RGB color. */
+ profile->alpha = 1;
+ profile->key = 0;
+ alpha_done = 1;
+ if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
+ }
+ }
+ }
+
+ /*make the profile's key always 16-bit for consistency - repeat each byte twice*/
+ profile->key_r += (profile->key_r << 8);
+ profile->key_g += (profile->key_g << 8);
+ profile->key_b += (profile->key_b << 8);
+ }
+
+ color_tree_cleanup(&tree);
+ return error;
+}
+
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+/*Adds a single color to the color profile. The profile must already have been inited. The color must be given as 16-bit
+(with 2 bytes repeating for 8-bit and 65535 for opaque alpha channel). This function is expensive, do not call it for
+all pixels of an image but only for a few additional values. */
+static unsigned lodepng_color_profile_add(LodePNGColorProfile* profile,
+ unsigned r, unsigned g, unsigned b, unsigned a) {
+ unsigned error = 0;
+ unsigned char image[8];
+ LodePNGColorMode mode;
+ lodepng_color_mode_init(&mode);
+ image[0] = r >> 8; image[1] = r; image[2] = g >> 8; image[3] = g;
+ image[4] = b >> 8; image[5] = b; image[6] = a >> 8; image[7] = a;
+ mode.bitdepth = 16;
+ mode.colortype = LCT_RGBA;
+ error = lodepng_get_color_profile(profile, image, 1, 1, &mode);
+ lodepng_color_mode_cleanup(&mode);
+ return error;
+}
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+
+/*Autochoose color model given the computed profile. mode_in is to copy palette order from
+when relevant.*/
+static unsigned auto_choose_color_from_profile(LodePNGColorMode* mode_out,
+ const LodePNGColorMode* mode_in,
+ const LodePNGColorProfile* prof) {
+ unsigned error = 0;
+ unsigned palettebits, palette_ok;
+ size_t i, n;
+ size_t numpixels = prof->numpixels;
+
+ unsigned alpha = prof->alpha;
+ unsigned key = prof->key;
+ unsigned bits = prof->bits;
+
+ mode_out->key_defined = 0;
+
+ if(key && numpixels <= 16) {
+ alpha = 1; /*too few pixels to justify tRNS chunk overhead*/
+ key = 0;
+ if(bits < 8) bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
+ }
+ n = prof->numcolors;
+ palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8));
+ palette_ok = n <= 256 && bits <= 8;
+ if(numpixels < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/
+ if(!prof->colored && bits <= palettebits) palette_ok = 0; /*gray is less overhead*/
+
+ if(palette_ok) {
+ const unsigned char* p = prof->palette;
+ lodepng_palette_clear(mode_out); /*remove potential earlier palette*/
+ for(i = 0; i != prof->numcolors; ++i) {
+ error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]);
+ if(error) break;
+ }
+
+ mode_out->colortype = LCT_PALETTE;
+ mode_out->bitdepth = palettebits;
+
+ if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize
+ && mode_in->bitdepth == mode_out->bitdepth) {
+ /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/
+ lodepng_color_mode_cleanup(mode_out);
+ lodepng_color_mode_copy(mode_out, mode_in);
+ }
+ } else /*8-bit or 16-bit per channel*/ {
+ mode_out->bitdepth = bits;
+ mode_out->colortype = alpha ? (prof->colored ? LCT_RGBA : LCT_GREY_ALPHA)
+ : (prof->colored ? LCT_RGB : LCT_GREY);
+
+ if(key) {
+ unsigned mask = (1u << mode_out->bitdepth) - 1u; /*profile always uses 16-bit, mask converts it*/
+ mode_out->key_r = prof->key_r & mask;
+ mode_out->key_g = prof->key_g & mask;
+ mode_out->key_b = prof->key_b & mask;
+ mode_out->key_defined = 1;
+ }
+ }
+
+ return error;
+}
+
+/*Automatically chooses color type that gives smallest amount of bits in the
+output image, e.g. gray if there are only grayscale pixels, palette if there
+are less than 256 colors, color key if only single transparent color, ...
+Updates values of mode with a potentially smaller color model. mode_out should
+contain the user chosen color model, but will be overwritten with the new chosen one.*/
+unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
+ const unsigned char* image, unsigned w, unsigned h,
+ const LodePNGColorMode* mode_in) {
+ unsigned error = 0;
+ LodePNGColorProfile prof;
+ lodepng_color_profile_init(&prof);
+ error = lodepng_get_color_profile(&prof, image, w, h, mode_in);
+ if(error) return error;
+ return auto_choose_color_from_profile(mode_out, mode_in, &prof);
+}
+
+#endif /* #ifdef LODEPNG_COMPILE_ENCODER */
+
+/*
+Paeth predicter, used by PNG filter type 4
+The parameters are of type short, but should come from unsigned chars, the shorts
+are only needed to make the paeth calculation correct.
+*/
+static unsigned char paethPredictor(short a, short b, short c) {
+ short pa = abs(b - c);
+ short pb = abs(a - c);
+ short pc = abs(a + b - c - c);
+
+ if(pc < pa && pc < pb) return (unsigned char)c;
+ else if(pb < pa) return (unsigned char)b;
+ else return (unsigned char)a;
+}
+
+/*shared values used by multiple Adam7 related functions*/
+
+static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/
+static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/
+static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/
+static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/
+
+/*
+Outputs various dimensions and positions in the image related to the Adam7 reduced images.
+passw: output containing the width of the 7 passes
+passh: output containing the height of the 7 passes
+filter_passstart: output containing the index of the start and end of each
+ reduced image with filter bytes
+padded_passstart output containing the index of the start and end of each
+ reduced image when without filter bytes but with padded scanlines
+passstart: output containing the index of the start and end of each reduced
+ image without padding between scanlines, but still padding between the images
+w, h: width and height of non-interlaced image
+bpp: bits per pixel
+"padded" is only relevant if bpp is less than 8 and a scanline or image does not
+ end at a full byte
+*/
+static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8],
+ size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) {
+ /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/
+ unsigned i;
+
+ /*calculate width and height in pixels of each pass*/
+ for(i = 0; i != 7; ++i) {
+ passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i];
+ passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i];
+ if(passw[i] == 0) passh[i] = 0;
+ if(passh[i] == 0) passw[i] = 0;
+ }
+
+ filter_passstart[0] = padded_passstart[0] = passstart[0] = 0;
+ for(i = 0; i != 7; ++i) {
+ /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/
+ filter_passstart[i + 1] = filter_passstart[i]
+ + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0);
+ /*bits padded if needed to fill full byte at end of each scanline*/
+ padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8);
+ /*only padded at end of reduced image*/
+ passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8;
+ }
+}
+
+#ifdef LODEPNG_COMPILE_DECODER
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / PNG Decoder / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+/*read the information from the header and store it in the LodePNGInfo. return value is error*/
+unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state,
+ const unsigned char* in, size_t insize) {
+ unsigned width, height;
+ LodePNGInfo* info = &state->info_png;
+ if(insize == 0 || in == 0) {
+ CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/
+ }
+ if(insize < 33) {
+ CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/
+ }
+
+ /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/
+ /* TODO: remove this. One should use a new LodePNGState for new sessions */
+ lodepng_info_cleanup(info);
+ lodepng_info_init(info);
+
+ if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71
+ || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) {
+ CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/
+ }
+ if(lodepng_chunk_length(in + 8) != 13) {
+ CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/
+ }
+ if(!lodepng_chunk_type_equals(in + 8, "IHDR")) {
+ CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/
+ }
+
+ /*read the values given in the header*/
+ width = lodepng_read32bitInt(&in[16]);
+ height = lodepng_read32bitInt(&in[20]);
+ info->color.bitdepth = in[24];
+ info->color.colortype = (LodePNGColorType)in[25];
+ info->compression_method = in[26];
+ info->filter_method = in[27];
+ info->interlace_method = in[28];
+
+ if(width == 0 || height == 0) {
+ CERROR_RETURN_ERROR(state->error, 93);
+ }
+
+ if(w) *w = width;
+ if(h) *h = height;
+
+ if(!state->decoder.ignore_crc) {
+ unsigned CRC = lodepng_read32bitInt(&in[29]);
+ unsigned checksum = lodepng_crc32(&in[12], 17);
+ if(CRC != checksum) {
+ CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/
+ }
+ }
+
+ /*error: only compression method 0 is allowed in the specification*/
+ if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32);
+ /*error: only filter method 0 is allowed in the specification*/
+ if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33);
+ /*error: only interlace methods 0 and 1 exist in the specification*/
+ if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34);
+
+ state->error = checkColorValidity(info->color.colortype, info->color.bitdepth);
+ return state->error;
+}
+
+static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon,
+ size_t bytewidth, unsigned char filterType, size_t length) {
+ /*
+ For PNG filter method 0
+ unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte,
+ the filter works byte per byte (bytewidth = 1)
+ precon is the previous unfiltered scanline, recon the result, scanline the current one
+ the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead
+ recon and scanline MAY be the same memory address! precon must be disjoint.
+ */
+
+ size_t i;
+ switch(filterType) {
+ case 0:
+ for(i = 0; i != length; ++i) recon[i] = scanline[i];
+ break;
+ case 1:
+ for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
+ for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth];
+ break;
+ case 2:
+ if(precon) {
+ for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];
+ } else {
+ for(i = 0; i != length; ++i) recon[i] = scanline[i];
+ }
+ break;
+ case 3:
+ if(precon) {
+ for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1);
+ for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1);
+ } else {
+ for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
+ for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1);
+ }
+ break;
+ case 4:
+ if(precon) {
+ for(i = 0; i != bytewidth; ++i) {
+ recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
+ }
+ for(i = bytewidth; i < length; ++i) {
+ recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
+ }
+ } else {
+ for(i = 0; i != bytewidth; ++i) {
+ recon[i] = scanline[i];
+ }
+ for(i = bytewidth; i < length; ++i) {
+ /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
+ recon[i] = (scanline[i] + recon[i - bytewidth]);
+ }
+ }
+ break;
+ default: return 36; /*error: unexisting filter type given*/
+ }
+ return 0;
+}
+
+static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) {
+ /*
+ For PNG filter method 0
+ this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times)
+ out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline
+ w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel
+ in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes)
+ */
+
+ unsigned y;
+ unsigned char* prevline = 0;
+
+ /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
+ size_t bytewidth = (bpp + 7) / 8;
+ size_t linebytes = (w * bpp + 7) / 8;
+
+ for(y = 0; y < h; ++y) {
+ size_t outindex = linebytes * y;
+ size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
+ unsigned char filterType = in[inindex];
+
+ CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes));
+
+ prevline = &out[outindex];
+ }
+
+ return 0;
+}
+
+/*
+in: Adam7 interlaced image, with no padding bits between scanlines, but between
+ reduced images so that each reduced image starts at a byte.
+out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h
+bpp: bits per pixel
+out has the following size in bits: w * h * bpp.
+in is possibly bigger due to padding bits between reduced images.
+out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation
+(because that's likely a little bit faster)
+NOTE: comments about padding bits are only relevant if bpp < 8
+*/
+static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) {
+ unsigned passw[7], passh[7];
+ size_t filter_passstart[8], padded_passstart[8], passstart[8];
+ unsigned i;
+
+ Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
+
+ if(bpp >= 8) {
+ for(i = 0; i != 7; ++i) {
+ unsigned x, y, b;
+ size_t bytewidth = bpp / 8;
+ for(y = 0; y < passh[i]; ++y)
+ for(x = 0; x < passw[i]; ++x) {
+ size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth;
+ size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;
+ for(b = 0; b < bytewidth; ++b) {
+ out[pixeloutstart + b] = in[pixelinstart + b];
+ }
+ }
+ }
+ } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ {
+ for(i = 0; i != 7; ++i) {
+ unsigned x, y, b;
+ unsigned ilinebits = bpp * passw[i];
+ unsigned olinebits = bpp * w;
+ size_t obp, ibp; /*bit pointers (for out and in buffer)*/
+ for(y = 0; y < passh[i]; ++y)
+ for(x = 0; x < passw[i]; ++x) {
+ ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
+ obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;
+ for(b = 0; b < bpp; ++b) {
+ unsigned char bit = readBitFromReversedStream(&ibp, in);
+ /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/
+ setBitOfReversedStream0(&obp, out, bit);
+ }
+ }
+ }
+ }
+}
+
+static void removePaddingBits(unsigned char* out, const unsigned char* in,
+ size_t olinebits, size_t ilinebits, unsigned h) {
+ /*
+ After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need
+ to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers
+ for the Adam7 code, the color convert code and the output to the user.
+ in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must
+ have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits
+ also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7
+ only useful if (ilinebits - olinebits) is a value in the range 1..7
+ */
+ unsigned y;
+ size_t diff = ilinebits - olinebits;
+ size_t ibp = 0, obp = 0; /*input and output bit pointers*/
+ for(y = 0; y < h; ++y) {
+ size_t x;
+ for(x = 0; x < olinebits; ++x) {
+ unsigned char bit = readBitFromReversedStream(&ibp, in);
+ setBitOfReversedStream(&obp, out, bit);
+ }
+ ibp += diff;
+ }
+}
+
+/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from
+the IDAT chunks (with filter index bytes and possible padding bits)
+return value is error*/
+static unsigned postProcessScanlines(unsigned char* out, unsigned char* in,
+ unsigned w, unsigned h, const LodePNGInfo* info_png) {
+ /*
+ This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype.
+ Steps:
+ *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8)
+ *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace
+ NOTE: the in buffer will be overwritten with intermediate data!
+ */
+ unsigned bpp = lodepng_get_bpp(&info_png->color);
+ if(bpp == 0) return 31; /*error: invalid colortype*/
+
+ if(info_png->interlace_method == 0) {
+ if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) {
+ CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp));
+ removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h);
+ }
+ /*we can immediately filter into the out buffer, no other steps needed*/
+ else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp));
+ } else /*interlace_method is 1 (Adam7)*/ {
+ unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8];
+ unsigned i;
+
+ Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
+
+ for(i = 0; i != 7; ++i) {
+ CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp));
+ /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline,
+ move bytes instead of bits or move not at all*/
+ if(bpp < 8) {
+ /*remove padding bits in scanlines; after this there still may be padding
+ bits between the different reduced images: each reduced image still starts nicely at a byte*/
+ removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp,
+ ((passw[i] * bpp + 7) / 8) * 8, passh[i]);
+ }
+ }
+
+ Adam7_deinterlace(out, in, w, h, bpp);
+ }
+
+ return 0;
+}
+
+static unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) {
+ unsigned pos = 0, i;
+ if(color->palette) lodepng_free(color->palette);
+ color->palettesize = chunkLength / 3;
+ color->palette = (unsigned char*)lodepng_malloc(4 * color->palettesize);
+ if(!color->palette && color->palettesize) {
+ color->palettesize = 0;
+ return 83; /*alloc fail*/
+ }
+ if(color->palettesize > 256) return 38; /*error: palette too big*/
+
+ for(i = 0; i != color->palettesize; ++i) {
+ color->palette[4 * i + 0] = data[pos++]; /*R*/
+ color->palette[4 * i + 1] = data[pos++]; /*G*/
+ color->palette[4 * i + 2] = data[pos++]; /*B*/
+ color->palette[4 * i + 3] = 255; /*alpha*/
+ }
+
+ return 0; /* OK */
+}
+
+static unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) {
+ unsigned i;
+ if(color->colortype == LCT_PALETTE) {
+ /*error: more alpha values given than there are palette entries*/
+ if(chunkLength > color->palettesize) return 39;
+
+ for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i];
+ } else if(color->colortype == LCT_GREY) {
+ /*error: this chunk must be 2 bytes for grayscale image*/
+ if(chunkLength != 2) return 30;
+
+ color->key_defined = 1;
+ color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1];
+ } else if(color->colortype == LCT_RGB) {
+ /*error: this chunk must be 6 bytes for RGB image*/
+ if(chunkLength != 6) return 41;
+
+ color->key_defined = 1;
+ color->key_r = 256u * data[0] + data[1];
+ color->key_g = 256u * data[2] + data[3];
+ color->key_b = 256u * data[4] + data[5];
+ }
+ else return 42; /*error: tRNS chunk not allowed for other color models*/
+
+ return 0; /* OK */
+}
+
+
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+/*background color chunk (bKGD)*/
+static unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
+ if(info->color.colortype == LCT_PALETTE) {
+ /*error: this chunk must be 1 byte for indexed color image*/
+ if(chunkLength != 1) return 43;
+
+ /*error: invalid palette index, or maybe this chunk appeared before PLTE*/
+ if(data[0] >= info->color.palettesize) return 103;
+
+ info->background_defined = 1;
+ info->background_r = info->background_g = info->background_b = data[0];
+ } else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) {
+ /*error: this chunk must be 2 bytes for grayscale image*/
+ if(chunkLength != 2) return 44;
+
+ /*the values are truncated to bitdepth in the PNG file*/
+ info->background_defined = 1;
+ info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1];
+ } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) {
+ /*error: this chunk must be 6 bytes for grayscale image*/
+ if(chunkLength != 6) return 45;
+
+ /*the values are truncated to bitdepth in the PNG file*/
+ info->background_defined = 1;
+ info->background_r = 256u * data[0] + data[1];
+ info->background_g = 256u * data[2] + data[3];
+ info->background_b = 256u * data[4] + data[5];
+ }
+
+ return 0; /* OK */
+}
+
+/*text chunk (tEXt)*/
+static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
+ unsigned error = 0;
+ char *key = 0, *str = 0;
+ unsigned i;
+
+ while(!error) /*not really a while loop, only used to break on error*/ {
+ unsigned length, string2_begin;
+
+ length = 0;
+ while(length < chunkLength && data[length] != 0) ++length;
+ /*even though it's not allowed by the standard, no error is thrown if
+ there's no null termination char, if the text is empty*/
+ if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
+
+ key = (char*)lodepng_malloc(length + 1);
+ if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
+
+ key[length] = 0;
+ for(i = 0; i != length; ++i) key[i] = (char)data[i];
+
+ string2_begin = length + 1; /*skip keyword null terminator*/
+
+ length = (unsigned)(chunkLength < string2_begin ? 0 : chunkLength - string2_begin);
+ str = (char*)lodepng_malloc(length + 1);
+ if(!str) CERROR_BREAK(error, 83); /*alloc fail*/
+
+ str[length] = 0;
+ for(i = 0; i != length; ++i) str[i] = (char)data[string2_begin + i];
+
+ error = lodepng_add_text(info, key, str);
+
+ break;
+ }
+
+ lodepng_free(key);
+ lodepng_free(str);
+
+ return error;
+}
+
+/*compressed text chunk (zTXt)*/
+static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
+ const unsigned char* data, size_t chunkLength) {
+ unsigned error = 0;
+ unsigned i;
+
+ unsigned length, string2_begin;
+ char *key = 0;
+ ucvector decoded;
+
+ ucvector_init(&decoded);
+
+ while(!error) /*not really a while loop, only used to break on error*/ {
+ for(length = 0; length < chunkLength && data[length] != 0; ++length) ;
+ if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
+ if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
+
+ key = (char*)lodepng_malloc(length + 1);
+ if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
+
+ key[length] = 0;
+ for(i = 0; i != length; ++i) key[i] = (char)data[i];
+
+ if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/
+
+ string2_begin = length + 2;
+ if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
+
+ length = (unsigned)chunkLength - string2_begin;
+ /*will fail if zlib error, e.g. if length is too small*/
+ error = zlib_decompress(&decoded.data, &decoded.size,
+ (unsigned char*)(&data[string2_begin]),
+ length, zlibsettings);
+ if(error) break;
+ ucvector_push_back(&decoded, 0);
+
+ error = lodepng_add_text(info, key, (char*)decoded.data);
+
+ break;
+ }
+
+ lodepng_free(key);
+ ucvector_cleanup(&decoded);
+
+ return error;
+}
+
+/*international text chunk (iTXt)*/
+static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
+ const unsigned char* data, size_t chunkLength) {
+ unsigned error = 0;
+ unsigned i;
+
+ unsigned length, begin, compressed;
+ char *key = 0, *langtag = 0, *transkey = 0;
+ ucvector decoded;
+ ucvector_init(&decoded); /* TODO: only use in case of compressed text */
+
+ while(!error) /*not really a while loop, only used to break on error*/ {
+ /*Quick check if the chunk length isn't too small. Even without check
+ it'd still fail with other error checks below if it's too short. This just gives a different error code.*/
+ if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/
+
+ /*read the key*/
+ for(length = 0; length < chunkLength && data[length] != 0; ++length) ;
+ if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/
+ if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
+
+ key = (char*)lodepng_malloc(length + 1);
+ if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
+
+ key[length] = 0;
+ for(i = 0; i != length; ++i) key[i] = (char)data[i];
+
+ /*read the compression method*/
+ compressed = data[length + 1];
+ if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/
+
+ /*even though it's not allowed by the standard, no error is thrown if
+ there's no null termination char, if the text is empty for the next 3 texts*/
+
+ /*read the langtag*/
+ begin = length + 3;
+ length = 0;
+ for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length;
+
+ langtag = (char*)lodepng_malloc(length + 1);
+ if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/
+
+ langtag[length] = 0;
+ for(i = 0; i != length; ++i) langtag[i] = (char)data[begin + i];
+
+ /*read the transkey*/
+ begin += length + 1;
+ length = 0;
+ for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length;
+
+ transkey = (char*)lodepng_malloc(length + 1);
+ if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/
+
+ transkey[length] = 0;
+ for(i = 0; i != length; ++i) transkey[i] = (char)data[begin + i];
+
+ /*read the actual text*/
+ begin += length + 1;
+
+ length = (unsigned)chunkLength < begin ? 0 : (unsigned)chunkLength - begin;
+
+ if(compressed) {
+ /*will fail if zlib error, e.g. if length is too small*/
+ error = zlib_decompress(&decoded.data, &decoded.size,
+ (unsigned char*)(&data[begin]),
+ length, zlibsettings);
+ if(error) break;
+ if(decoded.allocsize < decoded.size) decoded.allocsize = decoded.size;
+ ucvector_push_back(&decoded, 0);
+ } else {
+ if(!ucvector_resize(&decoded, length + 1)) CERROR_BREAK(error, 83 /*alloc fail*/);
+
+ decoded.data[length] = 0;
+ for(i = 0; i != length; ++i) decoded.data[i] = data[begin + i];
+ }
+
+ error = lodepng_add_itext(info, key, langtag, transkey, (char*)decoded.data);
+
+ break;
+ }
+
+ lodepng_free(key);
+ lodepng_free(langtag);
+ lodepng_free(transkey);
+ ucvector_cleanup(&decoded);
+
+ return error;
+}
+
+static unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
+ if(chunkLength != 7) return 73; /*invalid tIME chunk size*/
+
+ info->time_defined = 1;
+ info->time.year = 256u * data[0] + data[1];
+ info->time.month = data[2];
+ info->time.day = data[3];
+ info->time.hour = data[4];
+ info->time.minute = data[5];
+ info->time.second = data[6];
+
+ return 0; /* OK */
+}
+
+static unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
+ if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/
+
+ info->phys_defined = 1;
+ info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3];
+ info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7];
+ info->phys_unit = data[8];
+
+ return 0; /* OK */
+}
+
+static unsigned readChunk_gAMA(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
+ if(chunkLength != 4) return 96; /*invalid gAMA chunk size*/
+
+ info->gama_defined = 1;
+ info->gama_gamma = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3];
+
+ return 0; /* OK */
+}
+
+static unsigned readChunk_cHRM(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
+ if(chunkLength != 32) return 97; /*invalid cHRM chunk size*/
+
+ info->chrm_defined = 1;
+ info->chrm_white_x = 16777216u * data[ 0] + 65536u * data[ 1] + 256u * data[ 2] + data[ 3];
+ info->chrm_white_y = 16777216u * data[ 4] + 65536u * data[ 5] + 256u * data[ 6] + data[ 7];
+ info->chrm_red_x = 16777216u * data[ 8] + 65536u * data[ 9] + 256u * data[10] + data[11];
+ info->chrm_red_y = 16777216u * data[12] + 65536u * data[13] + 256u * data[14] + data[15];
+ info->chrm_green_x = 16777216u * data[16] + 65536u * data[17] + 256u * data[18] + data[19];
+ info->chrm_green_y = 16777216u * data[20] + 65536u * data[21] + 256u * data[22] + data[23];
+ info->chrm_blue_x = 16777216u * data[24] + 65536u * data[25] + 256u * data[26] + data[27];
+ info->chrm_blue_y = 16777216u * data[28] + 65536u * data[29] + 256u * data[30] + data[31];
+
+ return 0; /* OK */
+}
+
+static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
+ if(chunkLength != 1) return 98; /*invalid sRGB chunk size (this one is never ignored)*/
+
+ info->srgb_defined = 1;
+ info->srgb_intent = data[0];
+
+ return 0; /* OK */
+}
+
+static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
+ const unsigned char* data, size_t chunkLength) {
+ unsigned error = 0;
+ unsigned i;
+
+ unsigned length, string2_begin;
+ ucvector decoded;
+
+ info->iccp_defined = 1;
+ if(info->iccp_name) lodepng_clear_icc(info);
+
+ for(length = 0; length < chunkLength && data[length] != 0; ++length) ;
+ if(length + 2 >= chunkLength) return 75; /*no null termination, corrupt?*/
+ if(length < 1 || length > 79) return 89; /*keyword too short or long*/
+
+ info->iccp_name = (char*)lodepng_malloc(length + 1);
+ if(!info->iccp_name) return 83; /*alloc fail*/
+
+ info->iccp_name[length] = 0;
+ for(i = 0; i != length; ++i) info->iccp_name[i] = (char)data[i];
+
+ if(data[length + 1] != 0) return 72; /*the 0 byte indicating compression must be 0*/
+
+ string2_begin = length + 2;
+ if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/
+
+ length = (unsigned)chunkLength - string2_begin;
+ ucvector_init(&decoded);
+ error = zlib_decompress(&decoded.data, &decoded.size,
+ (unsigned char*)(&data[string2_begin]),
+ length, zlibsettings);
+ if(!error) {
+ info->iccp_profile_size = (unsigned int)decoded.size;
+ info->iccp_profile = (unsigned char*)lodepng_malloc(decoded.size);
+ if(info->iccp_profile) {
+ memcpy(info->iccp_profile, decoded.data, decoded.size);
+ } else {
+ error = 83; /* alloc fail */
+ }
+ }
+ ucvector_cleanup(&decoded);
+ return error;
+}
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+
+unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
+ const unsigned char* in, size_t insize) {
+ const unsigned char* chunk = in + pos;
+ unsigned chunkLength;
+ const unsigned char* data;
+ unsigned unhandled = 0;
+ unsigned error = 0;
+
+ if (pos + 4 > insize) return 30;
+ chunkLength = lodepng_chunk_length(chunk);
+ if(chunkLength > 2147483647) return 63;
+ data = lodepng_chunk_data_const(chunk);
+ if(data + chunkLength + 4 > in + insize) return 30;
+
+ if(lodepng_chunk_type_equals(chunk, "PLTE")) {
+ error = readChunk_PLTE(&state->info_png.color, data, chunkLength);
+ } else if(lodepng_chunk_type_equals(chunk, "tRNS")) {
+ error = readChunk_tRNS(&state->info_png.color, data, chunkLength);
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ } else if(lodepng_chunk_type_equals(chunk, "bKGD")) {
+ error = readChunk_bKGD(&state->info_png, data, chunkLength);
+ } else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
+ error = readChunk_tEXt(&state->info_png, data, chunkLength);
+ } else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
+ error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+ } else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
+ error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+ } else if(lodepng_chunk_type_equals(chunk, "tIME")) {
+ error = readChunk_tIME(&state->info_png, data, chunkLength);
+ } else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
+ error = readChunk_pHYs(&state->info_png, data, chunkLength);
+ } else if(lodepng_chunk_type_equals(chunk, "gAMA")) {
+ error = readChunk_gAMA(&state->info_png, data, chunkLength);
+ } else if(lodepng_chunk_type_equals(chunk, "cHRM")) {
+ error = readChunk_cHRM(&state->info_png, data, chunkLength);
+ } else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
+ error = readChunk_sRGB(&state->info_png, data, chunkLength);
+ } else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
+ error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ } else {
+ /* unhandled chunk is ok (is not an error) */
+ unhandled = 1;
+ }
+
+ if(!error && !unhandled && !state->decoder.ignore_crc) {
+ if(lodepng_chunk_check_crc(chunk)) return 57; /*invalid CRC*/
+ }
+
+ return error;
+}
+
+/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/
+static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
+ LodePNGState* state,
+ const unsigned char* in, size_t insize) {
+ unsigned char IEND = 0;
+ const unsigned char* chunk;
+ size_t i;
+ ucvector idat; /*the data from idat chunks*/
+ ucvector scanlines;
+ size_t predict;
+ size_t outsize = 0;
+
+ /*for unknown chunk order*/
+ unsigned unknown = 0;
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+
+
+ /* safe output values in case error happens */
+ *out = 0;
+ *w = *h = 0;
+
+ state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/
+ if(state->error) return;
+
+ if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) {
+ CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/
+ }
+
+ ucvector_init(&idat);
+ chunk = &in[33]; /*first byte of the first chunk after the header*/
+
+ /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk.
+ IDAT data is put at the start of the in buffer*/
+ while(!IEND && !state->error) {
+ unsigned chunkLength;
+ const unsigned char* data; /*the data in the chunk*/
+
+ /*error: size of the in buffer too small to contain next chunk*/
+ if((size_t)((chunk - in) + 12) > insize || chunk < in) {
+ if(state->decoder.ignore_end) break; /*other errors may still happen though*/
+ CERROR_BREAK(state->error, 30);
+ }
+
+ /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/
+ chunkLength = lodepng_chunk_length(chunk);
+ /*error: chunk length larger than the max PNG chunk size*/
+ if(chunkLength > 2147483647) {
+ if(state->decoder.ignore_end) break; /*other errors may still happen though*/
+ CERROR_BREAK(state->error, 63);
+ }
+
+ if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) {
+ CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/
+ }
+
+ data = lodepng_chunk_data_const(chunk);
+
+ unknown = 0;
+
+ /*IDAT chunk, containing compressed image data*/
+ if(lodepng_chunk_type_equals(chunk, "IDAT")) {
+ size_t oldsize = idat.size;
+ size_t newsize;
+ if(lodepng_addofl(oldsize, chunkLength, &newsize)) CERROR_BREAK(state->error, 95);
+ if(!ucvector_resize(&idat, newsize)) CERROR_BREAK(state->error, 83 /*alloc fail*/);
+ for(i = 0; i != chunkLength; ++i) idat.data[oldsize + i] = data[i];
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ critical_pos = 3;
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ } else if(lodepng_chunk_type_equals(chunk, "IEND")) {
+ /*IEND chunk*/
+ IEND = 1;
+ } else if(lodepng_chunk_type_equals(chunk, "PLTE")) {
+ /*palette chunk (PLTE)*/
+ state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength);
+ if(state->error) break;
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ critical_pos = 2;
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ } else if(lodepng_chunk_type_equals(chunk, "tRNS")) {
+ /*palette transparency chunk (tRNS). Even though this one is an ancillary chunk , it is still compiled
+ in without 'LODEPNG_COMPILE_ANCILLARY_CHUNKS' because it contains essential color information that
+ affects the alpha channel of pixels. */
+ state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength);
+ if(state->error) break;
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ /*background color chunk (bKGD)*/
+ } else if(lodepng_chunk_type_equals(chunk, "bKGD")) {
+ state->error = readChunk_bKGD(&state->info_png, data, chunkLength);
+ if(state->error) break;
+ } else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
+ /*text chunk (tEXt)*/
+ if(state->decoder.read_text_chunks) {
+ state->error = readChunk_tEXt(&state->info_png, data, chunkLength);
+ if(state->error) break;
+ }
+ } else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
+ /*compressed text chunk (zTXt)*/
+ if(state->decoder.read_text_chunks) {
+ state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+ if(state->error) break;
+ }
+ } else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
+ /*international text chunk (iTXt)*/
+ if(state->decoder.read_text_chunks) {
+ state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+ if(state->error) break;
+ }
+ } else if(lodepng_chunk_type_equals(chunk, "tIME")) {
+ state->error = readChunk_tIME(&state->info_png, data, chunkLength);
+ if(state->error) break;
+ } else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
+ state->error = readChunk_pHYs(&state->info_png, data, chunkLength);
+ if(state->error) break;
+ } else if(lodepng_chunk_type_equals(chunk, "gAMA")) {
+ state->error = readChunk_gAMA(&state->info_png, data, chunkLength);
+ if(state->error) break;
+ } else if(lodepng_chunk_type_equals(chunk, "cHRM")) {
+ state->error = readChunk_cHRM(&state->info_png, data, chunkLength);
+ if(state->error) break;
+ } else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
+ state->error = readChunk_sRGB(&state->info_png, data, chunkLength);
+ if(state->error) break;
+ } else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
+ state->error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
+ if(state->error) break;
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ } else /*it's not an implemented chunk type, so ignore it: skip over the data*/ {
+ /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/
+ if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk)) {
+ CERROR_BREAK(state->error, 69);
+ }
+
+ unknown = 1;
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ if(state->decoder.remember_unknown_chunks) {
+ state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1],
+ &state->info_png.unknown_chunks_size[critical_pos - 1], chunk);
+ if(state->error) break;
+ }
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ }
+
+ if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/ {
+ if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/
+ }
+
+ if(!IEND) chunk = lodepng_chunk_next_const(chunk);
+ }
+
+ ucvector_init(&scanlines);
+ /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation.
+ If the decompressed size does not match the prediction, the image must be corrupt.*/
+ if(state->info_png.interlace_method == 0) {
+ predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color);
+ } else {
+ /*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/
+ const LodePNGColorMode* color = &state->info_png.color;
+ predict = 0;
+ predict += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color);
+ if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color);
+ predict += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color);
+ if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color);
+ predict += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color);
+ if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color);
+ predict += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color);
+ }
+ if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/
+ if(!state->error) {
+ state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data,
+ idat.size, &state->decoder.zlibsettings);
+ if(!state->error && scanlines.size != predict) state->error = 91; /*decompressed size doesn't match prediction*/
+ }
+ ucvector_cleanup(&idat);
+
+ if(!state->error) {
+ outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color);
+ *out = (unsigned char*)lodepng_malloc(outsize);
+ if(!*out) state->error = 83; /*alloc fail*/
+ }
+ if(!state->error) {
+ for(i = 0; i < outsize; i++) (*out)[i] = 0;
+ state->error = postProcessScanlines(*out, scanlines.data, *w, *h, &state->info_png);
+ }
+ ucvector_cleanup(&scanlines);
+}
+
+unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,
+ LodePNGState* state,
+ const unsigned char* in, size_t insize) {
+ *out = 0;
+ decodeGeneric(out, w, h, state, in, insize);
+ if(state->error) return state->error;
+ if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) {
+ /*same color type, no copying or converting of data needed*/
+ /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype
+ the raw image has to the end user*/
+ if(!state->decoder.color_convert) {
+ state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color);
+ if(state->error) return state->error;
+ }
+ } else {
+ /*color conversion needed; sort of copy of the data*/
+ unsigned char* data = *out;
+ size_t outsize;
+
+ /*TODO: check if this works according to the statement in the documentation: "The converter can convert
+ from grayscale input color type, to 8-bit grayscale or grayscale with alpha"*/
+ if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA)
+ && !(state->info_raw.bitdepth == 8)) {
+ return 56; /*unsupported color mode conversion*/
+ }
+
+ outsize = lodepng_get_raw_size(*w, *h, &state->info_raw);
+ *out = (unsigned char*)lodepng_malloc(outsize);
+ if(!(*out)) {
+ state->error = 83; /*alloc fail*/
+ }
+ else state->error = lodepng_convert(*out, data, &state->info_raw,
+ &state->info_png.color, *w, *h);
+ lodepng_free(data);
+ }
+ return state->error;
+}
+
+unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in,
+ size_t insize, LodePNGColorType colortype, unsigned bitdepth) {
+ unsigned error;
+ LodePNGState state;
+ lodepng_state_init(&state);
+ state.info_raw.colortype = colortype;
+ state.info_raw.bitdepth = bitdepth;
+ error = lodepng_decode(out, w, h, &state, in, insize);
+ lodepng_state_cleanup(&state);
+ return error;
+}
+
+unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) {
+ return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8);
+}
+
+unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) {
+ return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8);
+}
+
+#ifdef LODEPNG_COMPILE_DISK
+unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename,
+ LodePNGColorType colortype, unsigned bitdepth) {
+ unsigned char* buffer = 0;
+ size_t buffersize;
+ unsigned error;
+ /* safe output values in case error happens */
+ *out = 0;
+ *w = *h = 0;
+ error = lodepng_load_file(&buffer, &buffersize, filename);
+ if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth);
+ lodepng_free(buffer);
+ return error;
+}
+
+unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) {
+ return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8);
+}
+
+unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) {
+ return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8);
+}
+#endif /*LODEPNG_COMPILE_DISK*/
+
+void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) {
+ settings->color_convert = 1;
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ settings->read_text_chunks = 1;
+ settings->remember_unknown_chunks = 0;
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ settings->ignore_crc = 0;
+ settings->ignore_critical = 0;
+ settings->ignore_end = 0;
+ lodepng_decompress_settings_init(&settings->zlibsettings);
+}
+
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)
+
+void lodepng_state_init(LodePNGState* state) {
+#ifdef LODEPNG_COMPILE_DECODER
+ lodepng_decoder_settings_init(&state->decoder);
+#endif /*LODEPNG_COMPILE_DECODER*/
+#ifdef LODEPNG_COMPILE_ENCODER
+ lodepng_encoder_settings_init(&state->encoder);
+#endif /*LODEPNG_COMPILE_ENCODER*/
+ lodepng_color_mode_init(&state->info_raw);
+ lodepng_info_init(&state->info_png);
+ state->error = 1;
+}
+
+void lodepng_state_cleanup(LodePNGState* state) {
+ lodepng_color_mode_cleanup(&state->info_raw);
+ lodepng_info_cleanup(&state->info_png);
+}
+
+void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source) {
+ lodepng_state_cleanup(dest);
+ *dest = *source;
+ lodepng_color_mode_init(&dest->info_raw);
+ lodepng_info_init(&dest->info_png);
+ dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return;
+ dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return;
+}
+
+#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */
+
+#ifdef LODEPNG_COMPILE_ENCODER
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* / PNG Encoder / */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+/*chunkName must be string of 4 characters*/
+static unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length) {
+ CERROR_TRY_RETURN(lodepng_chunk_create(&out->data, &out->size, (unsigned)length, chunkName, data));
+ out->allocsize = out->size; /*fix the allocsize again*/
+ return 0;
+}
+
+static void writeSignature(ucvector* out) {
+ /*8 bytes PNG signature, aka the magic bytes*/
+ ucvector_push_back(out, 137);
+ ucvector_push_back(out, 80);
+ ucvector_push_back(out, 78);
+ ucvector_push_back(out, 71);
+ ucvector_push_back(out, 13);
+ ucvector_push_back(out, 10);
+ ucvector_push_back(out, 26);
+ ucvector_push_back(out, 10);
+}
+
+static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h,
+ LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) {
+ unsigned error = 0;
+ ucvector header;
+ ucvector_init(&header);
+
+ lodepng_add32bitInt(&header, w); /*width*/
+ lodepng_add32bitInt(&header, h); /*height*/
+ ucvector_push_back(&header, (unsigned char)bitdepth); /*bit depth*/
+ ucvector_push_back(&header, (unsigned char)colortype); /*color type*/
+ ucvector_push_back(&header, 0); /*compression method*/
+ ucvector_push_back(&header, 0); /*filter method*/
+ ucvector_push_back(&header, interlace_method); /*interlace method*/
+
+ error = addChunk(out, "IHDR", header.data, header.size);
+ ucvector_cleanup(&header);
+
+ return error;
+}
+
+static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) {
+ unsigned error = 0;
+ size_t i;
+ ucvector PLTE;
+ ucvector_init(&PLTE);
+ for(i = 0; i != info->palettesize * 4; ++i) {
+ /*add all channels except alpha channel*/
+ if(i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]);
+ }
+ error = addChunk(out, "PLTE", PLTE.data, PLTE.size);
+ ucvector_cleanup(&PLTE);
+
+ return error;
+}
+
+static unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info) {
+ unsigned error = 0;
+ size_t i;
+ ucvector tRNS;
+ ucvector_init(&tRNS);
+ if(info->colortype == LCT_PALETTE) {
+ size_t amount = info->palettesize;
+ /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/
+ for(i = info->palettesize; i != 0; --i) {
+ if(info->palette[4 * (i - 1) + 3] == 255) --amount;
+ else break;
+ }
+ /*add only alpha channel*/
+ for(i = 0; i != amount; ++i) ucvector_push_back(&tRNS, info->palette[4 * i + 3]);
+ } else if(info->colortype == LCT_GREY) {
+ if(info->key_defined) {
+ ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8));
+ ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255));
+ }
+ } else if(info->colortype == LCT_RGB) {
+ if(info->key_defined) {
+ ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8));
+ ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255));
+ ucvector_push_back(&tRNS, (unsigned char)(info->key_g >> 8));
+ ucvector_push_back(&tRNS, (unsigned char)(info->key_g & 255));
+ ucvector_push_back(&tRNS, (unsigned char)(info->key_b >> 8));
+ ucvector_push_back(&tRNS, (unsigned char)(info->key_b & 255));
+ }
+ }
+
+ error = addChunk(out, "tRNS", tRNS.data, tRNS.size);
+ ucvector_cleanup(&tRNS);
+
+ return error;
+}
+
+static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize,
+ LodePNGCompressSettings* zlibsettings) {
+ ucvector zlibdata;
+ unsigned error = 0;
+
+ /*compress with the Zlib compressor*/
+ ucvector_init(&zlibdata);
+ error = zlib_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings);
+ if(!error) error = addChunk(out, "IDAT", zlibdata.data, zlibdata.size);
+ ucvector_cleanup(&zlibdata);
+
+ return error;
+}
+
+static unsigned addChunk_IEND(ucvector* out) {
+ unsigned error = 0;
+ error = addChunk(out, "IEND", 0, 0);
+ return error;
+}
+
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+
+static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) {
+ unsigned error = 0;
+ size_t i;
+ ucvector text;
+ ucvector_init(&text);
+ for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)keyword[i]);
+ if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
+ ucvector_push_back(&text, 0); /*0 termination char*/
+ for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)textstring[i]);
+ error = addChunk(out, "tEXt", text.data, text.size);
+ ucvector_cleanup(&text);
+
+ return error;
+}
+
+static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring,
+ LodePNGCompressSettings* zlibsettings) {
+ unsigned error = 0;
+ ucvector data, compressed;
+ size_t i, textsize = strlen(textstring);
+
+ ucvector_init(&data);
+ ucvector_init(&compressed);
+ for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]);
+ if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
+ ucvector_push_back(&data, 0); /*0 termination char*/
+ ucvector_push_back(&data, 0); /*compression method: 0*/
+
+ error = zlib_compress(&compressed.data, &compressed.size,
+ (unsigned char*)textstring, textsize, zlibsettings);
+ if(!error) {
+ for(i = 0; i != compressed.size; ++i) ucvector_push_back(&data, compressed.data[i]);
+ error = addChunk(out, "zTXt", data.data, data.size);
+ }
+
+ ucvector_cleanup(&compressed);
+ ucvector_cleanup(&data);
+ return error;
+}
+
+static unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* keyword, const char* langtag,
+ const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings) {
+ unsigned error = 0;
+ ucvector data;
+ size_t i, textsize = strlen(textstring);
+
+ ucvector_init(&data);
+
+ for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]);
+ if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
+ ucvector_push_back(&data, 0); /*null termination char*/
+ ucvector_push_back(&data, compressed ? 1 : 0); /*compression flag*/
+ ucvector_push_back(&data, 0); /*compression method*/
+ for(i = 0; langtag[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)langtag[i]);
+ ucvector_push_back(&data, 0); /*null termination char*/
+ for(i = 0; transkey[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)transkey[i]);
+ ucvector_push_back(&data, 0); /*null termination char*/
+
+ if(compressed) {
+ ucvector compressed_data;
+ ucvector_init(&compressed_data);
+ error = zlib_compress(&compressed_data.data, &compressed_data.size,
+ (unsigned char*)textstring, textsize, zlibsettings);
+ if(!error) {
+ for(i = 0; i != compressed_data.size; ++i) ucvector_push_back(&data, compressed_data.data[i]);
+ }
+ ucvector_cleanup(&compressed_data);
+ } else /*not compressed*/ {
+ for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)textstring[i]);
+ }
+
+ if(!error) error = addChunk(out, "iTXt", data.data, data.size);
+ ucvector_cleanup(&data);
+ return error;
+}
+
+static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) {
+ unsigned error = 0;
+ ucvector bKGD;
+ ucvector_init(&bKGD);
+ if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) {
+ ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8));
+ ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255));
+ } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) {
+ ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8));
+ ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255));
+ ucvector_push_back(&bKGD, (unsigned char)(info->background_g >> 8));
+ ucvector_push_back(&bKGD, (unsigned char)(info->background_g & 255));
+ ucvector_push_back(&bKGD, (unsigned char)(info->background_b >> 8));
+ ucvector_push_back(&bKGD, (unsigned char)(info->background_b & 255));
+ } else if(info->color.colortype == LCT_PALETTE) {
+ ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); /*palette index*/
+ }
+
+ error = addChunk(out, "bKGD", bKGD.data, bKGD.size);
+ ucvector_cleanup(&bKGD);
+
+ return error;
+}
+
+static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) {
+ unsigned error = 0;
+ unsigned char* data = (unsigned char*)lodepng_malloc(7);
+ if(!data) return 83; /*alloc fail*/
+ data[0] = (unsigned char)(time->year >> 8);
+ data[1] = (unsigned char)(time->year & 255);
+ data[2] = (unsigned char)time->month;
+ data[3] = (unsigned char)time->day;
+ data[4] = (unsigned char)time->hour;
+ data[5] = (unsigned char)time->minute;
+ data[6] = (unsigned char)time->second;
+ error = addChunk(out, "tIME", data, 7);
+ lodepng_free(data);
+ return error;
+}
+
+static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) {
+ unsigned error = 0;
+ ucvector data;
+ ucvector_init(&data);
+
+ lodepng_add32bitInt(&data, info->phys_x);
+ lodepng_add32bitInt(&data, info->phys_y);
+ ucvector_push_back(&data, info->phys_unit);
+
+ error = addChunk(out, "pHYs", data.data, data.size);
+ ucvector_cleanup(&data);
+
+ return error;
+}
+
+static unsigned addChunk_gAMA(ucvector* out, const LodePNGInfo* info) {
+ unsigned error = 0;
+ ucvector data;
+ ucvector_init(&data);
+
+ lodepng_add32bitInt(&data, info->gama_gamma);
+
+ error = addChunk(out, "gAMA", data.data, data.size);
+ ucvector_cleanup(&data);
+
+ return error;
+}
+
+static unsigned addChunk_cHRM(ucvector* out, const LodePNGInfo* info) {
+ unsigned error = 0;
+ ucvector data;
+ ucvector_init(&data);
+
+ lodepng_add32bitInt(&data, info->chrm_white_x);
+ lodepng_add32bitInt(&data, info->chrm_white_y);
+ lodepng_add32bitInt(&data, info->chrm_red_x);
+ lodepng_add32bitInt(&data, info->chrm_red_y);
+ lodepng_add32bitInt(&data, info->chrm_green_x);
+ lodepng_add32bitInt(&data, info->chrm_green_y);
+ lodepng_add32bitInt(&data, info->chrm_blue_x);
+ lodepng_add32bitInt(&data, info->chrm_blue_y);
+
+ error = addChunk(out, "cHRM", data.data, data.size);
+ ucvector_cleanup(&data);
+
+ return error;
+}
+
+static unsigned addChunk_sRGB(ucvector* out, const LodePNGInfo* info) {
+ unsigned char data = info->srgb_intent;
+ return addChunk(out, "sRGB", &data, 1);
+}
+
+static unsigned addChunk_iCCP(ucvector* out, const LodePNGInfo* info, LodePNGCompressSettings* zlibsettings) {
+ unsigned error = 0;
+ ucvector data, compressed;
+ size_t i;
+
+ ucvector_init(&data);
+ ucvector_init(&compressed);
+ for(i = 0; info->iccp_name[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)info->iccp_name[i]);
+ if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
+ ucvector_push_back(&data, 0); /*0 termination char*/
+ ucvector_push_back(&data, 0); /*compression method: 0*/
+
+ error = zlib_compress(&compressed.data, &compressed.size,
+ info->iccp_profile, info->iccp_profile_size, zlibsettings);
+ if(!error) {
+ for(i = 0; i != compressed.size; ++i) ucvector_push_back(&data, compressed.data[i]);
+ error = addChunk(out, "iCCP", data.data, data.size);
+ }
+
+ ucvector_cleanup(&compressed);
+ ucvector_cleanup(&data);
+ return error;
+}
+
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+
+static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline,
+ size_t length, size_t bytewidth, unsigned char filterType) {
+ size_t i;
+ switch(filterType) {
+ case 0: /*None*/
+ for(i = 0; i != length; ++i) out[i] = scanline[i];
+ break;
+ case 1: /*Sub*/
+ for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];
+ for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth];
+ break;
+ case 2: /*Up*/
+ if(prevline) {
+ for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i];
+ } else {
+ for(i = 0; i != length; ++i) out[i] = scanline[i];
+ }
+ break;
+ case 3: /*Average*/
+ if(prevline) {
+ for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1);
+ for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1);
+ } else {
+ for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];
+ for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1);
+ }
+ break;
+ case 4: /*Paeth*/
+ if(prevline) {
+ /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/
+ for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]);
+ for(i = bytewidth; i < length; ++i) {
+ out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth]));
+ }
+ } else {
+ for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];
+ /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/
+ for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]);
+ }
+ break;
+ default: return; /*unexisting filter type given*/
+ }
+}
+
+/* log2 approximation. A slight bit faster than std::log. */
+static float flog2(float f) {
+ float result = 0;
+ while(f > 32) { result += 4; f /= 16; }
+ while(f > 2) { ++result; f /= 2; }
+ return result + 1.442695f * (f * f * f / 3 - 3 * f * f / 2 + 3 * f - 1.83333f);
+}
+
+static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h,
+ const LodePNGColorMode* info, const LodePNGEncoderSettings* settings) {
+ /*
+ For PNG filter method 0
+ out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are
+ the scanlines with 1 extra byte per scanline
+ */
+
+ unsigned bpp = lodepng_get_bpp(info);
+ /*the width of a scanline in bytes, not including the filter type*/
+ size_t linebytes = (w * bpp + 7) / 8;
+ /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
+ size_t bytewidth = (bpp + 7) / 8;
+ const unsigned char* prevline = 0;
+ unsigned x, y;
+ unsigned error = 0;
+ LodePNGFilterStrategy strategy = settings->filter_strategy;
+
+ /*
+ There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard:
+ * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e.
+ use fixed filtering, with the filter None).
+ * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is
+ not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply
+ all five filters and select the filter that produces the smallest sum of absolute values per row.
+ This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true.
+
+ If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed,
+ but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum
+ heuristic is used.
+ */
+ if(settings->filter_palette_zero &&
+ (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO;
+
+ if(bpp == 0) return 31; /*error: invalid color type*/
+
+ if(strategy == LFS_ZERO) {
+ for(y = 0; y != h; ++y) {
+ size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
+ size_t inindex = linebytes * y;
+ out[outindex] = 0; /*filter type byte*/
+ filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, 0);
+ prevline = &in[inindex];
+ }
+ } else if(strategy == LFS_MINSUM) {
+ /*adaptive filtering*/
+ size_t sum[5];
+ unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
+ size_t smallest = 0;
+ unsigned char type, bestType = 0;
+
+ for(type = 0; type != 5; ++type) {
+ attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
+ if(!attempt[type]) return 83; /*alloc fail*/
+ }
+
+ if(!error) {
+ for(y = 0; y != h; ++y) {
+ /*try the 5 filter types*/
+ for(type = 0; type != 5; ++type) {
+ filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
+
+ /*calculate the sum of the result*/
+ sum[type] = 0;
+ if(type == 0) {
+ for(x = 0; x != linebytes; ++x) sum[type] += (unsigned char)(attempt[type][x]);
+ } else {
+ for(x = 0; x != linebytes; ++x) {
+ /*For differences, each byte should be treated as signed, values above 127 are negative
+ (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there.
+ This means filtertype 0 is almost never chosen, but that is justified.*/
+ unsigned char s = attempt[type][x];
+ sum[type] += s < 128 ? s : (255U - s);
+ }
+ }
+
+ /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
+ if(type == 0 || sum[type] < smallest) {
+ bestType = type;
+ smallest = sum[type];
+ }
+ }
+
+ prevline = &in[y * linebytes];
+
+ /*now fill the out values*/
+ out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
+ for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
+ }
+ }
+
+ for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
+ } else if(strategy == LFS_ENTROPY) {
+ float sum[5];
+ unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
+ float smallest = 0;
+ unsigned type, bestType = 0;
+ unsigned count[256];
+
+ for(type = 0; type != 5; ++type) {
+ attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
+ if(!attempt[type]) return 83; /*alloc fail*/
+ }
+
+ for(y = 0; y != h; ++y) {
+ /*try the 5 filter types*/
+ for(type = 0; type != 5; ++type) {
+ filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
+ for(x = 0; x != 256; ++x) count[x] = 0;
+ for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]];
+ ++count[type]; /*the filter type itself is part of the scanline*/
+ sum[type] = 0;
+ for(x = 0; x != 256; ++x) {
+ float p = count[x] / (float)(linebytes + 1);
+ sum[type] += count[x] == 0 ? 0 : flog2(1 / p) * p;
+ }
+ /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
+ if(type == 0 || sum[type] < smallest) {
+ bestType = type;
+ smallest = sum[type];
+ }
+ }
+
+ prevline = &in[y * linebytes];
+
+ /*now fill the out values*/
+ out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
+ for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
+ }
+
+ for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
+ } else if(strategy == LFS_PREDEFINED) {
+ for(y = 0; y != h; ++y) {
+ size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
+ size_t inindex = linebytes * y;
+ unsigned char type = settings->predefined_filters[y];
+ out[outindex] = type; /*filter type byte*/
+ filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);
+ prevline = &in[inindex];
+ }
+ } else if(strategy == LFS_BRUTE_FORCE) {
+ /*brute force filter chooser.
+ deflate the scanline after every filter attempt to see which one deflates best.
+ This is very slow and gives only slightly smaller, sometimes even larger, result*/
+ size_t size[5];
+ unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
+ size_t smallest = 0;
+ unsigned type = 0, bestType = 0;
+ unsigned char* dummy;
+ LodePNGCompressSettings zlibsettings = settings->zlibsettings;
+ /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose,
+ to simulate the true case where the tree is the same for the whole image. Sometimes it gives
+ better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare
+ cases better compression. It does make this a bit less slow, so it's worth doing this.*/
+ zlibsettings.btype = 1;
+ /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG
+ images only, so disable it*/
+ zlibsettings.custom_zlib = 0;
+ zlibsettings.custom_deflate = 0;
+ for(type = 0; type != 5; ++type) {
+ attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
+ if(!attempt[type]) return 83; /*alloc fail*/
+ }
+ for(y = 0; y != h; ++y) /*try the 5 filter types*/ {
+ for(type = 0; type != 5; ++type) {
+ unsigned testsize = (unsigned)linebytes;
+ /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/
+
+ filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
+ size[type] = 0;
+ dummy = 0;
+ zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings);
+ lodepng_free(dummy);
+ /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/
+ if(type == 0 || size[type] < smallest) {
+ bestType = type;
+ smallest = size[type];
+ }
+ }
+ prevline = &in[y * linebytes];
+ out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
+ for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
+ }
+ for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
+ }
+ else return 88; /* unknown filter strategy */
+
+ return error;
+}
+
+static void addPaddingBits(unsigned char* out, const unsigned char* in,
+ size_t olinebits, size_t ilinebits, unsigned h) {
+ /*The opposite of the removePaddingBits function
+ olinebits must be >= ilinebits*/
+ unsigned y;
+ size_t diff = olinebits - ilinebits;
+ size_t obp = 0, ibp = 0; /*bit pointers*/
+ for(y = 0; y != h; ++y) {
+ size_t x;
+ for(x = 0; x < ilinebits; ++x) {
+ unsigned char bit = readBitFromReversedStream(&ibp, in);
+ setBitOfReversedStream(&obp, out, bit);
+ }
+ /*obp += diff; --> no, fill in some value in the padding bits too, to avoid
+ "Use of uninitialised value of size ###" warning from valgrind*/
+ for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0);
+ }
+}
+
+/*
+in: non-interlaced image with size w*h
+out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with
+ no padding bits between scanlines, but between reduced images so that each
+ reduced image starts at a byte.
+bpp: bits per pixel
+there are no padding bits, not between scanlines, not between reduced images
+in has the following size in bits: w * h * bpp.
+out is possibly bigger due to padding bits between reduced images
+NOTE: comments about padding bits are only relevant if bpp < 8
+*/
+static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) {
+ unsigned passw[7], passh[7];
+ size_t filter_passstart[8], padded_passstart[8], passstart[8];
+ unsigned i;
+
+ Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
+
+ if(bpp >= 8) {
+ for(i = 0; i != 7; ++i) {
+ unsigned x, y, b;
+ size_t bytewidth = bpp / 8;
+ for(y = 0; y < passh[i]; ++y)
+ for(x = 0; x < passw[i]; ++x) {
+ size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;
+ size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth;
+ for(b = 0; b < bytewidth; ++b) {
+ out[pixeloutstart + b] = in[pixelinstart + b];
+ }
+ }
+ }
+ } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ {
+ for(i = 0; i != 7; ++i) {
+ unsigned x, y, b;
+ unsigned ilinebits = bpp * passw[i];
+ unsigned olinebits = bpp * w;
+ size_t obp, ibp; /*bit pointers (for out and in buffer)*/
+ for(y = 0; y < passh[i]; ++y)
+ for(x = 0; x < passw[i]; ++x) {
+ ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;
+ obp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
+ for(b = 0; b < bpp; ++b) {
+ unsigned char bit = readBitFromReversedStream(&ibp, in);
+ setBitOfReversedStream(&obp, out, bit);
+ }
+ }
+ }
+ }
+}
+
+/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image.
+return value is error**/
+static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in,
+ unsigned w, unsigned h,
+ const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings) {
+ /*
+ This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps:
+ *) if no Adam7: 1) add padding bits (= posible extra bits per scanline if bpp < 8) 2) filter
+ *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter
+ */
+ unsigned bpp = lodepng_get_bpp(&info_png->color);
+ unsigned error = 0;
+
+ if(info_png->interlace_method == 0) {
+ *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/
+ *out = (unsigned char*)lodepng_malloc(*outsize);
+ if(!(*out) && (*outsize)) error = 83; /*alloc fail*/
+
+ if(!error) {
+ /*non multiple of 8 bits per scanline, padding bits needed per scanline*/
+ if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) {
+ unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7) / 8));
+ if(!padded) error = 83; /*alloc fail*/
+ if(!error) {
+ addPaddingBits(padded, in, ((w * bpp + 7) / 8) * 8, w * bpp, h);
+ error = filter(*out, padded, w, h, &info_png->color, settings);
+ }
+ lodepng_free(padded);
+ } else {
+ /*we can immediately filter into the out buffer, no other steps needed*/
+ error = filter(*out, in, w, h, &info_png->color, settings);
+ }
+ }
+ } else /*interlace_method is 1 (Adam7)*/ {
+ unsigned passw[7], passh[7];
+ size_t filter_passstart[8], padded_passstart[8], passstart[8];
+ unsigned char* adam7;
+
+ Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
+
+ *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/
+ *out = (unsigned char*)lodepng_malloc(*outsize);
+ if(!(*out)) error = 83; /*alloc fail*/
+
+ adam7 = (unsigned char*)lodepng_malloc(passstart[7]);
+ if(!adam7 && passstart[7]) error = 83; /*alloc fail*/
+
+ if(!error) {
+ unsigned i;
+
+ Adam7_interlace(adam7, in, w, h, bpp);
+ for(i = 0; i != 7; ++i) {
+ if(bpp < 8) {
+ unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]);
+ if(!padded) ERROR_BREAK(83); /*alloc fail*/
+ addPaddingBits(padded, &adam7[passstart[i]],
+ ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]);
+ error = filter(&(*out)[filter_passstart[i]], padded,
+ passw[i], passh[i], &info_png->color, settings);
+ lodepng_free(padded);
+ } else {
+ error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]],
+ passw[i], passh[i], &info_png->color, settings);
+ }
+
+ if(error) break;
+ }
+ }
+
+ lodepng_free(adam7);
+ }
+
+ return error;
+}
+
+/*
+palette must have 4 * palettesize bytes allocated, and given in format RGBARGBARGBARGBA...
+returns 0 if the palette is opaque,
+returns 1 if the palette has a single color with alpha 0 ==> color key
+returns 2 if the palette is semi-translucent.
+*/
+static unsigned getPaletteTranslucency(const unsigned char* palette, size_t palettesize) {
+ size_t i;
+ unsigned key = 0;
+ unsigned r = 0, g = 0, b = 0; /*the value of the color with alpha 0, so long as color keying is possible*/
+ for(i = 0; i != palettesize; ++i) {
+ if(!key && palette[4 * i + 3] == 0) {
+ r = palette[4 * i + 0]; g = palette[4 * i + 1]; b = palette[4 * i + 2];
+ key = 1;
+ i = (size_t)(-1); /*restart from beginning, to detect earlier opaque colors with key's value*/
+ }
+ else if(palette[4 * i + 3] != 255) return 2;
+ /*when key, no opaque RGB may have key's RGB*/
+ else if(key && r == palette[i * 4 + 0] && g == palette[i * 4 + 1] && b == palette[i * 4 + 2]) return 2;
+ }
+ return key;
+}
+
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) {
+ unsigned char* inchunk = data;
+ while((size_t)(inchunk - data) < datasize) {
+ CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk));
+ out->allocsize = out->size; /*fix the allocsize again*/
+ inchunk = lodepng_chunk_next(inchunk);
+ }
+ return 0;
+}
+
+static unsigned isGrayICCProfile(const unsigned char* profile, unsigned size) {
+ /*
+ It is a gray profile if bytes 16-19 are "GRAY", rgb profile if bytes 16-19
+ are "RGB ". We do not perform any full parsing of the ICC profile here, other
+ than check those 4 bytes to grayscale profile. Other than that, validity of
+ the profile is not checked. This is needed only because the PNG specification
+ requires using a non-gray color model if there is an ICC profile with "RGB "
+ (sadly limiting compression opportunities if the input data is grayscale RGB
+ data), and requires using a gray color model if it is "GRAY".
+ */
+ if(size < 20) return 0;
+ return profile[16] == 'G' && profile[17] == 'R' && profile[18] == 'A' && profile[19] == 'Y';
+}
+
+static unsigned isRGBICCProfile(const unsigned char* profile, unsigned size) {
+ /* See comment in isGrayICCProfile*/
+ if(size < 20) return 0;
+ return profile[16] == 'R' && profile[17] == 'G' && profile[18] == 'B' && profile[19] == ' ';
+}
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+
+unsigned lodepng_encode(unsigned char** out, size_t* outsize,
+ const unsigned char* image, unsigned w, unsigned h,
+ LodePNGState* state) {
+ unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/
+ size_t datasize = 0;
+ ucvector outv;
+ LodePNGInfo info;
+
+ ucvector_init(&outv);
+ lodepng_info_init(&info);
+
+ /*provide some proper output values if error will happen*/
+ *out = 0;
+ *outsize = 0;
+ state->error = 0;
+
+ /*check input values validity*/
+ if((state->info_png.color.colortype == LCT_PALETTE || state->encoder.force_palette)
+ && (state->info_png.color.palettesize == 0 || state->info_png.color.palettesize > 256)) {
+ state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/
+ goto cleanup;
+ }
+ if(state->encoder.zlibsettings.btype > 2) {
+ state->error = 61; /*error: unexisting btype*/
+ goto cleanup;
+ }
+ if(state->info_png.interlace_method > 1) {
+ state->error = 71; /*error: unexisting interlace mode*/
+ goto cleanup;
+ }
+ state->error = checkColorValidity(state->info_png.color.colortype, state->info_png.color.bitdepth);
+ if(state->error) goto cleanup; /*error: unexisting color type given*/
+ state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth);
+ if(state->error) goto cleanup; /*error: unexisting color type given*/
+
+ /* color convert and compute scanline filter types */
+ lodepng_info_copy(&info, &state->info_png);
+ if(state->encoder.auto_convert) {
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ if(state->info_png.background_defined) {
+ unsigned bg_r = state->info_png.background_r;
+ unsigned bg_g = state->info_png.background_g;
+ unsigned bg_b = state->info_png.background_b;
+ unsigned r = 0, g = 0, b = 0;
+ LodePNGColorProfile prof;
+ LodePNGColorMode mode16 = lodepng_color_mode_make(LCT_RGB, 16);
+ lodepng_convert_rgb(&r, &g, &b, bg_r, bg_g, bg_b, &mode16, &state->info_png.color);
+ lodepng_color_profile_init(&prof);
+ state->error = lodepng_get_color_profile(&prof, image, w, h, &state->info_raw);
+ if(state->error) goto cleanup;
+ lodepng_color_profile_add(&prof, r, g, b, 65535);
+ state->error = auto_choose_color_from_profile(&info.color, &state->info_raw, &prof);
+ if(state->error) goto cleanup;
+ if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b,
+ bg_r, bg_g, bg_b, &info.color, &state->info_png.color)) {
+ state->error = 104;
+ goto cleanup;
+ }
+ }
+ else
+#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */
+ {
+ state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw);
+ if(state->error) goto cleanup;
+ }
+ }
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ if(state->info_png.iccp_defined) {
+ unsigned gray_icc = isGrayICCProfile(state->info_png.iccp_profile, state->info_png.iccp_profile_size);
+ unsigned gray_png = info.color.colortype == LCT_GREY || info.color.colortype == LCT_GREY_ALPHA;
+ /* TODO: perhaps instead of giving errors or less optimal compression, we can automatically modify
+ the ICC profile here to say "GRAY" or "RGB " to match the PNG color type, unless this will require
+ non trivial changes to the rest of the ICC profile */
+ if(!gray_icc && !isRGBICCProfile(state->info_png.iccp_profile, state->info_png.iccp_profile_size)) {
+ state->error = 100; /* Disallowed profile color type for PNG */
+ goto cleanup;
+ }
+ if(!state->encoder.auto_convert && gray_icc != gray_png) {
+ /* Non recoverable: encoder not allowed to convert color type, and requested color type not
+ compatible with ICC color type */
+ state->error = 101;
+ goto cleanup;
+ }
+ if(gray_icc && !gray_png) {
+ /* Non recoverable: trying to set grayscale ICC profile while colored pixels were given */
+ state->error = 102;
+ goto cleanup;
+ /* NOTE: this relies on the fact that lodepng_auto_choose_color never returns palette for grayscale pixels */
+ }
+ if(!gray_icc && gray_png) {
+ /* Recoverable but an unfortunate loss in compression density: We have grayscale pixels but
+ are forced to store them in more expensive RGB format that will repeat each value 3 times
+ because the PNG spec does not allow an RGB ICC profile with internal grayscale color data */
+ if(info.color.colortype == LCT_GREY) info.color.colortype = LCT_RGB;
+ if(info.color.colortype == LCT_GREY_ALPHA) info.color.colortype = LCT_RGBA;
+ if(info.color.bitdepth < 8) info.color.bitdepth = 8;
+ }
+ }
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) {
+ unsigned char* converted;
+ size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8;
+
+ converted = (unsigned char*)lodepng_malloc(size);
+ if(!converted && size) state->error = 83; /*alloc fail*/
+ if(!state->error) {
+ state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h);
+ }
+ if(!state->error) preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder);
+ lodepng_free(converted);
+ if(state->error) goto cleanup;
+ }
+ else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder);
+
+ /* output all PNG chunks */ {
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ size_t i;
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ /*write signature and chunks*/
+ writeSignature(&outv);
+ /*IHDR*/
+ addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method);
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ /*unknown chunks between IHDR and PLTE*/
+ if(info.unknown_chunks_data[0]) {
+ state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]);
+ if(state->error) goto cleanup;
+ }
+ /*color profile chunks must come before PLTE */
+ if(info.iccp_defined) addChunk_iCCP(&outv, &info, &state->encoder.zlibsettings);
+ if(info.srgb_defined) addChunk_sRGB(&outv, &info);
+ if(info.gama_defined) addChunk_gAMA(&outv, &info);
+ if(info.chrm_defined) addChunk_cHRM(&outv, &info);
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ /*PLTE*/
+ if(info.color.colortype == LCT_PALETTE) {
+ addChunk_PLTE(&outv, &info.color);
+ }
+ if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) {
+ addChunk_PLTE(&outv, &info.color);
+ }
+ /*tRNS*/
+ if(info.color.colortype == LCT_PALETTE && getPaletteTranslucency(info.color.palette, info.color.palettesize) != 0) {
+ addChunk_tRNS(&outv, &info.color);
+ }
+ if((info.color.colortype == LCT_GREY || info.color.colortype == LCT_RGB) && info.color.key_defined) {
+ addChunk_tRNS(&outv, &info.color);
+ }
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ /*bKGD (must come between PLTE and the IDAt chunks*/
+ if(info.background_defined) {
+ state->error = addChunk_bKGD(&outv, &info);
+ if(state->error) goto cleanup;
+ }
+ /*pHYs (must come before the IDAT chunks)*/
+ if(info.phys_defined) addChunk_pHYs(&outv, &info);
+
+ /*unknown chunks between PLTE and IDAT*/
+ if(info.unknown_chunks_data[1]) {
+ state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]);
+ if(state->error) goto cleanup;
+ }
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ /*IDAT (multiple IDAT chunks must be consecutive)*/
+ state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings);
+ if(state->error) goto cleanup;
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ /*tIME*/
+ if(info.time_defined) addChunk_tIME(&outv, &info.time);
+ /*tEXt and/or zTXt*/
+ for(i = 0; i != info.text_num; ++i) {
+ if(strlen(info.text_keys[i]) > 79) {
+ state->error = 66; /*text chunk too large*/
+ goto cleanup;
+ }
+ if(strlen(info.text_keys[i]) < 1) {
+ state->error = 67; /*text chunk too small*/
+ goto cleanup;
+ }
+ if(state->encoder.text_compression) {
+ addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings);
+ } else {
+ addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]);
+ }
+ }
+ /*LodePNG version id in text chunk*/
+ if(state->encoder.add_id) {
+ unsigned already_added_id_text = 0;
+ for(i = 0; i != info.text_num; ++i) {
+ if(!strcmp(info.text_keys[i], "LodePNG")) {
+ already_added_id_text = 1;
+ break;
+ }
+ }
+ if(already_added_id_text == 0) {
+ addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/
+ }
+ }
+ /*iTXt*/
+ for(i = 0; i != info.itext_num; ++i) {
+ if(strlen(info.itext_keys[i]) > 79) {
+ state->error = 66; /*text chunk too large*/
+ goto cleanup;
+ }
+ if(strlen(info.itext_keys[i]) < 1) {
+ state->error = 67; /*text chunk too small*/
+ goto cleanup;
+ }
+ addChunk_iTXt(&outv, state->encoder.text_compression,
+ info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i],
+ &state->encoder.zlibsettings);
+ }
+
+ /*unknown chunks between IDAT and IEND*/
+ if(info.unknown_chunks_data[2]) {
+ state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]);
+ if(state->error) goto cleanup;
+ }
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+ addChunk_IEND(&outv);
+ }
+
+cleanup:
+ lodepng_info_cleanup(&info);
+ lodepng_free(data);
+
+ /*instead of cleaning the vector up, give it to the output*/
+ *out = outv.data;
+ *outsize = outv.size;
+
+ return state->error;
+}
+
+unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image,
+ unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) {
+ unsigned error;
+ LodePNGState state;
+ lodepng_state_init(&state);
+ state.info_raw.colortype = colortype;
+ state.info_raw.bitdepth = bitdepth;
+ state.info_png.color.colortype = colortype;
+ state.info_png.color.bitdepth = bitdepth;
+ lodepng_encode(out, outsize, image, w, h, &state);
+ error = state.error;
+ lodepng_state_cleanup(&state);
+ return error;
+}
+
+unsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) {
+ return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8);
+}
+
+unsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) {
+ return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8);
+}
+
+#ifdef LODEPNG_COMPILE_DISK
+unsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h,
+ LodePNGColorType colortype, unsigned bitdepth) {
+ unsigned char* buffer;
+ size_t buffersize;
+ unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth);
+ if(!error) error = lodepng_save_file(buffer, buffersize, filename);
+ lodepng_free(buffer);
+ return error;
+}
+
+unsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) {
+ return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8);
+}
+
+unsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) {
+ return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8);
+}
+#endif /*LODEPNG_COMPILE_DISK*/
+
+void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings) {
+ lodepng_compress_settings_init(&settings->zlibsettings);
+ settings->filter_palette_zero = 1;
+ settings->filter_strategy = LFS_MINSUM;
+ settings->auto_convert = 1;
+ settings->force_palette = 0;
+ settings->predefined_filters = 0;
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ settings->add_id = 0;
+ settings->text_compression = 1;
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+}
+
+#endif /*LODEPNG_COMPILE_ENCODER*/
+#endif /*LODEPNG_COMPILE_PNG*/
+
+#ifdef LODEPNG_COMPILE_ERROR_TEXT
+/*
+This returns the description of a numerical error code in English. This is also
+the documentation of all the error codes.
+*/
+const char* lodepng_error_text(unsigned code) {
+ switch(code) {
+ case 0: return "no error, everything went ok";
+ case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/
+ case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/
+ case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/
+ case 13: return "problem while processing dynamic deflate block";
+ case 14: return "problem while processing dynamic deflate block";
+ case 15: return "problem while processing dynamic deflate block";
+ case 16: return "unexisting code while processing dynamic deflate block";
+ case 17: return "end of out buffer memory reached while inflating";
+ case 18: return "invalid distance code while inflating";
+ case 19: return "end of out buffer memory reached while inflating";
+ case 20: return "invalid deflate block BTYPE encountered while decoding";
+ case 21: return "NLEN is not ones complement of LEN in a deflate block";
+
+ /*end of out buffer memory reached while inflating:
+ This can happen if the inflated deflate data is longer than the amount of bytes required to fill up
+ all the pixels of the image, given the color depth and image dimensions. Something that doesn't
+ happen in a normal, well encoded, PNG image.*/
+ case 22: return "end of out buffer memory reached while inflating";
+ case 23: return "end of in buffer memory reached while inflating";
+ case 24: return "invalid FCHECK in zlib header";
+ case 25: return "invalid compression method in zlib header";
+ case 26: return "FDICT encountered in zlib header while it's not used for PNG";
+ case 27: return "PNG file is smaller than a PNG header";
+ /*Checks the magic file header, the first 8 bytes of the PNG file*/
+ case 28: return "incorrect PNG signature, it's no PNG or corrupted";
+ case 29: return "first chunk is not the header chunk";
+ case 30: return "chunk length too large, chunk broken off at end of file";
+ case 31: return "illegal PNG color type or bpp";
+ case 32: return "illegal PNG compression method";
+ case 33: return "illegal PNG filter method";
+ case 34: return "illegal PNG interlace method";
+ case 35: return "chunk length of a chunk is too large or the chunk too small";
+ case 36: return "illegal PNG filter type encountered";
+ case 37: return "illegal bit depth for this color type given";
+ case 38: return "the palette is too big"; /*more than 256 colors*/
+ case 39: return "tRNS chunk before PLTE or has more entries than palette size";
+ case 40: return "tRNS chunk has wrong size for grayscale image";
+ case 41: return "tRNS chunk has wrong size for RGB image";
+ case 42: return "tRNS chunk appeared while it was not allowed for this color type";
+ case 43: return "bKGD chunk has wrong size for palette image";
+ case 44: return "bKGD chunk has wrong size for grayscale image";
+ case 45: return "bKGD chunk has wrong size for RGB image";
+ case 48: return "empty input buffer given to decoder. Maybe caused by non-existing file?";
+ case 49: return "jumped past memory while generating dynamic huffman tree";
+ case 50: return "jumped past memory while generating dynamic huffman tree";
+ case 51: return "jumped past memory while inflating huffman block";
+ case 52: return "jumped past memory while inflating";
+ case 53: return "size of zlib data too small";
+ case 54: return "repeat symbol in tree while there was no value symbol yet";
+ /*jumped past tree while generating huffman tree, this could be when the
+ tree will have more leaves than symbols after generating it out of the
+ given lenghts. They call this an oversubscribed dynamic bit lengths tree in zlib.*/
+ case 55: return "jumped past tree while generating huffman tree";
+ case 56: return "given output image colortype or bitdepth not supported for color conversion";
+ case 57: return "invalid CRC encountered (checking CRC can be disabled)";
+ case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)";
+ case 59: return "requested color conversion not supported";
+ case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)";
+ case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)";
+ /*LodePNG leaves the choice of RGB to grayscale conversion formula to the user.*/
+ case 62: return "conversion from color to grayscale not supported";
+ /*(2^31-1)*/
+ case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk";
+ /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/
+ case 64: return "the length of the END symbol 256 in the Huffman tree is 0";
+ case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes";
+ case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte";
+ case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors";
+ case 69: return "unknown chunk type with 'critical' flag encountered by the decoder";
+ case 71: return "unexisting interlace mode given to encoder (must be 0 or 1)";
+ case 72: return "while decoding, unexisting compression method encountering in zTXt or iTXt chunk (it must be 0)";
+ case 73: return "invalid tIME chunk size";
+ case 74: return "invalid pHYs chunk size";
+ /*length could be wrong, or data chopped off*/
+ case 75: return "no null termination char found while decoding text chunk";
+ case 76: return "iTXt chunk too short to contain required bytes";
+ case 77: return "integer overflow in buffer size";
+ case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/
+ case 79: return "failed to open file for writing";
+ case 80: return "tried creating a tree of 0 symbols";
+ case 81: return "lazy matching at pos 0 is impossible";
+ case 82: return "color conversion to palette requested while a color isn't in palette, or index out of bounds";
+ case 83: return "memory allocation failed";
+ case 84: return "given image too small to contain all pixels to be encoded";
+ case 86: return "impossible offset in lz77 encoding (internal bug)";
+ case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined";
+ case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy";
+ case 89: return "text chunk keyword too short or long: must have size 1-79";
+ /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/
+ case 90: return "windowsize must be a power of two";
+ case 91: return "invalid decompressed idat size";
+ case 92: return "integer overflow due to too many pixels";
+ case 93: return "zero width or height is invalid";
+ case 94: return "header chunk must have a size of 13 bytes";
+ case 95: return "integer overflow with combined idat chunk size";
+ case 96: return "invalid gAMA chunk size";
+ case 97: return "invalid cHRM chunk size";
+ case 98: return "invalid sRGB chunk size";
+ case 99: return "invalid sRGB rendering intent";
+ case 100: return "invalid ICC profile color type, the PNG specification only allows RGB or GRAY";
+ case 101: return "PNG specification does not allow RGB ICC profile on gray color types and vice versa";
+ case 102: return "not allowed to set grayscale ICC profile with colored pixels by PNG specification";
+ case 103: return "invalid palette index in bKGD chunk. Maybe it came before PLTE chunk?";
+ case 104: return "invalid bKGD color while encoding (e.g. palette index out of range)";
+ }
+ return "unknown error code";
+}
+#endif /*LODEPNG_COMPILE_ERROR_TEXT*/
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* ////////////////////////////////////////////////////////////////////////// */
+/* // C++ Wrapper // */
+/* ////////////////////////////////////////////////////////////////////////// */
+/* ////////////////////////////////////////////////////////////////////////// */
+
+#ifdef LODEPNG_COMPILE_CPP
+namespace lodepng {
+
+#ifdef LODEPNG_COMPILE_DISK
+unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename) {
+ long size = lodepng_filesize(filename.c_str());
+ if(size < 0) return 78;
+ buffer.resize((size_t)size);
+ return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str());
+}
+
+/*write given buffer to the file, overwriting the file, it doesn't append to it.*/
+unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename) {
+ return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str());
+}
+#endif /* LODEPNG_COMPILE_DISK */
+
+#ifdef LODEPNG_COMPILE_ZLIB
+#ifdef LODEPNG_COMPILE_DECODER
+unsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
+ const LodePNGDecompressSettings& settings) {
+ unsigned char* buffer = 0;
+ size_t buffersize = 0;
+ unsigned error = zlib_decompress(&buffer, &buffersize, in, insize, &settings);
+ if(buffer) {
+ out.insert(out.end(), &buffer[0], &buffer[buffersize]);
+ lodepng_free(buffer);
+ }
+ return error;
+}
+
+unsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
+ const LodePNGDecompressSettings& settings) {
+ return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings);
+}
+#endif /* LODEPNG_COMPILE_DECODER */
+
+#ifdef LODEPNG_COMPILE_ENCODER
+unsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
+ const LodePNGCompressSettings& settings) {
+ unsigned char* buffer = 0;
+ size_t buffersize = 0;
+ unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings);
+ if(buffer) {
+ out.insert(out.end(), &buffer[0], &buffer[buffersize]);
+ lodepng_free(buffer);
+ }
+ return error;
+}
+
+unsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
+ const LodePNGCompressSettings& settings) {
+ return compress(out, in.empty() ? 0 : &in[0], in.size(), settings);
+}
+#endif /* LODEPNG_COMPILE_ENCODER */
+#endif /* LODEPNG_COMPILE_ZLIB */
+
+
+#ifdef LODEPNG_COMPILE_PNG
+
+State::State() {
+ lodepng_state_init(this);
+}
+
+State::State(const State& other) {
+ lodepng_state_init(this);
+ lodepng_state_copy(this, &other);
+}
+
+State::~State() {
+ lodepng_state_cleanup(this);
+}
+
+State& State::operator=(const State& other) {
+ lodepng_state_copy(this, &other);
+ return *this;
+}
+
+#ifdef LODEPNG_COMPILE_DECODER
+
+unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const unsigned char* in,
+ size_t insize, LodePNGColorType colortype, unsigned bitdepth) {
+ unsigned char* buffer;
+ unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth);
+ if(buffer && !error) {
+ State state;
+ state.info_raw.colortype = colortype;
+ state.info_raw.bitdepth = bitdepth;
+ size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
+ out.insert(out.end(), &buffer[0], &buffer[buffersize]);
+ lodepng_free(buffer);
+ }
+ return error;
+}
+
+unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
+ const std::vector<unsigned char>& in, LodePNGColorType colortype, unsigned bitdepth) {
+ return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth);
+}
+
+unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
+ State& state,
+ const unsigned char* in, size_t insize) {
+ unsigned char* buffer = NULL;
+ unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize);
+ if(buffer && !error) {
+ size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
+ out.insert(out.end(), &buffer[0], &buffer[buffersize]);
+ }
+ lodepng_free(buffer);
+ return error;
+}
+
+unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
+ State& state,
+ const std::vector<unsigned char>& in) {
+ return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size());
+}
+
+#ifdef LODEPNG_COMPILE_DISK
+unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const std::string& filename,
+ LodePNGColorType colortype, unsigned bitdepth) {
+ std::vector<unsigned char> buffer;
+ /* safe output values in case error happens */
+ w = h = 0;
+ unsigned error = load_file(buffer, filename);
+ if(error) return error;
+ return decode(out, w, h, buffer, colortype, bitdepth);
+}
+#endif /* LODEPNG_COMPILE_DECODER */
+#endif /* LODEPNG_COMPILE_DISK */
+
+#ifdef LODEPNG_COMPILE_ENCODER
+unsigned encode(std::vector<unsigned char>& out, const unsigned char* in, unsigned w, unsigned h,
+ LodePNGColorType colortype, unsigned bitdepth) {
+ unsigned char* buffer;
+ size_t buffersize;
+ unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth);
+ if(buffer) {
+ out.insert(out.end(), &buffer[0], &buffer[buffersize]);
+ lodepng_free(buffer);
+ }
+ return error;
+}
+
+unsigned encode(std::vector<unsigned char>& out,
+ const std::vector<unsigned char>& in, unsigned w, unsigned h,
+ LodePNGColorType colortype, unsigned bitdepth) {
+ if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;
+ return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);
+}
+
+unsigned encode(std::vector<unsigned char>& out,
+ const unsigned char* in, unsigned w, unsigned h,
+ State& state) {
+ unsigned char* buffer;
+ size_t buffersize;
+ unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state);
+ if(buffer) {
+ out.insert(out.end(), &buffer[0], &buffer[buffersize]);
+ lodepng_free(buffer);
+ }
+ return error;
+}
+
+unsigned encode(std::vector<unsigned char>& out,
+ const std::vector<unsigned char>& in, unsigned w, unsigned h,
+ State& state) {
+ if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84;
+ return encode(out, in.empty() ? 0 : &in[0], w, h, state);
+}
+
+#ifdef LODEPNG_COMPILE_DISK
+unsigned encode(const std::string& filename,
+ const unsigned char* in, unsigned w, unsigned h,
+ LodePNGColorType colortype, unsigned bitdepth) {
+ std::vector<unsigned char> buffer;
+ unsigned error = encode(buffer, in, w, h, colortype, bitdepth);
+ if(!error) error = save_file(buffer, filename);
+ return error;
+}
+
+unsigned encode(const std::string& filename,
+ const std::vector<unsigned char>& in, unsigned w, unsigned h,
+ LodePNGColorType colortype, unsigned bitdepth) {
+ if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;
+ return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);
+}
+#endif /* LODEPNG_COMPILE_DISK */
+#endif /* LODEPNG_COMPILE_ENCODER */
+#endif /* LODEPNG_COMPILE_PNG */
+} /* namespace lodepng */
+#endif /*LODEPNG_COMPILE_CPP*/
diff --git a/thirdparty/basis_universal/lodepng.h b/thirdparty/basis_universal/lodepng.h
new file mode 100644
index 0000000000..476a2061e2
--- /dev/null
+++ b/thirdparty/basis_universal/lodepng.h
@@ -0,0 +1,1930 @@
+/*
+LodePNG version 20190210
+
+Copyright (c) 2005-2019 Lode Vandevenne
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+*/
+
+#ifndef LODEPNG_H
+#define LODEPNG_H
+
+#include <string.h> /*for size_t*/
+
+extern const char* LODEPNG_VERSION_STRING;
+
+/*
+The following #defines are used to create code sections. They can be disabled
+to disable code sections, which can give faster compile time and smaller binary.
+The "NO_COMPILE" defines are designed to be used to pass as defines to the
+compiler command to disable them without modifying this header, e.g.
+-DLODEPNG_NO_COMPILE_ZLIB for gcc.
+In addition to those below, you can also define LODEPNG_NO_COMPILE_CRC to
+allow implementing a custom lodepng_crc32.
+*/
+/*deflate & zlib. If disabled, you must specify alternative zlib functions in
+the custom_zlib field of the compress and decompress settings*/
+#ifndef LODEPNG_NO_COMPILE_ZLIB
+#define LODEPNG_COMPILE_ZLIB
+#endif
+
+/*png encoder and png decoder*/
+#ifndef LODEPNG_NO_COMPILE_PNG
+#define LODEPNG_COMPILE_PNG
+#endif
+
+/*deflate&zlib decoder and png decoder*/
+#ifndef LODEPNG_NO_COMPILE_DECODER
+#define LODEPNG_COMPILE_DECODER
+#endif
+
+/*deflate&zlib encoder and png encoder*/
+#ifndef LODEPNG_NO_COMPILE_ENCODER
+#define LODEPNG_COMPILE_ENCODER
+#endif
+
+/*the optional built in harddisk file loading and saving functions*/
+#ifndef LODEPNG_NO_COMPILE_DISK
+#define LODEPNG_COMPILE_DISK
+#endif
+
+/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/
+#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
+#define LODEPNG_COMPILE_ANCILLARY_CHUNKS
+#endif
+
+/*ability to convert error numerical codes to English text string*/
+#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT
+#define LODEPNG_COMPILE_ERROR_TEXT
+#endif
+
+/*Compile the default allocators (C's free, malloc and realloc). If you disable this,
+you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your
+source files with custom allocators.*/
+#ifndef LODEPNG_NO_COMPILE_ALLOCATORS
+#define LODEPNG_COMPILE_ALLOCATORS
+#endif
+
+/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/
+#ifdef __cplusplus
+#ifndef LODEPNG_NO_COMPILE_CPP
+#define LODEPNG_COMPILE_CPP
+#endif
+#endif
+
+#ifdef LODEPNG_COMPILE_CPP
+#include <vector>
+#include <string>
+#endif /*LODEPNG_COMPILE_CPP*/
+
+#ifdef LODEPNG_COMPILE_PNG
+/*The PNG color types (also used for raw).*/
+typedef enum LodePNGColorType {
+ LCT_GREY = 0, /*grayscale: 1,2,4,8,16 bit*/
+ LCT_RGB = 2, /*RGB: 8,16 bit*/
+ LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/
+ LCT_GREY_ALPHA = 4, /*grayscale with alpha: 8,16 bit*/
+ LCT_RGBA = 6 /*RGB with alpha: 8,16 bit*/
+} LodePNGColorType;
+
+#ifdef LODEPNG_COMPILE_DECODER
+/*
+Converts PNG data in memory to raw pixel data.
+out: Output parameter. Pointer to buffer that will contain the raw pixel data.
+ After decoding, its size is w * h * (bytes per pixel) bytes larger than
+ initially. Bytes per pixel depends on colortype and bitdepth.
+ Must be freed after usage with free(*out).
+ Note: for 16-bit per channel colors, uses big endian format like PNG does.
+w: Output parameter. Pointer to width of pixel data.
+h: Output parameter. Pointer to height of pixel data.
+in: Memory buffer with the PNG file.
+insize: size of the in buffer.
+colortype: the desired color type for the raw output image. See explanation on PNG color types.
+bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types.
+Return value: LodePNG error code (0 means no error).
+*/
+unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h,
+ const unsigned char* in, size_t insize,
+ LodePNGColorType colortype, unsigned bitdepth);
+
+/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/
+unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h,
+ const unsigned char* in, size_t insize);
+
+/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/
+unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h,
+ const unsigned char* in, size_t insize);
+
+#ifdef LODEPNG_COMPILE_DISK
+/*
+Load PNG from disk, from file with given name.
+Same as the other decode functions, but instead takes a filename as input.
+*/
+unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,
+ const char* filename,
+ LodePNGColorType colortype, unsigned bitdepth);
+
+/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/
+unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,
+ const char* filename);
+
+/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/
+unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,
+ const char* filename);
+#endif /*LODEPNG_COMPILE_DISK*/
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+
+#ifdef LODEPNG_COMPILE_ENCODER
+/*
+Converts raw pixel data into a PNG image in memory. The colortype and bitdepth
+ of the output PNG image cannot be chosen, they are automatically determined
+ by the colortype, bitdepth and content of the input pixel data.
+ Note: for 16-bit per channel colors, needs big endian format like PNG does.
+out: Output parameter. Pointer to buffer that will contain the PNG image data.
+ Must be freed after usage with free(*out).
+outsize: Output parameter. Pointer to the size in bytes of the out buffer.
+image: The raw pixel data to encode. The size of this buffer should be
+ w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth.
+w: width of the raw pixel data in pixels.
+h: height of the raw pixel data in pixels.
+colortype: the color type of the raw input image. See explanation on PNG color types.
+bitdepth: the bit depth of the raw input image. See explanation on PNG color types.
+Return value: LodePNG error code (0 means no error).
+*/
+unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize,
+ const unsigned char* image, unsigned w, unsigned h,
+ LodePNGColorType colortype, unsigned bitdepth);
+
+/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/
+unsigned lodepng_encode32(unsigned char** out, size_t* outsize,
+ const unsigned char* image, unsigned w, unsigned h);
+
+/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/
+unsigned lodepng_encode24(unsigned char** out, size_t* outsize,
+ const unsigned char* image, unsigned w, unsigned h);
+
+#ifdef LODEPNG_COMPILE_DISK
+/*
+Converts raw pixel data into a PNG file on disk.
+Same as the other encode functions, but instead takes a filename as output.
+NOTE: This overwrites existing files without warning!
+*/
+unsigned lodepng_encode_file(const char* filename,
+ const unsigned char* image, unsigned w, unsigned h,
+ LodePNGColorType colortype, unsigned bitdepth);
+
+/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/
+unsigned lodepng_encode32_file(const char* filename,
+ const unsigned char* image, unsigned w, unsigned h);
+
+/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/
+unsigned lodepng_encode24_file(const char* filename,
+ const unsigned char* image, unsigned w, unsigned h);
+#endif /*LODEPNG_COMPILE_DISK*/
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+
+#ifdef LODEPNG_COMPILE_CPP
+namespace lodepng {
+#ifdef LODEPNG_COMPILE_DECODER
+/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype
+is the format to output the pixels to. Default is RGBA 8-bit per channel.*/
+unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
+ const unsigned char* in, size_t insize,
+ LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
+unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
+ const std::vector<unsigned char>& in,
+ LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
+#ifdef LODEPNG_COMPILE_DISK
+/*
+Converts PNG file from disk to raw pixel data in memory.
+Same as the other decode functions, but instead takes a filename as input.
+*/
+unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
+ const std::string& filename,
+ LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
+#endif /* LODEPNG_COMPILE_DISK */
+#endif /* LODEPNG_COMPILE_DECODER */
+
+#ifdef LODEPNG_COMPILE_ENCODER
+/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype
+is that of the raw input data. The output PNG color type will be auto chosen.*/
+unsigned encode(std::vector<unsigned char>& out,
+ const unsigned char* in, unsigned w, unsigned h,
+ LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
+unsigned encode(std::vector<unsigned char>& out,
+ const std::vector<unsigned char>& in, unsigned w, unsigned h,
+ LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
+#ifdef LODEPNG_COMPILE_DISK
+/*
+Converts 32-bit RGBA raw pixel data into a PNG file on disk.
+Same as the other encode functions, but instead takes a filename as output.
+NOTE: This overwrites existing files without warning!
+*/
+unsigned encode(const std::string& filename,
+ const unsigned char* in, unsigned w, unsigned h,
+ LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
+unsigned encode(const std::string& filename,
+ const std::vector<unsigned char>& in, unsigned w, unsigned h,
+ LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
+#endif /* LODEPNG_COMPILE_DISK */
+#endif /* LODEPNG_COMPILE_ENCODER */
+} /* namespace lodepng */
+#endif /*LODEPNG_COMPILE_CPP*/
+#endif /*LODEPNG_COMPILE_PNG*/
+
+#ifdef LODEPNG_COMPILE_ERROR_TEXT
+/*Returns an English description of the numerical error code.*/
+const char* lodepng_error_text(unsigned code);
+#endif /*LODEPNG_COMPILE_ERROR_TEXT*/
+
+#ifdef LODEPNG_COMPILE_DECODER
+/*Settings for zlib decompression*/
+typedef struct LodePNGDecompressSettings LodePNGDecompressSettings;
+struct LodePNGDecompressSettings {
+ /* Check LodePNGDecoderSettings for more ignorable errors such as ignore_crc */
+ unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/
+
+ /*use custom zlib decoder instead of built in one (default: null)*/
+ unsigned (*custom_zlib)(unsigned char**, size_t*,
+ const unsigned char*, size_t,
+ const LodePNGDecompressSettings*);
+ /*use custom deflate decoder instead of built in one (default: null)
+ if custom_zlib is used, custom_deflate is ignored since only the built in
+ zlib function will call custom_deflate*/
+ unsigned (*custom_inflate)(unsigned char**, size_t*,
+ const unsigned char*, size_t,
+ const LodePNGDecompressSettings*);
+
+ const void* custom_context; /*optional custom settings for custom functions*/
+};
+
+extern const LodePNGDecompressSettings lodepng_default_decompress_settings;
+void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings);
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+#ifdef LODEPNG_COMPILE_ENCODER
+/*
+Settings for zlib compression. Tweaking these settings tweaks the balance
+between speed and compression ratio.
+*/
+typedef struct LodePNGCompressSettings LodePNGCompressSettings;
+struct LodePNGCompressSettings /*deflate = compress*/ {
+ /*LZ77 related settings*/
+ unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/
+ unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/
+ unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/
+ unsigned minmatch; /*mininum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/
+ unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/
+ unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/
+
+ /*use custom zlib encoder instead of built in one (default: null)*/
+ unsigned (*custom_zlib)(unsigned char**, size_t*,
+ const unsigned char*, size_t,
+ const LodePNGCompressSettings*);
+ /*use custom deflate encoder instead of built in one (default: null)
+ if custom_zlib is used, custom_deflate is ignored since only the built in
+ zlib function will call custom_deflate*/
+ unsigned (*custom_deflate)(unsigned char**, size_t*,
+ const unsigned char*, size_t,
+ const LodePNGCompressSettings*);
+
+ const void* custom_context; /*optional custom settings for custom functions*/
+};
+
+extern const LodePNGCompressSettings lodepng_default_compress_settings;
+void lodepng_compress_settings_init(LodePNGCompressSettings* settings);
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+#ifdef LODEPNG_COMPILE_PNG
+/*
+Color mode of an image. Contains all information required to decode the pixel
+bits to RGBA colors. This information is the same as used in the PNG file
+format, and is used both for PNG and raw image data in LodePNG.
+*/
+typedef struct LodePNGColorMode {
+ /*header (IHDR)*/
+ LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/
+ unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/
+
+ /*
+ palette (PLTE and tRNS)
+
+ Dynamically allocated with the colors of the palette, including alpha.
+ When encoding a PNG, to store your colors in the palette of the LodePNGColorMode, first use
+ lodepng_palette_clear, then for each color use lodepng_palette_add.
+ If you encode an image without alpha with palette, don't forget to put value 255 in each A byte of the palette.
+
+ When decoding, by default you can ignore this palette, since LodePNG already
+ fills the palette colors in the pixels of the raw RGBA output.
+
+ The palette is only supported for color type 3.
+ */
+ unsigned char* palette; /*palette in RGBARGBA... order. When allocated, must be either 0, or have size 1024*/
+ size_t palettesize; /*palette size in number of colors (amount of bytes is 4 * palettesize)*/
+
+ /*
+ transparent color key (tRNS)
+
+ This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit.
+ For grayscale PNGs, r, g and b will all 3 be set to the same.
+
+ When decoding, by default you can ignore this information, since LodePNG sets
+ pixels with this key to transparent already in the raw RGBA output.
+
+ The color key is only supported for color types 0 and 2.
+ */
+ unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/
+ unsigned key_r; /*red/grayscale component of color key*/
+ unsigned key_g; /*green component of color key*/
+ unsigned key_b; /*blue component of color key*/
+} LodePNGColorMode;
+
+/*init, cleanup and copy functions to use with this struct*/
+void lodepng_color_mode_init(LodePNGColorMode* info);
+void lodepng_color_mode_cleanup(LodePNGColorMode* info);
+/*return value is error code (0 means no error)*/
+unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source);
+/* Makes a temporary LodePNGColorMode that does not need cleanup (no palette) */
+LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth);
+
+void lodepng_palette_clear(LodePNGColorMode* info);
+/*add 1 color to the palette*/
+unsigned lodepng_palette_add(LodePNGColorMode* info,
+ unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+
+/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/
+unsigned lodepng_get_bpp(const LodePNGColorMode* info);
+/*get the amount of color channels used, based on colortype in the struct.
+If a palette is used, it counts as 1 channel.*/
+unsigned lodepng_get_channels(const LodePNGColorMode* info);
+/*is it a grayscale type? (only colortype 0 or 4)*/
+unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info);
+/*has it got an alpha channel? (only colortype 2 or 6)*/
+unsigned lodepng_is_alpha_type(const LodePNGColorMode* info);
+/*has it got a palette? (only colortype 3)*/
+unsigned lodepng_is_palette_type(const LodePNGColorMode* info);
+/*only returns true if there is a palette and there is a value in the palette with alpha < 255.
+Loops through the palette to check this.*/
+unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info);
+/*
+Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image.
+Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels).
+Returns false if the image can only have opaque pixels.
+In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values,
+or if "key_defined" is true.
+*/
+unsigned lodepng_can_have_alpha(const LodePNGColorMode* info);
+/*Returns the byte size of a raw image buffer with given width, height and color mode*/
+size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color);
+
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+/*The information of a Time chunk in PNG.*/
+typedef struct LodePNGTime {
+ unsigned year; /*2 bytes used (0-65535)*/
+ unsigned month; /*1-12*/
+ unsigned day; /*1-31*/
+ unsigned hour; /*0-23*/
+ unsigned minute; /*0-59*/
+ unsigned second; /*0-60 (to allow for leap seconds)*/
+} LodePNGTime;
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+
+/*Information about the PNG image, except pixels, width and height.*/
+typedef struct LodePNGInfo {
+ /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/
+ unsigned compression_method;/*compression method of the original file. Always 0.*/
+ unsigned filter_method; /*filter method of the original file*/
+ unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/
+ LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/
+
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ /*
+ Suggested background color chunk (bKGD)
+
+ This uses the same color mode and bit depth as the PNG (except no alpha channel),
+ with values truncated to the bit depth in the unsigned integer.
+
+ For grayscale and palette PNGs, the value is stored in background_r. The values
+ in background_g and background_b are then unused.
+
+ So when decoding, you may get these in a different color mode than the one you requested
+ for the raw pixels.
+
+ When encoding with auto_convert, you must use the color model defined in info_png.color for
+ these values. The encoder normally ignores info_png.color when auto_convert is on, but will
+ use it to interpret these values (and convert copies of them to its chosen color model).
+
+ When encoding, avoid setting this to an expensive color, such as a non-gray value
+ when the image is gray, or the compression will be worse since it will be forced to
+ write the PNG with a more expensive color mode (when auto_convert is on).
+
+ The decoder does not use this background color to edit the color of pixels. This is a
+ completely optional metadata feature.
+ */
+ unsigned background_defined; /*is a suggested background color given?*/
+ unsigned background_r; /*red/gray/palette component of suggested background color*/
+ unsigned background_g; /*green component of suggested background color*/
+ unsigned background_b; /*blue component of suggested background color*/
+
+ /*
+ non-international text chunks (tEXt and zTXt)
+
+ The char** arrays each contain num strings. The actual messages are in
+ text_strings, while text_keys are keywords that give a short description what
+ the actual text represents, e.g. Title, Author, Description, or anything else.
+
+ All the string fields below including keys, names and language tags are null terminated.
+ The PNG specification uses null characters for the keys, names and tags, and forbids null
+ characters to appear in the main text which is why we can use null termination everywhere here.
+
+ A keyword is minimum 1 character and maximum 79 characters long. It's
+ discouraged to use a single line length longer than 79 characters for texts.
+
+ Don't allocate these text buffers yourself. Use the init/cleanup functions
+ correctly and use lodepng_add_text and lodepng_clear_text.
+ */
+ size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/
+ char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/
+ char** text_strings; /*the actual text*/
+
+ /*
+ international text chunks (iTXt)
+ Similar to the non-international text chunks, but with additional strings
+ "langtags" and "transkeys".
+ */
+ size_t itext_num; /*the amount of international texts in this PNG*/
+ char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/
+ char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/
+ char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/
+ char** itext_strings; /*the actual international text - UTF-8 string*/
+
+ /*time chunk (tIME)*/
+ unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/
+ LodePNGTime time;
+
+ /*phys chunk (pHYs)*/
+ unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/
+ unsigned phys_x; /*pixels per unit in x direction*/
+ unsigned phys_y; /*pixels per unit in y direction*/
+ unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/
+
+ /*
+ Color profile related chunks: gAMA, cHRM, sRGB, iCPP
+
+ LodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these color
+ profile values. It merely passes on the information. If you wish to use color profiles and convert colors, please
+ use these values with a color management library.
+
+ See the PNG, ICC and sRGB specifications for more information about the meaning of these values.
+ */
+
+ /* gAMA chunk: optional, overridden by sRGB or iCCP if those are present. */
+ unsigned gama_defined; /* Whether a gAMA chunk is present (0 = not present, 1 = present). */
+ unsigned gama_gamma; /* Gamma exponent times 100000 */
+
+ /* cHRM chunk: optional, overridden by sRGB or iCCP if those are present. */
+ unsigned chrm_defined; /* Whether a cHRM chunk is present (0 = not present, 1 = present). */
+ unsigned chrm_white_x; /* White Point x times 100000 */
+ unsigned chrm_white_y; /* White Point y times 100000 */
+ unsigned chrm_red_x; /* Red x times 100000 */
+ unsigned chrm_red_y; /* Red y times 100000 */
+ unsigned chrm_green_x; /* Green x times 100000 */
+ unsigned chrm_green_y; /* Green y times 100000 */
+ unsigned chrm_blue_x; /* Blue x times 100000 */
+ unsigned chrm_blue_y; /* Blue y times 100000 */
+
+ /*
+ sRGB chunk: optional. May not appear at the same time as iCCP.
+ If gAMA is also present gAMA must contain value 45455.
+ If cHRM is also present cHRM must contain respectively 31270,32900,64000,33000,30000,60000,15000,6000.
+ */
+ unsigned srgb_defined; /* Whether an sRGB chunk is present (0 = not present, 1 = present). */
+ unsigned srgb_intent; /* Rendering intent: 0=perceptual, 1=rel. colorimetric, 2=saturation, 3=abs. colorimetric */
+
+ /*
+ iCCP chunk: optional. May not appear at the same time as sRGB.
+
+ LodePNG does not parse or use the ICC profile (except its color space header field for an edge case), a
+ separate library to handle the ICC data (not included in LodePNG) format is needed to use it for color
+ management and conversions.
+
+ For encoding, if iCCP is present, gAMA and cHRM are recommended to be added as well with values that match the ICC
+ profile as closely as possible, if you wish to do this you should provide the correct values for gAMA and cHRM and
+ enable their '_defined' flags since LodePNG will not automatically compute them from the ICC profile.
+
+ For encoding, the ICC profile is required by the PNG specification to be an "RGB" profile for non-gray
+ PNG color types and a "GRAY" profile for gray PNG color types. If you disable auto_convert, you must ensure
+ the ICC profile type matches your requested color type, else the encoder gives an error. If auto_convert is
+ enabled (the default), and the ICC profile is not a good match for the pixel data, this will result in an encoder
+ error if the pixel data has non-gray pixels for a GRAY profile, or a silent less-optimal compression of the pixel
+ data if the pixels could be encoded as grayscale but the ICC profile is RGB.
+
+ To avoid this do not set an ICC profile in the image unless there is a good reason for it, and when doing so
+ make sure you compute it carefully to avoid the above problems.
+ */
+ unsigned iccp_defined; /* Whether an iCCP chunk is present (0 = not present, 1 = present). */
+ char* iccp_name; /* Null terminated string with profile name, 1-79 bytes */
+ /*
+ The ICC profile in iccp_profile_size bytes.
+ Don't allocate this buffer yourself. Use the init/cleanup functions
+ correctly and use lodepng_set_icc and lodepng_clear_icc.
+ */
+ unsigned char* iccp_profile;
+ unsigned iccp_profile_size; /* The size of iccp_profile in bytes */
+
+ /* End of color profile related chunks */
+
+
+ /*
+ unknown chunks: chunks not known by LodePNG, passed on byte for byte.
+
+ There are 3 buffers, one for each position in the PNG where unknown chunks can appear.
+ Each buffer contains all unknown chunks for that position consecutively.
+ The 3 positions are:
+ 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND.
+
+ For encoding, do not store critical chunks or known chunks that are enabled with a "_defined" flag
+ above in here, since the encoder will blindly follow this and could then encode an invalid PNG file
+ (such as one with two IHDR chunks or the disallowed combination of sRGB with iCCP). But do use
+ this if you wish to store an ancillary chunk that is not supported by LodePNG (such as sPLT or hIST),
+ or any non-standard PNG chunk.
+
+ Do not allocate or traverse this data yourself. Use the chunk traversing functions declared
+ later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct.
+ */
+ unsigned char* unknown_chunks_data[3];
+ size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+} LodePNGInfo;
+
+/*init, cleanup and copy functions to use with this struct*/
+void lodepng_info_init(LodePNGInfo* info);
+void lodepng_info_cleanup(LodePNGInfo* info);
+/*return value is error code (0 means no error)*/
+unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source);
+
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/
+void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/
+
+unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,
+ const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/
+void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/
+
+/*replaces if exists*/
+unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size);
+void lodepng_clear_icc(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+
+/*
+Converts raw buffer from one color type to another color type, based on
+LodePNGColorMode structs to describe the input and output color type.
+See the reference manual at the end of this header file to see which color conversions are supported.
+return value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported)
+The out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel
+of the output color type (lodepng_get_bpp).
+For < 8 bpp images, there should not be padding bits at the end of scanlines.
+For 16-bit per channel colors, uses big endian format like PNG does.
+Return value is LodePNG error code
+*/
+unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
+ const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
+ unsigned w, unsigned h);
+
+#ifdef LODEPNG_COMPILE_DECODER
+/*
+Settings for the decoder. This contains settings for the PNG and the Zlib
+decoder, but not the Info settings from the Info structs.
+*/
+typedef struct LodePNGDecoderSettings {
+ LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/
+
+ /* Check LodePNGDecompressSettings for more ignorable errors such as ignore_adler32 */
+ unsigned ignore_crc; /*ignore CRC checksums*/
+ unsigned ignore_critical; /*ignore unknown critical chunks*/
+ unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/
+ /* TODO: make a system involving warnings with levels and a strict mode instead. Other potentially recoverable
+ errors: srgb rendering intent value, size of content of ancillary chunks, more than 79 characters for some
+ strings, placement/combination rules for ancillary chunks, crc of unknown chunks, allowed characters
+ in string keys, etc... */
+
+ unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/
+
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/
+ /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/
+ unsigned remember_unknown_chunks;
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+} LodePNGDecoderSettings;
+
+void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings);
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+#ifdef LODEPNG_COMPILE_ENCODER
+/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/
+typedef enum LodePNGFilterStrategy {
+ /*every filter at zero*/
+ LFS_ZERO,
+ /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/
+ LFS_MINSUM,
+ /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending
+ on the image, this is better or worse than minsum.*/
+ LFS_ENTROPY,
+ /*
+ Brute-force-search PNG filters by compressing each filter for each scanline.
+ Experimental, very slow, and only rarely gives better compression than MINSUM.
+ */
+ LFS_BRUTE_FORCE,
+ /*use predefined_filters buffer: you specify the filter type for each scanline*/
+ LFS_PREDEFINED
+} LodePNGFilterStrategy;
+
+/*Gives characteristics about the integer RGBA colors of the image (count, alpha channel usage, bit depth, ...),
+which helps decide which color model to use for encoding.
+Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms.
+NOTE: This is not related to the ICC color profile, search "iccp_profile" instead to find the ICC/chromacity/...
+fields in this header file.*/
+typedef struct LodePNGColorProfile {
+ unsigned colored; /*not grayscale*/
+ unsigned key; /*image is not opaque and color key is possible instead of full alpha*/
+ unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/
+ unsigned short key_g;
+ unsigned short key_b;
+ unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/
+ unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16.*/
+ unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order*/
+ unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for grayscale only. 16 if 16-bit per channel required.*/
+ size_t numpixels;
+} LodePNGColorProfile;
+
+void lodepng_color_profile_init(LodePNGColorProfile* profile);
+
+/*Get a LodePNGColorProfile of the image. The profile must already have been inited.
+NOTE: This is not related to the ICC color profile, search "iccp_profile" instead to find the ICC/chromacity/...
+fields in this header file.*/
+unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
+ const unsigned char* image, unsigned w, unsigned h,
+ const LodePNGColorMode* mode_in);
+/*The function LodePNG uses internally to decide the PNG color with auto_convert.
+Chooses an optimal color model, e.g. gray if only gray pixels, palette if < 256 colors, ...*/
+unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
+ const unsigned char* image, unsigned w, unsigned h,
+ const LodePNGColorMode* mode_in);
+
+/*Settings for the encoder.*/
+typedef struct LodePNGEncoderSettings {
+ LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/
+
+ unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/
+
+ /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than
+ 8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to
+ completely follow the official PNG heuristic, filter_palette_zero must be true and
+ filter_strategy must be LFS_MINSUM*/
+ unsigned filter_palette_zero;
+ /*Which filter strategy to use when not using zeroes due to filter_palette_zero.
+ Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/
+ LodePNGFilterStrategy filter_strategy;
+ /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with
+ the same length as the amount of scanlines in the image, and each value must <= 5. You
+ have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero
+ must be set to 0 to ensure this is also used on palette or low bitdepth images.*/
+ const unsigned char* predefined_filters;
+
+ /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette).
+ If colortype is 3, PLTE is _always_ created.*/
+ unsigned force_palette;
+#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
+ /*add LodePNG identifier and version as a text chunk, for debugging*/
+ unsigned add_id;
+ /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/
+ unsigned text_compression;
+#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
+} LodePNGEncoderSettings;
+
+void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings);
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+
+#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)
+/*The settings, state and information for extended encoding and decoding.*/
+typedef struct LodePNGState {
+#ifdef LODEPNG_COMPILE_DECODER
+ LodePNGDecoderSettings decoder; /*the decoding settings*/
+#endif /*LODEPNG_COMPILE_DECODER*/
+#ifdef LODEPNG_COMPILE_ENCODER
+ LodePNGEncoderSettings encoder; /*the encoding settings*/
+#endif /*LODEPNG_COMPILE_ENCODER*/
+ LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/
+ LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/
+ unsigned error;
+#ifdef LODEPNG_COMPILE_CPP
+ /* For the lodepng::State subclass. */
+ virtual ~LodePNGState(){}
+#endif
+} LodePNGState;
+
+/*init, cleanup and copy functions to use with this struct*/
+void lodepng_state_init(LodePNGState* state);
+void lodepng_state_cleanup(LodePNGState* state);
+void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source);
+#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */
+
+#ifdef LODEPNG_COMPILE_DECODER
+/*
+Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and
+getting much more information about the PNG image and color mode.
+*/
+unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,
+ LodePNGState* state,
+ const unsigned char* in, size_t insize);
+
+/*
+Read the PNG header, but not the actual data. This returns only the information
+that is in the IHDR chunk of the PNG, such as width, height and color type. The
+information is placed in the info_png field of the LodePNGState.
+*/
+unsigned lodepng_inspect(unsigned* w, unsigned* h,
+ LodePNGState* state,
+ const unsigned char* in, size_t insize);
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+/*
+Reads one metadata chunk (other than IHDR) of the PNG file and outputs what it
+read in the state. Returns error code on failure.
+Use lodepng_inspect first with a new state, then e.g. lodepng_chunk_find_const
+to find the desired chunk type, and if non null use lodepng_inspect_chunk (with
+chunk_pointer - start_of_file as pos).
+Supports most metadata chunks from the PNG standard (gAMA, bKGD, tEXt, ...).
+Ignores unsupported, unknown, non-metadata or IHDR chunks (without error).
+Requirements: &in[pos] must point to start of a chunk, must use regular
+lodepng_inspect first since format of most other chunks depends on IHDR, and if
+there is a PLTE chunk, that one must be inspected before tRNS or bKGD.
+*/
+unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
+ const unsigned char* in, size_t insize);
+
+#ifdef LODEPNG_COMPILE_ENCODER
+/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/
+unsigned lodepng_encode(unsigned char** out, size_t* outsize,
+ const unsigned char* image, unsigned w, unsigned h,
+ LodePNGState* state);
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+/*
+The lodepng_chunk functions are normally not needed, except to traverse the
+unknown chunks stored in the LodePNGInfo struct, or add new ones to it.
+It also allows traversing the chunks of an encoded PNG file yourself.
+
+The chunk pointer always points to the beginning of the chunk itself, that is
+the first byte of the 4 length bytes.
+
+In the PNG file format, chunks have the following format:
+-4 bytes length: length of the data of the chunk in bytes (chunk itself is 12 bytes longer)
+-4 bytes chunk type (ASCII a-z,A-Z only, see below)
+-length bytes of data (may be 0 bytes if length was 0)
+-4 bytes of CRC, computed on chunk name + data
+
+The first chunk starts at the 8th byte of the PNG file, the entire rest of the file
+exists out of concatenated chunks with the above format.
+
+PNG standard chunk ASCII naming conventions:
+-First byte: uppercase = critical, lowercase = ancillary
+-Second byte: uppercase = public, lowercase = private
+-Third byte: must be uppercase
+-Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy
+*/
+
+/*
+Gets the length of the data of the chunk. Total chunk length has 12 bytes more.
+There must be at least 4 bytes to read from. If the result value is too large,
+it may be corrupt data.
+*/
+unsigned lodepng_chunk_length(const unsigned char* chunk);
+
+/*puts the 4-byte type in null terminated string*/
+void lodepng_chunk_type(char type[5], const unsigned char* chunk);
+
+/*check if the type is the given type*/
+unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type);
+
+/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/
+unsigned char lodepng_chunk_ancillary(const unsigned char* chunk);
+
+/*0: public, 1: private (see PNG standard)*/
+unsigned char lodepng_chunk_private(const unsigned char* chunk);
+
+/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/
+unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk);
+
+/*get pointer to the data of the chunk, where the input points to the header of the chunk*/
+unsigned char* lodepng_chunk_data(unsigned char* chunk);
+const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk);
+
+/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/
+unsigned lodepng_chunk_check_crc(const unsigned char* chunk);
+
+/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/
+void lodepng_chunk_generate_crc(unsigned char* chunk);
+
+/*
+Iterate to next chunks, allows iterating through all chunks of the PNG file.
+Input must be at the beginning of a chunk (result of a previous lodepng_chunk_next call,
+or the 8th byte of a PNG file which always has the first chunk), or alternatively may
+point to the first byte of the PNG file (which is not a chunk but the magic header, the
+function will then skip over it and return the first real chunk).
+Expects at least 8 readable bytes of memory in the input pointer.
+Will output pointer to the start of the next chunk or the end of the file if there
+is no more chunk after this. Start this process at the 8th byte of the PNG file.
+In a non-corrupt PNG file, the last chunk should have name "IEND".
+*/
+unsigned char* lodepng_chunk_next(unsigned char* chunk);
+const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk);
+
+/*Finds the first chunk with the given type in the range [chunk, end), or returns NULL if not found.*/
+unsigned char* lodepng_chunk_find(unsigned char* chunk, const unsigned char* end, const char type[5]);
+const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]);
+
+/*
+Appends chunk to the data in out. The given chunk should already have its chunk header.
+The out variable and outlength are updated to reflect the new reallocated buffer.
+Returns error code (0 if it went ok)
+*/
+unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk);
+
+/*
+Appends new chunk to out. The chunk to append is given by giving its length, type
+and data separately. The type is a 4-letter string.
+The out variable and outlength are updated to reflect the new reallocated buffer.
+Returne error code (0 if it went ok)
+*/
+unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,
+ const char* type, const unsigned char* data);
+
+
+/*Calculate CRC32 of buffer*/
+unsigned lodepng_crc32(const unsigned char* buf, size_t len);
+#endif /*LODEPNG_COMPILE_PNG*/
+
+
+#ifdef LODEPNG_COMPILE_ZLIB
+/*
+This zlib part can be used independently to zlib compress and decompress a
+buffer. It cannot be used to create gzip files however, and it only supports the
+part of zlib that is required for PNG, it does not support dictionaries.
+*/
+
+#ifdef LODEPNG_COMPILE_DECODER
+/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/
+unsigned lodepng_inflate(unsigned char** out, size_t* outsize,
+ const unsigned char* in, size_t insize,
+ const LodePNGDecompressSettings* settings);
+
+/*
+Decompresses Zlib data. Reallocates the out buffer and appends the data. The
+data must be according to the zlib specification.
+Either, *out must be NULL and *outsize must be 0, or, *out must be a valid
+buffer and *outsize its size in bytes. out must be freed by user after usage.
+*/
+unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize,
+ const unsigned char* in, size_t insize,
+ const LodePNGDecompressSettings* settings);
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+#ifdef LODEPNG_COMPILE_ENCODER
+/*
+Compresses data with Zlib. Reallocates the out buffer and appends the data.
+Zlib adds a small header and trailer around the deflate data.
+The data is output in the format of the zlib specification.
+Either, *out must be NULL and *outsize must be 0, or, *out must be a valid
+buffer and *outsize its size in bytes. out must be freed by user after usage.
+*/
+unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize,
+ const unsigned char* in, size_t insize,
+ const LodePNGCompressSettings* settings);
+
+/*
+Find length-limited Huffman code for given frequencies. This function is in the
+public interface only for tests, it's used internally by lodepng_deflate.
+*/
+unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,
+ size_t numcodes, unsigned maxbitlen);
+
+/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/
+unsigned lodepng_deflate(unsigned char** out, size_t* outsize,
+ const unsigned char* in, size_t insize,
+ const LodePNGCompressSettings* settings);
+
+#endif /*LODEPNG_COMPILE_ENCODER*/
+#endif /*LODEPNG_COMPILE_ZLIB*/
+
+#ifdef LODEPNG_COMPILE_DISK
+/*
+Load a file from disk into buffer. The function allocates the out buffer, and
+after usage you should free it.
+out: output parameter, contains pointer to loaded buffer.
+outsize: output parameter, size of the allocated out buffer
+filename: the path to the file to load
+return value: error code (0 means ok)
+*/
+unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);
+
+/*
+Save a file from buffer to disk. Warning, if it exists, this function overwrites
+the file without warning!
+buffer: the buffer to write
+buffersize: size of the buffer to write
+filename: the path to the file to save to
+return value: error code (0 means ok)
+*/
+unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);
+#endif /*LODEPNG_COMPILE_DISK*/
+
+#ifdef LODEPNG_COMPILE_CPP
+/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */
+namespace lodepng {
+#ifdef LODEPNG_COMPILE_PNG
+class State : public LodePNGState {
+ public:
+ State();
+ State(const State& other);
+ virtual ~State();
+ State& operator=(const State& other);
+};
+
+#ifdef LODEPNG_COMPILE_DECODER
+/* Same as other lodepng::decode, but using a State for more settings and information. */
+unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
+ State& state,
+ const unsigned char* in, size_t insize);
+unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
+ State& state,
+ const std::vector<unsigned char>& in);
+#endif /*LODEPNG_COMPILE_DECODER*/
+
+#ifdef LODEPNG_COMPILE_ENCODER
+/* Same as other lodepng::encode, but using a State for more settings and information. */
+unsigned encode(std::vector<unsigned char>& out,
+ const unsigned char* in, unsigned w, unsigned h,
+ State& state);
+unsigned encode(std::vector<unsigned char>& out,
+ const std::vector<unsigned char>& in, unsigned w, unsigned h,
+ State& state);
+#endif /*LODEPNG_COMPILE_ENCODER*/
+
+#ifdef LODEPNG_COMPILE_DISK
+/*
+Load a file from disk into an std::vector.
+return value: error code (0 means ok)
+*/
+unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);
+
+/*
+Save the binary data in an std::vector to a file on disk. The file is overwritten
+without warning.
+*/
+unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
+#endif /* LODEPNG_COMPILE_DISK */
+#endif /* LODEPNG_COMPILE_PNG */
+
+#ifdef LODEPNG_COMPILE_ZLIB
+#ifdef LODEPNG_COMPILE_DECODER
+/* Zlib-decompress an unsigned char buffer */
+unsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
+ const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);
+
+/* Zlib-decompress an std::vector */
+unsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
+ const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);
+#endif /* LODEPNG_COMPILE_DECODER */
+
+#ifdef LODEPNG_COMPILE_ENCODER
+/* Zlib-compress an unsigned char buffer */
+unsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
+ const LodePNGCompressSettings& settings = lodepng_default_compress_settings);
+
+/* Zlib-compress an std::vector */
+unsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
+ const LodePNGCompressSettings& settings = lodepng_default_compress_settings);
+#endif /* LODEPNG_COMPILE_ENCODER */
+#endif /* LODEPNG_COMPILE_ZLIB */
+} /* namespace lodepng */
+#endif /*LODEPNG_COMPILE_CPP*/
+
+/*
+TODO:
+[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often
+[.] check compatibility with various compilers - done but needs to be redone for every newer version
+[X] converting color to 16-bit per channel types
+[X] support color profile chunk types (but never let them touch RGB values by default)
+[ ] support all public PNG chunk types (almost done except sBIT, sPLT and hIST)
+[ ] make sure encoder generates no chunks with size > (2^31)-1
+[ ] partial decoding (stream processing)
+[X] let the "isFullyOpaque" function check color keys and transparent palettes too
+[X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl"
+[ ] allow treating some errors like warnings, when image is recoverable (e.g. 69, 57, 58)
+[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ...
+[ ] error messages with line numbers (and version)
+[ ] errors in state instead of as return code?
+[ ] new errors/warnings like suspiciously big decompressed ztxt or iccp chunk
+[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes
+[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ...
+[ ] allow user to give data (void*) to custom allocator
+[ ] provide alternatives for C library functions not present on some platforms (memcpy, ...)
+[ ] rename "grey" to "gray" everywhere since "color" also uses US spelling (keep "grey" copies for backwards compatibility)
+*/
+
+#endif /*LODEPNG_H inclusion guard*/
+
+/*
+LodePNG Documentation
+---------------------
+
+0. table of contents
+--------------------
+
+ 1. about
+ 1.1. supported features
+ 1.2. features not supported
+ 2. C and C++ version
+ 3. security
+ 4. decoding
+ 5. encoding
+ 6. color conversions
+ 6.1. PNG color types
+ 6.2. color conversions
+ 6.3. padding bits
+ 6.4. A note about 16-bits per channel and endianness
+ 7. error values
+ 8. chunks and PNG editing
+ 9. compiler support
+ 10. examples
+ 10.1. decoder C++ example
+ 10.2. decoder C example
+ 11. state settings reference
+ 12. changes
+ 13. contact information
+
+
+1. about
+--------
+
+PNG is a file format to store raster images losslessly with good compression,
+supporting different color types and alpha channel.
+
+LodePNG is a PNG codec according to the Portable Network Graphics (PNG)
+Specification (Second Edition) - W3C Recommendation 10 November 2003.
+
+The specifications used are:
+
+*) Portable Network Graphics (PNG) Specification (Second Edition):
+ http://www.w3.org/TR/2003/REC-PNG-20031110
+*) RFC 1950 ZLIB Compressed Data Format version 3.3:
+ http://www.gzip.org/zlib/rfc-zlib.html
+*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3:
+ http://www.gzip.org/zlib/rfc-deflate.html
+
+The most recent version of LodePNG can currently be found at
+http://lodev.org/lodepng/
+
+LodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds
+extra functionality.
+
+LodePNG exists out of two files:
+-lodepng.h: the header file for both C and C++
+-lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage
+
+If you want to start using LodePNG right away without reading this doc, get the
+examples from the LodePNG website to see how to use it in code, or check the
+smaller examples in chapter 13 here.
+
+LodePNG is simple but only supports the basic requirements. To achieve
+simplicity, the following design choices were made: There are no dependencies
+on any external library. There are functions to decode and encode a PNG with
+a single function call, and extended versions of these functions taking a
+LodePNGState struct allowing to specify or get more information. By default
+the colors of the raw image are always RGB or RGBA, no matter what color type
+the PNG file uses. To read and write files, there are simple functions to
+convert the files to/from buffers in memory.
+
+This all makes LodePNG suitable for loading textures in games, demos and small
+programs, ... It's less suitable for full fledged image editors, loading PNGs
+over network (it requires all the image data to be available before decoding can
+begin), life-critical systems, ...
+
+1.1. supported features
+-----------------------
+
+The following features are supported by the decoder:
+
+*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image,
+ or the same color type as the PNG
+*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image
+*) Adam7 interlace and deinterlace for any color type
+*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk
+*) support for alpha channels, including RGBA color model, translucent palettes and color keying
+*) zlib decompression (inflate)
+*) zlib compression (deflate)
+*) CRC32 and ADLER32 checksums
+*) colorimetric color profile conversions: currently experimentally available in lodepng_util.cpp only,
+ plus alternatively ability to pass on chroma/gamma/ICC profile information to other color management system.
+*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks.
+*) the following chunks are supported by both encoder and decoder:
+ IHDR: header information
+ PLTE: color palette
+ IDAT: pixel data
+ IEND: the final chunk
+ tRNS: transparency for palettized images
+ tEXt: textual information
+ zTXt: compressed textual information
+ iTXt: international textual information
+ bKGD: suggested background color
+ pHYs: physical dimensions
+ tIME: modification time
+ cHRM: RGB chromaticities
+ gAMA: RGB gamma correction
+ iCCP: ICC color profile
+ sRGB: rendering intent
+
+1.2. features not supported
+---------------------------
+
+The following features are _not_ supported:
+
+*) some features needed to make a conformant PNG-Editor might be still missing.
+*) partial loading/stream processing. All data must be available and is processed in one call.
+*) The following public chunks are not (yet) supported but treated as unknown chunks by LodePNG:
+ sBIT
+ hIST
+ sPLT
+
+
+2. C and C++ version
+--------------------
+
+The C version uses buffers allocated with alloc that you need to free()
+yourself. You need to use init and cleanup functions for each struct whenever
+using a struct from the C version to avoid exploits and memory leaks.
+
+The C++ version has extra functions with std::vectors in the interface and the
+lodepng::State class which is a LodePNGState with constructor and destructor.
+
+These files work without modification for both C and C++ compilers because all
+the additional C++ code is in "#ifdef __cplusplus" blocks that make C-compilers
+ignore it, and the C code is made to compile both with strict ISO C90 and C++.
+
+To use the C++ version, you need to rename the source file to lodepng.cpp
+(instead of lodepng.c), and compile it with a C++ compiler.
+
+To use the C version, you need to rename the source file to lodepng.c (instead
+of lodepng.cpp), and compile it with a C compiler.
+
+
+3. Security
+-----------
+
+Even if carefully designed, it's always possible that LodePNG contains possible
+exploits. If you discover one, please let me know, and it will be fixed.
+
+When using LodePNG, care has to be taken with the C version of LodePNG, as well
+as the C-style structs when working with C++. The following conventions are used
+for all C-style structs:
+
+-if a struct has a corresponding init function, always call the init function when making a new one
+-if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks
+-if a struct has a corresponding copy function, use the copy function instead of "=".
+ The destination must also be inited already.
+
+
+4. Decoding
+-----------
+
+Decoding converts a PNG compressed image to a raw pixel buffer.
+
+Most documentation on using the decoder is at its declarations in the header
+above. For C, simple decoding can be done with functions such as
+lodepng_decode32, and more advanced decoding can be done with the struct
+LodePNGState and lodepng_decode. For C++, all decoding can be done with the
+various lodepng::decode functions, and lodepng::State can be used for advanced
+features.
+
+When using the LodePNGState, it uses the following fields for decoding:
+*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here
+*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get
+*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use
+
+LodePNGInfo info_png
+--------------------
+
+After decoding, this contains extra information of the PNG image, except the actual
+pixels, width and height because these are already gotten directly from the decoder
+functions.
+
+It contains for example the original color type of the PNG image, text comments,
+suggested background color, etc... More details about the LodePNGInfo struct are
+at its declaration documentation.
+
+LodePNGColorMode info_raw
+-------------------------
+
+When decoding, here you can specify which color type you want
+the resulting raw image to be. If this is different from the colortype of the
+PNG, then the decoder will automatically convert the result. This conversion
+always works, except if you want it to convert a color PNG to grayscale or to
+a palette with missing colors.
+
+By default, 32-bit color is used for the result.
+
+LodePNGDecoderSettings decoder
+------------------------------
+
+The settings can be used to ignore the errors created by invalid CRC and Adler32
+chunks, and to disable the decoding of tEXt chunks.
+
+There's also a setting color_convert, true by default. If false, no conversion
+is done, the resulting data will be as it was in the PNG (after decompression)
+and you'll have to puzzle the colors of the pixels together yourself using the
+color type information in the LodePNGInfo.
+
+
+5. Encoding
+-----------
+
+Encoding converts a raw pixel buffer to a PNG compressed image.
+
+Most documentation on using the encoder is at its declarations in the header
+above. For C, simple encoding can be done with functions such as
+lodepng_encode32, and more advanced decoding can be done with the struct
+LodePNGState and lodepng_encode. For C++, all encoding can be done with the
+various lodepng::encode functions, and lodepng::State can be used for advanced
+features.
+
+Like the decoder, the encoder can also give errors. However it gives less errors
+since the encoder input is trusted, the decoder input (a PNG image that could
+be forged by anyone) is not trusted.
+
+When using the LodePNGState, it uses the following fields for encoding:
+*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be.
+*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has
+*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use
+
+LodePNGInfo info_png
+--------------------
+
+When encoding, you use this the opposite way as when decoding: for encoding,
+you fill in the values you want the PNG to have before encoding. By default it's
+not needed to specify a color type for the PNG since it's automatically chosen,
+but it's possible to choose it yourself given the right settings.
+
+The encoder will not always exactly match the LodePNGInfo struct you give,
+it tries as close as possible. Some things are ignored by the encoder. The
+encoder uses, for example, the following settings from it when applicable:
+colortype and bitdepth, text chunks, time chunk, the color key, the palette, the
+background color, the interlace method, unknown chunks, ...
+
+When encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk.
+If the palette contains any colors for which the alpha channel is not 255 (so
+there are translucent colors in the palette), it'll add a tRNS chunk.
+
+LodePNGColorMode info_raw
+-------------------------
+
+You specify the color type of the raw image that you give to the input here,
+including a possible transparent color key and palette you happen to be using in
+your raw image data.
+
+By default, 32-bit color is assumed, meaning your input has to be in RGBA
+format with 4 bytes (unsigned chars) per pixel.
+
+LodePNGEncoderSettings encoder
+------------------------------
+
+The following settings are supported (some are in sub-structs):
+*) auto_convert: when this option is enabled, the encoder will
+automatically choose the smallest possible color mode (including color key) that
+can encode the colors of all pixels without information loss.
+*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree,
+ 2 = dynamic huffman tree (best compression). Should be 2 for proper
+ compression.
+*) use_lz77: whether or not to use LZ77 for compressed block types. Should be
+ true for proper compression.
+*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value
+ 2048 by default, but can be set to 32768 for better, but slow, compression.
+*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE
+ chunk if force_palette is true. This can used as suggested palette to convert
+ to by viewers that don't support more than 256 colors (if those still exist)
+*) add_id: add text chunk "Encoder: LodePNG <version>" to the image.
+*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks.
+ zTXt chunks use zlib compression on the text. This gives a smaller result on
+ large texts but a larger result on small texts (such as a single program name).
+ It's all tEXt or all zTXt though, there's no separate setting per text yet.
+
+
+6. color conversions
+--------------------
+
+An important thing to note about LodePNG, is that the color type of the PNG, and
+the color type of the raw image, are completely independent. By default, when
+you decode a PNG, you get the result as a raw image in the color type you want,
+no matter whether the PNG was encoded with a palette, grayscale or RGBA color.
+And if you encode an image, by default LodePNG will automatically choose the PNG
+color type that gives good compression based on the values of colors and amount
+of colors in the image. It can be configured to let you control it instead as
+well, though.
+
+To be able to do this, LodePNG does conversions from one color mode to another.
+It can convert from almost any color type to any other color type, except the
+following conversions: RGB to grayscale is not supported, and converting to a
+palette when the palette doesn't have a required color is not supported. This is
+not supported on purpose: this is information loss which requires a color
+reduction algorithm that is beyong the scope of a PNG encoder (yes, RGB to gray
+is easy, but there are multiple ways if you want to give some channels more
+weight).
+
+By default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB
+color, no matter what color type the PNG has. And by default when encoding,
+LodePNG automatically picks the best color model for the output PNG, and expects
+the input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control
+the color format of the images yourself, you can skip this chapter.
+
+6.1. PNG color types
+--------------------
+
+A PNG image can have many color types, ranging from 1-bit color to 64-bit color,
+as well as palettized color modes. After the zlib decompression and unfiltering
+in the PNG image is done, the raw pixel data will have that color type and thus
+a certain amount of bits per pixel. If you want the output raw image after
+decoding to have another color type, a conversion is done by LodePNG.
+
+The PNG specification gives the following color types:
+
+0: grayscale, bit depths 1, 2, 4, 8, 16
+2: RGB, bit depths 8 and 16
+3: palette, bit depths 1, 2, 4 and 8
+4: grayscale with alpha, bit depths 8 and 16
+6: RGBA, bit depths 8 and 16
+
+Bit depth is the amount of bits per pixel per color channel. So the total amount
+of bits per pixel is: amount of channels * bitdepth.
+
+6.2. color conversions
+----------------------
+
+As explained in the sections about the encoder and decoder, you can specify
+color types and bit depths in info_png and info_raw to change the default
+behaviour.
+
+If, when decoding, you want the raw image to be something else than the default,
+you need to set the color type and bit depth you want in the LodePNGColorMode,
+or the parameters colortype and bitdepth of the simple decoding function.
+
+If, when encoding, you use another color type than the default in the raw input
+image, you need to specify its color type and bit depth in the LodePNGColorMode
+of the raw image, or use the parameters colortype and bitdepth of the simple
+encoding function.
+
+If, when encoding, you don't want LodePNG to choose the output PNG color type
+but control it yourself, you need to set auto_convert in the encoder settings
+to false, and specify the color type you want in the LodePNGInfo of the
+encoder (including palette: it can generate a palette if auto_convert is true,
+otherwise not).
+
+If the input and output color type differ (whether user chosen or auto chosen),
+LodePNG will do a color conversion, which follows the rules below, and may
+sometimes result in an error.
+
+To avoid some confusion:
+-the decoder converts from PNG to raw image
+-the encoder converts from raw image to PNG
+-the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image
+-the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG
+-when encoding, the color type in LodePNGInfo is ignored if auto_convert
+ is enabled, it is automatically generated instead
+-when decoding, the color type in LodePNGInfo is set by the decoder to that of the original
+ PNG image, but it can be ignored since the raw image has the color type you requested instead
+-if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion
+ between the color types is done if the color types are supported. If it is not
+ supported, an error is returned. If the types are the same, no conversion is done.
+-even though some conversions aren't supported, LodePNG supports loading PNGs from any
+ colortype and saving PNGs to any colortype, sometimes it just requires preparing
+ the raw image correctly before encoding.
+-both encoder and decoder use the same color converter.
+
+The function lodepng_convert does the color conversion. It is available in the
+interface but normally isn't needed since the encoder and decoder already call
+it.
+
+Non supported color conversions:
+-color to grayscale when non-gray pixels are present: no error is thrown, but
+the result will look ugly because only the red channel is taken (it assumes all
+three channels are the same in this case so ignores green and blue). The reason
+no error is given is to allow converting from three-channel grayscale images to
+one-channel even if there are numerical imprecisions.
+-anything to palette when the palette does not have an exact match for a from-color
+in it: in this case an error is thrown
+
+Supported color conversions:
+-anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA
+-any gray or gray+alpha, to gray or gray+alpha
+-anything to a palette, as long as the palette has the requested colors in it
+-removing alpha channel
+-higher to smaller bitdepth, and vice versa
+
+If you want no color conversion to be done (e.g. for speed or control):
+-In the encoder, you can make it save a PNG with any color type by giving the
+raw color mode and LodePNGInfo the same color mode, and setting auto_convert to
+false.
+-In the decoder, you can make it store the pixel data in the same color type
+as the PNG has, by setting the color_convert setting to false. Settings in
+info_raw are then ignored.
+
+6.3. padding bits
+-----------------
+
+In the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines
+have a bit amount that isn't a multiple of 8, then padding bits are used so that each
+scanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output.
+The raw input image you give to the encoder, and the raw output image you get from the decoder
+will NOT have these padding bits, e.g. in the case of a 1-bit image with a width
+of 7 pixels, the first pixel of the second scanline will the the 8th bit of the first byte,
+not the first bit of a new byte.
+
+6.4. A note about 16-bits per channel and endianness
+----------------------------------------------------
+
+LodePNG uses unsigned char arrays for 16-bit per channel colors too, just like
+for any other color format. The 16-bit values are stored in big endian (most
+significant byte first) in these arrays. This is the opposite order of the
+little endian used by x86 CPU's.
+
+LodePNG always uses big endian because the PNG file format does so internally.
+Conversions to other formats than PNG uses internally are not supported by
+LodePNG on purpose, there are myriads of formats, including endianness of 16-bit
+colors, the order in which you store R, G, B and A, and so on. Supporting and
+converting to/from all that is outside the scope of LodePNG.
+
+This may mean that, depending on your use case, you may want to convert the big
+endian output of LodePNG to little endian with a for loop. This is certainly not
+always needed, many applications and libraries support big endian 16-bit colors
+anyway, but it means you cannot simply cast the unsigned char* buffer to an
+unsigned short* buffer on x86 CPUs.
+
+
+7. error values
+---------------
+
+All functions in LodePNG that return an error code, return 0 if everything went
+OK, or a non-zero code if there was an error.
+
+The meaning of the LodePNG error values can be retrieved with the function
+lodepng_error_text: given the numerical error code, it returns a description
+of the error in English as a string.
+
+Check the implementation of lodepng_error_text to see the meaning of each code.
+
+
+8. chunks and PNG editing
+-------------------------
+
+If you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG
+editor that should follow the rules about handling of unknown chunks, or if your
+program is able to read other types of chunks than the ones handled by LodePNG,
+then that's possible with the chunk functions of LodePNG.
+
+A PNG chunk has the following layout:
+
+4 bytes length
+4 bytes type name
+length bytes data
+4 bytes CRC
+
+8.1. iterating through chunks
+-----------------------------
+
+If you have a buffer containing the PNG image data, then the first chunk (the
+IHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the
+signature of the PNG and are not part of a chunk. But if you start at byte 8
+then you have a chunk, and can check the following things of it.
+
+NOTE: none of these functions check for memory buffer boundaries. To avoid
+exploits, always make sure the buffer contains all the data of the chunks.
+When using lodepng_chunk_next, make sure the returned value is within the
+allocated memory.
+
+unsigned lodepng_chunk_length(const unsigned char* chunk):
+
+Get the length of the chunk's data. The total chunk length is this length + 12.
+
+void lodepng_chunk_type(char type[5], const unsigned char* chunk):
+unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type):
+
+Get the type of the chunk or compare if it's a certain type
+
+unsigned char lodepng_chunk_critical(const unsigned char* chunk):
+unsigned char lodepng_chunk_private(const unsigned char* chunk):
+unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk):
+
+Check if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are).
+Check if the chunk is private (public chunks are part of the standard, private ones not).
+Check if the chunk is safe to copy. If it's not, then, when modifying data in a critical
+chunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your
+program doesn't handle that type of unknown chunk.
+
+unsigned char* lodepng_chunk_data(unsigned char* chunk):
+const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk):
+
+Get a pointer to the start of the data of the chunk.
+
+unsigned lodepng_chunk_check_crc(const unsigned char* chunk):
+void lodepng_chunk_generate_crc(unsigned char* chunk):
+
+Check if the crc is correct or generate a correct one.
+
+unsigned char* lodepng_chunk_next(unsigned char* chunk):
+const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk):
+
+Iterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these
+functions do no boundary checking of the allocated data whatsoever, so make sure there is enough
+data available in the buffer to be able to go to the next chunk.
+
+unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk):
+unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,
+ const char* type, const unsigned char* data):
+
+These functions are used to create new chunks that are appended to the data in *out that has
+length *outlength. The append function appends an existing chunk to the new data. The create
+function creates a new chunk with the given parameters and appends it. Type is the 4-letter
+name of the chunk.
+
+8.2. chunks in info_png
+-----------------------
+
+The LodePNGInfo struct contains fields with the unknown chunk in it. It has 3
+buffers (each with size) to contain 3 types of unknown chunks:
+the ones that come before the PLTE chunk, the ones that come between the PLTE
+and the IDAT chunks, and the ones that come after the IDAT chunks.
+It's necessary to make the distionction between these 3 cases because the PNG
+standard forces to keep the ordering of unknown chunks compared to the critical
+chunks, but does not force any other ordering rules.
+
+info_png.unknown_chunks_data[0] is the chunks before PLTE
+info_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT
+info_png.unknown_chunks_data[2] is the chunks after IDAT
+
+The chunks in these 3 buffers can be iterated through and read by using the same
+way described in the previous subchapter.
+
+When using the decoder to decode a PNG, you can make it store all unknown chunks
+if you set the option settings.remember_unknown_chunks to 1. By default, this
+option is off (0).
+
+The encoder will always encode unknown chunks that are stored in the info_png.
+If you need it to add a particular chunk that isn't known by LodePNG, you can
+use lodepng_chunk_append or lodepng_chunk_create to the chunk data in
+info_png.unknown_chunks_data[x].
+
+Chunks that are known by LodePNG should not be added in that way. E.g. to make
+LodePNG add a bKGD chunk, set background_defined to true and add the correct
+parameters there instead.
+
+
+9. compiler support
+-------------------
+
+No libraries other than the current standard C library are needed to compile
+LodePNG. For the C++ version, only the standard C++ library is needed on top.
+Add the files lodepng.c(pp) and lodepng.h to your project, include
+lodepng.h where needed, and your program can read/write PNG files.
+
+It is compatible with C90 and up, and C++03 and up.
+
+If performance is important, use optimization when compiling! For both the
+encoder and decoder, this makes a large difference.
+
+Make sure that LodePNG is compiled with the same compiler of the same version
+and with the same settings as the rest of the program, or the interfaces with
+std::vectors and std::strings in C++ can be incompatible.
+
+CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets.
+
+*) gcc and g++
+
+LodePNG is developed in gcc so this compiler is natively supported. It gives no
+warnings with compiler options "-Wall -Wextra -pedantic -ansi", with gcc and g++
+version 4.7.1 on Linux, 32-bit and 64-bit.
+
+*) Clang
+
+Fully supported and warning-free.
+
+*) Mingw
+
+The Mingw compiler (a port of gcc for Windows) should be fully supported by
+LodePNG.
+
+*) Visual Studio and Visual C++ Express Edition
+
+LodePNG should be warning-free with warning level W4. Two warnings were disabled
+with pragmas though: warning 4244 about implicit conversions, and warning 4996
+where it wants to use a non-standard function fopen_s instead of the standard C
+fopen.
+
+Visual Studio may want "stdafx.h" files to be included in each source file and
+give an error "unexpected end of file while looking for precompiled header".
+This is not standard C++ and will not be added to the stock LodePNG. You can
+disable it for lodepng.cpp only by right clicking it, Properties, C/C++,
+Precompiled Headers, and set it to Not Using Precompiled Headers there.
+
+NOTE: Modern versions of VS should be fully supported, but old versions, e.g.
+VS6, are not guaranteed to work.
+
+*) Compilers on Macintosh
+
+LodePNG has been reported to work both with gcc and LLVM for Macintosh, both for
+C and C++.
+
+*) Other Compilers
+
+If you encounter problems on any compilers, feel free to let me know and I may
+try to fix it if the compiler is modern and standards complient.
+
+
+10. examples
+------------
+
+This decoder example shows the most basic usage of LodePNG. More complex
+examples can be found on the LodePNG website.
+
+10.1. decoder C++ example
+-------------------------
+
+#include "lodepng.h"
+#include <iostream>
+
+int main(int argc, char *argv[]) {
+ const char* filename = argc > 1 ? argv[1] : "test.png";
+
+ //load and decode
+ std::vector<unsigned char> image;
+ unsigned width, height;
+ unsigned error = lodepng::decode(image, width, height, filename);
+
+ //if there's an error, display it
+ if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl;
+
+ //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ...
+}
+
+10.2. decoder C example
+-----------------------
+
+#include "lodepng.h"
+
+int main(int argc, char *argv[]) {
+ unsigned error;
+ unsigned char* image;
+ size_t width, height;
+ const char* filename = argc > 1 ? argv[1] : "test.png";
+
+ error = lodepng_decode32_file(&image, &width, &height, filename);
+
+ if(error) printf("decoder error %u: %s\n", error, lodepng_error_text(error));
+
+ / * use image here * /
+
+ free(image);
+ return 0;
+}
+
+11. state settings reference
+----------------------------
+
+A quick reference of some settings to set on the LodePNGState
+
+For decoding:
+
+state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums
+state.decoder.zlibsettings.custom_...: use custom inflate function
+state.decoder.ignore_crc: ignore CRC checksums
+state.decoder.ignore_critical: ignore unknown critical chunks
+state.decoder.ignore_end: ignore missing IEND chunk. May fail if this corruption causes other errors
+state.decoder.color_convert: convert internal PNG color to chosen one
+state.decoder.read_text_chunks: whether to read in text metadata chunks
+state.decoder.remember_unknown_chunks: whether to read in unknown chunks
+state.info_raw.colortype: desired color type for decoded image
+state.info_raw.bitdepth: desired bit depth for decoded image
+state.info_raw....: more color settings, see struct LodePNGColorMode
+state.info_png....: no settings for decoder but ouput, see struct LodePNGInfo
+
+For encoding:
+
+state.encoder.zlibsettings.btype: disable compression by setting it to 0
+state.encoder.zlibsettings.use_lz77: use LZ77 in compression
+state.encoder.zlibsettings.windowsize: tweak LZ77 windowsize
+state.encoder.zlibsettings.minmatch: tweak min LZ77 length to match
+state.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching
+state.encoder.zlibsettings.lazymatching: try one more LZ77 matching
+state.encoder.zlibsettings.custom_...: use custom deflate function
+state.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png
+state.encoder.filter_palette_zero: PNG filter strategy for palette
+state.encoder.filter_strategy: PNG filter strategy to encode with
+state.encoder.force_palette: add palette even if not encoding to one
+state.encoder.add_id: add LodePNG identifier and version as a text chunk
+state.encoder.text_compression: use compressed text chunks for metadata
+state.info_raw.colortype: color type of raw input image you provide
+state.info_raw.bitdepth: bit depth of raw input image you provide
+state.info_raw: more color settings, see struct LodePNGColorMode
+state.info_png.color.colortype: desired color type if auto_convert is false
+state.info_png.color.bitdepth: desired bit depth if auto_convert is false
+state.info_png.color....: more color settings, see struct LodePNGColorMode
+state.info_png....: more PNG related settings, see struct LodePNGInfo
+
+
+12. changes
+-----------
+
+The version number of LodePNG is the date of the change given in the format
+yyyymmdd.
+
+Some changes aren't backwards compatible. Those are indicated with a (!)
+symbol.
+
+*) 30 dec 2018: code style changes only: removed newlines before opening braces.
+*) 10 sep 2018: added way to inspect metadata chunks without full decoding.
+*) 19 aug 2018 (!): fixed color mode bKGD is encoded with and made it use
+ palette index in case of palette.
+*) 10 aug 2018 (!): added support for gAMA, cHRM, sRGB and iCCP chunks. This
+ change is backwards compatible unless you relied on unknown_chunks for those.
+*) 11 jun 2018: less restrictive check for pixel size integer overflow
+*) 14 jan 2018: allow optionally ignoring a few more recoverable errors
+*) 17 sep 2017: fix memory leak for some encoder input error cases
+*) 27 nov 2016: grey+alpha auto color model detection bugfix
+*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort).
+*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within
+ the limits of pure C90).
+*) 08 dec 2015: Made load_file function return error if file can't be opened.
+*) 24 okt 2015: Bugfix with decoding to palette output.
+*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding.
+*) 23 aug 2014: Reduced needless memory usage of decoder.
+*) 28 jun 2014: Removed fix_png setting, always support palette OOB for
+ simplicity. Made ColorProfile public.
+*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization.
+*) 22 dec 2013: Power of two windowsize required for optimization.
+*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key.
+*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png).
+*) 11 mar 2013 (!): Bugfix with custom free. Changed from "my" to "lodepng_"
+ prefix for the custom allocators and made it possible with a new #define to
+ use custom ones in your project without needing to change lodepng's code.
+*) 28 jan 2013: Bugfix with color key.
+*) 27 okt 2012: Tweaks in text chunk keyword length error handling.
+*) 8 okt 2012 (!): Added new filter strategy (entropy) and new auto color mode.
+ (no palette). Better deflate tree encoding. New compression tweak settings.
+ Faster color conversions while decoding. Some internal cleanups.
+*) 23 sep 2012: Reduced warnings in Visual Studio a little bit.
+*) 1 sep 2012 (!): Removed #define's for giving custom (de)compression functions
+ and made it work with function pointers instead.
+*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc
+ and free functions and toggle #defines from compiler flags. Small fixes.
+*) 6 may 2012 (!): Made plugging in custom zlib/deflate functions more flexible.
+*) 22 apr 2012 (!): Made interface more consistent, renaming a lot. Removed
+ redundant C++ codec classes. Reduced amount of structs. Everything changed,
+ but it is cleaner now imho and functionality remains the same. Also fixed
+ several bugs and shrunk the implementation code. Made new samples.
+*) 6 nov 2011 (!): By default, the encoder now automatically chooses the best
+ PNG color model and bit depth, based on the amount and type of colors of the
+ raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color.
+*) 9 okt 2011: simpler hash chain implementation for the encoder.
+*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching.
+*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking.
+ A bug with the PNG filtertype heuristic was fixed, so that it chooses much
+ better ones (it's quite significant). A setting to do an experimental, slow,
+ brute force search for PNG filter types is added.
+*) 17 aug 2011 (!): changed some C zlib related function names.
+*) 16 aug 2011: made the code less wide (max 120 characters per line).
+*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors.
+*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled.
+*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman
+ to optimize long sequences of zeros.
+*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and
+ LodePNG_InfoColor_canHaveAlpha functions for convenience.
+*) 7 nov 2010: added LodePNG_error_text function to get error code description.
+*) 30 okt 2010: made decoding slightly faster
+*) 26 okt 2010: (!) changed some C function and struct names (more consistent).
+ Reorganized the documentation and the declaration order in the header.
+*) 08 aug 2010: only changed some comments and external samples.
+*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version.
+*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers.
+*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could
+ read by ignoring the problem but windows apps couldn't.
+*) 06 jun 2008: added more error checks for out of memory cases.
+*) 26 apr 2008: added a few more checks here and there to ensure more safety.
+*) 06 mar 2008: crash with encoding of strings fixed
+*) 02 feb 2008: support for international text chunks added (iTXt)
+*) 23 jan 2008: small cleanups, and #defines to divide code in sections
+*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor.
+*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder.
+*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added
+ Also various fixes, such as in the deflate and the padding bits code.
+*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved
+ filtering code of encoder.
+*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A
+ C++ wrapper around this provides an interface almost identical to before.
+ Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code
+ are together in these files but it works both for C and C++ compilers.
+*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks
+*) 30 aug 2007: bug fixed which makes this Borland C++ compatible
+*) 09 aug 2007: some VS2005 warnings removed again
+*) 21 jul 2007: deflate code placed in new namespace separate from zlib code
+*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images
+*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing
+ invalid std::vector element [0] fixed, and level 3 and 4 warnings removed
+*) 02 jun 2007: made the encoder add a tag with version by default
+*) 27 may 2007: zlib and png code separated (but still in the same file),
+ simple encoder/decoder functions added for more simple usage cases
+*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69),
+ moved some examples from here to lodepng_examples.cpp
+*) 12 may 2007: palette decoding bug fixed
+*) 24 apr 2007: changed the license from BSD to the zlib license
+*) 11 mar 2007: very simple addition: ability to encode bKGD chunks.
+*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding
+ palettized PNG images. Plus little interface change with palette and texts.
+*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes.
+ Fixed a bug where the end code of a block had length 0 in the Huffman tree.
+*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented
+ and supported by the encoder, resulting in smaller PNGs at the output.
+*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone.
+*) 24 jan 2007: gave encoder an error interface. Added color conversion from any
+ greyscale type to 8-bit greyscale with or without alpha.
+*) 21 jan 2007: (!) Totally changed the interface. It allows more color types
+ to convert to and is more uniform. See the manual for how it works now.
+*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days:
+ encode/decode custom tEXt chunks, separate classes for zlib & deflate, and
+ at last made the decoder give errors for incorrect Adler32 or Crc.
+*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel.
+*) 29 dec 2006: Added support for encoding images without alpha channel, and
+ cleaned out code as well as making certain parts faster.
+*) 28 dec 2006: Added "Settings" to the encoder.
+*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now.
+ Removed some code duplication in the decoder. Fixed little bug in an example.
+*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter.
+ Fixed a bug of the decoder with 16-bit per color.
+*) 15 okt 2006: Changed documentation structure
+*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the
+ given image buffer, however for now it's not compressed.
+*) 08 sep 2006: (!) Changed to interface with a Decoder class
+*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different
+ way. Renamed decodePNG to decodePNGGeneric.
+*) 29 jul 2006: (!) Changed the interface: image info is now returned as a
+ struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy.
+*) 28 jul 2006: Cleaned the code and added new error checks.
+ Corrected terminology "deflate" into "inflate".
+*) 23 jun 2006: Added SDL example in the documentation in the header, this
+ example allows easy debugging by displaying the PNG and its transparency.
+*) 22 jun 2006: (!) Changed way to obtain error value. Added
+ loadFile function for convenience. Made decodePNG32 faster.
+*) 21 jun 2006: (!) Changed type of info vector to unsigned.
+ Changed position of palette in info vector. Fixed an important bug that
+ happened on PNGs with an uncompressed block.
+*) 16 jun 2006: Internally changed unsigned into unsigned where
+ needed, and performed some optimizations.
+*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them
+ in LodePNG namespace. Changed the order of the parameters. Rewrote the
+ documentation in the header. Renamed files to lodepng.cpp and lodepng.h
+*) 22 apr 2006: Optimized and improved some code
+*) 07 sep 2005: (!) Changed to std::vector interface
+*) 12 aug 2005: Initial release (C++, decoder only)
+
+
+13. contact information
+-----------------------
+
+Feel free to contact me with suggestions, problems, comments, ... concerning
+LodePNG. If you encounter a PNG image that doesn't work properly with this
+decoder, feel free to send it and I'll use it to find and fix the problem.
+
+My email address is (puzzle the account and domain together with an @ symbol):
+Domain: gmail dot com.
+Account: lode dot vandevenne.
+
+
+Copyright (c) 2005-2019 Lode Vandevenne
+*/
diff --git a/thirdparty/basis_universal/transcoder/basisu.h b/thirdparty/basis_universal/transcoder/basisu.h
new file mode 100644
index 0000000000..25600a69bf
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu.h
@@ -0,0 +1,386 @@
+// basisu.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#ifdef _MSC_VER
+
+ #pragma warning (disable : 4201)
+ #pragma warning (disable : 4127) // warning C4127: conditional expression is constant
+ #pragma warning (disable : 4530) // C++ exception handler used, but unwind semantics are not enabled.
+
+ #ifndef BASISU_NO_ITERATOR_DEBUG_LEVEL
+ //#define _HAS_ITERATOR_DEBUGGING 0
+
+ #if defined(_DEBUG) || defined(DEBUG)
+ // This is madness, but we need to disable iterator debugging in debug builds or the encoder is unsable because MSVC's iterator debugging implementation is totally broken.
+ #ifndef _ITERATOR_DEBUG_LEVEL
+ #define _ITERATOR_DEBUG_LEVEL 1
+ #endif
+ #ifndef _SECURE_SCL
+ #define _SECURE_SCL 1
+ #endif
+ #else // defined(_DEBUG) || defined(DEBUG)
+ #ifndef _SECURE_SCL
+ #define _SECURE_SCL 0
+ #endif
+ #ifndef _ITERATOR_DEBUG_LEVEL
+ #define _ITERATOR_DEBUG_LEVEL 0
+ #endif
+ #endif // defined(_DEBUG) || defined(DEBUG)
+
+ #ifndef NOMINMAX
+ #define NOMINMAX
+ #endif
+
+ #endif // BASISU_NO_ITERATOR_DEBUG_LEVEL
+
+#endif // _MSC_VER
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdarg.h>
+#include <string.h>
+#include <memory.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <limits>
+#include <functional>
+#include <iterator>
+#include <type_traits>
+#include <vector>
+#include <assert.h>
+#include <random>
+
+#ifdef max
+#undef max
+#endif
+
+#ifdef min
+#undef min
+#endif
+
+#ifdef _WIN32
+#define strcasecmp _stricmp
+#endif
+
+// Set to one to enable debug printf()'s when any errors occur, for development/debugging.
+#ifndef BASISU_DEVEL_MESSAGES
+#define BASISU_DEVEL_MESSAGES 0
+#endif
+
+#define BASISU_NOTE_UNUSED(x) (void)(x)
+#define BASISU_ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#define BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(x) x(const x &) = delete; x& operator= (const x &) = delete;
+#define BASISU_ASSUME(x) static_assert(x, #x);
+#define BASISU_OFFSETOF(s, m) (uint32_t)(intptr_t)(&((s *)(0))->m)
+#define BASISU_STRINGIZE(x) #x
+#define BASISU_STRINGIZE2(x) BASISU_STRINGIZE(x)
+
+#if BASISU_DEVEL_MESSAGES
+ #define BASISU_DEVEL_ERROR(...) do { basisu::debug_printf(__VA_ARGS__); } while(0)
+#else
+ #define BASISU_DEVEL_ERROR(...)
+#endif
+
+namespace basisu
+{
+ // Types/utilities
+
+#ifdef _WIN32
+ const char BASISU_PATH_SEPERATOR_CHAR = '\\';
+#else
+ const char BASISU_PATH_SEPERATOR_CHAR = '/';
+#endif
+
+ typedef std::vector<uint8_t> uint8_vec;
+ typedef std::vector<int16_t> int16_vec;
+ typedef std::vector<uint16_t> uint16_vec;
+ typedef std::vector<uint32_t> uint_vec;
+ typedef std::vector<uint64_t> uint64_vec;
+ typedef std::vector<int> int_vec;
+ typedef std::vector<bool> bool_vec;
+
+ void enable_debug_printf(bool enabled);
+ void debug_printf(const char *pFmt, ...);
+
+ template <typename T> inline void clear_obj(T& obj) { memset(&obj, 0, sizeof(obj)); }
+
+ template <typename T0, typename T1> inline T0 lerp(T0 a, T0 b, T1 c) { return a + (b - a) * c; }
+
+ template <typename S> inline S maximum(S a, S b) { return (a > b) ? a : b; }
+ template <typename S> inline S maximum(S a, S b, S c) { return maximum(maximum(a, b), c); }
+
+ template <typename S> inline S minimum(S a, S b) { return (a < b) ? a : b; }
+ template <typename S> inline S minimum(S a, S b, S c) { return minimum(minimum(a, b), c); }
+
+ template <typename S> inline S clamp(S value, S low, S high) { return (value < low) ? low : ((value > high) ? high : value); }
+
+ inline uint32_t iabs(int32_t i) { return (i < 0) ? static_cast<uint32_t>(-i) : static_cast<uint32_t>(i); }
+ inline uint64_t iabs64(int64_t i) { return (i < 0) ? static_cast<uint64_t>(-i) : static_cast<uint64_t>(i); }
+
+ template<typename T> inline void clear_vector(T &vec) { vec.erase(vec.begin(), vec.end()); }
+ template<typename T> inline typename T::value_type *enlarge_vector(T &vec, size_t n) { size_t cs = vec.size(); vec.resize(cs + n); return &vec[cs]; }
+
+ template<typename S> inline S square(S val) { return val * val; }
+
+ inline bool is_pow2(uint32_t x) { return x && ((x & (x - 1U)) == 0U); }
+ inline bool is_pow2(uint64_t x) { return x && ((x & (x - 1U)) == 0U); }
+
+ template<typename T> inline T open_range_check(T v, T minv, T maxv) { assert(v >= minv && v < maxv); return v; }
+ template<typename T> inline T open_range_check(T v, T maxv) { assert(v < maxv); BASISU_NOTE_UNUSED(maxv); return v; }
+
+ inline uint32_t total_bits(uint32_t v) { uint32_t l = 0; for ( ; v > 0U; ++l) v >>= 1; return l; }
+
+ template<typename T> inline T saturate(T val) { return clamp(val, 0.0f, 1.0f); }
+
+ template<typename T, typename R> inline void append_vector(T &vec, const R *pObjs, size_t n)
+ {
+ if (n)
+ {
+ const size_t cur_s = vec.size();
+ vec.resize(cur_s + n);
+ memcpy(&vec[cur_s], pObjs, sizeof(R) * n);
+ }
+ }
+
+ template<typename T> inline void append_vector(T &vec, const T &other_vec)
+ {
+ if (other_vec.size())
+ append_vector(vec, &other_vec[0], other_vec.size());
+ }
+
+ template<typename T> inline void vector_ensure_element_is_valid(T &vec, size_t idx)
+ {
+ if (idx >= vec.size())
+ vec.resize(idx + 1);
+ }
+
+ template<typename T> inline void vector_sort(T &vec)
+ {
+ if (vec.size())
+ std::sort(vec.begin(), vec.end());
+ }
+
+ template<typename T, typename U> inline bool unordered_set_contains(T& set, const U&obj)
+ {
+ return set.find(obj) != set.end();
+ }
+
+ template<typename T> int vector_find(const T &vec, const typename T::value_type &obj)
+ {
+ assert(vec.size() <= INT_MAX);
+ for (size_t i = 0; i < vec.size(); i++)
+ if (vec[i] == obj)
+ return static_cast<int>(i);
+ return -1;
+ }
+
+ template<typename T> void vector_set_all(T &vec, const typename T::value_type &obj)
+ {
+ for (size_t i = 0; i < vec.size(); i++)
+ vec[i] = obj;
+ }
+
+ inline uint64_t read_be64(const void *p)
+ {
+ uint64_t val = 0;
+ for (uint32_t i = 0; i < 8; i++)
+ val |= (static_cast<uint64_t>(static_cast<const uint8_t *>(p)[7 - i]) << (i * 8));
+ return val;
+ }
+
+ inline void write_be64(void *p, uint64_t x)
+ {
+ for (uint32_t i = 0; i < 8; i++)
+ static_cast<uint8_t *>(p)[7 - i] = static_cast<uint8_t>(x >> (i * 8));
+ }
+
+ static inline uint16_t byteswap16(uint16_t x) { return static_cast<uint16_t>((x << 8) | (x >> 8)); }
+ static inline uint32_t byteswap32(uint32_t x) { return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24)); }
+
+ inline uint32_t floor_log2i(uint32_t v)
+ {
+ uint32_t b = 0;
+ for (; v > 1U; ++b)
+ v >>= 1;
+ return b;
+ }
+
+ inline uint32_t ceil_log2i(uint32_t v)
+ {
+ uint32_t b = floor_log2i(v);
+ if ((b != 32) && (v > (1U << b)))
+ ++b;
+ return b;
+ }
+
+ inline int posmod(int x, int y)
+ {
+ if (x >= 0)
+ return (x < y) ? x : (x % y);
+ int m = (-x) % y;
+ return (m != 0) ? (y - m) : m;
+ }
+
+ inline bool do_excl_ranges_overlap(int la, int ha, int lb, int hb)
+ {
+ assert(la < ha && lb < hb);
+ if ((ha <= lb) || (la >= hb)) return false;
+ return true;
+ }
+
+ // Always little endian 2-4 byte unsigned int
+ template<uint32_t NumBytes>
+ struct packed_uint
+ {
+ uint8_t m_bytes[NumBytes];
+
+ inline packed_uint() { static_assert(NumBytes <= 4, "NumBytes <= 4"); }
+ inline packed_uint(uint32_t v) { *this = v; }
+ inline packed_uint(const packed_uint& other) { *this = other; }
+
+ inline packed_uint& operator= (uint32_t v) { for (uint32_t i = 0; i < NumBytes; i++) m_bytes[i] = static_cast<uint8_t>(v >> (i * 8)); return *this; }
+
+ inline operator uint32_t() const
+ {
+ switch (NumBytes)
+ {
+ case 1: return m_bytes[0];
+ case 2: return (m_bytes[1] << 8U) | m_bytes[0];
+ case 3: return (m_bytes[2] << 16U) | (m_bytes[1] << 8U) | (m_bytes[0]);
+ default: return (m_bytes[3] << 24U) | (m_bytes[2] << 16U) | (m_bytes[1] << 8U) | (m_bytes[0]);
+ }
+ }
+ };
+
+ enum eZero { cZero };
+ enum eNoClamp { cNoClamp };
+
+ // Rice/Huffman entropy coding
+
+ // This is basically Deflate-style canonical Huffman, except we allow for a lot more symbols.
+ enum
+ {
+ cHuffmanMaxSupportedCodeSize = 16, cHuffmanMaxSupportedInternalCodeSize = 31,
+ cHuffmanFastLookupBits = 10, cHuffmanFastLookupSize = 1 << cHuffmanFastLookupBits,
+ cHuffmanMaxSymsLog2 = 14, cHuffmanMaxSyms = 1 << cHuffmanMaxSymsLog2,
+
+ // Small zero runs
+ cHuffmanSmallZeroRunSizeMin = 3, cHuffmanSmallZeroRunSizeMax = 10, cHuffmanSmallZeroRunExtraBits = 3,
+
+ // Big zero run
+ cHuffmanBigZeroRunSizeMin = 11, cHuffmanBigZeroRunSizeMax = 138, cHuffmanBigZeroRunExtraBits = 7,
+
+ // Small non-zero run
+ cHuffmanSmallRepeatSizeMin = 3, cHuffmanSmallRepeatSizeMax = 6, cHuffmanSmallRepeatExtraBits = 2,
+
+ // Big non-zero run
+ cHuffmanBigRepeatSizeMin = 7, cHuffmanBigRepeatSizeMax = 134, cHuffmanBigRepeatExtraBits = 7,
+
+ cHuffmanTotalCodelengthCodes = 21, cHuffmanSmallZeroRunCode = 17, cHuffmanBigZeroRunCode = 18, cHuffmanSmallRepeatCode = 19, cHuffmanBigRepeatCode = 20
+ };
+
+ static const uint8_t g_huffman_sorted_codelength_codes[] = { cHuffmanSmallZeroRunCode, cHuffmanBigZeroRunCode, cHuffmanSmallRepeatCode, cHuffmanBigRepeatCode, 0, 8, 7, 9, 6, 0xA, 5, 0xB, 4, 0xC, 3, 0xD, 2, 0xE, 1, 0xF, 0x10 };
+ const uint32_t cHuffmanTotalSortedCodelengthCodes = sizeof(g_huffman_sorted_codelength_codes) / sizeof(g_huffman_sorted_codelength_codes[0]);
+
+ // GPU texture formats
+
+ enum class texture_format
+ {
+ cInvalidTextureFormat = -1,
+
+ // Block-based formats
+ cETC1, // ETC1
+ cETC1S, // ETC1 (subset: diff colors only, no subblocks)
+ cETC2_RGB, // ETC2 color block
+ cETC2_RGBA, // ETC2 alpha block followed by ETC2 color block
+ cETC2_ALPHA, // ETC2 EAC alpha block
+ cBC1, // DXT1
+ cBC3, // DXT5 (DXT5A block followed by a DXT1 block)
+ cBC4, // DXT5A
+ cBC5, // 3DC/DXN (two DXT5A blocks)
+ cBC7,
+ cASTC4x4,
+ cPVRTC1_4_RGB,
+ cPVRTC1_4_RGBA,
+ cATC_RGB,
+ cATC_RGBA_INTERPOLATED_ALPHA,
+ cFXT1_RGB,
+ cPVRTC2_4_RGBA,
+ cETC2_R11_EAC,
+ cETC2_RG11_EAC,
+
+ // Uncompressed/raw pixels
+ cRGBA32,
+ cRGB565,
+ cBGR565,
+ cRGBA4444,
+ cABGR4444
+ };
+
+ inline uint32_t get_bytes_per_block(texture_format fmt)
+ {
+ switch (fmt)
+ {
+ case texture_format::cETC1:
+ case texture_format::cETC1S:
+ case texture_format::cETC2_RGB:
+ case texture_format::cETC2_ALPHA:
+ case texture_format::cBC1:
+ case texture_format::cBC4:
+ case texture_format::cPVRTC1_4_RGB:
+ case texture_format::cPVRTC1_4_RGBA:
+ case texture_format::cATC_RGB:
+ case texture_format::cPVRTC2_4_RGBA:
+ case texture_format::cETC2_R11_EAC:
+ return 8;
+ case texture_format::cRGBA32:
+ return sizeof(uint32_t) * 16;
+ default:
+ break;
+ }
+ return 16;
+ }
+
+ inline uint32_t get_qwords_per_block(texture_format fmt)
+ {
+ return get_bytes_per_block(fmt) >> 3;
+ }
+
+ inline uint32_t get_block_width(texture_format fmt)
+ {
+ BASISU_NOTE_UNUSED(fmt);
+ switch (fmt)
+ {
+ case texture_format::cFXT1_RGB:
+ return 8;
+ default:
+ break;
+ }
+ return 4;
+ }
+
+ inline uint32_t get_block_height(texture_format fmt)
+ {
+ BASISU_NOTE_UNUSED(fmt);
+ return 4;
+ }
+
+} // namespace basisu
+
diff --git a/thirdparty/basis_universal/transcoder/basisu_file_headers.h b/thirdparty/basis_universal/transcoder/basisu_file_headers.h
new file mode 100644
index 0000000000..c90b3f3af0
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_file_headers.h
@@ -0,0 +1,121 @@
+// basis_file_headers.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "basisu_transcoder_internal.h"
+
+namespace basist
+{
+ // Slice desc header flags
+ enum basis_slice_desc_flags
+ {
+ cSliceDescFlagsIsAlphaData = 1,
+ cSliceDescFlagsFrameIsIFrame = 2 // Video only: Frame doesn't refer to previous frame (no usage of conditional replenishment pred symbols)
+ };
+
+#pragma pack(push)
+#pragma pack(1)
+ struct basis_slice_desc
+ {
+ basisu::packed_uint<3> m_image_index; // The index of the source image provided to the encoder (will always appear in order from first to last, first image index is 0, no skipping allowed)
+ basisu::packed_uint<1> m_level_index; // The mipmap level index (mipmaps will always appear from largest to smallest)
+ basisu::packed_uint<1> m_flags; // enum basis_slice_desc_flags
+
+ basisu::packed_uint<2> m_orig_width; // The original image width (may not be a multiple of 4 pixels)
+ basisu::packed_uint<2> m_orig_height; // The original image height (may not be a multiple of 4 pixels)
+
+ basisu::packed_uint<2> m_num_blocks_x; // The slice's block X dimensions. Each block is 4x4 pixels. The slice's pixel resolution may or may not be a power of 2.
+ basisu::packed_uint<2> m_num_blocks_y; // The slice's block Y dimensions.
+
+ basisu::packed_uint<4> m_file_ofs; // Offset from the header to the start of the slice's data
+ basisu::packed_uint<4> m_file_size; // The size of the compressed slice data in bytes
+
+ basisu::packed_uint<2> m_slice_data_crc16; // The CRC16 of the compressed slice data, for extra-paranoid use cases
+ };
+
+ // File header files
+ enum basis_header_flags
+ {
+ cBASISHeaderFlagETC1S = 1, // Always set for basis universal files
+ cBASISHeaderFlagYFlipped = 2, // Set if the texture had to be Y flipped before encoding
+ cBASISHeaderFlagHasAlphaSlices = 4 // True if the odd slices contain alpha data
+ };
+
+ // The image type field attempts to describe how to interpret the image data in a Basis file.
+ // The encoder library doesn't really do anything special or different with these texture types, this is mostly here for the benefit of the user.
+ // We do make sure the various constraints are followed (2DArray/cubemap/videoframes/volume implies that each image has the same resolution and # of mipmap levels, etc., cubemap implies that the # of image slices is a multiple of 6)
+ enum basis_texture_type
+ {
+ cBASISTexType2D = 0, // An arbitrary array of 2D RGB or RGBA images with optional mipmaps, array size = # images, each image may have a different resolution and # of mipmap levels
+ cBASISTexType2DArray = 1, // An array of 2D RGB or RGBA images with optional mipmaps, array size = # images, each image has the same resolution and mipmap levels
+ cBASISTexTypeCubemapArray = 2, // an array of cubemap levels, total # of images must be divisable by 6, in X+, X-, Y+, Y-, Z+, Z- order, with optional mipmaps
+ cBASISTexTypeVideoFrames = 3, // An array of 2D video frames, with optional mipmaps, # frames = # images, each image has the same resolution and # of mipmap levels
+ cBASISTexTypeVolume = 4, // A 3D texture with optional mipmaps, Z dimension = # images, each image has the same resolution and # of mipmap levels
+
+ cBASISTexTypeTotal
+ };
+
+ enum
+ {
+ cBASISMaxUSPerFrame = 0xFFFFFF
+ };
+
+ struct basis_file_header
+ {
+ enum
+ {
+ cBASISSigValue = ('B' << 8) | 's',
+ cBASISFirstVersion = 0x10
+ };
+
+ basisu::packed_uint<2> m_sig; // 2 byte file signature
+ basisu::packed_uint<2> m_ver; // Baseline file version
+ basisu::packed_uint<2> m_header_size; // Header size in bytes, sizeof(basis_file_header)
+ basisu::packed_uint<2> m_header_crc16; // crc16 of the remaining header data
+
+ basisu::packed_uint<4> m_data_size; // The total size of all data after the header
+ basisu::packed_uint<2> m_data_crc16; // The CRC16 of all data after the header
+
+ basisu::packed_uint<3> m_total_slices; // The total # of compressed slices (1 slice per image, or 2 for alpha basis files)
+
+ basisu::packed_uint<3> m_total_images; // The total # of images
+
+ basisu::packed_uint<1> m_format; // enum basist::block_format
+ basisu::packed_uint<2> m_flags; // enum basist::header_flags
+ basisu::packed_uint<1> m_tex_type; // enum basist::basis_texture_type
+ basisu::packed_uint<3> m_us_per_frame; // Framerate of video, in microseconds per frame
+
+ basisu::packed_uint<4> m_reserved; // For future use
+ basisu::packed_uint<4> m_userdata0; // For client use
+ basisu::packed_uint<4> m_userdata1; // For client use
+
+ basisu::packed_uint<2> m_total_endpoints; // The number of endpoints in the endpoint codebook
+ basisu::packed_uint<4> m_endpoint_cb_file_ofs; // The compressed endpoint codebook's file offset relative to the header
+ basisu::packed_uint<3> m_endpoint_cb_file_size; // The compressed endpoint codebook's size in bytes
+
+ basisu::packed_uint<2> m_total_selectors; // The number of selectors in the endpoint codebook
+ basisu::packed_uint<4> m_selector_cb_file_ofs; // The compressed selectors codebook's file offset relative to the header
+ basisu::packed_uint<3> m_selector_cb_file_size; // The compressed selector codebook's size in bytes
+
+ basisu::packed_uint<4> m_tables_file_ofs; // The file offset of the compressed Huffman codelength tables, for decompressing slices
+ basisu::packed_uint<4> m_tables_file_size; // The file size in bytes of the compressed huffman codelength tables
+
+ basisu::packed_uint<4> m_slice_desc_file_ofs; // The file offset to the slice description array, usually follows the header
+
+ basisu::packed_uint<4> m_extended_file_ofs; // The file offset of the "extended" header and compressed data, for future use
+ basisu::packed_uint<4> m_extended_file_size; // The file size in bytes of the "extended" header and compressed data, for future use
+ };
+#pragma pack (pop)
+
+} // namespace basist
diff --git a/thirdparty/basis_universal/transcoder/basisu_global_selector_cb.h b/thirdparty/basis_universal/transcoder/basisu_global_selector_cb.h
new file mode 100644
index 0000000000..695b0b3b97
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_global_selector_cb.h
@@ -0,0 +1,272 @@
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+{
+0x0, 0x505, 0x5555, 0x5F5F, 0x5055050, 0x5055F5F, 0x50AAA551, 0xFAA5A5AA, 0x6AAA5095, 0x41E6FBAB, 0x19AE99F5, 0x1057AAA4, 0x54005A1A, 0x4459AEAF, 0x56015B, 0xBAA9A554,
+0x4335E5E0, 0xD9FE5FBB, 0x2525256A, 0x9AE892, 0xC0D5FAF5, 0x5BA5E641, 0x7EDEC8B8, 0xBB671211, 0x4C9844EE, 0xEE042415, 0xE5663EAE, 0x90909091, 0xAAA45AFF, 0x15556E1D, 0xA6959195, 0x4BFF8BF,
+0x5166AAF, 0x15490065, 0x6F5BAFAF, 0xFF00FF00, 0xD96956AA, 0x15AF6B, 0xFF5A00AA, 0xE0E557AA, 0x1A6F19BD, 0x69655555, 0xD0500158, 0xEEEDD894, 0xE4E4FE, 0xC71B7B10, 0x55AA5AAF, 0x50AA59BE,
+0xE4E990E4, 0x5353B63B, 0xFEE5D0E4, 0x96AF051A, 0x3CC95A6, 0x70B5A40D, 0x9504196E, 0x4A0BD7A3, 0x11B89592, 0xAAFF4095, 0x55A5D4E0, 0xBBA55050, 0x1111666, 0xA5544000, 0xED994444, 0x5A56BF,
+0x94A954B9, 0xFB651000, 0x604E633E, 0x14291A15, 0x56965956, 0xB8E0D0C0, 0x5A565A55, 0x65A61A6A, 0xE490F990, 0xCA87AAF5, 0x6060A0B, 0x24C23143, 0x55AA9A40, 0x505E1605, 0xCEC0486E, 0x156E55EA,
+0x79978B0B, 0x4595F53C, 0x405C4AF7, 0xC1897D75, 0xD5F40BA6, 0x95444017, 0x14AD6935, 0x87C7A7BD, 0x4A4E8597, 0xFF1D7E55, 0x451400F9, 0x1112277B, 0x9A0590F8, 0x53E3492E, 0xE590E995, 0x7E730A9A,
+0x929697E7, 0x2E781609, 0xE22317A1, 0xEDE9D884, 0xDDD75CDD, 0xAF1B6F1A, 0xE6909047, 0xA77DAD5D, 0x184C0D5D, 0xFAB56010, 0x5EA4F1D0, 0x11166B6B, 0xF51A7AD6, 0xF79950F4, 0x1B6B1B11, 0x9A6D6469,
+0x441997E, 0x4546869A, 0x95AA6965, 0x155A6A, 0x6E68B0E6, 0x5A55A665, 0x1B051605, 0x601D8BE6, 0xBD2F1B06, 0x409A429B, 0x23272721, 0xB07454A9, 0x7E66A3A1, 0x1B6A5500, 0xA0E0F5A6, 0xBF5A0500,
+0x55A5A9A9, 0x99D9E995, 0xE440566F, 0x6550BE99, 0x2267777B, 0xFA50FE50, 0xA657B441, 0xB4E29343, 0x555090E5, 0x45465B6B, 0xE654E6, 0xEA90469B, 0x2E05D2F4, 0x99594444, 0xF1C20746, 0x295AD2E0,
+0xF990EA95, 0x804459AE, 0xA9999894, 0x1F41E4A5, 0x4040E5E5, 0x5481E1F2, 0x2AFF59F1, 0x6B6B1712, 0xA7131051, 0xF9406F16, 0x1B2B5B9E, 0x587E0F2F, 0x547E1919, 0xD0F5645B, 0xB1B1B1B, 0x5756A4FE,
+0x46A9B965, 0x1529F99D, 0xE490E490, 0x4495FE, 0x985E0B06, 0x5FD2D23A, 0x5D0E95A, 0xF69103F4, 0x4029790, 0x1B062F1B, 0xEE594500, 0xB6539B5A, 0x106165BA, 0xD26B7C8D, 0x8B2A25A5, 0x55EAD5E3,
+0x431FB8E1, 0xBEB4E646, 0x9A5A4545, 0x5015A6B, 0x90D4B83D, 0xDB8A99A4, 0x9E894905, 0xDD7D1101, 0xA95E00BF, 0x579FA5A5, 0xA292D145, 0x93292C96, 0xF9A995A5, 0xBFE8A450, 0xB990D15B, 0x45D1E01A,
+0x4BD3F767, 0xF243479A, 0x7E420927, 0xF9E5E090, 0xA1C869F, 0x253A36, 0x9BAB569A, 0x4147031F, 0xA059AFE, 0xE0D6590F, 0xD5EAD5E6, 0x9A4B4641, 0x5AAA4406, 0x55EA90E4, 0x10179BC4, 0x44485999,
+0x5156253E, 0x1F29E054, 0xCDDAA773, 0x5601AB05, 0x94FC94C0, 0x116166BB, 0xBF964006, 0x414196EB, 0x8498D9ED, 0xB5E08687, 0xBD564150, 0x2B8D9DF8, 0x7F12017E, 0x90904747, 0x50B56AB, 0xDBD19490,
+0xBB5A5659, 0xBAF40E4, 0x6D649014, 0x1D29166F, 0x414F3D75, 0x6F929540, 0x565AAF05, 0xBD9884E5, 0xF5342A25, 0x157915AE, 0x1A055A55, 0x9019A19F, 0x64B96A05, 0x35689CCC, 0x996012E2, 0x5252677B,
+0x156AA401, 0x25BCE483, 0xAA665555, 0xD6AF4B0F, 0x3F4BBDE0, 0x9404A9AF, 0xA590F9E4, 0x8191A5FD, 0x568190B4, 0x591A6616, 0x92C11D3E, 0x97D2E5FC, 0xF5A55A6F, 0xBEE0969B, 0x8918B4CA, 0xE0915397,
+0x5243472F, 0x95EA4055, 0x55E6E0A4, 0x9AEBD181, 0xF4A25357, 0x11115666, 0xFE45FF0A, 0x8BC7D2E1, 0x800556BB, 0x757D6A96, 0xFA909A5B, 0x68962FDB, 0xEB0056AA, 0x69970241, 0xAA58AD64, 0xC4D9DED5,
+0x5A5BF2F0, 0xBD0905B4, 0x197D7801, 0x8987EDC4, 0xFF40565A, 0x460978A4, 0xE4067FE4, 0x5DA23153, 0xB90565AE, 0x5E14B946, 0x4E35879F, 0xC72F8666, 0x1816472F, 0x9A5A4949, 0x64A0D1E5, 0xC7025B1A,
+0x1B061B55, 0xFFAA051B, 0xAF5DEDA1, 0xAA955094, 0x6659965A, 0x99A95DAD, 0x9450A5A5, 0xA550A595, 0x6914B950, 0xEF454944, 0x906BB990, 0xD680944B, 0xE091461B, 0x5363B7BB, 0xF0743906, 0x66566A69,
+0x4B85D0BC, 0x40E494A5, 0x1161B6B6, 0x519BD59, 0x5998401, 0x1651F26B, 0x5709BB1B, 0x6AE1D1B9, 0xD19297BF, 0x1A69FEE4, 0x6066B5A, 0x74A56491, 0xB4661151, 0x559191A4, 0x96756A68, 0xF5C791A6,
+0x20297A15, 0x6B660100, 0x313177A2, 0x55054150, 0x6A969669, 0xF0B82111, 0x555A6996, 0xB666295A, 0x1EA95441, 0x6A166BA5, 0x8C18566D, 0x2797278A, 0x82A552BD, 0xF964BD14, 0x41540668, 0x5078785A,
+0x5754FE, 0xF9E0E5FA, 0x15453D3F, 0x5A9699A9, 0xD9854147, 0x849494E9, 0x1DC39734, 0x67E797B3, 0x107066F, 0xAED9986C, 0xAB564140, 0x9B51A6B7, 0x5FD3E2F4, 0x5A5429F9, 0xF9A05161, 0x5A5A6965,
+0xDDD88484, 0xFA50FA55, 0x90E5E4FA, 0x6BF166B, 0x6566665A, 0xE450A6E5, 0xEB45AA04, 0xDA9A4646, 0xD7A37235, 0x11431B97, 0xD41D6E64, 0xD3D3A1A0, 0x5D540E9, 0x627777BB, 0x5054A4BE, 0x593A05ED,
+0x2EBE454B, 0x1ABA1015, 0x7C64B460, 0xC358B47F, 0x176F4293, 0xA6E417AB, 0xF611756E, 0x1F40D499, 0x84885D5F, 0x2F0B9B9B, 0x14BE05, 0xE5919590, 0x101B146E, 0x7B261190, 0xDC96F8B0, 0xF460257E,
+0x34B0AFC0, 0xEB9140FE, 0xC5C589DD, 0x1F6D6865, 0xF5100195, 0xAF560607, 0x505066B5, 0x7E590999, 0x13E190E4, 0xA56ABD59, 0xC21B68D7, 0xE594E4, 0xF6576E50, 0xFFA751D1, 0x19A179CB, 0x2726797,
+0xA1931C7C, 0xE1D90F1B, 0x7F2B2510, 0x6AF90055, 0x5F1E4C88, 0xE410757A, 0x95702212, 0x7B762100, 0x1B05BF6A, 0x16F05AB, 0xDDC5C9C9, 0x72BE594, 0xE490E555, 0xC5E50106, 0x816DAC16, 0x5540FA90,
+0x156605FF, 0x3B372621, 0x2B57A67D, 0x6C661E16, 0x1E97A917, 0xE6E2D383, 0x1B40F91B, 0xD9A63333, 0x34E18629, 0xA71616E9, 0x84946D99, 0x1B6906AF, 0xEFDE8904, 0x88F52470, 0x50E990F8, 0x4182E1B4,
+0xBAE1865B, 0xF48E4F4, 0x64A0517F, 0xA1F45902, 0x12177BF5, 0x465EBD91, 0x37A747, 0xF0A5106, 0x4C4E8A5, 0x62779E65, 0xDE494989, 0x7B6796D1, 0xC5C5C58A, 0xE4786B07, 0x6F07E0F9, 0x5554A550,
+0x95559333, 0x747A6B5, 0xA4A45500, 0xE998444, 0xF5966371, 0x111116BB, 0x783A679, 0x95409AFF, 0xFF9690E4, 0x60743EBD, 0x1C5A90FD, 0x2B051EE9, 0x5B7A1624, 0xEB415701, 0x1B6B0155, 0x9BCB8586,
+0x599E5C51, 0x510064BE, 0x50FA6060, 0x16066B5B, 0x54DA89D5, 0xA01468B5, 0xC1655E5, 0x55FF6657, 0xE4985E9, 0xD738BE27, 0x6938D450, 0x47D0E4FE, 0x4858986E, 0xE793431E, 0x1A05FFFD, 0x18939141,
+0x15EE4620, 0x79E45151, 0x663AA556, 0xD1266DD9, 0x7E0655E0, 0xB6A7676D, 0x54A96AA5, 0x1664092B, 0x56517AA0, 0xD6402CB8, 0x40A7773C, 0x554F0646, 0x488D5F2F, 0xE4E49095, 0x1C7CB4E0, 0x7C27529A,
+0xF6FAA151, 0xCC7358D6, 0xE8406D15, 0x6E074B5F, 0x638359F7, 0xD4E9A88C, 0xE888050F, 0xE6546A0B, 0xB9904EBD, 0x755061AF, 0xA371285C, 0xE95A1904, 0xCADD042D, 0x757F6ED6, 0xE4A91F06, 0x6D5D0909,
+0xE49559B8, 0xF4B0569B, 0x8454B5B9, 0x2161B5B6, 0x855AADEE, 0x575B0544, 0xBFE4D086, 0xE484CBEB, 0xF9F5426F, 0xCC653366, 0xA3524656, 0x9A5989E4, 0x10451466, 0x71F1655, 0x9B90A4ED, 0x14599FF,
+0x9666AA91, 0x5A99A945, 0x9685CD8F, 0xB8506A91, 0xB427E0F8, 0x50A990FE, 0xA5FA9090, 0x60D4DA80, 0x28E35CB3, 0x55E4AA, 0xD20B55A4, 0xE15F86, 0x36E6995E, 0x54036FFF, 0xA79D2250, 0xBA11A500,
+0x404603AC, 0x641065A0, 0x9DD84A0A, 0x969B061B, 0x36737313, 0x7B65631A, 0xA4E4C099, 0x9590448F, 0xD57F0680, 0x6094D86D, 0x15D8E3BD, 0x757F7DD7, 0xB45B854, 0x6560FA98, 0x7A805637, 0xD68416BB,
+0x7B767131, 0x90F9E8FE, 0xA4E54045, 0xE0411F6E, 0xD57D7DDD, 0x33CB1C33, 0x58ADD010, 0x9B1FA5C6, 0xA401BE95, 0xA950F994, 0xA851971E, 0x33CC33CC, 0x10F0B164, 0x151A6F01, 0x78B5660C, 0x33333225,
+0x41162402, 0x5F0506CB, 0xFD96166F, 0xE4417643, 0x56A51A94, 0x5323BFEA, 0xD12DD12D, 0xA999959A, 0x547C6482, 0x499EE652, 0x4AC7D1E5, 0x2D3DAD07, 0x6B171201, 0xAF065854, 0xD6C4891D, 0xCC739CE7,
+0x9D692663, 0x3E41597C, 0xF38314BB, 0x1150A4F4, 0xE1E50FA, 0xF4D60B6F, 0x5A54E590, 0x227AB5F0, 0x73A3D7FC, 0xD7420A59, 0x12015A59, 0x4F1999D5, 0xA90EE44A, 0x1065B9B5, 0xD10533E3, 0xBA918409,
+0xE5409FEF, 0x4549047F, 0x6B57A6A5, 0xE94691AA, 0x111A6E7E, 0x45496BA, 0x49FD999, 0x414D5B8D, 0xAB10EF5E, 0xE9878505, 0x8C910499, 0xC0C5DA3E, 0x6F1B7298, 0x177D78D0, 0x687B5665, 0x3F470353,
+0x1441A590, 0xE1965F6F, 0x5A5B4A8D, 0x47D7C98, 0xD1404115, 0xB89A053F, 0x8C4095FE, 0x4861E055, 0x3B417607, 0xF9E0E4E0, 0x65B0506, 0x93633236, 0xAA07A5E4, 0x77747080, 0x776160F0, 0x1672B05,
+0xA54E0428, 0x520A9625, 0xE581065, 0x90C76D76, 0x2157B2B3, 0x5C5BE06, 0x151A5A01, 0xA9D5C081, 0xCBCD9854, 0xFDD1061F, 0xB66111B1, 0x9DC3D7B0, 0x650A7642, 0x8095734D, 0xD052011B, 0xE0A1479B,
+0x9501BFF8, 0xE9D9BD0D, 0x7A017925, 0x69A67373, 0x41E0E557, 0x5F844124, 0xEAB0695E, 0x566B5040, 0xCCC9D693, 0xA79684DE, 0x6B5BC3C1, 0x9595667B, 0x9C33CA5C, 0x8984C5C5, 0x459BBDE9, 0x1F10A5F4,
+0x22A55AA, 0x97C3430D, 0xAA569A55, 0x552E1E00, 0xD3C3C78B, 0x82C7521E, 0x5B0605EA, 0x5FF69268, 0xD081460B, 0xE4517F06, 0x4448C9CE, 0x2F69F940, 0x476DA470, 0x9F96FE12, 0x4D8D9E8E, 0x6A6A16B5,
+0x1D05BE66, 0x84F5BD, 0x691E1B41, 0xE0939B17, 0x159059AA, 0x1E5792B9, 0x25A701A5, 0x439162E, 0xE994077C, 0x5CC396AA, 0x1D0D9AA5, 0x4A4A598D, 0x1B6F156B, 0x1A1B0F40, 0x34CB34CB, 0x6F542E,
+0x32CC739C, 0x94EB9669, 0xDA8D4E1D, 0xC6C5C46E, 0x10152B3F, 0x8787F9F9, 0x5E42D064, 0x699B05E9, 0x7030295E, 0x495E09BE, 0xEE191016, 0x801D2D56, 0x3A0099F9, 0xEA09059E, 0x5BAB5100, 0x393D49C,
+0x10E15DC2, 0xB056DD4, 0x3536915, 0xE0C18719, 0xEB964090, 0x6172727, 0xFD5900FA, 0xD10B78D1, 0x33332626, 0x50F990F9, 0x78600A5B, 0xE2B5401B, 0xAE5E9404, 0xF2CF0C0, 0x9E9D8080, 0x84E4F4F9,
+0x41F0E59F, 0x90787E12, 0xE4E19143, 0x761D6706, 0x6560BCE5, 0x134A9BD3, 0x23768995, 0x22ADF6, 0x434A5C72, 0xD4985444, 0x70936BFF, 0xAB54E0E7, 0x45E7A682, 0x7A786D90, 0xF8546A00, 0x5F5E4540,
+0x999A651E, 0xF9E297FD, 0xAF86E5, 0xD00B6E54, 0x5442878A, 0x50E940A5, 0x61F6AF1, 0x479701AA, 0xAE455E5D, 0x6560123E, 0x22D17625, 0x83071B64, 0xF9460251, 0x5F4B064A, 0x8742417C, 0x5F89C51A,
+0x14A29F50, 0x5013BF6B, 0x76395676, 0x54A590F9, 0x40915AA7, 0xEB95E041, 0x7E560504, 0x65B9E4D1, 0x3F63A594, 0x17448216, 0x1A4F87F1, 0xF990E696, 0xECE89A50, 0x2266B17, 0x6A959A98, 0x50F5001A,
+0xBF056A55, 0x74470FFE, 0x65251011, 0x9F7D6597, 0x51BB962, 0xA0D04297, 0xA257F0D1, 0x5B1569D5, 0x4F40959E, 0xEC5D1D0D, 0x51A1A, 0x1DF56462, 0xC4491A6F, 0x4B4A55EF, 0xFD741D5F, 0xE1526713,
+0x875153E2, 0x9752A2E2, 0xEFDA8504, 0xF0E84756, 0xE0A196E9, 0x5FAF5C40, 0x9A3359CC, 0xE056062E, 0xB07B71D7, 0x5966475D, 0x66161100, 0x444A0151, 0xDAC7D6F5, 0xFBE8E314, 0x35098512, 0x1A7F7690,
+0xAF970158, 0x666A6996, 0xD1D10938, 0x742969B, 0x4542A5FE, 0x6EBE50A1, 0x816E7955, 0x64E1D0C1, 0x105156AA, 0x6A9AD0F5, 0xB4909E2E, 0x55A6A959, 0x45B4999F, 0x3266CC26, 0x9B915EE, 0x9769E58B,
+0x2EF59968, 0x3F2F0711, 0x79798469, 0x6161B6B6, 0xA79504B1, 0x9B92A351, 0x61C08573, 0xAB1B656F, 0x37271601, 0xE4840979, 0x45D1C1DA, 0xA4C4961B, 0x59A7F2F0, 0xEA9FC147, 0x635362B0, 0x9561EAF,
+0x6B6762A1, 0x585A43D3, 0x8484819F, 0xD1C30D5D, 0x2123101D, 0xA0F8E4F9, 0x63676220, 0x17EB6A5, 0x90E63F27, 0xDD256045, 0x7B66A1A0, 0x64143F6, 0x41D479D7, 0xF1520F82, 0x12B44687, 0x1504BE1A,
+0x90E45401, 0xC4C98E4F, 0x919097C, 0xA7A52919, 0xB9B62313, 0x9695C089, 0x30C5E6BD, 0xAA55669B, 0xD19F0645, 0x1150E2FF, 0x36213121, 0x1F1F0A05, 0x2A315099, 0x2A1E0414, 0xA3E3D04, 0xD5992851,
+0x19A56A45, 0x5D0669E5, 0xA7C1F8C0, 0x84D1E5AA, 0x7292A464, 0x9040F5E4, 0xF185405, 0x1FAE4509, 0xF91690BE, 0x5540A540, 0xA1D2874B, 0x560B65F8, 0xC207E1E6, 0x646D0F9, 0x5A1440, 0xBB454116,
+0x13597242, 0x413A4504, 0x66E7D2D2, 0x61DA6950, 0x519DF0A0, 0xD2926EB4, 0xA583060B, 0x247E1587, 0xE50590BD, 0xEFF50146, 0x6252B722, 0x4B9AF552, 0x42445A5, 0x5D0844D0, 0xD7C1D18, 0x6B53900,
+0x7DD68434, 0xE6964247, 0xE0A50B5, 0x72635347, 0x669A6B06, 0x91549A65, 0x8F097CA5, 0x849458EC, 0xF9B09275, 0x71390D5A, 0x478BC9D6, 0x5D579AA5, 0x9ED08605, 0xCA1C35D3, 0x1029669, 0x1344FEA7,
+0x5B468B87, 0xA7F29990, 0x60BDB855, 0x3430B574, 0x544461FF, 0xC5C9550E, 0x69E716A7, 0x112336, 0x3F11D2D7, 0x2F0796E4, 0xB5250B00, 0x33CC33DD, 0x20357676, 0x7B6F9272, 0x114B09BB, 0xA7F6C987,
+0x32959833, 0x40D25BB6, 0x13170353, 0xD52E5949, 0x93626538, 0x43449A56, 0x655890BA, 0x2F56811B, 0xE5E4C88, 0xA6079500, 0xA4F90507, 0x6460A055, 0xE990906D, 0x156F56AC, 0x54CF00, 0x181D5A0A,
+0x7C09E947, 0xAD9E898C, 0xFF914212, 0x6933A7CC, 0xB2935B2E, 0x4454D8A2, 0xA6A560B6, 0x519E2075, 0x575FA6A5, 0xB8B06916, 0x598B471B, 0x10686AD1, 0x45EA0170, 0xD0470B9B, 0x3B511E0B, 0x53D79D0,
+0xCBCAC5C5, 0xDAD54CD0, 0x3542EE79, 0xB4AD4FD, 0x642DFF01, 0xB99109B9, 0xE1919B9F, 0x97B84162, 0xE995460A, 0x1060F5F5, 0x166DBCF1, 0x4214957A, 0x6C60626, 0x50FE4F0B, 0xB466470A, 0x808596E2,
+0x70D1440D, 0x818617B6, 0xC8E8DDED, 0x40443474, 0x103E0750, 0x1559A9, 0x16E29FF, 0x54FE0447, 0x34CAB25C, 0x9B30756A, 0xB0E74B05, 0xE19051D, 0x402E7450, 0xF5E0D1AB, 0x87979B5F, 0x8707BA71,
+0x90B4A491, 0x1A2F5301, 0x6C44D318, 0x8AC0A1F4, 0x5A6F0306, 0xE1159090, 0xF9A54183, 0x4CC7321C, 0x7E64868B, 0xFDE60582, 0x4BE77014, 0x1B902D01, 0x104D8FA7, 0x16A7CD, 0x94693912, 0x62E759A,
+0x594BA906, 0x5D023747, 0xDF9757AD, 0x97364CCA, 0xFA011265, 0x12E16116, 0x7A615600, 0x501196F9, 0x5067E247, 0x2A75B070, 0xBC0196BE, 0x19FD8907, 0xCA8511AE, 0x7B671210, 0xB8F0966F, 0x600AE5F4,
+0x4146858E, 0xA579C124, 0x19F26C13, 0x2320776, 0x595BF900, 0xFB059055, 0x6FD6E460, 0x86CAD5D, 0x948153A5, 0xC6C546FF, 0xE199AD5A, 0x656A566A, 0x81256994, 0x7C285400, 0x37CD6A37, 0x4CF4E1B,
+0xD181E0B5, 0x90F89F46, 0x5AD2D072, 0xF1F44D4, 0xB5E091C6, 0xFF90E764, 0x656B9965, 0x833471C7, 0xE6470700, 0x521A517, 0x56620BF, 0x7A6458C9, 0x566959A6, 0x5A5FF3D2, 0xD050063F, 0x9AC17C39,
+0xC1F03D19, 0xE7939343, 0x35312404, 0x76671223, 0xA0D05804, 0x7B773262, 0x5E2E6465, 0xE6860519, 0xDE909B5A, 0xB5C094E4, 0xAF019B15, 0x1A57027F, 0x7874E7D3, 0xB35674A, 0xD0854FB6, 0x916509FD,
+0x431F91FF, 0x9B605420, 0x566978B4, 0xE8D1042D, 0x2533074, 0xEC904443, 0xD404A4D1, 0xB9984945, 0x435181E6, 0xDFD0520A, 0x37FC61D, 0x1540FA94, 0x876DB853, 0x9D686C9D, 0x5D7DE642, 0x556A6669,
+0x6B166F05, 0xF0F06616, 0xE490051F, 0x147B0606, 0xFD76D9D9, 0x3B814E5D, 0x16E6460, 0x91F05406, 0x37444D34, 0x1B17BF00, 0xA8465A05, 0x12429D1C, 0x79753935, 0x639291F4, 0x6761F0F4, 0xBC789460,
+0xF890D79E, 0x54780743, 0x1131367B, 0xD6487C64, 0x8E582E4F, 0x6A972A65, 0x1BA6D0E5, 0x17D6007A, 0x82590727, 0x95D0FA, 0x1540E47E, 0x56B91A0B, 0x8A85C4D4, 0x9F8205E4, 0x80D4C58B, 0x75D3E647,
+0x5956D966, 0x74ED4500, 0x167EA440, 0x255E191, 0x31811515, 0x82999DDF, 0x11670BB8, 0x2BDAD965, 0x5AA5669A, 0x55BF105A, 0x88496E59, 0x5AF56600, 0x4858E751, 0xF4811BB9, 0xB501A7B0, 0x11B26DB,
+0x767C9887, 0x602D7703, 0x1219F8FD, 0x464297D, 0xFF06DB95, 0x156A04BF, 0x5050A39C, 0x35CA4F94, 0x7F00EF1B, 0x68353273, 0x150663B6, 0x79666190, 0xDA650647, 0xA962959A, 0x96E596FF, 0x537E17A3,
+0x57F9E440, 0x101458FF, 0xA4D4E441, 0x1898C4E0, 0x7E189481, 0xB6C71904, 0x9A95EDDD, 0x944449FF, 0x61E4C997, 0x52DF8F5, 0x6A51F46E, 0x9145AD, 0xD9A8DDD2, 0x8784E63D, 0xFF5B906E, 0x2998A559,
+0xCCCC6633, 0xB954C0D0, 0x70B5663B, 0x531C8B25, 0xFFBA0191, 0xF4E35B90, 0x40FF7150, 0x1F075AE5, 0xD0015BFF, 0xDCC3D6DB, 0x4E54A07F, 0x7E9647A, 0xA19D4E1, 0x51504404, 0xE7D68A8A, 0xAF10A450,
+0x71B71184, 0x79940A0E, 0x821B196E, 0x50413A5B, 0x5707962D, 0xD1B63962, 0x819DEDE4, 0xEEC5CB54, 0x251DBAD, 0x50BD6D1D, 0x20976E74, 0xDDC98A4F, 0x451079E9, 0x69146E, 0x68590311, 0x8045A9F4,
+0xEEC58B96, 0x98CCC996, 0x94784451, 0xE6D6015B, 0x3035B95, 0x12E39F6, 0x50EE4058, 0x4D1C74A0, 0xA4291505, 0x936B67D4, 0x2AC1449D, 0xA4015A6D, 0xAFCB4414, 0x74A50038, 0xDED051C8, 0x347B76DA,
+0x817ED01B, 0xDD2D79D2, 0x5A1A011B, 0xA040F556, 0x540246B8, 0xF2B45A06, 0x6A4999B4, 0x4B67D0BF, 0x31614701, 0x456C84C1, 0xB8F4814C, 0xFF009669, 0x4F4A4999, 0x907D95AB, 0xB7A49402, 0x526E61D,
+0x5A9542D3, 0xF8792606, 0xA913569, 0x3193534B, 0x7A61D074, 0x51A452E3, 0x40E490E5, 0x4106377, 0x404A1709, 0x1562727, 0xC0B89996, 0x4440781E, 0x78FA9053, 0x5D1E00E8, 0x1C3C75D0, 0xD581AB05,
+0x85C58A4, 0x44E490E4, 0xCD94CDCA, 0xB252E6D6, 0x1FC345AB, 0x40C5B905, 0x26693851, 0xEC3741D, 0x1B5869B, 0xA161510, 0xE061977B, 0x8A580510, 0xD960D554, 0xB53E091, 0x14B900FA, 0x3E094659,
+0x6090906, 0xE6B47C17, 0xECEC9840, 0xF9A405FA, 0x90F994FA, 0x2B750A5, 0x803B3D25, 0x14AE405F, 0x6F97E0FD, 0xCD34E38C, 0xDED0D4AF, 0x96D1C038, 0x51E78187, 0x93D7CACD, 0xD4D052A7, 0xE6558B4F,
+0xF6025766, 0xE54074B0, 0x6613252C, 0x257A75, 0x1B1266B5, 0xF956E0B6, 0x44D3E3B9, 0xC5C5E9E6, 0xEBD69599, 0x9F91D0F8, 0xB0A05253, 0x6E0F1761, 0x425FE480, 0xA5A051FF, 0xB1384DC7, 0x1CE31CD3,
+0xEBF6701B, 0x6B152998, 0x35A62510, 0xD140E5E6, 0x9070791D, 0x3CA6D1, 0xDAC98985, 0x90917E97, 0x19BCF91, 0xD0C7CBC7, 0xB5466B37, 0xB111D25B, 0x9A29978C, 0x3196C50, 0xCAC5C1FF, 0x4F4A4192,
+0xB14E708B, 0xD5E958D3, 0x73747E24, 0xEDE0D6A2, 0x1B91436E, 0x79252511, 0xCBC58C44, 0x7E64F890, 0x9F05B9F4, 0x1B55E0D0, 0x21D1E969, 0xF4558028, 0xF9E5C3C2, 0x1974325B, 0x6A94E0F0, 0xD101A5BD,
+0x1A17075, 0x5B2D78E1, 0x17194807, 0xF5C24B1D, 0xFA40E655, 0x7A095515, 0xE106F993, 0x565A1103, 0x5A54F6E0, 0xF5E0016E, 0xD6CBC5C1, 0xF940E696, 0xAE316D90, 0x6A146A00, 0x9B96E9E4, 0x6351D86F,
+0x5A466995, 0xD4460B8A, 0x2CC3744E, 0x99666696, 0x20257ABF, 0xA3F2955, 0xD5D0919A, 0x54444859, 0xFC5C606F, 0xA6653749, 0x306E696, 0x2528BD70, 0xA07BCE5, 0xF0A46662, 0xDC649440, 0x99C7874A,
+0x656CBEB, 0x5151A67B, 0x60DB4B05, 0xD1444107, 0x514B74, 0x165025A, 0x5B5A1101, 0x7101179A, 0xD09A070B, 0x50A096BF, 0x47A9521D, 0x4B2D7492, 0x3F0F1B53, 0x1941ABFF, 0x7B666111, 0xD3C345BA,
+0x1CA9D6, 0xE18359B9, 0x1590E6F8, 0xF4285902, 0xBF1B92D0, 0x1BE76D, 0x2A5582C3, 0x8979164B, 0x3C721B40, 0x33C0CF30, 0x2DD21EE1, 0xE9D30707, 0x192DF65, 0x1B92E7C5, 0x33333669, 0x1E0560F4,
+0xFB53034B, 0x966A6699, 0x6F9797A7, 0xEF469BDB, 0x1943F5F6, 0x1DA7C70A, 0x74741E9E, 0xF5709967, 0x520B74F1, 0x4741FBAB, 0xDA6712B9, 0xCBC6C1D0, 0x67E2D64, 0x5E03B625, 0xC088D9D5, 0xF89005FA,
+0x5A2516AA, 0xE5C7D9D6, 0x69FE5096, 0x435BE0D1, 0x7193DB8, 0x9CCC9967, 0x54613301, 0x461211BC, 0x730C6FAB, 0x6050A5B1, 0x7EB91141, 0x6A152F00, 0x69665AE5, 0xAE5780F8, 0x7D06F90, 0x2032D510,
+0x4E0746D1, 0xA69C33CC, 0x1A462616, 0x36C6C6C6, 0xFFA59D1F, 0x9B6D74F1, 0x1197907E, 0x656A9995, 0x91742E48, 0xD00538F5, 0x441542, 0x40D2469B, 0xFF5999, 0x15A9966A, 0x94841EF9, 0xA5651D1F,
+0xCC9C6633, 0x2F7D107E, 0x9B81411F, 0x9E59A669, 0x5E970007, 0x7E2E1F03, 0x29B5F244, 0x86C5D48, 0x548581B4, 0xF955CF44, 0xE35CB2CD, 0xA956B6D7, 0xE0E69125, 0x1969C59D, 0x550099EF, 0x68D99F24,
+0x5FA65010, 0x2B1256FD, 0xF8244147, 0x1D56470C, 0x2162A76, 0x62F16510, 0xAA556995, 0x540669, 0x14C29726, 0x4790FC0, 0x2CC19B44, 0x6CD7759D, 0xD7F64140, 0x425F81E4, 0x5034348D, 0x65095966,
+0x7261B0F5, 0xAF5681D1, 0x935A4051, 0x5262767B, 0x595EC2E8, 0xDB743847, 0x3C60A513, 0xC21F3991, 0xCB34C738, 0xD19AE995, 0xB9171781, 0x1107AB66, 0x5FC0D790, 0x2070F1F6, 0x6E5E1A09, 0xB5407E5E,
+0x505494EA, 0xE4703556, 0xF890999E, 0xA65BF595, 0x2919A7F, 0x49DD3880, 0x94EF960A, 0x183D1906, 0x1500F9F9, 0x9DEE4509, 0xF5FA6313, 0xE0526850, 0xBFE60005, 0xF16E685, 0xF90065A5, 0x916AF859,
+0xFF608454, 0xE6BF5094, 0x81D1E0FA, 0xA19FF91, 0x60D59CD9, 0x39524274, 0xD7994F4, 0x36295C8D, 0xE0503945, 0x2D85C545, 0xD1500658, 0x22172635, 0x338C5626, 0xDE812506, 0xDB57E8D0, 0xE9D955F6,
+0x9F6C94E6, 0x9636CC33, 0x2A1A3542, 0xF95D80F5, 0xD4266F42, 0x1C9E5F9, 0x74A1C30E, 0x6B16A050, 0xFB03506A, 0x4218B469, 0x94D1422D, 0x427D3531, 0xC25BAD40, 0x6692B292, 0x5A50E9A5, 0x717CD4C3,
+0x71938F59, 0x5147400A, 0x41BC6EB5, 0xD4A0D4E4, 0x1D0E5FA, 0xF6869F06, 0xA7E35252, 0xF4D1421B, 0xA4894DE7, 0x2D946B1A, 0xD0FFC684, 0x17C291E4, 0x7F525000, 0x15848139, 0x669669A5, 0xA7A76353,
+0xA996966A, 0x2FE155C0, 0x1E1E42D6, 0x4CB19976, 0x1103BE69, 0x57699082, 0x71624AF, 0xE1445A09, 0x969A4504, 0x5602955E, 0x5A1548E4, 0x5B074314, 0x74A6CE66, 0x9038152E, 0xD8C4554F, 0x3EBB0657,
+0xA8A65669, 0xB9B56010, 0x96B92D86, 0xE9D9CCA4, 0x33DE69A7, 0x5C8CD8E4, 0xF5D1401A, 0x4B59A46B, 0xCD258D07, 0xF3C3A475, 0x105DFC2E, 0xF7929140, 0xA4A450FE, 0x5B4598, 0x17137B75, 0x1B05F082,
+0xD62474D1, 0x673AB500, 0xA9460B5E, 0x47025AD1, 0x6E6695D9, 0x1262B6F6, 0x6AE65190, 0x66A69499, 0xD0993A76, 0x22321727, 0x55C0C56F, 0x6F7D1E43, 0x352F53E, 0x6AD6662F, 0x62713623, 0x948484F9,
+0x27161E04, 0xE996065B, 0xFED0411E, 0x8BC59A4B, 0x689E4B01, 0x40467E7E, 0x550E0F8, 0x1832D78D, 0x6CEC9580, 0x6A9E8F6E, 0x5340D4B1, 0x1449C6D, 0x22163530, 0xB4F6C3C6, 0xAD01DA95, 0x656F051E,
+0x8151167B, 0xA0C3966B, 0x40F85B15, 0xDD4B8D2A, 0x24BB667, 0x52E193F, 0x56A7019B, 0x12625504, 0x11A16297, 0x4B59066C, 0x59E990A0, 0xA45C0B00, 0x92C34B3F, 0xD06F6325, 0xC68D18B9, 0x74783C30,
+0xEA58C5CD, 0x142151F7, 0xDA649E04, 0xDA950602, 0x6E641510, 0xA7249144, 0xF46A1FF, 0xA950F611, 0x752E1FC, 0x7A460551, 0xB8E0D6D1, 0xE9D09151, 0xC745A104, 0x2072E687, 0x9F870105, 0x65A0F1FB,
+0xD0D500F9, 0x1A901FE1, 0x6F4E9401, 0x33322558, 0x52532732, 0xDB16B782, 0xBAA56046, 0xBCA19396, 0x411B39B7, 0xDC847184, 0x31C8B364, 0x6A66906E, 0x3F85D8F0, 0x36EB4393, 0xD518985, 0x34392F47,
+0x1FCF4E96, 0xF4A05E06, 0xBD5B102C, 0xFF056A65, 0x561BB601, 0xACC50A51, 0xA3733235, 0x7E1B53E2, 0x5251A0E5, 0xE078156F, 0x1F56E790, 0xA9965D59, 0xE0949C7D, 0xD87D560A, 0xD0649CED, 0x1065A47E,
+0x257CE4C3, 0xE2409597, 0x71D49220, 0x253929F, 0x47673ECA, 0x716B51F3, 0x4C1C48C5, 0xC7C1520B, 0x7B593060, 0x4F88491E, 0xA566A956, 0x7767A34, 0x65149A00, 0xB6D75A5F, 0x96A757A6, 0xA050617B,
+0xB007D141, 0x12A377B0, 0xC4E8D5F5, 0xE0C74B95, 0xC13C06F9, 0x7996213D, 0x9AC68F45, 0x65460B95, 0x99A7C292, 0x889C9C6C, 0xA4EDD440, 0xB0693DF, 0xFF50E490, 0x507A977, 0xE4147ED0, 0x80F19505,
+0xFCC5066E, 0x74B64319, 0x103A1EC6, 0xB288507E, 0x56A779A0, 0x7C9056AA, 0x381294FD, 0x5D194EC1, 0xF0C19B1F, 0xD60A1DE1, 0x94C0C4DF, 0x7E66824B, 0x69670667, 0x461520C7, 0x7466071F, 0x96FD1A00,
+0x10C4EA65, 0x93DE045, 0x6F01E2E5, 0xB196946, 0x504246AD, 0xB45E0F4, 0xABF1194, 0x84C94D5A, 0x111D27E, 0xF6951BBD, 0xE081166B, 0x56699965, 0xA1F16C54, 0x46107A64, 0x821C3491, 0x88D86E5B,
+0xE5D2C7CB, 0x5203432F, 0xE616332B, 0xF9854938, 0xD2736742, 0x671061F7, 0x9248BDB8, 0x544106E2, 0x6134280D, 0xC65E091D, 0x5599E860, 0xECC245B4, 0xFE4564E0, 0xD500F4F4, 0x59FDC0ED, 0x44530376,
+0xB152767E, 0x6A074351, 0xC565DE, 0xAD995844, 0x57F1D099, 0xB252D484, 0xD1984D8E, 0x5196A66, 0x2C59E167, 0xC0E9055F, 0xFD196F06, 0xF5F0C1C7, 0xFAD05152, 0x2126E0F5, 0xE9F42911, 0xC8339895,
+0x8D405BD, 0x50E94377, 0x443AF945, 0x5011293C, 0x76A297AD, 0x1EE440C5, 0x35DAD9A0, 0xA4419590, 0x165BA619, 0xF60B9A65, 0x1F89444A, 0x71B0255, 0x476DF0A6, 0x61D4A1A, 0x469F9DB0, 0x32355C8C,
+0x86091D46, 0xE795060B, 0x2296305C, 0x6E41F80, 0xF490E594, 0xF4E25699, 0xBF65AC50, 0x4A7E75DB, 0x1015F458, 0xB04ACD9E, 0xEE5478F4, 0x7F630C53, 0x4E49F5F0, 0xCDA3319C, 0xBE116D20, 0x4589D9E9,
+0x7435434B, 0xFDD96656, 0x5F681E4, 0x99AD1C50, 0x552A5401, 0x68F04549, 0x73B66D2, 0x1F86D101, 0xD041160B, 0xF906FFA5, 0x689676DE, 0x5F4780BD, 0xF0939AA5, 0x1F0B5F40, 0x501B3F, 0xA8C193B5,
+0x8C73CC33, 0xE24F7CD3, 0x9090A565, 0xA990D59A, 0xA1C14877, 0x946D8180, 0xF8343124, 0x14C1E915, 0x4919CBA5, 0xFF55D001, 0xF4E152A2, 0x46687EF0, 0xF05ABD48, 0xB7B37460, 0x1474C58, 0x94E490E8,
+0xB9E44183, 0x78D32DE1, 0xC8E4489F, 0x5BDAA45B, 0xB5610147, 0x5162A5F9, 0x5D6191C8, 0x4595C0A6, 0xA57DC996, 0x6D9D0D1E, 0xF58BC767, 0x1A0E5509, 0x409BD2D7, 0xFF5C135, 0x33B7579, 0xEF035600,
+0x779152B, 0x50B091B7, 0x363A3162, 0x491069DB, 0x9C4E0C5F, 0x945A1B12, 0x5490FF00, 0xB5A0B400, 0x1F82D64A, 0xB2C7426, 0x329CDA73, 0xA9995AA5, 0xF65876B4, 0x1E4E890E, 0x857AB576, 0xA52E054,
+0x1D11D88C, 0xA35895B0, 0x6F196890, 0xC7143E70, 0x6BE401FE, 0x111BA961, 0x66070AF5, 0x5F07130F, 0xA15061B6, 0x8C73CD32, 0x6C6481D6, 0x6AD5A6C1, 0x14A5872C, 0x46B90BE4, 0xE5586946, 0x3163C58C,
+0x1431B550, 0x91E94F09, 0x66F5C24B, 0xEE40461E, 0x97593992, 0x19E059F4, 0x94F92E05, 0x8CC445EA, 0x403D64A7, 0xB0FE5D8, 0x9C9B5C00, 0x7EDED9A4, 0x7CD393B5, 0xF1A50DA, 0x372B4077, 0xBF9046E7,
+0x56261E6D, 0x51232570, 0x40153CAB, 0x9B6F6712, 0x51C0160A, 0xB990052F, 0x3788B955, 0x555064A0, 0x6F0B5B05, 0x9776666B, 0xAA069B45, 0xAFF81440, 0x91E4DE1A, 0x80D5C9C6, 0x1E9E5DA4, 0x2B65B450,
+0x1213362B, 0xD766654A, 0x461346C, 0x197B2441, 0x5F9547EB, 0x15AF0506, 0x464C8D9D, 0x4021957A, 0xFE54E413, 0x13295035, 0x145E0D2, 0x4D4854E9, 0xBE50919B, 0xA76CF940, 0x91E1406E, 0x9A655A9A,
+0x3E65005A, 0x1C0B6666, 0x2611AC57, 0xBE7D1442, 0x311E3FC, 0xA4858185, 0x6E54D2A1, 0x9140A5DE, 0x844EC85, 0xF4A81540, 0x1159BF9, 0x2896D07D, 0xD5E690EA, 0x40A47D47, 0x6F672C16, 0xF1611217,
+0xE4096F65, 0x621D05EF, 0x9040979F, 0xC1C5CA46, 0x5B9606B5, 0x5101767A, 0x448C9568, 0xE4983D12, 0xCBC8B5E9, 0x1B15E402, 0xE1C60E15, 0x44E68419, 0x90D48DC, 0x7A9042BB, 0x151285D, 0x676B2613,
+0x121644B4, 0x920F52E3, 0x56DE09E, 0x6E6607A4, 0x5E560B0E, 0xC20B7616, 0xAF464146, 0x8C5C2835, 0x474BC2C6, 0xBC6419CA, 0x5C4353F0, 0x31392547, 0x504295AA, 0xCC593363, 0x1C0C6DBA, 0x4D71B7F,
+0xCC593633, 0xE71A250B, 0xE8CC599D, 0x894FA695, 0x4EC3513E, 0x39C0C645, 0x7B526034, 0xF91E2E06, 0x1A663699, 0x202599EF, 0xC1D1E195, 0x75E600FF, 0xD0D1ECDC, 0xD6DB6050, 0xE0E5016F, 0xF0910B15,
+0xD68C6917, 0x6F1A3D00, 0xF5D61BA6, 0x336D1CA5, 0x7888941D, 0x78D0912D, 0xE1D1C34C, 0x592E4C41, 0x1539F804, 0xFB019650, 0xD5E50609, 0xE8C553F9, 0x411BEBD, 0xE580D1DA, 0x1CACD693, 0xAF15BCE1,
+0x1104909C, 0x4B3B4686, 0xB3A31251, 0x50F5665, 0x1D4EC1D3, 0x2830D712, 0x401F0475, 0xC089D4DD, 0xB2425701, 0x40076F65, 0xA950F5A4, 0x9F9990BF, 0x70214431, 0x22753C31, 0xCC7369D9, 0xE9919061,
+0xF45A1F1, 0xBD0690D0, 0x79A6C180, 0x2FDD105A, 0x584296CA, 0x116F906E, 0x58484C5C, 0xDF9B10E6, 0x5184486D, 0xE9D89D90, 0x69B05ED2, 0xD9841D2B, 0xC2C6C5E6, 0xF88947CD, 0x90696469, 0xC5C0C6DF,
+0x677B0640, 0x4B479BC5, 0x83D1B811, 0x5B47E440, 0x1A419DEA, 0x3DD8D4A9, 0x8752B0F3, 0xD1D18189, 0xCCA632CC, 0x725CCB73, 0x6325CC33, 0x14464A25, 0x5410303F, 0xF8C12F85, 0x39D205E5, 0xFE850549,
+0xC68710B5, 0x471F7842, 0xD34A4C6C, 0x4742D188, 0xBFD50A44, 0x1987777C, 0x5B61C12, 0xB2530677, 0xD995A916, 0x75B496A0, 0x31E61E7, 0x53939DED, 0x51705B00, 0xBA5A4046, 0xFF14A4, 0x2599DCF8,
+0x7D47F02E, 0x9B959064, 0xDCD4E014, 0x38C22DD1, 0x65647C88, 0xD4606066, 0x3551E0D2, 0xD06157FE, 0x1131260B, 0x8B81E454, 0x1E1865FF, 0x1966A524, 0x4B4684D8, 0x3450F1B6, 0xE4FE41D1, 0x1D31F1E6,
+0xC47C1F4A, 0x94656AB, 0x45D101B, 0xB681B712, 0x9BD09215, 0x77924154, 0xFCECD4A0, 0xF0F1C72D, 0x74D0834F, 0xE4908117, 0x65E0365C, 0x955A09EF, 0x6E744349, 0xF4692B13, 0x34750F6E, 0x94D198A9,
+0x839C2DB2, 0xED929580, 0xEA609E65, 0x1A15F8D1, 0xFE00D6AD, 0xD5DC0141, 0xD90D3995, 0x6E6640ED, 0xA9B443CF, 0xE50681D9, 0x3F705659, 0x5F5E4844, 0x9A254A5B, 0x26618195, 0x8B945DAD, 0xDFD4E490,
+0x674352C0, 0x9967C1C0, 0x5990E995, 0xDEC544BA, 0xA7DA444, 0x16457E8, 0x142DFE04, 0xA4D5C084, 0x13172539, 0x84FC3590, 0xA9734748, 0xFE07F451, 0x42119AED, 0x8F087916, 0x13A65D1, 0x82856E75,
+0x3511B1B9, 0xA61BD018, 0x8619B893, 0x40BD89E5, 0x9A15F640, 0x4052464F, 0x9D87C1E0, 0x972C58F0, 0x84D8ED54, 0xE64D9C5D, 0xF421502F, 0xF24864, 0x59B8A154, 0x9A2596DF, 0x1441E6FA, 0x1BE46F90,
+0xA8915051, 0xA5B62611, 0xF582841D, 0x825362B7, 0x55F367E, 0x415263BD, 0x3E463930, 0x68754A06, 0x1117F280, 0x8B16B855, 0xEC75E1C4, 0xA0771117, 0x669DB850, 0x6D171238, 0x47167213, 0x90B21746,
+0xD92649C8, 0xCAC6C6F1, 0xE392C769, 0x60E7939B, 0x14130475, 0x56001A7D, 0xF657028F, 0x6F6819E, 0x29974C33, 0x49A57C5C, 0xD590E890, 0x6FF1116, 0x132B7665, 0xA0C60B56, 0x9844DF41, 0xA1B103E,
+0x44845EEF, 0xA6D2F5D5, 0x55FA4600, 0xBF611264, 0x6AD53610, 0xED594A11, 0xCFC15015, 0x96264247, 0xA4F1D3DA, 0x257EC166, 0xB8D6C114, 0xEA90CF4F, 0x6D5A804, 0x3F0695E8, 0x9C90BCE9, 0xAB4701D1,
+0x136357B5, 0x994D9E0E, 0x121652B2, 0x6D9FD261, 0x5CCC9733, 0x873B95E5, 0x905E9C80, 0xA051BA6F, 0x5F478589, 0x197AD19A, 0x50015DE9, 0x5BAE412F, 0x4111162B, 0x738F386, 0xE4835BAE, 0x5B55A2D0,
+0x5E4B038, 0xF9F91014, 0x8FCBD1E1, 0xD98B4743, 0xB9955DAF, 0xC5373DCD, 0xBD1C8114, 0x250532F1, 0x24504E0E, 0x62D7C50, 0xE8D44154, 0xA8944044, 0x9D669995, 0x530C6FFA, 0x65167BA7, 0xE641BE,
+0x811AB5D2, 0xD18A9D09, 0x6F064045, 0xBF902991, 0xC54F07FF, 0xF6962B11, 0xA4819FDB, 0x60F46A54, 0xE451815B, 0x7C197B, 0x9D44DA0C, 0x869640FF, 0x18C44D18, 0x40247F66, 0x5221F711, 0x510196FF,
+0x353261EF, 0x44490E0E, 0xF994E956, 0x926C45BF, 0x7D96855F, 0x84D4C98A, 0xE06BF456, 0xC21B1641, 0x4B5CB493, 0xDA90D366, 0xE8964D44, 0x197C75DA, 0xD6D46333, 0x465E78A1, 0x1942461E, 0xC1356656,
+0x58D631CC, 0xD773384C, 0x4A9940E5, 0xA0F97414, 0x53532327, 0x78107AB5, 0x3C091BA5, 0xA6469144, 0x44E45841, 0xC50D5842, 0x4A199678, 0x46365DF8, 0x5463E87, 0x8D2C1151, 0xFF5895, 0x2FD231C8,
+0x6C9CD2B3, 0xD74243B2, 0xC4409CDE, 0xB8E0411F, 0x26670F05, 0x5B6697A9, 0x55464A2B, 0x2E0F569A, 0x4660E25B, 0xFE500715, 0x9C683532, 0xCB0C5949, 0x806C6592, 0x679B0156, 0xFE005F15, 0xA540FE50,
+0x1F281510, 0x906D4F00, 0x57052C80, 0xA95BC0B5, 0x6C98C5CB, 0x44581E4E, 0xAD9D4846, 0x8352C7DB, 0xB21E50D9, 0xEB4607B7, 0x99AC9C77, 0x1509D9FC, 0x5460133E, 0x4244EE5A, 0xEF5A259A, 0x3439461B,
+0x6B940B05, 0x59E94484, 0x5062B45E, 0x859B9363, 0xFDE48194, 0x325362D2, 0xE460FB46, 0xD78B98E7, 0x64A3D346, 0xE5B06277, 0x9F655A41, 0x676B5302, 0xEA950B7D, 0xFD158A, 0x775362B4, 0x75C21938,
+0x861EB9D2, 0x589532CC, 0x1025190B, 0xD46B06FF, 0xB50E7C44, 0xCDD7A372, 0xB5B96100, 0xF2B491A1, 0x5E9960F4, 0xF1CC582E, 0x89C99575, 0x7AA1475F, 0x7B66C124, 0xD0D681EF, 0x44156E08, 0x8F1F1056,
+0x6E67D240, 0x9A4C4951, 0xD451E4A7, 0xEA941B13, 0x7E470070, 0x85422E7F, 0x5B9690FE, 0xDE06E626, 0xC8854A15, 0x5A05ED4D, 0x80F46E1B, 0x9011F302, 0x4493D2D8, 0xE50D9D68, 0xFB764400, 0x64D1816F,
+0x9965A616, 0xBF011811, 0x155B0252, 0x3D9DA411, 0x58D96D90, 0x5FAC14F, 0x34E09F47, 0x7470303D, 0x35316E5B, 0x84782D19, 0x6074B114, 0xDF85124F, 0x5B47B723, 0x91327673, 0x31A3C548, 0x6D04F9,
+0x65DA62CC, 0x779B6270, 0x9037699, 0xD59A061B, 0xD140F5D0, 0x546F04E5, 0x197A6193, 0x150F46FA, 0xE0592151, 0x54A9D0DB, 0xAA55D851, 0x50616F64, 0x35307994, 0x1198C72F, 0x472E79D1, 0xFF01981,
+0xF6195AFF, 0x58E66219, 0x69D3D67C, 0x3395C832, 0x5DA31DFF, 0xD66E7583, 0x802979D7, 0x1C419805, 0xA596916A, 0x6A464414, 0x64702547, 0xD31AB704, 0x91E6C21B, 0x41AF55, 0xC600DF64, 0x2D162960,
+0xD0D9AC64, 0x921C6378, 0xD0051C18, 0xCC26969C, 0x3C856899, 0x56A9D3A3, 0xC8CCD966, 0xB42552E2, 0xFF055B5B, 0x4AC7E641, 0xE747D0DD, 0x45A5F75D, 0xFD960205, 0xA60391FD, 0x5EAD8484, 0x13D0E563,
+0x11011BBF, 0xF4A4414, 0xCB5D0939, 0x1D6DE804, 0x2D6DF850, 0xB7E11431, 0x8B253410, 0x24D7A918, 0xA6591F6A, 0xFA0545, 0x10D3421A, 0x4E4CE453, 0x99C48C3D, 0x71D1C0F, 0xB4B94045, 0xE0815D05,
+0x9D854214, 0xF5F06136, 0x1A58FD15, 0x4742A650, 0x7E66464A, 0xCAC5D1F2, 0x99A91441, 0xB06115FB, 0xC0F43522, 0x9CE9CDC8, 0x59EA404E, 0x5B42A707, 0x16914BD, 0x872DF087, 0x4114AE9E, 0x3B1284FE,
+0x5E5E5808, 0x4680D66C, 0x364246C2, 0x65C2462E, 0x421C78A1, 0x1EB8D5EA, 0x28F24C55, 0x5021670B, 0x90BD7875, 0x71385CCA, 0xE7F07411, 0x1F11A366, 0x5FDFB852, 0x4C4DE05A, 0x9E0D9AD6, 0xE0953C84,
+0xE5CC0641, 0xE01BF406, 0x51E4072A, 0x4D66B8B5, 0x272DAD04, 0xF2C3986D, 0x6D680158, 0x464B0755, 0x550047FB, 0x74B41D1, 0xAF58676C, 0x7A655241, 0x64B9505B, 0x4D1D4D8D, 0xFFA5909B, 0x2F0754C1,
+0x4052256D, 0xB9D68609, 0x66615EB, 0x8A3D64D1, 0x2392D1E5, 0xF0A15ABD, 0xF7375B01, 0x699291A1, 0x607D0154, 0x6F19CDC6, 0x869DAC51, 0x11164726, 0xB0B50B1A, 0x9550E320, 0x257FF450, 0x3264669A,
+0xDF5D405B, 0x819855E7, 0x6B97C0A4, 0x88394945, 0xBCF14411, 0x6ED499, 0x570193E3, 0xFA346401, 0xF479095, 0xE6E6850B, 0xB2F1615, 0x95E2160, 0x144D8A3D, 0x3932D186, 0x5B64F801, 0x1F0746E7,
+0x1443EF98, 0xE8444E49, 0x4740EB50, 0xB9035B58, 0xD3D21B3E, 0xB8767699, 0x67D78366, 0xBD1187CB, 0x6C5C0C1C, 0x906D3E13, 0x9E1E6C49, 0x400598ED, 0x529106FD, 0xB4C10D2D, 0x740DC334, 0xE99458A0,
+0x94C8D572, 0xD7D18228, 0x13E566E, 0x1BC3D629, 0x63136172, 0x51A1B10, 0xF305F4E0, 0x679F6813, 0xD38356EA, 0xD669C856, 0xC5CE5A4, 0xC738CB74, 0x567DB480, 0xA65F9440, 0xE207176B, 0x9D5E4A88,
+0x1EFD6440, 0x1095738A, 0xF005646E, 0x19E1870, 0xEC481545, 0x2E598105, 0x55F7439F, 0xDBDB41A1, 0xE64F995, 0x6A9164A9, 0xA5191E04, 0xF4D1413C, 0x646EA056, 0xE3911263, 0x20117A65, 0xF9059304,
+0x48366754, 0x12166B67, 0x868A677, 0x46DB80C0, 0x1878D69A, 0x60D26DC1, 0x405EE804, 0x84D990BF, 0xDAD54606, 0xD93365CC, 0x93B2971B, 0x31269151, 0x5F0E58C2, 0x19B96390, 0xA1AD444, 0x90286D94,
+0xB1D10B7E, 0x40FAA451, 0x8276815E, 0x8669F400, 0xB5A61B12, 0x65FC9B8, 0x446AA55, 0xA11D8378, 0xAD9F4468, 0x21266E1E, 0x868544FC, 0x67520318, 0x858DD0EB, 0x86D4906F, 0x51D3A9A6, 0x9767857E,
+0xD6C99C68, 0x33CC2667, 0x660795F4, 0xD1F10155, 0x86D90D16, 0xE66A1603, 0xF5F86440, 0xE98E4504, 0x17424B9A, 0xB0839F59, 0xE70438F0, 0x432A7560, 0x92D89FC5, 0x37C42399, 0x11617570, 0x249605BE,
+0x101BE265, 0xEE905053, 0x4540DA59, 0x9729A4FF, 0xEE850607, 0x9FD15248, 0x50E5B323, 0x7579F946, 0x498459AF, 0x919C2C1E, 0x6AD78374, 0xB1647421, 0x9EE0B603, 0xA6D35E9, 0x96696C9E, 0x587A5003,
+0x49454A9, 0x6D6D9393, 0xC98677E9, 0x4095C2EF, 0x9C608505, 0x15940C2C, 0x5B60D2DB, 0x1C8151A9, 0x60F491D2, 0x2B670453, 0x4F1964BA, 0xB4430B51, 0xA9860454, 0xB0E41E46, 0x1406B7E3, 0x562701E4,
+0x20D1F6A1, 0x5352A966, 0x64E1D62F, 0x92C6ED07, 0xF882561B, 0x99195A04, 0xC934E3AC, 0xD9B91810, 0x474B04F4, 0x3D9A66, 0xCA9C10AF, 0xE1942916, 0xA125355, 0x32295C8C, 0x675A64E1, 0x9D906494,
+0x6C60EB1F, 0x7874C1BC, 0x1CB53038, 0x56D0F9D1, 0xB1EB954, 0x7C781540, 0x5323619E, 0x6FE055A9, 0xE7440D22, 0x7431A347, 0x6F1BE146, 0x1015BF00, 0x62381905, 0x7025B440, 0x176AF050, 0x5D270EF1,
+0x46AF4C18, 0x4B86D9ED, 0x8B177010, 0xFAD09606, 0xBFA15E50, 0x4701D72D, 0xA298A55E, 0x865CA950, 0x9B5B1227, 0xE0B9175, 0xF481F1FC, 0x7E5D0440, 0x1A697FE5, 0xDE84C5F0, 0xF9975303, 0x4CB46C54,
+0x3ED0D666, 0xE6B07065, 0xF0661263, 0x117C93A0, 0xD56DB4E1, 0x2E5E0E5D, 0x873DE11F, 0x5512413E, 0x5E9CE404, 0xB4C10B7F, 0xF990E956, 0x84C95E95, 0xB5E04B1F, 0x86815BA5, 0x7A5CB26C, 0x42F41F91,
+0xF4592E03, 0xF51F1300, 0x99D7810F, 0xB16051A7, 0x5B57B03E, 0xEE590B55, 0xC014FDD6, 0xF9C04505, 0x1A669669, 0x984C5F84, 0x1A6FD2E3, 0x1A075E5, 0xD80E450C, 0xD66942B6, 0xD050E31F, 0xBA605440,
+0x50E7856A, 0x406E53EF, 0xF01191B, 0xBF055243, 0x9B25E9E7, 0xF892A157, 0x2D598957, 0x85896B6, 0xEF44584B, 0x170667FB, 0xD1017F38, 0xCEC58687, 0x443C6C99, 0xB5B83D3, 0xFD05D91B, 0xA6D72DD3,
+0x6C98D9D0, 0xD66990E0, 0xDE850B0F, 0xE9964609, 0x8605B94B, 0x6DC0D196, 0xB194A5, 0x6F13424D, 0x9ED13215, 0x7064249F, 0x5751E0B0, 0x166F26D6, 0x559EC2F8, 0xE12C5C71, 0x59898D15, 0xBC015A05,
+0x90D18B0F, 0xB0E8649C, 0x170B98D0, 0x8181F491, 0xD990498C, 0x76312925, 0x93B53402, 0xCC1C4B54, 0x2F3F5006, 0x56EC4F10, 0x1AE501E4, 0x6F4D40DB, 0xA3525D69, 0x1329E491, 0x400AF995, 0x2D5C4806,
+0xB091667D, 0xCC6C1627, 0x425CD9EC, 0xF552931A, 0xA6D46580, 0xF4AE50E0, 0x1979909A, 0xF1750058, 0x3365CCD9, 0xBA166500, 0x86779739, 0x67F2611, 0x55109A0B, 0x51016A65, 0x1160BBF, 0x5A6C1401,
+0xC4DC9984, 0x33534244, 0x4057113A, 0xF1F431C1, 0xF8A44BE5, 0x1A976851, 0xB9B5C28F, 0xFE099454, 0xB065B8B5, 0xC0217707, 0xF3831BD1, 0x9757401B, 0x1D293580, 0x7A951200, 0x20615AF5, 0x6272757,
+0xE0FC2907, 0xD860B5C1, 0x985F89C, 0xC25C2C5F, 0x7F941C01, 0xA95A450A, 0x44D89A95, 0xCE1C0C58, 0x194184F9, 0x579BB371, 0x90111F40, 0x5F037075, 0xBB516996, 0x4EC9791, 0xCCEC9C44, 0x5D8404F8,
+0x48FE9D1, 0x4792E3E2, 0x6F35E381, 0x5F0350FB, 0xFF6C56, 0x6050A5F7, 0x589625C9, 0x8F79061D, 0x11D0421F, 0x9061F184, 0x504662BE, 0x8FC7D190, 0xB4404627, 0xEA1F1B03, 0xAF59D0EA, 0x79E50E04,
+0xCF80445D, 0x4191D38B, 0x8F51328, 0x6653E282, 0x8C5C3573, 0x90E05929, 0xC5910D2B, 0xAE479D46, 0x2F7C1610, 0x24B1637E, 0xCB001F55, 0x118384B5, 0xA3421710, 0xAA0725F4, 0xE9C0959A, 0xE5E74114,
+0x4A44CB25, 0x1763BD90, 0x1B095404, 0xCF09D095, 0x5B8344AC, 0xC5C0F9D1, 0xA7615441, 0xE990474B, 0x63536723, 0x1E305BA6, 0xE56B066B, 0xCA817916, 0x9F798578, 0xD7692E06, 0x56F01481, 0x37215100,
+0x17111401, 0xF890F955, 0xA68D68D6, 0xD64A06F0, 0x9F65D9D2, 0xBE90095F, 0x9967072F, 0xE01C947B, 0x12235709, 0x589DFD, 0xBB154A41, 0x2D5DC01F, 0xC58B5C08, 0xCB64DC4C, 0x9F9393AC, 0x7303467E,
+0x599EC984, 0x46E111FC, 0x7A679404, 0xA90647FB, 0x40EE949A, 0x77076E08, 0x10736423, 0x53D90AB, 0x1F510BB, 0x85CC253A, 0xAA905666, 0x45EC0B4, 0x835121F1, 0x2E5A4247, 0x1D8664A0, 0x51442CE0,
+0xDD88451E, 0xE85C0113, 0xFA409601, 0xA4211627, 0x459F50BA, 0x984C458A, 0xE65A60D7, 0x958143B2, 0xD3835BFA, 0xF727F110, 0x4F074354, 0x11113D3D, 0x1558312B, 0xFF08E6D6, 0x89BC5910, 0x99F99287,
+0x40D4183F, 0xDA66A550, 0xA45CE279, 0x7F97A251, 0xB1B025F, 0x70772265, 0xF0E21E16, 0xE79959B5, 0x496669C6, 0xECD00716, 0x5619ECE1, 0x6E5C11F, 0x1101FFF8, 0x55A01DCB, 0xA5053970, 0x3D448855,
+0x9F92E540, 0x35B8A4D0, 0x84119CA7, 0x5429406F, 0x90E05B56, 0x3752E1D8, 0xE1B42D87, 0x9454B0F1, 0xDD382505, 0x1904ED6F, 0xD94D0C58, 0x7C52031F, 0x14B06706, 0x79928799, 0x40149BC7, 0xE9DCD6D0,
+0x104F4D1, 0xD9663448, 0xBD85D003, 0x358CCDA3, 0x66F5412B, 0x6E65066A, 0x6E19B161, 0x55D1AA50, 0x785C9D30, 0x162530BE, 0x7AE64548, 0xA51B9B0E, 0xF9A56400, 0x32CE35DB, 0x17285370, 0xB0117B76,
+0x7CE04741, 0x9D0C51A4, 0xBF004D55, 0xAAD5AC11, 0x6599CB41, 0xFBD09444, 0x936291E5, 0x2D5EA056, 0x1129656A, 0x7FC09506, 0xD44149C8, 0xBA750352, 0xD2431943, 0x7967E182, 0xB813C497, 0x24219465,
+0xC43C9169, 0x6FD81483, 0x6152E3C, 0x59947B6, 0x27F90D12, 0x54046D2A, 0xD521309B, 0xE6653921, 0x9164F4F1, 0x1521FB4A, 0x61C54C38, 0x416484BF, 0x2776B11F, 0x59A9D884, 0xED806B54, 0x1BB0D59B,
+0x4E8D91A1, 0x782FD131, 0xC05A0377, 0x7A121126, 0xDFC5D0E0, 0xEF859E05, 0x7BB60515, 0x5DD26D89, 0x2E291157, 0x9F2F3530, 0xC08156A9, 0x6D91CDC5, 0xF1548117, 0xB52517FE, 0x2053E947, 0xAB5785C5,
+0x479A91E0, 0x9F90FE01, 0x312484DE, 0x441BC1A5, 0x66B501F5, 0xC4617A5B, 0x916BB0F4, 0x20657C7A, 0xE25390FF, 0x1F3861B4, 0x550586AF, 0x6B8599D4, 0x9F4294EC, 0xF4D48147, 0xD0965233, 0x1E05CFED,
+0x59176903, 0x2D2976C, 0xCD33338C, 0x1441E4AD, 0x4196C088, 0xF6079403, 0x969DC030, 0x64990D29, 0x2453F372, 0x8658909B, 0x458046FB, 0x11A185C4, 0x58FC1144, 0x31E641A, 0x8E47709E, 0xF1611277,
+0x61F907A, 0xB7100F5C, 0x5A170B19, 0x160557E, 0x55B39D0, 0xC0C556EF, 0xBBF50299, 0xD1D23E12, 0x69588543, 0x4546890, 0x90FA4115, 0x11C5ED8, 0x68B74789, 0xC06F0117, 0x172790AD, 0x606DAC54,
+0x8D488154, 0x8444EC98, 0x9A6592D3, 0xE5E15040, 0xDB031762, 0x2F099450, 0x404F0F5A, 0x1D09E9F4, 0x56045E1F, 0xF9C99F00, 0x136C6599, 0xB0C36E91, 0x1C2835B0, 0x60BE6B5, 0x462FB4D1, 0xCB19B6D7,
+0x6C48C4D9, 0xD0D19B69, 0xA5E544FC, 0xE4851E31, 0x41E464B8, 0x59C6F9D4, 0xF0A6527E, 0x5333D1E0, 0x4862F606, 0x72370631, 0xC2B490C5, 0x4643DE5C, 0x54F9C489, 0xFC526C40, 0xB0A56895, 0x45C1C134,
+0x768F1981, 0x6E295005, 0x950B6964, 0x4B4CD5E9, 0xEB131245, 0x447F844, 0x131B1D76, 0x99981A7, 0x500B1F0A, 0x91011B1B, 0x64E64709, 0xA45C8145, 0xB53001D1, 0xDB462885, 0xBE06D015, 0x4858541B,
+0x6C86C3B5, 0x70A1967B, 0x969B0414, 0xEF485C04, 0x7FE151C1, 0xEBE7F444, 0x5341990B, 0x71D58060, 0xF5A61E10, 0x79F2C53, 0xE5E41F00, 0xBFF4505, 0xE01BB4E9, 0xBFE3905D, 0xDB7664D0, 0x956A065B,
+0x12894E1, 0xBF14B401, 0x30F7A97, 0xA85C97E0, 0xF40643E9, 0xF8506706, 0x9B9B06AB, 0x5AA05995, 0x45448E3D, 0xE1D1907F, 0x24F4C22C, 0x82C2959A, 0xBF065243, 0x8785812D, 0x9A94A916, 0x315B2C60,
+0x523291D9, 0xF2991609, 0x2830579C, 0x999973CC, 0x4B14C098, 0xC1C5053, 0xD1C1C68A, 0x64B67F3, 0xD09B801D, 0x6A7C1044, 0x48580954, 0x859F095A, 0x46533620, 0x592C852D, 0xA5419141, 0x4D16A1D0,
+0xB0B153B, 0xE1944E4A, 0x21371633, 0xCEC9C4E4, 0xA5D70E08, 0x4E4C4DD, 0x591CAC04, 0x5B021DBC, 0x9967CC33, 0x81C0E5FD, 0xF651C104, 0x966760C9, 0x95E1303C, 0xEC5C6440, 0x50BF9F4, 0x3561C31E,
+0x45A096AD, 0xFF92500B, 0xF6598904, 0x19F9C50B, 0x60C64D18, 0xD640584F, 0x2194E1F3, 0xF031163D, 0x101B56E0, 0xDE5921DA, 0xBF01FD1, 0x706FD94, 0x34CB30CE, 0xB857061C, 0x5225B609, 0xC43C3135,
+0xC03B9350, 0xF001676F, 0xF0C18767, 0x6611391B, 0x4F89A46, 0x1F42441A, 0x649F0F46, 0xB5E0015E, 0x7966830E, 0x9740F4F7, 0xC8CC4451, 0x59BD404B, 0xCC9435E1, 0x3B15B2A0, 0x123C1607, 0x59468D90,
+0x40E0D749, 0x14C1F46E, 0x448BD6A9, 0x659AF556, 0x50E7435B, 0xAED2933C, 0x56051308, 0xCE146E50, 0x1C904F10, 0xEC485E0D, 0x169A936C, 0x51633605, 0xDB57A830, 0x62957AB, 0xF4F14448, 0x45CAD5D,
+0x695CC006, 0x104606B9, 0x81D1D86D, 0x8649F050, 0x20D1DB56, 0xE5E53CC0, 0xCB470256, 0xC629E494, 0x49385F8F, 0x65056E31, 0x9C86F095, 0xC8CC9865, 0x869D8118, 0xD1021F11, 0x87DAD1E2, 0xAF04D500,
+0x4518464, 0xB857B085, 0x4505E834, 0xB1E25F04, 0xD8DD9084, 0x35978C33, 0x11A64257, 0x991A1E41, 0x66B06752, 0xBAF41443, 0xBD4A4544, 0xD6753B66, 0xCAC6C639, 0x154480FD, 0x99D19BC, 0x546EE442,
+0xD0C0193E, 0x7491E21F, 0x24B0B3C7, 0xF981D501, 0x74438B58, 0x54C47391, 0x9EDD1180, 0xE697874F, 0x2E41F8E5, 0x468FDD9, 0x4F1E439C, 0x5542EB81, 0xA554FAE0, 0x1E43E2B0, 0x606D5898, 0x6587C4E8,
+0x6B86C511, 0x6050A6D3, 0x1C523485, 0xF2530396, 0x4A2D5884, 0x6FD09193, 0x29978F84, 0xFE490999, 0x9189675E, 0x99277401, 0xDD6F2494, 0x8CD39344, 0xB5783D9, 0xC859EE, 0xAC701503, 0x8FC1D7E1,
+0xA0854317, 0xD09E8444, 0x4510F2BD, 0xED484CD4, 0xDE5D0C1C, 0xC0854367, 0xD1642134, 0x503876E, 0x7C046A5E, 0xE5644035, 0x3D043173, 0x5DE8991, 0xA603D6D0, 0x70644B1B, 0x41C3F55, 0x799EC50,
+0x5C1D005A, 0xB54027BB, 0x501703FB, 0xCE5E2D84, 0xC248776B, 0x34C31DB1, 0xD08146F6, 0x6194D488, 0x902D95DF, 0x56239699, 0x79566996, 0x46366797, 0x2075B449, 0xE619904B, 0xF1FC491D, 0x4026925F,
+0x85CE994, 0xC62D651B, 0xE0F50B4, 0x60976F55, 0x5B7706A6, 0x49471F41, 0xF6D91352, 0x551A062F, 0x4145CFCA, 0x55B14234, 0xABF12531, 0xB915F0F4, 0x8AC7E275, 0x4679C12F, 0xE21353EC, 0x693602A5,
+0x4BC256AB, 0x463D64A6, 0x5E7C6B8, 0x143983F0, 0x3646871A, 0x601D1FE, 0x4D4601FC, 0xB489D0DF, 0xF7814046, 0xE5A50BA7, 0xB34A116, 0x707C4151, 0x804466BB, 0xCF450C5C, 0x1329B9F4, 0xFE400655,
+0xF4A1431B, 0x51D3202D, 0x74B0A444, 0xA6F1612, 0x6C584C8C, 0xC014F665, 0xD3982957, 0x36C136D1, 0x5C45CCD0, 0x9F459882, 0x91A753A2, 0xA9752C4C, 0x421B4297, 0x776A2313, 0x35397906, 0x48065762,
+0x1129B440, 0xAF410B5D, 0x7F9582D2, 0x4B51E650, 0x891D0D77, 0xE59909E5, 0x705D234B, 0xC3DA9055, 0xF1B11501, 0x44BC94D9, 0x1FA55C48, 0x2A422657, 0xC41091A1, 0x18970E74, 0x7699099, 0x10616AD7,
+0x1AE19F10, 0x475A6C31, 0xA27257E9, 0xC484582C, 0xD699665A, 0x17C94C18, 0xE1569B, 0x11855ABF, 0xA580D607, 0x64C18B7E, 0x7030A605, 0x2B3660D0, 0x165BE103, 0x809E1867, 0x47407FD7, 0x34E4858B,
+0x90ED740B, 0x1B43C2F5, 0xF451527C, 0x5723E1C5, 0xE1D1065B, 0xA51A9DF4, 0x7F099A85, 0x4157030B, 0x1D9F60B8, 0xC11491FD, 0xFE850A55, 0xB990431F, 0xA0C78D16, 0x6F5A4D40, 0xFE4411E, 0x34426B56,
+0x5014FE0F, 0xBD5DC51A, 0xC63637C3, 0xE1B459B2, 0xFA871B05, 0x4544D0AD, 0xE5E5093D, 0x3306C5DD, 0x47C33484, 0x6F1E146, 0xE4974F1, 0xDD48050F, 0xAB151E12, 0x5169FC92, 0x5055B27A, 0xD142AD5C,
+0x4B16B0F4, 0x312BC955, 0x75B10FC, 0x4A9E0458, 0xA65D34CE, 0x90D366CF, 0x10099D29, 0x8B358419, 0x87D2B5DA, 0x31162EF5, 0xF61989C5, 0x1F4341F8, 0xBC4C6D9C, 0x11A759, 0x9553A21, 0xCFC41530,
+0x1F05B610, 0x5B2F64C0, 0x117F1124, 0xF3D24D9, 0x44447874, 0x74351A06, 0x64C48979, 0x63C185B, 0x91F094A4, 0x4E1D1C48, 0x969103AE, 0x9CFC6067, 0x2FC94045, 0xED3844C4, 0x676C935B, 0x6E2091B5,
+0x2D9744EC, 0x6A111227, 0x78DB90E5, 0x8045587E, 0xC4E4591E, 0x479BE1E0, 0x5B667499, 0x50E0493E, 0xFB54819C, 0x431491F8, 0xD3EF50E0, 0x7363926, 0x50FF6440, 0x44DC6C9D, 0xF6D9965A, 0x548499,
+0x150A1403, 0xC7324CC7, 0xAFF0474B, 0xB479966E, 0xAD9E5451, 0xF9913C41, 0x1F09B46, 0x3E35461E, 0xA0C66C10, 0xA4D1D103, 0xA05470B4, 0x6F1A3531, 0x4047B2F5, 0x11472CE0, 0x3AE41631, 0xFD36A905,
+0xF4436F91, 0x4A419766, 0x50699E67, 0x5408D93D, 0x112711AF, 0xF500642F, 0x160BD66A, 0x11B0BFE, 0xC2C55CA1, 0x31CF859, 0xC6C95401, 0xD9C0E5C1, 0xE46056AE, 0xF5E30710, 0xA5FF0150, 0x4454203F,
+0xB6660959, 0x2522776, 0x2D586970, 0x7370757, 0x60953317, 0x81E7072D, 0x68149E6, 0x653834, 0x363D9D81, 0xB429113F, 0x566C0258, 0x51F92F00, 0xE19C5812, 0x11FB150, 0x59A65200, 0x2775E0F4,
+0x106752A3, 0x7574326, 0x5CC34739, 0xDAD54805, 0x5E936BC7, 0xCFCAC5C9, 0x2FC42555, 0xD06994C0, 0x5CAC7400, 0x5D84D074, 0x6D668604, 0xE50B19BD, 0xE7969F55, 0xFF925005, 0x65B266B, 0x4743035E,
+0x972C44C7, 0x5AB47260, 0x77123580, 0xD92DB404, 0x451BB8D1, 0xB94B4447, 0x9B955210, 0xA253815, 0x79AC5184, 0xE3D10C5C, 0x452410FB, 0xDFD3A148, 0xE0336E46, 0x4E287599, 0x12B750A9, 0xDAC0DE47,
+0xC18459A9, 0xC764CD30, 0x2334675E, 0xF6490DB8, 0x49172679, 0x659B6994, 0x7A912691, 0xB2B76074, 0xB9E58704, 0xCC33D9A9, 0x207F6A7, 0xC405F801, 0x560297CF, 0x48140E5F, 0xC44E676A, 0xB191DED,
+0x11035F60, 0x5B1F60B4, 0xA4EB1443, 0x5A6C06E6, 0x1915AE9, 0x33CD2696, 0x879F4444, 0xD442170B, 0xC9C9D9D6, 0xA1D4C124, 0xC40366B7, 0x22497E9, 0xCD18D7F9, 0x99FD111A, 0x9F6B53A1, 0xE051ABFC,
+0xBC10071D, 0xA566A759, 0x6DBC5E5, 0x4A9DA851, 0x2266B15, 0x123D6E9B, 0x66E05449, 0xD10D3870, 0x1706E462, 0xAF0B9B51, 0xE0109D6C, 0xF144861B, 0x813ED01B, 0xB6496C10, 0x1ED00768, 0x60747C10,
+0x46494376, 0x5E4C10B0, 0x573D5906, 0x5A02E5FE, 0xB3E005F2, 0xC05C4F45, 0xDBD58982, 0x6D13171F, 0x9741FA00, 0x61DB852, 0x8D46D299, 0x47421E4D, 0x74A94E6, 0x4DA31CD3, 0x681602FF, 0xC67962D7,
+0x1560BBA, 0xF8849D85, 0x7DD6D5B8, 0x5B6B4640, 0x441A349F, 0x61B3601F, 0xD550E2D3, 0xCF18111B, 0x97673333, 0xC59909E4, 0x57DAE840, 0xBB910E5, 0x144484F9, 0xA85C2511, 0x4092D5EA, 0x89910391,
+0x7D385500, 0x3D1D2176, 0x802FD41B, 0xA5D94890, 0x656E9099, 0xE66906E6, 0x4331A2D5, 0x4478E25B, 0xE78C41D, 0x3565D979, 0x4147133B, 0x89C6C64A, 0x45C9CDCF, 0x532315FA, 0x3E5A0D04, 0xB111DBFC,
+0x63162FF7, 0x9E0B9CD0, 0xA758E46B, 0xA097421F, 0xAE544262, 0xA59A5DDD, 0x3732261D, 0x71736790, 0x8895A173, 0x687470B1, 0x57E564FE, 0x6A765404, 0xF5E21482, 0x667150E1, 0xC0A764D9, 0x89950C14,
+0x3756912B, 0x3913499, 0x6FB553C3, 0x29920995, 0x750EC738, 0xC35C6992, 0xAA55E404, 0xCB4B0753, 0x20396156, 0xDB04F4C1, 0x7876825F, 0xD562319A, 0x592D121B, 0xF9360956, 0x47811B47, 0xD9BD5884,
+0x170A35E, 0x844EE59A, 0x8684EDDA, 0x405F1000, 0x813641A7, 0x176681A2, 0x7DBE6440, 0x87C6A54, 0xC485D905, 0x1AB0811D, 0xDBA59291, 0xFA52817C, 0x3981E5F0, 0x5109FEE5, 0xC1284557, 0x573B2703,
+0x30640659, 0xF1D3E997, 0x906253B7, 0x9076C3FD, 0xCA34D35C, 0xF481491C, 0x5976A4C0, 0x3FF1144, 0x26170649, 0x196B9065, 0x90693D09, 0xF0211A17, 0xAF016DD4, 0x4E449C48, 0x6F9A84F4, 0xB4449818,
+0x606DB144, 0x916B97A6, 0xEBD0FD19, 0xAA08D541, 0xD71BE505, 0x1E6507AF, 0x3E4B1361, 0xF391619, 0x4264BC50, 0x60563321, 0x4A370617, 0x436452E7, 0xBE107604, 0xDDA9C18E, 0xBF5B0371, 0x906F1107,
+0x55C5C83C, 0x31364782, 0x68DD9F1, 0xF99607E6, 0x2996367E, 0x5AF4458, 0x96582D30, 0xC4E4D98A, 0xE68719BE, 0x20C56C64, 0x5A550246, 0xB759B079, 0x64439BFB, 0xB1240D2E, 0x271350B2, 0x4314AF56,
+0xA9998D72, 0x5E8D1481, 0xB65D7253, 0x669392B8, 0xF0919B6C, 0x9F9790DD, 0x60979838, 0x3D625168, 0x12196D58, 0x59E9448A, 0x30547C92, 0x8E317590, 0x7B954843, 0x323D4907, 0x5A4D5308, 0xD10490DB,
+0x92CE4511, 0xB9353125, 0xA91F4050, 0xDC485D08, 0x2F11742, 0xB9B4090F, 0xD09891FF, 0x9503936, 0x80E3505F, 0xED99405F, 0xEA9058DE, 0x55019FC0, 0x9A1F412C, 0x471660DA, 0xF4D0C505, 0x4926666D,
+0x4191C3EF, 0x1A0526F5, 0x55F889C7, 0xD33CC738, 0x7A66C601, 0xF701C662, 0x6E953906, 0x6E6559AD, 0x1626C57A, 0xE0075266, 0x67069A5B, 0xA5F70401, 0x47786090, 0x8111C53B, 0xB4640B1A, 0x269D5DAE,
+0x50C4A474, 0x2A94987D, 0x44C05226, 0x6114423F, 0xB8474F1D, 0x8E0E05D8, 0x87B40FD2, 0x1F4392FD, 0x170E995, 0x1563DE0, 0x6F9AC5CA, 0x752A0D1D, 0xFF0A44D0, 0x7FD0D366, 0x51A62E05, 0xD0D5E8DE,
+0x56113F30, 0xE4056D87, 0xAB3B5100, 0x46539C6, 0x7F676290, 0xB851130D, 0xF5E09183, 0x64AC5D2D, 0x55F9404B, 0xE256F977, 0x70617760, 0xEE48E450, 0xDD5E35C8, 0x94D400F8, 0x446A0667, 0xEA935184,
+0x464B07F8, 0x8C74B6D4, 0x8D9D59A5, 0xCEC6ADD5, 0x2D0956A3, 0xA5BA5103, 0x31353123, 0x55FF4140, 0xA2440F15, 0x89266792, 0x44E1E154, 0xE5B41338, 0x2FCE9901, 0x95E6811B, 0x475C871, 0xAE9E4A44,
+0x5E0D141, 0xE702D66B, 0x474707E2, 0x6486CBC5, 0x7476016E, 0xB1D29B56, 0x7A34C605, 0x51427906, 0xE7967F97, 0x65D29C90, 0x55081AD, 0xD6E64045, 0x67134368, 0x9101E6DD, 0x68957841, 0x3D3D5909,
+0xE0525BAF, 0x134A4D3C, 0xC1B11909, 0x16493B76, 0x6B96D0A0, 0xBF0E79D6, 0x2C7096F9, 0x90FC04D6, 0x1742E472, 0x531CA1AC, 0xDAD08646, 0x9066669, 0xA7588D86, 0x913C54C2, 0x742A4514, 0x17111ABC,
+0xDDD7EDE5, 0x6699C498, 0x75313135, 0xE4995F64, 0x2582667E, 0x9C5C4C48, 0x1D0D10D9, 0x5B4C164, 0x46E616CB, 0xD18444BF, 0xE1D4695C, 0x40095E99, 0xECE02955, 0xFF40A411, 0x54D2421B, 0xE1C7DB05,
+0x80E5095D, 0x6745E907, 0xA6197007, 0x760674F9, 0x1522170A, 0x65181FF, 0xE0FDA45, 0x521C7867, 0x6B91D382, 0x657A83C1, 0x73C98C35, 0xB3CC31D6, 0x164B257B, 0x6F9605F9, 0x52F49EB5, 0x87592907,
+0x1B10D6F8, 0x949FD54, 0x910315BA, 0x40F09B47, 0xB761C144, 0x6D039D5, 0x59B113F, 0xE5C6D9, 0x176990FB, 0x90F8A465, 0x6DB8D144, 0x4552E392, 0xC94396B9, 0x36315A97, 0x7E874215, 0x40116F6F,
+0xDF193401, 0x70689317, 0x7E021740, 0xD5C044BD, 0xF1636E94, 0x5B0D34A1, 0x1027F689, 0x44A45590, 0xD443035F, 0xD7A4418C, 0xD949F480, 0x84C1E154, 0x6090966E, 0x40B56C1E, 0x9669C540, 0xA6305505,
+0x1667E244, 0xC245885D, 0xD504A5E, 0xA4F0C549, 0x358472A8, 0xC414BF20, 0x43369729, 0xB1112711, 0x78644352, 0x811CB856, 0x6F9792F0, 0x1E1E4195, 0x62C58C14, 0x2619D3A2, 0x998056BD, 0x653F3410,
+0x919184E4, 0x64906D6C, 0xE3D7996, 0x47660563, 0x50A91F03, 0x49F8C5CB, 0xFE15235E, 0x9783451, 0x716257B7, 0x1AB5351, 0x1710DC84, 0x3FA01D5A, 0x9844AD64, 0xE4D901BC, 0xEE546352, 0xF9547987,
+0xF6834B47, 0xB651F6D, 0xE09C9045, 0xE491424E, 0x94F9050B, 0x7DA6091D, 0xB5C14D74, 0x123A699D, 0x1F413CC3, 0x9F434158, 0x55D8C8C4, 0x51106FF, 0xD36CB1C, 0x1541FCE1, 0xC3344ED3, 0x3E29D905,
+0x150A6579, 0x502475A, 0x454B0F04, 0x65902722, 0x9EA055, 0x26568CC5, 0x7EB1443, 0x42186F96, 0x132357A9, 0x74091F13, 0xEE55480F, 0x7A0B4A45, 0xF01A8637, 0x937D68D5, 0xE2611115, 0x8A853663,
+0x60D295AB, 0x1946461A, 0xBB5190A1, 0x6D514218, 0x7C6482CF, 0x8759ACC8, 0x7E86C805, 0x42D3755F, 0xF4C10529, 0x471F1400, 0x5394238C, 0x112D54A8, 0x55E450F8, 0xDC2191BA, 0xA5F93011, 0x1A2159F5,
+0x4051A297, 0x66066999, 0xA644C058, 0x54EC9148, 0xFAFB0146, 0x1150FCEC, 0x4141D171, 0xF09F0444, 0x488E5E0E, 0x3D190F10, 0x406E405F, 0xFE9904AD, 0x101F5C6F, 0x454B093B, 0x40946C1F, 0xF0B966D,
+0xC16464DB, 0x91E2D6F9, 0x97789074, 0x537C5C40, 0x44A533C3, 0x74102B33, 0x40D425C1, 0xD748C936, 0x786619C9, 0x40917985, 0x66594C1C, 0x2F05D2D2, 0x8C711B4, 0xF9602757, 0x1013854A, 0x7D6296D0,
+0x3D99B8F0, 0x495D3243, 0x916864BE, 0x4E43B947, 0xE756A110, 0xA8D09D7D, 0xBF625095, 0xC1D48F87, 0x8BD47099, 0xDB631315, 0xE54139A0, 0xE4DC9C63, 0x846C2544, 0x4F0E04D1, 0xE0B15B26, 0x3249499D,
+
+}
diff --git a/thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h b/thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h
new file mode 100644
index 0000000000..b0260541c3
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h
@@ -0,0 +1,673 @@
+// basisu_global_selector_palette.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "basisu_transcoder_internal.h"
+#include <algorithm>
+
+namespace basist
+{
+ class etc1_global_palette_entry_modifier
+ {
+ public:
+ enum { cTotalBits = 15, cTotalValues = 1 << cTotalBits };
+
+ etc1_global_palette_entry_modifier(uint32_t index = 0)
+ {
+#ifdef _DEBUG
+ static bool s_tested;
+ if (!s_tested)
+ {
+ s_tested = true;
+ for (uint32_t i = 0; i < cTotalValues; i++)
+ {
+ etc1_global_palette_entry_modifier m(i);
+ etc1_global_palette_entry_modifier n = m;
+
+ assert(n.get_index() == i);
+ }
+ }
+#endif
+
+ set_index(index);
+ }
+
+ void set_index(uint32_t index)
+ {
+ assert(index < cTotalValues);
+ m_rot = index & 3;
+ m_flip = (index >> 2) & 1;
+ m_inv = (index >> 3) & 1;
+ m_contrast = (index >> 4) & 3;
+ m_shift = (index >> 6) & 1;
+ m_median = (index >> 7) & 1;
+ m_div = (index >> 8) & 1;
+ m_rand = (index >> 9) & 1;
+ m_dilate = (index >> 10) & 1;
+ m_shift_x = (index >> 11) & 1;
+ m_shift_y = (index >> 12) & 1;
+ m_erode = (index >> 13) & 1;
+ m_high_pass = (index >> 14) & 1;
+ }
+
+ uint32_t get_index() const
+ {
+ return m_rot | (m_flip << 2) | (m_inv << 3) | (m_contrast << 4) | (m_shift << 6) | (m_median << 7) | (m_div << 8) | (m_rand << 9) | (m_dilate << 10) | (m_shift_x << 11) | (m_shift_y << 12) | (m_erode << 13) | (m_high_pass << 14);
+ }
+
+ void clear()
+ {
+ basisu::clear_obj(*this);
+ }
+
+ uint8_t m_contrast;
+ bool m_rand;
+ bool m_median;
+ bool m_div;
+ bool m_shift;
+ bool m_inv;
+ bool m_flip;
+ bool m_dilate;
+ bool m_shift_x;
+ bool m_shift_y;
+ bool m_erode;
+ bool m_high_pass;
+ uint8_t m_rot;
+ };
+
+ enum modifier_types
+ {
+ cModifierContrast,
+ cModifierRand,
+ cModifierMedian,
+ cModifierDiv,
+ cModifierShift,
+ cModifierInv,
+ cModifierFlippedAndRotated,
+ cModifierDilate,
+ cModifierShiftX,
+ cModifierShiftY,
+ cModifierErode,
+ cModifierHighPass,
+ cTotalModifiers
+ };
+
+#define ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_MOD_BITS (etc1_global_palette_entry_modifier::cTotalBits)
+
+ struct etc1_selector_palette_entry
+ {
+ etc1_selector_palette_entry()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ basisu::clear_obj(*this);
+ }
+
+ uint8_t operator[] (uint32_t i) const { assert(i < 16); return m_selectors[i]; }
+ uint8_t&operator[] (uint32_t i) { assert(i < 16); return m_selectors[i]; }
+
+ void set_uint32(uint32_t v)
+ {
+ for (uint32_t byte_index = 0; byte_index < 4; byte_index++)
+ {
+ uint32_t b = (v >> (byte_index * 8)) & 0xFF;
+
+ m_selectors[byte_index * 4 + 0] = b & 3;
+ m_selectors[byte_index * 4 + 1] = (b >> 2) & 3;
+ m_selectors[byte_index * 4 + 2] = (b >> 4) & 3;
+ m_selectors[byte_index * 4 + 3] = (b >> 6) & 3;
+ }
+ }
+
+ uint32_t get_uint32() const
+ {
+ return get_byte(0) | (get_byte(1) << 8) | (get_byte(2) << 16) | (get_byte(3) << 24);
+ }
+
+ uint32_t get_byte(uint32_t byte_index) const
+ {
+ assert(byte_index < 4);
+
+ return m_selectors[byte_index * 4 + 0] |
+ (m_selectors[byte_index * 4 + 1] << 2) |
+ (m_selectors[byte_index * 4 + 2] << 4) |
+ (m_selectors[byte_index * 4 + 3] << 6);
+ }
+
+ uint8_t operator()(uint32_t x, uint32_t y) const { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
+ uint8_t&operator()(uint32_t x, uint32_t y) { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
+
+ uint32_t calc_distance(const etc1_selector_palette_entry &other) const
+ {
+ uint32_t dist = 0;
+ for (uint32_t i = 0; i < 8; i++)
+ {
+ int delta = static_cast<int>(m_selectors[i]) - static_cast<int>(other.m_selectors[i]);
+ dist += delta * delta;
+ }
+ return dist;
+ }
+
+#if 0
+ uint32_t calc_hamming_dist(const etc1_selector_palette_entry &other) const
+ {
+ uint32_t dist = 0;
+ for (uint32_t i = 0; i < 4; i++)
+ dist += g_hamming_dist[get_byte(i) ^ other.get_byte(i)];
+ return dist;
+ }
+#endif
+
+ etc1_selector_palette_entry get_inverted() const
+ {
+ etc1_selector_palette_entry result;
+
+ for (uint32_t i = 0; i < 16; i++)
+ result.m_selectors[i] = 3 - m_selectors[i];
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_divided() const
+ {
+ etc1_selector_palette_entry result;
+
+ const uint8_t div_selector[4] = { 2, 0, 3, 1 };
+
+ for (uint32_t i = 0; i < 16; i++)
+ result.m_selectors[i] = div_selector[m_selectors[i]];
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_shifted(int delta) const
+ {
+ etc1_selector_palette_entry result;
+
+ for (uint32_t i = 0; i < 16; i++)
+ result.m_selectors[i] = static_cast<uint8_t>(basisu::clamp<int>(m_selectors[i] + delta, 0, 3));
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_randomized() const
+ {
+ uint32_t seed = get_uint32();
+
+ etc1_selector_palette_entry result;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ int s = (*this)(x, y);
+
+ // between 0 and 10
+ uint32_t i = basisd_urand(seed, 6) + basisd_urand(seed, 6);
+ if (i == 0)
+ s -= 2;
+ else if (i == 10)
+ s += 2;
+ else if (i < 3)
+ s -= 1;
+ else if (i > 7)
+ s += 1;
+
+ result(x, y) = static_cast<uint8_t>(basisu::clamp<int>(s, 0, 3));
+ }
+ }
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_contrast(int table_index) const
+ {
+ assert(table_index < 4);
+
+ etc1_selector_palette_entry result;
+
+ static const uint8_t s_contrast_tables[4][4] =
+ {
+ { 0, 1, 2, 3 }, // not used
+ { 0, 0, 3, 3 },
+ { 1, 1, 2, 2 },
+ { 1, 1, 3, 3 }
+ };
+
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ result[i] = s_contrast_tables[table_index][(*this)[i]];
+ }
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_dilated() const
+ {
+ etc1_selector_palette_entry result;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t max_selector = 0;
+
+ for (int yd = -1; yd <= 1; yd++)
+ {
+ int fy = y + yd;
+ if ((fy < 0) || (fy > 3))
+ continue;
+
+ for (int xd = -1; xd <= 1; xd++)
+ {
+ int fx = x + xd;
+ if ((fx < 0) || (fx > 3))
+ continue;
+
+ max_selector = basisu::maximum<uint32_t>(max_selector, (*this)(fx, fy));
+ }
+ }
+
+ result(x, y) = static_cast<uint8_t>(max_selector);
+ }
+ }
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_eroded() const
+ {
+ etc1_selector_palette_entry result;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t min_selector = 99;
+
+ for (int yd = -1; yd <= 1; yd++)
+ {
+ int fy = y + yd;
+ if ((fy < 0) || (fy > 3))
+ continue;
+
+ for (int xd = -1; xd <= 1; xd++)
+ {
+ int fx = x + xd;
+ if ((fx < 0) || (fx > 3))
+ continue;
+
+ min_selector = basisu::minimum<uint32_t>(min_selector, (*this)(fx, fy));
+ }
+ }
+
+ result(x, y) = static_cast<uint8_t>(min_selector);
+ }
+ }
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_shift_x() const
+ {
+ etc1_selector_palette_entry result;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ int sx = x - 1;
+ if (sx < 0)
+ sx = 0;
+
+ result(x, y) = (*this)(sx, y);
+ }
+ }
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_shift_y() const
+ {
+ etc1_selector_palette_entry result;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ int sy = y - 1;
+ if (sy < 0)
+ sy = 3;
+
+ for (uint32_t x = 0; x < 4; x++)
+ result(x, y) = (*this)(x, sy);
+ }
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_median() const
+ {
+ etc1_selector_palette_entry result;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ // ABC
+ // D F
+ // GHI
+
+ uint8_t selectors[8];
+ uint32_t n = 0;
+
+ for (int yd = -1; yd <= 1; yd++)
+ {
+ int fy = y + yd;
+ if ((fy < 0) || (fy > 3))
+ continue;
+
+ for (int xd = -1; xd <= 1; xd++)
+ {
+ if ((xd | yd) == 0)
+ continue;
+
+ int fx = x + xd;
+ if ((fx < 0) || (fx > 3))
+ continue;
+
+ selectors[n++] = (*this)(fx, fy);
+ }
+ }
+
+ std::sort(selectors, selectors + n);
+
+ result(x, y) = selectors[n / 2];
+ }
+ }
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_high_pass() const
+ {
+ etc1_selector_palette_entry result;
+
+ static const int kernel[3][3] =
+ {
+ { 0, -1, 0 },
+ { -1, 8, -1 },
+ { 0, -1, 0 }
+ };
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ // ABC
+ // D F
+ // GHI
+
+ int sum = 0;
+
+ for (int yd = -1; yd <= 1; yd++)
+ {
+ int fy = y + yd;
+ fy = basisu::clamp<int>(fy, 0, 3);
+
+ for (int xd = -1; xd <= 1; xd++)
+ {
+ int fx = x + xd;
+ fx = basisu::clamp<int>(fx, 0, 3);
+
+ int k = (*this)(fx, fy);
+ sum += k * kernel[yd + 1][xd + 1];
+ }
+ }
+
+ sum = sum / 4;
+
+ result(x, y) = static_cast<uint8_t>(basisu::clamp<int>(sum, 0, 3));
+ }
+ }
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_flipped_and_rotated(bool flip, uint32_t rotation_index) const
+ {
+ etc1_selector_palette_entry temp;
+
+ if (flip)
+ {
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ temp(x, y) = (*this)(x, 3 - y);
+ }
+ else
+ {
+ temp = *this;
+ }
+
+ etc1_selector_palette_entry result;
+
+ switch (rotation_index)
+ {
+ case 0:
+ result = temp;
+ break;
+ case 1:
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ result(x, y) = temp(y, 3 - x);
+ break;
+ case 2:
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ result(x, y) = temp(3 - x, 3 - y);
+ break;
+ case 3:
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ result(x, y) = temp(3 - y, x);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return result;
+ }
+
+ etc1_selector_palette_entry get_modified(const etc1_global_palette_entry_modifier &modifier) const
+ {
+ etc1_selector_palette_entry r(*this);
+
+ if (modifier.m_shift_x)
+ r = r.get_shift_x();
+
+ if (modifier.m_shift_y)
+ r = r.get_shift_y();
+
+ r = r.get_flipped_and_rotated(modifier.m_flip != 0, modifier.m_rot);
+
+ if (modifier.m_dilate)
+ r = r.get_dilated();
+
+ if (modifier.m_erode)
+ r = r.get_eroded();
+
+ if (modifier.m_high_pass)
+ r = r.get_high_pass();
+
+ if (modifier.m_rand)
+ r = r.get_randomized();
+
+ if (modifier.m_div)
+ r = r.get_divided();
+
+ if (modifier.m_shift)
+ r = r.get_shifted(1);
+
+ if (modifier.m_contrast)
+ r = r.get_contrast(modifier.m_contrast);
+
+ if (modifier.m_inv)
+ r = r.get_inverted();
+
+ if (modifier.m_median)
+ r = r.get_median();
+
+ return r;
+ }
+
+ etc1_selector_palette_entry apply_modifier(modifier_types mod_type, const etc1_global_palette_entry_modifier &modifier) const
+ {
+ switch (mod_type)
+ {
+ case cModifierContrast:
+ return get_contrast(modifier.m_contrast);
+ case cModifierRand:
+ return get_randomized();
+ case cModifierMedian:
+ return get_median();
+ case cModifierDiv:
+ return get_divided();
+ case cModifierShift:
+ return get_shifted(1);
+ case cModifierInv:
+ return get_inverted();
+ case cModifierFlippedAndRotated:
+ return get_flipped_and_rotated(modifier.m_flip != 0, modifier.m_rot);
+ case cModifierDilate:
+ return get_dilated();
+ case cModifierShiftX:
+ return get_shift_x();
+ case cModifierShiftY:
+ return get_shift_y();
+ case cModifierErode:
+ return get_eroded();
+ case cModifierHighPass:
+ return get_high_pass();
+ default:
+ assert(0);
+ break;
+ }
+
+ return *this;
+ }
+
+ etc1_selector_palette_entry get_modified(const etc1_global_palette_entry_modifier &modifier, uint32_t num_order, const modifier_types *pOrder) const
+ {
+ etc1_selector_palette_entry r(*this);
+
+ for (uint32_t i = 0; i < num_order; i++)
+ {
+ r = r.apply_modifier(pOrder[i], modifier);
+ }
+
+ return r;
+ }
+
+ bool operator< (const etc1_selector_palette_entry &other) const
+ {
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ if (m_selectors[i] < other.m_selectors[i])
+ return true;
+ else if (m_selectors[i] != other.m_selectors[i])
+ return false;
+ }
+
+ return false;
+ }
+
+ bool operator== (const etc1_selector_palette_entry &other) const
+ {
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ if (m_selectors[i] != other.m_selectors[i])
+ return false;
+ }
+
+ return true;
+ }
+
+ private:
+ uint8_t m_selectors[16];
+ };
+
+ typedef std::vector<etc1_selector_palette_entry> etc1_selector_palette_entry_vec;
+
+ extern const uint32_t g_global_selector_cb[];
+ extern const uint32_t g_global_selector_cb_size;
+
+#define ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_PAL_BITS (12)
+
+ struct etc1_global_selector_codebook_entry_id
+ {
+ uint32_t m_palette_index;
+ etc1_global_palette_entry_modifier m_modifier;
+
+ etc1_global_selector_codebook_entry_id(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) : m_palette_index(palette_index), m_modifier(modifier) { }
+
+ etc1_global_selector_codebook_entry_id() { }
+
+ void set(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) { m_palette_index = palette_index; m_modifier = modifier; }
+ };
+
+ typedef std::vector<etc1_global_selector_codebook_entry_id> etc1_global_selector_codebook_entry_id_vec;
+
+ class etc1_global_selector_codebook
+ {
+ public:
+ etc1_global_selector_codebook() { }
+ etc1_global_selector_codebook(uint32_t N, const uint32_t *pEntries) { init(N, pEntries); }
+
+ void init(uint32_t N, const uint32_t* pEntries);
+
+ void print_code(FILE *pFile);
+
+ void clear()
+ {
+ m_palette.clear();
+ }
+
+ uint32_t size() const { return (uint32_t)m_palette.size(); }
+
+ const etc1_selector_palette_entry_vec &get_palette() const
+ {
+ return m_palette;
+ }
+
+ etc1_selector_palette_entry get_entry(uint32_t palette_index) const
+ {
+ return m_palette[palette_index];
+ }
+
+ etc1_selector_palette_entry get_entry(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) const
+ {
+ return m_palette[palette_index].get_modified(modifier);
+ }
+
+ etc1_selector_palette_entry get_entry(const etc1_global_selector_codebook_entry_id &id) const
+ {
+ return m_palette[id.m_palette_index].get_modified(id.m_modifier);
+ }
+
+ etc1_selector_palette_entry_vec m_palette;
+ };
+
+} // namespace basist
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
new file mode 100644
index 0000000000..d15b6013d9
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
@@ -0,0 +1,10532 @@
+// basisu_transcoder.cpp
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "basisu_transcoder.h"
+#include <limits.h>
+#include <vector>
+
+// The supported .basis file header version. Keep in sync with BASIS_FILE_VERSION.
+#define BASISD_SUPPORTED_BASIS_VERSION (0x13)
+
+// Set to 1 for fuzz testing. This will disable all CRC16 checks on headers and compressed data.
+#ifndef BASISU_NO_HEADER_OR_DATA_CRC16_CHECKS
+#define BASISU_NO_HEADER_OR_DATA_CRC16_CHECKS 0
+#endif
+
+#ifndef BASISD_SUPPORT_DXT1
+#define BASISD_SUPPORT_DXT1 1
+#endif
+
+#ifndef BASISD_SUPPORT_DXT5A
+#define BASISD_SUPPORT_DXT5A 1
+#endif
+
+// Disable all BC7 transcoders if necessary (useful when cross compiling to Javascript)
+#if defined(BASISD_SUPPORT_BC7) && !BASISD_SUPPORT_BC7
+ #ifndef BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY
+ #define BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY 0
+ #endif
+ #ifndef BASISD_SUPPORT_BC7_MODE5
+ #define BASISD_SUPPORT_BC7_MODE5 0
+ #endif
+#endif // !BASISD_SUPPORT_BC7
+
+// BC7 mode 6 opaque only is the highest quality (compared to ETC1), but the tables are massive.
+// For web/mobile use you probably should disable this.
+#ifndef BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY
+#define BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY 1
+#endif
+
+// BC7 mode 5 supports both opaque and opaque+alpha textures, and uses substantially less memory than BC7 mode 6 and even BC1.
+#ifndef BASISD_SUPPORT_BC7_MODE5
+#define BASISD_SUPPORT_BC7_MODE5 1
+#endif
+
+#ifndef BASISD_SUPPORT_PVRTC1
+#define BASISD_SUPPORT_PVRTC1 1
+#endif
+
+#ifndef BASISD_SUPPORT_ETC2_EAC_A8
+#define BASISD_SUPPORT_ETC2_EAC_A8 1
+#endif
+
+#ifndef BASISD_SUPPORT_ASTC
+#define BASISD_SUPPORT_ASTC 1
+#endif
+
+// Note that if BASISD_SUPPORT_ATC is enabled, BASISD_SUPPORT_DXT5A should also be enabled for alpha support.
+#ifndef BASISD_SUPPORT_ATC
+#define BASISD_SUPPORT_ATC 1
+#endif
+
+// Support for ETC2 EAC R11 and ETC2 EAC RG11
+#ifndef BASISD_SUPPORT_ETC2_EAC_RG11
+#define BASISD_SUPPORT_ETC2_EAC_RG11 1
+#endif
+
+// If BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY is 1, opaque blocks will be transcoded to ASTC at slightly higher quality (higher than BC1), but the transcoder tables will be 2x as large.
+// This impacts grayscale and grayscale+alpha textures the most.
+#ifndef BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY
+ #ifdef __EMSCRIPTEN__
+ // Let's assume size matters more than quality when compiling with emscripten.
+ #define BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY 0
+ #else
+ // Compiling native, so an extra 64K lookup table is probably acceptable.
+ #define BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY 1
+ #endif
+#endif
+
+#ifndef BASISD_SUPPORT_FXT1
+#define BASISD_SUPPORT_FXT1 1
+#endif
+
+#ifndef BASISD_SUPPORT_PVRTC2
+#define BASISD_SUPPORT_PVRTC2 1
+#endif
+
+#if BASISD_SUPPORT_PVRTC2
+#if !BASISD_SUPPORT_ATC
+#error BASISD_SUPPORT_ATC must be 1 if BASISD_SUPPORT_PVRTC2 is 1
+#endif
+#endif
+
+#if BASISD_SUPPORT_ATC
+#if !BASISD_SUPPORT_DXT5A
+#error BASISD_SUPPORT_DXT5A must be 1 if BASISD_SUPPORT_ATC is 1
+#endif
+#endif
+
+#define BASISD_WRITE_NEW_BC7_TABLES 0
+#define BASISD_WRITE_NEW_BC7_MODE5_TABLES 0
+#define BASISD_WRITE_NEW_DXT1_TABLES 0
+#define BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES 0
+#define BASISD_WRITE_NEW_ASTC_TABLES 0
+#define BASISD_WRITE_NEW_ATC_TABLES 0
+#define BASISD_WRITE_NEW_ETC2_EAC_R11_TABLES 0
+
+#ifndef BASISD_ENABLE_DEBUG_FLAGS
+#define BASISD_ENABLE_DEBUG_FLAGS 0
+#endif
+
+namespace basisu
+{
+ bool g_debug_printf;
+
+ void enable_debug_printf(bool enabled)
+ {
+ g_debug_printf = enabled;
+ }
+
+ void debug_printf(const char* pFmt, ...)
+ {
+#if BASISU_DEVEL_MESSAGES
+ g_debug_printf = true;
+#endif
+ if (g_debug_printf)
+ {
+ va_list args;
+ va_start(args, pFmt);
+ vprintf(pFmt, args);
+ va_end(args);
+ }
+ }
+} // namespace basisu
+
+namespace basist
+{
+#if BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY
+#include "basisu_transcoder_tables_bc7_m6.inc"
+#endif
+
+#if BASISD_ENABLE_DEBUG_FLAGS
+ static uint32_t g_debug_flags = 0;
+#endif
+
+ uint32_t get_debug_flags()
+ {
+#if BASISD_ENABLE_DEBUG_FLAGS
+ return g_debug_flags;
+#else
+ return 0;
+#endif
+ }
+
+ void set_debug_flags(uint32_t f)
+ {
+ (void)f;
+#if BASISD_ENABLE_DEBUG_FLAGS
+ g_debug_flags = f;
+#endif
+ }
+ uint16_t crc16(const void* r, size_t size, uint16_t crc)
+ {
+ crc = ~crc;
+
+ const uint8_t* p = reinterpret_cast<const uint8_t*>(r);
+ for (; size; --size)
+ {
+ const uint16_t q = *p++ ^ (crc >> 8);
+ uint16_t k = (q >> 4) ^ q;
+ crc = (((crc << 8) ^ k) ^ (k << 5)) ^ (k << 12);
+ }
+
+ return static_cast<uint16_t>(~crc);
+ }
+
+ const uint32_t g_global_selector_cb[] =
+#include "basisu_global_selector_cb.h"
+ ;
+
+ const uint32_t g_global_selector_cb_size = sizeof(g_global_selector_cb) / sizeof(g_global_selector_cb[0]);
+
+ void etc1_global_selector_codebook::init(uint32_t N, const uint32_t* pEntries)
+ {
+ m_palette.resize(N);
+ for (uint32_t i = 0; i < N; i++)
+ m_palette[i].set_uint32(pEntries[i]);
+ }
+
+ void etc1_global_selector_codebook::print_code(FILE* pFile)
+ {
+ fprintf(pFile, "{\n");
+ for (uint32_t i = 0; i < m_palette.size(); i++)
+ {
+ fprintf(pFile, "0x%X,", m_palette[i].get_uint32());
+ if ((i & 15) == 15)
+ fprintf(pFile, "\n");
+ }
+ fprintf(pFile, "\n}\n");
+ }
+
+ enum etc_constants
+ {
+ cETC1BytesPerBlock = 8U,
+
+ cETC1SelectorBits = 2U,
+ cETC1SelectorValues = 1U << cETC1SelectorBits,
+ cETC1SelectorMask = cETC1SelectorValues - 1U,
+
+ cETC1BlockShift = 2U,
+ cETC1BlockSize = 1U << cETC1BlockShift,
+
+ cETC1LSBSelectorIndicesBitOffset = 0,
+ cETC1MSBSelectorIndicesBitOffset = 16,
+
+ cETC1FlipBitOffset = 32,
+ cETC1DiffBitOffset = 33,
+
+ cETC1IntenModifierNumBits = 3,
+ cETC1IntenModifierValues = 1 << cETC1IntenModifierNumBits,
+ cETC1RightIntenModifierTableBitOffset = 34,
+ cETC1LeftIntenModifierTableBitOffset = 37,
+
+ // Base+Delta encoding (5 bit bases, 3 bit delta)
+ cETC1BaseColorCompNumBits = 5,
+ cETC1BaseColorCompMax = 1 << cETC1BaseColorCompNumBits,
+
+ cETC1DeltaColorCompNumBits = 3,
+ cETC1DeltaColorComp = 1 << cETC1DeltaColorCompNumBits,
+ cETC1DeltaColorCompMax = 1 << cETC1DeltaColorCompNumBits,
+
+ cETC1BaseColor5RBitOffset = 59,
+ cETC1BaseColor5GBitOffset = 51,
+ cETC1BaseColor5BBitOffset = 43,
+
+ cETC1DeltaColor3RBitOffset = 56,
+ cETC1DeltaColor3GBitOffset = 48,
+ cETC1DeltaColor3BBitOffset = 40,
+
+ // Absolute (non-delta) encoding (two 4-bit per component bases)
+ cETC1AbsColorCompNumBits = 4,
+ cETC1AbsColorCompMax = 1 << cETC1AbsColorCompNumBits,
+
+ cETC1AbsColor4R1BitOffset = 60,
+ cETC1AbsColor4G1BitOffset = 52,
+ cETC1AbsColor4B1BitOffset = 44,
+
+ cETC1AbsColor4R2BitOffset = 56,
+ cETC1AbsColor4G2BitOffset = 48,
+ cETC1AbsColor4B2BitOffset = 40,
+
+ cETC1ColorDeltaMin = -4,
+ cETC1ColorDeltaMax = 3,
+
+ // Delta3:
+ // 0 1 2 3 4 5 6 7
+ // 000 001 010 011 100 101 110 111
+ // 0 1 2 3 -4 -3 -2 -1
+ };
+
+#define DECLARE_ETC1_INTEN_TABLE(name, N) \
+ static const int name[cETC1IntenModifierValues][cETC1SelectorValues] = \
+ { \
+ { N * -8, N * -2, N * 2, N * 8 },{ N * -17, N * -5, N * 5, N * 17 },{ N * -29, N * -9, N * 9, N * 29 },{ N * -42, N * -13, N * 13, N * 42 }, \
+ { N * -60, N * -18, N * 18, N * 60 },{ N * -80, N * -24, N * 24, N * 80 },{ N * -106, N * -33, N * 33, N * 106 },{ N * -183, N * -47, N * 47, N * 183 } \
+ };
+
+ DECLARE_ETC1_INTEN_TABLE(g_etc1_inten_tables, 1);
+ DECLARE_ETC1_INTEN_TABLE(g_etc1_inten_tables16, 16);
+ DECLARE_ETC1_INTEN_TABLE(g_etc1_inten_tables48, 3 * 16);
+
+ static const uint8_t g_etc_5_to_8[32] = { 0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173, 181, 189, 198, 206, 214, 222, 231, 239, 247, 255 };
+
+ struct decoder_etc_block
+ {
+ // big endian uint64:
+ // bit ofs: 56 48 40 32 24 16 8 0
+ // byte ofs: b0, b1, b2, b3, b4, b5, b6, b7
+ union
+ {
+ uint64_t m_uint64;
+
+ uint32_t m_uint32[2];
+
+ uint8_t m_bytes[8];
+
+ struct
+ {
+ signed m_dred2 : 3;
+ uint32_t m_red1 : 5;
+
+ signed m_dgreen2 : 3;
+ uint32_t m_green1 : 5;
+
+ signed m_dblue2 : 3;
+ uint32_t m_blue1 : 5;
+
+ uint32_t m_flip : 1;
+ uint32_t m_diff : 1;
+ uint32_t m_cw2 : 3;
+ uint32_t m_cw1 : 3;
+
+ uint32_t m_selectors;
+ } m_differential;
+ };
+
+ inline void clear()
+ {
+ assert(sizeof(*this) == 8);
+ basisu::clear_obj(*this);
+ }
+
+ inline void set_byte_bits(uint32_t ofs, uint32_t num, uint32_t bits)
+ {
+ assert((ofs + num) <= 64U);
+ assert(num && (num < 32U));
+ assert((ofs >> 3) == ((ofs + num - 1) >> 3));
+ assert(bits < (1U << num));
+ const uint32_t byte_ofs = 7 - (ofs >> 3);
+ const uint32_t byte_bit_ofs = ofs & 7;
+ const uint32_t mask = (1 << num) - 1;
+ m_bytes[byte_ofs] &= ~(mask << byte_bit_ofs);
+ m_bytes[byte_ofs] |= (bits << byte_bit_ofs);
+ }
+
+ inline void set_flip_bit(bool flip)
+ {
+ m_bytes[3] &= ~1;
+ m_bytes[3] |= static_cast<uint8_t>(flip);
+ }
+
+ inline void set_diff_bit(bool diff)
+ {
+ m_bytes[3] &= ~2;
+ m_bytes[3] |= (static_cast<uint32_t>(diff) << 1);
+ }
+
+ // Sets intensity modifier table (0-7) used by subblock subblock_id (0 or 1)
+ inline void set_inten_table(uint32_t subblock_id, uint32_t t)
+ {
+ assert(subblock_id < 2);
+ assert(t < 8);
+ const uint32_t ofs = subblock_id ? 2 : 5;
+ m_bytes[3] &= ~(7 << ofs);
+ m_bytes[3] |= (t << ofs);
+ }
+
+ // Selector "val" ranges from 0-3 and is a direct index into g_etc1_inten_tables.
+ inline void set_selector(uint32_t x, uint32_t y, uint32_t val)
+ {
+ assert((x | y | val) < 4);
+ const uint32_t bit_index = x * 4 + y;
+
+ uint8_t* p = &m_bytes[7 - (bit_index >> 3)];
+
+ const uint32_t byte_bit_ofs = bit_index & 7;
+ const uint32_t mask = 1 << byte_bit_ofs;
+
+ static const uint8_t s_selector_index_to_etc1[4] = { 3, 2, 0, 1 };
+ const uint32_t etc1_val = s_selector_index_to_etc1[val];
+
+ const uint32_t lsb = etc1_val & 1;
+ const uint32_t msb = etc1_val >> 1;
+
+ p[0] &= ~mask;
+ p[0] |= (lsb << byte_bit_ofs);
+
+ p[-2] &= ~mask;
+ p[-2] |= (msb << byte_bit_ofs);
+ }
+
+ // Returned encoded selector value ranges from 0-3 (this is NOT a direct index into g_etc1_inten_tables, see get_selector())
+ inline uint32_t get_raw_selector(uint32_t x, uint32_t y) const
+ {
+ assert((x | y) < 4);
+
+ const uint32_t bit_index = x * 4 + y;
+ const uint32_t byte_bit_ofs = bit_index & 7;
+ const uint8_t* p = &m_bytes[7 - (bit_index >> 3)];
+ const uint32_t lsb = (p[0] >> byte_bit_ofs) & 1;
+ const uint32_t msb = (p[-2] >> byte_bit_ofs) & 1;
+ const uint32_t val = lsb | (msb << 1);
+
+ return val;
+ }
+
+ // Returned selector value ranges from 0-3 and is a direct index into g_etc1_inten_tables.
+ inline uint32_t get_selector(uint32_t x, uint32_t y) const
+ {
+ static const uint8_t s_etc1_to_selector_index[cETC1SelectorValues] = { 2, 3, 1, 0 };
+ return s_etc1_to_selector_index[get_raw_selector(x, y)];
+ }
+
+ inline void set_raw_selector_bits(uint32_t bits)
+ {
+ m_bytes[4] = static_cast<uint8_t>(bits);
+ m_bytes[5] = static_cast<uint8_t>(bits >> 8);
+ m_bytes[6] = static_cast<uint8_t>(bits >> 16);
+ m_bytes[7] = static_cast<uint8_t>(bits >> 24);
+ }
+
+ inline bool are_all_selectors_the_same() const
+ {
+ uint32_t v = *reinterpret_cast<const uint32_t*>(&m_bytes[4]);
+
+ if ((v == 0xFFFFFFFF) || (v == 0xFFFF) || (!v) || (v == 0xFFFF0000))
+ return true;
+
+ return false;
+ }
+
+ inline void set_raw_selector_bits(uint8_t byte0, uint8_t byte1, uint8_t byte2, uint8_t byte3)
+ {
+ m_bytes[4] = byte0;
+ m_bytes[5] = byte1;
+ m_bytes[6] = byte2;
+ m_bytes[7] = byte3;
+ }
+
+ inline uint32_t get_raw_selector_bits() const
+ {
+ return m_bytes[4] | (m_bytes[5] << 8) | (m_bytes[6] << 16) | (m_bytes[7] << 24);
+ }
+
+ inline void set_base4_color(uint32_t idx, uint16_t c)
+ {
+ if (idx)
+ {
+ set_byte_bits(cETC1AbsColor4R2BitOffset, 4, (c >> 8) & 15);
+ set_byte_bits(cETC1AbsColor4G2BitOffset, 4, (c >> 4) & 15);
+ set_byte_bits(cETC1AbsColor4B2BitOffset, 4, c & 15);
+ }
+ else
+ {
+ set_byte_bits(cETC1AbsColor4R1BitOffset, 4, (c >> 8) & 15);
+ set_byte_bits(cETC1AbsColor4G1BitOffset, 4, (c >> 4) & 15);
+ set_byte_bits(cETC1AbsColor4B1BitOffset, 4, c & 15);
+ }
+ }
+
+ inline void set_base5_color(uint16_t c)
+ {
+ set_byte_bits(cETC1BaseColor5RBitOffset, 5, (c >> 10) & 31);
+ set_byte_bits(cETC1BaseColor5GBitOffset, 5, (c >> 5) & 31);
+ set_byte_bits(cETC1BaseColor5BBitOffset, 5, c & 31);
+ }
+
+ void set_delta3_color(uint16_t c)
+ {
+ set_byte_bits(cETC1DeltaColor3RBitOffset, 3, (c >> 6) & 7);
+ set_byte_bits(cETC1DeltaColor3GBitOffset, 3, (c >> 3) & 7);
+ set_byte_bits(cETC1DeltaColor3BBitOffset, 3, c & 7);
+ }
+
+ void set_block_color4(const color32& c0_unscaled, const color32& c1_unscaled)
+ {
+ set_diff_bit(false);
+
+ set_base4_color(0, pack_color4(c0_unscaled, false));
+ set_base4_color(1, pack_color4(c1_unscaled, false));
+ }
+
+ void set_block_color5(const color32& c0_unscaled, const color32& c1_unscaled)
+ {
+ set_diff_bit(true);
+
+ set_base5_color(pack_color5(c0_unscaled, false));
+
+ int dr = c1_unscaled.r - c0_unscaled.r;
+ int dg = c1_unscaled.g - c0_unscaled.g;
+ int db = c1_unscaled.b - c0_unscaled.b;
+
+ set_delta3_color(pack_delta3(dr, dg, db));
+ }
+
+ bool set_block_color5_check(const color32& c0_unscaled, const color32& c1_unscaled)
+ {
+ set_diff_bit(true);
+
+ set_base5_color(pack_color5(c0_unscaled, false));
+
+ int dr = c1_unscaled.r - c0_unscaled.r;
+ int dg = c1_unscaled.g - c0_unscaled.g;
+ int db = c1_unscaled.b - c0_unscaled.b;
+
+ if (((dr < cETC1ColorDeltaMin) || (dr > cETC1ColorDeltaMax)) ||
+ ((dg < cETC1ColorDeltaMin) || (dg > cETC1ColorDeltaMax)) ||
+ ((db < cETC1ColorDeltaMin) || (db > cETC1ColorDeltaMax)))
+ return false;
+
+ set_delta3_color(pack_delta3(dr, dg, db));
+
+ return true;
+ }
+
+ inline uint32_t get_byte_bits(uint32_t ofs, uint32_t num) const
+ {
+ assert((ofs + num) <= 64U);
+ assert(num && (num <= 8U));
+ assert((ofs >> 3) == ((ofs + num - 1) >> 3));
+ const uint32_t byte_ofs = 7 - (ofs >> 3);
+ const uint32_t byte_bit_ofs = ofs & 7;
+ return (m_bytes[byte_ofs] >> byte_bit_ofs) & ((1 << num) - 1);
+ }
+
+ inline uint16_t get_base5_color() const
+ {
+ const uint32_t r = get_byte_bits(cETC1BaseColor5RBitOffset, 5);
+ const uint32_t g = get_byte_bits(cETC1BaseColor5GBitOffset, 5);
+ const uint32_t b = get_byte_bits(cETC1BaseColor5BBitOffset, 5);
+ return static_cast<uint16_t>(b | (g << 5U) | (r << 10U));
+ }
+
+ inline color32 get_base5_color_unscaled() const
+ {
+ return color32(m_differential.m_red1, m_differential.m_green1, m_differential.m_blue1, 255);
+ }
+
+ inline uint32_t get_inten_table(uint32_t subblock_id) const
+ {
+ assert(subblock_id < 2);
+ const uint32_t ofs = subblock_id ? 2 : 5;
+ return (m_bytes[3] >> ofs) & 7;
+ }
+
+ static uint16_t pack_color4(const color32& color, bool scaled, uint32_t bias = 127U)
+ {
+ return pack_color4(color.r, color.g, color.b, scaled, bias);
+ }
+
+ static uint16_t pack_color4(uint32_t r, uint32_t g, uint32_t b, bool scaled, uint32_t bias = 127U)
+ {
+ if (scaled)
+ {
+ r = (r * 15U + bias) / 255U;
+ g = (g * 15U + bias) / 255U;
+ b = (b * 15U + bias) / 255U;
+ }
+
+ r = basisu::minimum(r, 15U);
+ g = basisu::minimum(g, 15U);
+ b = basisu::minimum(b, 15U);
+
+ return static_cast<uint16_t>(b | (g << 4U) | (r << 8U));
+ }
+
+ static uint16_t pack_color5(const color32& color, bool scaled, uint32_t bias = 127U)
+ {
+ return pack_color5(color.r, color.g, color.b, scaled, bias);
+ }
+
+ static uint16_t pack_color5(uint32_t r, uint32_t g, uint32_t b, bool scaled, uint32_t bias = 127U)
+ {
+ if (scaled)
+ {
+ r = (r * 31U + bias) / 255U;
+ g = (g * 31U + bias) / 255U;
+ b = (b * 31U + bias) / 255U;
+ }
+
+ r = basisu::minimum(r, 31U);
+ g = basisu::minimum(g, 31U);
+ b = basisu::minimum(b, 31U);
+
+ return static_cast<uint16_t>(b | (g << 5U) | (r << 10U));
+ }
+
+ uint16_t pack_delta3(const color32& color)
+ {
+ return pack_delta3(color.r, color.g, color.b);
+ }
+
+ uint16_t pack_delta3(int r, int g, int b)
+ {
+ assert((r >= cETC1ColorDeltaMin) && (r <= cETC1ColorDeltaMax));
+ assert((g >= cETC1ColorDeltaMin) && (g <= cETC1ColorDeltaMax));
+ assert((b >= cETC1ColorDeltaMin) && (b <= cETC1ColorDeltaMax));
+ if (r < 0) r += 8;
+ if (g < 0) g += 8;
+ if (b < 0) b += 8;
+ return static_cast<uint16_t>(b | (g << 3) | (r << 6));
+ }
+
+ static color32 unpack_color5(uint16_t packed_color5, bool scaled, uint32_t alpha = 255)
+ {
+ uint32_t b = packed_color5 & 31U;
+ uint32_t g = (packed_color5 >> 5U) & 31U;
+ uint32_t r = (packed_color5 >> 10U) & 31U;
+
+ if (scaled)
+ {
+ b = (b << 3U) | (b >> 2U);
+ g = (g << 3U) | (g >> 2U);
+ r = (r << 3U) | (r >> 2U);
+ }
+
+ return color32(r, g, b, alpha);
+ }
+
+ static void unpack_color5(uint32_t& r, uint32_t& g, uint32_t& b, uint16_t packed_color5, bool scaled)
+ {
+ color32 c(unpack_color5(packed_color5, scaled, 0));
+ r = c.r;
+ g = c.g;
+ b = c.b;
+ }
+
+ static void get_diff_subblock_colors(color32* pDst, uint16_t packed_color5, uint32_t table_idx)
+ {
+ assert(table_idx < cETC1IntenModifierValues);
+ const int* pInten_modifer_table = &g_etc1_inten_tables[table_idx][0];
+
+ uint32_t r, g, b;
+ unpack_color5(r, g, b, packed_color5, true);
+
+ const int ir = static_cast<int>(r), ig = static_cast<int>(g), ib = static_cast<int>(b);
+
+ const int y0 = pInten_modifer_table[0];
+ pDst[0].set(clamp255(ir + y0), clamp255(ig + y0), clamp255(ib + y0), 255);
+
+ const int y1 = pInten_modifer_table[1];
+ pDst[1].set(clamp255(ir + y1), clamp255(ig + y1), clamp255(ib + y1), 255);
+
+ const int y2 = pInten_modifer_table[2];
+ pDst[2].set(clamp255(ir + y2), clamp255(ig + y2), clamp255(ib + y2), 255);
+
+ const int y3 = pInten_modifer_table[3];
+ pDst[3].set(clamp255(ir + y3), clamp255(ig + y3), clamp255(ib + y3), 255);
+ }
+
+ static int clamp255(int x)
+ {
+ if (x & 0xFFFFFF00)
+ {
+ if (x < 0)
+ x = 0;
+ else if (x > 255)
+ x = 255;
+ }
+
+ return x;
+ }
+
+ static void get_block_colors5(color32* pBlock_colors, const color32& base_color5, uint32_t inten_table)
+ {
+ color32 b(base_color5);
+
+ b.r = (b.r << 3) | (b.r >> 2);
+ b.g = (b.g << 3) | (b.g >> 2);
+ b.b = (b.b << 3) | (b.b >> 2);
+
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ pBlock_colors[0].set(clamp255(b.r + pInten_table[0]), clamp255(b.g + pInten_table[0]), clamp255(b.b + pInten_table[0]), 255);
+ pBlock_colors[1].set(clamp255(b.r + pInten_table[1]), clamp255(b.g + pInten_table[1]), clamp255(b.b + pInten_table[1]), 255);
+ pBlock_colors[2].set(clamp255(b.r + pInten_table[2]), clamp255(b.g + pInten_table[2]), clamp255(b.b + pInten_table[2]), 255);
+ pBlock_colors[3].set(clamp255(b.r + pInten_table[3]), clamp255(b.g + pInten_table[3]), clamp255(b.b + pInten_table[3]), 255);
+ }
+
+ static void get_block_color5(const color32& base_color5, uint32_t inten_table, uint32_t index, uint32_t& r, uint32_t &g, uint32_t &b)
+ {
+ assert(index < 4);
+
+ uint32_t br = (base_color5.r << 3) | (base_color5.r >> 2);
+ uint32_t bg = (base_color5.g << 3) | (base_color5.g >> 2);
+ uint32_t bb = (base_color5.b << 3) | (base_color5.b >> 2);
+
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ r = clamp255(br + pInten_table[index]);
+ g = clamp255(bg + pInten_table[index]);
+ b = clamp255(bb + pInten_table[index]);
+ }
+
+ static void get_block_color5_r(const color32& base_color5, uint32_t inten_table, uint32_t index, uint32_t &r)
+ {
+ assert(index < 4);
+
+ uint32_t br = (base_color5.r << 3) | (base_color5.r >> 2);
+
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ r = clamp255(br + pInten_table[index]);
+ }
+
+ static void get_block_colors5_g(int* pBlock_colors, const color32& base_color5, uint32_t inten_table)
+ {
+ const int g = (base_color5.g << 3) | (base_color5.g >> 2);
+
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ pBlock_colors[0] = clamp255(g + pInten_table[0]);
+ pBlock_colors[1] = clamp255(g + pInten_table[1]);
+ pBlock_colors[2] = clamp255(g + pInten_table[2]);
+ pBlock_colors[3] = clamp255(g + pInten_table[3]);
+ }
+
+ static void get_block_colors5_bounds(color32* pBlock_colors, const color32& base_color5, uint32_t inten_table, uint32_t l = 0, uint32_t h = 3)
+ {
+ color32 b(base_color5);
+
+ b.r = (b.r << 3) | (b.r >> 2);
+ b.g = (b.g << 3) | (b.g >> 2);
+ b.b = (b.b << 3) | (b.b >> 2);
+
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ pBlock_colors[0].set(clamp255(b.r + pInten_table[l]), clamp255(b.g + pInten_table[l]), clamp255(b.b + pInten_table[l]), 255);
+ pBlock_colors[1].set(clamp255(b.r + pInten_table[h]), clamp255(b.g + pInten_table[h]), clamp255(b.b + pInten_table[h]), 255);
+ }
+
+ static void get_block_colors5_bounds_g(uint32_t* pBlock_colors, const color32& base_color5, uint32_t inten_table, uint32_t l = 0, uint32_t h = 3)
+ {
+ color32 b(base_color5);
+
+ b.g = (b.g << 3) | (b.g >> 2);
+
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ pBlock_colors[0] = clamp255(b.g + pInten_table[l]);
+ pBlock_colors[1] = clamp255(b.g + pInten_table[h]);
+ }
+ };
+
+ enum dxt_constants
+ {
+ cDXT1SelectorBits = 2U, cDXT1SelectorValues = 1U << cDXT1SelectorBits, cDXT1SelectorMask = cDXT1SelectorValues - 1U,
+ cDXT5SelectorBits = 3U, cDXT5SelectorValues = 1U << cDXT5SelectorBits, cDXT5SelectorMask = cDXT5SelectorValues - 1U,
+ };
+
+ static const uint8_t g_etc1_x_selector_unpack[4][256] =
+ {
+ {
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ },
+ {
+ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
+ 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3,
+ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
+ 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3,
+ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
+ 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3,
+ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
+ 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3,
+ },
+
+ {
+ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
+ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
+ 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3,
+ 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3,
+ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
+ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
+ 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3,
+ 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3,
+ },
+
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ }
+ };
+
+ struct dxt1_block
+ {
+ enum { cTotalEndpointBytes = 2, cTotalSelectorBytes = 4 };
+
+ uint8_t m_low_color[cTotalEndpointBytes];
+ uint8_t m_high_color[cTotalEndpointBytes];
+ uint8_t m_selectors[cTotalSelectorBytes];
+
+ inline void clear() { basisu::clear_obj(*this); }
+
+ inline uint32_t get_high_color() const { return m_high_color[0] | (m_high_color[1] << 8U); }
+ inline uint32_t get_low_color() const { return m_low_color[0] | (m_low_color[1] << 8U); }
+ inline void set_low_color(uint16_t c) { m_low_color[0] = static_cast<uint8_t>(c & 0xFF); m_low_color[1] = static_cast<uint8_t>((c >> 8) & 0xFF); }
+ inline void set_high_color(uint16_t c) { m_high_color[0] = static_cast<uint8_t>(c & 0xFF); m_high_color[1] = static_cast<uint8_t>((c >> 8) & 0xFF); }
+ inline uint32_t get_selector(uint32_t x, uint32_t y) const { assert((x < 4U) && (y < 4U)); return (m_selectors[y] >> (x * cDXT1SelectorBits)) & cDXT1SelectorMask; }
+ inline void set_selector(uint32_t x, uint32_t y, uint32_t val) { assert((x < 4U) && (y < 4U) && (val < 4U)); m_selectors[y] &= (~(cDXT1SelectorMask << (x * cDXT1SelectorBits))); m_selectors[y] |= (val << (x * cDXT1SelectorBits)); }
+
+ static uint16_t pack_color(const color32& color, bool scaled, uint32_t bias = 127U)
+ {
+ uint32_t r = color.r, g = color.g, b = color.b;
+ if (scaled)
+ {
+ r = (r * 31U + bias) / 255U;
+ g = (g * 63U + bias) / 255U;
+ b = (b * 31U + bias) / 255U;
+ }
+ return static_cast<uint16_t>(basisu::minimum(b, 31U) | (basisu::minimum(g, 63U) << 5U) | (basisu::minimum(r, 31U) << 11U));
+ }
+
+ static uint16_t pack_unscaled_color(uint32_t r, uint32_t g, uint32_t b) { return static_cast<uint16_t>(b | (g << 5U) | (r << 11U)); }
+ };
+
+ struct dxt_selector_range
+ {
+ uint32_t m_low;
+ uint32_t m_high;
+ };
+
+#if BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY
+ static dxt_selector_range g_etc1_to_bc7_selector_ranges[] =
+ {
+ { 0, 0 },
+ { 1, 1 },
+ { 2, 2 },
+ { 3, 3 },
+
+ { 0, 3 },
+
+ { 1, 3 },
+ { 0, 2 },
+
+ { 1, 2 },
+
+ { 2, 3 },
+ { 0, 1 },
+ };
+ const uint32_t NUM_ETC1_TO_BC7_M6_SELECTOR_RANGES = sizeof(g_etc1_to_bc7_selector_ranges) / sizeof(g_etc1_to_bc7_selector_ranges[0]);
+
+ static uint32_t g_etc1_to_bc7_m6_selector_range_index[4][4];
+
+ static const uint8_t g_etc1_to_bc7_selector_mappings[][4] =
+ {
+#if 1
+ { 5 * 0, 5 * 0, 5 * 0, 5 * 0 },
+ { 5 * 0, 5 * 0, 5 * 0, 5 * 1 },
+ { 5 * 0, 5 * 0, 5 * 0, 5 * 2 },
+ { 5 * 0, 5 * 0, 5 * 0, 5 * 3 },
+ { 5 * 0, 5 * 0, 5 * 1, 5 * 1 },
+ { 5 * 0, 5 * 0, 5 * 1, 5 * 2 },
+ { 5 * 0, 5 * 0, 5 * 1, 5 * 3 },
+ { 5 * 0, 5 * 0, 5 * 2, 5 * 2 },
+ { 5 * 0, 5 * 0, 5 * 2, 5 * 3 },
+ { 5 * 0, 5 * 0, 5 * 3, 5 * 3 },
+ { 5 * 0, 5 * 1, 5 * 1, 5 * 1 },
+ { 5 * 0, 5 * 1, 5 * 1, 5 * 2 },
+ { 5 * 0, 5 * 1, 5 * 1, 5 * 3 },
+ { 5 * 0, 5 * 1, 5 * 2, 5 * 2 },
+ { 5 * 0, 5 * 1, 5 * 2, 5 * 3 },
+ { 5 * 0, 5 * 1, 5 * 3, 5 * 3 },
+ { 5 * 0, 5 * 2, 5 * 2, 5 * 2 },
+ { 5 * 0, 5 * 2, 5 * 2, 5 * 3 },
+ { 5 * 0, 5 * 2, 5 * 3, 5 * 3 },
+ { 5 * 0, 5 * 3, 5 * 3, 5 * 3 },
+ { 5 * 1, 5 * 1, 5 * 1, 5 * 1 },
+ { 5 * 1, 5 * 1, 5 * 1, 5 * 2 },
+ { 5 * 1, 5 * 1, 5 * 1, 5 * 3 },
+ { 5 * 1, 5 * 1, 5 * 2, 5 * 2 },
+ { 5 * 1, 5 * 1, 5 * 2, 5 * 3 },
+ { 5 * 1, 5 * 1, 5 * 3, 5 * 3 },
+ { 5 * 1, 5 * 2, 5 * 2, 5 * 2 },
+ { 5 * 1, 5 * 2, 5 * 2, 5 * 3 },
+ { 5 * 1, 5 * 2, 5 * 3, 5 * 3 },
+ { 5 * 1, 5 * 3, 5 * 3, 5 * 3 },
+ { 5 * 2, 5 * 2, 5 * 2, 5 * 2 },
+ { 5 * 2, 5 * 2, 5 * 2, 5 * 3 },
+ { 5 * 2, 5 * 2, 5 * 3, 5 * 3 },
+ { 5 * 2, 5 * 3, 5 * 3, 5 * 3 },
+ { 5 * 3, 5 * 3, 5 * 3, 5 * 3 },
+
+ { 0, 1, 2, 3 },
+ { 0, 0, 1, 1 },
+ { 0, 0, 0, 1 },
+ { 0, 2, 4, 6 },
+ { 0, 3, 6, 9 },
+ { 0, 4, 8, 12 },
+
+ { 0, 4, 9, 15 },
+ { 0, 6, 11, 15 },
+
+ { 1, 2, 3, 4 },
+ { 1, 3, 5, 7 },
+
+ { 1, 8, 8, 14 },
+#else
+ { 5 * 0, 5 * 0, 5 * 1, 5 * 1 },
+ { 5 * 0, 5 * 0, 5 * 1, 5 * 2 },
+ { 5 * 0, 5 * 0, 5 * 1, 5 * 3 },
+ { 5 * 0, 5 * 0, 5 * 2, 5 * 3 },
+ { 5 * 0, 5 * 1, 5 * 1, 5 * 1 },
+ { 5 * 0, 5 * 1, 5 * 2, 5 * 2 },
+ { 5 * 0, 5 * 1, 5 * 2, 5 * 3 },
+ { 5 * 0, 5 * 2, 5 * 3, 5 * 3 },
+ { 5 * 1, 5 * 2, 5 * 2, 5 * 2 },
+#endif
+ { 5 * 1, 5 * 2, 5 * 3, 5 * 3 },
+ { 8, 8, 8, 8 },
+ };
+ const uint32_t NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS = sizeof(g_etc1_to_bc7_selector_mappings) / sizeof(g_etc1_to_bc7_selector_mappings[0]);
+
+ static uint8_t g_etc1_to_bc7_selector_mappings_inv[NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS][4];
+
+ // encoding from LSB to MSB: low8, high8, error16, size is [32*8][NUM_ETC1_TO_BC7_M6_SELECTOR_RANGES][NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS]
+ extern const uint32_t* g_etc1_to_bc7_m6_table[];
+
+ const uint16_t s_bptc_table_aWeight4[16] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
+
+#if BASISD_WRITE_NEW_BC7_TABLES
+ static void create_etc1_to_bc7_m6_conversion_table()
+ {
+ FILE* pFile = NULL;
+
+ pFile = fopen("basisu_decoder_tables_bc7_m6.inc", "w");
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ fprintf(pFile, "static const uint32_t g_etc1_to_bc7_m6_table%u[] = {\n", g + inten * 32);
+ uint32_t n = 0;
+
+ for (uint32_t sr = 0; sr < NUM_ETC1_TO_BC7_M6_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1_to_bc7_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1_to_bc7_selector_ranges[sr].m_high;
+
+ for (uint32_t m = 0; m < NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 127; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 127; lo++)
+ {
+ uint32_t bc7_block_colors[16];
+
+ bc7_block_colors[0] = lo << 1;
+ bc7_block_colors[15] = (hi << 1) | 1;
+
+ for (uint32_t i = 1; i < 15; i++)
+ bc7_block_colors[i] = (bc7_block_colors[0] * (64 - s_bptc_table_aWeight4[i]) + bc7_block_colors[15] * s_bptc_table_aWeight4[i] + 32) >> 6;
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = (int)block_colors[s].g - (int)bc7_block_colors[g_etc1_to_bc7_selector_mappings[m][s]];
+
+ total_err += err * err;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ } // lo
+
+ } // hi
+
+ best_err = basisu::minimum<uint32_t>(best_err, 0xFFFF);
+
+ const uint32_t index = (g + inten * 32) * (NUM_ETC1_TO_BC7_M6_SELECTOR_RANGES * NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS) + (sr * NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS) + m;
+
+ uint32_t v = best_err | (best_lo << 18) | (best_hi << 25);
+
+ fprintf(pFile, "0x%X,", v);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+
+ } // m
+ } // sr
+
+ fprintf(pFile, "};\n");
+
+ } // g
+ } // inten
+
+ fprintf(pFile, "const uint32_t *g_etc1_to_bc7_m6_table[] = {\n");
+
+ for (uint32_t i = 0; i < 32 * 8; i++)
+ {
+ fprintf(pFile, "g_etc1_to_bc7_m6_table%u, ", i);
+ if ((i & 15) == 15)
+ fprintf(pFile, "\n");
+ }
+
+ fprintf(pFile, "};\n");
+ fclose(pFile);
+ }
+#endif
+#endif
+
+ struct etc1_to_dxt1_56_solution
+ {
+ uint8_t m_lo;
+ uint8_t m_hi;
+ uint16_t m_err;
+ };
+
+#if BASISD_SUPPORT_DXT1
+ static dxt_selector_range g_etc1_to_dxt1_selector_ranges[] =
+ {
+ { 0, 3 },
+
+ { 1, 3 },
+ { 0, 2 },
+
+ { 1, 2 },
+
+ { 2, 3 },
+ { 0, 1 },
+ };
+
+ const uint32_t NUM_ETC1_TO_DXT1_SELECTOR_RANGES = sizeof(g_etc1_to_dxt1_selector_ranges) / sizeof(g_etc1_to_dxt1_selector_ranges[0]);
+
+ static uint32_t g_etc1_to_dxt1_selector_range_index[4][4];
+
+ const uint32_t NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS = 10;
+ static const uint8_t g_etc1_to_dxt1_selector_mappings[NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS][4] =
+ {
+ { 0, 0, 1, 1 },
+ { 0, 0, 1, 2 },
+ { 0, 0, 1, 3 },
+ { 0, 0, 2, 3 },
+ { 0, 1, 1, 1 },
+ { 0, 1, 2, 2 },
+ { 0, 1, 2, 3 },
+ { 0, 2, 3, 3 },
+ { 1, 2, 2, 2 },
+ { 1, 2, 3, 3 },
+ };
+
+ static uint8_t g_etc1_to_dxt1_selector_mappings_raw_dxt1_256[NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS][256];
+ static uint8_t g_etc1_to_dxt1_selector_mappings_raw_dxt1_inv_256[NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS][256];
+
+ static const etc1_to_dxt1_56_solution g_etc1_to_dxt_6[32 * 8 * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS * NUM_ETC1_TO_DXT1_SELECTOR_RANGES] = {
+#include "basisu_transcoder_tables_dxt1_6.inc"
+ };
+
+ static const etc1_to_dxt1_56_solution g_etc1_to_dxt_5[32 * 8 * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS * NUM_ETC1_TO_DXT1_SELECTOR_RANGES] = {
+#include "basisu_transcoder_tables_dxt1_5.inc"
+ };
+
+ // First saw the idea for optimal BC1 single-color block encoding using lookup tables in ryg_dxt.
+ struct bc1_match_entry
+ {
+ uint8_t m_hi;
+ uint8_t m_lo;
+ };
+ static bc1_match_entry g_bc1_match5_equals_1[256], g_bc1_match6_equals_1[256]; // selector 1, allow equals hi/lo
+ static bc1_match_entry g_bc1_match5_equals_0[256], g_bc1_match6_equals_0[256]; // selector 0, allow equals hi/lo
+
+ static void prepare_bc1_single_color_table(bc1_match_entry* pTable, const uint8_t* pExpand, int size0, int size1, int sel)
+ {
+ for (int i = 0; i < 256; i++)
+ {
+ int lowest_e = 256;
+ for (int lo = 0; lo < size0; lo++)
+ {
+ for (int hi = 0; hi < size1; hi++)
+ {
+ const int lo_e = pExpand[lo], hi_e = pExpand[hi];
+ int e;
+
+ if (sel == 1)
+ {
+ // Selector 1
+ e = abs(((hi_e * 2 + lo_e) / 3) - i) + ((abs(hi_e - lo_e) >> 5));
+ }
+ else
+ {
+ assert(sel == 0);
+
+ // Selector 0
+ e = abs(hi_e - i);
+ }
+
+ if (e < lowest_e)
+ {
+ pTable[i].m_hi = static_cast<uint8_t>(hi);
+ pTable[i].m_lo = static_cast<uint8_t>(lo);
+
+ lowest_e = e;
+ }
+
+ } // hi
+ } // lo
+ }
+ }
+#endif // BASISD_SUPPORT_DXT1
+
+#if BASISD_WRITE_NEW_DXT1_TABLES
+ static void create_etc1_to_dxt1_5_conversion_table()
+ {
+ FILE* pFile = nullptr;
+ fopen_s(&pFile, "basisu_transcoder_tables_dxt1_5.inc", "w");
+
+ uint32_t n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1_TO_DXT1_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1_to_dxt1_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1_to_dxt1_selector_ranges[sr].m_high;
+
+ for (uint32_t m = 0; m < NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 31; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 31; lo++)
+ {
+ //if (lo == hi) continue;
+
+ uint32_t colors[4];
+
+ colors[0] = (lo << 3) | (lo >> 2);
+ colors[3] = (hi << 3) | (hi >> 2);
+
+ colors[1] = (colors[0] * 2 + colors[3]) / 3;
+ colors[2] = (colors[3] * 2 + colors[0]) / 3;
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1_to_dxt1_selector_mappings[m][s]];
+
+ total_err += err * err;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ assert(best_err <= 0xFFFF);
+
+ //table[g + inten * 32].m_solutions[sr][m].m_lo = static_cast<uint8_t>(best_lo);
+ //table[g + inten * 32].m_solutions[sr][m].m_hi = static_cast<uint8_t>(best_hi);
+ //table[g + inten * 32].m_solutions[sr][m].m_err = static_cast<uint16_t>(best_err);
+
+ //assert(best_lo != best_hi);
+ fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+ } // m
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+ }
+
+ static void create_etc1_to_dxt1_6_conversion_table()
+ {
+ FILE* pFile = nullptr;
+ fopen_s(&pFile, "basisu_transcoder_tables_dxt1_6.inc", "w");
+
+ uint32_t n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1_TO_DXT1_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1_to_dxt1_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1_to_dxt1_selector_ranges[sr].m_high;
+
+ for (uint32_t m = 0; m < NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 63; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 63; lo++)
+ {
+ //if (lo == hi) continue;
+
+ uint32_t colors[4];
+
+ colors[0] = (lo << 2) | (lo >> 4);
+ colors[3] = (hi << 2) | (hi >> 4);
+
+ colors[1] = (colors[0] * 2 + colors[3]) / 3;
+ colors[2] = (colors[3] * 2 + colors[0]) / 3;
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1_to_dxt1_selector_mappings[m][s]];
+
+ total_err += err * err;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ assert(best_err <= 0xFFFF);
+
+ //table[g + inten * 32].m_solutions[sr][m].m_lo = static_cast<uint8_t>(best_lo);
+ //table[g + inten * 32].m_solutions[sr][m].m_hi = static_cast<uint8_t>(best_hi);
+ //table[g + inten * 32].m_solutions[sr][m].m_err = static_cast<uint16_t>(best_err);
+
+ //assert(best_lo != best_hi);
+ fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+
+ } // m
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+ }
+#endif
+
+#if BASISD_SUPPORT_ETC2_EAC_A8 || BASISD_SUPPORT_ETC2_EAC_RG11
+ static const int8_t g_eac_modifier_table[16][8] =
+ {
+ { -3, -6, -9, -15, 2, 5, 8, 14 },
+ { -3, -7, -10, -13, 2, 6, 9, 12 },
+ { -2, -5, -8, -13, 1, 4, 7, 12 },
+ { -2, -4, -6, -13, 1, 3, 5, 12 },
+ { -3, -6, -8, -12, 2, 5, 7, 11 },
+ { -3, -7, -9, -11, 2, 6, 8, 10 },
+ { -4, -7, -8, -11, 3, 6, 7, 10 },
+ { -3, -5, -8, -11, 2, 4, 7, 10 },
+
+ { -2, -6, -8, -10, 1, 5, 7, 9 },
+ { -2, -5, -8, -10, 1, 4, 7, 9 },
+ { -2, -4, -8, -10, 1, 3, 7, 9 },
+ { -2, -5, -7, -10, 1, 4, 6, 9 },
+ { -3, -4, -7, -10, 2, 3, 6, 9 },
+ { -1, -2, -3, -10, 0, 1, 2, 9 }, // entry 13
+ { -4, -6, -8, -9, 3, 5, 7, 8 },
+ { -3, -5, -7, -9, 2, 4, 6, 8 }
+ };
+
+ // Used by ETC2 EAC A8 and ETC2 EAC R11/RG11.
+ struct eac_block
+ {
+ uint16_t m_base : 8;
+
+ uint16_t m_table : 4;
+ uint16_t m_multiplier : 4;
+
+ uint8_t m_selectors[6];
+
+ uint32_t get_selector(uint32_t x, uint32_t y) const
+ {
+ assert((x < 4) && (y < 4));
+
+ const uint32_t ofs = 45 - (y + x * 4) * 3;
+
+ const uint64_t pixels = get_selector_bits();
+
+ return (pixels >> ofs) & 7;
+ }
+
+ void set_selector(uint32_t x, uint32_t y, uint32_t s)
+ {
+ assert((x < 4) && (y < 4) && (s < 8));
+
+ const uint32_t ofs = 45 - (y + x * 4) * 3;
+
+ uint64_t pixels = get_selector_bits();
+
+ pixels &= ~(7ULL << ofs);
+ pixels |= (static_cast<uint64_t>(s) << ofs);
+
+ set_selector_bits(pixels);
+ }
+
+ uint64_t get_selector_bits() const
+ {
+ uint64_t pixels = ((uint64_t)m_selectors[0] << 40) | ((uint64_t)m_selectors[1] << 32) |
+ ((uint64_t)m_selectors[2] << 24) |
+ ((uint64_t)m_selectors[3] << 16) | ((uint64_t)m_selectors[4] << 8) | m_selectors[5];
+ return pixels;
+ }
+
+ void set_selector_bits(uint64_t pixels)
+ {
+ m_selectors[0] = (uint8_t)(pixels >> 40);
+ m_selectors[1] = (uint8_t)(pixels >> 32);
+ m_selectors[2] = (uint8_t)(pixels >> 24);
+ m_selectors[3] = (uint8_t)(pixels >> 16);
+ m_selectors[4] = (uint8_t)(pixels >> 8);
+ m_selectors[5] = (uint8_t)(pixels);
+ }
+ };
+
+ static const dxt_selector_range s_etc2_eac_selector_ranges[] =
+ {
+ { 0, 3 },
+
+ { 1, 3 },
+ { 0, 2 },
+
+ { 1, 2 },
+ };
+
+ const uint32_t NUM_ETC2_EAC_SELECTOR_RANGES = sizeof(s_etc2_eac_selector_ranges) / sizeof(s_etc2_eac_selector_ranges[0]);
+
+ struct etc1_g_to_eac_conversion
+ {
+ uint8_t m_base;
+ uint8_t m_table_mul; // mul*16+table
+ uint16_t m_trans; // translates ETC1 selectors to ETC2_EAC_A8
+ };
+#endif // BASISD_SUPPORT_ETC2_EAC_A8 || BASISD_SUPPORT_ETC2_EAC_RG11
+
+#if BASISD_SUPPORT_ETC2_EAC_A8
+
+#if BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES
+ struct pack_eac_a8_results
+ {
+ uint32_t m_base;
+ uint32_t m_table;
+ uint32_t m_multiplier;
+ std::vector<uint8_t> m_selectors;
+ std::vector<uint8_t> m_selectors_temp;
+ };
+
+ static uint64_t pack_eac_a8_exhaustive(pack_eac_a8_results& results, const uint8_t* pPixels, uint32_t num_pixels)
+ {
+ results.m_selectors.resize(num_pixels);
+ results.m_selectors_temp.resize(num_pixels);
+
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t base_color = 0; base_color < 256; base_color++)
+ {
+ for (uint32_t multiplier = 1; multiplier < 16; multiplier++)
+ {
+ for (uint32_t table = 0; table < 16; table++)
+ {
+ uint64_t total_err = 0;
+
+ for (uint32_t i = 0; i < num_pixels; i++)
+ {
+ const int a = pPixels[i];
+
+ uint32_t best_s_err = UINT32_MAX;
+ uint32_t best_s = 0;
+ for (uint32_t s = 0; s < 8; s++)
+ {
+ int v = (int)multiplier * g_eac_modifier_table[table][s] + (int)base_color;
+ if (v < 0)
+ v = 0;
+ else if (v > 255)
+ v = 255;
+
+ uint32_t err = abs(a - v);
+ if (err < best_s_err)
+ {
+ best_s_err = err;
+ best_s = s;
+ }
+ }
+
+ results.m_selectors_temp[i] = static_cast<uint8_t>(best_s);
+
+ total_err += best_s_err * best_s_err;
+ if (total_err >= best_err)
+ break;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ results.m_base = base_color;
+ results.m_multiplier = multiplier;
+ results.m_table = table;
+ results.m_selectors.swap(results.m_selectors_temp);
+ }
+
+ } // table
+
+ } // multiplier
+
+ } // base_color
+
+ return best_err;
+ }
+#endif // BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES
+
+ static
+#if !BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES
+ const
+#endif
+ etc1_g_to_eac_conversion s_etc1_g_to_etc2_a8[32 * 8][NUM_ETC2_EAC_SELECTOR_RANGES] =
+ {
+ { { 0,1,3328 },{ 0,1,3328 },{ 0,1,256 },{ 0,1,256 } },
+ { { 0,226,3936 },{ 0,226,3936 },{ 0,81,488 },{ 0,81,488 } },
+ { { 6,178,4012 },{ 6,178,4008 },{ 0,146,501 },{ 0,130,496 } },
+ { { 14,178,4012 },{ 14,178,4008 },{ 8,146,501 },{ 6,82,496 } },
+ { { 23,178,4012 },{ 23,178,4008 },{ 17,146,501 },{ 3,228,496 } },
+ { { 31,178,4012 },{ 31,178,4008 },{ 25,146,501 },{ 11,228,496 } },
+ { { 39,178,4012 },{ 39,178,4008 },{ 33,146,501 },{ 19,228,496 } },
+ { { 47,178,4012 },{ 47,178,4008 },{ 41,146,501 },{ 27,228,496 } },
+ { { 56,178,4012 },{ 56,178,4008 },{ 50,146,501 },{ 36,228,496 } },
+ { { 64,178,4012 },{ 64,178,4008 },{ 58,146,501 },{ 44,228,496 } },
+ { { 72,178,4012 },{ 72,178,4008 },{ 66,146,501 },{ 52,228,496 } },
+ { { 80,178,4012 },{ 80,178,4008 },{ 74,146,501 },{ 60,228,496 } },
+ { { 89,178,4012 },{ 89,178,4008 },{ 83,146,501 },{ 69,228,496 } },
+ { { 97,178,4012 },{ 97,178,4008 },{ 91,146,501 },{ 77,228,496 } },
+ { { 105,178,4012 },{ 105,178,4008 },{ 99,146,501 },{ 85,228,496 } },
+ { { 113,178,4012 },{ 113,178,4008 },{ 107,146,501 },{ 93,228,496 } },
+ { { 122,178,4012 },{ 122,178,4008 },{ 116,146,501 },{ 102,228,496 } },
+ { { 130,178,4012 },{ 130,178,4008 },{ 124,146,501 },{ 110,228,496 } },
+ { { 138,178,4012 },{ 138,178,4008 },{ 132,146,501 },{ 118,228,496 } },
+ { { 146,178,4012 },{ 146,178,4008 },{ 140,146,501 },{ 126,228,496 } },
+ { { 155,178,4012 },{ 155,178,4008 },{ 149,146,501 },{ 135,228,496 } },
+ { { 163,178,4012 },{ 163,178,4008 },{ 157,146,501 },{ 143,228,496 } },
+ { { 171,178,4012 },{ 171,178,4008 },{ 165,146,501 },{ 151,228,496 } },
+ { { 179,178,4012 },{ 179,178,4008 },{ 173,146,501 },{ 159,228,496 } },
+ { { 188,178,4012 },{ 188,178,4008 },{ 182,146,501 },{ 168,228,496 } },
+ { { 196,178,4012 },{ 196,178,4008 },{ 190,146,501 },{ 176,228,496 } },
+ { { 204,178,4012 },{ 204,178,4008 },{ 198,146,501 },{ 184,228,496 } },
+ { { 212,178,4012 },{ 212,178,4008 },{ 206,146,501 },{ 192,228,496 } },
+ { { 221,178,4012 },{ 221,178,4008 },{ 215,146,501 },{ 201,228,496 } },
+ { { 229,178,4012 },{ 229,178,4008 },{ 223,146,501 },{ 209,228,496 } },
+ { { 235,66,4012 },{ 221,100,4008 },{ 231,146,501 },{ 217,228,496 } },
+ { { 211,102,4085 },{ 118,31,4080 },{ 211,102,501 },{ 118,31,496 } },
+ { { 1,2,3328 },{ 1,2,3328 },{ 0,1,320 },{ 0,1,320 } },
+ { { 7,162,3905 },{ 7,162,3904 },{ 1,17,480 },{ 1,17,480 } },
+ { { 15,162,3906 },{ 15,162,3904 },{ 1,117,352 },{ 1,117,352 } },
+ { { 23,162,3906 },{ 23,162,3904 },{ 5,34,500 },{ 4,53,424 } },
+ { { 32,162,3906 },{ 32,162,3904 },{ 14,34,500 },{ 3,69,424 } },
+ { { 40,162,3906 },{ 40,162,3904 },{ 22,34,500 },{ 1,133,496 } },
+ { { 48,162,3906 },{ 48,162,3904 },{ 30,34,500 },{ 4,85,496 } },
+ { { 56,162,3906 },{ 56,162,3904 },{ 38,34,500 },{ 12,85,496 } },
+ { { 65,162,3906 },{ 65,162,3904 },{ 47,34,500 },{ 1,106,424 } },
+ { { 73,162,3906 },{ 73,162,3904 },{ 55,34,500 },{ 9,106,424 } },
+ { { 81,162,3906 },{ 81,162,3904 },{ 63,34,500 },{ 7,234,496 } },
+ { { 89,162,3906 },{ 89,162,3904 },{ 71,34,500 },{ 15,234,496 } },
+ { { 98,162,3906 },{ 98,162,3904 },{ 80,34,500 },{ 24,234,496 } },
+ { { 106,162,3906 },{ 106,162,3904 },{ 88,34,500 },{ 32,234,496 } },
+ { { 114,162,3906 },{ 114,162,3904 },{ 96,34,500 },{ 40,234,496 } },
+ { { 122,162,3906 },{ 122,162,3904 },{ 104,34,500 },{ 48,234,496 } },
+ { { 131,162,3906 },{ 131,162,3904 },{ 113,34,500 },{ 57,234,496 } },
+ { { 139,162,3906 },{ 139,162,3904 },{ 121,34,500 },{ 65,234,496 } },
+ { { 147,162,3906 },{ 147,162,3904 },{ 129,34,500 },{ 73,234,496 } },
+ { { 155,162,3906 },{ 155,162,3904 },{ 137,34,500 },{ 81,234,496 } },
+ { { 164,162,3906 },{ 164,162,3904 },{ 146,34,500 },{ 90,234,496 } },
+ { { 172,162,3906 },{ 172,162,3904 },{ 154,34,500 },{ 98,234,496 } },
+ { { 180,162,3906 },{ 180,162,3904 },{ 162,34,500 },{ 106,234,496 } },
+ { { 188,162,3906 },{ 188,162,3904 },{ 170,34,500 },{ 114,234,496 } },
+ { { 197,162,3906 },{ 197,162,3904 },{ 179,34,500 },{ 123,234,496 } },
+ { { 205,162,3906 },{ 205,162,3904 },{ 187,34,500 },{ 131,234,496 } },
+ { { 213,162,3906 },{ 213,162,3904 },{ 195,34,500 },{ 139,234,496 } },
+ { { 221,162,3906 },{ 221,162,3904 },{ 203,34,500 },{ 147,234,496 } },
+ { { 230,162,3906 },{ 230,162,3904 },{ 212,34,500 },{ 156,234,496 } },
+ { { 238,162,3906 },{ 174,106,4008 },{ 220,34,500 },{ 164,234,496 } },
+ { { 240,178,4001 },{ 182,106,4008 },{ 228,34,500 },{ 172,234,496 } },
+ { { 166,108,4085 },{ 115,31,4080 },{ 166,108,501 },{ 115,31,496 } },
+ { { 1,68,3328 },{ 1,68,3328 },{ 0,17,384 },{ 0,17,384 } },
+ { { 1,148,3904 },{ 1,148,3904 },{ 1,2,384 },{ 1,2,384 } },
+ { { 21,18,3851 },{ 21,18,3848 },{ 1,50,488 },{ 1,50,488 } },
+ { { 27,195,3851 },{ 29,18,3848 },{ 0,67,488 },{ 0,67,488 } },
+ { { 34,195,3907 },{ 38,18,3848 },{ 20,66,482 },{ 0,3,496 } },
+ { { 42,195,3907 },{ 46,18,3848 },{ 28,66,482 },{ 2,6,424 } },
+ { { 50,195,3907 },{ 54,18,3848 },{ 36,66,482 },{ 4,22,424 } },
+ { { 58,195,3907 },{ 62,18,3848 },{ 44,66,482 },{ 3,73,424 } },
+ { { 67,195,3907 },{ 71,18,3848 },{ 53,66,482 },{ 3,22,496 } },
+ { { 75,195,3907 },{ 79,18,3848 },{ 61,66,482 },{ 2,137,496 } },
+ { { 83,195,3907 },{ 87,18,3848 },{ 69,66,482 },{ 1,89,496 } },
+ { { 91,195,3907 },{ 95,18,3848 },{ 77,66,482 },{ 9,89,496 } },
+ { { 100,195,3907 },{ 104,18,3848 },{ 86,66,482 },{ 18,89,496 } },
+ { { 108,195,3907 },{ 112,18,3848 },{ 94,66,482 },{ 26,89,496 } },
+ { { 116,195,3907 },{ 120,18,3848 },{ 102,66,482 },{ 34,89,496 } },
+ { { 124,195,3907 },{ 128,18,3848 },{ 110,66,482 },{ 42,89,496 } },
+ { { 133,195,3907 },{ 137,18,3848 },{ 119,66,482 },{ 51,89,496 } },
+ { { 141,195,3907 },{ 145,18,3848 },{ 127,66,482 },{ 59,89,496 } },
+ { { 149,195,3907 },{ 153,18,3848 },{ 135,66,482 },{ 67,89,496 } },
+ { { 157,195,3907 },{ 161,18,3848 },{ 143,66,482 },{ 75,89,496 } },
+ { { 166,195,3907 },{ 170,18,3848 },{ 152,66,482 },{ 84,89,496 } },
+ { { 174,195,3907 },{ 178,18,3848 },{ 160,66,482 },{ 92,89,496 } },
+ { { 182,195,3907 },{ 186,18,3848 },{ 168,66,482 },{ 100,89,496 } },
+ { { 190,195,3907 },{ 194,18,3848 },{ 176,66,482 },{ 108,89,496 } },
+ { { 199,195,3907 },{ 203,18,3848 },{ 185,66,482 },{ 117,89,496 } },
+ { { 207,195,3907 },{ 211,18,3848 },{ 193,66,482 },{ 125,89,496 } },
+ { { 215,195,3907 },{ 219,18,3848 },{ 201,66,482 },{ 133,89,496 } },
+ { { 223,195,3907 },{ 227,18,3848 },{ 209,66,482 },{ 141,89,496 } },
+ { { 231,195,3907 },{ 168,89,4008 },{ 218,66,482 },{ 150,89,496 } },
+ { { 236,18,3907 },{ 176,89,4008 },{ 226,66,482 },{ 158,89,496 } },
+ { { 158,90,4085 },{ 103,31,4080 },{ 158,90,501 },{ 103,31,496 } },
+ { { 166,90,4085 },{ 111,31,4080 },{ 166,90,501 },{ 111,31,496 } },
+ { { 0,70,3328 },{ 0,70,3328 },{ 0,45,256 },{ 0,45,256 } },
+ { { 0,117,3904 },{ 0,117,3904 },{ 0,35,384 },{ 0,35,384 } },
+ { { 13,165,3905 },{ 13,165,3904 },{ 3,221,416 },{ 3,221,416 } },
+ { { 21,165,3906 },{ 21,165,3904 },{ 11,221,416 },{ 11,221,416 } },
+ { { 30,165,3906 },{ 30,165,3904 },{ 7,61,352 },{ 7,61,352 } },
+ { { 38,165,3906 },{ 38,165,3904 },{ 2,125,352 },{ 2,125,352 } },
+ { { 46,165,3906 },{ 46,165,3904 },{ 2,37,500 },{ 10,125,352 } },
+ { { 54,165,3906 },{ 54,165,3904 },{ 10,37,500 },{ 5,61,424 } },
+ { { 63,165,3906 },{ 63,165,3904 },{ 19,37,500 },{ 1,189,424 } },
+ { { 4,254,4012 },{ 71,165,3904 },{ 27,37,500 },{ 9,189,424 } },
+ { { 12,254,4012 },{ 79,165,3904 },{ 35,37,500 },{ 4,77,424 } },
+ { { 20,254,4012 },{ 87,165,3904 },{ 43,37,500 },{ 12,77,424 } },
+ { { 29,254,4012 },{ 96,165,3904 },{ 52,37,500 },{ 8,93,424 } },
+ { { 37,254,4012 },{ 104,165,3904 },{ 60,37,500 },{ 3,141,496 } },
+ { { 45,254,4012 },{ 112,165,3904 },{ 68,37,500 },{ 11,141,496 } },
+ { { 53,254,4012 },{ 120,165,3904 },{ 76,37,500 },{ 6,93,496 } },
+ { { 62,254,4012 },{ 129,165,3904 },{ 85,37,500 },{ 15,93,496 } },
+ { { 70,254,4012 },{ 137,165,3904 },{ 93,37,500 },{ 23,93,496 } },
+ { { 78,254,4012 },{ 145,165,3904 },{ 101,37,500 },{ 31,93,496 } },
+ { { 86,254,4012 },{ 153,165,3904 },{ 109,37,500 },{ 39,93,496 } },
+ { { 95,254,4012 },{ 162,165,3904 },{ 118,37,500 },{ 48,93,496 } },
+ { { 103,254,4012 },{ 170,165,3904 },{ 126,37,500 },{ 56,93,496 } },
+ { { 111,254,4012 },{ 178,165,3904 },{ 134,37,500 },{ 64,93,496 } },
+ { { 119,254,4012 },{ 186,165,3904 },{ 142,37,500 },{ 72,93,496 } },
+ { { 128,254,4012 },{ 195,165,3904 },{ 151,37,500 },{ 81,93,496 } },
+ { { 136,254,4012 },{ 203,165,3904 },{ 159,37,500 },{ 89,93,496 } },
+ { { 212,165,3906 },{ 136,77,4008 },{ 167,37,500 },{ 97,93,496 } },
+ { { 220,165,3394 },{ 131,93,4008 },{ 175,37,500 },{ 105,93,496 } },
+ { { 214,181,4001 },{ 140,93,4008 },{ 184,37,500 },{ 114,93,496 } },
+ { { 222,181,4001 },{ 148,93,4008 },{ 192,37,500 },{ 122,93,496 } },
+ { { 114,95,4085 },{ 99,31,4080 },{ 114,95,501 },{ 99,31,496 } },
+ { { 122,95,4085 },{ 107,31,4080 },{ 122,95,501 },{ 107,31,496 } },
+ { { 0,102,3840 },{ 0,102,3840 },{ 0,18,384 },{ 0,18,384 } },
+ { { 5,167,3904 },{ 5,167,3904 },{ 0,13,256 },{ 0,13,256 } },
+ { { 4,54,3968 },{ 4,54,3968 },{ 1,67,448 },{ 1,67,448 } },
+ { { 30,198,3850 },{ 30,198,3848 },{ 0,3,480 },{ 0,3,480 } },
+ { { 39,198,3850 },{ 39,198,3848 },{ 3,52,488 },{ 3,52,488 } },
+ { { 47,198,3851 },{ 47,198,3848 },{ 3,4,488 },{ 3,4,488 } },
+ { { 55,198,3851 },{ 55,198,3848 },{ 1,70,488 },{ 1,70,488 } },
+ { { 54,167,3906 },{ 63,198,3848 },{ 3,22,488 },{ 3,22,488 } },
+ { { 62,167,3906 },{ 72,198,3848 },{ 24,118,488 },{ 0,6,496 } },
+ { { 70,167,3906 },{ 80,198,3848 },{ 32,118,488 },{ 2,89,488 } },
+ { { 78,167,3906 },{ 88,198,3848 },{ 40,118,488 },{ 1,73,496 } },
+ { { 86,167,3906 },{ 96,198,3848 },{ 48,118,488 },{ 0,28,424 } },
+ { { 95,167,3906 },{ 105,198,3848 },{ 57,118,488 },{ 9,28,424 } },
+ { { 103,167,3906 },{ 113,198,3848 },{ 65,118,488 },{ 5,108,496 } },
+ { { 111,167,3906 },{ 121,198,3848 },{ 73,118,488 },{ 13,108,496 } },
+ { { 119,167,3906 },{ 129,198,3848 },{ 81,118,488 },{ 21,108,496 } },
+ { { 128,167,3906 },{ 138,198,3848 },{ 90,118,488 },{ 6,28,496 } },
+ { { 136,167,3906 },{ 146,198,3848 },{ 98,118,488 },{ 14,28,496 } },
+ { { 144,167,3906 },{ 154,198,3848 },{ 106,118,488 },{ 22,28,496 } },
+ { { 152,167,3906 },{ 162,198,3848 },{ 114,118,488 },{ 30,28,496 } },
+ { { 161,167,3906 },{ 171,198,3848 },{ 123,118,488 },{ 39,28,496 } },
+ { { 169,167,3906 },{ 179,198,3848 },{ 131,118,488 },{ 47,28,496 } },
+ { { 177,167,3906 },{ 187,198,3848 },{ 139,118,488 },{ 55,28,496 } },
+ { { 185,167,3906 },{ 195,198,3848 },{ 147,118,488 },{ 63,28,496 } },
+ { { 194,167,3906 },{ 120,12,4008 },{ 156,118,488 },{ 72,28,496 } },
+ { { 206,198,3907 },{ 116,28,4008 },{ 164,118,488 },{ 80,28,496 } },
+ { { 214,198,3907 },{ 124,28,4008 },{ 172,118,488 },{ 88,28,496 } },
+ { { 222,198,3395 },{ 132,28,4008 },{ 180,118,488 },{ 96,28,496 } },
+ { { 207,134,4001 },{ 141,28,4008 },{ 189,118,488 },{ 105,28,496 } },
+ { { 95,30,4085 },{ 86,31,4080 },{ 95,30,501 },{ 86,31,496 } },
+ { { 103,30,4085 },{ 94,31,4080 },{ 103,30,501 },{ 94,31,496 } },
+ { { 111,30,4085 },{ 102,31,4080 },{ 111,30,501 },{ 102,31,496 } },
+ { { 0,104,3840 },{ 0,104,3840 },{ 0,18,448 },{ 0,18,448 } },
+ { { 4,39,3904 },{ 4,39,3904 },{ 0,4,384 },{ 0,4,384 } },
+ { { 0,56,3968 },{ 0,56,3968 },{ 0,84,448 },{ 0,84,448 } },
+ { { 6,110,3328 },{ 6,110,3328 },{ 0,20,448 },{ 0,20,448 } },
+ { { 41,200,3850 },{ 41,200,3848 },{ 1,4,480 },{ 1,4,480 } },
+ { { 49,200,3850 },{ 49,200,3848 },{ 1,8,416 },{ 1,8,416 } },
+ { { 57,200,3851 },{ 57,200,3848 },{ 1,38,488 },{ 1,38,488 } },
+ { { 65,200,3851 },{ 65,200,3848 },{ 1,120,488 },{ 1,120,488 } },
+ { { 74,200,3851 },{ 74,200,3848 },{ 2,72,488 },{ 2,72,488 } },
+ { { 69,6,3907 },{ 82,200,3848 },{ 2,24,488 },{ 2,24,488 } },
+ { { 77,6,3907 },{ 90,200,3848 },{ 26,120,488 },{ 10,24,488 } },
+ { { 97,63,3330 },{ 98,200,3848 },{ 34,120,488 },{ 2,8,496 } },
+ { { 106,63,3330 },{ 107,200,3848 },{ 43,120,488 },{ 3,92,488 } },
+ { { 114,63,3330 },{ 115,200,3848 },{ 51,120,488 },{ 11,92,488 } },
+ { { 122,63,3330 },{ 123,200,3848 },{ 59,120,488 },{ 7,76,496 } },
+ { { 130,63,3330 },{ 131,200,3848 },{ 67,120,488 },{ 15,76,496 } },
+ { { 139,63,3330 },{ 140,200,3848 },{ 76,120,488 },{ 24,76,496 } },
+ { { 147,63,3330 },{ 148,200,3848 },{ 84,120,488 },{ 32,76,496 } },
+ { { 155,63,3330 },{ 156,200,3848 },{ 92,120,488 },{ 40,76,496 } },
+ { { 163,63,3330 },{ 164,200,3848 },{ 100,120,488 },{ 48,76,496 } },
+ { { 172,63,3330 },{ 173,200,3848 },{ 109,120,488 },{ 57,76,496 } },
+ { { 184,6,3851 },{ 181,200,3848 },{ 117,120,488 },{ 65,76,496 } },
+ { { 192,6,3851 },{ 133,28,3936 },{ 125,120,488 },{ 73,76,496 } },
+ { { 189,200,3907 },{ 141,28,3936 },{ 133,120,488 },{ 81,76,496 } },
+ { { 198,200,3907 },{ 138,108,4000 },{ 142,120,488 },{ 90,76,496 } },
+ { { 206,200,3907 },{ 146,108,4000 },{ 150,120,488 },{ 98,76,496 } },
+ { { 214,200,3395 },{ 154,108,4000 },{ 158,120,488 },{ 106,76,496 } },
+ { { 190,136,4001 },{ 162,108,4000 },{ 166,120,488 },{ 114,76,496 } },
+ { { 123,30,4076 },{ 87,15,4080 },{ 123,30,492 },{ 87,15,496 } },
+ { { 117,110,4084 },{ 80,31,4080 },{ 117,110,500 },{ 80,31,496 } },
+ { { 125,110,4084 },{ 88,31,4080 },{ 125,110,500 },{ 88,31,496 } },
+ { { 133,110,4084 },{ 96,31,4080 },{ 133,110,500 },{ 96,31,496 } },
+ { { 9,56,3904 },{ 9,56,3904 },{ 0,67,448 },{ 0,67,448 } },
+ { { 1,8,3904 },{ 1,8,3904 },{ 1,84,448 },{ 1,84,448 } },
+ { { 1,124,3904 },{ 1,124,3904 },{ 0,39,384 },{ 0,39,384 } },
+ { { 9,124,3904 },{ 9,124,3904 },{ 1,4,448 },{ 1,4,448 } },
+ { { 6,76,3904 },{ 6,76,3904 },{ 0,70,448 },{ 0,70,448 } },
+ { { 62,6,3859 },{ 62,6,3856 },{ 2,38,480 },{ 2,38,480 } },
+ { { 70,6,3859 },{ 70,6,3856 },{ 5,43,416 },{ 5,43,416 } },
+ { { 78,6,3859 },{ 78,6,3856 },{ 2,11,416 },{ 2,11,416 } },
+ { { 87,6,3859 },{ 87,6,3856 },{ 0,171,488 },{ 0,171,488 } },
+ { { 67,8,3906 },{ 95,6,3856 },{ 8,171,488 },{ 8,171,488 } },
+ { { 75,8,3907 },{ 103,6,3856 },{ 5,123,488 },{ 5,123,488 } },
+ { { 83,8,3907 },{ 111,6,3856 },{ 2,75,488 },{ 2,75,488 } },
+ { { 92,8,3907 },{ 120,6,3856 },{ 0,27,488 },{ 0,27,488 } },
+ { { 100,8,3907 },{ 128,6,3856 },{ 8,27,488 },{ 8,27,488 } },
+ { { 120,106,3843 },{ 136,6,3856 },{ 100,6,387 },{ 16,27,488 } },
+ { { 128,106,3843 },{ 144,6,3856 },{ 108,6,387 },{ 2,11,496 } },
+ { { 137,106,3843 },{ 153,6,3856 },{ 117,6,387 },{ 11,11,496 } },
+ { { 145,106,3843 },{ 161,6,3856 },{ 125,6,387 },{ 19,11,496 } },
+ { { 163,8,3851 },{ 137,43,3904 },{ 133,6,387 },{ 27,11,496 } },
+ { { 171,8,3851 },{ 101,11,4000 },{ 141,6,387 },{ 35,11,496 } },
+ { { 180,8,3851 },{ 110,11,4000 },{ 150,6,387 },{ 44,11,496 } },
+ { { 188,8,3851 },{ 118,11,4000 },{ 158,6,387 },{ 52,11,496 } },
+ { { 172,72,3907 },{ 126,11,4000 },{ 166,6,387 },{ 60,11,496 } },
+ { { 174,6,3971 },{ 134,11,4000 },{ 174,6,387 },{ 68,11,496 } },
+ { { 183,6,3971 },{ 143,11,4000 },{ 183,6,387 },{ 77,11,496 } },
+ { { 191,6,3971 },{ 151,11,4000 },{ 191,6,387 },{ 85,11,496 } },
+ { { 199,6,3971 },{ 159,11,4000 },{ 199,6,387 },{ 93,11,496 } },
+ { { 92,12,4084 },{ 69,15,4080 },{ 92,12,500 },{ 69,15,496 } },
+ { { 101,12,4084 },{ 78,15,4080 },{ 101,12,500 },{ 78,15,496 } },
+ { { 109,12,4084 },{ 86,15,4080 },{ 109,12,500 },{ 86,15,496 } },
+ { { 117,12,4084 },{ 79,31,4080 },{ 117,12,500 },{ 79,31,496 } },
+ { { 125,12,4084 },{ 87,31,4080 },{ 125,12,500 },{ 87,31,496 } },
+ { { 71,8,3602 },{ 71,8,3600 },{ 2,21,384 },{ 2,21,384 } },
+ { { 79,8,3611 },{ 79,8,3608 },{ 0,69,448 },{ 0,69,448 } },
+ { { 87,8,3611 },{ 87,8,3608 },{ 0,23,384 },{ 0,23,384 } },
+ { { 95,8,3611 },{ 95,8,3608 },{ 1,5,448 },{ 1,5,448 } },
+ { { 104,8,3611 },{ 104,8,3608 },{ 0,88,448 },{ 0,88,448 } },
+ { { 112,8,3611 },{ 112,8,3608 },{ 0,72,448 },{ 0,72,448 } },
+ { { 120,8,3611 },{ 121,8,3608 },{ 36,21,458 },{ 36,21,456 } },
+ { { 133,47,3091 },{ 129,8,3608 },{ 44,21,458 },{ 44,21,456 } },
+ { { 142,47,3091 },{ 138,8,3608 },{ 53,21,459 },{ 53,21,456 } },
+ { { 98,12,3850 },{ 98,12,3848 },{ 61,21,459 },{ 61,21,456 } },
+ { { 106,12,3850 },{ 106,12,3848 },{ 10,92,480 },{ 69,21,456 } },
+ { { 114,12,3851 },{ 114,12,3848 },{ 18,92,480 },{ 77,21,456 } },
+ { { 87,12,3906 },{ 87,12,3904 },{ 3,44,488 },{ 86,21,456 } },
+ { { 95,12,3906 },{ 95,12,3904 },{ 11,44,488 },{ 94,21,456 } },
+ { { 103,12,3906 },{ 103,12,3904 },{ 19,44,488 },{ 102,21,456 } },
+ { { 111,12,3907 },{ 111,12,3904 },{ 27,44,489 },{ 110,21,456 } },
+ { { 120,12,3907 },{ 120,12,3904 },{ 36,44,489 },{ 119,21,456 } },
+ { { 128,12,3907 },{ 128,12,3904 },{ 44,44,489 },{ 127,21,456 } },
+ { { 136,12,3907 },{ 136,12,3904 },{ 52,44,489 },{ 135,21,456 } },
+ { { 144,12,3907 },{ 144,12,3904 },{ 60,44,489 },{ 143,21,456 } },
+ { { 153,12,3907 },{ 153,12,3904 },{ 69,44,490 },{ 152,21,456 } },
+ { { 161,12,3395 },{ 149,188,3968 },{ 77,44,490 },{ 160,21,456 } },
+ { { 169,12,3395 },{ 198,21,3928 },{ 85,44,490 },{ 168,21,456 } },
+ { { 113,95,4001 },{ 201,69,3992 },{ 125,8,483 },{ 176,21,456 } },
+ { { 122,95,4001 },{ 200,21,3984 },{ 134,8,483 },{ 185,21,456 } },
+ { { 142,8,4067 },{ 208,21,3984 },{ 142,8,483 },{ 193,21,456 } },
+ { { 151,8,4067 },{ 47,15,4080 },{ 151,8,483 },{ 47,15,496 } },
+ { { 159,8,4067 },{ 55,15,4080 },{ 159,8,483 },{ 55,15,496 } },
+ { { 168,8,4067 },{ 64,15,4080 },{ 168,8,483 },{ 64,15,496 } },
+ { { 160,40,4075 },{ 72,15,4080 },{ 160,40,491 },{ 72,15,496 } },
+ { { 168,40,4075 },{ 80,15,4080 },{ 168,40,491 },{ 80,15,496 } },
+ { { 144,8,4082 },{ 88,15,4080 },{ 144,8,498 },{ 88,15,496 } }
+ };
+#endif // BASISD_SUPPORT_ETC2_EAC_A8
+
+#if BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES
+ static void create_etc2_eac_a8_conversion_table()
+ {
+ FILE* pFile = fopen("basisu_decoder_tables_etc2_eac_a8.inc", "w");
+
+ for (uint32_t inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t base = 0; base < 32; base++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(base, base, base, 255), false), inten);
+
+ fprintf(pFile, "{");
+
+ for (uint32_t sel_range = 0; sel_range < NUM_ETC2_EAC_SELECTOR_RANGES; sel_range++)
+ {
+ const uint32_t low_selector = s_etc2_eac_selector_ranges[sel_range].m_low;
+ const uint32_t high_selector = s_etc2_eac_selector_ranges[sel_range].m_high;
+
+ // We have a ETC1 base color and intensity, and a used selector range from low_selector-high_selector.
+ // Now find the best ETC2 EAC A8 base/table/multiplier that fits these colors.
+
+ uint8_t pixels[4];
+ uint32_t num_pixels = 0;
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ pixels[num_pixels++] = block_colors[s].g;
+
+ pack_eac_a8_results pack_results;
+ pack_eac_a8_exhaustive(pack_results, pixels, num_pixels);
+
+ etc1_g_to_eac_conversion& c = s_etc1_g_to_etc2_a8[base + inten * 32][sel_range];
+
+ c.m_base = pack_results.m_base;
+ c.m_table_mul = pack_results.m_table * 16 + pack_results.m_multiplier;
+ c.m_trans = 0;
+
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ if ((s < low_selector) || (s > high_selector))
+ continue;
+
+ uint32_t etc2_selector = pack_results.m_selectors[s - low_selector];
+
+ c.m_trans |= (etc2_selector << (s * 3));
+ }
+
+ fprintf(pFile, "{%u,%u,%u}", c.m_base, c.m_table_mul, c.m_trans);
+ if (sel_range < (NUM_ETC2_EAC_SELECTOR_RANGES - 1))
+ fprintf(pFile, ",");
+ }
+
+ fprintf(pFile, "},\n");
+ }
+ }
+
+ fclose(pFile);
+ }
+#endif
+
+#if BASISD_WRITE_NEW_ETC2_EAC_R11_TABLES
+ struct pack_eac_r11_results
+ {
+ uint32_t m_base;
+ uint32_t m_table;
+ uint32_t m_multiplier;
+ std::vector<uint8_t> m_selectors;
+ std::vector<uint8_t> m_selectors_temp;
+ };
+
+ static uint64_t pack_eac_r11_exhaustive(pack_eac_r11_results& results, const uint8_t* pPixels, uint32_t num_pixels)
+ {
+ results.m_selectors.resize(num_pixels);
+ results.m_selectors_temp.resize(num_pixels);
+
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t base_color = 0; base_color < 256; base_color++)
+ {
+ for (uint32_t multiplier = 0; multiplier < 16; multiplier++)
+ {
+ for (uint32_t table = 0; table < 16; table++)
+ {
+ uint64_t total_err = 0;
+
+ for (uint32_t i = 0; i < num_pixels; i++)
+ {
+ // Convert 8-bit input to 11-bits
+ const int a = (pPixels[i] * 2047 + 128) / 255;
+
+ uint32_t best_s_err = UINT32_MAX;
+ uint32_t best_s = 0;
+ for (uint32_t s = 0; s < 8; s++)
+ {
+ int v = (int)(multiplier ? (multiplier * 8) : 1) * g_eac_modifier_table[table][s] + (int)base_color * 8 + 4;
+ if (v < 0)
+ v = 0;
+ else if (v > 2047)
+ v = 2047;
+
+ uint32_t err = abs(a - v);
+ if (err < best_s_err)
+ {
+ best_s_err = err;
+ best_s = s;
+ }
+ }
+
+ results.m_selectors_temp[i] = static_cast<uint8_t>(best_s);
+
+ total_err += best_s_err * best_s_err;
+ if (total_err >= best_err)
+ break;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ results.m_base = base_color;
+ results.m_multiplier = multiplier;
+ results.m_table = table;
+ results.m_selectors.swap(results.m_selectors_temp);
+ }
+
+ } // table
+
+ } // multiplier
+
+ } // base_color
+
+ return best_err;
+ }
+
+ static void create_etc2_eac_r11_conversion_table()
+ {
+ FILE* pFile = nullptr;
+ fopen_s(&pFile, "basisu_decoder_tables_etc2_eac_r11.inc", "w");
+
+ for (uint32_t inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t base = 0; base < 32; base++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(base, base, base, 255), false), inten);
+
+ fprintf(pFile, "{");
+
+ for (uint32_t sel_range = 0; sel_range < NUM_ETC2_EAC_SELECTOR_RANGES; sel_range++)
+ {
+ const uint32_t low_selector = s_etc2_eac_selector_ranges[sel_range].m_low;
+ const uint32_t high_selector = s_etc2_eac_selector_ranges[sel_range].m_high;
+
+ // We have a ETC1 base color and intensity, and a used selector range from low_selector-high_selector.
+ // Now find the best ETC2 EAC R11 base/table/multiplier that fits these colors.
+
+ uint8_t pixels[4];
+ uint32_t num_pixels = 0;
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ pixels[num_pixels++] = block_colors[s].g;
+
+ pack_eac_r11_results pack_results;
+ pack_eac_r11_exhaustive(pack_results, pixels, num_pixels);
+
+ etc1_g_to_eac_conversion c;
+
+ c.m_base = (uint8_t)pack_results.m_base;
+ c.m_table_mul = (uint8_t)(pack_results.m_table * 16 + pack_results.m_multiplier);
+ c.m_trans = 0;
+
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ if ((s < low_selector) || (s > high_selector))
+ continue;
+
+ uint32_t etc2_selector = pack_results.m_selectors[s - low_selector];
+
+ c.m_trans |= (etc2_selector << (s * 3));
+ }
+
+ fprintf(pFile, "{%u,%u,%u}", c.m_base, c.m_table_mul, c.m_trans);
+ if (sel_range < (NUM_ETC2_EAC_SELECTOR_RANGES - 1))
+ fprintf(pFile, ",");
+ }
+
+ fprintf(pFile, "},\n");
+ }
+ }
+
+ fclose(pFile);
+ }
+#endif // BASISD_WRITE_NEW_ETC2_EAC_R11_TABLES
+
+#if BASISD_WRITE_NEW_ASTC_TABLES
+ static void create_etc1_to_astc_conversion_table_0_47();
+ static void create_etc1_to_astc_conversion_table_0_255();
+#endif
+
+#if BASISD_SUPPORT_ASTC
+ static void transcoder_init_astc();
+#endif
+
+#if BASISD_WRITE_NEW_BC7_MODE5_TABLES
+ static void create_etc1_to_bc7_m5_color_conversion_table();
+ static void create_etc1_to_bc7_m5_alpha_conversion_table();
+#endif
+
+#if BASISD_SUPPORT_BC7_MODE5
+ static void transcoder_init_bc7_mode5();
+#endif
+
+#if BASISD_WRITE_NEW_ATC_TABLES
+ static void create_etc1s_to_atc_conversion_tables();
+#endif
+
+#if BASISD_SUPPORT_ATC
+ static void transcoder_init_atc();
+#endif
+
+#if BASISD_SUPPORT_PVRTC2
+ static void transcoder_init_pvrtc2();
+#endif
+
+ // Library global initialization. Requires ~9 milliseconds when compiled and executed natively on a Core i7 2.2 GHz.
+ // If this is too slow, these computed tables can easilky be moved to be compiled in.
+ void basisu_transcoder_init()
+ {
+ static bool s_initialized;
+ if (s_initialized)
+ return;
+
+#if BASISD_SUPPORT_ASTC
+ transcoder_init_astc();
+#endif
+
+#if BASISD_WRITE_NEW_ASTC_TABLES
+ create_etc1_to_astc_conversion_table_0_47();
+ create_etc1_to_astc_conversion_table_0_255();
+ exit(0);
+#endif
+
+#if BASISD_WRITE_NEW_BC7_TABLES
+ create_etc1_to_bc7_m6_conversion_table();
+ exit(0);
+#endif
+
+#if BASISD_WRITE_NEW_BC7_MODE5_TABLES
+ create_etc1_to_bc7_m5_color_conversion_table();
+ create_etc1_to_bc7_m5_alpha_conversion_table();
+ exit(0);
+#endif
+
+#if BASISD_WRITE_NEW_DXT1_TABLES
+ create_etc1_to_dxt1_5_conversion_table();
+ create_etc1_to_dxt1_6_conversion_table();
+ exit(0);
+#endif
+
+#if BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES
+ create_etc2_eac_a8_conversion_table();
+ exit(0);
+#endif
+
+#if BASISD_WRITE_NEW_ATC_TABLES
+ create_etc1s_to_atc_conversion_tables();
+ exit(0);
+#endif
+
+#if BASISD_WRITE_NEW_ETC2_EAC_R11_TABLES
+ create_etc2_eac_r11_conversion_table();
+ exit(0);
+#endif
+
+#if BASISD_SUPPORT_DXT1
+ uint8_t bc1_expand5[32];
+ for (int i = 0; i < 32; i++)
+ bc1_expand5[i] = static_cast<uint8_t>((i << 3) | (i >> 2));
+ prepare_bc1_single_color_table(g_bc1_match5_equals_1, bc1_expand5, 32, 32, 1);
+ prepare_bc1_single_color_table(g_bc1_match5_equals_0, bc1_expand5, 1, 32, 0);
+
+ uint8_t bc1_expand6[64];
+ for (int i = 0; i < 64; i++)
+ bc1_expand6[i] = static_cast<uint8_t>((i << 2) | (i >> 4));
+ prepare_bc1_single_color_table(g_bc1_match6_equals_1, bc1_expand6, 64, 64, 1);
+ prepare_bc1_single_color_table(g_bc1_match6_equals_0, bc1_expand6, 1, 64, 0);
+
+ for (uint32_t i = 0; i < NUM_ETC1_TO_DXT1_SELECTOR_RANGES; i++)
+ {
+ uint32_t l = g_etc1_to_dxt1_selector_ranges[i].m_low;
+ uint32_t h = g_etc1_to_dxt1_selector_ranges[i].m_high;
+ g_etc1_to_dxt1_selector_range_index[l][h] = i;
+ }
+
+ for (uint32_t sm = 0; sm < NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS; sm++)
+ {
+ uint8_t etc1_to_dxt1_selector_mappings_raw_dxt1[4];
+ uint8_t etc1_to_dxt1_selector_mappings_raw_dxt1_inv[4];
+
+ for (uint32_t j = 0; j < 4; j++)
+ {
+ static const uint8_t s_linear_dxt1_to_dxt1[4] = { 0, 2, 3, 1 };
+ static const uint8_t s_dxt1_inverted_xlat[4] = { 1, 0, 3, 2 };
+
+ etc1_to_dxt1_selector_mappings_raw_dxt1[j] = (uint8_t)s_linear_dxt1_to_dxt1[g_etc1_to_dxt1_selector_mappings[sm][j]];
+ etc1_to_dxt1_selector_mappings_raw_dxt1_inv[j] = (uint8_t)s_dxt1_inverted_xlat[etc1_to_dxt1_selector_mappings_raw_dxt1[j]];
+ }
+
+ for (uint32_t i = 0; i < 256; i++)
+ {
+ uint32_t k = 0, k_inv = 0;
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ k |= (etc1_to_dxt1_selector_mappings_raw_dxt1[(i >> (s * 2)) & 3] << (s * 2));
+ k_inv |= (etc1_to_dxt1_selector_mappings_raw_dxt1_inv[(i >> (s * 2)) & 3] << (s * 2));
+ }
+ g_etc1_to_dxt1_selector_mappings_raw_dxt1_256[sm][i] = (uint8_t)k;
+ g_etc1_to_dxt1_selector_mappings_raw_dxt1_inv_256[sm][i] = (uint8_t)k_inv;
+ }
+ }
+#endif
+
+#if BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY
+ for (uint32_t i = 0; i < NUM_ETC1_TO_BC7_M6_SELECTOR_RANGES; i++)
+ {
+ uint32_t l = g_etc1_to_bc7_selector_ranges[i].m_low;
+ uint32_t h = g_etc1_to_bc7_selector_ranges[i].m_high;
+ g_etc1_to_bc7_m6_selector_range_index[l][h] = i;
+ }
+
+ for (uint32_t sm = 0; sm < NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS; sm++)
+ for (uint32_t j = 0; j < 4; j++)
+ g_etc1_to_bc7_selector_mappings_inv[sm][j] = 15 - g_etc1_to_bc7_selector_mappings[sm][j];
+#endif
+
+#if BASISD_SUPPORT_BC7_MODE5
+ transcoder_init_bc7_mode5();
+#endif
+
+#if BASISD_SUPPORT_ATC
+ transcoder_init_atc();
+#endif
+
+#if BASISD_SUPPORT_PVRTC2
+ transcoder_init_pvrtc2();
+#endif
+
+ s_initialized = true;
+ }
+
+#if BASISD_SUPPORT_DXT1
+ static void convert_etc1s_to_dxt1(dxt1_block* pDst_block, const endpoint *pEndpoints, const selector* pSelector, bool use_threecolor_blocks)
+ {
+#if !BASISD_WRITE_NEW_DXT1_TABLES
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ const color32& base_color = pEndpoints->m_color5;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ if (low_selector == high_selector)
+ {
+ uint32_t r, g, b;
+ decoder_etc_block::get_block_color5(base_color, inten_table, low_selector, r, g, b);
+
+ uint32_t mask = 0xAA;
+ uint32_t max16 = (g_bc1_match5_equals_1[r].m_hi << 11) | (g_bc1_match6_equals_1[g].m_hi << 5) | g_bc1_match5_equals_1[b].m_hi;
+ uint32_t min16 = (g_bc1_match5_equals_1[r].m_lo << 11) | (g_bc1_match6_equals_1[g].m_lo << 5) | g_bc1_match5_equals_1[b].m_lo;
+
+ if ((!use_threecolor_blocks) && (min16 == max16))
+ {
+ // This is an annoying edge case that impacts BC3.
+ // This is to guarantee that BC3 blocks never use punchthrough alpha (3 color) mode, which isn't supported on some (all?) GPU's.
+ mask = 0;
+
+ // Make l > h
+ if (min16 > 0)
+ min16--;
+ else
+ {
+ // l = h = 0
+ assert(min16 == max16 && max16 == 0);
+
+ max16 = 1;
+ min16 = 0;
+ mask = 0x55;
+ }
+
+ assert(max16 > min16);
+ }
+
+ if (max16 < min16)
+ {
+ std::swap(max16, min16);
+ mask ^= 0x55;
+ }
+
+ pDst_block->set_low_color(static_cast<uint16_t>(max16));
+ pDst_block->set_high_color(static_cast<uint16_t>(min16));
+ pDst_block->m_selectors[0] = static_cast<uint8_t>(mask);
+ pDst_block->m_selectors[1] = static_cast<uint8_t>(mask);
+ pDst_block->m_selectors[2] = static_cast<uint8_t>(mask);
+ pDst_block->m_selectors[3] = static_cast<uint8_t>(mask);
+
+ return;
+ }
+ else if ((inten_table >= 7) && (pSelector->m_num_unique_selectors == 2) && (pSelector->m_lo_selector == 0) && (pSelector->m_hi_selector == 3))
+ {
+ color32 block_colors[4];
+
+ decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table);
+
+ const uint32_t r0 = block_colors[0].r;
+ const uint32_t g0 = block_colors[0].g;
+ const uint32_t b0 = block_colors[0].b;
+
+ const uint32_t r1 = block_colors[3].r;
+ const uint32_t g1 = block_colors[3].g;
+ const uint32_t b1 = block_colors[3].b;
+
+ uint32_t max16 = (g_bc1_match5_equals_0[r0].m_hi << 11) | (g_bc1_match6_equals_0[g0].m_hi << 5) | g_bc1_match5_equals_0[b0].m_hi;
+ uint32_t min16 = (g_bc1_match5_equals_0[r1].m_hi << 11) | (g_bc1_match6_equals_0[g1].m_hi << 5) | g_bc1_match5_equals_0[b1].m_hi;
+
+ uint32_t l = 0, h = 1;
+
+ if (min16 == max16)
+ {
+ // Make l > h
+ if (min16 > 0)
+ {
+ min16--;
+
+ l = 0;
+ h = 0;
+ }
+ else
+ {
+ // l = h = 0
+ assert(min16 == max16 && max16 == 0);
+
+ max16 = 1;
+ min16 = 0;
+
+ l = 1;
+ h = 1;
+ }
+
+ assert(max16 > min16);
+ }
+
+ if (max16 < min16)
+ {
+ std::swap(max16, min16);
+ l = 1;
+ h = 0;
+ }
+
+ pDst_block->set_low_color((uint16_t)max16);
+ pDst_block->set_high_color((uint16_t)min16);
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+ pDst_block->set_selector(x, y, (s == 3) ? h : l);
+ }
+ }
+
+ return;
+ }
+
+ const uint32_t selector_range_table = g_etc1_to_dxt1_selector_range_index[low_selector][high_selector];
+
+ //[32][8][RANGES][MAPPING]
+ const etc1_to_dxt1_56_solution* pTable_r = &g_etc1_to_dxt_5[(inten_table * 32 + base_color.r) * (NUM_ETC1_TO_DXT1_SELECTOR_RANGES * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS];
+ const etc1_to_dxt1_56_solution* pTable_g = &g_etc1_to_dxt_6[(inten_table * 32 + base_color.g) * (NUM_ETC1_TO_DXT1_SELECTOR_RANGES * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS];
+ const etc1_to_dxt1_56_solution* pTable_b = &g_etc1_to_dxt_5[(inten_table * 32 + base_color.b) * (NUM_ETC1_TO_DXT1_SELECTOR_RANGES * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS];
+
+ uint32_t best_err = UINT_MAX;
+ uint32_t best_mapping = 0;
+
+ assert(NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS == 10);
+#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } }
+ DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4);
+ DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9);
+#undef DO_ITER
+
+ uint32_t l = dxt1_block::pack_unscaled_color(pTable_r[best_mapping].m_lo, pTable_g[best_mapping].m_lo, pTable_b[best_mapping].m_lo);
+ uint32_t h = dxt1_block::pack_unscaled_color(pTable_r[best_mapping].m_hi, pTable_g[best_mapping].m_hi, pTable_b[best_mapping].m_hi);
+
+ const uint8_t* pSelectors_xlat_256 = &g_etc1_to_dxt1_selector_mappings_raw_dxt1_256[best_mapping][0];
+
+ if (l < h)
+ {
+ std::swap(l, h);
+ pSelectors_xlat_256 = &g_etc1_to_dxt1_selector_mappings_raw_dxt1_inv_256[best_mapping][0];
+ }
+
+ pDst_block->set_low_color(static_cast<uint16_t>(l));
+ pDst_block->set_high_color(static_cast<uint16_t>(h));
+
+ if (l == h)
+ {
+ uint8_t mask = 0;
+
+ if (!use_threecolor_blocks)
+ {
+ // This is an annoying edge case that impacts BC3.
+
+ // Make l > h
+ if (h > 0)
+ h--;
+ else
+ {
+ // l = h = 0
+ assert(l == h && h == 0);
+
+ h = 0;
+ l = 1;
+ mask = 0x55;
+ }
+
+ assert(l > h);
+ pDst_block->set_low_color(static_cast<uint16_t>(l));
+ pDst_block->set_high_color(static_cast<uint16_t>(h));
+ }
+
+ pDst_block->m_selectors[0] = mask;
+ pDst_block->m_selectors[1] = mask;
+ pDst_block->m_selectors[2] = mask;
+ pDst_block->m_selectors[3] = mask;
+
+ return;
+ }
+
+ pDst_block->m_selectors[0] = pSelectors_xlat_256[pSelector->m_selectors[0]];
+ pDst_block->m_selectors[1] = pSelectors_xlat_256[pSelector->m_selectors[1]];
+ pDst_block->m_selectors[2] = pSelectors_xlat_256[pSelector->m_selectors[2]];
+ pDst_block->m_selectors[3] = pSelectors_xlat_256[pSelector->m_selectors[3]];
+#endif
+ }
+
+#if BASISD_ENABLE_DEBUG_FLAGS
+ static void convert_etc1s_to_dxt1_vis(dxt1_block* pDst_block, const endpoint* pEndpoints, const selector* pSelector, bool use_threecolor_blocks)
+ {
+ convert_etc1s_to_dxt1(pDst_block, pEndpoints, pSelector, use_threecolor_blocks);
+
+ if (g_debug_flags & cDebugFlagVisBC1Sels)
+ {
+ uint32_t l = dxt1_block::pack_unscaled_color(31, 63, 31);
+ uint32_t h = dxt1_block::pack_unscaled_color(0, 0, 0);
+ pDst_block->set_low_color(static_cast<uint16_t>(l));
+ pDst_block->set_high_color(static_cast<uint16_t>(h));
+ }
+ else if (g_debug_flags & cDebugFlagVisBC1Endpoints)
+ {
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ pDst_block->set_selector(x, y, (y < 2) ? 0 : 1);
+ }
+ }
+#endif
+#endif
+
+#if BASISD_SUPPORT_FXT1
+ struct fxt1_block
+ {
+ union
+ {
+ struct
+ {
+ uint64_t m_t00 : 2;
+ uint64_t m_t01 : 2;
+ uint64_t m_t02 : 2;
+ uint64_t m_t03 : 2;
+ uint64_t m_t04 : 2;
+ uint64_t m_t05 : 2;
+ uint64_t m_t06 : 2;
+ uint64_t m_t07 : 2;
+ uint64_t m_t08 : 2;
+ uint64_t m_t09 : 2;
+ uint64_t m_t10 : 2;
+ uint64_t m_t11 : 2;
+ uint64_t m_t12 : 2;
+ uint64_t m_t13 : 2;
+ uint64_t m_t14 : 2;
+ uint64_t m_t15 : 2;
+ uint64_t m_t16 : 2;
+ uint64_t m_t17 : 2;
+ uint64_t m_t18 : 2;
+ uint64_t m_t19 : 2;
+ uint64_t m_t20 : 2;
+ uint64_t m_t21 : 2;
+ uint64_t m_t22 : 2;
+ uint64_t m_t23 : 2;
+ uint64_t m_t24 : 2;
+ uint64_t m_t25 : 2;
+ uint64_t m_t26 : 2;
+ uint64_t m_t27 : 2;
+ uint64_t m_t28 : 2;
+ uint64_t m_t29 : 2;
+ uint64_t m_t30 : 2;
+ uint64_t m_t31 : 2;
+ } m_lo;
+ uint64_t m_lo_bits;
+ uint8_t m_sels[8];
+ };
+ union
+ {
+ struct
+ {
+#ifdef BASISU_USE_ORIGINAL_3DFX_FXT1_ENCODING
+ uint64_t m_b1 : 5;
+ uint64_t m_g1 : 5;
+ uint64_t m_r1 : 5;
+ uint64_t m_b0 : 5;
+ uint64_t m_g0 : 5;
+ uint64_t m_r0 : 5;
+ uint64_t m_b3 : 5;
+ uint64_t m_g3 : 5;
+ uint64_t m_r3 : 5;
+ uint64_t m_b2 : 5;
+ uint64_t m_g2 : 5;
+ uint64_t m_r2 : 5;
+#else
+ uint64_t m_b0 : 5;
+ uint64_t m_g0 : 5;
+ uint64_t m_r0 : 5;
+ uint64_t m_b1 : 5;
+ uint64_t m_g1 : 5;
+ uint64_t m_r1 : 5;
+ uint64_t m_b2 : 5;
+ uint64_t m_g2 : 5;
+ uint64_t m_r2 : 5;
+ uint64_t m_b3 : 5;
+ uint64_t m_g3 : 5;
+ uint64_t m_r3 : 5;
+#endif
+ uint64_t m_alpha : 1;
+ uint64_t m_glsb : 2;
+ uint64_t m_mode : 1;
+ } m_hi;
+ uint64_t m_hi_bits;
+ };
+ };
+
+ static uint8_t conv_dxt1_to_fxt1_sels(uint32_t sels)
+ {
+ static uint8_t s_conv_table[16] = { 0, 3, 1, 2, 12, 15, 13, 14, 4, 7, 5, 6, 8, 11, 9, 10 };
+ return s_conv_table[sels & 15] | (s_conv_table[sels >> 4] << 4);
+ }
+
+ static void convert_etc1s_to_fxt1(void *pDst, const endpoint *pEndpoints, const selector *pSelectors, uint32_t fxt1_subblock)
+ {
+ fxt1_block* pBlock = static_cast<fxt1_block*>(pDst);
+
+ // CC_MIXED is basically DXT1 with different encoding tricks.
+ // So transcode ETC1S to DXT1, then transcode that to FXT1 which is easy and nearly lossless.
+ // (It's not completely lossless because FXT1 rounds in its color lerps while DXT1 doesn't, but it should be good enough.)
+ dxt1_block blk;
+ convert_etc1s_to_dxt1(&blk, pEndpoints, pSelectors, false);
+
+ const uint32_t l = blk.get_low_color();
+ const uint32_t h = blk.get_high_color();
+
+ color32 color0((l >> 11) & 31, (l >> 5) & 63, l & 31, 255);
+ color32 color1((h >> 11) & 31, (h >> 5) & 63, h & 31, 255);
+
+ uint32_t g0 = color0.g & 1;
+ uint32_t g1 = color1.g & 1;
+
+ color0.g >>= 1;
+ color1.g >>= 1;
+
+ blk.m_selectors[0] = conv_dxt1_to_fxt1_sels(blk.m_selectors[0]);
+ blk.m_selectors[1] = conv_dxt1_to_fxt1_sels(blk.m_selectors[1]);
+ blk.m_selectors[2] = conv_dxt1_to_fxt1_sels(blk.m_selectors[2]);
+ blk.m_selectors[3] = conv_dxt1_to_fxt1_sels(blk.m_selectors[3]);
+
+ if ((blk.get_selector(0, 0) >> 1) != (g0 ^ g1))
+ {
+ std::swap(color0, color1);
+ std::swap(g0, g1);
+
+ blk.m_selectors[0] ^= 0xFF;
+ blk.m_selectors[1] ^= 0xFF;
+ blk.m_selectors[2] ^= 0xFF;
+ blk.m_selectors[3] ^= 0xFF;
+ }
+
+ if (fxt1_subblock == 0)
+ {
+ pBlock->m_hi.m_mode = 1;
+ pBlock->m_hi.m_alpha = 0;
+ pBlock->m_hi.m_glsb = g1 | (g1 << 1);
+ pBlock->m_hi.m_r0 = color0.r;
+ pBlock->m_hi.m_g0 = color0.g;
+ pBlock->m_hi.m_b0 = color0.b;
+ pBlock->m_hi.m_r1 = color1.r;
+ pBlock->m_hi.m_g1 = color1.g;
+ pBlock->m_hi.m_b1 = color1.b;
+ pBlock->m_hi.m_r2 = color0.r;
+ pBlock->m_hi.m_g2 = color0.g;
+ pBlock->m_hi.m_b2 = color0.b;
+ pBlock->m_hi.m_r3 = color1.r;
+ pBlock->m_hi.m_g3 = color1.g;
+ pBlock->m_hi.m_b3 = color1.b;
+ pBlock->m_sels[0] = blk.m_selectors[0];
+ pBlock->m_sels[1] = blk.m_selectors[1];
+ pBlock->m_sels[2] = blk.m_selectors[2];
+ pBlock->m_sels[3] = blk.m_selectors[3];
+
+ static const uint8_t s_border_dup[4] = { 0, 85, 170, 255 };
+ pBlock->m_sels[4] = s_border_dup[blk.m_selectors[0] >> 6];
+ pBlock->m_sels[5] = s_border_dup[blk.m_selectors[1] >> 6];
+ pBlock->m_sels[6] = s_border_dup[blk.m_selectors[2] >> 6];
+ pBlock->m_sels[7] = s_border_dup[blk.m_selectors[3] >> 6];
+ }
+ else
+ {
+ pBlock->m_hi.m_glsb = (pBlock->m_hi.m_glsb & 1) | (g1 << 1);
+ pBlock->m_hi.m_r2 = color0.r;
+ pBlock->m_hi.m_g2 = color0.g;
+ pBlock->m_hi.m_b2 = color0.b;
+ pBlock->m_hi.m_r3 = color1.r;
+ pBlock->m_hi.m_g3 = color1.g;
+ pBlock->m_hi.m_b3 = color1.b;
+ pBlock->m_sels[4] = blk.m_selectors[0];
+ pBlock->m_sels[5] = blk.m_selectors[1];
+ pBlock->m_sels[6] = blk.m_selectors[2];
+ pBlock->m_sels[7] = blk.m_selectors[3];
+ }
+ }
+#endif // BASISD_SUPPORT_FXT1
+#if BASISD_SUPPORT_DXT5A
+ static dxt_selector_range s_dxt5a_selector_ranges[] =
+ {
+ { 0, 3 },
+
+ { 1, 3 },
+ { 0, 2 },
+
+ { 1, 2 },
+ };
+
+ const uint32_t NUM_DXT5A_SELECTOR_RANGES = sizeof(s_dxt5a_selector_ranges) / sizeof(s_dxt5a_selector_ranges[0]);
+
+ struct etc1_g_to_dxt5a_conversion
+ {
+ uint8_t m_lo, m_hi;
+ uint16_t m_trans;
+ };
+
+ static etc1_g_to_dxt5a_conversion g_etc1_g_to_dxt5a[32 * 8][NUM_DXT5A_SELECTOR_RANGES] =
+ {
+ { { 8, 0, 393 },{ 8, 0, 392 },{ 2, 0, 9 },{ 2, 0, 8 }, }, { { 6, 16, 710 },{ 16, 6, 328 },{ 0, 10, 96 },{ 10, 6, 8 }, },
+ { { 28, 5, 1327 },{ 24, 14, 328 },{ 8, 18, 96 },{ 18, 14, 8 }, }, { { 36, 13, 1327 },{ 32, 22, 328 },{ 16, 26, 96 },{ 26, 22, 8 }, },
+ { { 45, 22, 1327 },{ 41, 31, 328 },{ 25, 35, 96 },{ 35, 31, 8 }, }, { { 53, 30, 1327 },{ 49, 39, 328 },{ 33, 43, 96 },{ 43, 39, 8 }, },
+ { { 61, 38, 1327 },{ 57, 47, 328 },{ 41, 51, 96 },{ 51, 47, 8 }, }, { { 69, 46, 1327 },{ 65, 55, 328 },{ 49, 59, 96 },{ 59, 55, 8 }, },
+ { { 78, 55, 1327 },{ 74, 64, 328 },{ 58, 68, 96 },{ 68, 64, 8 }, }, { { 86, 63, 1327 },{ 82, 72, 328 },{ 66, 76, 96 },{ 76, 72, 8 }, },
+ { { 94, 71, 1327 },{ 90, 80, 328 },{ 74, 84, 96 },{ 84, 80, 8 }, }, { { 102, 79, 1327 },{ 98, 88, 328 },{ 82, 92, 96 },{ 92, 88, 8 }, },
+ { { 111, 88, 1327 },{ 107, 97, 328 },{ 91, 101, 96 },{ 101, 97, 8 }, }, { { 119, 96, 1327 },{ 115, 105, 328 },{ 99, 109, 96 },{ 109, 105, 8 }, },
+ { { 127, 104, 1327 },{ 123, 113, 328 },{ 107, 117, 96 },{ 117, 113, 8 }, }, { { 135, 112, 1327 },{ 131, 121, 328 },{ 115, 125, 96 },{ 125, 121, 8 }, },
+ { { 144, 121, 1327 },{ 140, 130, 328 },{ 124, 134, 96 },{ 134, 130, 8 }, }, { { 152, 129, 1327 },{ 148, 138, 328 },{ 132, 142, 96 },{ 142, 138, 8 }, },
+ { { 160, 137, 1327 },{ 156, 146, 328 },{ 140, 150, 96 },{ 150, 146, 8 }, }, { { 168, 145, 1327 },{ 164, 154, 328 },{ 148, 158, 96 },{ 158, 154, 8 }, },
+ { { 177, 154, 1327 },{ 173, 163, 328 },{ 157, 167, 96 },{ 167, 163, 8 }, }, { { 185, 162, 1327 },{ 181, 171, 328 },{ 165, 175, 96 },{ 175, 171, 8 }, },
+ { { 193, 170, 1327 },{ 189, 179, 328 },{ 173, 183, 96 },{ 183, 179, 8 }, }, { { 201, 178, 1327 },{ 197, 187, 328 },{ 181, 191, 96 },{ 191, 187, 8 }, },
+ { { 210, 187, 1327 },{ 206, 196, 328 },{ 190, 200, 96 },{ 200, 196, 8 }, }, { { 218, 195, 1327 },{ 214, 204, 328 },{ 198, 208, 96 },{ 208, 204, 8 }, },
+ { { 226, 203, 1327 },{ 222, 212, 328 },{ 206, 216, 96 },{ 216, 212, 8 }, }, { { 234, 211, 1327 },{ 230, 220, 328 },{ 214, 224, 96 },{ 224, 220, 8 }, },
+ { { 243, 220, 1327 },{ 239, 229, 328 },{ 223, 233, 96 },{ 233, 229, 8 }, }, { { 251, 228, 1327 },{ 247, 237, 328 },{ 231, 241, 96 },{ 241, 237, 8 }, },
+ { { 239, 249, 3680 },{ 245, 249, 3648 },{ 239, 249, 96 },{ 249, 245, 8 }, }, { { 247, 253, 4040 },{ 255, 253, 8 },{ 247, 253, 456 },{ 255, 253, 8 }, },
+ { { 5, 17, 566 },{ 5, 17, 560 },{ 5, 0, 9 },{ 5, 0, 8 }, }, { { 25, 0, 313 },{ 25, 3, 328 },{ 13, 0, 49 },{ 13, 3, 8 }, },
+ { { 39, 0, 1329 },{ 33, 11, 328 },{ 11, 21, 70 },{ 21, 11, 8 }, }, { { 47, 7, 1329 },{ 41, 19, 328 },{ 29, 7, 33 },{ 29, 19, 8 }, },
+ { { 50, 11, 239 },{ 50, 28, 328 },{ 38, 16, 33 },{ 38, 28, 8 }, }, { { 92, 13, 2423 },{ 58, 36, 328 },{ 46, 24, 33 },{ 46, 36, 8 }, },
+ { { 100, 21, 2423 },{ 66, 44, 328 },{ 54, 32, 33 },{ 54, 44, 8 }, }, { { 86, 7, 1253 },{ 74, 52, 328 },{ 62, 40, 33 },{ 62, 52, 8 }, },
+ { { 95, 16, 1253 },{ 83, 61, 328 },{ 71, 49, 33 },{ 71, 61, 8 }, }, { { 103, 24, 1253 },{ 91, 69, 328 },{ 79, 57, 33 },{ 79, 69, 8 }, },
+ { { 111, 32, 1253 },{ 99, 77, 328 },{ 87, 65, 33 },{ 87, 77, 8 }, }, { { 119, 40, 1253 },{ 107, 85, 328 },{ 95, 73, 33 },{ 95, 85, 8 }, },
+ { { 128, 49, 1253 },{ 116, 94, 328 },{ 104, 82, 33 },{ 104, 94, 8 }, }, { { 136, 57, 1253 },{ 124, 102, 328 },{ 112, 90, 33 },{ 112, 102, 8 }, },
+ { { 144, 65, 1253 },{ 132, 110, 328 },{ 120, 98, 33 },{ 120, 110, 8 }, }, { { 152, 73, 1253 },{ 140, 118, 328 },{ 128, 106, 33 },{ 128, 118, 8 }, },
+ { { 161, 82, 1253 },{ 149, 127, 328 },{ 137, 115, 33 },{ 137, 127, 8 }, }, { { 169, 90, 1253 },{ 157, 135, 328 },{ 145, 123, 33 },{ 145, 135, 8 }, },
+ { { 177, 98, 1253 },{ 165, 143, 328 },{ 153, 131, 33 },{ 153, 143, 8 }, }, { { 185, 106, 1253 },{ 173, 151, 328 },{ 161, 139, 33 },{ 161, 151, 8 }, },
+ { { 194, 115, 1253 },{ 182, 160, 328 },{ 170, 148, 33 },{ 170, 160, 8 }, }, { { 202, 123, 1253 },{ 190, 168, 328 },{ 178, 156, 33 },{ 178, 168, 8 }, },
+ { { 210, 131, 1253 },{ 198, 176, 328 },{ 186, 164, 33 },{ 186, 176, 8 }, }, { { 218, 139, 1253 },{ 206, 184, 328 },{ 194, 172, 33 },{ 194, 184, 8 }, },
+ { { 227, 148, 1253 },{ 215, 193, 328 },{ 203, 181, 33 },{ 203, 193, 8 }, }, { { 235, 156, 1253 },{ 223, 201, 328 },{ 211, 189, 33 },{ 211, 201, 8 }, },
+ { { 243, 164, 1253 },{ 231, 209, 328 },{ 219, 197, 33 },{ 219, 209, 8 }, }, { { 183, 239, 867 },{ 239, 217, 328 },{ 227, 205, 33 },{ 227, 217, 8 }, },
+ { { 254, 214, 1329 },{ 248, 226, 328 },{ 236, 214, 33 },{ 236, 226, 8 }, }, { { 222, 244, 3680 },{ 234, 244, 3648 },{ 244, 222, 33 },{ 244, 234, 8 }, },
+ { { 230, 252, 3680 },{ 242, 252, 3648 },{ 252, 230, 33 },{ 252, 242, 8 }, }, { { 238, 250, 4040 },{ 255, 250, 8 },{ 238, 250, 456 },{ 255, 250, 8 }, },
+ { { 9, 29, 566 },{ 9, 29, 560 },{ 9, 0, 9 },{ 9, 0, 8 }, }, { { 17, 37, 566 },{ 17, 37, 560 },{ 17, 0, 9 },{ 17, 0, 8 }, },
+ { { 45, 0, 313 },{ 45, 0, 312 },{ 25, 0, 49 },{ 25, 7, 8 }, }, { { 14, 63, 2758 },{ 5, 53, 784 },{ 15, 33, 70 },{ 33, 15, 8 }, },
+ { { 71, 6, 1329 },{ 72, 4, 1328 },{ 42, 4, 33 },{ 42, 24, 8 }, }, { { 70, 3, 239 },{ 70, 2, 232 },{ 50, 12, 33 },{ 50, 32, 8 }, },
+ { { 0, 98, 2842 },{ 78, 10, 232 },{ 58, 20, 33 },{ 58, 40, 8 }, }, { { 97, 27, 1329 },{ 86, 18, 232 },{ 66, 28, 33 },{ 66, 48, 8 }, },
+ { { 0, 94, 867 },{ 95, 27, 232 },{ 75, 37, 33 },{ 75, 57, 8 }, }, { { 8, 102, 867 },{ 103, 35, 232 },{ 83, 45, 33 },{ 83, 65, 8 }, },
+ { { 12, 112, 867 },{ 111, 43, 232 },{ 91, 53, 33 },{ 91, 73, 8 }, }, { { 139, 2, 1253 },{ 119, 51, 232 },{ 99, 61, 33 },{ 99, 81, 8 }, },
+ { { 148, 13, 1253 },{ 128, 60, 232 },{ 108, 70, 33 },{ 108, 90, 8 }, }, { { 156, 21, 1253 },{ 136, 68, 232 },{ 116, 78, 33 },{ 116, 98, 8 }, },
+ { { 164, 29, 1253 },{ 144, 76, 232 },{ 124, 86, 33 },{ 124, 106, 8 }, }, { { 172, 37, 1253 },{ 152, 84, 232 },{ 132, 94, 33 },{ 132, 114, 8 }, },
+ { { 181, 46, 1253 },{ 161, 93, 232 },{ 141, 103, 33 },{ 141, 123, 8 }, }, { { 189, 54, 1253 },{ 169, 101, 232 },{ 149, 111, 33 },{ 149, 131, 8 }, },
+ { { 197, 62, 1253 },{ 177, 109, 232 },{ 157, 119, 33 },{ 157, 139, 8 }, }, { { 205, 70, 1253 },{ 185, 117, 232 },{ 165, 127, 33 },{ 165, 147, 8 }, },
+ { { 214, 79, 1253 },{ 194, 126, 232 },{ 174, 136, 33 },{ 174, 156, 8 }, }, { { 222, 87, 1253 },{ 202, 134, 232 },{ 182, 144, 33 },{ 182, 164, 8 }, },
+ { { 230, 95, 1253 },{ 210, 142, 232 },{ 190, 152, 33 },{ 190, 172, 8 }, }, { { 238, 103, 1253 },{ 218, 150, 232 },{ 198, 160, 33 },{ 198, 180, 8 }, },
+ { { 247, 112, 1253 },{ 227, 159, 232 },{ 207, 169, 33 },{ 207, 189, 8 }, }, { { 255, 120, 1253 },{ 235, 167, 232 },{ 215, 177, 33 },{ 215, 197, 8 }, },
+ { { 146, 243, 867 },{ 243, 175, 232 },{ 223, 185, 33 },{ 223, 205, 8 }, }, { { 184, 231, 3682 },{ 203, 251, 784 },{ 231, 193, 33 },{ 231, 213, 8 }, },
+ { { 193, 240, 3682 },{ 222, 240, 3648 },{ 240, 202, 33 },{ 240, 222, 8 }, }, { { 255, 210, 169 },{ 230, 248, 3648 },{ 248, 210, 33 },{ 248, 230, 8 }, },
+ { { 218, 238, 4040 },{ 255, 238, 8 },{ 218, 238, 456 },{ 255, 238, 8 }, }, { { 226, 246, 4040 },{ 255, 246, 8 },{ 226, 246, 456 },{ 255, 246, 8 }, },
+ { { 13, 42, 566 },{ 13, 42, 560 },{ 13, 0, 9 },{ 13, 0, 8 }, }, { { 50, 0, 329 },{ 50, 0, 328 },{ 21, 0, 9 },{ 21, 0, 8 }, },
+ { { 29, 58, 566 },{ 67, 2, 1352 },{ 3, 29, 70 },{ 29, 3, 8 }, }, { { 10, 79, 2758 },{ 76, 11, 1352 },{ 11, 37, 70 },{ 37, 11, 8 }, },
+ { { 7, 75, 790 },{ 7, 75, 784 },{ 20, 46, 70 },{ 46, 20, 8 }, }, { { 15, 83, 790 },{ 97, 1, 1328 },{ 28, 54, 70 },{ 54, 28, 8 }, },
+ { { 101, 7, 1329 },{ 105, 9, 1328 },{ 62, 0, 39 },{ 62, 36, 8 }, }, { { 99, 1, 239 },{ 99, 3, 232 },{ 1, 71, 98 },{ 70, 44, 8 }, },
+ { { 107, 11, 239 },{ 108, 12, 232 },{ 10, 80, 98 },{ 79, 53, 8 }, }, { { 115, 19, 239 },{ 116, 20, 232 },{ 18, 88, 98 },{ 87, 61, 8 }, },
+ { { 123, 27, 239 },{ 124, 28, 232 },{ 26, 96, 98 },{ 95, 69, 8 }, }, { { 131, 35, 239 },{ 132, 36, 232 },{ 34, 104, 98 },{ 103, 77, 8 }, },
+ { { 140, 44, 239 },{ 141, 45, 232 },{ 43, 113, 98 },{ 112, 86, 8 }, }, { { 148, 52, 239 },{ 149, 53, 232 },{ 51, 121, 98 },{ 120, 94, 8 }, },
+ { { 156, 60, 239 },{ 157, 61, 232 },{ 59, 129, 98 },{ 128, 102, 8 }, }, { { 164, 68, 239 },{ 165, 69, 232 },{ 67, 137, 98 },{ 136, 110, 8 }, },
+ { { 173, 77, 239 },{ 174, 78, 232 },{ 76, 146, 98 },{ 145, 119, 8 }, }, { { 181, 85, 239 },{ 182, 86, 232 },{ 84, 154, 98 },{ 153, 127, 8 }, },
+ { { 189, 93, 239 },{ 190, 94, 232 },{ 92, 162, 98 },{ 161, 135, 8 }, }, { { 197, 101, 239 },{ 198, 102, 232 },{ 100, 170, 98 },{ 169, 143, 8 }, },
+ { { 206, 110, 239 },{ 207, 111, 232 },{ 109, 179, 98 },{ 178, 152, 8 }, }, { { 214, 118, 239 },{ 215, 119, 232 },{ 117, 187, 98 },{ 186, 160, 8 }, },
+ { { 222, 126, 239 },{ 223, 127, 232 },{ 125, 195, 98 },{ 194, 168, 8 }, }, { { 230, 134, 239 },{ 231, 135, 232 },{ 133, 203, 98 },{ 202, 176, 8 }, },
+ { { 239, 143, 239 },{ 240, 144, 232 },{ 142, 212, 98 },{ 211, 185, 8 }, }, { { 247, 151, 239 },{ 180, 248, 784 },{ 150, 220, 98 },{ 219, 193, 8 }, },
+ { { 159, 228, 3682 },{ 201, 227, 3648 },{ 158, 228, 98 },{ 227, 201, 8 }, }, { { 181, 249, 3928 },{ 209, 235, 3648 },{ 166, 236, 98 },{ 235, 209, 8 }, },
+ { { 255, 189, 169 },{ 218, 244, 3648 },{ 175, 245, 98 },{ 244, 218, 8 }, }, { { 197, 226, 4040 },{ 226, 252, 3648 },{ 183, 253, 98 },{ 252, 226, 8 }, },
+ { { 205, 234, 4040 },{ 255, 234, 8 },{ 205, 234, 456 },{ 255, 234, 8 }, }, { { 213, 242, 4040 },{ 255, 242, 8 },{ 213, 242, 456 },{ 255, 242, 8 }, },
+ { { 18, 60, 566 },{ 18, 60, 560 },{ 18, 0, 9 },{ 18, 0, 8 }, }, { { 26, 68, 566 },{ 26, 68, 560 },{ 26, 0, 9 },{ 26, 0, 8 }, },
+ { { 34, 76, 566 },{ 34, 76, 560 },{ 34, 0, 9 },{ 34, 0, 8 }, }, { { 5, 104, 2758 },{ 98, 5, 1352 },{ 42, 0, 57 },{ 42, 6, 8 }, },
+ { { 92, 0, 313 },{ 93, 1, 312 },{ 15, 51, 70 },{ 51, 15, 8 }, }, { { 3, 101, 790 },{ 3, 101, 784 },{ 0, 59, 88 },{ 59, 23, 8 }, },
+ { { 14, 107, 790 },{ 11, 109, 784 },{ 31, 67, 70 },{ 67, 31, 8 }, }, { { 19, 117, 790 },{ 19, 117, 784 },{ 39, 75, 70 },{ 75, 39, 8 }, },
+ { { 28, 126, 790 },{ 28, 126, 784 },{ 83, 5, 33 },{ 84, 48, 8 }, }, { { 132, 0, 239 },{ 36, 134, 784 },{ 91, 13, 33 },{ 92, 56, 8 }, },
+ { { 142, 4, 239 },{ 44, 142, 784 },{ 99, 21, 33 },{ 100, 64, 8 }, }, { { 150, 12, 239 },{ 52, 150, 784 },{ 107, 29, 33 },{ 108, 72, 8 }, },
+ { { 159, 21, 239 },{ 61, 159, 784 },{ 116, 38, 33 },{ 117, 81, 8 }, }, { { 167, 29, 239 },{ 69, 167, 784 },{ 124, 46, 33 },{ 125, 89, 8 }, },
+ { { 175, 37, 239 },{ 77, 175, 784 },{ 132, 54, 33 },{ 133, 97, 8 }, }, { { 183, 45, 239 },{ 85, 183, 784 },{ 140, 62, 33 },{ 141, 105, 8 }, },
+ { { 192, 54, 239 },{ 94, 192, 784 },{ 149, 71, 33 },{ 150, 114, 8 }, }, { { 200, 62, 239 },{ 102, 200, 784 },{ 157, 79, 33 },{ 158, 122, 8 }, },
+ { { 208, 70, 239 },{ 110, 208, 784 },{ 165, 87, 33 },{ 166, 130, 8 }, }, { { 216, 78, 239 },{ 118, 216, 784 },{ 173, 95, 33 },{ 174, 138, 8 }, },
+ { { 225, 87, 239 },{ 127, 225, 784 },{ 182, 104, 33 },{ 183, 147, 8 }, }, { { 233, 95, 239 },{ 135, 233, 784 },{ 190, 112, 33 },{ 191, 155, 8 }, },
+ { { 241, 103, 239 },{ 143, 241, 784 },{ 198, 120, 33 },{ 199, 163, 8 }, }, { { 111, 208, 3682 },{ 151, 249, 784 },{ 206, 128, 33 },{ 207, 171, 8 }, },
+ { { 120, 217, 3682 },{ 180, 216, 3648 },{ 215, 137, 33 },{ 216, 180, 8 }, }, { { 128, 225, 3682 },{ 188, 224, 3648 },{ 223, 145, 33 },{ 224, 188, 8 }, },
+ { { 155, 253, 3928 },{ 196, 232, 3648 },{ 231, 153, 33 },{ 232, 196, 8 }, }, { { 144, 241, 3682 },{ 204, 240, 3648 },{ 239, 161, 33 },{ 240, 204, 8 }, },
+ { { 153, 250, 3682 },{ 213, 249, 3648 },{ 248, 170, 33 },{ 249, 213, 8 }, }, { { 179, 221, 4040 },{ 255, 221, 8 },{ 179, 221, 456 },{ 255, 221, 8 }, },
+ { { 187, 229, 4040 },{ 255, 229, 8 },{ 187, 229, 456 },{ 255, 229, 8 }, }, { { 195, 237, 4040 },{ 255, 237, 8 },{ 195, 237, 456 },{ 255, 237, 8 }, },
+ { { 24, 80, 566 },{ 24, 80, 560 },{ 24, 0, 9 },{ 24, 0, 8 }, }, { { 32, 88, 566 },{ 32, 88, 560 },{ 32, 0, 9 },{ 32, 0, 8 }, },
+ { { 40, 96, 566 },{ 40, 96, 560 },{ 40, 0, 9 },{ 40, 0, 8 }, }, { { 48, 104, 566 },{ 48, 104, 560 },{ 48, 0, 9 },{ 48, 0, 8 }, },
+ { { 9, 138, 2758 },{ 130, 7, 1352 },{ 9, 57, 70 },{ 57, 9, 8 }, }, { { 119, 0, 313 },{ 120, 0, 312 },{ 17, 65, 70 },{ 65, 17, 8 }, },
+ { { 0, 128, 784 },{ 128, 6, 312 },{ 25, 73, 70 },{ 73, 25, 8 }, }, { { 6, 137, 790 },{ 5, 136, 784 },{ 33, 81, 70 },{ 81, 33, 8 }, },
+ { { 42, 171, 2758 },{ 14, 145, 784 },{ 42, 90, 70 },{ 90, 42, 8 }, }, { { 50, 179, 2758 },{ 22, 153, 784 },{ 50, 98, 70 },{ 98, 50, 8 }, },
+ { { 58, 187, 2758 },{ 30, 161, 784 },{ 58, 106, 70 },{ 106, 58, 8 }, }, { { 191, 18, 1329 },{ 38, 169, 784 },{ 112, 9, 33 },{ 114, 66, 8 }, },
+ { { 176, 0, 239 },{ 47, 178, 784 },{ 121, 18, 33 },{ 123, 75, 8 }, }, { { 187, 1, 239 },{ 55, 186, 784 },{ 129, 26, 33 },{ 131, 83, 8 }, },
+ { { 195, 10, 239 },{ 63, 194, 784 },{ 137, 34, 33 },{ 139, 91, 8 }, }, { { 203, 18, 239 },{ 71, 202, 784 },{ 145, 42, 33 },{ 147, 99, 8 }, },
+ { { 212, 27, 239 },{ 80, 211, 784 },{ 154, 51, 33 },{ 156, 108, 8 }, }, { { 220, 35, 239 },{ 88, 219, 784 },{ 162, 59, 33 },{ 164, 116, 8 }, },
+ { { 228, 43, 239 },{ 96, 227, 784 },{ 170, 67, 33 },{ 172, 124, 8 }, }, { { 236, 51, 239 },{ 104, 235, 784 },{ 178, 75, 33 },{ 180, 132, 8 }, },
+ { { 245, 60, 239 },{ 113, 244, 784 },{ 187, 84, 33 },{ 189, 141, 8 }, }, { { 91, 194, 3680 },{ 149, 197, 3648 },{ 195, 92, 33 },{ 197, 149, 8 }, },
+ { { 99, 202, 3680 },{ 157, 205, 3648 },{ 203, 100, 33 },{ 205, 157, 8 }, }, { { 107, 210, 3680 },{ 165, 213, 3648 },{ 211, 108, 33 },{ 213, 165, 8 }, },
+ { { 119, 249, 3928 },{ 174, 222, 3648 },{ 220, 117, 33 },{ 222, 174, 8 }, }, { { 127, 255, 856 },{ 182, 230, 3648 },{ 228, 125, 33 },{ 230, 182, 8 }, },
+ { { 255, 135, 169 },{ 190, 238, 3648 },{ 236, 133, 33 },{ 238, 190, 8 }, }, { { 140, 243, 3680 },{ 198, 246, 3648 },{ 244, 141, 33 },{ 246, 198, 8 }, },
+ { { 151, 207, 4040 },{ 255, 207, 8 },{ 151, 207, 456 },{ 255, 207, 8 }, }, { { 159, 215, 4040 },{ 255, 215, 8 },{ 159, 215, 456 },{ 255, 215, 8 }, },
+ { { 167, 223, 4040 },{ 255, 223, 8 },{ 167, 223, 456 },{ 255, 223, 8 }, }, { { 175, 231, 4040 },{ 255, 231, 8 },{ 175, 231, 456 },{ 255, 231, 8 }, },
+ { { 33, 106, 566 },{ 33, 106, 560 },{ 33, 0, 9 },{ 33, 0, 8 }, }, { { 41, 114, 566 },{ 41, 114, 560 },{ 41, 0, 9 },{ 41, 0, 8 }, },
+ { { 49, 122, 566 },{ 49, 122, 560 },{ 49, 0, 9 },{ 49, 0, 8 }, }, { { 57, 130, 566 },{ 57, 130, 560 },{ 57, 0, 9 },{ 57, 0, 8 }, },
+ { { 66, 139, 566 },{ 66, 139, 560 },{ 66, 0, 9 },{ 66, 0, 8 }, }, { { 74, 147, 566 },{ 170, 7, 1352 },{ 8, 74, 70 },{ 74, 8, 8 }, },
+ { { 152, 0, 313 },{ 178, 15, 1352 },{ 0, 82, 80 },{ 82, 16, 8 }, }, { { 162, 0, 313 },{ 186, 23, 1352 },{ 24, 90, 70 },{ 90, 24, 8 }, },
+ { { 0, 171, 784 },{ 195, 32, 1352 },{ 33, 99, 70 },{ 99, 33, 8 }, }, { { 6, 179, 790 },{ 203, 40, 1352 },{ 41, 107, 70 },{ 107, 41, 8 }, },
+ { { 15, 187, 790 },{ 211, 48, 1352 },{ 115, 0, 41 },{ 115, 49, 8 }, }, { { 61, 199, 710 },{ 219, 56, 1352 },{ 57, 123, 70 },{ 123, 57, 8 }, },
+ { { 70, 208, 710 },{ 228, 65, 1352 },{ 66, 132, 70 },{ 132, 66, 8 }, }, { { 78, 216, 710 },{ 236, 73, 1352 },{ 74, 140, 70 },{ 140, 74, 8 }, },
+ { { 86, 224, 710 },{ 244, 81, 1352 },{ 145, 7, 33 },{ 148, 82, 8 }, }, { { 222, 8, 233 },{ 252, 89, 1352 },{ 153, 15, 33 },{ 156, 90, 8 }, },
+ { { 235, 0, 239 },{ 241, 101, 328 },{ 166, 6, 39 },{ 165, 99, 8 }, }, { { 32, 170, 3680 },{ 249, 109, 328 },{ 0, 175, 98 },{ 173, 107, 8 }, },
+ { { 40, 178, 3680 },{ 115, 181, 3648 },{ 8, 183, 98 },{ 181, 115, 8 }, }, { { 48, 186, 3680 },{ 123, 189, 3648 },{ 16, 191, 98 },{ 189, 123, 8 }, },
+ { { 57, 195, 3680 },{ 132, 198, 3648 },{ 25, 200, 98 },{ 198, 132, 8 }, }, { { 67, 243, 3928 },{ 140, 206, 3648 },{ 33, 208, 98 },{ 206, 140, 8 }, },
+ { { 76, 251, 3928 },{ 148, 214, 3648 },{ 41, 216, 98 },{ 214, 148, 8 }, }, { { 86, 255, 856 },{ 156, 222, 3648 },{ 49, 224, 98 },{ 222, 156, 8 }, },
+ { { 255, 93, 169 },{ 165, 231, 3648 },{ 58, 233, 98 },{ 231, 165, 8 }, }, { { 98, 236, 3680 },{ 173, 239, 3648 },{ 66, 241, 98 },{ 239, 173, 8 }, },
+ { { 108, 181, 4040 },{ 181, 247, 3648 },{ 74, 249, 98 },{ 247, 181, 8 }, }, { { 116, 189, 4040 },{ 255, 189, 8 },{ 116, 189, 456 },{ 255, 189, 8 }, },
+ { { 125, 198, 4040 },{ 255, 198, 8 },{ 125, 198, 456 },{ 255, 198, 8 }, }, { { 133, 206, 4040 },{ 255, 206, 8 },{ 133, 206, 456 },{ 255, 206, 8 }, },
+ { { 141, 214, 4040 },{ 255, 214, 8 },{ 141, 214, 456 },{ 255, 214, 8 }, }, { { 149, 222, 4040 },{ 255, 222, 8 },{ 149, 222, 456 },{ 255, 222, 8 }, },
+ { { 47, 183, 566 },{ 47, 183, 560 },{ 47, 0, 9 },{ 47, 0, 8 }, }, { { 55, 191, 566 },{ 55, 191, 560 },{ 55, 0, 9 },{ 55, 0, 8 }, },
+ { { 63, 199, 566 },{ 63, 199, 560 },{ 63, 0, 9 },{ 63, 0, 8 }, }, { { 71, 207, 566 },{ 71, 207, 560 },{ 71, 0, 9 },{ 71, 0, 8 }, },
+ { { 80, 216, 566 },{ 80, 216, 560 },{ 80, 0, 9 },{ 80, 0, 8 }, }, { { 88, 224, 566 },{ 88, 224, 560 },{ 88, 0, 9 },{ 88, 0, 8 }, },
+ { { 3, 233, 710 },{ 3, 233, 704 },{ 2, 96, 70 },{ 96, 2, 8 }, }, { { 11, 241, 710 },{ 11, 241, 704 },{ 10, 104, 70 },{ 104, 10, 8 }, },
+ { { 20, 250, 710 },{ 20, 250, 704 },{ 19, 113, 70 },{ 113, 19, 8 }, }, { { 27, 121, 3654 },{ 27, 121, 3648 },{ 27, 121, 70 },{ 121, 27, 8 }, },
+ { { 35, 129, 3654 },{ 35, 129, 3648 },{ 35, 129, 70 },{ 129, 35, 8 }, }, { { 43, 137, 3654 },{ 43, 137, 3648 },{ 43, 137, 70 },{ 137, 43, 8 }, },
+ { { 52, 146, 3654 },{ 52, 146, 3648 },{ 52, 146, 70 },{ 146, 52, 8 }, }, { { 60, 154, 3654 },{ 60, 154, 3648 },{ 60, 154, 70 },{ 154, 60, 8 }, },
+ { { 68, 162, 3654 },{ 68, 162, 3648 },{ 68, 162, 70 },{ 162, 68, 8 }, }, { { 76, 170, 3654 },{ 76, 170, 3648 },{ 76, 170, 70 },{ 170, 76, 8 }, },
+ { { 85, 179, 3654 },{ 85, 179, 3648 },{ 85, 179, 70 },{ 179, 85, 8 }, }, { { 93, 187, 3654 },{ 93, 187, 3648 },{ 93, 187, 70 },{ 187, 93, 8 }, },
+ { { 101, 195, 3654 },{ 101, 195, 3648 },{ 101, 195, 70 },{ 195, 101, 8 }, }, { { 109, 203, 3654 },{ 109, 203, 3648 },{ 109, 203, 70 },{ 203, 109, 8 }, },
+ { { 118, 212, 3654 },{ 118, 212, 3648 },{ 118, 212, 70 },{ 212, 118, 8 }, }, { { 126, 220, 3654 },{ 126, 220, 3648 },{ 126, 220, 70 },{ 220, 126, 8 }, },
+ { { 134, 228, 3654 },{ 134, 228, 3648 },{ 134, 228, 70 },{ 228, 134, 8 }, }, { { 5, 236, 3680 },{ 142, 236, 3648 },{ 5, 236, 96 },{ 236, 142, 8 }, },
+ { { 14, 245, 3680 },{ 151, 245, 3648 },{ 14, 245, 96 },{ 245, 151, 8 }, }, { { 23, 159, 4040 },{ 159, 253, 3648 },{ 23, 159, 456 },{ 253, 159, 8 }, },
+ { { 31, 167, 4040 },{ 255, 167, 8 },{ 31, 167, 456 },{ 255, 167, 8 }, }, { { 39, 175, 4040 },{ 255, 175, 8 },{ 39, 175, 456 },{ 255, 175, 8 }, },
+ { { 48, 184, 4040 },{ 255, 184, 8 },{ 48, 184, 456 },{ 255, 184, 8 }, }, { { 56, 192, 4040 },{ 255, 192, 8 },{ 56, 192, 456 },{ 255, 192, 8 }, },
+ { { 64, 200, 4040 },{ 255, 200, 8 },{ 64, 200, 456 },{ 255, 200, 8 }, },{ { 72, 208, 4040 },{ 255, 208, 8 },{ 72, 208, 456 },{ 255, 208, 8 }, },
+
+ };
+
+ struct dxt5a_block
+ {
+ uint8_t m_endpoints[2];
+
+ enum { cTotalSelectorBytes = 6 };
+ uint8_t m_selectors[cTotalSelectorBytes];
+
+ inline void clear()
+ {
+ basisu::clear_obj(*this);
+ }
+
+ inline uint32_t get_low_alpha() const
+ {
+ return m_endpoints[0];
+ }
+
+ inline uint32_t get_high_alpha() const
+ {
+ return m_endpoints[1];
+ }
+
+ inline void set_low_alpha(uint32_t i)
+ {
+ assert(i <= UINT8_MAX);
+ m_endpoints[0] = static_cast<uint8_t>(i);
+ }
+
+ inline void set_high_alpha(uint32_t i)
+ {
+ assert(i <= UINT8_MAX);
+ m_endpoints[1] = static_cast<uint8_t>(i);
+ }
+
+ inline bool is_alpha6_block() const { return get_low_alpha() <= get_high_alpha(); }
+
+ uint32_t get_endpoints_as_word() const { return m_endpoints[0] | (m_endpoints[1] << 8); }
+ uint32_t get_selectors_as_word(uint32_t index) { assert(index < 3); return m_selectors[index * 2] | (m_selectors[index * 2 + 1] << 8); }
+
+ inline uint32_t get_selector(uint32_t x, uint32_t y) const
+ {
+ assert((x < 4U) && (y < 4U));
+
+ uint32_t selector_index = (y * 4) + x;
+ uint32_t bit_index = selector_index * cDXT5SelectorBits;
+
+ uint32_t byte_index = bit_index >> 3;
+ uint32_t bit_ofs = bit_index & 7;
+
+ uint32_t v = m_selectors[byte_index];
+ if (byte_index < (cTotalSelectorBytes - 1))
+ v |= (m_selectors[byte_index + 1] << 8);
+
+ return (v >> bit_ofs) & 7;
+ }
+
+ inline void set_selector(uint32_t x, uint32_t y, uint32_t val)
+ {
+ assert((x < 4U) && (y < 4U) && (val < 8U));
+
+ uint32_t selector_index = (y * 4) + x;
+ uint32_t bit_index = selector_index * cDXT5SelectorBits;
+
+ uint32_t byte_index = bit_index >> 3;
+ uint32_t bit_ofs = bit_index & 7;
+
+ uint32_t v = m_selectors[byte_index];
+ if (byte_index < (cTotalSelectorBytes - 1))
+ v |= (m_selectors[byte_index + 1] << 8);
+
+ v &= (~(7 << bit_ofs));
+ v |= (val << bit_ofs);
+
+ m_selectors[byte_index] = static_cast<uint8_t>(v);
+ if (byte_index < (cTotalSelectorBytes - 1))
+ m_selectors[byte_index + 1] = static_cast<uint8_t>(v >> 8);
+ }
+
+ enum { cMaxSelectorValues = 8 };
+
+ static uint32_t get_block_values6(color32* pDst, uint32_t l, uint32_t h)
+ {
+ pDst[0].a = static_cast<uint8_t>(l);
+ pDst[1].a = static_cast<uint8_t>(h);
+ pDst[2].a = static_cast<uint8_t>((l * 4 + h) / 5);
+ pDst[3].a = static_cast<uint8_t>((l * 3 + h * 2) / 5);
+ pDst[4].a = static_cast<uint8_t>((l * 2 + h * 3) / 5);
+ pDst[5].a = static_cast<uint8_t>((l + h * 4) / 5);
+ pDst[6].a = 0;
+ pDst[7].a = 255;
+ return 6;
+ }
+
+ static uint32_t get_block_values8(color32* pDst, uint32_t l, uint32_t h)
+ {
+ pDst[0].a = static_cast<uint8_t>(l);
+ pDst[1].a = static_cast<uint8_t>(h);
+ pDst[2].a = static_cast<uint8_t>((l * 6 + h) / 7);
+ pDst[3].a = static_cast<uint8_t>((l * 5 + h * 2) / 7);
+ pDst[4].a = static_cast<uint8_t>((l * 4 + h * 3) / 7);
+ pDst[5].a = static_cast<uint8_t>((l * 3 + h * 4) / 7);
+ pDst[6].a = static_cast<uint8_t>((l * 2 + h * 5) / 7);
+ pDst[7].a = static_cast<uint8_t>((l + h * 6) / 7);
+ return 8;
+ }
+
+ static uint32_t get_block_values(color32* pDst, uint32_t l, uint32_t h)
+ {
+ if (l > h)
+ return get_block_values8(pDst, l, h);
+ else
+ return get_block_values6(pDst, l, h);
+ }
+ };
+
+ static void convert_etc1s_to_dxt5a(dxt5a_block* pDst_block, const endpoint* pEndpoints, const selector* pSelector)
+ {
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ const color32& base_color = pEndpoints->m_color5;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ if (low_selector == high_selector)
+ {
+ uint32_t r;
+ decoder_etc_block::get_block_color5_r(base_color, inten_table, low_selector, r);
+
+ pDst_block->set_low_alpha(r);
+ pDst_block->set_high_alpha(r);
+ pDst_block->m_selectors[0] = 0;
+ pDst_block->m_selectors[1] = 0;
+ pDst_block->m_selectors[2] = 0;
+ pDst_block->m_selectors[3] = 0;
+ pDst_block->m_selectors[4] = 0;
+ pDst_block->m_selectors[5] = 0;
+ return;
+ }
+ else if (pSelector->m_num_unique_selectors == 2)
+ {
+ color32 block_colors[4];
+
+ decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table);
+
+ const uint32_t r0 = block_colors[low_selector].r;
+ const uint32_t r1 = block_colors[high_selector].r;
+
+ pDst_block->set_low_alpha(r0);
+ pDst_block->set_high_alpha(r1);
+
+ // TODO: Optimize this
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+ pDst_block->set_selector(x, y, (s == high_selector) ? 1 : 0);
+ }
+ }
+
+ return;
+ }
+
+ uint32_t selector_range_table = 0;
+ for (selector_range_table = 0; selector_range_table < NUM_DXT5A_SELECTOR_RANGES; selector_range_table++)
+ if ((low_selector == s_dxt5a_selector_ranges[selector_range_table].m_low) && (high_selector == s_dxt5a_selector_ranges[selector_range_table].m_high))
+ break;
+ if (selector_range_table >= NUM_DXT5A_SELECTOR_RANGES)
+ selector_range_table = 0;
+
+ const etc1_g_to_dxt5a_conversion* pTable_entry = &g_etc1_g_to_dxt5a[base_color.r + inten_table * 32][selector_range_table];
+
+ pDst_block->set_low_alpha(pTable_entry->m_lo);
+ pDst_block->set_high_alpha(pTable_entry->m_hi);
+
+ // TODO: Optimize this (like ETC1->BC1)
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+
+ uint32_t ds = (pTable_entry->m_trans >> (s * 3)) & 7;
+
+ pDst_block->set_selector(x, y, ds);
+ }
+ }
+ }
+#endif //BASISD_SUPPORT_DXT5A
+
+ // PVRTC
+
+#if BASISD_SUPPORT_PVRTC1
+ static const uint16_t g_pvrtc_swizzle_table[256] =
+ {
+ 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
+ 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
+ 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
+ 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
+ 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
+ 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
+ 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
+ 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
+ };
+
+ // Note we can't use simple calculations to convert PVRTC1 encoded endpoint components to/from 8-bits, due to hardware approximations.
+ static const uint8_t g_pvrtc_5[32] = { 0,8,16,24,33,41,49,57,66,74,82,90,99,107,115,123,132,140,148,156,165,173,181,189,198,206,214,222,231,239,247,255 };
+ static const uint8_t g_pvrtc_4[16] = { 0,16,33,49,66,82,99,115,140,156,173,189,206,222,239,255 };
+ static const uint8_t g_pvrtc_3[8] = { 0,33,74,107,148,181,222,255 };
+ static const uint8_t g_pvrtc_alpha[9] = { 0,34,68,102,136,170,204,238,255 };
+
+ static const uint8_t g_pvrtc_5_floor[256] =
+ {
+ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,
+ 3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,
+ 7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,
+ 11,11,11,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15,
+ 15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,
+ 19,19,19,19,19,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,
+ 23,23,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,27,27,
+ 27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,31
+ };
+
+ static const uint8_t g_pvrtc_5_ceil[256] =
+ {
+ 0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,
+ 4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,8,8,8,8,8,8,
+ 8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,12,12,12,12,12,
+ 12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,16,16,16,16,
+ 16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,
+ 20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,
+ 24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,28,
+ 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,31,31,31,31,31,31,31,31
+ };
+
+ static const uint8_t g_pvrtc_4_floor[256] =
+ {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15
+ };
+
+ static const uint8_t g_pvrtc_4_ceil[256] =
+ {
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,
+ 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,
+ 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
+ };
+
+ static const uint8_t g_pvrtc_3_floor[256] =
+ {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,
+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7
+ };
+
+ static const uint8_t g_pvrtc_3_ceil[256] =
+ {
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,
+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+ };
+
+ static const uint8_t g_pvrtc_alpha_floor[256] =
+ {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8
+ };
+
+ static const uint8_t g_pvrtc_alpha_ceil[256] =
+ {
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+ };
+
+ struct pvrtc4_block
+ {
+ uint32_t m_modulation;
+ uint32_t m_endpoints;
+
+ pvrtc4_block() : m_modulation(0), m_endpoints(0) { }
+
+ inline bool operator== (const pvrtc4_block& rhs) const
+ {
+ return (m_modulation == rhs.m_modulation) && (m_endpoints == rhs.m_endpoints);
+ }
+
+ inline void clear()
+ {
+ m_modulation = 0;
+ m_endpoints = 0;
+ }
+
+ inline bool get_block_uses_transparent_modulation() const
+ {
+ return (m_endpoints & 1) != 0;
+ }
+
+ inline void set_block_uses_transparent_modulation(bool m)
+ {
+ m_endpoints = (m_endpoints & ~1U) | static_cast<uint32_t>(m);
+ }
+
+ inline bool is_endpoint_opaque(uint32_t endpoint_index) const
+ {
+ static const uint32_t s_bitmasks[2] = { 0x8000U, 0x80000000U };
+ return (m_endpoints & s_bitmasks[basisu::open_range_check(endpoint_index, 2U)]) != 0;
+ }
+
+ inline void set_endpoint_opaque(uint32_t endpoint_index, bool opaque)
+ {
+ assert(endpoint_index < 2);
+ static const uint32_t s_bitmasks[2] = { 0x8000U, 0x80000000U };
+ if (opaque)
+ m_endpoints |= s_bitmasks[endpoint_index];
+ else
+ m_endpoints &= ~s_bitmasks[endpoint_index];
+ }
+
+ inline color32 get_endpoint_5554(uint32_t endpoint_index) const
+ {
+ assert(endpoint_index < 2);
+ static const uint32_t s_endpoint_mask[2] = { 0xFFFE, 0xFFFF };
+ uint32_t packed = (m_endpoints >> (basisu::open_range_check(endpoint_index, 2U) ? 16 : 0)) & s_endpoint_mask[endpoint_index];
+
+ uint32_t r, g, b, a;
+ if (packed & 0x8000)
+ {
+ // opaque 554 or 555
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = packed & 31;
+
+ if (!endpoint_index)
+ b |= (b >> 4);
+
+ a = 0xF;
+ }
+ else
+ {
+ // translucent 4433 or 4443
+ r = (packed >> 7) & 0x1E;
+ g = (packed >> 3) & 0x1E;
+ b = (packed & 0xF) << 1;
+
+ r |= (r >> 4);
+ g |= (g >> 4);
+
+ if (!endpoint_index)
+ b |= (b >> 3);
+ else
+ b |= (b >> 4);
+
+ a = (packed >> 11) & 0xE;
+ }
+
+ assert((r < 32) && (g < 32) && (b < 32) && (a < 16));
+
+ return color32(r, g, b, a);
+ }
+
+ inline color32 get_endpoint_8888(uint32_t endpoint_index) const
+ {
+ assert(endpoint_index < 2);
+ static const uint32_t s_endpoint_mask[2] = { 0xFFFE, 0xFFFF };
+ uint32_t packed = (m_endpoints >> (basisu::open_range_check(endpoint_index, 2U) ? 16 : 0)) & s_endpoint_mask[endpoint_index];
+
+ uint32_t r, g, b, a;
+ if (packed & 0x8000)
+ {
+ // opaque 554 or 555
+ // 1RRRRRGGGGGBBBBM
+ // 1RRRRRGGGGGBBBBB
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = packed & 31;
+
+ r = g_pvrtc_5[r];
+ g = g_pvrtc_5[g];
+
+ if (!endpoint_index)
+ b = g_pvrtc_4[b >> 1];
+ else
+ b = g_pvrtc_5[b];
+
+ a = 255;
+ }
+ else
+ {
+ // translucent 4433 or 4443
+ // 0AAA RRRR GGGG BBBM
+ // 0AAA RRRR GGGG BBBB
+ r = (packed >> 8) & 0xF;
+ g = (packed >> 4) & 0xF;
+ b = packed & 0xF;
+ a = (packed >> 12) & 7;
+
+ r = g_pvrtc_4[r];
+ g = g_pvrtc_4[g];
+
+ if (!endpoint_index)
+ b = g_pvrtc_3[b >> 1];
+ else
+ b = g_pvrtc_4[b];
+
+ a = g_pvrtc_alpha[a];
+ }
+
+ return color32(r, g, b, a);
+ }
+
+ inline uint32_t get_endpoint_l8(uint32_t endpoint_index) const
+ {
+ color32 c(get_endpoint_8888(endpoint_index));
+ return c.r + c.g + c.b + c.a;
+ }
+
+ inline uint32_t get_opaque_endpoint_l0() const
+ {
+ uint32_t packed = m_endpoints & 0xFFFE;
+
+ uint32_t r, g, b;
+ assert(packed & 0x8000);
+
+ // opaque 554 or 555
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = packed & 31;
+ b |= (b >> 4);
+
+ return r + g + b;
+ }
+
+ inline uint32_t get_opaque_endpoint_l1() const
+ {
+ uint32_t packed = m_endpoints >> 16;
+
+ uint32_t r, g, b;
+ assert(packed & 0x8000);
+
+ // opaque 554 or 555
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = packed & 31;
+
+ return r + g + b;
+ }
+
+ static uint32_t get_component_precision_in_bits(uint32_t c, uint32_t endpoint_index, bool opaque_endpoint)
+ {
+ static const uint32_t s_comp_prec[4][4] =
+ {
+ // R0 G0 B0 A0 R1 G1 B1 A1
+ { 4, 4, 3, 3 },{ 4, 4, 4, 3 }, // transparent endpoint
+
+ { 5, 5, 4, 0 },{ 5, 5, 5, 0 } // opaque endpoint
+ };
+ return s_comp_prec[basisu::open_range_check(endpoint_index, 2U) + (opaque_endpoint * 2)][basisu::open_range_check(c, 4U)];
+ }
+
+ static color32 get_color_precision_in_bits(uint32_t endpoint_index, bool opaque_endpoint)
+ {
+ static const color32 s_color_prec[4] =
+ {
+ color32(4, 4, 3, 3), color32(4, 4, 4, 3), // transparent endpoint
+ color32(5, 5, 4, 0), color32(5, 5, 5, 0) // opaque endpoint
+ };
+ return s_color_prec[basisu::open_range_check(endpoint_index, 2U) + (opaque_endpoint * 2)];
+ }
+
+ inline void set_opaque_endpoint_floor(uint32_t endpoint_index, const color32& c)
+ {
+ assert(endpoint_index < 2);
+ const uint32_t m = m_endpoints & 1;
+
+ uint32_t r = g_pvrtc_5_floor[c[0]], g = g_pvrtc_5_floor[c[1]], b = c[2];
+
+ if (!endpoint_index)
+ b = g_pvrtc_4_floor[b] << 1;
+ else
+ b = g_pvrtc_5_floor[b];
+
+ // rgba=555 here
+ assert((r < 32) && (g < 32) && (b < 32));
+
+ // 1RRRRRGGGGGBBBBM
+ // 1RRRRRGGGGGBBBBB
+
+ // opaque 554 or 555
+ uint32_t packed = 0x8000 | (r << 10) | (g << 5) | b;
+ if (!endpoint_index)
+ packed = (packed & ~1) | m;
+
+ assert(packed <= 0xFFFF);
+
+ if (endpoint_index)
+ m_endpoints = (m_endpoints & 0xFFFFU) | (packed << 16);
+ else
+ m_endpoints = (m_endpoints & 0xFFFF0000U) | packed;
+ }
+
+ inline void set_opaque_endpoint_ceil(uint32_t endpoint_index, const color32& c)
+ {
+ assert(endpoint_index < 2);
+ const uint32_t m = m_endpoints & 1;
+
+ uint32_t r = g_pvrtc_5_ceil[c[0]], g = g_pvrtc_5_ceil[c[1]], b = c[2];
+
+ if (!endpoint_index)
+ b = g_pvrtc_4_ceil[b] << 1;
+ else
+ b = g_pvrtc_5_ceil[b];
+
+ // rgba=555 here
+ assert((r < 32) && (g < 32) && (b < 32));
+
+ // 1RRRRRGGGGGBBBBM
+ // 1RRRRRGGGGGBBBBB
+
+ // opaque 554 or 555
+ uint32_t packed = 0x8000 | (r << 10) | (g << 5) | b;
+ if (!endpoint_index)
+ packed |= m;
+
+ assert(packed <= 0xFFFF);
+
+ if (endpoint_index)
+ m_endpoints = (m_endpoints & 0xFFFFU) | (packed << 16);
+ else
+ m_endpoints = (m_endpoints & 0xFFFF0000U) | packed;
+ }
+
+ // opaque endpoints: 554 or 555
+ // transparent endpoints: 3443 or 3444
+ inline void set_endpoint_raw(uint32_t endpoint_index, const color32& c, bool opaque_endpoint)
+ {
+ assert(endpoint_index < 2);
+ const uint32_t m = m_endpoints & 1;
+ uint32_t r = c[0], g = c[1], b = c[2], a = c[3];
+
+ uint32_t packed;
+
+ if (opaque_endpoint)
+ {
+ if (!endpoint_index)
+ {
+ // 554
+ // 1RRRRRGGGGGBBBBM
+ assert((r < 32) && (g < 32) && (b < 16));
+ packed = 0x8000 | (r << 10) | (g << 5) | (b << 1) | m;
+ }
+ else
+ {
+ // 555
+ // 1RRRRRGGGGGBBBBB
+ assert((r < 32) && (g < 32) && (b < 32));
+ packed = 0x8000 | (r << 10) | (g << 5) | b;
+ }
+ }
+ else
+ {
+ if (!endpoint_index)
+ {
+ // 3443
+ // 0AAA RRRR GGGG BBBM
+ assert((r < 16) && (g < 16) && (b < 8) && (a < 8));
+ packed = (a << 12) | (r << 8) | (g << 4) | (b << 1) | m;
+ }
+ else
+ {
+ // 3444
+ // 0AAA RRRR GGGG BBBB
+ assert((r < 16) && (g < 16) && (b < 16) && (a < 8));
+ packed = (a << 12) | (r << 8) | (g << 4) | b;
+ }
+ }
+
+ assert(packed <= 0xFFFF);
+
+ if (endpoint_index)
+ m_endpoints = (m_endpoints & 0xFFFFU) | (packed << 16);
+ else
+ m_endpoints = (m_endpoints & 0xFFFF0000U) | packed;
+ }
+
+ inline void set_endpoint_floor(uint32_t endpoint_index, const color32& c)
+ {
+ assert(endpoint_index < 2);
+
+ int a = g_pvrtc_alpha_floor[c.a];
+ if (a == 8)
+ {
+ // 554 or 555
+ uint32_t r = g_pvrtc_5_floor[c[0]], g = g_pvrtc_5_floor[c[1]], b = c[2];
+
+ if (!endpoint_index)
+ b = g_pvrtc_4_floor[b];
+ else
+ b = g_pvrtc_5_floor[b];
+
+ set_endpoint_raw(endpoint_index, color32(r, g, b, a), true);
+ }
+ else
+ {
+ // 4433 or 4443
+ uint32_t r = g_pvrtc_4_floor[c[0]], g = g_pvrtc_4_floor[c[1]], b = c[2];
+
+ if (!endpoint_index)
+ b = g_pvrtc_3_floor[b];
+ else
+ b = g_pvrtc_4_floor[b];
+
+ set_endpoint_raw(endpoint_index, color32(r, g, b, a), false);
+ }
+ }
+
+ inline void set_endpoint_ceil(uint32_t endpoint_index, const color32& c)
+ {
+ assert(endpoint_index < 2);
+
+ int a = g_pvrtc_alpha_ceil[c.a];
+ if (a == 8)
+ {
+ // 554 or 555
+ uint32_t r = g_pvrtc_5_ceil[c[0]], g = g_pvrtc_5_ceil[c[1]], b = c[2];
+
+ if (!endpoint_index)
+ b = g_pvrtc_4_ceil[b];
+ else
+ b = g_pvrtc_5_ceil[b];
+
+ set_endpoint_raw(endpoint_index, color32(r, g, b, a), true);
+ }
+ else
+ {
+ // 4433 or 4443
+ uint32_t r = g_pvrtc_4_ceil[c[0]], g = g_pvrtc_4_ceil[c[1]], b = c[2];
+
+ if (!endpoint_index)
+ b = g_pvrtc_3_ceil[b];
+ else
+ b = g_pvrtc_4_ceil[b];
+
+ set_endpoint_raw(endpoint_index, color32(r, g, b, a), false);
+ }
+ }
+
+ inline uint32_t get_modulation(uint32_t x, uint32_t y) const
+ {
+ assert((x < 4) && (y < 4));
+ return (m_modulation >> ((y * 4 + x) * 2)) & 3;
+ }
+
+ // Scaled by 8
+ inline const uint32_t* get_scaled_modulation_values(bool block_uses_transparent_modulation) const
+ {
+ static const uint32_t s_block_scales[2][4] = { { 0, 3, 5, 8 },{ 0, 4, 4, 8 } };
+ return s_block_scales[block_uses_transparent_modulation];
+ }
+
+ // Scaled by 8
+ inline uint32_t get_scaled_modulation(uint32_t x, uint32_t y) const
+ {
+ return get_scaled_modulation_values(get_block_uses_transparent_modulation())[get_modulation(x, y)];
+ }
+
+ inline void set_modulation(uint32_t x, uint32_t y, uint32_t s)
+ {
+ assert((x < 4) && (y < 4) && (s < 4));
+ uint32_t n = (y * 4 + x) * 2;
+ m_modulation = (m_modulation & (~(3 << n))) | (s << n);
+ assert(get_modulation(x, y) == s);
+ }
+
+ // Assumes modulation was initialized to 0
+ inline void set_modulation_fast(uint32_t x, uint32_t y, uint32_t s)
+ {
+ assert((x < 4) && (y < 4) && (s < 4));
+ uint32_t n = (y * 4 + x) * 2;
+ m_modulation |= (s << n);
+ assert(get_modulation(x, y) == s);
+ }
+ };
+
+ static const uint8_t g_pvrtc_bilinear_weights[16][4] =
+ {
+ { 4, 4, 4, 4 }, { 2, 6, 2, 6 }, { 8, 0, 8, 0 }, { 6, 2, 6, 2 },
+ { 2, 2, 6, 6 }, { 1, 3, 3, 9 }, { 4, 0, 12, 0 }, { 3, 1, 9, 3 },
+ { 8, 8, 0, 0 }, { 4, 12, 0, 0 }, { 16, 0, 0, 0 }, { 12, 4, 0, 0 },
+ { 6, 6, 2, 2 }, { 3, 9, 1, 3 }, { 12, 0, 4, 0 }, { 9, 3, 3, 1 },
+ };
+
+ struct pvrtc1_temp_block
+ {
+ decoder_etc_block m_etc1_block;
+ uint32_t m_pvrtc_endpoints;
+ };
+
+ static inline uint32_t get_opaque_endpoint_l0(uint32_t endpoints)
+ {
+ uint32_t packed = endpoints;
+
+ uint32_t r, g, b;
+ assert(packed & 0x8000);
+
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = packed & 30;
+ b |= (b >> 4);
+
+ return r + g + b;
+ }
+
+ static inline uint32_t get_opaque_endpoint_l1(uint32_t endpoints)
+ {
+ uint32_t packed = endpoints >> 16;
+
+ uint32_t r, g, b;
+ assert(packed & 0x8000);
+
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = packed & 31;
+
+ return r + g + b;
+ }
+
+ static color32 get_endpoint_8888(uint32_t endpoints, uint32_t endpoint_index)
+ {
+ assert(endpoint_index < 2);
+ static const uint32_t s_endpoint_mask[2] = { 0xFFFE, 0xFFFF };
+ uint32_t packed = (endpoints >> (basisu::open_range_check(endpoint_index, 2U) ? 16 : 0)) & s_endpoint_mask[endpoint_index];
+
+ uint32_t r, g, b, a;
+ if (packed & 0x8000)
+ {
+ // opaque 554 or 555
+ // 1RRRRRGGGGGBBBBM
+ // 1RRRRRGGGGGBBBBB
+ r = (packed >> 10) & 31;
+ g = (packed >> 5) & 31;
+ b = packed & 31;
+
+ r = g_pvrtc_5[r];
+ g = g_pvrtc_5[g];
+
+ if (!endpoint_index)
+ b = g_pvrtc_4[b >> 1];
+ else
+ b = g_pvrtc_5[b];
+
+ a = 255;
+ }
+ else
+ {
+ // translucent 4433 or 4443
+ // 0AAA RRRR GGGG BBBM
+ // 0AAA RRRR GGGG BBBB
+ r = (packed >> 8) & 0xF;
+ g = (packed >> 4) & 0xF;
+ b = packed & 0xF;
+ a = (packed >> 12) & 7;
+
+ r = g_pvrtc_4[r];
+ g = g_pvrtc_4[g];
+
+ if (!endpoint_index)
+ b = g_pvrtc_3[b >> 1];
+ else
+ b = g_pvrtc_4[b];
+
+ a = g_pvrtc_alpha[a];
+ }
+
+ return color32(r, g, b, a);
+ }
+
+ static uint32_t get_endpoint_l8(uint32_t endpoints, uint32_t endpoint_index)
+ {
+ color32 c(get_endpoint_8888(endpoints, endpoint_index));
+ return c.r + c.g + c.b + c.a;
+ }
+
+ // TODO: Support decoding a non-pow2 ETC1S texture into the next larger pow2 PVRTC texture.
+ static void fixup_pvrtc1_4_modulation_rgb(const decoder_etc_block* pETC_Blocks, const uint32_t* pPVRTC_endpoints, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y)
+ {
+ const uint32_t x_mask = num_blocks_x - 1;
+ const uint32_t y_mask = num_blocks_y - 1;
+ const uint32_t x_bits = basisu::total_bits(x_mask);
+ const uint32_t y_bits = basisu::total_bits(y_mask);
+ const uint32_t min_bits = basisu::minimum(x_bits, y_bits);
+ const uint32_t max_bits = basisu::maximum(x_bits, y_bits);
+ const uint32_t swizzle_mask = (1 << (min_bits * 2)) - 1;
+
+ uint32_t block_index = 0;
+
+ // really 3x3
+ int e0[4][4], e1[4][4];
+
+ for (int y = 0; y < static_cast<int>(num_blocks_y); y++)
+ {
+ const uint32_t* pE_rows[3];
+
+ for (int ey = 0; ey < 3; ey++)
+ {
+ int by = y + ey - 1;
+
+ const uint32_t* pE = &pPVRTC_endpoints[(by & y_mask) * num_blocks_x];
+
+ pE_rows[ey] = pE;
+
+ for (int ex = 0; ex < 3; ex++)
+ {
+ int bx = 0 + ex - 1;
+
+ const uint32_t e = pE[bx & x_mask];
+
+ e0[ex][ey] = (get_opaque_endpoint_l0(e) * 255) / 31;
+ e1[ex][ey] = (get_opaque_endpoint_l1(e) * 255) / 31;
+ }
+ }
+
+ const uint32_t y_swizzle = (g_pvrtc_swizzle_table[y >> 8] << 16) | g_pvrtc_swizzle_table[y & 0xFF];
+
+ for (int x = 0; x < static_cast<int>(num_blocks_x); x++, block_index++)
+ {
+ const decoder_etc_block& src_block = pETC_Blocks[block_index];
+
+ const uint32_t x_swizzle = (g_pvrtc_swizzle_table[x >> 8] << 17) | (g_pvrtc_swizzle_table[x & 0xFF] << 1);
+
+ uint32_t swizzled = x_swizzle | y_swizzle;
+ if (num_blocks_x != num_blocks_y)
+ {
+ swizzled &= swizzle_mask;
+
+ if (num_blocks_x > num_blocks_y)
+ swizzled |= ((x >> min_bits) << (min_bits * 2));
+ else
+ swizzled |= ((y >> min_bits) << (min_bits * 2));
+ }
+
+ pvrtc4_block* pDst_block = static_cast<pvrtc4_block*>(pDst_blocks) + swizzled;
+ pDst_block->m_endpoints = pPVRTC_endpoints[block_index];
+
+ uint32_t base_r = g_etc_5_to_8[src_block.m_differential.m_red1];
+ uint32_t base_g = g_etc_5_to_8[src_block.m_differential.m_green1];
+ uint32_t base_b = g_etc_5_to_8[src_block.m_differential.m_blue1];
+
+ const int* pInten_table48 = g_etc1_inten_tables48[src_block.m_differential.m_cw1];
+ int by = (base_r + base_g + base_b) * 16;
+ int block_colors_y_x16[4];
+ block_colors_y_x16[0] = by + pInten_table48[2];
+ block_colors_y_x16[1] = by + pInten_table48[3];
+ block_colors_y_x16[2] = by + pInten_table48[1];
+ block_colors_y_x16[3] = by + pInten_table48[0];
+
+ {
+ const uint32_t ex = 2;
+ int bx = x + ex - 1;
+ bx &= x_mask;
+
+#define DO_ROW(ey) \
+ { \
+ const uint32_t e = pE_rows[ey][bx]; \
+ e0[ex][ey] = (get_opaque_endpoint_l0(e) * 255) / 31; \
+ e1[ex][ey] = (get_opaque_endpoint_l1(e) * 255) / 31; \
+ }
+
+ DO_ROW(0);
+ DO_ROW(1);
+ DO_ROW(2);
+#undef DO_ROW
+ }
+
+ uint32_t mod = 0;
+
+ uint32_t lookup_x[4];
+
+#define DO_LOOKUP(lx) { \
+ const uint32_t byte_ofs = 7 - (((lx) * 4) >> 3); \
+ const uint32_t lsb_bits = src_block.m_bytes[byte_ofs] >> (((lx) & 1) * 4); \
+ const uint32_t msb_bits = src_block.m_bytes[byte_ofs - 2] >> (((lx) & 1) * 4); \
+ lookup_x[lx] = (lsb_bits & 0xF) | ((msb_bits & 0xF) << 4); }
+
+ DO_LOOKUP(0);
+ DO_LOOKUP(1);
+ DO_LOOKUP(2);
+ DO_LOOKUP(3);
+#undef DO_LOOKUP
+
+#define DO_PIX(lx, ly, w0, w1, w2, w3) \
+ { \
+ int ca_l = a0 * w0 + a1 * w1 + a2 * w2 + a3 * w3; \
+ int cb_l = b0 * w0 + b1 * w1 + b2 * w2 + b3 * w3; \
+ int cl = block_colors_y_x16[g_etc1_x_selector_unpack[ly][lookup_x[lx]]]; \
+ int dl = cb_l - ca_l; \
+ int vl = cl - ca_l; \
+ int p = vl * 16; \
+ if (ca_l > cb_l) { p = -p; dl = -dl; } \
+ uint32_t m = 0; \
+ if (p > 3 * dl) m = (uint32_t)(1 << ((ly) * 8 + (lx) * 2)); \
+ if (p > 8 * dl) m = (uint32_t)(2 << ((ly) * 8 + (lx) * 2)); \
+ if (p > 13 * dl) m = (uint32_t)(3 << ((ly) * 8 + (lx) * 2)); \
+ mod |= m; \
+ }
+
+ {
+ const uint32_t ex = 0, ey = 0;
+ const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1];
+ const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1];
+ DO_PIX(0, 0, 4, 4, 4, 4);
+ DO_PIX(1, 0, 2, 6, 2, 6);
+ DO_PIX(0, 1, 2, 2, 6, 6);
+ DO_PIX(1, 1, 1, 3, 3, 9);
+ }
+
+ {
+ const uint32_t ex = 1, ey = 0;
+ const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1];
+ const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1];
+ DO_PIX(2, 0, 8, 0, 8, 0);
+ DO_PIX(3, 0, 6, 2, 6, 2);
+ DO_PIX(2, 1, 4, 0, 12, 0);
+ DO_PIX(3, 1, 3, 1, 9, 3);
+ }
+
+ {
+ const uint32_t ex = 0, ey = 1;
+ const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1];
+ const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1];
+ DO_PIX(0, 2, 8, 8, 0, 0);
+ DO_PIX(1, 2, 4, 12, 0, 0);
+ DO_PIX(0, 3, 6, 6, 2, 2);
+ DO_PIX(1, 3, 3, 9, 1, 3);
+ }
+
+ {
+ const uint32_t ex = 1, ey = 1;
+ const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1];
+ const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1];
+ DO_PIX(2, 2, 16, 0, 0, 0);
+ DO_PIX(3, 2, 12, 4, 0, 0);
+ DO_PIX(2, 3, 12, 0, 4, 0);
+ DO_PIX(3, 3, 9, 3, 3, 1);
+ }
+#undef DO_PIX
+
+ pDst_block->m_modulation = mod;
+
+ e0[0][0] = e0[1][0]; e0[1][0] = e0[2][0];
+ e0[0][1] = e0[1][1]; e0[1][1] = e0[2][1];
+ e0[0][2] = e0[1][2]; e0[1][2] = e0[2][2];
+
+ e1[0][0] = e1[1][0]; e1[1][0] = e1[2][0];
+ e1[0][1] = e1[1][1]; e1[1][1] = e1[2][1];
+ e1[0][2] = e1[1][2]; e1[1][2] = e1[2][2];
+
+ } // x
+ } // y
+ }
+
+ static void fixup_pvrtc1_4_modulation_rgba(
+ const decoder_etc_block* pETC_Blocks,
+ const uint32_t* pPVRTC_endpoints,
+ void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, void *pAlpha_blocks,
+ const endpoint* pEndpoints, const selector* pSelectors)
+ {
+ const uint32_t x_mask = num_blocks_x - 1;
+ const uint32_t y_mask = num_blocks_y - 1;
+ const uint32_t x_bits = basisu::total_bits(x_mask);
+ const uint32_t y_bits = basisu::total_bits(y_mask);
+ const uint32_t min_bits = basisu::minimum(x_bits, y_bits);
+ const uint32_t max_bits = basisu::maximum(x_bits, y_bits);
+ const uint32_t swizzle_mask = (1 << (min_bits * 2)) - 1;
+
+ uint32_t block_index = 0;
+
+ // really 3x3
+ int e0[4][4], e1[4][4];
+
+ for (int y = 0; y < static_cast<int>(num_blocks_y); y++)
+ {
+ const uint32_t* pE_rows[3];
+
+ for (int ey = 0; ey < 3; ey++)
+ {
+ int by = y + ey - 1;
+
+ const uint32_t* pE = &pPVRTC_endpoints[(by & y_mask) * num_blocks_x];
+
+ pE_rows[ey] = pE;
+
+ for (int ex = 0; ex < 3; ex++)
+ {
+ int bx = 0 + ex - 1;
+
+ const uint32_t e = pE[bx & x_mask];
+
+ e0[ex][ey] = get_endpoint_l8(e, 0);
+ e1[ex][ey] = get_endpoint_l8(e, 1);
+ }
+ }
+
+ const uint32_t y_swizzle = (g_pvrtc_swizzle_table[y >> 8] << 16) | g_pvrtc_swizzle_table[y & 0xFF];
+
+ for (int x = 0; x < static_cast<int>(num_blocks_x); x++, block_index++)
+ {
+ const decoder_etc_block& src_block = pETC_Blocks[block_index];
+
+ const uint16_t* pSrc_alpha_block = reinterpret_cast<const uint16_t*>(static_cast<const uint32_t*>(pAlpha_blocks) + x + (y * num_blocks_x));
+ const endpoint* pAlpha_endpoints = &pEndpoints[pSrc_alpha_block[0]];
+ const selector* pAlpha_selectors = &pSelectors[pSrc_alpha_block[1]];
+
+ const uint32_t x_swizzle = (g_pvrtc_swizzle_table[x >> 8] << 17) | (g_pvrtc_swizzle_table[x & 0xFF] << 1);
+
+ uint32_t swizzled = x_swizzle | y_swizzle;
+ if (num_blocks_x != num_blocks_y)
+ {
+ swizzled &= swizzle_mask;
+
+ if (num_blocks_x > num_blocks_y)
+ swizzled |= ((x >> min_bits) << (min_bits * 2));
+ else
+ swizzled |= ((y >> min_bits) << (min_bits * 2));
+ }
+
+ pvrtc4_block* pDst_block = static_cast<pvrtc4_block*>(pDst_blocks) + swizzled;
+ pDst_block->m_endpoints = pPVRTC_endpoints[block_index];
+
+ uint32_t base_r = g_etc_5_to_8[src_block.m_differential.m_red1];
+ uint32_t base_g = g_etc_5_to_8[src_block.m_differential.m_green1];
+ uint32_t base_b = g_etc_5_to_8[src_block.m_differential.m_blue1];
+
+ const int* pInten_table48 = g_etc1_inten_tables48[src_block.m_differential.m_cw1];
+ int by = (base_r + base_g + base_b) * 16;
+ int block_colors_y_x16[4];
+ block_colors_y_x16[0] = basisu::clamp<int>(by + pInten_table48[0], 0, 48 * 255);
+ block_colors_y_x16[1] = basisu::clamp<int>(by + pInten_table48[1], 0, 48 * 255);
+ block_colors_y_x16[2] = basisu::clamp<int>(by + pInten_table48[2], 0, 48 * 255);
+ block_colors_y_x16[3] = basisu::clamp<int>(by + pInten_table48[3], 0, 48 * 255);
+
+ uint32_t alpha_base_g = g_etc_5_to_8[pAlpha_endpoints->m_color5.g] * 16;
+ const int* pInten_table16 = g_etc1_inten_tables16[pAlpha_endpoints->m_inten5];
+ int alpha_block_colors_x16[4];
+ alpha_block_colors_x16[0] = basisu::clamp<int>(alpha_base_g + pInten_table16[0], 0, 16 * 255);
+ alpha_block_colors_x16[1] = basisu::clamp<int>(alpha_base_g + pInten_table16[1], 0, 16 * 255);
+ alpha_block_colors_x16[2] = basisu::clamp<int>(alpha_base_g + pInten_table16[2], 0, 16 * 255);
+ alpha_block_colors_x16[3] = basisu::clamp<int>(alpha_base_g + pInten_table16[3], 0, 16 * 255);
+
+ // clamp((base_r + base_g + base_b) * 16 + color_inten[s] * 48) + clamp(alpha_base_g * 16 + alpha_inten[as] * 16)
+
+ {
+ const uint32_t ex = 2;
+ int bx = x + ex - 1;
+ bx &= x_mask;
+
+#define DO_ROW(ey) \
+ { \
+ const uint32_t e = pE_rows[ey][bx]; \
+ e0[ex][ey] = get_endpoint_l8(e, 0); \
+ e1[ex][ey] = get_endpoint_l8(e, 1); \
+ }
+
+ DO_ROW(0);
+ DO_ROW(1);
+ DO_ROW(2);
+#undef DO_ROW
+ }
+
+ uint32_t mod = 0;
+
+#define DO_PIX(lx, ly, w0, w1, w2, w3) \
+ { \
+ int ca_l = a0 * w0 + a1 * w1 + a2 * w2 + a3 * w3; \
+ int cb_l = b0 * w0 + b1 * w1 + b2 * w2 + b3 * w3; \
+ int cl = block_colors_y_x16[(src_block.m_bytes[4 + ly] >> (lx * 2)) & 3] + alpha_block_colors_x16[(pAlpha_selectors->m_selectors[ly] >> (lx * 2)) & 3]; \
+ int dl = cb_l - ca_l; \
+ int vl = cl - ca_l; \
+ int p = vl * 16; \
+ if (ca_l > cb_l) { p = -p; dl = -dl; } \
+ uint32_t m = 0; \
+ if (p > 3 * dl) m = (uint32_t)(1 << ((ly) * 8 + (lx) * 2)); \
+ if (p > 8 * dl) m = (uint32_t)(2 << ((ly) * 8 + (lx) * 2)); \
+ if (p > 13 * dl) m = (uint32_t)(3 << ((ly) * 8 + (lx) * 2)); \
+ mod |= m; \
+ }
+
+ {
+ const uint32_t ex = 0, ey = 0;
+ const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1];
+ const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1];
+ DO_PIX(0, 0, 4, 4, 4, 4);
+ DO_PIX(1, 0, 2, 6, 2, 6);
+ DO_PIX(0, 1, 2, 2, 6, 6);
+ DO_PIX(1, 1, 1, 3, 3, 9);
+ }
+
+ {
+ const uint32_t ex = 1, ey = 0;
+ const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1];
+ const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1];
+ DO_PIX(2, 0, 8, 0, 8, 0);
+ DO_PIX(3, 0, 6, 2, 6, 2);
+ DO_PIX(2, 1, 4, 0, 12, 0);
+ DO_PIX(3, 1, 3, 1, 9, 3);
+ }
+
+ {
+ const uint32_t ex = 0, ey = 1;
+ const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1];
+ const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1];
+ DO_PIX(0, 2, 8, 8, 0, 0);
+ DO_PIX(1, 2, 4, 12, 0, 0);
+ DO_PIX(0, 3, 6, 6, 2, 2);
+ DO_PIX(1, 3, 3, 9, 1, 3);
+ }
+
+ {
+ const uint32_t ex = 1, ey = 1;
+ const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1];
+ const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1];
+ DO_PIX(2, 2, 16, 0, 0, 0);
+ DO_PIX(3, 2, 12, 4, 0, 0);
+ DO_PIX(2, 3, 12, 0, 4, 0);
+ DO_PIX(3, 3, 9, 3, 3, 1);
+ }
+#undef DO_PIX
+
+ pDst_block->m_modulation = mod;
+
+ e0[0][0] = e0[1][0]; e0[1][0] = e0[2][0];
+ e0[0][1] = e0[1][1]; e0[1][1] = e0[2][1];
+ e0[0][2] = e0[1][2]; e0[1][2] = e0[2][2];
+
+ e1[0][0] = e1[1][0]; e1[1][0] = e1[2][0];
+ e1[0][1] = e1[1][1]; e1[1][1] = e1[2][1];
+ e1[0][2] = e1[1][2]; e1[1][2] = e1[2][2];
+
+ } // x
+ } // y
+ }
+#endif // BASISD_SUPPORT_PVRTC1
+
+#if BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY
+ struct bc7_mode_6
+ {
+ struct
+ {
+ uint64_t m_mode : 7;
+ uint64_t m_r0 : 7;
+ uint64_t m_r1 : 7;
+ uint64_t m_g0 : 7;
+ uint64_t m_g1 : 7;
+ uint64_t m_b0 : 7;
+ uint64_t m_b1 : 7;
+ uint64_t m_a0 : 7;
+ uint64_t m_a1 : 7;
+ uint64_t m_p0 : 1;
+ } m_lo;
+
+ union
+ {
+ struct
+ {
+ uint64_t m_p1 : 1;
+ uint64_t m_s00 : 3;
+ uint64_t m_s10 : 4;
+ uint64_t m_s20 : 4;
+ uint64_t m_s30 : 4;
+
+ uint64_t m_s01 : 4;
+ uint64_t m_s11 : 4;
+ uint64_t m_s21 : 4;
+ uint64_t m_s31 : 4;
+
+ uint64_t m_s02 : 4;
+ uint64_t m_s12 : 4;
+ uint64_t m_s22 : 4;
+ uint64_t m_s32 : 4;
+
+ uint64_t m_s03 : 4;
+ uint64_t m_s13 : 4;
+ uint64_t m_s23 : 4;
+ uint64_t m_s33 : 4;
+
+ } m_hi;
+
+ uint64_t m_hi_bits;
+ };
+ };
+
+ static void convert_etc1s_to_bc7_m6(bc7_mode_6* pDst_block, const endpoint *pEndpoint, const selector* pSelector)
+ {
+#if !BASISD_WRITE_NEW_BC7_TABLES
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ const uint32_t base_color_r = pEndpoint->m_color5.r;
+ const uint32_t base_color_g = pEndpoint->m_color5.g;
+ const uint32_t base_color_b = pEndpoint->m_color5.b;
+ const uint32_t inten_table = pEndpoint->m_inten5;
+
+ if (pSelector->m_num_unique_selectors <= 2)
+ {
+ // Only two unique selectors so just switch to block truncation coding (BTC) to avoid quality issues on extreme blocks.
+ pDst_block->m_lo.m_mode = 64;
+
+ pDst_block->m_lo.m_a0 = 127;
+ pDst_block->m_lo.m_a1 = 127;
+
+ color32 block_colors[4];
+
+ decoder_etc_block::get_block_colors5(block_colors, color32(base_color_r, base_color_g, base_color_b, 255), inten_table);
+
+ const uint32_t r0 = block_colors[low_selector].r;
+ const uint32_t g0 = block_colors[low_selector].g;
+ const uint32_t b0 = block_colors[low_selector].b;
+ const uint32_t low_bits0 = (r0 & 1) + (g0 & 1) + (b0 & 1);
+ uint32_t p0 = low_bits0 >= 2;
+
+ const uint32_t r1 = block_colors[high_selector].r;
+ const uint32_t g1 = block_colors[high_selector].g;
+ const uint32_t b1 = block_colors[high_selector].b;
+ const uint32_t low_bits1 = (r1 & 1) + (g1 & 1) + (b1 & 1);
+ uint32_t p1 = low_bits1 >= 2;
+
+ pDst_block->m_lo.m_r0 = r0 >> 1;
+ pDst_block->m_lo.m_g0 = g0 >> 1;
+ pDst_block->m_lo.m_b0 = b0 >> 1;
+ pDst_block->m_lo.m_p0 = p0;
+
+ pDst_block->m_lo.m_r1 = r1 >> 1;
+ pDst_block->m_lo.m_g1 = g1 >> 1;
+ pDst_block->m_lo.m_b1 = b1 >> 1;
+
+ uint32_t output_low_selector = 0;
+ uint32_t output_bit_offset = 1;
+ uint64_t output_hi_bits = p1;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+ uint32_t os = (s == low_selector) ? output_low_selector : (15 ^ output_low_selector);
+
+ uint32_t num_bits = 4;
+
+ if ((x | y) == 0)
+ {
+ if (os & 8)
+ {
+ pDst_block->m_lo.m_r0 = r1 >> 1;
+ pDst_block->m_lo.m_g0 = g1 >> 1;
+ pDst_block->m_lo.m_b0 = b1 >> 1;
+ pDst_block->m_lo.m_p0 = p1;
+
+ pDst_block->m_lo.m_r1 = r0 >> 1;
+ pDst_block->m_lo.m_g1 = g0 >> 1;
+ pDst_block->m_lo.m_b1 = b0 >> 1;
+
+ output_hi_bits &= ~1ULL;
+ output_hi_bits |= p0;
+ std::swap(p0, p1);
+
+ output_low_selector = 15;
+ os = 0;
+ }
+
+ num_bits = 3;
+ }
+
+ output_hi_bits |= (static_cast<uint64_t>(os) << output_bit_offset);
+ output_bit_offset += num_bits;
+ }
+ }
+
+ pDst_block->m_hi_bits = output_hi_bits;
+
+ assert(pDst_block->m_hi.m_p1 == p1);
+
+ return;
+ }
+
+ uint32_t selector_range_table = g_etc1_to_bc7_m6_selector_range_index[low_selector][high_selector];
+
+ const uint32_t* pTable_r = g_etc1_to_bc7_m6_table[base_color_r + inten_table * 32] + (selector_range_table * NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS);
+ const uint32_t* pTable_g = g_etc1_to_bc7_m6_table[base_color_g + inten_table * 32] + (selector_range_table * NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS);
+ const uint32_t* pTable_b = g_etc1_to_bc7_m6_table[base_color_b + inten_table * 32] + (selector_range_table * NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS);
+
+#if 1
+ assert(NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS == 48);
+
+ uint32_t best_err0 = UINT_MAX, best_err1 = UINT_MAX;
+
+#define DO_ITER2(idx) \
+ { \
+ uint32_t v0 = ((pTable_r[(idx)+0] + pTable_g[(idx)+0] + pTable_b[(idx)+0]) << 14) | ((idx) + 0); if (v0 < best_err0) best_err0 = v0; \
+ uint32_t v1 = ((pTable_r[(idx)+1] + pTable_g[(idx)+1] + pTable_b[(idx)+1]) << 14) | ((idx) + 1); if (v1 < best_err1) best_err1 = v1; \
+ }
+#define DO_ITER4(idx) DO_ITER2(idx); DO_ITER2((idx) + 2);
+#define DO_ITER8(idx) DO_ITER4(idx); DO_ITER4((idx) + 4);
+#define DO_ITER16(idx) DO_ITER8(idx); DO_ITER8((idx) + 8);
+
+ DO_ITER16(0);
+ DO_ITER16(16);
+ DO_ITER16(32);
+#undef DO_ITER2
+#undef DO_ITER4
+#undef DO_ITER8
+#undef DO_ITER16
+
+ uint32_t best_err = basisu::minimum(best_err0, best_err1);
+ uint32_t best_mapping = best_err & 0xFF;
+ //best_err >>= 14;
+#else
+ uint32_t best_err = UINT_MAX;
+ uint32_t best_mapping = 0;
+ assert((NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS % 2) == 0);
+ for (uint32_t m = 0; m < NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS; m += 2)
+ {
+#define DO_ITER(idx) { uint32_t total_err = (pTable_r[idx] + pTable_g[idx] + pTable_b[idx]) & 0x3FFFF; if (total_err < best_err) { best_err = total_err; best_mapping = idx; } }
+ DO_ITER(m);
+ DO_ITER(m + 1);
+#undef DO_ITER
+ }
+#endif
+
+ pDst_block->m_lo.m_mode = 64;
+
+ pDst_block->m_lo.m_a0 = 127;
+ pDst_block->m_lo.m_a1 = 127;
+
+ uint64_t v = 0;
+ const uint8_t* pSelectors_xlat;
+
+ if (g_etc1_to_bc7_selector_mappings[best_mapping][pSelector->get_selector(0, 0)] & 8)
+ {
+ pDst_block->m_lo.m_r1 = (pTable_r[best_mapping] >> 18) & 0x7F;
+ pDst_block->m_lo.m_g1 = (pTable_g[best_mapping] >> 18) & 0x7F;
+ pDst_block->m_lo.m_b1 = (pTable_b[best_mapping] >> 18) & 0x7F;
+
+ pDst_block->m_lo.m_r0 = (pTable_r[best_mapping] >> 25) & 0x7F;
+ pDst_block->m_lo.m_g0 = (pTable_g[best_mapping] >> 25) & 0x7F;
+ pDst_block->m_lo.m_b0 = (pTable_b[best_mapping] >> 25) & 0x7F;
+
+ pDst_block->m_lo.m_p0 = 1;
+ pDst_block->m_hi.m_p1 = 0;
+
+ v = 0;
+ pSelectors_xlat = &g_etc1_to_bc7_selector_mappings_inv[best_mapping][0];
+ }
+ else
+ {
+ pDst_block->m_lo.m_r0 = (pTable_r[best_mapping] >> 18) & 0x7F;
+ pDst_block->m_lo.m_g0 = (pTable_g[best_mapping] >> 18) & 0x7F;
+ pDst_block->m_lo.m_b0 = (pTable_b[best_mapping] >> 18) & 0x7F;
+
+ pDst_block->m_lo.m_r1 = (pTable_r[best_mapping] >> 25) & 0x7F;
+ pDst_block->m_lo.m_g1 = (pTable_g[best_mapping] >> 25) & 0x7F;
+ pDst_block->m_lo.m_b1 = (pTable_b[best_mapping] >> 25) & 0x7F;
+
+ pDst_block->m_lo.m_p0 = 0;
+ pDst_block->m_hi.m_p1 = 1;
+
+ v = 1;
+ pSelectors_xlat = &g_etc1_to_bc7_selector_mappings[best_mapping][0];
+ }
+
+ uint64_t v1 = 0, v2 = 0, v3 = 0;
+
+#define DO_X(x, s0, s1, s2, s3) { \
+ v |= ((uint64_t)pSelectors_xlat[(pSelector->m_selectors[0] >> ((x) * 2)) & 3] << (s0)); \
+ v1 |= ((uint64_t)pSelectors_xlat[(pSelector->m_selectors[1] >> ((x) * 2)) & 3] << (s1)); \
+ v2 |= ((uint64_t)pSelectors_xlat[(pSelector->m_selectors[2] >> ((x) * 2)) & 3] << (s2)); \
+ v3 |= ((uint64_t)pSelectors_xlat[(pSelector->m_selectors[3] >> ((x) * 2)) & 3] << (s3)); }
+
+ // 1 4 8 12
+ // 16 20 24 28
+ // 32 36 40 44
+ // 48 52 56 60
+
+ DO_X(0, 1, 16, 32, 48);
+ DO_X(1, 4, 20, 36, 52);
+ DO_X(2, 8, 24, 40, 56);
+ DO_X(3, 12, 28, 44, 60);
+#undef DO_X
+
+ pDst_block->m_hi_bits = v | v1 | v2 | v3;
+#endif
+
+ }
+#endif // BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY
+
+#if BASISD_SUPPORT_BC7_MODE5
+ static dxt_selector_range g_etc1_to_bc7_m5_selector_ranges[] =
+ {
+ { 0, 3 },
+ { 1, 3 },
+ { 0, 2 },
+ { 1, 2 },
+ { 2, 3 },
+ { 0, 1 },
+ };
+
+ const uint32_t NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES = sizeof(g_etc1_to_bc7_m5_selector_ranges) / sizeof(g_etc1_to_bc7_m5_selector_ranges[0]);
+
+ static uint32_t g_etc1_to_bc7_m5_selector_range_index[4][4];
+
+ const uint32_t NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS = 10;
+ static const uint8_t g_etc1_to_bc7_m5_selector_mappings[NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS][4] =
+ {
+ { 0, 0, 1, 1 },
+ { 0, 0, 1, 2 },
+ { 0, 0, 1, 3 },
+ { 0, 0, 2, 3 },
+ { 0, 1, 1, 1 },
+ { 0, 1, 2, 2 },
+ { 0, 1, 2, 3 },
+ { 0, 2, 3, 3 },
+ { 1, 2, 2, 2 },
+ { 1, 2, 3, 3 },
+ };
+
+ struct etc1_to_bc7_m5_solution
+ {
+ uint8_t m_lo;
+ uint8_t m_hi;
+ uint16_t m_err;
+ };
+
+ static const etc1_to_bc7_m5_solution g_etc1_to_bc7_m5_color[32 * 8 * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS * NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES] = {
+#include "basisu_transcoder_tables_bc7_m5_color.inc"
+ };
+
+ static dxt_selector_range g_etc1_to_bc7_m5a_selector_ranges[] =
+ {
+ { 0, 3 },
+ { 1, 3 },
+ { 0, 2 },
+ { 1, 2 },
+ { 2, 3 },
+ { 0, 1 }
+ };
+
+ const uint32_t NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES = sizeof(g_etc1_to_bc7_m5a_selector_ranges) / sizeof(g_etc1_to_bc7_m5a_selector_ranges[0]);
+
+ static uint32_t g_etc1_to_bc7_m5a_selector_range_index[4][4];
+
+ struct etc1_g_to_bc7_m5a_conversion
+ {
+ uint8_t m_lo, m_hi;
+ uint8_t m_trans;
+ };
+
+ static etc1_g_to_bc7_m5a_conversion g_etc1_g_to_bc7_m5a[8 * 32 * NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES] =
+ {
+ #include "basisu_transcoder_tables_bc7_m5_alpha.inc"
+ };
+
+ static inline uint32_t set_block_bits(uint8_t* pBytes, uint32_t val, uint32_t num_bits, uint32_t cur_ofs)
+ {
+ assert(num_bits < 32);
+ assert(val < (1ULL << num_bits));
+
+ uint32_t mask = (1 << num_bits) - 1;
+
+ while (num_bits)
+ {
+ const uint32_t n = basisu::minimum<uint32_t>(8 - (cur_ofs & 7), num_bits);
+
+ pBytes[cur_ofs >> 3] &= ~static_cast<uint8_t>(mask << (cur_ofs & 7));
+ pBytes[cur_ofs >> 3] |= static_cast<uint8_t>(val << (cur_ofs & 7));
+
+ val >>= n;
+ mask >>= n;
+
+ num_bits -= n;
+ cur_ofs += n;
+ }
+
+ return cur_ofs;
+ }
+
+ struct bc7_mode_5
+ {
+ union
+ {
+ struct
+ {
+ uint64_t m_mode : 6;
+ uint64_t m_rot : 2;
+
+ uint64_t m_r0 : 7;
+ uint64_t m_r1 : 7;
+ uint64_t m_g0 : 7;
+ uint64_t m_g1 : 7;
+ uint64_t m_b0 : 7;
+ uint64_t m_b1 : 7;
+ uint64_t m_a0 : 8;
+ uint64_t m_a1_0 : 6;
+
+ } m_lo;
+
+ uint64_t m_lo_bits;
+ };
+
+ union
+ {
+ struct
+ {
+ uint64_t m_a1_1 : 2;
+
+ // bit 2
+ uint64_t m_c00 : 1;
+ uint64_t m_c10 : 2;
+ uint64_t m_c20 : 2;
+ uint64_t m_c30 : 2;
+
+ uint64_t m_c01 : 2;
+ uint64_t m_c11 : 2;
+ uint64_t m_c21 : 2;
+ uint64_t m_c31 : 2;
+
+ uint64_t m_c02 : 2;
+ uint64_t m_c12 : 2;
+ uint64_t m_c22 : 2;
+ uint64_t m_c32 : 2;
+
+ uint64_t m_c03 : 2;
+ uint64_t m_c13 : 2;
+ uint64_t m_c23 : 2;
+ uint64_t m_c33 : 2;
+
+ // bit 33
+ uint64_t m_a00 : 1;
+ uint64_t m_a10 : 2;
+ uint64_t m_a20 : 2;
+ uint64_t m_a30 : 2;
+
+ uint64_t m_a01 : 2;
+ uint64_t m_a11 : 2;
+ uint64_t m_a21 : 2;
+ uint64_t m_a31 : 2;
+
+ uint64_t m_a02 : 2;
+ uint64_t m_a12 : 2;
+ uint64_t m_a22 : 2;
+ uint64_t m_a32 : 2;
+
+ uint64_t m_a03 : 2;
+ uint64_t m_a13 : 2;
+ uint64_t m_a23 : 2;
+ uint64_t m_a33 : 2;
+
+ } m_hi;
+
+ uint64_t m_hi_bits;
+ };
+ };
+
+#if BASISD_WRITE_NEW_BC7_MODE5_TABLES
+ static void create_etc1_to_bc7_m5_color_conversion_table()
+ {
+ FILE* pFile = nullptr;
+ fopen_s(&pFile, "basisu_transcoder_tables_bc7_m5_color.inc", "w");
+
+ uint32_t n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1_to_bc7_m5_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1_to_bc7_m5_selector_ranges[sr].m_high;
+
+ for (uint32_t m = 0; m < NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 127; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 127; lo++)
+ {
+ uint32_t colors[4];
+
+ colors[0] = (lo << 1) | (lo >> 6);
+ colors[3] = (hi << 1) | (hi >> 6);
+
+ colors[1] = (colors[0] * (64 - 21) + colors[3] * 21 + 32) / 64;
+ colors[2] = (colors[0] * (64 - 43) + colors[3] * 43 + 32) / 64;
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1_to_bc7_m5_selector_mappings[m][s]];
+
+ int err_scale = 1;
+ // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor
+ // the low/high selectors which are clamping to either 0 or 255.
+ if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3)))
+ err_scale = 5;
+
+ total_err += (err * err) * err_scale;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ best_err = basisu::minimum<uint32_t>(best_err, 0xFFFF);
+
+ fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+ } // m
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+ }
+
+ static void create_etc1_to_bc7_m5_alpha_conversion_table()
+ {
+ FILE* pFile = nullptr;
+ fopen_s(&pFile, "basisu_transcoder_tables_bc7_m5_alpha.inc", "w");
+
+ uint32_t n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1_to_bc7_m5a_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1_to_bc7_m5a_selector_ranges[sr].m_high;
+
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+ uint32_t best_output_selectors = 0;
+
+ for (uint32_t hi = 0; hi <= 255; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 255; lo++)
+ {
+ uint32_t colors[4];
+
+ colors[0] = lo;
+ colors[3] = hi;
+
+ colors[1] = (colors[0] * (64 - 21) + colors[3] * 21 + 32) / 64;
+ colors[2] = (colors[0] * (64 - 43) + colors[3] * 43 + 32) / 64;
+
+ uint64_t total_err = 0;
+ uint32_t output_selectors = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int best_mapping_err = INT_MAX;
+ int best_k = 0;
+ for (int k = 0; k < 4; k++)
+ {
+ int mapping_err = block_colors[s].g - colors[k];
+ mapping_err *= mapping_err;
+
+ // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor
+ // the low/high selectors which are clamping to either 0 or 255.
+ if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3)))
+ mapping_err *= 5;
+
+ if (mapping_err < best_mapping_err)
+ {
+ best_mapping_err = mapping_err;
+ best_k = k;
+ }
+ } // k
+
+ total_err += best_mapping_err;
+ output_selectors |= (best_k << (s * 2));
+ } // s
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ best_output_selectors = output_selectors;
+ }
+
+ } // lo
+ } // hi
+
+ fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, best_output_selectors);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+ }
+#endif // BASISD_WRITE_NEW_BC7_MODE5_TABLES
+
+ struct bc7_m5_match_entry
+ {
+ uint8_t m_hi;
+ uint8_t m_lo;
+ };
+
+ static bc7_m5_match_entry g_bc7_m5_equals_1[256] =
+ {
+ {0,0},{1,0},{3,0},{4,0},{6,0},{7,0},{9,0},{10,0},{12,0},{13,0},{15,0},{16,0},{18,0},{20,0},{21,0},{23,0},
+ {24,0},{26,0},{27,0},{29,0},{30,0},{32,0},{33,0},{35,0},{36,0},{38,0},{39,0},{41,0},{42,0},{44,0},{45,0},{47,0},
+ {48,0},{50,0},{52,0},{53,0},{55,0},{56,0},{58,0},{59,0},{61,0},{62,0},{64,0},{65,0},{66,0},{68,0},{69,0},{71,0},
+ {72,0},{74,0},{75,0},{77,0},{78,0},{80,0},{82,0},{83,0},{85,0},{86,0},{88,0},{89,0},{91,0},{92,0},{94,0},{95,0},
+ {97,0},{98,0},{100,0},{101,0},{103,0},{104,0},{106,0},{107,0},{109,0},{110,0},{112,0},{114,0},{115,0},{117,0},{118,0},{120,0},
+ {121,0},{123,0},{124,0},{126,0},{127,0},{127,1},{126,2},{126,3},{127,3},{127,4},{126,5},{126,6},{127,6},{127,7},{126,8},{126,9},
+ {127,9},{127,10},{126,11},{126,12},{127,12},{127,13},{126,14},{125,15},{127,15},{126,16},{126,17},{127,17},{127,18},{126,19},{126,20},{127,20},
+ {127,21},{126,22},{126,23},{127,23},{127,24},{126,25},{126,26},{127,26},{127,27},{126,28},{126,29},{127,29},{127,30},{126,31},{126,32},{127,32},
+ {127,33},{126,34},{126,35},{127,35},{127,36},{126,37},{126,38},{127,38},{127,39},{126,40},{126,41},{127,41},{127,42},{126,43},{126,44},{127,44},
+ {127,45},{126,46},{125,47},{127,47},{126,48},{126,49},{127,49},{127,50},{126,51},{126,52},{127,52},{127,53},{126,54},{126,55},{127,55},{127,56},
+ {126,57},{126,58},{127,58},{127,59},{126,60},{126,61},{127,61},{127,62},{126,63},{125,64},{126,64},{126,65},{127,65},{127,66},{126,67},{126,68},
+ {127,68},{127,69},{126,70},{126,71},{127,71},{127,72},{126,73},{126,74},{127,74},{127,75},{126,76},{125,77},{127,77},{126,78},{126,79},{127,79},
+ {127,80},{126,81},{126,82},{127,82},{127,83},{126,84},{126,85},{127,85},{127,86},{126,87},{126,88},{127,88},{127,89},{126,90},{126,91},{127,91},
+ {127,92},{126,93},{126,94},{127,94},{127,95},{126,96},{126,97},{127,97},{127,98},{126,99},{126,100},{127,100},{127,101},{126,102},{126,103},{127,103},
+ {127,104},{126,105},{126,106},{127,106},{127,107},{126,108},{125,109},{127,109},{126,110},{126,111},{127,111},{127,112},{126,113},{126,114},{127,114},{127,115},
+ {126,116},{126,117},{127,117},{127,118},{126,119},{126,120},{127,120},{127,121},{126,122},{126,123},{127,123},{127,124},{126,125},{126,126},{127,126},{127,127}
+ };
+
+ static void transcoder_init_bc7_mode5()
+ {
+#if 0
+ // This is a little too much work to do at init time, so precompute it.
+ for (int i = 0; i < 256; i++)
+ {
+ int lowest_e = 256;
+ for (int lo = 0; lo < 128; lo++)
+ {
+ for (int hi = 0; hi < 128; hi++)
+ {
+ const int lo_e = (lo << 1) | (lo >> 6);
+ const int hi_e = (hi << 1) | (hi >> 6);
+
+ // Selector 1
+ int v = (lo_e * (64 - 21) + hi_e * 21 + 32) >> 6;
+ int e = abs(v - i);
+
+ if (e < lowest_e)
+ {
+ g_bc7_m5_equals_1[i].m_hi = static_cast<uint8_t>(hi);
+ g_bc7_m5_equals_1[i].m_lo = static_cast<uint8_t>(lo);
+
+ lowest_e = e;
+ }
+
+ } // hi
+
+ } // lo
+
+ printf("{%u,%u},", g_bc7_m5_equals_1[i].m_hi, g_bc7_m5_equals_1[i].m_lo);
+ if ((i & 15) == 15) printf("\n");
+ }
+#endif
+
+ for (uint32_t i = 0; i < NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES; i++)
+ {
+ uint32_t l = g_etc1_to_bc7_m5_selector_ranges[i].m_low;
+ uint32_t h = g_etc1_to_bc7_m5_selector_ranges[i].m_high;
+ g_etc1_to_bc7_m5_selector_range_index[l][h] = i;
+ }
+
+ for (uint32_t i = 0; i < NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES; i++)
+ {
+ uint32_t l = g_etc1_to_bc7_m5a_selector_ranges[i].m_low;
+ uint32_t h = g_etc1_to_bc7_m5a_selector_ranges[i].m_high;
+ g_etc1_to_bc7_m5a_selector_range_index[l][h] = i;
+ }
+ }
+
+ static void convert_etc1s_to_bc7_m5_color(void* pDst, const endpoint* pEndpoints, const selector* pSelector)
+ {
+ bc7_mode_5* pDst_block = static_cast<bc7_mode_5*>(pDst);
+
+ static_cast<uint64_t*>(pDst)[0] = 0;
+ static_cast<uint64_t*>(pDst)[1] = 0;
+
+ pDst_block->m_lo.m_mode = 1 << 5;
+ pDst_block->m_lo.m_a0 = 255;
+ pDst_block->m_lo.m_a1_0 = 63;
+ pDst_block->m_hi.m_a1_1 = 3;
+
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ const uint32_t base_color_r = pEndpoints->m_color5.r;
+ const uint32_t base_color_g = pEndpoints->m_color5.g;
+ const uint32_t base_color_b = pEndpoints->m_color5.b;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ if (pSelector->m_num_unique_selectors == 1)
+ {
+ // Solid color block - use precomputed tables and set selectors to 1.
+ uint32_t r, g, b;
+ decoder_etc_block::get_block_color5(pEndpoints->m_color5, inten_table, low_selector, r, g, b);
+
+ pDst_block->m_lo.m_r0 = g_bc7_m5_equals_1[r].m_lo;
+ pDst_block->m_lo.m_g0 = g_bc7_m5_equals_1[g].m_lo;
+ pDst_block->m_lo.m_b0 = g_bc7_m5_equals_1[b].m_lo;
+
+ pDst_block->m_lo.m_r1 = g_bc7_m5_equals_1[r].m_hi;
+ pDst_block->m_lo.m_g1 = g_bc7_m5_equals_1[g].m_hi;
+ pDst_block->m_lo.m_b1 = g_bc7_m5_equals_1[b].m_hi;
+
+ set_block_bits((uint8_t*)pDst, 0x2aaaaaab, 31, 66);
+ return;
+ }
+ else if (pSelector->m_num_unique_selectors == 2)
+ {
+ // Only one or two unique selectors, so just switch to block truncation coding (BTC) to avoid quality issues on extreme blocks.
+ color32 block_colors[4];
+
+ decoder_etc_block::get_block_colors5(block_colors, color32(base_color_r, base_color_g, base_color_b, 255), inten_table);
+
+ const uint32_t r0 = block_colors[low_selector].r;
+ const uint32_t g0 = block_colors[low_selector].g;
+ const uint32_t b0 = block_colors[low_selector].b;
+
+ const uint32_t r1 = block_colors[high_selector].r;
+ const uint32_t g1 = block_colors[high_selector].g;
+ const uint32_t b1 = block_colors[high_selector].b;
+
+ pDst_block->m_lo.m_r0 = r0 >> 1;
+ pDst_block->m_lo.m_g0 = g0 >> 1;
+ pDst_block->m_lo.m_b0 = b0 >> 1;
+
+ pDst_block->m_lo.m_r1 = r1 >> 1;
+ pDst_block->m_lo.m_g1 = g1 >> 1;
+ pDst_block->m_lo.m_b1 = b1 >> 1;
+
+ uint32_t output_low_selector = 0, output_bit_offset = 0, output_bits = 0;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+ uint32_t os = (s == low_selector) ? output_low_selector : (3 ^ output_low_selector);
+
+ uint32_t num_bits = 2;
+
+ if ((x | y) == 0)
+ {
+ if (os & 2)
+ {
+ pDst_block->m_lo.m_r0 = r1 >> 1;
+ pDst_block->m_lo.m_g0 = g1 >> 1;
+ pDst_block->m_lo.m_b0 = b1 >> 1;
+
+ pDst_block->m_lo.m_r1 = r0 >> 1;
+ pDst_block->m_lo.m_g1 = g0 >> 1;
+ pDst_block->m_lo.m_b1 = b0 >> 1;
+
+ output_low_selector = 3;
+ os = 0;
+ }
+
+ num_bits = 1;
+ }
+
+ output_bits |= (os << output_bit_offset);
+ output_bit_offset += num_bits;
+ }
+ }
+
+ set_block_bits((uint8_t*)pDst, output_bits, 31, 66);
+ return;
+ }
+
+ const uint32_t selector_range_table = g_etc1_to_bc7_m5_selector_range_index[low_selector][high_selector];
+
+ //[32][8][RANGES][MAPPING]
+ const etc1_to_bc7_m5_solution* pTable_r = &g_etc1_to_bc7_m5_color[(inten_table * 32 + base_color_r) * (NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS];
+ const etc1_to_bc7_m5_solution* pTable_g = &g_etc1_to_bc7_m5_color[(inten_table * 32 + base_color_g) * (NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS];
+ const etc1_to_bc7_m5_solution* pTable_b = &g_etc1_to_bc7_m5_color[(inten_table * 32 + base_color_b) * (NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS];
+
+ uint32_t best_err = UINT_MAX;
+ uint32_t best_mapping = 0;
+
+ assert(NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS == 10);
+#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } }
+ DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4);
+ DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9);
+#undef DO_ITER
+
+ const uint8_t* pSelectors_xlat = &g_etc1_to_bc7_m5_selector_mappings[best_mapping][0];
+
+ uint32_t s_inv = 0;
+ if (pSelectors_xlat[pSelector->get_selector(0, 0)] & 2)
+ {
+ pDst_block->m_lo.m_r0 = pTable_r[best_mapping].m_hi;
+ pDst_block->m_lo.m_g0 = pTable_g[best_mapping].m_hi;
+ pDst_block->m_lo.m_b0 = pTable_b[best_mapping].m_hi;
+
+ pDst_block->m_lo.m_r1 = pTable_r[best_mapping].m_lo;
+ pDst_block->m_lo.m_g1 = pTable_g[best_mapping].m_lo;
+ pDst_block->m_lo.m_b1 = pTable_b[best_mapping].m_lo;
+
+ s_inv = 3;
+ }
+ else
+ {
+ pDst_block->m_lo.m_r0 = pTable_r[best_mapping].m_lo;
+ pDst_block->m_lo.m_g0 = pTable_g[best_mapping].m_lo;
+ pDst_block->m_lo.m_b0 = pTable_b[best_mapping].m_lo;
+
+ pDst_block->m_lo.m_r1 = pTable_r[best_mapping].m_hi;
+ pDst_block->m_lo.m_g1 = pTable_g[best_mapping].m_hi;
+ pDst_block->m_lo.m_b1 = pTable_b[best_mapping].m_hi;
+ }
+
+ uint32_t output_bits = 0, output_bit_ofs = 0;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ const uint32_t s = pSelector->get_selector(x, y);
+
+ const uint32_t os = pSelectors_xlat[s] ^ s_inv;
+
+ output_bits |= (os << output_bit_ofs);
+
+ output_bit_ofs += (((x | y) == 0) ? 1 : 2);
+ }
+ }
+
+ set_block_bits((uint8_t*)pDst, output_bits, 31, 66);
+ }
+
+ static void convert_etc1s_to_bc7_m5_alpha(void* pDst, const endpoint* pEndpoints, const selector* pSelector)
+ {
+ bc7_mode_5* pDst_block = static_cast<bc7_mode_5*>(pDst);
+
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ const uint32_t base_color_r = pEndpoints->m_color5.r;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ if (pSelector->m_num_unique_selectors == 1)
+ {
+ uint32_t r;
+ decoder_etc_block::get_block_color5_r(pEndpoints->m_color5, inten_table, low_selector, r);
+
+ pDst_block->m_lo.m_a0 = r;
+ pDst_block->m_lo.m_a1_0 = r & 63;
+ pDst_block->m_hi.m_a1_1 = r >> 6;
+
+ return;
+ }
+ else if (pSelector->m_num_unique_selectors == 2)
+ {
+ // Only one or two unique selectors, so just switch to block truncation coding (BTC) to avoid quality issues on extreme blocks.
+ int block_colors[4];
+
+ decoder_etc_block::get_block_colors5_g(block_colors, pEndpoints->m_color5, inten_table);
+
+ pDst_block->m_lo.m_a0 = block_colors[low_selector];
+ pDst_block->m_lo.m_a1_0 = block_colors[high_selector] & 63;
+ pDst_block->m_hi.m_a1_1 = block_colors[high_selector] >> 6;
+
+ uint32_t output_low_selector = 0, output_bit_offset = 0, output_bits = 0;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ const uint32_t s = pSelector->get_selector(x, y);
+ uint32_t os = (s == low_selector) ? output_low_selector : (3 ^ output_low_selector);
+
+ uint32_t num_bits = 2;
+
+ if ((x | y) == 0)
+ {
+ if (os & 2)
+ {
+ pDst_block->m_lo.m_a0 = block_colors[high_selector];
+ pDst_block->m_lo.m_a1_0 = block_colors[low_selector] & 63;
+ pDst_block->m_hi.m_a1_1 = block_colors[low_selector] >> 6;
+
+ output_low_selector = 3;
+ os = 0;
+ }
+
+ num_bits = 1;
+ }
+
+ output_bits |= (os << output_bit_offset);
+ output_bit_offset += num_bits;
+ }
+ }
+
+ set_block_bits((uint8_t*)pDst, output_bits, 31, 97);
+ return;
+ }
+
+ const uint32_t selector_range_table = g_etc1_to_bc7_m5a_selector_range_index[low_selector][high_selector];
+
+ const etc1_g_to_bc7_m5a_conversion* pTable = &g_etc1_g_to_bc7_m5a[inten_table * (32 * NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES) + base_color_r * NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES + selector_range_table];
+
+ pDst_block->m_lo.m_a0 = pTable->m_lo;
+ pDst_block->m_lo.m_a1_0 = pTable->m_hi & 63;
+ pDst_block->m_hi.m_a1_1 = pTable->m_hi >> 6;
+
+ uint32_t output_bit_offset = 0, output_bits = 0, selector_trans = pTable->m_trans;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ const uint32_t s = pSelector->get_selector(x, y);
+ uint32_t os = (selector_trans >> (s * 2)) & 3;
+
+ uint32_t num_bits = 2;
+
+ if ((x | y) == 0)
+ {
+ if (os & 2)
+ {
+ pDst_block->m_lo.m_a0 = pTable->m_hi;
+ pDst_block->m_lo.m_a1_0 = pTable->m_lo & 63;
+ pDst_block->m_hi.m_a1_1 = pTable->m_lo >> 6;
+
+ selector_trans ^= 0xFF;
+ os ^= 3;
+ }
+
+ num_bits = 1;
+ }
+
+ output_bits |= (os << output_bit_offset);
+ output_bit_offset += num_bits;
+ }
+ }
+
+ set_block_bits((uint8_t*)pDst, output_bits, 31, 97);
+ }
+#endif // BASISD_SUPPORT_BC7_MODE5
+
+#if BASISD_SUPPORT_ETC2_EAC_A8
+ static void convert_etc1s_to_etc2_eac_a8(eac_block* pDst_block, const endpoint* pEndpoints, const selector* pSelector)
+ {
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ const color32& base_color = pEndpoints->m_color5;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ if (low_selector == high_selector)
+ {
+ uint32_t r;
+ decoder_etc_block::get_block_color5_r(base_color, inten_table, low_selector, r);
+
+ // Constant alpha block
+ // Select table 13, use selector 4 (0), set multiplier to 1 and base color g
+ pDst_block->m_base = r;
+ pDst_block->m_table = 13;
+ pDst_block->m_multiplier = 1;
+
+ // selectors are all 4's
+ static const uint8_t s_etc2_eac_a8_sel4[6] = { 0x92, 0x49, 0x24, 0x92, 0x49, 0x24 };
+ memcpy(pDst_block->m_selectors, s_etc2_eac_a8_sel4, sizeof(s_etc2_eac_a8_sel4));
+
+ return;
+ }
+
+ uint32_t selector_range_table = 0;
+ for (selector_range_table = 0; selector_range_table < NUM_ETC2_EAC_SELECTOR_RANGES; selector_range_table++)
+ if ((low_selector == s_etc2_eac_selector_ranges[selector_range_table].m_low) && (high_selector == s_etc2_eac_selector_ranges[selector_range_table].m_high))
+ break;
+ if (selector_range_table >= NUM_ETC2_EAC_SELECTOR_RANGES)
+ selector_range_table = 0;
+
+ const etc1_g_to_eac_conversion* pTable_entry = &s_etc1_g_to_etc2_a8[base_color.r + inten_table * 32][selector_range_table];
+
+ pDst_block->m_base = pTable_entry->m_base;
+ pDst_block->m_table = pTable_entry->m_table_mul >> 4;
+ pDst_block->m_multiplier = pTable_entry->m_table_mul & 15;
+
+ uint64_t selector_bits = 0;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+
+ uint32_t ds = (pTable_entry->m_trans >> (s * 3)) & 7;
+
+ const uint32_t dst_ofs = 45 - (y + x * 4) * 3;
+ selector_bits |= (static_cast<uint64_t>(ds) << dst_ofs);
+ }
+ }
+
+ pDst_block->set_selector_bits(selector_bits);
+ }
+#endif // BASISD_SUPPORT_ETC2_EAC_A8
+
+#if BASISD_SUPPORT_ETC2_EAC_RG11
+ static const etc1_g_to_eac_conversion s_etc1_g_to_etc2_r11[32 * 8][NUM_ETC2_EAC_SELECTOR_RANGES] =
+ {
+ {{0,1,3328},{0,1,3328},{0,16,457},{0,16,456}},
+ {{0,226,3936},{0,226,3936},{0,17,424},{8,0,472}},
+ {{6,178,4012},{6,178,4008},{0,146,501},{16,0,472}},
+ {{14,178,4012},{14,178,4008},{8,146,501},{24,0,472}},
+ {{23,178,4012},{23,178,4008},{17,146,501},{33,0,472}},
+ {{31,178,4012},{31,178,4008},{25,146,501},{41,0,472}},
+ {{39,178,4012},{39,178,4008},{33,146,501},{49,0,472}},
+ {{47,178,4012},{47,178,4008},{41,146,501},{27,228,496}},
+ {{56,178,4012},{56,178,4008},{50,146,501},{36,228,496}},
+ {{64,178,4012},{64,178,4008},{58,146,501},{44,228,496}},
+ {{72,178,4012},{72,178,4008},{66,146,501},{52,228,496}},
+ {{80,178,4012},{80,178,4008},{74,146,501},{60,228,496}},
+ {{89,178,4012},{89,178,4008},{83,146,501},{69,228,496}},
+ {{97,178,4012},{97,178,4008},{91,146,501},{77,228,496}},
+ {{105,178,4012},{105,178,4008},{99,146,501},{85,228,496}},
+ {{113,178,4012},{113,178,4008},{107,146,501},{93,228,496}},
+ {{122,178,4012},{122,178,4008},{116,146,501},{102,228,496}},
+ {{130,178,4012},{130,178,4008},{124,146,501},{110,228,496}},
+ {{138,178,4012},{138,178,4008},{132,146,501},{118,228,496}},
+ {{146,178,4012},{146,178,4008},{140,146,501},{126,228,496}},
+ {{155,178,4012},{155,178,4008},{149,146,501},{135,228,496}},
+ {{163,178,4012},{163,178,4008},{157,146,501},{143,228,496}},
+ {{171,178,4012},{171,178,4008},{165,146,501},{151,228,496}},
+ {{179,178,4012},{179,178,4008},{173,146,501},{159,228,496}},
+ {{188,178,4012},{188,178,4008},{182,146,501},{168,228,496}},
+ {{196,178,4012},{196,178,4008},{190,146,501},{176,228,496}},
+ {{204,178,4012},{204,178,4008},{198,146,501},{184,228,496}},
+ {{212,178,4012},{212,178,4008},{206,146,501},{192,228,496}},
+ {{221,178,4012},{221,178,4008},{215,146,501},{201,228,496}},
+ {{229,178,4012},{229,178,4008},{223,146,501},{209,228,496}},
+ {{235,66,4012},{221,100,4008},{231,146,501},{217,228,496}},
+ {{211,102,4085},{254,32,4040},{211,102,501},{254,32,456}},
+ {{0,2,3328},{0,2,3328},{0,1,320},{0,1,320}},
+ {{7,162,3905},{7,162,3904},{0,17,480},{0,17,480}},
+ {{15,162,3906},{15,162,3904},{1,117,352},{1,117,352}},
+ {{23,162,3906},{23,162,3904},{5,34,500},{4,53,424}},
+ {{32,162,3906},{32,162,3904},{14,34,500},{3,69,424}},
+ {{40,162,3906},{40,162,3904},{22,34,500},{1,133,496}},
+ {{48,162,3906},{48,162,3904},{30,34,500},{4,85,496}},
+ {{56,162,3906},{56,162,3904},{38,34,500},{12,85,496}},
+ {{65,162,3906},{65,162,3904},{47,34,500},{1,106,424}},
+ {{73,162,3906},{73,162,3904},{55,34,500},{9,106,424}},
+ {{81,162,3906},{81,162,3904},{63,34,500},{7,234,496}},
+ {{89,162,3906},{89,162,3904},{71,34,500},{15,234,496}},
+ {{98,162,3906},{98,162,3904},{80,34,500},{24,234,496}},
+ {{106,162,3906},{106,162,3904},{88,34,500},{32,234,496}},
+ {{114,162,3906},{114,162,3904},{96,34,500},{40,234,496}},
+ {{122,162,3906},{122,162,3904},{104,34,500},{48,234,496}},
+ {{131,162,3906},{131,162,3904},{113,34,500},{57,234,496}},
+ {{139,162,3906},{139,162,3904},{121,34,500},{65,234,496}},
+ {{147,162,3906},{147,162,3904},{129,34,500},{73,234,496}},
+ {{155,162,3906},{155,162,3904},{137,34,500},{81,234,496}},
+ {{164,162,3906},{164,162,3904},{146,34,500},{90,234,496}},
+ {{172,162,3906},{172,162,3904},{154,34,500},{98,234,496}},
+ {{180,162,3906},{180,162,3904},{162,34,500},{106,234,496}},
+ {{188,162,3906},{188,162,3904},{170,34,500},{114,234,496}},
+ {{197,162,3906},{197,162,3904},{179,34,500},{123,234,496}},
+ {{205,162,3906},{205,162,3904},{187,34,500},{131,234,496}},
+ {{213,162,3906},{213,162,3904},{195,34,500},{139,234,496}},
+ {{221,162,3906},{221,162,3904},{203,34,500},{147,234,496}},
+ {{230,162,3906},{230,162,3904},{212,34,500},{156,234,496}},
+ {{238,162,3906},{174,106,4008},{220,34,500},{164,234,496}},
+ {{240,178,4001},{182,106,4008},{228,34,500},{172,234,496}},
+ {{166,108,4085},{115,31,4080},{166,108,501},{115,31,496}},
+ {{1,68,3328},{1,68,3328},{0,1,384},{0,1,384}},
+ {{1,51,3968},{1,51,3968},{0,2,384},{0,2,384}},
+ {{21,18,3851},{21,18,3848},{1,50,488},{1,50,488}},
+ {{26,195,3851},{29,18,3848},{0,67,488},{0,67,488}},
+ {{35,195,3851},{38,18,3848},{12,115,488},{0,3,496}},
+ {{43,195,3851},{46,18,3848},{20,115,488},{2,6,424}},
+ {{51,195,3851},{54,18,3848},{36,66,482},{4,22,424}},
+ {{59,195,3851},{62,18,3848},{44,66,482},{3,73,424}},
+ {{68,195,3851},{71,18,3848},{53,66,482},{3,22,496}},
+ {{76,195,3851},{79,18,3848},{61,66,482},{2,137,496}},
+ {{84,195,3851},{87,18,3848},{69,66,482},{1,89,496}},
+ {{92,195,3851},{95,18,3848},{77,66,482},{9,89,496}},
+ {{101,195,3851},{104,18,3848},{86,66,482},{18,89,496}},
+ {{109,195,3851},{112,18,3848},{94,66,482},{26,89,496}},
+ {{117,195,3851},{120,18,3848},{102,66,482},{34,89,496}},
+ {{125,195,3851},{128,18,3848},{110,66,482},{42,89,496}},
+ {{134,195,3851},{137,18,3848},{119,66,482},{51,89,496}},
+ {{141,195,3907},{145,18,3848},{127,66,482},{59,89,496}},
+ {{149,195,3907},{153,18,3848},{135,66,482},{67,89,496}},
+ {{157,195,3907},{161,18,3848},{143,66,482},{75,89,496}},
+ {{166,195,3907},{170,18,3848},{152,66,482},{84,89,496}},
+ {{174,195,3907},{178,18,3848},{160,66,482},{92,89,496}},
+ {{182,195,3907},{186,18,3848},{168,66,482},{100,89,496}},
+ {{190,195,3907},{194,18,3848},{176,66,482},{108,89,496}},
+ {{199,195,3907},{203,18,3848},{185,66,482},{117,89,496}},
+ {{207,195,3907},{211,18,3848},{193,66,482},{125,89,496}},
+ {{215,195,3907},{219,18,3848},{201,66,482},{133,89,496}},
+ {{223,195,3907},{227,18,3848},{209,66,482},{141,89,496}},
+ {{232,195,3907},{168,89,4008},{218,66,482},{150,89,496}},
+ {{236,18,3907},{176,89,4008},{226,66,482},{158,89,496}},
+ {{158,90,4085},{103,31,4080},{158,90,501},{103,31,496}},
+ {{166,90,4085},{111,31,4080},{166,90,501},{111,31,496}},
+ {{0,70,3328},{0,70,3328},{0,17,448},{0,17,448}},
+ {{0,117,3904},{0,117,3904},{0,35,384},{0,35,384}},
+ {{13,165,3905},{13,165,3904},{2,211,480},{2,211,480}},
+ {{21,165,3906},{21,165,3904},{1,51,488},{1,51,488}},
+ {{30,165,3906},{30,165,3904},{7,61,352},{7,61,352}},
+ {{38,165,3906},{38,165,3904},{2,125,352},{2,125,352}},
+ {{46,165,3906},{46,165,3904},{1,37,500},{10,125,352}},
+ {{54,165,3906},{54,165,3904},{9,37,500},{5,61,424}},
+ {{63,165,3906},{63,165,3904},{18,37,500},{1,189,424}},
+ {{71,165,3906},{71,165,3904},{26,37,500},{9,189,424}},
+ {{79,165,3906},{79,165,3904},{34,37,500},{4,77,424}},
+ {{87,165,3906},{87,165,3904},{42,37,500},{12,77,424}},
+ {{96,165,3906},{96,165,3904},{51,37,500},{8,93,424}},
+ {{104,165,3906},{104,165,3904},{59,37,500},{3,141,496}},
+ {{112,165,3906},{112,165,3904},{68,37,500},{11,141,496}},
+ {{120,165,3906},{120,165,3904},{76,37,500},{6,93,496}},
+ {{129,165,3906},{129,165,3904},{85,37,500},{15,93,496}},
+ {{70,254,4012},{137,165,3904},{93,37,500},{23,93,496}},
+ {{145,165,3906},{145,165,3904},{101,37,500},{31,93,496}},
+ {{86,254,4012},{153,165,3904},{109,37,500},{39,93,496}},
+ {{163,165,3906},{162,165,3904},{118,37,500},{48,93,496}},
+ {{171,165,3906},{170,165,3904},{126,37,500},{56,93,496}},
+ {{179,165,3906},{178,165,3904},{134,37,500},{64,93,496}},
+ {{187,165,3906},{187,165,3904},{142,37,500},{72,93,496}},
+ {{196,165,3906},{196,165,3904},{151,37,500},{81,93,496}},
+ {{204,165,3906},{204,165,3904},{159,37,500},{89,93,496}},
+ {{212,165,3906},{136,77,4008},{167,37,500},{97,93,496}},
+ {{220,165,3906},{131,93,4008},{175,37,500},{105,93,496}},
+ {{214,181,4001},{140,93,4008},{184,37,500},{114,93,496}},
+ {{222,181,4001},{148,93,4008},{192,37,500},{122,93,496}},
+ {{115,95,4085},{99,31,4080},{115,95,501},{99,31,496}},
+ {{123,95,4085},{107,31,4080},{123,95,501},{107,31,496}},
+ {{0,102,3840},{0,102,3840},{0,18,384},{0,18,384}},
+ {{5,167,3904},{5,167,3904},{0,13,256},{0,13,256}},
+ {{4,54,3968},{4,54,3968},{1,67,448},{1,67,448}},
+ {{30,198,3850},{30,198,3848},{0,3,480},{0,3,480}},
+ {{39,198,3850},{39,198,3848},{3,52,488},{3,52,488}},
+ {{47,198,3851},{47,198,3848},{3,4,488},{3,4,488}},
+ {{55,198,3851},{55,198,3848},{1,70,488},{1,70,488}},
+ {{53,167,3906},{63,198,3848},{3,22,488},{3,22,488}},
+ {{62,167,3906},{72,198,3848},{24,118,488},{0,6,496}},
+ {{70,167,3906},{80,198,3848},{32,118,488},{2,89,488}},
+ {{78,167,3906},{88,198,3848},{40,118,488},{1,73,496}},
+ {{86,167,3906},{96,198,3848},{48,118,488},{0,28,424}},
+ {{95,167,3906},{105,198,3848},{57,118,488},{9,28,424}},
+ {{103,167,3906},{113,198,3848},{65,118,488},{5,108,496}},
+ {{111,167,3906},{121,198,3848},{73,118,488},{13,108,496}},
+ {{119,167,3906},{129,198,3848},{81,118,488},{21,108,496}},
+ {{128,167,3906},{138,198,3848},{90,118,488},{6,28,496}},
+ {{136,167,3906},{146,198,3848},{98,118,488},{14,28,496}},
+ {{145,167,3906},{154,198,3848},{106,118,488},{22,28,496}},
+ {{153,167,3906},{162,198,3848},{114,118,488},{30,28,496}},
+ {{162,167,3906},{171,198,3848},{123,118,488},{39,28,496}},
+ {{170,167,3906},{179,198,3848},{131,118,488},{47,28,496}},
+ {{178,167,3906},{187,198,3848},{139,118,488},{55,28,496}},
+ {{186,167,3906},{195,198,3848},{147,118,488},{63,28,496}},
+ {{194,167,3906},{120,12,4008},{156,118,488},{72,28,496}},
+ {{206,198,3907},{116,28,4008},{164,118,488},{80,28,496}},
+ {{214,198,3907},{124,28,4008},{172,118,488},{88,28,496}},
+ {{222,198,3395},{132,28,4008},{180,118,488},{96,28,496}},
+ {{207,134,4001},{141,28,4008},{189,118,488},{105,28,496}},
+ {{95,30,4085},{86,31,4080},{95,30,501},{86,31,496}},
+ {{103,30,4085},{94,31,4080},{103,30,501},{94,31,496}},
+ {{111,30,4085},{102,31,4080},{111,30,501},{102,31,496}},
+ {{0,104,3840},{0,104,3840},{0,18,448},{0,18,448}},
+ {{4,39,3904},{4,39,3904},{0,4,384},{0,4,384}},
+ {{0,56,3968},{0,56,3968},{0,84,448},{0,84,448}},
+ {{6,110,3328},{6,110,3328},{0,20,448},{0,20,448}},
+ {{41,200,3850},{41,200,3848},{1,4,480},{1,4,480}},
+ {{49,200,3850},{49,200,3848},{1,8,416},{1,8,416}},
+ {{57,200,3851},{57,200,3848},{1,38,488},{1,38,488}},
+ {{65,200,3851},{65,200,3848},{1,120,488},{1,120,488}},
+ {{74,200,3851},{74,200,3848},{2,72,488},{2,72,488}},
+ {{68,6,3907},{82,200,3848},{2,24,488},{2,24,488}},
+ {{77,6,3907},{90,200,3848},{26,120,488},{10,24,488}},
+ {{97,63,3330},{98,200,3848},{34,120,488},{2,8,496}},
+ {{106,63,3330},{107,200,3848},{43,120,488},{3,92,488}},
+ {{114,63,3330},{115,200,3848},{51,120,488},{11,92,488}},
+ {{122,63,3330},{123,200,3848},{59,120,488},{7,76,496}},
+ {{130,63,3330},{131,200,3848},{67,120,488},{15,76,496}},
+ {{139,63,3330},{140,200,3848},{76,120,488},{24,76,496}},
+ {{147,63,3330},{148,200,3848},{84,120,488},{32,76,496}},
+ {{155,63,3330},{156,200,3848},{92,120,488},{40,76,496}},
+ {{164,63,3330},{164,200,3848},{100,120,488},{48,76,496}},
+ {{173,63,3330},{173,200,3848},{109,120,488},{57,76,496}},
+ {{184,6,3851},{181,200,3848},{117,120,488},{65,76,496}},
+ {{192,6,3851},{133,28,3936},{125,120,488},{73,76,496}},
+ {{189,200,3907},{141,28,3936},{133,120,488},{81,76,496}},
+ {{198,200,3907},{138,108,4000},{142,120,488},{90,76,496}},
+ {{206,200,3907},{146,108,4000},{150,120,488},{98,76,496}},
+ {{214,200,3395},{154,108,4000},{158,120,488},{106,76,496}},
+ {{190,136,4001},{162,108,4000},{166,120,488},{114,76,496}},
+ {{123,30,4076},{87,15,4080},{123,30,492},{87,15,496}},
+ {{117,110,4084},{80,31,4080},{117,110,500},{80,31,496}},
+ {{125,110,4084},{88,31,4080},{125,110,500},{88,31,496}},
+ {{133,110,4084},{96,31,4080},{133,110,500},{96,31,496}},
+ {{9,56,3904},{9,56,3904},{0,67,448},{0,67,448}},
+ {{1,8,3904},{1,8,3904},{1,84,448},{1,84,448}},
+ {{1,124,3904},{1,124,3904},{0,39,384},{0,39,384}},
+ {{9,124,3904},{9,124,3904},{1,4,448},{1,4,448}},
+ {{6,76,3904},{6,76,3904},{0,70,448},{0,70,448}},
+ {{62,6,3859},{62,6,3856},{2,38,480},{2,38,480}},
+ {{70,6,3859},{70,6,3856},{5,43,416},{5,43,416}},
+ {{78,6,3859},{78,6,3856},{2,11,416},{2,11,416}},
+ {{87,6,3859},{87,6,3856},{0,171,488},{0,171,488}},
+ {{67,8,3906},{95,6,3856},{8,171,488},{8,171,488}},
+ {{75,8,3907},{103,6,3856},{5,123,488},{5,123,488}},
+ {{83,8,3907},{111,6,3856},{2,75,488},{2,75,488}},
+ {{92,8,3907},{120,6,3856},{0,27,488},{0,27,488}},
+ {{100,8,3907},{128,6,3856},{8,27,488},{8,27,488}},
+ {{120,106,3843},{136,6,3856},{99,6,387},{16,27,488}},
+ {{128,106,3843},{144,6,3856},{107,6,387},{2,11,496}},
+ {{137,106,3843},{153,6,3856},{117,6,387},{11,11,496}},
+ {{145,106,3843},{161,6,3856},{125,6,387},{19,11,496}},
+ {{163,8,3851},{137,43,3904},{133,6,387},{27,11,496}},
+ {{171,8,3851},{145,43,3904},{141,6,387},{35,11,496}},
+ {{180,8,3851},{110,11,4000},{150,6,387},{44,11,496}},
+ {{188,8,3851},{118,11,4000},{158,6,387},{52,11,496}},
+ {{172,72,3907},{126,11,4000},{166,6,387},{60,11,496}},
+ {{174,6,3971},{134,11,4000},{174,6,387},{68,11,496}},
+ {{183,6,3971},{143,11,4000},{183,6,387},{77,11,496}},
+ {{191,6,3971},{151,11,4000},{191,6,387},{85,11,496}},
+ {{199,6,3971},{159,11,4000},{199,6,387},{93,11,496}},
+ {{92,12,4084},{69,15,4080},{92,12,500},{69,15,496}},
+ {{101,12,4084},{78,15,4080},{101,12,500},{78,15,496}},
+ {{110,12,4084},{86,15,4080},{110,12,500},{86,15,496}},
+ {{118,12,4084},{79,31,4080},{118,12,500},{79,31,496}},
+ {{126,12,4084},{87,31,4080},{126,12,500},{87,31,496}},
+ {{71,8,3602},{71,8,3600},{2,21,384},{2,21,384}},
+ {{79,8,3611},{79,8,3608},{0,69,448},{0,69,448}},
+ {{87,8,3611},{87,8,3608},{0,23,384},{0,23,384}},
+ {{95,8,3611},{95,8,3608},{1,5,448},{1,5,448}},
+ {{104,8,3611},{104,8,3608},{0,88,448},{0,88,448}},
+ {{112,8,3611},{112,8,3608},{0,72,448},{0,72,448}},
+ {{120,8,3611},{121,8,3608},{36,21,458},{36,21,456}},
+ {{133,47,3091},{129,8,3608},{44,21,458},{44,21,456}},
+ {{142,47,3091},{138,8,3608},{53,21,459},{53,21,456}},
+ {{98,12,3850},{98,12,3848},{61,21,459},{61,21,456}},
+ {{106,12,3850},{106,12,3848},{10,92,480},{69,21,456}},
+ {{114,12,3851},{114,12,3848},{18,92,480},{77,21,456}},
+ {{123,12,3851},{123,12,3848},{3,44,488},{86,21,456}},
+ {{95,12,3906},{95,12,3904},{11,44,488},{94,21,456}},
+ {{103,12,3906},{103,12,3904},{19,44,488},{102,21,456}},
+ {{111,12,3907},{111,12,3904},{27,44,489},{110,21,456}},
+ {{120,12,3907},{120,12,3904},{36,44,489},{119,21,456}},
+ {{128,12,3907},{128,12,3904},{44,44,489},{127,21,456}},
+ {{136,12,3907},{136,12,3904},{52,44,489},{135,21,456}},
+ {{144,12,3907},{144,12,3904},{60,44,490},{144,21,456}},
+ {{153,12,3907},{153,12,3904},{69,44,490},{153,21,456}},
+ {{161,12,3395},{149,188,3968},{77,44,490},{161,21,456}},
+ {{169,12,3395},{199,21,3928},{85,44,490},{169,21,456}},
+ {{113,95,4001},{202,69,3992},{125,8,483},{177,21,456}},
+ {{122,95,4001},{201,21,3984},{134,8,483},{186,21,456}},
+ {{143,8,4067},{209,21,3984},{142,8,483},{194,21,456}},
+ {{151,8,4067},{47,15,4080},{151,8,483},{47,15,496}},
+ {{159,8,4067},{55,15,4080},{159,8,483},{55,15,496}},
+ {{168,8,4067},{64,15,4080},{168,8,483},{64,15,496}},
+ {{160,40,4075},{72,15,4080},{160,40,491},{72,15,496}},
+ {{168,40,4075},{80,15,4080},{168,40,491},{80,15,496}},
+ {{144,8,4082},{88,15,4080},{144,8,498},{88,15,496}},
+ };
+
+ static void convert_etc1s_to_etc2_eac_r11(eac_block* pDst_block, const endpoint* pEndpoints, const selector* pSelector)
+ {
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ const color32& base_color = pEndpoints->m_color5;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ if (low_selector == high_selector)
+ {
+ uint32_t r;
+ decoder_etc_block::get_block_color5_r(base_color, inten_table, low_selector, r);
+
+ // Constant alpha block
+ // Select table 13, use selector 4 (0), set multiplier to 1 and base color r
+ pDst_block->m_base = r;
+ pDst_block->m_table = 13;
+ pDst_block->m_multiplier = 1;
+
+ // selectors are all 4's
+ static const uint8_t s_etc2_eac_r11_sel4[6] = { 0x92, 0x49, 0x24, 0x92, 0x49, 0x24 };
+ memcpy(pDst_block->m_selectors, s_etc2_eac_r11_sel4, sizeof(s_etc2_eac_r11_sel4));
+
+ return;
+ }
+
+ uint32_t selector_range_table = 0;
+ for (selector_range_table = 0; selector_range_table < NUM_ETC2_EAC_SELECTOR_RANGES; selector_range_table++)
+ if ((low_selector == s_etc2_eac_selector_ranges[selector_range_table].m_low) && (high_selector == s_etc2_eac_selector_ranges[selector_range_table].m_high))
+ break;
+ if (selector_range_table >= NUM_ETC2_EAC_SELECTOR_RANGES)
+ selector_range_table = 0;
+
+ const etc1_g_to_eac_conversion* pTable_entry = &s_etc1_g_to_etc2_r11[base_color.r + inten_table * 32][selector_range_table];
+
+ pDst_block->m_base = pTable_entry->m_base;
+ pDst_block->m_table = pTable_entry->m_table_mul >> 4;
+ pDst_block->m_multiplier = pTable_entry->m_table_mul & 15;
+
+ uint64_t selector_bits = 0;
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+
+ uint32_t ds = (pTable_entry->m_trans >> (s * 3)) & 7;
+
+ const uint32_t dst_ofs = 45 - (y + x * 4) * 3;
+ selector_bits |= (static_cast<uint64_t>(ds) << dst_ofs);
+ }
+ }
+
+ pDst_block->set_selector_bits(selector_bits);
+ }
+#endif // BASISD_SUPPORT_ETC2_EAC_RG11
+
+// ASTC
+ struct etc1_to_astc_solution
+ {
+ uint8_t m_lo;
+ uint8_t m_hi;
+ uint16_t m_err;
+ };
+
+#if BASISD_SUPPORT_ASTC
+ static dxt_selector_range g_etc1_to_astc_selector_ranges[] =
+ {
+ { 0, 3 },
+
+ { 1, 3 },
+ { 0, 2 },
+
+ { 1, 2 },
+
+ { 2, 3 },
+ { 0, 1 },
+ };
+
+ const uint32_t NUM_ETC1_TO_ASTC_SELECTOR_RANGES = sizeof(g_etc1_to_astc_selector_ranges) / sizeof(g_etc1_to_astc_selector_ranges[0]);
+
+ static uint32_t g_etc1_to_astc_selector_range_index[4][4];
+
+ const uint32_t NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS = 10;
+ static const uint8_t g_etc1_to_astc_selector_mappings[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS][4] =
+ {
+ { 0, 0, 1, 1 },
+ { 0, 0, 1, 2 },
+ { 0, 0, 1, 3 },
+ { 0, 0, 2, 3 },
+ { 0, 1, 1, 1 },
+ { 0, 1, 2, 2 },
+ { 0, 1, 2, 3 },
+ { 0, 2, 3, 3 },
+ { 1, 2, 2, 2 },
+ { 1, 2, 3, 3 },
+ };
+
+ static const etc1_to_astc_solution g_etc1_to_astc[32 * 8 * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS * NUM_ETC1_TO_ASTC_SELECTOR_RANGES] = {
+#include "basisu_transcoder_tables_astc.inc"
+ };
+
+ // The best selector mapping to use given a base base+inten table and used selector range for converting grayscale data.
+ static uint8_t g_etc1_to_astc_best_grayscale_mapping[32][8][NUM_ETC1_TO_ASTC_SELECTOR_RANGES];
+
+#if BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY
+ static const etc1_to_astc_solution g_etc1_to_astc_0_255[32 * 8 * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS * NUM_ETC1_TO_ASTC_SELECTOR_RANGES] = {
+#include "basisu_transcoder_tables_astc_0_255.inc"
+ };
+ static uint8_t g_etc1_to_astc_best_grayscale_mapping_0_255[32][8][NUM_ETC1_TO_ASTC_SELECTOR_RANGES];
+#endif
+
+ static uint32_t g_ise_to_unquant[48];
+
+#if BASISD_WRITE_NEW_ASTC_TABLES
+ static void create_etc1_to_astc_conversion_table_0_47()
+ {
+ FILE* pFile = nullptr;
+ fopen_s(&pFile, "basisu_transcoder_tables_astc.inc", "w");
+
+ uint32_t n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1_TO_ASTC_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1_to_astc_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1_to_astc_selector_ranges[sr].m_high;
+
+ uint32_t mapping_best_low[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+ uint32_t mapping_best_high[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+ uint64_t mapping_best_err[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+ uint64_t highest_best_err = 0;
+
+ for (uint32_t m = 0; m < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 47; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 47; lo++)
+ {
+ uint32_t colors[4];
+
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ uint32_t s_scaled = s | (s << 2) | (s << 4);
+ if (s_scaled > 32)
+ s_scaled++;
+
+ uint32_t c0 = g_ise_to_unquant[lo] | (g_ise_to_unquant[lo] << 8);
+ uint32_t c1 = g_ise_to_unquant[hi] | (g_ise_to_unquant[hi] << 8);
+ colors[s] = ((c0 * (64 - s_scaled) + c1 * s_scaled + 32) / 64) >> 8;
+ }
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1_to_astc_selector_mappings[m][s]];
+
+ int err_scale = 1;
+ // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor
+ // the low/high selectors which are clamping to either 0 or 255.
+ if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3)))
+ err_scale = 8;
+
+ total_err += (err * err) * err_scale;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ mapping_best_low[m] = best_lo;
+ mapping_best_high[m] = best_hi;
+ mapping_best_err[m] = best_err;
+ highest_best_err = basisu::maximum(highest_best_err, best_err);
+
+ } // m
+
+ for (uint32_t m = 0; m < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; m++)
+ {
+ uint64_t err = mapping_best_err[m];
+
+ err = basisu::minimum<uint64_t>(err, 0xFFFF);
+
+ fprintf(pFile, "{%u,%u,%u},", mapping_best_low[m], mapping_best_high[m], (uint32_t)err);
+
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+ } // m
+
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+ }
+
+ static void create_etc1_to_astc_conversion_table_0_255()
+ {
+ FILE* pFile = nullptr;
+ fopen_s(&pFile, "basisu_transcoder_tables_astc_0_255.inc", "w");
+
+ uint32_t n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1_TO_ASTC_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1_to_astc_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1_to_astc_selector_ranges[sr].m_high;
+
+ uint32_t mapping_best_low[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+ uint32_t mapping_best_high[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+ uint64_t mapping_best_err[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+ uint64_t highest_best_err = 0;
+
+ for (uint32_t m = 0; m < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 255; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 255; lo++)
+ {
+ uint32_t colors[4];
+
+ for (uint32_t s = 0; s < 4; s++)
+ {
+ uint32_t s_scaled = s | (s << 2) | (s << 4);
+ if (s_scaled > 32)
+ s_scaled++;
+
+ uint32_t c0 = lo | (lo << 8);
+ uint32_t c1 = hi | (hi << 8);
+ colors[s] = ((c0 * (64 - s_scaled) + c1 * s_scaled + 32) / 64) >> 8;
+ }
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1_to_astc_selector_mappings[m][s]];
+
+ // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor
+ // the low/high selectors which are clamping to either 0 or 255.
+ int err_scale = 1;
+ if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3)))
+ err_scale = 8;
+
+ total_err += (err * err) * err_scale;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ mapping_best_low[m] = best_lo;
+ mapping_best_high[m] = best_hi;
+ mapping_best_err[m] = best_err;
+ highest_best_err = basisu::maximum(highest_best_err, best_err);
+ } // m
+
+ for (uint32_t m = 0; m < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; m++)
+ {
+ uint64_t err = mapping_best_err[m];
+
+ err = basisu::minimum<uint64_t>(err, 0xFFFF);
+
+ fprintf(pFile, "{%u,%u,%u},", mapping_best_low[m], mapping_best_high[m], (uint32_t)err);
+
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+ } // m
+
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+ }
+#endif
+
+#endif
+
+#if BASISD_SUPPORT_ASTC
+ struct astc_block_params
+ {
+ // 2 groups of 5, but only a max of 8 are used (RRGGBBAA00)
+ uint8_t m_endpoints[10];
+ uint8_t m_weights[32];
+ };
+
+ // Table encodes 5 trits to 8 output bits. 3^5 entries.
+ // Inverse of the trit bit manipulation process in https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-integer-sequence-encoding
+ static const uint8_t g_astc_trit_encode[243] = { 0, 1, 2, 4, 5, 6, 8, 9, 10, 16, 17, 18, 20, 21, 22, 24, 25, 26, 3, 7, 11, 19, 23, 27, 12, 13, 14, 32, 33, 34, 36, 37, 38, 40, 41, 42, 48, 49, 50, 52, 53, 54, 56, 57, 58, 35, 39,
+ 43, 51, 55, 59, 44, 45, 46, 64, 65, 66, 68, 69, 70, 72, 73, 74, 80, 81, 82, 84, 85, 86, 88, 89, 90, 67, 71, 75, 83, 87, 91, 76, 77, 78, 128, 129, 130, 132, 133, 134, 136, 137, 138, 144, 145, 146, 148, 149, 150, 152, 153, 154,
+ 131, 135, 139, 147, 151, 155, 140, 141, 142, 160, 161, 162, 164, 165, 166, 168, 169, 170, 176, 177, 178, 180, 181, 182, 184, 185, 186, 163, 167, 171, 179, 183, 187, 172, 173, 174, 192, 193, 194, 196, 197, 198, 200, 201, 202,
+ 208, 209, 210, 212, 213, 214, 216, 217, 218, 195, 199, 203, 211, 215, 219, 204, 205, 206, 96, 97, 98, 100, 101, 102, 104, 105, 106, 112, 113, 114, 116, 117, 118, 120, 121, 122, 99, 103, 107, 115, 119, 123, 108, 109, 110, 224,
+ 225, 226, 228, 229, 230, 232, 233, 234, 240, 241, 242, 244, 245, 246, 248, 249, 250, 227, 231, 235, 243, 247, 251, 236, 237, 238, 28, 29, 30, 60, 61, 62, 92, 93, 94, 156, 157, 158, 188, 189, 190, 220, 221, 222, 31, 63, 95, 159,
+ 191, 223, 124, 125, 126 };
+
+ // Writes bits to output in an endian safe way
+ static inline void astc_set_bits(uint32_t *pOutput, int &bit_pos, uint32_t value, int total_bits)
+ {
+ uint8_t* pBytes = reinterpret_cast<uint8_t*>(pOutput);
+
+ while (total_bits)
+ {
+ const uint32_t bits_to_write = std::min(total_bits, 8 - (bit_pos & 7));
+
+ pBytes[bit_pos >> 3] |= static_cast<uint8_t>(value << (bit_pos & 7));
+
+ bit_pos += bits_to_write;
+ total_bits -= bits_to_write;
+ value >>= bits_to_write;
+ }
+ }
+
+ // Extracts bits [low,high]
+ static inline uint32_t astc_extract_bits(uint32_t bits, int low, int high)
+ {
+ return (bits >> low) & ((1 << (high - low + 1)) - 1);
+ }
+
+ // Encodes 5 values to output, usable for any range that uses trits and bits
+ static void astc_encode_trits(uint32_t *pOutput, const uint8_t *pValues, int& bit_pos, int n)
+ {
+ // First extract the trits and the bits from the 5 input values
+ int trits = 0, bits[5];
+ const uint32_t bit_mask = (1 << n) - 1;
+ for (int i = 0; i < 5; i++)
+ {
+ static const int s_muls[5] = { 1, 3, 9, 27, 81 };
+
+ const int t = pValues[i] >> n;
+
+ trits += t * s_muls[i];
+ bits[i] = pValues[i] & bit_mask;
+ }
+
+ // Encode the trits, by inverting the bit manipulations done by the decoder, converting 5 trits into 8-bits.
+ // See https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-integer-sequence-encoding
+
+ assert(trits < 243);
+ const int T = g_astc_trit_encode[trits];
+
+ // Now interleave the 8 encoded trit bits with the bits to form the encoded output. See table 94.
+ astc_set_bits(pOutput, bit_pos, bits[0] | (astc_extract_bits(T, 0, 1) << n) | (bits[1] << (2 + n)), n * 2 + 2);
+
+ astc_set_bits(pOutput, bit_pos, astc_extract_bits(T, 2, 3) | (bits[2] << 2) | (astc_extract_bits(T, 4, 4) << (2 + n)) | (bits[3] << (3 + n)) | (astc_extract_bits(T, 5, 6) << (3 + n * 2)) |
+ (bits[4] << (5 + n * 2)) | (astc_extract_bits(T, 7, 7) << (5 + n * 3)), n * 3 + 6);
+ }
+
+ // Packs a single format ASTC block using Color Endpoint Mode 12 (LDR RGBA direct), endpoint BISE range 13, 2-bit weights (range 2).
+ // We're always going to output blocks containing alpha, even if the input doesn't have alpha, for simplicity.
+ // Each block always has 4x4 weights, uses range 13 BISE encoding on the endpoints (0-47), and each weight ranges from 0-3. This encoding should be roughly equal in quality vs. BC1 for color.
+ // 8 total endpoints, stored as RGBA LH LH LH LH order, each ranging from 0-47.
+ // Note the input [0,47] endpoint values are not linear - they are encoded as outlined in the ASTC spec:
+ // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-endpoint-unquantization
+ // 32 total weights, stored as 16 CA CA, each ranging from 0-3.
+ static void astc_pack_block_cem_12_weight_range2(uint32_t *pOutput, const astc_block_params* pBlock)
+ {
+ uint8_t* pBytes = reinterpret_cast<uint8_t*>(pOutput);
+
+ // Write constant block mode, color component selector, number of partitions, color endpoint mode
+ // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#_block_mode
+ pBytes[0] = 0x42; pBytes[1] = 0x84; pBytes[2] = 0x01; pBytes[3] = 0x00;
+ pBytes[4] = 0x00; pBytes[5] = 0x00; pBytes[6] = 0x00; pBytes[7] = 0xc0;
+
+ pOutput[2] = 0;
+ pOutput[3] = 0;
+
+ // Pack 8 endpoints (each ranging between [0,47]) using BISE starting at bit 17
+ int bit_pos = 17;
+ astc_encode_trits(pOutput, pBlock->m_endpoints, bit_pos, 4);
+ astc_encode_trits(pOutput, pBlock->m_endpoints + 5, bit_pos, 4);
+
+ // Pack 32 2-bit weights, which are stored from the top down into the block in opposite bit order.
+
+ for (uint32_t i = 0; i < 32; i++)
+ {
+ static const uint8_t s_reverse_bits[4] = { 0, 2, 1, 3 };
+ const uint32_t ofs = 126 - (i * 2);
+ pBytes[ofs >> 3] |= (s_reverse_bits[pBlock->m_weights[i]] << (ofs & 7));
+ }
+ }
+
+ // CEM mode 12 (LDR RGBA Direct), 8-bit endpoints, 1-bit weights
+ // This ASTC mode is basically block truncation coding (BTC) using 1-bit weights and 8-bit/component endpoints - very convenient.
+ static void astc_pack_block_cem_12_weight_range0(uint32_t* pOutput, const astc_block_params* pBlock)
+ {
+ uint8_t* pBytes = reinterpret_cast<uint8_t*>(pOutput);
+
+ // Write constant block mode, color component selector, number of partitions, color endpoint mode
+ // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#_block_mode
+ pBytes[0] = 0x41; pBytes[1] = 0x84; pBytes[2] = 0x01; pBytes[3] = 0x00;
+ pOutput[1] = 0;
+ pBytes[8] = 0x00; pBytes[9] = 0x00; pBytes[10] = 0x00; pBytes[11] = 0xc0;
+ pOutput[3] = 0;
+
+ // Pack 8 endpoints (each ranging between [0,255]) as 8-bits starting at bit 17
+ int bit_pos = 17;
+ for (uint32_t i = 0; i < 8; i++)
+ astc_set_bits(pOutput, bit_pos, pBlock->m_endpoints[i], 8);
+
+ // Pack 32 1-bit weights, which are stored from the top down into the block in opposite bit order.
+ for (uint32_t i = 0; i < 32; i++)
+ {
+ const uint32_t ofs = 127 - i;
+ pBytes[ofs >> 3] |= (pBlock->m_weights[i] << (ofs & 7));
+ }
+ }
+
+#if BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY
+ // Optional 8-bit endpoint packing functions.
+
+ // CEM mode 4 (LDR Luminance+Alpha Direct), 8-bit endpoints, 2 bit weights
+ static void astc_pack_block_cem_4_weight_range2(uint32_t* pOutput, const astc_block_params* pBlock)
+ {
+ uint8_t* pBytes = reinterpret_cast<uint8_t*>(pOutput);
+
+ // Write constant block mode, color component selector, number of partitions, color endpoint mode
+ // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#_block_mode
+ pBytes[0] = 0x42; pBytes[1] = 0x84; pBytes[2] = 0x00; pBytes[3] = 0x00;
+ pBytes[4] = 0x00; pBytes[5] = 0x00; pBytes[6] = 0x00; pBytes[7] = 0xc0;
+
+ pOutput[2] = 0;
+ pOutput[3] = 0;
+
+ // Pack 4 endpoints (each ranging between [0,255]) as 8-bits starting at bit 17
+ int bit_pos = 17;
+ for (uint32_t i = 0; i < 4; i++)
+ astc_set_bits(pOutput, bit_pos, pBlock->m_endpoints[i], 8);
+
+ // Pack 32 2-bit weights, which are stored from the top down into the block in opposite bit order.
+ for (uint32_t i = 0; i < 32; i++)
+ {
+ static const uint8_t s_reverse_bits[4] = { 0, 2, 1, 3 };
+ const uint32_t ofs = 126 - (i * 2);
+ pBytes[ofs >> 3] |= (s_reverse_bits[pBlock->m_weights[i]] << (ofs & 7));
+ }
+ }
+
+ // CEM mode 8 (LDR RGB Direct), 8-bit endpoints, 2 bit weights
+ static void astc_pack_block_cem_8_weight_range2(uint32_t* pOutput, const astc_block_params* pBlock)
+ {
+ uint8_t* pBytes = reinterpret_cast<uint8_t*>(pOutput);
+
+ // Write constant block mode, color component selector, number of partitions, color endpoint mode
+ // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#_block_mode
+ pBytes[0] = 0x42; pBytes[1] = 0x00; pBytes[2] = 0x01; pBytes[3] = 0x00;
+
+ pOutput[1] = 0;
+ pOutput[2] = 0;
+ pOutput[3] = 0;
+
+ // Pack 6 endpoints (each ranging between [0,255]) as 8-bits starting at bit 17
+ int bit_pos = 17;
+ for (uint32_t i = 0; i < 6; i++)
+ astc_set_bits(pOutput, bit_pos, pBlock->m_endpoints[i], 8);
+
+ // Pack 16 2-bit weights, which are stored from the top down into the block in opposite bit order.
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ static const uint8_t s_reverse_bits[4] = { 0, 2, 1, 3 };
+ const uint32_t ofs = 126 - (i * 2);
+ pBytes[ofs >> 3] |= (s_reverse_bits[pBlock->m_weights[i]] << (ofs & 7));
+ }
+ }
+#endif
+
+ // Optimal quantized [0,47] entry to use given [0,255] input
+ static uint8_t g_astc_single_color_encoding_0[256];
+
+ // Optimal quantized [0,47] low/high values given [0,255] input assuming a selector of 1
+ static struct
+ {
+ uint8_t m_lo, m_hi;
+ } g_astc_single_color_encoding_1[256];
+
+ static void transcoder_init_astc()
+ {
+ for (uint32_t base_color = 0; base_color < 32; base_color++)
+ {
+ for (uint32_t inten_table = 0; inten_table < 8; inten_table++)
+ {
+ for (uint32_t range_index = 0; range_index < NUM_ETC1_TO_ASTC_SELECTOR_RANGES; range_index++)
+ {
+ const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc[(inten_table * 32 + base_color) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + range_index * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+
+ uint32_t best_mapping = 0;
+ uint32_t best_err = UINT32_MAX;
+ for (uint32_t mapping_index = 0; mapping_index < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; mapping_index++)
+ {
+ if (pTable_g[mapping_index].m_err < best_err)
+ {
+ best_err = pTable_g[mapping_index].m_err;
+ best_mapping = mapping_index;
+ }
+ }
+
+ g_etc1_to_astc_best_grayscale_mapping[base_color][inten_table][range_index] = static_cast<uint8_t>(best_mapping);
+ }
+ }
+ }
+
+#if BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY
+ for (uint32_t base_color = 0; base_color < 32; base_color++)
+ {
+ for (uint32_t inten_table = 0; inten_table < 8; inten_table++)
+ {
+ for (uint32_t range_index = 0; range_index < NUM_ETC1_TO_ASTC_SELECTOR_RANGES; range_index++)
+ {
+ const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc_0_255[(inten_table * 32 + base_color) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + range_index * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+
+ uint32_t best_mapping = 0;
+ uint32_t best_err = UINT32_MAX;
+ for (uint32_t mapping_index = 0; mapping_index < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; mapping_index++)
+ {
+ if (pTable_g[mapping_index].m_err < best_err)
+ {
+ best_err = pTable_g[mapping_index].m_err;
+ best_mapping = mapping_index;
+ }
+ }
+
+ g_etc1_to_astc_best_grayscale_mapping_0_255[base_color][inten_table][range_index] = static_cast<uint8_t>(best_mapping);
+ }
+ }
+ }
+#endif
+
+ for (uint32_t i = 0; i < NUM_ETC1_TO_ASTC_SELECTOR_RANGES; i++)
+ {
+ uint32_t l = g_etc1_to_astc_selector_ranges[i].m_low;
+ uint32_t h = g_etc1_to_astc_selector_ranges[i].m_high;
+ g_etc1_to_astc_selector_range_index[l][h] = i;
+ }
+
+ // Endpoint dequantization, see:
+ // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-endpoint-unquantization
+ for (uint32_t trit = 0; trit < 3; trit++)
+ {
+ for (uint32_t bit = 0; bit < 16; bit++)
+ {
+ const uint32_t A = (bit & 1) ? 511 : 0;
+ const uint32_t B = (bit >> 1) | ((bit >> 1) << 6);
+ const uint32_t C = 22;
+ const uint32_t D = trit;
+
+ uint32_t unq = D * C + B;
+ unq = unq ^ A;
+ unq = (A & 0x80) | (unq >> 2);
+
+ g_ise_to_unquant[bit | (trit << 4)] = unq;
+ }
+ }
+
+ // Compute table used for optimal single color encoding.
+ for (int i = 0; i < 256; i++)
+ {
+ int lowest_e = INT_MAX;
+
+ for (int lo = 0; lo < 48; lo++)
+ {
+ for (int hi = 0; hi < 48; hi++)
+ {
+ const int lo_v = g_ise_to_unquant[lo];
+ const int hi_v = g_ise_to_unquant[hi];
+
+ int l = lo_v | (lo_v << 8);
+ int h = hi_v | (hi_v << 8);
+
+ int v = ((l * (64 - 21) + (h * 21) + 32) / 64) >> 8;
+
+ int e = abs(v - i);
+
+ if (e < lowest_e)
+ {
+ g_astc_single_color_encoding_1[i].m_hi = static_cast<uint8_t>(hi);
+ g_astc_single_color_encoding_1[i].m_lo = static_cast<uint8_t>(lo);
+
+ lowest_e = e;
+ }
+
+ } // hi
+ } // lo
+ }
+
+ for (int i = 0; i < 256; i++)
+ {
+ int lowest_e = INT_MAX;
+
+ for (int lo = 0; lo < 48; lo++)
+ {
+ const int lo_v = g_ise_to_unquant[lo];
+
+ int e = abs(lo_v - i);
+
+ if (e < lowest_e)
+ {
+ g_astc_single_color_encoding_0[i] = static_cast<uint8_t>(lo);
+
+ lowest_e = e;
+ }
+ } // lo
+ }
+ }
+
+ // Converts opaque or color+alpha ETC1S block to ASTC 4x4.
+ // This function tries to use the best ASTC mode given the block's actual contents.
+ static void convert_etc1s_to_astc_4x4(void* pDst_block, const endpoint* pEndpoints, const selector* pSelector,
+ bool transcode_alpha, const endpoint *pEndpoint_codebook, const selector *pSelector_codebook)
+ {
+ astc_block_params blk;
+
+ blk.m_endpoints[8] = 0;
+ blk.m_endpoints[9] = 0;
+
+ int constant_alpha_val = 255;
+ int num_unique_alpha_selectors = 1;
+
+ if (transcode_alpha)
+ {
+ const selector& alpha_selectors = pSelector_codebook[((uint16_t*)pDst_block)[1]];
+
+ num_unique_alpha_selectors = alpha_selectors.m_num_unique_selectors;
+
+ if (num_unique_alpha_selectors == 1)
+ {
+ const endpoint& alpha_endpoint = pEndpoint_codebook[((uint16_t*)pDst_block)[0]];
+
+ const color32& alpha_base_color = alpha_endpoint.m_color5;
+ const uint32_t alpha_inten_table = alpha_endpoint.m_inten5;
+
+ int alpha_block_colors[4];
+ decoder_etc_block::get_block_colors5_g(alpha_block_colors, alpha_base_color, alpha_inten_table);
+
+ constant_alpha_val = alpha_block_colors[alpha_selectors.m_lo_selector];
+ }
+ }
+
+ const color32& base_color = pEndpoints->m_color5;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ // Handle solid color or BTC blocks, which can always be encoded from ETC1S to ASTC losslessly.
+ if ((pSelector->m_num_unique_selectors == 1) && (num_unique_alpha_selectors == 1))
+ {
+ // Both color and alpha are constant, write a solid color block and exit.
+ // See https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-void-extent-blocks
+ uint32_t r, g, b;
+ decoder_etc_block::get_block_color5(base_color, inten_table, low_selector, r, g, b);
+
+ uint32_t* pOutput = static_cast<uint32_t*>(pDst_block);
+ uint8_t* pBytes = reinterpret_cast<uint8_t*>(pDst_block);
+
+ pBytes[0] = 0xfc; pBytes[1] = 0xfd; pBytes[2] = 0xff; pBytes[3] = 0xff;
+
+ pOutput[1] = 0xffffffff;
+ pOutput[2] = 0;
+ pOutput[3] = 0;
+
+ int bit_pos = 64;
+ astc_set_bits(pOutput, bit_pos, r | (r << 8), 16);
+ astc_set_bits(pOutput, bit_pos, g | (g << 8), 16);
+ astc_set_bits(pOutput, bit_pos, b | (b << 8), 16);
+ astc_set_bits(pOutput, bit_pos, constant_alpha_val | (constant_alpha_val << 8), 16);
+
+ return;
+ }
+ else if ((pSelector->m_num_unique_selectors <= 2) && (num_unique_alpha_selectors <= 2))
+ {
+ // Both color and alpha use <= 2 unique selectors each.
+ // Use block truncation coding, which is lossless with ASTC (8-bit endpoints, 1-bit weights).
+ color32 block_colors[4];
+ decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table);
+
+ blk.m_endpoints[0] = block_colors[low_selector].r;
+ blk.m_endpoints[2] = block_colors[low_selector].g;
+ blk.m_endpoints[4] = block_colors[low_selector].b;
+
+ blk.m_endpoints[1] = block_colors[high_selector].r;
+ blk.m_endpoints[3] = block_colors[high_selector].g;
+ blk.m_endpoints[5] = block_colors[high_selector].b;
+
+ int s0 = blk.m_endpoints[0] + blk.m_endpoints[2] + blk.m_endpoints[4];
+ int s1 = blk.m_endpoints[1] + blk.m_endpoints[3] + blk.m_endpoints[5];
+ bool invert = false;
+ if (s1 < s0)
+ {
+ std::swap(blk.m_endpoints[0], blk.m_endpoints[1]);
+ std::swap(blk.m_endpoints[2], blk.m_endpoints[3]);
+ std::swap(blk.m_endpoints[4], blk.m_endpoints[5]);
+ invert = true;
+ }
+
+ if (transcode_alpha)
+ {
+ const endpoint& alpha_endpoint = pEndpoint_codebook[((uint16_t*)pDst_block)[0]];
+ const selector& alpha_selectors = pSelector_codebook[((uint16_t*)pDst_block)[1]];
+
+ const color32& alpha_base_color = alpha_endpoint.m_color5;
+ const uint32_t alpha_inten_table = alpha_endpoint.m_inten5;
+
+ const uint32_t alpha_low_selector = alpha_selectors.m_lo_selector;
+ const uint32_t alpha_high_selector = alpha_selectors.m_hi_selector;
+
+ int alpha_block_colors[4];
+ decoder_etc_block::get_block_colors5_g(alpha_block_colors, alpha_base_color, alpha_inten_table);
+
+ blk.m_endpoints[6] = static_cast<uint8_t>(alpha_block_colors[alpha_low_selector]);
+ blk.m_endpoints[7] = static_cast<uint8_t>(alpha_block_colors[alpha_high_selector]);
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = alpha_selectors.get_selector(x, y);
+ s = (s == alpha_high_selector) ? 1 : 0;
+
+ blk.m_weights[(x + y * 4) * 2 + 1] = static_cast<uint8_t>(s);
+ } // x
+ } // y
+ }
+ else
+ {
+ blk.m_endpoints[6] = 255;
+ blk.m_endpoints[7] = 255;
+
+ for (uint32_t i = 0; i < 16; i++)
+ blk.m_weights[i * 2 + 1] = 0;
+ }
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+
+ s = (s == high_selector) ? 1 : 0;
+
+ if (invert)
+ s = 1 - s;
+
+ blk.m_weights[(x + y * 4) * 2] = static_cast<uint8_t>(s);
+ } // x
+ } // y
+
+ astc_pack_block_cem_12_weight_range0(reinterpret_cast<uint32_t*>(pDst_block), &blk);
+
+ return;
+ }
+
+ // Either alpha and/or color use > 2 unique selectors each, so we must do something more complex.
+
+#if BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY
+ // The optional higher quality modes use 8-bits endpoints vs. [0,47] endpoints.
+
+ // If the block's base color is grayscale, all pixels are grayscale, so encode the block as Luminance+Alpha.
+ if ((base_color.r == base_color.g) && (base_color.r == base_color.b))
+ {
+ if (transcode_alpha)
+ {
+ const endpoint& alpha_endpoint = pEndpoint_codebook[((uint16_t*)pDst_block)[0]];
+ const selector& alpha_selectors = pSelector_codebook[((uint16_t*)pDst_block)[1]];
+
+ const color32& alpha_base_color = alpha_endpoint.m_color5;
+ const uint32_t alpha_inten_table = alpha_endpoint.m_inten5;
+
+ const uint32_t alpha_low_selector = alpha_selectors.m_lo_selector;
+ const uint32_t alpha_high_selector = alpha_selectors.m_hi_selector;
+
+ if (num_unique_alpha_selectors <= 2)
+ {
+ // Simple alpha block with only 1 or 2 unique values, so use BTC. This is lossless.
+ int alpha_block_colors[4];
+ decoder_etc_block::get_block_colors5_g(alpha_block_colors, alpha_base_color, alpha_inten_table);
+
+ blk.m_endpoints[2] = static_cast<uint8_t>(alpha_block_colors[alpha_low_selector]);
+ blk.m_endpoints[3] = static_cast<uint8_t>(alpha_block_colors[alpha_high_selector]);
+
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ uint32_t s = alpha_selectors.get_selector(i & 3, i >> 2);
+ blk.m_weights[i * 2 + 1] = (s == alpha_high_selector) ? 3 : 0;
+ }
+ }
+ else
+ {
+ // Convert ETC1S alpha
+ const uint32_t alpha_selector_range_table = g_etc1_to_astc_selector_range_index[alpha_low_selector][alpha_high_selector];
+
+ //[32][8][RANGES][MAPPING]
+ const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc_0_255[(alpha_inten_table * 32 + alpha_base_color.g) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + alpha_selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+
+ const uint32_t best_mapping = g_etc1_to_astc_best_grayscale_mapping_0_255[alpha_base_color.g][alpha_inten_table][alpha_selector_range_table];
+
+ blk.m_endpoints[2] = pTable_g[best_mapping].m_lo;
+ blk.m_endpoints[3] = pTable_g[best_mapping].m_hi;
+
+ const uint8_t* pSelectors_xlat = &g_etc1_to_astc_selector_mappings[best_mapping][0];
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = alpha_selectors.get_selector(x, y);
+ uint32_t as = pSelectors_xlat[s];
+
+ blk.m_weights[(x + y * 4) * 2 + 1] = static_cast<uint8_t>(as);
+ } // x
+ } // y
+ }
+ }
+ else
+ {
+ // No alpha slice - set output alpha to all 255's
+ blk.m_endpoints[2] = 255;
+ blk.m_endpoints[3] = 255;
+
+ for (uint32_t i = 0; i < 16; i++)
+ blk.m_weights[i * 2 + 1] = 0;
+ }
+
+ if (pSelector->m_num_unique_selectors <= 2)
+ {
+ // Simple color block with only 1 or 2 unique values, so use BTC. This is lossless.
+ int block_colors[4];
+ decoder_etc_block::get_block_colors5_g(block_colors, base_color, inten_table);
+
+ blk.m_endpoints[0] = static_cast<uint8_t>(block_colors[low_selector]);
+ blk.m_endpoints[1] = static_cast<uint8_t>(block_colors[high_selector]);
+
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ uint32_t s = pSelector->get_selector(i & 3, i >> 2);
+ blk.m_weights[i * 2] = (s == high_selector) ? 3 : 0;
+ }
+ }
+ else
+ {
+ // Convert ETC1S alpha
+ const uint32_t selector_range_table = g_etc1_to_astc_selector_range_index[low_selector][high_selector];
+
+ //[32][8][RANGES][MAPPING]
+ const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc_0_255[(inten_table * 32 + base_color.g) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+
+ const uint32_t best_mapping = g_etc1_to_astc_best_grayscale_mapping_0_255[base_color.g][inten_table][selector_range_table];
+
+ blk.m_endpoints[0] = pTable_g[best_mapping].m_lo;
+ blk.m_endpoints[1] = pTable_g[best_mapping].m_hi;
+
+ const uint8_t* pSelectors_xlat = &g_etc1_to_astc_selector_mappings[best_mapping][0];
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+ uint32_t as = pSelectors_xlat[s];
+
+ blk.m_weights[(x + y * 4) * 2] = static_cast<uint8_t>(as);
+ } // x
+ } // y
+ }
+
+ astc_pack_block_cem_4_weight_range2(reinterpret_cast<uint32_t*>(pDst_block), &blk);
+ return;
+ }
+
+ // The block isn't grayscale and it uses > 2 unique selectors for opaque and/or alpha.
+ // Check for fully opaque blocks, if so use 8-bit endpoints for slightly higher opaque quality (higher than BC1, but lower than BC7 mode 6 opaque).
+ if ((num_unique_alpha_selectors == 1) && (constant_alpha_val == 255))
+ {
+ // Convert ETC1S color
+ const uint32_t selector_range_table = g_etc1_to_astc_selector_range_index[low_selector][high_selector];
+
+ //[32][8][RANGES][MAPPING]
+ const etc1_to_astc_solution* pTable_r = &g_etc1_to_astc_0_255[(inten_table * 32 + base_color.r) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+ const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc_0_255[(inten_table * 32 + base_color.g) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+ const etc1_to_astc_solution* pTable_b = &g_etc1_to_astc_0_255[(inten_table * 32 + base_color.b) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+
+ uint32_t best_err = UINT_MAX;
+ uint32_t best_mapping = 0;
+
+ assert(NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS == 10);
+#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } }
+ DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4);
+ DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9);
+#undef DO_ITER
+
+ blk.m_endpoints[0] = pTable_r[best_mapping].m_lo;
+ blk.m_endpoints[1] = pTable_r[best_mapping].m_hi;
+
+ blk.m_endpoints[2] = pTable_g[best_mapping].m_lo;
+ blk.m_endpoints[3] = pTable_g[best_mapping].m_hi;
+
+ blk.m_endpoints[4] = pTable_b[best_mapping].m_lo;
+ blk.m_endpoints[5] = pTable_b[best_mapping].m_hi;
+
+ int s0 = blk.m_endpoints[0] + blk.m_endpoints[2] + blk.m_endpoints[4];
+ int s1 = blk.m_endpoints[1] + blk.m_endpoints[3] + blk.m_endpoints[5];
+ bool invert = false;
+
+ if (s1 < s0)
+ {
+ std::swap(blk.m_endpoints[0], blk.m_endpoints[1]);
+ std::swap(blk.m_endpoints[2], blk.m_endpoints[3]);
+ std::swap(blk.m_endpoints[4], blk.m_endpoints[5]);
+ invert = true;
+ }
+
+ const uint8_t* pSelectors_xlat = &g_etc1_to_astc_selector_mappings[best_mapping][0];
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+ uint32_t as = pSelectors_xlat[s];
+ if (invert)
+ as = 3 - as;
+
+ blk.m_weights[x + y * 4] = static_cast<uint8_t>(as);
+ } // x
+ } // y
+
+ // Now pack to ASTC
+ astc_pack_block_cem_8_weight_range2(reinterpret_cast<uint32_t*>(pDst_block), &blk);
+ return;
+ }
+#endif //#if BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY
+
+ // Nothing else worked, so fall back to CEM Mode 12 (LDR RGBA Direct), [0,47] endpoints, weight range 2 (2-bit weights), dual planes.
+ // This mode can handle everything, but at slightly less quality than BC1.
+ if (transcode_alpha)
+ {
+ const endpoint& alpha_endpoint = pEndpoint_codebook[((uint16_t*)pDst_block)[0]];
+ const selector& alpha_selectors = pSelector_codebook[((uint16_t*)pDst_block)[1]];
+
+ const color32& alpha_base_color = alpha_endpoint.m_color5;
+ const uint32_t alpha_inten_table = alpha_endpoint.m_inten5;
+
+ const uint32_t alpha_low_selector = alpha_selectors.m_lo_selector;
+ const uint32_t alpha_high_selector = alpha_selectors.m_hi_selector;
+
+ if (alpha_low_selector == alpha_high_selector)
+ {
+ // Solid alpha block - use precomputed tables.
+ int alpha_block_colors[4];
+ decoder_etc_block::get_block_colors5_g(alpha_block_colors, alpha_base_color, alpha_inten_table);
+
+ const uint32_t g = alpha_block_colors[alpha_low_selector];
+
+ blk.m_endpoints[6] = g_astc_single_color_encoding_1[g].m_lo;
+ blk.m_endpoints[7] = g_astc_single_color_encoding_1[g].m_hi;
+
+ for (uint32_t i = 0; i < 16; i++)
+ blk.m_weights[i * 2 + 1] = 1;
+ }
+ else if ((alpha_inten_table >= 7) && (alpha_selectors.m_num_unique_selectors == 2) && (alpha_low_selector == 0) && (alpha_high_selector == 3))
+ {
+ // Handle outlier case where only the two outer colors are used with inten table 7.
+ color32 alpha_block_colors[4];
+
+ decoder_etc_block::get_block_colors5(alpha_block_colors, alpha_base_color, alpha_inten_table);
+
+ const uint32_t g0 = alpha_block_colors[0].g;
+ const uint32_t g1 = alpha_block_colors[3].g;
+
+ blk.m_endpoints[6] = g_astc_single_color_encoding_0[g0];
+ blk.m_endpoints[7] = g_astc_single_color_encoding_0[g1];
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = alpha_selectors.get_selector(x, y);
+ uint32_t as = (s == alpha_high_selector) ? 3 : 0;
+
+ blk.m_weights[(x + y * 4) * 2 + 1] = static_cast<uint8_t>(as);
+ } // x
+ } // y
+ }
+ else
+ {
+ // Convert ETC1S alpha
+ const uint32_t alpha_selector_range_table = g_etc1_to_astc_selector_range_index[alpha_low_selector][alpha_high_selector];
+
+ //[32][8][RANGES][MAPPING]
+ const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc[(alpha_inten_table * 32 + alpha_base_color.g) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + alpha_selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+
+ const uint32_t best_mapping = g_etc1_to_astc_best_grayscale_mapping[alpha_base_color.g][alpha_inten_table][alpha_selector_range_table];
+
+ blk.m_endpoints[6] = pTable_g[best_mapping].m_lo;
+ blk.m_endpoints[7] = pTable_g[best_mapping].m_hi;
+
+ const uint8_t* pSelectors_xlat = &g_etc1_to_astc_selector_mappings[best_mapping][0];
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = alpha_selectors.get_selector(x, y);
+ uint32_t as = pSelectors_xlat[s];
+
+ blk.m_weights[(x + y * 4) * 2 + 1] = static_cast<uint8_t>(as);
+ } // x
+ } // y
+ }
+ }
+ else
+ {
+ // No alpha slice - set output alpha to all 255's
+ // 1 is 255 when dequantized
+ blk.m_endpoints[6] = 1;
+ blk.m_endpoints[7] = 1;
+
+ for (uint32_t i = 0; i < 16; i++)
+ blk.m_weights[i * 2 + 1] = 0;
+ }
+
+ if (low_selector == high_selector)
+ {
+ // Solid color block - use precomputed tables of optimal endpoints assuming selector weights are all 1.
+ color32 block_colors[4];
+
+ decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table);
+
+ const uint32_t r = block_colors[low_selector].r;
+ const uint32_t g = block_colors[low_selector].g;
+ const uint32_t b = block_colors[low_selector].b;
+
+ blk.m_endpoints[0] = g_astc_single_color_encoding_1[r].m_lo;
+ blk.m_endpoints[1] = g_astc_single_color_encoding_1[r].m_hi;
+
+ blk.m_endpoints[2] = g_astc_single_color_encoding_1[g].m_lo;
+ blk.m_endpoints[3] = g_astc_single_color_encoding_1[g].m_hi;
+
+ blk.m_endpoints[4] = g_astc_single_color_encoding_1[b].m_lo;
+ blk.m_endpoints[5] = g_astc_single_color_encoding_1[b].m_hi;
+
+ int s0 = g_ise_to_unquant[blk.m_endpoints[0]] + g_ise_to_unquant[blk.m_endpoints[2]] + g_ise_to_unquant[blk.m_endpoints[4]];
+ int s1 = g_ise_to_unquant[blk.m_endpoints[1]] + g_ise_to_unquant[blk.m_endpoints[3]] + g_ise_to_unquant[blk.m_endpoints[5]];
+ bool invert = false;
+
+ if (s1 < s0)
+ {
+ std::swap(blk.m_endpoints[0], blk.m_endpoints[1]);
+ std::swap(blk.m_endpoints[2], blk.m_endpoints[3]);
+ std::swap(blk.m_endpoints[4], blk.m_endpoints[5]);
+ invert = true;
+ }
+
+ for (uint32_t i = 0; i < 16; i++)
+ blk.m_weights[i * 2] = invert ? 2 : 1;
+ }
+ else if ((inten_table >= 7) && (pSelector->m_num_unique_selectors == 2) && (pSelector->m_lo_selector == 0) && (pSelector->m_hi_selector == 3))
+ {
+ // Handle outlier case where only the two outer colors are used with inten table 7.
+ color32 block_colors[4];
+
+ decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table);
+
+ const uint32_t r0 = block_colors[0].r;
+ const uint32_t g0 = block_colors[0].g;
+ const uint32_t b0 = block_colors[0].b;
+
+ const uint32_t r1 = block_colors[3].r;
+ const uint32_t g1 = block_colors[3].g;
+ const uint32_t b1 = block_colors[3].b;
+
+ blk.m_endpoints[0] = g_astc_single_color_encoding_0[r0];
+ blk.m_endpoints[1] = g_astc_single_color_encoding_0[r1];
+
+ blk.m_endpoints[2] = g_astc_single_color_encoding_0[g0];
+ blk.m_endpoints[3] = g_astc_single_color_encoding_0[g1];
+
+ blk.m_endpoints[4] = g_astc_single_color_encoding_0[b0];
+ blk.m_endpoints[5] = g_astc_single_color_encoding_0[b1];
+
+ int s0 = g_ise_to_unquant[blk.m_endpoints[0]] + g_ise_to_unquant[blk.m_endpoints[2]] + g_ise_to_unquant[blk.m_endpoints[4]];
+ int s1 = g_ise_to_unquant[blk.m_endpoints[1]] + g_ise_to_unquant[blk.m_endpoints[3]] + g_ise_to_unquant[blk.m_endpoints[5]];
+ bool invert = false;
+
+ if (s1 < s0)
+ {
+ std::swap(blk.m_endpoints[0], blk.m_endpoints[1]);
+ std::swap(blk.m_endpoints[2], blk.m_endpoints[3]);
+ std::swap(blk.m_endpoints[4], blk.m_endpoints[5]);
+ invert = true;
+ }
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+ uint32_t as = (s == low_selector) ? 0 : 3;
+
+ if (invert)
+ as = 3 - as;
+
+ blk.m_weights[(x + y * 4) * 2] = static_cast<uint8_t>(as);
+ } // x
+ } // y
+ }
+ else
+ {
+ // Convert ETC1S color
+ const uint32_t selector_range_table = g_etc1_to_astc_selector_range_index[low_selector][high_selector];
+
+ //[32][8][RANGES][MAPPING]
+ const etc1_to_astc_solution* pTable_r = &g_etc1_to_astc[(inten_table * 32 + base_color.r) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+ const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc[(inten_table * 32 + base_color.g) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+ const etc1_to_astc_solution* pTable_b = &g_etc1_to_astc[(inten_table * 32 + base_color.b) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS];
+
+ uint32_t best_err = UINT_MAX;
+ uint32_t best_mapping = 0;
+
+ assert(NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS == 10);
+#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } }
+ DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4);
+ DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9);
+#undef DO_ITER
+
+ blk.m_endpoints[0] = pTable_r[best_mapping].m_lo;
+ blk.m_endpoints[1] = pTable_r[best_mapping].m_hi;
+
+ blk.m_endpoints[2] = pTable_g[best_mapping].m_lo;
+ blk.m_endpoints[3] = pTable_g[best_mapping].m_hi;
+
+ blk.m_endpoints[4] = pTable_b[best_mapping].m_lo;
+ blk.m_endpoints[5] = pTable_b[best_mapping].m_hi;
+
+ int s0 = g_ise_to_unquant[blk.m_endpoints[0]] + g_ise_to_unquant[blk.m_endpoints[2]] + g_ise_to_unquant[blk.m_endpoints[4]];
+ int s1 = g_ise_to_unquant[blk.m_endpoints[1]] + g_ise_to_unquant[blk.m_endpoints[3]] + g_ise_to_unquant[blk.m_endpoints[5]];
+ bool invert = false;
+
+ if (s1 < s0)
+ {
+ std::swap(blk.m_endpoints[0], blk.m_endpoints[1]);
+ std::swap(blk.m_endpoints[2], blk.m_endpoints[3]);
+ std::swap(blk.m_endpoints[4], blk.m_endpoints[5]);
+ invert = true;
+ }
+
+ const uint8_t* pSelectors_xlat = &g_etc1_to_astc_selector_mappings[best_mapping][0];
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = pSelector->get_selector(x, y);
+ uint32_t as = pSelectors_xlat[s];
+ if (invert)
+ as = 3 - as;
+
+ blk.m_weights[(x + y * 4) * 2] = static_cast<uint8_t>(as);
+ } // x
+ } // y
+ }
+
+ // Now pack to ASTC
+ astc_pack_block_cem_12_weight_range2(reinterpret_cast<uint32_t *>(pDst_block), &blk);
+ }
+#endif
+
+#if BASISD_SUPPORT_ATC
+ // ATC and PVRTC2 both use these tables.
+ struct etc1s_to_atc_solution
+ {
+ uint8_t m_lo;
+ uint8_t m_hi;
+ uint16_t m_err;
+ };
+
+ static dxt_selector_range g_etc1s_to_atc_selector_ranges[] =
+ {
+ { 0, 3 },
+ { 1, 3 },
+ { 0, 2 },
+ { 1, 2 },
+ { 2, 3 },
+ { 0, 1 },
+ };
+
+ const uint32_t NUM_ETC1S_TO_ATC_SELECTOR_RANGES = sizeof(g_etc1s_to_atc_selector_ranges) / sizeof(g_etc1s_to_atc_selector_ranges[0]);
+
+ static uint32_t g_etc1s_to_atc_selector_range_index[4][4];
+
+ const uint32_t NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS = 10;
+ static const uint8_t g_etc1s_to_atc_selector_mappings[NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS][4] =
+ {
+ { 0, 0, 1, 1 },
+ { 0, 0, 1, 2 },
+ { 0, 0, 1, 3 },
+ { 0, 0, 2, 3 },
+ { 0, 1, 1, 1 },
+ { 0, 1, 2, 2 },
+ { 0, 1, 2, 3 }, //6 - identity
+ { 0, 2, 3, 3 },
+ { 1, 2, 2, 2 },
+ { 1, 2, 3, 3 },
+ };
+ const uint32_t ATC_IDENTITY_SELECTOR_MAPPING_INDEX = 6;
+
+#if BASISD_SUPPORT_PVRTC2
+ static const etc1s_to_atc_solution g_etc1s_to_pvrtc2_45[32 * 8 * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS * NUM_ETC1S_TO_ATC_SELECTOR_RANGES] = {
+#include "basisu_transcoder_tables_pvrtc2_45.inc"
+ };
+
+ static const etc1s_to_atc_solution g_etc1s_to_pvrtc2_alpha_33[32 * 8 * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS * NUM_ETC1S_TO_ATC_SELECTOR_RANGES] = {
+#include "basisu_transcoder_tables_pvrtc2_alpha_33.inc"
+ };
+#endif
+
+ static const etc1s_to_atc_solution g_etc1s_to_atc_55[32 * 8 * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS * NUM_ETC1S_TO_ATC_SELECTOR_RANGES] = {
+#include "basisu_transcoder_tables_atc_55.inc"
+ };
+
+ static const etc1s_to_atc_solution g_etc1s_to_atc_56[32 * 8 * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS * NUM_ETC1S_TO_ATC_SELECTOR_RANGES] = {
+#include "basisu_transcoder_tables_atc_56.inc"
+ };
+
+ struct atc_match_entry
+ {
+ uint8_t m_lo;
+ uint8_t m_hi;
+ };
+ static atc_match_entry g_pvrtc2_match45_equals_1[256], g_atc_match55_equals_1[256], g_atc_match56_equals_1[256]; // selector 1
+ static atc_match_entry g_pvrtc2_match4[256], g_atc_match5[256], g_atc_match6[256];
+
+ static void prepare_atc_single_color_table(atc_match_entry* pTable, int size0, int size1, int sel)
+ {
+ for (int i = 0; i < 256; i++)
+ {
+ int lowest_e = 256;
+ for (int lo = 0; lo < size0; lo++)
+ {
+ int lo_e = lo;
+ if (size0 == 16)
+ {
+ lo_e = (lo_e << 1) | (lo_e >> 3);
+ lo_e = (lo_e << 3) | (lo_e >> 2);
+ }
+ else if (size0 == 32)
+ lo_e = (lo_e << 3) | (lo_e >> 2);
+ else
+ lo_e = (lo_e << 2) | (lo_e >> 4);
+
+ for (int hi = 0; hi < size1; hi++)
+ {
+ int hi_e = hi;
+ if (size1 == 16)
+ {
+ // This is only for PVRTC2 - expand to 5 then 8
+ hi_e = (hi_e << 1) | (hi_e >> 3);
+ hi_e = (hi_e << 3) | (hi_e >> 2);
+ }
+ else if (size1 == 32)
+ hi_e = (hi_e << 3) | (hi_e >> 2);
+ else
+ hi_e = (hi_e << 2) | (hi_e >> 4);
+
+ int e;
+
+ if (sel == 1)
+ {
+ // Selector 1
+ e = abs(((lo_e * 5 + hi_e * 3) / 8) - i);
+ }
+ else
+ {
+ assert(sel == 3);
+
+ // Selector 3
+ e = abs(hi_e - i);
+ }
+
+ if (e < lowest_e)
+ {
+ pTable[i].m_lo = static_cast<uint8_t>(lo);
+ pTable[i].m_hi = static_cast<uint8_t>(hi);
+
+ lowest_e = e;
+ }
+
+ } // hi
+ } // lo
+ } // i
+ }
+
+ static void transcoder_init_atc()
+ {
+ prepare_atc_single_color_table(g_pvrtc2_match45_equals_1, 16, 32, 1);
+ prepare_atc_single_color_table(g_atc_match55_equals_1, 32, 32, 1);
+ prepare_atc_single_color_table(g_atc_match56_equals_1, 32, 64, 1);
+
+ prepare_atc_single_color_table(g_pvrtc2_match4, 1, 16, 3);
+ prepare_atc_single_color_table(g_atc_match5, 1, 32, 3);
+ prepare_atc_single_color_table(g_atc_match6, 1, 64, 3);
+
+ for (uint32_t i = 0; i < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; i++)
+ {
+ uint32_t l = g_etc1s_to_atc_selector_ranges[i].m_low;
+ uint32_t h = g_etc1s_to_atc_selector_ranges[i].m_high;
+ g_etc1s_to_atc_selector_range_index[l][h] = i;
+ }
+ }
+
+ struct atc_block
+ {
+ uint8_t m_lo[2];
+ uint8_t m_hi[2];
+ uint8_t m_sels[4];
+
+ void set_low_color(uint32_t r, uint32_t g, uint32_t b)
+ {
+ assert((r < 32) && (g < 32) && (b < 32));
+ uint32_t x = (r << 10) | (g << 5) | b;
+ m_lo[0] = x & 0xFF;
+ m_lo[1] = (x >> 8) & 0xFF;
+ }
+
+ void set_high_color(uint32_t r, uint32_t g, uint32_t b)
+ {
+ assert((r < 32) && (g < 64) && (b < 32));
+ uint32_t x = (r << 11) | (g << 5) | b;
+ m_hi[0] = x & 0xFF;
+ m_hi[1] = (x >> 8) & 0xFF;
+ }
+ };
+
+ static void convert_etc1s_to_atc(void* pDst, const endpoint* pEndpoints, const selector* pSelector)
+ {
+ atc_block* pBlock = static_cast<atc_block*>(pDst);
+
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ const color32& base_color = pEndpoints->m_color5;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ if (low_selector == high_selector)
+ {
+ uint32_t r, g, b;
+ decoder_etc_block::get_block_color5(base_color, inten_table, low_selector, r, g, b);
+
+ pBlock->set_low_color(g_atc_match55_equals_1[r].m_lo, g_atc_match56_equals_1[g].m_lo, g_atc_match55_equals_1[b].m_lo);
+ pBlock->set_high_color(g_atc_match55_equals_1[r].m_hi, g_atc_match56_equals_1[g].m_hi, g_atc_match55_equals_1[b].m_hi);
+
+ pBlock->m_sels[0] = 0x55;
+ pBlock->m_sels[1] = 0x55;
+ pBlock->m_sels[2] = 0x55;
+ pBlock->m_sels[3] = 0x55;
+
+ return;
+ }
+ else if ((inten_table >= 7) && (pSelector->m_num_unique_selectors == 2) && (pSelector->m_lo_selector == 0) && (pSelector->m_hi_selector == 3))
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table);
+
+ const uint32_t r0 = block_colors[0].r;
+ const uint32_t g0 = block_colors[0].g;
+ const uint32_t b0 = block_colors[0].b;
+
+ const uint32_t r1 = block_colors[3].r;
+ const uint32_t g1 = block_colors[3].g;
+ const uint32_t b1 = block_colors[3].b;
+
+ pBlock->set_low_color(g_atc_match5[r0].m_hi, g_atc_match5[g0].m_hi, g_atc_match5[b0].m_hi);
+ pBlock->set_high_color(g_atc_match5[r1].m_hi, g_atc_match6[g1].m_hi, g_atc_match5[b1].m_hi);
+
+ pBlock->m_sels[0] = pSelector->m_selectors[0];
+ pBlock->m_sels[1] = pSelector->m_selectors[1];
+ pBlock->m_sels[2] = pSelector->m_selectors[2];
+ pBlock->m_sels[3] = pSelector->m_selectors[3];
+
+ return;
+ }
+
+ const uint32_t selector_range_table = g_etc1s_to_atc_selector_range_index[low_selector][high_selector];
+
+ //[32][8][RANGES][MAPPING]
+ const etc1s_to_atc_solution* pTable_r = &g_etc1s_to_atc_55[(inten_table * 32 + base_color.r) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS];
+ const etc1s_to_atc_solution* pTable_g = &g_etc1s_to_atc_56[(inten_table * 32 + base_color.g) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS];
+ const etc1s_to_atc_solution* pTable_b = &g_etc1s_to_atc_55[(inten_table * 32 + base_color.b) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS];
+
+ uint32_t best_err = UINT_MAX;
+ uint32_t best_mapping = 0;
+
+ assert(NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS == 10);
+#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } }
+ DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4);
+ DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9);
+#undef DO_ITER
+
+ pBlock->set_low_color(pTable_r[best_mapping].m_lo, pTable_g[best_mapping].m_lo, pTable_b[best_mapping].m_lo);
+ pBlock->set_high_color(pTable_r[best_mapping].m_hi, pTable_g[best_mapping].m_hi, pTable_b[best_mapping].m_hi);
+
+ if (ATC_IDENTITY_SELECTOR_MAPPING_INDEX == best_mapping)
+ {
+ pBlock->m_sels[0] = pSelector->m_selectors[0];
+ pBlock->m_sels[1] = pSelector->m_selectors[1];
+ pBlock->m_sels[2] = pSelector->m_selectors[2];
+ pBlock->m_sels[3] = pSelector->m_selectors[3];
+ }
+ else
+ {
+ const uint8_t* pSelectors_xlat = &g_etc1s_to_atc_selector_mappings[best_mapping][0];
+
+ const uint32_t sel_bits0 = pSelector->m_selectors[0];
+ const uint32_t sel_bits1 = pSelector->m_selectors[1];
+ const uint32_t sel_bits2 = pSelector->m_selectors[2];
+ const uint32_t sel_bits3 = pSelector->m_selectors[3];
+
+ uint32_t atc_sels0 = 0, atc_sels1 = 0, atc_sels2 = 0, atc_sels3 = 0;
+
+#define DO_X(x) { \
+ const uint32_t x_shift = (x) * 2; \
+ atc_sels0 |= (pSelectors_xlat[(sel_bits0 >> x_shift) & 3] << x_shift); \
+ atc_sels1 |= (pSelectors_xlat[(sel_bits1 >> x_shift) & 3] << x_shift); \
+ atc_sels2 |= (pSelectors_xlat[(sel_bits2 >> x_shift) & 3] << x_shift); \
+ atc_sels3 |= (pSelectors_xlat[(sel_bits3 >> x_shift) & 3] << x_shift); }
+
+ DO_X(0);
+ DO_X(1);
+ DO_X(2);
+ DO_X(3);
+#undef DO_X
+
+ pBlock->m_sels[0] = (uint8_t)atc_sels0;
+ pBlock->m_sels[1] = (uint8_t)atc_sels1;
+ pBlock->m_sels[2] = (uint8_t)atc_sels2;
+ pBlock->m_sels[3] = (uint8_t)atc_sels3;
+ }
+ }
+
+#if BASISD_WRITE_NEW_ATC_TABLES
+ static void create_etc1s_to_atc_conversion_tables()
+ {
+ // ATC 55
+ FILE* pFile = nullptr;
+ fopen_s(&pFile, "basisu_transcoder_tables_atc_55.inc", "w");
+
+ uint32_t n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high;
+
+ for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 31; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 31; lo++)
+ {
+ uint32_t colors[4];
+
+ colors[0] = (lo << 3) | (lo >> 2);
+ colors[3] = (hi << 3) | (hi >> 2);
+
+ colors[1] = (colors[0] * 5 + colors[3] * 3) / 8;
+ colors[2] = (colors[3] * 5 + colors[0] * 3) / 8;
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]];
+
+ int err_scale = 1;
+ // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor
+ // the low/high selectors which are clamping to either 0 or 255.
+ if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3)))
+ err_scale = 5;
+
+ total_err += (err * err) * err_scale;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ //assert(best_err <= 0xFFFF);
+ best_err = basisu::minimum<uint32_t>(best_err, 0xFFFF);
+
+ fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+ } // m
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+ pFile = nullptr;
+
+ // ATC 56
+ fopen_s(&pFile, "basisu_transcoder_tables_atc_56.inc", "w");
+
+ n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high;
+
+ for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 63; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 31; lo++)
+ {
+ uint32_t colors[4];
+
+ colors[0] = (lo << 3) | (lo >> 2);
+ colors[3] = (hi << 2) | (hi >> 4);
+
+ colors[1] = (colors[0] * 5 + colors[3] * 3) / 8;
+ colors[2] = (colors[3] * 5 + colors[0] * 3) / 8;
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]];
+
+ int err_scale = 1;
+ // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor
+ // the low/high selectors which are clamping to either 0 or 255.
+ if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3)))
+ err_scale = 5;
+
+ total_err += (err * err) * err_scale;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ //assert(best_err <= 0xFFFF);
+ best_err = basisu::minimum<uint32_t>(best_err, 0xFFFF);
+
+ fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+ } // m
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+
+ // PVRTC2 45
+ fopen_s(&pFile, "basisu_transcoder_tables_pvrtc2_45.inc", "w");
+
+ n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high;
+
+ for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 31; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 15; lo++)
+ {
+ uint32_t colors[4];
+
+ colors[0] = (lo << 1) | (lo >> 3);
+ colors[0] = (colors[0] << 3) | (colors[0] >> 2);
+
+ colors[3] = (hi << 3) | (hi >> 2);
+
+ colors[1] = (colors[0] * 5 + colors[3] * 3) / 8;
+ colors[2] = (colors[3] * 5 + colors[0] * 3) / 8;
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]];
+
+ int err_scale = 1;
+ // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor
+ // the low/high selectors which are clamping to either 0 or 255.
+ if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3)))
+ err_scale = 5;
+
+ total_err += (err * err) * err_scale;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ //assert(best_err <= 0xFFFF);
+ best_err = basisu::minimum<uint32_t>(best_err, 0xFFFF);
+
+ fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+ } // m
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+
+#if 0
+ // PVRTC2 34
+ fopen_s(&pFile, "basisu_transcoder_tables_pvrtc2_34.inc", "w");
+
+ n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high;
+
+ for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 15; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 7; lo++)
+ {
+ uint32_t colors[4];
+
+ colors[0] = (lo << 2) | (lo >> 1);
+ colors[0] = (colors[0] << 3) | (colors[0] >> 2);
+
+ colors[3] = (hi << 1) | (hi >> 3);
+ colors[3] = (colors[3] << 3) | (colors[3] >> 2);
+
+ colors[1] = (colors[0] * 5 + colors[3] * 3) / 8;
+ colors[2] = (colors[3] * 5 + colors[0] * 3) / 8;
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]];
+
+ int err_scale = 1;
+ // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor
+ // the low/high selectors which are clamping to either 0 or 255.
+ if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3)))
+ err_scale = 5;
+
+ total_err += (err * err) * err_scale;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ //assert(best_err <= 0xFFFF);
+ best_err = basisu::minimum<uint32_t>(best_err, 0xFFFF);
+
+ fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+ } // m
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+#endif
+#if 0
+ // PVRTC2 44
+ fopen_s(&pFile, "basisu_transcoder_tables_pvrtc2_44.inc", "w");
+
+ n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high;
+
+ for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 15; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 15; lo++)
+ {
+ uint32_t colors[4];
+
+ colors[0] = (lo << 1) | (lo >> 3);
+ colors[0] = (colors[0] << 3) | (colors[0] >> 2);
+
+ colors[3] = (hi << 1) | (hi >> 3);
+ colors[3] = (colors[3] << 3) | (colors[3] >> 2);
+
+ colors[1] = (colors[0] * 5 + colors[3] * 3) / 8;
+ colors[2] = (colors[3] * 5 + colors[0] * 3) / 8;
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]];
+
+ int err_scale = 1;
+ // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor
+ // the low/high selectors which are clamping to either 0 or 255.
+ if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3)))
+ err_scale = 5;
+
+ total_err += (err * err) * err_scale;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ //assert(best_err <= 0xFFFF);
+ best_err = basisu::minimum<uint32_t>(best_err, 0xFFFF);
+
+ fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+ } // m
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+#endif
+
+ // PVRTC2 alpha 33
+ fopen_s(&pFile, "basisu_transcoder_tables_pvrtc2_alpha_33.inc", "w");
+
+ n = 0;
+
+ for (int inten = 0; inten < 8; inten++)
+ {
+ for (uint32_t g = 0; g < 32; g++)
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten);
+
+ for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++)
+ {
+ const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low;
+ const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high;
+
+ for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++)
+ {
+ uint32_t best_lo = 0;
+ uint32_t best_hi = 0;
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t hi = 0; hi <= 7; hi++)
+ {
+ for (uint32_t lo = 0; lo <= 7; lo++)
+ {
+ uint32_t colors[4];
+
+ colors[0] = (lo << 1);
+ colors[0] = (colors[0] << 4) | colors[0];
+
+ colors[3] = (hi << 1) | 1;
+ colors[3] = (colors[3] << 4) | colors[3];
+
+ colors[1] = (colors[0] * 5 + colors[3] * 3) / 8;
+ colors[2] = (colors[3] * 5 + colors[0] * 3) / 8;
+
+ uint64_t total_err = 0;
+
+ for (uint32_t s = low_selector; s <= high_selector; s++)
+ {
+ int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]];
+
+ int err_scale = 1;
+ // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor
+ // the low/high selectors which are clamping to either 0 or 255.
+ if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3)))
+ err_scale = 5;
+
+ total_err += (err * err) * err_scale;
+ }
+
+ if (total_err < best_err)
+ {
+ best_err = total_err;
+ best_lo = lo;
+ best_hi = hi;
+ }
+ }
+ }
+
+ //assert(best_err <= 0xFFFF);
+ best_err = basisu::minimum<uint32_t>(best_err, 0xFFFF);
+
+ fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err);
+ n++;
+ if ((n & 31) == 31)
+ fprintf(pFile, "\n");
+ } // m
+ } // sr
+ } // g
+ } // inten
+
+ fclose(pFile);
+ }
+#endif // BASISD_WRITE_NEW_ATC_TABLES
+
+#endif // BASISD_SUPPORT_ATC
+
+#if BASISD_SUPPORT_PVRTC2
+ struct pvrtc2_block
+ {
+ uint8_t m_modulation[4];
+
+ union
+ {
+ union
+ {
+ // Opaque mode: RGB colora=554 and colorb=555
+ struct
+ {
+ uint32_t m_mod_flag : 1;
+ uint32_t m_blue_a : 4;
+ uint32_t m_green_a : 5;
+ uint32_t m_red_a : 5;
+ uint32_t m_hard_flag : 1;
+ uint32_t m_blue_b : 5;
+ uint32_t m_green_b : 5;
+ uint32_t m_red_b : 5;
+ uint32_t m_opaque_flag : 1;
+
+ } m_opaque_color_data;
+
+ // Transparent mode: RGBA colora=4433 and colorb=4443
+ struct
+ {
+ uint32_t m_mod_flag : 1;
+ uint32_t m_blue_a : 3;
+ uint32_t m_green_a : 4;
+ uint32_t m_red_a : 4;
+ uint32_t m_alpha_a : 3;
+ uint32_t m_hard_flag : 1;
+ uint32_t m_blue_b : 4;
+ uint32_t m_green_b : 4;
+ uint32_t m_red_b : 4;
+ uint32_t m_alpha_b : 3;
+ uint32_t m_opaque_flag : 1;
+
+ } m_trans_color_data;
+ };
+
+ uint32_t m_color_data_bits;
+ };
+
+ // 554
+ void set_low_color(uint32_t r, uint32_t g, uint32_t b)
+ {
+ assert((r < 32) && (g < 32) && (b < 16));
+ m_opaque_color_data.m_red_a = r;
+ m_opaque_color_data.m_green_a = g;
+ m_opaque_color_data.m_blue_a = b;
+ }
+
+ // 555
+ void set_high_color(uint32_t r, uint32_t g, uint32_t b)
+ {
+ assert((r < 32) && (g < 32) && (b < 32));
+ m_opaque_color_data.m_red_b = r;
+ m_opaque_color_data.m_green_b = g;
+ m_opaque_color_data.m_blue_b = b;
+ }
+
+ // 4433
+ void set_trans_low_color(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
+ {
+ assert((r < 16) && (g < 16) && (b < 8) && (a < 8));
+ m_trans_color_data.m_red_a = r;
+ m_trans_color_data.m_green_a = g;
+ m_trans_color_data.m_blue_a = b;
+ m_trans_color_data.m_alpha_a = a;
+ }
+
+ // 4443
+ void set_trans_high_color(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
+ {
+ assert((r < 16) && (g < 16) && (b < 16) && (a < 8));
+ m_trans_color_data.m_red_b = r;
+ m_trans_color_data.m_green_b = g;
+ m_trans_color_data.m_blue_b = b;
+ m_trans_color_data.m_alpha_b = a;
+ }
+ };
+
+ static struct
+ {
+ uint8_t m_l, m_h;
+ } g_pvrtc2_trans_match34[256];
+
+ static struct
+ {
+ uint8_t m_l, m_h;
+ } g_pvrtc2_trans_match44[256];
+
+ static struct
+ {
+ uint8_t m_l, m_h;
+ } g_pvrtc2_alpha_match33[256];
+
+ static struct
+ {
+ uint8_t m_l, m_h;
+ } g_pvrtc2_alpha_match33_0[256];
+
+ static struct
+ {
+ uint8_t m_l, m_h;
+ } g_pvrtc2_alpha_match33_3[256];
+
+ // PVRTC2 can be forced to look like a slightly weaker variant of ATC/BC1, so that's what we do here for simplicity.
+ static void convert_etc1s_to_pvrtc2_rgb(void* pDst, const endpoint* pEndpoints, const selector* pSelector)
+ {
+ pvrtc2_block* pBlock = static_cast<pvrtc2_block*>(pDst);
+
+ pBlock->m_opaque_color_data.m_hard_flag = 1;
+ pBlock->m_opaque_color_data.m_mod_flag = 0;
+ pBlock->m_opaque_color_data.m_opaque_flag = 1;
+
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ const color32& base_color = pEndpoints->m_color5;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ if (low_selector == high_selector)
+ {
+ uint32_t r, g, b;
+ decoder_etc_block::get_block_color5(base_color, inten_table, low_selector, r, g, b);
+
+ pBlock->set_low_color(g_atc_match55_equals_1[r].m_lo, g_atc_match55_equals_1[g].m_lo, g_pvrtc2_match45_equals_1[b].m_lo);
+ pBlock->set_high_color(g_atc_match55_equals_1[r].m_hi, g_atc_match55_equals_1[g].m_hi, g_pvrtc2_match45_equals_1[b].m_hi);
+
+ pBlock->m_modulation[0] = 0x55;
+ pBlock->m_modulation[1] = 0x55;
+ pBlock->m_modulation[2] = 0x55;
+ pBlock->m_modulation[3] = 0x55;
+
+ return;
+ }
+ else if ((inten_table >= 7) && (pSelector->m_num_unique_selectors == 2) && (pSelector->m_lo_selector == 0) && (pSelector->m_hi_selector == 3))
+ {
+ color32 block_colors[4];
+ decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table);
+
+ const uint32_t r0 = block_colors[0].r;
+ const uint32_t g0 = block_colors[0].g;
+ const uint32_t b0 = block_colors[0].b;
+
+ const uint32_t r1 = block_colors[3].r;
+ const uint32_t g1 = block_colors[3].g;
+ const uint32_t b1 = block_colors[3].b;
+
+ pBlock->set_low_color(g_atc_match5[r0].m_hi, g_atc_match5[g0].m_hi, g_pvrtc2_match4[b0].m_hi);
+ pBlock->set_high_color(g_atc_match5[r1].m_hi, g_atc_match5[g1].m_hi, g_atc_match5[b1].m_hi);
+
+ pBlock->m_modulation[0] = pSelector->m_selectors[0];
+ pBlock->m_modulation[1] = pSelector->m_selectors[1];
+ pBlock->m_modulation[2] = pSelector->m_selectors[2];
+ pBlock->m_modulation[3] = pSelector->m_selectors[3];
+
+ return;
+ }
+
+ const uint32_t selector_range_table = g_etc1s_to_atc_selector_range_index[low_selector][high_selector];
+
+ //[32][8][RANGES][MAPPING]
+ const etc1s_to_atc_solution* pTable_r = &g_etc1s_to_atc_55[(inten_table * 32 + base_color.r) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS];
+ const etc1s_to_atc_solution* pTable_g = &g_etc1s_to_atc_55[(inten_table * 32 + base_color.g) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS];
+ const etc1s_to_atc_solution* pTable_b = &g_etc1s_to_pvrtc2_45[(inten_table * 32 + base_color.b) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS];
+
+ uint32_t best_err = UINT_MAX;
+ uint32_t best_mapping = 0;
+
+ assert(NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS == 10);
+#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } }
+ DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4);
+ DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9);
+#undef DO_ITER
+
+ pBlock->set_low_color(pTable_r[best_mapping].m_lo, pTable_g[best_mapping].m_lo, pTable_b[best_mapping].m_lo);
+ pBlock->set_high_color(pTable_r[best_mapping].m_hi, pTable_g[best_mapping].m_hi, pTable_b[best_mapping].m_hi);
+
+ if (ATC_IDENTITY_SELECTOR_MAPPING_INDEX == best_mapping)
+ {
+ pBlock->m_modulation[0] = pSelector->m_selectors[0];
+ pBlock->m_modulation[1] = pSelector->m_selectors[1];
+ pBlock->m_modulation[2] = pSelector->m_selectors[2];
+ pBlock->m_modulation[3] = pSelector->m_selectors[3];
+ }
+ else
+ {
+ // TODO: We could make this faster using several precomputed 256 entry tables, like ETC1S->BC1 does.
+ const uint8_t* pSelectors_xlat = &g_etc1s_to_atc_selector_mappings[best_mapping][0];
+
+ const uint32_t sel_bits0 = pSelector->m_selectors[0];
+ const uint32_t sel_bits1 = pSelector->m_selectors[1];
+ const uint32_t sel_bits2 = pSelector->m_selectors[2];
+ const uint32_t sel_bits3 = pSelector->m_selectors[3];
+
+ uint32_t sels0 = 0, sels1 = 0, sels2 = 0, sels3 = 0;
+
+#define DO_X(x) { \
+ const uint32_t x_shift = (x) * 2; \
+ sels0 |= (pSelectors_xlat[(sel_bits0 >> x_shift) & 3] << x_shift); \
+ sels1 |= (pSelectors_xlat[(sel_bits1 >> x_shift) & 3] << x_shift); \
+ sels2 |= (pSelectors_xlat[(sel_bits2 >> x_shift) & 3] << x_shift); \
+ sels3 |= (pSelectors_xlat[(sel_bits3 >> x_shift) & 3] << x_shift); }
+
+ DO_X(0);
+ DO_X(1);
+ DO_X(2);
+ DO_X(3);
+#undef DO_X
+
+ pBlock->m_modulation[0] = (uint8_t)sels0;
+ pBlock->m_modulation[1] = (uint8_t)sels1;
+ pBlock->m_modulation[2] = (uint8_t)sels2;
+ pBlock->m_modulation[3] = (uint8_t)sels3;
+ }
+ }
+
+ typedef struct { float c[4]; } vec4F;
+
+ static inline int32_t clampi(int32_t value, int32_t low, int32_t high) { if (value < low) value = low; else if (value > high) value = high; return value; }
+ static inline float clampf(float value, float low, float high) { if (value < low) value = low; else if (value > high) value = high; return value; }
+ static inline float saturate(float value) { return clampf(value, 0, 1.0f); }
+ static inline vec4F* vec4F_set_scalar(vec4F* pV, float x) { pV->c[0] = x; pV->c[1] = x; pV->c[2] = x; pV->c[3] = x; return pV; }
+ static inline vec4F* vec4F_set(vec4F* pV, float x, float y, float z, float w) { pV->c[0] = x; pV->c[1] = y; pV->c[2] = z; pV->c[3] = w; return pV; }
+ static inline vec4F* vec4F_saturate_in_place(vec4F* pV) { pV->c[0] = saturate(pV->c[0]); pV->c[1] = saturate(pV->c[1]); pV->c[2] = saturate(pV->c[2]); pV->c[3] = saturate(pV->c[3]); return pV; }
+ static inline vec4F vec4F_saturate(const vec4F* pV) { vec4F res; res.c[0] = saturate(pV->c[0]); res.c[1] = saturate(pV->c[1]); res.c[2] = saturate(pV->c[2]); res.c[3] = saturate(pV->c[3]); return res; }
+ static inline vec4F vec4F_from_color(const color32* pC) { vec4F res; vec4F_set(&res, pC->c[0], pC->c[1], pC->c[2], pC->c[3]); return res; }
+ static inline vec4F vec4F_add(const vec4F* pLHS, const vec4F* pRHS) { vec4F res; vec4F_set(&res, pLHS->c[0] + pRHS->c[0], pLHS->c[1] + pRHS->c[1], pLHS->c[2] + pRHS->c[2], pLHS->c[3] + pRHS->c[3]); return res; }
+ static inline vec4F vec4F_sub(const vec4F* pLHS, const vec4F* pRHS) { vec4F res; vec4F_set(&res, pLHS->c[0] - pRHS->c[0], pLHS->c[1] - pRHS->c[1], pLHS->c[2] - pRHS->c[2], pLHS->c[3] - pRHS->c[3]); return res; }
+ static inline float vec4F_dot(const vec4F* pLHS, const vec4F* pRHS) { return pLHS->c[0] * pRHS->c[0] + pLHS->c[1] * pRHS->c[1] + pLHS->c[2] * pRHS->c[2] + pLHS->c[3] * pRHS->c[3]; }
+ static inline vec4F vec4F_mul(const vec4F* pLHS, float s) { vec4F res; vec4F_set(&res, pLHS->c[0] * s, pLHS->c[1] * s, pLHS->c[2] * s, pLHS->c[3] * s); return res; }
+ static inline vec4F* vec4F_normalize_in_place(vec4F* pV) { float s = pV->c[0] * pV->c[0] + pV->c[1] * pV->c[1] + pV->c[2] * pV->c[2] + pV->c[3] * pV->c[3]; if (s != 0.0f) { s = 1.0f / sqrtf(s); pV->c[0] *= s; pV->c[1] *= s; pV->c[2] *= s; pV->c[3] *= s; } return pV; }
+
+ static color32 convert_rgba_5554_to_8888(const color32& col)
+ {
+ return color32((col[0] << 3) | (col[0] >> 2), (col[1] << 3) | (col[1] >> 2), (col[2] << 3) | (col[2] >> 2), (col[3] << 4) | col[3]);
+ }
+
+ static inline int sq(int x) { return x * x; }
+
+ // PVRTC2 is a slightly borked format for alpha: In Non-Interpolated mode, the way AlphaB8 is exanded from 4 to 8 bits means it can never be 0.
+ // This is actually very bad, because on 100% transparent blocks which have non-trivial color pixels, part of the color channel will leak into alpha!
+ // And there's nothing straightforward we can do because using the other modes is too expensive/complex. I can see why Apple didn't adopt it.
+ static void convert_etc1s_to_pvrtc2_rgba(void* pDst, const endpoint* pEndpoints, const selector* pSelector, const endpoint* pEndpoint_codebook, const selector* pSelector_codebook)
+ {
+ pvrtc2_block* pBlock = static_cast<pvrtc2_block*>(pDst);
+
+ const endpoint& alpha_endpoint = pEndpoint_codebook[((uint16_t*)pBlock)[0]];
+ const selector& alpha_selectors = pSelector_codebook[((uint16_t*)pBlock)[1]];
+
+ pBlock->m_opaque_color_data.m_hard_flag = 1;
+ pBlock->m_opaque_color_data.m_mod_flag = 0;
+ pBlock->m_opaque_color_data.m_opaque_flag = 0;
+
+ const int num_unique_alpha_selectors = alpha_selectors.m_num_unique_selectors;
+
+ const color32& alpha_base_color = alpha_endpoint.m_color5;
+ const uint32_t alpha_inten_table = alpha_endpoint.m_inten5;
+
+ int constant_alpha_val = -1;
+
+ int alpha_block_colors[4];
+ decoder_etc_block::get_block_colors5_g(alpha_block_colors, alpha_base_color, alpha_inten_table);
+
+ if (num_unique_alpha_selectors == 1)
+ {
+ constant_alpha_val = alpha_block_colors[alpha_selectors.m_lo_selector];
+ }
+ else
+ {
+ constant_alpha_val = alpha_block_colors[alpha_selectors.m_lo_selector];
+
+ for (uint32_t i = alpha_selectors.m_lo_selector + 1; i <= alpha_selectors.m_hi_selector; i++)
+ {
+ if (constant_alpha_val != alpha_block_colors[i])
+ {
+ constant_alpha_val = -1;
+ break;
+ }
+ }
+ }
+
+ if (constant_alpha_val >= 250)
+ {
+ // It's opaque enough, so don't bother trying to encode it as an alpha block.
+ convert_etc1s_to_pvrtc2_rgb(pDst, pEndpoints, pSelector);
+ return;
+ }
+
+ const color32& base_color = pEndpoints->m_color5;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ const int num_unique_color_selectors = pSelector->m_num_unique_selectors;
+
+ // We need to reencode the block at the pixel level, unfortunately, from two ETC1S planes.
+ // Do 4D incremental PCA, project all pixels to this hyperline, then quantize to packed endpoints and compute the modulation values.
+ const int br = (base_color.r << 3) | (base_color.r >> 2);
+ const int bg = (base_color.g << 3) | (base_color.g >> 2);
+ const int bb = (base_color.b << 3) | (base_color.b >> 2);
+
+ color32 block_cols[4];
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ const int ci = g_etc1_inten_tables[inten_table][i];
+ block_cols[i].set_clamped(br + ci, bg + ci, bb + ci, alpha_block_colors[i]);
+ }
+
+ bool solid_color_block = true;
+ if (num_unique_color_selectors > 1)
+ {
+ for (uint32_t i = low_selector + 1; i <= high_selector; i++)
+ {
+ if ((block_cols[low_selector].r != block_cols[i].r) || (block_cols[low_selector].g != block_cols[i].g) || (block_cols[low_selector].b != block_cols[i].b))
+ {
+ solid_color_block = false;
+ break;
+ }
+ }
+ }
+
+ if ((solid_color_block) && (constant_alpha_val >= 0))
+ {
+ // Constant color/alpha block.
+ // This is more complex than it may seem because of the way color and alpha are packed in PVRTC2. We need to evaluate mod0, mod1 and mod3 encodings to find the best one.
+ uint32_t r, g, b;
+ decoder_etc_block::get_block_color5(base_color, inten_table, low_selector, r, g, b);
+
+ // Mod 0
+ uint32_t lr0 = (r * 15 + 128) / 255, lg0 = (g * 15 + 128) / 255, lb0 = (b * 7 + 128) / 255;
+ uint32_t la0 = g_pvrtc2_alpha_match33_0[constant_alpha_val].m_l;
+
+ uint32_t cr0 = (lr0 << 1) | (lr0 >> 3);
+ uint32_t cg0 = (lg0 << 1) | (lg0 >> 3);
+ uint32_t cb0 = (lb0 << 2) | (lb0 >> 1);
+ uint32_t ca0 = (la0 << 1);
+
+ cr0 = (cr0 << 3) | (cr0 >> 2);
+ cg0 = (cg0 << 3) | (cg0 >> 2);
+ cb0 = (cb0 << 3) | (cb0 >> 2);
+ ca0 = (ca0 << 4) | ca0;
+
+ uint32_t err0 = sq(cr0 - r) + sq(cg0 - g) + sq(cb0 - b) + sq(ca0 - constant_alpha_val) * 2;
+
+ // If the alpha is < 3 or so we're kinda screwed. It's better to have some RGB error than it is to turn a 100% transparent area slightly opaque.
+ if ((err0 == 0) || (constant_alpha_val < 3))
+ {
+ pBlock->set_trans_low_color(lr0, lg0, lb0, la0);
+ pBlock->set_trans_high_color(0, 0, 0, 0);
+
+ pBlock->m_modulation[0] = 0;
+ pBlock->m_modulation[1] = 0;
+ pBlock->m_modulation[2] = 0;
+ pBlock->m_modulation[3] = 0;
+ return;
+ }
+
+ // Mod 3
+ uint32_t lr3 = (r * 15 + 128) / 255, lg3 = (g * 15 + 128) / 255, lb3 = (b * 15 + 128) / 255;
+ uint32_t la3 = g_pvrtc2_alpha_match33_3[constant_alpha_val].m_l;
+
+ uint32_t cr3 = (lr3 << 1) | (lr3 >> 3);
+ uint32_t cg3 = (lg3 << 1) | (lg3 >> 3);
+ uint32_t cb3 = (lb3 << 1) | (lb3 >> 3);
+ uint32_t ca3 = (la3 << 1) | 1;
+
+ cr3 = (cr3 << 3) | (cr3 >> 2);
+ cg3 = (cg3 << 3) | (cg3 >> 2);
+ cb3 = (cb3 << 3) | (cb3 >> 2);
+ ca3 = (ca3 << 4) | ca3;
+
+ uint32_t err3 = sq(cr3 - r) + sq(cg3 - g) + sq(cb3 - b) + sq(ca3 - constant_alpha_val) * 2;
+
+ // Mod 1
+ uint32_t lr1 = g_pvrtc2_trans_match44[r].m_l, lg1 = g_pvrtc2_trans_match44[g].m_l, lb1 = g_pvrtc2_trans_match34[b].m_l;
+ uint32_t hr1 = g_pvrtc2_trans_match44[r].m_h, hg1 = g_pvrtc2_trans_match44[g].m_h, hb1 = g_pvrtc2_trans_match34[b].m_h;
+ uint32_t la1 = g_pvrtc2_alpha_match33[constant_alpha_val].m_l, ha1 = g_pvrtc2_alpha_match33[constant_alpha_val].m_h;
+
+ uint32_t clr1 = (lr1 << 1) | (lr1 >> 3);
+ uint32_t clg1 = (lg1 << 1) | (lg1 >> 3);
+ uint32_t clb1 = (lb1 << 2) | (lb1 >> 1);
+ uint32_t cla1 = (la1 << 1);
+
+ clr1 = (clr1 << 3) | (clr1 >> 2);
+ clg1 = (clg1 << 3) | (clg1 >> 2);
+ clb1 = (clb1 << 3) | (clb1 >> 2);
+ cla1 = (cla1 << 4) | cla1;
+
+ uint32_t chr1 = (hr1 << 1) | (hr1 >> 3);
+ uint32_t chg1 = (hg1 << 1) | (hg1 >> 3);
+ uint32_t chb1 = (hb1 << 1) | (hb1 >> 3);
+ uint32_t cha1 = (ha1 << 1) | 1;
+
+ chr1 = (chr1 << 3) | (chr1 >> 2);
+ chg1 = (chg1 << 3) | (chg1 >> 2);
+ chb1 = (chb1 << 3) | (chb1 >> 2);
+ cha1 = (cha1 << 4) | cha1;
+
+ uint32_t r1 = (clr1 * 5 + chr1 * 3) / 8;
+ uint32_t g1 = (clg1 * 5 + chg1 * 3) / 8;
+ uint32_t b1 = (clb1 * 5 + chb1 * 3) / 8;
+ uint32_t a1 = (cla1 * 5 + cha1 * 3) / 8;
+
+ uint32_t err1 = sq(r1 - r) + sq(g1 - g) + sq(b1 - b) + sq(a1 - constant_alpha_val) * 2;
+
+ if ((err1 < err0) && (err1 < err3))
+ {
+ pBlock->set_trans_low_color(lr1, lg1, lb1, la1);
+ pBlock->set_trans_high_color(hr1, hg1, hb1, ha1);
+
+ pBlock->m_modulation[0] = 0x55;
+ pBlock->m_modulation[1] = 0x55;
+ pBlock->m_modulation[2] = 0x55;
+ pBlock->m_modulation[3] = 0x55;
+ }
+ else if (err0 < err3)
+ {
+ pBlock->set_trans_low_color(lr0, lg0, lb0, la0);
+ pBlock->set_trans_high_color(0, 0, 0, 0);
+
+ pBlock->m_modulation[0] = 0;
+ pBlock->m_modulation[1] = 0;
+ pBlock->m_modulation[2] = 0;
+ pBlock->m_modulation[3] = 0;
+ }
+ else
+ {
+ pBlock->set_trans_low_color(0, 0, 0, 0);
+ pBlock->set_trans_high_color(lr3, lg3, lb3, la3);
+
+ pBlock->m_modulation[0] = 0xFF;
+ pBlock->m_modulation[1] = 0xFF;
+ pBlock->m_modulation[2] = 0xFF;
+ pBlock->m_modulation[3] = 0xFF;
+ }
+
+ return;
+ }
+
+ // It's a complex block with non-solid color and/or alpha pixels.
+ vec4F minColor, maxColor;
+
+ if (solid_color_block)
+ {
+ // It's a solid color block.
+ uint32_t low_a = block_cols[alpha_selectors.m_lo_selector].a;
+ uint32_t high_a = block_cols[alpha_selectors.m_hi_selector].a;
+
+ const float S = 1.0f / 255.0f;
+ vec4F_set(&minColor, block_cols[low_selector].r * S, block_cols[low_selector].g * S, block_cols[low_selector].b * S, low_a * S);
+ vec4F_set(&maxColor, block_cols[low_selector].r * S, block_cols[low_selector].g * S, block_cols[low_selector].b * S, high_a * S);
+ }
+ else if (constant_alpha_val >= 0)
+ {
+ // It's a solid alpha block.
+ const float S = 1.0f / 255.0f;
+ vec4F_set(&minColor, block_cols[low_selector].r * S, block_cols[low_selector].g * S, block_cols[low_selector].b * S, constant_alpha_val * S);
+ vec4F_set(&maxColor, block_cols[high_selector].r * S, block_cols[high_selector].g * S, block_cols[high_selector].b * S, constant_alpha_val * S);
+ }
+ // See if any of the block colors got clamped - if so the principle axis got distorted (it's no longer just the ETC1S luma axis).
+ // To keep quality up we need to use full 4D PCA in this case.
+ else if ((block_cols[low_selector].c[0] == 0) || (block_cols[high_selector].c[0] == 255) ||
+ (block_cols[low_selector].c[1] == 0) || (block_cols[high_selector].c[1] == 255) ||
+ (block_cols[low_selector].c[2] == 0) || (block_cols[high_selector].c[2] == 255) ||
+ (block_cols[alpha_selectors.m_lo_selector].c[3] == 0) || (block_cols[alpha_selectors.m_hi_selector].c[3] == 255))
+ {
+ // Find principle component of RGBA colors treated as 4D vectors.
+ color32 pixels[16];
+
+ uint32_t sum_r = 0, sum_g = 0, sum_b = 0, sum_a = 0;
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ color32 rgb(block_cols[pSelector->get_selector(i & 3, i >> 2)]);
+ uint32_t a = block_cols[alpha_selectors.get_selector(i & 3, i >> 2)].a;
+
+ pixels[i].set(rgb.r, rgb.g, rgb.b, a);
+
+ sum_r += rgb.r;
+ sum_g += rgb.g;
+ sum_b += rgb.b;
+ sum_a += a;
+ }
+
+ vec4F meanColor;
+ vec4F_set(&meanColor, (float)sum_r, (float)sum_g, (float)sum_b, (float)sum_a);
+ vec4F meanColorScaled = vec4F_mul(&meanColor, 1.0f / 16.0f);
+
+ meanColor = vec4F_mul(&meanColor, 1.0f / (float)(16.0f * 255.0f));
+ vec4F_saturate_in_place(&meanColor);
+
+ vec4F axis;
+ vec4F_set_scalar(&axis, 0.0f);
+ // Why this incremental method? Because it's stable and predictable. Covar+power method can require a lot of iterations to converge in 4D.
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ vec4F color = vec4F_from_color(&pixels[i]);
+ color = vec4F_sub(&color, &meanColorScaled);
+ vec4F a = vec4F_mul(&color, color.c[0]);
+ vec4F b = vec4F_mul(&color, color.c[1]);
+ vec4F c = vec4F_mul(&color, color.c[2]);
+ vec4F d = vec4F_mul(&color, color.c[3]);
+ vec4F n = i ? axis : color;
+ vec4F_normalize_in_place(&n);
+ axis.c[0] += vec4F_dot(&a, &n);
+ axis.c[1] += vec4F_dot(&b, &n);
+ axis.c[2] += vec4F_dot(&c, &n);
+ axis.c[3] += vec4F_dot(&d, &n);
+ }
+
+ vec4F_normalize_in_place(&axis);
+
+ if (vec4F_dot(&axis, &axis) < .5f)
+ vec4F_set_scalar(&axis, .5f);
+
+ float l = 1e+9f, h = -1e+9f;
+
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ vec4F color = vec4F_from_color(&pixels[i]);
+
+ vec4F q = vec4F_sub(&color, &meanColorScaled);
+ float d = vec4F_dot(&q, &axis);
+
+ l = basisu::minimum(l, d);
+ h = basisu::maximum(h, d);
+ }
+
+ l *= (1.0f / 255.0f);
+ h *= (1.0f / 255.0f);
+
+ vec4F b0 = vec4F_mul(&axis, l);
+ vec4F b1 = vec4F_mul(&axis, h);
+ vec4F c0 = vec4F_add(&meanColor, &b0);
+ vec4F c1 = vec4F_add(&meanColor, &b1);
+ minColor = vec4F_saturate(&c0);
+ maxColor = vec4F_saturate(&c1);
+ if (minColor.c[3] > maxColor.c[3])
+ std::swap(minColor, maxColor);
+ }
+ else
+ {
+ // We know the RGB axis is luma, because it's an ETC1S block and none of the block colors got clamped. So we only need to use 2D PCA.
+ // We project each LA vector onto two 2D lines with axes (1,1) and (1,-1) and find the largest projection to determine if axis A is flipped relative to L.
+ uint32_t block_cols_l[4], block_cols_a[4];
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ block_cols_l[i] = block_cols[i].r + block_cols[i].g + block_cols[i].b;
+ block_cols_a[i] = block_cols[i].a * 3;
+ }
+
+ int p0_min = INT_MAX, p0_max = INT_MIN;
+ int p1_min = INT_MAX, p1_max = INT_MIN;
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ const uint32_t cs = pSelector->m_selectors[y];
+ const uint32_t as = alpha_selectors.m_selectors[y];
+
+ {
+ const int l = block_cols_l[cs & 3];
+ const int a = block_cols_a[as & 3];
+ const int p0 = l + a; p0_min = basisu::minimum(p0_min, p0); p0_max = basisu::maximum(p0_max, p0);
+ const int p1 = l - a; p1_min = basisu::minimum(p1_min, p1); p1_max = basisu::maximum(p1_max, p1);
+ }
+ {
+ const int l = block_cols_l[(cs >> 2) & 3];
+ const int a = block_cols_a[(as >> 2) & 3];
+ const int p0 = l + a; p0_min = basisu::minimum(p0_min, p0); p0_max = basisu::maximum(p0_max, p0);
+ const int p1 = l - a; p1_min = basisu::minimum(p1_min, p1); p1_max = basisu::maximum(p1_max, p1);
+ }
+ {
+ const int l = block_cols_l[(cs >> 4) & 3];
+ const int a = block_cols_a[(as >> 4) & 3];
+ const int p0 = l + a; p0_min = basisu::minimum(p0_min, p0); p0_max = basisu::maximum(p0_max, p0);
+ const int p1 = l - a; p1_min = basisu::minimum(p1_min, p1); p1_max = basisu::maximum(p1_max, p1);
+ }
+ {
+ const int l = block_cols_l[cs >> 6];
+ const int a = block_cols_a[as >> 6];
+ const int p0 = l + a; p0_min = basisu::minimum(p0_min, p0); p0_max = basisu::maximum(p0_max, p0);
+ const int p1 = l - a; p1_min = basisu::minimum(p1_min, p1); p1_max = basisu::maximum(p1_max, p1);
+ }
+ }
+
+ int dist0 = p0_max - p0_min;
+ int dist1 = p1_max - p1_min;
+
+ const float S = 1.0f / 255.0f;
+
+ vec4F_set(&minColor, block_cols[low_selector].r * S, block_cols[low_selector].g * S, block_cols[low_selector].b * S, block_cols[alpha_selectors.m_lo_selector].a * S);
+ vec4F_set(&maxColor, block_cols[high_selector].r * S, block_cols[high_selector].g * S, block_cols[high_selector].b * S, block_cols[alpha_selectors.m_hi_selector].a * S);
+
+ // See if the A component of the principle axis is flipped relative to L. If so, we need to flip either RGB or A bounds.
+ if (dist1 > dist0)
+ {
+ std::swap(minColor.c[0], maxColor.c[0]);
+ std::swap(minColor.c[1], maxColor.c[1]);
+ std::swap(minColor.c[2], maxColor.c[2]);
+ }
+ }
+
+ // 4433 4443
+ color32 trialMinColor, trialMaxColor;
+
+ trialMinColor.set_clamped((int)(minColor.c[0] * 15.0f + .5f), (int)(minColor.c[1] * 15.0f + .5f), (int)(minColor.c[2] * 7.0f + .5f), (int)(minColor.c[3] * 7.0f + .5f));
+ trialMaxColor.set_clamped((int)(maxColor.c[0] * 15.0f + .5f), (int)(maxColor.c[1] * 15.0f + .5f), (int)(maxColor.c[2] * 15.0f + .5f), (int)(maxColor.c[3] * 7.0f + .5f));
+
+ pBlock->set_trans_low_color(trialMinColor.r, trialMinColor.g, trialMinColor.b, trialMinColor.a);
+ pBlock->set_trans_high_color(trialMaxColor.r, trialMaxColor.g, trialMaxColor.b, trialMaxColor.a);
+
+ color32 color_a((trialMinColor.r << 1) | (trialMinColor.r >> 3), (trialMinColor.g << 1) | (trialMinColor.g >> 3), (trialMinColor.b << 2) | (trialMinColor.b >> 1), trialMinColor.a << 1);
+ color32 color_b((trialMaxColor.r << 1) | (trialMaxColor.r >> 3), (trialMaxColor.g << 1) | (trialMaxColor.g >> 3), (trialMaxColor.b << 1) | (trialMaxColor.b >> 3), (trialMaxColor.a << 1) | 1);
+
+ color32 color0(convert_rgba_5554_to_8888(color_a));
+ color32 color3(convert_rgba_5554_to_8888(color_b));
+
+ const int lr = color0.r;
+ const int lg = color0.g;
+ const int lb = color0.b;
+ const int la = color0.a;
+
+ const int axis_r = color3.r - lr;
+ const int axis_g = color3.g - lg;
+ const int axis_b = color3.b - lb;
+ const int axis_a = color3.a - la;
+ const int len_a = (axis_r * axis_r) + (axis_g * axis_g) + (axis_b * axis_b) + (axis_a * axis_a);
+
+ const int thresh01 = (len_a * 3) / 16;
+ const int thresh12 = len_a >> 1;
+ const int thresh23 = (len_a * 13) / 16;
+
+ if ((axis_r | axis_g | axis_b) == 0)
+ {
+ int ca_sel[4];
+
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ int ca = (block_cols[i].a - la) * axis_a;
+ ca_sel[i] = (ca >= thresh23) + (ca >= thresh12) + (ca >= thresh01);
+ }
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ const uint32_t a_sels = alpha_selectors.m_selectors[y];
+
+ uint32_t sel = ca_sel[a_sels & 3] | (ca_sel[(a_sels >> 2) & 3] << 2) | (ca_sel[(a_sels >> 4) & 3] << 4) | (ca_sel[a_sels >> 6] << 6);
+
+ pBlock->m_modulation[y] = (uint8_t)sel;
+ }
+ }
+ else
+ {
+ int cy[4], ca[4];
+
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ cy[i] = (block_cols[i].r - lr) * axis_r + (block_cols[i].g - lg) * axis_g + (block_cols[i].b - lb) * axis_b;
+ ca[i] = (block_cols[i].a - la) * axis_a;
+ }
+
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ const uint32_t c_sels = pSelector->m_selectors[y];
+ const uint32_t a_sels = alpha_selectors.m_selectors[y];
+
+ const int d0 = cy[c_sels & 3] + ca[a_sels & 3];
+ const int d1 = cy[(c_sels >> 2) & 3] + ca[(a_sels >> 2) & 3];
+ const int d2 = cy[(c_sels >> 4) & 3] + ca[(a_sels >> 4) & 3];
+ const int d3 = cy[c_sels >> 6] + ca[a_sels >> 6];
+
+ uint32_t sel = ((d0 >= thresh23) + (d0 >= thresh12) + (d0 >= thresh01)) |
+ (((d1 >= thresh23) + (d1 >= thresh12) + (d1 >= thresh01)) << 2) |
+ (((d2 >= thresh23) + (d2 >= thresh12) + (d2 >= thresh01)) << 4) |
+ (((d3 >= thresh23) + (d3 >= thresh12) + (d3 >= thresh01)) << 6);
+
+ pBlock->m_modulation[y] = (uint8_t)sel;
+ }
+ }
+ }
+
+ static void transcoder_init_pvrtc2()
+ {
+ for (uint32_t v = 0; v < 256; v++)
+ {
+ int best_l = 0, best_h = 0, lowest_err = INT_MAX;
+
+ for (uint32_t l = 0; l < 8; l++)
+ {
+ uint32_t le = (l << 1);
+ le = (le << 4) | le;
+
+ for (uint32_t h = 0; h < 8; h++)
+ {
+ uint32_t he = (h << 1) | 1;
+ he = (he << 4) | he;
+
+ uint32_t m = (le * 5 + he * 3) / 8;
+
+ int err = labs((int)v - (int)m);
+ if (err < lowest_err)
+ {
+ lowest_err = err;
+ best_l = l;
+ best_h = h;
+ }
+ }
+ }
+
+ g_pvrtc2_alpha_match33[v].m_l = (uint8_t)best_l;
+ g_pvrtc2_alpha_match33[v].m_h = (uint8_t)best_h;
+ }
+
+ for (uint32_t v = 0; v < 256; v++)
+ {
+ int best_l = 0, best_h = 0, lowest_err = INT_MAX;
+
+ for (uint32_t l = 0; l < 8; l++)
+ {
+ uint32_t le = (l << 1);
+ le = (le << 4) | le;
+
+ int err = labs((int)v - (int)le);
+ if (err < lowest_err)
+ {
+ lowest_err = err;
+ best_l = l;
+ best_h = l;
+ }
+ }
+
+ g_pvrtc2_alpha_match33_0[v].m_l = (uint8_t)best_l;
+ g_pvrtc2_alpha_match33_0[v].m_h = (uint8_t)best_h;
+ }
+
+ for (uint32_t v = 0; v < 256; v++)
+ {
+ int best_l = 0, best_h = 0, lowest_err = INT_MAX;
+
+ for (uint32_t h = 0; h < 8; h++)
+ {
+ uint32_t he = (h << 1) | 1;
+ he = (he << 4) | he;
+
+ int err = labs((int)v - (int)he);
+ if (err < lowest_err)
+ {
+ lowest_err = err;
+ best_l = h;
+ best_h = h;
+ }
+ }
+
+ g_pvrtc2_alpha_match33_3[v].m_l = (uint8_t)best_l;
+ g_pvrtc2_alpha_match33_3[v].m_h = (uint8_t)best_h;
+ }
+
+ for (uint32_t v = 0; v < 256; v++)
+ {
+ int best_l = 0, best_h = 0, lowest_err = INT_MAX;
+
+ for (uint32_t l = 0; l < 8; l++)
+ {
+ uint32_t le = (l << 2) | (l >> 1);
+ le = (le << 3) | (le >> 2);
+
+ for (uint32_t h = 0; h < 16; h++)
+ {
+ uint32_t he = (h << 1) | (h >> 3);
+ he = (he << 3) | (he >> 2);
+
+ uint32_t m = (le * 5 + he * 3) / 8;
+
+ int err = labs((int)v - (int)m);
+ if (err < lowest_err)
+ {
+ lowest_err = err;
+ best_l = l;
+ best_h = h;
+ }
+ }
+ }
+
+ g_pvrtc2_trans_match34[v].m_l = (uint8_t)best_l;
+ g_pvrtc2_trans_match34[v].m_h = (uint8_t)best_h;
+ }
+
+ for (uint32_t v = 0; v < 256; v++)
+ {
+ int best_l = 0, best_h = 0, lowest_err = INT_MAX;
+
+ for (uint32_t l = 0; l < 16; l++)
+ {
+ uint32_t le = (l << 1) | (l >> 3);
+ le = (le << 3) | (le >> 2);
+
+ for (uint32_t h = 0; h < 16; h++)
+ {
+ uint32_t he = (h << 1) | (h >> 3);
+ he = (he << 3) | (he >> 2);
+
+ uint32_t m = (le * 5 + he * 3) / 8;
+
+ int err = labs((int)v - (int)m);
+ if (err < lowest_err)
+ {
+ lowest_err = err;
+ best_l = l;
+ best_h = h;
+ }
+ }
+ }
+
+ g_pvrtc2_trans_match44[v].m_l = (uint8_t)best_l;
+ g_pvrtc2_trans_match44[v].m_h = (uint8_t)best_h;
+ }
+ }
+#endif // BASISD_SUPPORT_PVRTC2
+
+ basisu_lowlevel_transcoder::basisu_lowlevel_transcoder(const etc1_global_selector_codebook* pGlobal_sel_codebook) :
+ m_pGlobal_sel_codebook(pGlobal_sel_codebook),
+ m_selector_history_buf_size(0)
+ {
+ }
+
+ bool basisu_lowlevel_transcoder::decode_palettes(
+ uint32_t num_endpoints, const uint8_t* pEndpoints_data, uint32_t endpoints_data_size,
+ uint32_t num_selectors, const uint8_t* pSelectors_data, uint32_t selectors_data_size)
+ {
+ bitwise_decoder sym_codec;
+
+ huffman_decoding_table color5_delta_model0, color5_delta_model1, color5_delta_model2, inten_delta_model;
+
+ if (!sym_codec.init(pEndpoints_data, endpoints_data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 0\n");
+ return false;
+ }
+
+ if (!sym_codec.read_huffman_table(color5_delta_model0))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 1\n");
+ return false;
+ }
+
+ if (!sym_codec.read_huffman_table(color5_delta_model1))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 1a\n");
+ return false;
+ }
+
+ if (!sym_codec.read_huffman_table(color5_delta_model2))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 2a\n");
+ return false;
+ }
+
+ if (!sym_codec.read_huffman_table(inten_delta_model))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 2b\n");
+ return false;
+ }
+
+ if (!color5_delta_model0.is_valid() || !color5_delta_model1.is_valid() || !color5_delta_model2.is_valid() || !inten_delta_model.is_valid())
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 2b\n");
+ return false;
+ }
+
+ const bool endpoints_are_grayscale = sym_codec.get_bits(1) != 0;
+
+ m_endpoints.resize(num_endpoints);
+
+ color32 prev_color5(16, 16, 16, 0);
+ uint32_t prev_inten = 0;
+
+ for (uint32_t i = 0; i < num_endpoints; i++)
+ {
+ uint32_t inten_delta = sym_codec.decode_huffman(inten_delta_model);
+ m_endpoints[i].m_inten5 = static_cast<uint8_t>((inten_delta + prev_inten) & 7);
+ prev_inten = m_endpoints[i].m_inten5;
+
+ for (uint32_t c = 0; c < (endpoints_are_grayscale ? 1U : 3U); c++)
+ {
+ int delta;
+ if (prev_color5[c] <= basist::COLOR5_PAL0_PREV_HI)
+ delta = sym_codec.decode_huffman(color5_delta_model0);
+ else if (prev_color5[c] <= basist::COLOR5_PAL1_PREV_HI)
+ delta = sym_codec.decode_huffman(color5_delta_model1);
+ else
+ delta = sym_codec.decode_huffman(color5_delta_model2);
+
+ int v = (prev_color5[c] + delta) & 31;
+
+ m_endpoints[i].m_color5[c] = static_cast<uint8_t>(v);
+
+ prev_color5[c] = static_cast<uint8_t>(v);
+ }
+
+ if (endpoints_are_grayscale)
+ {
+ m_endpoints[i].m_color5[1] = m_endpoints[i].m_color5[0];
+ m_endpoints[i].m_color5[2] = m_endpoints[i].m_color5[0];
+ }
+ }
+
+ sym_codec.stop();
+
+ m_selectors.resize(num_selectors);
+
+ if (!sym_codec.init(pSelectors_data, selectors_data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 5\n");
+ return false;
+ }
+
+ basist::huffman_decoding_table delta_selector_pal_model;
+
+ const bool used_global_selector_cb = (sym_codec.get_bits(1) == 1);
+
+ if (used_global_selector_cb)
+ {
+ // global selector palette
+ uint32_t pal_bits = sym_codec.get_bits(4);
+ uint32_t mod_bits = sym_codec.get_bits(4);
+
+ basist::huffman_decoding_table mod_model;
+ if (mod_bits)
+ {
+ if (!sym_codec.read_huffman_table(mod_model))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 6\n");
+ return false;
+ }
+ if (!mod_model.is_valid())
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 6a\n");
+ return false;
+ }
+ }
+
+ for (uint32_t i = 0; i < num_selectors; i++)
+ {
+ uint32_t pal_index = 0;
+ if (pal_bits)
+ pal_index = sym_codec.get_bits(pal_bits);
+
+ uint32_t mod_index = 0;
+ if (mod_bits)
+ mod_index = sym_codec.decode_huffman(mod_model);
+
+ if (pal_index >= m_pGlobal_sel_codebook->size())
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 7z\n");
+ return false;
+ }
+
+ const etc1_selector_palette_entry e(m_pGlobal_sel_codebook->get_entry(pal_index, etc1_global_palette_entry_modifier(mod_index)));
+
+ // TODO: Optimize this
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ m_selectors[i].set_selector(x, y, e[x + y * 4]);
+
+ m_selectors[i].init_flags();
+ }
+ }
+ else
+ {
+ const bool used_hybrid_selector_cb = (sym_codec.get_bits(1) == 1);
+
+ if (used_hybrid_selector_cb)
+ {
+ const uint32_t pal_bits = sym_codec.get_bits(4);
+ const uint32_t mod_bits = sym_codec.get_bits(4);
+
+ basist::huffman_decoding_table uses_global_cb_bitflags_model;
+ if (!sym_codec.read_huffman_table(uses_global_cb_bitflags_model))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 7\n");
+ return false;
+ }
+ if (!uses_global_cb_bitflags_model.is_valid())
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 7a\n");
+ return false;
+ }
+
+ basist::huffman_decoding_table global_mod_indices_model;
+ if (mod_bits)
+ {
+ if (!sym_codec.read_huffman_table(global_mod_indices_model))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 8\n");
+ return false;
+ }
+ if (!global_mod_indices_model.is_valid())
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 8a\n");
+ return false;
+ }
+ }
+
+ uint32_t cur_uses_global_cb_bitflags = 0;
+ uint32_t uses_global_cb_bitflags_remaining = 0;
+
+ for (uint32_t q = 0; q < num_selectors; q++)
+ {
+ if (!uses_global_cb_bitflags_remaining)
+ {
+ cur_uses_global_cb_bitflags = sym_codec.decode_huffman(uses_global_cb_bitflags_model);
+
+ uses_global_cb_bitflags_remaining = 8;
+ }
+ uses_global_cb_bitflags_remaining--;
+
+ const bool used_global_cb_flag = (cur_uses_global_cb_bitflags & 1) != 0;
+ cur_uses_global_cb_bitflags >>= 1;
+
+ if (used_global_cb_flag)
+ {
+ const uint32_t pal_index = pal_bits ? sym_codec.get_bits(pal_bits) : 0;
+ const uint32_t mod_index = mod_bits ? sym_codec.decode_huffman(global_mod_indices_model) : 0;
+
+ if (pal_index >= m_pGlobal_sel_codebook->size())
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 8b\n");
+ return false;
+ }
+
+ const etc1_selector_palette_entry e(m_pGlobal_sel_codebook->get_entry(pal_index, etc1_global_palette_entry_modifier(mod_index)));
+
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ m_selectors[q].set_selector(x, y, e[x + y * 4]);
+ }
+ else
+ {
+ for (uint32_t j = 0; j < 4; j++)
+ {
+ uint32_t cur_byte = sym_codec.get_bits(8);
+
+ for (uint32_t k = 0; k < 4; k++)
+ m_selectors[q].set_selector(k, j, (cur_byte >> (k * 2)) & 3);
+ }
+ }
+
+ m_selectors[q].init_flags();
+ }
+ }
+ else
+ {
+ const bool used_raw_encoding = (sym_codec.get_bits(1) == 1);
+
+ if (used_raw_encoding)
+ {
+ for (uint32_t i = 0; i < num_selectors; i++)
+ {
+ for (uint32_t j = 0; j < 4; j++)
+ {
+ uint32_t cur_byte = sym_codec.get_bits(8);
+
+ for (uint32_t k = 0; k < 4; k++)
+ m_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3);
+ }
+
+ m_selectors[i].init_flags();
+ }
+ }
+ else
+ {
+ if (!sym_codec.read_huffman_table(delta_selector_pal_model))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 10\n");
+ return false;
+ }
+
+ if ((num_selectors > 1) && (!delta_selector_pal_model.is_valid()))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 10a\n");
+ return false;
+ }
+
+ uint8_t prev_bytes[4] = { 0, 0, 0, 0 };
+
+ for (uint32_t i = 0; i < num_selectors; i++)
+ {
+ if (!i)
+ {
+ for (uint32_t j = 0; j < 4; j++)
+ {
+ uint32_t cur_byte = sym_codec.get_bits(8);
+ prev_bytes[j] = static_cast<uint8_t>(cur_byte);
+
+ for (uint32_t k = 0; k < 4; k++)
+ m_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3);
+ }
+ m_selectors[i].init_flags();
+ continue;
+ }
+
+ for (uint32_t j = 0; j < 4; j++)
+ {
+ int delta_byte = sym_codec.decode_huffman(delta_selector_pal_model);
+
+ uint32_t cur_byte = delta_byte ^ prev_bytes[j];
+ prev_bytes[j] = static_cast<uint8_t>(cur_byte);
+
+ for (uint32_t k = 0; k < 4; k++)
+ m_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3);
+ }
+ m_selectors[i].init_flags();
+ }
+ }
+ }
+ }
+
+ sym_codec.stop();
+
+ return true;
+ }
+
+ bool basisu_lowlevel_transcoder::decode_tables(const uint8_t* pTable_data, uint32_t table_data_size)
+ {
+ basist::bitwise_decoder sym_codec;
+ if (!sym_codec.init(pTable_data, table_data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 0\n");
+ return false;
+ }
+
+ if (!sym_codec.read_huffman_table(m_endpoint_pred_model))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 1\n");
+ return false;
+ }
+
+ if (m_endpoint_pred_model.get_code_sizes().size() == 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 1a\n");
+ return false;
+ }
+
+ if (!sym_codec.read_huffman_table(m_delta_endpoint_model))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 2\n");
+ return false;
+ }
+
+ if (m_delta_endpoint_model.get_code_sizes().size() == 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 2a\n");
+ return false;
+ }
+
+ if (!sym_codec.read_huffman_table(m_selector_model))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 3\n");
+ return false;
+ }
+
+ if (m_selector_model.get_code_sizes().size() == 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 3a\n");
+ return false;
+ }
+
+ if (!sym_codec.read_huffman_table(m_selector_history_buf_rle_model))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 4\n");
+ return false;
+ }
+
+ if (m_selector_history_buf_rle_model.get_code_sizes().size() == 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 4a\n");
+ return false;
+ }
+
+ m_selector_history_buf_size = sym_codec.get_bits(13);
+
+ sym_codec.stop();
+
+ return true;
+ }
+
+ bool basisu_lowlevel_transcoder::transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt,
+ uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const basis_file_header& header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels,
+ basisu_transcoder_state* pState, bool transcode_alpha, void *pAlpha_blocks, uint32_t output_rows_in_pixels)
+ {
+ (void)transcode_alpha;
+ (void)pAlpha_blocks;
+
+ if (!pState)
+ pState = &m_def_state;
+
+ const bool is_video = (header.m_tex_type == cBASISTexTypeVideoFrames);
+ const uint32_t total_blocks = num_blocks_x * num_blocks_y;
+
+ if (!output_row_pitch_in_blocks_or_pixels)
+ {
+ if (basis_block_format_is_uncompressed(fmt))
+ output_row_pitch_in_blocks_or_pixels = slice_desc.m_orig_width;
+ else
+ {
+ if (fmt == block_format::cFXT1_RGB)
+ output_row_pitch_in_blocks_or_pixels = (slice_desc.m_orig_width + 7) / 8;
+ else
+ output_row_pitch_in_blocks_or_pixels = num_blocks_x;
+ }
+ }
+
+ if (basis_block_format_is_uncompressed(fmt))
+ {
+ if (!output_rows_in_pixels)
+ output_rows_in_pixels = slice_desc.m_orig_height;
+ }
+
+ std::vector<uint32_t>* pPrev_frame_indices = nullptr;
+ if (is_video)
+ {
+ // TODO: Add check to make sure the caller hasn't tried skipping past p-frames
+ const bool alpha_flag = (slice_desc.m_flags & cSliceDescFlagsIsAlphaData) != 0;
+ const uint32_t level_index = slice_desc.m_level_index;
+
+ if (level_index >= basisu_transcoder_state::cMaxPrevFrameLevels)
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: unsupported level_index\n");
+ return false;
+ }
+
+ pPrev_frame_indices = &pState->m_prev_frame_indices[alpha_flag][level_index];
+ if (pPrev_frame_indices->size() < total_blocks)
+ pPrev_frame_indices->resize(total_blocks);
+ }
+
+ basist::bitwise_decoder sym_codec;
+
+ if (!sym_codec.init(pImage_data, image_data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: sym_codec.init failed\n");
+ return false;
+ }
+
+ approx_move_to_front selector_history_buf(m_selector_history_buf_size);
+
+ const uint32_t SELECTOR_HISTORY_BUF_FIRST_SYMBOL_INDEX = (uint32_t)m_selectors.size();
+ const uint32_t SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX = m_selector_history_buf_size + SELECTOR_HISTORY_BUF_FIRST_SYMBOL_INDEX;
+ uint32_t cur_selector_rle_count = 0;
+
+ decoder_etc_block block;
+ memset(&block, 0, sizeof(block));
+
+ block.set_flip_bit(true);
+ block.set_diff_bit(true);
+
+ void* pPVRTC_work_mem = nullptr;
+ uint32_t* pPVRTC_endpoints = nullptr;
+ if ((fmt == block_format::cPVRTC1_4_RGB) || (fmt == block_format::cPVRTC1_4_RGBA))
+ {
+ pPVRTC_work_mem = malloc(num_blocks_x * num_blocks_y * (sizeof(decoder_etc_block) + sizeof(uint32_t)));
+ if (!pPVRTC_work_mem)
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: malloc failed\n");
+ return false;
+ }
+ pPVRTC_endpoints = (uint32_t*) & ((decoder_etc_block*)pPVRTC_work_mem)[num_blocks_x * num_blocks_y];
+ }
+
+ if (pState->m_block_endpoint_preds[0].size() < num_blocks_x)
+ {
+ pState->m_block_endpoint_preds[0].resize(num_blocks_x);
+ pState->m_block_endpoint_preds[1].resize(num_blocks_x);
+ }
+
+ uint32_t cur_pred_bits = 0;
+ int prev_endpoint_pred_sym = 0;
+ int endpoint_pred_repeat_count = 0;
+ uint32_t prev_endpoint_index = 0;
+
+ for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
+ {
+ const uint32_t cur_block_endpoint_pred_array = block_y & 1;
+
+ for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
+ {
+ // Decode endpoint index predictor symbols
+ if ((block_x & 1) == 0)
+ {
+ if ((block_y & 1) == 0)
+ {
+ if (endpoint_pred_repeat_count)
+ {
+ endpoint_pred_repeat_count--;
+ cur_pred_bits = prev_endpoint_pred_sym;
+ }
+ else
+ {
+ cur_pred_bits = sym_codec.decode_huffman(m_endpoint_pred_model);
+ if (cur_pred_bits == ENDPOINT_PRED_REPEAT_LAST_SYMBOL)
+ {
+ endpoint_pred_repeat_count = sym_codec.decode_vlc(ENDPOINT_PRED_COUNT_VLC_BITS) + ENDPOINT_PRED_MIN_REPEAT_COUNT - 1;
+
+ cur_pred_bits = prev_endpoint_pred_sym;
+ }
+ else
+ {
+ prev_endpoint_pred_sym = cur_pred_bits;
+ }
+ }
+
+ pState->m_block_endpoint_preds[cur_block_endpoint_pred_array ^ 1][block_x].m_pred_bits = (uint8_t)(cur_pred_bits >> 4);
+ }
+ else
+ {
+ cur_pred_bits = pState->m_block_endpoint_preds[cur_block_endpoint_pred_array][block_x].m_pred_bits;
+ }
+ }
+
+ // Decode endpoint index
+ uint32_t endpoint_index, selector_index = 0;
+
+ const uint32_t pred = cur_pred_bits & 3;
+ cur_pred_bits >>= 2;
+
+ if (pred == 0)
+ {
+ // Left
+ if (!block_x)
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: invalid datastream (0)\n");
+ if (pPVRTC_work_mem)
+ free(pPVRTC_work_mem);
+ return false;
+ }
+
+ endpoint_index = prev_endpoint_index;
+ }
+ else if (pred == 1)
+ {
+ // Upper
+ if (!block_y)
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: invalid datastream (1)\n");
+ if (pPVRTC_work_mem)
+ free(pPVRTC_work_mem);
+ return false;
+ }
+
+ endpoint_index = pState->m_block_endpoint_preds[cur_block_endpoint_pred_array ^ 1][block_x].m_endpoint_index;
+ }
+ else if (pred == 2)
+ {
+ if (is_video)
+ {
+ assert(pred == CR_ENDPOINT_PRED_INDEX);
+ endpoint_index = (*pPrev_frame_indices)[block_x + block_y * num_blocks_x];
+ selector_index = endpoint_index >> 16;
+ endpoint_index &= 0xFFFFU;
+ }
+ else
+ {
+ // Upper left
+ if ((!block_x) || (!block_y))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: invalid datastream (2)\n");
+ if (pPVRTC_work_mem)
+ free(pPVRTC_work_mem);
+ return false;
+ }
+
+ endpoint_index = pState->m_block_endpoint_preds[cur_block_endpoint_pred_array ^ 1][block_x - 1].m_endpoint_index;
+ }
+ }
+ else
+ {
+ // Decode and apply delta
+ const uint32_t delta_sym = sym_codec.decode_huffman(m_delta_endpoint_model);
+
+ endpoint_index = delta_sym + prev_endpoint_index;
+ if (endpoint_index >= m_endpoints.size())
+ endpoint_index -= (int)m_endpoints.size();
+ }
+
+ pState->m_block_endpoint_preds[cur_block_endpoint_pred_array][block_x].m_endpoint_index = (uint16_t)endpoint_index;
+
+ prev_endpoint_index = endpoint_index;
+
+ // Decode selector index
+ if ((!is_video) || (pred != CR_ENDPOINT_PRED_INDEX))
+ {
+ int selector_sym;
+ if (cur_selector_rle_count > 0)
+ {
+ cur_selector_rle_count--;
+
+ selector_sym = (int)m_selectors.size();
+ }
+ else
+ {
+ selector_sym = sym_codec.decode_huffman(m_selector_model);
+
+ if (selector_sym == static_cast<int>(SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX))
+ {
+ int run_sym = sym_codec.decode_huffman(m_selector_history_buf_rle_model);
+
+ if (run_sym == (SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL - 1))
+ cur_selector_rle_count = sym_codec.decode_vlc(7) + SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH;
+ else
+ cur_selector_rle_count = run_sym + SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH;
+
+ if (cur_selector_rle_count > total_blocks)
+ {
+ // The file is corrupted or we've got a bug.
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: invalid datastream (3)\n");
+ if (pPVRTC_work_mem)
+ free(pPVRTC_work_mem);
+ return false;
+ }
+
+ selector_sym = (int)m_selectors.size();
+
+ cur_selector_rle_count--;
+ }
+ }
+
+ if (selector_sym >= (int)m_selectors.size())
+ {
+ assert(m_selector_history_buf_size > 0);
+
+ int history_buf_index = selector_sym - (int)m_selectors.size();
+
+ if (history_buf_index >= (int)selector_history_buf.size())
+ {
+ // The file is corrupted or we've got a bug.
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: invalid datastream (4)\n");
+ if (pPVRTC_work_mem)
+ free(pPVRTC_work_mem);
+ return false;
+ }
+
+ selector_index = selector_history_buf[history_buf_index];
+
+ if (history_buf_index != 0)
+ selector_history_buf.use(history_buf_index);
+ }
+ else
+ {
+ selector_index = selector_sym;
+
+ if (m_selector_history_buf_size)
+ selector_history_buf.add(selector_index);
+ }
+ }
+
+ if ((endpoint_index >= m_endpoints.size()) || (selector_index >= m_selectors.size()))
+ {
+ // The file is corrupted or we've got a bug.
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: invalid datastream (5)\n");
+ if (pPVRTC_work_mem)
+ free(pPVRTC_work_mem);
+ return false;
+ }
+
+ if (is_video)
+ (*pPrev_frame_indices)[block_x + block_y * num_blocks_x] = endpoint_index | (selector_index << 16);
+
+#if BASISD_ENABLE_DEBUG_FLAGS
+ if ((g_debug_flags & cDebugFlagVisCRs) && ((fmt == block_format::cETC1) || (fmt == block_format::cBC1)))
+ {
+ if ((is_video) && (pred == 2))
+ {
+ decoder_etc_block* pDst_block = reinterpret_cast<decoder_etc_block*>(static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes);
+ memset(pDst_block, 0xFF, 8);
+ continue;
+ }
+ }
+#endif
+
+ const endpoint* pEndpoints = &m_endpoints[endpoint_index];
+ const selector* pSelector = &m_selectors[selector_index];
+
+ switch (fmt)
+ {
+ case block_format::cETC1:
+ {
+ decoder_etc_block* pDst_block = reinterpret_cast<decoder_etc_block*>(static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes);
+
+ block.set_base5_color(decoder_etc_block::pack_color5(pEndpoints->m_color5, false));
+ block.set_inten_table(0, pEndpoints->m_inten5);
+ block.set_inten_table(1, pEndpoints->m_inten5);
+
+ pDst_block->m_uint32[0] = block.m_uint32[0];
+ pDst_block->set_raw_selector_bits(pSelector->m_bytes[0], pSelector->m_bytes[1], pSelector->m_bytes[2], pSelector->m_bytes[3]);
+
+ break;
+ }
+ case block_format::cBC1:
+ {
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+
+#if BASISD_SUPPORT_DXT1
+#if BASISD_ENABLE_DEBUG_FLAGS
+ if (g_debug_flags & (cDebugFlagVisBC1Sels | cDebugFlagVisBC1Endpoints))
+ convert_etc1s_to_dxt1_vis(static_cast<dxt1_block*>(pDst_block), pEndpoints, pSelector, bc1_allow_threecolor_blocks);
+ else
+#endif
+ convert_etc1s_to_dxt1(static_cast<dxt1_block*>(pDst_block), pEndpoints, pSelector, bc1_allow_threecolor_blocks);
+#else
+ assert(0);
+#endif
+ break;
+ }
+ case block_format::cBC4:
+ {
+#if BASISD_SUPPORT_DXT5A
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+ convert_etc1s_to_dxt5a(static_cast<dxt5a_block*>(pDst_block), pEndpoints, pSelector);
+#else
+ assert(0);
+#endif
+ break;
+ }
+ case block_format::cPVRTC1_4_RGB:
+ {
+#if BASISD_SUPPORT_PVRTC1
+ block.set_base5_color(decoder_etc_block::pack_color5(pEndpoints->m_color5, false));
+ block.set_inten_table(0, pEndpoints->m_inten5);
+ block.set_inten_table(1, pEndpoints->m_inten5);
+ block.set_raw_selector_bits(pSelector->m_bytes[0], pSelector->m_bytes[1], pSelector->m_bytes[2], pSelector->m_bytes[3]);
+
+ ((decoder_etc_block*)pPVRTC_work_mem)[block_x + block_y * num_blocks_x] = block;
+
+ const color32& base_color = pEndpoints->m_color5;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+
+ // Get block's RGB bounding box
+ color32 block_colors[2];
+ decoder_etc_block::get_block_colors5_bounds(block_colors, base_color, inten_table, low_selector, high_selector);
+
+ assert(block_colors[0][0] <= block_colors[1][0]);
+ assert(block_colors[0][1] <= block_colors[1][1]);
+ assert(block_colors[0][2] <= block_colors[1][2]);
+
+ // Set PVRTC1 endpoints to floor/ceil of bounding box's coordinates.
+ pvrtc4_block temp;
+ temp.set_opaque_endpoint_floor(0, block_colors[0]);
+ temp.set_opaque_endpoint_ceil(1, block_colors[1]);
+
+ pPVRTC_endpoints[block_x + block_y * num_blocks_x] = temp.m_endpoints;
+#else
+ assert(0);
+#endif
+
+ break;
+ }
+ case block_format::cPVRTC1_4_RGBA:
+ {
+#if BASISD_SUPPORT_PVRTC1
+ assert(pAlpha_blocks);
+
+ block.set_base5_color(decoder_etc_block::pack_color5(pEndpoints->m_color5, false));
+ block.set_inten_table(0, pEndpoints->m_inten5);
+ block.set_inten_table(1, pEndpoints->m_inten5);
+ block.set_raw_selector_bits(pSelector->m_selectors[0], pSelector->m_selectors[1], pSelector->m_selectors[2], pSelector->m_selectors[3]);
+
+ ((decoder_etc_block*)pPVRTC_work_mem)[block_x + block_y * num_blocks_x] = block;
+
+ // Get block's RGBA bounding box
+ const color32& base_color = pEndpoints->m_color5;
+ const uint32_t inten_table = pEndpoints->m_inten5;
+ const uint32_t low_selector = pSelector->m_lo_selector;
+ const uint32_t high_selector = pSelector->m_hi_selector;
+ color32 block_colors[2];
+ decoder_etc_block::get_block_colors5_bounds(block_colors, base_color, inten_table, low_selector, high_selector);
+
+ assert(block_colors[0][0] <= block_colors[1][0]);
+ assert(block_colors[0][1] <= block_colors[1][1]);
+ assert(block_colors[0][2] <= block_colors[1][2]);
+
+ const uint16_t* pAlpha_block = reinterpret_cast<uint16_t*>(static_cast<uint8_t*>(pAlpha_blocks) + (block_x + block_y * num_blocks_x) * sizeof(uint32_t));
+
+ const endpoint* pAlpha_endpoints = &m_endpoints[pAlpha_block[0]];
+ const selector* pAlpha_selector = &m_selectors[pAlpha_block[1]];
+
+ const color32& alpha_base_color = pAlpha_endpoints->m_color5;
+ const uint32_t alpha_inten_table = pAlpha_endpoints->m_inten5;
+ const uint32_t alpha_low_selector = pAlpha_selector->m_lo_selector;
+ const uint32_t alpha_high_selector = pAlpha_selector->m_hi_selector;
+ uint32_t alpha_block_colors[2];
+ decoder_etc_block::get_block_colors5_bounds_g(alpha_block_colors, alpha_base_color, alpha_inten_table, alpha_low_selector, alpha_high_selector);
+ assert(alpha_block_colors[0] <= alpha_block_colors[1]);
+ block_colors[0].a = (uint8_t)alpha_block_colors[0];
+ block_colors[1].a = (uint8_t)alpha_block_colors[1];
+
+ // Set PVRTC1 endpoints to floor/ceil of bounding box's coordinates.
+ pvrtc4_block temp;
+ temp.set_endpoint_floor(0, block_colors[0]);
+ temp.set_endpoint_ceil(1, block_colors[1]);
+
+ pPVRTC_endpoints[block_x + block_y * num_blocks_x] = temp.m_endpoints;
+#else
+ assert(0);
+#endif
+
+ break;
+ }
+ case block_format::cBC7_M6_OPAQUE_ONLY:
+ {
+#if BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+ convert_etc1s_to_bc7_m6(static_cast<bc7_mode_6*>(pDst_block), pEndpoints, pSelector);
+#else
+ assert(0);
+#endif
+ break;
+ }
+ case block_format::cBC7_M5_COLOR:
+ {
+#if BASISD_SUPPORT_BC7_MODE5
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+ convert_etc1s_to_bc7_m5_color(pDst_block, pEndpoints, pSelector);
+#else
+ assert(0);
+#endif
+ break;
+ }
+ case block_format::cBC7_M5_ALPHA:
+ {
+#if BASISD_SUPPORT_BC7_MODE5
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+ convert_etc1s_to_bc7_m5_alpha(pDst_block, pEndpoints, pSelector);
+#else
+ assert(0);
+#endif
+ break;
+ }
+ case block_format::cETC2_EAC_A8:
+ {
+#if BASISD_SUPPORT_ETC2_EAC_A8
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+ convert_etc1s_to_etc2_eac_a8(static_cast<eac_block*>(pDst_block), pEndpoints, pSelector);
+#else
+ assert(0);
+#endif
+ break;
+ }
+ case block_format::cASTC_4x4:
+ {
+#if BASISD_SUPPORT_ASTC
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+ convert_etc1s_to_astc_4x4(pDst_block, pEndpoints, pSelector, transcode_alpha, &m_endpoints[0], &m_selectors[0]);
+#else
+ assert(0);
+#endif
+ break;
+ }
+ case block_format::cATC_RGB:
+ {
+#if BASISD_SUPPORT_ATC
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+ convert_etc1s_to_atc(pDst_block, pEndpoints, pSelector);
+#else
+ assert(0);
+#endif
+ break;
+ }
+ case block_format::cFXT1_RGB:
+ {
+#if BASISD_SUPPORT_FXT1
+ const uint32_t fxt1_block_x = block_x >> 1;
+ const uint32_t fxt1_block_y = block_y;
+ const uint32_t fxt1_subblock = block_x & 1;
+
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (fxt1_block_x + fxt1_block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+
+ convert_etc1s_to_fxt1(pDst_block, pEndpoints, pSelector, fxt1_subblock);
+#else
+ assert(0);
+#endif
+ break;
+ }
+ case block_format::cPVRTC2_4_RGB:
+ {
+#if BASISD_SUPPORT_PVRTC2
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+ convert_etc1s_to_pvrtc2_rgb(pDst_block, pEndpoints, pSelector);
+#endif
+ break;
+ }
+ case block_format::cPVRTC2_4_RGBA:
+ {
+#if BASISD_SUPPORT_PVRTC2
+ assert(transcode_alpha);
+
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+
+ convert_etc1s_to_pvrtc2_rgba(pDst_block, pEndpoints, pSelector, &m_endpoints[0], &m_selectors[0]);
+#endif
+ break;
+ }
+ case block_format::cIndices:
+ {
+ uint16_t* pDst_block = reinterpret_cast<uint16_t *>(static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes);
+ pDst_block[0] = static_cast<uint16_t>(endpoint_index);
+ pDst_block[1] = static_cast<uint16_t>(selector_index);
+ break;
+ }
+ case block_format::cA32:
+ {
+ assert(sizeof(uint32_t) == output_block_or_pixel_stride_in_bytes);
+ uint8_t* pDst_pixels = static_cast<uint8_t*>(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint32_t);
+
+ const uint32_t max_x = basisu::minimum<int>(4, output_row_pitch_in_blocks_or_pixels - block_x * 4);
+ const uint32_t max_y = basisu::minimum<int>(4, output_rows_in_pixels - block_y * 4);
+
+ int colors[4];
+ decoder_etc_block::get_block_colors5_g(colors, pEndpoints->m_color5, pEndpoints->m_inten5);
+
+ if (max_x == 4)
+ {
+ for (uint32_t y = 0; y < max_y; y++)
+ {
+ const uint32_t s = pSelector->m_selectors[y];
+
+ pDst_pixels[3] = static_cast<uint8_t>(colors[s & 3]);
+ pDst_pixels[3+4] = static_cast<uint8_t>(colors[(s >> 2) & 3]);
+ pDst_pixels[3+8] = static_cast<uint8_t>(colors[(s >> 4) & 3]);
+ pDst_pixels[3+12] = static_cast<uint8_t>(colors[(s >> 6) & 3]);
+
+ pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint32_t);
+ }
+ }
+ else
+ {
+ for (uint32_t y = 0; y < max_y; y++)
+ {
+ const uint32_t s = pSelector->m_selectors[y];
+
+ for (uint32_t x = 0; x < max_x; x++)
+ pDst_pixels[3 + 4 * x] = static_cast<uint8_t>(colors[(s >> (x * 2)) & 3]);
+
+ pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint32_t);
+ }
+ }
+
+ break;
+ }
+ case block_format::cRGB32:
+ {
+ assert(sizeof(uint32_t) == output_block_or_pixel_stride_in_bytes);
+ uint8_t* pDst_pixels = static_cast<uint8_t*>(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint32_t);
+
+ const uint32_t max_x = basisu::minimum<int>(4, output_row_pitch_in_blocks_or_pixels - block_x * 4);
+ const uint32_t max_y = basisu::minimum<int>(4, output_rows_in_pixels - block_y * 4);
+
+ color32 colors[4];
+ decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5);
+
+ for (uint32_t y = 0; y < max_y; y++)
+ {
+ const uint32_t s = pSelector->m_selectors[y];
+
+ for (uint32_t x = 0; x < max_x; x++)
+ {
+ const color32& c = colors[(s >> (x * 2)) & 3];
+
+ pDst_pixels[0 + 4 * x] = c.r;
+ pDst_pixels[1 + 4 * x] = c.g;
+ pDst_pixels[2 + 4 * x] = c.b;
+ }
+
+ pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint32_t);
+ }
+
+ break;
+ }
+ case block_format::cRGBA32:
+ {
+ assert(sizeof(uint32_t) == output_block_or_pixel_stride_in_bytes);
+ uint8_t* pDst_pixels = static_cast<uint8_t*>(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint32_t);
+
+ const uint32_t max_x = basisu::minimum<int>(4, output_row_pitch_in_blocks_or_pixels - block_x * 4);
+ const uint32_t max_y = basisu::minimum<int>(4, output_rows_in_pixels - block_y * 4);
+
+ color32 colors[4];
+ decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5);
+
+ for (uint32_t y = 0; y < max_y; y++)
+ {
+ const uint32_t s = pSelector->m_selectors[y];
+
+ for (uint32_t x = 0; x < max_x; x++)
+ {
+ const color32& c = colors[(s >> (x * 2)) & 3];
+
+ pDst_pixels[0 + 4 * x] = c.r;
+ pDst_pixels[1 + 4 * x] = c.g;
+ pDst_pixels[2 + 4 * x] = c.b;
+ pDst_pixels[3 + 4 * x] = 255;
+ }
+
+ pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint32_t);
+ }
+
+ break;
+ }
+ case block_format::cRGB565:
+ case block_format::cBGR565:
+ {
+ assert(sizeof(uint16_t) == output_block_or_pixel_stride_in_bytes);
+ uint8_t* pDst_pixels = static_cast<uint8_t*>(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint16_t);
+
+ const uint32_t max_x = basisu::minimum<int>(4, output_row_pitch_in_blocks_or_pixels - block_x * 4);
+ const uint32_t max_y = basisu::minimum<int>(4, output_rows_in_pixels - block_y * 4);
+
+ color32 colors[4];
+ decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5);
+
+ uint16_t packed_colors[4];
+ if (fmt == block_format::cRGB565)
+ {
+ for (uint32_t i = 0; i < 4; i++)
+ packed_colors[i] = static_cast<uint16_t>(((colors[i].r >> 3) << 11) | ((colors[i].g >> 2) << 5) | (colors[i].b >> 3));
+ }
+ else
+ {
+ for (uint32_t i = 0; i < 4; i++)
+ packed_colors[i] = static_cast<uint16_t>(((colors[i].b >> 3) << 11) | ((colors[i].g >> 2) << 5) | (colors[i].r >> 3));
+ }
+
+ for (uint32_t y = 0; y < max_y; y++)
+ {
+ const uint32_t s = pSelector->m_selectors[y];
+
+ for (uint32_t x = 0; x < max_x; x++)
+ reinterpret_cast<uint16_t *>(pDst_pixels)[x] = packed_colors[(s >> (x * 2)) & 3];
+
+ pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint16_t);
+ }
+
+ break;
+ }
+ case block_format::cRGBA4444_COLOR:
+ {
+ assert(sizeof(uint16_t) == output_block_or_pixel_stride_in_bytes);
+ uint8_t* pDst_pixels = static_cast<uint8_t*>(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint16_t);
+
+ const uint32_t max_x = basisu::minimum<int>(4, output_row_pitch_in_blocks_or_pixels - block_x * 4);
+ const uint32_t max_y = basisu::minimum<int>(4, output_rows_in_pixels - block_y * 4);
+
+ color32 colors[4];
+ decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5);
+
+ uint16_t packed_colors[4];
+ for (uint32_t i = 0; i < 4; i++)
+ packed_colors[i] = static_cast<uint16_t>(((colors[i].r >> 4) << 12) | ((colors[i].g >> 4) << 8) | ((colors[i].b >> 4) << 4));
+
+ for (uint32_t y = 0; y < max_y; y++)
+ {
+ const uint32_t s = pSelector->m_selectors[y];
+
+ for (uint32_t x = 0; x < max_x; x++)
+ {
+ uint16_t cur = reinterpret_cast<uint16_t*>(pDst_pixels)[x];
+ cur = (cur & 0xF) | packed_colors[(s >> (x * 2)) & 3];
+ reinterpret_cast<uint16_t*>(pDst_pixels)[x] = cur;
+ }
+
+ pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint16_t);
+ }
+
+ break;
+ }
+ case block_format::cRGBA4444_COLOR_OPAQUE:
+ {
+ assert(sizeof(uint16_t) == output_block_or_pixel_stride_in_bytes);
+ uint8_t* pDst_pixels = static_cast<uint8_t*>(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint16_t);
+
+ const uint32_t max_x = basisu::minimum<int>(4, output_row_pitch_in_blocks_or_pixels - block_x * 4);
+ const uint32_t max_y = basisu::minimum<int>(4, output_rows_in_pixels - block_y * 4);
+
+ color32 colors[4];
+ decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5);
+
+ uint16_t packed_colors[4];
+ for (uint32_t i = 0; i < 4; i++)
+ packed_colors[i] = static_cast<uint16_t>(((colors[i].r >> 4) << 12) | ((colors[i].g >> 4) << 8) | ((colors[i].b >> 4) << 4) | 0xF);
+
+ for (uint32_t y = 0; y < max_y; y++)
+ {
+ const uint32_t s = pSelector->m_selectors[y];
+
+ for (uint32_t x = 0; x < max_x; x++)
+ reinterpret_cast<uint16_t*>(pDst_pixels)[x] = packed_colors[(s >> (x * 2)) & 3];
+
+ pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint16_t);
+ }
+
+ break;
+ }
+ case block_format::cRGBA4444_ALPHA:
+ {
+ assert(sizeof(uint16_t) == output_block_or_pixel_stride_in_bytes);
+ uint8_t* pDst_pixels = static_cast<uint8_t*>(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint16_t);
+
+ const uint32_t max_x = basisu::minimum<int>(4, output_row_pitch_in_blocks_or_pixels - block_x * 4);
+ const uint32_t max_y = basisu::minimum<int>(4, output_rows_in_pixels - block_y * 4);
+
+ color32 colors[4];
+ decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5);
+
+ uint16_t packed_colors[4];
+ for (uint32_t i = 0; i < 4; i++)
+ packed_colors[i] = colors[i].g >> 4;
+
+ for (uint32_t y = 0; y < max_y; y++)
+ {
+ const uint32_t s = pSelector->m_selectors[y];
+
+ for (uint32_t x = 0; x < max_x; x++)
+ reinterpret_cast<uint16_t*>(pDst_pixels)[x] = packed_colors[(s >> (x * 2)) & 3];
+
+ pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint16_t);
+ }
+
+ break;
+ }
+ case block_format::cETC2_EAC_R11:
+ {
+#if BASISD_SUPPORT_ETC2_EAC_RG11
+ void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes;
+ convert_etc1s_to_etc2_eac_r11(static_cast<eac_block*>(pDst_block), pEndpoints, pSelector);
+#else
+ assert(0);
+#endif
+ break;
+ }
+ default:
+ {
+ assert(0);
+ break;
+ }
+ }
+
+ } // block_x
+
+ } // block-y
+
+ if (endpoint_pred_repeat_count != 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: endpoint_pred_repeat_count != 0. The file is corrupted or this is a bug\n");
+ return false;
+ }
+
+ //assert(endpoint_pred_repeat_count == 0);
+
+#if BASISD_SUPPORT_PVRTC1
+ // PVRTC post process - create per-pixel modulation values.
+ if (fmt == block_format::cPVRTC1_4_RGB)
+ fixup_pvrtc1_4_modulation_rgb((decoder_etc_block*)pPVRTC_work_mem, pPVRTC_endpoints, pDst_blocks, num_blocks_x, num_blocks_y);
+ else if (fmt == block_format::cPVRTC1_4_RGBA)
+ fixup_pvrtc1_4_modulation_rgba((decoder_etc_block*)pPVRTC_work_mem, pPVRTC_endpoints, pDst_blocks, num_blocks_x, num_blocks_y, pAlpha_blocks, &m_endpoints[0], &m_selectors[0]);
+#endif // BASISD_SUPPORT_PVRTC1
+
+ if (pPVRTC_work_mem)
+ free(pPVRTC_work_mem);
+
+ return true;
+ }
+
+ basisu_transcoder::basisu_transcoder(const etc1_global_selector_codebook* pGlobal_sel_codebook) :
+ m_lowlevel_decoder(pGlobal_sel_codebook)
+ {
+ }
+
+ bool basisu_transcoder::validate_file_checksums(const void* pData, uint32_t data_size, bool full_validation) const
+ {
+ if (!validate_header(pData, data_size))
+ return false;
+
+ const basis_file_header* pHeader = reinterpret_cast<const basis_file_header*>(pData);
+
+#if !BASISU_NO_HEADER_OR_DATA_CRC16_CHECKS
+ if (crc16(&pHeader->m_data_size, sizeof(basis_file_header) - BASISU_OFFSETOF(basis_file_header, m_data_size), 0) != pHeader->m_header_crc16)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header CRC check failed\n");
+ return false;
+ }
+
+ if (full_validation)
+ {
+ if (crc16(reinterpret_cast<const uint8_t*>(pData) + sizeof(basis_file_header), pHeader->m_data_size, 0) != pHeader->m_data_crc16)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: data CRC check failed\n");
+ return false;
+ }
+ }
+#endif
+
+ return true;
+ }
+
+ bool basisu_transcoder::validate_header_quick(const void* pData, uint32_t data_size) const
+ {
+ if (data_size <= sizeof(basis_file_header))
+ return false;
+
+ const basis_file_header* pHeader = reinterpret_cast<const basis_file_header*>(pData);
+
+ if ((pHeader->m_sig != basis_file_header::cBASISSigValue) || (pHeader->m_ver != BASISD_SUPPORTED_BASIS_VERSION) || (pHeader->m_header_size != sizeof(basis_file_header)))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header has an invalid signature, or file version is unsupported\n");
+ return false;
+ }
+
+ uint32_t expected_file_size = sizeof(basis_file_header) + pHeader->m_data_size;
+ if (data_size < expected_file_size)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: source buffer is too small\n");
+ return false;
+ }
+
+ if ((!pHeader->m_total_slices) || (!pHeader->m_total_images))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::validate_header_quick: header is invalid\n");
+ return false;
+ }
+
+ if ((pHeader->m_slice_desc_file_ofs >= data_size) ||
+ ((data_size - pHeader->m_slice_desc_file_ofs) < (sizeof(basis_slice_desc) * pHeader->m_total_slices))
+ )
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::validate_header_quick: passed in buffer is too small or data is corrupted\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ bool basisu_transcoder::validate_header(const void* pData, uint32_t data_size) const
+ {
+ if (data_size <= sizeof(basis_file_header))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: input source buffer is too small\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = reinterpret_cast<const basis_file_header*>(pData);
+
+ if ((pHeader->m_sig != basis_file_header::cBASISSigValue) || (pHeader->m_ver != BASISD_SUPPORTED_BASIS_VERSION) || (pHeader->m_header_size != sizeof(basis_file_header)))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header has an invalid signature, or file version is unsupported\n");
+ return false;
+ }
+
+ uint32_t expected_file_size = sizeof(basis_file_header) + pHeader->m_data_size;
+ if (data_size < expected_file_size)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: input source buffer is too small, or header is corrupted\n");
+ return false;
+ }
+
+ if ((!pHeader->m_total_images) || (!pHeader->m_total_slices))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid basis file (total images or slices are 0)\n");
+ return false;
+ }
+
+ if (pHeader->m_total_images > pHeader->m_total_slices)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid basis file (too many images)\n");
+ return false;
+ }
+
+ if (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices)
+ {
+ if (pHeader->m_total_slices & 1)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid alpha basis file\n");
+ return false;
+ }
+ }
+
+ if ((pHeader->m_flags & cBASISHeaderFlagETC1S) == 0)
+ {
+ // We only support ETC1S in basis universal
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid basis file (ETC1S flag check)\n");
+ return false;
+ }
+
+ if ((pHeader->m_slice_desc_file_ofs >= data_size) ||
+ ((data_size - pHeader->m_slice_desc_file_ofs) < (sizeof(basis_slice_desc) * pHeader->m_total_slices))
+ )
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::validate_header_quick: passed in buffer is too small or data is corrupted\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ basis_texture_type basisu_transcoder::get_texture_type(const void* pData, uint32_t data_size) const
+ {
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_texture_type: header validation failed\n");
+ return cBASISTexType2DArray;
+ }
+
+ const basis_file_header* pHeader = static_cast<const basis_file_header*>(pData);
+
+ basis_texture_type btt = static_cast<basis_texture_type>(static_cast<uint8_t>(pHeader->m_tex_type));
+
+ if (btt >= cBASISTexTypeTotal)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::validate_header_quick: header's texture type field is invalid\n");
+ return cBASISTexType2DArray;
+ }
+
+ return btt;
+ }
+
+ bool basisu_transcoder::get_userdata(const void* pData, uint32_t data_size, uint32_t& userdata0, uint32_t& userdata1) const
+ {
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_userdata: header validation failed\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = static_cast<const basis_file_header*>(pData);
+
+ userdata0 = pHeader->m_userdata0;
+ userdata1 = pHeader->m_userdata1;
+ return true;
+ }
+
+ uint32_t basisu_transcoder::get_total_images(const void* pData, uint32_t data_size) const
+ {
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header validation failed\n");
+ return 0;
+ }
+
+ const basis_file_header* pHeader = static_cast<const basis_file_header*>(pData);
+
+ return pHeader->m_total_images;
+ }
+
+ bool basisu_transcoder::get_image_info(const void* pData, uint32_t data_size, basisu_image_info& image_info, uint32_t image_index) const
+ {
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: header validation failed\n");
+ return false;
+ }
+
+ int slice_index = find_first_slice_index(pData, data_size, image_index, 0);
+ if (slice_index < 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: invalid slice index\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = static_cast<const basis_file_header*>(pData);
+
+ if (image_index >= pHeader->m_total_images)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: invalid image_index\n");
+ return false;
+ }
+
+ const basis_slice_desc* pSlice_descs = reinterpret_cast<const basis_slice_desc*>(static_cast<const uint8_t*>(pData) + pHeader->m_slice_desc_file_ofs);
+
+ uint32_t total_levels = 1;
+ for (uint32_t i = slice_index + 1; i < pHeader->m_total_slices; i++)
+ if (pSlice_descs[i].m_image_index == image_index)
+ total_levels = basisu::maximum<uint32_t>(total_levels, pSlice_descs[i].m_level_index + 1);
+ else
+ break;
+
+ if (total_levels > 16)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: invalid image_index\n");
+ return false;
+ }
+
+ const basis_slice_desc& slice_desc = pSlice_descs[slice_index];
+
+ image_info.m_image_index = image_index;
+ image_info.m_total_levels = total_levels;
+ image_info.m_alpha_flag = (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices) != 0;
+ image_info.m_iframe_flag = (slice_desc.m_flags & cSliceDescFlagsFrameIsIFrame) != 0;
+ image_info.m_width = slice_desc.m_num_blocks_x * 4;
+ image_info.m_height = slice_desc.m_num_blocks_y * 4;
+ image_info.m_orig_width = slice_desc.m_orig_width;
+ image_info.m_orig_height = slice_desc.m_orig_height;
+ image_info.m_num_blocks_x = slice_desc.m_num_blocks_x;
+ image_info.m_num_blocks_y = slice_desc.m_num_blocks_y;
+ image_info.m_total_blocks = image_info.m_num_blocks_x * image_info.m_num_blocks_y;
+ image_info.m_first_slice_index = slice_index;
+
+ return true;
+ }
+
+ uint32_t basisu_transcoder::get_total_image_levels(const void* pData, uint32_t data_size, uint32_t image_index) const
+ {
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: header validation failed\n");
+ return false;
+ }
+
+ int slice_index = find_first_slice_index(pData, data_size, image_index, 0);
+ if (slice_index < 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: failed finding slice\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = static_cast<const basis_file_header*>(pData);
+
+ if (image_index >= pHeader->m_total_images)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: invalid image_index\n");
+ return false;
+ }
+
+ const basis_slice_desc* pSlice_descs = reinterpret_cast<const basis_slice_desc*>(static_cast<const uint8_t*>(pData) + pHeader->m_slice_desc_file_ofs);
+
+ uint32_t total_levels = 1;
+ for (uint32_t i = slice_index + 1; i < pHeader->m_total_slices; i++)
+ if (pSlice_descs[i].m_image_index == image_index)
+ total_levels = basisu::maximum<uint32_t>(total_levels, pSlice_descs[i].m_level_index + 1);
+ else
+ break;
+
+ const uint32_t cMaxSupportedLevels = 16;
+ if (total_levels > cMaxSupportedLevels)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: invalid image levels!\n");
+ return false;
+ }
+
+ return total_levels;
+ }
+
+ bool basisu_transcoder::get_image_level_desc(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, uint32_t& orig_width, uint32_t& orig_height, uint32_t& total_blocks) const
+ {
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_desc: header validation failed\n");
+ return false;
+ }
+
+ int slice_index = find_first_slice_index(pData, data_size, image_index, level_index);
+ if (slice_index < 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_desc: failed finding slice\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = static_cast<const basis_file_header*>(pData);
+
+ if (image_index >= pHeader->m_total_images)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_desc: invalid image_index\n");
+ return false;
+ }
+
+ const basis_slice_desc* pSlice_descs = reinterpret_cast<const basis_slice_desc*>(static_cast<const uint8_t*>(pData) + pHeader->m_slice_desc_file_ofs);
+
+ const basis_slice_desc& slice_desc = pSlice_descs[slice_index];
+
+ orig_width = slice_desc.m_orig_width;
+ orig_height = slice_desc.m_orig_height;
+ total_blocks = slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y;
+
+ return true;
+ }
+
+ bool basisu_transcoder::get_image_level_info(const void* pData, uint32_t data_size, basisu_image_level_info& image_info, uint32_t image_index, uint32_t level_index) const
+ {
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_info: validate_file_checksums failed\n");
+ return false;
+ }
+
+ int slice_index = find_first_slice_index(pData, data_size, image_index, level_index);
+ if (slice_index < 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_info: failed finding slice\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = static_cast<const basis_file_header*>(pData);
+
+ if (image_index >= pHeader->m_total_images)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_info: invalid image_index\n");
+ return false;
+ }
+
+ const basis_slice_desc* pSlice_descs = reinterpret_cast<const basis_slice_desc*>(static_cast<const uint8_t*>(pData) + pHeader->m_slice_desc_file_ofs);
+
+ const basis_slice_desc& slice_desc = pSlice_descs[slice_index];
+
+ image_info.m_image_index = image_index;
+ image_info.m_level_index = level_index;
+ image_info.m_alpha_flag = (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices) != 0;
+ image_info.m_iframe_flag = (slice_desc.m_flags & cSliceDescFlagsFrameIsIFrame) != 0;
+ image_info.m_width = slice_desc.m_num_blocks_x * 4;
+ image_info.m_height = slice_desc.m_num_blocks_y * 4;
+ image_info.m_orig_width = slice_desc.m_orig_width;
+ image_info.m_orig_height = slice_desc.m_orig_height;
+ image_info.m_num_blocks_x = slice_desc.m_num_blocks_x;
+ image_info.m_num_blocks_y = slice_desc.m_num_blocks_y;
+ image_info.m_total_blocks = image_info.m_num_blocks_x * image_info.m_num_blocks_y;
+ image_info.m_first_slice_index = slice_index;
+
+ return true;
+ }
+
+ bool basisu_transcoder::get_file_info(const void* pData, uint32_t data_size, basisu_file_info& file_info) const
+ {
+ if (!validate_file_checksums(pData, data_size, false))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_file_info: validate_file_checksums failed\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = static_cast<const basis_file_header*>(pData);
+ const basis_slice_desc* pSlice_descs = reinterpret_cast<const basis_slice_desc*>(static_cast<const uint8_t*>(pData) + pHeader->m_slice_desc_file_ofs);
+
+ file_info.m_version = pHeader->m_ver;
+
+ file_info.m_total_header_size = sizeof(basis_file_header) + pHeader->m_total_slices * sizeof(basis_slice_desc);
+
+ file_info.m_total_selectors = pHeader->m_total_selectors;
+ file_info.m_selector_codebook_size = pHeader->m_selector_cb_file_size;
+
+ file_info.m_total_endpoints = pHeader->m_total_endpoints;
+ file_info.m_endpoint_codebook_size = pHeader->m_endpoint_cb_file_size;
+
+ file_info.m_tables_size = pHeader->m_tables_file_size;
+
+ file_info.m_etc1s = (pHeader->m_flags & cBASISHeaderFlagETC1S) != 0;
+ file_info.m_y_flipped = (pHeader->m_flags & cBASISHeaderFlagYFlipped) != 0;
+ file_info.m_has_alpha_slices = (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices) != 0;
+
+ const uint32_t total_slices = pHeader->m_total_slices;
+
+ file_info.m_slice_info.resize(total_slices);
+
+ file_info.m_slices_size = 0;
+
+ file_info.m_tex_type = static_cast<basis_texture_type>(static_cast<uint8_t>(pHeader->m_tex_type));
+
+ if (file_info.m_tex_type > cBASISTexTypeTotal)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_file_info: invalid texture type, file is corrupted\n");
+ return false;
+ }
+
+ file_info.m_us_per_frame = pHeader->m_us_per_frame;
+ file_info.m_userdata0 = pHeader->m_userdata0;
+ file_info.m_userdata1 = pHeader->m_userdata1;
+
+ file_info.m_image_mipmap_levels.resize(0);
+ file_info.m_image_mipmap_levels.resize(pHeader->m_total_images);
+
+ file_info.m_total_images = pHeader->m_total_images;
+
+ for (uint32_t i = 0; i < total_slices; i++)
+ {
+ file_info.m_slices_size += pSlice_descs[i].m_file_size;
+
+ basisu_slice_info& slice_info = file_info.m_slice_info[i];
+
+ slice_info.m_orig_width = pSlice_descs[i].m_orig_width;
+ slice_info.m_orig_height = pSlice_descs[i].m_orig_height;
+ slice_info.m_width = pSlice_descs[i].m_num_blocks_x * 4;
+ slice_info.m_height = pSlice_descs[i].m_num_blocks_y * 4;
+ slice_info.m_num_blocks_x = pSlice_descs[i].m_num_blocks_x;
+ slice_info.m_num_blocks_y = pSlice_descs[i].m_num_blocks_y;
+ slice_info.m_total_blocks = slice_info.m_num_blocks_x * slice_info.m_num_blocks_y;
+ slice_info.m_compressed_size = pSlice_descs[i].m_file_size;
+ slice_info.m_slice_index = i;
+ slice_info.m_image_index = pSlice_descs[i].m_image_index;
+ slice_info.m_level_index = pSlice_descs[i].m_level_index;
+ slice_info.m_unpacked_slice_crc16 = pSlice_descs[i].m_slice_data_crc16;
+ slice_info.m_alpha_flag = (pSlice_descs[i].m_flags & cSliceDescFlagsIsAlphaData) != 0;
+ slice_info.m_iframe_flag = (pSlice_descs[i].m_flags & cSliceDescFlagsFrameIsIFrame) != 0;
+
+ if (pSlice_descs[i].m_image_index >= pHeader->m_total_images)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_file_info: slice desc's image index is invalid\n");
+ return false;
+ }
+
+ file_info.m_image_mipmap_levels[pSlice_descs[i].m_image_index] = basisu::maximum<uint32_t>(file_info.m_image_mipmap_levels[pSlice_descs[i].m_image_index], pSlice_descs[i].m_level_index + 1);
+
+ if (file_info.m_image_mipmap_levels[pSlice_descs[i].m_image_index] > 16)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::get_file_info: slice mipmap level is invalid\n");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool basisu_transcoder::start_transcoding(const void* pData, uint32_t data_size) const
+ {
+ if (m_lowlevel_decoder.m_endpoints.size())
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: already called start_transcoding\n");
+ return true;
+ }
+
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: header validation failed\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = reinterpret_cast<const basis_file_header*>(pData);
+
+ const uint8_t* pDataU8 = static_cast<const uint8_t*>(pData);
+
+ if (!pHeader->m_endpoint_cb_file_size || !pHeader->m_selector_cb_file_size || !pHeader->m_tables_file_size)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted (0)\n");
+ }
+
+ if ((pHeader->m_endpoint_cb_file_ofs > data_size) || (pHeader->m_selector_cb_file_ofs > data_size) || (pHeader->m_tables_file_ofs > data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted or passed in buffer too small (1)\n");
+ return false;
+ }
+
+ if (pHeader->m_endpoint_cb_file_size > (data_size - pHeader->m_endpoint_cb_file_ofs))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted or passed in buffer too small (2)\n");
+ return false;
+ }
+
+ if (pHeader->m_selector_cb_file_size > (data_size - pHeader->m_selector_cb_file_ofs))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted or passed in buffer too small (3)\n");
+ return false;
+ }
+
+ if (pHeader->m_tables_file_size > (data_size - pHeader->m_tables_file_ofs))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted or passed in buffer too small (3)\n");
+ return false;
+ }
+
+ if (!m_lowlevel_decoder.decode_palettes(
+ pHeader->m_total_endpoints, pDataU8 + pHeader->m_endpoint_cb_file_ofs, pHeader->m_endpoint_cb_file_size,
+ pHeader->m_total_selectors, pDataU8 + pHeader->m_selector_cb_file_ofs, pHeader->m_selector_cb_file_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: decode_palettes failed\n");
+ return false;
+ }
+
+ if (!m_lowlevel_decoder.decode_tables(pDataU8 + pHeader->m_tables_file_ofs, pHeader->m_tables_file_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: decode_tables failed\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ bool basisu_transcoder::transcode_slice(const void* pData, uint32_t data_size, uint32_t slice_index, void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, block_format fmt,
+ uint32_t output_block_or_pixel_stride_in_bytes, uint32_t decode_flags, uint32_t output_row_pitch_in_blocks_or_pixels, basisu_transcoder_state* pState, void *pAlpha_blocks, uint32_t output_rows_in_pixels) const
+ {
+ if (!m_lowlevel_decoder.m_endpoints.size())
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: must call start_transcoding first\n");
+ return false;
+ }
+
+ if (decode_flags & cDecodeFlagsPVRTCDecodeToNextPow2)
+ {
+ // TODO: Not yet supported
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: cDecodeFlagsPVRTCDecodeToNextPow2 currently unsupported\n");
+ return false;
+ }
+
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: header validation failed\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = reinterpret_cast<const basis_file_header*>(pData);
+
+ const uint8_t* pDataU8 = static_cast<const uint8_t*>(pData);
+
+ if (slice_index >= pHeader->m_total_slices)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: slice_index >= pHeader->m_total_slices\n");
+ return false;
+ }
+
+ const basis_slice_desc& slice_desc = reinterpret_cast<const basis_slice_desc*>(pDataU8 + pHeader->m_slice_desc_file_ofs)[slice_index];
+
+ uint32_t total_4x4_blocks = slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y;
+
+ if (basis_block_format_is_uncompressed(fmt))
+ {
+ // Assume the output buffer is orig_width by orig_height
+ if (!output_row_pitch_in_blocks_or_pixels)
+ output_row_pitch_in_blocks_or_pixels = slice_desc.m_orig_width;
+
+ if (!output_rows_in_pixels)
+ output_rows_in_pixels = slice_desc.m_orig_height;
+
+ // Now make sure the output buffer is large enough, or we'll overwrite memory.
+ if (output_blocks_buf_size_in_blocks_or_pixels < (output_rows_in_pixels * output_row_pitch_in_blocks_or_pixels))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: output_blocks_buf_size_in_blocks_or_pixels < (output_rows_in_pixels * output_row_pitch_in_blocks_or_pixels)\n");
+ return false;
+ }
+ }
+ else if (fmt == block_format::cFXT1_RGB)
+ {
+ const uint32_t num_blocks_fxt1_x = (slice_desc.m_orig_width + 7) / 8;
+ const uint32_t num_blocks_fxt1_y = (slice_desc.m_orig_height + 3) / 4;
+ const uint32_t total_blocks_fxt1 = num_blocks_fxt1_x * num_blocks_fxt1_y;
+
+ if (output_blocks_buf_size_in_blocks_or_pixels < total_blocks_fxt1)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: output_blocks_buf_size_in_blocks_or_pixels < total_blocks_fxt1\n");
+ return false;
+ }
+ }
+ else
+ {
+ if (output_blocks_buf_size_in_blocks_or_pixels < total_4x4_blocks)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: output_blocks_buf_size_in_blocks_or_pixels < total_blocks\n");
+ return false;
+ }
+ }
+
+ if (fmt != block_format::cETC1)
+ {
+ if ((fmt == block_format::cPVRTC1_4_RGB) || (fmt == block_format::cPVRTC1_4_RGBA))
+ {
+ if ((!basisu::is_pow2(slice_desc.m_num_blocks_x * 4)) || (!basisu::is_pow2(slice_desc.m_num_blocks_y * 4)))
+ {
+ // PVRTC1 only supports power of 2 dimensions
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: PVRTC1 only supports power of 2 dimensions\n");
+ return false;
+ }
+ }
+ }
+
+ if (slice_desc.m_file_ofs > data_size)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: invalid slice_desc.m_file_ofs, or passed in buffer too small\n");
+ return false;
+ }
+
+ const uint32_t data_size_left = data_size - slice_desc.m_file_ofs;
+ if (data_size_left < slice_desc.m_file_size)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: invalid slice_desc.m_file_size, or passed in buffer too small\n");
+ return false;
+ }
+
+ return m_lowlevel_decoder.transcode_slice(pOutput_blocks, slice_desc.m_num_blocks_x, slice_desc.m_num_blocks_y,
+ pDataU8 + slice_desc.m_file_ofs, slice_desc.m_file_size,
+ fmt, output_block_or_pixel_stride_in_bytes, (decode_flags & cDecodeFlagsBC1ForbidThreeColorBlocks) == 0, *pHeader, slice_desc, output_row_pitch_in_blocks_or_pixels, pState,
+ (decode_flags & cDecodeFlagsOutputHasAlphaIndices) != 0, pAlpha_blocks, output_rows_in_pixels);
+ }
+
+ int basisu_transcoder::find_first_slice_index(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index) const
+ {
+ (void)data_size;
+
+ const basis_file_header* pHeader = reinterpret_cast<const basis_file_header*>(pData);
+ const uint8_t* pDataU8 = static_cast<const uint8_t*>(pData);
+
+ // For very large basis files this search could be painful
+ // TODO: Binary search this
+ for (uint32_t slice_iter = 0; slice_iter < pHeader->m_total_slices; slice_iter++)
+ {
+ const basis_slice_desc& slice_desc = reinterpret_cast<const basis_slice_desc*>(pDataU8 + pHeader->m_slice_desc_file_ofs)[slice_iter];
+ if ((slice_desc.m_image_index == image_index) && (slice_desc.m_level_index == level_index))
+ return slice_iter;
+ }
+
+ BASISU_DEVEL_ERROR("basisu_transcoder::find_first_slice_index: didn't find slice\n");
+
+ return -1;
+ }
+
+ int basisu_transcoder::find_slice(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, bool alpha_data) const
+ {
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::find_slice: header validation failed\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = reinterpret_cast<const basis_file_header*>(pData);
+ const uint8_t* pDataU8 = static_cast<const uint8_t*>(pData);
+ const basis_slice_desc* pSlice_descs = reinterpret_cast<const basis_slice_desc*>(pDataU8 + pHeader->m_slice_desc_file_ofs);
+
+ // For very large basis files this search could be painful
+ // TODO: Binary search this
+ for (uint32_t slice_iter = 0; slice_iter < pHeader->m_total_slices; slice_iter++)
+ {
+ const basis_slice_desc& slice_desc = pSlice_descs[slice_iter];
+ if ((slice_desc.m_image_index == image_index) && (slice_desc.m_level_index == level_index))
+ {
+ const bool slice_alpha = (slice_desc.m_flags & cSliceDescFlagsIsAlphaData) != 0;
+ if (slice_alpha == alpha_data)
+ return slice_iter;
+ }
+ }
+
+ BASISU_DEVEL_ERROR("basisu_transcoder::find_slice: didn't find slice\n");
+
+ return -1;
+ }
+
+ static void write_opaque_alpha_blocks(
+ uint32_t num_blocks_x, uint32_t num_blocks_y,
+ void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, block_format fmt,
+ uint32_t block_stride_in_bytes, uint32_t output_row_pitch_in_blocks_or_pixels)
+ {
+ BASISU_NOTE_UNUSED(output_blocks_buf_size_in_blocks_or_pixels);
+
+ if (!output_row_pitch_in_blocks_or_pixels)
+ output_row_pitch_in_blocks_or_pixels = num_blocks_x;
+
+ if ((fmt == block_format::cETC2_EAC_A8) || (fmt == block_format::cETC2_EAC_R11))
+ {
+#if BASISD_SUPPORT_ETC2_EAC_A8
+ eac_block blk;
+ blk.m_base = 255;
+ blk.m_multiplier = 1;
+ blk.m_table = 13;
+
+ // Selectors are all 4's
+ static const uint8_t s_etc2_eac_a8_sel4[6] = { 0x92, 0x49, 0x24, 0x92, 0x49, 0x24 };
+ memcpy(&blk.m_selectors, s_etc2_eac_a8_sel4, sizeof(s_etc2_eac_a8_sel4));
+
+ for (uint32_t y = 0; y < num_blocks_y; y++)
+ {
+ uint32_t dst_ofs = y * output_row_pitch_in_blocks_or_pixels * block_stride_in_bytes;
+ for (uint32_t x = 0; x < num_blocks_x; x++)
+ {
+ memcpy((uint8_t*)pOutput_blocks + dst_ofs, &blk, sizeof(blk));
+ dst_ofs += block_stride_in_bytes;
+ }
+ }
+#endif
+ }
+ else if (fmt == block_format::cBC4)
+ {
+#if BASISD_SUPPORT_DXT5A
+ dxt5a_block blk;
+ blk.m_endpoints[0] = 255;
+ blk.m_endpoints[1] = 255;
+ memset(blk.m_selectors, 0, sizeof(blk.m_selectors));
+
+ for (uint32_t y = 0; y < num_blocks_y; y++)
+ {
+ uint32_t dst_ofs = y * output_row_pitch_in_blocks_or_pixels * block_stride_in_bytes;
+ for (uint32_t x = 0; x < num_blocks_x; x++)
+ {
+ memcpy((uint8_t*)pOutput_blocks + dst_ofs, &blk, sizeof(blk));
+ dst_ofs += block_stride_in_bytes;
+ }
+ }
+#endif
+ }
+ }
+
+ bool basisu_transcoder::transcode_image_level(
+ const void* pData, uint32_t data_size,
+ uint32_t image_index, uint32_t level_index,
+ void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
+ transcoder_texture_format fmt,
+ uint32_t decode_flags, uint32_t output_row_pitch_in_blocks_or_pixels, basisu_transcoder_state *pState, uint32_t output_rows_in_pixels) const
+ {
+ const uint32_t bytes_per_block = basis_get_bytes_per_block(fmt);
+
+ if (!m_lowlevel_decoder.m_endpoints.size())
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: must call start_transcoding() first\n");
+ return false;
+ }
+
+ const bool transcode_alpha_data_to_opaque_formats = (decode_flags & cDecodeFlagsTranscodeAlphaDataToOpaqueFormats) != 0;
+
+ if (decode_flags & cDecodeFlagsPVRTCDecodeToNextPow2)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: cDecodeFlagsPVRTCDecodeToNextPow2 currently unsupported\n");
+ // TODO: Not yet supported
+ return false;
+ }
+
+ if (!validate_header_quick(pData, data_size))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: header validation failed\n");
+ return false;
+ }
+
+ const basis_file_header* pHeader = reinterpret_cast<const basis_file_header*>(pData);
+
+ const uint8_t* pDataU8 = static_cast<const uint8_t*>(pData);
+
+ const basis_slice_desc* pSlice_descs = reinterpret_cast<const basis_slice_desc*>(pDataU8 + pHeader->m_slice_desc_file_ofs);
+
+ const bool basis_file_has_alpha_slices = (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices) != 0;
+
+ int slice_index = find_first_slice_index(pData, data_size, image_index, level_index);
+ if (slice_index < 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: failed finding slice index\n");
+ // Unable to find the requested image/level
+ return false;
+ }
+
+ if ((fmt == transcoder_texture_format::cTFPVRTC1_4_RGBA) && (!basis_file_has_alpha_slices))
+ {
+ // Switch to PVRTC1 RGB if the input doesn't have alpha.
+ fmt = transcoder_texture_format::cTFPVRTC1_4_RGB;
+ }
+
+ if (pSlice_descs[slice_index].m_flags & cSliceDescFlagsIsAlphaData)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file has out of order alpha slice\n");
+
+ // The first slice shouldn't have alpha data in a properly formed basis file
+ return false;
+ }
+
+ if (basis_file_has_alpha_slices)
+ {
+ // The alpha data should immediately follow the color data, and have the same resolution.
+ if ((slice_index + 1U) >= pHeader->m_total_slices)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file has missing alpha slice\n");
+ // basis file is missing the alpha slice
+ return false;
+ }
+
+ // Basic sanity checks
+ if ((pSlice_descs[slice_index + 1].m_flags & cSliceDescFlagsIsAlphaData) == 0)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file has missing alpha slice (flag check)\n");
+ // This slice should have alpha data
+ return false;
+ }
+
+ if ((pSlice_descs[slice_index].m_num_blocks_x != pSlice_descs[slice_index + 1].m_num_blocks_x) || (pSlice_descs[slice_index].m_num_blocks_y != pSlice_descs[slice_index + 1].m_num_blocks_y))
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file slice dimensions bad\n");
+ // Alpha slice should have been the same res as the color slice
+ return false;
+ }
+ }
+
+ bool status = false;
+
+ const uint32_t total_slice_blocks = pSlice_descs[slice_index].m_num_blocks_x * pSlice_descs[slice_index].m_num_blocks_y;
+
+ if (((fmt == transcoder_texture_format::cTFPVRTC1_4_RGB) || (fmt == transcoder_texture_format::cTFPVRTC1_4_RGBA)) && (output_blocks_buf_size_in_blocks_or_pixels > total_slice_blocks))
+ {
+ // The transcoder doesn't write beyond total_slice_blocks, so we need to clear the rest ourselves.
+ // For GL usage, PVRTC1 4bpp image size is (max(width, 8)* max(height, 8) * 4 + 7) / 8.
+ // However, for KTX and internally in Basis this formula isn't used, it's just ((width+3)/4) * ((height+3)/4) * bytes_per_block. This is all the transcoder actually writes to memory.
+ memset(static_cast<uint8_t*>(pOutput_blocks) + total_slice_blocks * bytes_per_block, 0, (output_blocks_buf_size_in_blocks_or_pixels - total_slice_blocks) * bytes_per_block);
+ }
+
+ switch (fmt)
+ {
+ case transcoder_texture_format::cTFETC1_RGB:
+ {
+ uint32_t slice_index_to_decode = slice_index;
+ // If the caller wants us to transcode the mip level's alpha data, then use the next slice.
+ if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats))
+ slice_index_to_decode++;
+
+ status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC1, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ETC1 failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFBC1_RGB:
+ {
+#if !BASISD_SUPPORT_DXT1
+ return false;
+#endif
+ uint32_t slice_index_to_decode = slice_index;
+ // If the caller wants us to transcode the mip level's alpha data, then use the next slice.
+ if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats))
+ slice_index_to_decode++;
+
+ status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC1, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC1 failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFBC4_R:
+ {
+#if !BASISD_SUPPORT_DXT5A
+ return false;
+#endif
+ uint32_t slice_index_to_decode = slice_index;
+ // If the caller wants us to transcode the mip level's alpha data, then use the next slice.
+ if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats))
+ slice_index_to_decode++;
+
+ status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC4 failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFPVRTC1_4_RGB:
+ {
+#if !BASISD_SUPPORT_PVRTC1
+ return false;
+#endif
+ uint32_t slice_index_to_decode = slice_index;
+ // If the caller wants us to transcode the mip level's alpha data, then use the next slice.
+ if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats))
+ slice_index_to_decode++;
+
+ // output_row_pitch_in_blocks_or_pixels is actually ignored because we're transcoding to PVRTC1. (Print a dev warning if it's != 0?)
+ status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC1_4_RGB, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to PVRTC1 4 RGB failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFPVRTC1_4_RGBA:
+ {
+#if !BASISD_SUPPORT_PVRTC1
+ return false;
+#endif
+ assert(basis_file_has_alpha_slices);
+
+ // Temp buffer to hold alpha block endpoint/selector indices
+ std::vector<uint32_t> temp_block_indices(total_slice_blocks);
+
+ // First transcode alpha data to temp buffer
+ status = transcode_slice(pData, data_size, slice_index + 1, &temp_block_indices[0], total_slice_blocks, block_format::cIndices, sizeof(uint32_t), decode_flags, pSlice_descs[slice_index].m_num_blocks_x, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to PVRTC1 4 RGBA failed (0)\n");
+ }
+ else
+ {
+ // output_row_pitch_in_blocks_or_pixels is actually ignored because we're transcoding to PVRTC1. (Print a dev warning if it's != 0?)
+ status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC1_4_RGBA, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState, &temp_block_indices[0]);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to PVRTC1 4 RGBA failed (1)\n");
+ }
+ }
+
+ break;
+ }
+ case transcoder_texture_format::cTFBC7_M6_RGB:
+ {
+#if !BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY
+ return false;
+#endif
+ uint32_t slice_index_to_decode = slice_index;
+ // If the caller wants us to transcode the mip level's alpha data, then use the next slice.
+ if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats))
+ slice_index_to_decode++;
+
+ status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC7_M6_OPAQUE_ONLY, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC7 m6 opaque only failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFBC7_M5_RGBA:
+ {
+#if !BASISD_SUPPORT_BC7_MODE5
+ return false;
+#else
+ assert(bytes_per_block == 16);
+
+ // First transcode the color slice. The cBC7_M5_COLOR transcoder will output opaque mode 5 blocks.
+ status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC7_M5_COLOR, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+
+ if ((status) && (basis_file_has_alpha_slices))
+ {
+ // Now transcode the alpha slice. The cBC7_M5_ALPHA transcoder will now change the opaque mode 5 blocks to blocks with alpha.
+ status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC7_M5_ALPHA, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ }
+
+ break;
+#endif
+ }
+ case transcoder_texture_format::cTFETC2_RGBA:
+ {
+#if !BASISD_SUPPORT_ETC2_EAC_A8
+ return false;
+#endif
+ assert(bytes_per_block == 16);
+
+ if (basis_file_has_alpha_slices)
+ {
+ // First decode the alpha data
+ status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_A8, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ }
+ else
+ {
+ write_opaque_alpha_blocks(pSlice_descs[slice_index].m_num_blocks_x, pSlice_descs[slice_index].m_num_blocks_y, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_A8, 16, output_row_pitch_in_blocks_or_pixels);
+ status = true;
+ }
+
+ if (status)
+ {
+ // Now decode the color data
+ status = transcode_slice(pData, data_size, slice_index, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC1, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ETC2 RGB failed\n");
+ }
+ }
+ else
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ETC2 A failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFBC3_RGBA:
+ {
+#if !BASISD_SUPPORT_DXT1
+ return false;
+#endif
+#if !BASISD_SUPPORT_DXT5A
+ return false;
+#endif
+ assert(bytes_per_block == 16);
+
+ // First decode the alpha data
+ if (basis_file_has_alpha_slices)
+ {
+ status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ }
+ else
+ {
+ write_opaque_alpha_blocks(pSlice_descs[slice_index].m_num_blocks_x, pSlice_descs[slice_index].m_num_blocks_y, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, output_row_pitch_in_blocks_or_pixels);
+ status = true;
+ }
+
+ if (status)
+ {
+ // Now decode the color data. Forbid 3 color blocks, which aren't allowed in BC3.
+ status = transcode_slice(pData, data_size, slice_index, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC1, 16, decode_flags | cDecodeFlagsBC1ForbidThreeColorBlocks, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC3 RGB failed\n");
+ }
+ }
+ else
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC3 A failed\n");
+ }
+
+ break;
+ }
+ case transcoder_texture_format::cTFBC5_RG:
+ {
+#if !BASISD_SUPPORT_DXT5A
+ return false;
+#endif
+ assert(bytes_per_block == 16);
+
+ // Decode the R data (actually the green channel of the color data slice in the basis file)
+ status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (status)
+ {
+ if (basis_file_has_alpha_slices)
+ {
+ // Decode the G data (actually the green channel of the alpha data slice in the basis file)
+ status = transcode_slice(pData, data_size, slice_index + 1, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC5 1 failed\n");
+ }
+ }
+ else
+ {
+ write_opaque_alpha_blocks(pSlice_descs[slice_index].m_num_blocks_x, pSlice_descs[slice_index].m_num_blocks_y, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, output_row_pitch_in_blocks_or_pixels);
+ status = true;
+ }
+ }
+ else
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC5 channel 0 failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFASTC_4x4_RGBA:
+ {
+#if !BASISD_SUPPORT_ASTC
+ return false;
+#endif
+ assert(bytes_per_block == 16);
+
+ if (basis_file_has_alpha_slices)
+ {
+ // First decode the alpha data to the output (we're using the output texture as a temp buffer here).
+ status = transcode_slice(pData, data_size, slice_index + 1, (uint8_t*)pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cIndices, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to failed\n");
+ }
+ else
+ {
+ // Now decode the color data and transcode to ASTC. The transcoder function will read the alpha selector data from the output texture as it converts and
+ // transcode both the alpha and color data at the same time to ASTC.
+ status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cASTC_4x4, 16, decode_flags | cDecodeFlagsOutputHasAlphaIndices, output_row_pitch_in_blocks_or_pixels, pState);
+ }
+ }
+ else
+ status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cASTC_4x4, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+
+ break;
+ }
+ case transcoder_texture_format::cTFATC_RGB:
+ {
+#if !BASISD_SUPPORT_ATC
+ return false;
+#endif
+ uint32_t slice_index_to_decode = slice_index;
+ // If the caller wants us to transcode the mip level's alpha data, then use the next slice.
+ if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats))
+ slice_index_to_decode++;
+
+ status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cATC_RGB, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ATC_RGB failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFATC_RGBA:
+ {
+#if !BASISD_SUPPORT_ATC
+ return false;
+#endif
+#if !BASISD_SUPPORT_DXT5A
+ return false;
+#endif
+ assert(bytes_per_block == 16);
+
+ // First decode the alpha data
+ if (basis_file_has_alpha_slices)
+ {
+ status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ }
+ else
+ {
+ write_opaque_alpha_blocks(pSlice_descs[slice_index].m_num_blocks_x, pSlice_descs[slice_index].m_num_blocks_y, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, output_row_pitch_in_blocks_or_pixels);
+ status = true;
+ }
+
+ if (status)
+ {
+ status = transcode_slice(pData, data_size, slice_index, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cATC_RGB, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ATC RGB failed\n");
+ }
+ }
+ else
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ATC A failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFPVRTC2_4_RGB:
+ {
+#if !BASISD_SUPPORT_PVRTC2
+ return false;
+#endif
+ uint32_t slice_index_to_decode = slice_index;
+ // If the caller wants us to transcode the mip level's alpha data, then use the next slice.
+ if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats))
+ slice_index_to_decode++;
+
+ status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC2_4_RGB, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to cPVRTC2_4_RGB failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFPVRTC2_4_RGBA:
+ {
+#if !BASISD_SUPPORT_PVRTC2
+ return false;
+#endif
+ if (basis_file_has_alpha_slices)
+ {
+ // First decode the alpha data to the output (we're using the output texture as a temp buffer here).
+ status = transcode_slice(pData, data_size, slice_index + 1, (uint8_t*)pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cIndices, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to failed\n");
+ }
+ else
+ {
+ // Now decode the color data and transcode to PVRTC2 RGBA.
+ status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC2_4_RGBA, bytes_per_block, decode_flags | cDecodeFlagsOutputHasAlphaIndices, output_row_pitch_in_blocks_or_pixels, pState);
+ }
+ }
+ else
+ status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC2_4_RGB, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to cPVRTC2_4_RGBA failed\n");
+ }
+
+ break;
+ }
+ case transcoder_texture_format::cTFRGBA32:
+ {
+ // Raw 32bpp pixels, decoded in the usual raster order (NOT block order) into an image in memory.
+
+ // First decode the alpha data
+ if (basis_file_has_alpha_slices)
+ status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cA32, sizeof(uint32_t), decode_flags, output_row_pitch_in_blocks_or_pixels, pState, nullptr, output_rows_in_pixels);
+ else
+ status = true;
+
+ if (status)
+ {
+ status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, basis_file_has_alpha_slices ? block_format::cRGB32 : block_format::cRGBA32, sizeof(uint32_t), decode_flags, output_row_pitch_in_blocks_or_pixels, pState, nullptr, output_rows_in_pixels);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to RGBA32 RGB failed\n");
+ }
+ }
+ else
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to RGBA32 A failed\n");
+ }
+
+ break;
+ }
+ case transcoder_texture_format::cTFRGB565:
+ case transcoder_texture_format::cTFBGR565:
+ {
+ // Raw 16bpp pixels, decoded in the usual raster order (NOT block order) into an image in memory.
+
+ uint32_t slice_index_to_decode = slice_index;
+ // If the caller wants us to transcode the mip level's alpha data, then use the next slice.
+ if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats))
+ slice_index_to_decode++;
+
+ status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, (fmt == transcoder_texture_format::cTFRGB565) ? block_format::cRGB565 : block_format::cBGR565, sizeof(uint16_t), decode_flags, output_row_pitch_in_blocks_or_pixels, pState, nullptr, output_rows_in_pixels);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to RGB565 RGB failed\n");
+ }
+
+ break;
+ }
+ case transcoder_texture_format::cTFRGBA4444:
+ {
+ // Raw 16bpp pixels, decoded in the usual raster order (NOT block order) into an image in memory.
+
+ // First decode the alpha data
+ if (basis_file_has_alpha_slices)
+ status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cRGBA4444_ALPHA, sizeof(uint16_t), decode_flags, output_row_pitch_in_blocks_or_pixels, pState, nullptr, output_rows_in_pixels);
+ else
+ status = true;
+
+ if (status)
+ {
+ status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, basis_file_has_alpha_slices ? block_format::cRGBA4444_COLOR : block_format::cRGBA4444_COLOR_OPAQUE, sizeof(uint16_t), decode_flags, output_row_pitch_in_blocks_or_pixels, pState, nullptr, output_rows_in_pixels);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to RGBA4444 RGB failed\n");
+ }
+ }
+ else
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to RGBA4444 A failed\n");
+ }
+
+ break;
+ }
+ case transcoder_texture_format::cTFFXT1_RGB:
+ {
+#if !BASISD_SUPPORT_FXT1
+ return false;
+#endif
+ uint32_t slice_index_to_decode = slice_index;
+ // If the caller wants us to transcode the mip level's alpha data, then use the next slice.
+ if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats))
+ slice_index_to_decode++;
+
+ status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cFXT1_RGB, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to FXT1_RGB failed\n");
+ }
+ break;
+ }
+ case transcoder_texture_format::cTFETC2_EAC_R11:
+ {
+#if !BASISD_SUPPORT_ETC2_EAC_RG11
+ return false;
+#endif
+ uint32_t slice_index_to_decode = slice_index;
+ // If the caller wants us to transcode the mip level's alpha data, then use the next slice.
+ if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats))
+ slice_index_to_decode++;
+
+ status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_R11, bytes_per_block, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ETC2_EAC_R11 failed\n");
+ }
+
+ break;
+ }
+ case transcoder_texture_format::cTFETC2_EAC_RG11:
+ {
+#if !BASISD_SUPPORT_ETC2_EAC_RG11
+ return false;
+#endif
+ assert(bytes_per_block == 16);
+
+ if (basis_file_has_alpha_slices)
+ {
+ // First decode the alpha data to G
+ status = transcode_slice(pData, data_size, slice_index + 1, (uint8_t *)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_R11, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ }
+ else
+ {
+ write_opaque_alpha_blocks(pSlice_descs[slice_index].m_num_blocks_x, pSlice_descs[slice_index].m_num_blocks_y, (uint8_t *)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_R11, 16, output_row_pitch_in_blocks_or_pixels);
+ status = true;
+ }
+
+ if (status)
+ {
+ // Now decode the color data to R
+ status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_R11, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState);
+ if (!status)
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ETC2_EAC_R11 R failed\n");
+ }
+ }
+ else
+ {
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ETC2_EAC_R11 G failed\n");
+ }
+
+ break;
+ }
+ default:
+ {
+ assert(0);
+ BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: Invalid fmt\n");
+ break;
+ }
+ }
+
+ return status;
+ }
+
+ uint32_t basis_get_bytes_per_block(transcoder_texture_format fmt)
+ {
+ switch (fmt)
+ {
+ case transcoder_texture_format::cTFETC1_RGB:
+ case transcoder_texture_format::cTFBC1_RGB:
+ case transcoder_texture_format::cTFBC4_R:
+ case transcoder_texture_format::cTFPVRTC1_4_RGB:
+ case transcoder_texture_format::cTFPVRTC1_4_RGBA:
+ case transcoder_texture_format::cTFATC_RGB:
+ case transcoder_texture_format::cTFPVRTC2_4_RGB:
+ case transcoder_texture_format::cTFPVRTC2_4_RGBA:
+ case transcoder_texture_format::cTFETC2_EAC_R11:
+ return 8;
+ case transcoder_texture_format::cTFBC7_M6_RGB:
+ case transcoder_texture_format::cTFBC7_M5_RGBA:
+ case transcoder_texture_format::cTFETC2_RGBA:
+ case transcoder_texture_format::cTFBC3_RGBA:
+ case transcoder_texture_format::cTFBC5_RG:
+ case transcoder_texture_format::cTFASTC_4x4_RGBA:
+ case transcoder_texture_format::cTFATC_RGBA:
+ case transcoder_texture_format::cTFFXT1_RGB:
+ case transcoder_texture_format::cTFETC2_EAC_RG11:
+ return 16;
+ case transcoder_texture_format::cTFRGBA32:
+ return sizeof(uint32_t) * 16;
+ case transcoder_texture_format::cTFRGB565:
+ case transcoder_texture_format::cTFBGR565:
+ case transcoder_texture_format::cTFRGBA4444:
+ return sizeof(uint16_t) * 16;
+ default:
+ assert(0);
+ BASISU_DEVEL_ERROR("basis_get_basisu_texture_format: Invalid fmt\n");
+ break;
+ }
+ return 0;
+ }
+
+ const char* basis_get_format_name(transcoder_texture_format fmt)
+ {
+ switch (fmt)
+ {
+ case transcoder_texture_format::cTFETC1_RGB: return "ETC1_RGB";
+ case transcoder_texture_format::cTFBC1_RGB: return "BC1_RGB";
+ case transcoder_texture_format::cTFBC4_R: return "BC4_R";
+ case transcoder_texture_format::cTFPVRTC1_4_RGB: return "PVRTC1_4_RGB";
+ case transcoder_texture_format::cTFPVRTC1_4_RGBA: return "PVRTC1_4_RGBA";
+ case transcoder_texture_format::cTFBC7_M6_RGB: return "BC7_M6_RGB";
+ case transcoder_texture_format::cTFBC7_M5_RGBA: return "BC7_M5_RGBA";
+ case transcoder_texture_format::cTFETC2_RGBA: return "ETC2_RGBA";
+ case transcoder_texture_format::cTFBC3_RGBA: return "BC3_RGBA";
+ case transcoder_texture_format::cTFBC5_RG: return "BC5_RG";
+ case transcoder_texture_format::cTFASTC_4x4_RGBA: return "ASTC_RGBA";
+ case transcoder_texture_format::cTFATC_RGB: return "ATC_RGB";
+ case transcoder_texture_format::cTFATC_RGBA: return "ATC_RGBA";
+ case transcoder_texture_format::cTFRGBA32: return "RGBA32";
+ case transcoder_texture_format::cTFRGB565: return "RGB565";
+ case transcoder_texture_format::cTFBGR565: return "BGR565";
+ case transcoder_texture_format::cTFRGBA4444: return "RGBA4444";
+ case transcoder_texture_format::cTFFXT1_RGB: return "FXT1_RGB";
+ case transcoder_texture_format::cTFPVRTC2_4_RGB: return "PVRTC2_4_RGB";
+ case transcoder_texture_format::cTFPVRTC2_4_RGBA: return "PVRTC2_4_RGBA";
+ case transcoder_texture_format::cTFETC2_EAC_R11: return "ETC2_EAC_R11";
+ case transcoder_texture_format::cTFETC2_EAC_RG11: return "ETC2_EAC_RG11";
+ default:
+ assert(0);
+ BASISU_DEVEL_ERROR("basis_get_basisu_texture_format: Invalid fmt\n");
+ break;
+ }
+ return "";
+ }
+
+ const char* basis_get_texture_type_name(basis_texture_type tex_type)
+ {
+ switch (tex_type)
+ {
+ case cBASISTexType2D: return "2D";
+ case cBASISTexType2DArray: return "2D array";
+ case cBASISTexTypeCubemapArray: return "cubemap array";
+ case cBASISTexTypeVideoFrames: return "video";
+ case cBASISTexTypeVolume: return "3D";
+ default:
+ assert(0);
+ BASISU_DEVEL_ERROR("basis_get_texture_type_name: Invalid tex_type\n");
+ break;
+ }
+ return "";
+ }
+
+ bool basis_transcoder_format_has_alpha(transcoder_texture_format fmt)
+ {
+ switch (fmt)
+ {
+ case transcoder_texture_format::cTFETC2_RGBA:
+ case transcoder_texture_format::cTFBC3_RGBA:
+ case transcoder_texture_format::cTFASTC_4x4_RGBA:
+ case transcoder_texture_format::cTFBC7_M5_RGBA:
+ case transcoder_texture_format::cTFPVRTC1_4_RGBA:
+ case transcoder_texture_format::cTFPVRTC2_4_RGBA:
+ case transcoder_texture_format::cTFATC_RGBA:
+ case transcoder_texture_format::cTFRGBA32:
+ case transcoder_texture_format::cTFRGBA4444:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ basisu::texture_format basis_get_basisu_texture_format(transcoder_texture_format fmt)
+ {
+ switch (fmt)
+ {
+ case transcoder_texture_format::cTFETC1_RGB: return basisu::texture_format::cETC1;
+ case transcoder_texture_format::cTFBC1_RGB: return basisu::texture_format::cBC1;
+ case transcoder_texture_format::cTFBC4_R: return basisu::texture_format::cBC4;
+ case transcoder_texture_format::cTFPVRTC1_4_RGB: return basisu::texture_format::cPVRTC1_4_RGB;
+ case transcoder_texture_format::cTFPVRTC1_4_RGBA: return basisu::texture_format::cPVRTC1_4_RGBA;
+ case transcoder_texture_format::cTFBC7_M6_RGB: return basisu::texture_format::cBC7;
+ case transcoder_texture_format::cTFBC7_M5_RGBA: return basisu::texture_format::cBC7;
+ case transcoder_texture_format::cTFETC2_RGBA: return basisu::texture_format::cETC2_RGBA;
+ case transcoder_texture_format::cTFBC3_RGBA: return basisu::texture_format::cBC3;
+ case transcoder_texture_format::cTFBC5_RG: return basisu::texture_format::cBC5;
+ case transcoder_texture_format::cTFASTC_4x4_RGBA: return basisu::texture_format::cASTC4x4;
+ case transcoder_texture_format::cTFATC_RGB: return basisu::texture_format::cATC_RGB;
+ case transcoder_texture_format::cTFATC_RGBA: return basisu::texture_format::cATC_RGBA_INTERPOLATED_ALPHA;
+ case transcoder_texture_format::cTFRGBA32: return basisu::texture_format::cRGBA32;
+ case transcoder_texture_format::cTFRGB565: return basisu::texture_format::cRGB565;
+ case transcoder_texture_format::cTFBGR565: return basisu::texture_format::cBGR565;
+ case transcoder_texture_format::cTFRGBA4444: return basisu::texture_format::cRGBA4444;
+ case transcoder_texture_format::cTFFXT1_RGB: return basisu::texture_format::cFXT1_RGB;
+ case transcoder_texture_format::cTFPVRTC2_4_RGB: return basisu::texture_format::cPVRTC2_4_RGBA;
+ case transcoder_texture_format::cTFPVRTC2_4_RGBA: return basisu::texture_format::cPVRTC2_4_RGBA;
+ case transcoder_texture_format::cTFETC2_EAC_R11: return basisu::texture_format::cETC2_R11_EAC;
+ case transcoder_texture_format::cTFETC2_EAC_RG11: return basisu::texture_format::cETC2_RG11_EAC;
+ default:
+ assert(0);
+ BASISU_DEVEL_ERROR("basis_get_basisu_texture_format: Invalid fmt\n");
+ break;
+ }
+ return basisu::texture_format::cInvalidTextureFormat;
+ }
+
+ bool basis_transcoder_format_is_uncompressed(transcoder_texture_format tex_type)
+ {
+ switch (tex_type)
+ {
+ case transcoder_texture_format::cTFRGBA32:
+ case transcoder_texture_format::cTFRGB565:
+ case transcoder_texture_format::cTFBGR565:
+ case transcoder_texture_format::cTFRGBA4444:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ bool basis_block_format_is_uncompressed(block_format tex_type)
+ {
+ switch (tex_type)
+ {
+ case block_format::cRGB32:
+ case block_format::cRGBA32:
+ case block_format::cA32:
+ case block_format::cRGB565:
+ case block_format::cBGR565:
+ case block_format::cRGBA4444_COLOR:
+ case block_format::cRGBA4444_ALPHA:
+ case block_format::cRGBA4444_COLOR_OPAQUE:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ uint32_t basis_get_uncompressed_bytes_per_pixel(transcoder_texture_format fmt)
+ {
+ switch (fmt)
+ {
+ case transcoder_texture_format::cTFRGBA32:
+ return sizeof(uint32_t);
+ case transcoder_texture_format::cTFRGB565:
+ case transcoder_texture_format::cTFBGR565:
+ case transcoder_texture_format::cTFRGBA4444:
+ return sizeof(uint16_t);
+ default:
+ break;
+ }
+ return 0;
+ }
+
+ uint32_t basis_get_block_width(transcoder_texture_format tex_type)
+ {
+ switch (tex_type)
+ {
+ case transcoder_texture_format::cTFFXT1_RGB:
+ return 8;
+ default:
+ break;
+ }
+ return 4;
+ }
+
+ uint32_t basis_get_block_height(transcoder_texture_format tex_type)
+ {
+ (void)tex_type;
+ return 4;
+ }
+
+ bool basis_is_format_supported(transcoder_texture_format tex_type)
+ {
+ switch (tex_type)
+ {
+ // ETC1 and uncompressed are always supported.
+ case transcoder_texture_format::cTFETC1_RGB:
+ case transcoder_texture_format::cTFRGBA32:
+ case transcoder_texture_format::cTFRGB565:
+ case transcoder_texture_format::cTFBGR565:
+ case transcoder_texture_format::cTFRGBA4444:
+ return true;
+#if BASISD_SUPPORT_DXT1
+ case transcoder_texture_format::cTFBC1_RGB:
+ return true;
+#endif
+#if BASISD_SUPPORT_DXT5A
+ case transcoder_texture_format::cTFBC4_R:
+ case transcoder_texture_format::cTFBC5_RG:
+ return true;
+#endif
+#if BASISD_SUPPORT_DXT1 && BASISD_SUPPORT_DXT5A
+ case transcoder_texture_format::cTFBC3_RGBA:
+ return true;
+#endif
+#if BASISD_SUPPORT_PVRTC1
+ case transcoder_texture_format::cTFPVRTC1_4_RGB:
+ case transcoder_texture_format::cTFPVRTC1_4_RGBA:
+ return true;
+#endif
+#if BASISD_SUPPORT_BC7_MODE6_OPAQUE_ONLY
+ case transcoder_texture_format::cTFBC7_M6_RGB:
+ return true;
+#endif
+#if BASISD_SUPPORT_BC7_MODE5
+ case transcoder_texture_format::cTFBC7_M5_RGBA:
+ return true;
+#endif
+#if BASISD_SUPPORT_ETC2_EAC_A8
+ case transcoder_texture_format::cTFETC2_RGBA:
+ return true;
+#endif
+#if BASISD_SUPPORT_ASTC
+ case transcoder_texture_format::cTFASTC_4x4_RGBA:
+ return true;
+#endif
+#if BASISD_SUPPORT_ATC
+ case transcoder_texture_format::cTFATC_RGB:
+ case transcoder_texture_format::cTFATC_RGBA:
+ return true;
+#endif
+#if BASISD_SUPPORT_FXT1
+ case transcoder_texture_format::cTFFXT1_RGB:
+ return true;
+#endif
+#if BASISD_SUPPORT_PVRTC2
+ case transcoder_texture_format::cTFPVRTC2_4_RGB:
+ case transcoder_texture_format::cTFPVRTC2_4_RGBA:
+ return true;
+#endif
+#if BASISD_SUPPORT_ETC2_EAC_RG11
+ case transcoder_texture_format::cTFETC2_EAC_R11:
+ case transcoder_texture_format::cTFETC2_EAC_RG11:
+ return true;
+#endif
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+} // namespace basist
+
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder.h b/thirdparty/basis_universal/transcoder/basisu_transcoder.h
new file mode 100644
index 0000000000..770c64122d
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder.h
@@ -0,0 +1,377 @@
+// basisu_transcoder.h
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+// Set BASISU_DEVEL_MESSAGES to 1 to enable debug printf()'s whenever an error occurs, for easier debugging during development.
+//#define BASISU_DEVEL_MESSAGES 1
+
+#include "basisu_transcoder_internal.h"
+#include "basisu_global_selector_palette.h"
+#include "basisu_file_headers.h"
+
+namespace basist
+{
+ // High-level composite texture formats supported by the transcoder.
+ // Each of these texture formats directly correspond to OpenGL/D3D/Vulkan etc. texture formats.
+ // Notes:
+ // - If you specify a texture format that supports alpha, but the .basis file doesn't have alpha, the transcoder will automatically output a
+ // fully opaque (255) alpha channel.
+ // - The PVRTC1 texture formats only support power of 2 dimension .basis files, but this may be relaxed in a future version.
+ // - The PVRTC1 transcoders are real-time encoders, so don't expect the highest quality. We may add a slower encoder with improved quality.
+ // - These enums must be kept in sync with Javascript code that calls the transcoder.
+ enum class transcoder_texture_format
+ {
+ // Compressed formats
+
+ // ETC1-2
+ cTFETC1_RGB = 0, // Opaque only, returns RGB or alpha data if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
+ cTFETC2_RGBA = 1, // Opaque+alpha, ETC2_EAC_A8 block followed by a ETC1 block, alpha channel will be opaque for opaque .basis files
+
+ // BC1-5, BC7 (desktop, some mobile devices)
+ cTFBC1_RGB = 2, // Opaque only, no punchthrough alpha support yet, transcodes alpha slice if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
+ cTFBC3_RGBA = 3, // Opaque+alpha, BC4 followed by a BC1 block, alpha channel will be opaque for opaque .basis files
+ cTFBC4_R = 4, // Red only, alpha slice is transcoded to output if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
+ cTFBC5_RG = 5, // XY: Two BC4 blocks, X=R and Y=Alpha, .basis file should have alpha data (if not Y will be all 255's)
+ cTFBC7_M6_RGB = 6, // Opaque only, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified. Highest quality of all the non-ETC1 formats.
+ cTFBC7_M5_RGBA = 7, // Opaque+alpha, alpha channel will be opaque for opaque .basis files
+
+ // PVRTC1 4bpp (mobile, PowerVR devices)
+ cTFPVRTC1_4_RGB = 8, // Opaque only, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified, nearly lowest quality of any texture format.
+ cTFPVRTC1_4_RGBA = 9, // Opaque+alpha, most useful for simple opacity maps. If .basis file doens't have alpha cTFPVRTC1_4_RGB will be used instead. Lowest quality of any supported texture format.
+
+ // ASTC (mobile, Intel devices, hopefully all desktop GPU's one day)
+ cTFASTC_4x4_RGBA = 10, // Opaque+alpha, ASTC 4x4, alpha channel will be opaque for opaque .basis files. Transcoder uses RGB/RGBA/L/LA modes, void extent, and up to two ([0,47] and [0,255]) endpoint precisions.
+
+ // ATC (mobile, Adreno devices, this is a niche format)
+ cTFATC_RGB = 11, // Opaque, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified. ATI ATC (GL_ATC_RGB_AMD)
+ cTFATC_RGBA = 12, // Opaque+alpha, alpha channel will be opaque for opaque .basis files. ATI ATC (GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD)
+
+ // FXT1 (desktop, Intel devices, this is a super obscure format)
+ cTFFXT1_RGB = 17, // Opaque only, uses exclusively CC_MIXED blocks. Notable for having a 8x4 block size. GL_3DFX_texture_compression_FXT1 is supported on Intel integrated GPU's (such as HD 630).
+ // Punch-through alpha is relatively easy to support, but full alpha is harder. This format is only here for completeness so opaque-only is fine for now.
+ // See the BASISU_USE_ORIGINAL_3DFX_FXT1_ENCODING macro in basisu_transcoder_internal.h.
+
+ cTFPVRTC2_4_RGB = 18, // Opaque-only, almost BC1 quality, much faster to transcode and supports arbitrary texture dimensions (unlike PVRTC1 RGB).
+ cTFPVRTC2_4_RGBA = 19, // Opaque+alpha, slower to encode than cTFPVRTC2_4_RGB. Premultiplied alpha is highly recommended, otherwise the color channel can leak into the alpha channel on transparent blocks.
+
+ cTFETC2_EAC_R11 = 20, // R only (ETC2 EAC R11 unsigned)
+ cTFETC2_EAC_RG11 = 21, // RG only (ETC2 EAC RG11 unsigned), R=opaque.r, G=alpha - for tangent space normal maps
+
+ // Uncompressed (raw pixel) formats
+ cTFRGBA32 = 13, // 32bpp RGBA image stored in raster (not block) order in memory, R is first byte, A is last byte.
+ cTFRGB565 = 14, // 166pp RGB image stored in raster (not block) order in memory, R at bit position 11
+ cTFBGR565 = 15, // 16bpp RGB image stored in raster (not block) order in memory, R at bit position 0
+ cTFRGBA4444 = 16, // 16bpp RGBA image stored in raster (not block) order in memory, R at bit position 12, A at bit position 0
+
+ cTFTotalTextureFormats = 22,
+
+ // Old enums for compatibility with code compiled against previous versions
+ cTFETC1 = cTFETC1_RGB,
+ cTFETC2 = cTFETC2_RGBA,
+ cTFBC1 = cTFBC1_RGB,
+ cTFBC3 = cTFBC3_RGBA,
+ cTFBC4 = cTFBC4_R,
+ cTFBC5 = cTFBC5_RG,
+ cTFBC7_M6_OPAQUE_ONLY = cTFBC7_M6_RGB,
+ cTFBC7_M5 = cTFBC7_M5_RGBA,
+ cTFASTC_4x4 = cTFASTC_4x4_RGBA,
+ cTFATC_RGBA_INTERPOLATED_ALPHA = cTFATC_RGBA,
+ };
+
+ uint32_t basis_get_bytes_per_block(transcoder_texture_format fmt);
+ const char* basis_get_format_name(transcoder_texture_format fmt);
+ bool basis_transcoder_format_has_alpha(transcoder_texture_format fmt);
+ basisu::texture_format basis_get_basisu_texture_format(transcoder_texture_format fmt);
+ const char* basis_get_texture_type_name(basis_texture_type tex_type);
+
+ bool basis_transcoder_format_is_uncompressed(transcoder_texture_format tex_type);
+ uint32_t basis_get_uncompressed_bytes_per_pixel(transcoder_texture_format fmt);
+
+ uint32_t basis_get_block_width(transcoder_texture_format tex_type);
+ uint32_t basis_get_block_height(transcoder_texture_format tex_type);
+
+ // Returns true if the specified format was enabled at compile time.
+ bool basis_is_format_supported(transcoder_texture_format tex_type);
+
+ class basisu_transcoder;
+
+ // This struct holds all state used during transcoding. For video, it needs to persist between image transcodes (it holds the previous frame).
+ // For threading you can use one state per thread.
+ struct basisu_transcoder_state
+ {
+ struct block_preds
+ {
+ uint16_t m_endpoint_index;
+ uint8_t m_pred_bits;
+ };
+
+ std::vector<block_preds> m_block_endpoint_preds[2];
+
+ enum { cMaxPrevFrameLevels = 16 };
+ std::vector<uint32_t> m_prev_frame_indices[2][cMaxPrevFrameLevels]; // [alpha_flag][level_index]
+ };
+
+ // Low-level helper class that does the actual transcoding.
+ class basisu_lowlevel_transcoder
+ {
+ friend class basisu_transcoder;
+
+ public:
+ basisu_lowlevel_transcoder(const basist::etc1_global_selector_codebook *pGlobal_sel_codebook);
+
+ bool decode_palettes(
+ uint32_t num_endpoints, const uint8_t *pEndpoints_data, uint32_t endpoints_data_size,
+ uint32_t num_selectors, const uint8_t *pSelectors_data, uint32_t selectors_data_size);
+
+ bool decode_tables(const uint8_t *pTable_data, uint32_t table_data_size);
+
+ bool transcode_slice(void *pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t *pImage_data, uint32_t image_data_size, block_format fmt,
+ uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const basis_file_header &header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels = 0,
+ basisu_transcoder_state *pState = nullptr, bool astc_transcode_alpha = false, void* pAlpha_blocks = nullptr, uint32_t output_rows_in_pixels = 0);
+
+ private:
+ typedef std::vector<endpoint> endpoint_vec;
+ endpoint_vec m_endpoints;
+
+ typedef std::vector<selector> selector_vec;
+ selector_vec m_selectors;
+
+ const etc1_global_selector_codebook *m_pGlobal_sel_codebook;
+
+ huffman_decoding_table m_endpoint_pred_model, m_delta_endpoint_model, m_selector_model, m_selector_history_buf_rle_model;
+
+ uint32_t m_selector_history_buf_size;
+
+ basisu_transcoder_state m_def_state;
+ };
+
+ struct basisu_slice_info
+ {
+ uint32_t m_orig_width;
+ uint32_t m_orig_height;
+
+ uint32_t m_width;
+ uint32_t m_height;
+
+ uint32_t m_num_blocks_x;
+ uint32_t m_num_blocks_y;
+ uint32_t m_total_blocks;
+
+ uint32_t m_compressed_size;
+
+ uint32_t m_slice_index; // the slice index in the .basis file
+ uint32_t m_image_index; // the source image index originally provided to the encoder
+ uint32_t m_level_index; // the mipmap level within this image
+
+ uint32_t m_unpacked_slice_crc16;
+
+ bool m_alpha_flag; // true if the slice has alpha data
+ bool m_iframe_flag; // true if the slice is an I-Frame
+ };
+
+ typedef std::vector<basisu_slice_info> basisu_slice_info_vec;
+
+ struct basisu_image_info
+ {
+ uint32_t m_image_index;
+ uint32_t m_total_levels;
+
+ uint32_t m_orig_width;
+ uint32_t m_orig_height;
+
+ uint32_t m_width;
+ uint32_t m_height;
+
+ uint32_t m_num_blocks_x;
+ uint32_t m_num_blocks_y;
+ uint32_t m_total_blocks;
+
+ uint32_t m_first_slice_index;
+
+ bool m_alpha_flag; // true if the image has alpha data
+ bool m_iframe_flag; // true if the image is an I-Frame
+ };
+
+ struct basisu_image_level_info
+ {
+ uint32_t m_image_index;
+ uint32_t m_level_index;
+
+ uint32_t m_orig_width;
+ uint32_t m_orig_height;
+
+ uint32_t m_width;
+ uint32_t m_height;
+
+ uint32_t m_num_blocks_x;
+ uint32_t m_num_blocks_y;
+ uint32_t m_total_blocks;
+
+ uint32_t m_first_slice_index;
+
+ bool m_alpha_flag; // true if the image has alpha data
+ bool m_iframe_flag; // true if the image is an I-Frame
+ };
+
+ struct basisu_file_info
+ {
+ uint32_t m_version;
+ uint32_t m_total_header_size;
+
+ uint32_t m_total_selectors;
+ uint32_t m_selector_codebook_size;
+
+ uint32_t m_total_endpoints;
+ uint32_t m_endpoint_codebook_size;
+
+ uint32_t m_tables_size;
+ uint32_t m_slices_size;
+
+ basis_texture_type m_tex_type;
+ uint32_t m_us_per_frame;
+
+ // Low-level slice information (1 slice per image for color-only basis files, 2 for alpha basis files)
+ basisu_slice_info_vec m_slice_info;
+
+ uint32_t m_total_images; // total # of images
+ std::vector<uint32_t> m_image_mipmap_levels; // the # of mipmap levels for each image
+
+ uint32_t m_userdata0;
+ uint32_t m_userdata1;
+
+ bool m_etc1s; // always true for basis universal
+ bool m_y_flipped; // true if the image was Y flipped
+ bool m_has_alpha_slices; // true if the texture has alpha slices (even slices RGB, odd slices alpha)
+ };
+
+ // High-level transcoder class which accepts .basis file data and allows the caller to query information about the file and transcode image levels to various texture formats.
+ // If you're just starting out this is the class you care about.
+ class basisu_transcoder
+ {
+ basisu_transcoder(basisu_transcoder&);
+ basisu_transcoder& operator= (const basisu_transcoder&);
+
+ public:
+ basisu_transcoder(const etc1_global_selector_codebook *pGlobal_sel_codebook);
+
+ // Validates the .basis file. This computes a crc16 over the entire file, so it's slow.
+ bool validate_file_checksums(const void *pData, uint32_t data_size, bool full_validation) const;
+
+ // Quick header validation - no crc16 checks.
+ bool validate_header(const void *pData, uint32_t data_size) const;
+
+ basis_texture_type get_texture_type(const void *pData, uint32_t data_size) const;
+ bool get_userdata(const void *pData, uint32_t data_size, uint32_t &userdata0, uint32_t &userdata1) const;
+
+ // Returns the total number of images in the basis file (always 1 or more).
+ // Note that the number of mipmap levels for each image may differ, and that images may have different resolutions.
+ uint32_t get_total_images(const void *pData, uint32_t data_size) const;
+
+ // Returns the number of mipmap levels in an image.
+ uint32_t get_total_image_levels(const void *pData, uint32_t data_size, uint32_t image_index) const;
+
+ // Returns basic information about an image. Note that orig_width/orig_height may not be a multiple of 4.
+ bool get_image_level_desc(const void *pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, uint32_t &orig_width, uint32_t &orig_height, uint32_t &total_blocks) const;
+
+ // Returns information about the specified image.
+ bool get_image_info(const void *pData, uint32_t data_size, basisu_image_info &image_info, uint32_t image_index) const;
+
+ // Returns information about the specified image's mipmap level.
+ bool get_image_level_info(const void *pData, uint32_t data_size, basisu_image_level_info &level_info, uint32_t image_index, uint32_t level_index) const;
+
+ // Get a description of the basis file and low-level information about each slice.
+ bool get_file_info(const void *pData, uint32_t data_size, basisu_file_info &file_info) const;
+
+ // start_transcoding() must be called before calling transcode_slice() or transcode_image_level().
+ // This decompresses the selector/endpoint codebooks, so ideally you would only call this once per .basis file (not each image/mipmap level).
+ bool start_transcoding(const void *pData, uint32_t data_size) const;
+
+ // Returns true if start_transcoding() has been called.
+ bool get_ready_to_transcode() const { return m_lowlevel_decoder.m_endpoints.size() > 0; }
+
+ enum
+ {
+ // PVRTC1: decode non-pow2 ETC1S texture level to the next larger power of 2 (not implemented yet, but we're going to support it). Ignored if the slice's dimensions are already a power of 2.
+ cDecodeFlagsPVRTCDecodeToNextPow2 = 2,
+
+ // When decoding to an opaque texture format, if the basis file has alpha, decode the alpha slice instead of the color slice to the output texture format.
+ // This is primarily to allow decoding of textures with alpha to multiple ETC1 textures (one for color, another for alpha).
+ cDecodeFlagsTranscodeAlphaDataToOpaqueFormats = 4,
+
+ // Forbid usage of BC1 3 color blocks (we don't support BC1 punchthrough alpha yet).
+ // This flag is used internally when decoding to BC3.
+ cDecodeFlagsBC1ForbidThreeColorBlocks = 8,
+
+ // The output buffer contains alpha endpoint/selector indices.
+ // Used internally when decoding formats like ASTC that require both color and alpha data to be available when transcoding to the output format.
+ cDecodeFlagsOutputHasAlphaIndices = 16
+ };
+
+ // transcode_image_level() decodes a single mipmap level from the .basis file to any of the supported output texture formats.
+ // It'll first find the slice(s) to transcode, then call transcode_slice() one or two times to decode both the color and alpha texture data (or RG texture data from two slices for BC5).
+ // If the .basis file doesn't have alpha slices, the output alpha blocks will be set to fully opaque (all 255's).
+ // Currently, to decode to PVRTC1 the basis texture's dimensions in pixels must be a power of 2, due to PVRTC1 format requirements.
+ // output_blocks_buf_size_in_blocks_or_pixels should be at least the image level's total_blocks (num_blocks_x * num_blocks_y), or the total number of output pixels if fmt==cTFRGBA32.
+ // output_row_pitch_in_blocks_or_pixels: Number of blocks or pixels per row. If 0, the transcoder uses the slice's num_blocks_x or orig_width (NOT num_blocks_x * 4). Ignored for PVRTC1 (due to texture swizzling).
+ // output_rows_in_pixels: Ignored unless fmt is cRGBA32. The total number of output rows in the output buffer. If 0, the transcoder assumes the slice's orig_height (NOT num_blocks_y * 4).
+ // Notes:
+ // - basisu_transcoder_init() must have been called first to initialize the transcoder lookup tables before calling this function.
+ // - This method assumes the output texture buffer is readable. In some cases to handle alpha, the transcoder will write temporary data to the output texture in
+ // a first pass, which will be read in a second pass.
+ bool transcode_image_level(
+ const void *pData, uint32_t data_size,
+ uint32_t image_index, uint32_t level_index,
+ void *pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
+ transcoder_texture_format fmt,
+ uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, basisu_transcoder_state *pState = nullptr, uint32_t output_rows_in_pixels = 0) const;
+
+ // Finds the basis slice corresponding to the specified image/level/alpha params, or -1 if the slice can't be found.
+ int find_slice(const void *pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, bool alpha_data) const;
+
+ // transcode_slice() decodes a single slice from the .basis file. It's a low-level API - most likely you want to use transcode_image_level().
+ // This is a low-level API, and will be needed to be called multiple times to decode some texture formats (like BC3, BC5, or ETC2).
+ // output_blocks_buf_size_in_blocks_or_pixels is just used for verification to make sure the output buffer is large enough.
+ // output_blocks_buf_size_in_blocks_or_pixels should be at least the image level's total_blocks (num_blocks_x * num_blocks_y), or the total number of output pixels if fmt==cTFRGBA32.
+ // output_block_stride_in_bytes: Number of bytes between each output block.
+ // output_row_pitch_in_blocks_or_pixels: Number of blocks or pixels per row. If 0, the transcoder uses the slice's num_blocks_x or orig_width (NOT num_blocks_x * 4). Ignored for PVRTC1 (due to texture swizzling).
+ // output_rows_in_pixels: Ignored unless fmt is cRGBA32. The total number of output rows in the output buffer. If 0, the transcoder assumes the slice's orig_height (NOT num_blocks_y * 4).
+ // Notes:
+ // - basisu_transcoder_init() must have been called first to initialize the transcoder lookup tables before calling this function.
+ bool transcode_slice(const void *pData, uint32_t data_size, uint32_t slice_index,
+ void *pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
+ block_format fmt, uint32_t output_block_stride_in_bytes, uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, basisu_transcoder_state * pState = nullptr, void* pAlpha_blocks = nullptr, uint32_t output_rows_in_pixels = 0) const;
+
+ private:
+ mutable basisu_lowlevel_transcoder m_lowlevel_decoder;
+
+ int find_first_slice_index(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index) const;
+
+ bool validate_header_quick(const void* pData, uint32_t data_size) const;
+ };
+
+ // basisu_transcoder_init() must be called before a .basis file can be transcoded.
+ void basisu_transcoder_init();
+
+ enum debug_flags_t
+ {
+ cDebugFlagVisCRs = 1,
+ cDebugFlagVisBC1Sels = 2,
+ cDebugFlagVisBC1Endpoints = 4
+ };
+ uint32_t get_debug_flags();
+ void set_debug_flags(uint32_t f);
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_internal.h b/thirdparty/basis_universal/transcoder/basisu_transcoder_internal.h
new file mode 100644
index 0000000000..a9c6823d92
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_internal.h
@@ -0,0 +1,754 @@
+// basisu_transcoder_internal.h - Universal texture format transcoder library.
+// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
+//
+// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#ifdef _MSC_VER
+#pragma warning (disable: 4127) // conditional expression is constant
+#endif
+
+#define BASISD_LIB_VERSION 107
+#define BASISD_VERSION_STRING "01.11"
+
+#ifdef _DEBUG
+#define BASISD_BUILD_DEBUG
+#else
+#define BASISD_BUILD_RELEASE
+#endif
+
+#include "basisu.h"
+
+#define BASISD_znew (z = 36969 * (z & 65535) + (z >> 16))
+
+namespace basisu
+{
+ extern bool g_debug_printf;
+}
+
+namespace basist
+{
+ // Low-level formats directly supported by the transcoder (other supported texture formats are combinations of these low-level block formats).
+ // You probably don't care about these enum's unless you are going pretty low-level and calling the transcoder to decode individual slices.
+ enum class block_format
+ {
+ cETC1, // ETC1S RGB
+ cBC1, // DXT1 RGB
+ cBC4, // DXT5A (alpha block only)
+ cPVRTC1_4_RGB, // opaque-only PVRTC1 4bpp
+ cPVRTC1_4_RGBA, // PVRTC1 4bpp RGBA
+ cBC7_M6_OPAQUE_ONLY, // RGB BC7 mode 6
+ cBC7_M5_COLOR, // RGB BC7 mode 5 color (writes an opaque mode 5 block)
+ cBC7_M5_ALPHA, // alpha portion of BC7 mode 5 (cBC7_M5_COLOR output data must have been written to the output buffer first to set the mode/rot fields etc.)
+ cETC2_EAC_A8, // alpha block of ETC2 EAC (first 8 bytes of the 16-bit ETC2 EAC RGBA format)
+ cASTC_4x4, // ASTC 4x4 (either color-only or color+alpha). Note that the transcoder always currently assumes sRGB is not enabled when outputting ASTC
+ // data. If you use a sRGB ASTC format you'll get ~1 LSB of additional error, because of the different way ASTC decoders scale 8-bit endpoints to 16-bits during unpacking.
+ cATC_RGB,
+ cATC_RGBA_INTERPOLATED_ALPHA,
+ cFXT1_RGB, // Opaque-only, has oddball 8x4 pixel block size
+
+ cIndices, // Used internally: Write 16-bit endpoint and selector indices directly to output (output block must be at least 32-bits)
+
+ cRGB32, // Writes RGB components to 32bpp output pixels
+ cRGBA32, // Writes RGB255 components to 32bpp output pixels
+ cA32, // Writes alpha component to 32bpp output pixels
+
+ cRGB565,
+ cBGR565,
+
+ cRGBA4444_COLOR,
+ cRGBA4444_ALPHA,
+ cRGBA4444_COLOR_OPAQUE,
+
+ cPVRTC2_4_RGB,
+ cPVRTC2_4_RGBA,
+
+ cETC2_EAC_R11,
+
+ cTotalBlockFormats
+ };
+
+ const int COLOR5_PAL0_PREV_HI = 9, COLOR5_PAL0_DELTA_LO = -9, COLOR5_PAL0_DELTA_HI = 31;
+ const int COLOR5_PAL1_PREV_HI = 21, COLOR5_PAL1_DELTA_LO = -21, COLOR5_PAL1_DELTA_HI = 21;
+ const int COLOR5_PAL2_PREV_HI = 31, COLOR5_PAL2_DELTA_LO = -31, COLOR5_PAL2_DELTA_HI = 9;
+ const int COLOR5_PAL_MIN_DELTA_B_RUNLEN = 3, COLOR5_PAL_DELTA_5_RUNLEN_VLC_BITS = 3;
+
+ const uint32_t ENDPOINT_PRED_TOTAL_SYMBOLS = (4 * 4 * 4 * 4) + 1;
+ const uint32_t ENDPOINT_PRED_REPEAT_LAST_SYMBOL = ENDPOINT_PRED_TOTAL_SYMBOLS - 1;
+ const uint32_t ENDPOINT_PRED_MIN_REPEAT_COUNT = 3;
+ const uint32_t ENDPOINT_PRED_COUNT_VLC_BITS = 4;
+
+ const uint32_t NUM_ENDPOINT_PREDS = 3;// BASISU_ARRAY_SIZE(g_endpoint_preds);
+ const uint32_t CR_ENDPOINT_PRED_INDEX = NUM_ENDPOINT_PREDS - 1;
+ const uint32_t NO_ENDPOINT_PRED_INDEX = 3;//NUM_ENDPOINT_PREDS;
+ const uint32_t MAX_SELECTOR_HISTORY_BUF_SIZE = 64;
+ const uint32_t SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH = 3;
+ const uint32_t SELECTOR_HISTORY_BUF_RLE_COUNT_BITS = 6;
+ const uint32_t SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL = (1 << SELECTOR_HISTORY_BUF_RLE_COUNT_BITS);
+
+ uint16_t crc16(const void *r, size_t size, uint16_t crc);
+
+ class huffman_decoding_table
+ {
+ friend class bitwise_decoder;
+
+ public:
+ huffman_decoding_table()
+ {
+ }
+
+ void clear()
+ {
+ basisu::clear_vector(m_code_sizes);
+ basisu::clear_vector(m_lookup);
+ basisu::clear_vector(m_tree);
+ }
+
+ bool init(uint32_t total_syms, const uint8_t *pCode_sizes)
+ {
+ if (!total_syms)
+ {
+ clear();
+ return true;
+ }
+
+ m_code_sizes.resize(total_syms);
+ memcpy(&m_code_sizes[0], pCode_sizes, total_syms);
+
+ m_lookup.resize(0);
+ m_lookup.resize(basisu::cHuffmanFastLookupSize);
+
+ m_tree.resize(0);
+ m_tree.resize(total_syms * 2);
+
+ uint32_t syms_using_codesize[basisu::cHuffmanMaxSupportedInternalCodeSize + 1];
+ basisu::clear_obj(syms_using_codesize);
+ for (uint32_t i = 0; i < total_syms; i++)
+ {
+ if (pCode_sizes[i] > basisu::cHuffmanMaxSupportedInternalCodeSize)
+ return false;
+ syms_using_codesize[pCode_sizes[i]]++;
+ }
+
+ uint32_t next_code[basisu::cHuffmanMaxSupportedInternalCodeSize + 1];
+ next_code[0] = next_code[1] = 0;
+
+ uint32_t used_syms = 0, total = 0;
+ for (uint32_t i = 1; i < basisu::cHuffmanMaxSupportedInternalCodeSize; i++)
+ {
+ used_syms += syms_using_codesize[i];
+ next_code[i + 1] = (total = ((total + syms_using_codesize[i]) << 1));
+ }
+
+ if (((1U << basisu::cHuffmanMaxSupportedInternalCodeSize) != total) && (used_syms > 1U))
+ return false;
+
+ for (int tree_next = -1, sym_index = 0; sym_index < (int)total_syms; ++sym_index)
+ {
+ uint32_t rev_code = 0, l, cur_code, code_size = pCode_sizes[sym_index];
+ if (!code_size)
+ continue;
+
+ cur_code = next_code[code_size]++;
+
+ for (l = code_size; l > 0; l--, cur_code >>= 1)
+ rev_code = (rev_code << 1) | (cur_code & 1);
+
+ if (code_size <= basisu::cHuffmanFastLookupBits)
+ {
+ uint32_t k = (code_size << 16) | sym_index;
+ while (rev_code < basisu::cHuffmanFastLookupSize)
+ {
+ if (m_lookup[rev_code] != 0)
+ {
+ // Supplied codesizes can't create a valid prefix code.
+ return false;
+ }
+
+ m_lookup[rev_code] = k;
+ rev_code += (1 << code_size);
+ }
+ continue;
+ }
+
+ int tree_cur;
+ if (0 == (tree_cur = m_lookup[rev_code & (basisu::cHuffmanFastLookupSize - 1)]))
+ {
+ const uint32_t idx = rev_code & (basisu::cHuffmanFastLookupSize - 1);
+ if (m_lookup[idx] != 0)
+ {
+ // Supplied codesizes can't create a valid prefix code.
+ return false;
+ }
+
+ m_lookup[idx] = tree_next;
+ tree_cur = tree_next;
+ tree_next -= 2;
+ }
+
+ if (tree_cur >= 0)
+ {
+ // Supplied codesizes can't create a valid prefix code.
+ return false;
+ }
+
+ rev_code >>= (basisu::cHuffmanFastLookupBits - 1);
+
+ for (int j = code_size; j > (basisu::cHuffmanFastLookupBits + 1); j--)
+ {
+ tree_cur -= ((rev_code >>= 1) & 1);
+
+ const int idx = -tree_cur - 1;
+ if (idx < 0)
+ return false;
+ else if (idx >= (int)m_tree.size())
+ m_tree.resize(idx + 1);
+
+ if (!m_tree[idx])
+ {
+ m_tree[idx] = (int16_t)tree_next;
+ tree_cur = tree_next;
+ tree_next -= 2;
+ }
+ else
+ {
+ tree_cur = m_tree[idx];
+ if (tree_cur >= 0)
+ {
+ // Supplied codesizes can't create a valid prefix code.
+ return false;
+ }
+ }
+ }
+
+ tree_cur -= ((rev_code >>= 1) & 1);
+
+ const int idx = -tree_cur - 1;
+ if (idx < 0)
+ return false;
+ else if (idx >= (int)m_tree.size())
+ m_tree.resize(idx + 1);
+
+ if (m_tree[idx] != 0)
+ {
+ // Supplied codesizes can't create a valid prefix code.
+ return false;
+ }
+
+ m_tree[idx] = (int16_t)sym_index;
+ }
+
+ return true;
+ }
+
+ const basisu::uint8_vec &get_code_sizes() const { return m_code_sizes; }
+
+ bool is_valid() const { return m_code_sizes.size() > 0; }
+
+ private:
+ basisu::uint8_vec m_code_sizes;
+ basisu::int_vec m_lookup;
+ basisu::int16_vec m_tree;
+ };
+
+ class bitwise_decoder
+ {
+ public:
+ bitwise_decoder() :
+ m_buf_size(0),
+ m_pBuf(nullptr),
+ m_pBuf_start(nullptr),
+ m_pBuf_end(nullptr),
+ m_bit_buf(0),
+ m_bit_buf_size(0)
+ {
+ }
+
+ void clear()
+ {
+ m_buf_size = 0;
+ m_pBuf = nullptr;
+ m_pBuf_start = nullptr;
+ m_pBuf_end = nullptr;
+ m_bit_buf = 0;
+ m_bit_buf_size = 0;
+ }
+
+ bool init(const uint8_t *pBuf, uint32_t buf_size)
+ {
+ if ((!pBuf) && (buf_size))
+ return false;
+
+ m_buf_size = buf_size;
+ m_pBuf = pBuf;
+ m_pBuf_start = pBuf;
+ m_pBuf_end = pBuf + buf_size;
+ m_bit_buf = 0;
+ m_bit_buf_size = 0;
+ return true;
+ }
+
+ void stop()
+ {
+ }
+
+ inline uint32_t peek_bits(uint32_t num_bits)
+ {
+ if (!num_bits)
+ return 0;
+
+ assert(num_bits <= 25);
+
+ while (m_bit_buf_size < num_bits)
+ {
+ uint32_t c = 0;
+ if (m_pBuf < m_pBuf_end)
+ c = *m_pBuf++;
+
+ m_bit_buf |= (c << m_bit_buf_size);
+ m_bit_buf_size += 8;
+ assert(m_bit_buf_size <= 32);
+ }
+
+ return m_bit_buf & ((1 << num_bits) - 1);
+ }
+
+ void remove_bits(uint32_t num_bits)
+ {
+ assert(m_bit_buf_size >= num_bits);
+
+ m_bit_buf >>= num_bits;
+ m_bit_buf_size -= num_bits;
+ }
+
+ uint32_t get_bits(uint32_t num_bits)
+ {
+ if (num_bits > 25)
+ {
+ assert(num_bits <= 32);
+
+ const uint32_t bits0 = peek_bits(25);
+ m_bit_buf >>= 25;
+ m_bit_buf_size -= 25;
+ num_bits -= 25;
+
+ const uint32_t bits = peek_bits(num_bits);
+ m_bit_buf >>= num_bits;
+ m_bit_buf_size -= num_bits;
+
+ return bits0 | (bits << 25);
+ }
+
+ const uint32_t bits = peek_bits(num_bits);
+
+ m_bit_buf >>= num_bits;
+ m_bit_buf_size -= num_bits;
+
+ return bits;
+ }
+
+ uint32_t decode_truncated_binary(uint32_t n)
+ {
+ assert(n >= 2);
+
+ const uint32_t k = basisu::floor_log2i(n);
+ const uint32_t u = (1 << (k + 1)) - n;
+
+ uint32_t result = get_bits(k);
+
+ if (result >= u)
+ result = ((result << 1) | get_bits(1)) - u;
+
+ return result;
+ }
+
+ uint32_t decode_rice(uint32_t m)
+ {
+ assert(m);
+
+ uint32_t q = 0;
+ for (;;)
+ {
+ uint32_t k = peek_bits(16);
+
+ uint32_t l = 0;
+ while (k & 1)
+ {
+ l++;
+ k >>= 1;
+ }
+
+ q += l;
+
+ remove_bits(l);
+
+ if (l < 16)
+ break;
+ }
+
+ return (q << m) + (get_bits(m + 1) >> 1);
+ }
+
+ inline uint32_t decode_vlc(uint32_t chunk_bits)
+ {
+ assert(chunk_bits);
+
+ const uint32_t chunk_size = 1 << chunk_bits;
+ const uint32_t chunk_mask = chunk_size - 1;
+
+ uint32_t v = 0;
+ uint32_t ofs = 0;
+
+ for ( ; ; )
+ {
+ uint32_t s = get_bits(chunk_bits + 1);
+ v |= ((s & chunk_mask) << ofs);
+ ofs += chunk_bits;
+
+ if ((s & chunk_size) == 0)
+ break;
+
+ if (ofs >= 32)
+ {
+ assert(0);
+ break;
+ }
+ }
+
+ return v;
+ }
+
+ inline uint32_t decode_huffman(const huffman_decoding_table &ct)
+ {
+ assert(ct.m_code_sizes.size());
+
+ while (m_bit_buf_size < 16)
+ {
+ uint32_t c = 0;
+ if (m_pBuf < m_pBuf_end)
+ c = *m_pBuf++;
+
+ m_bit_buf |= (c << m_bit_buf_size);
+ m_bit_buf_size += 8;
+ assert(m_bit_buf_size <= 32);
+ }
+
+ int code_len;
+
+ int sym;
+ if ((sym = ct.m_lookup[m_bit_buf & (basisu::cHuffmanFastLookupSize - 1)]) >= 0)
+ {
+ code_len = sym >> 16;
+ sym &= 0xFFFF;
+ }
+ else
+ {
+ code_len = basisu::cHuffmanFastLookupBits;
+ do
+ {
+ sym = ct.m_tree[~sym + ((m_bit_buf >> code_len++) & 1)]; // ~sym = -sym - 1
+ } while (sym < 0);
+ }
+
+ m_bit_buf >>= code_len;
+ m_bit_buf_size -= code_len;
+
+ return sym;
+ }
+
+ bool read_huffman_table(huffman_decoding_table &ct)
+ {
+ ct.clear();
+
+ const uint32_t total_used_syms = get_bits(basisu::cHuffmanMaxSymsLog2);
+
+ if (!total_used_syms)
+ return true;
+ if (total_used_syms > basisu::cHuffmanMaxSyms)
+ return false;
+
+ uint8_t code_length_code_sizes[basisu::cHuffmanTotalCodelengthCodes];
+ basisu::clear_obj(code_length_code_sizes);
+
+ const uint32_t num_codelength_codes = get_bits(5);
+ if ((num_codelength_codes < 1) || (num_codelength_codes > basisu::cHuffmanTotalCodelengthCodes))
+ return false;
+
+ for (uint32_t i = 0; i < num_codelength_codes; i++)
+ code_length_code_sizes[basisu::g_huffman_sorted_codelength_codes[i]] = static_cast<uint8_t>(get_bits(3));
+
+ huffman_decoding_table code_length_table;
+ if (!code_length_table.init(basisu::cHuffmanTotalCodelengthCodes, code_length_code_sizes))
+ return false;
+
+ if (!code_length_table.is_valid())
+ return false;
+
+ basisu::uint8_vec code_sizes(total_used_syms);
+
+ uint32_t cur = 0;
+ while (cur < total_used_syms)
+ {
+ int c = decode_huffman(code_length_table);
+
+ if (c <= 16)
+ code_sizes[cur++] = static_cast<uint8_t>(c);
+ else if (c == basisu::cHuffmanSmallZeroRunCode)
+ cur += get_bits(basisu::cHuffmanSmallZeroRunExtraBits) + basisu::cHuffmanSmallZeroRunSizeMin;
+ else if (c == basisu::cHuffmanBigZeroRunCode)
+ cur += get_bits(basisu::cHuffmanBigZeroRunExtraBits) + basisu::cHuffmanBigZeroRunSizeMin;
+ else
+ {
+ if (!cur)
+ return false;
+
+ uint32_t l;
+ if (c == basisu::cHuffmanSmallRepeatCode)
+ l = get_bits(basisu::cHuffmanSmallRepeatExtraBits) + basisu::cHuffmanSmallRepeatSizeMin;
+ else
+ l = get_bits(basisu::cHuffmanBigRepeatExtraBits) + basisu::cHuffmanBigRepeatSizeMin;
+
+ const uint8_t prev = code_sizes[cur - 1];
+ if (prev == 0)
+ return false;
+ do
+ {
+ if (cur >= total_used_syms)
+ return false;
+ code_sizes[cur++] = prev;
+ } while (--l > 0);
+ }
+ }
+
+ if (cur != total_used_syms)
+ return false;
+
+ return ct.init(total_used_syms, &code_sizes[0]);
+ }
+
+ private:
+ uint32_t m_buf_size;
+ const uint8_t *m_pBuf;
+ const uint8_t *m_pBuf_start;
+ const uint8_t *m_pBuf_end;
+
+ uint32_t m_bit_buf;
+ uint32_t m_bit_buf_size;
+ };
+
+ inline uint32_t basisd_rand(uint32_t seed)
+ {
+ if (!seed)
+ seed++;
+ uint32_t z = seed;
+ BASISD_znew;
+ return z;
+ }
+
+ // Returns random number in [0,limit). Max limit is 0xFFFF.
+ inline uint32_t basisd_urand(uint32_t& seed, uint32_t limit)
+ {
+ seed = basisd_rand(seed);
+ return (((seed ^ (seed >> 16)) & 0xFFFF) * limit) >> 16;
+ }
+
+ class approx_move_to_front
+ {
+ public:
+ approx_move_to_front(uint32_t n)
+ {
+ init(n);
+ }
+
+ void init(uint32_t n)
+ {
+ m_values.resize(n);
+ m_rover = n / 2;
+ }
+
+ const basisu::int_vec& get_values() const { return m_values; }
+ basisu::int_vec& get_values() { return m_values; }
+
+ uint32_t size() const { return (uint32_t)m_values.size(); }
+
+ const int& operator[] (uint32_t index) const { return m_values[index]; }
+ int operator[] (uint32_t index) { return m_values[index]; }
+
+ void add(int new_value)
+ {
+ m_values[m_rover++] = new_value;
+ if (m_rover == m_values.size())
+ m_rover = (uint32_t)m_values.size() / 2;
+ }
+
+ void use(uint32_t index)
+ {
+ if (index)
+ {
+ //std::swap(m_values[index / 2], m_values[index]);
+ int x = m_values[index / 2];
+ int y = m_values[index];
+ m_values[index / 2] = y;
+ m_values[index] = x;
+ }
+ }
+
+ // returns -1 if not found
+ int find(int value) const
+ {
+ for (uint32_t i = 0; i < m_values.size(); i++)
+ if (m_values[i] == value)
+ return i;
+ return -1;
+ }
+
+ void reset()
+ {
+ const uint32_t n = (uint32_t)m_values.size();
+
+ m_values.clear();
+
+ init(n);
+ }
+
+ private:
+ basisu::int_vec m_values;
+ uint32_t m_rover;
+ };
+
+ struct decoder_etc_block;
+
+ inline uint8_t clamp255(int32_t i)
+ {
+ return (uint8_t)((i & 0xFFFFFF00U) ? (~(i >> 31)) : i);
+ }
+
+ struct color32
+ {
+ union
+ {
+ struct
+ {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+ uint8_t a;
+ };
+
+ uint8_t c[4];
+
+ uint32_t m;
+ };
+
+ color32() { }
+
+ color32(uint32_t vr, uint32_t vg, uint32_t vb, uint32_t va) { set(vr, vg, vb, va); }
+
+ void set(uint32_t vr, uint32_t vg, uint32_t vb, uint32_t va) { c[0] = static_cast<uint8_t>(vr); c[1] = static_cast<uint8_t>(vg); c[2] = static_cast<uint8_t>(vb); c[3] = static_cast<uint8_t>(va); }
+
+ void set_clamped(int vr, int vg, int vb, int va) { c[0] = clamp255(vr); c[1] = clamp255(vg); c[2] = clamp255(vb); c[3] = clamp255(va); }
+
+ uint8_t operator[] (uint32_t idx) const { assert(idx < 4); return c[idx]; }
+ uint8_t &operator[] (uint32_t idx) { assert(idx < 4); return c[idx]; }
+
+ bool operator== (const color32&rhs) const { return m == rhs.m; }
+ };
+
+ struct endpoint
+ {
+ color32 m_color5;
+ uint8_t m_inten5;
+ };
+
+ struct selector
+ {
+ // Plain selectors (2-bits per value)
+ uint8_t m_selectors[4];
+
+ // ETC1 selectors
+ uint8_t m_bytes[4];
+
+ uint8_t m_lo_selector, m_hi_selector;
+ uint8_t m_num_unique_selectors;
+
+ void init_flags()
+ {
+ uint32_t hist[4] = { 0, 0, 0, 0 };
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint32_t s = get_selector(x, y);
+ hist[s]++;
+ }
+ }
+
+ m_lo_selector = 3;
+ m_hi_selector = 0;
+ m_num_unique_selectors = 0;
+
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ if (hist[i])
+ {
+ m_num_unique_selectors++;
+ if (i < m_lo_selector) m_lo_selector = static_cast<uint8_t>(i);
+ if (i > m_hi_selector) m_hi_selector = static_cast<uint8_t>(i);
+ }
+ }
+ }
+
+ // Returned selector value ranges from 0-3 and is a direct index into g_etc1_inten_tables.
+ inline uint32_t get_selector(uint32_t x, uint32_t y) const
+ {
+ assert((x < 4) && (y < 4));
+ return (m_selectors[y] >> (x * 2)) & 3;
+ }
+
+ void set_selector(uint32_t x, uint32_t y, uint32_t val)
+ {
+ static const uint8_t s_selector_index_to_etc1[4] = { 3, 2, 0, 1 };
+
+ assert((x | y | val) < 4);
+
+ m_selectors[y] &= ~(3 << (x * 2));
+ m_selectors[y] |= (val << (x * 2));
+
+ const uint32_t etc1_bit_index = x * 4 + y;
+
+ uint8_t *p = &m_bytes[3 - (etc1_bit_index >> 3)];
+
+ const uint32_t byte_bit_ofs = etc1_bit_index & 7;
+ const uint32_t mask = 1 << byte_bit_ofs;
+
+ const uint32_t etc1_val = s_selector_index_to_etc1[val];
+
+ const uint32_t lsb = etc1_val & 1;
+ const uint32_t msb = etc1_val >> 1;
+
+ p[0] &= ~mask;
+ p[0] |= (lsb << byte_bit_ofs);
+
+ p[-2] &= ~mask;
+ p[-2] |= (msb << byte_bit_ofs);
+ }
+ };
+
+ bool basis_block_format_is_uncompressed(block_format tex_type);
+
+} // namespace basist
+
+
+
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_astc.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_astc.inc
new file mode 100644
index 0000000000..7f38f4a863
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_astc.inc
@@ -0,0 +1,481 @@
+{0,2,18},{0,32,2},{0,16,10},{0,16,10},{0,32,35},{0,16,27},{0,16,11},{0,16,27},{0,16,36},{0,16,28},{0,2,18},{0,32,2},{0,16,10},{0,16,10},{16,0,35},{0,16,27},{0,16,11},{0,16,27},{32,0,35},{0,16,27},{0,16,1},{0,16,1},{0,16,1},{0,16,1},{0,16,2},{0,16,2},{0,16,2},{0,0,4},{0,0,4},{0,0,4},{0,16,1},
+{0,16,1},{0,16,1},{0,16,1},{0,16,2},{0,16,2},{0,16,2},{0,0,4},{16,0,2},{0,0,4},{0,2,18},{0,32,2},{0,16,10},{0,16,10},{0,2,18},{2,0,18},{0,16,10},{0,16,18},{2,0,18},{0,16,18},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{16,4,44},{16,18,27},{16,2,30},
+{16,2,30},{0,4,52},{0,18,20},{0,2,1},{0,32,27},{0,2,77},{0,32,36},{16,4,19},{16,18,2},{16,2,5},{16,2,5},{32,32,51},{0,18,20},{0,2,1},{0,32,27},{32,32,51},{0,32,27},{16,18,26},{16,18,26},{16,18,26},{16,32,27},{0,34,8},{0,2,1},{0,2,1},{0,32,2},{0,32,19},{0,32,11},{16,18,1},{16,18,1},{16,18,1},{16,32,2},{16,2,8},
+{0,2,1},{0,2,1},{0,32,2},{34,0,8},{0,32,2},{16,4,18},{16,18,1},{16,2,4},{0,2,0},{16,4,18},{4,16,18},{0,2,0},{0,32,26},{4,16,18},{0,32,26},{16,0,26},{16,0,26},{16,0,26},{16,0,26},{0,18,0},{0,18,0},{0,18,0},{0,32,1},{0,16,10},{0,16,10},{32,36,36},{32,4,20},{32,34,31},{32,18,28},{16,6,60},{32,34,31},{32,18,19},
+{16,18,28},{0,34,52},{0,18,22},{2,4,22},{2,34,6},{2,18,14},{2,18,14},{18,2,51},{32,34,22},{32,18,10},{0,18,18},{38,0,51},{0,18,18},{32,4,19},{32,4,19},{32,4,19},{32,18,19},{32,34,17},{32,18,10},{32,18,10},{32,2,13},{16,18,14},{16,2,8},{2,18,5},{2,18,5},{2,18,5},{2,18,5},{2,2,8},{32,18,1},{32,18,1},{32,2,4},{2,2,8},
+{32,2,4},{4,0,18},{32,4,2},{2,18,10},{0,34,9},{4,0,18},{8,0,18},{0,34,9},{0,18,18},{8,0,18},{0,18,18},{32,0,18},{32,0,18},{32,0,18},{32,0,18},{32,18,9},{32,18,9},{32,18,9},{32,2,9},{16,2,4},{16,2,4},{18,6,44},{18,20,26},{18,4,30},{18,4,30},{2,6,52},{2,20,21},{2,4,1},{2,34,27},{16,20,52},{32,34,27},{18,6,19},
+{18,20,1},{18,4,5},{18,4,5},{20,16,51},{2,20,21},{2,4,1},{2,34,27},{16,20,51},{2,34,27},{18,20,26},{18,20,26},{18,20,26},{18,34,27},{2,36,8},{2,4,1},{2,4,1},{2,34,2},{32,4,11},{32,34,2},{18,20,1},{18,20,1},{18,20,1},{18,34,2},{18,4,8},{2,4,1},{2,4,1},{2,34,2},{36,2,8},{2,34,2},{36,0,18},{18,20,0},{18,4,4},
+{2,4,0},{36,0,18},{6,18,18},{2,4,0},{0,34,26},{6,18,18},{0,34,26},{18,0,26},{18,0,26},{18,0,26},{18,0,26},{2,4,1},{2,4,1},{2,4,1},{2,34,1},{32,34,1},{32,34,1},{34,8,40},{34,6,21},{34,36,33},{34,36,28},{34,22,55},{34,36,25},{34,36,13},{34,20,31},{32,6,55},{18,20,20},{4,6,21},{4,36,5},{4,36,5},{4,20,11},{22,0,51},
+{34,36,21},{34,36,9},{2,20,19},{32,6,51},{2,20,19},{34,6,21},{34,6,21},{34,6,21},{34,20,21},{34,6,14},{34,20,6},{34,20,6},{34,4,14},{18,20,11},{18,20,11},{4,36,1},{4,36,1},{4,36,1},{4,20,2},{2,24,8},{34,20,2},{34,20,2},{4,4,10},{28,0,8},{4,4,10},{22,16,18},{34,6,1},{4,36,4},{18,36,4},{22,16,18},{44,16,18},{18,36,4},
+{0,20,18},{44,16,18},{0,20,18},{34,0,20},{34,0,20},{34,0,20},{34,0,20},{34,20,5},{34,20,5},{34,20,5},{34,4,5},{18,20,2},{18,20,2},{20,8,46},{20,22,27},{20,6,31},{20,6,28},{4,24,52},{4,22,19},{4,6,7},{4,6,36},{18,22,56},{34,6,31},{20,8,21},{20,22,2},{20,6,6},{20,6,3},{36,6,51},{4,22,18},{4,6,6},{18,6,26},{31,0,51},
+{18,6,26},{20,22,26},{20,22,26},{20,22,26},{20,6,27},{4,38,9},{4,6,6},{4,6,6},{4,36,1},{34,6,9},{4,36,4},{20,22,1},{20,22,1},{20,22,1},{20,6,2},{22,2,8},{20,36,4},{20,36,4},{4,36,0},{42,2,8},{4,36,0},{22,4,18},{20,22,1},{36,6,2},{4,6,2},{22,4,18},{15,0,18},{4,6,2},{0,6,26},{15,0,18},{0,6,26},{20,0,26},
+{20,0,26},{20,0,26},{20,0,26},{4,22,1},{4,22,1},{4,22,1},{4,36,1},{4,36,4},{4,36,4},{36,40,38},{36,8,22},{36,38,33},{36,38,28},{36,24,55},{36,38,25},{36,38,13},{20,22,28},{34,8,55},{4,22,23},{6,8,21},{6,38,5},{6,38,5},{6,22,11},{24,2,51},{36,38,21},{20,38,9},{4,22,19},{13,0,51},{4,22,19},{36,8,21},{36,8,21},{36,8,21},
+{36,22,21},{36,8,14},{36,22,6},{36,22,6},{36,6,14},{4,38,10},{4,22,14},{6,38,1},{6,38,1},{6,38,1},{6,22,2},{8,2,8},{36,22,2},{36,22,2},{6,6,10},{30,2,8},{6,6,10},{10,0,18},{36,8,2},{6,38,4},{4,38,5},{10,0,18},{4,8,18},{4,38,5},{0,22,18},{4,8,18},{0,22,18},{36,0,20},{36,0,20},{36,0,20},{36,0,20},{36,22,5},
+{36,22,5},{36,22,5},{36,6,5},{4,22,5},{4,22,5},{22,10,46},{22,24,26},{22,8,30},{22,8,30},{6,26,52},{6,24,21},{6,8,5},{6,38,37},{20,24,53},{6,38,40},{22,10,21},{22,24,1},{22,8,5},{22,8,5},{16,11,51},{6,24,20},{6,8,4},{6,38,36},{25,0,51},{6,38,36},{22,24,26},{22,24,26},{22,24,26},{22,8,30},{6,40,9},{6,8,5},{6,8,5},
+{6,38,1},{36,8,11},{6,38,4},{22,24,1},{22,24,1},{22,24,1},{22,8,5},{24,4,8},{6,8,4},{6,8,4},{6,38,0},{11,0,8},{6,38,0},{42,0,18},{22,24,0},{22,8,4},{6,8,0},{42,0,18},{9,0,18},{6,8,0},{0,8,36},{9,0,18},{0,8,36},{22,0,26},{22,0,26},{22,0,26},{22,0,26},{6,24,1},{6,24,1},{6,24,1},{6,38,1},{6,38,4},
+{6,38,4},{38,12,44},{38,10,30},{38,40,46},{38,40,34},{38,26,53},{38,40,21},{38,40,9},{38,24,25},{6,10,57},{22,24,22},{8,10,21},{8,40,5},{8,40,5},{8,24,17},{28,0,51},{38,40,20},{38,40,8},{6,24,21},{37,0,51},{6,24,21},{38,26,26},{38,26,26},{38,26,26},{38,24,30},{38,10,9},{38,40,5},{38,40,5},{38,24,9},{22,24,11},{22,24,6},{8,40,1},
+{8,40,1},{8,40,1},{8,24,1},{38,10,8},{8,24,4},{8,24,4},{6,24,5},{23,0,8},{6,24,5},{16,7,18},{38,10,4},{8,40,4},{6,40,5},{16,7,18},{21,0,18},{6,40,5},{0,24,20},{21,0,18},{0,24,20},{38,0,26},{38,0,26},{38,0,26},{38,0,26},{38,40,1},{38,40,1},{38,40,1},{38,8,2},{22,24,2},{22,24,2},{24,12,38},{24,26,22},{24,10,30},
+{24,10,22},{8,28,52},{8,26,19},{8,10,6},{8,40,37},{38,26,55},{38,10,30},{24,12,22},{24,26,6},{24,10,14},{24,10,6},{42,6,51},{8,26,18},{24,10,3},{22,10,26},{19,0,51},{22,10,26},{24,26,21},{24,26,21},{24,26,21},{24,10,21},{8,42,9},{8,10,5},{8,10,5},{8,40,1},{38,10,8},{8,40,4},{24,26,5},{24,26,5},{24,26,5},{24,10,5},{28,2,8},
+{24,10,2},{24,10,2},{8,40,0},{42,8,8},{8,40,0},{26,8,18},{24,26,2},{40,10,2},{8,10,1},{26,8,18},{15,6,18},{8,10,1},{0,10,26},{15,6,18},{0,10,26},{24,0,20},{24,0,20},{24,0,20},{24,0,20},{8,26,1},{8,26,1},{8,26,1},{8,40,1},{38,10,4},{38,10,4},{40,14,40},{40,12,21},{40,42,33},{40,42,33},{40,28,55},{40,42,23},{40,42,18},
+{40,26,33},{8,12,57},{24,26,22},{10,12,21},{10,42,5},{10,42,5},{10,26,17},{30,2,51},{40,42,19},{24,42,14},{8,26,21},{35,2,51},{8,26,21},{40,12,21},{40,12,21},{40,12,21},{40,26,21},{40,12,14},{40,26,6},{40,26,6},{40,10,14},{8,42,10},{24,26,6},{10,42,1},{10,42,1},{10,42,1},{10,26,1},{16,3,8},{40,26,2},{40,26,2},{8,26,5},{17,0,8},
+{8,26,5},{16,1,18},{40,12,1},{10,42,4},{8,42,5},{16,1,18},{19,2,18},{8,42,5},{0,26,20},{19,2,18},{0,26,20},{40,0,20},{40,0,20},{40,0,20},{40,0,20},{40,26,5},{40,26,5},{40,26,5},{40,10,5},{24,26,2},{24,26,2},{26,14,38},{26,28,22},{26,12,30},{26,12,22},{10,30,52},{10,28,21},{10,12,6},{10,42,37},{24,28,53},{40,12,31},{26,14,22},
+{26,28,6},{26,12,14},{26,12,6},{47,2,51},{10,28,20},{26,12,3},{24,12,26},{17,2,51},{24,12,26},{26,28,21},{26,28,21},{26,28,21},{26,12,21},{10,44,9},{10,12,5},{10,12,5},{10,42,1},{40,12,9},{40,42,2},{26,28,5},{26,28,5},{26,28,5},{26,12,5},{30,4,8},{26,12,2},{26,12,2},{10,42,0},{15,8,8},{10,42,0},{15,0,18},{26,28,2},{42,12,5},
+{10,12,1},{15,0,18},{5,4,18},{10,12,1},{0,12,26},{5,4,18},{0,12,26},{26,0,20},{26,0,20},{26,0,20},{26,0,20},{10,28,1},{10,28,1},{10,28,1},{10,42,1},{40,42,2},{40,42,2},{42,47,46},{42,14,31},{12,44,37},{42,44,31},{42,46,52},{42,44,21},{42,44,6},{42,28,25},{10,14,51},{26,28,20},{12,30,18},{12,14,2},{12,44,1},{12,44,10},{29,0,51},
+{42,44,20},{42,44,5},{26,28,20},{37,6,51},{26,28,20},{42,30,26},{42,30,26},{42,30,26},{42,28,30},{42,14,9},{42,44,5},{42,44,5},{42,28,9},{10,44,9},{26,28,4},{12,44,0},{12,44,0},{12,44,0},{12,28,0},{45,0,8},{12,28,4},{12,28,4},{26,28,4},{27,8,8},{26,28,4},{45,2,18},{12,14,2},{12,44,1},{26,44,1},{45,2,18},{25,8,18},{26,44,1},
+{0,28,20},{25,8,18},{0,28,20},{42,0,26},{42,0,26},{42,0,26},{42,0,26},{42,44,1},{42,44,1},{42,44,1},{42,12,5},{26,28,0},{26,28,0},{28,47,38},{28,30,22},{28,14,33},{28,14,25},{12,31,55},{12,30,23},{12,14,18},{12,14,33},{42,30,55},{42,14,21},{28,47,22},{28,30,6},{44,14,14},{28,14,9},{46,10,51},{12,30,19},{28,14,6},{26,14,21},{23,8,51},
+{26,14,21},{28,30,21},{28,30,21},{28,30,21},{28,14,21},{12,46,14},{12,14,14},{12,14,14},{12,44,6},{42,14,10},{12,44,6},{28,30,5},{28,30,5},{28,30,5},{28,14,5},{29,2,8},{28,14,2},{28,14,2},{12,44,2},{35,6,8},{12,44,2},{8,7,18},{28,30,2},{44,14,5},{12,14,5},{8,7,18},{33,6,18},{12,14,5},{0,14,20},{33,6,18},{0,14,20},{28,0,20},
+{28,0,20},{28,0,20},{28,0,20},{12,30,5},{12,30,5},{12,30,5},{12,44,5},{42,14,1},{42,14,1},{44,15,46},{44,47,27},{14,46,37},{44,46,31},{44,31,53},{44,46,21},{44,46,6},{44,30,25},{42,47,55},{28,30,22},{14,31,20},{14,47,8},{14,46,1},{14,46,10},{38,3,51},{44,46,20},{44,46,5},{12,30,21},{35,8,51},{12,30,21},{44,31,26},{44,31,26},{44,31,26},
+{44,30,30},{44,47,11},{44,46,5},{44,46,5},{44,30,9},{12,46,9},{28,30,6},{14,46,0},{14,46,0},{14,46,0},{14,30,0},{43,2,8},{14,30,4},{14,30,4},{12,30,5},{21,8,8},{12,30,5},{41,0,18},{44,47,1},{14,46,1},{28,46,1},{41,0,18},{19,8,18},{28,46,1},{0,30,20},{19,8,18},{0,30,20},{44,0,26},{44,0,26},{44,0,26},{44,0,26},{44,46,1},
+{44,46,1},{44,46,1},{44,14,5},{28,30,2},{28,30,2},{30,45,38},{30,31,21},{30,47,24},{30,47,24},{14,29,55},{14,31,22},{14,47,8},{14,46,55},{28,31,53},{44,47,41},{30,45,22},{30,31,5},{30,47,8},{30,47,8},{41,2,51},{14,31,18},{14,47,4},{12,47,37},{17,8,51},{12,47,37},{30,31,20},{30,31,20},{30,31,20},{30,47,24},{14,15,14},{14,47,8},{14,47,8},
+{14,46,6},{44,47,9},{14,46,6},{30,31,4},{30,31,4},{30,31,4},{30,47,8},{38,1,8},{14,47,4},{14,47,4},{14,46,2},{43,28,8},{14,46,2},{9,0,18},{30,31,1},{46,47,1},{14,47,0},{9,0,18},{0,9,18},{14,47,0},{0,47,36},{0,9,18},{0,47,36},{30,0,20},{30,0,20},{30,0,20},{30,0,20},{14,31,4},{14,31,4},{14,31,4},{14,46,5},{14,46,5},
+{14,46,5},{46,43,54},{46,45,41},{47,15,55},{46,15,44},{46,13,51},{46,15,20},{46,15,8},{46,31,24},{14,45,56},{30,31,21},{47,29,21},{47,15,6},{47,15,6},{47,31,17},{23,0,51},{46,15,20},{46,15,8},{30,31,20},{18,9,51},{30,31,20},{46,13,37},{46,13,37},{46,13,37},{46,15,40},{46,45,8},{46,15,4},{46,15,4},{46,31,8},{14,15,14},{30,31,5},{47,15,2},
+{47,15,2},{47,15,2},{47,31,1},{39,0,8},{46,15,4},{46,15,4},{30,31,4},{9,28,8},{30,31,4},{39,2,18},{47,15,5},{47,15,5},{30,15,4},{39,2,18},{34,9,18},{30,15,4},{0,31,20},{34,9,18},{0,31,20},{46,0,36},{46,0,36},{46,0,36},{46,0,36},{46,15,0},{46,15,0},{46,15,0},{46,47,1},{30,31,1},{30,31,1},{31,43,38},{31,29,22},{31,45,25},
+{31,45,22},{47,43,53},{47,29,19},{47,45,6},{47,15,37},{46,29,52},{46,45,27},{31,43,22},{31,29,6},{31,45,9},{31,45,6},{9,6,51},{47,29,18},{47,45,5},{30,45,26},{32,7,51},{30,45,26},{31,13,21},{31,13,21},{31,13,21},{31,45,21},{47,13,9},{47,45,5},{47,45,5},{47,15,1},{46,45,10},{46,15,8},{31,13,5},{31,13,5},{31,13,5},{31,45,5},{23,2,8},
+{31,15,4},{31,15,4},{47,15,0},{20,9,8},{47,15,0},{47,11,18},{31,29,2},{15,45,5},{47,45,1},{47,11,18},{22,9,18},{47,45,1},{0,45,26},{22,9,18},{0,45,26},{31,0,20},{31,0,20},{31,0,20},{31,0,20},{47,29,1},{47,29,1},{47,29,1},{47,15,1},{46,45,1},{46,45,1},{15,11,38},{15,43,21},{15,13,33},{15,13,33},{15,27,55},{15,13,23},{15,13,18},
+{15,29,33},{47,13,59},{31,29,22},{45,27,21},{45,13,6},{45,13,6},{45,29,17},{21,2,51},{15,13,19},{15,13,14},{31,29,21},{24,9,51},{31,29,21},{15,27,21},{15,27,21},{15,27,21},{15,29,21},{15,13,14},{15,29,6},{15,29,6},{15,45,14},{47,13,10},{31,29,6},{45,13,2},{45,13,2},{45,13,2},{45,29,1},{37,2,8},{15,29,2},{15,29,2},{31,29,5},{34,7,8},
+{31,29,5},{35,0,18},{15,43,1},{45,13,5},{31,13,5},{35,0,18},{36,7,18},{31,13,5},{0,29,20},{36,7,18},{0,29,20},{15,0,20},{15,0,20},{15,0,20},{15,0,20},{15,13,5},{15,13,5},{15,13,5},{15,45,5},{31,29,2},{31,29,2},{29,41,38},{29,27,20},{29,43,25},{29,43,25},{45,41,53},{45,27,21},{45,43,6},{45,13,37},{31,27,53},{15,43,31},{29,41,22},
+{29,27,4},{29,43,9},{29,43,9},{35,2,51},{45,27,20},{45,43,5},{31,43,26},{34,5,51},{31,43,26},{29,27,20},{29,27,20},{29,27,20},{29,13,24},{45,11,9},{45,43,5},{45,43,5},{45,13,1},{15,43,9},{15,13,2},{29,27,4},{29,27,4},{29,27,4},{29,13,8},{44,1,8},{29,13,4},{29,13,4},{45,13,0},{26,9,8},{45,13,0},{3,0,18},{29,27,0},{13,43,5},
+{45,43,1},{3,0,18},{0,3,18},{45,43,1},{0,43,26},{0,3,18},{0,43,26},{29,0,20},{29,0,20},{29,0,20},{29,0,20},{45,27,1},{45,27,1},{45,27,1},{45,13,1},{15,13,2},{15,13,2},{13,9,46},{13,41,31},{43,11,37},{13,11,31},{13,25,53},{13,11,21},{13,11,6},{13,27,30},{29,11,56},{29,27,22},{43,25,18},{43,41,2},{43,11,1},{43,27,16},{17,0,51},
+{13,11,20},{13,11,5},{29,27,21},{18,3,51},{29,27,21},{13,25,26},{13,25,26},{13,25,26},{13,27,27},{13,41,9},{13,27,3},{13,27,3},{13,27,14},{45,11,9},{29,27,6},{43,11,0},{43,11,0},{43,11,0},{43,27,0},{31,5,8},{13,27,2},{13,27,2},{29,27,5},{14,9,8},{29,27,5},{31,3,18},{43,41,2},{43,11,1},{29,11,1},{31,3,18},{34,3,18},{29,11,1},
+{0,27,20},{34,3,18},{0,27,20},{13,0,26},{13,0,26},{13,0,26},{13,0,26},{13,11,1},{13,11,1},{13,11,1},{13,43,5},{29,27,2},{29,27,2},{27,39,38},{27,25,22},{27,41,33},{27,41,25},{43,23,55},{43,25,23},{43,41,18},{43,41,33},{13,25,55},{13,41,21},{27,39,22},{27,25,6},{11,41,14},{27,41,9},{27,9,51},{43,25,19},{27,41,6},{13,41,21},{14,7,51},
+{13,41,21},{27,9,21},{27,9,21},{27,9,21},{27,41,21},{43,9,14},{43,25,14},{43,25,14},{43,11,5},{13,41,10},{43,11,5},{27,9,5},{27,9,5},{27,9,5},{27,41,5},{17,2,8},{27,41,2},{27,41,2},{43,11,1},{16,1,8},{43,11,1},{43,7,18},{27,25,2},{11,41,5},{27,41,5},{43,7,18},{18,1,18},{27,41,5},{0,41,20},{18,1,18},{0,41,20},{27,0,20},
+{27,0,20},{27,0,20},{27,0,20},{43,9,5},{43,9,5},{43,9,5},{43,11,4},{13,41,1},{13,41,1},{11,7,46},{11,39,30},{41,9,37},{11,9,31},{11,23,53},{11,9,21},{11,9,6},{11,25,30},{13,39,55},{27,25,22},{41,23,18},{41,9,4},{41,9,1},{41,25,16},{17,6,51},{11,9,20},{11,9,5},{27,25,21},{20,1,51},{27,25,21},{11,23,26},{11,23,26},{11,23,26},
+{11,25,27},{11,39,9},{11,25,3},{11,25,3},{11,25,14},{43,9,9},{27,25,6},{41,9,0},{41,9,0},{41,9,0},{41,25,0},{29,3,8},{11,25,2},{11,25,2},{27,25,5},{43,9,8},{27,25,5},{29,1,18},{41,9,4},{41,9,1},{27,9,1},{29,1,18},{36,1,18},{27,9,1},{0,25,20},{36,1,18},{0,25,20},{11,0,26},{11,0,26},{11,0,26},{11,0,26},{11,9,1},
+{11,9,1},{11,9,1},{11,41,2},{27,25,2},{27,25,2},{25,37,38},{25,23,22},{25,39,25},{25,39,25},{41,21,55},{41,23,23},{41,39,9},{41,39,46},{27,23,53},{11,39,30},{25,37,22},{25,23,6},{25,39,9},{25,39,9},{27,3,51},{41,23,19},{41,39,5},{27,39,26},{39,9,51},{27,39,26},{25,7,21},{25,7,21},{25,7,21},{25,9,24},{41,7,14},{41,39,8},{41,39,8},
+{41,9,5},{11,39,8},{41,9,5},{25,7,5},{25,7,5},{25,7,5},{25,9,8},{39,11,8},{25,9,4},{25,9,4},{41,9,1},{22,1,8},{41,9,1},{41,5,18},{25,23,2},{9,39,2},{41,39,1},{41,5,18},{23,9,18},{41,39,1},{0,39,26},{23,9,18},{0,39,26},{25,0,20},{25,0,20},{25,0,20},{25,0,20},{41,7,5},{41,7,5},{41,7,5},{41,9,4},{41,9,4},
+{41,9,4},{39,21,54},{39,7,40},{39,7,37},{9,7,41},{9,5,51},{9,7,20},{9,7,5},{9,23,30},{41,37,51},{25,23,26},{39,21,18},{39,7,4},{39,7,1},{39,7,17},{11,1,51},{9,7,20},{9,7,5},{25,23,26},{5,9,51},{25,23,26},{39,7,36},{39,7,36},{39,7,36},{39,23,36},{9,21,10},{9,7,4},{9,7,4},{9,23,5},{41,7,12},{25,23,1},{39,7,0},
+{39,7,0},{39,7,0},{39,23,0},{25,5,8},{9,7,4},{9,7,4},{25,23,1},{10,1,8},{25,23,1},{25,3,18},{39,7,4},{39,7,1},{25,7,1},{25,3,18},{12,1,18},{25,7,1},{0,23,26},{12,1,18},{0,23,26},{9,0,36},{9,0,36},{9,0,36},{9,0,36},{9,7,0},{9,7,0},{9,7,0},{9,23,4},{25,23,0},{25,23,0},{23,19,38},{23,5,23},{23,21,28},
+{23,37,23},{39,19,55},{39,21,25},{39,37,13},{39,37,33},{9,21,53},{9,37,22},{7,21,27},{23,5,14},{7,37,14},{23,37,14},{23,5,51},{39,21,21},{23,37,6},{9,37,21},{14,1,51},{9,37,21},{23,5,19},{23,5,19},{23,5,19},{23,37,19},{39,5,14},{39,21,9},{39,21,9},{39,7,5},{9,37,11},{39,7,5},{23,5,10},{23,5,10},{23,5,10},{7,7,10},{9,3,8},
+{23,37,2},{23,37,2},{39,7,1},{31,3,8},{39,7,1},{37,7,18},{23,5,5},{7,37,5},{23,37,5},{37,7,18},{30,1,18},{23,37,5},{0,37,20},{30,1,18},{0,37,20},{23,0,18},{23,0,18},{23,0,18},{23,0,18},{39,5,5},{39,5,5},{39,5,5},{39,7,4},{9,37,2},{9,37,2},{7,33,44},{7,35,31},{7,5,36},{7,5,31},{7,19,53},{7,5,22},{7,5,7},
+{7,21,31},{39,35,57},{23,21,27},{37,19,20},{37,5,4},{37,5,1},{37,5,17},{23,17,51},{7,5,21},{7,5,6},{23,21,26},{45,17,51},{23,21,26},{7,19,26},{7,19,26},{7,19,26},{7,5,30},{7,35,9},{7,5,6},{7,5,6},{7,21,6},{39,5,9},{23,21,2},{37,5,0},{37,5,0},{37,5,0},{37,21,0},{23,3,8},{37,21,4},{37,21,4},{23,21,1},{43,3,8},
+{23,21,1},{23,1,18},{37,5,4},{37,5,1},{23,5,1},{23,1,18},{33,7,18},{23,5,1},{0,21,26},{33,7,18},{0,21,26},{7,0,26},{7,0,26},{7,0,26},{7,0,26},{7,5,2},{7,5,2},{7,5,2},{7,37,2},{23,21,1},{23,21,1},{21,17,38},{21,19,20},{21,35,31},{21,35,23},{37,17,55},{37,19,22},{37,35,13},{37,35,33},{23,19,56},{7,35,21},{5,19,27},
+{21,19,11},{5,35,14},{21,35,14},{21,3,51},{37,19,18},{21,35,6},{7,35,21},{43,1,51},{7,35,21},{21,3,19},{21,3,19},{21,3,19},{21,35,19},{37,3,14},{37,35,9},{37,35,9},{37,5,5},{7,35,10},{37,5,5},{21,3,10},{21,3,10},{21,3,10},{5,5,10},{3,25,8},{21,35,2},{21,35,2},{37,5,1},{29,1,8},{37,5,1},{35,5,18},{21,19,2},{5,35,5},
+{21,35,5},{35,5,18},{27,1,18},{21,35,5},{0,35,20},{27,1,18},{0,35,20},{21,0,18},{21,0,18},{21,0,18},{21,0,18},{37,19,4},{37,19,4},{37,19,4},{37,5,4},{7,35,1},{7,35,1},{35,17,44},{35,33,27},{35,3,27},{35,3,35},{5,1,51},{5,3,26},{5,3,1},{5,19,30},{37,33,51},{21,19,26},{35,17,19},{35,33,2},{35,3,2},{35,3,10},{5,1,51},
+{5,3,26},{5,3,1},{21,19,26},{9,1,51},{21,19,26},{35,3,27},{35,3,27},{35,3,27},{35,19,27},{5,17,10},{5,3,1},{5,3,1},{5,19,5},{37,3,12},{21,19,1},{35,3,2},{35,3,2},{35,3,2},{35,19,2},{19,5,8},{5,3,1},{5,3,1},{21,19,1},{37,3,8},{21,19,1},{19,3,18},{35,33,1},{35,3,1},{5,3,1},{19,3,18},{39,1,18},{5,3,1},
+{0,19,26},{39,1,18},{0,19,26},{35,0,26},{35,0,26},{35,0,26},{35,0,26},{5,3,0},{5,3,0},{5,3,0},{5,19,4},{21,19,0},{21,19,0},{19,1,54},{19,1,22},{19,17,28},{19,33,27},{19,1,61},{35,17,30},{19,33,19},{35,33,31},{5,17,52},{5,33,20},{3,1,24},{3,17,8},{3,33,13},{3,33,17},{17,5,51},{35,17,21},{19,33,10},{5,33,19},{5,17,51},
+{5,33,19},{19,1,18},{19,1,18},{19,1,18},{19,33,18},{19,17,19},{19,33,10},{19,33,10},{19,3,14},{5,33,11},{35,3,6},{3,33,4},{3,33,4},{3,33,4},{3,3,8},{3,3,8},{19,33,1},{19,33,1},{19,3,5},{3,3,8},{19,3,5},{33,33,18},{19,1,4},{3,33,9},{19,33,9},{33,33,18},{33,33,18},{19,33,9},{0,33,18},{33,33,18},{0,33,18},{19,0,18},
+{19,0,18},{19,0,18},{19,0,18},{35,1,9},{35,1,9},{35,1,9},{19,3,10},{35,3,2},{35,3,2},{33,1,76},{33,1,36},{33,1,27},{33,1,35},{33,1,84},{3,1,26},{3,1,1},{3,17,30},{19,1,56},{19,17,27},{17,1,43},{33,1,11},{33,1,2},{33,1,10},{1,3,51},{3,1,26},{3,1,1},{19,17,26},{3,1,51},{19,17,26},{33,1,27},{33,1,27},{33,1,27},
+{33,17,26},{3,1,16},{3,1,1},{3,1,1},{3,17,5},{35,1,12},{19,17,2},{33,1,2},{33,1,2},{33,1,2},{33,17,1},{17,3,8},{3,1,1},{3,1,1},{19,17,1},{35,1,8},{19,17,1},{17,1,18},{17,1,10},{33,1,1},{19,1,0},{17,1,18},{33,1,18},{19,1,0},{0,17,26},{33,1,18},{0,17,26},{33,0,26},{33,0,26},{33,0,26},{33,0,26},{3,1,0},
+{3,1,0},{3,1,0},{3,17,4},{19,17,1},{19,17,1},{17,1,36},{17,1,28},{17,1,27},{17,1,19},{17,1,28},{17,1,12},{17,1,11},{17,1,10},{33,1,20},{33,1,2},{1,1,4},{1,1,4},{1,1,4},{1,1,4},{1,17,3},{17,1,3},{17,1,2},{17,1,1},{17,1,3},{17,1,1},{17,1,27},{17,1,27},{17,1,27},{17,1,19},{17,1,19},{17,1,11},{17,1,11},
+{17,1,10},{33,1,11},{33,1,2},{1,1,4},{1,1,4},{1,1,4},{1,1,4},{1,17,2},{17,1,2},{17,1,2},{17,1,1},{17,1,2},{17,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{17,0,18},{17,0,18},{17,0,18},{17,0,18},{17,1,10},{17,1,10},{17,1,10},{17,1,10},{33,1,2},
+{33,1,2},{0,4,74},{0,18,10},{0,2,1},{0,2,26},{0,34,154},{0,2,99},{0,32,49},{0,32,121},{0,32,162},{0,32,130},{0,4,74},{0,18,10},{0,2,1},{0,2,26},{32,0,153},{0,2,99},{0,32,49},{0,32,121},{0,32,153},{0,32,121},{0,2,0},{0,2,0},{0,2,0},{0,16,4},{0,32,13},{0,16,5},{0,16,5},{0,16,9},{0,16,14},{0,16,10},{0,2,0},
+{0,2,0},{0,2,0},{0,16,4},{16,0,13},{0,16,5},{0,16,5},{0,16,9},{32,0,13},{0,16,9},{32,32,72},{0,18,10},{0,2,1},{0,2,26},{32,32,72},{32,32,72},{0,2,26},{0,32,72},{32,32,72},{0,32,72},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,38,81},{0,20,10},{16,34,34},
+{0,18,26},{0,36,243},{0,34,99},{0,18,26},{0,2,139},{0,18,279},{0,2,164},{16,6,76},{16,4,8},{16,34,9},{16,18,24},{18,0,243},{0,34,99},{0,18,26},{0,2,139},{36,0,243},{0,2,139},{0,20,10},{0,20,10},{0,20,10},{0,18,10},{0,34,50},{0,18,10},{0,18,10},{0,32,20},{0,32,61},{0,32,29},{16,4,4},{16,4,4},{16,4,4},{16,2,5},{16,2,50},
+{0,18,10},{0,18,10},{0,32,20},{34,0,50},{0,32,20},{18,2,72},{0,20,1},{16,34,5},{0,18,17},{18,2,72},{38,0,72},{0,18,17},{0,18,80},{38,0,72},{0,18,80},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,32,0},{0,32,0},{0,32,0},{0,16,0},{0,16,1},{0,16,1},{16,24,135},{16,6,66},{16,20,122},{16,4,66},{0,8,244},{0,20,81},{0,4,2},
+{0,34,121},{0,4,344},{0,34,185},{32,8,74},{32,36,1},{32,4,17},{32,4,17},{16,38,243},{0,20,81},{0,4,2},{0,34,121},{38,16,243},{0,34,121},{16,22,61},{16,22,61},{16,22,61},{16,4,65},{0,6,52},{0,4,1},{0,4,1},{0,18,9},{0,18,94},{0,18,45},{32,36,0},{32,36,0},{32,36,0},{32,34,0},{2,2,50},{0,4,1},{0,4,1},{0,18,9},{2,2,50},
+{0,18,9},{20,16,72},{32,36,1},{2,4,1},{0,4,1},{20,16,72},{16,20,72},{0,4,1},{0,34,72},{16,20,72},{0,34,72},{16,0,61},{16,0,61},{16,0,61},{16,0,61},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,32,25},{0,32,25},{32,26,152},{2,22,91},{2,36,119},{32,20,89},{16,10,247},{16,6,78},{16,36,13},{16,4,110},{0,36,293},{0,4,103},{18,8,76},
+{18,6,8},{18,36,9},{2,20,19},{20,2,243},{16,6,74},{32,20,9},{0,4,94},{42,0,243},{0,4,94},{32,8,81},{32,8,81},{32,8,81},{32,20,80},{16,8,54},{16,36,9},{16,36,9},{16,34,8},{0,4,77},{0,34,6},{18,6,4},{18,6,4},{18,6,4},{18,4,5},{18,4,50},{32,20,0},{32,20,0},{16,34,4},{36,2,50},{16,34,4},{18,8,72},{2,22,1},{18,36,5},
+{0,36,4},{18,8,72},{44,0,72},{0,36,4},{0,4,90},{44,0,72},{0,4,90},{32,0,80},{32,0,80},{32,0,80},{32,0,80},{16,6,4},{16,6,4},{16,6,4},{16,34,4},{0,34,2},{0,34,2},{18,42,146},{18,8,83},{18,22,139},{18,6,79},{2,26,243},{2,38,78},{2,6,9},{2,36,110},{0,38,252},{0,36,79},{34,10,73},{34,8,6},{4,6,21},{34,6,14},{38,0,243},
+{2,38,78},{18,6,6},{0,36,75},{30,0,243},{0,36,75},{18,24,75},{18,24,75},{18,24,75},{18,6,75},{2,24,50},{2,6,5},{2,6,5},{2,20,4},{0,6,53},{16,20,2},{34,8,2},{34,8,2},{34,8,2},{34,36,2},{2,24,50},{18,6,2},{18,6,2},{16,20,1},{28,0,50},{16,20,1},{36,6,72},{34,8,5},{4,6,5},{2,6,5},{36,6,72},{31,0,72},{2,6,5},
+{0,36,74},{31,0,72},{0,36,74},{18,0,74},{18,0,74},{18,0,74},{18,0,74},{2,22,0},{2,22,0},{2,22,0},{2,4,4},{16,20,2},{16,20,2},{4,12,154},{4,24,85},{4,38,106},{34,38,95},{18,12,253},{18,8,90},{34,38,15},{18,6,122},{0,24,244},{16,22,93},{20,10,76},{20,8,9},{20,38,6},{20,22,24},{24,0,243},{18,8,81},{34,38,6},{0,22,80},{32,8,243},
+{0,22,80},{4,40,80},{4,40,80},{4,40,80},{4,22,80},{34,24,59},{34,22,10},{34,22,10},{18,36,19},{32,22,53},{32,6,5},{20,8,5},{20,8,5},{20,8,5},{20,6,8},{22,2,50},{34,22,1},{34,22,1},{32,6,4},{42,2,50},{32,6,4},{24,2,72},{20,8,5},{20,38,2},{18,38,1},{24,2,72},{13,0,72},{18,38,1},{0,22,80},{13,0,72},{0,22,80},{4,0,80},
+{4,0,80},{4,0,80},{4,0,80},{34,22,9},{34,22,9},{34,22,9},{18,36,10},{32,6,1},{32,6,1},{20,28,146},{20,10,77},{20,8,122},{20,8,77},{4,28,243},{4,40,78},{4,8,5},{4,38,110},{32,40,244},{2,38,79},{36,12,73},{36,40,2},{6,8,18},{36,8,18},{38,6,243},{34,40,73},{4,8,5},{2,38,75},{27,0,243},{2,38,75},{20,26,73},{20,26,73},{20,26,73},
+{20,8,76},{4,26,50},{4,8,4},{4,8,4},{4,22,4},{2,8,50},{18,22,2},{36,40,1},{36,40,1},{36,40,1},{36,38,2},{8,2,50},{4,8,4},{4,8,4},{18,22,1},{30,2,50},{18,22,1},{16,11,72},{36,40,1},{6,8,2},{4,8,1},{16,11,72},{25,0,72},{4,8,1},{0,38,74},{25,0,72},{0,38,74},{20,0,72},{20,0,72},{20,0,72},{20,0,72},{4,24,0},
+{4,24,0},{4,24,0},{4,6,4},{18,22,2},{18,22,2},{6,14,154},{6,26,85},{6,40,109},{6,24,97},{20,14,248},{20,10,78},{20,40,13},{20,8,110},{2,26,244},{34,8,91},{22,12,76},{22,10,9},{22,40,9},{22,24,29},{26,2,243},{20,10,74},{20,40,9},{2,24,80},{38,8,243},{2,24,80},{6,42,80},{6,42,80},{6,42,80},{6,24,81},{20,12,54},{20,40,9},{20,40,9},
+{20,38,13},{34,24,53},{34,8,10},{22,10,5},{22,10,5},{22,10,5},{22,8,5},{24,4,50},{36,24,1},{36,24,1},{34,8,9},{11,0,50},{34,8,9},{26,4,72},{22,10,5},{22,40,5},{4,40,5},{26,4,72},{7,0,72},{4,40,5},{0,24,80},{7,0,72},{0,24,80},{6,0,80},{6,0,80},{6,0,80},{6,0,80},{20,10,4},{20,10,4},{20,10,4},{20,38,4},{34,8,1},
+{34,8,1},{22,46,146},{22,12,83},{38,26,122},{22,10,79},{6,30,245},{6,42,74},{6,10,10},{6,40,111},{4,42,247},{20,40,79},{38,14,76},{38,12,5},{8,10,21},{38,10,17},{44,0,243},{6,42,73},{6,10,9},{4,40,74},{26,8,243},{4,40,74},{22,28,75},{22,28,75},{22,28,75},{22,10,75},{6,28,51},{6,10,6},{6,10,6},{6,24,6},{4,10,53},{20,24,6},{38,12,4},
+{38,12,4},{38,12,4},{38,40,5},{38,10,50},{22,40,4},{22,40,4},{36,24,1},{23,0,50},{36,24,1},{42,6,72},{38,12,1},{8,10,5},{6,10,5},{42,6,72},{19,0,72},{6,10,5},{0,40,74},{19,0,72},{0,40,74},{22,0,74},{22,0,74},{22,0,74},{22,0,74},{6,26,2},{6,26,2},{6,26,2},{6,8,5},{20,24,5},{20,24,5},{8,46,154},{8,28,85},{8,42,106},
+{8,42,97},{38,46,247},{38,12,82},{38,42,10},{22,26,119},{4,28,247},{36,26,83},{24,14,75},{24,28,6},{24,42,6},{24,26,30},{30,0,243},{38,12,78},{38,42,6},{4,26,75},{33,0,243},{4,26,75},{8,44,80},{8,44,80},{8,44,80},{8,26,80},{38,28,56},{38,26,9},{38,26,9},{38,40,14},{20,42,54},{6,10,9},{24,12,1},{24,12,1},{24,12,1},{24,10,5},{28,2,50},
+{38,26,5},{38,26,5},{6,10,5},{42,8,50},{6,10,5},{30,2,72},{8,28,5},{24,42,5},{22,42,1},{30,2,72},{35,2,72},{22,42,1},{0,26,74},{35,2,72},{0,26,74},{8,0,80},{8,0,80},{8,0,80},{8,0,80},{38,26,5},{38,26,5},{38,26,5},{38,40,5},{6,40,4},{6,40,4},{24,15,146},{24,14,83},{24,28,126},{24,12,79},{8,31,243},{8,44,78},{8,12,9},
+{8,42,110},{36,44,245},{22,42,79},{40,46,75},{40,14,6},{10,12,21},{40,12,14},{47,0,243},{8,44,78},{8,12,9},{6,42,74},{27,6,243},{6,42,74},{24,30,75},{24,30,75},{24,30,75},{24,12,75},{8,14,52},{8,12,5},{8,12,5},{8,26,5},{6,12,53},{22,26,6},{40,14,2},{40,14,2},{40,14,2},{40,42,1},{16,3,50},{24,42,4},{24,42,4},{38,26,1},{17,0,50},
+{38,26,1},{47,2,72},{40,14,5},{10,12,5},{8,12,5},{47,2,72},{17,2,72},{8,12,5},{0,42,74},{17,2,72},{0,42,74},{24,0,74},{24,0,74},{24,0,74},{24,0,74},{8,28,0},{8,28,0},{8,28,0},{8,10,1},{22,26,5},{22,26,5},{10,15,152},{10,30,85},{10,44,106},{40,44,95},{40,31,252},{24,14,90},{40,44,15},{24,12,122},{6,30,247},{38,28,89},{26,47,73},
+{26,30,6},{26,44,6},{26,28,21},{34,3,243},{8,30,76},{40,44,6},{6,28,80},{35,4,243},{6,28,80},{10,46,80},{10,46,80},{10,46,80},{10,28,81},{40,30,59},{40,28,10},{40,28,10},{24,42,18},{22,44,51},{8,12,9},{26,14,1},{26,14,1},{26,14,1},{26,12,5},{30,4,50},{40,28,1},{40,28,1},{8,12,5},{15,8,50},{8,12,5},{15,2,72},{10,30,5},{26,44,5},
+{24,44,1},{15,2,72},{33,4,72},{24,44,1},{0,28,80},{33,4,72},{0,28,80},{10,0,80},{10,0,80},{10,0,80},{10,0,80},{40,28,9},{40,28,9},{40,28,9},{24,42,9},{8,12,5},{8,12,5},{26,13,152},{26,47,89},{42,30,122},{26,14,89},{10,29,245},{10,46,74},{10,30,15},{10,44,106},{8,46,247},{24,44,81},{42,45,76},{42,47,9},{12,30,18},{42,14,17},{4,1,243},
+{10,46,73},{26,14,10},{8,44,80},{1,4,243},{8,44,80},{26,15,80},{26,15,80},{26,15,80},{26,14,80},{10,31,51},{10,30,6},{10,30,6},{10,28,6},{24,14,54},{24,28,6},{42,47,5},{42,47,5},{42,47,5},{42,44,5},{45,0,50},{26,14,1},{26,14,1},{40,28,1},{27,8,50},{40,28,1},{46,10,72},{12,46,5},{12,30,9},{26,14,9},{46,10,72},{23,8,72},{26,14,9},
+{0,44,80},{23,8,72},{0,44,80},{26,0,80},{26,0,80},{26,0,80},{26,0,80},{10,30,2},{10,30,2},{10,30,2},{10,12,5},{24,44,1},{24,44,1},{12,13,148},{12,31,79},{12,46,110},{12,46,83},{42,29,248},{42,47,85},{42,46,5},{26,30,126},{8,31,247},{40,30,83},{28,29,75},{28,47,5},{28,46,5},{28,46,26},{27,0,243},{26,31,80},{42,46,1},{8,30,75},{37,8,243},
+{8,30,75},{12,15,74},{12,15,74},{12,15,74},{12,30,74},{42,15,56},{42,46,5},{42,46,5},{26,14,21},{24,46,56},{10,14,2},{28,47,1},{28,47,1},{28,47,1},{28,14,5},{29,2,50},{42,46,1},{42,46,1},{10,14,1},{35,6,50},{10,14,1},{38,3,72},{28,47,4},{44,46,1},{26,46,1},{38,3,72},{35,8,72},{26,46,1},{0,30,74},{35,8,72},{0,30,74},{12,0,74},
+{12,0,74},{12,0,74},{12,0,74},{42,46,4},{42,46,4},{42,46,4},{42,44,5},{10,14,1},{10,14,1},{28,11,146},{28,45,84},{44,47,121},{28,47,79},{12,27,244},{12,15,79},{12,47,6},{12,46,106},{40,15,244},{26,46,81},{44,43,76},{44,15,6},{14,47,11},{44,47,14},{28,13,243},{42,15,76},{12,47,5},{10,46,80},{27,12,243},{10,46,80},{28,13,75},{28,13,75},{28,13,75},
+{28,47,78},{12,29,51},{12,47,5},{12,47,5},{12,30,6},{10,47,51},{26,30,6},{44,15,5},{44,15,5},{44,15,5},{44,46,5},{43,2,50},{12,47,4},{12,47,4},{42,30,1},{21,8,50},{42,30,1},{41,2,72},{44,15,2},{14,47,2},{12,47,1},{41,2,72},{17,8,72},{12,47,1},{0,46,80},{17,8,72},{0,46,80},{28,0,74},{28,0,74},{28,0,74},{28,0,74},{12,31,1},
+{12,31,1},{12,31,1},{12,14,5},{26,46,1},{26,46,1},{14,11,148},{14,29,79},{14,15,114},{14,31,90},{44,27,248},{28,45,84},{28,15,18},{28,47,115},{10,29,247},{42,47,91},{30,27,75},{30,45,5},{30,15,6},{30,31,21},{40,3,243},{28,45,75},{28,15,9},{10,31,80},{16,9,243},{10,31,80},{14,13,74},{14,13,74},{14,13,74},{14,31,74},{44,13,56},{44,31,6},{44,31,6},
+{44,46,21},{42,31,52},{42,47,10},{30,45,1},{30,45,1},{30,45,1},{30,47,2},{38,1,50},{44,31,2},{44,31,2},{42,47,9},{43,28,50},{42,47,9},{29,12,72},{30,45,4},{30,15,5},{12,15,5},{29,12,72},{26,13,72},{12,15,5},{0,31,80},{26,13,72},{0,31,80},{14,0,74},{14,0,74},{14,0,74},{14,0,74},{44,15,5},{44,15,5},{44,15,5},{44,46,5},{42,47,1},
+{42,47,1},{30,9,154},{46,43,91},{46,29,115},{30,45,85},{14,9,247},{14,13,77},{14,29,18},{14,15,114},{12,13,247},{28,15,79},{46,25,83},{46,43,10},{47,45,21},{46,45,17},{10,1,243},{14,13,73},{30,45,6},{12,15,74},{4,9,243},{12,15,74},{30,11,80},{30,11,80},{30,11,80},{30,45,81},{14,11,56},{14,29,9},{14,29,9},{14,31,6},{12,45,56},{44,31,5},{46,43,9},
+{46,43,9},{46,43,9},{46,15,10},{39,0,50},{30,45,2},{30,45,2},{44,31,1},{9,28,50},{44,31,1},{9,6,72},{46,43,1},{47,45,5},{14,45,5},{9,6,72},{32,7,72},{14,45,5},{0,15,74},{32,7,72},{0,15,74},{30,0,80},{30,0,80},{30,0,80},{30,0,80},{14,13,5},{14,13,5},{14,13,5},{14,31,5},{44,31,4},{44,31,4},{47,9,154},{47,27,81},{47,13,106},
+{47,13,97},{46,9,244},{46,43,79},{46,13,6},{46,45,121},{12,27,248},{44,29,84},{31,25,75},{31,27,6},{31,13,6},{31,29,30},{21,0,243},{46,43,78},{46,13,5},{12,29,75},{18,7,243},{12,29,75},{47,11,80},{47,11,80},{47,11,80},{47,29,80},{46,11,51},{46,13,5},{46,13,5},{46,15,11},{28,13,54},{14,45,6},{31,43,1},{31,43,1},{31,43,1},{31,29,5},{23,2,50},
+{46,13,4},{46,13,4},{14,45,5},{20,9,50},{14,45,5},{21,2,72},{47,27,1},{15,13,5},{30,13,1},{21,2,72},{24,9,72},{30,13,1},{0,29,74},{24,9,72},{0,29,74},{47,0,80},{47,0,80},{47,0,80},{47,0,80},{46,13,1},{46,13,1},{46,13,1},{46,15,2},{14,45,2},{14,45,2},{31,7,146},{31,41,83},{31,27,126},{31,43,79},{47,23,243},{47,11,78},{47,43,5},
+{47,13,110},{14,11,247},{30,13,79},{15,9,75},{15,11,2},{15,27,21},{15,43,14},{14,3,243},{47,11,78},{47,43,5},{14,13,74},{32,5,243},{14,13,74},{31,9,75},{31,9,75},{31,9,75},{31,43,75},{47,25,52},{47,43,1},{47,43,1},{47,29,5},{14,43,56},{46,29,5},{15,11,1},{15,11,1},{15,11,1},{15,13,1},{37,2,50},{47,43,1},{47,43,1},{46,29,1},{34,7,50},
+{46,29,1},{35,2,72},{15,11,1},{45,43,5},{47,43,4},{35,2,72},{34,5,72},{47,43,4},{0,13,74},{34,5,72},{0,13,74},{31,0,74},{31,0,74},{31,0,74},{31,0,74},{47,27,1},{47,27,1},{47,27,1},{47,45,1},{46,29,4},{46,29,4},{45,7,152},{45,25,81},{45,11,106},{45,11,97},{15,23,253},{31,25,90},{31,11,15},{31,43,122},{14,25,247},{46,27,89},{29,39,73},
+{29,25,6},{29,11,6},{29,27,26},{46,3,243},{47,25,76},{31,11,6},{14,27,80},{16,3,243},{14,27,80},{45,9,80},{45,9,80},{45,9,80},{45,27,81},{15,25,59},{15,27,10},{15,27,10},{31,13,18},{30,11,54},{46,43,9},{29,41,1},{29,41,1},{29,41,1},{29,43,2},{44,1,50},{15,27,1},{15,27,1},{46,43,5},{26,9,50},{46,43,5},{46,1,72},{45,25,1},{13,11,5},
+{31,11,2},{46,1,72},{26,7,72},{31,11,2},{0,27,80},{26,7,72},{0,27,80},{45,0,80},{45,0,80},{45,0,80},{45,0,80},{15,27,9},{15,27,9},{15,27,9},{31,13,9},{47,13,5},{47,13,5},{29,5,154},{29,39,89},{13,25,122},{29,41,89},{45,21,245},{45,9,74},{45,41,15},{45,11,106},{47,9,247},{31,11,85},{13,37,76},{13,9,9},{43,25,18},{13,41,17},{1,0,243},
+{45,9,73},{29,41,10},{47,11,80},{0,1,243},{47,11,80},{29,7,80},{29,7,80},{29,7,80},{29,41,80},{45,23,51},{45,41,6},{45,41,6},{45,27,6},{31,41,54},{31,27,6},{13,9,5},{13,9,5},{13,9,5},{13,11,5},{31,5,50},{29,41,1},{29,41,1},{15,27,1},{14,9,50},{15,27,1},{27,9,72},{13,9,5},{43,25,9},{29,41,9},{27,9,72},{14,7,72},{29,41,9},
+{0,11,80},{14,7,72},{0,11,80},{29,0,80},{29,0,80},{29,0,80},{29,0,80},{45,25,1},{45,25,1},{45,25,1},{45,27,5},{31,11,5},{31,11,5},{43,5,148},{43,23,79},{43,9,110},{43,9,83},{13,21,248},{13,39,85},{13,9,9},{29,25,126},{47,23,248},{15,25,83},{27,21,75},{27,23,6},{27,9,5},{27,9,26},{15,1,243},{29,23,74},{13,9,5},{31,25,75},{9,11,243},
+{31,25,75},{43,7,74},{43,7,74},{43,7,74},{43,25,74},{13,7,56},{13,9,9},{13,9,9},{13,11,21},{15,9,56},{15,41,6},{27,39,1},{27,39,1},{27,39,1},{27,25,5},{17,2,50},{43,25,4},{43,25,4},{15,41,2},{16,1,50},{15,41,2},{17,6,72},{27,23,5},{11,9,1},{29,9,0},{17,6,72},{20,1,72},{29,9,0},{0,25,74},{20,1,72},{0,25,74},{43,0,74},
+{43,0,74},{43,0,74},{43,0,74},{13,9,5},{13,9,5},{13,9,5},{13,11,5},{15,41,5},{15,41,5},{27,3,146},{27,37,83},{27,23,119},{27,39,79},{43,19,244},{43,7,79},{43,39,10},{43,9,106},{15,7,245},{29,9,85},{11,35,76},{11,7,9},{41,39,14},{11,39,17},{27,5,243},{13,7,78},{27,39,9},{45,9,80},{6,1,243},{45,9,80},{27,5,75},{27,5,75},{27,5,75},
+{27,39,75},{43,21,51},{43,39,6},{43,39,6},{43,25,6},{45,39,53},{29,25,6},{11,7,5},{11,7,5},{11,7,5},{11,9,5},{29,3,50},{27,39,5},{27,39,5},{13,25,1},{43,9,50},{13,25,1},{27,3,72},{41,7,4},{41,39,5},{27,39,5},{27,3,72},{39,9,72},{27,39,5},{0,9,80},{39,9,72},{0,9,80},{27,0,74},{27,0,74},{27,0,74},{27,0,74},{43,23,1},
+{43,23,1},{43,23,1},{43,25,5},{29,9,5},{29,9,5},{41,3,148},{41,21,79},{41,7,111},{41,7,91},{11,19,248},{11,37,85},{11,7,10},{27,39,122},{45,21,248},{13,23,83},{25,19,75},{25,21,6},{25,7,6},{25,23,30},{17,10,243},{27,21,81},{11,7,6},{29,23,75},{24,1,243},{29,23,75},{41,5,74},{41,5,74},{41,5,74},{41,23,74},{11,5,56},{11,7,9},{11,7,9},
+{11,9,21},{29,7,54},{13,39,5},{25,37,1},{25,37,1},{25,37,1},{25,39,2},{39,11,50},{41,23,4},{41,23,4},{13,39,4},{22,1,50},{13,39,4},{39,7,72},{25,21,5},{9,7,5},{27,7,2},{39,7,72},{26,1,72},{27,7,2},{0,23,74},{26,1,72},{0,23,74},{41,0,74},{41,0,74},{41,0,74},{41,0,74},{11,7,5},{11,7,5},{11,7,5},{11,9,5},{13,39,1},
+{13,39,1},{25,1,154},{9,35,91},{9,21,110},{25,37,89},{41,1,247},{41,5,77},{41,21,13},{41,7,109},{43,5,247},{27,7,85},{39,19,81},{9,35,10},{39,21,13},{9,37,22},{41,1,243},{41,5,73},{41,21,9},{43,7,80},{47,3,243},{43,7,80},{25,3,80},{25,3,80},{25,3,80},{25,37,80},{41,3,56},{41,21,9},{41,21,9},{41,23,9},{27,37,54},{11,23,9},{39,21,9},
+{39,21,9},{39,21,9},{9,7,10},{25,5,50},{25,37,1},{25,37,1},{11,23,5},{10,1,50},{11,23,5},{23,5,72},{9,35,1},{39,21,4},{11,21,4},{23,5,72},{14,1,72},{11,21,4},{0,7,80},{14,1,72},{0,7,80},{25,0,80},{25,0,80},{25,0,80},{25,0,80},{41,5,5},{41,5,5},{41,5,5},{41,23,5},{27,7,5},{27,7,5},{39,1,148},{39,3,79},{39,5,110},
+{39,5,83},{9,1,244},{9,35,79},{9,5,5},{9,21,122},{43,19,248},{11,21,77},{23,17,72},{23,19,2},{23,5,4},{23,5,25},{9,1,243},{25,19,74},{9,5,4},{27,21,73},{46,1,243},{27,21,73},{39,3,75},{39,3,75},{39,3,75},{39,21,75},{9,3,51},{9,5,5},{9,5,5},{9,7,18},{11,5,53},{41,37,2},{23,19,1},{23,19,1},{23,19,1},{23,21,1},{9,3,50},
+{9,5,4},{9,5,4},{41,37,1},{31,3,50},{41,37,1},{23,17,72},{23,19,2},{7,5,4},{25,5,0},{23,17,72},{45,17,72},{25,5,0},{0,21,72},{45,17,72},{0,21,72},{39,0,74},{39,0,74},{39,0,74},{39,0,74},{9,5,1},{9,5,1},{9,5,1},{9,7,2},{41,37,1},{41,37,1},{7,1,184},{23,17,93},{7,19,122},{23,35,89},{23,1,260},{39,3,74},{39,35,15},
+{39,5,106},{41,3,247},{25,5,85},{37,17,81},{7,33,5},{37,19,19},{7,35,17},{19,9,243},{39,3,73},{23,35,10},{41,5,80},{45,1,243},{41,5,80},{23,1,80},{23,1,80},{23,1,80},{23,35,80},{39,17,51},{39,35,6},{39,35,6},{39,21,6},{25,35,54},{9,21,9},{7,33,4},{7,33,4},{7,33,4},{7,5,5},{23,3,50},{23,35,1},{23,35,1},{9,21,5},{43,3,50},
+{9,21,5},{21,3,72},{7,33,1},{37,19,10},{23,35,9},{21,3,72},{43,1,72},{23,35,9},{0,5,80},{43,1,72},{0,5,80},{23,0,80},{23,0,80},{23,0,80},{23,0,80},{39,19,1},{39,19,1},{39,19,1},{39,21,2},{25,5,5},{25,5,5},{21,1,234},{37,1,79},{37,3,110},{37,3,90},{37,1,300},{7,33,82},{7,3,9},{23,19,139},{41,17,248},{9,19,83},{21,1,90},
+{21,17,2},{21,3,4},{21,3,25},{21,17,243},{23,17,74},{7,3,5},{25,19,75},{17,21,243},{25,19,75},{37,1,75},{37,1,75},{37,1,75},{37,19,74},{7,1,56},{7,19,6},{7,19,6},{7,5,21},{9,3,53},{9,35,6},{21,17,1},{21,17,1},{21,17,1},{21,19,4},{3,25,50},{7,19,2},{7,19,2},{9,35,2},{29,1,50},{9,35,2},{17,39,72},{21,17,2},{5,3,4},
+{23,3,0},{17,39,72},{39,17,72},{23,3,0},{0,19,74},{39,17,72},{0,19,74},{37,0,74},{37,0,74},{37,0,74},{37,0,74},{7,3,5},{7,3,5},{7,3,5},{7,5,5},{9,35,5},{9,35,5},{5,1,290},{5,1,103},{5,17,110},{21,33,106},{5,1,345},{37,1,78},{37,17,13},{37,3,119},{39,1,248},{23,3,91},{35,1,126},{35,1,6},{35,17,8},{5,33,29},{35,1,243},
+{37,1,74},{37,17,9},{9,33,81},{1,35,243},{9,33,81},{5,1,94},{5,1,94},{5,1,94},{21,33,90},{21,1,61},{37,17,9},{37,17,9},{37,19,9},{23,33,53},{7,19,8},{35,17,4},{35,17,4},{35,17,4},{35,3,4},{19,5,50},{21,33,0},{21,33,0},{7,19,4},{37,3,50},{7,19,4},{17,5,72},{35,1,2},{35,17,4},{7,17,4},{17,5,72},{5,17,72},{7,17,4},
+{0,33,80},{5,17,72},{0,33,80},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{37,1,4},{37,1,4},{37,1,4},{37,19,5},{23,3,1},{23,3,1},{19,1,349},{35,1,185},{35,1,121},{35,1,81},{19,1,398},{5,1,102},{5,1,2},{21,17,122},{37,1,270},{7,17,66},{3,1,126},{19,1,45},{19,1,9},{19,1,25},{33,33,221},{35,1,82},{5,1,1},{23,17,61},{33,33,221},
+{23,17,61},{35,1,121},{35,1,121},{35,1,121},{35,17,73},{35,1,94},{5,1,2},{5,1,2},{5,33,17},{7,1,53},{37,33,1},{19,1,9},{19,1,9},{19,1,9},{19,17,1},{3,3,50},{5,1,1},{5,1,1},{37,33,0},{3,3,50},{37,33,0},{1,3,61},{33,1,25},{3,1,1},{5,1,1},{1,3,61},{3,1,61},{5,1,1},{0,17,61},{3,1,61},{0,17,61},{35,0,72},
+{35,0,72},{35,0,72},{35,0,72},{5,1,1},{5,1,1},{5,1,1},{5,3,1},{37,33,1},{37,33,1},{3,1,239},{3,1,164},{3,1,139},{19,1,89},{3,1,239},{19,1,62},{19,1,26},{35,17,34},{35,1,163},{21,1,10},{33,1,69},{33,1,29},{33,1,20},{33,1,4},{1,3,93},{3,1,38},{19,1,10},{21,1,10},{3,1,93},{21,1,10},{3,1,139},{3,1,139},{3,1,139},
+{19,1,89},{19,1,138},{19,1,26},{19,1,26},{35,17,9},{5,1,74},{5,17,8},{33,1,20},{33,1,20},{33,1,20},{33,1,4},{17,3,50},{19,1,10},{19,1,10},{5,17,4},{35,1,50},{5,17,4},{1,17,5},{17,1,1},{17,1,0},{33,1,0},{1,17,5},{17,1,5},{33,1,0},{0,1,9},{17,1,5},{0,1,9},{19,0,80},{19,0,80},{19,0,80},{19,0,80},{19,1,17},
+{19,1,17},{19,1,17},{35,17,5},{21,1,1},{21,1,1},{17,1,162},{33,1,130},{33,1,121},{33,1,81},{33,1,138},{33,1,58},{33,1,49},{3,1,1},{19,1,82},{19,1,10},{17,1,18},{17,1,10},{17,1,9},{17,1,1},{1,17,18},{17,1,6},{17,1,5},{3,1,0},{17,1,18},{3,1,0},{33,1,121},{33,1,121},{33,1,121},{33,1,81},{33,1,89},{33,1,49},{33,1,49},
+{3,1,1},{19,1,46},{19,1,10},{17,1,9},{17,1,9},{17,1,9},{17,1,1},{17,1,13},{17,1,5},{17,1,5},{3,1,0},{33,1,13},{3,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{33,0,72},{33,0,72},{33,0,72},{33,0,72},{3,1,26},{3,1,26},{3,1,26},{3,1,1},{19,1,10},
+{19,1,10},{0,38,200},{0,20,25},{0,34,5},{0,34,85},{0,20,442},{0,34,266},{0,18,125},{0,2,318},{0,18,482},{0,2,343},{0,38,200},{0,20,25},{0,34,5},{0,34,85},{16,4,441},{0,34,266},{0,18,125},{0,2,318},{4,16,441},{0,2,318},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,2,41},{0,32,13},{0,32,13},{0,16,25},{0,16,46},{0,16,26},{0,4,1},
+{0,4,1},{0,4,1},{0,2,1},{0,2,41},{0,32,13},{0,32,13},{0,16,25},{2,0,41},{0,16,25},{18,2,200},{0,20,25},{0,34,5},{0,34,85},{18,2,200},{38,0,200},{0,34,85},{0,18,208},{38,0,200},{0,18,208},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,10,202},{0,22,1},{0,20,26},
+{0,4,41},{0,22,689},{0,20,352},{0,4,141},{0,18,468},{0,34,750},{0,18,504},{0,10,202},{0,22,1},{0,20,26},{0,4,41},{34,0,686},{0,20,352},{0,4,141},{0,18,468},{0,34,686},{0,18,468},{0,22,0},{0,22,0},{0,22,0},{0,34,1},{0,34,145},{0,18,45},{0,18,45},{0,32,85},{0,32,158},{0,32,94},{0,22,0},{0,22,0},{0,22,0},{0,34,1},{16,2,145},
+{0,18,45},{0,18,45},{0,32,85},{34,0,145},{0,32,85},{20,16,200},{0,22,1},{16,20,5},{0,4,41},{20,16,200},{16,20,200},{0,4,41},{0,34,200},{16,20,200},{0,34,200},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{16,12,229},{16,8,30},{16,6,74},{16,36,58},{0,10,723},{0,6,282},{0,36,69},
+{0,4,414},{0,20,868},{0,34,513},{16,12,204},{16,8,5},{32,6,29},{16,36,33},{4,2,723},{0,6,282},{0,36,69},{0,4,414},{10,0,723},{0,4,414},{16,8,30},{16,8,30},{16,8,30},{16,4,33},{0,6,164},{0,4,25},{0,4,25},{0,18,65},{0,18,206},{0,18,101},{16,8,5},{16,8,5},{16,8,5},{16,4,8},{2,2,162},{0,4,25},{0,4,25},{0,18,65},{2,2,162},
+{0,18,65},{18,8,200},{16,8,1},{2,36,5},{0,36,20},{18,8,200},{44,0,200},{0,36,20},{0,4,218},{44,0,200},{0,4,218},{16,0,29},{16,0,29},{16,0,29},{16,0,29},{0,18,1},{0,18,1},{0,18,1},{0,32,0},{0,32,9},{0,32,9},{16,30,327},{32,40,139},{32,22,202},{16,6,151},{0,28,724},{0,8,236},{0,22,14},{0,20,350},{0,6,956},{0,20,494},{2,12,203},
+{2,24,2},{2,22,27},{2,6,42},{36,2,723},{0,8,236},{0,22,14},{0,20,350},{20,4,723},{0,20,350},{16,42,125},{16,42,125},{16,42,125},{16,6,126},{0,24,164},{0,6,1},{0,6,1},{0,4,37},{0,4,280},{0,34,109},{2,24,1},{2,24,1},{2,24,1},{2,36,2},{18,4,162},{0,6,1},{0,6,1},{0,4,37},{36,2,162},{0,4,37},{8,0,200},{2,24,1},{18,22,5},
+{0,22,10},{8,0,200},{47,0,200},{0,22,10},{0,36,200},{47,0,200},{0,36,200},{16,0,125},{16,0,125},{16,0,125},{16,0,125},{0,6,0},{0,6,0},{0,6,0},{0,18,1},{0,18,37},{0,18,37},{2,46,410},{2,26,218},{2,8,317},{2,38,226},{16,30,725},{16,40,217},{16,38,15},{0,6,312},{0,38,988},{0,6,417},{34,28,209},{18,26,13},{34,8,27},{18,38,34},{8,0,723},
+{0,40,203},{16,38,14},{0,6,296},{47,0,723},{0,6,296},{2,12,208},{2,12,208},{2,12,208},{2,22,209},{16,42,163},{16,38,6},{16,38,6},{16,20,26},{0,6,285},{0,20,81},{18,26,9},{18,26,9},{18,26,9},{34,6,10},{2,24,162},{32,22,5},{32,22,5},{0,20,17},{28,0,162},{0,20,17},{24,2,200},{18,26,4},{4,8,9},{0,8,10},{24,2,200},{13,0,200},{0,8,10},
+{0,22,208},{13,0,200},{0,22,208},{2,0,208},{2,0,208},{2,0,208},{2,0,208},{16,8,1},{16,8,1},{16,8,1},{16,4,2},{0,4,45},{0,4,45},{18,15,402},{18,12,222},{34,24,331},{18,24,218},{32,47,725},{32,26,212},{32,24,5},{32,38,324},{0,24,884},{0,38,300},{4,30,200},{4,26,5},{4,24,36},{4,8,41},{40,0,723},{16,26,203},{32,24,4},{0,38,251},{46,2,723},
+{0,38,251},{18,14,203},{18,14,203},{18,14,203},{18,8,202},{32,28,163},{32,24,5},{32,24,5},{32,6,21},{0,38,219},{0,6,13},{4,26,1},{4,26,1},{4,26,1},{4,38,0},{22,2,162},{2,8,1},{2,8,1},{0,6,4},{42,2,162},{0,6,4},{16,11,200},{34,42,4},{20,24,4},{32,24,0},{16,11,200},{25,0,200},{32,24,0},{0,38,202},{25,0,200},{0,38,202},{18,0,202},
+{18,0,202},{18,0,202},{18,0,202},{32,40,1},{32,40,1},{32,40,1},{32,36,1},{0,6,9},{0,6,9},{4,15,408},{4,28,221},{4,10,317},{4,40,221},{18,31,725},{18,42,217},{18,40,6},{2,8,315},{0,26,788},{0,8,228},{20,47,204},{20,12,6},{36,10,27},{20,40,33},{10,2,723},{32,12,203},{18,40,5},{0,8,227},{45,2,723},{0,8,227},{4,14,208},{4,14,208},{4,14,208},
+{4,24,209},{18,44,163},{18,40,2},{18,40,2},{18,22,26},{0,24,179},{0,38,3},{20,12,5},{20,12,5},{20,12,5},{20,24,5},{8,2,162},{18,40,1},{18,40,1},{0,38,2},{30,2,162},{0,38,2},{26,4,200},{20,12,2},{6,40,5},{18,40,4},{26,4,200},{7,0,200},{18,40,4},{0,24,208},{7,0,200},{0,24,208},{4,0,208},{4,0,208},{4,0,208},{4,0,208},{18,10,1},
+{18,10,1},{18,10,1},{18,6,2},{0,38,2},{0,38,2},{20,13,402},{20,14,220},{36,26,331},{20,26,216},{34,45,725},{34,12,213},{34,26,5},{34,24,337},{0,12,740},{16,40,216},{6,31,202},{6,28,1},{6,26,36},{6,10,41},{42,2,723},{18,28,200},{34,26,4},{0,40,209},{44,6,723},{0,40,209},{20,46,200},{20,46,200},{20,46,200},{20,10,201},{34,30,163},{34,26,5},{34,26,5},
+{34,8,18},{0,26,164},{32,8,2},{6,28,0},{6,28,0},{6,28,0},{6,40,1},{24,4,162},{4,10,1},{4,10,1},{2,8,2},{11,0,162},{2,8,2},{14,0,200},{6,28,1},{22,26,4},{34,26,0},{14,0,200},{8,10,200},{34,26,0},{0,40,200},{8,10,200},{0,40,200},{20,0,200},{20,0,200},{20,0,200},{20,0,200},{34,42,1},{34,42,1},{34,42,1},{34,38,1},{32,8,1},
+{32,8,1},{6,13,404},{6,30,219},{6,12,327},{6,42,215},{20,29,725},{20,44,217},{20,12,9},{4,10,321},{0,14,723},{32,26,222},{38,15,206},{38,14,8},{38,12,24},{22,42,34},{14,0,723},{4,14,203},{20,12,8},{0,26,203},{8,10,723},{0,26,203},{6,47,202},{6,47,202},{6,47,202},{6,26,206},{20,46,163},{20,12,5},{20,12,5},{20,24,30},{32,42,164},{2,40,6},{38,44,4},
+{38,44,4},{38,44,4},{38,10,5},{38,10,162},{20,12,4},{20,12,4},{2,40,2},{23,0,162},{2,40,2},{30,2,200},{38,14,4},{8,12,4},{4,12,4},{30,2,200},{35,2,200},{4,12,4},{0,26,202},{35,2,200},{0,26,202},{6,0,202},{6,0,202},{6,0,202},{6,0,202},{20,12,1},{20,12,1},{20,12,1},{20,8,2},{2,10,4},{2,10,4},{22,11,402},{22,47,227},{38,44,321},
+{22,28,218},{36,27,727},{36,30,215},{36,28,13},{36,42,327},{32,30,725},{18,42,212},{8,29,200},{8,30,4},{24,28,29},{8,12,45},{0,1,723},{20,30,203},{6,28,5},{32,42,202},{1,0,723},{32,42,202},{22,15,202},{22,15,202},{22,15,202},{22,12,202},{36,15,168},{36,28,13},{36,28,13},{36,10,17},{2,28,163},{34,10,9},{8,30,0},{8,30,0},{8,30,0},{8,42,0},{28,2,162},
+{6,12,5},{6,12,5},{4,10,4},{42,8,162},{4,10,4},{47,2,200},{8,30,4},{24,28,4},{36,28,0},{47,2,200},{17,2,200},{36,28,0},{0,42,202},{17,2,200},{0,42,202},{22,0,202},{22,0,202},{22,0,202},{22,0,202},{36,14,5},{36,14,5},{36,14,5},{36,40,4},{34,26,2},{34,26,2},{8,11,408},{8,31,221},{8,14,312},{8,44,226},{22,27,724},{22,46,217},{22,44,12},
+{6,12,321},{2,47,728},{34,28,234},{40,29,209},{24,47,10},{40,14,22},{24,44,34},{18,3,723},{36,47,203},{22,44,11},{32,28,208},{45,8,723},{32,28,208},{8,15,209},{8,15,209},{8,15,209},{8,28,209},{22,15,165},{22,44,3},{22,44,3},{22,26,30},{34,44,164},{4,42,6},{40,30,10},{40,30,10},{40,30,10},{40,12,10},{16,3,162},{22,44,2},{22,44,2},{4,42,2},{17,0,162},
+{4,42,2},{15,2,200},{24,47,1},{10,14,4},{6,14,5},{15,2,200},{33,4,200},{6,14,5},{0,28,208},{33,4,200},{0,28,208},{8,0,208},{8,0,208},{8,0,208},{8,0,208},{22,14,1},{22,14,1},{22,14,1},{22,10,2},{4,12,4},{4,12,4},{24,9,402},{24,45,227},{40,46,324},{24,30,218},{38,25,727},{38,47,213},{38,30,13},{38,28,325},{34,31,727},{20,44,218},{10,27,202},
+{10,31,1},{26,30,29},{10,14,45},{4,3,723},{22,31,200},{8,30,8},{34,44,202},{3,4,723},{34,44,202},{24,13,202},{24,13,202},{24,13,202},{24,14,202},{38,13,168},{38,30,13},{38,30,13},{38,12,17},{4,30,163},{36,12,9},{10,31,0},{10,31,0},{10,31,0},{10,44,0},{30,4,162},{8,14,4},{8,14,4},{6,12,4},{15,8,162},{6,12,4},{43,0,200},{10,31,1},{26,30,4},
+{38,30,0},{43,0,200},{19,6,200},{38,30,0},{0,44,202},{19,6,200},{0,44,202},{24,0,202},{24,0,202},{24,0,202},{24,0,202},{38,46,5},{38,46,5},{38,46,5},{38,42,4},{20,28,4},{20,28,4},{10,9,404},{10,29,219},{26,47,330},{10,46,222},{24,9,723},{24,15,209},{24,47,18},{8,14,324},{4,45,723},{36,30,222},{42,11,206},{42,15,8},{42,47,22},{26,46,41},{43,0,723},
+{8,15,202},{24,47,18},{4,30,202},{19,6,723},{4,30,202},{10,43,202},{10,43,202},{10,43,202},{10,30,206},{24,13,162},{24,46,8},{24,46,8},{24,44,25},{20,47,168},{22,44,4},{42,15,4},{42,15,4},{42,15,4},{42,14,8},{45,0,162},{40,46,4},{40,46,4},{22,44,0},{27,8,162},{22,44,0},{38,3,200},{42,15,4},{12,47,9},{8,47,10},{38,3,200},{35,8,200},{8,47,10},
+{0,30,202},{35,8,200},{0,30,202},{10,0,202},{10,0,202},{10,0,202},{10,0,202},{24,47,0},{24,47,0},{24,47,0},{24,12,4},{22,44,4},{22,44,4},{26,7,408},{42,13,236},{42,15,332},{26,31,224},{40,23,727},{40,45,213},{40,31,8},{40,46,312},{36,29,725},{22,46,218},{12,25,201},{12,13,6},{28,31,29},{12,47,42},{11,0,723},{24,29,203},{40,31,4},{6,46,209},{5,8,723},
+{6,46,209},{26,41,208},{26,41,208},{26,41,208},{26,47,208},{40,11,168},{40,31,8},{40,31,8},{40,14,22},{6,31,163},{38,30,10},{12,13,2},{12,13,2},{12,13,2},{12,46,2},{29,2,162},{10,47,2},{10,47,2},{22,30,9},{35,6,162},{22,30,9},{41,2,200},{42,13,4},{44,31,1},{40,31,0},{41,2,200},{17,8,200},{40,31,0},{0,46,208},{17,8,200},{0,46,208},{26,0,208},
+{26,0,208},{26,0,208},{26,0,208},{40,15,4},{40,15,4},{40,15,4},{40,44,5},{38,30,1},{38,30,1},{12,7,404},{12,27,212},{12,45,332},{12,15,215},{26,23,724},{26,13,216},{26,15,8},{26,47,318},{6,43,723},{8,47,227},{44,9,206},{44,13,8},{44,45,22},{28,15,38},{24,3,723},{10,13,202},{26,15,8},{6,31,209},{3,24,723},{6,31,209},{12,41,202},{12,41,202},{12,41,202},
+{12,31,203},{26,11,162},{26,15,4},{26,15,4},{26,46,25},{38,15,162},{24,46,4},{44,13,4},{44,13,4},{44,13,4},{44,47,5},{43,2,162},{26,15,4},{26,15,4},{24,46,0},{21,8,162},{24,46,0},{29,12,200},{28,43,2},{14,15,8},{26,15,4},{29,12,200},{26,13,200},{26,15,4},{0,31,208},{26,13,200},{0,31,208},{12,0,202},{12,0,202},{12,0,202},{12,0,202},{26,45,0},
+{26,45,0},{26,45,0},{26,14,4},{24,46,4},{24,46,4},{28,5,402},{28,41,222},{44,13,332},{28,29,218},{42,21,727},{42,43,213},{42,29,8},{42,31,340},{38,27,724},{24,15,217},{14,23,201},{14,27,3},{30,29,29},{14,45,42},{9,2,723},{26,27,201},{42,29,4},{22,15,201},{2,9,723},{22,15,201},{28,9,202},{28,9,202},{28,9,202},{28,45,203},{42,9,168},{42,29,8},{42,29,8},
+{42,47,21},{8,29,163},{40,47,2},{14,11,2},{14,11,2},{14,11,2},{14,15,2},{38,1,162},{12,45,2},{12,45,2},{10,47,2},{43,28,162},{10,47,2},{37,0,200},{14,27,2},{46,29,1},{42,29,0},{37,0,200},{36,9,200},{42,29,0},{0,15,200},{36,9,200},{0,15,200},{28,0,202},{28,0,202},{28,0,202},{28,0,202},{42,13,4},{42,13,4},{42,13,4},{42,46,5},{40,47,1},
+{40,47,1},{14,35,400},{14,25,217},{30,43,340},{14,13,213},{28,5,723},{28,11,209},{28,43,8},{12,45,332},{8,41,724},{40,29,222},{46,7,201},{46,41,2},{46,43,21},{30,13,41},{37,0,723},{12,41,203},{28,43,8},{8,29,202},{36,9,723},{8,29,202},{14,23,201},{14,23,201},{14,23,201},{14,13,204},{28,9,162},{28,43,4},{28,43,4},{28,31,29},{40,13,164},{26,15,3},{46,11,2},
+{46,11,2},{46,11,2},{46,29,5},{39,0,162},{44,13,2},{44,13,2},{10,15,2},{9,28,162},{10,15,2},{21,2,200},{46,41,1},{47,43,5},{12,43,4},{21,2,200},{24,9,200},{12,43,4},{0,29,202},{24,9,200},{0,29,202},{14,0,200},{14,0,200},{14,0,200},{14,0,200},{28,43,0},{28,43,0},{28,43,0},{28,47,1},{26,15,2},{26,15,2},{30,3,410},{46,9,227},{46,27,318},
+{30,27,224},{14,5,728},{44,25,215},{14,27,8},{44,13,332},{40,25,725},{26,13,212},{47,21,200},{47,25,4},{47,27,25},{47,43,52},{5,0,723},{28,25,203},{14,27,4},{40,13,202},{0,5,723},{40,13,202},{30,7,209},{30,7,209},{30,7,209},{30,43,208},{14,39,166},{14,27,8},{14,27,8},{44,45,22},{10,27,163},{12,45,8},{47,25,0},{47,25,0},{47,25,0},{47,13,0},{23,2,162},
+{14,27,4},{14,27,4},{12,45,4},{20,9,162},{12,45,4},{35,2,200},{47,25,4},{15,27,4},{44,27,0},{35,2,200},{34,5,200},{44,27,0},{0,13,202},{34,5,200},{0,13,202},{30,0,208},{30,0,208},{30,0,208},{30,0,208},{14,27,4},{14,27,4},{14,27,4},{14,15,8},{42,29,2},{42,29,2},{47,3,408},{47,23,218},{47,41,312},{47,11,226},{30,3,723},{30,9,209},{30,41,8},
+{14,43,332},{10,39,723},{12,43,236},{15,21,209},{31,39,10},{15,41,22},{31,11,43},{30,3,723},{44,39,204},{30,41,8},{40,27,208},{42,9,723},{40,27,208},{47,7,209},{47,7,209},{47,7,209},{47,27,208},{30,7,162},{30,41,4},{30,41,4},{30,29,29},{42,11,164},{12,13,6},{31,23,9},{31,23,9},{31,23,9},{31,27,10},{37,2,162},{46,11,2},{46,11,2},{12,13,2},{34,7,162},
+{12,13,2},{46,1,200},{31,39,1},{45,41,5},{14,41,4},{46,1,200},{26,7,200},{14,41,4},{0,27,208},{26,7,200},{0,27,208},{47,0,208},{47,0,208},{47,0,208},{47,0,208},{30,41,0},{30,41,0},{30,41,0},{30,45,1},{12,43,4},{12,43,4},{31,1,402},{31,37,222},{15,9,324},{31,25,218},{46,17,733},{46,23,215},{46,25,18},{46,27,330},{42,23,725},{28,11,219},{45,19,202},
+{45,23,4},{45,25,25},{45,41,52},{3,2,723},{30,23,203},{47,25,8},{42,11,202},{2,3,723},{42,11,202},{31,5,202},{31,5,202},{31,5,202},{31,41,202},{46,5,173},{46,25,18},{46,25,18},{46,43,22},{12,25,163},{14,43,8},{45,23,0},{45,23,0},{45,23,0},{45,11,0},{44,1,162},{47,41,4},{47,41,4},{14,43,4},{26,9,162},{14,43,4},{31,1,200},{45,23,4},{13,25,4},
+{46,25,0},{31,1,200},{32,1,200},{46,25,0},{0,11,202},{32,1,200},{0,11,202},{31,0,202},{31,0,202},{31,0,202},{31,0,202},{46,9,10},{46,9,10},{46,9,10},{46,13,9},{28,27,4},{28,27,4},{45,1,404},{45,21,218},{29,39,325},{45,9,222},{31,1,723},{31,7,209},{31,39,13},{47,41,324},{12,37,725},{44,25,227},{13,3,206},{13,37,9},{13,39,17},{29,9,48},{31,1,723},
+{47,7,208},{31,39,13},{12,25,202},{32,1,723},{12,25,202},{45,35,202},{45,35,202},{45,35,202},{45,25,203},{31,5,162},{31,9,8},{31,9,8},{31,27,29},{14,9,166},{30,11,1},{13,7,4},{13,7,4},{13,7,4},{13,25,8},{31,5,162},{15,9,4},{15,9,4},{30,11,0},{14,9,162},{30,11,0},{17,6,200},{29,21,4},{43,39,4},{46,39,5},{17,6,200},{20,1,200},{46,39,5},
+{0,25,202},{20,1,200},{0,25,202},{45,0,202},{45,0,202},{45,0,202},{45,0,202},{31,39,0},{31,39,0},{31,39,0},{31,27,4},{30,11,1},{30,11,1},{13,1,440},{29,35,234},{13,7,321},{29,23,218},{45,1,732},{15,21,215},{45,23,12},{15,9,312},{44,21,731},{30,9,221},{43,17,201},{43,5,6},{27,23,30},{43,39,46},{45,1,723},{31,21,203},{45,23,3},{14,9,209},{27,9,723},
+{14,9,209},{29,33,208},{29,33,208},{29,33,208},{29,39,208},{15,3,168},{45,23,11},{45,23,11},{15,41,22},{14,23,168},{46,25,10},{43,5,2},{43,5,2},{43,5,2},{43,9,2},{17,2,162},{45,23,2},{45,23,2},{30,25,10},{16,1,162},{30,25,10},{27,3,200},{13,5,4},{11,23,2},{15,23,1},{27,3,200},{39,9,200},{15,23,1},{0,9,208},{39,9,200},{0,9,208},{29,0,208},
+{29,0,208},{29,0,208},{29,0,208},{15,7,5},{15,7,5},{15,7,5},{15,11,4},{46,25,1},{46,25,1},{43,1,500},{43,19,212},{43,37,327},{43,7,220},{13,1,760},{29,5,209},{29,37,13},{45,39,321},{14,35,724},{46,23,227},{11,1,206},{11,35,9},{11,37,17},{27,7,43},{33,10,723},{15,35,204},{29,37,13},{14,23,202},{38,1,723},{14,23,202},{43,33,202},{43,33,202},{43,33,202},
+{43,23,203},{29,3,162},{29,7,5},{29,7,5},{29,25,29},{46,7,165},{31,9,4},{11,5,4},{11,5,4},{11,5,4},{11,39,5},{29,3,162},{13,7,5},{13,7,5},{31,9,0},{43,9,162},{31,9,0},{39,7,200},{27,35,2},{41,37,4},{15,37,5},{39,7,200},{26,1,200},{15,37,5},{0,23,202},{26,1,200},{0,23,202},{43,0,202},{43,0,202},{43,0,202},{43,0,202},{29,37,0},
+{29,37,0},{29,37,0},{29,25,4},{31,9,4},{31,9,4},{11,1,530},{27,33,222},{11,5,321},{27,21,219},{27,1,812},{13,19,215},{13,21,9},{13,7,327},{46,19,724},{31,7,219},{25,1,225},{41,3,6},{25,21,30},{41,37,46},{41,3,723},{29,19,203},{13,21,5},{46,7,202},{21,9,723},{46,7,202},{27,1,203},{27,1,203},{27,1,203},{27,37,202},{13,1,168},{13,21,8},{13,21,8},
+{13,39,24},{47,21,163},{15,39,8},{41,3,2},{41,3,2},{41,3,2},{41,7,1},{39,11,162},{13,21,4},{13,21,4},{45,39,4},{22,1,162},{45,39,4},{25,1,200},{11,3,4},{9,21,2},{13,21,1},{25,1,200},{33,9,200},{13,21,1},{0,7,202},{33,9,200},{0,7,202},{27,0,202},{27,0,202},{27,0,202},{27,0,202},{13,5,4},{13,5,4},{13,5,4},{13,9,4},{15,39,4},
+{15,39,4},{25,1,634},{41,17,216},{25,35,337},{41,5,220},{41,1,863},{27,3,211},{27,35,5},{27,37,331},{47,33,725},{15,21,220},{9,1,251},{9,33,2},{9,35,18},{25,5,48},{25,1,723},{43,33,203},{27,35,5},{47,21,200},{33,9,723},{47,21,200},{41,1,209},{41,1,209},{41,1,209},{41,5,204},{27,1,164},{27,35,4},{27,35,4},{27,7,36},{15,5,164},{29,7,1},{9,3,2},
+{9,3,2},{9,3,2},{9,21,2},{25,5,162},{11,5,1},{11,5,1},{29,7,0},{10,1,162},{29,7,0},{23,17,200},{9,33,1},{39,35,1},{43,35,1},{23,17,200},{45,17,200},{43,35,1},{0,21,200},{45,17,200},{0,21,200},{41,0,200},{41,0,200},{41,0,200},{41,0,200},{27,35,0},{27,35,0},{27,35,0},{27,23,4},{29,7,1},{29,7,1},{39,1,724},{9,1,228},{9,3,315},
+{25,19,218},{9,1,932},{11,17,213},{41,19,6},{11,5,317},{15,17,725},{29,5,221},{23,1,288},{39,1,3},{23,19,26},{39,19,51},{39,1,723},{27,17,203},{41,19,2},{15,5,208},{31,1,723},{15,5,208},{9,1,227},{9,1,227},{9,1,227},{25,35,209},{41,1,174},{41,19,5},{41,19,5},{11,37,27},{45,19,163},{13,21,6},{39,1,2},{39,1,2},{39,1,2},{39,5,2},{9,3,162},
+{41,19,1},{41,19,1},{13,21,5},{31,3,162},{13,21,5},{21,3,200},{39,1,2},{7,19,2},{11,19,1},{21,3,200},{43,1,200},{11,19,1},{0,5,208},{43,1,200},{0,5,208},{25,0,208},{25,0,208},{25,0,208},{25,0,208},{41,19,4},{41,19,4},{41,19,4},{41,7,5},{13,21,2},{13,21,2},{23,1,864},{39,1,300},{39,33,324},{39,3,222},{39,1,1020},{25,1,211},{25,33,5},
+{25,35,331},{29,1,732},{13,19,222},{37,1,347},{7,1,13},{7,33,21},{23,3,48},{1,13,723},{25,1,211},{25,33,5},{15,19,203},{13,1,723},{15,19,203},{39,1,251},{39,1,251},{39,1,251},{39,19,203},{9,1,195},{25,33,4},{25,33,4},{25,5,36},{13,3,164},{27,5,5},{7,1,4},{7,1,4},{7,1,4},{7,35,8},{23,3,162},{9,3,1},{9,3,1},{27,5,1},{43,3,162},
+{27,5,1},{17,39,200},{7,1,9},{37,33,1},{41,33,1},{17,39,200},{39,17,200},{41,33,1},{0,19,202},{39,17,200},{0,19,202},{39,0,202},{39,0,202},{39,0,202},{39,0,202},{25,33,0},{25,33,0},{25,33,0},{25,21,4},{43,35,4},{43,35,4},{37,1,1012},{7,1,417},{7,1,312},{23,17,218},{7,1,1144},{39,1,268},{39,17,15},{9,3,317},{27,1,804},{27,3,218},{5,1,398},
+{21,1,81},{21,17,26},{37,17,51},{35,3,723},{23,1,254},{39,17,6},{13,3,208},{25,1,723},{13,3,208},{7,1,296},{7,1,296},{7,1,296},{23,33,209},{39,1,243},{39,17,14},{39,17,14},{9,35,27},{43,17,163},{27,19,13},{21,1,17},{21,1,17},{21,1,17},{37,3,1},{3,25,162},{39,17,5},{39,17,5},{27,19,9},{29,1,162},{27,19,9},{19,1,200},{5,1,45},{5,17,2},
+{9,17,1},{19,1,200},{37,1,200},{9,17,1},{0,3,208},{37,1,200},{0,3,208},{23,0,208},{23,0,208},{23,0,208},{23,0,208},{9,1,10},{9,1,10},{9,1,10},{9,5,9},{27,19,4},{27,19,4},{5,1,919},{21,1,494},{21,1,350},{37,1,201},{21,1,1014},{7,1,251},{23,1,14},{23,33,202},{9,1,721},{41,33,139},{19,1,341},{35,1,109},{5,1,37},{5,1,26},{3,3,546},
+{37,1,213},{7,1,1},{43,17,125},{3,3,546},{43,17,125},{21,1,350},{21,1,350},{21,1,350},{37,1,201},{37,1,312},{23,1,14},{23,1,14},{23,3,27},{41,1,168},{25,3,2},{5,1,37},{5,1,37},{5,1,37},{5,17,5},{19,5,162},{7,1,1},{7,1,1},{25,3,1},{37,3,162},{25,3,1},{33,1,113},{19,1,37},{19,1,1},{7,1,0},{33,1,113},{35,1,113},{7,1,0},
+{0,17,125},{35,1,113},{0,17,125},{37,0,200},{37,0,200},{37,0,200},{37,0,200},{23,1,10},{23,1,10},{23,1,10},{23,19,5},{25,3,1},{25,3,1},{35,1,773},{35,1,513},{5,1,414},{5,1,227},{35,1,818},{21,1,218},{37,1,69},{7,17,74},{23,1,534},{9,17,30},{3,1,190},{19,1,101},{19,1,65},{35,1,5},{33,33,333},{35,1,114},{5,1,25},{9,17,30},{33,33,333},
+{9,17,30},{5,1,414},{5,1,414},{5,1,414},{5,1,227},{21,1,373},{37,1,69},{37,1,69},{7,33,29},{9,1,216},{9,17,5},{19,1,65},{19,1,65},{19,1,65},{35,1,5},{3,3,162},{5,1,25},{5,1,25},{9,17,5},{3,3,162},{9,17,5},{17,1,25},{33,1,9},{33,1,0},{19,1,1},{17,1,25},{33,1,25},{19,1,1},{0,17,29},{33,1,25},{0,17,29},{5,0,218},
+{5,0,218},{5,0,218},{5,0,218},{37,1,20},{37,1,20},{37,1,20},{37,3,5},{9,17,1},{9,17,1},{3,1,642},{19,1,504},{19,1,468},{35,1,264},{19,1,657},{35,1,229},{5,1,141},{21,1,26},{21,1,457},{23,1,1},{33,1,134},{33,1,94},{33,1,85},{3,1,26},{1,19,193},{19,1,81},{19,1,45},{23,1,0},{19,1,193},{23,1,0},{19,1,468},{19,1,468},{19,1,468},
+{35,1,264},{35,1,425},{5,1,141},{5,1,141},{21,1,26},{7,1,254},{23,1,1},{33,1,85},{33,1,85},{33,1,85},{3,1,26},{17,3,145},{19,1,45},{19,1,45},{23,1,0},{35,1,145},{23,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{35,0,200},{35,0,200},{35,0,200},{35,0,200},{5,1,41},
+{5,1,41},{5,1,41},{21,17,5},{23,1,1},{23,1,1},{3,1,418},{3,1,343},{3,1,318},{3,1,243},{3,1,370},{19,1,161},{19,1,125},{35,1,5},{35,1,250},{21,1,25},{17,1,34},{17,1,26},{17,1,25},{33,1,13},{17,1,54},{33,1,22},{33,1,13},{5,1,1},{33,1,54},{5,1,1},{3,1,318},{3,1,318},{3,1,318},{3,1,243},{3,1,270},{19,1,125},{19,1,125},
+{35,1,5},{5,1,165},{21,1,25},{17,1,25},{17,1,25},{17,1,25},{33,1,13},{1,3,41},{33,1,13},{33,1,13},{5,1,1},{3,1,41},{5,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{19,0,208},{19,0,208},{19,0,208},{19,0,208},{35,1,85},{35,1,85},{35,1,85},{35,1,5},{21,1,25},
+{21,1,25},{0,26,421},{0,38,45},{0,36,2},{0,20,160},{0,38,926},{0,20,577},{0,4,264},{0,18,701},{0,34,989},{0,18,737},{0,26,421},{0,38,45},{0,36,2},{0,20,160},{34,0,925},{0,20,577},{0,4,264},{0,18,701},{0,34,925},{0,18,701},{0,20,1},{0,20,1},{0,20,1},{0,18,1},{0,18,85},{0,2,34},{0,2,34},{0,32,53},{0,32,94},{0,32,62},{0,20,1},
+{0,20,1},{0,20,1},{0,18,1},{32,0,85},{0,2,34},{0,2,34},{0,32,53},{18,0,85},{0,32,53},{34,4,421},{0,38,45},{0,36,2},{0,20,160},{34,4,421},{26,0,421},{0,20,160},{0,34,421},{26,0,421},{0,34,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,44,421},{0,24,13},{0,22,32},
+{0,36,113},{0,24,1262},{0,6,670},{0,20,304},{0,4,886},{0,4,1382},{0,34,953},{0,44,421},{0,24,13},{0,22,32},{0,36,113},{18,4,1261},{0,6,670},{0,20,304},{0,4,886},{36,2,1261},{0,4,886},{0,8,0},{0,8,0},{0,8,0},{0,4,0},{0,4,221},{0,34,73},{0,34,73},{0,2,125},{0,2,246},{0,2,150},{0,8,0},{0,8,0},{0,8,0},{0,4,0},{2,0,221},
+{0,34,73},{0,34,73},{0,2,125},{4,0,221},{0,2,125},{22,0,421},{0,24,13},{16,6,8},{0,36,113},{22,0,421},{44,0,421},{0,36,113},{0,20,433},{44,0,421},{0,20,433},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,430},{0,26,10},{16,38,79},{0,22,74},{0,42,1514},{0,38,717},{0,6,253},
+{0,20,965},{0,36,1713},{0,4,1109},{16,46,425},{16,10,9},{16,38,54},{0,22,74},{20,2,1514},{0,38,717},{0,6,253},{0,20,965},{42,0,1514},{0,20,965},{0,26,10},{0,26,10},{0,26,10},{0,36,9},{0,6,340},{0,20,97},{0,20,97},{0,18,185},{0,18,382},{0,18,221},{16,10,5},{16,10,5},{16,10,5},{16,36,5},{2,2,338},{0,20,97},{0,20,97},{0,18,185},{2,2,338},
+{0,18,185},{8,0,421},{0,26,1},{2,38,2},{0,22,65},{8,0,421},{31,0,421},{0,22,65},{0,36,421},{31,0,421},{0,36,421},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,32,0},{0,32,0},{0,32,0},{0,16,0},{0,16,1},{0,16,1},{16,45,482},{16,12,66},{32,24,186},{16,8,126},{0,14,1517},{0,24,605},{0,38,117},{0,6,886},{0,22,1815},{0,36,1085},{32,31,421},
+{32,42,1},{2,8,51},{32,38,85},{22,16,1514},{0,24,605},{0,38,117},{0,6,886},{44,16,1514},{0,6,886},{16,28,61},{16,28,61},{16,28,61},{16,22,62},{0,24,340},{0,22,37},{0,22,37},{0,4,125},{0,4,456},{0,34,213},{32,42,0},{32,42,0},{32,42,0},{32,6,1},{18,4,338},{0,22,37},{0,22,37},{0,4,125},{36,2,338},{0,4,125},{40,0,421},{32,42,1},{18,8,5},
+{0,8,37},{40,0,421},{13,0,421},{0,8,37},{0,22,433},{13,0,421},{0,22,433},{16,0,61},{16,0,61},{16,0,61},{16,0,61},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,32,25},{0,32,25},{32,43,623},{32,44,219},{32,10,382},{32,24,243},{0,15,1517},{0,26,497},{0,24,35},{0,22,761},{0,8,2003},{0,22,1050},{18,15,422},{18,28,6},{18,40,51},{2,24,77},{24,0,1514},
+{0,26,497},{0,24,35},{0,22,761},{32,8,1514},{0,22,761},{32,30,202},{32,30,202},{32,30,202},{32,8,203},{0,28,338},{0,8,10},{0,8,10},{0,20,89},{0,6,565},{0,20,233},{18,12,1},{18,12,1},{18,12,1},{18,38,1},{2,24,338},{0,8,10},{0,8,10},{0,20,89},{28,0,338},{0,20,89},{40,4,421},{2,28,5},{4,40,1},{0,24,26},{40,4,421},{25,0,421},{0,24,26},
+{0,38,425},{25,0,421},{0,38,425},{32,0,202},{32,0,202},{32,0,202},{32,0,202},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{0,34,68},{0,34,68},{2,11,821},{2,30,429},{2,26,634},{2,10,429},{0,27,1514},{0,28,446},{0,10,8},{0,8,670},{0,40,2187},{0,38,1083},{34,29,422},{34,14,6},{4,26,50},{34,10,86},{38,6,1514},{0,28,446},{0,10,8},{0,8,670},{27,0,1514},
+{0,8,670},{2,31,401},{2,31,401},{2,31,401},{2,24,404},{0,46,340},{0,10,4},{0,10,4},{0,6,52},{0,22,677},{0,6,277},{34,14,2},{34,14,2},{34,14,2},{34,8,5},{22,2,338},{0,10,4},{0,10,4},{0,6,52},{42,2,338},{0,6,52},{28,0,421},{34,14,5},{36,10,5},{0,10,4},{28,0,421},{7,0,421},{0,10,4},{0,24,425},{7,0,421},{0,24,425},{2,0,400},
+{2,0,400},{2,0,400},{2,0,400},{0,26,0},{0,26,0},{0,26,0},{0,36,1},{0,4,149},{0,4,149},{18,9,842},{18,47,462},{34,12,661},{18,26,450},{16,25,1521},{16,14,441},{16,42,15},{16,24,653},{0,26,2030},{0,24,882},{20,13,425},{20,30,9},{20,42,54},{4,26,77},{26,2,1514},{0,14,422},{16,42,11},{0,24,626},{38,8,1514},{0,24,626},{18,45,421},{18,45,421},{18,45,421},
+{18,10,422},{16,15,344},{16,42,14},{16,42,14},{16,38,38},{0,24,602},{0,38,162},{20,14,4},{20,14,4},{20,14,4},{20,40,5},{8,2,338},{32,26,2},{32,26,2},{0,38,18},{30,2,338},{0,38,18},{14,0,421},{4,30,5},{6,42,1},{0,42,1},{14,0,421},{19,0,421},{0,42,1},{0,40,421},{19,0,421},{0,40,421},{18,0,421},{18,0,421},{18,0,421},{18,0,421},{16,12,5},
+{16,12,5},{16,12,5},{16,6,8},{0,6,80},{0,6,80},{4,9,854},{4,31,458},{4,28,674},{34,12,453},{2,25,1515},{32,30,445},{2,12,9},{32,10,657},{0,28,1850},{0,10,666},{36,27,422},{36,46,6},{6,28,48},{36,12,86},{16,7,1514},{16,46,421},{2,12,8},{0,10,545},{21,0,1514},{0,10,545},{34,13,433},{34,13,433},{34,13,433},{34,42,433},{2,15,339},{2,12,5},{2,12,5},
+{32,8,50},{0,10,477},{0,8,62},{36,46,2},{36,46,2},{36,46,2},{36,10,5},{24,4,338},{2,12,4},{2,12,4},{0,24,9},{11,0,338},{0,24,9},{0,1,421},{36,46,5},{38,12,5},{2,12,4},{0,1,421},{1,0,421},{2,12,4},{0,26,425},{1,0,421},{0,26,425},{4,0,433},{4,0,433},{4,0,433},{4,0,433},{2,28,1},{2,28,1},{2,28,1},{2,38,2},{0,8,37},
+{0,8,37},{20,7,842},{20,45,455},{36,14,655},{20,28,450},{34,9,1523},{18,47,450},{34,44,13},{18,42,659},{0,14,1731},{0,42,542},{22,11,422},{22,47,5},{22,44,50},{6,28,86},{30,0,1514},{2,47,421},{34,44,4},{0,42,506},{33,0,1514},{0,42,506},{20,43,421},{20,43,421},{20,43,421},{20,12,425},{18,13,347},{34,28,11},{34,28,11},{18,40,43},{0,12,389},{0,10,9},{22,47,1},
+{22,47,1},{22,47,1},{22,42,1},{38,10,338},{34,28,2},{34,28,2},{0,10,5},{23,0,338},{0,10,5},{2,1,421},{22,47,4},{8,44,0},{18,44,0},{2,1,421},{1,2,421},{18,44,0},{0,42,425},{1,2,421},{0,42,425},{20,0,421},{20,0,421},{20,0,421},{20,0,421},{18,30,9},{18,30,9},{18,30,9},{34,8,10},{0,10,5},{0,10,5},{6,37,846},{6,29,454},{6,46,685},
+{6,14,459},{4,7,1517},{4,31,446},{4,14,19},{34,12,655},{0,47,1635},{0,12,478},{38,9,425},{38,15,6},{8,30,41},{38,14,77},{47,0,1514},{18,15,422},{20,14,11},{0,12,477},{27,6,1514},{0,12,477},{6,27,426},{6,27,426},{6,27,426},{6,44,426},{4,13,340},{4,14,10},{4,14,10},{4,26,50},{0,44,355},{16,26,6},{38,15,5},{38,15,5},{38,15,5},{38,28,5},{28,2,338},
+{20,14,2},{20,14,2},{32,26,1},{42,8,338},{32,26,1},{29,0,421},{38,15,2},{40,14,10},{18,30,9},{29,0,421},{33,4,421},{18,30,9},{0,28,425},{33,4,421},{0,28,425},{6,0,425},{6,0,425},{6,0,425},{6,0,425},{4,30,1},{4,30,1},{4,30,1},{4,40,0},{16,26,5},{16,26,5},{22,5,842},{22,43,455},{38,47,679},{22,30,455},{20,21,1521},{20,15,438},{36,46,13},
+{20,28,653},{0,15,1553},{16,44,454},{24,9,422},{24,45,5},{24,46,50},{8,30,77},{34,3,1514},{4,45,422},{36,46,4},{0,44,434},{35,4,1514},{0,44,434},{22,41,421},{22,41,421},{22,41,421},{22,14,422},{20,11,342},{36,30,11},{36,30,11},{20,42,38},{0,46,340},{32,12,5},{24,45,1},{24,45,1},{24,45,1},{24,44,1},{16,3,338},{36,30,2},{36,30,2},{32,12,4},{17,0,338},
+{32,12,4},{43,0,421},{24,45,4},{10,46,0},{4,46,1},{43,0,421},{19,6,421},{4,46,1},{0,44,425},{19,6,421},{0,44,425},{22,0,421},{22,0,421},{22,0,421},{22,0,421},{20,31,5},{20,31,5},{20,31,5},{20,26,5},{32,12,1},{32,12,1},{8,5,854},{8,27,458},{24,31,670},{38,47,462},{6,5,1517},{6,29,446},{6,47,6},{36,14,655},{0,29,1530},{32,30,465},{40,23,422},
+{40,13,2},{10,31,48},{40,46,90},{45,2,1514},{20,13,425},{6,47,6},{0,30,434},{25,8,1514},{0,30,434},{8,25,434},{8,25,434},{8,25,434},{8,30,437},{6,11,340},{6,47,5},{6,47,5},{6,12,52},{16,47,342},{18,28,1},{40,13,1},{40,13,1},{40,13,1},{40,14,5},{30,4,338},{22,46,4},{22,46,4},{18,28,1},{15,8,338},{18,28,1},{11,0,421},{40,13,1},{26,47,5},
+{6,47,2},{11,0,421},{5,8,421},{6,47,2},{0,30,425},{5,8,421},{0,30,425},{8,0,433},{8,0,433},{8,0,433},{8,0,433},{6,31,0},{6,31,0},{6,31,0},{6,42,0},{18,28,1},{18,28,1},{24,33,846},{24,41,465},{40,15,658},{24,31,454},{38,5,1518},{22,13,446},{38,15,14},{22,46,667},{0,27,1518},{18,46,453},{26,7,421},{26,27,2},{42,15,53},{10,31,86},{27,0,1514},
+{6,43,425},{38,15,10},{16,46,434},{37,8,1514},{16,46,434},{24,23,426},{24,23,426},{24,23,426},{24,47,426},{38,25,344},{38,31,9},{38,31,9},{22,44,41},{18,31,341},{4,14,2},{26,27,1},{26,27,1},{26,27,1},{26,46,1},{45,0,338},{8,31,5},{8,31,5},{4,14,1},{27,8,338},{4,14,1},{8,1,421},{26,27,2},{12,15,1},{6,15,2},{8,1,421},{1,8,421},{6,15,2},
+{0,46,433},{1,8,421},{0,46,433},{24,0,425},{24,0,425},{24,0,425},{24,0,425},{38,15,4},{38,15,4},{38,15,4},{38,12,8},{4,14,1},{4,14,1},{10,33,846},{10,25,454},{26,29,658},{10,45,454},{8,3,1517},{8,27,446},{8,45,8},{38,47,650},{32,11,1518},{4,47,462},{42,5,425},{42,11,9},{12,29,43},{42,15,89},{28,13,1514},{22,11,422},{8,45,8},{16,31,426},{27,12,1514},
+{16,31,426},{10,23,425},{10,23,425},{10,23,425},{10,15,429},{8,9,340},{8,45,4},{8,45,4},{8,30,50},{34,45,341},{20,30,6},{42,11,5},{42,11,5},{42,11,5},{42,31,8},{29,2,338},{8,45,4},{8,45,4},{36,30,1},{35,6,338},{36,30,1},{23,0,421},{12,11,4},{44,45,5},{8,45,4},{23,0,421},{18,9,421},{8,45,4},{0,31,425},{18,9,421},{0,31,425},{10,0,425},
+{10,0,425},{10,0,425},{10,0,425},{8,13,1},{8,13,1},{8,13,1},{8,44,0},{20,30,5},{20,30,5},{26,1,846},{26,39,470},{42,13,658},{26,29,454},{40,3,1523},{24,11,446},{24,13,20},{24,31,658},{2,25,1521},{20,15,458},{28,5,422},{28,25,6},{28,13,51},{12,29,86},{40,3,1514},{8,41,421},{24,13,11},{18,15,421},{16,9,1514},{18,15,421},{26,21,426},{26,21,426},{26,21,426},
+{26,45,426},{24,7,347},{40,29,11},{40,29,11},{24,46,41},{20,29,342},{36,47,10},{28,41,1},{28,41,1},{28,41,1},{28,15,2},{43,2,338},{40,29,2},{40,29,2},{36,47,9},{21,8,338},{36,47,9},{37,0,421},{12,25,5},{14,13,1},{8,13,2},{37,0,421},{32,7,421},{8,13,2},{0,15,421},{32,7,421},{0,15,421},{26,0,425},{26,0,425},{26,0,425},{26,0,425},{24,27,9},
+{24,27,9},{24,27,9},{40,14,10},{36,47,1},{36,47,1},{12,1,850},{12,23,454},{12,27,666},{12,43,454},{10,1,1517},{10,25,446},{10,43,8},{40,45,666},{34,9,1515},{6,45,462},{44,3,425},{44,9,9},{14,27,50},{44,13,89},{39,2,1514},{24,9,422},{10,43,8},{18,29,426},{34,9,1514},{18,29,426},{12,21,425},{12,21,425},{12,21,425},{12,13,429},{10,7,340},{10,43,4},{10,43,4},
+{10,47,50},{36,43,341},{22,31,1},{44,9,5},{44,9,5},{44,9,5},{44,29,8},{38,1,338},{26,13,4},{26,13,4},{22,31,1},{43,28,338},{22,31,1},{5,0,421},{14,9,4},{46,43,5},{10,43,4},{5,0,421},{0,5,421},{10,43,4},{0,29,425},{0,5,421},{0,29,425},{12,0,425},{12,0,425},{12,0,425},{12,0,425},{10,27,0},{10,27,0},{10,27,0},{10,46,0},{22,31,1},
+{22,31,1},{44,1,890},{44,7,462},{44,41,666},{28,27,454},{42,1,1518},{26,39,446},{42,11,8},{26,13,666},{4,23,1523},{22,13,454},{30,33,421},{30,23,1},{46,11,50},{30,27,89},{21,0,1514},{40,23,425},{42,11,4},{20,13,425},{18,7,1514},{20,13,425},{28,19,426},{28,19,426},{28,19,426},{28,27,429},{42,21,344},{42,11,8},{42,11,8},{26,15,50},{6,11,341},{8,45,9},{30,23,1},
+{30,23,1},{30,23,1},{30,13,0},{39,0,338},{42,11,4},{42,11,4},{8,45,5},{9,28,338},{8,45,5},{14,1,421},{30,23,1},{47,11,0},{26,11,0},{14,1,421},{4,5,421},{26,11,0},{0,13,425},{4,5,421},{0,13,425},{28,0,425},{28,0,425},{28,0,425},{28,0,425},{42,11,4},{42,11,4},{42,11,4},{42,47,5},{8,15,4},{8,15,4},{30,1,950},{14,21,458},{30,25,658},
+{14,41,446},{28,1,1542},{12,23,438},{12,25,20},{12,43,658},{36,7,1518},{38,27,470},{46,1,430},{46,37,10},{47,25,41},{46,41,82},{14,3,1514},{26,7,422},{28,41,11},{20,27,426},{32,5,1514},{20,27,426},{14,19,421},{14,19,421},{14,19,421},{14,11,422},{12,35,339},{12,25,11},{12,25,11},{12,29,51},{38,41,338},{24,29,6},{46,37,9},{46,37,9},{46,37,9},{46,27,10},{23,2,338},
+{28,41,2},{28,41,2},{40,29,1},{20,9,338},{40,29,1},{17,0,421},{46,37,1},{31,25,10},{26,25,9},{17,0,421},{18,3,421},{26,25,9},{0,27,425},{18,3,421},{0,27,425},{14,0,421},{14,0,421},{14,0,421},{14,0,421},{12,9,2},{12,9,2},{12,9,2},{12,15,1},{24,13,5},{24,13,5},{46,1,1010},{46,5,462},{46,39,650},{30,25,454},{14,1,1575},{28,7,446},{44,9,8},
+{28,27,658},{6,21,1523},{24,11,454},{31,1,422},{31,21,6},{31,9,50},{47,25,77},{46,3,1514},{42,21,425},{44,9,4},{22,11,425},{16,3,1514},{22,11,425},{30,17,426},{30,17,426},{30,17,426},{30,25,429},{44,19,344},{44,9,8},{44,9,8},{28,13,43},{8,9,340},{10,43,9},{31,37,1},{31,37,1},{31,37,1},{31,11,2},{37,2,338},{44,9,4},{44,9,4},{10,43,5},{34,7,338},
+{10,43,5},{31,1,421},{31,21,5},{45,9,0},{12,9,1},{31,1,421},{32,1,421},{12,9,1},{0,11,425},{32,1,421},{0,11,425},{30,0,425},{30,0,425},{30,0,425},{30,0,425},{44,9,4},{44,9,4},{44,9,4},{44,45,5},{10,13,4},{10,13,4},{31,1,1098},{47,19,453},{47,23,667},{47,39,473},{46,1,1641},{14,21,438},{14,39,14},{14,41,658},{38,5,1518},{40,25,465},{45,1,437},
+{15,5,2},{45,23,41},{15,39,86},{31,3,1514},{28,5,422},{30,39,9},{22,25,426},{34,3,1514},{22,25,426},{47,17,434},{47,17,434},{47,17,434},{47,9,437},{14,33,339},{14,39,10},{14,39,10},{14,43,53},{40,39,341},{26,27,2},{15,5,1},{15,5,1},{15,5,1},{15,25,5},{44,1,338},{30,9,5},{30,9,5},{26,27,1},{26,9,338},{26,27,1},{45,1,421},{15,5,1},{13,39,8},
+{14,39,4},{45,1,421},{20,1,421},{14,39,4},{0,25,425},{20,1,421},{0,25,425},{47,0,433},{47,0,433},{47,0,433},{47,0,433},{14,7,2},{14,7,2},{14,7,2},{14,13,1},{26,27,2},{26,27,2},{45,1,1202},{31,33,465},{15,37,655},{31,7,461},{47,1,1725},{30,35,446},{46,7,6},{30,25,670},{24,19,1518},{26,9,458},{13,1,469},{29,19,1},{13,7,52},{29,23,85},{15,1,1514},
+{14,35,426},{46,7,5},{24,9,434},{9,11,1514},{24,9,434},{31,1,434},{31,1,434},{31,1,434},{31,39,426},{46,17,339},{46,7,6},{46,7,6},{30,11,48},{10,7,341},{12,41,2},{29,19,1},{29,19,1},{29,19,1},{29,9,0},{31,5,338},{47,23,4},{47,23,4},{12,41,1},{14,9,338},{12,41,1},{43,1,421},{29,19,1},{43,7,0},{30,7,0},{43,1,421},{8,1,421},{30,7,0},
+{0,9,433},{8,1,421},{0,9,433},{31,0,425},{31,0,425},{31,0,425},{31,0,425},{46,7,2},{46,7,2},{46,7,2},{46,27,5},{12,41,1},{12,41,1},{29,1,1346},{45,17,454},{29,21,653},{45,37,459},{45,1,1818},{47,19,446},{47,37,13},{46,39,679},{10,3,1518},{42,23,455},{27,1,526},{13,33,5},{43,21,38},{13,7,93},{27,5,1514},{30,3,425},{31,37,11},{40,23,421},{6,1,1514},
+{40,23,421},{45,1,434},{45,1,434},{45,1,434},{45,7,429},{47,1,340},{47,37,4},{47,37,4},{47,25,50},{42,37,338},{44,25,5},{13,33,4},{13,33,4},{13,33,4},{13,23,5},{17,2,338},{31,37,2},{31,37,2},{44,25,1},{16,1,338},{44,25,1},{11,1,421},{13,33,1},{27,21,5},{30,21,5},{11,1,421},{26,1,421},{30,21,5},{0,23,421},{26,1,421},{0,23,421},{45,0,425},
+{45,0,425},{45,0,425},{45,0,425},{47,5,1},{47,5,1},{47,5,1},{47,11,0},{44,25,4},{44,25,4},{43,1,1502},{13,1,478},{13,35,655},{29,5,461},{29,1,1926},{31,3,446},{15,5,19},{47,7,685},{26,17,1518},{28,7,454},{11,1,569},{27,17,6},{27,5,50},{43,21,97},{17,10,1514},{47,33,425},{15,5,10},{26,7,426},{24,1,1514},{26,7,426},{13,1,477},{13,1,477},{13,1,477},
+{29,37,426},{15,1,355},{15,21,11},{15,21,11},{31,9,41},{12,5,341},{14,39,6},{27,33,1},{27,33,1},{27,33,1},{27,7,2},{29,3,338},{15,21,2},{15,21,2},{14,39,5},{43,9,338},{14,39,5},{25,1,421},{43,1,5},{41,5,0},{31,5,1},{25,1,421},{14,1,421},{31,5,1},{0,7,425},{14,1,421},{0,7,425},{29,0,425},{29,0,425},{29,0,425},{29,0,425},{31,19,9},
+{31,19,9},{31,19,9},{31,25,10},{14,39,2},{14,39,2},{11,1,1634},{43,1,542},{43,19,659},{43,35,459},{43,1,2070},{45,17,446},{45,35,13},{15,37,655},{12,1,1518},{44,21,455},{25,1,646},{11,1,9},{41,19,43},{11,5,93},{25,3,1514},{31,1,422},{29,35,11},{42,21,421},{12,1,1514},{42,21,421},{43,1,506},{43,1,506},{43,1,506},{43,5,429},{29,1,381},{45,35,4},{45,35,4},
+{45,23,50},{44,35,338},{46,23,5},{11,1,5},{11,1,5},{11,1,5},{11,21,5},{39,11,338},{29,35,2},{29,35,2},{46,23,1},{22,1,338},{46,23,1},{39,1,421},{11,1,5},{25,19,10},{31,19,9},{39,1,421},{31,1,421},{31,19,9},{0,21,421},{31,1,421},{0,21,421},{43,0,425},{43,0,425},{43,0,425},{43,0,425},{45,19,0},{45,19,0},{45,19,0},{45,9,0},{46,23,4},
+{46,23,4},{25,1,1874},{11,1,666},{11,33,657},{27,3,451},{11,1,2201},{13,1,454},{13,3,9},{29,5,674},{14,1,1557},{30,5,458},{39,1,722},{9,1,62},{9,33,50},{25,19,85},{9,1,1514},{29,1,446},{13,3,5},{44,5,433},{46,1,1514},{44,5,433},{11,1,545},{11,1,545},{11,1,545},{27,19,429},{43,1,437},{13,3,8},{13,3,8},{29,7,48},{30,19,341},{47,37,6},{25,1,9},
+{25,1,9},{25,1,9},{25,5,0},{25,5,338},{13,3,4},{13,3,4},{47,37,2},{10,1,338},{47,37,2},{37,1,421},{9,1,37},{39,3,2},{29,3,1},{37,1,421},{43,1,421},{29,3,1},{0,5,433},{43,1,421},{0,5,433},{27,0,425},{27,0,425},{27,0,425},{27,0,425},{13,3,4},{13,3,4},{13,3,4},{13,39,5},{46,21,5},{46,21,5},{9,1,2030},{25,1,882},{25,17,653},
+{41,33,453},{9,1,2382},{27,1,546},{43,17,15},{13,35,661},{47,1,1653},{46,19,462},{7,1,837},{39,1,162},{39,17,38},{9,33,89},{19,9,1514},{27,1,521},{43,17,14},{44,19,421},{45,1,1514},{44,19,421},{25,1,626},{25,1,626},{25,1,626},{41,3,422},{11,1,488},{43,17,11},{43,17,11},{43,21,54},{46,33,340},{31,21,9},{39,1,18},{39,1,18},{39,1,18},{9,19,10},{9,3,338},
+{27,33,2},{27,33,2},{15,21,4},{31,3,338},{15,21,4},{5,1,421},{7,1,80},{7,17,8},{13,17,5},{5,1,421},{9,1,421},{13,17,5},{0,19,421},{9,1,421},{0,19,421},{41,0,421},{41,0,421},{41,0,421},{41,0,421},{43,1,1},{43,1,1},{43,1,1},{43,7,1},{31,5,5},{31,5,5},{23,1,2201},{39,1,1083},{9,1,670},{25,1,450},{39,1,2443},{11,1,684},{11,1,8},
+{27,3,634},{29,1,1751},{31,3,429},{21,1,890},{7,1,277},{7,1,52},{23,17,74},{21,17,1459},{25,1,603},{11,1,4},{30,3,401},{17,21,1459},{30,3,401},{9,1,670},{9,1,670},{9,1,670},{25,17,429},{25,1,579},{11,1,8},{11,1,8},{27,5,50},{47,1,340},{15,35,6},{7,1,52},{7,1,52},{7,1,52},{23,3,0},{23,3,338},{11,1,4},{11,1,4},{15,35,2},{43,3,338},
+{15,35,2},{19,1,392},{5,1,149},{37,1,1},{27,1,0},{19,1,392},{37,1,392},{27,1,0},{0,3,400},{37,1,392},{0,3,400},{25,0,425},{25,0,425},{25,0,425},{25,0,425},{11,1,4},{11,1,4},{11,1,4},{11,37,5},{15,35,5},{15,35,5},{7,1,1901},{23,1,1050},{23,1,761},{39,1,426},{7,1,2093},{9,1,551},{25,1,35},{11,33,382},{13,1,1407},{45,33,219},{5,1,638},
+{21,1,233},{21,1,89},{7,1,29},{17,39,1064},{23,1,398},{9,1,10},{31,33,202},{39,17,1064},{31,33,202},{23,1,761},{23,1,761},{23,1,761},{39,1,426},{9,1,638},{25,1,35},{25,1,35},{41,19,51},{45,1,355},{29,19,6},{21,1,89},{21,1,89},{21,1,89},{7,17,5},{3,25,338},{9,1,10},{9,1,10},{13,19,1},{29,1,338},{13,19,1},{3,1,200},{35,1,68},{5,1,1},
+{9,1,1},{3,1,200},{5,1,200},{9,1,1},{0,33,202},{5,1,200},{0,33,202},{39,0,425},{39,0,425},{39,0,425},{39,0,425},{25,1,26},{25,1,26},{25,1,26},{41,5,1},{29,3,5},{29,3,5},{21,1,1606},{37,1,1085},{7,1,886},{7,1,461},{21,1,1749},{23,1,470},{39,1,117},{25,33,186},{11,1,1166},{13,17,66},{19,1,461},{35,1,213},{5,1,125},{21,1,2},{3,3,722},
+{7,1,266},{23,1,37},{29,17,61},{3,3,722},{29,17,61},{7,1,886},{7,1,886},{7,1,886},{7,1,461},{23,1,770},{39,1,117},{39,1,117},{9,3,51},{43,1,426},{43,33,1},{5,1,125},{5,1,125},{5,1,125},{21,1,2},{19,5,338},{23,1,37},{23,1,37},{43,33,0},{37,3,338},{43,33,0},{1,3,61},{33,1,25},{3,1,1},{5,1,1},{1,3,61},{3,1,61},{5,1,1},
+{0,17,61},{3,1,61},{0,17,61},{23,0,433},{23,0,433},{23,0,433},{23,0,433},{9,1,37},{9,1,37},{9,1,37},{9,19,5},{43,33,1},{43,33,1},{5,1,1450},{5,1,1109},{21,1,965},{37,1,542},{5,1,1505},{7,1,478},{7,1,253},{39,17,79},{9,1,1054},{27,1,10},{3,1,318},{19,1,221},{19,1,185},{35,1,29},{33,33,509},{35,1,210},{21,1,97},{27,1,10},{33,33,509},
+{27,1,10},{21,1,965},{21,1,965},{21,1,965},{37,1,542},{21,1,900},{7,1,253},{7,1,253},{39,17,54},{41,1,549},{11,17,9},{19,1,185},{19,1,185},{19,1,185},{35,1,29},{3,3,338},{21,1,97},{21,1,97},{11,17,5},{3,3,338},{11,17,5},{1,17,5},{17,1,1},{17,1,0},{33,1,0},{1,17,5},{17,1,5},{33,1,0},{0,1,9},{17,1,5},{0,1,9},{37,0,421},
+{37,0,421},{37,0,421},{37,0,421},{23,1,65},{23,1,65},{23,1,65},{39,3,2},{27,1,1},{27,1,1},{35,1,1213},{35,1,953},{5,1,886},{5,1,545},{35,1,1186},{21,1,448},{21,1,304},{23,1,32},{23,1,790},{25,1,13},{33,1,198},{3,1,150},{3,1,125},{19,1,36},{33,1,294},{19,1,121},{35,1,73},{9,1,0},{1,33,294},{9,1,0},{5,1,886},{5,1,886},{5,1,886},
+{5,1,545},{5,1,765},{21,1,304},{21,1,304},{23,1,32},{39,1,486},{25,1,13},{3,1,125},{3,1,125},{3,1,125},{19,1,36},{3,1,221},{35,1,73},{35,1,73},{9,1,0},{5,1,221},{9,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{21,0,433},{21,0,433},{21,0,433},{21,0,433},{37,1,113},
+{37,1,113},{37,1,113},{7,17,8},{25,1,13},{25,1,13},{3,1,885},{19,1,737},{19,1,701},{35,1,485},{19,1,834},{5,1,364},{5,1,264},{37,1,2},{7,1,554},{39,1,45},{17,1,82},{33,1,62},{33,1,53},{33,1,13},{1,3,114},{33,1,54},{3,1,34},{21,1,1},{3,1,114},{21,1,1},{19,1,701},{19,1,701},{19,1,701},{35,1,485},{35,1,574},{5,1,264},{5,1,264},
+{37,1,2},{7,1,329},{39,1,45},{33,1,53},{33,1,53},{33,1,53},{33,1,13},{33,1,85},{3,1,34},{3,1,34},{21,1,1},{19,1,85},{21,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{35,0,421},{35,0,421},{35,0,421},{35,0,421},{21,1,160},{21,1,160},{21,1,160},{37,1,2},{39,1,45},
+{39,1,45},{0,30,882},{0,10,100},{0,38,2},{0,6,340},{0,10,1896},{0,22,1189},{0,6,565},{0,4,1421},{0,20,2043},{0,4,1521},{0,30,882},{0,10,100},{0,38,2},{0,6,340},{4,2,1896},{0,22,1189},{0,6,565},{0,4,1421},{10,0,1896},{0,4,1421},{0,22,1},{0,22,1},{0,22,1},{0,34,0},{0,4,164},{0,18,52},{0,18,52},{0,32,98},{0,32,179},{0,32,107},{0,22,1},
+{0,22,1},{0,22,1},{0,34,0},{32,16,162},{0,18,52},{0,18,52},{0,32,98},{16,32,162},{0,32,98},{38,0,882},{0,10,100},{0,38,2},{0,6,340},{38,0,882},{30,0,882},{0,6,340},{0,20,884},{30,0,882},{0,20,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,15,884},{0,12,34},{0,24,13},
+{0,38,250},{0,12,2355},{0,8,1355},{0,22,585},{0,20,1669},{0,36,2567},{0,20,1813},{0,15,884},{0,12,34},{0,24,13},{0,38,250},{0,12,2355},{0,8,1355},{0,22,585},{0,20,1669},{12,0,2355},{0,20,1669},{0,10,0},{0,10,0},{0,10,0},{0,20,1},{0,20,340},{0,4,125},{0,4,125},{0,2,200},{0,18,376},{0,2,225},{0,10,0},{0,10,0},{0,10,0},{0,20,1},{16,4,338},
+{0,4,125},{0,4,125},{0,2,200},{4,16,338},{0,2,200},{24,0,882},{0,12,34},{16,24,4},{0,38,250},{24,0,882},{32,8,882},{0,38,250},{0,6,884},{32,8,882},{0,6,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,27,882},{0,14,9},{0,40,81},{0,8,202},{0,14,2899},{0,24,1539},{0,8,643},
+{0,6,2004},{0,6,3189},{0,36,2207},{0,27,882},{0,14,9},{16,40,61},{0,8,202},{6,2,2899},{0,24,1539},{0,8,643},{0,6,2004},{14,0,2899},{0,6,2004},{0,28,1},{0,28,1},{0,28,1},{0,6,4},{0,22,578},{0,36,221},{0,36,221},{0,18,365},{0,18,632},{0,18,401},{0,28,1},{0,28,1},{0,28,1},{0,6,4},{32,4,578},{0,36,221},{0,36,221},{0,18,365},{22,0,578},
+{0,18,365},{38,6,882},{0,14,9},{2,40,1},{0,8,202},{38,6,882},{27,0,882},{0,8,202},{0,22,884},{27,0,882},{0,22,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{16,25,910},{16,46,31},{16,26,151},{0,40,181},{0,31,3048},{0,26,1416},{0,40,506},{0,22,1944},{0,38,3484},{0,6,2233},{16,25,885},
+{16,46,6},{32,26,78},{16,40,165},{36,6,3048},{0,26,1416},{0,40,506},{0,22,1944},{31,0,3048},{0,22,1944},{16,30,26},{16,30,26},{16,30,26},{16,38,27},{0,24,650},{0,22,157},{0,22,157},{0,4,325},{0,4,766},{0,4,425},{16,30,1},{16,30,1},{16,30,1},{16,38,2},{18,4,648},{0,22,157},{0,22,157},{0,4,325},{36,2,648},{0,4,325},{26,2,882},{0,46,5},{18,26,4},
+{0,40,145},{26,2,882},{38,8,882},{0,40,145},{0,8,890},{38,8,882},{0,8,890},{16,0,26},{16,0,26},{16,0,26},{16,0,26},{0,18,0},{0,18,0},{0,18,0},{0,32,1},{0,16,10},{0,16,10},{16,7,1009},{16,31,134},{32,12,297},{16,26,238},{0,43,3048},{0,28,1224},{0,26,267},{0,8,1764},{0,24,3685},{0,38,2157},{2,9,885},{2,47,5},{18,12,77},{32,26,165},{6,8,3048},
+{0,28,1224},{0,26,267},{0,8,1764},{43,0,3048},{0,8,1764},{16,45,125},{16,45,125},{16,45,125},{16,40,126},{0,28,648},{0,24,80},{0,24,80},{0,36,260},{0,6,875},{0,20,413},{2,46,1},{2,46,1},{2,46,1},{2,24,2},{2,24,648},{0,24,80},{0,24,80},{0,36,260},{28,0,648},{0,36,260},{44,0,882},{2,47,4},{4,42,1},{0,26,98},{44,0,882},{26,8,882},{0,26,98},
+{0,24,890},{26,8,882},{0,24,890},{16,0,125},{16,0,125},{16,0,125},{16,0,125},{0,6,0},{0,6,0},{0,6,0},{0,18,1},{0,18,37},{0,18,37},{32,5,1147},{32,45,282},{2,44,523},{32,12,381},{0,9,3051},{0,14,1110},{0,12,116},{0,24,1658},{0,26,3859},{0,8,2173},{18,23,886},{18,15,6},{34,28,69},{18,42,166},{40,4,3048},{0,14,1110},{0,12,116},{0,24,1658},{22,8,3048},
+{0,24,1658},{32,13,265},{32,13,265},{32,13,265},{32,10,266},{0,46,650},{0,26,26},{0,26,26},{0,22,194},{0,22,987},{0,6,427},{18,15,5},{18,15,5},{18,15,5},{18,40,5},{22,2,648},{0,26,26},{0,26,26},{0,22,194},{42,2,648},{0,22,194},{30,0,882},{18,15,2},{20,28,4},{0,12,52},{30,0,882},{33,0,882},{0,12,52},{0,10,884},{33,0,882},{0,10,884},{32,0,265},
+{32,0,265},{32,0,265},{32,0,265},{0,24,0},{0,24,0},{0,24,0},{0,4,4},{0,34,89},{0,34,89},{2,3,1365},{2,13,510},{18,14,813},{2,28,566},{0,37,3048},{0,46,1013},{0,44,42},{0,10,1509},{0,12,4057},{0,10,2185},{4,7,885},{4,45,10},{20,44,86},{34,28,173},{28,0,3048},{0,46,1013},{0,44,42},{0,10,1509},{37,0,3048},{0,10,1509},{2,11,482},{2,11,482},{2,11,482},
+{2,42,481},{0,29,650},{0,12,4},{0,12,4},{0,38,128},{0,8,1161},{0,22,483},{4,15,2},{4,15,2},{4,15,2},{4,26,2},{8,2,648},{0,12,4},{0,12,4},{0,38,128},{30,2,648},{0,38,128},{47,0,882},{34,45,2},{6,44,1},{0,44,26},{47,0,882},{27,6,882},{0,44,26},{0,26,890},{27,6,882},{0,26,890},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{0,12,0},
+{0,12,0},{0,12,0},{0,6,1},{0,20,180},{0,20,180},{18,17,1647},{18,27,810},{34,46,1178},{2,14,837},{0,19,3048},{0,15,933},{0,14,21},{0,26,1443},{0,28,4329},{0,26,2227},{20,21,885},{20,29,5},{36,30,69},{20,44,182},{42,6,3048},{0,15,933},{0,14,21},{0,26,1443},{19,0,3048},{0,26,1443},{18,25,765},{18,25,765},{18,25,765},{18,28,766},{0,11,648},{0,14,5},{0,14,5},
+{0,24,89},{0,10,1342},{0,8,557},{20,29,1},{20,29,1},{20,29,1},{20,42,2},{24,4,648},{16,44,2},{16,44,2},{0,24,89},{11,0,648},{0,24,89},{34,3,882},{4,13,4},{22,30,4},{0,14,17},{34,3,882},{35,4,882},{0,14,17},{0,12,884},{35,4,882},{0,12,884},{18,0,765},{18,0,765},{18,0,765},{18,0,765},{0,30,0},{0,30,0},{0,30,0},{0,38,0},{0,6,274},
+{0,6,274},{34,1,1782},{34,41,940},{4,31,1356},{34,46,950},{16,1,3052},{16,29,910},{16,46,22},{0,12,1335},{0,46,4231},{0,12,1924},{6,5,882},{6,43,5},{22,47,86},{36,30,174},{32,3,3048},{0,13,900},{32,46,13},{0,12,1299},{39,4,3048},{0,12,1299},{34,23,882},{34,23,882},{34,23,882},{34,14,883},{16,9,651},{16,46,18},{16,46,18},{16,10,74},{0,42,1256},{0,40,434},{6,13,0},
+{6,13,0},{6,13,0},{6,28,1},{38,10,648},{2,30,2},{2,30,2},{0,10,45},{23,0,648},{0,10,45},{4,1,882},{36,27,4},{8,46,4},{0,46,5},{4,1,882},{1,4,882},{0,46,5},{0,28,890},{1,4,882},{0,28,890},{34,0,882},{34,0,882},{34,0,882},{34,0,882},{16,31,1},{16,31,1},{16,31,1},{16,24,1},{0,8,250},{0,8,250},{20,1,1814},{20,25,945},{36,15,1363},
+{4,47,945},{2,1,3052},{32,43,916},{2,47,23},{16,44,1337},{0,31,3975},{0,28,1612},{22,19,886},{22,11,6},{38,31,77},{22,46,185},{2,1,3048},{0,27,883},{2,47,19},{0,44,1188},{1,2,3048},{0,44,1188},{20,7,901},{20,7,901},{20,7,901},{20,30,900},{2,9,654},{2,47,14},{2,47,14},{32,26,70},{0,28,1059},{0,26,236},{22,27,4},{22,27,4},{22,27,4},{22,14,8},{28,2,648},
+{18,46,5},{18,46,5},{0,42,36},{42,8,648},{0,42,36},{27,0,882},{22,11,2},{24,31,4},{0,31,5},{27,0,882},{37,8,882},{0,31,5},{0,14,882},{37,8,882},{0,14,882},{4,0,900},{4,0,900},{4,0,900},{4,0,900},{2,15,5},{2,15,5},{2,15,5},{2,40,4},{0,40,146},{0,40,146},{6,1,1864},{36,39,947},{6,29,1356},{36,31,943},{34,1,3073},{18,27,910},{18,15,21},
+{2,14,1335},{0,45,3751},{0,14,1379},{8,3,885},{8,41,5},{24,15,85},{38,31,182},{29,0,3048},{32,11,884},{34,15,16},{0,30,1146},{37,6,3048},{0,30,1146},{36,21,882},{36,21,882},{36,21,882},{36,47,886},{18,7,649},{18,15,21},{18,15,21},{18,12,74},{0,14,945},{0,12,91},{8,11,2},{8,11,2},{8,11,2},{8,30,2},{16,3,648},{34,31,1},{34,31,1},{0,12,10},{17,0,648},
+{0,12,10},{28,13,882},{38,25,4},{10,15,1},{2,15,1},{28,13,882},{27,12,882},{2,15,1},{0,30,890},{27,12,882},{0,30,890},{36,0,882},{36,0,882},{36,0,882},{36,0,882},{18,29,1},{18,29,1},{18,29,1},{18,26,1},{0,42,68},{0,42,68},{22,1,1944},{22,23,945},{38,13,1363},{6,45,945},{20,1,3115},{34,41,916},{4,45,18},{18,46,1337},{0,13,3580},{0,46,1153},{24,17,886},
+{24,9,6},{40,29,69},{24,15,168},{46,10,3048},{2,25,885},{4,45,14},{0,46,1053},{23,8,3048},{0,46,1053},{22,5,901},{22,5,901},{22,5,901},{6,31,901},{4,7,654},{4,45,9},{4,45,9},{34,28,70},{0,47,825},{0,44,25},{24,25,4},{24,25,4},{24,25,4},{24,46,8},{30,4,648},{20,15,0},{20,15,0},{0,44,0},{15,8,648},{0,44,0},{40,3,882},{24,9,2},{26,29,4},
+{2,29,5},{40,3,882},{16,9,882},{2,29,5},{0,47,890},{16,9,882},{0,47,890},{6,0,900},{6,0,900},{6,0,900},{6,0,900},{4,13,5},{4,13,5},{4,13,5},{4,42,4},{0,28,18},{0,28,18},{8,1,2056},{38,21,956},{8,43,1348},{38,29,949},{6,1,3156},{20,25,910},{20,13,22},{4,47,1318},{0,11,3384},{0,31,1015},{10,1,882},{10,39,5},{26,13,75},{40,29,174},{27,2,3048},
+{34,9,885},{36,13,10},{0,31,990},{39,10,3048},{0,31,990},{38,3,885},{38,3,885},{38,3,885},{38,45,885},{20,5,649},{20,13,21},{20,13,21},{20,14,66},{0,15,729},{0,30,5},{10,9,0},{10,9,0},{10,9,0},{10,31,1},{45,0,648},{6,29,2},{6,29,2},{16,30,4},{27,8,648},{16,30,4},{10,1,882},{40,23,1},{12,13,1},{4,13,1},{10,1,882},{4,9,882},{4,13,1},
+{0,31,890},{4,9,882},{0,31,890},{38,0,884},{38,0,884},{38,0,884},{38,0,884},{20,27,1},{20,27,1},{20,27,1},{20,28,1},{0,30,1},{0,30,1},{40,1,2134},{24,21,943},{40,11,1348},{8,43,952},{38,1,3240},{36,39,914},{6,27,22},{36,15,1330},{0,25,3244},{0,15,951},{42,1,891},{26,7,10},{42,27,77},{26,13,171},{8,1,3048},{4,23,886},{6,27,21},{0,15,950},{1,8,3048},
+{0,15,950},{24,3,890},{24,3,890},{24,3,890},{24,29,890},{6,35,649},{6,43,10},{6,43,10},{36,30,77},{0,13,675},{32,46,6},{26,7,10},{26,7,10},{26,7,10},{26,15,10},{29,2,648},{22,13,2},{22,13,2},{2,46,2},{35,6,648},{2,46,2},{21,0,882},{26,7,1},{28,27,4},{4,27,5},{21,0,882},{18,7,882},{4,27,5},{0,45,884},{18,7,882},{0,45,884},{24,0,890},
+{24,0,890},{24,0,890},{24,0,890},{6,11,1},{6,11,1},{6,11,1},{6,44,2},{16,47,2},{16,47,2},{26,1,2252},{40,35,940},{10,41,1348},{40,27,954},{24,1,3321},{22,23,910},{22,11,22},{6,45,1318},{0,39,3156},{0,29,940},{28,1,920},{12,37,5},{28,41,77},{12,27,180},{23,0,3048},{36,7,884},{38,11,10},{0,29,915},{18,9,3048},{0,29,915},{40,17,882},{40,17,882},{40,17,882},
+{40,43,883},{22,3,649},{38,27,20},{38,27,20},{22,47,86},{0,27,656},{2,31,9},{12,7,0},{12,7,0},{12,7,0},{12,29,1},{43,2,648},{38,27,4},{38,27,4},{34,47,4},{21,8,648},{34,47,4},{14,3,882},{42,21,1},{14,11,1},{6,11,1},{14,3,882},{32,5,882},{6,11,1},{0,29,890},{32,5,882},{0,29,890},{40,0,882},{40,0,882},{40,0,882},{40,0,882},{22,25,1},
+{22,25,1},{22,25,1},{22,30,2},{2,31,0},{2,31,0},{42,1,2404},{26,19,935},{42,9,1348},{10,41,952},{40,1,3409},{38,37,914},{8,41,30},{38,29,1354},{0,37,3087},{2,13,951},{14,1,954},{28,5,6},{44,25,77},{28,11,185},{9,6,3048},{6,21,886},{24,41,21},{0,43,900},{32,7,3048},{0,43,900},{26,1,891},{26,1,891},{26,1,891},{26,27,891},{8,3,654},{8,41,14},{8,41,14},
+{38,31,77},{16,41,651},{34,15,3},{28,5,5},{28,5,5},{28,5,5},{28,13,5},{38,1,648},{24,11,2},{24,11,2},{4,15,2},{43,28,648},{4,15,2},{46,3,882},{28,5,2},{30,25,4},{6,25,5},{46,3,882},{16,3,882},{6,25,5},{0,43,884},{16,3,882},{0,43,884},{26,0,890},{26,0,890},{26,0,890},{26,0,890},{8,9,5},{8,9,5},{8,9,5},{8,46,4},{34,15,2},
+{34,15,2},{28,1,2612},{12,3,951},{28,39,1354},{42,9,952},{26,1,3544},{24,21,910},{40,9,30},{8,43,1348},{0,35,3060},{18,27,935},{30,1,1005},{14,35,3},{30,39,77},{44,25,185},{41,12,3048},{38,35,890},{40,9,14},{0,27,891},{16,5,3048},{0,27,891},{42,1,900},{42,1,900},{42,1,900},{42,41,885},{24,1,654},{40,25,21},{40,25,21},{24,45,77},{2,9,651},{4,29,6},{14,5,2},
+{14,5,2},{14,5,2},{14,27,2},{39,0,648},{10,25,2},{10,25,2},{4,29,5},{9,28,648},{4,29,5},{1,0,882},{44,19,2},{47,9,4},{8,9,5},{1,0,882},{0,1,882},{8,9,5},{0,27,890},{0,1,882},{0,27,890},{42,0,884},{42,0,884},{42,0,884},{42,0,884},{24,7,5},{24,7,5},{24,7,5},{24,31,4},{4,29,2},{4,29,2},{14,1,2774},{28,1,940},{44,7,1318},
+{12,39,966},{12,1,3700},{40,35,916},{10,23,22},{40,11,1348},{16,19,3051},{34,41,940},{47,1,1061},{30,3,9},{46,23,86},{30,9,190},{14,1,3048},{8,19,886},{26,39,20},{16,41,882},{4,5,3048},{16,41,882},{28,1,915},{28,1,915},{28,1,915},{28,25,890},{10,1,657},{10,39,10},{10,39,10},{40,29,77},{18,39,654},{36,13,5},{46,35,4},{46,35,4},{46,35,4},{46,11,4},{23,2,648},
+{42,9,4},{42,9,4},{6,13,0},{20,9,648},{6,13,0},{15,1,882},{30,3,0},{31,23,2},{24,23,1},{15,1,882},{9,11,882},{24,23,1},{0,41,882},{9,11,882},{0,41,882},{28,0,890},{28,0,890},{28,0,890},{28,0,890},{10,7,1},{10,7,1},{10,7,1},{10,15,1},{20,43,1},{20,43,1},{46,1,3014},{14,1,951},{14,37,1330},{44,23,958},{14,1,3865},{26,19,913},{26,7,22},
+{10,41,1348},{32,33,3049},{20,25,943},{15,1,1154},{47,33,6},{31,37,77},{46,23,185},{17,0,3048},{40,3,885},{42,7,10},{2,25,890},{18,3,3048},{2,25,890},{14,1,950},{14,1,950},{14,1,950},{44,39,885},{42,1,672},{26,7,21},{26,7,21},{26,43,77},{34,7,652},{6,27,10},{47,3,2},{47,3,2},{47,3,2},{47,25,2},{37,2,648},{12,23,2},{12,23,2},{6,27,10},{34,7,648},
+{6,27,10},{27,5,882},{46,17,2},{45,7,2},{10,7,1},{27,5,882},{6,1,882},{10,7,1},{0,25,890},{6,1,882},{0,25,890},{44,0,884},{44,0,884},{44,0,884},{44,0,884},{26,5,5},{26,5,5},{26,5,5},{26,29,4},{6,27,1},{6,27,1},{47,1,3214},{30,1,1015},{46,5,1318},{14,37,966},{30,1,4009},{42,33,916},{12,21,22},{42,9,1348},{18,17,3051},{20,39,956},{29,1,1240},
+{31,1,5},{15,21,66},{31,7,185},{27,9,3048},{10,17,886},{12,21,21},{2,39,885},{14,7,3048},{2,39,885},{30,1,990},{30,1,990},{30,1,990},{30,23,890},{28,1,715},{12,37,10},{12,37,10},{12,27,75},{20,37,651},{38,11,5},{31,17,4},{31,17,4},{31,17,4},{31,9,8},{44,1,648},{28,7,2},{28,7,2},{8,11,0},{26,9,648},{8,11,0},{17,10,882},{31,1,1},{29,21,1},
+{26,21,1},{17,10,882},{24,1,882},{26,21,1},{0,39,884},{24,1,882},{0,39,884},{30,0,890},{30,0,890},{30,0,890},{30,0,890},{12,5,1},{12,5,1},{12,5,1},{12,13,1},{22,41,1},{22,41,1},{15,1,3526},{47,1,1153},{47,19,1337},{46,5,958},{47,1,4231},{28,17,910},{44,5,18},{12,39,1363},{20,1,3067},{22,23,945},{43,1,1380},{45,1,25},{29,35,70},{45,21,185},{13,3,3048},
+{12,1,888},{44,5,9},{18,7,901},{44,5,3048},{18,7,901},{47,1,1053},{47,1,1053},{47,1,1053},{46,37,890},{14,1,762},{44,5,14},{44,5,14},{28,41,69},{6,5,650},{8,25,6},{45,1,0},{45,1,0},{45,1,0},{45,23,0},{31,5,648},{14,21,0},{14,21,0},{24,25,4},{14,9,648},{24,25,4},{41,1,882},{29,1,18},{43,5,4},{12,5,5},{41,1,882},{47,3,882},{12,5,5},
+{0,7,900},{47,3,882},{0,7,900},{46,0,890},{46,0,890},{46,0,890},{46,0,890},{28,3,5},{28,3,5},{28,3,5},{28,27,4},{8,25,2},{8,25,2},{29,1,3764},{15,1,1379},{15,3,1335},{47,35,950},{15,1,4477},{14,1,925},{14,19,21},{28,7,1356},{22,1,3145},{38,37,947},{11,1,1485},{13,1,91},{13,19,74},{29,35,178},{43,1,3048},{14,1,925},{14,19,21},{20,37,882},{8,1,3048},
+{20,37,882},{31,1,1146},{31,1,1146},{31,1,1146},{31,21,890},{46,1,841},{14,35,16},{14,35,16},{14,25,85},{38,35,649},{40,9,5},{13,1,10},{13,1,10},{13,1,10},{13,7,9},{17,2,648},{30,35,1},{30,35,1},{10,9,2},{16,1,648},{10,9,2},{9,1,882},{43,1,68},{27,19,1},{28,19,1},{9,1,882},{46,1,882},{28,19,1},{0,37,882},{46,1,882},{0,37,882},{31,0,890},
+{31,0,890},{31,0,890},{31,0,890},{14,3,1},{14,3,1},{14,3,1},{14,11,1},{40,9,4},{40,9,4},{13,1,4076},{29,1,1612},{45,17,1337},{15,3,950},{29,1,4684},{46,1,1035},{46,3,23},{14,37,1363},{24,1,3256},{24,21,945},{41,1,1650},{27,1,236},{27,33,70},{13,19,174},{11,1,3048},{47,1,1013},{46,3,14},{20,5,901},{5,9,3048},{20,5,901},{45,1,1188},{45,1,1188},{45,1,1188},
+{15,35,883},{47,1,910},{46,3,19},{46,3,19},{30,39,77},{8,3,651},{10,23,6},{43,1,36},{43,1,36},{43,1,36},{43,21,1},{29,3,648},{47,19,5},{47,19,5},{26,23,4},{43,9,648},{26,23,4},{19,9,882},{41,1,146},{41,3,4},{14,3,5},{19,9,882},{45,1,882},{14,3,5},{0,5,900},{45,1,882},{0,5,900},{15,0,882},{15,0,882},{15,0,882},{15,0,882},{30,1,5},
+{30,1,5},{30,1,5},{30,25,4},{10,23,2},{10,23,2},{11,1,4374},{13,1,1924},{13,1,1335},{45,33,961},{13,1,4972},{47,1,1225},{47,17,22},{30,5,1356},{26,1,3460},{40,35,940},{9,1,1755},{41,1,434},{11,17,74},{27,3,185},{23,5,3048},{15,1,1146},{47,17,18},{22,35,882},{14,1,3048},{22,35,882},{13,1,1299},{13,1,1299},{13,1,1299},{29,19,890},{15,1,1017},{47,33,13},{47,33,13},
+{46,23,86},{40,33,652},{42,7,5},{11,1,45},{11,1,45},{11,1,45},{27,5,5},{39,11,648},{31,3,2},{31,3,2},{12,7,0},{22,1,648},{12,7,0},{21,17,882},{9,1,250},{25,17,1},{30,17,1},{21,17,882},{17,21,882},{30,17,1},{0,35,882},{17,21,882},{0,35,882},{29,0,890},{29,0,890},{29,0,890},{29,0,890},{47,1,5},{47,1,5},{47,1,5},{47,9,4},{26,37,4},
+{26,37,4},{41,1,4427},{27,1,2227},{27,1,1443},{13,17,925},{11,1,4878},{45,1,1331},{15,1,21},{47,35,1178},{44,1,3438},{26,19,810},{23,1,1746},{9,1,557},{25,1,89},{11,17,142},{23,17,2814},{13,1,1125},{15,1,5},{24,19,765},{45,17,2814},{24,19,765},{27,1,1443},{27,1,1443},{27,1,1443},{13,33,884},{29,1,1132},{15,1,21},{15,1,21},{31,37,69},{10,1,648},{28,21,5},{25,1,89},
+{25,1,89},{25,1,89},{41,19,1},{25,5,648},{45,17,2},{45,17,2},{28,21,1},{10,1,648},{28,21,1},{19,3,761},{7,1,274},{39,1,0},{31,1,0},{19,3,761},{39,1,761},{31,1,0},{0,19,765},{39,1,761},{0,19,765},{13,0,884},{13,0,884},{13,0,884},{13,0,884},{15,1,17},{15,1,17},{15,1,17},{31,23,4},{12,5,4},{12,5,4},{9,1,3933},{11,1,2185},{11,1,1509},
+{27,1,899},{41,1,4346},{13,1,1109},{45,1,42},{15,19,813},{30,1,2958},{12,3,510},{7,1,1386},{23,1,483},{39,1,128},{25,17,59},{3,25,2249},{11,1,870},{13,1,4},{10,3,482},{29,1,2249},{10,3,482},{11,1,1509},{11,1,1509},{11,1,1509},{27,17,890},{43,1,1275},{45,1,42},{45,1,42},{45,21,86},{12,1,675},{44,5,10},{39,1,128},{39,1,128},{39,1,128},{9,3,5},{9,3,648},
+{13,1,4},{13,1,4},{14,5,2},{31,3,648},{14,5,2},{3,3,481},{21,1,180},{7,1,1},{13,1,0},{3,3,481},{7,1,481},{13,1,0},{0,3,481},{7,1,481},{0,3,481},{27,0,890},{27,0,890},{27,0,890},{27,0,890},{45,1,26},{45,1,26},{45,1,26},{45,7,1},{44,35,2},{44,35,2},{39,1,3541},{9,1,2173},{25,1,1658},{11,1,893},{9,1,3801},{27,1,1035},{13,1,116},
+{45,3,523},{47,1,2574},{44,33,282},{21,1,1070},{7,1,427},{23,1,194},{39,1,16},{21,17,1769},{25,1,673},{27,1,26},{12,33,265},{17,21,1769},{12,33,265},{25,1,1658},{25,1,1658},{25,1,1658},{11,1,893},{11,1,1386},{13,1,116},{13,1,116},{29,35,69},{14,1,734},{14,19,6},{23,1,194},{23,1,194},{23,1,194},{39,17,1},{23,3,648},{27,1,26},{27,1,26},{14,19,5},{43,3,648},
+{14,19,5},{33,3,265},{35,1,89},{5,1,4},{25,1,0},{33,3,265},{21,1,265},{25,1,0},{0,33,265},{21,1,265},{0,33,265},{11,0,884},{11,0,884},{11,0,884},{11,0,884},{13,1,52},{13,1,52},{13,1,52},{29,21,4},{14,19,2},{14,19,2},{23,1,3267},{39,1,2157},{9,1,1764},{25,1,954},{39,1,3397},{11,1,950},{27,1,267},{13,33,297},{29,1,2313},{30,17,134},{5,1,838},
+{21,1,413},{37,1,260},{7,1,9},{17,39,1374},{23,1,518},{25,1,80},{44,17,125},{39,17,1374},{44,17,125},{9,1,1764},{9,1,1764},{9,1,1764},{25,1,954},{25,1,1569},{27,1,267},{27,1,267},{13,19,77},{47,1,846},{46,3,5},{37,1,260},{37,1,260},{37,1,260},{7,1,9},{3,25,648},{25,1,80},{25,1,80},{47,3,1},{29,1,648},{47,3,1},{33,1,113},{19,1,37},{19,1,1},
+{7,1,0},{33,1,113},{35,1,113},{7,1,0},{0,17,125},{35,1,113},{0,17,125},{25,0,890},{25,0,890},{25,0,890},{25,0,890},{27,1,98},{27,1,98},{27,1,98},{43,5,1},{46,3,4},{46,3,4},{7,1,3032},{7,1,2233},{23,1,1944},{39,1,1083},{7,1,3096},{9,1,1028},{41,1,506},{27,17,151},{13,1,2068},{47,17,31},{35,1,693},{5,1,425},{5,1,325},{21,1,52},{3,3,1032},
+{7,1,406},{23,1,157},{31,17,26},{3,3,1032},{31,17,26},{23,1,1944},{23,1,1944},{23,1,1944},{39,1,1083},{39,1,1723},{41,1,506},{41,1,506},{27,33,78},{45,1,1034},{47,17,6},{5,1,325},{5,1,325},{5,1,325},{21,1,52},{19,5,648},{23,1,157},{23,1,157},{31,17,1},{37,3,648},{31,17,1},{17,1,18},{17,1,10},{33,1,1},{19,1,0},{17,1,18},{33,1,18},{19,1,0},
+{0,17,26},{33,1,18},{0,17,26},{9,0,890},{9,0,890},{9,0,890},{9,0,890},{41,1,145},{41,1,145},{41,1,145},{27,19,4},{47,1,5},{47,1,5},{21,1,2710},{37,1,2207},{7,1,2004},{23,1,1173},{21,1,2775},{39,1,1036},{9,1,643},{41,1,81},{11,1,1900},{15,1,9},{3,1,524},{19,1,401},{19,1,365},{5,1,104},{33,33,771},{5,1,369},{37,1,221},{29,1,1},{33,33,771},
+{29,1,1},{7,1,2004},{7,1,2004},{7,1,2004},{23,1,1173},{23,1,1784},{9,1,643},{9,1,643},{41,17,61},{13,1,1091},{15,1,9},{19,1,365},{19,1,365},{19,1,365},{5,1,104},{33,5,578},{37,1,221},{37,1,221},{29,1,1},{23,1,578},{29,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{23,0,884},
+{23,0,884},{23,0,884},{23,0,884},{9,1,202},{9,1,202},{9,1,202},{41,3,1},{15,1,9},{15,1,9},{5,1,2214},{21,1,1813},{21,1,1669},{7,1,1109},{21,1,2151},{23,1,874},{23,1,585},{25,1,13},{25,1,1508},{13,1,34},{3,1,300},{3,1,225},{3,1,200},{19,1,61},{33,17,451},{35,1,192},{5,1,125},{11,1,0},{17,33,451},{11,1,0},{21,1,1669},{21,1,1669},{21,1,1669},
+{7,1,1109},{7,1,1460},{23,1,585},{23,1,585},{25,1,13},{11,1,872},{13,1,34},{3,1,200},{3,1,200},{3,1,200},{19,1,61},{17,5,338},{5,1,125},{5,1,125},{11,1,0},{5,17,338},{11,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{7,0,884},{7,0,884},{7,0,884},{7,0,884},{39,1,250},
+{39,1,250},{39,1,250},{25,17,4},{13,1,34},{13,1,34},{35,1,1818},{5,1,1521},{5,1,1421},{21,1,1028},{5,1,1675},{7,1,790},{7,1,565},{39,1,2},{23,1,1155},{11,1,100},{33,1,147},{33,1,107},{33,1,98},{3,1,29},{1,19,216},{19,1,88},{19,1,52},{23,1,1},{19,1,216},{23,1,1},{5,1,1421},{5,1,1421},{5,1,1421},{21,1,1028},{21,1,1158},{7,1,565},{7,1,565},
+{39,1,2},{25,1,723},{11,1,100},{33,1,98},{33,1,98},{33,1,98},{3,1,29},{33,17,162},{19,1,52},{19,1,52},{23,1,1},{17,33,162},{23,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{21,0,884},{21,0,884},{21,0,884},{21,0,884},{7,1,340},{7,1,340},{7,1,340},{39,1,2},{11,1,100},
+{11,1,100},{0,13,1568},{0,14,185},{0,10,5},{0,8,586},{0,44,3371},{0,24,2147},{0,8,1027},{0,36,2571},{0,6,3617},{0,20,2729},{0,13,1568},{0,14,185},{0,10,5},{0,8,586},{18,8,3371},{0,24,2147},{0,8,1027},{0,36,2571},{44,0,3371},{0,36,2571},{0,24,1},{0,24,1},{0,24,1},{0,20,1},{0,20,288},{0,34,100},{0,34,100},{0,2,164},{0,2,321},{0,2,189},{0,24,1},
+{0,24,1},{0,24,1},{0,20,1},{32,2,288},{0,34,100},{0,34,100},{0,2,164},{20,0,288},{0,2,164},{24,2,1568},{0,14,185},{0,10,5},{0,8,586},{24,2,1568},{13,0,1568},{0,8,586},{0,22,1576},{13,0,1568},{0,22,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,1568},{0,46,89},{0,26,20},
+{0,40,505},{0,46,3968},{0,10,2316},{0,24,1078},{0,6,2880},{0,22,4305},{0,6,3105},{0,25,1568},{0,46,89},{0,26,20},{0,40,505},{18,10,3968},{0,10,2316},{0,24,1078},{0,6,2880},{46,0,3968},{0,6,2880},{0,12,1},{0,12,1},{0,12,1},{0,6,0},{0,6,514},{0,20,193},{0,20,193},{0,18,317},{0,18,556},{0,18,353},{0,12,1},{0,12,1},{0,12,1},{0,6,0},{2,2,512},
+{0,20,193},{0,20,193},{0,18,317},{2,2,512},{0,18,317},{16,11,1568},{0,46,89},{16,26,5},{0,40,505},{16,11,1568},{25,0,1568},{0,40,505},{0,38,1570},{25,0,1568},{0,38,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,7,1568},{0,15,37},{16,12,76},{0,10,421},{0,15,4652},{0,42,2540},{0,10,1097},
+{0,38,3251},{0,8,5108},{0,22,3545},{0,7,1568},{0,15,37},{16,12,51},{0,10,421},{38,2,4651},{0,42,2540},{0,10,1097},{0,38,3251},{16,8,4651},{0,38,3251},{0,46,0},{0,46,0},{0,46,0},{0,38,1},{0,8,802},{0,6,289},{0,6,289},{0,34,493},{0,34,872},{0,34,557},{0,46,0},{0,46,0},{0,46,0},{0,38,1},{4,0,802},{0,6,289},{0,6,289},{0,34,493},{8,0,802},
+{0,34,493},{26,4,1568},{0,15,37},{32,12,2},{0,10,421},{26,4,1568},{7,0,1568},{0,10,421},{0,24,1576},{7,0,1568},{0,24,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,19,1570},{0,29,8},{16,44,166},{0,12,338},{0,29,5420},{0,28,2755},{0,26,1208},{0,8,3659},{0,24,5988},{0,38,4028},{0,19,1570},
+{0,29,8},{16,44,141},{0,12,338},{40,0,5419},{0,28,2755},{0,26,1208},{0,8,3659},{46,2,5419},{0,8,3659},{0,45,0},{0,45,0},{0,45,0},{0,24,1},{0,24,1154},{0,22,433},{0,22,433},{0,4,697},{0,4,1270},{0,4,797},{0,45,0},{0,45,0},{0,45,0},{0,24,1},{18,4,1152},{0,22,433},{0,22,433},{0,4,697},{36,2,1152},{0,4,697},{14,0,1568},{0,29,8},{18,28,1},
+{0,12,338},{14,0,1568},{8,10,1568},{0,12,338},{0,40,1568},{8,10,1568},{0,40,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{16,17,1609},{16,43,45},{32,30,282},{0,28,325},{0,25,5419},{0,14,2514},{0,12,804},{0,24,3462},{0,10,6191},{0,8,3965},{32,3,1574},{32,13,17},{2,14,130},{16,28,312},{16,11,5419},
+{0,14,2514},{0,12,804},{0,24,3462},{25,0,5419},{0,24,3462},{16,43,41},{16,43,41},{16,43,41},{16,10,42},{0,28,1152},{0,40,292},{0,40,292},{0,36,596},{0,6,1379},{0,20,761},{32,29,4},{32,29,4},{32,29,4},{32,10,5},{2,24,1152},{0,40,292},{0,40,292},{0,36,596},{28,0,1152},{0,36,596},{30,2,1568},{0,27,4},{4,14,1},{0,28,244},{30,2,1568},{35,2,1568},{0,28,244},
+{0,26,1570},{35,2,1568},{0,26,1570},{16,0,41},{16,0,41},{16,0,41},{16,0,41},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,32,13},{0,32,13},{32,1,1733},{32,11,159},{32,46,455},{16,14,377},{0,7,5419},{0,47,2294},{0,44,542},{0,10,3225},{0,12,6401},{0,10,3901},{2,17,1569},{2,27,6},{18,46,125},{32,14,296},{26,4,5419},{0,47,2294},{0,44,542},{0,10,3225},{7,0,5419},
+{0,10,3225},{32,11,158},{32,11,158},{32,11,158},{32,42,157},{0,46,1154},{0,26,170},{0,26,170},{0,22,482},{0,22,1491},{0,6,739},{2,27,2},{2,27,2},{2,27,2},{2,26,5},{22,2,1152},{0,26,170},{0,26,170},{0,22,482},{42,2,1152},{0,22,482},{47,2,1568},{32,11,2},{20,30,5},{0,14,185},{47,2,1568},{17,2,1568},{0,14,185},{0,42,1570},{17,2,1568},{0,42,1570},{32,0,157},
+{32,0,157},{32,0,157},{32,0,157},{0,22,0},{0,22,0},{0,22,0},{0,34,1},{0,18,45},{0,18,45},{2,1,2003},{32,9,330},{2,31,710},{32,30,517},{0,35,5420},{0,15,2081},{0,30,345},{0,42,3099},{0,28,6641},{0,10,3885},{34,1,1574},{34,11,17},{4,47,134},{18,30,312},{14,0,5419},{0,15,2081},{0,30,345},{0,42,3099},{8,10,5419},{0,42,3099},{32,23,317},{32,23,317},{32,23,317},
+{32,28,317},{0,29,1154},{0,28,80},{0,28,80},{0,8,388},{0,8,1665},{0,38,753},{34,27,4},{34,27,4},{34,27,4},{34,12,5},{8,2,1152},{0,28,80},{0,28,80},{0,8,388},{30,2,1152},{0,8,388},{15,2,1568},{18,41,4},{36,47,5},{0,46,125},{15,2,1568},{33,4,1568},{0,46,125},{0,28,1576},{33,4,1568},{0,28,1576},{32,0,317},{32,0,317},{32,0,317},{32,0,317},{0,40,0},
+{0,40,0},{0,40,0},{0,20,0},{0,34,113},{0,34,113},{18,1,2395},{2,23,570},{18,45,1046},{2,47,725},{0,1,5419},{0,13,1947},{0,47,185},{0,12,2880},{0,14,6964},{0,12,3841},{20,1,1593},{4,25,6},{20,15,131},{34,46,326},{0,1,5419},{0,13,1947},{0,47,185},{0,12,2880},{1,0,5419},{0,12,2880},{2,21,546},{2,21,546},{2,21,546},{2,14,545},{0,11,1152},{0,30,37},{0,30,37},
+{0,24,317},{0,10,1846},{0,8,797},{4,25,2},{4,25,2},{4,25,2},{4,28,2},{24,4,1152},{0,30,37},{0,30,37},{0,24,317},{11,0,1152},{0,24,317},{43,0,1568},{34,9,1},{22,31,1},{0,47,85},{43,0,1568},{19,6,1568},{0,47,85},{0,44,1570},{19,6,1568},{0,44,1570},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,28,0},{0,28,0},{0,28,0},{0,6,1},{0,20,208},
+{0,20,208},{4,1,3030},{18,37,927},{34,29,1474},{18,15,1042},{16,1,5540},{0,27,1787},{0,15,57},{0,44,2668},{0,46,7299},{0,28,3836},{6,1,1612},{36,39,10},{6,29,136},{20,31,312},{47,2,5419},{0,27,1787},{0,15,57},{0,44,2668},{17,2,5419},{0,44,2668},{18,19,883},{18,19,883},{18,19,883},{18,46,882},{0,23,1152},{0,31,5},{0,31,5},{0,10,225},{0,26,2064},{0,10,901},{36,9,2},
+{36,9,2},{36,9,2},{36,14,1},{38,10,1152},{0,31,5},{0,31,5},{0,10,225},{23,0,1152},{0,10,225},{38,3,1568},{20,39,4},{8,45,5},{0,15,41},{38,3,1568},{35,8,1568},{0,15,41},{0,30,1570},{35,8,1568},{0,30,1570},{18,0,882},{18,0,882},{18,0,882},{18,0,882},{0,47,1},{0,47,1},{0,47,1},{0,8,1},{0,6,325},{0,6,325},{20,1,3734},{34,5,1332},{4,43,1958},
+{18,45,1395},{2,1,5808},{0,25,1676},{0,29,20},{0,30,2566},{0,15,7631},{0,44,3925},{22,1,1656},{6,7,9},{22,13,132},{6,45,309},{15,2,5419},{0,25,1676},{0,29,20},{0,30,2566},{33,4,5419},{0,30,2566},{34,33,1258},{34,33,1258},{34,33,1258},{34,47,1259},{0,5,1154},{0,45,5},{0,45,5},{0,42,180},{0,12,2275},{0,10,981},{6,23,4},{6,23,4},{6,23,4},{6,46,5},{28,2,1152},
+{16,15,1},{16,15,1},{0,42,180},{42,8,1152},{0,42,180},{41,2,1568},{36,7,2},{24,29,5},{0,29,20},{41,2,1568},{17,8,1568},{0,29,20},{0,46,1576},{17,8,1568},{0,46,1576},{34,0,1258},{34,0,1258},{34,0,1258},{34,0,1258},{0,29,0},{0,29,0},{0,29,0},{0,40,1},{0,38,482},{0,38,482},{36,1,4356},{4,19,1676},{20,27,2370},{34,13,1683},{18,1,6121},{0,39,1616},{16,43,36},
+{0,46,2397},{0,45,7815},{0,46,3837},{8,1,1715},{38,37,10},{8,43,131},{22,29,312},{43,0,5419},{0,39,1612},{16,43,27},{0,46,2393},{19,6,5419},{0,46,2393},{4,1,1577},{4,1,1577},{4,1,1577},{4,15,1576},{0,17,1156},{16,13,22},{16,13,22},{0,12,134},{0,44,2441},{0,12,971},{38,23,1},{38,23,1},{38,23,1},{38,47,2},{16,3,1152},{32,29,1},{32,29,1},{0,12,130},{17,0,1152},
+{0,12,130},{29,12,1568},{22,37,4},{10,43,5},{0,43,10},{29,12,1568},{26,13,1568},{0,43,10},{0,31,1576},{26,13,1568},{0,31,1576},{4,0,1576},{4,0,1576},{4,0,1576},{4,0,1576},{0,41,4},{0,41,4},{0,41,4},{0,26,4},{0,24,562},{0,24,562},{22,1,4616},{20,3,1677},{6,41,2378},{20,43,1681},{4,1,6311},{16,7,1620},{32,27,20},{0,31,2365},{0,43,7444},{0,47,3383},{40,1,1766},
+{8,5,11},{24,11,132},{8,13,314},{11,0,5419},{0,37,1577},{32,27,19},{0,31,2265},{5,8,5419},{0,31,2265},{20,1,1593},{20,1,1593},{20,1,1593},{20,29,1569},{32,1,1155},{32,27,19},{32,27,19},{16,44,125},{0,46,2150},{0,28,659},{8,21,2},{8,21,2},{8,21,2},{8,31,2},{30,4,1152},{18,13,1},{18,13,1},{0,44,72},{15,8,1152},{0,44,72},{37,0,1568},{38,5,2},{26,27,2},
+{0,27,2},{37,0,1568},{36,9,1568},{0,27,2},{0,15,1568},{36,9,1568},{0,15,1568},{20,0,1568},{20,0,1568},{20,0,1568},{20,0,1568},{32,41,1},{32,41,1},{32,41,1},{32,42,2},{0,26,388},{0,26,388},{8,1,4936},{6,17,1676},{22,9,2363},{36,11,1689},{36,1,6476},{2,37,1620},{18,41,24},{32,15,2370},{0,41,7036},{0,15,2859},{26,1,1851},{40,35,11},{10,25,136},{24,27,321},{41,2,5419},
+{16,5,1571},{18,41,20},{0,15,2130},{17,8,5419},{0,15,2130},{6,1,1619},{6,1,1619},{6,1,1619},{6,13,1571},{18,1,1158},{18,11,21},{18,11,21},{2,30,125},{0,31,1905},{0,14,425},{40,5,2},{40,5,2},{40,5,2},{40,45,2},{45,0,1152},{4,27,5},{4,27,5},{0,30,41},{27,8,1152},{0,30,41},{21,2,1568},{24,19,2},{12,41,1},{16,41,1},{21,2,1568},{24,9,1568},{16,41,1},
+{0,29,1570},{24,9,1568},{0,29,1570},{6,0,1570},{6,0,1570},{6,0,1570},{6,0,1570},{18,25,4},{18,25,4},{18,25,4},{18,28,5},{0,28,232},{0,28,232},{24,1,5154},{38,1,1680},{8,39,2378},{22,41,1683},{22,1,6708},{18,5,1628},{34,25,24},{2,29,2363},{0,9,6740},{0,45,2553},{12,1,1964},{10,3,8},{26,9,139},{40,41,309},{29,12,5419},{2,35,1572},{4,25,21},{0,29,2027},{26,13,5419},
+{0,29,2027},{38,1,1664},{38,1,1664},{38,1,1664},{22,27,1570},{4,1,1185},{34,25,20},{34,25,20},{34,46,130},{0,45,1721},{0,46,218},{10,19,4},{10,19,4},{10,19,4},{10,13,8},{29,2,1152},{20,11,5},{20,11,5},{0,47,25},{35,6,1152},{0,47,25},{35,2,1568},{10,3,4},{28,25,5},{18,25,4},{35,2,1568},{34,5,1568},{18,25,4},{0,13,1570},{34,5,1568},{0,13,1570},{22,0,1570},
+{22,0,1570},{22,0,1570},{22,0,1570},{34,23,1},{34,23,1},{34,23,1},{34,14,4},{0,14,149},{0,14,149},{26,1,5444},{8,1,1724},{24,23,2378},{38,9,1689},{8,1,6964},{4,35,1620},{20,39,36},{34,13,2370},{0,23,6513},{0,13,2244},{44,1,2099},{42,33,11},{12,23,136},{26,25,321},{37,0,5419},{18,3,1571},{20,39,27},{0,43,1924},{36,9,5419},{0,43,1924},{8,1,1720},{8,1,1720},{8,1,1720},
+{8,11,1577},{36,1,1224},{20,9,19},{20,9,19},{4,47,122},{0,43,1548},{0,31,90},{42,19,1},{42,19,1},{42,19,1},{42,43,2},{43,2,1152},{6,25,5},{6,25,5},{0,31,9},{21,8,1152},{0,31,9},{46,1,1568},{26,17,2},{14,39,2},{18,39,1},{46,1,1568},{26,7,1568},{18,39,1},{0,27,1576},{26,7,1568},{0,27,1576},{8,0,1576},{8,0,1576},{8,0,1576},{8,0,1576},{20,23,9},
+{20,23,9},{20,23,9},{4,30,10},{0,47,73},{0,47,73},{42,1,5700},{40,1,1798},{40,37,2375},{24,39,1683},{40,1,7153},{20,3,1626},{36,23,24},{4,27,2386},{0,21,6243},{0,27,1980},{30,1,2210},{12,1,8},{28,7,132},{42,39,323},{5,0,5419},{4,33,1572},{6,23,21},{0,27,1836},{0,5,5419},{0,27,1836},{40,1,1762},{40,1,1762},{40,1,1762},{24,25,1570},{6,1,1275},{36,23,20},{36,23,20},
+{36,15,125},{0,41,1395},{0,45,25},{12,17,4},{12,17,4},{12,17,4},{12,11,8},{38,1,1152},{22,9,4},{22,9,4},{0,45,0},{43,28,1152},{0,45,0},{31,1,1568},{42,1,2},{30,23,5},{4,23,5},{31,1,1568},{32,1,1568},{4,23,5},{0,11,1570},{32,1,1568},{0,11,1570},{24,0,1570},{24,0,1570},{24,0,1570},{24,0,1570},{36,21,1},{36,21,1},{36,21,1},{36,46,4},{0,15,25},
+{0,15,25},{28,1,6116},{26,1,1980},{26,5,2386},{40,7,1689},{26,1,7408},{6,17,1620},{22,37,24},{36,41,2375},{0,35,6044},{0,41,1798},{47,1,2385},{44,1,25},{14,37,125},{28,23,315},{35,2,5419},{20,1,1569},{22,37,20},{0,41,1762},{34,5,5419},{0,41,1762},{26,1,1836},{26,1,1836},{26,1,1836},{10,9,1574},{38,1,1363},{22,7,21},{22,7,21},{6,29,132},{0,9,1284},{0,13,8},{44,1,0},
+{44,1,0},{44,1,0},{44,41,0},{39,0,1152},{8,23,4},{8,23,4},{16,13,4},{9,28,1152},{16,13,4},{17,6,1568},{14,1,25},{47,37,4},{20,37,1},{17,6,1568},{20,1,1568},{20,37,1},{0,25,1570},{20,1,1568},{0,25,1570},{10,0,1570},{10,0,1570},{10,0,1570},{10,0,1570},{22,5,5},{22,5,5},{22,5,5},{22,31,5},{0,43,2},{0,43,2},{14,1,6434},{12,1,2244},{12,35,2370},
+{26,21,1685},{12,1,7724},{38,1,1620},{38,21,36},{22,25,2378},{0,3,5839},{0,9,1724},{31,1,2546},{30,1,90},{46,5,122},{14,7,322},{46,1,5419},{22,1,1602},{8,21,19},{0,9,1720},{26,7,5419},{0,9,1720},{42,1,1924},{42,1,1924},{42,1,1924},{26,23,1577},{24,1,1414},{38,21,27},{38,21,27},{22,13,136},{0,7,1218},{32,43,11},{30,1,9},{30,1,9},{30,1,9},{14,9,10},{23,2,1152},
+{24,7,5},{24,7,5},{18,43,1},{20,9,1152},{18,43,1},{27,3,1568},{46,1,73},{31,5,10},{36,5,9},{27,3,1568},{39,9,1568},{36,5,9},{0,9,1576},{39,9,1568},{0,9,1576},{26,0,1576},{26,0,1576},{26,0,1576},{26,0,1576},{38,19,1},{38,19,1},{38,19,1},{38,15,2},{16,27,2},{16,27,2},{30,1,6786},{44,1,2553},{28,3,2363},{42,5,1689},{28,1,8052},{24,1,1671},{24,35,24},
+{38,9,2378},{0,1,5715},{0,39,1680},{45,1,2675},{47,1,218},{47,35,130},{30,21,315},{31,1,5419},{24,1,1667},{24,35,20},{0,39,1664},{32,1,5419},{0,39,1664},{28,1,2027},{28,1,2027},{28,1,2027},{12,7,1571},{10,1,1521},{24,5,21},{24,5,21},{8,27,139},{0,21,1169},{2,11,8},{46,1,25},{46,1,25},{46,1,25},{46,39,1},{37,2,1152},{10,21,5},{10,21,5},{18,11,4},{34,7,1152},
+{18,11,4},{39,7,1568},{15,1,149},{15,35,4},{22,35,1},{39,7,1568},{26,1,1568},{22,35,1},{0,23,1570},{26,1,1568},{0,23,1570},{12,0,1570},{12,0,1570},{12,0,1570},{12,0,1570},{24,19,4},{24,19,4},{24,19,4},{24,29,5},{2,11,4},{2,11,4},{47,1,7186},{14,1,2859},{14,33,2370},{28,35,1683},{30,1,8313},{40,1,1819},{40,19,24},{8,23,2363},{16,1,5820},{16,7,1676},{13,1,2892},
+{15,1,425},{31,3,125},{47,35,321},{45,1,5419},{26,1,1796},{10,19,21},{0,7,1619},{27,9,5419},{0,7,1619},{14,1,2130},{14,1,2130},{14,1,2130},{28,21,1570},{42,1,1608},{40,19,20},{40,19,20},{24,11,136},{0,19,1155},{34,41,11},{31,1,41},{31,1,41},{31,1,41},{47,7,5},{44,1,1152},{26,5,5},{26,5,5},{4,41,2},{26,9,1152},{4,41,2},{25,1,1568},{29,1,232},{29,19,5},
+{24,19,4},{25,1,1568},{33,9,1568},{24,19,4},{0,7,1570},{33,9,1568},{0,7,1570},{28,0,1570},{28,0,1570},{28,0,1570},{28,0,1570},{40,17,1},{40,17,1},{40,17,1},{40,13,1},{18,25,2},{18,25,2},{15,1,7706},{46,1,3383},{30,1,2365},{14,3,1685},{47,1,8695},{42,1,2092},{26,33,20},{40,7,2378},{4,1,6099},{2,21,1677},{27,1,3152},{29,1,659},{45,17,125},{31,19,315},{27,3,5419},
+{44,1,1993},{26,33,19},{0,21,1593},{39,9,5419},{0,21,1593},{30,1,2265},{30,1,2265},{30,1,2265},{14,5,1572},{28,1,1764},{26,33,19},{26,33,19},{10,25,132},{32,3,1155},{4,9,11},{45,1,72},{45,1,72},{45,1,72},{15,37,1},{31,5,1152},{12,19,1},{12,19,1},{20,9,2},{14,9,1152},{20,9,2},{23,17,1568},{27,1,388},{43,33,2},{40,33,1},{23,17,1568},{45,17,1568},{40,33,1},
+{0,21,1568},{45,17,1568},{0,21,1568},{14,0,1568},{14,0,1568},{14,0,1568},{14,0,1568},{26,1,2},{26,1,2},{26,1,2},{26,27,2},{4,39,2},{4,39,2},{45,1,8016},{47,1,3837},{47,1,2397},{30,17,1685},{31,1,9093},{28,1,2484},{42,17,36},{26,21,2370},{36,1,6379},{18,5,1676},{11,1,3345},{13,1,971},{13,1,134},{15,33,326},{39,7,5419},{30,1,2185},{12,17,22},{0,5,1577},{26,1,5419},
+{0,5,1577},{47,1,2393},{47,1,2393},{47,1,2393},{30,19,1576},{14,1,1890},{42,17,27},{42,17,27},{42,9,131},{2,17,1152},{36,39,10},{13,1,130},{13,1,130},{13,1,130},{45,5,5},{17,2,1152},{28,33,1},{28,33,1},{22,39,1},{16,1,1152},{22,39,1},{21,3,1568},{25,1,562},{27,1,4},{40,1,4},{21,3,1568},{43,1,1568},{40,1,4},{0,5,1576},{43,1,1568},{0,5,1576},{30,0,1576},
+{30,0,1576},{30,0,1576},{30,0,1576},{42,1,10},{42,1,10},{42,1,10},{42,11,5},{36,23,4},{36,23,4},{13,1,7700},{45,1,3925},{31,1,2566},{47,17,1637},{45,1,8460},{14,1,2285},{28,1,20},{42,5,1958},{38,1,5932},{4,35,1332},{9,1,2987},{11,1,981},{43,1,180},{29,17,219},{9,3,4803},{47,1,1925},{44,1,5},{32,35,1258},{31,3,4803},{32,35,1258},{31,1,2566},{31,1,2566},{31,1,2566},
+{47,3,1577},{30,1,2054},{28,1,20},{28,1,20},{12,23,132},{34,1,1155},{6,7,9},{43,1,180},{43,1,180},{43,1,180},{13,35,1},{29,3,1152},{14,17,1},{14,17,1},{22,7,4},{43,9,1152},{22,7,4},{21,1,1250},{39,1,482},{41,1,1},{28,1,0},{21,1,1250},{41,1,1250},{28,1,0},{0,35,1258},{41,1,1250},{0,35,1258},{47,0,1576},{47,0,1576},{47,0,1576},{47,0,1576},{28,1,20},
+{28,1,20},{28,1,20},{28,25,5},{6,37,2},{6,37,2},{43,1,7164},{29,1,3836},{45,1,2668},{31,1,1579},{13,1,7780},{30,1,2041},{14,1,57},{28,35,1474},{24,1,5308},{36,19,927},{9,1,2475},{11,1,901},{11,1,225},{43,17,110},{37,7,4056},{15,1,1590},{30,1,5},{18,19,883},{30,1,4056},{18,19,883},{45,1,2668},{45,1,2668},{45,1,2668},{31,17,1570},{47,1,2214},{14,1,57},{14,1,57},
+{28,7,136},{36,1,1186},{38,37,10},{11,1,225},{11,1,225},{11,1,225},{43,3,5},{39,11,1152},{30,1,5},{30,1,5},{8,37,2},{22,1,1152},{8,37,2},{5,1,882},{7,1,325},{9,1,1},{46,1,1},{5,1,882},{9,1,882},{46,1,1},{0,19,882},{9,1,882},{0,19,882},{31,0,1570},{31,0,1570},{31,0,1570},{31,0,1570},{14,1,41},{14,1,41},{14,1,41},{44,9,5},{38,21,4},
+{38,21,4},{11,1,6493},{13,1,3841},{13,1,2880},{45,1,1574},{43,1,7071},{47,1,1822},{46,1,185},{44,19,1046},{26,1,4761},{22,3,570},{23,1,2034},{9,1,797},{25,1,317},{11,17,34},{23,17,3318},{13,1,1221},{31,1,37},{20,3,546},{45,17,3318},{20,3,546},{13,1,2880},{13,1,2880},{13,1,2880},{45,1,1574},{45,1,2443},{46,1,185},{46,1,185},{14,21,131},{38,1,1275},{24,5,6},{25,1,317},
+{25,1,317},{25,1,317},{11,33,1},{25,5,1152},{31,1,37},{31,1,37},{24,5,2},{10,1,1152},{24,5,2},{3,3,545},{21,1,208},{7,1,1},{29,1,0},{3,3,545},{23,1,545},{29,1,0},{0,3,545},{23,1,545},{0,3,545},{45,0,1570},{45,0,1570},{45,0,1570},{45,0,1570},{46,1,85},{46,1,85},{46,1,85},{30,23,1},{8,35,1},{8,35,1},{41,1,6095},{11,1,3885},{43,1,3099},
+{13,1,1636},{11,1,6422},{45,1,1767},{31,1,345},{30,3,710},{44,1,4358},{8,33,330},{7,1,1698},{39,1,753},{9,1,388},{41,1,9},{3,25,2753},{27,1,1018},{29,1,80},{22,33,317},{29,1,2753},{22,33,317},{43,1,3099},{43,1,3099},{43,1,3099},{13,1,1636},{29,1,2628},{31,1,345},{31,1,345},{46,5,134},{40,1,1395},{10,35,17},{9,1,388},{9,1,388},{9,1,388},{41,1,9},{9,3,1152},
+{29,1,80},{29,1,80},{26,35,4},{31,3,1152},{26,35,4},{33,3,313},{35,1,113},{21,1,0},{41,1,0},{33,3,313},{21,1,313},{41,1,0},{0,33,317},{21,1,313},{0,33,317},{29,0,1576},{29,0,1576},{29,0,1576},{29,0,1576},{47,1,125},{47,1,125},{47,1,125},{46,37,5},{40,19,4},{40,19,4},{9,1,5661},{11,1,3901},{11,1,3225},{43,1,1739},{41,1,5978},{29,1,1685},{45,1,542},
+{47,33,455},{14,1,3994},{10,33,159},{21,1,1418},{7,1,739},{23,1,482},{9,1,16},{21,17,2273},{11,1,878},{27,1,170},{10,33,158},{17,21,2273},{10,33,158},{11,1,3225},{11,1,3225},{11,1,3225},{43,1,1739},{43,1,2875},{45,1,542},{45,1,542},{47,19,125},{42,1,1584},{26,3,6},{23,1,482},{23,1,482},{23,1,482},{9,1,16},{23,3,1152},{27,1,170},{27,1,170},{26,3,2},{43,3,1152},
+{26,3,2},{17,3,145},{19,1,45},{35,1,1},{23,1,0},{17,3,145},{35,1,145},{23,1,0},{0,33,157},{35,1,145},{0,33,157},{43,0,1570},{43,0,1570},{43,0,1570},{43,0,1570},{15,1,185},{15,1,185},{15,1,185},{31,21,5},{10,33,2},{10,33,2},{39,1,5341},{9,1,3965},{25,1,3462},{11,1,1889},{9,1,5505},{13,1,1765},{13,1,804},{31,33,282},{47,1,3750},{42,17,45},{5,1,1210},
+{21,1,761},{37,1,596},{23,1,73},{17,39,1878},{9,1,781},{41,1,292},{42,17,41},{39,17,1878},{42,17,41},{25,1,3462},{25,1,3462},{25,1,3462},{11,1,1889},{11,1,3058},{13,1,804},{13,1,804},{15,3,130},{44,1,1798},{12,33,17},{37,1,596},{37,1,596},{37,1,596},{23,1,73},{3,25,1152},{41,1,292},{41,1,292},{28,33,4},{29,1,1152},{28,33,4},{1,3,41},{33,1,13},{3,1,1},
+{5,1,1},{1,3,41},{3,1,41},{5,1,1},{0,17,41},{3,1,41},{0,17,41},{27,0,1570},{27,0,1570},{27,0,1570},{27,0,1570},{29,1,244},{29,1,244},{29,1,244},{15,5,1},{26,1,4},{26,1,4},{23,1,5128},{39,1,4028},{9,1,3659},{25,1,2169},{39,1,5148},{11,1,1917},{27,1,1208},{45,17,166},{29,1,3628},{28,1,8},{35,1,1089},{5,1,797},{5,1,697},{37,1,221},{3,3,1536},
+{7,1,706},{23,1,433},{44,1,0},{3,3,1536},{44,1,0},{9,1,3659},{9,1,3659},{9,1,3659},{25,1,2169},{25,1,3366},{27,1,1208},{27,1,1208},{45,17,141},{47,1,2105},{28,1,8},{5,1,697},{5,1,697},{5,1,697},{37,1,221},{19,5,1152},{23,1,433},{23,1,433},{44,1,0},{37,3,1152},{44,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},
+{0,1,0},{1,1,0},{0,1,0},{41,0,1568},{41,0,1568},{41,0,1568},{41,0,1568},{13,1,338},{13,1,338},{13,1,338},{29,19,1},{28,1,8},{28,1,8},{7,1,4416},{23,1,3545},{39,1,3251},{9,1,2027},{23,1,4372},{41,1,1771},{11,1,1097},{13,17,76},{29,1,2956},{14,1,37},{19,1,753},{35,1,557},{35,1,493},{21,1,148},{17,5,1067},{21,1,513},{7,1,289},{47,1,0},{5,17,1067},
+{47,1,0},{39,1,3251},{39,1,3251},{39,1,3251},{9,1,2027},{9,1,2819},{11,1,1097},{11,1,1097},{13,17,51},{47,1,1769},{14,1,37},{35,1,493},{35,1,493},{35,1,493},{21,1,148},{5,1,802},{7,1,289},{7,1,289},{47,1,0},{9,1,802},{47,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{25,0,1576},
+{25,0,1576},{25,0,1576},{25,0,1576},{11,1,421},{11,1,421},{11,1,421},{13,33,2},{14,1,37},{14,1,37},{21,1,3786},{7,1,3105},{7,1,2880},{23,1,1929},{7,1,3648},{9,1,1532},{25,1,1078},{27,1,20},{13,1,2452},{47,1,89},{3,1,456},{19,1,353},{19,1,317},{35,1,89},{33,33,683},{5,1,321},{21,1,193},{13,1,1},{33,33,683},{13,1,1},{7,1,2880},{7,1,2880},{7,1,2880},
+{23,1,1929},{39,1,2411},{25,1,1078},{25,1,1078},{27,1,20},{29,1,1451},{47,1,89},{19,1,317},{19,1,317},{19,1,317},{35,1,89},{3,3,512},{21,1,193},{21,1,193},{13,1,1},{3,3,512},{13,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{39,0,1570},{39,0,1570},{39,0,1570},{39,0,1570},{41,1,505},
+{41,1,505},{41,1,505},{27,17,5},{47,1,89},{47,1,89},{21,1,3210},{21,1,2729},{37,1,2571},{7,1,1825},{21,1,3015},{39,1,1388},{9,1,1027},{11,1,5},{11,1,2032},{15,1,185},{3,1,264},{3,1,189},{3,1,164},{19,1,45},{17,3,384},{35,1,164},{35,1,100},{25,1,1},{35,1,384},{25,1,1},{37,1,2571},{37,1,2571},{37,1,2571},{7,1,1825},{7,1,2112},{9,1,1027},{9,1,1027},
+{11,1,5},{13,1,1235},{15,1,185},{3,1,164},{3,1,164},{3,1,164},{19,1,45},{33,3,288},{35,1,100},{35,1,100},{25,1,1},{21,1,288},{25,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{23,0,1576},{23,0,1576},{23,0,1576},{23,0,1576},{9,1,586},{9,1,586},{9,1,586},{11,1,5},{15,1,185},
+{15,1,185},{0,37,2665},{0,45,274},{0,44,8},{0,26,1025},{0,15,5885},{0,12,3666},{0,10,1742},{0,38,4406},{0,8,6359},{0,22,4730},{0,37,2665},{0,45,274},{0,44,8},{0,26,1025},{22,4,5885},{0,12,3666},{0,10,1742},{0,38,4406},{15,0,5885},{0,38,4406},{0,28,0},{0,28,0},{0,28,0},{0,6,1},{0,22,545},{0,20,208},{0,20,208},{0,18,340},{0,18,593},{0,18,376},{0,28,0},
+{0,28,0},{0,28,0},{0,6,1},{2,2,545},{0,20,208},{0,20,208},{0,18,340},{22,0,545},{0,18,340},{28,0,2665},{0,45,274},{0,44,8},{0,26,1025},{28,0,2665},{37,0,2665},{0,26,1025},{0,24,2665},{37,0,2665},{0,24,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,3,2665},{0,43,169},{0,14,17},
+{0,12,865},{0,13,6669},{0,28,3898},{0,42,1825},{0,8,4826},{0,24,7263},{0,38,5231},{0,3,2665},{0,43,169},{0,14,17},{0,12,865},{24,2,6669},{0,28,3898},{0,42,1825},{0,8,4826},{13,0,6669},{0,8,4826},{0,46,1},{0,46,1},{0,46,1},{0,8,4},{0,8,841},{0,6,306},{0,6,306},{0,34,520},{0,34,917},{0,34,584},{0,46,1},{0,46,1},{0,46,1},{0,8,4},{4,0,841},
+{0,6,306},{0,6,306},{0,34,520},{8,0,841},{0,34,520},{44,2,2665},{0,43,169},{16,14,2},{0,12,865},{44,2,2665},{3,0,2665},{0,12,865},{0,40,2669},{3,0,2665},{0,40,2669},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,1,2669},{0,41,85},{16,46,79},{0,44,725},{0,11,7538},{0,14,4214},{0,12,1842},
+{0,8,5354},{0,10,8241},{0,8,5795},{0,1,2669},{0,41,85},{16,46,54},{0,44,725},{24,4,7538},{0,14,4214},{0,12,1842},{0,8,5354},{11,0,7538},{0,8,5354},{0,29,1},{0,29,1},{0,29,1},{0,24,4},{0,40,1201},{0,22,458},{0,22,458},{0,4,730},{0,4,1325},{0,4,830},{0,29,1},{0,29,1},{0,29,1},{0,24,4},{20,0,1201},{0,22,458},{0,22,458},{0,4,730},{40,0,1201},
+{0,4,730},{30,2,2665},{0,41,85},{32,46,5},{0,44,725},{30,2,2665},{35,2,2665},{0,44,725},{0,26,2665},{35,2,2665},{0,26,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{16,1,2799},{0,9,29},{16,31,167},{0,14,650},{0,9,8493},{0,46,4485},{0,44,1934},{0,40,5878},{0,26,9333},{0,40,6503},{16,1,2774},
+{0,9,29},{16,31,142},{0,14,650},{42,0,8493},{0,46,4485},{0,44,1934},{0,40,5878},{9,0,8493},{0,40,5878},{0,11,0},{0,11,0},{0,11,0},{0,26,1},{0,26,1625},{0,24,629},{0,24,629},{0,20,986},{0,20,1793},{0,20,1130},{0,11,0},{0,11,0},{0,11,0},{0,26,1},{36,0,1625},{0,24,629},{0,24,629},{0,20,986},{26,0,1625},{0,20,986},{2,1,2665},{0,9,29},{18,47,1},
+{0,14,650},{2,1,2665},{1,2,2665},{0,14,650},{0,42,2669},{1,2,2665},{0,42,2669},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{32,1,3171},{0,7,4},{16,15,315},{0,46,514},{0,7,9669},{0,31,4865},{0,46,2114},{0,10,6505},{0,12,10663},{0,10,7181},{32,1,3050},{0,7,4},{32,15,274},{0,46,514},{26,4,9669},
+{0,31,4865},{0,46,2114},{0,10,6505},{7,0,9669},{0,10,6505},{0,23,0},{0,23,0},{0,23,0},{0,12,1},{0,28,2178},{0,10,820},{0,10,820},{0,6,1348},{0,6,2405},{0,20,1553},{0,23,0},{0,23,0},{0,23,0},{0,12,1},{2,24,2178},{0,10,820},{0,10,820},{0,6,1348},{28,0,2178},{0,6,1348},{29,0,2665},{0,7,4},{4,31,9},{0,46,514},{29,0,2665},{17,4,2665},{0,46,514},
+{0,28,2665},{17,4,2665},{0,28,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,1,3529},{16,21,35},{32,29,444},{0,31,474},{0,19,9670},{0,45,4529},{0,46,1634},{0,42,6265},{0,28,10919},{0,26,7149},{18,1,3146},{16,21,10},{2,29,285},{0,31,474},{14,0,9669},{0,45,4529},{0,46,1634},{0,42,6265},{8,10,9669},
+{0,42,6265},{16,21,34},{16,21,34},{16,21,34},{16,44,34},{0,46,2180},{0,12,610},{0,12,610},{0,22,1184},{0,22,2517},{0,22,1473},{16,21,9},{16,21,9},{16,21,9},{16,44,9},{22,2,2178},{0,12,610},{0,12,610},{0,22,1184},{42,2,2178},{0,22,1184},{13,2,2665},{16,21,1},{20,45,0},{0,31,410},{13,2,2665},{3,6,2665},{0,31,410},{0,14,2677},{3,6,2665},{0,14,2677},{16,0,34},
+{16,0,34},{16,0,34},{16,0,34},{0,34,0},{0,34,0},{0,34,0},{0,32,1},{0,32,10},{0,32,10},{18,1,3971},{32,35,150},{2,43,644},{16,45,534},{0,1,9669},{0,43,4214},{0,31,1226},{0,28,5954},{0,14,11246},{0,12,6951},{4,1,3285},{2,5,4},{34,13,274},{32,15,483},{0,1,9669},{0,43,4214},{0,31,1226},{0,28,5954},{1,0,9669},{0,28,5954},{16,3,146},{16,3,146},{16,3,146},
+{16,30,147},{0,29,2180},{0,28,458},{0,28,458},{0,8,1018},{0,8,2691},{0,38,1419},{2,21,0},{2,21,0},{2,21,0},{2,14,1},{8,2,2178},{0,28,458},{0,28,458},{0,8,1018},{30,2,2178},{0,8,1018},{27,2,2665},{2,5,4},{6,29,9},{0,15,338},{27,2,2665},{35,8,2665},{0,15,338},{0,30,2665},{35,8,2665},{0,30,2665},{16,0,146},{16,0,146},{16,0,146},{16,0,146},{0,6,1},
+{0,6,1},{0,6,1},{0,18,4},{0,18,40},{0,18,40},{34,1,4603},{32,3,307},{2,11,925},{32,29,667},{16,1,9779},{0,41,3905},{0,45,913},{0,44,5653},{0,46,11530},{0,44,6878},{36,1,3390},{18,19,11},{4,27,269},{2,29,474},{18,3,9669},{0,41,3905},{0,45,913},{0,44,5653},{45,8,9669},{0,44,5653},{32,1,291},{32,1,291},{32,1,291},{32,47,291},{0,11,2178},{0,46,305},{0,46,305},
+{0,40,925},{0,10,2872},{0,8,1427},{34,5,10},{34,5,10},{34,5,10},{18,46,9},{24,4,2178},{0,46,305},{0,46,305},{0,40,925},{11,0,2178},{0,40,925},{8,1,2665},{18,19,2},{22,43,0},{0,29,265},{8,1,2665},{1,8,2665},{0,29,265},{0,46,2677},{1,8,2665},{0,46,2677},{32,0,290},{32,0,290},{32,0,290},{32,0,290},{0,24,1},{0,24,1},{0,24,1},{0,20,1},{0,34,100},
+{0,34,100},{20,1,5538},{2,17,582},{34,41,1298},{2,43,882},{2,1,10086},{0,9,3618},{0,43,581},{0,30,5418},{0,15,11905},{0,14,6895},{22,1,3586},{4,3,3},{36,11,273},{34,43,478},{15,2,9669},{0,9,3618},{0,43,581},{0,30,5418},{33,4,9669},{0,30,5418},{2,1,570},{2,1,570},{2,1,570},{2,15,549},{0,23,2178},{0,15,185},{0,15,185},{0,10,765},{0,26,3090},{0,10,1441},{4,3,2},
+{4,3,2},{4,3,2},{4,47,2},{38,10,2178},{0,15,185},{0,15,185},{0,10,765},{23,0,2178},{0,10,765},{23,0,2665},{4,3,2},{8,11,8},{0,43,181},{23,0,2665},{18,9,2665},{0,43,181},{0,31,2665},{18,9,2665},{0,31,2665},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,28,0},{0,28,0},{0,28,0},{0,6,1},{0,20,208},{0,20,208},{36,1,6378},{18,1,926},{4,9,1734},
+{18,27,1131},{18,1,10495},{0,7,3434},{0,27,353},{0,47,5186},{0,45,12293},{0,46,6789},{8,1,3785},{20,17,10},{6,25,270},{4,27,491},{43,0,9669},{0,7,3434},{0,27,353},{0,47,5186},{19,6,9669},{0,47,5186},{18,1,922},{18,1,922},{18,1,922},{18,45,842},{0,5,2180},{0,29,106},{0,29,106},{0,42,666},{0,12,3301},{0,26,1514},{36,3,4},{36,3,4},{36,3,4},{36,15,8},{28,2,2178},
+{0,29,106},{0,29,106},{0,42,666},{42,8,2178},{0,42,666},{7,2,2665},{20,17,1},{24,41,2},{0,11,136},{7,2,2665},{2,7,2665},{0,11,136},{0,15,2669},{2,7,2665},{0,15,2669},{18,0,841},{18,0,841},{18,0,841},{18,0,841},{0,46,1},{0,46,1},{0,46,1},{0,8,4},{0,6,306},{0,6,306},{6,1,7490},{34,1,1446},{4,39,2218},{18,41,1450},{34,1,11103},{0,21,3209},{0,41,187},
+{0,31,4909},{0,43,12686},{0,31,6845},{40,1,3938},{6,1,3},{38,9,273},{36,41,478},{11,0,9669},{0,21,3209},{0,41,187},{0,31,4909},{5,8,9669},{0,31,4909},{34,1,1382},{34,1,1382},{34,1,1382},{34,13,1213},{0,17,2178},{0,27,40},{0,27,40},{0,28,544},{0,44,3603},{0,12,1541},{6,1,2},{6,1,2},{6,1,2},{6,45,2},{16,3,2178},{0,27,40},{0,27,40},{0,28,544},{17,0,2178},
+{0,28,544},{21,2,2665},{6,1,2},{10,9,8},{0,25,90},{21,2,2665},{16,5,2665},{0,25,90},{0,29,2665},{16,5,2665},{0,29,2665},{34,0,1213},{34,0,1213},{34,0,1213},{34,0,1213},{0,29,1},{0,29,1},{0,29,1},{0,24,4},{0,22,458},{0,22,458},{22,1,8710},{20,1,2145},{20,7,2826},{34,25,1850},{20,1,11913},{0,35,3073},{0,9,86},{0,15,4721},{0,41,13118},{0,15,6837},{26,1,4118},
+{38,1,29},{8,23,258},{6,25,491},{24,3,9669},{0,35,3073},{0,9,86},{0,15,4721},{3,24,9669},{0,15,4721},{4,1,1973},{4,1,1973},{4,1,1973},{34,27,1630},{16,1,2221},{0,25,10},{0,25,10},{0,44,450},{0,46,3876},{0,28,1633},{38,1,4},{38,1,4},{38,1,4},{38,29,8},{30,4,2178},{0,25,10},{0,25,10},{0,44,450},{15,8,2178},{0,44,450},{14,1,2665},{8,1,25},{26,39,1},
+{0,9,61},{14,1,2665},{4,5,2665},{0,9,61},{0,13,2669},{4,5,2665},{0,13,2669},{34,0,1629},{34,0,1629},{34,0,1629},{34,0,1629},{0,11,0},{0,11,0},{0,11,0},{0,26,1},{0,24,629},{0,24,629},{8,1,10335},{36,1,3100},{36,21,3546},{4,39,2361},{36,1,12883},{0,33,2901},{0,23,25},{0,13,4485},{0,25,13589},{0,45,6982},{42,1,4353},{24,1,117},{40,37,270},{38,39,491},{29,12,9669},
+{0,33,2901},{0,23,25},{0,13,4485},{26,13,9669},{0,13,4485},{36,1,2739},{36,1,2739},{36,1,2739},{4,41,2181},{32,1,2427},{0,39,4},{0,39,4},{0,46,353},{0,31,4242},{0,14,1830},{24,1,17},{24,1,17},{24,1,17},{8,43,2},{45,0,2178},{16,39,2},{16,39,2},{0,46,353},{27,8,2178},{0,46,353},{17,0,2665},{40,1,73},{12,7,5},{0,23,25},{17,0,2665},{18,3,2665},{0,23,25},
+{0,27,2665},{18,3,2665},{0,27,2665},{4,0,2180},{4,0,2180},{4,0,2180},{4,0,2180},{0,23,0},{0,23,0},{0,23,0},{0,12,1},{0,10,820},{0,10,820},{24,1,11582},{6,1,4137},{6,35,4199},{20,7,2845},{6,1,13958},{0,1,2826},{0,37,31},{0,43,4255},{0,39,13958},{0,43,6958},{28,1,4610},{10,1,278},{10,21,261},{8,23,481},{37,0,9669},{0,1,2825},{16,37,18},{0,43,4254},{36,9,9669},
+{0,43,4254},{36,1,3454},{36,1,3454},{36,1,3454},{20,9,2665},{18,1,2740},{16,7,26},{16,7,26},{0,47,278},{0,15,4491},{0,46,1858},{40,1,29},{40,1,29},{40,1,29},{40,27,5},{29,2,2178},{32,23,2},{32,23,2},{0,47,277},{35,6,2178},{0,47,277},{1,2,2665},{42,1,157},{28,37,2},{0,37,5},{1,2,2665},{2,1,2665},{0,37,5},{0,11,2677},{2,1,2665},{0,11,2677},{20,0,2665},
+{20,0,2665},{20,0,2665},{20,0,2665},{0,5,2},{0,5,2},{0,5,2},{0,14,5},{0,12,981},{0,12,981},{40,1,12090},{38,1,4554},{22,19,4203},{36,21,2837},{38,1,14410},{32,1,2930},{32,21,37},{0,27,4187},{0,37,13477},{0,27,6222},{14,1,4826},{42,1,465},{42,35,270},{40,7,488},{5,0,9669},{2,1,2921},{2,21,25},{0,27,4106},{0,5,9669},{0,27,4106},{22,1,3593},{22,1,3593},{22,1,3593},
+{6,39,2677},{34,1,2840},{32,21,21},{32,21,21},{16,15,277},{0,43,4186},{0,31,1450},{26,1,52},{26,1,52},{26,1,52},{10,41,2},{43,2,2178},{18,7,4},{18,7,4},{0,15,205},{21,8,2178},{0,15,205},{13,3,2665},{44,1,260},{14,5,5},{0,5,8},{13,3,2665},{20,1,2665},{0,5,8},{0,25,2665},{20,1,2665},{0,25,2665},{6,0,2677},{6,0,2677},{6,0,2677},{6,0,2677},{32,35,4},
+{32,35,4},{32,35,4},{32,30,5},{0,28,745},{0,28,745},{26,1,12542},{24,1,4990},{8,33,4178},{22,5,2845},{24,1,14719},{2,1,3162},{18,35,34},{16,41,4197},{0,5,13013},{0,41,5610},{46,1,5121},{28,1,754},{12,19,270},{26,21,484},{30,3,9669},{4,1,3110},{18,35,18},{0,41,3929},{42,9,9669},{0,41,3929},{8,1,3770},{8,1,3770},{8,1,3770},{22,7,2666},{20,1,3011},{18,5,26},{18,5,26},
+{32,45,261},{0,27,3822},{0,15,1062},{12,1,98},{12,1,98},{12,1,98},{42,25,5},{38,1,2178},{34,21,2},{34,21,2},{0,29,160},{43,28,2178},{0,29,160},{43,1,2665},{30,1,388},{30,35,2},{16,35,2},{43,1,2665},{8,1,2665},{16,35,2},{0,9,2677},{8,1,2665},{0,9,2677},{22,0,2665},{22,0,2665},{22,0,2665},{22,0,2665},{2,3,2},{2,3,2},{2,3,2},{2,46,5},{0,46,578},
+{0,46,578},{12,1,13222},{40,1,5610},{40,17,4197},{38,19,2849},{26,1,15194},{4,1,3497},{34,19,34},{32,9,4178},{0,3,12493},{0,25,4990},{47,1,5429},{14,1,1062},{44,33,261},{42,5,499},{46,1,9669},{36,1,3341},{4,19,26},{0,9,3770},{26,7,9669},{0,9,3770},{40,1,3929},{40,1,3929},{40,1,3929},{8,37,2678},{6,1,3174},{34,19,18},{34,19,18},{18,13,270},{0,25,3462},{0,29,754},{28,1,160},
+{28,1,160},{28,1,160},{12,39,5},{39,0,2178},{20,35,2},{20,35,2},{0,13,98},{9,28,2178},{0,13,98},{11,1,2665},{47,1,578},{47,3,5},{2,3,2},{11,1,2665},{42,1,2665},{2,3,2},{0,23,2665},{42,1,2665},{0,23,2665},{8,0,2677},{8,0,2677},{8,0,2677},{8,0,2677},{34,17,2},{34,17,2},{34,17,2},{34,31,2},{0,31,388},{0,31,388},{28,1,13826},{26,1,6222},{26,1,4187},
+{24,3,2835},{42,1,15614},{36,1,3886},{20,33,37},{18,23,4203},{0,17,12134},{0,39,4554},{45,1,5669},{30,1,1450},{14,17,277},{28,19,484},{31,1,9669},{38,1,3605},{20,33,21},{0,23,3593},{32,1,9669},{0,23,3593},{26,1,4106},{26,1,4106},{26,1,4106},{24,5,2665},{22,1,3378},{20,3,25},{20,3,25},{34,43,270},{0,39,3206},{0,43,465},{14,1,205},{14,1,205},{14,1,205},{44,7,5},{23,2,2178},
+{36,3,4},{36,3,4},{0,27,52},{20,9,2178},{0,27,52},{39,3,2665},{29,1,745},{31,33,5},{34,33,4},{39,3,2665},{14,1,2665},{34,33,4},{0,7,2677},{14,1,2665},{0,7,2677},{24,0,2665},{24,0,2665},{24,0,2665},{24,0,2665},{4,1,8},{4,1,8},{4,1,8},{4,15,5},{0,45,260},{0,45,260},{14,1,14322},{42,1,6958},{42,1,4255},{40,17,2837},{28,1,16150},{38,1,4422},{36,1,31},
+{34,7,4199},{0,1,11889},{0,7,4137},{29,1,6018},{47,1,1858},{46,1,278},{44,3,499},{45,1,9669},{40,1,3905},{6,17,26},{0,37,3454},{27,9,9669},{0,37,3454},{42,1,4254},{42,1,4254},{42,1,4254},{40,19,2678},{24,1,3540},{36,17,18},{36,17,18},{20,11,261},{0,37,2979},{0,11,278},{46,1,277},{46,1,277},{46,1,277},{14,37,5},{37,2,2178},{22,33,2},{22,33,2},{0,41,29},{34,7,2178},
+{0,41,29},{7,3,2665},{13,1,981},{15,1,5},{4,1,2},{7,3,2665},{15,1,2665},{4,1,2},{0,21,2665},{15,1,2665},{0,21,2665},{10,0,2677},{10,0,2677},{10,0,2677},{10,0,2677},{36,1,5},{36,1,5},{36,1,5},{36,29,2},{0,43,157},{0,43,157},{30,1,13683},{44,1,6982},{12,1,4485},{26,17,2739},{14,1,15204},{24,1,4100},{22,1,25},{20,37,3546},{0,1,10840},{0,37,3100},{13,1,5451},
+{15,1,1830},{47,1,353},{30,33,333},{39,11,8712},{26,1,3507},{38,1,4},{0,37,2739},{22,1,8712},{0,37,2739},{12,1,4485},{12,1,4485},{12,1,4485},{26,3,2665},{40,1,3736},{22,1,25},{22,1,25},{36,41,270},{0,5,2779},{0,25,117},{47,1,353},{47,1,353},{47,1,353},{46,5,5},{44,1,2178},{38,17,2},{38,17,2},{0,25,17},{26,9,2178},{0,25,17},{3,25,2178},{11,1,820},{13,1,1},
+{22,1,0},{3,25,2178},{29,1,2178},{22,1,0},{0,5,2180},{29,1,2178},{0,5,2180},{26,0,2665},{26,0,2665},{26,0,2665},{26,0,2665},{22,1,25},{22,1,25},{22,1,25},{6,13,5},{0,41,73},{0,41,73},{47,1,12750},{14,1,6837},{14,1,4721},{12,1,2694},{30,1,14061},{40,1,3663},{8,1,86},{6,21,2826},{2,1,9775},{0,21,2145},{11,1,4689},{29,1,1633},{45,1,450},{47,17,195},{17,10,7578},
+{44,1,2961},{24,1,10},{0,5,1973},{24,1,7578},{0,5,1973},{14,1,4721},{14,1,4721},{14,1,4721},{12,17,2673},{26,1,3965},{8,1,86},{8,1,86},{22,9,258},{0,3,2571},{0,39,29},{45,1,450},{45,1,450},{45,1,450},{47,19,5},{31,5,2178},{24,1,10},{24,1,10},{0,39,4},{14,9,2178},{0,39,4},{37,1,1625},{25,1,629},{27,1,1},{10,1,0},{37,1,1625},{27,1,1625},{10,1,0},
+{0,35,1629},{27,1,1625},{0,35,1629},{12,0,2669},{12,0,2669},{12,0,2669},{12,0,2669},{8,1,61},{8,1,61},{8,1,61},{38,27,1},{0,9,25},{0,9,25},{15,1,12134},{30,1,6845},{30,1,4909},{28,1,2666},{47,1,13165},{26,1,3426},{40,1,187},{38,5,2218},{2,1,9023},{0,35,1446},{11,1,4097},{13,1,1541},{29,1,544},{31,17,90},{39,7,6661},{14,1,2525},{26,1,40},{0,35,1382},{26,1,6661},
+{0,35,1382},{30,1,4909},{30,1,4909},{30,1,4909},{28,1,2666},{12,1,4230},{40,1,187},{40,1,187},{8,39,273},{0,17,2453},{0,7,3},{29,1,544},{29,1,544},{29,1,544},{15,3,5},{17,2,2178},{26,1,40},{26,1,40},{0,7,2},{16,1,2178},{0,7,2},{21,1,1201},{23,1,458},{25,1,4},{28,1,1},{21,1,1201},{41,1,1201},{28,1,1},{0,35,1213},{41,1,1201},{0,35,1213},{28,0,2665},
+{28,0,2665},{28,0,2665},{28,0,2665},{24,1,90},{24,1,90},{24,1,90},{8,11,8},{0,7,2},{0,7,2},{45,1,11330},{47,1,6789},{46,1,5186},{14,1,2694},{47,1,12365},{42,1,3246},{26,1,353},{8,5,1734},{20,1,8393},{0,19,926},{25,1,3614},{27,1,1514},{43,1,666},{45,17,35},{9,3,5829},{47,1,2177},{28,1,106},{0,19,922},{31,3,5829},{0,19,922},{46,1,5186},{46,1,5186},{46,1,5186},
+{14,1,2694},{14,1,4504},{26,1,353},{26,1,353},{24,7,270},{16,1,2450},{16,21,10},{43,1,666},{43,1,666},{43,1,666},{45,33,2},{29,3,2178},{28,1,106},{28,1,106},{2,37,4},{43,9,2178},{2,37,4},{5,1,841},{7,1,306},{9,1,4},{47,1,1},{5,1,841},{9,1,841},{47,1,1},{0,19,841},{9,1,841},{0,19,841},{14,0,2669},{14,0,2669},{14,0,2669},{14,0,2669},{10,1,136},
+{10,1,136},{10,1,136},{40,25,2},{16,21,1},{16,21,1},{29,1,10834},{15,1,6895},{31,1,5418},{30,1,2786},{45,1,11530},{44,1,3154},{42,1,581},{40,35,1298},{36,1,7857},{16,3,582},{9,1,3105},{11,1,1441},{11,1,765},{13,1,8},{37,7,5082},{47,1,1905},{14,1,185},{0,3,570},{30,1,5082},{0,3,570},{31,1,5418},{31,1,5418},{31,1,5418},{30,1,2786},{30,1,4724},{42,1,581},{42,1,581},
+{10,37,273},{2,1,2587},{2,5,3},{11,1,765},{11,1,765},{11,1,765},{13,1,8},{39,11,2178},{14,1,185},{14,1,185},{2,5,2},{22,1,2178},{2,5,2},{3,3,545},{21,1,208},{7,1,1},{29,1,0},{3,3,545},{23,1,545},{29,1,0},{0,3,545},{23,1,545},{0,3,545},{30,0,2665},{30,0,2665},{30,0,2665},{30,0,2665},{42,1,181},{42,1,181},{42,1,181},{10,9,8},{2,5,2},
+{2,5,2},{13,1,10311},{45,1,6878},{45,1,5653},{47,1,2933},{29,1,10827},{14,1,3066},{44,1,913},{10,3,925},{8,1,7297},{2,33,307},{39,1,2707},{9,1,1427},{41,1,925},{27,1,32},{23,17,4344},{29,1,1611},{47,1,305},{0,33,291},{45,17,4344},{0,33,291},{45,1,5653},{45,1,5653},{45,1,5653},{47,1,2933},{47,1,5051},{44,1,913},{44,1,913},{26,5,269},{4,1,2859},{18,19,11},{41,1,925},
+{41,1,925},{41,1,925},{27,1,32},{25,5,2178},{47,1,305},{47,1,305},{18,19,10},{10,1,2178},{18,19,10},{33,3,288},{35,1,100},{21,1,1},{25,1,1},{33,3,288},{21,1,288},{25,1,1},{0,33,290},{21,1,288},{0,33,290},{47,0,2677},{47,0,2677},{47,0,2677},{47,0,2677},{28,1,265},{28,1,265},{28,1,265},{42,23,0},{18,19,2},{18,19,2},{11,1,9837},{13,1,6951},{29,1,5954},
+{15,1,3166},{13,1,10279},{47,1,3138},{30,1,1226},{42,3,644},{40,1,6929},{34,33,150},{7,1,2436},{39,1,1419},{9,1,1018},{11,1,101},{3,25,3779},{13,1,1475},{29,1,458},{2,17,146},{29,1,3779},{2,17,146},{29,1,5954},{29,1,5954},{29,1,5954},{15,1,3166},{31,1,5396},{30,1,1226},{30,1,1226},{12,35,274},{36,1,3147},{4,3,4},{9,1,1018},{9,1,1018},{9,1,1018},{11,1,101},{9,3,2178},
+{29,1,458},{29,1,458},{20,3,0},{31,3,2178},{20,3,0},{17,3,128},{19,1,40},{19,1,4},{7,1,1},{17,3,128},{35,1,128},{7,1,1},{0,17,146},{35,1,128},{0,17,146},{31,0,2665},{31,0,2665},{31,0,2665},{31,0,2665},{14,1,338},{14,1,338},{14,1,338},{28,7,9},{4,3,4},{4,3,4},{11,1,9437},{27,1,7149},{43,1,6265},{29,1,3402},{11,1,9788},{47,1,3234},{47,1,1634},
+{28,33,444},{42,1,6719},{20,17,35},{21,1,2210},{23,1,1473},{23,1,1184},{25,1,241},{21,17,3299},{11,1,1400},{13,1,610},{20,17,34},{17,21,3299},{20,17,34},{43,1,6265},{43,1,6265},{43,1,6265},{29,1,3402},{45,1,5621},{47,1,1634},{47,1,1634},{28,3,285},{8,1,3421},{20,17,10},{23,1,1184},{23,1,1184},{23,1,1184},{25,1,241},{23,3,2178},{13,1,610},{13,1,610},{20,17,9},{43,3,2178},
+{20,17,9},{17,1,34},{33,1,10},{33,1,1},{35,1,0},{17,1,34},{3,1,34},{35,1,0},{0,17,34},{3,1,34},{0,17,34},{15,0,2677},{15,0,2677},{15,0,2677},{15,0,2677},{30,1,410},{30,1,410},{30,1,410},{44,21,0},{20,17,1},{20,17,1},{9,1,9175},{11,1,7181},{11,1,6505},{13,1,3686},{11,1,9340},{45,1,3447},{47,1,2114},{14,17,315},{44,1,6532},{6,1,4},{21,1,2034},
+{21,1,1553},{7,1,1348},{39,1,410},{17,39,2904},{9,1,1411},{11,1,820},{22,1,0},{39,17,2904},{22,1,0},{11,1,6505},{11,1,6505},{11,1,6505},{13,1,3686},{13,1,5990},{47,1,2114},{47,1,2114},{14,33,274},{40,1,3789},{6,1,4},{7,1,1348},{7,1,1348},{7,1,1348},{39,1,410},{3,25,2178},{11,1,820},{11,1,820},{22,1,0},{29,1,2178},{22,1,0},{1,1,0},{1,1,0},{1,1,0},
+{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{29,0,2665},{29,0,2665},{29,0,2665},{29,0,2665},{47,1,514},{47,1,514},{47,1,514},{30,5,9},{6,1,4},{6,1,4},{9,1,7987},{41,1,6503},{41,1,5878},{27,1,3561},{25,1,8118},{29,1,3051},{45,1,1934},{30,17,167},{30,1,5562},{8,1,29},{5,1,1507},{21,1,1130},{21,1,986},{23,1,298},{19,3,2166},
+{23,1,1019},{25,1,629},{10,1,0},{39,1,2166},{10,1,0},{41,1,5878},{41,1,5878},{41,1,5878},{27,1,3561},{27,1,5301},{45,1,1934},{45,1,1934},{30,17,142},{42,1,3266},{8,1,29},{21,1,986},{21,1,986},{21,1,986},{23,1,298},{37,1,1625},{25,1,629},{25,1,629},{10,1,0},{27,1,1625},{10,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},
+{0,1,0},{1,1,0},{0,1,0},{43,0,2669},{43,0,2669},{43,0,2669},{43,0,2669},{15,1,650},{15,1,650},{15,1,650},{46,19,1},{8,1,29},{8,1,29},{39,1,7111},{9,1,5795},{9,1,5354},{11,1,3381},{9,1,6983},{13,1,2803},{13,1,1842},{47,17,79},{47,1,4802},{40,1,85},{35,1,1132},{5,1,830},{5,1,730},{7,1,226},{3,3,1601},{7,1,739},{23,1,458},{28,1,1},{3,3,1601},
+{28,1,1},{9,1,5354},{9,1,5354},{9,1,5354},{11,1,3381},{11,1,4622},{13,1,1842},{13,1,1842},{47,17,54},{44,1,2834},{40,1,85},{5,1,730},{5,1,730},{5,1,730},{7,1,226},{21,1,1201},{23,1,458},{23,1,458},{28,1,1},{41,1,1201},{28,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{27,0,2665},
+{27,0,2665},{27,0,2665},{27,0,2665},{45,1,725},{45,1,725},{45,1,725},{47,33,5},{40,1,85},{40,1,85},{23,1,6361},{39,1,5231},{9,1,4826},{41,1,3294},{39,1,6071},{11,1,2610},{43,1,1825},{15,1,17},{47,1,4162},{42,1,169},{19,1,792},{35,1,584},{35,1,520},{21,1,153},{19,1,1121},{7,1,531},{7,1,306},{47,1,1},{37,1,1121},{47,1,1},{9,1,4826},{9,1,4826},{9,1,4826},
+{41,1,3294},{41,1,4145},{43,1,1825},{43,1,1825},{15,1,17},{30,1,2474},{42,1,169},{35,1,520},{35,1,520},{35,1,520},{21,1,153},{5,1,841},{7,1,306},{7,1,306},{47,1,1},{9,1,841},{47,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{41,0,2669},{41,0,2669},{41,0,2669},{41,0,2669},{13,1,865},
+{13,1,865},{13,1,865},{15,17,2},{42,1,169},{42,1,169},{7,1,5637},{23,1,4730},{39,1,4406},{9,1,3146},{39,1,5287},{11,1,2418},{11,1,1742},{45,1,8},{29,1,3547},{44,1,274},{3,1,489},{19,1,376},{19,1,340},{35,1,100},{33,33,726},{5,1,344},{21,1,208},{29,1,0},{33,33,726},{29,1,0},{39,1,4406},{39,1,4406},{39,1,4406},{9,1,3146},{9,1,3630},{11,1,1742},{11,1,1742},
+{45,1,8},{47,1,2178},{44,1,274},{19,1,340},{19,1,340},{19,1,340},{35,1,100},{3,3,545},{21,1,208},{21,1,208},{29,1,0},{23,1,545},{29,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{25,0,2665},{25,0,2665},{25,0,2665},{25,0,2665},{27,1,1025},{27,1,1025},{27,1,1025},{45,1,8},{44,1,274},
+{44,1,274},{36,1,50644},{0,1,2121},{0,25,169},{0,41,4591},{20,1,59804},{0,3,19310},{0,11,7401},{0,43,24008},{0,9,65535},{0,15,40741},{18,1,10267},{0,3,1445},{0,41,137},{0,15,3985},{42,6,18065},{0,45,12064},{0,31,6081},{0,12,14121},{19,0,18065},{0,12,14121},{0,15,1},{0,15,1},{0,15,1},{0,24,0},{0,24,1105},{0,22,410},{0,22,410},{0,4,666},{0,4,1217},{0,4,766},{0,15,1},
+{0,15,1},{0,15,1},{0,24,0},{34,2,1105},{0,22,410},{0,22,410},{0,4,666},{24,0,1105},{0,4,666},{43,2,9248},{0,3,1445},{0,41,137},{0,15,3985},{43,2,9248},{21,8,9248},{0,15,3985},{0,14,9256},{21,8,9248},{0,14,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{36,1,53600},{16,1,2998},{0,9,44},
+{0,25,3941},{36,1,62123},{0,1,18506},{0,25,6750},{0,27,23131},{0,39,65535},{0,29,40569},{34,1,10859},{0,1,1241},{0,9,50},{0,13,3690},{16,3,19334},{0,43,12449},{0,15,6117},{0,28,14809},{17,0,19334},{0,28,14809},{0,27,0},{0,27,0},{0,27,0},{0,10,1},{0,26,1513},{0,8,585},{0,8,585},{0,20,914},{0,20,1669},{0,20,1058},{0,27,0},{0,27,0},{0,27,0},{0,10,1},{34,4,1513},
+{0,8,585},{0,8,585},{0,20,914},{26,0,1513},{0,20,914},{38,1,9248},{0,1,1241},{0,9,50},{0,13,3690},{38,1,9248},{43,28,9248},{0,13,3690},{0,46,9250},{43,28,9248},{0,46,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{36,1,56716},{16,1,4497},{0,23,30},{0,39,3500},{36,1,64625},{0,1,18101},{0,9,6313},
+{0,11,22459},{0,37,65535},{0,43,39632},{4,1,11624},{0,1,1225},{0,39,10},{0,27,3400},{16,1,20689},{0,41,12854},{0,43,6221},{0,44,15490},{19,2,20689},{0,44,15490},{0,9,1},{0,9,1},{0,9,1},{0,42,1},{0,12,1985},{0,10,757},{0,10,757},{0,36,1241},{0,36,2193},{0,20,1394},{0,9,1},{0,9,1},{0,9,1},{0,42,1},{6,0,1985},{0,10,757},{0,10,757},{0,36,1241},{12,0,1985},
+{0,36,1241},{24,1,9248},{0,1,1225},{0,39,10},{0,27,3400},{24,1,9248},{32,9,9248},{0,27,3400},{0,47,9248},{32,9,9248},{0,47,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,1,58324},{32,1,6344},{0,7,6},{0,23,2873},{36,1,65535},{16,1,17968},{0,23,5727},{0,25,21128},{0,21,63585},{0,27,38087},{36,1,12449},
+{16,1,1437},{0,7,9},{0,41,3185},{47,2,22129},{0,25,13298},{0,43,6189},{0,44,16354},{17,2,22129},{0,44,16354},{0,21,0},{0,21,0},{0,21,0},{0,44,1},{0,44,2521},{0,26,953},{0,26,953},{0,6,1553},{0,6,2770},{0,6,1778},{0,21,0},{0,21,0},{0,21,0},{0,44,1},{22,0,2521},{0,26,953},{0,26,953},{0,6,1553},{44,0,2521},{0,6,1553},{7,0,9248},{16,1,1412},{16,7,0},
+{0,41,3185},{7,0,9248},{0,7,9248},{0,41,3185},{0,15,9266},{0,7,9248},{0,15,9266},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{22,1,58878},{32,1,8497},{0,21,52},{0,37,2302},{22,1,65535},{16,1,18091},{0,37,5062},{0,9,19646},{0,5,60796},{0,41,35977},{36,1,13547},{16,1,1923},{16,21,62},{0,25,2897},{45,0,23851},
+{0,39,13856},{0,27,6323},{0,46,17289},{27,8,23851},{0,46,17289},{0,33,0},{0,33,0},{0,33,0},{0,30,0},{0,46,3200},{0,12,1186},{0,12,1186},{0,38,1962},{0,22,3521},{0,22,2261},{0,33,0},{0,33,0},{0,33,0},{0,30,0},{18,10,3200},{0,12,1186},{0,12,1186},{0,38,1962},{46,0,3200},{0,38,1962},{37,2,9248},{2,1,1717},{2,21,5},{0,25,2897},{37,2,9248},{34,7,9248},{0,25,2897},
+{0,45,9250},{34,7,9248},{0,45,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{22,1,59528},{2,1,10468},{0,5,122},{0,21,1965},{22,1,65535},{16,1,18728},{0,21,4602},{0,23,18427},{0,3,58418},{0,25,34396},{6,1,14752},{2,1,2501},{16,35,141},{0,39,2720},{45,2,25472},{0,37,14401},{0,41,6413},{0,46,18185},{25,8,25472},
+{0,46,18185},{0,1,16},{0,1,16},{0,1,16},{0,47,0},{0,31,3872},{0,28,1450},{0,28,1450},{0,38,2362},{0,38,4283},{0,38,2723},{0,1,16},{0,1,16},{0,1,16},{0,47,0},{36,6,3872},{0,28,1450},{0,28,1450},{0,38,2362},{31,0,3872},{0,38,2362},{44,1,9248},{20,1,2041},{18,5,2},{0,39,2720},{44,1,9248},{26,9,9248},{0,39,2720},{0,13,9256},{26,9,9248},{0,13,9256},{0,0,0},
+{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{24,1,60070},{2,1,12544},{0,19,188},{0,35,1604},{22,1,65535},{32,1,19503},{0,5,4081},{0,7,17117},{0,3,56204},{0,25,32856},{22,1,15824},{2,1,3225},{32,19,229},{0,7,2478},{46,10,26744},{0,21,14657},{0,25,6357},{0,31,18737},{23,8,26744},{0,31,18737},{16,1,115},{16,1,115},{16,1,115},
+{0,15,5},{0,29,4420},{0,46,1613},{0,46,1613},{0,8,2642},{0,8,4931},{0,8,3083},{16,1,90},{16,1,90},{16,1,90},{0,15,5},{8,2,4418},{0,46,1613},{0,46,1613},{0,8,2642},{30,2,4418},{0,8,2642},{33,0,9248},{36,1,2405},{34,19,5},{0,7,2474},{33,0,9248},{32,3,9248},{0,7,2474},{0,43,9250},{32,3,9248},{0,43,9250},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,16,1},
+{0,16,1},{0,16,1},{0,16,1},{0,16,2},{0,16,2},{24,1,60699},{2,1,14864},{16,3,314},{0,19,1400},{24,1,65535},{2,1,20230},{0,19,3323},{0,37,15488},{0,17,54456},{0,39,31364},{24,1,16210},{4,1,3849},{2,33,221},{0,37,2328},{38,3,26744},{0,3,14114},{0,23,5618},{0,15,18273},{35,8,26744},{0,15,18273},{32,1,291},{32,1,291},{32,1,291},{16,29,50},{0,11,4418},{0,31,1325},{0,31,1325},
+{0,10,2465},{0,10,5112},{0,8,3051},{2,1,136},{2,1,136},{2,1,136},{32,29,5},{24,4,4418},{0,31,1325},{0,31,1325},{0,10,2465},{11,0,4418},{0,10,2465},{47,1,9248},{8,1,2738},{20,3,1},{0,37,2228},{47,1,9248},{31,9,9248},{0,37,2228},{0,11,9256},{31,9,9248},{0,11,9256},{16,0,50},{16,0,50},{16,0,50},{16,0,50},{0,4,0},{0,4,0},{0,4,0},{0,2,0},{0,32,18},
+{0,32,18},{24,1,61549},{2,1,17597},{16,17,476},{0,33,1268},{24,1,65535},{2,1,21346},{0,33,2615},{0,5,13900},{0,17,52724},{0,37,29656},{40,1,16729},{36,1,4545},{34,1,221},{32,21,2384},{8,1,26744},{0,3,13529},{0,37,4710},{0,29,17819},{1,8,26744},{0,29,17819},{2,1,626},{2,1,626},{2,1,626},{32,43,185},{0,23,4418},{0,45,1037},{0,45,1037},{0,10,2249},{0,26,5330},{0,10,2925},{34,1,185},
+{34,1,185},{34,1,185},{18,13,4},{38,10,4418},{0,45,1037},{0,45,1037},{0,10,2249},{23,0,4418},{0,10,2249},{29,3,9248},{40,1,3188},{6,17,2},{0,35,2041},{29,3,9248},{43,9,9248},{0,35,2041},{0,41,9256},{43,9,9248},{0,41,9256},{32,0,185},{32,0,185},{32,0,185},{32,0,185},{0,38,0},{0,38,0},{0,38,0},{0,34,1},{0,18,61},{0,18,61},{40,1,62083},{4,1,19345},{16,1,697},
+{0,17,1188},{24,1,65535},{2,1,22086},{0,17,2057},{0,35,12551},{0,1,51532},{0,37,28158},{26,1,16691},{36,1,5081},{20,1,265},{32,35,2281},{29,12,26259},{0,17,12803},{0,5,3981},{0,43,16952},{26,13,26259},{0,43,16952},{18,1,1006},{18,1,1006},{18,1,1006},{2,11,378},{0,5,4420},{0,43,820},{0,43,820},{0,12,2020},{0,12,5541},{0,42,2966},{20,1,265},{20,1,265},{20,1,265},{34,27,1},{28,2,4418},
+{0,43,820},{0,43,820},{0,12,2020},{42,8,4418},{0,12,2020},{43,3,8978},{42,1,3434},{22,1,1},{0,19,1737},{43,3,8978},{45,7,8978},{0,19,1737},{0,9,8986},{45,7,8978},{0,9,8986},{2,0,377},{2,0,377},{2,0,377},{2,0,377},{0,10,1},{0,10,1},{0,10,1},{0,20,4},{0,4,136},{0,4,136},{40,1,62361},{4,1,19653},{16,1,1095},{0,17,1126},{24,1,65535},{2,1,21601},{0,17,1502},
+{0,19,11253},{0,1,50904},{0,37,27226},{42,1,15419},{38,1,4708},{36,1,320},{18,19,1862},{23,2,24371},{0,1,11221},{0,35,2905},{0,27,15080},{20,9,24371},{0,27,15080},{34,1,1522},{34,1,1522},{34,1,1522},{2,25,618},{0,17,4418},{0,41,610},{0,41,610},{0,44,1810},{0,44,5843},{0,12,2885},{36,1,320},{36,1,320},{36,1,320},{20,11,9},{16,3,4418},{0,41,610},{0,41,610},{0,44,1810},{17,0,4418},
+{0,44,1810},{27,3,7938},{44,1,3033},{8,1,4},{0,19,1225},{27,3,7938},{39,9,7938},{0,19,1225},{0,9,7946},{39,9,7938},{0,9,7946},{2,0,617},{2,0,617},{2,0,617},{2,0,617},{0,44,0},{0,44,0},{0,44,0},{0,22,1},{0,36,232},{0,36,232},{40,1,62690},{4,1,20049},{32,1,1585},{16,17,1131},{40,1,65535},{2,1,21187},{0,17,1035},{0,19,10004},{0,1,50320},{0,37,26351},{28,1,14260},
+{24,1,4365},{22,1,410},{4,19,1523},{47,11,22568},{0,1,9893},{0,19,1997},{0,27,13320},{22,9,22568},{0,27,13320},{4,1,2169},{4,1,2169},{4,1,2169},{18,9,929},{16,1,4461},{0,9,442},{0,9,442},{0,14,1665},{0,46,6116},{0,44,2907},{22,1,410},{22,1,410},{22,1,410},{36,25,1},{30,4,4418},{0,9,442},{0,9,442},{0,14,1665},{15,8,4418},{0,14,1665},{11,3,6962},{14,1,2645},{10,1,1},
+{0,3,832},{11,3,6962},{44,3,6962},{0,3,832},{0,39,6962},{44,3,6962},{0,39,6962},{18,0,925},{18,0,925},{18,0,925},{18,0,925},{0,47,0},{0,47,0},{0,47,0},{0,8,0},{0,22,338},{0,22,338},{40,1,63078},{4,1,20586},{32,1,2208},{16,1,1221},{40,1,65535},{2,1,20797},{0,17,616},{0,19,8676},{0,1,49684},{0,37,25424},{14,1,12942},{40,1,4061},{8,1,530},{36,19,1147},{21,2,20642},
+{16,1,8678},{0,3,1157},{0,41,11489},{24,9,20642},{0,41,11489},{20,1,3009},{20,1,3009},{20,1,3009},{34,7,1358},{32,1,4667},{0,7,305},{0,7,305},{0,46,1445},{0,31,6482},{0,14,3034},{8,1,530},{8,1,530},{8,1,530},{22,9,5},{45,0,4418},{0,7,305},{0,7,305},{0,46,1445},{27,8,4418},{0,46,1445},{11,1,5941},{30,1,2260},{42,1,0},{0,33,445},{11,1,5941},{26,1,5941},{0,33,445},
+{0,23,5941},{26,1,5941},{0,23,5941},{34,0,1354},{34,0,1354},{34,0,1354},{34,0,1354},{0,13,0},{0,13,0},{0,13,0},{0,40,1},{0,8,522},{0,8,522},{40,1,63433},{4,1,21145},{32,1,2873},{16,1,1404},{40,1,65535},{2,1,20517},{0,1,339},{0,19,7570},{0,1,49136},{0,37,24652},{30,1,11862},{26,1,3845},{40,1,617},{22,3,868},{44,1,19021},{2,1,7769},{0,33,621},{0,25,9957},{26,9,19021},
+{0,25,9957},{36,1,3819},{36,1,3819},{36,1,3819},{4,37,1809},{2,1,5012},{0,5,185},{0,5,185},{0,31,1285},{0,15,6822},{0,46,3029},{40,1,617},{40,1,617},{40,1,617},{38,23,2},{29,2,4418},{0,5,185},{0,5,185},{0,31,1285},{35,6,4418},{0,31,1285},{41,1,5101},{47,1,1924},{28,1,1},{0,17,221},{41,1,5101},{28,1,5101},{0,17,221},{0,7,5113},{28,1,5101},{0,7,5113},{4,0,1808},
+{4,0,1808},{4,0,1808},{4,0,1808},{0,25,0},{0,25,0},{0,25,0},{0,26,4},{0,24,698},{0,24,698},{26,1,63733},{4,1,21777},{32,1,3641},{16,1,1687},{40,1,65535},{2,1,20303},{0,1,133},{0,3,6539},{0,1,48607},{0,37,23935},{30,1,10886},{42,1,3641},{26,1,724},{8,33,659},{46,3,17485},{2,1,6985},{0,17,257},{0,25,8565},{16,3,17485},{0,25,8565},{6,1,4820},{6,1,4820},{6,1,4820},
+{4,5,2324},{18,1,5437},{0,3,101},{0,3,101},{0,15,1129},{0,45,7234},{0,31,3141},{26,1,724},{26,1,724},{26,1,724},{24,7,4},{43,2,4418},{0,3,101},{0,3,101},{0,15,1129},{21,8,4418},{0,15,1129},{25,1,4325},{15,1,1658},{14,1,4},{0,17,61},{25,1,4325},{14,1,4325},{0,17,61},{0,7,4329},{14,1,4325},{0,7,4329},{4,0,2320},{4,0,2320},{4,0,2320},{4,0,2320},{0,7,0},
+{0,7,0},{0,7,0},{0,28,1},{0,10,872},{0,10,872},{26,1,63992},{4,1,22482},{2,1,4507},{32,1,2059},{40,1,65535},{2,1,20157},{0,1,26},{0,3,5537},{0,1,48100},{0,21,23272},{47,1,9918},{28,1,3518},{42,1,832},{24,33,446},{46,1,16034},{4,1,6314},{0,1,65},{0,39,7293},{26,7,16034},{0,39,7293},{22,1,5900},{22,1,5900},{22,1,5900},{20,19,2888},{34,1,6029},{0,17,40},{0,17,40},
+{0,29,1000},{0,43,7619},{0,15,3261},{42,1,832},{42,1,832},{42,1,832},{40,21,1},{38,1,4418},{0,17,40},{0,17,40},{0,29,1000},{43,28,4418},{0,29,1000},{9,1,3613},{29,1,1345},{47,1,4},{0,1,1},{9,1,3613},{46,1,3613},{0,1,1},{0,37,3613},{46,1,3613},{0,37,3613},{20,0,2888},{20,0,2888},{20,0,2888},{20,0,2888},{0,19,1},{0,19,1},{0,19,1},{0,14,0},{0,12,1082},
+{0,12,1082},{26,1,64289},{20,1,23310},{2,1,5546},{32,1,2553},{40,1,65535},{2,1,20076},{0,1,26},{0,3,4514},{0,1,47560},{0,5,22518},{31,1,9017},{14,1,3261},{28,1,1000},{10,33,281},{17,2,14504},{36,1,5594},{16,1,40},{0,23,5900},{16,1,14504},{0,23,5900},{38,1,7293},{38,1,7293},{38,1,7293},{36,33,3614},{4,1,6900},{0,1,65},{0,1,65},{0,43,832},{0,41,8070},{0,29,3518},{28,1,1000},
+{28,1,1000},{28,1,1000},{26,5,2},{39,0,4418},{16,1,40},{16,1,40},{0,43,832},{9,28,4418},{0,43,832},{23,17,2888},{13,1,1082},{15,1,0},{18,1,1},{23,17,2888},{45,17,2888},{18,1,1},{0,21,2888},{45,17,2888},{0,21,2888},{36,0,3613},{36,0,3613},{36,0,3613},{36,0,3613},{0,1,1},{0,1,1},{0,1,1},{0,46,4},{0,28,1345},{0,28,1345},{26,1,64605},{36,1,24062},{2,1,6574},
+{32,1,3098},{26,1,65535},{2,1,20094},{0,1,133},{0,33,3661},{0,1,47145},{0,5,21893},{45,1,8116},{30,1,3141},{14,1,1129},{42,17,147},{43,7,13235},{38,1,5012},{2,1,101},{0,7,4820},{18,1,13235},{0,7,4820},{24,1,8565},{24,1,8565},{24,1,8565},{6,1,4329},{36,1,7725},{16,1,257},{16,1,257},{0,27,724},{0,25,8530},{0,43,3641},{14,1,1129},{14,1,1129},{14,1,1129},{42,19,2},{23,2,4418},
+{2,1,101},{2,1,101},{0,27,724},{20,9,4418},{0,27,724},{37,3,2312},{11,1,872},{29,1,1},{6,1,0},{37,3,2312},{21,5,2312},{6,1,0},{0,5,2320},{21,5,2312},{0,5,2320},{6,0,4329},{6,0,4329},{6,0,4329},{6,0,4329},{16,1,61},{16,1,61},{16,1,61},{0,15,4},{0,14,1658},{0,14,1658},{26,1,64960},{36,1,24888},{18,1,7643},{32,1,3742},{26,1,65535},{4,1,20161},{0,1,342},
+{0,33,2900},{0,1,46786},{0,5,21347},{29,1,7443},{47,1,3029},{30,1,1285},{12,17,66},{17,6,12051},{24,1,4500},{4,1,185},{0,37,3819},{20,1,12051},{0,37,3819},{24,1,9957},{24,1,9957},{24,1,9957},{22,1,5161},{36,1,8717},{32,1,621},{32,1,621},{0,41,617},{0,39,9026},{0,27,3845},{30,1,1285},{30,1,1285},{30,1,1285},{28,3,4},{37,2,4418},{4,1,185},{4,1,185},{0,41,617},{34,7,4418},
+{0,41,617},{21,3,1800},{25,1,698},{27,1,4},{24,1,0},{21,3,1800},{43,1,1800},{24,1,0},{0,5,1808},{43,1,1800},{0,5,1808},{6,0,5113},{6,0,5113},{6,0,5113},{6,0,5113},{16,1,221},{16,1,221},{16,1,221},{0,29,1},{0,46,1924},{0,46,1924},{26,1,65314},{36,1,25774},{18,1,8796},{32,1,4480},{26,1,65535},{4,1,20229},{16,1,625},{0,33,2238},{0,1,46456},{0,5,20870},{13,1,6795},
+{15,1,3034},{47,1,1445},{44,1,17},{39,11,10952},{40,1,4076},{6,1,305},{0,21,3009},{22,1,10952},{0,21,3009},{40,1,11489},{40,1,11489},{40,1,11489},{38,1,6125},{6,1,9922},{2,1,1157},{2,1,1157},{0,9,530},{0,37,9571},{0,41,4061},{47,1,1445},{47,1,1445},{47,1,1445},{44,17,2},{44,1,4418},{6,1,305},{6,1,305},{0,9,530},{26,9,4418},{0,9,530},{5,3,1352},{9,1,522},{41,1,1},
+{12,1,0},{5,3,1352},{11,1,1352},{12,1,0},{0,35,1354},{11,1,1352},{0,35,1354},{22,0,5941},{22,0,5941},{22,0,5941},{22,0,5941},{32,1,445},{32,1,445},{32,1,445},{0,43,0},{0,31,2260},{0,31,2260},{26,1,65535},{36,1,26766},{18,1,10162},{2,1,5359},{26,1,65359},{4,1,20334},{16,1,1051},{0,33,1610},{0,1,45998},{0,5,20364},{11,1,6173},{45,1,2907},{15,1,1665},{30,1,2},{17,10,9818},
+{42,1,3693},{8,1,442},{0,5,2169},{24,1,9818},{0,5,2169},{26,1,13320},{26,1,13320},{26,1,13320},{8,1,7395},{22,1,11384},{18,1,1997},{18,1,1997},{0,23,410},{0,21,10181},{0,25,4365},{15,1,1665},{15,1,1665},{15,1,1665},{30,1,2},{31,5,4418},{8,1,442},{8,1,442},{0,23,410},{14,9,4418},{0,23,410},{5,1,925},{23,1,338},{9,1,0},{46,1,0},{5,1,925},{9,1,925},{46,1,0},
+{0,19,925},{9,1,925},{0,19,925},{38,0,6962},{38,0,6962},{38,0,6962},{38,0,6962},{2,1,832},{2,1,832},{2,1,832},{0,11,1},{0,15,2645},{0,15,2645},{26,1,65535},{36,1,27616},{18,1,11415},{2,1,6203},{26,1,65014},{4,1,20439},{16,1,1524},{0,17,1111},{0,1,45494},{0,5,19935},{11,1,5581},{13,1,2885},{45,1,1810},{47,1,50},{39,7,8901},{44,1,3373},{40,1,610},{0,35,1522},{26,1,8901},
+{0,35,1522},{26,1,15080},{26,1,15080},{26,1,15080},{24,1,8661},{24,1,12846},{34,1,2905},{34,1,2905},{0,37,320},{0,3,10790},{0,39,4708},{45,1,1810},{45,1,1810},{45,1,1810},{47,1,50},{17,2,4418},{40,1,610},{40,1,610},{0,37,320},{16,1,4418},{0,37,320},{35,1,613},{37,1,232},{23,1,1},{45,1,0},{35,1,613},{23,1,613},{45,1,0},{0,3,617},{23,1,613},{0,3,617},{8,0,7946},
+{8,0,7946},{8,0,7946},{8,0,7946},{18,1,1225},{18,1,1225},{18,1,1225},{0,9,4},{0,45,3033},{0,45,3033},{26,1,65535},{36,1,28505},{34,1,12706},{2,1,7117},{26,1,64677},{4,1,20609},{16,1,2082},{0,17,705},{0,1,45031},{0,5,19583},{41,1,5202},{43,1,2966},{13,1,2020},{31,1,148},{9,3,8069},{30,1,3125},{42,1,820},{0,19,1006},{31,3,8069},{0,19,1006},{42,1,16952},{42,1,16952},{42,1,16952},
+{24,1,10085},{24,1,14318},{4,1,3981},{4,1,3981},{0,21,265},{0,3,11302},{0,37,5081},{13,1,2020},{13,1,2020},{13,1,2020},{31,1,148},{29,3,4418},{42,1,820},{42,1,820},{0,21,265},{43,9,4418},{0,21,265},{19,1,365},{5,1,136},{21,1,4},{11,1,1},{19,1,365},{37,1,365},{11,1,1},{0,3,377},{37,1,365},{0,3,377},{8,0,8986},{8,0,8986},{8,0,8986},{8,0,8986},{18,1,1737},
+{18,1,1737},{18,1,1737},{0,23,1},{0,43,3434},{0,43,3434},{42,1,65535},{36,1,29412},{4,1,13785},{18,1,7875},{26,1,64490},{20,1,20801},{32,1,2593},{16,17,472},{0,1,43813},{0,3,17452},{9,1,4729},{11,1,2925},{11,1,2249},{45,1,281},{37,7,7322},{47,1,2941},{44,1,1037},{0,3,626},{30,1,7322},{0,3,626},{28,1,17819},{28,1,17819},{28,1,17819},{40,1,10777},{40,1,15150},{36,1,4710},{36,1,4710},
+{0,35,221},{0,17,11076},{0,37,4545},{11,1,2249},{11,1,2249},{11,1,2249},{45,1,281},{39,11,4418},{44,1,1037},{44,1,1037},{0,35,185},{22,1,4418},{0,35,185},{3,1,181},{19,1,61},{35,1,1},{39,1,0},{3,1,181},{5,1,181},{39,1,0},{0,33,185},{5,1,181},{0,33,185},{40,0,9256},{40,0,9256},{40,0,9256},{40,0,9256},{34,1,2041},{34,1,2041},{34,1,2041},{16,7,2},{0,41,3188},
+{0,41,3188},{42,1,65535},{38,1,30127},{36,1,14877},{4,1,8601},{42,1,64081},{36,1,20736},{18,1,3192},{2,17,302},{0,1,42247},{0,3,14278},{39,1,4387},{9,1,3051},{11,1,2465},{13,1,490},{23,17,6584},{29,1,2843},{30,1,1325},{0,33,291},{45,17,6584},{0,33,291},{14,1,18273},{14,1,18273},{14,1,18273},{42,1,11259},{26,1,15731},{22,1,5618},{22,1,5618},{32,3,221},{0,1,10637},{0,5,3849},{11,1,2465},
+{11,1,2465},{11,1,2465},{13,1,490},{25,5,4418},{30,1,1325},{30,1,1325},{0,3,136},{10,1,4418},{0,3,136},{1,3,50},{33,1,18},{3,1,0},{5,1,0},{1,3,50},{3,1,50},{5,1,0},{0,17,50},{3,1,50},{0,17,50},{10,0,9256},{10,0,9256},{10,0,9256},{10,0,9256},{36,1,2228},{36,1,2228},{36,1,2228},{2,21,1},{0,9,2738},{0,9,2738},{28,1,65535},{24,1,30766},{6,1,16028},
+{36,1,9391},{28,1,64158},{36,1,21269},{4,1,3821},{18,1,176},{0,1,41339},{0,3,11746},{23,1,4216},{9,1,3083},{9,1,2642},{27,1,776},{3,25,6019},{13,1,2763},{47,1,1613},{0,17,115},{29,1,6019},{0,17,115},{30,1,18737},{30,1,18737},{30,1,18737},{12,1,11820},{42,1,16379},{24,1,6357},{24,1,6357},{18,33,229},{0,1,10589},{0,3,3225},{9,1,2642},{9,1,2642},{9,1,2642},{27,1,776},{9,3,4418},
+{47,1,1613},{47,1,1613},{0,17,90},{31,3,4418},{0,17,90},{1,17,2},{17,1,2},{17,1,1},{17,1,1},{1,17,2},{17,1,2},{17,1,1},{0,1,4},{17,1,2},{0,1,4},{42,0,9250},{42,0,9250},{42,0,9250},{42,0,9250},{6,1,2474},{6,1,2474},{6,1,2474},{18,35,5},{0,37,2405},{0,37,2405},{14,1,65535},{24,1,31241},{22,1,16737},{6,1,10024},{14,1,64173},{38,1,21415},{20,1,4180},
+{4,1,111},{16,1,40689},{0,3,9508},{7,1,3648},{39,1,2723},{39,1,2362},{11,1,725},{37,1,5163},{13,1,2451},{29,1,1450},{0,1,16},{7,19,5163},{0,1,16},{47,1,18185},{47,1,18185},{47,1,18185},{44,1,11714},{28,1,15784},{40,1,6413},{40,1,6413},{34,17,141},{0,1,9881},{0,3,2501},{39,1,2362},{39,1,2362},{39,1,2362},{11,1,725},{37,7,3872},{29,1,1450},{29,1,1450},{0,1,16},{30,1,3872},
+{0,1,16},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{12,0,9256},{12,0,9256},{12,0,9256},{12,0,9256},{38,1,2720},{38,1,2720},{38,1,2720},{4,19,2},{0,21,2041},{0,21,2041},{30,1,65535},{40,1,31563},{8,1,17236},{38,1,10554},{14,1,63701},{24,1,21372},{36,1,4441},{20,1,45},{16,1,40151},{0,33,7454},{21,1,3014},
+{23,1,2261},{39,1,1962},{25,1,629},{21,17,4267},{11,1,2028},{13,1,1186},{32,1,0},{17,21,4267},{32,1,0},{47,1,17289},{47,1,17289},{47,1,17289},{14,1,11436},{14,1,14726},{26,1,6323},{26,1,6323},{20,17,62},{16,1,9032},{0,17,1923},{39,1,1962},{39,1,1962},{39,1,1962},{25,1,629},{19,11,3200},{13,1,1186},{13,1,1186},{32,1,0},{47,1,3200},{32,1,0},{1,1,0},{1,1,0},{1,1,0},
+{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{44,0,9250},{44,0,9250},{44,0,9250},{44,0,9250},{24,1,2897},{24,1,2897},{24,1,2897},{20,3,5},{0,3,1717},{0,3,1717},{30,1,65535},{26,1,31988},{24,1,17745},{8,1,11181},{30,1,63430},{40,1,21435},{22,1,4810},{6,1,5},{2,1,39477},{0,33,5328},{21,1,2339},{7,1,1778},{7,1,1553},{9,1,477},{19,5,3361},
+{25,1,1634},{27,1,953},{20,1,0},{37,3,3361},{20,1,0},{45,1,16354},{45,1,16354},{45,1,16354},{30,1,11202},{30,1,13722},{42,1,6189},{42,1,6189},{6,1,9},{2,1,8249},{0,17,1437},{7,1,1553},{7,1,1553},{7,1,1553},{9,1,477},{23,1,2521},{27,1,953},{27,1,953},{20,1,0},{45,1,2521},{20,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},
+{0,1,0},{1,1,0},{0,1,0},{14,0,9266},{14,0,9266},{14,0,9266},{14,0,9266},{40,1,3185},{40,1,3185},{40,1,3185},{6,17,0},{0,17,1412},{0,17,1412},{47,1,65535},{42,1,32389},{10,1,18354},{40,1,11850},{30,1,63370},{40,1,21737},{8,1,5159},{22,1,24},{2,1,39380},{0,17,3675},{5,1,1843},{21,1,1394},{37,1,1241},{23,1,370},{5,1,2646},{9,1,1282},{11,1,757},{8,1,1},{9,1,2646},
+{8,1,1},{45,1,15490},{45,1,15490},{45,1,15490},{47,1,10946},{47,1,12914},{42,1,6221},{42,1,6221},{38,1,10},{2,1,7753},{0,1,1225},{37,1,1241},{37,1,1241},{37,1,1241},{23,1,370},{7,1,1985},{11,1,757},{11,1,757},{8,1,1},{13,1,1985},{8,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{46,0,9248},
+{46,0,9248},{46,0,9248},{46,0,9248},{26,1,3400},{26,1,3400},{26,1,3400},{38,1,10},{0,1,1225},{0,1,1225},{47,1,65535},{28,1,33179},{26,1,18917},{10,1,12588},{47,1,62997},{26,1,21996},{24,1,5521},{8,1,36},{4,1,39403},{0,17,2452},{5,1,1411},{21,1,1058},{21,1,914},{7,1,274},{35,1,2017},{23,1,939},{9,1,585},{26,1,0},{1,35,2017},{26,1,0},{29,1,14809},{29,1,14809},{29,1,14809},
+{31,1,10801},{47,1,12162},{14,1,6117},{14,1,6117},{8,1,50},{20,1,7322},{0,1,1241},{21,1,914},{21,1,914},{21,1,914},{7,1,274},{35,5,1513},{9,1,585},{9,1,585},{26,1,0},{27,1,1513},{26,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{47,0,9250},{47,0,9250},{47,0,9250},{47,0,9250},{12,1,3690},
+{12,1,3690},{12,1,3690},{8,1,50},{0,1,1241},{0,1,1241},{45,1,65535},{14,1,33274},{42,1,19608},{42,1,13375},{47,1,62627},{42,1,22211},{10,1,6045},{24,1,138},{36,1,39015},{0,1,1732},{35,1,1048},{5,1,766},{5,1,666},{37,1,212},{3,3,1473},{7,1,675},{23,1,410},{14,1,1},{3,3,1473},{14,1,1},{13,1,14121},{13,1,14121},{13,1,14121},{45,1,10571},{45,1,11434},{30,1,6081},{30,1,6081},
+{40,1,137},{36,1,6926},{2,1,1445},{5,1,666},{5,1,666},{5,1,666},{37,1,212},{35,3,1105},{23,1,410},{23,1,410},{14,1,1},{25,1,1105},{14,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{15,0,9256},{15,0,9256},{15,0,9256},{15,0,9256},{14,1,3985},{14,1,3985},{14,1,3985},{40,1,137},{2,1,1445},
+{2,1,1445}, \ No newline at end of file
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_astc_0_255.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_astc_0_255.inc
new file mode 100644
index 0000000000..5e7a75396d
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_astc_0_255.inc
@@ -0,0 +1,481 @@
+{0,16,18},{0,12,1},{0,8,0},{0,7,5},{0,10,35},{0,6,21},{0,6,9},{0,4,24},{1,4,36},{0,4,25},{0,16,18},{0,12,1},{0,8,0},{0,7,5},{5,0,35},{0,6,21},{0,6,9},{0,4,24},{10,0,35},{0,4,24},{0,7,0},{0,7,0},{0,7,0},{0,3,0},{0,4,2},{0,3,0},{0,3,0},{0,1,1},{0,2,2},{0,1,1},{0,7,0},
+{0,7,0},{0,7,0},{0,3,0},{2,0,2},{0,3,0},{0,3,0},{0,1,1},{4,0,2},{0,1,1},{8,0,18},{0,12,1},{0,8,0},{0,7,5},{8,0,18},{16,0,18},{0,7,5},{0,5,18},{16,0,18},{0,5,18},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,34,36},{3,23,19},{4,17,25},
+{3,16,19},{0,34,51},{0,20,18},{0,16,1},{0,13,22},{0,15,68},{0,12,33},{6,28,18},{6,21,0},{6,16,1},{5,15,3},{17,0,51},{1,19,18},{2,15,1},{0,13,22},{34,0,51},{0,13,22},{3,25,18},{3,25,18},{3,25,18},{3,14,18},{0,25,8},{0,16,1},{0,16,1},{0,10,0},{0,12,17},{0,9,5},{6,19,0},{6,19,0},{6,19,0},{6,12,0},{12,0,8},
+{4,13,0},{4,13,0},{0,10,0},{25,0,8},{0,10,0},{20,0,18},{6,21,0},{8,16,0},{0,16,0},{20,0,18},{40,0,18},{0,16,0},{0,13,18},{40,0,18},{0,13,18},{3,0,18},{3,0,18},{3,0,18},{3,0,18},{0,19,0},{0,19,0},{0,19,0},{0,9,0},{0,9,4},{0,9,4},{11,42,36},{11,31,19},{12,24,24},{11,24,19},{8,42,51},{8,28,18},{8,24,1},
+{7,20,22},{0,27,52},{2,21,18},{14,36,18},{14,29,0},{14,24,1},{13,23,3},{29,0,51},{9,27,18},{10,23,1},{0,21,18},{58,0,51},{0,21,18},{11,33,18},{11,33,18},{11,33,18},{11,22,18},{8,33,8},{8,24,1},{8,24,1},{8,18,0},{2,23,8},{4,18,1},{14,26,0},{14,26,0},{14,26,0},{14,20,0},{24,0,8},{11,22,0},{11,22,0},{6,18,0},{49,0,8},
+{6,18,0},{32,0,18},{14,29,0},{15,24,0},{6,24,0},{32,0,18},{64,0,18},{6,24,0},{0,21,18},{64,0,18},{0,21,18},{11,0,18},{11,0,18},{11,0,18},{11,0,18},{8,27,0},{8,27,0},{8,27,0},{8,17,0},{4,19,0},{4,19,0},{19,50,36},{19,39,19},{20,32,24},{19,32,19},{16,50,51},{16,36,18},{16,32,1},{15,28,22},{7,37,51},{10,29,18},{22,43,18},
+{22,36,1},{22,32,1},{21,31,3},{41,0,51},{17,35,18},{18,31,1},{8,29,18},{82,0,51},{8,29,18},{19,41,18},{19,41,18},{19,41,18},{19,30,18},{16,41,8},{16,31,1},{16,31,1},{16,26,0},{10,31,8},{12,26,1},{22,34,0},{22,34,0},{22,34,0},{22,28,0},{36,0,8},{18,30,0},{18,30,0},{14,26,0},{73,0,8},{14,26,0},{43,0,18},{20,38,0},{23,32,0},
+{14,32,0},{43,0,18},{89,0,18},{14,32,0},{0,29,18},{89,0,18},{0,29,18},{19,0,18},{19,0,18},{19,0,18},{19,0,18},{16,35,0},{16,35,0},{16,35,0},{16,25,0},{12,27,0},{12,27,0},{28,59,36},{28,48,19},{29,41,24},{28,41,19},{25,59,51},{25,45,18},{25,41,1},{24,37,22},{16,46,51},{19,38,18},{31,52,18},{31,45,1},{31,41,1},{30,40,3},{54,0,51},
+{24,45,18},{27,40,1},{17,38,18},{110,0,51},{17,38,18},{28,49,18},{28,49,18},{28,49,18},{28,39,18},{25,49,8},{25,40,1},{25,40,1},{25,35,0},{19,40,8},{20,35,1},{31,43,0},{31,43,0},{31,43,0},{31,37,0},{49,0,8},{27,39,0},{27,39,0},{23,35,0},{101,0,8},{23,35,0},{57,0,18},{29,47,0},{32,41,0},{23,41,0},{57,0,18},{116,0,18},{23,41,0},
+{0,38,18},{116,0,18},{0,38,18},{28,0,18},{28,0,18},{28,0,18},{28,0,18},{25,43,0},{25,43,0},{25,43,0},{25,34,0},{19,37,0},{19,37,0},{36,66,36},{36,56,19},{37,49,24},{36,49,19},{33,66,51},{33,53,18},{33,49,1},{32,45,22},{23,54,51},{27,46,18},{39,60,18},{39,53,1},{39,49,1},{38,48,3},{66,0,51},{32,53,18},{35,48,1},{25,46,18},{134,0,51},
+{25,46,18},{36,57,18},{36,57,18},{36,57,18},{36,47,18},{33,57,8},{33,48,1},{33,48,1},{33,43,0},{25,49,8},{28,43,1},{39,51,0},{39,51,0},{39,51,0},{39,45,0},{61,0,8},{35,47,0},{35,47,0},{31,43,0},{125,0,8},{31,43,0},{69,0,18},{37,55,0},{40,49,0},{31,49,0},{69,0,18},{140,0,18},{31,49,0},{0,46,18},{140,0,18},{0,46,18},{36,0,18},
+{36,0,18},{36,0,18},{36,0,18},{33,51,0},{33,51,0},{33,51,0},{33,42,0},{27,45,0},{27,45,0},{44,74,36},{44,64,19},{45,57,24},{44,57,19},{41,74,51},{41,61,18},{41,57,1},{40,53,22},{31,62,51},{35,54,18},{47,68,18},{47,61,1},{47,57,1},{46,56,3},{78,0,51},{40,61,18},{43,56,1},{33,54,18},{158,0,51},{33,54,18},{44,65,18},{44,65,18},{44,65,18},
+{44,55,18},{41,65,8},{41,56,1},{41,56,1},{41,51,0},{33,57,8},{36,51,1},{47,59,0},{47,59,0},{47,59,0},{47,53,0},{73,0,8},{43,55,0},{43,55,0},{39,51,0},{149,0,8},{39,51,0},{81,0,18},{45,63,0},{48,57,0},{39,57,0},{81,0,18},{164,0,18},{39,57,0},{0,54,18},{164,0,18},{0,54,18},{44,0,18},{44,0,18},{44,0,18},{44,0,18},{41,59,0},
+{41,59,0},{41,59,0},{41,50,0},{35,53,0},{35,53,0},{52,82,36},{52,71,19},{53,65,24},{52,65,19},{49,82,51},{49,68,18},{49,65,1},{48,61,22},{39,70,51},{43,62,18},{55,76,18},{55,69,1},{55,65,1},{54,64,3},{89,0,51},{49,68,18},{51,64,1},{41,62,18},{183,0,51},{41,62,18},{52,73,18},{52,73,18},{52,73,18},{52,63,18},{49,73,8},{49,64,1},{49,64,1},
+{49,59,0},{42,64,8},{44,59,1},{55,67,0},{55,67,0},{55,67,0},{55,61,0},{85,0,8},{51,63,0},{51,63,0},{47,59,0},{174,0,8},{47,59,0},{92,0,18},{54,70,0},{56,65,0},{47,65,0},{92,0,18},{189,0,18},{47,65,0},{0,62,18},{189,0,18},{0,62,18},{52,0,18},{52,0,18},{52,0,18},{52,0,18},{49,67,0},{49,67,0},{49,67,0},{49,58,0},{43,61,0},
+{43,61,0},{61,91,36},{61,80,19},{62,74,24},{61,73,20},{58,91,51},{58,77,18},{58,73,2},{57,70,22},{48,79,51},{50,71,19},{64,85,18},{64,77,1},{64,74,1},{63,73,3},{103,0,51},{58,77,18},{59,74,1},{49,71,18},{210,0,51},{49,71,18},{61,82,18},{61,82,18},{61,82,18},{61,72,18},{58,82,8},{58,73,1},{58,73,1},{58,68,0},{51,73,8},{53,68,1},{64,76,0},
+{64,76,0},{64,76,0},{64,70,0},{98,0,8},{60,72,0},{60,72,0},{56,68,0},{201,0,8},{56,68,0},{106,0,18},{63,79,0},{65,74,0},{55,74,0},{106,0,18},{216,0,18},{55,74,0},{0,71,18},{216,0,18},{0,71,18},{61,0,18},{61,0,18},{61,0,18},{61,0,18},{58,76,0},{58,76,0},{58,76,0},{58,67,0},{53,69,0},{53,69,0},{69,99,36},{69,88,19},{70,82,24},
+{69,81,20},{66,99,51},{66,85,18},{66,81,2},{65,79,23},{56,87,51},{58,79,19},{72,93,18},{72,85,1},{72,82,1},{72,80,5},{115,0,51},{66,85,18},{67,82,1},{57,79,18},{234,0,51},{57,79,18},{69,90,18},{69,90,18},{69,90,18},{69,79,18},{66,90,8},{66,81,1},{66,81,1},{66,75,1},{59,81,8},{61,76,1},{72,84,0},{72,84,0},{72,84,0},{72,78,0},{110,0,8},
+{69,79,0},{69,79,0},{63,76,0},{225,0,8},{63,76,0},{118,0,18},{71,87,0},{73,82,0},{63,82,0},{118,0,18},{240,0,18},{63,82,0},{0,79,18},{240,0,18},{0,79,18},{69,0,18},{69,0,18},{69,0,18},{69,0,18},{66,84,0},{66,84,0},{66,84,0},{66,75,0},{61,77,0},{61,77,0},{77,107,36},{77,96,19},{78,90,24},{77,89,20},{74,107,51},{74,93,18},{74,89,2},
+{73,87,23},{64,95,51},{66,87,19},{80,101,18},{80,93,1},{80,90,1},{80,88,5},{127,0,51},{74,93,18},{75,90,1},{65,87,18},{254,2,51},{65,87,18},{77,98,18},{77,98,18},{77,98,18},{77,87,18},{74,98,8},{74,89,1},{74,89,1},{74,83,1},{67,89,8},{69,84,1},{80,92,0},{80,92,0},{80,92,0},{80,86,0},{122,0,8},{77,87,0},{77,87,0},{71,84,0},{249,0,8},
+{71,84,0},{129,0,18},{79,95,0},{81,90,0},{71,90,0},{129,0,18},{254,5,18},{71,90,0},{0,87,18},{254,5,18},{0,87,18},{77,0,18},{77,0,18},{77,0,18},{77,0,18},{74,92,0},{74,92,0},{74,92,0},{74,83,0},{69,85,0},{69,85,0},{85,115,36},{85,104,19},{86,98,24},{85,97,20},{82,115,51},{82,101,18},{82,97,2},{81,95,23},{72,103,51},{74,95,19},{88,109,18},
+{88,101,1},{88,98,1},{88,96,5},{138,0,51},{82,101,18},{83,98,1},{73,95,18},{254,14,51},{73,95,18},{85,106,18},{85,106,18},{85,106,18},{85,95,18},{82,106,8},{82,97,1},{82,97,1},{82,91,1},{75,97,8},{77,92,1},{88,100,0},{88,100,0},{88,100,0},{88,94,0},{134,0,8},{85,95,0},{85,95,0},{79,92,0},{255,9,8},{79,92,0},{141,0,18},{87,103,0},{89,98,0},
+{79,98,0},{141,0,18},{254,17,18},{79,98,0},{0,95,18},{254,17,18},{0,95,18},{85,0,18},{85,0,18},{85,0,18},{85,0,18},{82,100,0},{82,100,0},{82,100,0},{82,91,0},{77,93,0},{77,93,0},{94,124,36},{94,113,19},{95,107,24},{94,106,20},{91,124,51},{91,110,18},{91,106,2},{90,104,23},{81,112,51},{83,104,19},{97,118,18},{97,110,1},{97,107,1},{97,105,5},{152,0,51},
+{91,110,18},{92,107,1},{82,104,18},{255,27,51},{82,104,18},{94,115,18},{94,115,18},{94,115,18},{94,104,18},{91,115,8},{91,106,1},{91,106,1},{91,100,1},{84,106,8},{86,101,1},{97,108,0},{97,108,0},{97,108,0},{97,103,0},{147,0,8},{94,104,0},{94,104,0},{88,101,0},{254,23,8},{88,101,0},{155,0,18},{96,112,0},{98,107,0},{88,107,0},{155,0,18},{255,30,18},{88,107,0},
+{0,104,18},{255,30,18},{0,104,18},{94,0,18},{94,0,18},{94,0,18},{94,0,18},{91,109,0},{91,109,0},{91,109,0},{91,100,0},{86,102,0},{86,102,0},{102,132,36},{102,121,19},{102,116,23},{102,114,20},{99,132,51},{99,118,18},{99,114,2},{98,112,23},{89,120,51},{91,112,19},{105,125,18},{105,118,1},{105,115,1},{105,113,5},{164,0,51},{99,118,18},{100,114,1},{90,112,18},{255,39,51},
+{90,112,18},{102,123,18},{102,123,18},{102,123,18},{102,112,18},{99,123,8},{99,114,1},{99,114,1},{99,108,1},{92,114,8},{94,109,1},{105,116,0},{105,116,0},{105,116,0},{105,111,0},{159,0,8},{102,112,0},{102,112,0},{96,109,0},{254,35,8},{96,109,0},{167,0,18},{104,120,0},{106,115,0},{96,115,0},{167,0,18},{254,42,18},{96,115,0},{0,112,18},{254,42,18},{0,112,18},{102,0,18},
+{102,0,18},{102,0,18},{102,0,18},{99,117,0},{99,117,0},{99,117,0},{99,108,0},{94,110,0},{94,110,0},{110,140,36},{110,130,18},{110,124,23},{110,122,20},{107,140,51},{107,126,18},{107,122,2},{106,120,23},{97,128,51},{99,120,19},{113,133,18},{113,126,1},{113,123,1},{113,121,5},{175,0,51},{107,126,18},{108,122,1},{98,120,18},{254,51,51},{98,120,18},{110,130,18},{110,130,18},{110,130,18},
+{110,120,18},{107,131,8},{107,122,1},{107,122,1},{107,116,1},{100,122,8},{102,117,1},{113,124,0},{113,124,0},{113,124,0},{113,119,0},{171,0,8},{110,120,0},{110,120,0},{104,117,0},{255,46,8},{104,117,0},{178,0,18},{112,128,0},{114,123,0},{104,123,0},{178,0,18},{254,54,18},{104,123,0},{0,120,18},{254,54,18},{0,120,18},{110,0,18},{110,0,18},{110,0,18},{110,0,18},{107,124,0},
+{107,124,0},{107,124,0},{107,116,0},{102,118,0},{102,118,0},{118,147,36},{118,138,18},{118,132,23},{118,130,20},{115,148,51},{115,134,18},{115,130,2},{114,128,23},{105,136,51},{108,128,18},{121,141,18},{121,134,1},{121,131,1},{121,129,5},{187,0,51},{115,134,18},{116,130,1},{106,128,18},{254,63,51},{106,128,18},{118,138,18},{118,138,18},{118,138,18},{118,128,18},{115,138,8},{115,130,1},{115,130,1},
+{115,124,1},{108,130,8},{110,125,1},{121,132,0},{121,132,0},{121,132,0},{121,127,0},{183,0,8},{118,128,0},{118,128,0},{112,125,0},{255,58,8},{112,125,0},{190,0,18},{120,136,0},{122,131,0},{112,131,0},{190,0,18},{254,66,18},{112,131,0},{0,128,18},{254,66,18},{0,128,18},{118,0,18},{118,0,18},{118,0,18},{118,0,18},{115,132,0},{115,132,0},{115,132,0},{115,124,0},{110,126,0},
+{110,126,0},{127,156,36},{127,147,18},{127,141,23},{127,139,20},{124,156,51},{124,143,18},{124,139,2},{123,137,23},{114,145,51},{117,137,18},{130,150,18},{130,143,1},{130,140,1},{130,138,5},{201,0,51},{124,143,18},{125,139,1},{115,137,18},{255,76,51},{115,137,18},{127,147,18},{127,147,18},{127,147,18},{127,137,18},{124,147,8},{124,139,1},{124,139,1},{124,133,1},{117,139,8},{119,134,1},{130,141,0},
+{130,141,0},{130,141,0},{130,136,0},{196,0,8},{127,137,0},{127,137,0},{121,134,0},{254,72,8},{121,134,0},{204,0,18},{129,145,0},{131,140,0},{121,140,0},{204,0,18},{255,79,18},{121,140,0},{0,137,18},{255,79,18},{0,137,18},{127,0,18},{127,0,18},{127,0,18},{127,0,18},{124,141,0},{124,141,0},{124,141,0},{124,133,0},{119,135,0},{119,135,0},{135,164,36},{135,154,19},{135,149,23},
+{135,147,20},{132,164,51},{132,151,18},{132,147,2},{131,145,23},{121,153,51},{125,145,18},{138,158,18},{138,151,1},{138,148,1},{138,146,5},{213,0,51},{131,151,18},{133,147,1},{123,145,18},{254,88,51},{123,145,18},{135,155,18},{135,155,18},{135,155,18},{135,145,18},{132,155,8},{132,147,1},{132,147,1},{132,141,1},{125,147,8},{127,142,1},{138,149,0},{138,149,0},{138,149,0},{138,144,0},{208,0,8},
+{135,145,0},{135,145,0},{129,142,0},{254,84,8},{129,142,0},{215,0,18},{137,153,0},{139,148,0},{129,148,0},{215,0,18},{254,91,18},{129,148,0},{0,145,18},{254,91,18},{0,145,18},{135,0,18},{135,0,18},{135,0,18},{135,0,18},{132,149,0},{132,149,0},{132,149,0},{132,141,0},{127,143,0},{127,143,0},{143,172,36},{143,162,19},{143,157,23},{143,155,20},{140,172,51},{140,159,18},{140,155,2},
+{139,153,23},{129,161,51},{132,153,19},{146,166,18},{146,159,1},{146,156,1},{146,154,5},{224,0,51},{139,159,18},{141,155,1},{130,153,18},{254,100,51},{130,153,18},{143,163,18},{143,163,18},{143,163,18},{143,153,18},{140,163,8},{140,155,1},{140,155,1},{140,149,1},{132,155,8},{135,150,1},{146,157,0},{146,157,0},{146,157,0},{146,152,0},{220,0,8},{143,153,0},{143,153,0},{137,150,0},{255,95,8},
+{137,150,0},{227,0,18},{144,161,0},{147,156,0},{136,156,0},{227,0,18},{254,103,18},{136,156,0},{0,153,18},{254,103,18},{0,153,18},{143,0,18},{143,0,18},{143,0,18},{143,0,18},{140,157,0},{140,157,0},{140,157,0},{140,149,0},{135,151,0},{135,151,0},{151,180,36},{151,170,19},{151,165,23},{151,163,20},{148,180,51},{148,167,18},{148,163,2},{148,160,24},{137,169,51},{140,161,19},{154,174,18},
+{154,167,1},{154,164,1},{154,162,5},{236,0,51},{147,167,18},{149,164,1},{138,161,18},{254,112,51},{138,161,18},{151,171,18},{151,171,18},{151,171,18},{151,161,18},{148,171,8},{148,162,1},{148,162,1},{148,157,1},{140,163,8},{143,158,1},{154,165,0},{154,165,0},{154,165,0},{154,160,0},{232,0,8},{150,161,0},{150,161,0},{144,158,0},{255,107,8},{144,158,0},{239,0,18},{152,169,0},{155,164,0},
+{144,164,0},{239,0,18},{254,115,18},{144,164,0},{0,161,18},{254,115,18},{0,161,18},{151,0,18},{151,0,18},{151,0,18},{151,0,18},{148,165,0},{148,165,0},{148,165,0},{148,157,0},{142,159,0},{142,159,0},{160,189,36},{160,179,19},{160,174,23},{160,172,20},{157,189,51},{157,176,18},{157,172,2},{157,169,24},{146,178,51},{149,170,19},{163,183,18},{163,176,1},{163,173,1},{163,172,5},{250,0,51},
+{156,176,18},{158,173,1},{147,170,18},{255,125,51},{147,170,18},{160,180,18},{160,180,18},{160,180,18},{160,170,18},{157,180,8},{157,171,1},{157,171,1},{157,166,1},{149,172,8},{152,167,1},{163,174,0},{163,174,0},{163,174,0},{163,168,0},{245,0,8},{159,170,0},{159,170,0},{153,167,0},{254,121,8},{153,167,0},{253,0,18},{161,178,0},{164,173,0},{153,173,0},{253,0,18},{254,128,18},{153,173,0},
+{0,170,18},{254,128,18},{0,170,18},{160,0,18},{160,0,18},{160,0,18},{160,0,18},{157,174,0},{157,174,0},{157,174,0},{157,165,0},{151,168,0},{151,168,0},{168,197,36},{168,187,19},{168,182,23},{168,180,20},{165,197,51},{165,184,18},{165,180,2},{165,177,24},{154,186,51},{157,178,19},{171,191,18},{171,184,1},{171,181,1},{171,180,5},{255,13,51},{164,184,18},{166,181,1},{155,178,18},{254,137,51},
+{155,178,18},{168,188,18},{168,188,18},{168,188,18},{168,178,18},{165,188,8},{165,179,1},{165,179,1},{165,174,1},{157,180,8},{160,175,1},{171,182,0},{171,182,0},{171,182,0},{171,176,0},{255,4,8},{167,178,0},{167,178,0},{161,175,0},{255,132,8},{161,175,0},{255,19,18},{169,186,0},{172,181,0},{161,181,0},{255,19,18},{254,140,18},{161,181,0},{0,178,18},{254,140,18},{0,178,18},{168,0,18},
+{168,0,18},{168,0,18},{168,0,18},{165,182,0},{165,182,0},{165,182,0},{165,173,0},{159,176,0},{159,176,0},{176,205,36},{176,195,19},{176,190,23},{176,188,20},{173,205,51},{173,192,18},{173,188,2},{173,185,24},{162,194,51},{165,186,19},{179,199,18},{179,192,1},{179,189,1},{179,188,5},{255,37,51},{172,192,18},{174,189,1},{163,186,18},{254,149,51},{163,186,18},{176,196,18},{176,196,18},{176,196,18},
+{176,186,18},{173,196,8},{173,187,1},{173,187,1},{173,182,1},{165,188,8},{168,183,1},{179,190,0},{179,190,0},{179,190,0},{179,184,0},{255,28,8},{175,186,0},{175,186,0},{169,183,0},{255,144,8},{169,183,0},{255,43,18},{177,194,0},{180,189,0},{169,189,0},{255,43,18},{254,152,18},{169,189,0},{0,186,18},{254,152,18},{0,186,18},{176,0,18},{176,0,18},{176,0,18},{176,0,18},{173,190,0},
+{173,190,0},{173,190,0},{173,181,0},{167,184,0},{167,184,0},{184,213,36},{184,203,19},{184,197,22},{184,196,20},{181,213,51},{181,200,18},{181,196,2},{181,193,24},{170,202,51},{173,194,19},{187,207,18},{187,201,1},{187,197,0},{187,196,5},{255,61,51},{180,200,18},{182,197,1},{171,194,18},{254,161,51},{171,194,18},{184,204,18},{184,204,18},{184,204,18},{184,194,18},{181,204,8},{181,195,1},{181,195,1},
+{181,190,1},{173,196,8},{176,191,1},{187,197,0},{187,197,0},{187,197,0},{187,192,0},{255,52,8},{183,194,0},{183,194,0},{177,191,0},{255,156,8},{177,191,0},{255,67,18},{185,202,0},{187,197,0},{177,197,0},{255,67,18},{254,164,18},{177,197,0},{0,194,18},{254,164,18},{0,194,18},{184,0,18},{184,0,18},{184,0,18},{184,0,18},{181,198,0},{181,198,0},{181,198,0},{181,189,0},{175,192,0},
+{175,192,0},{193,222,36},{193,212,18},{193,206,22},{193,205,20},{190,222,51},{189,209,19},{190,206,1},{190,202,24},{179,211,51},{182,203,19},{196,215,18},{196,210,1},{196,206,0},{196,205,5},{255,89,51},{189,209,18},{190,206,1},{180,203,18},{254,174,51},{180,203,18},{193,212,18},{193,212,18},{193,212,18},{193,203,18},{190,213,8},{190,204,1},{190,204,1},{190,199,1},{182,205,8},{185,200,1},{196,206,0},
+{196,206,0},{196,206,0},{196,201,0},{255,79,8},{192,203,0},{192,203,0},{186,200,0},{253,170,8},{186,200,0},{255,95,18},{194,211,0},{196,206,0},{186,206,0},{255,95,18},{254,177,18},{186,206,0},{0,203,18},{254,177,18},{0,203,18},{193,0,18},{193,0,18},{193,0,18},{193,0,18},{190,206,0},{190,206,0},{190,206,0},{190,198,0},{184,201,0},{184,201,0},{201,229,36},{201,220,18},{201,214,22},
+{201,213,20},{198,230,51},{197,217,19},{198,214,1},{198,210,24},{187,219,51},{190,211,19},{204,223,18},{204,218,1},{204,214,0},{204,213,5},{255,113,51},{197,217,18},{198,214,1},{188,211,18},{254,186,51},{188,211,18},{201,220,18},{201,220,18},{201,220,18},{201,211,18},{198,220,8},{198,212,1},{198,212,1},{198,207,1},{190,213,8},{192,208,1},{204,214,0},{204,214,0},{204,214,0},{204,209,0},{255,104,8},
+{200,211,0},{200,211,0},{194,208,0},{255,181,8},{194,208,0},{255,119,18},{202,219,0},{204,214,0},{194,214,0},{255,119,18},{254,189,18},{194,214,0},{0,211,18},{254,189,18},{0,211,18},{201,0,18},{201,0,18},{201,0,18},{201,0,18},{198,214,0},{198,214,0},{198,214,0},{198,206,0},{192,209,0},{192,209,0},{209,237,36},{209,228,18},{209,222,22},{209,221,20},{206,237,51},{205,225,19},{206,222,1},
+{206,218,24},{196,226,51},{197,219,19},{212,231,18},{212,226,1},{212,222,0},{212,221,5},{255,137,51},{205,225,18},{206,222,1},{196,219,18},{254,198,51},{196,219,18},{209,228,18},{209,228,18},{209,228,18},{209,219,18},{206,228,8},{206,220,1},{206,220,1},{206,215,1},{198,221,8},{200,216,1},{212,222,0},{212,222,0},{212,222,0},{212,217,0},{255,128,8},{208,219,0},{208,219,0},{202,216,0},{255,193,8},
+{202,216,0},{255,143,18},{210,227,0},{212,222,0},{202,222,0},{255,143,18},{254,201,18},{202,222,0},{0,219,18},{254,201,18},{0,219,18},{209,0,18},{209,0,18},{209,0,18},{209,0,18},{206,222,0},{206,222,0},{206,222,0},{206,214,0},{200,217,0},{200,217,0},{217,245,36},{217,236,18},{217,230,22},{217,229,20},{214,245,51},{213,233,19},{214,230,1},{214,226,24},{204,234,51},{205,227,19},{220,239,18},
+{220,234,1},{220,230,0},{220,229,5},{255,161,51},{213,233,18},{214,230,1},{204,227,18},{254,210,51},{204,227,18},{217,236,18},{217,236,18},{217,236,18},{217,227,18},{214,236,8},{214,228,1},{214,228,1},{214,223,1},{206,229,8},{208,224,1},{220,230,0},{220,230,0},{220,230,0},{220,225,0},{255,152,8},{216,227,0},{216,227,0},{210,224,0},{255,205,8},{210,224,0},{255,167,18},{218,235,0},{220,230,0},
+{210,230,0},{255,167,18},{253,213,18},{210,230,0},{0,227,18},{253,213,18},{0,227,18},{217,0,18},{217,0,18},{217,0,18},{217,0,18},{214,230,0},{214,230,0},{214,230,0},{214,222,0},{208,225,0},{208,225,0},{226,254,36},{226,245,18},{226,239,22},{226,238,20},{223,254,51},{223,241,18},{223,239,1},{223,235,24},{213,243,51},{214,236,19},{229,248,18},{228,243,1},{229,239,0},{229,238,5},{255,189,51},
+{223,241,18},{223,239,1},{212,236,18},{254,223,51},{212,236,18},{226,245,18},{226,245,18},{226,245,18},{226,236,18},{223,245,8},{223,237,1},{223,237,1},{223,232,1},{216,237,8},{217,233,1},{229,239,0},{229,239,0},{229,239,0},{229,234,0},{255,180,8},{225,236,0},{225,236,0},{219,233,0},{255,218,8},{219,233,0},{255,195,18},{228,243,0},{229,239,0},{218,239,0},{255,195,18},{254,226,18},{218,239,0},
+{0,236,18},{254,226,18},{0,236,18},{226,0,18},{226,0,18},{226,0,18},{226,0,18},{223,239,0},{223,239,0},{223,239,0},{223,231,0},{217,234,0},{217,234,0},{235,254,46},{234,253,18},{234,247,22},{233,246,22},{233,255,56},{231,249,18},{231,247,1},{231,243,24},{221,251,51},{222,244,19},{238,254,19},{237,249,1},{237,247,0},{237,246,5},{255,213,51},{231,249,18},{231,247,1},{220,244,18},{254,235,51},
+{220,244,18},{234,253,18},{234,253,18},{234,253,18},{234,244,18},{231,253,8},{231,245,1},{231,245,1},{231,240,1},{224,245,8},{226,241,0},{237,247,0},{237,247,0},{237,247,0},{237,242,0},{255,204,8},{233,244,0},{233,244,0},{226,241,0},{255,230,8},{226,241,0},{255,219,18},{236,251,0},{237,247,0},{226,247,0},{255,219,18},{254,238,18},{226,247,0},{0,244,18},{254,238,18},{0,244,18},{234,0,18},
+{234,0,18},{234,0,18},{234,0,18},{231,247,0},{231,247,0},{231,247,0},{231,239,0},{226,241,0},{226,241,0},{245,255,72},{243,255,33},{242,255,22},{241,254,22},{242,255,81},{240,255,21},{239,255,1},{238,251,25},{234,255,56},{230,252,19},{248,255,29},{246,255,5},{245,255,0},{244,254,6},{255,237,51},{240,255,20},{239,255,1},{228,252,18},{254,247,51},{228,252,18},{242,255,22},{242,255,22},{242,255,22},
+{242,251,18},{241,254,14},{239,253,1},{239,253,1},{239,249,1},{232,253,8},{234,249,0},{245,255,0},{245,255,0},{245,255,0},{245,250,0},{255,228,8},{242,251,0},{242,251,0},{234,249,0},{255,242,8},{234,249,0},{255,243,18},{246,255,4},{245,255,0},{234,255,0},{255,243,18},{254,250,18},{234,255,0},{0,252,18},{254,250,18},{0,252,18},{242,0,18},{242,0,18},{242,0,18},{242,0,18},{239,255,0},
+{239,255,0},{239,255,0},{239,247,0},{234,249,0},{234,249,0},{251,255,28},{251,255,25},{251,255,24},{250,255,19},{251,255,24},{249,255,10},{248,255,9},{247,255,0},{246,255,12},{243,255,1},{254,255,1},{253,255,1},{253,255,1},{253,255,0},{255,249,3},{252,255,0},{252,255,0},{246,255,0},{254,253,3},{246,255,0},{251,255,24},{251,255,24},{251,255,24},{250,255,19},{250,254,19},{248,255,9},{248,255,9},
+{247,255,0},{246,255,8},{243,255,1},{253,254,1},{253,254,1},{253,254,1},{253,255,0},{255,249,2},{252,255,0},{252,255,0},{246,255,0},{254,253,2},{246,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{250,0,18},{250,0,18},{250,0,18},{250,0,18},{248,255,5},{248,255,5},{248,255,5},{247,255,0},{243,255,1},
+{243,255,1},{0,34,72},{0,24,5},{0,17,0},{0,13,25},{0,22,153},{0,15,90},{0,13,41},{0,10,110},{0,9,162},{0,8,119},{0,34,72},{0,24,5},{0,17,0},{0,13,25},{11,0,153},{0,15,90},{0,13,41},{0,10,110},{22,0,153},{0,10,110},{0,16,0},{0,16,0},{0,16,0},{0,8,0},{0,7,13},{0,6,2},{0,6,2},{0,4,5},{0,3,13},{0,4,6},{0,16,0},
+{0,16,0},{0,16,0},{0,8,0},{3,0,13},{0,6,2},{0,6,2},{0,4,5},{7,0,13},{0,4,5},{17,0,72},{0,24,5},{0,17,0},{0,13,25},{17,0,72},{34,0,72},{0,13,25},{0,11,72},{34,0,72},{0,11,72},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,54,77},{2,37,5},{3,25,18},
+{1,23,13},{0,43,243},{0,27,99},{0,23,24},{0,16,139},{0,18,276},{0,16,164},{3,52,72},{3,36,0},{4,26,6},{2,24,11},{21,0,243},{0,27,99},{0,23,24},{0,16,139},{43,0,243},{0,16,139},{2,36,5},{2,36,5},{2,36,5},{1,19,5},{0,25,50},{0,18,5},{0,18,5},{0,10,18},{0,12,59},{0,10,27},{3,34,0},{3,34,0},{3,34,0},{3,18,0},{12,0,50},
+{0,18,5},{0,18,5},{0,10,18},{25,0,50},{0,10,18},{29,0,72},{3,36,0},{8,25,0},{0,23,8},{29,0,72},{58,0,72},{0,23,8},{0,19,72},{58,0,72},{0,19,72},{1,0,5},{1,0,5},{1,0,5},{1,0,5},{0,10,0},{0,10,0},{0,10,0},{0,5,0},{0,3,1},{0,3,1},{6,70,133},{6,46,65},{7,35,94},{5,33,65},{0,67,243},{0,39,75},{0,32,2},
+{0,25,105},{0,30,332},{0,24,164},{11,60,72},{11,44,0},{12,34,6},{10,32,11},{33,0,243},{0,39,75},{1,32,1},{0,25,105},{67,0,243},{0,25,105},{6,52,61},{6,52,61},{6,52,61},{5,29,61},{0,49,50},{0,32,1},{0,32,1},{0,19,5},{0,21,94},{0,18,35},{11,42,0},{11,42,0},{11,42,0},{11,26,0},{24,0,50},{3,30,0},{3,30,0},{0,19,5},{49,0,50},
+{0,19,5},{41,0,72},{11,44,0},{16,33,0},{0,32,1},{41,0,72},{82,0,72},{0,32,1},{0,27,72},{82,0,72},{0,27,72},{5,0,61},{5,0,61},{5,0,61},{5,0,61},{0,34,0},{0,34,0},{0,34,0},{0,17,0},{0,15,17},{0,15,17},{13,80,144},{13,56,77},{15,43,109},{12,40,76},{7,77,243},{7,49,73},{7,41,1},{5,33,100},{0,42,287},{0,33,98},{19,68,72},
+{19,52,0},{20,42,6},{18,40,11},{45,0,243},{4,50,72},{9,40,1},{0,34,83},{92,0,243},{0,34,83},{13,62,72},{13,62,72},{13,62,72},{13,37,72},{7,59,50},{7,41,1},{7,41,1},{6,28,3},{0,36,66},{0,29,4},{19,50,0},{19,50,0},{19,50,0},{19,34,0},{36,0,50},{11,38,0},{11,38,0},{0,29,0},{73,0,50},{0,29,0},{52,0,72},{18,52,0},{23,41,0},
+{5,41,0},{52,0,72},{107,0,72},{5,41,0},{0,35,72},{107,0,72},{0,35,72},{13,0,72},{13,0,72},{13,0,72},{13,0,72},{7,44,0},{7,44,0},{7,44,0},{7,25,0},{0,27,2},{0,27,2},{22,89,144},{22,65,77},{24,52,109},{21,49,76},{16,86,243},{16,58,73},{16,50,1},{14,42,100},{0,57,248},{3,43,75},{28,77,72},{28,61,0},{29,50,5},{27,49,11},{58,0,243},
+{13,59,72},{18,49,1},{0,44,73},{119,0,243},{0,44,73},{22,71,72},{22,71,72},{22,71,72},{22,46,72},{16,68,50},{16,50,1},{16,50,1},{15,37,3},{0,49,50},{6,38,1},{28,59,0},{28,59,0},{28,59,0},{28,43,0},{49,0,50},{20,47,0},{20,47,0},{8,38,0},{101,0,50},{8,38,0},{66,0,72},{27,61,0},{32,50,0},{13,50,0},{66,0,72},{134,0,72},{13,50,0},
+{0,44,72},{134,0,72},{0,44,72},{22,0,72},{22,0,72},{22,0,72},{22,0,72},{16,53,0},{16,53,0},{16,53,0},{16,34,0},{6,39,0},{6,39,0},{30,97,144},{30,73,77},{32,59,106},{30,56,77},{24,94,243},{24,66,73},{24,58,2},{22,50,100},{2,69,243},{10,51,76},{36,85,72},{36,67,1},{37,58,5},{35,57,11},{70,0,243},{21,67,72},{26,58,1},{3,52,72},{143,0,243},
+{3,52,72},{30,79,72},{30,79,72},{30,79,72},{30,54,72},{24,76,50},{25,56,2},{25,56,2},{23,45,3},{8,57,50},{14,46,1},{36,66,0},{36,66,0},{36,66,0},{36,51,0},{61,0,50},{27,56,0},{27,56,0},{16,46,0},{125,0,50},{16,46,0},{78,0,72},{35,69,0},{40,58,0},{21,58,0},{78,0,72},{158,0,72},{21,58,0},{0,52,72},{158,0,72},{0,52,72},{30,0,72},
+{30,0,72},{30,0,72},{30,0,72},{24,61,0},{24,61,0},{24,61,0},{24,42,0},{14,47,0},{14,47,0},{38,105,144},{38,81,77},{40,67,106},{38,64,77},{32,102,243},{32,74,73},{32,66,2},{30,59,103},{10,77,243},{18,59,76},{44,93,72},{44,75,1},{45,66,5},{44,63,13},{82,0,243},{29,75,72},{33,66,1},{11,60,72},{167,0,243},{11,60,72},{38,87,72},{38,87,72},{38,87,72},
+{38,62,72},{32,84,50},{33,64,2},{33,64,2},{31,53,3},{16,65,50},{22,54,1},{44,74,0},{44,74,0},{44,74,0},{44,59,0},{73,0,50},{35,63,0},{35,63,0},{23,54,0},{149,0,50},{23,54,0},{89,0,72},{43,77,0},{48,66,0},{29,66,0},{89,0,72},{183,0,72},{29,66,0},{0,60,72},{183,0,72},{0,60,72},{38,0,72},{38,0,72},{38,0,72},{38,0,72},{32,69,0},
+{32,69,0},{32,69,0},{32,50,0},{21,55,0},{21,55,0},{46,113,144},{46,88,76},{48,75,106},{46,72,77},{40,110,243},{40,82,73},{40,73,2},{38,67,103},{18,85,243},{26,67,76},{52,100,72},{52,83,1},{53,74,5},{52,72,13},{94,0,243},{37,83,72},{41,74,1},{19,68,72},{192,0,243},{19,68,72},{46,95,72},{46,95,72},{46,95,72},{46,70,72},{40,92,50},{40,73,1},{40,73,1},
+{39,61,3},{24,73,50},{30,62,1},{52,82,0},{52,82,0},{52,82,0},{52,67,0},{85,0,50},{43,71,0},{43,71,0},{31,62,0},{174,0,50},{31,62,0},{101,0,72},{51,85,0},{56,74,0},{37,74,0},{101,0,72},{207,0,72},{37,74,0},{0,68,72},{207,0,72},{0,68,72},{46,0,72},{46,0,72},{46,0,72},{46,0,72},{40,76,0},{40,76,0},{40,76,0},{40,58,0},{29,63,0},
+{29,63,0},{55,122,144},{55,97,76},{57,84,106},{55,81,77},{49,119,243},{48,91,74},{49,82,2},{47,76,103},{27,94,243},{35,76,76},{61,109,72},{61,92,1},{62,83,5},{61,81,13},{107,0,243},{46,92,72},{50,83,1},{28,77,72},{219,0,243},{28,77,72},{55,103,72},{55,103,72},{55,103,72},{55,79,72},{49,101,50},{49,82,1},{49,82,1},{49,69,5},{33,82,50},{38,71,1},{61,91,0},
+{61,91,0},{61,91,0},{61,76,0},{98,0,50},{52,80,0},{52,80,0},{40,71,0},{201,0,50},{40,71,0},{115,0,72},{60,94,0},{65,83,0},{46,83,0},{115,0,72},{234,0,72},{46,83,0},{0,77,72},{234,0,72},{0,77,72},{55,0,72},{55,0,72},{55,0,72},{55,0,72},{49,85,0},{49,85,0},{49,85,0},{49,67,0},{38,72,0},{38,72,0},{63,130,144},{63,105,76},{65,92,106},
+{63,89,77},{57,127,243},{56,99,74},{57,90,2},{55,84,103},{35,102,243},{42,84,76},{69,117,72},{69,100,1},{70,91,5},{69,89,13},{119,0,243},{54,100,72},{58,91,1},{36,85,72},{243,0,243},{36,85,72},{63,111,72},{63,111,72},{63,111,72},{63,87,72},{57,108,50},{57,90,1},{57,90,1},{57,77,5},{41,90,50},{46,79,1},{69,99,0},{69,99,0},{69,99,0},{69,84,0},{110,0,50},
+{60,88,0},{60,88,0},{48,79,0},{225,0,50},{48,79,0},{127,0,72},{68,102,0},{73,91,0},{54,91,0},{127,0,72},{254,2,72},{54,91,0},{0,85,72},{254,2,72},{0,85,72},{63,0,72},{63,0,72},{63,0,72},{63,0,72},{57,93,0},{57,93,0},{57,93,0},{57,75,0},{46,80,0},{46,80,0},{71,137,144},{71,113,76},{73,100,106},{71,97,77},{65,135,243},{64,107,74},{65,98,2},
+{63,92,103},{44,109,243},{50,92,76},{77,125,72},{77,108,1},{78,99,5},{77,97,13},{131,0,243},{62,108,72},{66,99,1},{44,93,72},{255,6,243},{44,93,72},{71,119,72},{71,119,72},{71,119,72},{71,95,72},{65,116,50},{65,98,1},{65,98,1},{65,85,5},{49,98,50},{54,87,1},{77,107,0},{77,107,0},{77,107,0},{77,92,0},{122,0,50},{68,96,0},{68,96,0},{56,87,0},{249,0,50},
+{56,87,0},{138,0,72},{76,110,0},{81,99,0},{62,99,0},{138,0,72},{254,14,72},{62,99,0},{0,93,72},{254,14,72},{0,93,72},{71,0,72},{71,0,72},{71,0,72},{71,0,72},{65,101,0},{65,101,0},{65,101,0},{65,83,0},{54,88,0},{54,88,0},{79,145,144},{79,121,76},{81,108,106},{79,105,77},{73,142,243},{72,115,74},{73,106,2},{71,100,103},{52,117,243},{58,100,76},{85,133,72},
+{85,116,1},{86,107,5},{85,105,13},{143,0,243},{70,116,72},{74,107,1},{52,101,72},{255,18,243},{52,101,72},{79,127,72},{79,127,72},{79,127,72},{79,103,72},{73,124,50},{73,106,1},{73,106,1},{73,93,5},{57,106,50},{62,95,1},{85,115,0},{85,115,0},{85,115,0},{85,100,0},{134,0,50},{76,104,0},{76,104,0},{64,95,0},{255,9,50},{64,95,0},{150,0,72},{84,118,0},{89,107,0},
+{70,107,0},{150,0,72},{254,26,72},{70,107,0},{0,101,72},{254,26,72},{0,101,72},{79,0,72},{79,0,72},{79,0,72},{79,0,72},{73,109,0},{73,109,0},{73,109,0},{73,91,0},{62,96,0},{62,96,0},{88,154,144},{88,130,76},{90,117,106},{88,114,77},{82,151,243},{81,124,74},{82,115,2},{80,109,103},{61,126,243},{67,109,76},{94,142,72},{94,125,1},{95,116,5},{94,114,13},{156,0,243},
+{79,125,72},{83,116,1},{61,110,72},{254,32,243},{61,110,72},{88,136,72},{88,136,72},{88,136,72},{88,112,72},{82,133,50},{82,115,1},{82,115,1},{82,102,5},{66,115,50},{71,104,1},{94,124,0},{94,124,0},{94,124,0},{94,109,0},{147,0,50},{85,113,0},{85,113,0},{73,104,0},{254,23,50},{73,104,0},{164,0,72},{93,127,0},{98,116,0},{79,116,0},{164,0,72},{255,39,72},{79,116,0},
+{0,110,72},{255,39,72},{0,110,72},{88,0,72},{88,0,72},{88,0,72},{88,0,72},{82,118,0},{82,118,0},{82,118,0},{82,100,0},{71,105,0},{71,105,0},{96,162,144},{96,138,76},{98,125,106},{96,122,77},{90,159,243},{90,131,73},{90,123,2},{88,117,103},{69,134,243},{75,117,76},{102,150,72},{102,133,1},{103,124,5},{102,122,13},{168,0,243},{88,132,72},{91,124,1},{69,118,72},{255,43,243},
+{69,118,72},{96,144,72},{96,144,72},{96,144,72},{96,120,72},{90,141,50},{90,123,1},{90,123,1},{90,110,5},{74,123,50},{79,112,1},{102,132,0},{102,132,0},{102,132,0},{102,117,0},{159,0,50},{93,121,0},{93,121,0},{81,112,0},{254,35,50},{81,112,0},{175,0,72},{101,135,0},{106,124,0},{87,124,0},{175,0,72},{254,51,72},{87,124,0},{0,118,72},{254,51,72},{0,118,72},{96,0,72},
+{96,0,72},{96,0,72},{96,0,72},{90,126,0},{90,126,0},{90,126,0},{90,108,0},{79,113,0},{79,113,0},{104,170,144},{104,146,76},{106,133,106},{104,130,77},{98,167,243},{98,139,73},{98,131,2},{96,125,103},{77,142,243},{83,125,76},{110,158,72},{110,142,0},{111,132,5},{110,130,13},{180,0,243},{96,140,72},{99,132,1},{76,126,72},{255,55,243},{76,126,72},{104,152,72},{104,152,72},{104,152,72},
+{104,128,72},{98,149,50},{98,131,1},{98,131,1},{98,118,5},{83,130,50},{87,120,1},{110,140,0},{110,140,0},{110,140,0},{110,125,0},{171,0,50},{101,129,0},{101,129,0},{89,120,0},{255,46,50},{89,120,0},{187,0,72},{110,142,0},{114,132,0},{94,132,0},{187,0,72},{254,63,72},{94,132,0},{0,126,72},{254,63,72},{0,126,72},{104,0,72},{104,0,72},{104,0,72},{104,0,72},{98,134,0},
+{98,134,0},{98,134,0},{98,116,0},{87,121,0},{87,121,0},{112,178,144},{112,154,76},{114,140,105},{112,138,77},{106,175,243},{106,147,73},{106,139,2},{104,133,103},{85,150,243},{91,133,76},{118,166,72},{118,149,1},{119,140,5},{118,138,13},{192,0,243},{104,148,72},{107,140,1},{84,134,72},{255,67,243},{84,134,72},{112,160,72},{112,160,72},{112,160,72},{112,136,72},{106,157,50},{106,139,1},{106,139,1},
+{106,126,5},{91,138,50},{95,128,1},{118,147,0},{118,147,0},{118,147,0},{118,133,0},{183,0,50},{109,137,0},{109,137,0},{97,128,0},{255,58,50},{97,128,0},{199,0,72},{117,151,0},{122,140,0},{102,140,0},{199,0,72},{254,75,72},{102,140,0},{0,134,72},{254,75,72},{0,134,72},{112,0,72},{112,0,72},{112,0,72},{112,0,72},{106,142,0},{106,142,0},{106,142,0},{106,124,0},{95,129,0},
+{95,129,0},{121,187,144},{121,163,76},{122,151,103},{121,148,77},{115,184,243},{115,156,73},{115,148,2},{112,141,105},{94,159,243},{100,142,76},{127,175,72},{127,158,1},{128,149,5},{127,147,13},{205,0,243},{113,157,72},{116,149,1},{93,143,72},{254,81,243},{93,143,72},{121,169,72},{121,169,72},{121,169,72},{121,145,72},{115,166,50},{115,148,1},{115,148,1},{115,135,5},{100,147,50},{104,137,1},{127,156,0},
+{127,156,0},{127,156,0},{127,142,0},{196,0,50},{117,146,0},{117,146,0},{106,137,0},{254,72,50},{106,137,0},{213,0,72},{125,160,0},{131,149,0},{111,149,0},{213,0,72},{254,88,72},{111,149,0},{0,143,72},{254,88,72},{0,143,72},{121,0,72},{121,0,72},{121,0,72},{121,0,72},{115,151,0},{115,151,0},{115,151,0},{115,133,0},{104,138,0},{104,138,0},{129,195,144},{129,170,76},{130,159,103},
+{129,156,77},{123,192,243},{123,164,73},{123,156,2},{122,149,106},{102,167,243},{108,150,76},{135,182,72},{135,166,1},{136,157,5},{134,155,14},{217,0,243},{121,165,72},{124,157,1},{101,151,72},{255,92,243},{101,151,72},{129,177,72},{129,177,72},{129,177,72},{129,152,72},{123,174,50},{123,155,1},{123,155,1},{123,143,5},{108,155,50},{113,145,0},{135,164,0},{135,164,0},{135,164,0},{135,150,0},{208,0,50},
+{125,154,0},{125,154,0},{113,145,0},{254,84,50},{113,145,0},{224,0,72},{133,168,0},{139,157,0},{119,157,0},{224,0,72},{254,100,72},{119,157,0},{0,151,72},{254,100,72},{0,151,72},{129,0,72},{129,0,72},{129,0,72},{129,0,72},{123,158,0},{123,158,0},{123,158,0},{123,141,0},{113,145,0},{113,145,0},{137,203,144},{137,178,76},{138,167,103},{137,164,77},{131,200,243},{130,173,74},{131,164,2},
+{130,157,106},{110,175,243},{116,158,76},{143,190,72},{143,174,1},{144,165,5},{142,163,14},{229,0,243},{129,173,72},{132,165,1},{109,159,72},{255,104,243},{109,159,72},{137,184,72},{137,184,72},{137,184,72},{137,160,72},{131,182,50},{131,163,1},{131,163,1},{131,152,5},{116,163,50},{120,153,1},{143,172,0},{143,172,0},{143,172,0},{143,157,0},{220,0,50},{133,162,0},{133,162,0},{121,153,0},{255,95,50},
+{121,153,0},{236,0,72},{141,176,0},{147,165,0},{127,165,0},{236,0,72},{254,112,72},{127,165,0},{0,159,72},{254,112,72},{0,159,72},{137,0,72},{137,0,72},{137,0,72},{137,0,72},{131,166,0},{131,166,0},{131,166,0},{131,149,0},{120,154,0},{120,154,0},{145,211,144},{145,186,76},{146,175,103},{145,172,77},{139,208,243},{138,181,74},{139,172,2},{138,165,106},{118,183,243},{124,166,76},{151,198,72},
+{151,182,1},{152,173,5},{150,171,14},{241,0,243},{135,182,72},{140,173,1},{117,167,72},{255,116,243},{117,167,72},{145,192,72},{145,192,72},{145,192,72},{145,168,72},{139,189,50},{139,171,1},{139,171,1},{139,160,5},{124,171,50},{128,161,1},{151,180,0},{151,180,0},{151,180,0},{151,165,0},{232,0,50},{141,170,0},{141,170,0},{129,161,0},{255,107,50},{129,161,0},{248,0,72},{149,184,0},{155,173,0},
+{135,173,0},{248,0,72},{254,124,72},{135,173,0},{0,167,72},{254,124,72},{0,167,72},{145,0,72},{145,0,72},{145,0,72},{145,0,72},{139,174,0},{139,174,0},{139,174,0},{139,156,0},{127,162,0},{127,162,0},{154,219,144},{154,195,76},{155,184,103},{154,181,77},{148,217,243},{147,190,74},{148,181,2},{147,174,106},{126,192,243},{133,175,76},{160,207,72},{160,191,1},{161,182,5},{159,180,14},{254,0,243},
+{144,191,72},{149,182,1},{126,176,72},{255,129,243},{126,176,72},{154,201,72},{154,201,72},{154,201,72},{154,177,72},{148,198,50},{148,180,1},{148,180,1},{148,169,5},{132,181,50},{137,170,1},{160,189,0},{160,189,0},{160,189,0},{160,174,0},{245,0,50},{150,179,0},{150,179,0},{138,170,0},{254,121,50},{138,170,0},{255,13,72},{158,193,0},{164,182,0},{144,182,0},{255,13,72},{254,137,72},{144,182,0},
+{0,176,72},{254,137,72},{0,176,72},{154,0,72},{154,0,72},{154,0,72},{154,0,72},{148,183,0},{148,183,0},{148,183,0},{148,165,0},{136,171,0},{136,171,0},{162,227,144},{162,203,76},{163,192,103},{162,189,77},{156,224,243},{155,198,74},{156,189,2},{155,182,106},{134,200,243},{141,183,76},{168,215,72},{168,199,1},{169,190,5},{167,188,14},{255,22,243},{152,199,72},{157,190,1},{134,184,72},{255,141,243},
+{134,184,72},{162,209,72},{162,209,72},{162,209,72},{162,185,72},{156,206,50},{156,188,1},{156,188,1},{156,177,5},{139,189,50},{145,178,1},{168,197,0},{168,197,0},{168,197,0},{168,182,0},{255,4,50},{158,187,0},{158,187,0},{146,178,0},{255,132,50},{146,178,0},{255,37,72},{166,201,0},{172,190,0},{152,190,0},{255,37,72},{254,149,72},{152,190,0},{0,184,72},{254,149,72},{0,184,72},{162,0,72},
+{162,0,72},{162,0,72},{162,0,72},{156,191,0},{156,191,0},{156,191,0},{156,173,0},{144,179,0},{144,179,0},{170,235,144},{170,211,76},{171,200,103},{170,197,77},{164,232,243},{163,206,74},{164,197,2},{163,190,106},{142,208,243},{149,191,76},{176,223,72},{176,207,1},{177,198,5},{175,196,14},{255,46,243},{160,207,72},{165,198,1},{142,192,72},{255,153,243},{142,192,72},{170,217,72},{170,217,72},{170,217,72},
+{170,193,72},{164,214,50},{164,196,1},{164,196,1},{164,185,5},{147,197,50},{153,186,1},{176,205,0},{176,205,0},{176,205,0},{176,190,0},{255,28,50},{166,195,0},{166,195,0},{154,186,0},{255,144,50},{154,186,0},{255,61,72},{174,209,0},{180,198,0},{160,198,0},{255,61,72},{254,161,72},{160,198,0},{0,192,72},{254,161,72},{0,192,72},{170,0,72},{170,0,72},{170,0,72},{170,0,72},{164,199,0},
+{164,199,0},{164,199,0},{164,181,0},{152,187,0},{152,187,0},{178,243,144},{178,219,76},{179,208,103},{178,205,77},{172,240,243},{171,214,74},{172,205,2},{171,198,106},{150,216,243},{157,199,76},{184,231,72},{184,215,1},{185,206,5},{183,204,14},{255,70,243},{169,214,72},{173,206,1},{150,200,72},{255,165,243},{150,200,72},{178,225,72},{178,225,72},{178,225,72},{178,201,72},{172,222,50},{172,204,1},{172,204,1},
+{172,193,5},{155,205,50},{161,194,1},{184,213,0},{184,213,0},{184,213,0},{184,198,0},{255,52,50},{174,203,0},{174,203,0},{162,194,0},{255,156,50},{162,194,0},{255,86,72},{182,217,0},{188,206,0},{168,206,0},{255,86,72},{255,172,72},{168,206,0},{0,200,72},{255,172,72},{0,200,72},{178,0,72},{178,0,72},{178,0,72},{178,0,72},{172,207,0},{172,207,0},{172,207,0},{172,189,0},{160,195,0},
+{160,195,0},{187,252,144},{187,228,76},{188,217,103},{187,214,77},{181,249,243},{180,222,74},{181,214,2},{180,207,106},{159,225,243},{166,208,76},{193,240,72},{193,224,1},{194,216,3},{192,213,14},{255,98,243},{178,223,72},{182,215,1},{158,209,72},{255,178,243},{158,209,72},{187,234,72},{187,234,72},{187,234,72},{187,210,72},{181,231,50},{181,213,1},{181,213,1},{181,202,5},{165,213,50},{170,203,1},{193,222,0},
+{193,222,0},{193,222,0},{193,207,0},{255,79,50},{183,212,0},{183,212,0},{171,203,0},{253,170,50},{171,203,0},{255,113,72},{192,225,0},{196,215,0},{177,215,0},{255,113,72},{254,186,72},{177,215,0},{0,209,72},{254,186,72},{0,209,72},{187,0,72},{187,0,72},{187,0,72},{187,0,72},{181,216,0},{181,216,0},{181,216,0},{181,198,0},{169,204,0},{169,204,0},{196,255,148},{195,236,76},{196,225,103},
+{195,222,77},{189,254,244},{188,230,74},{189,222,2},{188,215,106},{167,233,243},{173,217,77},{201,248,72},{201,231,1},{202,224,3},{200,221,14},{255,122,243},{186,231,72},{189,222,2},{166,217,72},{255,190,243},{166,217,72},{195,242,72},{195,242,72},{195,242,72},{195,218,72},{189,239,50},{189,221,1},{189,221,1},{189,210,5},{173,221,50},{178,211,1},{201,229,0},{201,229,0},{201,229,0},{201,215,0},{255,104,50},
+{191,220,0},{191,220,0},{179,211,0},{255,181,50},{179,211,0},{255,137,72},{200,233,0},{204,223,0},{184,223,0},{255,137,72},{254,198,72},{184,223,0},{0,217,72},{254,198,72},{0,217,72},{195,0,72},{195,0,72},{195,0,72},{195,0,72},{189,224,0},{189,224,0},{189,224,0},{189,206,0},{177,212,0},{177,212,0},{205,255,170},{203,244,76},{204,232,100},{202,230,79},{199,255,255},{196,238,74},{197,231,2},
+{196,223,106},{175,241,243},{181,225,77},{210,254,73},{209,239,1},{210,232,3},{208,229,14},{255,146,243},{194,239,72},{198,230,2},{174,225,72},{255,202,243},{174,225,72},{203,250,72},{203,250,72},{203,250,72},{203,226,72},{197,247,50},{197,229,1},{197,229,1},{197,218,5},{181,229,50},{186,219,1},{209,237,0},{209,237,0},{209,237,0},{209,223,0},{255,128,50},{199,228,0},{199,228,0},{187,219,0},{255,193,50},
+{187,219,0},{255,161,72},{208,241,0},{212,231,0},{192,231,0},{255,161,72},{254,210,72},{192,231,0},{0,225,72},{254,210,72},{0,225,72},{203,0,72},{203,0,72},{203,0,72},{203,0,72},{197,232,0},{197,232,0},{197,232,0},{197,214,0},{185,220,0},{185,220,0},{215,255,208},{212,252,75},{212,240,100},{210,238,79},{211,255,287},{204,246,74},{205,239,1},{203,231,109},{183,249,243},{189,233,77},{218,255,81},
+{217,247,1},{218,240,3},{215,237,17},{255,171,243},{202,247,72},{205,239,1},{182,233,72},{254,214,243},{182,233,72},{211,255,73},{211,255,73},{211,255,73},{211,234,72},{205,255,50},{205,237,1},{205,237,1},{205,226,5},{189,237,50},{194,227,0},{217,245,0},{217,245,0},{217,245,0},{217,231,0},{255,152,50},{208,235,0},{208,235,0},{194,227,0},{255,205,50},{194,227,0},{255,186,72},{216,249,0},{220,239,0},
+{200,239,0},{255,186,72},{255,221,72},{200,239,0},{0,233,72},{255,221,72},{0,233,72},{211,0,72},{211,0,72},{211,0,72},{211,0,72},{205,239,0},{205,239,0},{205,239,0},{205,222,0},{194,227,0},{194,227,0},{224,255,274},{222,255,98},{221,249,100},{219,247,79},{221,255,332},{213,255,74},{214,248,1},{212,240,109},{195,255,245},{198,242,77},{230,255,106},{226,255,4},{227,249,3},{224,246,17},{255,198,243},
+{213,255,73},{214,248,1},{191,242,72},{255,227,243},{191,242,72},{221,255,83},{221,255,83},{221,255,83},{220,243,72},{215,255,59},{214,246,1},{214,246,1},{213,234,6},{198,246,50},{203,236,0},{226,254,0},{226,254,0},{226,254,0},{226,240,0},{255,180,50},{217,244,0},{217,244,0},{203,236,0},{255,218,50},{203,236,0},{255,213,72},{228,255,2},{229,248,0},{209,248,0},{255,213,72},{254,235,72},{209,248,0},
+{0,242,72},{254,235,72},{0,242,72},{220,0,72},{220,0,72},{220,0,72},{220,0,72},{214,248,0},{214,248,0},{214,248,0},{214,231,0},{203,236,0},{203,236,0},{233,255,327},{231,255,164},{230,255,105},{228,253,77},{230,255,370},{225,255,95},{222,254,2},{220,248,94},{213,255,262},{208,249,65},{239,255,126},{237,255,35},{235,255,5},{234,253,13},{255,219,221},{228,255,82},{223,254,1},{201,249,61},{254,238,221},
+{201,249,61},{230,255,105},{230,255,105},{230,255,105},{228,251,72},{227,255,83},{222,254,1},{222,254,1},{221,243,6},{206,254,50},{211,244,0},{235,254,5},{235,254,5},{235,254,5},{234,248,0},{255,204,50},{225,252,0},{225,252,0},{211,244,0},{255,230,50},{211,244,0},{255,234,61},{240,255,17},{238,255,0},{219,255,0},{255,234,61},{255,245,61},{219,255,0},{0,249,61},{255,245,61},{0,249,61},{228,0,72},
+{228,0,72},{228,0,72},{228,0,72},{222,253,1},{222,253,1},{222,253,1},{222,239,0},{211,244,0},{211,244,0},{242,255,233},{239,255,164},{239,255,139},{237,255,78},{239,255,239},{234,255,62},{232,255,24},{230,252,18},{225,255,158},{218,253,5},{248,255,53},{245,255,27},{245,255,18},{242,255,1},{255,237,93},{240,255,26},{237,255,5},{217,253,5},{254,247,93},{217,253,5},{239,255,139},{239,255,139},{239,255,139},
+{237,255,78},{236,255,118},{232,255,24},{232,255,24},{229,251,6},{222,255,67},{219,252,0},{245,255,18},{245,255,18},{245,255,18},{242,254,1},{255,228,50},{237,255,5},{237,255,5},{219,252,0},{255,242,50},{219,252,0},{255,246,5},{251,254,1},{250,255,0},{243,255,0},{255,246,5},{255,251,5},{243,255,0},{0,253,5},{255,251,5},{0,253,5},{236,0,72},{236,0,72},{236,0,72},{236,0,72},{232,254,8},
+{232,254,8},{232,254,8},{230,247,0},{219,252,0},{219,252,0},{248,255,136},{245,255,119},{245,255,110},{244,255,81},{245,255,122},{243,255,52},{241,255,41},{238,255,0},{237,255,75},{231,255,5},{251,255,9},{251,255,6},{251,255,5},{250,255,1},{255,246,17},{249,255,3},{249,255,2},{237,255,0},{255,251,17},{237,255,0},{245,255,110},{245,255,110},{245,255,110},{244,255,81},{245,255,86},{241,255,41},{241,255,41},
+{238,255,0},{234,255,46},{231,255,5},{251,255,5},{251,255,5},{251,255,5},{250,255,1},{255,243,13},{249,255,2},{249,255,2},{237,255,0},{254,250,13},{237,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{244,0,72},{244,0,72},{244,0,72},{244,0,72},{241,254,25},{241,254,25},{241,254,25},{238,255,0},{231,255,5},
+{231,255,5},{0,58,200},{0,42,17},{0,29,0},{0,25,65},{0,40,441},{0,27,266},{0,23,121},{0,16,318},{0,18,467},{0,16,343},{0,58,200},{0,42,17},{0,29,0},{0,25,65},{20,0,441},{0,27,266},{0,23,121},{0,16,318},{40,0,441},{0,16,318},{0,28,0},{0,28,0},{0,28,0},{0,14,0},{0,13,41},{0,12,10},{0,12,10},{0,7,20},{0,6,42},{0,7,24},{0,28,0},
+{0,28,0},{0,28,0},{0,14,0},{6,0,41},{0,12,10},{0,12,10},{0,7,20},{13,0,41},{0,7,20},{29,0,200},{0,42,17},{0,29,0},{0,25,65},{29,0,200},{58,0,200},{0,25,65},{0,19,200},{58,0,200},{0,19,200},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,82,200},{0,54,1},{1,38,19},
+{0,34,34},{0,55,686},{0,36,339},{0,30,139},{0,22,446},{0,24,747},{0,22,495},{0,82,200},{0,54,1},{2,39,17},{0,34,34},{27,0,686},{0,36,339},{0,30,139},{0,22,446},{55,0,686},{0,22,446},{0,52,0},{0,52,0},{0,52,0},{0,26,0},{0,25,145},{0,21,45},{0,21,45},{0,13,80},{0,12,154},{0,10,94},{0,52,0},{0,52,0},{0,52,0},{0,26,0},{12,0,145},
+{0,21,45},{0,21,45},{0,13,80},{25,0,145},{0,13,80},{41,0,200},{0,54,1},{8,37,0},{0,34,34},{41,0,200},{82,0,200},{0,34,34},{0,27,200},{82,0,200},{0,27,200},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,99,225},{4,65,26},{6,46,74},{3,43,45},{0,79,723},{0,48,282},{0,42,54},
+{0,31,401},{0,36,852},{0,29,497},{7,92,200},{7,64,0},{9,46,21},{5,42,29},{39,0,723},{0,48,282},{0,42,54},{0,31,401},{79,0,723},{0,31,401},{4,68,25},{4,68,25},{4,68,25},{3,36,25},{0,49,162},{0,36,17},{0,36,17},{0,22,58},{0,21,206},{0,19,97},{7,62,0},{7,62,0},{7,62,0},{7,34,0},{24,0,162},{0,36,17},{0,36,17},{0,22,58},{49,0,162},
+{0,22,58},{52,0,200},{6,64,0},{16,45,0},{0,44,17},{52,0,200},{107,0,200},{0,44,17},{0,35,200},{107,0,200},{0,35,200},{3,0,25},{3,0,25},{3,0,25},{3,0,25},{0,22,0},{0,22,0},{0,22,0},{0,11,0},{0,9,5},{0,9,5},{8,115,313},{8,78,121},{10,56,198},{7,51,126},{0,104,723},{0,63,227},{0,51,6},{0,40,339},{0,48,956},{0,38,494},{15,100,200},
+{15,72,0},{17,54,21},{15,49,32},{51,0,723},{0,63,227},{0,51,6},{0,40,339},{104,0,723},{0,40,339},{8,84,113},{8,84,113},{8,84,113},{7,46,113},{0,73,162},{0,48,1},{0,48,1},{0,31,29},{0,33,270},{0,27,109},{15,70,0},{15,70,0},{15,70,0},{15,42,0},{36,0,162},{0,48,1},{0,48,1},{0,31,29},{73,0,162},{0,31,29},{64,0,200},{14,72,0},{24,53,0},
+{0,53,4},{64,0,200},{131,0,200},{0,53,4},{0,43,200},{131,0,200},{0,43,200},{7,0,113},{7,0,113},{7,0,113},{7,0,113},{0,46,0},{0,46,0},{0,46,0},{0,23,0},{0,18,34},{0,18,34},{14,130,400},{15,88,215},{17,66,315},{13,60,210},{4,123,723},{3,75,207},{4,62,2},{2,49,303},{0,60,969},{0,48,417},{24,109,200},{24,81,0},{26,63,21},{23,58,33},{64,0,723},
+{0,78,201},{6,62,1},{0,50,289},{131,0,723},{0,50,289},{14,99,200},{14,99,200},{14,99,200},{14,56,200},{4,92,162},{5,60,2},{5,60,2},{3,40,14},{0,45,280},{0,39,77},{24,79,0},{24,79,0},{24,79,0},{24,51,0},{49,0,162},{7,59,0},{7,59,0},{0,40,8},{101,0,162},{0,40,8},{78,0,200},{23,81,0},{32,62,0},{1,62,0},{78,0,200},{158,0,200},{1,62,0},
+{0,52,200},{158,0,200},{0,52,200},{14,0,200},{14,0,200},{14,0,200},{14,0,200},{4,65,0},{4,65,0},{4,65,0},{4,34,0},{0,33,40},{0,33,40},{22,138,400},{23,96,215},{25,74,315},{21,68,210},{12,131,723},{11,83,207},{12,70,2},{10,57,303},{0,72,865},{0,57,290},{32,117,200},{32,89,0},{34,71,21},{31,66,33},{76,0,723},{5,87,200},{14,70,1},{0,59,251},{155,0,723},
+{0,59,251},{22,107,200},{22,107,200},{22,107,200},{22,64,200},{12,100,162},{13,68,2},{13,68,2},{10,47,17},{0,60,213},{0,48,13},{32,87,0},{32,87,0},{32,87,0},{32,59,0},{61,0,162},{15,67,0},{15,67,0},{0,50,1},{125,0,162},{0,50,1},{89,0,200},{31,89,0},{40,70,0},{9,70,0},{89,0,200},{183,0,200},{9,70,0},{0,60,200},{183,0,200},{0,60,200},{22,0,200},
+{22,0,200},{22,0,200},{22,0,200},{12,73,0},{12,73,0},{12,73,0},{12,42,0},{0,45,8},{0,45,8},{30,145,400},{31,104,215},{33,82,315},{29,76,210},{20,139,723},{19,91,207},{20,78,2},{18,65,303},{0,88,787},{0,66,225},{40,125,200},{40,97,0},{43,79,19},{39,74,33},{88,0,723},{14,94,200},{22,78,1},{0,66,224},{180,0,723},{0,66,224},{30,115,200},{30,115,200},{30,115,200},
+{30,72,200},{20,108,162},{21,76,2},{21,76,2},{18,56,17},{0,72,173},{2,58,1},{40,95,0},{40,95,0},{40,95,0},{40,67,0},{73,0,162},{23,75,0},{23,75,0},{3,58,0},{149,0,162},{3,58,0},{101,0,200},{39,97,0},{48,78,0},{17,78,0},{101,0,200},{207,0,200},{17,78,0},{0,68,200},{207,0,200},{0,68,200},{30,0,200},{30,0,200},{30,0,200},{30,0,200},{20,81,0},
+{20,81,0},{20,81,0},{20,50,0},{1,59,0},{1,59,0},{38,153,400},{39,112,215},{41,90,315},{37,84,210},{28,147,723},{27,99,207},{28,86,2},{26,73,303},{0,100,739},{4,75,212},{48,133,200},{48,105,0},{51,87,19},{47,82,33},{100,0,723},{22,102,200},{30,86,1},{0,75,206},{204,0,723},{0,75,206},{38,123,200},{38,123,200},{38,123,200},{38,80,200},{28,116,162},{29,84,2},{29,84,2},
+{26,64,17},{0,85,162},{10,66,1},{48,103,0},{48,103,0},{48,103,0},{48,75,0},{85,0,162},{31,83,0},{31,83,0},{11,66,0},{174,0,162},{11,66,0},{113,0,200},{47,105,0},{56,86,0},{25,86,0},{113,0,200},{231,0,200},{25,86,0},{0,76,200},{231,0,200},{0,76,200},{38,0,200},{38,0,200},{38,0,200},{38,0,200},{28,89,0},{28,89,0},{28,89,0},{28,58,0},{9,67,0},
+{9,67,0},{47,162,400},{48,121,215},{50,98,308},{46,93,210},{37,155,723},{36,107,207},{37,95,2},{35,82,303},{0,113,723},{13,84,212},{57,142,200},{57,112,1},{60,96,19},{56,91,33},{113,0,723},{31,111,200},{39,95,1},{0,85,200},{231,0,723},{0,85,200},{47,132,200},{47,132,200},{47,132,200},{47,89,200},{37,125,162},{38,93,2},{38,93,2},{35,73,17},{10,93,162},{19,75,1},{57,111,0},
+{57,111,0},{57,111,0},{57,84,0},{98,0,162},{40,92,0},{40,92,0},{20,75,0},{201,0,162},{20,75,0},{127,0,200},{56,114,0},{65,95,0},{34,95,0},{127,0,200},{254,2,200},{34,95,0},{0,85,200},{254,2,200},{0,85,200},{47,0,200},{47,0,200},{47,0,200},{47,0,200},{37,98,0},{37,98,0},{37,98,0},{37,67,0},{18,76,0},{18,76,0},{55,170,400},{56,129,215},{58,106,308},
+{54,101,210},{45,163,723},{44,115,207},{45,103,2},{43,90,303},{8,121,723},{21,92,212},{65,150,200},{65,121,0},{68,104,19},{64,99,33},{125,0,723},{39,119,200},{47,103,1},{7,93,200},{255,0,723},{7,93,200},{55,140,200},{55,140,200},{55,140,200},{55,97,200},{45,133,162},{46,101,2},{46,101,2},{43,81,17},{18,101,162},{27,83,1},{65,119,0},{65,119,0},{65,119,0},{65,92,0},{110,0,162},
+{48,100,0},{48,100,0},{28,83,0},{225,0,162},{28,83,0},{138,0,200},{65,121,0},{73,103,0},{42,103,0},{138,0,200},{254,14,200},{42,103,0},{0,93,200},{254,14,200},{0,93,200},{55,0,200},{55,0,200},{55,0,200},{55,0,200},{45,106,0},{45,106,0},{45,106,0},{45,75,0},{26,84,0},{26,84,0},{63,178,400},{64,137,215},{66,114,308},{62,109,210},{53,171,723},{52,123,207},{53,111,2},
+{51,98,303},{16,129,723},{27,100,215},{73,158,200},{73,129,0},{76,112,19},{72,107,33},{137,0,723},{47,127,200},{55,111,1},{15,101,200},{255,12,723},{15,101,200},{63,148,200},{63,148,200},{63,148,200},{63,105,200},{53,141,162},{54,109,2},{54,109,2},{51,89,17},{26,109,162},{35,91,1},{73,127,0},{73,127,0},{73,127,0},{73,100,0},{122,0,162},{56,108,0},{56,108,0},{36,91,0},{249,0,162},
+{36,91,0},{150,0,200},{73,129,0},{81,111,0},{49,111,0},{150,0,200},{254,26,200},{49,111,0},{0,101,200},{254,26,200},{0,101,200},{63,0,200},{63,0,200},{63,0,200},{63,0,200},{53,114,0},{53,114,0},{53,114,0},{53,83,0},{34,92,0},{34,92,0},{71,186,400},{72,144,212},{74,122,308},{70,117,210},{61,179,723},{60,131,207},{61,118,2},{59,106,303},{24,137,723},{35,108,215},{81,166,200},
+{81,137,0},{84,120,19},{80,115,33},{149,0,723},{55,135,200},{62,119,1},{23,109,200},{255,24,723},{23,109,200},{71,156,200},{71,156,200},{71,156,200},{71,113,200},{61,149,162},{61,118,1},{61,118,1},{59,97,17},{34,117,162},{43,99,1},{81,135,0},{81,135,0},{81,135,0},{81,108,0},{134,0,162},{64,116,0},{64,116,0},{44,99,0},{255,9,162},{44,99,0},{162,0,200},{81,137,0},{89,119,0},
+{57,119,0},{162,0,200},{254,38,200},{57,119,0},{0,109,200},{254,38,200},{0,109,200},{71,0,200},{71,0,200},{71,0,200},{71,0,200},{61,121,0},{61,121,0},{61,121,0},{61,91,0},{42,100,0},{42,100,0},{80,195,400},{81,153,212},{83,131,308},{79,127,212},{70,188,723},{69,140,207},{70,127,2},{68,115,303},{34,145,723},{44,117,215},{90,174,200},{90,146,0},{93,129,19},{89,124,33},{162,0,723},
+{64,144,200},{71,128,1},{32,118,200},{254,38,723},{32,118,200},{80,165,200},{80,165,200},{80,165,200},{80,122,200},{70,158,162},{70,127,1},{70,127,1},{68,106,17},{43,126,162},{52,108,1},{90,144,0},{90,144,0},{90,144,0},{90,117,0},{147,0,162},{74,124,0},{74,124,0},{53,108,0},{254,23,162},{53,108,0},{175,0,200},{90,146,0},{98,128,0},{66,128,0},{175,0,200},{254,51,200},{66,128,0},
+{0,118,200},{254,51,200},{0,118,200},{80,0,200},{80,0,200},{80,0,200},{80,0,200},{70,130,0},{70,130,0},{70,130,0},{70,100,0},{51,109,0},{51,109,0},{88,203,400},{89,161,212},{91,139,308},{87,135,212},{78,196,723},{77,148,207},{78,135,2},{75,122,305},{42,153,723},{52,125,215},{98,182,200},{98,154,0},{101,137,19},{97,132,33},{174,0,723},{72,152,200},{79,136,1},{40,126,200},{255,49,723},
+{40,126,200},{88,172,200},{88,172,200},{88,172,200},{88,129,200},{78,166,162},{78,135,1},{78,135,1},{76,114,17},{51,134,162},{60,116,0},{98,152,0},{98,152,0},{98,152,0},{98,125,0},{159,0,162},{82,132,0},{82,132,0},{60,116,0},{254,35,162},{60,116,0},{187,0,200},{98,154,0},{106,136,0},{74,136,0},{187,0,200},{254,63,200},{74,136,0},{0,126,200},{254,63,200},{0,126,200},{88,0,200},
+{88,0,200},{88,0,200},{88,0,200},{78,138,0},{78,138,0},{78,138,0},{78,108,0},{60,116,0},{60,116,0},{96,211,400},{97,169,212},{99,147,308},{95,143,212},{86,204,723},{85,156,207},{86,143,2},{83,131,308},{50,161,723},{60,133,215},{106,190,200},{106,162,0},{109,145,19},{105,141,35},{186,0,723},{80,160,200},{87,144,1},{48,134,200},{255,61,723},{48,134,200},{96,180,200},{96,180,200},{96,180,200},
+{96,137,200},{86,174,162},{86,143,1},{86,143,1},{84,122,17},{59,142,162},{68,124,0},{106,160,0},{106,160,0},{106,160,0},{106,133,0},{171,0,162},{90,140,0},{90,140,0},{68,124,0},{255,46,162},{68,124,0},{199,0,200},{106,162,0},{114,144,0},{82,144,0},{199,0,200},{254,75,200},{82,144,0},{0,134,200},{254,75,200},{0,134,200},{96,0,200},{96,0,200},{96,0,200},{96,0,200},{86,146,0},
+{86,146,0},{86,146,0},{86,116,0},{68,124,0},{68,124,0},{104,219,400},{105,177,212},{107,155,308},{103,151,212},{94,212,723},{93,164,207},{94,151,2},{91,139,308},{58,169,723},{68,141,215},{114,198,200},{114,170,0},{117,153,19},{113,149,35},{198,0,723},{88,168,200},{95,152,1},{56,142,200},{255,73,723},{56,142,200},{104,188,200},{104,188,200},{104,188,200},{104,145,200},{94,181,162},{94,151,1},{94,151,1},
+{92,130,17},{67,150,162},{76,132,0},{114,168,0},{114,168,0},{114,168,0},{114,141,0},{183,0,162},{98,148,0},{98,148,0},{76,132,0},{255,58,162},{76,132,0},{211,0,200},{114,170,0},{122,152,0},{90,152,0},{211,0,200},{255,86,200},{90,152,0},{0,142,200},{255,86,200},{0,142,200},{104,0,200},{104,0,200},{104,0,200},{104,0,200},{94,154,0},{94,154,0},{94,154,0},{94,124,0},{76,132,0},
+{76,132,0},{113,228,400},{114,186,215},{116,164,308},{112,160,212},{103,221,723},{102,173,207},{103,160,2},{100,148,308},{67,178,723},{78,150,212},{123,207,200},{123,179,0},{125,163,17},{122,158,35},{211,0,723},{96,177,200},{104,161,1},{65,151,200},{255,86,723},{65,151,200},{113,197,200},{113,197,200},{113,197,200},{113,154,200},{103,190,162},{103,160,1},{103,160,1},{102,138,19},{76,159,162},{85,141,0},{123,177,0},
+{123,177,0},{123,177,0},{123,149,0},{196,0,162},{107,157,0},{107,157,0},{85,141,0},{254,72,162},{85,141,0},{224,0,200},{123,179,0},{131,161,0},{99,161,0},{224,0,200},{254,100,200},{99,161,0},{0,151,200},{254,100,200},{0,151,200},{113,0,200},{113,0,200},{113,0,200},{113,0,200},{103,163,0},{103,163,0},{103,163,0},{103,133,0},{85,141,0},{85,141,0},{121,235,400},{122,194,215},{124,172,308},
+{120,168,212},{111,229,723},{110,181,207},{111,168,2},{108,156,308},{75,186,723},{86,158,212},{131,215,200},{131,187,0},{133,171,17},{130,166,35},{223,0,723},{104,185,200},{112,169,1},{73,159,200},{255,98,723},{73,159,200},{121,205,200},{121,205,200},{121,205,200},{121,162,200},{111,198,162},{111,168,1},{111,168,1},{110,146,19},{84,167,162},{93,149,0},{131,185,0},{131,185,0},{131,185,0},{131,157,0},{208,0,162},
+{115,165,0},{115,165,0},{93,149,0},{254,84,162},{93,149,0},{236,0,200},{131,187,0},{139,169,0},{107,169,0},{236,0,200},{254,112,200},{107,169,0},{0,159,200},{254,112,200},{0,159,200},{121,0,200},{121,0,200},{121,0,200},{121,0,200},{111,171,0},{111,171,0},{111,171,0},{111,141,0},{93,149,0},{93,149,0},{129,243,400},{130,202,215},{133,180,305},{128,176,212},{119,236,723},{118,189,207},{119,176,2},
+{116,164,308},{83,194,723},{94,166,212},{139,223,200},{139,195,0},{141,179,17},{138,174,35},{235,0,723},{112,193,200},{120,177,1},{81,167,200},{255,110,723},{81,167,200},{129,213,200},{129,213,200},{129,213,200},{129,170,200},{119,206,162},{119,176,1},{119,176,1},{118,154,19},{91,175,162},{101,157,0},{139,192,0},{139,192,0},{139,192,0},{139,165,0},{220,0,162},{123,173,0},{123,173,0},{101,157,0},{255,95,162},
+{101,157,0},{248,0,200},{139,195,0},{147,177,0},{115,177,0},{248,0,200},{254,124,200},{115,177,0},{0,167,200},{254,124,200},{0,167,200},{129,0,200},{129,0,200},{129,0,200},{129,0,200},{119,179,0},{119,179,0},{119,179,0},{119,148,0},{101,157,0},{101,157,0},{137,251,400},{138,210,215},{140,187,303},{136,184,212},{127,244,723},{126,197,207},{127,184,2},{124,172,308},{91,202,723},{102,174,212},{147,231,200},
+{147,202,1},{149,187,17},{146,182,35},{247,0,723},{120,201,200},{128,185,1},{88,175,200},{255,122,723},{88,175,200},{137,221,200},{137,221,200},{137,221,200},{137,178,200},{127,214,162},{127,184,1},{127,184,1},{126,162,19},{99,183,162},{109,165,0},{147,200,0},{147,200,0},{147,200,0},{147,173,0},{232,0,162},{131,181,0},{131,181,0},{109,165,0},{255,107,162},{109,165,0},{255,10,200},{146,203,0},{155,185,0},
+{123,185,0},{255,10,200},{255,135,200},{123,185,0},{0,175,200},{255,135,200},{0,175,200},{137,0,200},{137,0,200},{137,0,200},{137,0,200},{127,187,0},{127,187,0},{127,187,0},{127,156,0},{109,165,0},{109,165,0},{147,255,404},{147,219,215},{149,196,303},{145,193,212},{136,253,723},{135,206,207},{136,193,2},{133,181,308},{100,211,723},{111,183,212},{156,240,200},{156,210,1},{158,196,17},{155,191,35},{255,10,723},
+{129,210,200},{137,194,1},{97,184,200},{255,135,723},{97,184,200},{146,230,200},{146,230,200},{146,230,200},{146,187,200},{136,223,162},{136,193,1},{136,193,1},{135,171,19},{108,192,162},{118,174,0},{156,209,0},{156,209,0},{156,209,0},{156,182,0},{245,0,162},{139,191,0},{139,191,0},{118,174,0},{254,121,162},{118,174,0},{255,37,200},{155,212,0},{164,194,0},{131,194,0},{255,37,200},{254,149,200},{131,194,0},
+{0,184,200},{254,149,200},{0,184,200},{146,0,200},{146,0,200},{146,0,200},{146,0,200},{136,196,0},{136,196,0},{136,196,0},{136,165,0},{118,174,0},{118,174,0},{156,255,426},{155,227,215},{157,204,303},{153,201,212},{146,254,728},{143,214,207},{144,202,2},{141,189,308},{108,219,723},{118,191,215},{164,248,200},{164,218,1},{166,204,17},{163,199,35},{255,34,723},{137,218,200},{145,201,2},{105,192,200},{255,147,723},
+{105,192,200},{154,238,200},{154,238,200},{154,238,200},{154,195,200},{144,231,162},{144,200,1},{144,200,1},{143,179,19},{116,200,162},{126,182,0},{164,217,0},{164,217,0},{164,217,0},{164,190,0},{255,4,162},{146,199,0},{146,199,0},{126,182,0},{255,132,162},{126,182,0},{255,61,200},{163,220,0},{172,202,0},{139,202,0},{255,61,200},{254,161,200},{139,202,0},{0,192,200},{254,161,200},{0,192,200},{154,0,200},
+{154,0,200},{154,0,200},{154,0,200},{144,204,0},{144,204,0},{144,204,0},{144,173,0},{126,182,0},{126,182,0},{165,255,468},{163,234,212},{165,212,303},{162,207,213},{156,255,747},{151,222,207},{152,210,2},{149,197,308},{115,228,723},{126,199,215},{172,255,200},{172,226,1},{174,212,17},{171,207,35},{255,58,723},{145,226,200},{153,209,2},{113,200,200},{255,159,723},{113,200,200},{162,246,200},{162,246,200},{162,246,200},
+{162,203,200},{152,239,162},{152,208,1},{152,208,1},{151,187,19},{124,208,162},{134,190,0},{172,225,0},{172,225,0},{172,225,0},{172,198,0},{255,28,162},{155,206,0},{155,206,0},{134,190,0},{255,144,162},{134,190,0},{255,86,200},{171,228,0},{180,210,0},{147,210,0},{255,86,200},{255,172,200},{147,210,0},{0,200,200},{255,172,200},{0,200,200},{162,0,200},{162,0,200},{162,0,200},{162,0,200},{152,211,0},
+{152,211,0},{152,211,0},{152,181,0},{134,190,0},{134,190,0},{175,255,522},{171,242,212},{173,220,303},{170,216,213},{165,255,788},{158,232,208},{160,218,2},{157,205,308},{123,235,723},{134,207,215},{181,255,209},{180,234,1},{182,220,17},{179,215,35},{255,82,723},{153,234,200},{161,217,2},{121,208,200},{254,171,723},{121,208,200},{170,253,200},{170,253,200},{170,253,200},{170,211,200},{160,247,162},{160,216,1},{160,216,1},
+{159,195,19},{132,216,162},{141,198,1},{180,233,0},{180,233,0},{180,233,0},{180,206,0},{255,52,162},{163,214,0},{163,214,0},{142,198,0},{255,156,162},{142,198,0},{255,110,200},{179,236,0},{188,218,0},{155,218,0},{255,110,200},{255,184,200},{155,218,0},{0,208,200},{255,184,200},{0,208,200},{170,0,200},{170,0,200},{170,0,200},{170,0,200},{160,219,0},{160,219,0},{160,219,0},{160,189,0},{141,199,0},
+{141,199,0},{184,255,612},{180,251,212},{182,229,303},{179,225,213},{178,255,844},{167,239,210},{169,227,2},{165,214,315},{132,244,723},{143,216,215},{193,255,234},{189,243,1},{191,229,17},{187,224,38},{255,110,723},{162,243,200},{170,226,2},{130,217,200},{255,184,723},{130,217,200},{180,254,206},{180,254,206},{180,254,206},{179,220,200},{170,253,163},{169,225,1},{169,225,1},{168,204,19},{141,225,162},{150,207,0},{189,242,0},
+{189,242,0},{189,242,0},{189,215,0},{255,79,162},{172,223,0},{172,223,0},{150,207,0},{253,170,162},{150,207,0},{255,137,200},{188,245,0},{197,227,0},{164,227,0},{255,137,200},{254,198,200},{164,227,0},{0,217,200},{254,198,200},{0,217,200},{179,0,200},{179,0,200},{179,0,200},{179,0,200},{169,228,0},{169,228,0},{169,228,0},{169,198,0},{150,207,0},{150,207,0},{193,255,714},{189,255,225},{190,237,303},
+{187,233,213},{187,255,919},{175,247,210},{177,235,2},{173,222,315},{140,252,723},{151,224,215},{202,255,275},{197,251,1},{199,237,17},{195,232,38},{255,134,723},{170,251,200},{178,234,2},{138,225,200},{255,196,723},{138,225,200},{189,254,224},{189,254,224},{189,254,224},{187,228,200},{178,255,171},{177,233,1},{177,233,1},{176,212,19},{149,233,162},{158,215,0},{197,250,0},{197,250,0},{197,250,0},{197,223,0},{255,104,162},
+{180,231,0},{180,231,0},{158,215,0},{255,181,162},{158,215,0},{255,161,200},{196,253,0},{204,235,0},{172,235,0},{255,161,200},{254,210,200},{172,235,0},{0,225,200},{254,210,200},{0,225,200},{187,0,200},{187,0,200},{187,0,200},{187,0,200},{177,236,0},{177,236,0},{177,236,0},{177,206,0},{158,215,0},{158,215,0},{202,255,836},{198,255,290},{198,245,303},{195,241,213},{199,255,1015},{183,255,210},{185,243,2},
+{181,230,315},{152,255,732},{159,232,215},{214,254,331},{207,255,13},{207,245,17},{203,240,38},{255,158,723},{183,255,206},{186,242,2},{146,233,200},{255,208,723},{146,233,200},{196,255,251},{196,255,251},{196,255,251},{195,236,200},{190,255,195},{185,241,1},{185,241,1},{184,221,21},{157,241,162},{166,223,0},{205,255,1},{205,255,1},{205,255,1},{205,231,0},{255,128,162},{188,239,0},{188,239,0},{166,223,0},{255,193,162},
+{166,223,0},{255,186,200},{210,255,8},{212,243,0},{180,243,0},{255,186,200},{255,221,200},{180,243,0},{0,233,200},{255,221,200},{0,233,200},{195,0,200},{195,0,200},{195,0,200},{195,0,200},{185,244,0},{185,244,0},{185,244,0},{185,214,0},{166,223,0},{166,223,0},{215,255,976},{207,255,417},{206,253,303},{203,249,213},{208,255,1124},{195,255,258},{193,251,2},{189,238,315},{167,255,797},{166,240,215},{221,255,392},
+{216,255,77},{215,252,14},{211,248,38},{255,183,723},{198,255,248},{194,250,2},{154,241,200},{254,220,723},{154,241,200},{205,255,289},{205,255,289},{205,255,289},{203,244,200},{199,255,230},{193,249,1},{193,249,1},{192,229,21},{165,249,162},{174,231,0},{215,255,8},{215,255,8},{215,255,8},{213,239,0},{255,152,162},{196,247,0},{196,247,0},{174,231,0},{255,205,162},{174,231,0},{255,210,200},{222,255,40},{220,251,0},
+{188,251,0},{255,210,200},{255,233,200},{188,251,0},{0,241,200},{255,233,200},{0,241,200},{203,0,200},{203,0,200},{203,0,200},{203,0,200},{193,252,0},{193,252,0},{193,252,0},{193,222,0},{174,231,0},{174,231,0},{221,255,895},{217,255,494},{215,255,339},{212,255,201},{218,255,994},{207,255,251},{204,255,6},{199,245,198},{189,255,702},{176,247,121},{233,255,318},{228,255,109},{224,255,29},{222,253,13},{255,204,546},
+{213,255,198},{205,255,1},{169,247,113},{255,230,546},{169,247,113},{215,255,339},{215,255,339},{215,255,339},{212,253,200},{211,255,293},{204,255,6},{204,255,6},{201,238,21},{177,255,165},{183,240,0},{224,255,29},{224,255,29},{224,255,29},{222,248,0},{255,180,162},{206,254,1},{206,254,1},{183,240,0},{255,218,162},{183,240,0},{255,228,113},{237,255,34},{232,255,0},{207,255,0},{255,228,113},{255,242,113},{207,255,0},
+{0,247,113},{255,242,113},{0,247,113},{212,0,200},{212,0,200},{212,0,200},{212,0,200},{202,255,4},{202,255,4},{202,255,4},{202,231,0},{183,240,0},{183,240,0},{230,255,737},{226,255,497},{224,255,401},{220,255,216},{227,255,783},{216,255,206},{213,255,54},{209,249,74},{201,255,534},{189,251,26},{239,255,190},{235,255,97},{233,255,58},{230,255,1},{255,219,333},{225,255,110},{219,255,17},{185,251,25},{254,238,333},
+{185,251,25},{224,255,401},{224,255,401},{224,255,401},{220,255,216},{218,255,354},{213,255,54},{213,255,54},{209,246,21},{192,255,203},{191,248,0},{233,255,58},{233,255,58},{233,255,58},{230,254,1},{255,204,162},{219,255,17},{219,255,17},{191,248,0},{255,230,162},{191,248,0},{255,240,25},{246,255,5},{244,255,0},{231,255,0},{255,240,25},{255,248,25},{231,255,0},{0,251,25},{255,248,25},{0,251,25},{220,0,200},
+{220,0,200},{220,0,200},{220,0,200},{211,255,17},{211,255,17},{211,255,17},{210,239,0},{191,248,0},{191,248,0},{236,255,616},{233,255,495},{233,255,446},{228,255,264},{233,255,626},{225,255,220},{225,255,139},{217,254,19},{216,255,434},{199,255,1},{245,255,121},{244,255,94},{242,255,80},{240,255,20},{255,234,193},{237,255,75},{234,255,45},{201,255,0},{255,245,193},{201,255,0},{233,255,446},{233,255,446},{233,255,446},
+{228,255,264},{230,255,401},{225,255,139},{225,255,139},{216,253,17},{207,255,254},{199,255,1},{242,255,80},{242,255,80},{242,255,80},{240,255,20},{255,225,145},{234,255,45},{234,255,45},{201,255,0},{254,241,145},{201,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{228,0,200},{228,0,200},{228,0,200},{228,0,200},{221,255,34},
+{221,255,34},{221,255,34},{218,247,0},{200,254,1},{200,254,1},{242,255,400},{239,255,343},{239,255,318},{237,255,227},{239,255,370},{234,255,161},{232,255,121},{226,255,0},{225,255,243},{213,255,17},{251,255,33},{248,255,24},{248,255,20},{246,255,4},{255,243,54},{246,255,17},{243,255,10},{225,255,0},{254,250,54},{225,255,0},{239,255,318},{239,255,318},{239,255,318},{237,255,227},{236,255,253},{232,255,121},{232,255,121},
+{226,255,0},{219,255,150},{213,255,17},{248,255,20},{248,255,20},{248,255,20},{246,255,4},{255,237,41},{243,255,10},{243,255,10},{225,255,0},{254,247,41},{225,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{236,0,200},{236,0,200},{236,0,200},{236,0,200},{230,255,65},{230,255,65},{230,255,65},{226,255,0},{213,255,17},
+{213,255,17},{0,82,421},{0,60,40},{0,42,0},{0,34,145},{0,55,925},{0,36,566},{0,33,262},{0,22,677},{0,27,989},{0,22,726},{0,82,421},{0,60,40},{0,42,0},{0,34,145},{27,0,925},{0,36,566},{0,33,262},{0,22,677},{55,0,925},{0,22,677},{0,40,0},{0,40,0},{0,40,0},{0,20,0},{0,19,85},{0,15,25},{0,15,25},{0,10,45},{0,9,89},{0,8,54},{0,40,0},
+{0,40,0},{0,40,0},{0,20,0},{9,0,85},{0,15,25},{0,15,25},{0,10,45},{19,0,85},{0,10,45},{41,0,421},{0,60,40},{0,42,0},{0,34,145},{41,0,421},{82,0,421},{0,34,145},{0,27,421},{82,0,421},{0,27,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,107,421},{0,72,8},{1,50,18},
+{0,44,100},{0,73,1261},{0,48,670},{0,42,282},{0,28,857},{0,33,1369},{0,28,938},{0,107,421},{0,72,8},{2,51,14},{0,44,100},{36,0,1261},{0,48,670},{0,42,282},{0,28,857},{73,0,1261},{0,28,857},{0,64,0},{0,64,0},{0,64,0},{0,32,0},{0,31,221},{0,27,73},{0,27,73},{0,16,125},{0,15,237},{0,13,144},{0,64,0},{0,64,0},{0,64,0},{0,32,0},{15,0,221},
+{0,27,73},{0,27,73},{0,16,125},{31,0,221},{0,16,125},{52,0,421},{0,72,8},{7,50,0},{0,44,100},{52,0,421},{107,0,421},{0,44,100},{0,35,421},{107,0,421},{0,35,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,127,426},{1,86,5},{4,59,67},{0,53,70},{0,92,1514},{0,60,701},{0,51,243},
+{0,37,946},{0,42,1695},{0,34,1083},{3,125,421},{3,84,1},{7,59,42},{1,54,69},{45,0,1514},{0,60,701},{0,51,243},{0,37,946},{92,0,1514},{0,37,946},{2,84,5},{2,84,5},{2,84,5},{1,43,5},{0,49,338},{0,36,89},{0,36,89},{0,22,170},{0,21,382},{0,19,217},{3,82,0},{3,82,0},{3,82,0},{3,42,0},{24,0,338},{0,36,89},{0,36,89},{0,22,170},{49,0,338},
+{0,22,170},{64,0,421},{1,86,0},{15,58,0},{0,53,61},{64,0,421},{131,0,421},{0,53,61},{0,43,421},{131,0,421},{0,43,421},{1,0,5},{1,0,5},{1,0,5},{1,0,5},{0,10,0},{0,10,0},{0,10,0},{0,5,0},{0,3,1},{0,3,1},{6,143,482},{6,97,63},{8,69,163},{4,63,110},{0,116,1514},{0,72,589},{0,60,109},{0,44,857},{0,54,1815},{0,44,1053},{11,133,421},
+{11,91,1},{15,67,42},{9,62,69},{57,0,1514},{0,72,589},{0,60,109},{0,44,857},{116,0,1514},{0,44,857},{6,101,61},{6,101,61},{6,101,61},{6,52,61},{0,73,338},{0,51,34},{0,51,34},{0,31,117},{0,33,446},{0,29,209},{11,90,0},{11,90,0},{11,90,0},{11,50,0},{36,0,338},{0,51,34},{0,51,34},{0,31,117},{73,0,338},{0,31,117},{76,0,421},{10,93,0},{23,66,0},
+{0,62,32},{76,0,421},{155,0,421},{0,62,32},{0,51,421},{155,0,421},{0,51,421},{5,0,61},{5,0,61},{5,0,61},{5,0,61},{0,34,0},{0,34,0},{0,34,0},{0,17,0},{0,15,17},{0,15,17},{10,162,621},{11,109,215},{14,78,362},{9,71,234},{0,143,1514},{0,88,489},{0,72,22},{0,56,750},{0,66,1982},{0,53,1047},{20,142,421},{20,100,1},{24,76,42},{18,71,69},{70,0,1514},
+{0,88,489},{0,72,22},{0,56,750},{143,0,1514},{0,56,750},{10,120,200},{10,120,200},{10,120,200},{10,64,200},{0,101,338},{0,69,4},{0,69,4},{0,40,72},{0,45,552},{0,39,229},{20,99,0},{20,99,0},{20,99,0},{20,59,0},{49,0,338},{0,69,4},{0,69,4},{0,40,72},{101,0,338},{0,40,72},{89,0,421},{19,102,0},{32,75,0},{0,74,10},{89,0,421},{183,0,421},{0,74,10},
+{0,60,421},{183,0,421},{0,60,421},{10,0,200},{10,0,200},{10,0,200},{10,0,200},{0,61,0},{0,61,0},{0,61,0},{0,30,0},{0,24,65},{0,24,65},{14,178,813},{15,119,423},{18,88,618},{13,81,414},{0,167,1514},{0,100,441},{0,83,2},{0,65,670},{0,75,2165},{0,60,1070},{28,150,421},{28,108,1},{32,84,42},{26,79,69},{82,0,1514},{0,100,441},{2,82,2},{0,65,670},{167,0,1514},
+{0,65,670},{14,136,392},{14,136,392},{14,136,392},{14,74,392},{0,125,338},{1,80,2},{1,80,2},{0,50,41},{0,54,677},{0,48,277},{28,107,0},{28,107,0},{28,107,0},{28,67,0},{61,0,338},{3,79,0},{3,79,0},{0,50,41},{125,0,338},{0,50,41},{101,0,421},{27,110,0},{40,83,0},{0,83,1},{101,0,421},{207,0,421},{0,83,1},{0,68,421},{207,0,421},{0,68,421},{14,0,392},
+{14,0,392},{14,0,392},{14,0,392},{0,85,0},{0,85,0},{0,85,0},{0,42,0},{0,33,136},{0,33,136},{22,186,842},{22,128,450},{26,96,655},{21,89,441},{7,177,1514},{5,111,434},{8,90,4},{4,72,639},{0,88,2003},{0,69,858},{36,157,421},{36,116,1},{40,92,42},{34,87,69},{94,0,1514},{0,113,422},{8,90,3},{0,71,602},{192,0,1514},{0,71,602},{22,144,421},{22,144,421},{22,144,421},
+{21,82,421},{7,135,338},{8,90,3},{8,90,3},{6,59,35},{0,69,581},{0,57,150},{36,115,0},{36,115,0},{36,115,0},{36,75,0},{73,0,338},{11,87,0},{11,87,0},{0,59,18},{149,0,338},{0,59,18},{113,0,421},{35,118,0},{48,91,0},{2,91,0},{113,0,421},{231,0,421},{2,91,0},{0,76,421},{231,0,421},{0,76,421},{21,0,421},{21,0,421},{21,0,421},{21,0,421},{7,95,0},
+{7,95,0},{7,95,0},{7,50,0},{0,48,80},{0,48,80},{30,194,842},{30,136,450},{34,104,655},{29,97,441},{15,185,1514},{13,119,434},{16,98,4},{12,80,639},{0,103,1850},{0,80,663},{44,165,421},{44,124,1},{48,100,42},{42,95,69},{106,0,1514},{6,122,421},{16,98,3},{0,80,542},{216,0,1514},{0,80,542},{30,152,421},{30,152,421},{30,152,421},{29,90,421},{15,143,338},{16,98,3},{16,98,3},
+{14,67,35},{0,81,477},{0,66,52},{44,123,0},{44,123,0},{44,123,0},{44,83,0},{85,0,338},{19,95,0},{19,95,0},{0,68,5},{174,0,338},{0,68,5},{125,0,421},{43,126,0},{56,99,0},{10,99,0},{125,0,421},{255,0,421},{10,99,0},{0,84,421},{255,0,421},{0,84,421},{29,0,421},{29,0,421},{29,0,421},{29,0,421},{15,103,0},{15,103,0},{15,103,0},{15,58,0},{0,63,29},
+{0,63,29},{39,203,842},{39,145,450},{43,113,655},{37,106,445},{24,194,1514},{22,126,438},{25,107,4},{21,89,639},{0,115,1710},{0,90,519},{53,174,421},{53,133,1},{56,110,38},{51,104,69},{119,0,1514},{15,131,421},{25,107,3},{0,90,494},{243,0,1514},{0,90,494},{39,160,421},{39,160,421},{39,160,421},{38,99,421},{24,152,338},{25,107,3},{25,107,3},{23,76,35},{0,97,389},{0,78,3},{53,132,0},
+{53,132,0},{53,132,0},{53,92,0},{98,0,338},{29,103,0},{29,103,0},{0,79,0},{201,0,338},{0,79,0},{138,0,421},{52,135,0},{65,108,0},{19,108,0},{138,0,421},{254,14,421},{19,108,0},{0,93,421},{254,14,421},{0,93,421},{38,0,421},{38,0,421},{38,0,421},{38,0,421},{24,112,0},{24,112,0},{24,112,0},{24,67,0},{0,78,2},{0,78,2},{47,211,842},{47,153,450},{51,121,655},
+{45,114,445},{32,202,1514},{30,134,438},{33,115,4},{29,97,639},{0,129,1617},{0,99,458},{61,182,421},{61,141,1},{64,118,38},{59,112,69},{131,0,1514},{23,139,421},{33,115,3},{0,99,458},{255,6,1514},{0,99,458},{47,168,421},{47,168,421},{47,168,421},{46,107,421},{32,160,338},{33,115,3},{33,115,3},{31,84,35},{0,109,349},{5,87,1},{61,140,0},{61,140,0},{61,140,0},{61,100,0},{110,0,338},
+{37,111,0},{37,111,0},{8,87,0},{225,0,338},{8,87,0},{150,0,421},{60,143,0},{73,116,0},{27,116,0},{150,0,421},{254,26,421},{27,116,0},{0,101,421},{254,26,421},{0,101,421},{46,0,421},{46,0,421},{46,0,421},{46,0,421},{32,120,0},{32,120,0},{32,120,0},{32,75,0},{5,88,0},{5,88,0},{55,219,842},{55,161,450},{59,129,655},{53,122,445},{40,210,1514},{38,142,438},{41,123,4},
+{36,105,646},{0,141,1553},{3,108,450},{69,190,421},{69,149,1},{72,126,38},{68,118,73},{143,0,1514},{32,146,421},{41,123,3},{0,108,434},{255,18,1514},{0,108,434},{55,176,421},{55,176,421},{55,176,421},{55,114,421},{40,168,338},{41,123,3},{41,123,3},{39,92,35},{0,122,338},{13,95,1},{69,148,0},{69,148,0},{69,148,0},{69,108,0},{122,0,338},{45,119,0},{45,119,0},{15,95,0},{249,0,338},
+{15,95,0},{162,0,421},{68,151,0},{81,124,0},{35,124,0},{162,0,421},{254,38,421},{35,124,0},{0,109,421},{254,38,421},{0,109,421},{54,0,421},{54,0,421},{54,0,421},{54,0,421},{40,128,0},{40,128,0},{40,128,0},{40,83,0},{13,96,0},{13,96,0},{63,227,842},{63,169,450},{68,134,654},{61,130,445},{48,218,1514},{46,151,434},{49,131,4},{44,113,646},{0,153,1521},{11,116,450},{77,198,421},
+{77,157,1},{80,134,38},{74,128,74},{155,0,1514},{40,154,421},{49,131,3},{0,117,422},{255,30,1514},{0,117,422},{63,184,421},{63,184,421},{63,184,421},{63,122,421},{48,175,338},{49,131,3},{49,131,3},{47,100,35},{8,130,338},{21,103,1},{77,156,0},{77,156,0},{77,156,0},{77,116,0},{134,0,338},{53,127,0},{53,127,0},{23,103,0},{255,9,338},{23,103,0},{174,0,421},{76,159,0},{89,132,0},
+{43,132,0},{174,0,421},{255,49,421},{43,132,0},{0,117,421},{255,49,421},{0,117,421},{62,0,421},{62,0,421},{62,0,421},{62,0,421},{48,136,0},{48,136,0},{48,136,0},{48,91,0},{21,104,0},{21,104,0},{72,236,842},{72,178,450},{76,145,646},{70,139,445},{57,227,1514},{55,160,434},{58,140,4},{53,122,646},{4,166,1514},{20,125,450},{86,207,421},{86,166,1},{89,143,38},{83,137,74},{168,0,1514},
+{49,163,421},{58,140,3},{4,126,421},{255,43,1514},{4,126,421},{72,193,421},{72,193,421},{72,193,421},{72,131,421},{57,184,338},{58,140,3},{58,140,3},{56,109,35},{18,138,338},{30,112,1},{86,164,0},{86,164,0},{86,164,0},{86,125,0},{147,0,338},{62,136,0},{62,136,0},{32,112,0},{254,23,338},{32,112,0},{187,0,421},{85,168,0},{98,141,0},{52,141,0},{187,0,421},{254,63,421},{52,141,0},
+{0,126,421},{254,63,421},{0,126,421},{71,0,421},{71,0,421},{71,0,421},{71,0,421},{57,145,0},{57,145,0},{57,145,0},{57,100,0},{30,113,0},{30,113,0},{80,243,842},{80,186,450},{84,153,646},{78,147,445},{65,235,1514},{63,168,434},{66,148,4},{61,130,646},{12,174,1514},{27,133,450},{94,215,421},{94,174,1},{97,151,38},{91,145,74},{180,0,1514},{57,171,421},{66,148,3},{11,134,421},{255,55,1514},
+{11,134,421},{80,201,421},{80,201,421},{80,201,421},{80,139,421},{65,192,338},{66,148,3},{66,148,3},{63,116,36},{26,146,338},{38,120,1},{94,172,0},{94,172,0},{94,172,0},{94,132,0},{159,0,338},{70,144,0},{70,144,0},{40,120,0},{254,35,338},{40,120,0},{199,0,421},{92,176,0},{106,149,0},{60,149,0},{199,0,421},{254,75,421},{60,149,0},{0,134,421},{254,75,421},{0,134,421},{79,0,421},
+{79,0,421},{79,0,421},{79,0,421},{65,153,0},{65,153,0},{65,153,0},{65,108,0},{38,121,0},{38,121,0},{88,251,842},{88,194,450},{92,161,646},{86,155,445},{73,243,1514},{71,176,434},{74,156,4},{69,138,646},{21,181,1514},{35,141,450},{102,223,421},{102,182,1},{105,159,38},{99,153,74},{192,0,1514},{65,179,421},{74,156,3},{19,142,421},{255,67,1514},{19,142,421},{88,209,421},{88,209,421},{88,209,421},
+{88,147,421},{73,200,338},{74,156,3},{74,156,3},{71,125,38},{34,154,338},{46,128,1},{102,180,0},{102,180,0},{102,180,0},{102,140,0},{171,0,338},{78,152,0},{78,152,0},{48,128,0},{255,46,338},{48,128,0},{211,0,421},{100,184,0},{114,157,0},{68,157,0},{211,0,421},{255,86,421},{68,157,0},{0,142,421},{255,86,421},{0,142,421},{87,0,421},{87,0,421},{87,0,421},{87,0,421},{73,161,0},
+{73,161,0},{73,161,0},{73,116,0},{46,129,0},{46,129,0},{97,254,850},{96,202,450},{100,169,646},{94,163,445},{81,251,1514},{79,184,434},{82,164,4},{77,146,646},{29,189,1514},{43,149,450},{110,231,421},{110,190,1},{113,167,38},{107,161,74},{204,0,1514},{73,187,421},{83,164,2},{27,150,421},{255,79,1514},{27,150,421},{96,217,421},{96,217,421},{96,217,421},{96,155,421},{81,208,338},{82,163,2},{82,163,2},
+{79,133,38},{42,162,338},{54,136,1},{110,188,0},{110,188,0},{110,188,0},{110,148,0},{183,0,338},{86,160,0},{86,160,0},{56,136,0},{255,58,338},{56,136,0},{223,0,421},{108,192,0},{122,165,0},{76,165,0},{223,0,421},{255,98,421},{76,165,0},{0,150,421},{255,98,421},{0,150,421},{95,0,421},{95,0,421},{95,0,421},{95,0,421},{81,169,0},{81,169,0},{81,169,0},{81,124,0},{54,137,0},
+{54,137,0},{107,255,878},{105,211,450},{109,178,646},{103,172,445},{91,254,1518},{88,193,434},{91,173,4},{86,155,646},{38,198,1514},{52,158,450},{119,240,421},{119,199,1},{122,176,38},{116,170,74},{217,0,1514},{82,196,421},{92,173,2},{36,159,421},{255,92,1514},{36,159,421},{105,226,421},{105,226,421},{105,226,421},{105,164,421},{90,217,338},{91,172,2},{91,172,2},{88,142,38},{51,171,338},{63,145,1},{119,197,0},
+{119,197,0},{119,197,0},{119,157,0},{196,0,338},{95,169,0},{95,169,0},{65,145,0},{254,72,338},{65,145,0},{236,0,421},{117,201,0},{130,174,0},{84,174,0},{236,0,421},{254,112,421},{84,174,0},{0,159,421},{254,112,421},{0,159,421},{104,0,421},{104,0,421},{104,0,421},{104,0,421},{90,177,0},{90,177,0},{90,177,0},{90,133,0},{63,146,0},{63,146,0},{116,255,926},{113,218,450},{117,186,646},
+{111,180,445},{101,255,1535},{96,201,434},{99,181,4},{94,163,646},{46,206,1514},{60,166,450},{127,247,421},{127,207,1},{130,184,38},{124,178,74},{229,0,1514},{90,204,421},{99,181,3},{44,167,421},{255,104,1514},{44,167,421},{113,234,421},{113,234,421},{113,234,421},{113,172,421},{98,225,338},{99,180,3},{99,180,3},{96,150,38},{59,179,338},{71,153,1},{127,205,0},{127,205,0},{127,205,0},{127,165,0},{208,0,338},
+{103,177,0},{103,177,0},{73,153,0},{254,84,338},{73,153,0},{248,0,421},{125,209,0},{138,182,0},{92,182,0},{248,0,421},{254,124,421},{92,182,0},{0,167,421},{254,124,421},{0,167,421},{112,0,421},{112,0,421},{112,0,421},{112,0,421},{98,185,0},{98,185,0},{98,185,0},{98,141,0},{71,154,0},{71,154,0},{125,255,994},{121,226,450},{125,194,646},{120,186,446},{113,255,1575},{104,209,434},{107,189,4},
+{102,171,646},{54,214,1514},{68,174,450},{135,255,421},{135,215,1},{139,192,36},{132,186,74},{241,0,1514},{98,212,421},{107,189,3},{52,175,421},{255,116,1514},{52,175,421},{121,241,421},{121,241,421},{121,241,421},{121,180,421},{106,233,338},{107,188,3},{107,188,3},{104,158,38},{67,187,338},{79,161,1},{135,213,0},{135,213,0},{135,213,0},{135,173,0},{220,0,338},{110,185,0},{110,185,0},{81,161,0},{255,95,338},
+{81,161,0},{255,10,421},{133,217,0},{146,190,0},{100,190,0},{255,10,421},{255,135,421},{100,190,0},{0,175,421},{255,135,421},{0,175,421},{120,0,421},{120,0,421},{120,0,421},{120,0,421},{106,193,0},{106,193,0},{106,193,0},{106,149,0},{79,162,0},{79,162,0},{135,255,1070},{129,234,450},{133,202,646},{128,195,446},{122,255,1626},{112,216,438},{115,197,4},{110,179,646},{62,222,1514},{76,182,450},{146,254,434},
+{143,223,1},{146,199,35},{140,194,74},{253,0,1514},{106,220,421},{115,197,3},{60,183,421},{254,128,1514},{60,183,421},{129,249,421},{129,249,421},{129,249,421},{129,188,421},{114,241,338},{115,196,3},{115,196,3},{112,166,38},{75,195,338},{87,169,1},{143,221,0},{143,221,0},{143,221,0},{143,181,0},{232,0,338},{118,193,0},{118,193,0},{89,169,0},{255,107,338},{89,169,0},{255,34,421},{141,225,0},{154,198,0},
+{108,198,0},{255,34,421},{255,147,421},{108,198,0},{0,183,421},{255,147,421},{0,183,421},{128,0,421},{128,0,421},{128,0,421},{128,0,421},{114,201,0},{114,201,0},{114,201,0},{114,157,0},{87,170,0},{87,170,0},{144,255,1190},{138,243,450},{142,211,646},{137,204,446},{132,255,1703},{121,225,438},{124,206,4},{121,187,654},{71,231,1514},{85,191,450},{156,255,461},{152,232,1},{155,208,35},{151,202,75},{255,22,1514},
+{114,229,421},{124,206,3},{69,192,421},{255,141,1514},{69,192,421},{138,255,422},{138,255,422},{138,255,422},{137,197,421},{123,250,338},{124,205,3},{124,205,3},{121,175,38},{84,204,338},{96,178,1},{152,230,0},{152,230,0},{152,230,0},{152,190,0},{245,0,338},{127,202,0},{127,202,0},{97,178,0},{254,121,338},{97,178,0},{255,61,421},{150,234,0},{163,207,0},{117,207,0},{255,61,421},{254,161,421},{117,207,0},
+{0,192,421},{254,161,421},{0,192,421},{137,0,421},{137,0,421},{137,0,421},{137,0,421},{123,210,0},{123,210,0},{123,210,0},{123,166,0},{95,179,0},{95,179,0},{153,255,1318},{146,251,450},{150,219,646},{145,212,446},{144,255,1791},{129,233,438},{132,214,4},{126,196,655},{78,240,1514},{93,199,450},{165,255,506},{160,240,1},{163,216,35},{158,210,78},{255,46,1514},{122,237,421},{132,214,3},{77,200,421},{255,153,1514},
+{77,200,421},{147,255,434},{147,255,434},{147,255,434},{145,205,421},{132,255,339},{132,213,3},{132,213,3},{129,183,38},{92,212,338},{104,186,1},{160,238,0},{160,238,0},{160,238,0},{160,198,0},{255,4,338},{135,210,0},{135,210,0},{105,186,0},{255,132,338},{105,186,0},{255,86,421},{158,242,0},{171,215,0},{125,215,0},{255,86,421},{255,172,421},{125,215,0},{0,200,421},{255,172,421},{0,200,421},{145,0,421},
+{145,0,421},{145,0,421},{145,0,421},{131,218,0},{131,218,0},{131,218,0},{131,174,0},{103,187,0},{103,187,0},{162,255,1466},{156,255,458},{158,226,639},{153,220,446},{153,255,1902},{137,240,438},{140,222,4},{134,204,655},{85,248,1514},{101,207,450},{175,255,554},{168,249,1},{171,224,35},{166,218,78},{255,70,1514},{130,245,421},{140,222,3},{85,208,421},{255,165,1514},{85,208,421},{156,255,458},{156,255,458},{156,255,458},
+{153,213,421},{141,255,350},{140,221,3},{140,221,3},{137,191,38},{99,220,338},{112,194,1},{168,245,0},{168,245,0},{168,245,0},{168,206,0},{255,28,338},{143,218,0},{143,218,0},{113,194,0},{255,144,338},{113,194,0},{255,110,421},{166,250,0},{179,223,0},{133,223,0},{255,110,421},{255,184,421},{133,223,0},{0,208,421},{255,184,421},{0,208,421},{153,0,421},{153,0,421},{153,0,421},{153,0,421},{139,226,0},
+{139,226,0},{139,226,0},{139,182,0},{111,195,0},{111,195,0},{172,255,1606},{165,255,519},{166,234,639},{161,228,446},{165,255,2030},{145,248,438},{148,230,4},{142,212,655},{95,255,1515},{109,215,450},{187,255,626},{177,255,3},{179,232,35},{174,226,78},{255,95,1514},{138,253,421},{148,230,3},{93,216,421},{254,177,1514},{93,216,421},{165,255,494},{165,255,494},{165,255,494},{161,221,421},{150,255,379},{148,229,3},{148,229,3},
+{145,199,38},{107,228,338},{120,202,1},{176,253,0},{176,253,0},{176,253,0},{176,214,0},{255,52,338},{151,226,0},{151,226,0},{121,202,0},{255,156,338},{121,202,0},{255,134,421},{177,255,2},{187,231,0},{141,231,0},{255,134,421},{255,196,421},{141,231,0},{0,216,421},{255,196,421},{0,216,421},{161,0,421},{161,0,421},{161,0,421},{161,0,421},{147,234,0},{147,234,0},{147,234,0},{147,190,0},{119,203,0},
+{119,203,0},{184,255,1818},{175,255,663},{175,243,639},{170,237,446},{175,255,2175},{155,255,443},{157,239,4},{151,221,655},{113,255,1557},{118,224,450},{196,255,722},{189,255,52},{188,241,35},{183,235,78},{255,122,1514},{155,255,442},{157,239,3},{101,225,421},{255,190,1514},{101,225,421},{175,255,542},{175,255,542},{175,255,542},{170,230,421},{162,255,424},{157,238,3},{157,238,3},{155,207,42},{116,237,338},{129,211,1},{186,254,5},
+{186,254,5},{186,254,5},{185,223,0},{255,79,338},{160,235,0},{160,235,0},{130,211,0},{253,170,338},{130,211,0},{255,161,421},{192,255,29},{196,240,0},{150,240,0},{255,161,421},{254,210,421},{150,240,0},{0,225,421},{254,210,421},{0,225,421},{170,0,421},{170,0,421},{170,0,421},{170,0,421},{156,243,0},{156,243,0},{156,243,0},{156,199,0},{128,212,0},{128,212,0},{193,255,2022},{184,255,858},{183,251,639},
+{178,245,446},{187,255,2343},{167,255,523},{165,247,4},{159,229,655},{131,255,1653},{126,232,450},{208,255,826},{198,255,150},{196,249,35},{191,243,78},{255,146,1514},{167,255,514},{165,247,3},{109,233,421},{255,202,1514},{109,233,421},{181,255,602},{181,255,602},{181,255,602},{178,238,421},{172,255,474},{165,246,3},{165,246,3},{163,215,42},{124,245,338},{137,219,1},{196,255,18},{196,255,18},{196,255,18},{193,231,0},{255,104,338},
+{168,243,0},{168,243,0},{138,219,0},{255,181,338},{138,219,0},{255,186,421},{207,255,80},{204,248,0},{158,248,0},{255,186,421},{255,221,421},{158,248,0},{0,233,421},{255,221,421},{0,233,421},{178,0,421},{178,0,421},{178,0,421},{178,0,421},{164,251,0},{164,251,0},{164,251,0},{164,207,0},{136,220,0},{136,220,0},{202,255,2175},{195,255,1070},{190,255,670},{186,253,441},{196,255,2443},{177,255,663},{172,255,2},
+{167,237,618},{146,255,1735},{135,240,423},{215,255,876},{207,255,277},{205,255,41},{199,251,69},{255,171,1459},{186,255,584},{174,254,2},{117,241,392},{254,214,1459},{117,241,392},{190,255,670},{190,255,670},{190,255,670},{186,246,421},{181,255,547},{173,253,2},{173,253,2},{171,223,42},{132,253,338},{145,227,1},{205,255,41},{205,255,41},{205,255,41},{201,239,0},{255,128,338},{176,251,0},{176,251,0},{146,227,0},{255,193,338},
+{146,227,0},{255,210,392},{222,255,136},{213,255,0},{167,255,0},{255,210,392},{255,233,392},{167,255,0},{0,241,392},{255,233,392},{0,241,392},{186,0,421},{186,0,421},{186,0,421},{186,0,421},{172,255,1},{172,255,1},{172,255,1},{172,214,0},{144,228,0},{144,228,0},{208,255,1867},{202,255,1047},{199,255,750},{194,255,421},{205,255,2052},{186,255,524},{183,255,22},{177,241,362},{161,255,1400},{145,244,215},{224,255,625},
+{216,255,229},{215,255,72},{207,253,17},{255,186,1064},{198,255,392},{186,255,4},{133,245,200},{255,221,1064},{133,245,200},{199,255,750},{199,255,750},{199,255,750},{194,254,421},{193,255,635},{183,255,22},{183,255,22},{179,231,42},{146,255,350},{153,235,1},{215,255,72},{215,255,72},{215,255,72},{209,247,0},{255,152,338},{186,255,4},{186,255,4},{154,235,0},{255,205,338},{154,235,0},{255,222,200},{231,255,65},{224,255,0},
+{192,255,0},{255,222,200},{255,239,200},{192,255,0},{0,245,200},{255,239,200},{0,245,200},{194,0,421},{194,0,421},{194,0,421},{194,0,421},{181,255,10},{181,255,10},{181,255,10},{180,222,0},{152,236,0},{152,236,0},{215,255,1586},{211,255,1053},{211,255,857},{204,255,446},{215,255,1698},{198,255,455},{195,255,109},{186,247,163},{177,255,1161},{158,249,63},{230,255,425},{226,255,209},{224,255,117},{218,255,1},{255,204,722},
+{210,255,254},{204,255,34},{152,249,61},{255,230,722},{152,249,61},{211,255,857},{211,255,857},{211,255,857},{204,255,446},{202,255,749},{195,255,109},{195,255,109},{188,240,42},{164,255,413},{162,244,1},{224,255,117},{224,255,117},{224,255,117},{218,254,1},{255,180,338},{204,255,34},{204,255,34},{163,244,0},{255,218,338},{163,244,0},{255,234,61},{240,255,17},{238,255,0},{219,255,0},{255,234,61},{255,245,61},{219,255,0},
+{0,249,61},{255,245,61},{0,249,61},{203,0,421},{203,0,421},{203,0,421},{203,0,421},{193,255,32},{193,255,32},{193,255,32},{189,231,0},{161,245,0},{161,245,0},{224,255,1422},{221,255,1083},{218,255,946},{213,255,525},{221,255,1470},{207,255,478},{204,255,243},{196,251,67},{189,255,1025},{169,253,5},{239,255,318},{235,255,217},{233,255,170},{228,255,29},{255,219,509},{222,255,198},{219,255,89},{169,253,5},{254,238,509},
+{169,253,5},{218,255,946},{218,255,946},{218,255,946},{213,255,525},{215,255,862},{204,255,243},{204,255,243},{196,248,42},{180,255,530},{169,252,1},{233,255,170},{233,255,170},{233,255,170},{228,255,29},{255,204,338},{219,255,89},{219,255,89},{171,252,0},{255,230,338},{171,252,0},{255,246,5},{251,254,1},{250,255,0},{243,255,0},{255,246,5},{255,251,5},{243,255,0},{0,253,5},{255,251,5},{0,253,5},{211,0,421},
+{211,0,421},{211,0,421},{211,0,421},{202,255,61},{202,255,61},{202,255,61},{197,239,0},{169,253,0},{169,253,0},{230,255,1153},{227,255,938},{227,255,857},{222,255,533},{227,255,1141},{216,255,434},{213,255,282},{204,253,18},{201,255,790},{183,255,8},{242,255,192},{242,255,144},{239,255,125},{237,255,34},{255,231,294},{234,255,121},{228,255,73},{189,255,0},{254,244,294},{189,255,0},{227,255,857},{227,255,857},{227,255,857},
+{222,255,533},{221,255,741},{213,255,282},{213,255,282},{204,253,14},{192,255,465},{183,255,8},{239,255,125},{239,255,125},{239,255,125},{237,255,34},{255,219,221},{228,255,73},{228,255,73},{189,255,0},{254,238,221},{189,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{219,0,421},{219,0,421},{219,0,421},{219,0,421},{211,255,100},
+{211,255,100},{211,255,100},{205,247,0},{183,255,8},{183,255,8},{236,255,853},{233,255,726},{233,255,677},{228,255,485},{233,255,793},{225,255,355},{222,255,262},{213,255,0},{213,255,534},{195,255,40},{248,255,68},{245,255,54},{245,255,45},{243,255,10},{255,240,113},{240,255,41},{240,255,25},{213,255,0},{255,248,113},{213,255,0},{233,255,677},{233,255,677},{233,255,677},{228,255,485},{227,255,545},{222,255,262},{222,255,262},
+{213,255,0},{204,255,329},{195,255,40},{245,255,45},{245,255,45},{245,255,45},{243,255,10},{255,231,85},{240,255,25},{240,255,25},{213,255,0},{254,244,85},{213,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{227,0,421},{227,0,421},{227,0,421},{227,0,421},{221,255,145},{221,255,145},{221,255,145},{213,255,0},{195,255,40},
+{195,255,40},{0,119,882},{0,84,97},{0,60,1},{0,50,325},{0,79,1896},{0,51,1188},{0,47,563},{0,31,1410},{0,36,2029},{0,31,1510},{0,119,882},{0,84,97},{0,60,1},{0,50,325},{39,0,1896},{0,51,1188},{0,47,563},{0,31,1410},{79,0,1896},{0,31,1410},{0,55,0},{0,55,0},{0,55,0},{0,27,0},{0,28,162},{0,21,52},{0,21,52},{0,13,89},{0,12,173},{0,13,105},{0,55,0},
+{0,55,0},{0,55,0},{0,27,0},{14,0,162},{0,21,52},{0,21,52},{0,13,89},{28,0,162},{0,13,89},{58,0,882},{0,84,97},{0,60,1},{0,50,325},{58,0,882},{119,0,882},{0,50,325},{0,39,882},{119,0,882},{0,39,882},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,143,882},{0,97,34},{1,68,11},
+{0,59,250},{0,95,2355},{0,63,1332},{0,54,585},{0,40,1656},{0,45,2556},{0,37,1802},{0,143,882},{0,97,34},{2,69,9},{0,59,250},{46,0,2355},{0,63,1332},{0,54,585},{0,40,1656},{95,0,2355},{0,40,1656},{0,79,0},{0,79,0},{0,79,0},{0,39,0},{0,40,338},{0,33,116},{0,33,116},{0,19,193},{0,18,365},{0,16,225},{0,79,0},{0,79,0},{0,79,0},{0,39,0},{20,0,338},
+{0,33,116},{0,33,116},{0,19,193},{40,0,338},{0,19,193},{70,0,882},{0,97,34},{6,68,0},{0,59,250},{70,0,882},{143,0,882},{0,59,250},{0,47,882},{143,0,882},{0,47,882},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,167,882},{0,112,5},{2,78,61},{0,68,185},{0,113,2899},{0,75,1508},{0,63,633},
+{0,44,1965},{0,51,3176},{0,44,2161},{0,167,882},{0,112,5},{4,77,53},{0,68,185},{55,0,2899},{0,75,1508},{0,63,633},{0,44,1965},{113,0,2899},{0,44,1965},{0,104,0},{0,104,0},{0,104,0},{0,51,0},{0,52,578},{0,42,205},{0,42,205},{0,25,337},{0,24,629},{0,22,389},{0,104,0},{0,104,0},{0,104,0},{0,51,0},{26,0,578},{0,42,205},{0,42,205},{0,25,337},{52,0,578},
+{0,25,337},{82,0,882},{0,112,5},{14,76,0},{0,68,185},{82,0,882},{167,0,882},{0,68,185},{0,55,882},{167,0,882},{0,55,882},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,186,900},{3,124,18},{6,88,133},{1,78,162},{0,134,3048},{0,88,1398},{0,72,469},{0,53,1923},{0,60,3457},{0,50,2205},{6,179,882},
+{6,121,2},{10,86,69},{3,77,158},{66,0,3048},{0,88,1398},{0,72,469},{0,53,1923},{134,0,3048},{0,53,1923},{3,122,18},{3,122,18},{3,122,18},{3,61,18},{0,73,648},{0,54,157},{0,54,157},{0,31,317},{0,33,756},{0,31,417},{6,116,0},{6,116,0},{6,116,0},{6,60,0},{36,0,648},{0,54,157},{0,54,157},{0,31,317},{73,0,648},{0,31,317},{94,0,882},{2,124,0},{22,84,0},
+{0,77,130},{94,0,882},{192,0,882},{0,77,130},{0,63,882},{192,0,882},{0,63,882},{3,0,18},{3,0,18},{3,0,18},{3,0,18},{0,19,0},{0,19,0},{0,19,0},{0,9,0},{0,9,4},{0,9,4},{8,203,995},{8,136,115},{11,96,290},{6,86,230},{0,161,3048},{0,100,1221},{0,84,250},{0,62,1758},{0,75,3651},{0,60,2156},{15,188,882},{15,130,2},{19,95,69},{12,86,158},{79,0,3048},
+{0,100,1221},{0,84,250},{0,62,1758},{161,0,3048},{0,62,1758},{8,139,113},{8,139,113},{8,139,113},{8,72,113},{0,101,648},{0,72,73},{0,72,73},{0,40,242},{0,45,862},{0,39,409},{15,125,0},{15,125,0},{15,125,0},{15,69,0},{49,0,648},{0,72,73},{0,72,73},{0,40,242},{101,0,648},{0,40,242},{107,0,882},{11,133,0},{31,93,0},{0,87,85},{107,0,882},{219,0,882},{0,87,85},
+{0,72,882},{219,0,882},{0,72,882},{7,0,113},{7,0,113},{7,0,113},{7,0,113},{0,46,0},{0,46,0},{0,46,0},{0,23,0},{0,18,34},{0,18,34},{12,219,1147},{12,146,275},{16,104,510},{11,95,365},{0,186,3048},{0,115,1096},{0,94,114},{0,71,1620},{0,88,3844},{0,69,2137},{23,196,882},{23,138,2},{27,103,69},{20,94,158},{91,0,3048},{0,115,1096},{0,94,114},{0,71,1620},{186,0,3048},
+{0,71,1620},{12,155,265},{12,155,265},{12,155,265},{12,82,265},{0,125,648},{0,84,25},{0,84,25},{0,53,180},{0,54,987},{0,48,427},{23,133,0},{23,133,0},{23,133,0},{23,77,0},{61,0,648},{0,84,25},{0,84,25},{0,53,180},{125,0,648},{0,53,180},{119,0,882},{20,140,0},{39,101,0},{0,96,50},{119,0,882},{243,0,882},{0,96,50},{0,80,882},{243,0,882},{0,80,882},{11,0,265},
+{11,0,265},{11,0,265},{11,0,265},{0,70,0},{0,70,0},{0,70,0},{0,35,0},{0,27,89},{0,27,89},{16,235,1363},{17,157,505},{20,114,802},{14,104,559},{0,210,3048},{0,127,1000},{0,105,34},{0,80,1494},{0,94,4056},{0,78,2148},{31,204,882},{31,145,2},{35,111,69},{27,102,165},{103,0,3048},{0,127,1000},{0,105,34},{0,80,1494},{210,0,3048},{0,80,1494},{16,171,481},{16,171,481},{16,171,481},
+{16,92,481},{0,149,648},{0,100,1},{0,100,1},{0,62,125},{0,66,1139},{0,57,473},{31,140,0},{31,140,0},{31,140,0},{31,85,0},{73,0,648},{0,100,1},{0,100,1},{0,62,125},{149,0,648},{0,62,125},{131,0,882},{28,148,0},{47,109,0},{0,105,25},{131,0,882},{255,6,882},{0,105,25},{0,88,882},{255,6,882},{0,88,882},{15,0,481},{15,0,481},{15,0,481},{15,0,481},{0,95,0},
+{0,95,0},{0,95,0},{0,46,0},{0,39,169},{0,39,169},{20,251,1643},{21,167,805},{25,122,1170},{19,112,822},{0,234,3048},{0,141,933},{1,115,10},{0,90,1395},{0,106,4312},{0,84,2188},{39,212,882},{39,153,2},{43,119,69},{35,110,165},{115,0,3048},{0,141,933},{1,115,9},{0,90,1395},{234,0,3048},{0,90,1395},{20,187,761},{20,187,761},{20,187,761},{19,102,761},{0,174,648},{1,111,5},{1,111,5},
+{0,71,80},{0,75,1322},{0,66,547},{39,148,0},{39,148,0},{39,148,0},{39,93,0},{85,0,648},{5,109,0},{5,109,0},{0,71,80},{174,0,648},{0,71,80},{143,0,882},{36,156,0},{55,117,0},{0,115,8},{143,0,882},{255,18,882},{0,115,8},{0,96,882},{255,18,882},{0,96,882},{19,0,761},{19,0,761},{19,0,761},{19,0,761},{0,119,0},{0,119,0},{0,119,0},{0,58,0},{0,48,274},
+{0,48,274},{29,254,1780},{29,178,935},{33,133,1327},{26,122,936},{6,249,3048},{3,153,909},{8,125,13},{0,99,1314},{0,121,4212},{0,97,1924},{48,221,882},{48,162,2},{52,128,69},{44,119,165},{128,0,3048},{0,156,891},{10,124,9},{0,99,1278},{255,3,3048},{0,99,1278},{27,200,882},{27,200,882},{27,200,882},{27,112,882},{6,189,648},{7,123,11},{7,123,11},{3,80,61},{0,91,1227},{0,75,409},{48,157,0},
+{48,157,0},{48,157,0},{48,102,0},{98,0,648},{14,118,0},{14,118,0},{0,80,41},{201,0,648},{0,80,41},{156,0,882},{45,165,0},{63,126,0},{0,126,0},{156,0,882},{254,32,882},{0,126,0},{0,105,882},{254,32,882},{0,105,882},{27,0,882},{27,0,882},{27,0,882},{27,0,882},{6,134,0},{6,134,0},{6,134,0},{6,69,0},{0,63,232},{0,63,232},{38,254,1814},{37,186,935},{41,141,1327},
+{34,130,936},{15,255,3049},{11,161,909},{16,133,13},{8,107,1314},{0,132,3964},{0,106,1605},{56,229,882},{56,170,2},{60,136,69},{52,127,165},{140,0,3048},{2,167,882},{18,132,9},{0,108,1188},{255,15,3048},{0,108,1188},{35,208,882},{35,208,882},{35,208,882},{35,120,882},{14,196,648},{15,131,11},{15,131,11},{11,88,61},{0,103,1059},{0,88,221},{56,165,0},{56,165,0},{56,165,0},{56,110,0},{110,0,648},
+{22,126,0},{22,126,0},{0,90,20},{225,0,648},{0,90,20},{168,0,882},{53,173,0},{71,134,0},{5,134,0},{168,0,882},{255,43,882},{5,134,0},{0,113,882},{255,43,882},{0,113,882},{35,0,882},{35,0,882},{35,0,882},{35,0,882},{14,142,0},{14,142,0},{14,142,0},{14,77,0},{0,75,136},{0,75,136},{46,255,1854},{45,194,935},{49,149,1327},{42,138,936},{24,255,3064},{19,169,909},{22,141,14},
+{16,115,1314},{0,144,3748},{0,115,1348},{64,237,882},{64,178,2},{68,144,69},{60,135,165},{152,0,3048},{10,175,882},{26,140,9},{0,117,1110},{255,27,3048},{0,117,1110},{43,216,882},{43,216,882},{43,216,882},{43,128,882},{22,204,648},{23,139,11},{23,139,11},{21,95,62},{0,118,922},{0,97,91},{64,173,0},{64,173,0},{64,173,0},{64,117,0},{122,0,648},{30,134,0},{30,134,0},{0,99,5},{249,0,648},
+{0,99,5},{180,0,882},{61,181,0},{79,142,0},{13,142,0},{180,0,882},{255,55,882},{13,142,0},{0,121,882},{255,55,882},{0,121,882},{43,0,882},{43,0,882},{43,0,882},{43,0,882},{22,150,0},{22,150,0},{22,150,0},{22,85,0},{0,91,58},{0,91,58},{55,255,1924},{53,202,935},{57,157,1327},{50,146,936},{36,255,3096},{27,177,909},{30,149,14},{24,123,1314},{0,159,3559},{0,124,1153},{72,245,882},
+{72,186,2},{77,152,65},{68,143,165},{164,0,3048},{19,182,882},{33,148,9},{0,126,1044},{255,39,3048},{0,126,1044},{51,224,882},{51,224,882},{51,224,882},{51,136,882},{30,212,648},{32,147,9},{32,147,9},{28,103,65},{0,129,810},{0,106,21},{72,181,0},{72,181,0},{72,181,0},{72,125,0},{134,0,648},{38,142,0},{38,142,0},{0,108,0},{255,9,648},{0,108,0},{192,0,882},{69,189,0},{87,150,0},
+{21,150,0},{192,0,882},{255,67,882},{21,150,0},{0,129,882},{255,67,882},{0,129,882},{51,0,882},{51,0,882},{51,0,882},{51,0,882},{30,158,0},{30,158,0},{30,158,0},{30,93,0},{0,106,17},{0,106,17},{67,255,2024},{62,211,935},{66,166,1327},{59,155,936},{46,255,3145},{36,186,909},{40,158,10},{33,132,1314},{0,172,3364},{0,133,1012},{81,254,882},{81,195,2},{86,161,65},{77,152,165},{177,0,3048},
+{28,191,882},{42,157,9},{0,136,990},{255,52,3048},{0,136,990},{60,233,882},{60,233,882},{60,233,882},{60,145,882},{39,221,648},{41,156,9},{41,156,9},{37,112,65},{0,144,720},{2,118,3},{81,190,0},{81,190,0},{81,190,0},{81,134,0},{147,0,648},{47,151,0},{47,151,0},{7,117,0},{254,23,648},{7,117,0},{205,0,882},{78,198,0},{96,159,0},{30,159,0},{205,0,882},{254,81,882},{30,159,0},
+{0,138,882},{254,81,882},{0,138,882},{60,0,882},{60,0,882},{60,0,882},{60,0,882},{39,167,0},{39,167,0},{39,167,0},{39,102,0},{0,121,0},{0,121,0},{76,255,2134},{70,218,935},{74,174,1327},{66,163,942},{58,255,3217},{45,193,904},{48,166,10},{41,140,1314},{0,184,3244},{0,145,948},{91,254,888},{89,203,2},{94,169,65},{85,160,165},{189,0,3048},{36,199,882},{50,165,9},{0,145,948},{255,64,3048},
+{0,145,948},{68,241,882},{68,241,882},{68,241,882},{68,153,882},{47,229,648},{49,164,9},{49,164,9},{45,120,65},{0,156,672},{10,126,3},{89,198,0},{89,198,0},{89,198,0},{89,142,0},{159,0,648},{56,158,0},{56,158,0},{15,125,0},{254,35,648},{15,125,0},{217,0,882},{86,206,0},{104,167,0},{38,167,0},{217,0,882},{255,92,882},{38,167,0},{0,146,882},{255,92,882},{0,146,882},{68,0,882},
+{68,0,882},{68,0,882},{68,0,882},{47,174,0},{47,174,0},{47,174,0},{47,109,0},{7,129,0},{7,129,0},{86,255,2252},{78,226,935},{82,182,1327},{74,171,942},{67,255,3300},{53,201,904},{56,174,10},{49,148,1314},{0,199,3151},{3,152,935},{101,255,906},{97,211,2},{102,177,65},{93,168,165},{201,0,3048},{44,207,882},{58,173,9},{0,152,915},{255,76,3048},{0,152,915},{76,249,882},{76,249,882},{76,249,882},
+{76,161,882},{55,237,648},{57,172,9},{57,172,9},{53,128,65},{0,171,649},{18,134,3},{97,206,0},{97,206,0},{97,206,0},{97,150,0},{171,0,648},{64,166,0},{64,166,0},{23,133,0},{255,46,648},{23,133,0},{229,0,882},{94,214,0},{112,175,0},{46,175,0},{229,0,882},{255,104,882},{46,175,0},{0,154,882},{255,104,882},{0,154,882},{76,0,882},{76,0,882},{76,0,882},{76,0,882},{55,182,0},
+{55,182,0},{55,182,0},{55,117,0},{16,136,0},{16,136,0},{95,255,2398},{86,234,935},{90,190,1327},{82,179,942},{76,255,3409},{61,209,904},{64,182,10},{56,155,1318},{0,211,3087},{11,160,935},{110,255,939},{105,219,2},{110,185,65},{101,176,165},{213,0,3048},{52,215,882},{66,181,9},{0,161,893},{254,88,3048},{0,161,893},{84,254,883},{84,254,883},{84,254,883},{84,169,882},{63,245,648},{65,180,9},{65,180,9},
+{61,136,65},{7,179,648},{27,141,2},{105,214,0},{105,214,0},{105,214,0},{105,158,0},{183,0,648},{72,174,0},{72,174,0},{31,141,0},{255,58,648},{31,141,0},{241,0,882},{101,222,0},{120,183,0},{54,183,0},{241,0,882},{255,116,882},{54,183,0},{0,162,882},{255,116,882},{0,162,882},{84,0,882},{84,0,882},{84,0,882},{84,0,882},{63,190,0},{63,190,0},{63,190,0},{63,125,0},{24,144,0},
+{24,144,0},{104,255,2584},{95,243,935},{100,199,1318},{91,188,942},{89,255,3529},{69,219,909},{73,191,10},{65,165,1327},{0,224,3052},{20,169,935},{122,255,996},{114,228,2},{119,194,65},{111,183,171},{226,0,3048},{61,224,882},{75,190,9},{0,171,883},{255,101,3048},{0,171,883},{94,254,893},{94,254,893},{94,254,893},{93,177,882},{72,254,648},{74,189,9},{74,189,9},{70,145,65},{16,188,648},{36,150,2},{114,222,0},
+{114,222,0},{114,222,0},{114,167,0},{196,0,648},{81,183,0},{81,183,0},{39,150,0},{254,72,648},{39,150,0},{254,0,882},{110,231,0},{129,192,0},{63,192,0},{254,0,882},{255,129,882},{63,192,0},{0,171,882},{255,129,882},{0,171,882},{93,0,882},{93,0,882},{93,0,882},{93,0,882},{72,199,0},{72,199,0},{72,199,0},{72,134,0},{33,153,0},{33,153,0},{113,255,2774},{103,251,935},{107,206,1314},
+{99,196,942},{98,255,3672},{77,227,909},{81,199,10},{73,173,1327},{5,235,3048},{28,177,935},{132,255,1054},{121,236,3},{127,202,65},{119,192,173},{238,0,3048},{69,232,882},{83,198,9},{4,179,882},{255,113,3048},{4,179,882},{103,254,915},{103,254,915},{103,254,915},{101,185,882},{82,255,654},{82,197,9},{82,197,9},{78,153,65},{24,196,648},{44,158,2},{122,230,0},{122,230,0},{122,230,0},{122,175,0},{208,0,648},
+{89,191,0},{89,191,0},{47,158,0},{254,84,648},{47,158,0},{255,22,882},{118,239,0},{137,200,0},{71,200,0},{255,22,882},{255,141,882},{71,200,0},{0,179,882},{255,141,882},{0,179,882},{101,0,882},{101,0,882},{101,0,882},{101,0,882},{80,207,0},{80,207,0},{80,207,0},{80,142,0},{41,161,0},{41,161,0},{122,255,2984},{110,255,948},{115,214,1314},{107,204,942},{110,255,3832},{85,235,909},{89,207,10},
+{81,181,1327},{13,243,3048},{36,185,935},{141,255,1131},{129,244,3},{135,210,65},{127,200,173},{250,0,3048},{77,240,882},{91,206,9},{12,187,882},{255,125,3048},{12,187,882},{110,255,948},{110,255,948},{110,255,948},{109,193,882},{92,255,672},{90,205,9},{90,205,9},{86,161,65},{32,204,648},{52,166,2},{130,238,0},{130,238,0},{130,238,0},{130,183,0},{220,0,648},{97,199,0},{97,199,0},{55,166,0},{255,95,648},
+{55,166,0},{255,46,882},{126,247,0},{145,208,0},{79,208,0},{255,46,882},{255,153,882},{79,208,0},{0,187,882},{255,153,882},{0,187,882},{109,0,882},{109,0,882},{109,0,882},{109,0,882},{88,215,0},{88,215,0},{88,215,0},{88,150,0},{49,169,0},{49,169,0},{132,255,3182},{122,255,1012},{123,222,1314},{115,212,942},{119,255,4009},{93,243,909},{97,215,10},{89,189,1327},{21,251,3048},{44,193,935},{150,255,1226},
+{137,252,3},{143,218,65},{135,208,173},{255,13,3048},{83,249,882},{99,214,9},{20,195,882},{254,137,3048},{20,195,882},{119,255,990},{119,255,990},{119,255,990},{117,201,882},{101,255,705},{98,213,9},{98,213,9},{94,169,65},{40,212,648},{60,174,2},{138,246,0},{138,246,0},{138,246,0},{138,191,0},{232,0,648},{104,208,0},{104,208,0},{63,174,0},{255,107,648},{63,174,0},{255,70,882},{134,255,0},{153,216,0},
+{86,216,0},{255,70,882},{255,165,882},{86,216,0},{0,195,882},{255,165,882},{0,195,882},{117,0,882},{117,0,882},{117,0,882},{117,0,882},{96,223,0},{96,223,0},{96,223,0},{96,158,0},{57,177,0},{57,177,0},{141,255,3464},{131,255,1153},{132,231,1314},{124,221,942},{132,255,4209},{102,252,909},{105,224,14},{98,198,1327},{37,255,3060},{53,202,935},{162,255,1349},{149,255,21},{152,227,65},{144,217,173},{255,40,3048},
+{95,255,885},{108,223,9},{29,204,882},{255,150,3048},{29,204,882},{129,255,1044},{129,255,1044},{129,255,1044},{126,210,882},{113,255,762},{107,222,9},{107,222,9},{103,178,65},{49,221,648},{69,183,2},{147,255,0},{147,255,0},{147,255,0},{147,200,0},{245,0,648},{112,217,0},{112,217,0},{72,183,0},{254,121,648},{72,183,0},{255,98,882},{149,255,17},{162,225,0},{95,225,0},{255,98,882},{255,178,882},{95,225,0},
+{0,204,882},{255,178,882},{0,204,882},{126,0,882},{126,0,882},{126,0,882},{126,0,882},{105,232,0},{105,232,0},{105,232,0},{105,167,0},{66,186,0},{66,186,0},{150,255,3734},{140,255,1348},{140,239,1314},{132,229,942},{141,255,4420},{113,255,925},{113,232,14},{106,206,1327},{52,255,3132},{61,210,935},{172,255,1459},{158,255,91},{160,234,62},{152,225,173},{255,64,3048},{110,255,923},{116,232,11},{37,212,882},{255,162,3048},
+{37,212,882},{138,255,1110},{138,255,1110},{138,255,1110},{134,218,882},{122,255,827},{115,229,9},{115,229,9},{111,187,69},{57,229,648},{77,191,2},{156,255,5},{156,255,5},{156,255,5},{155,208,0},{255,4,648},{120,225,0},{120,225,0},{80,191,0},{255,132,648},{80,191,0},{255,122,882},{164,255,58},{170,233,0},{103,233,0},{255,122,882},{255,190,882},{103,233,0},{0,212,882},{255,190,882},{0,212,882},{134,0,882},
+{134,0,882},{134,0,882},{134,0,882},{113,240,0},{113,240,0},{113,240,0},{113,175,0},{74,194,0},{74,194,0},{162,255,4022},{149,255,1605},{148,247,1314},{140,237,942},{150,255,4657},{122,255,1020},{122,239,13},{114,214,1327},{70,255,3256},{69,218,935},{181,255,1598},{167,255,221},{167,244,61},{160,233,173},{255,89,3048},{128,255,1003},{123,240,11},{45,220,882},{254,174,3048},{45,220,882},{147,255,1188},{147,255,1188},{147,255,1188},
+{142,226,882},{132,255,897},{123,237,9},{123,237,9},{119,195,69},{65,237,648},{85,199,2},{165,255,20},{165,255,20},{165,255,20},{163,216,0},{255,28,648},{128,233,0},{128,233,0},{88,199,0},{255,144,648},{88,199,0},{255,146,882},{180,255,136},{178,241,0},{111,241,0},{255,146,882},{255,202,882},{111,241,0},{0,220,882},{255,202,882},{0,220,882},{142,0,882},{142,0,882},{142,0,882},{142,0,882},{121,248,0},
+{121,248,0},{121,248,0},{121,183,0},{82,202,0},{82,202,0},{172,255,4300},{158,255,1924},{156,255,1314},{150,244,943},{162,255,4905},{134,255,1204},{130,247,13},{122,222,1327},{82,255,3448},{77,226,935},{190,255,1755},{180,255,409},{175,252,61},{168,241,173},{255,113,3048},{143,255,1125},{131,248,11},{53,228,882},{254,186,3048},{53,228,882},{156,255,1278},{156,255,1278},{156,255,1278},{150,234,882},{141,255,992},{131,245,9},{131,245,9},
+{127,203,69},{73,245,648},{93,207,2},{175,255,41},{175,255,41},{175,255,41},{171,224,0},{255,52,648},{137,240,0},{137,240,0},{96,207,0},{255,156,648},{96,207,0},{255,171,882},{192,255,232},{186,249,0},{119,249,0},{255,171,882},{254,214,882},{119,249,0},{0,228,882},{254,214,882},{0,228,882},{150,0,882},{150,0,882},{150,0,882},{150,0,882},{129,255,0},{129,255,0},{129,255,0},{129,191,0},{90,210,0},
+{90,210,0},{178,255,4349},{171,255,2188},{165,255,1395},{159,251,923},{172,255,4837},{146,255,1309},{140,254,10},{132,229,1170},{104,255,3433},{88,234,805},{202,255,1725},{189,255,547},{184,255,80},{176,249,133},{255,137,2814},{158,255,1125},{143,254,5},{66,235,761},{254,198,2814},{66,235,761},{165,255,1395},{165,255,1395},{165,255,1395},{159,243,882},{153,255,1115},{140,254,9},{140,254,9},{136,212,69},{81,254,648},{102,216,2},{184,255,80},
+{184,255,80},{184,255,80},{180,233,0},{255,79,648},{146,249,0},{146,249,0},{105,216,0},{253,170,648},{105,216,0},{255,192,761},{207,255,274},{196,255,0},{134,255,0},{255,192,761},{255,224,761},{134,255,0},{0,235,761},{255,224,761},{0,235,761},{159,0,882},{159,0,882},{159,0,882},{159,0,882},{140,254,8},{140,254,8},{140,254,8},{138,200,0},{99,219,0},{99,219,0},{187,255,3903},{177,255,2148},{175,255,1494},
+{167,253,887},{181,255,4274},{155,255,1106},{149,255,34},{140,234,802},{119,255,2958},{98,238,505},{208,255,1361},{198,255,473},{193,255,125},{187,251,53},{255,152,2249},{167,255,857},{155,255,1},{82,239,481},{255,205,2249},{82,239,481},{175,255,1494},{175,255,1494},{175,255,1494},{167,251,882},{162,255,1242},{149,255,34},{149,255,34},{144,220,69},{95,255,670},{110,224,2},{193,255,125},{193,255,125},{193,255,125},{188,241,0},{255,104,648},
+{155,255,1},{155,255,1},{113,224,0},{255,181,648},{113,224,0},{255,204,481},{216,255,169},{208,255,0},{158,255,0},{255,204,481},{255,230,481},{158,255,0},{0,239,481},{255,230,481},{0,239,481},{167,0,882},{167,0,882},{167,0,882},{167,0,882},{149,254,25},{149,254,25},{149,254,25},{146,208,0},{106,227,0},{106,227,0},{193,255,3535},{186,255,2137},{184,255,1620},{175,255,891},{187,255,3794},{167,255,978},{159,255,114},
+{150,238,510},{131,255,2574},{109,243,275},{215,255,1046},{207,255,427},{202,255,180},{195,253,9},{255,171,1769},{183,255,650},{167,255,25},{98,243,265},{254,214,1769},{98,243,265},{184,255,1620},{184,255,1620},{184,255,1620},{175,255,891},{172,255,1364},{159,255,114},{159,255,114},{152,228,69},{113,255,734},{117,232,2},{202,255,180},{202,255,180},{202,255,180},{196,249,0},{255,128,648},{167,255,25},{167,255,25},{120,232,0},{255,193,648},
+{120,232,0},{255,216,265},{228,255,89},{220,255,0},{183,255,0},{255,216,265},{255,236,265},{183,255,0},{0,243,265},{255,236,265},{0,243,265},{175,0,882},{175,0,882},{175,0,882},{175,0,882},{159,255,50},{159,255,50},{159,255,50},{154,216,0},{114,235,0},{114,235,0},{202,255,3229},{195,255,2156},{193,255,1758},{183,255,946},{196,255,3397},{174,255,950},{171,255,250},{158,243,290},{146,255,2281},{119,247,115},{221,255,822},
+{216,255,409},{215,255,242},{204,255,1},{255,186,1374},{195,255,498},{183,255,73},{114,247,113},{255,221,1374},{114,247,113},{193,255,1758},{193,255,1758},{193,255,1758},{183,255,946},{181,255,1521},{171,255,250},{171,255,250},{160,236,69},{128,255,840},{125,240,2},{215,255,242},{215,255,242},{215,255,242},{204,255,1},{255,152,648},{183,255,73},{183,255,73},{128,240,0},{255,205,648},{128,240,0},{255,228,113},{237,255,34},{232,255,0},
+{207,255,0},{255,228,113},{255,242,113},{207,255,0},{0,247,113},{255,242,113},{0,247,113},{183,0,882},{183,0,882},{183,0,882},{183,0,882},{168,255,85},{168,255,85},{168,255,85},{162,224,0},{122,243,0},{122,243,0},{211,255,2974},{205,255,2205},{202,255,1923},{195,255,1069},{205,255,3055},{186,255,981},{180,255,469},{167,249,133},{161,255,2061},{131,252,18},{230,255,645},{224,255,417},{224,255,317},{216,255,45},{255,204,1032},
+{210,255,404},{201,255,157},{131,252,18},{255,230,1032},{131,252,18},{202,255,1923},{202,255,1923},{202,255,1923},{195,255,1069},{193,255,1710},{180,255,469},{180,255,469},{169,245,69},{146,255,1011},{134,249,2},{224,255,317},{224,255,317},{224,255,317},{216,255,45},{255,180,648},{201,255,157},{201,255,157},{137,249,0},{255,218,648},{137,249,0},{255,243,18},{246,255,4},{245,255,0},{234,255,0},{255,243,18},{254,250,18},{234,255,0},
+{0,252,18},{254,250,18},{0,252,18},{192,0,882},{192,0,882},{192,0,882},{192,0,882},{178,255,130},{178,255,130},{178,255,130},{171,233,0},{131,252,0},{131,252,0},{218,255,2682},{211,255,2161},{211,255,1965},{204,255,1170},{215,255,2712},{195,255,1014},{192,255,633},{177,253,61},{167,255,1893},{143,255,5},{236,255,513},{233,255,389},{230,255,337},{225,255,97},{255,219,771},{219,255,342},{213,255,205},{149,255,0},{254,238,771},
+{149,255,0},{211,255,1965},{211,255,1965},{211,255,1965},{204,255,1170},{202,255,1755},{192,255,633},{192,255,633},{178,251,53},{161,255,1085},{143,255,5},{230,255,337},{230,255,337},{230,255,337},{225,255,97},{255,201,578},{213,255,205},{213,255,205},{149,255,0},{254,229,578},{149,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{200,0,882},
+{200,0,882},{200,0,882},{200,0,882},{187,255,185},{187,255,185},{187,255,185},{179,241,0},{143,255,5},{143,255,5},{221,255,2188},{218,255,1802},{215,255,1656},{210,255,1086},{218,255,2117},{204,255,865},{201,255,585},{187,254,11},{183,255,1467},{158,255,34},{242,255,297},{239,255,225},{236,255,193},{231,255,53},{255,225,451},{228,255,192},{222,255,116},{174,255,0},{254,241,451},{174,255,0},{215,255,1656},{215,255,1656},{215,255,1656},
+{210,255,1086},{211,255,1426},{201,255,585},{201,255,585},{186,253,9},{167,255,869},{158,255,34},{236,255,193},{236,255,193},{236,255,193},{231,255,53},{255,213,338},{222,255,116},{222,255,116},{174,255,0},{254,235,338},{174,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{208,0,882},{208,0,882},{208,0,882},{208,0,882},{196,255,250},
+{196,255,250},{196,255,250},{187,249,0},{158,255,34},{158,255,34},{227,255,1772},{224,255,1510},{224,255,1410},{219,255,1021},{224,255,1645},{210,255,761},{208,255,563},{195,255,1},{195,255,1123},{171,255,97},{245,255,136},{242,255,105},{242,255,89},{237,255,25},{255,234,216},{237,255,86},{234,255,52},{198,255,0},{255,245,216},{198,255,0},{224,255,1410},{224,255,1410},{224,255,1410},{219,255,1021},{215,255,1140},{208,255,563},{208,255,563},
+{195,255,1},{186,255,696},{171,255,97},{242,255,89},{242,255,89},{242,255,89},{237,255,25},{255,225,162},{234,255,52},{234,255,52},{198,255,0},{254,241,162},{198,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{216,0,882},{216,0,882},{216,0,882},{216,0,882},{205,255,325},{205,255,325},{205,255,325},{195,255,1},{171,255,97},
+{171,255,97},{0,158,1568},{0,112,169},{0,80,4},{0,68,585},{0,107,3371},{0,69,2124},{0,62,1013},{0,40,2532},{0,48,3617},{0,40,2701},{0,158,1568},{0,112,169},{0,80,4},{0,68,585},{52,0,3371},{0,69,2124},{0,62,1013},{0,40,2532},{107,0,3371},{0,40,2532},{0,73,0},{0,73,0},{0,73,0},{0,36,0},{0,37,288},{0,30,97},{0,30,97},{0,16,164},{0,15,312},{0,16,189},{0,73,0},
+{0,73,0},{0,73,0},{0,36,0},{18,0,288},{0,30,97},{0,30,97},{0,16,164},{37,0,288},{0,16,164},{78,0,1568},{0,112,169},{0,80,4},{0,68,585},{78,0,1568},{158,0,1568},{0,68,585},{0,52,1568},{158,0,1568},{0,52,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,183,1568},{0,124,89},{0,89,10},
+{0,77,482},{0,122,3968},{0,81,2316},{0,69,1041},{0,50,2857},{0,57,4304},{0,47,3092},{0,183,1568},{0,124,89},{2,88,8},{0,77,482},{60,0,3968},{0,81,2316},{0,69,1041},{0,50,2857},{122,0,3968},{0,50,2857},{0,98,0},{0,98,0},{0,98,0},{0,48,0},{0,49,512},{0,39,180},{0,39,180},{0,22,296},{0,21,556},{0,22,345},{0,98,0},{0,98,0},{0,98,0},{0,48,0},{24,0,512},
+{0,39,180},{0,39,180},{0,22,296},{49,0,512},{0,22,296},{89,0,1568},{0,124,89},{5,88,0},{0,77,482},{89,0,1568},{183,0,1568},{0,77,482},{0,60,1568},{183,0,1568},{0,60,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,207,1568},{0,138,34},{2,97,58},{0,83,394},{0,137,4651},{0,91,2507},{0,78,1093},
+{0,56,3225},{0,63,5084},{0,53,3532},{0,207,1568},{0,138,34},{3,98,49},{0,83,394},{67,0,4651},{0,91,2507},{0,78,1093},{0,56,3225},{137,0,4651},{0,56,3225},{0,122,0},{0,122,0},{0,122,0},{0,60,0},{0,61,800},{0,48,289},{0,48,289},{0,28,468},{0,27,872},{0,25,545},{0,122,0},{0,122,0},{0,122,0},{0,60,0},{30,0,800},{0,48,289},{0,48,289},{0,28,468},{61,0,800},
+{0,28,468},{101,0,1568},{0,138,34},{13,96,0},{0,83,394},{101,0,1568},{207,0,1568},{0,83,394},{0,68,1568},{207,0,1568},{0,68,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,231,1568},{0,153,5},{3,107,148},{0,93,317},{0,155,5419},{0,100,2754},{0,88,1161},{0,62,3641},{0,69,5968},{0,59,4028},{0,231,1568},
+{0,153,5},{6,107,126},{0,93,317},{76,0,5419},{0,100,2754},{0,88,1161},{0,62,3641},{155,0,5419},{0,62,3641},{0,146,0},{0,146,0},{0,146,0},{0,72,0},{0,73,1152},{0,57,424},{0,57,424},{0,34,680},{0,33,1260},{0,31,789},{0,146,0},{0,146,0},{0,146,0},{0,72,0},{36,0,1152},{0,57,424},{0,57,424},{0,34,680},{73,0,1152},{0,34,680},{113,0,1568},{0,153,5},{21,104,0},
+{0,93,317},{113,0,1568},{231,0,1568},{0,93,317},{0,76,1568},{231,0,1568},{0,76,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,248,1609},{4,166,41},{9,116,259},{2,104,303},{0,183,5419},{0,115,2480},{0,100,798},{0,71,3404},{0,84,6188},{0,68,3926},{9,240,1568},{9,162,5},{15,115,121},{5,104,293},{89,0,5419},
+{0,115,2480},{0,100,798},{0,71,3404},{183,0,5419},{0,71,3404},{5,163,41},{5,163,41},{5,163,41},{4,83,41},{0,101,1152},{0,75,274},{0,75,274},{0,44,569},{0,45,1366},{0,40,747},{9,155,0},{9,155,0},{9,155,0},{9,81,0},{49,0,1152},{0,75,274},{0,75,274},{0,44,569},{101,0,1152},{0,44,569},{127,0,1568},{4,166,0},{30,113,0},{0,105,233},{127,0,1568},{254,2,1568},{0,105,233},
+{0,85,1568},{254,2,1568},{0,85,1568},{4,0,41},{4,0,41},{4,0,41},{4,0,41},{0,28,0},{0,28,0},{0,28,0},{0,14,0},{0,12,10},{0,12,10},{9,255,1731},{9,176,146},{13,126,435},{7,112,374},{0,207,5419},{0,129,2265},{0,109,532},{0,80,3202},{0,94,6384},{0,77,3861},{17,248,1568},{17,170,5},{23,123,121},{13,112,293},{101,0,5419},{0,129,2265},{0,109,532},{0,80,3202},{207,0,5419},
+{0,80,3202},{9,179,145},{9,179,145},{9,179,145},{9,92,145},{0,125,1152},{0,88,157},{0,88,157},{0,53,468},{0,54,1491},{0,50,737},{17,163,0},{17,163,0},{17,163,0},{17,89,0},{61,0,1152},{0,88,157},{0,88,157},{0,53,468},{125,0,1152},{0,53,468},{138,0,1568},{12,174,0},{38,121,0},{0,114,170},{138,0,1568},{254,14,1568},{0,114,170},{0,93,1568},{254,14,1568},{0,93,1568},{8,0,145},
+{8,0,145},{8,0,145},{8,0,145},{0,52,0},{0,52,0},{0,52,0},{0,26,0},{0,21,45},{0,21,45},{15,255,1991},{13,189,321},{18,134,687},{10,121,510},{0,231,5419},{0,141,2081},{0,121,324},{0,90,3035},{0,106,6640},{0,87,3833},{26,254,1569},{25,178,5},{31,131,121},{21,120,293},{113,0,5419},{0,141,2081},{0,121,324},{0,90,3035},{231,0,5419},{0,90,3035},{13,195,313},{13,195,313},{13,195,313},
+{13,102,313},{0,149,1152},{0,103,80},{0,103,80},{0,62,377},{0,66,1643},{0,57,749},{25,171,0},{25,171,0},{25,171,0},{25,97,0},{73,0,1152},{0,103,80},{0,103,80},{0,62,377},{149,0,1152},{0,62,377},{150,0,1568},{21,181,0},{46,129,0},{0,123,117},{150,0,1568},{254,26,1568},{0,123,117},{0,101,1568},{254,26,1568},{0,101,1568},{12,0,313},{12,0,313},{12,0,313},{12,0,313},{0,76,0},
+{0,76,0},{0,76,0},{0,38,0},{0,30,106},{0,30,106},{24,255,2387},{17,199,565},{23,142,1015},{15,129,713},{0,255,5419},{0,156,1924},{0,130,166},{0,99,2857},{0,115,6921},{0,94,3818},{36,255,1579},{33,187,4},{39,139,121},{29,128,293},{125,0,5419},{0,156,1924},{0,130,166},{0,99,2857},{255,0,5419},{0,99,2857},{17,212,545},{17,212,545},{17,212,545},{17,112,545},{0,174,1152},{0,118,29},{0,118,29},
+{0,71,296},{0,75,1826},{0,66,787},{33,179,0},{33,179,0},{33,179,0},{33,104,0},{85,0,1152},{0,118,29},{0,118,29},{0,71,296},{174,0,1152},{0,71,296},{162,0,1568},{29,189,0},{54,137,0},{0,133,80},{162,0,1568},{254,38,1568},{0,133,80},{0,109,1568},{254,38,1568},{0,109,1568},{16,0,545},{16,0,545},{16,0,545},{16,0,545},{0,101,0},{0,101,0},{0,101,0},{0,49,0},{0,39,193},
+{0,39,193},{30,255,3004},{22,210,924},{28,153,1470},{19,140,1026},{6,255,5520},{0,172,1772},{0,142,57},{0,108,2668},{0,127,7276},{0,103,3836},{46,255,1602},{41,195,3},{48,148,121},{38,137,293},{138,0,5419},{0,172,1772},{0,142,57},{0,108,2668},{254,14,5419},{0,108,2668},{21,231,882},{21,231,882},{21,231,882},{21,124,882},{0,201,1152},{0,132,2},{0,132,2},{0,83,218},{0,88,2034},{0,75,865},{42,188,0},
+{42,188,0},{42,188,0},{42,113,0},{98,0,1152},{0,132,2},{0,132,2},{0,83,218},{201,0,1152},{0,83,218},{175,0,1568},{38,198,0},{63,146,0},{0,142,41},{175,0,1568},{254,51,1568},{0,142,41},{0,118,1568},{254,51,1568},{0,118,1568},{21,0,882},{21,0,882},{21,0,882},{21,0,882},{0,128,0},{0,128,0},{0,128,0},{0,63,0},{0,51,320},{0,51,320},{36,255,3708},{27,221,1316},{33,161,1956},
+{24,148,1369},{15,255,5777},{0,184,1676},{0,151,19},{0,117,2514},{0,138,7620},{0,112,3881},{55,255,1643},{49,203,3},{56,156,121},{46,145,293},{150,0,5419},{0,184,1676},{0,151,19},{0,117,2514},{254,26,5419},{0,117,2514},{25,247,1250},{25,247,1250},{25,247,1250},{25,134,1250},{0,225,1152},{1,147,3},{1,147,3},{0,90,164},{0,100,2274},{0,84,961},{50,196,0},{50,196,0},{50,196,0},{50,121,0},{110,0,1152},
+{5,143,0},{5,143,0},{0,90,164},{225,0,1152},{0,90,164},{187,0,1568},{46,206,0},{71,154,0},{0,151,18},{187,0,1568},{254,63,1568},{0,151,18},{0,126,1568},{254,63,1568},{0,126,1568},{25,0,1250},{25,0,1250},{25,0,1250},{25,0,1250},{0,152,0},{0,152,0},{0,152,0},{0,75,0},{0,60,461},{0,60,461},{43,255,4356},{32,232,1665},{38,169,2370},{29,156,1670},{21,255,6121},{0,196,1616},{3,161,20},
+{0,126,2376},{0,150,7804},{0,121,3804},{67,255,1699},{57,211,3},{64,164,121},{54,153,293},{162,0,5419},{0,196,1612},{5,160,17},{0,126,2372},{254,38,5419},{0,126,2372},{30,255,1572},{30,255,1572},{30,255,1572},{30,143,1568},{2,245,1152},{4,159,17},{4,159,17},{0,99,117},{0,109,2403},{0,94,953},{58,204,0},{58,204,0},{58,204,0},{58,129,0},{122,0,1152},{13,151,0},{13,151,0},{0,99,113},{249,0,1152},
+{0,99,113},{199,0,1568},{54,214,0},{79,162,0},{0,160,5},{199,0,1568},{254,75,1568},{0,160,5},{0,134,1568},{254,75,1568},{0,134,1568},{30,0,1568},{30,0,1568},{30,0,1568},{30,0,1568},{2,172,0},{2,172,0},{2,172,0},{2,86,0},{0,72,541},{0,72,541},{52,255,4586},{40,240,1665},{47,177,2355},{37,164,1670},{33,255,6289},{7,206,1615},{11,169,20},{1,134,2353},{0,162,7444},{0,130,3321},{76,255,1766},
+{65,219,3},{72,172,121},{61,161,302},{174,0,5419},{0,211,1577},{13,168,17},{0,133,2259},{255,49,5419},{0,133,2259},{39,255,1586},{39,255,1586},{39,255,1586},{38,151,1568},{10,253,1152},{12,167,17},{12,167,17},{7,109,115},{0,124,2150},{0,103,659},{66,211,0},{66,211,0},{66,211,0},{66,137,0},{134,0,1152},{21,159,0},{21,159,0},{0,108,72},{255,9,1152},{0,108,72},{211,0,1568},{62,222,0},{86,170,0},
+{0,170,0},{211,0,1568},{255,86,1568},{0,170,0},{0,142,1568},{255,86,1568},{0,142,1568},{38,0,1568},{38,0,1568},{38,0,1568},{38,0,1568},{10,180,0},{10,180,0},{10,180,0},{10,93,0},{0,88,373},{0,88,373},{64,255,4866},{49,249,1665},{55,188,2353},{46,173,1670},{43,255,6476},{16,215,1615},{20,178,20},{10,143,2353},{0,178,7036},{0,139,2856},{86,255,1851},{75,228,5},{81,181,121},{70,170,302},{187,0,5419},
+{4,222,1568},{22,177,17},{0,145,2124},{254,63,5419},{0,145,2124},{49,255,1612},{49,255,1612},{49,255,1612},{47,160,1568},{21,255,1158},{21,176,17},{21,176,17},{16,118,115},{0,138,1900},{0,115,392},{75,220,0},{75,220,0},{75,220,0},{75,146,0},{147,0,1152},{30,168,0},{30,168,0},{0,120,34},{254,23,1152},{0,120,34},{224,0,1568},{71,231,0},{95,179,0},{7,179,0},{224,0,1568},{254,100,1568},{7,179,0},
+{0,151,1568},{254,100,1568},{0,151,1568},{47,0,1568},{47,0,1568},{47,0,1568},{47,0,1568},{19,189,0},{19,189,0},{19,189,0},{19,102,0},{0,103,232},{0,103,232},{73,255,5136},{57,254,1666},{63,196,2353},{54,181,1670},{55,255,6684},{24,223,1615},{28,186,20},{18,151,2353},{0,190,6740},{0,151,2504},{95,255,1954},{83,236,5},{89,189,121},{78,178,302},{199,0,5419},{12,230,1568},{30,185,17},{0,154,2018},{254,75,5419},
+{0,154,2018},{58,255,1650},{58,255,1650},{58,255,1650},{55,168,1568},{30,255,1179},{29,184,17},{29,184,17},{24,126,115},{0,150,1708},{0,127,216},{83,228,0},{83,228,0},{83,228,0},{83,154,0},{159,0,1152},{38,176,0},{38,176,0},{0,130,17},{254,35,1152},{0,130,17},{236,0,1568},{78,240,0},{103,187,0},{15,187,0},{236,0,1568},{254,112,1568},{15,187,0},{0,159,1568},{254,112,1568},{0,159,1568},{55,0,1568},
+{55,0,1568},{55,0,1568},{55,0,1568},{27,197,0},{27,197,0},{27,197,0},{27,110,0},{0,115,136},{0,115,136},{82,255,5426},{67,255,1701},{71,204,2353},{62,189,1670},{64,255,6905},{32,231,1615},{36,194,20},{26,159,2353},{0,202,6476},{0,160,2211},{107,255,2066},{91,244,5},{97,197,121},{86,186,302},{211,0,5419},{20,238,1568},{38,193,17},{0,160,1922},{255,86,5419},{0,160,1922},{67,255,1700},{67,255,1700},{67,255,1700},
+{63,176,1568},{39,255,1218},{37,192,17},{37,192,17},{32,134,115},{0,165,1545},{0,136,90},{91,236,0},{91,236,0},{91,236,0},{91,162,0},{171,0,1152},{46,184,0},{46,184,0},{0,139,4},{255,46,1152},{0,139,4},{248,0,1568},{85,248,0},{111,195,0},{23,195,0},{248,0,1568},{254,124,1568},{23,195,0},{0,167,1568},{254,124,1568},{0,167,1568},{63,0,1568},{63,0,1568},{63,0,1568},{63,0,1568},{35,205,0},
+{35,205,0},{35,205,0},{35,118,0},{0,129,65},{0,129,65},{92,255,5700},{76,255,1798},{79,212,2353},{70,197,1670},{73,255,7152},{40,239,1615},{44,202,20},{34,167,2353},{0,215,6213},{0,169,1980},{116,255,2195},{99,252,5},{104,206,115},{94,194,302},{223,0,5419},{28,246,1568},{46,201,17},{0,169,1836},{255,98,5419},{0,169,1836},{76,255,1762},{76,255,1762},{76,255,1762},{71,184,1568},{49,255,1260},{45,200,17},{45,200,17},
+{40,142,115},{0,178,1395},{0,145,24},{99,244,0},{99,244,0},{99,244,0},{99,170,0},{183,0,1152},{54,192,0},{54,192,0},{0,147,0},{255,58,1152},{0,147,0},{255,10,1568},{94,254,1},{119,203,0},{31,203,0},{255,10,1568},{255,135,1568},{31,203,0},{0,175,1568},{255,135,1568},{0,175,1568},{71,0,1568},{71,0,1568},{71,0,1568},{71,0,1568},{43,213,0},{43,213,0},{43,213,0},{43,126,0},{0,144,20},
+{0,144,20},{101,255,6066},{86,255,1980},{88,221,2353},{79,206,1670},{86,255,7408},{49,248,1615},{53,211,20},{43,176,2353},{0,230,5988},{0,179,1798},{129,255,2347},{110,255,24},{113,215,115},{103,203,302},{236,0,5419},{37,255,1568},{55,210,17},{0,179,1762},{254,112,5419},{0,179,1762},{86,255,1836},{86,255,1836},{86,255,1836},{80,193,1568},{61,255,1331},{54,209,17},{54,209,17},{49,151,115},{0,193,1281},{3,156,5},{108,253,0},
+{108,253,0},{108,253,0},{108,179,0},{196,0,1152},{63,201,0},{63,201,0},{9,156,0},{254,72,1152},{9,156,0},{255,37,1568},{110,255,20},{128,212,0},{40,212,0},{255,37,1568},{254,149,1568},{40,212,0},{0,184,1568},{254,149,1568},{0,184,1568},{80,0,1568},{80,0,1568},{80,0,1568},{80,0,1568},{52,222,0},{52,222,0},{52,222,0},{52,135,0},{0,159,1},{0,159,1},{110,255,6416},{95,255,2211},{96,229,2353},
+{86,213,1674},{95,255,7689},{58,254,1616},{61,219,20},{51,184,2353},{0,242,5820},{0,188,1701},{138,255,2502},{119,255,90},{121,223,115},{111,211,302},{248,0,5419},{52,255,1595},{63,218,17},{0,188,1700},{254,124,5419},{0,188,1700},{95,255,1922},{95,255,1922},{95,255,1922},{88,201,1568},{70,255,1414},{62,217,17},{62,217,17},{58,158,121},{0,205,1209},{11,164,5},{116,255,4},{116,255,4},{116,255,4},{116,187,0},{208,0,1152},
+{70,209,0},{70,209,0},{17,164,0},{254,84,1152},{17,164,0},{255,61,1568},{125,255,65},{136,220,0},{48,220,0},{255,61,1568},{254,161,1568},{48,220,0},{0,192,1568},{254,161,1568},{0,192,1568},{88,0,1568},{88,0,1568},{88,0,1568},{88,0,1568},{60,230,0},{60,230,0},{60,230,0},{60,143,0},{7,169,0},{7,169,0},{119,255,6786},{104,255,2504},{104,237,2353},{94,222,1676},{107,255,7985},{68,255,1665},{69,227,20},
+{59,192,2353},{0,254,5684},{0,197,1666},{147,255,2675},{128,255,216},{129,231,115},{119,219,302},{255,10,5419},{67,255,1665},{71,226,17},{0,197,1650},{255,135,5419},{0,197,1650},{101,255,2018},{101,255,2018},{101,255,2018},{96,209,1568},{82,255,1510},{70,224,17},{70,224,17},{66,166,121},{0,218,1163},{19,172,5},{125,255,17},{125,255,17},{125,255,17},{124,195,0},{220,0,1152},{78,217,0},{78,217,0},{25,172,0},{255,95,1152},
+{25,172,0},{255,86,1568},{140,255,136},{144,228,0},{56,228,0},{255,86,1568},{255,172,1568},{56,228,0},{0,200,1568},{255,172,1568},{0,200,1568},{96,0,1568},{96,0,1568},{96,0,1568},{96,0,1568},{68,238,0},{68,238,0},{68,238,0},{68,151,0},{15,177,0},{15,177,0},{129,255,7124},{116,255,2856},{112,245,2353},{102,230,1676},{116,255,8300},{79,255,1802},{77,235,20},{67,200,2353},{7,255,5788},{5,206,1665},{156,255,2866},
+{140,255,392},{137,239,115},{127,227,302},{255,34,5419},{82,255,1779},{79,234,17},{0,206,1612},{255,147,5419},{0,206,1612},{110,255,2124},{110,255,2124},{110,255,2124},{104,217,1568},{92,255,1608},{78,232,17},{78,232,17},{74,174,121},{1,231,1152},{27,180,5},{135,255,34},{135,255,34},{135,255,34},{132,203,0},{232,0,1152},{86,225,0},{86,225,0},{33,180,0},{255,107,1152},{33,180,0},{255,110,1568},{152,255,232},{152,236,0},
+{64,236,0},{255,110,1568},{255,184,1568},{64,236,0},{0,208,1568},{255,184,1568},{0,208,1568},{104,0,1568},{104,0,1568},{104,0,1568},{104,0,1568},{76,246,0},{76,246,0},{76,246,0},{76,159,0},{24,184,0},{24,184,0},{138,255,7586},{125,255,3321},{121,254,2353},{111,239,1676},{129,255,8636},{92,255,2092},{86,244,20},{78,208,2355},{28,255,6049},{14,215,1665},{168,255,3097},{152,255,659},{146,248,115},{136,236,302},{255,61,5419},
+{101,255,1977},{88,243,17},{0,216,1586},{254,161,5419},{0,216,1586},{122,255,2259},{122,255,2259},{122,255,2259},{113,226,1568},{101,255,1746},{87,241,17},{87,241,17},{83,183,121},{10,240,1152},{36,190,3},{147,255,72},{147,255,72},{147,255,72},{141,212,0},{245,0,1152},{95,234,0},{95,234,0},{42,189,0},{254,121,1152},{42,189,0},{255,137,1568},{167,255,373},{161,245,0},{73,245,0},{255,137,1568},{254,198,1568},{73,245,0},
+{0,217,1568},{254,198,1568},{0,217,1568},{113,0,1568},{113,0,1568},{113,0,1568},{113,0,1568},{85,254,0},{85,254,0},{85,254,0},{85,168,0},{33,193,0},{33,193,0},{147,255,8016},{134,255,3804},{129,255,2376},{119,247,1676},{138,255,8985},{104,255,2436},{94,252,20},{85,216,2370},{40,255,6353},{22,223,1665},{178,255,3291},{161,255,953},{156,255,117},{146,243,305},{255,86,5419},{119,255,2185},{96,251,17},{0,225,1572},{255,172,5419},
+{0,225,1572},{129,255,2372},{129,255,2372},{129,255,2372},{121,233,1568},{113,255,1890},{95,249,17},{95,249,17},{91,191,121},{18,248,1152},{44,198,3},{156,255,113},{156,255,113},{156,255,113},{149,220,0},{255,4,1152},{103,242,0},{103,242,0},{49,197,0},{255,132,1152},{49,197,0},{255,161,1568},{183,255,541},{169,253,0},{80,253,0},{255,161,1568},{254,210,1568},{80,253,0},{0,225,1568},{254,210,1568},{0,225,1568},{121,0,1568},
+{121,0,1568},{121,0,1568},{121,0,1568},{94,254,5},{94,254,5},{94,254,5},{93,176,0},{41,201,0},{41,201,0},{156,255,7638},{143,255,3881},{138,255,2514},{128,250,1620},{147,255,8460},{113,255,2285},{104,255,19},{94,222,1956},{58,255,5932},{34,228,1316},{184,255,2947},{171,255,961},{165,255,164},{152,246,206},{255,104,4803},{131,255,1925},{108,254,3},{6,230,1250},{255,181,4803},{6,230,1250},{138,255,2514},{138,255,2514},{138,255,2514},
+{129,241,1568},{122,255,2043},{104,255,19},{104,255,19},{99,199,121},{28,255,1153},{52,206,3},{165,255,164},{165,255,164},{165,255,164},{157,228,0},{255,28,1152},{111,250,0},{111,250,0},{57,205,0},{255,144,1152},{57,205,0},{255,177,1250},{195,255,461},{180,255,0},{101,255,0},{255,177,1250},{254,217,1250},{101,255,0},{0,230,1250},{254,217,1250},{0,230,1250},{129,0,1568},{129,0,1568},{129,0,1568},{129,0,1568},{104,255,18},
+{104,255,18},{104,255,18},{101,184,0},{49,209,0},{49,209,0},{165,255,7060},{152,255,3836},{147,255,2668},{137,253,1576},{156,255,7717},{122,255,2020},{113,255,57},{102,227,1470},{73,255,5307},{44,232,924},{193,255,2466},{180,255,865},{172,255,218},{162,250,98},{255,119,4056},{143,255,1557},{122,255,2},{22,234,882},{254,189,4056},{22,234,882},{147,255,2668},{147,255,2668},{147,255,2668},{137,249,1568},{132,255,2193},{113,255,57},{113,255,57},
+{107,207,121},{40,255,1185},{60,214,3},{172,255,218},{172,255,218},{172,255,218},{165,236,0},{255,52,1152},{122,255,2},{122,255,2},{65,213,0},{255,156,1152},{65,213,0},{255,189,882},{204,255,320},{192,255,0},{125,255,0},{255,189,882},{254,223,882},{125,255,0},{0,234,882},{254,223,882},{0,234,882},{137,0,1568},{137,0,1568},{137,0,1568},{137,0,1568},{113,255,41},{113,255,41},{113,255,41},{109,192,0},{57,217,0},
+{57,217,0},{172,255,6429},{161,255,3818},{156,255,2857},{146,255,1572},{165,255,6979},{134,255,1813},{125,255,166},{113,232,1015},{82,255,4731},{56,238,565},{199,255,2010},{189,255,787},{184,255,296},{173,252,26},{255,137,3318},{155,255,1221},{137,255,29},{41,238,545},{254,198,3318},{41,238,545},{156,255,2857},{156,255,2857},{156,255,2857},{146,255,1572},{141,255,2403},{125,255,166},{125,255,166},{116,216,121},{61,255,1273},{68,222,4},{184,255,296},
+{184,255,296},{184,255,296},{174,245,0},{255,79,1152},{137,255,29},{137,255,29},{74,222,0},{253,170,1152},{74,222,0},{255,201,545},{216,255,193},{205,255,0},{152,255,0},{255,201,545},{254,229,545},{152,255,0},{0,238,545},{254,229,545},{0,238,545},{146,0,1568},{146,0,1568},{146,0,1568},{146,0,1568},{122,255,80},{122,255,80},{122,255,80},{118,201,0},{66,226,0},{66,226,0},{178,255,5997},{168,255,3833},{165,255,3035},
+{155,255,1619},{172,255,6365},{143,255,1710},{134,255,324},{121,237,687},{101,255,4330},{66,242,321},{208,255,1673},{198,255,749},{193,255,377},{182,255,1},{255,152,2753},{167,255,989},{152,255,80},{57,242,313},{255,205,2753},{57,242,313},{165,255,3035},{165,255,3035},{165,255,3035},{155,255,1619},{153,255,2603},{134,255,324},{134,255,324},{124,224,121},{76,255,1395},{76,230,5},{193,255,377},{193,255,377},{193,255,377},{182,253,0},{255,104,1152},
+{152,255,80},{152,255,80},{82,230,0},{255,181,1152},{82,230,0},{255,213,313},{225,255,106},{217,255,0},{177,255,0},{255,213,313},{254,235,313},{177,255,0},{0,242,313},{254,235,313},{0,242,313},{154,0,1568},{154,0,1568},{154,0,1568},{154,0,1568},{132,255,117},{132,255,117},{132,255,117},{126,209,0},{74,234,0},{74,234,0},{187,255,5627},{178,255,3861},{175,255,3202},{164,255,1720},{178,255,5889},{152,255,1685},{146,255,532},
+{129,242,435},{116,255,3993},{79,246,146},{215,255,1382},{205,255,737},{202,255,468},{192,255,13},{255,171,2273},{180,255,850},{167,255,157},{74,246,145},{254,214,2273},{74,246,145},{175,255,3202},{175,255,3202},{175,255,3202},{164,255,1720},{162,255,2818},{146,255,532},{146,255,532},{132,232,121},{92,255,1584},{84,238,5},{202,255,468},{202,255,468},{202,255,468},{192,255,13},{255,128,1152},{167,255,157},{167,255,157},{90,238,0},{255,193,1152},
+{90,238,0},{255,225,145},{234,255,45},{229,255,0},{201,255,0},{255,225,145},{254,241,145},{201,255,0},{0,246,145},{254,241,145},{0,246,145},{162,0,1568},{162,0,1568},{162,0,1568},{162,0,1568},{141,255,170},{141,255,170},{141,255,170},{134,217,0},{80,243,0},{80,243,0},{193,255,5331},{187,255,3926},{184,255,3404},{174,255,1889},{187,255,5490},{161,255,1738},{155,255,798},{139,246,259},{128,255,3745},{88,251,41},{221,255,1182},
+{215,255,747},{211,255,569},{201,255,73},{255,186,1878},{192,255,746},{180,255,274},{90,250,41},{255,221,1878},{90,250,41},{184,255,3404},{184,255,3404},{184,255,3404},{174,255,1889},{172,255,3020},{155,255,798},{155,255,798},{140,240,121},{107,255,1798},{92,246,5},{211,255,569},{211,255,569},{211,255,569},{201,255,73},{255,152,1152},{180,255,274},{180,255,274},{98,246,0},{255,205,1152},{98,246,0},{255,237,41},{243,255,10},{241,255,0},
+{225,255,0},{255,237,41},{254,247,41},{225,255,0},{0,250,41},{254,247,41},{0,250,41},{170,0,1568},{170,0,1568},{170,0,1568},{170,0,1568},{150,255,233},{150,255,233},{150,255,233},{142,225,0},{88,251,0},{88,251,0},{202,255,5076},{196,255,4028},{193,255,3641},{183,255,2129},{196,255,5148},{174,255,1917},{167,255,1161},{147,251,148},{143,255,3577},{101,255,5},{230,255,1041},{224,255,789},{221,255,680},{210,255,205},{255,204,1536},
+{207,255,706},{198,255,424},{107,255,0},{255,230,1536},{107,255,0},{193,255,3641},{193,255,3641},{193,255,3641},{183,255,2129},{184,255,3299},{167,255,1161},{167,255,1161},{148,249,126},{125,255,2089},{101,255,5},{221,255,680},{221,255,680},{221,255,680},{210,255,205},{255,180,1152},{198,255,424},{198,255,424},{107,255,0},{255,218,1152},{107,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},
+{0,255,0},{255,254,0},{0,255,0},{179,0,1568},{179,0,1568},{179,0,1568},{179,0,1568},{162,255,317},{162,255,317},{162,255,317},{151,234,0},{101,255,5},{101,255,5},{208,255,4372},{202,255,3532},{199,255,3225},{189,255,2017},{202,255,4324},{180,255,1693},{177,255,1093},{157,252,58},{155,255,2953},{116,255,34},{233,255,716},{230,255,545},{227,255,468},{219,255,137},{255,213,1067},{213,255,482},{207,255,289},{131,255,0},{254,235,1067},
+{131,255,0},{199,255,3225},{199,255,3225},{199,255,3225},{189,255,2017},{190,255,2819},{177,255,1093},{177,255,1093},{157,252,49},{137,255,1737},{116,255,34},{227,255,468},{227,255,468},{227,255,468},{219,255,137},{255,192,800},{207,255,289},{207,255,289},{131,255,0},{255,224,800},{131,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{187,0,1568},
+{187,0,1568},{187,0,1568},{187,0,1568},{172,255,394},{172,255,394},{172,255,394},{159,242,0},{116,255,34},{116,255,34},{215,255,3720},{208,255,3092},{205,255,2857},{198,255,1910},{208,255,3604},{189,255,1510},{183,255,1041},{165,254,10},{164,255,2420},{131,255,89},{239,255,456},{233,255,345},{233,255,296},{225,255,85},{255,219,683},{222,255,300},{216,255,180},{155,255,0},{254,238,683},{155,255,0},{205,255,2857},{205,255,2857},{205,255,2857},
+{198,255,1910},{196,255,2411},{183,255,1041},{183,255,1041},{167,253,8},{149,255,1449},{131,255,89},{233,255,296},{233,255,296},{233,255,296},{225,255,85},{255,204,512},{216,255,180},{216,255,180},{155,255,0},{255,230,512},{155,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{195,0,1568},{195,0,1568},{195,0,1568},{195,0,1568},{178,255,482},
+{178,255,482},{178,255,482},{167,250,0},{131,255,89},{131,255,89},{218,255,3170},{215,255,2701},{215,255,2532},{207,255,1825},{215,255,2956},{198,255,1373},{192,255,1013},{175,255,4},{167,255,2025},{143,255,169},{242,255,249},{239,255,189},{239,255,164},{234,255,45},{255,228,384},{231,255,162},{225,255,97},{180,255,0},{255,242,384},{180,255,0},{215,255,2532},{215,255,2532},{215,255,2532},{207,255,1825},{205,255,2070},{192,255,1013},{192,255,1013},
+{175,255,4},{161,255,1225},{143,255,169},{239,255,164},{239,255,164},{239,255,164},{234,255,45},{255,216,288},{225,255,97},{225,255,97},{180,255,0},{255,236,288},{180,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{203,0,1568},{203,0,1568},{203,0,1568},{203,0,1568},{187,255,585},{187,255,585},{187,255,585},{175,255,4},{143,255,169},
+{143,255,169},{0,210,2665},{0,147,274},{0,106,1},{0,90,985},{0,140,5885},{0,94,3649},{0,81,1742},{0,56,4398},{0,63,6341},{0,56,4722},{0,210,2665},{0,147,274},{0,106,1},{0,90,985},{69,0,5885},{0,94,3649},{0,81,1742},{0,56,4398},{140,0,5885},{0,56,4398},{0,101,0},{0,101,0},{0,101,0},{0,49,0},{0,49,545},{0,39,193},{0,39,193},{0,22,317},{0,21,593},{0,22,366},{0,101,0},
+{0,101,0},{0,101,0},{0,49,0},{24,0,545},{0,39,193},{0,39,193},{0,22,317},{49,0,545},{0,22,317},{103,0,2665},{0,147,274},{0,106,1},{0,90,985},{103,0,2665},{210,0,2665},{0,90,985},{0,69,2665},{210,0,2665},{0,69,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,234,2665},{0,162,169},{1,114,11},
+{0,99,850},{0,158,6669},{0,103,3898},{0,91,1770},{0,62,4826},{0,72,7238},{0,62,5226},{0,234,2665},{0,162,169},{2,115,9},{0,99,850},{78,0,6669},{0,103,3898},{0,91,1770},{0,62,4826},{158,0,6669},{0,62,4826},{0,125,0},{0,125,0},{0,125,0},{0,61,0},{0,61,841},{0,51,305},{0,51,305},{0,28,493},{0,27,917},{0,28,574},{0,125,0},{0,125,0},{0,125,0},{0,61,0},{30,0,841},
+{0,51,305},{0,51,305},{0,28,493},{61,0,841},{0,28,493},{115,0,2665},{0,162,169},{6,114,0},{0,99,850},{115,0,2665},{234,0,2665},{0,99,850},{0,77,2665},{234,0,2665},{0,77,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,255,2669},{0,175,80},{2,124,61},{0,108,725},{0,174,7538},{0,115,4178},{0,100,1832},
+{0,71,5294},{0,78,8238},{0,68,5786},{2,254,2669},{0,175,80},{4,123,53},{0,108,725},{85,0,7538},{0,115,4178},{0,100,1832},{0,71,5294},{174,0,7538},{0,71,5294},{0,149,0},{0,149,0},{0,149,0},{0,73,0},{0,73,1201},{0,60,442},{0,60,442},{0,34,709},{0,33,1313},{0,31,824},{0,149,0},{0,149,0},{0,149,0},{0,73,0},{36,0,1201},{0,60,442},{0,60,442},{0,34,709},{73,0,1201},
+{0,34,709},{127,0,2665},{0,175,80},{14,122,0},{0,108,725},{127,0,2665},{254,2,2665},{0,108,725},{0,85,2665},{254,2,2665},{0,85,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,255,2795},{0,190,29},{3,134,155},{0,117,610},{0,189,8493},{0,124,4485},{0,109,1922},{0,77,5810},{0,88,9310},{0,74,6402},{6,255,2761},
+{0,190,29},{6,134,133},{0,117,610},{92,0,8493},{0,124,4485},{0,109,1922},{0,77,5810},{189,0,8493},{0,77,5810},{0,174,0},{0,174,0},{0,174,0},{0,85,0},{0,85,1625},{0,69,605},{0,69,605},{0,40,965},{0,39,1781},{0,37,1120},{0,174,0},{0,174,0},{0,174,0},{0,85,0},{42,0,1625},{0,69,605},{0,69,605},{0,40,965},{85,0,1625},{0,40,965},{138,0,2665},{0,190,29},{22,130,0},
+{0,117,610},{138,0,2665},{254,14,2665},{0,117,610},{0,93,2665},{254,14,2665},{0,93,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{9,255,3139},{0,205,2},{5,145,311},{0,126,493},{0,207,9669},{0,135,4865},{0,118,2054},{0,83,6450},{0,94,10654},{0,80,7162},{12,255,3029},{0,205,2},{9,143,266},{0,126,493},{101,0,9669},
+{0,135,4865},{0,118,2054},{0,83,6450},{207,0,9669},{0,83,6450},{0,201,0},{0,201,0},{0,201,0},{0,98,0},{0,101,2178},{0,81,820},{0,81,820},{0,47,1322},{0,45,2392},{0,40,1521},{0,201,0},{0,201,0},{0,201,0},{0,98,0},{49,0,2178},{0,81,820},{0,81,820},{0,47,1322},{101,0,2178},{0,47,1322},{152,0,2665},{0,205,2},{30,139,0},{0,126,493},{152,0,2665},{255,27,2665},{0,126,493},
+{0,102,2665},{255,27,2665},{0,102,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{15,255,3483},{4,217,32},{10,153,429},{2,135,473},{0,231,9669},{0,150,4526},{0,127,1610},{0,93,6193},{0,106,10910},{0,90,7050},{24,255,3141},{8,213,2},{17,151,266},{2,135,469},{113,0,9669},{0,150,4526},{0,127,1610},{0,93,6193},{231,0,9669},
+{0,93,6193},{4,217,32},{4,217,32},{4,217,32},{4,108,32},{0,125,2178},{0,94,605},{0,94,605},{0,56,1165},{0,54,2517},{0,50,1457},{8,209,0},{8,209,0},{8,209,0},{8,106,0},{61,0,2178},{0,94,605},{0,94,605},{0,56,1165},{125,0,2178},{0,56,1165},{164,0,2665},{5,216,0},{38,147,0},{0,136,410},{164,0,2665},{255,39,2665},{0,136,410},{0,110,2665},{255,39,2665},{0,110,2665},{4,0,32},
+{4,0,32},{4,0,32},{4,0,32},{0,25,0},{0,25,0},{0,25,0},{0,12,0},{0,9,8},{0,9,8},{21,255,3971},{8,227,132},{15,161,623},{5,144,523},{0,255,9669},{0,162,4214},{0,139,1218},{0,102,5913},{0,118,11198},{0,96,6942},{33,255,3266},{16,222,1},{25,159,266},{10,143,469},{125,0,9669},{0,162,4214},{0,139,1218},{0,102,5913},{255,0,9669},{0,102,5913},{8,233,128},{8,233,128},{8,233,128},
+{8,118,128},{0,149,2178},{0,109,442},{0,109,442},{0,65,1018},{0,66,2669},{0,59,1419},{16,217,0},{16,217,0},{16,217,0},{16,114,0},{73,0,2178},{0,109,442},{0,109,442},{0,65,1018},{149,0,2178},{0,65,1018},{175,0,2665},{14,223,0},{46,155,0},{0,145,325},{175,0,2665},{254,51,2665},{0,145,325},{0,118,2665},{254,51,2665},{0,118,2665},{8,0,128},{8,0,128},{8,0,128},{8,0,128},{0,49,0},
+{0,49,0},{0,49,0},{0,24,0},{0,21,40},{0,21,40},{27,255,4603},{13,238,300},{19,171,891},{10,152,642},{6,255,9761},{0,175,3898},{0,148,882},{0,111,5645},{0,127,11511},{0,105,6861},{43,255,3390},{24,230,1},{33,167,266},{18,151,469},{137,0,9669},{0,175,3898},{0,148,882},{0,111,5645},{255,12,9669},{0,111,5645},{12,249,288},{12,249,288},{12,249,288},{12,128,288},{0,174,2178},{0,124,305},{0,124,305},
+{0,74,881},{0,75,2852},{0,68,1409},{24,225,0},{24,225,0},{24,225,0},{24,122,0},{85,0,2178},{0,124,305},{0,124,305},{0,74,881},{174,0,2178},{0,74,881},{187,0,2665},{22,231,0},{54,163,0},{0,154,250},{187,0,2665},{254,63,2665},{0,154,250},{0,126,2665},{254,63,2665},{0,126,2665},{12,0,288},{12,0,288},{12,0,288},{12,0,288},{0,73,0},{0,73,0},{0,73,0},{0,36,0},{0,30,97},
+{0,30,97},{36,255,5482},{17,251,574},{24,179,1282},{14,162,853},{15,255,10055},{0,190,3618},{0,160,569},{0,120,5354},{0,138,11902},{0,114,6807},{55,255,3569},{33,239,1},{42,176,266},{27,160,469},{150,0,9669},{0,190,3618},{0,160,569},{0,120,5354},{254,26,9669},{0,120,5354},{18,255,558},{18,255,558},{18,255,558},{16,139,545},{0,201,2178},{0,138,180},{0,138,180},{0,83,740},{0,88,3060},{0,78,1427},{33,233,0},
+{33,233,0},{33,233,0},{33,131,0},{98,0,2178},{0,138,180},{0,138,180},{0,83,740},{201,0,2178},{0,83,740},{201,0,2665},{31,240,0},{63,172,0},{0,166,180},{201,0,2665},{255,76,2665},{0,166,180},{0,135,2665},{255,76,2665},{0,135,2665},{16,0,545},{16,0,545},{16,0,545},{16,0,545},{0,101,0},{0,101,0},{0,101,0},{0,49,0},{0,39,193},{0,39,193},{43,255,6378},{24,255,915},{29,187,1710},
+{18,172,1113},{21,255,10495},{0,205,3401},{0,169,353},{0,126,5126},{0,150,12278},{0,123,6786},{64,255,3738},{41,246,2},{50,183,259},{35,168,469},{162,0,9669},{0,205,3401},{0,169,353},{0,126,5126},{254,38,9669},{0,126,5126},{24,255,914},{24,255,914},{24,255,914},{20,149,841},{0,225,2178},{0,153,97},{0,153,97},{0,93,637},{0,100,3300},{0,88,1469},{41,241,0},{41,241,0},{41,241,0},{41,139,0},{110,0,2178},
+{0,153,97},{0,153,97},{0,93,637},{225,0,2178},{0,93,637},{213,0,2665},{38,249,0},{71,180,0},{0,173,130},{213,0,2665},{254,88,2665},{0,173,130},{0,143,2665},{254,88,2665},{0,143,2665},{20,0,841},{20,0,841},{20,0,841},{20,0,841},{0,125,0},{0,125,0},{0,125,0},{0,61,0},{0,51,305},{0,51,305},{49,255,7446},{30,255,1431},{33,197,2210},{22,179,1438},{30,255,11102},{0,218,3189},{0,182,185},
+{0,136,4909},{0,162,12686},{0,130,6797},{73,255,3925},{49,254,2},{57,193,258},{43,176,469},{174,0,9669},{0,218,3189},{0,182,185},{0,136,4909},{255,49,9669},{0,136,4909},{27,255,1382},{27,255,1382},{27,255,1382},{24,159,1201},{0,249,2178},{0,168,40},{0,168,40},{0,102,530},{0,109,3565},{0,94,1537},{49,249,0},{49,249,0},{49,249,0},{49,147,0},{122,0,2178},{0,168,40},{0,168,40},{0,102,530},{249,0,2178},
+{0,102,530},{224,0,2665},{46,255,1},{79,188,0},{0,182,85},{224,0,2665},{254,100,2665},{0,182,85},{0,151,2665},{254,100,2665},{0,151,2665},{24,0,1201},{24,0,1201},{24,0,1201},{24,0,1201},{0,149,0},{0,149,0},{0,149,0},{0,73,0},{0,60,442},{0,60,442},{55,255,8658},{36,255,2131},{38,205,2786},{27,188,1837},{36,255,11866},{0,230,3029},{0,191,75},{0,145,4685},{0,172,13066},{0,139,6826},{86,255,4118},
+{58,255,26},{65,201,258},{51,184,469},{186,0,9669},{0,230,3029},{0,191,75},{0,145,4685},{255,61,9669},{0,145,4685},{33,255,1954},{33,255,1954},{33,255,1954},{28,169,1625},{3,255,2219},{0,181,5},{0,181,5},{0,111,433},{0,121,3861},{0,103,1633},{57,254,1},{57,254,1},{57,254,1},{57,155,0},{134,0,2178},{0,181,5},{0,181,5},{0,111,433},{255,9,2178},{0,111,433},{236,0,2665},{61,255,20},{87,196,0},
+{0,191,50},{236,0,2665},{254,112,2665},{0,191,50},{0,159,2665},{254,112,2665},{0,159,2665},{28,0,1625},{28,0,1625},{28,0,1625},{28,0,1625},{0,174,0},{0,174,0},{0,174,0},{0,85,0},{0,69,605},{0,69,605},{61,255,10195},{43,255,3100},{43,216,3523},{31,198,2356},{43,255,12883},{0,245,2885},{0,203,20},{0,157,4450},{0,184,13589},{0,148,6898},{95,255,4346},{70,255,117},{74,210,258},{60,193,469},{199,0,9669},
+{0,245,2885},{0,203,20},{0,157,4450},{254,75,9669},{0,157,4450},{39,255,2734},{39,255,2734},{39,255,2734},{33,180,2178},{12,255,2420},{1,196,2},{1,196,2},{0,123,337},{0,132,4227},{0,112,1777},{67,255,10},{67,255,10},{67,255,10},{66,164,0},{147,0,2178},{4,194,0},{4,194,0},{0,123,337},{254,23,2178},{0,123,337},{250,0,2665},{76,255,73},{96,205,0},{0,203,20},{250,0,2665},{255,125,2665},{0,203,20},
+{0,168,2665},{255,125,2665},{0,168,2665},{33,0,2178},{33,0,2178},{33,0,2178},{33,0,2178},{0,201,0},{0,201,0},{0,201,0},{0,98,0},{0,81,820},{0,81,820},{67,255,11582},{49,255,4083},{48,224,4162},{36,206,2818},{49,255,13898},{1,255,2805},{2,212,20},{0,163,4255},{0,196,13958},{0,157,6886},{104,255,4577},{79,255,259},{82,218,258},{68,201,469},{211,0,9669},{1,255,2805},{4,211,17},{0,163,4254},{255,86,9669},
+{0,163,4254},{46,255,3434},{46,255,3434},{46,255,3434},{37,190,2665},{18,255,2709},{3,210,17},{3,210,17},{0,130,270},{0,141,4491},{0,121,1854},{76,255,29},{76,255,29},{76,255,29},{74,172,0},{159,0,2178},{12,202,0},{12,202,0},{0,130,269},{254,35,2178},{0,130,269},{255,13,2665},{92,255,157},{104,213,0},{0,212,5},{255,13,2665},{254,137,2665},{0,212,5},{0,176,2665},{254,137,2665},{0,176,2665},{37,0,2665},
+{37,0,2665},{37,0,2665},{37,0,2665},{1,223,0},{1,223,0},{1,223,0},{1,110,0},{0,91,953},{0,91,953},{79,255,12086},{58,255,4502},{56,232,4162},{44,214,2818},{61,255,14298},{10,255,2910},{10,220,20},{0,173,4166},{0,208,13470},{0,166,6215},{113,255,4826},{89,255,465},{90,226,258},{78,208,474},{223,0,9669},{10,255,2909},{12,219,17},{0,173,4085},{255,98,9669},{0,173,4085},{55,255,3574},{55,255,3574},{55,255,3574},
+{46,197,2665},{27,255,2840},{11,218,17},{11,218,17},{4,140,258},{0,156,4142},{0,133,1430},{86,255,52},{86,255,52},{86,255,52},{82,180,0},{171,0,2178},{20,210,0},{20,210,0},{0,139,202},{255,46,2178},{0,139,202},{255,37,2665},{107,255,260},{112,221,0},{0,220,1},{255,37,2665},{254,149,2665},{0,220,1},{0,184,2665},{254,149,2665},{0,184,2665},{45,0,2665},{45,0,2665},{45,0,2665},{45,0,2665},{9,231,0},
+{9,231,0},{9,231,0},{9,118,0},{0,103,745},{0,103,745},{86,255,12542},{67,255,4983},{64,240,4162},{52,222,2818},{70,255,14719},{22,255,3118},{18,228,20},{5,181,4162},{0,221,12955},{0,176,5593},{125,255,5090},{101,255,713},{98,234,258},{84,218,481},{235,0,9669},{28,255,3073},{20,227,17},{0,182,3909},{255,110,9669},{0,182,3909},{64,255,3726},{64,255,3726},{64,255,3726},{54,205,2665},{36,255,2989},{19,226,17},{19,226,17},
+{12,148,258},{0,172,3797},{0,142,1062},{95,255,89},{95,255,89},{95,255,89},{90,188,0},{183,0,2178},{28,218,0},{28,218,0},{0,148,145},{255,58,2178},{0,148,145},{255,61,2665},{119,255,388},{120,229,0},{5,229,0},{255,61,2665},{254,161,2665},{5,229,0},{0,192,2665},{254,161,2665},{0,192,2665},{53,0,2665},{53,0,2665},{53,0,2665},{53,0,2665},{17,239,0},{17,239,0},{17,239,0},{17,126,0},{0,118,562},
+{0,118,562},{98,255,13154},{79,255,5593},{73,249,4162},{61,231,2818},{86,255,15194},{34,255,3462},{27,237,20},{14,190,4162},{0,236,12478},{0,188,4983},{135,255,5365},{113,255,1062},{107,243,258},{93,227,481},{248,0,9669},{40,255,3330},{29,236,17},{0,191,3726},{254,124,9669},{0,191,3726},{73,255,3909},{73,255,3909},{73,255,3909},{63,214,2665},{46,255,3156},{28,235,17},{28,235,17},{21,157,258},{0,184,3462},{0,154,713},{107,255,145},
+{107,255,145},{107,255,145},{99,197,0},{196,0,2178},{37,227,0},{37,227,0},{0,160,89},{254,72,2178},{0,160,89},{255,89,2665},{137,255,562},{129,238,0},{14,238,0},{255,89,2665},{254,174,2665},{14,238,0},{0,201,2665},{254,174,2665},{0,201,2665},{62,0,2665},{62,0,2665},{62,0,2665},{62,0,2665},{26,248,0},{26,248,0},{26,248,0},{26,135,0},{0,135,388},{0,135,388},{107,255,13718},{89,255,6215},{82,255,4166},
+{69,239,2818},{92,255,15614},{46,255,3885},{35,245,20},{22,198,4162},{0,248,12086},{0,197,4502},{144,255,5658},{122,255,1430},{115,251,258},{101,235,481},{255,10,9669},{61,255,3601},{37,244,17},{0,200,3574},{255,135,9669},{0,200,3574},{82,255,4085},{82,255,4085},{82,255,4085},{71,222,2665},{58,255,3332},{36,242,17},{36,242,17},{29,165,258},{0,196,3206},{0,163,465},{116,255,202},{116,255,202},{116,255,202},{107,205,0},{208,0,2178},
+{44,235,0},{44,235,0},{0,169,52},{254,84,2178},{0,169,52},{255,113,2665},{152,255,745},{137,246,0},{22,246,0},{255,113,2665},{254,186,2665},{22,246,0},{0,209,2665},{254,186,2665},{0,209,2665},{70,0,2665},{70,0,2665},{70,0,2665},{70,0,2665},{34,253,1},{34,253,1},{34,253,1},{34,143,0},{0,147,260},{0,147,260},{116,255,14302},{98,255,6886},{89,255,4255},{77,247,2818},{104,255,16094},{55,255,4382},{43,253,20},
+{30,206,4162},{0,254,11806},{0,206,4083},{153,255,5969},{134,255,1854},{125,255,270},{109,243,481},{255,34,9669},{76,255,3905},{45,252,17},{0,209,3434},{255,147,9669},{0,209,3434},{89,255,4254},{89,255,4254},{89,255,4254},{79,230,2665},{67,255,3525},{44,250,17},{44,250,17},{37,173,258},{0,211,2979},{0,176,259},{125,255,269},{125,255,269},{125,255,269},{115,213,0},{220,0,2178},{52,243,0},{52,243,0},{0,179,29},{255,95,2178},
+{0,179,29},{255,137,2665},{164,255,953},{145,254,0},{30,254,0},{255,137,2665},{254,198,2665},{30,254,0},{0,217,2665},{254,198,2665},{0,217,2665},{78,0,2665},{78,0,2665},{78,0,2665},{78,0,2665},{43,255,5},{43,255,5},{43,255,5},{42,150,0},{0,162,157},{0,162,157},{122,255,13635},{107,255,6898},{98,255,4450},{86,250,2739},{110,255,15195},{67,255,4071},{52,255,20},{39,212,3523},{1,255,10735},{0,212,3100},{162,255,5381},
+{143,255,1777},{132,255,337},{118,246,331},{255,52,8712},{82,255,3492},{59,254,2},{0,216,2734},{255,156,8712},{0,216,2734},{98,255,4450},{98,255,4450},{98,255,4450},{87,238,2665},{76,255,3736},{52,255,20},{52,255,20},{45,181,258},{0,224,2757},{0,185,117},{132,255,337},{132,255,337},{132,255,337},{123,221,0},{232,0,2178},{60,251,0},{60,251,0},{0,188,10},{255,107,2178},{0,188,10},{255,152,2178},{174,255,820},{156,255,0},
+{52,255,0},{255,152,2178},{255,205,2178},{52,255,0},{0,222,2178},{255,205,2178},{0,222,2178},{86,0,2665},{86,0,2665},{86,0,2665},{86,0,2665},{52,255,20},{52,255,20},{52,255,20},{50,158,0},{0,178,73},{0,178,73},{132,255,12678},{116,255,6826},{110,255,4685},{95,253,2678},{119,255,14061},{76,255,3663},{64,255,75},{49,216,2786},{10,255,9739},{0,219,2131},{172,255,4629},{152,255,1633},{144,255,433},{129,248,179},{255,70,7578},
+{101,255,2949},{73,255,5},{0,222,1954},{255,165,7578},{0,222,1954},{110,255,4685},{110,255,4685},{110,255,4685},{96,247,2665},{89,255,3960},{64,255,75},{64,255,75},{54,190,258},{0,239,2571},{0,197,26},{144,255,433},{144,255,433},{144,255,433},{132,230,0},{245,0,2178},{73,255,5},{73,255,5},{0,197,1},{254,121,2178},{0,197,1},{255,164,1625},{186,255,605},{170,255,0},{79,255,0},{255,164,1625},{255,211,1625},{79,255,0},
+{0,226,1625},{255,211,1625},{0,226,1625},{95,0,2665},{95,0,2665},{95,0,2665},{95,0,2665},{64,255,50},{64,255,50},{64,255,50},{59,167,0},{0,193,20},{0,193,20},{138,255,11970},{125,255,6797},{119,255,4909},{104,255,2665},{129,255,13086},{82,255,3411},{73,255,185},{57,221,2210},{22,255,8987},{0,225,1431},{178,255,4049},{161,255,1537},{153,255,530},{137,250,83},{255,86,6661},{113,255,2525},{86,255,40},{0,225,1382},{255,172,6661},
+{0,225,1382},{119,255,4909},{119,255,4909},{119,255,4909},{104,255,2665},{98,255,4197},{73,255,185},{73,255,185},{62,198,258},{0,251,2435},{1,206,2},{153,255,530},{153,255,530},{153,255,530},{140,238,0},{255,4,2178},{86,255,40},{86,255,40},{4,206,0},{255,132,2178},{4,206,0},{255,177,1201},{195,255,442},{181,255,0},{104,255,0},{255,177,1201},{254,217,1201},{104,255,0},{0,230,1201},{254,217,1201},{0,230,1201},{103,0,2665},
+{103,0,2665},{103,0,2665},{103,0,2665},{73,255,85},{73,255,85},{73,255,85},{67,175,0},{0,208,1},{0,208,1},{147,255,11330},{132,255,6786},{129,255,5126},{113,255,2694},{135,255,12250},{95,255,3225},{86,255,353},{67,225,1710},{37,255,8326},{0,231,915},{184,255,3541},{167,255,1469},{162,255,637},{146,253,24},{255,104,5829},{125,255,2165},{101,255,97},{0,231,914},{255,181,5829},{0,231,914},{129,255,5126},{129,255,5126},{129,255,5126},
+{113,255,2694},{107,255,4452},{86,255,353},{86,255,353},{72,205,259},{1,255,2421},{9,214,2},{162,255,637},{162,255,637},{162,255,637},{148,245,0},{255,28,2178},{101,255,97},{101,255,97},{12,214,0},{255,144,2178},{12,214,0},{255,189,841},{204,255,305},{193,255,0},{128,255,0},{255,189,841},{254,223,841},{128,255,0},{0,234,841},{254,223,841},{0,234,841},{111,0,2665},{111,0,2665},{111,0,2665},{111,0,2665},{82,255,130},
+{82,255,130},{82,255,130},{75,183,0},{6,217,0},{6,217,0},{153,255,10758},{141,255,6807},{135,255,5354},{122,255,2777},{144,255,11503},{104,255,3102},{95,255,569},{75,230,1282},{49,255,7825},{3,237,574},{190,255,3105},{177,255,1427},{172,255,740},{156,254,1},{255,119,5082},{137,255,1869},{116,255,180},{0,237,558},{254,189,5082},{0,237,558},{135,255,5354},{135,255,5354},{135,255,5354},{122,255,2777},{119,255,4724},{95,255,569},{95,255,569},
+{79,213,266},{16,255,2587},{16,222,1},{172,255,740},{172,255,740},{172,255,740},{156,253,0},{255,52,2178},{116,255,180},{116,255,180},{20,222,0},{255,156,2178},{20,222,0},{255,201,545},{216,255,193},{205,255,0},{152,255,0},{255,201,545},{254,229,545},{152,255,0},{0,238,545},{254,229,545},{0,238,545},{119,0,2665},{119,0,2665},{119,0,2665},{119,0,2665},{89,255,180},{89,255,180},{89,255,180},{83,191,0},{15,224,0},
+{15,224,0},{162,255,10197},{150,255,6861},{144,255,5645},{131,255,2933},{153,255,10765},{116,255,3051},{107,255,882},{84,236,891},{64,255,7297},{17,242,300},{199,255,2694},{186,255,1409},{181,255,881},{167,255,20},{255,137,4344},{152,255,1611},{131,255,305},{4,243,288},{254,198,4344},{4,243,288},{144,255,5645},{144,255,5645},{144,255,5645},{131,255,2933},{129,255,5005},{107,255,882},{107,255,882},{88,222,266},{34,255,2824},{25,231,1},{181,255,881},
+{181,255,881},{181,255,881},{167,255,20},{255,79,2178},{131,255,305},{131,255,305},{28,231,0},{253,170,2178},{28,231,0},{255,216,288},{225,255,97},{218,255,0},{180,255,0},{255,216,288},{255,236,288},{180,255,0},{0,243,288},{255,236,288},{0,243,288},{128,0,2665},{128,0,2665},{128,0,2665},{128,0,2665},{101,255,250},{101,255,250},{101,255,250},{92,200,0},{24,233,0},{24,233,0},{172,255,9731},{159,255,6942},{153,255,5913},
+{140,255,3130},{162,255,10204},{125,255,3090},{116,255,1218},{94,240,623},{79,255,6924},{27,246,132},{205,255,2402},{196,255,1419},{190,255,1018},{177,255,97},{255,152,3779},{164,255,1451},{146,255,442},{20,247,128},{255,205,3779},{20,247,128},{153,255,5913},{153,255,5913},{153,255,5913},{140,255,3130},{138,255,5304},{116,255,1218},{116,255,1218},{96,230,266},{49,255,3115},{33,239,1},{190,255,1018},{190,255,1018},{190,255,1018},{177,255,97},{255,104,2178},
+{146,255,442},{146,255,442},{36,239,0},{255,181,2178},{36,239,0},{255,228,128},{234,255,40},{230,255,0},{204,255,0},{255,228,128},{255,242,128},{204,255,0},{0,247,128},{255,242,128},{0,247,128},{136,0,2665},{136,0,2665},{136,0,2665},{136,0,2665},{110,255,325},{110,255,325},{110,255,325},{100,208,0},{32,241,0},{32,241,0},{175,255,9359},{165,255,7050},{162,255,6193},{149,255,3381},{172,255,9691},{134,255,3207},{128,255,1610},
+{102,245,429},{92,255,6719},{38,251,32},{215,255,2156},{205,255,1457},{199,255,1165},{186,255,221},{255,171,3299},{177,255,1398},{161,255,605},{36,251,32},{254,214,3299},{36,251,32},{162,255,6193},{162,255,6193},{162,255,6193},{149,255,3381},{147,255,5621},{128,255,1610},{128,255,1610},{104,238,266},{67,255,3419},{41,247,2},{199,255,1165},{199,255,1165},{199,255,1165},{186,255,221},{255,128,2178},{161,255,605},{161,255,605},{44,247,0},{255,193,2178},
+{44,247,0},{255,240,32},{246,255,8},{242,255,0},{228,255,0},{255,240,32},{255,248,32},{228,255,0},{0,251,32},{255,248,32},{0,251,32},{144,0,2665},{144,0,2665},{144,0,2665},{144,0,2665},{119,255,410},{119,255,410},{119,255,410},{108,216,0},{39,250,0},{39,250,0},{184,255,9067},{175,255,7162},{172,255,6450},{158,255,3686},{175,255,9268},{146,255,3399},{137,255,2054},{110,250,311},{107,255,6532},{49,255,2},{221,255,1992},
+{211,255,1521},{208,255,1322},{195,255,397},{255,186,2904},{189,255,1366},{174,255,820},{52,255,0},{255,221,2904},{52,255,0},{172,255,6450},{172,255,6450},{172,255,6450},{158,255,3686},{159,255,5949},{137,255,2054},{137,255,2054},{112,246,266},{82,255,3765},{49,255,2},{208,255,1322},{208,255,1322},{208,255,1322},{195,255,397},{255,152,2178},{174,255,820},{174,255,820},{52,255,0},{255,205,2178},{52,255,0},{255,252,0},{255,254,0},{254,255,0},
+{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{152,0,2665},{152,0,2665},{152,0,2665},{152,0,2665},{129,255,493},{129,255,493},{129,255,493},{116,224,0},{49,255,2},{49,255,2},{190,255,7987},{181,255,6402},{178,255,5810},{167,255,3509},{184,255,7999},{155,255,3048},{146,255,1922},{121,252,155},{119,255,5562},{64,255,29},{224,255,1476},{218,255,1120},{215,255,965},{204,255,292},{255,195,2166},
+{198,255,1009},{186,255,605},{79,255,0},{254,226,2166},{79,255,0},{178,255,5810},{178,255,5810},{178,255,5810},{167,255,3509},{165,255,5209},{146,255,1922},{146,255,1922},{121,249,133},{95,255,3258},{64,255,29},{215,255,965},{215,255,965},{215,255,965},{204,255,292},{255,164,1625},{186,255,605},{186,255,605},{79,255,0},{255,211,1625},{79,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},
+{0,255,0},{255,254,0},{0,255,0},{161,0,2665},{161,0,2665},{161,0,2665},{161,0,2665},{138,255,610},{138,255,610},{138,255,610},{125,233,0},{64,255,29},{64,255,29},{196,255,7111},{187,255,5786},{184,255,5294},{174,255,3381},{187,255,6982},{161,255,2780},{155,255,1832},{131,253,61},{128,255,4795},{79,255,80},{230,255,1088},{224,255,824},{221,255,709},{210,255,212},{255,204,1601},{204,255,737},{195,255,442},{104,255,0},{255,230,1601},
+{104,255,0},{184,255,5294},{184,255,5294},{184,255,5294},{174,255,3381},{172,255,4582},{155,255,1832},{155,255,1832},{132,251,53},{107,255,2834},{79,255,80},{221,255,709},{221,255,709},{221,255,709},{210,255,212},{255,177,1201},{195,255,442},{195,255,442},{104,255,0},{254,217,1201},{104,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{169,0,2665},
+{169,0,2665},{169,0,2665},{169,0,2665},{147,255,725},{147,255,725},{147,255,725},{133,241,0},{79,255,80},{79,255,80},{202,255,6315},{193,255,5226},{190,255,4826},{180,255,3253},{193,255,6066},{167,255,2568},{164,255,1770},{141,254,11},{137,255,4122},{92,255,169},{233,255,753},{227,255,574},{227,255,493},{219,255,146},{255,210,1121},{213,255,507},{204,255,305},{128,255,0},{255,233,1121},{128,255,0},{190,255,4826},{190,255,4826},{190,255,4826},
+{180,255,3253},{181,255,4065},{164,255,1770},{164,255,1770},{140,253,9},{119,255,2474},{92,255,169},{227,255,493},{227,255,493},{227,255,493},{219,255,146},{255,189,841},{204,255,305},{204,255,305},{128,255,0},{254,223,841},{128,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{177,0,2665},{177,0,2665},{177,0,2665},{177,0,2665},{156,255,850},
+{156,255,850},{156,255,850},{141,249,0},{92,255,169},{92,255,169},{208,255,5599},{199,255,4722},{199,255,4398},{189,255,3130},{199,255,5254},{177,255,2395},{171,255,1742},{149,255,1},{149,255,3538},{107,255,274},{236,255,484},{233,255,366},{233,255,317},{225,255,90},{255,219,726},{222,255,321},{216,255,193},{152,255,0},{254,238,726},{152,255,0},{199,255,4398},{199,255,4398},{199,255,4398},{189,255,3130},{187,255,3613},{171,255,1742},{171,255,1742},
+{149,255,1},{131,255,2178},{107,255,274},{233,255,317},{233,255,317},{233,255,317},{225,255,90},{255,201,545},{216,255,193},{216,255,193},{152,255,0},{254,229,545},{152,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{185,0,2665},{185,0,2665},{185,0,2665},{185,0,2665},{165,255,985},{165,255,985},{165,255,985},{149,255,1},{107,255,274},
+{107,255,274},{43,255,50657},{1,255,1974},{0,182,128},{0,176,4572},{36,255,59540},{0,242,19268},{0,176,7306},{0,160,23941},{0,187,65535},{0,148,40590},{21,255,10267},{0,248,1412},{0,179,137},{0,148,3929},{115,0,18065},{0,153,12036},{0,139,6077},{0,93,14060},{234,0,18065},{0,93,14060},{0,143,0},{0,143,0},{0,143,0},{0,70,0},{0,70,1105},{0,57,405},{0,57,405},{0,34,653},{0,33,1209},{0,31,756},{0,143,0},
+{0,143,0},{0,143,0},{0,70,0},{35,0,1105},{0,57,405},{0,57,405},{0,34,653},{70,0,1105},{0,34,653},{171,0,9248},{0,248,1412},{0,179,137},{0,148,3929},{171,0,9248},{255,46,9248},{0,148,3929},{0,115,9248},{255,46,9248},{0,115,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{43,255,53600},{4,255,2885},{0,191,38},
+{0,185,3941},{43,255,62123},{0,254,18376},{0,182,6726},{0,169,23131},{0,196,65535},{0,154,40086},{27,255,10859},{0,254,1184},{0,188,45},{0,157,3656},{122,0,19334},{0,162,12449},{0,145,6089},{0,102,14754},{249,0,19334},{0,102,14754},{0,167,0},{0,167,0},{0,167,0},{0,82,0},{0,82,1513},{0,66,562},{0,66,562},{0,37,900},{0,36,1658},{0,37,1044},{0,167,0},{0,167,0},{0,167,0},{0,82,0},{41,0,1513},
+{0,66,562},{0,66,562},{0,37,900},{82,0,1513},{0,37,900},{183,0,9248},{0,254,1184},{0,188,45},{0,157,3656},{183,0,9248},{255,58,9248},{0,157,3656},{0,123,9248},{255,58,9248},{0,123,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{46,255,56765},{7,255,4404},{0,199,3},{0,194,3404},{43,255,64774},{1,255,17986},{0,191,6229},
+{0,176,22449},{0,215,65535},{0,160,39678},{33,255,11587},{1,255,1171},{0,199,4},{0,166,3393},{129,0,20689},{0,172,12834},{0,154,6125},{0,108,15490},{254,5,20689},{0,108,15490},{0,192,0},{0,192,0},{0,192,0},{0,94,0},{0,95,1985},{0,75,745},{0,75,745},{0,44,1202},{0,42,2178},{0,40,1374},{0,192,0},{0,192,0},{0,192,0},{0,94,0},{46,0,1985},{0,75,745},{0,75,745},{0,44,1202},{95,0,1985},
+{0,44,1202},{195,0,9248},{1,255,1170},{0,199,4},{0,166,3393},{195,0,9248},{255,70,9248},{0,166,3393},{0,131,9248},{255,70,9248},{0,131,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{49,255,58131},{7,255,6200},{0,207,6},{0,203,2858},{46,255,65535},{1,255,17772},{0,200,5638},{0,182,21148},{0,215,63337},{0,166,38166},{43,255,12449},
+{1,255,1395},{1,208,6},{0,176,3170},{138,0,22129},{0,184,13298},{0,163,6189},{0,114,16274},{254,14,22129},{0,114,16274},{0,216,0},{0,216,0},{0,216,0},{0,106,0},{0,107,2521},{0,88,928},{0,88,928},{0,50,1530},{0,48,2770},{0,47,1762},{0,216,0},{0,216,0},{0,216,0},{0,106,0},{52,0,2521},{0,88,928},{0,88,928},{0,50,1530},{107,0,2521},{0,50,1530},{207,0,9248},{7,255,1378},{5,207,0},
+{0,176,3170},{207,0,9248},{255,82,9248},{0,176,3170},{0,139,9248},{255,82,9248},{0,139,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{55,255,58853},{10,255,8410},{0,216,47},{0,212,2312},{52,255,65535},{4,255,18024},{0,209,5015},{0,191,19619},{0,224,60697},{0,176,36050},{46,255,13542},{7,255,1877},{4,217,53},{0,185,2897},{147,0,23851},
+{0,196,13856},{0,173,6281},{0,120,17216},{254,23,23851},{0,120,17216},{0,243,0},{0,243,0},{0,243,0},{0,119,0},{0,122,3200},{0,97,1186},{0,97,1186},{0,56,1945},{0,54,3521},{0,53,2243},{0,243,0},{0,243,0},{0,243,0},{0,119,0},{60,0,3200},{0,97,1186},{0,97,1186},{0,56,1945},{122,0,3200},{0,56,1945},{220,0,9248},{22,255,1693},{14,216,0},{0,185,2897},{220,0,9248},{255,95,9248},{0,185,2897},
+{0,148,9248},{255,95,9248},{0,148,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{58,255,59395},{13,255,10486},{0,225,107},{0,219,1933},{55,255,65535},{7,255,18658},{0,215,4619},{0,200,18436},{0,233,58566},{0,182,34489},{52,255,14690},{13,255,2489},{6,228,133},{0,194,2664},{155,0,25472},{0,208,14384},{0,182,6401},{0,126,18104},{255,30,25472},
+{0,126,18104},{0,255,16},{0,255,16},{0,255,16},{0,131,0},{0,134,3872},{0,106,1445},{0,106,1445},{0,62,2357},{0,60,4265},{0,56,2717},{2,254,13},{2,254,13},{2,254,13},{0,131,0},{66,0,3872},{0,106,1445},{0,106,1445},{0,62,2357},{134,0,3872},{0,62,2357},{232,0,9248},{37,255,2000},{22,224,0},{0,194,2664},{232,0,9248},{255,107,9248},{0,194,2664},{0,156,9248},{255,107,9248},{0,156,9248},{0,0,0},
+{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{61,255,59976},{16,255,12621},{2,233,174},{0,228,1613},{58,255,65535},{10,255,19459},{0,224,4093},{0,206,17181},{0,242,56514},{0,188,32973},{58,255,15746},{19,255,3205},{10,235,217},{0,206,2444},{164,0,26744},{0,218,14587},{0,191,6305},{0,136,18737},{255,39,26744},{0,136,18737},{3,255,110},{3,255,110},{3,255,110},
+{1,142,2},{0,149,4418},{0,118,1585},{0,118,1585},{0,68,2633},{0,66,4909},{0,62,3077},{6,255,80},{6,255,80},{6,255,80},{2,142,0},{73,0,4418},{0,118,1585},{0,118,1585},{0,68,2633},{149,0,4418},{0,68,2633},{244,0,9248},{49,255,2377},{30,232,0},{0,206,2440},{244,0,9248},{255,119,9248},{0,206,2440},{0,164,9248},{255,119,9248},{0,164,9248},{1,0,2},{1,0,2},{1,0,2},{1,0,2},{0,7,0},
+{0,7,0},{0,7,0},{0,3,0},{0,3,0},{0,3,0},{67,255,60796},{19,255,14846},{3,240,286},{0,234,1405},{64,255,65535},{13,255,20226},{0,233,3321},{0,212,15538},{0,254,54317},{0,197,31240},{67,255,16195},{31,255,3805},{18,243,217},{0,212,2328},{175,0,26744},{0,230,14051},{0,200,5525},{0,142,18273},{254,51,26744},{0,142,18273},{9,255,278},{9,255,278},{9,255,278},{5,152,50},{0,174,4418},{0,129,1313},{0,129,1313},
+{0,77,2410},{0,75,5092},{0,71,2987},{15,255,125},{15,255,125},{15,255,125},{10,150,0},{85,0,4418},{0,129,1313},{0,129,1313},{0,77,2410},{174,0,4418},{0,77,2410},{255,1,9248},{64,255,2738},{37,240,0},{0,212,2228},{255,1,9248},{254,131,9248},{0,212,2228},{0,172,9248},{254,131,9248},{0,172,9248},{5,0,50},{5,0,50},{5,0,50},{5,0,50},{0,31,0},{0,31,0},{0,31,0},{0,15,0},{0,12,13},
+{0,12,13},{70,255,61549},{25,255,17357},{4,250,459},{1,244,1256},{70,255,65535},{16,255,21346},{0,242,2603},{0,225,13862},{0,254,52221},{0,206,29474},{79,255,16720},{43,255,4545},{27,252,217},{7,223,2341},{189,0,26744},{0,245,13481},{0,212,4710},{0,154,17762},{255,64,26744},{0,154,17762},{15,255,602},{15,255,602},{15,255,602},{10,163,181},{0,201,4418},{0,147,1037},{0,147,1037},{0,83,2196},{0,88,5300},{0,80,2921},{27,255,185},
+{27,255,185},{27,255,185},{19,159,0},{98,0,4418},{0,147,1037},{0,147,1037},{0,83,2196},{201,0,4418},{0,83,2196},{255,28,9248},{82,255,3176},{46,249,0},{0,225,2020},{255,28,9248},{255,144,9248},{0,225,2020},{0,181,9248},{255,144,9248},{0,181,9248},{9,0,181},{9,0,181},{9,0,181},{9,0,181},{0,58,0},{0,58,0},{0,58,0},{0,29,0},{0,24,58},{0,24,58},{73,255,62082},{28,255,19099},{6,255,688},
+{2,251,1170},{73,255,65535},{19,255,22086},{0,248,2054},{0,231,12530},{0,254,51038},{0,212,28165},{86,255,16691},{52,255,4985},{36,255,250},{14,230,2238},{199,0,26259},{0,254,12692},{0,221,3965},{0,160,16946},{254,75,26259},{0,160,16946},{21,255,1006},{21,255,1006},{21,255,1006},{14,173,365},{0,225,4418},{0,162,820},{0,162,820},{0,96,1994},{0,100,5540},{0,90,2891},{36,255,250},{36,255,250},{36,255,250},{27,167,0},{110,0,4418},
+{0,162,820},{0,162,820},{0,96,1994},{225,0,4418},{0,96,1994},{255,49,8978},{95,255,3433},{55,255,0},{0,231,1732},{255,49,8978},{254,155,8978},{0,231,1732},{0,188,8978},{254,155,8978},{0,188,8978},{13,0,365},{13,0,365},{13,0,365},{13,0,365},{0,82,0},{0,82,0},{0,82,0},{0,41,0},{0,33,125},{0,33,125},{76,255,62399},{28,255,19454},{6,255,1075},{2,251,1090},{73,255,65535},{19,255,21590},{0,250,1503},
+{0,231,11251},{0,254,50424},{0,212,27242},{95,255,15410},{58,255,4661},{46,255,317},{24,231,1853},{208,0,24371},{0,254,11124},{0,227,2881},{0,166,15066},{254,84,24371},{0,166,15066},{27,255,1522},{27,255,1522},{27,255,1522},{17,183,613},{0,249,4418},{0,175,605},{0,175,605},{0,105,1801},{0,109,5805},{0,97,2885},{46,255,317},{46,255,317},{46,255,317},{35,175,0},{122,0,4418},{0,175,605},{0,175,605},{0,105,1801},{249,0,4418},
+{0,105,1801},{255,61,7938},{104,255,3026},{67,255,0},{0,237,1224},{255,61,7938},{254,161,7938},{0,237,1224},{0,192,7938},{254,161,7938},{0,192,7938},{17,0,613},{17,0,613},{17,0,613},{17,0,613},{0,107,0},{0,107,0},{0,107,0},{0,52,0},{0,42,218},{0,42,218},{76,255,62711},{28,255,19886},{9,255,1549},{3,252,1093},{73,255,65535},{19,255,21152},{0,251,1032},{0,234,10008},{0,254,49821},{0,212,26360},{101,255,14198},
+{67,255,4361},{55,255,400},{33,234,1502},{215,0,22568},{1,255,9795},{0,230,1973},{0,169,13320},{254,91,22568},{0,169,13320},{33,255,2150},{33,255,2150},{33,255,2150},{21,193,925},{3,255,4459},{0,190,442},{0,190,442},{0,114,1618},{0,121,6101},{0,106,2901},{55,255,400},{55,255,400},{55,255,400},{43,183,0},{134,0,4418},{0,190,442},{0,190,442},{0,114,1618},{255,9,4418},{0,114,1618},{255,73,6962},{113,255,2645},{79,255,0},
+{0,240,801},{255,73,6962},{254,167,6962},{0,240,801},{0,196,6962},{254,167,6962},{0,196,6962},{21,0,925},{21,0,925},{21,0,925},{21,0,925},{0,131,0},{0,131,0},{0,131,0},{0,64,0},{0,51,337},{0,51,337},{76,255,63078},{31,255,20439},{9,255,2192},{4,253,1202},{76,255,65535},{19,255,20732},{0,251,606},{0,234,8676},{0,254,49164},{0,212,25424},{110,255,12917},{79,255,4059},{64,255,505},{43,234,1147},{224,0,20642},
+{1,255,8589},{0,236,1155},{0,179,11489},{254,100,20642},{0,179,11489},{39,255,2986},{39,255,2986},{39,255,2986},{26,204,1352},{12,255,4660},{0,205,289},{0,205,289},{0,126,1424},{0,132,6467},{0,115,2955},{64,255,505},{64,255,505},{64,255,505},{52,192,0},{147,0,4418},{0,205,289},{0,205,289},{0,126,1424},{254,23,4418},{0,126,1424},{255,86,5941},{125,255,2248},{92,255,0},{0,243,433},{255,86,5941},{255,172,5941},{0,243,433},
+{0,200,5941},{255,172,5941},{0,200,5941},{26,0,1352},{26,0,1352},{26,0,1352},{26,0,1352},{0,158,0},{0,158,0},{0,158,0},{0,78,0},{0,63,500},{0,63,500},{79,255,63411},{31,255,21008},{12,255,2858},{7,253,1393},{76,255,65535},{22,255,20416},{0,253,320},{0,237,7549},{0,254,48613},{0,218,24643},{116,255,11849},{82,255,3845},{73,255,610},{53,238,867},{232,0,19021},{10,255,7741},{0,242,611},{0,182,9957},{255,107,19021},
+{0,182,9957},{43,255,3819},{43,255,3819},{43,255,3819},{30,214,1800},{15,255,4981},{0,221,169},{0,221,169},{0,133,1282},{0,141,6822},{0,124,3029},{73,255,610},{73,255,610},{73,255,610},{60,200,0},{159,0,4418},{0,221,169},{0,221,169},{0,133,1282},{254,35,4418},{0,133,1282},{255,98,5101},{134,255,1921},{104,255,0},{0,246,202},{255,98,5101},{255,178,5101},{0,246,202},{0,204,5101},{255,178,5101},{0,204,5101},{30,0,1800},
+{30,0,1800},{30,0,1800},{30,0,1800},{0,183,0},{0,183,0},{0,183,0},{0,89,0},{0,72,673},{0,72,673},{86,255,63733},{34,255,21637},{12,255,3614},{8,254,1668},{76,255,65535},{22,255,20164},{0,254,123},{0,237,6489},{0,254,48082},{0,218,23857},{122,255,10853},{95,255,3629},{86,255,724},{62,241,632},{241,0,17485},{22,255,6965},{0,248,243},{0,188,8529},{255,116,17485},{0,188,8529},{49,255,4787},{49,255,4787},{49,255,4787},
+{34,224,2312},{21,255,5437},{0,233,89},{0,233,89},{0,142,1129},{0,153,7206},{0,133,3131},{86,255,724},{86,255,724},{86,255,724},{68,207,0},{171,0,4418},{0,233,89},{0,233,89},{0,142,1129},{255,46,4418},{0,142,1129},{255,110,4325},{143,255,1620},{116,255,0},{0,252,58},{255,110,4325},{255,184,4325},{0,252,58},{0,208,4325},{255,184,4325},{0,208,4325},{34,0,2312},{34,0,2312},{34,0,2312},{34,0,2312},{0,207,0},
+{0,207,0},{0,207,0},{0,101,0},{0,88,865},{0,88,865},{86,255,63992},{34,255,22322},{15,255,4457},{8,255,2033},{76,255,65535},{22,255,19980},{0,254,23},{0,240,5494},{0,254,47573},{0,218,23129},{129,255,9866},{104,255,3441},{92,255,832},{71,244,435},{248,0,16034},{34,255,6253},{0,254,51},{0,194,7213},{254,124,16034},{0,194,7213},{55,255,5867},{55,255,5867},{55,255,5867},{38,234,2888},{27,255,6029},{0,248,34},{0,248,34},
+{0,154,985},{0,162,7619},{0,142,3261},{92,255,832},{92,255,832},{92,255,832},{76,215,0},{183,0,4418},{0,248,34},{0,248,34},{0,154,985},{255,58,4418},{0,154,985},{255,122,3613},{152,255,1345},{128,255,0},{0,255,1},{255,122,3613},{255,190,3613},{0,255,1},{0,212,3613},{255,190,3613},{0,212,3613},{38,0,2888},{38,0,2888},{38,0,2888},{38,0,2888},{0,231,0},{0,231,0},{0,231,0},{0,113,0},{0,91,1066},
+{0,91,1066},{86,255,64310},{37,255,23174},{15,255,5504},{10,255,2546},{79,255,65535},{25,255,19854},{1,255,23},{0,240,4466},{0,254,47048},{0,221,22366},{138,255,8897},{113,255,3261},{101,255,985},{80,247,258},{255,4,14504},{40,255,5561},{7,255,34},{0,200,5867},{255,132,14504},{0,200,5867},{61,255,7213},{61,255,7213},{61,255,7213},{42,245,3613},{33,255,6859},{1,255,51},{1,255,51},{0,163,832},{0,175,8059},{0,151,3441},{101,255,985},
+{101,255,985},{101,255,985},{85,224,0},{196,0,4418},{7,255,34},{7,255,34},{0,163,832},{254,72,4418},{0,163,832},{255,137,2888},{164,255,1066},{141,255,0},{22,255,0},{255,137,2888},{254,198,2888},{22,255,0},{0,217,2888},{254,198,2888},{0,217,2888},{42,0,3613},{42,0,3613},{42,0,3613},{42,0,3613},{0,255,1},{0,255,1},{0,255,1},{0,127,0},{0,103,1345},{0,103,1345},{86,255,64605},{37,255,23983},{18,255,6523},
+{10,255,3097},{86,255,65535},{25,255,19808},{1,255,124},{0,243,3633},{0,254,46617},{0,221,21751},{144,255,8113},{122,255,3131},{113,255,1129},{90,248,139},{255,19,13235},{58,255,5012},{22,255,89},{0,206,4787},{254,140,13235},{0,206,4787},{67,255,8529},{67,255,8529},{67,255,8529},{46,255,4325},{43,255,7725},{7,255,243},{7,255,243},{0,169,724},{0,184,8530},{0,160,3629},{113,255,1129},{113,255,1129},{113,255,1129},{93,232,0},{208,0,4418},
+{22,255,89},{22,255,89},{0,169,724},{254,84,4418},{0,169,724},{255,149,2312},{167,255,865},{153,255,0},{46,255,0},{255,149,2312},{254,204,2312},{46,255,0},{0,221,2312},{254,204,2312},{0,221,2312},{46,0,4325},{46,0,4325},{46,0,4325},{46,0,4325},{3,255,58},{3,255,58},{3,255,58},{0,138,0},{0,112,1620},{0,112,1620},{86,255,64960},{37,255,24878},{18,255,7621},{13,255,3738},{86,255,65535},{25,255,19851},{2,255,323},
+{0,243,2885},{0,254,46257},{0,224,21209},{153,255,7392},{131,255,3029},{122,255,1282},{99,251,56},{255,37,12051},{70,255,4500},{34,255,169},{0,212,3819},{254,149,12051},{0,212,3819},{70,255,9957},{70,255,9957},{70,255,9957},{52,255,5141},{46,255,8712},{13,255,611},{13,255,611},{0,182,610},{0,196,9026},{0,169,3845},{122,255,1282},{122,255,1282},{122,255,1282},{101,240,0},{220,0,4418},{34,255,169},{34,255,169},{0,182,610},{255,95,4418},
+{0,182,610},{255,161,1800},{183,255,673},{165,255,0},{70,255,0},{255,161,1800},{254,210,1800},{70,255,0},{0,225,1800},{254,210,1800},{0,225,1800},{50,0,5101},{50,0,5101},{50,0,5101},{50,0,5101},{9,255,202},{9,255,202},{9,255,202},{0,150,0},{0,121,1921},{0,121,1921},{86,255,65314},{43,255,25774},{21,255,8796},{13,255,4456},{86,255,65535},{25,255,19965},{4,255,614},{0,246,2222},{0,254,45929},{0,224,20720},{159,255,6740},
+{140,255,2955},{129,255,1424},{108,254,11},{255,52,10952},{82,255,4052},{49,255,289},{0,216,2986},{255,156,10952},{0,216,2986},{76,255,11489},{76,255,11489},{76,255,11489},{58,255,6109},{52,255,9860},{19,255,1155},{19,255,1155},{0,191,505},{0,208,9554},{0,176,4059},{129,255,1424},{129,255,1424},{129,255,1424},{109,248,0},{232,0,4418},{49,255,289},{49,255,289},{0,191,505},{255,107,4418},{0,191,505},{255,174,1352},{192,255,500},{177,255,0},
+{95,255,0},{255,174,1352},{255,215,1352},{95,255,0},{0,229,1352},{255,215,1352},{0,229,1352},{54,0,5941},{54,0,5941},{54,0,5941},{54,0,5941},{12,255,433},{12,255,433},{12,255,433},{0,162,0},{0,129,2248},{0,129,2248},{86,255,65535},{43,255,26766},{21,255,10162},{13,255,5358},{86,255,65359},{28,255,20101},{4,255,1047},{0,246,1573},{0,254,45474},{0,227,20192},{172,255,6085},{149,255,2901},{141,255,1618},{119,255,2},{255,70,9818},
+{95,255,3685},{64,255,442},{0,222,2150},{255,165,9818},{0,222,2150},{86,255,13320},{86,255,13320},{86,255,13320},{61,255,7370},{58,255,11310},{22,255,1973},{22,255,1973},{0,200,400},{0,218,10107},{0,188,4361},{141,255,1618},{141,255,1618},{141,255,1618},{119,255,2},{245,0,4418},{64,255,442},{64,255,442},{0,200,400},{254,121,4418},{0,200,400},{255,186,925},{204,255,337},{190,255,0},{122,255,0},{255,186,925},{255,221,925},{122,255,0},
+{0,233,925},{255,221,925},{0,233,925},{59,0,6962},{59,0,6962},{59,0,6962},{59,0,6962},{15,255,801},{15,255,801},{15,255,801},{0,175,0},{0,141,2645},{0,141,2645},{86,255,65535},{43,255,27616},{24,255,11405},{16,255,6203},{86,255,65014},{28,255,20233},{5,255,1524},{0,249,1090},{1,255,44974},{0,227,19721},{175,255,5534},{156,255,2885},{150,255,1801},{128,255,40},{255,86,8901},{107,255,3373},{79,255,605},{0,228,1522},{255,172,8901},
+{0,228,1522},{89,255,15066},{89,255,15066},{89,255,15066},{67,255,8646},{64,255,12746},{28,255,2881},{28,255,2881},{0,209,317},{0,230,10691},{0,194,4661},{150,255,1801},{150,255,1801},{150,255,1801},{128,255,40},{255,4,4418},{79,255,605},{79,255,605},{0,209,317},{255,132,4418},{0,209,317},{255,198,613},{213,255,218},{202,255,0},{146,255,0},{255,198,613},{255,227,613},{146,255,0},{0,237,613},{255,227,613},{0,237,613},{63,0,7938},
+{63,0,7938},{63,0,7938},{63,0,7938},{18,255,1224},{18,255,1224},{18,255,1224},{0,187,0},{0,150,3026},{0,150,3026},{89,255,65535},{43,255,28505},{24,255,12681},{16,255,7117},{86,255,64678},{28,255,20430},{7,255,2079},{0,249,697},{1,255,44506},{0,227,19330},{181,255,5094},{165,255,2891},{159,255,1994},{137,255,130},{255,104,8069},{119,255,3125},{92,255,820},{0,234,1006},{255,181,8069},{0,234,1006},{95,255,16946},{95,255,16946},{95,255,16946},
+{73,255,10074},{67,255,14315},{34,255,3965},{34,255,3965},{0,219,250},{0,239,11302},{0,203,4985},{159,255,1994},{159,255,1994},{159,255,1994},{137,255,130},{255,28,4418},{92,255,820},{92,255,820},{0,219,250},{255,144,4418},{0,219,250},{255,210,365},{222,255,125},{214,255,0},{171,255,0},{255,210,365},{255,233,365},{171,255,0},{0,241,365},{255,233,365},{0,241,365},{67,0,8978},{67,0,8978},{67,0,8978},{67,0,8978},{24,255,1732},
+{24,255,1732},{24,255,1732},{0,199,0},{0,159,3433},{0,159,3433},{92,255,65535},{49,255,29231},{30,255,13748},{22,255,7832},{89,255,64474},{34,255,20616},{13,255,2581},{5,251,455},{1,255,43254},{0,230,17214},{187,255,4726},{175,255,2921},{172,255,2196},{146,255,272},{255,119,7322},{131,255,2941},{107,255,1037},{0,240,602},{254,189,7322},{0,240,602},{101,255,17762},{101,255,17762},{101,255,17762},{79,255,10742},{76,255,15150},{43,255,4710},{43,255,4710},
+{3,228,217},{0,251,10994},{0,212,4545},{172,255,2196},{172,255,2196},{172,255,2196},{146,255,272},{255,52,4418},{107,255,1037},{107,255,1037},{0,228,185},{255,156,4418},{0,228,185},{255,222,181},{231,255,58},{226,255,0},{195,255,0},{255,222,181},{255,239,181},{195,255,0},{0,245,181},{255,239,181},{0,245,181},{74,0,9248},{74,0,9248},{74,0,9248},{74,0,9248},{30,255,2020},{30,255,2020},{30,255,2020},{6,208,0},{0,172,3176},
+{0,172,3176},{98,255,65535},{58,255,30030},{43,255,14936},{31,255,8624},{95,255,64295},{43,255,20818},{22,255,3192},{15,252,275},{1,255,41806},{0,236,14271},{196,255,4387},{184,255,2987},{178,255,2410},{158,255,490},{255,137,6584},{146,255,2811},{125,255,1313},{0,246,278},{254,198,6584},{0,246,278},{113,255,18273},{113,255,18273},{113,255,18273},{89,255,11256},{89,255,15726},{55,255,5525},{55,255,5525},{12,237,217},{0,254,10500},{0,224,3805},{178,255,2410},
+{178,255,2410},{178,255,2410},{158,255,490},{255,79,4418},{125,255,1313},{125,255,1313},{0,240,125},{253,170,4418},{0,240,125},{255,237,50},{243,255,13},{239,255,0},{222,255,0},{255,237,50},{254,247,50},{222,255,0},{0,250,50},{254,247,50},{0,250,50},{83,0,9248},{83,0,9248},{83,0,9248},{83,0,9248},{43,255,2228},{43,255,2228},{43,255,2228},{15,217,0},{0,190,2738},{0,190,2738},{104,255,65535},{67,255,30820},{49,255,16060},
+{40,255,9410},{101,255,64140},{52,255,21086},{31,255,3826},{22,253,162},{1,255,40863},{0,239,11797},{202,255,4163},{193,255,3077},{187,255,2633},{167,255,740},{255,152,6019},{158,255,2763},{137,255,1585},{0,252,110},{255,205,6019},{0,252,110},{119,255,18737},{119,255,18737},{119,255,18737},{98,255,11747},{98,255,16315},{64,255,6305},{64,255,6305},{20,245,217},{1,255,10451},{0,236,3205},{187,255,2633},{187,255,2633},{187,255,2633},{167,255,740},{255,104,4418},
+{137,255,1585},{137,255,1585},{0,249,80},{255,181,4418},{0,249,80},{255,249,2},{252,255,0},{251,255,0},{246,255,0},{255,249,2},{254,253,2},{246,255,0},{0,254,2},{254,253,2},{0,254,2},{91,0,9248},{91,0,9248},{91,0,9248},{91,0,9248},{49,255,2440},{49,255,2440},{49,255,2440},{23,225,0},{0,205,2377},{0,205,2377},{110,255,65535},{73,255,31223},{55,255,16690},{49,255,9985},{107,255,63957},{58,255,21217},{38,255,4182},
+{30,255,97},{1,255,40169},{0,242,9493},{208,255,3603},{199,255,2717},{193,255,2357},{174,255,725},{255,164,5163},{167,255,2409},{149,255,1445},{0,255,16},{255,211,5163},{0,255,16},{129,255,18104},{129,255,18104},{129,255,18104},{107,255,11680},{107,255,15698},{73,255,6401},{73,255,6401},{27,249,133},{1,255,9723},{0,242,2489},{193,255,2357},{193,255,2357},{193,255,2357},{174,255,725},{255,119,3872},{149,255,1445},{149,255,1445},{0,252,13},{254,189,3872},
+{0,252,13},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{99,0,9248},{99,0,9248},{99,0,9248},{99,0,9248},{61,255,2664},{61,255,2664},{61,255,2664},{31,233,0},{0,218,2000},{0,218,2000},{116,255,65535},{79,255,31523},{64,255,17156},{55,255,10522},{113,255,63756},{67,255,21315},{46,255,4385},{38,254,41},{4,255,39799},{0,245,7354},{215,255,2952},
+{202,255,2243},{199,255,1945},{183,255,593},{255,171,4267},{167,255,2009},{158,255,1186},{10,255,0},{254,214,4267},{10,255,0},{135,255,17216},{135,255,17216},{135,255,17216},{116,255,11435},{113,255,14726},{82,255,6281},{82,255,6281},{38,251,53},{1,255,8923},{0,248,1877},{199,255,1945},{199,255,1945},{199,255,1945},{183,255,593},{255,131,3200},{158,255,1186},{158,255,1186},{10,255,0},{254,195,3200},{10,255,0},{255,252,0},{255,254,0},{254,255,0},
+{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{107,0,9248},{107,0,9248},{107,0,9248},{107,0,9248},{70,255,2897},{70,255,2897},{70,255,2897},{39,241,0},{0,233,1693},{0,233,1693},{122,255,65535},{89,255,32024},{73,255,17745},{64,255,11181},{119,255,63505},{73,255,21450},{55,255,4731},{48,255,5},{13,255,39517},{0,248,5202},{218,255,2308},{208,255,1762},{205,255,1530},{192,255,464},{255,180,3361},
+{183,255,1587},{167,255,928},{37,255,0},{255,218,3361},{37,255,0},{141,255,16274},{141,255,16274},{141,255,16274},{122,255,11169},{122,255,13721},{92,255,6189},{92,255,6189},{47,254,6},{13,255,8241},{0,254,1395},{205,255,1530},{205,255,1530},{205,255,1530},{192,255,464},{255,143,2521},{167,255,928},{167,255,928},{37,255,0},{254,201,2521},{37,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},
+{0,255,0},{255,254,0},{0,255,0},{116,0,9248},{116,0,9248},{116,0,9248},{116,0,9248},{79,255,3170},{79,255,3170},{79,255,3170},{48,250,0},{0,248,1378},{0,248,1378},{129,255,65535},{95,255,32533},{79,255,18407},{73,255,11877},{129,255,63435},{82,255,21690},{64,255,5107},{56,255,2},{25,255,39436},{0,248,3611},{221,255,1809},{215,255,1374},{211,255,1202},{198,255,360},{255,189,2646},{192,255,1241},{180,255,745},{61,255,0},{254,223,2646},
+{61,255,0},{147,255,15490},{147,255,15490},{147,255,15490},{131,255,10946},{129,255,12826},{101,255,6125},{101,255,6125},{56,255,4},{25,255,7705},{0,254,1171},{211,255,1202},{211,255,1202},{211,255,1202},{198,255,360},{255,155,1985},{180,255,745},{180,255,745},{61,255,0},{254,207,1985},{61,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{124,0,9248},
+{124,0,9248},{124,0,9248},{124,0,9248},{89,255,3393},{89,255,3393},{89,255,3393},{56,255,4},{0,254,1170},{0,254,1170},{132,255,65535},{101,255,32957},{86,255,19017},{82,255,12610},{129,255,62977},{89,255,22061},{73,255,5530},{64,255,31},{34,255,39178},{0,251,2372},{224,255,1376},{218,255,1044},{218,255,900},{204,255,272},{255,198,2017},{198,255,937},{189,255,562},{86,255,0},{255,227,2017},{86,255,0},{153,255,14754},{153,255,14754},{153,255,14754},
+{137,255,10742},{135,255,12066},{107,255,6089},{107,255,6089},{67,255,45},{37,255,7233},{1,255,1184},{218,255,900},{218,255,900},{218,255,900},{204,255,272},{255,167,1513},{189,255,562},{189,255,562},{86,255,0},{253,213,1513},{86,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{132,0,9248},{132,0,9248},{132,0,9248},{132,0,9248},{98,255,3656},
+{98,255,3656},{98,255,3656},{67,255,45},{1,255,1184},{1,255,1184},{138,255,65535},{107,255,33448},{95,255,19729},{89,255,13446},{135,255,62717},{95,255,22307},{79,255,6021},{73,255,105},{40,255,38959},{0,254,1627},{230,255,996},{224,255,756},{221,255,653},{213,255,194},{255,204,1473},{207,255,675},{198,255,405},{110,255,0},{255,230,1473},{110,255,0},{162,255,14060},{162,255,14060},{162,255,14060},{146,255,10545},{141,255,11378},{116,255,6077},{116,255,6077},
+{76,255,137},{40,255,6873},{7,255,1412},{221,255,653},{221,255,653},{221,255,653},{213,255,194},{255,180,1105},{198,255,405},{198,255,405},{110,255,0},{255,218,1105},{110,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{140,0,9248},{140,0,9248},{140,0,9248},{140,0,9248},{107,255,3929},{107,255,3929},{107,255,3929},{76,255,137},{7,255,1412},
+{7,255,1412}, \ No newline at end of file
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_atc_55.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_atc_55.inc
new file mode 100644
index 0000000000..61f7476efc
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_atc_55.inc
@@ -0,0 +1,481 @@
+{0,2,20},{0,1,10},{0,1,1},{0,1,9},{0,1,35},{0,1,27},{0,1,18},{0,1,61},{0,1,52},{0,0,68},{0,2,20},{0,1,10},{0,1,1},{0,1,9},{0,1,35},{0,1,27},{0,1,18},{0,1,61},{1,0,35},{0,1,61},{0,1,1},{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,1},
+{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{1,0,18},{0,1,10},{0,1,1},{0,1,9},{1,0,18},{0,1,18},{0,1,9},{0,1,36},{0,1,18},{0,1,36},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,4,56},{0,3,38},{0,2,52},
+{0,2,36},{0,4,56},{0,3,35},{0,2,0},{0,2,52},{0,2,88},{0,1,78},{1,3,24},{1,2,14},{1,2,5},{1,2,13},{1,2,51},{0,3,35},{0,2,0},{0,2,52},{2,1,51},{0,2,52},{0,3,37},{0,3,37},{0,3,37},{0,2,36},{0,3,10},{0,2,0},{0,2,0},{0,1,5},{0,1,35},{0,1,14},{1,2,5},{1,2,5},{1,2,5},{1,1,8},{1,1,8},
+{0,2,0},{0,2,0},{0,1,5},{1,1,8},{0,1,5},{2,1,18},{0,3,2},{1,2,1},{0,2,0},{2,1,18},{1,2,18},{0,2,0},{0,2,36},{1,2,18},{0,2,36},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,10},{0,1,10},{1,5,56},{1,4,38},{1,3,52},{1,3,36},{1,5,56},{1,4,35},{1,3,0},
+{1,3,52},{0,4,72},{0,3,38},{2,4,24},{2,3,14},{2,3,5},{2,3,13},{2,3,51},{0,4,24},{1,3,0},{0,3,37},{3,2,51},{0,3,37},{1,4,37},{1,4,37},{1,4,37},{1,3,36},{1,4,10},{1,3,0},{1,3,0},{1,2,5},{0,3,11},{1,2,14},{2,3,5},{2,3,5},{2,3,5},{2,2,8},{2,2,8},{1,3,0},{1,3,0},{1,2,5},{2,2,8},
+{1,2,5},{3,2,18},{1,4,2},{2,3,1},{1,3,0},{3,2,18},{7,0,18},{1,3,0},{0,3,36},{7,0,18},{0,3,36},{1,0,36},{1,0,36},{1,0,36},{1,0,36},{1,3,0},{1,3,0},{1,3,0},{1,2,1},{0,3,2},{0,3,2},{2,6,56},{2,5,38},{2,4,53},{2,4,37},{2,6,56},{2,5,35},{2,4,1},{2,4,66},{0,5,60},{1,4,52},{3,5,24},
+{3,4,14},{3,4,6},{3,4,14},{3,4,51},{1,5,24},{2,4,1},{1,4,51},{9,0,51},{1,4,51},{2,5,37},{2,5,37},{2,5,37},{2,4,36},{2,5,10},{2,4,0},{2,4,0},{2,3,5},{1,4,11},{2,3,14},{3,4,5},{3,4,5},{3,4,5},{3,3,8},{3,3,8},{2,4,0},{2,4,0},{2,3,5},{8,0,8},{2,3,5},{4,3,18},{2,5,2},{3,4,2},
+{2,4,1},{4,3,18},{8,1,18},{2,4,1},{0,4,50},{8,1,18},{0,4,50},{2,0,36},{2,0,36},{2,0,36},{2,0,36},{2,4,0},{2,4,0},{2,4,0},{2,3,1},{1,4,2},{1,4,2},{3,8,70},{3,6,58},{4,5,69},{3,5,51},{3,7,52},{3,6,25},{3,5,3},{3,5,46},{2,6,60},{2,5,36},{4,6,24},{4,5,14},{4,5,5},{4,5,13},{6,2,51},
+{3,6,24},{3,5,2},{2,5,36},{7,3,51},{2,5,36},{3,7,51},{3,7,51},{3,7,51},{3,5,51},{3,6,9},{3,5,3},{3,5,3},{3,4,9},{1,6,12},{3,4,12},{4,5,5},{4,5,5},{4,5,5},{4,4,8},{6,1,8},{3,5,2},{3,5,2},{3,4,8},{11,0,8},{3,4,8},{7,1,18},{3,6,8},{4,5,1},{3,5,1},{7,1,18},{11,1,18},{3,5,1},
+{0,5,36},{11,1,18},{0,5,36},{3,0,50},{3,0,50},{3,0,50},{3,0,50},{3,5,2},{3,5,2},{3,5,2},{3,4,5},{2,5,0},{2,5,0},{4,8,56},{4,7,38},{4,6,52},{4,6,36},{4,8,56},{4,7,35},{4,6,0},{4,6,52},{3,7,60},{3,6,36},{5,7,24},{5,6,14},{5,6,5},{5,6,13},{8,1,51},{3,7,35},{4,6,0},{3,6,36},{6,5,51},
+{3,6,36},{4,7,37},{4,7,37},{4,7,37},{4,6,36},{4,7,10},{4,6,0},{4,6,0},{4,5,5},{2,7,12},{4,5,14},{5,6,5},{5,6,5},{5,6,5},{5,5,8},{8,0,8},{4,6,0},{4,6,0},{4,5,5},{5,5,8},{4,5,5},{9,0,18},{4,7,2},{5,6,1},{4,6,0},{9,0,18},{15,0,18},{4,6,0},{0,6,36},{15,0,18},{0,6,36},{4,0,36},
+{4,0,36},{4,0,36},{4,0,36},{4,6,0},{4,6,0},{4,6,0},{4,5,1},{3,6,0},{3,6,0},{5,9,56},{5,8,38},{5,7,52},{5,7,36},{5,9,56},{5,8,35},{5,7,0},{5,7,52},{3,8,63},{4,7,38},{6,8,24},{6,7,14},{6,7,5},{6,7,13},{9,2,51},{4,8,24},{5,7,0},{4,7,37},{17,0,51},{4,7,37},{5,8,37},{5,8,37},{5,8,37},
+{5,7,36},{5,8,10},{5,7,0},{5,7,0},{5,6,5},{4,7,11},{5,6,14},{6,7,5},{6,7,5},{6,7,5},{6,6,8},{9,1,8},{5,7,0},{5,7,0},{5,6,5},{16,0,8},{5,6,5},{10,1,18},{5,8,2},{6,7,1},{5,7,0},{10,1,18},{16,1,18},{5,7,0},{0,7,36},{16,1,18},{0,7,36},{5,0,36},{5,0,36},{5,0,36},{5,0,36},{5,7,0},
+{5,7,0},{5,7,0},{5,6,1},{4,7,2},{4,7,2},{6,10,56},{6,9,38},{6,8,53},{6,8,37},{6,10,56},{6,9,35},{6,8,1},{6,8,66},{4,9,60},{5,8,52},{7,9,24},{7,8,14},{7,8,6},{7,8,14},{10,3,51},{5,9,24},{6,8,1},{5,8,51},{18,1,51},{5,8,51},{6,9,37},{6,9,37},{6,9,37},{6,8,36},{6,9,10},{6,8,0},{6,8,0},
+{6,7,5},{5,8,11},{6,7,14},{7,8,5},{7,8,5},{7,8,5},{7,7,8},{10,2,8},{6,8,0},{6,8,0},{6,7,5},{17,1,8},{6,7,5},{11,2,18},{6,9,2},{7,8,2},{6,8,1},{11,2,18},{17,2,18},{6,8,1},{0,8,50},{17,2,18},{0,8,50},{6,0,36},{6,0,36},{6,0,36},{6,0,36},{6,8,0},{6,8,0},{6,8,0},{6,7,1},{5,8,2},
+{5,8,2},{7,12,70},{7,10,58},{8,9,69},{7,9,51},{7,11,52},{7,10,25},{7,9,3},{7,9,46},{6,10,60},{6,9,36},{8,10,24},{8,9,14},{8,9,5},{8,9,13},{13,1,51},{7,10,24},{7,9,2},{6,9,36},{21,1,51},{6,9,36},{7,11,51},{7,11,51},{7,11,51},{7,9,51},{7,10,9},{7,9,3},{7,9,3},{7,8,9},{5,10,12},{7,8,12},{8,9,5},
+{8,9,5},{8,9,5},{8,8,8},{13,0,8},{7,9,2},{7,9,2},{7,8,8},{20,1,8},{7,8,8},{14,0,18},{7,10,8},{8,9,1},{7,9,1},{14,0,18},{20,2,18},{7,9,1},{0,9,36},{20,2,18},{0,9,36},{7,0,50},{7,0,50},{7,0,50},{7,0,50},{7,9,2},{7,9,2},{7,9,2},{7,8,5},{6,9,0},{6,9,0},{8,12,56},{8,11,38},{8,10,52},
+{8,10,36},{8,12,56},{8,11,35},{8,10,0},{8,10,52},{7,11,60},{7,10,36},{9,11,24},{9,10,14},{9,10,5},{9,10,13},{14,2,51},{7,11,35},{8,10,0},{7,10,36},{25,0,51},{7,10,36},{8,11,37},{8,11,37},{8,11,37},{8,10,36},{8,11,10},{8,10,0},{8,10,0},{8,9,5},{6,11,12},{8,9,14},{9,10,5},{9,10,5},{9,10,5},{9,9,8},{14,1,8},
+{8,10,0},{8,10,0},{8,9,5},{24,0,8},{8,9,5},{15,1,18},{8,11,2},{9,10,1},{8,10,0},{15,1,18},{24,1,18},{8,10,0},{0,10,36},{24,1,18},{0,10,36},{8,0,36},{8,0,36},{8,0,36},{8,0,36},{8,10,0},{8,10,0},{8,10,0},{8,9,1},{7,10,0},{7,10,0},{9,13,56},{9,12,38},{9,11,52},{9,11,36},{9,13,56},{9,12,35},{9,11,0},
+{9,11,52},{7,12,63},{8,11,38},{10,12,24},{10,11,14},{10,11,5},{10,11,13},{16,1,51},{8,12,24},{9,11,0},{8,11,37},{26,1,51},{8,11,37},{9,12,37},{9,12,37},{9,12,37},{9,11,36},{9,12,10},{9,11,0},{9,11,0},{9,10,5},{8,11,11},{9,10,14},{10,11,5},{10,11,5},{10,11,5},{10,10,8},{16,0,8},{9,11,0},{9,11,0},{9,10,5},{25,1,8},
+{9,10,5},{17,0,18},{9,12,2},{10,11,1},{9,11,0},{17,0,18},{25,2,18},{9,11,0},{0,11,36},{25,2,18},{0,11,36},{9,0,36},{9,0,36},{9,0,36},{9,0,36},{9,11,0},{9,11,0},{9,11,0},{9,10,1},{8,11,2},{8,11,2},{10,14,56},{10,13,38},{10,12,53},{10,12,37},{10,14,56},{10,13,35},{10,12,1},{10,12,66},{8,13,60},{9,12,52},{11,13,24},
+{11,12,14},{11,12,6},{11,12,14},{17,2,51},{9,13,24},{10,12,1},{9,12,51},{27,2,51},{9,12,51},{10,13,37},{10,13,37},{10,13,37},{10,12,36},{10,13,10},{10,12,0},{10,12,0},{10,11,5},{9,12,11},{10,11,14},{11,12,5},{11,12,5},{11,12,5},{11,11,8},{17,1,8},{10,12,0},{10,12,0},{10,11,5},{26,2,8},{10,11,5},{18,1,18},{10,13,2},{11,12,2},
+{10,12,1},{18,1,18},{31,0,18},{10,12,1},{0,12,50},{31,0,18},{0,12,50},{10,0,36},{10,0,36},{10,0,36},{10,0,36},{10,12,0},{10,12,0},{10,12,0},{10,11,1},{9,12,2},{9,12,2},{11,16,70},{11,14,58},{12,13,69},{11,13,51},{11,15,52},{11,14,25},{11,13,3},{11,13,46},{10,14,60},{10,13,36},{12,14,24},{12,13,14},{12,13,5},{12,13,13},{17,5,51},
+{11,14,24},{11,13,2},{10,13,36},{30,2,51},{10,13,36},{11,15,51},{11,15,51},{11,15,51},{11,13,51},{11,14,9},{11,13,3},{11,13,3},{11,12,9},{9,14,12},{11,12,12},{12,13,5},{12,13,5},{12,13,5},{12,12,8},{17,4,8},{11,13,2},{11,13,2},{11,12,8},{29,2,8},{11,12,8},{18,4,18},{11,14,8},{12,13,1},{11,13,1},{18,4,18},{29,3,18},{11,13,1},
+{0,13,36},{29,3,18},{0,13,36},{11,0,50},{11,0,50},{11,0,50},{11,0,50},{11,13,2},{11,13,2},{11,13,2},{11,12,5},{10,13,0},{10,13,0},{12,16,56},{12,15,38},{12,14,52},{12,14,36},{12,16,56},{12,15,35},{12,14,0},{12,14,52},{11,15,60},{11,14,36},{13,15,24},{13,14,14},{13,14,5},{13,14,13},{18,6,51},{11,15,35},{12,14,0},{11,14,36},{31,3,51},
+{11,14,36},{12,15,37},{12,15,37},{12,15,37},{12,14,36},{12,15,10},{12,14,0},{12,14,0},{12,13,5},{10,15,12},{12,13,14},{13,14,5},{13,14,5},{13,14,5},{13,13,8},{18,5,8},{12,14,0},{12,14,0},{12,13,5},{30,3,8},{12,13,5},{20,3,18},{12,15,2},{13,14,1},{12,14,0},{20,3,18},{28,5,18},{12,14,0},{0,14,36},{28,5,18},{0,14,36},{12,0,36},
+{12,0,36},{12,0,36},{12,0,36},{12,14,0},{12,14,0},{12,14,0},{12,13,1},{11,14,0},{11,14,0},{13,17,56},{13,16,38},{13,15,52},{13,15,36},{13,17,56},{13,16,35},{13,15,0},{13,15,52},{11,16,63},{12,15,38},{14,16,24},{14,15,14},{14,15,5},{14,15,13},{23,0,51},{12,16,24},{13,15,0},{12,15,37},{30,5,51},{12,15,37},{13,16,37},{13,16,37},{13,16,37},
+{13,15,36},{13,16,10},{13,15,0},{13,15,0},{13,14,5},{12,15,11},{13,14,14},{14,15,5},{14,15,5},{14,15,5},{14,14,8},{20,4,8},{13,15,0},{13,15,0},{13,14,5},{29,5,8},{13,14,5},{21,4,18},{13,16,2},{14,15,1},{13,15,0},{21,4,18},{29,6,18},{13,15,0},{0,15,36},{29,6,18},{0,15,36},{13,0,36},{13,0,36},{13,0,36},{13,0,36},{13,15,0},
+{13,15,0},{13,15,0},{13,14,1},{12,15,2},{12,15,2},{14,18,56},{14,17,38},{14,16,53},{14,16,37},{14,18,56},{14,17,35},{14,16,1},{14,16,66},{12,17,60},{13,16,52},{15,17,24},{15,16,14},{15,16,6},{15,16,14},{24,1,51},{13,17,24},{14,16,1},{13,16,51},{31,6,51},{13,16,51},{14,17,37},{14,17,37},{14,17,37},{14,16,36},{14,17,10},{14,16,0},{14,16,0},
+{14,15,5},{13,16,11},{14,15,14},{15,16,5},{15,16,5},{15,16,5},{15,15,8},{24,0,8},{14,16,0},{14,16,0},{14,15,5},{30,6,8},{14,15,5},{25,0,18},{14,17,2},{15,16,2},{14,16,1},{25,0,18},{30,7,18},{14,16,1},{0,16,50},{30,7,18},{0,16,50},{14,0,36},{14,0,36},{14,0,36},{14,0,36},{14,16,0},{14,16,0},{14,16,0},{14,15,1},{13,16,2},
+{13,16,2},{15,20,70},{15,18,58},{16,17,69},{15,17,51},{15,19,52},{15,18,25},{15,17,3},{15,17,46},{14,18,60},{14,17,36},{16,18,24},{16,17,14},{16,17,5},{16,17,13},{21,9,51},{15,18,24},{15,17,2},{14,17,36},{29,9,51},{14,17,36},{15,19,51},{15,19,51},{15,19,51},{15,17,51},{15,18,9},{15,17,3},{15,17,3},{15,16,9},{13,18,12},{15,16,12},{16,17,5},
+{16,17,5},{16,17,5},{16,16,8},{24,3,8},{15,17,2},{15,17,2},{15,16,8},{28,9,8},{15,16,8},{25,3,18},{15,18,8},{16,17,1},{15,17,1},{25,3,18},{28,10,18},{15,17,1},{0,17,36},{28,10,18},{0,17,36},{15,0,50},{15,0,50},{15,0,50},{15,0,50},{15,17,2},{15,17,2},{15,17,2},{15,16,5},{14,17,0},{14,17,0},{16,20,56},{16,19,38},{16,18,52},
+{16,18,36},{16,20,56},{16,19,35},{16,18,0},{16,18,52},{15,19,60},{15,18,36},{17,19,24},{17,18,14},{17,18,5},{17,18,13},{22,10,51},{15,19,35},{16,18,0},{15,18,36},{30,10,51},{15,18,36},{16,19,37},{16,19,37},{16,19,37},{16,18,36},{16,19,10},{16,18,0},{16,18,0},{16,17,5},{14,19,12},{16,17,14},{17,18,5},{17,18,5},{17,18,5},{17,17,8},{22,9,8},
+{16,18,0},{16,18,0},{16,17,5},{29,10,8},{16,17,5},{24,7,18},{16,19,2},{17,18,1},{16,18,0},{24,7,18},{29,11,18},{16,18,0},{0,18,36},{29,11,18},{0,18,36},{16,0,36},{16,0,36},{16,0,36},{16,0,36},{16,18,0},{16,18,0},{16,18,0},{16,17,1},{15,18,0},{15,18,0},{17,21,56},{17,20,38},{17,19,52},{17,19,36},{17,21,56},{17,20,35},{17,19,0},
+{17,19,52},{15,20,63},{16,19,38},{18,20,24},{18,19,14},{18,19,5},{18,19,13},{27,4,51},{16,20,24},{17,19,0},{16,19,37},{31,11,51},{16,19,37},{17,20,37},{17,20,37},{17,20,37},{17,19,36},{17,20,10},{17,19,0},{17,19,0},{17,18,5},{16,19,11},{17,18,14},{18,19,5},{18,19,5},{18,19,5},{18,18,8},{24,8,8},{17,19,0},{17,19,0},{17,18,5},{30,11,8},
+{17,18,5},{28,3,18},{17,20,2},{18,19,1},{17,19,0},{28,3,18},{28,13,18},{17,19,0},{0,19,36},{28,13,18},{0,19,36},{17,0,36},{17,0,36},{17,0,36},{17,0,36},{17,19,0},{17,19,0},{17,19,0},{17,18,1},{16,19,2},{16,19,2},{18,22,56},{18,21,38},{18,20,53},{18,20,37},{18,22,56},{18,21,35},{18,20,1},{18,20,66},{16,21,60},{17,20,52},{19,21,24},
+{19,20,14},{19,20,6},{19,20,14},{31,0,51},{17,21,24},{18,20,1},{17,20,51},{30,13,51},{17,20,51},{18,21,37},{18,21,37},{18,21,37},{18,20,36},{18,21,10},{18,20,0},{18,20,0},{18,19,5},{17,20,11},{18,19,14},{19,20,5},{19,20,5},{19,20,5},{19,19,8},{28,4,8},{18,20,0},{18,20,0},{18,19,5},{29,13,8},{18,19,5},{29,4,18},{18,21,2},{19,20,2},
+{18,20,1},{29,4,18},{29,14,18},{18,20,1},{0,20,50},{29,14,18},{0,20,50},{18,0,36},{18,0,36},{18,0,36},{18,0,36},{18,20,0},{18,20,0},{18,20,0},{18,19,1},{17,20,2},{17,20,2},{19,24,70},{19,22,58},{20,21,69},{19,21,51},{19,23,52},{19,22,25},{19,21,3},{19,21,46},{18,22,60},{18,21,36},{20,22,24},{20,21,14},{20,21,5},{20,21,13},{31,3,51},
+{19,22,24},{19,21,2},{18,21,36},{23,19,51},{18,21,36},{19,23,51},{19,23,51},{19,23,51},{19,21,51},{19,22,9},{19,21,3},{19,21,3},{19,20,9},{17,22,12},{19,20,12},{20,21,5},{20,21,5},{20,21,5},{20,20,8},{31,2,8},{19,21,2},{19,21,2},{19,20,8},{27,16,8},{19,20,8},{29,7,18},{19,22,8},{20,21,1},{19,21,1},{29,7,18},{27,17,18},{19,21,1},
+{0,21,36},{27,17,18},{0,21,36},{19,0,50},{19,0,50},{19,0,50},{19,0,50},{19,21,2},{19,21,2},{19,21,2},{19,20,5},{18,21,0},{18,21,0},{20,24,56},{20,23,38},{20,22,52},{20,22,36},{20,24,56},{20,23,35},{20,22,0},{20,22,52},{19,23,60},{19,22,36},{21,23,24},{21,22,14},{21,22,5},{21,22,13},{26,14,51},{19,23,35},{20,22,0},{19,22,36},{22,21,51},
+{19,22,36},{20,23,37},{20,23,37},{20,23,37},{20,22,36},{20,23,10},{20,22,0},{20,22,0},{20,21,5},{18,23,12},{20,21,14},{21,22,5},{21,22,5},{21,22,5},{21,21,8},{26,13,8},{20,22,0},{20,22,0},{20,21,5},{21,21,8},{20,21,5},{28,11,18},{20,23,2},{21,22,1},{20,22,0},{28,11,18},{31,16,18},{20,22,0},{0,22,36},{31,16,18},{0,22,36},{20,0,36},
+{20,0,36},{20,0,36},{20,0,36},{20,22,0},{20,22,0},{20,22,0},{20,21,1},{19,22,0},{19,22,0},{21,25,56},{21,24,38},{21,23,52},{21,23,36},{21,25,56},{21,24,35},{21,23,0},{21,23,52},{19,24,63},{20,23,38},{22,24,24},{22,23,14},{22,23,5},{22,23,13},{31,8,51},{20,24,24},{21,23,0},{20,23,37},{28,19,51},{20,23,37},{21,24,37},{21,24,37},{21,24,37},
+{21,23,36},{21,24,10},{21,23,0},{21,23,0},{21,22,5},{20,23,11},{21,22,14},{22,23,5},{22,23,5},{22,23,5},{22,22,8},{28,12,8},{21,23,0},{21,23,0},{21,22,5},{22,22,8},{21,22,5},{29,12,18},{21,24,2},{22,23,1},{21,23,0},{29,12,18},{27,20,18},{21,23,0},{0,23,36},{27,20,18},{0,23,36},{21,0,36},{21,0,36},{21,0,36},{21,0,36},{21,23,0},
+{21,23,0},{21,23,0},{21,22,1},{20,23,2},{20,23,2},{22,26,56},{22,25,38},{22,24,53},{22,24,37},{22,26,56},{22,25,35},{22,24,1},{22,24,66},{20,25,60},{21,24,52},{23,25,24},{23,24,14},{23,24,6},{23,24,14},{29,14,51},{21,25,24},{22,24,1},{21,24,51},{29,20,51},{21,24,51},{22,25,37},{22,25,37},{22,25,37},{22,24,36},{22,25,10},{22,24,0},{22,24,0},
+{22,23,5},{21,24,11},{22,23,14},{23,24,5},{23,24,5},{23,24,5},{23,23,8},{29,13,8},{22,24,0},{22,24,0},{22,23,5},{28,20,8},{22,23,5},{30,13,18},{22,25,2},{23,24,2},{22,24,1},{30,13,18},{28,21,18},{22,24,1},{0,24,50},{28,21,18},{0,24,50},{22,0,36},{22,0,36},{22,0,36},{22,0,36},{22,24,0},{22,24,0},{22,24,0},{22,23,1},{21,24,2},
+{21,24,2},{23,28,70},{23,26,58},{24,25,69},{23,25,51},{23,27,52},{23,26,25},{23,25,3},{23,25,46},{22,26,60},{22,25,36},{24,26,24},{24,25,14},{24,25,5},{24,25,13},{29,17,51},{23,26,24},{23,25,2},{22,25,36},{27,23,51},{22,25,36},{23,27,51},{23,27,51},{23,27,51},{23,25,51},{23,26,9},{23,25,3},{23,25,3},{23,24,9},{21,26,12},{23,24,12},{24,25,5},
+{24,25,5},{24,25,5},{24,24,8},{29,16,8},{23,25,2},{23,25,2},{23,24,8},{31,20,8},{23,24,8},{30,16,18},{23,26,8},{24,25,1},{23,25,1},{30,16,18},{31,21,18},{23,25,1},{0,25,36},{31,21,18},{0,25,36},{23,0,50},{23,0,50},{23,0,50},{23,0,50},{23,25,2},{23,25,2},{23,25,2},{23,24,5},{22,25,0},{22,25,0},{24,28,56},{24,27,38},{24,26,52},
+{24,26,36},{24,28,56},{24,27,35},{24,26,0},{24,26,52},{23,27,60},{23,26,36},{25,27,24},{25,26,14},{25,26,5},{25,26,13},{30,18,51},{23,27,35},{24,26,0},{23,26,36},{26,25,51},{23,26,36},{24,27,37},{24,27,37},{24,27,37},{24,26,36},{24,27,10},{24,26,0},{24,26,0},{24,25,5},{22,27,12},{24,25,14},{25,26,5},{25,26,5},{25,26,5},{25,25,8},{30,17,8},
+{24,26,0},{24,26,0},{24,25,5},{25,25,8},{24,25,5},{31,17,18},{24,27,2},{25,26,1},{24,26,0},{31,17,18},{25,26,18},{24,26,0},{0,26,36},{25,26,18},{0,26,36},{24,0,36},{24,0,36},{24,0,36},{24,0,36},{24,26,0},{24,26,0},{24,26,0},{24,25,1},{23,26,0},{23,26,0},{25,29,56},{25,28,38},{25,27,52},{25,27,36},{25,29,56},{25,28,35},{25,27,0},
+{25,27,52},{23,28,63},{24,27,38},{26,28,24},{26,27,14},{26,27,5},{26,27,13},{31,19,51},{24,28,24},{25,27,0},{24,27,37},{27,26,51},{24,27,37},{25,28,37},{25,28,37},{25,28,37},{25,27,36},{25,28,10},{25,27,0},{25,27,0},{25,26,5},{24,27,11},{25,26,14},{26,27,5},{26,27,5},{26,27,5},{26,26,8},{31,18,8},{25,27,0},{25,27,0},{25,26,5},{26,26,8},
+{25,26,5},{30,21,18},{25,28,2},{26,27,1},{25,27,0},{30,21,18},{31,24,18},{25,27,0},{0,27,36},{31,24,18},{0,27,36},{25,0,36},{25,0,36},{25,0,36},{25,0,36},{25,27,0},{25,27,0},{25,27,0},{25,26,1},{24,27,2},{24,27,2},{26,30,56},{26,29,38},{26,28,53},{26,28,37},{26,30,56},{26,29,35},{26,28,1},{26,28,66},{24,29,60},{25,28,52},{27,29,24},
+{27,28,14},{27,28,6},{27,28,14},{30,23,51},{25,29,24},{26,28,1},{25,28,51},{28,27,51},{25,28,51},{26,29,37},{26,29,37},{26,29,37},{26,28,36},{26,29,10},{26,28,0},{26,28,0},{26,27,5},{25,28,11},{26,27,14},{27,28,5},{27,28,5},{27,28,5},{27,27,8},{30,22,8},{26,28,0},{26,28,0},{26,27,5},{27,27,8},{26,27,5},{31,22,18},{26,29,2},{27,28,2},
+{26,28,1},{31,22,18},{27,28,18},{26,28,1},{0,28,50},{27,28,18},{0,28,50},{26,0,36},{26,0,36},{26,0,36},{26,0,36},{26,28,0},{26,28,0},{26,28,0},{26,27,1},{25,28,2},{25,28,2},{27,31,76},{27,30,58},{28,29,69},{27,29,51},{27,31,52},{27,30,25},{27,29,3},{27,29,46},{26,30,60},{26,29,36},{28,30,24},{28,29,14},{28,29,5},{28,29,13},{30,26,51},
+{27,30,24},{27,29,2},{26,29,36},{31,27,51},{26,29,36},{27,31,51},{27,31,51},{27,31,51},{27,29,51},{27,30,9},{27,29,3},{27,29,3},{27,28,9},{25,30,12},{27,28,12},{28,29,5},{28,29,5},{28,29,5},{28,28,8},{30,25,8},{27,29,2},{27,29,2},{27,28,8},{30,27,8},{27,28,8},{31,25,18},{27,30,8},{28,29,1},{27,29,1},{31,25,18},{28,29,18},{27,29,1},
+{0,29,36},{28,29,18},{0,29,36},{27,0,50},{27,0,50},{27,0,50},{27,0,50},{27,29,2},{27,29,2},{27,29,2},{27,28,5},{26,29,0},{26,29,0},{28,31,86},{28,31,38},{28,30,52},{28,30,36},{28,31,59},{28,31,35},{28,30,0},{28,30,52},{27,31,60},{27,30,36},{29,31,24},{29,30,14},{29,30,5},{29,30,13},{31,27,51},{27,31,35},{28,30,0},{27,30,36},{30,29,51},
+{27,30,36},{28,31,37},{28,31,37},{28,31,37},{28,30,36},{28,31,10},{28,30,0},{28,30,0},{28,29,5},{26,31,12},{28,29,14},{29,30,5},{29,30,5},{29,30,5},{29,29,8},{31,26,8},{28,30,0},{28,30,0},{28,29,5},{29,29,8},{28,29,5},{30,29,18},{28,31,2},{29,30,1},{28,30,0},{30,29,18},{29,30,18},{28,30,0},{0,30,36},{29,30,18},{0,30,36},{28,0,36},
+{28,0,36},{28,0,36},{28,0,36},{28,30,0},{28,30,0},{28,30,0},{28,29,1},{27,30,0},{27,30,0},{30,31,94},{30,31,78},{29,31,52},{29,31,36},{30,31,115},{29,31,36},{29,31,0},{29,31,52},{29,31,88},{28,31,38},{30,31,30},{30,31,14},{30,31,5},{30,31,13},{30,31,51},{29,31,36},{29,31,0},{28,31,37},{31,30,51},{28,31,37},{29,31,52},{29,31,52},{29,31,52},
+{29,31,36},{29,31,16},{29,31,0},{29,31,0},{29,30,5},{28,31,11},{29,30,14},{30,31,5},{30,31,5},{30,31,5},{30,30,8},{30,30,8},{29,31,0},{29,31,0},{29,30,5},{30,30,8},{29,30,5},{31,30,18},{30,31,10},{30,31,1},{29,31,0},{31,30,18},{30,31,18},{29,31,0},{0,31,36},{30,31,18},{0,31,36},{29,0,36},{29,0,36},{29,0,36},{29,0,36},{29,31,0},
+{29,31,0},{29,31,0},{29,30,1},{28,31,2},{28,31,2},{31,31,68},{31,31,68},{30,31,61},{30,31,45},{30,31,59},{30,31,27},{30,31,18},{30,31,1},{30,31,28},{30,31,10},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{30,31,1},{30,31,61},{30,31,61},{30,31,61},{30,31,45},{30,31,34},{30,31,18},{30,31,18},
+{30,31,1},{30,31,19},{30,31,10},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{30,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{30,0,36},{30,0,36},{30,0,36},{30,0,36},{30,31,9},{30,31,9},{30,31,9},{30,31,1},{30,31,10},
+{30,31,10},{0,4,74},{0,3,20},{0,2,2},{0,2,26},{0,2,158},{0,2,110},{0,2,62},{0,1,115},{0,1,178},{0,1,124},{0,4,74},{0,3,20},{0,2,2},{0,2,26},{1,1,154},{0,2,110},{0,2,62},{0,1,115},{1,1,154},{0,1,115},{0,2,1},{0,2,1},{0,2,1},{0,1,0},{0,1,13},{0,1,9},{0,1,9},{0,0,25},{0,0,25},{0,0,25},{0,2,1},
+{0,2,1},{0,2,1},{0,1,0},{0,1,13},{0,1,9},{0,1,9},{0,0,25},{1,0,13},{0,0,25},{1,2,72},{0,3,20},{0,2,2},{0,2,26},{1,2,72},{2,1,72},{0,2,26},{0,1,90},{2,1,72},{0,1,90},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,6,83},{0,5,13},{0,3,26},
+{0,3,14},{0,5,248},{0,3,140},{0,3,41},{0,2,139},{0,2,319},{0,2,175},{0,6,83},{0,5,13},{0,3,26},{0,3,14},{1,3,243},{0,3,140},{0,3,41},{0,2,139},{3,1,243},{0,2,139},{0,4,10},{0,4,10},{0,4,10},{0,3,13},{0,3,52},{0,2,18},{0,2,18},{0,1,29},{0,1,77},{0,1,38},{0,4,10},{0,4,10},{0,4,10},{0,3,13},{1,1,50},
+{0,2,18},{0,2,18},{0,1,29},{1,1,50},{0,1,29},{2,3,72},{0,5,4},{1,3,2},{0,3,5},{2,3,72},{3,2,72},{0,3,5},{0,2,90},{3,2,72},{0,2,90},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,0},{0,1,0},{0,1,0},{0,1,4},{0,0,9},{0,0,9},{1,7,147},{1,6,77},{1,4,89},{1,4,77},{0,7,244},{0,5,96},{0,4,2},
+{0,3,106},{0,4,395},{0,3,187},{1,7,83},{1,6,13},{1,4,25},{1,4,13},{2,4,243},{0,5,96},{0,4,2},{0,3,106},{4,2,243},{0,3,106},{1,5,74},{1,5,74},{1,5,74},{1,4,77},{0,5,52},{0,4,2},{0,4,2},{0,3,25},{0,3,133},{0,2,62},{1,5,10},{1,5,10},{1,5,10},{1,4,13},{2,2,50},{0,4,2},{0,4,2},{0,3,25},{2,2,50},
+{0,3,25},{3,4,72},{1,6,4},{2,4,1},{0,4,1},{3,4,72},{9,0,72},{0,4,1},{0,3,90},{9,0,72},{0,3,90},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,2,37},{0,2,37},{2,8,164},{2,7,94},{2,5,106},{2,5,94},{1,8,245},{1,6,97},{1,5,3},{1,4,97},{0,6,364},{0,4,106},{2,8,83},
+{2,7,13},{2,5,25},{2,5,13},{6,0,243},{0,7,76},{1,5,2},{0,4,81},{10,0,243},{0,4,81},{2,6,91},{2,6,91},{2,6,91},{2,5,94},{1,6,53},{1,5,3},{1,5,3},{1,3,27},{0,4,107},{0,4,42},{2,6,10},{2,6,10},{2,6,10},{2,5,13},{3,3,50},{1,5,2},{1,5,2},{0,4,17},{8,0,50},{0,4,17},{7,0,72},{2,7,4},{3,5,1},
+{1,5,1},{7,0,72},{10,1,72},{1,5,1},{0,4,80},{10,1,72},{0,4,80},{2,0,90},{2,0,90},{2,0,90},{2,0,90},{1,5,2},{1,5,2},{1,5,2},{1,3,2},{0,3,20},{0,3,20},{3,10,154},{3,8,81},{3,6,106},{3,6,82},{2,10,248},{2,7,99},{2,6,5},{2,5,99},{0,7,308},{0,5,100},{3,10,90},{3,8,17},{4,6,27},{3,6,18},{6,3,243},
+{1,8,73},{2,6,5},{1,5,90},{8,3,243},{1,5,90},{3,8,81},{3,8,81},{3,8,81},{3,6,81},{2,8,52},{2,6,4},{2,6,4},{2,5,18},{0,6,72},{0,5,19},{3,8,17},{3,8,17},{3,8,17},{3,6,17},{6,1,50},{2,6,4},{2,6,4},{1,5,9},{11,0,50},{1,5,9},{8,1,72},{3,8,1},{4,6,2},{3,6,2},{8,1,72},{6,5,72},{3,6,2},
+{0,5,90},{6,5,72},{0,5,90},{3,0,80},{3,0,80},{3,0,80},{3,0,80},{2,6,0},{2,6,0},{2,6,0},{2,4,4},{0,6,8},{0,6,8},{4,10,164},{4,9,94},{4,7,107},{4,7,95},{3,11,248},{3,8,89},{3,7,5},{3,6,99},{0,9,253},{1,6,100},{4,10,83},{4,9,13},{4,7,26},{4,7,14},{8,2,243},{2,9,73},{3,7,5},{2,6,90},{12,2,243},
+{2,6,90},{4,8,91},{4,8,91},{4,8,91},{4,7,94},{3,9,52},{3,7,4},{3,7,4},{3,6,18},{0,8,50},{1,6,19},{4,8,10},{4,8,10},{4,8,10},{4,7,13},{8,0,50},{3,7,4},{3,7,4},{2,6,9},{5,5,50},{2,6,9},{9,2,72},{4,9,4},{5,7,2},{3,7,5},{9,2,72},{17,0,72},{3,7,5},{0,6,90},{17,0,72},{0,6,90},{4,0,90},
+{4,0,90},{4,0,90},{4,0,90},{3,7,0},{3,7,0},{3,7,0},{3,5,4},{1,7,8},{1,7,8},{5,11,164},{5,10,94},{5,8,106},{5,8,94},{4,11,245},{4,9,97},{4,8,3},{4,7,107},{0,11,249},{2,7,100},{5,11,83},{5,10,13},{5,8,25},{5,8,13},{9,3,243},{3,10,73},{4,8,2},{3,7,90},{18,0,243},{3,7,90},{5,9,91},{5,9,91},{5,9,91},
+{5,8,94},{4,9,53},{4,8,3},{4,8,3},{4,7,26},{1,9,50},{2,7,19},{5,9,10},{5,9,10},{5,9,10},{5,8,13},{9,1,50},{4,8,2},{4,8,2},{3,7,9},{16,0,50},{3,7,9},{10,3,72},{5,10,4},{6,8,1},{4,8,1},{10,3,72},{18,1,72},{4,8,1},{0,7,90},{18,1,72},{0,7,90},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{4,8,2},
+{4,8,2},{4,8,2},{4,6,2},{1,8,9},{1,8,9},{6,12,164},{6,11,94},{6,9,106},{6,9,94},{5,12,245},{5,10,97},{5,9,3},{5,8,97},{1,12,252},{3,8,85},{6,12,83},{6,11,13},{6,9,25},{6,9,13},{10,4,243},{4,11,76},{5,9,2},{4,8,81},{19,1,243},{4,8,81},{6,10,91},{6,10,91},{6,10,91},{6,9,94},{5,10,53},{5,9,3},{5,9,3},
+{5,7,27},{2,10,50},{3,8,21},{6,10,10},{6,10,10},{6,10,10},{6,9,13},{10,2,50},{5,9,2},{5,9,2},{4,8,17},{17,1,50},{4,8,17},{11,4,72},{6,11,4},{7,9,1},{5,9,1},{11,4,72},{19,2,72},{5,9,1},{0,8,80},{19,2,72},{0,8,80},{6,0,90},{6,0,90},{6,0,90},{6,0,90},{5,9,2},{5,9,2},{5,9,2},{5,7,2},{3,8,5},
+{3,8,5},{7,14,154},{7,12,81},{7,10,106},{7,10,82},{6,14,248},{6,11,99},{6,10,5},{6,9,99},{2,13,244},{4,9,100},{7,14,90},{7,12,17},{8,10,27},{7,10,18},{13,2,243},{5,12,73},{6,10,5},{5,9,90},{22,1,243},{5,9,90},{7,12,81},{7,12,81},{7,12,81},{7,10,81},{6,12,52},{6,10,4},{6,10,4},{6,9,18},{3,11,53},{4,9,19},{7,12,17},
+{7,12,17},{7,12,17},{7,10,17},{13,0,50},{6,10,4},{6,10,4},{5,9,9},{20,1,50},{5,9,9},{14,2,72},{7,12,1},{8,10,2},{7,10,2},{14,2,72},{25,0,72},{7,10,2},{0,9,90},{25,0,72},{0,9,90},{7,0,80},{7,0,80},{7,0,80},{7,0,80},{6,10,0},{6,10,0},{6,10,0},{6,8,4},{4,10,8},{4,10,8},{8,14,164},{8,13,94},{8,11,107},
+{8,11,95},{7,15,248},{7,12,89},{7,11,5},{7,10,99},{3,14,244},{5,10,100},{8,14,83},{8,13,13},{8,11,26},{8,11,14},{14,3,243},{6,13,73},{7,11,5},{6,10,90},{26,0,243},{6,10,90},{8,12,91},{8,12,91},{8,12,91},{8,11,94},{7,13,52},{7,11,4},{7,11,4},{7,10,18},{4,12,50},{5,10,19},{8,12,10},{8,12,10},{8,12,10},{8,11,13},{14,1,50},
+{7,11,4},{7,11,4},{6,10,9},{24,0,50},{6,10,9},{16,1,72},{8,13,4},{9,11,2},{7,11,5},{16,1,72},{26,1,72},{7,11,5},{0,10,90},{26,1,72},{0,10,90},{8,0,90},{8,0,90},{8,0,90},{8,0,90},{7,11,0},{7,11,0},{7,11,0},{7,9,4},{5,11,8},{5,11,8},{9,15,164},{9,14,94},{9,12,106},{9,12,94},{8,15,245},{8,13,97},{8,12,3},
+{8,11,107},{4,15,249},{6,11,100},{9,15,83},{9,14,13},{9,12,25},{9,12,13},{16,2,243},{7,14,73},{8,12,2},{7,11,90},{27,1,243},{7,11,90},{9,13,91},{9,13,91},{9,13,91},{9,12,94},{8,13,53},{8,12,3},{8,12,3},{8,11,26},{5,13,50},{6,11,19},{9,13,10},{9,13,10},{9,13,10},{9,12,13},{16,0,50},{8,12,2},{8,12,2},{7,11,9},{25,1,50},
+{7,11,9},{17,2,72},{9,14,4},{10,12,1},{8,12,1},{17,2,72},{27,2,72},{8,12,1},{0,11,90},{27,2,72},{0,11,90},{9,0,90},{9,0,90},{9,0,90},{9,0,90},{8,12,2},{8,12,2},{8,12,2},{8,10,2},{5,12,9},{5,12,9},{10,16,164},{10,15,94},{10,13,106},{10,13,94},{9,16,245},{9,14,97},{9,13,3},{9,12,97},{5,16,252},{7,12,85},{10,16,83},
+{10,15,13},{10,13,25},{10,13,13},{17,3,243},{8,15,76},{9,13,2},{8,12,81},{28,2,243},{8,12,81},{10,14,91},{10,14,91},{10,14,91},{10,13,94},{9,14,53},{9,13,3},{9,13,3},{9,11,27},{6,14,50},{7,12,21},{10,14,10},{10,14,10},{10,14,10},{10,13,13},{17,1,50},{9,13,2},{9,13,2},{8,12,17},{26,2,50},{8,12,17},{18,3,72},{10,15,4},{11,13,1},
+{9,13,1},{18,3,72},{28,3,72},{9,13,1},{0,12,80},{28,3,72},{0,12,80},{10,0,90},{10,0,90},{10,0,90},{10,0,90},{9,13,2},{9,13,2},{9,13,2},{9,11,2},{7,12,5},{7,12,5},{11,18,154},{11,16,81},{11,14,106},{11,14,82},{10,18,248},{10,15,99},{10,14,5},{10,13,99},{6,17,244},{8,13,100},{11,18,90},{11,16,17},{12,14,27},{11,14,18},{17,6,243},
+{9,16,73},{10,14,5},{9,13,90},{31,2,243},{9,13,90},{11,16,81},{11,16,81},{11,16,81},{11,14,81},{10,16,52},{10,14,4},{10,14,4},{10,13,18},{7,15,53},{8,13,19},{11,16,17},{11,16,17},{11,16,17},{11,14,17},{17,4,50},{10,14,4},{10,14,4},{9,13,9},{29,2,50},{9,13,9},{18,6,72},{11,16,1},{12,14,2},{11,14,2},{18,6,72},{31,3,72},{11,14,2},
+{0,13,90},{31,3,72},{0,13,90},{11,0,80},{11,0,80},{11,0,80},{11,0,80},{10,14,0},{10,14,0},{10,14,0},{10,12,4},{8,14,8},{8,14,8},{12,18,164},{12,17,94},{12,15,107},{12,15,95},{11,19,248},{11,16,89},{11,15,5},{11,14,99},{7,18,244},{9,14,100},{12,18,83},{12,17,13},{12,15,26},{12,15,14},{22,0,243},{10,17,73},{11,15,5},{10,14,90},{30,4,243},
+{10,14,90},{12,16,91},{12,16,91},{12,16,91},{12,15,94},{11,17,52},{11,15,4},{11,15,4},{11,14,18},{8,16,50},{9,14,19},{12,16,10},{12,16,10},{12,16,10},{12,15,13},{18,5,50},{11,15,4},{11,15,4},{10,14,9},{30,3,50},{10,14,9},{23,0,72},{12,17,4},{13,15,2},{11,15,5},{23,0,72},{30,5,72},{11,15,5},{0,14,90},{30,5,72},{0,14,90},{12,0,90},
+{12,0,90},{12,0,90},{12,0,90},{11,15,0},{11,15,0},{11,15,0},{11,13,4},{9,15,8},{9,15,8},{13,19,164},{13,18,94},{13,16,106},{13,16,94},{12,19,245},{12,17,97},{12,16,3},{12,15,107},{8,19,249},{10,15,100},{13,19,83},{13,18,13},{13,16,25},{13,16,13},{23,1,243},{11,18,73},{12,16,2},{11,15,90},{31,5,243},{11,15,90},{13,17,91},{13,17,91},{13,17,91},
+{13,16,94},{12,17,53},{12,16,3},{12,16,3},{12,15,26},{9,17,50},{10,15,19},{13,17,10},{13,17,10},{13,17,10},{13,16,13},{20,4,50},{12,16,2},{12,16,2},{11,15,9},{29,5,50},{11,15,9},{24,1,72},{13,18,4},{14,16,1},{12,16,1},{24,1,72},{31,6,72},{12,16,1},{0,15,90},{31,6,72},{0,15,90},{13,0,90},{13,0,90},{13,0,90},{13,0,90},{12,16,2},
+{12,16,2},{12,16,2},{12,14,2},{9,16,9},{9,16,9},{14,20,164},{14,19,94},{14,17,106},{14,17,94},{13,20,245},{13,18,97},{13,17,3},{13,16,97},{9,20,252},{11,16,85},{14,20,83},{14,19,13},{14,17,25},{14,17,13},{24,2,243},{12,19,76},{13,17,2},{12,16,81},{27,9,243},{12,16,81},{14,18,91},{14,18,91},{14,18,91},{14,17,94},{13,18,53},{13,17,3},{13,17,3},
+{13,15,27},{10,18,50},{11,16,21},{14,18,10},{14,18,10},{14,18,10},{14,17,13},{24,0,50},{13,17,2},{13,17,2},{12,16,17},{30,6,50},{12,16,17},{25,2,72},{14,19,4},{15,17,1},{13,17,1},{25,2,72},{27,10,72},{13,17,1},{0,16,80},{27,10,72},{0,16,80},{14,0,90},{14,0,90},{14,0,90},{14,0,90},{13,17,2},{13,17,2},{13,17,2},{13,15,2},{11,16,5},
+{11,16,5},{15,22,154},{15,20,81},{15,18,106},{15,18,82},{14,22,248},{14,19,99},{14,18,5},{14,17,99},{10,21,244},{12,17,100},{15,22,90},{15,20,17},{16,18,27},{15,18,18},{27,0,243},{13,20,73},{14,18,5},{13,17,90},{30,9,243},{13,17,90},{15,20,81},{15,20,81},{15,20,81},{15,18,81},{14,20,52},{14,18,4},{14,18,4},{14,17,18},{11,19,53},{12,17,19},{15,20,17},
+{15,20,17},{15,20,17},{15,18,17},{24,3,50},{14,18,4},{14,18,4},{13,17,9},{28,9,50},{13,17,9},{22,10,72},{15,20,1},{16,18,2},{15,18,2},{22,10,72},{30,10,72},{15,18,2},{0,17,90},{30,10,72},{0,17,90},{15,0,80},{15,0,80},{15,0,80},{15,0,80},{14,18,0},{14,18,0},{14,18,0},{14,16,4},{12,18,8},{12,18,8},{16,22,164},{16,21,94},{16,19,107},
+{16,19,95},{15,23,248},{15,20,89},{15,19,5},{15,18,99},{11,22,244},{13,18,100},{16,22,83},{16,21,13},{16,19,26},{16,19,14},{26,4,243},{14,21,73},{15,19,5},{14,18,90},{31,10,243},{14,18,90},{16,20,91},{16,20,91},{16,20,91},{16,19,94},{15,21,52},{15,19,4},{15,19,4},{15,18,18},{12,20,50},{13,18,19},{16,20,10},{16,20,10},{16,20,10},{16,19,13},{22,9,50},
+{15,19,4},{15,19,4},{14,18,9},{29,10,50},{14,18,9},{27,4,72},{16,21,4},{17,19,2},{15,19,5},{27,4,72},{31,11,72},{15,19,5},{0,18,90},{31,11,72},{0,18,90},{16,0,90},{16,0,90},{16,0,90},{16,0,90},{15,19,0},{15,19,0},{15,19,0},{15,17,4},{13,19,8},{13,19,8},{17,23,164},{17,22,94},{17,20,106},{17,20,94},{16,23,245},{16,21,97},{16,20,3},
+{16,19,107},{12,23,249},{14,19,100},{17,23,83},{17,22,13},{17,20,25},{17,20,13},{30,0,243},{15,22,73},{16,20,2},{15,19,90},{30,12,243},{15,19,90},{17,21,91},{17,21,91},{17,21,91},{17,20,94},{16,21,53},{16,20,3},{16,20,3},{16,19,26},{13,21,50},{14,19,19},{17,21,10},{17,21,10},{17,21,10},{17,20,13},{24,8,50},{16,20,2},{16,20,2},{15,19,9},{30,11,50},
+{15,19,9},{31,0,72},{17,22,4},{18,20,1},{16,20,1},{31,0,72},{30,13,72},{16,20,1},{0,19,90},{30,13,72},{0,19,90},{17,0,90},{17,0,90},{17,0,90},{17,0,90},{16,20,2},{16,20,2},{16,20,2},{16,18,2},{13,20,9},{13,20,9},{18,24,164},{18,23,94},{18,21,106},{18,21,94},{17,24,245},{17,22,97},{17,21,3},{17,20,97},{13,24,252},{15,20,85},{18,24,83},
+{18,23,13},{18,21,25},{18,21,13},{31,1,243},{16,23,76},{17,21,2},{16,20,81},{31,13,243},{16,20,81},{18,22,91},{18,22,91},{18,22,91},{18,21,94},{17,22,53},{17,21,3},{17,21,3},{17,19,27},{14,22,50},{15,20,21},{18,22,10},{18,22,10},{18,22,10},{18,21,13},{28,4,50},{17,21,2},{17,21,2},{16,20,17},{29,13,50},{16,20,17},{29,6,72},{18,23,4},{19,21,1},
+{17,21,1},{29,6,72},{31,14,72},{17,21,1},{0,20,80},{31,14,72},{0,20,80},{18,0,90},{18,0,90},{18,0,90},{18,0,90},{17,21,2},{17,21,2},{17,21,2},{17,19,2},{15,20,5},{15,20,5},{19,26,154},{19,24,81},{19,22,106},{19,22,82},{18,26,248},{18,23,99},{18,22,5},{18,21,99},{14,25,244},{16,21,100},{19,26,90},{19,24,17},{20,22,27},{19,22,18},{31,4,243},
+{17,24,73},{18,22,5},{17,21,90},{24,19,243},{17,21,90},{19,24,81},{19,24,81},{19,24,81},{19,22,81},{18,24,52},{18,22,4},{18,22,4},{18,21,18},{15,23,53},{16,21,19},{19,24,17},{19,24,17},{19,24,17},{19,22,17},{31,2,50},{18,22,4},{18,22,4},{17,21,9},{27,16,50},{17,21,9},{26,14,72},{19,24,1},{20,22,2},{19,22,2},{26,14,72},{22,21,72},{19,22,2},
+{0,21,90},{22,21,72},{0,21,90},{19,0,80},{19,0,80},{19,0,80},{19,0,80},{18,22,0},{18,22,0},{18,22,0},{18,20,4},{16,22,8},{16,22,8},{20,26,164},{20,25,94},{20,23,107},{20,23,95},{19,27,248},{19,24,89},{19,23,5},{19,22,99},{15,26,244},{17,22,100},{20,26,83},{20,25,13},{20,23,26},{20,23,14},{30,8,243},{18,25,73},{19,23,5},{18,22,90},{28,18,243},
+{18,22,90},{20,24,91},{20,24,91},{20,24,91},{20,23,94},{19,25,52},{19,23,4},{19,23,4},{19,22,18},{16,24,50},{17,22,19},{20,24,10},{20,24,10},{20,24,10},{20,23,13},{26,13,50},{19,23,4},{19,23,4},{18,22,9},{21,21,50},{18,22,9},{31,8,72},{20,25,4},{21,23,2},{19,23,5},{31,8,72},{28,19,72},{19,23,5},{0,22,90},{28,19,72},{0,22,90},{20,0,90},
+{20,0,90},{20,0,90},{20,0,90},{19,23,0},{19,23,0},{19,23,0},{19,21,4},{17,23,8},{17,23,8},{21,27,164},{21,26,94},{21,24,106},{21,24,94},{20,27,245},{20,25,97},{20,24,3},{20,23,107},{16,27,249},{18,23,100},{21,27,83},{21,26,13},{21,24,25},{21,24,13},{31,9,243},{19,26,73},{20,24,2},{19,23,90},{29,19,243},{19,23,90},{21,25,91},{21,25,91},{21,25,91},
+{21,24,94},{20,25,53},{20,24,3},{20,24,3},{20,23,26},{17,25,50},{18,23,19},{21,25,10},{21,25,10},{21,25,10},{21,24,13},{28,12,50},{20,24,2},{20,24,2},{19,23,9},{22,22,50},{19,23,9},{29,14,72},{21,26,4},{22,24,1},{20,24,1},{29,14,72},{29,20,72},{20,24,1},{0,23,90},{29,20,72},{0,23,90},{21,0,90},{21,0,90},{21,0,90},{21,0,90},{20,24,2},
+{20,24,2},{20,24,2},{20,22,2},{17,24,9},{17,24,9},{22,28,164},{22,27,94},{22,25,106},{22,25,94},{21,28,245},{21,26,97},{21,25,3},{21,24,97},{17,28,252},{19,24,85},{22,28,83},{22,27,13},{22,25,25},{22,25,13},{29,15,243},{20,27,76},{21,25,2},{20,24,81},{30,20,243},{20,24,81},{22,26,91},{22,26,91},{22,26,91},{22,25,94},{21,26,53},{21,25,3},{21,25,3},
+{21,23,27},{18,26,50},{19,24,21},{22,26,10},{22,26,10},{22,26,10},{22,25,13},{29,13,50},{21,25,2},{21,25,2},{20,24,17},{28,20,50},{20,24,17},{30,15,72},{22,27,4},{23,25,1},{21,25,1},{30,15,72},{30,21,72},{21,25,1},{0,24,80},{30,21,72},{0,24,80},{22,0,90},{22,0,90},{22,0,90},{22,0,90},{21,25,2},{21,25,2},{21,25,2},{21,23,2},{19,24,5},
+{19,24,5},{23,30,154},{23,28,81},{23,26,106},{23,26,82},{22,30,248},{22,27,99},{22,26,5},{22,25,99},{18,29,244},{20,25,100},{23,30,90},{23,28,17},{24,26,27},{23,26,18},{29,18,243},{21,28,73},{22,26,5},{21,25,90},{28,23,243},{21,25,90},{23,28,81},{23,28,81},{23,28,81},{23,26,81},{22,28,52},{22,26,4},{22,26,4},{22,25,18},{19,27,53},{20,25,19},{23,28,17},
+{23,28,17},{23,28,17},{23,26,17},{29,16,50},{22,26,4},{22,26,4},{21,25,9},{31,20,50},{21,25,9},{30,18,72},{23,28,1},{24,26,2},{23,26,2},{30,18,72},{26,25,72},{23,26,2},{0,25,90},{26,25,72},{0,25,90},{23,0,80},{23,0,80},{23,0,80},{23,0,80},{22,26,0},{22,26,0},{22,26,0},{22,24,4},{20,26,8},{20,26,8},{24,30,164},{24,29,94},{24,27,107},
+{24,27,95},{23,31,248},{23,28,89},{23,27,5},{23,26,99},{19,30,244},{21,26,100},{24,30,83},{24,29,13},{24,27,26},{24,27,14},{30,19,243},{22,29,73},{23,27,5},{22,26,90},{27,25,243},{22,26,90},{24,28,91},{24,28,91},{24,28,91},{24,27,94},{23,29,52},{23,27,4},{23,27,4},{23,26,18},{20,28,50},{21,26,19},{24,28,10},{24,28,10},{24,28,10},{24,27,13},{30,17,50},
+{23,27,4},{23,27,4},{22,26,9},{25,25,50},{22,26,9},{31,19,72},{24,29,4},{25,27,2},{23,27,5},{31,19,72},{27,26,72},{23,27,5},{0,26,90},{27,26,72},{0,26,90},{24,0,90},{24,0,90},{24,0,90},{24,0,90},{23,27,0},{23,27,0},{23,27,0},{23,25,4},{21,27,8},{21,27,8},{25,31,164},{25,30,94},{25,28,106},{25,28,94},{24,31,245},{24,29,97},{24,28,3},
+{24,27,107},{20,31,249},{22,27,100},{25,31,83},{25,30,13},{25,28,25},{25,28,13},{29,23,243},{23,30,73},{24,28,2},{23,27,90},{28,26,243},{23,27,90},{25,29,91},{25,29,91},{25,29,91},{25,28,94},{24,29,53},{24,28,3},{24,28,3},{24,27,26},{21,29,50},{22,27,19},{25,29,10},{25,29,10},{25,29,10},{25,28,13},{31,18,50},{24,28,2},{24,28,2},{23,27,9},{26,26,50},
+{23,27,9},{30,23,72},{25,30,4},{26,28,1},{24,28,1},{30,23,72},{28,27,72},{24,28,1},{0,27,90},{28,27,72},{0,27,90},{25,0,90},{25,0,90},{25,0,90},{25,0,90},{24,28,2},{24,28,2},{24,28,2},{24,26,2},{21,28,9},{21,28,9},{26,31,194},{26,31,94},{26,29,106},{26,29,94},{25,31,284},{25,30,97},{25,29,3},{25,28,97},{22,31,253},{23,28,85},{27,31,99},
+{26,31,13},{26,29,25},{26,29,13},{30,24,243},{24,31,76},{25,29,2},{24,28,81},{29,27,243},{24,28,81},{26,30,91},{26,30,91},{26,30,91},{26,29,94},{25,30,53},{25,29,3},{25,29,3},{25,27,27},{22,30,50},{23,28,21},{26,30,10},{26,30,10},{26,30,10},{26,29,13},{30,22,50},{25,29,2},{25,29,2},{24,28,17},{27,27,50},{24,28,17},{31,24,72},{26,31,4},{27,29,1},
+{25,29,1},{31,24,72},{24,31,72},{25,29,1},{0,28,80},{24,31,72},{0,28,80},{26,0,90},{26,0,90},{26,0,90},{26,0,90},{25,29,2},{25,29,2},{25,29,2},{25,27,2},{23,28,5},{23,28,5},{27,31,280},{27,31,120},{27,30,106},{27,30,82},{27,31,328},{26,31,99},{26,30,5},{26,29,99},{24,31,308},{24,29,100},{28,31,105},{28,31,45},{28,30,27},{27,30,18},{30,27,243},
+{26,31,99},{26,30,5},{25,29,90},{30,28,243},{25,29,90},{27,31,84},{27,31,84},{27,31,84},{27,30,81},{26,31,58},{26,30,4},{26,30,4},{26,29,18},{23,31,53},{24,29,19},{27,31,20},{27,31,20},{27,31,20},{27,30,17},{30,25,50},{26,30,4},{26,30,4},{25,29,9},{30,27,50},{25,29,9},{31,27,72},{28,31,20},{28,30,2},{27,30,2},{31,27,72},{30,29,72},{27,30,2},
+{0,29,90},{30,29,72},{0,29,90},{27,0,80},{27,0,80},{27,0,80},{27,0,80},{26,30,0},{26,30,0},{26,30,0},{26,28,4},{24,30,8},{24,30,8},{28,31,331},{28,31,187},{28,31,106},{28,31,94},{28,31,358},{27,31,173},{27,31,4},{27,30,82},{26,31,355},{25,30,83},{29,31,126},{29,31,62},{28,31,25},{28,31,13},{30,29,221},{28,31,121},{27,31,4},{26,30,73},{29,30,221},
+{26,30,73},{28,31,106},{28,31,106},{28,31,106},{28,31,94},{27,31,100},{27,31,4},{27,31,4},{27,30,18},{25,31,72},{25,30,19},{28,31,25},{28,31,25},{28,31,25},{28,31,13},{31,26,50},{27,31,4},{27,31,4},{26,30,9},{29,29,50},{26,30,9},{31,29,61},{29,31,37},{29,31,1},{27,31,4},{31,29,61},{31,30,61},{27,31,4},{0,30,73},{31,30,61},{0,30,73},{28,0,90},
+{28,0,90},{28,0,90},{28,0,90},{27,31,0},{27,31,0},{27,31,0},{27,29,4},{25,31,8},{25,31,8},{29,31,239},{29,31,175},{29,31,139},{29,31,99},{29,31,239},{28,31,122},{28,31,41},{28,31,26},{28,31,233},{26,31,19},{30,31,54},{30,31,38},{30,31,29},{29,31,18},{30,31,93},{29,31,54},{29,31,18},{27,31,9},{31,30,93},{27,31,9},{29,31,139},{29,31,139},{29,31,139},
+{29,31,99},{29,31,139},{28,31,41},{28,31,41},{28,31,26},{27,31,116},{26,31,19},{30,31,29},{30,31,29},{30,31,29},{29,31,18},{30,30,50},{29,31,18},{29,31,18},{27,31,9},{30,30,50},{27,31,9},{31,30,9},{31,31,9},{30,31,4},{30,31,0},{31,30,9},{30,31,9},{30,31,0},{0,31,9},{30,31,9},{0,31,9},{29,0,90},{29,0,90},{29,0,90},{29,0,90},{28,31,5},
+{28,31,5},{28,31,5},{28,30,2},{26,31,10},{26,31,10},{30,31,140},{30,31,124},{30,31,115},{30,31,99},{30,31,131},{29,31,98},{29,31,62},{29,31,2},{29,31,122},{28,31,20},{31,31,25},{31,31,25},{31,31,25},{30,31,18},{31,30,22},{30,31,18},{30,31,9},{29,31,1},{30,31,22},{29,31,1},{30,31,115},{30,31,115},{30,31,115},{30,31,99},{30,31,106},{29,31,62},{29,31,62},
+{29,31,2},{29,31,86},{28,31,20},{31,31,25},{31,31,25},{31,31,25},{30,31,18},{31,30,13},{30,31,9},{30,31,9},{29,31,1},{30,31,13},{29,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{30,0,90},{30,0,90},{30,0,90},{30,0,90},{29,31,26},{29,31,26},{29,31,26},{29,31,2},{28,31,20},
+{28,31,20},{0,6,202},{0,5,52},{0,3,25},{0,3,61},{0,4,442},{0,3,313},{0,3,142},{0,2,318},{0,2,498},{0,2,354},{0,6,202},{0,5,52},{0,3,25},{0,3,61},{2,1,441},{0,3,313},{0,3,142},{0,2,318},{1,2,441},{0,2,318},{0,3,0},{0,3,0},{0,3,0},{0,2,1},{0,1,45},{0,1,25},{0,1,25},{0,1,26},{0,1,50},{0,1,35},{0,3,0},
+{0,3,0},{0,3,0},{0,2,1},{1,0,41},{0,1,25},{0,1,25},{0,1,26},{0,1,41},{0,1,26},{2,3,200},{0,5,52},{0,3,25},{0,3,61},{2,3,200},{3,2,200},{0,3,61},{0,2,218},{3,2,200},{0,2,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,9,200},{0,7,20},{0,5,20},
+{0,4,25},{0,6,686},{0,5,433},{0,4,169},{0,3,443},{0,3,794},{0,3,524},{0,9,200},{0,7,20},{0,5,20},{0,4,25},{3,1,686},{0,5,433},{0,4,169},{0,3,443},{6,0,686},{0,3,443},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{0,3,145},{0,2,85},{0,2,85},{0,2,101},{0,1,178},{0,1,115},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{1,1,145},
+{0,2,85},{0,2,85},{0,2,101},{3,0,145},{0,2,101},{3,4,200},{0,7,20},{1,4,16},{0,4,25},{3,4,200},{9,0,200},{0,4,25},{0,3,218},{9,0,200},{0,3,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,11,257},{0,9,54},{1,6,85},{0,5,65},{0,9,728},{0,6,371},{0,5,80},
+{0,4,377},{0,5,949},{0,4,521},{1,10,201},{1,8,18},{1,6,21},{1,5,26},{4,2,723},{0,6,371},{0,5,80},{0,4,377},{7,1,723},{0,4,377},{0,8,50},{0,8,50},{0,8,50},{0,5,49},{0,5,164},{0,4,50},{0,4,50},{0,3,65},{0,3,245},{0,2,126},{1,7,2},{1,7,2},{1,7,2},{1,4,5},{2,2,162},{0,4,50},{0,4,50},{0,3,65},{2,2,162},
+{0,3,65},{7,0,200},{0,9,5},{2,5,16},{0,5,16},{7,0,200},{10,1,200},{0,5,16},{0,4,208},{10,1,200},{0,4,208},{0,0,49},{0,0,49},{0,0,49},{0,0,49},{0,2,1},{0,2,1},{0,2,1},{0,1,4},{0,1,13},{0,1,13},{1,12,315},{1,10,118},{1,7,178},{1,6,129},{0,11,724},{0,8,289},{0,6,34},{0,5,308},{0,6,1087},{0,5,533},{2,11,201},
+{2,9,18},{2,7,21},{2,6,26},{5,3,723},{0,8,289},{0,6,34},{0,5,308},{8,2,723},{0,5,308},{1,9,114},{1,9,114},{1,9,114},{1,6,113},{0,8,162},{0,6,18},{0,6,18},{0,4,25},{0,4,338},{0,3,162},{2,8,2},{2,8,2},{2,8,2},{2,5,5},{3,3,162},{0,6,18},{0,6,18},{0,4,25},{8,0,162},{0,4,25},{6,4,200},{1,10,5},{3,6,16},
+{1,6,16},{6,4,200},{14,0,200},{1,6,16},{0,5,208},{14,0,200},{0,5,208},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,5,0},{0,5,0},{0,5,0},{0,3,0},{0,2,61},{0,2,61},{2,14,410},{2,11,209},{2,8,288},{2,7,234},{0,14,739},{0,10,254},{0,8,33},{0,6,270},{0,8,1131},{0,6,450},{3,12,200},{3,10,13},{3,8,25},{3,7,29},{6,4,723},
+{0,10,238},{0,8,17},{0,6,254},{14,0,723},{0,6,254},{2,11,209},{2,11,209},{2,11,209},{2,7,209},{0,11,178},{0,8,17},{0,8,17},{0,5,18},{0,6,376},{0,5,123},{3,9,0},{3,9,0},{3,9,0},{3,7,4},{6,1,162},{0,8,1},{0,8,1},{0,5,2},{11,0,162},{0,5,2},{9,2,200},{2,11,1},{4,7,25},{0,8,17},{9,2,200},{17,0,200},{0,8,17},
+{0,6,218},{17,0,200},{0,6,218},{2,0,208},{2,0,208},{2,0,208},{2,0,208},{0,8,16},{0,8,16},{0,8,16},{1,4,17},{0,4,80},{0,4,80},{3,15,410},{3,12,212},{3,9,288},{3,8,224},{1,15,739},{1,11,254},{1,9,33},{1,7,270},{0,9,1013},{0,7,308},{4,13,201},{4,11,21},{4,9,21},{4,8,26},{10,0,723},{0,12,227},{1,9,17},{0,7,227},{15,1,723},
+{0,7,227},{3,11,212},{3,11,212},{3,11,212},{3,8,208},{2,10,180},{1,9,17},{1,9,17},{1,6,18},{0,8,306},{0,6,41},{4,10,2},{4,10,2},{4,10,2},{4,7,5},{8,0,162},{1,9,1},{1,9,1},{1,6,2},{5,5,162},{1,6,2},{10,3,200},{3,12,4},{5,8,16},{3,8,16},{10,3,200},{18,1,200},{3,8,16},{0,7,218},{18,1,200},{0,7,218},{3,0,208},
+{3,0,208},{3,0,208},{3,0,208},{1,9,16},{1,9,16},{1,9,16},{2,5,17},{0,6,40},{0,6,40},{4,15,426},{4,13,223},{4,10,283},{4,9,234},{2,16,739},{2,12,267},{2,10,33},{2,8,273},{0,11,913},{0,8,225},{5,14,201},{5,12,18},{5,10,21},{5,9,26},{11,1,723},{0,13,208},{2,10,17},{0,8,209},{16,2,723},{0,8,209},{4,12,219},{4,12,219},{4,12,219},
+{4,9,218},{3,11,180},{2,10,17},{2,10,17},{2,7,18},{0,9,229},{0,7,27},{5,11,2},{5,11,2},{5,11,2},{5,8,5},{9,1,162},{2,10,1},{2,10,1},{2,7,2},{16,0,162},{2,7,2},{11,4,200},{3,14,4},{6,9,16},{4,9,16},{11,4,200},{19,2,200},{4,9,16},{0,8,208},{19,2,200},{0,8,208},{4,0,218},{4,0,218},{4,0,218},{4,0,218},{2,10,16},
+{2,10,16},{2,10,16},{3,6,17},{0,8,17},{0,8,17},{5,16,420},{5,14,223},{5,11,283},{5,10,234},{3,17,739},{3,13,267},{3,11,33},{3,9,273},{0,13,868},{0,9,213},{6,15,201},{6,13,18},{6,11,21},{6,10,26},{12,2,723},{0,15,204},{3,11,17},{1,9,209},{22,0,723},{1,9,209},{5,13,219},{5,13,219},{5,13,219},{5,10,218},{3,14,180},{3,11,17},{3,11,17},
+{3,8,20},{0,11,189},{1,8,17},{6,12,2},{6,12,2},{6,12,2},{6,9,5},{10,2,162},{3,11,1},{3,11,1},{2,8,1},{17,1,162},{2,8,1},{15,0,200},{5,14,5},{7,10,16},{5,10,16},{15,0,200},{20,3,200},{5,10,16},{0,9,208},{20,3,200},{0,9,208},{5,0,218},{5,0,218},{5,0,218},{5,0,218},{3,11,16},{3,11,16},{3,11,16},{3,8,20},{0,9,5},
+{0,9,5},{6,18,410},{6,15,209},{6,12,288},{6,11,234},{4,18,739},{4,14,254},{4,12,33},{4,10,270},{0,15,804},{2,10,227},{7,16,200},{7,14,13},{7,12,25},{7,11,29},{15,0,723},{1,16,209},{4,12,17},{2,10,218},{20,3,723},{2,10,218},{6,15,209},{6,15,209},{6,15,209},{6,11,209},{4,15,178},{4,12,17},{4,12,17},{4,9,18},{0,13,171},{2,9,26},{7,13,0},
+{7,13,0},{7,13,0},{7,11,4},{13,0,162},{4,12,1},{4,12,1},{4,9,2},{20,1,162},{4,9,2},{16,1,200},{6,15,1},{8,11,25},{4,12,17},{16,1,200},{26,1,200},{4,12,17},{0,10,218},{26,1,200},{0,10,218},{6,0,208},{6,0,208},{6,0,208},{6,0,208},{4,12,16},{4,12,16},{4,12,16},{5,8,17},{1,11,5},{1,11,5},{7,19,410},{7,16,212},{7,13,288},
+{7,12,224},{5,19,739},{5,15,254},{5,13,33},{5,11,270},{0,16,747},{3,11,227},{8,17,201},{8,15,21},{8,13,21},{8,12,26},{14,4,723},{3,16,209},{5,13,17},{3,11,218},{24,2,723},{3,11,218},{7,15,212},{7,15,212},{7,15,212},{7,12,208},{6,14,180},{5,13,17},{5,13,17},{5,10,18},{1,14,171},{3,10,26},{8,14,2},{8,14,2},{8,14,2},{8,11,5},{14,1,162},
+{5,13,1},{5,13,1},{5,10,2},{24,0,162},{5,10,2},{17,2,200},{7,16,4},{9,12,16},{7,12,16},{17,2,200},{27,2,200},{7,12,16},{0,11,218},{27,2,200},{0,11,218},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{5,13,16},{5,13,16},{5,13,16},{6,9,17},{2,12,8},{2,12,8},{8,19,426},{8,17,223},{8,14,283},{8,13,234},{6,20,739},{6,16,267},{6,14,33},
+{6,12,273},{0,18,727},{3,12,218},{9,18,201},{9,16,18},{9,14,21},{9,13,26},{18,0,723},{4,17,208},{6,14,17},{4,12,209},{30,0,723},{4,12,209},{8,16,219},{8,16,219},{8,16,219},{8,13,218},{7,15,180},{6,14,17},{6,14,17},{6,11,18},{2,15,171},{4,11,27},{9,15,2},{9,15,2},{9,15,2},{9,12,5},{16,0,162},{6,14,1},{6,14,1},{6,11,2},{25,1,162},
+{6,11,2},{18,3,200},{7,18,4},{10,13,16},{8,13,16},{18,3,200},{28,3,200},{8,13,16},{0,12,208},{28,3,200},{0,12,208},{8,0,218},{8,0,218},{8,0,218},{8,0,218},{6,14,16},{6,14,16},{6,14,16},{7,10,17},{3,13,8},{3,13,8},{9,20,420},{9,18,223},{9,15,283},{9,14,234},{7,21,739},{7,17,267},{7,15,33},{7,13,273},{1,19,727},{4,13,213},{10,19,201},
+{10,17,18},{10,15,21},{10,14,26},{19,1,723},{4,19,204},{7,15,17},{5,13,209},{31,1,723},{5,13,209},{9,17,219},{9,17,219},{9,17,219},{9,14,218},{7,18,180},{7,15,17},{7,15,17},{7,12,20},{3,16,173},{5,12,17},{10,16,2},{10,16,2},{10,16,2},{10,13,5},{17,1,162},{7,15,1},{7,15,1},{6,12,1},{26,2,162},{6,12,1},{20,2,200},{9,18,5},{11,14,16},
+{9,14,16},{20,2,200},{24,7,200},{9,14,16},{0,13,208},{24,7,200},{0,13,208},{9,0,218},{9,0,218},{9,0,218},{9,0,218},{7,15,16},{7,15,16},{7,15,16},{7,12,20},{4,13,5},{4,13,5},{10,22,410},{10,19,209},{10,16,288},{10,15,234},{8,22,739},{8,18,254},{8,16,33},{8,14,270},{2,20,724},{6,14,227},{11,20,200},{11,18,13},{11,16,25},{11,15,29},{20,2,723},
+{5,20,209},{8,16,17},{6,14,218},{24,7,723},{6,14,218},{10,19,209},{10,19,209},{10,19,209},{10,15,209},{8,19,178},{8,16,17},{8,16,17},{8,13,18},{3,18,170},{6,13,26},{11,17,0},{11,17,0},{11,17,0},{11,15,4},{17,4,162},{8,16,1},{8,16,1},{8,13,2},{29,2,162},{8,13,2},{23,0,200},{10,19,1},{12,15,25},{8,16,17},{23,0,200},{30,5,200},{8,16,17},
+{0,14,218},{30,5,200},{0,14,218},{10,0,208},{10,0,208},{10,0,208},{10,0,208},{8,16,16},{8,16,16},{8,16,16},{9,12,17},{5,15,5},{5,15,5},{11,23,410},{11,20,212},{11,17,288},{11,16,224},{9,23,739},{9,19,254},{9,17,33},{9,15,270},{3,21,724},{7,15,227},{12,21,201},{12,19,21},{12,17,21},{12,16,26},{21,3,723},{7,20,209},{9,17,17},{7,15,218},{28,6,723},
+{7,15,218},{11,19,212},{11,19,212},{11,19,212},{11,16,208},{10,18,180},{9,17,17},{9,17,17},{9,14,18},{5,18,171},{7,14,26},{12,18,2},{12,18,2},{12,18,2},{12,15,5},{18,5,162},{9,17,1},{9,17,1},{9,14,2},{30,3,162},{9,14,2},{24,1,200},{11,20,4},{13,16,16},{11,16,16},{24,1,200},{31,6,200},{11,16,16},{0,15,218},{31,6,200},{0,15,218},{11,0,208},
+{11,0,208},{11,0,208},{11,0,208},{9,17,16},{9,17,16},{9,17,16},{10,13,17},{6,16,8},{6,16,8},{12,23,426},{12,21,223},{12,18,283},{12,17,234},{10,24,739},{10,20,267},{10,18,33},{10,16,273},{4,22,727},{7,16,218},{13,22,201},{13,20,18},{13,18,21},{13,17,26},{22,4,723},{8,21,208},{10,18,17},{8,16,209},{29,7,723},{8,16,209},{12,20,219},{12,20,219},{12,20,219},
+{12,17,218},{11,19,180},{10,18,17},{10,18,17},{10,15,18},{6,19,171},{8,15,27},{13,19,2},{13,19,2},{13,19,2},{13,16,5},{20,4,162},{10,18,1},{10,18,1},{10,15,2},{29,5,162},{10,15,2},{25,2,200},{11,22,4},{14,17,16},{12,17,16},{25,2,200},{27,10,200},{12,17,16},{0,16,208},{27,10,200},{0,16,208},{12,0,218},{12,0,218},{12,0,218},{12,0,218},{10,18,16},
+{10,18,16},{10,18,16},{11,14,17},{7,17,8},{7,17,8},{13,24,420},{13,22,223},{13,19,283},{13,18,234},{11,25,739},{11,21,267},{11,19,33},{11,17,273},{5,23,727},{8,17,213},{14,23,201},{14,21,18},{14,19,21},{14,18,26},{26,0,723},{8,23,204},{11,19,17},{9,17,209},{30,8,723},{9,17,209},{13,21,219},{13,21,219},{13,21,219},{13,18,218},{11,22,180},{11,19,17},{11,19,17},
+{11,16,20},{7,20,173},{9,16,17},{14,20,2},{14,20,2},{14,20,2},{14,17,5},{24,0,162},{11,19,1},{11,19,1},{10,16,1},{30,6,162},{10,16,1},{26,3,200},{13,22,5},{15,18,16},{13,18,16},{26,3,200},{28,11,200},{13,18,16},{0,17,208},{28,11,200},{0,17,208},{13,0,218},{13,0,218},{13,0,218},{13,0,218},{11,19,16},{11,19,16},{11,19,16},{11,16,20},{8,17,5},
+{8,17,5},{14,26,410},{14,23,209},{14,20,288},{14,19,234},{12,26,739},{12,22,254},{12,20,33},{12,18,270},{6,24,724},{10,18,227},{15,24,200},{15,22,13},{15,20,25},{15,19,29},{26,3,723},{9,24,209},{12,20,17},{10,18,218},{28,11,723},{10,18,218},{14,23,209},{14,23,209},{14,23,209},{14,19,209},{12,23,178},{12,20,17},{12,20,17},{12,17,18},{7,22,170},{10,17,26},{15,21,0},
+{15,21,0},{15,21,0},{15,19,4},{24,3,162},{12,20,1},{12,20,1},{12,17,2},{28,9,162},{12,17,2},{27,4,200},{14,23,1},{16,19,25},{12,20,17},{27,4,200},{31,11,200},{12,20,17},{0,18,218},{31,11,200},{0,18,218},{14,0,208},{14,0,208},{14,0,208},{14,0,208},{12,20,16},{12,20,16},{12,20,16},{13,16,17},{9,19,5},{9,19,5},{15,27,410},{15,24,212},{15,21,288},
+{15,20,224},{13,27,739},{13,23,254},{13,21,33},{13,19,270},{7,25,724},{11,19,227},{16,25,201},{16,23,21},{16,21,21},{16,20,26},{28,2,723},{11,24,209},{13,21,17},{11,19,218},{27,13,723},{11,19,218},{15,23,212},{15,23,212},{15,23,212},{15,20,208},{14,22,180},{13,21,17},{13,21,17},{13,18,18},{9,22,171},{11,18,26},{16,22,2},{16,22,2},{16,22,2},{16,19,5},{22,9,162},
+{13,21,1},{13,21,1},{13,18,2},{29,10,162},{13,18,2},{31,0,200},{15,24,4},{17,20,16},{15,20,16},{31,0,200},{30,13,200},{15,20,16},{0,19,218},{30,13,200},{0,19,218},{15,0,208},{15,0,208},{15,0,208},{15,0,208},{13,21,16},{13,21,16},{13,21,16},{14,17,17},{10,20,8},{10,20,8},{16,27,426},{16,25,223},{16,22,283},{16,21,234},{14,28,739},{14,24,267},{14,22,33},
+{14,20,273},{8,26,727},{11,20,218},{17,26,201},{17,24,18},{17,22,21},{17,21,26},{29,3,723},{12,25,208},{14,22,17},{12,20,209},{28,14,723},{12,20,209},{16,24,219},{16,24,219},{16,24,219},{16,21,218},{15,23,180},{14,22,17},{14,22,17},{14,19,18},{10,23,171},{12,19,27},{17,23,2},{17,23,2},{17,23,2},{17,20,5},{24,8,162},{14,22,1},{14,22,1},{14,19,2},{30,11,162},
+{14,19,2},{29,6,200},{15,26,4},{18,21,16},{16,21,16},{29,6,200},{31,14,200},{16,21,16},{0,20,208},{31,14,200},{0,20,208},{16,0,218},{16,0,218},{16,0,218},{16,0,218},{14,22,16},{14,22,16},{14,22,16},{15,18,17},{11,21,8},{11,21,8},{17,28,420},{17,26,223},{17,23,283},{17,22,234},{15,29,739},{15,25,267},{15,23,33},{15,21,273},{9,27,727},{12,21,213},{18,27,201},
+{18,25,18},{18,23,21},{18,22,26},{30,4,723},{12,27,204},{15,23,17},{13,21,209},{29,15,723},{13,21,209},{17,25,219},{17,25,219},{17,25,219},{17,22,218},{15,26,180},{15,23,17},{15,23,17},{15,20,20},{11,24,173},{13,20,17},{18,24,2},{18,24,2},{18,24,2},{18,21,5},{28,4,162},{15,23,1},{15,23,1},{14,20,1},{29,13,162},{14,20,1},{30,7,200},{17,26,5},{19,22,16},
+{17,22,16},{30,7,200},{30,16,200},{17,22,16},{0,21,208},{30,16,200},{0,21,208},{17,0,218},{17,0,218},{17,0,218},{17,0,218},{15,23,16},{15,23,16},{15,23,16},{15,20,20},{12,21,5},{12,21,5},{18,30,410},{18,27,209},{18,24,288},{18,23,234},{16,30,739},{16,26,254},{16,24,33},{16,22,270},{10,28,724},{14,22,227},{19,28,200},{19,26,13},{19,24,25},{19,23,29},{30,7,723},
+{13,28,209},{16,24,17},{14,22,218},{30,16,723},{14,22,218},{18,27,209},{18,27,209},{18,27,209},{18,23,209},{16,27,178},{16,24,17},{16,24,17},{16,21,18},{11,26,170},{14,21,26},{19,25,0},{19,25,0},{19,25,0},{19,23,4},{31,2,162},{16,24,1},{16,24,1},{16,21,2},{27,16,162},{16,21,2},{31,8,200},{18,27,1},{20,23,25},{16,24,17},{31,8,200},{28,19,200},{16,24,17},
+{0,22,218},{28,19,200},{0,22,218},{18,0,208},{18,0,208},{18,0,208},{18,0,208},{16,24,16},{16,24,16},{16,24,16},{17,20,17},{13,23,5},{13,23,5},{19,31,410},{19,28,212},{19,25,288},{19,24,224},{17,31,739},{17,27,254},{17,25,33},{17,23,270},{11,29,724},{15,23,227},{20,29,201},{20,27,21},{20,25,21},{20,24,26},{29,11,723},{15,28,209},{17,25,17},{15,23,218},{31,17,723},
+{15,23,218},{19,27,212},{19,27,212},{19,27,212},{19,24,208},{18,26,180},{17,25,17},{17,25,17},{17,22,18},{13,26,171},{15,22,26},{20,26,2},{20,26,2},{20,26,2},{20,23,5},{26,13,162},{17,25,1},{17,25,1},{17,22,2},{21,21,162},{17,22,2},{29,14,200},{19,28,4},{21,24,16},{19,24,16},{29,14,200},{29,20,200},{19,24,16},{0,23,218},{29,20,200},{0,23,218},{19,0,208},
+{19,0,208},{19,0,208},{19,0,208},{17,25,16},{17,25,16},{17,25,16},{18,21,17},{14,24,8},{14,24,8},{20,31,426},{20,29,223},{20,26,283},{20,25,234},{19,30,740},{18,28,267},{18,26,33},{18,24,273},{12,30,727},{15,24,218},{21,30,201},{21,28,18},{21,26,21},{21,25,26},{30,12,723},{16,29,208},{18,26,17},{16,24,209},{27,21,723},{16,24,209},{20,28,219},{20,28,219},{20,28,219},
+{20,25,218},{19,27,180},{18,26,17},{18,26,17},{18,23,18},{14,27,171},{16,23,27},{21,27,2},{21,27,2},{21,27,2},{21,24,5},{28,12,162},{18,26,1},{18,26,1},{18,23,2},{22,22,162},{18,23,2},{30,15,200},{19,30,4},{22,25,16},{20,25,16},{30,15,200},{30,21,200},{20,25,16},{0,24,208},{30,21,200},{0,24,208},{20,0,218},{20,0,218},{20,0,218},{20,0,218},{18,26,16},
+{18,26,16},{18,26,16},{19,22,17},{15,25,8},{15,25,8},{21,31,468},{21,30,223},{21,27,283},{21,26,234},{20,31,749},{19,29,267},{19,27,33},{19,25,273},{13,31,727},{16,25,213},{22,31,201},{22,29,18},{22,27,21},{22,26,26},{31,13,723},{16,31,204},{19,27,17},{17,25,209},{28,22,723},{17,25,209},{21,29,219},{21,29,219},{21,29,219},{21,26,218},{19,30,180},{19,27,17},{19,27,17},
+{19,24,20},{15,28,173},{17,24,17},{22,28,2},{22,28,2},{22,28,2},{22,25,5},{29,13,162},{19,27,1},{19,27,1},{18,24,1},{28,20,162},{18,24,1},{31,16,200},{21,30,5},{23,26,16},{21,26,16},{31,16,200},{31,22,200},{21,26,16},{0,25,208},{31,22,200},{0,25,208},{21,0,218},{21,0,218},{21,0,218},{21,0,218},{19,27,16},{19,27,16},{19,27,16},{19,24,20},{16,25,5},
+{16,25,5},{22,31,570},{22,31,209},{22,28,288},{22,27,234},{21,31,804},{20,30,254},{20,28,33},{20,26,270},{15,31,753},{18,26,227},{23,31,232},{23,30,13},{23,28,25},{23,27,29},{31,16,723},{19,31,216},{20,28,17},{18,26,218},{31,22,723},{18,26,218},{22,31,209},{22,31,209},{22,31,209},{22,27,209},{20,31,178},{20,28,17},{20,28,17},{20,25,18},{15,30,170},{18,25,26},{23,29,0},
+{23,29,0},{23,29,0},{23,27,4},{29,16,162},{20,28,1},{20,28,1},{20,25,2},{31,20,162},{20,25,2},{31,19,200},{22,31,1},{24,27,25},{20,28,17},{31,19,200},{27,26,200},{20,28,17},{0,26,218},{27,26,200},{0,26,218},{22,0,208},{22,0,208},{22,0,208},{22,0,208},{20,28,16},{20,28,16},{20,28,16},{21,24,17},{17,27,5},{17,27,5},{23,31,696},{23,31,237},{23,29,288},
+{23,28,224},{23,31,888},{21,31,254},{21,29,33},{21,27,270},{17,31,824},{19,27,227},{24,31,273},{24,31,21},{24,29,21},{24,28,26},{30,20,723},{20,31,233},{21,29,17},{19,27,218},{30,24,723},{19,27,218},{23,31,212},{23,31,212},{23,31,212},{23,28,208},{22,30,180},{21,29,17},{21,29,17},{21,26,18},{17,30,171},{19,26,26},{24,30,2},{24,30,2},{24,30,2},{24,27,5},{30,17,162},
+{21,29,1},{21,29,1},{21,26,2},{25,25,162},{21,26,2},{30,23,200},{24,31,20},{25,28,16},{23,28,16},{30,23,200},{28,27,200},{23,28,16},{0,27,218},{28,27,200},{0,27,218},{23,0,208},{23,0,208},{23,0,208},{23,0,208},{21,29,16},{21,29,16},{21,29,16},{22,25,17},{18,28,8},{18,28,8},{25,31,804},{24,31,334},{24,30,283},{24,29,234},{24,31,957},{22,31,297},{22,30,33},
+{22,28,273},{20,31,913},{19,28,218},{26,31,313},{25,31,51},{25,30,21},{25,29,26},{31,21,723},{22,31,281},{22,30,17},{20,28,209},{31,25,723},{20,28,209},{24,31,234},{24,31,234},{24,31,234},{24,29,218},{23,31,180},{22,30,17},{22,30,17},{22,27,18},{18,31,171},{20,27,27},{25,31,2},{25,31,2},{25,31,2},{25,28,5},{31,18,162},{22,30,1},{22,30,1},{22,27,2},{26,26,162},
+{22,27,2},{31,24,200},{25,31,50},{26,29,16},{24,29,16},{31,24,200},{24,31,200},{24,29,16},{0,28,208},{24,31,200},{0,28,208},{24,0,218},{24,0,218},{24,0,218},{24,0,218},{22,30,16},{22,30,16},{22,30,16},{23,26,17},{19,29,8},{19,29,8},{26,31,930},{25,31,492},{25,31,283},{25,30,234},{25,31,1068},{24,31,389},{23,31,33},{23,29,273},{21,31,999},{20,29,213},{27,31,379},
+{26,31,149},{26,31,21},{26,30,26},{29,27,723},{24,31,364},{23,31,17},{21,29,209},{27,29,723},{21,29,209},{25,31,267},{25,31,267},{25,31,267},{25,30,218},{24,31,205},{23,31,17},{23,31,17},{23,28,20},{20,31,189},{21,28,17},{26,31,5},{26,31,5},{26,31,5},{26,29,5},{30,22,162},{23,31,1},{23,31,1},{22,28,1},{27,27,162},{22,28,1},{30,28,200},{27,31,90},{27,30,16},
+{25,30,16},{30,28,200},{28,30,200},{25,30,16},{0,29,208},{28,30,200},{0,29,208},{25,0,218},{25,0,218},{25,0,218},{25,0,218},{23,31,16},{23,31,16},{23,31,16},{23,28,20},{20,29,5},{20,29,5},{27,31,877},{26,31,585},{26,31,329},{26,31,209},{26,31,990},{25,31,397},{25,31,36},{24,30,165},{23,31,910},{22,30,122},{28,31,306},{28,31,162},{27,31,36},{27,31,4},{31,26,546},
+{26,31,306},{25,31,20},{22,30,113},{29,29,546},{22,30,113},{26,31,329},{26,31,329},{26,31,329},{26,31,209},{25,31,276},{25,31,36},{25,31,36},{24,29,18},{22,31,230},{22,29,26},{27,31,36},{27,31,36},{27,31,36},{27,31,4},{30,25,162},{25,31,20},{25,31,20},{24,29,2},{30,27,162},{24,29,2},{30,30,113},{29,31,61},{28,31,0},{26,31,1},{30,30,113},{30,30,113},{26,31,1},
+{0,30,113},{30,30,113},{0,30,113},{26,0,208},{26,0,208},{26,0,208},{26,0,208},{25,30,17},{25,30,17},{25,30,17},{25,28,17},{21,31,5},{21,31,5},{28,31,731},{27,31,573},{27,31,404},{27,31,244},{27,31,797},{26,31,354},{26,31,98},{25,30,82},{25,31,737},{23,31,58},{29,31,190},{29,31,126},{28,31,65},{28,31,5},{30,29,333},{28,31,185},{27,31,52},{23,31,49},{29,30,333},
+{23,31,49},{27,31,404},{27,31,404},{27,31,404},{27,31,244},{27,31,356},{26,31,98},{26,31,98},{25,30,18},{24,31,315},{23,30,26},{28,31,65},{28,31,65},{28,31,65},{28,31,5},{31,26,162},{27,31,52},{27,31,52},{25,30,2},{29,29,162},{25,30,2},{31,30,25},{30,31,13},{30,31,4},{29,31,1},{31,30,25},{30,31,25},{29,31,1},{0,31,49},{30,31,25},{0,31,49},{27,0,208},
+{27,0,208},{27,0,208},{27,0,208},{26,31,17},{26,31,17},{26,31,17},{26,29,17},{23,31,9},{23,31,9},{29,31,642},{28,31,524},{28,31,443},{28,31,299},{28,31,623},{28,31,335},{27,31,201},{26,31,17},{27,31,610},{24,31,26},{30,31,131},{30,31,115},{29,31,101},{29,31,37},{31,29,193},{29,31,121},{28,31,85},{26,31,1},{29,31,193},{26,31,1},{28,31,443},{28,31,443},{28,31,443},
+{28,31,299},{28,31,398},{27,31,201},{27,31,201},{26,31,17},{26,31,378},{24,31,26},{29,31,101},{29,31,101},{29,31,101},{29,31,37},{31,28,145},{28,31,85},{28,31,85},{26,31,1},{30,30,145},{26,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{28,0,218},{28,0,218},{28,0,218},{28,0,218},{27,31,32},
+{27,31,32},{27,31,32},{27,30,17},{24,31,26},{24,31,26},{29,31,418},{29,31,354},{29,31,318},{29,31,254},{29,31,370},{28,31,223},{28,31,142},{28,31,25},{28,31,358},{26,31,58},{30,31,51},{30,31,35},{30,31,26},{30,31,10},{31,30,54},{30,31,34},{30,31,25},{28,31,0},{30,31,54},{28,31,0},{29,31,318},{29,31,318},{29,31,318},{29,31,254},{29,31,270},{28,31,142},{28,31,142},
+{28,31,25},{27,31,249},{26,31,58},{30,31,26},{30,31,26},{30,31,26},{30,31,10},{30,31,41},{30,31,25},{30,31,25},{28,31,0},{31,30,41},{28,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{29,0,218},{29,0,218},{29,0,218},{29,0,218},{28,31,61},{28,31,61},{28,31,61},{28,31,25},{26,31,58},
+{26,31,58},{0,9,421},{0,7,113},{0,5,5},{0,4,130},{0,6,925},{0,5,658},{0,4,274},{0,3,670},{0,3,1039},{0,3,751},{0,9,421},{0,7,113},{0,5,5},{0,4,130},{3,1,925},{0,5,658},{0,4,274},{0,3,670},{6,0,925},{0,3,670},{0,4,1},{0,4,1},{0,4,1},{0,3,4},{0,2,85},{0,2,45},{0,2,45},{0,1,50},{0,1,98},{0,1,59},{0,4,1},
+{0,4,1},{0,4,1},{0,3,4},{0,2,85},{0,2,45},{0,2,45},{0,1,50},{2,0,85},{0,1,50},{5,1,421},{0,7,113},{0,5,5},{0,4,130},{5,1,421},{9,0,421},{0,4,130},{0,3,445},{9,0,421},{0,3,445},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,12,425},{0,9,52},{0,6,10},
+{0,6,82},{0,8,1261},{0,6,805},{0,5,322},{0,4,833},{0,4,1445},{0,4,977},{0,12,425},{0,9,52},{0,6,10},{0,6,82},{3,3,1261},{0,6,805},{0,5,322},{0,4,833},{8,0,1261},{0,4,833},{0,7,0},{0,7,0},{0,7,0},{0,4,1},{0,3,225},{0,3,117},{0,3,117},{0,2,125},{0,2,257},{0,2,161},{0,7,0},{0,7,0},{0,7,0},{0,4,1},{2,0,221},
+{0,3,117},{0,3,117},{0,2,125},{2,1,221},{0,2,125},{7,0,421},{0,9,52},{1,6,5},{0,6,82},{7,0,421},{10,1,421},{0,6,82},{0,4,433},{10,1,421},{0,4,433},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,14,430},{0,11,29},{0,7,74},{0,7,46},{0,10,1514},{0,8,874},{0,6,307},
+{0,5,917},{0,5,1814},{0,4,1074},{0,14,430},{0,11,29},{1,7,35},{0,7,46},{6,0,1514},{0,8,874},{0,6,307},{0,5,917},{10,0,1514},{0,5,917},{0,10,10},{0,10,10},{0,10,10},{0,6,10},{0,5,340},{0,5,160},{0,5,160},{0,3,169},{0,3,421},{0,3,250},{0,10,10},{0,10,10},{0,10,10},{0,6,10},{2,2,338},{0,5,160},{0,5,160},{0,3,169},{2,2,338},
+{0,3,169},{8,1,421},{0,11,20},{2,7,5},{0,7,37},{8,1,421},{14,0,421},{0,7,37},{0,5,433},{14,0,421},{0,5,433},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,0},{0,1,0},{0,1,0},{0,1,4},{0,0,9},{0,0,9},{1,15,494},{1,12,102},{1,8,137},{1,8,122},{0,12,1517},{0,9,737},{0,7,185},{0,6,794},{0,7,1982},{0,5,1062},{1,15,430},
+{1,12,38},{2,8,34},{1,8,58},{7,1,1514},{0,9,737},{0,7,185},{0,6,794},{11,1,1514},{0,6,794},{1,11,74},{1,11,74},{1,11,74},{1,7,74},{0,8,338},{0,6,98},{0,6,98},{0,4,97},{0,4,514},{0,4,241},{1,11,10},{1,11,10},{1,11,10},{1,7,10},{3,3,338},{0,6,98},{0,6,98},{0,4,97},{8,0,338},{0,4,97},{10,0,421},{0,13,9},{3,8,4},
+{0,8,16},{10,0,421},{17,0,421},{0,8,16},{0,6,433},{17,0,421},{0,6,433},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,2,37},{0,2,37},{1,18,629},{1,14,213},{2,9,354},{1,9,218},{0,15,1517},{0,11,630},{0,9,50},{0,7,670},{0,8,2198},{0,6,1109},{3,15,437},{2,13,41},{3,9,33},{2,9,53},{8,2,1514},
+{0,11,630},{0,9,50},{0,7,670},{12,2,1514},{0,7,670},{1,13,209},{1,13,209},{1,13,209},{1,8,212},{0,11,338},{0,8,41},{0,8,41},{0,5,50},{0,6,680},{0,5,275},{3,10,17},{3,10,17},{3,10,17},{2,8,17},{6,1,338},{0,8,41},{0,8,41},{0,5,50},{11,0,338},{0,5,50},{12,0,421},{0,15,1},{4,9,5},{0,9,1},{12,0,421},{20,0,421},{0,9,1},
+{0,7,445},{20,0,421},{0,7,445},{1,0,208},{1,0,208},{1,0,208},{1,0,208},{0,7,1},{0,7,1},{0,7,1},{0,4,0},{0,3,106},{0,3,106},{2,19,821},{2,15,405},{2,11,570},{2,10,410},{0,18,1514},{0,13,577},{0,10,14},{0,8,602},{0,10,2462},{0,7,1175},{3,17,441},{3,14,41},{4,10,35},{3,10,53},{9,3,1514},{0,13,577},{0,10,14},{0,8,602},{18,0,1514},
+{0,8,602},{2,14,401},{2,14,401},{2,14,401},{2,9,404},{0,13,340},{0,10,13},{0,10,13},{0,6,29},{0,7,851},{0,6,353},{3,13,17},{3,13,17},{3,13,17},{3,9,17},{8,0,338},{0,10,13},{0,10,13},{0,6,29},{5,5,338},{0,6,29},{13,1,421},{1,16,4},{5,10,5},{1,10,1},{13,1,421},{21,1,421},{1,10,1},{0,8,433},{21,1,421},{0,8,433},{2,0,400},
+{2,0,400},{2,0,400},{2,0,400},{0,9,1},{0,9,1},{0,9,1},{0,6,4},{0,4,208},{0,4,208},{3,20,854},{3,16,437},{3,12,597},{3,11,443},{1,19,1515},{0,15,570},{1,11,15},{0,9,582},{0,11,2337},{0,9,933},{4,18,430},{4,15,29},{5,11,35},{4,11,46},{10,4,1514},{0,15,521},{1,11,14},{0,9,533},{19,1,1514},{0,9,533},{3,15,434},{3,15,434},{3,15,434},
+{3,10,437},{1,14,341},{1,11,14},{1,11,14},{1,7,30},{0,8,755},{0,7,222},{4,14,10},{4,14,10},{4,14,10},{4,10,10},{9,1,338},{0,12,2},{0,12,2},{0,7,26},{16,0,338},{0,7,26},{15,0,421},{3,16,4},{6,11,5},{2,11,1},{15,0,421},{25,0,421},{2,11,1},{0,9,433},{25,0,421},{0,9,433},{3,0,433},{3,0,433},{3,0,433},{3,0,433},{1,10,2},
+{1,10,2},{1,10,2},{1,7,5},{0,6,157},{0,6,157},{4,21,866},{4,17,454},{4,13,609},{4,12,461},{2,20,1515},{1,16,570},{2,12,19},{1,10,582},{0,13,2214},{0,10,707},{5,19,430},{5,16,38},{6,12,34},{5,12,58},{14,0,1514},{0,16,458},{2,12,18},{0,10,482},{20,2,1514},{0,10,482},{4,16,445},{4,16,445},{4,16,445},{4,11,449},{2,15,341},{2,12,19},{2,12,19},
+{2,8,26},{0,10,635},{0,8,106},{5,15,10},{5,15,10},{5,15,10},{5,11,10},{10,2,338},{1,13,2},{1,13,2},{1,8,16},{17,1,338},{1,8,16},{16,1,421},{3,18,4},{7,12,4},{3,12,0},{16,1,421},{26,1,421},{3,12,0},{0,10,433},{26,1,421},{0,10,433},{4,0,445},{4,0,445},{4,0,445},{4,0,445},{2,11,2},{2,11,2},{2,11,2},{2,7,10},{0,8,90},
+{0,8,90},{5,22,854},{5,18,438},{5,14,603},{5,13,443},{3,21,1517},{3,16,554},{3,13,21},{3,11,589},{0,15,2046},{0,11,535},{7,19,437},{6,17,41},{7,13,33},{6,13,53},{14,3,1514},{0,18,429},{3,13,21},{0,11,454},{26,0,1514},{0,11,454},{5,17,434},{5,17,434},{5,17,434},{5,12,437},{3,17,340},{3,13,20},{3,13,20},{3,9,29},{0,12,557},{0,10,49},{7,14,17},
+{7,14,17},{7,14,17},{6,12,17},{13,0,338},{2,14,4},{2,14,4},{1,10,10},{20,1,338},{1,10,10},{17,2,421},{4,19,1},{8,13,5},{4,13,1},{17,2,421},{29,1,421},{4,13,1},{0,11,445},{29,1,421},{0,11,445},{5,0,433},{5,0,433},{5,0,433},{5,0,433},{3,12,1},{3,12,1},{3,12,1},{3,9,4},{0,10,40},{0,10,40},{6,23,854},{6,19,438},{6,15,603},
+{6,14,443},{4,22,1515},{3,18,566},{4,14,15},{3,12,578},{0,16,1911},{0,12,458},{7,21,441},{7,18,41},{8,14,35},{7,14,53},{16,2,1514},{0,20,425},{4,14,14},{0,12,433},{27,1,1514},{0,12,433},{6,18,434},{6,18,434},{6,18,434},{6,13,437},{4,17,341},{4,14,14},{4,14,14},{4,10,30},{0,14,477},{0,11,35},{7,17,17},{7,17,17},{7,17,17},{7,13,17},{14,1,338},
+{3,15,4},{3,15,4},{2,11,10},{24,0,338},{2,11,10},{18,3,421},{5,20,4},{9,14,5},{5,14,1},{18,3,421},{30,2,421},{5,14,1},{0,12,433},{30,2,421},{0,12,433},{6,0,433},{6,0,433},{6,0,433},{6,0,433},{4,13,2},{4,13,2},{4,13,2},{4,10,5},{0,12,25},{0,12,25},{7,24,854},{7,20,437},{7,16,597},{7,15,443},{5,23,1515},{4,19,570},{5,15,15},
+{4,13,582},{0,18,1787},{0,13,442},{8,22,430},{8,19,29},{9,15,35},{8,15,46},{17,3,1514},{2,20,425},{5,15,14},{1,13,433},{28,2,1514},{1,13,433},{7,19,434},{7,19,434},{7,19,434},{7,14,437},{5,18,341},{5,15,14},{5,15,14},{5,11,30},{0,16,419},{1,12,45},{8,18,10},{8,18,10},{8,18,10},{8,14,10},{16,0,338},{4,16,2},{4,16,2},{3,12,17},{25,1,338},
+{3,12,17},{20,2,421},{7,20,4},{10,15,5},{6,15,1},{20,2,421},{31,3,421},{6,15,1},{0,13,433},{31,3,421},{0,13,433},{7,0,433},{7,0,433},{7,0,433},{7,0,433},{5,14,2},{5,14,2},{5,14,2},{5,11,5},{0,13,9},{0,13,9},{8,25,866},{8,21,454},{8,17,609},{8,16,461},{6,24,1515},{5,20,570},{6,16,19},{5,14,582},{0,20,1686},{1,14,442},{9,23,430},
+{9,20,38},{10,16,34},{9,16,58},{18,4,1514},{3,21,425},{6,16,18},{2,14,433},{29,3,1514},{2,14,433},{8,20,445},{8,20,445},{8,20,445},{8,15,449},{6,19,341},{6,16,19},{6,16,19},{6,12,26},{0,17,372},{2,13,45},{9,19,10},{9,19,10},{9,19,10},{9,15,10},{17,1,338},{5,17,2},{5,17,2},{5,12,16},{26,2,338},{5,12,16},{23,0,421},{7,22,4},{11,16,4},
+{7,16,0},{23,0,421},{30,5,421},{7,16,0},{0,14,433},{30,5,421},{0,14,433},{8,0,445},{8,0,445},{8,0,445},{8,0,445},{6,15,2},{6,15,2},{6,15,2},{6,11,10},{0,15,5},{0,15,5},{9,26,854},{9,22,438},{9,18,603},{9,17,443},{7,25,1517},{7,20,554},{7,17,21},{7,15,589},{0,22,1614},{2,15,462},{11,23,437},{10,21,41},{11,17,33},{10,17,53},{22,0,1514},
+{3,23,422},{7,17,21},{3,15,446},{30,4,1514},{3,15,446},{9,21,434},{9,21,434},{9,21,434},{9,16,437},{7,21,340},{7,17,20},{7,17,20},{7,13,29},{0,19,347},{3,14,46},{11,18,17},{11,18,17},{11,18,17},{10,16,17},{17,4,338},{6,18,4},{6,18,4},{5,14,10},{29,2,338},{5,14,10},{24,1,421},{8,23,1},{12,17,5},{8,17,1},{24,1,421},{31,6,421},{8,17,1},
+{0,15,445},{31,6,421},{0,15,445},{9,0,433},{9,0,433},{9,0,433},{9,0,433},{7,16,1},{7,16,1},{7,16,1},{7,13,4},{2,16,8},{2,16,8},{10,27,854},{10,23,438},{10,19,603},{10,18,443},{8,26,1515},{7,22,566},{8,18,15},{7,16,578},{0,23,1566},{3,16,443},{11,25,441},{11,22,41},{12,18,35},{11,18,53},{23,1,1514},{4,24,425},{8,18,14},{4,16,433},{31,5,1514},
+{4,16,433},{10,22,434},{10,22,434},{10,22,434},{10,17,437},{8,21,341},{8,18,14},{8,18,14},{8,14,30},{1,20,341},{4,15,35},{11,21,17},{11,21,17},{11,21,17},{11,17,17},{18,5,338},{7,19,4},{7,19,4},{6,15,10},{30,3,338},{6,15,10},{25,2,421},{9,24,4},{13,18,5},{9,18,1},{25,2,421},{29,9,421},{9,18,1},{0,16,433},{29,9,421},{0,16,433},{10,0,433},
+{10,0,433},{10,0,433},{10,0,433},{8,17,2},{8,17,2},{8,17,2},{8,14,5},{3,17,8},{3,17,8},{11,28,854},{11,24,437},{11,20,597},{11,19,443},{9,27,1515},{8,23,570},{9,19,15},{8,17,582},{0,25,1533},{4,17,442},{12,26,430},{12,23,29},{13,19,35},{12,19,46},{24,2,1514},{6,24,425},{9,19,14},{5,17,433},{27,9,1514},{5,17,433},{11,23,434},{11,23,434},{11,23,434},
+{11,18,437},{9,22,341},{9,19,14},{9,19,14},{9,15,30},{2,21,341},{5,16,45},{12,22,10},{12,22,10},{12,22,10},{12,18,10},{20,4,338},{8,20,2},{8,20,2},{7,16,17},{29,5,338},{7,16,17},{26,3,421},{11,24,4},{14,19,5},{10,19,1},{26,3,421},{30,10,421},{10,19,1},{0,17,433},{30,10,421},{0,17,433},{11,0,433},{11,0,433},{11,0,433},{11,0,433},{9,18,2},
+{9,18,2},{9,18,2},{9,15,5},{4,17,9},{4,17,9},{12,29,866},{12,25,454},{12,21,609},{12,20,461},{10,28,1515},{9,24,570},{10,20,19},{9,18,582},{0,27,1521},{5,18,442},{13,27,430},{13,24,38},{14,20,34},{13,20,58},{25,3,1514},{7,25,425},{10,20,18},{6,18,433},{28,10,1514},{6,18,433},{12,24,445},{12,24,445},{12,24,445},{12,19,449},{10,23,341},{10,20,19},{10,20,19},
+{10,16,26},{3,22,341},{6,17,45},{13,23,10},{13,23,10},{13,23,10},{13,19,10},{24,0,338},{9,21,2},{9,21,2},{9,16,16},{30,6,338},{9,16,16},{28,2,421},{11,26,4},{15,20,4},{11,20,0},{28,2,421},{31,11,421},{11,20,0},{0,18,433},{31,11,421},{0,18,433},{12,0,445},{12,0,445},{12,0,445},{12,0,445},{10,19,2},{10,19,2},{10,19,2},{10,15,10},{4,19,5},
+{4,19,5},{13,30,854},{13,26,438},{13,22,603},{13,21,443},{11,29,1517},{11,24,554},{11,21,21},{11,19,589},{1,28,1518},{6,19,462},{15,27,437},{14,25,41},{15,21,33},{14,21,53},{26,4,1514},{7,27,422},{11,21,21},{7,19,446},{31,10,1514},{7,19,446},{13,25,434},{13,25,434},{13,25,434},{13,20,437},{11,25,340},{11,21,20},{11,21,20},{11,17,29},{3,24,339},{7,18,46},{15,22,17},
+{15,22,17},{15,22,17},{14,20,17},{24,3,338},{10,22,4},{10,22,4},{9,18,10},{28,9,338},{9,18,10},{31,0,421},{12,27,1},{16,21,5},{12,21,1},{31,0,421},{30,13,421},{12,21,1},{0,19,445},{30,13,421},{0,19,445},{13,0,433},{13,0,433},{13,0,433},{13,0,433},{11,20,1},{11,20,1},{11,20,1},{11,17,4},{6,20,8},{6,20,8},{14,31,854},{14,27,438},{14,23,603},
+{14,22,443},{12,30,1515},{11,26,566},{12,22,15},{11,20,578},{2,29,1518},{7,20,443},{15,29,441},{15,26,41},{16,22,35},{15,22,53},{30,0,1514},{8,28,425},{12,22,14},{8,20,433},{30,12,1514},{8,20,433},{14,26,434},{14,26,434},{14,26,434},{14,21,437},{12,25,341},{12,22,14},{12,22,14},{12,18,30},{5,24,341},{8,19,35},{15,25,17},{15,25,17},{15,25,17},{15,21,17},{22,9,338},
+{11,23,4},{11,23,4},{10,19,10},{29,10,338},{10,19,10},{31,3,421},{13,28,4},{17,22,5},{13,22,1},{31,3,421},{31,14,421},{13,22,1},{0,20,433},{31,14,421},{0,20,433},{14,0,433},{14,0,433},{14,0,433},{14,0,433},{12,21,2},{12,21,2},{12,21,2},{12,18,5},{7,21,8},{7,21,8},{15,31,878},{15,28,437},{15,24,597},{15,23,443},{13,31,1515},{12,27,570},{13,23,15},
+{12,21,582},{3,30,1518},{8,21,442},{16,30,430},{16,27,29},{17,23,35},{16,23,46},{31,1,1514},{10,28,425},{13,23,14},{9,21,433},{31,13,1514},{9,21,433},{15,27,434},{15,27,434},{15,27,434},{15,22,437},{13,26,341},{13,23,14},{13,23,14},{13,19,30},{6,25,341},{9,20,45},{16,26,10},{16,26,10},{16,26,10},{16,22,10},{24,8,338},{12,24,2},{12,24,2},{11,20,17},{30,11,338},
+{11,20,17},{30,7,421},{15,28,4},{18,23,5},{14,23,1},{30,7,421},{30,16,421},{14,23,1},{0,21,433},{30,16,421},{0,21,433},{15,0,433},{15,0,433},{15,0,433},{15,0,433},{13,22,2},{13,22,2},{13,22,2},{13,19,5},{8,21,9},{8,21,9},{16,31,926},{16,29,454},{16,25,609},{16,24,461},{14,31,1542},{13,28,570},{14,24,19},{13,22,582},{4,31,1521},{9,22,442},{17,31,430},
+{17,28,38},{18,24,34},{17,24,58},{29,7,1514},{11,29,425},{14,24,18},{10,22,433},{27,17,1514},{10,22,433},{16,28,445},{16,28,445},{16,28,445},{16,23,449},{14,27,341},{14,24,19},{14,24,19},{14,20,26},{7,26,341},{10,21,45},{17,27,10},{17,27,10},{17,27,10},{17,23,10},{28,4,338},{13,25,2},{13,25,2},{13,20,16},{29,13,338},{13,20,16},{31,8,421},{15,30,4},{19,24,4},
+{15,24,0},{31,8,421},{31,17,421},{15,24,0},{0,22,433},{31,17,421},{0,22,433},{16,0,445},{16,0,445},{16,0,445},{16,0,445},{14,23,2},{14,23,2},{14,23,2},{14,19,10},{8,23,5},{8,23,5},{17,31,1034},{17,30,438},{17,26,603},{17,25,443},{16,31,1598},{15,28,554},{15,25,21},{15,23,589},{6,31,1535},{10,23,462},{19,31,437},{18,29,41},{19,25,33},{18,25,53},{30,8,1514},
+{11,31,422},{15,25,21},{11,23,446},{28,18,1514},{11,23,446},{17,29,434},{17,29,434},{17,29,434},{17,24,437},{15,29,340},{15,25,20},{15,25,20},{15,21,29},{7,28,339},{11,22,46},{19,26,17},{19,26,17},{19,26,17},{18,24,17},{31,2,338},{14,26,4},{14,26,4},{13,22,10},{27,16,338},{13,22,10},{31,11,421},{16,31,1},{20,25,5},{16,25,1},{31,11,421},{31,19,421},{16,25,1},
+{0,23,445},{31,19,421},{0,23,445},{17,0,433},{17,0,433},{17,0,433},{17,0,433},{15,24,1},{15,24,1},{15,24,1},{15,21,4},{10,24,8},{10,24,8},{18,31,1166},{18,31,438},{18,27,603},{18,26,443},{17,31,1643},{15,30,566},{16,26,15},{15,24,578},{8,31,1566},{11,24,443},{20,31,458},{19,30,41},{20,26,35},{19,26,53},{31,9,1514},{13,31,429},{16,26,14},{12,24,433},{29,19,1514},
+{12,24,433},{18,30,434},{18,30,434},{18,30,434},{18,25,437},{16,29,341},{16,26,14},{16,26,14},{16,22,30},{9,28,341},{12,23,35},{19,29,17},{19,29,17},{19,29,17},{19,25,17},{26,13,338},{15,27,4},{15,27,4},{14,23,10},{21,21,338},{14,23,10},{30,15,421},{18,31,5},{21,26,5},{17,26,1},{30,15,421},{30,21,421},{17,26,1},{0,24,433},{30,21,421},{0,24,433},{18,0,433},
+{18,0,433},{18,0,433},{18,0,433},{16,25,2},{16,25,2},{16,25,2},{16,22,5},{11,25,8},{11,25,8},{20,31,1326},{19,31,470},{19,28,597},{19,27,443},{18,31,1742},{16,31,570},{17,27,15},{16,25,582},{10,31,1638},{12,25,442},{21,31,506},{20,31,29},{21,27,35},{20,27,46},{29,15,1514},{15,31,461},{17,27,14},{13,25,433},{30,20,1514},{13,25,433},{19,31,434},{19,31,434},{19,31,434},
+{19,26,437},{17,30,341},{17,27,14},{17,27,14},{17,23,30},{10,29,341},{13,24,45},{20,30,10},{20,30,10},{20,30,10},{20,26,10},{28,12,338},{16,28,2},{16,28,2},{15,24,17},{22,22,338},{15,24,17},{31,16,421},{20,31,20},{22,27,5},{18,27,1},{31,16,421},{31,22,421},{18,27,1},{0,25,433},{31,22,421},{0,25,433},{19,0,433},{19,0,433},{19,0,433},{19,0,433},{17,26,2},
+{17,26,2},{17,26,2},{17,23,5},{12,25,9},{12,25,9},{21,31,1470},{20,31,561},{20,29,609},{20,28,461},{19,31,1895},{18,31,578},{18,28,19},{17,26,582},{12,31,1761},{13,26,442},{22,31,590},{21,31,59},{22,28,34},{21,28,58},{30,16,1514},{17,31,530},{18,28,18},{14,26,433},{31,21,1514},{14,26,433},{20,31,461},{20,31,461},{20,31,461},{20,27,449},{18,31,341},{18,28,19},{18,28,19},
+{18,24,26},{11,30,341},{14,25,45},{21,31,10},{21,31,10},{21,31,10},{21,27,10},{29,13,338},{17,29,2},{17,29,2},{17,24,16},{28,20,338},{17,24,16},{31,19,421},{21,31,50},{23,28,4},{19,28,0},{31,19,421},{30,24,421},{19,28,0},{0,26,433},{30,24,421},{0,26,433},{20,0,445},{20,0,445},{20,0,445},{20,0,445},{18,27,2},{18,27,2},{18,27,2},{18,23,10},{12,27,5},
+{12,27,5},{22,31,1674},{21,31,753},{21,30,603},{21,29,443},{21,31,2046},{19,31,629},{19,29,21},{19,27,589},{15,31,1917},{14,27,462},{24,31,674},{23,31,120},{23,29,33},{22,29,53},{30,19,1514},{19,31,629},{19,29,21},{15,27,446},{27,25,1514},{15,27,446},{21,31,497},{21,31,497},{21,31,497},{21,28,437},{19,31,388},{19,29,20},{19,29,20},{19,25,29},{12,31,347},{15,26,46},{23,30,17},
+{23,30,17},{23,30,17},{22,28,17},{29,16,338},{18,30,4},{18,30,4},{17,26,10},{31,20,338},{17,26,10},{30,23,421},{23,31,104},{24,29,5},{20,29,1},{30,23,421},{30,26,421},{20,29,1},{0,27,445},{30,26,421},{0,27,445},{21,0,433},{21,0,433},{21,0,433},{21,0,433},{19,28,1},{19,28,1},{19,28,1},{19,25,4},{14,28,8},{14,28,8},{23,31,1902},{22,31,995},{22,31,603},
+{22,30,443},{22,31,2235},{20,31,759},{20,30,15},{19,28,578},{17,31,2118},{15,28,443},{25,31,770},{24,31,250},{24,30,35},{23,30,53},{29,23,1514},{21,31,701},{20,30,14},{16,28,433},{28,26,1514},{16,28,433},{22,31,554},{22,31,554},{22,31,554},{22,29,437},{21,31,437},{20,30,14},{20,30,14},{20,26,30},{14,31,379},{16,27,35},{24,31,25},{24,31,25},{24,31,25},{23,29,17},{30,17,338},
+{19,31,4},{19,31,4},{18,27,10},{25,25,338},{18,27,10},{31,24,421},{25,31,169},{25,30,5},{21,30,1},{31,24,421},{31,27,421},{21,30,1},{0,28,433},{31,27,421},{0,28,433},{22,0,433},{22,0,433},{22,0,433},{22,0,433},{20,29,2},{20,29,2},{20,29,2},{20,26,5},{15,29,8},{15,29,8},{24,31,2045},{24,31,1233},{23,31,629},{23,31,442},{24,31,2360},{22,31,914},{21,31,14},
+{20,29,549},{19,31,2241},{16,29,409},{26,31,849},{25,31,395},{25,31,34},{24,31,45},{30,24,1459},{23,31,778},{21,31,13},{17,29,400},{29,27,1459},{17,29,400},{23,31,629},{23,31,629},{23,31,629},{23,30,437},{22,31,491},{21,31,14},{21,31,14},{21,27,30},{16,31,446},{17,28,45},{25,31,34},{25,31,34},{25,31,34},{24,30,10},{31,18,338},{21,31,13},{21,31,13},{19,28,17},{26,26,338},
+{19,28,17},{30,28,392},{27,31,218},{26,31,4},{22,31,0},{30,28,392},{28,30,392},{22,31,0},{0,29,400},{28,30,392},{0,29,400},{23,0,433},{23,0,433},{23,0,433},{23,0,433},{21,30,2},{21,30,2},{21,30,2},{21,27,5},{16,29,9},{16,29,9},{25,31,1767},{25,31,1167},{24,31,701},{24,31,449},{24,31,1976},{23,31,747},{22,31,66},{22,29,337},{20,31,1820},{17,30,217},{27,31,611},
+{26,31,317},{26,31,61},{25,31,10},{31,24,1064},{25,31,587},{23,31,41},{18,30,208},{24,31,1064},{18,30,208},{24,31,701},{24,31,701},{24,31,701},{24,31,449},{23,31,581},{22,31,66},{22,31,66},{22,28,26},{18,31,530},{18,29,45},{26,31,61},{26,31,61},{26,31,61},{25,31,10},{30,22,338},{23,31,41},{23,31,41},{21,28,16},{27,27,338},{21,28,16},{29,31,200},{28,31,106},{27,31,1},
+{25,31,1},{29,31,200},{31,29,200},{25,31,1},{0,30,208},{31,29,200},{0,30,208},{24,0,445},{24,0,445},{24,0,445},{24,0,445},{22,31,2},{22,31,2},{22,31,2},{22,27,10},{16,31,5},{16,31,5},{26,31,1542},{26,31,1122},{25,31,833},{25,31,497},{26,31,1647},{24,31,687},{24,31,203},{23,30,122},{22,31,1515},{19,30,110},{28,31,410},{28,31,266},{27,31,116},{27,31,20},{31,26,722},
+{26,31,402},{25,31,100},{21,30,74},{29,29,722},{21,30,74},{25,31,833},{25,31,833},{25,31,833},{25,31,497},{24,31,707},{24,31,203},{24,31,203},{23,29,29},{20,31,619},{19,30,46},{27,31,116},{27,31,116},{27,31,116},{27,31,20},{30,25,338},{25,31,100},{25,31,100},{21,30,10},{30,27,338},{21,30,10},{31,29,61},{29,31,37},{29,31,1},{27,31,4},{31,29,61},{31,30,61},{27,31,4},
+{0,30,73},{31,30,61},{0,30,73},{25,0,433},{25,0,433},{25,0,433},{25,0,433},{23,31,25},{23,31,25},{23,31,25},{23,29,4},{18,31,17},{18,31,17},{27,31,1406},{27,31,1134},{26,31,962},{26,31,602},{27,31,1454},{25,31,702},{25,31,341},{24,31,59},{24,31,1378},{20,31,35},{29,31,318},{28,31,250},{28,31,169},{28,31,61},{30,29,509},{28,31,313},{27,31,164},{22,31,10},{29,30,509},
+{22,31,10},{26,31,962},{26,31,962},{26,31,962},{26,31,602},{26,31,827},{25,31,341},{25,31,341},{24,30,30},{22,31,747},{20,31,35},{28,31,169},{28,31,169},{28,31,169},{28,31,61},{31,26,338},{27,31,164},{27,31,164},{22,31,10},{29,29,338},{22,31,10},{31,30,9},{31,31,9},{30,31,4},{30,31,0},{31,30,9},{30,31,9},{30,31,0},{0,31,9},{30,31,9},{0,31,9},{26,0,433},
+{26,0,433},{26,0,433},{26,0,433},{24,31,50},{24,31,50},{24,31,50},{24,30,5},{20,31,26},{20,31,26},{28,31,1135},{28,31,991},{27,31,874},{27,31,602},{28,31,1162},{26,31,618},{26,31,362},{25,31,5},{25,31,1087},{22,31,58},{30,31,219},{29,31,161},{29,31,125},{29,31,61},{31,29,297},{29,31,193},{28,31,117},{24,31,1},{30,30,297},{24,31,1},{27,31,874},{27,31,874},{27,31,874},
+{27,31,602},{27,31,730},{26,31,362},{26,31,362},{25,31,5},{24,31,681},{22,31,58},{29,31,125},{29,31,125},{29,31,125},{29,31,61},{30,29,221},{28,31,117},{28,31,117},{24,31,1},{31,29,221},{24,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{27,0,433},{27,0,433},{27,0,433},{27,0,433},{25,31,101},
+{25,31,101},{25,31,101},{25,31,5},{22,31,58},{22,31,58},{29,31,885},{28,31,751},{28,31,670},{28,31,526},{28,31,778},{27,31,483},{27,31,314},{26,31,10},{26,31,777},{24,31,117},{30,31,75},{30,31,59},{30,31,50},{30,31,34},{30,31,114},{29,31,81},{29,31,45},{27,31,0},{31,30,114},{27,31,0},{28,31,670},{28,31,670},{28,31,670},{28,31,526},{28,31,553},{27,31,314},{27,31,314},
+{26,31,10},{25,31,518},{24,31,117},{30,31,50},{30,31,50},{30,31,50},{30,31,34},{31,29,85},{29,31,45},{29,31,45},{27,31,0},{29,31,85},{27,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{28,0,445},{28,0,445},{28,0,445},{28,0,445},{27,31,145},{27,31,145},{27,31,145},{26,31,10},{24,31,117},
+{24,31,117},{0,13,884},{0,10,225},{0,7,18},{0,6,265},{0,9,1899},{0,7,1355},{0,6,589},{0,4,1354},{0,5,2124},{0,4,1498},{0,13,884},{0,10,225},{0,7,18},{0,6,265},{4,2,1896},{0,7,1355},{0,6,589},{0,4,1354},{7,1,1896},{0,4,1354},{0,6,0},{0,6,0},{0,6,0},{0,4,4},{0,3,162},{0,3,90},{0,3,90},{0,2,104},{0,2,200},{0,1,134},{0,6,0},
+{0,6,0},{0,6,0},{0,4,4},{0,3,162},{0,3,90},{0,3,90},{0,2,104},{3,0,162},{0,2,104},{6,3,882},{0,10,225},{0,7,18},{0,6,265},{6,3,882},{8,3,882},{0,6,265},{0,5,890},{8,3,882},{0,5,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,15,884},{0,12,170},{0,8,8},
+{0,7,202},{0,10,2360},{0,8,1530},{0,7,643},{0,5,1579},{0,6,2684},{0,5,1804},{0,15,884},{0,12,170},{0,8,8},{0,7,202},{5,2,2355},{0,8,1530},{0,7,643},{0,5,1579},{7,2,2355},{0,5,1579},{0,9,1},{0,9,1},{0,9,1},{0,5,1},{0,4,340},{0,4,180},{0,4,180},{0,2,200},{0,2,392},{0,2,236},{0,9,1},{0,9,1},{0,9,1},{0,5,1},{2,1,338},
+{0,4,180},{0,4,180},{0,2,200},{1,2,338},{0,2,200},{8,2,882},{0,12,170},{0,8,8},{0,7,202},{8,2,882},{12,2,882},{0,7,202},{0,6,890},{12,2,882},{0,6,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,18,882},{0,14,106},{0,10,52},{0,9,148},{0,12,2899},{0,9,1773},{0,8,725},
+{0,6,1854},{0,7,3348},{0,5,2124},{0,18,882},{0,14,106},{0,10,52},{0,9,148},{2,9,2899},{0,9,1773},{0,8,725},{0,6,1854},{12,0,2899},{0,6,1854},{0,11,1},{0,11,1},{0,11,1},{0,7,1},{0,6,580},{0,5,306},{0,5,306},{0,3,325},{0,3,667},{0,3,406},{0,11,1},{0,11,1},{0,11,1},{0,7,1},{1,4,578},{0,5,306},{0,5,306},{0,3,325},{4,1,578},
+{0,3,325},{9,3,882},{0,14,106},{1,9,8},{0,9,148},{9,3,882},{18,0,882},{0,9,148},{0,7,890},{18,0,882},{0,7,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,21,920},{0,16,89},{1,11,120},{0,10,121},{0,14,3051},{0,11,1709},{0,9,557},{0,7,1795},{0,8,3651},{0,6,2174},{1,19,886},
+{0,16,89},{1,11,56},{0,10,121},{8,1,3048},{0,11,1709},{0,9,557},{0,7,1795},{6,5,3048},{0,7,1795},{0,14,37},{0,14,37},{0,14,37},{0,8,37},{0,8,648},{0,7,274},{0,7,274},{0,4,277},{0,4,824},{0,4,421},{1,12,4},{1,12,4},{1,12,4},{1,8,8},{3,3,648},{0,7,274},{0,7,274},{0,4,277},{8,0,648},{0,4,277},{10,4,882},{0,16,53},{2,10,8},
+{0,10,85},{10,4,882},{19,1,882},{0,10,85},{0,8,900},{19,1,882},{0,8,900},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,10},{0,1,10},{1,22,995},{1,17,158},{1,12,230},{1,11,186},{0,17,3051},{0,13,1579},{0,10,346},{0,8,1630},{0,9,3924},{0,7,2173},{2,20,885},{2,16,90},{2,12,53},{1,11,122},{8,4,3048},
+{0,13,1579},{0,10,346},{0,8,1630},{14,2,3048},{0,8,1630},{1,15,113},{1,15,113},{1,15,113},{1,9,117},{0,11,648},{0,9,169},{0,9,169},{0,5,200},{0,6,990},{0,5,425},{2,13,2},{2,13,2},{2,13,2},{2,9,2},{6,1,648},{0,9,169},{0,9,169},{0,5,200},{11,0,648},{0,5,200},{13,2,882},{0,18,17},{3,11,18},{0,11,34},{13,2,882},{22,1,882},{0,11,34},
+{0,9,890},{22,1,882},{0,9,890},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,5,0},{0,5,0},{0,5,0},{0,3,0},{0,2,61},{0,2,61},{1,24,1173},{1,19,306},{2,13,422},{1,12,318},{0,20,3048},{0,15,1443},{0,12,204},{0,9,1483},{0,11,4212},{0,8,2174},{3,21,885},{3,17,90},{3,13,53},{2,12,117},{12,0,3048},{0,15,1443},{0,12,204},{0,9,1483},{20,0,3048},
+{0,9,1483},{1,18,290},{1,18,290},{1,18,290},{1,11,289},{0,13,650},{0,11,109},{0,11,109},{0,7,148},{0,7,1161},{0,6,473},{3,14,2},{3,14,2},{3,14,2},{3,10,2},{8,0,648},{0,11,109},{0,11,109},{0,7,148},{5,5,648},{0,7,148},{14,3,882},{0,20,8},{4,12,8},{0,12,8},{14,3,882},{26,0,882},{0,12,8},{0,10,890},{26,0,882},{0,10,890},{1,0,289},
+{1,0,289},{1,0,289},{1,0,289},{0,8,1},{0,8,1},{0,8,1},{0,5,4},{0,3,145},{0,3,145},{2,25,1365},{2,20,497},{2,14,713},{2,13,510},{0,23,3051},{0,16,1278},{0,13,86},{0,10,1354},{0,12,4609},{0,9,2228},{4,22,886},{3,19,94},{4,14,56},{3,13,117},{13,1,3048},{0,16,1278},{0,13,86},{0,10,1354},{21,1,3048},{0,10,1354},{2,19,482},{2,19,482},{2,19,482},
+{2,12,481},{0,16,648},{0,12,72},{0,12,72},{0,8,101},{0,8,1352},{0,7,557},{4,15,5},{4,15,5},{4,15,5},{4,11,5},{9,1,648},{0,12,72},{0,12,72},{0,8,101},{16,0,648},{0,8,101},{16,2,882},{1,21,8},{5,13,8},{0,13,5},{16,2,882},{27,1,882},{0,13,5},{0,11,890},{27,1,882},{0,11,890},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{0,10,1},
+{0,10,1},{0,10,1},{0,6,1},{0,5,261},{0,5,261},{2,28,1667},{2,22,793},{3,15,1033},{2,14,793},{0,25,3048},{0,18,1170},{0,14,36},{0,11,1243},{0,14,5005},{0,10,2318},{5,23,886},{4,20,89},{5,15,56},{4,14,121},{14,2,3048},{0,18,1170},{0,14,36},{0,11,1243},{25,0,3048},{0,11,1243},{2,21,786},{2,21,786},{2,21,786},{2,14,789},{0,19,650},{0,14,32},{0,14,32},
+{0,9,50},{0,9,1619},{0,8,661},{5,16,4},{5,16,4},{5,16,4},{5,12,8},{10,2,648},{0,14,32},{0,14,32},{0,9,50},{17,1,648},{0,9,50},{17,3,882},{2,22,8},{6,14,8},{1,14,5},{17,3,882},{28,2,882},{1,14,5},{0,12,900},{28,2,882},{0,12,900},{2,0,785},{2,0,785},{2,0,785},{2,0,785},{0,13,1},{0,13,1},{0,13,1},{0,8,4},{0,6,405},
+{0,6,405},{3,29,1784},{3,23,902},{4,16,1186},{3,15,910},{1,26,3055},{0,20,1095},{1,15,47},{0,12,1159},{0,16,4945},{0,12,2084},{6,24,885},{6,20,90},{6,16,53},{5,15,122},{12,8,3048},{0,20,1059},{0,16,41},{0,12,1123},{28,0,3048},{0,12,1123},{3,23,901},{3,23,901},{3,23,901},{3,15,901},{1,20,652},{1,15,38},{1,15,38},{1,10,44},{0,11,1577},{0,9,545},{6,17,2},
+{6,17,2},{6,17,2},{6,13,2},{13,0,648},{0,16,5},{0,16,5},{0,10,13},{20,1,648},{0,10,13},{17,6,882},{3,23,2},{7,15,18},{3,15,10},{17,6,882},{31,2,882},{3,15,10},{0,13,890},{31,2,882},{0,13,890},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{1,14,4},{1,14,4},{1,14,4},{1,9,5},{0,8,373},{0,8,373},{4,30,1772},{4,24,898},{5,17,1186},
+{4,16,898},{2,27,3055},{1,21,1095},{2,16,33},{1,13,1159},{0,17,4639},{0,13,1730},{7,25,885},{7,21,90},{7,17,53},{6,16,117},{16,4,3048},{0,21,996},{2,16,29},{0,13,1054},{29,1,3048},{0,13,1054},{4,23,891},{4,23,891},{4,23,891},{4,16,894},{2,21,652},{2,16,29},{2,16,29},{2,11,44},{0,13,1452},{0,11,365},{7,18,2},{7,18,2},{7,18,2},{7,14,2},{14,1,648},
+{0,18,1},{0,18,1},{0,11,4},{24,0,648},{0,11,4},{22,0,882},{4,24,8},{8,16,8},{3,16,5},{22,0,882},{30,4,882},{3,16,5},{0,14,890},{30,4,882},{0,14,890},{4,0,890},{4,0,890},{4,0,890},{4,0,890},{2,15,4},{2,15,4},{2,15,4},{2,10,5},{0,9,269},{0,9,269},{5,31,1772},{5,25,898},{6,18,1186},{5,17,898},{3,28,3055},{2,22,1095},{3,17,33},
+{2,14,1159},{0,19,4419},{0,14,1444},{8,26,886},{7,23,94},{8,18,56},{7,17,117},{17,5,3048},{0,23,936},{3,17,29},{0,14,1003},{30,2,3048},{0,14,1003},{5,24,891},{5,24,891},{5,24,891},{5,17,894},{3,22,652},{3,17,29},{3,17,29},{3,12,41},{0,15,1296},{0,12,235},{8,19,5},{8,19,5},{8,19,5},{8,15,5},{16,0,648},{1,19,1},{1,19,1},{1,12,1},{25,1,648},
+{1,12,1},{23,1,882},{5,25,8},{9,17,8},{4,17,5},{23,1,882},{31,5,882},{4,17,5},{0,15,890},{31,5,882},{0,15,890},{5,0,890},{5,0,890},{5,0,890},{5,0,890},{3,16,4},{3,16,4},{3,16,4},{3,11,5},{0,11,185},{0,11,185},{6,31,1790},{6,26,898},{7,19,1186},{6,18,898},{4,29,3057},{3,23,1095},{4,18,45},{3,15,1159},{0,20,4156},{0,15,1226},{9,27,886},
+{8,24,89},{9,19,56},{8,18,121},{18,6,3048},{0,25,909},{4,18,36},{0,15,970},{31,3,3048},{0,15,970},{6,25,891},{6,25,891},{6,25,891},{6,18,894},{4,23,659},{4,18,41},{4,18,41},{3,13,46},{0,16,1137},{0,13,137},{9,20,4},{9,20,4},{9,20,4},{9,16,8},{17,1,648},{2,20,2},{2,20,2},{2,13,1},{26,2,648},{2,13,1},{24,2,882},{6,26,8},{10,18,8},
+{5,18,5},{24,2,882},{27,9,882},{5,18,5},{0,16,900},{27,9,882},{0,16,900},{6,0,890},{6,0,890},{6,0,890},{6,0,890},{4,17,10},{4,17,10},{4,17,10},{4,12,13},{0,13,136},{0,13,136},{8,31,1844},{7,27,902},{8,20,1186},{7,19,910},{5,30,3055},{4,24,1095},{5,19,47},{4,16,1159},{0,22,3940},{0,16,1055},{10,28,885},{10,24,90},{10,20,53},{9,19,122},{22,2,3048},
+{0,27,886},{4,20,41},{0,17,926},{22,10,3048},{0,17,926},{7,27,901},{7,27,901},{7,27,901},{7,19,901},{5,24,652},{5,19,38},{5,19,38},{5,14,44},{0,18,1002},{0,15,110},{10,21,2},{10,21,2},{10,21,2},{10,17,2},{17,4,648},{3,21,4},{3,21,4},{3,14,5},{29,2,648},{3,14,5},{27,0,882},{7,27,2},{11,19,18},{7,19,10},{27,0,882},{30,9,882},{7,19,10},
+{0,17,890},{30,9,882},{0,17,890},{7,0,900},{7,0,900},{7,0,900},{7,0,900},{5,18,4},{5,18,4},{5,18,4},{5,13,5},{0,15,74},{0,15,74},{9,31,1886},{8,28,898},{9,21,1186},{8,20,898},{6,31,3055},{5,25,1095},{6,20,33},{5,17,1159},{0,23,3820},{0,18,963},{11,29,885},{11,25,90},{11,21,53},{10,20,117},{23,3,3048},{1,28,888},{6,20,29},{0,18,899},{28,8,3048},
+{0,18,899},{8,27,891},{8,27,891},{8,27,891},{8,20,894},{6,25,652},{6,20,29},{6,20,29},{6,15,44},{0,20,876},{0,16,102},{11,22,2},{11,22,2},{11,22,2},{11,18,2},{18,5,648},{4,22,1},{4,22,1},{4,15,4},{30,3,648},{4,15,4},{26,4,882},{8,28,8},{12,20,8},{7,20,5},{26,4,882},{31,10,882},{7,20,5},{0,18,890},{31,10,882},{0,18,890},{8,0,890},
+{8,0,890},{8,0,890},{8,0,890},{6,19,4},{6,19,4},{6,19,4},{6,14,5},{0,17,29},{0,17,29},{10,31,1964},{9,29,898},{10,22,1186},{9,21,898},{7,31,3100},{6,26,1095},{7,21,33},{6,18,1159},{0,25,3679},{0,19,899},{12,30,886},{11,27,94},{12,22,56},{11,21,117},{21,9,3048},{2,29,888},{7,21,29},{0,19,890},{29,9,3048},{0,19,890},{9,28,891},{9,28,891},{9,28,891},
+{9,21,894},{7,26,652},{7,21,29},{7,21,29},{7,16,41},{0,22,800},{2,16,98},{12,23,5},{12,23,5},{12,23,5},{12,19,5},{20,4,648},{5,23,1},{5,23,1},{5,16,1},{29,5,648},{5,16,1},{30,0,882},{9,29,8},{13,21,8},{8,21,5},{30,0,882},{30,12,882},{8,21,5},{0,19,890},{30,12,882},{0,19,890},{9,0,890},{9,0,890},{9,0,890},{9,0,890},{7,20,4},
+{7,20,4},{7,20,4},{7,15,5},{0,19,9},{0,19,9},{11,31,2078},{10,30,898},{11,23,1186},{10,22,898},{9,31,3181},{7,27,1095},{8,22,45},{7,19,1159},{0,27,3523},{0,20,908},{13,31,886},{12,28,89},{13,23,56},{12,22,121},{22,10,3048},{3,30,888},{8,22,36},{1,20,901},{30,10,3048},{1,20,901},{10,29,891},{10,29,891},{10,29,891},{10,22,894},{8,27,659},{8,22,41},{8,22,41},
+{7,17,46},{0,23,747},{3,17,98},{13,24,4},{13,24,4},{13,24,4},{13,20,8},{24,0,648},{6,24,2},{6,24,2},{6,17,1},{30,6,648},{6,17,1},{31,1,882},{10,30,8},{14,22,8},{9,22,5},{31,1,882},{31,13,882},{9,22,5},{0,20,900},{31,13,882},{0,20,900},{10,0,890},{10,0,890},{10,0,890},{10,0,890},{8,21,10},{8,21,10},{8,21,10},{8,16,13},{0,20,8},
+{0,20,8},{12,31,2228},{11,31,902},{12,24,1186},{11,23,910},{10,31,3256},{8,28,1095},{9,23,47},{8,20,1159},{0,29,3364},{2,21,894},{14,31,915},{14,28,90},{14,24,53},{13,23,122},{29,1,3048},{4,31,886},{8,24,41},{2,21,890},{26,14,3048},{2,21,890},{11,31,901},{11,31,901},{11,31,901},{11,23,901},{9,28,652},{9,23,38},{9,23,38},{9,18,44},{0,25,705},{3,19,101},{14,25,2},
+{14,25,2},{14,25,2},{14,21,2},{24,3,648},{7,25,4},{7,25,4},{7,18,5},{28,9,648},{7,18,5},{31,4,882},{11,31,2},{15,23,18},{11,23,10},{31,4,882},{24,19,882},{11,23,10},{0,21,890},{24,19,882},{0,21,890},{11,0,900},{11,0,900},{11,0,900},{11,0,900},{9,22,4},{9,22,4},{9,22,4},{9,17,5},{2,21,4},{2,21,4},{13,31,2414},{12,31,907},{13,25,1186},
+{12,24,898},{11,31,3391},{9,29,1095},{10,24,33},{9,21,1159},{0,31,3276},{3,22,894},{15,31,981},{15,29,90},{15,25,53},{14,24,117},{30,2,3048},{6,31,906},{10,24,29},{3,22,890},{27,15,3048},{3,22,890},{12,31,891},{12,31,891},{12,31,891},{12,24,894},{10,29,652},{10,24,29},{10,24,29},{10,19,44},{0,27,665},{4,20,102},{15,26,2},{15,26,2},{15,26,2},{15,22,2},{22,9,648},
+{8,26,1},{8,26,1},{8,19,4},{29,10,648},{8,19,4},{30,8,882},{12,31,17},{16,24,8},{11,24,5},{30,8,882},{28,18,882},{11,24,5},{0,22,890},{28,18,882},{0,22,890},{12,0,890},{12,0,890},{12,0,890},{12,0,890},{10,23,4},{10,23,4},{10,23,4},{10,18,5},{3,22,4},{3,22,4},{15,31,2606},{13,31,987},{14,26,1186},{13,25,898},{13,31,3517},{10,30,1095},{11,25,33},
+{10,22,1159},{1,31,3300},{4,23,899},{17,31,1014},{15,31,94},{16,26,56},{15,25,117},{31,3,3048},{8,31,936},{11,25,29},{4,23,890},{23,19,3048},{4,23,890},{13,31,906},{13,31,906},{13,31,906},{13,25,894},{11,30,652},{11,25,29},{11,25,29},{11,20,41},{0,29,651},{6,20,98},{16,27,5},{16,27,5},{16,27,5},{16,23,5},{24,8,648},{9,27,1},{9,27,1},{9,20,1},{30,11,648},
+{9,20,1},{31,9,882},{14,31,37},{17,25,8},{12,25,5},{31,9,882},{29,19,882},{12,25,5},{0,23,890},{29,19,882},{0,23,890},{13,0,890},{13,0,890},{13,0,890},{13,0,890},{11,24,4},{11,24,4},{11,24,4},{11,19,5},{3,24,5},{3,24,5},{16,31,2792},{15,31,1079},{15,27,1186},{14,26,898},{14,31,3652},{11,31,1095},{12,26,45},{11,23,1159},{3,31,3436},{4,24,908},{18,31,1080},
+{17,31,110},{17,27,56},{16,26,121},{26,14,3048},{10,31,996},{12,26,36},{5,24,901},{22,21,3048},{5,24,901},{14,31,939},{14,31,939},{14,31,939},{14,26,894},{12,31,659},{12,26,41},{12,26,41},{11,21,46},{1,30,651},{7,21,98},{17,28,4},{17,28,4},{17,28,4},{17,24,8},{28,4,648},{10,28,2},{10,28,2},{10,21,1},{29,13,648},{10,21,1},{29,15,882},{16,31,80},{18,26,8},
+{13,26,5},{29,15,882},{30,20,882},{13,26,5},{0,24,900},{30,20,882},{0,24,900},{14,0,890},{14,0,890},{14,0,890},{14,0,890},{12,25,10},{12,25,10},{12,25,10},{12,20,13},{4,24,8},{4,24,8},{17,31,3038},{16,31,1268},{16,28,1186},{15,27,910},{15,31,3879},{12,31,1146},{13,27,47},{12,24,1159},{5,31,3667},{6,25,894},{19,31,1205},{18,31,147},{18,28,53},{17,27,122},{30,10,3048},
+{12,31,1110},{12,28,41},{6,25,890},{30,18,3048},{6,25,890},{16,31,979},{16,31,979},{16,31,979},{15,27,901},{13,31,670},{13,27,38},{13,27,38},{13,22,44},{2,31,648},{7,23,101},{18,29,2},{18,29,2},{18,29,2},{18,25,2},{31,2,648},{11,29,4},{11,29,4},{11,22,5},{27,16,648},{11,22,5},{29,18,882},{18,31,146},{19,27,18},{15,27,10},{29,18,882},{28,23,882},{15,27,10},
+{0,25,890},{28,23,882},{0,25,890},{15,0,900},{15,0,900},{15,0,900},{15,0,900},{13,26,4},{13,26,4},{13,26,4},{13,21,5},{6,25,4},{6,25,4},{18,31,3308},{17,31,1502},{17,29,1186},{16,28,898},{17,31,4077},{14,31,1230},{14,28,33},{13,25,1159},{8,31,3820},{7,26,894},{21,31,1368},{19,31,261},{19,29,53},{18,28,117},{31,11,3048},{14,31,1226},{14,28,29},{7,26,890},{31,19,3048},
+{7,26,890},{17,31,1018},{17,31,1018},{17,31,1018},{16,28,894},{14,31,724},{14,28,29},{14,28,29},{14,23,44},{4,31,665},{8,24,102},{19,30,2},{19,30,2},{19,30,2},{19,26,2},{26,13,648},{12,30,1},{12,30,1},{12,23,4},{21,21,648},{12,23,4},{30,19,882},{20,31,193},{20,28,8},{15,28,5},{30,19,882},{27,25,882},{15,28,5},{0,26,890},{27,25,882},{0,26,890},{16,0,890},
+{16,0,890},{16,0,890},{16,0,890},{14,27,4},{14,27,4},{14,27,4},{14,22,5},{7,26,4},{7,26,4},{19,31,3614},{18,31,1804},{18,30,1186},{17,29,898},{18,31,4284},{15,31,1417},{15,29,33},{14,26,1159},{9,31,4036},{8,27,899},{22,31,1494},{20,31,405},{20,30,56},{19,29,117},{29,17,3048},{16,31,1395},{15,29,29},{8,27,890},{27,23,3048},{8,27,890},{18,31,1075},{18,31,1075},{18,31,1075},
+{17,29,894},{16,31,787},{15,29,29},{15,29,29},{15,24,41},{6,31,705},{10,24,98},{20,31,5},{20,31,5},{20,31,5},{20,27,5},{28,12,648},{13,31,1},{13,31,1},{13,24,1},{22,22,648},{13,24,1},{29,23,882},{22,31,277},{21,29,8},{16,29,5},{29,23,882},{28,26,882},{16,29,5},{0,27,890},{28,26,882},{0,27,890},{17,0,890},{17,0,890},{17,0,890},{17,0,890},{15,28,4},
+{15,28,4},{15,28,4},{15,23,5},{7,28,5},{7,28,5},{20,31,4014},{19,31,2174},{19,31,1186},{18,30,898},{19,31,4545},{17,31,1725},{16,30,45},{15,27,1159},{11,31,4300},{8,28,908},{23,31,1656},{22,31,585},{21,31,56},{20,30,121},{30,18,3048},{18,31,1563},{16,30,36},{9,28,901},{26,25,3048},{9,28,901},{19,31,1150},{19,31,1150},{19,31,1150},{18,30,894},{17,31,841},{16,30,41},{16,30,41},
+{15,25,46},{8,31,747},{11,25,98},{21,31,20},{21,31,20},{21,31,20},{21,28,8},{29,13,648},{15,31,5},{15,31,5},{14,25,1},{28,20,648},{14,25,1},{30,24,882},{23,31,397},{22,30,8},{17,30,5},{30,24,882},{29,27,882},{17,30,5},{0,28,900},{29,27,882},{0,28,900},{18,0,890},{18,0,890},{18,0,890},{18,0,890},{16,29,10},{16,29,10},{16,29,10},{16,24,13},{8,28,8},
+{8,28,8},{22,31,4123},{21,31,2404},{20,31,1278},{19,31,901},{20,31,4626},{18,31,1849},{17,31,38},{16,28,1006},{14,31,4330},{10,29,789},{24,31,1629},{23,31,715},{22,31,65},{22,30,101},{31,19,2814},{20,31,1505},{17,31,34},{10,29,785},{27,26,2814},{10,29,785},{20,31,1278},{20,31,1278},{20,31,1278},{19,31,901},{18,31,948},{17,31,38},{17,31,38},{17,26,44},{10,31,840},{11,27,101},{22,31,65},
+{22,31,65},{22,31,65},{22,29,2},{29,16,648},{17,31,34},{17,31,34},{15,26,5},{31,20,648},{15,26,5},{31,25,761},{25,31,425},{23,31,9},{19,31,1},{31,25,761},{28,29,761},{19,31,1},{0,29,785},{28,29,761},{0,29,785},{19,0,900},{19,0,900},{19,0,900},{19,0,900},{17,30,4},{17,30,4},{17,30,4},{17,25,5},{10,29,4},{10,29,4},{23,31,3735},{22,31,2314},{21,31,1395},
+{20,31,899},{22,31,4090},{19,31,1618},{18,31,104},{17,29,686},{15,31,3826},{11,29,507},{25,31,1285},{24,31,609},{23,31,122},{23,31,37},{30,22,2249},{21,31,1186},{19,31,74},{13,29,482},{27,27,2249},{13,29,482},{21,31,1395},{21,31,1395},{21,31,1395},{20,31,899},{19,31,1086},{18,31,104},{18,31,104},{18,27,44},{12,31,969},{12,28,102},{23,31,122},{23,31,122},{23,31,122},{23,30,2},{30,17,648},
+{19,31,74},{19,31,74},{16,27,4},{25,25,648},{16,27,4},{31,26,481},{27,31,269},{25,31,0},{21,31,0},{31,26,481},{31,28,481},{21,31,0},{0,29,481},{31,28,481},{0,29,481},{20,0,890},{20,0,890},{20,0,890},{20,0,890},{18,31,4},{18,31,4},{18,31,4},{18,26,5},{11,30,4},{11,30,4},{23,31,3399},{23,31,2260},{22,31,1530},{21,31,954},{23,31,3639},{20,31,1402},{19,31,238},
+{18,29,405},{17,31,3443},{12,30,314},{26,31,1009},{25,31,525},{25,31,164},{24,31,5},{30,24,1769},{23,31,918},{21,31,113},{14,30,290},{29,27,1769},{14,30,290},{22,31,1530},{22,31,1530},{22,31,1530},{21,31,954},{21,31,1251},{19,31,238},{19,31,238},{19,28,41},{14,31,1105},{14,28,98},{25,31,164},{25,31,164},{25,31,164},{24,31,5},{31,18,648},{21,31,113},{21,31,113},{17,28,1},{26,26,648},
+{17,28,1},{30,29,265},{28,31,145},{27,31,4},{24,31,1},{30,29,265},{29,30,265},{24,31,1},{0,30,289},{29,30,265},{0,30,289},{21,0,890},{21,0,890},{21,0,890},{21,0,890},{19,31,13},{19,31,13},{19,31,13},{19,27,5},{12,31,9},{12,31,9},{24,31,3069},{24,31,2257},{23,31,1683},{23,31,1054},{24,31,3258},{22,31,1330},{21,31,378},{19,30,213},{20,31,3102},{14,30,166},{27,31,801},
+{26,31,477},{26,31,221},{25,31,20},{31,24,1374},{24,31,758},{23,31,181},{16,30,114},{24,31,1374},{16,30,114},{23,31,1683},{23,31,1683},{23,31,1683},{23,31,1054},{22,31,1401},{21,31,378},{21,31,378},{19,29,46},{16,31,1296},{15,29,98},{26,31,221},{26,31,221},{26,31,221},{25,31,20},{30,22,648},{23,31,181},{23,31,181},{18,29,1},{27,27,648},{18,29,1},{30,30,113},{29,31,61},{28,31,0},
+{26,31,1},{30,30,113},{30,30,113},{26,31,1},{0,30,113},{30,30,113},{0,30,113},{22,0,890},{22,0,890},{22,0,890},{22,0,890},{20,31,45},{20,31,45},{20,31,45},{20,28,13},{13,31,25},{13,31,25},{25,31,2860},{25,31,2260},{24,31,1854},{24,31,1210},{25,31,2932},{23,31,1310},{22,31,609},{21,30,108},{21,31,2731},{15,31,101},{28,31,630},{27,31,475},{27,31,306},{26,31,101},{31,26,1032},
+{26,31,612},{25,31,290},{18,31,37},{29,29,1032},{18,31,37},{24,31,1854},{24,31,1854},{24,31,1854},{24,31,1210},{23,31,1620},{22,31,609},{22,31,609},{21,30,44},{18,31,1515},{15,31,101},{27,31,306},{27,31,306},{27,31,306},{26,31,101},{30,25,648},{25,31,290},{25,31,290},{19,30,5},{30,27,648},{19,30,5},{31,30,18},{30,31,10},{30,31,1},{29,31,0},{31,30,18},{30,31,18},{29,31,0},
+{0,31,36},{30,31,18},{0,31,36},{23,0,900},{23,0,900},{23,0,900},{23,0,900},{21,31,104},{21,31,104},{21,31,104},{21,29,5},{15,31,65},{15,31,65},{26,31,2626},{26,31,2206},{25,31,1915},{25,31,1315},{26,31,2641},{24,31,1333},{23,31,789},{22,31,40},{22,31,2445},{17,31,116},{29,31,524},{28,31,406},{28,31,325},{27,31,170},{30,29,771},{27,31,507},{26,31,320},{20,31,0},{29,30,771},
+{20,31,0},{25,31,1915},{25,31,1915},{25,31,1915},{25,31,1315},{24,31,1661},{23,31,789},{23,31,789},{22,31,40},{20,31,1517},{17,31,116},{28,31,325},{28,31,325},{28,31,325},{27,31,170},{31,26,580},{26,31,320},{26,31,320},{20,31,0},{30,28,580},{20,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{24,0,890},
+{24,0,890},{24,0,890},{24,0,890},{23,31,164},{23,31,164},{23,31,164},{22,30,5},{17,31,116},{17,31,116},{27,31,2156},{27,31,1884},{26,31,1630},{26,31,1210},{26,31,2081},{25,31,1108},{24,31,705},{23,31,5},{23,31,1927},{19,31,180},{29,31,300},{29,31,236},{29,31,200},{28,31,85},{31,28,451},{28,31,283},{27,31,194},{23,31,1},{28,31,451},{23,31,1},{26,31,1630},{26,31,1630},{26,31,1630},
+{26,31,1210},{25,31,1347},{24,31,705},{24,31,705},{23,31,5},{22,31,1229},{19,31,180},{29,31,200},{29,31,200},{29,31,200},{28,31,85},{31,27,338},{27,31,194},{27,31,194},{23,31,1},{30,29,338},{23,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{25,0,890},{25,0,890},{25,0,890},{25,0,890},{24,31,221},
+{24,31,221},{24,31,221},{23,31,5},{19,31,180},{19,31,180},{28,31,1782},{27,31,1564},{27,31,1395},{27,31,1123},{27,31,1620},{26,31,937},{25,31,651},{24,31,25},{24,31,1560},{21,31,233},{30,31,150},{30,31,134},{29,31,104},{29,31,40},{31,29,216},{29,31,136},{28,31,90},{25,31,1},{29,31,216},{25,31,1},{27,31,1395},{27,31,1395},{27,31,1395},{27,31,1123},{26,31,1101},{25,31,651},{25,31,651},
+{24,31,25},{23,31,998},{21,31,233},{29,31,104},{29,31,104},{29,31,104},{29,31,40},{31,28,162},{28,31,90},{28,31,90},{25,31,1},{28,31,162},{25,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{26,0,890},{26,0,890},{26,0,890},{26,0,890},{25,31,290},{25,31,290},{25,31,290},{24,31,25},{21,31,233},
+{21,31,233},{0,17,1568},{0,14,442},{0,10,40},{0,8,485},{0,11,3379},{0,9,2369},{0,8,1061},{0,5,2435},{0,6,3760},{0,5,2660},{0,17,1568},{0,14,442},{0,10,40},{0,8,485},{7,0,3371},{0,9,2369},{0,8,1061},{0,5,2435},{10,1,3371},{0,5,2435},{0,8,0},{0,8,0},{0,8,0},{0,5,1},{0,4,288},{0,4,160},{0,4,160},{0,2,164},{0,2,332},{0,2,200},{0,8,0},
+{0,8,0},{0,8,0},{0,5,1},{0,4,288},{0,4,160},{0,4,160},{0,2,164},{4,0,288},{0,2,164},{9,2,1568},{0,14,442},{0,10,40},{0,8,485},{9,2,1568},{17,0,1568},{0,8,485},{0,6,1586},{17,0,1568},{0,6,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,20,1570},{0,16,325},{0,11,5},
+{0,9,392},{0,13,3968},{0,10,2630},{0,9,1121},{0,6,2710},{0,7,4484},{0,6,3034},{0,20,1570},{0,16,325},{0,11,5},{0,9,392},{2,10,3968},{0,10,2630},{0,9,1121},{0,6,2710},{13,0,3968},{0,6,2710},{0,11,1},{0,11,1},{0,11,1},{0,6,4},{0,5,514},{0,5,274},{0,5,274},{0,3,289},{0,3,595},{0,3,370},{0,11,1},{0,11,1},{0,11,1},{0,6,4},{2,2,512},
+{0,5,274},{0,5,274},{0,3,289},{2,2,512},{0,3,289},{10,3,1568},{0,16,325},{0,11,5},{0,9,392},{10,3,1568},{18,1,1568},{0,9,392},{0,7,1586},{18,1,1568},{0,7,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,22,1570},{0,17,225},{0,12,18},{0,11,292},{0,15,4652},{0,11,2945},{0,10,1217},
+{0,7,3035},{0,8,5283},{0,7,3476},{0,22,1570},{0,17,225},{0,12,18},{0,11,292},{4,8,4651},{0,11,2945},{0,10,1217},{0,7,3035},{13,1,4651},{0,7,3035},{0,13,0},{0,13,0},{0,13,0},{0,8,1},{0,7,802},{0,6,424},{0,6,424},{0,4,449},{0,3,931},{0,3,562},{0,13,0},{0,13,0},{0,13,0},{0,8,1},{4,0,800},{0,6,424},{0,6,424},{0,4,449},{5,1,800},
+{0,4,449},{11,4,1568},{0,17,225},{1,12,13},{0,11,292},{11,4,1568},{19,2,1568},{0,11,292},{0,8,1576},{19,2,1568},{0,8,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,1570},{0,19,149},{0,13,73},{0,12,194},{0,17,5424},{0,13,3368},{0,11,1349},{0,8,3449},{0,9,6213},{0,7,3956},{0,25,1570},
+{0,19,149},{0,13,73},{0,12,194},{10,0,5419},{0,13,3368},{0,11,1349},{0,8,3449},{15,1,5419},{0,8,3449},{0,16,1},{0,16,1},{0,16,1},{0,9,4},{0,8,1152},{0,7,610},{0,7,610},{0,4,625},{0,4,1328},{0,4,769},{0,16,1},{0,16,1},{0,16,1},{0,9,4},{3,3,1152},{0,7,610},{0,7,610},{0,4,625},{8,0,1152},{0,4,625},{15,0,1568},{0,19,149},{2,13,13},
+{0,12,194},{15,0,1568},{20,3,1568},{0,12,194},{0,9,1576},{20,3,1568},{0,9,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,26,1633},{0,21,155},{1,14,150},{0,13,198},{0,20,5424},{0,15,3099},{0,12,996},{0,9,3179},{0,10,6544},{0,8,3890},{1,26,1569},{1,20,131},{2,14,69},{1,13,181},{10,3,5419},
+{0,15,3099},{0,12,996},{0,9,3179},{18,1,5419},{0,9,3179},{1,17,65},{1,17,65},{1,17,65},{1,11,69},{0,11,1152},{0,9,445},{0,9,445},{0,6,505},{0,6,1494},{0,5,737},{1,17,1},{1,17,1},{1,17,1},{1,11,5},{6,1,1152},{0,9,445},{0,9,445},{0,6,505},{11,0,1152},{0,6,505},{16,1,1568},{0,21,74},{3,14,5},{0,13,117},{16,1,1568},{26,1,1568},{0,13,117},
+{0,10,1586},{26,1,1568},{0,10,1586},{1,0,65},{1,0,65},{1,0,65},{1,0,65},{0,3,0},{0,3,0},{0,3,0},{0,2,1},{0,1,25},{0,1,25},{1,29,1715},{1,22,219},{2,15,342},{1,14,262},{0,22,5420},{0,16,2834},{0,13,726},{0,10,2966},{0,11,6916},{0,9,3860},{2,27,1569},{2,21,131},{3,15,69},{2,14,181},{11,4,5419},{0,16,2834},{0,13,726},{0,10,2966},{19,2,5419},
+{0,10,2966},{1,20,146},{1,20,146},{1,20,146},{1,12,146},{0,13,1154},{0,11,337},{0,11,337},{0,7,388},{0,7,1665},{0,6,749},{2,18,1},{2,18,1},{2,18,1},{2,12,5},{8,0,1152},{0,11,337},{0,11,337},{0,7,388},{5,5,1152},{0,7,388},{17,2,1568},{0,23,34},{4,15,5},{0,14,72},{17,2,1568},{27,2,1568},{0,14,72},{0,11,1586},{27,2,1568},{0,11,1586},{1,0,145},
+{1,0,145},{1,0,145},{1,0,145},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{0,2,85},{0,2,85},{2,30,1907},{1,24,398},{2,16,542},{1,15,425},{0,25,5424},{0,18,2630},{0,15,486},{0,11,2771},{0,13,7299},{0,11,3860},{3,28,1569},{3,22,131},{4,16,82},{3,15,181},{15,0,5419},{0,18,2630},{0,15,486},{0,11,2771},{20,3,5419},{0,11,2771},{2,21,338},{2,21,338},{2,21,338},
+{2,13,338},{0,16,1152},{0,13,274},{0,13,274},{0,8,305},{0,8,1856},{0,7,797},{3,19,1},{3,19,1},{3,19,1},{3,13,5},{9,1,1152},{0,13,274},{0,13,274},{0,8,305},{16,0,1152},{0,8,305},{18,3,1568},{0,25,17},{5,16,13},{0,15,45},{18,3,1568},{28,3,1568},{0,15,45},{0,12,1576},{28,3,1568},{0,12,1576},{2,0,337},{2,0,337},{2,0,337},{2,0,337},{0,8,1},
+{0,8,1},{0,8,1},{0,5,0},{0,4,169},{0,4,169},{2,31,2145},{2,25,590},{3,17,862},{2,16,619},{0,27,5420},{0,20,2424},{0,16,282},{0,12,2552},{0,15,7711},{0,11,3908},{4,29,1570},{4,23,149},{4,17,73},{4,16,194},{14,4,5419},{0,20,2424},{0,16,282},{0,12,2552},{24,2,5419},{0,12,2552},{2,23,546},{2,23,546},{2,23,546},{2,15,546},{0,19,1154},{0,15,194},{0,15,194},
+{0,9,218},{0,9,2123},{0,8,865},{4,20,1},{4,20,1},{4,20,1},{4,13,4},{10,2,1152},{0,15,194},{0,15,194},{0,9,218},{17,1,1152},{0,9,218},{20,2,1568},{0,27,5},{6,17,13},{0,16,26},{20,2,1568},{24,7,1568},{0,16,26},{0,13,1576},{24,7,1568},{0,13,1576},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,289},
+{0,5,289},{3,31,2596},{3,26,941},{3,19,1289},{3,17,972},{0,30,5420},{0,22,2243},{0,17,145},{0,13,2386},{0,16,8161},{0,13,3986},{5,30,1569},{5,24,131},{6,18,69},{5,17,181},{17,2,5419},{0,22,2243},{0,17,145},{0,13,2386},{27,2,5419},{0,13,2386},{3,24,901},{3,24,901},{3,24,901},{3,16,901},{0,22,1154},{0,17,109},{0,17,109},{0,10,145},{0,11,2441},{0,9,1001},{5,21,1},
+{5,21,1},{5,21,1},{5,15,5},{13,0,1152},{0,17,109},{0,17,109},{0,10,145},{20,1,1152},{0,10,145},{23,0,1568},{1,28,2},{7,18,5},{0,18,8},{23,0,1568},{30,5,1568},{0,18,8},{0,14,1586},{30,5,1568},{0,14,1586},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{0,14,1},{0,14,1},{0,14,1},{0,8,1},{0,6,468},{0,6,468},{4,31,3146},{3,28,1262},{4,19,1743},
+{3,18,1297},{1,31,5484},{0,23,2096},{0,19,69},{0,14,2251},{0,18,8669},{0,14,4100},{6,31,1569},{6,25,131},{7,19,69},{6,18,181},{18,3,5419},{0,23,2096},{0,19,69},{0,14,2251},{28,3,5419},{0,14,2251},{3,27,1252},{3,27,1252},{3,27,1252},{3,17,1256},{0,24,1152},{0,18,61},{0,18,61},{0,11,100},{0,12,2859},{0,10,1157},{6,22,1},{6,22,1},{6,22,1},{6,16,5},{14,1,1152},
+{0,18,61},{0,18,61},{0,11,100},{24,0,1152},{0,11,100},{24,1,1568},{2,29,2},{8,19,5},{0,19,5},{24,1,1568},{31,6,1568},{0,19,5},{0,15,1586},{31,6,1568},{0,15,1586},{3,0,1252},{3,0,1252},{3,0,1252},{3,0,1252},{0,16,1},{0,16,1},{0,16,1},{0,10,1},{0,8,657},{0,8,657},{5,31,3716},{4,29,1603},{4,21,2148},{4,19,1631},{2,31,5655},{0,25,2005},{0,20,31},
+{0,15,2138},{0,19,8963},{0,15,4070},{7,31,1587},{7,26,131},{8,20,82},{7,19,181},{20,2,5419},{0,25,2001},{0,20,27},{0,15,2134},{24,7,5419},{0,15,2134},{4,28,1587},{4,28,1587},{4,28,1587},{4,18,1590},{0,27,1158},{0,20,22},{0,20,22},{0,12,62},{0,14,3075},{0,11,1221},{7,23,1},{7,23,1},{7,23,1},{7,17,5},{16,0,1152},{0,20,18},{0,20,18},{0,12,58},{25,1,1152},
+{0,12,58},{25,2,1568},{3,30,2},{9,20,13},{1,20,9},{25,2,1568},{27,10,1568},{1,20,9},{0,16,1576},{27,10,1568},{0,16,1576},{4,0,1586},{4,0,1586},{4,0,1586},{4,0,1586},{0,19,4},{0,19,4},{0,19,4},{0,11,8},{0,9,769},{0,9,769},{6,31,3890},{5,30,1603},{5,22,2148},{5,20,1627},{3,31,5748},{0,27,1989},{1,21,31},{0,17,2117},{0,21,8560},{0,16,3545},{9,31,1634},
+{8,27,149},{8,21,73},{8,20,194},{21,3,5419},{0,27,1889},{1,21,27},{0,17,2017},{28,6,5419},{0,17,2017},{5,29,1587},{5,29,1587},{5,29,1587},{5,19,1590},{1,28,1158},{1,21,22},{1,21,22},{1,13,62},{0,16,2801},{0,13,949},{8,24,1},{8,24,1},{8,24,1},{8,17,4},{17,1,1152},{0,22,2},{0,22,2},{0,14,26},{26,2,1152},{0,14,26},{26,3,1568},{4,31,5},{10,21,13},
+{2,21,9},{26,3,1568},{28,11,1568},{2,21,9},{0,17,1576},{28,11,1568},{0,17,1576},{5,0,1586},{5,0,1586},{5,0,1586},{5,0,1586},{1,20,4},{1,20,4},{1,20,4},{1,12,8},{0,10,625},{0,10,625},{7,31,4136},{6,31,1589},{7,23,2157},{6,21,1621},{4,31,5895},{1,28,1977},{2,22,33},{1,18,2107},{0,23,8196},{0,17,3043},{10,31,1667},{9,28,131},{10,22,69},{9,21,181},{24,1,5419},
+{0,29,1772},{2,22,24},{0,18,1875},{31,6,5419},{0,18,1875},{6,30,1576},{6,30,1576},{6,30,1576},{6,20,1580},{2,29,1161},{2,22,29},{2,22,29},{2,15,58},{0,17,2529},{0,14,656},{9,25,1},{9,25,1},{9,25,1},{9,19,5},{17,4,1152},{0,24,1},{0,24,1},{0,15,1},{29,2,1152},{0,15,1},{27,4,1568},{6,31,13},{11,22,5},{3,22,5},{27,4,1568},{31,11,1568},{3,22,5},
+{0,18,1586},{31,11,1568},{0,18,1586},{6,0,1576},{6,0,1576},{6,0,1576},{6,0,1576},{2,21,10},{2,21,10},{2,21,10},{2,14,13},{0,12,520},{0,12,520},{8,31,4436},{7,31,1625},{8,23,2175},{7,22,1621},{6,31,6079},{3,28,1973},{3,23,33},{2,19,2107},{0,24,7969},{0,18,2675},{11,31,1745},{10,29,131},{11,23,69},{10,22,181},{25,2,5419},{0,30,1699},{3,23,24},{0,19,1782},{27,10,5419},
+{0,19,1782},{7,31,1576},{7,31,1576},{7,31,1576},{7,21,1580},{3,30,1161},{3,23,29},{3,23,29},{3,16,74},{0,19,2313},{0,15,474},{10,26,1},{10,26,1},{10,26,1},{10,20,5},{18,5,1152},{1,25,1},{1,25,1},{0,16,2},{30,3,1152},{0,16,2},{31,0,1568},{8,31,34},{12,23,5},{4,23,5},{31,0,1568},{30,13,1568},{4,23,5},{0,19,1586},{30,13,1568},{0,19,1586},{7,0,1576},
+{7,0,1576},{7,0,1576},{7,0,1576},{3,22,10},{3,22,10},{3,22,10},{3,15,13},{0,14,400},{0,14,400},{9,31,4730},{8,31,1716},{8,25,2148},{8,23,1631},{7,31,6244},{3,30,1977},{4,24,31},{4,19,2138},{0,26,7669},{0,19,2375},{12,31,1832},{11,30,131},{12,24,82},{11,23,181},{26,3,5419},{1,31,1699},{4,24,27},{0,20,1720},{28,11,5419},{0,20,1720},{8,31,1595},{8,31,1595},{8,31,1595},
+{8,22,1590},{4,31,1158},{4,24,22},{4,24,22},{4,16,62},{0,21,2091},{0,17,306},{11,27,1},{11,27,1},{11,27,1},{11,21,5},{20,4,1152},{2,26,1},{2,26,1},{1,17,2},{29,5,1152},{1,17,2},{29,6,1568},{9,31,68},{13,24,13},{5,24,9},{29,6,1568},{31,14,1568},{5,24,9},{0,20,1576},{31,14,1568},{0,20,1576},{8,0,1586},{8,0,1586},{8,0,1586},{8,0,1586},{4,23,4},
+{4,23,4},{4,23,4},{4,15,8},{0,16,277},{0,16,277},{11,31,5010},{9,31,1878},{9,26,2148},{9,24,1627},{8,31,6508},{4,31,1989},{5,25,31},{4,21,2117},{0,28,7364},{0,21,2098},{14,31,1952},{12,31,149},{12,25,73},{12,24,194},{28,2,5419},{3,31,1787},{5,25,27},{0,21,1657},{27,13,5419},{0,21,1657},{9,31,1622},{9,31,1622},{9,31,1622},{9,23,1590},{5,31,1164},{5,25,22},{5,25,22},
+{5,17,62},{0,22,1928},{0,18,194},{12,28,1},{12,28,1},{12,28,1},{12,21,4},{24,0,1152},{3,27,1},{3,27,1},{2,18,2},{30,6,1152},{2,18,2},{30,7,1568},{11,31,116},{14,25,13},{6,25,9},{30,7,1568},{30,16,1568},{6,25,9},{0,21,1576},{30,16,1568},{0,21,1576},{9,0,1586},{9,0,1586},{9,0,1586},{9,0,1586},{5,24,4},{5,24,4},{5,24,4},{5,16,8},{0,18,193},
+{0,18,193},{12,31,5316},{11,31,2154},{11,27,2157},{10,25,1621},{10,31,6800},{6,31,1999},{6,26,33},{5,22,2107},{0,29,7068},{0,22,1836},{15,31,2081},{13,31,206},{14,26,69},{13,25,181},{31,0,5419},{5,31,1937},{6,26,24},{0,22,1611},{30,13,5419},{0,22,1611},{10,31,1676},{10,31,1676},{10,31,1676},{10,24,1580},{7,31,1179},{6,26,29},{6,26,29},{6,19,58},{0,24,1798},{0,19,157},{13,29,1},
+{13,29,1},{13,29,1},{13,23,5},{24,3,1152},{4,28,1},{4,28,1},{4,19,1},{28,9,1152},{4,19,1},{31,8,1568},{13,31,205},{15,26,5},{7,26,5},{31,8,1568},{28,19,1568},{7,26,5},{0,22,1586},{28,19,1568},{0,22,1586},{10,0,1576},{10,0,1576},{10,0,1576},{10,0,1576},{6,25,10},{6,25,10},{6,25,10},{6,18,13},{0,20,106},{0,20,106},{13,31,5658},{12,31,2435},{12,27,2175},
+{11,26,1621},{11,31,7055},{7,31,2090},{7,27,33},{6,23,2107},{0,31,6820},{0,23,1690},{16,31,2216},{14,31,334},{15,27,69},{14,26,181},{29,6,5419},{7,31,2081},{7,27,24},{0,23,1590},{31,14,5419},{0,23,1590},{11,31,1745},{11,31,1745},{11,31,1745},{11,25,1580},{8,31,1220},{7,27,29},{7,27,29},{7,20,74},{0,26,1650},{1,20,137},{14,30,1},{14,30,1},{14,30,1},{14,24,5},{22,9,1152},
+{5,29,1},{5,29,1},{4,20,2},{29,10,1152},{4,20,2},{29,14,1568},{15,31,289},{16,27,5},{8,27,5},{29,14,1568},{29,20,1568},{8,27,5},{0,23,1586},{29,20,1568},{0,23,1586},{11,0,1576},{11,0,1576},{11,0,1576},{11,0,1576},{7,26,10},{7,26,10},{7,26,10},{7,19,13},{0,22,58},{0,22,58},{14,31,6036},{13,31,2751},{12,29,2148},{12,27,1631},{12,31,7316},{8,31,2228},{8,28,31},
+{8,23,2138},{0,31,6884},{0,24,1613},{17,31,2402},{16,31,500},{16,28,82},{15,27,181},{30,7,5419},{9,31,2195},{8,28,27},{0,24,1577},{30,16,5419},{0,24,1577},{12,31,1811},{12,31,1811},{12,31,1811},{12,26,1590},{9,31,1286},{8,28,22},{8,28,22},{8,20,62},{0,28,1508},{2,21,137},{15,31,1},{15,31,1},{15,31,1},{15,25,5},{24,8,1152},{6,30,1},{6,30,1},{5,21,2},{30,11,1152},
+{5,21,2},{30,15,1568},{17,31,410},{17,28,13},{9,28,9},{30,15,1568},{30,21,1568},{9,28,9},{0,24,1576},{30,21,1568},{0,24,1576},{12,0,1586},{12,0,1586},{12,0,1586},{12,0,1586},{8,27,4},{8,27,4},{8,27,4},{8,19,8},{0,24,37},{0,24,37},{15,31,6450},{14,31,3135},{13,30,2148},{13,28,1627},{13,31,7661},{10,31,2448},{9,29,31},{8,25,2117},{2,31,7196},{0,25,1593},{19,31,2594},
+{17,31,698},{16,29,73},{16,28,194},{29,11,5419},{11,31,2379},{9,29,27},{1,25,1577},{31,17,5419},{1,25,1577},{13,31,1910},{13,31,1910},{13,31,1910},{13,27,1590},{10,31,1388},{9,29,22},{9,29,22},{9,21,62},{0,30,1416},{3,22,137},{16,31,4},{16,31,4},{16,31,4},{16,25,4},{28,4,1152},{7,31,1},{7,31,1},{6,22,2},{29,13,1152},{6,22,2},{31,16,1568},{19,31,530},{18,29,13},
+{10,29,9},{31,16,1568},{31,22,1568},{10,29,9},{0,25,1576},{31,22,1568},{0,25,1576},{13,0,1586},{13,0,1586},{13,0,1586},{13,0,1586},{9,28,4},{9,28,4},{9,28,4},{9,20,8},{0,25,17},{0,25,17},{16,31,6900},{15,31,3657},{15,31,2157},{14,29,1621},{15,31,8023},{11,31,2845},{10,30,33},{9,26,2107},{5,31,7651},{1,26,1611},{20,31,2866},{18,31,1011},{18,30,69},{17,29,181},{29,14,5419},
+{13,31,2657},{10,30,24},{3,26,1587},{29,20,5419},{3,26,1587},{15,31,2057},{15,31,2057},{15,31,2057},{14,28,1580},{12,31,1476},{10,30,29},{10,30,29},{10,23,58},{0,31,1324},{4,23,157},{17,31,37},{17,31,37},{17,31,37},{17,27,5},{31,2,1152},{9,31,4},{9,31,4},{8,23,1},{27,16,1152},{8,23,1},{31,19,1568},{21,31,637},{19,30,5},{11,30,5},{31,19,1568},{27,26,1568},{11,30,5},
+{0,26,1586},{27,26,1568},{0,26,1586},{14,0,1576},{14,0,1576},{14,0,1576},{14,0,1576},{10,29,10},{10,29,10},{10,29,10},{10,22,13},{1,27,9},{1,27,9},{18,31,7332},{16,31,4196},{16,31,2175},{15,30,1621},{16,31,8348},{13,31,3285},{11,31,33},{10,27,2107},{8,31,8004},{2,27,1611},{21,31,3112},{20,31,1281},{19,31,69},{18,30,181},{30,15,5419},{15,31,2897},{11,31,24},{3,27,1590},{30,21,5419},
+{3,27,1590},{16,31,2171},{16,31,2171},{16,31,2171},{15,29,1580},{13,31,1590},{11,31,29},{11,31,29},{11,24,74},{2,31,1424},{5,24,137},{19,31,65},{19,31,65},{19,31,65},{18,28,5},{26,13,1152},{11,31,20},{11,31,20},{8,24,2},{21,21,1152},{8,24,2},{30,23,1568},{23,31,785},{20,31,5},{12,31,5},{30,23,1568},{28,27,1568},{12,31,5},{0,27,1586},{28,27,1568},{0,27,1586},{15,0,1576},
+{15,0,1576},{15,0,1576},{15,0,1576},{11,30,10},{11,30,10},{11,30,10},{11,23,13},{1,28,8},{1,28,8},{19,31,7014},{17,31,4230},{17,31,2294},{16,31,1595},{17,31,7865},{14,31,3114},{12,31,85},{12,27,1706},{8,31,7436},{3,28,1268},{22,31,2794},{21,31,1221},{20,31,113},{19,30,114},{30,17,4803},{17,31,2648},{13,31,61},{4,28,1253},{25,25,4803},{4,28,1253},{17,31,2294},{17,31,2294},{17,31,2294},
+{16,30,1590},{14,31,1740},{12,31,85},{12,31,85},{12,24,62},{3,31,1571},{6,25,137},{20,31,113},{20,31,113},{20,31,113},{19,29,5},{28,12,1152},{13,31,61},{13,31,61},{9,25,2},{22,22,1152},{9,25,2},{31,23,1250},{24,31,680},{21,31,4},{15,31,0},{31,23,1250},{23,31,1250},{15,31,0},{0,28,1252},{23,31,1250},{0,28,1252},{16,0,1586},{16,0,1586},{16,0,1586},{16,0,1586},{12,31,4},
+{12,31,4},{12,31,4},{12,23,8},{2,29,8},{2,29,8},{19,31,6534},{18,31,4116},{18,31,2435},{17,31,1590},{18,31,7164},{15,31,2809},{14,31,161},{12,28,1256},{10,31,6748},{5,28,945},{23,31,2340},{22,31,1065},{21,31,164},{20,31,64},{31,17,4056},{18,31,2211},{15,31,113},{7,28,900},{25,26,4056},{7,28,900},{18,31,2435},{18,31,2435},{18,31,2435},{17,31,1590},{16,31,1923},{14,31,161},{14,31,161},
+{13,25,62},{6,31,1729},{7,26,137},{21,31,164},{21,31,164},{21,31,164},{20,29,4},{29,13,1152},{15,31,113},{15,31,113},{10,26,2},{28,20,1152},{10,26,2},{30,26,882},{25,31,482},{23,31,0},{18,31,1},{30,26,882},{31,27,882},{18,31,1},{0,28,900},{31,27,882},{0,28,900},{17,0,1586},{17,0,1586},{17,0,1586},{17,0,1586},{13,31,13},{13,31,13},{13,31,13},{13,24,8},{3,30,8},
+{3,30,8},{21,31,6091},{20,31,4022},{19,31,2609},{18,31,1640},{19,31,6490},{16,31,2617},{15,31,318},{14,28,835},{11,31,6135},{6,29,598},{24,31,1881},{23,31,931},{22,31,245},{21,31,5},{31,19,3318},{20,31,1733},{17,31,202},{8,29,545},{27,26,3318},{8,29,545},{19,31,2609},{19,31,2609},{19,31,2609},{18,31,1640},{17,31,2086},{15,31,318},{15,31,318},{14,27,58},{8,31,1868},{8,27,157},{22,31,245},
+{22,31,245},{22,31,245},{21,31,5},{29,16,1152},{17,31,202},{17,31,202},{12,27,1},{31,20,1152},{12,27,1},{31,26,545},{26,31,305},{25,31,4},{20,31,1},{31,26,545},{29,29,545},{20,31,1},{0,29,545},{29,29,545},{0,29,545},{18,0,1576},{18,0,1576},{18,0,1576},{18,0,1576},{15,31,29},{15,31,29},{15,31,29},{14,26,13},{5,31,9},{5,31,9},{22,31,5719},{21,31,3980},{20,31,2834},
+{19,31,1745},{20,31,6050},{18,31,2457},{16,31,536},{15,29,515},{14,31,5674},{7,30,406},{25,31,1573},{24,31,861},{23,31,338},{22,31,10},{30,22,2753},{21,31,1438},{19,31,290},{11,29,338},{27,27,2753},{11,29,338},{20,31,2834},{20,31,2834},{20,31,2834},{19,31,1745},{18,31,2284},{16,31,536},{16,31,536},{15,28,74},{10,31,2064},{9,28,137},{23,31,338},{23,31,338},{23,31,338},{22,31,10},{30,17,1152},
+{19,31,290},{19,31,290},{12,28,2},{25,25,1152},{12,28,2},{31,27,313},{28,31,181},{26,31,1},{23,31,0},{31,27,313},{30,29,313},{23,31,0},{0,29,337},{30,29,313},{0,29,337},{19,0,1576},{19,0,1576},{19,0,1576},{19,0,1576},{16,31,52},{16,31,52},{16,31,52},{15,27,13},{6,31,25},{6,31,25},{22,31,5399},{22,31,3974},{21,31,3035},{20,31,1875},{21,31,5619},{19,31,2378},{18,31,776},
+{16,30,318},{15,31,5258},{9,30,225},{26,31,1333},{25,31,813},{24,31,425},{23,31,65},{30,24,2273},{23,31,1218},{20,31,353},{12,30,146},{29,27,2273},{12,30,146},{21,31,3035},{21,31,3035},{21,31,3035},{20,31,1875},{19,31,2518},{18,31,776},{18,31,776},{16,28,62},{11,31,2323},{10,29,137},{24,31,425},{24,31,425},{24,31,425},{23,31,65},{31,18,1152},{20,31,353},{20,31,353},{13,29,2},{26,26,1152},
+{13,29,2},{31,28,145},{28,31,85},{28,31,4},{26,31,1},{31,28,145},{30,30,145},{26,31,1},{0,30,145},{30,30,145},{0,30,145},{20,0,1586},{20,0,1586},{20,0,1586},{20,0,1586},{17,31,85},{17,31,85},{17,31,85},{16,27,8},{8,31,40},{8,31,40},{23,31,5143},{23,31,4004},{22,31,3254},{21,31,2070},{22,31,5274},{20,31,2310},{19,31,1062},{17,30,133},{17,31,5011},{10,31,161},{27,31,1161},
+{26,31,801},{26,31,545},{25,31,164},{31,24,1878},{24,31,1094},{22,31,461},{14,30,66},{24,31,1878},{14,30,66},{22,31,3254},{22,31,3254},{22,31,3254},{21,31,2070},{20,31,2833},{19,31,1062},{19,31,1062},{17,29,62},{14,31,2577},{11,30,137},{26,31,545},{26,31,545},{26,31,545},{25,31,164},{30,22,1152},{22,31,461},{22,31,461},{14,30,2},{27,27,1152},{14,30,2},{30,31,41},{30,31,25},{29,31,1},
+{28,31,0},{30,31,41},{31,30,41},{28,31,0},{0,30,65},{31,30,41},{0,30,65},{21,0,1586},{21,0,1586},{21,0,1586},{21,0,1586},{18,31,136},{18,31,136},{18,31,136},{17,28,8},{10,31,80},{10,31,80},{24,31,4882},{24,31,4070},{23,31,3532},{22,31,2360},{24,31,4945},{21,31,2422},{20,31,1433},{18,31,58},{20,31,4717},{12,31,157},{28,31,1026},{27,31,835},{27,31,666},{26,31,305},{31,26,1536},
+{26,31,996},{24,31,628},{16,31,1},{29,29,1536},{16,31,1},{23,31,3532},{23,31,3532},{23,31,3532},{22,31,2360},{22,31,3110},{20,31,1433},{20,31,1433},{18,31,58},{16,31,2939},{12,31,157},{27,31,666},{27,31,666},{27,31,666},{26,31,305},{30,25,1152},{24,31,628},{24,31,628},{16,31,1},{30,27,1152},{16,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},
+{0,31,0},{31,31,0},{0,31,0},{22,0,1576},{22,0,1576},{22,0,1576},{22,0,1576},{19,31,221},{19,31,221},{19,31,221},{18,30,13},{12,31,157},{12,31,157},{25,31,4212},{24,31,3590},{24,31,3106},{23,31,2201},{24,31,4129},{22,31,2101},{21,31,1301},{19,31,13},{20,31,3869},{14,31,233},{28,31,706},{28,31,562},{28,31,481},{27,31,218},{31,27,1067},{27,31,699},{25,31,442},{18,31,1},{30,29,1067},
+{18,31,1},{24,31,3106},{24,31,3106},{24,31,3106},{23,31,2201},{23,31,2668},{21,31,1301},{21,31,1301},{19,31,13},{18,31,2523},{14,31,233},{28,31,481},{28,31,481},{28,31,481},{27,31,218},{31,25,802},{25,31,442},{25,31,442},{18,31,1},{31,27,802},{18,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{23,0,1576},
+{23,0,1576},{23,0,1576},{23,0,1576},{20,31,325},{20,31,325},{20,31,325},{19,31,13},{14,31,233},{14,31,233},{26,31,3642},{25,31,3132},{25,31,2771},{24,31,2070},{25,31,3444},{23,31,1834},{22,31,1205},{20,31,8},{21,31,3219},{16,31,346},{29,31,456},{28,31,370},{28,31,289},{28,31,145},{30,29,683},{28,31,451},{27,31,290},{21,31,1},{29,30,683},{21,31,1},{25,31,2771},{25,31,2771},{25,31,2771},
+{24,31,2070},{24,31,2273},{22,31,1205},{22,31,1205},{20,31,8},{20,31,2121},{16,31,346},{28,31,289},{28,31,289},{28,31,289},{28,31,145},{31,26,512},{27,31,290},{27,31,290},{21,31,1},{29,29,512},{21,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{24,0,1586},{24,0,1586},{24,0,1586},{24,0,1586},{22,31,421},
+{22,31,421},{22,31,421},{20,31,8},{16,31,346},{16,31,346},{26,31,3162},{26,31,2742},{26,31,2486},{25,31,1947},{26,31,2877},{24,31,1641},{23,31,1145},{22,31,52},{22,31,2673},{18,31,458},{29,31,264},{29,31,200},{29,31,164},{28,31,81},{30,30,384},{28,31,243},{28,31,162},{23,31,1},{30,30,384},{23,31,1},{26,31,2486},{26,31,2486},{26,31,2486},{25,31,1947},{24,31,1969},{23,31,1145},{23,31,1145},
+{22,31,52},{20,31,1785},{18,31,458},{29,31,164},{29,31,164},{29,31,164},{28,31,81},{31,27,290},{28,31,162},{28,31,162},{23,31,1},{30,29,290},{23,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{25,0,1586},{25,0,1586},{25,0,1586},{25,0,1586},{23,31,520},{23,31,520},{23,31,520},{22,31,52},{18,31,458},
+{18,31,458},{0,23,2665},{0,18,680},{0,13,50},{0,11,785},{0,15,5885},{0,11,4118},{0,10,1800},{0,7,4202},{0,8,6546},{0,7,4643},{0,23,2665},{0,18,680},{0,13,50},{0,11,785},{9,0,5885},{0,11,4118},{0,10,1800},{0,7,4202},{15,0,5885},{0,7,4202},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,549},{0,5,289},{0,5,289},{0,3,306},{0,3,630},{0,3,387},{0,11,0},
+{0,11,0},{0,11,0},{0,7,4},{2,2,545},{0,5,289},{0,5,289},{0,3,306},{4,1,545},{0,3,306},{13,1,2665},{0,18,680},{0,13,50},{0,11,785},{13,1,2665},{23,0,2665},{0,11,785},{0,8,2689},{23,0,2665},{0,8,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,2665},{0,20,521},{0,14,5},
+{0,12,625},{0,17,6669},{0,13,4529},{0,11,1890},{0,8,4610},{0,9,7494},{0,7,5171},{0,25,2665},{0,20,521},{0,14,5},{0,12,625},{9,2,6669},{0,13,4529},{0,11,1890},{0,8,4610},{17,0,6669},{0,8,4610},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{0,7,841},{0,6,445},{0,6,445},{0,4,464},{0,3,982},{0,3,595},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{4,0,841},
+{0,6,445},{0,6,445},{0,4,464},{7,0,841},{0,4,464},{14,2,2665},{0,20,521},{0,14,5},{0,12,625},{14,2,2665},{25,0,2665},{0,12,625},{0,9,2689},{25,0,2665},{0,9,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,28,2665},{0,22,405},{0,15,10},{0,13,514},{0,19,7541},{0,14,4934},{0,12,2042},
+{0,9,5045},{0,10,8546},{0,8,5682},{0,28,2665},{0,22,405},{0,15,10},{0,13,514},{10,2,7538},{0,14,4934},{0,12,2042},{0,9,5045},{17,1,7538},{0,9,5045},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{0,8,1201},{0,7,637},{0,7,637},{0,4,656},{0,4,1385},{0,4,800},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{5,0,1201},{0,7,637},{0,7,637},{0,4,656},{8,0,1201},
+{0,4,656},{16,1,2665},{0,22,405},{1,15,5},{0,13,514},{16,1,2665},{28,0,2665},{0,13,514},{0,10,2689},{28,0,2665},{0,10,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,30,2669},{0,23,313},{0,16,68},{0,15,410},{0,20,8498},{0,16,5330},{0,13,2210},{0,10,5530},{0,11,9702},{0,9,6270},{0,30,2669},
+{0,23,313},{0,16,68},{0,15,410},{11,2,8493},{0,16,5330},{0,13,2210},{0,10,5530},{17,2,8493},{0,10,5530},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{0,9,1629},{0,8,832},{0,8,832},{0,5,881},{0,5,1874},{0,5,1106},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{5,1,1625},{0,8,832},{0,8,832},{0,5,881},{8,1,1625},{0,5,881},{17,2,2665},{0,23,313},{2,16,8},
+{0,15,410},{17,2,2665},{29,1,2665},{0,15,410},{0,11,2689},{29,1,2665},{0,11,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,2777},{0,26,232},{0,17,197},{0,16,305},{0,22,9674},{0,17,5849},{0,14,2450},{0,10,6106},{0,12,11199},{0,10,7006},{1,31,2741},{0,26,232},{1,17,146},{0,16,305},{11,4,9669},
+{0,17,5849},{0,14,2450},{0,10,6106},{19,2,9669},{0,10,6106},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{0,11,2178},{0,10,1125},{0,10,1125},{0,6,1189},{0,6,2520},{0,5,1475},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{6,1,2178},{0,10,1125},{0,10,1125},{0,6,1189},{11,0,2178},{0,6,1189},{20,0,2665},{0,26,232},{3,17,2},{0,16,305},{20,0,2665},{30,2,2665},{0,16,305},
+{0,12,2689},{30,2,2665},{0,12,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,31,2949},{0,28,217},{1,18,261},{0,17,282},{0,25,9670},{0,19,5529},{0,16,1970},{0,12,5738},{0,13,11589},{0,11,6898},{2,31,2789},{0,28,217},{2,18,146},{0,17,282},{15,0,9669},{0,19,5529},{0,16,1970},{0,12,5738},{20,3,9669},
+{0,12,5738},{0,24,64},{0,24,64},{0,24,64},{1,14,64},{0,13,2180},{0,11,949},{0,11,949},{0,7,1018},{0,7,2691},{0,6,1433},{1,23,1},{1,23,1},{1,23,1},{1,14,0},{8,0,2178},{0,11,949},{0,11,949},{0,7,1018},{5,5,2178},{0,7,1018},{21,1,2665},{0,28,153},{4,18,5},{0,17,218},{21,1,2665},{31,3,2665},{0,17,218},{0,13,2689},{31,3,2665},{0,13,2689},{0,0,64},
+{0,0,64},{0,0,64},{0,0,64},{0,3,1},{0,3,1},{0,3,1},{0,2,4},{0,1,18},{0,1,18},{2,31,3285},{1,28,273},{2,19,453},{1,18,346},{0,27,9674},{0,20,5170},{0,17,1546},{0,13,5429},{0,15,11993},{0,12,6819},{3,31,2873},{1,28,209},{3,19,146},{1,18,282},{14,4,9669},{0,20,5170},{0,17,1546},{0,13,5429},{24,2,9669},{0,13,5429},{1,25,128},{1,25,128},{1,25,128},
+{1,15,137},{0,16,2178},{0,13,832},{0,13,832},{0,8,881},{0,8,2882},{0,7,1427},{2,23,4},{2,23,4},{2,23,4},{2,15,0},{9,1,2178},{0,13,832},{0,13,832},{0,8,881},{16,0,2178},{0,8,881},{23,0,2665},{0,29,85},{5,19,5},{0,18,149},{23,0,2665},{30,5,2665},{0,18,149},{0,14,2689},{30,5,2665},{0,14,2689},{1,0,128},{1,0,128},{1,0,128},{1,0,128},{0,5,1},
+{0,5,1},{0,5,1},{0,3,1},{0,2,72},{0,2,72},{3,31,3785},{1,30,405},{2,21,676},{1,19,469},{0,30,9669},{0,22,4878},{0,18,1190},{0,14,5138},{0,16,12390},{0,13,6789},{4,31,2966},{2,29,209},{4,20,149},{2,19,282},{18,0,9669},{0,22,4878},{0,18,1190},{0,14,5138},{30,0,9669},{0,14,5138},{2,26,320},{2,26,320},{2,26,320},{1,17,320},{0,19,2180},{0,15,680},{0,15,680},
+{0,9,740},{0,9,3149},{0,8,1441},{3,24,1},{3,24,1},{3,24,1},{3,16,1},{10,2,2178},{0,15,680},{0,15,680},{0,9,740},{17,1,2178},{0,9,740},{24,1,2665},{0,31,41},{6,20,8},{0,19,98},{24,1,2665},{31,6,2665},{0,19,98},{0,15,2689},{31,6,2665},{0,15,2689},{1,0,320},{1,0,320},{1,0,320},{1,0,320},{0,8,0},{0,8,0},{0,8,0},{0,5,1},{0,4,160},
+{0,4,160},{4,31,4514},{2,31,630},{3,22,1027},{2,20,694},{1,31,9738},{0,23,4646},{0,20,849},{0,15,4826},{0,18,12955},{0,14,6798},{6,31,3101},{3,31,218},{5,21,146},{3,20,299},{18,3,9669},{0,23,4646},{0,20,849},{0,15,4826},{28,3,9669},{0,15,4826},{2,29,545},{2,29,545},{2,29,545},{2,18,546},{0,22,2180},{0,17,505},{0,17,505},{0,11,610},{0,11,3467},{0,10,1513},{4,26,1},
+{4,26,1},{4,26,1},{4,17,0},{13,0,2178},{0,17,505},{0,17,505},{0,11,610},{20,1,2178},{0,11,610},{26,1,2665},{2,31,85},{7,21,2},{0,20,65},{26,1,2665},{31,8,2665},{0,20,65},{0,16,2689},{31,8,2665},{0,16,2689},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,289},{0,5,289},{4,31,5330},{3,31,1018},{3,23,1430},
+{2,21,979},{2,31,9981},{0,26,4406},{0,21,579},{0,16,4610},{0,19,13489},{0,15,6846},{7,31,3233},{4,31,226},{6,22,146},{4,21,282},{20,2,9669},{0,26,4406},{0,21,579},{0,16,4610},{24,7,9669},{0,16,4610},{3,30,865},{3,30,865},{3,30,865},{3,19,866},{0,24,2178},{0,19,389},{0,19,389},{0,12,464},{0,12,3885},{0,11,1603},{5,27,1},{5,27,1},{5,27,1},{5,18,0},{14,1,2178},
+{0,19,389},{0,19,389},{0,12,464},{24,0,2178},{0,12,464},{28,0,2665},{3,31,153},{8,22,5},{0,22,37},{28,0,2665},{30,10,2665},{0,22,37},{0,17,2689},{30,10,2665},{0,17,2689},{3,0,865},{3,0,865},{3,0,865},{3,0,865},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{0,6,445},{0,6,445},{5,31,6270},{3,31,1626},{4,24,1886},{3,22,1299},{2,31,10381},{0,28,4146},{0,22,377},
+{0,17,4373},{0,20,14006},{0,16,6915},{8,31,3434},{6,31,242},{7,23,146},{5,22,282},{21,3,9669},{0,28,4146},{0,22,377},{0,17,4373},{28,6,9669},{0,17,4373},{3,31,1226},{3,31,1226},{3,31,1226},{3,21,1205},{0,27,2180},{0,21,274},{0,21,274},{0,13,353},{0,14,4269},{0,11,1763},{6,27,4},{6,27,4},{6,27,4},{6,19,0},{16,0,2178},{0,21,274},{0,21,274},{0,13,353},{25,1,2178},
+{0,13,353},{29,1,2665},{5,31,232},{9,23,5},{0,23,10},{29,1,2665},{31,11,2665},{0,23,10},{0,18,2689},{31,11,2665},{0,18,2689},{3,0,1201},{3,0,1201},{3,0,1201},{3,0,1201},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{0,7,637},{0,7,637},{6,31,7374},{4,31,2339},{4,25,2441},{3,23,1730},{3,31,10950},{0,29,3909},{0,23,243},{0,18,4154},{0,22,14614},{0,17,7029},{9,31,3638},
+{7,31,320},{8,24,149},{6,23,282},{22,4,9669},{0,29,3909},{0,23,243},{0,18,4154},{29,7,9669},{0,18,4154},{4,31,1714},{4,31,1714},{4,31,1714},{3,22,1666},{0,29,2180},{0,23,194},{0,23,194},{0,14,260},{0,15,4686},{0,13,1937},{7,28,1},{7,28,1},{7,28,1},{7,20,1},{17,1,2178},{0,23,194},{0,23,194},{0,14,260},{26,2,2178},{0,14,260},{31,0,2665},{8,31,313},{10,24,8},
+{0,24,4},{31,0,2665},{30,13,2665},{0,24,4},{0,19,2689},{30,13,2665},{0,19,2689},{3,0,1665},{3,0,1665},{3,0,1665},{3,0,1665},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{0,8,832},{0,8,832},{7,31,8807},{5,31,3388},{5,26,3116},{4,24,2243},{4,31,11766},{0,31,3686},{0,25,138},{0,19,3938},{0,23,15369},{0,18,7206},{11,31,3853},{8,31,457},{9,25,146},{7,24,299},{25,2,9669},
+{0,31,3686},{0,25,138},{0,19,3938},{27,10,9669},{0,19,3938},{5,31,2427},{5,31,2427},{5,31,2427},{4,23,2182},{0,31,2210},{0,25,137},{0,25,137},{0,15,181},{0,16,5157},{0,14,2163},{8,30,1},{8,30,1},{8,30,1},{8,21,0},{17,4,2178},{0,25,137},{0,25,137},{0,15,181},{29,2,2178},{0,15,181},{31,3,2665},{9,31,405},{11,25,2},{1,25,2},{31,3,2665},{30,15,2665},{1,25,2},
+{0,20,2689},{30,15,2665},{0,20,2689},{4,0,2178},{4,0,2178},{4,0,2178},{4,0,2178},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{0,10,1125},{0,10,1125},{7,31,10230},{6,31,4421},{6,27,3739},{4,26,2742},{5,31,12634},{0,31,3719},{0,26,87},{0,20,3771},{0,25,16061},{0,19,7283},{12,31,4050},{10,31,629},{10,26,146},{8,25,282},{26,3,9669},{0,31,3718},{0,26,86},{0,20,3770},{28,11,9669},
+{0,20,3770},{5,31,3050},{5,31,3050},{5,31,3050},{5,24,2690},{1,31,2325},{0,26,86},{0,26,86},{0,16,129},{0,18,5544},{0,15,2318},{9,31,1},{9,31,1},{9,31,1},{9,22,0},{18,5,2178},{0,26,85},{0,26,85},{0,16,128},{30,3,2178},{0,16,128},{31,6,2665},{11,31,521},{12,26,5},{2,26,2},{31,6,2665},{29,17,2665},{2,26,2},{0,21,2689},{29,17,2665},{0,21,2689},{5,0,2689},
+{5,0,2689},{5,0,2689},{5,0,2689},{0,24,1},{0,24,1},{0,24,1},{0,15,5},{0,11,1348},{0,11,1348},{9,31,10738},{7,31,4899},{7,28,3705},{5,27,2742},{6,31,13045},{1,31,4002},{1,27,87},{0,21,3686},{0,27,15601},{0,20,6570},{13,31,4302},{11,31,857},{11,27,146},{9,26,282},{28,2,9669},{2,31,3954},{1,27,86},{0,21,3605},{27,13,9669},{0,21,3605},{6,31,3173},{6,31,3173},{6,31,3173},
+{6,25,2690},{2,31,2427},{1,28,83},{1,28,83},{1,17,129},{0,20,5170},{0,16,1856},{10,31,4},{10,31,4},{10,31,4},{10,23,0},{20,4,2178},{0,28,32},{0,28,32},{0,17,89},{29,5,2178},{0,17,89},{31,8,2665},{13,31,680},{13,27,5},{3,27,2},{31,8,2665},{30,18,2665},{3,27,2},{0,22,2689},{30,18,2665},{0,22,2689},{6,0,2689},{6,0,2689},{6,0,2689},{6,0,2689},{1,25,1},
+{1,25,1},{1,25,1},{1,15,10},{0,13,1217},{0,13,1217},{10,31,11278},{8,31,5402},{7,29,3750},{6,28,2745},{7,31,13510},{3,31,4314},{2,28,77},{1,22,3686},{0,28,15046},{0,21,5958},{14,31,4590},{12,31,1171},{12,28,149},{10,27,282},{29,3,9669},{3,31,4265},{2,28,76},{0,22,3458},{28,14,9669},{0,22,3458},{7,31,3314},{7,31,3314},{7,31,3314},{7,26,2690},{4,31,2532},{2,28,73},{2,28,73},
+{2,18,129},{0,21,4837},{0,17,1490},{11,31,25},{11,31,25},{11,31,25},{11,24,1},{24,0,2178},{0,30,8},{0,30,8},{0,19,49},{30,6,2178},{0,19,49},{31,11,2665},{15,31,832},{14,28,8},{4,28,4},{31,11,2665},{31,19,2665},{4,28,4},{0,23,2689},{31,19,2665},{0,23,2689},{7,0,2689},{7,0,2689},{7,0,2689},{7,0,2689},{2,26,1},{2,26,1},{2,26,1},{2,16,5},{0,14,1037},
+{0,14,1037},{11,31,11942},{10,31,6090},{9,30,3739},{7,29,2751},{9,31,14053},{4,31,4863},{3,29,79},{2,24,3689},{0,30,14558},{0,23,5274},{16,31,4858},{14,31,1556},{13,29,146},{11,28,299},{29,6,9669},{6,31,4594},{3,29,75},{0,24,3265},{31,14,9669},{0,24,3265},{9,31,3505},{9,31,3505},{9,31,3505},{8,27,2693},{5,31,2645},{3,30,72},{3,30,72},{3,19,134},{0,23,4506},{0,19,1109},{12,31,64},
+{12,31,64},{12,31,64},{12,25,0},{24,3,2178},{1,31,10},{1,31,10},{0,20,16},{28,9,2178},{0,20,16},{31,14,2665},{17,31,1053},{15,29,2},{5,29,2},{31,14,2665},{29,22,2665},{5,29,2},{0,24,2689},{29,22,2665},{0,24,2689},{8,0,2689},{8,0,2689},{8,0,2689},{8,0,2689},{3,27,5},{3,27,5},{3,27,5},{3,18,8},{0,16,818},{0,16,818},{12,31,12466},{11,31,6718},{10,31,3739},
+{8,30,2742},{10,31,14554},{6,31,5363},{4,30,87},{3,24,3654},{0,31,14190},{0,24,4785},{17,31,5158},{15,31,1938},{14,30,146},{12,29,282},{30,7,9669},{8,31,4806},{4,30,86},{0,25,3130},{30,16,9669},{0,25,3130},{10,31,3658},{10,31,3658},{10,31,3658},{9,28,2690},{6,31,2795},{4,30,86},{4,30,86},{4,20,129},{0,25,4315},{0,20,809},{14,31,100},{14,31,100},{14,31,100},{13,26,0},{22,9,2178},
+{3,31,34},{3,31,34},{0,21,1},{29,10,2178},{0,21,1},{30,18,2665},{19,31,1241},{16,30,5},{6,30,2},{30,18,2665},{30,23,2665},{6,30,2},{0,25,2689},{30,23,2665},{0,25,2689},{9,0,2689},{9,0,2689},{9,0,2689},{9,0,2689},{4,28,1},{4,28,1},{4,28,1},{4,19,5},{0,18,666},{0,18,666},{14,31,13094},{12,31,7445},{11,31,3830},{9,31,2742},{12,31,14998},{8,31,5926},{5,31,87},
+{4,25,3686},{0,31,14254},{0,25,4323},{18,31,5494},{16,31,2414},{15,31,146},{13,30,282},{29,11,9669},{10,31,5138},{5,31,86},{0,26,3013},{31,17,9669},{0,26,3013},{11,31,3829},{11,31,3829},{11,31,3829},{10,29,2690},{7,31,2981},{5,31,86},{5,31,86},{5,21,129},{0,27,4059},{0,21,597},{15,31,145},{15,31,145},{15,31,145},{14,27,0},{24,8,2178},{5,31,85},{5,31,85},{1,22,1},{30,11,2178},
+{1,22,1},{31,19,2665},{20,31,1378},{17,31,5},{7,31,2},{31,19,2665},{29,25,2665},{7,31,2},{0,26,2689},{29,25,2665},{0,26,2689},{10,0,2689},{10,0,2689},{10,0,2689},{10,0,2689},{5,29,1},{5,29,1},{5,29,1},{5,19,10},{0,20,505},{0,20,505},{15,31,12507},{13,31,7370},{12,31,4001},{11,31,2705},{13,31,14148},{8,31,5491},{6,31,154},{5,26,3063},{1,31,13399},{0,26,3306},{19,31,4949},
+{17,31,2261},{16,31,202},{15,30,185},{29,13,8712},{11,31,4644},{7,31,145},{0,27,2403},{28,20,8712},{0,27,2403},{12,31,4001},{12,31,4001},{12,31,4001},{11,30,2690},{9,31,3204},{6,31,154},{6,31,154},{6,22,129},{0,28,3762},{0,23,425},{16,31,202},{16,31,202},{16,31,202},{15,28,1},{28,4,2178},{7,31,145},{7,31,145},{2,23,1},{29,13,2178},{2,23,1},{30,22,2178},{22,31,1145},{18,31,1},
+{10,31,1},{30,22,2178},{27,27,2178},{10,31,1},{0,27,2178},{27,27,2178},{0,27,2178},{11,0,2689},{11,0,2689},{11,0,2689},{11,0,2689},{6,30,1},{6,30,1},{6,30,1},{6,20,5},{0,22,389},{0,22,389},{16,31,11658},{14,31,7195},{13,31,4225},{12,31,2693},{14,31,13066},{10,31,5014},{8,31,261},{6,27,2390},{3,31,12366},{0,27,2277},{20,31,4338},{18,31,2037},{17,31,289},{16,30,89},{29,15,7578},
+{13,31,4037},{9,31,202},{0,27,1701},{30,20,7578},{0,27,1701},{13,31,4225},{13,31,4225},{13,31,4225},{12,31,2693},{10,31,3429},{8,31,261},{8,31,261},{7,23,134},{0,30,3509},{0,24,306},{17,31,289},{17,31,289},{17,31,289},{16,29,0},{31,2,2178},{9,31,202},{9,31,202},{3,24,0},{27,16,2178},{3,24,0},{31,22,1625},{23,31,850},{20,31,0},{13,31,1},{31,22,1625},{30,26,1625},{13,31,1},
+{0,27,1665},{30,26,1625},{0,27,1665},{12,0,2689},{12,0,2689},{12,0,2689},{12,0,2689},{7,31,5},{7,31,5},{7,31,5},{7,22,8},{0,24,306},{0,24,306},{16,31,11002},{15,31,7081},{14,31,4450},{13,31,2738},{15,31,12205},{11,31,4663},{9,31,411},{7,27,1845},{4,31,11643},{0,28,1578},{21,31,3802},{20,31,1845},{18,31,388},{17,31,25},{30,15,6661},{15,31,3525},{11,31,290},{0,28,1217},{30,21,6661},
+{0,28,1217},{14,31,4450},{14,31,4450},{14,31,4450},{13,31,2738},{11,31,3675},{9,31,411},{9,31,411},{8,24,129},{0,31,3354},{0,25,244},{18,31,388},{18,31,388},{18,31,388},{17,30,0},{26,13,2178},{11,31,290},{11,31,290},{4,25,1},{21,21,2178},{4,25,1},{31,23,1201},{24,31,653},{22,31,4},{15,31,1},{31,23,1201},{30,27,1201},{15,31,1},{0,28,1201},{30,27,1201},{0,28,1201},{13,0,2689},
+{13,0,2689},{13,0,2689},{13,0,2689},{8,31,17},{8,31,17},{8,31,17},{8,23,5},{0,26,218},{0,26,218},{17,31,10434},{16,31,7010},{15,31,4693},{14,31,2833},{16,31,11374},{12,31,4462},{10,31,629},{8,28,1387},{6,31,10895},{0,28,1002},{22,31,3334},{20,31,1701},{19,31,505},{18,31,0},{30,17,5829},{16,31,3145},{12,31,405},{1,28,866},{25,25,5829},{1,28,866},{15,31,4693},{15,31,4693},{15,31,4693},
+{14,31,2833},{12,31,3906},{10,31,629},{10,31,629},{9,25,129},{1,31,3525},{0,27,228},{19,31,505},{19,31,505},{19,31,505},{18,31,0},{28,12,2178},{12,31,405},{12,31,405},{5,26,1},{22,22,2178},{5,26,1},{30,26,841},{25,31,461},{23,31,1},{18,31,0},{30,26,841},{31,27,841},{18,31,0},{0,28,865},{31,27,841},{0,28,865},{14,0,2689},{14,0,2689},{14,0,2689},{14,0,2689},{9,31,50},
+{9,31,50},{9,31,50},{9,23,10},{0,28,137},{0,28,137},{18,31,9934},{17,31,6962},{16,31,4913},{15,31,2978},{17,31,10683},{13,31,4277},{11,31,915},{9,28,994},{8,31,10078},{0,29,630},{23,31,2934},{22,31,1605},{21,31,650},{19,31,25},{31,17,5082},{18,31,2769},{14,31,521},{2,29,546},{25,26,5082},{2,29,546},{16,31,4913},{16,31,4913},{16,31,4913},{15,31,2978},{14,31,4170},{11,31,915},{11,31,915},
+{10,26,129},{3,31,3789},{1,28,226},{21,31,650},{21,31,650},{21,31,650},{19,31,25},{29,13,2178},{14,31,521},{14,31,521},{6,27,1},{28,20,2178},{6,27,1},{31,26,545},{26,31,305},{25,31,4},{20,31,1},{31,26,545},{29,29,545},{20,31,1},{0,29,545},{29,29,545},{0,29,545},{15,0,2689},{15,0,2689},{15,0,2689},{15,0,2689},{11,31,74},{11,31,74},{11,31,74},{10,24,5},{0,29,85},
+{0,29,85},{19,31,9465},{18,31,6955},{17,31,5233},{16,31,3218},{18,31,10003},{14,31,4183},{13,31,1258},{10,29,645},{9,31,9445},{1,30,409},{24,31,2529},{23,31,1525},{22,31,785},{20,31,100},{31,19,4344},{20,31,2345},{16,31,698},{5,29,321},{27,26,4344},{5,29,321},{17,31,5233},{17,31,5233},{17,31,5233},{16,31,3218},{15,31,4491},{13,31,1258},{13,31,1258},{11,27,134},{5,31,4171},{2,29,213},{22,31,785},
+{22,31,785},{22,31,785},{20,31,100},{29,16,2178},{16,31,698},{16,31,698},{7,28,0},{31,20,2178},{7,28,0},{31,27,290},{28,31,162},{26,31,4},{23,31,1},{31,27,290},{30,29,290},{23,31,1},{0,29,320},{30,29,290},{0,29,320},{16,0,2689},{16,0,2689},{16,0,2689},{16,0,2689},{12,31,113},{12,31,113},{12,31,113},{11,26,8},{0,31,45},{0,31,45},{20,31,9219},{19,31,6985},{18,31,5530},
+{17,31,3473},{19,31,9496},{15,31,4186},{14,31,1630},{12,29,426},{11,31,8961},{3,30,277},{25,31,2275},{24,31,1509},{23,31,932},{22,31,208},{30,22,3779},{21,31,2086},{18,31,850},{6,30,129},{27,27,3779},{6,30,129},{18,31,5530},{18,31,5530},{18,31,5530},{17,31,3473},{16,31,4770},{14,31,1630},{14,31,1630},{12,28,129},{8,31,4442},{3,30,213},{23,31,932},{23,31,932},{23,31,932},{22,31,208},{30,17,2178},
+{18,31,850},{18,31,850},{8,29,1},{25,25,2178},{8,29,1},{30,30,128},{29,31,72},{28,31,1},{26,31,0},{30,30,128},{30,30,128},{26,31,0},{0,30,128},{30,30,128},{0,30,128},{17,0,2689},{17,0,2689},{17,0,2689},{17,0,2689},{13,31,170},{13,31,170},{13,31,170},{12,27,5},{2,31,89},{2,31,89},{21,31,8929},{20,31,7062},{19,31,5845},{18,31,3778},{20,31,9188},{17,31,4260},{15,31,2070},
+{13,30,234},{13,31,8680},{4,31,228},{26,31,2089},{25,31,1515},{24,31,1073},{23,31,353},{30,24,3299},{22,31,1913},{20,31,965},{9,30,65},{29,27,3299},{9,30,65},{19,31,5845},{19,31,5845},{19,31,5845},{18,31,3778},{17,31,5124},{15,31,2070},{15,31,2070},{13,29,129},{9,31,4725},{4,31,228},{24,31,1073},{24,31,1073},{24,31,1073},{23,31,353},{31,18,2178},{20,31,965},{20,31,965},{9,30,1},{26,26,2178},
+{9,30,1},{31,30,34},{30,31,18},{29,31,4},{28,31,1},{31,30,34},{31,30,34},{28,31,1},{0,30,64},{31,30,34},{0,30,64},{18,0,2689},{18,0,2689},{18,0,2689},{18,0,2689},{14,31,245},{14,31,245},{14,31,245},{13,27,10},{4,31,164},{4,31,164},{22,31,8707},{21,31,7170},{21,31,6209},{19,31,4133},{21,31,8853},{18,31,4387},{17,31,2548},{14,31,170},{14,31,8388},{6,31,244},{27,31,1971},
+{26,31,1557},{25,31,1250},{24,31,565},{31,24,2904},{23,31,1826},{22,31,1145},{10,31,1},{24,31,2904},{10,31,1},{21,31,6209},{21,31,6209},{21,31,6209},{19,31,4133},{19,31,5460},{17,31,2548},{17,31,2548},{14,30,129},{11,31,5085},{6,31,244},{25,31,1250},{25,31,1250},{25,31,1250},{24,31,565},{30,22,2178},{22,31,1145},{22,31,1145},{10,31,1},{27,27,2178},{10,31,1},{31,31,0},{31,31,0},{31,31,0},
+{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{19,0,2689},{19,0,2689},{19,0,2689},{19,0,2689},{15,31,338},{15,31,338},{15,31,338},{14,28,5},{6,31,244},{6,31,244},{23,31,7705},{22,31,6418},{21,31,5633},{20,31,3845},{22,31,7654},{19,31,3874},{18,31,2310},{15,31,53},{15,31,7258},{8,31,317},{27,31,1458},{27,31,1186},{26,31,932},{25,31,425},{31,25,2166},
+{25,31,1398},{23,31,850},{13,31,1},{28,29,2166},{13,31,1},{21,31,5633},{21,31,5633},{21,31,5633},{20,31,3845},{19,31,4830},{18,31,2310},{18,31,2310},{15,31,53},{13,31,4506},{8,31,317},{26,31,932},{26,31,932},{26,31,932},{25,31,425},{31,22,1625},{23,31,850},{23,31,850},{13,31,1},{30,26,1625},{13,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},
+{0,31,0},{31,31,0},{0,31,0},{20,0,2689},{20,0,2689},{20,0,2689},{20,0,2689},{16,31,449},{16,31,449},{16,31,449},{15,30,8},{8,31,317},{8,31,317},{24,31,6881},{23,31,5814},{22,31,5138},{21,31,3650},{23,31,6713},{20,31,3400},{19,31,2142},{16,31,5},{17,31,6397},{9,31,425},{28,31,1075},{27,31,866},{27,31,697},{26,31,320},{31,26,1601},{26,31,1041},{24,31,653},{15,31,1},{29,29,1601},
+{15,31,1},{22,31,5138},{22,31,5138},{22,31,5138},{21,31,3650},{21,31,4313},{19,31,2142},{19,31,2142},{16,31,5},{14,31,3981},{9,31,425},{27,31,697},{27,31,697},{27,31,697},{26,31,320},{31,23,1201},{24,31,653},{24,31,653},{15,31,1},{30,27,1201},{15,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{21,0,2689},
+{21,0,2689},{21,0,2689},{21,0,2689},{18,31,549},{18,31,549},{18,31,549},{16,31,5},{9,31,425},{9,31,425},{24,31,6097},{24,31,5285},{23,31,4693},{22,31,3473},{23,31,5833},{21,31,3067},{20,31,1988},{17,31,10},{18,31,5571},{11,31,541},{28,31,739},{28,31,595},{27,31,505},{27,31,233},{30,28,1121},{26,31,737},{25,31,461},{18,31,0},{28,30,1121},{18,31,0},{23,31,4693},{23,31,4693},{23,31,4693},
+{22,31,3473},{22,31,3845},{20,31,1988},{20,31,1988},{17,31,10},{15,31,3542},{11,31,541},{27,31,505},{27,31,505},{27,31,505},{27,31,233},{30,26,841},{25,31,461},{25,31,461},{18,31,0},{31,27,841},{18,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{22,0,2689},{22,0,2689},{22,0,2689},{22,0,2689},{19,31,666},
+{19,31,666},{19,31,666},{17,31,10},{11,31,541},{11,31,541},{25,31,5427},{24,31,4757},{24,31,4273},{23,31,3314},{24,31,5002},{22,31,2788},{21,31,1898},{18,31,65},{20,31,4714},{13,31,698},{29,31,489},{28,31,387},{28,31,306},{28,31,162},{30,29,726},{27,31,482},{26,31,305},{20,31,1},{29,30,726},{20,31,1},{24,31,4273},{24,31,4273},{24,31,4273},{23,31,3314},{22,31,3429},{21,31,1898},{21,31,1898},
+{18,31,65},{17,31,3213},{13,31,698},{28,31,306},{28,31,306},{28,31,306},{28,31,162},{31,26,545},{26,31,305},{26,31,305},{20,31,1},{29,29,545},{20,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{23,0,2689},{23,0,2689},{23,0,2689},{23,0,2689},{20,31,832},{20,31,832},{20,31,832},{18,31,65},{13,31,698},
+{13,31,698},{4,31,33740},{0,31,5184},{0,22,420},{0,21,4221},{3,31,45594},{0,29,24105},{0,21,8317},{0,18,24790},{0,21,63990},{0,16,38959},{2,31,9704},{0,30,2866},{0,21,389},{0,19,3229},{14,2,18065},{0,20,13257},{0,17,6153},{0,12,13481},{25,0,18065},{0,12,13481},{0,15,1},{0,15,1},{0,15,1},{0,9,1},{0,8,1105},{0,7,585},{0,7,585},{0,4,596},{0,4,1273},{0,4,740},{0,15,1},
+{0,15,1},{0,15,1},{0,9,1},{4,1,1105},{0,7,585},{0,7,585},{0,4,596},{8,0,1105},{0,4,596},{20,4,9248},{0,30,2866},{0,21,389},{0,19,3229},{20,4,9248},{29,5,9248},{0,19,3229},{0,14,9248},{29,5,9248},{0,14,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,31,38380},{1,31,6614},{0,23,245},
+{0,22,3864},{4,31,50747},{0,31,24961},{0,22,8353},{0,19,25735},{0,22,65535},{0,17,41319},{2,31,10152},{0,31,2624},{0,23,229},{0,20,2980},{16,0,19334},{0,20,13769},{0,18,6243},{0,13,14116},{25,1,19334},{0,13,14116},{0,18,0},{0,18,0},{0,18,0},{0,11,1},{0,9,1513},{0,8,772},{0,8,772},{0,5,821},{0,5,1750},{0,4,1028},{0,18,0},{0,18,0},{0,18,0},{0,11,1},{5,1,1513},
+{0,8,772},{0,8,772},{0,5,821},{9,0,1513},{0,5,821},{24,0,9248},{0,31,2624},{0,23,229},{0,20,2980},{24,0,9248},{30,6,9248},{0,20,2980},{0,15,9248},{30,6,9248},{0,15,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,31,43788},{1,31,8598},{0,24,126},{0,23,3525},{4,31,56155},{0,31,26241},{0,23,8425},
+{0,20,26793},{0,23,65535},{0,18,43819},{3,31,10706},{0,31,2624},{0,24,122},{0,21,2701},{17,0,20689},{0,22,14385},{0,19,6369},{0,13,14756},{25,2,20689},{0,13,14756},{0,21,1},{0,21,1},{0,21,1},{0,12,4},{0,10,1989},{0,9,1018},{0,9,1018},{0,6,1096},{0,5,2294},{0,5,1334},{0,21,1},{0,21,1},{0,21,1},{0,12,4},{5,2,1985},{0,9,1018},{0,9,1018},{0,6,1096},{9,1,1985},
+{0,6,1096},{25,1,9248},{0,31,2624},{0,24,122},{0,21,2701},{25,1,9248},{31,7,9248},{0,21,2701},{0,16,9250},{31,7,9248},{0,16,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,31,49566},{1,31,11350},{0,25,41},{0,24,3109},{4,31,62331},{0,31,28289},{0,24,8585},{0,21,27848},{0,23,65535},{0,19,46459},{4,31,11395},
+{0,31,2880},{0,25,37},{0,22,2440},{17,2,22129},{0,23,15030},{0,20,6509},{0,14,15441},{27,2,22129},{0,14,15441},{0,23,1},{0,23,1},{0,23,1},{0,14,0},{0,12,2525},{0,10,1300},{0,10,1300},{0,6,1384},{0,6,2905},{0,6,1708},{0,23,1},{0,23,1},{0,23,1},{0,14,0},{7,0,2521},{0,10,1300},{0,10,1300},{0,6,1384},{10,1,2521},{0,6,1384},{26,2,9248},{1,31,2866},{0,25,37},
+{0,22,2440},{26,2,9248},{27,11,9248},{0,22,2440},{0,17,9250},{27,11,9248},{0,17,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,31,56892},{2,31,15166},{0,26,20},{0,25,2804},{5,31,65535},{0,31,31511},{0,25,8733},{0,22,29095},{0,26,65535},{0,20,49444},{4,31,12385},{1,31,3380},{0,26,4},{0,23,2173},{17,4,23851},
+{0,23,15948},{0,21,6729},{0,15,16274},{29,2,23851},{0,15,16274},{0,26,0},{0,26,0},{0,26,0},{0,16,4},{0,13,3200},{0,11,1665},{0,11,1665},{0,7,1754},{0,7,3691},{0,6,2185},{0,26,0},{0,26,0},{0,26,0},{0,16,4},{2,10,3200},{0,11,1665},{0,11,1665},{0,7,1754},{13,0,3200},{0,7,1754},{24,8,9248},{3,31,3204},{0,26,4},{0,23,2173},{24,8,9248},{30,11,9248},{0,23,2173},
+{0,18,9248},{30,11,9248},{0,18,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,31,63870},{2,31,19230},{0,27,45},{0,27,2520},{5,31,65535},{1,31,35016},{0,26,8925},{0,23,30250},{0,28,65535},{0,21,52374},{5,31,13379},{2,31,4026},{0,27,29},{0,24,1901},{18,4,25472},{0,26,16706},{0,22,6963},{0,16,17124},{29,3,25472},
+{0,16,17124},{0,29,1},{0,29,1},{0,29,1},{0,17,1},{0,14,3874},{0,13,2084},{0,13,2084},{0,8,2165},{0,8,4466},{0,7,2627},{0,29,1},{0,29,1},{0,29,1},{0,17,1},{8,1,3872},{0,13,2084},{0,13,2084},{0,8,2165},{6,5,3872},{0,8,2165},{28,4,9248},{5,31,3589},{1,27,4},{0,24,1901},{28,4,9248},{29,13,9248},{0,24,1901},{0,19,9248},{29,13,9248},{0,19,9248},{0,0,0},
+{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,31,65535},{2,31,24002},{0,28,109},{0,27,2268},{6,31,65535},{1,31,38780},{0,27,8825},{0,24,30825},{0,28,65535},{0,22,54996},{6,31,14345},{2,31,4766},{1,28,62},{0,26,1697},{18,6,26744},{0,28,17104},{0,23,6957},{0,17,17625},{31,3,26744},{0,17,17625},{0,31,5},{0,31,5},{0,31,5},
+{0,19,5},{0,16,4418},{0,14,2306},{0,14,2306},{0,9,2420},{0,8,5122},{0,8,2997},{0,31,5},{0,31,5},{0,31,5},{0,19,5},{9,1,4418},{0,14,2306},{0,14,2306},{0,9,2420},{16,0,4418},{0,9,2420},{29,5,9248},{8,31,3904},{2,28,1},{0,26,1693},{29,5,9248},{30,14,9248},{0,26,1693},{0,20,9250},{30,14,9248},{0,20,9250},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,1},
+{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{7,31,65535},{3,31,29032},{0,29,330},{0,28,2105},{6,31,65535},{2,31,42151},{0,28,7781},{0,25,30108},{0,29,65535},{0,22,56388},{7,31,14819},{3,31,5416},{2,29,62},{0,27,1580},{23,0,26744},{0,29,16547},{0,24,6221},{0,18,17124},{30,5,26744},{0,18,17124},{1,31,84},{1,31,84},{1,31,84},{1,20,72},{0,19,4420},{0,16,2005},{0,16,2005},
+{0,10,2165},{0,9,5389},{0,9,2925},{1,31,20},{1,31,20},{1,31,20},{1,20,8},{10,2,4418},{0,16,2005},{0,16,2005},{0,10,2165},{17,1,4418},{0,10,2165},{30,6,9248},{8,31,4160},{3,29,1},{0,27,1480},{30,6,9248},{31,15,9248},{0,27,1480},{0,21,9250},{31,15,9248},{0,21,9250},{1,0,68},{1,0,68},{1,0,68},{1,0,68},{0,3,1},{0,3,1},{0,3,1},{0,2,0},{0,1,34},
+{0,1,34},{7,31,65535},{3,31,35719},{1,30,717},{0,30,2062},{7,31,65535},{2,31,46660},{0,29,6696},{0,26,29322},{0,31,65535},{0,23,58077},{9,31,15473},{5,31,6173},{3,30,65},{1,28,1601},{23,3,26744},{0,31,15992},{0,26,5346},{0,19,16582},{28,8,26744},{0,19,16582},{2,31,329},{2,31,329},{2,31,329},{1,21,189},{0,22,4420},{0,18,1737},{0,18,1737},{0,11,1898},{0,11,5707},{0,10,2885},{3,31,34},
+{3,31,34},{3,31,34},{2,21,10},{13,0,4418},{0,18,1737},{0,18,1737},{0,11,1898},{20,1,4418},{0,11,1898},{28,12,9248},{10,31,4570},{4,30,4},{0,28,1285},{28,12,9248},{22,22,9248},{0,28,1285},{0,22,9248},{22,22,9248},{0,22,9248},{1,0,185},{1,0,185},{1,0,185},{1,0,185},{0,6,1},{0,6,1},{0,6,1},{0,4,1},{0,3,97},{0,3,97},{7,31,65535},{4,31,40786},{1,31,1122},
+{0,30,2138},{7,31,65535},{2,31,49800},{0,30,5634},{0,27,27967},{0,31,65535},{0,24,58770},{10,31,15531},{6,31,6593},{4,31,61},{2,29,1533},{25,2,26259},{0,31,15284},{0,27,4514},{0,20,15812},{27,10,26259},{0,20,15812},{2,31,633},{2,31,633},{2,31,633},{2,22,381},{0,24,4418},{0,20,1480},{0,20,1480},{0,12,1640},{0,12,6125},{0,11,2891},{4,31,61},{4,31,61},{4,31,61},{3,22,10},{14,1,4418},
+{0,20,1480},{0,20,1480},{0,12,1640},{24,0,4418},{0,12,1640},{30,11,8978},{11,31,4744},{5,31,0},{0,29,1040},{30,11,8978},{31,18,8978},{0,29,1040},{0,23,8980},{31,18,8978},{0,23,8980},{2,0,377},{2,0,377},{2,0,377},{2,0,377},{0,9,0},{0,9,0},{0,9,0},{0,5,4},{0,4,193},{0,4,193},{8,31,65535},{4,31,40898},{1,31,1890},{0,31,2125},{7,31,65535},{3,31,47871},{0,30,4194},
+{0,27,24703},{0,31,65535},{0,24,56130},{11,31,14325},{8,31,6051},{5,31,100},{3,29,1218},{22,9,24371},{0,31,13716},{0,28,3402},{0,21,13989},{29,10,24371},{0,21,13989},{3,31,1058},{3,31,1058},{3,31,1058},{2,24,617},{0,27,4420},{0,22,1280},{0,22,1280},{0,13,1445},{0,14,6509},{0,12,2945},{5,31,100},{5,31,100},{5,31,100},{4,23,5},{16,0,4418},{0,22,1280},{0,22,1280},{0,13,1445},{25,1,4418},
+{0,13,1445},{29,14,7938},{13,31,4225},{7,31,4},{0,29,656},{29,14,7938},{29,20,7938},{0,29,656},{0,23,7956},{29,20,7938},{0,23,7956},{2,0,617},{2,0,617},{2,0,617},{2,0,617},{0,11,4},{0,11,4},{0,11,4},{0,7,0},{0,5,325},{0,5,325},{8,31,65535},{4,31,41266},{1,31,2914},{1,31,2170},{7,31,65535},{3,31,46175},{0,30,3010},{0,27,21695},{0,31,65535},{0,25,53636},{12,31,13140},
+{8,31,5571},{6,31,157},{4,29,932},{24,7,22568},{0,31,12404},{0,28,2474},{0,21,12245},{29,11,22568},{0,21,12245},{4,31,1630},{4,31,1630},{4,31,1630},{3,25,937},{0,29,4420},{0,23,1090},{0,23,1090},{0,14,1268},{0,15,6926},{0,13,3029},{6,31,157},{6,31,157},{6,31,157},{5,24,8},{17,1,4418},{0,23,1090},{0,23,1090},{0,14,1268},{26,2,4418},{0,14,1268},{31,12,6962},{14,31,3709},{8,31,1},
+{0,30,353},{31,12,6962},{27,22,6962},{0,30,353},{0,24,6970},{27,22,6962},{0,24,6970},{3,0,937},{3,0,937},{3,0,937},{3,0,937},{0,14,0},{0,14,0},{0,14,0},{0,8,4},{0,6,493},{0,6,493},{9,31,65535},{5,31,41956},{2,31,4257},{1,31,2512},{7,31,65535},{3,31,44573},{0,30,1984},{0,28,18569},{0,31,65535},{0,25,51026},{13,31,11930},{10,31,5125},{7,31,250},{5,29,701},{27,4,20642},
+{1,31,11209},{0,29,1634},{0,22,10422},{31,11,20642},{0,22,10422},{4,31,2350},{4,31,2350},{4,31,2350},{3,27,1361},{0,31,4450},{0,25,949},{0,25,949},{0,16,1096},{0,16,7397},{0,14,3171},{7,31,250},{7,31,250},{7,31,250},{6,25,10},{17,4,4418},{0,25,949},{0,25,949},{0,16,1096},{29,2,4418},{0,16,1096},{30,15,5941},{15,31,3176},{10,31,0},{0,30,128},{30,15,5941},{30,21,5941},{0,30,128},
+{0,24,5953},{30,21,5941},{0,24,5953},{3,0,1360},{3,0,1360},{3,0,1360},{3,0,1360},{0,17,0},{0,17,0},{0,17,0},{0,10,1},{0,8,697},{0,8,697},{9,31,65535},{5,31,42660},{2,31,5617},{1,31,3088},{8,31,65535},{3,31,43421},{0,31,1250},{0,28,15865},{0,31,65535},{0,25,48978},{13,31,10922},{11,31,4753},{8,31,360},{6,30,509},{28,4,19021},{2,31,10246},{0,30,1088},{0,23,8945},{29,13,19021},
+{0,23,8945},{5,31,3131},{5,31,3131},{5,31,3131},{4,28,1822},{1,31,4580},{0,28,776},{0,28,776},{0,17,925},{0,18,7893},{0,15,3333},{8,31,360},{8,31,360},{8,31,360},{7,26,10},{18,5,4418},{0,28,776},{0,28,776},{0,17,925},{30,3,4418},{0,17,925},{31,15,5101},{17,31,2777},{11,31,9},{0,31,25},{31,15,5101},{30,22,5101},{0,31,25},{0,25,5105},{30,22,5101},{0,25,5105},{4,0,1818},
+{4,0,1818},{4,0,1818},{4,0,1818},{0,20,1},{0,20,1},{0,20,1},{0,12,1},{0,9,925},{0,9,925},{9,31,65535},{5,31,43620},{2,31,7233},{1,31,3920},{8,31,65535},{3,31,42525},{0,31,738},{0,28,13417},{0,31,65535},{0,25,47186},{14,31,9978},{11,31,4449},{10,31,452},{7,30,354},{31,1,17485},{3,31,9369},{0,30,704},{0,24,7570},{31,13,17485},{0,24,7570},{6,31,4058},{6,31,4058},{6,31,4058},
+{4,29,2315},{2,31,4874},{0,29,610},{0,29,610},{0,18,772},{0,20,8427},{0,16,3497},{10,31,452},{10,31,452},{10,31,452},{8,27,5},{20,4,4418},{0,29,610},{0,29,610},{0,18,772},{29,5,4418},{0,18,772},{31,16,4325},{18,31,2357},{13,31,0},{1,31,0},{31,16,4325},{31,22,4325},{1,31,0},{0,25,4337},{31,22,4325},{0,25,4337},{4,0,2314},{4,0,2314},{4,0,2314},{4,0,2314},{0,22,1},
+{0,22,1},{0,22,1},{0,13,4},{0,10,1189},{0,10,1189},{9,31,65535},{5,31,44836},{2,31,9105},{2,31,4905},{8,31,65535},{3,31,41885},{0,31,482},{0,28,11225},{0,31,65535},{0,26,45590},{15,31,9102},{13,31,4161},{11,31,557},{9,30,212},{29,6,16034},{5,31,8602},{0,31,482},{0,24,6242},{31,14,16034},{0,24,6242},{6,31,5066},{6,31,5066},{6,31,5066},{5,30,2907},{2,31,5322},{0,31,482},{0,31,482},
+{0,19,637},{0,20,8939},{0,17,3725},{11,31,557},{11,31,557},{11,31,557},{9,28,8},{24,0,4418},{0,31,482},{0,31,482},{0,19,637},{30,6,4418},{0,19,637},{30,19,3613},{20,31,1940},{15,31,4},{4,31,1},{30,19,3613},{31,23,3613},{4,31,1},{0,26,3617},{31,23,3613},{0,26,3617},{5,0,2906},{5,0,2906},{5,0,2906},{5,0,2906},{0,25,1},{0,25,1},{0,25,1},{0,15,0},{0,11,1489},
+{0,11,1489},{9,31,65535},{5,31,46510},{3,31,11362},{2,31,6237},{9,31,65535},{3,31,41471},{0,31,500},{0,29,8976},{0,31,65535},{0,26,43934},{16,31,8139},{14,31,3853},{12,31,680},{10,30,109},{26,13,14504},{8,31,7667},{0,31,500},{0,25,4979},{21,21,14504},{0,25,4979},{7,31,6337},{7,31,6337},{7,31,6337},{5,31,3642},{3,31,5962},{0,31,500},{0,31,500},{0,20,520},{0,22,9629},{0,18,4035},{12,31,680},
+{12,31,680},{12,31,680},{10,29,10},{24,3,4418},{0,31,500},{0,31,500},{0,20,520},{28,9,4418},{0,20,520},{31,19,2888},{20,31,1517},{16,31,1},{7,31,1},{31,19,2888},{27,26,2888},{7,31,1},{0,26,2906},{27,26,2888},{0,26,2906},{5,0,3617},{5,0,3617},{5,0,3617},{5,0,3617},{0,28,1},{0,28,1},{0,28,1},{0,17,4},{0,11,1930},{0,11,1930},{10,31,65535},{6,31,48082},{3,31,13570},
+{2,31,7693},{9,31,65535},{3,31,41375},{0,31,788},{0,29,7120},{0,31,65535},{0,26,42734},{17,31,7409},{15,31,3625},{13,31,821},{11,31,45},{28,11,13235},{8,31,6899},{2,31,628},{0,25,3987},{31,16,13235},{0,25,3987},{7,31,7681},{7,31,7681},{7,31,7681},{6,31,4437},{4,31,6659},{1,31,738},{1,31,738},{0,21,421},{0,23,10286},{0,20,4305},{13,31,821},{13,31,821},{13,31,821},{11,30,10},{22,9,4418},
+{2,31,628},{2,31,628},{0,21,421},{29,10,4418},{0,21,421},{31,20,2312},{21,31,1217},{18,31,1},{9,31,0},{31,20,2312},{30,25,2312},{9,31,0},{0,27,2314},{30,25,2312},{0,27,2314},{6,0,4337},{6,0,4337},{6,0,4337},{6,0,4337},{0,30,1},{0,30,1},{0,30,1},{0,18,1},{0,13,2329},{0,13,2329},{10,31,65535},{6,31,49890},{3,31,16034},{2,31,9405},{9,31,65535},{4,31,41526},{0,31,1332},
+{0,29,5520},{0,31,65535},{0,26,41790},{18,31,6747},{16,31,3459},{14,31,980},{12,31,5},{31,8,12051},{10,31,6275},{4,31,801},{0,26,3066},{28,19,12051},{0,26,3066},{8,31,9062},{8,31,9062},{8,31,9062},{7,31,5410},{4,31,7555},{1,31,1154},{1,31,1154},{0,23,325},{0,23,11118},{0,20,4625},{14,31,980},{14,31,980},{14,31,980},{12,31,5},{24,8,4418},{4,31,801},{4,31,801},{0,23,325},{30,11,4418},
+{0,23,325},{30,23,1800},{23,31,949},{19,31,4},{12,31,1},{30,23,1800},{28,27,1800},{12,31,1},{0,27,1818},{28,27,1800},{0,27,1818},{6,0,5105},{6,0,5105},{6,0,5105},{6,0,5105},{0,31,36},{0,31,36},{0,31,36},{0,20,4},{0,15,2741},{0,15,2741},{10,31,65535},{6,31,51954},{3,31,18754},{3,31,11330},{9,31,65535},{4,31,41798},{1,31,2082},{0,29,4176},{0,31,65535},{0,27,41092},{19,31,6153},
+{17,31,3297},{16,31,1154},{13,31,20},{29,13,10952},{11,31,5708},{6,31,965},{0,27,2291},{28,20,10952},{0,27,2291},{9,31,10545},{9,31,10545},{9,31,10545},{7,31,6482},{5,31,8549},{2,31,1716},{2,31,1716},{0,24,221},{0,26,11876},{0,22,4989},{16,31,1154},{16,31,1154},{16,31,1154},{13,31,20},{28,4,4418},{6,31,965},{6,31,965},{0,24,221},{29,13,4418},{0,24,221},{29,26,1352},{23,31,725},{21,31,0},
+{14,31,1},{29,26,1352},{31,26,1352},{14,31,1},{0,28,1360},{31,26,1352},{0,28,1360},{7,0,5953},{7,0,5953},{7,0,5953},{7,0,5953},{1,31,145},{1,31,145},{1,31,145},{0,21,1},{0,16,3130},{0,16,3130},{10,31,65535},{6,31,54582},{4,31,21886},{3,31,13652},{9,31,65535},{4,31,42410},{1,31,3144},{0,30,2841},{0,31,65535},{0,27,40390},{19,31,5649},{18,31,3157},{17,31,1325},{15,31,74},{29,15,9818},
+{13,31,5241},{8,31,1108},{0,27,1589},{30,20,9818},{0,27,1589},{10,31,12376},{10,31,12376},{10,31,12376},{8,31,7844},{6,31,9861},{3,31,2576},{3,31,2576},{0,25,136},{0,28,12696},{0,23,5429},{17,31,1325},{17,31,1325},{17,31,1325},{15,31,74},{31,2,4418},{8,31,1108},{8,31,1108},{0,25,136},{27,16,4418},{0,25,136},{31,24,925},{25,31,505},{23,31,1},{17,31,1},{31,24,925},{31,27,925},{17,31,1},
+{0,28,937},{31,27,925},{0,28,937},{7,0,6970},{7,0,6970},{7,0,6970},{7,0,6970},{1,31,388},{1,31,388},{1,31,388},{0,23,0},{0,17,3665},{0,17,3665},{10,31,65535},{7,31,57052},{4,31,24910},{3,31,15988},{9,31,65535},{4,31,43226},{1,31,4360},{0,30,1833},{0,31,65535},{0,27,40038},{21,31,5202},{19,31,3073},{18,31,1508},{16,31,180},{30,15,8901},{14,31,4814},{10,31,1300},{0,28,1021},{30,21,8901},
+{0,28,1021},{10,31,14136},{10,31,14136},{10,31,14136},{8,31,9252},{7,31,11195},{3,31,3536},{3,31,3536},{0,26,85},{0,29,13491},{0,23,5925},{18,31,1508},{18,31,1508},{18,31,1508},{16,31,180},{26,13,4418},{10,31,1300},{10,31,1300},{0,26,85},{21,21,4418},{0,26,85},{30,27,613},{26,31,337},{24,31,1},{20,31,1},{30,27,613},{30,28,613},{20,31,1},{0,29,617},{30,28,613},{0,29,617},{8,0,7956},
+{8,0,7956},{8,0,7956},{8,0,7956},{2,31,697},{2,31,697},{2,31,697},{0,25,4},{0,18,4181},{0,18,4181},{11,31,65535},{7,31,59708},{4,31,28190},{3,31,18580},{10,31,65535},{5,31,44295},{1,31,5832},{0,30,1081},{0,31,65535},{0,27,39942},{22,31,4818},{20,31,3017},{19,31,1709},{17,31,325},{30,17,8069},{15,31,4473},{11,31,1514},{0,29,602},{25,25,8069},{0,29,602},{11,31,15965},{11,31,15965},{11,31,15965},
+{9,31,10757},{7,31,12667},{4,31,4662},{4,31,4662},{0,27,52},{0,30,14340},{0,25,6449},{19,31,1709},{19,31,1709},{19,31,1709},{17,31,325},{28,12,4418},{11,31,1514},{11,31,1514},{0,27,52},{22,22,4418},{0,27,52},{31,27,365},{27,31,205},{26,31,1},{22,31,1},{31,27,365},{30,29,365},{22,31,1},{0,29,377},{30,29,365},{0,29,377},{8,0,8980},{8,0,8980},{8,0,8980},{8,0,8980},{2,31,1097},
+{2,31,1097},{2,31,1097},{0,26,1},{0,20,4682},{0,20,4682},{11,31,65535},{8,31,58981},{5,31,29551},{4,31,19751},{10,31,65535},{5,31,43215},{2,31,6910},{1,30,686},{0,31,65535},{0,28,34909},{23,31,4502},{21,31,3011},{20,31,1973},{18,31,520},{31,17,7322},{17,31,4242},{13,31,1769},{0,29,314},{25,26,7322},{0,29,314},{12,31,16739},{12,31,16739},{12,31,16739},{10,31,11492},{8,31,13636},{5,31,5510},{5,31,5510},
+{1,28,54},{0,31,14139},{0,26,6041},{20,31,1973},{20,31,1973},{20,31,1973},{18,31,520},{29,13,4418},{13,31,1769},{13,31,1769},{0,28,29},{28,20,4418},{0,28,29},{31,28,181},{28,31,97},{27,31,4},{25,31,0},{31,28,181},{31,29,181},{25,31,0},{0,30,185},{31,29,181},{0,30,185},{9,0,9248},{9,0,9248},{9,0,9248},{9,0,9248},{3,31,1348},{3,31,1348},{3,31,1348},{1,27,5},{0,21,4520},
+{0,21,4520},{12,31,65535},{9,31,57270},{6,31,30345},{5,31,20521},{11,31,65535},{6,31,41449},{3,31,8015},{2,31,301},{0,31,65535},{0,28,28330},{24,31,4181},{22,31,3053},{21,31,2248},{20,31,772},{31,19,6584},{20,31,3941},{15,31,2041},{0,30,77},{27,26,6584},{0,30,77},{13,31,17289},{13,31,17289},{13,31,17289},{11,31,12050},{10,31,14315},{7,31,6389},{7,31,6389},{2,29,53},{0,31,13860},{0,28,5286},{21,31,2248},
+{21,31,2248},{21,31,2248},{20,31,772},{29,16,4418},{15,31,2041},{15,31,2041},{0,30,13},{31,20,4418},{0,30,13},{30,31,50},{30,31,34},{29,31,0},{28,31,1},{30,31,50},{31,30,50},{28,31,1},{0,30,68},{31,30,50},{0,30,68},{10,0,9250},{10,0,9250},{10,0,9250},{10,0,9250},{4,31,1549},{4,31,1549},{4,31,1549},{2,28,2},{0,23,4114},{0,23,4114},{13,31,65535},{9,31,55894},{7,31,31068},
+{6,31,21256},{12,31,65535},{8,31,39740},{4,31,9073},{3,31,90},{0,31,65535},{0,29,23356},{24,31,3973},{23,31,3125},{23,31,2500},{21,31,1037},{30,22,6019},{20,31,3701},{17,31,2340},{0,31,4},{27,27,6019},{0,31,4},{14,31,17796},{14,31,17796},{14,31,17796},{12,31,12625},{11,31,14957},{8,31,7139},{8,31,7139},{3,30,53},{0,31,14020},{0,29,4652},{23,31,2500},{23,31,2500},{23,31,2500},{21,31,1037},{30,17,4418},
+{17,31,2340},{17,31,2340},{0,31,4},{25,25,4418},{0,31,4},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{31,31,4},{30,31,1},{0,31,4},{31,31,4},{0,31,4},{11,0,9250},{11,0,9250},{11,0,9250},{11,0,9250},{6,31,1765},{6,31,1765},{6,31,1765},{3,29,2},{0,25,3877},{0,25,3877},{13,31,65535},{10,31,53236},{8,31,30487},{7,31,21105},{13,31,65535},{8,31,37332},{5,31,9177},
+{4,31,36},{1,31,65535},{0,29,18680},{25,31,3443},{24,31,2741},{23,31,2248},{22,31,980},{29,25,5163},{21,31,3218},{20,31,2117},{3,31,1},{30,26,5163},{3,31,1},{15,31,17289},{15,31,17289},{15,31,17289},{13,31,12512},{12,31,14328},{9,31,7149},{9,31,7149},{4,31,20},{0,31,13376},{0,29,3944},{23,31,2248},{23,31,2248},{23,31,2248},{22,31,980},{31,17,3872},{20,31,2117},{20,31,2117},{3,31,1},{25,26,3872},
+{3,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{12,0,9248},{12,0,9248},{12,0,9248},{12,0,9248},{7,31,1972},{7,31,1972},{7,31,1972},{4,30,5},{0,27,3545},{0,27,3545},{14,31,65535},{11,31,50266},{9,31,29322},{8,31,20567},{13,31,65535},{9,31,35025},{6,31,8985},{5,31,21},{2,31,65535},{0,29,14712},{26,31,2873},
+{25,31,2283},{24,31,1825},{22,31,820},{30,24,4267},{22,31,2657},{20,31,1685},{5,31,1},{29,27,4267},{5,31,1},{16,31,16427},{16,31,16427},{16,31,16427},{14,31,12185},{13,31,13442},{10,31,6915},{10,31,6915},{5,31,5},{1,31,12539},{0,30,3314},{24,31,1825},{24,31,1825},{24,31,1825},{22,31,820},{28,23,3200},{20,31,1685},{20,31,1685},{5,31,1},{28,25,3200},{5,31,1},{31,31,0},{31,31,0},{31,31,0},
+{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{13,0,9248},{13,0,9248},{13,0,9248},{13,0,9248},{8,31,2250},{8,31,2250},{8,31,2250},{5,31,5},{0,28,3170},{0,28,3170},{15,31,65535},{12,31,47239},{10,31,28065},{9,31,20104},{14,31,65535},{10,31,32574},{7,31,8839},{6,31,54},{3,31,64890},{0,30,10964},{26,31,2252},{25,31,1806},{25,31,1445},{23,31,650},{30,25,3361},
+{23,31,2091},{21,31,1322},{8,31,0},{30,27,3361},{8,31,0},{17,31,15584},{17,31,15584},{17,31,15584},{15,31,11846},{14,31,12522},{11,31,6697},{11,31,6697},{6,31,50},{3,31,11669},{0,31,2834},{25,31,1445},{25,31,1445},{25,31,1445},{23,31,650},{30,21,2521},{21,31,1322},{21,31,1322},{8,31,0},{31,24,2521},{8,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},
+{0,31,0},{31,31,0},{0,31,0},{14,0,9250},{14,0,9250},{14,0,9250},{14,0,9250},{9,31,2525},{9,31,2525},{9,31,2525},{6,31,50},{0,31,2834},{0,31,2834},{16,31,65535},{13,31,44559},{11,31,27000},{10,31,19705},{15,31,64179},{11,31,30525},{8,31,8677},{7,31,149},{3,31,60570},{0,30,8308},{27,31,1782},{26,31,1416},{25,31,1157},{24,31,520},{30,26,2646},{23,31,1691},{22,31,1040},{11,31,1},{31,27,2646},
+{11,31,1},{18,31,14889},{18,31,14889},{18,31,14889},{16,31,11585},{15,31,11778},{12,31,6555},{12,31,6555},{7,31,145},{3,31,11061},{0,31,2610},{25,31,1157},{25,31,1157},{25,31,1157},{24,31,520},{31,21,1985},{22,31,1040},{22,31,1040},{11,31,1},{31,25,1985},{11,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{15,0,9250},
+{15,0,9250},{15,0,9250},{15,0,9250},{10,31,2792},{10,31,2792},{10,31,2792},{7,31,145},{0,31,2610},{0,31,2610},{16,31,63318},{14,31,42019},{12,31,25930},{11,31,19324},{16,31,59178},{11,31,28845},{9,31,8605},{8,31,276},{6,31,56253},{0,30,6420},{27,31,1366},{27,31,1094},{26,31,872},{25,31,397},{30,27,2017},{25,31,1298},{23,31,794},{13,31,1},{30,28,2017},{13,31,1},{19,31,14244},{19,31,14244},{19,31,14244},
+{17,31,11312},{16,31,11037},{13,31,6429},{13,31,6429},{8,31,260},{6,31,10457},{0,31,2642},{26,31,872},{26,31,872},{26,31,872},{25,31,397},{31,22,1513},{23,31,794},{23,31,794},{13,31,1},{29,27,1513},{13,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{16,0,9248},{16,0,9248},{16,0,9248},{16,0,9248},{12,31,3074},
+{12,31,3074},{12,31,3074},{8,31,260},{0,31,2642},{0,31,2642},{17,31,58848},{15,31,39619},{13,31,24975},{12,31,19007},{16,31,54474},{13,31,27057},{10,31,8569},{9,31,461},{8,31,51302},{0,31,5046},{28,31,979},{27,31,806},{27,31,637},{26,31,292},{31,26,1473},{26,31,953},{24,31,605},{16,31,0},{29,29,1473},{16,31,0},{19,31,13604},{19,31,13604},{19,31,13604},{18,31,11057},{16,31,10429},{14,31,6339},{14,31,6339},
+{10,31,424},{8,31,9713},{1,31,2900},{27,31,637},{27,31,637},{27,31,637},{26,31,292},{30,25,1105},{24,31,605},{24,31,605},{16,31,0},{30,27,1105},{16,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{17,0,9248},{17,0,9248},{17,0,9248},{17,0,9248},{12,31,3330},{12,31,3330},{12,31,3330},{10,31,424},{1,31,2900},
+{1,31,2900}, \ No newline at end of file
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_atc_56.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_atc_56.inc
new file mode 100644
index 0000000000..f57a232a85
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_atc_56.inc
@@ -0,0 +1,481 @@
+{0,3,20},{0,3,5},{0,2,1},{0,2,9},{0,2,35},{0,2,27},{0,1,17},{0,1,24},{0,1,41},{0,1,25},{0,3,20},{0,3,5},{0,2,1},{0,2,9},{0,2,35},{0,2,27},{0,1,17},{0,1,24},{1,0,35},{0,1,24},{0,1,1},{0,1,1},{0,1,1},{0,1,0},{0,1,2},{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,1,1},
+{0,1,1},{0,1,1},{0,1,0},{0,1,2},{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{1,0,18},{0,3,5},{0,2,1},{0,2,9},{1,0,18},{1,1,18},{0,2,9},{0,1,20},{1,1,18},{0,1,20},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,9,54},{0,7,37},{0,4,52},
+{0,4,36},{0,7,52},{0,5,21},{0,4,0},{0,3,21},{0,4,88},{0,3,37},{1,5,24},{1,5,9},{1,4,5},{1,4,13},{2,1,51},{0,5,21},{0,4,0},{0,3,21},{3,1,51},{0,3,21},{0,7,36},{0,7,36},{0,7,36},{0,4,36},{0,5,10},{0,4,0},{0,4,0},{0,2,5},{0,3,26},{0,2,14},{1,3,5},{1,3,5},{1,3,5},{1,3,4},{1,2,8},
+{0,4,0},{0,4,0},{0,2,5},{2,1,8},{0,2,5},{2,2,18},{0,7,1},{1,4,1},{0,4,0},{2,2,18},{2,3,18},{0,4,0},{0,3,20},{2,3,18},{0,3,20},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,4,0},{0,4,0},{0,4,0},{0,2,1},{0,2,10},{0,2,10},{1,11,54},{1,9,37},{1,6,52},{1,6,36},{1,9,52},{1,7,21},{1,6,0},
+{1,5,21},{0,7,63},{0,5,25},{2,7,24},{2,7,9},{2,6,5},{2,6,13},{3,3,51},{1,7,21},{1,6,0},{1,5,21},{4,3,51},{1,5,21},{1,9,36},{1,9,36},{1,9,36},{1,6,36},{1,7,10},{1,6,0},{1,6,0},{1,4,5},{0,6,11},{0,5,9},{2,5,5},{2,5,5},{2,5,5},{2,5,4},{3,1,8},{1,6,0},{1,6,0},{1,4,5},{3,3,8},
+{1,4,5},{3,4,18},{1,9,1},{2,6,1},{1,6,0},{3,4,18},{7,0,18},{1,6,0},{0,5,20},{7,0,18},{0,5,20},{1,0,36},{1,0,36},{1,0,36},{1,0,36},{1,6,0},{1,6,0},{1,6,0},{1,4,1},{0,6,2},{0,6,2},{2,13,54},{2,11,37},{2,8,52},{2,8,36},{2,11,52},{2,9,21},{2,8,0},{2,7,21},{0,11,51},{1,7,25},{3,9,24},
+{3,9,9},{3,8,5},{3,8,13},{5,1,51},{2,9,21},{2,8,0},{2,7,21},{9,0,51},{2,7,21},{2,11,36},{2,11,36},{2,11,36},{2,8,36},{2,9,10},{2,8,0},{2,8,0},{2,6,5},{1,8,11},{1,7,9},{3,7,5},{3,7,5},{3,7,5},{3,7,4},{3,6,8},{2,8,0},{2,8,0},{2,6,5},{8,0,8},{2,6,5},{4,6,18},{2,11,1},{3,8,1},
+{2,8,0},{4,6,18},{8,2,18},{2,8,0},{0,7,20},{8,2,18},{0,7,20},{2,0,36},{2,0,36},{2,0,36},{2,0,36},{2,8,0},{2,8,0},{2,8,0},{2,6,1},{1,8,2},{1,8,2},{3,15,70},{3,13,51},{4,10,69},{3,10,52},{3,14,52},{3,12,25},{3,10,4},{3,9,27},{1,13,53},{2,10,26},{4,12,22},{4,11,12},{4,10,5},{4,10,9},{6,4,51},
+{2,13,22},{3,10,3},{3,9,26},{11,1,51},{3,9,26},{3,13,51},{3,13,51},{3,13,51},{3,10,51},{3,12,9},{3,11,2},{3,11,2},{3,9,2},{2,11,9},{3,9,10},{4,10,4},{4,10,4},{4,10,4},{4,9,5},{6,2,8},{3,11,1},{3,11,1},{3,9,1},{11,0,8},{3,9,1},{7,2,18},{3,13,1},{4,10,1},{3,10,2},{7,2,18},{11,2,18},{3,10,2},
+{0,9,26},{11,2,18},{0,9,26},{3,0,50},{3,0,50},{3,0,50},{3,0,50},{3,11,1},{3,11,1},{3,11,1},{3,9,1},{2,10,0},{2,10,0},{4,17,54},{4,15,36},{4,13,54},{4,12,38},{4,15,52},{4,14,24},{4,12,3},{4,11,26},{2,15,53},{3,12,26},{5,14,22},{5,13,12},{5,12,5},{5,12,9},{8,2,51},{3,15,22},{4,12,3},{4,11,26},{12,3,51},
+{4,11,26},{4,15,36},{4,15,36},{4,15,36},{4,12,37},{4,14,8},{4,12,2},{4,12,2},{4,11,1},{3,13,9},{3,11,14},{5,12,4},{5,12,4},{5,12,4},{5,11,5},{8,0,8},{4,12,2},{4,12,2},{4,11,1},{11,3,8},{4,11,1},{9,0,18},{4,15,0},{5,12,1},{4,12,2},{9,0,18},{15,0,18},{4,12,2},{0,11,26},{15,0,18},{0,11,26},{4,0,36},
+{4,0,36},{4,0,36},{4,0,36},{4,12,1},{4,12,1},{4,12,1},{4,11,0},{3,12,0},{3,12,0},{5,19,54},{5,17,37},{5,15,54},{5,14,38},{5,17,52},{5,15,27},{5,14,3},{5,13,26},{3,17,52},{4,14,26},{6,15,24},{6,15,12},{6,14,5},{6,14,9},{10,1,51},{4,17,21},{5,14,3},{5,13,26},{17,0,51},{5,13,26},{5,17,36},{5,17,36},{5,17,36},
+{5,14,37},{5,15,10},{5,14,2},{5,14,2},{5,13,1},{4,15,12},{4,13,11},{6,14,4},{6,14,4},{6,14,4},{6,13,5},{9,2,8},{5,14,2},{5,14,2},{5,13,1},{16,0,8},{5,13,1},{10,2,18},{5,17,1},{6,14,1},{5,14,2},{10,2,18},{16,2,18},{5,14,2},{0,13,26},{16,2,18},{0,13,26},{5,0,36},{5,0,36},{5,0,36},{5,0,36},{5,14,1},
+{5,14,1},{5,14,1},{5,13,0},{4,14,0},{4,14,0},{6,21,54},{6,19,37},{6,16,52},{6,16,36},{6,19,52},{6,17,21},{6,16,0},{6,15,26},{4,19,51},{5,15,36},{7,17,24},{7,17,9},{7,16,5},{7,16,13},{11,3,51},{6,17,21},{6,16,0},{6,15,26},{18,2,51},{6,15,26},{6,19,36},{6,19,36},{6,19,36},{6,16,36},{6,17,10},{6,16,0},{6,16,0},
+{6,15,1},{5,16,11},{5,15,11},{7,15,5},{7,15,5},{7,15,5},{7,15,5},{11,1,8},{6,16,0},{6,16,0},{6,15,1},{17,2,8},{6,15,1},{11,4,18},{6,19,1},{7,16,1},{6,16,0},{11,4,18},{17,4,18},{6,16,0},{0,15,26},{17,4,18},{0,15,26},{6,0,36},{6,0,36},{6,0,36},{6,0,36},{6,16,0},{6,16,0},{6,16,0},{6,15,0},{5,16,2},
+{5,16,2},{7,23,70},{7,21,51},{8,18,69},{7,18,52},{7,22,52},{7,20,25},{7,18,4},{7,17,27},{5,21,53},{6,18,26},{8,20,22},{8,19,12},{8,18,5},{8,18,9},{13,2,51},{6,21,22},{7,18,3},{7,17,26},{21,2,51},{7,17,26},{7,21,51},{7,21,51},{7,21,51},{7,18,51},{7,20,9},{7,19,2},{7,19,2},{7,17,2},{6,19,9},{7,17,10},{8,18,4},
+{8,18,4},{8,18,4},{8,17,5},{13,0,8},{7,19,1},{7,19,1},{7,17,1},{20,2,8},{7,17,1},{14,0,18},{7,21,1},{8,18,1},{7,18,2},{14,0,18},{20,4,18},{7,18,2},{0,17,26},{20,4,18},{0,17,26},{7,0,50},{7,0,50},{7,0,50},{7,0,50},{7,19,1},{7,19,1},{7,19,1},{7,17,1},{6,18,0},{6,18,0},{8,25,54},{8,23,36},{8,21,54},
+{8,20,38},{8,24,51},{8,22,24},{8,20,3},{8,19,26},{6,23,53},{7,20,26},{9,22,22},{9,21,12},{9,20,5},{9,20,9},{14,4,51},{7,23,22},{8,20,3},{8,19,26},{25,0,51},{8,19,26},{8,23,36},{8,23,36},{8,23,36},{8,20,37},{8,22,8},{8,20,2},{8,20,2},{8,19,1},{7,21,9},{7,19,14},{9,20,4},{9,20,4},{9,20,4},{9,19,5},{14,2,8},
+{8,20,2},{8,20,2},{8,19,1},{24,0,8},{8,19,1},{15,2,18},{8,23,0},{9,20,1},{8,20,2},{15,2,18},{25,1,18},{8,20,2},{0,19,26},{25,1,18},{0,19,26},{8,0,36},{8,0,36},{8,0,36},{8,0,36},{8,20,1},{8,20,1},{8,20,1},{8,19,0},{7,20,0},{7,20,0},{9,27,54},{9,25,36},{9,23,54},{9,22,38},{9,26,51},{9,24,24},{9,22,3},
+{9,21,26},{7,25,53},{8,22,26},{10,24,22},{10,23,12},{10,22,5},{10,22,9},{16,2,51},{8,25,19},{9,22,3},{9,21,26},{27,1,51},{9,21,26},{9,25,36},{9,25,36},{9,25,36},{9,22,37},{9,24,8},{9,22,2},{9,22,2},{9,21,1},{8,23,12},{8,21,11},{10,22,4},{10,22,4},{10,22,4},{10,21,5},{16,0,8},{9,22,2},{9,22,2},{9,21,1},{26,1,8},
+{9,21,1},{17,0,18},{9,25,0},{10,22,1},{9,22,2},{17,0,18},{26,3,18},{9,22,2},{0,21,26},{26,3,18},{0,21,26},{9,0,36},{9,0,36},{9,0,36},{9,0,36},{9,22,1},{9,22,1},{9,22,1},{9,21,0},{8,22,0},{8,22,0},{10,29,54},{10,27,36},{10,25,54},{10,24,38},{10,28,51},{10,26,24},{10,24,3},{10,23,26},{8,27,52},{9,24,26},{11,26,22},
+{11,25,12},{11,24,5},{11,24,9},{17,4,51},{9,27,19},{10,24,3},{10,23,26},{27,4,51},{10,23,26},{10,27,36},{10,27,36},{10,27,36},{10,24,37},{10,26,8},{10,24,2},{10,24,2},{10,23,1},{9,25,12},{9,23,11},{11,24,4},{11,24,4},{11,24,4},{11,23,5},{17,2,8},{10,24,2},{10,24,2},{10,23,1},{27,3,8},{10,23,1},{18,2,18},{10,27,0},{11,24,1},
+{10,24,2},{18,2,18},{31,0,18},{10,24,2},{0,23,26},{31,0,18},{0,23,26},{10,0,36},{10,0,36},{10,0,36},{10,0,36},{10,24,1},{10,24,1},{10,24,1},{10,23,0},{9,24,0},{9,24,0},{11,31,70},{11,29,52},{11,27,70},{11,27,54},{11,30,53},{11,28,20},{11,27,5},{11,26,25},{10,28,56},{10,26,22},{12,28,22},{12,27,9},{12,26,8},{12,26,9},{19,3,51},
+{11,28,19},{11,27,4},{10,26,21},{30,4,51},{10,26,21},{11,30,50},{11,30,50},{11,30,50},{11,27,50},{11,28,11},{11,27,1},{11,27,1},{11,25,2},{10,27,11},{11,25,10},{12,26,4},{12,26,4},{12,26,4},{12,25,5},{19,1,8},{11,27,0},{11,27,0},{11,25,1},{29,4,8},{11,25,1},{20,1,18},{11,29,2},{12,26,4},{11,27,4},{20,1,18},{29,6,18},{11,27,4},
+{0,26,20},{29,6,18},{0,26,20},{11,0,50},{11,0,50},{11,0,50},{11,0,50},{11,27,1},{11,27,1},{11,27,1},{11,25,2},{10,26,2},{10,26,2},{12,33,54},{12,31,37},{12,29,56},{12,29,41},{12,32,51},{12,30,22},{12,29,5},{12,28,24},{11,30,56},{11,28,22},{13,30,22},{13,29,9},{13,28,8},{13,28,9},{20,5,51},{12,30,22},{12,29,5},{11,28,21},{31,6,51},
+{11,28,21},{12,31,37},{12,31,37},{12,31,37},{12,29,37},{12,30,8},{12,29,1},{12,29,1},{12,27,0},{11,29,11},{12,27,9},{13,28,4},{13,28,4},{13,28,4},{13,27,5},{20,3,8},{12,29,1},{12,29,1},{12,27,0},{30,6,8},{12,27,0},{21,3,18},{12,31,1},{13,28,4},{13,28,5},{21,3,18},{30,8,18},{13,28,5},{0,28,20},{30,8,18},{0,28,20},{12,0,36},
+{12,0,36},{12,0,36},{12,0,36},{12,29,0},{12,29,0},{12,29,0},{12,27,0},{11,28,2},{11,28,2},{13,35,54},{13,33,36},{13,31,56},{13,31,41},{13,34,51},{13,32,24},{13,31,5},{13,30,24},{11,33,53},{12,30,21},{14,32,22},{14,31,9},{14,30,8},{14,30,9},{23,0,51},{12,33,19},{13,31,5},{12,30,21},{31,9,51},{12,30,21},{13,33,36},{13,33,36},{13,33,36},
+{13,31,37},{13,32,8},{13,31,1},{13,31,1},{13,29,0},{12,31,9},{13,29,9},{14,30,4},{14,30,4},{14,30,4},{14,29,5},{21,5,8},{13,31,1},{13,31,1},{13,29,0},{31,8,8},{13,29,0},{22,5,18},{13,33,0},{14,30,4},{14,30,5},{22,5,18},{31,10,18},{14,30,5},{0,30,20},{31,10,18},{0,30,20},{13,0,36},{13,0,36},{13,0,36},{13,0,36},{13,31,0},
+{13,31,0},{13,31,0},{13,29,0},{12,30,1},{12,30,1},{14,37,54},{14,35,36},{14,33,54},{14,32,38},{14,36,51},{14,34,24},{14,32,3},{14,32,35},{12,35,52},{13,32,26},{15,34,22},{15,33,12},{15,32,5},{15,32,9},{24,2,51},{13,35,19},{14,32,3},{13,32,26},{27,17,51},{13,32,26},{14,35,36},{14,35,36},{14,35,36},{14,32,37},{14,34,8},{14,32,2},{14,32,2},
+{14,31,0},{13,33,12},{14,31,9},{15,32,4},{15,32,4},{15,32,4},{15,31,5},{24,0,8},{14,32,2},{14,32,2},{14,31,0},{31,11,8},{14,31,0},{25,0,18},{14,35,0},{15,32,1},{14,32,2},{25,0,18},{31,13,18},{14,32,2},{0,32,26},{31,13,18},{0,32,26},{14,0,36},{14,0,36},{14,0,36},{14,0,36},{14,32,1},{14,32,1},{14,32,1},{14,31,0},{13,32,0},
+{13,32,0},{15,40,68},{15,37,52},{15,35,70},{15,35,54},{15,38,53},{15,36,20},{15,35,5},{15,34,25},{14,36,56},{14,34,22},{16,36,22},{16,35,9},{16,34,8},{16,34,9},{26,1,51},{15,36,19},{15,35,4},{14,34,21},{30,17,51},{14,34,21},{15,38,50},{15,38,50},{15,38,50},{15,35,50},{15,36,11},{15,35,1},{15,35,1},{15,33,2},{14,35,11},{15,33,10},{16,34,4},
+{16,34,4},{16,34,4},{16,33,5},{24,6,8},{15,35,0},{15,35,0},{15,33,1},{29,17,8},{15,33,1},{25,6,18},{15,37,2},{16,34,4},{15,35,4},{25,6,18},{29,19,18},{15,35,4},{0,34,20},{29,19,18},{0,34,20},{15,0,50},{15,0,50},{15,0,50},{15,0,50},{15,35,1},{15,35,1},{15,35,1},{15,33,2},{14,34,2},{14,34,2},{16,41,56},{16,39,37},{16,37,56},
+{16,37,41},{16,40,51},{16,38,22},{16,37,5},{16,36,24},{15,38,56},{15,36,22},{17,38,22},{17,37,9},{17,36,8},{17,36,9},{27,3,51},{16,38,22},{16,37,5},{15,36,21},{31,19,51},{15,36,21},{16,39,37},{16,39,37},{16,39,37},{16,37,37},{16,38,8},{16,37,1},{16,37,1},{16,35,0},{15,37,11},{16,35,9},{17,36,4},{17,36,4},{17,36,4},{17,35,5},{27,1,8},
+{16,37,1},{16,37,1},{16,35,0},{30,19,8},{16,35,0},{28,1,18},{16,39,1},{17,36,4},{17,36,5},{28,1,18},{30,21,18},{17,36,5},{0,36,20},{30,21,18},{0,36,20},{16,0,36},{16,0,36},{16,0,36},{16,0,36},{16,37,0},{16,37,0},{16,37,0},{16,35,0},{15,36,2},{15,36,2},{17,43,56},{17,41,37},{17,39,56},{17,39,41},{17,42,51},{17,40,22},{17,39,5},
+{17,38,24},{15,42,56},{16,38,21},{18,40,22},{18,39,9},{18,38,8},{18,38,9},{28,5,51},{17,40,22},{17,39,5},{16,38,21},{31,22,51},{16,38,21},{17,41,37},{17,41,37},{17,41,37},{17,39,37},{17,40,8},{17,39,1},{17,39,1},{17,37,0},{16,39,9},{17,37,9},{18,38,4},{18,38,4},{18,38,4},{18,37,5},{28,3,8},{17,39,1},{17,39,1},{17,37,0},{31,21,8},
+{17,37,0},{29,3,18},{17,41,1},{18,38,4},{18,38,5},{29,3,18},{31,23,18},{18,38,5},{0,38,20},{31,23,18},{0,38,20},{17,0,36},{17,0,36},{17,0,36},{17,0,36},{17,39,0},{17,39,0},{17,39,0},{17,37,0},{16,38,1},{16,38,1},{18,45,56},{18,43,37},{18,41,56},{18,41,41},{18,44,51},{18,42,22},{18,41,5},{18,40,24},{16,43,53},{17,40,21},{19,42,22},
+{19,41,9},{19,40,8},{19,40,9},{31,0,51},{18,42,22},{18,41,5},{17,40,21},{28,29,51},{17,40,21},{18,43,37},{18,43,37},{18,43,37},{18,41,37},{18,42,8},{18,41,1},{18,41,1},{18,39,0},{17,41,9},{18,39,9},{19,40,4},{19,40,4},{19,40,4},{19,39,5},{29,5,8},{18,41,1},{18,41,1},{18,39,0},{31,24,8},{18,39,0},{30,5,18},{18,43,1},{19,40,4},
+{19,40,5},{30,5,18},{31,26,18},{19,40,5},{0,40,20},{31,26,18},{0,40,20},{18,0,36},{18,0,36},{18,0,36},{18,0,36},{18,41,0},{18,41,0},{18,41,0},{18,39,0},{17,40,1},{17,40,1},{19,48,68},{19,46,51},{20,43,70},{19,43,51},{19,47,52},{19,44,22},{19,43,3},{19,42,20},{17,46,51},{18,42,23},{20,44,24},{20,44,8},{20,43,6},{20,42,14},{31,6,51},
+{19,44,21},{19,43,2},{19,42,19},{31,29,51},{19,42,19},{19,46,50},{19,46,50},{19,46,50},{19,43,50},{19,45,9},{19,43,2},{19,43,2},{19,41,3},{18,43,10},{19,41,6},{20,42,5},{20,42,5},{20,42,5},{20,42,5},{31,4,8},{19,43,1},{19,43,1},{19,41,2},{30,29,8},{19,41,2},{30,11,18},{19,46,1},{20,43,2},{19,43,1},{30,11,18},{30,31,18},{19,43,1},
+{0,42,18},{30,31,18},{0,42,18},{19,0,50},{19,0,50},{19,0,50},{19,0,50},{19,43,2},{19,43,2},{19,43,2},{19,41,2},{18,43,1},{18,43,1},{20,49,56},{20,47,38},{20,45,53},{20,45,37},{20,48,51},{20,46,19},{20,45,1},{20,44,22},{18,48,56},{19,44,23},{21,46,24},{21,46,8},{21,45,6},{21,44,14},{30,15,51},{20,46,19},{20,45,1},{19,44,22},{31,32,51},
+{19,44,22},{20,47,37},{20,47,37},{20,47,37},{20,45,36},{20,46,10},{20,45,0},{20,45,0},{20,43,2},{19,45,10},{20,43,11},{21,44,5},{21,44,5},{21,44,5},{21,44,5},{30,13,8},{20,45,0},{20,45,0},{20,43,2},{31,31,8},{20,43,2},{31,13,18},{20,47,2},{21,45,2},{20,45,1},{31,13,18},{30,34,18},{20,45,1},{0,44,18},{30,34,18},{0,44,18},{20,0,36},
+{20,0,36},{20,0,36},{20,0,36},{20,45,0},{20,45,0},{20,45,0},{20,43,1},{19,45,1},{19,45,1},{21,51,56},{21,49,37},{21,47,53},{21,47,37},{21,50,51},{21,48,22},{21,47,1},{21,46,22},{19,50,56},{20,46,20},{22,48,22},{22,48,13},{22,47,6},{22,46,14},{30,20,51},{21,48,22},{21,47,1},{20,46,19},{31,35,51},{20,46,19},{21,49,37},{21,49,37},{21,49,37},
+{21,47,36},{21,48,8},{21,47,0},{21,47,0},{21,45,2},{20,47,11},{21,45,11},{22,46,5},{22,46,5},{22,46,5},{22,46,5},{31,15,8},{21,47,0},{21,47,0},{21,45,2},{31,34,8},{21,45,2},{31,18,18},{21,49,1},{22,47,2},{21,47,1},{31,18,18},{31,36,18},{21,47,1},{0,46,18},{31,36,18},{0,46,18},{21,0,36},{21,0,36},{21,0,36},{21,0,36},{21,47,0},
+{21,47,0},{21,47,0},{21,45,1},{20,46,2},{20,46,2},{22,53,56},{22,51,37},{22,49,56},{22,49,41},{22,52,51},{22,50,22},{22,49,5},{22,48,24},{20,51,53},{21,48,21},{23,50,22},{23,49,9},{23,48,8},{23,48,9},{31,22,51},{22,50,22},{22,49,5},{21,48,21},{28,42,51},{21,48,21},{22,51,37},{22,51,37},{22,51,37},{22,49,37},{22,50,8},{22,49,1},{22,49,1},
+{22,47,2},{21,49,9},{22,47,11},{23,48,4},{23,48,4},{23,48,4},{23,48,5},{31,20,8},{22,49,1},{22,49,1},{22,47,2},{31,37,8},{22,47,2},{31,23,18},{22,51,1},{23,48,4},{23,48,5},{31,23,18},{31,39,18},{23,48,5},{0,48,20},{31,39,18},{0,48,20},{22,0,36},{22,0,36},{22,0,36},{22,0,36},{22,49,0},{22,49,0},{22,49,0},{22,47,1},{21,48,1},
+{21,48,1},{23,56,68},{23,54,51},{24,51,70},{23,51,51},{23,55,52},{23,52,22},{23,51,3},{23,50,20},{21,54,51},{22,50,23},{24,52,24},{24,52,8},{24,51,6},{24,50,14},{31,28,51},{23,52,21},{23,51,2},{23,50,19},{31,42,51},{23,50,19},{23,54,50},{23,54,50},{23,54,50},{23,51,50},{23,53,9},{23,51,2},{23,51,2},{23,49,3},{22,51,10},{23,49,6},{24,50,5},
+{24,50,5},{24,50,5},{24,50,5},{31,26,8},{23,51,1},{23,51,1},{23,49,2},{30,42,8},{23,49,2},{31,29,18},{23,54,1},{24,51,2},{23,51,1},{31,29,18},{30,44,18},{23,51,1},{0,50,18},{30,44,18},{0,50,18},{23,0,50},{23,0,50},{23,0,50},{23,0,50},{23,51,2},{23,51,2},{23,51,2},{23,49,2},{22,51,1},{22,51,1},{24,58,54},{24,55,38},{24,53,53},
+{24,53,37},{24,56,52},{24,54,19},{24,53,1},{24,52,22},{22,56,51},{23,52,23},{25,54,24},{25,54,8},{25,53,6},{25,52,14},{31,33,51},{24,54,19},{24,53,1},{23,52,22},{31,45,51},{23,52,22},{24,56,36},{24,56,36},{24,56,36},{24,53,36},{24,54,10},{24,53,0},{24,53,0},{24,51,2},{23,53,10},{24,51,11},{25,52,5},{25,52,5},{25,52,5},{25,52,5},{31,31,8},
+{24,53,0},{24,53,0},{24,51,2},{31,44,8},{24,51,2},{31,34,18},{24,55,2},{25,53,2},{24,53,1},{31,34,18},{31,46,18},{24,53,1},{0,52,18},{31,46,18},{0,52,18},{24,0,36},{24,0,36},{24,0,36},{24,0,36},{24,53,0},{24,53,0},{24,53,0},{24,51,1},{23,53,1},{23,53,1},{25,60,54},{25,57,38},{25,55,53},{25,55,37},{25,58,52},{25,56,19},{25,55,1},
+{25,54,22},{23,58,51},{24,54,20},{26,56,24},{26,56,8},{26,55,6},{26,54,14},{31,38,51},{25,56,19},{25,55,1},{24,54,19},{31,48,51},{24,54,19},{25,58,36},{25,58,36},{25,58,36},{25,55,36},{25,56,10},{25,55,0},{25,55,0},{25,53,2},{24,55,11},{25,53,11},{26,54,5},{26,54,5},{26,54,5},{26,54,5},{31,36,8},{25,55,0},{25,55,0},{25,53,2},{31,47,8},
+{25,53,2},{30,43,18},{25,57,2},{26,55,2},{25,55,1},{30,43,18},{30,50,18},{25,55,1},{0,54,18},{30,50,18},{0,54,18},{25,0,36},{25,0,36},{25,0,36},{25,0,36},{25,55,0},{25,55,0},{25,55,0},{25,53,1},{24,54,2},{24,54,2},{26,62,54},{26,59,38},{26,57,53},{26,57,37},{26,60,52},{26,58,19},{26,57,1},{26,56,22},{25,58,56},{25,56,20},{27,58,24},
+{27,58,8},{27,57,6},{27,56,14},{30,47,51},{26,58,19},{26,57,1},{25,56,19},{31,51,51},{25,56,19},{26,60,36},{26,60,36},{26,60,36},{26,57,36},{26,58,10},{26,57,0},{26,57,0},{26,55,2},{25,57,11},{26,55,11},{27,56,5},{27,56,5},{27,56,5},{27,56,5},{30,45,8},{26,57,0},{26,57,0},{26,55,2},{31,50,8},{26,55,2},{31,45,18},{26,59,2},{27,57,2},
+{26,57,1},{31,45,18},{31,52,18},{26,57,1},{0,56,18},{31,52,18},{0,56,18},{26,0,36},{26,0,36},{26,0,36},{26,0,36},{26,57,0},{26,57,0},{26,57,0},{26,55,1},{25,56,2},{25,56,2},{27,63,76},{27,62,52},{28,59,69},{27,59,51},{27,63,52},{27,60,21},{27,59,3},{27,58,22},{25,62,52},{26,58,28},{28,60,24},{28,60,9},{28,59,5},{28,59,13},{31,49,51},
+{27,60,20},{27,59,2},{27,58,21},{30,56,51},{27,58,21},{27,62,51},{27,62,51},{27,62,51},{27,59,51},{27,61,9},{27,59,3},{27,59,3},{27,58,6},{26,60,11},{27,57,12},{28,58,5},{28,58,5},{28,58,5},{28,58,4},{29,54,8},{27,59,2},{27,59,2},{27,58,5},{29,56,8},{27,58,5},{30,54,18},{27,62,2},{28,59,1},{27,59,1},{30,54,18},{29,58,18},{27,59,1},
+{0,58,20},{29,58,18},{0,58,20},{27,0,50},{27,0,50},{27,0,50},{27,0,50},{27,60,1},{27,60,1},{27,60,1},{27,58,2},{26,59,0},{26,59,0},{28,63,86},{28,63,38},{28,61,52},{28,61,36},{28,63,59},{28,62,21},{28,61,0},{28,60,21},{27,62,60},{27,60,28},{29,62,24},{29,62,9},{29,61,5},{29,61,13},{30,58,51},{28,62,21},{28,61,0},{28,60,21},{31,58,51},
+{28,60,21},{28,63,37},{28,63,37},{28,63,37},{28,61,36},{28,62,10},{28,61,0},{28,61,0},{28,59,5},{27,62,11},{27,60,12},{29,60,5},{29,60,5},{29,60,5},{29,60,4},{30,56,8},{28,61,0},{28,61,0},{28,59,5},{30,58,8},{28,59,5},{31,56,18},{28,63,2},{29,61,1},{28,61,0},{31,56,18},{30,60,18},{28,61,0},{0,60,20},{30,60,18},{0,60,20},{28,0,36},
+{28,0,36},{28,0,36},{28,0,36},{28,61,0},{28,61,0},{28,61,0},{28,59,1},{27,61,0},{27,61,0},{30,63,94},{30,63,78},{29,63,52},{29,63,36},{30,63,115},{29,63,36},{29,63,0},{29,62,21},{29,63,88},{28,62,25},{30,63,30},{30,63,14},{30,63,5},{30,63,13},{31,60,51},{29,63,36},{29,63,0},{29,62,21},{31,61,51},{29,62,21},{29,63,52},{29,63,52},{29,63,52},
+{29,63,36},{29,63,16},{29,63,0},{29,63,0},{29,61,5},{28,63,11},{28,62,9},{30,62,5},{30,62,5},{30,62,5},{30,62,4},{31,58,8},{29,63,0},{29,63,0},{29,61,5},{31,60,8},{29,61,5},{31,61,18},{30,63,10},{30,63,1},{29,63,0},{31,61,18},{31,62,18},{29,63,0},{0,62,20},{31,62,18},{0,62,20},{29,0,36},{29,0,36},{29,0,36},{29,0,36},{29,63,0},
+{29,63,0},{29,63,0},{29,61,1},{28,63,2},{28,63,2},{31,63,68},{31,63,68},{30,63,61},{30,63,45},{30,63,59},{30,63,27},{30,63,18},{30,63,1},{30,63,28},{30,63,10},{31,63,4},{31,63,4},{31,63,4},{31,63,4},{31,63,4},{31,63,4},{31,63,4},{30,63,1},{31,63,4},{30,63,1},{30,63,61},{30,63,61},{30,63,61},{30,63,45},{30,63,34},{30,63,18},{30,63,18},
+{30,63,1},{30,63,19},{30,63,10},{31,63,4},{31,63,4},{31,63,4},{31,63,4},{31,62,4},{31,63,4},{31,63,4},{30,63,1},{31,63,4},{30,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{30,0,36},{30,0,36},{30,0,36},{30,0,36},{30,63,9},{30,63,9},{30,63,9},{30,63,1},{30,63,10},
+{30,63,10},{0,7,74},{0,6,20},{0,4,2},{0,4,26},{0,5,153},{0,4,110},{0,3,45},{0,2,115},{0,3,169},{0,2,124},{0,7,74},{0,6,20},{0,4,2},{0,4,26},{0,5,153},{0,4,110},{0,3,45},{0,2,115},{0,3,153},{0,2,115},{0,3,1},{0,3,1},{0,3,1},{0,2,0},{0,2,13},{0,2,9},{0,2,9},{0,1,5},{0,1,14},{0,1,6},{0,3,1},
+{0,3,1},{0,3,1},{0,2,0},{0,2,13},{0,2,9},{0,2,9},{0,1,5},{1,0,13},{0,1,5},{2,1,72},{0,6,20},{0,4,2},{0,4,26},{2,1,72},{3,1,72},{0,4,26},{0,3,74},{3,1,72},{0,3,74},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,13,81},{0,10,13},{0,6,26},
+{0,6,14},{0,9,244},{0,7,129},{0,6,41},{0,4,139},{0,5,300},{0,4,175},{0,13,81},{0,10,13},{0,6,26},{0,6,14},{2,3,243},{0,7,129},{0,6,41},{0,4,139},{4,1,243},{0,4,139},{0,9,9},{0,9,9},{0,9,9},{0,5,10},{0,5,52},{0,5,17},{0,5,17},{0,3,17},{0,3,68},{0,3,33},{0,9,9},{0,9,9},{0,9,9},{0,5,10},{1,2,50},
+{0,5,17},{0,5,17},{0,3,17},{2,1,50},{0,3,17},{3,3,72},{0,10,4},{1,6,2},{0,6,5},{3,3,72},{4,3,72},{0,6,5},{0,5,74},{4,3,72},{0,5,74},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,2},{0,1,2},{1,15,145},{1,12,77},{1,8,90},{1,8,78},{0,15,243},{0,10,96},{0,8,3},
+{0,6,106},{0,8,395},{0,6,187},{1,15,81},{1,12,13},{1,8,26},{1,8,14},{4,1,243},{0,10,96},{0,8,3},{0,6,106},{5,3,243},{0,6,106},{1,11,73},{1,11,73},{1,11,73},{1,7,74},{0,11,50},{0,8,2},{0,8,2},{0,5,2},{0,5,131},{0,5,51},{1,11,9},{1,11,9},{1,11,9},{1,7,10},{3,1,50},{0,8,2},{0,8,2},{0,5,2},{3,3,50},
+{0,5,2},{5,1,72},{1,12,4},{2,8,2},{0,8,2},{5,1,72},{9,0,72},{0,8,2},{0,7,74},{9,0,72},{0,7,74},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,7,1},{0,7,1},{0,7,1},{0,4,1},{0,3,32},{0,3,32},{2,17,162},{2,14,94},{2,10,107},{2,10,95},{1,17,244},{1,12,97},{1,10,4},{1,8,107},{0,11,345},{0,8,116},{2,17,81},
+{2,14,13},{2,10,26},{2,10,14},{6,0,243},{0,14,76},{1,10,3},{0,9,83},{10,0,243},{0,9,83},{2,13,90},{2,13,90},{2,13,90},{2,9,91},{1,13,51},{1,10,3},{1,10,3},{1,7,3},{0,9,94},{0,7,14},{2,13,9},{2,13,9},{2,13,9},{2,9,10},{3,6,50},{1,10,2},{1,10,2},{1,7,2},{8,0,50},{1,7,2},{7,0,72},{2,14,4},{3,10,2},
+{1,10,2},{7,0,72},{10,2,72},{1,10,2},{0,9,74},{10,2,72},{0,9,74},{2,0,90},{2,0,90},{2,0,90},{2,0,90},{1,9,2},{1,9,2},{1,9,2},{1,6,2},{0,7,13},{0,7,13},{3,19,154},{3,16,82},{3,13,100},{3,12,85},{2,19,244},{2,15,90},{2,13,5},{2,11,97},{0,15,287},{0,11,73},{3,19,90},{3,16,18},{4,12,29},{3,12,21},{6,6,243},
+{1,16,75},{2,13,5},{0,11,73},{12,1,243},{0,11,73},{3,15,81},{3,15,81},{3,15,81},{3,12,81},{2,15,52},{2,13,1},{2,13,1},{2,9,4},{0,13,61},{0,10,14},{3,15,17},{3,15,17},{3,15,17},{3,12,17},{6,2,50},{2,13,1},{2,13,1},{2,9,4},{11,0,50},{2,9,4},{8,2,72},{3,16,2},{4,12,4},{2,13,4},{8,2,72},{12,3,72},{2,13,4},
+{0,11,72},{12,3,72},{0,11,72},{3,0,80},{3,0,80},{3,0,80},{3,0,80},{2,12,0},{2,12,0},{2,12,0},{2,9,0},{0,11,1},{0,11,1},{4,21,162},{4,18,94},{4,15,103},{4,14,95},{3,21,244},{3,17,88},{3,15,5},{3,13,97},{0,18,260},{1,13,73},{4,21,81},{4,18,13},{4,15,22},{4,14,14},{9,1,243},{2,18,75},{3,15,5},{1,13,73},{13,3,243},
+{1,13,73},{4,17,90},{4,17,90},{4,17,90},{4,14,91},{3,17,52},{3,15,1},{3,15,1},{3,11,4},{0,16,52},{1,12,14},{4,17,9},{4,17,9},{4,17,9},{4,14,10},{8,0,50},{3,15,1},{3,15,1},{3,11,4},{11,3,50},{3,11,4},{10,1,72},{3,20,2},{5,14,4},{3,15,4},{10,1,72},{17,0,72},{3,15,4},{0,13,72},{17,0,72},{0,13,72},{4,0,90},
+{4,0,90},{4,0,90},{4,0,90},{3,14,0},{3,14,0},{3,14,0},{3,11,0},{1,13,1},{1,13,1},{5,23,162},{5,20,94},{5,16,107},{5,16,95},{4,23,244},{4,18,97},{4,16,4},{4,15,98},{0,22,244},{2,15,73},{5,23,81},{5,20,13},{5,16,26},{5,16,14},{10,3,243},{3,20,75},{4,16,3},{2,15,73},{18,0,243},{2,15,73},{5,19,90},{5,19,90},{5,19,90},
+{5,15,94},{4,19,51},{4,16,3},{4,16,3},{4,13,5},{1,18,52},{2,14,14},{5,19,9},{5,19,9},{5,19,9},{5,15,13},{9,2,50},{4,16,2},{4,16,2},{4,13,4},{16,0,50},{4,13,4},{11,3,72},{5,20,4},{6,16,2},{4,16,2},{11,3,72},{18,2,72},{4,16,2},{0,15,72},{18,2,72},{0,15,72},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{4,15,2},
+{4,15,2},{4,15,2},{4,13,1},{2,15,1},{2,15,1},{6,25,162},{6,22,94},{6,18,107},{6,18,95},{5,25,244},{5,20,97},{5,18,4},{5,16,107},{1,24,244},{3,17,74},{6,25,81},{6,22,13},{6,18,26},{6,18,14},{12,1,243},{3,24,75},{5,18,3},{3,17,74},{19,2,243},{3,17,74},{6,21,90},{6,21,90},{6,21,90},{6,17,91},{5,21,51},{5,18,3},{5,18,3},
+{5,15,5},{2,20,52},{3,16,19},{6,21,9},{6,21,9},{6,21,9},{6,17,10},{11,1,50},{5,18,2},{5,18,2},{5,15,4},{17,2,50},{5,15,4},{13,1,72},{6,22,4},{7,18,2},{5,18,2},{13,1,72},{19,4,72},{5,18,2},{0,17,74},{19,4,72},{0,17,74},{6,0,90},{6,0,90},{6,0,90},{6,0,90},{5,17,2},{5,17,2},{5,17,2},{5,15,1},{3,17,0},
+{3,17,0},{7,27,154},{7,24,82},{7,21,100},{7,20,85},{6,27,244},{6,23,90},{6,21,5},{6,19,97},{2,26,244},{4,19,73},{7,27,90},{7,24,18},{8,20,29},{7,20,21},{13,4,243},{5,24,75},{6,21,5},{4,19,73},{22,2,243},{4,19,73},{7,23,81},{7,23,81},{7,23,81},{7,20,81},{6,23,52},{6,21,1},{6,21,1},{6,17,4},{3,23,52},{4,18,14},{7,23,17},
+{7,23,17},{7,23,17},{7,20,17},{13,0,50},{6,21,1},{6,21,1},{6,17,4},{20,2,50},{6,17,4},{14,4,72},{7,24,2},{8,20,4},{6,21,4},{14,4,72},{25,0,72},{6,21,4},{0,19,72},{25,0,72},{0,19,72},{7,0,80},{7,0,80},{7,0,80},{7,0,80},{6,20,0},{6,20,0},{6,20,0},{6,17,0},{4,19,1},{4,19,1},{8,29,162},{8,26,92},{8,23,103},
+{8,22,95},{7,29,244},{7,25,90},{7,23,5},{7,21,97},{3,28,244},{5,21,73},{8,29,81},{8,26,11},{8,23,22},{8,22,14},{14,6,243},{6,26,75},{7,23,5},{5,21,73},{26,0,243},{5,21,73},{8,25,90},{8,25,90},{8,25,90},{8,22,91},{7,25,52},{7,23,1},{7,23,1},{7,19,4},{4,24,52},{5,20,14},{8,25,9},{8,25,9},{8,25,9},{8,22,10},{14,2,50},
+{7,23,1},{7,23,1},{7,19,4},{24,0,50},{7,19,4},{16,2,72},{8,26,2},{9,22,4},{7,23,4},{16,2,72},{27,1,72},{7,23,4},{0,21,72},{27,1,72},{0,21,72},{8,0,90},{8,0,90},{8,0,90},{8,0,90},{7,22,0},{7,22,0},{7,22,0},{7,19,0},{5,21,1},{5,21,1},{9,31,162},{9,28,92},{9,25,103},{9,24,95},{8,31,244},{8,26,100},{8,24,9},
+{8,23,98},{4,30,244},{6,23,73},{9,31,81},{9,28,11},{9,25,22},{9,24,14},{16,4,243},{7,28,75},{8,24,8},{6,23,73},{27,2,243},{6,23,73},{9,27,90},{9,27,90},{9,27,90},{9,24,91},{8,27,51},{8,24,5},{8,24,5},{8,21,5},{5,26,52},{6,22,14},{9,27,9},{9,27,9},{9,27,9},{9,24,10},{16,0,50},{8,24,4},{8,24,4},{8,21,4},{26,1,50},
+{8,21,4},{17,4,72},{9,28,2},{10,24,4},{8,25,4},{17,4,72},{27,4,72},{8,25,4},{0,23,72},{27,4,72},{0,23,72},{9,0,90},{9,0,90},{9,0,90},{9,0,90},{8,24,1},{8,24,1},{8,24,1},{8,21,1},{6,23,1},{6,23,1},{10,33,162},{10,30,92},{10,27,103},{10,26,95},{9,33,244},{9,28,100},{9,26,9},{9,25,98},{5,32,244},{7,25,73},{10,33,81},
+{10,30,11},{10,27,22},{10,26,14},{17,6,243},{8,30,75},{9,26,8},{7,25,73},{28,4,243},{7,25,73},{10,29,90},{10,29,90},{10,29,90},{10,26,91},{9,29,51},{9,26,5},{9,26,5},{9,23,5},{6,28,52},{7,24,14},{10,29,9},{10,29,9},{10,29,9},{10,26,10},{17,2,50},{9,26,4},{9,26,4},{9,23,4},{27,3,50},{9,23,4},{18,6,72},{10,30,2},{11,26,4},
+{9,27,4},{18,6,72},{28,6,72},{9,27,4},{0,25,72},{28,6,72},{0,25,72},{10,0,90},{10,0,90},{10,0,90},{10,0,90},{9,26,1},{9,26,1},{9,26,1},{9,23,1},{7,25,1},{7,25,1},{11,35,154},{11,32,82},{11,29,97},{11,29,85},{10,35,244},{10,31,96},{10,29,3},{10,27,90},{6,34,244},{8,27,78},{11,35,90},{11,32,18},{12,29,27},{11,29,21},{19,5,243},
+{9,32,75},{10,29,3},{9,27,75},{31,4,243},{9,27,75},{11,31,81},{11,31,81},{11,31,81},{11,28,80},{10,31,52},{10,29,2},{10,29,2},{10,26,5},{7,31,50},{9,26,11},{11,31,17},{11,31,17},{11,31,17},{11,28,16},{19,1,50},{10,29,2},{10,29,2},{9,26,2},{29,4,50},{9,26,2},{20,5,72},{11,32,2},{12,29,2},{10,29,2},{20,5,72},{31,6,72},{10,29,2},
+{0,27,74},{31,6,72},{0,27,74},{11,0,80},{11,0,80},{11,0,80},{11,0,80},{10,28,1},{10,28,1},{10,28,1},{10,25,1},{8,28,2},{8,28,2},{12,37,162},{12,34,92},{12,31,107},{12,30,99},{11,37,244},{11,33,90},{11,31,3},{11,29,90},{7,36,244},{9,29,78},{12,37,81},{12,34,11},{12,31,26},{12,30,18},{22,0,243},{10,34,75},{11,31,3},{10,29,75},{31,7,243},
+{10,29,75},{12,33,90},{12,33,90},{12,33,90},{12,30,90},{11,33,52},{11,31,2},{11,31,2},{11,28,5},{8,32,52},{10,28,11},{12,33,9},{12,33,9},{12,33,9},{12,30,9},{20,3,50},{11,31,2},{11,31,2},{10,28,2},{30,6,50},{10,28,2},{23,0,72},{12,34,2},{13,31,2},{11,31,2},{23,0,72},{31,9,72},{11,31,2},{0,29,74},{31,9,72},{0,29,74},{12,0,90},
+{12,0,90},{12,0,90},{12,0,90},{11,30,1},{11,30,1},{11,30,1},{11,27,1},{9,30,2},{9,30,2},{13,39,162},{13,36,92},{13,33,103},{13,32,95},{12,39,244},{12,34,100},{12,32,9},{12,31,100},{8,38,244},{10,31,78},{13,39,81},{13,36,11},{13,33,22},{13,32,14},{23,2,243},{11,36,75},{12,32,8},{11,31,75},{28,14,243},{11,31,75},{13,35,90},{13,35,90},{13,35,90},
+{13,32,91},{12,35,51},{12,32,5},{12,32,5},{12,30,6},{9,34,52},{11,30,11},{13,35,9},{13,35,9},{13,35,9},{13,32,10},{21,5,50},{12,32,4},{12,32,4},{11,30,2},{31,8,50},{11,30,2},{24,2,72},{13,36,2},{14,32,4},{12,33,4},{24,2,72},{27,17,72},{12,33,4},{0,31,74},{27,17,72},{0,31,74},{13,0,90},{13,0,90},{13,0,90},{13,0,90},{12,32,1},
+{12,32,1},{12,32,1},{12,29,1},{10,31,4},{10,31,4},{14,41,162},{14,38,92},{14,35,103},{14,34,95},{13,41,244},{13,36,100},{13,34,9},{13,33,98},{9,40,244},{11,33,73},{14,41,81},{14,38,11},{14,35,22},{14,34,14},{24,4,243},{12,38,75},{13,34,8},{11,33,73},{28,17,243},{11,33,73},{14,37,90},{14,37,90},{14,37,90},{14,34,91},{13,37,51},{13,34,5},{13,34,5},
+{13,31,10},{10,36,52},{11,32,14},{14,37,9},{14,37,9},{14,37,9},{14,34,10},{24,0,50},{13,34,4},{13,34,4},{12,32,4},{31,11,50},{12,32,4},{25,4,72},{14,38,2},{15,34,4},{13,35,4},{25,4,72},{28,19,72},{13,35,4},{0,33,72},{28,19,72},{0,33,72},{14,0,90},{14,0,90},{14,0,90},{14,0,90},{13,34,1},{13,34,1},{13,34,1},{13,31,1},{11,33,1},
+{11,33,1},{15,44,152},{15,40,84},{15,37,97},{15,37,85},{14,44,243},{14,39,96},{14,37,3},{14,35,90},{10,42,244},{12,35,78},{15,44,88},{15,40,20},{16,37,27},{15,37,21},{27,0,243},{13,41,76},{14,37,3},{13,35,75},{31,17,243},{13,35,75},{15,40,80},{15,40,80},{15,40,80},{15,36,80},{14,40,50},{14,37,2},{14,37,2},{14,34,5},{11,39,50},{13,34,11},{15,40,16},
+{15,40,16},{15,40,16},{15,36,16},{24,6,50},{14,37,2},{14,37,2},{13,34,2},{29,17,50},{13,34,2},{27,3,72},{15,40,4},{16,37,2},{14,37,2},{27,3,72},{31,19,72},{14,37,2},{0,35,74},{31,19,72},{0,35,74},{15,0,80},{15,0,80},{15,0,80},{15,0,80},{14,36,1},{14,36,1},{14,36,1},{14,33,1},{12,36,2},{12,36,2},{16,45,164},{16,42,95},{16,39,107},
+{16,38,99},{15,46,243},{15,41,96},{15,39,3},{15,37,90},{11,44,244},{13,37,78},{16,45,83},{16,42,14},{16,39,26},{16,38,18},{27,5,243},{14,43,76},{15,39,3},{14,37,75},{31,20,243},{14,37,75},{16,41,91},{16,41,91},{16,41,91},{16,38,90},{15,42,50},{15,39,2},{15,39,2},{15,36,5},{12,41,51},{14,36,11},{16,41,10},{16,41,10},{16,41,10},{16,38,9},{27,1,50},
+{15,39,2},{15,39,2},{14,36,2},{30,19,50},{14,36,2},{28,5,72},{15,44,4},{17,39,2},{15,39,2},{28,5,72},{31,22,72},{15,39,2},{0,37,74},{31,22,72},{0,37,74},{16,0,90},{16,0,90},{16,0,90},{16,0,90},{15,38,1},{15,38,1},{15,38,1},{15,35,1},{13,38,2},{13,38,2},{17,47,164},{17,44,95},{17,41,107},{17,40,99},{16,47,245},{16,43,91},{16,41,3},
+{16,39,100},{12,46,244},{14,39,78},{17,47,83},{17,44,14},{17,41,26},{17,40,18},{30,0,243},{15,45,76},{16,41,2},{15,39,75},{28,27,243},{15,39,75},{17,43,91},{17,43,91},{17,43,91},{17,40,90},{16,43,53},{16,41,2},{16,41,2},{16,38,6},{13,43,51},{15,38,11},{17,43,10},{17,43,10},{17,43,10},{17,40,9},{28,3,50},{16,41,1},{16,41,1},{15,38,2},{31,21,50},
+{15,38,2},{31,0,72},{16,46,1},{18,41,2},{16,41,1},{31,0,72},{28,29,72},{16,41,1},{0,39,74},{28,29,72},{0,39,74},{17,0,90},{17,0,90},{17,0,90},{17,0,90},{16,40,1},{16,40,1},{16,40,1},{16,37,1},{14,40,2},{14,40,2},{18,49,162},{18,46,95},{18,43,107},{18,42,99},{17,49,244},{17,45,91},{17,43,3},{17,41,100},{13,48,244},{15,41,78},{18,49,81},
+{18,46,14},{18,43,26},{18,42,18},{31,2,243},{15,48,75},{17,43,2},{15,41,78},{29,29,243},{15,41,78},{18,45,91},{18,45,91},{18,45,91},{18,42,90},{17,45,53},{17,43,2},{17,43,2},{17,40,6},{14,45,51},{16,40,18},{18,45,10},{18,45,10},{18,45,10},{18,42,9},{29,5,50},{17,43,1},{17,43,1},{16,40,2},{31,24,50},{16,40,2},{30,9,72},{17,48,2},{19,43,2},
+{17,43,1},{30,9,72},{29,31,72},{17,43,1},{0,41,74},{29,31,72},{0,41,74},{18,0,90},{18,0,90},{18,0,90},{18,0,90},{17,42,1},{17,42,1},{17,42,1},{17,39,1},{15,42,2},{15,42,2},{19,52,152},{19,48,84},{19,45,105},{19,45,84},{18,52,243},{18,47,89},{18,45,1},{18,43,96},{14,50,244},{16,44,81},{19,52,88},{19,48,20},{20,45,26},{19,45,20},{31,8,243},
+{17,49,76},{18,45,1},{16,44,80},{31,30,243},{16,44,80},{19,48,80},{19,48,80},{19,48,80},{19,44,81},{18,48,50},{18,45,1},{18,45,1},{18,42,1},{15,47,52},{17,42,13},{19,48,16},{19,48,16},{19,48,16},{19,44,17},{31,4,50},{18,45,1},{18,45,1},{18,42,1},{30,29,50},{18,42,1},{30,15,72},{19,48,4},{20,45,1},{18,45,1},{30,15,72},{31,32,72},{18,45,1},
+{0,43,80},{31,32,72},{0,43,80},{19,0,80},{19,0,80},{19,0,80},{19,0,80},{18,45,0},{18,45,0},{18,45,0},{18,41,1},{16,44,1},{16,44,1},{20,53,164},{20,50,95},{20,47,106},{20,47,94},{19,54,243},{19,49,96},{19,47,1},{19,45,96},{15,52,244},{17,46,81},{20,53,83},{20,50,14},{20,47,25},{20,47,13},{29,20,243},{18,51,76},{19,47,1},{17,46,80},{31,33,243},
+{17,46,80},{20,49,91},{20,49,91},{20,49,91},{20,46,90},{19,50,50},{19,47,1},{19,47,1},{19,44,1},{16,49,51},{18,44,13},{20,49,10},{20,49,10},{20,49,10},{20,46,9},{30,13,50},{19,47,1},{19,47,1},{19,44,1},{31,31,50},{19,44,1},{30,20,72},{19,52,4},{21,47,1},{19,47,1},{30,20,72},{31,35,72},{19,47,1},{0,45,80},{31,35,72},{0,45,80},{20,0,90},
+{20,0,90},{20,0,90},{20,0,90},{19,47,0},{19,47,0},{19,47,0},{19,43,1},{17,46,1},{17,46,1},{21,55,164},{21,52,95},{21,49,107},{21,48,99},{20,55,245},{20,51,91},{20,49,3},{20,47,97},{16,54,244},{18,47,85},{21,55,83},{21,52,14},{21,49,26},{21,48,18},{30,22,243},{19,53,76},{20,49,2},{19,47,81},{28,40,243},{19,47,81},{21,51,91},{21,51,91},{21,51,91},
+{21,48,90},{20,51,53},{20,49,2},{20,49,2},{20,46,5},{17,51,51},{19,46,13},{21,51,10},{21,51,10},{21,51,10},{21,48,9},{31,15,50},{20,49,1},{20,49,1},{19,46,4},{31,34,50},{19,46,4},{31,22,72},{20,54,1},{22,49,2},{20,49,1},{31,22,72},{28,42,72},{20,49,1},{0,47,80},{28,42,72},{0,47,80},{21,0,90},{21,0,90},{21,0,90},{21,0,90},{20,48,1},
+{20,48,1},{20,48,1},{20,45,2},{18,48,2},{18,48,2},{22,57,164},{22,54,95},{22,51,107},{22,50,99},{21,57,245},{21,53,91},{21,51,3},{21,49,100},{17,56,244},{19,49,78},{22,57,83},{22,54,14},{22,51,26},{22,50,18},{31,24,243},{19,56,76},{21,51,2},{19,49,78},{29,42,243},{19,49,78},{22,53,91},{22,53,91},{22,53,91},{22,50,90},{21,53,53},{21,51,2},{21,51,2},
+{21,48,6},{18,53,51},{20,48,18},{22,53,10},{22,53,10},{22,53,10},{22,50,9},{31,20,50},{21,51,1},{21,51,1},{20,48,2},{31,37,50},{20,48,2},{31,27,72},{21,56,1},{23,51,2},{21,51,1},{31,27,72},{29,44,72},{21,51,1},{0,49,74},{29,44,72},{0,49,74},{22,0,90},{22,0,90},{22,0,90},{22,0,90},{21,50,1},{21,50,1},{21,50,1},{21,47,2},{19,50,2},
+{19,50,2},{23,60,152},{23,57,81},{23,53,105},{23,53,84},{22,60,243},{22,55,89},{22,53,1},{22,51,96},{18,59,244},{20,52,81},{23,60,88},{23,57,17},{24,53,26},{23,53,20},{31,30,243},{21,57,73},{22,53,1},{20,52,80},{31,43,243},{20,52,80},{23,56,80},{23,56,80},{23,56,80},{23,52,81},{22,56,50},{22,53,1},{22,53,1},{22,50,1},{19,55,52},{21,50,13},{23,56,16},
+{23,56,16},{23,56,16},{23,52,17},{31,26,50},{22,53,1},{22,53,1},{22,50,1},{30,42,50},{22,50,1},{31,33,72},{23,57,1},{24,53,1},{22,53,1},{31,33,72},{31,45,72},{22,53,1},{0,51,80},{31,45,72},{0,51,80},{23,0,80},{23,0,80},{23,0,80},{23,0,80},{22,53,0},{22,53,0},{22,53,0},{22,49,1},{20,52,1},{20,52,1},{24,62,162},{24,58,94},{24,55,106},
+{24,55,94},{23,62,243},{23,57,89},{23,55,1},{23,53,96},{19,61,244},{21,54,81},{24,62,81},{24,58,13},{24,55,25},{24,55,13},{31,35,243},{22,59,73},{23,55,1},{21,54,80},{27,51,243},{21,54,80},{24,58,90},{24,58,90},{24,58,90},{24,54,90},{23,58,50},{23,55,1},{23,55,1},{23,52,1},{20,57,50},{22,52,13},{24,58,9},{24,58,9},{24,58,9},{24,54,9},{31,31,50},
+{23,55,1},{23,55,1},{23,52,1},{31,44,50},{23,52,1},{31,38,72},{24,58,4},{25,55,1},{23,55,1},{31,38,72},{31,48,72},{23,55,1},{0,53,80},{31,48,72},{0,53,80},{24,0,90},{24,0,90},{24,0,90},{24,0,90},{23,55,0},{23,55,0},{23,55,0},{23,51,1},{21,54,1},{21,54,1},{25,63,164},{25,60,94},{25,57,106},{25,57,94},{24,63,245},{24,59,97},{24,57,3},
+{24,55,97},{20,63,249},{22,56,81},{25,63,83},{25,60,13},{25,57,25},{25,57,13},{31,40,243},{23,61,73},{24,57,2},{22,56,80},{31,49,243},{22,56,80},{25,60,90},{25,60,90},{25,60,90},{25,56,90},{24,60,51},{24,57,3},{24,57,3},{24,54,5},{21,59,50},{23,54,13},{25,60,9},{25,60,9},{25,60,9},{25,56,9},{31,36,50},{24,57,2},{24,57,2},{23,54,4},{31,47,50},
+{23,54,4},{30,47,72},{25,60,4},{26,57,1},{24,57,1},{30,47,72},{31,51,72},{24,57,1},{0,55,80},{31,51,72},{0,55,80},{25,0,90},{25,0,90},{25,0,90},{25,0,90},{24,56,2},{24,56,2},{24,56,2},{24,53,2},{22,56,1},{22,56,1},{26,63,194},{26,62,94},{26,59,106},{26,59,94},{25,63,284},{25,61,97},{25,59,3},{25,57,97},{22,63,253},{23,58,81},{27,62,99},
+{26,62,13},{26,59,25},{26,59,13},{29,52,243},{24,63,76},{25,59,2},{23,58,80},{28,56,243},{23,58,80},{26,62,90},{26,62,90},{26,62,90},{26,58,90},{25,62,51},{25,59,3},{25,59,3},{25,56,5},{22,61,50},{24,56,10},{26,62,9},{26,62,9},{26,62,9},{26,58,9},{30,45,50},{25,59,2},{25,59,2},{24,56,1},{31,50,50},{24,56,1},{30,52,72},{26,62,4},{27,59,1},
+{25,59,1},{30,52,72},{28,58,72},{25,59,1},{0,57,80},{28,58,72},{0,57,80},{26,0,90},{26,0,90},{26,0,90},{26,0,90},{25,58,2},{25,58,2},{25,58,2},{25,55,2},{23,58,1},{23,58,1},{27,63,280},{27,63,120},{27,62,105},{27,61,82},{27,63,328},{26,63,99},{26,61,5},{26,59,99},{24,63,308},{24,60,74},{28,63,105},{28,63,45},{28,61,27},{27,61,18},{31,51,243},
+{26,63,99},{26,61,5},{24,60,74},{31,56,243},{24,60,74},{27,63,84},{27,63,84},{27,63,84},{27,60,81},{26,63,58},{26,62,2},{26,62,2},{26,58,2},{23,63,53},{25,58,9},{27,63,20},{27,63,20},{27,63,20},{27,60,17},{29,54,50},{26,62,2},{26,62,2},{26,58,2},{29,56,50},{26,58,2},{30,58,72},{28,63,20},{28,61,2},{27,61,2},{30,58,72},{31,58,72},{27,61,2},
+{0,60,74},{31,58,72},{0,60,74},{27,0,80},{27,0,80},{27,0,80},{27,0,80},{26,61,0},{26,61,0},{26,61,0},{26,58,1},{24,60,0},{24,60,0},{28,63,331},{28,63,187},{28,63,106},{28,63,94},{28,63,358},{27,63,173},{27,63,4},{27,61,82},{26,63,355},{25,62,65},{29,63,126},{29,63,62},{28,63,25},{28,63,13},{31,56,221},{28,63,121},{27,63,4},{25,62,65},{30,60,221},
+{25,62,65},{28,63,106},{28,63,106},{28,63,106},{28,62,91},{27,63,100},{27,63,4},{27,63,4},{27,60,2},{25,63,72},{26,60,9},{28,63,25},{28,63,25},{28,63,25},{28,62,10},{30,56,50},{27,63,4},{27,63,4},{27,60,2},{30,58,50},{27,60,2},{31,59,61},{29,63,37},{29,63,1},{27,63,4},{31,59,61},{31,61,61},{27,63,4},{0,62,65},{31,61,61},{0,62,65},{28,0,90},
+{28,0,90},{28,0,90},{28,0,90},{27,63,0},{27,63,0},{27,63,0},{27,60,1},{25,62,0},{25,62,0},{29,63,239},{29,63,175},{29,63,139},{29,63,99},{29,63,239},{28,63,122},{28,63,41},{28,62,19},{28,63,233},{26,63,19},{30,63,54},{30,63,38},{30,63,29},{29,63,18},{31,60,93},{29,63,54},{29,63,18},{27,63,9},{31,61,93},{27,63,9},{29,63,139},{29,63,139},{29,63,139},
+{29,63,99},{29,63,139},{28,63,41},{28,63,41},{28,62,3},{27,63,116},{27,62,9},{30,63,29},{30,63,29},{30,63,29},{29,63,18},{31,58,50},{29,63,18},{29,63,18},{28,62,2},{31,60,50},{28,62,2},{31,62,5},{31,63,9},{30,63,4},{30,63,0},{31,62,5},{31,62,9},{30,63,0},{0,63,9},{31,62,9},{0,63,9},{29,0,90},{29,0,90},{29,0,90},{29,0,90},{28,63,5},
+{28,63,5},{28,63,5},{28,61,2},{27,62,8},{27,62,8},{30,63,140},{30,63,124},{30,63,115},{30,63,99},{30,63,131},{29,63,98},{29,63,62},{29,63,2},{29,63,122},{28,63,20},{31,63,25},{31,63,25},{31,63,25},{30,63,18},{31,62,17},{30,63,18},{30,63,9},{29,63,1},{31,62,22},{29,63,1},{30,63,115},{30,63,115},{30,63,115},{30,63,99},{30,63,106},{29,63,62},{29,63,62},
+{29,63,2},{29,63,86},{28,63,20},{31,63,25},{31,63,25},{31,63,25},{30,63,18},{31,61,13},{30,63,9},{30,63,9},{29,63,1},{31,62,13},{29,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{30,0,90},{30,0,90},{30,0,90},{30,0,90},{29,63,26},{29,63,26},{29,63,26},{29,63,2},{28,63,20},
+{28,63,20},{0,13,200},{0,10,52},{0,7,2},{0,6,61},{0,9,441},{0,7,308},{0,5,139},{0,4,318},{0,5,491},{0,4,354},{0,13,200},{0,10,52},{0,7,2},{0,6,61},{2,2,441},{0,7,308},{0,5,139},{0,4,318},{2,3,441},{0,4,318},{0,6,0},{0,6,0},{0,6,0},{0,4,1},{0,3,41},{0,3,20},{0,3,20},{0,2,26},{0,2,50},{0,1,30},{0,6,0},
+{0,6,0},{0,6,0},{0,4,1},{1,0,41},{0,3,20},{0,3,20},{0,2,26},{1,1,41},{0,2,26},{3,3,200},{0,10,52},{0,7,2},{0,6,61},{3,3,200},{4,3,200},{0,6,61},{0,5,202},{4,3,200},{0,5,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,18,200},{0,14,20},{0,10,13},
+{0,9,26},{0,12,686},{0,9,419},{0,8,178},{0,5,442},{0,7,789},{0,5,491},{0,18,200},{0,14,20},{0,10,13},{0,9,26},{3,2,686},{0,9,419},{0,8,178},{0,5,442},{6,0,686},{0,5,442},{0,11,1},{0,11,1},{0,11,1},{0,7,0},{0,6,145},{0,5,74},{0,5,74},{0,3,74},{0,3,165},{0,3,90},{0,11,1},{0,11,1},{0,11,1},{0,7,0},{1,2,145},
+{0,5,74},{0,5,74},{0,3,74},{3,0,145},{0,3,74},{5,1,200},{0,14,20},{1,9,2},{0,9,26},{5,1,200},{9,0,200},{0,9,26},{0,7,202},{9,0,200},{0,7,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,23,251},{0,17,53},{1,12,78},{0,11,54},{0,17,724},{0,13,362},{0,11,86},
+{0,8,387},{0,9,932},{0,7,498},{1,20,201},{1,16,21},{1,12,14},{1,11,27},{4,4,723},{0,13,362},{0,11,86},{0,8,387},{7,2,723},{0,8,387},{0,17,49},{0,17,49},{0,17,49},{0,10,49},{0,11,162},{0,9,45},{0,9,45},{0,5,50},{0,5,243},{0,5,99},{1,13,2},{1,13,2},{1,13,2},{1,9,1},{3,1,162},{0,9,45},{0,9,45},{0,5,50},{3,3,162},
+{0,5,50},{7,0,200},{0,17,4},{2,11,2},{0,11,5},{7,0,200},{10,2,200},{0,11,5},{0,9,202},{10,2,200},{0,9,202},{0,0,49},{0,0,49},{0,0,49},{0,0,49},{0,5,0},{0,5,0},{0,5,0},{0,3,0},{0,2,13},{0,2,13},{1,25,315},{1,19,117},{1,14,171},{1,13,118},{0,23,723},{0,16,299},{0,13,18},{0,10,318},{0,12,1087},{0,9,516},{2,22,201},
+{2,17,21},{2,14,14},{2,13,27},{5,6,723},{0,16,299},{0,13,18},{0,10,318},{8,4,723},{0,10,318},{1,19,113},{1,19,113},{1,19,113},{1,12,113},{0,16,162},{0,13,17},{0,13,17},{0,8,26},{0,8,338},{0,7,129},{2,15,2},{2,15,2},{2,15,2},{2,11,1},{3,6,162},{0,13,17},{0,13,17},{0,8,26},{8,0,162},{0,8,26},{7,5,200},{1,19,4},{3,13,2},
+{0,13,2},{7,5,200},{14,0,200},{0,13,2},{0,11,202},{14,0,200},{0,11,202},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,10,0},{0,10,0},{0,10,0},{0,6,0},{0,5,58},{0,5,58},{2,28,408},{2,22,210},{2,16,281},{2,15,213},{0,29,739},{0,20,260},{0,16,29},{0,13,280},{0,15,1143},{0,12,464},{3,25,200},{3,21,16},{3,16,18},{3,15,20},{7,5,723},
+{0,20,244},{0,16,13},{0,13,264},{14,0,723},{0,13,264},{2,21,209},{2,21,209},{2,21,209},{2,14,209},{1,19,178},{0,17,18},{0,17,18},{0,10,21},{0,12,376},{0,9,121},{3,18,0},{3,18,0},{3,18,0},{3,13,1},{6,2,162},{0,17,2},{0,17,2},{0,10,5},{11,0,162},{0,10,5},{10,1,200},{2,22,2},{4,15,5},{2,15,5},{10,1,200},{17,0,200},{2,15,5},
+{0,13,200},{17,0,200},{0,13,200},{2,0,208},{2,0,208},{2,0,208},{2,0,208},{1,13,16},{1,13,16},{1,13,16},{1,8,17},{0,8,80},{0,8,80},{3,30,408},{3,24,210},{3,18,281},{3,17,213},{1,31,739},{1,22,260},{2,17,27},{1,15,280},{0,19,1000},{0,14,322},{4,26,201},{4,22,21},{4,18,14},{4,17,27},{10,0,723},{0,23,212},{2,17,11},{0,15,225},{15,2,723},
+{0,15,225},{3,23,209},{3,23,209},{3,23,209},{3,16,209},{2,21,178},{1,19,18},{1,19,18},{1,12,21},{0,15,294},{0,12,44},{4,19,2},{4,19,2},{4,19,2},{4,15,2},{8,0,162},{1,19,2},{1,19,2},{0,13,4},{11,3,162},{0,13,4},{11,3,200},{3,24,2},{5,17,2},{2,17,2},{11,3,200},{18,2,200},{2,17,2},{0,15,200},{18,2,200},{0,15,200},{3,0,208},
+{3,0,208},{3,0,208},{3,0,208},{2,15,16},{2,15,16},{2,15,16},{2,10,17},{0,12,40},{0,12,40},{4,31,420},{4,26,222},{4,20,276},{4,19,223},{3,29,740},{2,24,260},{3,19,27},{2,16,270},{0,23,920},{0,16,234},{5,28,201},{5,24,21},{5,20,14},{5,19,27},{11,2,723},{0,27,200},{3,19,11},{0,17,211},{16,4,723},{0,17,211},{4,25,218},{4,25,218},{4,25,218},
+{4,18,218},{3,23,178},{2,21,18},{2,21,18},{2,14,21},{0,19,228},{0,15,17},{5,21,2},{5,21,2},{5,21,2},{5,17,1},{9,2,162},{2,21,2},{2,21,2},{1,15,4},{16,0,162},{1,15,4},{13,1,200},{3,28,2},{6,19,2},{3,19,2},{13,1,200},{19,4,200},{3,19,2},{0,17,202},{19,4,200},{0,17,202},{4,0,218},{4,0,218},{4,0,218},{4,0,218},{3,17,16},
+{3,17,16},{3,17,16},{3,12,17},{0,15,13},{0,15,13},{5,33,420},{5,28,222},{5,22,276},{5,21,223},{3,34,740},{3,26,260},{3,22,29},{3,18,270},{0,25,844},{0,19,202},{6,30,201},{6,26,21},{6,22,14},{6,21,27},{12,4,723},{1,29,200},{3,22,13},{0,19,202},{22,0,723},{0,19,202},{5,27,218},{5,27,218},{5,27,218},{5,20,218},{3,28,178},{3,23,18},{3,23,18},
+{3,16,18},{0,22,195},{1,17,17},{6,23,2},{6,23,2},{6,23,2},{6,19,1},{11,1,162},{3,23,2},{3,23,2},{3,16,2},{17,2,162},{3,16,2},{15,0,200},{5,28,4},{7,21,2},{4,21,2},{15,0,200},{24,1,200},{4,21,2},{0,19,202},{24,1,200},{0,19,202},{5,0,218},{5,0,218},{5,0,218},{5,0,218},{3,22,16},{3,22,16},{3,22,16},{3,16,17},{0,19,0},
+{0,19,0},{6,36,408},{6,30,210},{6,24,276},{6,23,213},{4,37,739},{4,28,260},{4,24,24},{4,21,280},{0,29,780},{1,21,202},{7,33,200},{7,29,17},{7,24,13},{7,23,20},{15,0,723},{2,31,203},{4,24,8},{1,21,201},{24,1,723},{1,21,201},{6,29,209},{6,29,209},{6,29,209},{6,22,209},{5,27,178},{4,25,17},{4,25,17},{4,18,21},{0,26,168},{2,19,14},{7,26,0},
+{7,26,0},{7,26,0},{7,21,1},{13,0,162},{4,25,1},{4,25,1},{3,19,4},{20,2,162},{3,19,4},{16,2,200},{6,30,2},{8,23,5},{6,23,5},{16,2,200},{27,1,200},{6,23,5},{0,21,200},{27,1,200},{0,21,200},{6,0,208},{6,0,208},{6,0,208},{6,0,208},{5,21,16},{5,21,16},{5,21,16},{5,16,17},{1,21,2},{1,21,2},{7,38,408},{7,32,210},{7,26,276},
+{7,25,213},{5,39,739},{5,30,260},{5,26,24},{5,23,280},{0,33,749},{2,23,202},{8,34,201},{8,30,19},{8,26,14},{8,25,21},{16,1,723},{3,33,202},{5,26,8},{2,23,201},{25,3,723},{2,23,201},{7,31,209},{7,31,209},{7,31,209},{7,24,209},{6,29,178},{5,27,17},{5,27,17},{5,20,21},{0,30,164},{3,21,14},{8,28,1},{8,28,1},{8,28,1},{8,23,2},{14,2,162},
+{5,27,1},{5,27,1},{4,21,4},{24,0,162},{4,21,4},{17,4,200},{7,32,2},{9,25,5},{7,25,5},{17,4,200},{27,4,200},{7,25,5},{0,23,200},{27,4,200},{0,23,200},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{6,23,16},{6,23,16},{6,23,16},{6,18,17},{2,23,2},{2,23,2},{8,39,420},{8,34,222},{8,28,286},{8,27,223},{6,41,739},{6,32,260},{6,28,24},
+{6,25,280},{0,36,725},{3,25,202},{9,36,201},{9,32,21},{9,28,14},{9,27,21},{18,0,723},{4,35,200},{6,28,8},{3,25,201},{30,0,723},{3,25,201},{8,33,218},{8,33,218},{8,33,218},{8,26,219},{7,31,178},{6,29,17},{6,29,17},{6,22,21},{2,30,168},{4,23,17},{9,30,1},{9,30,1},{9,30,1},{9,25,2},{16,0,162},{6,29,1},{6,29,1},{5,23,4},{26,1,162},
+{5,23,4},{18,6,200},{7,36,2},{10,27,5},{8,27,5},{18,6,200},{28,6,200},{8,27,5},{0,25,200},{28,6,200},{0,25,200},{8,0,218},{8,0,218},{8,0,218},{8,0,218},{7,25,16},{7,25,16},{7,25,16},{7,20,17},{3,25,2},{3,25,2},{9,41,420},{9,36,222},{9,30,286},{9,29,223},{7,43,739},{7,34,260},{7,30,24},{7,27,280},{1,38,725},{4,27,201},{10,38,201},
+{10,34,21},{10,30,14},{10,29,21},{19,2,723},{5,37,200},{7,30,8},{4,27,201},{31,2,723},{4,27,201},{9,35,218},{9,35,218},{9,35,218},{9,28,219},{7,36,178},{7,31,17},{7,31,17},{7,24,21},{2,33,165},{5,25,17},{10,31,2},{10,31,2},{10,31,2},{10,27,2},{17,2,162},{7,31,1},{7,31,1},{6,25,4},{27,3,162},{6,25,4},{21,1,200},{9,36,4},{11,29,5},
+{9,29,5},{21,1,200},{29,8,200},{9,29,5},{0,27,200},{29,8,200},{0,27,200},{9,0,218},{9,0,218},{9,0,218},{9,0,218},{7,30,16},{7,30,16},{7,30,16},{7,24,17},{4,27,1},{4,27,1},{10,44,408},{10,38,210},{10,32,276},{10,31,217},{8,45,739},{8,36,260},{8,32,24},{8,29,267},{2,41,727},{5,29,207},{11,41,200},{11,37,17},{11,32,13},{11,31,18},{21,1,723},
+{6,39,203},{8,32,8},{6,29,203},{29,8,723},{6,29,203},{10,37,209},{10,37,209},{10,37,209},{10,31,208},{9,35,178},{8,33,17},{8,33,17},{8,27,21},{3,36,165},{6,27,18},{11,34,0},{11,34,0},{11,34,0},{11,30,1},{19,1,162},{8,33,1},{8,33,1},{7,27,2},{29,4,162},{7,27,2},{23,0,200},{10,38,2},{12,32,8},{9,32,5},{23,0,200},{31,9,200},{9,32,5},
+{0,29,202},{31,9,200},{0,29,202},{10,0,208},{10,0,208},{10,0,208},{10,0,208},{9,29,16},{9,29,16},{9,29,16},{9,25,16},{5,30,2},{5,30,2},{11,46,408},{11,40,210},{11,34,276},{11,33,213},{9,47,739},{9,38,260},{9,34,24},{9,31,267},{3,43,727},{6,31,207},{12,42,203},{12,38,19},{12,34,14},{12,33,21},{22,3,723},{7,41,203},{9,34,8},{7,31,203},{30,10,723},
+{7,31,203},{11,39,209},{11,39,209},{11,39,209},{11,32,209},{10,37,178},{9,35,17},{9,35,17},{9,29,21},{4,38,164},{7,29,18},{12,36,1},{12,36,1},{12,36,1},{12,31,2},{20,3,162},{9,35,1},{9,35,1},{8,29,2},{30,6,162},{8,29,2},{24,2,200},{11,40,2},{13,33,5},{11,33,5},{24,2,200},{27,17,200},{11,33,5},{0,31,202},{27,17,200},{0,31,202},{11,0,208},
+{11,0,208},{11,0,208},{11,0,208},{10,31,16},{10,31,16},{10,31,16},{10,27,16},{6,32,2},{6,32,2},{12,47,420},{12,42,220},{12,36,286},{12,35,223},{10,49,739},{10,40,260},{10,36,24},{10,33,280},{3,46,727},{7,33,202},{13,44,203},{13,40,19},{13,36,14},{13,35,21},{24,1,723},{8,43,202},{10,36,8},{7,33,201},{31,12,723},{7,33,201},{12,41,218},{12,41,218},{12,41,218},
+{12,34,219},{11,39,178},{10,37,17},{10,37,17},{10,31,21},{5,40,164},{8,31,21},{13,38,1},{13,38,1},{13,38,1},{13,33,2},{21,5,162},{10,37,1},{10,37,1},{9,31,2},{31,8,162},{9,31,2},{25,4,200},{12,42,2},{14,35,5},{12,35,5},{25,4,200},{28,19,200},{12,35,5},{0,33,200},{28,19,200},{0,33,200},{12,0,218},{12,0,218},{12,0,218},{12,0,218},{11,33,16},
+{11,33,16},{11,33,16},{11,29,16},{7,33,2},{7,33,2},{13,49,420},{13,44,220},{13,38,286},{13,37,223},{11,51,739},{11,42,260},{11,38,24},{11,35,280},{4,48,729},{8,35,201},{14,46,203},{14,42,19},{14,38,14},{14,37,21},{26,0,723},{9,45,202},{11,38,8},{8,35,201},{31,15,723},{8,35,201},{13,43,218},{13,43,218},{13,43,218},{13,36,219},{11,44,178},{11,39,17},{11,39,17},
+{11,32,21},{6,42,164},{9,33,17},{14,40,1},{14,40,1},{14,40,1},{14,35,2},{24,0,162},{11,39,1},{11,39,1},{10,33,4},{31,11,162},{10,33,4},{26,6,200},{13,44,2},{15,37,5},{13,37,5},{26,6,200},{29,21,200},{13,37,5},{0,35,200},{29,21,200},{0,35,200},{13,0,218},{13,0,218},{13,0,218},{13,0,218},{11,38,16},{11,38,16},{11,38,16},{11,32,17},{8,35,1},
+{8,35,1},{14,52,408},{14,46,212},{14,41,282},{14,39,217},{12,53,739},{12,44,259},{12,40,27},{12,37,267},{6,49,727},{9,37,207},{15,49,200},{15,44,20},{15,40,17},{15,39,18},{26,6,723},{10,48,203},{12,40,11},{10,37,203},{29,21,723},{10,37,203},{14,46,208},{14,46,208},{14,46,208},{14,39,208},{13,43,178},{12,41,18},{12,41,18},{12,35,21},{7,44,163},{10,35,18},{15,42,1},
+{15,42,1},{15,42,1},{15,38,1},{24,6,162},{12,41,2},{12,41,2},{11,35,2},{29,17,162},{11,35,2},{28,5,200},{13,48,2},{16,40,5},{13,40,1},{28,5,200},{31,22,200},{13,40,1},{0,37,202},{31,22,200},{0,37,202},{14,0,208},{14,0,208},{14,0,208},{14,0,208},{13,37,16},{13,37,16},{13,37,16},{13,33,16},{9,38,2},{9,38,2},{15,54,408},{15,48,210},{15,43,282},
+{15,41,217},{13,55,739},{13,46,259},{13,42,27},{13,39,267},{7,51,727},{10,39,207},{16,50,203},{16,47,18},{16,42,11},{16,41,26},{29,1,723},{11,49,203},{13,42,11},{11,39,203},{30,23,723},{11,39,203},{15,47,209},{15,47,209},{15,47,209},{15,41,208},{14,45,178},{13,43,18},{13,43,18},{13,37,21},{8,46,164},{11,37,18},{16,44,1},{16,44,1},{16,44,1},{16,39,2},{27,1,162},
+{13,43,2},{13,43,2},{12,37,2},{30,19,162},{12,37,2},{31,0,200},{15,48,2},{17,42,5},{14,42,1},{31,0,200},{28,29,200},{14,42,1},{0,39,202},{28,29,200},{0,39,202},{15,0,208},{15,0,208},{15,0,208},{15,0,208},{14,39,16},{14,39,16},{14,39,16},{14,35,16},{10,40,2},{10,40,2},{16,56,418},{16,50,220},{16,44,283},{16,43,228},{14,57,739},{14,48,260},{14,44,27},
+{14,41,267},{7,54,727},{11,41,207},{17,52,203},{17,48,19},{17,44,11},{17,43,26},{30,3,723},{12,51,202},{14,44,11},{12,41,203},{31,25,723},{12,41,203},{16,49,218},{16,49,218},{16,49,218},{16,43,219},{15,47,178},{14,45,18},{14,45,18},{14,39,21},{9,48,164},{12,39,21},{17,46,1},{17,46,1},{17,46,1},{17,41,2},{28,3,162},{14,45,2},{14,45,2},{13,39,2},{31,21,162},
+{13,39,2},{30,9,200},{16,50,2},{18,44,5},{15,44,1},{30,9,200},{29,31,200},{15,44,1},{0,41,202},{29,31,200},{0,41,202},{16,0,218},{16,0,218},{16,0,218},{16,0,218},{15,41,16},{15,41,16},{15,41,16},{15,37,16},{11,42,2},{11,42,2},{17,58,418},{17,52,220},{17,46,283},{17,45,228},{15,59,739},{15,50,260},{15,46,27},{15,43,267},{8,56,724},{12,43,206},{18,54,203},
+{18,50,19},{18,46,11},{18,45,26},{31,5,723},{13,53,202},{15,46,11},{13,43,203},{31,28,723},{13,43,203},{17,51,218},{17,51,218},{17,51,218},{17,45,219},{15,52,178},{15,47,18},{15,47,18},{15,41,21},{10,50,164},{13,41,21},{18,48,1},{18,48,1},{18,48,1},{18,43,2},{29,5,162},{15,47,2},{15,47,2},{14,41,2},{31,24,162},{14,41,2},{31,11,200},{17,52,2},{19,46,5},
+{16,46,1},{31,11,200},{29,34,200},{16,46,1},{0,43,202},{29,34,200},{0,43,202},{17,0,218},{17,0,218},{17,0,218},{17,0,218},{15,46,17},{15,46,17},{15,46,17},{15,40,16},{12,44,2},{12,44,2},{18,60,410},{18,54,212},{18,49,282},{18,48,218},{17,58,739},{16,52,259},{16,48,27},{16,45,273},{10,57,724},{13,46,208},{19,57,200},{19,52,20},{19,48,17},{19,47,25},{31,11,723},
+{14,56,203},{16,48,11},{14,45,208},{29,34,723},{14,45,208},{18,54,208},{18,54,208},{18,54,208},{18,47,208},{17,51,178},{16,49,18},{16,49,18},{16,43,20},{11,52,163},{14,44,24},{19,50,1},{19,50,1},{19,50,1},{19,46,0},{31,4,162},{16,49,2},{16,49,2},{15,43,4},{30,29,162},{15,43,4},{30,20,200},{18,54,4},{20,48,5},{17,48,1},{30,20,200},{31,35,200},{17,48,1},
+{0,45,208},{31,35,200},{0,45,208},{18,0,208},{18,0,208},{18,0,208},{18,0,208},{17,45,17},{17,45,17},{17,45,17},{17,41,16},{13,46,0},{13,46,0},{19,62,410},{19,56,212},{19,51,282},{19,49,217},{18,60,739},{17,54,259},{17,50,27},{17,47,273},{11,59,724},{14,47,218},{20,59,201},{20,55,18},{20,50,11},{20,49,26},{31,16,723},{15,58,203},{17,50,11},{15,47,208},{30,36,723},
+{15,47,208},{19,56,208},{19,56,208},{19,56,208},{19,49,208},{18,53,178},{17,51,18},{17,51,18},{17,45,20},{12,54,164},{15,46,24},{20,52,1},{20,52,1},{20,52,1},{20,48,2},{30,13,162},{17,51,2},{17,51,2},{16,45,1},{31,31,162},{16,45,1},{31,22,200},{19,56,4},{21,50,5},{18,50,1},{31,22,200},{28,42,200},{18,50,1},{0,47,208},{28,42,200},{0,47,208},{19,0,208},
+{19,0,208},{19,0,208},{19,0,208},{18,47,17},{18,47,17},{18,47,17},{18,43,16},{14,48,2},{14,48,2},{20,63,426},{20,58,223},{20,52,283},{20,51,228},{19,62,739},{18,56,259},{18,52,27},{18,49,267},{12,61,727},{15,49,207},{21,61,201},{21,57,18},{21,52,11},{21,51,26},{31,21,723},{16,60,203},{18,52,11},{16,49,203},{31,38,723},{16,49,203},{20,57,219},{20,57,219},{20,57,219},
+{20,51,219},{19,55,178},{18,53,18},{18,53,18},{18,47,20},{13,56,164},{16,47,17},{21,54,1},{21,54,1},{21,54,1},{21,49,2},{31,15,162},{18,53,2},{18,53,2},{17,47,1},{31,34,162},{17,47,1},{31,27,200},{19,60,4},{22,52,5},{19,52,1},{31,27,200},{29,44,200},{19,52,1},{0,49,202},{29,44,200},{0,49,202},{20,0,218},{20,0,218},{20,0,218},{20,0,218},{19,49,16},
+{19,49,16},{19,49,16},{19,45,16},{15,50,2},{15,50,2},{21,63,468},{21,60,223},{21,54,283},{21,53,228},{20,63,749},{19,58,259},{19,54,27},{19,51,267},{13,63,727},{16,51,206},{22,63,201},{22,59,18},{22,54,11},{22,53,26},{30,30,723},{17,62,203},{19,54,11},{17,51,203},{31,41,723},{17,51,203},{21,59,219},{21,59,219},{21,59,219},{21,53,219},{19,60,180},{19,55,18},{19,55,18},
+{19,49,21},{14,58,164},{17,49,21},{22,56,1},{22,56,1},{22,56,1},{22,51,2},{31,20,162},{19,55,2},{19,55,2},{18,49,2},{31,37,162},{18,49,2},{31,32,200},{20,62,1},{23,54,5},{20,54,1},{31,32,200},{30,46,200},{20,54,1},{0,51,202},{30,46,200},{0,51,202},{21,0,218},{21,0,218},{21,0,218},{21,0,218},{19,54,17},{19,54,17},{19,54,17},{19,48,16},{16,52,2},
+{16,52,2},{22,63,570},{22,63,209},{22,57,288},{22,56,212},{21,63,804},{20,61,254},{20,56,33},{20,53,273},{15,63,753},{17,54,208},{23,63,232},{23,61,13},{23,56,16},{23,55,25},{31,32,723},{19,62,212},{20,56,17},{18,53,208},{30,46,723},{18,53,208},{22,62,208},{22,62,208},{22,62,208},{22,55,208},{20,63,178},{20,57,17},{20,57,17},{20,51,20},{15,60,163},{18,52,24},{23,59,0},
+{23,59,0},{23,59,0},{23,54,0},{31,26,162},{20,57,1},{20,57,1},{19,51,4},{30,42,162},{19,51,4},{31,38,200},{22,63,1},{24,56,1},{21,56,1},{31,38,200},{31,48,200},{21,56,1},{0,53,208},{31,48,200},{0,53,208},{22,0,208},{22,0,208},{22,0,208},{22,0,208},{20,57,16},{20,57,16},{20,57,16},{21,49,16},{17,54,0},{17,54,0},{23,63,696},{23,63,237},{23,59,288},
+{23,58,212},{23,63,888},{21,63,254},{21,58,33},{21,55,273},{17,63,824},{18,56,208},{24,63,273},{24,62,21},{24,58,17},{24,57,26},{30,41,723},{20,63,233},{21,58,17},{19,55,208},{29,50,723},{19,55,208},{23,63,212},{23,63,212},{23,63,212},{23,57,208},{22,61,180},{21,59,17},{21,59,17},{21,53,20},{16,62,163},{19,54,24},{24,60,2},{24,60,2},{24,60,2},{24,56,2},{31,31,162},
+{21,59,1},{21,59,1},{20,53,1},{31,44,162},{20,53,1},{30,47,200},{24,62,20},{25,58,1},{22,58,1},{30,47,200},{31,51,200},{22,58,1},{0,55,208},{31,51,200},{0,55,208},{23,0,208},{23,0,208},{23,0,208},{23,0,208},{21,59,16},{21,59,16},{21,59,16},{22,51,16},{18,56,0},{18,56,0},{25,63,804},{24,63,334},{24,61,283},{24,60,227},{24,63,957},{22,63,297},{22,60,33},
+{22,57,273},{20,63,913},{19,58,208},{26,63,313},{25,63,51},{25,60,17},{25,59,26},{31,43,723},{22,63,281},{22,60,17},{19,58,208},{30,52,723},{19,58,208},{24,63,234},{24,63,234},{24,63,234},{24,59,218},{23,63,180},{22,61,17},{22,61,17},{22,55,20},{18,62,171},{20,55,17},{25,62,2},{25,62,2},{25,62,2},{25,58,2},{31,36,162},{22,61,1},{22,61,1},{21,55,1},{31,47,162},
+{21,55,1},{30,52,200},{25,63,50},{26,60,1},{23,60,1},{30,52,200},{28,58,200},{23,60,1},{0,57,208},{28,58,200},{0,57,208},{24,0,218},{24,0,218},{24,0,218},{24,0,218},{22,61,16},{22,61,16},{22,61,16},{23,53,16},{19,58,0},{19,58,0},{26,63,930},{25,63,492},{25,63,283},{25,62,227},{25,63,1068},{24,63,389},{23,62,33},{23,59,273},{21,63,999},{20,60,209},{27,63,379},
+{26,63,149},{26,62,17},{26,61,26},{31,48,723},{24,63,364},{24,62,16},{20,60,208},{31,54,723},{20,60,208},{25,63,267},{25,63,267},{25,63,267},{25,61,218},{24,63,205},{23,63,17},{23,63,17},{23,57,20},{20,63,189},{21,57,17},{26,63,5},{26,63,5},{26,63,5},{26,60,2},{30,45,162},{23,63,1},{23,63,1},{22,57,1},{31,50,162},{22,57,1},{31,54,200},{27,63,90},{27,62,1},
+{24,62,0},{31,54,200},{29,60,200},{24,62,0},{0,59,208},{29,60,200},{0,59,208},{25,0,218},{25,0,218},{25,0,218},{25,0,218},{23,63,16},{23,63,16},{23,63,16},{23,56,17},{20,60,1},{20,60,1},{27,63,877},{26,63,585},{26,63,329},{26,63,209},{26,63,990},{25,63,397},{25,63,36},{24,61,165},{23,63,910},{22,61,122},{28,63,306},{28,63,162},{27,63,36},{27,63,4},{30,56,546},
+{26,63,306},{25,63,20},{22,61,113},{30,58,546},{22,61,113},{26,63,329},{26,63,329},{26,63,329},{26,63,209},{25,63,276},{25,63,36},{25,63,36},{24,59,18},{22,63,230},{22,60,22},{27,63,36},{27,63,36},{27,63,36},{27,62,0},{29,54,162},{25,63,20},{25,63,20},{24,59,2},{29,56,162},{24,59,2},{31,58,113},{29,63,61},{28,63,0},{26,63,1},{31,58,113},{31,60,113},{26,63,1},
+{0,61,113},{31,60,113},{0,61,113},{26,0,208},{26,0,208},{26,0,208},{26,0,208},{25,62,16},{25,62,16},{25,62,16},{25,57,17},{21,62,1},{21,62,1},{28,63,731},{27,63,573},{27,63,404},{27,63,244},{27,63,797},{26,63,354},{26,63,98},{25,62,57},{25,63,737},{23,62,38},{29,63,190},{29,63,126},{28,63,65},{28,63,5},{31,56,333},{28,63,185},{27,63,52},{24,62,26},{30,60,333},
+{24,62,26},{27,63,404},{27,63,404},{27,63,404},{27,63,244},{27,63,356},{26,63,98},{26,63,98},{25,61,18},{24,63,315},{23,62,22},{28,63,65},{28,63,65},{28,63,65},{28,63,5},{30,56,162},{27,63,52},{27,63,52},{25,61,2},{30,58,162},{25,61,2},{31,61,25},{30,63,13},{30,63,4},{29,63,1},{31,61,25},{31,62,25},{29,63,1},{0,62,25},{31,62,25},{0,62,25},{27,0,208},
+{27,0,208},{27,0,208},{27,0,208},{26,63,17},{26,63,17},{26,63,17},{26,59,17},{23,63,9},{23,63,9},{29,63,642},{28,63,524},{28,63,443},{28,63,299},{28,63,623},{28,63,335},{27,63,201},{26,63,17},{27,63,610},{24,63,26},{30,63,131},{30,63,115},{29,63,101},{29,63,37},{31,59,193},{29,63,121},{28,63,85},{26,63,1},{30,62,193},{26,63,1},{28,63,443},{28,63,443},{28,63,443},
+{28,63,299},{28,63,398},{27,63,201},{27,63,201},{26,63,17},{26,63,378},{24,63,26},{29,63,101},{29,63,101},{29,63,101},{29,63,37},{31,57,145},{28,63,85},{28,63,85},{26,63,1},{31,60,145},{26,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{28,0,218},{28,0,218},{28,0,218},{28,0,218},{27,63,32},
+{27,63,32},{27,63,32},{27,61,17},{24,63,26},{24,63,26},{29,63,418},{29,63,354},{29,63,318},{29,63,254},{29,63,370},{28,63,223},{28,63,142},{28,63,25},{28,63,358},{26,63,58},{30,63,51},{30,63,35},{30,63,26},{30,63,10},{31,61,54},{30,63,34},{30,63,25},{28,63,0},{31,62,54},{28,63,0},{29,63,318},{29,63,318},{29,63,318},{29,63,254},{29,63,270},{28,63,142},{28,63,142},
+{28,63,25},{27,63,249},{26,63,58},{30,63,26},{30,63,26},{30,63,26},{30,63,10},{31,60,41},{30,63,25},{30,63,25},{28,63,0},{31,61,41},{28,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{29,0,218},{29,0,218},{29,0,218},{29,0,218},{28,63,61},{28,63,61},{28,63,61},{28,63,25},{26,63,58},
+{26,63,58},{0,18,421},{0,15,106},{0,10,8},{0,9,117},{0,12,925},{0,9,650},{0,9,286},{0,6,670},{0,7,1030},{0,5,726},{0,18,421},{0,15,106},{0,10,8},{0,9,117},{3,2,925},{0,9,650},{0,9,286},{0,6,670},{6,0,925},{0,6,670},{0,9,0},{0,9,0},{0,9,0},{0,5,1},{0,4,85},{0,4,45},{0,4,45},{0,2,50},{0,2,98},{0,2,59},{0,9,0},
+{0,9,0},{0,9,0},{0,5,1},{1,1,85},{0,4,45},{0,4,45},{0,2,50},{2,0,85},{0,2,50},{5,1,421},{0,15,106},{0,10,8},{0,9,117},{5,1,421},{9,0,421},{0,9,117},{0,7,421},{9,0,421},{0,7,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,24,421},{0,19,53},{0,13,8},
+{0,11,72},{0,16,1261},{0,12,805},{0,11,328},{0,7,822},{0,9,1438},{0,7,922},{0,24,421},{0,19,53},{0,13,8},{0,11,72},{3,6,1261},{0,12,805},{0,11,328},{0,7,822},{8,0,1261},{0,7,822},{0,14,0},{0,14,0},{0,14,0},{0,8,1},{0,7,221},{0,7,116},{0,7,116},{0,4,125},{0,4,257},{0,3,146},{0,14,0},{0,14,0},{0,14,0},{0,8,1},{2,0,221},
+{0,7,116},{0,7,116},{0,4,125},{3,1,221},{0,4,125},{7,0,421},{0,19,53},{1,12,8},{0,11,72},{7,0,421},{11,1,421},{0,11,72},{0,9,421},{11,1,421},{0,9,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,29,430},{0,22,34},{0,15,62},{0,14,49},{0,20,1514},{0,15,866},{0,13,301},
+{0,9,894},{0,11,1797},{0,9,1063},{0,29,430},{0,22,34},{1,15,33},{0,14,49},{6,0,1514},{0,15,866},{0,13,301},{0,9,894},{10,0,1514},{0,9,894},{0,19,10},{0,19,10},{0,19,10},{0,12,10},{0,11,338},{0,9,149},{0,9,149},{0,5,162},{0,5,419},{0,5,211},{0,19,10},{0,19,10},{0,19,10},{0,12,10},{3,1,338},{0,9,149},{0,9,149},{0,5,162},{3,3,338},
+{0,5,162},{8,2,421},{0,22,25},{2,14,8},{0,14,40},{8,2,421},{14,0,421},{0,14,40},{0,11,421},{14,0,421},{0,11,421},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,2},{0,1,2},{1,31,494},{1,24,98},{1,17,131},{1,16,110},{0,25,1517},{0,19,734},{0,15,157},{0,11,789},{0,14,1982},{0,11,1045},{1,31,430},
+{1,24,34},{2,16,35},{1,16,46},{7,2,1514},{0,19,734},{0,15,157},{0,11,789},{11,2,1514},{0,11,789},{1,21,74},{1,21,74},{1,21,74},{1,14,74},{0,16,338},{0,13,89},{0,13,89},{0,8,106},{0,8,514},{0,7,217},{1,21,10},{1,21,10},{1,21,10},{1,14,10},{3,6,338},{0,13,89},{0,13,89},{0,8,106},{8,0,338},{0,8,106},{10,0,421},{0,26,5},{3,16,5},
+{0,16,10},{10,0,421},{17,0,421},{0,16,10},{0,13,421},{17,0,421},{0,13,421},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,7,1},{0,7,1},{0,7,1},{0,4,1},{0,3,32},{0,3,32},{1,37,629},{1,28,213},{2,19,340},{1,18,216},{0,31,1517},{0,23,629},{0,18,54},{0,14,686},{0,17,2187},{0,13,1070},{3,30,437},{2,27,33},{3,19,29},{2,18,45},{9,1,1514},
+{0,23,629},{0,18,54},{0,14,686},{13,3,1514},{0,14,686},{1,27,209},{1,27,209},{1,27,209},{1,17,208},{0,22,338},{0,17,34},{0,17,34},{0,11,53},{0,11,666},{0,9,273},{3,21,16},{3,21,16},{3,21,16},{3,15,16},{6,2,338},{0,17,34},{0,17,34},{0,11,53},{11,0,338},{0,11,53},{12,0,421},{0,30,1},{4,18,8},{0,18,5},{12,0,421},{20,0,421},{0,18,5},
+{0,15,421},{20,0,421},{0,15,421},{1,0,208},{1,0,208},{1,0,208},{1,0,208},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{0,6,106},{0,6,106},{2,39,821},{2,30,405},{2,22,557},{2,20,408},{0,36,1517},{0,25,562},{0,21,14},{0,16,589},{0,19,2445},{0,15,1130},{3,35,437},{3,29,33},{4,21,33},{3,20,45},{10,3,1514},{0,25,562},{0,21,14},{0,16,589},{18,0,1514},
+{0,16,589},{2,29,401},{2,29,401},{2,29,401},{2,19,400},{0,27,340},{0,21,10},{0,21,10},{0,13,20},{0,14,851},{0,11,357},{3,26,16},{3,26,16},{3,26,16},{3,18,16},{8,0,338},{0,21,10},{0,21,10},{0,13,20},{11,3,338},{0,13,20},{13,1,421},{1,32,2},{5,20,8},{1,20,5},{13,1,421},{21,2,421},{1,20,5},{0,17,421},{21,2,421},{0,17,421},{2,0,400},
+{2,0,400},{2,0,400},{2,0,400},{0,19,0},{0,19,0},{0,19,0},{0,11,1},{0,9,205},{0,9,205},{3,41,854},{3,32,435},{3,24,590},{3,22,441},{1,38,1518},{0,29,543},{1,23,15},{0,18,575},{0,23,2318},{0,17,906},{4,37,430},{4,30,34},{5,23,33},{4,22,49},{12,1,1514},{0,29,494},{1,23,14},{0,18,526},{19,2,1514},{0,18,526},{3,31,434},{3,31,434},{3,31,434},
+{3,21,433},{1,29,341},{1,23,11},{1,23,11},{1,15,21},{0,17,734},{0,15,230},{4,27,10},{4,27,10},{4,27,10},{4,20,10},{9,2,338},{0,25,2},{0,25,2},{0,15,5},{16,0,338},{0,15,5},{15,0,421},{3,32,2},{6,22,8},{2,22,5},{15,0,421},{25,0,421},{2,22,5},{0,19,421},{25,0,421},{0,19,421},{3,0,433},{3,0,433},{3,0,433},{3,0,433},{1,21,1},
+{1,21,1},{1,21,1},{1,13,2},{0,12,157},{0,12,157},{4,42,866},{4,34,450},{4,26,581},{4,24,458},{2,40,1518},{1,31,543},{2,25,15},{1,20,575},{0,27,2166},{0,20,706},{5,39,430},{5,32,34},{6,25,33},{5,24,49},{14,0,1514},{0,32,461},{2,25,14},{0,20,481},{20,4,1514},{0,20,481},{4,33,445},{4,33,445},{4,33,445},{4,23,445},{2,31,341},{2,25,11},{2,25,11},
+{2,17,27},{0,21,626},{0,17,102},{5,29,10},{5,29,10},{5,29,10},{5,22,10},{11,1,338},{1,27,2},{1,27,2},{0,17,2},{17,2,338},{0,17,2},{16,1,421},{3,36,2},{7,24,8},{3,24,5},{16,1,421},{27,1,421},{3,24,5},{0,21,421},{27,1,421},{0,21,421},{4,0,445},{4,0,445},{4,0,445},{4,0,445},{2,23,1},{2,23,1},{2,23,1},{2,15,2},{0,16,97},
+{0,16,97},{5,45,854},{5,36,438},{5,28,579},{5,26,446},{3,43,1514},{3,32,545},{3,27,9},{3,22,582},{0,31,2010},{0,22,546},{7,38,437},{6,35,33},{7,27,26},{6,26,50},{14,6,1514},{0,37,430},{3,27,9},{0,23,446},{26,0,1514},{0,23,446},{5,35,434},{5,35,434},{5,35,434},{5,25,434},{3,34,338},{3,27,8},{3,27,8},{3,19,20},{0,25,525},{0,19,45},{7,29,16},
+{7,29,16},{7,29,16},{7,23,16},{13,0,338},{2,29,0},{2,29,0},{1,20,4},{20,2,338},{1,20,4},{18,1,421},{4,38,1},{8,26,10},{4,27,2},{18,1,421},{29,2,421},{4,27,2},{0,23,421},{29,2,421},{0,23,421},{5,0,433},{5,0,433},{5,0,433},{5,0,433},{3,25,1},{3,25,1},{3,25,1},{3,17,1},{0,19,41},{0,19,41},{6,47,854},{6,38,438},{6,30,579},
+{6,28,446},{4,45,1515},{3,36,553},{4,29,15},{3,24,589},{0,34,1887},{0,25,450},{7,44,437},{7,37,33},{8,29,30},{7,28,50},{16,4,1514},{0,40,422},{4,29,14},{0,25,425},{27,2,1514},{0,25,425},{6,37,434},{6,37,434},{6,37,434},{6,27,434},{4,35,341},{4,29,14},{4,29,14},{4,21,21},{0,29,461},{0,22,41},{7,34,16},{7,34,16},{7,34,16},{7,26,16},{14,2,338},
+{3,31,0},{3,31,0},{2,22,4},{24,0,338},{2,22,4},{19,3,421},{5,40,1},{8,29,5},{5,29,2},{19,3,421},{30,4,421},{5,29,2},{0,25,421},{30,4,421},{0,25,421},{6,0,433},{6,0,433},{6,0,433},{6,0,433},{4,27,1},{4,27,1},{4,27,1},{4,19,2},{0,23,13},{0,23,13},{7,49,854},{7,40,438},{7,32,590},{7,30,446},{5,47,1515},{4,37,543},{5,31,15},
+{4,26,591},{0,36,1785},{0,27,422},{8,45,430},{8,38,34},{9,31,30},{8,30,43},{17,6,1514},{1,42,422},{5,31,14},{0,27,422},{28,4,1514},{0,27,422},{7,39,434},{7,39,434},{7,39,434},{7,29,434},{5,37,341},{5,31,14},{5,31,14},{5,23,21},{0,32,404},{1,24,41},{8,35,10},{8,35,10},{8,35,10},{8,28,9},{16,0,338},{4,33,2},{4,33,2},{3,24,4},{26,1,338},
+{3,24,4},{21,1,421},{6,42,1},{9,31,5},{6,31,2},{21,1,421},{31,6,421},{6,31,2},{0,27,421},{31,6,421},{0,27,421},{7,0,433},{7,0,433},{7,0,433},{7,0,433},{5,29,1},{5,29,1},{5,29,1},{5,21,2},{0,27,1},{0,27,1},{8,50,866},{8,42,450},{8,34,581},{8,32,458},{6,48,1518},{5,39,543},{6,33,15},{5,28,591},{0,40,1685},{1,29,422},{9,47,430},
+{9,40,34},{10,33,33},{9,32,49},{20,1,1514},{2,44,422},{6,33,14},{1,29,422},{29,6,1514},{1,29,422},{8,41,445},{8,41,445},{8,41,445},{8,31,446},{6,39,341},{6,33,11},{6,33,11},{6,25,21},{0,35,371},{2,26,41},{9,37,10},{9,37,10},{9,37,10},{9,30,9},{17,2,338},{5,35,2},{5,35,2},{5,25,5},{27,3,338},{5,25,5},{23,0,421},{7,44,1},{11,32,8},
+{7,32,5},{23,0,421},{31,9,421},{7,32,5},{0,29,421},{31,9,421},{0,29,421},{8,0,445},{8,0,445},{8,0,445},{8,0,445},{6,31,1},{6,31,1},{6,31,1},{6,23,2},{1,29,1},{1,29,1},{9,53,854},{9,45,437},{9,36,579},{9,34,446},{7,51,1514},{7,41,546},{7,35,9},{6,31,589},{0,44,1607},{2,31,430},{11,46,437},{10,43,36},{11,35,26},{10,34,50},{22,0,1514},
+{3,47,421},{7,35,9},{3,31,426},{31,7,1514},{3,31,426},{9,43,434},{9,43,434},{9,43,434},{9,33,434},{7,42,338},{7,35,8},{7,35,8},{7,27,18},{0,39,344},{3,29,42},{11,37,16},{11,37,16},{11,37,16},{10,32,16},{19,1,338},{6,37,0},{6,37,0},{5,28,1},{29,4,338},{5,28,1},{24,2,421},{8,46,1},{12,34,10},{8,35,2},{24,2,421},{30,14,421},{8,35,2},
+{0,31,425},{30,14,421},{0,31,425},{9,0,433},{9,0,433},{9,0,433},{9,0,433},{7,33,1},{7,33,1},{7,33,1},{7,26,1},{2,32,2},{2,32,2},{10,55,854},{10,47,437},{10,38,579},{10,36,446},{8,53,1515},{7,43,561},{8,37,15},{7,32,589},{0,47,1577},{3,33,425},{11,52,437},{11,45,36},{12,37,30},{11,36,50},{23,2,1514},{4,48,422},{8,37,14},{3,33,425},{28,14,1514},
+{3,33,425},{10,45,434},{10,45,434},{10,45,434},{10,35,434},{8,43,341},{8,37,14},{8,37,14},{8,29,19},{0,43,340},{4,30,38},{11,42,16},{11,42,16},{11,42,16},{11,34,16},{20,3,338},{7,39,0},{7,39,0},{6,30,1},{30,6,338},{6,30,1},{26,1,421},{9,48,1},{12,37,5},{9,37,2},{26,1,421},{30,17,421},{9,37,2},{0,33,421},{30,17,421},{0,33,421},{10,0,433},
+{10,0,433},{10,0,433},{10,0,433},{8,35,1},{8,35,1},{8,35,1},{8,28,2},{3,34,2},{3,34,2},{11,57,854},{11,48,438},{11,40,579},{11,38,446},{9,55,1515},{8,46,555},{9,39,15},{8,34,591},{0,51,1530},{4,35,422},{12,53,430},{12,46,34},{13,39,30},{12,38,43},{24,4,1514},{5,50,422},{9,39,14},{4,35,422},{28,17,1514},{4,35,422},{11,47,434},{11,47,434},{11,47,434},
+{11,37,434},{9,45,341},{9,39,14},{9,39,14},{9,31,19},{1,45,340},{5,32,41},{12,44,9},{12,44,9},{12,44,9},{12,36,9},{21,5,338},{8,41,1},{8,41,1},{7,32,4},{31,8,338},{7,32,4},{27,3,421},{10,50,1},{13,39,5},{10,39,2},{27,3,421},{31,19,421},{10,39,2},{0,35,421},{31,19,421},{0,35,421},{11,0,433},{11,0,433},{11,0,433},{11,0,433},{9,37,1},
+{9,37,1},{9,37,1},{9,30,2},{4,35,1},{4,35,1},{12,58,866},{12,50,450},{12,41,590},{12,40,458},{10,57,1515},{9,48,555},{10,41,15},{9,36,591},{0,54,1518},{5,37,422},{13,55,430},{13,48,34},{14,41,30},{13,40,43},{25,6,1514},{6,52,422},{10,41,14},{5,37,422},{29,19,1514},{5,37,422},{12,49,445},{12,49,445},{12,49,445},{12,39,446},{10,47,341},{10,41,14},{10,41,14},
+{10,33,21},{2,47,340},{6,34,41},{13,46,9},{13,46,9},{13,46,9},{13,38,9},{24,0,338},{9,43,1},{9,43,1},{9,33,5},{31,11,338},{9,33,5},{29,1,421},{11,52,1},{14,41,5},{11,41,2},{29,1,421},{31,22,421},{11,41,2},{0,37,421},{31,22,421},{0,37,421},{12,0,445},{12,0,445},{12,0,445},{12,0,445},{10,39,1},{10,39,1},{10,39,1},{10,31,5},{5,37,1},
+{5,37,1},{13,61,854},{13,53,437},{13,44,593},{13,43,442},{11,59,1517},{11,49,546},{11,43,13},{10,39,589},{1,57,1518},{6,39,430},{15,54,437},{14,51,36},{15,43,25},{14,42,48},{27,5,1514},{7,55,421},{11,43,13},{7,39,426},{31,20,1514},{7,39,426},{13,51,434},{13,51,434},{13,51,434},{13,42,434},{11,50,338},{11,43,13},{11,43,13},{11,35,18},{4,47,341},{7,37,42},{15,45,16},
+{15,45,16},{15,45,16},{15,39,17},{24,6,338},{10,45,1},{10,45,1},{9,36,1},{29,17,338},{9,36,1},{31,0,421},{12,54,1},{16,43,4},{12,43,0},{31,0,421},{30,27,421},{12,43,0},{0,39,425},{30,27,421},{0,39,425},{13,0,433},{13,0,433},{13,0,433},{13,0,433},{11,41,1},{11,41,1},{11,41,1},{11,34,1},{6,40,1},{6,40,1},{14,63,854},{14,55,437},{14,46,593},
+{14,45,442},{12,61,1515},{11,51,561},{12,45,19},{11,41,589},{2,59,1518},{7,41,430},{15,60,437},{15,53,36},{16,45,34},{15,44,48},{30,0,1514},{9,55,425},{12,45,18},{8,41,426},{28,27,1514},{8,41,426},{14,53,434},{14,53,434},{14,53,434},{14,44,434},{12,51,341},{12,46,17},{12,46,17},{12,37,19},{4,51,340},{8,38,38},{15,50,16},{15,50,16},{15,50,16},{15,42,17},{27,1,338},
+{11,47,1},{11,47,1},{10,38,1},{30,19,338},{10,38,1},{31,6,421},{13,56,1},{17,45,4},{13,45,0},{31,6,421},{31,29,421},{13,45,0},{0,41,425},{31,29,421},{0,41,425},{14,0,433},{14,0,433},{14,0,433},{14,0,433},{12,43,1},{12,43,1},{12,43,1},{12,36,2},{7,42,1},{7,42,1},{15,63,878},{15,57,437},{15,48,579},{15,47,442},{13,63,1515},{12,54,555},{13,47,19},
+{12,43,574},{3,61,1518},{8,43,429},{16,61,430},{16,54,34},{17,47,34},{16,46,41},{31,2,1514},{10,57,425},{13,47,18},{9,43,426},{29,29,1514},{9,43,426},{15,55,434},{15,55,434},{15,55,434},{15,46,434},{13,53,341},{13,47,19},{13,47,19},{13,39,19},{5,53,340},{9,40,38},{16,52,9},{16,52,9},{16,52,9},{16,44,10},{28,3,338},{12,49,1},{12,49,1},{11,40,1},{31,21,338},
+{11,40,1},{31,11,421},{14,58,1},{18,47,4},{14,47,0},{31,11,421},{31,32,421},{14,47,0},{0,43,425},{31,32,421},{0,43,425},{15,0,433},{15,0,433},{15,0,433},{15,0,433},{13,45,1},{13,45,1},{13,45,1},{13,38,2},{8,43,4},{8,43,4},{16,63,926},{16,58,450},{16,49,590},{16,48,458},{14,63,1542},{13,56,555},{14,49,15},{13,45,574},{4,62,1517},{9,45,429},{17,63,430},
+{17,56,34},{18,49,30},{17,48,43},{30,11,1514},{11,59,425},{14,49,14},{10,45,426},{30,31,1514},{10,45,426},{16,57,445},{16,57,445},{16,57,445},{16,47,446},{14,55,341},{14,49,14},{14,49,14},{14,41,19},{6,55,340},{10,42,38},{17,54,9},{17,54,9},{17,54,9},{17,46,10},{29,5,338},{13,51,1},{13,51,1},{12,42,1},{31,24,338},{12,42,1},{31,16,421},{15,60,1},{18,49,5},
+{15,49,2},{31,16,421},{31,35,421},{15,49,2},{0,45,425},{31,35,421},{0,45,425},{16,0,445},{16,0,445},{16,0,445},{16,0,445},{14,47,1},{14,47,1},{14,47,1},{14,40,2},{9,45,4},{9,45,4},{17,63,1034},{17,61,438},{17,52,593},{17,51,442},{16,63,1598},{15,57,554},{15,51,13},{15,47,577},{6,63,1535},{10,48,434},{19,63,437},{18,59,41},{19,51,25},{18,50,48},{29,20,1514},
+{11,63,422},{15,51,13},{11,47,433},{31,33,1514},{11,47,433},{17,60,433},{17,60,433},{17,60,433},{17,50,434},{15,58,338},{15,51,13},{15,51,13},{15,43,20},{7,57,339},{12,44,41},{19,53,16},{19,53,16},{19,53,16},{19,47,17},{31,4,338},{14,53,1},{14,53,1},{13,44,1},{30,29,338},{13,44,1},{31,22,421},{16,63,1},{20,51,4},{16,51,0},{31,22,421},{30,40,421},{16,51,0},
+{0,47,433},{30,40,421},{0,47,433},{17,0,433},{17,0,433},{17,0,433},{17,0,433},{15,49,1},{15,49,1},{15,49,1},{15,42,0},{10,48,1},{10,48,1},{18,63,1166},{18,63,438},{18,54,593},{18,53,442},{17,63,1643},{15,60,561},{16,53,19},{15,49,589},{8,63,1566},{11,49,430},{20,63,458},{19,61,41},{20,53,34},{19,52,48},{30,22,1514},{13,63,429},{16,53,18},{12,49,426},{28,40,1514},
+{12,49,426},{18,62,433},{18,62,433},{18,62,433},{18,52,434},{16,60,339},{16,54,17},{16,54,17},{16,45,26},{9,57,341},{13,46,41},{19,58,17},{19,58,17},{19,58,17},{19,50,17},{30,13,338},{15,55,1},{15,55,1},{14,46,1},{31,31,338},{14,46,1},{31,27,421},{18,63,5},{21,53,4},{17,53,0},{31,27,421},{31,42,421},{17,53,0},{0,49,425},{31,42,421},{0,49,425},{18,0,433},
+{18,0,433},{18,0,433},{18,0,433},{16,51,1},{16,51,1},{16,51,1},{16,44,1},{11,50,1},{11,50,1},{20,63,1326},{19,63,470},{19,56,593},{19,55,442},{18,63,1742},{16,62,546},{17,55,19},{16,51,574},{10,63,1638},{12,51,429},{21,63,506},{20,63,29},{21,55,34},{20,54,41},{31,24,1514},{15,63,461},{17,55,18},{13,51,426},{29,42,1514},{13,51,426},{19,63,434},{19,63,434},{19,63,434},
+{19,54,434},{17,62,339},{17,56,17},{17,56,17},{17,47,26},{10,59,341},{13,48,38},{20,60,9},{20,60,9},{20,60,9},{20,52,10},{31,15,338},{16,57,2},{16,57,2},{15,48,1},{31,34,338},{15,48,1},{31,32,421},{20,63,20},{22,55,4},{18,55,0},{31,32,421},{31,45,421},{18,55,0},{0,51,425},{31,45,421},{0,51,425},{19,0,433},{19,0,433},{19,0,433},{19,0,433},{17,53,1},
+{17,53,1},{17,53,1},{17,46,1},{12,51,4},{12,51,4},{21,63,1470},{20,63,561},{20,58,582},{20,57,461},{19,63,1895},{18,62,562},{18,57,19},{17,53,574},{12,63,1761},{13,53,429},{22,63,590},{21,63,59},{22,57,34},{21,56,41},{31,29,1514},{17,63,530},{18,57,18},{14,53,426},{30,44,1514},{14,53,426},{20,63,461},{20,63,461},{20,63,461},{20,55,446},{18,63,341},{18,58,17},{18,58,17},
+{18,49,19},{11,61,341},{14,50,38},{21,62,9},{21,62,9},{21,62,9},{21,54,10},{31,20,338},{17,59,2},{17,59,2},{16,50,1},{31,37,338},{16,50,1},{31,38,421},{21,63,50},{23,57,4},{19,57,0},{31,38,421},{31,48,421},{19,57,0},{0,53,425},{31,48,421},{0,53,425},{20,0,445},{20,0,445},{20,0,445},{20,0,445},{18,55,1},{18,55,1},{18,55,1},{18,48,2},{13,53,4},
+{13,53,4},{22,63,1674},{21,63,753},{21,60,586},{21,59,443},{21,63,2046},{19,63,629},{19,60,19},{19,55,577},{15,63,1917},{14,56,426},{24,63,674},{23,63,120},{23,60,29},{22,58,50},{31,35,1514},{19,63,629},{19,60,19},{14,56,425},{27,51,1514},{14,56,425},{21,63,497},{21,63,497},{21,63,497},{21,58,433},{19,63,388},{19,60,10},{19,60,10},{19,51,20},{12,63,347},{16,52,41},{23,61,17},
+{23,61,17},{23,61,17},{23,55,17},{31,26,338},{18,62,2},{18,62,2},{17,52,1},{30,42,338},{17,52,1},{31,44,421},{23,63,104},{24,59,5},{20,59,1},{31,44,421},{31,51,421},{20,59,1},{0,56,425},{31,51,421},{0,56,425},{21,0,433},{21,0,433},{21,0,433},{21,0,433},{19,58,0},{19,58,0},{19,58,0},{19,50,0},{14,56,1},{14,56,1},{23,63,1902},{22,63,995},{22,62,586},
+{22,61,443},{22,63,2235},{20,63,759},{20,61,15},{19,57,578},{17,63,2118},{15,58,426},{25,63,770},{24,63,250},{24,61,35},{23,60,50},{31,40,1514},{21,63,701},{20,61,14},{15,58,425},{31,49,1514},{15,58,425},{22,63,554},{22,63,554},{22,63,554},{22,60,433},{21,63,437},{20,61,14},{20,61,14},{20,53,26},{14,63,379},{17,54,41},{24,63,25},{24,63,25},{24,63,25},{23,59,17},{31,31,338},
+{19,63,4},{19,63,4},{18,54,1},{31,44,338},{18,54,1},{31,49,421},{25,63,169},{25,61,5},{21,61,1},{31,49,421},{30,56,421},{21,61,1},{0,58,425},{30,56,421},{0,58,425},{22,0,433},{22,0,433},{22,0,433},{22,0,433},{20,59,2},{20,59,2},{20,59,2},{20,52,1},{15,58,1},{15,58,1},{24,63,2045},{24,63,1233},{23,63,629},{23,63,442},{24,63,2360},{22,63,914},{21,63,14},
+{20,59,549},{19,63,2241},{16,60,401},{26,63,849},{25,63,395},{25,63,34},{24,62,41},{29,52,1459},{23,63,778},{21,63,13},{17,59,400},{28,56,1459},{17,59,400},{23,63,629},{23,63,629},{23,63,629},{23,62,433},{22,63,491},{21,63,14},{21,63,14},{21,55,26},{16,63,446},{18,56,41},{25,63,34},{25,63,34},{25,63,34},{24,60,10},{31,36,338},{21,63,13},{21,63,13},{19,56,1},{31,47,338},
+{19,56,1},{31,54,392},{27,63,218},{26,63,4},{22,63,0},{31,54,392},{29,60,392},{22,63,0},{0,59,400},{29,60,392},{0,59,400},{23,0,433},{23,0,433},{23,0,433},{23,0,433},{21,61,2},{21,61,2},{21,61,2},{21,54,1},{16,60,1},{16,60,1},{25,63,1767},{25,63,1167},{24,63,701},{24,63,449},{24,63,1976},{23,63,747},{22,63,66},{21,60,306},{20,63,1820},{17,61,217},{27,63,611},
+{26,63,317},{26,63,61},{25,63,10},{30,52,1064},{25,63,587},{23,63,41},{18,61,208},{28,58,1064},{18,61,208},{24,63,701},{24,63,701},{24,63,701},{24,63,449},{23,63,581},{22,63,66},{22,63,66},{22,57,26},{18,63,530},{19,58,41},{26,63,61},{26,63,61},{26,63,61},{25,62,10},{30,45,338},{23,63,41},{23,63,41},{20,58,1},{31,50,338},{20,58,1},{30,60,200},{28,63,106},{27,63,1},
+{25,63,1},{30,60,200},{31,59,200},{25,63,1},{0,60,208},{31,59,200},{0,60,208},{24,0,445},{24,0,445},{24,0,445},{24,0,445},{22,63,2},{22,63,2},{22,63,2},{22,56,1},{17,62,1},{17,62,1},{26,63,1542},{26,63,1122},{25,63,833},{25,63,497},{26,63,1647},{24,63,687},{24,63,203},{23,61,122},{22,63,1515},{19,62,78},{28,63,410},{28,63,266},{27,63,116},{27,63,20},{30,56,722},
+{26,63,402},{25,63,100},{20,62,65},{30,58,722},{20,62,65},{25,63,833},{25,63,833},{25,63,833},{25,63,497},{24,63,707},{24,63,203},{24,63,203},{23,60,17},{20,63,619},{19,61,46},{27,63,116},{27,63,116},{27,63,116},{27,63,20},{29,54,338},{25,63,100},{25,63,100},{22,60,2},{29,56,338},{22,60,2},{31,59,61},{29,63,37},{29,63,1},{27,63,4},{31,59,61},{31,61,61},{27,63,4},
+{0,62,65},{31,61,61},{0,62,65},{25,0,433},{25,0,433},{25,0,433},{25,0,433},{23,63,25},{23,63,25},{23,63,25},{23,58,1},{19,62,13},{19,62,13},{27,63,1406},{27,63,1134},{26,63,962},{26,63,602},{27,63,1454},{25,63,702},{25,63,341},{24,62,43},{24,63,1378},{20,63,35},{29,63,318},{28,63,250},{28,63,169},{28,63,61},{31,56,509},{28,63,313},{27,63,164},{22,63,10},{30,60,509},
+{22,63,10},{26,63,962},{26,63,962},{26,63,962},{26,63,602},{26,63,827},{25,63,341},{25,63,341},{24,62,27},{22,63,747},{20,63,35},{28,63,169},{28,63,169},{28,63,169},{28,63,61},{30,56,338},{27,63,164},{27,63,164},{23,62,2},{30,58,338},{23,62,2},{31,62,5},{31,63,9},{30,63,4},{30,63,0},{31,62,5},{31,62,9},{30,63,0},{0,63,9},{31,62,9},{0,63,9},{26,0,433},
+{26,0,433},{26,0,433},{26,0,433},{24,63,50},{24,63,50},{24,63,50},{24,60,1},{20,63,26},{20,63,26},{28,63,1135},{28,63,991},{27,63,874},{27,63,602},{28,63,1162},{26,63,618},{26,63,362},{25,63,5},{25,63,1087},{22,63,58},{30,63,219},{29,63,161},{29,63,125},{29,63,61},{30,62,294},{29,63,193},{28,63,117},{24,63,1},{31,60,297},{24,63,1},{27,63,874},{27,63,874},{27,63,874},
+{27,63,602},{27,63,730},{26,63,362},{26,63,362},{25,63,5},{24,63,681},{22,63,58},{29,63,125},{29,63,125},{29,63,125},{29,63,61},{31,56,221},{28,63,117},{28,63,117},{24,63,1},{31,59,221},{24,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{27,0,433},{27,0,433},{27,0,433},{27,0,433},{25,63,101},
+{25,63,101},{25,63,101},{25,62,1},{22,63,58},{22,63,58},{29,63,885},{28,63,751},{28,63,670},{28,63,526},{28,63,778},{27,63,483},{27,63,314},{26,63,10},{26,63,777},{24,63,117},{30,63,75},{30,63,59},{30,63,50},{30,63,34},{31,60,114},{29,63,81},{29,63,45},{27,63,0},{31,61,114},{27,63,0},{28,63,670},{28,63,670},{28,63,670},{28,63,526},{28,63,553},{27,63,314},{27,63,314},
+{26,63,10},{25,63,518},{24,63,117},{30,63,50},{30,63,50},{30,63,50},{30,63,34},{31,59,85},{29,63,45},{29,63,45},{27,63,0},{30,62,85},{27,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{28,0,445},{28,0,445},{28,0,445},{28,0,445},{27,63,145},{27,63,145},{27,63,145},{26,63,10},{24,63,117},
+{24,63,117},{0,26,882},{0,21,218},{0,15,16},{0,13,260},{0,17,1899},{0,13,1341},{0,11,593},{0,8,1380},{0,9,2113},{0,7,1513},{0,26,882},{0,21,218},{0,15,16},{0,13,260},{4,4,1896},{0,13,1341},{0,11,593},{0,8,1380},{7,2,1896},{0,8,1380},{0,12,0},{0,12,0},{0,12,0},{0,7,1},{0,6,162},{0,5,85},{0,5,85},{0,3,85},{0,3,186},{0,3,101},{0,12,0},
+{0,12,0},{0,12,0},{0,7,1},{1,3,162},{0,5,85},{0,5,85},{0,3,85},{3,0,162},{0,3,85},{6,6,882},{0,21,218},{0,15,16},{0,13,260},{6,6,882},{12,1,882},{0,13,260},{0,10,884},{12,1,882},{0,10,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,884},{0,25,146},{0,17,2},
+{0,15,185},{0,21,2355},{0,17,1539},{0,13,653},{0,10,1605},{0,11,2667},{0,9,1777},{0,31,884},{0,25,146},{0,17,2},{0,15,185},{5,4,2355},{0,17,1539},{0,13,653},{0,10,1605},{7,4,2355},{0,10,1605},{0,17,1},{0,17,1},{0,17,1},{0,10,1},{0,9,338},{0,8,180},{0,8,180},{0,5,180},{0,5,389},{0,5,229},{0,17,1},{0,17,1},{0,17,1},{0,10,1},{2,2,338},
+{0,8,180},{0,8,180},{0,5,180},{2,3,338},{0,5,180},{9,1,882},{0,25,146},{0,17,2},{0,15,185},{9,1,882},{13,3,882},{0,15,185},{0,12,884},{13,3,882},{0,12,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,36,884},{0,29,90},{0,19,37},{0,17,130},{0,25,2899},{0,19,1764},{0,16,733},
+{0,11,1853},{0,13,3325},{0,11,2109},{0,36,884},{0,29,90},{0,19,37},{0,17,130},{7,1,2899},{0,19,1764},{0,16,733},{0,11,1853},{12,0,2899},{0,11,1853},{0,23,0},{0,23,0},{0,23,0},{0,14,1},{0,11,580},{0,11,305},{0,11,305},{0,6,325},{0,6,667},{0,5,389},{0,23,0},{0,23,0},{0,23,0},{0,14,1},{2,5,578},{0,11,305},{0,11,305},{0,6,325},{5,1,578},
+{0,6,325},{10,3,882},{0,29,90},{1,19,2},{0,17,130},{10,3,882},{18,0,882},{0,17,130},{0,14,884},{18,0,882},{0,14,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,42,918},{0,32,81},{1,21,105},{0,20,109},{0,29,3051},{0,21,1707},{0,19,569},{0,13,1800},{0,16,3672},{0,13,2161},{1,38,888},
+{0,32,81},{1,21,41},{0,20,109},{8,2,3048},{0,21,1707},{0,19,569},{0,13,1800},{12,3,3048},{0,13,1800},{0,28,36},{0,28,36},{0,28,36},{0,17,37},{0,16,648},{0,13,269},{0,13,269},{0,9,292},{0,8,824},{0,7,417},{1,25,4},{1,25,4},{1,25,4},{1,16,5},{3,6,648},{0,13,269},{0,13,269},{0,9,292},{8,0,648},{0,9,292},{12,1,882},{0,32,45},{2,21,2},
+{0,20,73},{12,1,882},{19,2,882},{0,20,73},{0,16,890},{19,2,882},{0,16,890},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,4,0},{0,4,0},{0,4,0},{0,2,1},{0,2,10},{0,2,10},{1,44,997},{1,34,154},{1,24,229},{1,22,178},{0,35,3048},{0,25,1528},{0,21,324},{0,16,1605},{0,19,3907},{0,15,2138},{2,41,883},{2,32,86},{2,24,42},{1,22,114},{9,5,3048},
+{0,25,1528},{0,21,324},{0,16,1605},{15,3,3048},{0,16,1605},{1,31,113},{1,31,113},{1,31,113},{1,19,113},{0,22,648},{0,17,164},{0,17,164},{0,11,193},{0,11,976},{0,9,443},{2,27,2},{2,27,2},{2,27,2},{2,18,1},{6,2,648},{0,17,164},{0,17,164},{0,11,193},{11,0,648},{0,11,193},{13,4,882},{0,36,13},{3,23,4},{0,22,32},{13,4,882},{22,2,882},{0,22,32},
+{0,18,884},{22,2,882},{0,18,884},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,10,0},{0,10,0},{0,10,0},{0,6,0},{0,5,58},{0,5,58},{1,49,1173},{1,38,302},{2,26,421},{1,24,321},{0,40,3051},{0,29,1380},{0,23,186},{0,18,1464},{0,21,4201},{0,17,2149},{3,43,883},{3,34,86},{3,26,42},{2,24,114},{12,0,3048},{0,29,1380},{0,23,186},{0,18,1464},{20,0,3048},
+{0,18,1464},{1,36,289},{1,36,289},{1,36,289},{1,22,290},{0,27,650},{0,21,100},{0,21,100},{0,13,130},{0,14,1161},{0,13,491},{3,29,2},{3,29,2},{3,29,2},{3,20,1},{8,0,648},{0,21,100},{0,21,100},{0,13,130},{11,3,648},{0,13,130},{14,6,882},{0,40,1},{4,25,1},{0,25,16},{14,6,882},{26,0,882},{0,25,16},{0,20,884},{26,0,882},{0,20,884},{1,0,289},
+{1,0,289},{1,0,289},{1,0,289},{0,15,1},{0,15,1},{0,15,1},{0,9,1},{0,7,136},{0,7,136},{2,51,1365},{2,40,494},{2,28,722},{2,26,513},{0,46,3048},{0,32,1269},{0,27,82},{0,20,1341},{0,25,4525},{0,19,2197},{4,45,886},{3,38,90},{4,28,36},{3,26,114},{13,2,3048},{0,32,1269},{0,27,82},{0,20,1341},{21,2,3048},{0,20,1341},{2,38,481},{2,38,481},{2,38,481},
+{2,24,482},{0,32,650},{0,25,52},{0,25,52},{0,15,85},{0,17,1345},{0,15,569},{4,31,4},{4,31,4},{4,31,4},{4,22,5},{9,2,648},{0,25,52},{0,25,52},{0,15,85},{16,0,648},{0,15,85},{16,4,882},{1,42,1},{5,27,1},{0,27,1},{16,4,882},{27,2,882},{0,27,1},{0,22,884},{27,2,882},{0,22,884},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{0,21,0},
+{0,21,0},{0,21,0},{0,12,1},{0,9,250},{0,9,250},{2,57,1667},{2,44,786},{3,30,1042},{2,29,801},{0,51,3048},{0,36,1157},{0,29,20},{0,22,1236},{0,27,4891},{0,21,2281},{5,47,886},{4,41,86},{5,30,36},{4,28,116},{14,4,3048},{0,36,1157},{0,29,20},{0,22,1236},{25,0,3048},{0,22,1236},{2,43,785},{2,43,785},{2,43,785},{2,27,786},{0,38,648},{0,29,20},{0,29,20},
+{0,18,40},{0,19,1594},{0,16,677},{5,33,4},{5,33,4},{5,33,4},{5,24,5},{11,1,648},{0,29,20},{0,29,20},{0,18,40},{17,2,648},{0,18,40},{17,6,882},{2,44,1},{6,29,1},{1,29,1},{17,6,882},{28,4,882},{1,29,1},{0,24,884},{28,4,882},{0,24,884},{2,0,785},{2,0,785},{2,0,785},{2,0,785},{0,26,0},{0,26,0},{0,26,0},{0,16,1},{0,11,400},
+{0,11,400},{3,59,1784},{3,46,901},{4,32,1195},{3,31,910},{1,53,3055},{0,40,1094},{1,31,23},{0,25,1175},{0,31,4840},{0,23,2054},{6,49,883},{6,41,81},{6,32,42},{5,30,123},{14,10,3048},{0,40,1058},{1,31,19},{0,25,1139},{28,0,3048},{0,25,1139},{3,46,900},{3,46,900},{3,46,900},{3,30,900},{1,40,654},{1,31,22},{1,31,22},{1,20,38},{0,23,1560},{0,19,533},{6,35,2},
+{6,35,2},{6,35,2},{6,26,1},{13,0,648},{0,33,5},{0,33,5},{0,20,13},{20,2,648},{0,20,13},{19,5,882},{3,46,1},{7,31,5},{2,31,1},{19,5,882},{31,4,882},{2,31,1},{0,26,882},{31,4,882},{0,26,882},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{1,29,4},{1,29,4},{1,29,4},{1,18,4},{0,15,377},{0,15,377},{4,61,1772},{4,48,891},{5,34,1195},
+{4,33,906},{2,55,3055},{1,42,1094},{2,33,29},{1,27,1175},{0,34,4609},{0,26,1716},{7,51,883},{7,43,81},{7,34,42},{6,32,114},{18,1,3048},{0,44,990},{2,33,25},{0,27,1058},{29,2,3048},{0,27,1058},{4,47,891},{4,47,891},{4,47,891},{4,32,891},{2,42,654},{2,33,29},{2,33,29},{2,22,38},{0,27,1396},{0,21,347},{7,37,2},{7,37,2},{7,37,2},{7,28,1},{14,2,648},
+{0,37,1},{0,37,1},{0,23,5},{24,0,648},{0,23,5},{22,0,882},{4,48,1},{8,33,1},{3,33,0},{22,0,882},{31,7,882},{3,33,0},{0,28,882},{31,7,882},{0,28,882},{4,0,890},{4,0,890},{4,0,890},{4,0,890},{2,31,4},{2,31,4},{2,31,4},{2,20,4},{0,19,260},{0,19,260},{5,63,1772},{5,50,891},{6,36,1195},{5,35,906},{3,57,3055},{2,44,1094},{3,35,29},
+{2,29,1175},{0,38,4381},{0,29,1436},{8,53,886},{7,47,89},{8,36,36},{7,34,114},{19,3,3048},{0,47,949},{3,35,25},{0,29,995},{30,4,3048},{0,29,995},{5,49,890},{5,49,890},{5,49,890},{5,33,891},{3,44,654},{3,35,29},{3,35,29},{3,24,38},{0,29,1251},{0,24,221},{8,39,4},{8,39,4},{8,39,4},{8,30,4},{16,0,648},{1,39,1},{1,39,1},{0,25,2},{26,1,648},
+{0,25,2},{23,2,882},{5,50,1},{9,35,1},{4,35,1},{23,2,882},{28,14,882},{4,35,1},{0,30,882},{28,14,882},{0,30,882},{5,0,890},{5,0,890},{5,0,890},{5,0,890},{3,32,5},{3,32,5},{3,32,5},{3,22,4},{0,23,180},{0,23,180},{6,63,1790},{6,52,891},{7,38,1195},{6,37,906},{4,59,3057},{3,46,1094},{4,37,29},{3,31,1175},{0,42,4185},{0,31,1206},{9,55,886},
+{8,49,86},{9,38,36},{8,36,116},{20,5,3048},{0,51,907},{4,37,20},{0,31,950},{31,6,3048},{0,31,950},{6,51,890},{6,51,890},{6,51,890},{6,35,891},{4,46,657},{4,37,29},{4,37,29},{3,26,49},{0,34,1121},{0,27,117},{9,41,4},{9,41,4},{9,41,4},{9,32,5},{17,2,648},{2,41,1},{2,41,1},{1,27,2},{27,3,648},{1,27,2},{24,4,882},{6,52,1},{10,37,1},
+{5,37,1},{24,4,882},{28,17,882},{5,37,1},{0,32,884},{28,17,882},{0,32,884},{6,0,890},{6,0,890},{6,0,890},{6,0,890},{4,34,9},{4,34,9},{4,34,9},{4,24,10},{0,27,116},{0,27,116},{8,63,1844},{7,54,901},{8,40,1188},{7,39,910},{5,62,3052},{4,48,1094},{5,39,23},{4,33,1175},{0,44,3969},{0,33,1039},{10,57,885},{10,49,81},{10,40,35},{9,38,123},{23,1,3048},
+{0,55,888},{5,39,19},{0,34,907},{29,12,3048},{0,34,907},{7,54,900},{7,54,900},{7,54,900},{7,38,900},{5,48,654},{5,39,22},{5,39,22},{5,28,45},{0,38,990},{0,29,80},{10,43,2},{10,43,2},{10,43,2},{10,34,1},{19,1,648},{3,43,1},{3,43,1},{3,29,1},{29,4,648},{3,29,1},{27,0,882},{7,54,1},{11,39,5},{6,39,1},{27,0,882},{31,17,882},{6,39,1},
+{0,34,882},{31,17,882},{0,34,882},{7,0,900},{7,0,900},{7,0,900},{7,0,900},{5,37,4},{5,37,4},{5,37,4},{5,26,4},{0,31,58},{0,31,58},{9,63,1886},{8,56,892},{9,42,1188},{8,41,900},{6,63,3055},{5,50,1094},{6,41,23},{5,35,1175},{0,49,3804},{0,36,935},{11,59,885},{11,51,81},{11,42,35},{10,40,123},{23,6,3048},{0,58,883},{6,41,19},{0,36,886},{30,14,3048},
+{0,36,886},{8,55,891},{8,55,891},{8,55,891},{8,40,891},{6,50,654},{6,41,22},{6,41,22},{6,30,45},{0,40,889},{1,31,80},{11,45,2},{11,45,2},{11,45,2},{11,36,1},{20,3,648},{5,43,2},{5,43,2},{4,31,1},{30,6,648},{4,31,1},{27,5,882},{8,56,2},{12,41,2},{7,41,1},{27,5,882},{31,20,882},{7,41,1},{0,36,882},{31,20,882},{0,36,882},{8,0,890},
+{8,0,890},{8,0,890},{8,0,890},{6,39,4},{6,39,4},{6,39,4},{6,28,4},{0,34,25},{0,34,25},{10,63,1964},{9,58,892},{10,44,1188},{9,43,900},{7,63,3100},{6,52,1094},{7,43,23},{6,37,1175},{0,51,3640},{0,38,887},{12,61,886},{11,55,89},{12,44,38},{11,42,123},{26,1,3048},{1,60,883},{7,43,19},{0,38,883},{30,17,3048},{0,38,883},{9,57,891},{9,57,891},{9,57,891},
+{9,42,891},{7,52,654},{7,43,22},{7,43,22},{7,32,38},{0,44,801},{2,34,86},{12,47,4},{12,47,4},{12,47,4},{12,38,4},{21,5,648},{6,45,2},{6,45,2},{4,33,2},{31,8,648},{4,33,2},{30,0,882},{9,58,2},{13,43,2},{8,43,1},{30,0,882},{28,27,882},{8,43,1},{0,38,882},{28,27,882},{0,38,882},{9,0,890},{9,0,890},{9,0,890},{9,0,890},{7,41,4},
+{7,41,4},{7,41,4},{7,30,4},{0,38,5},{0,38,5},{11,63,2078},{10,60,892},{11,46,1188},{10,45,900},{9,63,3181},{7,54,1094},{8,45,35},{7,39,1175},{0,55,3496},{1,40,887},{13,63,886},{12,56,88},{13,46,38},{12,44,110},{27,3,3048},{2,62,883},{7,46,25},{1,40,883},{31,19,3048},{1,40,883},{10,59,891},{10,59,891},{10,59,891},{10,44,891},{8,54,657},{8,45,34},{8,45,34},
+{7,34,49},{0,48,756},{3,36,86},{13,49,4},{13,49,4},{13,49,4},{13,40,4},{24,0,648},{6,49,1},{6,49,1},{5,35,2},{31,11,648},{5,35,2},{31,2,882},{10,60,2},{14,45,2},{9,45,1},{31,2,882},{29,29,882},{9,45,1},{0,40,882},{29,29,882},{0,40,882},{10,0,890},{10,0,890},{10,0,890},{10,0,890},{8,42,9},{8,42,9},{8,42,9},{8,32,10},{0,42,1},
+{0,42,1},{12,63,2228},{11,63,902},{12,48,1188},{11,47,908},{10,63,3256},{8,57,1095},{9,47,33},{8,41,1164},{0,59,3364},{2,42,889},{14,63,915},{14,57,90},{14,48,35},{13,47,117},{29,2,3048},{4,63,886},{8,48,25},{3,42,885},{29,25,3048},{3,42,885},{11,62,900},{11,62,900},{11,62,900},{11,46,900},{9,57,652},{9,47,29},{9,47,29},{9,36,45},{0,51,691},{4,37,80},{14,51,2},
+{14,51,2},{14,51,2},{14,42,2},{24,6,648},{7,51,1},{7,51,1},{7,37,1},{29,17,648},{7,37,1},{31,8,882},{11,63,2},{15,47,8},{10,47,5},{31,8,882},{31,30,882},{10,47,5},{0,42,884},{31,30,882},{0,42,884},{11,0,900},{11,0,900},{11,0,900},{11,0,900},{9,45,4},{9,45,4},{9,45,4},{9,34,4},{1,44,1},{1,44,1},{13,63,2414},{12,63,907},{13,50,1188},
+{12,49,900},{11,63,3391},{9,59,1095},{10,49,23},{9,43,1164},{0,63,3276},{3,44,889},{15,63,981},{15,59,90},{15,50,35},{14,48,123},{31,1,3048},{6,63,906},{10,49,19},{4,44,885},{30,27,3048},{4,44,885},{12,63,891},{12,63,891},{12,63,891},{12,48,891},{10,59,652},{10,49,22},{10,49,22},{10,38,45},{0,55,659},{5,39,80},{15,53,2},{15,53,2},{15,53,2},{15,44,2},{27,1,648},
+{9,51,2},{9,51,2},{8,39,1},{30,19,648},{8,39,1},{29,20,882},{12,63,17},{16,49,2},{11,49,1},{29,20,882},{31,33,882},{11,49,1},{0,44,884},{31,33,882},{0,44,884},{12,0,890},{12,0,890},{12,0,890},{12,0,890},{10,47,4},{10,47,4},{10,47,4},{10,36,4},{2,46,1},{2,46,1},{15,63,2606},{13,63,987},{14,52,1188},{13,51,900},{13,63,3517},{10,61,1095},{11,51,23},
+{10,45,1164},{1,63,3300},{4,46,892},{17,63,1014},{15,63,94},{16,52,38},{15,50,123},{31,6,3048},{8,63,936},{11,51,19},{5,46,885},{31,29,3048},{5,46,885},{13,63,906},{13,63,906},{13,63,906},{13,50,891},{11,61,652},{11,51,22},{11,51,22},{11,40,45},{0,59,651},{6,41,80},{16,55,4},{16,55,4},{16,55,4},{16,46,5},{28,3,648},{10,53,2},{10,53,2},{9,41,1},{31,21,648},
+{9,41,1},{30,22,882},{14,63,37},{17,51,2},{12,51,1},{30,22,882},{28,40,882},{12,51,1},{0,46,884},{28,40,882},{0,46,884},{13,0,890},{13,0,890},{13,0,890},{13,0,890},{11,49,4},{11,49,4},{11,49,4},{11,38,4},{3,48,0},{3,48,0},{16,63,2792},{15,63,1079},{15,54,1188},{14,53,900},{14,63,3652},{11,63,1095},{12,53,35},{11,47,1164},{3,63,3436},{5,48,887},{18,63,1080},
+{17,62,102},{17,54,38},{16,52,110},{30,15,3048},{10,63,996},{11,54,25},{5,48,883},{31,32,3048},{5,48,883},{14,63,939},{14,63,939},{14,63,939},{14,52,891},{12,62,657},{12,53,34},{12,53,34},{12,42,50},{1,61,651},{7,43,80},{17,57,4},{17,57,4},{17,57,4},{17,48,4},{29,5,648},{11,55,2},{11,55,2},{10,43,1},{31,24,648},{10,43,1},{31,24,882},{16,63,80},{18,53,2},
+{13,53,1},{31,24,882},{29,42,882},{13,53,1},{0,48,882},{29,42,882},{0,48,882},{14,0,890},{14,0,890},{14,0,890},{14,0,890},{12,50,9},{12,50,9},{12,50,9},{12,40,9},{4,50,1},{4,50,1},{17,63,3038},{16,63,1268},{16,57,1186},{15,55,908},{15,63,3879},{12,63,1146},{13,55,33},{12,49,1164},{5,63,3667},{6,50,889},{19,63,1205},{18,63,147},{18,56,41},{17,55,117},{31,17,3048},
+{12,63,1110},{12,56,20},{7,50,885},{29,38,3048},{7,50,885},{16,63,979},{16,63,979},{16,63,979},{15,54,900},{13,63,670},{13,55,29},{13,55,29},{13,45,41},{2,63,648},{8,46,81},{18,60,1},{18,60,1},{18,60,1},{18,50,2},{31,4,648},{11,59,4},{11,59,4},{11,45,1},{30,29,648},{11,45,1},{31,30,882},{18,63,146},{19,56,5},{14,55,5},{31,30,882},{31,43,882},{14,55,5},
+{0,50,884},{31,43,882},{0,50,884},{15,0,900},{15,0,900},{15,0,900},{15,0,900},{13,53,4},{13,53,4},{13,53,4},{13,42,5},{5,52,1},{5,52,1},{18,63,3308},{17,63,1502},{17,59,1186},{16,57,898},{17,63,4077},{14,63,1230},{14,57,33},{13,51,1164},{8,63,3820},{7,52,889},{21,63,1368},{19,63,261},{19,58,41},{18,57,117},{30,26,3048},{14,63,1226},{13,58,20},{8,52,885},{30,40,3048},
+{8,52,885},{17,63,1018},{17,63,1018},{17,63,1018},{16,56,890},{14,63,724},{14,57,29},{14,57,29},{14,47,41},{4,63,665},{9,48,88},{19,62,1},{19,62,1},{19,62,1},{19,52,2},{30,13,648},{12,61,1},{12,61,1},{12,47,1},{31,31,648},{12,47,1},{31,35,882},{20,63,193},{20,58,4},{15,57,5},{31,35,882},{27,51,882},{15,57,5},{0,52,884},{27,51,882},{0,52,884},{16,0,890},
+{16,0,890},{16,0,890},{16,0,890},{14,55,4},{14,55,4},{14,55,4},{14,44,5},{6,54,1},{6,54,1},{19,63,3614},{18,63,1804},{18,61,1186},{17,59,898},{18,63,4284},{15,63,1417},{15,59,33},{14,53,1164},{9,63,4036},{8,54,892},{22,63,1494},{20,63,405},{20,60,33},{19,59,117},{31,28,3048},{16,63,1395},{14,60,20},{9,54,885},{31,42,3048},{9,54,885},{18,63,1075},{18,63,1075},{18,63,1075},
+{17,58,890},{16,63,787},{15,59,29},{15,59,29},{15,48,45},{6,63,705},{10,49,80},{20,63,5},{20,63,5},{20,63,5},{20,54,5},{31,15,648},{13,63,1},{13,63,1},{13,49,1},{31,34,648},{13,49,1},{31,40,882},{22,63,277},{21,60,4},{16,59,5},{31,40,882},{31,49,882},{16,59,5},{0,54,884},{31,49,882},{0,54,884},{17,0,890},{17,0,890},{17,0,890},{17,0,890},{15,57,4},
+{15,57,4},{15,57,4},{15,46,5},{7,56,1},{7,56,1},{20,63,4014},{19,63,2174},{19,63,1186},{18,61,898},{19,63,4545},{17,63,1725},{16,62,39},{15,55,1164},{11,63,4300},{9,56,892},{23,63,1656},{22,63,585},{21,62,33},{20,60,108},{31,33,3048},{18,63,1563},{15,62,20},{10,56,885},{31,45,3048},{10,56,885},{19,63,1150},{19,63,1150},{19,63,1150},{18,60,890},{17,63,841},{16,62,35},{16,62,35},
+{16,50,50},{8,63,747},{11,51,80},{21,63,20},{21,63,20},{21,63,20},{21,56,5},{31,20,648},{15,63,5},{15,63,5},{14,51,1},{31,37,648},{14,51,1},{29,52,882},{23,63,397},{22,62,4},{17,61,5},{29,52,882},{28,56,882},{17,61,5},{0,56,884},{28,56,882},{0,56,884},{18,0,890},{18,0,890},{18,0,890},{18,0,890},{16,58,10},{16,58,10},{16,58,10},{16,48,9},{8,58,0},
+{8,58,0},{22,63,4123},{21,63,2404},{20,63,1278},{19,63,901},{20,63,4626},{18,63,1849},{17,63,38},{16,57,1006},{14,63,4330},{10,58,771},{24,63,1629},{23,63,715},{22,63,65},{22,62,81},{31,38,2814},{20,63,1505},{17,63,34},{11,58,761},{31,48,2814},{11,58,761},{20,63,1278},{20,63,1278},{20,63,1278},{19,62,901},{18,63,948},{17,63,38},{17,63,38},{17,53,41},{10,63,840},{12,54,81},{22,63,65},
+{22,63,65},{22,63,65},{22,59,2},{31,26,648},{17,63,34},{17,63,34},{15,53,1},{30,42,648},{15,53,1},{31,50,761},{25,63,425},{23,63,9},{19,63,1},{31,50,761},{31,55,761},{19,63,1},{0,58,761},{31,55,761},{0,58,761},{19,0,900},{19,0,900},{19,0,900},{19,0,900},{17,61,4},{17,61,4},{17,61,4},{17,50,5},{9,60,2},{9,60,2},{23,63,3735},{22,63,2314},{21,63,1395},
+{20,63,899},{22,63,4090},{19,63,1618},{18,63,104},{17,58,678},{15,63,3826},{11,59,507},{25,63,1285},{24,63,609},{23,63,122},{23,62,26},{30,45,2249},{21,63,1186},{19,63,74},{13,59,482},{31,50,2249},{13,59,482},{21,63,1395},{21,63,1395},{21,63,1395},{20,63,899},{19,63,1086},{18,63,104},{18,63,104},{18,55,41},{12,63,969},{13,56,81},{23,63,122},{23,63,122},{23,63,122},{23,61,2},{31,31,648},
+{19,63,74},{19,63,74},{16,55,1},{31,44,648},{16,55,1},{31,53,481},{27,63,269},{25,63,0},{21,63,0},{31,53,481},{31,57,481},{21,63,0},{0,59,481},{31,57,481},{0,59,481},{20,0,890},{20,0,890},{20,0,890},{20,0,890},{18,63,4},{18,63,4},{18,63,4},{18,52,5},{10,62,2},{10,62,2},{23,63,3399},{23,63,2260},{22,63,1530},{21,63,954},{23,63,3639},{20,63,1402},{19,63,238},
+{18,59,405},{17,63,3443},{13,60,297},{26,63,1009},{25,63,525},{25,63,164},{24,63,5},{29,52,1769},{23,63,918},{21,63,113},{14,60,266},{28,56,1769},{14,60,266},{22,63,1530},{22,63,1530},{22,63,1530},{21,63,954},{21,63,1251},{19,63,238},{19,63,238},{19,57,41},{14,63,1105},{14,58,81},{25,63,164},{25,63,164},{25,63,164},{24,62,5},{31,36,648},{21,63,113},{21,63,113},{17,57,1},{31,47,648},
+{17,57,1},{31,55,265},{28,63,145},{27,63,4},{24,63,1},{31,55,265},{30,60,265},{24,63,1},{0,60,265},{30,60,265},{0,60,265},{21,0,890},{21,0,890},{21,0,890},{21,0,890},{19,63,13},{19,63,13},{19,63,13},{19,54,5},{12,62,8},{12,62,8},{24,63,3069},{24,63,2257},{23,63,1683},{23,63,1054},{24,63,3258},{22,63,1330},{21,63,378},{19,61,213},{20,63,3102},{14,61,166},{27,63,801},
+{26,63,477},{26,63,221},{25,63,20},{30,52,1374},{24,63,758},{23,63,181},{16,61,114},{28,58,1374},{16,61,114},{23,63,1683},{23,63,1683},{23,63,1683},{23,63,1054},{22,63,1401},{21,63,378},{21,63,378},{19,59,46},{16,63,1296},{15,60,81},{26,63,221},{26,63,221},{26,63,221},{25,63,20},{30,45,648},{23,63,181},{23,63,181},{18,59,1},{31,50,648},{18,59,1},{31,58,113},{29,63,61},{28,63,0},
+{26,63,1},{31,58,113},{31,60,113},{26,63,1},{0,61,113},{31,60,113},{0,61,113},{22,0,890},{22,0,890},{22,0,890},{22,0,890},{20,63,45},{20,63,45},{20,63,45},{20,56,10},{13,63,25},{13,63,25},{25,63,2860},{25,63,2260},{24,63,1854},{24,63,1210},{25,63,2932},{23,63,1310},{22,63,609},{20,62,81},{21,63,2731},{16,62,94},{28,63,630},{27,63,475},{27,63,306},{26,63,101},{30,56,1032},
+{26,63,612},{25,63,290},{18,62,21},{30,58,1032},{18,62,21},{24,63,1854},{24,63,1854},{24,63,1854},{24,63,1210},{23,63,1620},{22,63,609},{22,63,609},{21,61,44},{18,63,1515},{16,62,78},{27,63,306},{27,63,306},{27,63,306},{26,63,101},{29,54,648},{25,63,290},{25,63,290},{19,61,5},{29,56,648},{19,61,5},{31,61,18},{30,63,10},{30,63,1},{29,63,0},{31,61,18},{31,62,18},{29,63,0},
+{0,62,20},{31,62,18},{0,62,20},{23,0,900},{23,0,900},{23,0,900},{23,0,900},{21,63,104},{21,63,104},{21,63,104},{21,59,5},{15,63,65},{15,63,65},{26,63,2626},{26,63,2206},{25,63,1915},{25,63,1315},{26,63,2641},{24,63,1333},{23,63,789},{22,63,40},{22,63,2445},{17,63,116},{29,63,524},{28,63,406},{28,63,325},{27,63,170},{31,56,771},{27,63,507},{26,63,320},{20,63,0},{30,60,771},
+{20,63,0},{25,63,1915},{25,63,1915},{25,63,1915},{25,63,1315},{24,63,1661},{23,63,789},{23,63,789},{22,62,29},{20,63,1517},{17,63,116},{28,63,325},{28,63,325},{28,63,325},{27,63,170},{31,52,578},{26,63,320},{26,63,320},{20,63,0},{28,60,578},{20,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{24,0,890},
+{24,0,890},{24,0,890},{24,0,890},{23,63,164},{23,63,164},{23,63,164},{22,61,5},{17,63,116},{17,63,116},{27,63,2156},{27,63,1884},{26,63,1630},{26,63,1210},{26,63,2081},{25,63,1108},{24,63,705},{23,63,5},{23,63,1927},{19,63,180},{29,63,300},{29,63,236},{29,63,200},{28,63,85},{31,57,451},{28,63,283},{27,63,194},{23,63,1},{29,62,451},{23,63,1},{26,63,1630},{26,63,1630},{26,63,1630},
+{26,63,1210},{25,63,1347},{24,63,705},{24,63,705},{23,63,5},{22,63,1229},{19,63,180},{29,63,200},{29,63,200},{29,63,200},{28,63,85},{30,58,338},{27,63,194},{27,63,194},{23,63,1},{31,58,338},{23,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{25,0,890},{25,0,890},{25,0,890},{25,0,890},{24,63,221},
+{24,63,221},{24,63,221},{23,63,5},{19,63,180},{19,63,180},{28,63,1782},{27,63,1564},{27,63,1395},{27,63,1123},{27,63,1620},{26,63,937},{25,63,651},{24,63,25},{24,63,1560},{21,63,233},{30,63,150},{30,63,134},{29,63,104},{29,63,40},{31,59,216},{29,63,136},{28,63,90},{25,63,1},{30,62,216},{25,63,1},{27,63,1395},{27,63,1395},{27,63,1395},{27,63,1123},{26,63,1101},{25,63,651},{25,63,651},
+{24,63,25},{23,63,998},{21,63,233},{29,63,104},{29,63,104},{29,63,104},{29,63,40},{31,57,162},{28,63,90},{28,63,90},{25,63,1},{29,62,162},{25,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{26,0,890},{26,0,890},{26,0,890},{26,0,890},{25,63,290},{25,63,290},{25,63,290},{24,63,25},{21,63,233},
+{21,63,233},{0,34,1570},{0,27,400},{0,19,25},{0,16,481},{0,23,3372},{0,17,2355},{0,15,1053},{0,11,2425},{0,13,3753},{0,11,2681},{0,34,1570},{0,27,400},{0,19,25},{0,16,481},{7,0,3371},{0,17,2355},{0,15,1053},{0,11,2425},{10,2,3371},{0,11,2425},{0,16,0},{0,16,0},{0,16,0},{0,10,1},{0,8,288},{0,7,149},{0,7,149},{0,5,160},{0,4,332},{0,4,200},{0,16,0},
+{0,16,0},{0,16,0},{0,10,1},{1,5,288},{0,7,149},{0,7,149},{0,5,160},{4,0,288},{0,5,160},{10,1,1568},{0,27,400},{0,19,25},{0,16,481},{10,1,1568},{17,0,1568},{0,16,481},{0,13,1568},{17,0,1568},{0,13,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,40,1568},{0,31,296},{0,22,2},
+{0,20,373},{0,27,3968},{0,21,2627},{0,17,1107},{0,13,2720},{0,15,4479},{0,11,3065},{0,40,1568},{0,31,296},{0,22,2},{0,20,373},{7,3,3968},{0,21,2627},{0,17,1107},{0,13,2720},{13,0,3968},{0,13,2720},{0,21,1},{0,21,1},{0,21,1},{0,13,0},{0,11,512},{0,9,269},{0,9,269},{0,5,288},{0,5,593},{0,5,337},{0,21,1},{0,21,1},{0,21,1},{0,13,0},{3,1,512},
+{0,9,269},{0,9,269},{0,5,288},{3,3,512},{0,5,288},{11,3,1568},{0,31,296},{0,22,2},{0,20,373},{11,3,1568},{18,2,1568},{0,20,373},{0,15,1568},{18,2,1568},{0,15,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,45,1568},{0,34,221},{0,24,17},{0,22,274},{0,30,4651},{0,23,2924},{0,19,1209},
+{0,15,3065},{0,17,5292},{0,13,3465},{0,45,1568},{0,34,221},{0,24,17},{0,22,274},{8,3,4651},{0,23,2924},{0,19,1209},{0,15,3065},{14,1,4651},{0,15,3065},{0,27,0},{0,27,0},{0,27,0},{0,16,0},{0,13,802},{0,12,424},{0,12,424},{0,7,433},{0,7,918},{0,7,533},{0,27,0},{0,27,0},{0,27,0},{0,16,0},{4,0,800},{0,12,424},{0,12,424},{0,7,433},{6,1,800},
+{0,7,433},{13,1,1568},{0,34,221},{1,24,2},{0,22,274},{13,1,1568},{19,4,1568},{0,22,274},{0,17,1570},{19,4,1568},{0,17,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,50,1568},{0,38,145},{0,26,82},{0,24,193},{0,34,5419},{0,25,3275},{0,21,1347},{0,16,3410},{0,17,6220},{0,15,3933},{0,50,1568},
+{0,38,145},{1,26,81},{0,24,193},{10,0,5419},{0,25,3275},{0,21,1347},{0,16,3410},{15,2,5419},{0,16,3410},{0,32,0},{0,32,0},{0,32,0},{0,19,0},{0,16,1152},{0,15,605},{0,15,605},{0,9,628},{0,8,1328},{0,7,789},{0,32,0},{0,32,0},{0,32,0},{0,19,0},{3,6,1152},{0,15,605},{0,15,605},{0,9,628},{8,0,1152},{0,9,628},{15,0,1568},{0,38,145},{2,26,2},
+{0,24,193},{15,0,1568},{24,1,1568},{0,24,193},{0,19,1570},{24,1,1568},{0,19,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,53,1633},{0,42,166},{1,29,162},{0,26,209},{0,40,5419},{0,29,3012},{0,25,964},{0,18,3152},{0,21,6513},{0,17,3861},{1,53,1569},{1,42,138},{2,28,74},{1,26,186},{11,3,5419},
+{0,29,3012},{0,25,964},{0,18,3152},{18,2,5419},{0,18,3152},{1,34,66},{1,34,66},{1,34,66},{1,21,66},{0,22,1152},{0,19,442},{0,19,442},{0,11,493},{0,11,1480},{0,11,749},{1,34,2},{1,34,2},{1,34,2},{1,21,2},{6,2,1152},{0,19,442},{0,19,442},{0,11,493},{11,0,1152},{0,11,493},{16,2,1568},{0,42,85},{3,28,0},{0,26,128},{16,2,1568},{27,1,1568},{0,26,128},
+{0,21,1568},{27,1,1568},{0,21,1568},{1,0,65},{1,0,65},{1,0,65},{1,0,65},{0,6,0},{0,6,0},{0,6,0},{0,4,1},{0,3,20},{0,3,20},{1,58,1713},{1,44,230},{2,31,354},{1,28,273},{0,45,5419},{0,32,2817},{0,27,682},{0,20,2945},{0,25,6853},{0,19,3825},{2,55,1569},{2,44,138},{3,30,74},{2,28,186},{13,1,5419},{0,32,2817},{0,27,682},{0,20,2945},{19,4,5419},
+{0,20,2945},{1,40,145},{1,40,145},{1,40,145},{1,25,146},{0,27,1154},{0,23,338},{0,23,338},{0,13,394},{0,14,1665},{0,13,755},{2,36,2},{2,36,2},{2,36,2},{2,23,2},{8,0,1152},{0,23,338},{0,23,338},{0,13,394},{11,3,1152},{0,13,394},{17,4,1568},{0,46,41},{4,30,1},{0,29,80},{17,4,1568},{27,4,1568},{0,29,80},{0,23,1568},{27,4,1568},{0,23,1568},{1,0,145},
+{1,0,145},{1,0,145},{1,0,145},{0,11,1},{0,11,1},{0,11,1},{0,7,0},{0,5,74},{0,5,74},{2,60,1905},{1,49,393},{2,33,531},{1,31,433},{0,50,5419},{0,36,2609},{0,29,468},{0,22,2756},{0,27,7195},{0,21,3825},{3,57,1569},{3,46,138},{4,32,81},{3,30,186},{15,0,5419},{0,36,2609},{0,29,468},{0,22,2756},{24,1,5419},{0,22,2756},{2,42,337},{2,42,337},{2,42,337},
+{2,27,338},{0,32,1154},{0,25,244},{0,25,244},{0,16,289},{0,17,1849},{0,15,797},{3,38,2},{3,38,2},{3,38,2},{3,25,2},{9,2,1152},{0,25,244},{0,25,244},{0,16,289},{16,0,1152},{0,16,289},{18,6,1568},{0,51,16},{5,32,2},{0,31,41},{18,6,1568},{28,6,1568},{0,31,41},{0,25,1568},{28,6,1568},{0,25,1568},{2,0,337},{2,0,337},{2,0,337},{2,0,337},{0,17,0},
+{0,17,0},{0,17,0},{0,10,0},{0,7,164},{0,7,164},{2,63,2145},{2,51,585},{3,35,851},{2,33,618},{0,55,5420},{0,40,2425},{0,32,274},{0,24,2585},{0,29,7609},{0,23,3861},{4,58,1570},{4,47,136},{5,34,81},{4,32,193},{16,1,5419},{0,40,2425},{0,32,274},{0,24,2585},{25,3,5419},{0,24,2585},{2,47,545},{2,47,545},{2,47,545},{2,30,545},{0,38,1152},{0,29,164},{0,29,164},
+{0,18,208},{0,19,2098},{0,17,869},{4,40,0},{4,40,0},{4,40,0},{4,27,1},{11,1,1152},{0,29,164},{0,29,164},{0,18,208},{17,2,1152},{0,18,208},{21,1,1568},{0,54,2},{6,34,2},{0,33,13},{21,1,1568},{29,8,1568},{0,33,13},{0,27,1568},{29,8,1568},{0,27,1568},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,22,0},{0,22,0},{0,22,0},{0,13,1},{0,10,289},
+{0,10,289},{3,63,2596},{3,53,934},{3,37,1277},{2,35,964},{0,61,5420},{0,44,2242},{0,35,141},{0,28,2402},{0,32,8131},{0,25,3956},{5,61,1569},{5,50,138},{6,36,74},{5,34,186},{17,4,5419},{0,44,2242},{0,35,141},{0,28,2402},{27,4,5419},{0,28,2402},{3,49,901},{3,49,901},{3,49,901},{3,32,900},{0,44,1152},{0,34,97},{0,34,97},{0,20,145},{0,23,2436},{0,19,989},{5,43,1},
+{5,43,1},{5,43,1},{5,30,2},{13,0,1152},{0,34,97},{0,34,97},{0,20,145},{20,2,1152},{0,20,145},{23,0,1568},{1,57,2},{7,36,0},{0,36,1},{23,0,1568},{31,9,1568},{0,36,1},{0,29,1570},{31,9,1568},{0,29,1570},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{0,28,0},{0,28,0},{0,28,0},{0,17,1},{0,13,461},{0,13,461},{4,63,3146},{3,57,1262},{4,40,1731},
+{3,37,1284},{1,63,5484},{0,46,2129},{0,38,53},{0,30,2243},{0,36,8615},{0,27,4070},{6,63,1569},{6,52,138},{7,38,74},{6,36,186},{18,6,5419},{0,46,2129},{0,38,53},{0,30,2243},{28,6,5419},{0,30,2243},{3,55,1252},{3,55,1252},{3,55,1252},{3,35,1253},{0,49,1152},{0,38,53},{0,38,53},{0,23,89},{0,25,2763},{0,21,1139},{6,45,1},{6,45,1},{6,45,1},{6,32,2},{14,2,1152},
+{0,38,53},{0,38,53},{0,23,89},{24,0,1152},{0,23,89},{24,2,1568},{2,59,2},{8,38,1},{1,38,1},{24,2,1568},{27,17,1568},{1,38,1},{0,31,1570},{27,17,1568},{0,31,1570},{3,0,1252},{3,0,1252},{3,0,1252},{3,0,1252},{0,33,0},{0,33,0},{0,33,0},{0,20,0},{0,15,653},{0,15,653},{5,63,3716},{4,58,1599},{4,42,2134},{4,39,1627},{2,63,5655},{0,51,1983},{0,40,33},
+{0,32,2133},{0,38,8925},{0,30,4044},{7,63,1587},{7,54,138},{8,40,80},{7,38,186},{21,1,5419},{0,51,1979},{0,40,29},{0,32,2129},{29,8,5419},{0,32,2129},{4,56,1587},{4,56,1587},{4,56,1587},{4,37,1586},{0,54,1156},{0,41,29},{0,41,29},{0,25,54},{0,27,2988},{0,23,1193},{7,47,1},{7,47,1},{7,47,1},{7,33,2},{16,0,1152},{0,41,25},{0,41,25},{0,25,50},{26,1,1152},
+{0,25,50},{25,4,1568},{3,61,2},{9,40,1},{2,40,1},{25,4,1568},{28,19,1568},{2,40,1},{0,33,1568},{28,19,1568},{0,33,1568},{4,0,1586},{4,0,1586},{4,0,1586},{4,0,1586},{0,38,5},{0,38,5},{0,38,5},{0,23,4},{0,17,754},{0,17,754},{6,63,3890},{5,60,1599},{5,44,2134},{5,41,1627},{3,63,5748},{0,55,1975},{1,42,33},{0,33,2085},{0,42,8569},{0,32,3525},{9,63,1634},
+{8,55,136},{9,42,80},{8,40,208},{22,3,5419},{0,55,1875},{1,42,29},{0,33,1985},{30,10,5419},{0,33,1985},{5,58,1587},{5,58,1587},{5,58,1587},{5,39,1586},{1,56,1156},{1,43,29},{1,43,29},{1,27,54},{0,31,2736},{0,25,907},{8,48,0},{8,48,0},{8,48,0},{8,35,1},{17,2,1152},{0,45,5},{0,45,5},{0,28,17},{27,3,1152},{0,28,17},{26,6,1568},{4,62,1},{10,42,1},
+{3,42,1},{26,6,1568},{29,21,1568},{3,42,1},{0,35,1568},{29,21,1568},{0,35,1568},{5,0,1586},{5,0,1586},{5,0,1586},{5,0,1586},{1,40,5},{1,40,5},{1,40,5},{1,25,4},{0,21,610},{0,21,610},{7,63,4136},{6,63,1589},{7,46,2141},{6,44,1613},{4,63,5895},{2,55,1973},{2,45,43},{2,35,2100},{0,46,8199},{0,34,3051},{10,63,1667},{9,57,131},{10,45,74},{9,43,195},{24,2,5419},
+{0,59,1772},{2,45,34},{0,36,1874},{27,17,5419},{0,36,1874},{6,61,1576},{6,61,1576},{6,61,1576},{6,41,1577},{2,59,1161},{2,46,26},{2,46,26},{2,30,49},{0,36,2505},{0,29,616},{9,51,1},{9,51,1},{9,51,1},{9,38,2},{19,1,1152},{0,49,2},{0,49,2},{0,30,4},{29,4,1152},{0,30,4},{28,5,1568},{6,63,13},{11,44,1},{4,44,1},{28,5,1568},{31,22,1568},{4,44,1},
+{0,37,1570},{31,22,1568},{0,37,1570},{6,0,1576},{6,0,1576},{6,0,1576},{6,0,1576},{2,43,9},{2,43,9},{2,43,9},{2,27,10},{0,25,468},{0,25,468},{8,63,4436},{7,63,1625},{7,49,2161},{7,46,1613},{6,63,6079},{3,57,1973},{3,47,43},{3,37,2100},{0,49,7908},{0,37,2671},{11,63,1745},{10,59,131},{11,47,74},{10,45,195},{25,4,5419},{0,61,1699},{3,47,34},{0,38,1787},{28,19,5419},
+{0,38,1787},{7,63,1576},{7,63,1576},{7,63,1576},{7,43,1577},{3,61,1161},{3,47,34},{3,47,34},{3,32,59},{0,38,2294},{0,31,422},{10,53,1},{10,53,1},{10,53,1},{10,40,2},{20,3,1152},{2,49,2},{2,49,2},{1,32,2},{30,6,1152},{1,32,2},{31,0,1568},{8,63,34},{12,46,1},{5,46,1},{31,0,1568},{28,29,1568},{5,46,1},{0,39,1570},{28,29,1568},{0,39,1570},{7,0,1576},
+{7,0,1576},{7,0,1576},{7,0,1576},{3,45,9},{3,45,9},{3,45,9},{3,29,10},{0,29,356},{0,29,356},{9,63,4730},{8,63,1716},{8,50,2134},{8,47,1627},{7,63,6244},{3,61,1977},{4,48,33},{3,40,2100},{0,53,7620},{0,40,2343},{12,63,1832},{11,61,131},{12,48,80},{11,47,195},{26,6,5419},{1,63,1699},{4,48,29},{0,41,1714},{29,21,5419},{0,41,1714},{8,63,1595},{8,63,1595},{8,63,1595},
+{8,45,1587},{4,62,1158},{4,49,29},{4,49,29},{4,33,54},{0,42,2098},{0,34,282},{11,55,1},{11,55,1},{11,55,1},{11,42,2},{21,5,1152},{3,51,2},{3,51,2},{2,34,2},{31,8,1152},{2,34,2},{30,9,1568},{9,63,68},{13,48,1},{6,48,1},{30,9,1568},{29,31,1568},{6,48,1},{0,41,1570},{29,31,1568},{0,41,1570},{8,0,1586},{8,0,1586},{8,0,1586},{8,0,1586},{4,47,4},
+{4,47,4},{4,47,4},{4,31,5},{0,32,269},{0,32,269},{11,63,5010},{9,63,1878},{9,52,2134},{9,49,1627},{8,63,6508},{4,62,1965},{5,50,33},{4,42,2079},{0,55,7360},{0,42,2067},{14,63,1952},{12,63,149},{13,50,80},{12,48,208},{29,1,5419},{3,63,1787},{5,50,29},{0,43,1651},{30,23,5419},{0,43,1651},{9,63,1622},{9,63,1622},{9,63,1622},{9,47,1587},{5,63,1164},{5,51,29},{5,51,29},
+{5,35,54},{0,46,1926},{0,36,186},{12,56,0},{12,56,0},{12,56,0},{12,44,1},{24,0,1152},{3,55,2},{3,55,2},{3,36,2},{31,11,1152},{3,36,2},{31,11,1568},{11,63,116},{14,50,1},{7,50,1},{31,11,1568},{29,34,1568},{7,50,1},{0,43,1570},{29,34,1568},{0,43,1570},{9,0,1586},{9,0,1586},{9,0,1586},{9,0,1586},{5,48,5},{5,48,5},{5,48,5},{5,33,4},{0,36,185},
+{0,36,185},{12,63,5316},{11,63,2154},{11,54,2141},{10,52,1613},{10,63,6800},{6,62,1995},{6,53,43},{5,44,2085},{0,59,7068},{0,44,1845},{15,63,2081},{13,63,206},{14,53,74},{13,51,195},{31,0,5419},{5,63,1937},{6,53,34},{0,45,1601},{28,29,5419},{0,45,1601},{10,63,1676},{10,63,1676},{10,63,1676},{10,49,1577},{7,63,1179},{6,54,26},{6,54,26},{6,38,49},{0,49,1764},{0,40,149},{13,59,1},
+{13,59,1},{13,59,1},{13,46,1},{24,6,1152},{4,57,1},{4,57,1},{4,38,4},{29,17,1152},{4,38,4},{30,20,1568},{13,63,205},{15,52,1},{8,52,1},{30,20,1568},{31,35,1568},{8,52,1},{0,45,1576},{31,35,1568},{0,45,1576},{10,0,1576},{10,0,1576},{10,0,1576},{10,0,1576},{6,51,9},{6,51,9},{6,51,9},{6,35,10},{0,40,113},{0,40,113},{13,63,5658},{12,63,2435},{12,56,2148},
+{11,54,1613},{11,63,7055},{7,63,2090},{7,55,43},{6,46,2085},{0,63,6820},{0,47,1701},{16,63,2216},{14,63,334},{15,55,74},{14,53,195},{30,9,5419},{7,63,2081},{7,55,34},{0,47,1580},{29,31,5419},{0,47,1580},{11,63,1745},{11,63,1745},{11,63,1745},{11,51,1577},{8,63,1220},{7,56,26},{7,56,26},{7,40,49},{0,53,1624},{0,42,145},{14,61,1},{14,61,1},{14,61,1},{14,48,2},{27,1,1152},
+{5,59,1},{5,59,1},{5,40,4},{30,19,1152},{5,40,4},{31,22,1568},{15,63,289},{16,54,1},{9,54,1},{31,22,1568},{28,42,1568},{9,54,1},{0,47,1576},{28,42,1568},{0,47,1576},{11,0,1576},{11,0,1576},{11,0,1576},{11,0,1576},{7,53,9},{7,53,9},{7,53,9},{7,37,10},{0,44,61},{0,44,61},{14,63,6036},{13,63,2751},{12,58,2119},{12,55,1627},{12,63,7316},{8,63,2228},{8,57,31},
+{7,48,2100},{0,63,6884},{0,49,1606},{17,63,2402},{16,63,500},{16,57,82},{15,55,195},{31,11,5419},{9,63,2195},{8,57,27},{0,49,1570},{29,34,5419},{0,49,1570},{12,63,1811},{12,63,1811},{12,63,1811},{12,53,1587},{9,63,1286},{8,57,22},{8,57,22},{8,41,56},{0,57,1508},{1,44,145},{15,63,1},{15,63,1},{15,63,1},{15,50,2},{28,3,1152},{6,61,1},{6,61,1},{6,42,4},{31,21,1152},
+{6,42,4},{31,27,1568},{17,63,410},{17,56,1},{10,56,1},{31,27,1568},{29,44,1568},{10,56,1},{0,49,1570},{29,44,1568},{0,49,1570},{12,0,1586},{12,0,1586},{12,0,1586},{12,0,1586},{8,55,4},{8,55,4},{8,55,4},{8,39,5},{0,48,34},{0,48,34},{15,63,6450},{14,63,3135},{13,60,2119},{13,57,1627},{13,63,7661},{10,63,2448},{9,59,31},{8,50,2079},{2,63,7196},{0,51,1580},{19,63,2594},
+{17,63,698},{16,59,73},{16,57,194},{31,16,5419},{11,63,2379},{9,59,27},{1,51,1570},{30,36,5419},{1,51,1570},{13,63,1910},{13,63,1910},{13,63,1910},{13,55,1587},{10,63,1388},{9,59,22},{9,59,22},{9,43,56},{0,61,1416},{2,46,145},{16,63,4},{16,63,4},{16,63,4},{16,52,1},{29,5,1152},{7,63,1},{7,63,1},{7,44,4},{31,24,1152},{7,44,4},{31,32,1568},{19,63,530},{18,58,1},
+{11,58,1},{31,32,1568},{30,46,1568},{11,58,1},{0,51,1570},{30,46,1568},{0,51,1570},{13,0,1586},{13,0,1586},{13,0,1586},{13,0,1586},{9,57,4},{9,57,4},{9,57,4},{9,41,5},{0,51,10},{0,51,10},{16,63,6900},{15,63,3657},{15,62,2128},{14,60,1616},{15,63,8023},{11,63,2845},{10,61,33},{9,52,2085},{5,63,7651},{1,54,1584},{20,63,2866},{18,63,1011},{18,61,69},{17,59,181},{31,22,5419},
+{13,63,2657},{10,61,24},{2,53,1577},{28,42,5419},{2,53,1577},{15,63,2057},{15,63,2057},{15,63,2057},{14,58,1577},{12,63,1476},{10,61,29},{10,61,29},{10,46,54},{0,63,1324},{4,47,137},{17,63,37},{17,63,37},{17,63,37},{17,54,1},{31,4,1152},{9,63,4},{9,63,4},{7,47,2},{30,29,1152},{7,47,2},{31,38,1568},{21,63,637},{19,60,5},{12,60,4},{31,38,1568},{31,48,1568},{12,60,4},
+{0,53,1576},{31,48,1568},{0,53,1576},{14,0,1576},{14,0,1576},{14,0,1576},{14,0,1576},{10,59,10},{10,59,10},{10,59,10},{10,44,10},{0,56,0},{0,56,0},{18,63,7332},{16,63,4196},{16,63,2175},{15,62,1616},{16,63,8348},{13,63,3285},{11,63,33},{10,54,2085},{8,63,8004},{2,56,1584},{21,63,3112},{20,63,1281},{19,63,69},{18,61,181},{31,27,5419},{15,63,2897},{11,63,24},{3,55,1577},{29,44,5419},
+{3,55,1577},{16,63,2171},{16,63,2171},{16,63,2171},{15,60,1577},{13,63,1590},{11,63,29},{11,63,29},{11,48,49},{2,63,1424},{4,50,145},{19,63,65},{19,63,65},{19,63,65},{18,56,1},{30,13,1152},{11,63,20},{11,63,20},{9,48,4},{31,31,1152},{9,48,4},{30,47,1568},{23,63,785},{20,62,4},{13,62,4},{30,47,1568},{31,51,1568},{13,62,4},{0,55,1576},{31,51,1568},{0,55,1576},{15,0,1576},
+{15,0,1576},{15,0,1576},{15,0,1576},{11,61,10},{11,61,10},{11,61,10},{11,46,10},{1,58,0},{1,58,0},{19,63,7014},{17,63,4230},{17,63,2294},{16,63,1595},{17,63,7865},{14,63,3114},{12,63,85},{12,55,1713},{8,63,7436},{3,57,1268},{22,63,2794},{21,63,1221},{20,63,113},{19,61,114},{31,31,4803},{17,63,2648},{13,63,61},{4,57,1253},{31,44,4803},{4,57,1253},{17,63,2294},{17,63,2294},{17,63,2294},
+{16,62,1587},{14,63,1740},{12,63,85},{12,63,85},{12,49,56},{3,63,1571},{5,52,145},{20,63,113},{20,63,113},{20,63,113},{19,58,1},{31,15,1152},{13,63,61},{13,63,61},{10,50,4},{31,34,1152},{10,50,4},{31,47,1250},{24,63,680},{21,63,4},{15,63,0},{31,47,1250},{31,53,1250},{15,63,0},{0,57,1252},{31,53,1250},{0,57,1252},{16,0,1586},{16,0,1586},{16,0,1586},{16,0,1586},{12,63,4},
+{12,63,4},{12,63,4},{12,47,8},{2,60,0},{2,60,0},{19,63,6534},{18,63,4116},{18,63,2435},{17,63,1590},{18,63,7164},{15,63,2809},{14,63,161},{12,57,1256},{10,63,6748},{5,58,909},{23,63,2340},{22,63,1065},{21,63,164},{20,62,41},{31,34,4056},{18,63,2211},{15,63,113},{6,58,884},{31,46,4056},{6,58,884},{18,63,2435},{18,63,2435},{18,63,2435},{17,63,1590},{16,63,1923},{14,63,161},{14,63,161},
+{13,51,56},{6,63,1729},{6,54,145},{21,63,164},{21,63,164},{21,63,164},{20,60,0},{31,20,1152},{15,63,113},{15,63,113},{11,52,4},{31,37,1152},{11,52,4},{31,49,882},{25,63,482},{23,63,0},{18,63,1},{31,49,882},{30,56,882},{18,63,1},{0,58,884},{30,56,882},{0,58,884},{17,0,1586},{17,0,1586},{17,0,1586},{17,0,1586},{13,63,13},{13,63,13},{13,63,13},{13,49,5},{3,62,0},
+{3,62,0},{21,63,6091},{20,63,4022},{19,63,2609},{18,63,1640},{19,63,6490},{16,63,2617},{15,63,318},{14,58,834},{11,63,6135},{6,59,598},{24,63,1881},{23,63,931},{22,63,245},{21,63,5},{31,38,3318},{20,63,1733},{17,63,202},{8,59,545},{31,48,3318},{8,59,545},{19,63,2609},{19,63,2609},{19,63,2609},{18,63,1640},{17,63,2086},{15,63,318},{15,63,318},{14,54,54},{8,63,1868},{8,55,137},{22,63,245},
+{22,63,245},{22,63,245},{21,62,2},{31,26,1152},{17,63,202},{17,63,202},{11,55,2},{30,42,1152},{11,55,2},{31,52,545},{26,63,305},{25,63,4},{20,63,1},{31,52,545},{30,58,545},{20,63,1},{0,59,545},{30,58,545},{0,59,545},{18,0,1576},{18,0,1576},{18,0,1576},{18,0,1576},{15,63,29},{15,63,29},{15,63,29},{14,52,10},{5,62,5},{5,62,5},{22,63,5719},{21,63,3980},{20,63,2834},
+{19,63,1745},{20,63,6050},{18,63,2457},{16,63,536},{15,59,515},{14,63,5674},{8,60,385},{25,63,1573},{24,63,861},{23,63,338},{22,63,10},{30,45,2753},{21,63,1438},{19,63,290},{10,60,313},{31,50,2753},{10,60,313},{20,63,2834},{20,63,2834},{20,63,2834},{19,63,1745},{18,63,2284},{16,63,536},{16,63,536},{15,56,54},{10,63,2064},{9,57,137},{23,63,338},{23,63,338},{23,63,338},{22,63,10},{31,31,1152},
+{19,63,290},{19,63,290},{12,57,2},{31,44,1152},{12,57,2},{31,55,313},{28,63,181},{26,63,1},{23,63,0},{31,55,313},{31,58,313},{23,63,0},{0,60,313},{31,58,313},{0,60,313},{19,0,1576},{19,0,1576},{19,0,1576},{19,0,1576},{16,63,52},{16,63,52},{16,63,52},{15,54,10},{7,62,25},{7,62,25},{22,63,5399},{22,63,3974},{21,63,3035},{20,63,1875},{21,63,5619},{19,63,2378},{18,63,776},
+{16,60,294},{15,63,5258},{9,61,225},{26,63,1333},{25,63,813},{24,63,425},{23,63,65},{29,52,2273},{23,63,1218},{20,63,353},{12,61,146},{28,56,2273},{12,61,146},{21,63,3035},{21,63,3035},{21,63,3035},{20,63,1875},{19,63,2518},{18,63,776},{18,63,776},{16,58,49},{11,63,2323},{10,59,137},{24,63,425},{24,63,425},{24,63,425},{23,63,65},{31,36,1152},{20,63,353},{20,63,353},{13,59,2},{31,47,1152},
+{13,59,2},{31,57,145},{28,63,85},{28,63,4},{26,63,1},{31,57,145},{31,60,145},{26,63,1},{0,61,145},{31,60,145},{0,61,145},{20,0,1586},{20,0,1586},{20,0,1586},{20,0,1586},{17,63,85},{17,63,85},{17,63,85},{16,56,5},{8,63,40},{8,63,40},{23,63,5143},{23,63,4004},{22,63,3254},{21,63,2070},{22,63,5274},{20,63,2310},{19,63,1062},{17,61,133},{17,63,5011},{10,63,161},{27,63,1161},
+{26,63,801},{26,63,545},{25,63,164},{30,52,1878},{24,63,1094},{22,63,461},{13,62,42},{28,58,1878},{13,62,42},{22,63,3254},{22,63,3254},{22,63,3254},{21,63,2070},{20,63,2833},{19,63,1062},{19,63,1062},{17,60,49},{14,63,2577},{11,61,137},{26,63,545},{26,63,545},{26,63,545},{25,63,164},{30,45,1152},{22,63,461},{22,63,461},{14,61,2},{31,50,1152},{14,61,2},{31,60,41},{30,63,25},{29,63,1},
+{28,63,0},{31,60,41},{31,61,41},{28,63,0},{0,62,41},{31,61,41},{0,62,41},{21,0,1586},{21,0,1586},{21,0,1586},{21,0,1586},{18,63,136},{18,63,136},{18,63,136},{17,58,5},{10,63,80},{10,63,80},{24,63,4882},{24,63,4070},{23,63,3532},{22,63,2360},{24,63,4945},{21,63,2422},{20,63,1433},{18,63,58},{20,63,4717},{12,63,157},{28,63,1026},{27,63,835},{27,63,666},{26,63,305},{30,56,1536},
+{26,63,996},{24,63,628},{16,63,1},{30,58,1536},{16,63,1},{23,63,3532},{23,63,3532},{23,63,3532},{22,63,2360},{22,63,3110},{20,63,1433},{20,63,1433},{18,62,50},{16,63,2939},{12,63,157},{27,63,666},{27,63,666},{27,63,666},{26,63,305},{29,54,1152},{24,63,628},{24,63,628},{16,63,1},{29,56,1152},{16,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},
+{0,63,0},{31,63,0},{0,63,0},{22,0,1576},{22,0,1576},{22,0,1576},{22,0,1576},{19,63,221},{19,63,221},{19,63,221},{18,60,9},{12,63,157},{12,63,157},{25,63,4212},{24,63,3590},{24,63,3106},{23,63,2201},{24,63,4129},{22,63,2101},{21,63,1301},{19,63,13},{20,63,3869},{14,63,233},{28,63,706},{28,63,562},{28,63,481},{27,63,218},{30,58,1067},{27,63,699},{25,63,442},{18,63,1},{31,58,1067},
+{18,63,1},{24,63,3106},{24,63,3106},{24,63,3106},{23,63,2201},{23,63,2668},{21,63,1301},{21,63,1301},{19,63,13},{18,63,2523},{14,63,233},{28,63,481},{28,63,481},{28,63,481},{27,63,218},{31,50,800},{25,63,442},{25,63,442},{18,63,1},{31,55,800},{18,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{23,0,1576},
+{23,0,1576},{23,0,1576},{23,0,1576},{20,63,325},{20,63,325},{20,63,325},{19,62,9},{14,63,233},{14,63,233},{26,63,3642},{25,63,3132},{25,63,2771},{24,63,2070},{25,63,3444},{23,63,1834},{22,63,1205},{20,63,8},{21,63,3219},{16,63,346},{29,63,456},{28,63,370},{28,63,289},{28,63,145},{31,56,683},{28,63,451},{27,63,290},{21,63,1},{30,60,683},{21,63,1},{25,63,2771},{25,63,2771},{25,63,2771},
+{24,63,2070},{24,63,2273},{22,63,1205},{22,63,1205},{20,63,8},{20,63,2121},{16,63,346},{28,63,289},{28,63,289},{28,63,289},{28,63,145},{30,56,512},{27,63,290},{27,63,290},{21,63,1},{30,58,512},{21,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{24,0,1586},{24,0,1586},{24,0,1586},{24,0,1586},{22,63,421},
+{22,63,421},{22,63,421},{20,63,8},{16,63,346},{16,63,346},{26,63,3162},{26,63,2742},{26,63,2486},{25,63,1947},{26,63,2877},{24,63,1641},{23,63,1145},{22,63,52},{22,63,2673},{18,63,458},{29,63,264},{29,63,200},{29,63,164},{28,63,81},{31,58,384},{28,63,243},{28,63,162},{23,63,1},{31,60,384},{23,63,1},{26,63,2486},{26,63,2486},{26,63,2486},{25,63,1947},{24,63,1969},{23,63,1145},{23,63,1145},
+{22,63,52},{20,63,1785},{18,63,458},{29,63,164},{29,63,164},{29,63,164},{28,63,81},{31,55,288},{28,63,162},{28,63,162},{23,63,1},{28,62,288},{23,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{25,0,1586},{25,0,1586},{25,0,1586},{25,0,1586},{23,63,520},{23,63,520},{23,63,520},{22,63,52},{18,63,458},
+{18,63,458},{0,46,2665},{0,36,666},{0,26,37},{0,22,773},{0,31,5885},{0,23,4085},{0,21,1802},{0,15,4214},{0,17,6543},{0,13,4662},{0,46,2665},{0,36,666},{0,26,37},{0,22,773},{9,0,5885},{0,23,4085},{0,21,1802},{0,15,4214},{15,0,5885},{0,15,4214},{0,22,0},{0,22,0},{0,22,0},{0,13,1},{0,11,545},{0,10,289},{0,10,289},{0,6,306},{0,6,630},{0,5,362},{0,22,0},
+{0,22,0},{0,22,0},{0,13,1},{3,1,545},{0,10,289},{0,10,289},{0,6,306},{5,1,545},{0,6,306},{13,2,2665},{0,36,666},{0,26,37},{0,22,773},{13,2,2665},{23,0,2665},{0,22,773},{0,17,2665},{23,0,2665},{0,17,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,51,2665},{0,40,530},{0,28,2},
+{0,24,650},{0,34,6670},{0,27,4445},{0,23,1886},{0,16,4577},{0,19,7493},{0,15,5130},{0,51,2665},{0,40,530},{0,28,2},{0,24,650},{10,1,6669},{0,27,4445},{0,23,1886},{0,16,4577},{17,0,6669},{0,16,4577},{0,27,1},{0,27,1},{0,27,1},{0,16,1},{0,14,841},{0,13,442},{0,13,442},{0,7,458},{0,7,965},{0,7,558},{0,27,1},{0,27,1},{0,27,1},{0,16,1},{4,0,841},
+{0,13,442},{0,13,442},{0,7,458},{7,0,841},{0,7,458},{15,1,2665},{0,40,530},{0,28,2},{0,24,650},{15,1,2665},{25,0,2665},{0,24,650},{0,19,2665},{25,0,2665},{0,19,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,56,2665},{0,44,410},{0,30,17},{0,28,522},{0,38,7538},{0,29,4826},{0,25,2006},
+{0,18,5002},{0,21,8547},{0,16,5681},{0,56,2665},{0,44,410},{0,30,17},{0,28,522},{11,1,7538},{0,29,4826},{0,25,2006},{0,18,5002},{17,2,7538},{0,18,5002},{0,32,1},{0,32,1},{0,32,1},{0,19,1},{0,16,1201},{0,15,628},{0,15,628},{0,9,653},{0,9,1382},{0,9,822},{0,32,1},{0,32,1},{0,32,1},{0,19,1},{5,0,1201},{0,15,628},{0,15,628},{0,9,653},{8,0,1201},
+{0,9,653},{16,2,2665},{0,44,410},{1,30,2},{0,28,522},{16,2,2665},{28,0,2665},{0,28,522},{0,21,2665},{28,0,2665},{0,21,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,62,2665},{0,49,325},{0,33,65},{0,30,405},{0,41,8493},{0,31,5261},{0,27,2162},{0,20,5477},{0,23,9705},{0,18,6259},{0,62,2665},
+{0,49,325},{0,33,65},{0,30,405},{11,4,8493},{0,31,5261},{0,27,2162},{0,20,5477},{17,4,8493},{0,20,5477},{0,38,0},{0,38,0},{0,38,0},{0,23,1},{0,19,1625},{0,17,821},{0,17,821},{0,11,898},{0,10,1874},{0,9,1094},{0,38,0},{0,38,0},{0,38,0},{0,23,1},{5,2,1625},{0,17,821},{0,17,821},{0,11,898},{8,2,1625},{0,11,898},{18,1,2665},{0,49,325},{2,32,1},
+{0,30,405},{18,1,2665},{29,2,2665},{0,30,405},{0,23,2665},{29,2,2665},{0,23,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,63,2777},{0,51,221},{0,35,178},{0,32,306},{0,45,9669},{0,34,5810},{0,29,2382},{0,22,6054},{0,25,11123},{0,20,6989},{1,63,2741},{0,51,221},{1,35,137},{0,32,306},{13,1,9669},
+{0,34,5810},{0,29,2382},{0,22,6054},{19,4,9669},{0,22,6054},{0,44,0},{0,44,0},{0,44,0},{0,26,1},{0,22,2178},{0,19,1108},{0,19,1108},{0,11,1213},{0,11,2506},{0,11,1469},{0,44,0},{0,44,0},{0,44,0},{0,26,1},{6,2,2178},{0,19,1108},{0,19,1108},{0,11,1213},{11,0,2178},{0,11,1213},{20,0,2665},{0,51,221},{3,34,1},{0,32,306},{20,0,2665},{31,3,2665},{0,32,306},
+{0,25,2669},{31,3,2665},{0,25,2669},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,63,2949},{0,55,209},{1,37,242},{0,35,285},{0,50,9669},{0,38,5486},{0,32,1938},{0,24,5733},{0,27,11477},{0,22,6887},{2,63,2789},{0,55,209},{2,37,137},{0,35,285},{15,0,9669},{0,38,5486},{0,32,1938},{0,24,5733},{24,1,9669},
+{0,24,5733},{1,46,64},{1,46,64},{1,46,64},{1,28,65},{0,27,2180},{0,23,932},{0,23,932},{0,15,1037},{0,14,2691},{0,13,1421},{1,46,0},{1,46,0},{1,46,0},{1,28,1},{8,0,2178},{0,23,932},{0,23,932},{0,15,1037},{11,3,2178},{0,15,1037},{21,2,2665},{0,55,145},{4,36,2},{0,35,221},{21,2,2665},{31,6,2665},{0,35,221},{0,27,2669},{31,6,2665},{0,27,2669},{0,0,64},
+{0,0,64},{0,0,64},{0,0,64},{0,5,1},{0,5,1},{0,5,1},{0,3,1},{0,3,17},{0,3,17},{2,63,3285},{1,57,273},{2,39,434},{1,37,349},{0,56,9670},{0,42,5186},{0,34,1530},{0,26,5430},{0,29,11903},{0,24,6821},{3,63,2873},{1,57,209},{3,39,137},{1,37,285},{16,1,9669},{0,42,5186},{0,34,1530},{0,26,5430},{25,3,9669},{0,26,5430},{1,51,128},{1,51,128},{1,51,128},
+{1,31,129},{0,32,2180},{0,27,772},{0,27,772},{0,16,865},{0,17,2875},{0,15,1409},{2,47,1},{2,47,1},{2,47,1},{2,30,1},{9,2,2178},{0,27,772},{0,27,772},{0,16,865},{16,0,2178},{0,16,865},{23,0,2665},{0,59,85},{5,38,2},{0,37,146},{23,0,2665},{31,9,2665},{0,37,146},{0,29,2669},{31,9,2665},{0,29,2669},{1,0,128},{1,0,128},{1,0,128},{1,0,128},{0,11,0},
+{0,11,0},{0,11,0},{0,6,1},{0,5,65},{0,5,65},{3,63,3785},{1,61,405},{2,41,653},{1,39,466},{0,61,9669},{0,44,4909},{0,36,1190},{0,28,5145},{0,32,12358},{0,26,6791},{4,63,2966},{2,59,209},{4,41,154},{2,39,285},{18,0,9669},{0,44,4909},{0,36,1190},{0,28,5145},{30,0,9669},{0,28,5145},{2,53,320},{2,53,320},{2,53,320},{2,33,321},{0,38,2178},{0,31,628},{0,31,628},
+{0,18,730},{0,19,3124},{0,17,1427},{3,49,1},{3,49,1},{3,49,1},{3,32,0},{11,1,2178},{0,31,628},{0,31,628},{0,18,730},{17,2,2178},{0,18,730},{24,2,2665},{0,63,41},{6,40,2},{0,39,89},{24,2,2665},{30,14,2665},{0,39,89},{0,31,2669},{30,14,2665},{0,31,2669},{1,0,320},{1,0,320},{1,0,320},{1,0,320},{0,16,0},{0,16,0},{0,16,0},{0,10,1},{0,7,149},
+{0,7,149},{4,63,4514},{2,63,630},{3,45,1013},{2,41,681},{1,63,9738},{0,49,4610},{0,40,833},{0,30,4849},{0,36,12905},{0,29,6798},{6,63,3101},{4,60,208},{5,43,149},{3,41,286},{18,6,9669},{0,49,4610},{0,40,833},{0,30,4849},{28,6,9669},{0,30,4849},{2,59,545},{2,59,545},{2,59,545},{2,37,545},{0,44,2178},{0,34,493},{0,34,493},{0,22,584},{0,23,3462},{0,19,1493},{4,52,0},
+{4,52,0},{4,52,0},{4,34,1},{13,0,2178},{0,34,493},{0,34,493},{0,22,584},{20,2,2178},{0,22,584},{26,1,2665},{2,63,85},{7,42,4},{0,41,52},{26,1,2665},{31,16,2665},{0,41,52},{0,33,2669},{31,16,2665},{0,33,2669},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,22,0},{0,22,0},{0,22,0},{0,13,1},{0,10,289},{0,10,289},{4,63,5330},{3,63,1018},{3,47,1406},
+{2,43,966},{2,63,9981},{0,53,4366},{0,42,585},{0,33,4609},{0,38,13451},{0,31,6834},{7,63,3233},{5,62,208},{6,45,149},{4,42,285},{21,1,9669},{0,53,4366},{0,42,585},{0,33,4609},{29,8,9669},{0,33,4609},{3,61,865},{3,61,865},{3,61,865},{3,39,865},{0,49,2178},{0,38,377},{0,38,377},{0,24,461},{0,25,3789},{0,21,1589},{5,54,0},{5,54,0},{5,54,0},{5,36,1},{14,2,2178},
+{0,38,377},{0,38,377},{0,24,461},{24,0,2178},{0,24,461},{28,0,2665},{3,63,153},{8,44,5},{0,44,20},{28,0,2665},{31,19,2665},{0,44,20},{0,35,2669},{31,19,2665},{0,35,2669},{3,0,865},{3,0,865},{3,0,865},{3,0,865},{0,27,1},{0,27,1},{0,27,1},{0,16,1},{0,13,442},{0,13,442},{5,63,6270},{3,63,1626},{4,49,1866},{3,45,1286},{2,63,10381},{0,55,4133},{0,45,401},
+{0,35,4366},{0,42,14023},{0,32,6917},{8,63,3434},{6,63,242},{7,47,149},{5,44,285},{22,3,9669},{0,55,4133},{0,45,401},{0,35,4366},{30,10,9669},{0,35,4366},{3,63,1226},{3,63,1226},{3,63,1226},{3,42,1201},{0,54,2178},{0,42,277},{0,42,277},{0,26,356},{0,27,4170},{0,23,1721},{6,56,0},{6,56,0},{6,56,0},{6,38,1},{16,0,2178},{0,42,277},{0,42,277},{0,26,356},{26,1,2178},
+{0,26,356},{29,2,2665},{5,63,232},{9,46,5},{0,46,5},{29,2,2665},{31,22,2665},{0,46,5},{0,37,2669},{31,22,2665},{0,37,2669},{3,0,1201},{3,0,1201},{3,0,1201},{3,0,1201},{0,32,1},{0,32,1},{0,32,1},{0,19,1},{0,15,628},{0,15,628},{6,63,7374},{4,63,2339},{4,51,2411},{3,48,1715},{3,63,10950},{0,59,3909},{0,47,257},{0,37,4141},{0,44,14641},{0,34,7031},{9,63,3638},
+{7,63,320},{8,49,154},{6,46,285},{24,1,9669},{0,59,3909},{0,47,257},{0,37,4141},{31,12,9669},{0,37,4141},{4,63,1714},{4,63,1714},{4,63,1714},{4,44,1665},{0,59,2180},{0,46,193},{0,46,193},{0,28,269},{0,31,4582},{0,25,1889},{7,58,0},{7,58,0},{7,58,0},{7,40,1},{17,2,2178},{0,46,193},{0,46,193},{0,28,269},{27,3,2178},{0,28,269},{31,0,2665},{8,63,313},{10,48,2},
+{1,48,2},{31,0,2665},{30,27,2665},{1,48,2},{0,39,2669},{30,27,2665},{0,39,2669},{3,0,1665},{3,0,1665},{3,0,1665},{3,0,1665},{0,38,0},{0,38,0},{0,38,0},{0,23,1},{0,17,821},{0,17,821},{7,63,8807},{5,63,3388},{5,53,3082},{4,49,2230},{4,63,11766},{0,63,3686},{0,51,134},{0,39,3909},{0,46,15438},{0,37,7214},{11,63,3853},{8,63,457},{9,51,149},{7,49,286},{25,4,9669},
+{0,63,3686},{0,51,134},{0,39,3909},{28,19,9669},{0,39,3909},{5,63,2427},{5,63,2427},{5,63,2427},{4,47,2179},{0,63,2210},{0,49,128},{0,49,128},{0,31,193},{0,34,5117},{0,29,2123},{8,60,0},{8,60,0},{8,60,0},{8,42,1},{19,1,2178},{0,49,128},{0,49,128},{0,31,193},{29,4,2178},{0,31,193},{31,6,2665},{9,63,405},{11,50,4},{2,50,4},{31,6,2665},{31,29,2665},{2,50,4},
+{0,42,2669},{31,29,2665},{0,42,2669},{4,0,2178},{4,0,2178},{4,0,2178},{4,0,2178},{0,44,0},{0,44,0},{0,44,0},{0,26,1},{0,19,1108},{0,19,1108},{7,63,10230},{6,63,4421},{6,55,3705},{4,52,2725},{5,63,12634},{0,63,3719},{0,53,77},{0,41,3727},{0,51,15978},{0,39,7289},{12,63,4050},{10,63,629},{10,53,149},{8,50,285},{26,6,9669},{0,63,3718},{0,53,76},{0,41,3726},{29,21,9669},
+{0,41,3726},{5,63,3050},{5,63,3050},{5,63,3050},{5,49,2690},{1,63,2325},{0,53,73},{0,53,73},{0,33,118},{0,36,5499},{0,31,2266},{9,62,0},{9,62,0},{9,62,0},{9,44,1},{20,3,2178},{0,53,72},{0,53,72},{0,33,117},{30,6,2178},{0,33,117},{31,12,2665},{11,63,521},{12,52,5},{3,52,4},{31,12,2665},{31,32,2665},{3,52,4},{0,44,2669},{31,32,2665},{0,44,2669},{5,0,2689},
+{5,0,2689},{5,0,2689},{5,0,2689},{0,49,1},{0,49,1},{0,49,1},{0,29,2},{0,21,1341},{0,21,1341},{9,63,10738},{7,63,4899},{7,57,3705},{5,54,2725},{6,63,13045},{1,63,4002},{1,55,77},{0,43,3642},{0,53,15510},{0,42,6577},{13,63,4302},{11,63,857},{11,55,149},{9,52,285},{29,1,9669},{2,63,3954},{1,55,76},{0,43,3561},{30,23,9669},{0,43,3561},{6,63,3173},{6,63,3173},{6,63,3173},
+{6,51,2690},{2,63,2427},{1,55,73},{1,55,73},{1,35,118},{0,40,5171},{0,32,1846},{10,63,4},{10,63,4},{10,63,4},{10,46,1},{21,5,2178},{0,57,32},{0,57,32},{0,35,72},{31,8,2178},{0,35,72},{31,17,2665},{13,63,680},{13,54,5},{3,55,4},{31,17,2665},{31,35,2665},{3,55,4},{0,46,2669},{31,35,2665},{0,46,2669},{6,0,2689},{6,0,2689},{6,0,2689},{6,0,2689},{1,51,1},
+{1,51,1},{1,51,1},{1,31,2},{0,25,1145},{0,25,1145},{10,63,11278},{8,63,5402},{8,58,3742},{6,56,2725},{7,63,13510},{3,63,4314},{2,57,77},{1,45,3642},{0,57,15046},{0,44,5927},{14,63,4590},{12,63,1171},{12,57,149},{10,54,285},{30,3,9669},{3,63,4265},{2,57,76},{0,45,3414},{31,25,9669},{0,45,3414},{7,63,3314},{7,63,3314},{7,63,3314},{7,53,2690},{4,63,2532},{2,57,73},{2,57,73},
+{2,37,118},{0,44,4867},{0,36,1470},{11,63,25},{11,63,25},{11,63,25},{11,48,1},{24,0,2178},{0,61,8},{0,61,8},{0,38,40},{31,11,2178},{0,38,40},{31,22,2665},{15,63,832},{14,56,5},{4,57,4},{31,22,2665},{30,40,2665},{4,57,4},{0,47,2677},{30,40,2665},{0,47,2677},{7,0,2689},{7,0,2689},{7,0,2689},{7,0,2689},{2,53,1},{2,53,1},{2,53,1},{2,33,2},{0,29,965},
+{0,29,965},{11,63,11942},{10,63,6090},{9,62,3723},{8,58,2734},{9,63,14053},{4,63,4863},{3,59,79},{2,48,3633},{0,61,14558},{0,46,5283},{16,63,4858},{14,63,1556},{13,60,138},{11,57,299},{30,9,9669},{6,63,4594},{3,59,75},{0,48,3233},{29,31,9669},{0,48,3233},{9,63,3505},{9,63,3505},{9,63,3505},{8,55,2690},{5,63,2645},{3,61,72},{3,61,72},{3,39,117},{0,46,4539},{0,38,1091},{12,63,64},
+{12,63,64},{12,63,64},{12,50,1},{24,6,2178},{1,63,10},{1,63,10},{0,40,13},{29,17,2178},{0,40,13},{31,28,2665},{17,63,1053},{15,59,2},{5,59,2},{31,28,2665},{31,42,2665},{5,59,2},{0,50,2669},{31,42,2665},{0,50,2669},{8,0,2689},{8,0,2689},{8,0,2689},{8,0,2689},{3,55,5},{3,55,5},{3,55,5},{3,36,5},{0,34,794},{0,34,794},{12,63,12466},{11,63,6718},{10,62,3738},
+{8,60,2723},{10,63,14554},{6,63,5363},{4,61,87},{3,50,3633},{0,63,14190},{0,49,4774},{17,63,5158},{15,63,1938},{14,62,138},{12,59,282},{31,11,9669},{8,63,4806},{4,61,86},{0,50,3110},{29,34,9669},{0,50,3110},{10,63,3658},{10,63,3658},{10,63,3658},{9,57,2690},{6,63,2795},{4,62,66},{4,62,66},{4,41,131},{0,51,4269},{0,40,833},{14,63,100},{14,63,100},{14,63,100},{13,52,1},{27,1,2178},
+{3,63,34},{3,63,34},{0,43,2},{30,19,2178},{0,43,2},{31,33,2665},{19,63,1241},{16,61,5},{6,61,2},{31,33,2665},{31,45,2665},{6,61,2},{0,52,2669},{31,45,2665},{0,52,2669},{9,0,2689},{9,0,2689},{9,0,2689},{9,0,2689},{4,57,1},{4,57,1},{4,57,1},{4,37,2},{0,38,650},{0,38,650},{14,63,13094},{12,63,7445},{11,63,3830},{9,62,2723},{12,63,14998},{8,63,5926},{5,63,87},
+{4,51,3642},{0,63,14254},{0,51,4306},{18,63,5494},{16,63,2414},{15,63,146},{13,61,282},{31,16,9669},{10,63,5138},{5,63,86},{0,52,3005},{30,36,9669},{0,52,3005},{11,63,3829},{11,63,3829},{11,63,3829},{10,59,2690},{7,63,2981},{5,63,86},{5,63,86},{5,43,131},{0,53,4014},{0,44,601},{15,63,145},{15,63,145},{15,63,145},{14,54,1},{28,3,2178},{5,63,85},{5,63,85},{1,45,2},{31,21,2178},
+{1,45,2},{31,38,2665},{20,63,1378},{17,63,5},{7,63,2},{31,38,2665},{31,48,2665},{7,63,2},{0,54,2669},{31,48,2665},{0,54,2669},{10,0,2689},{10,0,2689},{10,0,2689},{10,0,2689},{5,59,1},{5,59,1},{5,59,1},{5,39,2},{0,40,520},{0,40,520},{15,63,12507},{13,63,7370},{12,63,4001},{11,63,2705},{13,63,14148},{8,63,5491},{6,63,154},{5,53,3033},{1,63,13399},{0,53,3297},{19,63,4949},
+{17,63,2261},{16,63,202},{15,61,185},{31,20,8712},{11,63,4644},{7,63,145},{0,54,2365},{31,37,8712},{0,54,2365},{12,63,4001},{12,63,4001},{12,63,4001},{11,61,2690},{9,63,3204},{6,63,154},{6,63,154},{6,45,131},{0,57,3762},{0,46,419},{16,63,202},{16,63,202},{16,63,202},{15,56,1},{29,5,2178},{7,63,145},{7,63,145},{2,47,2},{31,24,2178},{2,47,2},{30,45,2178},{22,63,1145},{18,63,1},
+{10,63,1},{30,45,2178},{31,50,2178},{10,63,1},{0,55,2180},{31,50,2178},{0,55,2180},{11,0,2689},{11,0,2689},{11,0,2689},{11,0,2689},{6,61,1},{6,61,1},{6,61,1},{6,41,2},{0,44,400},{0,44,400},{16,63,11658},{14,63,7195},{13,63,4225},{12,63,2693},{14,63,13066},{10,63,5014},{8,63,261},{6,54,2366},{3,63,12366},{0,55,2274},{20,63,4338},{18,63,2037},{17,63,289},{16,62,80},{31,24,7578},
+{13,63,4037},{9,63,202},{0,55,1698},{29,42,7578},{0,55,1698},{13,63,4225},{13,63,4225},{13,63,4225},{12,63,2693},{10,63,3429},{8,63,261},{8,63,261},{7,47,132},{0,61,3509},{0,49,290},{17,63,289},{17,63,289},{17,63,289},{16,59,0},{31,4,2178},{9,63,202},{9,63,202},{3,49,2},{30,29,2178},{3,49,2},{31,44,1625},{23,63,850},{20,63,0},{13,63,1},{31,44,1625},{31,52,1625},{13,63,1},
+{0,56,1625},{31,52,1625},{0,56,1625},{12,0,2689},{12,0,2689},{12,0,2689},{12,0,2689},{7,63,5},{7,63,5},{7,63,5},{7,44,4},{0,49,289},{0,49,289},{16,63,11002},{15,63,7081},{14,63,4450},{13,63,2738},{15,63,12205},{11,63,4663},{9,63,411},{7,55,1813},{4,63,11643},{0,56,1550},{21,63,3802},{20,63,1845},{18,63,388},{17,62,25},{31,27,6661},{15,63,3525},{11,63,290},{0,57,1217},{29,44,6661},
+{0,57,1217},{14,63,4450},{14,63,4450},{14,63,4450},{13,63,2738},{11,63,3675},{9,63,411},{9,63,411},{8,49,131},{0,63,3354},{0,51,222},{18,63,388},{18,63,388},{18,63,388},{17,61,0},{30,13,2178},{11,63,290},{11,63,290},{4,51,2},{31,31,2178},{4,51,2},{31,47,1201},{24,63,653},{22,63,4},{15,63,1},{31,47,1201},{31,53,1201},{15,63,1},{0,57,1201},{31,53,1201},{0,57,1201},{13,0,2689},
+{13,0,2689},{13,0,2689},{13,0,2689},{8,63,17},{8,63,17},{8,63,17},{8,46,2},{0,53,205},{0,53,205},{17,63,10434},{16,63,7010},{15,63,4693},{14,63,2833},{16,63,11374},{12,63,4462},{10,63,629},{8,56,1358},{6,63,10895},{0,57,1002},{22,63,3334},{20,63,1701},{19,63,505},{18,63,0},{31,31,5829},{16,63,3145},{12,63,405},{1,58,842},{31,44,5829},{1,58,842},{15,63,4693},{15,63,4693},{15,63,4693},
+{14,63,2833},{12,63,3906},{10,63,629},{10,63,629},{9,51,131},{1,63,3525},{0,54,218},{19,63,505},{19,63,505},{19,63,505},{18,63,0},{31,15,2178},{12,63,405},{12,63,405},{5,53,2},{31,34,2178},{5,53,2},{31,49,841},{25,63,461},{23,63,1},{18,63,0},{31,49,841},{31,55,841},{18,63,0},{0,58,841},{31,55,841},{0,58,841},{14,0,2689},{14,0,2689},{14,0,2689},{14,0,2689},{9,63,50},
+{9,63,50},{9,63,50},{9,48,2},{0,57,137},{0,57,137},{18,63,9934},{17,63,6962},{16,63,4913},{15,63,2978},{17,63,10683},{13,63,4277},{11,63,915},{9,58,974},{8,63,10078},{0,59,630},{23,63,2934},{22,63,1605},{21,63,650},{19,63,25},{31,34,5082},{18,63,2769},{14,63,521},{2,59,546},{31,46,5082},{2,59,546},{16,63,4913},{16,63,4913},{16,63,4913},{15,63,2978},{14,63,4170},{11,63,915},{11,63,915},
+{10,53,131},{3,63,3789},{1,56,218},{21,63,650},{21,63,650},{21,63,650},{19,63,25},{31,20,2178},{14,63,521},{14,63,521},{6,55,2},{31,37,2178},{6,55,2},{31,52,545},{26,63,305},{25,63,4},{20,63,1},{31,52,545},{30,58,545},{20,63,1},{0,59,545},{30,58,545},{0,59,545},{15,0,2689},{15,0,2689},{15,0,2689},{15,0,2689},{11,63,74},{11,63,74},{11,63,74},{10,49,2},{0,59,85},
+{0,59,85},{19,63,9465},{18,63,6955},{17,63,5233},{16,63,3218},{18,63,10003},{14,63,4183},{13,63,1258},{11,58,645},{9,63,9445},{1,61,409},{24,63,2529},{23,63,1525},{22,63,785},{20,63,100},{31,38,4344},{20,63,2345},{16,63,698},{4,60,289},{31,48,4344},{4,60,289},{17,63,5233},{17,63,5233},{17,63,5233},{16,63,3218},{15,63,4491},{13,63,1258},{13,63,1258},{11,56,120},{5,63,4171},{2,59,213},{22,63,785},
+{22,63,785},{22,63,785},{20,63,100},{31,26,2178},{16,63,698},{16,63,698},{7,57,0},{30,42,2178},{7,57,0},{31,55,288},{28,63,162},{26,63,4},{23,63,1},{31,55,288},{28,62,288},{23,63,1},{0,60,288},{28,62,288},{0,60,288},{16,0,2689},{16,0,2689},{16,0,2689},{16,0,2689},{12,63,113},{12,63,113},{12,63,113},{11,52,4},{0,63,45},{0,63,45},{20,63,9219},{19,63,6985},{18,63,5530},
+{17,63,3473},{19,63,9496},{15,63,4186},{14,63,1630},{11,60,404},{11,63,8961},{3,61,277},{25,63,2275},{24,63,1509},{23,63,932},{22,63,208},{30,45,3779},{21,63,2086},{18,63,850},{6,61,129},{31,50,3779},{6,61,129},{18,63,5530},{18,63,5530},{18,63,5530},{17,63,3473},{16,63,4770},{14,63,1630},{14,63,1630},{12,57,129},{8,63,4442},{3,61,213},{23,63,932},{23,63,932},{23,63,932},{22,63,208},{31,31,2178},
+{18,63,850},{18,63,850},{8,59,1},{31,44,2178},{8,59,1},{31,58,128},{29,63,72},{28,63,1},{26,63,0},{31,58,128},{31,60,128},{26,63,0},{0,61,128},{31,60,128},{0,61,128},{17,0,2689},{17,0,2689},{17,0,2689},{17,0,2689},{13,63,170},{13,63,170},{13,63,170},{12,54,2},{2,63,89},{2,63,89},{21,63,8929},{20,63,7062},{19,63,5845},{18,63,3778},{20,63,9188},{17,63,4260},{15,63,2070},
+{13,61,234},{13,63,8680},{4,62,212},{26,63,2089},{25,63,1515},{24,63,1073},{23,63,353},{29,52,3299},{22,63,1913},{20,63,965},{8,62,32},{28,56,3299},{8,62,32},{19,63,5845},{19,63,5845},{19,63,5845},{18,63,3778},{17,63,5124},{15,63,2070},{15,63,2070},{13,59,129},{9,63,4725},{4,62,196},{24,63,1073},{24,63,1073},{24,63,1073},{23,63,353},{31,36,2178},{20,63,965},{20,63,965},{9,61,1},{31,47,2178},
+{9,61,1},{31,60,34},{30,63,18},{29,63,4},{28,63,1},{31,60,34},{31,61,34},{28,63,1},{0,62,32},{31,61,34},{0,62,32},{18,0,2689},{18,0,2689},{18,0,2689},{18,0,2689},{14,63,245},{14,63,245},{14,63,245},{13,56,2},{4,63,164},{4,63,164},{22,63,8707},{21,63,7170},{21,63,6209},{19,63,4133},{21,63,8853},{18,63,4387},{17,63,2548},{14,62,154},{14,63,8388},{6,63,244},{27,63,1971},
+{26,63,1557},{25,63,1250},{24,63,565},{30,52,2904},{23,63,1826},{22,63,1145},{10,63,1},{28,58,2904},{10,63,1},{21,63,6209},{21,63,6209},{21,63,6209},{19,63,4133},{19,63,5460},{17,63,2548},{17,63,2548},{14,61,129},{11,63,5085},{6,63,244},{25,63,1250},{25,63,1250},{25,63,1250},{24,63,565},{30,45,2178},{22,63,1145},{22,63,1145},{10,63,1},{31,50,2178},{10,63,1},{31,63,0},{31,63,0},{31,63,0},
+{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{19,0,2689},{19,0,2689},{19,0,2689},{19,0,2689},{15,63,338},{15,63,338},{15,63,338},{14,58,2},{6,63,244},{6,63,244},{23,63,7705},{22,63,6418},{21,63,5633},{20,63,3845},{22,63,7654},{19,63,3874},{18,63,2310},{15,63,53},{15,63,7258},{8,63,317},{27,63,1458},{27,63,1186},{26,63,932},{25,63,425},{30,54,2166},
+{25,63,1398},{23,63,850},{13,63,1},{29,58,2166},{13,63,1},{21,63,5633},{21,63,5633},{21,63,5633},{20,63,3845},{19,63,4830},{18,63,2310},{18,63,2310},{15,62,45},{13,63,4506},{8,63,317},{26,63,932},{26,63,932},{26,63,932},{25,63,425},{31,44,1625},{23,63,850},{23,63,850},{13,63,1},{31,52,1625},{13,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},
+{0,63,0},{31,63,0},{0,63,0},{20,0,2689},{20,0,2689},{20,0,2689},{20,0,2689},{16,63,449},{16,63,449},{16,63,449},{15,60,4},{8,63,317},{8,63,317},{24,63,6881},{23,63,5814},{22,63,5138},{21,63,3650},{23,63,6713},{20,63,3400},{19,63,2142},{16,63,5},{17,63,6397},{9,63,425},{28,63,1075},{27,63,866},{27,63,697},{26,63,320},{30,56,1601},{26,63,1041},{24,63,653},{15,63,1},{30,58,1601},
+{15,63,1},{22,63,5138},{22,63,5138},{22,63,5138},{21,63,3650},{21,63,4313},{19,63,2142},{19,63,2142},{16,63,5},{14,63,3981},{9,63,425},{27,63,697},{27,63,697},{27,63,697},{26,63,320},{31,47,1201},{24,63,653},{24,63,653},{15,63,1},{31,53,1201},{15,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{21,0,2689},
+{21,0,2689},{21,0,2689},{21,0,2689},{18,63,549},{18,63,549},{18,63,549},{16,62,1},{9,63,425},{9,63,425},{24,63,6097},{24,63,5285},{23,63,4693},{22,63,3473},{23,63,5833},{21,63,3067},{20,63,1988},{17,63,10},{18,63,5571},{11,63,541},{28,63,739},{28,63,595},{27,63,505},{27,63,233},{31,54,1121},{26,63,737},{25,63,461},{18,63,0},{29,60,1121},{18,63,0},{23,63,4693},{23,63,4693},{23,63,4693},
+{22,63,3473},{22,63,3845},{20,63,1988},{20,63,1988},{17,63,10},{15,63,3542},{11,63,541},{27,63,505},{27,63,505},{27,63,505},{27,63,233},{31,49,841},{25,63,461},{25,63,461},{18,63,0},{31,55,841},{18,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{22,0,2689},{22,0,2689},{22,0,2689},{22,0,2689},{19,63,666},
+{19,63,666},{19,63,666},{17,63,10},{11,63,541},{11,63,541},{25,63,5427},{24,63,4757},{24,63,4273},{23,63,3314},{24,63,5002},{22,63,2788},{21,63,1898},{18,63,65},{20,63,4714},{13,63,698},{29,63,489},{28,63,387},{28,63,306},{28,63,162},{31,56,726},{27,63,482},{26,63,305},{20,63,1},{30,60,726},{20,63,1},{24,63,4273},{24,63,4273},{24,63,4273},{23,63,3314},{22,63,3429},{21,63,1898},{21,63,1898},
+{18,63,65},{17,63,3213},{13,63,698},{28,63,306},{28,63,306},{28,63,306},{28,63,162},{31,52,545},{26,63,305},{26,63,305},{20,63,1},{30,58,545},{20,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{23,0,2689},{23,0,2689},{23,0,2689},{23,0,2689},{20,63,832},{20,63,832},{20,63,832},{18,63,65},{13,63,698},
+{13,63,698},{4,63,33740},{0,63,5184},{0,45,446},{0,43,4126},{3,63,45594},{0,59,24105},{0,42,8295},{0,37,24703},{0,44,64117},{0,34,38807},{2,63,9704},{0,61,2866},{0,44,386},{0,37,3205},{14,4,18065},{0,38,13219},{0,34,6147},{0,24,13496},{25,0,18065},{0,24,13496},{0,31,1},{0,31,1},{0,31,1},{0,19,1},{0,16,1105},{0,15,584},{0,15,584},{0,9,605},{0,8,1273},{0,7,750},{0,31,1},
+{0,31,1},{0,31,1},{0,19,1},{4,2,1105},{0,15,584},{0,15,584},{0,9,605},{8,0,1105},{0,9,605},{21,5,9248},{0,61,2866},{0,44,386},{0,37,3205},{21,5,9248},{31,8,9248},{0,37,3205},{0,28,9256},{31,8,9248},{0,28,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,63,38380},{1,63,6614},{0,47,261},
+{0,45,3769},{4,63,50747},{0,63,24961},{0,44,8337},{0,39,25658},{0,46,65535},{0,36,41267},{2,63,10152},{0,63,2624},{0,46,221},{0,41,2929},{16,0,19334},{0,42,13795},{0,36,6237},{0,26,14121},{26,1,19334},{0,26,14121},{0,36,1},{0,36,1},{0,36,1},{0,22,0},{0,18,1513},{0,17,769},{0,17,769},{0,9,845},{0,9,1742},{0,9,1014},{0,36,1},{0,36,1},{0,36,1},{0,22,0},{5,1,1513},
+{0,17,769},{0,17,769},{0,9,845},{9,0,1513},{0,9,845},{24,0,9248},{0,63,2624},{0,46,221},{0,41,2929},{24,0,9248},{31,11,9248},{0,41,2929},{0,30,9256},{31,11,9248},{0,30,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,63,43788},{1,63,8598},{0,49,121},{0,47,3430},{4,63,56155},{0,63,26241},{0,46,8415},
+{0,41,26663},{0,46,65535},{0,36,43795},{3,63,10706},{0,63,2624},{0,48,116},{0,43,2650},{17,0,20689},{0,44,14404},{0,38,6363},{0,28,14796},{26,3,20689},{0,28,14796},{0,42,0},{0,42,0},{0,42,0},{0,25,0},{0,21,1985},{0,19,1009},{0,19,1009},{0,11,1090},{0,11,2281},{0,11,1346},{0,42,0},{0,42,0},{0,42,0},{0,25,0},{6,1,1985},{0,19,1009},{0,19,1009},{0,11,1090},{9,2,1985},
+{0,11,1090},{25,2,9248},{0,63,2624},{0,48,116},{0,43,2650},{25,2,9248},{27,19,9248},{0,43,2650},{0,32,9250},{27,19,9248},{0,32,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,63,49566},{1,63,11350},{0,51,36},{0,50,3105},{4,63,62331},{0,63,28289},{0,48,8549},{0,43,27718},{0,49,65535},{0,38,46395},{4,63,11395},
+{0,63,2880},{0,51,36},{0,45,2389},{17,4,22129},{0,46,15067},{0,40,6525},{0,28,15500},{27,4,22129},{0,28,15500},{0,47,0},{0,47,0},{0,47,0},{0,28,1},{0,24,2521},{0,21,1285},{0,21,1285},{0,13,1385},{0,12,2905},{0,11,1714},{0,47,0},{0,47,0},{0,47,0},{0,28,1},{7,0,2521},{0,21,1285},{0,21,1285},{0,13,1385},{11,1,2521},{0,13,1385},{26,4,9248},{1,63,2866},{0,51,36},
+{0,45,2389},{26,4,9248},{28,21,9248},{0,45,2389},{0,34,9250},{28,21,9248},{0,34,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,63,56892},{2,63,15166},{0,53,5},{0,52,2726},{5,63,65535},{0,63,31511},{0,51,8735},{0,45,28953},{0,53,65535},{0,40,49505},{4,63,12385},{1,63,3380},{0,53,1},{0,47,2120},{19,1,23851},
+{0,49,15876},{0,42,6761},{0,30,16331},{29,4,23851},{0,30,16331},{0,53,0},{0,53,0},{0,53,0},{0,32,1},{0,27,3200},{0,23,1640},{0,23,1640},{0,15,1769},{0,13,3689},{0,13,2169},{0,53,0},{0,53,0},{0,53,0},{0,32,1},{7,3,3200},{0,23,1640},{0,23,1640},{0,15,1769},{13,0,3200},{0,15,1769},{28,3,9248},{3,63,3204},{0,53,1},{0,47,2120},{28,3,9248},{31,21,9248},{0,47,2120},
+{0,36,9256},{31,21,9248},{0,36,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,63,63870},{2,63,19230},{0,55,30},{0,54,2429},{5,63,65535},{1,63,35016},{0,53,8921},{0,47,30108},{0,55,65535},{0,42,52385},{5,63,13379},{2,63,4026},{0,56,18},{0,50,1885},{20,1,25472},{0,53,16616},{0,46,6989},{0,33,17105},{29,6,25472},
+{0,33,17105},{0,58,0},{0,58,0},{0,58,0},{0,35,0},{0,29,3874},{0,25,1994},{0,25,1994},{0,16,2129},{0,15,4454},{0,15,2637},{0,58,0},{0,58,0},{0,58,0},{0,35,0},{8,2,3872},{0,25,1994},{0,25,1994},{0,16,2129},{12,3,3872},{0,16,2129},{29,5,9248},{5,63,3589},{1,55,1},{0,50,1885},{29,5,9248},{31,24,9248},{0,50,1885},{0,38,9256},{31,24,9248},{0,38,9256},{0,0,0},
+{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,63,65535},{2,63,24002},{0,57,109},{0,56,2154},{6,63,65535},{1,63,38780},{0,55,8815},{0,48,30807},{0,57,65535},{0,44,54965},{6,63,14345},{2,63,4766},{1,58,54},{0,52,1670},{20,5,26744},{0,55,17059},{0,46,7005},{0,33,17609},{31,6,26744},{0,33,17609},{0,63,5},{0,63,5},{0,63,5},
+{0,38,4},{0,32,4420},{0,29,2210},{0,29,2210},{0,18,2378},{0,17,5115},{0,16,2981},{0,63,5},{0,63,5},{0,63,5},{0,38,4},{9,2,4418},{0,29,2210},{0,29,2210},{0,18,2378},{16,0,4418},{0,18,2378},{30,7,9248},{8,63,3904},{2,57,1},{0,52,1666},{30,7,9248},{28,31,9248},{0,52,1666},{0,40,9256},{28,31,9248},{0,40,9256},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,1},
+{0,1,1},{0,1,1},{0,1,0},{0,1,1},{0,1,1},{7,63,65535},{3,63,29032},{0,60,314},{0,58,1989},{6,63,65535},{2,63,42151},{0,57,7781},{0,50,30102},{0,59,65535},{0,46,56345},{7,63,14819},{3,63,5416},{2,60,54},{0,54,1565},{23,0,26744},{0,59,16547},{0,49,6177},{0,37,17105},{31,9,26744},{0,37,17105},{1,63,84},{1,63,84},{1,63,84},{1,40,68},{0,38,4418},{0,31,1972},{0,31,1972},
+{0,20,2129},{0,19,5364},{0,18,2915},{1,63,20},{1,63,20},{1,63,20},{1,40,4},{11,1,4418},{0,31,1972},{0,31,1972},{0,20,2129},{17,2,4418},{0,20,2129},{31,9,9248},{8,63,4160},{3,59,1},{0,54,1465},{31,9,9248},{28,34,9248},{0,54,1465},{0,42,9256},{28,34,9248},{0,42,9256},{1,0,68},{1,0,68},{1,0,68},{1,0,68},{0,7,0},{0,7,0},{0,7,0},{0,4,0},{0,3,25},
+{0,3,25},{7,63,65535},{3,63,35719},{1,62,657},{0,60,1985},{7,63,65535},{2,63,46660},{0,59,6696},{0,52,29368},{0,63,65535},{0,49,58301},{9,63,15473},{5,63,6173},{3,62,45},{1,56,1566},{23,6,26744},{0,63,15992},{0,53,5318},{0,39,16547},{30,14,26744},{0,39,16547},{2,63,329},{2,63,329},{2,63,329},{1,44,186},{0,44,4418},{0,36,1709},{0,36,1709},{0,22,1872},{0,23,5702},{0,20,2885},{3,63,34},
+{3,63,34},{3,63,34},{2,42,10},{13,0,4418},{0,36,1709},{0,36,1709},{0,22,1872},{20,2,4418},{0,22,1872},{31,15,9248},{10,63,4570},{4,61,4},{0,56,1268},{31,15,9248},{31,34,9248},{0,56,1268},{0,45,9250},{31,34,9248},{0,45,9250},{1,0,185},{1,0,185},{1,0,185},{1,0,185},{0,13,0},{0,13,0},{0,13,0},{0,8,1},{0,6,97},{0,6,97},{7,63,65535},{4,63,40786},{1,63,1122},
+{0,62,2034},{7,63,65535},{2,63,49800},{0,61,5634},{0,54,27965},{0,63,65535},{0,49,58553},{10,63,15531},{6,63,6593},{4,63,61},{2,58,1482},{25,4,26259},{0,63,15284},{0,55,4484},{0,41,15722},{28,19,26259},{0,41,15722},{2,63,633},{2,63,633},{2,63,633},{2,46,378},{0,49,4418},{0,40,1489},{0,40,1489},{0,24,1665},{0,25,6029},{0,22,2897},{4,63,61},{4,63,61},{4,63,61},{3,44,10},{14,2,4418},
+{0,40,1489},{0,40,1489},{0,24,1665},{24,0,4418},{0,24,1665},{31,19,8978},{11,63,4744},{5,63,0},{0,58,1025},{31,19,8978},{30,38,8978},{0,58,1025},{0,46,8986},{30,38,8978},{0,46,8986},{2,0,377},{2,0,377},{2,0,377},{2,0,377},{0,18,0},{0,18,0},{0,18,0},{0,11,0},{0,8,193},{0,8,193},{8,63,65535},{4,63,40898},{1,63,1890},{1,62,2029},{7,63,65535},{3,63,47871},{0,61,4194},
+{0,56,24760},{0,63,65535},{0,49,55881},{11,63,14325},{8,63,6051},{5,63,100},{3,58,1197},{27,1,24371},{0,63,13716},{0,57,3402},{0,41,13914},{30,19,24371},{0,41,13914},{3,63,1058},{3,63,1058},{3,63,1058},{2,49,618},{0,54,4418},{0,44,1285},{0,44,1285},{0,26,1476},{0,27,6410},{0,25,2937},{5,63,100},{5,63,100},{5,63,100},{4,46,5},{16,0,4418},{0,44,1285},{0,44,1285},{0,26,1476},{26,1,4418},
+{0,26,1476},{31,22,7938},{13,63,4225},{7,63,4},{0,60,628},{31,22,7938},{28,42,7938},{0,60,628},{0,47,7946},{28,42,7938},{0,47,7946},{2,0,617},{2,0,617},{2,0,617},{2,0,617},{0,23,1},{0,23,1},{0,23,1},{0,14,0},{0,11,320},{0,11,320},{8,63,65535},{4,63,41266},{1,63,2914},{1,62,2109},{7,63,65535},{3,63,46175},{0,61,3010},{0,56,21624},{0,63,65535},{0,51,53461},{12,63,13140},
+{8,63,5571},{6,63,157},{4,59,932},{28,1,22568},{0,63,12404},{0,57,2474},{0,43,12155},{30,21,22568},{0,43,12155},{4,63,1630},{4,63,1630},{4,63,1630},{3,51,938},{0,59,4420},{0,46,1117},{0,46,1117},{0,30,1280},{0,31,6822},{0,27,3009},{6,63,157},{6,63,157},{6,63,157},{5,48,4},{17,2,4418},{0,46,1117},{0,46,1117},{0,30,1280},{27,3,4418},{0,30,1280},{30,28,6962},{14,63,3709},{8,63,1},
+{0,60,340},{30,28,6962},{31,40,6962},{0,60,340},{0,48,6964},{31,40,6962},{0,48,6964},{3,0,937},{3,0,937},{3,0,937},{3,0,937},{0,29,0},{0,29,0},{0,29,0},{0,17,0},{0,13,482},{0,13,482},{9,63,65535},{5,63,41956},{2,63,4257},{1,62,2505},{7,63,65535},{3,63,44573},{0,62,1944},{0,56,18402},{0,63,65535},{0,51,50815},{13,63,11930},{10,63,5125},{7,63,250},{5,59,701},{28,5,20642},
+{1,63,11209},{0,59,1634},{0,45,10346},{31,22,20642},{0,45,10346},{4,63,2350},{4,63,2350},{4,63,2350},{3,54,1361},{0,63,4450},{0,51,914},{0,51,914},{0,32,1097},{0,34,7357},{0,29,3131},{7,63,250},{7,63,250},{7,63,250},{6,50,10},{19,1,4418},{0,51,914},{0,51,914},{0,32,1097},{29,4,4418},{0,32,1097},{31,27,5941},{15,63,3176},{10,63,0},{0,62,116},{31,27,5941},{31,42,5941},{0,62,116},
+{0,49,5945},{31,42,5941},{0,49,5945},{3,0,1360},{3,0,1360},{3,0,1360},{3,0,1360},{0,34,1},{0,34,1},{0,34,1},{0,21,1},{0,17,706},{0,17,706},{9,63,65535},{5,63,42660},{2,63,5617},{1,63,3088},{8,63,65535},{3,63,43421},{0,62,1240},{0,56,15810},{0,63,65535},{0,51,48735},{13,63,10922},{11,63,4753},{8,63,360},{6,61,509},{29,5,19021},{2,63,10246},{0,61,1088},{0,47,8885},{31,24,19021},
+{0,47,8885},{5,63,3131},{5,63,3131},{5,63,3131},{4,56,1818},{1,63,4580},{0,55,754},{0,55,754},{0,35,928},{0,36,7846},{0,31,3281},{8,63,360},{8,63,360},{8,63,360},{7,52,10},{20,3,4418},{0,55,754},{0,55,754},{0,35,928},{30,6,4418},{0,35,928},{31,30,5101},{17,63,2777},{11,63,9},{0,62,20},{31,30,5101},{31,43,5101},{0,62,20},{0,50,5105},{31,43,5101},{0,50,5105},{4,0,1818},
+{4,0,1818},{4,0,1818},{4,0,1818},{0,40,0},{0,40,0},{0,40,0},{0,24,0},{0,17,914},{0,17,914},{9,63,65535},{5,63,43620},{2,63,7233},{1,63,3920},{8,63,65535},{3,63,42525},{0,63,738},{0,58,13413},{0,63,65535},{0,51,46911},{14,63,9978},{11,63,4449},{10,63,452},{8,60,344},{31,2,17485},{3,63,9369},{0,61,704},{0,48,7498},{29,29,17485},{0,48,7498},{6,63,4058},{6,63,4058},{6,63,4058},
+{4,59,2315},{2,63,4874},{0,59,610},{0,59,610},{0,37,769},{0,38,8389},{0,32,3497},{10,63,452},{10,63,452},{10,63,452},{8,54,5},{21,5,4418},{0,59,610},{0,59,610},{0,37,769},{31,8,4418},{0,37,769},{31,32,4325},{18,63,2357},{13,63,0},{1,63,0},{31,32,4325},{31,45,4325},{1,63,0},{0,51,4329},{31,45,4325},{0,51,4329},{4,0,2314},{4,0,2314},{4,0,2314},{4,0,2314},{0,45,0},
+{0,45,0},{0,45,0},{0,27,0},{0,19,1184},{0,19,1184},{9,63,65535},{5,63,44836},{2,63,9105},{2,63,4905},{8,63,65535},{3,63,41885},{0,63,482},{0,58,11125},{0,63,65535},{0,51,45343},{15,63,9102},{13,63,4161},{11,63,557},{9,61,212},{30,9,16034},{5,63,8602},{0,63,482},{0,48,6250},{29,31,16034},{0,48,6250},{6,63,5066},{6,63,5066},{6,63,5066},{5,61,2907},{2,63,5322},{0,63,482},{0,63,482},
+{0,39,628},{0,42,8965},{0,36,3717},{11,63,557},{11,63,557},{11,63,557},{9,56,5},{24,0,4418},{0,63,482},{0,63,482},{0,39,628},{31,11,4418},{0,39,628},{31,35,3613},{20,63,1940},{15,63,4},{4,63,1},{31,35,3613},{28,50,3613},{4,63,1},{0,52,3617},{28,50,3613},{0,52,3617},{5,0,2906},{5,0,2906},{5,0,2906},{5,0,2906},{0,50,0},{0,50,0},{0,50,0},{0,30,1},{0,23,1480},
+{0,23,1480},{9,63,65535},{5,63,46510},{3,63,11362},{2,63,6237},{9,63,65535},{3,63,41471},{0,63,500},{0,58,8857},{0,63,65535},{0,53,43697},{16,63,8139},{14,63,3853},{12,63,680},{10,62,89},{30,13,14504},{8,63,7667},{0,63,500},{0,50,4961},{31,31,14504},{0,50,4961},{7,63,6337},{7,63,6337},{7,63,6337},{5,63,3642},{3,63,5962},{0,63,500},{0,63,500},{0,41,493},{0,44,9656},{0,38,3995},{12,63,680},
+{12,63,680},{12,63,680},{10,59,10},{24,6,4418},{0,63,500},{0,63,500},{0,41,493},{29,17,4418},{0,41,493},{31,38,2888},{20,63,1517},{16,63,1},{7,63,1},{31,38,2888},{31,48,2888},{7,63,1},{0,53,2896},{31,48,2888},{0,53,2896},{5,0,3617},{5,0,3617},{5,0,3617},{5,0,3617},{0,56,0},{0,56,0},{0,56,0},{0,34,1},{0,25,1853},{0,25,1853},{10,63,65535},{6,63,48082},{3,63,13570},
+{2,63,7693},{9,63,65535},{3,63,41375},{0,63,788},{0,58,7113},{0,63,65535},{0,53,42465},{17,63,7409},{15,63,3625},{13,63,821},{11,62,34},{31,13,13235},{8,63,6899},{2,63,628},{0,52,3956},{30,34,13235},{0,52,3956},{7,63,7681},{7,63,7681},{7,63,7681},{6,63,4437},{4,63,6659},{1,63,738},{1,63,738},{0,43,394},{0,46,10331},{0,40,4289},{13,63,821},{13,63,821},{13,63,821},{11,61,10},{27,1,4418},
+{2,63,628},{2,63,628},{0,43,394},{30,19,4418},{0,43,394},{31,41,2312},{21,63,1217},{18,63,1},{9,63,0},{31,41,2312},{29,52,2312},{9,63,0},{0,54,2320},{29,52,2312},{0,54,2320},{6,0,4337},{6,0,4337},{6,0,4337},{6,0,4337},{0,61,1},{0,61,1},{0,61,1},{0,37,0},{0,27,2225},{0,27,2225},{10,63,65535},{6,63,49890},{3,63,16034},{2,63,9405},{9,63,65535},{4,63,41526},{0,63,1332},
+{0,59,5520},{0,63,65535},{0,53,41489},{18,63,6747},{16,63,3459},{14,63,980},{12,63,5},{30,20,12051},{10,63,6275},{4,63,801},{0,53,3089},{31,35,12051},{0,53,3089},{8,63,9062},{8,63,9062},{8,63,9062},{7,63,5410},{4,63,7555},{1,63,1154},{1,63,1154},{0,46,306},{0,49,11046},{0,42,4619},{14,63,980},{14,63,980},{14,63,980},{12,62,5},{28,3,4418},{4,63,801},{4,63,801},{0,46,306},{31,21,4418},
+{0,46,306},{30,47,1800},{23,63,949},{19,63,4},{12,63,1},{30,47,1800},{31,51,1800},{12,63,1},{0,55,1808},{31,51,1800},{0,55,1808},{6,0,5105},{6,0,5105},{6,0,5105},{6,0,5105},{0,63,36},{0,63,36},{0,63,36},{0,40,0},{0,29,2633},{0,29,2633},{10,63,65535},{6,63,51954},{3,63,18754},{3,63,11330},{9,63,65535},{4,63,41798},{1,63,2082},{0,60,4084},{0,63,65535},{0,53,40769},{19,63,6153},
+{17,63,3297},{16,63,1154},{13,63,20},{31,20,10952},{11,63,5708},{6,63,965},{0,54,2281},{31,37,10952},{0,54,2281},{9,63,10545},{9,63,10545},{9,63,10545},{7,63,6482},{5,63,8549},{2,63,1716},{2,63,1716},{0,48,208},{0,53,11786},{0,44,4985},{16,63,1154},{16,63,1154},{16,63,1154},{13,63,20},{29,5,4418},{6,63,965},{6,63,965},{0,48,208},{31,24,4418},{0,48,208},{31,46,1352},{23,63,725},{21,63,0},
+{14,63,1},{31,46,1352},{30,54,1352},{14,63,1},{0,56,1360},{30,54,1352},{0,56,1360},{7,0,5953},{7,0,5953},{7,0,5953},{7,0,5953},{1,63,145},{1,63,145},{1,63,145},{0,43,1},{0,31,3077},{0,31,3077},{10,63,65535},{6,63,54582},{4,63,21886},{3,63,13652},{9,63,65535},{4,63,42410},{1,63,3144},{0,60,2770},{0,63,65535},{0,55,40127},{19,63,5649},{18,63,3157},{17,63,1325},{15,63,74},{31,24,9818},
+{13,63,5241},{8,63,1108},{0,56,1538},{29,42,9818},{0,56,1538},{10,63,12376},{10,63,12376},{10,63,12376},{8,63,7844},{6,63,9861},{3,63,2576},{3,63,2576},{0,50,145},{0,55,12659},{0,46,5441},{17,63,1325},{17,63,1325},{17,63,1325},{15,63,74},{31,4,4418},{8,63,1108},{8,63,1108},{0,50,145},{30,29,4418},{0,50,145},{31,49,925},{25,63,505},{23,63,1},{17,63,1},{31,49,925},{30,56,925},{17,63,1},
+{0,58,929},{30,56,925},{0,58,929},{7,0,6970},{7,0,6970},{7,0,6970},{7,0,6970},{1,63,388},{1,63,388},{1,63,388},{0,47,0},{0,34,3625},{0,34,3625},{10,63,65535},{7,63,57052},{4,63,24910},{3,63,15988},{9,63,65535},{4,63,43226},{1,63,4360},{0,61,1833},{0,63,65535},{0,55,39743},{21,63,5202},{19,63,3073},{18,63,1508},{16,63,180},{31,27,8901},{14,63,4814},{10,63,1300},{0,57,1021},{29,44,8901},
+{0,57,1021},{10,63,14136},{10,63,14136},{10,63,14136},{8,63,9252},{7,63,11195},{3,63,3536},{3,63,3536},{0,53,89},{0,59,13491},{0,49,5921},{18,63,1508},{18,63,1508},{18,63,1508},{16,63,180},{30,13,4418},{10,63,1300},{10,63,1300},{0,53,89},{31,31,4418},{0,53,89},{31,51,613},{26,63,337},{24,63,1},{20,63,1},{31,51,613},{31,56,613},{20,63,1},{0,59,617},{31,56,613},{0,59,617},{8,0,7956},
+{8,0,7956},{8,0,7956},{8,0,7956},{2,63,697},{2,63,697},{2,63,697},{0,50,0},{0,36,4141},{0,36,4141},{11,63,65535},{7,63,59708},{4,63,28190},{3,63,18580},{10,63,65535},{5,63,44295},{1,63,5832},{0,61,1081},{0,63,65535},{0,55,39615},{22,63,4818},{20,63,3017},{19,63,1709},{17,63,325},{31,31,8069},{15,63,4473},{11,63,1514},{0,58,593},{31,44,8069},{0,58,593},{11,63,15965},{11,63,15965},{11,63,15965},
+{9,63,10757},{7,63,12667},{4,63,4662},{4,63,4662},{0,55,50},{0,61,14340},{0,51,6395},{19,63,1709},{19,63,1709},{19,63,1709},{17,63,325},{31,15,4418},{11,63,1514},{11,63,1514},{0,55,50},{31,34,4418},{0,55,50},{31,54,365},{27,63,205},{26,63,1},{22,63,1},{31,54,365},{31,58,365},{22,63,1},{0,60,369},{31,58,365},{0,60,369},{8,0,8980},{8,0,8980},{8,0,8980},{8,0,8980},{2,63,1097},
+{2,63,1097},{2,63,1097},{0,53,0},{0,40,4689},{0,40,4689},{11,63,65535},{8,63,58981},{5,63,29551},{4,63,19751},{10,63,65535},{5,63,43215},{2,63,6910},{1,62,614},{0,63,65535},{0,57,34909},{23,63,4502},{21,63,3011},{20,63,1973},{18,63,520},{31,34,7322},{17,63,4242},{13,63,1769},{0,60,274},{31,46,7322},{0,60,274},{12,63,16739},{12,63,16739},{12,63,16739},{10,63,11492},{8,63,13636},{5,63,5510},{5,63,5510},
+{0,58,53},{0,63,14139},{0,53,5981},{20,63,1973},{20,63,1973},{20,63,1973},{18,63,520},{31,20,4418},{13,63,1769},{13,63,1769},{0,58,17},{31,37,4418},{0,58,17},{31,57,181},{28,63,97},{27,63,4},{25,63,0},{31,57,181},{31,59,181},{25,63,0},{0,61,185},{31,59,181},{0,61,185},{9,0,9248},{9,0,9248},{9,0,9248},{9,0,9248},{3,63,1348},{3,63,1348},{3,63,1348},{1,55,4},{0,42,4545},
+{0,42,4545},{12,63,65535},{9,63,57270},{6,63,30345},{5,63,20521},{11,63,65535},{6,63,41449},{3,63,8015},{2,62,242},{0,63,65535},{0,57,28330},{24,63,4181},{22,63,3053},{21,63,2248},{20,63,772},{31,38,6584},{20,63,3941},{15,63,2041},{0,61,77},{31,48,6584},{0,61,77},{13,63,17289},{13,63,17289},{13,63,17289},{11,63,12050},{10,63,14315},{7,63,6389},{7,63,6389},{2,60,41},{0,63,13860},{0,55,5252},{21,63,2248},
+{21,63,2248},{21,63,2248},{20,63,772},{31,26,4418},{15,63,2041},{15,63,2041},{0,60,4},{30,42,4418},{0,60,4},{31,60,50},{30,63,34},{29,63,0},{28,63,1},{31,60,50},{31,61,50},{28,63,1},{0,62,52},{31,61,50},{0,62,52},{10,0,9250},{10,0,9250},{10,0,9250},{10,0,9250},{4,63,1549},{4,63,1549},{4,63,1549},{2,57,2},{0,46,4141},{0,46,4141},{13,63,65535},{9,63,55894},{7,63,31068},
+{6,63,21256},{12,63,65535},{8,63,39740},{4,63,9073},{3,63,90},{0,63,65535},{0,59,23356},{24,63,3973},{23,63,3125},{23,63,2500},{21,63,1037},{30,45,6019},{20,63,3701},{17,63,2340},{0,63,4},{31,50,6019},{0,63,4},{14,63,17796},{14,63,17796},{14,63,17796},{12,63,12625},{11,63,14957},{8,63,7139},{8,63,7139},{3,62,41},{0,63,14020},{0,59,4652},{23,63,2500},{23,63,2500},{23,63,2500},{21,63,1037},{31,31,4418},
+{17,63,2340},{17,63,2340},{1,62,4},{31,44,4418},{1,62,4},{31,62,4},{31,63,4},{31,63,4},{30,63,1},{31,62,4},{31,63,4},{30,63,1},{0,63,4},{31,63,4},{0,63,4},{11,0,9250},{11,0,9250},{11,0,9250},{11,0,9250},{6,63,1765},{6,63,1765},{6,63,1765},{3,59,2},{0,51,3816},{0,51,3816},{13,63,65535},{10,63,53236},{8,63,30487},{7,63,21105},{13,63,65535},{8,63,37332},{5,63,9177},
+{4,63,36},{1,63,65535},{0,59,18680},{25,63,3443},{24,63,2741},{23,63,2248},{22,63,980},{31,44,5163},{21,63,3218},{20,63,2117},{3,63,1},{29,54,5163},{3,63,1},{15,63,17289},{15,63,17289},{15,63,17289},{13,63,12512},{12,63,14328},{9,63,7149},{9,63,7149},{4,63,20},{0,63,13376},{0,59,3944},{23,63,2248},{23,63,2248},{23,63,2248},{22,63,980},{31,34,3872},{20,63,2117},{20,63,2117},{3,63,1},{31,46,3872},
+{3,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{12,0,9248},{12,0,9248},{12,0,9248},{12,0,9248},{7,63,1972},{7,63,1972},{7,63,1972},{4,61,5},{0,55,3488},{0,55,3488},{14,63,65535},{11,63,50266},{9,63,29322},{8,63,20567},{13,63,65535},{9,63,35025},{6,63,8985},{5,63,21},{2,63,65535},{0,59,14712},{26,63,2873},
+{25,63,2283},{24,63,1825},{22,63,820},{29,52,4267},{22,63,2657},{20,63,1685},{5,63,1},{28,56,4267},{5,63,1},{16,63,16427},{16,63,16427},{16,63,16427},{14,63,12185},{13,63,13442},{10,63,6915},{10,63,6915},{5,63,5},{1,63,12539},{0,61,3314},{24,63,1825},{24,63,1825},{24,63,1825},{22,63,820},{31,37,3200},{20,63,1685},{20,63,1685},{5,63,1},{27,52,3200},{5,63,1},{31,63,0},{31,63,0},{31,63,0},
+{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{13,0,9248},{13,0,9248},{13,0,9248},{13,0,9248},{8,63,2250},{8,63,2250},{8,63,2250},{5,63,5},{0,57,3170},{0,57,3170},{15,63,65535},{12,63,47239},{10,63,28065},{9,63,20104},{14,63,65535},{10,63,32574},{7,63,8839},{6,63,54},{3,63,64890},{0,61,10964},{26,63,2252},{25,63,1806},{25,63,1445},{23,63,650},{29,54,3361},
+{23,63,2091},{21,63,1322},{8,63,0},{29,56,3361},{8,63,0},{17,63,15584},{17,63,15584},{17,63,15584},{15,63,11846},{14,63,12522},{11,63,6697},{11,63,6697},{6,63,50},{3,63,11669},{0,63,2834},{25,63,1445},{25,63,1445},{25,63,1445},{23,63,650},{31,40,2521},{21,63,1322},{21,63,1322},{8,63,0},{31,49,2521},{8,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},
+{0,63,0},{31,63,0},{0,63,0},{14,0,9250},{14,0,9250},{14,0,9250},{14,0,9250},{9,63,2525},{9,63,2525},{9,63,2525},{6,63,50},{0,63,2834},{0,63,2834},{16,63,65535},{13,63,44559},{11,63,27000},{10,63,19705},{15,63,64179},{11,63,30525},{8,63,8677},{7,63,149},{3,63,60570},{0,61,8308},{27,63,1782},{26,63,1416},{25,63,1157},{24,63,520},{31,49,2646},{23,63,1691},{22,63,1040},{11,63,1},{30,56,2646},
+{11,63,1},{18,63,14889},{18,63,14889},{18,63,14889},{16,63,11585},{15,63,11778},{12,63,6555},{12,63,6555},{7,63,145},{3,63,11061},{0,63,2610},{25,63,1157},{25,63,1157},{25,63,1157},{24,63,520},{31,42,1985},{22,63,1040},{22,63,1040},{11,63,1},{30,52,1985},{11,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{15,0,9250},
+{15,0,9250},{15,0,9250},{15,0,9250},{10,63,2792},{10,63,2792},{10,63,2792},{7,63,145},{0,63,2610},{0,63,2610},{16,63,63318},{14,63,42019},{12,63,25930},{11,63,19324},{16,63,59178},{11,63,28845},{9,63,8605},{8,63,276},{6,63,56253},{0,61,6420},{27,63,1366},{27,63,1094},{26,63,872},{25,63,397},{31,51,2017},{25,63,1298},{23,63,794},{13,63,1},{31,56,2017},{13,63,1},{19,63,14244},{19,63,14244},{19,63,14244},
+{17,63,11312},{16,63,11037},{13,63,6429},{13,63,6429},{8,63,260},{6,63,10457},{0,63,2642},{26,63,872},{26,63,872},{26,63,872},{25,63,397},{31,45,1513},{23,63,794},{23,63,794},{13,63,1},{31,52,1513},{13,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{16,0,9248},{16,0,9248},{16,0,9248},{16,0,9248},{12,63,3074},
+{12,63,3074},{12,63,3074},{8,63,260},{0,63,2642},{0,63,2642},{17,63,58848},{15,63,39619},{13,63,24975},{12,63,19007},{16,63,54474},{13,63,27057},{10,63,8569},{9,63,461},{8,63,51302},{0,63,5046},{28,63,979},{27,63,806},{27,63,637},{26,63,292},{30,56,1473},{26,63,953},{24,63,605},{16,63,0},{30,58,1473},{16,63,0},{19,63,13604},{19,63,13604},{19,63,13604},{18,63,11057},{16,63,10429},{14,63,6339},{14,63,6339},
+{10,63,424},{8,63,9713},{1,63,2900},{27,63,637},{27,63,637},{27,63,637},{26,63,292},{31,48,1105},{24,63,605},{24,63,605},{16,63,0},{31,54,1105},{16,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{17,0,9248},{17,0,9248},{17,0,9248},{17,0,9248},{12,63,3330},{12,63,3330},{12,63,3330},{10,63,424},{1,63,2900},
+{1,63,2900}, \ No newline at end of file
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m5_alpha.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m5_alpha.inc
new file mode 100644
index 0000000000..433b126a71
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m5_alpha.inc
@@ -0,0 +1,49 @@
+{7,0,47},{7,0,44},{2,0,15},{2,0,12},{8,2,48},{0,0,0},{15,0,27},{15,1,24},{9,0,7},{15,1,24},{23,3,96},{6,0,3},{24,7,27},{24,7,24},{18,3,6},{18,5,4},{24,5,16},{21,1,6},{32,15,27},{32,15,24},{26,11,6},{26,13,4},{32,13,16},{22,3,1},{41,24,27},{41,24,24},{35,20,6},{35,22,4},{41,22,16},{31,12,1},{49,32,27},
+{49,32,24},{43,28,6},{43,30,4},{49,30,16},{39,20,1},{57,40,27},{57,40,24},{51,36,6},{51,38,4},{57,38,16},{47,28,1},{65,48,27},{65,48,24},{59,44,6},{59,46,4},{65,46,16},{55,36,1},{74,57,27},{74,57,24},{68,53,6},{68,55,4},{74,55,16},{64,45,1},{82,65,27},{82,65,24},{76,61,6},{76,63,4},{82,63,16},{72,53,1},{90,73,27},{90,73,24},{84,69,6},
+{84,71,4},{90,71,16},{80,61,1},{98,81,27},{98,81,24},{92,77,6},{92,79,4},{98,79,16},{88,69,1},{107,90,27},{107,90,24},{101,86,6},{101,88,4},{107,88,16},{97,78,1},{115,98,27},{115,98,24},{109,94,6},{109,96,4},{115,96,16},{105,86,1},{123,106,27},{123,106,24},{117,102,6},{117,104,4},{123,104,16},{113,94,1},{131,114,27},{131,114,24},{125,110,6},{125,112,4},{131,112,16},
+{121,102,1},{140,123,27},{140,123,24},{134,119,6},{134,121,4},{140,121,16},{130,111,1},{148,131,27},{148,131,24},{142,127,6},{142,129,4},{148,129,16},{138,119,1},{156,139,27},{156,139,24},{150,135,6},{150,137,4},{156,137,16},{146,127,1},{164,147,27},{164,147,24},{158,143,6},{158,145,4},{164,145,16},{154,135,1},{173,156,27},{173,156,24},{167,152,6},{167,154,4},{173,154,16},{163,144,1},{181,164,27},
+{181,164,24},{175,160,6},{175,162,4},{181,162,16},{171,152,1},{189,172,27},{189,172,24},{183,168,6},{183,170,4},{189,170,16},{179,160,1},{197,180,27},{197,180,24},{191,176,6},{191,178,4},{197,178,16},{187,168,1},{206,189,27},{206,189,24},{200,185,6},{200,187,4},{206,187,16},{196,177,1},{214,197,27},{214,197,24},{208,193,6},{208,195,4},{214,195,16},{204,185,1},{222,205,27},{222,205,24},{216,201,6},
+{216,203,4},{222,203,16},{212,193,1},{230,213,27},{230,213,24},{224,209,6},{224,211,4},{230,211,16},{220,201,1},{239,222,27},{239,222,24},{233,218,6},{233,220,4},{239,220,16},{229,210,1},{247,230,27},{247,230,24},{241,226,6},{241,228,4},{247,228,16},{237,218,1},{255,238,27},{255,238,24},{249,234,6},{249,236,4},{255,236,16},{245,226,1},{255,247,7},{255,248,4},{255,247,7},{255,248,4},{255,0,0},
+{253,234,1},{16,0,47},{16,0,44},{5,0,15},{5,0,12},{17,5,48},{0,0,0},{37,1,111},{36,2,108},{13,0,11},{13,3,12},{37,1,96},{3,0,3},{33,0,27},{33,0,24},{31,0,27},{31,1,24},{45,9,96},{11,0,3},{40,7,27},{41,8,24},{39,7,27},{29,0,4},{41,3,16},{19,1,2},{49,16,27},{50,17,24},{38,5,6},{38,6,4},{50,12,16},{40,4,6},{57,24,27},
+{58,25,24},{46,13,6},{46,14,4},{58,20,16},{36,0,1},{65,32,27},{66,33,24},{54,21,6},{54,22,4},{66,28,16},{44,6,1},{73,40,27},{74,41,24},{62,29,6},{62,30,4},{74,36,16},{52,14,1},{82,49,27},{83,50,24},{71,38,6},{71,39,4},{83,45,16},{61,23,1},{90,57,27},{91,58,24},{79,46,6},{79,47,4},{91,53,16},{69,31,1},{98,65,27},{99,66,24},{87,54,6},
+{87,55,4},{99,61,16},{77,39,1},{106,73,27},{107,74,24},{95,62,6},{95,63,4},{107,69,16},{85,47,1},{115,82,27},{116,83,24},{104,71,6},{104,72,4},{116,78,16},{94,56,1},{123,90,27},{124,91,24},{112,79,6},{112,80,4},{124,86,16},{102,64,1},{131,98,27},{132,99,24},{120,87,6},{120,88,4},{132,94,16},{110,72,1},{139,106,27},{140,107,24},{128,95,6},{128,96,4},{140,102,16},
+{118,80,1},{148,115,27},{149,116,24},{137,104,6},{137,105,4},{149,111,16},{127,89,1},{156,123,27},{157,124,24},{145,112,6},{145,113,4},{157,119,16},{135,97,1},{164,131,27},{165,132,24},{153,120,6},{153,121,4},{165,127,16},{143,105,1},{172,139,27},{173,140,24},{161,128,6},{161,129,4},{173,135,16},{151,113,1},{181,148,27},{182,149,24},{170,137,6},{170,138,4},{182,144,16},{160,122,1},{189,156,27},
+{190,157,24},{178,145,6},{178,146,4},{190,152,16},{168,130,1},{197,164,27},{198,165,24},{186,153,6},{186,154,4},{198,160,16},{176,138,1},{205,172,27},{206,173,24},{194,161,6},{194,162,4},{206,168,16},{184,146,1},{214,181,27},{215,182,24},{203,170,6},{203,171,4},{215,177,16},{193,155,1},{222,189,27},{223,190,24},{211,178,6},{211,179,4},{223,185,16},{201,163,1},{230,197,27},{231,198,24},{219,186,6},
+{219,187,4},{231,193,16},{209,171,1},{238,205,27},{239,206,24},{227,194,6},{227,195,4},{239,201,16},{217,179,1},{247,214,27},{248,215,24},{236,203,6},{236,204,4},{248,210,16},{226,188,1},{255,222,27},{255,222,24},{244,211,6},{244,212,4},{255,220,16},{234,196,1},{254,218,6},{255,242,28},{252,219,6},{252,220,4},{255,245,16},{242,204,1},{255,238,7},{255,239,4},{255,238,7},{255,239,4},{255,0,0},
+{250,212,1},{28,0,47},{28,0,44},{9,0,15},{9,0,12},{29,9,48},{0,0,0},{53,0,111},{53,0,108},{17,0,15},{17,0,12},{37,7,32},{0,0,0},{66,3,111},{63,7,108},{25,0,11},{25,7,12},{65,5,96},{7,0,3},{51,0,27},{71,15,108},{47,0,27},{33,6,8},{73,13,96},{15,0,3},{61,4,27},{80,24,108},{61,4,27},{60,6,24},{62,0,16},{24,4,3},{69,12,27},
+{88,32,108},{69,12,27},{68,14,24},{70,8,16},{32,2,2},{77,20,27},{96,40,108},{58,2,6},{58,2,4},{78,16,16},{60,0,6},{85,28,27},{104,48,108},{66,10,6},{66,10,4},{86,24,16},{68,8,6},{94,37,27},{113,57,108},{75,19,6},{75,19,4},{95,33,16},{77,17,6},{102,45,27},{121,65,108},{83,27,6},{83,27,4},{103,41,16},{65,3,1},{110,53,27},{129,73,108},{91,35,6},
+{91,35,4},{111,49,16},{73,11,1},{118,61,27},{137,81,108},{99,43,6},{99,43,4},{119,57,16},{81,19,1},{127,70,27},{146,90,108},{108,52,6},{108,52,4},{128,66,16},{90,28,1},{135,78,27},{154,98,108},{116,60,6},{116,60,4},{136,74,16},{98,36,1},{143,86,27},{162,106,108},{124,68,6},{124,68,4},{144,82,16},{106,44,1},{151,94,27},{170,114,108},{132,76,6},{132,76,4},{152,90,16},
+{114,52,1},{160,103,27},{179,123,108},{141,85,6},{141,85,4},{161,99,16},{123,61,1},{168,111,27},{187,131,108},{149,93,6},{149,93,4},{169,107,16},{131,69,1},{176,119,27},{195,139,108},{157,101,6},{157,101,4},{177,115,16},{139,77,1},{184,127,27},{203,147,108},{165,109,6},{165,109,4},{185,123,16},{147,85,1},{193,136,27},{212,156,108},{174,118,6},{174,118,4},{194,132,16},{156,94,1},{201,144,27},
+{220,164,108},{182,126,6},{182,126,4},{202,140,16},{164,102,1},{209,152,27},{228,172,108},{190,134,6},{190,134,4},{210,148,16},{172,110,1},{217,160,27},{236,180,108},{198,142,6},{198,142,4},{218,156,16},{180,118,1},{226,169,27},{245,189,108},{207,151,6},{207,151,4},{227,165,16},{189,127,1},{234,177,27},{253,197,108},{215,159,6},{215,159,4},{235,173,16},{197,135,1},{242,185,27},{243,186,24},{223,167,6},
+{223,167,4},{243,181,16},{205,143,1},{250,193,27},{251,194,24},{231,175,6},{231,175,4},{251,189,16},{213,151,1},{255,203,27},{255,206,24},{240,184,6},{240,184,4},{255,208,16},{222,160,1},{251,188,6},{255,230,28},{248,192,6},{248,192,4},{255,233,16},{230,168,1},{255,200,6},{255,202,4},{255,200,6},{255,202,4},{255,0,0},{238,176,1},{255,226,7},{255,227,4},{255,226,7},{255,227,4},{255,0,0},
+{246,184,1},{41,0,47},{41,0,44},{13,0,15},{13,0,12},{42,13,48},{0,0,0},{71,0,111},{71,0,108},{21,0,15},{21,0,12},{50,7,32},{0,0,0},{86,1,111},{85,2,108},{29,1,15},{29,3,12},{87,0,96},{3,0,3},{96,6,111},{93,10,108},{37,0,11},{37,11,12},{95,8,96},{11,0,3},{71,0,27},{102,19,108},{68,0,27},{46,7,8},{104,17,96},{20,0,3},{82,0,27},
+{110,27,108},{81,0,27},{80,2,24},{112,25,96},{28,0,3},{91,7,27},{118,35,108},{91,7,27},{88,10,24},{91,2,16},{36,7,3},{99,15,27},{126,43,108},{99,15,27},{96,18,24},{99,10,16},{44,1,2},{108,24,27},{135,52,108},{108,24,27},{79,0,4},{108,19,16},{53,10,2},{116,32,27},{143,60,108},{87,5,6},{87,7,4},{116,27,16},{90,3,6},{124,40,27},{151,68,108},{95,13,6},
+{95,15,4},{124,35,16},{98,11,6},{132,48,27},{159,76,108},{103,21,6},{103,23,4},{132,43,16},{106,19,6},{141,57,27},{168,85,108},{112,30,6},{112,32,4},{141,52,16},{115,28,6},{149,65,27},{176,93,108},{120,38,6},{120,40,4},{149,60,16},{94,5,1},{157,73,27},{184,101,108},{128,46,6},{128,48,4},{157,68,16},{102,13,1},{165,81,27},{192,109,108},{136,54,6},{136,56,4},{165,76,16},
+{110,21,1},{174,90,27},{201,118,108},{145,63,6},{145,65,4},{174,85,16},{119,30,1},{182,98,27},{209,126,108},{153,71,6},{153,73,4},{182,93,16},{127,38,1},{190,106,27},{217,134,108},{161,79,6},{161,81,4},{190,101,16},{135,46,1},{198,114,27},{225,142,108},{169,87,6},{169,89,4},{198,109,16},{143,54,1},{207,123,27},{234,151,108},{178,96,6},{178,98,4},{207,118,16},{152,63,1},{215,131,27},
+{242,159,108},{186,104,6},{186,106,4},{215,126,16},{160,71,1},{223,139,27},{250,167,108},{194,112,6},{194,114,4},{223,134,16},{168,79,1},{231,147,27},{231,147,24},{202,120,6},{202,122,4},{231,142,16},{176,87,1},{240,156,27},{240,156,24},{211,129,6},{211,131,4},{240,151,16},{185,96,1},{248,164,27},{248,164,24},{219,137,6},{219,139,4},{248,159,16},{193,104,1},{254,173,27},{255,174,24},{227,145,6},
+{227,147,4},{255,169,16},{201,112,1},{255,182,27},{255,187,24},{235,153,6},{235,155,4},{255,193,16},{209,120,1},{249,159,6},{255,218,28},{244,162,6},{244,164,4},{255,220,16},{218,129,1},{254,169,6},{254,168,4},{252,170,6},{252,172,4},{255,245,16},{226,137,1},{255,184,6},{255,190,4},{255,184,6},{255,190,4},{255,0,0},{234,145,1},{255,213,7},{255,214,4},{255,213,7},{255,214,4},{255,0,0},
+{242,153,1},{59,0,47},{59,0,44},{18,0,15},{18,0,12},{60,18,48},{0,0,0},{69,0,47},{68,2,44},{26,0,15},{26,0,12},{68,5,32},{0,0,0},{111,0,111},{111,0,108},{34,0,15},{34,0,12},{76,13,32},{0,0,0},{123,3,111},{122,5,108},{42,3,15},{42,6,12},{125,1,96},{6,0,3},{135,8,111},{131,14,108},{50,0,11},{51,15,12},{134,10,96},{15,0,3},{95,0,27},
+{139,22,108},{59,2,11},{59,5,8},{142,18,96},{23,0,3},{105,0,27},{147,30,108},{99,0,27},{67,13,8},{150,26,96},{31,0,3},{115,0,27},{155,38,108},{113,1,27},{110,4,24},{158,34,96},{39,0,3},{125,7,27},{164,47,108},{125,7,27},{119,13,24},{167,43,96},{48,6,3},{133,15,27},{172,55,108},{133,15,27},{127,21,24},{134,5,16},{56,14,3},{141,23,27},{180,63,108},{141,23,27},
+{135,29,24},{142,13,16},{64,1,2},{149,31,27},{188,71,108},{149,31,27},{143,37,24},{150,21,16},{72,9,2},{158,40,27},{197,80,108},{118,1,6},{117,6,4},{159,30,16},{120,0,6},{166,48,27},{205,88,108},{126,9,6},{125,14,4},{167,38,16},{130,6,6},{174,56,27},{213,96,108},{134,17,6},{133,22,4},{175,46,16},{138,14,6},{182,64,27},{221,104,108},{142,25,6},{141,30,4},{183,54,16},
+{146,22,6},{191,73,27},{230,113,108},{151,34,6},{150,39,4},{192,63,16},{155,31,6},{199,81,27},{238,121,108},{159,42,6},{158,47,4},{200,71,16},{163,39,6},{207,89,27},{246,129,108},{167,50,6},{166,55,4},{208,79,16},{130,1,1},{215,97,27},{254,137,108},{175,58,6},{174,63,4},{216,87,16},{138,9,1},{224,106,27},{224,106,24},{184,67,6},{183,72,4},{225,96,16},{147,18,1},{232,114,27},
+{232,114,24},{192,75,6},{191,80,4},{233,104,16},{155,26,1},{240,122,27},{240,122,24},{200,83,6},{199,88,4},{241,112,16},{163,34,1},{248,130,27},{248,130,24},{208,91,6},{207,96,4},{249,120,16},{171,42,1},{255,140,27},{254,142,24},{217,100,6},{216,105,4},{255,135,16},{180,51,1},{255,149,27},{255,156,24},{225,108,6},{224,113,4},{255,159,16},{188,59,1},{255,159,27},{253,196,28},{233,116,6},
+{232,121,4},{255,184,16},{196,67,1},{247,120,6},{255,205,28},{241,124,6},{240,129,4},{255,208,16},{204,75,1},{252,132,6},{252,132,4},{250,133,6},{249,138,4},{255,236,16},{213,84,1},{255,144,6},{255,150,4},{255,144,6},{255,150,4},{255,0,0},{221,92,1},{254,185,7},{255,175,4},{253,187,7},{255,175,4},{255,0,0},{229,100,1},{255,196,7},{255,199,4},{255,196,7},{255,199,4},{255,0,0},
+{237,108,1},{80,0,47},{80,0,44},{24,0,15},{24,0,12},{80,24,48},{0,0,0},{88,1,47},{88,1,44},{32,0,15},{32,0,12},{88,4,32},{0,0,0},{138,0,111},{138,0,108},{40,0,15},{40,0,12},{96,12,32},{0,0,0},{153,0,111},{153,0,108},{48,0,15},{48,0,12},{104,20,32},{0,0,0},{166,4,111},{164,8,108},{57,4,15},{57,9,12},{167,3,96},{9,0,3},{176,9,111},
+{172,16,108},{65,0,11},{65,17,12},{175,11,96},{17,0,3},{189,13,111},{180,24,108},{73,0,11},{73,1,8},{183,19,96},{25,0,3},{129,0,27},{188,32,108},{83,2,11},{81,9,8},{191,27,96},{33,0,3},{141,0,27},{197,41,108},{132,0,27},{90,18,8},{200,36,96},{42,0,3},{151,0,27},{205,49,108},{148,0,27},{145,3,24},{208,44,96},{50,0,3},{160,3,27},{213,57,108},{160,3,27},
+{153,11,24},{216,52,96},{58,2,3},{168,11,27},{221,65,108},{168,11,27},{161,19,24},{170,0,16},{66,10,3},{177,20,27},{230,74,108},{177,20,27},{170,28,24},{179,7,16},{75,19,3},{185,28,27},{238,82,108},{185,28,27},{178,36,24},{187,15,16},{83,0,2},{193,36,27},{246,90,108},{193,36,27},{186,44,24},{195,23,16},{91,7,2},{201,44,27},{254,98,108},{201,44,27},{147,0,4},{203,31,16},
+{99,15,2},{210,53,27},{211,54,24},{157,1,6},{156,9,4},{212,40,16},{108,24,2},{218,61,27},{219,62,24},{165,9,6},{164,17,4},{220,48,16},{170,6,6},{226,69,27},{227,70,24},{173,17,6},{172,25,4},{228,56,16},{178,14,6},{234,77,27},{235,78,24},{181,25,6},{180,33,4},{236,64,16},{186,22,6},{243,86,27},{244,87,24},{190,34,6},{189,42,4},{245,73,16},{195,31,6},{251,94,27},
+{252,95,24},{198,42,6},{197,50,4},{253,81,16},{203,39,6},{255,104,27},{255,107,24},{206,50,6},{205,58,4},{255,102,16},{211,47,6},{255,113,27},{255,123,24},{214,58,6},{213,66,4},{255,126,16},{219,55,6},{255,126,27},{253,172,28},{223,67,6},{222,75,4},{255,153,16},{174,2,1},{242,66,6},{254,182,28},{231,75,6},{230,83,4},{255,178,16},{182,10,1},{246,79,6},{255,190,28},{239,83,6},
+{238,91,4},{255,202,16},{190,18,1},{251,89,6},{251,88,4},{247,91,6},{246,99,4},{255,227,16},{198,26,1},{255,102,6},{255,108,4},{255,102,6},{255,108,4},{255,0,0},{207,35,1},{255,117,6},{255,132,4},{255,117,6},{255,132,4},{255,0,0},{215,43,1},{254,167,7},{255,156,4},{254,167,7},{255,156,4},{255,0,0},{223,51,1},{255,175,7},{255,181,4},{255,175,7},{255,181,4},{255,0,0},
+{231,59,1},{105,0,47},{105,0,44},{33,0,15},{33,0,12},{106,33,48},{0,0,0},{115,0,47},{114,2,44},{41,0,15},{41,0,12},{114,5,32},{0,0,0},{123,2,47},{124,3,44},{49,0,15},{49,0,12},{122,13,32},{0,0,0},{190,0,111},{190,0,108},{57,0,15},{57,0,12},{130,21,32},{0,0,0},{205,0,111},{205,0,108},{66,0,15},{66,0,12},{139,30,32},{0,0,0},{217,4,111},
+{215,7,108},{74,4,15},{74,8,12},{218,3,96},{8,0,3},{229,8,111},{223,15,108},{80,0,11},{82,16,12},{226,11,96},{16,0,3},{237,13,111},{231,23,108},{89,0,11},{90,24,12},{234,19,96},{24,0,3},{251,17,111},{240,32,108},{99,0,11},{99,1,8},{243,28,96},{33,0,3},{169,0,27},{248,40,108},{108,2,11},{107,9,8},{251,36,96},{41,0,3},{181,0,27},{254,49,108},{166,0,27},
+{115,17,8},{188,79,32},{49,0,3},{190,0,27},{255,59,108},{181,0,27},{123,25,8},{196,87,32},{57,0,3},{203,0,27},{203,0,24},{197,0,27},{196,2,24},{205,96,32},{66,0,3},{213,1,27},{212,3,24},{211,2,27},{204,10,24},{213,104,32},{74,1,3},{221,9,27},{220,11,24},{219,10,27},{212,18,24},{221,0,16},{82,9,3},{229,17,27},{228,19,24},{227,18,27},{220,26,24},{229,5,16},
+{90,17,3},{238,26,27},{237,28,24},{236,27,27},{229,35,24},{238,14,16},{99,26,3},{246,34,27},{245,36,24},{244,35,27},{237,43,24},{246,22,16},{107,34,3},{254,42,27},{253,44,24},{252,43,27},{245,51,24},{254,30,16},{115,6,2},{255,52,27},{255,58,24},{255,52,27},{253,59,24},{255,53,16},{123,14,2},{255,64,27},{255,74,24},{196,0,6},{198,100,8},{255,80,16},{132,23,2},{255,74,27},
+{255,89,24},{206,1,6},{206,4,4},{255,105,16},{140,31,2},{255,86,27},{253,147,28},{215,7,6},{214,12,4},{255,129,16},{219,4,6},{255,95,27},{255,155,28},{223,15,6},{222,20,4},{255,153,16},{227,12,6},{242,17,6},{255,166,28},{232,24,6},{231,29,4},{255,181,16},{236,21,6},{247,26,6},{255,175,28},{240,32,6},{239,37,4},{255,205,16},{244,29,6},{251,38,6},{251,37,4},{248,40,6},
+{247,45,4},{255,230,16},{252,37,6},{255,50,6},{255,53,4},{255,50,6},{255,53,4},{255,0,0},{189,80,2},{255,65,6},{255,80,4},{255,65,6},{255,80,4},{255,0,0},{198,89,2},{252,131,7},{255,105,4},{252,131,7},{255,105,4},{255,0,0},{206,97,2},{254,139,7},{255,129,4},{253,141,7},{255,129,4},{255,0,0},{214,105,2},{255,150,7},{255,153,4},{255,150,7},{255,153,4},{255,0,0},
+{222,0,1},{181,0,47},{178,0,44},{47,0,15},{47,0,12},{183,47,48},{0,0,0},{190,0,47},{190,0,44},{55,0,15},{55,0,12},{191,55,48},{0,0,0},{199,0,47},{199,0,44},{63,0,15},{63,0,12},{199,63,48},{0,0,0},{207,0,47},{207,1,44},{71,0,15},{71,0,12},{207,4,32},{0,0,0},{216,1,47},{218,3,44},{80,0,15},{80,0,12},{216,13,32},{0,0,0},{225,1,47},
+{227,6,44},{88,0,15},{88,0,12},{224,21,32},{0,0,0},{233,2,47},{235,11,44},{96,1,15},{96,2,12},{232,29,32},{2,0,3},{241,4,47},{243,19,44},{104,5,15},{104,10,12},{240,37,32},{10,0,3},{251,5,47},{252,28,44},{113,9,15},{113,19,12},{249,46,32},{19,0,3},{255,9,47},{255,37,44},{117,0,11},{121,27,12},{255,55,32},{27,0,3},{255,9,47},{255,46,44},{126,0,11},
+{129,35,12},{255,67,32},{35,0,3},{248,0,27},{255,55,44},{137,0,11},{137,43,12},{255,79,32},{43,0,3},{250,0,27},{255,64,44},{147,2,11},{146,6,8},{255,93,32},{52,0,3},{251,0,27},{255,73,44},{155,4,11},{154,14,8},{255,104,32},{60,0,3},{253,0,27},{248,0,24},{233,0,27},{162,22,8},{255,116,32},{68,0,3},{254,0,27},{254,0,24},{248,0,27},{170,30,8},{255,128,32},
+{76,0,3},{255,1,27},{255,7,24},{255,1,27},{179,39,8},{255,22,16},{85,0,3},{255,2,27},{255,22,24},{255,7,27},{187,47,8},{255,47,16},{93,0,3},{255,4,27},{251,100,28},{182,0,7},{195,55,8},{255,71,16},{101,0,3},{255,4,27},{253,108,28},{191,0,7},{203,63,8},{255,95,16},{109,0,3},{255,7,27},{255,118,28},{200,0,7},{212,72,8},{255,123,16},{118,0,3},{246,0,7},
+{255,129,28},{209,0,7},{220,80,8},{255,147,16},{126,0,3},{246,0,7},{255,138,28},{218,0,7},{228,88,8},{255,172,16},{134,0,3},{249,3,7},{245,91,8},{228,3,7},{236,96,8},{255,196,16},{142,6,3},{251,14,7},{250,102,8},{237,12,7},{245,105,8},{255,223,16},{151,15,3},{253,22,7},{254,112,8},{245,20,7},{253,113,8},{255,248,16},{159,23,3},{253,31,7},{255,124,8},{249,28,7},
+{255,124,8},{255,0,0},{167,31,3},{254,39,7},{255,10,4},{252,37,7},{255,10,4},{255,0,0},{175,39,3},{255,48,7},{255,38,4},{254,48,7},{255,38,4},{255,0,0},{184,48,3},{255,56,7},{255,62,4},{255,56,7},{255,62,4},{255,0,0},{192,56,3},{255,65,7},{255,86,4},{255,65,7},{255,86,4},{255,0,0},{200,64,3},{255,74,7},{255,111,4},{255,77,7},{255,111,4},{255,0,0},
+{208,5,2}, \ No newline at end of file
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m5_color.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m5_color.inc
new file mode 100644
index 0000000000..357b14b7a1
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m5_color.inc
@@ -0,0 +1,481 @@
+{0,7,18},{0,5,2},{0,4,1},{0,3,8},{0,4,35},{0,3,24},{0,3,12},{0,2,29},{0,2,36},{0,2,30},{0,7,18},{0,5,2},{0,4,1},{0,3,8},{2,0,35},{0,3,24},{0,3,12},{0,2,29},{4,0,35},{0,2,29},{0,3,0},{0,3,0},{0,3,0},{0,1,1},{0,1,2},{0,1,2},{0,1,2},{0,1,1},{1,0,3},{0,1,2},{0,3,0},
+{0,3,0},{0,3,0},{0,1,1},{1,0,2},{1,0,2},{1,0,2},{0,1,1},{1,0,2},{0,1,1},{4,0,18},{0,5,2},{0,4,1},{0,3,8},{4,0,18},{7,0,18},{0,3,8},{0,2,20},{7,0,18},{0,2,20},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,15,38},{2,11,20},{2,8,24},
+{1,8,21},{0,16,51},{0,10,19},{0,8,2},{0,6,24},{0,8,76},{0,6,40},{3,13,18},{3,10,2},{3,8,1},{3,7,5},{8,0,51},{1,9,19},{0,8,2},{0,6,24},{16,0,51},{0,6,24},{2,11,20},{2,11,20},{2,11,20},{1,7,20},{0,12,8},{0,7,2},{0,7,2},{0,5,1},{0,5,19},{0,5,10},{3,9,0},{3,9,0},{3,9,0},{3,6,0},{6,0,8},
+{1,7,0},{1,7,0},{0,5,1},{12,0,8},{0,5,1},{10,0,18},{2,11,0},{3,8,1},{0,8,1},{10,0,18},{20,0,18},{0,8,1},{0,6,20},{20,0,18},{0,6,20},{1,0,20},{1,0,20},{1,0,20},{1,0,20},{0,9,0},{0,9,0},{0,9,0},{0,4,1},{0,3,8},{0,3,8},{6,19,38},{6,15,20},{6,12,24},{5,12,21},{4,20,51},{4,14,19},{4,12,2},
+{4,10,24},{0,14,52},{1,10,20},{7,17,18},{7,14,2},{7,12,1},{7,11,5},{14,0,51},{5,13,19},{4,12,2},{1,10,20},{29,0,51},{1,10,20},{6,15,20},{6,15,20},{6,15,20},{5,11,20},{4,16,8},{4,11,2},{4,11,2},{4,9,1},{0,12,8},{1,9,2},{7,13,0},{7,13,0},{7,13,0},{7,10,0},{12,0,8},{5,11,0},{5,11,0},{3,9,0},{24,0,8},
+{3,9,0},{15,1,18},{6,15,0},{7,12,1},{3,12,0},{15,1,18},{32,0,18},{3,12,0},{0,10,20},{32,0,18},{0,10,20},{5,0,20},{5,0,20},{5,0,20},{5,0,20},{4,13,0},{4,13,0},{4,13,0},{4,8,1},{1,10,0},{1,10,0},{10,23,38},{10,19,20},{10,16,24},{9,16,21},{8,24,51},{8,18,19},{8,16,2},{8,14,24},{3,18,52},{5,14,20},{11,21,18},
+{11,18,2},{11,16,1},{11,15,5},{20,0,51},{9,17,19},{8,16,2},{5,14,20},{41,0,51},{5,14,20},{10,19,20},{10,19,20},{10,19,20},{9,15,20},{8,20,8},{8,15,2},{8,15,2},{8,13,1},{4,16,8},{5,13,2},{11,17,0},{11,17,0},{11,17,0},{11,14,0},{18,0,8},{9,15,0},{9,15,0},{7,13,0},{36,0,8},{7,13,0},{21,1,18},{10,19,0},{11,16,1},
+{7,16,0},{21,1,18},{44,0,18},{7,16,0},{0,14,20},{44,0,18},{0,14,20},{9,0,20},{9,0,20},{9,0,20},{9,0,20},{8,17,0},{8,17,0},{8,17,0},{8,12,1},{5,14,0},{5,14,0},{14,29,36},{14,24,18},{14,21,23},{14,20,20},{13,28,52},{13,22,20},{13,20,2},{12,19,23},{7,23,51},{9,19,18},{16,25,19},{15,23,1},{16,20,2},{15,20,6},{27,0,51},
+{13,22,19},{13,20,1},{8,19,18},{55,0,51},{8,19,18},{14,24,18},{14,24,18},{14,24,18},{14,19,18},{13,23,9},{13,20,1},{13,20,1},{12,17,2},{9,20,8},{10,18,1},{16,20,1},{16,20,1},{16,20,1},{16,18,1},{24,1,8},{14,19,0},{14,19,0},{12,17,1},{50,0,8},{12,17,1},{28,0,18},{15,23,0},{16,20,1},{12,20,1},{28,0,18},{58,0,18},{12,20,1},
+{0,19,18},{58,0,18},{0,19,18},{14,0,18},{14,0,18},{14,0,18},{14,0,18},{13,20,1},{13,20,1},{13,20,1},{12,17,1},{10,18,0},{10,18,0},{18,33,36},{18,28,18},{18,25,23},{18,24,20},{17,32,52},{17,26,20},{17,24,2},{16,23,23},{11,27,51},{13,23,18},{20,29,19},{19,27,1},{20,24,2},{19,24,6},{33,0,51},{17,26,19},{17,24,1},{12,23,18},{66,0,51},
+{12,23,18},{18,28,18},{18,28,18},{18,28,18},{18,23,18},{17,27,9},{17,24,1},{17,24,1},{16,21,2},{13,24,8},{14,22,1},{20,24,1},{20,24,1},{20,24,1},{20,22,1},{30,1,8},{18,23,0},{18,23,0},{16,21,1},{62,0,8},{16,21,1},{34,0,18},{19,27,0},{20,24,1},{16,24,1},{34,0,18},{69,0,18},{16,24,1},{0,23,18},{69,0,18},{0,23,18},{18,0,18},
+{18,0,18},{18,0,18},{18,0,18},{17,24,1},{17,24,1},{17,24,1},{16,21,1},{14,22,0},{14,22,0},{22,37,36},{22,32,18},{22,29,23},{22,28,20},{21,36,52},{21,30,20},{21,28,2},{20,27,23},{15,31,51},{17,27,18},{24,33,19},{23,31,1},{24,28,2},{23,28,6},{39,0,51},{21,30,19},{21,28,1},{16,27,18},{78,0,51},{16,27,18},{22,32,18},{22,32,18},{22,32,18},
+{22,27,18},{21,31,9},{21,28,1},{21,28,1},{20,25,2},{17,28,8},{18,26,1},{24,28,1},{24,28,1},{24,28,1},{24,26,1},{36,1,8},{22,27,0},{22,27,0},{20,25,1},{74,0,8},{20,25,1},{40,0,18},{23,31,0},{24,28,1},{20,28,1},{40,0,18},{82,0,18},{20,28,1},{0,27,18},{82,0,18},{0,27,18},{22,0,18},{22,0,18},{22,0,18},{22,0,18},{21,28,1},
+{21,28,1},{21,28,1},{20,25,1},{18,26,0},{18,26,0},{26,41,36},{26,36,18},{26,33,23},{26,32,20},{25,40,52},{25,34,20},{25,32,2},{24,31,23},{19,35,51},{21,31,18},{28,37,19},{27,35,1},{28,32,2},{27,32,6},{45,0,51},{25,34,19},{25,32,1},{20,31,18},{91,0,51},{20,31,18},{26,36,18},{26,36,18},{26,36,18},{26,31,18},{25,35,9},{25,32,1},{25,32,1},
+{24,29,2},{21,32,8},{22,30,1},{28,32,1},{28,32,1},{28,32,1},{28,30,1},{42,1,8},{26,31,0},{26,31,0},{24,29,1},{86,0,8},{24,29,1},{46,0,18},{27,35,0},{28,32,1},{24,32,1},{46,0,18},{94,0,18},{24,32,1},{0,31,18},{94,0,18},{0,31,18},{26,0,18},{26,0,18},{26,0,18},{26,0,18},{25,32,1},{25,32,1},{25,32,1},{24,29,1},{22,30,0},
+{22,30,0},{31,44,38},{31,40,20},{31,37,24},{30,37,21},{29,45,51},{29,39,19},{29,37,2},{29,35,24},{24,39,52},{26,35,20},{32,42,18},{32,39,2},{32,37,1},{32,36,5},{51,0,51},{30,38,19},{29,37,2},{26,35,20},{104,0,51},{26,35,20},{31,40,20},{31,40,20},{31,40,20},{30,36,20},{29,41,8},{29,36,2},{29,36,2},{29,34,1},{25,37,8},{26,34,2},{32,38,0},
+{32,38,0},{32,38,0},{32,35,0},{49,0,8},{30,36,0},{30,36,0},{28,34,0},{100,0,8},{28,34,0},{53,0,18},{31,40,0},{32,37,1},{28,37,0},{53,0,18},{107,0,18},{28,37,0},{0,35,20},{107,0,18},{0,35,20},{30,0,20},{30,0,20},{30,0,20},{30,0,20},{29,38,0},{29,38,0},{29,38,0},{29,33,1},{26,35,0},{26,35,0},{35,48,38},{35,44,20},{35,41,24},
+{34,41,21},{33,49,51},{33,43,19},{33,41,2},{33,39,24},{28,43,52},{30,39,20},{36,46,18},{36,43,2},{36,41,1},{36,40,5},{57,0,51},{34,42,19},{33,41,2},{30,39,20},{117,0,51},{30,39,20},{35,44,20},{35,44,20},{35,44,20},{34,40,20},{33,45,8},{33,40,2},{33,40,2},{33,38,1},{29,41,8},{30,38,2},{36,42,0},{36,42,0},{36,42,0},{36,39,0},{55,0,8},
+{34,40,0},{34,40,0},{32,38,0},{112,0,8},{32,38,0},{59,0,18},{35,44,0},{36,41,1},{32,41,0},{59,0,18},{120,0,18},{32,41,0},{0,39,20},{120,0,18},{0,39,20},{34,0,20},{34,0,20},{34,0,20},{34,0,20},{33,42,0},{33,42,0},{33,42,0},{33,37,1},{30,39,0},{30,39,0},{39,52,38},{39,48,20},{39,45,24},{38,45,21},{37,53,51},{37,47,19},{37,45,2},
+{37,43,24},{32,47,52},{34,43,20},{40,50,18},{40,47,2},{40,45,1},{40,44,5},{63,0,51},{38,46,19},{37,45,2},{34,43,20},{127,1,51},{34,43,20},{39,48,20},{39,48,20},{39,48,20},{38,44,20},{37,49,8},{37,44,2},{37,44,2},{37,42,1},{33,45,8},{34,42,2},{40,46,0},{40,46,0},{40,46,0},{40,43,0},{61,0,8},{38,44,0},{38,44,0},{36,42,0},{124,0,8},
+{36,42,0},{64,0,18},{39,48,0},{40,45,1},{36,45,0},{64,0,18},{126,3,18},{36,45,0},{0,43,20},{126,3,18},{0,43,20},{38,0,20},{38,0,20},{38,0,20},{38,0,20},{37,46,0},{37,46,0},{37,46,0},{37,41,1},{34,43,0},{34,43,0},{43,56,38},{43,52,20},{43,49,24},{42,49,21},{41,57,51},{41,51,19},{41,49,2},{41,47,24},{36,51,52},{38,47,20},{44,54,18},
+{44,51,2},{44,49,1},{44,48,5},{69,0,51},{42,50,19},{41,49,2},{38,47,20},{127,7,51},{38,47,20},{43,52,20},{43,52,20},{43,52,20},{42,48,20},{41,53,8},{41,48,2},{41,48,2},{41,46,1},{37,49,8},{38,46,2},{44,50,0},{44,50,0},{44,50,0},{44,47,0},{66,1,8},{42,48,0},{42,48,0},{40,46,0},{126,5,8},{40,46,0},{70,0,18},{43,52,0},{44,49,1},
+{40,49,0},{70,0,18},{126,9,18},{40,49,0},{0,47,20},{126,9,18},{0,47,20},{42,0,20},{42,0,20},{42,0,20},{42,0,20},{41,50,0},{41,50,0},{41,50,0},{41,45,1},{38,47,0},{38,47,0},{47,62,36},{47,57,18},{47,54,23},{47,53,20},{46,61,52},{46,55,20},{46,53,2},{45,52,23},{40,56,51},{42,52,18},{49,58,19},{48,56,1},{49,53,2},{48,53,6},{75,1,51},
+{46,55,19},{46,53,1},{41,52,18},{126,14,51},{41,52,18},{47,57,18},{47,57,18},{47,57,18},{47,52,18},{46,56,9},{46,53,1},{46,53,1},{45,50,2},{42,53,8},{43,51,1},{49,53,1},{49,53,1},{49,53,1},{49,51,1},{73,0,8},{47,52,0},{47,52,0},{45,50,1},{126,12,8},{45,50,1},{77,0,18},{48,56,0},{49,53,1},{45,53,1},{77,0,18},{127,15,18},{45,53,1},
+{0,52,18},{127,15,18},{0,52,18},{47,0,18},{47,0,18},{47,0,18},{47,0,18},{46,53,1},{46,53,1},{46,53,1},{45,50,1},{43,51,0},{43,51,0},{51,65,36},{51,61,18},{51,58,23},{51,57,20},{50,64,52},{50,59,20},{50,57,2},{49,56,23},{44,60,51},{46,56,18},{53,62,19},{52,60,1},{53,57,2},{52,57,6},{81,0,51},{50,59,19},{50,57,1},{45,56,18},{126,20,51},
+{45,56,18},{51,61,18},{51,61,18},{51,61,18},{51,56,18},{50,60,9},{50,57,1},{50,57,1},{49,54,2},{46,57,8},{47,55,1},{53,57,1},{53,57,1},{53,57,1},{53,55,1},{79,0,8},{51,56,0},{51,56,0},{49,54,1},{127,17,8},{49,54,1},{83,0,18},{52,60,0},{53,57,1},{49,57,1},{83,0,18},{127,21,18},{49,57,1},{0,56,18},{127,21,18},{0,56,18},{51,0,18},
+{51,0,18},{51,0,18},{51,0,18},{50,57,1},{50,57,1},{50,57,1},{49,54,1},{47,55,0},{47,55,0},{55,69,36},{55,64,19},{55,62,23},{55,61,20},{54,68,52},{54,63,20},{54,61,2},{53,60,23},{48,64,51},{50,60,18},{57,65,19},{56,64,2},{57,61,2},{56,61,6},{87,0,51},{54,63,19},{54,61,1},{49,60,18},{126,26,51},{49,60,18},{55,65,18},{55,65,18},{55,65,18},
+{55,60,18},{54,64,9},{54,61,1},{54,61,1},{53,58,2},{50,61,8},{51,59,1},{57,61,1},{57,61,1},{57,61,1},{57,59,1},{85,0,8},{55,60,0},{55,60,0},{53,58,1},{127,23,8},{53,58,1},{89,0,18},{55,64,1},{57,61,1},{53,61,1},{89,0,18},{127,27,18},{53,61,1},{0,60,18},{127,27,18},{0,60,18},{55,0,18},{55,0,18},{55,0,18},{55,0,18},{54,61,1},
+{54,61,1},{54,61,1},{53,58,1},{51,59,0},{51,59,0},{59,73,36},{59,68,19},{59,66,26},{59,64,22},{58,72,52},{57,67,19},{57,65,2},{57,63,28},{52,68,51},{53,64,21},{61,69,19},{60,67,2},{61,65,1},{60,65,5},{93,0,51},{57,67,18},{57,65,1},{52,64,20},{126,32,51},{52,64,20},{59,69,18},{59,69,18},{59,69,18},{59,64,18},{58,68,9},{58,64,2},{58,64,2},
+{57,62,2},{55,64,9},{55,63,1},{61,65,1},{61,65,1},{61,65,1},{61,63,1},{91,0,8},{58,64,1},{58,64,1},{57,62,1},{127,29,8},{57,62,1},{95,0,18},{60,67,1},{61,65,0},{56,65,0},{95,0,18},{127,33,18},{56,65,0},{0,64,20},{127,33,18},{0,64,20},{59,0,18},{59,0,18},{59,0,18},{59,0,18},{58,65,1},{58,65,1},{58,65,1},{57,62,1},{55,63,0},
+{55,63,0},{63,79,38},{63,73,21},{64,70,28},{63,69,22},{62,78,51},{62,71,18},{62,69,2},{61,68,26},{57,72,51},{58,68,19},{65,74,19},{64,72,1},{65,69,2},{64,69,6},{100,0,51},{62,71,18},{62,69,2},{58,68,18},{127,38,51},{58,68,18},{63,74,20},{63,74,20},{63,74,20},{63,68,21},{62,73,8},{62,69,1},{62,69,1},{62,66,1},{59,69,9},{60,66,2},{65,69,1},
+{65,69,1},{65,69,1},{65,67,1},{98,0,8},{63,68,1},{63,68,1},{62,66,1},{127,36,8},{62,66,1},{101,1,18},{64,72,0},{65,69,1},{62,69,1},{101,1,18},{126,40,18},{62,69,1},{0,68,18},{126,40,18},{0,68,18},{63,0,20},{63,0,20},{63,0,20},{63,0,20},{62,70,0},{62,70,0},{62,70,0},{62,66,0},{60,66,1},{60,66,1},{67,82,36},{67,77,18},{67,74,23},
+{67,73,20},{66,81,52},{66,75,20},{66,73,2},{65,72,23},{61,76,51},{62,72,19},{69,78,19},{68,76,1},{69,73,2},{68,73,6},{106,0,51},{66,75,19},{66,73,1},{62,72,18},{127,44,51},{62,72,18},{67,77,18},{67,77,18},{67,77,18},{67,72,18},{66,76,9},{66,73,1},{66,73,1},{65,70,2},{63,73,9},{63,71,2},{69,73,1},{69,73,1},{69,73,1},{69,71,1},{104,0,8},
+{67,72,0},{67,72,0},{65,70,1},{127,42,8},{65,70,1},{107,1,18},{68,76,0},{69,73,1},{65,73,1},{107,1,18},{126,46,18},{65,73,1},{0,72,18},{126,46,18},{0,72,18},{67,0,18},{67,0,18},{67,0,18},{67,0,18},{66,73,1},{66,73,1},{66,73,1},{65,70,1},{63,71,1},{63,71,1},{71,86,36},{71,81,18},{71,78,23},{71,77,20},{70,85,52},{70,79,20},{70,77,2},
+{69,76,23},{64,80,51},{66,76,18},{73,82,19},{72,80,1},{73,77,2},{72,77,6},{112,0,51},{70,79,19},{70,77,1},{65,76,18},{127,50,51},{65,76,18},{71,81,18},{71,81,18},{71,81,18},{71,76,18},{70,80,9},{70,77,1},{70,77,1},{69,74,2},{66,77,8},{67,75,1},{73,77,1},{73,77,1},{73,77,1},{73,75,1},{110,0,8},{71,76,0},{71,76,0},{69,74,1},{126,48,8},
+{69,74,1},{113,0,18},{72,80,0},{73,77,1},{69,77,1},{113,0,18},{126,52,18},{69,77,1},{0,76,18},{126,52,18},{0,76,18},{71,0,18},{71,0,18},{71,0,18},{71,0,18},{70,77,1},{70,77,1},{70,77,1},{69,74,1},{67,75,0},{67,75,0},{75,90,36},{75,85,18},{75,82,23},{75,81,20},{74,89,52},{74,83,20},{74,81,2},{73,80,23},{68,84,51},{70,80,18},{77,86,19},
+{76,84,1},{77,81,2},{76,81,6},{118,0,51},{74,83,19},{74,81,1},{69,80,18},{127,56,51},{69,80,18},{75,85,18},{75,85,18},{75,85,18},{75,80,18},{74,84,9},{74,81,1},{74,81,1},{73,78,2},{70,81,8},{71,79,1},{77,81,1},{77,81,1},{77,81,1},{77,79,1},{115,1,8},{75,80,0},{75,80,0},{73,78,1},{126,54,8},{73,78,1},{119,0,18},{76,84,0},{77,81,1},
+{73,81,1},{119,0,18},{126,58,18},{73,81,1},{0,80,18},{126,58,18},{0,80,18},{75,0,18},{75,0,18},{75,0,18},{75,0,18},{74,81,1},{74,81,1},{74,81,1},{73,78,1},{71,79,0},{71,79,0},{80,93,38},{80,89,20},{80,86,24},{79,86,21},{78,94,51},{78,88,19},{78,86,2},{78,84,24},{73,88,52},{75,84,20},{81,91,18},{81,88,2},{81,86,1},{81,85,5},{124,1,51},
+{79,87,19},{78,86,2},{75,84,20},{126,63,51},{75,84,20},{80,89,20},{80,89,20},{80,89,20},{79,85,20},{78,90,8},{78,85,2},{78,85,2},{78,83,1},{74,86,8},{75,83,2},{81,87,0},{81,87,0},{81,87,0},{81,84,0},{122,0,8},{79,85,0},{79,85,0},{77,83,0},{126,61,8},{77,83,0},{126,0,18},{80,89,0},{81,86,1},{77,86,0},{126,0,18},{126,64,18},{77,86,0},
+{0,84,20},{126,64,18},{0,84,20},{79,0,20},{79,0,20},{79,0,20},{79,0,20},{78,87,0},{78,87,0},{78,87,0},{78,82,1},{75,84,0},{75,84,0},{84,97,38},{84,93,20},{84,90,24},{83,90,21},{82,98,51},{82,92,19},{82,90,2},{82,88,24},{77,92,52},{79,88,20},{85,95,18},{85,92,2},{85,90,1},{85,89,5},{127,7,51},{83,91,19},{82,90,2},{79,88,20},{127,68,51},
+{79,88,20},{84,93,20},{84,93,20},{84,93,20},{83,89,20},{82,94,8},{82,89,2},{82,89,2},{82,87,1},{78,90,8},{79,87,2},{85,91,0},{85,91,0},{85,91,0},{85,88,0},{127,2,8},{83,89,0},{83,89,0},{81,87,0},{127,66,8},{81,87,0},{127,10,18},{84,93,0},{85,90,1},{81,90,0},{127,10,18},{126,70,18},{81,90,0},{0,88,20},{126,70,18},{0,88,20},{83,0,20},
+{83,0,20},{83,0,20},{83,0,20},{82,91,0},{82,91,0},{82,91,0},{82,86,1},{79,88,0},{79,88,0},{88,101,38},{88,97,20},{88,94,24},{87,94,21},{86,102,51},{86,96,19},{86,94,2},{86,92,24},{81,96,52},{83,92,20},{89,99,18},{89,96,2},{89,94,1},{89,93,5},{127,19,51},{87,95,19},{86,94,2},{83,92,20},{127,74,51},{83,92,20},{88,97,20},{88,97,20},{88,97,20},
+{87,93,20},{86,98,8},{86,93,2},{86,93,2},{86,91,1},{82,94,8},{83,91,2},{89,95,0},{89,95,0},{89,95,0},{89,92,0},{127,14,8},{87,93,0},{87,93,0},{85,91,0},{127,72,8},{85,91,0},{127,22,18},{88,97,0},{89,94,1},{85,94,0},{127,22,18},{126,76,18},{85,94,0},{0,92,20},{126,76,18},{0,92,20},{87,0,20},{87,0,20},{87,0,20},{87,0,20},{86,95,0},
+{86,95,0},{86,95,0},{86,90,1},{83,92,0},{83,92,0},{92,105,38},{92,101,20},{92,98,24},{91,98,21},{90,106,51},{90,100,19},{90,98,2},{90,96,24},{85,100,52},{87,96,20},{93,103,18},{93,100,2},{93,98,1},{93,97,5},{127,31,51},{91,99,19},{90,98,2},{87,96,20},{127,80,51},{87,96,20},{92,101,20},{92,101,20},{92,101,20},{91,97,20},{90,102,8},{90,97,2},{90,97,2},
+{90,95,1},{86,98,8},{87,95,2},{93,99,0},{93,99,0},{93,99,0},{93,96,0},{127,27,8},{91,97,0},{91,97,0},{89,95,0},{126,78,8},{89,95,0},{127,34,18},{92,101,0},{93,98,1},{89,98,0},{127,34,18},{126,82,18},{89,98,0},{0,96,20},{126,82,18},{0,96,20},{91,0,20},{91,0,20},{91,0,20},{91,0,20},{90,99,0},{90,99,0},{90,99,0},{90,94,1},{87,96,0},
+{87,96,0},{96,111,36},{96,106,18},{96,103,23},{96,102,20},{95,110,52},{95,104,20},{95,102,2},{94,101,23},{89,105,51},{91,101,18},{98,107,19},{97,105,1},{98,102,2},{97,102,6},{127,45,51},{95,104,19},{95,102,1},{90,101,18},{126,87,51},{90,101,18},{96,106,18},{96,106,18},{96,106,18},{96,101,18},{95,105,9},{95,102,1},{95,102,1},{94,99,2},{91,102,8},{92,100,1},{98,102,1},
+{98,102,1},{98,102,1},{98,100,1},{127,40,8},{96,101,0},{96,101,0},{94,99,1},{126,85,8},{94,99,1},{127,48,18},{97,105,0},{98,102,1},{94,102,1},{127,48,18},{127,88,18},{94,102,1},{0,101,18},{127,88,18},{0,101,18},{96,0,18},{96,0,18},{96,0,18},{96,0,18},{95,102,1},{95,102,1},{95,102,1},{94,99,1},{92,100,0},{92,100,0},{100,115,36},{100,110,18},{100,107,23},
+{100,106,20},{99,114,52},{99,108,20},{99,106,2},{98,105,23},{93,109,51},{95,105,18},{102,111,19},{101,109,1},{102,106,2},{101,106,6},{127,57,51},{99,108,19},{99,106,1},{94,105,18},{126,93,51},{94,105,18},{100,110,18},{100,110,18},{100,110,18},{100,105,18},{99,109,9},{99,106,1},{99,106,1},{98,103,2},{95,106,8},{96,104,1},{102,106,1},{102,106,1},{102,106,1},{102,104,1},{127,53,8},
+{100,105,0},{100,105,0},{98,103,1},{126,91,8},{98,103,1},{127,60,18},{101,109,0},{102,106,1},{98,106,1},{127,60,18},{127,94,18},{98,106,1},{0,105,18},{127,94,18},{0,105,18},{100,0,18},{100,0,18},{100,0,18},{100,0,18},{99,106,1},{99,106,1},{99,106,1},{98,103,1},{96,104,0},{96,104,0},{104,119,36},{104,114,18},{104,111,23},{104,110,20},{103,118,52},{103,112,20},{103,110,2},
+{102,109,23},{97,113,51},{99,109,18},{106,115,19},{105,113,1},{106,110,2},{105,110,6},{127,69,51},{103,112,19},{103,110,1},{98,109,18},{126,99,51},{98,109,18},{104,114,18},{104,114,18},{104,114,18},{104,109,18},{103,113,9},{103,110,1},{103,110,1},{102,107,2},{99,110,8},{100,108,1},{106,110,1},{106,110,1},{106,110,1},{106,108,1},{127,64,8},{104,109,0},{104,109,0},{102,107,1},{126,97,8},
+{102,107,1},{127,72,18},{105,113,0},{106,110,1},{102,110,1},{127,72,18},{127,100,18},{102,110,1},{0,109,18},{127,100,18},{0,109,18},{104,0,18},{104,0,18},{104,0,18},{104,0,18},{103,110,1},{103,110,1},{103,110,1},{102,107,1},{100,108,0},{100,108,0},{108,123,36},{108,118,18},{108,115,23},{108,114,20},{107,122,52},{107,116,20},{107,114,2},{106,113,23},{101,117,51},{103,113,18},{110,119,19},
+{109,117,1},{110,114,2},{109,114,6},{127,81,51},{107,116,19},{107,114,1},{102,113,18},{126,105,51},{102,113,18},{108,118,18},{108,118,18},{108,118,18},{108,113,18},{107,117,9},{107,114,1},{107,114,1},{106,111,2},{103,114,8},{104,112,1},{110,114,1},{110,114,1},{110,114,1},{110,112,1},{127,76,8},{108,113,0},{108,113,0},{106,111,1},{126,103,8},{106,111,1},{127,84,18},{109,117,0},{110,114,1},
+{106,114,1},{127,84,18},{127,106,18},{106,114,1},{0,113,18},{127,106,18},{0,113,18},{108,0,18},{108,0,18},{108,0,18},{108,0,18},{107,114,1},{107,114,1},{107,114,1},{106,111,1},{104,112,0},{104,112,0},{113,126,38},{113,122,20},{113,119,24},{112,119,21},{111,127,51},{111,121,19},{111,119,2},{111,117,24},{106,121,52},{108,117,20},{114,124,18},{114,121,2},{114,119,1},{114,118,5},{127,95,51},
+{112,120,19},{111,119,2},{108,117,20},{127,111,51},{108,117,20},{113,122,20},{113,122,20},{113,122,20},{112,118,20},{111,123,8},{111,118,2},{111,118,2},{111,116,1},{107,119,8},{108,116,2},{114,120,0},{114,120,0},{114,120,0},{114,117,0},{127,90,8},{112,118,0},{112,118,0},{110,116,0},{127,109,8},{110,116,0},{127,98,18},{113,122,0},{114,119,1},{110,119,0},{127,98,18},{126,113,18},{110,119,0},
+{0,117,20},{126,113,18},{0,117,20},{112,0,20},{112,0,20},{112,0,20},{112,0,20},{111,120,0},{111,120,0},{111,120,0},{111,115,1},{108,117,0},{108,117,0},{117,127,46},{117,126,20},{117,123,24},{116,123,21},{116,126,63},{115,125,19},{115,123,2},{115,121,24},{110,125,52},{112,121,20},{118,127,20},{118,125,2},{118,123,1},{118,122,5},{127,107,51},{116,124,19},{115,123,2},{112,121,20},{127,117,51},
+{112,121,20},{117,126,20},{117,126,20},{117,126,20},{116,122,20},{115,127,8},{115,122,2},{115,122,2},{115,120,1},{111,123,8},{112,120,2},{118,124,0},{118,124,0},{118,124,0},{118,121,0},{127,102,8},{116,122,0},{116,122,0},{114,120,0},{127,115,8},{114,120,0},{127,110,18},{117,126,0},{118,123,1},{114,123,0},{127,110,18},{126,119,18},{114,123,0},{0,121,20},{126,119,18},{0,121,20},{116,0,20},
+{116,0,20},{116,0,20},{116,0,20},{115,124,0},{115,124,0},{115,124,0},{115,119,1},{112,121,0},{112,121,0},{122,126,86},{121,127,40},{121,127,24},{120,127,21},{121,127,88},{119,127,27},{119,127,2},{119,125,24},{116,127,60},{116,125,20},{123,127,30},{122,127,10},{122,127,1},{122,126,5},{127,119,51},{121,127,24},{119,127,2},{116,125,20},{127,123,51},{116,125,20},{121,127,24},{121,127,24},{121,127,24},
+{120,126,20},{120,127,14},{119,126,2},{119,126,2},{119,124,1},{115,127,8},{116,124,2},{122,126,1},{122,126,1},{122,126,1},{122,125,0},{127,115,8},{120,126,0},{120,126,0},{118,124,0},{127,121,8},{118,124,0},{127,122,18},{124,127,8},{122,127,1},{118,127,0},{127,122,18},{126,125,18},{118,127,0},{0,125,20},{126,125,18},{0,125,20},{120,0,20},{120,0,20},{120,0,20},{120,0,20},{119,126,1},
+{119,126,1},{119,126,1},{119,123,1},{116,125,0},{116,125,0},{125,126,38},{125,127,30},{125,127,29},{125,127,21},{125,126,35},{124,127,16},{124,127,12},{123,127,1},{122,127,20},{122,127,2},{126,127,2},{126,127,2},{126,127,1},{126,127,1},{127,125,3},{127,126,3},{125,127,2},{124,127,0},{127,126,3},{124,127,0},{125,126,29},{125,126,29},{125,126,29},{125,127,21},{124,127,24},{124,127,12},{124,127,12},
+{123,127,1},{122,127,11},{122,127,2},{126,127,1},{126,127,1},{126,127,1},{126,127,1},{127,125,2},{127,126,2},{127,126,2},{124,127,0},{127,126,2},{124,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{124,0,20},{124,0,20},{124,0,20},{124,0,20},{124,127,8},{124,127,8},{124,127,8},{123,127,1},{122,127,2},
+{122,127,2},{0,16,72},{0,11,8},{0,8,1},{0,7,25},{0,10,153},{0,8,97},{0,6,50},{0,4,115},{0,5,162},{0,4,124},{0,16,72},{0,11,8},{0,8,1},{0,7,25},{5,0,153},{0,8,97},{0,6,50},{0,4,115},{10,0,153},{0,4,115},{0,7,0},{0,7,0},{0,7,0},{0,4,0},{0,3,13},{0,2,5},{0,2,5},{0,1,10},{0,2,14},{0,1,11},{0,7,0},
+{0,7,0},{0,7,0},{0,4,0},{2,0,13},{0,2,5},{0,2,5},{0,1,10},{3,0,13},{0,1,10},{8,0,72},{0,11,8},{0,8,1},{0,7,25},{8,0,72},{16,0,72},{0,7,25},{0,5,74},{16,0,72},{0,5,74},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,27,77},{1,18,5},{1,13,15},
+{1,11,18},{0,21,243},{0,14,108},{0,11,29},{0,8,154},{0,9,287},{0,8,179},{2,25,73},{1,18,1},{2,12,6},{1,11,14},{10,1,243},{0,14,108},{0,11,29},{0,8,154},{21,0,243},{0,8,154},{1,17,5},{1,17,5},{1,17,5},{1,9,5},{0,12,50},{0,8,8},{0,8,8},{0,5,25},{0,5,61},{0,5,34},{2,15,1},{2,15,1},{2,15,1},{1,9,1},{6,0,50},
+{0,8,8},{0,8,8},{0,5,25},{12,0,50},{0,5,25},{14,0,72},{1,18,0},{4,12,1},{0,12,10},{14,0,72},{29,0,72},{0,12,10},{0,9,74},{29,0,72},{0,9,74},{1,0,5},{1,0,5},{1,0,5},{1,0,5},{0,4,0},{0,4,0},{0,4,0},{0,2,0},{0,2,1},{0,2,1},{3,35,133},{3,24,63},{4,17,90},{3,16,66},{0,33,243},{0,19,75},{0,16,2},
+{0,13,110},{0,14,345},{0,12,179},{6,29,73},{5,22,1},{6,16,6},{5,15,14},{16,0,243},{0,19,75},{0,16,2},{0,13,110},{33,0,243},{0,13,110},{3,26,61},{3,26,61},{3,26,61},{3,14,61},{0,24,50},{0,16,1},{0,16,1},{0,10,5},{0,11,101},{0,9,46},{6,19,1},{6,19,1},{6,19,1},{5,13,1},{12,0,50},{1,15,0},{1,15,0},{0,10,5},{24,0,50},
+{0,10,5},{20,0,72},{5,22,0},{8,16,1},{0,16,2},{20,0,72},{41,0,72},{0,16,2},{0,13,74},{41,0,72},{0,13,74},{3,0,61},{3,0,61},{3,0,61},{3,0,61},{0,16,0},{0,16,0},{0,16,0},{0,8,0},{0,5,25},{0,5,25},{7,39,146},{7,28,76},{8,21,107},{6,20,79},{4,37,244},{4,23,76},{4,20,3},{3,16,107},{0,22,292},{0,17,106},{10,33,73},
+{9,26,1},{10,20,6},{9,19,14},{22,0,243},{2,25,72},{4,20,2},{0,17,90},{45,0,243},{0,17,90},{7,30,74},{7,30,74},{7,30,74},{7,18,74},{4,28,51},{4,20,2},{4,20,2},{3,14,6},{0,17,68},{0,14,5},{10,23,1},{10,23,1},{10,23,1},{9,17,1},{18,0,50},{5,19,0},{5,19,0},{0,14,1},{36,0,50},{0,14,1},{26,0,72},{9,26,0},{12,20,1},
+{3,20,1},{26,0,72},{53,0,72},{3,20,1},{0,17,74},{53,0,72},{0,17,74},{6,0,74},{6,0,74},{6,0,74},{6,0,74},{4,20,1},{4,20,1},{4,20,1},{4,12,1},{0,14,4},{0,14,4},{11,44,144},{11,32,76},{12,25,105},{11,24,77},{8,43,243},{8,28,75},{8,25,2},{8,21,105},{0,28,248},{1,22,76},{14,38,72},{14,30,1},{15,25,5},{14,24,13},{29,0,243},
+{7,29,72},{8,25,2},{0,22,76},{59,0,243},{0,22,76},{11,35,72},{11,35,72},{11,35,72},{11,23,72},{8,34,50},{8,24,1},{8,24,1},{8,18,5},{1,24,51},{3,19,1},{14,29,0},{14,29,0},{14,29,0},{14,21,1},{24,1,50},{9,24,0},{9,24,0},{3,19,0},{50,0,50},{3,19,0},{33,0,72},{13,31,0},{16,25,0},{6,25,0},{33,0,72},{66,0,72},{6,25,0},
+{0,22,72},{66,0,72},{0,22,72},{11,0,72},{11,0,72},{11,0,72},{11,0,72},{8,26,0},{8,26,0},{8,26,0},{8,17,0},{2,20,0},{2,20,0},{15,48,144},{15,36,76},{16,29,105},{15,28,77},{12,47,243},{12,32,75},{12,29,2},{12,25,105},{2,33,244},{5,26,76},{18,42,72},{18,34,1},{19,29,5},{18,28,13},{35,0,243},{11,33,72},{12,29,2},{1,26,72},{71,0,243},
+{1,26,72},{15,39,72},{15,39,72},{15,39,72},{15,27,72},{12,38,50},{12,28,1},{12,28,1},{12,22,5},{5,28,51},{7,23,1},{18,33,0},{18,33,0},{18,33,0},{18,25,1},{30,1,50},{13,28,0},{13,28,0},{7,23,0},{62,0,50},{7,23,0},{39,0,72},{17,35,0},{20,29,0},{10,29,0},{39,0,72},{78,0,72},{10,29,0},{0,26,72},{78,0,72},{0,26,72},{15,0,72},
+{15,0,72},{15,0,72},{15,0,72},{12,30,0},{12,30,0},{12,30,0},{12,21,0},{6,24,0},{6,24,0},{19,52,144},{19,40,76},{20,33,105},{19,32,77},{16,51,243},{16,36,75},{16,33,2},{16,29,105},{6,37,244},{9,30,76},{22,46,72},{22,38,1},{23,33,5},{22,32,13},{41,0,243},{15,37,72},{16,33,2},{5,30,72},{83,0,243},{5,30,72},{19,43,72},{19,43,72},{19,43,72},
+{19,31,72},{16,42,50},{16,32,1},{16,32,1},{16,26,5},{9,32,51},{11,27,1},{22,37,0},{22,37,0},{22,37,0},{22,29,1},{36,1,50},{17,32,0},{17,32,0},{11,27,0},{74,0,50},{11,27,0},{45,0,72},{21,39,0},{24,33,0},{14,33,0},{45,0,72},{91,0,72},{14,33,0},{0,30,72},{91,0,72},{0,30,72},{19,0,72},{19,0,72},{19,0,72},{19,0,72},{16,34,0},
+{16,34,0},{16,34,0},{16,25,0},{10,28,0},{10,28,0},{23,56,144},{23,44,76},{24,37,105},{23,36,77},{20,55,243},{20,40,75},{20,37,2},{20,33,105},{10,41,244},{13,34,76},{26,50,72},{26,42,1},{27,37,5},{26,36,13},{47,0,243},{19,41,72},{20,37,2},{9,34,72},{95,0,243},{9,34,72},{23,47,72},{23,47,72},{23,47,72},{23,35,72},{20,46,50},{20,36,1},{20,36,1},
+{20,30,5},{13,36,51},{15,31,1},{26,41,0},{26,41,0},{26,41,0},{26,33,1},{42,1,50},{21,36,0},{21,36,0},{15,31,0},{86,0,50},{15,31,0},{50,1,72},{25,43,0},{28,37,0},{18,37,0},{50,1,72},{103,0,72},{18,37,0},{0,34,72},{103,0,72},{0,34,72},{23,0,72},{23,0,72},{23,0,72},{23,0,72},{20,38,0},{20,38,0},{20,38,0},{20,29,0},{14,32,0},
+{14,32,0},{28,60,146},{28,49,76},{29,42,107},{27,41,79},{25,58,244},{25,44,76},{25,41,3},{24,37,107},{14,46,244},{17,38,76},{31,54,73},{30,47,1},{31,41,6},{30,40,14},{53,1,243},{23,46,72},{25,41,2},{15,38,74},{109,0,243},{15,38,74},{28,51,74},{28,51,74},{28,51,74},{28,39,74},{25,49,51},{25,41,2},{25,41,2},{24,35,6},{18,40,51},{19,36,1},{31,44,1},
+{31,44,1},{31,44,1},{30,38,1},{49,0,50},{26,40,0},{26,40,0},{21,35,1},{100,0,50},{21,35,1},{57,0,72},{30,47,0},{33,41,1},{24,41,1},{57,0,72},{117,0,72},{24,41,1},{0,38,74},{117,0,72},{0,38,74},{27,0,74},{27,0,74},{27,0,74},{27,0,74},{25,41,1},{25,41,1},{25,41,1},{25,33,1},{19,36,0},{19,36,0},{32,64,146},{32,53,76},{33,46,107},
+{31,45,79},{29,62,244},{29,48,76},{29,45,3},{28,41,107},{18,50,244},{21,42,76},{35,58,73},{34,51,1},{35,45,6},{34,44,14},{59,1,243},{27,50,72},{29,45,2},{19,42,74},{121,0,243},{19,42,74},{32,55,74},{32,55,74},{32,55,74},{32,43,74},{29,53,51},{29,45,2},{29,45,2},{28,39,6},{22,44,51},{23,40,1},{35,48,1},{35,48,1},{35,48,1},{34,42,1},{55,0,50},
+{30,44,0},{30,44,0},{25,39,1},{112,0,50},{25,39,1},{63,0,72},{34,51,0},{37,45,1},{28,45,1},{63,0,72},{127,1,72},{28,45,1},{0,42,74},{127,1,72},{0,42,74},{31,0,74},{31,0,74},{31,0,74},{31,0,74},{29,45,1},{29,45,1},{29,45,1},{29,37,1},{23,40,0},{23,40,0},{36,67,146},{36,57,76},{37,50,107},{35,49,79},{33,66,244},{33,52,76},{33,49,3},
+{32,45,107},{22,54,244},{25,46,76},{39,62,73},{38,55,1},{39,49,6},{38,48,14},{65,0,243},{31,54,72},{33,49,2},{23,46,74},{127,3,243},{23,46,74},{36,59,74},{36,59,74},{36,59,74},{36,47,74},{33,57,51},{33,49,2},{33,49,2},{32,43,6},{26,48,51},{27,44,1},{39,52,1},{39,52,1},{39,52,1},{38,46,1},{61,0,50},{34,48,0},{34,48,0},{29,43,1},{124,0,50},
+{29,43,1},{69,0,72},{38,55,0},{41,49,1},{32,49,1},{69,0,72},{127,7,72},{32,49,1},{0,46,74},{127,7,72},{0,46,74},{35,0,74},{35,0,74},{35,0,74},{35,0,74},{33,49,1},{33,49,1},{33,49,1},{33,41,1},{27,44,0},{27,44,0},{40,71,146},{40,61,76},{41,54,107},{39,53,79},{37,70,244},{37,56,76},{37,53,3},{36,49,107},{26,58,244},{29,50,76},{43,65,73},
+{42,59,1},{43,53,6},{42,52,14},{71,0,243},{35,58,72},{37,53,2},{27,50,74},{127,9,243},{27,50,74},{40,63,74},{40,63,74},{40,63,74},{40,51,74},{37,61,51},{37,53,2},{37,53,2},{36,47,6},{30,52,51},{31,48,1},{43,56,1},{43,56,1},{43,56,1},{42,50,1},{66,1,50},{38,52,0},{38,52,0},{33,47,1},{126,5,50},{33,47,1},{75,0,72},{42,59,0},{45,53,1},
+{36,53,1},{75,0,72},{127,13,72},{36,53,1},{0,50,74},{127,13,72},{0,50,74},{39,0,74},{39,0,74},{39,0,74},{39,0,74},{37,53,1},{37,53,1},{37,53,1},{37,45,1},{31,48,0},{31,48,0},{44,77,144},{44,65,77},{45,58,105},{44,57,77},{41,75,243},{41,61,75},{41,58,2},{41,54,105},{31,62,244},{34,55,76},{47,71,72},{47,63,1},{48,58,5},{47,57,13},{78,0,243},
+{40,62,72},{41,58,2},{30,55,72},{126,16,243},{30,55,72},{44,68,72},{44,68,72},{44,68,72},{44,56,72},{41,66,50},{41,57,1},{41,57,1},{41,51,5},{34,57,51},{36,52,1},{47,62,0},{47,62,0},{47,62,0},{47,54,1},{73,0,50},{42,57,0},{42,57,0},{36,52,0},{126,12,50},{36,52,0},{81,0,72},{47,63,1},{49,58,0},{39,58,0},{81,0,72},{126,20,72},{39,58,0},
+{0,55,72},{126,20,72},{0,55,72},{44,0,72},{44,0,72},{44,0,72},{44,0,72},{41,59,0},{41,59,0},{41,59,0},{41,50,0},{35,53,0},{35,53,0},{48,81,144},{48,69,77},{49,62,105},{48,61,77},{45,79,243},{45,65,73},{45,62,2},{45,58,105},{34,67,243},{38,59,76},{51,75,72},{51,66,1},{52,62,5},{51,61,13},{83,1,243},{45,65,73},{45,62,2},{34,59,72},{126,22,243},
+{34,59,72},{48,72,72},{48,72,72},{48,72,72},{48,60,72},{45,70,50},{45,61,1},{45,61,1},{45,55,5},{38,61,51},{40,56,1},{51,65,0},{51,65,0},{51,65,0},{51,58,1},{79,0,50},{46,61,0},{46,61,0},{40,56,0},{127,17,50},{40,56,0},{87,0,72},{51,66,1},{53,62,0},{43,62,0},{87,0,72},{126,26,72},{43,62,0},{0,59,72},{126,26,72},{0,59,72},{48,0,72},
+{48,0,72},{48,0,72},{48,0,72},{45,63,0},{45,63,0},{45,63,0},{45,54,0},{39,57,0},{39,57,0},{52,85,144},{52,73,77},{53,67,105},{52,65,77},{49,83,243},{49,69,73},{49,65,2},{49,62,105},{38,71,243},{42,63,76},{55,79,72},{55,70,1},{55,66,5},{54,65,14},{89,1,243},{49,69,73},{49,65,2},{38,63,72},{126,28,243},{38,63,72},{52,76,72},{52,76,72},{52,76,72},
+{52,63,73},{49,74,50},{49,65,1},{49,65,1},{49,59,5},{41,65,50},{44,60,1},{55,69,0},{55,69,0},{55,69,0},{55,62,1},{85,0,50},{50,64,1},{50,64,1},{44,60,0},{127,23,50},{44,60,0},{93,0,72},{55,70,1},{57,65,1},{48,65,1},{93,0,72},{126,32,72},{48,65,1},{0,63,72},{126,32,72},{0,63,72},{52,0,72},{52,0,72},{52,0,72},{52,0,72},{49,67,0},
+{49,67,0},{49,67,0},{49,58,0},{43,61,0},{43,61,0},{56,89,144},{56,77,77},{57,71,105},{56,69,77},{53,87,243},{53,73,73},{53,69,2},{52,66,103},{42,75,243},{45,66,79},{59,83,72},{59,74,1},{59,70,5},{58,69,14},{95,1,243},{53,73,73},{53,69,2},{43,66,74},{126,34,243},{43,66,74},{56,80,72},{56,80,72},{56,80,72},{56,67,73},{53,78,50},{53,69,1},{53,69,1},
+{53,63,5},{45,69,50},{47,64,2},{59,73,0},{59,73,0},{59,73,0},{59,66,0},{91,0,50},{55,67,1},{55,67,1},{47,64,1},{127,29,50},{47,64,1},{99,0,72},{59,74,1},{61,69,1},{52,69,1},{99,0,72},{126,38,72},{52,69,1},{0,66,74},{126,38,72},{0,66,74},{56,0,72},{56,0,72},{56,0,72},{56,0,72},{53,71,0},{53,71,0},{53,71,0},{53,62,0},{47,64,1},
+{47,64,1},{61,92,146},{61,80,79},{61,75,103},{60,74,78},{58,91,244},{57,78,74},{58,74,2},{56,70,105},{47,79,243},{49,71,77},{63,88,73},{63,79,2},{64,74,5},{63,73,14},{102,0,243},{57,78,73},{58,74,1},{47,71,72},{126,41,243},{47,71,72},{61,83,74},{61,83,74},{61,83,74},{60,72,74},{58,82,51},{58,73,2},{58,73,2},{57,68,5},{50,73,50},{52,68,1},{63,79,1},
+{63,79,1},{63,79,1},{63,71,1},{98,0,50},{59,72,1},{59,72,1},{53,68,0},{127,36,50},{53,68,0},{106,0,72},{63,79,1},{65,74,0},{56,74,0},{106,0,72},{127,44,72},{56,74,0},{0,71,72},{127,44,72},{0,71,72},{60,0,74},{60,0,74},{60,0,74},{60,0,74},{58,74,1},{58,74,1},{58,74,1},{57,66,1},{52,68,1},{52,68,1},{64,97,144},{64,85,76},{65,78,105},
+{64,77,77},{62,95,244},{61,82,74},{62,78,2},{60,74,105},{51,83,243},{53,75,77},{67,91,72},{67,83,1},{68,78,5},{67,77,13},{108,0,243},{61,82,73},{62,78,1},{51,75,72},{125,47,243},{51,75,72},{64,88,72},{64,88,72},{64,88,72},{64,76,72},{62,86,51},{62,77,2},{62,77,2},{61,72,5},{54,77,50},{56,72,1},{67,82,0},{67,82,0},{67,82,0},{67,74,1},{104,0,50},
+{63,76,1},{63,76,1},{57,72,0},{127,42,50},{57,72,0},{112,0,72},{66,84,0},{69,78,0},{60,78,0},{112,0,72},{127,50,72},{60,78,0},{0,75,72},{127,50,72},{0,75,72},{64,0,72},{64,0,72},{64,0,72},{64,0,72},{62,78,1},{62,78,1},{62,78,1},{61,70,1},{56,72,1},{56,72,1},{68,101,144},{68,89,76},{69,82,105},{68,81,77},{65,100,243},{65,85,75},{65,82,2},
+{65,78,105},{55,87,243},{57,79,77},{71,95,72},{71,87,1},{72,82,5},{71,81,13},{114,0,243},{64,86,72},{65,82,2},{55,79,72},{127,52,243},{55,79,72},{68,92,72},{68,92,72},{68,92,72},{68,80,72},{65,91,50},{65,81,1},{65,81,1},{65,75,5},{58,81,50},{60,76,1},{71,86,0},{71,86,0},{71,86,0},{71,78,1},{110,0,50},{66,81,0},{66,81,0},{61,76,0},{126,48,50},
+{61,76,0},{118,0,72},{70,88,0},{73,82,0},{64,82,0},{118,0,72},{127,56,72},{64,82,0},{0,79,72},{127,56,72},{0,79,72},{68,0,72},{68,0,72},{68,0,72},{68,0,72},{65,83,0},{65,83,0},{65,83,0},{65,74,0},{60,76,1},{60,76,1},{72,105,144},{72,93,76},{73,86,105},{72,85,77},{69,104,243},{69,89,75},{69,86,2},{69,82,105},{59,91,243},{61,83,77},{75,99,72},
+{75,91,1},{76,86,5},{75,85,13},{120,0,243},{68,90,72},{69,86,2},{59,83,72},{127,58,243},{59,83,72},{72,96,72},{72,96,72},{72,96,72},{72,84,72},{69,95,50},{69,85,1},{69,85,1},{69,79,5},{62,85,50},{64,80,1},{75,90,0},{75,90,0},{75,90,0},{75,82,1},{115,1,50},{70,85,0},{70,85,0},{64,80,0},{126,54,50},{64,80,0},{124,0,72},{74,92,0},{77,86,0},
+{67,86,0},{124,0,72},{127,62,72},{67,86,0},{0,83,72},{127,62,72},{0,83,72},{72,0,72},{72,0,72},{72,0,72},{72,0,72},{69,87,0},{69,87,0},{69,87,0},{69,78,0},{64,80,1},{64,80,1},{77,109,146},{77,98,76},{78,91,107},{76,90,79},{74,107,244},{74,93,76},{74,90,3},{73,86,107},{63,96,243},{66,87,76},{80,103,73},{79,96,1},{80,90,6},{79,89,14},{127,0,243},
+{72,95,72},{74,90,2},{64,87,74},{126,65,243},{64,87,74},{77,100,74},{77,100,74},{77,100,74},{77,88,74},{74,98,51},{74,90,2},{74,90,2},{73,84,6},{67,89,51},{68,85,1},{80,93,1},{80,93,1},{80,93,1},{79,87,1},{122,0,50},{75,89,0},{75,89,0},{70,84,1},{126,61,50},{70,84,1},{127,7,72},{79,96,0},{82,90,1},{73,90,1},{127,7,72},{127,68,72},{73,90,1},
+{0,87,74},{127,68,72},{0,87,74},{76,0,74},{76,0,74},{76,0,74},{76,0,74},{74,90,1},{74,90,1},{74,90,1},{74,82,1},{68,85,0},{68,85,0},{81,113,146},{81,102,76},{82,95,107},{80,94,79},{78,111,244},{78,97,76},{78,94,3},{77,90,107},{67,99,244},{70,91,76},{84,107,73},{83,100,1},{84,94,6},{83,93,14},{127,11,243},{76,99,72},{78,94,2},{68,91,74},{126,71,243},
+{68,91,74},{81,104,74},{81,104,74},{81,104,74},{81,92,74},{78,102,51},{78,94,2},{78,94,2},{77,88,6},{71,93,51},{72,89,1},{84,97,1},{84,97,1},{84,97,1},{83,91,1},{127,2,50},{79,93,0},{79,93,0},{74,88,1},{127,66,50},{74,88,1},{127,19,72},{83,100,0},{86,94,1},{77,94,1},{127,19,72},{127,74,72},{77,94,1},{0,91,74},{127,74,72},{0,91,74},{80,0,74},
+{80,0,74},{80,0,74},{80,0,74},{78,94,1},{78,94,1},{78,94,1},{78,86,1},{72,89,0},{72,89,0},{85,117,146},{85,106,76},{86,99,107},{84,98,79},{82,115,244},{82,101,76},{82,98,3},{81,94,107},{71,103,244},{74,95,76},{88,111,73},{87,104,1},{88,98,6},{87,97,14},{127,24,243},{80,103,72},{82,98,2},{72,95,74},{125,77,243},{72,95,74},{85,108,74},{85,108,74},{85,108,74},
+{85,96,74},{82,106,51},{82,98,2},{82,98,2},{81,92,6},{75,97,51},{76,93,1},{88,101,1},{88,101,1},{88,101,1},{87,95,1},{127,14,50},{83,97,0},{83,97,0},{78,92,1},{127,72,50},{78,92,1},{127,31,72},{87,104,0},{90,98,1},{81,98,1},{127,31,72},{127,80,72},{81,98,1},{0,95,74},{127,80,72},{0,95,74},{84,0,74},{84,0,74},{84,0,74},{84,0,74},{82,98,1},
+{82,98,1},{82,98,1},{82,90,1},{76,93,0},{76,93,0},{89,121,146},{89,110,76},{90,103,107},{88,102,79},{86,119,244},{86,105,76},{86,102,3},{85,98,107},{75,107,244},{78,99,76},{92,115,73},{91,108,1},{92,102,6},{91,101,14},{127,36,243},{84,107,72},{86,102,2},{76,99,74},{127,82,243},{76,99,74},{89,112,74},{89,112,74},{89,112,74},{89,100,74},{86,110,51},{86,102,2},{86,102,2},
+{85,96,6},{79,101,51},{80,97,1},{92,105,1},{92,105,1},{92,105,1},{91,99,1},{127,27,50},{87,101,0},{87,101,0},{82,96,1},{126,78,50},{82,96,1},{127,43,72},{91,108,0},{94,102,1},{85,102,1},{127,43,72},{127,86,72},{85,102,1},{0,99,74},{127,86,72},{0,99,74},{88,0,74},{88,0,74},{88,0,74},{88,0,74},{86,102,1},{86,102,1},{86,102,1},{86,94,1},{80,97,0},
+{80,97,0},{93,126,144},{93,114,76},{94,107,105},{93,106,77},{90,125,243},{90,110,75},{90,107,2},{90,103,105},{80,111,244},{83,104,76},{96,120,72},{96,112,1},{97,107,5},{96,106,13},{127,50,243},{89,111,72},{90,107,2},{79,104,72},{127,89,243},{79,104,72},{93,117,72},{93,117,72},{93,117,72},{93,105,72},{90,116,50},{90,106,1},{90,106,1},{90,100,5},{83,106,51},{85,101,1},{96,111,0},
+{96,111,0},{96,111,0},{96,103,1},{127,40,50},{91,106,0},{91,106,0},{85,101,0},{126,85,50},{85,101,0},{127,57,72},{95,113,0},{98,107,0},{88,107,0},{127,57,72},{126,93,72},{88,107,0},{0,104,72},{126,93,72},{0,104,72},{93,0,72},{93,0,72},{93,0,72},{93,0,72},{90,108,0},{90,108,0},{90,108,0},{90,99,0},{84,102,0},{84,102,0},{97,127,152},{97,118,76},{98,111,105},
+{97,110,77},{94,127,244},{94,114,75},{94,111,2},{94,107,105},{84,115,244},{87,108,76},{100,124,72},{100,116,1},{101,111,5},{100,110,13},{127,62,243},{93,115,72},{94,111,2},{83,108,72},{127,95,243},{83,108,72},{97,121,72},{97,121,72},{97,121,72},{97,109,72},{94,120,50},{94,110,1},{94,110,1},{94,104,5},{87,110,51},{89,105,1},{100,115,0},{100,115,0},{100,115,0},{100,107,1},{127,53,50},
+{95,110,0},{95,110,0},{89,105,0},{126,91,50},{89,105,0},{127,69,72},{99,117,0},{102,111,0},{92,111,0},{127,69,72},{126,99,72},{92,111,0},{0,108,72},{126,99,72},{0,108,72},{97,0,72},{97,0,72},{97,0,72},{97,0,72},{94,112,0},{94,112,0},{94,112,0},{94,103,0},{88,106,0},{88,106,0},{102,126,184},{101,122,76},{102,115,105},{101,114,77},{100,127,260},{98,118,75},{98,115,2},
+{98,111,105},{88,119,244},{91,112,76},{104,127,74},{104,120,1},{105,115,5},{104,114,13},{127,73,243},{97,119,72},{98,115,2},{87,112,72},{127,101,243},{87,112,72},{101,125,72},{101,125,72},{101,125,72},{101,113,72},{98,124,50},{98,114,1},{98,114,1},{98,108,5},{91,114,51},{93,109,1},{104,119,0},{104,119,0},{104,119,0},{104,111,1},{127,64,50},{99,114,0},{99,114,0},{93,109,0},{126,97,50},
+{93,109,0},{127,81,72},{103,121,0},{106,115,0},{96,115,0},{127,81,72},{126,105,72},{96,115,0},{0,112,72},{126,105,72},{0,112,72},{101,0,72},{101,0,72},{101,0,72},{101,0,72},{98,116,0},{98,116,0},{98,116,0},{98,107,0},{92,110,0},{92,110,0},{106,127,224},{105,126,76},{106,119,105},{105,118,77},{104,127,299},{102,122,75},{102,119,2},{102,115,105},{92,123,244},{95,116,76},{109,127,84},
+{108,124,1},{109,119,5},{108,118,13},{127,86,243},{101,123,72},{102,119,2},{91,116,72},{127,107,243},{91,116,72},{105,126,76},{105,126,76},{105,126,76},{105,117,72},{102,126,52},{102,118,1},{102,118,1},{102,112,5},{95,118,51},{97,113,1},{108,123,0},{108,123,0},{108,123,0},{108,115,1},{127,76,50},{103,118,0},{103,118,0},{97,113,0},{126,103,50},{97,113,0},{127,93,72},{107,125,0},{110,119,0},
+{100,119,0},{127,93,72},{126,111,72},{100,119,0},{0,116,72},{126,111,72},{0,116,72},{105,0,72},{105,0,72},{105,0,72},{105,0,72},{102,120,0},{102,120,0},{102,120,0},{102,111,0},{96,114,0},{96,114,0},{111,127,290},{111,127,103},{111,124,107},{109,123,79},{111,127,345},{107,126,76},{107,123,3},{106,119,107},{98,127,248},{99,120,76},{114,127,113},{113,127,5},{113,123,6},{112,122,14},{127,99,243},
+{107,126,75},{107,123,2},{97,120,74},{126,114,243},{97,120,74},{110,126,90},{110,126,90},{110,126,90},{110,121,74},{108,126,67},{107,123,2},{107,123,2},{106,117,6},{100,122,51},{101,118,1},{113,126,1},{113,126,1},{113,126,1},{112,120,1},{127,90,50},{108,122,0},{108,122,0},{103,117,1},{127,109,50},{103,117,1},{127,107,72},{113,127,4},{115,123,1},{106,123,1},{127,107,72},{127,117,72},{106,123,1},
+{0,120,74},{127,117,72},{0,120,74},{109,0,74},{109,0,74},{109,0,74},{109,0,74},{107,123,1},{107,123,1},{107,123,1},{107,115,1},{101,118,0},{101,118,0},{117,127,343},{115,127,179},{114,127,110},{113,126,78},{115,127,387},{111,127,102},{111,127,2},{110,123,90},{105,127,263},{103,124,63},{120,127,134},{118,127,46},{117,127,5},{116,126,9},{127,110,221},{113,127,89},{111,127,1},{101,124,61},{126,119,221},
+{101,124,61},{114,127,110},{114,127,110},{114,127,110},{114,125,74},{112,127,91},{111,127,2},{111,127,2},{110,121,6},{104,126,51},{105,122,1},{117,127,5},{117,127,5},{117,127,5},{116,124,1},{127,102,50},{112,126,0},{112,126,0},{107,121,1},{127,115,50},{107,121,1},{127,118,61},{119,127,25},{119,127,0},{110,127,0},{127,118,61},{126,123,61},{110,127,0},{0,124,61},{126,123,61},{0,124,61},{113,0,74},
+{113,0,74},{113,0,74},{113,0,74},{111,127,1},{111,127,1},{111,127,1},{111,119,1},{105,122,0},{105,122,0},{120,127,239},{119,127,179},{119,127,154},{118,127,83},{120,127,254},{116,127,78},{116,127,29},{114,126,15},{113,127,169},{109,126,5},{123,127,54},{122,127,34},{122,127,25},{121,127,2},{127,119,93},{119,127,33},{119,127,8},{109,126,5},{127,123,93},{109,126,5},{119,126,154},{119,126,154},{119,126,154},
+{118,127,83},{117,127,125},{116,127,29},{116,127,29},{114,125,6},{110,127,72},{109,126,1},{122,126,25},{122,126,25},{122,126,25},{121,127,2},{127,115,50},{119,127,8},{119,127,8},{111,125,1},{127,121,50},{111,125,1},{127,124,5},{125,127,1},{125,127,0},{122,127,0},{127,124,5},{126,126,5},{122,127,0},{0,126,5},{126,126,5},{0,126,5},{117,0,74},{117,0,74},{117,0,74},{117,0,74},{115,127,10},
+{115,127,10},{115,127,10},{115,123,1},{109,126,0},{109,126,0},{123,127,140},{123,127,124},{123,127,115},{122,127,83},{123,127,131},{121,127,66},{120,127,50},{119,127,1},{119,127,86},{116,127,8},{126,127,11},{125,127,11},{125,127,10},{125,127,2},{127,124,17},{125,127,6},{124,127,5},{119,127,0},{126,126,17},{119,127,0},{123,127,115},{123,127,115},{123,127,115},{122,127,83},{121,127,98},{120,127,50},{120,127,50},
+{119,127,1},{116,127,57},{116,127,8},{125,126,10},{125,126,10},{125,126,10},{125,127,2},{127,122,13},{124,127,5},{124,127,5},{119,127,0},{126,125,13},{119,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{121,0,74},{121,0,74},{121,0,74},{121,0,74},{120,127,25},{120,127,25},{120,127,25},{119,127,1},{116,127,8},
+{116,127,8},{0,29,200},{0,19,18},{0,14,1},{0,13,73},{0,20,441},{0,11,281},{0,11,134},{0,7,331},{0,8,474},{0,7,356},{0,29,200},{0,19,18},{0,14,1},{0,13,73},{10,0,441},{0,11,281},{0,11,134},{0,7,331},{20,0,441},{0,7,331},{0,13,0},{0,13,0},{0,13,0},{0,7,0},{0,6,41},{0,5,13},{0,5,13},{0,3,25},{0,3,45},{0,3,29},{0,13,0},
+{0,13,0},{0,13,0},{0,7,0},{3,0,41},{0,5,13},{0,5,13},{0,3,25},{6,0,41},{0,3,25},{14,0,200},{0,19,18},{0,14,1},{0,13,73},{14,0,200},{29,0,200},{0,13,73},{0,9,202},{29,0,200},{0,9,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,41,200},{0,27,2},{1,19,18},
+{0,17,45},{0,27,686},{0,19,346},{0,15,158},{0,10,467},{0,11,762},{0,10,516},{0,41,200},{0,27,2},{1,19,14},{0,17,45},{13,1,686},{0,19,346},{0,15,158},{0,10,467},{27,0,686},{0,10,467},{0,26,0},{0,26,0},{0,26,0},{0,13,0},{0,12,145},{0,11,53},{0,11,53},{0,6,89},{0,5,158},{0,6,105},{0,26,0},{0,26,0},{0,26,0},{0,13,0},{6,0,145},
+{0,11,53},{0,11,53},{0,6,89},{12,0,145},{0,6,89},{20,0,200},{1,26,2},{4,18,1},{0,17,45},{20,0,200},{41,0,200},{0,17,45},{0,13,202},{41,0,200},{0,13,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,49,225},{2,32,27},{3,24,71},{1,21,54},{0,39,723},{0,25,283},{0,20,65},
+{0,15,419},{0,17,865},{0,15,519},{4,45,201},{3,32,1},{5,23,19},{3,21,35},{19,0,723},{0,25,283},{0,20,65},{0,15,419},{39,0,723},{0,15,419},{2,34,25},{2,34,25},{2,34,25},{2,17,26},{0,24,162},{0,17,20},{0,17,20},{0,10,61},{0,11,213},{0,9,110},{4,30,1},{4,30,1},{4,30,1},{3,17,1},{12,0,162},{0,17,20},{0,17,20},{0,10,61},{24,0,162},
+{0,10,61},{26,0,200},{3,32,0},{8,22,1},{0,21,18},{26,0,200},{53,0,200},{0,21,18},{0,17,202},{53,0,200},{0,17,202},{2,0,25},{2,0,25},{2,0,25},{2,0,25},{0,10,0},{0,10,0},{0,10,0},{0,5,0},{0,5,9},{0,5,9},{4,57,313},{4,39,121},{5,28,198},{4,25,131},{0,52,723},{0,31,227},{0,26,9},{0,20,362},{0,22,959},{0,19,515},{8,49,201},
+{7,36,1},{9,27,19},{7,25,35},{25,0,723},{0,31,227},{0,26,9},{0,20,362},{52,0,723},{0,20,362},{4,42,113},{4,42,113},{4,42,113},{4,22,114},{0,36,162},{0,24,2},{0,24,2},{0,15,34},{0,17,285},{0,14,122},{8,34,1},{8,34,1},{8,34,1},{7,21,1},{18,0,162},{1,23,2},{1,23,2},{0,15,34},{36,0,162},{0,15,34},{32,0,200},{7,36,0},{12,26,1},
+{0,26,5},{32,0,200},{65,0,200},{0,26,5},{0,21,202},{65,0,200},{0,21,202},{4,0,113},{4,0,113},{4,0,113},{4,0,113},{0,23,0},{0,23,0},{0,23,0},{0,11,0},{0,8,41},{0,8,41},{7,64,400},{7,43,216},{8,32,312},{7,30,213},{2,61,723},{1,38,208},{2,31,2},{0,24,312},{0,31,980},{0,24,440},{12,54,200},{12,40,0},{13,31,20},{11,29,36},{32,0,723},
+{0,38,203},{2,31,2},{0,24,296},{65,0,723},{0,24,296},{7,49,200},{7,49,200},{7,49,200},{7,28,200},{2,46,162},{2,31,2},{2,31,2},{2,20,20},{0,22,280},{0,19,84},{12,39,0},{12,39,0},{12,39,0},{12,25,1},{24,1,162},{4,29,0},{4,29,0},{0,20,13},{50,0,162},{0,20,13},{39,0,200},{12,40,0},{16,31,0},{0,31,0},{39,0,200},{78,0,200},{0,31,0},
+{0,26,200},{78,0,200},{0,26,200},{7,0,200},{7,0,200},{7,0,200},{7,0,200},{2,32,0},{2,32,0},{2,32,0},{2,17,0},{0,14,50},{0,14,50},{11,68,400},{11,47,216},{12,36,312},{11,34,213},{6,65,723},{5,42,208},{6,35,2},{4,28,312},{0,37,868},{0,28,304},{16,58,200},{16,44,0},{17,35,20},{15,33,36},{38,0,723},{3,43,200},{6,35,2},{0,29,257},{77,0,723},
+{0,29,257},{11,53,200},{11,53,200},{11,53,200},{11,32,200},{6,50,162},{6,35,2},{6,35,2},{6,24,20},{0,28,216},{0,24,20},{16,43,0},{16,43,0},{16,43,0},{16,29,1},{30,1,162},{8,33,0},{8,33,0},{0,24,4},{62,0,162},{0,24,4},{45,0,200},{16,44,0},{20,35,0},{4,35,0},{45,0,200},{91,0,200},{4,35,0},{0,30,200},{91,0,200},{0,30,200},{11,0,200},
+{11,0,200},{11,0,200},{11,0,200},{6,36,0},{6,36,0},{6,36,0},{6,21,0},{0,22,8},{0,22,8},{15,72,400},{15,51,216},{16,40,312},{15,38,213},{10,69,723},{9,46,208},{10,39,2},{8,32,312},{0,43,788},{0,33,228},{20,62,200},{20,48,0},{21,39,20},{19,37,36},{44,0,723},{7,47,200},{10,39,2},{0,33,224},{89,0,723},{0,33,224},{15,57,200},{15,57,200},{15,57,200},
+{15,36,200},{10,54,162},{10,39,2},{10,39,2},{10,28,20},{0,35,179},{1,29,0},{20,47,0},{20,47,0},{20,47,0},{20,33,1},{36,1,162},{12,37,0},{12,37,0},{1,29,0},{74,0,162},{1,29,0},{50,1,200},{20,48,0},{24,39,0},{8,39,0},{50,1,200},{103,0,200},{8,39,0},{0,34,200},{103,0,200},{0,34,200},{15,0,200},{15,0,200},{15,0,200},{15,0,200},{10,40,0},
+{10,40,0},{10,40,0},{10,25,0},{1,29,0},{1,29,0},{19,76,400},{19,55,216},{20,44,312},{19,42,213},{14,73,723},{13,50,208},{14,43,2},{12,36,312},{0,49,740},{1,37,216},{24,66,200},{24,52,0},{25,43,20},{23,41,36},{50,0,723},{11,51,200},{14,43,2},{0,38,209},{101,0,723},{0,38,209},{19,61,200},{19,61,200},{19,61,200},{19,40,200},{14,58,162},{14,43,2},{14,43,2},
+{14,32,20},{1,42,163},{5,33,0},{24,51,0},{24,51,0},{24,51,0},{24,37,1},{42,1,162},{16,41,0},{16,41,0},{5,33,0},{86,0,162},{5,33,0},{56,1,200},{24,52,0},{28,43,0},{12,43,0},{56,1,200},{115,0,200},{12,43,0},{0,38,200},{115,0,200},{0,38,200},{19,0,200},{19,0,200},{19,0,200},{19,0,200},{14,44,0},{14,44,0},{14,44,0},{14,29,0},{5,33,0},
+{5,33,0},{24,80,402},{24,60,212},{25,49,308},{23,47,212},{19,76,724},{19,53,212},{19,47,4},{17,41,308},{1,55,724},{6,42,212},{29,69,201},{28,57,1},{30,48,19},{28,46,35},{56,1,723},{15,56,200},{19,47,3},{1,42,202},{115,0,723},{1,42,202},{24,64,202},{24,64,202},{24,64,202},{24,44,202},{19,61,163},{19,46,3},{19,46,3},{18,36,19},{6,46,163},{9,38,1},{29,55,1},
+{29,55,1},{29,55,1},{28,42,1},{49,0,162},{20,46,0},{20,46,0},{11,37,1},{100,0,162},{11,37,1},{63,0,200},{28,57,0},{33,47,1},{18,47,1},{63,0,200},{127,1,200},{18,47,1},{0,42,202},{127,1,200},{0,42,202},{23,0,202},{23,0,202},{23,0,202},{23,0,202},{19,48,1},{19,48,1},{19,48,1},{19,33,1},{9,38,0},{9,38,0},{28,84,402},{28,64,215},{29,53,308},
+{27,51,212},{23,80,724},{23,57,212},{23,51,4},{21,45,308},{5,59,724},{10,46,212},{33,73,201},{32,61,1},{34,52,19},{32,50,35},{62,1,723},{19,60,200},{23,51,3},{5,46,202},{127,0,723},{5,46,202},{28,68,202},{28,68,202},{28,68,202},{28,48,202},{23,65,163},{23,50,3},{23,50,3},{22,40,19},{10,50,163},{13,42,1},{33,59,1},{33,59,1},{33,59,1},{32,46,1},{55,0,162},
+{24,50,0},{24,50,0},{15,41,1},{112,0,162},{15,41,1},{69,0,200},{32,61,0},{37,51,1},{22,51,1},{69,0,200},{127,7,200},{22,51,1},{0,46,202},{127,7,200},{0,46,202},{27,0,202},{27,0,202},{27,0,202},{27,0,202},{23,52,1},{23,52,1},{23,52,1},{23,37,1},{13,42,0},{13,42,0},{32,88,402},{32,68,215},{33,57,308},{31,55,212},{27,84,724},{27,61,212},{27,55,4},
+{25,49,308},{8,64,723},{14,50,212},{37,77,201},{36,64,2},{38,56,19},{36,54,35},{68,0,723},{22,64,201},{27,55,3},{9,50,202},{127,6,723},{9,50,202},{32,72,202},{32,72,202},{32,72,202},{32,52,202},{27,69,163},{27,54,3},{27,54,3},{26,44,19},{14,54,163},{17,46,1},{37,63,1},{37,63,1},{37,63,1},{36,50,1},{61,0,162},{28,54,0},{28,54,0},{19,45,1},{124,0,162},
+{19,45,1},{75,0,200},{36,64,1},{41,55,1},{26,55,1},{75,0,200},{127,13,200},{26,55,1},{0,50,202},{127,13,200},{0,50,202},{31,0,202},{31,0,202},{31,0,202},{31,0,202},{27,56,1},{27,56,1},{27,56,1},{27,41,1},{17,46,0},{17,46,0},{36,92,402},{36,72,215},{37,61,308},{35,59,212},{31,88,724},{30,65,207},{31,59,4},{29,53,308},{12,68,723},{18,54,212},{41,81,201},
+{41,67,2},{42,60,19},{40,58,35},{74,0,723},{28,67,201},{31,59,3},{13,54,202},{127,12,723},{13,54,202},{36,76,202},{36,76,202},{36,76,202},{36,56,202},{31,73,163},{31,58,3},{31,58,3},{30,48,19},{18,58,163},{21,50,1},{41,66,1},{41,66,1},{41,66,1},{40,54,1},{66,1,162},{32,58,0},{32,58,0},{23,49,1},{126,5,162},{23,49,1},{80,1,200},{41,67,1},{45,59,1},
+{30,59,1},{80,1,200},{126,19,200},{30,59,1},{0,54,202},{126,19,200},{0,54,202},{35,0,202},{35,0,202},{35,0,202},{35,0,202},{31,60,1},{31,60,1},{31,60,1},{31,45,1},{21,50,0},{21,50,0},{40,97,400},{40,77,213},{42,64,314},{40,63,213},{35,94,723},{35,70,209},{35,64,6},{33,57,312},{17,72,723},{22,58,216},{45,87,200},{45,72,1},{46,64,21},{44,62,36},{80,1,723},
+{33,71,201},{36,63,4},{16,59,200},{126,19,723},{16,59,200},{40,82,200},{40,82,200},{40,82,200},{40,61,200},{35,78,162},{35,63,4},{35,63,4},{35,53,20},{22,63,163},{26,54,0},{45,72,0},{45,72,0},{45,72,0},{45,58,1},{73,0,162},{37,62,0},{37,62,0},{26,54,0},{126,12,162},{26,54,0},{87,0,200},{45,72,1},{49,64,1},{32,64,1},{87,0,200},{126,26,200},{32,64,1},
+{0,59,200},{126,26,200},{0,59,200},{40,0,200},{40,0,200},{40,0,200},{40,0,200},{35,65,0},{35,65,0},{35,65,0},{35,50,0},{26,54,0},{26,54,0},{44,101,400},{44,81,213},{46,68,314},{44,66,213},{39,98,723},{39,74,209},{39,67,2},{37,61,312},{21,76,723},{26,62,216},{49,91,200},{49,76,1},{50,68,21},{48,66,38},{86,1,723},{37,75,201},{39,67,2},{20,63,200},{126,25,723},
+{20,63,200},{44,86,200},{44,86,200},{44,86,200},{44,64,200},{39,82,162},{39,67,1},{39,67,1},{39,57,20},{25,67,162},{30,58,0},{49,76,0},{49,76,0},{49,76,0},{49,62,1},{79,0,162},{41,65,1},{41,65,1},{30,58,0},{127,17,162},{30,58,0},{93,0,200},{49,76,1},{53,67,1},{38,67,1},{93,0,200},{126,32,200},{38,67,1},{0,63,200},{126,32,200},{0,63,200},{44,0,200},
+{44,0,200},{44,0,200},{44,0,200},{39,69,0},{39,69,0},{39,69,0},{39,54,0},{30,58,0},{30,58,0},{48,105,400},{48,85,213},{50,72,314},{48,70,213},{43,102,723},{43,78,209},{43,71,2},{41,65,315},{25,80,723},{29,66,215},{53,95,200},{53,80,1},{54,72,21},{52,70,38},{92,1,723},{41,79,201},{43,71,2},{25,66,202},{126,31,723},{25,66,202},{48,90,200},{48,90,200},{48,90,200},
+{48,68,200},{43,86,162},{43,71,1},{43,71,1},{43,61,20},{29,71,162},{34,62,0},{53,80,0},{53,80,0},{53,80,0},{53,66,0},{85,0,162},{45,69,1},{45,69,1},{34,62,0},{127,23,162},{34,62,0},{99,0,200},{53,80,1},{57,71,1},{42,71,1},{99,0,200},{126,38,200},{42,71,1},{0,66,202},{126,38,200},{0,66,202},{48,0,200},{48,0,200},{48,0,200},{48,0,200},{43,73,0},
+{43,73,0},{43,73,0},{43,58,0},{34,62,0},{34,62,0},{52,109,400},{52,89,213},{54,76,314},{52,74,213},{47,106,723},{47,82,209},{47,75,2},{45,69,315},{29,84,723},{33,70,215},{57,99,200},{57,84,1},{58,76,21},{56,74,38},{98,1,723},{45,83,201},{47,75,2},{29,70,202},{126,37,723},{29,70,202},{52,94,200},{52,94,200},{52,94,200},{52,72,200},{47,90,162},{47,75,1},{47,75,1},
+{46,65,21},{33,75,162},{38,65,2},{57,84,0},{57,84,0},{57,84,0},{57,70,0},{91,0,162},{49,73,1},{49,73,1},{39,65,1},{127,29,162},{39,65,1},{105,0,200},{57,84,1},{61,75,1},{46,75,1},{105,0,200},{126,44,200},{46,75,1},{0,70,202},{126,44,200},{0,70,202},{52,0,200},{52,0,200},{52,0,200},{52,0,200},{47,77,0},{47,77,0},{47,77,0},{47,62,0},{38,65,1},
+{38,65,1},{57,113,402},{57,93,215},{58,82,315},{56,79,215},{52,109,724},{51,86,207},{52,80,2},{51,73,314},{33,89,723},{38,75,213},{62,102,201},{62,88,2},{62,81,21},{60,79,38},{105,0,723},{49,88,201},{52,80,1},{33,75,200},{126,44,723},{33,75,200},{57,97,202},{57,97,202},{57,97,202},{56,77,202},{52,94,163},{52,79,2},{52,79,2},{51,69,21},{38,79,162},{42,70,1},{62,87,1},
+{62,87,1},{62,87,1},{62,74,1},{98,0,162},{54,77,1},{54,77,1},{43,70,0},{127,36,162},{43,70,0},{112,0,200},{62,88,1},{65,80,0},{50,80,0},{112,0,200},{127,50,200},{50,80,0},{0,75,200},{127,50,200},{0,75,200},{56,0,202},{56,0,202},{56,0,202},{56,0,202},{52,80,1},{52,80,1},{52,80,1},{51,66,1},{43,69,1},{43,69,1},{61,117,402},{61,97,215},{62,86,315},
+{60,83,215},{56,113,724},{55,90,207},{56,84,2},{55,77,314},{37,93,723},{42,79,213},{65,107,200},{65,93,0},{66,84,20},{64,82,36},{111,0,723},{53,92,201},{56,84,1},{37,79,200},{127,49,723},{37,79,200},{61,101,202},{61,101,202},{61,101,202},{60,81,202},{56,98,163},{56,83,2},{56,83,2},{55,73,21},{42,83,162},{46,74,1},{65,92,0},{65,92,0},{65,92,0},{65,78,1},{104,0,162},
+{58,81,1},{58,81,1},{47,74,0},{127,42,162},{47,74,0},{118,0,200},{65,93,0},{69,84,0},{54,84,0},{118,0,200},{127,56,200},{54,84,0},{0,79,200},{127,56,200},{0,79,200},{60,0,202},{60,0,202},{60,0,202},{60,0,202},{56,84,1},{56,84,1},{56,84,1},{55,70,1},{47,73,1},{47,73,1},{64,122,400},{64,100,216},{65,89,312},{64,87,213},{60,117,724},{59,94,207},{60,88,2},
+{59,81,314},{41,97,723},{46,83,213},{69,111,200},{69,97,0},{70,88,20},{68,86,36},{117,0,723},{57,96,201},{60,88,1},{41,83,200},{127,55,723},{41,83,200},{64,106,200},{64,106,200},{64,106,200},{64,85,200},{60,102,163},{60,87,2},{60,87,2},{59,77,21},{46,87,162},{50,78,1},{69,96,0},{69,96,0},{69,96,0},{69,82,1},{110,0,162},{62,85,1},{62,85,1},{51,78,0},{126,48,162},
+{51,78,0},{124,0,200},{69,97,0},{73,88,0},{58,88,0},{124,0,200},{127,62,200},{58,88,0},{0,83,200},{127,62,200},{0,83,200},{64,0,200},{64,0,200},{64,0,200},{64,0,200},{60,88,1},{60,88,1},{60,88,1},{59,74,1},{51,77,1},{51,77,1},{68,126,400},{68,104,216},{69,93,312},{68,91,213},{63,123,724},{63,98,207},{63,92,6},{63,85,314},{45,101,723},{50,87,213},{73,115,200},
+{73,101,0},{74,92,20},{72,90,36},{123,0,723},{61,100,201},{64,91,4},{45,87,200},{127,61,723},{45,87,200},{68,110,200},{68,110,200},{68,110,200},{68,89,200},{63,108,163},{64,91,4},{64,91,4},{63,81,21},{50,91,162},{54,82,1},{73,100,0},{73,100,0},{73,100,0},{73,86,1},{115,1,162},{65,90,0},{65,90,0},{55,82,0},{126,54,162},{55,82,0},{127,5,200},{73,101,0},{77,92,0},
+{62,92,0},{127,5,200},{126,68,200},{62,92,0},{0,87,200},{126,68,200},{0,87,200},{68,0,200},{68,0,200},{68,0,200},{68,0,200},{63,94,1},{63,94,1},{63,94,1},{63,78,1},{55,81,1},{55,81,1},{73,126,410},{73,109,212},{74,98,308},{72,96,212},{68,126,724},{68,102,212},{68,96,4},{66,90,308},{50,105,723},{54,91,215},{78,119,201},{77,106,1},{79,97,19},{77,95,35},{127,5,723},
+{64,105,200},{68,96,3},{50,91,202},{126,68,723},{50,91,202},{73,114,202},{73,114,202},{73,114,202},{73,93,202},{68,110,163},{68,95,3},{68,95,3},{67,85,19},{54,96,162},{59,86,2},{78,104,1},{78,104,1},{78,104,1},{77,91,1},{122,0,162},{69,95,0},{69,95,0},{60,86,1},{126,61,162},{60,86,1},{127,19,200},{77,106,0},{82,96,1},{67,96,1},{127,19,200},{127,74,200},{67,96,1},
+{0,91,202},{127,74,200},{0,91,202},{72,0,202},{72,0,202},{72,0,202},{72,0,202},{68,97,1},{68,97,1},{68,97,1},{68,82,1},{59,86,1},{59,86,1},{77,127,434},{77,113,212},{78,102,308},{76,100,212},{72,127,732},{72,106,212},{72,100,4},{70,94,308},{54,109,723},{58,95,215},{82,123,201},{81,110,1},{83,101,19},{81,99,35},{127,18,723},{68,109,200},{72,100,3},{54,95,202},{126,74,723},
+{54,95,202},{77,118,202},{77,118,202},{77,118,202},{77,97,202},{72,114,163},{72,99,3},{72,99,3},{71,89,19},{58,100,162},{63,90,2},{82,108,1},{82,108,1},{82,108,1},{81,95,1},{127,2,162},{73,99,0},{73,99,0},{64,90,1},{127,66,162},{64,90,1},{127,31,200},{81,110,0},{86,100,1},{71,100,1},{127,31,200},{127,80,200},{71,100,1},{0,95,202},{127,80,200},{0,95,202},{76,0,202},
+{76,0,202},{76,0,202},{76,0,202},{72,101,1},{72,101,1},{72,101,1},{72,86,1},{63,90,1},{63,90,1},{82,127,468},{81,117,212},{82,106,308},{80,104,212},{77,127,753},{76,110,212},{76,104,4},{74,98,308},{58,113,723},{62,99,215},{86,127,201},{85,114,1},{87,105,19},{85,103,35},{127,30,723},{72,113,200},{76,104,3},{58,99,202},{127,79,723},{58,99,202},{81,122,202},{81,122,202},{81,122,202},
+{81,101,202},{76,118,163},{76,103,3},{76,103,3},{75,93,19},{62,104,162},{66,95,1},{86,112,1},{86,112,1},{86,112,1},{85,99,1},{127,14,162},{77,103,0},{77,103,0},{68,94,1},{127,72,162},{68,94,1},{127,43,200},{85,114,0},{90,104,1},{75,104,1},{127,43,200},{127,86,200},{75,104,1},{0,99,202},{127,86,200},{0,99,202},{80,0,202},{80,0,202},{80,0,202},{80,0,202},{76,105,1},
+{76,105,1},{76,105,1},{76,90,1},{66,95,0},{66,95,0},{86,127,546},{85,121,212},{86,110,308},{84,108,212},{82,127,788},{80,114,212},{80,108,4},{78,102,308},{62,117,723},{67,103,212},{91,127,211},{89,118,1},{91,109,19},{89,107,35},{127,42,723},{76,117,200},{80,108,3},{62,103,202},{127,85,723},{62,103,202},{85,126,202},{85,126,202},{85,126,202},{85,105,202},{80,122,163},{80,107,3},{80,107,3},
+{79,97,19},{67,107,163},{70,99,1},{90,116,1},{90,116,1},{90,116,1},{89,103,1},{127,27,162},{81,107,0},{81,107,0},{72,98,1},{126,78,162},{72,98,1},{127,56,200},{89,118,0},{94,108,1},{79,108,1},{127,56,200},{127,92,200},{79,108,1},{0,103,202},{127,92,200},{0,103,202},{84,0,202},{84,0,202},{84,0,202},{84,0,202},{80,109,1},{80,109,1},{80,109,1},{80,94,1},{70,99,0},
+{70,99,0},{91,127,632},{89,125,216},{90,114,312},{89,112,213},{88,127,852},{83,120,208},{84,113,2},{82,106,312},{66,121,724},{71,107,216},{97,127,244},{94,122,0},{95,113,20},{93,111,36},{127,56,723},{81,121,200},{84,113,2},{65,108,200},{127,92,723},{65,108,200},{89,127,209},{89,127,209},{89,127,209},{89,110,200},{84,126,164},{84,113,2},{84,113,2},{84,102,20},{71,112,163},{75,103,0},{94,121,0},
+{94,121,0},{94,121,0},{94,107,1},{127,40,162},{86,111,0},{86,111,0},{75,103,0},{126,85,162},{75,103,0},{127,69,200},{94,122,0},{98,113,0},{82,113,0},{127,69,200},{126,99,200},{82,113,0},{0,108,200},{126,99,200},{0,108,200},{89,0,200},{89,0,200},{89,0,200},{89,0,200},{84,114,0},{84,114,0},{84,114,0},{84,99,0},{75,103,0},{75,103,0},{97,127,728},{94,127,228},{94,118,312},
+{93,116,213},{94,127,932},{87,124,208},{88,117,2},{86,110,312},{70,125,724},{75,111,216},{101,127,286},{98,126,0},{99,117,20},{97,115,36},{127,67,723},{85,125,200},{88,117,2},{69,112,200},{127,98,723},{69,112,200},{94,127,224},{94,127,224},{94,127,224},{93,114,200},{89,127,174},{88,117,2},{88,117,2},{88,106,20},{75,116,163},{79,107,0},{98,125,0},{98,125,0},{98,125,0},{98,111,1},{127,53,162},
+{90,115,0},{90,115,0},{79,107,0},{126,91,162},{79,107,0},{127,81,200},{98,126,0},{102,117,0},{86,117,0},{127,81,200},{126,105,200},{86,117,0},{0,112,200},{126,105,200},{0,112,200},{93,0,200},{93,0,200},{93,0,200},{93,0,200},{88,118,0},{88,118,0},{88,118,0},{88,103,0},{79,107,0},{79,107,0},{100,127,864},{99,127,304},{98,122,312},{97,120,213},{98,127,1043},{92,127,211},{92,121,2},
+{90,114,312},{76,127,732},{79,115,216},{106,127,336},{102,127,20},{103,121,20},{101,119,36},{127,79,723},{90,127,208},{92,121,2},{73,116,200},{127,104,723},{73,116,200},{98,127,257},{98,127,257},{98,127,257},{97,118,200},{94,127,196},{92,121,2},{92,121,2},{92,110,20},{79,120,163},{83,111,0},{102,126,4},{102,126,4},{102,126,4},{102,115,1},{127,64,162},{94,119,0},{94,119,0},{83,111,0},{126,97,162},
+{83,111,0},{127,93,200},{105,127,8},{106,121,0},{90,121,0},{127,93,200},{126,111,200},{90,121,0},{0,116,200},{126,111,200},{0,116,200},{97,0,200},{97,0,200},{97,0,200},{97,0,200},{92,122,0},{92,122,0},{92,122,0},{92,107,0},{83,111,0},{83,111,0},{106,127,992},{103,127,440},{102,126,312},{101,124,213},{103,127,1144},{96,127,272},{96,125,2},{94,118,312},{84,127,804},{83,119,216},{111,127,398},
+{108,127,84},{107,125,20},{105,123,36},{127,92,723},{99,127,248},{96,125,2},{77,120,200},{126,110,723},{77,120,200},{103,127,296},{103,127,296},{103,127,296},{101,122,200},{100,127,244},{96,125,2},{96,125,2},{96,114,20},{83,124,163},{87,115,0},{107,127,13},{107,127,13},{107,127,13},{106,119,1},{127,76,162},{98,123,0},{98,123,0},{87,115,0},{126,103,162},{87,115,0},{127,105,200},{111,127,45},{110,125,0},
+{94,125,0},{127,105,200},{126,117,200},{94,125,0},{0,120,200},{126,117,200},{0,120,200},{101,0,200},{101,0,200},{101,0,200},{101,0,200},{96,126,0},{96,126,0},{96,126,0},{96,111,0},{87,115,0},{87,115,0},{111,127,919},{108,127,515},{107,127,362},{105,127,203},{109,127,1027},{102,127,267},{101,127,9},{99,122,198},{93,127,703},{88,123,121},{115,127,338},{113,127,122},{112,127,34},{110,126,14},{127,102,546},
+{108,127,202},{102,127,2},{85,123,113},{127,115,546},{85,123,113},{107,127,362},{107,127,362},{107,127,362},{106,126,202},{104,127,309},{101,127,9},{101,127,9},{100,118,19},{89,127,168},{91,120,1},{112,127,34},{112,127,34},{112,127,34},{110,124,1},{127,90,162},{104,126,2},{104,126,2},{93,119,1},{127,109,162},{93,119,1},{127,115,113},{119,127,41},{116,127,0},{104,127,0},{127,115,113},{127,121,113},{104,127,0},
+{0,123,113},{127,121,113},{0,123,113},{105,0,202},{105,0,202},{105,0,202},{105,0,202},{101,127,5},{101,127,5},{101,127,5},{101,115,1},{91,120,0},{91,120,0},{114,127,751},{111,127,514},{111,127,414},{110,127,218},{114,127,814},{108,127,219},{107,127,65},{103,124,71},{102,127,539},{94,125,27},{120,127,206},{117,127,110},{117,127,61},{115,127,2},{127,110,333},{113,127,121},{110,127,20},{93,125,25},{126,119,333},
+{93,125,25},{111,127,414},{111,127,414},{111,127,414},{110,127,218},{109,127,371},{107,127,65},{107,127,65},{104,122,19},{96,127,203},{95,124,1},{117,127,61},{117,127,61},{117,127,61},{115,127,2},{127,102,162},{110,127,20},{110,127,20},{97,123,1},{127,115,162},{97,123,1},{127,121,25},{122,127,9},{122,127,0},{116,127,0},{127,121,25},{127,124,25},{116,127,0},{0,125,25},{127,124,25},{0,125,25},{109,0,202},
+{109,0,202},{109,0,202},{109,0,202},{106,127,18},{106,127,18},{106,127,18},{105,119,1},{95,124,0},{95,124,0},{117,127,636},{117,127,516},{117,127,467},{115,127,282},{117,127,643},{111,127,241},{111,127,141},{108,126,18},{108,127,434},{99,127,2},{123,127,131},{121,127,105},{121,127,89},{119,127,26},{127,118,193},{119,127,86},{116,127,53},{101,127,0},{126,123,193},{101,127,0},{117,127,467},{117,127,467},{117,127,467},
+{115,127,282},{114,127,410},{111,127,141},{111,127,141},{108,126,14},{105,127,254},{99,127,2},{121,127,89},{121,127,89},{121,127,89},{119,127,26},{127,113,145},{116,127,53},{116,127,53},{101,127,0},{127,120,145},{101,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{113,0,202},{113,0,202},{113,0,202},{113,0,202},{111,127,41},
+{111,127,41},{111,127,41},{109,123,1},{101,126,2},{101,126,2},{120,127,412},{120,127,356},{120,127,331},{118,127,238},{120,127,387},{116,127,183},{116,127,134},{113,127,1},{113,127,262},{108,127,18},{124,127,41},{124,127,29},{124,127,25},{122,127,10},{127,122,54},{122,127,22},{122,127,13},{113,127,0},{126,125,54},{113,127,0},{120,127,331},{120,127,331},{120,127,331},{118,127,238},{117,127,266},{116,127,134},{116,127,134},
+{113,127,1},{110,127,161},{108,127,18},{124,127,25},{124,127,25},{124,127,25},{122,127,10},{127,119,41},{122,127,13},{122,127,13},{113,127,0},{127,123,41},{113,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{117,0,202},{117,0,202},{117,0,202},{117,0,202},{114,127,73},{114,127,73},{114,127,73},{113,127,1},{108,127,18},
+{108,127,18},{0,41,421},{0,28,41},{0,21,1},{0,18,157},{0,27,925},{0,19,569},{0,17,285},{0,12,701},{0,12,1005},{0,10,751},{0,41,421},{0,28,41},{0,21,1},{0,18,157},{13,1,925},{0,19,569},{0,17,285},{0,12,701},{27,0,925},{0,12,701},{0,20,0},{0,20,0},{0,20,0},{0,10,0},{0,9,85},{0,8,29},{0,8,29},{0,4,50},{0,5,94},{0,4,59},{0,20,0},
+{0,20,0},{0,20,0},{0,10,0},{5,0,85},{0,8,29},{0,8,29},{0,4,50},{9,0,85},{0,4,50},{20,0,421},{0,28,41},{0,21,1},{0,18,157},{20,0,421},{41,0,421},{0,18,157},{0,14,421},{41,0,421},{0,14,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,53,421},{0,37,9},{1,25,17},
+{0,21,113},{0,36,1261},{0,22,677},{0,20,305},{0,15,881},{0,17,1383},{0,13,971},{0,53,421},{0,37,9},{1,25,13},{0,21,113},{18,0,1261},{0,22,677},{0,20,305},{0,15,881},{36,0,1261},{0,15,881},{0,32,0},{0,32,0},{0,32,0},{0,15,1},{0,15,221},{0,11,85},{0,11,85},{0,7,130},{0,8,246},{0,7,155},{0,32,0},{0,32,0},{0,32,0},{0,15,1},{8,0,221},
+{0,11,85},{0,11,85},{0,7,130},{15,0,221},{0,7,130},{26,0,421},{0,37,9},{3,25,1},{0,21,113},{26,0,421},{53,0,421},{0,21,113},{0,18,421},{53,0,421},{0,18,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,63,426},{1,42,6},{2,29,66},{0,27,74},{0,45,1514},{0,28,706},{0,25,258},
+{0,18,974},{0,19,1706},{0,18,1118},{2,61,422},{1,42,2},{3,30,38},{0,27,74},{22,0,1514},{0,28,706},{0,25,258},{0,18,974},{45,0,1514},{0,18,974},{1,42,5},{1,42,5},{1,42,5},{1,21,5},{0,24,338},{0,19,90},{0,19,90},{0,10,181},{0,11,389},{0,10,230},{2,40,1},{2,40,1},{2,40,1},{1,21,1},{12,0,338},{0,19,90},{0,19,90},{0,10,181},{24,0,338},
+{0,10,181},{32,0,421},{1,42,1},{7,29,1},{0,27,65},{32,0,421},{65,0,421},{0,27,65},{0,22,421},{65,0,421},{0,22,421},{1,0,5},{1,0,5},{1,0,5},{1,0,5},{0,4,0},{0,4,0},{0,4,0},{0,2,0},{0,2,1},{0,2,1},{3,71,482},{3,48,62},{4,34,158},{2,31,117},{0,58,1514},{0,37,594},{0,31,122},{0,23,881},{0,25,1818},{0,21,1086},{6,65,422},
+{5,46,2},{7,34,38},{4,31,74},{28,0,1514},{0,37,594},{0,31,122},{0,23,881},{58,0,1514},{0,23,881},{3,50,61},{3,50,61},{3,50,61},{3,26,61},{0,36,338},{0,25,34},{0,25,34},{0,15,130},{0,17,461},{0,14,226},{6,44,1},{6,44,1},{6,44,1},{5,25,1},{18,0,338},{0,25,34},{0,25,34},{0,15,130},{36,0,338},{0,15,130},{38,0,421},{5,46,1},{11,33,1},
+{0,32,40},{38,0,421},{77,0,421},{0,32,40},{0,26,421},{77,0,421},{0,26,421},{3,0,61},{3,0,61},{3,0,61},{3,0,61},{0,16,0},{0,16,0},{0,16,0},{0,8,0},{0,5,25},{0,5,25},{5,80,621},{5,55,213},{7,40,357},{5,35,241},{0,71,1514},{0,43,497},{0,36,29},{0,27,761},{0,31,1989},{0,26,1079},{10,70,421},{10,50,1},{11,38,41},{8,35,77},{35,0,1514},
+{0,43,497},{0,36,29},{0,27,761},{71,0,1514},{0,27,761},{5,60,200},{5,60,200},{5,60,200},{5,32,200},{0,50,338},{0,34,4},{0,34,4},{0,21,80},{0,22,552},{0,19,244},{10,49,0},{10,49,0},{10,49,0},{10,29,0},{24,1,338},{0,34,4},{0,34,4},{0,21,80},{50,0,338},{0,21,80},{45,0,421},{10,50,1},{16,37,1},{0,36,13},{45,0,421},{91,0,421},{0,36,13},
+{0,30,421},{91,0,421},{0,30,421},{5,0,200},{5,0,200},{5,0,200},{5,0,200},{0,30,0},{0,30,0},{0,30,0},{0,15,0},{0,11,74},{0,11,74},{7,89,813},{7,60,421},{10,43,617},{7,40,417},{0,83,1514},{0,51,446},{0,41,3},{0,32,686},{0,37,2165},{0,31,1101},{14,74,421},{14,54,1},{15,42,41},{12,39,77},{41,0,1514},{0,51,446},{0,41,3},{0,32,686},{83,0,1514},
+{0,32,686},{7,67,392},{7,67,392},{7,67,392},{7,37,392},{0,62,338},{0,41,2},{0,41,2},{0,24,52},{0,28,680},{0,23,298},{14,53,0},{14,53,0},{14,53,0},{14,33,0},{30,1,338},{2,39,0},{2,39,0},{0,24,52},{62,0,338},{0,24,52},{51,0,421},{14,54,1},{20,41,1},{0,41,2},{51,0,421},{103,0,421},{0,41,2},{0,34,421},{103,0,421},{0,34,421},{7,0,392},
+{7,0,392},{7,0,392},{7,0,392},{0,42,0},{0,42,0},{0,42,0},{0,21,0},{0,17,146},{0,17,146},{11,93,842},{11,65,453},{12,48,654},{11,44,446},{4,87,1515},{3,54,435},{4,45,4},{0,36,654},{0,43,2030},{0,35,882},{18,78,421},{18,58,1},{19,46,41},{16,43,77},{47,0,1514},{0,57,422},{4,45,3},{0,36,605},{95,0,1514},{0,36,605},{11,71,421},{11,71,421},{11,71,421},
+{11,41,421},{4,66,339},{4,45,3},{4,45,3},{2,29,41},{0,34,581},{0,28,161},{18,57,0},{18,57,0},{18,57,0},{18,37,0},{36,1,338},{6,43,0},{6,43,0},{0,30,20},{74,0,338},{0,30,20},{57,0,421},{18,58,1},{24,45,1},{2,45,1},{57,0,421},{115,0,421},{2,45,1},{0,38,421},{115,0,421},{0,38,421},{11,0,421},{11,0,421},{11,0,421},{11,0,421},{4,46,1},
+{4,46,1},{4,46,1},{3,25,1},{0,22,85},{0,22,85},{15,97,842},{16,67,453},{16,52,654},{15,48,446},{8,91,1515},{7,58,435},{8,49,4},{4,40,654},{0,51,1850},{0,40,682},{22,82,421},{22,62,1},{23,50,41},{20,47,77},{53,0,1514},{3,61,421},{8,49,3},{0,41,554},{107,0,1514},{0,41,554},{15,75,421},{15,75,421},{15,75,421},{15,45,421},{8,70,339},{8,49,3},{8,49,3},
+{6,33,41},{0,40,477},{0,34,57},{22,61,0},{22,61,0},{22,61,0},{22,41,0},{42,1,338},{10,47,0},{10,47,0},{0,34,8},{86,0,338},{0,34,8},{63,0,421},{22,62,1},{28,49,1},{6,49,1},{63,0,421},{127,0,421},{6,49,1},{0,42,421},{127,0,421},{0,42,421},{15,0,421},{15,0,421},{15,0,421},{15,0,421},{8,50,1},{8,50,1},{8,50,1},{7,29,1},{0,31,29},
+{0,31,29},{19,102,842},{20,71,451},{21,57,650},{19,52,446},{12,97,1514},{12,63,437},{12,54,2},{9,45,650},{0,57,1710},{0,45,530},{27,86,422},{26,67,1},{28,55,38},{25,52,74},{59,1,1514},{7,66,421},{12,54,2},{0,45,494},{121,0,1514},{0,45,494},{19,81,421},{19,81,421},{19,81,421},{19,49,422},{12,75,338},{12,54,2},{12,54,2},{11,38,38},{0,49,402},{0,39,6},{27,64,1},
+{27,64,1},{27,64,1},{26,46,1},{49,0,338},{14,52,0},{14,52,0},{1,39,1},{100,0,338},{1,39,1},{69,0,421},{26,67,0},{32,54,1},{10,54,0},{69,0,421},{127,7,421},{10,54,0},{0,47,421},{127,7,421},{0,47,421},{19,0,421},{19,0,421},{19,0,421},{19,0,421},{12,56,0},{12,56,0},{12,56,0},{12,33,1},{0,38,5},{0,38,5},{23,106,842},{24,75,451},{25,61,650},
+{23,56,446},{16,101,1514},{15,67,434},{16,58,2},{13,49,650},{0,64,1617},{0,50,462},{31,90,422},{30,71,1},{32,59,38},{29,56,74},{65,0,1514},{11,70,421},{16,58,2},{0,50,461},{127,3,1514},{0,50,461},{23,85,421},{23,85,421},{23,85,421},{23,53,422},{16,79,338},{16,58,2},{16,58,2},{15,42,38},{0,54,349},{3,43,2},{31,68,1},{31,68,1},{31,68,1},{30,50,1},{55,0,338},
+{18,56,0},{18,56,0},{5,43,1},{112,0,338},{5,43,1},{75,0,421},{30,71,0},{36,58,1},{14,58,0},{75,0,421},{127,13,421},{14,58,0},{0,51,421},{127,13,421},{0,51,421},{23,0,421},{23,0,421},{23,0,421},{23,0,421},{16,60,0},{16,60,0},{16,60,0},{16,37,1},{3,43,1},{3,43,1},{27,110,842},{28,79,451},{30,64,650},{27,60,446},{20,105,1514},{19,71,434},{20,62,2},
+{17,53,650},{0,70,1553},{1,54,450},{35,94,422},{34,75,1},{36,63,38},{33,60,74},{71,0,1514},{15,74,421},{20,62,2},{0,54,441},{127,9,1514},{0,54,441},{27,89,421},{27,89,421},{27,89,421},{27,57,422},{20,83,338},{20,62,2},{20,62,2},{19,46,38},{0,61,338},{7,47,2},{35,72,1},{35,72,1},{35,72,1},{34,54,1},{61,0,338},{22,60,0},{22,60,0},{9,47,1},{124,0,338},
+{9,47,1},{81,0,421},{34,75,0},{40,62,1},{18,62,0},{81,0,421},{126,19,421},{18,62,0},{0,55,421},{126,19,421},{0,55,421},{27,0,421},{27,0,421},{27,0,421},{27,0,421},{20,64,0},{20,64,0},{20,64,0},{20,41,1},{7,47,1},{7,47,1},{31,114,842},{32,83,451},{33,67,650},{31,64,446},{24,109,1514},{23,75,434},{24,65,6},{21,57,650},{0,76,1521},{5,58,450},{39,98,422},
+{38,79,1},{41,66,42},{37,63,81},{77,0,1514},{19,78,421},{25,65,2},{0,59,425},{127,15,1514},{0,59,425},{31,93,421},{31,93,421},{31,93,421},{31,61,422},{24,87,338},{24,64,5},{24,64,5},{23,50,38},{5,64,339},{11,51,2},{39,76,1},{39,76,1},{39,76,1},{38,58,1},{66,1,338},{25,64,1},{25,64,1},{13,51,1},{126,5,338},{13,51,1},{87,0,421},{38,79,0},{45,65,1},
+{23,65,1},{87,0,421},{126,25,421},{23,65,1},{0,59,421},{126,25,421},{0,59,421},{31,0,421},{31,0,421},{31,0,421},{31,0,421},{24,67,0},{24,67,0},{24,67,0},{24,45,1},{11,51,1},{11,51,1},{36,118,842},{37,88,453},{38,72,646},{35,69,445},{29,112,1515},{27,79,438},{29,69,6},{25,61,654},{3,82,1515},{10,63,450},{43,103,421},{43,83,2},{45,70,41},{42,67,76},{83,1,1514},
+{24,82,421},{29,69,5},{2,63,421},{126,22,1514},{2,63,421},{36,96,421},{36,96,421},{36,96,421},{36,65,421},{29,91,339},{29,69,2},{29,69,2},{27,54,41},{10,68,339},{15,56,1},{43,82,0},{43,82,0},{43,82,0},{43,62,0},{73,0,338},{31,67,1},{31,67,1},{16,56,0},{126,12,338},{16,56,0},{93,0,421},{42,84,0},{49,70,0},{26,70,0},{93,0,421},{126,32,421},{26,70,0},
+{0,63,421},{126,32,421},{0,63,421},{36,0,421},{36,0,421},{36,0,421},{36,0,421},{29,71,1},{29,71,1},{29,71,1},{28,50,1},{15,56,1},{15,56,1},{40,122,842},{41,92,453},{42,76,646},{39,73,445},{33,116,1515},{31,83,438},{33,73,6},{30,64,650},{7,86,1515},{15,66,451},{47,107,421},{47,87,2},{49,74,41},{46,71,76},{89,1,1514},{28,86,421},{33,73,5},{5,67,421},{126,28,1514},
+{5,67,421},{40,100,421},{40,100,421},{40,100,421},{40,69,421},{33,95,339},{33,73,2},{33,73,2},{31,58,41},{14,72,339},{19,60,1},{47,86,0},{47,86,0},{47,86,0},{47,66,0},{79,0,338},{35,71,1},{35,71,1},{20,60,0},{127,17,338},{20,60,0},{99,0,421},{46,88,0},{53,74,0},{30,74,0},{99,0,421},{126,38,421},{30,74,0},{0,67,421},{126,38,421},{0,67,421},{40,0,421},
+{40,0,421},{40,0,421},{40,0,421},{33,75,1},{33,75,1},{33,75,1},{32,54,1},{19,60,1},{19,60,1},{44,126,842},{45,96,453},{46,80,646},{43,77,445},{37,120,1515},{35,87,438},{37,77,6},{34,68,650},{11,90,1515},{19,70,451},{51,111,421},{51,91,2},{53,78,41},{50,75,76},{95,1,1514},{32,90,421},{37,77,5},{9,71,421},{126,34,1514},{9,71,421},{44,104,421},{44,104,421},{44,104,421},
+{44,73,421},{37,99,339},{37,77,2},{37,77,2},{35,62,41},{18,76,339},{23,64,1},{51,90,0},{51,90,0},{51,90,0},{51,70,0},{85,0,338},{39,75,1},{39,75,1},{23,64,1},{127,23,338},{23,64,1},{105,0,421},{50,92,0},{57,78,0},{34,78,0},{105,0,421},{126,44,421},{34,78,0},{0,71,421},{126,44,421},{0,71,421},{44,0,421},{44,0,421},{44,0,421},{44,0,421},{37,79,1},
+{37,79,1},{37,79,1},{36,58,1},{23,64,0},{23,64,0},{48,126,854},{49,100,453},{50,84,646},{47,81,445},{41,124,1515},{39,91,438},{41,81,6},{38,72,650},{15,94,1515},{23,74,451},{55,115,421},{55,95,2},{57,82,41},{54,79,76},{101,1,1514},{36,94,421},{41,81,5},{13,75,421},{126,40,1514},{13,75,421},{48,108,421},{48,108,421},{48,108,421},{48,77,421},{41,103,339},{41,81,2},{41,81,2},
+{40,65,42},{22,80,339},{27,68,1},{55,94,0},{55,94,0},{55,94,0},{55,74,0},{91,0,338},{43,79,1},{43,79,1},{29,67,1},{127,29,338},{29,67,1},{111,0,421},{54,96,0},{61,82,0},{38,82,0},{111,0,421},{127,49,421},{38,82,0},{0,75,421},{127,49,421},{0,75,421},{48,0,421},{48,0,421},{48,0,421},{48,0,421},{41,83,1},{41,83,1},{41,83,1},{40,62,1},{27,68,0},
+{27,68,0},{53,127,886},{53,104,451},{54,88,650},{52,85,446},{46,126,1521},{44,96,434},{45,86,6},{43,77,646},{18,99,1515},{27,78,453},{60,119,422},{59,100,1},{62,87,42},{59,84,75},{108,0,1514},{40,99,421},{46,86,2},{18,79,421},{125,47,1514},{18,79,421},{52,114,421},{52,114,421},{52,114,421},{52,82,421},{45,108,338},{45,85,5},{45,85,5},{45,70,41},{26,85,339},{31,72,2},{60,97,1},
+{60,97,1},{60,97,1},{60,78,1},{98,0,338},{48,83,1},{48,83,1},{33,72,0},{127,36,338},{33,72,0},{118,0,421},{59,100,0},{65,86,1},{44,86,1},{118,0,421},{127,56,421},{44,86,1},{0,79,421},{127,56,421},{0,79,421},{52,0,421},{52,0,421},{52,0,421},{52,0,421},{45,88,0},{45,88,0},{45,88,0},{45,66,0},{31,73,0},{31,73,0},{58,127,926},{57,108,451},{58,92,650},
+{56,89,446},{51,126,1542},{48,100,434},{49,90,6},{47,81,646},{22,103,1515},{31,82,453},{63,125,422},{63,104,1},{64,91,41},{63,88,75},{114,0,1514},{44,103,421},{50,90,2},{22,83,421},{127,52,1514},{22,83,421},{56,118,421},{56,118,421},{56,118,421},{56,86,421},{49,112,338},{49,89,5},{49,89,5},{49,74,41},{30,89,339},{35,76,2},{63,103,1},{63,103,1},{63,103,1},{63,82,2},{104,0,338},
+{52,87,1},{52,87,1},{37,76,0},{127,42,338},{37,76,0},{124,0,421},{63,104,0},{69,90,1},{48,90,1},{124,0,421},{127,62,421},{48,90,1},{0,83,421},{127,62,421},{0,83,421},{56,0,421},{56,0,421},{56,0,421},{56,0,421},{49,92,0},{49,92,0},{49,92,0},{49,70,0},{35,77,0},{35,77,0},{62,127,1010},{61,112,451},{62,96,650},{60,93,446},{56,127,1577},{52,104,434},{53,94,6},
+{51,85,646},{26,107,1515},{35,86,453},{67,126,425},{67,107,1},{68,95,41},{65,92,77},{120,0,1514},{48,107,421},{54,94,2},{26,87,421},{127,58,1514},{26,87,421},{60,122,421},{60,122,421},{60,122,421},{60,90,421},{53,116,338},{53,93,5},{53,93,5},{53,78,41},{34,93,339},{39,80,2},{67,106,0},{67,106,0},{67,106,0},{67,86,0},{110,0,338},{56,91,1},{56,91,1},{41,80,0},{126,48,338},
+{41,80,0},{127,5,421},{67,107,1},{73,94,1},{52,94,1},{127,5,421},{126,68,421},{52,94,1},{0,87,421},{126,68,421},{0,87,421},{60,0,421},{60,0,421},{60,0,421},{60,0,421},{53,96,0},{53,96,0},{53,96,0},{53,74,0},{39,81,0},{39,81,0},{68,127,1098},{64,117,450},{65,101,654},{64,97,446},{61,127,1626},{56,108,434},{57,98,6},{55,89,646},{30,111,1515},{39,90,453},{72,127,437},
+{71,111,1},{72,99,41},{69,96,77},{126,0,1514},{52,111,421},{58,98,2},{30,91,421},{126,64,1514},{30,91,421},{64,125,421},{64,125,421},{64,125,421},{64,94,421},{57,120,338},{57,97,5},{57,97,5},{57,82,41},{38,97,339},{43,84,2},{71,110,0},{71,110,0},{71,110,0},{71,90,0},{115,1,338},{60,95,1},{60,95,1},{45,84,0},{126,54,338},{45,84,0},{127,18,421},{71,111,1},{77,98,1},
+{56,98,1},{127,18,421},{126,74,421},{56,98,1},{0,91,421},{126,74,421},{0,91,421},{64,0,421},{64,0,421},{64,0,421},{64,0,421},{57,100,0},{57,100,0},{57,100,0},{57,78,0},{43,85,0},{43,85,0},{71,127,1214},{69,122,450},{70,106,650},{68,101,446},{66,127,1722},{60,112,438},{62,102,6},{59,93,650},{36,115,1515},{44,95,451},{78,126,470},{75,116,2},{77,104,38},{74,101,74},{127,11,1514},
+{57,115,421},{62,102,5},{34,96,421},{126,71,1514},{34,96,421},{68,127,425},{68,127,425},{68,127,425},{68,98,422},{62,124,339},{62,102,2},{62,102,2},{61,86,42},{43,101,339},{48,89,1},{76,114,1},{76,114,1},{76,114,1},{75,95,1},{122,0,338},{63,101,1},{63,101,1},{50,88,1},{126,61,338},{50,88,1},{127,31,421},{75,116,1},{81,103,1},{59,103,0},{127,31,421},{127,80,421},{59,103,0},
+{0,96,421},{127,80,421},{0,96,421},{68,0,421},{68,0,421},{68,0,421},{68,0,421},{62,104,1},{62,104,1},{62,104,1},{62,82,1},{48,89,0},{48,89,0},{77,127,1334},{73,126,450},{74,110,650},{72,105,446},{71,127,1805},{65,116,437},{65,107,2},{63,97,650},{40,119,1515},{48,99,451},{82,127,506},{79,120,2},{81,108,38},{78,105,74},{127,24,1514},{61,119,421},{65,107,2},{38,100,421},{125,77,1514},
+{38,100,421},{73,126,441},{73,126,441},{73,126,441},{72,102,422},{65,127,340},{65,107,2},{65,107,2},{64,91,38},{47,105,339},{52,93,1},{80,118,1},{80,118,1},{80,118,1},{79,99,1},{127,2,338},{67,105,0},{67,105,0},{54,92,1},{127,66,338},{54,92,1},{127,43,421},{79,120,1},{85,107,1},{63,107,0},{127,43,421},{127,86,421},{63,107,0},{0,100,421},{127,86,421},{0,100,421},{72,0,421},
+{72,0,421},{72,0,421},{72,0,421},{65,109,0},{65,109,0},{65,109,0},{65,86,1},{52,93,0},{52,93,0},{82,127,1470},{77,127,462},{78,114,650},{76,109,446},{77,127,1917},{69,120,437},{69,111,2},{66,102,650},{44,123,1515},{52,103,451},{88,127,562},{83,124,2},{85,112,38},{82,109,74},{127,36,1514},{65,122,421},{69,111,2},{42,104,421},{127,82,1514},{42,104,421},{77,127,461},{77,127,461},{77,127,461},
+{76,106,422},{71,127,356},{69,111,2},{69,111,2},{68,95,38},{51,109,339},{56,97,1},{84,122,1},{84,122,1},{84,122,1},{83,103,1},{127,14,338},{71,109,0},{71,109,0},{58,96,1},{127,72,338},{58,96,1},{127,56,421},{83,124,1},{89,111,1},{67,111,0},{127,56,421},{127,92,421},{67,111,0},{0,104,421},{127,92,421},{0,104,421},{76,0,421},{76,0,421},{76,0,421},{76,0,421},{69,113,0},
+{69,113,0},{69,113,0},{69,90,1},{56,97,0},{56,97,0},{85,127,1634},{82,127,530},{82,118,650},{80,113,446},{82,127,2030},{73,124,437},{73,115,2},{70,106,650},{48,127,1515},{56,107,451},{92,127,646},{87,127,6},{89,116,38},{86,113,74},{127,48,1514},{69,126,421},{73,115,2},{46,108,421},{127,88,1514},{46,108,421},{82,127,494},{82,127,494},{82,127,494},{80,110,422},{75,127,386},{73,115,2},{73,115,2},
+{72,99,38},{55,113,339},{60,101,1},{88,126,1},{88,126,1},{88,126,1},{87,107,1},{127,27,338},{75,113,0},{75,113,0},{62,100,1},{126,78,338},{62,100,1},{127,67,421},{89,126,5},{93,115,1},{71,115,0},{127,67,421},{127,98,421},{71,115,0},{0,108,421},{127,98,421},{0,108,421},{80,0,421},{80,0,421},{80,0,421},{80,0,421},{73,117,0},{73,117,0},{73,117,0},{73,94,1},{60,101,0},
+{60,101,0},{91,127,1838},{87,127,682},{86,122,654},{85,118,446},{88,127,2198},{78,127,450},{78,119,4},{74,110,654},{57,127,1557},{60,111,453},{97,127,741},{93,127,57},{93,120,41},{90,117,77},{127,62,1514},{76,127,446},{78,119,3},{51,112,421},{127,95,1514},{51,112,421},{86,127,554},{86,127,554},{86,127,554},{85,115,421},{80,127,435},{78,119,3},{78,119,3},{76,103,41},{59,118,339},{64,105,1},{93,126,8},
+{93,126,8},{93,126,8},{92,111,0},{127,40,338},{80,117,0},{80,117,0},{65,105,0},{126,85,338},{65,105,0},{127,81,421},{96,127,29},{98,119,1},{76,119,1},{127,81,421},{126,105,421},{76,119,1},{0,112,421},{126,105,421},{0,112,421},{85,0,421},{85,0,421},{85,0,421},{85,0,421},{78,120,1},{78,120,1},{78,120,1},{77,99,1},{64,105,1},{64,105,1},{97,127,2070},{92,127,882},{90,126,654},
+{89,122,446},{91,127,2382},{84,127,546},{82,123,4},{78,114,654},{64,127,1658},{62,116,453},{103,127,837},{99,127,161},{97,124,41},{94,121,77},{127,73,1514},{84,127,521},{82,123,3},{55,116,421},{127,101,1514},{55,116,421},{91,127,605},{91,127,605},{91,127,605},{89,119,421},{85,127,485},{82,123,3},{82,123,3},{80,107,41},{63,122,339},{68,109,1},{97,127,20},{97,127,20},{97,127,20},{96,115,0},{127,53,338},
+{84,121,0},{84,121,0},{69,109,0},{126,91,338},{69,109,0},{127,93,421},{102,127,85},{102,123,1},{80,123,1},{127,93,421},{126,111,421},{80,123,1},{0,116,421},{126,111,421},{0,116,421},{89,0,421},{89,0,421},{89,0,421},{89,0,421},{82,124,1},{82,124,1},{82,124,1},{81,103,1},{68,109,1},{68,109,1},{100,127,2201},{96,127,1101},{95,127,686},{93,126,441},{97,127,2469},{87,127,689},{86,127,3},
+{84,117,617},{73,127,1735},{67,120,421},{109,127,916},{104,127,298},{102,127,52},{98,125,68},{127,86,1459},{93,127,584},{86,127,2},{59,120,392},{127,107,1459},{59,120,392},{95,127,686},{95,127,686},{95,127,686},{93,123,421},{91,127,557},{86,127,3},{86,127,3},{84,111,41},{66,126,338},{72,113,1},{102,126,52},{102,126,52},{102,126,52},{100,119,0},{127,64,338},{88,125,0},{88,125,0},{73,113,0},{126,97,338},
+{73,113,0},{127,105,392},{110,127,146},{106,127,0},{84,127,0},{127,105,392},{126,117,392},{84,127,0},{0,120,392},{126,117,392},{0,120,392},{93,0,421},{93,0,421},{93,0,421},{93,0,421},{86,127,2},{86,127,2},{86,127,2},{85,107,1},{72,113,1},{72,113,1},{103,127,1901},{101,127,1079},{100,127,761},{97,127,421},{100,127,2093},{93,127,537},{91,127,29},{87,120,357},{81,127,1425},{72,122,213},{111,127,638},
+{108,127,244},{106,127,80},{103,126,17},{127,93,1064},{99,127,392},{93,127,4},{67,122,200},{126,111,1064},{67,122,200},{100,127,761},{100,127,761},{100,127,761},{97,127,421},{95,127,659},{91,127,29},{91,127,29},{88,115,41},{73,127,350},{76,117,1},{106,127,80},{106,127,80},{106,127,80},{104,123,0},{127,76,338},{93,127,4},{93,127,4},{77,117,0},{126,103,338},{77,117,0},{127,111,200},{116,127,74},{112,127,0},
+{96,127,0},{127,111,200},{126,120,200},{96,127,0},{0,122,200},{126,120,200},{0,122,200},{97,0,421},{97,0,421},{97,0,421},{97,0,421},{91,127,13},{91,127,13},{91,127,13},{89,111,1},{76,117,1},{76,117,1},{109,127,1646},{106,127,1086},{104,127,881},{102,127,450},{106,127,1730},{99,127,474},{96,127,122},{93,123,158},{87,127,1166},{79,124,62},{114,127,446},{111,127,225},{111,127,125},{108,127,2},{127,102,722},
+{105,127,254},{102,127,34},{76,124,61},{127,115,722},{76,124,61},{104,127,881},{104,127,881},{104,127,881},{102,127,450},{100,127,770},{96,127,122},{96,127,122},{93,120,38},{81,127,426},{81,121,2},{111,127,125},{111,127,125},{111,127,125},{108,127,2},{127,90,338},{102,127,34},{102,127,34},{83,121,1},{127,109,338},{83,121,1},{127,118,61},{119,127,25},{119,127,0},{110,127,0},{127,118,61},{126,123,61},{110,127,0},
+{0,124,61},{126,123,61},{0,124,61},{101,0,421},{101,0,421},{101,0,421},{101,0,421},{95,127,40},{95,127,40},{95,127,40},{94,115,1},{81,121,1},{81,121,1},{111,127,1450},{111,127,1109},{109,127,974},{105,127,542},{111,127,1505},{102,127,514},{102,127,258},{98,125,66},{96,127,1026},{84,126,6},{120,127,342},{117,127,230},{117,127,181},{113,127,37},{127,110,509},{111,127,213},{108,127,90},{85,126,5},{126,119,509},
+{85,126,5},{109,127,974},{109,127,974},{109,127,974},{105,127,542},{106,127,882},{102,127,258},{102,127,258},{97,124,38},{90,127,530},{85,125,2},{117,127,181},{117,127,181},{117,127,181},{113,127,37},{127,102,338},{108,127,90},{108,127,90},{87,125,1},{127,115,338},{87,125,1},{127,124,5},{125,127,1},{125,127,0},{122,127,0},{127,124,5},{126,126,5},{122,127,0},{0,126,5},{126,126,5},{0,126,5},{105,0,421},
+{105,0,421},{105,0,421},{105,0,421},{100,127,65},{100,127,65},{100,127,65},{98,119,1},{85,125,1},{85,125,1},{114,127,1179},{114,127,971},{112,127,881},{111,127,545},{114,127,1170},{108,127,457},{107,127,305},{102,126,17},{102,127,793},{90,127,9},{121,127,209},{120,127,155},{120,127,130},{118,127,45},{127,116,294},{116,127,134},{113,127,85},{95,127,0},{126,122,294},{95,127,0},{112,127,881},{112,127,881},{112,127,881},
+{111,127,545},{111,127,765},{107,127,305},{107,127,305},{102,126,13},{96,127,465},{90,127,9},{120,127,130},{120,127,130},{120,127,130},{118,127,45},{127,110,221},{113,127,85},{113,127,85},{95,127,0},{126,119,221},{95,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{109,0,421},{109,0,421},{109,0,421},{109,0,421},{106,127,113},
+{106,127,113},{106,127,113},{102,123,1},{90,127,9},{90,127,9},{117,127,871},{117,127,751},{115,127,701},{113,127,502},{117,127,822},{111,127,364},{111,127,264},{106,127,1},{105,127,537},{99,127,41},{123,127,75},{123,127,59},{123,127,50},{121,127,17},{127,121,113},{119,127,54},{119,127,29},{107,127,0},{127,124,113},{107,127,0},{115,127,701},{115,127,701},{115,127,701},{113,127,502},{114,127,561},{111,127,264},{111,127,264},
+{106,127,1},{102,127,329},{99,127,41},{123,127,50},{123,127,50},{123,127,50},{121,127,17},{127,116,85},{119,127,29},{119,127,29},{107,127,0},{126,122,85},{107,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{113,0,421},{113,0,421},{113,0,421},{113,0,421},{109,127,157},{109,127,157},{109,127,157},{106,127,1},{99,127,41},
+{99,127,41},{0,59,882},{0,40,100},{0,30,4},{0,24,340},{0,39,1896},{0,25,1188},{0,23,590},{0,15,1444},{0,19,2040},{0,15,1544},{0,59,882},{0,40,100},{0,30,4},{0,24,340},{19,0,1896},{0,25,1188},{0,23,590},{0,15,1444},{39,0,1896},{0,15,1444},{0,27,0},{0,27,0},{0,27,0},{0,13,1},{0,13,162},{0,11,58},{0,11,58},{0,7,97},{0,5,179},{0,6,116},{0,27,0},
+{0,27,0},{0,27,0},{0,13,1},{7,0,162},{0,11,58},{0,11,58},{0,7,97},{13,0,162},{0,7,97},{29,0,882},{0,40,100},{0,30,4},{0,24,340},{29,0,882},{59,0,882},{0,24,340},{0,19,884},{59,0,882},{0,19,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,71,882},{0,49,40},{1,34,12},
+{0,30,260},{0,47,2355},{0,31,1332},{0,28,612},{0,18,1700},{0,22,2556},{0,18,1844},{0,71,882},{0,49,40},{1,34,8},{0,30,260},{23,0,2355},{0,31,1332},{0,28,612},{0,18,1700},{47,0,2355},{0,18,1700},{0,39,0},{0,39,0},{0,39,0},{0,19,0},{0,20,338},{0,14,130},{0,14,130},{0,10,205},{0,8,371},{0,9,244},{0,39,0},{0,39,0},{0,39,0},{0,19,0},{10,0,338},
+{0,14,130},{0,14,130},{0,10,205},{20,0,338},{0,10,205},{35,0,882},{0,49,40},{3,34,0},{0,30,260},{35,0,882},{71,0,882},{0,30,260},{0,23,884},{71,0,882},{0,23,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,83,882},{0,55,8},{1,40,60},{0,33,200},{0,56,2899},{0,37,1508},{0,31,660},
+{0,21,2004},{0,25,3176},{0,21,2200},{0,83,882},{0,55,8},{2,38,52},{0,33,200},{27,1,2899},{0,37,1508},{0,31,660},{0,21,2004},{56,0,2899},{0,21,2004},{0,52,0},{0,52,0},{0,52,0},{0,25,0},{0,26,578},{0,19,208},{0,19,208},{0,13,353},{0,11,635},{0,10,414},{0,52,0},{0,52,0},{0,52,0},{0,25,0},{13,0,578},{0,19,208},{0,19,208},{0,13,353},{26,0,578},
+{0,13,353},{41,0,882},{0,55,8},{7,38,0},{0,33,200},{41,0,882},{83,0,882},{0,33,200},{0,27,884},{83,0,882},{0,27,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,91,902},{1,62,20},{3,44,133},{0,39,172},{0,66,3048},{0,43,1416},{0,37,488},{0,27,1944},{0,31,3460},{0,26,2254},{3,89,882},
+{3,60,2},{5,44,68},{2,38,168},{33,0,3048},{0,43,1416},{0,37,488},{0,27,1944},{66,0,3048},{0,27,1944},{2,60,20},{2,60,20},{2,60,20},{2,30,20},{0,36,648},{0,28,160},{0,28,160},{0,15,340},{0,17,771},{0,15,440},{3,58,0},{3,58,0},{3,58,0},{3,30,0},{18,0,648},{0,28,160},{0,28,160},{0,15,340},{36,0,648},{0,15,340},{47,0,882},{1,62,0},{11,42,0},
+{0,39,136},{47,0,882},{95,0,882},{0,39,136},{0,31,884},{95,0,882},{0,31,884},{1,0,20},{1,0,20},{1,0,20},{1,0,20},{0,9,0},{0,9,0},{0,9,0},{0,4,1},{0,3,8},{0,3,8},{4,101,995},{4,67,114},{6,48,283},{3,44,242},{0,80,3048},{0,51,1224},{0,43,267},{0,32,1794},{0,37,3651},{0,30,2195},{8,93,883},{7,65,2},{9,48,67},{6,42,171},{39,1,3048},
+{0,51,1224},{0,43,267},{0,32,1794},{80,0,3048},{0,32,1794},{4,69,113},{4,69,113},{4,69,113},{4,36,113},{0,50,648},{0,34,74},{0,34,74},{0,21,250},{0,22,862},{0,19,434},{8,61,1},{8,61,1},{8,61,1},{8,34,1},{24,1,648},{0,34,74},{0,34,74},{0,21,250},{50,0,648},{0,21,250},{53,1,882},{6,65,1},{15,47,1},{0,44,89},{53,1,882},{109,0,882},{0,44,89},
+{0,36,882},{109,0,882},{0,36,882},{4,0,113},{4,0,113},{4,0,113},{4,0,113},{0,23,0},{0,23,0},{0,23,0},{0,11,0},{0,8,41},{0,8,41},{6,109,1147},{6,72,274},{8,53,499},{5,47,367},{0,92,3048},{0,57,1096},{0,47,129},{0,36,1635},{0,43,3859},{0,34,2183},{12,97,883},{11,69,2},{13,52,67},{10,46,171},{45,1,3048},{0,57,1096},{0,47,129},{0,36,1635},{92,0,3048},
+{0,36,1635},{6,77,265},{6,77,265},{6,77,265},{6,41,265},{0,62,648},{0,43,26},{0,43,26},{0,26,193},{0,28,990},{0,23,458},{12,65,1},{12,65,1},{12,65,1},{12,38,1},{30,1,648},{0,43,26},{0,43,26},{0,26,193},{62,0,648},{0,26,193},{59,1,882},{10,69,1},{19,51,1},{0,49,58},{59,1,882},{121,0,882},{0,49,58},{0,40,882},{121,0,882},{0,40,882},{6,0,265},
+{6,0,265},{6,0,265},{6,0,265},{0,35,0},{0,35,0},{0,35,0},{0,17,0},{0,14,97},{0,14,97},{8,117,1363},{8,77,506},{10,58,795},{7,52,559},{0,104,3048},{0,63,1000},{0,53,41},{0,39,1523},{0,46,4095},{0,38,2195},{16,101,883},{15,73,2},{17,56,67},{14,50,171},{51,0,3048},{0,63,1000},{0,53,41},{0,39,1523},{104,0,3048},{0,39,1523},{8,85,481},{8,85,481},{8,85,481},
+{8,46,481},{0,74,648},{0,49,2},{0,49,2},{0,30,130},{0,31,1146},{0,28,494},{16,69,1},{16,69,1},{16,69,1},{16,42,1},{36,1,648},{0,49,2},{0,49,2},{0,30,130},{74,0,648},{0,30,130},{65,0,882},{14,73,1},{23,55,1},{0,53,25},{65,0,882},{127,3,882},{0,53,25},{0,44,882},{127,3,882},{0,44,882},{8,0,481},{8,0,481},{8,0,481},{8,0,481},{0,47,0},
+{0,47,0},{0,47,0},{0,23,0},{0,19,169},{0,19,169},{10,125,1643},{11,83,802},{13,61,1159},{9,56,826},{0,117,3048},{0,70,933},{0,58,11},{0,45,1395},{0,54,4321},{0,43,2227},{20,105,883},{19,77,2},{21,60,67},{18,54,171},{57,0,3048},{0,70,933},{0,58,11},{0,45,1395},{117,0,3048},{0,45,1395},{10,93,761},{10,93,761},{10,93,761},{10,51,761},{0,86,648},{0,56,4},{0,56,4},
+{0,35,89},{0,37,1322},{0,31,578},{20,73,1},{20,73,1},{20,73,1},{20,46,1},{42,1,648},{3,54,0},{3,54,0},{0,35,89},{86,0,648},{0,35,89},{71,0,882},{18,77,1},{27,59,1},{0,58,10},{71,0,882},{127,9,882},{0,58,10},{0,48,882},{127,9,882},{0,48,882},{10,0,761},{10,0,761},{10,0,761},{10,0,761},{0,59,0},{0,59,0},{0,59,0},{0,29,0},{0,22,277},
+{0,22,277},{14,126,1784},{14,89,929},{17,65,1329},{13,60,945},{3,124,3048},{2,75,910},{3,62,14},{0,50,1329},{0,60,4212},{0,47,1974},{24,110,882},{24,80,5},{27,64,70},{23,59,168},{63,2,3048},{0,77,893},{4,63,10},{0,50,1293},{126,2,3048},{0,50,1293},{14,99,884},{14,99,884},{14,99,884},{13,56,884},{3,94,648},{3,62,10},{3,62,10},{1,40,68},{0,46,1256},{0,37,428},{24,78,0},
+{24,78,0},{24,78,0},{24,51,0},{49,0,648},{7,59,0},{7,59,0},{0,39,52},{100,0,648},{0,39,52},{78,0,882},{23,81,1},{32,63,0},{0,63,1},{78,0,882},{126,16,882},{0,63,1},{0,52,884},{126,16,882},{0,52,884},{13,0,884},{13,0,884},{13,0,884},{13,0,884},{3,66,0},{3,66,0},{3,66,0},{3,34,0},{0,31,232},{0,31,232},{19,126,1814},{18,93,929},{21,69,1329},
+{17,65,942},{7,127,3051},{6,79,910},{7,66,14},{4,54,1329},{0,67,3975},{0,52,1640},{28,114,882},{28,84,5},{30,67,66},{27,63,168},{69,1,3048},{1,83,882},{9,66,10},{0,53,1205},{126,8,3048},{0,53,1205},{18,103,884},{18,103,884},{18,103,884},{17,60,884},{7,98,648},{8,65,9},{8,65,9},{5,44,68},{0,51,1059},{0,43,236},{28,82,0},{28,82,0},{28,82,0},{28,55,0},{55,0,648},
+{11,63,0},{11,63,0},{0,45,20},{112,0,648},{0,45,20},{83,1,882},{27,85,1},{36,66,1},{4,66,1},{83,1,882},{126,22,882},{4,66,1},{0,56,884},{126,22,882},{0,56,884},{17,0,884},{17,0,884},{17,0,884},{17,0,884},{7,70,0},{7,70,0},{7,70,0},{7,38,0},{0,37,136},{0,37,136},{23,127,1854},{22,97,929},{25,73,1329},{21,69,942},{12,127,3064},{10,83,910},{11,70,14},
+{8,58,1329},{0,73,3751},{0,57,1374},{32,118,882},{32,88,5},{34,71,66},{30,67,165},{75,1,3048},{5,87,882},{13,70,10},{0,59,1125},{126,14,3048},{0,59,1125},{22,107,884},{22,107,884},{22,107,884},{21,64,884},{11,102,648},{12,69,9},{12,69,9},{9,48,68},{0,57,923},{0,49,108},{32,86,0},{32,86,0},{32,86,0},{32,59,0},{61,0,648},{16,65,1},{16,65,1},{0,49,8},{124,0,648},
+{0,49,8},{89,1,882},{31,89,1},{40,70,1},{8,70,1},{89,1,882},{126,28,882},{8,70,1},{0,60,884},{126,28,882},{0,60,884},{21,0,884},{21,0,884},{21,0,884},{21,0,884},{11,74,0},{11,74,0},{11,74,0},{11,42,0},{0,46,68},{0,46,68},{29,127,1934},{26,101,929},{29,77,1329},{25,73,942},{17,127,3091},{14,87,910},{15,74,14},{12,62,1329},{0,79,3559},{0,62,1174},{36,122,882},
+{36,92,5},{38,75,66},{34,71,165},{81,0,3048},{9,91,882},{17,74,10},{0,62,1053},{126,20,3048},{0,62,1053},{26,111,884},{26,111,884},{26,111,884},{26,67,884},{15,106,648},{16,73,9},{16,73,9},{13,52,68},{0,64,810},{0,54,26},{36,90,0},{36,90,0},{36,90,0},{36,63,0},{66,1,648},{20,69,1},{20,69,1},{0,54,1},{126,5,648},{0,54,1},{95,1,882},{35,93,1},{44,74,1},
+{12,74,1},{95,1,882},{126,34,882},{12,74,1},{0,64,882},{126,34,882},{0,64,882},{25,0,884},{25,0,884},{25,0,884},{25,0,884},{15,78,0},{15,78,0},{15,78,0},{15,46,0},{0,51,18},{0,51,18},{33,127,2036},{31,106,931},{33,81,1331},{29,77,942},{23,127,3145},{19,92,910},{19,79,14},{17,65,1329},{0,87,3375},{0,66,1021},{41,126,883},{40,98,2},{43,80,65},{39,76,166},{88,0,3048},
+{14,95,882},{21,78,9},{0,66,996},{127,26,3048},{0,66,996},{30,116,882},{30,116,882},{30,116,882},{30,72,882},{20,109,649},{20,77,10},{20,77,10},{18,57,67},{0,70,729},{1,59,3},{41,94,1},{41,94,1},{41,94,1},{40,67,1},{73,0,648},{24,74,1},{24,74,1},{4,58,1},{126,12,648},{4,58,1},{102,0,882},{39,98,1},{48,79,0},{15,79,0},{102,0,882},{126,41,882},{15,79,0},
+{0,68,884},{126,41,882},{0,68,884},{30,0,882},{30,0,882},{30,0,882},{30,0,882},{20,82,1},{20,82,1},{20,82,1},{19,51,1},{0,60,0},{0,60,0},{38,127,2134},{35,110,931},{37,85,1331},{33,81,942},{29,127,3217},{23,96,910},{23,83,14},{21,69,1329},{0,93,3247},{0,71,949},{45,127,891},{44,102,2},{47,84,65},{43,80,166},{94,0,3048},{18,99,882},{25,82,9},{0,72,948},{127,32,3048},
+{0,72,948},{34,120,882},{34,120,882},{34,120,882},{34,76,882},{24,113,649},{24,81,10},{24,81,10},{22,61,67},{0,79,673},{5,63,3},{45,98,1},{45,98,1},{45,98,1},{44,71,1},{79,0,648},{28,78,1},{28,78,1},{8,62,1},{127,17,648},{8,62,1},{108,0,882},{43,102,1},{52,83,0},{19,83,0},{108,0,882},{125,47,882},{19,83,0},{0,72,884},{125,47,882},{0,72,884},{34,0,882},
+{34,0,882},{34,0,882},{34,0,882},{24,86,1},{24,86,1},{24,86,1},{23,55,1},{3,64,1},{3,64,1},{42,127,2284},{39,114,931},{41,89,1331},{37,85,942},{33,127,3316},{27,100,910},{27,87,14},{25,73,1329},{0,99,3151},{1,76,929},{50,127,909},{48,106,2},{51,88,65},{47,84,166},{100,0,3048},{22,103,882},{29,86,9},{0,75,916},{127,38,3048},{0,75,916},{38,124,882},{38,124,882},{38,124,882},
+{38,80,882},{28,117,649},{28,85,10},{28,85,10},{27,64,66},{0,85,649},{8,66,5},{49,102,1},{49,102,1},{49,102,1},{48,75,1},{85,0,648},{32,82,1},{32,82,1},{11,66,0},{127,23,648},{11,66,0},{114,0,882},{47,106,1},{56,87,0},{23,87,0},{114,0,882},{127,52,882},{23,87,0},{0,76,884},{127,52,882},{0,76,884},{38,0,882},{38,0,882},{38,0,882},{38,0,882},{28,90,1},
+{28,90,1},{28,90,1},{27,59,1},{8,67,1},{8,67,1},{47,127,2414},{43,118,931},{45,93,1331},{41,89,942},{38,127,3409},{31,104,910},{31,91,14},{29,77,1329},{0,105,3087},{5,80,929},{55,127,939},{52,110,2},{55,92,65},{51,88,166},{106,0,3048},{26,107,882},{33,90,9},{0,80,893},{127,44,3048},{0,80,893},{42,127,883},{42,127,883},{42,127,883},{42,84,882},{32,121,649},{32,89,10},{32,89,10},
+{31,68,66},{4,89,649},{12,70,5},{53,106,1},{53,106,1},{53,106,1},{52,79,1},{91,0,648},{36,86,1},{36,86,1},{15,70,0},{127,29,648},{15,70,0},{120,0,882},{51,110,1},{60,91,0},{27,91,0},{120,0,882},{127,58,882},{27,91,0},{0,80,884},{127,58,882},{0,80,884},{42,0,882},{42,0,882},{42,0,882},{42,0,882},{32,94,1},{32,94,1},{32,94,1},{31,63,1},{12,71,1},
+{12,71,1},{52,127,2584},{47,122,929},{50,98,1329},{46,94,942},{44,127,3547},{35,108,910},{36,95,14},{34,82,1331},{0,112,3055},{9,84,931},{61,127,996},{57,113,5},{59,96,66},{55,92,165},{112,1,3048},{30,112,882},{38,95,10},{0,85,883},{126,51,3048},{0,85,883},{47,127,893},{47,127,893},{47,127,893},{47,88,884},{36,127,648},{37,94,9},{37,94,9},{35,72,65},{9,93,649},{17,75,2},{57,111,0},
+{57,111,0},{57,111,0},{57,83,0},{98,0,648},{41,90,1},{41,90,1},{21,74,1},{127,36,648},{21,74,1},{127,0,882},{56,114,1},{64,96,1},{33,95,1},{127,0,882},{126,65,882},{33,95,1},{0,85,882},{126,65,882},{0,85,882},{46,0,884},{46,0,884},{46,0,884},{46,0,884},{36,99,0},{36,99,0},{36,99,0},{36,67,0},{17,75,1},{17,75,1},{58,127,2792},{51,126,929},{54,102,1329},
+{50,98,942},{49,127,3672},{39,112,910},{40,99,14},{38,86,1331},{3,117,3049},{13,88,931},{65,127,1061},{61,117,5},{63,100,66},{59,96,165},{118,1,3048},{34,116,882},{42,99,10},{2,89,882},{126,57,3048},{2,89,882},{52,127,916},{52,127,916},{52,127,916},{51,92,884},{41,127,654},{41,98,9},{41,98,9},{39,76,65},{13,97,649},{21,79,2},{61,115,0},{61,115,0},{61,115,0},{61,87,0},{104,0,648},
+{45,94,1},{45,94,1},{25,78,1},{127,42,648},{25,78,1},{127,11,882},{60,118,1},{68,100,1},{37,99,1},{127,11,882},{126,71,882},{37,99,1},{0,89,882},{126,71,882},{0,89,882},{50,0,884},{50,0,884},{50,0,884},{50,0,884},{40,103,0},{40,103,0},{40,103,0},{40,71,0},{21,79,1},{21,79,1},{61,127,2984},{55,127,949},{58,106,1329},{54,102,942},{55,127,3832},{43,116,910},{44,103,14},
+{42,90,1331},{7,121,3049},{17,92,931},{71,127,1149},{64,122,3},{66,105,67},{63,100,165},{124,1,3048},{38,120,882},{46,103,10},{6,93,882},{126,63,3048},{6,93,882},{55,127,948},{55,127,948},{55,127,948},{55,96,884},{46,126,682},{45,102,9},{45,102,9},{43,80,65},{17,101,649},{25,83,2},{65,118,1},{65,118,1},{65,118,1},{65,91,1},{110,0,648},{49,98,1},{49,98,1},{29,82,1},{126,48,648},
+{29,82,1},{127,24,882},{63,123,1},{72,104,1},{41,103,1},{127,24,882},{125,77,882},{41,103,1},{0,93,882},{125,77,882},{0,93,882},{54,0,884},{54,0,884},{54,0,884},{54,0,884},{44,107,0},{44,107,0},{44,107,0},{44,75,0},{25,83,1},{25,83,1},{65,127,3214},{61,127,1021},{62,110,1329},{58,106,942},{61,127,4024},{47,120,910},{48,107,14},{46,94,1331},{11,125,3049},{21,96,931},{74,127,1245},
+{68,126,3},{70,109,67},{67,103,171},{127,7,3048},{42,124,882},{50,107,10},{10,97,882},{127,68,3048},{10,97,882},{61,127,996},{61,127,996},{61,127,996},{59,100,884},{50,127,714},{49,106,9},{49,106,9},{47,84,65},{21,105,649},{29,87,2},{69,122,1},{69,122,1},{69,122,1},{69,95,1},{115,1,648},{53,102,1},{53,102,1},{33,86,1},{126,54,648},{33,86,1},{127,36,882},{67,127,0},{76,108,1},
+{45,107,1},{127,36,882},{127,82,882},{45,107,1},{0,97,882},{127,82,882},{0,97,882},{58,0,884},{58,0,884},{58,0,884},{58,0,884},{48,111,0},{48,111,0},{48,111,0},{48,79,0},{29,87,1},{29,87,1},{71,127,3494},{65,127,1174},{66,114,1320},{62,110,942},{65,127,4231},{52,125,910},{52,112,14},{50,98,1329},{19,127,3067},{26,101,929},{79,127,1364},{73,127,26},{75,114,68},{72,108,168},{127,21,3048},
+{48,127,885},{54,111,9},{16,101,884},{127,75,3048},{16,101,884},{65,127,1053},{65,127,1053},{65,127,1053},{63,105,882},{56,127,769},{53,110,10},{53,110,10},{52,89,66},{25,110,649},{33,91,5},{73,126,1},{73,126,1},{73,126,1},{73,100,0},{122,0,648},{57,107,1},{57,107,1},{36,91,0},{126,61,648},{36,91,0},{127,50,882},{76,127,18},{81,112,0},{48,112,0},{127,50,882},{127,89,882},{48,112,0},
+{0,101,884},{127,89,882},{0,101,884},{63,0,882},{63,0,882},{63,0,882},{63,0,882},{53,115,1},{53,115,1},{53,115,1},{53,83,1},{33,92,1},{33,92,1},{74,127,3782},{70,127,1374},{70,118,1320},{66,113,945},{71,127,4455},{57,127,926},{56,116,14},{54,102,1329},{25,127,3139},{30,105,929},{85,127,1476},{79,127,97},{79,118,68},{76,112,168},{127,33,3048},{57,127,925},{58,115,9},{20,105,884},{126,81,3048},
+{20,105,884},{68,127,1125},{68,127,1125},{68,127,1125},{66,109,884},{61,127,827},{57,114,10},{57,114,10},{56,93,66},{29,114,649},{37,95,5},{78,126,8},{78,126,8},{78,126,8},{77,104,0},{127,2,648},{61,111,1},{61,111,1},{40,95,0},{127,66,648},{40,95,0},{127,62,882},{81,127,68},{85,116,0},{52,116,0},{127,62,882},{127,95,882},{52,116,0},{0,105,884},{127,95,882},{0,105,884},{66,0,884},
+{66,0,884},{66,0,884},{66,0,884},{57,119,1},{57,119,1},{57,119,1},{57,87,1},{37,96,1},{37,96,1},{79,127,4024},{75,127,1640},{74,122,1320},{70,117,945},{74,127,4699},{63,127,1030},{60,120,14},{58,106,1329},{34,127,3259},{34,109,929},{91,127,1620},{84,127,236},{83,122,68},{80,116,168},{127,45,3048},{64,127,1003},{62,119,9},{24,109,884},{126,87,3048},{24,109,884},{74,127,1205},{74,127,1205},{74,127,1205},
+{70,113,884},{65,127,910},{61,118,10},{61,118,10},{60,97,66},{33,118,649},{41,99,5},{82,127,20},{82,127,20},{82,127,20},{81,108,0},{127,14,648},{64,116,0},{64,116,0},{44,99,0},{127,72,648},{44,99,0},{127,73,882},{90,127,136},{89,120,0},{56,120,0},{127,73,882},{127,101,882},{56,120,0},{0,109,884},{127,101,882},{0,109,884},{70,0,884},{70,0,884},{70,0,884},{70,0,884},{61,123,1},
+{61,123,1},{61,123,1},{61,91,1},{41,100,1},{41,100,1},{85,127,4328},{79,127,1925},{78,126,1320},{74,121,945},{79,127,4920},{67,127,1215},{64,123,14},{62,110,1329},{43,127,3435},{38,113,929},{94,127,1784},{90,127,428},{87,126,68},{84,120,168},{127,57,3048},{70,127,1131},{65,124,10},{28,113,884},{126,93,3048},{28,113,884},{77,127,1293},{77,127,1293},{77,127,1293},{74,117,884},{71,127,1006},{64,123,10},{64,123,10},
+{63,100,70},{37,122,649},{45,103,5},{87,126,52},{87,126,52},{87,126,52},{85,112,0},{127,27,648},{68,120,0},{68,120,0},{48,103,0},{126,78,648},{48,103,0},{127,86,882},{96,127,232},{93,124,0},{60,124,0},{127,86,882},{127,107,882},{60,124,0},{0,113,884},{127,107,882},{0,113,884},{74,0,884},{74,0,884},{74,0,884},{74,0,884},{64,126,1},{64,126,1},{64,126,1},{64,95,0},{45,104,1},
+{45,104,1},{88,127,4403},{84,127,2227},{82,127,1395},{78,125,922},{85,127,4875},{73,127,1326},{69,127,11},{65,115,1174},{54,127,3438},{44,116,802},{100,127,1746},{95,127,578},{92,127,89},{88,124,126},{127,69,2814},{79,127,1146},{71,127,4},{33,117,761},{126,99,2814},{33,117,761},{82,127,1395},{82,127,1395},{82,127,1395},{79,121,883},{77,127,1137},{69,127,11},{69,127,11},{67,106,67},{42,126,649},{50,108,2},{92,127,89},
+{92,127,89},{92,127,89},{90,116,1},{127,40,648},{73,124,0},{73,124,0},{54,107,1},{126,85,648},{54,107,1},{127,96,761},{105,127,277},{98,127,0},{67,127,0},{127,96,761},{127,112,761},{67,127,0},{0,117,761},{127,112,761},{0,117,761},{79,0,882},{79,0,882},{79,0,882},{79,0,882},{69,127,10},{69,127,10},{69,127,10},{68,100,1},{50,108,1},{50,108,1},{94,127,3955},{89,127,2195},{88,127,1523},
+{83,127,886},{91,127,4323},{79,127,1139},{74,127,41},{71,116,799},{60,127,2958},{49,118,506},{103,127,1386},{99,127,494},{97,127,130},{92,125,50},{127,76,2249},{87,127,870},{78,127,2},{42,119,481},{126,103,2249},{42,119,481},{88,127,1523},{88,127,1523},{88,127,1523},{83,125,883},{82,127,1251},{74,127,41},{74,127,41},{71,110,67},{48,127,670},{54,112,2},{97,127,130},{97,127,130},{97,127,130},{94,120,1},{127,53,648},
+{78,127,2},{78,127,2},{58,111,1},{126,91,648},{58,111,1},{127,102,481},{108,127,169},{104,127,0},{79,127,0},{127,102,481},{127,115,481},{79,127,0},{0,119,481},{127,115,481},{0,119,481},{83,0,882},{83,0,882},{83,0,882},{83,0,882},{74,127,25},{74,127,25},{74,127,25},{72,104,1},{54,112,1},{54,112,1},{97,127,3571},{93,127,2183},{91,127,1635},{87,127,891},{94,127,3827},{84,127,1035},{79,127,114},
+{74,119,499},{67,127,2577},{55,121,274},{106,127,1098},{102,127,458},{101,127,193},{97,126,9},{127,86,1769},{93,127,654},{84,127,26},{50,121,265},{127,107,1769},{50,121,265},{91,127,1635},{91,127,1635},{91,127,1635},{87,127,891},{85,127,1387},{79,127,114},{79,127,114},{75,114,67},{57,127,734},{58,116,2},{101,127,193},{101,127,193},{101,127,193},{98,124,1},{127,64,648},{84,127,26},{84,127,26},{62,115,1},{126,97,648},
+{62,115,1},{127,108,265},{113,127,97},{110,127,0},{92,127,0},{127,108,265},{127,118,265},{92,127,0},{0,121,265},{127,118,265},{0,121,265},{87,0,882},{87,0,882},{87,0,882},{87,0,882},{79,127,50},{79,127,50},{79,127,50},{76,108,1},{58,116,1},{58,116,1},{100,127,3267},{97,127,2195},{95,127,1794},{92,127,954},{97,127,3435},{87,127,975},{84,127,267},{79,121,283},{73,127,2281},{60,123,114},{111,127,838},
+{107,127,434},{106,127,250},{102,127,2},{127,93,1374},{99,127,502},{93,127,74},{58,123,113},{126,111,1374},{58,123,113},{95,127,1794},{95,127,1794},{95,127,1794},{92,127,954},{91,127,1539},{84,127,267},{84,127,267},{79,118,67},{64,127,840},{62,120,2},{106,127,250},{106,127,250},{106,127,250},{102,127,2},{127,76,648},{93,127,74},{93,127,74},{65,119,1},{126,103,648},{65,119,1},{127,115,113},{119,127,41},{116,127,0},
+{104,127,0},{127,115,113},{127,121,113},{104,127,0},{0,123,113},{127,121,113},{0,123,113},{91,0,882},{91,0,882},{91,0,882},{91,0,882},{83,127,89},{83,127,89},{83,127,89},{80,112,1},{62,120,1},{62,120,1},{103,127,3032},{101,127,2254},{100,127,1944},{96,127,1080},{103,127,3096},{93,127,1012},{90,127,488},{83,124,133},{81,127,2104},{65,126,20},{114,127,666},{111,127,425},{111,127,325},{108,127,52},{127,102,1032},
+{105,127,404},{99,127,160},{67,125,20},{127,115,1032},{67,125,20},{100,127,1944},{100,127,1944},{100,127,1944},{96,127,1080},{97,127,1736},{90,127,488},{90,127,488},{83,122,68},{73,127,1011},{67,124,2},{111,127,325},{111,127,325},{111,127,325},{108,127,52},{127,90,648},{99,127,160},{99,127,160},{69,124,0},{127,109,648},{69,124,0},{127,122,18},{124,127,8},{122,127,1},{118,127,0},{127,122,18},{126,125,18},{118,127,0},
+{0,125,20},{126,125,18},{0,125,20},{95,0,884},{95,0,884},{95,0,884},{95,0,884},{88,127,136},{88,127,136},{88,127,136},{85,116,0},{65,126,0},{65,126,0},{109,127,2756},{106,127,2200},{103,127,2004},{102,127,1188},{106,127,2760},{96,127,1060},{96,127,660},{87,126,60},{87,127,1900},{72,127,8},{117,127,534},{117,127,414},{114,127,353},{111,127,104},{127,110,771},{108,127,352},{108,127,208},{75,127,0},{126,119,771},
+{75,127,0},{103,127,2004},{103,127,2004},{103,127,2004},{102,127,1188},{100,127,1784},{96,127,660},{96,127,660},{89,125,52},{81,127,1112},{72,127,8},{114,127,353},{114,127,353},{114,127,353},{111,127,104},{127,101,578},{108,127,208},{108,127,208},{75,127,0},{127,114,578},{75,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{99,0,884},
+{99,0,884},{99,0,884},{99,0,884},{94,127,200},{94,127,200},{94,127,200},{89,120,0},{72,127,8},{72,127,8},{111,127,2214},{109,127,1844},{109,127,1700},{105,127,1096},{109,127,2180},{102,127,900},{99,127,612},{93,126,12},{93,127,1468},{78,127,40},{120,127,306},{118,127,244},{117,127,205},{116,127,65},{127,113,451},{113,127,211},{111,127,125},{87,127,0},{127,120,451},{87,127,0},{109,127,1700},{109,127,1700},{109,127,1700},
+{105,127,1096},{103,127,1460},{99,127,612},{99,127,612},{93,126,8},{87,127,872},{78,127,40},{117,127,205},{117,127,205},{117,127,205},{116,127,65},{127,107,338},{111,127,125},{111,127,125},{87,127,0},{127,117,338},{87,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{103,0,884},{103,0,884},{103,0,884},{103,0,884},{97,127,260},
+{97,127,260},{97,127,260},{93,124,0},{78,127,40},{78,127,40},{114,127,1798},{111,127,1521},{111,127,1421},{108,127,1028},{111,127,1675},{105,127,792},{104,127,590},{97,127,4},{96,127,1128},{87,127,100},{123,127,150},{121,127,116},{120,127,97},{119,127,29},{127,118,216},{119,127,99},{116,127,58},{99,127,0},{126,123,216},{99,127,0},{111,127,1421},{111,127,1421},{111,127,1421},{108,127,1028},{109,127,1188},{104,127,590},{104,127,590},
+{97,127,4},{93,127,696},{87,127,100},{120,127,97},{120,127,97},{120,127,97},{119,127,29},{127,113,162},{116,127,58},{116,127,58},{99,127,0},{127,120,162},{99,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{107,0,884},{107,0,884},{107,0,884},{107,0,884},{103,127,340},{103,127,340},{103,127,340},{97,127,4},{87,127,100},
+{87,127,100},{0,78,1568},{0,54,170},{0,40,4},{0,33,596},{0,53,3371},{0,34,2124},{0,31,1048},{0,21,2552},{0,25,3628},{0,21,2748},{0,78,1568},{0,54,170},{0,40,4},{0,33,596},{26,0,3371},{0,34,2124},{0,31,1048},{0,21,2552},{53,0,3371},{0,21,2552},{0,36,0},{0,36,0},{0,36,0},{0,18,0},{0,18,288},{0,14,106},{0,14,106},{0,9,180},{0,8,315},{0,7,206},{0,36,0},
+{0,36,0},{0,36,0},{0,18,0},{9,0,288},{0,14,106},{0,14,106},{0,9,180},{18,0,288},{0,9,180},{39,0,1568},{0,54,170},{0,40,4},{0,33,596},{39,0,1568},{78,0,1568},{0,33,596},{0,26,1568},{78,0,1568},{0,26,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,91,1568},{0,63,90},{0,45,8},
+{0,39,500},{0,61,3968},{0,40,2316},{0,35,1078},{0,24,2880},{0,28,4304},{0,24,3136},{0,91,1568},{0,63,90},{1,44,8},{0,39,500},{30,0,3968},{0,40,2316},{0,35,1078},{0,24,2880},{61,0,3968},{0,24,2880},{0,48,0},{0,48,0},{0,48,0},{0,24,0},{0,24,512},{0,19,180},{0,19,180},{0,10,313},{0,11,563},{0,10,362},{0,48,0},{0,48,0},{0,48,0},{0,24,0},{12,0,512},
+{0,19,180},{0,19,180},{0,10,313},{24,0,512},{0,10,313},{45,0,1568},{0,63,90},{2,44,0},{0,39,500},{45,0,1568},{91,0,1568},{0,39,500},{0,30,1568},{91,0,1568},{0,30,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,103,1568},{0,70,37},{1,49,48},{0,42,400},{0,68,4651},{0,46,2540},{0,40,1128},
+{0,27,3256},{0,31,5084},{0,27,3580},{0,103,1568},{0,70,37},{1,49,44},{0,42,400},{33,1,4651},{0,46,2540},{0,40,1128},{0,27,3256},{68,0,4651},{0,27,3256},{0,61,0},{0,61,0},{0,61,0},{0,30,0},{0,30,800},{0,25,292},{0,25,292},{0,13,485},{0,14,883},{0,13,566},{0,61,0},{0,61,0},{0,61,0},{0,30,0},{15,0,800},{0,25,292},{0,25,292},{0,13,485},{30,0,800},
+{0,13,485},{50,1,1568},{0,70,37},{6,48,0},{0,42,400},{50,1,1568},{103,0,1568},{0,42,400},{0,34,1568},{103,0,1568},{0,34,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,115,1568},{0,76,5},{1,54,145},{0,47,325},{0,77,5419},{0,51,2755},{0,43,1208},{0,30,3680},{0,34,5968},{0,30,4080},{0,115,1568},
+{0,76,5},{3,53,121},{0,47,325},{38,0,5419},{0,51,2755},{0,43,1208},{0,30,3680},{77,0,5419},{0,30,3680},{0,72,0},{0,72,0},{0,72,0},{0,36,0},{0,36,1152},{0,28,424},{0,28,424},{0,18,720},{0,17,1275},{0,15,824},{0,72,0},{0,72,0},{0,72,0},{0,36,0},{18,0,1152},{0,28,424},{0,28,424},{0,18,720},{36,0,1152},{0,18,720},{56,1,1568},{0,76,5},{10,52,0},
+{0,47,325},{56,1,1568},{115,0,1568},{0,47,325},{0,38,1568},{115,0,1568},{0,38,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,125,1609},{2,82,42},{5,58,254},{1,51,318},{0,91,5419},{0,57,2480},{0,49,835},{0,36,3427},{0,40,6191},{0,35,3991},{5,119,1569},{4,80,6},{8,58,122},{2,52,302},{45,0,5419},
+{0,57,2480},{0,49,835},{0,36,3427},{91,0,5419},{0,36,3427},{2,82,41},{2,82,41},{2,82,41},{2,41,42},{0,50,1152},{0,37,274},{0,37,274},{0,21,586},{0,22,1366},{0,20,782},{5,76,1},{5,76,1},{5,76,1},{5,40,1},{24,1,1152},{0,37,274},{0,37,274},{0,21,586},{50,0,1152},{0,21,586},{63,0,1568},{2,82,1},{15,56,1},{0,53,245},{63,0,1568},{127,1,1568},{0,53,245},
+{0,42,1570},{127,1,1568},{0,42,1570},{2,0,41},{2,0,41},{2,0,41},{2,0,41},{0,13,0},{0,13,0},{0,13,0},{0,7,0},{0,5,13},{0,5,13},{5,126,1735},{4,87,150},{7,63,426},{3,56,382},{0,103,5419},{0,64,2265},{0,54,557},{0,39,3243},{0,46,6415},{0,39,3919},{9,123,1569},{8,84,6},{12,62,122},{6,56,302},{50,1,5419},{0,64,2265},{0,54,557},{0,39,3243},{103,0,5419},
+{0,39,3243},{4,90,145},{4,90,145},{4,90,145},{4,46,146},{0,62,1152},{0,43,170},{0,43,170},{0,27,482},{0,28,1494},{0,24,770},{9,80,1},{9,80,1},{9,80,1},{9,44,1},{30,1,1152},{0,43,170},{0,43,170},{0,27,482},{62,0,1152},{0,27,482},{69,0,1568},{6,86,1},{19,60,1},{0,56,181},{69,0,1568},{127,7,1568},{0,56,181},{0,46,1570},{127,7,1568},{0,46,1570},{4,0,145},
+{4,0,145},{4,0,145},{4,0,145},{0,26,0},{0,26,0},{0,26,0},{0,13,0},{0,11,53},{0,11,53},{9,127,1991},{7,93,322},{9,66,678},{5,61,518},{0,115,5419},{0,70,2081},{0,60,341},{0,45,3035},{0,51,6641},{0,42,3891},{13,127,1569},{12,88,6},{15,66,122},{10,60,302},{56,1,5419},{0,70,2081},{0,60,341},{0,45,3035},{115,0,5419},{0,45,3035},{6,98,313},{6,98,313},{6,98,313},
+{6,51,314},{0,74,1152},{0,51,80},{0,51,80},{0,30,394},{0,31,1650},{0,28,782},{13,84,1},{13,84,1},{13,84,1},{13,48,1},{36,1,1152},{0,51,80},{0,51,80},{0,30,394},{74,0,1152},{0,30,394},{75,0,1568},{10,90,1},{23,64,0},{0,62,125},{75,0,1568},{127,13,1568},{0,62,125},{0,50,1570},{127,13,1568},{0,50,1570},{6,0,313},{6,0,313},{6,0,313},{6,0,313},{0,38,0},
+{0,38,0},{0,38,0},{0,18,1},{0,14,117},{0,14,117},{12,127,2387},{9,98,566},{11,71,1002},{7,64,721},{0,127,5419},{0,76,1929},{0,64,181},{0,50,2886},{0,57,6921},{0,47,3879},{17,127,1577},{16,92,6},{19,70,122},{13,64,309},{62,1,5419},{0,76,1929},{0,64,181},{0,50,2886},{127,0,5419},{0,50,2886},{8,106,545},{8,106,545},{8,106,545},{8,56,545},{0,86,1152},{0,57,32},{0,57,32},
+{0,36,306},{0,37,1826},{0,34,822},{17,88,1},{17,88,1},{17,88,1},{17,52,1},{42,1,1152},{0,57,32},{0,57,32},{0,36,306},{86,0,1152},{0,36,306},{80,1,1568},{14,94,1},{27,68,0},{0,66,80},{80,1,1568},{126,19,1568},{0,66,80},{0,54,1570},{126,19,1568},{0,54,1570},{8,0,545},{8,0,545},{8,0,545},{8,0,545},{0,50,0},{0,50,0},{0,50,0},{0,24,1},{0,19,193},
+{0,19,193},{15,127,3004},{11,106,925},{14,77,1461},{9,69,1030},{3,127,5520},{0,84,1769},{0,70,66},{0,53,2697},{0,63,7276},{0,51,3898},{23,127,1602},{21,97,5},{23,74,125},{19,67,306},{69,0,5419},{0,84,1769},{0,70,66},{0,53,2697},{127,7,5419},{0,53,2697},{11,114,884},{11,114,884},{11,114,884},{10,62,884},{0,100,1152},{0,65,5},{0,65,5},{0,42,232},{0,43,2064},{0,37,896},{21,93,0},
+{21,93,0},{21,93,0},{21,57,0},{49,0,1152},{0,65,5},{0,65,5},{0,42,232},{100,0,1152},{0,42,232},{87,0,1568},{19,98,1},{31,73,1},{0,71,45},{87,0,1568},{126,26,1568},{0,71,45},{0,59,1568},{126,26,1568},{0,59,1568},{10,0,884},{10,0,884},{10,0,884},{10,0,884},{0,64,0},{0,64,0},{0,64,0},{0,31,0},{0,25,320},{0,25,320},{17,127,3702},{13,111,1317},{17,80,1945},
+{11,74,1374},{6,127,5788},{0,90,1681},{0,75,18},{0,59,2537},{0,70,7631},{0,55,3952},{29,127,1650},{25,101,5},{27,78,125},{23,71,306},{75,0,5419},{0,90,1681},{0,75,18},{0,59,2537},{127,13,5419},{0,59,2537},{13,122,1252},{13,122,1252},{13,122,1252},{13,66,1252},{0,112,1152},{0,72,5},{0,72,5},{0,45,164},{0,51,2291},{0,43,992},{25,97,0},{25,97,0},{25,97,0},{25,61,0},{55,0,1152},
+{3,70,1},{3,70,1},{0,45,164},{112,0,1152},{0,45,164},{93,0,1568},{23,102,1},{35,77,1},{0,75,18},{93,0,1568},{126,32,1568},{0,75,18},{0,63,1568},{126,32,1568},{0,63,1568},{12,0,1252},{12,0,1252},{12,0,1252},{12,0,1252},{0,75,0},{0,75,0},{0,75,0},{0,37,0},{0,31,464},{0,31,464},{23,127,4370},{16,114,1661},{19,85,2353},{14,77,1674},{12,127,6128},{0,99,1621},{2,80,18},
+{0,62,2397},{0,73,7815},{0,60,3858},{32,127,1702},{29,105,5},{31,82,125},{27,75,306},{80,1,5419},{0,99,1617},{2,80,14},{0,62,2393},{126,19,5419},{0,62,2393},{15,127,1572},{15,127,1572},{15,127,1572},{15,71,1568},{1,122,1152},{1,79,17},{1,79,17},{0,50,121},{0,54,2403},{0,46,996},{29,101,0},{29,101,0},{29,101,0},{29,64,0},{61,0,1152},{7,74,1},{7,74,1},{0,50,117},{124,0,1152},
+{0,50,117},{99,0,1568},{27,106,1},{39,81,1},{0,80,5},{99,0,1568},{126,38,1568},{0,80,5},{0,66,1570},{126,38,1568},{0,66,1570},{15,0,1568},{15,0,1568},{15,0,1568},{15,0,1568},{1,86,0},{1,86,0},{1,86,0},{1,43,0},{0,34,544},{0,34,544},{26,127,4586},{20,118,1661},{23,89,2353},{18,81,1674},{17,127,6275},{3,102,1617},{6,84,18},{1,67,2355},{0,81,7401},{0,64,3371},{38,127,1766},
+{33,109,5},{35,86,125},{31,79,306},{86,1,5419},{0,105,1577},{6,84,14},{0,66,2259},{126,25,5419},{0,66,2259},{20,127,1585},{20,127,1585},{20,127,1585},{19,75,1568},{5,126,1152},{5,83,17},{5,83,17},{4,54,121},{0,60,2155},{0,51,682},{33,105,0},{33,105,0},{33,105,0},{33,68,0},{66,1,1152},{11,78,1},{11,78,1},{0,55,80},{126,5,1152},{0,55,80},{105,0,1568},{31,110,1},{43,85,1},
+{0,84,1},{105,0,1568},{126,44,1568},{0,84,1},{0,70,1570},{126,44,1568},{0,70,1570},{19,0,1568},{19,0,1568},{19,0,1568},{19,0,1568},{5,90,0},{5,90,0},{5,90,0},{5,47,0},{0,43,388},{0,43,388},{32,127,4866},{25,123,1659},{27,93,2355},{23,86,1670},{23,127,6489},{8,107,1615},{10,88,18},{5,71,2353},{0,87,7039},{0,70,2897},{44,127,1865},{37,113,6},{40,91,122},{36,84,305},{93,0,5419},
+{2,111,1569},{10,88,17},{0,72,2124},{126,32,5419},{0,72,2124},{24,127,1619},{24,127,1619},{24,127,1619},{24,79,1570},{10,127,1161},{10,88,14},{10,88,14},{8,58,122},{0,67,1905},{0,57,409},{38,109,1},{38,109,1},{38,109,1},{37,73,1},{73,0,1152},{15,83,1},{15,83,1},{0,59,41},{126,12,1152},{0,59,41},{112,0,1568},{35,115,1},{48,89,0},{4,89,0},{112,0,1568},{127,50,1568},{4,89,0},
+{0,75,1568},{127,50,1568},{0,75,1568},{23,0,1570},{23,0,1570},{23,0,1570},{23,0,1570},{10,93,1},{10,93,1},{10,93,1},{10,51,1},{0,51,232},{0,51,232},{35,127,5154},{29,127,1659},{31,97,2355},{27,90,1670},{26,127,6689},{12,111,1615},{14,92,18},{9,75,2353},{0,93,6751},{0,74,2541},{49,127,1955},{41,117,6},{44,95,122},{40,88,305},{99,0,5419},{6,115,1569},{14,92,17},{0,75,2020},{126,38,5419},
+{0,75,2020},{29,127,1650},{29,127,1650},{29,127,1650},{28,83,1570},{15,127,1179},{14,92,14},{14,92,14},{12,62,122},{0,76,1713},{0,63,225},{42,113,1},{42,113,1},{42,113,1},{41,77,1},{79,0,1152},{19,87,1},{19,87,1},{0,64,20},{127,17,1152},{0,64,20},{118,0,1568},{39,119,1},{52,93,0},{8,93,0},{118,0,1568},{127,56,1568},{8,93,0},{0,79,1568},{127,56,1568},{0,79,1568},{27,0,1570},
+{27,0,1570},{27,0,1570},{27,0,1570},{14,97,1},{14,97,1},{14,97,1},{14,55,1},{0,57,136},{0,57,136},{41,127,5426},{33,127,1711},{35,101,2355},{31,94,1670},{32,127,6905},{16,115,1615},{18,96,18},{13,79,2353},{0,102,6483},{0,79,2241},{52,127,2075},{45,121,6},{48,99,122},{44,92,305},{105,0,5419},{10,119,1569},{18,96,17},{0,80,1929},{126,44,5419},{0,80,1929},{33,127,1707},{33,127,1707},{33,127,1707},
+{32,87,1570},{20,127,1209},{18,96,14},{18,96,14},{15,66,125},{0,81,1526},{0,67,97},{46,117,1},{46,117,1},{46,117,1},{45,81,1},{85,0,1152},{23,91,1},{23,91,1},{0,69,4},{127,23,1152},{0,69,4},{124,0,1568},{43,123,1},{56,97,0},{12,97,0},{124,0,1568},{127,62,1568},{12,97,0},{0,83,1568},{127,62,1568},{0,83,1568},{31,0,1570},{31,0,1570},{31,0,1570},{31,0,1570},{18,101,1},
+{18,101,1},{18,101,1},{18,59,1},{0,64,65},{0,64,65},{44,127,5762},{38,127,1811},{39,105,2355},{35,98,1670},{38,127,7153},{20,119,1615},{22,100,18},{17,83,2353},{0,108,6243},{0,83,2009},{58,127,2195},{49,125,6},{52,103,122},{48,96,305},{111,0,5419},{14,123,1569},{22,100,17},{0,85,1856},{127,49,5419},{0,85,1856},{38,127,1762},{38,127,1762},{38,127,1762},{36,91,1570},{26,127,1265},{22,100,14},{22,100,14},
+{19,70,125},{0,87,1398},{0,73,25},{50,121,1},{50,121,1},{50,121,1},{49,85,1},{91,0,1152},{27,95,1},{27,95,1},{0,73,0},{127,29,1152},{0,73,0},{127,5,1568},{47,127,1},{60,101,0},{16,101,0},{127,5,1568},{126,68,1568},{16,101,0},{0,87,1568},{126,68,1568},{0,87,1568},{35,0,1570},{35,0,1570},{35,0,1570},{35,0,1570},{22,105,1},{22,105,1},{22,105,1},{22,63,1},{0,70,25},
+{0,70,25},{52,127,6088},{43,127,2009},{44,110,2353},{39,102,1674},{44,127,7451},{24,123,1617},{27,105,18},{22,88,2355},{0,113,5999},{0,89,1811},{65,127,2385},{54,127,25},{56,107,125},{52,100,306},{118,0,5419},{19,127,1569},{27,105,14},{0,89,1762},{127,56,5419},{0,89,1762},{42,127,1856},{42,127,1856},{42,127,1856},{40,96,1568},{30,127,1344},{26,104,17},{26,104,17},{24,75,122},{0,96,1281},{1,78,6},{54,126,0},
+{54,126,0},{54,126,0},{54,89,0},{98,0,1152},{32,99,1},{32,99,1},{6,77,1},{127,36,1152},{6,77,1},{127,19,1568},{54,127,25},{64,105,1},{21,105,1},{127,19,1568},{127,74,1568},{21,105,1},{0,91,1570},{127,74,1568},{0,91,1570},{40,0,1568},{40,0,1568},{40,0,1568},{40,0,1568},{26,111,0},{26,111,0},{26,111,0},{26,67,0},{0,79,1},{0,79,1},{55,127,6416},{48,127,2241},{48,114,2353},
+{43,106,1674},{49,127,7696},{28,127,1617},{31,109,18},{26,92,2355},{0,122,5827},{0,94,1711},{68,127,2521},{60,127,97},{60,111,125},{56,104,306},{124,0,5419},{25,127,1601},{31,109,14},{0,94,1707},{127,62,5419},{0,94,1707},{47,127,1929},{47,127,1929},{47,127,1929},{44,100,1568},{35,127,1414},{30,108,17},{30,108,17},{28,79,122},{0,102,1209},{5,82,6},{58,127,4},{58,127,4},{58,127,4},{58,93,0},{104,0,1152},
+{36,103,1},{36,103,1},{10,81,1},{127,42,1152},{10,81,1},{127,31,1568},{63,127,65},{68,109,1},{25,109,1},{127,31,1568},{127,80,1568},{25,109,1},{0,95,1570},{127,80,1568},{0,95,1570},{44,0,1568},{44,0,1568},{44,0,1568},{44,0,1568},{30,115,0},{30,115,0},{30,115,0},{30,71,0},{4,83,1},{4,83,1},{61,127,6800},{53,127,2541},{52,118,2353},{47,110,1674},{52,127,7996},{34,127,1665},{35,113,18},
+{30,96,2355},{0,126,5709},{0,98,1659},{74,127,2705},{64,127,225},{65,115,122},{60,108,306},{127,5,5419},{34,127,1665},{35,113,14},{0,98,1650},{126,68,5419},{0,98,1650},{52,127,2020},{52,127,2020},{52,127,2020},{48,104,1568},{41,127,1510},{34,112,17},{34,112,17},{32,83,122},{0,108,1169},{9,86,6},{63,126,20},{63,126,20},{63,126,20},{62,97,0},{110,0,1152},{40,107,1},{40,107,1},{14,85,1},{126,48,1152},
+{14,85,1},{127,43,1568},{70,127,136},{72,113,1},{29,113,1},{127,43,1568},{127,86,1568},{29,113,1},{0,99,1570},{127,86,1568},{0,99,1570},{48,0,1568},{48,0,1568},{48,0,1568},{48,0,1568},{34,119,0},{34,119,0},{34,119,0},{34,75,0},{8,87,1},{8,87,1},{65,127,7186},{57,127,2897},{56,122,2353},{51,114,1674},{58,127,8300},{40,127,1809},{39,117,18},{34,100,2355},{5,127,5791},{4,102,1659},{79,127,2875},
+{70,127,409},{69,119,122},{63,114,310},{127,18,5419},{43,127,1777},{39,117,14},{0,103,1619},{126,74,5419},{0,103,1619},{55,127,2124},{55,127,2124},{55,127,2124},{52,108,1568},{44,127,1634},{38,116,17},{38,116,17},{36,87,122},{1,115,1153},{13,90,6},{68,127,41},{68,127,41},{68,127,41},{66,101,1},{115,1,1152},{44,111,1},{44,111,1},{18,89,1},{126,54,1152},{18,89,1},{127,56,1568},{76,127,232},{76,117,1},
+{33,117,1},{127,56,1568},{127,92,1568},{33,117,1},{0,103,1570},{127,92,1568},{0,103,1570},{52,0,1568},{52,0,1568},{52,0,1568},{52,0,1568},{38,123,0},{38,123,0},{38,123,0},{38,79,0},{12,91,1},{12,91,1},{68,127,7650},{63,127,3371},{60,126,2355},{56,119,1670},{65,127,8695},{46,127,2083},{43,121,18},{38,104,2353},{14,127,6049},{6,107,1661},{82,127,3112},{76,127,682},{73,123,121},{67,117,305},{127,31,5419},
+{51,127,1977},{43,121,17},{0,107,1585},{127,80,5419},{0,107,1585},{61,127,2259},{61,127,2259},{61,127,2259},{57,112,1570},{52,127,1755},{43,121,14},{43,121,14},{40,91,125},{6,119,1153},{18,94,5},{72,127,80},{72,127,80},{72,127,80},{70,106,0},{122,0,1152},{48,116,1},{48,116,1},{21,94,0},{126,61,1152},{21,94,0},{127,69,1568},{84,127,388},{80,122,0},{37,122,0},{127,69,1568},{126,99,1568},{37,122,0},
+{0,108,1568},{126,99,1568},{0,108,1568},{56,0,1570},{56,0,1570},{56,0,1570},{56,0,1570},{43,126,1},{43,126,1},{43,126,1},{42,84,1},{16,96,1},{16,96,1},{74,127,8066},{67,127,3858},{65,127,2397},{60,123,1670},{68,127,9035},{51,127,2458},{47,125,18},{42,108,2353},{22,127,6379},{10,111,1661},{88,127,3320},{79,127,977},{77,127,121},{71,121,305},{127,43,5419},{60,127,2185},{47,125,17},{0,112,1572},{127,86,5419},
+{0,112,1572},{65,127,2393},{65,127,2393},{65,127,2393},{61,116,1570},{55,127,1891},{47,125,14},{47,125,14},{44,95,125},{10,123,1153},{22,98,5},{77,127,117},{77,127,117},{77,127,117},{74,110,0},{127,2,1152},{52,120,1},{52,120,1},{25,98,0},{127,66,1152},{25,98,0},{127,81,1568},{93,127,544},{84,126,0},{41,126,0},{127,81,1568},{126,105,1568},{41,126,0},{0,112,1568},{126,105,1568},{0,112,1568},{60,0,1570},
+{60,0,1570},{60,0,1570},{60,0,1570},{47,127,5},{47,127,5},{47,127,5},{46,88,1},{20,100,1},{20,100,1},{79,127,7660},{72,127,3952},{68,127,2537},{64,125,1620},{74,127,8515},{57,127,2310},{52,127,18},{47,110,1945},{28,127,5939},{16,114,1317},{91,127,2984},{84,127,992},{82,127,164},{76,123,201},{127,53,4803},{64,127,1931},{54,126,5},{5,114,1252},{126,91,4803},{5,114,1252},{68,127,2537},{68,127,2537},{68,127,2537},
+{64,120,1569},{61,127,2043},{52,127,18},{52,127,18},{48,99,125},{14,127,1153},{26,102,5},{82,127,164},{82,127,164},{82,127,164},{78,114,0},{127,14,1152},{56,124,1},{56,124,1},{29,102,0},{127,72,1152},{29,102,0},{127,89,1250},{96,127,464},{90,127,0},{51,127,0},{127,89,1250},{125,109,1250},{51,127,0},{0,114,1252},{125,109,1250},{0,114,1252},{64,0,1568},{64,0,1568},{64,0,1568},{64,0,1568},{52,127,18},
+{52,127,18},{52,127,18},{50,92,1},{24,104,1},{24,104,1},{82,127,7060},{76,127,3898},{74,127,2697},{68,126,1576},{79,127,7756},{60,127,2062},{57,127,66},{50,113,1461},{37,127,5307},{21,116,925},{97,127,2504},{90,127,896},{85,127,232},{80,125,96},{127,60,4056},{70,127,1563},{60,127,5},{13,116,884},{127,94,4056},{13,116,884},{74,127,2697},{74,127,2697},{74,127,2697},{68,124,1569},{65,127,2214},{57,127,66},{57,127,66},
+{52,103,125},{22,127,1186},{30,106,5},{85,127,232},{85,127,232},{85,127,232},{82,118,0},{127,27,1152},{62,126,5},{62,126,5},{33,106,0},{126,78,1152},{33,106,0},{127,95,882},{102,127,320},{96,127,0},{63,127,0},{127,95,882},{127,111,882},{63,127,0},{0,116,884},{127,111,882},{0,116,884},{68,0,1568},{68,0,1568},{68,0,1568},{68,0,1568},{56,127,45},{56,127,45},{56,127,45},{54,96,1},{28,108,1},
+{28,108,1},{85,127,6483},{79,127,3828},{79,127,2867},{73,127,1574},{82,127,6979},{67,127,1846},{63,127,181},{56,116,1002},{43,127,4714},{29,118,566},{100,127,2034},{93,127,822},{91,127,306},{86,125,26},{127,69,3318},{76,127,1233},{70,127,32},{20,119,545},{126,99,3318},{20,119,545},{79,127,2867},{79,127,2867},{79,127,2867},{73,127,1574},{71,127,2425},{63,127,181},{63,127,181},{57,108,122},{31,127,1273},{34,111,6},{91,127,306},
+{91,127,306},{91,127,306},{87,122,1},{127,40,1152},{70,127,32},{70,127,32},{39,110,1},{126,85,1152},{39,110,1},{127,101,545},{108,127,193},{102,127,1},{76,127,0},{127,101,545},{127,114,545},{76,127,0},{0,119,545},{127,114,545},{0,119,545},{72,0,1570},{72,0,1570},{72,0,1570},{72,0,1570},{61,127,80},{61,127,80},{61,127,80},{59,100,0},{33,112,1},{33,112,1},{88,127,6059},{84,127,3891},{82,127,3035},
+{76,127,1634},{85,127,6411},{70,127,1754},{67,127,341},{61,118,678},{51,127,4330},{34,120,322},{103,127,1698},{98,127,782},{97,127,394},{90,127,2},{127,76,2753},{84,127,1018},{76,127,80},{28,121,313},{126,103,2753},{28,121,313},{82,127,3035},{82,127,3035},{82,127,3035},{76,127,1634},{77,127,2641},{67,127,341},{67,127,341},{61,112,122},{37,127,1401},{38,115,6},{97,127,394},{97,127,394},{97,127,394},{91,126,1},{127,53,1152},
+{76,127,80},{76,127,80},{43,114,1},{126,91,1152},{43,114,1},{127,107,313},{111,127,116},{108,127,1},{89,127,0},{127,107,313},{127,117,313},{89,127,0},{0,121,313},{127,117,313},{0,121,313},{76,0,1570},{76,0,1570},{76,0,1570},{76,0,1570},{65,127,125},{65,127,125},{65,127,125},{63,104,0},{37,116,1},{37,116,1},{94,127,5691},{88,127,3919},{88,127,3243},{81,127,1739},{88,127,5947},{76,127,1722},{73,127,557},
+{64,120,426},{57,127,3994},{39,122,150},{106,127,1434},{102,127,770},{100,127,482},{95,127,17},{127,86,2273},{90,127,850},{84,127,170},{36,123,145},{127,107,2273},{36,123,145},{88,127,3243},{88,127,3243},{88,127,3243},{81,127,1739},{79,127,2835},{73,127,557},{73,127,557},{65,115,122},{46,127,1561},{42,119,6},{100,127,482},{100,127,482},{100,127,482},{95,127,17},{127,64,1152},{84,127,170},{84,127,170},{47,118,1},{126,97,1152},
+{47,118,1},{127,113,145},{116,127,53},{114,127,0},{101,127,0},{127,113,145},{127,120,145},{101,127,0},{0,123,145},{127,120,145},{0,123,145},{80,0,1570},{80,0,1570},{80,0,1570},{80,0,1570},{71,127,181},{71,127,181},{71,127,181},{67,108,1},{41,120,1},{41,120,1},{97,127,5379},{92,127,3991},{91,127,3427},{87,127,1907},{94,127,5539},{79,127,1783},{79,127,822},{69,122,254},{64,127,3745},{44,125,42},{111,127,1210},
+{106,127,782},{106,127,586},{99,127,82},{127,93,1878},{96,127,746},{90,127,274},{44,125,41},{126,111,1878},{44,125,41},{91,127,3427},{91,127,3427},{91,127,3427},{87,127,1907},{85,127,3051},{79,127,822},{79,127,822},{69,119,122},{54,127,1798},{46,123,6},{106,127,586},{106,127,586},{106,127,586},{99,127,82},{127,76,1152},{90,127,274},{90,127,274},{51,122,1},{126,103,1152},{51,122,1},{127,119,41},{122,127,13},{120,127,0},
+{113,127,0},{127,119,41},{127,123,41},{113,127,0},{0,125,41},{127,123,41},{0,125,41},{84,0,1570},{84,0,1570},{84,0,1570},{84,0,1570},{74,127,245},{74,127,245},{74,127,245},{71,112,1},{45,124,1},{45,124,1},{100,127,5128},{97,127,4080},{97,127,3680},{90,127,2152},{97,127,5200},{87,127,1964},{84,127,1208},{73,126,145},{73,127,3580},{51,127,5},{114,127,1062},{111,127,797},{111,127,697},{105,127,212},{127,102,1536},
+{102,127,708},{99,127,424},{54,127,0},{127,115,1536},{54,127,0},{97,127,3680},{97,127,3680},{97,127,3680},{90,127,2152},{91,127,3328},{84,127,1208},{84,127,1208},{74,124,121},{63,127,2089},{51,127,5},{111,127,697},{111,127,697},{111,127,697},{105,127,212},{127,90,1152},{99,127,424},{99,127,424},{54,127,0},{127,109,1152},{54,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},
+{0,127,0},{127,127,0},{0,127,0},{89,0,1568},{89,0,1568},{89,0,1568},{89,0,1568},{79,127,320},{79,127,320},{79,127,320},{75,117,0},{51,127,5},{51,127,5},{103,127,4416},{100,127,3580},{100,127,3256},{96,127,2040},{100,127,4372},{90,127,1736},{87,127,1128},{79,126,57},{76,127,2956},{57,127,37},{117,127,738},{114,127,566},{114,127,485},{108,127,148},{127,107,1067},{108,127,484},{102,127,292},{66,127,0},{127,117,1067},
+{66,127,0},{100,127,3256},{100,127,3256},{100,127,3256},{96,127,2040},{94,127,2852},{87,127,1128},{87,127,1128},{78,125,45},{70,127,1739},{57,127,37},{114,127,485},{114,127,485},{114,127,485},{108,127,148},{127,96,800},{102,127,292},{102,127,292},{66,127,0},{127,112,800},{66,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{93,0,1568},
+{93,0,1568},{93,0,1568},{93,0,1568},{85,127,400},{85,127,400},{85,127,400},{79,121,0},{57,127,37},{57,127,37},{106,127,3784},{103,127,3136},{103,127,2880},{99,127,1924},{103,127,3648},{93,127,1564},{92,127,1078},{82,127,8},{81,127,2480},{64,127,90},{117,127,482},{117,127,362},{117,127,313},{113,127,97},{127,110,683},{111,127,321},{108,127,180},{78,127,0},{126,119,683},{78,127,0},{103,127,2880},{103,127,2880},{103,127,2880},
+{99,127,1924},{97,127,2448},{92,127,1078},{92,127,1078},{83,126,8},{76,127,1451},{64,127,90},{117,127,313},{117,127,313},{117,127,313},{113,127,97},{127,102,512},{108,127,180},{108,127,180},{78,127,0},{127,115,512},{78,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{97,0,1568},{97,0,1568},{97,0,1568},{97,0,1568},{88,127,500},
+{88,127,500},{88,127,500},{83,125,0},{64,127,90},{64,127,90},{109,127,3232},{106,127,2748},{106,127,2552},{102,127,1832},{106,127,3028},{99,127,1420},{96,127,1048},{87,127,4},{87,127,2032},{73,127,170},{120,127,262},{120,127,206},{118,127,180},{116,127,53},{127,115,384},{116,127,179},{113,127,106},{90,127,0},{127,121,384},{90,127,0},{106,127,2552},{106,127,2552},{106,127,2552},{102,127,1832},{103,127,2112},{96,127,1048},{96,127,1048},
+{87,127,4},{81,127,1260},{73,127,170},{118,127,180},{118,127,180},{118,127,180},{116,127,53},{127,108,288},{113,127,106},{113,127,106},{90,127,0},{127,118,288},{90,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{101,0,1568},{101,0,1568},{101,0,1568},{101,0,1568},{94,127,596},{94,127,596},{94,127,596},{87,127,4},{73,127,170},
+{73,127,170},{0,104,2665},{0,73,274},{0,53,4},{0,45,985},{0,69,5885},{0,46,3677},{0,41,1789},{0,27,4441},{0,31,6341},{0,27,4765},{0,104,2665},{0,73,274},{0,53,4},{0,45,985},{34,0,5885},{0,46,3677},{0,41,1789},{0,27,4441},{69,0,5885},{0,27,4441},{0,50,0},{0,50,0},{0,50,0},{0,24,1},{0,24,545},{0,19,193},{0,19,193},{0,12,337},{0,11,598},{0,10,387},{0,50,0},
+{0,50,0},{0,50,0},{0,24,1},{12,0,545},{0,19,193},{0,19,193},{0,12,337},{24,0,545},{0,12,337},{51,0,2665},{0,73,274},{0,53,4},{0,45,985},{51,0,2665},{104,0,2665},{0,45,985},{0,35,2665},{104,0,2665},{0,35,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,117,2665},{0,81,160},{1,57,12},
+{0,50,872},{0,78,6669},{0,51,3898},{0,46,1825},{0,33,4865},{0,34,7249},{0,30,5277},{0,117,2665},{0,81,160},{1,57,8},{0,50,872},{39,0,6669},{0,51,3898},{0,46,1825},{0,33,4865},{78,0,6669},{0,33,4865},{0,62,0},{0,62,0},{0,62,0},{0,30,1},{0,30,841},{0,25,305},{0,25,305},{0,13,514},{0,14,926},{0,13,595},{0,62,0},{0,62,0},{0,62,0},{0,30,1},{15,0,841},
+{0,25,305},{0,25,305},{0,13,514},{30,0,841},{0,13,514},{57,0,2665},{0,81,160},{3,57,0},{0,50,872},{57,0,2665},{117,0,2665},{0,50,872},{0,39,2665},{117,0,2665},{0,39,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,127,2669},{0,87,80},{1,63,60},{0,53,740},{0,86,7538},{0,57,4178},{0,49,1889},
+{0,36,5333},{0,40,8241},{0,33,5845},{0,127,2669},{0,87,80},{2,61,52},{0,53,740},{42,1,7538},{0,57,4178},{0,49,1889},{0,36,5333},{86,0,7538},{0,36,5333},{0,74,0},{0,74,0},{0,74,0},{0,36,1},{0,36,1201},{0,28,445},{0,28,445},{0,18,745},{0,17,1326},{0,15,861},{0,74,0},{0,74,0},{0,74,0},{0,36,1},{18,0,1201},{0,28,445},{0,28,445},{0,18,745},{36,0,1201},
+{0,18,745},{63,0,2665},{0,87,80},{7,61,0},{0,53,740},{63,0,2665},{127,1,2665},{0,53,740},{0,43,2665},{127,1,2665},{0,43,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,127,2797},{0,93,32},{2,65,154},{0,59,628},{0,94,8493},{0,63,4490},{0,54,1965},{0,39,5849},{0,43,9333},{0,36,6469},{3,127,2761},
+{0,93,32},{3,66,126},{0,59,628},{46,0,8493},{0,63,4490},{0,54,1965},{0,39,5849},{94,0,8493},{0,39,5849},{0,86,0},{0,86,0},{0,86,0},{0,42,1},{0,42,1625},{0,34,605},{0,34,605},{0,21,1009},{0,19,1781},{0,18,1161},{0,86,0},{0,86,0},{0,86,0},{0,42,1},{21,0,1625},{0,34,605},{0,34,605},{0,21,1009},{42,0,1625},{0,21,1009},{69,0,2665},{0,93,32},{11,64,1},
+{0,59,628},{69,0,2665},{127,7,2665},{0,59,628},{0,47,2665},{127,7,2665},{0,47,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,127,3157},{0,102,2},{2,71,304},{0,62,514},{0,103,9669},{0,67,4865},{0,60,2107},{0,42,6485},{0,46,10689},{0,39,7245},{6,127,3029},{0,102,2},{5,71,260},{0,62,514},{50,1,9669},
+{0,67,4865},{0,60,2107},{0,42,6485},{103,0,9669},{0,42,6485},{0,100,0},{0,100,0},{0,100,0},{0,49,0},{0,50,2178},{0,40,820},{0,40,820},{0,24,1348},{0,22,2392},{0,21,1556},{0,100,0},{0,100,0},{0,100,0},{0,49,0},{24,1,2178},{0,40,820},{0,40,820},{0,24,1348},{50,0,2178},{0,24,1348},{76,0,2665},{0,102,2},{15,69,0},{0,62,514},{76,0,2665},{126,14,2665},{0,62,514},
+{0,51,2665},{126,14,2665},{0,51,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,127,3509},{2,108,32},{4,76,424},{1,67,473},{0,115,9669},{0,73,4529},{0,64,1649},{0,45,6209},{0,51,10919},{0,45,7109},{12,127,3141},{4,106,2},{9,75,260},{1,67,469},{56,1,9669},{0,73,4529},{0,64,1649},{0,45,6209},{115,0,9669},
+{0,45,6209},{2,108,32},{2,108,32},{2,108,32},{2,54,32},{0,62,2178},{0,46,628},{0,46,628},{0,27,1184},{0,28,2520},{0,26,1502},{4,104,0},{4,104,0},{4,104,0},{4,53,0},{30,1,2178},{0,46,628},{0,46,628},{0,27,1184},{62,0,2178},{0,27,1184},{81,0,2665},{2,108,0},{19,73,0},{0,66,421},{81,0,2665},{126,20,2665},{0,66,421},{0,55,2665},{126,20,2665},{0,55,2665},{2,0,32},
+{2,0,32},{2,0,32},{2,0,32},{0,12,0},{0,12,0},{0,12,0},{0,6,0},{0,5,10},{0,5,10},{12,127,3989},{4,114,130},{7,79,616},{3,72,525},{0,127,9669},{0,81,4178},{0,67,1265},{0,50,5950},{0,57,11199},{0,49,7029},{17,127,3253},{8,110,2},{13,79,260},{5,71,469},{62,1,9669},{0,81,4178},{0,67,1265},{0,50,5950},{127,0,9669},{0,50,5950},{4,116,128},{4,116,128},{4,116,128},
+{4,59,128},{0,74,2178},{0,54,442},{0,54,442},{0,33,1040},{0,31,2676},{0,30,1460},{8,108,0},{8,108,0},{8,108,0},{8,57,0},{36,1,2178},{0,54,442},{0,54,442},{0,33,1040},{74,0,2178},{0,33,1040},{87,0,2665},{6,112,0},{23,77,0},{0,72,325},{87,0,2665},{126,26,2665},{0,72,325},{0,59,2665},{126,26,2665},{0,59,2665},{4,0,128},{4,0,128},{4,0,128},{4,0,128},{0,24,0},
+{0,24,0},{0,24,0},{0,12,0},{0,8,50},{0,8,50},{15,127,4613},{6,118,304},{9,84,880},{4,76,645},{3,127,9761},{0,87,3898},{0,73,913},{0,56,5686},{0,63,11511},{0,53,6939},{20,127,3401},{12,114,2},{17,83,260},{9,75,469},{68,0,9669},{0,87,3898},{0,73,913},{0,56,5686},{127,6,9669},{0,56,5686},{6,124,288},{6,124,288},{6,124,288},{6,63,289},{0,86,2178},{0,60,306},{0,60,306},
+{0,36,900},{0,37,2852},{0,34,1452},{12,112,0},{12,112,0},{12,112,0},{12,61,0},{42,1,2178},{0,60,306},{0,60,306},{0,36,900},{86,0,2178},{0,36,900},{93,0,2665},{10,116,0},{27,81,0},{0,77,260},{93,0,2665},{126,32,2665},{0,77,260},{0,63,2665},{126,32,2665},{0,63,2665},{6,0,288},{6,0,288},{6,0,288},{6,0,288},{0,36,0},{0,36,0},{0,36,0},{0,18,0},{0,14,106},
+{0,14,106},{17,127,5446},{9,124,575},{12,90,1267},{8,80,862},{7,127,10073},{0,96,3625},{0,79,594},{0,59,5393},{0,70,11905},{0,57,6894},{26,127,3570},{16,119,3},{21,87,259},{14,80,470},{75,0,9669},{0,96,3625},{0,79,594},{0,59,5393},{127,13,9669},{0,59,5393},{9,127,558},{9,127,558},{9,127,558},{8,69,545},{0,100,2178},{0,67,185},{0,67,185},{0,42,754},{0,43,3090},{0,38,1478},{17,115,1},
+{17,115,1},{17,115,1},{16,65,1},{49,0,2178},{0,67,185},{0,67,185},{0,42,754},{100,0,2178},{0,42,754},{100,0,2665},{15,120,0},{32,85,1},{0,82,193},{100,0,2665},{127,38,2665},{0,82,193},{0,67,2665},{127,38,2665},{0,67,2665},{8,0,545},{8,0,545},{8,0,545},{8,0,545},{0,50,0},{0,50,0},{0,50,0},{0,24,1},{0,19,193},{0,19,193},{20,127,6378},{12,127,915},{15,93,1695},
+{9,84,1118},{12,127,10506},{0,102,3401},{0,84,366},{0,65,5186},{0,76,12289},{0,61,6870},{32,127,3738},{20,123,3},{25,91,259},{18,84,470},{80,1,9669},{0,102,3401},{0,84,366},{0,65,5186},{126,19,9669},{0,65,5186},{12,127,914},{12,127,914},{12,127,914},{10,74,841},{0,112,2178},{0,76,97},{0,76,97},{0,45,650},{0,51,3317},{0,43,1514},{21,119,1},{21,119,1},{21,119,1},{20,69,1},{55,0,2178},
+{0,76,97},{0,76,97},{0,45,650},{112,0,2178},{0,45,650},{106,0,2665},{19,124,0},{36,89,1},{0,86,130},{106,0,2665},{127,44,2665},{0,86,130},{0,71,2665},{127,44,2665},{0,71,2665},{10,0,841},{10,0,841},{10,0,841},{10,0,841},{0,62,0},{0,62,0},{0,62,0},{0,30,1},{0,25,305},{0,25,305},{23,127,7454},{15,127,1431},{17,97,2214},{11,89,1438},{15,127,11102},{0,108,3209},{0,90,198},
+{0,69,4913},{0,81,12639},{0,65,6875},{38,127,3938},{24,127,3},{29,95,259},{22,88,470},{86,1,9669},{0,108,3209},{0,90,198},{0,69,4913},{126,25,9669},{0,69,4913},{15,127,1382},{15,127,1382},{15,127,1382},{12,79,1201},{0,124,2178},{0,84,37},{0,84,37},{0,50,549},{0,54,3565},{0,46,1598},{25,123,1},{25,123,1},{25,123,1},{24,73,1},{61,0,2178},{0,84,37},{0,84,37},{0,50,549},{124,0,2178},
+{0,50,549},{112,0,2665},{24,127,2},{40,93,1},{0,91,89},{112,0,2665},{127,50,2665},{0,91,89},{0,75,2665},{127,50,2665},{0,75,2665},{12,0,1201},{12,0,1201},{12,0,1201},{12,0,1201},{0,74,0},{0,74,0},{0,74,0},{0,36,1},{0,28,445},{0,28,445},{26,127,8674},{18,127,2131},{19,102,2786},{13,93,1839},{17,127,11833},{0,113,3038},{0,95,86},{0,72,4685},{0,84,13079},{0,70,6909},{41,127,4130},
+{30,127,35},{33,99,259},{26,92,470},{92,1,9669},{0,113,3038},{0,95,86},{0,72,4685},{126,31,9669},{0,72,4685},{17,127,1941},{17,127,1941},{17,127,1941},{14,84,1625},{3,127,2222},{0,90,5},{0,90,5},{0,56,445},{0,60,3861},{0,51,1674},{29,127,1},{29,127,1},{29,127,1},{28,77,1},{66,1,2178},{0,90,5},{0,90,5},{0,56,445},{126,5,2178},{0,56,445},{118,0,2665},{31,127,20},{44,97,1},
+{0,95,50},{118,0,2665},{127,56,2665},{0,95,50},{0,79,2665},{127,56,2665},{0,79,2665},{14,0,1625},{14,0,1625},{14,0,1625},{14,0,1625},{0,86,0},{0,86,0},{0,86,0},{0,42,1},{0,34,605},{0,34,605},{32,127,10209},{21,127,3140},{22,108,3525},{15,98,2360},{20,127,12902},{0,122,2885},{0,101,21},{0,78,4450},{0,93,13598},{0,73,6982},{47,127,4373},{34,127,134},{38,104,260},{30,96,469},{99,0,9669},
+{0,122,2885},{0,101,21},{0,78,4450},{126,38,9669},{0,78,4450},{20,127,2717},{20,127,2717},{20,127,2717},{16,90,2180},{6,127,2420},{0,98,1},{0,98,1},{0,62,353},{0,64,4230},{0,57,1814},{34,126,13},{34,126,13},{34,126,13},{33,81,1},{73,0,2178},{2,96,1},{2,96,1},{0,62,353},{126,12,2178},{0,62,353},{125,0,2665},{40,127,74},{48,102,0},{0,101,20},{125,0,2665},{126,63,2665},{0,101,20},
+{0,84,2665},{126,63,2665},{0,84,2665},{16,0,2180},{16,0,2180},{16,0,2180},{16,0,2180},{0,100,0},{0,100,0},{0,100,0},{0,49,0},{0,40,820},{0,40,820},{35,127,11582},{25,127,4131},{25,111,4166},{17,103,2825},{26,127,13903},{1,126,2826},{1,105,18},{0,83,4290},{0,96,13969},{0,79,6967},{52,127,4577},{40,127,270},{42,108,260},{34,100,469},{105,0,9669},{1,126,2825},{1,105,17},{0,83,4289},{126,44,9669},
+{0,83,4289},{23,127,3434},{23,127,3434},{23,127,3434},{19,94,2666},{9,127,2709},{1,105,14},{1,105,14},{0,66,275},{0,70,4491},{0,60,1893},{38,127,29},{38,127,29},{38,127,29},{37,85,1},{79,0,2178},{6,100,1},{6,100,1},{0,66,274},{127,17,2178},{0,66,274},{127,7,2665},{46,127,146},{52,106,0},{0,105,8},{127,7,2665},{127,68,2665},{0,105,8},{0,88,2665},{127,68,2665},{0,88,2665},{19,0,2665},
+{19,0,2665},{19,0,2665},{19,0,2665},{1,110,1},{1,110,1},{1,110,1},{0,55,1},{0,43,985},{0,43,985},{38,127,12090},{30,127,4561},{29,115,4166},{21,107,2825},{29,127,14311},{5,127,2910},{5,109,18},{0,86,4166},{0,105,13477},{0,84,6285},{58,127,4833},{46,127,470},{46,112,260},{38,104,469},{111,0,9669},{5,127,2909},{5,109,17},{0,86,4085},{127,49,9669},{0,86,4085},{26,127,3590},{26,127,3590},{26,127,3590},
+{23,98,2666},{12,127,2853},{5,109,14},{5,109,14},{3,69,259},{0,76,4147},{0,64,1475},{44,127,61},{44,127,61},{44,127,61},{41,89,1},{85,0,2178},{10,104,1},{10,104,1},{0,69,202},{127,23,2178},{0,69,202},{127,19,2665},{54,127,260},{56,110,0},{0,110,0},{127,19,2665},{127,74,2665},{0,110,0},{0,92,2665},{127,74,2665},{0,92,2665},{23,0,2665},{23,0,2665},{23,0,2665},{23,0,2665},{5,114,1},
+{5,114,1},{5,114,1},{4,59,1},{0,51,745},{0,51,745},{44,127,12610},{34,127,5039},{33,119,4166},{25,111,2825},{35,127,14719},{11,127,3118},{9,113,18},{4,90,4166},{0,113,13003},{0,87,5661},{61,127,5093},{51,127,736},{50,116,260},{42,108,469},{117,0,9669},{14,127,3073},{9,113,17},{0,89,3929},{127,55,9669},{0,89,3929},{32,127,3726},{32,127,3726},{32,127,3726},{27,102,2666},{17,127,2979},{9,113,14},{9,113,14},
+{7,73,259},{0,84,3784},{0,70,1091},{47,127,97},{47,127,97},{47,127,97},{45,93,1},{91,0,2178},{14,108,1},{14,108,1},{0,75,146},{127,29,2178},{0,75,146},{127,31,2665},{60,127,388},{60,114,0},{3,114,0},{127,31,2665},{127,80,2665},{3,114,0},{0,96,2665},{127,80,2665},{0,96,2665},{27,0,2665},{27,0,2665},{27,0,2665},{27,0,2665},{9,118,1},{9,118,1},{9,118,1},{8,63,1},{0,60,565},
+{0,60,565},{49,127,13154},{40,127,5661},{37,123,4166},{30,116,2823},{41,127,15213},{16,127,3497},{14,118,18},{8,94,4166},{0,116,12489},{0,93,5039},{68,127,5409},{57,127,1091},{54,120,259},{47,113,470},{124,0,9669},{22,127,3341},{14,118,14},{0,95,3726},{127,62,9669},{0,95,3726},{38,127,3929},{38,127,3929},{38,127,3929},{31,107,2665},{23,127,3156},{13,117,17},{13,117,17},{11,77,260},{0,90,3467},{0,76,736},{52,127,146},
+{52,127,146},{52,127,146},{49,98,1},{98,0,2178},{19,112,1},{19,112,1},{0,80,97},{127,36,2178},{0,80,97},{127,45,2665},{67,127,565},{64,119,1},{9,118,1},{127,45,2665},{126,87,2665},{9,118,1},{0,100,2665},{126,87,2665},{0,100,2665},{31,0,2665},{31,0,2665},{31,0,2665},{31,0,2665},{13,123,0},{13,123,0},{13,123,0},{13,67,0},{0,67,388},{0,67,388},{52,127,13734},{43,127,6285},{41,127,4166},
+{34,120,2823},{47,127,15677},{22,127,3905},{18,122,18},{12,98,4166},{0,125,12093},{0,97,4561},{71,127,5701},{60,127,1475},{58,124,259},{51,117,470},{127,5,9669},{31,127,3601},{18,122,14},{0,101,3590},{126,68,9669},{0,101,3590},{41,127,4085},{41,127,4085},{41,127,4085},{35,111,2665},{29,127,3332},{17,121,17},{17,121,17},{15,81,260},{0,99,3211},{0,81,470},{58,127,202},{58,127,202},{58,127,202},{53,102,1},{104,0,2178},
+{23,116,1},{23,116,1},{0,83,61},{127,42,2178},{0,83,61},{127,57,2665},{76,127,745},{68,123,1},{13,122,1},{127,57,2665},{126,93,2665},{13,122,1},{0,104,2665},{126,93,2665},{0,104,2665},{35,0,2665},{35,0,2665},{35,0,2665},{35,0,2665},{17,127,0},{17,127,0},{17,127,0},{17,71,0},{0,73,260},{0,73,260},{58,127,14302},{48,127,6967},{44,127,4290},{38,124,2823},{52,127,16094},{28,127,4409},{22,126,18},
+{16,102,4166},{0,126,11883},{0,102,4131},{77,127,6005},{67,127,1893},{61,127,275},{55,121,470},{127,18,9669},{40,127,3909},{22,126,14},{0,104,3434},{126,74,9669},{0,104,3434},{44,127,4289},{44,127,4289},{44,127,4289},{39,115,2665},{35,127,3540},{21,125,17},{21,125,17},{19,85,260},{0,105,2979},{0,87,270},{61,127,274},{61,127,274},{61,127,274},{57,106,1},{110,0,2178},{27,120,1},{27,120,1},{0,89,29},{126,48,2178},
+{0,89,29},{127,69,2665},{81,127,985},{72,127,1},{17,126,1},{127,69,2665},{126,99,2665},{17,126,1},{0,108,2665},{126,99,2665},{0,108,2665},{39,0,2665},{39,0,2665},{39,0,2665},{39,0,2665},{22,126,8},{22,126,8},{22,126,8},{21,75,0},{0,81,146},{0,81,146},{61,127,13635},{53,127,6982},{49,127,4450},{42,125,2742},{55,127,15195},{34,127,4106},{26,127,21},{19,105,3525},{2,127,10776},{0,106,3140},{79,127,5396},
+{70,127,1814},{65,127,353},{59,122,321},{127,27,8712},{46,127,3462},{29,127,1},{0,107,2717},{126,78,8712},{0,107,2717},{49,127,4450},{49,127,4450},{49,127,4450},{43,119,2665},{38,127,3736},{26,127,21},{26,127,21},{23,89,260},{0,113,2772},{0,93,134},{65,127,353},{65,127,353},{65,127,353},{61,110,1},{115,1,2178},{31,124,1},{31,124,1},{0,93,13},{126,54,2178},{0,93,13},{127,76,2178},{87,127,820},{78,127,0},
+{27,127,0},{127,76,2178},{126,103,2178},{27,127,0},{0,110,2180},{126,103,2178},{0,110,2180},{43,0,2665},{43,0,2665},{43,0,2665},{43,0,2665},{26,127,20},{26,127,20},{26,127,20},{25,79,0},{0,87,74},{0,87,74},{65,127,12750},{57,127,6909},{55,127,4685},{48,126,2678},{61,127,14070},{37,127,3711},{32,127,86},{25,108,2786},{5,127,9739},{0,109,2131},{85,127,4658},{76,127,1674},{71,127,445},{64,123,173},{127,36,7578},
+{51,127,2949},{37,127,5},{0,110,1941},{127,82,7578},{0,110,1941},{55,127,4685},{55,127,4685},{55,127,4685},{48,123,2666},{44,127,3987},{32,127,86},{32,127,86},{28,94,259},{0,119,2571},{0,97,35},{71,127,445},{71,127,445},{71,127,445},{66,114,1},{122,0,2178},{37,127,5},{37,127,5},{0,98,1},{126,61,2178},{0,98,1},{127,83,1625},{93,127,605},{84,127,1},{40,127,0},{127,83,1625},{126,106,1625},{40,127,0},
+{0,113,1625},{126,106,1625},{0,113,1625},{48,0,2665},{48,0,2665},{48,0,2665},{48,0,2665},{32,127,50},{32,127,50},{32,127,50},{30,83,1},{0,96,20},{0,96,20},{68,127,12050},{62,127,6875},{58,127,4913},{52,127,2666},{65,127,13165},{43,127,3423},{37,127,198},{30,110,2214},{11,127,8987},{0,112,1431},{88,127,4082},{79,127,1547},{77,127,549},{68,124,81},{127,43,6661},{57,127,2525},{43,127,37},{0,112,1382},{127,86,6661},
+{0,112,1382},{58,127,4913},{58,127,4913},{58,127,4913},{52,127,2666},{49,127,4197},{37,127,198},{37,127,198},{32,98,259},{0,125,2435},{0,103,3},{77,127,549},{77,127,549},{77,127,549},{70,118,1},{127,2,2178},{43,127,37},{43,127,37},{3,102,1},{127,66,2178},{3,102,1},{127,89,1201},{99,127,445},{90,127,1},{53,127,0},{127,89,1201},{125,109,1201},{53,127,0},{0,115,1201},{125,109,1201},{0,115,1201},{52,0,2665},
+{52,0,2665},{52,0,2665},{52,0,2665},{36,127,89},{36,127,89},{36,127,89},{34,87,1},{0,103,2},{0,103,2},{74,127,11418},{65,127,6870},{62,127,5186},{56,127,2701},{68,127,12313},{46,127,3251},{43,127,366},{34,112,1695},{14,127,8383},{0,115,915},{91,127,3578},{84,127,1514},{79,127,650},{73,126,21},{127,53,5829},{63,127,2165},{51,127,97},{0,115,914},{126,91,5829},{0,115,914},{62,127,5186},{62,127,5186},{62,127,5186},
+{56,127,2701},{55,127,4461},{43,127,366},{43,127,366},{36,102,259},{2,127,2427},{4,107,3},{79,127,650},{79,127,650},{79,127,650},{74,122,1},{127,14,2178},{51,127,97},{51,127,97},{7,106,1},{127,72,2178},{7,106,1},{127,95,841},{102,127,305},{96,127,1},{64,127,0},{127,95,841},{127,111,841},{64,127,0},{0,117,841},{127,111,841},{0,117,841},{56,0,2665},{56,0,2665},{56,0,2665},{56,0,2665},{41,127,130},
+{41,127,130},{41,127,130},{38,91,1},{3,108,0},{3,108,0},{77,127,10830},{69,127,6894},{68,127,5393},{60,127,2786},{71,127,11565},{54,127,3154},{48,127,594},{37,115,1267},{25,127,7825},{3,118,575},{94,127,3146},{87,127,1478},{85,127,754},{77,127,1},{127,60,5082},{70,127,1869},{57,127,185},{0,118,558},{127,94,5082},{0,118,558},{68,127,5393},{68,127,5393},{68,127,5393},{60,127,2786},{58,127,4725},{48,127,594},{48,127,594},
+{40,106,259},{8,127,2587},{8,111,3},{85,127,754},{85,127,754},{85,127,754},{78,126,1},{127,27,2178},{57,127,185},{57,127,185},{11,110,1},{126,78,2178},{11,110,1},{127,101,545},{108,127,193},{102,127,1},{76,127,0},{127,101,545},{127,114,545},{76,127,0},{0,119,545},{127,114,545},{0,119,545},{60,0,2665},{60,0,2665},{60,0,2665},{60,0,2665},{45,127,193},{45,127,193},{45,127,193},{42,95,1},{7,112,0},
+{7,112,0},{79,127,10221},{74,127,6939},{71,127,5686},{64,127,2954},{77,127,10836},{57,127,3109},{54,127,913},{42,117,880},{34,127,7300},{8,120,304},{100,127,2736},{93,127,1452},{91,127,900},{83,127,29},{127,69,4344},{76,127,1611},{67,127,306},{2,121,288},{126,99,4344},{2,121,288},{71,127,5686},{71,127,5686},{71,127,5686},{64,127,2954},{65,127,5051},{54,127,913},{54,127,913},{44,110,260},{14,127,2856},{13,115,2},{91,127,900},
+{91,127,900},{91,127,900},{83,127,29},{127,40,2178},{67,127,306},{67,127,306},{15,115,0},{126,85,2178},{15,115,0},{127,108,288},{113,127,106},{109,127,0},{90,127,0},{127,108,288},{127,118,288},{90,127,0},{0,121,288},{127,118,288},{0,121,288},{64,0,2665},{64,0,2665},{64,0,2665},{64,0,2665},{50,127,260},{50,127,260},{50,127,260},{46,100,0},{11,117,0},{11,117,0},{85,127,9781},{79,127,6942},{77,127,5950},
+{70,127,3146},{79,127,10205},{63,127,3141},{57,127,1265},{47,119,616},{40,127,6924},{13,123,130},{103,127,2436},{97,127,1460},{94,127,1040},{87,127,104},{127,76,3779},{81,127,1496},{73,127,442},{10,123,128},{126,103,3779},{10,123,128},{77,127,5950},{77,127,5950},{77,127,5950},{70,127,3146},{68,127,5347},{57,127,1265},{57,127,1265},{48,114,260},{25,127,3115},{17,119,2},{94,127,1040},{94,127,1040},{94,127,1040},{87,127,104},{127,53,2178},
+{73,127,442},{73,127,442},{19,119,0},{126,91,2178},{19,119,0},{127,115,128},{116,127,50},{115,127,0},{102,127,0},{127,115,128},{127,121,128},{102,127,0},{0,123,128},{127,121,128},{0,123,128},{68,0,2665},{68,0,2665},{68,0,2665},{68,0,2665},{55,127,325},{55,127,325},{55,127,325},{50,104,0},{15,121,0},{15,121,0},{88,127,9417},{82,127,7109},{82,127,6209},{73,127,3406},{85,127,9733},{67,127,3260},{63,127,1649},
+{50,122,424},{46,127,6644},{19,125,32},{106,127,2208},{101,127,1502},{100,127,1184},{93,127,232},{127,86,3299},{87,127,1400},{81,127,628},{19,125,32},{127,107,3299},{19,125,32},{82,127,6209},{82,127,6209},{82,127,6209},{73,127,3406},{74,127,5659},{63,127,1649},{63,127,1649},{52,118,260},{34,127,3419},{21,123,2},{100,127,1184},{100,127,1184},{100,127,1184},{93,127,232},{127,64,2178},{81,127,628},{81,127,628},{23,123,0},{126,97,2178},
+{23,123,0},{127,121,32},{122,127,10},{121,127,0},{115,127,0},{127,121,32},{127,124,32},{115,127,0},{0,125,32},{127,124,32},{0,125,32},{72,0,2665},{72,0,2665},{72,0,2665},{72,0,2665},{61,127,421},{61,127,421},{61,127,421},{54,108,0},{19,125,0},{19,125,0},{91,127,9133},{88,127,7245},{85,127,6485},{79,127,3710},{88,127,9325},{73,127,3460},{67,127,2107},{55,124,304},{54,127,6532},{25,127,2},{111,127,2038},
+{106,127,1556},{103,127,1348},{96,127,416},{127,93,2904},{93,127,1368},{87,127,820},{27,127,0},{126,111,2904},{27,127,0},{85,127,6485},{85,127,6485},{85,127,6485},{79,127,3710},{79,127,5949},{67,127,2107},{67,127,2107},{56,122,260},{40,127,3771},{25,127,2},{103,127,1348},{103,127,1348},{103,127,1348},{96,127,416},{127,76,2178},{87,127,820},{87,127,820},{27,127,0},{126,103,2178},{27,127,0},{127,127,0},{127,127,0},{127,127,0},
+{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{76,0,2665},{76,0,2665},{76,0,2665},{76,0,2665},{65,127,514},{65,127,514},{65,127,514},{58,112,0},{25,127,2},{25,127,2},{94,127,8049},{91,127,6469},{88,127,5849},{84,127,3561},{91,127,8053},{76,127,3106},{73,127,1965},{62,125,154},{60,127,5562},{34,127,32},{111,127,1507},{109,127,1161},{106,127,1009},{102,127,305},{127,98,2166},
+{99,127,1009},{93,127,605},{40,127,0},{126,113,2166},{40,127,0},{88,127,5849},{88,127,5849},{88,127,5849},{84,127,3561},{82,127,5209},{73,127,1965},{73,127,1965},{61,124,126},{46,127,3225},{34,127,32},{106,127,1009},{106,127,1009},{106,127,1009},{102,127,305},{127,83,1625},{93,127,605},{93,127,605},{40,127,0},{126,106,1625},{40,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},
+{0,127,0},{127,127,0},{0,127,0},{80,0,2665},{80,0,2665},{80,0,2665},{80,0,2665},{68,127,628},{68,127,628},{68,127,628},{63,116,1},{34,127,32},{34,127,32},{97,127,7165},{94,127,5845},{91,127,5333},{87,127,3401},{94,127,7033},{79,127,2823},{79,127,1862},{64,126,60},{64,127,4795},{40,127,80},{114,127,1107},{111,127,830},{111,127,730},{105,127,221},{127,102,1601},{102,127,737},{99,127,445},{53,127,0},{127,115,1601},
+{53,127,0},{91,127,5333},{91,127,5333},{91,127,5333},{87,127,3401},{85,127,4629},{79,127,1862},{79,127,1862},{66,125,52},{54,127,2834},{40,127,80},{111,127,730},{111,127,730},{111,127,730},{105,127,221},{127,89,1201},{99,127,445},{99,127,445},{53,127,0},{125,109,1201},{53,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{84,0,2665},
+{84,0,2665},{84,0,2665},{84,0,2665},{74,127,740},{74,127,740},{74,127,740},{66,120,0},{40,127,80},{40,127,80},{100,127,6361},{97,127,5277},{94,127,4865},{90,127,3265},{97,127,6117},{84,127,2641},{79,127,1814},{70,126,12},{70,127,4123},{46,127,160},{117,127,779},{114,127,595},{114,127,514},{108,127,153},{127,105,1121},{105,127,513},{102,127,305},{64,127,0},{126,117,1121},{64,127,0},{94,127,4865},{94,127,4865},{94,127,4865},
+{90,127,3265},{91,127,4117},{79,127,1814},{79,127,1814},{70,126,8},{60,127,2474},{46,127,160},{114,127,514},{114,127,514},{114,127,514},{108,127,153},{127,95,841},{102,127,305},{102,127,305},{64,127,0},{127,111,841},{64,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{88,0,2665},{88,0,2665},{88,0,2665},{88,0,2665},{79,127,853},
+{79,127,853},{79,127,853},{70,124,0},{46,127,160},{46,127,160},{103,127,5637},{100,127,4765},{100,127,4441},{93,127,3153},{100,127,5305},{90,127,2465},{86,127,1789},{74,127,4},{73,127,3543},{54,127,274},{117,127,507},{117,127,387},{115,127,337},{111,127,101},{127,110,726},{108,127,337},{108,127,193},{76,127,0},{126,119,726},{76,127,0},{100,127,4441},{100,127,4441},{100,127,4441},{93,127,3153},{94,127,3657},{86,127,1789},{86,127,1789},
+{74,127,4},{67,127,2182},{54,127,274},{115,127,337},{115,127,337},{115,127,337},{111,127,101},{127,101,545},{108,127,193},{108,127,193},{76,127,0},{127,114,545},{76,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{92,0,2665},{92,0,2665},{92,0,2665},{92,0,2665},{82,127,985},{82,127,985},{82,127,985},{74,127,4},{54,127,274},
+{54,127,274},{17,127,39416},{1,127,2073},{0,90,164},{0,86,5261},{17,127,49709},{0,113,21212},{0,85,8480},{0,75,26137},{0,87,56335},{0,67,37225},{12,127,10274},{0,122,1413},{0,90,148},{0,75,3940},{57,0,18065},{0,76,12036},{0,68,6166},{0,45,14098},{117,0,18065},{0,45,14098},{0,71,0},{0,71,0},{0,71,0},{0,35,0},{0,35,1105},{0,28,405},{0,28,405},{0,15,689},{0,14,1226},{0,15,789},{0,71,0},
+{0,71,0},{0,71,0},{0,35,0},{17,0,1105},{0,28,405},{0,28,405},{0,15,689},{35,0,1105},{0,15,689},{85,0,9248},{0,122,1413},{0,90,148},{0,75,3940},{85,0,9248},{127,23,9248},{0,75,3940},{0,57,9250},{127,23,9248},{0,57,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{20,127,44736},{2,127,2677},{0,95,64},
+{0,92,4941},{17,127,55213},{0,119,21820},{0,89,8426},{0,78,27209},{0,90,60583},{0,73,39465},{15,127,10870},{0,125,1213},{0,93,52},{0,78,3656},{61,0,19334},{0,81,12395},{0,73,6176},{0,50,14795},{124,0,19334},{0,50,14795},{0,83,0},{0,83,0},{0,83,0},{0,41,0},{0,41,1513},{0,34,565},{0,34,565},{0,18,937},{0,19,1661},{0,18,1081},{0,83,0},{0,83,0},{0,83,0},{0,41,0},{20,0,1513},
+{0,34,565},{0,34,565},{0,18,937},{41,0,1513},{0,18,937},{91,0,9248},{0,125,1213},{0,93,52},{0,78,3656},{91,0,9248},{127,29,9248},{0,78,3656},{0,61,9250},{127,29,9248},{0,61,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{20,127,50624},{2,127,4005},{0,99,4},{0,95,4545},{20,127,61345},{0,125,22460},{0,93,8410},
+{0,83,28480},{0,96,65039},{0,76,41789},{17,127,11556},{1,127,1217},{0,99,4},{0,83,3425},{64,0,20689},{0,87,12835},{0,76,6216},{0,53,15539},{126,3,20689},{0,53,15539},{0,95,0},{0,95,0},{0,95,0},{0,47,0},{0,47,1985},{0,37,745},{0,37,745},{0,21,1225},{0,22,2185},{0,21,1421},{0,95,0},{0,95,0},{0,95,0},{0,47,0},{23,0,1985},{0,37,745},{0,37,745},{0,21,1225},{47,0,1985},
+{0,21,1225},{97,0,9248},{2,127,1205},{0,99,4},{0,83,3425},{97,0,9248},{127,35,9248},{0,83,3425},{0,65,9248},{127,35,9248},{0,65,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{23,127,56952},{5,127,6081},{0,103,9},{0,98,4221},{20,127,65535},{0,126,23535},{0,97,8416},{0,86,29640},{0,99,65535},{0,79,44233},{20,127,12416},
+{2,127,1397},{1,103,8},{0,86,3181},{69,0,22129},{0,90,13307},{0,81,6266},{0,56,16331},{127,7,22129},{0,56,16331},{0,107,0},{0,107,0},{0,107,0},{0,53,0},{0,53,2521},{0,43,953},{0,43,953},{0,24,1553},{0,22,2777},{0,24,1809},{0,107,0},{0,107,0},{0,107,0},{0,53,0},{26,0,2521},{0,43,953},{0,43,953},{0,24,1553},{53,0,2521},{0,24,1553},{103,0,9248},{2,127,1381},{2,103,0},
+{0,86,3181},{103,0,9248},{127,41,9248},{0,86,3181},{0,69,9248},{127,41,9248},{0,69,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{26,127,64790},{5,127,9105},{1,108,78},{0,104,3845},{23,127,65535},{2,127,25370},{0,102,8458},{0,89,31046},{0,105,65535},{0,81,47079},{23,127,13542},{5,127,1881},{2,109,50},{0,92,2897},{73,0,23851},
+{0,96,13865},{0,87,6374},{0,59,17289},{126,12,23851},{0,59,17289},{0,121,0},{0,121,0},{0,121,0},{0,59,1},{0,61,3200},{0,51,1210},{0,51,1210},{0,27,1972},{0,25,3528},{0,27,2296},{0,121,0},{0,121,0},{0,121,0},{0,59,1},{30,0,3200},{0,51,1210},{0,51,1210},{0,27,1972},{61,0,3200},{0,27,1972},{110,0,9248},{11,127,1693},{7,107,1},{0,92,2897},{110,0,9248},{126,48,9248},{0,92,2897},
+{0,73,9250},{126,48,9248},{0,73,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{26,127,65535},{5,127,12609},{1,111,198},{0,107,3541},{26,127,65535},{2,127,27706},{0,105,8522},{0,92,32390},{0,113,65535},{0,87,49743},{26,127,14690},{8,127,2501},{3,113,126},{0,98,2665},{77,0,25472},{0,102,14385},{0,90,6486},{0,62,18185},{127,15,25472},
+{0,62,18185},{0,127,16},{0,127,16},{0,127,16},{0,65,0},{0,66,3872},{0,51,1450},{0,51,1450},{0,30,2384},{0,28,4268},{0,27,2776},{1,127,13},{1,127,13},{1,127,13},{0,65,0},{33,0,3872},{0,51,1450},{0,51,1450},{0,30,2384},{66,0,3872},{0,30,2384},{115,1,9248},{19,127,2041},{11,111,1},{0,98,2665},{115,1,9248},{126,54,9248},{0,98,2665},{0,77,9250},{126,54,9248},{0,77,9250},{0,0,0},
+{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{29,127,65535},{8,127,16605},{1,116,349},{0,112,3274},{26,127,65535},{2,127,30470},{0,109,8346},{0,98,33226},{0,113,65535},{0,90,52035},{29,127,15746},{11,127,3213},{5,117,217},{0,101,2445},{81,0,26744},{0,108,14657},{0,96,6398},{0,66,18739},{126,20,26744},{0,66,18739},{3,127,116},{3,127,116},{3,127,116},
+{0,71,4},{0,74,4418},{0,57,1586},{0,57,1586},{0,33,2664},{0,31,4916},{0,30,3140},{3,127,80},{3,127,80},{3,127,80},{1,70,1},{36,1,4418},{0,57,1586},{0,57,1586},{0,33,2664},{74,0,4418},{0,33,2664},{121,1,9248},{25,127,2377},{15,115,1},{0,101,2441},{121,1,9248},{126,60,9248},{0,101,2441},{0,81,9250},{126,60,9248},{0,81,9250},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,3,0},
+{0,3,0},{0,3,0},{0,1,1},{1,0,2},{1,0,2},{32,127,65535},{11,127,21205},{2,120,605},{0,115,3106},{29,127,65535},{2,127,33062},{0,114,7330},{0,101,32522},{0,119,65535},{0,93,52995},{35,127,16210},{14,127,3809},{9,121,217},{0,107,2325},{87,0,26744},{0,116,14054},{0,99,5606},{0,72,18275},{126,26,26744},{0,72,18275},{6,127,292},{6,127,292},{6,127,292},{2,76,52},{0,86,4418},{0,64,1313},{0,64,1313},
+{0,39,2440},{0,37,5092},{0,36,3044},{9,127,128},{9,127,128},{9,127,128},{5,74,1},{42,1,4418},{0,64,1313},{0,64,1313},{0,39,2440},{86,0,4418},{0,39,2440},{127,1,9248},{34,127,2741},{19,119,1},{0,107,2225},{127,1,9248},{127,65,9248},{0,107,2225},{0,85,9250},{127,65,9248},{0,85,9250},{2,0,52},{2,0,52},{2,0,52},{2,0,52},{0,15,0},{0,15,0},{0,15,0},{0,7,1},{0,5,18},
+{0,5,18},{35,127,65535},{11,127,27154},{3,124,1078},{0,121,3041},{32,127,65535},{5,127,36765},{0,119,6285},{0,107,31809},{0,125,65535},{0,96,54246},{38,127,16729},{22,127,4594},{14,126,218},{4,111,2318},{94,0,26744},{0,122,13481},{0,105,4785},{0,75,17772},{127,32,26744},{0,75,17772},{9,127,614},{9,127,614},{9,127,614},{5,81,181},{0,100,4418},{0,73,1037},{0,73,1037},{0,42,2210},{0,43,5330},{0,41,2986},{13,127,193},
+{13,127,193},{13,127,193},{9,79,1},{49,0,4418},{0,73,1037},{0,73,1037},{0,42,2210},{100,0,4418},{0,42,2210},{127,14,9248},{40,127,3177},{23,124,0},{0,110,2009},{127,14,9248},{127,72,9248},{0,110,2009},{0,90,9248},{127,72,9248},{0,90,9248},{5,0,181},{5,0,181},{5,0,181},{5,0,181},{0,29,0},{0,29,0},{0,29,0},{0,14,0},{0,11,65},{0,11,65},{35,127,65535},{14,127,31662},{4,127,1705},
+{0,124,3025},{35,127,65535},{8,127,39325},{0,122,5245},{0,110,30421},{0,125,65535},{0,102,54322},{44,127,16749},{25,127,5034},{17,127,245},{7,114,2214},{99,0,26259},{0,125,12725},{0,111,3981},{0,78,16984},{126,38,26259},{0,78,16984},{10,127,1025},{10,127,1025},{10,127,1025},{7,86,365},{0,112,4418},{0,81,797},{0,81,797},{0,47,2025},{0,51,5557},{0,45,2950},{17,127,245},{17,127,245},{17,127,245},{13,83,1},{55,0,4418},
+{0,81,797},{0,81,797},{0,47,2025},{112,0,4418},{0,47,2025},{127,25,8978},{46,127,3385},{28,127,0},{0,115,1732},{127,25,8978},{127,77,8978},{0,115,1732},{0,93,8980},{127,77,8978},{0,93,8980},{7,0,365},{7,0,365},{7,0,365},{7,0,365},{0,41,0},{0,41,0},{0,41,0},{0,20,0},{0,17,137},{0,17,137},{38,127,65535},{14,127,32078},{6,127,2618},{1,125,2789},{35,127,65535},{8,127,37485},{0,123,3805},
+{0,110,27013},{0,125,65535},{0,102,51330},{49,127,15435},{31,127,4714},{23,127,317},{12,116,1830},{104,0,24371},{0,125,11205},{0,113,2881},{0,83,15117},{127,42,24371},{0,83,15117},{12,127,1538},{12,127,1538},{12,127,1538},{9,91,613},{0,124,4418},{0,87,605},{0,87,605},{0,53,1825},{0,54,5805},{0,49,2946},{23,127,317},{23,127,317},{23,127,317},{17,87,1},{61,0,4418},{0,87,605},{0,87,605},{0,53,1825},{124,0,4418},
+{0,53,1825},{127,31,7938},{51,127,3029},{34,127,0},{0,118,1224},{127,31,7938},{127,80,7938},{0,118,1224},{0,95,7940},{127,80,7938},{0,95,7940},{9,0,613},{9,0,613},{9,0,613},{9,0,613},{0,53,0},{0,53,0},{0,53,0},{0,26,0},{0,22,221},{0,22,221},{38,127,65535},{14,127,32750},{6,127,3706},{3,124,2753},{35,127,65535},{8,127,35901},{0,124,2601},{0,110,23861},{0,125,65535},{0,102,48594},{52,127,14211},
+{34,127,4410},{26,127,405},{16,117,1482},{107,1,22568},{2,127,9869},{0,116,1973},{0,86,13349},{126,46,22568},{0,86,13349},{17,127,2137},{17,127,2137},{17,127,2137},{11,96,925},{3,127,4462},{0,93,445},{0,93,445},{0,56,1649},{0,60,6101},{0,54,2966},{26,127,405},{26,127,405},{26,127,405},{21,91,1},{66,1,4418},{0,93,445},{0,93,445},{0,56,1649},{126,5,4418},{0,56,1649},{127,37,6962},{57,127,2645},{40,127,0},
+{0,118,808},{127,37,6962},{127,83,6962},{0,118,808},{0,97,6964},{127,83,6962},{0,97,6964},{11,0,925},{11,0,925},{11,0,925},{11,0,925},{0,65,0},{0,65,0},{0,65,0},{0,32,0},{0,25,337},{0,25,337},{38,127,65535},{14,127,33812},{7,127,5233},{4,125,2961},{35,127,65535},{8,127,34425},{0,125,1509},{0,112,20542},{0,125,65535},{0,105,45810},{55,127,12917},{40,127,4114},{32,127,505},{22,117,1140},{112,0,20642},
+{2,127,8609},{0,119,1157},{0,89,11489},{127,50,20642},{0,89,11489},{20,127,2969},{20,127,2969},{20,127,2969},{13,102,1352},{6,127,4660},{0,102,289},{0,102,289},{0,62,1445},{0,64,6470},{0,57,3018},{32,127,505},{32,127,505},{32,127,505},{26,95,1},{73,0,4418},{0,102,289},{0,102,289},{0,62,1445},{126,12,4418},{0,62,1445},{127,43,5941},{63,127,2248},{46,127,1},{0,121,433},{127,43,5941},{127,86,5941},{0,121,433},
+{0,100,5941},{127,86,5941},{0,100,5941},{13,0,1352},{13,0,1352},{13,0,1352},{13,0,1352},{0,78,0},{0,78,0},{0,78,0},{0,39,0},{0,31,500},{0,31,500},{38,127,65535},{19,127,34934},{9,127,6748},{5,126,3381},{38,127,65535},{11,127,33369},{0,125,789},{0,112,17822},{0,125,65535},{0,105,43458},{58,127,11849},{43,127,3870},{38,127,617},{27,119,868},{115,1,19021},{5,127,7741},{0,120,621},{0,92,9957},{126,54,19021},
+{0,92,9957},{23,127,3833},{23,127,3833},{23,127,3833},{15,107,1800},{9,127,4984},{0,108,185},{0,108,185},{0,66,1282},{0,70,6822},{0,63,3090},{38,127,617},{38,127,617},{38,127,617},{30,99,1},{79,0,4418},{0,108,185},{0,108,185},{0,66,1282},{127,17,4418},{0,66,1282},{127,50,5101},{67,127,1921},{52,127,0},{0,124,205},{127,50,5101},{127,89,5101},{0,124,205},{0,102,5101},{127,89,5101},{0,102,5101},{15,0,1800},
+{15,0,1800},{15,0,1800},{15,0,1800},{0,91,0},{0,91,0},{0,91,0},{0,45,0},{0,37,676},{0,37,676},{41,127,65535},{19,127,36134},{9,127,8476},{5,126,4005},{38,127,65535},{11,127,32489},{0,126,309},{0,115,15210},{0,125,65535},{0,105,41362},{61,127,10853},{46,127,3674},{41,127,725},{31,120,632},{120,0,17485},{11,127,6965},{0,123,249},{0,95,8537},{127,58,17485},{0,95,8537},{23,127,4809},{23,127,4809},{23,127,4809},
+{17,112,2312},{12,127,5444},{0,116,89},{0,116,89},{0,72,1130},{0,76,7206},{0,67,3194},{41,127,725},{41,127,725},{41,127,725},{34,103,1},{85,0,4418},{0,116,89},{0,116,89},{0,72,1130},{127,23,4418},{0,72,1130},{127,56,4325},{70,127,1625},{58,127,0},{0,124,61},{127,56,4325},{127,92,4325},{0,124,61},{0,104,4325},{127,92,4325},{0,104,4325},{17,0,2312},{17,0,2312},{17,0,2312},{17,0,2312},{0,103,0},
+{0,103,0},{0,103,0},{0,50,1},{0,40,872},{0,40,872},{41,127,65535},{19,127,37590},{9,127,10460},{6,127,4841},{38,127,65535},{11,127,31865},{0,127,65},{0,115,12842},{0,125,65535},{0,105,39522},{65,127,9918},{51,127,3500},{47,127,853},{35,121,436},{124,0,16034},{14,127,6273},{0,125,53},{0,98,7229},{127,62,16034},{0,98,7229},{26,127,5881},{26,127,5881},{26,127,5881},{19,117,2888},{15,127,6040},{0,125,37},{0,125,37},
+{0,75,986},{0,81,7565},{0,70,3318},{47,127,853},{47,127,853},{47,127,853},{38,107,1},{91,0,4418},{0,125,37},{0,125,37},{0,75,986},{127,29,4418},{0,75,986},{127,62,3613},{76,127,1345},{64,127,0},{0,127,1},{127,62,3613},{127,95,3613},{0,127,1},{0,106,3613},{127,95,3613},{0,106,3613},{19,0,2888},{19,0,2888},{19,0,2888},{19,0,2888},{0,115,0},{0,115,0},{0,115,0},{0,56,1},{0,46,1096},
+{0,46,1096},{41,127,65535},{22,127,39522},{12,127,12842},{7,127,6030},{38,127,65535},{11,127,31469},{0,127,65},{0,118,10460},{0,125,65535},{0,108,37590},{68,127,8954},{57,127,3318},{52,127,986},{40,123,258},{127,2,14504},{22,127,5594},{2,127,37},{0,101,5881},{127,66,14504},{0,101,5881},{29,127,7229},{29,127,7229},{29,127,7229},{21,122,3614},{17,127,6824},{1,127,53},{1,127,53},{0,80,853},{0,87,8059},{0,76,3500},{52,127,986},
+{52,127,986},{52,127,986},{42,112,1},{98,0,4418},{2,127,37},{2,127,37},{0,80,853},{127,36,4418},{0,80,853},{127,69,2888},{81,127,1096},{70,127,1},{11,127,0},{127,69,2888},{126,99,2888},{11,127,0},{0,108,2888},{126,99,2888},{0,108,2888},{21,0,3613},{21,0,3613},{21,0,3613},{21,0,3613},{0,127,1},{0,127,1},{0,127,1},{0,63,0},{0,51,1345},{0,51,1345},{41,127,65535},{22,127,41362},{12,127,15210},
+{8,127,7309},{41,127,65535},{11,127,31389},{1,127,309},{0,118,8476},{0,125,65535},{0,108,36134},{71,127,8174},{60,127,3194},{55,127,1130},{45,123,137},{127,10,13235},{28,127,5018},{11,127,89},{0,101,4809},{126,70,13235},{0,101,4809},{32,127,8537},{32,127,8537},{32,127,8537},{23,127,4326},{20,127,7700},{4,127,249},{4,127,249},{0,86,725},{0,93,8531},{0,81,3674},{55,127,1130},{55,127,1130},{55,127,1130},{46,116,1},{104,0,4418},
+{11,127,89},{11,127,89},{0,86,725},{127,42,4418},{0,86,725},{127,75,2312},{87,127,872},{76,127,1},{24,127,0},{127,75,2312},{126,102,2312},{24,127,0},{0,110,2312},{126,102,2312},{0,110,2312},{23,0,4325},{23,0,4325},{23,0,4325},{23,0,4325},{3,127,61},{3,127,61},{3,127,61},{0,69,0},{0,54,1625},{0,54,1625},{44,127,65535},{22,127,43458},{15,127,17822},{8,127,8829},{41,127,65535},{14,127,31497},{2,127,789},
+{0,118,6748},{0,125,65535},{0,108,34934},{77,127,7454},{64,127,3090},{61,127,1282},{50,125,53},{127,19,12051},{34,127,4506},{16,127,185},{0,104,3833},{127,74,12051},{0,104,3833},{35,127,9957},{35,127,9957},{35,127,9957},{25,127,5150},{23,127,8712},{5,127,621},{5,127,621},{0,89,617},{0,96,9035},{0,84,3870},{61,127,1282},{61,127,1282},{61,127,1282},{50,120,1},{110,0,4418},{16,127,185},{16,127,185},{0,89,617},{126,48,4418},
+{0,89,617},{127,81,1800},{90,127,676},{82,127,0},{36,127,0},{127,81,1800},{126,105,1800},{36,127,0},{0,112,1800},{126,105,1800},{0,112,1800},{25,0,5101},{25,0,5101},{25,0,5101},{25,0,5101},{3,127,205},{3,127,205},{3,127,205},{0,75,0},{0,60,1921},{0,60,1921},{44,127,65535},{22,127,45810},{15,127,20542},{10,127,10546},{41,127,65535},{14,127,31833},{2,127,1509},{0,120,5233},{0,125,65535},{0,113,33812},{79,127,6740},
+{70,127,3018},{65,127,1445},{54,126,9},{127,27,10952},{40,127,4058},{25,127,289},{0,107,2969},{126,78,10952},{0,107,2969},{38,127,11489},{38,127,11489},{38,127,11489},{28,127,6114},{26,127,9860},{8,127,1157},{8,127,1157},{0,95,505},{0,102,9555},{0,87,4114},{65,127,1445},{65,127,1445},{65,127,1445},{54,124,1},{115,1,4418},{25,127,289},{25,127,289},{0,95,505},{126,54,4418},{0,95,505},{127,87,1352},{96,127,500},{88,127,0},
+{48,127,0},{127,87,1352},{126,108,1352},{48,127,0},{0,114,1352},{126,108,1352},{0,114,1352},{27,0,5941},{27,0,5941},{27,0,5941},{27,0,5941},{6,127,433},{6,127,433},{6,127,433},{0,80,1},{0,64,2248},{0,64,2248},{44,127,65535},{25,127,48594},{17,127,23861},{11,127,12725},{41,127,65535},{14,127,32517},{3,127,2601},{0,121,3706},{0,126,65535},{0,113,32750},{82,127,6098},{73,127,2966},{71,127,1649},{59,127,4},{127,36,9818},
+{46,127,3638},{34,127,445},{0,110,2137},{127,82,9818},{0,110,2137},{41,127,13349},{41,127,13349},{41,127,13349},{31,127,7380},{29,127,11310},{11,127,1973},{11,127,1973},{0,101,405},{0,108,10181},{0,93,4410},{71,127,1649},{71,127,1649},{71,127,1649},{59,127,4},{122,0,4418},{34,127,445},{34,127,445},{0,101,405},{126,61,4418},{0,101,405},{127,93,925},{102,127,337},{95,127,0},{62,127,0},{127,93,925},{126,111,925},{62,127,0},
+{0,116,925},{126,111,925},{0,116,925},{29,0,6964},{29,0,6964},{29,0,6964},{29,0,6964},{9,127,808},{9,127,808},{9,127,808},{0,87,0},{0,70,2645},{0,70,2645},{44,127,65535},{25,127,51330},{17,127,27013},{11,127,14917},{41,127,65535},{14,127,33397},{4,127,3805},{0,121,2618},{1,126,65535},{0,113,32078},{88,127,5594},{79,127,2891},{74,127,1825},{64,127,45},{127,43,8901},{54,127,3373},{40,127,605},{0,115,1538},{127,86,8901},
+{0,115,1538},{44,127,15117},{44,127,15117},{44,127,15117},{34,127,8664},{32,127,12746},{14,127,2881},{14,127,2881},{0,104,317},{0,113,10694},{0,96,4714},{74,127,1825},{74,127,1825},{74,127,1825},{64,127,45},{127,2,4418},{40,127,605},{40,127,605},{0,104,317},{127,66,4418},{0,104,317},{127,99,613},{105,127,221},{101,127,0},{73,127,0},{127,99,613},{126,114,613},{73,127,0},{0,118,613},{126,114,613},{0,118,613},{31,0,7940},
+{31,0,7940},{31,0,7940},{31,0,7940},{9,127,1224},{9,127,1224},{9,127,1224},{0,93,0},{0,76,3029},{0,76,3029},{49,127,65535},{25,127,54322},{17,127,30421},{13,127,17348},{44,127,65535},{14,127,34533},{5,127,5245},{0,123,1705},{2,127,65535},{0,113,31662},{91,127,5146},{82,127,2950},{79,127,1994},{67,127,145},{127,53,8069},{60,127,3125},{46,127,797},{0,117,1025},{126,91,8069},{0,117,1025},{49,127,16984},{49,127,16984},{49,127,16984},
+{37,127,10100},{35,127,14318},{16,127,3981},{16,127,3981},{0,110,245},{0,119,11302},{0,102,5034},{79,127,1994},{79,127,1994},{79,127,1994},{67,127,145},{127,14,4418},{46,127,797},{46,127,797},{0,110,245},{127,72,4418},{0,110,245},{127,105,365},{111,127,136},{107,127,0},{86,127,0},{127,105,365},{126,117,365},{86,127,0},{0,120,365},{126,117,365},{0,120,365},{33,0,8980},{33,0,8980},{33,0,8980},{33,0,8980},{12,127,1732},
+{12,127,1732},{12,127,1732},{0,99,0},{0,81,3385},{0,81,3385},{49,127,65535},{28,127,54246},{20,127,31809},{16,127,18396},{49,127,65535},{19,127,34118},{8,127,6285},{3,124,1078},{2,127,65535},{0,116,27154},{94,127,4770},{86,127,2986},{82,127,2210},{73,127,281},{127,60,7322},{67,127,2945},{54,127,1037},{0,118,614},{127,94,7322},{0,118,614},{52,127,17772},{52,127,17772},{52,127,17772},{40,127,10764},{38,127,15150},{22,127,4785},{22,127,4785},
+{1,113,218},{0,125,10994},{0,105,4594},{82,127,2210},{82,127,2210},{82,127,2210},{73,127,281},{127,27,4418},{54,127,1037},{54,127,1037},{0,114,193},{126,78,4418},{0,114,193},{127,111,181},{116,127,65},{113,127,0},{98,127,0},{127,111,181},{126,120,181},{98,127,0},{0,122,181},{126,120,181},{0,122,181},{37,0,9248},{37,0,9248},{37,0,9248},{37,0,9248},{17,127,2009},{17,127,2009},{17,127,2009},{3,104,0},{0,87,3177},
+{0,87,3177},{52,127,65535},{34,127,52995},{26,127,32522},{21,127,19126},{49,127,65535},{22,127,32935},{13,127,7330},{7,125,605},{2,127,64493},{0,116,21205},{97,127,4436},{91,127,3044},{88,127,2440},{79,127,505},{127,69,6584},{73,127,2811},{63,127,1313},{0,121,292},{126,99,6584},{0,121,292},{55,127,18275},{55,127,18275},{55,127,18275},{46,127,11259},{44,127,15797},{28,127,5606},{28,127,5606},{6,118,217},{0,125,10589},{0,113,3809},{88,127,2440},
+{88,127,2440},{88,127,2440},{79,127,505},{127,40,4418},{63,127,1313},{63,127,1313},{0,118,128},{126,85,4418},{0,118,128},{127,119,50},{122,127,18},{119,127,1},{111,127,0},{127,119,50},{127,123,50},{111,127,0},{0,124,52},{127,123,50},{0,124,52},{41,0,9250},{41,0,9250},{41,0,9250},{41,0,9250},{20,127,2225},{20,127,2225},{20,127,2225},{8,108,1},{0,93,2741},{0,93,2741},{55,127,65535},{37,127,52035},{29,127,33226},
+{25,127,19751},{52,127,65535},{28,127,31983},{18,127,8346},{11,126,349},{2,127,60061},{0,119,16605},{100,127,4216},{97,127,3140},{94,127,2664},{84,127,776},{127,76,6019},{76,127,2779},{70,127,1586},{0,124,116},{126,103,6019},{0,124,116},{61,127,18739},{61,127,18739},{61,127,18739},{51,127,11794},{49,127,16315},{31,127,6398},{31,127,6398},{10,122,217},{2,127,10565},{0,116,3213},{94,127,2664},{94,127,2664},{94,127,2664},{84,127,776},{127,53,4418},
+{70,127,1586},{70,127,1586},{0,124,80},{126,91,4418},{0,124,80},{127,125,2},{127,126,2},{125,127,1},{124,127,0},{127,125,2},{127,126,2},{124,127,0},{0,126,4},{127,126,2},{0,126,4},{45,0,9250},{45,0,9250},{45,0,9250},{45,0,9250},{26,127,2441},{26,127,2441},{26,127,2441},{12,112,1},{0,102,2377},{0,102,2377},{58,127,65535},{40,127,49743},{35,127,32390},{28,127,19671},{55,127,65535},{31,127,30383},{22,127,8522},
+{15,126,198},{2,127,55505},{0,122,12609},{103,127,3648},{100,127,2776},{97,127,2384},{87,127,740},{127,83,5163},{84,127,2468},{73,127,1450},{0,127,16},{126,106,5163},{0,127,16},{65,127,18185},{65,127,18185},{65,127,18185},{54,127,11714},{52,127,15699},{37,127,6486},{37,127,6486},{14,124,126},{2,127,9785},{0,119,2501},{97,127,2384},{97,127,2384},{97,127,2384},{87,127,740},{127,60,3872},{73,127,1450},{73,127,1450},{0,126,13},{127,94,3872},
+{0,126,13},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{49,0,9250},{49,0,9250},{49,0,9250},{49,0,9250},{29,127,2665},{29,127,2665},{29,127,2665},{16,116,1},{0,108,2041},{0,108,2041},{61,127,65535},{46,127,47079},{38,127,31046},{33,127,19370},{58,127,65535},{34,127,28647},{25,127,8458},{19,126,78},{2,127,51393},{0,122,9105},{106,127,3012},
+{100,127,2296},{100,127,1972},{90,127,612},{127,86,4267},{87,127,2028},{76,127,1210},{5,127,0},{127,107,4267},{5,127,0},{65,127,17289},{65,127,17289},{65,127,17289},{57,127,11462},{55,127,14739},{40,127,6374},{40,127,6374},{18,125,50},{2,127,8937},{0,122,1881},{100,127,1972},{100,127,1972},{100,127,1972},{90,127,612},{127,66,3200},{76,127,1210},{76,127,1210},{5,127,0},{127,97,3200},{5,127,0},{127,127,0},{127,127,0},{127,127,0},
+{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{53,0,9250},{53,0,9250},{53,0,9250},{53,0,9250},{35,127,2897},{35,127,2897},{35,127,2897},{20,120,1},{0,116,1693},{0,116,1693},{65,127,65535},{48,127,44233},{41,127,29640},{37,127,18961},{61,127,65535},{40,127,26823},{30,127,8416},{24,127,9},{8,127,47133},{0,122,6081},{109,127,2377},{103,127,1809},{103,127,1553},{96,127,481},{127,90,3361},
+{90,127,1593},{84,127,953},{19,127,0},{127,109,3361},{19,127,0},{71,127,16331},{71,127,16331},{71,127,16331},{63,127,11212},{61,127,13721},{46,127,6266},{46,127,6266},{24,126,8},{5,127,8245},{0,125,1397},{103,127,1553},{103,127,1553},{103,127,1553},{96,127,481},{127,72,2521},{84,127,953},{84,127,953},{19,127,0},{127,100,2521},{19,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},
+{0,127,0},{127,127,0},{0,127,0},{58,0,9248},{58,0,9248},{58,0,9248},{58,0,9248},{41,127,3181},{41,127,3181},{41,127,3181},{24,125,0},{0,125,1381},{0,125,1381},{65,127,65535},{51,127,41789},{44,127,28480},{40,127,18673},{65,127,65535},{43,127,25251},{34,127,8410},{28,127,4},{14,127,43557},{0,125,4005},{111,127,1843},{106,127,1421},{106,127,1225},{99,127,373},{127,95,2646},{96,127,1241},{90,127,745},{31,127,0},{127,111,2646},
+{31,127,0},{74,127,15539},{74,127,15539},{74,127,15539},{64,127,10979},{65,127,12914},{51,127,6216},{51,127,6216},{28,127,4},{11,127,7709},{0,126,1217},{106,127,1225},{106,127,1225},{106,127,1225},{99,127,373},{127,78,1985},{90,127,745},{90,127,745},{31,127,0},{127,103,1985},{31,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{62,0,9248},
+{62,0,9248},{62,0,9248},{62,0,9248},{44,127,3425},{44,127,3425},{44,127,3425},{28,127,4},{0,125,1205},{0,125,1205},{68,127,65535},{54,127,39465},{49,127,27209},{46,127,18393},{65,127,64563},{46,127,23799},{38,127,8426},{32,127,64},{14,127,40437},{0,125,2677},{111,127,1411},{111,127,1070},{109,127,937},{102,127,281},{127,99,2017},{99,127,937},{93,127,565},{43,127,0},{126,114,2017},{43,127,0},{77,127,14795},{77,127,14795},{77,127,14795},
+{70,127,10779},{68,127,12146},{54,127,6176},{54,127,6176},{34,127,52},{14,127,7281},{2,127,1213},{109,127,937},{109,127,937},{109,127,937},{102,127,281},{127,84,1513},{93,127,565},{93,127,565},{43,127,0},{127,106,1513},{43,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{65,0,9250},{65,0,9250},{65,0,9250},{65,0,9250},{49,127,3656},
+{49,127,3656},{49,127,3656},{34,127,52},{2,127,1213},{2,127,1213},{71,127,63180},{60,127,37225},{52,127,26137},{48,127,18128},{68,127,59595},{51,127,22636},{42,127,8480},{37,127,164},{22,127,37455},{0,126,2073},{114,127,1019},{111,127,766},{111,127,666},{105,127,205},{127,102,1473},{102,127,681},{99,127,405},{56,127,0},{127,115,1473},{56,127,0},{79,127,14066},{79,127,14066},{79,127,14066},{73,127,10571},{71,127,11450},{59,127,6166},{59,127,6166},
+{37,127,148},{25,127,6914},{5,127,1413},{111,127,666},{111,127,666},{111,127,666},{105,127,205},{127,90,1105},{99,127,405},{99,127,405},{56,127,0},{127,109,1105},{56,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{69,0,9250},{69,0,9250},{69,0,9250},{69,0,9250},{52,127,3940},{52,127,3940},{52,127,3940},{37,127,148},{5,127,1413},
+{5,127,1413}, \ No newline at end of file
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m6.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m6.inc
new file mode 100644
index 0000000000..6b814e6132
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_bc7_m6.inc
@@ -0,0 +1,4383 @@
+// Copyright (C) 2017-2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+static const uint32_t g_etc1_to_bc7_m6_table0[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x80000,0x80000,0x1,0x40000,0x40000,0x40000,0x80000,0x80000,0x1,0x80000,0x80000,0x1,0x1,0x40000,0x40000,0x40000,0x80000,0x80000,0x1,0x80000,0x80000,0x1,0x1,0x80000,
+0x80000,0x1,0x1,0x1,0x40000,0x40000,0x40000,0x40000,0x40000,0x80000,0x80000,0x80000,0x40000,0x40000,0x80000,0x1,0x80000,0x100000,0x180000,0x2C0000,0x6000001,0x180000,0x2C0000,0x6000001,0x2C0000,0x6000001,0x6000001,0x180000,0x2C0000,0x6000001,0x2C0000,0x6000001,
+0x6000001,0x2C0000,0x6000001,0x6000001,0x6000001,0x180000,0x2C0000,0x6000001,0x2C0000,0x6000001,0x6000001,0x2C0000,0x6000001,0x6000001,0x6000001,0x2C0000,0x6000001,0x6000001,0x6000001,0x6000001,0x140000,0x100000,0x100000,0x180000,0x240000,0x440000,0x6000001,0x6000001,0x140000,0x1C0000,0xD40000,0x6000001,
+0x200000,0x4002C,0x16000004,0xA000005,0x6000005,0xE000012,0x8000005,0x6000001,0x6000012,0x400000A,0x4000012,0x8000023,0x600000D,0x6000005,0x6000016,0x400000E,0x4000016,0x4000023,0x4000013,0x400001B,0x2000023,0x4002C,0x6000011,0x6000009,0x600001A,0x4000012,0x400001A,0x2040027,0x4000017,0x200001F,0x2000024,0x8002C,
+0x400001C,0x2000022,0x2000027,0x200002C,0x1600000B,0x48000012,0x78000004,0xE00000C,0xA000009,0x600000C,0x6000009,0x4000011,0x1000000F,0xA000012,0x4000013,0x200001F,0x8002C,0x80024,0x12040004,0xA040004,0x6000005,0xE000012,0x8000005,0x6000001,0x6000012,0x400000A,0x4000012,0x80023,0x600000D,0x6000005,0x6000016,0x400000E,
+0x4000016,0xC0023,0x4000013,0x400001B,0x2000023,0x80023,0x600000D,0x6000005,0x6000016,0x400000E,0x4000016,0xC0023,0x4000013,0x400001B,0x2000023,0xC0023,0x4000013,0x400001B,0x2000023,0x2000023,0x1600000B,0x48000012,0x5A040004,0xE00000C,0xA000009,0x600000C,0x6000009,0x4000011,0x1000000E,0xA000011,0x4000013,0x400001B,
+0xC0023,0x4,0x4,0x4,0x4,0x4000000,0x4000000,0x4000000,0x2000000,0x2000000,0x1,0x2000002,0x2000002,0x2000002,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2000003,0x2000003,0x2000003,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x3,
+0x3,0x3,0x3,0x3,0x4000001,0x18000000,0x4,0x2000001,0x4000001,0x1,0x1,0x1,0x2000001,0x4000001,0x2,0x2,0x3,0x4,0x4,0x4,0x4,0x4000000,0x4000000,0x4000000,0x2000000,0x2000000,0x1,0x2000002,0x2000002,0x2000002,0x1,0x1,
+0x1,0x2,0x2,0x2,0x2,0x2000002,0x2000002,0x2000002,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x4000001,0x18000000,0x4,0x2000001,0x4000001,0x1,0x1,0x1,0x2000001,0x4000001,0x2,0x2,
+0x2,0x80014,0x12040000,0xA040000,0x6040001,0x20C0012,0x8000005,0x6000001,0x180012,0x400000A,0x4000012,0x20C0012,0x8000005,0x6000001,0x180012,0x400000A,0x4000012,0x180012,0x400000A,0x4000012,0x4000012,0x20C0012,0x8000005,0x6000001,0x180012,0x400000A,0x4000012,0x180012,0x400000A,0x4000012,0x4000012,0x180012,
+0x400000A,0x4000012,0x4000012,0x4000012,0x1C000008,0xC080012,0x5A040000,0xA040008,0xA000005,0x6000008,0x6000005,0x600000A,0x14000008,0xC000008,0x6000005,0x4000012,0x140012,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table1[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0x100000,0x100000,0x100000,0x100000,0x100000,
+0x100000,0x200000,0x200000,0x200000,0x4000001,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x200000,0x200000,0x200000,0x4000001,0x200000,0x200000,0x200000,0x4000001,0x4000001,0xC0000,0xC0000,0xC0000,0x20C0000,0x40C0000,0x100000,0x100000,0x140000,0x20C0000,0x40C0000,0x180000,0x200000,
+0x180000,0x140000,0x140000,0x140000,0x140000,0x1C0000,0x1C0000,0x1C0000,0x380000,0x380000,0x8000001,0x1C0000,0x1C0000,0x1C0000,0x380000,0x380000,0x8000001,0x380000,0x380000,0x8000001,0x8000001,0x1C0000,0x1C0000,0x1C0000,0x380000,0x380000,0x8000001,0x380000,0x380000,0x8000001,0x8000001,0x380000,
+0x380000,0x8000001,0x8000001,0x8000001,0x180000,0x2140000,0x140000,0x2180000,0x200000,0x280000,0x2C0000,0x440000,0x180000,0x1C0000,0x280000,0x8000001,0x280000,0x200000,0x300000,0x5C0000,0xE000001,0x300000,0x5C0000,0xE000001,0x5C0000,0xE000001,0xE000001,0x300000,0x5C0000,0xE000001,0x5C0000,0xE000001,
+0xE000001,0x5C0000,0xE000001,0xE000001,0xE000001,0x300000,0x5C0000,0xE000001,0x5C0000,0xE000001,0xE000001,0x5C0000,0xE000001,0xE000001,0xE000001,0x5C0000,0xE000001,0xE000001,0xE000001,0xE000001,0x280000,0x8200000,0x8200000,0x340000,0x4C0000,0x940000,0xE000001,0xE000001,0x2C0000,0x3C0000,0x1D40000,0xE000001,
+0x400000,0x100088,0x220C0034,0x140C0034,0xE0C0035,0x1E080026,0x14080015,0xE080019,0x10080026,0xE040016,0xC040026,0x20000033,0x16000009,0x1004000F,0x12000012,0xE000002,0xC000016,0x10000033,0xE000011,0xA00001B,0xA000033,0x180088,0x1200003D,0xE000034,0x12000036,0xE00001B,0xC000026,0xC00004B,0xC000023,0xA00002B,0xA000043,0x2C0088,
+0xA000054,0xA00004C,0x800005F,0x600008C,0x48000002,0x8C080026,0x9E0C0034,0x26000001,0x18000002,0x12000002,0x10000002,0xE000002,0x3200000E,0x1E000005,0x1000000B,0xA00002B,0x200088,0x140034,0x1E100008,0x12100009,0xE100009,0x1A0C0012,0x120C0001,0x100C0001,0x100C0012,0xE0C0005,0xC0C0012,0x200033,0x14040009,0xE080009,0x12000012,0xE000002,
+0xC040012,0x3C0033,0xE000011,0xA00001B,0xA000033,0x200033,0x14040009,0xE080009,0x12000012,0xE000002,0xC040012,0x3C0033,0xE000011,0xA00001B,0xA000033,0x3C0033,0xE000011,0xA00001B,0xA000033,0xA000033,0x44040001,0x6E0C0012,0x80100008,0x20040001,0x18000002,0x12000002,0xE040002,0xE000002,0x32000005,0x1E000001,0x1000000A,0xA00001B,
+0x2C0033,0xC0034,0xC0034,0xC0034,0xC0034,0x14080014,0x14080014,0x14080014,0xC080014,0xC080014,0x8040015,0x16000008,0x16000008,0x16000008,0xE000001,0xE000001,0xA000005,0xA00000A,0xA00000A,0x8000001,0x600000A,0x20C0033,0x20C0033,0x20C0033,0xC000015,0xC000015,0x8000013,0x8000019,0x8000019,0x800000A,0x600000E,0x180033,
+0x180033,0x6000023,0x4000023,0x4000033,0x48000001,0x5C080014,0xC0034,0x24000001,0x18000001,0x12000001,0x10000001,0xC000001,0x24000009,0x1C000004,0xE000009,0x800000A,0x140033,0x100008,0x100008,0x100008,0x100008,0x100C0000,0x100C0000,0x100C0000,0xA0C0001,0xA0C0001,0x80C0001,0x180008,0x180008,0x180008,0xA080001,0xA080001,
+0x8080001,0x2C0008,0x2C0008,0x8000001,0x600000A,0x180008,0x180008,0x180008,0xA080001,0xA080001,0x8080001,0x2C0008,0x2C0008,0x8000001,0x600000A,0x2C0008,0x2C0008,0x8000001,0x600000A,0x600000A,0x3A040000,0x3E0C0000,0x100008,0x1E040000,0x14040000,0x10040000,0xC080001,0xC040000,0x26040001,0x1C000000,0x200008,0x8000001,
+0x200008,0x180014,0x1A140000,0x12140000,0xE140001,0x2240012,0x120C0001,0xE100001,0x4C0012,0xE000001,0xC000012,0x2240012,0x120C0001,0xE100001,0x4C0012,0xE000001,0xC000012,0x4C0012,0xE000001,0xC000012,0xC000012,0x2240012,0x120C0001,0xE100001,0x4C0012,0xE000001,0xC000012,0x4C0012,0xE000001,0xC000012,0xC000012,0x4C0012,
+0xE000001,0xC000012,0xC000012,0xC000012,0x44040001,0x1C0012,0x62140000,0x26000000,0x18000001,0x12000001,0xE040001,0xE000002,0x36000002,0x1E000001,0x10040000,0xC000012,0x340012,0x40014,0x40014,0x40014,0x40014,0x40014,0x40014,0x40014,0x40014,0x40014,0x40014,0x10000000,0x10000000,0x10000000,0x10000000,0x10000000,
+0x10000000,0x8000000,0x8000000,0x8000000,0x4000001,0x80012,0x80012,0x80012,0x80012,0x80012,0x80012,0x6000005,0x6000005,0x6000005,0x4000005,0xC0012,0xC0012,0xC0012,0x400000A,0x2000012,0x58000000,0x40014,0x40014,0x28000000,0x1C000000,0x14000000,0x14000000,0xE000000,0x20000005,0x16000002,0xA000001,0x6000005,
+0xC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table2[] = {
+0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x2C0000,
+0x2C0000,0x2C0000,0x2C0000,0x6000001,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x180000,0x200000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x280000,0x280000,0x280000,0x280000,0x280000,
+0x280000,0x500000,0x500000,0x500000,0xC000001,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x500000,0x500000,0x500000,0xC000001,0x500000,0x500000,0x500000,0xC000001,0xC000001,0x61C0000,0x1C0000,0x1C0000,0x200000,0x4200000,0x2240000,0x2240000,0x22C0000,0x200000,0x4200000,0x380000,0x500000,
+0x380000,0x240000,0x240000,0x240000,0x240000,0x340000,0x340000,0x340000,0x680000,0x680000,0x10000001,0x340000,0x340000,0x340000,0x680000,0x680000,0x10000001,0x680000,0x680000,0x10000001,0x10000001,0x340000,0x340000,0x340000,0x680000,0x680000,0x10000001,0x680000,0x680000,0x10000001,0x10000001,0x680000,
+0x680000,0x10000001,0x10000001,0x10000001,0x2280000,0xA240000,0x240000,0x300000,0x3C0000,0x4C0000,0x540000,0x800000,0x2C0000,0x340000,0x4C0000,0x10000001,0x4C0000,0x300000,0x2440000,0x8C0000,0x16000001,0x2440000,0x8C0000,0x16000001,0x8C0000,0x16000001,0x16000001,0x2440000,0x8C0000,0x16000001,0x8C0000,0x16000001,
+0x16000001,0x8C0000,0x16000001,0x16000001,0x16000001,0x2440000,0x8C0000,0x16000001,0x8C0000,0x16000001,0x16000001,0x8C0000,0x16000001,0x16000001,0x16000001,0x8C0000,0x16000001,0x16000001,0x16000001,0x16000001,0x3C0000,0x340000,0x340000,0x500000,0x740000,0xE00000,0x16000001,0x16000001,0x400000,0x580000,0x9E40000,0x16000001,
+0x640000,0x200088,0x2A1C0034,0x1C1C0034,0x161C0035,0x26180026,0x1C180015,0x16180019,0x18180026,0x16140016,0x14140026,0x28100033,0x1E100009,0x1814000F,0x1A100012,0x16100002,0x14100016,0x18100033,0x160C000F,0x140C001A,0x12100033,0x300088,0x22040033,0x16100034,0x1C040026,0x18080013,0x140C0024,0x1A000035,0x1604000A,0x14000013,0x12040033,0x5C0088,
+0x1600003C,0x12000034,0x10000044,0xE00008C,0x50100002,0x94180026,0xA61C0034,0x2E100001,0x20100002,0x1A100002,0x18100002,0x16100002,0x4A080001,0x2A0C0001,0x180C0009,0x14000013,0x400088,0x240034,0x26200008,0x1A200009,0x16200009,0x221C0012,0x1A1C0001,0x181C0001,0x181C0012,0x161C0005,0x141C0012,0x380033,0x1C140009,0x16180009,0x1A100012,0x16100002,
+0x14140012,0x700033,0x16040009,0x14000012,0x12000033,0x380033,0x1C140009,0x16180009,0x1A100012,0x16100002,0x14140012,0x700033,0x16040009,0x14000012,0x12000033,0x700033,0x16040009,0x14000012,0x12000033,0x12000033,0x4C140001,0x761C0012,0x88200008,0x28140001,0x20100002,0x1A100002,0x16140002,0x160C0002,0x4A080001,0x26100001,0x180C0008,0x14000012,
+0x500033,0x1C0034,0x1C0034,0x1C0034,0x1C0034,0x1C180014,0x1C180014,0x1C180014,0x14180014,0x14180014,0x10140015,0x1E100008,0x1E100008,0x1E100008,0x16100001,0x16100001,0x12100005,0x1210000A,0x1210000A,0x10100001,0xE10000A,0x2240033,0x2240033,0x2240033,0x18080012,0x18080012,0x10100013,0x16040009,0x16040009,0x10080002,0xE08000A,0x4C0033,
+0x4C0033,0x10000013,0xE00000E,0xC000033,0x50100001,0x64180014,0x1C0034,0x2C100001,0x20100001,0x1A100001,0x18100001,0x14100001,0x48080000,0x2A0C0000,0x16100009,0x10080002,0x340033,0x200008,0x200008,0x200008,0x200008,0x181C0000,0x181C0000,0x181C0000,0x121C0001,0x121C0001,0x101C0001,0x300008,0x300008,0x300008,0x12180001,0x12180001,
+0x10180001,0x5C0008,0x5C0008,0x10100001,0xE00000A,0x300008,0x300008,0x300008,0x12180001,0x12180001,0x10180001,0x5C0008,0x5C0008,0x10100001,0xE00000A,0x5C0008,0x5C0008,0x10100001,0xE00000A,0xE00000A,0x42140000,0x461C0000,0x200008,0x26140000,0x1C140000,0x18140000,0x14180001,0x14140000,0x3E0C0000,0x24100000,0x400008,0x10100001,
+0x400008,0x280014,0x22240000,0x1A240000,0x16240001,0x23C0012,0x1A1C0001,0x16200001,0x7C0012,0x16100001,0x14000012,0x23C0012,0x1A1C0001,0x16200001,0x7C0012,0x16100001,0x14000012,0x7C0012,0x16100001,0x14000012,0x14000012,0x23C0012,0x1A1C0001,0x16200001,0x7C0012,0x16100001,0x14000012,0x7C0012,0x16100001,0x14000012,0x14000012,0x7C0012,
+0x16100001,0x14000012,0x14000012,0x14000012,0x5C0C0000,0x2C0012,0x6A240000,0x2E100000,0x20100001,0x1C0C0000,0x16140001,0x16080001,0x52040000,0x2E080000,0x18140000,0x14000012,0x580012,0x140014,0x140014,0x140014,0x140014,0x140014,0x140014,0x140014,0x140014,0x140014,0x140014,0x18100000,0x18100000,0x18100000,0x18100000,0x18100000,
+0x18100000,0x10100000,0x10100000,0x10100000,0xC100001,0x200012,0x200012,0x200012,0x200012,0x200012,0x200012,0x10080001,0x10080001,0x10080001,0xC0C0001,0x3C0012,0x3C0012,0x3C0012,0xC000002,0xA000012,0x60100000,0x140014,0x140014,0x30100000,0x24100000,0x1C100000,0x1C100000,0x16100000,0x48080000,0x2A0C0000,0x12100001,0x10080001,
+0x2C0012,};
+static const uint32_t g_etc1_to_bc7_m6_table3[] = {
+0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x5C0000,
+0x5C0000,0x5C0000,0x5C0000,0xE000001,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x8200000,0x8200000,0x8200000,0x300000,0x400000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x400000,0x400000,0x400000,0x400000,0x400000,
+0x400000,0x800000,0x800000,0x800000,0x14000001,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x800000,0x800000,0x800000,0x14000001,0x800000,0x800000,0x800000,0x14000001,0x14000001,0xE2C0000,0x2C0000,0x2C0000,0x340000,0x4340000,0x3C0000,0x3C0000,0x480000,0x340000,0x4340000,0x5C0000,0x800000,
+0x5C0000,0x340000,0x340000,0x340000,0x340000,0x4C0000,0x4C0000,0x4C0000,0x980000,0x980000,0x18000001,0x4C0000,0x4C0000,0x4C0000,0x980000,0x980000,0x18000001,0x980000,0x980000,0x18000001,0x18000001,0x4C0000,0x4C0000,0x4C0000,0x980000,0x980000,0x18000001,0x980000,0x980000,0x18000001,0x18000001,0x980000,
+0x980000,0x18000001,0x18000001,0x18000001,0x3C0000,0x380000,0x340000,0x2440000,0x2540000,0x6C0000,0x7C0000,0xBC0000,0x400000,0x4C0000,0x6C0000,0x18000001,0x6C0000,0x400000,0x25C0000,0xBC0000,0x1E000001,0x25C0000,0xBC0000,0x1E000001,0xBC0000,0x1E000001,0x1E000001,0x25C0000,0xBC0000,0x1E000001,0xBC0000,0x1E000001,
+0x1E000001,0xBC0000,0x1E000001,0x1E000001,0x1E000001,0x25C0000,0xBC0000,0x1E000001,0xBC0000,0x1E000001,0x1E000001,0xBC0000,0x1E000001,0x1E000001,0x1E000001,0xBC0000,0x1E000001,0x1E000001,0x1E000001,0x1E000001,0x500000,0x440000,0x440000,0x6C0000,0x9C0000,0x1300000,0x1E000001,0x1E000001,0x2540000,0x780000,0x11F40000,0x1E000001,
+0x880000,0x300088,0x322C0034,0x242C0034,0x1E2C0035,0x2E280026,0x24280015,0x1E280019,0x20280026,0x1E240016,0x1C240026,0x30200033,0x26200009,0x2024000F,0x22200012,0x1E200002,0x1C200016,0x20200033,0x1E1C000F,0x1C1C001A,0x1A200033,0x2440088,0x2A140033,0x1E200034,0x24140026,0x20180013,0x1C1C0024,0x240C0033,0x1E14000A,0x1C100013,0x1A140033,0x8C0088,
+0x1E000034,0x1C000024,0x1A000037,0x1600008C,0x58200002,0x9C280026,0xAE2C0034,0x36200001,0x28200002,0x22200002,0x20200002,0x1E200002,0x52180001,0x321C0001,0x201C0009,0x1C100013,0x640088,0x340034,0x2E300008,0x22300009,0x1E300009,0x2A2C0012,0x222C0001,0x202C0001,0x202C0012,0x1E2C0005,0x1C2C0012,0x500033,0x24240009,0x1E280009,0x22200012,0x1E200002,
+0x1C240012,0xA00033,0x1E140009,0x1C100012,0x1A000033,0x500033,0x24240009,0x1E280009,0x22200012,0x1E200002,0x1C240012,0xA00033,0x1E140009,0x1C100012,0x1A000033,0xA00033,0x1E140009,0x1C100012,0x1A000033,0x1A000033,0x54240001,0x7E2C0012,0x90300008,0x30240001,0x28200002,0x22200002,0x1E240002,0x1E1C0002,0x52180001,0x2E200001,0x201C0008,0x1C100012,
+0x700033,0x2C0034,0x2C0034,0x2C0034,0x2C0034,0x24280014,0x24280014,0x24280014,0x1C280014,0x1C280014,0x18240015,0x26200008,0x26200008,0x26200008,0x1E200001,0x1E200001,0x1A200005,0x1A20000A,0x1A20000A,0x18200001,0x1620000A,0x23C0033,0x23C0033,0x23C0033,0x20180012,0x20180012,0x18200013,0x1E140009,0x1E140009,0x18180002,0x1618000A,0x7C0033,
+0x7C0033,0x180C0013,0x1604000A,0x14000033,0x58200001,0x6C280014,0x2C0034,0x34200001,0x28200001,0x22200001,0x20200001,0x1C200001,0x50180000,0x321C0000,0x1E200009,0x18180002,0x580033,0x300008,0x300008,0x300008,0x300008,0x202C0000,0x202C0000,0x202C0000,0x1A2C0001,0x1A2C0001,0x182C0001,0x2440008,0x2440008,0x2440008,0x1A280001,0x1A280001,
+0x18280001,0x8C0008,0x8C0008,0x18200001,0x1600000A,0x2440008,0x2440008,0x2440008,0x1A280001,0x1A280001,0x18280001,0x8C0008,0x8C0008,0x18200001,0x1600000A,0x8C0008,0x8C0008,0x18200001,0x1600000A,0x1600000A,0x4A240000,0x4E2C0000,0x300008,0x2E240000,0x24240000,0x20240000,0x1C280001,0x1C240000,0x461C0000,0x2C200000,0x640008,0x18200001,
+0x640008,0x380014,0x2A340000,0x22340000,0x1E340001,0x540012,0x222C0001,0x1E300001,0xAC0012,0x1E200001,0x1C000012,0x540012,0x222C0001,0x1E300001,0xAC0012,0x1E200001,0x1C000012,0xAC0012,0x1E200001,0x1C000012,0x1C000012,0x540012,0x222C0001,0x1E300001,0xAC0012,0x1E200001,0x1C000012,0xAC0012,0x1E200001,0x1C000012,0x1C000012,0xAC0012,
+0x1E200001,0x1C000012,0x1C000012,0x1C000012,0x641C0000,0x63C0012,0x72340000,0x36200000,0x28200001,0x241C0000,0x1E240001,0x1E180001,0x5A140000,0x36180000,0x20240000,0x1C000012,0x780012,0x240014,0x240014,0x240014,0x240014,0x240014,0x240014,0x240014,0x240014,0x240014,0x240014,0x20200000,0x20200000,0x20200000,0x20200000,0x20200000,
+0x20200000,0x18200000,0x18200000,0x18200000,0x14200001,0x380012,0x380012,0x380012,0x380012,0x380012,0x380012,0x18180001,0x18180001,0x18180001,0x141C0001,0x700012,0x700012,0x700012,0x140C0001,0x12000012,0x68200000,0x240014,0x240014,0x38200000,0x2C200000,0x24200000,0x24200000,0x1E200000,0x50180000,0x321C0000,0x1A200001,0x18180001,
+0x500012,};
+static const uint32_t g_etc1_to_bc7_m6_table4[] = {
+0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x940000,
+0x940000,0x940000,0x940000,0x18000000,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x2340000,0x2340000,0x2340000,0x480000,0x680000,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,
+0x5C0000,0xB80000,0xB80000,0xB80000,0x1E000000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0xB80000,0xB80000,0xB80000,0x1E000000,0xB80000,0xB80000,0xB80000,0x1E000000,0x1E000000,0x8400000,0x3C0001,0x3C0001,0x480000,0x24C0000,0x540000,0x540000,0x680000,0x480000,0x24C0000,0x800000,0xB80000,
+0x800000,0x440001,0x440001,0x440001,0x440001,0x680000,0x680000,0x680000,0xD00000,0xD00000,0x22000000,0x680000,0x680000,0x680000,0xD00000,0xD00000,0x22000000,0xD00000,0xD00000,0x22000000,0x22000000,0x680000,0x680000,0x680000,0xD00000,0xD00000,0x22000000,0xD00000,0xD00000,0x22000000,0x22000000,0xD00000,
+0xD00000,0x22000000,0x22000000,0x22000000,0x500000,0xC480000,0x440001,0x25C0000,0x740000,0x940000,0xA80000,0x1000000,0x580000,0x680000,0x940000,0x22000000,0x940000,0x500001,0x780000,0xF40000,0x28000000,0x780000,0xF40000,0x28000000,0xF40000,0x28000000,0x28000000,0x780000,0xF40000,0x28000000,0xF40000,0x28000000,
+0x28000000,0xF40000,0x28000000,0x28000000,0x28000000,0x780000,0xF40000,0x28000000,0xF40000,0x28000000,0x28000000,0xF40000,0x28000000,0x28000000,0x28000000,0xF40000,0x28000000,0x28000000,0x28000000,0x28000000,0x4640000,0x580000,0x580000,0x880000,0xC80000,0x1880000,0x28000000,0x28000000,0x700000,0x980000,0x1BE80000,0x28000000,
+0xAC0000,0x40008C,0x3E3C0033,0x2E3C0033,0x283C0033,0x38380024,0x2E380013,0x2A38001A,0x2A380024,0x26380016,0x24380026,0x36340034,0x2E34000A,0x2A34000F,0x2C300013,0x28300002,0x24340016,0x28340034,0x2630000F,0x24300019,0x22300035,0x600088,0x32280033,0x28300033,0x2C280026,0x282C0012,0x24300026,0x2E1C0033,0x28200009,0x24240015,0x22280034,0xC40088,
+0x280C0033,0x24140026,0x22080034,0x20000088,0x62340002,0xB4380024,0xC63C0033,0x3C340002,0x30340002,0x2A340002,0x28340002,0x28300002,0x5E280001,0x3E2C0001,0x28300009,0x24240015,0x8C0088,0x480033,0x3644000A,0x2C40000A,0x2840000A,0x30400013,0x2C3C0002,0x28400001,0x28400013,0x283C0005,0x243C0015,0x2680033,0x2E340009,0x2838000A,0x2C300012,0x28300001,
+0x24380014,0xD80033,0x28200008,0x24240014,0x22000034,0x2680033,0x2E340009,0x2838000A,0x2C300012,0x28300001,0x24380014,0xD80033,0x28200008,0x24240014,0x22000034,0xD80033,0x28200008,0x24240014,0x22000034,0x22000034,0x62340001,0x78400013,0x8A44000A,0x3C340001,0x30340001,0x2A340001,0x28340001,0x28300001,0x5E280001,0x3A300001,0x28300009,0x24240014,
+0x980033,0x3C0033,0x3C0033,0x3C0033,0x3C0033,0x30380012,0x30380012,0x30380012,0x26380012,0x26380012,0x22380012,0x2E340009,0x2E340009,0x2E340009,0x26340002,0x26340002,0x22340005,0x24300009,0x24300009,0x22300001,0x20300009,0x580033,0x580033,0x580033,0x282C0012,0x282C0012,0x22300012,0x26280009,0x26280009,0x22280001,0x20280009,0xB00033,
+0xB00033,0x221C0012,0x20100008,0x1E000034,0x56340002,0x84380012,0x3C0033,0x3A340001,0x30340001,0x2A340001,0x28340002,0x26300002,0x5E280000,0x38300001,0x28300008,0x22280001,0x7C0033,0x40000A,0x40000A,0x40000A,0x40000A,0x28400001,0x28400001,0x28400001,0x243C0001,0x243C0001,0x223C0001,0x600008,0x600008,0x600008,0x24380001,0x24380001,
+0x22380001,0xC40008,0xC40008,0x222C0000,0x20000008,0x600008,0x600008,0x600008,0x24380001,0x24380001,0x22380001,0xC40008,0xC40008,0x222C0000,0x20000008,0xC40008,0xC40008,0x222C0000,0x20000008,0x20000008,0x4A380000,0x48400001,0x40000A,0x3A340000,0x2C380000,0x28380000,0x26380000,0x24380001,0x4C300000,0x34340000,0x8C0008,0x222C0000,
+0x8C0008,0x4C0012,0x32480001,0x2A480001,0x28440001,0x700012,0x2C3C0001,0x28400000,0xE40012,0x282C0000,0x24000014,0x700012,0x2C3C0001,0x28400000,0xE40012,0x282C0000,0x24000014,0xE40012,0x282C0000,0x24000014,0x24000014,0x700012,0x2C3C0001,0x28400000,0xE40012,0x282C0000,0x24000014,0xE40012,0x282C0000,0x24000014,0x24000014,0xE40012,
+0x282C0000,0x24000014,0x24000014,0x24000014,0x722C0000,0x500012,0x6C480001,0x40300000,0x30340001,0x2C300000,0x28340000,0x28240000,0x66240000,0x3E2C0000,0x28380001,0x24000014,0xA00012,0x380012,0x380012,0x380012,0x380012,0x380012,0x380012,0x380012,0x380012,0x380012,0x380012,0x28340001,0x28340001,0x28340001,0x28340001,0x28340001,
+0x28340001,0x20340001,0x20340001,0x20340001,0x1E300001,0x2500012,0x2500012,0x2500012,0x2500012,0x2500012,0x2500012,0x22280001,0x22280001,0x22280001,0x1E2C0000,0xA40012,0xA40012,0xA40012,0x1E180000,0x1A000014,0x62340001,0x380012,0x380012,0x3A340001,0x30340001,0x2A340001,0x2A340001,0x26340001,0x5E280000,0x402C0000,0x24300000,0x22280001,
+0x740012,};
+static const uint32_t g_etc1_to_bc7_m6_table5[] = {
+0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0xC40000,
+0xC40000,0xC40000,0xC40000,0x20000000,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0xA440000,0xA440000,0xA440000,0x600000,0x8C0000,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x740000,0x740000,0x740000,0x740000,0x740000,
+0x740000,0xE80000,0xE80000,0xE80000,0x26000000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0xE80000,0xE80000,0xE80000,0x26000000,0xE80000,0xE80000,0xE80000,0x26000000,0x26000000,0x540000,0x4C0001,0x4C0001,0x4580000,0x2600000,0x2680000,0x2680000,0x2800000,0x4580000,0x2600000,0xA40000,0xE80000,
+0xA40000,0x540001,0x540001,0x540001,0x540001,0x800000,0x800000,0x800000,0x1000000,0x1000000,0x2A000000,0x800000,0x800000,0x800000,0x1000000,0x1000000,0x2A000000,0x1000000,0x1000000,0x2A000000,0x2A000000,0x800000,0x800000,0x800000,0x1000000,0x1000000,0x2A000000,0x1000000,0x1000000,0x2A000000,0x2A000000,0x1000000,
+0x1000000,0x2A000000,0x2A000000,0x2A000000,0x640000,0x5C0000,0x540001,0x740000,0x900000,0xB40000,0xD00000,0x13C0000,0x6C0000,0x800000,0xB40000,0x2A000000,0xB40000,0x600001,0x900000,0x1240000,0x30000000,0x900000,0x1240000,0x30000000,0x1240000,0x30000000,0x30000000,0x900000,0x1240000,0x30000000,0x1240000,0x30000000,
+0x30000000,0x1240000,0x30000000,0x30000000,0x30000000,0x900000,0x1240000,0x30000000,0x1240000,0x30000000,0x30000000,0x1240000,0x30000000,0x30000000,0x30000000,0x1240000,0x30000000,0x30000000,0x30000000,0x30000000,0x4780000,0x680000,0x680000,0xA40000,0xEC0000,0x1D80000,0x30000000,0x30000000,0x840000,0xB80000,0x23F80000,0x30000000,
+0xD00000,0x50008C,0x464C0033,0x364C0033,0x304C0033,0x40480024,0x36480013,0x3248001A,0x32480024,0x2E480016,0x2C480026,0x3E440034,0x3644000A,0x3244000F,0x34400013,0x30400002,0x2C440016,0x30440034,0x2E40000F,0x2C400019,0x2A400035,0x780088,0x3A380033,0x30400033,0x34380026,0x303C0012,0x2C400026,0x362C0033,0x30300009,0x2C340015,0x2A380034,0xF40088,
+0x301C0033,0x2C240026,0x2A180034,0x28000088,0x6A440002,0xBC480024,0xCE4C0033,0x44440002,0x38440002,0x32440002,0x30440002,0x30400002,0x66380001,0x463C0001,0x30400009,0x2C340015,0xAC0088,0x580033,0x3E54000A,0x3450000A,0x3050000A,0x38500013,0x344C0002,0x30500001,0x30500013,0x304C0005,0x2C4C0015,0x2800033,0x36440009,0x3048000A,0x34400012,0x30400001,
+0x2C480014,0x1080033,0x30300008,0x2C340014,0x2A000034,0x2800033,0x36440009,0x3048000A,0x34400012,0x30400001,0x2C480014,0x1080033,0x30300008,0x2C340014,0x2A000034,0x1080033,0x30300008,0x2C340014,0x2A000034,0x2A000034,0x6A440001,0x80500013,0x9254000A,0x44440001,0x38440001,0x32440001,0x30440001,0x30400001,0x66380001,0x42400001,0x30400009,0x2C340014,
+0xB80033,0x4C0033,0x4C0033,0x4C0033,0x4C0033,0x38480012,0x38480012,0x38480012,0x2E480012,0x2E480012,0x2A480012,0x36440009,0x36440009,0x36440009,0x2E440002,0x2E440002,0x2A440005,0x2C400009,0x2C400009,0x2A400001,0x28400009,0x700033,0x700033,0x700033,0x303C0012,0x303C0012,0x2A400012,0x2E380009,0x2E380009,0x2A380001,0x28380009,0xE40033,
+0xE40033,0x2A2C0012,0x28200008,0x26000034,0x5E440002,0x8C480012,0x4C0033,0x42440001,0x38440001,0x32440001,0x30440002,0x2E400002,0x66380000,0x40400001,0x30400008,0x2A380001,0xA00033,0x50000A,0x50000A,0x50000A,0x50000A,0x30500001,0x30500001,0x30500001,0x2C4C0001,0x2C4C0001,0x2A4C0001,0x780008,0x780008,0x780008,0x2C480001,0x2C480001,
+0x2A480001,0xF40008,0xF40008,0x2A3C0000,0x28000008,0x780008,0x780008,0x780008,0x2C480001,0x2C480001,0x2A480001,0xF40008,0xF40008,0x2A3C0000,0x28000008,0xF40008,0xF40008,0x2A3C0000,0x28000008,0x28000008,0x52480000,0x50500001,0x50000A,0x42440000,0x34480000,0x30480000,0x2E480000,0x2C480001,0x54400000,0x3C440000,0xAC0008,0x2A3C0000,
+0xAC0008,0x5C0012,0x3A580001,0x32580001,0x30540001,0x880012,0x344C0001,0x30500000,0x1140012,0x303C0000,0x2C000014,0x880012,0x344C0001,0x30500000,0x1140012,0x303C0000,0x2C000014,0x1140012,0x303C0000,0x2C000014,0x2C000014,0x880012,0x344C0001,0x30500000,0x1140012,0x303C0000,0x2C000014,0x1140012,0x303C0000,0x2C000014,0x2C000014,0x1140012,
+0x303C0000,0x2C000014,0x2C000014,0x2C000014,0x7A3C0000,0x8600012,0x74580001,0x48400000,0x38440001,0x34400000,0x30440000,0x30340000,0x6E340000,0x463C0000,0x30480001,0x2C000014,0xC00012,0x480012,0x480012,0x480012,0x480012,0x480012,0x480012,0x480012,0x480012,0x480012,0x480012,0x30440001,0x30440001,0x30440001,0x30440001,0x30440001,
+0x30440001,0x28440001,0x28440001,0x28440001,0x26400001,0x2680012,0x2680012,0x2680012,0x2680012,0x2680012,0x2680012,0x2A380001,0x2A380001,0x2A380001,0x263C0000,0xD80012,0xD80012,0xD80012,0x26280000,0x22000014,0x6A440001,0x480012,0x480012,0x42440001,0x38440001,0x32440001,0x32440001,0x2E440001,0x66380000,0x483C0000,0x2C400000,0x2A380001,
+0x980012,};
+static const uint32_t g_etc1_to_bc7_m6_table6[] = {
+0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0xF40000,
+0xF40000,0xF40000,0xF40000,0x28000000,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x580000,0x580000,0x580000,0x780000,0xAC0000,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,
+0x8C0000,0x1180000,0x1180000,0x1180000,0x2E000000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x1180000,0x1180000,0x1180000,0x2E000000,0x1180000,0x1180000,0x1180000,0x2E000000,0x2E000000,0x640000,0x5C0001,0x5C0001,0x6C0000,0x2740000,0x800000,0x800000,0x9C0000,0x6C0000,0x2740000,0xC80000,0x1180000,
+0xC80000,0x640001,0x640001,0x640001,0x640001,0x980000,0x980000,0x980000,0x1300000,0x1300000,0x32000000,0x980000,0x980000,0x980000,0x1300000,0x1300000,0x32000000,0x1300000,0x1300000,0x32000000,0x32000000,0x980000,0x980000,0x980000,0x1300000,0x1300000,0x32000000,0x1300000,0x1300000,0x32000000,0x32000000,0x1300000,
+0x1300000,0x32000000,0x32000000,0x32000000,0x4740000,0x6C0000,0x640001,0x2880000,0xAC0000,0xD80000,0xF80000,0x1780000,0x800000,0x980000,0xD80000,0x32000000,0xD80000,0x700001,0xA80000,0x1580000,0x38000000,0xA80000,0x1580000,0x38000000,0x1580000,0x38000000,0x38000000,0xA80000,0x1580000,0x38000000,0x1580000,0x38000000,
+0x38000000,0x1580000,0x38000000,0x38000000,0x38000000,0xA80000,0x1580000,0x38000000,0x1580000,0x38000000,0x38000000,0x1580000,0x38000000,0x38000000,0x38000000,0x1580000,0x38000000,0x38000000,0x38000000,0x38000000,0x48C0000,0x4780000,0x4780000,0xC00000,0x1140000,0x7F80000,0x38000000,0x38000000,0x2980000,0xD40000,0x2DCC0000,0x38000000,
+0xF00000,0x60008C,0x4E5C0033,0x3E5C0033,0x385C0033,0x48580024,0x3E580013,0x3A58001A,0x3A580024,0x36580016,0x34580026,0x46540034,0x3E54000A,0x3A54000F,0x3C500013,0x38500002,0x34540016,0x38540034,0x3650000F,0x34500019,0x32500035,0x900088,0x42480033,0x38500033,0x3C480026,0x384C0012,0x34500026,0x3E3C0033,0x38400009,0x34440015,0x32480034,0x1240088,
+0x382C0033,0x34340026,0x32280034,0x30000088,0x72540002,0xC4580024,0xD65C0033,0x4C540002,0x40540002,0x3A540002,0x38540002,0x38500002,0x6E480001,0x4E4C0001,0x38500009,0x34440015,0xD00088,0x680033,0x4664000A,0x3C60000A,0x3860000A,0x40600013,0x3C5C0002,0x38600001,0x38600013,0x385C0005,0x345C0015,0x2980033,0x3E540009,0x3858000A,0x3C500012,0x38500001,
+0x34580014,0x1380033,0x38400008,0x34440014,0x32000034,0x2980033,0x3E540009,0x3858000A,0x3C500012,0x38500001,0x34580014,0x1380033,0x38400008,0x34440014,0x32000034,0x1380033,0x38400008,0x34440014,0x32000034,0x32000034,0x72540001,0x88600013,0x9A64000A,0x4C540001,0x40540001,0x3A540001,0x38540001,0x38500001,0x6E480001,0x4A500001,0x38500009,0x34440014,
+0xDC0033,0x5C0033,0x5C0033,0x5C0033,0x5C0033,0x40580012,0x40580012,0x40580012,0x36580012,0x36580012,0x32580012,0x3E540009,0x3E540009,0x3E540009,0x36540002,0x36540002,0x32540005,0x34500009,0x34500009,0x32500001,0x30500009,0x880033,0x880033,0x880033,0x384C0012,0x384C0012,0x32500012,0x36480009,0x36480009,0x32480001,0x30480009,0x1140033,
+0x1140033,0x323C0012,0x30300008,0x2E000034,0x66540002,0x94580012,0x5C0033,0x4A540001,0x40540001,0x3A540001,0x38540002,0x36500002,0x6E480000,0x48500001,0x38500008,0x32480001,0xC00033,0x60000A,0x60000A,0x60000A,0x60000A,0x38600001,0x38600001,0x38600001,0x345C0001,0x345C0001,0x325C0001,0x900008,0x900008,0x900008,0x34580001,0x34580001,
+0x32580001,0x1240008,0x1240008,0x324C0000,0x30000008,0x900008,0x900008,0x900008,0x34580001,0x34580001,0x32580001,0x1240008,0x1240008,0x324C0000,0x30000008,0x1240008,0x1240008,0x324C0000,0x30000008,0x30000008,0x5A580000,0x58600001,0x60000A,0x4A540000,0x3C580000,0x38580000,0x36580000,0x34580001,0x5C500000,0x44540000,0xD00008,0x324C0000,
+0xD00008,0x6C0012,0x42680001,0x3A680001,0x38640001,0xA00012,0x3C5C0001,0x38600000,0x1440012,0x384C0000,0x34000014,0xA00012,0x3C5C0001,0x38600000,0x1440012,0x384C0000,0x34000014,0x1440012,0x384C0000,0x34000014,0x34000014,0xA00012,0x3C5C0001,0x38600000,0x1440012,0x384C0000,0x34000014,0x1440012,0x384C0000,0x34000014,0x34000014,0x1440012,
+0x384C0000,0x34000014,0x34000014,0x34000014,0x824C0000,0x740012,0x7C680001,0x50500000,0x40540001,0x3C500000,0x38540000,0x38440000,0x76440000,0x4E4C0000,0x38580001,0x34000014,0xE40012,0x580012,0x580012,0x580012,0x580012,0x580012,0x580012,0x580012,0x580012,0x580012,0x580012,0x38540001,0x38540001,0x38540001,0x38540001,0x38540001,
+0x38540001,0x30540001,0x30540001,0x30540001,0x2E500001,0x2800012,0x2800012,0x2800012,0x2800012,0x2800012,0x2800012,0x32480001,0x32480001,0x32480001,0x2E4C0000,0x1080012,0x1080012,0x1080012,0x2E380000,0x2A000014,0x72540001,0x580012,0x580012,0x4A540001,0x40540001,0x3A540001,0x3A540001,0x36540001,0x6E480000,0x504C0000,0x34500000,0x32480001,
+0xB80012,};
+static const uint32_t g_etc1_to_bc7_m6_table7[] = {
+0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x1240000,
+0x1240000,0x1240000,0x1240000,0x30000000,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x680000,0x680000,0x680000,0x900000,0xD00000,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,
+0xA40000,0x14C0000,0x14C0000,0x14C0000,0x36000000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0x14C0000,0x14C0000,0x14C0000,0x36000000,0x14C0000,0x14C0000,0x14C0000,0x36000000,0x36000000,0x2740000,0x6C0001,0x6C0001,0x800000,0x2880000,0x940000,0x940000,0xB80000,0x800000,0x2880000,0xE80000,0x14C0000,
+0xE80000,0x740001,0x740001,0x740001,0x740001,0xB00000,0xB00000,0xB00000,0x1640000,0x1640000,0x3A000000,0xB00000,0xB00000,0xB00000,0x1640000,0x1640000,0x3A000000,0x1640000,0x1640000,0x3A000000,0x3A000000,0xB00000,0xB00000,0xB00000,0x1640000,0x1640000,0x3A000000,0x1640000,0x1640000,0x3A000000,0x3A000000,0x1640000,
+0x1640000,0x3A000000,0x3A000000,0x3A000000,0x880000,0x67C0000,0x740001,0xA00000,0xC40000,0xF80000,0x1200000,0x1B40000,0x940000,0xB00000,0xF80000,0x3A000000,0xF80000,0x800001,0xC00000,0x1880000,0x40000000,0xC00000,0x1880000,0x40000000,0x1880000,0x40000000,0x40000000,0xC00000,0x1880000,0x40000000,0x1880000,0x40000000,
+0x40000000,0x1880000,0x40000000,0x40000000,0x40000000,0xC00000,0x1880000,0x40000000,0x1880000,0x40000000,0x40000000,0x1880000,0x40000000,0x40000000,0x40000000,0x1880000,0x40000000,0x40000000,0x40000000,0x40000000,0x4A00000,0xC880000,0xC880000,0xD80000,0x13C0000,0x11F80000,0x40000000,0x40000000,0xB00000,0xF40000,0x35DC0000,0x40000000,
+0x1140000,0x70008C,0x566C0033,0x466C0033,0x406C0033,0x50680024,0x46680013,0x4268001A,0x42680024,0x3E680016,0x3C680026,0x4E640034,0x4664000A,0x4264000F,0x44600013,0x40600002,0x3C640016,0x40640034,0x3E60000F,0x3C600019,0x3A600035,0xA80088,0x4A580033,0x40600033,0x44580026,0x405C0012,0x3C600026,0x464C0033,0x40500009,0x3C540015,0x3A580034,0x1580088,
+0x403C0033,0x3C440026,0x3A380034,0x38000088,0x7A640002,0xCC680024,0xDE6C0033,0x54640002,0x48640002,0x42640002,0x40640002,0x40600002,0x76580001,0x565C0001,0x40600009,0x3C540015,0xF00088,0x780033,0x4E74000A,0x4470000A,0x4070000A,0x48700013,0x446C0002,0x40700001,0x40700013,0x406C0005,0x3C6C0015,0x2B00033,0x46640009,0x4068000A,0x44600012,0x40600001,
+0x3C680014,0x1680033,0x40500008,0x3C540014,0x3A000034,0x2B00033,0x46640009,0x4068000A,0x44600012,0x40600001,0x3C680014,0x1680033,0x40500008,0x3C540014,0x3A000034,0x1680033,0x40500008,0x3C540014,0x3A000034,0x3A000034,0x7A640001,0x90700013,0xA274000A,0x54640001,0x48640001,0x42640001,0x40640001,0x40600001,0x76580001,0x52600001,0x40600009,0x3C540014,
+0xFC0033,0x6C0033,0x6C0033,0x6C0033,0x6C0033,0x48680012,0x48680012,0x48680012,0x3E680012,0x3E680012,0x3A680012,0x46640009,0x46640009,0x46640009,0x3E640002,0x3E640002,0x3A640005,0x3C600009,0x3C600009,0x3A600001,0x38600009,0xA00033,0xA00033,0xA00033,0x405C0012,0x405C0012,0x3A600012,0x3E580009,0x3E580009,0x3A580001,0x38580009,0x1440033,
+0x1440033,0x3A4C0012,0x38400008,0x36000034,0x6E640002,0x9C680012,0x6C0033,0x52640001,0x48640001,0x42640001,0x40640002,0x3E600002,0x76580000,0x50600001,0x40600008,0x3A580001,0xE40033,0x70000A,0x70000A,0x70000A,0x70000A,0x40700001,0x40700001,0x40700001,0x3C6C0001,0x3C6C0001,0x3A6C0001,0xA80008,0xA80008,0xA80008,0x3C680001,0x3C680001,
+0x3A680001,0x1580008,0x1580008,0x3A5C0000,0x38000008,0xA80008,0xA80008,0xA80008,0x3C680001,0x3C680001,0x3A680001,0x1580008,0x1580008,0x3A5C0000,0x38000008,0x1580008,0x1580008,0x3A5C0000,0x38000008,0x38000008,0x62680000,0x60700001,0x70000A,0x52640000,0x44680000,0x40680000,0x3E680000,0x3C680001,0x64600000,0x4C640000,0xF00008,0x3A5C0000,
+0xF00008,0x7C0012,0x4A780001,0x42780001,0x40740001,0xB80012,0x446C0001,0x40700000,0x1740012,0x405C0000,0x3C000014,0xB80012,0x446C0001,0x40700000,0x1740012,0x405C0000,0x3C000014,0x1740012,0x405C0000,0x3C000014,0x3C000014,0xB80012,0x446C0001,0x40700000,0x1740012,0x405C0000,0x3C000014,0x1740012,0x405C0000,0x3C000014,0x3C000014,0x1740012,
+0x405C0000,0x3C000014,0x3C000014,0x3C000014,0x8A5C0000,0x840012,0x84780001,0x58600000,0x48640001,0x44600000,0x40640000,0x40540000,0x7E540000,0x565C0000,0x40680001,0x3C000014,0x1080012,0x680012,0x680012,0x680012,0x680012,0x680012,0x680012,0x680012,0x680012,0x680012,0x680012,0x40640001,0x40640001,0x40640001,0x40640001,0x40640001,
+0x40640001,0x38640001,0x38640001,0x38640001,0x36600001,0x2980012,0x2980012,0x2980012,0x2980012,0x2980012,0x2980012,0x3A580001,0x3A580001,0x3A580001,0x365C0000,0x1380012,0x1380012,0x1380012,0x36480000,0x32000014,0x7A640001,0x680012,0x680012,0x52640001,0x48640001,0x42640001,0x42640001,0x3E640001,0x76580000,0x585C0000,0x3C600000,0x3A580001,
+0xDC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table8[] = {
+0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0x15C0000,
+0x15C0000,0x15C0000,0x15C0000,0x38000001,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x7C0000,0x7C0000,0x7C0000,0xAC0000,0xF40000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,
+0x2BC0000,0x1800000,0x1800000,0x1800000,0x3E000001,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x1800000,0x1800000,0x1800000,0x3E000001,0x1800000,0x1800000,0x1800000,0x3E000001,0x3E000001,0x880000,0x800000,0x800000,0x940000,0xA00000,0x2AC0000,0x2AC0000,0x2D40000,0x940000,0xA00000,0x1100000,0x1800000,
+0x1100000,0x880000,0x880000,0x880000,0x880000,0xC80000,0xC80000,0xC80000,0x1980000,0x1980000,0x42000001,0xC80000,0xC80000,0xC80000,0x1980000,0x1980000,0x42000001,0x1980000,0x1980000,0x42000001,0x42000001,0xC80000,0xC80000,0xC80000,0x1980000,0x1980000,0x42000001,0x1980000,0x1980000,0x42000001,0x42000001,0x1980000,
+0x1980000,0x42000001,0x42000001,0x42000001,0x49C0000,0x900000,0x880000,0xB80000,0xE40000,0x1200000,0x14C0000,0x1F80000,0x2A80000,0xC80000,0x1200000,0x42000001,0x1200000,0x940000,0xDC0000,0x1BC0000,0x48000001,0xDC0000,0x1BC0000,0x48000001,0x1BC0000,0x48000001,0x48000001,0xDC0000,0x1BC0000,0x48000001,0x1BC0000,0x48000001,
+0x48000001,0x1BC0000,0x48000001,0x48000001,0x48000001,0xDC0000,0x1BC0000,0x48000001,0x1BC0000,0x48000001,0x48000001,0x1BC0000,0x48000001,0x48000001,0x48000001,0x1BC0000,0x48000001,0x48000001,0x48000001,0x48000001,0xB80000,0x69C0000,0x69C0000,0xF80000,0x1680000,0x1DF40000,0x48000001,0x48000001,0xC80000,0x1140000,0x3FD00000,0x48000001,
+0x1380000,0x840088,0x5C800034,0x4E800034,0x48800035,0x587C0026,0x4E7C0015,0x487C0019,0x4A7C0026,0x48780016,0x46780026,0x5A740033,0x50740009,0x4A78000F,0x4C740012,0x48740002,0x46740016,0x4A740033,0x4870000F,0x4670001A,0x44740033,0xC40088,0x54680033,0x48740034,0x4E680026,0x4A6C0013,0x46700024,0x4E600033,0x4868000A,0x46640013,0x44680033,0x18C0088,
+0x48540034,0x46500024,0x44440033,0x4000008C,0x82740002,0xC67C0026,0xD8800034,0x60740001,0x52740002,0x4C740002,0x4A740002,0x48740002,0x7C6C0001,0x5C700001,0x4A700009,0x46640013,0x1180088,0x880034,0x58840008,0x4C840009,0x48840009,0x54800012,0x4C800001,0x4A800001,0x4A800012,0x48800005,0x46800012,0xCC0033,0x4E780009,0x487C0009,0x4C740012,0x48740002,
+0x46780012,0x1A00033,0x48680009,0x46640012,0x44000033,0xCC0033,0x4E780009,0x487C0009,0x4C740012,0x48740002,0x46780012,0x1A00033,0x48680009,0x46640012,0x44000033,0x1A00033,0x48680009,0x46640012,0x44000033,0x44000033,0x7E780001,0xA8800012,0xBA840008,0x5A780001,0x52740002,0x4C740002,0x48780002,0x48700002,0x7C6C0001,0x58740001,0x4A700008,0x46640012,
+0x1240033,0x800034,0x800034,0x800034,0x800034,0x4E7C0014,0x4E7C0014,0x4E7C0014,0x467C0014,0x467C0014,0x42780015,0x50740008,0x50740008,0x50740008,0x48740001,0x48740001,0x44740005,0x4474000A,0x4474000A,0x42740001,0x4074000A,0xBC0033,0xBC0033,0xBC0033,0x4A6C0012,0x4A6C0012,0x42740013,0x48680009,0x48680009,0x426C0002,0x406C000A,0x17C0033,
+0x17C0033,0x42600013,0x4058000A,0x3E000033,0x82740001,0x967C0014,0x800034,0x5E740001,0x52740001,0x4C740001,0x4A740001,0x46740001,0x7A6C0000,0x5C700000,0x48740009,0x426C0002,0x10C0033,0x840008,0x840008,0x840008,0x840008,0x4A800000,0x4A800000,0x4A800000,0x44800001,0x44800001,0x42800001,0xC40008,0xC40008,0xC40008,0x447C0001,0x447C0001,
+0x427C0001,0x18C0008,0x18C0008,0x42740001,0x4000000A,0xC40008,0xC40008,0xC40008,0x447C0001,0x447C0001,0x427C0001,0x18C0008,0x18C0008,0x42740001,0x4000000A,0x18C0008,0x18C0008,0x42740001,0x4000000A,0x4000000A,0x74780000,0x78800000,0x840008,0x58780000,0x4E780000,0x4A780000,0x467C0001,0x46780000,0x70700000,0x56740000,0x1180008,0x42740001,
+0x1180008,0x8C0014,0x54880000,0x4C880000,0x48880001,0x2D00012,0x4C800001,0x48840001,0x1AC0012,0x48740001,0x46000012,0x2D00012,0x4C800001,0x48840001,0x1AC0012,0x48740001,0x46000012,0x1AC0012,0x48740001,0x46000012,0x46000012,0x2D00012,0x4C800001,0x48840001,0x1AC0012,0x48740001,0x46000012,0x1AC0012,0x48740001,0x46000012,0x46000012,0x1AC0012,
+0x48740001,0x46000012,0x46000012,0x46000012,0x8E700000,0x980012,0x9C880000,0x60740000,0x52740001,0x4E700000,0x48780001,0x486C0001,0x84680000,0x606C0000,0x4A780000,0x46000012,0x12C0012,0x780014,0x780014,0x780014,0x780014,0x780014,0x780014,0x780014,0x780014,0x780014,0x780014,0x4A740000,0x4A740000,0x4A740000,0x4A740000,0x4A740000,
+0x4A740000,0x42740000,0x42740000,0x42740000,0x3E740001,0xB40012,0xB40012,0xB40012,0xB40012,0xB40012,0xB40012,0x426C0001,0x426C0001,0x426C0001,0x3E700001,0x1700012,0x1700012,0x1700012,0x3E600001,0x3C000012,0x92740000,0x780014,0x780014,0x62740000,0x56740000,0x4E740000,0x4E740000,0x48740000,0x7A6C0000,0x5C700000,0x44740001,0x426C0001,
+0x1000012,};
+static const uint32_t g_etc1_to_bc7_m6_table9[] = {
+0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0x18C0000,
+0x18C0000,0x18C0000,0x18C0000,0x40000001,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x8C0000,0x8C0000,0x8C0000,0xC40000,0x1180000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,
+0xD40000,0x1B00000,0x1B00000,0x1B00000,0x46000001,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0x1B00000,0x1B00000,0x1B00000,0x46000001,0x1B00000,0x1B00000,0x1B00000,0x46000001,0x46000001,0x4980000,0x900000,0x900000,0xA80000,0xB40000,0xC40000,0xC40000,0xF00000,0xA80000,0xB40000,0x1300000,0x1B00000,
+0x1300000,0x980000,0x980000,0x980000,0x980000,0xE00000,0xE00000,0xE00000,0x1CC0000,0x1CC0000,0x4A000001,0xE00000,0xE00000,0xE00000,0x1CC0000,0x1CC0000,0x4A000001,0x1CC0000,0x1CC0000,0x4A000001,0x4A000001,0xE00000,0xE00000,0xE00000,0x1CC0000,0x1CC0000,0x4A000001,0x1CC0000,0x1CC0000,0x4A000001,0x4A000001,0x1CC0000,
+0x1CC0000,0x4A000001,0x4A000001,0x4A000001,0xB00000,0x8A00000,0x980000,0x2CC0000,0x1000000,0x1400000,0x1740000,0xBFC0000,0x2BC0000,0xE00000,0x1400000,0x4A000001,0x1400000,0xA40000,0xF40000,0x1F00000,0x50000001,0xF40000,0x1F00000,0x50000001,0x1F00000,0x50000001,0x50000001,0xF40000,0x1F00000,0x50000001,0x1F00000,0x50000001,
+0x50000001,0x1F00000,0x50000001,0x50000001,0x50000001,0xF40000,0x1F00000,0x50000001,0x1F00000,0x50000001,0x50000001,0x1F00000,0x50000001,0x50000001,0x50000001,0x1F00000,0x50000001,0x50000001,0x50000001,0x50000001,0x2CC0000,0xEAC0000,0xEAC0000,0x1140000,0x1900000,0x27F40000,0x50000001,0x50000001,0x2DC0000,0x1340000,0x47E00000,0x50000001,
+0x15C0000,0x940088,0x64900034,0x56900034,0x50900035,0x608C0026,0x568C0015,0x508C0019,0x528C0026,0x50880016,0x4E880026,0x62840033,0x58840009,0x5288000F,0x54840012,0x50840002,0x4E840016,0x52840033,0x5080000F,0x4E80001A,0x4C840033,0xDC0088,0x5C780033,0x50840034,0x56780026,0x527C0013,0x4E800024,0x56700033,0x5078000A,0x4E740013,0x4C780033,0x1BC0088,
+0x50640034,0x4E600024,0x4C540033,0x4800008C,0x8A840002,0xCE8C0026,0xE0900034,0x68840001,0x5A840002,0x54840002,0x52840002,0x50840002,0x847C0001,0x64800001,0x52800009,0x4E740013,0x1380088,0x980034,0x60940008,0x54940009,0x50940009,0x5C900012,0x54900001,0x52900001,0x52900012,0x50900005,0x4E900012,0xE40033,0x56880009,0x508C0009,0x54840012,0x50840002,
+0x4E880012,0x1D00033,0x50780009,0x4E740012,0x4C000033,0xE40033,0x56880009,0x508C0009,0x54840012,0x50840002,0x4E880012,0x1D00033,0x50780009,0x4E740012,0x4C000033,0x1D00033,0x50780009,0x4E740012,0x4C000033,0x4C000033,0x86880001,0xB0900012,0xC2940008,0x62880001,0x5A840002,0x54840002,0x50880002,0x50800002,0x847C0001,0x60840001,0x52800008,0x4E740012,
+0x1480033,0x900034,0x900034,0x900034,0x900034,0x568C0014,0x568C0014,0x568C0014,0x4E8C0014,0x4E8C0014,0x4A880015,0x58840008,0x58840008,0x58840008,0x50840001,0x50840001,0x4C840005,0x4C84000A,0x4C84000A,0x4A840001,0x4884000A,0x2D00033,0x2D00033,0x2D00033,0x527C0012,0x527C0012,0x4A840013,0x50780009,0x50780009,0x4A7C0002,0x487C000A,0x1AC0033,
+0x1AC0033,0x4A700013,0x4868000A,0x46000033,0x8A840001,0x9E8C0014,0x900034,0x66840001,0x5A840001,0x54840001,0x52840001,0x4E840001,0x827C0000,0x64800000,0x50840009,0x4A7C0002,0x12C0033,0x940008,0x940008,0x940008,0x940008,0x52900000,0x52900000,0x52900000,0x4C900001,0x4C900001,0x4A900001,0xDC0008,0xDC0008,0xDC0008,0x4C8C0001,0x4C8C0001,
+0x4A8C0001,0x1BC0008,0x1BC0008,0x4A840001,0x4800000A,0xDC0008,0xDC0008,0xDC0008,0x4C8C0001,0x4C8C0001,0x4A8C0001,0x1BC0008,0x1BC0008,0x4A840001,0x4800000A,0x1BC0008,0x1BC0008,0x4A840001,0x4800000A,0x4800000A,0x7C880000,0x80900000,0x940008,0x60880000,0x56880000,0x52880000,0x4E8C0001,0x4E880000,0x78800000,0x5E840000,0x1380008,0x4A840001,
+0x1380008,0x9C0014,0x5C980000,0x54980000,0x50980001,0x2E80012,0x54900001,0x50940001,0x1DC0012,0x50840001,0x4E000012,0x2E80012,0x54900001,0x50940001,0x1DC0012,0x50840001,0x4E000012,0x1DC0012,0x50840001,0x4E000012,0x4E000012,0x2E80012,0x54900001,0x50940001,0x1DC0012,0x50840001,0x4E000012,0x1DC0012,0x50840001,0x4E000012,0x4E000012,0x1DC0012,
+0x50840001,0x4E000012,0x4E000012,0x4E000012,0x96800000,0xA80012,0xA4980000,0x68840000,0x5A840001,0x56800000,0x50880001,0x507C0001,0x8C780000,0x687C0000,0x52880000,0x4E000012,0x1500012,0x880014,0x880014,0x880014,0x880014,0x880014,0x880014,0x880014,0x880014,0x880014,0x880014,0x52840000,0x52840000,0x52840000,0x52840000,0x52840000,
+0x52840000,0x4A840000,0x4A840000,0x4A840000,0x46840001,0xCC0012,0xCC0012,0xCC0012,0xCC0012,0xCC0012,0xCC0012,0x4A7C0001,0x4A7C0001,0x4A7C0001,0x46800001,0x1A00012,0x1A00012,0x1A00012,0x46700001,0x44000012,0x9A840000,0x880014,0x880014,0x6A840000,0x5E840000,0x56840000,0x56840000,0x50840000,0x827C0000,0x64800000,0x4C840001,0x4A7C0001,
+0x1240012,};
+static const uint32_t g_etc1_to_bc7_m6_table10[] = {
+0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0x1BC0000,
+0x1BC0000,0x1BC0000,0x1BC0000,0x48000001,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x69C0000,0x69C0000,0x69C0000,0xDC0000,0x1380000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,
+0xEC0000,0x1E40000,0x1E40000,0x1E40000,0x4E000001,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0x1E40000,0x1E40000,0x1E40000,0x4E000001,0x1E40000,0x1E40000,0x1E40000,0x4E000001,0x4E000001,0xCA80000,0xA00000,0xA00000,0x4B80000,0xC80000,0xD80000,0xD80000,0x10C0000,0x4B80000,0xC80000,0x1540000,0x1E40000,
+0x1540000,0xA80000,0xA80000,0xA80000,0xA80000,0xF80000,0xF80000,0xF80000,0x1FC0000,0x1FC0000,0x52000001,0xF80000,0xF80000,0xF80000,0x1FC0000,0x1FC0000,0x52000001,0x1FC0000,0x1FC0000,0x52000001,0x52000001,0xF80000,0xF80000,0xF80000,0x1FC0000,0x1FC0000,0x52000001,0x1FC0000,0x1FC0000,0x52000001,0x52000001,0x1FC0000,
+0x1FC0000,0x52000001,0x52000001,0x52000001,0xC40000,0xB40000,0xA80000,0xE40000,0x1180000,0x1640000,0x19C0000,0x17F80000,0x4D00000,0xF80000,0x1640000,0x52000001,0x1640000,0xB40000,0x10C0000,0xBF80000,0x58000001,0x10C0000,0xBF80000,0x58000001,0xBF80000,0x58000001,0x58000001,0x10C0000,0xBF80000,0x58000001,0xBF80000,0x58000001,
+0x58000001,0xBF80000,0x58000001,0x58000001,0x58000001,0x10C0000,0xBF80000,0x58000001,0xBF80000,0x58000001,0x58000001,0xBF80000,0x58000001,0x58000001,0x58000001,0xBF80000,0x58000001,0x58000001,0x58000001,0x58000001,0x2E00000,0xC00000,0xC00000,0x32C0000,0x1B80000,0x31F40000,0x58000001,0x58000001,0xF40000,0x1500000,0x4FF00000,0x58000001,
+0x17C0000,0xA40088,0x6CA00034,0x5EA00034,0x58A00035,0x689C0026,0x5E9C0015,0x589C0019,0x5A9C0026,0x58980016,0x56980026,0x6A940033,0x60940009,0x5A98000F,0x5C940012,0x58940002,0x56940016,0x5A940033,0x5890000F,0x5690001A,0x54940033,0xF40088,0x64880033,0x58940034,0x5E880026,0x5A8C0013,0x56900024,0x5E800033,0x5888000A,0x56840013,0x54880033,0x1F00088,
+0x58740034,0x56700024,0x54640033,0x5000008C,0x92940002,0xD69C0026,0xE8A00034,0x70940001,0x62940002,0x5C940002,0x5A940002,0x58940002,0x8C8C0001,0x6C900001,0x5A900009,0x56840013,0x15C0088,0xA80034,0x68A40008,0x5CA40009,0x58A40009,0x64A00012,0x5CA00001,0x5AA00001,0x5AA00012,0x58A00005,0x56A00012,0xFC0033,0x5E980009,0x589C0009,0x5C940012,0x58940002,
+0x56980012,0x3F80033,0x58880009,0x56840012,0x54000033,0xFC0033,0x5E980009,0x589C0009,0x5C940012,0x58940002,0x56980012,0x3F80033,0x58880009,0x56840012,0x54000033,0x3F80033,0x58880009,0x56840012,0x54000033,0x54000033,0x8E980001,0xB8A00012,0xCAA40008,0x6A980001,0x62940002,0x5C940002,0x58980002,0x58900002,0x8C8C0001,0x68940001,0x5A900008,0x56840012,
+0x1680033,0xA00034,0xA00034,0xA00034,0xA00034,0x5E9C0014,0x5E9C0014,0x5E9C0014,0x569C0014,0x569C0014,0x52980015,0x60940008,0x60940008,0x60940008,0x58940001,0x58940001,0x54940005,0x5494000A,0x5494000A,0x52940001,0x5094000A,0x2E80033,0x2E80033,0x2E80033,0x5A8C0012,0x5A8C0012,0x52940013,0x58880009,0x58880009,0x528C0002,0x508C000A,0x1DC0033,
+0x1DC0033,0x52800013,0x5078000A,0x4E000033,0x92940001,0xA69C0014,0xA00034,0x6E940001,0x62940001,0x5C940001,0x5A940001,0x56940001,0x8A8C0000,0x6C900000,0x58940009,0x528C0002,0x1500033,0xA40008,0xA40008,0xA40008,0xA40008,0x5AA00000,0x5AA00000,0x5AA00000,0x54A00001,0x54A00001,0x52A00001,0xF40008,0xF40008,0xF40008,0x549C0001,0x549C0001,
+0x529C0001,0x1F00008,0x1F00008,0x52940001,0x5000000A,0xF40008,0xF40008,0xF40008,0x549C0001,0x549C0001,0x529C0001,0x1F00008,0x1F00008,0x52940001,0x5000000A,0x1F00008,0x1F00008,0x52940001,0x5000000A,0x5000000A,0x84980000,0x88A00000,0xA40008,0x68980000,0x5E980000,0x5A980000,0x569C0001,0x56980000,0x80900000,0x66940000,0x15C0008,0x52940001,
+0x15C0008,0xAC0014,0x64A80000,0x5CA80000,0x58A80001,0x3000012,0x5CA00001,0x58A40001,0x5FC0012,0x58940001,0x56000012,0x3000012,0x5CA00001,0x58A40001,0x5FC0012,0x58940001,0x56000012,0x5FC0012,0x58940001,0x56000012,0x56000012,0x3000012,0x5CA00001,0x58A40001,0x5FC0012,0x58940001,0x56000012,0x5FC0012,0x58940001,0x56000012,0x56000012,0x5FC0012,
+0x58940001,0x56000012,0x56000012,0x56000012,0x9E900000,0x4B80012,0xACA80000,0x70940000,0x62940001,0x5E900000,0x58980001,0x588C0001,0x94880000,0x708C0000,0x5A980000,0x56000012,0x1700012,0x980014,0x980014,0x980014,0x980014,0x980014,0x980014,0x980014,0x980014,0x980014,0x980014,0x5A940000,0x5A940000,0x5A940000,0x5A940000,0x5A940000,
+0x5A940000,0x52940000,0x52940000,0x52940000,0x4E940001,0xE40012,0xE40012,0xE40012,0xE40012,0xE40012,0xE40012,0x528C0001,0x528C0001,0x528C0001,0x4E900001,0x1D00012,0x1D00012,0x1D00012,0x4E800001,0x4C000012,0xA2940000,0x980014,0x980014,0x72940000,0x66940000,0x5E940000,0x5E940000,0x58940000,0x8A8C0000,0x6C900000,0x54940001,0x528C0001,
+0x1480012,};
+static const uint32_t g_etc1_to_bc7_m6_table11[] = {
+0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0x1F00000,
+0x1F00000,0x1F00000,0x1F00000,0x50000001,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xEAC0000,0xEAC0000,0xEAC0000,0xF40000,0x15C0000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,
+0x1040000,0x7FC0000,0x7FC0000,0x7FC0000,0x56000001,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x7FC0000,0x7FC0000,0x7FC0000,0x56000001,0x7FC0000,0x7FC0000,0x7FC0000,0x56000001,0x56000001,0xBC0000,0xB00000,0xB00000,0xCC0000,0xDC0000,0xF00000,0xF00000,0x1280000,0xCC0000,0xDC0000,0x1740000,0x7FC0000,
+0x1740000,0xB80000,0xB80000,0xB80000,0xB80000,0x1100000,0x1100000,0x1100000,0xDFC0000,0xDFC0000,0x5A000001,0x1100000,0x1100000,0x1100000,0xDFC0000,0xDFC0000,0x5A000001,0xDFC0000,0xDFC0000,0x5A000001,0x5A000001,0x1100000,0x1100000,0x1100000,0xDFC0000,0xDFC0000,0x5A000001,0xDFC0000,0xDFC0000,0x5A000001,0x5A000001,0xDFC0000,
+0xDFC0000,0x5A000001,0x5A000001,0x5A000001,0x2D40000,0xC40000,0xB80000,0x2F80000,0x1340000,0x1880000,0x1C00000,0x21FC0000,0x4E40000,0x1100000,0x1880000,0x5A000001,0x1880000,0xC40000,0x1240000,0x17F80000,0x60000001,0x1240000,0x17F80000,0x60000001,0x17F80000,0x60000001,0x60000001,0x1240000,0x17F80000,0x60000001,0x17F80000,0x60000001,
+0x60000001,0x17F80000,0x60000001,0x60000001,0x60000001,0x1240000,0x17F80000,0x60000001,0x17F80000,0x60000001,0x60000001,0x17F80000,0x60000001,0x60000001,0x60000001,0x17F80000,0x60000001,0x60000001,0x60000001,0x60000001,0x2F40000,0xD00000,0xD00000,0x1480000,0x1E00000,0x3BF40000,0x60000001,0x60000001,0x3080000,0x1700000,0x59C40000,0x60000001,
+0x1A00000,0xB40088,0x74B00034,0x66B00034,0x60B00035,0x70AC0026,0x66AC0015,0x60AC0019,0x62AC0026,0x60A80016,0x5EA80026,0x72A40033,0x68A40009,0x62A8000F,0x64A40012,0x60A40002,0x5EA40016,0x62A40033,0x60A0000F,0x5EA0001A,0x5CA40033,0x10C0088,0x6C980033,0x60A40034,0x66980026,0x629C0013,0x5EA00024,0x66900033,0x6098000A,0x5E940013,0x5C980033,0xBF80088,
+0x60840034,0x5E800024,0x5C740033,0x5800008C,0x9AA40002,0xDEAC0026,0xF0B00034,0x78A40001,0x6AA40002,0x64A40002,0x62A40002,0x60A40002,0x949C0001,0x74A00001,0x62A00009,0x5E940013,0x17C0088,0xB80034,0x70B40008,0x64B40009,0x60B40009,0x6CB00012,0x64B00001,0x62B00001,0x62B00012,0x60B00005,0x5EB00012,0x1140033,0x66A80009,0x60AC0009,0x64A40012,0x60A40002,
+0x5EA80012,0xFF80033,0x60980009,0x5E940012,0x5C000033,0x1140033,0x66A80009,0x60AC0009,0x64A40012,0x60A40002,0x5EA80012,0xFF80033,0x60980009,0x5E940012,0x5C000033,0xFF80033,0x60980009,0x5E940012,0x5C000033,0x5C000033,0x96A80001,0xC0B00012,0xD2B40008,0x72A80001,0x6AA40002,0x64A40002,0x60A80002,0x60A00002,0x949C0001,0x70A40001,0x62A00008,0x5E940012,
+0x18C0033,0xB00034,0xB00034,0xB00034,0xB00034,0x66AC0014,0x66AC0014,0x66AC0014,0x5EAC0014,0x5EAC0014,0x5AA80015,0x68A40008,0x68A40008,0x68A40008,0x60A40001,0x60A40001,0x5CA40005,0x5CA4000A,0x5CA4000A,0x5AA40001,0x58A4000A,0x3000033,0x3000033,0x3000033,0x629C0012,0x629C0012,0x5AA40013,0x60980009,0x60980009,0x5A9C0002,0x589C000A,0x5FC0033,
+0x5FC0033,0x5A900013,0x5888000A,0x56000033,0x9AA40001,0xAEAC0014,0xB00034,0x76A40001,0x6AA40001,0x64A40001,0x62A40001,0x5EA40001,0x929C0000,0x74A00000,0x60A40009,0x5A9C0002,0x1700033,0xB40008,0xB40008,0xB40008,0xB40008,0x62B00000,0x62B00000,0x62B00000,0x5CB00001,0x5CB00001,0x5AB00001,0x10C0008,0x10C0008,0x10C0008,0x5CAC0001,0x5CAC0001,
+0x5AAC0001,0xBF80008,0xBF80008,0x5AA40001,0x5800000A,0x10C0008,0x10C0008,0x10C0008,0x5CAC0001,0x5CAC0001,0x5AAC0001,0xBF80008,0xBF80008,0x5AA40001,0x5800000A,0xBF80008,0xBF80008,0x5AA40001,0x5800000A,0x5800000A,0x8CA80000,0x90B00000,0xB40008,0x70A80000,0x66A80000,0x62A80000,0x5EAC0001,0x5EA80000,0x88A00000,0x6EA40000,0x17C0008,0x5AA40001,
+0x17C0008,0xBC0014,0x6CB80000,0x64B80000,0x60B80001,0x3180012,0x64B00001,0x60B40001,0x11FC0012,0x60A40001,0x5E000012,0x3180012,0x64B00001,0x60B40001,0x11FC0012,0x60A40001,0x5E000012,0x11FC0012,0x60A40001,0x5E000012,0x5E000012,0x3180012,0x64B00001,0x60B40001,0x11FC0012,0x60A40001,0x5E000012,0x11FC0012,0x60A40001,0x5E000012,0x5E000012,0x11FC0012,
+0x60A40001,0x5E000012,0x5E000012,0x5E000012,0xA6A00000,0xCC80012,0xB4B80000,0x78A40000,0x6AA40001,0x66A00000,0x60A80001,0x609C0001,0x9C980000,0x789C0000,0x62A80000,0x5E000012,0x1940012,0xA80014,0xA80014,0xA80014,0xA80014,0xA80014,0xA80014,0xA80014,0xA80014,0xA80014,0xA80014,0x62A40000,0x62A40000,0x62A40000,0x62A40000,0x62A40000,
+0x62A40000,0x5AA40000,0x5AA40000,0x5AA40000,0x56A40001,0xFC0012,0xFC0012,0xFC0012,0xFC0012,0xFC0012,0xFC0012,0x5A9C0001,0x5A9C0001,0x5A9C0001,0x56A00001,0x3F80012,0x3F80012,0x3F80012,0x56900001,0x54000012,0xAAA40000,0xA80014,0xA80014,0x7AA40000,0x6EA40000,0x66A40000,0x66A40000,0x60A40000,0x929C0000,0x74A00000,0x5CA40001,0x5A9C0001,
+0x1680012,};
+static const uint32_t g_etc1_to_bc7_m6_table12[] = {
+0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0xBFC0000,
+0xBFC0000,0xBFC0000,0xBFC0000,0x5A000000,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0x8C00000,0x8C00000,0x8C00000,0x30C0000,0x1800000,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,
+0x1200000,0x15F80000,0x15F80000,0x15F80000,0x60000000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x15F80000,0x15F80000,0x15F80000,0x60000000,0x15F80000,0x15F80000,0x15F80000,0x60000000,0x60000000,0xECC0000,0xC00001,0xC00001,0x2E00000,0xF40000,0x1080000,0x1080000,0x1440000,0x2E00000,0xF40000,0x19C0000,0x15F80000,
+0x19C0000,0xC80001,0xC80001,0xC80001,0xC80001,0x12C0000,0x12C0000,0x12C0000,0x1BF80000,0x1BF80000,0x64000000,0x12C0000,0x12C0000,0x12C0000,0x1BF80000,0x1BF80000,0x64000000,0x1BF80000,0x1BF80000,0x64000000,0x64000000,0x12C0000,0x12C0000,0x12C0000,0x1BF80000,0x1BF80000,0x64000000,0x1BF80000,0x1BF80000,0x64000000,0x64000000,0x1BF80000,
+0x1BF80000,0x64000000,0x64000000,0x64000000,0x6E80000,0xD80000,0xC80001,0x3100000,0x1540000,0x1AC0000,0x1EC0000,0x2DFC0000,0xFC0000,0x12C0000,0x1AC0000,0x64000000,0x1AC0000,0xD40001,0x33C0000,0x23FC0000,0x6A000000,0x33C0000,0x23FC0000,0x6A000000,0x23FC0000,0x6A000000,0x6A000000,0x33C0000,0x23FC0000,0x6A000000,0x23FC0000,0x6A000000,
+0x6A000000,0x23FC0000,0x6A000000,0x6A000000,0x6A000000,0x33C0000,0x23FC0000,0x6A000000,0x23FC0000,0x6A000000,0x6A000000,0x23FC0000,0x6A000000,0x6A000000,0x6A000000,0x23FC0000,0x6A000000,0x6A000000,0x6A000000,0x6A000000,0x10C0000,0xE40000,0xE40000,0x1680000,0x7F80000,0x45FC0000,0x6A000000,0x6A000000,0x1240000,0x1900000,0x61F40000,0x6A000000,
+0x1C80000,0xC4008C,0x80C00033,0x70C00033,0x6AC00033,0x7ABC0024,0x70BC0013,0x6CBC001A,0x6CBC0024,0x68BC0016,0x66BC0026,0x78B80034,0x70B8000A,0x6CB8000F,0x6EB40013,0x6AB40002,0x66B80016,0x6AB80034,0x68B4000F,0x66B40019,0x64B40035,0x3240088,0x74AC0033,0x6AB40033,0x6EAC0026,0x6AB00012,0x66B40026,0x70A00033,0x6AA40009,0x66A80015,0x64AC0034,0x17FC0088,
+0x6A900033,0x66980026,0x648C0034,0x62000088,0xA4B80002,0xF6BC0024,0xF8C00034,0x7EB80002,0x72B80002,0x6CB80002,0x6AB80002,0x6AB40002,0xA0AC0001,0x80B00001,0x6AB40009,0x66A80015,0x1A40088,0xCC0033,0x78C8000A,0x6EC4000A,0x6AC4000A,0x72C40013,0x6EC00002,0x6AC40001,0x6AC40013,0x6AC00005,0x66C00015,0x1300033,0x70B80009,0x6ABC000A,0x6EB40012,0x6AB40001,
+0x66BC0014,0x1DF40033,0x6AA40008,0x66A80014,0x64000034,0x1300033,0x70B80009,0x6ABC000A,0x6EB40012,0x6AB40001,0x66BC0014,0x1DF40033,0x6AA40008,0x66A80014,0x64000034,0x1DF40033,0x6AA40008,0x66A80014,0x64000034,0x64000034,0xA4B80001,0xBAC40013,0xCCC8000A,0x7EB80001,0x72B80001,0x6CB80001,0x6AB80001,0x6AB40001,0xA0AC0001,0x7CB40001,0x6AB40009,0x66A80014,
+0x1B00033,0xC00033,0xC00033,0xC00033,0xC00033,0x72BC0012,0x72BC0012,0x72BC0012,0x68BC0012,0x68BC0012,0x64BC0012,0x70B80009,0x70B80009,0x70B80009,0x68B80002,0x68B80002,0x64B80005,0x66B40009,0x66B40009,0x64B40001,0x62B40009,0x11C0033,0x11C0033,0x11C0033,0x6AB00012,0x6AB00012,0x64B40012,0x68AC0009,0x68AC0009,0x64AC0001,0x62AC0009,0x13FC0033,
+0x13FC0033,0x64A00012,0x62940008,0x60000034,0x98B80002,0xC6BC0012,0xC00033,0x7CB80001,0x72B80001,0x6CB80001,0x6AB80002,0x68B40002,0xA0AC0000,0x7AB40001,0x6AB40008,0x64AC0001,0x1980033,0xC4000A,0xC4000A,0xC4000A,0xC4000A,0x6AC40001,0x6AC40001,0x6AC40001,0x66C00001,0x66C00001,0x64C00001,0x3240008,0x3240008,0x3240008,0x66BC0001,0x66BC0001,
+0x64BC0001,0x17FC0008,0x17FC0008,0x64B00000,0x62000008,0x3240008,0x3240008,0x3240008,0x66BC0001,0x66BC0001,0x64BC0001,0x17FC0008,0x17FC0008,0x64B00000,0x62000008,0x17FC0008,0x17FC0008,0x64B00000,0x62000008,0x62000008,0x8CBC0000,0x8AC40001,0xC4000A,0x7CB80000,0x6EBC0000,0x6ABC0000,0x68BC0000,0x66BC0001,0x8EB40000,0x76B80000,0x1A40008,0x64B00000,
+0x1A40008,0xD00012,0x74CC0001,0x6CCC0001,0x6AC80001,0x1340012,0x6EC00001,0x6AC40000,0x1FF80012,0x6AB00000,0x66000014,0x1340012,0x6EC00001,0x6AC40000,0x1FF80012,0x6AB00000,0x66000014,0x1FF80012,0x6AB00000,0x66000014,0x66000014,0x1340012,0x6EC00001,0x6AC40000,0x1FF80012,0x6AB00000,0x66000014,0x1FF80012,0x6AB00000,0x66000014,0x66000014,0x1FF80012,
+0x6AB00000,0x66000014,0x66000014,0x66000014,0xB4B00000,0x6DC0012,0xAECC0001,0x82B40000,0x72B80001,0x6EB40000,0x6AB80000,0x6AA80000,0xA8A80000,0x80B00000,0x6ABC0001,0x66000014,0x1B80012,0xBC0012,0xBC0012,0xBC0012,0xBC0012,0xBC0012,0xBC0012,0xBC0012,0xBC0012,0xBC0012,0xBC0012,0x6AB80001,0x6AB80001,0x6AB80001,0x6AB80001,0x6AB80001,
+0x6AB80001,0x62B80001,0x62B80001,0x62B80001,0x60B40001,0x1180012,0x1180012,0x1180012,0x1180012,0x1180012,0x1180012,0x64AC0001,0x64AC0001,0x64AC0001,0x60B00000,0x11F80012,0x11F80012,0x11F80012,0x609C0000,0x5C000014,0xA4B80001,0xBC0012,0xBC0012,0x7CB80001,0x72B80001,0x6CB80001,0x6CB80001,0x68B80001,0xA0AC0000,0x82B00000,0x66B40000,0x64AC0001,
+0x1900012,};
+static const uint32_t g_etc1_to_bc7_m6_table13[] = {
+0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,0x17FC0000,
+0x17FC0000,0x17FC0000,0x17FC0000,0x62000000,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xD40000,0xD40000,0xD40000,0x3240000,0x1A40000,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,
+0x1380000,0x21F80000,0x21F80000,0x21F80000,0x68000000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x21F80000,0x21F80000,0x21F80000,0x68000000,0x21F80000,0x21F80000,0x21F80000,0x68000000,0x68000000,0xE00000,0xD00001,0xD00001,0xF40000,0x1080000,0x11C0000,0x11C0000,0x1600000,0xF40000,0x1080000,0x1BC0000,0x21F80000,
+0x1BC0000,0xD80001,0xD80001,0xD80001,0xD80001,0x1440000,0x1440000,0x1440000,0x27F80000,0x27F80000,0x6C000000,0x1440000,0x1440000,0x1440000,0x27F80000,0x27F80000,0x6C000000,0x27F80000,0x27F80000,0x6C000000,0x6C000000,0x1440000,0x1440000,0x1440000,0x27F80000,0x27F80000,0x6C000000,0x27F80000,0x27F80000,0x6C000000,0x6C000000,0x27F80000,
+0x27F80000,0x6C000000,0x6C000000,0x6C000000,0x2FC0000,0xE80000,0xD80001,0x1280000,0x36C0000,0x1D00000,0x9FC0000,0x39F80000,0x1100000,0x1440000,0x1D00000,0x6C000000,0x1D00000,0xE40001,0x1540000,0x2FFC0000,0x72000000,0x1540000,0x2FFC0000,0x72000000,0x2FFC0000,0x72000000,0x72000000,0x1540000,0x2FFC0000,0x72000000,0x2FFC0000,0x72000000,
+0x72000000,0x2FFC0000,0x72000000,0x72000000,0x72000000,0x1540000,0x2FFC0000,0x72000000,0x2FFC0000,0x72000000,0x72000000,0x2FFC0000,0x72000000,0x72000000,0x72000000,0x2FFC0000,0x72000000,0x72000000,0x72000000,0x72000000,0x1200000,0x2F40000,0x2F40000,0x3800000,0x15F80000,0x4FFC0000,0x72000000,0x72000000,0x1380000,0x1B00000,0x6BC80000,0x72000000,
+0x1E80000,0xD4008C,0x88D00033,0x78D00033,0x72D00033,0x82CC0024,0x78CC0013,0x74CC001A,0x74CC0024,0x70CC0016,0x6ECC0026,0x80C80034,0x78C8000A,0x74C8000F,0x76C40013,0x72C40002,0x6EC80016,0x72C80034,0x70C4000F,0x6EC40019,0x6CC40035,0x33C0088,0x7CBC0033,0x72C40033,0x76BC0026,0x72C00012,0x6EC40026,0x78B00033,0x72B40009,0x6EB80015,0x6CBC0034,0x23FC0088,
+0x72A00033,0x6EA80026,0x6C9C0034,0x6A000088,0xACC80002,0xFECC0024,0xF0D00037,0x86C80002,0x7AC80002,0x74C80002,0x72C80002,0x72C40002,0xA8BC0001,0x88C00001,0x72C40009,0x6EB80015,0x1C80088,0xDC0033,0x80D8000A,0x76D4000A,0x72D4000A,0x7AD40013,0x76D00002,0x72D40001,0x72D40013,0x72D00005,0x6ED00015,0x3440033,0x78C80009,0x72CC000A,0x76C40012,0x72C40001,
+0x6ECC0014,0x27FC0033,0x72B40008,0x6EB80014,0x6C000034,0x3440033,0x78C80009,0x72CC000A,0x76C40012,0x72C40001,0x6ECC0014,0x27FC0033,0x72B40008,0x6EB80014,0x6C000034,0x27FC0033,0x72B40008,0x6EB80014,0x6C000034,0x6C000034,0xACC80001,0xC2D40013,0xD4D8000A,0x86C80001,0x7AC80001,0x74C80001,0x72C80001,0x72C40001,0xA8BC0001,0x84C40001,0x72C40009,0x6EB80014,
+0x1D40033,0xD00033,0xD00033,0xD00033,0xD00033,0x7ACC0012,0x7ACC0012,0x7ACC0012,0x70CC0012,0x70CC0012,0x6CCC0012,0x78C80009,0x78C80009,0x78C80009,0x70C80002,0x70C80002,0x6CC80005,0x6EC40009,0x6EC40009,0x6CC40001,0x6AC40009,0x1340033,0x1340033,0x1340033,0x72C00012,0x72C00012,0x6CC40012,0x70BC0009,0x70BC0009,0x6CBC0001,0x6ABC0009,0x1FF80033,
+0x1FF80033,0x6CB00012,0x6AA40008,0x68000034,0xA0C80002,0xCECC0012,0xD00033,0x84C80001,0x7AC80001,0x74C80001,0x72C80002,0x70C40002,0xA8BC0000,0x82C40001,0x72C40008,0x6CBC0001,0x1B80033,0xD4000A,0xD4000A,0xD4000A,0xD4000A,0x72D40001,0x72D40001,0x72D40001,0x6ED00001,0x6ED00001,0x6CD00001,0x33C0008,0x33C0008,0x33C0008,0x6ECC0001,0x6ECC0001,
+0x6CCC0001,0x23FC0008,0x23FC0008,0x6CC00000,0x6A000008,0x33C0008,0x33C0008,0x33C0008,0x6ECC0001,0x6ECC0001,0x6CCC0001,0x23FC0008,0x23FC0008,0x6CC00000,0x6A000008,0x23FC0008,0x23FC0008,0x6CC00000,0x6A000008,0x6A000008,0x94CC0000,0x92D40001,0xD4000A,0x84C80000,0x76CC0000,0x72CC0000,0x70CC0000,0x6ECC0001,0x96C40000,0x7EC80000,0x1C80008,0x6CC00000,
+0x1C80008,0xE00012,0x7CDC0001,0x74DC0001,0x72D80001,0x14C0012,0x76D00001,0x72D40000,0x2BF80012,0x72C00000,0x6E000014,0x14C0012,0x76D00001,0x72D40000,0x2BF80012,0x72C00000,0x6E000014,0x2BF80012,0x72C00000,0x6E000014,0x6E000014,0x14C0012,0x76D00001,0x72D40000,0x2BF80012,0x72C00000,0x6E000014,0x2BF80012,0x72C00000,0x6E000014,0x6E000014,0x2BF80012,
+0x72C00000,0x6E000014,0x6E000014,0x6E000014,0xBCC00000,0xEEC0012,0xB6DC0001,0x8AC40000,0x7AC80001,0x76C40000,0x72C80000,0x72B80000,0xB0B80000,0x88C00000,0x72CC0001,0x6E000014,0x1DC0012,0xCC0012,0xCC0012,0xCC0012,0xCC0012,0xCC0012,0xCC0012,0xCC0012,0xCC0012,0xCC0012,0xCC0012,0x72C80001,0x72C80001,0x72C80001,0x72C80001,0x72C80001,
+0x72C80001,0x6AC80001,0x6AC80001,0x6AC80001,0x68C40001,0x1300012,0x1300012,0x1300012,0x1300012,0x1300012,0x1300012,0x6CBC0001,0x6CBC0001,0x6CBC0001,0x68C00000,0x1DF40012,0x1DF40012,0x1DF40012,0x68AC0000,0x64000014,0xACC80001,0xCC0012,0xCC0012,0x84C80001,0x7AC80001,0x74C80001,0x74C80001,0x70C80001,0xA8BC0000,0x8AC00000,0x6EC40000,0x6CBC0001,
+0x1B00012,};
+static const uint32_t g_etc1_to_bc7_m6_table14[] = {
+0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x23FC0000,
+0x23FC0000,0x23FC0000,0x23FC0000,0x6A000000,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xE40000,0xE40000,0xE40000,0x33C0000,0x1C80000,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,
+0x1500000,0x2DF80000,0x2DF80000,0x2DF80000,0x70000000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x2DF80000,0x2DF80000,0x2DF80000,0x70000000,0x2DF80000,0x2DF80000,0x2DF80000,0x70000000,0x70000000,0xF00000,0xE00001,0xE00001,0x7040000,0x11C0000,0x1340000,0x1340000,0x17C0000,0x7040000,0x11C0000,0x1E00000,0x2DF80000,
+0x1E00000,0xE80001,0xE80001,0xE80001,0xE80001,0x15C0000,0x15C0000,0x15C0000,0x33F80000,0x33F80000,0x74000000,0x15C0000,0x15C0000,0x15C0000,0x33F80000,0x33F80000,0x74000000,0x33F80000,0x33F80000,0x74000000,0x74000000,0x15C0000,0x15C0000,0x15C0000,0x33F80000,0x33F80000,0x74000000,0x33F80000,0x33F80000,0x74000000,0x74000000,0x33F80000,
+0x33F80000,0x74000000,0x74000000,0x74000000,0x1100000,0x4F80000,0xE80001,0x33C0000,0x1880000,0x1F00000,0x17FC0000,0x43FC0000,0x1240000,0x15C0000,0x1F00000,0x74000000,0x1F00000,0xF40001,0x16C0000,0x3BFC0000,0x7A000000,0x16C0000,0x3BFC0000,0x7A000000,0x3BFC0000,0x7A000000,0x7A000000,0x16C0000,0x3BFC0000,0x7A000000,0x3BFC0000,0x7A000000,
+0x7A000000,0x3BFC0000,0x7A000000,0x7A000000,0x7A000000,0x16C0000,0x3BFC0000,0x7A000000,0x3BFC0000,0x7A000000,0x7A000000,0x3BFC0000,0x7A000000,0x7A000000,0x7A000000,0x3BFC0000,0x7A000000,0x7A000000,0x7A000000,0x7A000000,0x1340000,0xB040000,0xB040000,0x19C0000,0x21FC0000,0x59FC0000,0x7A000000,0x7A000000,0x34C0000,0x1CC0000,0x73D80000,0x7A000000,
+0x7FC0000,0xE4008C,0x90E00033,0x80E00033,0x7AE00033,0x8ADC0024,0x80DC0013,0x7CDC001A,0x7CDC0024,0x78DC0016,0x76DC0026,0x88D80034,0x80D8000A,0x7CD8000F,0x7ED40013,0x7AD40002,0x76D80016,0x7AD80034,0x78D4000F,0x76D40019,0x74D40035,0x1540088,0x84CC0033,0x7AD40033,0x7ECC0026,0x7AD00012,0x76D40026,0x80C00033,0x7AC40009,0x76C80015,0x74CC0034,0x2FFC0088,
+0x7AB00033,0x76B80026,0x74AC0034,0x72000088,0xB4D80002,0xF6DC0026,0xF8E00037,0x8ED80002,0x82D80002,0x7CD80002,0x7AD80002,0x7AD40002,0xB0CC0001,0x90D00001,0x7AD40009,0x76C80015,0x1E80088,0xEC0033,0x88E8000A,0x7EE4000A,0x7AE4000A,0x82E40013,0x7EE00002,0x7AE40001,0x7AE40013,0x7AE00005,0x76E00015,0x35C0033,0x80D80009,0x7ADC000A,0x7ED40012,0x7AD40001,
+0x76DC0014,0x33FC0033,0x7AC40008,0x76C80014,0x74000034,0x35C0033,0x80D80009,0x7ADC000A,0x7ED40012,0x7AD40001,0x76DC0014,0x33FC0033,0x7AC40008,0x76C80014,0x74000034,0x33FC0033,0x7AC40008,0x76C80014,0x74000034,0x74000034,0xB4D80001,0xCAE40013,0xDCE8000A,0x8ED80001,0x82D80001,0x7CD80001,0x7AD80001,0x7AD40001,0xB0CC0001,0x8CD40001,0x7AD40009,0x76C80014,
+0x1F40033,0xE00033,0xE00033,0xE00033,0xE00033,0x82DC0012,0x82DC0012,0x82DC0012,0x78DC0012,0x78DC0012,0x74DC0012,0x80D80009,0x80D80009,0x80D80009,0x78D80002,0x78D80002,0x74D80005,0x76D40009,0x76D40009,0x74D40001,0x72D40009,0x14C0033,0x14C0033,0x14C0033,0x7AD00012,0x7AD00012,0x74D40012,0x78CC0009,0x78CC0009,0x74CC0001,0x72CC0009,0x2BF80033,
+0x2BF80033,0x74C00012,0x72B40008,0x70000034,0xA8D80002,0xD6DC0012,0xE00033,0x8CD80001,0x82D80001,0x7CD80001,0x7AD80002,0x78D40002,0xB0CC0000,0x8AD40001,0x7AD40008,0x74CC0001,0x1DC0033,0xE4000A,0xE4000A,0xE4000A,0xE4000A,0x7AE40001,0x7AE40001,0x7AE40001,0x76E00001,0x76E00001,0x74E00001,0x1540008,0x1540008,0x1540008,0x76DC0001,0x76DC0001,
+0x74DC0001,0x2FFC0008,0x2FFC0008,0x74D00000,0x72000008,0x1540008,0x1540008,0x1540008,0x76DC0001,0x76DC0001,0x74DC0001,0x2FFC0008,0x2FFC0008,0x74D00000,0x72000008,0x2FFC0008,0x2FFC0008,0x74D00000,0x72000008,0x72000008,0x9CDC0000,0x9AE40001,0xE4000A,0x8CD80000,0x7EDC0000,0x7ADC0000,0x78DC0000,0x76DC0001,0x9ED40000,0x86D80000,0x1E80008,0x74D00000,
+0x1E80008,0xF00012,0x84EC0001,0x7CEC0001,0x7AE80001,0x1640012,0x7EE00001,0x7AE40000,0x37F80012,0x7AD00000,0x76000014,0x1640012,0x7EE00001,0x7AE40000,0x37F80012,0x7AD00000,0x76000014,0x37F80012,0x7AD00000,0x76000014,0x76000014,0x1640012,0x7EE00001,0x7AE40000,0x37F80012,0x7AD00000,0x76000014,0x37F80012,0x7AD00000,0x76000014,0x76000014,0x37F80012,
+0x7AD00000,0x76000014,0x76000014,0x76000014,0xC4D00000,0x1000012,0xBEEC0001,0x92D40000,0x82D80001,0x7ED40000,0x7AD80000,0x7AC80000,0xB8C80000,0x90D00000,0x7ADC0001,0x76000014,0x1FC0012,0xDC0012,0xDC0012,0xDC0012,0xDC0012,0xDC0012,0xDC0012,0xDC0012,0xDC0012,0xDC0012,0xDC0012,0x7AD80001,0x7AD80001,0x7AD80001,0x7AD80001,0x7AD80001,
+0x7AD80001,0x72D80001,0x72D80001,0x72D80001,0x70D40001,0x3440012,0x3440012,0x3440012,0x3440012,0x3440012,0x3440012,0x74CC0001,0x74CC0001,0x74CC0001,0x70D00000,0x27FC0012,0x27FC0012,0x27FC0012,0x70BC0000,0x6C000014,0xB4D80001,0xDC0012,0xDC0012,0x8CD80001,0x82D80001,0x7CD80001,0x7CD80001,0x78D80001,0xB0CC0000,0x92D00000,0x76D40000,0x74CC0001,
+0x1D40012,};
+static const uint32_t g_etc1_to_bc7_m6_table15[] = {
+0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x2FFC0000,
+0x2FFC0000,0x2FFC0000,0x2FFC0000,0x72000000,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0x2F40000,0x2F40000,0x2F40000,0x1540000,0x1E80000,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,
+0x1680000,0x39F80000,0x39F80000,0x39F80000,0x78000000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x39F80000,0x39F80000,0x39F80000,0x78000000,0x39F80000,0x39F80000,0x39F80000,0x78000000,0x78000000,0x9000000,0xF00001,0xF00001,0x3180000,0x1300000,0x1480000,0x1480000,0x3940000,0x3180000,0x1300000,0x3FC0000,0x39F80000,
+0x3FC0000,0xF80001,0xF80001,0xF80001,0xF80001,0x1740000,0x1740000,0x1740000,0x3FF80000,0x3FF80000,0x7C000000,0x1740000,0x1740000,0x1740000,0x3FF80000,0x3FF80000,0x7C000000,0x3FF80000,0x3FF80000,0x7C000000,0x7C000000,0x1740000,0x1740000,0x1740000,0x3FF80000,0x3FF80000,0x7C000000,0x3FF80000,0x3FF80000,0x7C000000,0x7C000000,0x3FF80000,
+0x3FF80000,0x7C000000,0x7C000000,0x7C000000,0x7200000,0xD080000,0xF80001,0x1540000,0x1A40000,0xBFC0000,0x25FC0000,0x4FF80000,0x1380000,0x1740000,0xBFC0000,0x7C000000,0xBFC0000,0x1040001,0x1840000,0x47FC0000,0x82000000,0x1840000,0x47FC0000,0x82000000,0x47FC0000,0x82000000,0x82000000,0x1840000,0x47FC0000,0x82000000,0x47FC0000,0x82000000,
+0x82000000,0x47FC0000,0x82000000,0x82000000,0x82000000,0x1840000,0x47FC0000,0x82000000,0x47FC0000,0x82000000,0x82000000,0x47FC0000,0x82000000,0x82000000,0x82000000,0x47FC0000,0x82000000,0x82000000,0x82000000,0x82000000,0x1480000,0x1180000,0x1180000,0x1B80000,0x2FFC0000,0x65F00000,0x82000000,0x82000000,0x1640000,0x1EC0000,0x7BE80000,0x82000000,
+0x17FC0000,0xF4008C,0x98F00033,0x88F00033,0x82F00033,0x92EC0024,0x88EC0013,0x84EC001A,0x84EC0024,0x80EC0016,0x7EEC0026,0x90E80034,0x88E8000A,0x84E8000F,0x86E40013,0x82E40002,0x7EE80016,0x82E80034,0x80E4000F,0x7EE40019,0x7CE40035,0x16C0088,0x8CDC0033,0x82E40033,0x86DC0026,0x82E00012,0x7EE40026,0x88D00033,0x82D40009,0x7ED80015,0x7CDC0034,0x3BFC0088,
+0x82C00033,0x7EC80026,0x7CBC0034,0x7A000088,0xBCE80002,0xFEEC0026,0xF0F0003C,0x96E80002,0x8AE80002,0x84E80002,0x82E80002,0x82E40002,0xB8DC0001,0x98E00001,0x82E40009,0x7ED80015,0x7FC0088,0xFC0033,0x90F8000A,0x86F4000A,0x82F4000A,0x8AF40013,0x86F00002,0x82F40001,0x82F40013,0x82F00005,0x7EF00015,0x3740033,0x88E80009,0x82EC000A,0x86E40012,0x82E40001,
+0x7EEC0014,0x3FFC0033,0x82D40008,0x7ED80014,0x7C000034,0x3740033,0x88E80009,0x82EC000A,0x86E40012,0x82E40001,0x7EEC0014,0x3FFC0033,0x82D40008,0x7ED80014,0x7C000034,0x3FFC0033,0x82D40008,0x7ED80014,0x7C000034,0x7C000034,0xBCE80001,0xD2F40013,0xE4F8000A,0x96E80001,0x8AE80001,0x84E80001,0x82E80001,0x82E40001,0xB8DC0001,0x94E40001,0x82E40009,0x7ED80014,
+0xDFC0033,0xF00033,0xF00033,0xF00033,0xF00033,0x8AEC0012,0x8AEC0012,0x8AEC0012,0x80EC0012,0x80EC0012,0x7CEC0012,0x88E80009,0x88E80009,0x88E80009,0x80E80002,0x80E80002,0x7CE80005,0x7EE40009,0x7EE40009,0x7CE40001,0x7AE40009,0x1640033,0x1640033,0x1640033,0x82E00012,0x82E00012,0x7CE40012,0x80DC0009,0x80DC0009,0x7CDC0001,0x7ADC0009,0x37F80033,
+0x37F80033,0x7CD00012,0x7AC40008,0x78000034,0xB0E80002,0xDEEC0012,0xF00033,0x94E80001,0x8AE80001,0x84E80001,0x82E80002,0x80E40002,0xB8DC0000,0x92E40001,0x82E40008,0x7CDC0001,0x1FC0033,0xF4000A,0xF4000A,0xF4000A,0xF4000A,0x82F40001,0x82F40001,0x82F40001,0x7EF00001,0x7EF00001,0x7CF00001,0x16C0008,0x16C0008,0x16C0008,0x7EEC0001,0x7EEC0001,
+0x7CEC0001,0x3BFC0008,0x3BFC0008,0x7CE00000,0x7A000008,0x16C0008,0x16C0008,0x16C0008,0x7EEC0001,0x7EEC0001,0x7CEC0001,0x3BFC0008,0x3BFC0008,0x7CE00000,0x7A000008,0x3BFC0008,0x3BFC0008,0x7CE00000,0x7A000008,0x7A000008,0xA4EC0000,0xA2F40001,0xF4000A,0x94E80000,0x86EC0000,0x82EC0000,0x80EC0000,0x7EEC0001,0xA6E40000,0x8EE80000,0x7FC0008,0x7CE00000,
+0x7FC0008,0x1000012,0x8CFC0001,0x84FC0001,0x82F80001,0x17C0012,0x86F00001,0x82F40000,0x43F80012,0x82E00000,0x7E000014,0x17C0012,0x86F00001,0x82F40000,0x43F80012,0x82E00000,0x7E000014,0x43F80012,0x82E00000,0x7E000014,0x7E000014,0x17C0012,0x86F00001,0x82F40000,0x43F80012,0x82E00000,0x7E000014,0x43F80012,0x82E00000,0x7E000014,0x7E000014,0x43F80012,
+0x82E00000,0x7E000014,0x7E000014,0x7E000014,0xCCE00000,0x1100012,0xC6FC0001,0x9AE40000,0x8AE80001,0x86E40000,0x82E80000,0x82D80000,0xC0D80000,0x98E00000,0x82EC0001,0x7E000014,0x11FC0012,0xEC0012,0xEC0012,0xEC0012,0xEC0012,0xEC0012,0xEC0012,0xEC0012,0xEC0012,0xEC0012,0xEC0012,0x82E80001,0x82E80001,0x82E80001,0x82E80001,0x82E80001,
+0x82E80001,0x7AE80001,0x7AE80001,0x7AE80001,0x78E40001,0x35C0012,0x35C0012,0x35C0012,0x35C0012,0x35C0012,0x35C0012,0x7CDC0001,0x7CDC0001,0x7CDC0001,0x78E00000,0x33FC0012,0x33FC0012,0x33FC0012,0x78CC0000,0x74000014,0xBCE80001,0xEC0012,0xEC0012,0x94E80001,0x8AE80001,0x84E80001,0x84E80001,0x80E80001,0xB8DC0000,0x9AE00000,0x7EE40000,0x7CDC0001,
+0x1F40012,};
+static const uint32_t g_etc1_to_bc7_m6_table16[] = {
+0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x3DF80000,
+0x3DF80000,0x3DF80000,0x3DF80000,0x7A000001,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0x1080000,0x1080000,0x1080000,0x1700000,0x9FC0000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x3800000,0x3800000,0x3800000,0x3800000,0x3800000,
+0x3800000,0x45FC0000,0x45FC0000,0x45FC0000,0x80000001,0x3800000,0x3800000,0x3800000,0x3800000,0x3800000,0x3800000,0x45FC0000,0x45FC0000,0x45FC0000,0x80000001,0x45FC0000,0x45FC0000,0x45FC0000,0x80000001,0x80000001,0x3140000,0x1040000,0x1040000,0x52C0000,0x3440000,0x1600000,0x1600000,0x1B40000,0x52C0000,0x3440000,0x15FC0000,0x45FC0000,
+0x15FC0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x38C0000,0x38C0000,0x38C0000,0x4BFC0000,0x4BFC0000,0x84000001,0x38C0000,0x38C0000,0x38C0000,0x4BFC0000,0x4BFC0000,0x84000001,0x4BFC0000,0x4BFC0000,0x84000001,0x84000001,0x38C0000,0x38C0000,0x38C0000,0x4BFC0000,0x4BFC0000,0x84000001,0x4BFC0000,0x4BFC0000,0x84000001,0x84000001,0x4BFC0000,
+0x4BFC0000,0x84000001,0x84000001,0x84000001,0x1380000,0x71C0000,0x10C0000,0x16C0000,0x3C00000,0x1DF80000,0x35F80000,0x5BF80000,0x1500000,0x38C0000,0x1DF80000,0x84000001,0x1DF80000,0x1180000,0x1A00000,0x55F80000,0x8A000001,0x1A00000,0x55F80000,0x8A000001,0x55F80000,0x8A000001,0x8A000001,0x1A00000,0x55F80000,0x8A000001,0x55F80000,0x8A000001,
+0x8A000001,0x55F80000,0x8A000001,0x8A000001,0x8A000001,0x1A00000,0x55F80000,0x8A000001,0x55F80000,0x8A000001,0x8A000001,0x55F80000,0x8A000001,0x8A000001,0x8A000001,0x55F80000,0x8A000001,0x8A000001,0x8A000001,0x8A000001,0x1600000,0xD280000,0xD280000,0x3D40000,0x3FF80000,0x6FF80000,0x8A000001,0x8A000001,0x17C0000,0xBFC0000,0x85DC0000,0x8A000001,
+0x27FC0000,0x1080088,0x9F040034,0x91040034,0x8B040035,0x9B000026,0x91000015,0x8B000019,0x8D000026,0x8AFC0016,0x88FC0026,0x9CF80033,0x92F80009,0x8CFC000F,0x8EF80012,0x8AF80002,0x88F80016,0x8CF80033,0x8AF4000F,0x88F4001A,0x86F80033,0x1880088,0x96EC0033,0x8AF80034,0x90EC0026,0x8CF00013,0x88F40024,0x90E40033,0x8AEC000A,0x88E80013,0x86EC0033,0x49F80088,
+0x8AD80034,0x88D40024,0x86C80033,0x8200008C,0xC4F80002,0xF9000028,0xFB040038,0xA2F80001,0x94F80002,0x8EF80002,0x8CF80002,0x8AF80002,0xBEF00001,0x9EF40001,0x8CF40009,0x88E80013,0x19FC0088,0x10C0034,0x9B080008,0x8F080009,0x8B080009,0x97040012,0x8F040001,0x8D040001,0x8D040012,0x8B040005,0x89040012,0x1900033,0x90FC0009,0x8B000009,0x8EF80012,0x8AF80002,
+0x88FC0012,0x4DFC0033,0x8AEC0009,0x88E80012,0x86000033,0x1900033,0x90FC0009,0x8B000009,0x8EF80012,0x8AF80002,0x88FC0012,0x4DFC0033,0x8AEC0009,0x88E80012,0x86000033,0x4DFC0033,0x8AEC0009,0x88E80012,0x86000033,0x86000033,0xC0FC0001,0xEB040012,0xFD080008,0x9CFC0001,0x94F80002,0x8EF80002,0x8AFC0002,0x8AF40002,0xBEF00001,0x9AF80001,0x8CF40008,0x88E80012,
+0x1FF80033,0x1040034,0x1040034,0x1040034,0x1040034,0x91000014,0x91000014,0x91000014,0x89000014,0x89000014,0x84FC0015,0x92F80008,0x92F80008,0x92F80008,0x8AF80001,0x8AF80001,0x86F80005,0x86F8000A,0x86F8000A,0x84F80001,0x82F8000A,0x1800033,0x1800033,0x1800033,0x8CF00012,0x8CF00012,0x84F80013,0x8AEC0009,0x8AEC0009,0x84F00002,0x82F0000A,0x45F80033,
+0x45F80033,0x84E40013,0x82DC000A,0x80000033,0xC4F80001,0xD9000014,0x1040034,0xA0F80001,0x94F80001,0x8EF80001,0x8CF80001,0x88F80001,0xBCF00000,0x9EF40000,0x8AF80009,0x84F00002,0x13FC0033,0x1080008,0x1080008,0x1080008,0x1080008,0x8D040000,0x8D040000,0x8D040000,0x87040001,0x87040001,0x85040001,0x1880008,0x1880008,0x1880008,0x87000001,0x87000001,
+0x85000001,0x49F80008,0x49F80008,0x84F80001,0x8200000A,0x1880008,0x1880008,0x1880008,0x87000001,0x87000001,0x85000001,0x49F80008,0x49F80008,0x84F80001,0x8200000A,0x49F80008,0x49F80008,0x84F80001,0x8200000A,0x8200000A,0xB6FC0000,0xBB040000,0x1080008,0x9AFC0000,0x90FC0000,0x8CFC0000,0x89000001,0x88FC0000,0xB2F40000,0x98F80000,0x19FC0008,0x84F80001,
+0x19FC0008,0x1100014,0x970C0000,0x8F0C0000,0x8B0C0001,0x1980012,0x8F040001,0x8B080001,0x51F80012,0x8AF80001,0x88000012,0x1980012,0x8F040001,0x8B080001,0x51F80012,0x8AF80001,0x88000012,0x51F80012,0x8AF80001,0x88000012,0x88000012,0x1980012,0x8F040001,0x8B080001,0x51F80012,0x8AF80001,0x88000012,0x51F80012,0x8AF80001,0x88000012,0x88000012,0x51F80012,
+0x8AF80001,0x88000012,0x88000012,0x88000012,0xD0F40000,0x1240012,0xDF0C0000,0xA2F80000,0x94F80001,0x90F40000,0x8AFC0001,0x8AF00001,0xC6EC0000,0xA2F00000,0x8CFC0000,0x88000012,0x21FC0012,0xFC0014,0xFC0014,0xFC0014,0xFC0014,0xFC0014,0xFC0014,0xFC0014,0xFC0014,0xFC0014,0xFC0014,0x8CF80000,0x8CF80000,0x8CF80000,0x8CF80000,0x8CF80000,
+0x8CF80000,0x84F80000,0x84F80000,0x84F80000,0x80F80001,0x1780012,0x1780012,0x1780012,0x1780012,0x1780012,0x1780012,0x84F00001,0x84F00001,0x84F00001,0x80F40001,0x41FC0012,0x41FC0012,0x41FC0012,0x80E40001,0x7E000012,0xD4F80000,0xFC0014,0xFC0014,0xA4F80000,0x98F80000,0x90F80000,0x90F80000,0x8AF80000,0xBCF00000,0x9EF40000,0x86F80001,0x84F00001,
+0xFFC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table17[] = {
+0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x49F80000,
+0x49F80000,0x49F80000,0x49F80000,0x82000001,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x5180000,0x5180000,0x5180000,0x1880000,0x19FC0000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,
+0x3980000,0x51FC0000,0x51FC0000,0x51FC0000,0x88000001,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,0x51FC0000,0x51FC0000,0x51FC0000,0x88000001,0x51FC0000,0x51FC0000,0x51FC0000,0x88000001,0x88000001,0xB240000,0x1140000,0x1140000,0x1400000,0x3580000,0x1780000,0x1780000,0x1D00000,0x1400000,0x3580000,0x23FC0000,0x51FC0000,
+0x23FC0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x3A40000,0x3A40000,0x3A40000,0x57FC0000,0x57FC0000,0x8C000001,0x3A40000,0x3A40000,0x3A40000,0x57FC0000,0x57FC0000,0x8C000001,0x57FC0000,0x57FC0000,0x8C000001,0x8C000001,0x3A40000,0x3A40000,0x3A40000,0x57FC0000,0x57FC0000,0x8C000001,0x57FC0000,0x57FC0000,0x8C000001,0x8C000001,0x57FC0000,
+0x57FC0000,0x8C000001,0x8C000001,0x8C000001,0x5480000,0xF2C0000,0x11C0000,0x3800000,0x1DC0000,0x2BFC0000,0x41FC0000,0x65FC0000,0x1640000,0x3A40000,0x2BFC0000,0x8C000001,0x2BFC0000,0x1280000,0x1B80000,0x61F80000,0x92000001,0x1B80000,0x61F80000,0x92000001,0x61F80000,0x92000001,0x92000001,0x1B80000,0x61F80000,0x92000001,0x61F80000,0x92000001,
+0x92000001,0x61F80000,0x92000001,0x92000001,0x92000001,0x1B80000,0x61F80000,0x92000001,0x61F80000,0x92000001,0x92000001,0x61F80000,0x92000001,0x92000001,0x92000001,0x61F80000,0x92000001,0x92000001,0x92000001,0x92000001,0x1740000,0x13C0000,0x13C0000,0x1F00000,0x4BFC0000,0x79F80000,0x92000001,0x92000001,0x3900000,0x1BFC0000,0x8DEC0000,0x92000001,
+0x37FC0000,0x1180088,0xA7140034,0x99140034,0x93140035,0xA3100026,0x99100015,0x93100019,0x95100026,0x930C0016,0x910C0026,0xA5080033,0x9B080009,0x950C000F,0x97080012,0x93080002,0x91080016,0x95080033,0x9304000F,0x9104001A,0x8F080033,0x1A00088,0x9EFC0033,0x93080034,0x98FC0026,0x95000013,0x91040024,0x98F40033,0x92FC000A,0x90F80013,0x8EFC0033,0x55F80088,
+0x92E80034,0x90E40024,0x8ED80033,0x8A00008C,0xCD080002,0xF110002E,0xF314003D,0xAB080001,0x9D080002,0x97080002,0x95080002,0x93080002,0xC7000001,0xA7040001,0x95040009,0x90F80013,0x27FC0088,0x11C0034,0xA3180008,0x97180009,0x93180009,0x9F140012,0x97140001,0x95140001,0x95140012,0x93140005,0x91140012,0x1A80033,0x990C0009,0x93100009,0x97080012,0x93080002,
+0x910C0012,0x59FC0033,0x92FC0009,0x90F80012,0x8E000033,0x1A80033,0x990C0009,0x93100009,0x97080012,0x93080002,0x910C0012,0x59FC0033,0x92FC0009,0x90F80012,0x8E000033,0x59FC0033,0x92FC0009,0x90F80012,0x8E000033,0x8E000033,0xC90C0001,0xF3140012,0xF5180009,0xA50C0001,0x9D080002,0x97080002,0x930C0002,0x93040002,0xC7000001,0xA3080001,0x95040008,0x90F80012,
+0x2DFC0033,0x1140034,0x1140034,0x1140034,0x1140034,0x99100014,0x99100014,0x99100014,0x91100014,0x91100014,0x8D0C0015,0x9B080008,0x9B080008,0x9B080008,0x93080001,0x93080001,0x8F080005,0x8F08000A,0x8F08000A,0x8D080001,0x8B08000A,0x1980033,0x1980033,0x1980033,0x95000012,0x95000012,0x8D080013,0x92FC0009,0x92FC0009,0x8D000002,0x8B00000A,0x51F80033,
+0x51F80033,0x8CF40013,0x8AEC000A,0x88000033,0xCD080001,0xE1100014,0x1140034,0xA9080001,0x9D080001,0x97080001,0x95080001,0x91080001,0xC5000000,0xA7040000,0x93080009,0x8D000002,0x21FC0033,0x1180008,0x1180008,0x1180008,0x1180008,0x95140000,0x95140000,0x95140000,0x8F140001,0x8F140001,0x8D140001,0x1A00008,0x1A00008,0x1A00008,0x8F100001,0x8F100001,
+0x8D100001,0x55F80008,0x55F80008,0x8D080001,0x8A00000A,0x1A00008,0x1A00008,0x1A00008,0x8F100001,0x8F100001,0x8D100001,0x55F80008,0x55F80008,0x8D080001,0x8A00000A,0x55F80008,0x55F80008,0x8D080001,0x8A00000A,0x8A00000A,0xBF0C0000,0xC3140000,0x1180008,0xA30C0000,0x990C0000,0x950C0000,0x91100001,0x910C0000,0xBB040000,0xA1080000,0x27FC0008,0x8D080001,
+0x27FC0008,0x1200014,0x9F1C0000,0x971C0000,0x931C0001,0x1B00012,0x97140001,0x93180001,0x5DF40012,0x93080001,0x90000012,0x1B00012,0x97140001,0x93180001,0x5DF40012,0x93080001,0x90000012,0x5DF40012,0x93080001,0x90000012,0x90000012,0x1B00012,0x97140001,0x93180001,0x5DF40012,0x93080001,0x90000012,0x5DF40012,0x93080001,0x90000012,0x90000012,0x5DF40012,
+0x93080001,0x90000012,0x90000012,0x90000012,0xD9040000,0x3340012,0xE71C0000,0xAB080000,0x9D080001,0x99040000,0x930C0001,0x93000001,0xCEFC0000,0xAB000000,0x950C0000,0x90000012,0x31FC0012,0x10C0014,0x10C0014,0x10C0014,0x10C0014,0x10C0014,0x10C0014,0x10C0014,0x10C0014,0x10C0014,0x10C0014,0x95080000,0x95080000,0x95080000,0x95080000,0x95080000,
+0x95080000,0x8D080000,0x8D080000,0x8D080000,0x89080001,0x1900012,0x1900012,0x1900012,0x1900012,0x1900012,0x1900012,0x8D000001,0x8D000001,0x8D000001,0x89040001,0x4DFC0012,0x4DFC0012,0x4DFC0012,0x88F40001,0x86000012,0xDD080000,0x10C0014,0x10C0014,0xAD080000,0xA1080000,0x99080000,0x99080000,0x93080000,0xC5000000,0xA7040000,0x8F080001,0x8D000001,
+0x1FF80012,};
+static const uint32_t g_etc1_to_bc7_m6_table18[] = {
+0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x55F80000,
+0x55F80000,0x55F80000,0x55F80000,0x8A000001,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0xD280000,0xD280000,0xD280000,0x1A00000,0x27FC0000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,
+0x3B00000,0x5DFC0000,0x5DFC0000,0x5DFC0000,0x90000001,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x5DFC0000,0x5DFC0000,0x5DFC0000,0x90000001,0x5DFC0000,0x5DFC0000,0x5DFC0000,0x90000001,0x90000001,0x1380000,0x1240000,0x1240000,0x1540000,0x36C0000,0x18C0000,0x18C0000,0x1EC0000,0x1540000,0x36C0000,0x33FC0000,0x5DFC0000,
+0x33FC0000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x3BC0000,0x3BC0000,0x3BC0000,0x63FC0000,0x63FC0000,0x94000001,0x3BC0000,0x3BC0000,0x3BC0000,0x63FC0000,0x63FC0000,0x94000001,0x63FC0000,0x63FC0000,0x94000001,0x94000001,0x3BC0000,0x3BC0000,0x3BC0000,0x63FC0000,0x63FC0000,0x94000001,0x63FC0000,0x63FC0000,0x94000001,0x94000001,0x63FC0000,
+0x63FC0000,0x94000001,0x94000001,0x94000001,0x15C0000,0x1400000,0x12C0000,0x1980000,0x1F80000,0x3BFC0000,0x4FFC0000,0x71F80000,0x1780000,0x3BC0000,0x3BFC0000,0x94000001,0x3BFC0000,0x1380000,0x1D00000,0x6DF80000,0x9A000001,0x1D00000,0x6DF80000,0x9A000001,0x6DF80000,0x9A000001,0x9A000001,0x1D00000,0x6DF80000,0x9A000001,0x6DF80000,0x9A000001,
+0x9A000001,0x6DF80000,0x9A000001,0x9A000001,0x9A000001,0x1D00000,0x6DF80000,0x9A000001,0x6DF80000,0x9A000001,0x9A000001,0x6DF80000,0x9A000001,0x9A000001,0x9A000001,0x6DF80000,0x9A000001,0x9A000001,0x9A000001,0x9A000001,0x1880000,0x14C0000,0x14C0000,0xDFC0000,0x59FC0000,0x83F80000,0x9A000001,0x9A000001,0x1A80000,0x2DFC0000,0x95FC0000,0x9A000001,
+0x45FC0000,0x1280088,0xAF240034,0xA1240034,0x9B240035,0xAB200026,0xA1200015,0x9B200019,0x9D200026,0x9B1C0016,0x991C0026,0xAD180033,0xA3180009,0x9D1C000F,0x9F180012,0x9B180002,0x99180016,0x9D180033,0x9B14000F,0x9914001A,0x97180033,0x1B80088,0xA70C0033,0x9B180034,0xA10C0026,0x9D100013,0x99140024,0xA1040033,0x9B0C000A,0x99080013,0x970C0033,0x61F80088,
+0x9AF80034,0x98F40024,0x96E80033,0x9200008C,0xD5180002,0xF920002E,0xFB24003D,0xB3180001,0xA5180002,0x9F180002,0x9D180002,0x9B180002,0xCF100001,0xAF140001,0x9D140009,0x99080013,0x37FC0088,0x12C0034,0xAB280008,0x9F280009,0x9B280009,0xA7240012,0x9F240001,0x9D240001,0x9D240012,0x9B240005,0x99240012,0x1C00033,0xA11C0009,0x9B200009,0x9F180012,0x9B180002,
+0x991C0012,0x65F80033,0x9B0C0009,0x99080012,0x96000033,0x1C00033,0xA11C0009,0x9B200009,0x9F180012,0x9B180002,0x991C0012,0x65F80033,0x9B0C0009,0x99080012,0x96000033,0x65F80033,0x9B0C0009,0x99080012,0x96000033,0x96000033,0xD11C0001,0xFB240012,0xFD280009,0xAD1C0001,0xA5180002,0x9F180002,0x9B1C0002,0x9B140002,0xCF100001,0xAB180001,0x9D140008,0x99080012,
+0x3DF80033,0x1240034,0x1240034,0x1240034,0x1240034,0xA1200014,0xA1200014,0xA1200014,0x99200014,0x99200014,0x951C0015,0xA3180008,0xA3180008,0xA3180008,0x9B180001,0x9B180001,0x97180005,0x9718000A,0x9718000A,0x95180001,0x9318000A,0x1B00033,0x1B00033,0x1B00033,0x9D100012,0x9D100012,0x95180013,0x9B0C0009,0x9B0C0009,0x95100002,0x9310000A,0x5DF40033,
+0x5DF40033,0x95040013,0x92FC000A,0x90000033,0xD5180001,0xE9200014,0x1240034,0xB1180001,0xA5180001,0x9F180001,0x9D180001,0x99180001,0xCD100000,0xAF140000,0x9B180009,0x95100002,0x31FC0033,0x1280008,0x1280008,0x1280008,0x1280008,0x9D240000,0x9D240000,0x9D240000,0x97240001,0x97240001,0x95240001,0x1B80008,0x1B80008,0x1B80008,0x97200001,0x97200001,
+0x95200001,0x61F80008,0x61F80008,0x95180001,0x9200000A,0x1B80008,0x1B80008,0x1B80008,0x97200001,0x97200001,0x95200001,0x61F80008,0x61F80008,0x95180001,0x9200000A,0x61F80008,0x61F80008,0x95180001,0x9200000A,0x9200000A,0xC71C0000,0xCB240000,0x1280008,0xAB1C0000,0xA11C0000,0x9D1C0000,0x99200001,0x991C0000,0xC3140000,0xA9180000,0x37FC0008,0x95180001,
+0x37FC0008,0x1300014,0xA72C0000,0x9F2C0000,0x9B2C0001,0x3C40012,0x9F240001,0x9B280001,0x67FC0012,0x9B180001,0x98000012,0x3C40012,0x9F240001,0x9B280001,0x67FC0012,0x9B180001,0x98000012,0x67FC0012,0x9B180001,0x98000012,0x98000012,0x3C40012,0x9F240001,0x9B280001,0x67FC0012,0x9B180001,0x98000012,0x67FC0012,0x9B180001,0x98000012,0x98000012,0x67FC0012,
+0x9B180001,0x98000012,0x98000012,0x98000012,0xE1140000,0xB440012,0xEF2C0000,0xB3180000,0xA5180001,0xA1140000,0x9B1C0001,0x9B100001,0xD70C0000,0xB3100000,0x9D1C0000,0x98000012,0x3FFC0012,0x11C0014,0x11C0014,0x11C0014,0x11C0014,0x11C0014,0x11C0014,0x11C0014,0x11C0014,0x11C0014,0x11C0014,0x9D180000,0x9D180000,0x9D180000,0x9D180000,0x9D180000,
+0x9D180000,0x95180000,0x95180000,0x95180000,0x91180001,0x1A80012,0x1A80012,0x1A80012,0x1A80012,0x1A80012,0x1A80012,0x95100001,0x95100001,0x95100001,0x91140001,0x59FC0012,0x59FC0012,0x59FC0012,0x91040001,0x8E000012,0xE5180000,0x11C0014,0x11C0014,0xB5180000,0xA9180000,0xA1180000,0xA1180000,0x9B180000,0xCD100000,0xAF140000,0x97180001,0x95100001,
+0x2DFC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table19[] = {
+0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x61F80000,
+0x61F80000,0x61F80000,0x61F80000,0x92000001,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x13C0000,0x13C0000,0x13C0000,0x1B80000,0x37FC0000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,
+0x1C80000,0x69FC0000,0x69FC0000,0x69FC0000,0x98000001,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x69FC0000,0x69FC0000,0x69FC0000,0x98000001,0x69FC0000,0x69FC0000,0x69FC0000,0x98000001,0x98000001,0x1480000,0x1340000,0x1340000,0x5640000,0x3800000,0x1A40000,0x1A40000,0x7FC0000,0x5640000,0x3800000,0x41FC0000,0x69FC0000,
+0x41FC0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x1D40000,0x1D40000,0x1D40000,0x6FFC0000,0x6FFC0000,0x9C000001,0x1D40000,0x1D40000,0x1D40000,0x6FFC0000,0x6FFC0000,0x9C000001,0x6FFC0000,0x6FFC0000,0x9C000001,0x9C000001,0x1D40000,0x1D40000,0x1D40000,0x6FFC0000,0x6FFC0000,0x9C000001,0x6FFC0000,0x6FFC0000,0x9C000001,0x9C000001,0x6FFC0000,
+0x6FFC0000,0x9C000001,0x9C000001,0x9C000001,0x1700000,0x1500000,0x13C0000,0x3AC0000,0x11FC0000,0x49FC0000,0x5DF80000,0x7BFC0000,0x18C0000,0x1D40000,0x49FC0000,0x9C000001,0x49FC0000,0x1480000,0x1E80000,0x79F80000,0xA2000001,0x1E80000,0x79F80000,0xA2000001,0x79F80000,0xA2000001,0xA2000001,0x1E80000,0x79F80000,0xA2000001,0x79F80000,0xA2000001,
+0xA2000001,0x79F80000,0xA2000001,0xA2000001,0xA2000001,0x1E80000,0x79F80000,0xA2000001,0x79F80000,0xA2000001,0xA2000001,0x79F80000,0xA2000001,0xA2000001,0xA2000001,0x79F80000,0xA2000001,0xA2000001,0xA2000001,0xA2000001,0x19C0000,0x75C0000,0x75C0000,0x21FC0000,0x67F80000,0x8DF80000,0xA2000001,0xA2000001,0x3BC0000,0x3DFC0000,0x9FD00000,0xA2000001,
+0x55FC0000,0x1380088,0xB7340034,0xA9340034,0xA3340035,0xB3300026,0xA9300015,0xA3300019,0xA5300026,0xA32C0016,0xA12C0026,0xB5280033,0xAB280009,0xA52C000F,0xA7280012,0xA3280002,0xA1280016,0xA5280033,0xA324000F,0xA124001A,0x9F280033,0x1D00088,0xAF1C0033,0xA3280034,0xA91C0026,0xA5200013,0xA1240024,0xA9140033,0xA31C000A,0xA1180013,0x9F1C0033,0x6DF80088,
+0xA3080034,0xA1040024,0x9EF80033,0x9A00008C,0xDD280002,0xF1300038,0xF3340044,0xBB280001,0xAD280002,0xA7280002,0xA5280002,0xA3280002,0xD7200001,0xB7240001,0xA5240009,0xA1180013,0x45FC0088,0x13C0034,0xB3380008,0xA7380009,0xA3380009,0xAF340012,0xA7340001,0xA5340001,0xA5340012,0xA3340005,0xA1340012,0x1D80033,0xA92C0009,0xA3300009,0xA7280012,0xA3280002,
+0xA12C0012,0x71F80033,0xA31C0009,0xA1180012,0x9E000033,0x1D80033,0xA92C0009,0xA3300009,0xA7280012,0xA3280002,0xA12C0012,0x71F80033,0xA31C0009,0xA1180012,0x9E000033,0x71F80033,0xA31C0009,0xA1180012,0x9E000033,0x9E000033,0xD92C0001,0xF3340014,0xF538000C,0xB52C0001,0xAD280002,0xA7280002,0xA32C0002,0xA3240002,0xD7200001,0xB3280001,0xA5240008,0xA1180012,
+0x4BFC0033,0x1340034,0x1340034,0x1340034,0x1340034,0xA9300014,0xA9300014,0xA9300014,0xA1300014,0xA1300014,0x9D2C0015,0xAB280008,0xAB280008,0xAB280008,0xA3280001,0xA3280001,0x9F280005,0x9F28000A,0x9F28000A,0x9D280001,0x9B28000A,0x3C40033,0x3C40033,0x3C40033,0xA5200012,0xA5200012,0x9D280013,0xA31C0009,0xA31C0009,0x9D200002,0x9B20000A,0x67FC0033,
+0x67FC0033,0x9D140013,0x9B0C000A,0x98000033,0xDD280001,0xF1300014,0x1340034,0xB9280001,0xAD280001,0xA7280001,0xA5280001,0xA1280001,0xD5200000,0xB7240000,0xA3280009,0x9D200002,0x3FFC0033,0x1380008,0x1380008,0x1380008,0x1380008,0xA5340000,0xA5340000,0xA5340000,0x9F340001,0x9F340001,0x9D340001,0x1D00008,0x1D00008,0x1D00008,0x9F300001,0x9F300001,
+0x9D300001,0x6DF80008,0x6DF80008,0x9D280001,0x9A00000A,0x1D00008,0x1D00008,0x1D00008,0x9F300001,0x9F300001,0x9D300001,0x6DF80008,0x6DF80008,0x9D280001,0x9A00000A,0x6DF80008,0x6DF80008,0x9D280001,0x9A00000A,0x9A00000A,0xCF2C0000,0xD3340000,0x1380008,0xB32C0000,0xA92C0000,0xA52C0000,0xA1300001,0xA12C0000,0xCB240000,0xB1280000,0x45FC0008,0x9D280001,
+0x45FC0008,0x1400014,0xAF3C0000,0xA73C0000,0xA33C0001,0x3DC0012,0xA7340001,0xA3380001,0x73FC0012,0xA3280001,0xA0000012,0x3DC0012,0xA7340001,0xA3380001,0x73FC0012,0xA3280001,0xA0000012,0x73FC0012,0xA3280001,0xA0000012,0xA0000012,0x3DC0012,0xA7340001,0xA3380001,0x73FC0012,0xA3280001,0xA0000012,0x73FC0012,0xA3280001,0xA0000012,0xA0000012,0x73FC0012,
+0xA3280001,0xA0000012,0xA0000012,0xA0000012,0xE9240000,0x1580012,0xF73C0000,0xBB280000,0xAD280001,0xA9240000,0xA32C0001,0xA3200001,0xDF1C0000,0xBB200000,0xA52C0000,0xA0000012,0x4FFC0012,0x12C0014,0x12C0014,0x12C0014,0x12C0014,0x12C0014,0x12C0014,0x12C0014,0x12C0014,0x12C0014,0x12C0014,0xA5280000,0xA5280000,0xA5280000,0xA5280000,0xA5280000,
+0xA5280000,0x9D280000,0x9D280000,0x9D280000,0x99280001,0x1C00012,0x1C00012,0x1C00012,0x1C00012,0x1C00012,0x1C00012,0x9D200001,0x9D200001,0x9D200001,0x99240001,0x65F80012,0x65F80012,0x65F80012,0x99140001,0x96000012,0xED280000,0x12C0014,0x12C0014,0xBD280000,0xB1280000,0xA9280000,0xA9280000,0xA3280000,0xD5200000,0xB7240000,0x9F280001,0x9D200001,
+0x3DF80012,};
+static const uint32_t g_etc1_to_bc7_m6_table20[] = {
+0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x6DFC0000,
+0x6DFC0000,0x6DFC0000,0x6DFC0000,0x9C000000,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0xF4C0000,0xF4C0000,0xF4C0000,0x3D00000,0x47FC0000,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,
+0x1E40000,0x77F80000,0x77F80000,0x77F80000,0xA2000000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x77F80000,0x77F80000,0x77F80000,0xA2000000,0x77F80000,0x77F80000,0x77F80000,0xA2000000,0xA2000000,0x15C0000,0x1440001,0x1440001,0x17C0000,0x1980000,0x1BC0000,0x1BC0000,0x1DFC0000,0x17C0000,0x1980000,0x53FC0000,0x77F80000,
+0x53FC0000,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x1F00000,0x1F00000,0x1F00000,0x7DF80000,0x7DF80000,0xA6000000,0x1F00000,0x1F00000,0x1F00000,0x7DF80000,0x7DF80000,0xA6000000,0x7DF80000,0x7DF80000,0xA6000000,0xA6000000,0x1F00000,0x1F00000,0x1F00000,0x7DF80000,0x7DF80000,0xA6000000,0x7DF80000,0x7DF80000,0xA6000000,0xA6000000,0x7DF80000,
+0x7DF80000,0xA6000000,0xA6000000,0xA6000000,0x1840000,0x1640000,0x14C0001,0x3C40000,0x27FC0000,0x5BFC0000,0x6BFC0000,0x87FC0000,0x5A00000,0x1F00000,0x5BFC0000,0xA6000000,0x5BFC0000,0x1580001,0x7FC0000,0x85FC0000,0xAC000000,0x7FC0000,0x85FC0000,0xAC000000,0x85FC0000,0xAC000000,0xAC000000,0x7FC0000,0x85FC0000,0xAC000000,0x85FC0000,0xAC000000,
+0xAC000000,0x85FC0000,0xAC000000,0xAC000000,0xAC000000,0x7FC0000,0x85FC0000,0xAC000000,0x85FC0000,0xAC000000,0xAC000000,0x85FC0000,0xAC000000,0xAC000000,0xAC000000,0x85FC0000,0xAC000000,0xAC000000,0xAC000000,0xAC000000,0x3B00000,0x1700000,0x1700000,0x37FC0000,0x75FC0000,0x99F40000,0xAC000000,0xAC000000,0x3D40000,0x51FC0000,0xA9C40000,0xAC000000,
+0x65FC0000,0x148008C,0xC3440033,0xB3440033,0xAD440033,0xBD400024,0xB3400013,0xAF40001A,0xAF400024,0xAB400016,0xA9400026,0xBB3C0034,0xB33C000A,0xAF3C000F,0xB1380013,0xAD380002,0xA93C0016,0xAD3C0034,0xAB38000F,0xA9380019,0xA7380035,0x3E80088,0xB7300033,0xAD380033,0xB1300026,0xAD340012,0xA9380026,0xB3240033,0xAD280009,0xA92C0015,0xA7300034,0x79FC0088,
+0xAD140033,0xA91C0026,0xA7100034,0xA4000088,0xE73C0002,0xFB440034,0xFD480044,0xC13C0002,0xB53C0002,0xAF3C0002,0xAD3C0002,0xAD380002,0xE3300001,0xC3340001,0xAD380009,0xA92C0015,0x57FC0088,0x1500033,0xBB4C000A,0xB148000A,0xAD48000A,0xB5480013,0xB1440002,0xAD480001,0xAD480013,0xAD440005,0xA9440015,0x1F40033,0xB33C0009,0xAD40000A,0xB1380012,0xAD380001,
+0xA9400014,0x7FF80033,0xAD280008,0xA92C0014,0xA6000034,0x1F40033,0xB33C0009,0xAD40000A,0xB1380012,0xAD380001,0xA9400014,0x7FF80033,0xAD280008,0xA92C0014,0xA6000034,0x7FF80033,0xAD280008,0xA92C0014,0xA6000034,0xA6000034,0xE73C0001,0xFD480013,0xFF4C000B,0xC13C0001,0xB53C0001,0xAF3C0001,0xAD3C0001,0xAD380001,0xE3300001,0xBF380001,0xAD380009,0xA92C0014,
+0x5DF80033,0x1440033,0x1440033,0x1440033,0x1440033,0xB5400012,0xB5400012,0xB5400012,0xAB400012,0xAB400012,0xA7400012,0xB33C0009,0xB33C0009,0xB33C0009,0xAB3C0002,0xAB3C0002,0xA73C0005,0xA9380009,0xA9380009,0xA7380001,0xA5380009,0x1E00033,0x1E00033,0x1E00033,0xAD340012,0xAD340012,0xA7380012,0xAB300009,0xAB300009,0xA7300001,0xA5300009,0x75FC0033,
+0x75FC0033,0xA7240012,0xA5180008,0xA2000034,0xDB3C0002,0xF9400013,0x1440033,0xBF3C0001,0xB53C0001,0xAF3C0001,0xAD3C0002,0xAB380002,0xE3300000,0xBD380001,0xAD380008,0xA7300001,0x51FC0033,0x148000A,0x148000A,0x148000A,0x148000A,0xAD480001,0xAD480001,0xAD480001,0xA9440001,0xA9440001,0xA7440001,0x3E80008,0x3E80008,0x3E80008,0xA9400001,0xA9400001,
+0xA7400001,0x79FC0008,0x79FC0008,0xA7340000,0xA4000008,0x3E80008,0x3E80008,0x3E80008,0xA9400001,0xA9400001,0xA7400001,0x79FC0008,0x79FC0008,0xA7340000,0xA4000008,0x79FC0008,0x79FC0008,0xA7340000,0xA4000008,0xA4000008,0xCF400000,0xCD480001,0x148000A,0xBF3C0000,0xB1400000,0xAD400000,0xAB400000,0xA9400001,0xD1380000,0xB93C0000,0x57FC0008,0xA7340000,
+0x57FC0008,0x1540012,0xB7500001,0xAF500001,0xAD4C0001,0x1F80012,0xB1440001,0xAD480000,0x81FC0012,0xAD340000,0xA8000014,0x1F80012,0xB1440001,0xAD480000,0x81FC0012,0xAD340000,0xA8000014,0x81FC0012,0xAD340000,0xA8000014,0xA8000014,0x1F80012,0xB1440001,0xAD480000,0x81FC0012,0xAD340000,0xA8000014,0x81FC0012,0xAD340000,0xA8000014,0xA8000014,0x81FC0012,
+0xAD340000,0xA8000014,0xA8000014,0xA8000014,0xF7340000,0xD680012,0xF1500001,0xC5380000,0xB53C0001,0xB1380000,0xAD3C0000,0xAD2C0000,0xEB2C0000,0xC3340000,0xAD400001,0xA8000014,0x5FFC0012,0x1400012,0x1400012,0x1400012,0x1400012,0x1400012,0x1400012,0x1400012,0x1400012,0x1400012,0x1400012,0xAD3C0001,0xAD3C0001,0xAD3C0001,0xAD3C0001,0xAD3C0001,
+0xAD3C0001,0xA53C0001,0xA53C0001,0xA53C0001,0xA3380001,0x1DC0012,0x1DC0012,0x1DC0012,0x1DC0012,0x1DC0012,0x1DC0012,0xA7300001,0xA7300001,0xA7300001,0xA3340000,0x73F80012,0x73F80012,0x73F80012,0xA3200000,0x9E000014,0xE73C0001,0x1400012,0x1400012,0xBF3C0001,0xB53C0001,0xAF3C0001,0xAF3C0001,0xAB3C0001,0xE3300000,0xC5340000,0xA9380000,0xA7300001,
+0x4DFC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table21[] = {
+0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x79FC0000,
+0x79FC0000,0x79FC0000,0x79FC0000,0xA4000000,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1600000,0x1600000,0x1600000,0x3E80000,0x57FC0000,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,
+0x1FC0000,0x83F80000,0x83F80000,0x83F80000,0xAA000000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x83F80000,0x83F80000,0x83F80000,0xAA000000,0x83F80000,0x83F80000,0x83F80000,0xAA000000,0xAA000000,0x16C0000,0x1540001,0x1540001,0x38C0000,0x1AC0000,0x1D00000,0x1D00000,0x31FC0000,0x38C0000,0x1AC0000,0x61FC0000,0x83F80000,
+0x61FC0000,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0xDFC0000,0xDFC0000,0xDFC0000,0x89F80000,0x89F80000,0xAE000000,0xDFC0000,0xDFC0000,0xDFC0000,0x89F80000,0x89F80000,0xAE000000,0x89F80000,0x89F80000,0xAE000000,0xAE000000,0xDFC0000,0xDFC0000,0xDFC0000,0x89F80000,0x89F80000,0xAE000000,0x89F80000,0x89F80000,0xAE000000,0xAE000000,0x89F80000,
+0x89F80000,0xAE000000,0xAE000000,0xAE000000,0x1980000,0x3740000,0x15C0001,0x1DC0000,0x3BFC0000,0x69FC0000,0x79FC0000,0x93F80000,0x5B40000,0xDFC0000,0x69FC0000,0xAE000000,0x69FC0000,0x1680001,0x1FFC0000,0x91FC0000,0xB4000000,0x1FFC0000,0x91FC0000,0xB4000000,0x91FC0000,0xB4000000,0xB4000000,0x1FFC0000,0x91FC0000,0xB4000000,0x91FC0000,0xB4000000,
+0xB4000000,0x91FC0000,0xB4000000,0xB4000000,0xB4000000,0x1FFC0000,0x91FC0000,0xB4000000,0x91FC0000,0xB4000000,0xB4000000,0x91FC0000,0xB4000000,0xB4000000,0xB4000000,0x91FC0000,0xB4000000,0xB4000000,0xB4000000,0xB4000000,0x3C40000,0x9800000,0x9800000,0x4BFC0000,0x83FC0000,0xA3F40000,0xB4000000,0xB4000000,0x1EC0000,0x63FC0000,0xB1D40000,0xB4000000,
+0x75FC0000,0x158008C,0xCB540033,0xBB540033,0xB5540033,0xC5500024,0xBB500013,0xB750001A,0xB7500024,0xB3500016,0xB1500026,0xC34C0034,0xBB4C000A,0xB74C000F,0xB9480013,0xB5480002,0xB14C0016,0xB54C0034,0xB348000F,0xB1480019,0xAF480035,0x7FC0088,0xBF400033,0xB5480033,0xB9400026,0xB5440012,0xB1480026,0xBB340033,0xB5380009,0xB13C0015,0xAF400034,0x85FC0088,
+0xB5240033,0xB12C0026,0xAF200034,0xAC000088,0xEF4C0002,0xF354003E,0xF558004B,0xC94C0002,0xBD4C0002,0xB74C0002,0xB54C0002,0xB5480002,0xEB400001,0xCB440001,0xB5480009,0xB13C0015,0x65FC0088,0x1600033,0xC35C000A,0xB958000A,0xB558000A,0xBD580013,0xB9540002,0xB5580001,0xB5580013,0xB5540005,0xB1540015,0xFFC0033,0xBB4C0009,0xB550000A,0xB9480012,0xB5480001,
+0xB1500014,0x8BF80033,0xB5380008,0xB13C0014,0xAE000034,0xFFC0033,0xBB4C0009,0xB550000A,0xB9480012,0xB5480001,0xB1500014,0x8BF80033,0xB5380008,0xB13C0014,0xAE000034,0x8BF80033,0xB5380008,0xB13C0014,0xAE000034,0xAE000034,0xEF4C0001,0xF5580015,0xF75C000E,0xC94C0001,0xBD4C0001,0xB74C0001,0xB54C0001,0xB5480001,0xEB400001,0xC7480001,0xB5480009,0xB13C0014,
+0x6BFC0033,0x1540033,0x1540033,0x1540033,0x1540033,0xBD500012,0xBD500012,0xBD500012,0xB3500012,0xB3500012,0xAF500012,0xBB4C0009,0xBB4C0009,0xBB4C0009,0xB34C0002,0xB34C0002,0xAF4C0005,0xB1480009,0xB1480009,0xAF480001,0xAD480009,0x1F80033,0x1F80033,0x1F80033,0xB5440012,0xB5440012,0xAF480012,0xB3400009,0xB3400009,0xAF400001,0xAD400009,0x81FC0033,
+0x81FC0033,0xAF340012,0xAD280008,0xAA000034,0xE34C0002,0xF1500016,0x1540033,0xC74C0001,0xBD4C0001,0xB74C0001,0xB54C0002,0xB3480002,0xEB400000,0xC5480001,0xB5480008,0xAF400001,0x5FFC0033,0x158000A,0x158000A,0x158000A,0x158000A,0xB5580001,0xB5580001,0xB5580001,0xB1540001,0xB1540001,0xAF540001,0x7FC0008,0x7FC0008,0x7FC0008,0xB1500001,0xB1500001,
+0xAF500001,0x85FC0008,0x85FC0008,0xAF440000,0xAC000008,0x7FC0008,0x7FC0008,0x7FC0008,0xB1500001,0xB1500001,0xAF500001,0x85FC0008,0x85FC0008,0xAF440000,0xAC000008,0x85FC0008,0x85FC0008,0xAF440000,0xAC000008,0xAC000008,0xD7500000,0xD5580001,0x158000A,0xC74C0000,0xB9500000,0xB5500000,0xB3500000,0xB1500001,0xD9480000,0xC14C0000,0x65FC0008,0xAF440000,
+0x65FC0008,0x1640012,0xBF600001,0xB7600001,0xB55C0001,0x15FC0012,0xB9540001,0xB5580000,0x8DFC0012,0xB5440000,0xB0000014,0x15FC0012,0xB9540001,0xB5580000,0x8DFC0012,0xB5440000,0xB0000014,0x8DFC0012,0xB5440000,0xB0000014,0xB0000014,0x15FC0012,0xB9540001,0xB5580000,0x8DFC0012,0xB5440000,0xB0000014,0x8DFC0012,0xB5440000,0xB0000014,0xB0000014,0x8DFC0012,
+0xB5440000,0xB0000014,0xB0000014,0xB0000014,0xFF440000,0x17C0012,0xF9600001,0xCD480000,0xBD4C0001,0xB9480000,0xB54C0000,0xB53C0000,0xF33C0000,0xCB440000,0xB5500001,0xB0000014,0x6FFC0012,0x1500012,0x1500012,0x1500012,0x1500012,0x1500012,0x1500012,0x1500012,0x1500012,0x1500012,0x1500012,0xB54C0001,0xB54C0001,0xB54C0001,0xB54C0001,0xB54C0001,
+0xB54C0001,0xAD4C0001,0xAD4C0001,0xAD4C0001,0xAB480001,0x1F40012,0x1F40012,0x1F40012,0x1F40012,0x1F40012,0x1F40012,0xAF400001,0xAF400001,0xAF400001,0xAB440000,0x7FF80012,0x7FF80012,0x7FF80012,0xAB300000,0xA6000014,0xEF4C0001,0x1500012,0x1500012,0xC74C0001,0xBD4C0001,0xB74C0001,0xB74C0001,0xB34C0001,0xEB400000,0xCD440000,0xB1480000,0xAF400001,
+0x5DF80012,};
+static const uint32_t g_etc1_to_bc7_m6_table22[] = {
+0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x85FC0000,
+0x85FC0000,0x85FC0000,0x85FC0000,0xAC000000,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1700000,0x1700000,0x1700000,0x7FC0000,0x65FC0000,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,
+0x19FC0000,0x8FF80000,0x8FF80000,0x8FF80000,0xB2000000,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x8FF80000,0x8FF80000,0x8FF80000,0xB2000000,0x8FF80000,0x8FF80000,0x8FF80000,0xB2000000,0xB2000000,0x77C0000,0x1640001,0x1640001,0x1A00000,0x1C00000,0x1E80000,0x1E80000,0x45FC0000,0x1A00000,0x1C00000,0x71FC0000,0x8FF80000,
+0x71FC0000,0x16C0001,0x16C0001,0x16C0001,0x16C0001,0x25FC0000,0x25FC0000,0x25FC0000,0x95F80000,0x95F80000,0xB6000000,0x25FC0000,0x25FC0000,0x25FC0000,0x95F80000,0x95F80000,0xB6000000,0x95F80000,0x95F80000,0xB6000000,0xB6000000,0x25FC0000,0x25FC0000,0x25FC0000,0x95F80000,0x95F80000,0xB6000000,0x95F80000,0x95F80000,0xB6000000,0xB6000000,0x95F80000,
+0x95F80000,0xB6000000,0xB6000000,0xB6000000,0x3A80000,0xB840000,0x16C0001,0x3F00000,0x4FFC0000,0x79FC0000,0x87F80000,0x9DFC0000,0x1CC0000,0x25FC0000,0x79FC0000,0xB6000000,0x79FC0000,0x1780001,0x37FC0000,0x9DFC0000,0xBC000000,0x37FC0000,0x9DFC0000,0xBC000000,0x9DFC0000,0xBC000000,0xBC000000,0x37FC0000,0x9DFC0000,0xBC000000,0x9DFC0000,0xBC000000,
+0xBC000000,0x9DFC0000,0xBC000000,0xBC000000,0xBC000000,0x37FC0000,0x9DFC0000,0xBC000000,0x9DFC0000,0xBC000000,0xBC000000,0x9DFC0000,0xBC000000,0xBC000000,0xBC000000,0x9DFC0000,0xBC000000,0xBC000000,0xBC000000,0xBC000000,0x3D80000,0x1940000,0x1940000,0x5DFC0000,0x91FC0000,0xADF40000,0xBC000000,0xBC000000,0x9FC0000,0x73FC0000,0xB9E40000,0xBC000000,
+0x83FC0000,0x168008C,0xD3640033,0xC3640033,0xBD640033,0xCD600024,0xC3600013,0xBF60001A,0xBF600024,0xBB600016,0xB9600026,0xCB5C0034,0xC35C000A,0xBF5C000F,0xC1580013,0xBD580002,0xB95C0016,0xBD5C0034,0xBB58000F,0xB9580019,0xB7580035,0x1FFC0088,0xC7500033,0xBD580033,0xC1500026,0xBD540012,0xB9580026,0xC3440033,0xBD480009,0xB94C0015,0xB7500034,0x91FC0088,
+0xBD340033,0xB93C0026,0xB7300034,0xB4000088,0xF75C0002,0xFB64003E,0xFD68004B,0xD15C0002,0xC55C0002,0xBF5C0002,0xBD5C0002,0xBD580002,0xF3500001,0xD3540001,0xBD580009,0xB94C0015,0x75FC0088,0x1700033,0xCB6C000A,0xC168000A,0xBD68000A,0xC5680013,0xC1640002,0xBD680001,0xBD680013,0xBD640005,0xB9640015,0x29FC0033,0xC35C0009,0xBD60000A,0xC1580012,0xBD580001,
+0xB9600014,0x97F80033,0xBD480008,0xB94C0014,0xB6000034,0x29FC0033,0xC35C0009,0xBD60000A,0xC1580012,0xBD580001,0xB9600014,0x97F80033,0xBD480008,0xB94C0014,0xB6000034,0x97F80033,0xBD480008,0xB94C0014,0xB6000034,0xB6000034,0xF75C0001,0xFD680015,0xFF6C000E,0xD15C0001,0xC55C0001,0xBF5C0001,0xBD5C0001,0xBD580001,0xF3500001,0xCF580001,0xBD580009,0xB94C0014,
+0x7BFC0033,0x1640033,0x1640033,0x1640033,0x1640033,0xC5600012,0xC5600012,0xC5600012,0xBB600012,0xBB600012,0xB7600012,0xC35C0009,0xC35C0009,0xC35C0009,0xBB5C0002,0xBB5C0002,0xB75C0005,0xB9580009,0xB9580009,0xB7580001,0xB5580009,0x15FC0033,0x15FC0033,0x15FC0033,0xBD540012,0xBD540012,0xB7580012,0xBB500009,0xBB500009,0xB7500001,0xB5500009,0x8DFC0033,
+0x8DFC0033,0xB7440012,0xB5380008,0xB2000034,0xEB5C0002,0xF9600016,0x1640033,0xCF5C0001,0xC55C0001,0xBF5C0001,0xBD5C0002,0xBB580002,0xF3500000,0xCD580001,0xBD580008,0xB7500001,0x6FFC0033,0x168000A,0x168000A,0x168000A,0x168000A,0xBD680001,0xBD680001,0xBD680001,0xB9640001,0xB9640001,0xB7640001,0x1FFC0008,0x1FFC0008,0x1FFC0008,0xB9600001,0xB9600001,
+0xB7600001,0x91FC0008,0x91FC0008,0xB7540000,0xB4000008,0x1FFC0008,0x1FFC0008,0x1FFC0008,0xB9600001,0xB9600001,0xB7600001,0x91FC0008,0x91FC0008,0xB7540000,0xB4000008,0x91FC0008,0x91FC0008,0xB7540000,0xB4000008,0xB4000008,0xDF600000,0xDD680001,0x168000A,0xCF5C0000,0xC1600000,0xBD600000,0xBB600000,0xB9600001,0xE1580000,0xC95C0000,0x75FC0008,0xB7540000,
+0x75FC0008,0x1740012,0xC7700001,0xBF700001,0xBD6C0001,0x2FFC0012,0xC1640001,0xBD680000,0x99FC0012,0xBD540000,0xB8000014,0x2FFC0012,0xC1640001,0xBD680000,0x99FC0012,0xBD540000,0xB8000014,0x99FC0012,0xBD540000,0xB8000014,0xB8000014,0x2FFC0012,0xC1640001,0xBD680000,0x99FC0012,0xBD540000,0xB8000014,0x99FC0012,0xBD540000,0xB8000014,0xB8000014,0x99FC0012,
+0xBD540000,0xB8000014,0xB8000014,0xB8000014,0xF15C0001,0x18C0012,0xF1700002,0xD5580000,0xC55C0001,0xC1580000,0xBD5C0000,0xBD4C0000,0xFB4C0000,0xD3540000,0xBD600001,0xB8000014,0x7FF80012,0x1600012,0x1600012,0x1600012,0x1600012,0x1600012,0x1600012,0x1600012,0x1600012,0x1600012,0x1600012,0xBD5C0001,0xBD5C0001,0xBD5C0001,0xBD5C0001,0xBD5C0001,
+0xBD5C0001,0xB55C0001,0xB55C0001,0xB55C0001,0xB3580001,0xFFC0012,0xFFC0012,0xFFC0012,0xFFC0012,0xFFC0012,0xFFC0012,0xB7500001,0xB7500001,0xB7500001,0xB3540000,0x8BF80012,0x8BF80012,0x8BF80012,0xB3400000,0xAE000014,0xF75C0001,0x1600012,0x1600012,0xCF5C0001,0xC55C0001,0xBF5C0001,0xBF5C0001,0xBB5C0001,0xF3500000,0xD5540000,0xB9580000,0xB7500001,
+0x6BFC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table23[] = {
+0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x91FC0000,
+0x91FC0000,0x91FC0000,0x91FC0000,0xB4000000,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x9800000,0x9800000,0x9800000,0x1FFC0000,0x75FC0000,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,
+0x31FC0000,0x9BF80000,0x9BF80000,0x9BF80000,0xBA000000,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x9BF80000,0x9BF80000,0x9BF80000,0xBA000000,0x9BF80000,0x9BF80000,0x9BF80000,0xBA000000,0xBA000000,0xF8C0000,0x1740001,0x1740001,0x1B40000,0x1D40000,0x1FC0000,0x1FC0000,0x59FC0000,0x1B40000,0x1D40000,0x7FFC0000,0x9BF80000,
+0x7FFC0000,0x17C0001,0x17C0001,0x17C0001,0x17C0001,0x3DFC0000,0x3DFC0000,0x3DFC0000,0xA1F80000,0xA1F80000,0xBE000000,0x3DFC0000,0x3DFC0000,0x3DFC0000,0xA1F80000,0xA1F80000,0xBE000000,0xA1F80000,0xA1F80000,0xBE000000,0xBE000000,0x3DFC0000,0x3DFC0000,0x3DFC0000,0xA1F80000,0xA1F80000,0xBE000000,0xA1F80000,0xA1F80000,0xBE000000,0xBE000000,0xA1F80000,
+0xA1F80000,0xBE000000,0xBE000000,0xBE000000,0x1BC0000,0x1980000,0x17C0001,0xFFC0000,0x63FC0000,0x87FC0000,0x95F80000,0xA9F40000,0x1E00000,0x3DFC0000,0x87FC0000,0xBE000000,0x87FC0000,0x1880001,0x4FFC0000,0xA9FC0000,0xC4000000,0x4FFC0000,0xA9FC0000,0xC4000000,0xA9FC0000,0xC4000000,0xC4000000,0x4FFC0000,0xA9FC0000,0xC4000000,0xA9FC0000,0xC4000000,
+0xC4000000,0xA9FC0000,0xC4000000,0xC4000000,0xC4000000,0x4FFC0000,0xA9FC0000,0xC4000000,0xA9FC0000,0xC4000000,0xC4000000,0xA9FC0000,0xC4000000,0xC4000000,0xC4000000,0xA9FC0000,0xC4000000,0xC4000000,0xC4000000,0xC4000000,0x3EC0000,0x1A40000,0x1A40000,0x71FC0000,0x9FF80000,0xB7F40000,0xC4000000,0xC4000000,0x27FC0000,0x85FC0000,0xC1F40000,0xC4000000,
+0x93FC0000,0x178008C,0xDB740033,0xCB740033,0xC5740033,0xD5700024,0xCB700013,0xC770001A,0xC7700024,0xC3700016,0xC1700026,0xD36C0034,0xCB6C000A,0xC76C000F,0xC9680013,0xC5680002,0xC16C0016,0xC56C0034,0xC368000F,0xC1680019,0xBF680035,0x37FC0088,0xCF600033,0xC5680033,0xC9600026,0xC5640012,0xC1680026,0xCB540033,0xC5580009,0xC15C0015,0xBF600034,0x9DFC0088,
+0xC5440033,0xC14C0026,0xBF400034,0xBC000088,0xFF6C0002,0xF374004C,0xF5780054,0xD96C0002,0xCD6C0002,0xC76C0002,0xC56C0002,0xC5680002,0xFB600001,0xDB640001,0xC5680009,0xC15C0015,0x83FC0088,0x1800033,0xD37C000A,0xC978000A,0xC578000A,0xCD780013,0xC9740002,0xC5780001,0xC5780013,0xC5740005,0xC1740015,0x41FC0033,0xCB6C0009,0xC570000A,0xC9680012,0xC5680001,
+0xC1700014,0xA1FC0033,0xC5580008,0xC15C0014,0xBE000034,0x41FC0033,0xCB6C0009,0xC570000A,0xC9680012,0xC5680001,0xC1700014,0xA1FC0033,0xC5580008,0xC15C0014,0xBE000034,0xA1FC0033,0xC5580008,0xC15C0014,0xBE000034,0xBE000034,0xFF6C0001,0xF578001B,0xF77C0013,0xD96C0001,0xCD6C0001,0xC76C0001,0xC56C0001,0xC5680001,0xFB600001,0xD7680001,0xC5680009,0xC15C0014,
+0x89FC0033,0x1740033,0x1740033,0x1740033,0x1740033,0xCD700012,0xCD700012,0xCD700012,0xC3700012,0xC3700012,0xBF700012,0xCB6C0009,0xCB6C0009,0xCB6C0009,0xC36C0002,0xC36C0002,0xBF6C0005,0xC1680009,0xC1680009,0xBF680001,0xBD680009,0x2FFC0033,0x2FFC0033,0x2FFC0033,0xC5640012,0xC5640012,0xBF680012,0xC3600009,0xC3600009,0xBF600001,0xBD600009,0x99FC0033,
+0x99FC0033,0xBF540012,0xBD480008,0xBA000034,0xF36C0002,0xF170001B,0x1740033,0xD76C0001,0xCD6C0001,0xC76C0001,0xC56C0002,0xC3680002,0xFB600000,0xD5680001,0xC5680008,0xBF600001,0x7FF80033,0x178000A,0x178000A,0x178000A,0x178000A,0xC5780001,0xC5780001,0xC5780001,0xC1740001,0xC1740001,0xBF740001,0x37FC0008,0x37FC0008,0x37FC0008,0xC1700001,0xC1700001,
+0xBF700001,0x9DFC0008,0x9DFC0008,0xBF640000,0xBC000008,0x37FC0008,0x37FC0008,0x37FC0008,0xC1700001,0xC1700001,0xBF700001,0x9DFC0008,0x9DFC0008,0xBF640000,0xBC000008,0x9DFC0008,0x9DFC0008,0xBF640000,0xBC000008,0xBC000008,0xE7700000,0xE5780001,0x178000A,0xD76C0000,0xC9700000,0xC5700000,0xC3700000,0xC1700001,0xE9680000,0xD16C0000,0x83FC0008,0xBF640000,
+0x83FC0008,0x1840012,0xCF800001,0xC7800001,0xC57C0001,0x47FC0012,0xC9740001,0xC5780000,0xA5F80012,0xC5640000,0xC0000014,0x47FC0012,0xC9740001,0xC5780000,0xA5F80012,0xC5640000,0xC0000014,0xA5F80012,0xC5640000,0xC0000014,0xC0000014,0x47FC0012,0xC9740001,0xC5780000,0xA5F80012,0xC5640000,0xC0000014,0xA5F80012,0xC5640000,0xC0000014,0xC0000014,0xA5F80012,
+0xC5640000,0xC0000014,0xC0000014,0xC0000014,0xF96C0001,0x79C0012,0xF9800002,0xDD680000,0xCD6C0001,0xC9680000,0xC56C0000,0xC55C0000,0xF9640001,0xDB640000,0xC5700001,0xC0000014,0x8DFC0012,0x1700012,0x1700012,0x1700012,0x1700012,0x1700012,0x1700012,0x1700012,0x1700012,0x1700012,0x1700012,0xC56C0001,0xC56C0001,0xC56C0001,0xC56C0001,0xC56C0001,
+0xC56C0001,0xBD6C0001,0xBD6C0001,0xBD6C0001,0xBB680001,0x29FC0012,0x29FC0012,0x29FC0012,0x29FC0012,0x29FC0012,0x29FC0012,0xBF600001,0xBF600001,0xBF600001,0xBB640000,0x97F80012,0x97F80012,0x97F80012,0xBB500000,0xB6000014,0xFF6C0001,0x1700012,0x1700012,0xD76C0001,0xCD6C0001,0xC76C0001,0xC76C0001,0xC36C0001,0xFB600000,0xDD640000,0xC1680000,0xBF600001,
+0x7BFC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table24[] = {
+0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x9FF80000,
+0x9FF80000,0x9FF80000,0x9FF80000,0xBC000001,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x3940000,0x3940000,0x3940000,0x3BFC0000,0x85FC0000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x4DFC0000,
+0x4DFC0000,0xA7FC0000,0xA7FC0000,0xA7FC0000,0xC2000001,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0xA7FC0000,0xA7FC0000,0xA7FC0000,0xC2000001,0xA7FC0000,0xA7FC0000,0xA7FC0000,0xC2000001,0xC2000001,0x9A00000,0x1880000,0x1880000,0x1C80000,0x1EC0000,0x23FC0000,0x23FC0000,0x6FFC0000,0x1C80000,0x1EC0000,0x91FC0000,0xA7FC0000,
+0x91FC0000,0x1900000,0x1900000,0x1900000,0x1900000,0x59FC0000,0x59FC0000,0x59FC0000,0xADFC0000,0xADFC0000,0xC6000001,0x59FC0000,0x59FC0000,0x59FC0000,0xADFC0000,0xADFC0000,0xC6000001,0xADFC0000,0xADFC0000,0xC6000001,0xC6000001,0x59FC0000,0x59FC0000,0x59FC0000,0xADFC0000,0xADFC0000,0xC6000001,0xADFC0000,0xADFC0000,0xC6000001,0xC6000001,0xADFC0000,
+0xADFC0000,0xC6000001,0xC6000001,0xC6000001,0x1D00000,0xDA80000,0x1900000,0x31FC0000,0x79FC0000,0x99FC0000,0xA3FC0000,0xB5F80000,0x3F40000,0x59FC0000,0x99FC0000,0xC6000001,0x99FC0000,0x19C0000,0x6BFC0000,0xB7F80000,0xCC000001,0x6BFC0000,0xB7F80000,0xCC000001,0xB7F80000,0xCC000001,0xCC000001,0x6BFC0000,0xB7F80000,0xCC000001,0xB7F80000,0xCC000001,
+0xCC000001,0xB7F80000,0xCC000001,0xCC000001,0xCC000001,0x6BFC0000,0xB7F80000,0xCC000001,0xB7F80000,0xCC000001,0xCC000001,0xB7F80000,0xCC000001,0xCC000001,0xCC000001,0xB7F80000,0xCC000001,0xCC000001,0xCC000001,0xCC000001,0x11FC0000,0x1B80000,0x1B80000,0x87FC0000,0xADFC0000,0xC3F00000,0xCC000001,0xCC000001,0x49FC0000,0x97FC0000,0xCBE80000,0xCC000001,
+0xA3FC0000,0x18C0088,0xE1880034,0xD3880034,0xCD880035,0xDD840026,0xD3840015,0xCD840019,0xCF840026,0xCD800016,0xCB800026,0xDF7C0033,0xD57C0009,0xCF80000F,0xD17C0012,0xCD7C0002,0xCB7C0016,0xCF7C0033,0xCD78000F,0xCB78001A,0xC97C0033,0x53FC0088,0xD9700033,0xCD7C0034,0xD3700026,0xCF740013,0xCB780024,0xD3680033,0xCD70000A,0xCB6C0013,0xC9700033,0xABF80088,
+0xCD5C0034,0xCB580024,0xC94C0033,0xC400008C,0xFF800006,0xFD880048,0xFD880058,0xE57C0001,0xD77C0002,0xD17C0002,0xCF7C0002,0xCD7C0002,0xFF740004,0xE1780001,0xCF780009,0xCB6C0013,0x95FC0088,0x1900034,0xDD8C0008,0xD18C0009,0xCD8C0009,0xD9880012,0xD1880001,0xCF880001,0xCF880012,0xCD880005,0xCB880012,0x5BFC0033,0xD3800009,0xCD840009,0xD17C0012,0xCD7C0002,
+0xCB800012,0xAFFC0033,0xCD700009,0xCB6C0012,0xC8000033,0x5BFC0033,0xD3800009,0xCD840009,0xD17C0012,0xCD7C0002,0xCB800012,0xAFFC0033,0xCD700009,0xCB6C0012,0xC8000033,0xAFFC0033,0xCD700009,0xCB6C0012,0xC8000033,0xC8000033,0xFF800002,0xFF8C0018,0xFF8C0018,0xDF800001,0xD77C0002,0xD17C0002,0xCD800002,0xCD780002,0xFB780003,0xDD7C0001,0xCF780008,0xCB6C0012,
+0x9BFC0033,0x1880034,0x1880034,0x1880034,0x1880034,0xD3840014,0xD3840014,0xD3840014,0xCB840014,0xCB840014,0xC7800015,0xD57C0008,0xD57C0008,0xD57C0008,0xCD7C0001,0xCD7C0001,0xC97C0005,0xC97C000A,0xC97C000A,0xC77C0001,0xC57C000A,0x49FC0033,0x49FC0033,0x49FC0033,0xCF740012,0xCF740012,0xC77C0013,0xCD700009,0xCD700009,0xC7740002,0xC574000A,0xA7F80033,
+0xA7F80033,0xC7680013,0xC560000A,0xC2000033,0xF9800004,0xFB840018,0x1880034,0xE37C0001,0xD77C0001,0xD17C0001,0xCF7C0001,0xCB7C0001,0xFF740000,0xE1780000,0xCD7C0009,0xC7740002,0x8FFC0033,0x18C0008,0x18C0008,0x18C0008,0x18C0008,0xCF880000,0xCF880000,0xCF880000,0xC9880001,0xC9880001,0xC7880001,0x53FC0008,0x53FC0008,0x53FC0008,0xC9840001,0xC9840001,
+0xC7840001,0xABF80008,0xABF80008,0xC77C0001,0xC400000A,0x53FC0008,0x53FC0008,0x53FC0008,0xC9840001,0xC9840001,0xC7840001,0xABF80008,0xABF80008,0xC77C0001,0xC400000A,0xABF80008,0xABF80008,0xC77C0001,0xC400000A,0xC400000A,0xF9800000,0xFD880000,0x18C0008,0xDD800000,0xD3800000,0xCF800000,0xCB840001,0xCB800000,0xF5780000,0xDB7C0000,0x95FC0008,0xC77C0001,
+0x95FC0008,0x1940014,0xD9900000,0xD1900000,0xCD900001,0x63FC0012,0xD1880001,0xCD8C0001,0xB3F80012,0xCD7C0001,0xCA000012,0x63FC0012,0xD1880001,0xCD8C0001,0xB3F80012,0xCD7C0001,0xCA000012,0xB3F80012,0xCD7C0001,0xCA000012,0xCA000012,0x63FC0012,0xD1880001,0xCD8C0001,0xB3F80012,0xCD7C0001,0xCA000012,0xB3F80012,0xCD7C0001,0xCA000012,0xCA000012,0xB3F80012,
+0xCD7C0001,0xCA000012,0xCA000012,0xCA000012,0xF7840002,0x1B00012,0xF3940005,0xE57C0000,0xD77C0001,0xD3780000,0xCD800001,0xCD740001,0xF57C0002,0xE5740000,0xCF800000,0xCA000012,0x9FF80012,0x1800014,0x1800014,0x1800014,0x1800014,0x1800014,0x1800014,0x1800014,0x1800014,0x1800014,0x1800014,0xCF7C0000,0xCF7C0000,0xCF7C0000,0xCF7C0000,0xCF7C0000,
+0xCF7C0000,0xC77C0000,0xC77C0000,0xC77C0000,0xC37C0001,0x43FC0012,0x43FC0012,0x43FC0012,0x43FC0012,0x43FC0012,0x43FC0012,0xC7740001,0xC7740001,0xC7740001,0xC3780001,0xA3FC0012,0xA3FC0012,0xA3FC0012,0xC3680001,0xC0000012,0xF77C0004,0x1800014,0x1800014,0xE77C0000,0xDB7C0000,0xD37C0000,0xD37C0000,0xCD7C0000,0xFF740000,0xE1780000,0xC97C0001,0xC7740001,
+0x8BFC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table25[] = {
+0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0xABF80000,
+0xABF80000,0xABF80000,0xABF80000,0xC4000001,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0xBA40000,0xBA40000,0xBA40000,0x53FC0000,0x95FC0000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x65FC0000,0x65FC0000,0x65FC0000,0x65FC0000,0x65FC0000,
+0x65FC0000,0xB3FC0000,0xB3FC0000,0xB3FC0000,0xCA000001,0x65FC0000,0x65FC0000,0x65FC0000,0x65FC0000,0x65FC0000,0x65FC0000,0xB3FC0000,0xB3FC0000,0xB3FC0000,0xCA000001,0xB3FC0000,0xB3FC0000,0xB3FC0000,0xCA000001,0xCA000001,0x1B40000,0x1980000,0x1980000,0x5D80000,0x7FC0000,0x41FC0000,0x41FC0000,0x83FC0000,0x5D80000,0x7FC0000,0x9FFC0000,0xB3FC0000,
+0x9FFC0000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x71FC0000,0x71FC0000,0x71FC0000,0xB9FC0000,0xB9FC0000,0xCE000001,0x71FC0000,0x71FC0000,0x71FC0000,0xB9FC0000,0xB9FC0000,0xCE000001,0xB9FC0000,0xB9FC0000,0xCE000001,0xCE000001,0x71FC0000,0x71FC0000,0x71FC0000,0xB9FC0000,0xB9FC0000,0xCE000001,0xB9FC0000,0xB9FC0000,0xCE000001,0xCE000001,0xB9FC0000,
+0xB9FC0000,0xCE000001,0xCE000001,0xCE000001,0x1E40000,0x1BC0000,0x1A00000,0x4FFC0000,0x8DFC0000,0xA7FC0000,0xB1FC0000,0xBFFC0000,0x1BFC0000,0x71FC0000,0xA7FC0000,0xCE000001,0xA7FC0000,0x1AC0000,0x83FC0000,0xC3F80000,0xD4000001,0x83FC0000,0xC3F80000,0xD4000001,0xC3F80000,0xD4000001,0xD4000001,0x83FC0000,0xC3F80000,0xD4000001,0xC3F80000,0xD4000001,
+0xD4000001,0xC3F80000,0xD4000001,0xD4000001,0xD4000001,0x83FC0000,0xC3F80000,0xD4000001,0xC3F80000,0xD4000001,0xD4000001,0xC3F80000,0xD4000001,0xD4000001,0xD4000001,0xC3F80000,0xD4000001,0xD4000001,0xD4000001,0xD4000001,0x37FC0000,0x1C80000,0x1C80000,0x9BFC0000,0xBBFC0000,0xCDF00000,0xD4000001,0xD4000001,0x67FC0000,0xA9FC0000,0xD3F80000,0xD4000001,
+0xB3FC0000,0x19C0088,0xE9980034,0xDB980034,0xD5980035,0xE5940026,0xDB940015,0xD5940019,0xD7940026,0xD5900016,0xD3900026,0xE78C0033,0xDD8C0009,0xD790000F,0xD98C0012,0xD58C0002,0xD38C0016,0xD78C0033,0xD588000F,0xD388001A,0xD18C0033,0x6BFC0088,0xE1800033,0xD58C0034,0xDB800026,0xD7840013,0xD3880024,0xDB780033,0xD580000A,0xD37C0013,0xD1800033,0xB7F80088,
+0xD56C0034,0xD3680024,0xD15C0033,0xCC00008C,0xFF90000E,0xF5980056,0xF79C0061,0xED8C0001,0xDF8C0002,0xD98C0002,0xD78C0002,0xD58C0002,0xFF880008,0xE9880001,0xD7880009,0xD37C0013,0xA3FC0088,0x1A00034,0xE59C0008,0xD99C0009,0xD59C0009,0xE1980012,0xD9980001,0xD7980001,0xD7980012,0xD5980005,0xD3980012,0x75FC0033,0xDB900009,0xD5940009,0xD98C0012,0xD58C0002,
+0xD3900012,0xBBFC0033,0xD5800009,0xD37C0012,0xD0000033,0x75FC0033,0xDB900009,0xD5940009,0xD98C0012,0xD58C0002,0xD3900012,0xBBFC0033,0xD5800009,0xD37C0012,0xD0000033,0xBBFC0033,0xD5800009,0xD37C0012,0xD0000033,0xD0000033,0xFF940003,0xF79C001E,0xF9A00019,0xE7900001,0xDF8C0002,0xD98C0002,0xD5900002,0xD5880002,0xFF880004,0xE58C0001,0xD7880008,0xD37C0012,
+0xA9FC0033,0x1980034,0x1980034,0x1980034,0x1980034,0xDB940014,0xDB940014,0xDB940014,0xD3940014,0xD3940014,0xCF900015,0xDD8C0008,0xDD8C0008,0xDD8C0008,0xD58C0001,0xD58C0001,0xD18C0005,0xD18C000A,0xD18C000A,0xCF8C0001,0xCD8C000A,0x63FC0033,0x63FC0033,0x63FC0033,0xD7840012,0xD7840012,0xCF8C0013,0xD5800009,0xD5800009,0xCF840002,0xCD84000A,0xB3F80033,
+0xB3F80033,0xCF780013,0xCD70000A,0xCA000033,0xFF900005,0xF394001D,0x1980034,0xEB8C0001,0xDF8C0001,0xD98C0001,0xD78C0001,0xD38C0001,0xFB880002,0xE9880000,0xD58C0009,0xCF840002,0x9FF80033,0x19C0008,0x19C0008,0x19C0008,0x19C0008,0xD7980000,0xD7980000,0xD7980000,0xD1980001,0xD1980001,0xCF980001,0x6BFC0008,0x6BFC0008,0x6BFC0008,0xD1940001,0xD1940001,
+0xCF940001,0xB7F80008,0xB7F80008,0xCF8C0001,0xCC00000A,0x6BFC0008,0x6BFC0008,0x6BFC0008,0xD1940001,0xD1940001,0xCF940001,0xB7F80008,0xB7F80008,0xCF8C0001,0xCC00000A,0xB7F80008,0xB7F80008,0xCF8C0001,0xCC00000A,0xCC00000A,0xEB940001,0xF5980001,0x19C0008,0xE5900000,0xDB900000,0xD7900000,0xD3940001,0xD3900000,0xFD880000,0xE38C0000,0xA3FC0008,0xCF8C0001,
+0xA3FC0008,0x1A40014,0xE1A00000,0xD9A00000,0xD5A00001,0x7BFC0012,0xD9980001,0xD59C0001,0xBFF80012,0xD58C0001,0xD2000012,0x7BFC0012,0xD9980001,0xD59C0001,0xBFF80012,0xD58C0001,0xD2000012,0xBFF80012,0xD58C0001,0xD2000012,0xD2000012,0x7BFC0012,0xD9980001,0xD59C0001,0xBFF80012,0xD58C0001,0xD2000012,0xBFF80012,0xD58C0001,0xD2000012,0xD2000012,0xBFF80012,
+0xD58C0001,0xD2000012,0xD2000012,0xD2000012,0xFF940002,0x9C00012,0xFBA40005,0xED8C0000,0xDF8C0001,0xDB880000,0xD5900001,0xD5840001,0xFD8C0002,0xED840000,0xD7900000,0xD2000012,0xADFC0012,0x1900014,0x1900014,0x1900014,0x1900014,0x1900014,0x1900014,0x1900014,0x1900014,0x1900014,0x1900014,0xD78C0000,0xD78C0000,0xD78C0000,0xD78C0000,0xD78C0000,
+0xD78C0000,0xCF8C0000,0xCF8C0000,0xCF8C0000,0xCB8C0001,0x5BFC0012,0x5BFC0012,0x5BFC0012,0x5BFC0012,0x5BFC0012,0x5BFC0012,0xCF840001,0xCF840001,0xCF840001,0xCB880001,0xAFFC0012,0xAFFC0012,0xAFFC0012,0xCB780001,0xC8000012,0xFF8C0004,0x1900014,0x1900014,0xEF8C0000,0xE38C0000,0xDB8C0000,0xDB8C0000,0xD58C0000,0xFB880001,0xE9880000,0xD18C0001,0xCF840001,
+0x9BFC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table26[] = {
+0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0xB7F80000,
+0xB7F80000,0xB7F80000,0xB7F80000,0xCC000001,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x1B80000,0x1B80000,0x1B80000,0x6BFC0000,0xA3FC0000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x7DFC0000,0x7DFC0000,0x7DFC0000,0x7DFC0000,0x7DFC0000,
+0x7DFC0000,0xBFFC0000,0xBFFC0000,0xBFFC0000,0xD2000001,0x7DFC0000,0x7DFC0000,0x7DFC0000,0x7DFC0000,0x7DFC0000,0x7DFC0000,0xBFFC0000,0xBFFC0000,0xBFFC0000,0xD2000001,0xBFFC0000,0xBFFC0000,0xBFFC0000,0xD2000001,0xD2000001,0x1C40000,0x1A80000,0x1A80000,0x1EC0000,0x2DFC0000,0x5FFC0000,0x5FFC0000,0x97FC0000,0x1EC0000,0x2DFC0000,0xAFFC0000,0xBFFC0000,
+0xAFFC0000,0x1B00000,0x1B00000,0x1B00000,0x1B00000,0x89FC0000,0x89FC0000,0x89FC0000,0xC5FC0000,0xC5FC0000,0xD6000001,0x89FC0000,0x89FC0000,0x89FC0000,0xC5FC0000,0xC5FC0000,0xD6000001,0xC5FC0000,0xC5FC0000,0xD6000001,0xD6000001,0x89FC0000,0x89FC0000,0x89FC0000,0xC5FC0000,0xC5FC0000,0xD6000001,0xC5FC0000,0xC5FC0000,0xD6000001,0xD6000001,0xC5FC0000,
+0xC5FC0000,0xD6000001,0xD6000001,0xD6000001,0x5F40000,0x1CC0000,0x1B00000,0x6FFC0000,0xA1FC0000,0xB7FC0000,0xBFF80000,0xCBF80000,0x41FC0000,0x89FC0000,0xB7FC0000,0xD6000001,0xB7FC0000,0x1BC0000,0x9BFC0000,0xCFF80000,0xDC000001,0x9BFC0000,0xCFF80000,0xDC000001,0xCFF80000,0xDC000001,0xDC000001,0x9BFC0000,0xCFF80000,0xDC000001,0xCFF80000,0xDC000001,
+0xDC000001,0xCFF80000,0xDC000001,0xDC000001,0xDC000001,0x9BFC0000,0xCFF80000,0xDC000001,0xCFF80000,0xDC000001,0xDC000001,0xCFF80000,0xDC000001,0xDC000001,0xDC000001,0xCFF80000,0xDC000001,0xDC000001,0xDC000001,0xDC000001,0x5FFC0000,0x5D80000,0x5D80000,0xAFFC0000,0xC9F80000,0xD7F00000,0xDC000001,0xDC000001,0x85FC0000,0xB9FC0000,0xDDCC0000,0xDC000001,
+0xC1FC0000,0x1AC0088,0xF1A80034,0xE3A80034,0xDDA80035,0xEDA40026,0xE3A40015,0xDDA40019,0xDFA40026,0xDDA00016,0xDBA00026,0xEF9C0033,0xE59C0009,0xDFA0000F,0xE19C0012,0xDD9C0002,0xDB9C0016,0xDF9C0033,0xDD98000F,0xDB98001A,0xD99C0033,0x83FC0088,0xE9900033,0xDD9C0034,0xE3900026,0xDF940013,0xDB980024,0xE3880033,0xDD90000A,0xDB8C0013,0xD9900033,0xC3F80088,
+0xDD7C0034,0xDB780024,0xD96C0033,0xD400008C,0xFFA00016,0xFDA80056,0xFFAC0061,0xF59C0001,0xE79C0002,0xE19C0002,0xDF9C0002,0xDD9C0002,0xFF9C0013,0xF1980001,0xDF980009,0xDB8C0013,0xB3FC0088,0x1B00034,0xEDAC0008,0xE1AC0009,0xDDAC0009,0xE9A80012,0xE1A80001,0xDFA80001,0xDFA80012,0xDDA80005,0xDBA80012,0x8DFC0033,0xE3A00009,0xDDA40009,0xE19C0012,0xDD9C0002,
+0xDBA00012,0xC7FC0033,0xDD900009,0xDB8C0012,0xD8000033,0x8DFC0033,0xE3A00009,0xDDA40009,0xE19C0012,0xDD9C0002,0xDBA00012,0xC7FC0033,0xDD900009,0xDB8C0012,0xD8000033,0xC7FC0033,0xDD900009,0xDB8C0012,0xD8000033,0xD8000033,0xF9A80009,0xFFAC001E,0xF1B00020,0xEFA00001,0xE79C0002,0xE19C0002,0xDDA00002,0xDD980002,0xFDA00009,0xED9C0001,0xDF980008,0xDB8C0012,
+0xB9FC0033,0x1A80034,0x1A80034,0x1A80034,0x1A80034,0xE3A40014,0xE3A40014,0xE3A40014,0xDBA40014,0xDBA40014,0xD7A00015,0xE59C0008,0xE59C0008,0xE59C0008,0xDD9C0001,0xDD9C0001,0xD99C0005,0xD99C000A,0xD99C000A,0xD79C0001,0xD59C000A,0x7BFC0033,0x7BFC0033,0x7BFC0033,0xDF940012,0xDF940012,0xD79C0013,0xDD900009,0xDD900009,0xD7940002,0xD594000A,0xBFF80033,
+0xBFF80033,0xD7880013,0xD580000A,0xD2000033,0xFFA00006,0xFBA4001D,0x1A80034,0xF39C0001,0xE79C0001,0xE19C0001,0xDF9C0001,0xDB9C0001,0xFB980006,0xF1980000,0xDD9C0009,0xD7940002,0xADFC0033,0x1AC0008,0x1AC0008,0x1AC0008,0x1AC0008,0xDFA80000,0xDFA80000,0xDFA80000,0xD9A80001,0xD9A80001,0xD7A80001,0x83FC0008,0x83FC0008,0x83FC0008,0xD9A40001,0xD9A40001,
+0xD7A40001,0xC3F80008,0xC3F80008,0xD79C0001,0xD400000A,0x83FC0008,0x83FC0008,0x83FC0008,0xD9A40001,0xD9A40001,0xD7A40001,0xC3F80008,0xC3F80008,0xD79C0001,0xD400000A,0xC3F80008,0xC3F80008,0xD79C0001,0xD400000A,0xD400000A,0xF3A40001,0xFDA80001,0x1AC0008,0xEDA00000,0xE3A00000,0xDFA00000,0xDBA40001,0xDBA00000,0xF5A00001,0xEB9C0000,0xB3FC0008,0xD79C0001,
+0xB3FC0008,0x1B40014,0xE9B00000,0xE1B00000,0xDDB00001,0x93FC0012,0xE1A80001,0xDDAC0001,0xCBF80012,0xDD9C0001,0xDA000012,0x93FC0012,0xE1A80001,0xDDAC0001,0xCBF80012,0xDD9C0001,0xDA000012,0xCBF80012,0xDD9C0001,0xDA000012,0xDA000012,0x93FC0012,0xE1A80001,0xDDAC0001,0xCBF80012,0xDD9C0001,0xDA000012,0xCBF80012,0xDD9C0001,0xDA000012,0xDA000012,0xCBF80012,
+0xDD9C0001,0xDA000012,0xDA000012,0xDA000012,0xF9A80005,0x1D40012,0xF3B40008,0xF59C0000,0xE79C0001,0xE3980000,0xDDA00001,0xDD940001,0xFBA40005,0xF5940000,0xDFA00000,0xDA000012,0xBDF80012,0x1A00014,0x1A00014,0x1A00014,0x1A00014,0x1A00014,0x1A00014,0x1A00014,0x1A00014,0x1A00014,0x1A00014,0xDF9C0000,0xDF9C0000,0xDF9C0000,0xDF9C0000,0xDF9C0000,
+0xDF9C0000,0xD79C0000,0xD79C0000,0xD79C0000,0xD39C0001,0x75FC0012,0x75FC0012,0x75FC0012,0x75FC0012,0x75FC0012,0x75FC0012,0xD7940001,0xD7940001,0xD7940001,0xD3980001,0xBBFC0012,0xBBFC0012,0xBBFC0012,0xD3880001,0xD0000012,0xF9A00005,0x1A00014,0x1A00014,0xF79C0000,0xEB9C0000,0xE39C0000,0xE39C0000,0xDD9C0000,0xFB980002,0xF1980000,0xD99C0001,0xD7940001,
+0xA9FC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table27[] = {
+0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0xC3F80000,
+0xC3F80000,0xC3F80000,0xC3F80000,0xD4000001,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1C80000,0x1C80000,0x1C80000,0x83FC0000,0xB3FC0000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x95FC0000,0x95FC0000,0x95FC0000,0x95FC0000,0x95FC0000,
+0x95FC0000,0xCBFC0000,0xCBFC0000,0xCBFC0000,0xDA000001,0x95FC0000,0x95FC0000,0x95FC0000,0x95FC0000,0x95FC0000,0x95FC0000,0xCBFC0000,0xCBFC0000,0xCBFC0000,0xDA000001,0xCBFC0000,0xCBFC0000,0xCBFC0000,0xDA000001,0xDA000001,0x3D40000,0x1B80000,0x1B80000,0x9FC0000,0x55FC0000,0x7DFC0000,0x7DFC0000,0xABFC0000,0x9FC0000,0x55FC0000,0xBFF80000,0xCBFC0000,
+0xBFF80000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xD1FC0000,0xD1FC0000,0xDE000001,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xD1FC0000,0xD1FC0000,0xDE000001,0xD1FC0000,0xD1FC0000,0xDE000001,0xDE000001,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xD1FC0000,0xD1FC0000,0xDE000001,0xD1FC0000,0xD1FC0000,0xDE000001,0xDE000001,0xD1FC0000,
+0xD1FC0000,0xDE000001,0xDE000001,0xDE000001,0x27FC0000,0x7DC0000,0x1C00000,0x8DFC0000,0xB3FC0000,0xC5FC0000,0xCBFC0000,0xD5FC0000,0x69FC0000,0xA3FC0000,0xC5FC0000,0xDE000001,0xC5FC0000,0x1CC0000,0xB5FC0000,0xDBF80000,0xE4000001,0xB5FC0000,0xDBF80000,0xE4000001,0xDBF80000,0xE4000001,0xE4000001,0xB5FC0000,0xDBF80000,0xE4000001,0xDBF80000,0xE4000001,
+0xE4000001,0xDBF80000,0xE4000001,0xE4000001,0xE4000001,0xB5FC0000,0xDBF80000,0xE4000001,0xDBF80000,0xE4000001,0xE4000001,0xDBF80000,0xE4000001,0xE4000001,0xE4000001,0xDBF80000,0xE4000001,0xE4000001,0xE4000001,0xE4000001,0x87FC0000,0xDE80000,0xDE80000,0xC3FC0000,0xD5FC0000,0xE1F00000,0xE4000001,0xE4000001,0xA3FC0000,0xCBFC0000,0xE5DC0000,0xE4000001,
+0xD1FC0000,0x1BC0088,0xF9B80034,0xEBB80034,0xE5B80035,0xF5B40026,0xEBB40015,0xE5B40019,0xE7B40026,0xE5B00016,0xE3B00026,0xF7AC0033,0xEDAC0009,0xE7B0000F,0xE9AC0012,0xE5AC0002,0xE3AC0016,0xE7AC0033,0xE5A8000F,0xE3A8001A,0xE1AC0033,0x9BFC0088,0xF1A00033,0xE5AC0034,0xEBA00026,0xE7A40013,0xE3A80024,0xEB980033,0xE5A0000A,0xE39C0013,0xE1A00033,0xCFF80088,
+0xE58C0034,0xE3880024,0xE17C0033,0xDC00008C,0xFFB40021,0xF5B80068,0xF7BC006C,0xFDAC0001,0xEFAC0002,0xE9AC0002,0xE7AC0002,0xE5AC0002,0xFDB00021,0xF9A80001,0xE7A80009,0xE39C0013,0xC1FC0088,0x1C00034,0xF5BC0008,0xE9BC0009,0xE5BC0009,0xF1B80012,0xE9B80001,0xE7B80001,0xE7B80012,0xE5B80005,0xE3B80012,0xA5FC0033,0xEBB00009,0xE5B40009,0xE9AC0012,0xE5AC0002,
+0xE3B00012,0xD3FC0033,0xE5A00009,0xE39C0012,0xE0000033,0xA5FC0033,0xEBB00009,0xE5B40009,0xE9AC0012,0xE5AC0002,0xE3B00012,0xD3FC0033,0xE5A00009,0xE39C0012,0xE0000033,0xD3FC0033,0xE5A00009,0xE39C0012,0xE0000033,0xE0000033,0xFDB8000E,0xF9C00024,0xF9C00020,0xF7B00001,0xEFAC0002,0xE9AC0002,0xE5B00002,0xE5A80002,0xFDB00011,0xF5AC0001,0xE7A80008,0xE39C0012,
+0xC7FC0033,0x1B80034,0x1B80034,0x1B80034,0x1B80034,0xEBB40014,0xEBB40014,0xEBB40014,0xE3B40014,0xE3B40014,0xDFB00015,0xEDAC0008,0xEDAC0008,0xEDAC0008,0xE5AC0001,0xE5AC0001,0xE1AC0005,0xE1AC000A,0xE1AC000A,0xDFAC0001,0xDDAC000A,0x93FC0033,0x93FC0033,0x93FC0033,0xE7A40012,0xE7A40012,0xDFAC0013,0xE5A00009,0xE5A00009,0xDFA40002,0xDDA4000A,0xCBF80033,
+0xCBF80033,0xDF980013,0xDD90000A,0xDA000033,0xF9B00011,0xF3B40024,0x1B80034,0xFBAC0001,0xEFAC0001,0xE9AC0001,0xE7AC0001,0xE3AC0001,0xFBAC0009,0xF9A80000,0xE5AC0009,0xDFA40002,0xBDF80033,0x1BC0008,0x1BC0008,0x1BC0008,0x1BC0008,0xE7B80000,0xE7B80000,0xE7B80000,0xE1B80001,0xE1B80001,0xDFB80001,0x9BFC0008,0x9BFC0008,0x9BFC0008,0xE1B40001,0xE1B40001,
+0xDFB40001,0xCFF80008,0xCFF80008,0xDFAC0001,0xDC00000A,0x9BFC0008,0x9BFC0008,0x9BFC0008,0xE1B40001,0xE1B40001,0xDFB40001,0xCFF80008,0xCFF80008,0xDFAC0001,0xDC00000A,0xCFF80008,0xCFF80008,0xDFAC0001,0xDC00000A,0xDC00000A,0xFBB40001,0xF5B80004,0x1BC0008,0xF5B00000,0xEBB00000,0xE7B00000,0xE3B40001,0xE3B00000,0xFDB00001,0xF3AC0000,0xC1FC0008,0xDFAC0001,
+0xC1FC0008,0x1C40014,0xF1C00000,0xE9C00000,0xE5C00001,0xABFC0012,0xE9B80001,0xE5BC0001,0xD7F80012,0xE5AC0001,0xE2000012,0xABFC0012,0xE9B80001,0xE5BC0001,0xD7F80012,0xE5AC0001,0xE2000012,0xD7F80012,0xE5AC0001,0xE2000012,0xE2000012,0xABFC0012,0xE9B80001,0xE5BC0001,0xD7F80012,0xE5AC0001,0xE2000012,0xD7F80012,0xE5AC0001,0xE2000012,0xE2000012,0xD7F80012,
+0xE5AC0001,0xE2000012,0xE2000012,0xE2000012,0xFBBC0008,0x1E40012,0xFBC40008,0xFDAC0000,0xEFAC0001,0xEBA80000,0xE5B00001,0xE5A40001,0xF3BC0008,0xFDA40000,0xE7B00000,0xE2000012,0xCBFC0012,0x1B00014,0x1B00014,0x1B00014,0x1B00014,0x1B00014,0x1B00014,0x1B00014,0x1B00014,0x1B00014,0x1B00014,0xE7AC0000,0xE7AC0000,0xE7AC0000,0xE7AC0000,0xE7AC0000,
+0xE7AC0000,0xDFAC0000,0xDFAC0000,0xDFAC0000,0xDBAC0001,0x8DFC0012,0x8DFC0012,0x8DFC0012,0x8DFC0012,0x8DFC0012,0x8DFC0012,0xDFA40001,0xDFA40001,0xDFA40001,0xDBA80001,0xC7FC0012,0xC7FC0012,0xC7FC0012,0xDB980001,0xD8000012,0xF1B00008,0x1B00014,0x1B00014,0xFFAC0000,0xF3AC0000,0xEBAC0000,0xEBAC0000,0xE5AC0000,0xF7AC0005,0xF9A80000,0xE1AC0001,0xDFA40001,
+0xB9FC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table28[] = {
+0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0xD1F80000,
+0xD1F80000,0xD1F80000,0xD1F80000,0xDE000000,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1DC0000,0x1DC0000,0x1DC0000,0x9FFC0000,0xC3FC0000,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xB1FC0000,
+0xB1FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xE4000000,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xE4000000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xE4000000,0xE4000000,0x1E80000,0x1C80001,0x1C80001,0x49FC0000,0x81FC0000,0x9FFC0000,0x9FFC0000,0xC1FC0000,0x49FC0000,0x81FC0000,0xCFFC0000,0xD9FC0000,
+0xCFFC0000,0x1D00001,0x1D00001,0x1D00001,0x1D00001,0xBDFC0000,0xBDFC0000,0xBDFC0000,0xDFF80000,0xDFF80000,0xE8000000,0xBDFC0000,0xBDFC0000,0xBDFC0000,0xDFF80000,0xDFF80000,0xE8000000,0xDFF80000,0xDFF80000,0xE8000000,0xE8000000,0xBDFC0000,0xBDFC0000,0xBDFC0000,0xDFF80000,0xDFF80000,0xE8000000,0xDFF80000,0xDFF80000,0xE8000000,0xE8000000,0xDFF80000,
+0xDFF80000,0xE8000000,0xE8000000,0xE8000000,0x67FC0000,0x1F00000,0x1D00001,0xAFFC0000,0xCBFC0000,0xD7FC0000,0xDBFC0000,0xE1FC0000,0x95FC0000,0xBDFC0000,0xD7FC0000,0xE8000000,0xD7FC0000,0x1DC0001,0xCFFC0000,0xE7FC0000,0xEE000000,0xCFFC0000,0xE7FC0000,0xEE000000,0xE7FC0000,0xEE000000,0xEE000000,0xCFFC0000,0xE7FC0000,0xEE000000,0xE7FC0000,0xEE000000,
+0xEE000000,0xE7FC0000,0xEE000000,0xEE000000,0xEE000000,0xCFFC0000,0xE7FC0000,0xEE000000,0xE7FC0000,0xEE000000,0xEE000000,0xE7FC0000,0xEE000000,0xEE000000,0xEE000000,0xE7FC0000,0xEE000000,0xEE000000,0xEE000000,0xEE000000,0xB3FC0000,0x7FC0000,0x7FC0000,0xD9FC0000,0xE5FC0000,0xEBFC0000,0xEE000000,0xEE000000,0xC5FC0000,0xDDFC0000,0xEFD00000,0xEE000000,
+0xE1FC0000,0x1CC008C,0xFFC80037,0xF5C80033,0xEFC80033,0xFFC40024,0xF5C40013,0xF1C4001A,0xF1C40024,0xEDC40016,0xEBC40026,0xFDC00034,0xF5C0000A,0xF1C0000F,0xF3BC0013,0xEFBC0002,0xEBC00016,0xEFC00034,0xEDBC000F,0xEBBC0019,0xE9BC0035,0xB7FC0088,0xF9B40033,0xEFBC0033,0xF3B40026,0xEFB80012,0xEBBC0026,0xF5A80033,0xEFAC0009,0xEBB00015,0xE9B40034,0xDDF40088,
+0xEF980033,0xEBA00026,0xE9940034,0xE6000088,0xFDC8003F,0xFFCC0064,0xFFCC006C,0xFFC00007,0xF7C00002,0xF1C00002,0xEFC00002,0xEFBC0002,0xFFC40034,0xFFBC0005,0xEFBC0009,0xEBB00015,0xD3FC0088,0x1D40033,0xFDD0000A,0xF3CC000A,0xEFCC000A,0xF7CC0013,0xF3C80002,0xEFCC0001,0xEFCC0013,0xEFC80005,0xEBC80015,0xC1FC0033,0xF5C00009,0xEFC4000A,0xF3BC0012,0xEFBC0001,
+0xEBC40014,0xE1F80033,0xEFAC0008,0xEBB00014,0xE8000034,0xC1FC0033,0xF5C00009,0xEFC4000A,0xF3BC0012,0xEFBC0001,0xEBC40014,0xE1F80033,0xEFAC0008,0xEBB00014,0xE8000034,0xE1F80033,0xEFAC0008,0xEBB00014,0xE8000034,0xE8000034,0xFDCC0014,0xF1D0002D,0xF3D4002A,0xFFC40003,0xF7C00001,0xF1C00001,0xEFC00001,0xEFBC0001,0xF7CC0019,0xFFC00002,0xEFBC0009,0xEBB00014,
+0xD9FC0033,0x1C80033,0x1C80033,0x1C80033,0x1C80033,0xF7C40012,0xF7C40012,0xF7C40012,0xEDC40012,0xEDC40012,0xE9C40012,0xF5C00009,0xF5C00009,0xF5C00009,0xEDC00002,0xEDC00002,0xE9C00005,0xEBBC0009,0xEBBC0009,0xE9BC0001,0xE7BC0009,0xAFFC0033,0xAFFC0033,0xAFFC0033,0xEFB80012,0xEFB80012,0xE9BC0012,0xEDB40009,0xEDB40009,0xE9B40001,0xE7B40009,0xD7FC0033,
+0xD7FC0033,0xE9A80012,0xE79C0008,0xE4000034,0xFBC40013,0xFDC80023,0x1C80033,0xFDC00003,0xF7C00001,0xF1C00001,0xEFC00002,0xEDBC0002,0xFDC00013,0xFFBC0001,0xEFBC0008,0xE9B40001,0xCDFC0033,0x1CC000A,0x1CC000A,0x1CC000A,0x1CC000A,0xEFCC0001,0xEFCC0001,0xEFCC0001,0xEBC80001,0xEBC80001,0xE9C80001,0xB7FC0008,0xB7FC0008,0xB7FC0008,0xEBC40001,0xEBC40001,
+0xE9C40001,0xDDF40008,0xDDF40008,0xE9B80000,0xE6000008,0xB7FC0008,0xB7FC0008,0xB7FC0008,0xEBC40001,0xEBC40001,0xE9C40001,0xDDF40008,0xDDF40008,0xE9B80000,0xE6000008,0xDDF40008,0xDDF40008,0xE9B80000,0xE6000008,0xE6000008,0xFDC80002,0xFFCC0002,0x1CC000A,0xF5C80001,0xF3C40000,0xEFC40000,0xEDC40000,0xEBC40001,0xFFC40002,0xFBC00000,0xD3FC0008,0xE9B80000,
+0xD3FC0008,0x1D80012,0xF9D40001,0xF1D40001,0xEFD00001,0xC7FC0012,0xF3C80001,0xEFCC0000,0xE3FC0012,0xEFB80000,0xEA000014,0xC7FC0012,0xF3C80001,0xEFCC0000,0xE3FC0012,0xEFB80000,0xEA000014,0xE3FC0012,0xEFB80000,0xEA000014,0xEA000014,0xC7FC0012,0xF3C80001,0xEFCC0000,0xE3FC0012,0xEFB80000,0xEA000014,0xE3FC0012,0xEFB80000,0xEA000014,0xEA000014,0xE3FC0012,
+0xEFB80000,0xEA000014,0xEA000014,0xEA000014,0xFFD00008,0x1F80012,0xF5D8000D,0xFFC40002,0xF7C00001,0xF3BC0000,0xEFC00000,0xEFB00000,0xF9D00008,0xFFC00001,0xEFC40001,0xEA000014,0xDDF80012,0x1C40012,0x1C40012,0x1C40012,0x1C40012,0x1C40012,0x1C40012,0x1C40012,0x1C40012,0x1C40012,0x1C40012,0xEFC00001,0xEFC00001,0xEFC00001,0xEFC00001,0xEFC00001,
+0xEFC00001,0xE7C00001,0xE7C00001,0xE7C00001,0xE5BC0001,0xA9FC0012,0xA9FC0012,0xA9FC0012,0xA9FC0012,0xA9FC0012,0xA9FC0012,0xE9B40001,0xE9B40001,0xE9B40001,0xE5B80000,0xD5F80012,0xD5F80012,0xD5F80012,0xE5A40000,0xE0000014,0xF9C0000A,0x1C40012,0x1C40012,0xF9C00002,0xF7C00001,0xF1C00001,0xF1C00001,0xEDC00001,0xFFBC0005,0xFFBC0001,0xEBBC0000,0xE9B40001,
+0xC9FC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table29[] = {
+0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xDDF40000,
+0xDDF40000,0xDDF40000,0xDDF40000,0xE6000000,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1EC0000,0x1EC0000,0x1EC0000,0xB7FC0000,0xD3FC0000,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xC9FC0000,
+0xC9FC0000,0xE5F80000,0xE5F80000,0xE5F80000,0xEC000000,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xE5F80000,0xE5F80000,0xE5F80000,0xEC000000,0xE5F80000,0xE5F80000,0xE5F80000,0xEC000000,0xEC000000,0x5F80000,0x1D80001,0x1D80001,0x83FC0000,0xA9FC0000,0xBDFC0000,0xBDFC0000,0xD3FC0000,0x83FC0000,0xA9FC0000,0xDFF80000,0xE5F80000,
+0xDFF80000,0x1E00001,0x1E00001,0x1E00001,0x1E00001,0xD5FC0000,0xD5FC0000,0xD5FC0000,0xEBF80000,0xEBF80000,0xF0000000,0xD5FC0000,0xD5FC0000,0xD5FC0000,0xEBF80000,0xEBF80000,0xF0000000,0xEBF80000,0xEBF80000,0xF0000000,0xF0000000,0xD5FC0000,0xD5FC0000,0xD5FC0000,0xEBF80000,0xEBF80000,0xF0000000,0xEBF80000,0xEBF80000,0xF0000000,0xF0000000,0xEBF80000,
+0xEBF80000,0xF0000000,0xF0000000,0xF0000000,0x9FFC0000,0x27FC0000,0x1E00001,0xCDFC0000,0xDDFC0000,0xE5FC0000,0xE9F80000,0xEDF80000,0xBDFC0000,0xD5FC0000,0xE5FC0000,0xF0000000,0xE5FC0000,0x1EC0001,0xE9FC0000,0xF3FC0000,0xF6000000,0xE9FC0000,0xF3FC0000,0xF6000000,0xF3FC0000,0xF6000000,0xF6000000,0xE9FC0000,0xF3FC0000,0xF6000000,0xF3FC0000,0xF6000000,
+0xF6000000,0xF3FC0000,0xF6000000,0xF6000000,0xF6000000,0xE9FC0000,0xF3FC0000,0xF6000000,0xF3FC0000,0xF6000000,0xF6000000,0xF3FC0000,0xF6000000,0xF6000000,0xF6000000,0xF3FC0000,0xF6000000,0xF6000000,0xF6000000,0xF6000000,0xDBFC0000,0x87FC0000,0x87FC0000,0xEDFC0000,0xF3F80000,0xF5FC0000,0xF6000000,0xF6000000,0xE3FC0000,0xEFFC0000,0xF7E00000,0xF6000000,
+0xF1FC0000,0x1DC008C,0xFFDC0044,0xFDD80033,0xF7D80033,0xFDD80034,0xFDD40013,0xF9D4001A,0xF9D40024,0xF5D40016,0xF3D40026,0xFFD0003C,0xFDD0000A,0xF9D0000F,0xFBCC0013,0xF7CC0002,0xF3D00016,0xF7D00034,0xF5CC000F,0xF3CC0019,0xF1CC0035,0xCFFC0088,0xFFC80035,0xF7CC0033,0xFBC40026,0xF7C80012,0xF3CC0026,0xFDB80033,0xF7BC0009,0xF3C00015,0xF1C40034,0xE7FC0088,
+0xF7A80033,0xF3B00026,0xF1A40034,0xEE000088,0xFFD8004E,0xF7DC0076,0xF7DC007B,0xFFD4001A,0xFFD00002,0xF9D00002,0xF7D00002,0xF7CC0002,0xFFD4004A,0xFFD00015,0xF7CC0009,0xF3C00015,0xE1FC0088,0x1E40033,0xFFE0000E,0xFBDC000A,0xF7DC000A,0xFFDC0013,0xFBD80002,0xF7DC0001,0xF7DC0013,0xF7D80005,0xF3D80015,0xD9FC0033,0xFDD00009,0xF7D4000A,0xFBCC0012,0xF7CC0001,
+0xF3D40014,0xEDF80033,0xF7BC0008,0xF3C00014,0xF0000034,0xD9FC0033,0xFDD00009,0xF7D4000A,0xFBCC0012,0xF7CC0001,0xF3D40014,0xEDF80033,0xF7BC0008,0xF3C00014,0xF0000034,0xEDF80033,0xF7BC0008,0xF3C00014,0xF0000034,0xF0000034,0xFDE00021,0xF9E0002D,0xFBE4002A,0xFFD8000D,0xFFD00001,0xF9D00001,0xF7D00001,0xF7CC0001,0xFFDC0019,0xFFD4000A,0xF7CC0009,0xF3C00014,
+0xE7FC0033,0x1D80033,0x1D80033,0x1D80033,0x1D80033,0xFFD40012,0xFFD40012,0xFFD40012,0xF5D40012,0xF5D40012,0xF1D40012,0xFDD00009,0xFDD00009,0xFDD00009,0xF5D00002,0xF5D00002,0xF1D00005,0xF3CC0009,0xF3CC0009,0xF1CC0001,0xEFCC0009,0xC7FC0033,0xC7FC0033,0xC7FC0033,0xF7C80012,0xF7C80012,0xF1CC0012,0xF5C40009,0xF5C40009,0xF1C40001,0xEFC40009,0xE3FC0033,
+0xE3FC0033,0xF1B80012,0xEFAC0008,0xEC000034,0xFDD4001D,0xF5D8002A,0x1D80033,0xFFD4000A,0xFFD00001,0xF9D00001,0xF7D00002,0xF5CC0002,0xFFD00018,0xFFD00005,0xF7CC0008,0xF1C40001,0xDDF80033,0x1DC000A,0x1DC000A,0x1DC000A,0x1DC000A,0xF7DC0001,0xF7DC0001,0xF7DC0001,0xF3D80001,0xF3D80001,0xF1D80001,0xCFFC0008,0xCFFC0008,0xCFFC0008,0xF3D40001,0xF3D40001,
+0xF1D40001,0xE7FC0008,0xE7FC0008,0xF1C80000,0xEE000008,0xCFFC0008,0xCFFC0008,0xCFFC0008,0xF3D40001,0xF3D40001,0xF1D40001,0xE7FC0008,0xE7FC0008,0xF1C80000,0xEE000008,0xE7FC0008,0xE7FC0008,0xF1C80000,0xEE000008,0xEE000008,0xFFD80004,0xF7DC0005,0x1DC000A,0xFDD80001,0xFBD40000,0xF7D40000,0xF5D40000,0xF3D40001,0xF1DC0005,0xFBD40001,0xE1FC0008,0xF1C80000,
+0xE1FC0008,0x1E80012,0xFDE40002,0xF9E40001,0xF7E00001,0xDFFC0012,0xFBD80001,0xF7DC0000,0xEFFC0012,0xF7C80000,0xF2000014,0xDFFC0012,0xFBD80001,0xF7DC0000,0xEFFC0012,0xF7C80000,0xF2000014,0xEFFC0012,0xF7C80000,0xF2000014,0xF2000014,0xDFFC0012,0xFBD80001,0xF7DC0000,0xEFFC0012,0xF7C80000,0xF2000014,0xEFFC0012,0xF7C80000,0xF2000014,0xF2000014,0xEFFC0012,
+0xF7C80000,0xF2000014,0xF2000014,0xF2000014,0xF7E8000D,0x57FC0012,0xFDE8000D,0xFDE00008,0xFFD00001,0xFBCC0000,0xF7D00000,0xF7C00000,0xF9E4000D,0xFFD80005,0xF7D40001,0xF2000014,0xEBFC0012,0x1D40012,0x1D40012,0x1D40012,0x1D40012,0x1D40012,0x1D40012,0x1D40012,0x1D40012,0x1D40012,0x1D40012,0xF7D00001,0xF7D00001,0xF7D00001,0xF7D00001,0xF7D00001,
+0xF7D00001,0xEFD00001,0xEFD00001,0xEFD00001,0xEDCC0001,0xC1FC0012,0xC1FC0012,0xC1FC0012,0xC1FC0012,0xC1FC0012,0xC1FC0012,0xF1C40001,0xF1C40001,0xF1C40001,0xEDC80000,0xE1F80012,0xE1F80012,0xE1F80012,0xEDB40000,0xE8000014,0xF3D4000D,0x1D40012,0x1D40012,0xFBD00005,0xFFD00001,0xF9D00001,0xF9D00001,0xF5D00001,0xFBD00008,0xFDCC0004,0xF3CC0000,0xF1C40001,
+0xD9FC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table30[] = {
+0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xE7FC0000,
+0xE7FC0000,0xE7FC0000,0xE7FC0000,0xEE000000,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0x7FC0000,0x7FC0000,0x7FC0000,0xCFFC0000,0xE1FC0000,0x1E80001,0x1E80001,0x1E80001,0x1E80001,0x1E80001,0x1E80001,0x1E80001,0x1E80001,0x1E80001,0x1E80001,0xE3FC0000,0xE3FC0000,0xE3FC0000,0xE3FC0000,0xE3FC0000,
+0xE3FC0000,0xF1F80000,0xF1F80000,0xF1F80000,0xF4000000,0xE3FC0000,0xE3FC0000,0xE3FC0000,0xE3FC0000,0xE3FC0000,0xE3FC0000,0xF1F80000,0xF1F80000,0xF1F80000,0xF4000000,0xF1F80000,0xF1F80000,0xF1F80000,0xF4000000,0xF4000000,0x67FC0000,0x1E80001,0x1E80001,0xBBFC0000,0xD1FC0000,0xDBFC0000,0xDBFC0000,0xE7FC0000,0xBBFC0000,0xD1FC0000,0xEDFC0000,0xF1F80000,
+0xEDFC0000,0x1F00001,0x1F00001,0x1F00001,0x1F00001,0xEFFC0000,0xEFFC0000,0xEFFC0000,0xF7F80000,0xF7F80000,0xF8000000,0xEFFC0000,0xEFFC0000,0xEFFC0000,0xF7F80000,0xF7F80000,0xF8000000,0xF7F80000,0xF7F80000,0xF8000000,0xF8000000,0xEFFC0000,0xEFFC0000,0xEFFC0000,0xF7F80000,0xF7F80000,0xF8000000,0xF7F80000,0xF7F80000,0xF8000000,0xF8000000,0xF7F80000,
+0xF7F80000,0xF8000000,0xF8000000,0xF8000000,0xD7FC0000,0xA7FC0000,0x1F00001,0xEBFC0000,0xF1FC0000,0xF5FC0000,0xF5FC0000,0xF7FC0000,0xE3FC0000,0xEFFC0000,0xF5FC0000,0xF8000000,0xF5FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1EC008C,0xFFEC005F,0xFFE80043,0xFFE80033,0xFFE8004C,0xFFE4002B,0xFFE4001B,0xFFE40026,0xFDE40016,0xFBE40026,0xFFE80054,0xFFE40023,0xFFE00011,0xFFE0001B,0xFFDC0002,0xFBE00016,0xFFE00034,0xFDDC000F,0xFBDC0019,0xF9DC0035,0xE9FC0088,0xFFE4004B,0xFFDC0033,0xFFD80036,0xFFD80012,0xFBDC0026,0xFFD8003D,0xFFCC0009,0xFBD00015,0xF9D40034,0xF3FC0088,
+0xFFB80033,0xFBC00026,0xF9B40034,0xF6000088,0xFFEC006A,0xFFEC0076,0xFFEC007B,0xFFE8004F,0xFFE40026,0xFFE0000C,0xFFE00002,0xFFDC0002,0xFDEC006A,0xFFE4004A,0xFFDC0009,0xFBD00015,0xF1FC0088,0x1F40033,0xFDF00023,0xFFF0000E,0xFFEC000A,0xFDF00023,0xFFEC000A,0xFFEC0001,0xFFEC0013,0xFFE80005,0xFBE80015,0xF1FC0033,0xFFEC0019,0xFFE4000A,0xFFE40015,0xFFDC0001,
+0xFBE40014,0xF9F80033,0xFFCC0008,0xFBD00014,0xF8000034,0xF1FC0033,0xFFEC0019,0xFFE4000A,0xFFE40015,0xFFDC0001,0xFBE40014,0xF9F80033,0xFFCC0008,0xFBD00014,0xF8000034,0xF9F80033,0xFFCC0008,0xFBD00014,0xF8000034,0xF8000034,0xFDF4002A,0xF3F40033,0xF3F40033,0xFFEC001E,0xFFE80012,0xFFE40009,0xFFE00001,0xFFDC0001,0xFFF00029,0xFFF00021,0xFFDC0009,0xFBD00014,
+0xF7FC0033,0x1E80033,0x1E80033,0x1E80033,0x1E80033,0xFDE4001B,0xFDE4001B,0xFDE4001B,0xFDE40012,0xFDE40012,0xF9E40012,0xFFE00011,0xFFE00011,0xFFE00011,0xFDE00002,0xFDE00002,0xF9E00005,0xFBDC0009,0xFBDC0009,0xF9DC0001,0xF7DC0009,0xDFFC0033,0xDFFC0033,0xDFFC0033,0xFFD80012,0xFFD80012,0xF9DC0012,0xFDD40009,0xFDD40009,0xF9D40001,0xF7D40009,0xEFFC0033,
+0xEFFC0033,0xF9C80012,0xF7BC0008,0xF4000034,0xFFE80022,0xFDE8002A,0x1E80033,0xFDE4001A,0xFFE4000D,0xFFE00003,0xFFE00002,0xFDDC0002,0xFFE40021,0xFFE00018,0xFFDC0008,0xF9D40001,0xEBFC0033,0x1EC000A,0x1EC000A,0x1EC000A,0x1EC000A,0xFFEC0001,0xFFEC0001,0xFFEC0001,0xFBE80001,0xFBE80001,0xF9E80001,0xE9FC0008,0xE9FC0008,0xE9FC0008,0xFBE40001,0xFBE40001,
+0xF9E40001,0xF3FC0008,0xF3FC0008,0xF9D80000,0xF6000008,0xE9FC0008,0xE9FC0008,0xE9FC0008,0xFBE40001,0xFBE40001,0xF9E40001,0xF3FC0008,0xF3FC0008,0xF9D80000,0xF6000008,0xF3FC0008,0xF3FC0008,0xF9D80000,0xF6000008,0xF6000008,0xFBEC0005,0xFFEC0005,0x1EC000A,0xF9EC0005,0xFDE80002,0xFFE40000,0xFDE40000,0xFBE40001,0xF9EC0005,0xFFE80002,0xF1FC0008,0xF9D80000,
+0xF1FC0008,0x1F80012,0xFFF4000A,0xFFF00005,0xFFF00001,0xF7FC0012,0xFFF00005,0xFFEC0000,0xFBFC0012,0xFFD80000,0xFA000014,0xF7FC0012,0xFFF00005,0xFFEC0000,0xFBFC0012,0xFFD80000,0xFA000014,0xFBFC0012,0xFFD80000,0xFA000014,0xFA000014,0xF7FC0012,0xFFF00005,0xFFEC0000,0xFBFC0012,0xFFD80000,0xFA000014,0xFBFC0012,0xFFD80000,0xFA000014,0xFA000014,0xFBFC0012,
+0xFFD80000,0xFA000014,0xFA000014,0xFA000014,0xFFF8000D,0xD7FC0012,0xF5F80012,0xFFF4000D,0xFDF4000D,0xFFE80005,0xFFE00000,0xFFD00000,0xF5FC0012,0xFFF00011,0xFFE40001,0xFA000014,0xFBFC0012,0x1E40012,0x1E40012,0x1E40012,0x1E40012,0x1E40012,0x1E40012,0x1E40012,0x1E40012,0x1E40012,0x1E40012,0xFFE00001,0xFFE00001,0xFFE00001,0xFFE00001,0xFFE00001,
+0xFFE00001,0xF7E00001,0xF7E00001,0xF7E00001,0xF5DC0001,0xD9FC0012,0xD9FC0012,0xD9FC0012,0xD9FC0012,0xD9FC0012,0xD9FC0012,0xF9D40001,0xF9D40001,0xF9D40001,0xF5D80000,0xEDF80012,0xEDF80012,0xEDF80012,0xF5C40000,0xF0000014,0xFBE4000D,0x1E40012,0x1E40012,0xFBE0000A,0xFDE00005,0xFFE00002,0xFFE00002,0xFDE00001,0xF7E4000D,0xFDE00008,0xFBDC0000,0xF9D40001,
+0xE7FC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table31[] = {
+0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xF3FC0000,
+0xF3FC0000,0xF3FC0000,0xF3FC0000,0xF6000000,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0x87FC0000,0x87FC0000,0x87FC0000,0xE9FC0000,0xF1FC0000,0x1F80001,0x1F80001,0x1F80001,0x1F80001,0x1F80001,0x1F80001,0x1F80001,0x1F80001,0x1F80001,0x1F80001,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xFBFC0000,
+0xFBFC0000,0xFDF80000,0xFDF80000,0xFDF80000,0xFC000000,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xFDF80000,0xFDF80000,0xFDF80000,0xFC000000,0xFDF80000,0xFDF80000,0xFDF80000,0xFC000000,0xFC000000,0xE7FC0000,0x1F80001,0x1F80001,0xF5FC0000,0xF7FC0000,0xF9FC0000,0xF9FC0000,0xFBFC0000,0xF5FC0000,0xF7FC0000,0xFDF80000,0xFDF80000,
+0xFDF80000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1F8002C,0xFFF80027,0xFFF80024,0xFFF80023,0xFFF80022,0xFFF4001F,0xFFF4001B,0xFFF4001A,0xFFF40016,0xFFF40012,0xFFF4001C,0xFFF40017,0xFFF40013,0xFFF00012,0xFFF0000E,0xFFF0000A,0xFFF00009,0xFFF00005,0xFFF00001,0xFFEC0005,0xF7FC002C,0xFDF80027,0xFFF40023,0xFFF0001A,0xFFF00016,0xFFF00012,0xFFF00011,0xFFF0000D,0xFFE40005,0xFFE40005,0xFBFC002C,
+0xFFEC0023,0xFFE00012,0xFFCC0004,0xFC00002C,0xFFF80027,0xF5F8002C,0xF5F8002C,0xFFF80022,0xFFF4001A,0xFFF40012,0xFFF40011,0xFFF00009,0xFFF80022,0xFFF4001F,0xFFF0000B,0xFFE40005,0xFBFC002C,0x1FC0003,0xFDFC0003,0xFFFC0002,0xFFFC0002,0xFDFC0003,0xFFFC0002,0xFFFC0002,0xFFFC0001,0xFFFC0001,0xFFF80001,0xFDFC0003,0xFFFC0002,0xFFFC0002,0xFFFC0001,0xFFF80001,
+0xFFF80000,0xFFF80003,0xFFF80002,0xFFF00000,0xFE000004,0xFDFC0003,0xFFFC0002,0xFFFC0002,0xFFFC0001,0xFFF80001,0xFFF80000,0xFFF80003,0xFFF80002,0xFFF00000,0xFE000004,0xFFF80003,0xFFF80002,0xFFF00000,0xFE000004,0xFE000004,0xFDFC0003,0xF7FC0003,0xF7FC0003,0xFDFC0003,0xFFFC0002,0xFFFC0001,0xFFF80001,0xFFF80001,0xFDFC0003,0xFDFC0003,0xFFF80002,0xFFF00000,
+0xFFF80003,0x1F80023,0x1F80023,0x1F80023,0x1F80023,0xFFF4001B,0xFFF4001B,0xFFF4001B,0xFFF40016,0xFFF40016,0xFFF40012,0xFFF40013,0xFFF40013,0xFFF40013,0xFFF0000E,0xFFF0000E,0xFFF0000A,0xFFF00005,0xFFF00005,0xFFF00001,0xFDEC0005,0xF7FC0023,0xF7FC0023,0xF7FC0023,0xFFF00016,0xFFF00016,0xFFF00012,0xFFF0000D,0xFFF0000D,0xFFE40005,0xFDE80004,0xFBFC0023,
+0xFBFC0023,0xFFE00012,0xFDD40004,0xFA000024,0xFFF40022,0xF5F80023,0x1F80023,0xFFF4001D,0xFFF40016,0xFFF40011,0xFFF40011,0xFFF00009,0xFFF4001D,0xFFF40016,0xFFF0000B,0xFFE40005,0xFBFC0023,0x1FC0002,0x1FC0002,0x1FC0002,0x1FC0002,0xFDFC0002,0xFDFC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFF80001,0xFDFC0002,0xFDFC0002,0xFDFC0002,0xFFF80001,0xFFF80001,
+0xFFF80000,0xFFF80002,0xFFF80002,0xFFF00000,0xFC000004,0xFDFC0002,0xFDFC0002,0xFDFC0002,0xFFF80001,0xFFF80001,0xFFF80000,0xFFF80002,0xFFF80002,0xFFF00000,0xFC000004,0xFFF80002,0xFFF80002,0xFFF00000,0xFC000004,0xFC000004,0xFBFC0002,0xF7FC0002,0x1FC0002,0xFDFC0002,0xFDFC0002,0xFFF80001,0xFFF80001,0xFFF80001,0xFDFC0002,0xFDFC0002,0xFFF80002,0xFFF00000,
+0xFFF80002,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1F40012,0x1F40012,0x1F40012,0x1F40012,0x1F40012,0x1F40012,0x1F40012,0x1F40012,0x1F40012,0x1F40012,0xFDF0000A,0xFDF0000A,0xFDF0000A,0xFDF0000A,0xFDF0000A,
+0xFDF0000A,0xFFF00001,0xFFF00001,0xFFF00001,0xFDEC0001,0xF1FC0012,0xF1FC0012,0xF1FC0012,0xF1FC0012,0xF1FC0012,0xF1FC0012,0xFDEC0005,0xFDEC0005,0xFDEC0005,0xFDE80000,0xF9F80012,0xF9F80012,0xF9F80012,0xFDD40000,0xF8000014,0xF3F40012,0x1F40012,0x1F40012,0xFFF4000D,0xFDF4000D,0xFFF0000A,0xFFF0000A,0xFFF00005,0xFFF4000D,0xFDF4000D,0xFFF00002,0xFDEC0005,
+0xF7FC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table32[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x80001,0x80001,0x80001,0x80001,0x20C0000,0x20C0000,0x20C0000,0x180000,0x180000,0x4000000,0x20C0000,0x20C0000,0x20C0000,0x180000,0x180000,0x4000000,0x180000,0x180000,0x4000000,0x4000000,0x20C0000,0x20C0000,0x20C0000,0x180000,0x180000,0x4000000,0x180000,0x180000,0x4000000,0x4000000,0x180000,
+0x180000,0x4000000,0x4000000,0x4000000,0xC0000,0xC080000,0x80001,0xC0000,0x100000,0x140000,0x140000,0x200000,0xC0000,0x20C0000,0x140000,0x4000000,0x140000,0x200001,0x2300000,0x640000,0x10000000,0x2300000,0x640000,0x10000000,0x640000,0x10000000,0x10000000,0x2300000,0x640000,0x10000000,0x640000,0x10000000,
+0x10000000,0x640000,0x10000000,0x10000000,0x10000000,0x2300000,0x640000,0x10000000,0x640000,0x10000000,0x10000000,0x640000,0x10000000,0x10000000,0x10000000,0x640000,0x10000000,0x10000000,0x10000000,0x10000000,0x2280000,0x240000,0x240000,0x380000,0x500000,0x9C0000,0x10000000,0x10000000,0x22C0000,0x400000,0x1F40000,0x10000000,
+0x480000,0xC00C2,0x2E040011,0x18040011,0x10040011,0x20000048,0x18000009,0x10000001,0x10000048,0xE00001D,0xA000048,0x14000099,0x12000035,0xE00001D,0xC000060,0xC000030,0xA000058,0xA000099,0xA000059,0x8000074,0x6000099,0x1000C2,0x12000059,0xC000031,0xC000070,0xC000040,0x8000062,0x80000A7,0xA000069,0x800007D,0x600009D,0x1800C2,
+0x8000089,0x8000098,0x40000B2,0x40000C2,0x42000029,0xA8000048,0xEA040011,0x1E000029,0x16000032,0xE000032,0xC000022,0xA00003D,0x2C000056,0x1A00003D,0xC00004F,0x800007D,0x1400C2,0x10009A,0x2E04000D,0x1804000D,0x1004000D,0x20000048,0x18000009,0x10000001,0x10000048,0xE00001D,0xA000048,0x140099,0x12000035,0xE00001D,0xC000060,0xC000030,
+0xA000058,0x240099,0xA000059,0x8000074,0x6000099,0x140099,0x12000035,0xE00001D,0xC000060,0xC000030,0xA000058,0x240099,0xA000059,0x8000074,0x6000099,0x240099,0xA000059,0x8000074,0x6000099,0x6000099,0x42000029,0xA8000048,0xEA04000D,0x1E000029,0x16000032,0xE000032,0xC000022,0xA00003D,0x2C00004D,0x1A000039,0xC00004E,0x8000074,
+0x1C0099,0x40011,0x40011,0x40011,0x40011,0xE000000,0xE000000,0xE000000,0x6000000,0x6000000,0x4000000,0x400000D,0x400000D,0x400000D,0x6000004,0x6000004,0x4000004,0x200000D,0x200000D,0x2000008,0x200000D,0x40011,0x40011,0x40011,0x6000008,0x6000008,0x2000006,0x200000E,0x200000E,0x2000009,0x200000E,0x80011,
+0x80011,0x200000C,0x2000011,0x12,0x20000004,0x48000000,0x40011,0x10000004,0x6000005,0x8000004,0x8000004,0x4000005,0xC000009,0xA000006,0x200000D,0x2000009,0x80011,0x4000D,0x4000D,0x4000D,0x4000D,0xE000000,0xE000000,0xE000000,0x6000000,0x6000000,0x4000000,0x4000D,0x4000D,0x4000D,0x6000004,0x6000004,
+0x4000004,0x8000D,0x8000D,0x2000008,0x200000D,0x4000D,0x4000D,0x4000D,0x6000004,0x6000004,0x4000004,0x8000D,0x8000D,0x2000008,0x200000D,0x8000D,0x8000D,0x2000008,0x200000D,0x200000D,0x20000004,0x48000000,0x4000D,0x10000004,0x6000005,0x8000004,0x8000004,0x4000005,0x4040008,0xA000005,0x8000D,0x2000008,
+0x8000D,0x14004A,0x260C0001,0x16080001,0x10080001,0x200048,0x18000009,0x10000001,0x3C0048,0xE00001D,0xA000048,0x200048,0x18000009,0x10000001,0x3C0048,0xE00001D,0xA000048,0x3C0048,0xE00001D,0xA000048,0xA000048,0x200048,0x18000009,0x10000001,0x3C0048,0xE00001D,0xA000048,0x3C0048,0xE00001D,0xA000048,0xA000048,0x3C0048,
+0xE00001D,0xA000048,0xA000048,0xA000048,0x42000019,0x180048,0xAE0C0001,0x1E000019,0x16000019,0x10000019,0xE000014,0xE000028,0x32000022,0x1E00001D,0x10000011,0xA000048,0x2C0048,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table33[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x40001,0x40001,0x40001,0x40001,0x40001,0x40001,0x40001,0x40001,0x40001,0x40001,0x80000,0x80000,0x80000,0x80000,0x80000,
+0x80000,0xC0000,0xC0000,0xC0000,0x2000000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0xC0000,0xC0000,0xC0000,0x2000000,0xC0000,0xC0000,0xC0000,0x2000000,0x2000000,0xA040000,0x40001,0x40001,0x6040000,0x80000,0x80000,0x80000,0x80000,0x6040000,0x80000,0xC0000,0xC0000,
+0xC0000,0x180001,0x180001,0x180001,0x180001,0x2240000,0x2240000,0x2240000,0x4C0000,0x4C0000,0xC000000,0x2240000,0x2240000,0x2240000,0x4C0000,0x4C0000,0xC000000,0x4C0000,0x4C0000,0xC000000,0xC000000,0x2240000,0x2240000,0x2240000,0x4C0000,0x4C0000,0xC000000,0x4C0000,0x4C0000,0xC000000,0xC000000,0x4C0000,
+0x4C0000,0xC000000,0xC000000,0xC000000,0x41C0000,0x1C0000,0x180001,0x240000,0x2C0000,0x340000,0x3C0000,0x5C0000,0x200000,0x2240000,0x340000,0xC000000,0x340000,0x300001,0x480000,0x940000,0x18000000,0x480000,0x940000,0x18000000,0x940000,0x18000000,0x18000000,0x480000,0x940000,0x18000000,0x940000,0x18000000,
+0x18000000,0x940000,0x18000000,0x18000000,0x18000000,0x480000,0x940000,0x18000000,0x940000,0x18000000,0x18000000,0x940000,0x18000000,0x18000000,0x18000000,0x940000,0x18000000,0x18000000,0x18000000,0x18000000,0x23C0000,0x2340000,0x2340000,0x540000,0x780000,0xEC0000,0x18000000,0x18000000,0x440000,0x5C0000,0xBC80000,0x18000000,
+0x680000,0x14017F,0x3E0C005E,0x220C005E,0x180C005E,0x3404004D,0x22040006,0x1804000E,0x1A04004D,0x16000011,0x1204004D,0x2A0000F3,0x22000045,0x18000032,0x18000069,0x14000021,0x12000051,0x140000F3,0x10000084,0x10000090,0xC0000F4,0x1C017F,0x1E0000AE,0x18000072,0x180000A9,0x12000051,0x12000075,0x12000118,0x100000A8,0xE0000B2,0xC000104,0x38017F,
+0x100000FD,0xE0000FD,0xA000139,0xA000181,0x6400001A,0xFA04004F,0xFE0C0067,0x3400001A,0x22000021,0x1A00001A,0x1600000E,0x14000038,0x42000066,0x2C000041,0x1600005C,0xE0000B2,0x28017F,0x1C00F3,0x3A100032,0x20100032,0x18100032,0x30080049,0x22040002,0x18080005,0x1A040049,0x1604000E,0x12040049,0x2800F3,0x22000045,0x18000032,0x18000069,0x14000021,
+0x12000051,0x5000F3,0x10000084,0x10000090,0xC0000F4,0x2800F3,0x22000045,0x18000032,0x18000069,0x14000021,0x12000051,0x5000F3,0x10000084,0x10000090,0xC0000F4,0x5000F3,0x10000084,0x10000090,0xC0000F4,0xC0000F4,0x6400001A,0xEC080049,0xF0100036,0x3400001A,0x22000021,0x1A00001A,0x1600000E,0x14000038,0x50000052,0x2C000038,0x1600005B,0x10000090,
+0x3800F3,0xC005E,0xC005E,0xC005E,0xC005E,0x22040005,0x22040005,0x22040005,0x12040005,0x12040005,0xC040005,0x16000032,0x16000032,0x16000032,0x12000009,0x12000009,0xC000001,0xA000034,0xA000034,0xA000014,0x6000034,0x20C005D,0x20C005D,0x20C005D,0xC000021,0xC000021,0xC000011,0x8000043,0x8000043,0x8000022,0x6000038,0x18005D,
+0x18005D,0x800003D,0x400004D,0x400005D,0x52000005,0xAA040005,0xC005E,0x2C00000A,0x1A000008,0x1600000A,0x12000008,0xC00000D,0x3400001D,0x1C000016,0xE000033,0x8000022,0x14005D,0x100032,0x100032,0x100032,0x100032,0x1E080001,0x1E080001,0x1E080001,0x10080001,0x10080001,0xC040001,0x180032,0x180032,0x180032,0x12000009,0x12000009,
+0xC000001,0x2C0032,0x2C0032,0xA000014,0x6000034,0x180032,0x180032,0x180032,0x12000009,0x12000009,0xC000001,0x2C0032,0x2C0032,0xA000014,0x6000034,0x2C0032,0x2C0032,0xA000014,0x6000034,0x6000034,0x52000005,0x8C080001,0x100032,0x2C00000A,0x1A000008,0x1600000A,0x12000008,0xC00000D,0x34000014,0x1C000012,0x200032,0xA000014,
+0x200032,0x24004A,0x2E1C0001,0x1E180001,0x18180001,0x380048,0x22040001,0x180C0001,0x700048,0x16000008,0x12000048,0x380048,0x22040001,0x180C0001,0x700048,0x16000008,0x12000048,0x700048,0x16000008,0x12000048,0x12000048,0x380048,0x22040001,0x180C0001,0x700048,0x16000008,0x12000048,0x700048,0x16000008,0x12000048,0x12000048,0x700048,
+0x16000008,0x12000048,0x12000048,0x12000048,0x7400000A,0x280048,0xB61C0001,0x38000008,0x2204000D,0x1C000008,0x18000004,0x14000014,0x50000012,0x2E00000D,0x1A000001,0x12000048,0x500048,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x8000000,0x8000000,0x8000000,0x8000000,0x8000000,
+0x8000000,0x4000000,0x4000000,0x4000000,0x2000000,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x2000002,0x2000002,0x2000002,0x2000001,0x5,0x5,0x5,0x2000004,0x5,0x28000000,0x40005,0x40005,0x12000000,0xC000000,0xA000000,0xA000000,0x6000000,0x12000001,0xC000001,0x4000000,0x2000002,
+0x5,};
+static const uint32_t g_etc1_to_bc7_m6_table34[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x140001,0x140001,0x140001,0x140001,0x140001,0x140001,0x140001,0x140001,0x140001,0x140001,0x200000,0x200000,0x200000,0x200000,0x200000,
+0x200000,0x3C0000,0x3C0000,0x3C0000,0xA000000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x3C0000,0x3C0000,0x3C0000,0xA000000,0x3C0000,0x3C0000,0x3C0000,0xA000000,0xA000000,0x180000,0x140001,0x140001,0x2180000,0x1C0000,0x1C0000,0x1C0000,0x240000,0x2180000,0x1C0000,0x2C0000,0x3C0000,
+0x2C0000,0x280001,0x280001,0x280001,0x280001,0x23C0000,0x23C0000,0x23C0000,0x7C0000,0x7C0000,0x14000000,0x23C0000,0x23C0000,0x23C0000,0x7C0000,0x7C0000,0x14000000,0x7C0000,0x7C0000,0x14000000,0x14000000,0x23C0000,0x23C0000,0x23C0000,0x7C0000,0x7C0000,0x14000000,0x7C0000,0x7C0000,0x14000000,0x14000000,0x7C0000,
+0x7C0000,0x14000000,0x14000000,0x14000000,0x300000,0x2C0000,0x280001,0x380000,0x440000,0x580000,0x640000,0x980000,0x340000,0x23C0000,0x580000,0x14000000,0x580000,0x400001,0x600000,0xC40000,0x20000000,0x600000,0xC40000,0x20000000,0xC40000,0x20000000,0x20000000,0x600000,0xC40000,0x20000000,0xC40000,0x20000000,
+0x20000000,0xC40000,0x20000000,0x20000000,0x20000000,0x600000,0xC40000,0x20000000,0xC40000,0x20000000,0x20000000,0xC40000,0x20000000,0x20000000,0x20000000,0xC40000,0x20000000,0x20000000,0x20000000,0x20000000,0x4500000,0xA440000,0xA440000,0x26C0000,0xA00000,0x13C0000,0x20000000,0x20000000,0x580000,0x7C0000,0x13D80000,0x20000000,
+0x8C0000,0x200253,0x4E1400DE,0x2A1400DF,0x201400DE,0x440C0085,0x2C0C0042,0x220C005A,0x240C0085,0x1E0C0045,0x1A0C0085,0x420000F3,0x30000032,0x2008004A,0x2600004E,0x20000001,0x1A00004C,0x200000F3,0x1C000054,0x18000074,0x140000F4,0x300253,0x28000106,0x200000DD,0x220000D3,0x1E000069,0x18000099,0x1E000158,0x1A0000AF,0x180000B4,0x14000125,0x5C0253,
+0x16000179,0x16000159,0x100001AD,0x10000255,0x9C000003,0xF01000B1,0xF4180106,0x4E000001,0x36000001,0x28000001,0x20000005,0x1E00000C,0x64000051,0x3E00001D,0x20000042,0x180000B4,0x400253,0x2C00F3,0x42200032,0x28200032,0x20200032,0x38180049,0x2A140002,0x20180005,0x22140049,0x1E14000E,0x1A140049,0x4000F3,0x30000032,0x20100032,0x2404004E,0x20000001,
+0x1A040049,0x8000F3,0x1C000054,0x18000074,0x140000F4,0x4000F3,0x30000032,0x20100032,0x2404004E,0x20000001,0x1A040049,0x8000F3,0x1C000054,0x18000074,0x140000F4,0x8000F3,0x1C000054,0x18000074,0x140000F4,0x140000F4,0x9C000003,0xF4180049,0xF8200036,0x4E000001,0x36000001,0x28000001,0x20080001,0x1E00000C,0x6C000021,0x3E00000D,0x2000003E,0x18000074,
+0x5C00F3,0x1400DE,0x1400DE,0x1400DE,0x1400DE,0x320C003D,0x320C003D,0x320C003D,0x1C0C003D,0x1C0C003D,0x140C003D,0x30000032,0x30000032,0x30000032,0x1E000001,0x1E000001,0x1604000C,0x16000034,0x16000034,0x12000008,0xE000034,0x2000DD,0x2000DD,0x2000DD,0x18000059,0x18000059,0x12000041,0x12000068,0x12000068,0x1200002C,0xE00004D,0x3C00DD,
+0x3C00DD,0xE000089,0xA000095,0xA0000DD,0x98000002,0xEE0C003D,0x1400DE,0x4E000000,0x32000001,0x26000001,0x24000002,0x1A000001,0x56000023,0x36000012,0x1E000036,0x1200002C,0x2C00DD,0x200032,0x200032,0x200032,0x200032,0x26180001,0x26180001,0x26180001,0x18180001,0x18180001,0x14140001,0x300032,0x300032,0x300032,0x1C040001,0x1C040001,
+0x140C0000,0x5C0032,0x5C0032,0x12000008,0xE000034,0x300032,0x300032,0x300032,0x1C040001,0x1C040001,0x140C0000,0x5C0032,0x5C0032,0x12000008,0xE000034,0x5C0032,0x5C0032,0x12000008,0xE000034,0xE000034,0x7A080000,0x94180001,0x200032,0x4E000000,0x2C080001,0x24040000,0x1E080001,0x1A000001,0x5C000008,0x3C000002,0x400032,0x12000008,
+0x400032,0x34004A,0x362C0001,0x26280001,0x20280001,0x500048,0x2A140001,0x201C0001,0xA00048,0x20000001,0x1A000048,0x500048,0x2A140001,0x201C0001,0xA00048,0x20000001,0x1A000048,0xA00048,0x20000001,0x1A000048,0x1A000048,0x500048,0x2A140001,0x201C0001,0xA00048,0x20000001,0x1A000048,0xA00048,0x20000001,0x1A000048,0x1A000048,0xA00048,
+0x20000001,0x1A000048,0x1A000048,0x1A000048,0x9C000002,0x4380048,0xBE2C0001,0x4A040001,0x36000001,0x28000001,0x20080000,0x1E000008,0x72000008,0x46000004,0x220C0000,0x1A000048,0x700048,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0x20000000,0x20000000,0x20000000,0x20000000,0x20000000,
+0x20000000,0x10000000,0x10000000,0x10000000,0xA000000,0x10003D,0x10003D,0x10003D,0x10003D,0x10003D,0x10003D,0xC000014,0xC000014,0xC000014,0x800000D,0x18003D,0x18003D,0x18003D,0x8000028,0x400003D,0xA8000000,0xC003D,0xC003D,0x4A000000,0x34000000,0x28000000,0x28000000,0x1A000000,0x44000011,0x34000009,0x14000001,0xC000014,
+0x14003D,};
+static const uint32_t g_etc1_to_bc7_m6_table35[] = {
+0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x240000,
+0x240000,0x240000,0x240000,0x6000000,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xE0C0000,0xE0C0000,0xE0C0000,0x140000,0x1C0000,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x380000,0x380000,0x380000,0x380000,0x380000,
+0x380000,0x700000,0x700000,0x700000,0x12000000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x700000,0x700000,0x700000,0x12000000,0x700000,0x700000,0x700000,0x12000000,0x12000000,0x280000,0x240001,0x240001,0x2C0000,0x300000,0x340000,0x340000,0x400000,0x2C0000,0x300000,0x500000,0x700000,
+0x500000,0x380001,0x380001,0x380001,0x380001,0x540000,0x540000,0x540000,0xAC0000,0xAC0000,0x1C000000,0x540000,0x540000,0x540000,0xAC0000,0xAC0000,0x1C000000,0xAC0000,0xAC0000,0x1C000000,0x1C000000,0x540000,0x540000,0x540000,0xAC0000,0xAC0000,0x1C000000,0xAC0000,0xAC0000,0x1C000000,0x1C000000,0xAC0000,
+0xAC0000,0x1C000000,0x1C000000,0x1C000000,0x440000,0x63C0000,0x380001,0x24C0000,0x600000,0x780000,0x8C0000,0xD40000,0x480000,0x540000,0x780000,0x1C000000,0x780000,0x500001,0x780000,0xF40000,0x28000000,0x780000,0xF40000,0x28000000,0xF40000,0x28000000,0x28000000,0x780000,0xF40000,0x28000000,0xF40000,0x28000000,
+0x28000000,0xF40000,0x28000000,0x28000000,0x28000000,0x780000,0xF40000,0x28000000,0xF40000,0x28000000,0x28000000,0xF40000,0x28000000,0x28000000,0x28000000,0xF40000,0x28000000,0x28000000,0x28000000,0x28000000,0x4640000,0x580000,0x580000,0x880000,0xC80000,0x1880000,0x28000000,0x28000000,0x700000,0x980000,0x1BE80000,0x28000000,
+0xAC0000,0x300274,0x562400F3,0x322400F4,0x282400F3,0x4C1C0092,0x341C004F,0x2A1C0067,0x2C1C0092,0x2818004E,0x22180092,0x4A1000F4,0x38100033,0x2A140051,0x300C004A,0x28100002,0x2210004D,0x280C00F4,0x24080053,0x20080069,0x1C0C00F5,0x2440274,0x3A0000F5,0x281000F4,0x2E0000AA,0x28000049,0x22040090,0x2800011F,0x2400005D,0x20000069,0x1C0000FD,0x8C0274,
+0x2000015B,0x1C000120,0x1A000181,0x16000278,0xA4100004,0xF82000C2,0xFC28011F,0x56100002,0x3E100002,0x30100002,0x28100006,0x260C0006,0x90000009,0x54040000,0x2A080035,0x20000069,0x640274,0x3C00F3,0x4A300032,0x30300032,0x28300032,0x40280049,0x32240002,0x28280005,0x2A240049,0x2624000E,0x22240049,0x5800F3,0x38100032,0x28200032,0x300C0049,0x28100001,
+0x22140049,0xB000F3,0x2600003E,0x20000059,0x1C0000F4,0x5800F3,0x38100032,0x28200032,0x300C0049,0x28100001,0x22140049,0xB000F3,0x2600003E,0x20000059,0x1C0000F4,0xB000F3,0x2600003E,0x20000059,0x1C0000F4,0x1C0000F4,0xA4100003,0xFC280049,0xF030003B,0x56100001,0x3E100001,0x30100001,0x28180001,0x28080004,0x90000005,0x54040000,0x2A040033,0x20000059,
+0x7C00F3,0x2400F3,0x2400F3,0x2400F3,0x2400F3,0x3A1C004A,0x3A1C004A,0x3A1C004A,0x2418004A,0x2418004A,0x1C18004A,0x38100033,0x38100033,0x38100033,0x26100002,0x26100002,0x1E10000E,0x200C0033,0x200C0033,0x1C0C0005,0x160C0035,0x3400F3,0x3400F3,0x3400F3,0x28000049,0x28000049,0x1C08004A,0x22000042,0x22000042,0x1A000009,0x16000035,0x6800F3,
+0x6800F3,0x16000074,0x16000074,0x120000F4,0xA0100003,0xF61C004A,0x2400F3,0x56100001,0x3A100002,0x2E100002,0x2C100003,0x240C0001,0x84000005,0x54040000,0x260C0033,0x1A000009,0x4C00F3,0x300032,0x300032,0x300032,0x300032,0x2E280001,0x2E280001,0x2E280001,0x20280001,0x20280001,0x1C240001,0x2440032,0x2440032,0x2440032,0x24140001,0x24140001,
+0x1C1C0000,0x8C0032,0x8C0032,0x1C000000,0x16000034,0x2440032,0x2440032,0x2440032,0x24140001,0x24140001,0x1C1C0000,0x8C0032,0x8C0032,0x1C000000,0x16000034,0x8C0032,0x8C0032,0x1C000000,0x16000034,0x16000034,0x82180000,0x9C280001,0x300032,0x56100000,0x34180001,0x2C140000,0x26180001,0x240C0000,0x84040001,0x4E080000,0x640032,0x1C000000,
+0x640032,0x44004A,0x3E3C0001,0x2E380001,0x28380001,0x680048,0x32240001,0x282C0001,0xD00048,0x28080000,0x22000048,0x680048,0x32240001,0x282C0001,0xD00048,0x28080000,0x22000048,0xD00048,0x28080000,0x22000048,0x22000048,0x680048,0x32240001,0x282C0001,0xD00048,0x28080000,0x22000048,0xD00048,0x28080000,0x22000048,0x22000048,0xD00048,
+0x28080000,0x22000048,0x22000048,0x22000048,0xB8080000,0xC480048,0xC63C0001,0x5A0C0000,0x3E0C0001,0x32080000,0x28180000,0x28000001,0x94000002,0x54040000,0x2A1C0000,0x22000048,0x940048,0x18004A,0x18004A,0x18004A,0x18004A,0x18004A,0x18004A,0x18004A,0x18004A,0x18004A,0x18004A,0x28100001,0x28100001,0x28100001,0x28100001,0x28100001,
+0x28100001,0x180C0001,0x180C0001,0x180C0001,0x120C0001,0x2240048,0x2240048,0x2240048,0x2240048,0x2240048,0x2240048,0x18000005,0x18000005,0x18000005,0x12000001,0x4C0048,0x4C0048,0x4C0048,0x10000014,0xC000048,0xB0100001,0x18004A,0x18004A,0x52100001,0x3C100001,0x30100001,0x30100001,0x22100001,0x84000001,0x54040000,0x1C0C0001,0x18000005,
+0x340048,};
+static const uint32_t g_etc1_to_bc7_m6_table36[] = {
+0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x5C0000,
+0x5C0000,0x5C0000,0x5C0000,0xE000001,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x8200000,0x8200000,0x8200000,0x300000,0x400000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,
+0x2500000,0xA40000,0xA40000,0xA40000,0x1A000001,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,0xA40000,0xA40000,0xA40000,0x1A000001,0xA40000,0xA40000,0xA40000,0x1A000001,0x1A000001,0x3C0000,0x380000,0x380000,0x400000,0x2440000,0x4C0000,0x4C0000,0x5C0000,0x400000,0x2440000,0x740000,0xA40000,
+0x740000,0x4C0000,0x4C0000,0x4C0000,0x4C0000,0x700000,0x700000,0x700000,0xE40000,0xE40000,0x24000001,0x700000,0x700000,0x700000,0xE40000,0xE40000,0x24000001,0xE40000,0xE40000,0x24000001,0x24000001,0x700000,0x700000,0x700000,0xE40000,0xE40000,0x24000001,0xE40000,0xE40000,0x24000001,0x24000001,0xE40000,
+0xE40000,0x24000001,0x24000001,0x24000001,0x580000,0x500000,0x4C0000,0x680000,0x800000,0xA00000,0xB80000,0x1180000,0x600000,0x700000,0xA00000,0x24000001,0xA00000,0x640000,0x940000,0x12C0000,0x30000001,0x940000,0x12C0000,0x30000001,0x12C0000,0x30000001,0x30000001,0x940000,0x12C0000,0x30000001,0x12C0000,0x30000001,
+0x30000001,0x12C0000,0x30000001,0x30000001,0x30000001,0x940000,0x12C0000,0x30000001,0x12C0000,0x30000001,0x30000001,0x12C0000,0x30000001,0x30000001,0x30000001,0x12C0000,0x30000001,0x30000001,0x30000001,0x30000001,0x7C0000,0xC680000,0xC680000,0xA80000,0xF40000,0x1E00000,0x30000001,0x30000001,0x880000,0xBC0000,0x25DC0000,0x30000001,
+0xD40000,0x400278,0x5E3800F4,0x3C3800F4,0x303800F5,0x582C0090,0x402C004D,0x34300069,0x362C0090,0x302C004D,0x2A2C0092,0x542000F3,0x42200032,0x34280053,0x38200049,0x30200002,0x2C20004E,0x302000F4,0x2E1C0051,0x2A1C0067,0x262000F3,0x600274,0x460C00F3,0x302000F4,0x3E040092,0x3210004A,0x2A180092,0x360400FD,0x30000033,0x2A00004F,0x260800F4,0xC40274,
+0x2C000121,0x260000E2,0x2400014C,0x20000274,0xB4200005,0xF23400D0,0xF63C012C,0x62200000,0x48200001,0x38200002,0x32240006,0x30200006,0xAC080002,0x5A180002,0x321C0035,0x2A00004F,0x8C0274,0x4C00F4,0x52440034,0x3A400034,0x30400035,0x4C380048,0x3A380001,0x32380005,0x3238004A,0x3034000E,0x2A38004A,0x7400F3,0x40240032,0x32300033,0x38200049,0x30200002,
+0x2A28004A,0xE800F3,0x30000033,0x2A00004B,0x260000F3,0x7400F3,0x40240032,0x32300033,0x38200049,0x30200002,0x2A28004A,0xE800F3,0x30000033,0x2A00004B,0x260000F3,0xE800F3,0x30000033,0x2A00004B,0x260000F3,0x260000F3,0xA8240003,0xF63C004C,0xFA440038,0x62200000,0x48200001,0x38200002,0x32280001,0x30180003,0xAC080001,0x5A180001,0x34140032,0x2A00004B,
+0xA400F3,0x3800F4,0x3800F4,0x3800F4,0x3800F4,0x462C0048,0x462C0048,0x462C0048,0x2C2C0049,0x2C2C0049,0x242C0049,0x42200032,0x42200032,0x42200032,0x30200001,0x30200001,0x2624000E,0x28200032,0x28200032,0x24200005,0x20200032,0x5000F3,0x5000F3,0x5000F3,0x32100049,0x32100049,0x241C0049,0x30000032,0x30000032,0x240C0002,0x20100032,0xA000F3,
+0xA000F3,0x22000059,0x1E000053,0x1A0000F3,0xA8200004,0xFE2C0049,0x3800F4,0x62200000,0x44200001,0x38200001,0x34200004,0x2C200001,0xA20C0000,0x5A180001,0x301C0032,0x240C0002,0x7000F3,0x400034,0x400034,0x400034,0x400034,0x38380000,0x38380000,0x38380000,0x2A380000,0x2A380000,0x24380001,0x600032,0x600032,0x600032,0x2C280001,0x2C280001,
+0x24300001,0xC40032,0xC40032,0x24140001,0x20000032,0x600032,0x600032,0x600032,0x2C280001,0x2C280001,0x24300001,0xC40032,0xC40032,0x24140001,0x20000032,0xC40032,0xC40032,0x24140001,0x20000032,0x20000032,0x90280000,0xB4380000,0x400034,0x62200000,0x42240000,0x36240000,0x32280000,0x2C200001,0xA20C0000,0x5A180000,0x8C0032,0x24140001,
+0x8C0032,0x580048,0x4A4C0000,0x364C0001,0x304C0001,0x2800048,0x3A380001,0x30400001,0x1080048,0x301C0001,0x2A00004A,0x2800048,0x3A380001,0x30400001,0x1080048,0x301C0001,0x2A00004A,0x1080048,0x301C0001,0x2A00004A,0x2A00004A,0x2800048,0x3A380001,0x30400001,0x1080048,0x301C0001,0x2A00004A,0x1080048,0x301C0001,0x2A00004A,0x2A00004A,0x1080048,
+0x301C0001,0x2A00004A,0x2A00004A,0x2A00004A,0xC4180000,0x65C0048,0xDE4C0000,0x62200000,0x46200001,0x3A1C0000,0x302C0001,0x300C0001,0xB4040000,0x5E140000,0x32300001,0x2A00004A,0xB80048,0x2C0048,0x2C0048,0x2C0048,0x2C0048,0x2C0048,0x2C0048,0x2C0048,0x2C0048,0x2C0048,0x2C0048,0x34200000,0x34200000,0x34200000,0x34200000,0x34200000,
+0x34200000,0x20200001,0x20200001,0x20200001,0x1A200001,0x400048,0x400048,0x400048,0x400048,0x400048,0x400048,0x240C0001,0x240C0001,0x240C0001,0x1A140001,0x800048,0x800048,0x800048,0x1A000005,0x1400004A,0xC8200000,0x2C0048,0x2C0048,0x62200000,0x48200000,0x3C200000,0x3C200000,0x2C200000,0x9E0C0000,0x62140000,0x281C0000,0x240C0001,
+0x5C0048,};
+static const uint32_t g_etc1_to_bc7_m6_table37[] = {
+0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x8C0000,
+0x8C0000,0x8C0000,0x8C0000,0x16000001,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x340000,0x340000,0x340000,0x2440000,0x640000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x2680000,0x2680000,0x2680000,0x2680000,0x2680000,
+0x2680000,0xD80000,0xD80000,0xD80000,0x22000001,0x2680000,0x2680000,0x2680000,0x2680000,0x2680000,0x2680000,0xD80000,0xD80000,0xD80000,0x22000001,0xD80000,0xD80000,0xD80000,0x22000001,0x22000001,0x4C0000,0x480000,0x480000,0x540000,0x2580000,0x600000,0x600000,0x780000,0x540000,0x2580000,0x980000,0xD80000,
+0x980000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x880000,0x880000,0x880000,0x1140000,0x1140000,0x2C000001,0x880000,0x880000,0x880000,0x1140000,0x1140000,0x2C000001,0x1140000,0x1140000,0x2C000001,0x2C000001,0x880000,0x880000,0x880000,0x1140000,0x1140000,0x2C000001,0x1140000,0x1140000,0x2C000001,0x2C000001,0x1140000,
+0x1140000,0x2C000001,0x2C000001,0x2C000001,0x6680000,0x8600000,0x5C0000,0x7C0000,0x980000,0xC00000,0xE00000,0x1540000,0x740000,0x880000,0xC00000,0x2C000001,0xC00000,0x740000,0xAC0000,0x15C0000,0x38000001,0xAC0000,0x15C0000,0x38000001,0x15C0000,0x38000001,0x38000001,0xAC0000,0x15C0000,0x38000001,0x15C0000,0x38000001,
+0x38000001,0x15C0000,0x38000001,0x38000001,0x38000001,0xAC0000,0x15C0000,0x38000001,0x15C0000,0x38000001,0x38000001,0x15C0000,0x38000001,0x38000001,0x38000001,0x15C0000,0x38000001,0x38000001,0x38000001,0x38000001,0x900000,0x7C0000,0x7C0000,0x2C00000,0x11C0000,0x9F00000,0x38000001,0x38000001,0x9C0000,0xD80000,0x2DEC0000,0x38000001,
+0xF40000,0x500278,0x664800F4,0x444800F4,0x384800F5,0x603C0090,0x483C004D,0x3C400069,0x3E3C0090,0x383C004D,0x323C0092,0x5C3000F3,0x4A300032,0x3C380053,0x40300049,0x38300002,0x3430004E,0x383000F4,0x362C0051,0x322C0067,0x2E3000F3,0x780274,0x4E1C00F3,0x383000F4,0x46140092,0x3A20004A,0x32280092,0x440400F3,0x38100033,0x3210004F,0x2E1800F4,0xF40274,
+0x36000104,0x320000B2,0x2C00011F,0x28000274,0xBC300005,0xFA4400D0,0xFE4C012C,0x6A300000,0x50300001,0x40300002,0x3A340006,0x38300006,0xB4180002,0x62280002,0x3A2C0035,0x3210004F,0xAC0274,0x5C00F4,0x5A540034,0x42500034,0x38500035,0x54480048,0x42480001,0x3A480005,0x3A48004A,0x3844000E,0x3248004A,0x8C00F3,0x48340032,0x3A400033,0x40300049,0x38300002,
+0x3238004A,0x11800F3,0x38100033,0x3208004A,0x2E0000F3,0x8C00F3,0x48340032,0x3A400033,0x40300049,0x38300002,0x3238004A,0x11800F3,0x38100033,0x3208004A,0x2E0000F3,0x11800F3,0x38100033,0x3208004A,0x2E0000F3,0x2E0000F3,0xB0340003,0xFE4C004C,0xF254003D,0x6A300000,0x50300001,0x40300002,0x3A380001,0x38280003,0xB4180001,0x62280001,0x3C240032,0x3208004A,
+0xC800F3,0x4800F4,0x4800F4,0x4800F4,0x4800F4,0x4E3C0048,0x4E3C0048,0x4E3C0048,0x343C0049,0x343C0049,0x2C3C0049,0x4A300032,0x4A300032,0x4A300032,0x38300001,0x38300001,0x2E34000E,0x30300032,0x30300032,0x2C300005,0x28300032,0x6800F3,0x6800F3,0x6800F3,0x3A200049,0x3A200049,0x2C2C0049,0x38100032,0x38100032,0x2C1C0002,0x28200032,0xD000F3,
+0xD000F3,0x2C000049,0x2600003E,0x220000F3,0xB0300004,0xF63C004C,0x4800F4,0x6A300000,0x4C300001,0x40300001,0x3C300004,0x34300001,0xAA1C0000,0x62280001,0x382C0032,0x2C1C0002,0x9400F3,0x500034,0x500034,0x500034,0x500034,0x40480000,0x40480000,0x40480000,0x32480000,0x32480000,0x2C480001,0x780032,0x780032,0x780032,0x34380001,0x34380001,
+0x2C400001,0xF40032,0xF40032,0x2C240001,0x28000032,0x780032,0x780032,0x780032,0x34380001,0x34380001,0x2C400001,0xF40032,0xF40032,0x2C240001,0x28000032,0xF40032,0xF40032,0x2C240001,0x28000032,0x28000032,0x98380000,0xBC480000,0x500034,0x6A300000,0x4A340000,0x3E340000,0x3A380000,0x34300001,0xAA1C0000,0x62280000,0xAC0032,0x2C240001,
+0xAC0032,0x680048,0x525C0000,0x3E5C0001,0x385C0001,0x2980048,0x42480001,0x38500001,0x1380048,0x382C0001,0x3200004A,0x2980048,0x42480001,0x38500001,0x1380048,0x382C0001,0x3200004A,0x1380048,0x382C0001,0x3200004A,0x3200004A,0x2980048,0x42480001,0x38500001,0x1380048,0x382C0001,0x3200004A,0x1380048,0x382C0001,0x3200004A,0x3200004A,0x1380048,
+0x382C0001,0x3200004A,0x3200004A,0x3200004A,0xCC280000,0xE6C0048,0xE65C0000,0x6A300000,0x4E300001,0x422C0000,0x383C0001,0x381C0001,0xBC140000,0x66240000,0x3A400001,0x3200004A,0xDC0048,0x3C0048,0x3C0048,0x3C0048,0x3C0048,0x3C0048,0x3C0048,0x3C0048,0x3C0048,0x3C0048,0x3C0048,0x3C300000,0x3C300000,0x3C300000,0x3C300000,0x3C300000,
+0x3C300000,0x28300001,0x28300001,0x28300001,0x22300001,0x580048,0x580048,0x580048,0x580048,0x580048,0x580048,0x2C1C0001,0x2C1C0001,0x2C1C0001,0x22240001,0xB00048,0xB00048,0xB00048,0x22000001,0x1C00004A,0xD0300000,0x3C0048,0x3C0048,0x6A300000,0x50300000,0x44300000,0x44300000,0x34300000,0xA61C0000,0x6A240000,0x302C0000,0x2C1C0001,
+0x7C0048,};
+static const uint32_t g_etc1_to_bc7_m6_table38[] = {
+0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0xBC0000,
+0xBC0000,0xBC0000,0xBC0000,0x1E000001,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x440000,0x440000,0x440000,0x25C0000,0x880000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x2800000,0x2800000,0x2800000,0x2800000,0x2800000,
+0x2800000,0x1080000,0x1080000,0x1080000,0x2A000001,0x2800000,0x2800000,0x2800000,0x2800000,0x2800000,0x2800000,0x1080000,0x1080000,0x1080000,0x2A000001,0x1080000,0x1080000,0x1080000,0x2A000001,0x2A000001,0x65C0000,0x580000,0x580000,0x4640000,0x26C0000,0x780000,0x780000,0x940000,0x4640000,0x26C0000,0xB80000,0x1080000,
+0xB80000,0x6C0000,0x6C0000,0x6C0000,0x6C0000,0xA00000,0xA00000,0xA00000,0x1440000,0x1440000,0x34000001,0xA00000,0xA00000,0xA00000,0x1440000,0x1440000,0x34000001,0x1440000,0x1440000,0x34000001,0x34000001,0xA00000,0xA00000,0xA00000,0x1440000,0x1440000,0x34000001,0x1440000,0x1440000,0x34000001,0x34000001,0x1440000,
+0x1440000,0x34000001,0x34000001,0x34000001,0x27C0000,0x740000,0x6C0000,0x2900000,0xB40000,0xE40000,0x1080000,0x1900000,0x880000,0xA00000,0xE40000,0x34000001,0xE40000,0x840000,0xC40000,0x18C0000,0x40000001,0xC40000,0x18C0000,0x40000001,0x18C0000,0x40000001,0x40000001,0xC40000,0x18C0000,0x40000001,0x18C0000,0x40000001,
+0x40000001,0x18C0000,0x40000001,0x40000001,0x40000001,0xC40000,0x18C0000,0x40000001,0x18C0000,0x40000001,0x40000001,0x18C0000,0x40000001,0x40000001,0x40000001,0x18C0000,0x40000001,0x40000001,0x40000001,0x40000001,0xA40000,0x8C0000,0x8C0000,0xDC0000,0x1400000,0x13F00000,0x40000001,0x40000001,0xB40000,0xF80000,0x35FC0000,0x40000001,
+0x1180000,0x600278,0x6E5800F4,0x4C5800F4,0x405800F5,0x684C0090,0x504C004D,0x44500069,0x464C0090,0x404C004D,0x3A4C0092,0x644000F3,0x52400032,0x44480053,0x48400049,0x40400002,0x3C40004E,0x404000F4,0x3E3C0051,0x3A3C0067,0x364000F3,0x900274,0x562C00F3,0x404000F4,0x4E240092,0x4230004A,0x3A380092,0x4C1400F3,0x40200033,0x3A20004F,0x362800F4,0x1240274,
+0x400000F5,0x3A00009A,0x3400010B,0x30000274,0xC4400005,0xF25400E2,0xF65C0139,0x72400000,0x58400001,0x48400002,0x42440006,0x40400006,0xBC280002,0x6A380002,0x423C0035,0x3A20004F,0xD00274,0x6C00F4,0x62640034,0x4A600034,0x40600035,0x5C580048,0x4A580001,0x42580005,0x4258004A,0x4054000E,0x3A58004A,0xA400F3,0x50440032,0x42500033,0x48400049,0x40400002,
+0x3A48004A,0x14C00F3,0x40200033,0x3A18004A,0x360000F3,0xA400F3,0x50440032,0x42500033,0x48400049,0x40400002,0x3A48004A,0x14C00F3,0x40200033,0x3A18004A,0x360000F3,0x14C00F3,0x40200033,0x3A18004A,0x360000F3,0x360000F3,0xB8440003,0xF65C004E,0xFA64003D,0x72400000,0x58400001,0x48400002,0x42480001,0x40380003,0xBC280001,0x6A380001,0x44340032,0x3A18004A,
+0xE800F3,0x5800F4,0x5800F4,0x5800F4,0x5800F4,0x564C0048,0x564C0048,0x564C0048,0x3C4C0049,0x3C4C0049,0x344C0049,0x52400032,0x52400032,0x52400032,0x40400001,0x40400001,0x3644000E,0x38400032,0x38400032,0x34400005,0x30400032,0x8000F3,0x8000F3,0x8000F3,0x42300049,0x42300049,0x343C0049,0x40200032,0x40200032,0x342C0002,0x30300032,0x10000F3,
+0x10000F3,0x340C0049,0x30000033,0x2A0000F3,0xB8400004,0xFE4C004C,0x5800F4,0x72400000,0x54400001,0x48400001,0x44400004,0x3C400001,0xB22C0000,0x6A380001,0x403C0032,0x342C0002,0xB400F3,0x600034,0x600034,0x600034,0x600034,0x48580000,0x48580000,0x48580000,0x3A580000,0x3A580000,0x34580001,0x900032,0x900032,0x900032,0x3C480001,0x3C480001,
+0x34500001,0x1240032,0x1240032,0x34340001,0x30000032,0x900032,0x900032,0x900032,0x3C480001,0x3C480001,0x34500001,0x1240032,0x1240032,0x34340001,0x30000032,0x1240032,0x1240032,0x34340001,0x30000032,0x30000032,0xA0480000,0xC4580000,0x600034,0x72400000,0x52440000,0x46440000,0x42480000,0x3C400001,0xB22C0000,0x6A380000,0xD00032,0x34340001,
+0xD00032,0x780048,0x5A6C0000,0x466C0001,0x406C0001,0x2B00048,0x4A580001,0x40600001,0x1680048,0x403C0001,0x3A00004A,0x2B00048,0x4A580001,0x40600001,0x1680048,0x403C0001,0x3A00004A,0x1680048,0x403C0001,0x3A00004A,0x3A00004A,0x2B00048,0x4A580001,0x40600001,0x1680048,0x403C0001,0x3A00004A,0x1680048,0x403C0001,0x3A00004A,0x3A00004A,0x1680048,
+0x403C0001,0x3A00004A,0x3A00004A,0x3A00004A,0xD4380000,0x800048,0xEE6C0000,0x72400000,0x56400001,0x4A3C0000,0x404C0001,0x402C0001,0xC4240000,0x6E340000,0x42500001,0x3A00004A,0xFC0048,0x4C0048,0x4C0048,0x4C0048,0x4C0048,0x4C0048,0x4C0048,0x4C0048,0x4C0048,0x4C0048,0x4C0048,0x44400000,0x44400000,0x44400000,0x44400000,0x44400000,
+0x44400000,0x30400001,0x30400001,0x30400001,0x2A400001,0x700048,0x700048,0x700048,0x700048,0x700048,0x700048,0x342C0001,0x342C0001,0x342C0001,0x2A340001,0xE40048,0xE40048,0xE40048,0x2A100001,0x2400004A,0xD8400000,0x4C0048,0x4C0048,0x72400000,0x58400000,0x4C400000,0x4C400000,0x3C400000,0xAE2C0000,0x72340000,0x383C0000,0x342C0001,
+0xA00048,};
+static const uint32_t g_etc1_to_bc7_m6_table39[] = {
+0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0xF00000,
+0xF00000,0xF00000,0xF00000,0x26000001,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x2540000,0x2540000,0x2540000,0x2740000,0xA80000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,
+0x2980000,0x1380000,0x1380000,0x1380000,0x32000001,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,0x1380000,0x1380000,0x1380000,0x32000001,0x1380000,0x1380000,0x1380000,0x32000001,0x32000001,0xE6C0000,0x680000,0x680000,0x780000,0x2800000,0x8C0000,0x8C0000,0x2AC0000,0x780000,0x2800000,0xDC0000,0x1380000,
+0xDC0000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0xB80000,0xB80000,0xB80000,0x1740000,0x1740000,0x3C000001,0xB80000,0xB80000,0xB80000,0x1740000,0x1740000,0x3C000001,0x1740000,0x1740000,0x3C000001,0x3C000001,0xB80000,0xB80000,0xB80000,0x1740000,0x1740000,0x3C000001,0x1740000,0x1740000,0x3C000001,0x3C000001,0x1740000,
+0x1740000,0x3C000001,0x3C000001,0x3C000001,0x900000,0x840000,0x7C0000,0xA80000,0xD00000,0x1080000,0x12C0000,0x1CC0000,0x9C0000,0xB80000,0x1080000,0x3C000001,0x1080000,0x940000,0xDC0000,0x1BC0000,0x48000001,0xDC0000,0x1BC0000,0x48000001,0x1BC0000,0x48000001,0x48000001,0xDC0000,0x1BC0000,0x48000001,0x1BC0000,0x48000001,
+0x48000001,0x1BC0000,0x48000001,0x48000001,0x48000001,0xDC0000,0x1BC0000,0x48000001,0x1BC0000,0x48000001,0x48000001,0x1BC0000,0x48000001,0x48000001,0x48000001,0x1BC0000,0x48000001,0x48000001,0x48000001,0x48000001,0xB80000,0x69C0000,0x69C0000,0xF80000,0x1680000,0x1DF40000,0x48000001,0x48000001,0xC80000,0x1140000,0x3FD00000,0x48000001,
+0x1380000,0x700278,0x766800F4,0x546800F4,0x486800F5,0x705C0090,0x585C004D,0x4C600069,0x4E5C0090,0x485C004D,0x425C0092,0x6C5000F3,0x5A500032,0x4C580053,0x50500049,0x48500002,0x4450004E,0x485000F4,0x464C0051,0x424C0067,0x3E5000F3,0xA80274,0x5E3C00F3,0x485000F4,0x56340092,0x4A40004A,0x42480092,0x542400F3,0x48300033,0x4230004F,0x3E3800F4,0x1580274,
+0x480C00F4,0x42040092,0x3E0000F7,0x38000274,0xCC500005,0xFA6400E2,0xFE6C0139,0x7A500000,0x60500001,0x50500002,0x4A540006,0x48500006,0xC4380002,0x72480002,0x4A4C0035,0x4230004F,0xF00274,0x7C00F4,0x6A740034,0x52700034,0x48700035,0x64680048,0x52680001,0x4A680005,0x4A68004A,0x4864000E,0x4268004A,0xBC00F3,0x58540032,0x4A600033,0x50500049,0x48500002,
+0x4258004A,0x17C00F3,0x48300033,0x4228004A,0x3E0000F3,0xBC00F3,0x58540032,0x4A600033,0x50500049,0x48500002,0x4258004A,0x17C00F3,0x48300033,0x4228004A,0x3E0000F3,0x17C00F3,0x48300033,0x4228004A,0x3E0000F3,0x3E0000F3,0xC0540003,0xFE6C004E,0xF2740044,0x7A500000,0x60500001,0x50500002,0x4A580001,0x48480003,0xC4380001,0x72480001,0x4C440032,0x4228004A,
+0x10C00F3,0x6800F4,0x6800F4,0x6800F4,0x6800F4,0x5E5C0048,0x5E5C0048,0x5E5C0048,0x445C0049,0x445C0049,0x3C5C0049,0x5A500032,0x5A500032,0x5A500032,0x48500001,0x48500001,0x3E54000E,0x40500032,0x40500032,0x3C500005,0x38500032,0x9800F3,0x9800F3,0x9800F3,0x4A400049,0x4A400049,0x3C4C0049,0x48300032,0x48300032,0x3C3C0002,0x38400032,0x13000F3,
+0x13000F3,0x3C1C0049,0x38080032,0x320000F3,0xC0500004,0xF65C0051,0x6800F4,0x7A500000,0x5C500001,0x50500001,0x4C500004,0x44500001,0xBA3C0000,0x72480001,0x484C0032,0x3C3C0002,0xD800F3,0x700034,0x700034,0x700034,0x700034,0x50680000,0x50680000,0x50680000,0x42680000,0x42680000,0x3C680001,0xA80032,0xA80032,0xA80032,0x44580001,0x44580001,
+0x3C600001,0x1580032,0x1580032,0x3C440001,0x38000032,0xA80032,0xA80032,0xA80032,0x44580001,0x44580001,0x3C600001,0x1580032,0x1580032,0x3C440001,0x38000032,0x1580032,0x1580032,0x3C440001,0x38000032,0x38000032,0xA8580000,0xCC680000,0x700034,0x7A500000,0x5A540000,0x4E540000,0x4A580000,0x44500001,0xBA3C0000,0x72480000,0xF00032,0x3C440001,
+0xF00032,0x880048,0x627C0000,0x4E7C0001,0x487C0001,0xC80048,0x52680001,0x48700001,0x1980048,0x484C0001,0x4200004A,0xC80048,0x52680001,0x48700001,0x1980048,0x484C0001,0x4200004A,0x1980048,0x484C0001,0x4200004A,0x4200004A,0xC80048,0x52680001,0x48700001,0x1980048,0x484C0001,0x4200004A,0x1980048,0x484C0001,0x4200004A,0x4200004A,0x1980048,
+0x484C0001,0x4200004A,0x4200004A,0x4200004A,0xDC480000,0x900048,0xF67C0000,0x7A500000,0x5E500001,0x524C0000,0x485C0001,0x483C0001,0xCC340000,0x76440000,0x4A600001,0x4200004A,0x1200048,0x5C0048,0x5C0048,0x5C0048,0x5C0048,0x5C0048,0x5C0048,0x5C0048,0x5C0048,0x5C0048,0x5C0048,0x4C500000,0x4C500000,0x4C500000,0x4C500000,0x4C500000,
+0x4C500000,0x38500001,0x38500001,0x38500001,0x32500001,0x880048,0x880048,0x880048,0x880048,0x880048,0x880048,0x3C3C0001,0x3C3C0001,0x3C3C0001,0x32440001,0x1140048,0x1140048,0x1140048,0x32200001,0x2C00004A,0xE0500000,0x5C0048,0x5C0048,0x7A500000,0x60500000,0x54500000,0x54500000,0x44500000,0xB63C0000,0x7A440000,0x404C0000,0x3C3C0001,
+0xC00048,};
+static const uint32_t g_etc1_to_bc7_m6_table40[] = {
+0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x1240000,
+0x1240000,0x1240000,0x1240000,0x30000000,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x680000,0x680000,0x680000,0x900000,0xD00000,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,
+0xB40000,0x1700000,0x1700000,0x1700000,0x3C000000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0x1700000,0x1700000,0x1700000,0x3C000000,0x1700000,0x1700000,0x1700000,0x3C000000,0x3C000000,0x8800000,0x780001,0x780001,0x28C0000,0x980000,0x2A40000,0x2A40000,0xCC0000,0x28C0000,0x980000,0x1000000,0x1700000,
+0x1000000,0x8C0001,0x8C0001,0x8C0001,0x8C0001,0x2D00000,0x2D00000,0x2D00000,0x1AC0000,0x1AC0000,0x46000000,0x2D00000,0x2D00000,0x2D00000,0x1AC0000,0x1AC0000,0x46000000,0x1AC0000,0x1AC0000,0x46000000,0x46000000,0x2D00000,0x2D00000,0x2D00000,0x1AC0000,0x1AC0000,0x46000000,0x1AC0000,0x1AC0000,0x46000000,0x46000000,0x1AC0000,
+0x1AC0000,0x46000000,0x46000000,0x46000000,0xA40000,0x980000,0x8C0001,0xC00000,0x2EC0000,0x12C0000,0x15C0000,0x5F80000,0x2B00000,0x2D00000,0x12C0000,0x46000000,0x12C0000,0xA40001,0x2F40000,0x1F40000,0x52000000,0x2F40000,0x1F40000,0x52000000,0x1F40000,0x52000000,0x52000000,0x2F40000,0x1F40000,0x52000000,0x1F40000,0x52000000,
+0x52000000,0x1F40000,0x52000000,0x52000000,0x52000000,0x2F40000,0x1F40000,0x52000000,0x1F40000,0x52000000,0x52000000,0x1F40000,0x52000000,0x52000000,0x52000000,0x1F40000,0x52000000,0x52000000,0x52000000,0x52000000,0xD00000,0xB00000,0xB00000,0x3140000,0x1940000,0x27FC0000,0x52000000,0x52000000,0xE00000,0x1380000,0x49C40000,0x52000000,
+0x1600000,0x840274,0x807800F3,0x5C7800F4,0x527800F3,0x76700092,0x5E70004F,0x54700067,0x56700092,0x526C004E,0x4C6C0092,0x746400F4,0x62640033,0x54680051,0x5A60004A,0x52640002,0x4C64004D,0x526000F4,0x4E5C0053,0x4A5C0069,0x466000F5,0xC40274,0x684C00F3,0x526400F4,0x5E480092,0x52540049,0x4C580090,0x5C3800F3,0x52400032,0x4C40004D,0x464C00F4,0x18C0274,
+0x521800F3,0x4C140090,0x460800F4,0x40000278,0xCE640004,0xF47800F4,0xF67C014C,0x80640002,0x68640002,0x5A640002,0x52640006,0x50600006,0xCE4C0002,0x7E580000,0x545C0035,0x4C40004D,0x1180274,0x9000F3,0x74840032,0x5A840032,0x52840032,0x6A7C0049,0x5C780002,0x527C0005,0x54780049,0x5078000E,0x4C780049,0xD400F3,0x62640032,0x52740032,0x5A600049,0x52640001,
+0x4C680049,0x1B000F3,0x523C0032,0x4C380048,0x460000F4,0xD400F3,0x62640032,0x52740032,0x5A600049,0x52640001,0x4C680049,0x1B000F3,0x523C0032,0x4C380048,0x460000F4,0x1B000F3,0x523C0032,0x4C380048,0x460000F4,0x460000F4,0xCE640003,0xF8800053,0xFC880043,0x80640001,0x68640001,0x5A640001,0x526C0001,0x525C0004,0xD4480001,0x7E580000,0x54580033,0x4C380048,
+0x13000F3,0x7800F3,0x7800F3,0x7800F3,0x7800F3,0x6470004A,0x6470004A,0x6470004A,0x4E6C004A,0x4E6C004A,0x466C004A,0x62640033,0x62640033,0x62640033,0x50640002,0x50640002,0x4864000E,0x4A600033,0x4A600033,0x46600005,0x40600035,0x2B000F3,0x2B000F3,0x2B000F3,0x52540049,0x52540049,0x465C004A,0x50440032,0x50440032,0x464C0001,0x42500034,0x16800F3,
+0x16800F3,0x462C0048,0x40200034,0x3C0000F4,0xCA640003,0xF0700053,0x7800F3,0x80640001,0x64640002,0x58640002,0x56640003,0x4E600001,0xBE500000,0x7E580000,0x50600033,0x464C0001,0xFC00F3,0x840032,0x840032,0x840032,0x840032,0x587C0001,0x587C0001,0x587C0001,0x4A7C0001,0x4A7C0001,0x46780001,0xC40032,0xC40032,0xC40032,0x4E680001,0x4E680001,
+0x46700000,0x18C0032,0x18C0032,0x46500000,0x40000034,0xC40032,0xC40032,0xC40032,0x4E680001,0x4E680001,0x46700000,0x18C0032,0x18C0032,0x46500000,0x40000034,0x18C0032,0x18C0032,0x46500000,0x40000034,0x40000034,0xAC6C0000,0xC67C0001,0x840032,0x80640000,0x5E6C0001,0x56680000,0x506C0001,0x4E600000,0xBE500000,0x785C0000,0x1180032,0x46500000,
+0x1180032,0x98004A,0x68900001,0x588C0001,0x528C0001,0xE40048,0x5C780001,0x52800001,0x1D00048,0x525C0000,0x4C000048,0xE40048,0x5C780001,0x52800001,0x1D00048,0x525C0000,0x4C000048,0x1D00048,0x525C0000,0x4C000048,0x4C000048,0xE40048,0x5C780001,0x52800001,0x1D00048,0x525C0000,0x4C000048,0x1D00048,0x525C0000,0x4C000048,0x4C000048,0x1D00048,
+0x525C0000,0x4C000048,0x4C000048,0x4C000048,0xE25C0000,0xA40048,0xF0900001,0x84600000,0x68600001,0x5C5C0000,0x526C0000,0x52480000,0xD8440000,0x7E580000,0x54700000,0x4C000048,0x1480048,0x6C004A,0x6C004A,0x6C004A,0x6C004A,0x6C004A,0x6C004A,0x6C004A,0x6C004A,0x6C004A,0x6C004A,0x52640001,0x52640001,0x52640001,0x52640001,0x52640001,
+0x52640001,0x42600001,0x42600001,0x42600001,0x3C600001,0xA40048,0xA40048,0xA40048,0xA40048,0xA40048,0xA40048,0x464C0001,0x464C0001,0x464C0001,0x3C540001,0x14C0048,0x14C0048,0x14C0048,0x3C300000,0x36000048,0xDA640001,0x6C004A,0x6C004A,0x7C640001,0x66640001,0x5A640001,0x5A640001,0x4C640001,0xBA500000,0x7E580000,0x46600001,0x464C0001,
+0xE80048,};
+static const uint32_t g_etc1_to_bc7_m6_table41[] = {
+0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0x1580000,
+0x1580000,0x1580000,0x1580000,0x38000000,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x4780000,0x4780000,0x4780000,0xA80000,0xF00000,0x880001,0x880001,0x880001,0x880001,0x880001,0x880001,0x880001,0x880001,0x880001,0x880001,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,
+0xCC0000,0x1A00000,0x1A00000,0x1A00000,0x44000000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0x1A00000,0x1A00000,0x1A00000,0x44000000,0x1A00000,0x1A00000,0x1A00000,0x44000000,0x44000000,0x940000,0x880001,0x880001,0xA00000,0xAC0000,0xBC0000,0xBC0000,0xE80000,0xA00000,0xAC0000,0x1240000,0x1A00000,
+0x1240000,0x9C0001,0x9C0001,0x9C0001,0x9C0001,0x2E80000,0x2E80000,0x2E80000,0x1DC0000,0x1DC0000,0x4E000000,0x2E80000,0x2E80000,0x2E80000,0x1DC0000,0x1DC0000,0x4E000000,0x1DC0000,0x1DC0000,0x4E000000,0x4E000000,0x2E80000,0x2E80000,0x2E80000,0x1DC0000,0x1DC0000,0x4E000000,0x1DC0000,0x1DC0000,0x4E000000,0x4E000000,0x1DC0000,
+0x1DC0000,0x4E000000,0x4E000000,0x4E000000,0xB80000,0xA80000,0x9C0001,0x2D40000,0x1080000,0x1500000,0x1800000,0x11F40000,0x2C40000,0x2E80000,0x1500000,0x4E000000,0x1500000,0xB40001,0x30C0000,0xBFC0000,0x5A000000,0x30C0000,0xBFC0000,0x5A000000,0xBFC0000,0x5A000000,0x5A000000,0x30C0000,0xBFC0000,0x5A000000,0xBFC0000,0x5A000000,
+0x5A000000,0xBFC0000,0x5A000000,0x5A000000,0x5A000000,0x30C0000,0xBFC0000,0x5A000000,0xBFC0000,0x5A000000,0x5A000000,0xBFC0000,0x5A000000,0x5A000000,0x5A000000,0xBFC0000,0x5A000000,0x5A000000,0x5A000000,0x5A000000,0xE40000,0x8C00000,0x8C00000,0x1300000,0x1BC0000,0x31FC0000,0x5A000000,0x5A000000,0xF80000,0x1540000,0x51D40000,0x5A000000,
+0x1800000,0x940274,0x888800F3,0x648800F4,0x5A8800F3,0x7E800092,0x6680004F,0x5C800067,0x5E800092,0x5A7C004E,0x547C0092,0x7C7400F4,0x6A740033,0x5C780051,0x6270004A,0x5A740002,0x5474004D,0x5A7000F4,0x566C0053,0x526C0069,0x4E7000F5,0xDC0274,0x705C00F3,0x5A7400F4,0x66580092,0x5A640049,0x54680090,0x644800F3,0x5A500032,0x5450004D,0x4E5C00F4,0x1BC0274,
+0x5A2800F3,0x54240090,0x4E1800F4,0x48000278,0xD6740004,0xFC8800F4,0xFE8C014C,0x88740002,0x70740002,0x62740002,0x5A740006,0x58700006,0xD65C0002,0x86680000,0x5C6C0035,0x5450004D,0x1380274,0xA000F3,0x7C940032,0x62940032,0x5A940032,0x728C0049,0x64880002,0x5A8C0005,0x5C880049,0x5888000E,0x54880049,0xEC00F3,0x6A740032,0x5A840032,0x62700049,0x5A740001,
+0x54780049,0x1E400F3,0x5A4C0032,0x54480048,0x4E0000F4,0xEC00F3,0x6A740032,0x5A840032,0x62700049,0x5A740001,0x54780049,0x1E400F3,0x5A4C0032,0x54480048,0x4E0000F4,0x1E400F3,0x5A4C0032,0x54480048,0x4E0000F4,0x4E0000F4,0xD6740003,0xF0900059,0xF498004A,0x88740001,0x70740001,0x62740001,0x5A7C0001,0x5A6C0004,0xDC580001,0x86680000,0x5C680033,0x54480048,
+0x15400F3,0x8800F3,0x8800F3,0x8800F3,0x8800F3,0x6C80004A,0x6C80004A,0x6C80004A,0x567C004A,0x567C004A,0x4E7C004A,0x6A740033,0x6A740033,0x6A740033,0x58740002,0x58740002,0x5074000E,0x52700033,0x52700033,0x4E700005,0x48700035,0xC800F3,0xC800F3,0xC800F3,0x5A640049,0x5A640049,0x4E6C004A,0x58540032,0x58540032,0x4E5C0001,0x4A600034,0x19800F3,
+0x19800F3,0x4E3C0048,0x48300034,0x440000F4,0xD2740003,0xF8800053,0x8800F3,0x88740001,0x6C740002,0x60740002,0x5E740003,0x56700001,0xC6600000,0x86680000,0x58700033,0x4E5C0001,0x12000F3,0x940032,0x940032,0x940032,0x940032,0x608C0001,0x608C0001,0x608C0001,0x528C0001,0x528C0001,0x4E880001,0xDC0032,0xDC0032,0xDC0032,0x56780001,0x56780001,
+0x4E800000,0x1BC0032,0x1BC0032,0x4E600000,0x48000034,0xDC0032,0xDC0032,0xDC0032,0x56780001,0x56780001,0x4E800000,0x1BC0032,0x1BC0032,0x4E600000,0x48000034,0x1BC0032,0x1BC0032,0x4E600000,0x48000034,0x48000034,0xB47C0000,0xCE8C0001,0x940032,0x88740000,0x667C0001,0x5E780000,0x587C0001,0x56700000,0xC6600000,0x806C0000,0x1380032,0x4E600000,
+0x1380032,0xA8004A,0x70A00001,0x609C0001,0x5A9C0001,0xFC0048,0x64880001,0x5A900001,0x3F80048,0x5A6C0000,0x54000048,0xFC0048,0x64880001,0x5A900001,0x3F80048,0x5A6C0000,0x54000048,0x3F80048,0x5A6C0000,0x54000048,0x54000048,0xFC0048,0x64880001,0x5A900001,0x3F80048,0x5A6C0000,0x54000048,0x3F80048,0x5A6C0000,0x54000048,0x54000048,0x3F80048,
+0x5A6C0000,0x54000048,0x54000048,0x54000048,0xEA6C0000,0x2B40048,0xF8A00001,0x8C700000,0x70700001,0x646C0000,0x5A7C0000,0x5A580000,0xE0540000,0x86680000,0x5C800000,0x54000048,0x1680048,0x7C004A,0x7C004A,0x7C004A,0x7C004A,0x7C004A,0x7C004A,0x7C004A,0x7C004A,0x7C004A,0x7C004A,0x5A740001,0x5A740001,0x5A740001,0x5A740001,0x5A740001,
+0x5A740001,0x4A700001,0x4A700001,0x4A700001,0x44700001,0xBC0048,0xBC0048,0xBC0048,0xBC0048,0xBC0048,0xBC0048,0x4E5C0001,0x4E5C0001,0x4E5C0001,0x44640001,0x17C0048,0x17C0048,0x17C0048,0x44400000,0x3E000048,0xE2740001,0x7C004A,0x7C004A,0x84740001,0x6E740001,0x62740001,0x62740001,0x54740001,0xC2600000,0x86680000,0x4E700001,0x4E5C0001,
+0x10C0048,};
+static const uint32_t g_etc1_to_bc7_m6_table42[] = {
+0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0x1880000,
+0x1880000,0x1880000,0x1880000,0x40000000,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0xC880000,0xC880000,0xC880000,0xC00000,0x1140000,0x980001,0x980001,0x980001,0x980001,0x980001,0x980001,0x980001,0x980001,0x980001,0x980001,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,
+0xE40000,0x1D00000,0x1D00000,0x1D00000,0x4C000000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0x1D00000,0x1D00000,0x1D00000,0x4C000000,0x1D00000,0x1D00000,0x1D00000,0x4C000000,0x4C000000,0xA40000,0x980001,0x980001,0xB40000,0xC00000,0xD00000,0xD00000,0x3000000,0xB40000,0xC00000,0x1480000,0x1D00000,
+0x1480000,0xAC0001,0xAC0001,0xAC0001,0xAC0001,0x3000000,0x3000000,0x3000000,0x5FC0000,0x5FC0000,0x56000000,0x3000000,0x3000000,0x3000000,0x5FC0000,0x5FC0000,0x56000000,0x5FC0000,0x5FC0000,0x56000000,0x56000000,0x3000000,0x3000000,0x3000000,0x5FC0000,0x5FC0000,0x56000000,0x5FC0000,0x5FC0000,0x56000000,0x56000000,0x5FC0000,
+0x5FC0000,0x56000000,0x56000000,0x56000000,0x4C80000,0x4B80000,0xAC0001,0xEC0000,0x1240000,0x1700000,0x1A80000,0x1BF80000,0x2D80000,0x3000000,0x1700000,0x56000000,0x1700000,0xC40001,0x3240000,0x17FC0000,0x62000000,0x3240000,0x17FC0000,0x62000000,0x17FC0000,0x62000000,0x62000000,0x3240000,0x17FC0000,0x62000000,0x17FC0000,0x62000000,
+0x62000000,0x17FC0000,0x62000000,0x62000000,0x62000000,0x3240000,0x17FC0000,0x62000000,0x17FC0000,0x62000000,0x62000000,0x17FC0000,0x62000000,0x62000000,0x62000000,0x17FC0000,0x62000000,0x62000000,0x62000000,0x62000000,0xF80000,0xD40000,0xD40000,0x14C0000,0x1E40000,0x3BFC0000,0x62000000,0x62000000,0x10C0000,0x1740000,0x59E40000,0x62000000,
+0x1A40000,0xA40274,0x909800F3,0x6C9800F4,0x629800F3,0x86900092,0x6E90004F,0x64900067,0x66900092,0x628C004E,0x5C8C0092,0x848400F4,0x72840033,0x64880051,0x6A80004A,0x62840002,0x5C84004D,0x628000F4,0x5E7C0053,0x5A7C0069,0x568000F5,0xF40274,0x786C00F3,0x628400F4,0x6E680092,0x62740049,0x5C780090,0x6C5800F3,0x62600032,0x5C60004D,0x566C00F4,0x1F00274,
+0x623800F3,0x5C340090,0x562800F4,0x50000278,0xDE840004,0xF498010A,0xF8A0015B,0x90840002,0x78840002,0x6A840002,0x62840006,0x60800006,0xDE6C0002,0x8E780000,0x647C0035,0x5C60004D,0x15C0274,0xB000F3,0x84A40032,0x6AA40032,0x62A40032,0x7A9C0049,0x6C980002,0x629C0005,0x64980049,0x6098000E,0x5C980049,0x10400F3,0x72840032,0x62940032,0x6A800049,0x62840001,
+0x5C880049,0x7FC00F3,0x625C0032,0x5C580048,0x560000F4,0x10400F3,0x72840032,0x62940032,0x6A800049,0x62840001,0x5C880049,0x7FC00F3,0x625C0032,0x5C580048,0x560000F4,0x7FC00F3,0x625C0032,0x5C580048,0x560000F4,0x560000F4,0xDE840003,0xF8A00059,0xFCA8004A,0x90840001,0x78840001,0x6A840001,0x628C0001,0x627C0004,0xE4680001,0x8E780000,0x64780033,0x5C580048,
+0x17400F3,0x9800F3,0x9800F3,0x9800F3,0x9800F3,0x7490004A,0x7490004A,0x7490004A,0x5E8C004A,0x5E8C004A,0x568C004A,0x72840033,0x72840033,0x72840033,0x60840002,0x60840002,0x5884000E,0x5A800033,0x5A800033,0x56800005,0x50800035,0xE000F3,0xE000F3,0xE000F3,0x62740049,0x62740049,0x567C004A,0x60640032,0x60640032,0x566C0001,0x52700034,0x1CC00F3,
+0x1CC00F3,0x564C0048,0x50400034,0x4C0000F4,0xDA840003,0xF090005A,0x9800F3,0x90840001,0x74840002,0x68840002,0x66840003,0x5E800001,0xCE700000,0x8E780000,0x60800033,0x566C0001,0x14000F3,0xA40032,0xA40032,0xA40032,0xA40032,0x689C0001,0x689C0001,0x689C0001,0x5A9C0001,0x5A9C0001,0x56980001,0xF40032,0xF40032,0xF40032,0x5E880001,0x5E880001,
+0x56900000,0x1F00032,0x1F00032,0x56700000,0x50000034,0xF40032,0xF40032,0xF40032,0x5E880001,0x5E880001,0x56900000,0x1F00032,0x1F00032,0x56700000,0x50000034,0x1F00032,0x1F00032,0x56700000,0x50000034,0x50000034,0xBC8C0000,0xD69C0001,0xA40032,0x90840000,0x6E8C0001,0x66880000,0x608C0001,0x5E800000,0xCE700000,0x887C0000,0x15C0032,0x56700000,
+0x15C0032,0xB8004A,0x78B00001,0x68AC0001,0x62AC0001,0x1140048,0x6C980001,0x62A00001,0xFF80048,0x627C0000,0x5C000048,0x1140048,0x6C980001,0x62A00001,0xFF80048,0x627C0000,0x5C000048,0xFF80048,0x627C0000,0x5C000048,0x5C000048,0x1140048,0x6C980001,0x62A00001,0xFF80048,0x627C0000,0x5C000048,0xFF80048,0x627C0000,0x5C000048,0x5C000048,0xFF80048,
+0x627C0000,0x5C000048,0x5C000048,0x5C000048,0xF27C0000,0xAC40048,0xF0B00002,0x94800000,0x78800001,0x6C7C0000,0x628C0000,0x62680000,0xE8640000,0x8E780000,0x64900000,0x5C000048,0x18C0048,0x8C004A,0x8C004A,0x8C004A,0x8C004A,0x8C004A,0x8C004A,0x8C004A,0x8C004A,0x8C004A,0x8C004A,0x62840001,0x62840001,0x62840001,0x62840001,0x62840001,
+0x62840001,0x52800001,0x52800001,0x52800001,0x4C800001,0x2D00048,0x2D00048,0x2D00048,0x2D00048,0x2D00048,0x2D00048,0x566C0001,0x566C0001,0x566C0001,0x4C740001,0x1AC0048,0x1AC0048,0x1AC0048,0x4C500000,0x46000048,0xEA840001,0x8C004A,0x8C004A,0x8C840001,0x76840001,0x6A840001,0x6A840001,0x5C840001,0xCA700000,0x8E780000,0x56800001,0x566C0001,
+0x12C0048,};
+static const uint32_t g_etc1_to_bc7_m6_table43[] = {
+0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0x1B80000,
+0x1B80000,0x1B80000,0x1B80000,0x48000000,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x9C0000,0x9C0000,0x9C0000,0xD80000,0x1340000,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,
+0xFC0000,0x3F80000,0x3F80000,0x3F80000,0x54000000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0x3F80000,0x3F80000,0x3F80000,0x54000000,0x3F80000,0x3F80000,0x3F80000,0x54000000,0x54000000,0x2B40000,0xA80001,0xA80001,0x2C40000,0xD40000,0xE80000,0xE80000,0x11C0000,0x2C40000,0xD40000,0x1680000,0x3F80000,
+0x1680000,0xBC0001,0xBC0001,0xBC0001,0xBC0001,0x3180000,0x3180000,0x3180000,0x11FC0000,0x11FC0000,0x5E000000,0x3180000,0x3180000,0x3180000,0x11FC0000,0x11FC0000,0x5E000000,0x11FC0000,0x11FC0000,0x5E000000,0x5E000000,0x3180000,0x3180000,0x3180000,0x11FC0000,0x11FC0000,0x5E000000,0x11FC0000,0x11FC0000,0x5E000000,0x5E000000,0x11FC0000,
+0x11FC0000,0x5E000000,0x5E000000,0x5E000000,0xDC0000,0xCC80000,0xBC0001,0x3000000,0x1400000,0x1940000,0x1D00000,0x25FC0000,0x2EC0000,0x3180000,0x1940000,0x5E000000,0x1940000,0xD40001,0x33C0000,0x23FC0000,0x6A000000,0x33C0000,0x23FC0000,0x6A000000,0x23FC0000,0x6A000000,0x6A000000,0x33C0000,0x23FC0000,0x6A000000,0x23FC0000,0x6A000000,
+0x6A000000,0x23FC0000,0x6A000000,0x6A000000,0x6A000000,0x33C0000,0x23FC0000,0x6A000000,0x23FC0000,0x6A000000,0x6A000000,0x23FC0000,0x6A000000,0x6A000000,0x6A000000,0x23FC0000,0x6A000000,0x6A000000,0x6A000000,0x6A000000,0x10C0000,0xE40000,0xE40000,0x1680000,0x7F80000,0x45FC0000,0x6A000000,0x6A000000,0x1240000,0x1900000,0x61F40000,0x6A000000,
+0x1C80000,0xB40274,0x98A800F3,0x74A800F4,0x6AA800F3,0x8EA00092,0x76A0004F,0x6CA00067,0x6EA00092,0x6A9C004E,0x649C0092,0x8C9400F4,0x7A940033,0x6C980051,0x7290004A,0x6A940002,0x6494004D,0x6A9000F4,0x668C0053,0x628C0069,0x5E9000F5,0x10C0274,0x807C00F3,0x6A9400F4,0x76780092,0x6A840049,0x64880090,0x746800F3,0x6A700032,0x6470004D,0x5E7C00F4,0xBF80274,
+0x6A4800F3,0x64440090,0x5E3800F4,0x58000278,0xE6940004,0xFCA8010A,0xFEAC015F,0x98940002,0x80940002,0x72940002,0x6A940006,0x68900006,0xE67C0002,0x96880000,0x6C8C0035,0x6470004D,0x17C0274,0xC000F3,0x8CB40032,0x72B40032,0x6AB40032,0x82AC0049,0x74A80002,0x6AAC0005,0x6CA80049,0x68A8000E,0x64A80049,0x11C00F3,0x7A940032,0x6AA40032,0x72900049,0x6A940001,
+0x64980049,0x13FC00F3,0x6A6C0032,0x64680048,0x5E0000F4,0x11C00F3,0x7A940032,0x6AA40032,0x72900049,0x6A940001,0x64980049,0x13FC00F3,0x6A6C0032,0x64680048,0x5E0000F4,0x13FC00F3,0x6A6C0032,0x64680048,0x5E0000F4,0x5E0000F4,0xE6940003,0xF0B00063,0xF4B80053,0x98940001,0x80940001,0x72940001,0x6A9C0001,0x6A8C0004,0xEC780001,0x96880000,0x6C880033,0x64680048,
+0x19800F3,0xA800F3,0xA800F3,0xA800F3,0xA800F3,0x7CA0004A,0x7CA0004A,0x7CA0004A,0x669C004A,0x669C004A,0x5E9C004A,0x7A940033,0x7A940033,0x7A940033,0x68940002,0x68940002,0x6094000E,0x62900033,0x62900033,0x5E900005,0x58900035,0xF800F3,0xF800F3,0xF800F3,0x6A840049,0x6A840049,0x5E8C004A,0x68740032,0x68740032,0x5E7C0001,0x5A800034,0x1FC00F3,
+0x1FC00F3,0x5E5C0048,0x58500034,0x540000F4,0xE2940003,0xF8A0005A,0xA800F3,0x98940001,0x7C940002,0x70940002,0x6E940003,0x66900001,0xD6800000,0x96880000,0x68900033,0x5E7C0001,0x16400F3,0xB40032,0xB40032,0xB40032,0xB40032,0x70AC0001,0x70AC0001,0x70AC0001,0x62AC0001,0x62AC0001,0x5EA80001,0x10C0032,0x10C0032,0x10C0032,0x66980001,0x66980001,
+0x5EA00000,0xBF80032,0xBF80032,0x5E800000,0x58000034,0x10C0032,0x10C0032,0x10C0032,0x66980001,0x66980001,0x5EA00000,0xBF80032,0xBF80032,0x5E800000,0x58000034,0xBF80032,0xBF80032,0x5E800000,0x58000034,0x58000034,0xC49C0000,0xDEAC0001,0xB40032,0x98940000,0x769C0001,0x6E980000,0x689C0001,0x66900000,0xD6800000,0x908C0000,0x17C0032,0x5E800000,
+0x17C0032,0xC8004A,0x80C00001,0x70BC0001,0x6ABC0001,0x12C0048,0x74A80001,0x6AB00001,0x1BF80048,0x6A8C0000,0x64000048,0x12C0048,0x74A80001,0x6AB00001,0x1BF80048,0x6A8C0000,0x64000048,0x1BF80048,0x6A8C0000,0x64000048,0x64000048,0x12C0048,0x74A80001,0x6AB00001,0x1BF80048,0x6A8C0000,0x64000048,0x1BF80048,0x6A8C0000,0x64000048,0x64000048,0x1BF80048,
+0x6A8C0000,0x64000048,0x64000048,0x64000048,0xFA8C0000,0xD80048,0xF8C00002,0x9C900000,0x80900001,0x748C0000,0x6A9C0000,0x6A780000,0xF0740000,0x96880000,0x6CA00000,0x64000048,0x1AC0048,0x9C004A,0x9C004A,0x9C004A,0x9C004A,0x9C004A,0x9C004A,0x9C004A,0x9C004A,0x9C004A,0x9C004A,0x6A940001,0x6A940001,0x6A940001,0x6A940001,0x6A940001,
+0x6A940001,0x5A900001,0x5A900001,0x5A900001,0x54900001,0x2E80048,0x2E80048,0x2E80048,0x2E80048,0x2E80048,0x2E80048,0x5E7C0001,0x5E7C0001,0x5E7C0001,0x54840001,0x1DC0048,0x1DC0048,0x1DC0048,0x54600000,0x4E000048,0xF2940001,0x9C004A,0x9C004A,0x94940001,0x7E940001,0x72940001,0x72940001,0x64940001,0xD2800000,0x96880000,0x5E900001,0x5E7C0001,
+0x1500048,};
+static const uint32_t g_etc1_to_bc7_m6_table44[] = {
+0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0x1F00000,
+0x1F00000,0x1F00000,0x1F00000,0x50000001,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xEAC0000,0xEAC0000,0xEAC0000,0xF40000,0x15C0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,
+0x1180000,0x11F80000,0x11F80000,0x11F80000,0x5C000001,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x11F80000,0x11F80000,0x11F80000,0x5C000001,0x11F80000,0x11F80000,0x11F80000,0x5C000001,0x5C000001,0xC80000,0xBC0000,0xBC0000,0x4D80000,0xEC0000,0x1000000,0x1000000,0x13C0000,0x4D80000,0xEC0000,0x1900000,0x11F80000,
+0x1900000,0xD00000,0xD00000,0xD00000,0xD00000,0x1340000,0x1340000,0x1340000,0x1FF80000,0x1FF80000,0x66000001,0x1340000,0x1340000,0x1340000,0x1FF80000,0x1FF80000,0x66000001,0x1FF80000,0x1FF80000,0x66000001,0x66000001,0x1340000,0x1340000,0x1340000,0x1FF80000,0x1FF80000,0x66000001,0x1FF80000,0x1FF80000,0x66000001,0x66000001,0x1FF80000,
+0x1FF80000,0x66000001,0x66000001,0x66000001,0x2F00000,0x6DC0000,0xD00000,0x3180000,0x15C0000,0x1B80000,0x1FC0000,0x33F40000,0x1040000,0x1340000,0x1B80000,0x66000001,0x1B80000,0xE80000,0x1580000,0x31F80000,0x72000001,0x1580000,0x31F80000,0x72000001,0x31F80000,0x72000001,0x72000001,0x1580000,0x31F80000,0x72000001,0x31F80000,0x72000001,
+0x72000001,0x31F80000,0x72000001,0x72000001,0x72000001,0x1580000,0x31F80000,0x72000001,0x31F80000,0x72000001,0x72000001,0x31F80000,0x72000001,0x72000001,0x72000001,0x31F80000,0x72000001,0x72000001,0x72000001,0x72000001,0x5200000,0xF80000,0xF80000,0x1840000,0x15FC0000,0x51F80000,0x72000001,0x72000001,0x13C0000,0x1B40000,0x6BE80000,0x72000001,
+0x1EC0000,0xC40278,0xA0BC00F4,0x7EBC00F4,0x72BC00F5,0x9AB00090,0x82B0004D,0x76B40069,0x78B00090,0x72B0004D,0x6CB00092,0x96A400F3,0x84A40032,0x76AC0053,0x7AA40049,0x72A40002,0x6EA4004E,0x72A400F4,0x70A00051,0x6CA00067,0x68A400F3,0x3240274,0x889000F3,0x72A400F4,0x80880092,0x7494004A,0x6C9C0092,0x7E7800F3,0x72840033,0x6C84004F,0x688C00F4,0x17FC0274,
+0x726000F4,0x6C580092,0x684400F3,0x62000274,0xF6A40005,0xF6BC0120,0xF8C0016C,0xA4A40000,0x8AA40001,0x7AA40002,0x74A80006,0x72A40006,0xEE8C0002,0x9C9C0002,0x74A00035,0x6C84004F,0x1A40274,0xD000F4,0x94C80034,0x7CC40034,0x72C40035,0x8EBC0048,0x7CBC0001,0x74BC0005,0x74BC004A,0x72B8000E,0x6CBC004A,0x13800F3,0x82A80032,0x74B40033,0x7AA40049,0x72A40002,
+0x6CAC004A,0x21F800F3,0x72840033,0x6C7C004A,0x680000F3,0x13800F3,0x82A80032,0x74B40033,0x7AA40049,0x72A40002,0x6CAC004A,0x21F800F3,0x72840033,0x6C7C004A,0x680000F3,0x21F800F3,0x72840033,0x6C7C004A,0x680000F3,0x680000F3,0xEAA80003,0xFAC40060,0xFECC0054,0xA4A40000,0x8AA40001,0x7AA40002,0x74AC0001,0x729C0003,0xEE8C0001,0x9C9C0001,0x76980032,0x6C7C004A,
+0x1BC00F3,0xBC00F4,0xBC00F4,0xBC00F4,0xBC00F4,0x88B00048,0x88B00048,0x88B00048,0x6EB00049,0x6EB00049,0x66B00049,0x84A40032,0x84A40032,0x84A40032,0x72A40001,0x72A40001,0x68A8000E,0x6AA40032,0x6AA40032,0x66A40005,0x62A40032,0x11400F3,0x11400F3,0x11400F3,0x74940049,0x74940049,0x66A00049,0x72840032,0x72840032,0x66900002,0x62940032,0xFF800F3,
+0xFF800F3,0x66700049,0x625C0032,0x5C0000F3,0xEAA40004,0xF2B40060,0xBC00F4,0xA4A40000,0x86A40001,0x7AA40001,0x76A40004,0x6EA40001,0xE4900000,0x9C9C0001,0x72A00032,0x66900002,0x18C00F3,0xC40034,0xC40034,0xC40034,0xC40034,0x7ABC0000,0x7ABC0000,0x7ABC0000,0x6CBC0000,0x6CBC0000,0x66BC0001,0x3240032,0x3240032,0x3240032,0x6EAC0001,0x6EAC0001,
+0x66B40001,0x17FC0032,0x17FC0032,0x66980001,0x62000032,0x3240032,0x3240032,0x3240032,0x6EAC0001,0x6EAC0001,0x66B40001,0x17FC0032,0x17FC0032,0x66980001,0x62000032,0x17FC0032,0x17FC0032,0x66980001,0x62000032,0x62000032,0xD2AC0000,0xF6BC0000,0xC40034,0xA4A40000,0x84A80000,0x78A80000,0x74AC0000,0x6EA40001,0xE4900000,0x9C9C0000,0x1A40032,0x66980001,
+0x1A40032,0xDC0048,0x8CD00000,0x78D00001,0x72D00001,0x3440048,0x7CBC0001,0x72C40001,0x27FC0048,0x72A00001,0x6C00004A,0x3440048,0x7CBC0001,0x72C40001,0x27FC0048,0x72A00001,0x6C00004A,0x27FC0048,0x72A00001,0x6C00004A,0x6C00004A,0x3440048,0x7CBC0001,0x72C40001,0x27FC0048,0x72A00001,0x6C00004A,0x27FC0048,0x72A00001,0x6C00004A,0x6C00004A,0x27FC0048,
+0x72A00001,0x6C00004A,0x6C00004A,0x6C00004A,0xF6A40001,0xCE80048,0xF2D40005,0xA4A40000,0x88A40001,0x7CA00000,0x72B00001,0x72900001,0xF6880000,0xA0980000,0x74B40001,0x6C00004A,0x1D40048,0xB00048,0xB00048,0xB00048,0xB00048,0xB00048,0xB00048,0xB00048,0xB00048,0xB00048,0xB00048,0x76A40000,0x76A40000,0x76A40000,0x76A40000,0x76A40000,
+0x76A40000,0x62A40001,0x62A40001,0x62A40001,0x5CA40001,0x1040048,0x1040048,0x1040048,0x1040048,0x1040048,0x1040048,0x66900001,0x66900001,0x66900001,0x5C980001,0x7FC0048,0x7FC0048,0x7FC0048,0x5C740001,0x5600004A,0xFAA40001,0xB00048,0xB00048,0xA4A40000,0x8AA40000,0x7EA40000,0x7EA40000,0x6EA40000,0xE0900000,0xA4980000,0x6AA00000,0x66900001,
+0x1740048,};
+static const uint32_t g_etc1_to_bc7_m6_table45[] = {
+0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0xBF80000,
+0xBF80000,0xBF80000,0xBF80000,0x58000001,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xC00000,0xC00000,0xC00000,0x10C0000,0x17C0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,
+0x1300000,0x1DF40000,0x1DF40000,0x1DF40000,0x64000001,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1DF40000,0x1DF40000,0x1DF40000,0x64000001,0x1DF40000,0x1DF40000,0x1DF40000,0x64000001,0x64000001,0x4D80000,0xCC0000,0xCC0000,0xEC0000,0x1000000,0x1140000,0x1140000,0x3540000,0xEC0000,0x1000000,0x1B00000,0x1DF40000,
+0x1B00000,0xE00000,0xE00000,0xE00000,0xE00000,0x14C0000,0x14C0000,0x14C0000,0x2BF80000,0x2BF80000,0x6E000001,0x14C0000,0x14C0000,0x14C0000,0x2BF80000,0x2BF80000,0x6E000001,0x2BF80000,0x2BF80000,0x6E000001,0x6E000001,0x14C0000,0x14C0000,0x14C0000,0x2BF80000,0x2BF80000,0x6E000001,0x2BF80000,0x2BF80000,0x6E000001,0x6E000001,0x2BF80000,
+0x2BF80000,0x6E000001,0x6E000001,0x6E000001,0x1040000,0xEEC0000,0xE00000,0x1300000,0x1780000,0x1DC0000,0xFFC0000,0x3DF80000,0x1180000,0x14C0000,0x1DC0000,0x6E000001,0x1DC0000,0xF80000,0x1700000,0x3DF80000,0x7A000001,0x1700000,0x3DF80000,0x7A000001,0x3DF80000,0x7A000001,0x7A000001,0x1700000,0x3DF80000,0x7A000001,0x3DF80000,0x7A000001,
+0x7A000001,0x3DF80000,0x7A000001,0x7A000001,0x7A000001,0x1700000,0x3DF80000,0x7A000001,0x3DF80000,0x7A000001,0x7A000001,0x3DF80000,0x7A000001,0x7A000001,0x7A000001,0x3DF80000,0x7A000001,0x7A000001,0x7A000001,0x7A000001,0x5340000,0x1080000,0x1080000,0x1A00000,0x23FC0000,0x5BF80000,0x7A000001,0x7A000001,0x1500000,0x1D00000,0x73F80000,0x7A000001,
+0x9FC0000,0xD40278,0xA8CC00F4,0x86CC00F4,0x7ACC00F5,0xA2C00090,0x8AC0004D,0x7EC40069,0x80C00090,0x7AC0004D,0x74C00092,0x9EB400F3,0x8CB40032,0x7EBC0053,0x82B40049,0x7AB40002,0x76B4004E,0x7AB400F4,0x78B00051,0x74B00067,0x70B400F3,0x33C0274,0x90A000F3,0x7AB400F4,0x88980092,0x7CA4004A,0x74AC0092,0x868800F3,0x7A940033,0x7494004F,0x709C00F4,0x23FC0274,
+0x7A7000F4,0x74680092,0x705400F3,0x6A000274,0xFEB40005,0xFECC0120,0xF0D00181,0xACB40000,0x92B40001,0x82B40002,0x7CB80006,0x7AB40006,0xF69C0002,0xA4AC0002,0x7CB00035,0x7494004F,0x1C80274,0xE000F4,0x9CD80034,0x84D40034,0x7AD40035,0x96CC0048,0x84CC0001,0x7CCC0005,0x7CCC004A,0x7AC8000E,0x74CC004A,0x15000F3,0x8AB80032,0x7CC40033,0x82B40049,0x7AB40002,
+0x74BC004A,0x2DF800F3,0x7A940033,0x748C004A,0x700000F3,0x15000F3,0x8AB80032,0x7CC40033,0x82B40049,0x7AB40002,0x74BC004A,0x2DF800F3,0x7A940033,0x748C004A,0x700000F3,0x2DF800F3,0x7A940033,0x748C004A,0x700000F3,0x700000F3,0xF2B80003,0xF2D4006A,0xF6DC005D,0xACB40000,0x92B40001,0x82B40002,0x7CBC0001,0x7AAC0003,0xF69C0001,0xA4AC0001,0x7EA80032,0x748C004A,
+0x1E000F3,0xCC00F4,0xCC00F4,0xCC00F4,0xCC00F4,0x90C00048,0x90C00048,0x90C00048,0x76C00049,0x76C00049,0x6EC00049,0x8CB40032,0x8CB40032,0x8CB40032,0x7AB40001,0x7AB40001,0x70B8000E,0x72B40032,0x72B40032,0x6EB40005,0x6AB40032,0x12C00F3,0x12C00F3,0x12C00F3,0x7CA40049,0x7CA40049,0x6EB00049,0x7A940032,0x7A940032,0x6EA00002,0x6AA40032,0x1BF800F3,
+0x1BF800F3,0x6E800049,0x6A6C0032,0x640000F3,0xF2B40004,0xFAC40060,0xCC00F4,0xACB40000,0x8EB40001,0x82B40001,0x7EB40004,0x76B40001,0xECA00000,0xA4AC0001,0x7AB00032,0x6EA00002,0x1AC00F3,0xD40034,0xD40034,0xD40034,0xD40034,0x82CC0000,0x82CC0000,0x82CC0000,0x74CC0000,0x74CC0000,0x6ECC0001,0x33C0032,0x33C0032,0x33C0032,0x76BC0001,0x76BC0001,
+0x6EC40001,0x23FC0032,0x23FC0032,0x6EA80001,0x6A000032,0x33C0032,0x33C0032,0x33C0032,0x76BC0001,0x76BC0001,0x6EC40001,0x23FC0032,0x23FC0032,0x6EA80001,0x6A000032,0x23FC0032,0x23FC0032,0x6EA80001,0x6A000032,0x6A000032,0xDABC0000,0xFECC0000,0xD40034,0xACB40000,0x8CB80000,0x80B80000,0x7CBC0000,0x76B40001,0xECA00000,0xA4AC0000,0x1C80032,0x6EA80001,
+0x1C80032,0xEC0048,0x94E00000,0x80E00001,0x7AE00001,0x35C0048,0x84CC0001,0x7AD40001,0x33FC0048,0x7AB00001,0x7400004A,0x35C0048,0x84CC0001,0x7AD40001,0x33FC0048,0x7AB00001,0x7400004A,0x33FC0048,0x7AB00001,0x7400004A,0x7400004A,0x35C0048,0x84CC0001,0x7AD40001,0x33FC0048,0x7AB00001,0x7400004A,0x33FC0048,0x7AB00001,0x7400004A,0x7400004A,0x33FC0048,
+0x7AB00001,0x7400004A,0x7400004A,0x7400004A,0xFEB40001,0xFC0048,0xFAE40005,0xACB40000,0x90B40001,0x84B00000,0x7AC00001,0x7AA00001,0xFE980000,0xA8A80000,0x7CC40001,0x7400004A,0x1F40048,0xC00048,0xC00048,0xC00048,0xC00048,0xC00048,0xC00048,0xC00048,0xC00048,0xC00048,0xC00048,0x7EB40000,0x7EB40000,0x7EB40000,0x7EB40000,0x7EB40000,
+0x7EB40000,0x6AB40001,0x6AB40001,0x6AB40001,0x64B40001,0x11C0048,0x11C0048,0x11C0048,0x11C0048,0x11C0048,0x11C0048,0x6EA00001,0x6EA00001,0x6EA00001,0x64A80001,0x13FC0048,0x13FC0048,0x13FC0048,0x64840001,0x5E00004A,0xF2B40004,0xC00048,0xC00048,0xACB40000,0x92B40000,0x86B40000,0x86B40000,0x76B40000,0xE8A00000,0xACA80000,0x72B00000,0x6EA00001,
+0x1980048,};
+static const uint32_t g_etc1_to_bc7_m6_table46[] = {
+0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x17F80000,
+0x17F80000,0x17F80000,0x17F80000,0x60000001,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xD00000,0xD00000,0xD00000,0x1240000,0x1A00000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0x3440000,0x3440000,0x3440000,0x3440000,0x3440000,
+0x3440000,0x27FC0000,0x27FC0000,0x27FC0000,0x6C000001,0x3440000,0x3440000,0x3440000,0x3440000,0x3440000,0x3440000,0x27FC0000,0x27FC0000,0x27FC0000,0x6C000001,0x27FC0000,0x27FC0000,0x27FC0000,0x6C000001,0x6C000001,0xCE80000,0xDC0000,0xDC0000,0x1000000,0x1140000,0x12C0000,0x12C0000,0x1700000,0x1000000,0x1140000,0x1D40000,0x27FC0000,
+0x1D40000,0xF00000,0xF00000,0xF00000,0xF00000,0x1640000,0x1640000,0x1640000,0x37F80000,0x37F80000,0x76000001,0x1640000,0x1640000,0x1640000,0x37F80000,0x37F80000,0x76000001,0x37F80000,0x37F80000,0x76000001,0x76000001,0x1640000,0x1640000,0x1640000,0x37F80000,0x37F80000,0x76000001,0x37F80000,0x37F80000,0x76000001,0x76000001,0x37F80000,
+0x37F80000,0x76000001,0x76000001,0x76000001,0x1180000,0x1000000,0xF00000,0x3440000,0x1940000,0x1FC0000,0x1DF80000,0x47FC0000,0x12C0000,0x1640000,0x1FC0000,0x76000001,0x1FC0000,0x1080000,0x1880000,0x49F80000,0x82000001,0x1880000,0x49F80000,0x82000001,0x49F80000,0x82000001,0x82000001,0x1880000,0x49F80000,0x82000001,0x49F80000,0x82000001,
+0x82000001,0x49F80000,0x82000001,0x82000001,0x82000001,0x1880000,0x49F80000,0x82000001,0x49F80000,0x82000001,0x82000001,0x49F80000,0x82000001,0x82000001,0x82000001,0x49F80000,0x82000001,0x82000001,0x82000001,0x82000001,0x14C0000,0x5180000,0x5180000,0x1BC0000,0x31FC0000,0x65F80000,0x82000001,0x82000001,0x1680000,0x1F00000,0x7DCC0000,0x82000001,
+0x19FC0000,0xE40278,0xB0DC00F4,0x8EDC00F4,0x82DC00F5,0xAAD00090,0x92D0004D,0x86D40069,0x88D00090,0x82D0004D,0x7CD00092,0xA6C400F3,0x94C40032,0x86CC0053,0x8AC40049,0x82C40002,0x7EC4004E,0x82C400F4,0x80C00051,0x7CC00067,0x78C400F3,0x1540274,0x98B000F3,0x82C400F4,0x90A80092,0x84B4004A,0x7CBC0092,0x8E9800F3,0x82A40033,0x7CA4004F,0x78AC00F4,0x2FFC0274,
+0x828000F4,0x7C780092,0x786400F3,0x72000274,0xFAC80007,0xF6DC013A,0xF8E00181,0xB4C40000,0x9AC40001,0x8AC40002,0x84C80006,0x82C40006,0xFEAC0002,0xACBC0002,0x84C00035,0x7CA4004F,0x1E80274,0xF000F4,0xA4E80034,0x8CE40034,0x82E40035,0x9EDC0048,0x8CDC0001,0x84DC0005,0x84DC004A,0x82D8000E,0x7CDC004A,0x16800F3,0x92C80032,0x84D40033,0x8AC40049,0x82C40002,
+0x7CCC004A,0x39F800F3,0x82A40033,0x7C9C004A,0x780000F3,0x16800F3,0x92C80032,0x84D40033,0x8AC40049,0x82C40002,0x7CCC004A,0x39F800F3,0x82A40033,0x7C9C004A,0x780000F3,0x39F800F3,0x82A40033,0x7C9C004A,0x780000F3,0x780000F3,0xFAC80003,0xFAE4006A,0xFEEC005D,0xB4C40000,0x9AC40001,0x8AC40002,0x84CC0001,0x82BC0003,0xFEAC0001,0xACBC0001,0x86B80032,0x7C9C004A,
+0x3FC00F3,0xDC00F4,0xDC00F4,0xDC00F4,0xDC00F4,0x98D00048,0x98D00048,0x98D00048,0x7ED00049,0x7ED00049,0x76D00049,0x94C40032,0x94C40032,0x94C40032,0x82C40001,0x82C40001,0x78C8000E,0x7AC40032,0x7AC40032,0x76C40005,0x72C40032,0x14400F3,0x14400F3,0x14400F3,0x84B40049,0x84B40049,0x76C00049,0x82A40032,0x82A40032,0x76B00002,0x72B40032,0x27F800F3,
+0x27F800F3,0x76900049,0x727C0032,0x6C0000F3,0xFAC40004,0xF2D40069,0xDC00F4,0xB4C40000,0x96C40001,0x8AC40001,0x86C40004,0x7EC40001,0xF4B00000,0xACBC0001,0x82C00032,0x76B00002,0x1D000F3,0xE40034,0xE40034,0xE40034,0xE40034,0x8ADC0000,0x8ADC0000,0x8ADC0000,0x7CDC0000,0x7CDC0000,0x76DC0001,0x1540032,0x1540032,0x1540032,0x7ECC0001,0x7ECC0001,
+0x76D40001,0x2FFC0032,0x2FFC0032,0x76B80001,0x72000032,0x1540032,0x1540032,0x1540032,0x7ECC0001,0x7ECC0001,0x76D40001,0x2FFC0032,0x2FFC0032,0x76B80001,0x72000032,0x2FFC0032,0x2FFC0032,0x76B80001,0x72000032,0x72000032,0xE2CC0000,0xF6DC0001,0xE40034,0xB4C40000,0x94C80000,0x88C80000,0x84CC0000,0x7EC40001,0xF4B00000,0xACBC0000,0x1E80032,0x76B80001,
+0x1E80032,0xFC0048,0x9CF00000,0x88F00001,0x82F00001,0x3740048,0x8CDC0001,0x82E40001,0x3FFC0048,0x82C00001,0x7C00004A,0x3740048,0x8CDC0001,0x82E40001,0x3FFC0048,0x82C00001,0x7C00004A,0x3FFC0048,0x82C00001,0x7C00004A,0x7C00004A,0x3740048,0x8CDC0001,0x82E40001,0x3FFC0048,0x82C00001,0x7C00004A,0x3FFC0048,0x82C00001,0x7C00004A,0x7C00004A,0x3FFC0048,
+0x82C00001,0x7C00004A,0x7C00004A,0x7C00004A,0xFAC80002,0x10C0048,0xF2F40008,0xB4C40000,0x98C40001,0x8CC00000,0x82D00001,0x82B00001,0xFEAC0001,0xB0B80000,0x84D40001,0x7C00004A,0xDFC0048,0xD00048,0xD00048,0xD00048,0xD00048,0xD00048,0xD00048,0xD00048,0xD00048,0xD00048,0xD00048,0x86C40000,0x86C40000,0x86C40000,0x86C40000,0x86C40000,
+0x86C40000,0x72C40001,0x72C40001,0x72C40001,0x6CC40001,0x1340048,0x1340048,0x1340048,0x1340048,0x1340048,0x1340048,0x76B00001,0x76B00001,0x76B00001,0x6CB80001,0x1FF80048,0x1FF80048,0x1FF80048,0x6C940001,0x6600004A,0xFAC40004,0xD00048,0xD00048,0xB4C40000,0x9AC40000,0x8EC40000,0x8EC40000,0x7EC40000,0xF0B00000,0xB4B80000,0x7AC00000,0x76B00001,
+0x1B80048,};
+static const uint32_t g_etc1_to_bc7_m6_table47[] = {
+0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x21FC0000,
+0x21FC0000,0x21FC0000,0x21FC0000,0x68000001,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0x8E00000,0x8E00000,0x8E00000,0x13C0000,0x1C00000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,
+0x35C0000,0x33FC0000,0x33FC0000,0x33FC0000,0x74000001,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x33FC0000,0x33FC0000,0x33FC0000,0x74000001,0x33FC0000,0x33FC0000,0x33FC0000,0x74000001,0x74000001,0xFC0000,0xEC0000,0xEC0000,0x5100000,0x1280000,0x1400000,0x1400000,0x18C0000,0x5100000,0x1280000,0x1F40000,0x33FC0000,
+0x1F40000,0x1000000,0x1000000,0x1000000,0x1000000,0x17C0000,0x17C0000,0x17C0000,0x43F80000,0x43F80000,0x7E000001,0x17C0000,0x17C0000,0x17C0000,0x43F80000,0x43F80000,0x7E000001,0x43F80000,0x43F80000,0x7E000001,0x7E000001,0x17C0000,0x17C0000,0x17C0000,0x43F80000,0x43F80000,0x7E000001,0x43F80000,0x43F80000,0x7E000001,0x7E000001,0x43F80000,
+0x43F80000,0x7E000001,0x7E000001,0x7E000001,0x3280000,0x1100000,0x1000000,0x15C0000,0x3AC0000,0x11FC0000,0x29FC0000,0x53F80000,0x1400000,0x17C0000,0x11FC0000,0x7E000001,0x11FC0000,0x1180000,0x1A00000,0x55F80000,0x8A000001,0x1A00000,0x55F80000,0x8A000001,0x55F80000,0x8A000001,0x8A000001,0x1A00000,0x55F80000,0x8A000001,0x55F80000,0x8A000001,
+0x8A000001,0x55F80000,0x8A000001,0x8A000001,0x8A000001,0x1A00000,0x55F80000,0x8A000001,0x55F80000,0x8A000001,0x8A000001,0x55F80000,0x8A000001,0x8A000001,0x8A000001,0x55F80000,0x8A000001,0x8A000001,0x8A000001,0x8A000001,0x1600000,0xD280000,0xD280000,0x3D40000,0x3FF80000,0x6FF80000,0x8A000001,0x8A000001,0x17C0000,0xBFC0000,0x85DC0000,0x8A000001,
+0x27FC0000,0xF40278,0xB8EC00F4,0x96EC00F4,0x8AEC00F5,0xB2E00090,0x9AE0004D,0x8EE40069,0x90E00090,0x8AE0004D,0x84E00092,0xAED400F3,0x9CD40032,0x8EDC0053,0x92D40049,0x8AD40002,0x86D4004E,0x8AD400F4,0x88D00051,0x84D00067,0x80D400F3,0x16C0274,0xA0C000F3,0x8AD400F4,0x98B80092,0x8CC4004A,0x84CC0092,0x96A800F3,0x8AB40033,0x84B4004F,0x80BC00F4,0x3BFC0274,
+0x8A9000F4,0x84880092,0x807400F3,0x7A000274,0xFED8000A,0xFEEC013A,0xF0F00198,0xBCD40000,0xA2D40001,0x92D40002,0x8CD80006,0x8AD40006,0xFCC00004,0xB4CC0002,0x8CD00035,0x84B4004F,0x7FC0274,0x10000F4,0xACF80034,0x94F40034,0x8AF40035,0xA6EC0048,0x94EC0001,0x8CEC0005,0x8CEC004A,0x8AE8000E,0x84EC004A,0x18000F3,0x9AD80032,0x8CE40033,0x92D40049,0x8AD40002,
+0x84DC004A,0x45F800F3,0x8AB40033,0x84AC004A,0x800000F3,0x18000F3,0x9AD80032,0x8CE40033,0x92D40049,0x8AD40002,0x84DC004A,0x45F800F3,0x8AB40033,0x84AC004A,0x800000F3,0x45F800F3,0x8AB40033,0x84AC004A,0x800000F3,0x800000F3,0xF6DC0006,0xF4F80074,0xF6FC0068,0xBCD40000,0xA2D40001,0x92D40002,0x8CDC0001,0x8ACC0003,0xFCC00004,0xB4CC0001,0x8EC80032,0x84AC004A,
+0x13FC00F3,0xEC00F4,0xEC00F4,0xEC00F4,0xEC00F4,0xA0E00048,0xA0E00048,0xA0E00048,0x86E00049,0x86E00049,0x7EE00049,0x9CD40032,0x9CD40032,0x9CD40032,0x8AD40001,0x8AD40001,0x80D8000E,0x82D40032,0x82D40032,0x7ED40005,0x7AD40032,0x15C00F3,0x15C00F3,0x15C00F3,0x8CC40049,0x8CC40049,0x7ED00049,0x8AB40032,0x8AB40032,0x7EC00002,0x7AC40032,0x33F800F3,
+0x33F800F3,0x7EA00049,0x7A8C0032,0x740000F3,0xF6D80005,0xFAE40069,0xEC00F4,0xBCD40000,0x9ED40001,0x92D40001,0x8ED40004,0x86D40001,0xFCC00000,0xB4CC0001,0x8AD00032,0x7EC00002,0x1F000F3,0xF40034,0xF40034,0xF40034,0xF40034,0x92EC0000,0x92EC0000,0x92EC0000,0x84EC0000,0x84EC0000,0x7EEC0001,0x16C0032,0x16C0032,0x16C0032,0x86DC0001,0x86DC0001,
+0x7EE40001,0x3BFC0032,0x3BFC0032,0x7EC80001,0x7A000032,0x16C0032,0x16C0032,0x16C0032,0x86DC0001,0x86DC0001,0x7EE40001,0x3BFC0032,0x3BFC0032,0x7EC80001,0x7A000032,0x3BFC0032,0x3BFC0032,0x7EC80001,0x7A000032,0x7A000032,0xEADC0000,0xFEEC0001,0xF40034,0xBCD40000,0x9CD80000,0x90D80000,0x8CDC0000,0x86D40001,0xFCC00000,0xB4CC0000,0x7FC0032,0x7EC80001,
+0x7FC0032,0x10C0048,0xA5000000,0x91000001,0x8B000001,0x38C0048,0x94EC0001,0x8AF40001,0x4BFC0048,0x8AD00001,0x8400004A,0x38C0048,0x94EC0001,0x8AF40001,0x4BFC0048,0x8AD00001,0x8400004A,0x4BFC0048,0x8AD00001,0x8400004A,0x8400004A,0x38C0048,0x94EC0001,0x8AF40001,0x4BFC0048,0x8AD00001,0x8400004A,0x4BFC0048,0x8AD00001,0x8400004A,0x8400004A,0x4BFC0048,
+0x8AD00001,0x8400004A,0x8400004A,0x8400004A,0xF2E00005,0x71C0048,0xFB040008,0xBCD40000,0xA0D40001,0x94D00000,0x8AE00001,0x8AC00001,0xF4C80002,0xB8C80000,0x8CE40001,0x8400004A,0x1DF80048,0xE00048,0xE00048,0xE00048,0xE00048,0xE00048,0xE00048,0xE00048,0xE00048,0xE00048,0xE00048,0x8ED40000,0x8ED40000,0x8ED40000,0x8ED40000,0x8ED40000,
+0x8ED40000,0x7AD40001,0x7AD40001,0x7AD40001,0x74D40001,0x14C0048,0x14C0048,0x14C0048,0x14C0048,0x14C0048,0x14C0048,0x7EC00001,0x7EC00001,0x7EC00001,0x74C80001,0x2BF80048,0x2BF80048,0x2BF80048,0x74A40001,0x6E00004A,0xF4D80005,0xE00048,0xE00048,0xBCD40000,0xA2D40000,0x96D40000,0x96D40000,0x86D40000,0xF8C00000,0xBCC80000,0x82D00000,0x7EC00001,
+0x1DC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table48[] = {
+0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x2FFC0000,
+0x2FFC0000,0x2FFC0000,0x2FFC0000,0x72000000,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0x2F40000,0x2F40000,0x2F40000,0x1540000,0x1E80000,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,
+0x1780000,0x41FC0000,0x41FC0000,0x41FC0000,0x7E000000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x41FC0000,0x41FC0000,0x41FC0000,0x7E000000,0x41FC0000,0x41FC0000,0x41FC0000,0x7E000000,0x7E000000,0xF0C0000,0xFC0001,0xFC0001,0x1280000,0x33C0000,0x1580000,0x1580000,0x1AC0000,0x1280000,0x33C0000,0xFFC0000,0x41FC0000,
+0xFFC0000,0x1100001,0x1100001,0x1100001,0x1100001,0x1980000,0x1980000,0x1980000,0x51F80000,0x51F80000,0x88000000,0x1980000,0x1980000,0x1980000,0x51F80000,0x51F80000,0x88000000,0x51F80000,0x51F80000,0x88000000,0x88000000,0x1980000,0x1980000,0x1980000,0x51F80000,0x51F80000,0x88000000,0x51F80000,0x51F80000,0x88000000,0x88000000,0x51F80000,
+0x51F80000,0x88000000,0x88000000,0x88000000,0x73C0000,0x1240000,0x1100001,0x1740000,0x1CC0000,0x21FC0000,0x39FC0000,0x5FF80000,0x1580000,0x1980000,0x21FC0000,0x88000000,0x21FC0000,0x1280001,0x1BC0000,0x61FC0000,0x94000000,0x1BC0000,0x61FC0000,0x94000000,0x61FC0000,0x94000000,0x94000000,0x1BC0000,0x61FC0000,0x94000000,0x61FC0000,0x94000000,
+0x94000000,0x61FC0000,0x94000000,0x94000000,0x94000000,0x1BC0000,0x61FC0000,0x94000000,0x61FC0000,0x94000000,0x94000000,0x61FC0000,0x94000000,0x94000000,0x94000000,0x61FC0000,0x94000000,0x94000000,0x94000000,0x94000000,0x3740000,0x73C0000,0x73C0000,0x1F40000,0x4DFC0000,0x7BF40000,0x94000000,0x94000000,0x1940000,0x1DFC0000,0x8FD00000,0x94000000,
+0x39FC0000,0x1080274,0xC2FC00F3,0x9EFC00F4,0x94FC00F3,0xB8F40092,0xA0F4004F,0x96F40067,0x98F40092,0x94F0004E,0x8EF00092,0xB6E800F4,0xA4E80033,0x96EC0051,0x9CE4004A,0x94E80002,0x8EE8004D,0x94E400F4,0x90E00053,0x8CE00069,0x88E400F5,0x1880274,0xAAD000F3,0x94E800F4,0xA0CC0092,0x94D80049,0x8EDC0090,0x9EBC00F3,0x94C40032,0x8EC4004D,0x88D000F4,0x49F80274,
+0x949C00F3,0x8E980090,0x888C00F4,0x82000278,0xFEEC0012,0xF9000154,0xFB040194,0xC2E80002,0xAAE80002,0x9CE80002,0x94E80006,0x92E40006,0xFCD80009,0xC0DC0000,0x96E00035,0x8EC4004D,0x19FC0274,0x11400F3,0xB7080032,0x9D080032,0x95080032,0xAD000049,0x9EFC0002,0x95000005,0x96FC0049,0x92FC000E,0x8EFC0049,0x39800F3,0xA4E80032,0x94F80032,0x9CE40049,0x94E80001,
+0x8EEC0049,0x51FC00F3,0x94C00032,0x8EBC0048,0x880000F4,0x39800F3,0xA4E80032,0x94F80032,0x9CE40049,0x94E80001,0x8EEC0049,0x51FC00F3,0x94C00032,0x8EBC0048,0x880000F4,0x51FC00F3,0x94C00032,0x8EBC0048,0x880000F4,0x880000F4,0xFAF00006,0xFD080073,0xFF0C006B,0xC2E80001,0xAAE80001,0x9CE80001,0x94F00001,0x94E00004,0xFCD80005,0xC0DC0000,0x96DC0033,0x8EBC0048,
+0x23FC00F3,0xFC00F3,0xFC00F3,0xFC00F3,0xFC00F3,0xA6F4004A,0xA6F4004A,0xA6F4004A,0x90F0004A,0x90F0004A,0x88F0004A,0xA4E80033,0xA4E80033,0xA4E80033,0x92E80002,0x92E80002,0x8AE8000E,0x8CE40033,0x8CE40033,0x88E40005,0x82E40035,0x37400F3,0x37400F3,0x37400F3,0x94D80049,0x94D80049,0x88E0004A,0x92C80032,0x92C80032,0x88D00001,0x84D40034,0x3FFC00F3,
+0x3FFC00F3,0x88B00048,0x82A40034,0x7E0000F4,0xFEE80006,0xF4F80073,0xFC00F3,0xC2E80001,0xA6E80002,0x9AE80002,0x98E80003,0x90E40001,0xFCD40001,0xC0DC0000,0x92E40033,0x88D00001,0xDFC00F3,0x1080032,0x1080032,0x1080032,0x1080032,0x9B000001,0x9B000001,0x9B000001,0x8D000001,0x8D000001,0x88FC0001,0x1880032,0x1880032,0x1880032,0x90EC0001,0x90EC0001,
+0x88F40000,0x49F80032,0x49F80032,0x88D40000,0x82000034,0x1880032,0x1880032,0x1880032,0x90EC0001,0x90EC0001,0x88F40000,0x49F80032,0x49F80032,0x88D40000,0x82000034,0x49F80032,0x49F80032,0x88D40000,0x82000034,0x82000034,0xEEF00000,0xF9000002,0x1080032,0xC2E80000,0xA0F00001,0x98EC0000,0x92F00001,0x90E40000,0xF0DC0001,0xBAE00000,0x19FC0032,0x88D40000,
+0x19FC0032,0x11C004A,0xAB140001,0x9B100001,0x95100001,0x1A80048,0x9EFC0001,0x95040001,0x59FC0048,0x94E00000,0x8E000048,0x1A80048,0x9EFC0001,0x95040001,0x59FC0048,0x94E00000,0x8E000048,0x59FC0048,0x94E00000,0x8E000048,0x8E000048,0x1A80048,0x9EFC0001,0x95040001,0x59FC0048,0x94E00000,0x8E000048,0x59FC0048,0x94E00000,0x8E000048,0x8E000048,0x59FC0048,
+0x94E00000,0x8E000048,0x8E000048,0x8E000048,0xFAF00005,0x1300048,0xF518000D,0xC6E40000,0xAAE40001,0x9EE00000,0x94F00000,0x94CC0000,0xFCD80004,0xC0DC0000,0x96F40000,0x8E000048,0x2DFC0048,0xF0004A,0xF0004A,0xF0004A,0xF0004A,0xF0004A,0xF0004A,0xF0004A,0xF0004A,0xF0004A,0xF0004A,0x94E80001,0x94E80001,0x94E80001,0x94E80001,0x94E80001,
+0x94E80001,0x84E40001,0x84E40001,0x84E40001,0x7EE40001,0x1680048,0x1680048,0x1680048,0x1680048,0x1680048,0x1680048,0x88D00001,0x88D00001,0x88D00001,0x7ED80001,0x39F80048,0x39F80048,0x39F80048,0x7EB40000,0x78000048,0xFCE80005,0xF0004A,0xF0004A,0xBEE80001,0xA8E80001,0x9CE80001,0x9CE80001,0x8EE80001,0xFCD40000,0xC0DC0000,0x88E40001,0x88D00001,
+0x3FC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table49[] = {
+0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x3BFC0000,
+0x3BFC0000,0x3BFC0000,0x3BFC0000,0x7A000000,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xB040000,0xB040000,0xB040000,0x16C0000,0x7FC0000,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,
+0x1900000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x86000000,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x86000000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x86000000,0x86000000,0x1200000,0x10C0001,0x10C0001,0x5380000,0x5500000,0x1700000,0x1700000,0x1C40000,0x5380000,0x5500000,0x1FF80000,0x4DFC0000,
+0x1FF80000,0x1200001,0x1200001,0x1200001,0x1200001,0x1B00000,0x1B00000,0x1B00000,0x5DF40000,0x5DF40000,0x90000000,0x1B00000,0x1B00000,0x1B00000,0x5DF40000,0x5DF40000,0x90000000,0x5DF40000,0x5DF40000,0x90000000,0x90000000,0x1B00000,0x1B00000,0x1B00000,0x5DF40000,0x5DF40000,0x90000000,0x5DF40000,0x5DF40000,0x90000000,0x90000000,0x5DF40000,
+0x5DF40000,0x90000000,0x90000000,0x90000000,0x1500000,0x3340000,0x1200001,0x3880000,0x1E80000,0x31FC0000,0x47F80000,0x69FC0000,0x16C0000,0x1B00000,0x31FC0000,0x90000000,0x31FC0000,0x1380001,0x3D00000,0x6DFC0000,0x9C000000,0x3D00000,0x6DFC0000,0x9C000000,0x6DFC0000,0x9C000000,0x9C000000,0x3D00000,0x6DFC0000,0x9C000000,0x6DFC0000,0x9C000000,
+0x9C000000,0x6DFC0000,0x9C000000,0x9C000000,0x9C000000,0x3D00000,0x6DFC0000,0x9C000000,0x6DFC0000,0x9C000000,0x9C000000,0x6DFC0000,0x9C000000,0x9C000000,0x9C000000,0x6DFC0000,0x9C000000,0x9C000000,0x9C000000,0x9C000000,0x3880000,0xF4C0000,0xF4C0000,0xFFC0000,0x5BFC0000,0x85F40000,0x9C000000,0x9C000000,0x1AC0000,0x2FFC0000,0x97E00000,0x9C000000,
+0x47FC0000,0x1180274,0xCB0C00F3,0xA70C00F4,0x9D0C00F3,0xC1040092,0xA904004F,0x9F040067,0xA1040092,0x9D00004E,0x97000092,0xBEF800F4,0xACF80033,0x9EFC0051,0xA4F4004A,0x9CF80002,0x96F8004D,0x9CF400F4,0x98F00053,0x94F00069,0x90F400F5,0x1A00274,0xB2E000F3,0x9CF800F4,0xA8DC0092,0x9CE80049,0x96EC0090,0xA6CC00F3,0x9CD40032,0x96D4004D,0x90E000F4,0x55F80274,
+0x9CAC00F3,0x96A80090,0x909C00F4,0x8A000278,0xFCFC0024,0xFF0C0164,0xF31401AB,0xCAF80002,0xB2F80002,0xA4F80002,0x9CF80006,0x9AF40006,0xFCEC0016,0xC8EC0000,0x9EF00035,0x96D4004D,0x27FC0274,0x12400F3,0xBF180032,0xA5180032,0x9D180032,0xB5100049,0xA70C0002,0x9D100005,0x9F0C0049,0x9B0C000E,0x970C0049,0x3B000F3,0xACF80032,0x9D080032,0xA4F40049,0x9CF80001,
+0x96FC0049,0x5DFC00F3,0x9CD00032,0x96CC0048,0x900000F4,0x3B000F3,0xACF80032,0x9D080032,0xA4F40049,0x9CF80001,0x96FC0049,0x5DFC00F3,0x9CD00032,0x96CC0048,0x900000F4,0x5DFC00F3,0x9CD00032,0x96CC0048,0x900000F4,0x900000F4,0xFF00000B,0xF5180081,0xF9200076,0xCAF80001,0xB2F80001,0xA4F80001,0x9D000001,0x9CF00004,0xFCEC000D,0xC8EC0000,0x9EEC0033,0x96CC0048,
+0x33FC00F3,0x10C00F3,0x10C00F3,0x10C00F3,0x10C00F3,0xAF04004A,0xAF04004A,0xAF04004A,0x9900004A,0x9900004A,0x9100004A,0xACF80033,0xACF80033,0xACF80033,0x9AF80002,0x9AF80002,0x92F8000E,0x94F40033,0x94F40033,0x90F40005,0x8AF40035,0x38C00F3,0x38C00F3,0x38C00F3,0x9CE80049,0x9CE80049,0x90F0004A,0x9AD80032,0x9AD80032,0x90E00001,0x8CE40034,0x4BFC00F3,
+0x4BFC00F3,0x90C00048,0x8AB40034,0x860000F4,0xFAFC000B,0xFD080073,0x10C00F3,0xCAF80001,0xAEF80002,0xA2F80002,0xA0F80003,0x98F40001,0xF8E80005,0xC8EC0000,0x9AF40033,0x90E00001,0x1DF800F3,0x1180032,0x1180032,0x1180032,0x1180032,0xA3100001,0xA3100001,0xA3100001,0x95100001,0x95100001,0x910C0001,0x1A00032,0x1A00032,0x1A00032,0x98FC0001,0x98FC0001,
+0x91040000,0x55F80032,0x55F80032,0x90E40000,0x8A000034,0x1A00032,0x1A00032,0x1A00032,0x98FC0001,0x98FC0001,0x91040000,0x55F80032,0x55F80032,0x90E40000,0x8A000034,0x55F80032,0x55F80032,0x90E40000,0x8A000034,0x8A000034,0xF7000000,0xF1100005,0x1180032,0xCAF80000,0xA9000001,0xA0FC0000,0x9B000001,0x98F40000,0xF8EC0001,0xC2F00000,0x27FC0032,0x90E40000,
+0x27FC0032,0x12C004A,0xB3240001,0xA3200001,0x9D200001,0x1C00048,0xA70C0001,0x9D140001,0x65F80048,0x9CF00000,0x96000048,0x1C00048,0xA70C0001,0x9D140001,0x65F80048,0x9CF00000,0x96000048,0x65F80048,0x9CF00000,0x96000048,0x96000048,0x1C00048,0xA70C0001,0x9D140001,0x65F80048,0x9CF00000,0x96000048,0x65F80048,0x9CF00000,0x96000048,0x96000048,0x65F80048,
+0x9CF00000,0x96000048,0x96000048,0x96000048,0xFB040008,0x9400048,0xFD28000D,0xCEF40000,0xB2F40001,0xA6F00000,0x9D000000,0x9CDC0000,0xFEF00005,0xC8EC0000,0x9F040000,0x96000048,0x3DF80048,0x100004A,0x100004A,0x100004A,0x100004A,0x100004A,0x100004A,0x100004A,0x100004A,0x100004A,0x100004A,0x9CF80001,0x9CF80001,0x9CF80001,0x9CF80001,0x9CF80001,
+0x9CF80001,0x8CF40001,0x8CF40001,0x8CF40001,0x86F40001,0x1800048,0x1800048,0x1800048,0x1800048,0x1800048,0x1800048,0x90E00001,0x90E00001,0x90E00001,0x86E80001,0x45F80048,0x45F80048,0x45F80048,0x86C40000,0x80000048,0xF4F8000A,0x100004A,0x100004A,0xC6F80001,0xB0F80001,0xA4F80001,0xA4F80001,0x96F80001,0xF8E80001,0xC8EC0000,0x90F40001,0x90E00001,
+0x13FC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table50[] = {
+0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x47FC0000,
+0x47FC0000,0x47FC0000,0x47FC0000,0x82000000,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1180000,0x1180000,0x1180000,0x1840000,0x17FC0000,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,
+0x1A80000,0x59FC0000,0x59FC0000,0x59FC0000,0x8E000000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x59FC0000,0x59FC0000,0x59FC0000,0x8E000000,0x59FC0000,0x59FC0000,0x59FC0000,0x8E000000,0x8E000000,0x1300000,0x11C0001,0x11C0001,0x14C0000,0x5640000,0x1840000,0x1840000,0x1E00000,0x14C0000,0x5640000,0x2DFC0000,0x59FC0000,
+0x2DFC0000,0x1300001,0x1300001,0x1300001,0x1300001,0x3C40000,0x3C40000,0x3C40000,0x67FC0000,0x67FC0000,0x98000000,0x3C40000,0x3C40000,0x3C40000,0x67FC0000,0x67FC0000,0x98000000,0x67FC0000,0x67FC0000,0x98000000,0x98000000,0x3C40000,0x3C40000,0x3C40000,0x67FC0000,0x67FC0000,0x98000000,0x67FC0000,0x67FC0000,0x98000000,0x98000000,0x67FC0000,
+0x67FC0000,0x98000000,0x98000000,0x98000000,0x1640000,0xB440000,0x1300001,0x1A00000,0x5FC0000,0x3FFC0000,0x55F80000,0x75F80000,0x1800000,0x3C40000,0x3FFC0000,0x98000000,0x3FFC0000,0x1480001,0x3E80000,0x79FC0000,0xA4000000,0x3E80000,0x79FC0000,0xA4000000,0x79FC0000,0xA4000000,0xA4000000,0x3E80000,0x79FC0000,0xA4000000,0x79FC0000,0xA4000000,
+0xA4000000,0x79FC0000,0xA4000000,0xA4000000,0xA4000000,0x3E80000,0x79FC0000,0xA4000000,0x79FC0000,0xA4000000,0xA4000000,0x79FC0000,0xA4000000,0xA4000000,0xA4000000,0x79FC0000,0xA4000000,0xA4000000,0xA4000000,0xA4000000,0x39C0000,0x1600000,0x1600000,0x23FC0000,0x69F80000,0x8FF40000,0xA4000000,0xA4000000,0x1C00000,0x41FC0000,0x9FF00000,0xA4000000,
+0x57FC0000,0x1280274,0xD31C00F3,0xAF1C00F4,0xA51C00F3,0xC9140092,0xB114004F,0xA7140067,0xA9140092,0xA510004E,0x9F100092,0xC70800F4,0xB5080033,0xA70C0051,0xAD04004A,0xA5080002,0x9F08004D,0xA50400F4,0xA1000053,0x9D000069,0x990400F5,0x1B80274,0xBAF000F3,0xA50800F4,0xB0EC0092,0xA4F80049,0x9EFC0090,0xAEDC00F3,0xA4E40032,0x9EE4004D,0x98F000F4,0x61F80274,
+0xA4BC00F3,0x9EB80090,0x98AC00F4,0x92000278,0xFF0C0032,0xF9200172,0xFB2401AB,0xD3080002,0xBB080002,0xAD080002,0xA5080006,0xA3040006,0xFCFC0024,0xD0FC0000,0xA7000035,0x9EE4004D,0x37FC0274,0x13400F3,0xC7280032,0xAD280032,0xA5280032,0xBD200049,0xAF1C0002,0xA5200005,0xA71C0049,0xA31C000E,0x9F1C0049,0x1C800F3,0xB5080032,0xA5180032,0xAD040049,0xA5080001,
+0x9F0C0049,0x69FC00F3,0xA4E00032,0x9EDC0048,0x980000F4,0x1C800F3,0xB5080032,0xA5180032,0xAD040049,0xA5080001,0x9F0C0049,0x69FC00F3,0xA4E00032,0x9EDC0048,0x980000F4,0x69FC00F3,0xA4E00032,0x9EDC0048,0x980000F4,0x980000F4,0xFF14000E,0xFD280081,0xFF2C007A,0xD3080001,0xBB080001,0xAD080001,0xA5100001,0xA5000004,0xFF000013,0xD0FC0000,0xA6FC0033,0x9EDC0048,
+0x41FC00F3,0x11C00F3,0x11C00F3,0x11C00F3,0x11C00F3,0xB714004A,0xB714004A,0xB714004A,0xA110004A,0xA110004A,0x9910004A,0xB5080033,0xB5080033,0xB5080033,0xA3080002,0xA3080002,0x9B08000E,0x9D040033,0x9D040033,0x99040005,0x93040035,0x3A400F3,0x3A400F3,0x3A400F3,0xA4F80049,0xA4F80049,0x9900004A,0xA2E80032,0xA2E80032,0x98F00001,0x94F40034,0x57FC00F3,
+0x57FC00F3,0x98D00048,0x92C40034,0x8E0000F4,0xFF0C000E,0xF518007E,0x11C00F3,0xD3080001,0xB7080002,0xAB080002,0xA9080003,0xA1040001,0xFEF80006,0xD0FC0000,0xA3040033,0x98F00001,0x2BFC00F3,0x1280032,0x1280032,0x1280032,0x1280032,0xAB200001,0xAB200001,0xAB200001,0x9D200001,0x9D200001,0x991C0001,0x1B80032,0x1B80032,0x1B80032,0xA10C0001,0xA10C0001,
+0x99140000,0x61F80032,0x61F80032,0x98F40000,0x92000034,0x1B80032,0x1B80032,0x1B80032,0xA10C0001,0xA10C0001,0x99140000,0x61F80032,0x61F80032,0x98F40000,0x92000034,0x61F80032,0x61F80032,0x98F40000,0x92000034,0x92000034,0xFF100000,0xF9200005,0x1280032,0xD3080000,0xB1100001,0xA90C0000,0xA3100001,0xA1040000,0xF5000002,0xCB000000,0x37FC0032,0x98F40000,
+0x37FC0032,0x13C004A,0xBB340001,0xAB300001,0xA5300001,0x1D80048,0xAF1C0001,0xA5240001,0x71F80048,0xA5000000,0x9E000048,0x1D80048,0xAF1C0001,0xA5240001,0x71F80048,0xA5000000,0x9E000048,0x71F80048,0xA5000000,0x9E000048,0x9E000048,0x1D80048,0xAF1C0001,0xA5240001,0x71F80048,0xA5000000,0x9E000048,0x71F80048,0xA5000000,0x9E000048,0x9E000048,0x71F80048,
+0xA5000000,0x9E000048,0x9E000048,0x9E000048,0xFF14000A,0x1540048,0xF5380012,0xD7040000,0xBB040001,0xAF000000,0xA5100000,0xA4EC0000,0xF7080008,0xD0FC0000,0xA7140000,0x9E000048,0x4BFC0048,0x110004A,0x110004A,0x110004A,0x110004A,0x110004A,0x110004A,0x110004A,0x110004A,0x110004A,0x110004A,0xA5080001,0xA5080001,0xA5080001,0xA5080001,0xA5080001,
+0xA5080001,0x95040001,0x95040001,0x95040001,0x8F040001,0x1980048,0x1980048,0x1980048,0x1980048,0x1980048,0x1980048,0x98F00001,0x98F00001,0x98F00001,0x8EF80001,0x51F80048,0x51F80048,0x51F80048,0x8ED40000,0x88000048,0xFD08000A,0x110004A,0x110004A,0xCF080001,0xB9080001,0xAD080001,0xAD080001,0x9F080001,0xF8F80002,0xD0FC0000,0x99040001,0x98F00001,
+0x21FC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table51[] = {
+0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x53FC0000,
+0x53FC0000,0x53FC0000,0x53FC0000,0x8A000000,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1280000,0x1280000,0x1280000,0x19C0000,0x25FC0000,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,
+0x1C00000,0x65F80000,0x65F80000,0x65F80000,0x96000000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x65F80000,0x65F80000,0x65F80000,0x96000000,0x65F80000,0x65F80000,0x65F80000,0x96000000,0x96000000,0x9400000,0x12C0001,0x12C0001,0x1600000,0x5780000,0x3980000,0x3980000,0x1FC0000,0x1600000,0x5780000,0x3DF80000,0x65F80000,
+0x3DF80000,0x1400001,0x1400001,0x1400001,0x1400001,0x3DC0000,0x3DC0000,0x3DC0000,0x73FC0000,0x73FC0000,0xA0000000,0x3DC0000,0x3DC0000,0x3DC0000,0x73FC0000,0x73FC0000,0xA0000000,0x73FC0000,0x73FC0000,0xA0000000,0xA0000000,0x3DC0000,0x3DC0000,0x3DC0000,0x73FC0000,0x73FC0000,0xA0000000,0x73FC0000,0x73FC0000,0xA0000000,0xA0000000,0x73FC0000,
+0x73FC0000,0xA0000000,0xA0000000,0xA0000000,0x5740000,0x1580000,0x1400001,0x3B40000,0x19FC0000,0x4FFC0000,0x61FC0000,0x7FFC0000,0x1940000,0x3DC0000,0x4FFC0000,0xA0000000,0x4FFC0000,0x1580001,0x7FC0000,0x85FC0000,0xAC000000,0x7FC0000,0x85FC0000,0xAC000000,0x85FC0000,0xAC000000,0xAC000000,0x7FC0000,0x85FC0000,0xAC000000,0x85FC0000,0xAC000000,
+0xAC000000,0x85FC0000,0xAC000000,0xAC000000,0xAC000000,0x7FC0000,0x85FC0000,0xAC000000,0x85FC0000,0xAC000000,0xAC000000,0x85FC0000,0xAC000000,0xAC000000,0xAC000000,0x85FC0000,0xAC000000,0xAC000000,0xAC000000,0xAC000000,0x3B00000,0x1700000,0x1700000,0x37FC0000,0x75FC0000,0x99F40000,0xAC000000,0xAC000000,0x3D40000,0x51FC0000,0xA9C40000,0xAC000000,
+0x65FC0000,0x1380274,0xDB2C00F3,0xB72C00F4,0xAD2C00F3,0xD1240092,0xB924004F,0xAF240067,0xB1240092,0xAD20004E,0xA7200092,0xCF1800F4,0xBD180033,0xAF1C0051,0xB514004A,0xAD180002,0xA718004D,0xAD1400F4,0xA9100053,0xA5100069,0xA11400F5,0x1D00274,0xC30000F3,0xAD1800F4,0xB8FC0092,0xAD080049,0xA70C0090,0xB6EC00F3,0xACF40032,0xA6F4004D,0xA10000F4,0x6DF80274,
+0xACCC00F3,0xA6C80090,0xA0BC00F4,0x9A000278,0xFF20003E,0xFF2C018A,0xF33401C4,0xDB180002,0xC3180002,0xB5180002,0xAD180006,0xAB140006,0xFF10002E,0xD90C0000,0xAF100035,0xA6F4004D,0x45FC0274,0x14400F3,0xCF380032,0xB5380032,0xAD380032,0xC5300049,0xB72C0002,0xAD300005,0xAF2C0049,0xAB2C000E,0xA72C0049,0x1E000F3,0xBD180032,0xAD280032,0xB5140049,0xAD180001,
+0xA71C0049,0x75FC00F3,0xACF00032,0xA6EC0048,0xA00000F4,0x1E000F3,0xBD180032,0xAD280032,0xB5140049,0xAD180001,0xA71C0049,0x75FC00F3,0xACF00032,0xA6EC0048,0xA00000F4,0x75FC00F3,0xACF00032,0xA6EC0048,0xA00000F4,0xA00000F4,0xF928001A,0xF73C008B,0xF9400083,0xDB180001,0xC3180001,0xB5180001,0xAD200001,0xAD100004,0xFD140019,0xD90C0000,0xAF0C0033,0xA6EC0048,
+0x51FC00F3,0x12C00F3,0x12C00F3,0x12C00F3,0x12C00F3,0xBF24004A,0xBF24004A,0xBF24004A,0xA920004A,0xA920004A,0xA120004A,0xBD180033,0xBD180033,0xBD180033,0xAB180002,0xAB180002,0xA318000E,0xA5140033,0xA5140033,0xA1140005,0x9B140035,0x3BC00F3,0x3BC00F3,0x3BC00F3,0xAD080049,0xAD080049,0xA110004A,0xAAF80032,0xAAF80032,0xA1000001,0x9D040034,0x63FC00F3,
+0x63FC00F3,0xA0E00048,0x9AD40034,0x960000F4,0xFD1C0016,0xFD28007E,0x12C00F3,0xDB180001,0xBF180002,0xB3180002,0xB1180003,0xA9140001,0xFD0C000D,0xD90C0000,0xAB140033,0xA1000001,0x3BFC00F3,0x1380032,0x1380032,0x1380032,0x1380032,0xB3300001,0xB3300001,0xB3300001,0xA5300001,0xA5300001,0xA12C0001,0x1D00032,0x1D00032,0x1D00032,0xA91C0001,0xA91C0001,
+0xA1240000,0x6DF80032,0x6DF80032,0xA1040000,0x9A000034,0x1D00032,0x1D00032,0x1D00032,0xA91C0001,0xA91C0001,0xA1240000,0x6DF80032,0x6DF80032,0xA1040000,0x9A000034,0x6DF80032,0x6DF80032,0xA1040000,0x9A000034,0x9A000034,0xFF200001,0xF130000A,0x1380032,0xDB180000,0xB9200001,0xB11C0000,0xAB200001,0xA9140000,0xFD100002,0xD3100000,0x45FC0032,0xA1040000,
+0x45FC0032,0x14C004A,0xC3440001,0xB3400001,0xAD400001,0x1F00048,0xB72C0001,0xAD340001,0x7DF80048,0xAD100000,0xA6000048,0x1F00048,0xB72C0001,0xAD340001,0x7DF80048,0xAD100000,0xA6000048,0x7DF80048,0xAD100000,0xA6000048,0xA6000048,0x1F00048,0xB72C0001,0xAD340001,0x7DF80048,0xAD100000,0xA6000048,0x7DF80048,0xAD100000,0xA6000048,0xA6000048,0x7DF80048,
+0xAD100000,0xA6000048,0xA6000048,0xA6000048,0xFB2C000D,0x1640048,0xFD480012,0xDF140000,0xC3140001,0xB7100000,0xAD200000,0xACFC0000,0xFF180008,0xD90C0000,0xAF240000,0xA6000048,0x5BFC0048,0x120004A,0x120004A,0x120004A,0x120004A,0x120004A,0x120004A,0x120004A,0x120004A,0x120004A,0x120004A,0xAD180001,0xAD180001,0xAD180001,0xAD180001,0xAD180001,
+0xAD180001,0x9D140001,0x9D140001,0x9D140001,0x97140001,0x1B00048,0x1B00048,0x1B00048,0x1B00048,0x1B00048,0x1B00048,0xA1000001,0xA1000001,0xA1000001,0x97080001,0x5DF40048,0x5DF40048,0x5DF40048,0x96E40000,0x90000048,0xF71C000D,0x120004A,0x120004A,0xD7180001,0xC1180001,0xB5180001,0xB5180001,0xA7180001,0xFB080004,0xD90C0000,0xA1140001,0xA1000001,
+0x31FC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table52[] = {
+0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x61F80000,
+0x61F80000,0x61F80000,0x61F80000,0x92000001,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x13C0000,0x13C0000,0x13C0000,0x1B80000,0x37FC0000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,
+0x1DC0000,0x73F80000,0x73F80000,0x73F80000,0x9E000001,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x73F80000,0x73F80000,0x73F80000,0x9E000001,0x73F80000,0x73F80000,0x73F80000,0x9E000001,0x9E000001,0x3540000,0x1400000,0x1400000,0x1740000,0x1900000,0x1B40000,0x1B40000,0x17FC0000,0x1740000,0x1900000,0x4DFC0000,0x73F80000,
+0x4DFC0000,0x1540000,0x1540000,0x1540000,0x1540000,0x1F80000,0x1F80000,0x1F80000,0x81FC0000,0x81FC0000,0xA8000001,0x1F80000,0x1F80000,0x1F80000,0x81FC0000,0x81FC0000,0xA8000001,0x81FC0000,0x81FC0000,0xA8000001,0xA8000001,0x1F80000,0x1F80000,0x1F80000,0x81FC0000,0x81FC0000,0xA8000001,0x81FC0000,0x81FC0000,0xA8000001,0xA8000001,0x81FC0000,
+0x81FC0000,0xA8000001,0xA8000001,0xA8000001,0x18C0000,0xD680000,0x1540000,0x3CC0000,0x2FFC0000,0x5FFC0000,0x71FC0000,0x8BFC0000,0x3A80000,0x1F80000,0x5FFC0000,0xA8000001,0x5FFC0000,0x16C0000,0x23FC0000,0x93FC0000,0xB4000001,0x23FC0000,0x93FC0000,0xB4000001,0x93FC0000,0xB4000001,0xB4000001,0x23FC0000,0x93FC0000,0xB4000001,0x93FC0000,0xB4000001,
+0xB4000001,0x93FC0000,0xB4000001,0xB4000001,0xB4000001,0x23FC0000,0x93FC0000,0xB4000001,0x93FC0000,0xB4000001,0xB4000001,0x93FC0000,0xB4000001,0xB4000001,0xB4000001,0x93FC0000,0xB4000001,0xB4000001,0xB4000001,0xB4000001,0x1C80000,0x1840000,0x1840000,0x4DFC0000,0x85FC0000,0xA5F00000,0xB4000001,0xB4000001,0x1F00000,0x65FC0000,0xB1F40000,0xB4000001,
+0x77FC0000,0x1480278,0xE34000F4,0xC14000F4,0xB54000F5,0xDD340090,0xC534004D,0xB9380069,0xBB340090,0xB534004D,0xAF340092,0xD92800F3,0xC7280032,0xB9300053,0xBD280049,0xB5280002,0xB128004E,0xB52800F4,0xB3240051,0xAF240067,0xAB2800F3,0x3E80274,0xCB1400F3,0xB52800F4,0xC30C0092,0xB718004A,0xAF200092,0xC0FC00F3,0xB5080033,0xAF08004F,0xAB1000F4,0x79FC0274,
+0xB4E400F4,0xAEDC0092,0xAAC800F3,0xA4000274,0xFF340059,0xFB440190,0xFD4801C4,0xE7280000,0xCD280001,0xBD280002,0xB72C0006,0xB5280006,0xFF24004F,0xDF200002,0xB7240035,0xAF08004F,0x57FC0274,0x15400F4,0xD74C0034,0xBF480034,0xB5480035,0xD1400048,0xBF400001,0xB7400005,0xB740004A,0xB53C000E,0xAF40004A,0x1FC00F3,0xC52C0032,0xB7380033,0xBD280049,0xB5280002,
+0xAF30004A,0x83F800F3,0xB5080033,0xAF00004A,0xAA0000F3,0x1FC00F3,0xC52C0032,0xB7380033,0xBD280049,0xB5280002,0xAF30004A,0x83F800F3,0xB5080033,0xAF00004A,0xAA0000F3,0x83F800F3,0xB5080033,0xAF00004A,0xAA0000F3,0xAA0000F3,0xFF3C0024,0xFF4C008C,0xF1500095,0xE7280000,0xCD280001,0xBD280002,0xB7300001,0xB5200003,0xFB2C002A,0xDF200001,0xB91C0032,0xAF00004A,
+0x61FC00F3,0x14000F4,0x14000F4,0x14000F4,0x14000F4,0xCB340048,0xCB340048,0xCB340048,0xB1340049,0xB1340049,0xA9340049,0xC7280032,0xC7280032,0xC7280032,0xB5280001,0xB5280001,0xAB2C000E,0xAD280032,0xAD280032,0xA9280005,0xA5280032,0x1D800F3,0x1D800F3,0x1D800F3,0xB7180049,0xB7180049,0xA9240049,0xB5080032,0xB5080032,0xA9140002,0xA5180032,0x71F800F3,
+0x71F800F3,0xA8F40049,0xA4E00032,0x9E0000F3,0xF9300024,0xF73C008C,0x14000F4,0xE7280000,0xC9280001,0xBD280001,0xB9280004,0xB1280001,0xFF200012,0xDF200001,0xB5240032,0xA9140002,0x4BFC00F3,0x1480034,0x1480034,0x1480034,0x1480034,0xBD400000,0xBD400000,0xBD400000,0xAF400000,0xAF400000,0xA9400001,0x3E80032,0x3E80032,0x3E80032,0xB1300001,0xB1300001,
+0xA9380001,0x79FC0032,0x79FC0032,0xA91C0001,0xA4000032,0x3E80032,0x3E80032,0x3E80032,0xB1300001,0xB1300001,0xA9380001,0x79FC0032,0x79FC0032,0xA91C0001,0xA4000032,0x79FC0032,0x79FC0032,0xA91C0001,0xA4000032,0xA4000032,0xFB340004,0xFB440008,0x1480034,0xE7280000,0xC72C0000,0xBB2C0000,0xB7300000,0xB1280001,0xF9280005,0xDF200000,0x57FC0032,0xA91C0001,
+0x57FC0032,0x1600048,0xCF540000,0xBB540001,0xB5540001,0xFFC0048,0xBF400001,0xB5480001,0x8BF80048,0xB5240001,0xAE00004A,0xFFC0048,0xBF400001,0xB5480001,0x8BF80048,0xB5240001,0xAE00004A,0x8BF80048,0xB5240001,0xAE00004A,0xAE00004A,0xFFC0048,0xBF400001,0xB5480001,0x8BF80048,0xB5240001,0xAE00004A,0x8BF80048,0xB5240001,0xAE00004A,0xAE00004A,0x8BF80048,
+0xB5240001,0xAE00004A,0xAE00004A,0xAE00004A,0xFD400012,0x1780048,0xF75C0019,0xE7280000,0xCB280001,0xBF240000,0xB5340001,0xB5140001,0xFF2C0011,0xE31C0000,0xB7380001,0xAE00004A,0x6BFC0048,0x1340048,0x1340048,0x1340048,0x1340048,0x1340048,0x1340048,0x1340048,0x1340048,0x1340048,0x1340048,0xB9280000,0xB9280000,0xB9280000,0xB9280000,0xB9280000,
+0xB9280000,0xA5280001,0xA5280001,0xA5280001,0x9F280001,0x1C80048,0x1C80048,0x1C80048,0x1C80048,0x1C80048,0x1C80048,0xA9140001,0xA9140001,0xA9140001,0x9F1C0001,0x69FC0048,0x69FC0048,0x69FC0048,0x9EF80001,0x9800004A,0xFF2C000D,0x1340048,0x1340048,0xE7280000,0xCD280000,0xC1280000,0xC1280000,0xB1280000,0xFD1C0005,0xE71C0000,0xAD240000,0xA9140001,
+0x41FC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table53[] = {
+0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x6DF80000,
+0x6DF80000,0x6DF80000,0x6DF80000,0x9A000001,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x14C0000,0x14C0000,0x14C0000,0x1D00000,0x45FC0000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,
+0x1F40000,0x7FF80000,0x7FF80000,0x7FF80000,0xA6000001,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x7FF80000,0x7FF80000,0x7FF80000,0xA6000001,0x7FF80000,0x7FF80000,0x7FF80000,0xA6000001,0xA6000001,0xB640000,0x1500000,0x1500000,0x7840000,0x1A40000,0x1C80000,0x1C80000,0x2BFC0000,0x7840000,0x1A40000,0x5DF80000,0x7FF80000,
+0x5DF80000,0x1640000,0x1640000,0x1640000,0x1640000,0x15FC0000,0x15FC0000,0x15FC0000,0x8DFC0000,0x8DFC0000,0xB0000001,0x15FC0000,0x15FC0000,0x15FC0000,0x8DFC0000,0x8DFC0000,0xB0000001,0x8DFC0000,0x8DFC0000,0xB0000001,0xB0000001,0x15FC0000,0x15FC0000,0x15FC0000,0x8DFC0000,0x8DFC0000,0xB0000001,0x8DFC0000,0x8DFC0000,0xB0000001,0xB0000001,0x8DFC0000,
+0x8DFC0000,0xB0000001,0xB0000001,0xB0000001,0x59C0000,0x17C0000,0x1640000,0x1E40000,0x43FC0000,0x6FFC0000,0x7FF80000,0x97F80000,0x3BC0000,0x15FC0000,0x6FFC0000,0xB0000001,0x6FFC0000,0x17C0000,0x3BFC0000,0x9FF80000,0xBC000001,0x3BFC0000,0x9FF80000,0xBC000001,0x9FF80000,0xBC000001,0xBC000001,0x3BFC0000,0x9FF80000,0xBC000001,0x9FF80000,0xBC000001,
+0xBC000001,0x9FF80000,0xBC000001,0xBC000001,0xBC000001,0x3BFC0000,0x9FF80000,0xBC000001,0x9FF80000,0xBC000001,0xBC000001,0x9FF80000,0xBC000001,0xBC000001,0xBC000001,0x9FF80000,0xBC000001,0xBC000001,0xBC000001,0xBC000001,0x1DC0000,0x3940000,0x3940000,0x61FC0000,0x93F80000,0xAFF00000,0xBC000001,0xBC000001,0xDFC0000,0x75FC0000,0xBBC80000,0xBC000001,
+0x85FC0000,0x1580278,0xEB5000F4,0xC95000F4,0xBD5000F5,0xE5440090,0xCD44004D,0xC1480069,0xC3440090,0xBD44004D,0xB7440092,0xE13800F3,0xCF380032,0xC1400053,0xC5380049,0xBD380002,0xB938004E,0xBD3800F4,0xBB340051,0xB7340067,0xB33800F3,0x7FC0274,0xD32400F3,0xBD3800F4,0xCB1C0092,0xBF28004A,0xB7300092,0xC90C00F3,0xBD180033,0xB718004F,0xB32000F4,0x85FC0274,
+0xBCF400F4,0xB6EC0092,0xB2D800F3,0xAC000274,0xFF44007E,0xF35401B2,0xF55801DD,0xEF380000,0xD5380001,0xC5380002,0xBF3C0006,0xBD380006,0xFF34006A,0xE7300002,0xBF340035,0xB718004F,0x65FC0274,0x16400F4,0xDF5C0034,0xC7580034,0xBD580035,0xD9500048,0xC7500001,0xBF500005,0xBF50004A,0xBD4C000E,0xB750004A,0x19FC00F3,0xCD3C0032,0xBF480033,0xC5380049,0xBD380002,
+0xB740004A,0x8FF800F3,0xBD180033,0xB710004A,0xB20000F3,0x19FC00F3,0xCD3C0032,0xBF480033,0xC5380049,0xBD380002,0xB740004A,0x8FF800F3,0xBD180033,0xB710004A,0xB20000F3,0x8FF800F3,0xBD180033,0xB710004A,0xB20000F3,0xB20000F3,0xFD4C002D,0xF960009A,0xF9600095,0xEF380000,0xD5380001,0xC5380002,0xBF400001,0xBD300003,0xFD400033,0xE7300001,0xC12C0032,0xB710004A,
+0x71FC00F3,0x15000F4,0x15000F4,0x15000F4,0x15000F4,0xD3440048,0xD3440048,0xD3440048,0xB9440049,0xB9440049,0xB1440049,0xCF380032,0xCF380032,0xCF380032,0xBD380001,0xBD380001,0xB33C000E,0xB5380032,0xB5380032,0xB1380005,0xAD380032,0x1F000F3,0x1F000F3,0x1F000F3,0xBF280049,0xBF280049,0xB1340049,0xBD180032,0xBD180032,0xB1240002,0xAD280032,0x7DF800F3,
+0x7DF800F3,0xB1040049,0xACF00032,0xA60000F3,0xF940002D,0xFF4C008C,0x15000F4,0xEF380000,0xD1380001,0xC5380001,0xC1380004,0xB9380001,0xFF340019,0xE7300001,0xBD340032,0xB1240002,0x5BFC00F3,0x1580034,0x1580034,0x1580034,0x1580034,0xC5500000,0xC5500000,0xC5500000,0xB7500000,0xB7500000,0xB1500001,0x7FC0032,0x7FC0032,0x7FC0032,0xB9400001,0xB9400001,
+0xB1480001,0x85FC0032,0x85FC0032,0xB12C0001,0xAC000032,0x7FC0032,0x7FC0032,0x7FC0032,0xB9400001,0xB9400001,0xB1480001,0x85FC0032,0x85FC0032,0xB12C0001,0xAC000032,0x85FC0032,0x85FC0032,0xB12C0001,0xAC000032,0xAC000032,0xF7480005,0xF354000D,0x1580034,0xEF380000,0xCF3C0000,0xC33C0000,0xBF400000,0xB9380001,0xF53C0008,0xE7300000,0x65FC0032,0xB12C0001,
+0x65FC0032,0x1700048,0xD7640000,0xC3640001,0xBD640001,0x29FC0048,0xC7500001,0xBD580001,0x97F80048,0xBD340001,0xB600004A,0x29FC0048,0xC7500001,0xBD580001,0x97F80048,0xBD340001,0xB600004A,0x97F80048,0xBD340001,0xB600004A,0xB600004A,0x29FC0048,0xC7500001,0xBD580001,0x97F80048,0xBD340001,0xB600004A,0x97F80048,0xBD340001,0xB600004A,0xB600004A,0x97F80048,
+0xBD340001,0xB600004A,0xB600004A,0xB600004A,0xFF500014,0x1880048,0xFF6C0019,0xEF380000,0xD3380001,0xC7340000,0xBD440001,0xBD240001,0xF9480012,0xEB2C0000,0xBF480001,0xB600004A,0x7BFC0048,0x1440048,0x1440048,0x1440048,0x1440048,0x1440048,0x1440048,0x1440048,0x1440048,0x1440048,0x1440048,0xC1380000,0xC1380000,0xC1380000,0xC1380000,0xC1380000,
+0xC1380000,0xAD380001,0xAD380001,0xAD380001,0xA7380001,0x1E00048,0x1E00048,0x1E00048,0x1E00048,0x1E00048,0x1E00048,0xB1240001,0xB1240001,0xB1240001,0xA72C0001,0x75FC0048,0x75FC0048,0x75FC0048,0xA7080001,0xA000004A,0xF73C0014,0x1440048,0x1440048,0xEF380000,0xD5380000,0xC9380000,0xC9380000,0xB9380000,0xF9300008,0xEF2C0000,0xB5340000,0xB1240001,
+0x51FC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table54[] = {
+0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x79F80000,
+0x79F80000,0x79F80000,0x79F80000,0xA2000001,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x75C0000,0x75C0000,0x75C0000,0x1E80000,0x55FC0000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0xFFC0000,0xFFC0000,0xFFC0000,0xFFC0000,0xFFC0000,
+0xFFC0000,0x8BF80000,0x8BF80000,0x8BF80000,0xAE000001,0xFFC0000,0xFFC0000,0xFFC0000,0xFFC0000,0xFFC0000,0xFFC0000,0x8BF80000,0x8BF80000,0x8BF80000,0xAE000001,0x8BF80000,0x8BF80000,0x8BF80000,0xAE000001,0xAE000001,0x1780000,0x1600000,0x1600000,0x3980000,0x1B80000,0x3DC0000,0x3DC0000,0x3DFC0000,0x3980000,0x1B80000,0x6BFC0000,0x8BF80000,
+0x6BFC0000,0x1740000,0x1740000,0x1740000,0x1740000,0x2FFC0000,0x2FFC0000,0x2FFC0000,0x99FC0000,0x99FC0000,0xB8000001,0x2FFC0000,0x2FFC0000,0x2FFC0000,0x99FC0000,0x99FC0000,0xB8000001,0x99FC0000,0x99FC0000,0xB8000001,0xB8000001,0x2FFC0000,0x2FFC0000,0x2FFC0000,0x99FC0000,0x99FC0000,0xB8000001,0x99FC0000,0x99FC0000,0xB8000001,0xB8000001,0x99FC0000,
+0x99FC0000,0xB8000001,0xB8000001,0xB8000001,0x1B00000,0x18C0000,0x1740000,0x3F80000,0x57FC0000,0x7FF80000,0x8BFC0000,0xA1FC0000,0x5D00000,0x2FFC0000,0x7FF80000,0xB8000001,0x7FF80000,0x18C0000,0x53FC0000,0xABF80000,0xC4000001,0x53FC0000,0xABF80000,0xC4000001,0xABF80000,0xC4000001,0xC4000001,0x53FC0000,0xABF80000,0xC4000001,0xABF80000,0xC4000001,
+0xC4000001,0xABF80000,0xC4000001,0xC4000001,0xC4000001,0x53FC0000,0xABF80000,0xC4000001,0xABF80000,0xC4000001,0xC4000001,0xABF80000,0xC4000001,0xC4000001,0xC4000001,0xABF80000,0xC4000001,0xC4000001,0xC4000001,0xC4000001,0x1F00000,0xBA40000,0xBA40000,0x73FC0000,0x9FFC0000,0xB9F00000,0xC4000001,0xC4000001,0x2BFC0000,0x87FC0000,0xC3D80000,0xC4000001,
+0x95FC0000,0x1680278,0xF36000F4,0xD16000F4,0xC56000F5,0xED540090,0xD554004D,0xC9580069,0xCB540090,0xC554004D,0xBF540092,0xE94800F3,0xD7480032,0xC9500053,0xCD480049,0xC5480002,0xC148004E,0xC54800F4,0xC3440051,0xBF440067,0xBB4800F3,0x1FFC0274,0xDB3400F3,0xC54800F4,0xD32C0092,0xC738004A,0xBF400092,0xD11C00F3,0xC5280033,0xBF28004F,0xBB3000F4,0x91FC0274,
+0xC50400F4,0xBEFC0092,0xBAE800F3,0xB4000274,0xFF580096,0xFB6401B2,0xFD6801DD,0xF7480000,0xDD480001,0xCD480002,0xC74C0006,0xC5480006,0xFD4C008A,0xEF400002,0xC7440035,0xBF28004F,0x75FC0274,0x17400F4,0xE76C0034,0xCF680034,0xC5680035,0xE1600048,0xCF600001,0xC7600005,0xC760004A,0xC55C000E,0xBF60004A,0x31FC00F3,0xD54C0032,0xC7580033,0xCD480049,0xC5480002,
+0xBF50004A,0x9BF800F3,0xC5280033,0xBF20004A,0xBA0000F3,0x31FC00F3,0xD54C0032,0xC7580033,0xCD480049,0xC5480002,0xBF50004A,0x9BF800F3,0xC5280033,0xBF20004A,0xBA0000F3,0x9BF800F3,0xC5280033,0xBF20004A,0xBA0000F3,0xBA0000F3,0xFD60003E,0xFF6C009E,0xF37400A4,0xF7480000,0xDD480001,0xCD480002,0xC7500001,0xC5400003,0xFB54003D,0xEF400001,0xC93C0032,0xBF20004A,
+0x7FFC00F3,0x16000F4,0x16000F4,0x16000F4,0x16000F4,0xDB540048,0xDB540048,0xDB540048,0xC1540049,0xC1540049,0xB9540049,0xD7480032,0xD7480032,0xD7480032,0xC5480001,0xC5480001,0xBB4C000E,0xBD480032,0xBD480032,0xB9480005,0xB5480032,0xDFC00F3,0xDFC00F3,0xDFC00F3,0xC7380049,0xC7380049,0xB9440049,0xC5280032,0xC5280032,0xB9340002,0xB5380032,0x89F800F3,
+0x89F800F3,0xB9140049,0xB5000032,0xAE0000F3,0xFD540035,0xF75C0099,0x16000F4,0xF7480000,0xD9480001,0xCD480001,0xC9480004,0xC1480001,0xFB480029,0xEF400001,0xC5440032,0xB9340002,0x69FC00F3,0x1680034,0x1680034,0x1680034,0x1680034,0xCD600000,0xCD600000,0xCD600000,0xBF600000,0xBF600000,0xB9600001,0x1FFC0032,0x1FFC0032,0x1FFC0032,0xC1500001,0xC1500001,
+0xB9580001,0x91FC0032,0x91FC0032,0xB93C0001,0xB4000032,0x1FFC0032,0x1FFC0032,0x1FFC0032,0xC1500001,0xC1500001,0xB9580001,0x91FC0032,0x91FC0032,0xB93C0001,0xB4000032,0x91FC0032,0x91FC0032,0xB93C0001,0xB4000032,0xB4000032,0xFF580005,0xFB64000D,0x1680034,0xF7480000,0xD74C0000,0xCB4C0000,0xC7500000,0xC1480001,0xFD4C0008,0xEF400000,0x75FC0032,0xB93C0001,
+0x75FC0032,0x1800048,0xDF740000,0xCB740001,0xC5740001,0x41FC0048,0xCF600001,0xC5680001,0xA1FC0048,0xC5440001,0xBE00004A,0x41FC0048,0xCF600001,0xC5680001,0xA1FC0048,0xC5440001,0xBE00004A,0xA1FC0048,0xC5440001,0xBE00004A,0xBE00004A,0x41FC0048,0xCF600001,0xC5680001,0xA1FC0048,0xC5440001,0xBE00004A,0xA1FC0048,0xC5440001,0xBE00004A,0xBE00004A,0xA1FC0048,
+0xC5440001,0xBE00004A,0xBE00004A,0xBE00004A,0xF7680019,0x5980048,0xF77C0020,0xF7480000,0xDB480001,0xCF440000,0xC5540001,0xC5340001,0xFD580014,0xF33C0000,0xC7580001,0xBE00004A,0x89FC0048,0x1540048,0x1540048,0x1540048,0x1540048,0x1540048,0x1540048,0x1540048,0x1540048,0x1540048,0x1540048,0xC9480000,0xC9480000,0xC9480000,0xC9480000,0xC9480000,
+0xC9480000,0xB5480001,0xB5480001,0xB5480001,0xAF480001,0x1F80048,0x1F80048,0x1F80048,0x1F80048,0x1F80048,0x1F80048,0xB9340001,0xB9340001,0xB9340001,0xAF3C0001,0x81FC0048,0x81FC0048,0x81FC0048,0xAF180001,0xA800004A,0xFF4C0014,0x1540048,0x1540048,0xF7480000,0xDD480000,0xD1480000,0xD1480000,0xC1480000,0xF544000D,0xF73C0000,0xBD440000,0xB9340001,
+0x5FFC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table55[] = {
+0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x85F80000,
+0x85F80000,0x85F80000,0x85F80000,0xAA000001,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0xF6C0000,0xF6C0000,0xF6C0000,0x3FC0000,0x63FC0000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x29FC0000,0x29FC0000,0x29FC0000,0x29FC0000,0x29FC0000,
+0x29FC0000,0x97F80000,0x97F80000,0x97F80000,0xB6000001,0x29FC0000,0x29FC0000,0x29FC0000,0x29FC0000,0x29FC0000,0x29FC0000,0x97F80000,0x97F80000,0x97F80000,0xB6000001,0x97F80000,0x97F80000,0x97F80000,0xB6000001,0xB6000001,0x1880000,0x1700000,0x1700000,0x1AC0000,0x3CC0000,0x1F40000,0x1F40000,0x51FC0000,0x1AC0000,0x3CC0000,0x7BFC0000,0x97F80000,
+0x7BFC0000,0x1840000,0x1840000,0x1840000,0x1840000,0x47FC0000,0x47FC0000,0x47FC0000,0xA5F80000,0xA5F80000,0xC0000001,0x47FC0000,0x47FC0000,0x47FC0000,0xA5F80000,0xA5F80000,0xC0000001,0xA5F80000,0xA5F80000,0xC0000001,0xC0000001,0x47FC0000,0x47FC0000,0x47FC0000,0xA5F80000,0xA5F80000,0xC0000001,0xA5F80000,0xA5F80000,0xC0000001,0xC0000001,0xA5F80000,
+0xA5F80000,0xC0000001,0xC0000001,0xC0000001,0x1C40000,0x79C0000,0x1840000,0x1BFC0000,0x6BFC0000,0x8DFC0000,0x99FC0000,0xADF80000,0x5E40000,0x47FC0000,0x8DFC0000,0xC0000001,0x8DFC0000,0x19C0000,0x6BFC0000,0xB7F80000,0xCC000001,0x6BFC0000,0xB7F80000,0xCC000001,0xB7F80000,0xCC000001,0xCC000001,0x6BFC0000,0xB7F80000,0xCC000001,0xB7F80000,0xCC000001,
+0xCC000001,0xB7F80000,0xCC000001,0xCC000001,0xCC000001,0x6BFC0000,0xB7F80000,0xCC000001,0xB7F80000,0xCC000001,0xCC000001,0xB7F80000,0xCC000001,0xCC000001,0xCC000001,0xB7F80000,0xCC000001,0xCC000001,0xCC000001,0xCC000001,0x11FC0000,0x1B80000,0x1B80000,0x87FC0000,0xADFC0000,0xC3F00000,0xCC000001,0xCC000001,0x49FC0000,0x97FC0000,0xCBE80000,0xCC000001,
+0xA3FC0000,0x1780278,0xFB7000F4,0xD97000F4,0xCD7000F5,0xF5640090,0xDD64004D,0xD1680069,0xD3640090,0xCD64004D,0xC7640092,0xF15800F3,0xDF580032,0xD1600053,0xD5580049,0xCD580002,0xC958004E,0xCD5800F4,0xCB540051,0xC7540067,0xC35800F3,0x37FC0274,0xE34400F3,0xCD5800F4,0xDB3C0092,0xCF48004A,0xC7500092,0xD92C00F3,0xCD380033,0xC738004F,0xC34000F4,0x9DFC0274,
+0xCD1400F4,0xC70C0092,0xC2F800F3,0xBC000274,0xFF6C00C2,0xF37401D8,0xF57801F8,0xFF580000,0xE5580001,0xD5580002,0xCF5C0006,0xCD580006,0xFF5C00A6,0xF7500002,0xCF540035,0xC738004F,0x83FC0274,0x18400F4,0xEF7C0034,0xD7780034,0xCD780035,0xE9700048,0xD7700001,0xCF700005,0xCF70004A,0xCD6C000E,0xC770004A,0x49FC00F3,0xDD5C0032,0xCF680033,0xD5580049,0xCD580002,
+0xC760004A,0xA7F800F3,0xCD380033,0xC730004A,0xC20000F3,0x49FC00F3,0xDD5C0032,0xCF680033,0xD5580049,0xCD580002,0xC760004A,0xA7F800F3,0xCD380033,0xC730004A,0xC20000F3,0xA7F800F3,0xCD380033,0xC730004A,0xC20000F3,0xC20000F3,0xFD740049,0xF98000A8,0xFB8400A4,0xFF580000,0xE5580001,0xD5580002,0xCF600001,0xCD500003,0xFB680055,0xF7500001,0xD14C0032,0xC730004A,
+0x8FFC00F3,0x17000F4,0x17000F4,0x17000F4,0x17000F4,0xE3640048,0xE3640048,0xE3640048,0xC9640049,0xC9640049,0xC1640049,0xDF580032,0xDF580032,0xDF580032,0xCD580001,0xCD580001,0xC35C000E,0xC5580032,0xC5580032,0xC1580005,0xBD580032,0x25FC00F3,0x25FC00F3,0x25FC00F3,0xCF480049,0xCF480049,0xC1540049,0xCD380032,0xCD380032,0xC1440002,0xBD480032,0x95F800F3,
+0x95F800F3,0xC1240049,0xBD100032,0xB60000F3,0xFD64003E,0xFF6C0099,0x17000F4,0xFF580000,0xE1580001,0xD5580001,0xD1580004,0xC9580001,0xFF580032,0xF7500001,0xCD540032,0xC1440002,0x79FC00F3,0x1780034,0x1780034,0x1780034,0x1780034,0xD5700000,0xD5700000,0xD5700000,0xC7700000,0xC7700000,0xC1700001,0x37FC0032,0x37FC0032,0x37FC0032,0xC9600001,0xC9600001,
+0xC1680001,0x9DFC0032,0x9DFC0032,0xC14C0001,0xBC000032,0x37FC0032,0x37FC0032,0x37FC0032,0xC9600001,0xC9600001,0xC1680001,0x9DFC0032,0x9DFC0032,0xC14C0001,0xBC000032,0x9DFC0032,0x9DFC0032,0xC14C0001,0xBC000032,0xBC000032,0xFB6C0008,0xF3740014,0x1780034,0xFF580000,0xDF5C0000,0xD35C0000,0xCF600000,0xC9580001,0xF564000D,0xF7500000,0x83FC0032,0xC14C0001,
+0x83FC0032,0x1900048,0xE7840000,0xD3840001,0xCD840001,0x59FC0048,0xD7700001,0xCD780001,0xADFC0048,0xCD540001,0xC600004A,0x59FC0048,0xD7700001,0xCD780001,0xADFC0048,0xCD540001,0xC600004A,0xADFC0048,0xCD540001,0xC600004A,0xC600004A,0x59FC0048,0xD7700001,0xCD780001,0xADFC0048,0xCD540001,0xC600004A,0xADFC0048,0xCD540001,0xC600004A,0xC600004A,0xADFC0048,
+0xCD540001,0xC600004A,0xC600004A,0xC600004A,0xFF780019,0xDA80048,0xFF8C0020,0xFF580000,0xE3580001,0xD7540000,0xCD640001,0xCD440001,0xFF700019,0xFB4C0000,0xCF680001,0xC600004A,0x99FC0048,0x1640048,0x1640048,0x1640048,0x1640048,0x1640048,0x1640048,0x1640048,0x1640048,0x1640048,0x1640048,0xD1580000,0xD1580000,0xD1580000,0xD1580000,0xD1580000,
+0xD1580000,0xBD580001,0xBD580001,0xBD580001,0xB7580001,0x15FC0048,0x15FC0048,0x15FC0048,0x15FC0048,0x15FC0048,0x15FC0048,0xC1440001,0xC1440001,0xC1440001,0xB74C0001,0x8DFC0048,0x8DFC0048,0x8DFC0048,0xB7280001,0xB000004A,0xF9600019,0x1640048,0x1640048,0xFF580000,0xE5580000,0xD9580000,0xD9580000,0xC9580000,0xFD54000D,0xFF4C0000,0xC5540000,0xC1440001,
+0x6FFC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table56[] = {
+0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x91FC0000,
+0x91FC0000,0x91FC0000,0x91FC0000,0xB4000000,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x9800000,0x9800000,0x9800000,0x1FFC0000,0x75FC0000,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,
+0x43FC0000,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xC0000000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xC0000000,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xC0000000,0xC0000000,0x19C0000,0x1800001,0x1800001,0x1C00000,0x1E40000,0x17FC0000,0x17FC0000,0x67FC0000,0x1C00000,0x1E40000,0x8BFC0000,0xA3FC0000,
+0x8BFC0000,0x1940001,0x1940001,0x1940001,0x1940001,0x63FC0000,0x63FC0000,0x63FC0000,0xB3F80000,0xB3F80000,0xCA000000,0x63FC0000,0x63FC0000,0x63FC0000,0xB3F80000,0xB3F80000,0xCA000000,0xB3F80000,0xB3F80000,0xCA000000,0xCA000000,0x63FC0000,0x63FC0000,0x63FC0000,0xB3F80000,0xB3F80000,0xCA000000,0xB3F80000,0xB3F80000,0xCA000000,0xCA000000,0xB3F80000,
+0xB3F80000,0xCA000000,0xCA000000,0xCA000000,0x1D80000,0x1B00000,0x1940001,0x3DFC0000,0x81FC0000,0x9FF80000,0xA9F80000,0xB9F80000,0x1FC0000,0x63FC0000,0x9FF80000,0xCA000000,0x9FF80000,0x1AC0001,0x87FC0000,0xC5F80000,0xD6000000,0x87FC0000,0xC5F80000,0xD6000000,0xC5F80000,0xD6000000,0xD6000000,0x87FC0000,0xC5F80000,0xD6000000,0xC5F80000,0xD6000000,
+0xD6000000,0xC5F80000,0xD6000000,0xD6000000,0xD6000000,0x87FC0000,0xC5F80000,0xD6000000,0xC5F80000,0xD6000000,0xD6000000,0xC5F80000,0xD6000000,0xD6000000,0xD6000000,0xC5F80000,0xD6000000,0xD6000000,0xD6000000,0xD6000000,0x3DFC0000,0xDC80000,0xDC80000,0x9DFC0000,0xBDF80000,0xCDF80000,0xD6000000,0xD6000000,0x6BFC0000,0xABFC0000,0xD5DC0000,0xD6000000,
+0xB5FC0000,0x18C0274,0xFF8000F7,0xE18000F4,0xD78000F3,0xFB780092,0xE378004F,0xD9780067,0xDB780092,0xD774004E,0xD1740092,0xF96C00F4,0xE76C0033,0xD9700051,0xDF68004A,0xD76C0002,0xD16C004D,0xD76800F4,0xD3640053,0xCF640069,0xCB6800F5,0x53FC0274,0xED5400F3,0xD76C00F4,0xE3500092,0xD75C0049,0xD1600090,0xE14000F3,0xD7480032,0xD148004D,0xCB5400F4,0xABF80274,
+0xD72000F3,0xD11C0090,0xCB1000F4,0xC4000278,0xFF8000EA,0xFD8801D4,0xFD8801FC,0xFF70000E,0xED6C0002,0xDF6C0002,0xD76C0006,0xD5680006,0xFD7400D7,0xFF600006,0xD9640035,0xD148004D,0x95FC0274,0x19800F3,0xF98C0032,0xDF8C0032,0xD78C0032,0xEF840049,0xE1800002,0xD7840005,0xD9800049,0xD580000E,0xD1800049,0x65FC00F3,0xE76C0032,0xD77C0032,0xDF680049,0xD76C0001,
+0xD1700049,0xB3FC00F3,0xD7440032,0xD1400048,0xCA0000F4,0x65FC00F3,0xE76C0032,0xD77C0032,0xDF680049,0xD76C0001,0xD1700049,0xB3FC00F3,0xD7440032,0xD1400048,0xCA0000F4,0xB3FC00F3,0xD7440032,0xD1400048,0xCA0000F4,0xCA0000F4,0xFD880063,0xF39400B9,0xF39400B6,0xFF700005,0xED6C0001,0xDF6C0001,0xD7740001,0xD7640004,0xFF780062,0xFF640002,0xD9600033,0xD1400048,
+0x9FFC00F3,0x18000F3,0x18000F3,0x18000F3,0x18000F3,0xE978004A,0xE978004A,0xE978004A,0xD374004A,0xD374004A,0xCB74004A,0xE76C0033,0xE76C0033,0xE76C0033,0xD56C0002,0xD56C0002,0xCD6C000E,0xCF680033,0xCF680033,0xCB680005,0xC5680035,0x41FC00F3,0x41FC00F3,0x41FC00F3,0xD75C0049,0xD75C0049,0xCB64004A,0xD54C0032,0xD54C0032,0xCB540001,0xC7580034,0xA1FC00F3,
+0xA1FC00F3,0xCB340048,0xC5280034,0xC00000F4,0xFF740053,0xF77C00AB,0x18000F3,0xFD6C0006,0xE96C0002,0xDD6C0002,0xDB6C0003,0xD3680001,0xFF6C0049,0xFF600002,0xD5680033,0xCB540001,0x89FC00F3,0x18C0032,0x18C0032,0x18C0032,0x18C0032,0xDD840001,0xDD840001,0xDD840001,0xCF840001,0xCF840001,0xCB800001,0x53FC0032,0x53FC0032,0x53FC0032,0xD3700001,0xD3700001,
+0xCB780000,0xABF80032,0xABF80032,0xCB580000,0xC4000034,0x53FC0032,0x53FC0032,0x53FC0032,0xD3700001,0xD3700001,0xCB780000,0xABF80032,0xABF80032,0xCB580000,0xC4000034,0xABF80032,0xABF80032,0xCB580000,0xC4000034,0xC4000034,0xF780000D,0xFD880012,0x18C0032,0xFB700001,0xE3740001,0xDB700000,0xD5740001,0xD3680000,0xFD74000D,0xFD640000,0x95FC0032,0xCB580000,
+0x95FC0032,0x1A0004A,0xED980001,0xDD940001,0xD7940001,0x75FC0048,0xE1800001,0xD7880001,0xBBFC0048,0xD7640000,0xD0000048,0x75FC0048,0xE1800001,0xD7880001,0xBBFC0048,0xD7640000,0xD0000048,0xBBFC0048,0xD7640000,0xD0000048,0xD0000048,0x75FC0048,0xE1800001,0xD7880001,0xBBFC0048,0xD7640000,0xD0000048,0xBBFC0048,0xD7640000,0xD0000048,0xD0000048,0xBBFC0048,
+0xD7640000,0xD0000048,0xD0000048,0xD0000048,0xFD900020,0x7BC0048,0xF9A00029,0xFF740002,0xED680001,0xE1640000,0xD7740000,0xD7500000,0xFB880020,0xFF640001,0xD9780000,0xD0000048,0xA9FC0048,0x174004A,0x174004A,0x174004A,0x174004A,0x174004A,0x174004A,0x174004A,0x174004A,0x174004A,0x174004A,0xD76C0001,0xD76C0001,0xD76C0001,0xD76C0001,0xD76C0001,
+0xD76C0001,0xC7680001,0xC7680001,0xC7680001,0xC1680001,0x31FC0048,0x31FC0048,0x31FC0048,0x31FC0048,0x31FC0048,0x31FC0048,0xCB540001,0xCB540001,0xCB540001,0xC15C0001,0x9BF80048,0x9BF80048,0x9BF80048,0xC1380000,0xBA000048,0xF1700022,0x174004A,0x174004A,0xFB6C0002,0xEB6C0001,0xDF6C0001,0xDF6C0001,0xD16C0001,0xF9680012,0xFD600001,0xCB680001,0xCB540001,
+0x7FFC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table57[] = {
+0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x9DFC0000,
+0x9DFC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1940000,0x1940000,0x1940000,0x37FC0000,0x83FC0000,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x5BFC0000,0x5BFC0000,0x5BFC0000,0x5BFC0000,0x5BFC0000,
+0x5BFC0000,0xAFFC0000,0xAFFC0000,0xAFFC0000,0xC8000000,0x5BFC0000,0x5BFC0000,0x5BFC0000,0x5BFC0000,0x5BFC0000,0x5BFC0000,0xAFFC0000,0xAFFC0000,0xAFFC0000,0xC8000000,0xAFFC0000,0xAFFC0000,0xAFFC0000,0xC8000000,0xC8000000,0x1AC0000,0x1900001,0x1900001,0x1D40000,0x1F80000,0x35FC0000,0x35FC0000,0x7BFC0000,0x1D40000,0x1F80000,0x9BFC0000,0xAFFC0000,
+0x9BFC0000,0x1A40001,0x1A40001,0x1A40001,0x1A40001,0x7BFC0000,0x7BFC0000,0x7BFC0000,0xBFF80000,0xBFF80000,0xD2000000,0x7BFC0000,0x7BFC0000,0x7BFC0000,0xBFF80000,0xBFF80000,0xD2000000,0xBFF80000,0xBFF80000,0xD2000000,0xD2000000,0x7BFC0000,0x7BFC0000,0x7BFC0000,0xBFF80000,0xBFF80000,0xD2000000,0xBFF80000,0xBFF80000,0xD2000000,0xD2000000,0xBFF80000,
+0xBFF80000,0xD2000000,0xD2000000,0xD2000000,0x7E80000,0x9C00000,0x1A40001,0x5BFC0000,0x93FC0000,0xADFC0000,0xB5FC0000,0xC3FC0000,0x29FC0000,0x7BFC0000,0xADFC0000,0xD2000000,0xADFC0000,0x1BC0001,0x9FFC0000,0xD1F80000,0xDE000000,0x9FFC0000,0xD1F80000,0xDE000000,0xD1F80000,0xDE000000,0xDE000000,0x9FFC0000,0xD1F80000,0xDE000000,0xD1F80000,0xDE000000,
+0xDE000000,0xD1F80000,0xDE000000,0xDE000000,0xDE000000,0x9FFC0000,0xD1F80000,0xDE000000,0xD1F80000,0xDE000000,0xDE000000,0xD1F80000,0xDE000000,0xDE000000,0xDE000000,0xD1F80000,0xDE000000,0xDE000000,0xDE000000,0xDE000000,0x63FC0000,0x1DC0000,0x1DC0000,0xB1FC0000,0xC9FC0000,0xD7F80000,0xDE000000,0xDE000000,0x89FC0000,0xBBFC0000,0xDDEC0000,0xDE000000,
+0xC3FC0000,0x19C0274,0xFD94010B,0xE99000F4,0xDF9000F3,0xFD88009A,0xEB88004F,0xE1880067,0xE3880092,0xDF84004E,0xD9840092,0xFD7C00F5,0xEF7C0033,0xE1800051,0xE778004A,0xDF7C0002,0xD97C004D,0xDF7800F4,0xDB740053,0xD7740069,0xD37800F5,0x6BFC0274,0xF56400F3,0xDF7C00F4,0xEB600092,0xDF6C0049,0xD9700090,0xE95000F3,0xDF580032,0xD958004D,0xD36400F4,0xB7F80274,
+0xDF3000F3,0xD92C0090,0xD32000F4,0xCC000278,0xFF8C0114,0xF59801FA,0xF79C0217,0xFF800026,0xF57C0002,0xE77C0002,0xDF7C0006,0xDD780006,0xFF880104,0xFF78001B,0xE1740035,0xD958004D,0xA3FC0274,0x1A800F3,0xFF9C0033,0xE79C0032,0xDF9C0032,0xF7940049,0xE9900002,0xDF940005,0xE1900049,0xDD90000E,0xD9900049,0x7DFC00F3,0xEF7C0032,0xDF8C0032,0xE7780049,0xDF7C0001,
+0xD9800049,0xBFFC00F3,0xDF540032,0xD9500048,0xD20000F4,0x7DFC00F3,0xEF7C0032,0xDF8C0032,0xE7780049,0xDF7C0001,0xD9800049,0xBFFC00F3,0xDF540032,0xD9500048,0xD20000F4,0xBFFC00F3,0xDF540032,0xD9500048,0xD20000F4,0xD20000F4,0xFB980075,0xFBA400B9,0xFBA400B6,0xFF880013,0xF57C0001,0xE77C0001,0xDF840001,0xDF740004,0xFF900071,0xFD7C000D,0xE1700033,0xD9500048,
+0xAFFC00F3,0x19000F3,0x19000F3,0x19000F3,0x19000F3,0xF188004A,0xF188004A,0xF188004A,0xDB84004A,0xDB84004A,0xD384004A,0xEF7C0033,0xEF7C0033,0xEF7C0033,0xDD7C0002,0xDD7C0002,0xD57C000E,0xD7780033,0xD7780033,0xD3780005,0xCD780035,0x59FC00F3,0x59FC00F3,0x59FC00F3,0xDF6C0049,0xDF6C0049,0xD374004A,0xDD5C0032,0xDD5C0032,0xD3640001,0xCF680034,0xADFC00F3,
+0xADFC00F3,0xD3440048,0xCD380034,0xC80000F4,0xFF840062,0xFF8C00AB,0x19000F3,0xFF80000D,0xF17C0002,0xE57C0002,0xE37C0003,0xDB780001,0xFF800055,0xFF740006,0xDD780033,0xD3640001,0x99FC00F3,0x19C0032,0x19C0032,0x19C0032,0x19C0032,0xE5940001,0xE5940001,0xE5940001,0xD7940001,0xD7940001,0xD3900001,0x6BFC0032,0x6BFC0032,0x6BFC0032,0xDB800001,0xDB800001,
+0xD3880000,0xB7F80032,0xB7F80032,0xD3680000,0xCC000034,0x6BFC0032,0x6BFC0032,0x6BFC0032,0xDB800001,0xDB800001,0xD3880000,0xB7F80032,0xB7F80032,0xD3680000,0xCC000034,0xB7F80032,0xB7F80032,0xD3680000,0xCC000034,0xCC000034,0xFF90000D,0xF5980019,0x19C0032,0xFD840002,0xEB840001,0xE3800000,0xDD840001,0xDB780000,0xFD880012,0xFB7C0002,0xA3FC0032,0xD3680000,
+0xA3FC0032,0x1B0004A,0xF5A80001,0xE5A40001,0xDFA40001,0x8DFC0048,0xE9900001,0xDF980001,0xC7FC0048,0xDF740000,0xD8000048,0x8DFC0048,0xE9900001,0xDF980001,0xC7FC0048,0xDF740000,0xD8000048,0xC7FC0048,0xDF740000,0xD8000048,0xD8000048,0x8DFC0048,0xE9900001,0xDF980001,0xC7FC0048,0xDF740000,0xD8000048,0xC7FC0048,0xDF740000,0xD8000048,0xD8000048,0xC7FC0048,
+0xDF740000,0xD8000048,0xD8000048,0xD8000048,0xF7A40029,0xFCC0048,0xFFAC002D,0xFF8C0008,0xF5780001,0xE9740000,0xDF840000,0xDF600000,0xFF980022,0xFD800005,0xE1880000,0xD8000048,0xB9FC0048,0x184004A,0x184004A,0x184004A,0x184004A,0x184004A,0x184004A,0x184004A,0x184004A,0x184004A,0x184004A,0xDF7C0001,0xDF7C0001,0xDF7C0001,0xDF7C0001,0xDF7C0001,
+0xDF7C0001,0xCF780001,0xCF780001,0xCF780001,0xC9780001,0x49FC0048,0x49FC0048,0x49FC0048,0x49FC0048,0x49FC0048,0x49FC0048,0xD3640001,0xD3640001,0xD3640001,0xC96C0001,0xA7F80048,0xA7F80048,0xA7F80048,0xC9480000,0xC2000048,0xF9800022,0x184004A,0x184004A,0xFB7C0005,0xF37C0001,0xE77C0001,0xE77C0001,0xD97C0001,0xF57C0019,0xFD740002,0xD3780001,0xD3640001,
+0x8FFC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table58[] = {
+0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0xA9FC0000,
+0xA9FC0000,0xA9FC0000,0xA9FC0000,0xC4000000,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1A40000,0x1A40000,0x1A40000,0x4FFC0000,0x93FC0000,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x75FC0000,0x75FC0000,0x75FC0000,0x75FC0000,0x75FC0000,
+0x75FC0000,0xBBFC0000,0xBBFC0000,0xBBFC0000,0xD0000000,0x75FC0000,0x75FC0000,0x75FC0000,0x75FC0000,0x75FC0000,0x75FC0000,0xBBFC0000,0xBBFC0000,0xBBFC0000,0xD0000000,0xBBFC0000,0xBBFC0000,0xBBFC0000,0xD0000000,0xD0000000,0x7BC0000,0x1A00001,0x1A00001,0x5E40000,0x1FFC0000,0x53FC0000,0x53FC0000,0x8FFC0000,0x5E40000,0x1FFC0000,0xA9FC0000,0xBBFC0000,
+0xA9FC0000,0x1B40001,0x1B40001,0x1B40001,0x1B40001,0x93FC0000,0x93FC0000,0x93FC0000,0xCBF80000,0xCBF80000,0xDA000000,0x93FC0000,0x93FC0000,0x93FC0000,0xCBF80000,0xCBF80000,0xDA000000,0xCBF80000,0xCBF80000,0xDA000000,0xDA000000,0x93FC0000,0x93FC0000,0x93FC0000,0xCBF80000,0xCBF80000,0xDA000000,0xCBF80000,0xCBF80000,0xDA000000,0xDA000000,0xCBF80000,
+0xCBF80000,0xDA000000,0xDA000000,0xDA000000,0x3FC0000,0x1D40000,0x1B40001,0x79FC0000,0xA7FC0000,0xBDF80000,0xC3FC0000,0xCFF80000,0x51FC0000,0x93FC0000,0xBDF80000,0xDA000000,0xBDF80000,0x1CC0001,0xB7FC0000,0xDDF40000,0xE6000000,0xB7FC0000,0xDDF40000,0xE6000000,0xDDF40000,0xE6000000,0xE6000000,0xB7FC0000,0xDDF40000,0xE6000000,0xDDF40000,0xE6000000,
+0xE6000000,0xDDF40000,0xE6000000,0xE6000000,0xE6000000,0xB7FC0000,0xDDF40000,0xE6000000,0xDDF40000,0xE6000000,0xE6000000,0xDDF40000,0xE6000000,0xE6000000,0xE6000000,0xDDF40000,0xE6000000,0xE6000000,0xE6000000,0xE6000000,0x8BFC0000,0x1EC0000,0x1EC0000,0xC5FC0000,0xD7FC0000,0xE1FC0000,0xE6000000,0xE6000000,0xA7FC0000,0xCDFC0000,0xE5FC0000,0xE6000000,
+0xD3FC0000,0x1AC0274,0xFFA4011F,0xF1A000F4,0xE7A000F3,0xFF9800B2,0xF398004F,0xE9980067,0xEB980092,0xE794004E,0xE1940092,0xFF900104,0xF78C0033,0xE9900051,0xEF88004A,0xE78C0002,0xE18C004D,0xE78800F4,0xE3840053,0xDF840069,0xDB8800F5,0x83FC0274,0xFD7400F3,0xE78C00F4,0xF3700092,0xE77C0049,0xE1800090,0xF16000F3,0xE7680032,0xE168004D,0xDB7400F4,0xC3F80274,
+0xE74000F3,0xE13C0090,0xDB3000F4,0xD4000278,0xFFA00136,0xFDA801FA,0xFFAC0217,0xFF940053,0xFD8C0002,0xEF8C0002,0xE78C0006,0xE5880006,0xFF98012A,0xFF8C0042,0xE9840035,0xE168004D,0xB3FC0274,0x1B800F3,0xFFB0003E,0xEFAC0032,0xE7AC0032,0xFFA40049,0xF1A00002,0xE7A40005,0xE9A00049,0xE5A0000E,0xE1A00049,0x95FC00F3,0xF78C0032,0xE79C0032,0xEF880049,0xE78C0001,
+0xE1900049,0xCBFC00F3,0xE7640032,0xE1600048,0xDA0000F4,0x95FC00F3,0xF78C0032,0xE79C0032,0xEF880049,0xE78C0001,0xE1900049,0xCBFC00F3,0xE7640032,0xE1600048,0xDA0000F4,0xCBFC00F3,0xE7640032,0xE1600048,0xDA0000F4,0xDA0000F4,0xFBAC0082,0xF3B400CB,0xF3B400CB,0xFF980029,0xFD8C0001,0xEF8C0001,0xE7940001,0xE7840004,0xFFA40082,0xFF90001E,0xE9800033,0xE1600048,
+0xBFF800F3,0x1A000F3,0x1A000F3,0x1A000F3,0x1A000F3,0xF998004A,0xF998004A,0xF998004A,0xE394004A,0xE394004A,0xDB94004A,0xF78C0033,0xF78C0033,0xF78C0033,0xE58C0002,0xE58C0002,0xDD8C000E,0xDF880033,0xDF880033,0xDB880005,0xD5880035,0x71FC00F3,0x71FC00F3,0x71FC00F3,0xE77C0049,0xE77C0049,0xDB84004A,0xE56C0032,0xE56C0032,0xDB740001,0xD7780034,0xB9FC00F3,
+0xB9FC00F3,0xDB540048,0xD5480034,0xD00000F4,0xFB980075,0xF9A000BA,0x1A000F3,0xFF90001A,0xF98C0002,0xED8C0002,0xEB8C0003,0xE3880001,0xFF940064,0xFD8C0019,0xE5880033,0xDB740001,0xA7FC00F3,0x1AC0032,0x1AC0032,0x1AC0032,0x1AC0032,0xEDA40001,0xEDA40001,0xEDA40001,0xDFA40001,0xDFA40001,0xDBA00001,0x83FC0032,0x83FC0032,0x83FC0032,0xE3900001,0xE3900001,
+0xDB980000,0xC3F80032,0xC3F80032,0xDB780000,0xD4000034,0x83FC0032,0x83FC0032,0x83FC0032,0xE3900001,0xE3900001,0xDB980000,0xC3F80032,0xC3F80032,0xDB780000,0xD4000034,0xC3F80032,0xC3F80032,0xDB780000,0xD4000034,0xD4000034,0xFFA00014,0xFDA80019,0x1AC0032,0xFF980005,0xF3940001,0xEB900000,0xE5940001,0xE3880000,0xF5A00019,0xFB900005,0xB3FC0032,0xDB780000,
+0xB3FC0032,0x1C0004A,0xFDB80001,0xEDB40001,0xE7B40001,0xA5FC0048,0xF1A00001,0xE7A80001,0xD3FC0048,0xE7840000,0xE0000048,0xA5FC0048,0xF1A00001,0xE7A80001,0xD3FC0048,0xE7840000,0xE0000048,0xD3FC0048,0xE7840000,0xE0000048,0xE0000048,0xA5FC0048,0xF1A00001,0xE7A80001,0xD3FC0048,0xE7840000,0xE0000048,0xD3FC0048,0xE7840000,0xE0000048,0xE0000048,0xD3FC0048,
+0xE7840000,0xE0000048,0xE0000048,0xE0000048,0xFFB40029,0x1E00048,0xF9C00032,0xFFA00011,0xFD880001,0xF1840000,0xE7940000,0xE7700000,0xFFAC002D,0xFD9C000D,0xE9980000,0xE0000048,0xC7FC0048,0x194004A,0x194004A,0x194004A,0x194004A,0x194004A,0x194004A,0x194004A,0x194004A,0x194004A,0x194004A,0xE78C0001,0xE78C0001,0xE78C0001,0xE78C0001,0xE78C0001,
+0xE78C0001,0xD7880001,0xD7880001,0xD7880001,0xD1880001,0x63FC0048,0x63FC0048,0x63FC0048,0x63FC0048,0x63FC0048,0x63FC0048,0xDB740001,0xDB740001,0xDB740001,0xD17C0001,0xB3F80048,0xB3F80048,0xB3F80048,0xD1580000,0xCA000048,0xF3940029,0x194004A,0x194004A,0xFD8C000A,0xFB8C0001,0xEF8C0001,0xEF8C0001,0xE18C0001,0xFD8C0019,0xF9880008,0xDB880001,0xDB740001,
+0x9FF80048,};
+static const uint32_t g_etc1_to_bc7_m6_table59[] = {
+0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0xB5FC0000,
+0xB5FC0000,0xB5FC0000,0xB5FC0000,0xCC000000,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x3B40000,0x3B40000,0x3B40000,0x69FC0000,0xA1FC0000,0x1B00001,0x1B00001,0x1B00001,0x1B00001,0x1B00001,0x1B00001,0x1B00001,0x1B00001,0x1B00001,0x1B00001,0x8DFC0000,0x8DFC0000,0x8DFC0000,0x8DFC0000,0x8DFC0000,
+0x8DFC0000,0xC7FC0000,0xC7FC0000,0xC7FC0000,0xD8000000,0x8DFC0000,0x8DFC0000,0x8DFC0000,0x8DFC0000,0x8DFC0000,0x8DFC0000,0xC7FC0000,0xC7FC0000,0xC7FC0000,0xD8000000,0xC7FC0000,0xC7FC0000,0xC7FC0000,0xD8000000,0xD8000000,0xFCC0000,0x1B00001,0x1B00001,0x1F80000,0x47FC0000,0x71FC0000,0x71FC0000,0xA3FC0000,0x1F80000,0x47FC0000,0xB9FC0000,0xC7FC0000,
+0xB9FC0000,0x1C40001,0x1C40001,0x1C40001,0x1C40001,0xABFC0000,0xABFC0000,0xABFC0000,0xD7F80000,0xD7F80000,0xE2000000,0xABFC0000,0xABFC0000,0xABFC0000,0xD7F80000,0xD7F80000,0xE2000000,0xD7F80000,0xD7F80000,0xE2000000,0xE2000000,0xABFC0000,0xABFC0000,0xABFC0000,0xD7F80000,0xD7F80000,0xE2000000,0xD7F80000,0xD7F80000,0xE2000000,0xE2000000,0xD7F80000,
+0xD7F80000,0xE2000000,0xE2000000,0xE2000000,0x3BFC0000,0x1E40000,0x1C40001,0x97FC0000,0xBBFC0000,0xCBFC0000,0xD1FC0000,0xD9FC0000,0x77FC0000,0xABFC0000,0xCBFC0000,0xE2000000,0xCBFC0000,0x1DC0001,0xCFFC0000,0xE7FC0000,0xEE000000,0xCFFC0000,0xE7FC0000,0xEE000000,0xE7FC0000,0xEE000000,0xEE000000,0xCFFC0000,0xE7FC0000,0xEE000000,0xE7FC0000,0xEE000000,
+0xEE000000,0xE7FC0000,0xEE000000,0xEE000000,0xEE000000,0xCFFC0000,0xE7FC0000,0xEE000000,0xE7FC0000,0xEE000000,0xEE000000,0xE7FC0000,0xEE000000,0xEE000000,0xEE000000,0xE7FC0000,0xEE000000,0xEE000000,0xEE000000,0xEE000000,0xB3FC0000,0x7FC0000,0x7FC0000,0xD9FC0000,0xE5FC0000,0xEBFC0000,0xEE000000,0xEE000000,0xC5FC0000,0xDDFC0000,0xEFD00000,0xEE000000,
+0xE1FC0000,0x1BC0274,0xFFB4014C,0xF9B000F4,0xEFB000F3,0xFFB000E2,0xFBA8004F,0xF1A80067,0xF3A80092,0xEFA4004E,0xE9A40092,0xFFA40121,0xFF9C0033,0xF1A00051,0xF798004A,0xEF9C0002,0xE99C004D,0xEF9800F4,0xEB940053,0xE7940069,0xE39800F5,0x9BFC0274,0xFD9000FD,0xEF9C00F4,0xFB800092,0xEF8C0049,0xE9900090,0xF97000F3,0xEF780032,0xE978004D,0xE38400F4,0xCFF80274,
+0xEF5000F3,0xE94C0090,0xE34000F4,0xDC000278,0xFFB4016B,0xF5B80224,0xF7BC0234,0xFFAC009E,0xFF9C0013,0xF79C0002,0xEF9C0006,0xED980006,0xFDB0016B,0xFFA00086,0xF1940035,0xE978004D,0xC1FC0274,0x1C800F3,0xFDC00053,0xF7BC0032,0xEFBC0032,0xFDB80059,0xF9B00002,0xEFB40005,0xF1B00049,0xEDB0000E,0xE9B00049,0xAFFC00F3,0xFF9C0032,0xEFAC0032,0xF7980049,0xEF9C0001,
+0xE9A00049,0xD7FC00F3,0xEF740032,0xE9700048,0xE20000F4,0xAFFC00F3,0xFF9C0032,0xEFAC0032,0xF7980049,0xEF9C0001,0xE9A00049,0xD7FC00F3,0xEF740032,0xE9700048,0xE20000F4,0xD7FC00F3,0xEF740032,0xE9700048,0xE20000F4,0xE20000F4,0xFFBC0095,0xFBC400CB,0xFBC400CB,0xFFB00042,0xFFA40009,0xF79C0001,0xEFA40001,0xEF940004,0xFFB4009E,0xFFAC003D,0xF1900033,0xE9700048,
+0xCDFC00F3,0x1B000F3,0x1B000F3,0x1B000F3,0x1B000F3,0xFFA8004B,0xFFA8004B,0xFFA8004B,0xEBA4004A,0xEBA4004A,0xE3A4004A,0xFF9C0033,0xFF9C0033,0xFF9C0033,0xED9C0002,0xED9C0002,0xE59C000E,0xE7980033,0xE7980033,0xE3980005,0xDD980035,0x89FC00F3,0x89FC00F3,0x89FC00F3,0xEF8C0049,0xEF8C0049,0xE394004A,0xED7C0032,0xED7C0032,0xE3840001,0xDF880034,0xC5FC00F3,
+0xC5FC00F3,0xE3640048,0xDD580034,0xD80000F4,0xFFAC0082,0xFFAC00BE,0x1B000F3,0xFFA40033,0xFF9C0003,0xF59C0002,0xF39C0003,0xEB980001,0xFFA00079,0xFF9C002A,0xED980033,0xE3840001,0xB7FC00F3,0x1BC0032,0x1BC0032,0x1BC0032,0x1BC0032,0xF5B40001,0xF5B40001,0xF5B40001,0xE7B40001,0xE7B40001,0xE3B00001,0x9BFC0032,0x9BFC0032,0x9BFC0032,0xEBA00001,0xEBA00001,
+0xE3A80000,0xCFF80032,0xCFF80032,0xE3880000,0xDC000034,0x9BFC0032,0x9BFC0032,0x9BFC0032,0xEBA00001,0xEBA00001,0xE3A80000,0xCFF80032,0xCFF80032,0xE3880000,0xDC000034,0xCFF80032,0xCFF80032,0xE3880000,0xDC000034,0xDC000034,0xFBB40019,0xF5B80022,0x1BC0032,0xFBAC000D,0xFBA40001,0xF3A00000,0xEDA40001,0xEB980000,0xFDB00019,0xFFA40008,0xC1FC0032,0xE3880000,
+0xC1FC0032,0x1D0004A,0xFFC80005,0xF5C40001,0xEFC40001,0xBDFC0048,0xF9B00001,0xEFB80001,0xDFF80048,0xEF940000,0xE8000048,0xBDFC0048,0xF9B00001,0xEFB80001,0xDFF80048,0xEF940000,0xE8000048,0xDFF80048,0xEF940000,0xE8000048,0xE8000048,0xBDFC0048,0xF9B00001,0xEFB80001,0xDFF80048,0xEF940000,0xE8000048,0xDFF80048,0xEF940000,0xE8000048,0xE8000048,0xDFF80048,
+0xEF940000,0xE8000048,0xE8000048,0xE8000048,0xFBC80034,0x1F00048,0xFFCC003A,0xFDBC0019,0xFFA40005,0xF9940000,0xEFA40000,0xEF800000,0xF9C80032,0xFBB80019,0xF1A80000,0xE8000048,0xD7FC0048,0x1A4004A,0x1A4004A,0x1A4004A,0x1A4004A,0x1A4004A,0x1A4004A,0x1A4004A,0x1A4004A,0x1A4004A,0x1A4004A,0xEF9C0001,0xEF9C0001,0xEF9C0001,0xEF9C0001,0xEF9C0001,
+0xEF9C0001,0xDF980001,0xDF980001,0xDF980001,0xD9980001,0x7BFC0048,0x7BFC0048,0x7BFC0048,0x7BFC0048,0x7BFC0048,0x7BFC0048,0xE3840001,0xE3840001,0xE3840001,0xD98C0001,0xBFF80048,0xBFF80048,0xBFF80048,0xD9680000,0xD2000048,0xFBA40029,0x1A4004A,0x1A4004A,0xFFA0000D,0xFD9C0002,0xF79C0001,0xF79C0001,0xE99C0001,0xFD9C0020,0xFB98000D,0xE3980001,0xE3840001,
+0xADFC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table60[] = {
+0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0xC3F80000,
+0xC3F80000,0xC3F80000,0xC3F80000,0xD4000001,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1C80000,0x1C80000,0x1C80000,0x83FC0000,0xB3FC0000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,
+0xA9FC0000,0xD5F80000,0xD5F80000,0xD5F80000,0xE0000001,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xD5F80000,0xD5F80000,0xD5F80000,0xE0000001,0xD5F80000,0xD5F80000,0xD5F80000,0xE0000001,0xE0000001,0x9E00000,0x1C40000,0x1C40000,0x35FC0000,0x73FC0000,0x93FC0000,0x93FC0000,0xB9FC0000,0x35FC0000,0x73FC0000,0xC9FC0000,0xD5F80000,
+0xC9FC0000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0xC7FC0000,0xC7FC0000,0xC7FC0000,0xE3FC0000,0xE3FC0000,0xEA000001,0xC7FC0000,0xC7FC0000,0xC7FC0000,0xE3FC0000,0xE3FC0000,0xEA000001,0xE3FC0000,0xE3FC0000,0xEA000001,0xEA000001,0xC7FC0000,0xC7FC0000,0xC7FC0000,0xE3FC0000,0xE3FC0000,0xEA000001,0xE3FC0000,0xE3FC0000,0xEA000001,0xEA000001,0xE3FC0000,
+0xE3FC0000,0xEA000001,0xEA000001,0xEA000001,0x7BFC0000,0x1F80000,0x1D80000,0xB9FC0000,0xD1FC0000,0xDDF80000,0xDFFC0000,0xE5FC0000,0xA3FC0000,0xC7FC0000,0xDDF80000,0xEA000001,0xDDF80000,0x1F00000,0xEBFC0000,0xF5FC0000,0xF6000001,0xEBFC0000,0xF5FC0000,0xF6000001,0xF5FC0000,0xF6000001,0xF6000001,0xEBFC0000,0xF5FC0000,0xF6000001,0xF5FC0000,0xF6000001,
+0xF6000001,0xF5FC0000,0xF6000001,0xF6000001,0xF6000001,0xEBFC0000,0xF5FC0000,0xF6000001,0xF5FC0000,0xF6000001,0xF6000001,0xF5FC0000,0xF6000001,0xF6000001,0xF6000001,0xF5FC0000,0xF6000001,0xF6000001,0xF6000001,0xF6000001,0xDFFC0000,0x97FC0000,0x97FC0000,0xEFFC0000,0xF5F80000,0xF7F40000,0xF6000001,0xF6000001,0xE7FC0000,0xF1FC0000,0xF9C40000,0xF6000001,
+0xF3FC0000,0x1CC0278,0xFFC80181,0xFFC400FD,0xF7C400F5,0xFFC40120,0xFFBC0069,0xFBBC0069,0xFDB80090,0xF7B8004D,0xF1B80092,0xFFBC015B,0xFFB4005D,0xFBB40053,0xFFAC0049,0xF7AC0002,0xF3AC004E,0xF7AC00F4,0xF5A80051,0xF1A80067,0xEDAC00F3,0xB7FC0274,0xFFAC011F,0xF7AC00F4,0xFF9C00AA,0xF99C004A,0xF1A40092,0xFF8800F5,0xF78C0033,0xF18C004F,0xED9400F4,0xDDF40274,
+0xF76800F4,0xF1600092,0xED4C00F3,0xE6000274,0xFFC401B8,0xFFCC0220,0xFFCC0234,0xFFC000F1,0xFFB40059,0xFFAC0002,0xF9B00006,0xF7AC0006,0xFFC401A8,0xFFB800EA,0xF9A80035,0xF18C004F,0xD3FC0274,0x1D800F4,0xFFD00074,0xFFCC0035,0xF7CC0035,0xFFD00074,0xFFC40009,0xF9C40005,0xF9C4004A,0xF7C0000E,0xF1C4004A,0xC9FC00F3,0xFFB80042,0xF9BC0033,0xFFAC0049,0xF7AC0002,
+0xF1B4004A,0xE5F800F3,0xF78C0033,0xF184004A,0xEC0000F3,0xC9FC00F3,0xFFB80042,0xF9BC0033,0xFFAC0049,0xF7AC0002,0xF1B4004A,0xE5F800F3,0xF78C0033,0xF184004A,0xEC0000F3,0xE5F800F3,0xF78C0033,0xF184004A,0xEC0000F3,0xEC0000F3,0xFFD000AB,0xF5D800DE,0xF5D800DD,0xFFC80076,0xFFBC002E,0xFFAC0002,0xF9B40001,0xF7A40003,0xFDD000B5,0xFFC80063,0xFBA00032,0xF184004A,
+0xDFF800F3,0x1C400F4,0x1C400F4,0x1C400F4,0x1C400F4,0xFFBC0059,0xFFBC0059,0xFFBC0059,0xF3B80049,0xF3B80049,0xEBB80049,0xFFB0003E,0xFFB0003E,0xFFB0003E,0xF7AC0001,0xF7AC0001,0xEDB0000E,0xEFAC0032,0xEFAC0032,0xEBAC0005,0xE7AC0032,0xA5FC00F3,0xA5FC00F3,0xA5FC00F3,0xF99C0049,0xF99C0049,0xEBA80049,0xF78C0032,0xF78C0032,0xEB980002,0xE79C0032,0xD3FC00F3,
+0xD3FC00F3,0xEB780049,0xE7640032,0xE00000F3,0xFFBC0095,0xF9C000CC,0x1C400F4,0xFDB80056,0xFFB00018,0xFFAC0001,0xFBAC0004,0xF3AC0001,0xFFB40091,0xFFB00045,0xF7A80032,0xEB980002,0xC7FC00F3,0x1CC0034,0x1CC0034,0x1CC0034,0x1CC0034,0xFFC40000,0xFFC40000,0xFFC40000,0xF1C40000,0xF1C40000,0xEBC40001,0xB7FC0032,0xB7FC0032,0xB7FC0032,0xF3B40001,0xF3B40001,
+0xEBBC0001,0xDDF40032,0xDDF40032,0xEBA00001,0xE6000032,0xB7FC0032,0xB7FC0032,0xB7FC0032,0xF3B40001,0xF3B40001,0xEBBC0001,0xDDF40032,0xDDF40032,0xEBA00001,0xE6000032,0xDDF40032,0xDDF40032,0xEBA00001,0xE6000032,0xE6000032,0xFDC80020,0xFFCC0020,0x1CC0034,0xFDC00014,0xFDBC0005,0xFDB00000,0xF9B40000,0xF3AC0001,0xFFC40020,0xFBC00012,0xD3FC0032,0xEBA00001,
+0xD3FC0032,0x1E40048,0xFFDC0014,0xFDD80001,0xF7D80001,0xD9FC0048,0xFFC80005,0xF7CC0001,0xEDF80048,0xF7A80001,0xF000004A,0xD9FC0048,0xFFC80005,0xF7CC0001,0xEDF80048,0xF7A80001,0xF000004A,0xEDF80048,0xF7A80001,0xF000004A,0xF000004A,0xD9FC0048,0xFFC80005,0xF7CC0001,0xEDF80048,0xF7A80001,0xF000004A,0xEDF80048,0xF7A80001,0xF000004A,0xF000004A,0xEDF80048,
+0xF7A80001,0xF000004A,0xF000004A,0xF000004A,0xF5E4003D,0x37FC0048,0xFBE4003D,0xFFD40029,0xFDCC0019,0xFFAC0001,0xF7B80001,0xF7980001,0xFFDC0032,0xFFCC0028,0xF9BC0001,0xF000004A,0xE7FC0048,0x1B80048,0x1B80048,0x1B80048,0x1B80048,0x1B80048,0x1B80048,0x1B80048,0x1B80048,0x1B80048,0x1B80048,0xFBAC0000,0xFBAC0000,0xFBAC0000,0xFBAC0000,0xFBAC0000,
+0xFBAC0000,0xE7AC0001,0xE7AC0001,0xE7AC0001,0xE1AC0001,0x95FC0048,0x95FC0048,0x95FC0048,0x95FC0048,0x95FC0048,0x95FC0048,0xEB980001,0xEB980001,0xEB980001,0xE1A00001,0xCBFC0048,0xCBFC0048,0xCBFC0048,0xE17C0001,0xDA00004A,0xF3B40034,0x1B80048,0x1B80048,0xFBB40019,0xFDB00008,0xFFAC0001,0xFFAC0001,0xF3AC0000,0xF9B00029,0xFBAC0014,0xEFA80000,0xEB980001,
+0xBFF80048,};
+static const uint32_t g_etc1_to_bc7_m6_table61[] = {
+0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0xCFF80000,
+0xCFF80000,0xCFF80000,0xCFF80000,0xDC000001,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x5D80000,0x5D80000,0x5D80000,0x9BFC0000,0xC1FC0000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,
+0xC1FC0000,0xE1F80000,0xE1F80000,0xE1F80000,0xE8000001,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xE1F80000,0xE1F80000,0xE1F80000,0xE8000001,0xE1F80000,0xE1F80000,0xE1F80000,0xE8000001,0xE8000001,0x1F40000,0x1D40000,0x1D40000,0x6DFC0000,0x9BFC0000,0xB1FC0000,0xB1FC0000,0xCDFC0000,0x6DFC0000,0x9BFC0000,0xD9FC0000,0xE1F80000,
+0xD9FC0000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0xDFFC0000,0xDFFC0000,0xDFFC0000,0xEFFC0000,0xEFFC0000,0xF2000001,0xDFFC0000,0xDFFC0000,0xDFFC0000,0xEFFC0000,0xEFFC0000,0xF2000001,0xEFFC0000,0xEFFC0000,0xF2000001,0xF2000001,0xDFFC0000,0xDFFC0000,0xDFFC0000,0xEFFC0000,0xEFFC0000,0xF2000001,0xEFFC0000,0xEFFC0000,0xF2000001,0xF2000001,0xEFFC0000,
+0xEFFC0000,0xF2000001,0xF2000001,0xF2000001,0xB5FC0000,0x57FC0000,0x1E80000,0xD7FC0000,0xE5FC0000,0xEBFC0000,0xEDFC0000,0xF1F80000,0xCBFC0000,0xDFFC0000,0xEBFC0000,0xF2000001,0xEBFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1DC0255,0xFFDC01AD,0xFFD40125,0xFFD400F4,0xFFD00159,0xFFCC00B4,0xFFCC0074,0xFFCC0099,0xFFC8004C,0xF9C80085,0xFFD00179,0xFFC800AF,0xFFC40054,0xFFC00069,0xFFBC0001,0xF9C00045,0xFFBC00DD,0xFBBC004A,0xF9B8005A,0xF5BC00DE,0xCFFC0253,0xFFC00158,0xFFBC00F3,0xFFB800D3,0xFFAC004E,0xF9B40085,0xFFAC0106,0xFF9C0032,0xF99C0042,0xF5A400DF,0xE7FC0253,
+0xFF7800F3,0xF9700085,0xF55C00DE,0xEE000253,0xFFD801C7,0xF7DC0229,0xF7DC0234,0xFFD40139,0xFFCC00B5,0xFFC0003C,0xFFC0000C,0xFFBC0005,0xFFD401B7,0xFFD00122,0xFFB80036,0xF99C0042,0xE1FC0253,0x1E800DD,0xFDE40095,0xFFE0004D,0xFFDC0034,0xFFDC0089,0xFFD8002C,0xFFD80008,0xFFD40041,0xFDD0000C,0xF9D4003D,0xDFFC00DD,0xFFD80068,0xFFCC0034,0xFFCC0059,0xFFBC0001,
+0xF9C4003D,0xEFFC00DD,0xFF9C0032,0xF994003D,0xF40000DE,0xDFFC00DD,0xFFD80068,0xFFCC0034,0xFFCC0059,0xFFBC0001,0xF9C4003D,0xEFFC00DD,0xFF9C0032,0xF994003D,0xF40000DE,0xEFFC00DD,0xFF9C0032,0xF994003D,0xF40000DE,0xF40000DE,0xFFE400B5,0xFDE800C9,0xFDE800C8,0xFFDC0089,0xFFD40062,0xFFC8001E,0xFFC40001,0xFFB40002,0xFFE000BA,0xFFDC0082,0xFFB80036,0xF994003D,
+0xEBFC00DD,0x1D400F4,0x1D400F4,0x1D400F4,0x1D400F4,0xFDCC0074,0xFDCC0074,0xFDCC0074,0xFBC80049,0xFBC80049,0xF3C80049,0xFFC40054,0xFFC40054,0xFFC40054,0xFFBC0001,0xFFBC0001,0xF5C0000E,0xF7BC0032,0xF7BC0032,0xF3BC0005,0xEFBC0032,0xBDFC00F3,0xBDFC00F3,0xBDFC00F3,0xFDB4004E,0xFDB4004E,0xF3B80049,0xFF9C0032,0xFF9C0032,0xF3A80002,0xEFAC0032,0xDFF800F3,
+0xDFF800F3,0xF3880049,0xEF740032,0xE80000F3,0xFFCC00A8,0xFFCC00E0,0x1D400F4,0xFFCC0071,0xFFC40038,0xFFC00018,0xFFC0000C,0xFBBC0001,0xFDCC00A3,0xFFC40068,0xFFB80032,0xF3A80002,0xD7FC00F3,0x1DC0034,0x1DC0034,0x1DC0034,0x1DC0034,0xFDD80008,0xFDD80008,0xFDD80008,0xF9D40000,0xF9D40000,0xF3D40001,0xCFFC0032,0xCFFC0032,0xCFFC0032,0xFBC40001,0xFBC40001,
+0xF3CC0001,0xE7FC0032,0xE7FC0032,0xF3B00001,0xEE000032,0xCFFC0032,0xCFFC0032,0xCFFC0032,0xFBC40001,0xFBC40001,0xF3CC0001,0xE7FC0032,0xE7FC0032,0xF3B00001,0xEE000032,0xE7FC0032,0xE7FC0032,0xF3B00001,0xEE000032,0xEE000032,0xFFD80022,0xF7DC0029,0x1DC0034,0xFDD80019,0xFDD0000D,0xFFC80005,0xFFC40001,0xFBBC0001,0xF1DC0029,0xFBD40019,0xE1FC0032,0xF3B00001,
+0xE1FC0032,0x1F4003D,0xFFEC0028,0xFFEC000D,0xFFE80000,0xEFFC003D,0xFFE40014,0xFFDC0000,0xF7F8003D,0xFFB80000,0xF800003D,0xEFFC003D,0xFFE40014,0xFFDC0000,0xF7F8003D,0xFFB80000,0xF800003D,0xF7F8003D,0xFFB80000,0xF800003D,0xF800003D,0xEFFC003D,0xFFE40014,0xFFDC0000,0xF7F8003D,0xFFB80000,0xF800003D,0xF7F8003D,0xFFB80000,0xF800003D,0xF800003D,0xF7F8003D,
+0xFFB80000,0xF800003D,0xF800003D,0xF800003D,0xFBF00034,0xA7FC003D,0xF3F4003D,0xFFEC0029,0xFFE80020,0xFFD40011,0xFFC80000,0xFFA80000,0xFFF00032,0xFFEC0032,0xFFD00001,0xF800003D,0xF5FC003D,0x1C80048,0x1C80048,0x1C80048,0x1C80048,0x1C80048,0x1C80048,0x1C80048,0x1C80048,0x1C80048,0x1C80048,0xFFBC0001,0xFFBC0001,0xFFBC0001,0xFFBC0001,0xFFBC0001,
+0xFFBC0001,0xEFBC0001,0xEFBC0001,0xEFBC0001,0xE9BC0001,0xAFFC0048,0xAFFC0048,0xAFFC0048,0xAFFC0048,0xAFFC0048,0xAFFC0048,0xF3A80001,0xF3A80001,0xF3A80001,0xE9B00001,0xD7FC0048,0xD7FC0048,0xD7FC0048,0xE98C0001,0xE200004A,0xFBC40034,0x1C80048,0x1C80048,0xFBC40020,0xFDC00014,0xFDC00008,0xFDC00008,0xFBBC0000,0xF5C40032,0xFFBC001D,0xF7B80000,0xF3A80001,
+0xCDFC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table62[] = {
+0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xDBF80000,
+0xDBF80000,0xDBF80000,0xDBF80000,0xE4000001,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0xDE80000,0xDE80000,0xDE80000,0xB5FC0000,0xD1FC0000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,
+0xD9FC0000,0xEDF80000,0xEDF80000,0xEDF80000,0xF0000001,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xEDF80000,0xEDF80000,0xEDF80000,0xF0000001,0xEDF80000,0xEDF80000,0xEDF80000,0xF0000001,0xF0000001,0x37FC0000,0x1E40000,0x1E40000,0xA7FC0000,0xC1FC0000,0xCFFC0000,0xCFFC0000,0xE1FC0000,0xA7FC0000,0xC1FC0000,0xE7FC0000,0xEDF80000,
+0xE7FC0000,0x1F80000,0x1F80000,0x1F80000,0x1F80000,0xF7FC0000,0xF7FC0000,0xF7FC0000,0xFBFC0000,0xFBFC0000,0xFA000001,0xF7FC0000,0xF7FC0000,0xF7FC0000,0xFBFC0000,0xFBFC0000,0xFA000001,0xFBFC0000,0xFBFC0000,0xFA000001,0xFA000001,0xF7FC0000,0xF7FC0000,0xF7FC0000,0xFBFC0000,0xFBFC0000,0xFA000001,0xFBFC0000,0xFBFC0000,0xFA000001,0xFA000001,0xFBFC0000,
+0xFBFC0000,0xFA000001,0xFA000001,0xFA000001,0xEDFC0000,0xD7FC0000,0x1F80000,0xF5FC0000,0xF9FC0000,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xF3FC0000,0xF7FC0000,0xFBFC0000,0xFA000001,0xFBFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1E80181,0xFFE80139,0xFFE40104,0xFFE400F4,0xFFE000FD,0xFFE000B2,0xFFDC0090,0xFFD80075,0xFFD80051,0xFDD8004D,0xFFDC00FD,0xFFDC00A8,0xFFDC0084,0xFFD80051,0xFFD00021,0xFFD00011,0xFFCC0072,0xFFCC0032,0xFDCC000E,0xF9CC005E,0xE3FC017F,0xFFD80118,0xFFD400F3,0xFFCC00A9,0xFFCC0069,0xFDC8004D,0xFFC000AE,0xFFB80045,0xFDB40006,0xF9B8005E,0xF1F8017F,
+0xFFA800F3,0xFD90004D,0xF97C005E,0xF400017F,0xFFE40135,0xFDE8015D,0xFDE8016C,0xFFE000F5,0xFFDC00A3,0xFFD40055,0xFFD00038,0xFFD0000E,0xFFE40142,0xFFDC00E3,0xFFD0004E,0xFDB40006,0xEDFC017F,0x1F4005D,0xFDF0004D,0xFFF00038,0xFFEC0034,0xFFEC003D,0xFFEC0022,0xFFE80014,0xFFE40011,0xFFE40001,0xFDE40005,0xF1FC005D,0xFFEC0043,0xFFE40034,0xFFE40021,0xFFD80009,
+0xFDD80005,0xF9F8005D,0xFFCC0032,0xFDB40005,0xF800005E,0xF1FC005D,0xFFEC0043,0xFFE40034,0xFFE40021,0xFFD80009,0xFDD80005,0xF9F8005D,0xFFCC0032,0xFDB40005,0xF800005E,0xF9F8005D,0xFFCC0032,0xFDB40005,0xF800005E,0xF800005E,0xFDF00051,0xF3F4005D,0xF3F4005D,0xFFEC0042,0xFFE80030,0xFFE4001B,0xFFE0000D,0xFFD80008,0xFBF00051,0xFFE80044,0xFFDC0033,0xFDB40005,
+0xF7FC005D,0x1E400F4,0x1E400F4,0x1E400F4,0x1E400F4,0xFFDC0090,0xFFDC0090,0xFFDC0090,0xFFD80051,0xFFD80051,0xFBD80049,0xFFDC0084,0xFFDC0084,0xFFDC0084,0xFFD00021,0xFFD00021,0xFDD0000E,0xFFCC0032,0xFFCC0032,0xFBCC0005,0xF7CC0032,0xD5FC00F3,0xD5FC00F3,0xD5FC00F3,0xFFCC0069,0xFFCC0069,0xFBC80049,0xFFB80045,0xFFB80045,0xFBB80002,0xF7BC0032,0xEBF800F3,
+0xEBF800F3,0xFB980049,0xF7840032,0xF00000F3,0xFBE000C9,0xF9E000E1,0x1E400F4,0xFFDC0095,0xFFD80068,0xFFD40045,0xFFD00038,0xFFD0000E,0xFDE000CA,0xFFDC0092,0xFFD0004D,0xFBB80002,0xE5FC00F3,0x1EC0034,0x1EC0034,0x1EC0034,0x1EC0034,0xFFE80014,0xFFE80014,0xFFE80014,0xFFE40001,0xFFE40001,0xFBE40001,0xE9FC0032,0xE9FC0032,0xE9FC0032,0xFFD80009,0xFFD80009,
+0xFBDC0001,0xF3FC0032,0xF3FC0032,0xFBC00001,0xF6000032,0xE9FC0032,0xE9FC0032,0xE9FC0032,0xFFD80009,0xFFD80009,0xFBDC0001,0xF3FC0032,0xF3FC0032,0xFBC00001,0xF6000032,0xF3FC0032,0xF3FC0032,0xFBC00001,0xF6000032,0xF6000032,0xFBEC0029,0xFFEC0029,0x1EC0034,0xF9EC0029,0xFDE80020,0xFFE40012,0xFFE0000D,0xFFD80008,0xF9EC0029,0xFFE80020,0xF1FC0032,0xFBC00001,
+0xF1FC0032,0x1FC0005,0xFFF80004,0xFFF80001,0xFFF80000,0xFBFC0005,0xFFF80002,0xFFF40000,0xFDF80005,0xFFEC0000,0xFC000005,0xFBFC0005,0xFFF80002,0xFFF40000,0xFDF80005,0xFFEC0000,0xFC000005,0xFDF80005,0xFFEC0000,0xFC000005,0xFC000005,0xFBFC0005,0xFFF80002,0xFFF40000,0xFDF80005,0xFFEC0000,0xFC000005,0xFDF80005,0xFFEC0000,0xFC000005,0xFC000005,0xFDF80005,
+0xFFEC0000,0xFC000005,0xFC000005,0xFC000005,0xFFF80004,0xE7FC0005,0xF7FC0005,0xFBFC0005,0xFFF80002,0xFFF00001,0xFFF00000,0xFFE40000,0xF9FC0005,0xFBFC0005,0xFFF00000,0xFC000005,0xFDF80005,0x1D80048,0x1D80048,0x1D80048,0x1D80048,0x1D80048,0x1D80048,0x1D80048,0x1D80048,0x1D80048,0x1D80048,0xFFD00008,0xFFD00008,0xFFD00008,0xFFD00008,0xFFD00008,
+0xFFD00008,0xF7CC0001,0xF7CC0001,0xF7CC0001,0xF1CC0001,0xC7FC0048,0xC7FC0048,0xC7FC0048,0xC7FC0048,0xC7FC0048,0xC7FC0048,0xFBB80001,0xFBB80001,0xFBB80001,0xF1C00001,0xE3FC0048,0xE3FC0048,0xE3FC0048,0xF19C0001,0xEA00004A,0xF5D8003D,0x1D80048,0x1D80048,0xFDD40029,0xFFD0001D,0xFDD00014,0xFDD00014,0xFFCC0004,0xFDD40032,0xFFD00022,0xFFC80000,0xFBB80001,
+0xDDF80048,};
+static const uint32_t g_etc1_to_bc7_m6_table63[] = {
+0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xE7F80000,
+0xE7F80000,0xE7F80000,0xE7F80000,0xEC000001,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1FC0000,0x1FC0000,0x1FC0000,0xCDFC0000,0xDFFC0000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0xF1FC0000,0xF1FC0000,0xF1FC0000,0xF1FC0000,0xF1FC0000,
+0xF1FC0000,0xF9F80000,0xF9F80000,0xF9F80000,0xF8000001,0xF1FC0000,0xF1FC0000,0xF1FC0000,0xF1FC0000,0xF1FC0000,0xF1FC0000,0xF9F80000,0xF9F80000,0xF9F80000,0xF8000001,0xF9F80000,0xF9F80000,0xF9F80000,0xF8000001,0xF8000001,0xB7FC0000,0x1F40000,0x1F40000,0xDFFC0000,0xE9FC0000,0xEFFC0000,0xEFFC0000,0xF3FC0000,0xDFFC0000,0xE9FC0000,0xF7FC0000,0xF9F80000,
+0xF7FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1F400C2,0xFDF000B2,0xFFF0009D,0xFFF00099,0xFFEC0098,0xFFEC007D,0xFFEC0074,0xFFEC0062,0xFFE80058,0xFFE80048,0xFFEC0089,0xFFE80069,0xFFE80059,0xFFE40040,0xFFE40030,0xFFE0001D,0xFFE40031,0xFFE0001D,0xFFDC0001,0xFDDC0011,0xEFFC00C2,0xFFEC00A7,0xFFE80099,0xFFE40070,0xFFE40060,0xFFDC0048,0xFFD80059,0xFFD80035,0xFFCC0009,0xFDCC0011,0xF7F800C2,
+0xFFD40099,0xFFB80048,0xFD9C0011,0xF80000C2,0xFDF000B0,0xF3F400C2,0xF3F400C2,0xFFF0008E,0xFFEC006D,0xFFE8004A,0xFFE8003D,0xFFE40022,0xFFF000A2,0xFFF0008E,0xFFE0003F,0xFFCC0009,0xF5FC00C2,0x1FC0012,0xFFF80011,0xFFF8000E,0xFFF8000D,0xFFF8000C,0xFFF80009,0xFFF80008,0xFFF80006,0xFFF40004,0xFFF40000,0xFBFC0011,0xFFF8000E,0xFFF4000D,0xFFF00008,0xFFF00004,
+0xFFF00000,0xFDF80011,0xFFEC000D,0xFFE00000,0xFC000011,0xFBFC0011,0xFFF8000E,0xFFF4000D,0xFFF00008,0xFFF00004,0xFFF00000,0xFDF80011,0xFFEC000D,0xFFE00000,0xFC000011,0xFDF80011,0xFFEC000D,0xFFE00000,0xFC000011,0xFC000011,0xFFF80011,0xF7FC0012,0xF7FC0012,0xFFF8000C,0xFFF4000E,0xFFF40006,0xFFF40005,0xFFEC0004,0xFFF8000C,0xFBFC0011,0xFFF0000D,0xFFE00000,
+0xFDF80011,0x1F00099,0x1F00099,0x1F00099,0x1F00099,0xFFEC0074,0xFFEC0074,0xFFEC0074,0xFFE80058,0xFFE80058,0xFFE80048,0xFFE80059,0xFFE80059,0xFFE80059,0xFFE40030,0xFFE40030,0xFFE0001D,0xFFE0001D,0xFFE0001D,0xFFDC0001,0xFDDC000D,0xEBFC0099,0xEBFC0099,0xEBFC0099,0xFFE40060,0xFFE40060,0xFFDC0048,0xFFD80035,0xFFD80035,0xFFCC0009,0xFDCC000D,0xF5FC0099,
+0xF5FC0099,0xFFB80048,0xFD9C000D,0xF600009A,0xFFEC0089,0xFFEC0090,0x1F00099,0xFFE80074,0xFFEC005D,0xFFE80046,0xFFE8003D,0xFFE40022,0xFBEC0089,0xFFE80072,0xFFE0003E,0xFFCC0009,0xF3FC0099,0x1F8000D,0x1F8000D,0x1F8000D,0x1F8000D,0xFFF80008,0xFFF80008,0xFFF80008,0xFFF40004,0xFFF40004,0xFFF40000,0xF7FC000D,0xF7FC000D,0xF7FC000D,0xFFF00004,0xFFF00004,
+0xFFF00000,0xFBFC000D,0xFBFC000D,0xFFE00000,0xFC00000D,0xF7FC000D,0xF7FC000D,0xF7FC000D,0xFFF00004,0xFFF00004,0xFFF00000,0xFBFC000D,0xFBFC000D,0xFFE00000,0xFC00000D,0xFBFC000D,0xFBFC000D,0xFFE00000,0xFC00000D,0xFC00000D,0xF5FC000D,0xF5F8000D,0x1F8000D,0xFFF80008,0xFFF4000A,0xFFF40005,0xFFF40005,0xFFEC0004,0xFFF80008,0xFFF4000A,0xFBFC000D,0xFFE00000,
+0xFBFC000D,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1E80048,0x1E80048,0x1E80048,0x1E80048,0x1E80048,0x1E80048,0x1E80048,0x1E80048,0x1E80048,0x1E80048,0xFFE0001D,0xFFE0001D,0xFFE0001D,0xFFE0001D,0xFFE0001D,
+0xFFE0001D,0xFFDC0001,0xFFDC0001,0xFFDC0001,0xF9DC0001,0xDFFC0048,0xDFFC0048,0xDFFC0048,0xDFFC0048,0xDFFC0048,0xDFFC0048,0xFFCC0009,0xFFCC0009,0xFFCC0009,0xF9D00001,0xEFFC0048,0xEFFC0048,0xEFFC0048,0xF9AC0001,0xF200004A,0xFDE8003D,0x1E80048,0x1E80048,0xFDE40034,0xFFE40029,0xFFE00028,0xFFE00028,0xFFE00014,0xF9E8003D,0xFFE40032,0xFFDC000A,0xFFCC0009,
+0xEBFC0048,};
+static const uint32_t g_etc1_to_bc7_m6_table64[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x100001,0x100001,0x100001,0x100001,0x2180000,0x2180000,0x2180000,0x300000,0x300000,0x8000000,0x2180000,0x2180000,0x2180000,0x300000,0x300000,0x8000000,0x300000,0x300000,0x8000000,0x8000000,0x2180000,0x2180000,0x2180000,0x300000,0x300000,0x8000000,0x300000,0x300000,0x8000000,0x8000000,0x300000,
+0x300000,0x8000000,0x8000000,0x8000000,0x140000,0x140000,0x100001,0x180000,0x1C0000,0x240000,0x280000,0x3C0000,0x2140000,0x2180000,0x240000,0x8000000,0x240000,0x380001,0x540000,0xAC0000,0x1C000000,0x540000,0xAC0000,0x1C000000,0xAC0000,0x1C000000,0x1C000000,0x540000,0xAC0000,0x1C000000,0xAC0000,0x1C000000,
+0x1C000000,0xAC0000,0x1C000000,0x1C000000,0x1C000000,0x540000,0xAC0000,0x1C000000,0xAC0000,0x1C000000,0x1C000000,0xAC0000,0x1C000000,0x1C000000,0x1C000000,0xAC0000,0x1C000000,0x1C000000,0x1C000000,0x1C000000,0x480000,0x63C0000,0x63C0000,0x600000,0x8C0000,0x1140000,0x1C000000,0x1C000000,0x24C0000,0x6C0000,0xFD00000,0x1C000000,
+0x780000,0x140232,0x4E080039,0x28080039,0x1C040039,0x380000C8,0x28000011,0x1C000001,0x1C0000C8,0x16000048,0x120000C8,0x260001B9,0x22000096,0x18000051,0x18000110,0x16000088,0x120000EC,0x120001B9,0x1000010D,0x10000149,0xC0001B9,0x1C0232,0x1E000109,0x18000091,0x18000150,0x140000BB,0x12000110,0x120001DD,0x10000131,0xE000165,0xC0001C9,0x300232,
+0x10000186,0xA0001AA,0xA0001F2,0x8000232,0x7400007B,0xFA0400D2,0xFE0C0082,0x3400007B,0x2200008A,0x1A00007B,0x16000061,0x140000B5,0x460000F1,0x280000BD,0x160000CB,0xE000165,0x240232,0x1801BA,0x4E080029,0x28080029,0x1C080029,0x380000C8,0x28000011,0x1C000001,0x1C0000C8,0x16000048,0x120000C8,0x22401B9,0x22000096,0x18000051,0x18000110,0x16000088,
+0x120000EC,0x4C01B9,0x1000010D,0x10000149,0xC0001B9,0x22401B9,0x22000096,0x18000051,0x18000110,0x16000088,0x120000EC,0x4C01B9,0x1000010D,0x10000149,0xC0001B9,0x4C01B9,0x1000010D,0x10000149,0xC0001B9,0xC0001B9,0x7400007B,0xFA0400CE,0xFE0C005E,0x3400007B,0x2200008A,0x1A00007B,0x16000061,0x140000B5,0x500000DB,0x280000B4,0x160000CA,0x10000149,
+0x3401B9,0x40039,0x40039,0x40039,0x40039,0x1A000000,0x1A000000,0x1A000000,0xC000000,0xC000000,0x8000000,0xA000029,0xA000029,0xA000029,0xC000010,0xC000010,0x6000008,0x6000029,0x6000029,0x4000019,0x4000029,0x80036,0x80036,0x80036,0x6000018,0x6000018,0x600000C,0x600002D,0x600002D,0x400001D,0x400002D,0xC0036,
+0xC0036,0x4000022,0x2000031,0x2000036,0x3600000A,0x88000000,0x40039,0x1C000011,0x1000000D,0xC00000D,0xC00000A,0xA000011,0x1600001A,0x10000013,0x6000029,0x400001D,0xC0036,0x80029,0x80029,0x80029,0x80029,0x1A000000,0x1A000000,0x1A000000,0xC000000,0xC000000,0x8000000,0xC0029,0xC0029,0xC0029,0xC000010,0xC000010,
+0x6000008,0x140029,0x140029,0x4000019,0x4000029,0xC0029,0xC0029,0xC0029,0xC000010,0xC000010,0x6000008,0x140029,0x140029,0x4000019,0x4000029,0x140029,0x140029,0x4000019,0x4000029,0x4000029,0x3600000A,0x88000000,0x80029,0x1C000011,0x1000000D,0xC00000D,0xC00000A,0xA000011,0x16000019,0x10000012,0x100029,0x4000019,
+0x100029,0x2400CA,0x42140001,0x26100001,0x1C100001,0x3800C8,0x28000011,0x1C000001,0x7000C8,0x16000048,0x120000C8,0x3800C8,0x28000011,0x1C000001,0x7000C8,0x16000048,0x120000C8,0x7000C8,0x16000048,0x120000C8,0x120000C8,0x3800C8,0x28000011,0x1C000001,0x7000C8,0x16000048,0x120000C8,0x7000C8,0x16000048,0x120000C8,0x120000C8,0x7000C8,
+0x16000048,0x120000C8,0x120000C8,0x120000C8,0x7400004A,0x2800C8,0xF418000D,0x3C000041,0x2A000049,0x1E000041,0x18000034,0x18000061,0x50000062,0x34000050,0x1C000028,0x120000C8,0x5000C8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table65[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x200001,0x200001,0x200001,0x200001,0x2300000,0x2300000,0x2300000,0x640000,0x640000,0x10000000,0x2300000,0x2300000,0x2300000,0x640000,0x640000,0x10000000,0x640000,0x640000,0x10000000,0x10000000,0x2300000,0x2300000,0x2300000,0x640000,0x640000,0x10000000,0x640000,0x640000,0x10000000,0x10000000,0x640000,
+0x640000,0x10000000,0x10000000,0x10000000,0x280000,0x240000,0x200001,0x22C0000,0x380000,0x480000,0x500000,0x780000,0x2280000,0x2300000,0x480000,0x10000000,0x480000,0x480001,0x6C0000,0xDC0000,0x24000000,0x6C0000,0xDC0000,0x24000000,0xDC0000,0x24000000,0x24000000,0x6C0000,0xDC0000,0x24000000,0xDC0000,0x24000000,
+0x24000000,0xDC0000,0x24000000,0x24000000,0x24000000,0x6C0000,0xDC0000,0x24000000,0xDC0000,0x24000000,0x24000000,0xDC0000,0x24000000,0x24000000,0x24000000,0xDC0000,0x24000000,0x24000000,0x24000000,0x24000000,0x5C0000,0xE4C0000,0xE4C0000,0x7C0000,0xB40000,0x1600000,0x24000000,0x24000000,0x640000,0x880000,0x17E00000,0x24000000,
+0x9C0000,0x1C03A2,0x620C00C1,0x320C00C2,0x240C00C1,0x500000C8,0x34000001,0x26000014,0x260000CA,0x20000029,0x1A0000C8,0x360002AE,0x2E0000FE,0x220000A1,0x22000153,0x1E000098,0x18000110,0x1A0002AE,0x160001A9,0x160001C9,0x100002B1,0x2803A2,0x280001B3,0x2200011A,0x220001CC,0x1E0000FC,0x18000150,0x180002F1,0x160001E9,0x14000205,0x100002D5,0x4C03A2,
+0x1600028A,0x10000282,0x1000032A,0xC0003A2,0x96000085,0xFE0C0142,0xF2140189,0x48000099,0x360000A2,0x26000098,0x1E000065,0x1C0000E0,0x6400015C,0x3C0000E9,0x1E000145,0x14000205,0x3403A2,0x2402AE,0x5E100091,0x32100091,0x24100091,0x500000C8,0x34000001,0x26040011,0x260000CA,0x20000029,0x1A0000C8,0x3402AE,0x2E0000FE,0x220000A1,0x22000153,0x1E000098,
+0x18000110,0x6802AE,0x160001A9,0x160001C9,0x100002B1,0x3402AE,0x2E0000FE,0x220000A1,0x22000153,0x1E000098,0x18000110,0x6802AE,0x160001A9,0x160001C9,0x100002B1,0x6802AE,0x160001A9,0x160001C9,0x100002B1,0x100002B1,0x96000085,0xFE0C011E,0xF418010D,0x48000099,0x360000A2,0x26000098,0x1E000065,0x1C0000E0,0x64000138,0x3C0000D9,0x1E000141,0x160001C9,
+0x4C02AE,0xC00C1,0xC00C1,0xC00C1,0xC00C1,0x32000000,0x32000000,0x32000000,0x18000000,0x18000000,0x10000000,0x16000091,0x16000091,0x16000091,0x12000034,0x12000034,0xE00001D,0xC000091,0xC000091,0xA000055,0x8000091,0x1000C1,0x1000C1,0x1000C1,0x12000058,0x12000058,0xC000030,0xC0000A1,0xC0000A1,0xA000065,0x6000099,0x2000C1,
+0x2000C1,0xA000086,0x60000AE,0x40000C2,0x6000002D,0xF8000001,0xC00C1,0x3200003A,0x1E000034,0x1A00003A,0x1600002D,0xE000048,0x3400005E,0x26000054,0xE000092,0xA000065,0x1800C1,0x100091,0x100091,0x100091,0x100091,0x32000000,0x32000000,0x32000000,0x18000000,0x18000000,0x10000000,0x180091,0x180091,0x180091,0x12000034,0x12000034,
+0xE00001D,0x2C0091,0x2C0091,0xA000055,0x8000091,0x180091,0x180091,0x180091,0x12000034,0x12000034,0xE00001D,0x2C0091,0x2C0091,0xA000055,0x8000091,0x2C0091,0x2C0091,0xA000055,0x8000091,0x8000091,0x6000002D,0xF8000001,0x100091,0x3200003A,0x1E000034,0x1A00003A,0x1600002D,0xE000048,0x34000055,0x26000050,0x200091,0xA000055,
+0x200091,0x3400CA,0x4A240001,0x2E200001,0x24200001,0x5000C8,0x34000001,0x240C0001,0xA000C8,0x20000029,0x1A0000C8,0x5000C8,0x34000001,0x240C0001,0xA000C8,0x20000029,0x1A0000C8,0xA000C8,0x20000029,0x1A0000C8,0x1A0000C8,0x5000C8,0x34000001,0x240C0001,0xA000C8,0x20000029,0x1A0000C8,0xA000C8,0x20000029,0x1A0000C8,0x1A0000C8,0xA000C8,
+0x20000029,0x1A0000C8,0x1A0000C8,0x1A0000C8,0xA400002D,0x43800C8,0xFC28000D,0x52000022,0x36000029,0x28000029,0x22000014,0x20000041,0x72000048,0x46000034,0x2400000D,0x1A0000C8,0x7000C8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table66[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0x140000,0x140000,0x140000,0x140000,0x140000,
+0x140000,0x240000,0x240000,0x240000,0x6000000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x240000,0x240000,0x240000,0x6000000,0x240000,0x240000,0x240000,0x6000000,0x6000000,0xE0C0000,0xC0001,0xC0001,0x100000,0x100000,0x2100000,0x2100000,0x2140000,0x100000,0x100000,0x1C0000,0x240000,
+0x1C0000,0x300001,0x300001,0x300001,0x300001,0x480000,0x480000,0x480000,0x940000,0x940000,0x18000000,0x480000,0x480000,0x480000,0x940000,0x940000,0x18000000,0x940000,0x940000,0x18000000,0x18000000,0x480000,0x480000,0x480000,0x940000,0x940000,0x18000000,0x940000,0x940000,0x18000000,0x18000000,0x940000,
+0x940000,0x18000000,0x18000000,0x18000000,0x4380000,0x2340000,0x300001,0x440000,0x540000,0x680000,0x780000,0xB40000,0x23C0000,0x480000,0x680000,0x18000000,0x680000,0x580001,0x840000,0x10C0000,0x2C000000,0x840000,0x10C0000,0x2C000000,0x10C0000,0x2C000000,0x2C000000,0x840000,0x10C0000,0x2C000000,0x10C0000,0x2C000000,
+0x2C000000,0x10C0000,0x2C000000,0x2C000000,0x2C000000,0x840000,0x10C0000,0x2C000000,0x10C0000,0x2C000000,0x2C000000,0x10C0000,0x2C000000,0x2C000000,0x2C000000,0x10C0000,0x2C000000,0x2C000000,0x2C000000,0x2C000000,0x700000,0x600000,0x600000,0x2940000,0xDC0000,0x1B00000,0x2C000000,0x2C000000,0x2780000,0xA80000,0x1FF00000,0x2C000000,
+0xBC0000,0x2804C3,0x7414014E,0x3C14014F,0x2C14014E,0x600800E1,0x4008001A,0x2C0C0049,0x300800E3,0x28040036,0x220800E1,0x4E0002D3,0x3A0000CD,0x2C0000A4,0x2E00011A,0x2800003D,0x220000D8,0x260002D3,0x2000017A,0x1C0001A0,0x180002D4,0x3804C1,0x34000216,0x2800016D,0x280001F7,0x280000E6,0x22000151,0x22000354,0x200001F3,0x1C000204,0x18000314,0x7004C1,
+0x1C00031D,0x1A000305,0x160003C9,0x120004C1,0xC2000036,0xF41801F1,0xF8200266,0x6600003E,0x40000049,0x34000043,0x2A000015,0x24000084,0x82000121,0x5000009F,0x26000118,0x1C000204,0x5004C1,0x3402D3,0x662000A2,0x3A2000A2,0x2C2000A2,0x581000C9,0x3C100002,0x2E100015,0x300C00C9,0x2A080026,0x220C00C9,0x4C02D3,0x3A0000CD,0x2C0400A2,0x2E00011A,0x2800003D,
+0x220000D8,0x9802D3,0x2000017A,0x1C0001A0,0x180002D4,0x4C02D3,0x3A0000CD,0x2C0400A2,0x2E00011A,0x2800003D,0x220000D8,0x9802D3,0x2000017A,0x1C0001A0,0x180002D4,0x9802D3,0x2000017A,0x1C0001A0,0x180002D4,0x180002D4,0xC2000036,0xF8200139,0xFC280126,0x6600003E,0x40000049,0x34000043,0x2A000015,0x24000084,0x900000DD,0x50000086,0x26000114,0x1C0001A0,
+0x6C02D3,0x14014E,0x14014E,0x14014E,0x14014E,0x42080019,0x42080019,0x42080019,0x22080019,0x22080019,0x18080019,0x300000A2,0x300000A2,0x300000A2,0x22000011,0x22000011,0x18000001,0x160000A4,0x160000A4,0x14000041,0xE0000A4,0x20014D,0x20014D,0x20014D,0x1E00007D,0x1E00007D,0x14000041,0x120000D8,0x120000D8,0x1200006C,0xE0000BD,0x3C014D,
+0x3C014D,0x100000C9,0xA000105,0xA00014D,0xA000000D,0xFE0C002E,0x14014E,0x50000019,0x32000019,0x2A000014,0x2600000D,0x20000025,0x56000063,0x3C000042,0x1E0000A6,0x1200006C,0x2C014D,0x2000A2,0x2000A2,0x2000A2,0x2000A2,0x3A100001,0x3A100001,0x3A100001,0x20100001,0x20100001,0x180C0001,0x3000A2,0x3000A2,0x3000A2,0x22000011,0x22000011,
+0x18000001,0x5C00A2,0x5C00A2,0x14000041,0xE0000A4,0x3000A2,0x3000A2,0x3000A2,0x22000011,0x22000011,0x18000001,0x5C00A2,0x5C00A2,0x14000041,0xE0000A4,0x5C00A2,0x5C00A2,0x14000041,0xE0000A4,0xE0000A4,0xA000000D,0xF0100005,0x2000A2,0x50000019,0x32000019,0x2A000014,0x2600000D,0x20000025,0x64000041,0x3C000032,0x4000A2,0x14000041,
+0x4000A2,0x4400CA,0x52340001,0x36300001,0x2C300001,0x6800C8,0x3C100001,0x2C1C0001,0xD000C8,0x2A000014,0x220000C8,0x6800C8,0x3C100001,0x2C1C0001,0xD000C8,0x2A000014,0x220000C8,0xD000C8,0x2A000014,0x220000C8,0x220000C8,0x6800C8,0x3C100001,0x2C1C0001,0xD000C8,0x2A000014,0x220000C8,0xD000C8,0x2A000014,0x220000C8,0x220000C8,0xD000C8,
+0x2A000014,0x220000C8,0x220000C8,0x220000C8,0xC4040019,0xC4800C8,0xF4380012,0x6600000D,0x42040019,0x36000011,0x2C000004,0x28000029,0x94000032,0x58000019,0x2E000001,0x220000C8,0x9400C8,0x80019,0x80019,0x80019,0x80019,0x80019,0x80019,0x80019,0x80019,0x80019,0x80019,0x14000000,0x14000000,0x14000000,0x14000000,0x14000000,
+0x14000000,0xA000000,0xA000000,0xA000000,0x6000000,0x80019,0x80019,0x80019,0x80019,0x80019,0x80019,0x6000008,0x6000008,0x6000008,0x6000004,0xC0019,0xC0019,0xC0019,0x400000D,0x2000019,0x68000000,0x80019,0x80019,0x2E000000,0x20000000,0x18000000,0x18000000,0x10000000,0x20000008,0x20000004,0xC000001,0x6000008,
+0xC0019,};
+static const uint32_t g_etc1_to_bc7_m6_table67[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,
+0x2C0000,0x580000,0x580000,0x580000,0xE000000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x580000,0x580000,0x580000,0xE000000,0x580000,0x580000,0x580000,0xE000000,0xE000000,0x200000,0x1C0001,0x1C0001,0x6200000,0x240000,0x280000,0x280000,0x300000,0x6200000,0x240000,0x3C0000,0x580000,
+0x3C0000,0x400001,0x400001,0x400001,0x400001,0x600000,0x600000,0x600000,0xC40000,0xC40000,0x20000000,0x600000,0x600000,0x600000,0xC40000,0xC40000,0x20000000,0xC40000,0xC40000,0x20000000,0x20000000,0x600000,0x600000,0x600000,0xC40000,0xC40000,0x20000000,0xC40000,0xC40000,0x20000000,0x20000000,0xC40000,
+0xC40000,0x20000000,0x20000000,0x20000000,0x4C0000,0xA440000,0x400001,0x580000,0x26C0000,0x8C0000,0xA00000,0xF00000,0x4500000,0x600000,0x8C0000,0x20000000,0x8C0000,0x680001,0x9C0000,0x13C0000,0x34000000,0x9C0000,0x13C0000,0x34000000,0x13C0000,0x34000000,0x34000000,0x9C0000,0x13C0000,0x34000000,0x13C0000,0x34000000,
+0x34000000,0x13C0000,0x34000000,0x34000000,0x34000000,0x9C0000,0x13C0000,0x34000000,0x13C0000,0x34000000,0x34000000,0x13C0000,0x34000000,0x34000000,0x34000000,0x13C0000,0x34000000,0x34000000,0x34000000,0x34000000,0x840000,0x700000,0x700000,0xB00000,0x1000000,0x3F00000,0x34000000,0x34000000,0x900000,0xC40000,0x29C40000,0x34000000,
+0xE00000,0x340627,0x80200222,0x46200222,0x34200222,0x72100139,0x4C100076,0x361400C1,0x3A10013B,0x320C0082,0x2A100139,0x660002D3,0x4C0000A5,0x360800C8,0x3C0000E9,0x32000009,0x2A0000C9,0x320002D3,0x2C00012A,0x26000161,0x200002D4,0x480625,0x400002BE,0x34000225,0x3400024F,0x2E000106,0x2800017D,0x2E0003BC,0x280001FB,0x24000204,0x1E00034C,0x940625,
+0x26000412,0x200003A5,0x1C00047D,0x18000625,0xF8000009,0xFA2402DD,0xFE2C038E,0x7E00000B,0x5600000E,0x40000009,0x36000004,0x30000032,0xA40000F6,0x66000062,0x340000D4,0x24000204,0x680625,0x4402D3,0x6E3000A2,0x423000A2,0x343000A2,0x602000C9,0x44200002,0x36200015,0x381C00C9,0x32180026,0x2A1C00C9,0x6402D3,0x4C0000A5,0x341400A2,0x3C0000E9,0x32000009,
+0x2A0400C8,0xCC02D3,0x2C00012A,0x26000161,0x200002D4,0x6402D3,0x4C0000A5,0x341400A2,0x3C0000E9,0x32000009,0x2A0400C8,0xCC02D3,0x2C00012A,0x26000161,0x200002D4,0xCC02D3,0x2C00012A,0x26000161,0x200002D4,0x200002D4,0xF8000009,0xFE2C0141,0xF438013B,0x7E00000B,0x5600000E,0x40000009,0x34040002,0x30000032,0xAC000086,0x68000035,0x340000CB,0x26000161,
+0x9002D3,0x200222,0x200222,0x200222,0x200222,0x52100071,0x52100071,0x52100071,0x2C100071,0x2C100071,0x20100071,0x480000A2,0x480000A2,0x480000A2,0x2E000001,0x2E000001,0x2204000C,0x220000A2,0x220000A2,0x1C000020,0x160000A4,0x300222,0x300222,0x300222,0x280000C6,0x280000C6,0x1E000081,0x1E000118,0x1E000118,0x1A00007E,0x160000E4,0x5C0222,
+0x5C0222,0x16000145,0x14000178,0xE000225,0xE8000000,0xF21400BD,0x200222,0x7A000004,0x50000001,0x3C000002,0x36000000,0x2A000005,0x8200006D,0x56000032,0x2C0000AB,0x1A00007E,0x400222,0x3000A2,0x3000A2,0x3000A2,0x3000A2,0x42200001,0x42200001,0x42200001,0x28200001,0x28200001,0x201C0001,0x24400A2,0x24400A2,0x24400A2,0x2E000001,0x2E000001,
+0x200C0000,0x8C00A2,0x8C00A2,0x1C000020,0x160000A4,0x24400A2,0x24400A2,0x24400A2,0x2E000001,0x2E000001,0x200C0000,0x8C00A2,0x8C00A2,0x1C000020,0x160000A4,0x8C00A2,0x8C00A2,0x1C000020,0x160000A4,0x160000A4,0xE8000000,0xF8200005,0x3000A2,0x7A000004,0x50000001,0x3C000002,0x36000000,0x2A000005,0x96000028,0x5A000012,0x6400A2,0x1C000020,
+0x6400A2,0x5400CA,0x5A440001,0x3E400001,0x34400001,0x8000C8,0x44200001,0x342C0001,0x10000C8,0x32000005,0x2A0000C8,0x8000C8,0x44200001,0x342C0001,0x10000C8,0x32000005,0x2A0000C8,0x10000C8,0x32000005,0x2A0000C8,0x2A0000C8,0x8000C8,0x44200001,0x342C0001,0x10000C8,0x32000005,0x2A0000C8,0x10000C8,0x32000005,0x2A0000C8,0x2A0000C8,0x10000C8,
+0x32000005,0x2A0000C8,0x2A0000C8,0x2A0000C8,0xF8000008,0x5C00C8,0xFC480012,0x7E000002,0x56000005,0x3E040005,0x34080000,0x32000014,0xB6000020,0x6E00000A,0x36100001,0x2A0000C8,0xB400C8,0x100071,0x100071,0x100071,0x100071,0x100071,0x100071,0x100071,0x100071,0x100071,0x100071,0x2C000000,0x2C000000,0x2C000000,0x2C000000,0x2C000000,
+0x2C000000,0x16000000,0x16000000,0x16000000,0xE000000,0x140071,0x140071,0x140071,0x140071,0x140071,0x140071,0x12000028,0x12000028,0x12000028,0xC000014,0x240071,0x240071,0x240071,0xA000041,0x6000071,0xE8000000,0x100071,0x100071,0x68000000,0x48000000,0x36000000,0x36000000,0x24000000,0x52000022,0x42000011,0x1C000004,0x12000028,
+0x1C0071,};
+static const uint32_t g_etc1_to_bc7_m6_table68[] = {
+0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0x140000,
+0x140000,0x140000,0x140000,0x2000001,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0xC0000,0x100000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,
+0x2440000,0x8C0000,0x8C0000,0x8C0000,0x16000001,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x8C0000,0x8C0000,0x8C0000,0x16000001,0x8C0000,0x8C0000,0x8C0000,0x16000001,0x16000001,0x340000,0x300000,0x300000,0x380000,0x3C0000,0x400000,0x400000,0x500000,0x380000,0x3C0000,0x640000,0x8C0000,
+0x640000,0x540000,0x540000,0x540000,0x540000,0x7C0000,0x7C0000,0x7C0000,0xFC0000,0xFC0000,0x28000001,0x7C0000,0x7C0000,0x7C0000,0xFC0000,0xFC0000,0x28000001,0xFC0000,0xFC0000,0x28000001,0x28000001,0x7C0000,0x7C0000,0x7C0000,0xFC0000,0xFC0000,0x28000001,0xFC0000,0xFC0000,0x28000001,0x28000001,0xFC0000,
+0xFC0000,0x28000001,0x28000001,0x28000001,0x2600000,0x4580000,0x540000,0x2700000,0x8C0000,0xB00000,0xCC0000,0x1340000,0x680000,0x7C0000,0xB00000,0x28000001,0xB00000,0x7C0000,0xB80000,0x1740000,0x3C000001,0xB80000,0x1740000,0x3C000001,0x1740000,0x3C000001,0x3C000001,0xB80000,0x1740000,0x3C000001,0x1740000,0x3C000001,
+0x3C000001,0x1740000,0x3C000001,0x3C000001,0x3C000001,0xB80000,0x1740000,0x3C000001,0x1740000,0x3C000001,0x3C000001,0x1740000,0x3C000001,0x3C000001,0x3C000001,0x1740000,0x3C000001,0x3C000001,0x3C000001,0x3C000001,0x9C0000,0x840000,0x840000,0xD00000,0x12C0000,0xDF80000,0x3C000001,0x3C000001,0xA80000,0xE80000,0x31F40000,0x3C000001,
+0x1080000,0x400738,0x8A3002D4,0x503002D4,0x3C3002D5,0x801C0190,0x581C00D5,0x3E24013A,0x461C0190,0x3A1C00D5,0x321C0192,0x7A0802D3,0x5A0800A2,0x421400FF,0x4A0800D1,0x3C080002,0x320C00D7,0x3C0802D4,0x380000FD,0x3000013B,0x2A0802D3,0x600734,0x5200031F,0x3C0802D4,0x46000252,0x3A000107,0x320001A4,0x3A0003C9,0x340001AE,0x2E0001B3,0x2800032C,0xC40734,
+0x2C000479,0x2C0003F2,0x260004DF,0x20000734,0xFC100021,0xF23403D0,0xF63C049C,0x92080000,0x64080001,0x4A080002,0x3E0C0012,0x3A080011,0xD000008E,0x7E000018,0x3E0000AB,0x2E0001B3,0x8C0734,0x5402D4,0x764400A4,0x4A4400A4,0x3C4000A5,0x6C3000C8,0x4E300001,0x3E340015,0x403000C8,0x3A2C0026,0x323000CA,0x8002D3,0x580C00A2,0x3C2800A3,0x4C0000C9,0x3C080002,
+0x341400CA,0x10002D3,0x380000ED,0x3000012B,0x2A0002D3,0x8002D3,0x580C00A2,0x3C2800A3,0x4C0000C9,0x3C080002,0x341400CA,0x10002D3,0x380000ED,0x3000012B,0x2A0002D3,0x10002D3,0x380000ED,0x3000012B,0x2A0002D3,0x2A0002D3,0xFE140009,0xFA44014C,0xFE4C0138,0x92080000,0x64080001,0x4A080002,0x3E140002,0x3A00000A,0xD000003D,0x7E000008,0x3E0000AB,0x3000012B,
+0xB402D3,0x3002D4,0x3002D4,0x3002D4,0x3002D4,0x621C00C8,0x621C00C8,0x621C00C8,0x361C00C8,0x361C00C8,0x281C00C9,0x5A0800A2,0x5A0800A2,0x5A0800A2,0x3C080001,0x3C080001,0x2C0C0026,0x2E0800A2,0x2E0800A2,0x28040015,0x200800A2,0x4402D3,0x4402D3,0x4402D3,0x340000FE,0x340000FE,0x2A0000C9,0x2E00011D,0x2E00011D,0x2400005A,0x1E0000CE,0x8802D3,
+0x8802D3,0x20000199,0x1C0001A3,0x160002D3,0xFE0C0009,0xFA240139,0x3002D4,0x92080000,0x60080001,0x4A080001,0x440C0006,0x36080002,0xB400004B,0x76000012,0x3E0000A2,0x2400005A,0x6002D3,0x4000A4,0x4000A4,0x4000A4,0x4000A4,0x4E300000,0x4E300000,0x4E300000,0x32300000,0x32300000,0x28300001,0x6000A2,0x6000A2,0x6000A2,0x38100001,0x38100001,
+0x28200001,0xC400A2,0xC400A2,0x2600000D,0x200000A2,0x6000A2,0x6000A2,0x6000A2,0x38100001,0x38100001,0x28200001,0xC400A2,0xC400A2,0x2600000D,0x200000A2,0xC400A2,0xC400A2,0x2600000D,0x200000A2,0x200000A2,0xEA140000,0xF2340008,0x4000A4,0x92080000,0x5E0C0000,0x480C0000,0x3E140001,0x38040000,0xC200000D,0x7C000002,0x8C00A2,0x2600000D,
+0x8C00A2,0x6800C8,0x66540000,0x46540001,0x3C540001,0x29800C8,0x4E300001,0x3C400001,0x13800C8,0x3C040001,0x320000CA,0x29800C8,0x4E300001,0x3C400001,0x13800C8,0x3C040001,0x320000CA,0x13800C8,0x3C040001,0x320000CA,0x320000CA,0x29800C8,0x4E300001,0x3C400001,0x13800C8,0x3C040001,0x320000CA,0x13800C8,0x3C040001,0x320000CA,0x320000CA,0x13800C8,
+0x3C040001,0x320000CA,0x320000CA,0x320000CA,0xFE140008,0xE6C00C8,0xF65C0019,0x8E0C0000,0x64040001,0x4C040000,0x3C1C0001,0x3A00000A,0xD6040012,0x7E040002,0x40200000,0x320000CA,0xDC00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x40080000,0x40080000,0x40080000,0x40080000,0x40080000,
+0x40080000,0x20080001,0x20080001,0x20080001,0x16080001,0x2800C8,0x2800C8,0x2800C8,0x2800C8,0x2800C8,0x2800C8,0x1E00002D,0x1E00002D,0x1E00002D,0x16000011,0x5000C8,0x5000C8,0x5000C8,0x10000062,0xC0000CA,0xFE0C0008,0x1C00C8,0x1C00C8,0x8E080000,0x64080000,0x4E080000,0x4E080000,0x34080000,0x92000022,0x74000009,0x28040001,0x1E00002D,
+0x3800C8,};
+static const uint32_t g_etc1_to_bc7_m6_table69[] = {
+0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x240000,0x240000,0x240000,0x240000,0x240000,0x240000,0x240000,0x240000,0x240000,0x240000,0x440000,
+0x440000,0x440000,0x440000,0xA000001,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x4180000,0x4180000,0x4180000,0x240000,0x300000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,
+0x25C0000,0xBC0000,0xBC0000,0xBC0000,0x1E000001,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0xBC0000,0xBC0000,0xBC0000,0x1E000001,0xBC0000,0xBC0000,0xBC0000,0x1E000001,0x1E000001,0x440000,0x400000,0x400000,0x4480000,0x500000,0x2540000,0x2540000,0x6C0000,0x4480000,0x500000,0x880000,0xBC0000,
+0x880000,0x640000,0x640000,0x640000,0x640000,0x940000,0x940000,0x940000,0x12C0000,0x12C0000,0x30000001,0x940000,0x940000,0x940000,0x12C0000,0x12C0000,0x30000001,0x12C0000,0x12C0000,0x30000001,0x30000001,0x940000,0x940000,0x940000,0x12C0000,0x12C0000,0x30000001,0x12C0000,0x12C0000,0x30000001,0x30000001,0x12C0000,
+0x12C0000,0x30000001,0x30000001,0x30000001,0x740000,0xC680000,0x640000,0x880000,0xA80000,0xD40000,0xF40000,0x1700000,0x7C0000,0x940000,0xD40000,0x30000001,0xD40000,0x8C0000,0xD00000,0x1A40000,0x44000001,0xD00000,0x1A40000,0x44000001,0x1A40000,0x44000001,0x44000001,0xD00000,0x1A40000,0x44000001,0x1A40000,0x44000001,
+0x44000001,0x1A40000,0x44000001,0x44000001,0x44000001,0xD00000,0x1A40000,0x44000001,0x1A40000,0x44000001,0x44000001,0x1A40000,0x44000001,0x44000001,0x44000001,0x1A40000,0x44000001,0x44000001,0x44000001,0x44000001,0xB00000,0x2940000,0x2940000,0xEC0000,0x1540000,0x17F80000,0x44000001,0x44000001,0x2BC0000,0x1040000,0x3BC80000,0x44000001,
+0x1280000,0x500738,0x924002D4,0x584002D4,0x444002D5,0x882C0190,0x602C00D5,0x4634013A,0x4E2C0190,0x422C00D5,0x3A2C0192,0x821802D3,0x621800A2,0x4A2400FF,0x521800D1,0x44180002,0x3A1C00D7,0x441802D4,0x401000FD,0x3810013B,0x321802D3,0x780734,0x620002DD,0x441802D4,0x520001E2,0x460000CF,0x3A080192,0x46000361,0x4000011E,0x3800012F,0x300002EB,0xF40734,
+0x38000401,0x32000352,0x2C000477,0x28000734,0xFE20002A,0xFA4403D0,0xFE4C049C,0x9A180000,0x6C180001,0x52180002,0x461C0012,0x42180011,0xF6000022,0x8E080002,0x480C00A9,0x3800012F,0xAC0734,0x6402D4,0x7E5400A4,0x525400A4,0x445000A5,0x744000C8,0x56400001,0x46440015,0x484000C8,0x423C0026,0x3A4000CA,0x9802D3,0x601C00A2,0x443800A3,0x541000C9,0x44180002,
+0x3C2400CA,0x13002D3,0x420000CB,0x380000FE,0x320002D3,0x9802D3,0x601C00A2,0x443800A3,0x541000C9,0x44180002,0x3C2400CA,0x13002D3,0x420000CB,0x380000FE,0x320002D3,0x13002D3,0x420000CB,0x380000FE,0x320002D3,0x320002D3,0xF8280011,0xF254015E,0xF65C014D,0x9A180000,0x6C180001,0x52180002,0x46240002,0x440C0005,0xFA000013,0x8E080001,0x4A0400A2,0x380000FE,
+0xD802D3,0x4002D4,0x4002D4,0x4002D4,0x4002D4,0x6A2C00C8,0x6A2C00C8,0x6A2C00C8,0x3E2C00C8,0x3E2C00C8,0x302C00C9,0x621800A2,0x621800A2,0x621800A2,0x44180001,0x44180001,0x341C0026,0x361800A2,0x361800A2,0x30140015,0x281800A2,0x5C02D3,0x5C02D3,0x5C02D3,0x460000CE,0x460000CE,0x321000C9,0x3A0000D5,0x3A0000D5,0x2E000012,0x280000A3,0xB802D3,
+0xB802D3,0x2A00015B,0x2400016B,0x1E0002D3,0xFC1C0011,0xF234014C,0x4002D4,0x9A180000,0x68180001,0x52180001,0x4C1C0006,0x3E180002,0xE400000D,0x8E080001,0x461000A2,0x2E000012,0x8002D3,0x5000A4,0x5000A4,0x5000A4,0x5000A4,0x56400000,0x56400000,0x56400000,0x3A400000,0x3A400000,0x30400001,0x7800A2,0x7800A2,0x7800A2,0x40200001,0x40200001,
+0x30300001,0xF400A2,0xF400A2,0x30000002,0x280000A2,0x7800A2,0x7800A2,0x7800A2,0x40200001,0x40200001,0x30300001,0xF400A2,0xF400A2,0x30000002,0x280000A2,0xF400A2,0xF400A2,0x30000002,0x280000A2,0x280000A2,0xF2240000,0xFA440008,0x5000A4,0x9A180000,0x661C0000,0x501C0000,0x46240001,0x40140000,0xF4000004,0x8E080000,0xAC00A2,0x30000002,
+0xAC00A2,0x7800C8,0x6E640000,0x4E640001,0x44640001,0x2B000C8,0x56400001,0x44500001,0x16800C8,0x44140001,0x3A0000CA,0x2B000C8,0x56400001,0x44500001,0x16800C8,0x44140001,0x3A0000CA,0x16800C8,0x44140001,0x3A0000CA,0x3A0000CA,0x2B000C8,0x56400001,0x44500001,0x16800C8,0x44140001,0x3A0000CA,0x16800C8,0x44140001,0x3A0000CA,0x3A0000CA,0x16800C8,
+0x44140001,0x3A0000CA,0x3A0000CA,0x3A0000CA,0xF828000D,0x8000C8,0xFE6C0019,0x961C0000,0x6C140001,0x54140000,0x442C0001,0x44000002,0xF8040008,0x90080000,0x48300000,0x3A0000CA,0xFC00C8,0x2C00C8,0x2C00C8,0x2C00C8,0x2C00C8,0x2C00C8,0x2C00C8,0x2C00C8,0x2C00C8,0x2C00C8,0x2C00C8,0x48180000,0x48180000,0x48180000,0x48180000,0x48180000,
+0x48180000,0x28180001,0x28180001,0x28180001,0x1E180001,0x4000C8,0x4000C8,0x4000C8,0x4000C8,0x4000C8,0x4000C8,0x2E000009,0x2E000009,0x2E000009,0x1E040001,0x8000C8,0x8000C8,0x8000C8,0x1C00003A,0x140000CA,0xF61C000D,0x2C00C8,0x2C00C8,0x96180000,0x6C180000,0x56180000,0x56180000,0x3C180000,0xE0000004,0x86080001,0x30140001,0x2E000009,
+0x5C00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table70[] = {
+0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x740000,
+0x740000,0x740000,0x740000,0x12000001,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0xC280000,0xC280000,0xC280000,0x3C0000,0x540000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,
+0x2740000,0xF00000,0xF00000,0xF00000,0x26000001,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0xF00000,0xF00000,0xF00000,0x26000001,0xF00000,0xF00000,0xF00000,0x26000001,0x26000001,0x2540000,0x500000,0x500000,0x5C0000,0x640000,0x6C0000,0x6C0000,0x840000,0x5C0000,0x640000,0xA80000,0xF00000,
+0xA80000,0x740000,0x740000,0x740000,0x740000,0xAC0000,0xAC0000,0xAC0000,0x15C0000,0x15C0000,0x38000001,0xAC0000,0xAC0000,0xAC0000,0x15C0000,0x15C0000,0x38000001,0x15C0000,0x15C0000,0x38000001,0x38000001,0xAC0000,0xAC0000,0xAC0000,0x15C0000,0x15C0000,0x38000001,0x15C0000,0x15C0000,0x38000001,0x38000001,0x15C0000,
+0x15C0000,0x38000001,0x38000001,0x38000001,0x6840000,0x7C0000,0x740000,0x9C0000,0x2C00000,0xF40000,0x11C0000,0x1AC0000,0x900000,0xAC0000,0xF40000,0x38000001,0xF40000,0x9C0000,0xE80000,0x1D80000,0x4C000001,0xE80000,0x1D80000,0x4C000001,0x1D80000,0x4C000001,0x4C000001,0xE80000,0x1D80000,0x4C000001,0x1D80000,0x4C000001,
+0x4C000001,0x1D80000,0x4C000001,0x4C000001,0x4C000001,0xE80000,0x1D80000,0x4C000001,0x1D80000,0x4C000001,0x4C000001,0x1D80000,0x4C000001,0x4C000001,0x4C000001,0x1D80000,0x4C000001,0x4C000001,0x4C000001,0x4C000001,0xC40000,0xAA40000,0xAA40000,0x1040000,0x17C0000,0x21FC0000,0x4C000001,0x4C000001,0xD40000,0x1240000,0x43D80000,0x4C000001,
+0x14C0000,0x600738,0x9A5002D4,0x605002D4,0x4C5002D5,0x903C0190,0x683C00D5,0x4E44013A,0x563C0190,0x4A3C00D5,0x423C0192,0x8A2802D3,0x6A2800A2,0x523400FF,0x5A2800D1,0x4C280002,0x422C00D7,0x4C2802D4,0x482000FD,0x4020013B,0x3A2802D3,0x900734,0x720402D3,0x4C2802D4,0x6200019A,0x4E1000CF,0x42180192,0x52000319,0x4A0000C6,0x420000E7,0x3A0002D4,0x1240734,
+0x440003A9,0x3E0002E2,0x3600041C,0x30000734,0xFE34003D,0xF2540402,0xF65C04C1,0xA2280000,0x74280001,0x5A280002,0x4E2C0012,0x4A280011,0xFE100022,0x96180002,0x501C00A9,0x420000E7,0xD00734,0x7402D4,0x866400A4,0x5A6400A4,0x4C6000A5,0x7C5000C8,0x5E500001,0x4E540015,0x505000C8,0x4A4C0026,0x425000CA,0xB002D3,0x682C00A2,0x4C4800A3,0x5C2000C9,0x4C280002,
+0x443400CA,0x16402D3,0x4A0000AD,0x420000E3,0x3A0002D3,0xB002D3,0x682C00A2,0x4C4800A3,0x5C2000C9,0x4C280002,0x443400CA,0x16402D3,0x4A0000AD,0x420000E3,0x3A0002D3,0x16402D3,0x4A0000AD,0x420000E3,0x3A0002D3,0x3A0002D3,0xFC380018,0xFA64015E,0xFE6C014D,0xA2280000,0x74280001,0x5A280002,0x4E340002,0x4C1C0005,0xFE100019,0x96180001,0x521400A2,0x420000E3,
+0xF802D3,0x5002D4,0x5002D4,0x5002D4,0x5002D4,0x723C00C8,0x723C00C8,0x723C00C8,0x463C00C8,0x463C00C8,0x383C00C9,0x6A2800A2,0x6A2800A2,0x6A2800A2,0x4C280001,0x4C280001,0x3C2C0026,0x3E2800A2,0x3E2800A2,0x38240015,0x302800A2,0x7402D3,0x7402D3,0x7402D3,0x520800C9,0x520800C9,0x3A2000C9,0x460000AD,0x460000AD,0x38040002,0x300C00A2,0xE802D3,
+0xE802D3,0x32000119,0x2C000126,0x260002D3,0xFE2C0016,0xFA44014C,0x5002D4,0xA2280000,0x70280001,0x5A280001,0x542C0006,0x46280002,0xFA0C0005,0x96180001,0x4E2000A2,0x38040002,0xA402D3,0x6000A4,0x6000A4,0x6000A4,0x6000A4,0x5E500000,0x5E500000,0x5E500000,0x42500000,0x42500000,0x38500001,0x9000A2,0x9000A2,0x9000A2,0x48300001,0x48300001,
+0x38400001,0x12400A2,0x12400A2,0x38080001,0x300000A2,0x9000A2,0x9000A2,0x9000A2,0x48300001,0x48300001,0x38400001,0x12400A2,0x12400A2,0x38080001,0x300000A2,0x12400A2,0x12400A2,0x38080001,0x300000A2,0x300000A2,0xFA340000,0xF254000D,0x6000A4,0xA2280000,0x6E2C0000,0x582C0000,0x4E340001,0x48240000,0xFE0C0002,0x96180000,0xD000A2,0x38080001,
+0xD000A2,0x8800C8,0x76740000,0x56740001,0x4C740001,0xC800C8,0x5E500001,0x4C600001,0x19800C8,0x4C240001,0x420000CA,0xC800C8,0x5E500001,0x4C600001,0x19800C8,0x4C240001,0x420000CA,0x19800C8,0x4C240001,0x420000CA,0x420000CA,0xC800C8,0x5E500001,0x4C600001,0x19800C8,0x4C240001,0x420000CA,0x19800C8,0x4C240001,0x420000CA,0x420000CA,0x19800C8,
+0x4C240001,0x420000CA,0x420000CA,0x420000CA,0xFA3C0012,0x9000C8,0xF67C0020,0x9E2C0000,0x74240001,0x5C240000,0x4C3C0001,0x4C080001,0xFC14000A,0x98180000,0x50400000,0x420000CA,0x12000C8,0x3C00C8,0x3C00C8,0x3C00C8,0x3C00C8,0x3C00C8,0x3C00C8,0x3C00C8,0x3C00C8,0x3C00C8,0x3C00C8,0x50280000,0x50280000,0x50280000,0x50280000,0x50280000,
+0x50280000,0x30280001,0x30280001,0x30280001,0x26280001,0x5800C8,0x5800C8,0x5800C8,0x5800C8,0x5800C8,0x5800C8,0x38040001,0x38040001,0x38040001,0x26140001,0xB000C8,0xB000C8,0xB000C8,0x24000022,0x1C0000CA,0xFE2C000D,0x3C00C8,0x3C00C8,0x9E280000,0x74280000,0x5E280000,0x5E280000,0x44280000,0xF40C0001,0x8E180001,0x38240001,0x38040001,
+0x7C00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table71[] = {
+0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,0xA40000,
+0xA40000,0xA40000,0xA40000,0x1A000001,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x3C0000,0x3C0000,0x3C0000,0x2500000,0x740000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,
+0x28C0000,0x1200000,0x1200000,0x1200000,0x2E000001,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x1200000,0x1200000,0x1200000,0x2E000001,0x1200000,0x1200000,0x1200000,0x2E000001,0x2E000001,0xA640000,0x600000,0x600000,0x700000,0x780000,0x2800000,0x2800000,0xA00000,0x700000,0x780000,0xCC0000,0x1200000,
+0xCC0000,0x840000,0x840000,0x840000,0x840000,0xC40000,0xC40000,0xC40000,0x18C0000,0x18C0000,0x40000001,0xC40000,0xC40000,0xC40000,0x18C0000,0x18C0000,0x40000001,0x18C0000,0x18C0000,0x40000001,0x40000001,0xC40000,0xC40000,0xC40000,0x18C0000,0x18C0000,0x40000001,0x18C0000,0x18C0000,0x40000001,0x40000001,0x18C0000,
+0x18C0000,0x40000001,0x40000001,0x40000001,0x2980000,0x8C0000,0x840000,0xB40000,0xDC0000,0x1180000,0x1400000,0x1E80000,0xA40000,0xC40000,0x1180000,0x40000001,0x1180000,0xAC0000,0x1000000,0x5F80000,0x54000001,0x1000000,0x5F80000,0x54000001,0x5F80000,0x54000001,0x54000001,0x1000000,0x5F80000,0x54000001,0x5F80000,0x54000001,
+0x54000001,0x5F80000,0x54000001,0x54000001,0x54000001,0x1000000,0x5F80000,0x54000001,0x5F80000,0x54000001,0x54000001,0x5F80000,0x54000001,0x54000001,0x54000001,0x5F80000,0x54000001,0x54000001,0x54000001,0x54000001,0xD80000,0xB80000,0xB80000,0x1200000,0x1A40000,0x2BFC0000,0x54000001,0x54000001,0x2E80000,0x3400000,0x4BE80000,0x54000001,
+0x16C0000,0x700738,0xA26002D4,0x686002D4,0x546002D5,0x984C0190,0x704C00D5,0x5654013A,0x5E4C0190,0x524C00D5,0x4A4C0192,0x923802D3,0x723800A2,0x5A4400FF,0x623800D1,0x54380002,0x4A3C00D7,0x543802D4,0x503000FD,0x4830013B,0x423802D3,0xA80734,0x7A1402D3,0x543802D4,0x6C080192,0x562000CF,0x4A280192,0x620002E3,0x540000A3,0x4A0000D7,0x421002D4,0x1580734,
+0x4A000361,0x44000272,0x3E0003BF,0x38000734,0xFE440056,0xFA640402,0xFE6C04C1,0xAA380000,0x7C380001,0x62380002,0x563C0012,0x52380011,0xFE24003B,0x9E280002,0x582C00A9,0x4A0000D7,0xF00734,0x8402D4,0x8E7400A4,0x627400A4,0x547000A5,0x846000C8,0x66600001,0x56640015,0x586000C8,0x525C0026,0x4A6000CA,0x2C402D3,0x703C00A2,0x545800A3,0x643000C9,0x54380002,
+0x4C4400CA,0x19402D3,0x540000A3,0x4A0000CE,0x420002D3,0x2C402D3,0x703C00A2,0x545800A3,0x643000C9,0x54380002,0x4C4400CA,0x19402D3,0x540000A3,0x4A0000CE,0x420002D3,0x19402D3,0x540000A3,0x4A0000CE,0x420002D3,0x420002D3,0xFC4C001D,0xF2740174,0xF67C0164,0xAA380000,0x7C380001,0x62380002,0x56440002,0x542C0005,0xFE240022,0x9E280001,0x5A2400A2,0x4A0000CE,
+0x11C02D3,0x6002D4,0x6002D4,0x6002D4,0x6002D4,0x7A4C00C8,0x7A4C00C8,0x7A4C00C8,0x4E4C00C8,0x4E4C00C8,0x404C00C9,0x723800A2,0x723800A2,0x723800A2,0x54380001,0x54380001,0x443C0026,0x463800A2,0x463800A2,0x40340015,0x383800A2,0x8C02D3,0x8C02D3,0x8C02D3,0x5A1800C9,0x5A1800C9,0x423000C9,0x540000A2,0x540000A2,0x40140002,0x381C00A2,0x11802D3,
+0x11802D3,0x3E0000F1,0x360000FB,0x2E0002D3,0xF840001D,0xF2540161,0x6002D4,0xAA380000,0x78380001,0x62380001,0x5C3C0006,0x4E380002,0xFC1C000A,0x9E280001,0x563000A2,0x40140002,0xC802D3,0x7000A4,0x7000A4,0x7000A4,0x7000A4,0x66600000,0x66600000,0x66600000,0x4A600000,0x4A600000,0x40600001,0xA800A2,0xA800A2,0xA800A2,0x50400001,0x50400001,
+0x40500001,0x15800A2,0x15800A2,0x40180001,0x380000A2,0xA800A2,0xA800A2,0xA800A2,0x50400001,0x50400001,0x40500001,0x15800A2,0x15800A2,0x40180001,0x380000A2,0x15800A2,0x15800A2,0x40180001,0x380000A2,0x380000A2,0xF6480001,0xFA64000D,0x7000A4,0xAA380000,0x763C0000,0x603C0000,0x56440001,0x50340000,0xF6240005,0x9E280000,0xF000A2,0x40180001,
+0xF000A2,0x9800C8,0x7E840000,0x5E840001,0x54840001,0xE000C8,0x66600001,0x54700001,0x1CC00C8,0x54340001,0x4A0000CA,0xE000C8,0x66600001,0x54700001,0x1CC00C8,0x54340001,0x4A0000CA,0x1CC00C8,0x54340001,0x4A0000CA,0x4A0000CA,0xE000C8,0x66600001,0x54700001,0x1CC00C8,0x54340001,0x4A0000CA,0x1CC00C8,0x54340001,0x4A0000CA,0x4A0000CA,0x1CC00C8,
+0x54340001,0x4A0000CA,0x4A0000CA,0x4A0000CA,0xFC4C0014,0x8A000C8,0xFE8C0020,0xA63C0000,0x7C340001,0x64340000,0x544C0001,0x54180001,0xFE2C000D,0xA0280000,0x58500000,0x4A0000CA,0x14000C8,0x4C00C8,0x4C00C8,0x4C00C8,0x4C00C8,0x4C00C8,0x4C00C8,0x4C00C8,0x4C00C8,0x4C00C8,0x4C00C8,0x58380000,0x58380000,0x58380000,0x58380000,0x58380000,
+0x58380000,0x38380001,0x38380001,0x38380001,0x2E380001,0x7000C8,0x7000C8,0x7000C8,0x7000C8,0x7000C8,0x7000C8,0x40140001,0x40140001,0x40140001,0x2E240001,0xE400C8,0xE400C8,0xE400C8,0x2C00000D,0x240000CA,0xF63C0014,0x4C00C8,0x4C00C8,0xA6380000,0x7C380000,0x66380000,0x66380000,0x4C380000,0xFC1C0001,0x96280001,0x40340001,0x40140001,
+0xA000C8,};
+static const uint32_t g_etc1_to_bc7_m6_table72[] = {
+0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x6C0000,0x6C0000,0x6C0000,0x6C0000,0x6C0000,0x6C0000,0x6C0000,0x6C0000,0x6C0000,0x6C0000,0xDC0000,
+0xDC0000,0xDC0000,0xDC0000,0x24000000,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0x480001,0xE4C0000,0xE4C0000,0xE4C0000,0x6C0000,0x9C0000,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,
+0xA80000,0x1580000,0x1580000,0x1580000,0x38000000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0x1580000,0x1580000,0x1580000,0x38000000,0x1580000,0x1580000,0x1580000,0x38000000,0x38000000,0x4780000,0x700001,0x700001,0x840000,0x48C0000,0x2980000,0x2980000,0xC00000,0x840000,0x48C0000,0xF00000,0x1580000,
+0xF00000,0x940001,0x940001,0x940001,0x940001,0x2DC0000,0x2DC0000,0x2DC0000,0x1C40000,0x1C40000,0x4A000000,0x2DC0000,0x2DC0000,0x2DC0000,0x1C40000,0x1C40000,0x4A000000,0x1C40000,0x1C40000,0x4A000000,0x4A000000,0x2DC0000,0x2DC0000,0x2DC0000,0x1C40000,0x1C40000,0x4A000000,0x1C40000,0x1C40000,0x4A000000,0x4A000000,0x1C40000,
+0x1C40000,0x4A000000,0x4A000000,0x4A000000,0x4AC0000,0xA00000,0x940001,0xCC0000,0xFC0000,0x13C0000,0x16C0000,0xBF80000,0xBC0000,0x2DC0000,0x13C0000,0x4A000000,0x13C0000,0xBC0001,0x3180000,0x11FC0000,0x5E000000,0x3180000,0x11FC0000,0x5E000000,0x11FC0000,0x5E000000,0x5E000000,0x3180000,0x11FC0000,0x5E000000,0x11FC0000,0x5E000000,
+0x5E000000,0x11FC0000,0x5E000000,0x5E000000,0x5E000000,0x3180000,0x11FC0000,0x5E000000,0x11FC0000,0x5E000000,0x5E000000,0x11FC0000,0x5E000000,0x5E000000,0x5E000000,0x11FC0000,0x5E000000,0x5E000000,0x5E000000,0x5E000000,0x2EC0000,0xCC80000,0xCC80000,0x1400000,0x1D00000,0x37F40000,0x5E000000,0x5E000000,0x3000000,0x1640000,0x55DC0000,0x5E000000,
+0x1940000,0x840734,0xAE7002D3,0x707002D4,0x5E7002D3,0xA0600192,0x786000D7,0x6264013B,0x66600192,0x5C5C00D7,0x545C0192,0x984C02D4,0x7A4C00A3,0x625400FD,0x6A4800CF,0x5E4C0002,0x545000D5,0x5E4802D4,0x584000FF,0x5048013A,0x4A4802D5,0xC40734,0x822802D3,0x5E4C02D4,0x76180192,0x5E3000D1,0x54380190,0x700002D3,0x5E1000A2,0x541400D5,0x4A2402D4,0x18C0734,
+0x5600031B,0x50000212,0x48000378,0x40000738,0xFE580072,0xF4780434,0xF67C04EC,0xB24C0002,0x84480003,0x6C4C0002,0x5E500011,0x5C440012,0xFE34004E,0xAA380000,0x604000A9,0x541400D5,0x1180734,0x9802D3,0x988400A2,0x6C8400A2,0x5E8400A2,0x8A7400C9,0x6E740002,0x60740015,0x627000C9,0x5C6C0026,0x547000C9,0xE002D3,0x7A4C00A2,0x5E6800A2,0x6E4000C9,0x5E4C0001,
+0x545800C8,0x1CC02D3,0x5E0C00A2,0x540000C8,0x4A0002D4,0xE002D3,0x7A4C00A2,0x5E6800A2,0x6E4000C9,0x5E4C0001,0x545800C8,0x1CC02D3,0x5E0C00A2,0x540000C8,0x4A0002D4,0x1CC02D3,0x5E0C00A2,0x540000C8,0x4A0002D4,0x4A0002D4,0xFC60002D,0xFC880173,0xFE8C016B,0xB24C0001,0x84480002,0x6C4C0001,0x5E580002,0x5C3C0006,0xFE3C0033,0xAA380000,0x623800A2,0x540000C8,
+0x14002D3,0x7002D3,0x7002D3,0x7002D3,0x7002D3,0x806000CA,0x806000CA,0x806000CA,0x585C00CA,0x585C00CA,0x4A5C00CA,0x7A4C00A3,0x7A4C00A3,0x7A4C00A3,0x5C4C0002,0x5C4C0002,0x4C500026,0x4E4C00A3,0x4E4C00A3,0x48480015,0x404800A5,0x2A402D3,0x2A402D3,0x2A402D3,0x622C00C9,0x622C00C9,0x4A4400C8,0x5C1400A2,0x5C1400A2,0x4A240001,0x403000A4,0x15002D3,
+0x15002D3,0x480000D4,0x3E0000CD,0x380002D4,0xFC540026,0xFC68015E,0x7002D3,0xB6480001,0x804C0002,0x6A4C0002,0x644C0005,0x58480002,0xFE34000E,0xAA380000,0x5E4400A3,0x4A240001,0xEC02D3,0x8400A2,0x8400A2,0x8400A2,0x8400A2,0x6C740001,0x6C740001,0x6C740001,0x52740001,0x52740001,0x4A700001,0xC400A2,0xC400A2,0xC400A2,0x58540001,0x58540001,
+0x4A600000,0x18C00A2,0x18C00A2,0x4A280000,0x400000A4,0xC400A2,0xC400A2,0xC400A2,0x58540001,0x58540001,0x4A600000,0x18C00A2,0x18C00A2,0x4A280000,0x400000A4,0x18C00A2,0x18C00A2,0x4A280000,0x400000A4,0x400000A4,0xFE580001,0xF4780012,0x8400A2,0xB6480000,0x7C500000,0x68500000,0x60540000,0x58480001,0xFE340005,0xAA380000,0x11800A2,0x4A280000,
+0x11800A2,0xA800CA,0x84980001,0x68940001,0x5E940001,0xFC00C8,0x6E740001,0x5E800001,0x3F800C8,0x5E440000,0x540000C8,0xFC00C8,0x6E740001,0x5E800001,0x3F800C8,0x5E440000,0x540000C8,0x3F800C8,0x5E440000,0x540000C8,0x540000C8,0xFC00C8,0x6E740001,0x5E800001,0x3F800C8,0x5E440000,0x540000C8,0x3F800C8,0x5E440000,0x540000C8,0x540000C8,0x3F800C8,
+0x5E440000,0x540000C8,0x540000C8,0x540000C8,0xF6680019,0x2B400C8,0xF8A00029,0xB24C0000,0x84480001,0x6E440000,0x5E5C0000,0x5E240000,0xF4480012,0xAA380000,0x60640001,0x540000C8,0x16800C8,0x5C00CA,0x5C00CA,0x5C00CA,0x5C00CA,0x5C00CA,0x5C00CA,0x5C00CA,0x5C00CA,0x5C00CA,0x5C00CA,0x5E4C0001,0x5E4C0001,0x5E4C0001,0x5E4C0001,0x5E4C0001,
+0x5E4C0001,0x42480001,0x42480001,0x42480001,0x38480001,0x8C00C8,0x8C00C8,0x8C00C8,0x8C00C8,0x8C00C8,0x8C00C8,0x48280001,0x48280001,0x48280001,0x38340001,0x11800C8,0x11800C8,0x11800C8,0x38000001,0x2E0000C8,0xF0500019,0x5C00CA,0x5C00CA,0xAA4C0001,0x824C0001,0x6C4C0001,0x6C4C0001,0x544C0001,0xF8300002,0xA8380000,0x4C440000,0x48280001,
+0xC800C8,};
+static const uint32_t g_etc1_to_bc7_m6_table73[] = {
+0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x10C0000,
+0x10C0000,0x10C0000,0x10C0000,0x2C000000,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x580001,0x600000,0x600000,0x600000,0x840000,0xBC0000,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,
+0xC00000,0x1880000,0x1880000,0x1880000,0x40000000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0x1880000,0x1880000,0x1880000,0x40000000,0x1880000,0x1880000,0x1880000,0x40000000,0x40000000,0xC880000,0x800001,0x800001,0x980000,0x4A00000,0xB00000,0xB00000,0xD80000,0x980000,0x4A00000,0x1140000,0x1880000,
+0x1140000,0xA40001,0xA40001,0xA40001,0xA40001,0x2F40000,0x2F40000,0x2F40000,0x1F40000,0x1F40000,0x52000000,0x2F40000,0x2F40000,0x2F40000,0x1F40000,0x1F40000,0x52000000,0x1F40000,0x1F40000,0x52000000,0x52000000,0x2F40000,0x2F40000,0x2F40000,0x1F40000,0x1F40000,0x52000000,0x1F40000,0x1F40000,0x52000000,0x52000000,0x1F40000,
+0x1F40000,0x52000000,0x52000000,0x52000000,0xC00000,0xB00000,0xA40001,0xE00000,0x3140000,0x1600000,0x1940000,0x15FC0000,0xD00000,0x2F40000,0x1600000,0x52000000,0x1600000,0xCC0001,0x3300000,0x1DFC0000,0x66000000,0x3300000,0x1DFC0000,0x66000000,0x1DFC0000,0x66000000,0x66000000,0x3300000,0x1DFC0000,0x66000000,0x1DFC0000,0x66000000,
+0x66000000,0x1DFC0000,0x66000000,0x66000000,0x66000000,0x3300000,0x1DFC0000,0x66000000,0x1DFC0000,0x66000000,0x66000000,0x1DFC0000,0x66000000,0x66000000,0x66000000,0x1DFC0000,0x66000000,0x66000000,0x66000000,0x66000000,0x3000000,0xDC0000,0xDC0000,0x1580000,0x1F80000,0x41F40000,0x66000000,0x66000000,0x1180000,0x3800000,0x5DEC0000,0x66000000,
+0x1B40000,0x940734,0xB68002D3,0x788002D4,0x668002D3,0xA8700192,0x807000D7,0x6A74013B,0x6E700192,0x646C00D7,0x5C6C0192,0xA05C02D4,0x825C00A3,0x6A6400FD,0x725800CF,0x665C0002,0x5C6000D5,0x665802D4,0x605000FF,0x5858013A,0x525802D5,0xDC0734,0x8A3802D3,0x665C02D4,0x7E280192,0x664000D1,0x5C480190,0x781002D3,0x662000A2,0x5C2400D5,0x523402D4,0x1BC0734,
+0x600002F8,0x5A0001E0,0x50000339,0x48000738,0xFE6C0096,0xFC880434,0xFE8C04EC,0xBA5C0002,0x8C580003,0x745C0002,0x66600011,0x64540012,0xFC4C006E,0xB2480000,0x685000A9,0x5C2400D5,0x1380734,0xA802D3,0xA09400A2,0x749400A2,0x669400A2,0x928400C9,0x76840002,0x68840015,0x6A8000C9,0x647C0026,0x5C8000C9,0xF802D3,0x825C00A2,0x667800A2,0x765000C9,0x665C0001,
+0x5C6800C8,0x1FC02D3,0x661C00A2,0x5C1000C8,0x520002D4,0xF802D3,0x825C00A2,0x667800A2,0x765000C9,0x665C0001,0x5C6800C8,0x1FC02D3,0x661C00A2,0x5C1000C8,0x520002D4,0x1FC02D3,0x661C00A2,0x5C1000C8,0x520002D4,0x520002D4,0xFC740036,0xF4980189,0xF8A0017A,0xBA5C0001,0x8C580002,0x745C0001,0x66680002,0x644C0006,0xFC50003D,0xB2480000,0x6A4800A2,0x5C1000C8,
+0x16402D3,0x8002D3,0x8002D3,0x8002D3,0x8002D3,0x887000CA,0x887000CA,0x887000CA,0x606C00CA,0x606C00CA,0x526C00CA,0x825C00A3,0x825C00A3,0x825C00A3,0x645C0002,0x645C0002,0x54600026,0x565C00A3,0x565C00A3,0x50580015,0x485800A5,0x2BC02D3,0x2BC02D3,0x2BC02D3,0x6A3C00C9,0x6A3C00C9,0x525400C8,0x642400A2,0x642400A2,0x52340001,0x484000A4,0x18002D3,
+0x18002D3,0x520000CA,0x480000B4,0x400002D4,0xFC64002D,0xF4780173,0x8002D3,0xBE580001,0x885C0002,0x725C0002,0x6C5C0005,0x60580002,0xFE440019,0xB2480000,0x665400A3,0x52340001,0x11002D3,0x9400A2,0x9400A2,0x9400A2,0x9400A2,0x74840001,0x74840001,0x74840001,0x5A840001,0x5A840001,0x52800001,0xDC00A2,0xDC00A2,0xDC00A2,0x60640001,0x60640001,
+0x52700000,0x1BC00A2,0x1BC00A2,0x52380000,0x480000A4,0xDC00A2,0xDC00A2,0xDC00A2,0x60640001,0x60640001,0x52700000,0x1BC00A2,0x1BC00A2,0x52380000,0x480000A4,0x1BC00A2,0x1BC00A2,0x52380000,0x480000A4,0x480000A4,0xFA6C0002,0xFC880012,0x9400A2,0xBE580000,0x84600000,0x70600000,0x68640000,0x60580001,0xFA48000A,0xB2480000,0x13800A2,0x52380000,
+0x13800A2,0xB800CA,0x8CA80001,0x70A40001,0x66A40001,0x11400C8,0x76840001,0x66900001,0xFF800C8,0x66540000,0x5C0000C8,0x11400C8,0x76840001,0x66900001,0xFF800C8,0x66540000,0x5C0000C8,0xFF800C8,0x66540000,0x5C0000C8,0x5C0000C8,0x11400C8,0x76840001,0x66900001,0xFF800C8,0x66540000,0x5C0000C8,0xFF800C8,0x66540000,0x5C0000C8,0x5C0000C8,0xFF800C8,
+0x66540000,0x5C0000C8,0x5C0000C8,0x5C0000C8,0xFE780019,0xAC400C8,0xFEAC002D,0xBA5C0000,0x8C580001,0x76540000,0x666C0000,0x66340000,0xFC580012,0xB2480000,0x68740001,0x5C0000C8,0x18C00C8,0x6C00CA,0x6C00CA,0x6C00CA,0x6C00CA,0x6C00CA,0x6C00CA,0x6C00CA,0x6C00CA,0x6C00CA,0x6C00CA,0x665C0001,0x665C0001,0x665C0001,0x665C0001,0x665C0001,
+0x665C0001,0x4A580001,0x4A580001,0x4A580001,0x40580001,0xA400C8,0xA400C8,0xA400C8,0xA400C8,0xA400C8,0xA400C8,0x50380001,0x50380001,0x50380001,0x40440001,0x14C00C8,0x14C00C8,0x14C00C8,0x40080000,0x360000C8,0xF8600019,0x6C00CA,0x6C00CA,0xB25C0001,0x8A5C0001,0x745C0001,0x745C0001,0x5C5C0001,0xF4440005,0xB0480000,0x54540000,0x50380001,
+0xE800C8,};
+static const uint32_t g_etc1_to_bc7_m6_table74[] = {
+0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x13C0000,
+0x13C0000,0x13C0000,0x13C0000,0x34000000,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x700000,0x700000,0x700000,0x9C0000,0xE00000,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,
+0xD80000,0x1B80000,0x1B80000,0x1B80000,0x48000000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0x1B80000,0x1B80000,0x1B80000,0x48000000,0x1B80000,0x1B80000,0x1B80000,0x48000000,0x48000000,0x9C0000,0x900001,0x900001,0x2A80000,0x4B40000,0x2C40000,0x2C40000,0xF40000,0x2A80000,0x4B40000,0x1340000,0x1B80000,
+0x1340000,0xB40001,0xB40001,0xB40001,0xB40001,0x30C0000,0x30C0000,0x30C0000,0xBFC0000,0xBFC0000,0x5A000000,0x30C0000,0x30C0000,0x30C0000,0xBFC0000,0xBFC0000,0x5A000000,0xBFC0000,0xBFC0000,0x5A000000,0x5A000000,0x30C0000,0x30C0000,0x30C0000,0xBFC0000,0xBFC0000,0x5A000000,0xBFC0000,0xBFC0000,0x5A000000,0x5A000000,0xBFC0000,
+0xBFC0000,0x5A000000,0x5A000000,0x5A000000,0xD40000,0x8C00000,0xB40001,0xF80000,0x1300000,0x1800000,0x1BC0000,0x21F40000,0xE40000,0x30C0000,0x1800000,0x5A000000,0x1800000,0xDC0001,0x1480000,0x29FC0000,0x6E000000,0x1480000,0x29FC0000,0x6E000000,0x29FC0000,0x6E000000,0x6E000000,0x1480000,0x29FC0000,0x6E000000,0x29FC0000,0x6E000000,
+0x6E000000,0x29FC0000,0x6E000000,0x6E000000,0x6E000000,0x1480000,0x29FC0000,0x6E000000,0x29FC0000,0x6E000000,0x6E000000,0x29FC0000,0x6E000000,0x6E000000,0x6E000000,0x29FC0000,0x6E000000,0x6E000000,0x6E000000,0x6E000000,0x3140000,0xEC0000,0xEC0000,0x1740000,0xDFC0000,0x4BF40000,0x6E000000,0x6E000000,0x32C0000,0x1A00000,0x65FC0000,0x6E000000,
+0x1D80000,0xA40734,0xBE9002D3,0x809002D4,0x6E9002D3,0xB0800192,0x888000D7,0x7284013B,0x76800192,0x6C7C00D7,0x647C0192,0xA86C02D4,0x8A6C00A3,0x727400FD,0x7A6800CF,0x6E6C0002,0x647000D5,0x6E6802D4,0x686000FF,0x6068013A,0x5A6802D5,0xF40734,0x924802D3,0x6E6C02D4,0x86380192,0x6E5000D1,0x64580190,0x802002D3,0x6E3000A2,0x643400D5,0x5A4402D4,0x1F00734,
+0x6C0002D8,0x600001B8,0x5A000314,0x50000738,0xFC7C00BA,0xF498046A,0xF8A00513,0xC26C0002,0x94680003,0x7C6C0002,0x6E700011,0x6C640012,0xFE5C0082,0xBA580000,0x706000A9,0x643400D5,0x15C0734,0xB802D3,0xA8A400A2,0x7CA400A2,0x6EA400A2,0x9A9400C9,0x7E940002,0x70940015,0x729000C9,0x6C8C0026,0x649000C9,0x11002D3,0x8A6C00A2,0x6E8800A2,0x7E6000C9,0x6E6C0001,
+0x647800C8,0xDFC02D3,0x6E2C00A2,0x642000C8,0x5A0002D4,0x11002D3,0x8A6C00A2,0x6E8800A2,0x7E6000C9,0x6E6C0001,0x647800C8,0xDFC02D3,0x6E2C00A2,0x642000C8,0x5A0002D4,0xDFC02D3,0x6E2C00A2,0x642000C8,0x5A0002D4,0x5A0002D4,0xFE800049,0xFCA80189,0xFEAC0186,0xC26C0001,0x94680002,0x7C6C0001,0x6E780002,0x6C5C0006,0xFE600051,0xBA580000,0x725800A2,0x642000C8,
+0x18802D3,0x9002D3,0x9002D3,0x9002D3,0x9002D3,0x908000CA,0x908000CA,0x908000CA,0x687C00CA,0x687C00CA,0x5A7C00CA,0x8A6C00A3,0x8A6C00A3,0x8A6C00A3,0x6C6C0002,0x6C6C0002,0x5C700026,0x5E6C00A3,0x5E6C00A3,0x58680015,0x506800A5,0xD402D3,0xD402D3,0xD402D3,0x724C00C9,0x724C00C9,0x5A6400C8,0x6C3400A2,0x6C3400A2,0x5A440001,0x505000A4,0x1B002D3,
+0x1B002D3,0x5A0C00C8,0x500000A5,0x480002D4,0xFE74003B,0xFC880173,0x9002D3,0xC6680001,0x906C0002,0x7A6C0002,0x746C0005,0x68680002,0xFE580021,0xBA580000,0x6E6400A3,0x5A440001,0x13002D3,0xA400A2,0xA400A2,0xA400A2,0xA400A2,0x7C940001,0x7C940001,0x7C940001,0x62940001,0x62940001,0x5A900001,0xF400A2,0xF400A2,0xF400A2,0x68740001,0x68740001,
+0x5A800000,0x1F000A2,0x1F000A2,0x5A480000,0x500000A4,0xF400A2,0xF400A2,0xF400A2,0x68740001,0x68740001,0x5A800000,0x1F000A2,0x1F000A2,0x5A480000,0x500000A4,0x1F000A2,0x1F000A2,0x5A480000,0x500000A4,0x500000A4,0xF6800005,0xF4980019,0xA400A2,0xC6680000,0x8C700000,0x78700000,0x70740000,0x68680001,0xF260000D,0xBA580000,0x15C00A2,0x5A480000,
+0x15C00A2,0xC800CA,0x94B80001,0x78B40001,0x6EB40001,0x12C00C8,0x7E940001,0x6EA00001,0x1BF800C8,0x6E640000,0x640000C8,0x12C00C8,0x7E940001,0x6EA00001,0x1BF800C8,0x6E640000,0x640000C8,0x1BF800C8,0x6E640000,0x640000C8,0x640000C8,0x12C00C8,0x7E940001,0x6EA00001,0x1BF800C8,0x6E640000,0x640000C8,0x1BF800C8,0x6E640000,0x640000C8,0x640000C8,0x1BF800C8,
+0x6E640000,0x640000C8,0x640000C8,0x640000C8,0xFA8C0020,0xD800C8,0xF8C00032,0xC26C0000,0x94680001,0x7E640000,0x6E7C0000,0x6E440000,0xFC6C0019,0xBA580000,0x70840001,0x640000C8,0x1AC00C8,0x7C00CA,0x7C00CA,0x7C00CA,0x7C00CA,0x7C00CA,0x7C00CA,0x7C00CA,0x7C00CA,0x7C00CA,0x7C00CA,0x6E6C0001,0x6E6C0001,0x6E6C0001,0x6E6C0001,0x6E6C0001,
+0x6E6C0001,0x52680001,0x52680001,0x52680001,0x48680001,0xBC00C8,0xBC00C8,0xBC00C8,0xBC00C8,0xBC00C8,0xBC00C8,0x58480001,0x58480001,0x58480001,0x48540001,0x17C00C8,0x17C00C8,0x17C00C8,0x48180000,0x3E0000C8,0xF0700022,0x7C00CA,0x7C00CA,0xBA6C0001,0x926C0001,0x7C6C0001,0x7C6C0001,0x646C0001,0xFC540005,0xB8580000,0x5C640000,0x58480001,
+0x10C00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table75[] = {
+0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0x1700000,
+0x1700000,0x1700000,0x1700000,0x3C000000,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x8800000,0x8800000,0x8800000,0xB40000,0x1000000,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,
+0xF00000,0x1E80000,0x1E80000,0x1E80000,0x50000000,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,0x1E80000,0x1E80000,0x1E80000,0x50000000,0x1E80000,0x1E80000,0x1E80000,0x50000000,0x50000000,0xAC0000,0xA00001,0xA00001,0xBC0000,0xCC0000,0xDC0000,0xDC0000,0x1100000,0xBC0000,0xCC0000,0x1580000,0x1E80000,
+0x1580000,0xC40001,0xC40001,0xC40001,0xC40001,0x3240000,0x3240000,0x3240000,0x17FC0000,0x17FC0000,0x62000000,0x3240000,0x3240000,0x3240000,0x17FC0000,0x17FC0000,0x62000000,0x17FC0000,0x17FC0000,0x62000000,0x62000000,0x3240000,0x3240000,0x3240000,0x17FC0000,0x17FC0000,0x62000000,0x17FC0000,0x17FC0000,0x62000000,0x62000000,0x17FC0000,
+0x17FC0000,0x62000000,0x62000000,0x62000000,0x4E40000,0xD40000,0xC40001,0x10C0000,0x14C0000,0x1A40000,0x1E40000,0x2BF80000,0xF80000,0x3240000,0x1A40000,0x62000000,0x1A40000,0xEC0001,0x1600000,0x35FC0000,0x76000000,0x1600000,0x35FC0000,0x76000000,0x35FC0000,0x76000000,0x76000000,0x1600000,0x35FC0000,0x76000000,0x35FC0000,0x76000000,
+0x76000000,0x35FC0000,0x76000000,0x76000000,0x76000000,0x1600000,0x35FC0000,0x76000000,0x35FC0000,0x76000000,0x76000000,0x35FC0000,0x76000000,0x76000000,0x76000000,0x35FC0000,0x76000000,0x76000000,0x76000000,0x76000000,0x3280000,0x6FC0000,0x6FC0000,0x1900000,0x1BFC0000,0x55F40000,0x76000000,0x76000000,0x1440000,0x1C00000,0x6FD00000,0x76000000,
+0x1F80000,0xB40734,0xC6A002D3,0x88A002D4,0x76A002D3,0xB8900192,0x909000D7,0x7A94013B,0x7E900192,0x748C00D7,0x6C8C0192,0xB07C02D4,0x927C00A3,0x7A8400FD,0x827800CF,0x767C0002,0x6C8000D5,0x767802D4,0x707000FF,0x6878013A,0x627802D5,0x10C0734,0x9A5802D3,0x767C02D4,0x8E480192,0x766000D1,0x6C680190,0x883002D3,0x764000A2,0x6C4400D5,0x625402D4,0xBF80734,
+0x760002D3,0x6C000198,0x600002F8,0x58000738,0xFE8C00D4,0xFCA8046A,0xFEAC0517,0xCA7C0002,0x9C780003,0x847C0002,0x76800011,0x74740012,0xFE7000A7,0xC2680000,0x787000A9,0x6C4400D5,0x17C0734,0xC802D3,0xB0B400A2,0x84B400A2,0x76B400A2,0xA2A400C9,0x86A40002,0x78A40015,0x7AA000C9,0x749C0026,0x6CA000C9,0x12802D3,0x927C00A2,0x769800A2,0x867000C9,0x767C0001,
+0x6C8800C8,0x19FC02D3,0x763C00A2,0x6C3000C8,0x620002D4,0x12802D3,0x927C00A2,0x769800A2,0x867000C9,0x767C0001,0x6C8800C8,0x19FC02D3,0x763C00A2,0x6C3000C8,0x620002D4,0x19FC02D3,0x763C00A2,0x6C3000C8,0x620002D4,0x620002D4,0xFE940050,0xF4B801A3,0xF8C00193,0xCA7C0001,0x9C780002,0x847C0001,0x76880002,0x746C0006,0xFE780056,0xC2680000,0x7A6800A2,0x6C3000C8,
+0x1A802D3,0xA002D3,0xA002D3,0xA002D3,0xA002D3,0x989000CA,0x989000CA,0x989000CA,0x708C00CA,0x708C00CA,0x628C00CA,0x927C00A3,0x927C00A3,0x927C00A3,0x747C0002,0x747C0002,0x64800026,0x667C00A3,0x667C00A3,0x60780015,0x587800A5,0xEC02D3,0xEC02D3,0xEC02D3,0x7A5C00C9,0x7A5C00C9,0x627400C8,0x744400A2,0x744400A2,0x62540001,0x586000A4,0x1E402D3,
+0x1E402D3,0x621C00C8,0x580800A4,0x500002D4,0xFE840046,0xF498018A,0xA002D3,0xCE780001,0x987C0002,0x827C0002,0x7C7C0005,0x70780002,0xF86C0032,0xC2680000,0x767400A3,0x62540001,0x15402D3,0xB400A2,0xB400A2,0xB400A2,0xB400A2,0x84A40001,0x84A40001,0x84A40001,0x6AA40001,0x6AA40001,0x62A00001,0x10C00A2,0x10C00A2,0x10C00A2,0x70840001,0x70840001,
+0x62900000,0xBF800A2,0xBF800A2,0x62580000,0x580000A4,0x10C00A2,0x10C00A2,0x10C00A2,0x70840001,0x70840001,0x62900000,0xBF800A2,0xBF800A2,0x62580000,0x580000A4,0xBF800A2,0xBF800A2,0x62580000,0x580000A4,0x580000A4,0xFE900005,0xFCA80019,0xB400A2,0xCE780000,0x94800000,0x80800000,0x78840000,0x70780001,0xFA70000D,0xC2680000,0x17C00A2,0x62580000,
+0x17C00A2,0xD800CA,0x9CC80001,0x80C40001,0x76C40001,0x14400C8,0x86A40001,0x76B00001,0x27F800C8,0x76740000,0x6C0000C8,0x14400C8,0x86A40001,0x76B00001,0x27F800C8,0x76740000,0x6C0000C8,0x27F800C8,0x76740000,0x6C0000C8,0x6C0000C8,0x14400C8,0x86A40001,0x76B00001,0x27F800C8,0x76740000,0x6C0000C8,0x27F800C8,0x76740000,0x6C0000C8,0x6C0000C8,0x27F800C8,
+0x76740000,0x6C0000C8,0x6C0000C8,0x6C0000C8,0xF4A00029,0xE800C8,0xFECC003A,0xCA7C0000,0x9C780001,0x86740000,0x768C0000,0x76540000,0xF8840020,0xC2680000,0x78940001,0x6C0000C8,0x1D000C8,0x8C00CA,0x8C00CA,0x8C00CA,0x8C00CA,0x8C00CA,0x8C00CA,0x8C00CA,0x8C00CA,0x8C00CA,0x8C00CA,0x767C0001,0x767C0001,0x767C0001,0x767C0001,0x767C0001,
+0x767C0001,0x5A780001,0x5A780001,0x5A780001,0x50780001,0x2D000C8,0x2D000C8,0x2D000C8,0x2D000C8,0x2D000C8,0x2D000C8,0x60580001,0x60580001,0x60580001,0x50640001,0x1AC00C8,0x1AC00C8,0x1AC00C8,0x50280000,0x460000C8,0xF8800022,0x8C00CA,0x8C00CA,0xC27C0001,0x9A7C0001,0x847C0001,0x847C0001,0x6C7C0001,0xFC640008,0xC0680000,0x64740000,0x60580001,
+0x12C00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table76[] = {
+0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0xD00000,0xD00000,0xD00000,0xD00000,0xD00000,0xD00000,0xD00000,0xD00000,0xD00000,0xD00000,0x1A40000,
+0x1A40000,0x1A40000,0x1A40000,0x44000001,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x2940000,0x2940000,0x2940000,0xD00000,0x1280000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,
+0x10C0000,0xBF80000,0xBF80000,0xBF80000,0x58000001,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0xBF80000,0xBF80000,0xBF80000,0x58000001,0xBF80000,0xBF80000,0xBF80000,0x58000001,0x58000001,0xC00000,0xB40000,0xB40000,0xD00000,0x2E00000,0xF40000,0xF40000,0x32C0000,0xD00000,0x2E00000,0x17C0000,0xBF80000,
+0x17C0000,0xD80000,0xD80000,0xD80000,0xD80000,0x1400000,0x1400000,0x1400000,0x25F80000,0x25F80000,0x6A000001,0x1400000,0x1400000,0x1400000,0x25F80000,0x25F80000,0x6A000001,0x25F80000,0x25F80000,0x6A000001,0x6A000001,0x1400000,0x1400000,0x1400000,0x25F80000,0x25F80000,0x6A000001,0x25F80000,0x25F80000,0x6A000001,0x6A000001,0x25F80000,
+0x25F80000,0x6A000001,0x6A000001,0x6A000001,0xFC0000,0xAE40000,0xD80000,0x3240000,0x16C0000,0x1CC0000,0x9F80000,0x37FC0000,0x50C0000,0x1400000,0x1CC0000,0x6A000001,0x1CC0000,0x1000000,0x17C0000,0x43F80000,0x7E000001,0x17C0000,0x43F80000,0x7E000001,0x43F80000,0x7E000001,0x7E000001,0x17C0000,0x43F80000,0x7E000001,0x43F80000,0x7E000001,
+0x7E000001,0x43F80000,0x7E000001,0x7E000001,0x7E000001,0x17C0000,0x43F80000,0x7E000001,0x43F80000,0x7E000001,0x7E000001,0x43F80000,0x7E000001,0x7E000001,0x7E000001,0x43F80000,0x7E000001,0x7E000001,0x7E000001,0x7E000001,0x1400000,0x1100000,0x1100000,0x3AC0000,0x29FC0000,0x61F00000,0x7E000001,0x7E000001,0x15C0000,0x1E00000,0x79C40000,0x7E000001,
+0x11FC0000,0xC40738,0xCCB402D4,0x92B402D4,0x7EB402D5,0xC2A00190,0x9AA000D5,0x80A8013A,0x88A00190,0x7CA000D5,0x74A00192,0xBC8C02D3,0x9C8C00A2,0x849800FF,0x8C8C00D1,0x7E8C0002,0x749000D7,0x7E8C02D4,0x7A8400FD,0x7284013B,0x6C8C02D3,0x3240734,0xA46802D3,0x7E8C02D4,0x965C0192,0x807400CF,0x747C0192,0x904402D3,0x7E5400A3,0x745400D7,0x6C6402D4,0x17FC0734,
+0x7E1402D4,0x74080192,0x6C0002DC,0x62000734,0xFEA000FE,0xF6BC04A0,0xF8C0053C,0xD48C0000,0xA68C0001,0x8C8C0002,0x80900012,0x7C8C0011,0xFE8800DC,0xC87C0002,0x828000A9,0x745400D7,0x1A40734,0xD802D4,0xB8C800A4,0x8CC800A4,0x7EC400A5,0xAEB400C8,0x90B40001,0x80B80015,0x82B400C8,0x7CB00026,0x74B400CA,0x14402D3,0x9A9000A2,0x7EAC00A3,0x8E8400C9,0x7E8C0002,
+0x769800CA,0x27F802D3,0x7E5400A3,0x744400CA,0x6C0002D3,0x14402D3,0x9A9000A2,0x7EAC00A3,0x8E8400C9,0x7E8C0002,0x769800CA,0x27F802D3,0x7E5400A3,0x744400CA,0x6C0002D3,0x27F802D3,0x7E5400A3,0x744400CA,0x6C0002D3,0x6C0002D3,0xFAAC0065,0xFECC01A0,0xF2D401AD,0xD48C0000,0xA68C0001,0x8C8C0002,0x80980002,0x7E800005,0xFA900071,0xC87C0001,0x847800A2,0x744400CA,
+0x1D002D3,0xB402D4,0xB402D4,0xB402D4,0xB402D4,0xA4A000C8,0xA4A000C8,0xA4A000C8,0x78A000C8,0x78A000C8,0x6AA000C9,0x9C8C00A2,0x9C8C00A2,0x9C8C00A2,0x7E8C0001,0x7E8C0001,0x6E900026,0x708C00A2,0x708C00A2,0x6A880015,0x628C00A2,0x10802D3,0x10802D3,0x10802D3,0x846C00C9,0x846C00C9,0x6C8400C9,0x7E5400A2,0x7E5400A2,0x6A680002,0x627000A2,0x9F802D3,
+0x9F802D3,0x6A3000C9,0x621400A2,0x580002D3,0xFC9C005A,0xFEAC0189,0xB402D4,0xD48C0000,0xA28C0001,0x8C8C0001,0x86900006,0x788C0002,0xFE80003E,0xC87C0001,0x808400A2,0x6A680002,0x17802D3,0xC400A4,0xC400A4,0xC400A4,0xC400A4,0x90B40000,0x90B40000,0x90B40000,0x74B40000,0x74B40000,0x6AB40001,0x32400A2,0x32400A2,0x32400A2,0x7A940001,0x7A940001,
+0x6AA40001,0x17FC00A2,0x17FC00A2,0x6A6C0001,0x620000A2,0x32400A2,0x32400A2,0x32400A2,0x7A940001,0x7A940001,0x6AA40001,0x17FC00A2,0x17FC00A2,0x6A6C0001,0x620000A2,0x17FC00A2,0x17FC00A2,0x6A6C0001,0x620000A2,0x620000A2,0xFEA0000A,0xF6BC0020,0xC400A4,0xD48C0000,0xA0900000,0x8A900000,0x80980001,0x7A880000,0xF8880012,0xC87C0000,0x1A400A2,0x6A6C0001,
+0x1A400A2,0xEC00C8,0xA8D80000,0x88D80001,0x7ED80001,0x35C00C8,0x90B40001,0x7EC40001,0x33FC00C8,0x7E880001,0x740000CA,0x35C00C8,0x90B40001,0x7EC40001,0x33FC00C8,0x7E880001,0x740000CA,0x33FC00C8,0x7E880001,0x740000CA,0x740000CA,0x35C00C8,0x90B40001,0x7EC40001,0x33FC00C8,0x7E880001,0x740000CA,0x33FC00C8,0x7E880001,0x740000CA,0x740000CA,0x33FC00C8,
+0x7E880001,0x740000CA,0x740000CA,0x740000CA,0xFEB40029,0xFC00C8,0xFAE4003D,0xD0900000,0xA6880001,0x8E880000,0x7EA00001,0x7E6C0001,0xFE980020,0xCA7C0000,0x82A40000,0x740000CA,0x1F400C8,0xA000C8,0xA000C8,0xA000C8,0xA000C8,0xA000C8,0xA000C8,0xA000C8,0xA000C8,0xA000C8,0xA000C8,0x828C0000,0x828C0000,0x828C0000,0x828C0000,0x828C0000,
+0x828C0000,0x628C0001,0x628C0001,0x628C0001,0x588C0001,0xEC00C8,0xEC00C8,0xEC00C8,0xEC00C8,0xEC00C8,0xEC00C8,0x6A680001,0x6A680001,0x6A680001,0x58780001,0x1E400C8,0x1E400C8,0x1E400C8,0x583C0001,0x4E0000CA,0xF2940029,0xA000C8,0xA000C8,0xD08C0000,0xA68C0000,0x908C0000,0x908C0000,0x768C0000,0xF47C000D,0xC07C0001,0x6A880001,0x6A680001,
+0x15400C8,};
+static const uint32_t g_etc1_to_bc7_m6_table77[] = {
+0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0x1D80000,
+0x1D80000,0x1D80000,0x1D80000,0x4C000001,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0xAA40000,0xAA40000,0xAA40000,0xE80000,0x14C0000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,
+0x1240000,0x17F80000,0x17F80000,0x17F80000,0x60000001,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x17F80000,0x17F80000,0x17F80000,0x60000001,0x17F80000,0x17F80000,0x17F80000,0x60000001,0x60000001,0xD00000,0xC40000,0xC40000,0xE40000,0x2F40000,0x3080000,0x3080000,0x1480000,0xE40000,0x2F40000,0x1A00000,0x17F80000,
+0x1A00000,0xE80000,0xE80000,0xE80000,0xE80000,0x1580000,0x1580000,0x1580000,0x31F80000,0x31F80000,0x72000001,0x1580000,0x1580000,0x1580000,0x31F80000,0x31F80000,0x72000001,0x31F80000,0x31F80000,0x72000001,0x72000001,0x1580000,0x1580000,0x1580000,0x31F80000,0x31F80000,0x72000001,0x31F80000,0x31F80000,0x72000001,0x72000001,0x31F80000,
+0x31F80000,0x72000001,0x72000001,0x72000001,0x30C0000,0xF80000,0xE80000,0x13C0000,0x1840000,0x1EC0000,0x15FC0000,0x43F40000,0x5200000,0x1580000,0x1EC0000,0x72000001,0x1EC0000,0x1100000,0x1940000,0x4FF80000,0x86000001,0x1940000,0x4FF80000,0x86000001,0x4FF80000,0x86000001,0x86000001,0x1940000,0x4FF80000,0x86000001,0x4FF80000,0x86000001,
+0x86000001,0x4FF80000,0x86000001,0x86000001,0x86000001,0x1940000,0x4FF80000,0x86000001,0x4FF80000,0x86000001,0x86000001,0x4FF80000,0x86000001,0x86000001,0x86000001,0x4FF80000,0x86000001,0x86000001,0x86000001,0x86000001,0x1540000,0x9200000,0x9200000,0x1C80000,0x37FC0000,0x6BF00000,0x86000001,0x86000001,0x3700000,0x3FC0000,0x81D40000,0x86000001,
+0x1FFC0000,0xD40738,0xD4C402D4,0x9AC402D4,0x86C402D5,0xCAB00190,0xA2B000D5,0x88B8013A,0x90B00190,0x84B000D5,0x7CB00192,0xC49C02D3,0xA49C00A2,0x8CA800FF,0x949C00D1,0x869C0002,0x7CA000D7,0x869C02D4,0x829400FD,0x7A94013B,0x749C02D3,0x33C0734,0xAC7802D3,0x869C02D4,0x9E6C0192,0x888400CF,0x7C8C0192,0x985402D3,0x866400A3,0x7C6400D7,0x747402D4,0x23FC0734,
+0x862402D4,0x7C180192,0x740002D4,0x6A000734,0xFEB4012D,0xFECC04A0,0xFECC0554,0xDC9C0000,0xAE9C0001,0x949C0002,0x88A00012,0x849C0011,0xFE9800FA,0xD08C0002,0x8A9000A9,0x7C6400D7,0x1C80734,0xE802D4,0xC0D800A4,0x94D800A4,0x86D400A5,0xB6C400C8,0x98C40001,0x88C80015,0x8AC400C8,0x84C00026,0x7CC400CA,0x15C02D3,0xA2A000A2,0x86BC00A3,0x969400C9,0x869C0002,
+0x7EA800CA,0x33F802D3,0x866400A3,0x7C5400CA,0x740002D3,0x15C02D3,0xA2A000A2,0x86BC00A3,0x969400C9,0x869C0002,0x7EA800CA,0x33F802D3,0x866400A3,0x7C5400CA,0x740002D3,0x33F802D3,0x866400A3,0x7C5400CA,0x740002D3,0x740002D3,0xFEBC0076,0xF6DC01BA,0xFAE401AD,0xDC9C0000,0xAE9C0001,0x949C0002,0x88A80002,0x86900005,0xFEA40081,0xD08C0001,0x8C8800A2,0x7C5400CA,
+0x1F002D3,0xC402D4,0xC402D4,0xC402D4,0xC402D4,0xACB000C8,0xACB000C8,0xACB000C8,0x80B000C8,0x80B000C8,0x72B000C9,0xA49C00A2,0xA49C00A2,0xA49C00A2,0x869C0001,0x869C0001,0x76A00026,0x789C00A2,0x789C00A2,0x72980015,0x6A9C00A2,0x12002D3,0x12002D3,0x12002D3,0x8C7C00C9,0x8C7C00C9,0x749400C9,0x866400A2,0x866400A2,0x72780002,0x6A8000A2,0x15F802D3,
+0x15F802D3,0x724000C9,0x6A2400A2,0x600002D3,0xFEAC0065,0xF6BC01A0,0xC402D4,0xDC9C0000,0xAA9C0001,0x949C0001,0x8EA00006,0x809C0002,0xFE90004A,0xD08C0001,0x889400A2,0x72780002,0x19C02D3,0xD400A4,0xD400A4,0xD400A4,0xD400A4,0x98C40000,0x98C40000,0x98C40000,0x7CC40000,0x7CC40000,0x72C40001,0x33C00A2,0x33C00A2,0x33C00A2,0x82A40001,0x82A40001,
+0x72B40001,0x23FC00A2,0x23FC00A2,0x727C0001,0x6A0000A2,0x33C00A2,0x33C00A2,0x33C00A2,0x82A40001,0x82A40001,0x72B40001,0x23FC00A2,0x23FC00A2,0x727C0001,0x6A0000A2,0x23FC00A2,0x23FC00A2,0x727C0001,0x6A0000A2,0x6A0000A2,0xFAB4000D,0xFECC0020,0xD400A4,0xDC9C0000,0xA8A00000,0x92A00000,0x88A80001,0x82980000,0xF29C0019,0xD08C0000,0x1C800A2,0x727C0001,
+0x1C800A2,0xFC00C8,0xB0E80000,0x90E80001,0x86E80001,0x37400C8,0x98C40001,0x86D40001,0x3FFC00C8,0x86980001,0x7C0000CA,0x37400C8,0x98C40001,0x86D40001,0x3FFC00C8,0x86980001,0x7C0000CA,0x3FFC00C8,0x86980001,0x7C0000CA,0x7C0000CA,0x37400C8,0x98C40001,0x86D40001,0x3FFC00C8,0x86980001,0x7C0000CA,0x3FFC00C8,0x86980001,0x7C0000CA,0x7C0000CA,0x3FFC00C8,
+0x86980001,0x7C0000CA,0x7C0000CA,0x7C0000CA,0xFAC80032,0x10C00C8,0xF2F40048,0xD8A00000,0xAE980001,0x96980000,0x86B00001,0x867C0001,0xFEAC0029,0xD28C0000,0x8AB40000,0x7C0000CA,0xDFC00C8,0xB000C8,0xB000C8,0xB000C8,0xB000C8,0xB000C8,0xB000C8,0xB000C8,0xB000C8,0xB000C8,0xB000C8,0x8A9C0000,0x8A9C0000,0x8A9C0000,0x8A9C0000,0x8A9C0000,
+0x8A9C0000,0x6A9C0001,0x6A9C0001,0x6A9C0001,0x609C0001,0x10400C8,0x10400C8,0x10400C8,0x10400C8,0x10400C8,0x10400C8,0x72780001,0x72780001,0x72780001,0x60880001,0x7FC00C8,0x7FC00C8,0x7FC00C8,0x604C0001,0x560000CA,0xFAA40029,0xB000C8,0xB000C8,0xD89C0000,0xAE9C0000,0x989C0000,0x989C0000,0x7E9C0000,0xFC8C000D,0xC88C0001,0x72980001,0x72780001,
+0x17400C8,};
+static const uint32_t g_etc1_to_bc7_m6_table78[] = {
+0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0x1000000,0x1000000,0x1000000,0x1000000,0x1000000,0x1000000,0x1000000,0x1000000,0x1000000,0x1000000,0x5F80000,
+0x5F80000,0x5F80000,0x5F80000,0x54000001,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xB80000,0xB80000,0xB80000,0x1000000,0x16C0000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,
+0x13C0000,0x21FC0000,0x21FC0000,0x21FC0000,0x68000001,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x21FC0000,0x21FC0000,0x21FC0000,0x68000001,0x21FC0000,0x21FC0000,0x21FC0000,0x68000001,0x68000001,0x8E00000,0xD40000,0xD40000,0x4F40000,0x3080000,0x1200000,0x1200000,0x1640000,0x4F40000,0x3080000,0x1C00000,0x21FC0000,
+0x1C00000,0xF80000,0xF80000,0xF80000,0xF80000,0x1700000,0x1700000,0x1700000,0x3DF80000,0x3DF80000,0x7A000001,0x1700000,0x1700000,0x1700000,0x3DF80000,0x3DF80000,0x7A000001,0x3DF80000,0x3DF80000,0x7A000001,0x7A000001,0x1700000,0x1700000,0x1700000,0x3DF80000,0x3DF80000,0x7A000001,0x3DF80000,0x3DF80000,0x7A000001,0x7A000001,0x3DF80000,
+0x3DF80000,0x7A000001,0x7A000001,0x7A000001,0x1200000,0x1080000,0xF80000,0x1500000,0x1A00000,0x9FC0000,0x23FC0000,0x4DFC0000,0x5340000,0x1700000,0x9FC0000,0x7A000001,0x9FC0000,0x1200000,0x1AC0000,0x5BF80000,0x8E000001,0x1AC0000,0x5BF80000,0x8E000001,0x5BF80000,0x8E000001,0x8E000001,0x1AC0000,0x5BF80000,0x8E000001,0x5BF80000,0x8E000001,
+0x8E000001,0x5BF80000,0x8E000001,0x8E000001,0x8E000001,0x1AC0000,0x5BF80000,0x8E000001,0x5BF80000,0x8E000001,0x8E000001,0x5BF80000,0x8E000001,0x8E000001,0x8E000001,0x5BF80000,0x8E000001,0x8E000001,0x8E000001,0x8E000001,0x1680000,0x1340000,0x1340000,0x1E40000,0x45FC0000,0x75F00000,0x8E000001,0x8E000001,0x1880000,0x13FC0000,0x89E40000,0x8E000001,
+0x2FFC0000,0xE40738,0xDCD402D4,0xA2D402D4,0x8ED402D5,0xD2C00190,0xAAC000D5,0x90C8013A,0x98C00190,0x8CC000D5,0x84C00192,0xCCAC02D3,0xACAC00A2,0x94B800FF,0x9CAC00D1,0x8EAC0002,0x84B000D7,0x8EAC02D4,0x8AA400FD,0x82A4013B,0x7CAC02D3,0x1540734,0xB48802D3,0x8EAC02D4,0xA67C0192,0x909400CF,0x849C0192,0xA06402D3,0x8E7400A3,0x847400D7,0x7C8402D4,0x2FFC0734,
+0x8E3402D4,0x84280192,0x7C0C02D3,0x72000734,0xFEC40168,0xF6DC04DA,0xF8E00569,0xE4AC0000,0xB6AC0001,0x9CAC0002,0x90B00012,0x8CAC0011,0xFCB0013D,0xD89C0002,0x92A000A9,0x847400D7,0x1E80734,0xF802D4,0xC8E800A4,0x9CE800A4,0x8EE400A5,0xBED400C8,0xA0D40001,0x90D80015,0x92D400C8,0x8CD00026,0x84D400CA,0x17402D3,0xAAB000A2,0x8ECC00A3,0x9EA400C9,0x8EAC0002,
+0x86B800CA,0x3FF802D3,0x8E7400A3,0x846400CA,0x7C0002D3,0x17402D3,0xAAB000A2,0x8ECC00A3,0x9EA400C9,0x8EAC0002,0x86B800CA,0x3FF802D3,0x8E7400A3,0x846400CA,0x7C0002D3,0x3FF802D3,0x8E7400A3,0x846400CA,0x7C0002D3,0x7C0002D3,0xFED00083,0xFEEC01BA,0xF2F401C8,0xE4AC0000,0xB6AC0001,0x9CAC0002,0x90B80002,0x8EA00005,0xFEB40095,0xD89C0001,0x949800A2,0x846400CA,
+0xBFC02D3,0xD402D4,0xD402D4,0xD402D4,0xD402D4,0xB4C000C8,0xB4C000C8,0xB4C000C8,0x88C000C8,0x88C000C8,0x7AC000C9,0xACAC00A2,0xACAC00A2,0xACAC00A2,0x8EAC0001,0x8EAC0001,0x7EB00026,0x80AC00A2,0x80AC00A2,0x7AA80015,0x72AC00A2,0x13802D3,0x13802D3,0x13802D3,0x948C00C9,0x948C00C9,0x7CA400C9,0x8E7400A2,0x8E7400A2,0x7A880002,0x729000A2,0x21F802D3,
+0x21F802D3,0x7A5000C9,0x723400A2,0x680002D3,0xFEBC0075,0xFECC01A0,0xD402D4,0xE4AC0000,0xB2AC0001,0x9CAC0001,0x96B00006,0x88AC0002,0xFEA0005A,0xD89C0001,0x90A400A2,0x7A880002,0x1BC02D3,0xE400A4,0xE400A4,0xE400A4,0xE400A4,0xA0D40000,0xA0D40000,0xA0D40000,0x84D40000,0x84D40000,0x7AD40001,0x15400A2,0x15400A2,0x15400A2,0x8AB40001,0x8AB40001,
+0x7AC40001,0x2FFC00A2,0x2FFC00A2,0x7A8C0001,0x720000A2,0x15400A2,0x15400A2,0x15400A2,0x8AB40001,0x8AB40001,0x7AC40001,0x2FFC00A2,0x2FFC00A2,0x7A8C0001,0x720000A2,0x2FFC00A2,0x2FFC00A2,0x7A8C0001,0x720000A2,0x720000A2,0xF6C80012,0xF6DC0029,0xE400A4,0xE4AC0000,0xB0B00000,0x9AB00000,0x90B80001,0x8AA80000,0xFAAC0019,0xD89C0000,0x1E800A2,0x7A8C0001,
+0x1E800A2,0x10C00C8,0xB8F80000,0x98F80001,0x8EF80001,0x38C00C8,0xA0D40001,0x8EE40001,0x4BFC00C8,0x8EA80001,0x840000CA,0x38C00C8,0xA0D40001,0x8EE40001,0x4BFC00C8,0x8EA80001,0x840000CA,0x4BFC00C8,0x8EA80001,0x840000CA,0x840000CA,0x38C00C8,0xA0D40001,0x8EE40001,0x4BFC00C8,0x8EA80001,0x840000CA,0x4BFC00C8,0x8EA80001,0x840000CA,0x840000CA,0x4BFC00C8,
+0x8EA80001,0x840000CA,0x840000CA,0x840000CA,0xF2E0003D,0x71C00C8,0xFB040048,0xE0B00000,0xB6A80001,0x9EA80000,0x8EC00001,0x8E8C0001,0xF4C80032,0xDA9C0000,0x92C40000,0x840000CA,0x1DF800C8,0xC000C8,0xC000C8,0xC000C8,0xC000C8,0xC000C8,0xC000C8,0xC000C8,0xC000C8,0xC000C8,0xC000C8,0x92AC0000,0x92AC0000,0x92AC0000,0x92AC0000,0x92AC0000,
+0x92AC0000,0x72AC0001,0x72AC0001,0x72AC0001,0x68AC0001,0x11C00C8,0x11C00C8,0x11C00C8,0x11C00C8,0x11C00C8,0x11C00C8,0x7A880001,0x7A880001,0x7A880001,0x68980001,0x13FC00C8,0x13FC00C8,0x13FC00C8,0x685C0001,0x5E0000CA,0xF2B40034,0xC000C8,0xC000C8,0xE0AC0000,0xB6AC0000,0xA0AC0000,0xA0AC0000,0x86AC0000,0xFC9C0012,0xD09C0001,0x7AA80001,0x7A880001,
+0x19800C8,};
+static const uint32_t g_etc1_to_bc7_m6_table79[] = {
+0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x11F80000,
+0x11F80000,0x11F80000,0x11F80000,0x5C000001,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xC80000,0xC80000,0xC80000,0x1180000,0x1900000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,
+0x3500000,0x2DFC0000,0x2DFC0000,0x2DFC0000,0x70000001,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,0x2DFC0000,0x2DFC0000,0x2DFC0000,0x70000001,0x2DFC0000,0x2DFC0000,0x2DFC0000,0x70000001,0x70000001,0xF40000,0xE40000,0xE40000,0x1080000,0x31C0000,0x3340000,0x3340000,0x1800000,0x1080000,0x31C0000,0x1E40000,0x2DFC0000,
+0x1E40000,0x1080000,0x1080000,0x1080000,0x1080000,0x1880000,0x1880000,0x1880000,0x49F80000,0x49F80000,0x82000001,0x1880000,0x1880000,0x1880000,0x49F80000,0x49F80000,0x82000001,0x49F80000,0x49F80000,0x82000001,0x82000001,0x1880000,0x1880000,0x1880000,0x49F80000,0x49F80000,0x82000001,0x49F80000,0x49F80000,0x82000001,0x82000001,0x49F80000,
+0x49F80000,0x82000001,0x82000001,0x82000001,0x1340000,0x5180000,0x1080000,0x1680000,0x1BC0000,0x19FC0000,0x31FC0000,0x59F40000,0x14C0000,0x1880000,0x19FC0000,0x82000001,0x19FC0000,0x1300000,0x1C40000,0x67F80000,0x96000001,0x1C40000,0x67F80000,0x96000001,0x67F80000,0x96000001,0x96000001,0x1C40000,0x67F80000,0x96000001,0x67F80000,0x96000001,
+0x96000001,0x67F80000,0x96000001,0x96000001,0x96000001,0x1C40000,0x67F80000,0x96000001,0x67F80000,0x96000001,0x96000001,0x67F80000,0x96000001,0x96000001,0x96000001,0x67F80000,0x96000001,0x96000001,0x96000001,0x96000001,0x17C0000,0x1440000,0x1440000,0x3FC0000,0x53F80000,0x7FF00000,0x96000001,0x96000001,0x19C0000,0x25FC0000,0x91F40000,0x96000001,
+0x3FF80000,0xF40738,0xE4E402D4,0xAAE402D4,0x96E402D5,0xDAD00190,0xB2D000D5,0x98D8013A,0xA0D00190,0x94D000D5,0x8CD00192,0xD4BC02D3,0xB4BC00A2,0x9CC800FF,0xA4BC00D1,0x96BC0002,0x8CC000D7,0x96BC02D4,0x92B400FD,0x8AB4013B,0x84BC02D3,0x16C0734,0xBC9802D3,0x96BC02D4,0xAE8C0192,0x98A400CF,0x8CAC0192,0xA87402D3,0x968400A3,0x8C8400D7,0x849402D4,0x3BFC0734,
+0x964402D4,0x8C380192,0x841C02D3,0x7A000734,0xFED8019A,0xFEEC04DA,0xFEEC0585,0xECBC0000,0xBEBC0001,0xA4BC0002,0x98C00012,0x94BC0011,0xFEBC0167,0xE0AC0002,0x9AB000A9,0x8C8400D7,0x7FC0734,0x10802D4,0xD0F800A4,0xA4F800A4,0x96F400A5,0xC6E400C8,0xA8E40001,0x98E80015,0x9AE400C8,0x94E00026,0x8CE400CA,0x18C02D3,0xB2C000A2,0x96DC00A3,0xA6B400C9,0x96BC0002,
+0x8EC800CA,0x4BF802D3,0x968400A3,0x8C7400CA,0x840002D3,0x18C02D3,0xB2C000A2,0x96DC00A3,0xA6B400C9,0x96BC0002,0x8EC800CA,0x4BF802D3,0x968400A3,0x8C7400CA,0x840002D3,0x4BF802D3,0x968400A3,0x8C7400CA,0x840002D3,0x840002D3,0xFEE400A6,0xF90001D4,0xFB0401C8,0xECBC0000,0xBEBC0001,0xA4BC0002,0x98C80002,0x96B00005,0xFACC00B5,0xE0AC0001,0x9CA800A2,0x8C7400CA,
+0x1BFC02D3,0xE402D4,0xE402D4,0xE402D4,0xE402D4,0xBCD000C8,0xBCD000C8,0xBCD000C8,0x90D000C8,0x90D000C8,0x82D000C9,0xB4BC00A2,0xB4BC00A2,0xB4BC00A2,0x96BC0001,0x96BC0001,0x86C00026,0x88BC00A2,0x88BC00A2,0x82B80015,0x7ABC00A2,0x15002D3,0x15002D3,0x15002D3,0x9C9C00C9,0x9C9C00C9,0x84B400C9,0x968400A2,0x968400A2,0x82980002,0x7AA000A2,0x2DF802D3,
+0x2DF802D3,0x826000C9,0x7A4400A2,0x700002D3,0xFECC0084,0xF6DC01B9,0xE402D4,0xECBC0000,0xBABC0001,0xA4BC0001,0x9EC00006,0x90BC0002,0xFEB40065,0xE0AC0001,0x98B400A2,0x82980002,0x1E002D3,0xF400A4,0xF400A4,0xF400A4,0xF400A4,0xA8E40000,0xA8E40000,0xA8E40000,0x8CE40000,0x8CE40000,0x82E40001,0x16C00A2,0x16C00A2,0x16C00A2,0x92C40001,0x92C40001,
+0x82D40001,0x3BFC00A2,0x3BFC00A2,0x829C0001,0x7A0000A2,0x16C00A2,0x16C00A2,0x16C00A2,0x92C40001,0x92C40001,0x82D40001,0x3BFC00A2,0x3BFC00A2,0x829C0001,0x7A0000A2,0x3BFC00A2,0x3BFC00A2,0x829C0001,0x7A0000A2,0x7A0000A2,0xFED80012,0xFEEC0029,0xF400A4,0xECBC0000,0xB8C00000,0xA2C00000,0x98C80001,0x92B80000,0xFCC00020,0xE0AC0000,0x7FC00A2,0x829C0001,
+0x7FC00A2,0x11C00C8,0xC1080000,0xA1080001,0x97080001,0x3A400C8,0xA8E40001,0x96F40001,0x57FC00C8,0x96B80001,0x8C0000CA,0x3A400C8,0xA8E40001,0x96F40001,0x57FC00C8,0x96B80001,0x8C0000CA,0x57FC00C8,0x96B80001,0x8C0000CA,0x8C0000CA,0x3A400C8,0xA8E40001,0x96F40001,0x57FC00C8,0x96B80001,0x8C0000CA,0x57FC00C8,0x96B80001,0x8C0000CA,0x8C0000CA,0x57FC00C8,
+0x96B80001,0x8C0000CA,0x8C0000CA,0x8C0000CA,0xFAF0003D,0xF2C00C8,0xF3140055,0xE8C00000,0xBEB80001,0xA6B80000,0x96D00001,0x969C0001,0xFCD80032,0xE2AC0000,0x9AD40000,0x8C0000CA,0x2BFC00C8,0xD000C8,0xD000C8,0xD000C8,0xD000C8,0xD000C8,0xD000C8,0xD000C8,0xD000C8,0xD000C8,0xD000C8,0x9ABC0000,0x9ABC0000,0x9ABC0000,0x9ABC0000,0x9ABC0000,
+0x9ABC0000,0x7ABC0001,0x7ABC0001,0x7ABC0001,0x70BC0001,0x13400C8,0x13400C8,0x13400C8,0x13400C8,0x13400C8,0x13400C8,0x82980001,0x82980001,0x82980001,0x70A80001,0x1FF800C8,0x1FF800C8,0x1FF800C8,0x706C0001,0x660000CA,0xFAC40034,0xD000C8,0xD000C8,0xE8BC0000,0xBEBC0000,0xA8BC0000,0xA8BC0000,0x8EBC0000,0xF8B00019,0xD8AC0001,0x82B80001,0x82980001,
+0x1B800C8,};
+static const uint32_t g_etc1_to_bc7_m6_table80[] = {
+0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0x3300000,0x3300000,0x3300000,0x3300000,0x3300000,0x3300000,0x3300000,0x3300000,0x3300000,0x3300000,0x1DFC0000,
+0x1DFC0000,0x1DFC0000,0x1DFC0000,0x66000000,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0xDC0000,0xDC0000,0xDC0000,0x3300000,0x1B40000,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,
+0x16C0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x7A000000,0xB040000,0xF40001,0xF40001,0x51C0000,0x1340000,0x34C0000,0x34C0000,0x19C0000,0x51C0000,0x1340000,0x7FC0000,0x3BFC0000,
+0x7FC0000,0x1180001,0x1180001,0x1180001,0x1180001,0x1A40000,0x1A40000,0x1A40000,0x57F80000,0x57F80000,0x8C000000,0x1A40000,0x1A40000,0x1A40000,0x57F80000,0x57F80000,0x8C000000,0x57F80000,0x57F80000,0x8C000000,0x8C000000,0x1A40000,0x1A40000,0x1A40000,0x57F80000,0x57F80000,0x8C000000,0x57F80000,0x57F80000,0x8C000000,0x8C000000,0x57F80000,
+0x57F80000,0x8C000000,0x8C000000,0x8C000000,0x1480000,0x12C0000,0x1180001,0x1800000,0x1D80000,0x29FC0000,0x3FFC0000,0x65F40000,0x3600000,0x1A40000,0x29FC0000,0x8C000000,0x29FC0000,0x1400001,0x3DC0000,0x73FC0000,0xA0000000,0x3DC0000,0x73FC0000,0xA0000000,0x73FC0000,0xA0000000,0xA0000000,0x3DC0000,0x73FC0000,0xA0000000,0x73FC0000,0xA0000000,
+0xA0000000,0x73FC0000,0xA0000000,0xA0000000,0xA0000000,0x3DC0000,0x73FC0000,0xA0000000,0x73FC0000,0xA0000000,0xA0000000,0x73FC0000,0xA0000000,0xA0000000,0xA0000000,0x73FC0000,0xA0000000,0xA0000000,0xA0000000,0xA0000000,0x1940000,0x1580000,0x1580000,0x19FC0000,0x61FC0000,0x89FC0000,0xA0000000,0xA0000000,0x3B40000,0x37FC0000,0x9BE80000,0xA0000000,
+0x4FFC0000,0x1080734,0xF0F402D3,0xB2F402D4,0xA0F402D3,0xE2E40192,0xBAE400D7,0xA4E8013B,0xA8E40192,0x9EE000D7,0x96E00192,0xDAD002D4,0xBCD000A3,0xA4D800FD,0xACCC00CF,0xA0D00002,0x96D400D5,0xA0CC02D4,0x9AC400FF,0x92CC013A,0x8CCC02D5,0x1880734,0xC4AC02D3,0xA0D002D4,0xB89C0192,0xA0B400D1,0x96BC0190,0xB28402D3,0xA09400A2,0x969800D5,0x8CA802D4,0x49F80734,
+0xA05402D3,0x96440190,0x8C3002D4,0x82000738,0xFEEC01E2,0xF9000514,0xFB040594,0xF4D00002,0xC6CC0003,0xAED00002,0xA0D40011,0x9EC80012,0xFED4019A,0xECBC0000,0xA2C400A9,0x969800D5,0x19FC0734,0x11C02D3,0xDB0800A2,0xAF0800A2,0xA10800A2,0xCCF800C9,0xB0F80002,0xA2F80015,0xA4F400C9,0x9EF00026,0x96F400C9,0x3A402D3,0xBCD000A2,0xA0EC00A2,0xB0C400C9,0xA0D00001,
+0x96DC00C8,0x57FC02D3,0xA09000A2,0x968400C8,0x8C0002D4,0x3A402D3,0xBCD000A2,0xA0EC00A2,0xB0C400C9,0xA0D00001,0x96DC00C8,0x57FC02D3,0xA09000A2,0x968400C8,0x8C0002D4,0x57FC02D3,0xA09000A2,0x968400C8,0x8C0002D4,0x8C0002D4,0xFEF800B6,0xFF0C01E3,0xF51801E6,0xF4D00001,0xC6CC0002,0xAED00001,0xA0DC0002,0x9EC00006,0xFEDC00C5,0xECBC0000,0xA4BC00A2,0x968400C8,
+0x2BFC02D3,0xF402D3,0xF402D3,0xF402D3,0xF402D3,0xC2E400CA,0xC2E400CA,0xC2E400CA,0x9AE000CA,0x9AE000CA,0x8CE000CA,0xBCD000A3,0xBCD000A3,0xBCD000A3,0x9ED00002,0x9ED00002,0x8ED40026,0x90D000A3,0x90D000A3,0x8ACC0015,0x82CC00A5,0x36802D3,0x36802D3,0x36802D3,0xA4B000C9,0xA4B000C9,0x8CC800C8,0x9E9800A2,0x9E9800A2,0x8CA80001,0x82B400A4,0x39FC02D3,
+0x39FC02D3,0x8C7000C8,0x825C00A4,0x7A0002D4,0xFAE000A6,0xFEEC01BE,0xF402D3,0xF8CC0001,0xC2D00002,0xACD00002,0xA6D00005,0x9ACC0002,0xFCCC0080,0xECBC0000,0xA0C800A3,0x8CA80001,0x5FC02D3,0x10800A2,0x10800A2,0x10800A2,0x10800A2,0xAEF80001,0xAEF80001,0xAEF80001,0x94F80001,0x94F80001,0x8CF40001,0x18800A2,0x18800A2,0x18800A2,0x9AD80001,0x9AD80001,
+0x8CE40000,0x49F800A2,0x49F800A2,0x8CAC0000,0x820000A4,0x18800A2,0x18800A2,0x18800A2,0x9AD80001,0x9AD80001,0x8CE40000,0x49F800A2,0x49F800A2,0x8CAC0000,0x820000A4,0x49F800A2,0x49F800A2,0x8CAC0000,0x820000A4,0x820000A4,0xFAEC0019,0xF9000032,0x10800A2,0xF8CC0000,0xBED40000,0xAAD40000,0xA2D80000,0x9ACC0001,0xFED00028,0xECBC0000,0x19FC00A2,0x8CAC0000,
+0x19FC00A2,0x12C00CA,0xC71C0001,0xAB180001,0xA1180001,0x1C000C8,0xB0F80001,0xA1040001,0x65F800C8,0xA0C80000,0x960000C8,0x1C000C8,0xB0F80001,0xA1040001,0x65F800C8,0xA0C80000,0x960000C8,0x65F800C8,0xA0C80000,0x960000C8,0x960000C8,0x1C000C8,0xB0F80001,0xA1040001,0x65F800C8,0xA0C80000,0x960000C8,0x65F800C8,0xA0C80000,0x960000C8,0x960000C8,0x65F800C8,
+0xA0C80000,0x960000C8,0x960000C8,0x960000C8,0xFB040048,0x94000C8,0xFD280055,0xF4D00000,0xC6CC0001,0xB0C80000,0xA0E00000,0xA0A80000,0xFEF0003D,0xECBC0000,0xA2E80001,0x960000C8,0x3DF800C8,0xE000CA,0xE000CA,0xE000CA,0xE000CA,0xE000CA,0xE000CA,0xE000CA,0xE000CA,0xE000CA,0xE000CA,0xA0D00001,0xA0D00001,0xA0D00001,0xA0D00001,0xA0D00001,
+0xA0D00001,0x84CC0001,0x84CC0001,0x84CC0001,0x7ACC0001,0x15000C8,0x15000C8,0x15000C8,0x15000C8,0x15000C8,0x15000C8,0x8AAC0001,0x8AAC0001,0x8AAC0001,0x7AB80001,0x2DF800C8,0x2DF800C8,0x2DF800C8,0x7A7C0000,0x700000C8,0xF4D8003D,0xE000CA,0xE000CA,0xECD00001,0xC4D00001,0xAED00001,0xAED00001,0x96D00001,0xF4C40020,0xEABC0000,0x8EC80000,0x8AAC0001,
+0x1E000C8,};
+static const uint32_t g_etc1_to_bc7_m6_table81[] = {
+0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x29FC0000,
+0x29FC0000,0x29FC0000,0x29FC0000,0x6E000000,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xDC0001,0xEC0000,0xEC0000,0xEC0000,0x1480000,0x1D80000,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,
+0x1840000,0x47FC0000,0x47FC0000,0x47FC0000,0x82000000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x47FC0000,0x47FC0000,0x47FC0000,0x82000000,0x47FC0000,0x47FC0000,0x47FC0000,0x82000000,0x82000000,0x1180000,0x1040001,0x1040001,0x1300000,0x1480000,0x1640000,0x1640000,0x1B80000,0x1300000,0x1480000,0x17FC0000,0x47FC0000,
+0x17FC0000,0x1280001,0x1280001,0x1280001,0x1280001,0x1BC0000,0x1BC0000,0x1BC0000,0x61FC0000,0x61FC0000,0x94000000,0x1BC0000,0x1BC0000,0x1BC0000,0x61FC0000,0x61FC0000,0x94000000,0x61FC0000,0x61FC0000,0x94000000,0x94000000,0x1BC0000,0x1BC0000,0x1BC0000,0x61FC0000,0x61FC0000,0x94000000,0x61FC0000,0x61FC0000,0x94000000,0x94000000,0x61FC0000,
+0x61FC0000,0x94000000,0x94000000,0x94000000,0x5580000,0x73C0000,0x1280001,0x1940000,0x1F40000,0x39FC0000,0x4DFC0000,0x6FFC0000,0x3740000,0x1BC0000,0x39FC0000,0x94000000,0x39FC0000,0x1500001,0x3F40000,0x7FFC0000,0xA8000000,0x3F40000,0x7FFC0000,0xA8000000,0x7FFC0000,0xA8000000,0xA8000000,0x3F40000,0x7FFC0000,0xA8000000,0x7FFC0000,0xA8000000,
+0xA8000000,0x7FFC0000,0xA8000000,0xA8000000,0xA8000000,0x3F40000,0x7FFC0000,0xA8000000,0x7FFC0000,0xA8000000,0xA8000000,0x7FFC0000,0xA8000000,0xA8000000,0xA8000000,0x7FFC0000,0xA8000000,0xA8000000,0xA8000000,0xA8000000,0x1A80000,0x1680000,0x1680000,0x2DFC0000,0x6FFC0000,0x93FC0000,0xA8000000,0xA8000000,0x1CC0000,0x49FC0000,0xA3F80000,0xA8000000,
+0x5FF80000,0x1180734,0xF90402D3,0xBB0402D4,0xA90402D3,0xEAF40192,0xC2F400D7,0xACF8013B,0xB0F40192,0xA6F000D7,0x9EF00192,0xE2E002D4,0xC4E000A3,0xACE800FD,0xB4DC00CF,0xA8E00002,0x9EE400D5,0xA8DC02D4,0xA2D400FF,0x9ADC013A,0x94DC02D5,0x1A00734,0xCCBC02D3,0xA8E002D4,0xC0AC0192,0xA8C400D1,0x9ECC0190,0xBA9402D3,0xA8A400A2,0x9EA800D5,0x94B802D4,0x55F80734,
+0xA86402D3,0x9E540190,0x944002D4,0x8A000738,0xFEF8021F,0xFF0C0524,0xF31405C3,0xFCE00002,0xCEDC0003,0xB6E00002,0xA8E40011,0xA6D80012,0xFCEC01F6,0xF4CC0000,0xAAD400A9,0x9EA800D5,0x27FC0734,0x12C02D3,0xE31800A2,0xB71800A2,0xA91800A2,0xD50800C9,0xB9080002,0xAB080015,0xAD0400C9,0xA7000026,0x9F0400C9,0x3BC02D3,0xC4E000A2,0xA8FC00A2,0xB8D400C9,0xA8E00001,
+0x9EEC00C8,0x63FC02D3,0xA8A000A2,0x9E9400C8,0x940002D4,0x3BC02D3,0xC4E000A2,0xA8FC00A2,0xB8D400C9,0xA8E00001,0x9EEC00C8,0x63FC02D3,0xA8A000A2,0x9E9400C8,0x940002D4,0x63FC02D3,0xA8A000A2,0x9E9400C8,0x940002D4,0x940002D4,0xFB0C00DE,0xF92001F1,0xFD2801E6,0xFCE00001,0xCEDC0002,0xB6E00001,0xA8EC0002,0xA6D00006,0xFCF400E1,0xF4CC0000,0xACCC00A2,0x9E9400C8,
+0x3BFC02D3,0x10402D3,0x10402D3,0x10402D3,0x10402D3,0xCAF400CA,0xCAF400CA,0xCAF400CA,0xA2F000CA,0xA2F000CA,0x94F000CA,0xC4E000A3,0xC4E000A3,0xC4E000A3,0xA6E00002,0xA6E00002,0x96E40026,0x98E000A3,0x98E000A3,0x92DC0015,0x8ADC00A5,0x38002D3,0x38002D3,0x38002D3,0xACC000C9,0xACC000C9,0x94D800C8,0xA6A800A2,0xA6A800A2,0x94B80001,0x8AC400A4,0x45FC02D3,
+0x45FC02D3,0x948000C8,0x8A6C00A4,0x820002D4,0xFEF400BA,0xF90001D3,0x10402D3,0xF6E00002,0xCAE00002,0xB4E00002,0xAEE00005,0xA2DC0002,0xFED800A1,0xF4CC0000,0xA8D800A3,0x94B80001,0x15FC02D3,0x11800A2,0x11800A2,0x11800A2,0x11800A2,0xB7080001,0xB7080001,0xB7080001,0x9D080001,0x9D080001,0x95040001,0x1A000A2,0x1A000A2,0x1A000A2,0xA2E80001,0xA2E80001,
+0x94F40000,0x55F800A2,0x55F800A2,0x94BC0000,0x8A0000A4,0x1A000A2,0x1A000A2,0x1A000A2,0xA2E80001,0xA2E80001,0x94F40000,0x55F800A2,0x55F800A2,0x94BC0000,0x8A0000A4,0x55F800A2,0x55F800A2,0x94BC0000,0x8A0000A4,0x8A0000A4,0xF7000020,0xFF0C003A,0x11800A2,0xF4E40001,0xC6E40000,0xB2E40000,0xAAE80000,0xA2DC0001,0xF8EC0029,0xF4CC0000,0x27FC00A2,0x94BC0000,
+0x27FC00A2,0x13C00CA,0xCF2C0001,0xB3280001,0xA9280001,0x1D800C8,0xB9080001,0xA9140001,0x71F800C8,0xA8D80000,0x9E0000C8,0x1D800C8,0xB9080001,0xA9140001,0x71F800C8,0xA8D80000,0x9E0000C8,0x71F800C8,0xA8D80000,0x9E0000C8,0x9E0000C8,0x1D800C8,0xB9080001,0xA9140001,0x71F800C8,0xA8D80000,0x9E0000C8,0x71F800C8,0xA8D80000,0x9E0000C8,0x9E0000C8,0x71F800C8,
+0xA8D80000,0x9E0000C8,0x9E0000C8,0x9E0000C8,0xFF14004A,0x15400C8,0xF5380062,0xFCE00000,0xCEDC0001,0xB8D80000,0xA8F00000,0xA8B80000,0xF7080048,0xF4CC0000,0xAAF80001,0x9E0000C8,0x4BFC00C8,0xF000CA,0xF000CA,0xF000CA,0xF000CA,0xF000CA,0xF000CA,0xF000CA,0xF000CA,0xF000CA,0xF000CA,0xA8E00001,0xA8E00001,0xA8E00001,0xA8E00001,0xA8E00001,
+0xA8E00001,0x8CDC0001,0x8CDC0001,0x8CDC0001,0x82DC0001,0x16800C8,0x16800C8,0x16800C8,0x16800C8,0x16800C8,0x16800C8,0x92BC0001,0x92BC0001,0x92BC0001,0x82C80001,0x39F800C8,0x39F800C8,0x39F800C8,0x828C0000,0x780000C8,0xFCE8003D,0xF000CA,0xF000CA,0xF4E00001,0xCCE00001,0xB6E00001,0xB6E00001,0x9EE00001,0xFCD40020,0xF2CC0000,0x96D80000,0x92BC0001,
+0x3FC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table82[] = {
+0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x35FC0000,
+0x35FC0000,0x35FC0000,0x35FC0000,0x76000000,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0x6FC0000,0x6FC0000,0x6FC0000,0x1600000,0x1F80000,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,
+0x19C0000,0x53FC0000,0x53FC0000,0x53FC0000,0x8A000000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x53FC0000,0x53FC0000,0x53FC0000,0x8A000000,0x53FC0000,0x53FC0000,0x53FC0000,0x8A000000,0x8A000000,0x1280000,0x1140001,0x1140001,0x1440000,0x15C0000,0x3780000,0x3780000,0x1D40000,0x1440000,0x15C0000,0x25FC0000,0x53FC0000,
+0x25FC0000,0x1380001,0x1380001,0x1380001,0x1380001,0x3D00000,0x3D00000,0x3D00000,0x6DFC0000,0x6DFC0000,0x9C000000,0x3D00000,0x3D00000,0x3D00000,0x6DFC0000,0x6DFC0000,0x9C000000,0x6DFC0000,0x6DFC0000,0x9C000000,0x9C000000,0x3D00000,0x3D00000,0x3D00000,0x6DFC0000,0x6DFC0000,0x9C000000,0x6DFC0000,0x6DFC0000,0x9C000000,0x9C000000,0x6DFC0000,
+0x6DFC0000,0x9C000000,0x9C000000,0x9C000000,0x16C0000,0xF4C0000,0x1380001,0x1AC0000,0xFFC0000,0x47FC0000,0x5BFC0000,0x7BF40000,0x3880000,0x3D00000,0x47FC0000,0x9C000000,0x47FC0000,0x1600001,0x13FC0000,0x8BFC0000,0xB0000000,0x13FC0000,0x8BFC0000,0xB0000000,0x8BFC0000,0xB0000000,0xB0000000,0x13FC0000,0x8BFC0000,0xB0000000,0x8BFC0000,0xB0000000,
+0xB0000000,0x8BFC0000,0xB0000000,0xB0000000,0xB0000000,0x13FC0000,0x8BFC0000,0xB0000000,0x8BFC0000,0xB0000000,0xB0000000,0x8BFC0000,0xB0000000,0xB0000000,0xB0000000,0x8BFC0000,0xB0000000,0xB0000000,0xB0000000,0xB0000000,0x1BC0000,0x5780000,0x5780000,0x41FC0000,0x7DF80000,0x9DFC0000,0xB0000000,0xB0000000,0x1E00000,0x59FC0000,0xADCC0000,0xB0000000,
+0x6DFC0000,0x1280734,0xFD1402D4,0xC31402D4,0xB11402D3,0xF3040192,0xCB0400D7,0xB508013B,0xB9040192,0xAF0000D7,0xA7000192,0xEAF002D4,0xCCF000A3,0xB4F800FD,0xBCEC00CF,0xB0F00002,0xA6F400D5,0xB0EC02D4,0xAAE400FF,0xA2EC013A,0x9CEC02D5,0x1B80734,0xD4CC02D3,0xB0F002D4,0xC8BC0192,0xB0D400D1,0xA6DC0190,0xC2A402D3,0xB0B400A2,0xA6B800D5,0x9CC802D4,0x61F80734,
+0xB07402D3,0xA6640190,0x9C5002D4,0x92000738,0xFF0C0252,0xF9200552,0xFB2405C3,0xFEF00006,0xD6EC0003,0xBEF00002,0xB0F40011,0xAEE80012,0xFEF8021A,0xFCDC0000,0xB2E400A9,0xA6B800D5,0x37FC0734,0x13C02D3,0xEB2800A2,0xBF2800A2,0xB12800A2,0xDD1800C9,0xC1180002,0xB3180015,0xB51400C9,0xAF100026,0xA71400C9,0x1D402D3,0xCCF000A2,0xB10C00A2,0xC0E400C9,0xB0F00001,
+0xA6FC00C8,0x6FFC02D3,0xB0B000A2,0xA6A400C8,0x9C0002D4,0x1D402D3,0xCCF000A2,0xB10C00A2,0xC0E400C9,0xB0F00001,0xA6FC00C8,0x6FFC02D3,0xB0B000A2,0xA6A400C8,0x9C0002D4,0x6FFC02D3,0xB0B000A2,0xA6A400C8,0x9C0002D4,0x9C0002D4,0xFD1C00F5,0xFF2C0209,0xF5380203,0xFCF40005,0xD6EC0002,0xBEF00001,0xB0FC0002,0xAEE00006,0xFF0800F4,0xFCDC0000,0xB4DC00A2,0xA6A400C8,
+0x49FC02D3,0x11402D3,0x11402D3,0x11402D3,0x11402D3,0xD30400CA,0xD30400CA,0xD30400CA,0xAB0000CA,0xAB0000CA,0x9D0000CA,0xCCF000A3,0xCCF000A3,0xCCF000A3,0xAEF00002,0xAEF00002,0x9EF40026,0xA0F000A3,0xA0F000A3,0x9AEC0015,0x92EC00A5,0x39802D3,0x39802D3,0x39802D3,0xB4D000C9,0xB4D000C9,0x9CE800C8,0xAEB800A2,0xAEB800A2,0x9CC80001,0x92D400A4,0x51FC02D3,
+0x51FC02D3,0x9C9000C8,0x927C00A4,0x8A0002D4,0xFF0400CB,0xFF0C01DB,0x11402D3,0xFEF00002,0xD2F00002,0xBCF00002,0xB6F00005,0xAAEC0002,0xFCF000B5,0xFCDC0000,0xB0E800A3,0x9CC80001,0x23FC02D3,0x12800A2,0x12800A2,0x12800A2,0x12800A2,0xBF180001,0xBF180001,0xBF180001,0xA5180001,0xA5180001,0x9D140001,0x1B800A2,0x1B800A2,0x1B800A2,0xAAF80001,0xAAF80001,
+0x9D040000,0x61F800A2,0x61F800A2,0x9CCC0000,0x920000A4,0x1B800A2,0x1B800A2,0x1B800A2,0xAAF80001,0xAAF80001,0x9D040000,0x61F800A2,0x61F800A2,0x9CCC0000,0x920000A4,0x61F800A2,0x61F800A2,0x9CCC0000,0x920000A4,0x920000A4,0xFF100020,0xF920003D,0x12800A2,0xFCF40001,0xCEF40000,0xBAF40000,0xB2F80000,0xAAEC0001,0xFEF8002D,0xFCDC0000,0x37FC00A2,0x9CCC0000,
+0x37FC00A2,0x14C00CA,0xD73C0001,0xBB380001,0xB1380001,0x1F000C8,0xC1180001,0xB1240001,0x7DF800C8,0xB0E80000,0xA60000C8,0x1F000C8,0xC1180001,0xB1240001,0x7DF800C8,0xB0E80000,0xA60000C8,0x7DF800C8,0xB0E80000,0xA60000C8,0xA60000C8,0x1F000C8,0xC1180001,0xB1240001,0x7DF800C8,0xB0E80000,0xA60000C8,0x7DF800C8,0xB0E80000,0xA60000C8,0xA60000C8,0x7DF800C8,
+0xB0E80000,0xA60000C8,0xA60000C8,0xA60000C8,0xFB2C0055,0x16400C8,0xFD480062,0xFEF40001,0xD6EC0001,0xC0E80000,0xB1000000,0xB0C80000,0xFF180048,0xFCDC0000,0xB3080001,0xA60000C8,0x5BFC00C8,0x10000CA,0x10000CA,0x10000CA,0x10000CA,0x10000CA,0x10000CA,0x10000CA,0x10000CA,0x10000CA,0x10000CA,0xB0F00001,0xB0F00001,0xB0F00001,0xB0F00001,0xB0F00001,
+0xB0F00001,0x94EC0001,0x94EC0001,0x94EC0001,0x8AEC0001,0x18000C8,0x18000C8,0x18000C8,0x18000C8,0x18000C8,0x18000C8,0x9ACC0001,0x9ACC0001,0x9ACC0001,0x8AD80001,0x45F800C8,0x45F800C8,0x45F800C8,0x8A9C0000,0x800000C8,0xF4F8004A,0x10000CA,0x10000CA,0xFCF00001,0xD4F00001,0xBEF00001,0xBEF00001,0xA6F00001,0xF8E80029,0xFADC0000,0x9EE80000,0x9ACC0001,
+0x13FC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table83[] = {
+0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x41FC0000,
+0x41FC0000,0x41FC0000,0x41FC0000,0x7E000000,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xF0C0000,0xF0C0000,0xF0C0000,0x1780000,0xFFC0000,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,
+0x1B40000,0x5FF80000,0x5FF80000,0x5FF80000,0x92000000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x5FF80000,0x5FF80000,0x5FF80000,0x92000000,0x5FF80000,0x5FF80000,0x5FF80000,0x92000000,0x92000000,0x5380000,0x1240001,0x1240001,0x3540000,0x1700000,0x1900000,0x1900000,0x3EC0000,0x3540000,0x1700000,0x35FC0000,0x5FF80000,
+0x35FC0000,0x1480001,0x1480001,0x1480001,0x1480001,0x3E80000,0x3E80000,0x3E80000,0x79FC0000,0x79FC0000,0xA4000000,0x3E80000,0x3E80000,0x3E80000,0x79FC0000,0x79FC0000,0xA4000000,0x79FC0000,0x79FC0000,0xA4000000,0xA4000000,0x3E80000,0x3E80000,0x3E80000,0x79FC0000,0x79FC0000,0xA4000000,0x79FC0000,0x79FC0000,0xA4000000,0xA4000000,0x79FC0000,
+0x79FC0000,0xA4000000,0xA4000000,0xA4000000,0x1800000,0x1600000,0x1480001,0x1C00000,0x23FC0000,0x57FC0000,0x69F80000,0x85F80000,0x39C0000,0x3E80000,0x57FC0000,0xA4000000,0x57FC0000,0x1700001,0x2BFC0000,0x97FC0000,0xB8000000,0x2BFC0000,0x97FC0000,0xB8000000,0x97FC0000,0xB8000000,0xB8000000,0x2BFC0000,0x97FC0000,0xB8000000,0x97FC0000,0xB8000000,
+0xB8000000,0x97FC0000,0xB8000000,0xB8000000,0xB8000000,0x2BFC0000,0x97FC0000,0xB8000000,0x97FC0000,0xB8000000,0xB8000000,0x97FC0000,0xB8000000,0xB8000000,0xB8000000,0x97FC0000,0xB8000000,0xB8000000,0xB8000000,0xB8000000,0x1D00000,0xD880000,0xD880000,0x53FC0000,0x89FC0000,0xA7FC0000,0xB8000000,0xB8000000,0x1F80000,0x6BFC0000,0xB5DC0000,0xB8000000,
+0x7DF80000,0x1380734,0xFF2402DC,0xCB2402D4,0xB92402D3,0xFB140192,0xD31400D7,0xBD18013B,0xC1140192,0xB71000D7,0xAF100192,0xF30002D4,0xD50000A3,0xBD0800FD,0xC4FC00CF,0xB9000002,0xAF0400D5,0xB8FC02D4,0xB2F400FF,0xAAFC013A,0xA4FC02D5,0x1D00734,0xDCDC02D3,0xB90002D4,0xD0CC0192,0xB8E400D1,0xAEEC0190,0xCAB402D3,0xB8C400A2,0xAEC800D5,0xA4D802D4,0x6DF80734,
+0xB88402D3,0xAE740190,0xA46002D4,0x9A000738,0xFF20028E,0xFF2C056A,0xF33405F4,0xFF04001E,0xDEFC0003,0xC7000002,0xB9040011,0xB6F80012,0xFF10025E,0xFEF00006,0xBAF400A9,0xAEC800D5,0x45FC0734,0x14C02D3,0xF33800A2,0xC73800A2,0xB93800A2,0xE52800C9,0xC9280002,0xBB280015,0xBD2400C9,0xB7200026,0xAF2400C9,0x1EC02D3,0xD50000A2,0xB91C00A2,0xC8F400C9,0xB9000001,
+0xAF0C00C8,0x7BFC02D3,0xB8C000A2,0xAEB400C8,0xA40002D4,0x1EC02D3,0xD50000A2,0xB91C00A2,0xC8F400C9,0xB9000001,0xAF0C00C8,0x7BFC02D3,0xB8C000A2,0xAEB400C8,0xA40002D4,0x7BFC02D3,0xB8C000A2,0xAEB400C8,0xA40002D4,0xA40002D4,0xFD30010A,0xFB44020B,0xFD480203,0xFF08000D,0xDEFC0002,0xC7000001,0xB90C0002,0xB6F00006,0xFF180119,0xFEF00005,0xBCEC00A2,0xAEB400C8,
+0x59FC02D3,0x12402D3,0x12402D3,0x12402D3,0x12402D3,0xDB1400CA,0xDB1400CA,0xDB1400CA,0xB31000CA,0xB31000CA,0xA51000CA,0xD50000A3,0xD50000A3,0xD50000A3,0xB7000002,0xB7000002,0xA7040026,0xA90000A3,0xA90000A3,0xA2FC0015,0x9AFC00A5,0x3B002D3,0x3B002D3,0x3B002D3,0xBCE000C9,0xBCE000C9,0xA4F800C8,0xB6C800A2,0xB6C800A2,0xA4D80001,0x9AE400A4,0x5DFC02D3,
+0x5DFC02D3,0xA4A000C8,0x9A8C00A4,0x920002D4,0xFF1000F1,0xF92001EE,0x12402D3,0xFF00000B,0xDB000002,0xC5000002,0xBF000005,0xB2FC0002,0xFF0000CB,0xFCF00002,0xB8F800A3,0xA4D80001,0x33FC02D3,0x13800A2,0x13800A2,0x13800A2,0x13800A2,0xC7280001,0xC7280001,0xC7280001,0xAD280001,0xAD280001,0xA5240001,0x1D000A2,0x1D000A2,0x1D000A2,0xB3080001,0xB3080001,
+0xA5140000,0x6DF800A2,0x6DF800A2,0xA4DC0000,0x9A0000A4,0x1D000A2,0x1D000A2,0x1D000A2,0xB3080001,0xB3080001,0xA5140000,0x6DF800A2,0x6DF800A2,0xA4DC0000,0x9A0000A4,0x6DF800A2,0x6DF800A2,0xA4DC0000,0x9A0000A4,0x9A0000A4,0xFF200029,0xFF2C0049,0x13800A2,0xFD040004,0xD7040000,0xC3040000,0xBB080000,0xB2FC0001,0xFD100032,0xFCF00001,0x45FC00A2,0xA4DC0000,
+0x45FC00A2,0x15C00CA,0xDF4C0001,0xC3480001,0xB9480001,0xDFC00C8,0xC9280001,0xB9340001,0x89F800C8,0xB8F80000,0xAE0000C8,0xDFC00C8,0xC9280001,0xB9340001,0x89F800C8,0xB8F80000,0xAE0000C8,0x89F800C8,0xB8F80000,0xAE0000C8,0xAE0000C8,0xDFC00C8,0xC9280001,0xB9340001,0x89F800C8,0xB8F80000,0xAE0000C8,0x89F800C8,0xB8F80000,0xAE0000C8,0xAE0000C8,0x89F800C8,
+0xB8F80000,0xAE0000C8,0xAE0000C8,0xAE0000C8,0xF7400062,0x37400C8,0xF5580071,0xFD100005,0xDEFC0001,0xC8F80000,0xB9100000,0xB8D80000,0xFF2C0055,0xF8FC0002,0xBB180001,0xAE0000C8,0x69FC00C8,0x11000CA,0x11000CA,0x11000CA,0x11000CA,0x11000CA,0x11000CA,0x11000CA,0x11000CA,0x11000CA,0x11000CA,0xB9000001,0xB9000001,0xB9000001,0xB9000001,0xB9000001,
+0xB9000001,0x9CFC0001,0x9CFC0001,0x9CFC0001,0x92FC0001,0x19800C8,0x19800C8,0x19800C8,0x19800C8,0x19800C8,0x19800C8,0xA2DC0001,0xA2DC0001,0xA2DC0001,0x92E80001,0x51F800C8,0x51F800C8,0x51F800C8,0x92AC0000,0x880000C8,0xFD08004A,0x11000CA,0x11000CA,0xFD000002,0xDD000001,0xC7000001,0xC7000001,0xAF000001,0xFEF4002D,0xFAF00001,0xA6F80000,0xA2DC0001,
+0x21FC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table84[] = {
+0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x4FF80000,
+0x4FF80000,0x4FF80000,0x4FF80000,0x86000001,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x9200000,0x9200000,0x9200000,0x1940000,0x1FFC0000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,
+0x1D00000,0x6DF80000,0x6DF80000,0x6DF80000,0x9A000001,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x6DF80000,0x6DF80000,0x6DF80000,0x9A000001,0x6DF80000,0x6DF80000,0x6DF80000,0x9A000001,0x9A000001,0x14C0000,0x1380000,0x1380000,0x7680000,0x1880000,0x1A80000,0x1A80000,0xDFC0000,0x7680000,0x1880000,0x45FC0000,0x6DF80000,
+0x45FC0000,0x15C0000,0x15C0000,0x15C0000,0x15C0000,0x9FC0000,0x9FC0000,0x9FC0000,0x87FC0000,0x87FC0000,0xAC000001,0x9FC0000,0x9FC0000,0x9FC0000,0x87FC0000,0x87FC0000,0xAC000001,0x87FC0000,0x87FC0000,0xAC000001,0xAC000001,0x9FC0000,0x9FC0000,0x9FC0000,0x87FC0000,0x87FC0000,0xAC000001,0x87FC0000,0x87FC0000,0xAC000001,0xAC000001,0x87FC0000,
+0x87FC0000,0xAC000001,0xAC000001,0xAC000001,0x1940000,0x1740000,0x15C0000,0x1D80000,0x39FC0000,0x67FC0000,0x77FC0000,0x91FC0000,0x1B40000,0x9FC0000,0x67FC0000,0xAC000001,0x67FC0000,0x1840000,0x47FC0000,0xA5F80000,0xC0000001,0x47FC0000,0xA5F80000,0xC0000001,0xA5F80000,0xC0000001,0xC0000001,0x47FC0000,0xA5F80000,0xC0000001,0xA5F80000,0xC0000001,
+0xC0000001,0xA5F80000,0xC0000001,0xC0000001,0xC0000001,0x47FC0000,0xA5F80000,0xC0000001,0xA5F80000,0xC0000001,0xC0000001,0xA5F80000,0xC0000001,0xC0000001,0xC0000001,0xA5F80000,0xC0000001,0xC0000001,0xC0000001,0xC0000001,0x5E40000,0x79C0000,0x79C0000,0x6BFC0000,0x99FC0000,0xB3F80000,0xC0000001,0xC0000001,0x1BFC0000,0x7DFC0000,0xBFD00000,0xC0000001,
+0x8DFC0000,0x1480738,0xFD3802F8,0xD53802D4,0xC13802D5,0xFF240198,0xDD2400D5,0xC32C013A,0xCB240190,0xBF2400D5,0xB7240192,0xFF1002D3,0xDF1000A2,0xC71C00FF,0xCF1000D1,0xC1100002,0xB71400D7,0xC11002D4,0xBD0800FD,0xB508013B,0xAF1002D3,0x3E80734,0xE6EC02D3,0xC11002D4,0xD8E00192,0xC2F800CF,0xB7000192,0xD2C802D3,0xC0D800A3,0xB6D800D7,0xAEE802D4,0x79FC0734,
+0xC09802D4,0xB68C0192,0xAE7002D3,0xA4000734,0xFF3402E1,0xFB440590,0xFD4805F4,0xFF18004A,0xE9100001,0xCF100002,0xC3140012,0xBF100011,0xFF2402C7,0xFF080025,0xC50400A9,0xB6D800D7,0x57FC0734,0x15C02D4,0xFB4C00A4,0xCF4C00A4,0xC14800A5,0xF13800C8,0xD3380001,0xC33C0015,0xC53800C8,0xBF340026,0xB73800CA,0xDFC02D3,0xDD1400A2,0xC13000A3,0xD10800C9,0xC1100002,
+0xB91C00CA,0x89F802D3,0xC0D800A3,0xB6C800CA,0xAE0002D3,0xDFC02D3,0xDD1400A2,0xC13000A3,0xD10800C9,0xC1100002,0xB91C00CA,0x89F802D3,0xC0D800A3,0xB6C800CA,0xAE0002D3,0x89F802D3,0xC0D800A3,0xB6C800CA,0xAE0002D3,0xAE0002D3,0xFF44013A,0xF558022A,0xF5580225,0xFF20002A,0xE9100001,0xCF100002,0xC31C0002,0xC1040005,0xFF34013A,0xFF0C0012,0xC6FC00A2,0xB6C800CA,
+0x69FC02D3,0x13802D4,0x13802D4,0x13802D4,0x13802D4,0xE72400C8,0xE72400C8,0xE72400C8,0xBB2400C8,0xBB2400C8,0xAD2400C9,0xDF1000A2,0xDF1000A2,0xDF1000A2,0xC1100001,0xC1100001,0xB1140026,0xB31000A2,0xB31000A2,0xAD0C0015,0xA51000A2,0x1CC02D3,0x1CC02D3,0x1CC02D3,0xC6F000C9,0xC6F000C9,0xAF0800C9,0xC0D800A2,0xC0D800A2,0xACEC0002,0xA4F400A2,0x6BF802D3,
+0x6BF802D3,0xACB400C9,0xA49800A2,0x9A0002D3,0xFD28010A,0xFF2C0209,0x13802D4,0xFF180019,0xE5100001,0xCF100001,0xC9140006,0xBB100002,0xFF1400E5,0xFF04000E,0xC30800A2,0xACEC0002,0x43FC02D3,0x14800A4,0x14800A4,0x14800A4,0x14800A4,0xD3380000,0xD3380000,0xD3380000,0xB7380000,0xB7380000,0xAD380001,0x3E800A2,0x3E800A2,0x3E800A2,0xBD180001,0xBD180001,
+0xAD280001,0x79FC00A2,0x79FC00A2,0xACF00001,0xA40000A2,0x3E800A2,0x3E800A2,0x3E800A2,0xBD180001,0xBD180001,0xAD280001,0x79FC00A2,0x79FC00A2,0xACF00001,0xA40000A2,0x79FC00A2,0x79FC00A2,0xACF00001,0xA40000A2,0xA40000A2,0xFB340034,0xFB440048,0x14800A4,0xFF1C0008,0xE3140000,0xCD140000,0xC31C0001,0xBD0C0000,0xF928003D,0xF90C0005,0x57FC00A2,0xACF00001,
+0x57FC00A2,0x17000C8,0xEB5C0000,0xCB5C0001,0xC15C0001,0x29FC00C8,0xD3380001,0xC1480001,0x97F800C8,0xC10C0001,0xB60000CA,0x29FC00C8,0xD3380001,0xC1480001,0x97F800C8,0xC10C0001,0xB60000CA,0x97F800C8,0xC10C0001,0xB60000CA,0xB60000CA,0x29FC00C8,0xD3380001,0xC1480001,0x97F800C8,0xC10C0001,0xB60000CA,0x97F800C8,0xC10C0001,0xB60000CA,0xB60000CA,0x97F800C8,
+0xC10C0001,0xB60000CA,0xB60000CA,0xB60000CA,0xFF500064,0x18800C8,0xFF6C0071,0xFD28000D,0xE90C0001,0xD10C0000,0xC1240001,0xC0F00001,0xF9480062,0xFF100005,0xC5280000,0xB60000CA,0x7BFC00C8,0x12400C8,0x12400C8,0x12400C8,0x12400C8,0x12400C8,0x12400C8,0x12400C8,0x12400C8,0x12400C8,0x12400C8,0xC5100000,0xC5100000,0xC5100000,0xC5100000,0xC5100000,
+0xC5100000,0xA5100001,0xA5100001,0xA5100001,0x9B100001,0x3B000C8,0x3B000C8,0x3B000C8,0x3B000C8,0x3B000C8,0x3B000C8,0xACEC0001,0xACEC0001,0xACEC0001,0x9AFC0001,0x5DFC00C8,0x5DFC00C8,0x5DFC00C8,0x9AC00001,0x900000CA,0xF71C0055,0x12400C8,0x12400C8,0xF9140008,0xE9100000,0xD3100000,0xD3100000,0xB9100000,0xFD0C0032,0xFF000004,0xAD0C0001,0xACEC0001,
+0x33FC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table85[] = {
+0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x5BF80000,
+0x5BF80000,0x5BF80000,0x5BF80000,0x8E000001,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1340000,0x1340000,0x1340000,0x1AC0000,0x2FFC0000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,
+0x1E80000,0x79F80000,0x79F80000,0x79F80000,0xA2000001,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x79F80000,0x79F80000,0x79F80000,0xA2000001,0x79F80000,0x79F80000,0x79F80000,0xA2000001,0xA2000001,0x75C0000,0x1480000,0x1480000,0x37C0000,0x19C0000,0x3BC0000,0x3BC0000,0x21FC0000,0x37C0000,0x19C0000,0x55FC0000,0x79F80000,
+0x55FC0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x23FC0000,0x23FC0000,0x23FC0000,0x93FC0000,0x93FC0000,0xB4000001,0x23FC0000,0x23FC0000,0x23FC0000,0x93FC0000,0x93FC0000,0xB4000001,0x93FC0000,0x93FC0000,0xB4000001,0xB4000001,0x23FC0000,0x23FC0000,0x23FC0000,0x93FC0000,0x93FC0000,0xB4000001,0x93FC0000,0x93FC0000,0xB4000001,0xB4000001,0x93FC0000,
+0x93FC0000,0xB4000001,0xB4000001,0xB4000001,0x1A80000,0x1840000,0x16C0000,0x1F00000,0x4DFC0000,0x77FC0000,0x85FC0000,0x9DF40000,0x1C80000,0x23FC0000,0x77FC0000,0xB4000001,0x77FC0000,0x1940000,0x5FFC0000,0xB1F80000,0xC8000001,0x5FFC0000,0xB1F80000,0xC8000001,0xB1F80000,0xC8000001,0xC8000001,0x5FFC0000,0xB1F80000,0xC8000001,0xB1F80000,0xC8000001,
+0xC8000001,0xB1F80000,0xC8000001,0xC8000001,0xC8000001,0x5FFC0000,0xB1F80000,0xC8000001,0xB1F80000,0xC8000001,0xC8000001,0xB1F80000,0xC8000001,0xC8000001,0xC8000001,0xB1F80000,0xC8000001,0xC8000001,0xC8000001,0xC8000001,0x5F80000,0xFAC0000,0xFAC0000,0x7DFC0000,0xA7F80000,0xBDF80000,0xC8000001,0xC8000001,0x39FC0000,0x8FFC0000,0xC7E00000,0xC8000001,
+0x9DF80000,0x1580738,0xFF480314,0xDD4802D4,0xC94802D5,0xFD3801B8,0xE53400D5,0xCB3C013A,0xD3340190,0xC73400D5,0xBF340192,0xFF2402D8,0xE72000A2,0xCF2C00FF,0xD72000D1,0xC9200002,0xBF2400D7,0xC92002D4,0xC51800FD,0xBD18013B,0xB72002D3,0x7FC0734,0xEEFC02D3,0xC92002D4,0xE0F00192,0xCB0800CF,0xBF100192,0xDAD802D3,0xC8E800A3,0xBEE800D7,0xB6F802D4,0x85FC0734,
+0xC8A802D4,0xBE9C0192,0xB68002D3,0xAC000734,0xFF44033E,0xFF4C05D0,0xF5580625,0xFF2C0086,0xF1200001,0xD7200002,0xCB240012,0xC7200011,0xFF3402FA,0xFF1C0054,0xCD1400A9,0xBEE800D7,0x65FC0734,0x16C02D4,0xFF5C00A5,0xD75C00A4,0xC95800A5,0xF94800C8,0xDB480001,0xCB4C0015,0xCD4800C8,0xC7440026,0xBF4800CA,0x25FC02D3,0xE52400A2,0xC94000A3,0xD91800C9,0xC9200002,
+0xC12C00CA,0x95F802D3,0xC8E800A3,0xBED800CA,0xB60002D3,0x25FC02D3,0xE52400A2,0xC94000A3,0xD91800C9,0xC9200002,0xC12C00CA,0x95F802D3,0xC8E800A3,0xBED800CA,0xB60002D3,0x95F802D3,0xC8E800A3,0xBED800CA,0xB60002D3,0xB60002D3,0xFF500155,0xFD68022A,0xFD680225,0xFF340042,0xF1200001,0xD7200002,0xCB2C0002,0xC9140005,0xFF44015B,0xFF240029,0xCF0C00A2,0xBED800CA,
+0x79FC02D3,0x14802D4,0x14802D4,0x14802D4,0x14802D4,0xEF3400C8,0xEF3400C8,0xEF3400C8,0xC33400C8,0xC33400C8,0xB53400C9,0xE72000A2,0xE72000A2,0xE72000A2,0xC9200001,0xC9200001,0xB9240026,0xBB2000A2,0xBB2000A2,0xB51C0015,0xAD2000A2,0x1E402D3,0x1E402D3,0x1E402D3,0xCF0000C9,0xCF0000C9,0xB71800C9,0xC8E800A2,0xC8E800A2,0xB4FC0002,0xAD0400A2,0x77F802D3,
+0x77F802D3,0xB4C400C9,0xACA800A2,0xA20002D3,0xFD380124,0xFB44020C,0x14802D4,0xFD280035,0xED200001,0xD7200001,0xD1240006,0xC3200002,0xFB2C0109,0xFF18001A,0xCB1800A2,0xB4FC0002,0x53FC02D3,0x15800A4,0x15800A4,0x15800A4,0x15800A4,0xDB480000,0xDB480000,0xDB480000,0xBF480000,0xBF480000,0xB5480001,0x7FC00A2,0x7FC00A2,0x7FC00A2,0xC5280001,0xC5280001,
+0xB5380001,0x85FC00A2,0x85FC00A2,0xB5000001,0xAC0000A2,0x7FC00A2,0x7FC00A2,0x7FC00A2,0xC5280001,0xC5280001,0xB5380001,0x85FC00A2,0x85FC00A2,0xB5000001,0xAC0000A2,0x85FC00A2,0x85FC00A2,0xB5000001,0xAC0000A2,0xAC0000A2,0xF748003D,0xF3540055,0x15800A4,0xFD30000D,0xEB240000,0xD5240000,0xCB2C0001,0xC51C0000,0xFF340041,0xFD200008,0x65FC00A2,0xB5000001,
+0x65FC00A2,0x18000C8,0xF36C0000,0xD36C0001,0xC96C0001,0x41FC00C8,0xDB480001,0xC9580001,0xA1FC00C8,0xC91C0001,0xBE0000CA,0x41FC00C8,0xDB480001,0xC9580001,0xA1FC00C8,0xC91C0001,0xBE0000CA,0xA1FC00C8,0xC91C0001,0xBE0000CA,0xBE0000CA,0x41FC00C8,0xDB480001,0xC9580001,0xA1FC00C8,0xC91C0001,0xBE0000CA,0xA1FC00C8,0xC91C0001,0xBE0000CA,0xBE0000CA,0xA1FC00C8,
+0xC91C0001,0xBE0000CA,0xBE0000CA,0xBE0000CA,0xF7680071,0x59800C8,0xF77C0080,0xFF400012,0xF11C0001,0xD91C0000,0xC9340001,0xC9000001,0xFD580064,0xFF2C000D,0xCD380000,0xBE0000CA,0x89FC00C8,0x13400C8,0x13400C8,0x13400C8,0x13400C8,0x13400C8,0x13400C8,0x13400C8,0x13400C8,0x13400C8,0x13400C8,0xCD200000,0xCD200000,0xCD200000,0xCD200000,0xCD200000,
+0xCD200000,0xAD200001,0xAD200001,0xAD200001,0xA3200001,0x1C800C8,0x1C800C8,0x1C800C8,0x1C800C8,0x1C800C8,0x1C800C8,0xB4FC0001,0xB4FC0001,0xB4FC0001,0xA30C0001,0x69FC00C8,0x69FC00C8,0x69FC00C8,0xA2D00001,0x980000CA,0xFF2C0055,0x13400C8,0x13400C8,0xFB24000D,0xF1200000,0xDB200000,0xDB200000,0xC1200000,0xFD1C003D,0xFF140005,0xB51C0001,0xB4FC0001,
+0x41FC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table86[] = {
+0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x67F80000,
+0x67F80000,0x67F80000,0x67F80000,0x96000001,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1440000,0x1440000,0x1440000,0x1C40000,0x3FF80000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,
+0x3FC0000,0x85F80000,0x85F80000,0x85F80000,0xAA000001,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x85F80000,0x85F80000,0x85F80000,0xAA000001,0x85F80000,0x85F80000,0x85F80000,0xAA000001,0xAA000001,0xF6C0000,0x1580000,0x1580000,0x1900000,0x1B00000,0x1D40000,0x1D40000,0x33FC0000,0x1900000,0x1B00000,0x63FC0000,0x85F80000,
+0x63FC0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x9FF80000,0x9FF80000,0xBC000001,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x9FF80000,0x9FF80000,0xBC000001,0x9FF80000,0x9FF80000,0xBC000001,0xBC000001,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x9FF80000,0x9FF80000,0xBC000001,0x9FF80000,0x9FF80000,0xBC000001,0xBC000001,0x9FF80000,
+0x9FF80000,0xBC000001,0xBC000001,0xBC000001,0x5B80000,0x3940000,0x17C0000,0xDFC0000,0x61FC0000,0x85FC0000,0x93F80000,0xA7F80000,0x1DC0000,0x3BFC0000,0x85FC0000,0xBC000001,0x85FC0000,0x1A40000,0x77FC0000,0xBDF80000,0xD0000001,0x77FC0000,0xBDF80000,0xD0000001,0xBDF80000,0xD0000001,0xD0000001,0x77FC0000,0xBDF80000,0xD0000001,0xBDF80000,0xD0000001,
+0xD0000001,0xBDF80000,0xD0000001,0xD0000001,0xD0000001,0x77FC0000,0xBDF80000,0xD0000001,0xBDF80000,0xD0000001,0xD0000001,0xBDF80000,0xD0000001,0xD0000001,0xD0000001,0xBDF80000,0xD0000001,0xD0000001,0xD0000001,0xD0000001,0x23FC0000,0x1C00000,0x1C00000,0x91FC0000,0xB5F80000,0xC7F80000,0xD0000001,0xD0000001,0x57FC0000,0xA1FC0000,0xCFF00000,0xD0000001,
+0xABFC0000,0x1680738,0xFF5C0339,0xE55802D4,0xD15802D5,0xFF4801E0,0xED4400D5,0xD34C013A,0xDB440190,0xCF4400D5,0xC7440192,0xFD3802F8,0xEF3000A2,0xD73C00FF,0xDF3000D1,0xD1300002,0xC73400D7,0xD13002D4,0xCD2800FD,0xC528013B,0xBF3002D3,0x1FFC0734,0xF70C02D3,0xD13002D4,0xE9000192,0xD31800CF,0xC7200192,0xE2E802D3,0xD0F800A3,0xC6F800D7,0xBF0802D4,0x91FC0734,
+0xD0B802D4,0xC6AC0192,0xBE9002D3,0xB4000734,0xFF580386,0xFB6405D2,0xFD680625,0xFF4000D3,0xF9300001,0xDF300002,0xD3340012,0xCF300011,0xFD4C036A,0xFF300099,0xD52400A9,0xC6F800D7,0x75FC0734,0x17C02D4,0xFF6C00B4,0xDF6C00A4,0xD16800A5,0xFD5800CA,0xE3580001,0xD35C0015,0xD55800C8,0xCF540026,0xC75800CA,0x3DFC02D3,0xED3400A2,0xD15000A3,0xE12800C9,0xD1300002,
+0xC93C00CA,0xA1F802D3,0xD0F800A3,0xC6E800CA,0xBE0002D3,0x3DFC02D3,0xED3400A2,0xD15000A3,0xE12800C9,0xD1300002,0xC93C00CA,0xA1F802D3,0xD0F800A3,0xC6E800CA,0xBE0002D3,0xA1F802D3,0xD0F800A3,0xC6E800CA,0xBE0002D3,0xBE0002D3,0xFF64017A,0xF5780248,0xF77C0244,0xFF48006E,0xF9300001,0xDF300002,0xD33C0002,0xD1240005,0xFF5C016D,0xFD3C004B,0xD71C00A2,0xC6E800CA,
+0x87FC02D3,0x15802D4,0x15802D4,0x15802D4,0x15802D4,0xF74400C8,0xF74400C8,0xF74400C8,0xCB4400C8,0xCB4400C8,0xBD4400C9,0xEF3000A2,0xEF3000A2,0xEF3000A2,0xD1300001,0xD1300001,0xC1340026,0xC33000A2,0xC33000A2,0xBD2C0015,0xB53000A2,0x1FC02D3,0x1FC02D3,0x1FC02D3,0xD71000C9,0xD71000C9,0xBF2800C9,0xD0F800A2,0xD0F800A2,0xBD0C0002,0xB51400A2,0x83F802D3,
+0x83F802D3,0xBCD400C9,0xB4B800A2,0xAA0002D3,0xFD48013D,0xF3540229,0x15802D4,0xFF3C0048,0xF5300001,0xDF300001,0xD9340006,0xCB300002,0xFF3C0120,0xFD2C0035,0xD32800A2,0xBD0C0002,0x61FC02D3,0x16800A4,0x16800A4,0x16800A4,0x16800A4,0xE3580000,0xE3580000,0xE3580000,0xC7580000,0xC7580000,0xBD580001,0x1FFC00A2,0x1FFC00A2,0x1FFC00A2,0xCD380001,0xCD380001,
+0xBD480001,0x91FC00A2,0x91FC00A2,0xBD100001,0xB40000A2,0x1FFC00A2,0x1FFC00A2,0x1FFC00A2,0xCD380001,0xCD380001,0xBD480001,0x91FC00A2,0x91FC00A2,0xBD100001,0xB40000A2,0x91FC00A2,0x91FC00A2,0xBD100001,0xB40000A2,0xB40000A2,0xFF58003D,0xFB640055,0x16800A4,0xFF440012,0xF3340000,0xDD340000,0xD33C0001,0xCD2C0000,0xFD4C0048,0xFF300011,0x75FC00A2,0xBD100001,
+0x75FC00A2,0x19000C8,0xFB7C0000,0xDB7C0001,0xD17C0001,0x59FC00C8,0xE3580001,0xD1680001,0xADFC00C8,0xD12C0001,0xC60000CA,0x59FC00C8,0xE3580001,0xD1680001,0xADFC00C8,0xD12C0001,0xC60000CA,0xADFC00C8,0xD12C0001,0xC60000CA,0xC60000CA,0x59FC00C8,0xE3580001,0xD1680001,0xADFC00C8,0xD12C0001,0xC60000CA,0xADFC00C8,0xD12C0001,0xC60000CA,0xC60000CA,0xADFC00C8,
+0xD12C0001,0xC60000CA,0xC60000CA,0xC60000CA,0xFF780071,0xDA800C8,0xFF8C0080,0xFF580020,0xF92C0001,0xE12C0000,0xD1440001,0xD1100001,0xFF700071,0xFD480019,0xD5480000,0xC60000CA,0x99FC00C8,0x14400C8,0x14400C8,0x14400C8,0x14400C8,0x14400C8,0x14400C8,0x14400C8,0x14400C8,0x14400C8,0x14400C8,0xD5300000,0xD5300000,0xD5300000,0xD5300000,0xD5300000,
+0xD5300000,0xB5300001,0xB5300001,0xB5300001,0xAB300001,0x1E000C8,0x1E000C8,0x1E000C8,0x1E000C8,0x1E000C8,0x1E000C8,0xBD0C0001,0xBD0C0001,0xBD0C0001,0xAB1C0001,0x75FC00C8,0x75FC00C8,0x75FC00C8,0xAAE00001,0xA00000CA,0xF73C0064,0x14400C8,0x14400C8,0xFB340014,0xF9300000,0xE3300000,0xE3300000,0xC9300000,0xF9300048,0xF928000D,0xBD2C0001,0xBD0C0001,
+0x51FC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table87[] = {
+0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x73F80000,
+0x73F80000,0x73F80000,0x73F80000,0x9E000001,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x3540000,0x3540000,0x3540000,0x1DC0000,0x4DFC0000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,
+0x1BFC0000,0x91F80000,0x91F80000,0x91F80000,0xB2000001,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x91F80000,0x91F80000,0x91F80000,0xB2000001,0x91F80000,0x91F80000,0x91F80000,0xB2000001,0xB2000001,0x1800000,0x1680000,0x1680000,0x7A00000,0x1C40000,0x3E80000,0x3E80000,0x47FC0000,0x7A00000,0x1C40000,0x73FC0000,0x91F80000,
+0x73FC0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x53FC0000,0x53FC0000,0x53FC0000,0xABF80000,0xABF80000,0xC4000001,0x53FC0000,0x53FC0000,0x53FC0000,0xABF80000,0xABF80000,0xC4000001,0xABF80000,0xABF80000,0xC4000001,0xC4000001,0x53FC0000,0x53FC0000,0x53FC0000,0xABF80000,0xABF80000,0xC4000001,0xABF80000,0xABF80000,0xC4000001,0xC4000001,0xABF80000,
+0xABF80000,0xC4000001,0xC4000001,0xC4000001,0x1CC0000,0xBA40000,0x18C0000,0x2BFC0000,0x73FC0000,0x95FC0000,0x9FFC0000,0xB3F40000,0x1F00000,0x53FC0000,0x95FC0000,0xC4000001,0x95FC0000,0x1B40000,0x8FFC0000,0xC9F80000,0xD8000001,0x8FFC0000,0xC9F80000,0xD8000001,0xC9F80000,0xD8000001,0xD8000001,0x8FFC0000,0xC9F80000,0xD8000001,0xC9F80000,0xD8000001,
+0xD8000001,0xC9F80000,0xD8000001,0xD8000001,0xD8000001,0x8FFC0000,0xC9F80000,0xD8000001,0xC9F80000,0xD8000001,0xD8000001,0xC9F80000,0xD8000001,0xD8000001,0xD8000001,0xC9F80000,0xD8000001,0xD8000001,0xD8000001,0xD8000001,0x4BFC0000,0x1D00000,0x1D00000,0xA5FC0000,0xC1FC0000,0xD1F80000,0xD8000001,0xD8000001,0x75FC0000,0xB1FC0000,0xD9C40000,0xD8000001,
+0xBBFC0000,0x1780738,0xFF6C0378,0xED6802D4,0xD96802D5,0xFF5C0212,0xF55400D5,0xDB5C013A,0xE3540190,0xD75400D5,0xCF540192,0xFF50031B,0xF74000A2,0xDF4C00FF,0xE74000D1,0xD9400002,0xCF4400D7,0xD94002D4,0xD53800FD,0xCD38013B,0xC74002D3,0x37FC0734,0xFF1C02D3,0xD94002D4,0xF1100192,0xDB2800CF,0xCF300192,0xEAF802D3,0xD90800A3,0xCF0800D7,0xC71802D4,0x9DFC0734,
+0xD8C802D4,0xCEBC0192,0xC6A002D3,0xBC000734,0xFF6403DE,0xF3740618,0xF5780658,0xFF54012A,0xFF400006,0xE7400002,0xDB440012,0xD7400011,0xFF5C03A6,0xFF4400EA,0xDD3400A9,0xCF0800D7,0x83FC0734,0x18C02D4,0xFF8000CD,0xE77C00A4,0xD97800A5,0xFF6C00D4,0xEB680001,0xDB6C0015,0xDD6800C8,0xD7640026,0xCF6800CA,0x55FC02D3,0xF54400A2,0xD96000A3,0xE93800C9,0xD9400002,
+0xD14C00CA,0xADF802D3,0xD90800A3,0xCEF800CA,0xC60002D3,0x55FC02D3,0xF54400A2,0xD96000A3,0xE93800C9,0xD9400002,0xD14C00CA,0xADF802D3,0xD90800A3,0xCEF800CA,0xC60002D3,0xADF802D3,0xD90800A3,0xCEF800CA,0xC60002D3,0xC60002D3,0xFF780191,0xFD880248,0xFF8C0244,0xFF5C0096,0xFD440005,0xE7400002,0xDB4C0002,0xD9340005,0xFF7001A5,0xFF540071,0xDF2C00A2,0xCEF800CA,
+0x97FC02D3,0x16802D4,0x16802D4,0x16802D4,0x16802D4,0xFF5400C8,0xFF5400C8,0xFF5400C8,0xD35400C8,0xD35400C8,0xC55400C9,0xF74000A2,0xF74000A2,0xF74000A2,0xD9400001,0xD9400001,0xC9440026,0xCB4000A2,0xCB4000A2,0xC53C0015,0xBD4000A2,0x19FC02D3,0x19FC02D3,0x19FC02D3,0xDF2000C9,0xDF2000C9,0xC73800C9,0xD90800A2,0xD90800A2,0xC51C0002,0xBD2400A2,0x8FF802D3,
+0x8FF802D3,0xC4E400C9,0xBCC800A2,0xB20002D3,0xFF58015D,0xFB640229,0x16802D4,0xFF4C0065,0xFD400001,0xE7400001,0xE1440006,0xD3400002,0xFF500139,0xFF3C0054,0xDB3800A2,0xC51C0002,0x71FC02D3,0x17800A4,0x17800A4,0x17800A4,0x17800A4,0xEB680000,0xEB680000,0xEB680000,0xCF680000,0xCF680000,0xC5680001,0x37FC00A2,0x37FC00A2,0x37FC00A2,0xD5480001,0xD5480001,
+0xC5580001,0x9DFC00A2,0x9DFC00A2,0xC5200001,0xBC0000A2,0x37FC00A2,0x37FC00A2,0x37FC00A2,0xD5480001,0xD5480001,0xC5580001,0x9DFC00A2,0x9DFC00A2,0xC5200001,0xBC0000A2,0x9DFC00A2,0x9DFC00A2,0xC5200001,0xBC0000A2,0xBC0000A2,0xFB6C0048,0xF3740064,0x17800A4,0xFD580019,0xFB440000,0xE5440000,0xDB4C0001,0xD53C0000,0xF5640055,0xFF480014,0x83FC00A2,0xC5200001,
+0x83FC00A2,0x1A000C8,0xFF8C0001,0xE38C0001,0xD98C0001,0x71FC00C8,0xEB680001,0xD9780001,0xB9FC00C8,0xD93C0001,0xCE0000CA,0x71FC00C8,0xEB680001,0xD9780001,0xB9FC00C8,0xD93C0001,0xCE0000CA,0xB9FC00C8,0xD93C0001,0xCE0000CA,0xCE0000CA,0x71FC00C8,0xEB680001,0xD9780001,0xB9FC00C8,0xD93C0001,0xCE0000CA,0xB9FC00C8,0xD93C0001,0xCE0000CA,0xCE0000CA,0xB9FC00C8,
+0xD93C0001,0xCE0000CA,0xCE0000CA,0xCE0000CA,0xFF8C0080,0x1BC00C8,0xF79C0091,0xFF6C002D,0xFB480005,0xE93C0000,0xD9540001,0xD9200001,0xF7880080,0xFF600029,0xDD580000,0xCE0000CA,0xA7FC00C8,0x15400C8,0x15400C8,0x15400C8,0x15400C8,0x15400C8,0x15400C8,0x15400C8,0x15400C8,0x15400C8,0x15400C8,0xDD400000,0xDD400000,0xDD400000,0xDD400000,0xDD400000,
+0xDD400000,0xBD400001,0xBD400001,0xBD400001,0xB3400001,0x1F800C8,0x1F800C8,0x1F800C8,0x1F800C8,0x1F800C8,0x1F800C8,0xC51C0001,0xC51C0001,0xC51C0001,0xB32C0001,0x81FC00C8,0x81FC00C8,0x81FC00C8,0xB2F00001,0xA80000CA,0xFF4C0064,0x15400C8,0x15400C8,0xFD480019,0xFD400001,0xEB400000,0xEB400000,0xD1400000,0xFF3C0050,0xFD380014,0xC53C0001,0xC51C0001,
+0x5FFC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table88[] = {
+0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x3F40000,0x3F40000,0x3F40000,0x3F40000,0x3F40000,0x3F40000,0x3F40000,0x3F40000,0x3F40000,0x3F40000,0x7FFC0000,
+0x7FFC0000,0x7FFC0000,0x7FFC0000,0xA8000000,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1500001,0x1680000,0x1680000,0x1680000,0x3F40000,0x5FF80000,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,
+0x37FC0000,0x9DFC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x9DFC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x9DFC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0xBC000000,0x1940000,0x1780001,0x1780001,0x1B80000,0x3D80000,0x9FC0000,0x9FC0000,0x5DFC0000,0x1B80000,0x3D80000,0x83FC0000,0x9DFC0000,
+0x83FC0000,0x19C0001,0x19C0001,0x19C0001,0x19C0001,0x6FFC0000,0x6FFC0000,0x6FFC0000,0xB9F80000,0xB9F80000,0xCE000000,0x6FFC0000,0x6FFC0000,0x6FFC0000,0xB9F80000,0xB9F80000,0xCE000000,0xB9F80000,0xB9F80000,0xCE000000,0xCE000000,0x6FFC0000,0x6FFC0000,0x6FFC0000,0xB9F80000,0xB9F80000,0xCE000000,0xB9F80000,0xB9F80000,0xCE000000,0xCE000000,0xB9F80000,
+0xB9F80000,0xCE000000,0xCE000000,0xCE000000,0x3E00000,0x5B80000,0x19C0001,0x4DFC0000,0x8BFC0000,0xA5FC0000,0xAFFC0000,0xBFF40000,0x15FC0000,0x6FFC0000,0xA5FC0000,0xCE000000,0xA5FC0000,0x1C40001,0xABFC0000,0xD7F80000,0xE2000000,0xABFC0000,0xD7F80000,0xE2000000,0xD7F80000,0xE2000000,0xE2000000,0xABFC0000,0xD7F80000,0xE2000000,0xD7F80000,0xE2000000,
+0xE2000000,0xD7F80000,0xE2000000,0xE2000000,0xE2000000,0xABFC0000,0xD7F80000,0xE2000000,0xD7F80000,0xE2000000,0xE2000000,0xD7F80000,0xE2000000,0xE2000000,0xE2000000,0xD7F80000,0xE2000000,0xE2000000,0xE2000000,0xE2000000,0x77FC0000,0x1E40000,0x1E40000,0xBBFC0000,0xD1FC0000,0xDDF40000,0xE2000000,0xE2000000,0x97FC0000,0xC5FC0000,0xE1F40000,0xE2000000,
+0xCBFC0000,0x18C0734,0xFF8003BF,0xF57802D4,0xE37802D3,0xFF740272,0xFD6800D7,0xE76C013B,0xEB680192,0xE16400D7,0xD9640192,0xFF680361,0xFF5400A3,0xE75C00FD,0xEF5000CF,0xE3540002,0xD95800D5,0xE35002D4,0xDD4800FF,0xD550013A,0xCF5002D5,0x53FC0734,0xFF3802E3,0xE35402D4,0xFB200192,0xE33800D1,0xD9400190,0xF50802D3,0xE31800A2,0xD91C00D5,0xCF2C02D4,0xABF80734,
+0xE2D802D3,0xD8C80190,0xCEB402D4,0xC4000738,0xFF780447,0xFD880614,0xFD88065C,0xFF6C01B7,0xFF58002E,0xF1540002,0xE3580011,0xE14C0012,0xFF700413,0xFF5C016A,0xE54800A9,0xD91C00D5,0x95FC0734,0x1A002D3,0xFF9000FB,0xF18C00A2,0xE38C00A2,0xFF8000F1,0xF37C0002,0xE57C0015,0xE77800C9,0xE1740026,0xD97800C9,0x71FC02D3,0xFF5400A2,0xE37000A2,0xF34800C9,0xE3540001,
+0xD96000C8,0xB9FC02D3,0xE31400A2,0xD90800C8,0xCE0002D4,0x71FC02D3,0xFF5400A2,0xE37000A2,0xF34800C9,0xE3540001,0xD96000C8,0xB9FC02D3,0xE31400A2,0xD90800C8,0xCE0002D4,0xB9FC02D3,0xE31400A2,0xD90800C8,0xCE0002D4,0xCE0002D4,0xFD9001C4,0xF79C0269,0xF79C0266,0xFF7800D1,0xFF5C001A,0xF1540001,0xE3600002,0xE1440006,0xFF8801C3,0xFF7000B5,0xE74000A2,0xD90800C8,
+0xA7FC02D3,0x17802D3,0x17802D3,0x17802D3,0x17802D3,0xFF6800CE,0xFF6800CE,0xFF6800CE,0xDD6400CA,0xDD6400CA,0xCF6400CA,0xFF5400A3,0xFF5400A3,0xFF5400A3,0xE1540002,0xE1540002,0xD1580026,0xD35400A3,0xD35400A3,0xCD500015,0xC55000A5,0x35FC02D3,0x35FC02D3,0x35FC02D3,0xE73400C9,0xE73400C9,0xCF4C00C8,0xE11C00A2,0xE11C00A2,0xCF2C0001,0xC53800A4,0x9DF402D3,
+0x9DF402D3,0xCEF400C8,0xC4E000A4,0xBC0002D4,0xFF680189,0xF374024B,0x17802D3,0xFF600099,0xFF540009,0xEF540002,0xE9540005,0xDD500002,0xFF64016D,0xFF540079,0xE34C00A3,0xCF2C0001,0x81FC02D3,0x18C00A2,0x18C00A2,0x18C00A2,0x18C00A2,0xF17C0001,0xF17C0001,0xF17C0001,0xD77C0001,0xD77C0001,0xCF780001,0x53FC00A2,0x53FC00A2,0x53FC00A2,0xDD5C0001,0xDD5C0001,
+0xCF680000,0xABF800A2,0xABF800A2,0xCF300000,0xC40000A4,0x53FC00A2,0x53FC00A2,0x53FC00A2,0xDD5C0001,0xDD5C0001,0xCF680000,0xABF800A2,0xABF800A2,0xCF300000,0xC40000A4,0xABF800A2,0xABF800A2,0xCF300000,0xC40000A4,0xC40000A4,0xF7800055,0xFD880062,0x18C00A2,0xFB700029,0xFF580001,0xED580000,0xE55C0000,0xDD500001,0xFD740055,0xFD640020,0x95FC00A2,0xCF300000,
+0x95FC00A2,0x1B000CA,0xFFA4000D,0xED9C0001,0xE39C0001,0x8DFC00C8,0xF37C0001,0xE3880001,0xC7FC00C8,0xE34C0000,0xD80000C8,0x8DFC00C8,0xF37C0001,0xE3880001,0xC7FC00C8,0xE34C0000,0xD80000C8,0xC7FC00C8,0xE34C0000,0xD80000C8,0xD80000C8,0x8DFC00C8,0xF37C0001,0xE3880001,0xC7FC00C8,0xE34C0000,0xD80000C8,0xC7FC00C8,0xE34C0000,0xD80000C8,0xD80000C8,0xC7FC00C8,
+0xE34C0000,0xD80000C8,0xD80000C8,0xD80000C8,0xF7A40091,0xFCC00C8,0xFFAC0095,0xFF8C0048,0xFF64000D,0xF34C0000,0xE3640000,0xE32C0000,0xFF980082,0xFD80003D,0xE56C0001,0xD80000C8,0xB9FC00C8,0x16400CA,0x16400CA,0x16400CA,0x16400CA,0x16400CA,0x16400CA,0x16400CA,0x16400CA,0x16400CA,0x16400CA,0xE3540001,0xE3540001,0xE3540001,0xE3540001,0xE3540001,
+0xE3540001,0xC7500001,0xC7500001,0xC7500001,0xBD500001,0x19FC00C8,0x19FC00C8,0x19FC00C8,0x19FC00C8,0x19FC00C8,0x19FC00C8,0xCD300001,0xCD300001,0xCD300001,0xBD3C0001,0x8FF800C8,0x8FF800C8,0x8FF800C8,0xBD000000,0xB20000C8,0xF9600071,0x16400CA,0x16400CA,0xFF580022,0xFD540005,0xF1540001,0xF1540001,0xD9540001,0xFD540055,0xFF500019,0xD14C0000,0xCD300001,
+0x71FC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table89[] = {
+0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x13FC0000,0x13FC0000,0x13FC0000,0x13FC0000,0x13FC0000,0x13FC0000,0x13FC0000,0x13FC0000,0x13FC0000,0x13FC0000,0x8BFC0000,
+0x8BFC0000,0x8BFC0000,0x8BFC0000,0xB0000000,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x1600001,0x5780000,0x5780000,0x5780000,0x13FC0000,0x6DFC0000,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,
+0x4FFC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xC4000000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xC4000000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xC4000000,0xC4000000,0x1A40000,0x1880001,0x1880001,0x5C80000,0x3EC0000,0x27FC0000,0x27FC0000,0x71FC0000,0x5C80000,0x3EC0000,0x93FC0000,0xA9FC0000,
+0x93FC0000,0x1AC0001,0x1AC0001,0x1AC0001,0x1AC0001,0x87FC0000,0x87FC0000,0x87FC0000,0xC5F80000,0xC5F80000,0xD6000000,0x87FC0000,0x87FC0000,0x87FC0000,0xC5F80000,0xC5F80000,0xD6000000,0xC5F80000,0xC5F80000,0xD6000000,0xD6000000,0x87FC0000,0x87FC0000,0x87FC0000,0xC5F80000,0xC5F80000,0xD6000000,0xC5F80000,0xC5F80000,0xD6000000,0xD6000000,0xC5F80000,
+0xC5F80000,0xD6000000,0xD6000000,0xD6000000,0x1F40000,0xDC80000,0x1AC0001,0x6BFC0000,0x9DFC0000,0xB5FC0000,0xBDF80000,0xC9F80000,0x3DFC0000,0x87FC0000,0xB5FC0000,0xD6000000,0xB5FC0000,0x1D40001,0xC3FC0000,0xE1FC0000,0xEA000000,0xC3FC0000,0xE1FC0000,0xEA000000,0xE1FC0000,0xEA000000,0xEA000000,0xC3FC0000,0xE1FC0000,0xEA000000,0xE1FC0000,0xEA000000,
+0xEA000000,0xE1FC0000,0xEA000000,0xEA000000,0xEA000000,0xC3FC0000,0xE1FC0000,0xEA000000,0xE1FC0000,0xEA000000,0xEA000000,0xE1FC0000,0xEA000000,0xEA000000,0xEA000000,0xE1FC0000,0xEA000000,0xEA000000,0xEA000000,0xEA000000,0x9FFC0000,0x3F40000,0x3F40000,0xCFFC0000,0xDFF80000,0xE7F40000,0xEA000000,0xEA000000,0xB5FC0000,0xD5FC0000,0xEBC80000,0xEA000000,
+0xDBFC0000,0x19C0734,0xFF90041C,0xFD8802D4,0xEB8802D3,0xFF8002E2,0xFF7800E7,0xEF7C013B,0xF3780192,0xE97400D7,0xE1740192,0xFF7403A9,0xFF6800C6,0xEF6C00FD,0xF76000CF,0xEB640002,0xE16800D5,0xEB6002D4,0xE55800FF,0xDD60013A,0xD76002D5,0x6BFC0734,0xFF580319,0xEB6402D4,0xFF38019A,0xEB4800D1,0xE1500190,0xFD1802D3,0xEB2800A2,0xE12C00D5,0xD73C02D4,0xB7F80734,
+0xEAE802D3,0xE0D80190,0xD6C402D4,0xCC000738,0xFF8C0494,0xF598065A,0xF79C068F,0xFF800236,0xFF6C0086,0xF9640002,0xEB680011,0xE95C0012,0xFF800481,0xFF7401F7,0xED5800A9,0xE12C00D5,0xA3FC0734,0x1B002D3,0xFFA40126,0xF99C00A2,0xEB9C00A2,0xFF980119,0xFB8C0002,0xED8C0015,0xEF8800C9,0xE9840026,0xE18800C9,0x89FC02D3,0xFF7000AD,0xEB8000A2,0xFB5800C9,0xEB640001,
+0xE17000C8,0xC5FC02D3,0xEB2400A2,0xE11800C8,0xD60002D4,0x89FC02D3,0xFF7000AD,0xEB8000A2,0xFB5800C9,0xEB640001,0xE17000C8,0xC5FC02D3,0xEB2400A2,0xE11800C8,0xD60002D4,0xC5FC02D3,0xEB2400A2,0xE11800C8,0xD60002D4,0xD60002D4,0xFFA001E5,0xFFAC0269,0xFFAC0266,0xFF94010A,0xFF7C0049,0xF9640001,0xEB700002,0xE9540006,0xFF9801E6,0xFF8400E2,0xEF5000A2,0xE11800C8,
+0xB7FC02D3,0x18802D3,0x18802D3,0x18802D3,0x18802D3,0xFF7800E3,0xFF7800E3,0xFF7800E3,0xE57400CA,0xE57400CA,0xD77400CA,0xFF6800AD,0xFF6800AD,0xFF6800AD,0xE9640002,0xE9640002,0xD9680026,0xDB6400A3,0xDB6400A3,0xD5600015,0xCD6000A5,0x4DFC02D3,0x4DFC02D3,0x4DFC02D3,0xEF4400C9,0xEF4400C9,0xD75C00C8,0xE92C00A2,0xE92C00A2,0xD73C0001,0xCD4800A4,0xA7FC02D3,
+0xA7FC02D3,0xD70400C8,0xCCF000A4,0xC40002D4,0xFD8001A6,0xFB84024B,0x18802D3,0xFF7000CA,0xFF6C0022,0xF7640002,0xF1640005,0xE5600002,0xFF78018A,0xFF6800A8,0xEB5C00A3,0xD73C0001,0x91FC02D3,0x19C00A2,0x19C00A2,0x19C00A2,0x19C00A2,0xF98C0001,0xF98C0001,0xF98C0001,0xDF8C0001,0xDF8C0001,0xD7880001,0x6BFC00A2,0x6BFC00A2,0x6BFC00A2,0xE56C0001,0xE56C0001,
+0xD7780000,0xB7F800A2,0xB7F800A2,0xD7400000,0xCC0000A4,0x6BFC00A2,0x6BFC00A2,0x6BFC00A2,0xE56C0001,0xE56C0001,0xD7780000,0xB7F800A2,0xB7F800A2,0xD7400000,0xCC0000A4,0xB7F800A2,0xB7F800A2,0xD7400000,0xCC0000A4,0xCC0000A4,0xFF900055,0xF5980071,0x19C00A2,0xFD840032,0xFF700005,0xF5680000,0xED6C0000,0xE5600001,0xFD880062,0xFF74002D,0xA3FC00A2,0xD7400000,
+0xA3FC00A2,0x1C000CA,0xFFB40022,0xF5AC0001,0xEBAC0001,0xA5FC00C8,0xFB8C0001,0xEB980001,0xD3FC00C8,0xEB5C0000,0xE00000C8,0xA5FC00C8,0xFB8C0001,0xEB980001,0xD3FC00C8,0xEB5C0000,0xE00000C8,0xD3FC00C8,0xEB5C0000,0xE00000C8,0xE00000C8,0xA5FC00C8,0xFB8C0001,0xEB980001,0xD3FC00C8,0xEB5C0000,0xE00000C8,0xD3FC00C8,0xEB5C0000,0xE00000C8,0xE00000C8,0xD3FC00C8,
+0xEB5C0000,0xE00000C8,0xE00000C8,0xE00000C8,0xFFB40091,0x1E000C8,0xF9C000A2,0xFFA00059,0xFF7C0025,0xFB5C0000,0xEB740000,0xEB3C0000,0xFFAC0095,0xFF940050,0xED7C0001,0xE00000C8,0xC7FC00C8,0x17400CA,0x17400CA,0x17400CA,0x17400CA,0x17400CA,0x17400CA,0x17400CA,0x17400CA,0x17400CA,0x17400CA,0xEB640001,0xEB640001,0xEB640001,0xEB640001,0xEB640001,
+0xEB640001,0xCF600001,0xCF600001,0xCF600001,0xC5600001,0x31FC00C8,0x31FC00C8,0x31FC00C8,0x31FC00C8,0x31FC00C8,0x31FC00C8,0xD5400001,0xD5400001,0xD5400001,0xC54C0001,0x9BF800C8,0x9BF800C8,0x9BF800C8,0xC5100000,0xBA0000C8,0xFF6C007D,0x17400CA,0x17400CA,0xFF68002D,0xFF64000A,0xF9640001,0xF9640001,0xE1640001,0xF9680062,0xFD600029,0xD95C0000,0xD5400001,
+0x7FFC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table90[] = {
+0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x97FC0000,
+0x97FC0000,0x97FC0000,0x97FC0000,0xB8000000,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0xD880000,0xD880000,0xD880000,0x2BFC0000,0x7DF80000,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,
+0x69FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xCC000000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xCC000000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xCC000000,0xCC000000,0x3B40000,0x1980001,0x1980001,0x1DC0000,0xBFC0000,0x45FC0000,0x45FC0000,0x85FC0000,0x1DC0000,0xBFC0000,0xA1FC0000,0xB5FC0000,
+0xA1FC0000,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x9FFC0000,0x9FFC0000,0x9FFC0000,0xD1F80000,0xD1F80000,0xDE000000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0xD1F80000,0xD1F80000,0xDE000000,0xD1F80000,0xD1F80000,0xDE000000,0xDE000000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0xD1F80000,0xD1F80000,0xDE000000,0xD1F80000,0xD1F80000,0xDE000000,0xDE000000,0xD1F80000,
+0xD1F80000,0xDE000000,0xDE000000,0xDE000000,0x1FFC0000,0x1DC0000,0x1BC0001,0x89FC0000,0xB1FC0000,0xC3FC0000,0xC9FC0000,0xD5F40000,0x63FC0000,0x9FFC0000,0xC3FC0000,0xDE000000,0xC3FC0000,0x1E40001,0xDBFC0000,0xEDFC0000,0xF2000000,0xDBFC0000,0xEDFC0000,0xF2000000,0xEDFC0000,0xF2000000,0xF2000000,0xDBFC0000,0xEDFC0000,0xF2000000,0xEDFC0000,0xF2000000,
+0xF2000000,0xEDFC0000,0xF2000000,0xF2000000,0xF2000000,0xDBFC0000,0xEDFC0000,0xF2000000,0xEDFC0000,0xF2000000,0xF2000000,0xEDFC0000,0xF2000000,0xF2000000,0xF2000000,0xEDFC0000,0xF2000000,0xF2000000,0xF2000000,0xF2000000,0xC7FC0000,0x47FC0000,0x47FC0000,0xE3FC0000,0xEBFC0000,0xF1F40000,0xF2000000,0xF2000000,0xD3FC0000,0xE7FC0000,0xF3D80000,0xF2000000,
+0xE9FC0000,0x1AC0734,0xFFA40477,0xFF9C02EB,0xF39802D3,0xFF980352,0xFF8C012F,0xF78C013B,0xFB880192,0xF18400D7,0xE9840192,0xFF8C0401,0xFF7C011E,0xF77C00FD,0xFF7000CF,0xF3740002,0xE97800D5,0xF37002D4,0xED6800FF,0xE570013A,0xDF7002D5,0x83FC0734,0xFF700361,0xF37402D4,0xFF5801E2,0xF35800D1,0xE9600190,0xFF3802DD,0xF33800A2,0xE93C00D5,0xDF4C02D4,0xC3F80734,
+0xF2F802D3,0xE8E80190,0xDED402D4,0xD4000738,0xFFA004E6,0xFDA8065A,0xFFAC068F,0xFF9402CB,0xFF84010B,0xFF740006,0xF3780011,0xF16C0012,0xFF9804CA,0xFF84028B,0xF56800A9,0xE93C00D5,0xB3FC0734,0x1C002D3,0xFFB4016B,0xFFAC00A3,0xF3AC00A2,0xFFA8015B,0xFF9C0012,0xF59C0015,0xF79800C9,0xF1940026,0xE99800C9,0xA3FC02D3,0xFF8800D5,0xF39000A2,0xFF7000CE,0xF3740001,
+0xE98000C8,0xD1FC02D3,0xF33400A2,0xE92800C8,0xDE0002D4,0xA3FC02D3,0xFF8800D5,0xF39000A2,0xFF7000CE,0xF3740001,0xE98000C8,0xD1FC02D3,0xF33400A2,0xE92800C8,0xDE0002D4,0xD1FC02D3,0xF33400A2,0xE92800C8,0xDE0002D4,0xDE0002D4,0xFFB40202,0xF7BC028B,0xF7BC028B,0xFFA4015B,0xFF900089,0xFF740005,0xF3800002,0xF1640006,0xFDB00222,0xFF980136,0xF76000A2,0xE92800C8,
+0xC5FC02D3,0x19802D3,0x19802D3,0x19802D3,0x19802D3,0xFF8C00FE,0xFF8C00FE,0xFF8C00FE,0xED8400CA,0xED8400CA,0xDF8400CA,0xFF7800CB,0xFF7800CB,0xFF7800CB,0xF1740002,0xF1740002,0xE1780026,0xE37400A3,0xE37400A3,0xDD700015,0xD57000A5,0x65FC02D3,0x65FC02D3,0x65FC02D3,0xF75400C9,0xF75400C9,0xDF6C00C8,0xF13C00A2,0xF13C00A2,0xDF4C0001,0xD55800A4,0xB3FC02D3,
+0xB3FC02D3,0xDF1400C8,0xD50000A4,0xCC0002D4,0xFF9001C6,0xF598026A,0x19802D3,0xFF8800F3,0xFF80004A,0xFF740002,0xF9740005,0xED700002,0xFD8801C3,0xFF8000DD,0xF36C00A3,0xDF4C0001,0x9FFC02D3,0x1AC00A2,0x1AC00A2,0x1AC00A2,0x1AC00A2,0xFF9C0002,0xFF9C0002,0xFF9C0002,0xE79C0001,0xE79C0001,0xDF980001,0x83FC00A2,0x83FC00A2,0x83FC00A2,0xED7C0001,0xED7C0001,
+0xDF880000,0xC3F800A2,0xC3F800A2,0xDF500000,0xD40000A4,0x83FC00A2,0x83FC00A2,0x83FC00A2,0xED7C0001,0xED7C0001,0xDF880000,0xC3F800A2,0xC3F800A2,0xDF500000,0xD40000A4,0xC3F800A2,0xC3F800A2,0xDF500000,0xD40000A4,0xD40000A4,0xFFA00064,0xFDA80071,0x1AC00A2,0xFF98003D,0xFF840011,0xFD780000,0xF57C0000,0xED700001,0xF5A00071,0xFB90003D,0xB3FC00A2,0xDF500000,
+0xB3FC00A2,0x1D000CA,0xFFC4003A,0xFDBC0001,0xF3BC0001,0xBDFC00C8,0xFFA00009,0xF3A80001,0xDFF800C8,0xF36C0000,0xE80000C8,0xBDFC00C8,0xFFA00009,0xF3A80001,0xDFF800C8,0xF36C0000,0xE80000C8,0xDFF800C8,0xF36C0000,0xE80000C8,0xE80000C8,0xBDFC00C8,0xFFA00009,0xF3A80001,0xDFF800C8,0xF36C0000,0xE80000C8,0xDFF800C8,0xF36C0000,0xE80000C8,0xE80000C8,0xDFF800C8,
+0xF36C0000,0xE80000C8,0xE80000C8,0xE80000C8,0xFBC800A4,0x1F000C8,0xFFCC00AA,0xFDBC0071,0xFFA4003D,0xFF740004,0xF3840000,0xF34C0000,0xF9C800A2,0xFBB80071,0xF58C0001,0xE80000C8,0xD7FC00C8,0x18400CA,0x18400CA,0x18400CA,0x18400CA,0x18400CA,0x18400CA,0x18400CA,0x18400CA,0x18400CA,0x18400CA,0xF3740001,0xF3740001,0xF3740001,0xF3740001,0xF3740001,
+0xF3740001,0xD7700001,0xD7700001,0xD7700001,0xCD700001,0x49FC00C8,0x49FC00C8,0x49FC00C8,0x49FC00C8,0x49FC00C8,0x49FC00C8,0xDD500001,0xDD500001,0xDD500001,0xCD5C0001,0xA7F800C8,0xA7F800C8,0xA7F800C8,0xCD200000,0xC20000C8,0xF9800082,0x18400CA,0x18400CA,0xFB7C003D,0xFF780012,0xFD740002,0xFD740002,0xE9740001,0xFF74006A,0xFD740032,0xE16C0000,0xDD500001,
+0x8FFC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table91[] = {
+0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0xA3FC0000,
+0xA3FC0000,0xA3FC0000,0xA3FC0000,0xC0000000,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x19C0000,0x19C0000,0x19C0000,0x43FC0000,0x8BFC0000,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,
+0x81FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xD4000000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xD4000000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xD4000000,0xD4000000,0xBC40000,0x1A80001,0x1A80001,0x1F00000,0x33FC0000,0x63FC0000,0x63FC0000,0x99FC0000,0x1F00000,0x33FC0000,0xB1FC0000,0xC1FC0000,
+0xB1FC0000,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xDDF40000,0xDDF40000,0xE6000000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xDDF40000,0xDDF40000,0xE6000000,0xDDF40000,0xDDF40000,0xE6000000,0xE6000000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xDDF40000,0xDDF40000,0xE6000000,0xDDF40000,0xDDF40000,0xE6000000,0xE6000000,0xDDF40000,
+0xDDF40000,0xE6000000,0xE6000000,0xE6000000,0x57FC0000,0x1EC0000,0x1CC0001,0xA7FC0000,0xC5FC0000,0xD3FC0000,0xD7FC0000,0xDFF80000,0x8BFC0000,0xB7FC0000,0xD3FC0000,0xE6000000,0xD3FC0000,0x1F40001,0xF5FC0000,0xF9FC0000,0xFA000000,0xF5FC0000,0xF9FC0000,0xFA000000,0xF9FC0000,0xFA000000,0xFA000000,0xF5FC0000,0xF9FC0000,0xFA000000,0xF9FC0000,0xFA000000,
+0xFA000000,0xF9FC0000,0xFA000000,0xFA000000,0xFA000000,0xF5FC0000,0xF9FC0000,0xFA000000,0xF9FC0000,0xFA000000,0xFA000000,0xF9FC0000,0xFA000000,0xFA000000,0xFA000000,0xF9FC0000,0xFA000000,0xFA000000,0xFA000000,0xFA000000,0xEDFC0000,0xC7FC0000,0xC7FC0000,0xF7FC0000,0xF9FC0000,0xFBF40000,0xFA000000,0xFA000000,0xF1FC0000,0xF7FC0000,0xFBE80000,0xFA000000,
+0xF9FC0000,0x1BC0734,0xFFB004DF,0xFFAC032C,0xFBA802D3,0xFFA403F2,0xFFA001B3,0xFF9C013B,0xFF9401A4,0xF99400D7,0xF1940192,0xFFA40479,0xFF9401AE,0xFF8C00FD,0xFF880107,0xFB840002,0xF18800D5,0xFB8002D4,0xF57800FF,0xED80013A,0xE78002D5,0x9BFC0734,0xFF8803C9,0xFB8402D4,0xFF700252,0xFB6800D1,0xF1700190,0xFF58031F,0xFB4800A2,0xF14C00D5,0xE75C02D4,0xCFF80734,
+0xFB0802D3,0xF0F80190,0xE6E402D4,0xDC000738,0xFFB40553,0xF5B806A4,0xF7BC06C4,0xFFA4038C,0xFF9801BF,0xFF88005A,0xFB880011,0xF97C0012,0xFDB00553,0xFF98033A,0xFD7800A9,0xF14C00D5,0xC1FC0734,0x1D002D3,0xFFC401A3,0xFFC000CE,0xFBBC00A2,0xFFBC0199,0xFFB4005A,0xFDAC0015,0xFFA800C9,0xF9A40026,0xF1A800C9,0xBBFC02D3,0xFFA0011D,0xFBA000A2,0xFF8800FE,0xFB840001,
+0xF19000C8,0xDDFC02D3,0xFB4400A2,0xF13800C8,0xE60002D4,0xBBFC02D3,0xFFA0011D,0xFBA000A2,0xFF8800FE,0xFB840001,0xF19000C8,0xDDFC02D3,0xFB4400A2,0xF13800C8,0xE60002D4,0xDDFC02D3,0xFB4400A2,0xF13800C8,0xE60002D4,0xE60002D4,0xFBC80244,0xFFCC028B,0xFFCC028B,0xFFC001A6,0xFFA800ED,0xFF900039,0xFB900002,0xF9740006,0xFFC40243,0xFFB0019E,0xFF7000A2,0xF13800C8,
+0xD5FC02D3,0x1A802D3,0x1A802D3,0x1A802D3,0x1A802D3,0xFF9C012B,0xFF9C012B,0xFF9C012B,0xF59400CA,0xF59400CA,0xE79400CA,0xFF8C00ED,0xFF8C00ED,0xFF8C00ED,0xF9840002,0xF9840002,0xE9880026,0xEB8400A3,0xEB8400A3,0xE5800015,0xDD8000A5,0x7DFC02D3,0x7DFC02D3,0x7DFC02D3,0xFF6400C9,0xFF6400C9,0xE77C00C8,0xF94C00A2,0xF94C00A2,0xE75C0001,0xDD6800A4,0xBFFC02D3,
+0xBFFC02D3,0xE72400C8,0xDD1000A4,0xD40002D4,0xFFA001E5,0xFDA8026A,0x1A802D3,0xFF980126,0xFF940082,0xFF88001A,0xFF88000A,0xF5800002,0xFD9C01E1,0xFF900111,0xFB7C00A3,0xE75C0001,0xAFFC02D3,0x1BC00A2,0x1BC00A2,0x1BC00A2,0x1BC00A2,0xFFB0000D,0xFFB0000D,0xFFB0000D,0xEFAC0001,0xEFAC0001,0xE7A80001,0x9BFC00A2,0x9BFC00A2,0x9BFC00A2,0xF58C0001,0xF58C0001,
+0xE7980000,0xCFF800A2,0xCFF800A2,0xE7600000,0xDC0000A4,0x9BFC00A2,0x9BFC00A2,0x9BFC00A2,0xF58C0001,0xF58C0001,0xE7980000,0xCFF800A2,0xCFF800A2,0xE7600000,0xDC0000A4,0xCFF800A2,0xCFF800A2,0xE7600000,0xDC0000A4,0xDC0000A4,0xFBB40071,0xF5B80082,0x1BC00A2,0xFBAC0055,0xFF9C0022,0xFF900008,0xFD8C0000,0xF5800001,0xFDB00071,0xFFA40048,0xC1FC00A2,0xE7600000,
+0xC1FC00A2,0x1E000CA,0xFFDC0062,0xFFCC0011,0xFBCC0001,0xD5FC00C8,0xFFC0002D,0xFBB80001,0xEBF800C8,0xFB7C0000,0xF00000C8,0xD5FC00C8,0xFFC0002D,0xFBB80001,0xEBF800C8,0xFB7C0000,0xF00000C8,0xEBF800C8,0xFB7C0000,0xF00000C8,0xF00000C8,0xD5FC00C8,0xFFC0002D,0xFBB80001,0xEBF800C8,0xFB7C0000,0xF00000C8,0xEBF800C8,0xFB7C0000,0xF00000C8,0xF00000C8,0xEBF800C8,
+0xFB7C0000,0xF00000C8,0xF00000C8,0xF00000C8,0xF3E000B5,0x27FC00C8,0xF9E000B5,0xFDD40091,0xFFBC0061,0xFFA40022,0xFB940000,0xFB5C0000,0xFDD800A4,0xFFCC0082,0xFD9C0001,0xF00000C8,0xE5FC00C8,0x19400CA,0x19400CA,0x19400CA,0x19400CA,0x19400CA,0x19400CA,0x19400CA,0x19400CA,0x19400CA,0x19400CA,0xFB840001,0xFB840001,0xFB840001,0xFB840001,0xFB840001,
+0xFB840001,0xDF800001,0xDF800001,0xDF800001,0xD5800001,0x63FC00C8,0x63FC00C8,0x63FC00C8,0x63FC00C8,0x63FC00C8,0x63FC00C8,0xE5600001,0xE5600001,0xE5600001,0xD56C0001,0xB3F800C8,0xB3F800C8,0xB3F800C8,0xD5300000,0xCA0000C8,0xF3940091,0x19400CA,0x19400CA,0xFD8C004A,0xFD880022,0xFD84000A,0xFD84000A,0xF1840001,0xFD8C0071,0xF9880048,0xE97C0000,0xE5600001,
+0x9FF800C8,};
+static const uint32_t g_etc1_to_bc7_m6_table92[] = {
+0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x5FFC0000,0x5FFC0000,0x5FFC0000,0x5FFC0000,0x5FFC0000,0x5FFC0000,0x5FFC0000,0x5FFC0000,0x5FFC0000,0x5FFC0000,0xB1F80000,
+0xB1F80000,0xB1F80000,0xB1F80000,0xC8000001,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0x1940000,0xFAC0000,0xFAC0000,0xFAC0000,0x5FFC0000,0x9DF80000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,
+0x9BFC0000,0xCFF80000,0xCFF80000,0xCFF80000,0xDC000001,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0xCFF80000,0xCFF80000,0xCFF80000,0xDC000001,0xCFF80000,0xCFF80000,0xCFF80000,0xDC000001,0xDC000001,0x5D80000,0x1BC0000,0x1BC0000,0x17FC0000,0x5FFC0000,0x85FC0000,0x85FC0000,0xAFFC0000,0x17FC0000,0x5FFC0000,0xC1FC0000,0xCFF80000,
+0xC1FC0000,0x1E00000,0x1E00000,0x1E00000,0x1E00000,0xD3FC0000,0xD3FC0000,0xD3FC0000,0xE9FC0000,0xE9FC0000,0xEE000001,0xD3FC0000,0xD3FC0000,0xD3FC0000,0xE9FC0000,0xE9FC0000,0xEE000001,0xE9FC0000,0xE9FC0000,0xEE000001,0xEE000001,0xD3FC0000,0xD3FC0000,0xD3FC0000,0xE9FC0000,0xE9FC0000,0xEE000001,0xE9FC0000,0xE9FC0000,0xEE000001,0xEE000001,0xE9FC0000,
+0xE9FC0000,0xEE000001,0xEE000001,0xEE000001,0x97FC0000,0x17FC0000,0x1E00000,0xC9FC0000,0xDBFC0000,0xE3FC0000,0xE7F80000,0xEBF80000,0xB7FC0000,0xD3FC0000,0xE3FC0000,0xEE000001,0xE3FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1CC0625,0xFFC4047D,0xFFC0034C,0xFFBC02D4,0xFFBC03A5,0xFFB40204,0xFFB00161,0xFFAC017D,0xFFA800C9,0xF7A80139,0xFFB00412,0xFFAC01FB,0xFFA4012A,0xFFA00106,0xFF980009,0xF9980082,0xFF940225,0xFB9000C8,0xF59000C1,0xEF940222,0xB5FC0625,0xFFA003BC,0xFF9802D3,0xFF94024F,0xFF8400E9,0xF784013B,0xFF7C02BE,0xFF6400A5,0xF7640076,0xEF700222,0xDBF80625,
+0xFF2C02D3,0xF7180139,0xEEFC0222,0xE4000627,0xFFC404D9,0xFDC8059D,0xFFCC05C5,0xFFB40375,0xFFA801FF,0xFFA400B5,0xFF9C0032,0xFF900004,0xFFBC04B6,0xFFB00336,0xFF9000B4,0xF7640076,0xD1FC0625,0x1DC0225,0xFFD40178,0xFFCC00E4,0xFFCC00A4,0xFFD00145,0xFFC8007E,0xFFC40020,0xFFC00081,0xFDB8000C,0xF7BC0071,0xCFFC0222,0xFFC00118,0xFFB800A2,0xFFAC00C6,0xFF9C0001,
+0xF7A40071,0xE7FC0222,0xFF6C00A2,0xF7540071,0xEE000222,0xCFFC0222,0xFFC00118,0xFFB800A2,0xFFAC00C6,0xFF9C0001,0xF7A40071,0xE7FC0222,0xFF6C00A2,0xF7540071,0xEE000222,0xE7FC0222,0xFF6C00A2,0xF7540071,0xEE000222,0xEE000222,0xFFD801C3,0xF7DC0201,0xF7DC0204,0xFDD00171,0xFFC000F2,0xFFAC0059,0xFFA80005,0xFF900000,0xFDD801C5,0xFFC80146,0xFF9800AB,0xF7540071,
+0xE1FC0222,0x1BC02D4,0x1BC02D4,0x1BC02D4,0x1BC02D4,0xFFB00161,0xFFB00161,0xFFB00161,0xFDA800C8,0xFDA800C8,0xEFA800C9,0xFFA4012A,0xFFA4012A,0xFFA4012A,0xFF980009,0xFF980009,0xF3980026,0xF59400A2,0xF59400A2,0xEF900015,0xE79400A2,0x99FC02D3,0x99FC02D3,0x99FC02D3,0xFF8400E9,0xFF8400E9,0xF18C00C9,0xFF6400A5,0xFF6400A5,0xEF700002,0xE77800A2,0xCDFC02D3,
+0xCDFC02D3,0xEF3800C9,0xE71C00A2,0xDC0002D3,0xFBB40225,0xF5B8028C,0x1BC02D4,0xFFAC0175,0xFFA400D9,0xFF9C0059,0xFF9C0032,0xFD940002,0xFDB00201,0xFFA40163,0xFF9000AB,0xEF700002,0xBFFC02D3,0x1CC00A4,0x1CC00A4,0x1CC00A4,0x1CC00A4,0xFFC40020,0xFFC40020,0xFFC40020,0xF9BC0000,0xF9BC0000,0xEFBC0001,0xB7FC00A2,0xB7FC00A2,0xB7FC00A2,0xFF9C0001,0xFF9C0001,
+0xEFAC0001,0xDDF400A2,0xDDF400A2,0xEF740001,0xE60000A2,0xB7FC00A2,0xB7FC00A2,0xB7FC00A2,0xFF9C0001,0xFF9C0001,0xEFAC0001,0xDDF400A2,0xDDF400A2,0xEF740001,0xE60000A2,0xDDF400A2,0xDDF400A2,0xEF740001,0xE60000A2,0xE60000A2,0xFDC80080,0xFFCC0080,0x1CC00A4,0xFDC00064,0xFDBC003D,0xFFAC0019,0xFFA80005,0xFF900000,0xFFC40080,0xFBC00062,0xD3FC00A2,0xEF740001,
+0xD3FC00A2,0x1F00071,0xFFE80041,0xFFE40014,0xFFE00000,0xE9FC0071,0xFFD80028,0xFFD00000,0xF3FC0071,0xFFA00000,0xF6000071,0xE9FC0071,0xFFD80028,0xFFD00000,0xF3FC0071,0xFFA00000,0xF6000071,0xF3FC0071,0xFFA00000,0xF6000071,0xF6000071,0xE9FC0071,0xFFD80028,0xFFD00000,0xF3FC0071,0xFFA00000,0xF6000071,0xF3FC0071,0xFFA00000,0xF6000071,0xF6000071,0xF3FC0071,
+0xFFA00000,0xF6000071,0xF6000071,0xF6000071,0xFFEC0062,0x87FC0071,0xFFEC0064,0xFDE80055,0xFDE40048,0xFFC8001D,0xFFB40000,0xFF8C0000,0xFDEC0062,0xFFE40055,0xFFBC0004,0xF6000071,0xF1FC0071,0x1A800C8,0x1A800C8,0x1A800C8,0x1A800C8,0x1A800C8,0x1A800C8,0x1A800C8,0x1A800C8,0x1A800C8,0x1A800C8,0xFF980005,0xFF980005,0xFF980005,0xFF980005,0xFF980005,
+0xFF980005,0xE7940001,0xE7940001,0xE7940001,0xDD940001,0x7DFC00C8,0x7DFC00C8,0x7DFC00C8,0x7DFC00C8,0x7DFC00C8,0x7DFC00C8,0xEF700001,0xEF700001,0xEF700001,0xDD800001,0xBFFC00C8,0xBFFC00C8,0xBFFC00C8,0xDD440001,0xD20000CA,0xFBA40091,0x1A800C8,0x1A800C8,0xFFA00055,0xFD9C0034,0xFF980014,0xFF980014,0xFB940000,0xFD9C0082,0xFD9C0055,0xEF900001,0xEF700001,
+0xAFFC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table93[] = {
+0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x77FC0000,0x77FC0000,0x77FC0000,0x77FC0000,0x77FC0000,0x77FC0000,0x77FC0000,0x77FC0000,0x77FC0000,0x77FC0000,0xBDF80000,
+0xBDF80000,0xBDF80000,0xBDF80000,0xD0000001,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1C00000,0x1C00000,0x1C00000,0x77FC0000,0xABFC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,
+0xB5FC0000,0xDBF80000,0xDBF80000,0xDBF80000,0xE4000001,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xDBF80000,0xDBF80000,0xDBF80000,0xE4000001,0xDBF80000,0xDBF80000,0xDBF80000,0xE4000001,0xE4000001,0xDE80000,0x1CC0000,0x1CC0000,0x51FC0000,0x87FC0000,0xA3FC0000,0xA3FC0000,0xC3FC0000,0x51FC0000,0x87FC0000,0xD1FC0000,0xDBF80000,
+0xD1FC0000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0xEBFC0000,0xEBFC0000,0xEBFC0000,0xF5FC0000,0xF5FC0000,0xF6000001,0xEBFC0000,0xEBFC0000,0xEBFC0000,0xF5FC0000,0xF5FC0000,0xF6000001,0xF5FC0000,0xF5FC0000,0xF6000001,0xF6000001,0xEBFC0000,0xEBFC0000,0xEBFC0000,0xF5FC0000,0xF5FC0000,0xF6000001,0xF5FC0000,0xF5FC0000,0xF6000001,0xF6000001,0xF5FC0000,
+0xF5FC0000,0xF6000001,0xF6000001,0xF6000001,0xD1FC0000,0x97FC0000,0x1F00000,0xE7FC0000,0xEFFC0000,0xF3FC0000,0xF5F80000,0xF7F40000,0xDFFC0000,0xEBFC0000,0xF3FC0000,0xF6000001,0xF3FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1D804C1,0xFFD003C9,0xFFCC0314,0xFFCC02D4,0xFFC80305,0xFFC40204,0xFFC401A0,0xFFB80151,0xFFB800D8,0xFBB800E1,0xFFC4031D,0xFFBC01F3,0xFFBC017A,0xFFAC00E6,0xFFAC003D,0xFBA80036,0xFFAC016D,0xFFA400A4,0xF9A40049,0xF5A4014E,0xC7FC04C1,0xFFB80354,0xFFB002D3,0xFFAC01F7,0xFFA0011A,0xFB9800E3,0xFF940216,0xFF8800CD,0xFB78001A,0xF580014F,0xE3FC04C1,
+0xFF6002D3,0xFB3800E1,0xF514014E,0xEA0004C3,0xFFD003DA,0xF5D80485,0xF5D8049C,0xFFC402E5,0xFFBC01E3,0xFFB800E7,0xFFB40084,0xFFA80015,0xFFD003C4,0xFFC402B9,0xFFA800E4,0xFB78001A,0xDDF804C1,0x1E8014D,0xFDE40105,0xFFE000BD,0xFFDC00A4,0xFFDC00C9,0xFFD8006C,0xFFD40041,0xFFCC0041,0xFFCC0001,0xFBCC0019,0xDFFC014D,0xFFD800D8,0xFFCC00A4,0xFFC0007D,0xFFB80011,
+0xFBB80019,0xEFFC014D,0xFF9C00A2,0xFB740019,0xF400014E,0xDFFC014D,0xFFD800D8,0xFFCC00A4,0xFFC0007D,0xFFB80011,0xFBB80019,0xEFFC014D,0xFF9C00A2,0xFB740019,0xF400014E,0xEFFC014D,0xFF9C00A2,0xFB740019,0xF400014E,0xF400014E,0xFFE4011D,0xFDE80131,0xFDE80138,0xFFDC00E1,0xFFD400AA,0xFFC80056,0xFFBC0025,0xFFB0000D,0xFFE00122,0xFFDC00DA,0xFFB800A6,0xFB740019,
+0xEBFC014D,0x1CC02D4,0x1CC02D4,0x1CC02D4,0x1CC02D4,0xFFC401A0,0xFFC401A0,0xFFC401A0,0xFFB800D8,0xFFB800D8,0xF7B800C9,0xFFBC017A,0xFFBC017A,0xFFBC017A,0xFFAC003D,0xFFAC003D,0xFBA80026,0xFDA400A2,0xFDA400A2,0xF7A00015,0xEFA400A2,0xB1FC02D3,0xB1FC02D3,0xB1FC02D3,0xFFA0011A,0xFFA0011A,0xF99C00C9,0xFF8800CD,0xFF8800CD,0xF7800002,0xEF8800A2,0xD9FC02D3,
+0xD9FC02D3,0xF74800C9,0xEF2C00A2,0xE40002D3,0xFDC80244,0xFDC8028C,0x1CC02D4,0xFFBC01BA,0xFFB40131,0xFFB400A8,0xFFB40084,0xFFA80015,0xFFBC0236,0xFFBC01A6,0xFFA800DB,0xF7800002,0xCFFC02D3,0x1DC00A4,0x1DC00A4,0x1DC00A4,0x1DC00A4,0xFFD40041,0xFFD40041,0xFFD40041,0xFFCC0001,0xFFCC0001,0xF7CC0001,0xCFFC00A2,0xCFFC00A2,0xCFFC00A2,0xFFB80011,0xFFB80011,
+0xF7BC0001,0xE7FC00A2,0xE7FC00A2,0xF7840001,0xEE0000A2,0xCFFC00A2,0xCFFC00A2,0xCFFC00A2,0xFFB80011,0xFFB80011,0xF7BC0001,0xE7FC00A2,0xE7FC00A2,0xF7840001,0xEE0000A2,0xE7FC00A2,0xE7FC00A2,0xF7840001,0xEE0000A2,0xEE0000A2,0xFFD80082,0xF7DC0091,0x1DC00A4,0xFDD80071,0xFDD00055,0xFFC8003D,0xFFBC0025,0xFFB0000D,0xF1DC0091,0xFBD40071,0xE1FC00A2,0xF7840001,
+0xE1FC00A2,0x1F80019,0xFFF4000D,0xFFF00004,0xFFF00000,0xF5FC0019,0xFFF00008,0xFFE80000,0xF9FC0019,0xFFD40000,0xFA000019,0xF5FC0019,0xFFF00008,0xFFE80000,0xF9FC0019,0xFFD40000,0xFA000019,0xF9FC0019,0xFFD40000,0xFA000019,0xFA000019,0xF5FC0019,0xFFF00008,0xFFE80000,0xF9FC0019,0xFFD40000,0xFA000019,0xF9FC0019,0xFFD40000,0xFA000019,0xFA000019,0xF9FC0019,
+0xFFD40000,0xFA000019,0xFA000019,0xFA000019,0xFDF40014,0xC7FC0019,0xF5F80019,0xFFF40012,0xFFE80010,0xFFE80008,0xFFDC0000,0xFFC80000,0xF1FC0019,0xFFF00014,0xFFE00001,0xFA000019,0xF9FC0019,0x1B800C8,0x1B800C8,0x1B800C8,0x1B800C8,0x1B800C8,0x1B800C8,0x1B800C8,0x1B800C8,0x1B800C8,0x1B800C8,0xFFA80014,0xFFA80014,0xFFA80014,0xFFA80014,0xFFA80014,
+0xFFA80014,0xEFA40001,0xEFA40001,0xEFA40001,0xE5A40001,0x95FC00C8,0x95FC00C8,0x95FC00C8,0x95FC00C8,0x95FC00C8,0x95FC00C8,0xF7800001,0xF7800001,0xF7800001,0xE5900001,0xCBFC00C8,0xCBFC00C8,0xCBFC00C8,0xE5540001,0xDA0000CA,0xF3B400A4,0x1B800C8,0x1B800C8,0xFBB40071,0xFDB00048,0xFFAC0029,0xFFAC0029,0xFFA40004,0xF9B00091,0xFBAC0064,0xF7A00001,0xF7800001,
+0xBFF800C8,};
+static const uint32_t g_etc1_to_bc7_m6_table94[] = {
+0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0xC9F80000,
+0xC9F80000,0xC9F80000,0xC9F80000,0xD8000001,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1D00000,0x1D00000,0x1D00000,0x8FFC0000,0xBBFC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,
+0xCDFC0000,0xE7F80000,0xE7F80000,0xE7F80000,0xEC000001,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xE7F80000,0xE7F80000,0xE7F80000,0xEC000001,0xE7F80000,0xE7F80000,0xE7F80000,0xEC000001,0xEC000001,0x1FC0000,0x1DC0000,0x1DC0000,0x89FC0000,0xADFC0000,0xC1FC0000,0xC1FC0000,0xD7FC0000,0x89FC0000,0xADFC0000,0xDFFC0000,0xE7F80000,
+0xDFFC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1E403A2,0xFFDC032A,0xFFD802D5,0xFFD802B1,0xFFDC0282,0xFFD40205,0xFFD001C9,0xFFCC0150,0xFFCC0110,0xFFC800C8,0xFFD0028A,0xFFD001E9,0xFFC801A9,0xFFC000FC,0xFFC00098,0xFFBC0029,0xFFB8011A,0xFFB800A1,0xFFB00014,0xF9B400C1,0xD5FC03A2,0xFFCC02F1,0xFFC802AE,0xFFB801CC,0xFFB80153,0xFFAC00CA,0xFFAC01B3,0xFFA000FE,0xFF900001,0xF99400C2,0xEBF803A2,
+0xFF9002AE,0xFF5800C8,0xF93400C1,0xF00003A2,0xFDE00326,0xF9E00370,0xFBE40389,0xFFD40272,0xFFD001DA,0xFFC8012F,0xFFC400E0,0xFFB80065,0xFFD8030F,0xFFD00253,0xFFBC010D,0xFF900001,0xE5FC03A2,0x1F400C2,0xFDF000AE,0xFFF00099,0xFFEC0091,0xFFE80086,0xFFE80065,0xFFE80055,0xFFE40030,0xFFE0001D,0xFFDC0000,0xEFFC00C1,0xFFE400A1,0xFFE40091,0xFFD80058,0xFFD80034,
+0xFFCC0000,0xF7F800C1,0xFFC80091,0xFF940000,0xF80000C1,0xEFFC00C1,0xFFE400A1,0xFFE40091,0xFFD80058,0xFFD80034,0xFFCC0000,0xF7F800C1,0xFFC80091,0xFF940000,0xF80000C1,0xF7F800C1,0xFFC80091,0xFF940000,0xF80000C1,0xF80000C1,0xFDF000AC,0xFFEC00C0,0xF3F400C2,0xFFEC009B,0xFFE80081,0xFFE0005E,0xFFE00048,0xFFD0002D,0xFBF000AC,0xFFE80095,0xFFD80092,0xFF940000,
+0xF5FC00C1,0x1D802B1,0x1D802B1,0x1D802B1,0x1D802B1,0xFFD001C9,0xFFD001C9,0xFFD001C9,0xFFCC0110,0xFFCC0110,0xFFC800C8,0xFFC801A9,0xFFC801A9,0xFFC801A9,0xFFC00098,0xFFC00098,0xFFBC0029,0xFFB800A1,0xFFB800A1,0xFDB00011,0xF7B40091,0xC9FC02AE,0xC9FC02AE,0xC9FC02AE,0xFFB80153,0xFFB80153,0xFFAC00CA,0xFFA000FE,0xFFA000FE,0xFF900001,0xF7980091,0xE5F802AE,
+0xE5F802AE,0xFF5800C8,0xF73C0091,0xEC0002AE,0xFFD80245,0xF5D8028C,0x1D802B1,0xFFD401E2,0xFFCC017A,0xFFC40114,0xFFC400E0,0xFFB80065,0xFFD0022E,0xFFD001C3,0xFFBC0109,0xFF900001,0xDFF802AE,0x1EC0091,0x1EC0091,0x1EC0091,0x1EC0091,0xFFE80055,0xFFE80055,0xFFE80055,0xFFE0001D,0xFFE0001D,0xFFDC0000,0xE5FC0091,0xE5FC0091,0xE5FC0091,0xFFD80034,0xFFD80034,
+0xFFCC0000,0xF3F80091,0xF3F80091,0xFF940000,0xF6000091,0xE5FC0091,0xE5FC0091,0xE5FC0091,0xFFD80034,0xFFD80034,0xFFCC0000,0xF3F80091,0xF3F80091,0xFF940000,0xF6000091,0xF3F80091,0xF3F80091,0xFF940000,0xF6000091,0xF6000091,0xFBEC0080,0xFFEC0080,0x1EC0091,0xF9EC0080,0xFFE0006A,0xFFE00055,0xFFE00048,0xFFD0002D,0xF9EC0080,0xFFE80071,0xEFFC0091,0xFF940000,
+0xEFFC0091,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1C800C8,0x1C800C8,0x1C800C8,0x1C800C8,0x1C800C8,0x1C800C8,0x1C800C8,0x1C800C8,0x1C800C8,0x1C800C8,0xFFBC0029,0xFFBC0029,0xFFBC0029,0xFFBC0029,0xFFBC0029,
+0xFFBC0029,0xF7B40001,0xF7B40001,0xF7B40001,0xEDB40001,0xAFFC00C8,0xAFFC00C8,0xAFFC00C8,0xAFFC00C8,0xAFFC00C8,0xAFFC00C8,0xFF900001,0xFF900001,0xFF900001,0xEDA00001,0xD7FC00C8,0xD7FC00C8,0xD7FC00C8,0xED640001,0xE20000CA,0xFBC400A4,0x1C800C8,0x1C800C8,0xFBC40080,0xFFBC0061,0xFFBC0041,0xFFBC0041,0xFFB80014,0xFFBC009D,0xFFBC0075,0xFFB00001,0xFF900001,
+0xCDFC00C8,};
+static const uint32_t g_etc1_to_bc7_m6_table95[] = {
+0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xD5F80000,
+0xD5F80000,0xD5F80000,0xD5F80000,0xE0000001,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x9E00000,0x9E00000,0x9E00000,0xA9FC0000,0xC9FC0000,0x1EC0000,0x1EC0000,0x1EC0000,0x1EC0000,0x1EC0000,0x1EC0000,0x1EC0000,0x1EC0000,0x1EC0000,0x1EC0000,0xE5FC0000,0xE5FC0000,0xE5FC0000,0xE5FC0000,0xE5FC0000,
+0xE5FC0000,0xF3F80000,0xF3F80000,0xF3F80000,0xF4000001,0xE5FC0000,0xE5FC0000,0xE5FC0000,0xE5FC0000,0xE5FC0000,0xE5FC0000,0xF3F80000,0xF3F80000,0xF3F80000,0xF4000001,0xF3F80000,0xF3F80000,0xF3F80000,0xF4000001,0xF4000001,0x77FC0000,0x1EC0000,0x1EC0000,0xC3FC0000,0xD5FC0000,0xDFFC0000,0xDFFC0000,0xEBFC0000,0xC3FC0000,0xD5FC0000,0xEFFC0000,0xF3F80000,
+0xEFFC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1EC0232,0xFFE801F2,0xFFE401C9,0xFFE401B9,0xFFE801AA,0xFFE00165,0xFFDC0149,0xFFD80110,0xFFD800EC,0xFFD800C8,0xFFDC0186,0xFFDC0131,0xFFDC010D,0xFFD400BB,0xFFD00088,0xFFD00048,0xFFCC0091,0xFFCC0051,0xFFC40001,0xFBC40039,0xE3FC0232,0xFFD801DD,0xFFD801B9,0xFFCC0150,0xFFCC0110,0xFFC400C8,0xFFC00109,0xFFB80096,0xFFAC0011,0xFBAC0039,0xF1F80232,
+0xFFAC01B9,0xFF8800C8,0xFB5C0039,0xF4000232,0xFFE401E6,0xFDE80210,0xFFEC0221,0xFFE0019E,0xFFDC013E,0xFFD400D8,0xFFD000B5,0xFFD00061,0xFFE401ED,0xFFDC018C,0xFFD000AF,0xFFAC0011,0xEDFC0232,0x1F80036,0xFFF80031,0xFFF4002D,0xFFF40029,0xFFF40022,0xFFF4001D,0xFFF40019,0xFFF0000C,0xFFF00008,0xFFEC0000,0xF7FC0036,0xFFF0002D,0xFFF00029,0xFFF00018,0xFFE40010,
+0xFFE40000,0xFBFC0036,0xFFE00029,0xFFC80000,0xFA000039,0xF7FC0036,0xFFF0002D,0xFFF00029,0xFFF00018,0xFFE40010,0xFFE40000,0xFBFC0036,0xFFE00029,0xFFC80000,0xFA000039,0xFBFC0036,0xFFE00029,0xFFC80000,0xFA000039,0xFA000039,0xFFF40030,0xF5F80036,0xF5F80036,0xFFF8002C,0xFFF00022,0xFFEC0018,0xFFE80011,0xFFE4000A,0xFFF8002C,0xFFF4002B,0xFFE8002A,0xFFC80000,
+0xFBFC0036,0x1E401B9,0x1E401B9,0x1E401B9,0x1E401B9,0xFFDC0149,0xFFDC0149,0xFFDC0149,0xFFD800EC,0xFFD800EC,0xFFD800C8,0xFFDC010D,0xFFDC010D,0xFFDC010D,0xFFD00088,0xFFD00088,0xFFD00048,0xFFCC0051,0xFFCC0051,0xFFC40001,0xFBC40029,0xD9FC01B9,0xD9FC01B9,0xD9FC01B9,0xFFCC0110,0xFFCC0110,0xFFC400C8,0xFFB80096,0xFFB80096,0xFFAC0011,0xFBAC0029,0xEDF801B9,
+0xEDF801B9,0xFF8800C8,0xFB5C0029,0xF20001BA,0xFDE40182,0xFBE401A0,0x1E401B9,0xFFDC0144,0xFFD80101,0xFFD400C8,0xFFD000B5,0xFFD00061,0xFDE00181,0xFFDC013B,0xFFD000AE,0xFFAC0011,0xE7FC01B9,0x1F40029,0x1F40029,0x1F40029,0x1F40029,0xFFF40019,0xFFF40019,0xFFF40019,0xFFF00008,0xFFF00008,0xFFEC0000,0xF1FC0029,0xF1FC0029,0xF1FC0029,0xFFE40010,0xFFE40010,
+0xFFE40000,0xF9F80029,0xF9F80029,0xFFC80000,0xFA000029,0xF1FC0029,0xF1FC0029,0xF1FC0029,0xFFE40010,0xFFE40010,0xFFE40000,0xF9F80029,0xF9F80029,0xFFC80000,0xFA000029,0xF9F80029,0xF9F80029,0xFFC80000,0xFA000029,0xFA000029,0xFFF40020,0xF3F40029,0x1F40029,0xFDF40020,0xFFF00019,0xFFEC0014,0xFFE80011,0xFFE4000A,0xFDF40020,0xFDF00022,0xF7FC0029,0xFFC80000,
+0xF7FC0029,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1D800C8,0x1D800C8,0x1D800C8,0x1D800C8,0x1D800C8,0x1D800C8,0x1D800C8,0x1D800C8,0x1D800C8,0x1D800C8,0xFFD00048,0xFFD00048,0xFFD00048,0xFFD00048,0xFFD00048,
+0xFFD00048,0xFFC40001,0xFFC40001,0xFFC40001,0xF5C40001,0xC7FC00C8,0xC7FC00C8,0xC7FC00C8,0xC7FC00C8,0xC7FC00C8,0xC7FC00C8,0xFFAC0011,0xFFAC0011,0xFFAC0011,0xF5B00001,0xE3FC00C8,0xE3FC00C8,0xE3FC00C8,0xF5740001,0xEA0000CA,0xF5D800B5,0x1D800C8,0x1D800C8,0xFDD40091,0xFFD00075,0xFFCC0061,0xFFCC0061,0xFFCC0034,0xFDD400A2,0xFFD00082,0xFFC4001D,0xFFAC0011,
+0xDDF800C8,};
+static const uint32_t g_etc1_to_bc7_m6_table96[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x180001,0x180001,0x180001,0x180001,0x2240000,0x2240000,0x2240000,0x4C0000,0x4C0000,0xC000000,0x2240000,0x2240000,0x2240000,0x4C0000,0x4C0000,0xC000000,0x4C0000,0x4C0000,0xC000000,0xC000000,0x2240000,0x2240000,0x2240000,0x4C0000,0x4C0000,0xC000000,0x4C0000,0x4C0000,0xC000000,0xC000000,0x4C0000,
+0x4C0000,0xC000000,0xC000000,0xC000000,0x41C0000,0x1C0000,0x180001,0x240000,0x2C0000,0x340000,0x3C0000,0x5C0000,0x200000,0x2240000,0x340000,0xC000000,0x340000,0x540000,0x7C0000,0xFC0000,0x28000001,0x7C0000,0xFC0000,0x28000001,0xFC0000,0x28000001,0x28000001,0x7C0000,0xFC0000,0x28000001,0xFC0000,0x28000001,
+0x28000001,0xFC0000,0x28000001,0x28000001,0x28000001,0x7C0000,0xFC0000,0x28000001,0xFC0000,0x28000001,0x28000001,0xFC0000,0x28000001,0x28000001,0x28000001,0xFC0000,0x28000001,0x28000001,0x28000001,0x28000001,0x680000,0x4580000,0x4580000,0x8C0000,0xCC0000,0x1940000,0x28000001,0x28000001,0x2700000,0x9C0000,0x1DCC0000,0x28000001,
+0xB00000,0x1C0499,0x76080071,0x3C080071,0x28080072,0x500001A5,0x3A000028,0x28000001,0x280001A5,0x200000A2,0x1A0001A5,0x3600039D,0x2E000149,0x240000AA,0x22000236,0x2000011B,0x180001F1,0x1A00039D,0x1C000236,0x160002AE,0x1200039E,0x280499,0x28000216,0x22000127,0x220002AF,0x1E000181,0x18000231,0x180003E2,0x1600028E,0x140002EE,0x120003C2,0x500499,
+0x1600032F,0x10000373,0x1000041B,0xC00049B,0xA4000108,0xFE0C0229,0xF21401F2,0x48000118,0x3600011B,0x2800011B,0x220000C2,0x20000173,0x64000209,0x3C00017A,0x1E0001B6,0x140002EE,0x380499,0x24039D,0x720C0055,0x3A0C0055,0x280C0056,0x500001A5,0x3A000028,0x28000001,0x280001A5,0x200000A2,0x1A0001A5,0x34039D,0x2E000149,0x240000AA,0x22000236,0x2000011B,
+0x180001F1,0x68039D,0x1C000236,0x160002AE,0x1200039E,0x34039D,0x2E000149,0x240000AA,0x22000236,0x2000011B,0x180001F1,0x68039D,0x1C000236,0x160002AE,0x1200039E,0x68039D,0x1C000236,0x160002AE,0x1200039E,0x1200039E,0xA4000108,0xFE0C0205,0xF61C016E,0x48000118,0x3600011B,0x2800011B,0x220000C2,0x20000173,0x6C0001DB,0x3C00016A,0x1E0001B2,0x160002AE,
+0x4C039D,0x80071,0x80071,0x80071,0x80071,0x26000000,0x26000000,0x26000000,0x12000000,0x12000000,0xC000000,0x10000055,0x10000055,0x10000055,0xC000020,0xC000020,0xC000010,0x8000055,0x8000055,0x8000034,0x6000055,0xC0071,0xC0071,0xC0071,0xC000030,0xC000030,0xC000020,0x600005D,0x600005D,0x800003D,0x6000059,0x140071,
+0x140071,0x4000052,0x4000062,0x4000072,0x44000019,0xC8000000,0x80071,0x24000022,0x1A00001D,0x12000022,0x1200001D,0xC000022,0x24000036,0x1A00002D,0xA000056,0x800003D,0x100071,0xC0055,0xC0055,0xC0055,0xC0055,0x26000000,0x26000000,0x26000000,0x12000000,0x12000000,0xC000000,0x100055,0x100055,0x100055,0xC000020,0xC000020,
+0xC000010,0x200055,0x200055,0x8000034,0x6000055,0x100055,0x100055,0x100055,0xC000020,0xC000020,0xC000010,0x200055,0x200055,0x8000034,0x6000055,0x200055,0x200055,0x8000034,0x6000055,0x6000055,0x44000019,0xC8000000,0xC0055,0x24000022,0x1A00001D,0x12000022,0x1200001D,0xC000022,0x24000032,0x1A000029,0x180055,0x8000034,
+0x180055,0x3801A5,0x621C0001,0x361C0001,0x28180002,0x5001A5,0x3A000028,0x28000001,0xA001A5,0x200000A2,0x1A0001A5,0x5001A5,0x3A000028,0x28000001,0xA001A5,0x200000A2,0x1A0001A5,0xA001A5,0x200000A2,0x1A0001A5,0x1A0001A5,0x5001A5,0x3A000028,0x28000001,0xA001A5,0x200000A2,0x1A0001A5,0xA001A5,0x200000A2,0x1A0001A5,0x1A0001A5,0xA001A5,
+0x200000A2,0x1A0001A5,0x1A0001A5,0x1A0001A5,0xA40000A4,0x3C01A5,0xFC280062,0x52000091,0x360000A2,0x2C00009D,0x2400006A,0x200000CA,0x720000DD,0x4C0000B4,0x26000059,0x1A0001A5,0x7001A5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table97[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x280001,0x280001,0x280001,0x280001,0x23C0000,0x23C0000,0x23C0000,0x7C0000,0x7C0000,0x14000000,0x23C0000,0x23C0000,0x23C0000,0x7C0000,0x7C0000,0x14000000,0x7C0000,0x7C0000,0x14000000,0x14000000,0x23C0000,0x23C0000,0x23C0000,0x7C0000,0x7C0000,0x14000000,0x7C0000,0x7C0000,0x14000000,0x14000000,0x7C0000,
+0x7C0000,0x14000000,0x14000000,0x14000000,0x300000,0x2C0000,0x280001,0x380000,0x440000,0x580000,0x640000,0x980000,0x340000,0x23C0000,0x580000,0x14000000,0x580000,0x640000,0x940000,0x12C0000,0x30000001,0x940000,0x12C0000,0x30000001,0x12C0000,0x30000001,0x30000001,0x940000,0x12C0000,0x30000001,0x12C0000,0x30000001,
+0x30000001,0x12C0000,0x30000001,0x30000001,0x30000001,0x940000,0x12C0000,0x30000001,0x12C0000,0x30000001,0x30000001,0x12C0000,0x30000001,0x30000001,0x30000001,0x12C0000,0x30000001,0x30000001,0x30000001,0x30000001,0x7C0000,0xC680000,0xC680000,0xA80000,0xF40000,0x1E00000,0x30000001,0x30000001,0x880000,0xBC0000,0x25DC0000,0x30000001,
+0xD40000,0x240691,0x86100129,0x460C0129,0x300C012A,0x6A0001A5,0x46000008,0x32000011,0x340001A5,0x2C00006A,0x220001A5,0x480004ED,0x3A0001D1,0x2E00010E,0x2E00029E,0x2800012B,0x2200021E,0x220004ED,0x20000306,0x1C000362,0x160004EE,0x340691,0x34000316,0x280001E3,0x28000367,0x280001D4,0x1E000295,0x1E000566,0x2000037F,0x1C0003C6,0x1600052E,0x680691,
+0x1C00048F,0x1600049F,0x140005C6,0x10000693,0xC2000118,0xF2140349,0xF61C0372,0x66000128,0x4000013B,0x34000135,0x2A0000C3,0x240001AE,0x82000289,0x500001CD,0x26000266,0x1C0003C6,0x4C0691,0x3004ED,0x821400DD,0x441400DD,0x301400DE,0x6A0001A5,0x46000008,0x3204000E,0x340001A5,0x2C00006A,0x220001A5,0x24404ED,0x3A0001D1,0x2E00010E,0x2E00029E,0x2800012B,
+0x2200021E,0x8C04ED,0x20000306,0x1C000362,0x160004EE,0x24404ED,0x3A0001D1,0x2E00010E,0x2E00029E,0x2800012B,0x2200021E,0x8C04ED,0x20000306,0x1C000362,0x160004EE,0x8C04ED,0x20000306,0x1C000362,0x160004EE,0x160004EE,0xC2000118,0xF61C02BD,0xFA24026E,0x66000128,0x4000013B,0x34000135,0x2A0000C3,0x240001AE,0x82000249,0x500001B4,0x26000262,0x1C000362,
+0x6404ED,0xC0129,0xC0129,0xC0129,0xC0129,0x3E000000,0x3E000000,0x3E000000,0x1E000000,0x1E000000,0x14000000,0x1C0000DD,0x1C0000DD,0x1C0000DD,0x18000050,0x18000050,0x12000028,0xE0000DD,0xE0000DD,0xE000088,0xA0000DD,0x140126,0x140126,0x140126,0x12000088,0x12000088,0x1200004C,0xC0000F1,0xC0000F1,0xC0000A1,0x80000EA,0x240126,
+0x240126,0xA0000C6,0x8000105,0x6000126,0x76000041,0xFA040011,0xC0129,0x3A000059,0x28000050,0x22000055,0x1E000049,0x16000061,0x42000092,0x3200007D,0x120000DE,0xC0000A1,0x1C0126,0x1400DD,0x1400DD,0x1400DD,0x1400DD,0x3E000000,0x3E000000,0x3E000000,0x1E000000,0x1E000000,0x14000000,0x1C00DD,0x1C00DD,0x1C00DD,0x18000050,0x18000050,
+0x12000028,0x3800DD,0x3800DD,0xE000088,0xA0000DD,0x1C00DD,0x1C00DD,0x1C00DD,0x18000050,0x18000050,0x12000028,0x3800DD,0x3800DD,0xE000088,0xA0000DD,0x3800DD,0x3800DD,0xE000088,0xA0000DD,0xA0000DD,0x76000041,0xFA04000D,0x1400DD,0x3A000059,0x28000050,0x22000055,0x1E000049,0x16000061,0x42000082,0x32000074,0x2800DD,0xE000088,
+0x2800DD,0x4801A5,0x6A2C0001,0x3E2C0001,0x30280002,0x6801A5,0x46000008,0x30100001,0xD001A5,0x2C00006A,0x220001A5,0x6801A5,0x46000008,0x30100001,0xD001A5,0x2C00006A,0x220001A5,0xD001A5,0x2C00006A,0x220001A5,0x220001A5,0x6801A5,0x46000008,0x30100001,0xD001A5,0x2C00006A,0x220001A5,0xD001A5,0x2C00006A,0x220001A5,0x220001A5,0xD001A5,
+0x2C00006A,0x220001A5,0x220001A5,0x220001A5,0xD6000075,0x4C01A5,0xF4380071,0x6E000059,0x4A00006A,0x36000064,0x2E00003A,0x280000A2,0x920400B5,0x5E00007D,0x32000028,0x220001A5,0x9401A5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table98[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x40001,0x40001,0x40001,0x40001,0x40001,0x40001,0x40001,0x40001,0x40001,0x40001,0x80000,0x80000,0x80000,0x80000,0x80000,
+0x80000,0xC0000,0xC0000,0xC0000,0x2000000,0x80000,0x80000,0x80000,0x80000,0x80000,0x80000,0xC0000,0xC0000,0xC0000,0x2000000,0xC0000,0xC0000,0xC0000,0x2000000,0x2000000,0xA040000,0x40001,0x40001,0x6040000,0x80000,0x80000,0x80000,0x80000,0x6040000,0x80000,0xC0000,0xC0000,
+0xC0000,0x380001,0x380001,0x380001,0x380001,0x540000,0x540000,0x540000,0xAC0000,0xAC0000,0x1C000000,0x540000,0x540000,0x540000,0xAC0000,0xAC0000,0x1C000000,0xAC0000,0xAC0000,0x1C000000,0x1C000000,0x540000,0x540000,0x540000,0xAC0000,0xAC0000,0x1C000000,0xAC0000,0xAC0000,0x1C000000,0x1C000000,0xAC0000,
+0xAC0000,0x1C000000,0x1C000000,0x1C000000,0x440000,0x63C0000,0x380001,0x24C0000,0x600000,0x780000,0x8C0000,0xD40000,0x480000,0x540000,0x780000,0x1C000000,0x780000,0x740000,0xAC0000,0x15C0000,0x38000001,0xAC0000,0x15C0000,0x38000001,0x15C0000,0x38000001,0x38000001,0xAC0000,0x15C0000,0x38000001,0x15C0000,0x38000001,
+0x38000001,0x15C0000,0x38000001,0x38000001,0x38000001,0xAC0000,0x15C0000,0x38000001,0x15C0000,0x38000001,0x38000001,0x15C0000,0x38000001,0x38000001,0x38000001,0x15C0000,0x38000001,0x38000001,0x38000001,0x38000001,0x900000,0x7C0000,0x7C0000,0x2C00000,0x11C0000,0x9F00000,0x38000001,0x38000001,0x9C0000,0xD80000,0x2DEC0000,0x38000001,
+0xF40000,0x2C088E,0x9A1401FE,0x501401FE,0x381401FF,0x7E0401AA,0x54040005,0x3C08003E,0x3E0401AA,0x3404004F,0x2A0401AA,0x5A0005EA,0x46000218,0x36000163,0x3A0002BD,0x3000010A,0x28000215,0x2C0005EA,0x26000383,0x240003DD,0x1C0005ED,0x40088E,0x40000401,0x3400028E,0x340003FA,0x2E0001F3,0x280002BE,0x2800069F,0x2600042C,0x20000463,0x1C000651,0x80088E,
+0x200005EF,0x1C0005B2,0x1A000749,0x1600088E,0xF40000E9,0xF61C0486,0xFA24050F,0x74000111,0x5000011D,0x3C000103,0x34000096,0x2C00019A,0xA40002D1,0x5E0001D1,0x320002B1,0x20000463,0x5C088E,0x3C05EA,0x8E200152,0x4E200152,0x38200153,0x7A0801A6,0x54040001,0x3A10002A,0x3E0401A6,0x3404004B,0x2A0401A6,0x5805EA,0x46000218,0x36000163,0x3A0002BD,0x3000010A,
+0x28000215,0xB005EA,0x26000383,0x240003DD,0x1C0005ED,0x5805EA,0x46000218,0x36000163,0x3A0002BD,0x3000010A,0x28000215,0xB005EA,0x26000383,0x240003DD,0x1C0005ED,0xB005EA,0x26000383,0x240003DD,0x1C0005ED,0x1C0005ED,0xF40000E9,0xFC280356,0xFE2C0353,0x74000111,0x5000011D,0x3C000103,0x34000096,0x2C00019A,0xA400026D,0x5E0001AD,0x320002A8,0x240003DD,
+0x7C05EA,0x1401FE,0x1401FE,0x1401FE,0x1401FE,0x52040005,0x52040005,0x52040005,0x28040006,0x28040006,0x1C040005,0x30000152,0x30000152,0x30000152,0x22000059,0x22000059,0x1A000028,0x16000154,0x16000154,0x160000B4,0xE000154,0x2001FD,0x2001FD,0x2001FD,0x220000D2,0x220000D2,0x18000069,0x12000188,0x12000188,0x140000EA,0xE00016D,0x3C01FD,
+0x3C01FD,0x10000149,0xA0001B5,0xA0001FD,0xB6000049,0xFE0C005E,0x1401FE,0x50000071,0x3C000061,0x2E000061,0x2A000049,0x2000007D,0x640000DD,0x440000AD,0x1E000156,0x140000EA,0x2C01FD,0x200152,0x200152,0x200152,0x200152,0x4E080001,0x4E080001,0x4E080001,0x28080001,0x28080001,0x1C040001,0x300152,0x300152,0x300152,0x22000059,0x22000059,
+0x1A000028,0x5C0152,0x5C0152,0x160000B4,0xE000154,0x300152,0x300152,0x300152,0x22000059,0x22000059,0x1A000028,0x5C0152,0x5C0152,0x160000B4,0xE000154,0x5C0152,0x5C0152,0x160000B4,0xE000154,0xE000154,0xB6000049,0xFE0C003A,0x200152,0x50000071,0x3C000061,0x2E000061,0x2A000049,0x2000007D,0x640000B9,0x4400009D,0x400152,0x160000B4,
+0x400152,0x5801A5,0x723C0001,0x463C0001,0x38380002,0x8001A5,0x54040000,0x38200001,0x10001A5,0x36000049,0x2A0001A5,0x8001A5,0x54040000,0x38200001,0x10001A5,0x36000049,0x2A0001A5,0x10001A5,0x36000049,0x2A0001A5,0x2A0001A5,0x8001A5,0x54040000,0x38200001,0x10001A5,0x36000049,0x2A0001A5,0x10001A5,0x36000049,0x2A0001A5,0x2A0001A5,0x10001A5,
+0x36000049,0x2A0001A5,0x2A0001A5,0x2A0001A5,0xF6040055,0x5C01A5,0xFC480071,0x84000034,0x56000048,0x40000048,0x36000019,0x32000071,0xB4040091,0x6E000055,0x3C00000A,0x2A0001A5,0xB401A5,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x8000000,0x8000000,0x8000000,0x8000000,0x8000000,
+0x8000000,0x4000000,0x4000000,0x4000000,0x2000000,0x40005,0x40005,0x40005,0x40005,0x40005,0x40005,0x2000002,0x2000002,0x2000002,0x2000001,0x5,0x5,0x5,0x2000004,0x5,0x28000000,0x40005,0x40005,0x12000000,0xC000000,0xA000000,0xA000000,0x6000000,0x12000001,0xC000001,0x4000000,0x2000002,
+0x5,};
+static const uint32_t g_etc1_to_bc7_m6_table99[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x140001,0x140001,0x140001,0x140001,0x140001,0x140001,0x140001,0x140001,0x140001,0x140001,0x200000,0x200000,0x200000,0x200000,0x200000,
+0x200000,0x3C0000,0x3C0000,0x3C0000,0xA000000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x3C0000,0x3C0000,0x3C0000,0xA000000,0x3C0000,0x3C0000,0x3C0000,0xA000000,0xA000000,0x180000,0x140001,0x140001,0x2180000,0x1C0000,0x1C0000,0x1C0000,0x240000,0x2180000,0x1C0000,0x2C0000,0x3C0000,
+0x2C0000,0x480001,0x480001,0x480001,0x480001,0x6C0000,0x6C0000,0x6C0000,0xDC0000,0xDC0000,0x24000000,0x6C0000,0x6C0000,0x6C0000,0xDC0000,0xDC0000,0x24000000,0xDC0000,0xDC0000,0x24000000,0x24000000,0x6C0000,0x6C0000,0x6C0000,0xDC0000,0xDC0000,0x24000000,0xDC0000,0xDC0000,0x24000000,0x24000000,0xDC0000,
+0xDC0000,0x24000000,0x24000000,0x24000000,0x2540000,0xE4C0000,0x480001,0x640000,0x7C0000,0x9C0000,0xB40000,0x1100000,0x5C0000,0x6C0000,0x9C0000,0x24000000,0x9C0000,0x840000,0xC40000,0x18C0000,0x40000001,0xC40000,0x18C0000,0x40000001,0x18C0000,0x40000001,0x40000001,0xC40000,0x18C0000,0x40000001,0x18C0000,0x40000001,
+0x40000001,0x18C0000,0x40000001,0x40000001,0x40000001,0xC40000,0x18C0000,0x40000001,0x18C0000,0x40000001,0x40000001,0x18C0000,0x40000001,0x40000001,0x40000001,0x18C0000,0x40000001,0x40000001,0x40000001,0x40000001,0xA40000,0x8C0000,0x8C0000,0xDC0000,0x1400000,0x13F00000,0x40000001,0x40000001,0xB40000,0xF80000,0x35FC0000,0x40000001,
+0x1180000,0x380A26,0xA62002D2,0x5A2002D2,0x402002D3,0x8E0C01E2,0x600C003F,0x461000A2,0x480C01E2,0x3C080073,0x320C01E2,0x720005EA,0x580001A8,0x40040159,0x4600024D,0x3A00007A,0x320001C9,0x380005EA,0x320002FB,0x2C000362,0x240005ED,0x540A26,0x4C000489,0x3C00031B,0x40000432,0x3A0001E3,0x2E0002BE,0x34000717,0x30000415,0x2A00043D,0x2400067D,0xA40A26,
+0x260006D7,0x26000662,0x20000819,0x1C000A26,0xFA0400DE,0xFC2805A6,0xFE2C0687,0x90000086,0x6200008B,0x4C00007A,0x40000029,0x380000FA,0xC200025D,0x76000142,0x3C000233,0x2A00043D,0x740A26,0x4C05EA,0x96300152,0x56300152,0x40300153,0x821801A6,0x5C140001,0x4220002A,0x461401A6,0x3C14004B,0x321401A6,0x7005EA,0x580001A8,0x40080153,0x4600024D,0x3A00007A,
+0x320001C9,0xE405EA,0x320002FB,0x2C000362,0x240005ED,0x7005EA,0x580001A8,0x40080153,0x4600024D,0x3A00007A,0x320001C9,0xE405EA,0x320002FB,0x2C000362,0x240005ED,0xE405EA,0x320002FB,0x2C000362,0x240005ED,0x240005ED,0xFC0800CE,0xF438037A,0xFA44035E,0x90000086,0x6200008B,0x4C00007A,0x40000029,0x380000FA,0xD00001C1,0x7C000105,0x3C000223,0x2C000362,
+0xA005EA,0x2002D2,0x2002D2,0x2002D2,0x2002D2,0x620C003D,0x620C003D,0x620C003D,0x320C003E,0x320C003E,0x240C003D,0x48000152,0x48000152,0x48000152,0x34000025,0x34000025,0x24000001,0x22000152,0x22000152,0x1C000080,0x16000154,0x3002D2,0x3002D2,0x3002D2,0x280000FE,0x280000FE,0x2200007D,0x1E0001C8,0x1E0001C8,0x1C0000E4,0x16000194,0x5C02D2,
+0x5C02D2,0x160001B5,0x14000228,0xE0002D5,0xF6000014,0xF21400F5,0x2002D2,0x7A000034,0x54000028,0x40000028,0x38000019,0x2A00003D,0x820000D5,0x5A000086,0x2C00015B,0x1C0000E4,0x4002D2,0x300152,0x300152,0x300152,0x300152,0x56180001,0x56180001,0x56180001,0x30180001,0x30180001,0x24140001,0x2440152,0x2440152,0x2440152,0x34000025,0x34000025,
+0x24000001,0x8C0152,0x8C0152,0x1C000080,0x16000154,0x2440152,0x2440152,0x2440152,0x34000025,0x34000025,0x24000001,0x8C0152,0x8C0152,0x1C000080,0x16000154,0x8C0152,0x8C0152,0x1C000080,0x16000154,0x16000154,0xF6000014,0xF820003D,0x300152,0x7A000034,0x54000028,0x40000028,0x38000019,0x2A00003D,0x96000088,0x5A000062,0x640152,0x1C000080,
+0x640152,0x6801A5,0x7A4C0001,0x4E4C0001,0x40480002,0x9801A5,0x5C140000,0x40300001,0x13001A5,0x3E000022,0x320001A5,0x9801A5,0x5C140000,0x40300001,0x13001A5,0x3E000022,0x320001A5,0x13001A5,0x3E000022,0x320001A5,0x320001A5,0x9801A5,0x5C140000,0x40300001,0x13001A5,0x3E000022,0x320001A5,0x13001A5,0x3E000022,0x320001A5,0x320001A5,0x13001A5,
+0x3E000022,0x320001A5,0x320001A5,0x320001A5,0xFE140055,0x6C01A5,0xF4580082,0x9A000019,0x6A000028,0x4E000022,0x40000005,0x3A000055,0xD2040071,0x8600003A,0x44000001,0x320001A5,0xD801A5,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0xC003D,0x20000000,0x20000000,0x20000000,0x20000000,0x20000000,
+0x20000000,0x10000000,0x10000000,0x10000000,0xA000000,0x10003D,0x10003D,0x10003D,0x10003D,0x10003D,0x10003D,0xC000014,0xC000014,0xC000014,0x800000D,0x18003D,0x18003D,0x18003D,0x8000028,0x400003D,0xA8000000,0xC003D,0xC003D,0x4A000000,0x34000000,0x28000000,0x28000000,0x1A000000,0x44000011,0x34000009,0x14000001,0xC000014,
+0x14003D,};
+static const uint32_t g_etc1_to_bc7_m6_table100[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,
+0x3C0000,0x740000,0x740000,0x740000,0x12000001,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x740000,0x740000,0x740000,0x12000001,0x740000,0x740000,0x740000,0x12000001,0x12000001,0xC280000,0x280000,0x280000,0x42C0000,0x2300000,0x2340000,0x2340000,0x2400000,0x42C0000,0x2300000,0x540000,0x740000,
+0x540000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x880000,0x880000,0x880000,0x1140000,0x1140000,0x2C000001,0x880000,0x880000,0x880000,0x1140000,0x1140000,0x2C000001,0x1140000,0x1140000,0x2C000001,0x2C000001,0x880000,0x880000,0x880000,0x1140000,0x1140000,0x2C000001,0x1140000,0x1140000,0x2C000001,0x2C000001,0x1140000,
+0x1140000,0x2C000001,0x2C000001,0x2C000001,0x6680000,0x8600000,0x5C0000,0x7C0000,0x980000,0xC00000,0xE00000,0x1540000,0x740000,0x880000,0xC00000,0x2C000001,0xC00000,0x940001,0x2DC0000,0x1C40000,0x4A000000,0x2DC0000,0x1C40000,0x4A000000,0x1C40000,0x4A000000,0x4A000000,0x2DC0000,0x1C40000,0x4A000000,0x1C40000,0x4A000000,
+0x4A000000,0x1C40000,0x4A000000,0x4A000000,0x4A000000,0x2DC0000,0x1C40000,0x4A000000,0x1C40000,0x4A000000,0x4A000000,0x1C40000,0x4A000000,0x4A000000,0x4A000000,0x1C40000,0x4A000000,0x4A000000,0x4A000000,0x4A000000,0xBC0000,0xA00000,0xA00000,0xFC0000,0x16C0000,0x1DFC0000,0x4A000000,0x4A000000,0xCC0000,0x1180000,0x3FF00000,0x4A000000,
+0x13C0000,0x480C65,0xB62C0428,0x642C0428,0x4A2C0428,0xA014026D,0x6A1400D8,0x4C1C0165,0x5414026D,0x461000F0,0x3C14026D,0x8E0005EA,0x6A000163,0x4E080192,0x580001F6,0x4600001D,0x3C0001A5,0x440005ED,0x3E000284,0x38000301,0x2E0005EA,0x680C63,0x5E000594,0x48000438,0x4C0004BF,0x40000222,0x3A000313,0x400007BE,0x3A00041D,0x34000436,0x2E0006CB,0xD00C63,
+0x32000818,0x2C00076D,0x2600094E,0x22000C63,0xFE140162,0xF43807A1,0xF840089D,0xB400001E,0x76000024,0x5A000018,0x4A000001,0x4200007A,0xF2000212,0x900000D7,0x460001D4,0x34000436,0x940C63,0x5C05ED,0x9E440154,0x5E440154,0x4A400154,0x8C2801A5,0x64280002,0x4A300029,0x4E2801A5,0x4424004C,0x3C2801A5,0x8C05EA,0x6A000163,0x4A180152,0x580001F6,0x4600001D,
+0x3C0001A5,0x11805EA,0x3E000284,0x38000301,0x2E0005EA,0x8C05EA,0x6A000163,0x4A180152,0x580001F6,0x4600001D,0x3C0001A5,0x11805EA,0x3E000284,0x38000301,0x2E0005EA,0x11805EA,0x3E000284,0x38000301,0x2E0005EA,0x2E0005EA,0xFC1C00E5,0xFE4C0379,0xF2540384,0xB400001E,0x76000024,0x5A000018,0x4A000001,0x4200007A,0xF2000131,0x90000086,0x460001C4,0x38000301,
+0xC805EA,0x2C0428,0x2C0428,0x2C0428,0x2C0428,0x761400C8,0x761400C8,0x761400C8,0x3E1400C8,0x3E1400C8,0x2C1400C9,0x64000152,0x64000152,0x64000152,0x40000005,0x40000005,0x2E04000E,0x30000152,0x30000152,0x26000055,0x20000152,0x400428,0x400428,0x400428,0x3400018E,0x3400018E,0x2A0000F1,0x2800022D,0x2800022D,0x240000FA,0x1E0001BE,0x800428,
+0x800428,0x1C00028B,0x1C0002DB,0x1400042B,0xFC0C003E,0xF82001F1,0x2C0428,0xA400000D,0x6C000008,0x52000008,0x4C000000,0x38000019,0xB40000E3,0x76000072,0x3E000162,0x240000FA,0x5C0428,0x400154,0x400154,0x400154,0x400154,0x62280000,0x62280000,0x62280000,0x3A280000,0x3A280000,0x2C280001,0x600152,0x600152,0x600152,0x40000005,0x40000005,
+0x2C100001,0xC40152,0xC40152,0x26000055,0x20000152,0x600152,0x600152,0x600152,0x40000005,0x40000005,0x2C100001,0xC40152,0xC40152,0x26000055,0x20000152,0xC40152,0xC40152,0x26000055,0x20000152,0x20000152,0xFE100012,0xF2340048,0x400154,0xA400000D,0x6C000008,0x52000008,0x4C000000,0x38000019,0xC2000055,0x7C000032,0x8C0152,0x26000055,
+0x8C0152,0x7801A5,0x845C0000,0x585C0000,0x4A5C0000,0xB401A5,0x66240000,0x4A400000,0x16801A5,0x4800000D,0x3C0001A5,0xB401A5,0x66240000,0x4A400000,0x16801A5,0x4800000D,0x3C0001A5,0x16801A5,0x4800000D,0x3C0001A5,0x3C0001A5,0xB401A5,0x66240000,0x4A400000,0x16801A5,0x4800000D,0x3C0001A5,0x16801A5,0x4800000D,0x3C0001A5,0x3C0001A5,0x16801A5,
+0x4800000D,0x3C0001A5,0x3C0001A5,0x3C0001A5,0xFE280062,0x8001A5,0xFE6C0080,0xB4000005,0x78000012,0x5A000008,0x4A080000,0x46000034,0xF6080055,0x98000019,0x4E100000,0x3C0001A5,0xFC01A5,0x1400C8,0x1400C8,0x1400C8,0x1400C8,0x1400C8,0x1400C8,0x1400C8,0x1400C8,0x1400C8,0x1400C8,0x3C000000,0x3C000000,0x3C000000,0x3C000000,0x3C000000,
+0x3C000000,0x1C000001,0x1C000001,0x1C000001,0x12000001,0x1C00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x1C00C8,0x18000049,0x18000049,0x18000049,0x12000025,0x3800C8,0x3800C8,0x3800C8,0xE00007D,0x80000CA,0xFA040008,0x1400C8,0x1400C8,0x8A000000,0x60000000,0x4A000000,0x4A000000,0x30000000,0x7600003A,0x5600001D,0x24000004,0x18000049,
+0x2800C8,};
+static const uint32_t g_etc1_to_bc7_m6_table101[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,
+0x2500000,0xA40000,0xA40000,0xA40000,0x1A000001,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,0x2500000,0xA40000,0xA40000,0xA40000,0x1A000001,0xA40000,0xA40000,0xA40000,0x1A000001,0x1A000001,0x3C0000,0x380000,0x380000,0x400000,0x2440000,0x4C0000,0x4C0000,0x5C0000,0x400000,0x2440000,0x740000,0xA40000,
+0x740000,0x6C0000,0x6C0000,0x6C0000,0x6C0000,0xA00000,0xA00000,0xA00000,0x1440000,0x1440000,0x34000001,0xA00000,0xA00000,0xA00000,0x1440000,0x1440000,0x34000001,0x1440000,0x1440000,0x34000001,0x34000001,0xA00000,0xA00000,0xA00000,0x1440000,0x1440000,0x34000001,0x1440000,0x1440000,0x34000001,0x34000001,0x1440000,
+0x1440000,0x34000001,0x34000001,0x34000001,0x27C0000,0x740000,0x6C0000,0x2900000,0xB40000,0xE40000,0x1080000,0x1900000,0x880000,0xA00000,0xE40000,0x34000001,0xE40000,0xA40001,0x2F40000,0x1F40000,0x52000000,0x2F40000,0x1F40000,0x52000000,0x1F40000,0x52000000,0x52000000,0x2F40000,0x1F40000,0x52000000,0x1F40000,0x52000000,
+0x52000000,0x1F40000,0x52000000,0x52000000,0x52000000,0x2F40000,0x1F40000,0x52000000,0x1F40000,0x52000000,0x52000000,0x1F40000,0x52000000,0x52000000,0x52000000,0x1F40000,0x52000000,0x52000000,0x52000000,0x52000000,0xD00000,0xB00000,0xB00000,0x3140000,0x1940000,0x27FC0000,0x52000000,0x52000000,0xE00000,0x1380000,0x49C40000,0x52000000,
+0x1600000,0x540EC9,0xC23805B4,0x6C3805B5,0x523805B4,0xB21C032D,0x762001A4,0x56240261,0x5E1C032D,0x501801A4,0x441C032D,0xA60005EA,0x7C000153,0x581001FE,0x620001B9,0x50000005,0x440401B9,0x500005ED,0x4A000234,0x3E0002A5,0x360005EA,0x780EC7,0x680006C8,0x520005B3,0x5800057F,0x4C0002A2,0x400003A7,0x4C000876,0x46000455,0x3C00044E,0x34000717,0xF40EC7,
+0x380009AC,0x320008B1,0x30000A97,0x28000EC7,0xFE20025D,0xFA440995,0xFE4C0AC9,0xCC000001,0x8A000004,0x66000003,0x5408001C,0x4E000030,0xFE000225,0xA60000A2,0x54000194,0x3C00044E,0xAC0EC7,0x6C05ED,0xA6540154,0x66540154,0x52500154,0x943801A5,0x6C380002,0x52400029,0x563801A5,0x4C34004C,0x443801A5,0xA405EA,0x78040153,0x52280152,0x620001B9,0x50000005,
+0x441001A5,0x14C05EA,0x4A000234,0x3E0002A5,0x360005EA,0xA405EA,0x78040153,0x52280152,0x620001B9,0x50000005,0x441001A5,0x14C05EA,0x4A000234,0x3E0002A5,0x360005EA,0x14C05EA,0x4A000234,0x3E0002A5,0x360005EA,0x360005EA,0xFC3000F8,0xF65C039D,0xFA640384,0xCC000001,0x8A000004,0x66000003,0x52100001,0x4E000030,0xFE08010A,0xA8000035,0x5400017B,0x3E0002A5,
+0xE805EA,0x3805B4,0x3805B4,0x3805B4,0x3805B4,0x861C0188,0x861C0188,0x861C0188,0x481C0188,0x481C0188,0x341C0189,0x7C000152,0x7C000152,0x7C000152,0x50000001,0x50000001,0x36080042,0x3C000152,0x3C000152,0x3200002D,0x28000152,0x5005B3,0x5005B3,0x5005B3,0x4000024E,0x4000024E,0x3400019B,0x340002A5,0x340002A5,0x2E000122,0x280001FB,0xA005B3,
+0xA005B3,0x26000389,0x200003B6,0x1A0005B3,0xF81400D1,0xFE2C0329,0x3805B4,0xC6000001,0x84000001,0x64000001,0x5A040009,0x48000004,0xE4000105,0x9600006A,0x4C00016B,0x2E000122,0x7005B3,0x500154,0x500154,0x500154,0x500154,0x6A380000,0x6A380000,0x6A380000,0x42380000,0x42380000,0x34380001,0x780152,0x780152,0x780152,0x4C080001,0x4C080001,
+0x34200001,0xF40152,0xF40152,0x3200002D,0x28000152,0x780152,0x780152,0x780152,0x4C080001,0x4C080001,0x34200001,0xF40152,0xF40152,0x3200002D,0x28000152,0xF40152,0xF40152,0x3200002D,0x28000152,0x28000152,0xFE200019,0xFA440048,0x500154,0xC4040001,0x80040000,0x62040000,0x54100000,0x48000004,0xF4000034,0x9A000012,0xAC0152,0x3200002D,
+0xAC0152,0x8801A5,0x8C6C0000,0x606C0000,0x526C0000,0xC801A5,0x6E340000,0x52500000,0x19801A5,0x50000004,0x440001A5,0xC801A5,0x6E340000,0x52500000,0x19801A5,0x50000004,0x440001A5,0x19801A5,0x50000004,0x440001A5,0x440001A5,0xC801A5,0x6E340000,0x52500000,0x19801A5,0x50000004,0x440001A5,0x19801A5,0x50000004,0x440001A5,0x440001A5,0x19801A5,
+0x50000004,0x440001A5,0x440001A5,0x440001A5,0xF6400071,0x9001A5,0xF67C0091,0xCC000000,0x8A000004,0x66000002,0x52180000,0x5000001D,0xFE180055,0xAE00000A,0x56200000,0x440001A5,0x12001A5,0x1C0188,0x1C0188,0x1C0188,0x1C0188,0x1C0188,0x1C0188,0x1C0188,0x1C0188,0x1C0188,0x1C0188,0x54000000,0x54000000,0x54000000,0x54000000,0x54000000,
+0x54000000,0x28000000,0x28000000,0x28000000,0x1A000001,0x280188,0x280188,0x280188,0x280188,0x280188,0x280188,0x22000089,0x22000089,0x22000089,0x18000049,0x500188,0x500188,0x500188,0x100000F2,0xC00018A,0xFE0C0048,0x1C0188,0x1C0188,0xC4000000,0x88000000,0x68000000,0x68000000,0x44000000,0xA000007D,0x74000041,0x34000009,0x22000089,
+0x380188,};
+static const uint32_t g_etc1_to_bc7_m6_table102[] = {
+0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x240000,
+0x240000,0x240000,0x240000,0x6000000,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xC0001,0xE0C0000,0xE0C0000,0xE0C0000,0x140000,0x1C0000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x2680000,0x2680000,0x2680000,0x2680000,0x2680000,
+0x2680000,0xD80000,0xD80000,0xD80000,0x22000001,0x2680000,0x2680000,0x2680000,0x2680000,0x2680000,0x2680000,0xD80000,0xD80000,0xD80000,0x22000001,0xD80000,0xD80000,0xD80000,0x22000001,0x22000001,0x4C0000,0x480000,0x480000,0x540000,0x2580000,0x600000,0x600000,0x780000,0x540000,0x2580000,0x980000,0xD80000,
+0x980000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0xB80000,0xB80000,0xB80000,0x1740000,0x1740000,0x3C000001,0xB80000,0xB80000,0xB80000,0x1740000,0x1740000,0x3C000001,0x1740000,0x1740000,0x3C000001,0x3C000001,0xB80000,0xB80000,0xB80000,0x1740000,0x1740000,0x3C000001,0x1740000,0x1740000,0x3C000001,0x3C000001,0x1740000,
+0x1740000,0x3C000001,0x3C000001,0x3C000001,0x900000,0x840000,0x7C0000,0xA80000,0xD00000,0x1080000,0x12C0000,0x1CC0000,0x9C0000,0xB80000,0x1080000,0x3C000001,0x1080000,0xB40001,0x30C0000,0xBFC0000,0x5A000000,0x30C0000,0xBFC0000,0x5A000000,0xBFC0000,0x5A000000,0x5A000000,0x30C0000,0xBFC0000,0x5A000000,0xBFC0000,0x5A000000,
+0x5A000000,0xBFC0000,0x5A000000,0x5A000000,0x5A000000,0x30C0000,0xBFC0000,0x5A000000,0xBFC0000,0x5A000000,0x5A000000,0xBFC0000,0x5A000000,0x5A000000,0x5A000000,0xBFC0000,0x5A000000,0x5A000000,0x5A000000,0x5A000000,0xE40000,0x8C00000,0x8C00000,0x1300000,0x1BC0000,0x31FC0000,0x5A000000,0x5A000000,0xF80000,0x1540000,0x51D40000,0x5A000000,
+0x1800000,0x600F1E,0xCA4805ED,0x764405ED,0x5A4405ED,0xBA2C034A,0x7E3001C5,0x5E340286,0x662C034A,0x582801BD,0x4C2C034A,0xAE1005EB,0x84100154,0x6020020F,0x6C0801B6,0x58100006,0x4C1401BE,0x5A0C05EB,0x5204020D,0x4604028A,0x3E0C05EB,0x900F1A,0x7A000675,0x5A1005EA,0x680004BE,0x5800021D,0x4C000362,0x580007E9,0x4E00036B,0x46000371,0x3C00069F,0x1240F1A,
+0x44000939,0x3E0007FE,0x38000A17,0x30000F1A,0xFE3402CD,0xFE4C0A1A,0xF65C0B55,0xD4100002,0x920C0004,0x6E100004,0x5C180025,0x560C0023,0xFE100262,0xBC000021,0x5E000159,0x46000371,0xD00F1A,0x7C05ED,0xAE640154,0x6E640154,0x5A600154,0x9C4801A5,0x74480002,0x5A500029,0x5E4801A5,0x5444004C,0x4C4801A5,0xBC05EA,0x80140153,0x5A380152,0x700001A6,0x58100005,
+0x4C2001A5,0x17C05EA,0x500001E8,0x48000266,0x3E0005EA,0xBC05EA,0x80140153,0x5A380152,0x700001A6,0x58100005,0x4C2001A5,0x17C05EA,0x500001E8,0x48000266,0x3E0005EA,0x17C05EA,0x500001E8,0x48000266,0x3E0005EA,0x3E0005EA,0xFE3C0121,0xFE6C039D,0xF27403AD,0xD4100001,0x920C0003,0x6E100003,0x5A200001,0x5800000D,0xFE180129,0xBC000008,0x5E000158,0x48000266,
+0x10C05EA,0x4405ED,0x4405ED,0x4405ED,0x4405ED,0x8E2C01A5,0x8E2C01A5,0x8E2C01A5,0x502C01A5,0x502C01A5,0x3C2C01A6,0x84100153,0x84100153,0x84100153,0x58100002,0x58100002,0x3E18004B,0x44100153,0x44100153,0x380C002A,0x300C0153,0x6805EA,0x6805EA,0x6805EA,0x52000205,0x52000205,0x3C0401A6,0x40000248,0x40000248,0x3A0000A9,0x2E00019A,0xD005EA,
+0xD005EA,0x2C000356,0x2A00037E,0x220005EA,0xFE2000FA,0xF63C0379,0x4405ED,0xD80C0001,0x8C100002,0x6C100002,0x6410000B,0x500C0002,0xFE0000B5,0xB6000015,0x5A040153,0x3A0000A9,0x9405EA,0x600154,0x600154,0x600154,0x600154,0x72480000,0x72480000,0x72480000,0x4A480000,0x4A480000,0x3C480001,0x900152,0x900152,0x900152,0x54180001,0x54180001,
+0x3C300001,0x1240152,0x1240152,0x3A000019,0x30000152,0x900152,0x900152,0x900152,0x54180001,0x54180001,0x3C300001,0x1240152,0x1240152,0x3A000019,0x30000152,0x1240152,0x1240152,0x3A000019,0x30000152,0x30000152,0xFA340020,0xF2540055,0x600154,0xD80C0000,0x88140000,0x6A140000,0x5C200000,0x52080000,0xFE0C0032,0xBC000004,0xD00152,0x3A000019,
+0xD00152,0x9801A5,0x947C0000,0x687C0000,0x5A7C0000,0xE001A5,0x76440000,0x5A600000,0x1CC01A5,0x5A040000,0x4C0001A5,0xE001A5,0x76440000,0x5A600000,0x1CC01A5,0x5A040000,0x4C0001A5,0x1CC01A5,0x5A040000,0x4C0001A5,0x4C0001A5,0xE001A5,0x76440000,0x5A600000,0x1CC01A5,0x5A040000,0x4C0001A5,0x1CC01A5,0x5A040000,0x4C0001A5,0x4C0001A5,0x1CC01A5,
+0x5A040000,0x4C0001A5,0x4C0001A5,0x4C0001A5,0xFE500071,0xA401A5,0xFE8C0091,0xD4100000,0x98000000,0x70080000,0x5A280000,0x5800000D,0xFE2C0062,0xBC040002,0x5E300000,0x4C0001A5,0x14001A5,0x2C01A5,0x2C01A5,0x2C01A5,0x2C01A5,0x2C01A5,0x2C01A5,0x2C01A5,0x2C01A5,0x2C01A5,0x2C01A5,0x5C100001,0x5C100001,0x5C100001,0x5C100001,0x5C100001,
+0x5C100001,0x30100001,0x30100001,0x30100001,0x220C0002,0x4001A5,0x4001A5,0x4001A5,0x4001A5,0x4001A5,0x4001A5,0x2E000050,0x2E000050,0x2E000050,0x22000011,0x7C01A5,0x7C01A5,0x7C01A5,0x1C0000C1,0x140001A5,0xF61C0062,0x2C01A5,0x2C01A5,0xCC100001,0x90100001,0x70100001,0x70100001,0x4C100001,0xE0000041,0xA400000D,0x40080001,0x2E000050,
+0x5801A5,};
+static const uint32_t g_etc1_to_bc7_m6_table103[] = {
+0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x580000,
+0x580000,0x580000,0x580000,0xE000000,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x200000,0x200000,0x200000,0x2C0000,0x3C0000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x2800000,0x2800000,0x2800000,0x2800000,0x2800000,
+0x2800000,0x1080000,0x1080000,0x1080000,0x2A000001,0x2800000,0x2800000,0x2800000,0x2800000,0x2800000,0x2800000,0x1080000,0x1080000,0x1080000,0x2A000001,0x1080000,0x1080000,0x1080000,0x2A000001,0x2A000001,0x65C0000,0x580000,0x580000,0x4640000,0x26C0000,0x780000,0x780000,0x940000,0x4640000,0x26C0000,0xB80000,0x1080000,
+0xB80000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0xD00000,0xD00000,0xD00000,0x1A40000,0x1A40000,0x44000001,0xD00000,0xD00000,0xD00000,0x1A40000,0x1A40000,0x44000001,0x1A40000,0x1A40000,0x44000001,0x44000001,0xD00000,0xD00000,0xD00000,0x1A40000,0x1A40000,0x44000001,0x1A40000,0x1A40000,0x44000001,0x44000001,0x1A40000,
+0x1A40000,0x44000001,0x44000001,0x44000001,0x6A00000,0x2940000,0x8C0000,0x2BC0000,0xEC0000,0x1280000,0x1540000,0x3FC0000,0xB00000,0xD00000,0x1280000,0x44000001,0x1280000,0xC40001,0x3240000,0x17FC0000,0x62000000,0x3240000,0x17FC0000,0x62000000,0x17FC0000,0x62000000,0x62000000,0x3240000,0x17FC0000,0x62000000,0x17FC0000,0x62000000,
+0x62000000,0x17FC0000,0x62000000,0x62000000,0x62000000,0x3240000,0x17FC0000,0x62000000,0x17FC0000,0x62000000,0x62000000,0x17FC0000,0x62000000,0x62000000,0x62000000,0x17FC0000,0x62000000,0x62000000,0x62000000,0x62000000,0xF80000,0xD40000,0xD40000,0x14C0000,0x1E40000,0x3BFC0000,0x62000000,0x62000000,0x10C0000,0x1740000,0x59E40000,0x62000000,
+0x1A40000,0x700F1E,0xD25805ED,0x7E5405ED,0x625405ED,0xC23C034A,0x864001C5,0x66440286,0x6E3C034A,0x603801BD,0x543C034A,0xB62005EB,0x8C200154,0x6830020F,0x741801B6,0x60200006,0x542401BE,0x621C05EB,0x5A14020D,0x4E14028A,0x461C05EB,0xA80F1A,0x8C000615,0x622005EA,0x74000416,0x620001BA,0x5404034A,0x6200073B,0x5800028C,0x4E0002AB,0x4600062A,0x1580F1A,
+0x50000899,0x4A000746,0x3E000983,0x38000F1A,0xFE440322,0xFA640A2E,0xFE6C0B55,0xDC200002,0x9A1C0004,0x76200004,0x64280025,0x5E1C0023,0xFE1C02BE,0xD0040000,0x66100159,0x4E0002AB,0xF00F1A,0x8C05ED,0xB6740154,0x76740154,0x62700154,0xA45801A5,0x7C580002,0x62600029,0x665801A5,0x5C54004C,0x545801A5,0x2D005EA,0x88240153,0x62480152,0x7A0C01A5,0x60200005,
+0x543001A5,0x1AC05EA,0x5C0001A8,0x50000221,0x460005EA,0x2D005EA,0x88240153,0x62480152,0x7A0C01A5,0x60200005,0x543001A5,0x1AC05EA,0x5C0001A8,0x50000221,0x460005EA,0x1AC05EA,0x5C0001A8,0x50000221,0x460005EA,0x460005EA,0xFE500132,0xF67C03C5,0xFA8403AD,0xDC200001,0x9A1C0003,0x76200003,0x62300001,0x6008000C,0xFC300155,0xD0040000,0x68040152,0x50000221,
+0x12C05EA,0x5405ED,0x5405ED,0x5405ED,0x5405ED,0x963C01A5,0x963C01A5,0x963C01A5,0x583C01A5,0x583C01A5,0x443C01A6,0x8C200153,0x8C200153,0x8C200153,0x60200002,0x60200002,0x4628004B,0x4C200153,0x4C200153,0x401C002A,0x381C0153,0x8005EA,0x8005EA,0x8005EA,0x620001BA,0x620001BA,0x441401A6,0x520001E4,0x520001E4,0x4200003B,0x38000162,0x10005EA,
+0x10005EA,0x380002DE,0x32000303,0x2A0005EA,0xFC380111,0xFE4C0379,0x5405ED,0xE01C0001,0x94200002,0x74200002,0x6C20000B,0x581C0002,0xFE1400C8,0xD0040000,0x62140153,0x4200003B,0xB405EA,0x700154,0x700154,0x700154,0x700154,0x7A580000,0x7A580000,0x7A580000,0x52580000,0x52580000,0x44580001,0xA80152,0xA80152,0xA80152,0x5C280001,0x5C280001,
+0x44400001,0x1580152,0x1580152,0x44000005,0x38000152,0xA80152,0xA80152,0xA80152,0x5C280001,0x5C280001,0x44400001,0x1580152,0x1580152,0x44000005,0x38000152,0x1580152,0x1580152,0x44000005,0x38000152,0x38000152,0xF6480029,0xFA640055,0x700154,0xE01C0000,0x90240000,0x72240000,0x64300000,0x5A180000,0xF624003D,0xD0040000,0xF00152,0x44000005,
+0xF00152,0xA801A5,0x9C8C0000,0x708C0000,0x628C0000,0xF801A5,0x7E540000,0x62700000,0x1FC01A5,0x62140000,0x540001A5,0xF801A5,0x7E540000,0x62700000,0x1FC01A5,0x62140000,0x540001A5,0x1FC01A5,0x62140000,0x540001A5,0x540001A5,0xF801A5,0x7E540000,0x62700000,0x1FC01A5,0x62140000,0x540001A5,0x1FC01A5,0x62140000,0x540001A5,0x540001A5,0x1FC01A5,
+0x62140000,0x540001A5,0x540001A5,0x540001A5,0xFA640080,0xB401A5,0xF69C00A4,0xDC200000,0xA0100000,0x78180000,0x62380000,0x60000005,0xF4480071,0xD0040000,0x66400000,0x540001A5,0x16401A5,0x3C01A5,0x3C01A5,0x3C01A5,0x3C01A5,0x3C01A5,0x3C01A5,0x3C01A5,0x3C01A5,0x3C01A5,0x3C01A5,0x64200001,0x64200001,0x64200001,0x64200001,0x64200001,
+0x64200001,0x38200001,0x38200001,0x38200001,0x2A1C0002,0x5401A5,0x5401A5,0x5401A5,0x5401A5,0x5401A5,0x5401A5,0x3A000020,0x3A000020,0x3A000020,0x2A040001,0xAC01A5,0xAC01A5,0xAC01A5,0x26000092,0x1C0001A5,0xFE2C0062,0x3C01A5,0x3C01A5,0xD4200001,0x98200001,0x78200001,0x78200001,0x54200001,0xFA080029,0xCE040000,0x48180001,0x3A000020,
+0x7801A5,};
+static const uint32_t g_etc1_to_bc7_m6_table104[] = {
+0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x8C0000,
+0x8C0000,0x8C0000,0x8C0000,0x16000001,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x340000,0x340000,0x340000,0x2440000,0x640000,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x680001,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,
+0x9C0000,0x13C0000,0x13C0000,0x13C0000,0x34000000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x9C0000,0x13C0000,0x13C0000,0x13C0000,0x34000000,0x13C0000,0x13C0000,0x13C0000,0x34000000,0x34000000,0x700000,0x680001,0x680001,0x7C0000,0x840000,0x900000,0x900000,0xB00000,0x7C0000,0x840000,0xE00000,0x13C0000,
+0xE00000,0x9C0001,0x9C0001,0x9C0001,0x9C0001,0x2E80000,0x2E80000,0x2E80000,0x1DC0000,0x1DC0000,0x4E000000,0x2E80000,0x2E80000,0x2E80000,0x1DC0000,0x1DC0000,0x4E000000,0x1DC0000,0x1DC0000,0x4E000000,0x4E000000,0x2E80000,0x2E80000,0x2E80000,0x1DC0000,0x1DC0000,0x4E000000,0x1DC0000,0x1DC0000,0x4E000000,0x4E000000,0x1DC0000,
+0x1DC0000,0x4E000000,0x4E000000,0x4E000000,0xB80000,0xA80000,0x9C0001,0x2D40000,0x1080000,0x1500000,0x1800000,0x11F40000,0x2C40000,0x2E80000,0x1500000,0x4E000000,0x1500000,0xD80000,0x1400000,0x25F80000,0x6A000001,0x1400000,0x25F80000,0x6A000001,0x25F80000,0x6A000001,0x6A000001,0x1400000,0x25F80000,0x6A000001,0x25F80000,0x6A000001,
+0x6A000001,0x25F80000,0x6A000001,0x6A000001,0x6A000001,0x1400000,0x25F80000,0x6A000001,0x25F80000,0x6A000001,0x6A000001,0x25F80000,0x6A000001,0x6A000001,0x6A000001,0x25F80000,0x6A000001,0x6A000001,0x6A000001,0x6A000001,0x50C0000,0xAE40000,0xAE40000,0x16C0000,0x9F80000,0x47F80000,0x6A000001,0x6A000001,0x3240000,0x1940000,0x63D80000,0x6A000001,
+0x1CC0000,0x840F1A,0xDE6805EA,0x866805EA,0x6A6805EB,0xCC4C034A,0x8E5001C3,0x6E54028A,0x784C034A,0x684C01BE,0x5C4C034A,0xC23005EA,0x96300153,0x7040020D,0x7E2C01B2,0x6A300006,0x5E3401BD,0x6A3005EA,0x6224020F,0x58280286,0x4E3005ED,0xC40F1A,0x9E0005EB,0x6C3005EB,0x86000392,0x6C0801B6,0x5C18034A,0x740006B1,0x640001DC,0x5A000215,0x4E0005F1,0x18C0F1A,
+0x5C0007F7,0x50000662,0x4A0008D9,0x40000F1E,0xFE580372,0xF4780A82,0xF67C0B9A,0xE6300000,0xA2300003,0x80300002,0x6C380023,0x662C0025,0xFE3402F6,0xD6180002,0x7024015B,0x5A000215,0x1180F1A,0xA005EA,0xC0840152,0x80840152,0x6A840153,0xAC6C01A6,0x86680001,0x6C74002A,0x706801A6,0x6668004B,0x5C6801A6,0xEC05EA,0x90380153,0x6A5C0153,0x841C01A5,0x6A340002,
+0x5C4401A5,0x1E405EA,0x6600017D,0x5A0001F1,0x4E0005ED,0xEC05EA,0x90380153,0x6A5C0153,0x841C01A5,0x6A340002,0x5C4401A5,0x1E405EA,0x6600017D,0x5A0001F1,0x4E0005ED,0x1E405EA,0x6600017D,0x5A0001F1,0x4E0005ED,0x4E0005ED,0xFE640164,0xFE8C03CE,0xF49803D3,0xE6300000,0xA2300003,0x80300002,0x6C440002,0x6A1C000B,0xFE440171,0xD6180001,0x72140152,0x5A0001F1,
+0x15405EA,0x6805EA,0x6805EA,0x6805EA,0x6805EA,0xA24C01A5,0xA24C01A5,0xA24C01A5,0x624C01A5,0x624C01A5,0x4E4C01A5,0x96300152,0x96300152,0x96300152,0x68300005,0x68300005,0x503C004C,0x56300152,0x56300152,0x4A300029,0x40300154,0x29805EA,0x29805EA,0x29805EA,0x740001A5,0x740001A5,0x4E2401A5,0x5E00018B,0x5E00018B,0x4E000004,0x40080154,0x13805EA,
+0x13805EA,0x44000279,0x3C0002A5,0x320005ED,0xFC480129,0xF860039D,0x6805EA,0xE6300000,0xA0300002,0x80300002,0x7634000C,0x62300001,0xFE2800F2,0xD6180001,0x6C240152,0x4E000004,0xDC05EA,0x840152,0x840152,0x840152,0x840152,0x806C0001,0x806C0001,0x806C0001,0x5A6C0001,0x5A6C0001,0x4E680001,0xC40152,0xC40152,0xC40152,0x643C0001,0x643C0001,
+0x4E500000,0x18C0152,0x18C0152,0x4E000000,0x40000154,0xC40152,0xC40152,0xC40152,0x643C0001,0x643C0001,0x4E500000,0x18C0152,0x18C0152,0x4E000000,0x40000154,0x18C0152,0x18C0152,0x4E000000,0x40000154,0x40000154,0xFE580029,0xF4780062,0x840152,0xE6300000,0x98380000,0x7A380001,0x6E400000,0x622C0000,0xFE34003D,0xD6180000,0x1180152,0x4E000000,
+0x1180152,0xBC01A5,0xA4A00001,0x78A00001,0x6A9C0002,0x11401A5,0x86680000,0x6A840001,0xFF801A5,0x6A2C0001,0x5C0001A5,0x11401A5,0x86680000,0x6A840001,0xFF801A5,0x6A2C0001,0x5C0001A5,0xFF801A5,0x6A2C0001,0x5C0001A5,0x5C0001A5,0x11401A5,0x86680000,0x6A840001,0xFF801A5,0x6A2C0001,0x5C0001A5,0xFF801A5,0x6A2C0001,0x5C0001A5,0x5C0001A5,0xFF801A5,
+0x6A2C0001,0x5C0001A5,0x5C0001A5,0x5C0001A5,0xFE780080,0xC801A5,0xFEAC00AA,0xE2340000,0xA8240000,0x82280000,0x6A4C0001,0x6A000001,0xFC580071,0xD8180000,0x70500000,0x5C0001A5,0x18C01A5,0x4C01A5,0x4C01A5,0x4C01A5,0x4C01A5,0x4C01A5,0x4C01A5,0x4C01A5,0x4C01A5,0x4C01A5,0x4C01A5,0x6E300000,0x6E300000,0x6E300000,0x6E300000,0x6E300000,
+0x6E300000,0x42300000,0x42300000,0x42300000,0x34300000,0x7001A5,0x7001A5,0x7001A5,0x7001A5,0x7001A5,0x7001A5,0x4C000002,0x4C000002,0x4C000002,0x34140000,0xE401A5,0xE401A5,0xE401A5,0x30000061,0x260001A5,0xF8400071,0x4C01A5,0x4C01A5,0xE2300000,0xA4300000,0x84300000,0x84300000,0x5E300000,0xFC1C0032,0xCE180001,0x52280000,0x4C000002,
+0xA001A5,};
+static const uint32_t g_etc1_to_bc7_m6_table105[] = {
+0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0x25C0000,0xBC0000,
+0xBC0000,0xBC0000,0xBC0000,0x1E000001,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x440000,0x440000,0x440000,0x25C0000,0x880000,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0x780001,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,
+0xB40000,0x1700000,0x1700000,0x1700000,0x3C000000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0x1700000,0x1700000,0x1700000,0x3C000000,0x1700000,0x1700000,0x1700000,0x3C000000,0x3C000000,0x8800000,0x780001,0x780001,0x28C0000,0x980000,0x2A40000,0x2A40000,0xCC0000,0x28C0000,0x980000,0x1000000,0x1700000,
+0x1000000,0xAC0001,0xAC0001,0xAC0001,0xAC0001,0x3000000,0x3000000,0x3000000,0x5FC0000,0x5FC0000,0x56000000,0x3000000,0x3000000,0x3000000,0x5FC0000,0x5FC0000,0x56000000,0x5FC0000,0x5FC0000,0x56000000,0x56000000,0x3000000,0x3000000,0x3000000,0x5FC0000,0x5FC0000,0x56000000,0x5FC0000,0x5FC0000,0x56000000,0x56000000,0x5FC0000,
+0x5FC0000,0x56000000,0x56000000,0x56000000,0x4C80000,0x4B80000,0xAC0001,0xEC0000,0x1240000,0x1700000,0x1A80000,0x1BF80000,0x2D80000,0x3000000,0x1700000,0x56000000,0x1700000,0xE80000,0x1580000,0x31F80000,0x72000001,0x1580000,0x31F80000,0x72000001,0x31F80000,0x72000001,0x72000001,0x1580000,0x31F80000,0x72000001,0x31F80000,0x72000001,
+0x72000001,0x31F80000,0x72000001,0x72000001,0x72000001,0x1580000,0x31F80000,0x72000001,0x31F80000,0x72000001,0x72000001,0x31F80000,0x72000001,0x72000001,0x72000001,0x31F80000,0x72000001,0x72000001,0x72000001,0x72000001,0x5200000,0xF80000,0xF80000,0x1840000,0x15FC0000,0x51F80000,0x72000001,0x72000001,0x13C0000,0x1B40000,0x6BE80000,0x72000001,
+0x1EC0000,0x940F1A,0xE67805EA,0x8E7805EA,0x727805EB,0xD45C034A,0x966001C3,0x7664028A,0x805C034A,0x705C01BE,0x645C034A,0xCA4005EA,0x9E400153,0x7850020D,0x863C01B2,0x72400006,0x664401BD,0x724005EA,0x6A34020F,0x60380286,0x564005ED,0xDC0F1A,0xA61005EB,0x744005EB,0x9200035A,0x741801B6,0x6428034A,0x80000651,0x7000017C,0x620001D5,0x580805ED,0x1BC0F1A,
+0x66000786,0x5C0005BA,0x50000861,0x48000F1E,0xFE6403C8,0xFC880A82,0xFE8C0B9A,0xEE400000,0xAA400003,0x88400002,0x74480023,0x6E3C0025,0xFE440361,0xDE280002,0x7834015B,0x620001D5,0x1380F1A,0xB005EA,0xC8940152,0x88940152,0x72940153,0xB47C01A6,0x8E780001,0x7484002A,0x787801A6,0x6E78004B,0x647801A6,0x10405EA,0x98480153,0x726C0153,0x8C2C01A5,0x72440002,
+0x645401A5,0x7FC05EA,0x70000163,0x620001D5,0x560005ED,0x10405EA,0x98480153,0x726C0153,0x8C2C01A5,0x72440002,0x645401A5,0x7FC05EA,0x70000163,0x620001D5,0x560005ED,0x7FC05EA,0x70000163,0x620001D5,0x560005ED,0x560005ED,0xFE780179,0xF8A003EA,0xFCA803D3,0xEE400000,0xAA400003,0x88400002,0x74540002,0x722C000B,0xFE5C0189,0xDE280001,0x7A240152,0x620001D5,
+0x17405EA,0x7805EA,0x7805EA,0x7805EA,0x7805EA,0xAA5C01A5,0xAA5C01A5,0xAA5C01A5,0x6A5C01A5,0x6A5C01A5,0x565C01A5,0x9E400152,0x9E400152,0x9E400152,0x70400005,0x70400005,0x584C004C,0x5E400152,0x5E400152,0x52400029,0x48400154,0x2B005EA,0x2B005EA,0x2B005EA,0x7C1001A5,0x7C1001A5,0x563401A5,0x6A000163,0x6A000163,0x56080002,0x48180154,0x16805EA,
+0x16805EA,0x4E000239,0x44000248,0x3A0005ED,0xFE580149,0xFE6C03A5,0x7805EA,0xEE400000,0xA8400002,0x88400002,0x7E44000C,0x6A400001,0xFE3C010A,0xDE280001,0x74340152,0x56080002,0xFC05EA,0x940152,0x940152,0x940152,0x940152,0x887C0001,0x887C0001,0x887C0001,0x627C0001,0x627C0001,0x56780001,0xDC0152,0xDC0152,0xDC0152,0x6C4C0001,0x6C4C0001,
+0x56600000,0x1BC0152,0x1BC0152,0x56100000,0x48000154,0xDC0152,0xDC0152,0xDC0152,0x6C4C0001,0x6C4C0001,0x56600000,0x1BC0152,0x1BC0152,0x56100000,0x48000154,0x1BC0152,0x1BC0152,0x56100000,0x48000154,0x48000154,0xFA6C0032,0xFC880062,0x940152,0xEE400000,0xA0480000,0x82480001,0x76500000,0x6A3C0000,0xFA48004A,0xDE280000,0x1380152,0x56100000,
+0x1380152,0xCC01A5,0xACB00001,0x80B00001,0x72AC0002,0x12C01A5,0x8E780000,0x72940001,0x1BF801A5,0x723C0001,0x640001A5,0x12C01A5,0x8E780000,0x72940001,0x1BF801A5,0x723C0001,0x640001A5,0x1BF801A5,0x723C0001,0x640001A5,0x640001A5,0x12C01A5,0x8E780000,0x72940001,0x1BF801A5,0x723C0001,0x640001A5,0x1BF801A5,0x723C0001,0x640001A5,0x640001A5,0x1BF801A5,
+0x723C0001,0x640001A5,0x640001A5,0x640001A5,0xFA8C0091,0xD801A5,0xF8C000B5,0xEA440000,0xB0340000,0x8A380000,0x725C0001,0x72100001,0xFC6C0082,0xE0280000,0x78600000,0x640001A5,0x1AC01A5,0x5C01A5,0x5C01A5,0x5C01A5,0x5C01A5,0x5C01A5,0x5C01A5,0x5C01A5,0x5C01A5,0x5C01A5,0x5C01A5,0x76400000,0x76400000,0x76400000,0x76400000,0x76400000,
+0x76400000,0x4A400000,0x4A400000,0x4A400000,0x3C400000,0x8801A5,0x8801A5,0x8801A5,0x8801A5,0x8801A5,0x8801A5,0x58080000,0x58080000,0x58080000,0x3C240000,0x11401A5,0x11401A5,0x11401A5,0x38000034,0x2E0001A5,0xFE4C0075,0x5C01A5,0x5C01A5,0xEA400000,0xAC400000,0x8C400000,0x8C400000,0x66400000,0xF830003D,0xD6280001,0x5A380000,0x58080000,
+0xC001A5,};
+static const uint32_t g_etc1_to_bc7_m6_table106[] = {
+0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0x2740000,0xF00000,
+0xF00000,0xF00000,0xF00000,0x26000001,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x2540000,0x2540000,0x2540000,0x2740000,0xA80000,0x880001,0x880001,0x880001,0x880001,0x880001,0x880001,0x880001,0x880001,0x880001,0x880001,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,
+0xCC0000,0x1A00000,0x1A00000,0x1A00000,0x44000000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0x1A00000,0x1A00000,0x1A00000,0x44000000,0x1A00000,0x1A00000,0x1A00000,0x44000000,0x44000000,0x940000,0x880001,0x880001,0xA00000,0xAC0000,0xBC0000,0xBC0000,0xE80000,0xA00000,0xAC0000,0x1240000,0x1A00000,
+0x1240000,0xBC0001,0xBC0001,0xBC0001,0xBC0001,0x3180000,0x3180000,0x3180000,0x11FC0000,0x11FC0000,0x5E000000,0x3180000,0x3180000,0x3180000,0x11FC0000,0x11FC0000,0x5E000000,0x11FC0000,0x11FC0000,0x5E000000,0x5E000000,0x3180000,0x3180000,0x3180000,0x11FC0000,0x11FC0000,0x5E000000,0x11FC0000,0x11FC0000,0x5E000000,0x5E000000,0x11FC0000,
+0x11FC0000,0x5E000000,0x5E000000,0x5E000000,0xDC0000,0xCC80000,0xBC0001,0x3000000,0x1400000,0x1940000,0x1D00000,0x25FC0000,0x2EC0000,0x3180000,0x1940000,0x5E000000,0x1940000,0xF80000,0x1700000,0x3DF80000,0x7A000001,0x1700000,0x3DF80000,0x7A000001,0x3DF80000,0x7A000001,0x7A000001,0x1700000,0x3DF80000,0x7A000001,0x3DF80000,0x7A000001,
+0x7A000001,0x3DF80000,0x7A000001,0x7A000001,0x7A000001,0x1700000,0x3DF80000,0x7A000001,0x3DF80000,0x7A000001,0x7A000001,0x3DF80000,0x7A000001,0x7A000001,0x7A000001,0x3DF80000,0x7A000001,0x7A000001,0x7A000001,0x7A000001,0x5340000,0x1080000,0x1080000,0x1A00000,0x23FC0000,0x5BF80000,0x7A000001,0x7A000001,0x1500000,0x1D00000,0x73F80000,0x7A000001,
+0x9FC0000,0xA40F1A,0xEE8805EA,0x968805EA,0x7A8805EB,0xDC6C034A,0x9E7001C3,0x7E74028A,0x886C034A,0x786C01BE,0x6C6C034A,0xD25005EA,0xA6500153,0x8060020D,0x8E4C01B2,0x7A500006,0x6E5401BD,0x7A5005EA,0x7244020F,0x68480286,0x5E5005ED,0xF40F1A,0xAE2005EB,0x7C5005EB,0xA004034A,0x7C2801B6,0x6C38034A,0x8C000611,0x7A000155,0x6A0801C5,0x601805ED,0x1F00F1A,
+0x6C000716,0x66000542,0x5C0007E9,0x50000F1E,0xFE780419,0xF4980ADA,0xF8A00BDB,0xF6500000,0xB2500003,0x90500002,0x7C580023,0x764C0025,0xFE5C03A2,0xE6380002,0x8044015B,0x6A0801C5,0x15C0F1A,0xC005EA,0xD0A40152,0x90A40152,0x7AA40153,0xBC8C01A6,0x96880001,0x7C94002A,0x808801A6,0x7688004B,0x6C8801A6,0x11C05EA,0xA0580153,0x7A7C0153,0x943C01A5,0x7A540002,
+0x6C6401A5,0x13FC05EA,0x7A000155,0x6C0001B5,0x5E0005ED,0x11C05EA,0xA0580153,0x7A7C0153,0x943C01A5,0x7A540002,0x6C6401A5,0x13FC05EA,0x7A000155,0x6C0001B5,0x5E0005ED,0x13FC05EA,0x7A000155,0x6C0001B5,0x5E0005ED,0x5E0005ED,0xFC9001A9,0xFEAC03FE,0xF4B803FE,0xF6500000,0xB2500003,0x90500002,0x7C640002,0x7A3C000B,0xFE7001C3,0xE6380001,0x82340152,0x6C0001B5,
+0x19805EA,0x8805EA,0x8805EA,0x8805EA,0x8805EA,0xB26C01A5,0xB26C01A5,0xB26C01A5,0x726C01A5,0x726C01A5,0x5E6C01A5,0xA6500152,0xA6500152,0xA6500152,0x78500005,0x78500005,0x605C004C,0x66500152,0x66500152,0x5A500029,0x50500154,0xC805EA,0xC805EA,0xC805EA,0x842001A5,0x842001A5,0x5E4401A5,0x78040153,0x78040153,0x5E180002,0x50280154,0x19805EA,
+0x19805EA,0x560001FD,0x4E00020D,0x420005ED,0xFE680164,0xF88003C2,0x8805EA,0xF6500000,0xB0500002,0x90500002,0x8654000C,0x72500001,0xFC4C0123,0xE6380001,0x7C440152,0x5E180002,0x12005EA,0xA40152,0xA40152,0xA40152,0xA40152,0x908C0001,0x908C0001,0x908C0001,0x6A8C0001,0x6A8C0001,0x5E880001,0xF40152,0xF40152,0xF40152,0x745C0001,0x745C0001,
+0x5E700000,0x1F00152,0x1F00152,0x5E200000,0x50000154,0xF40152,0xF40152,0xF40152,0x745C0001,0x745C0001,0x5E700000,0x1F00152,0x1F00152,0x5E200000,0x50000154,0x1F00152,0x1F00152,0x5E200000,0x50000154,0x50000154,0xF680003D,0xF4980071,0xA40152,0xF6500000,0xA8580000,0x8A580001,0x7E600000,0x724C0000,0xF2600055,0xE6380000,0x15C0152,0x5E200000,
+0x15C0152,0xDC01A5,0xB4C00001,0x88C00001,0x7ABC0002,0x14401A5,0x96880000,0x7AA40001,0x27F801A5,0x7A4C0001,0x6C0001A5,0x14401A5,0x96880000,0x7AA40001,0x27F801A5,0x7A4C0001,0x6C0001A5,0x27F801A5,0x7A4C0001,0x6C0001A5,0x6C0001A5,0x14401A5,0x96880000,0x7AA40001,0x27F801A5,0x7A4C0001,0x6C0001A5,0x27F801A5,0x7A4C0001,0x6C0001A5,0x6C0001A5,0x27F801A5,
+0x7A4C0001,0x6C0001A5,0x6C0001A5,0x6C0001A5,0xFAA000A2,0xE801A5,0xFECC00C1,0xF2540000,0xB8440000,0x92480000,0x7A6C0001,0x7A200001,0xF6880091,0xE8380000,0x80700000,0x6C0001A5,0x1D001A5,0x6C01A5,0x6C01A5,0x6C01A5,0x6C01A5,0x6C01A5,0x6C01A5,0x6C01A5,0x6C01A5,0x6C01A5,0x6C01A5,0x7E500000,0x7E500000,0x7E500000,0x7E500000,0x7E500000,
+0x7E500000,0x52500000,0x52500000,0x52500000,0x44500000,0xA001A5,0xA001A5,0xA001A5,0xA001A5,0xA001A5,0xA001A5,0x60180000,0x60180000,0x60180000,0x44340000,0x14401A5,0x14401A5,0x14401A5,0x4200001D,0x360001A5,0xF8600080,0x6C01A5,0x6C01A5,0xF2500000,0xB4500000,0x94500000,0x94500000,0x6E500000,0xFE3C0041,0xDE380001,0x62480000,0x60180000,
+0xE401A5,};
+static const uint32_t g_etc1_to_bc7_m6_table107[] = {
+0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x1200000,
+0x1200000,0x1200000,0x1200000,0x2E000001,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0xA640000,0xA640000,0xA640000,0x28C0000,0xCC0000,0x980001,0x980001,0x980001,0x980001,0x980001,0x980001,0x980001,0x980001,0x980001,0x980001,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,
+0xE40000,0x1D00000,0x1D00000,0x1D00000,0x4C000000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0x1D00000,0x1D00000,0x1D00000,0x4C000000,0x1D00000,0x1D00000,0x1D00000,0x4C000000,0x4C000000,0xA40000,0x980001,0x980001,0xB40000,0xC00000,0xD00000,0xD00000,0x3000000,0xB40000,0xC00000,0x1480000,0x1D00000,
+0x1480000,0xCC0001,0xCC0001,0xCC0001,0xCC0001,0x3300000,0x3300000,0x3300000,0x1DFC0000,0x1DFC0000,0x66000000,0x3300000,0x3300000,0x3300000,0x1DFC0000,0x1DFC0000,0x66000000,0x1DFC0000,0x1DFC0000,0x66000000,0x66000000,0x3300000,0x3300000,0x3300000,0x1DFC0000,0x1DFC0000,0x66000000,0x1DFC0000,0x1DFC0000,0x66000000,0x66000000,0x1DFC0000,
+0x1DFC0000,0x66000000,0x66000000,0x66000000,0xF00000,0xDC0000,0xCC0001,0x1180000,0x1580000,0x1B40000,0x1F80000,0x31F80000,0x3000000,0x3300000,0x1B40000,0x66000000,0x1B40000,0x1080000,0x1880000,0x49F80000,0x82000001,0x1880000,0x49F80000,0x82000001,0x49F80000,0x82000001,0x82000001,0x1880000,0x49F80000,0x82000001,0x49F80000,0x82000001,
+0x82000001,0x49F80000,0x82000001,0x82000001,0x82000001,0x1880000,0x49F80000,0x82000001,0x49F80000,0x82000001,0x82000001,0x49F80000,0x82000001,0x82000001,0x82000001,0x49F80000,0x82000001,0x82000001,0x82000001,0x82000001,0x14C0000,0x5180000,0x5180000,0x1BC0000,0x31FC0000,0x65F80000,0x82000001,0x82000001,0x1680000,0x1F00000,0x7DCC0000,0x82000001,
+0x19FC0000,0xB40F1A,0xF69805EA,0x9E9805EA,0x829805EB,0xE47C034A,0xA68001C3,0x8684028A,0x907C034A,0x807C01BE,0x747C034A,0xDA6005EA,0xAE600153,0x8870020D,0x965C01B2,0x82600006,0x766401BD,0x826005EA,0x7A54020F,0x70580286,0x666005ED,0x10C0F1A,0xB63005EB,0x846005EB,0xA814034A,0x843801B6,0x7448034A,0x980005F1,0x820C0154,0x721801C5,0x682805ED,0xBF80F1A,
+0x780006AE,0x6C0004B6,0x64000795,0x58000F1E,0xFE8C046E,0xFCA80ADA,0xFEAC0BDF,0xFE600000,0xBA600003,0x98600002,0x84680023,0x7E5C0025,0xFE700403,0xEE480002,0x8854015B,0x721801C5,0x17C0F1A,0xD005EA,0xD8B40152,0x98B40152,0x82B40153,0xC49C01A6,0x9E980001,0x84A4002A,0x889801A6,0x7E98004B,0x749801A6,0x13405EA,0xA8680153,0x828C0153,0x9C4C01A5,0x82640002,
+0x747401A5,0x1FF805EA,0x820C0153,0x740001A9,0x660005ED,0x13405EA,0xA8680153,0x828C0153,0x9C4C01A5,0x82640002,0x747401A5,0x1FF805EA,0x820C0153,0x740001A9,0x660005ED,0x1FF805EA,0x820C0153,0x740001A9,0x660005ED,0x660005ED,0xFEA001C8,0xFAC40412,0xFCC803FE,0xFE600000,0xBA600003,0x98600002,0x84740002,0x824C000B,0xFC8401E2,0xEE480001,0x8A440152,0x740001A9,
+0x1B805EA,0x9805EA,0x9805EA,0x9805EA,0x9805EA,0xBA7C01A5,0xBA7C01A5,0xBA7C01A5,0x7A7C01A5,0x7A7C01A5,0x667C01A5,0xAE600152,0xAE600152,0xAE600152,0x80600005,0x80600005,0x686C004C,0x6E600152,0x6E600152,0x62600029,0x58600154,0xE005EA,0xE005EA,0xE005EA,0x8C3001A5,0x8C3001A5,0x665401A5,0x80140153,0x80140153,0x66280002,0x58380154,0x1CC05EA,
+0x1CC05EA,0x600001D5,0x560001C8,0x4A0005ED,0xFA7C0191,0xFE8C03CE,0x9805EA,0xFE600000,0xB8600002,0x98600002,0x8E64000C,0x7A600001,0xFC600152,0xEE480001,0x84540152,0x66280002,0x14005EA,0xB40152,0xB40152,0xB40152,0xB40152,0x989C0001,0x989C0001,0x989C0001,0x729C0001,0x729C0001,0x66980001,0x10C0152,0x10C0152,0x10C0152,0x7C6C0001,0x7C6C0001,
+0x66800000,0xBF80152,0xBF80152,0x66300000,0x58000154,0x10C0152,0x10C0152,0x10C0152,0x7C6C0001,0x7C6C0001,0x66800000,0xBF80152,0xBF80152,0x66300000,0x58000154,0xBF80152,0xBF80152,0x66300000,0x58000154,0x58000154,0xFE90003D,0xFCA80071,0xB40152,0xFE600000,0xB0680000,0x92680001,0x86700000,0x7A5C0000,0xFA700055,0xEE480000,0x17C0152,0x66300000,
+0x17C0152,0xEC01A5,0xBCD00001,0x90D00001,0x82CC0002,0x15C01A5,0x9E980000,0x82B40001,0x33F801A5,0x825C0001,0x740001A5,0x15C01A5,0x9E980000,0x82B40001,0x33F801A5,0x825C0001,0x740001A5,0x33F801A5,0x825C0001,0x740001A5,0x740001A5,0x15C01A5,0x9E980000,0x82B40001,0x33F801A5,0x825C0001,0x740001A5,0x33F801A5,0x825C0001,0x740001A5,0x740001A5,0x33F801A5,
+0x825C0001,0x740001A5,0x740001A5,0x740001A5,0xFCB000A4,0xFC01A5,0xF8E000CA,0xFA640000,0xC0540000,0x9A580000,0x827C0001,0x82300001,0xFE980091,0xF0480000,0x88800000,0x740001A5,0x1F001A5,0x7C01A5,0x7C01A5,0x7C01A5,0x7C01A5,0x7C01A5,0x7C01A5,0x7C01A5,0x7C01A5,0x7C01A5,0x7C01A5,0x86600000,0x86600000,0x86600000,0x86600000,0x86600000,
+0x86600000,0x5A600000,0x5A600000,0x5A600000,0x4C600000,0xB801A5,0xB801A5,0xB801A5,0xB801A5,0xB801A5,0xB801A5,0x68280000,0x68280000,0x68280000,0x4C440000,0x17401A5,0x17401A5,0x17401A5,0x4A000008,0x3E0001A5,0xFE6C0088,0x7C01A5,0x7C01A5,0xFA600000,0xBC600000,0x9C600000,0x9C600000,0x76600000,0xFA50004A,0xE6480001,0x6A580000,0x68280000,
+0x10801A5,};
+static const uint32_t g_etc1_to_bc7_m6_table108[] = {
+0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0x1580000,
+0x1580000,0x1580000,0x1580000,0x38000000,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x4780000,0x4780000,0x4780000,0xA80000,0xF00000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0x1000000,0x1000000,0x1000000,0x1000000,0x1000000,
+0x1000000,0x5F80000,0x5F80000,0x5F80000,0x54000001,0x1000000,0x1000000,0x1000000,0x1000000,0x1000000,0x1000000,0x5F80000,0x5F80000,0x5F80000,0x54000001,0x5F80000,0x5F80000,0x5F80000,0x54000001,0x54000001,0xB80000,0xAC0000,0xAC0000,0xC80000,0xD80000,0x2E80000,0x2E80000,0x1200000,0xC80000,0xD80000,0x16C0000,0x5F80000,
+0x16C0000,0xE00000,0xE00000,0xE00000,0xE00000,0x14C0000,0x14C0000,0x14C0000,0x2BF80000,0x2BF80000,0x6E000001,0x14C0000,0x14C0000,0x14C0000,0x2BF80000,0x2BF80000,0x6E000001,0x2BF80000,0x2BF80000,0x6E000001,0x6E000001,0x14C0000,0x14C0000,0x14C0000,0x2BF80000,0x2BF80000,0x6E000001,0x2BF80000,0x2BF80000,0x6E000001,0x6E000001,0x2BF80000,
+0x2BF80000,0x6E000001,0x6E000001,0x6E000001,0x1040000,0xEEC0000,0xE00000,0x1300000,0x1780000,0x1DC0000,0xFFC0000,0x3DF80000,0x1180000,0x14C0000,0x1DC0000,0x6E000001,0x1DC0000,0x1180001,0x1A40000,0x57F80000,0x8C000000,0x1A40000,0x57F80000,0x8C000000,0x57F80000,0x8C000000,0x8C000000,0x1A40000,0x57F80000,0x8C000000,0x57F80000,0x8C000000,
+0x8C000000,0x57F80000,0x8C000000,0x8C000000,0x8C000000,0x1A40000,0x57F80000,0x8C000000,0x57F80000,0x8C000000,0x8C000000,0x57F80000,0x8C000000,0x8C000000,0x8C000000,0x57F80000,0x8C000000,0x8C000000,0x8C000000,0x8C000000,0x3600000,0x12C0000,0x12C0000,0x1D80000,0x3FFC0000,0x71F40000,0x8C000000,0x8C000000,0x1800000,0xDFC0000,0x85FC0000,0x8C000000,
+0x29FC0000,0xC40F1E,0xFCAC05ED,0xA8A805ED,0x8CA805ED,0xEC90034A,0xB09401C5,0x90980286,0x9890034A,0x8A8C01BD,0x7E90034A,0xE07405EB,0xB6740154,0x9284020F,0x9E6C01B6,0x8A740006,0x7E7801BE,0x8C7005EB,0x8468020D,0x7868028A,0x707005EB,0x3240F1A,0xC04005EB,0x8C7405EA,0xB224034A,0x8E4C01B2,0x7E58034A,0xA40C05EB,0x8C1C0153,0x7C2C01C3,0x703C05EA,0x17FC0F1A,
+0x8400065A,0x7800043A,0x6C00071A,0x62000F1A,0xFEA004CC,0xF6BC0B32,0xF8C00C1E,0xFE74000E,0xC4700004,0xA0740004,0x8E7C0025,0x88700023,0xFE800477,0xFA580000,0x90640159,0x7C2C01C3,0x1A40F1A,0xE005ED,0xE0C80154,0xA0C80154,0x8CC40154,0xCEAC01A5,0xA6AC0002,0x8CB40029,0x90AC01A5,0x86A8004C,0x7EAC01A5,0x15005EA,0xB2780153,0x8C9C0152,0xA46001A5,0x8A740005,
+0x7E8401A5,0x2DF805EA,0x8C180152,0x7E0401A5,0x700005EA,0x15005EA,0xB2780153,0x8C9C0152,0xA46001A5,0x8A740005,0x7E8401A5,0x2DF805EA,0x8C180152,0x7E0401A5,0x700005EA,0x2DF805EA,0x8C180152,0x7E0401A5,0x700005EA,0x700005EA,0xFEB401E6,0xF2D4043D,0xF6DC0428,0xFE780005,0xC4700003,0xA0740003,0x8C840001,0x8A5C000C,0xFE980202,0xFA580000,0x92580152,0x7E0401A5,
+0x1E005EA,0xA805ED,0xA805ED,0xA805ED,0xA805ED,0xC09001A5,0xC09001A5,0xC09001A5,0x829001A5,0x829001A5,0x6E9001A6,0xB6740153,0xB6740153,0xB6740153,0x8A740002,0x8A740002,0x707C004B,0x76740153,0x76740153,0x6A70002A,0x62700153,0xFC05EA,0xFC05EA,0xFC05EA,0x964001A5,0x964001A5,0x6E6801A6,0x88280153,0x88280153,0x703C0001,0x62480152,0x3F805EA,
+0x3F805EA,0x6C0001B2,0x6000019A,0x540005EA,0xFE9001AE,0xFAA403EA,0xA805ED,0xFE740005,0xBE740002,0x9E740002,0x9674000B,0x82700002,0xFE74016D,0xFA580000,0x8C680153,0x703C0001,0x16805EA,0xC40154,0xC40154,0xC40154,0xC40154,0xA4AC0000,0xA4AC0000,0xA4AC0000,0x7CAC0000,0x7CAC0000,0x6EAC0001,0x3240152,0x3240152,0x3240152,0x867C0001,0x867C0001,
+0x6E940001,0x17FC0152,0x17FC0152,0x6E440001,0x62000152,0x3240152,0x3240152,0x3240152,0x867C0001,0x867C0001,0x6E940001,0x17FC0152,0x17FC0152,0x6E440001,0x62000152,0x17FC0152,0x17FC0152,0x6E440001,0x62000152,0x62000152,0xFEA0004A,0xF6BC0080,0xC40154,0xFE780001,0xBA780000,0x9C780000,0x8E840000,0x846C0000,0xF8880062,0xFA580000,0x1A40152,0x6E440001,
+0x1A40152,0xFC01A5,0xC6E00000,0x9AE00000,0x8CE00000,0x17801A5,0xA8A80000,0x8CC40000,0x3FFC01A5,0x8C680000,0x7E0001A5,0x17801A5,0xA8A80000,0x8CC40000,0x3FFC01A5,0x8C680000,0x7E0001A5,0x3FFC01A5,0x8C680000,0x7E0001A5,0x7E0001A5,0x17801A5,0xA8A80000,0x8CC40000,0x3FFC01A5,0x8C680000,0x7E0001A5,0x3FFC01A5,0x8C680000,0x7E0001A5,0x7E0001A5,0x3FFC01A5,
+0x8C680000,0x7E0001A5,0x7E0001A5,0x7E0001A5,0xFAC800B5,0x10C01A5,0xF2F400DD,0xFC7C0002,0xCA640000,0xA26C0000,0x8C8C0000,0x8C3C0000,0xFEAC00A4,0xFA580000,0x90940000,0x7E0001A5,0xDFC01A5,0x9001A5,0x9001A5,0x9001A5,0x9001A5,0x9001A5,0x9001A5,0x9001A5,0x9001A5,0x9001A5,0x9001A5,0x8E740001,0x8E740001,0x8E740001,0x8E740001,0x8E740001,
+0x8E740001,0x62740001,0x62740001,0x62740001,0x54700002,0xD401A5,0xD401A5,0xD401A5,0xD401A5,0xD401A5,0xD401A5,0x703C0000,0x703C0000,0x703C0000,0x54580001,0x1AC01A5,0x1AC01A5,0x1AC01A5,0x54000001,0x460001A5,0xFA840091,0x9001A5,0x9001A5,0xFE740001,0xC2740001,0xA2740001,0xA2740001,0x7E740001,0xF8680055,0xF8580000,0x726C0001,0x703C0000,
+0x12C01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table109[] = {
+0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0x1880000,
+0x1880000,0x1880000,0x1880000,0x40000000,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0x800001,0xC880000,0xC880000,0xC880000,0xC00000,0x1140000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,
+0x1180000,0x11F80000,0x11F80000,0x11F80000,0x5C000001,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x11F80000,0x11F80000,0x11F80000,0x5C000001,0x11F80000,0x11F80000,0x11F80000,0x5C000001,0x5C000001,0xC80000,0xBC0000,0xBC0000,0x4D80000,0xEC0000,0x1000000,0x1000000,0x13C0000,0x4D80000,0xEC0000,0x1900000,0x11F80000,
+0x1900000,0xF00000,0xF00000,0xF00000,0xF00000,0x1640000,0x1640000,0x1640000,0x37F80000,0x37F80000,0x76000001,0x1640000,0x1640000,0x1640000,0x37F80000,0x37F80000,0x76000001,0x37F80000,0x37F80000,0x76000001,0x76000001,0x1640000,0x1640000,0x1640000,0x37F80000,0x37F80000,0x76000001,0x37F80000,0x37F80000,0x76000001,0x76000001,0x37F80000,
+0x37F80000,0x76000001,0x76000001,0x76000001,0x1180000,0x1000000,0xF00000,0x3440000,0x1940000,0x1FC0000,0x1DF80000,0x47FC0000,0x12C0000,0x1640000,0x1FC0000,0x76000001,0x1FC0000,0x1280001,0x1BC0000,0x61FC0000,0x94000000,0x1BC0000,0x61FC0000,0x94000000,0x61FC0000,0x94000000,0x94000000,0x1BC0000,0x61FC0000,0x94000000,0x61FC0000,0x94000000,
+0x94000000,0x61FC0000,0x94000000,0x94000000,0x94000000,0x1BC0000,0x61FC0000,0x94000000,0x61FC0000,0x94000000,0x94000000,0x61FC0000,0x94000000,0x94000000,0x94000000,0x61FC0000,0x94000000,0x94000000,0x94000000,0x94000000,0x3740000,0x73C0000,0x73C0000,0x1F40000,0x4DFC0000,0x7BF40000,0x94000000,0x94000000,0x1940000,0x1DFC0000,0x8FD00000,0x94000000,
+0x39FC0000,0xD40F1E,0xFEBC05F1,0xB0B805ED,0x94B805ED,0xF4A0034A,0xB8A401C5,0x98A80286,0xA0A0034A,0x929C01BD,0x86A0034A,0xE88405EB,0xBE840154,0x9A94020F,0xA67C01B6,0x92840006,0x868801BE,0x948005EB,0x8C78020D,0x8078028A,0x788005EB,0x33C0F1A,0xC85005EB,0x948405EA,0xBA34034A,0x965C01B2,0x8668034A,0xAC1C05EB,0x942C0153,0x843C01C3,0x784C05EA,0x23FC0F1A,
+0x8E000629,0x820003F2,0x760006D7,0x6A000F1A,0xFEB40537,0xFECC0B32,0xFECC0C36,0xFE880026,0xCC800004,0xA8840004,0x968C0025,0x90800023,0xFE9804C6,0xFC6C0006,0x98740159,0x843C01C3,0x1C80F1A,0xF005ED,0xE8D80154,0xA8D80154,0x94D40154,0xD6BC01A5,0xAEBC0002,0x94C40029,0x98BC01A5,0x8EB8004C,0x86BC01A5,0x16805EA,0xBA880153,0x94AC0152,0xAC7001A5,0x92840005,
+0x869401A5,0x39F805EA,0x94280152,0x861401A5,0x780005EA,0x16805EA,0xBA880153,0x94AC0152,0xAC7001A5,0x92840005,0x869401A5,0x39F805EA,0x94280152,0x861401A5,0x780005EA,0x39F805EA,0x94280152,0x861401A5,0x780005EA,0x780005EA,0xFAC80226,0xFAE4043D,0xFEEC0428,0xFC900012,0xCC800003,0xA8840003,0x94940001,0x926C000C,0xFEAC0244,0xFE6C0002,0x9A680152,0x861401A5,
+0x3FC05EA,0xB805ED,0xB805ED,0xB805ED,0xB805ED,0xC8A001A5,0xC8A001A5,0xC8A001A5,0x8AA001A5,0x8AA001A5,0x76A001A6,0xBE840153,0xBE840153,0xBE840153,0x92840002,0x92840002,0x788C004B,0x7E840153,0x7E840153,0x7280002A,0x6A800153,0x11405EA,0x11405EA,0x11405EA,0x9E5001A5,0x9E5001A5,0x767801A6,0x90380153,0x90380153,0x784C0001,0x6A580152,0xFF805EA,
+0xFF805EA,0x760001A6,0x6800017E,0x5C0005EA,0xFEA001CB,0xFEAC040A,0xB805ED,0xFE88000D,0xC6840002,0xA6840002,0x9E84000B,0x8A800002,0xFE8001A3,0xFA6C0002,0x94780153,0x784C0001,0x18C05EA,0xD40154,0xD40154,0xD40154,0xD40154,0xACBC0000,0xACBC0000,0xACBC0000,0x84BC0000,0x84BC0000,0x76BC0001,0x33C0152,0x33C0152,0x33C0152,0x8E8C0001,0x8E8C0001,
+0x76A40001,0x23FC0152,0x23FC0152,0x76540001,0x6A000152,0x33C0152,0x33C0152,0x33C0152,0x8E8C0001,0x8E8C0001,0x76A40001,0x23FC0152,0x23FC0152,0x76540001,0x6A000152,0x23FC0152,0x23FC0152,0x76540001,0x6A000152,0x6A000152,0xFAB40055,0xFECC0080,0xD40154,0xFE880004,0xC2880000,0xA4880000,0x96940000,0x8C7C0000,0xFE94006A,0xFA6C0001,0x1C80152,0x76540001,
+0x1C80152,0x10C01A5,0xCEF00000,0xA2F00000,0x94F00000,0x19001A5,0xB0B80000,0x94D40000,0x4BFC01A5,0x94780000,0x860001A5,0x19001A5,0xB0B80000,0x94D40000,0x4BFC01A5,0x94780000,0x860001A5,0x4BFC01A5,0x94780000,0x860001A5,0x860001A5,0x19001A5,0xB0B80000,0x94D40000,0x4BFC01A5,0x94780000,0x860001A5,0x4BFC01A5,0x94780000,0x860001A5,0x860001A5,0x4BFC01A5,
+0x94780000,0x860001A5,0x860001A5,0x860001A5,0xF2E000C8,0x12001A5,0xFB0400DD,0xFE940005,0xD2740000,0xAA7C0000,0x949C0000,0x944C0000,0xF4C800B5,0xFE6C0001,0x98A40000,0x860001A5,0x1DF801A5,0xA001A5,0xA001A5,0xA001A5,0xA001A5,0xA001A5,0xA001A5,0xA001A5,0xA001A5,0xA001A5,0xA001A5,0x96840001,0x96840001,0x96840001,0x96840001,0x96840001,
+0x96840001,0x6A840001,0x6A840001,0x6A840001,0x5C800002,0xEC01A5,0xEC01A5,0xEC01A5,0xEC01A5,0xEC01A5,0xEC01A5,0x784C0000,0x784C0000,0x784C0000,0x5C680001,0x1DC01A5,0x1DC01A5,0x1DC01A5,0x5C100001,0x4E0001A5,0xF29400A2,0xA001A5,0xA001A5,0xFE840002,0xCA840001,0xAA840001,0xAA840001,0x86840001,0xFE740059,0xF86C0001,0x7A7C0001,0x784C0000,
+0x15001A5,};
+static const uint32_t g_etc1_to_bc7_m6_table110[] = {
+0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0x1B80000,
+0x1B80000,0x1B80000,0x1B80000,0x48000000,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x900001,0x9C0000,0x9C0000,0x9C0000,0xD80000,0x1340000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0xCC0000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,
+0x1300000,0x1DF40000,0x1DF40000,0x1DF40000,0x64000001,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1DF40000,0x1DF40000,0x1DF40000,0x64000001,0x1DF40000,0x1DF40000,0x1DF40000,0x64000001,0x64000001,0x4D80000,0xCC0000,0xCC0000,0xEC0000,0x1000000,0x1140000,0x1140000,0x3540000,0xEC0000,0x1000000,0x1B00000,0x1DF40000,
+0x1B00000,0x1000000,0x1000000,0x1000000,0x1000000,0x17C0000,0x17C0000,0x17C0000,0x43F80000,0x43F80000,0x7E000001,0x17C0000,0x17C0000,0x17C0000,0x43F80000,0x43F80000,0x7E000001,0x43F80000,0x43F80000,0x7E000001,0x7E000001,0x17C0000,0x17C0000,0x17C0000,0x43F80000,0x43F80000,0x7E000001,0x43F80000,0x43F80000,0x7E000001,0x7E000001,0x43F80000,
+0x43F80000,0x7E000001,0x7E000001,0x7E000001,0x3280000,0x1100000,0x1000000,0x15C0000,0x3AC0000,0x11FC0000,0x29FC0000,0x53F80000,0x1400000,0x17C0000,0x11FC0000,0x7E000001,0x11FC0000,0x1380001,0x3D00000,0x6DFC0000,0x9C000000,0x3D00000,0x6DFC0000,0x9C000000,0x6DFC0000,0x9C000000,0x9C000000,0x3D00000,0x6DFC0000,0x9C000000,0x6DFC0000,0x9C000000,
+0x9C000000,0x6DFC0000,0x9C000000,0x9C000000,0x9C000000,0x3D00000,0x6DFC0000,0x9C000000,0x6DFC0000,0x9C000000,0x9C000000,0x6DFC0000,0x9C000000,0x9C000000,0x9C000000,0x6DFC0000,0x9C000000,0x9C000000,0x9C000000,0x9C000000,0x3880000,0xF4C0000,0xF4C0000,0xFFC0000,0x5BFC0000,0x85F40000,0x9C000000,0x9C000000,0x1AC0000,0x2FFC0000,0x97E00000,0x9C000000,
+0x47FC0000,0xE40F1E,0xFCCC0606,0xB8C805ED,0x9CC805ED,0xFCB0034A,0xC0B401C5,0xA0B80286,0xA8B0034A,0x9AAC01BD,0x8EB0034A,0xF09405EB,0xC6940154,0xA2A4020F,0xAE8C01B6,0x9A940006,0x8E9801BE,0x9C9005EB,0x9488020D,0x8888028A,0x809005EB,0x1540F1A,0xD06005EB,0x9C9405EA,0xC244034A,0x9E6C01B2,0x8E78034A,0xB42C05EB,0x9C3C0153,0x8C4C01C3,0x805C05EA,0x2FFC0F1A,
+0x98000606,0x8A00039E,0x7E000686,0x72000F1A,0xFEC405AE,0xF6DC0B8E,0xF8E00C65,0xFE9C0054,0xD4900004,0xB0940004,0x9E9C0025,0x98900023,0xFCB00557,0xFE800014,0xA0840159,0x8C4C01C3,0x1E80F1A,0x10005ED,0xF0E80154,0xB0E80154,0x9CE40154,0xDECC01A5,0xB6CC0002,0x9CD40029,0xA0CC01A5,0x96C8004C,0x8ECC01A5,0x18005EA,0xC2980153,0x9CBC0152,0xB48001A5,0x9A940005,
+0x8EA401A5,0x45F805EA,0x9C380152,0x8E2401A5,0x800005EA,0x18005EA,0xC2980153,0x9CBC0152,0xB48001A5,0x9A940005,0x8EA401A5,0x45F805EA,0x9C380152,0x8E2401A5,0x800005EA,0x45F805EA,0x9C380152,0x8E2401A5,0x800005EA,0x800005EA,0xFED8024B,0xF4F80465,0xF6FC0455,0xFEA40029,0xD4900003,0xB0940003,0x9CA40001,0x9A7C000C,0xFCC00269,0xFE840008,0xA2780152,0x8E2401A5,
+0x13FC05EA,0xC805ED,0xC805ED,0xC805ED,0xC805ED,0xD0B001A5,0xD0B001A5,0xD0B001A5,0x92B001A5,0x92B001A5,0x7EB001A6,0xC6940153,0xC6940153,0xC6940153,0x9A940002,0x9A940002,0x809C004B,0x86940153,0x86940153,0x7A90002A,0x72900153,0x12C05EA,0x12C05EA,0x12C05EA,0xA66001A5,0xA66001A5,0x7E8801A6,0x98480153,0x98480153,0x805C0001,0x72680152,0x1BF805EA,
+0x1BF805EA,0x7E0801A6,0x72000162,0x640005EA,0xFAB40206,0xFAC40411,0xC805ED,0xFE98001A,0xCE940002,0xAE940002,0xA694000B,0x92900002,0xFE9401BA,0xFC7C000B,0x9C880153,0x805C0001,0x1AC05EA,0xE40154,0xE40154,0xE40154,0xE40154,0xB4CC0000,0xB4CC0000,0xB4CC0000,0x8CCC0000,0x8CCC0000,0x7ECC0001,0x1540152,0x1540152,0x1540152,0x969C0001,0x969C0001,
+0x7EB40001,0x2FFC0152,0x2FFC0152,0x7E640001,0x72000152,0x1540152,0x1540152,0x1540152,0x969C0001,0x969C0001,0x7EB40001,0x2FFC0152,0x2FFC0152,0x7E640001,0x72000152,0x2FFC0152,0x2FFC0152,0x7E640001,0x72000152,0x72000152,0xF6C80062,0xF6DC0091,0xE40154,0xFCA00008,0xCA980000,0xAC980000,0x9EA40000,0x948C0000,0xFAAC0071,0xFE800002,0x1E80152,0x7E640001,
+0x1E80152,0x11C01A5,0xD7000000,0xAB000000,0x9D000000,0x1A801A5,0xB8C80000,0x9CE40000,0x57FC01A5,0x9C880000,0x8E0001A5,0x1A801A5,0xB8C80000,0x9CE40000,0x57FC01A5,0x9C880000,0x8E0001A5,0x57FC01A5,0x9C880000,0x8E0001A5,0x8E0001A5,0x1A801A5,0xB8C80000,0x9CE40000,0x57FC01A5,0x9C880000,0x8E0001A5,0x57FC01A5,0x9C880000,0x8E0001A5,0x8E0001A5,0x57FC01A5,
+0x9C880000,0x8E0001A5,0x8E0001A5,0x8E0001A5,0xFAF000C8,0x13001A5,0xF31400F4,0xFCAC000D,0xDA840000,0xB28C0000,0x9CAC0000,0x9C5C0000,0xFCD800B5,0xFE880002,0xA0B40000,0x8E0001A5,0x2BFC01A5,0xB001A5,0xB001A5,0xB001A5,0xB001A5,0xB001A5,0xB001A5,0xB001A5,0xB001A5,0xB001A5,0xB001A5,0x9E940001,0x9E940001,0x9E940001,0x9E940001,0x9E940001,
+0x9E940001,0x72940001,0x72940001,0x72940001,0x64900002,0x10401A5,0x10401A5,0x10401A5,0x10401A5,0x10401A5,0x10401A5,0x805C0000,0x805C0000,0x805C0000,0x64780001,0x5FC01A5,0x5FC01A5,0x5FC01A5,0x64200001,0x560001A5,0xFAA400A2,0xB001A5,0xB001A5,0xF894000A,0xD2940001,0xB2940001,0xB2940001,0x8E940001,0xFA880064,0xFC7C0002,0x828C0001,0x805C0000,
+0x17001A5,};
+static const uint32_t g_etc1_to_bc7_m6_table111[] = {
+0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,0x1E80000,
+0x1E80000,0x1E80000,0x1E80000,0x50000000,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xAC0000,0xAC0000,0xAC0000,0xF00000,0x1580000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0x3440000,0x3440000,0x3440000,0x3440000,0x3440000,
+0x3440000,0x27FC0000,0x27FC0000,0x27FC0000,0x6C000001,0x3440000,0x3440000,0x3440000,0x3440000,0x3440000,0x3440000,0x27FC0000,0x27FC0000,0x27FC0000,0x6C000001,0x27FC0000,0x27FC0000,0x27FC0000,0x6C000001,0x6C000001,0xCE80000,0xDC0000,0xDC0000,0x1000000,0x1140000,0x12C0000,0x12C0000,0x1700000,0x1000000,0x1140000,0x1D40000,0x27FC0000,
+0x1D40000,0x1100000,0x1100000,0x1100000,0x1100000,0x1940000,0x1940000,0x1940000,0x4FF80000,0x4FF80000,0x86000001,0x1940000,0x1940000,0x1940000,0x4FF80000,0x4FF80000,0x86000001,0x4FF80000,0x4FF80000,0x86000001,0x86000001,0x1940000,0x1940000,0x1940000,0x4FF80000,0x4FF80000,0x86000001,0x4FF80000,0x4FF80000,0x86000001,0x86000001,0x4FF80000,
+0x4FF80000,0x86000001,0x86000001,0x86000001,0x13C0000,0x9200000,0x1100000,0x3700000,0x1C80000,0x1FFC0000,0x37FC0000,0x5DFC0000,0x1540000,0x1940000,0x1FFC0000,0x86000001,0x1FFC0000,0x1480001,0x3E80000,0x79FC0000,0xA4000000,0x3E80000,0x79FC0000,0xA4000000,0x79FC0000,0xA4000000,0xA4000000,0x3E80000,0x79FC0000,0xA4000000,0x79FC0000,0xA4000000,
+0xA4000000,0x79FC0000,0xA4000000,0xA4000000,0xA4000000,0x3E80000,0x79FC0000,0xA4000000,0x79FC0000,0xA4000000,0xA4000000,0x79FC0000,0xA4000000,0xA4000000,0xA4000000,0x79FC0000,0xA4000000,0xA4000000,0xA4000000,0xA4000000,0x39C0000,0x1600000,0x1600000,0x23FC0000,0x69F80000,0x8FF40000,0xA4000000,0xA4000000,0x1C00000,0x41FC0000,0x9FF00000,0xA4000000,
+0x57FC0000,0xF40F1E,0xFEDC061E,0xC0D805ED,0xA4D805ED,0xFCC00356,0xC8C401C5,0xA8C80286,0xB0C0034A,0xA2BC01BD,0x96C0034A,0xF8A405EB,0xCEA40154,0xAAB4020F,0xB69C01B6,0xA2A40006,0x96A801BE,0xA4A005EB,0x9C98020D,0x9098028A,0x88A005EB,0x16C0F1A,0xD87005EB,0xA4A405EA,0xCA54034A,0xA67C01B2,0x9688034A,0xBC3C05EB,0xA44C0153,0x945C01C3,0x886C05EA,0x3BFC0F1A,
+0xA20005F1,0x94000376,0x8400065A,0x7A000F1A,0xFED80614,0xFEEC0B8E,0xFEEC0C81,0xFEB00093,0xDCA00004,0xB8A40004,0xA6AC0025,0xA0A00023,0xFEBC05A3,0xFE94003E,0xA8940159,0x945C01C3,0x7FC0F1A,0x11005ED,0xF8F80154,0xB8F80154,0xA4F40154,0xE6DC01A5,0xBEDC0002,0xA4E40029,0xA8DC01A5,0x9ED8004C,0x96DC01A5,0x19805EA,0xCAA80153,0xA4CC0152,0xBC9001A5,0xA2A40005,
+0x96B401A5,0x51F805EA,0xA4480152,0x963401A5,0x880005EA,0x19805EA,0xCAA80153,0xA4CC0152,0xBC9001A5,0xA2A40005,0x96B401A5,0x51F805EA,0xA4480152,0x963401A5,0x880005EA,0x51F805EA,0xA4480152,0x963401A5,0x880005EA,0x880005EA,0xFEEC028B,0xFD080465,0xFF0C0455,0xFCBC0048,0xDCA00003,0xB8A40003,0xA4B40001,0xA28C000C,0xFCD80289,0xFE98001E,0xAA880152,0x963401A5,
+0x21FC05EA,0xD805ED,0xD805ED,0xD805ED,0xD805ED,0xD8C001A5,0xD8C001A5,0xD8C001A5,0x9AC001A5,0x9AC001A5,0x86C001A6,0xCEA40153,0xCEA40153,0xCEA40153,0xA2A40002,0xA2A40002,0x88AC004B,0x8EA40153,0x8EA40153,0x82A0002A,0x7AA00153,0x14405EA,0x14405EA,0x14405EA,0xAE7001A5,0xAE7001A5,0x869801A6,0xA0580153,0xA0580153,0x886C0001,0x7A780152,0x27F805EA,
+0x27F805EA,0x861801A6,0x7A000156,0x6C0005EA,0xFAC40225,0xFECC0439,0xD805ED,0xFEAC0032,0xD6A40002,0xB6A40002,0xAEA4000B,0x9AA00002,0xFAAC01E2,0xFE900015,0xA4980153,0x886C0001,0x1D005EA,0xF40154,0xF40154,0xF40154,0xF40154,0xBCDC0000,0xBCDC0000,0xBCDC0000,0x94DC0000,0x94DC0000,0x86DC0001,0x16C0152,0x16C0152,0x16C0152,0x9EAC0001,0x9EAC0001,
+0x86C40001,0x3BFC0152,0x3BFC0152,0x86740001,0x7A000152,0x16C0152,0x16C0152,0x16C0152,0x9EAC0001,0x9EAC0001,0x86C40001,0x3BFC0152,0x3BFC0152,0x86740001,0x7A000152,0x3BFC0152,0x3BFC0152,0x86740001,0x7A000152,0x7A000152,0xFED80062,0xFEEC0091,0xF40154,0xFEB4000D,0xD2A80000,0xB4A80000,0xA6B40000,0x9C9C0000,0xFCC00080,0xFE980005,0x7FC0152,0x86740001,
+0x7FC0152,0x12C01A5,0xDF100000,0xB3100000,0xA5100000,0x1C001A5,0xC0D80000,0xA4F40000,0x63FC01A5,0xA4980000,0x960001A5,0x1C001A5,0xC0D80000,0xA4F40000,0x63FC01A5,0xA4980000,0x960001A5,0x63FC01A5,0xA4980000,0x960001A5,0x960001A5,0x1C001A5,0xC0D80000,0xA4F40000,0x63FC01A5,0xA4980000,0x960001A5,0x63FC01A5,0xA4980000,0x960001A5,0x960001A5,0x63FC01A5,
+0xA4980000,0x960001A5,0x960001A5,0x960001A5,0xF70400DD,0x14001A5,0xFB2400F4,0xFEC00014,0xE2940000,0xBA9C0000,0xA4BC0000,0xA46C0000,0xFCEC00CA,0xFEA0000A,0xA8C40000,0x960001A5,0x3BFC01A5,0xC001A5,0xC001A5,0xC001A5,0xC001A5,0xC001A5,0xC001A5,0xC001A5,0xC001A5,0xC001A5,0xC001A5,0xA6A40001,0xA6A40001,0xA6A40001,0xA6A40001,0xA6A40001,
+0xA6A40001,0x7AA40001,0x7AA40001,0x7AA40001,0x6CA00002,0x11C01A5,0x11C01A5,0x11C01A5,0x11C01A5,0x11C01A5,0x11C01A5,0x886C0000,0x886C0000,0x886C0000,0x6C880001,0x11FC01A5,0x11FC01A5,0x11FC01A5,0x6C300001,0x5E0001A5,0xF2B400B5,0xC001A5,0xC001A5,0xFCA8000D,0xDAA40001,0xBAA40001,0xBAA40001,0x96A40001,0xFC9C0071,0xFC900005,0x8A9C0001,0x886C0000,
+0x19401A5,};
+static const uint32_t g_etc1_to_bc7_m6_table112[] = {
+0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0xBF80000,
+0xBF80000,0xBF80000,0xBF80000,0x58000001,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xC00000,0xC00000,0xC00000,0x10C0000,0x17C0000,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0xEC0001,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,
+0x1600000,0x35FC0000,0x35FC0000,0x35FC0000,0x76000000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x35FC0000,0x35FC0000,0x35FC0000,0x76000000,0x35FC0000,0x35FC0000,0x35FC0000,0x76000000,0x76000000,0x6FC0000,0xEC0001,0xEC0001,0x1140000,0x3280000,0x1440000,0x1440000,0x1900000,0x1140000,0x3280000,0x1F80000,0x35FC0000,
+0x1F80000,0x1200001,0x1200001,0x1200001,0x1200001,0x1B00000,0x1B00000,0x1B00000,0x5DF40000,0x5DF40000,0x90000000,0x1B00000,0x1B00000,0x1B00000,0x5DF40000,0x5DF40000,0x90000000,0x5DF40000,0x5DF40000,0x90000000,0x90000000,0x1B00000,0x1B00000,0x1B00000,0x5DF40000,0x5DF40000,0x90000000,0x5DF40000,0x5DF40000,0x90000000,0x90000000,0x5DF40000,
+0x5DF40000,0x90000000,0x90000000,0x90000000,0x1500000,0x3340000,0x1200001,0x3880000,0x1E80000,0x31FC0000,0x47F80000,0x69FC0000,0x16C0000,0x1B00000,0x31FC0000,0x90000000,0x31FC0000,0x15C0000,0x9FC0000,0x87FC0000,0xAC000001,0x9FC0000,0x87FC0000,0xAC000001,0x87FC0000,0xAC000001,0xAC000001,0x9FC0000,0x87FC0000,0xAC000001,0x87FC0000,0xAC000001,
+0xAC000001,0x87FC0000,0xAC000001,0xAC000001,0xAC000001,0x9FC0000,0x87FC0000,0xAC000001,0x87FC0000,0xAC000001,0xAC000001,0x87FC0000,0xAC000001,0xAC000001,0xAC000001,0x87FC0000,0xAC000001,0xAC000001,0xAC000001,0xAC000001,0x1B40000,0x1740000,0x1740000,0x39FC0000,0x77FC0000,0x99FC0000,0xAC000001,0xAC000001,0x1D80000,0x53FC0000,0xA9E40000,0xAC000001,
+0x67FC0000,0x1080F1A,0xFCF0065A,0xC8EC05EA,0xACEC05EB,0xFED40376,0xD0D401C3,0xB0D8028A,0xBAD0034A,0xAAD001BE,0x9ED0034A,0xFCB805F1,0xD8B40153,0xB2C4020D,0xC0B001B2,0xACB40006,0xA0B801BD,0xACB405EA,0xA4A8020F,0x9AAC0286,0x90B405ED,0x1880F1A,0xE08405EB,0xAEB405EB,0xD268034A,0xAE8C01B6,0x9E9C034A,0xC64805EB,0xAC600154,0x9C6C01C5,0x927C05ED,0x49F80F1A,
+0xAC0805EB,0x9C000356,0x9000061E,0x82000F1E,0xFEE4068A,0xF9000BEA,0xFB040CAA,0xFEC400EA,0xE4B40003,0xC2B40002,0xAEBC0023,0xA8B00025,0xFED40612,0xFEB0008D,0xB2A8015B,0x9C6C01C5,0x19FC0F1A,0x12405EA,0xFD080156,0xC3080152,0xAD080153,0xEEF001A6,0xC8EC0001,0xAEF8002A,0xB2EC01A6,0xA8EC004B,0x9EEC01A6,0x3B005EA,0xD2BC0153,0xACE00153,0xC6A001A5,0xACB80002,
+0x9EC801A5,0x5DFC05EA,0xAC600153,0x9E4801A5,0x900005ED,0x3B005EA,0xD2BC0153,0xACE00153,0xC6A001A5,0xACB80002,0x9EC801A5,0x5DFC05EA,0xAC600153,0x9E4801A5,0x900005ED,0x5DFC05EA,0xAC600153,0x9E4801A5,0x900005ED,0x900005ED,0xFF0002B2,0xF71C0492,0xF9200483,0xFED40072,0xE4B40003,0xC2B40002,0xAEC80002,0xACA0000B,0xFCEC02D4,0xFEB80048,0xB4980152,0x9E4801A5,
+0x33FC05EA,0xEC05EA,0xEC05EA,0xEC05EA,0xEC05EA,0xE4D001A5,0xE4D001A5,0xE4D001A5,0xA4D001A5,0xA4D001A5,0x90D001A5,0xD8B40152,0xD8B40152,0xD8B40152,0xAAB40005,0xAAB40005,0x92C0004C,0x98B40152,0x98B40152,0x8CB40029,0x82B40154,0x35C05EA,0x35C05EA,0x35C05EA,0xB68401A5,0xB68401A5,0x90A801A5,0xAA680153,0xAA680153,0x907C0002,0x828C0154,0x33FC05EA,
+0x33FC05EA,0x902801A5,0x820C0154,0x740005ED,0xFED80248,0xFAE4043D,0xEC05EA,0xFEBC0054,0xE2B40002,0xC2B40002,0xB8B8000C,0xA4B40001,0xFEBC020C,0xFEA40031,0xAEA80152,0x907C0002,0x1F405EA,0x1080152,0x1080152,0x1080152,0x1080152,0xC2F00001,0xC2F00001,0xC2F00001,0x9CF00001,0x9CF00001,0x90EC0001,0x1880152,0x1880152,0x1880152,0xA6C00001,0xA6C00001,
+0x90D40000,0x49F80152,0x49F80152,0x90840000,0x82000154,0x1880152,0x1880152,0x1880152,0xA6C00001,0xA6C00001,0x90D40000,0x49F80152,0x49F80152,0x90840000,0x82000154,0x49F80152,0x49F80152,0x90840000,0x82000154,0x82000154,0xFAEC0071,0xF90000A2,0x1080152,0xF6CC0019,0xDABC0000,0xBCBC0001,0xB0C40000,0xA4B00000,0xFED00088,0xFEB0000D,0x19FC0152,0x90840000,
+0x19FC0152,0x14001A5,0xE7240001,0xBB240001,0xAD200002,0x1D801A5,0xC8EC0000,0xAD080001,0x71F801A5,0xACB00001,0x9E0001A5,0x1D801A5,0xC8EC0000,0xAD080001,0x71F801A5,0xACB00001,0x9E0001A5,0x71F801A5,0xACB00001,0x9E0001A5,0x9E0001A5,0x1D801A5,0xC8EC0000,0xAD080001,0x71F801A5,0xACB00001,0x9E0001A5,0x71F801A5,0xACB00001,0x9E0001A5,0x9E0001A5,0x71F801A5,
+0xACB00001,0x9E0001A5,0x9E0001A5,0x9E0001A5,0xFF1400E1,0x15401A5,0xF5380109,0xFED80028,0xEAA80000,0xC4AC0000,0xACD00001,0xAC840001,0xF70800DD,0xFEC00012,0xB2D40000,0x9E0001A5,0x4BFC01A5,0xD001A5,0xD001A5,0xD001A5,0xD001A5,0xD001A5,0xD001A5,0xD001A5,0xD001A5,0xD001A5,0xD001A5,0xB0B40000,0xB0B40000,0xB0B40000,0xB0B40000,0xB0B40000,
+0xB0B40000,0x84B40000,0x84B40000,0x84B40000,0x76B40000,0x13401A5,0x13401A5,0x13401A5,0x13401A5,0x13401A5,0x13401A5,0x927C0000,0x927C0000,0x927C0000,0x76980000,0x1FF801A5,0x1FF801A5,0x1FF801A5,0x763C0000,0x680001A5,0xFCC800B5,0xD001A5,0xD001A5,0xFCB80014,0xE6B40000,0xC6B40000,0xC6B40000,0xA0B40000,0xF8B00080,0xFEA0000A,0x94AC0000,0x927C0000,
+0x1B801A5,};
+static const uint32_t g_etc1_to_bc7_m6_table113[] = {
+0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x17F80000,
+0x17F80000,0x17F80000,0x17F80000,0x60000001,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xD00000,0xD00000,0xD00000,0x1240000,0x1A00000,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0xFC0001,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,
+0x1780000,0x41FC0000,0x41FC0000,0x41FC0000,0x7E000000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x41FC0000,0x41FC0000,0x41FC0000,0x7E000000,0x41FC0000,0x41FC0000,0x41FC0000,0x7E000000,0x7E000000,0xF0C0000,0xFC0001,0xFC0001,0x1280000,0x33C0000,0x1580000,0x1580000,0x1AC0000,0x1280000,0x33C0000,0xFFC0000,0x41FC0000,
+0xFFC0000,0x1300001,0x1300001,0x1300001,0x1300001,0x3C40000,0x3C40000,0x3C40000,0x67FC0000,0x67FC0000,0x98000000,0x3C40000,0x3C40000,0x3C40000,0x67FC0000,0x67FC0000,0x98000000,0x67FC0000,0x67FC0000,0x98000000,0x98000000,0x3C40000,0x3C40000,0x3C40000,0x67FC0000,0x67FC0000,0x98000000,0x67FC0000,0x67FC0000,0x98000000,0x98000000,0x67FC0000,
+0x67FC0000,0x98000000,0x98000000,0x98000000,0x1640000,0xB440000,0x1300001,0x1A00000,0x5FC0000,0x3FFC0000,0x55F80000,0x75F80000,0x1800000,0x3C40000,0x3FFC0000,0x98000000,0x3FFC0000,0x16C0000,0x23FC0000,0x93FC0000,0xB4000001,0x23FC0000,0x93FC0000,0xB4000001,0x93FC0000,0xB4000001,0xB4000001,0x23FC0000,0x93FC0000,0xB4000001,0x93FC0000,0xB4000001,
+0xB4000001,0x93FC0000,0xB4000001,0xB4000001,0xB4000001,0x23FC0000,0x93FC0000,0xB4000001,0x93FC0000,0xB4000001,0xB4000001,0x93FC0000,0xB4000001,0xB4000001,0xB4000001,0x93FC0000,0xB4000001,0xB4000001,0xB4000001,0xB4000001,0x1C80000,0x1840000,0x1840000,0x4DFC0000,0x85FC0000,0xA5F00000,0xB4000001,0xB4000001,0x1F00000,0x65FC0000,0xB1F40000,0xB4000001,
+0x77FC0000,0x1180F1A,0xFF000686,0xD0FC05EA,0xB4FC05EB,0xFEE8039E,0xD8E401C3,0xB8E8028A,0xC2E0034A,0xB2E001BE,0xA6E0034A,0xFCCC0606,0xE0C40153,0xBAD4020D,0xC8C001B2,0xB4C40006,0xA8C801BD,0xB4C405EA,0xACB8020F,0xA2BC0286,0x98C405ED,0x1A00F1A,0xE89405EB,0xB6C405EB,0xDA78034A,0xB69C01B6,0xA6AC034A,0xCE5805EB,0xB4700154,0xA47C01C5,0x9A8C05ED,0x55F80F1A,
+0xB41805EB,0xA600034A,0x98000606,0x8A000F1E,0xFEF806F7,0xFF0C0BFA,0xFF0C0CEA,0xFED80150,0xECC40003,0xCAC40002,0xB6CC0023,0xB0C00025,0xFEE006BA,0xFEC000D3,0xBAB8015B,0xA47C01C5,0x27FC0F1A,0x13405EA,0xFF180162,0xCB180152,0xB5180153,0xF70001A6,0xD0FC0001,0xB708002A,0xBAFC01A6,0xB0FC004B,0xA6FC01A6,0x1C805EA,0xDACC0153,0xB4F00153,0xCEB001A5,0xB4C80002,
+0xA6D801A5,0x69FC05EA,0xB4700153,0xA65801A5,0x980005ED,0x1C805EA,0xDACC0153,0xB4F00153,0xCEB001A5,0xB4C80002,0xA6D801A5,0x69FC05EA,0xB4700153,0xA65801A5,0x980005ED,0x69FC05EA,0xB4700153,0xA65801A5,0x980005ED,0x980005ED,0xFF1402D5,0xFF2C0492,0xFF2C048B,0xFCE800A5,0xECC40003,0xCAC40002,0xB6D80002,0xB4B0000B,0xFEF802F6,0xFEC80065,0xBCA80152,0xA65801A5,
+0x41FC05EA,0xFC05EA,0xFC05EA,0xFC05EA,0xFC05EA,0xECE001A5,0xECE001A5,0xECE001A5,0xACE001A5,0xACE001A5,0x98E001A5,0xE0C40152,0xE0C40152,0xE0C40152,0xB2C40005,0xB2C40005,0x9AD0004C,0xA0C40152,0xA0C40152,0x94C40029,0x8AC40154,0x37405EA,0x37405EA,0x37405EA,0xBE9401A5,0xBE9401A5,0x98B801A5,0xB2780153,0xB2780153,0x988C0002,0x8A9C0154,0x3FFC05EA,
+0x3FFC05EA,0x983801A5,0x8A1C0154,0x7C0005ED,0xFEE80269,0xF4F80466,0xFC05EA,0xFED40071,0xEAC40002,0xCAC40002,0xC0C8000C,0xACC40001,0xFED00229,0xFEBC0048,0xB6B80152,0x988C0002,0xDFC05EA,0x1180152,0x1180152,0x1180152,0x1180152,0xCB000001,0xCB000001,0xCB000001,0xA5000001,0xA5000001,0x98FC0001,0x1A00152,0x1A00152,0x1A00152,0xAED00001,0xAED00001,
+0x98E40000,0x55F80152,0x55F80152,0x98940000,0x8A000154,0x1A00152,0x1A00152,0x1A00152,0xAED00001,0xAED00001,0x98E40000,0x55F80152,0x55F80152,0x98940000,0x8A000154,0x55F80152,0x55F80152,0x98940000,0x8A000154,0x8A000154,0xF7000080,0xFF0C00AA,0x1180152,0xFEDC0019,0xE2CC0000,0xC4CC0001,0xB8D40000,0xACC00000,0xF8EC0091,0xFEC40012,0x27FC0152,0x98940000,
+0x27FC0152,0x15001A5,0xEF340001,0xC3340001,0xB5300002,0x1F001A5,0xD0FC0000,0xB5180001,0x7DF801A5,0xB4C00001,0xA60001A5,0x1F001A5,0xD0FC0000,0xB5180001,0x7DF801A5,0xB4C00001,0xA60001A5,0x7DF801A5,0xB4C00001,0xA60001A5,0xA60001A5,0x1F001A5,0xD0FC0000,0xB5180001,0x7DF801A5,0xB4C00001,0xA60001A5,0x7DF801A5,0xB4C00001,0xA60001A5,0xA60001A5,0x7DF801A5,
+0xB4C00001,0xA60001A5,0xA60001A5,0xA60001A5,0xFB2C00F2,0x16401A5,0xFD480109,0xFEF40034,0xF2B80000,0xCCBC0000,0xB4E00001,0xB4940001,0xFF1800DD,0xFED80022,0xBAE40000,0xA60001A5,0x5BFC01A5,0xE001A5,0xE001A5,0xE001A5,0xE001A5,0xE001A5,0xE001A5,0xE001A5,0xE001A5,0xE001A5,0xE001A5,0xB8C40000,0xB8C40000,0xB8C40000,0xB8C40000,0xB8C40000,
+0xB8C40000,0x8CC40000,0x8CC40000,0x8CC40000,0x7EC40000,0x14C01A5,0x14C01A5,0x14C01A5,0x14C01A5,0x14C01A5,0x14C01A5,0x9A8C0000,0x9A8C0000,0x9A8C0000,0x7EA80000,0x2BF801A5,0x2BF801A5,0x2BF801A5,0x7E4C0000,0x700001A5,0xF4D800C8,0xE001A5,0xE001A5,0xFECC0019,0xEEC40000,0xCEC40000,0xCEC40000,0xA8C40000,0xFEBC0088,0xFEB4000D,0x9CBC0000,0x9A8C0000,
+0x1DC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table114[] = {
+0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x21FC0000,
+0x21FC0000,0x21FC0000,0x21FC0000,0x68000001,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0x8E00000,0x8E00000,0x8E00000,0x13C0000,0x1C00000,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x10C0001,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,
+0x1900000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x86000000,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x86000000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x86000000,0x86000000,0x1200000,0x10C0001,0x10C0001,0x5380000,0x5500000,0x1700000,0x1700000,0x1C40000,0x5380000,0x5500000,0x1FF80000,0x4DFC0000,
+0x1FF80000,0x1400001,0x1400001,0x1400001,0x1400001,0x3DC0000,0x3DC0000,0x3DC0000,0x73FC0000,0x73FC0000,0xA0000000,0x3DC0000,0x3DC0000,0x3DC0000,0x73FC0000,0x73FC0000,0xA0000000,0x73FC0000,0x73FC0000,0xA0000000,0xA0000000,0x3DC0000,0x3DC0000,0x3DC0000,0x73FC0000,0x73FC0000,0xA0000000,0x73FC0000,0x73FC0000,0xA0000000,0xA0000000,0x73FC0000,
+0x73FC0000,0xA0000000,0xA0000000,0xA0000000,0x5740000,0x1580000,0x1400001,0x3B40000,0x19FC0000,0x4FFC0000,0x61FC0000,0x7FFC0000,0x1940000,0x3DC0000,0x4FFC0000,0xA0000000,0x4FFC0000,0x17C0000,0x3BFC0000,0x9FF80000,0xBC000001,0x3BFC0000,0x9FF80000,0xBC000001,0x9FF80000,0xBC000001,0xBC000001,0x3BFC0000,0x9FF80000,0xBC000001,0x9FF80000,0xBC000001,
+0xBC000001,0x9FF80000,0xBC000001,0xBC000001,0xBC000001,0x3BFC0000,0x9FF80000,0xBC000001,0x9FF80000,0xBC000001,0xBC000001,0x9FF80000,0xBC000001,0xBC000001,0xBC000001,0x9FF80000,0xBC000001,0xBC000001,0xBC000001,0xBC000001,0x1DC0000,0x3940000,0x3940000,0x61FC0000,0x93F80000,0xAFF00000,0xBC000001,0xBC000001,0xDFC0000,0x75FC0000,0xBBC80000,0xBC000001,
+0x85FC0000,0x1280F1A,0xFF1006D7,0xD90C05EA,0xBD0C05EB,0xFEF803F2,0xE0F401C3,0xC0F8028A,0xCAF0034A,0xBAF001BE,0xAEF0034A,0xFEE00629,0xE8D40153,0xC2E4020D,0xD0D001B2,0xBCD40006,0xB0D801BD,0xBCD405EA,0xB4C8020F,0xAACC0286,0xA0D405ED,0x1B80F1A,0xF0A405EB,0xBED405EB,0xE288034A,0xBEAC01B6,0xAEBC034A,0xD66805EB,0xBC800154,0xAC8C01C5,0xA29C05ED,0x61F80F1A,
+0xBC2805EB,0xAE0C034A,0xA00005F1,0x92000F1E,0xFF0C0766,0xF9200C4A,0xFB240CF3,0xFEEC01C5,0xF4D40003,0xD2D40002,0xBEDC0023,0xB8D00025,0xFEF806FA,0xFED4013A,0xC2C8015B,0xAC8C01C5,0x37FC0F1A,0x14405EA,0xFD2C017E,0xD3280152,0xBD280153,0xFF1001A6,0xD90C0001,0xBF18002A,0xC30C01A6,0xB90C004B,0xAF0C01A6,0x1E005EA,0xE2DC0153,0xBD000153,0xD6C001A5,0xBCD80002,
+0xAEE801A5,0x75FC05EA,0xBC800153,0xAE6801A5,0xA00005ED,0x1E005EA,0xE2DC0153,0xBD000153,0xD6C001A5,0xBCD80002,0xAEE801A5,0x75FC05EA,0xBC800153,0xAE6801A5,0xA00005ED,0x75FC05EA,0xBC800153,0xAE6801A5,0xA00005ED,0xA00005ED,0xFF200312,0xF73C04BE,0xF94004B2,0xFEF800DE,0xF4D40003,0xD2D40002,0xBEE80002,0xBCC0000B,0xFD140322,0xFEE000A1,0xC4B80152,0xAE6801A5,
+0x51FC05EA,0x10C05EA,0x10C05EA,0x10C05EA,0x10C05EA,0xF4F001A5,0xF4F001A5,0xF4F001A5,0xB4F001A5,0xB4F001A5,0xA0F001A5,0xE8D40152,0xE8D40152,0xE8D40152,0xBAD40005,0xBAD40005,0xA2E0004C,0xA8D40152,0xA8D40152,0x9CD40029,0x92D40154,0x38C05EA,0x38C05EA,0x38C05EA,0xC6A401A5,0xC6A401A5,0xA0C801A5,0xBA880153,0xBA880153,0xA09C0002,0x92AC0154,0x4BFC05EA,
+0x4BFC05EA,0xA04801A5,0x922C0154,0x840005ED,0xFEF402A9,0xFD080466,0x10C05EA,0xFCE400A5,0xF2D40002,0xD2D40002,0xC8D8000C,0xB4D40001,0xFEE40266,0xFED00062,0xBEC80152,0xA09C0002,0x1DF805EA,0x1280152,0x1280152,0x1280152,0x1280152,0xD3100001,0xD3100001,0xD3100001,0xAD100001,0xAD100001,0xA10C0001,0x1B80152,0x1B80152,0x1B80152,0xB6E00001,0xB6E00001,
+0xA0F40000,0x61F80152,0x61F80152,0xA0A40000,0x92000154,0x1B80152,0x1B80152,0x1B80152,0xB6E00001,0xB6E00001,0xA0F40000,0x61F80152,0x61F80152,0xA0A40000,0x92000154,0x61F80152,0x61F80152,0xA0A40000,0x92000154,0x92000154,0xFF100080,0xF92000B5,0x1280152,0xFCF40029,0xEADC0000,0xCCDC0001,0xC0E40000,0xB4D00000,0xFEF80095,0xFEDC0019,0x37FC0152,0xA0A40000,
+0x37FC0152,0x16001A5,0xF7440001,0xCB440001,0xBD400002,0xDFC01A5,0xD90C0000,0xBD280001,0x89F801A5,0xBCD00001,0xAE0001A5,0xDFC01A5,0xD90C0000,0xBD280001,0x89F801A5,0xBCD00001,0xAE0001A5,0x89F801A5,0xBCD00001,0xAE0001A5,0xAE0001A5,0xDFC01A5,0xD90C0000,0xBD280001,0x89F801A5,0xBCD00001,0xAE0001A5,0x89F801A5,0xBCD00001,0xAE0001A5,0xAE0001A5,0x89F801A5,
+0xBCD00001,0xAE0001A5,0xAE0001A5,0xAE0001A5,0xF7400109,0x17801A5,0xF5580122,0xFD100048,0xFAC80000,0xD4CC0000,0xBCF00001,0xBCA40001,0xFF2C00F4,0xFEF0003A,0xC2F40000,0xAE0001A5,0x69FC01A5,0xF001A5,0xF001A5,0xF001A5,0xF001A5,0xF001A5,0xF001A5,0xF001A5,0xF001A5,0xF001A5,0xF001A5,0xC0D40000,0xC0D40000,0xC0D40000,0xC0D40000,0xC0D40000,
+0xC0D40000,0x94D40000,0x94D40000,0x94D40000,0x86D40000,0x16401A5,0x16401A5,0x16401A5,0x16401A5,0x16401A5,0x16401A5,0xA29C0000,0xA29C0000,0xA29C0000,0x86B80000,0x37F801A5,0x37F801A5,0x37F801A5,0x865C0000,0x780001A5,0xFCE800C8,0xF001A5,0xF001A5,0xFED80028,0xF6D40000,0xD6D40000,0xD6D40000,0xB0D40000,0xFCD40091,0xFAC80019,0xA4CC0000,0xA29C0000,
+0x1FC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table115[] = {
+0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,0x2DFC0000,
+0x2DFC0000,0x2DFC0000,0x2DFC0000,0x70000001,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xF40000,0xF40000,0xF40000,0x3500000,0x1E40000,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x11C0001,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,
+0x1A80000,0x59FC0000,0x59FC0000,0x59FC0000,0x8E000000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x59FC0000,0x59FC0000,0x59FC0000,0x8E000000,0x59FC0000,0x59FC0000,0x59FC0000,0x8E000000,0x8E000000,0x1300000,0x11C0001,0x11C0001,0x14C0000,0x5640000,0x1840000,0x1840000,0x1E00000,0x14C0000,0x5640000,0x2DFC0000,0x59FC0000,
+0x2DFC0000,0x1500001,0x1500001,0x1500001,0x1500001,0x3F40000,0x3F40000,0x3F40000,0x7FFC0000,0x7FFC0000,0xA8000000,0x3F40000,0x3F40000,0x3F40000,0x7FFC0000,0x7FFC0000,0xA8000000,0x7FFC0000,0x7FFC0000,0xA8000000,0xA8000000,0x3F40000,0x3F40000,0x3F40000,0x7FFC0000,0x7FFC0000,0xA8000000,0x7FFC0000,0x7FFC0000,0xA8000000,0xA8000000,0x7FFC0000,
+0x7FFC0000,0xA8000000,0xA8000000,0xA8000000,0x1880000,0x1680000,0x1500001,0x1CC0000,0x2DFC0000,0x5FF80000,0x6FFC0000,0x8BF80000,0x1A80000,0x3F40000,0x5FF80000,0xA8000000,0x5FF80000,0x18C0000,0x53FC0000,0xABF80000,0xC4000001,0x53FC0000,0xABF80000,0xC4000001,0xABF80000,0xC4000001,0xC4000001,0x53FC0000,0xABF80000,0xC4000001,0xABF80000,0xC4000001,
+0xC4000001,0xABF80000,0xC4000001,0xC4000001,0xC4000001,0x53FC0000,0xABF80000,0xC4000001,0xABF80000,0xC4000001,0xC4000001,0xABF80000,0xC4000001,0xC4000001,0xC4000001,0xABF80000,0xC4000001,0xC4000001,0xC4000001,0xC4000001,0x1F00000,0xBA40000,0xBA40000,0x73FC0000,0x9FFC0000,0xB9F00000,0xC4000001,0xC4000001,0x2BFC0000,0x87FC0000,0xC3D80000,0xC4000001,
+0x95FC0000,0x1380F1A,0xFF24071A,0xE11C05EA,0xC51C05EB,0xFF0C043A,0xE90401C3,0xC908028A,0xD300034A,0xC30001BE,0xB700034A,0xFEF4065A,0xF0E40153,0xCAF4020D,0xD8E001B2,0xC4E40006,0xB8E801BD,0xC4E405EA,0xBCD8020F,0xB2DC0286,0xA8E405ED,0x1D00F1A,0xF8B405EB,0xC6E405EB,0xEA98034A,0xC6BC01B6,0xB6CC034A,0xDE7805EB,0xC4900154,0xB49C01C5,0xAAAC05ED,0x6DF80F1A,
+0xC43805EB,0xB61C034A,0xA80005ED,0x9A000F1E,0xFF2007D6,0xFF2C0C62,0xFF2C0D3B,0xFF000242,0xFCE40003,0xDAE40002,0xC6EC0023,0xC0E00025,0xFF100782,0xFEE801CC,0xCAD8015B,0xB49C01C5,0x45FC0F1A,0x15405EA,0xFF3C019A,0xDB380152,0xC5380153,0xFF2401B2,0xE11C0001,0xC728002A,0xCB1C01A6,0xC11C004B,0xB71C01A6,0x1F805EA,0xEAEC0153,0xC5100153,0xDED001A5,0xC4E80002,
+0xB6F801A5,0x81FC05EA,0xC4900153,0xB67801A5,0xA80005ED,0x1F805EA,0xEAEC0153,0xC5100153,0xDED001A5,0xC4E80002,0xB6F801A5,0x81FC05EA,0xC4900153,0xB67801A5,0xA80005ED,0x81FC05EA,0xC4900153,0xB67801A5,0xA80005ED,0xA80005ED,0xFF340333,0xFF4C04BE,0xFF4C04BE,0xFF140109,0xFCE40003,0xDAE40002,0xC6F80002,0xC4D0000B,0xFF240356,0xFD0000DD,0xCCC80152,0xB67801A5,
+0x5FFC05EA,0x11C05EA,0x11C05EA,0x11C05EA,0x11C05EA,0xFD0001A5,0xFD0001A5,0xFD0001A5,0xBD0001A5,0xBD0001A5,0xA90001A5,0xF0E40152,0xF0E40152,0xF0E40152,0xC2E40005,0xC2E40005,0xAAF0004C,0xB0E40152,0xB0E40152,0xA4E40029,0x9AE40154,0x3A405EA,0x3A405EA,0x3A405EA,0xCEB401A5,0xCEB401A5,0xA8D801A5,0xC2980153,0xC2980153,0xA8AC0002,0x9ABC0154,0x57FC05EA,
+0x57FC05EA,0xA85801A5,0x9A3C0154,0x8C0005ED,0xFF0402D2,0xF5180491,0x11C05EA,0xFEF800C9,0xFAE40002,0xDAE40002,0xD0E8000C,0xBCE40001,0xFEF80289,0xFEE00099,0xC6D80152,0xA8AC0002,0x2BFC05EA,0x1380152,0x1380152,0x1380152,0x1380152,0xDB200001,0xDB200001,0xDB200001,0xB5200001,0xB5200001,0xA91C0001,0x1D00152,0x1D00152,0x1D00152,0xBEF00001,0xBEF00001,
+0xA9040000,0x6DF80152,0x6DF80152,0xA8B40000,0x9A000154,0x1D00152,0x1D00152,0x1D00152,0xBEF00001,0xBEF00001,0xA9040000,0x6DF80152,0x6DF80152,0xA8B40000,0x9A000154,0x6DF80152,0x6DF80152,0xA8B40000,0x9A000154,0x9A000154,0xFF200091,0xFF2C00C1,0x1380152,0xFD040034,0xF2EC0000,0xD4EC0001,0xC8F40000,0xBCE00000,0xFD1000A2,0xFCF00029,0x45FC0152,0xA8B40000,
+0x45FC0152,0x17001A5,0xFF540001,0xD3540001,0xC5500002,0x25FC01A5,0xE11C0000,0xC5380001,0x95F801A5,0xC4E00001,0xB60001A5,0x25FC01A5,0xE11C0000,0xC5380001,0x95F801A5,0xC4E00001,0xB60001A5,0x95F801A5,0xC4E00001,0xB60001A5,0xB60001A5,0x25FC01A5,0xE11C0000,0xC5380001,0x95F801A5,0xC4E00001,0xB60001A5,0x95F801A5,0xC4E00001,0xB60001A5,0xB60001A5,0x95F801A5,
+0xC4E00001,0xB60001A5,0xB60001A5,0xB60001A5,0xFF500109,0x18801A5,0xFD680122,0xFF200061,0xFCE40002,0xDCDC0000,0xC5000001,0xC4B40001,0xF5480109,0xFF100048,0xCB040000,0xB60001A5,0x79FC01A5,0x10001A5,0x10001A5,0x10001A5,0x10001A5,0x10001A5,0x10001A5,0x10001A5,0x10001A5,0x10001A5,0x10001A5,0xC8E40000,0xC8E40000,0xC8E40000,0xC8E40000,0xC8E40000,
+0xC8E40000,0x9CE40000,0x9CE40000,0x9CE40000,0x8EE40000,0x17C01A5,0x17C01A5,0x17C01A5,0x17C01A5,0x17C01A5,0x17C01A5,0xAAAC0000,0xAAAC0000,0xAAAC0000,0x8EC80000,0x43F801A5,0x43F801A5,0x43F801A5,0x8E6C0000,0x800001A5,0xF4F800DD,0x10001A5,0x10001A5,0xFAEC0034,0xFEE40000,0xDEE40000,0xDEE40000,0xB8E40000,0xFCE400A2,0xFED80022,0xACDC0000,0xAAAC0000,
+0x11FC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table116[] = {
+0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x3BFC0000,
+0x3BFC0000,0x3BFC0000,0x3BFC0000,0x7A000000,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xB040000,0xB040000,0xB040000,0x16C0000,0x7FC0000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1300000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,
+0x1C40000,0x67F80000,0x67F80000,0x67F80000,0x96000001,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x67F80000,0x67F80000,0x67F80000,0x96000001,0x67F80000,0x67F80000,0x67F80000,0x96000001,0x96000001,0x1440000,0x1300000,0x1300000,0x3600000,0x17C0000,0x19C0000,0x19C0000,0x3FC0000,0x3600000,0x17C0000,0x3FF80000,0x67F80000,
+0x3FF80000,0x1640000,0x1640000,0x1640000,0x1640000,0x15FC0000,0x15FC0000,0x15FC0000,0x8DFC0000,0x8DFC0000,0xB0000001,0x15FC0000,0x15FC0000,0x15FC0000,0x8DFC0000,0x8DFC0000,0xB0000001,0x8DFC0000,0x8DFC0000,0xB0000001,0xB0000001,0x15FC0000,0x15FC0000,0x15FC0000,0x8DFC0000,0x8DFC0000,0xB0000001,0x8DFC0000,0x8DFC0000,0xB0000001,0xB0000001,0x8DFC0000,
+0x8DFC0000,0xB0000001,0xB0000001,0xB0000001,0x59C0000,0x17C0000,0x1640000,0x1E40000,0x43FC0000,0x6FFC0000,0x7FF80000,0x97F80000,0x3BC0000,0x15FC0000,0x6FFC0000,0xB0000001,0x6FFC0000,0x19C0001,0x6FFC0000,0xB9F80000,0xCE000000,0x6FFC0000,0xB9F80000,0xCE000000,0xB9F80000,0xCE000000,0xCE000000,0x6FFC0000,0xB9F80000,0xCE000000,0xB9F80000,0xCE000000,
+0xCE000000,0xB9F80000,0xCE000000,0xCE000000,0xCE000000,0x6FFC0000,0xB9F80000,0xCE000000,0xB9F80000,0xCE000000,0xCE000000,0xB9F80000,0xCE000000,0xCE000000,0xCE000000,0xB9F80000,0xCE000000,0xCE000000,0xCE000000,0xCE000000,0x15FC0000,0x5B80000,0x5B80000,0x8BFC0000,0xAFFC0000,0xC3F80000,0xCE000000,0xCE000000,0x4DFC0000,0x99FC0000,0xCDCC0000,0xCE000000,
+0xA5FC0000,0x1480F1E,0xFF340795,0xEB2C05ED,0xCF2C05ED,0xFF2404B6,0xF31801C5,0xD31C0286,0xDB14034A,0xCD1001BD,0xC114034A,0xFF0C06AE,0xF8F80154,0xD508020F,0xE0F001B6,0xCCF80006,0xC0FC01BE,0xCEF405EB,0xC6EC020D,0xBAEC028A,0xB2F405EB,0x3E80F1A,0xFECC05F1,0xCEF805EA,0xF4A8034A,0xD0D001B2,0xC0DC034A,0xE69005EB,0xCEA00153,0xBEB001C3,0xB2C005EA,0x79FC0F1A,
+0xCE4805EA,0xC02C034A,0xB21005EA,0xA4000F1A,0xFF340865,0xFB440CAA,0xFD480D3E,0xFF1402EF,0xFEFC0019,0xE2F80004,0xD1000025,0xCAF40023,0xFF240839,0xFF000256,0xD2E80159,0xBEB001C3,0x57FC0F1A,0x16405ED,0xFF5001C8,0xE34C0154,0xCF480154,0xFF3C01D5,0xE9300002,0xCF380029,0xD33001A5,0xC92C004C,0xC13001A5,0x19FC05EA,0xF4FC0153,0xCF200152,0xE6E401A5,0xCCF80005,
+0xC10801A5,0x8FF805EA,0xCE9C0152,0xC08801A5,0xB20005EA,0x19FC05EA,0xF4FC0153,0xCF200152,0xE6E401A5,0xCCF80005,0xC10801A5,0x8FF805EA,0xCE9C0152,0xC08801A5,0xB20005EA,0x8FF805EA,0xCE9C0152,0xC08801A5,0xB20005EA,0xB20005EA,0xFF500376,0xF96004ED,0xFB6404E4,0xFF2C016D,0xFEFC0010,0xE2F80003,0xCF080001,0xCCE0000C,0xFD40039E,0xFF180122,0xD4DC0152,0xC08801A5,
+0x71FC05EA,0x12C05ED,0x12C05ED,0x12C05ED,0x12C05ED,0xFD1401A9,0xFD1401A9,0xFD1401A9,0xC51401A5,0xC51401A5,0xB11401A6,0xF8F80153,0xF8F80153,0xF8F80153,0xCCF80002,0xCCF80002,0xB300004B,0xB8F80153,0xB8F80153,0xACF4002A,0xA4F40153,0x1C005EA,0x1C005EA,0x1C005EA,0xD8C401A5,0xD8C401A5,0xB0EC01A6,0xCAAC0153,0xCAAC0153,0xB2C00001,0xA4CC0152,0x65F805EA,
+0x65F805EA,0xB06C01A6,0xA4480152,0x960005EA,0xFF2002FE,0xFD280492,0x12C05ED,0xFF080103,0xFEF80003,0xE0F80002,0xD8F8000B,0xC4F40002,0xFF0C02D3,0xFEF400CA,0xCEEC0153,0xB2C00001,0x3DF805EA,0x1480154,0x1480154,0x1480154,0x1480154,0xE7300000,0xE7300000,0xE7300000,0xBF300000,0xBF300000,0xB1300001,0x3E80152,0x3E80152,0x3E80152,0xC9000001,0xC9000001,
+0xB1180001,0x79FC0152,0x79FC0152,0xB0C80001,0xA4000152,0x3E80152,0x3E80152,0x3E80152,0xC9000001,0xC9000001,0xB1180001,0x79FC0152,0x79FC0152,0xB0C80001,0xA4000152,0x79FC0152,0x79FC0152,0xB0C80001,0xA4000152,0xA4000152,0xFB3400A4,0xFB4400C8,0x1480154,0xFF180041,0xFCFC0000,0xDEFC0000,0xD1080000,0xC6F00000,0xF92800B5,0xFF04003A,0x57FC0152,0xB0C80001,
+0x57FC0152,0x18001A5,0xFF680008,0xDD640000,0xCF640000,0x41FC01A5,0xEB2C0000,0xCF480000,0xA1FC01A5,0xCEEC0000,0xC00001A5,0x41FC01A5,0xEB2C0000,0xCF480000,0xA1FC01A5,0xCEEC0000,0xC00001A5,0xA1FC01A5,0xCEEC0000,0xC00001A5,0xC00001A5,0x41FC01A5,0xEB2C0000,0xCF480000,0xA1FC01A5,0xCEEC0000,0xC00001A5,0xA1FC01A5,0xCEEC0000,0xC00001A5,0xC00001A5,0xA1FC01A5,
+0xCEEC0000,0xC00001A5,0xC00001A5,0xC00001A5,0xFD680120,0x19C01A5,0xF77C0139,0xFF400071,0xFEFC0010,0xE4F00000,0xCF100000,0xCEC00000,0xFF5C0109,0xFF2C0064,0xD3180000,0xC00001A5,0x89FC01A5,0x11401A5,0x11401A5,0x11401A5,0x11401A5,0x11401A5,0x11401A5,0x11401A5,0x11401A5,0x11401A5,0x11401A5,0xD0F80001,0xD0F80001,0xD0F80001,0xD0F80001,0xD0F80001,
+0xD0F80001,0xA4F80001,0xA4F80001,0xA4F80001,0x96F40002,0x19801A5,0x19801A5,0x19801A5,0x19801A5,0x19801A5,0x19801A5,0xB2C00000,0xB2C00000,0xB2C00000,0x96DC0001,0x51F801A5,0x51F801A5,0x51F801A5,0x96840001,0x880001A5,0xFF0C00DD,0x11401A5,0x11401A5,0xFD00003D,0xFEF80002,0xE4F80001,0xE4F80001,0xC0F80001,0xFEF400AA,0xFAF00032,0xB4F00001,0xB2C00000,
+0x21FC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table117[] = {
+0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x1840000,0x47FC0000,
+0x47FC0000,0x47FC0000,0x47FC0000,0x82000000,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1040001,0x1180000,0x1180000,0x1180000,0x1840000,0x17FC0000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,
+0x1DC0000,0x73F80000,0x73F80000,0x73F80000,0x9E000001,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x73F80000,0x73F80000,0x73F80000,0x9E000001,0x73F80000,0x73F80000,0x73F80000,0x9E000001,0x9E000001,0x3540000,0x1400000,0x1400000,0x1740000,0x1900000,0x1B40000,0x1B40000,0x17FC0000,0x1740000,0x1900000,0x4DFC0000,0x73F80000,
+0x4DFC0000,0x1740000,0x1740000,0x1740000,0x1740000,0x2FFC0000,0x2FFC0000,0x2FFC0000,0x99FC0000,0x99FC0000,0xB8000001,0x2FFC0000,0x2FFC0000,0x2FFC0000,0x99FC0000,0x99FC0000,0xB8000001,0x99FC0000,0x99FC0000,0xB8000001,0xB8000001,0x2FFC0000,0x2FFC0000,0x2FFC0000,0x99FC0000,0x99FC0000,0xB8000001,0x99FC0000,0x99FC0000,0xB8000001,0xB8000001,0x99FC0000,
+0x99FC0000,0xB8000001,0xB8000001,0xB8000001,0x1B00000,0x18C0000,0x1740000,0x3F80000,0x57FC0000,0x7FF80000,0x8BFC0000,0xA1FC0000,0x5D00000,0x2FFC0000,0x7FF80000,0xB8000001,0x7FF80000,0x1AC0001,0x87FC0000,0xC5F80000,0xD6000000,0x87FC0000,0xC5F80000,0xD6000000,0xC5F80000,0xD6000000,0xD6000000,0x87FC0000,0xC5F80000,0xD6000000,0xC5F80000,0xD6000000,
+0xD6000000,0xC5F80000,0xD6000000,0xD6000000,0xD6000000,0x87FC0000,0xC5F80000,0xD6000000,0xC5F80000,0xD6000000,0xD6000000,0xC5F80000,0xD6000000,0xD6000000,0xD6000000,0xC5F80000,0xD6000000,0xD6000000,0xD6000000,0xD6000000,0x3DFC0000,0xDC80000,0xDC80000,0x9DFC0000,0xBDF80000,0xCDF80000,0xD6000000,0xD6000000,0x6BFC0000,0xABFC0000,0xD5DC0000,0xD6000000,
+0xB5FC0000,0x1580F1E,0xFF4407E9,0xF33C05ED,0xD73C05ED,0xFF300542,0xFB2801C5,0xDB2C0286,0xE324034A,0xD52001BD,0xC924034A,0xFF240716,0xFF080155,0xDD18020F,0xE90001B6,0xD5080006,0xC90C01BE,0xD70405EB,0xCEFC020D,0xC2FC028A,0xBB0405EB,0x7FC0F1A,0xFEE40611,0xD70805EA,0xFCB8034A,0xD8E001B2,0xC8EC034A,0xEEA005EB,0xD6B00153,0xC6C001C3,0xBAD005EA,0x85FC0F1A,
+0xD65805EA,0xC83C034A,0xBA2005EA,0xAC000F1A,0xFF4408FE,0xFF4C0CEA,0xF5580D89,0xFF2C03A6,0xFF10005D,0xEB080004,0xD9100025,0xD3040023,0xFF340886,0xFF180302,0xDAF80159,0xC6C001C3,0x65FC0F1A,0x17405ED,0xFF60020D,0xEB5C0154,0xD7580154,0xFF5001FD,0xF1400002,0xD7480029,0xDB4001A5,0xD13C004C,0xC94001A5,0x31FC05EA,0xFD0C0153,0xD7300152,0xEEF401A5,0xD5080005,
+0xC91801A5,0x9BF805EA,0xD6AC0152,0xC89801A5,0xBA0005EA,0x31FC05EA,0xFD0C0153,0xD7300152,0xEEF401A5,0xD5080005,0xC91801A5,0x9BF805EA,0xD6AC0152,0xC89801A5,0xBA0005EA,0x9BF805EA,0xD6AC0152,0xC89801A5,0xBA0005EA,0xBA0005EA,0xFF5803C9,0xFF6C04F5,0xFF6C0504,0xFF4001AA,0xFF18003B,0xEB080003,0xD7180001,0xD4F0000C,0xFF5403C9,0xFF2C017D,0xDCEC0152,0xC89801A5,
+0x7FFC05EA,0x13C05ED,0x13C05ED,0x13C05ED,0x13C05ED,0xFF2401B5,0xFF2401B5,0xFF2401B5,0xCD2401A5,0xCD2401A5,0xB92401A6,0xFD080155,0xFD080155,0xFD080155,0xD5080002,0xD5080002,0xBB10004B,0xC1080153,0xC1080153,0xB504002A,0xAD040153,0x1D805EA,0x1D805EA,0x1D805EA,0xE0D401A5,0xE0D401A5,0xB8FC01A6,0xD2BC0153,0xD2BC0153,0xBAD00001,0xACDC0152,0x71F805EA,
+0x71F805EA,0xB87C01A6,0xAC580152,0x9E0005EA,0xFF2C032B,0xF53804C1,0x13C05ED,0xFF1C0141,0xFF0C0013,0xE9080002,0xE108000B,0xCD040002,0xFF2002F9,0xFF100109,0xD6FC0153,0xBAD00001,0x4BFC05EA,0x1580154,0x1580154,0x1580154,0x1580154,0xEF400000,0xEF400000,0xEF400000,0xC7400000,0xC7400000,0xB9400001,0x7FC0152,0x7FC0152,0x7FC0152,0xD1100001,0xD1100001,
+0xB9280001,0x85FC0152,0x85FC0152,0xB8D80001,0xAC000152,0x7FC0152,0x7FC0152,0x7FC0152,0xD1100001,0xD1100001,0xB9280001,0x85FC0152,0x85FC0152,0xB8D80001,0xAC000152,0x85FC0152,0x85FC0152,0xB8D80001,0xAC000152,0xAC000152,0xF74800B5,0xF35400DD,0x1580154,0xFD300055,0xFD140002,0xE70C0000,0xD9180000,0xCF000000,0xFF3400B9,0xFD200048,0x65FC0152,0xB8D80001,
+0x65FC0152,0x19001A5,0xFF78001D,0xE5740000,0xD7740000,0x59FC01A5,0xF33C0000,0xD7580000,0xADFC01A5,0xD6FC0000,0xC80001A5,0x59FC01A5,0xF33C0000,0xD7580000,0xADFC01A5,0xD6FC0000,0xC80001A5,0xADFC01A5,0xD6FC0000,0xC80001A5,0xC80001A5,0x59FC01A5,0xF33C0000,0xD7580000,0xADFC01A5,0xD6FC0000,0xC80001A5,0xADFC01A5,0xD6FC0000,0xC80001A5,0xC80001A5,0xADFC01A5,
+0xD6FC0000,0xC80001A5,0xC80001A5,0xC80001A5,0xFF780122,0x1AC01A5,0xFF8C0139,0xFF580091,0xFF240020,0xED000000,0xD7200000,0xD6D00000,0xFF700120,0xFF40007D,0xDB280000,0xC80001A5,0x99FC01A5,0x12401A5,0x12401A5,0x12401A5,0x12401A5,0x12401A5,0x12401A5,0x12401A5,0x12401A5,0x12401A5,0x12401A5,0xD9080001,0xD9080001,0xD9080001,0xD9080001,0xD9080001,
+0xD9080001,0xAD080001,0xAD080001,0xAD080001,0x9F040002,0x1B001A5,0x1B001A5,0x1B001A5,0x1B001A5,0x1B001A5,0x1B001A5,0xBAD00000,0xBAD00000,0xBAD00000,0x9EEC0001,0x5DF401A5,0x5DF401A5,0x5DF401A5,0x9E940001,0x900001A5,0xF71C00F2,0x12401A5,0x12401A5,0xFF10004A,0xFD08000A,0xED080001,0xED080001,0xC9080001,0xFD0C00B5,0xFF00003D,0xBD000001,0xBAD00000,
+0x31FC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table118[] = {
+0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x53FC0000,
+0x53FC0000,0x53FC0000,0x53FC0000,0x8A000000,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1140001,0x1280000,0x1280000,0x1280000,0x19C0000,0x25FC0000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,
+0x1F40000,0x7FF80000,0x7FF80000,0x7FF80000,0xA6000001,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x1F40000,0x7FF80000,0x7FF80000,0x7FF80000,0xA6000001,0x7FF80000,0x7FF80000,0x7FF80000,0xA6000001,0xA6000001,0xB640000,0x1500000,0x1500000,0x7840000,0x1A40000,0x1C80000,0x1C80000,0x2BFC0000,0x7840000,0x1A40000,0x5DF80000,0x7FF80000,
+0x5DF80000,0x1840000,0x1840000,0x1840000,0x1840000,0x47FC0000,0x47FC0000,0x47FC0000,0xA5F80000,0xA5F80000,0xC0000001,0x47FC0000,0x47FC0000,0x47FC0000,0xA5F80000,0xA5F80000,0xC0000001,0xA5F80000,0xA5F80000,0xC0000001,0xC0000001,0x47FC0000,0x47FC0000,0x47FC0000,0xA5F80000,0xA5F80000,0xC0000001,0xA5F80000,0xA5F80000,0xC0000001,0xC0000001,0xA5F80000,
+0xA5F80000,0xC0000001,0xC0000001,0xC0000001,0x1C40000,0x79C0000,0x1840000,0x1BFC0000,0x6BFC0000,0x8DFC0000,0x99FC0000,0xADF80000,0x5E40000,0x47FC0000,0x8DFC0000,0xC0000001,0x8DFC0000,0x1BC0001,0x9FFC0000,0xD1F80000,0xDE000000,0x9FFC0000,0xD1F80000,0xDE000000,0xD1F80000,0xDE000000,0xDE000000,0x9FFC0000,0xD1F80000,0xDE000000,0xD1F80000,0xDE000000,
+0xDE000000,0xD1F80000,0xDE000000,0xDE000000,0xDE000000,0x9FFC0000,0xD1F80000,0xDE000000,0xD1F80000,0xDE000000,0xDE000000,0xD1F80000,0xDE000000,0xDE000000,0xDE000000,0xD1F80000,0xDE000000,0xDE000000,0xDE000000,0xDE000000,0x63FC0000,0x1DC0000,0x1DC0000,0xB1FC0000,0xC9FC0000,0xD7F80000,0xDE000000,0xDE000000,0x89FC0000,0xBBFC0000,0xDDEC0000,0xDE000000,
+0xC3FC0000,0x1680F1E,0xFF5C0861,0xFB4C05ED,0xDF4C05ED,0xFF4405BA,0xFF3801D5,0xE33C0286,0xEB34034A,0xDD3001BD,0xD134034A,0xFF300786,0xFF1C017C,0xE528020F,0xF11001B6,0xDD180006,0xD11C01BE,0xDF1405EB,0xD70C020D,0xCB0C028A,0xC31405EB,0x1FFC0F1A,0xFEFC0651,0xDF1805EA,0xFED4035A,0xE0F001B2,0xD0FC034A,0xF6B005EB,0xDEC00153,0xCED001C3,0xC2E005EA,0x91FC0F1A,
+0xDE6805EA,0xD04C034A,0xC23005EA,0xB4000F1A,0xFF58097A,0xFB640D0E,0xFD680D89,0xFF400463,0xFF2400D1,0xF3180004,0xE1200025,0xDB140023,0xFF440933,0xFF3003D3,0xE3080159,0xCED001C3,0x75FC0F1A,0x18405ED,0xFF740248,0xF36C0154,0xDF680154,0xFF5C0239,0xF9500002,0xDF580029,0xE35001A5,0xD94C004C,0xD15001A5,0x49FC05EA,0xFF280163,0xDF400152,0xF70401A5,0xDD180005,
+0xD12801A5,0xA7F805EA,0xDEBC0152,0xD0A801A5,0xC20005EA,0x49FC05EA,0xFF280163,0xDF400152,0xF70401A5,0xDD180005,0xD12801A5,0xA7F805EA,0xDEBC0152,0xD0A801A5,0xC20005EA,0xA7F805EA,0xDEBC0152,0xD0A801A5,0xC20005EA,0xC20005EA,0xFD7403F6,0xF980051D,0xFB840515,0xFF540209,0xFF30007D,0xF3180003,0xDF280001,0xDD00000C,0xFF5C040A,0xFF4801C4,0xE4FC0152,0xD0A801A5,
+0x8FFC05EA,0x14C05ED,0x14C05ED,0x14C05ED,0x14C05ED,0xFD3801D5,0xFD3801D5,0xFD3801D5,0xD53401A5,0xD53401A5,0xC13401A6,0xFF1C0163,0xFF1C0163,0xFF1C0163,0xDD180002,0xDD180002,0xC320004B,0xC9180153,0xC9180153,0xBD14002A,0xB5140153,0x1F005EA,0x1F005EA,0x1F005EA,0xE8E401A5,0xE8E401A5,0xC10C01A6,0xDACC0153,0xDACC0153,0xC2E00001,0xB4EC0152,0x7DF805EA,
+0x7DF805EA,0xC08C01A6,0xB4680152,0xA60005EA,0xFF3C035D,0xFD4804C1,0x14C05ED,0xFF2C0182,0xFF200033,0xF1180002,0xE918000B,0xD5140002,0xFF340322,0xFF1C014E,0xDF0C0153,0xC2E00001,0x5BFC05EA,0x1680154,0x1680154,0x1680154,0x1680154,0xF7500000,0xF7500000,0xF7500000,0xCF500000,0xCF500000,0xC1500001,0x1FFC0152,0x1FFC0152,0x1FFC0152,0xD9200001,0xD9200001,
+0xC1380001,0x91FC0152,0x91FC0152,0xC0E80001,0xB4000152,0x1FFC0152,0x1FFC0152,0x1FFC0152,0xD9200001,0xD9200001,0xC1380001,0x91FC0152,0x91FC0152,0xC0E80001,0xB4000152,0x91FC0152,0x91FC0152,0xC0E80001,0xB4000152,0xB4000152,0xFF5800B5,0xFB6400DD,0x1680154,0xFF440062,0xFD28000A,0xEF1C0000,0xE1280000,0xD7100000,0xFD4C00C8,0xFF300059,0x75FC0152,0xC0E80001,
+0x75FC0152,0x1A001A5,0xFF8C0034,0xED840000,0xDF840000,0x71FC01A5,0xFB4C0000,0xDF680000,0xB9FC01A5,0xDF0C0000,0xD00001A5,0x71FC01A5,0xFB4C0000,0xDF680000,0xB9FC01A5,0xDF0C0000,0xD00001A5,0xB9FC01A5,0xDF0C0000,0xD00001A5,0xD00001A5,0x71FC01A5,0xFB4C0000,0xDF680000,0xB9FC01A5,0xDF0C0000,0xD00001A5,0xB9FC01A5,0xDF0C0000,0xD00001A5,0xD00001A5,0xB9FC01A5,
+0xDF0C0000,0xD00001A5,0xD00001A5,0xD00001A5,0xFD900139,0x1BC01A5,0xF79C0154,0xFF6C00AA,0xFF3C003A,0xF5100000,0xDF300000,0xDEE00000,0xF7880139,0xFF6400A2,0xE3380000,0xD00001A5,0xA7FC01A5,0x13401A5,0x13401A5,0x13401A5,0x13401A5,0x13401A5,0x13401A5,0x13401A5,0x13401A5,0x13401A5,0x13401A5,0xE1180001,0xE1180001,0xE1180001,0xE1180001,0xE1180001,
+0xE1180001,0xB5180001,0xB5180001,0xB5180001,0xA7140002,0x1C801A5,0x1C801A5,0x1C801A5,0x1C801A5,0x1C801A5,0x1C801A5,0xC2E00000,0xC2E00000,0xC2E00000,0xA6FC0001,0x67FC01A5,0x67FC01A5,0x67FC01A5,0xA6A40001,0x980001A5,0xFF2C00F2,0x13401A5,0x13401A5,0xFF200059,0xFD1C0012,0xF5180001,0xF5180001,0xD1180001,0xFD1C00C8,0xFF140048,0xC5100001,0xC2E00000,
+0x3FFC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table119[] = {
+0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x5FF80000,
+0x5FF80000,0x5FF80000,0x5FF80000,0x92000000,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x5380000,0x5380000,0x5380000,0x1B40000,0x35FC0000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0x1600000,0xFFC0000,0xFFC0000,0xFFC0000,0xFFC0000,0xFFC0000,
+0xFFC0000,0x8BF80000,0x8BF80000,0x8BF80000,0xAE000001,0xFFC0000,0xFFC0000,0xFFC0000,0xFFC0000,0xFFC0000,0xFFC0000,0x8BF80000,0x8BF80000,0x8BF80000,0xAE000001,0x8BF80000,0x8BF80000,0x8BF80000,0xAE000001,0xAE000001,0x1780000,0x1600000,0x1600000,0x3980000,0x1B80000,0x3DC0000,0x3DC0000,0x3DFC0000,0x3980000,0x1B80000,0x6BFC0000,0x8BF80000,
+0x6BFC0000,0x1940000,0x1940000,0x1940000,0x1940000,0x5FFC0000,0x5FFC0000,0x5FFC0000,0xB1F80000,0xB1F80000,0xC8000001,0x5FFC0000,0x5FFC0000,0x5FFC0000,0xB1F80000,0xB1F80000,0xC8000001,0xB1F80000,0xB1F80000,0xC8000001,0xC8000001,0x5FFC0000,0x5FFC0000,0x5FFC0000,0xB1F80000,0xB1F80000,0xC8000001,0xB1F80000,0xB1F80000,0xC8000001,0xC8000001,0xB1F80000,
+0xB1F80000,0xC8000001,0xC8000001,0xC8000001,0x3D40000,0xFAC0000,0x1940000,0x39FC0000,0x7DFC0000,0x9DF80000,0xA7F80000,0xB7FC0000,0x5F80000,0x5FFC0000,0x9DF80000,0xC8000001,0x9DF80000,0x1CC0001,0xB7FC0000,0xDDF40000,0xE6000000,0xB7FC0000,0xDDF40000,0xE6000000,0xDDF40000,0xE6000000,0xE6000000,0xB7FC0000,0xDDF40000,0xE6000000,0xDDF40000,0xE6000000,
+0xE6000000,0xDDF40000,0xE6000000,0xE6000000,0xE6000000,0xB7FC0000,0xDDF40000,0xE6000000,0xDDF40000,0xE6000000,0xE6000000,0xDDF40000,0xE6000000,0xE6000000,0xE6000000,0xDDF40000,0xE6000000,0xE6000000,0xE6000000,0xE6000000,0x8BFC0000,0x1EC0000,0x1EC0000,0xC5FC0000,0xD7FC0000,0xE1FC0000,0xE6000000,0xE6000000,0xA7FC0000,0xCDFC0000,0xE5FC0000,0xE6000000,
+0xD3FC0000,0x1780F1E,0xFF6808D9,0xFF6005F1,0xE75C05ED,0xFF5C0662,0xFF480215,0xEB4C0286,0xF344034A,0xE54001BD,0xD944034A,0xFF4407F7,0xFF3401DC,0xED38020F,0xF92001B6,0xE5280006,0xD92C01BE,0xE72405EB,0xDF1C020D,0xD31C028A,0xCB2405EB,0x37FC0F1A,0xFF1406B1,0xE72805EA,0xFEF00392,0xE90001B2,0xD90C034A,0xFEC005EB,0xE6D00153,0xD6E001C3,0xCAF005EA,0x9DFC0F1A,
+0xE67805EA,0xD85C034A,0xCA4005EA,0xBC000F1A,0xFF6409F4,0xFF6C0D5E,0xF5780DD6,0xFF54052A,0xFF380175,0xFB280004,0xE9300025,0xE3240023,0xFF5C09AA,0xFF40048F,0xEB180159,0xD6E001C3,0x83FC0F1A,0x19405ED,0xFF8402A5,0xFB7C0154,0xE7780154,0xFF740279,0xFF600004,0xE7680029,0xEB6001A5,0xE15C004C,0xD96001A5,0x63FC05EA,0xFF40018B,0xE7500152,0xFF1401A5,0xE5280005,
+0xD93801A5,0xB3F805EA,0xE6CC0152,0xD8B801A5,0xCA0005EA,0x63FC05EA,0xFF40018B,0xE7500152,0xFF1401A5,0xE5280005,0xD93801A5,0xB3F805EA,0xE6CC0152,0xD8B801A5,0xCA0005EA,0xB3F805EA,0xE6CC0152,0xD8B801A5,0xCA0005EA,0xCA0005EA,0xFF800435,0xFF8C052D,0xFF8C053D,0xFF6C026A,0xFF4800CE,0xFB280003,0xE7380001,0xE510000C,0xFF78042A,0xFF5C022E,0xED0C0152,0xD8B801A5,
+0x9FF805EA,0x15C05ED,0x15C05ED,0x15C05ED,0x15C05ED,0xFF4801F1,0xFF4801F1,0xFF4801F1,0xDD4401A5,0xDD4401A5,0xC94401A6,0xFF30017D,0xFF30017D,0xFF30017D,0xE5280002,0xE5280002,0xCB30004B,0xD1280153,0xD1280153,0xC524002A,0xBD240153,0xDFC05EA,0xDFC05EA,0xDFC05EA,0xF0F401A5,0xF0F401A5,0xC91C01A6,0xE2DC0153,0xE2DC0153,0xCAF00001,0xBCFC0152,0x89F805EA,
+0x89F805EA,0xC89C01A6,0xBC780152,0xAE0005EA,0xFF4C038A,0xF75C04EE,0x15C05ED,0xFF4401C3,0xFF300062,0xF9280002,0xF128000B,0xDD240002,0xFF3C0371,0xFF300182,0xE71C0153,0xCAF00001,0x69FC05EA,0x1780154,0x1780154,0x1780154,0x1780154,0xFF600000,0xFF600000,0xFF600000,0xD7600000,0xD7600000,0xC9600001,0x37FC0152,0x37FC0152,0x37FC0152,0xE1300001,0xE1300001,
+0xC9480001,0x9DFC0152,0x9DFC0152,0xC8F80001,0xBC000152,0x37FC0152,0x37FC0152,0x37FC0152,0xE1300001,0xE1300001,0xC9480001,0x9DFC0152,0x9DFC0152,0xC8F80001,0xBC000152,0x9DFC0152,0x9DFC0152,0xC8F80001,0xBC000152,0xBC000152,0xFB6C00C8,0xF37400F4,0x1780154,0xFD580071,0xFF400012,0xF72C0000,0xE9380000,0xDF200000,0xF56400DD,0xFF480064,0x83FC0152,0xC8F80001,
+0x83FC0152,0x1B001A5,0xFF9C0061,0xF5940000,0xE7940000,0x89FC01A5,0xFF640002,0xE7780000,0xC5FC01A5,0xE71C0000,0xD80001A5,0x89FC01A5,0xFF640002,0xE7780000,0xC5FC01A5,0xE71C0000,0xD80001A5,0xC5FC01A5,0xE71C0000,0xD80001A5,0xD80001A5,0x89FC01A5,0xFF640002,0xE7780000,0xC5FC01A5,0xE71C0000,0xD80001A5,0xC5FC01A5,0xE71C0000,0xD80001A5,0xD80001A5,0xC5FC01A5,
+0xE71C0000,0xD80001A5,0xD80001A5,0xD80001A5,0xF7A40152,0x1CC01A5,0xFFAC0154,0xFF8400D0,0xFF640062,0xFD200000,0xE7400000,0xE6F00000,0xFF980139,0xFD8000C8,0xEB480000,0xD80001A5,0xB7FC01A5,0x14401A5,0x14401A5,0x14401A5,0x14401A5,0x14401A5,0x14401A5,0x14401A5,0x14401A5,0x14401A5,0x14401A5,0xE9280001,0xE9280001,0xE9280001,0xE9280001,0xE9280001,
+0xE9280001,0xBD280001,0xBD280001,0xBD280001,0xAF240002,0x1E001A5,0x1E001A5,0x1E001A5,0x1E001A5,0x1E001A5,0x1E001A5,0xCAF00000,0xCAF00000,0xCAF00000,0xAF0C0001,0x73FC01A5,0x73FC01A5,0x73FC01A5,0xAEB40001,0xA00001A5,0xF73C0109,0x14401A5,0x14401A5,0xFB340071,0xFB2C0022,0xFD280001,0xFD280001,0xD9280001,0xF93000DD,0xFF200061,0xCD200001,0xCAF00000,
+0x4FFC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table120[] = {
+0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x6DF80000,
+0x6DF80000,0x6DF80000,0x6DF80000,0x9A000001,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x14C0000,0x14C0000,0x14C0000,0x1D00000,0x45FC0000,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x1700001,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,
+0x2BFC0000,0x97FC0000,0x97FC0000,0x97FC0000,0xB8000000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x2BFC0000,0x97FC0000,0x97FC0000,0x97FC0000,0xB8000000,0x97FC0000,0x97FC0000,0x97FC0000,0xB8000000,0xB8000000,0xD880000,0x1700001,0x1700001,0x5AC0000,0x1D00000,0x1F80000,0x1F80000,0x53FC0000,0x5AC0000,0x1D00000,0x7DF80000,0x97FC0000,
+0x7DF80000,0x1A40001,0x1A40001,0x1A40001,0x1A40001,0x7BFC0000,0x7BFC0000,0x7BFC0000,0xBFF80000,0xBFF80000,0xD2000000,0x7BFC0000,0x7BFC0000,0x7BFC0000,0xBFF80000,0xBFF80000,0xD2000000,0xBFF80000,0xBFF80000,0xD2000000,0xD2000000,0x7BFC0000,0x7BFC0000,0x7BFC0000,0xBFF80000,0xBFF80000,0xD2000000,0xBFF80000,0xBFF80000,0xD2000000,0xD2000000,0xBFF80000,
+0xBFF80000,0xD2000000,0xD2000000,0xD2000000,0x7E80000,0x9C00000,0x1A40001,0x5BFC0000,0x93FC0000,0xADFC0000,0xB5FC0000,0xC3FC0000,0x29FC0000,0x7BFC0000,0xADFC0000,0xD2000000,0xADFC0000,0x1E00000,0xD3FC0000,0xE9FC0000,0xEE000001,0xD3FC0000,0xE9FC0000,0xEE000001,0xE9FC0000,0xEE000001,0xEE000001,0xD3FC0000,0xE9FC0000,0xEE000001,0xE9FC0000,0xEE000001,
+0xEE000001,0xE9FC0000,0xEE000001,0xEE000001,0xEE000001,0xD3FC0000,0xE9FC0000,0xEE000001,0xE9FC0000,0xEE000001,0xEE000001,0xE9FC0000,0xEE000001,0xEE000001,0xEE000001,0xE9FC0000,0xEE000001,0xEE000001,0xEE000001,0xEE000001,0xB7FC0000,0x17FC0000,0x17FC0000,0xDBFC0000,0xE7F80000,0xEDF40000,0xEE000001,0xEE000001,0xC9FC0000,0xE1FC0000,0xEFF00000,0xEE000001,
+0xE3FC0000,0x18C0F1A,0xFF800983,0xFF70062A,0xEF7005EB,0xFF680746,0xFF6002AB,0xF35C028A,0xFD54034A,0xED5401BE,0xE154034A,0xFF5C0899,0xFF4C028C,0xF548020D,0xFF3801BA,0xEF380006,0xE33C01BD,0xEF3805EA,0xE72C020F,0xDD300286,0xD33805ED,0x53FC0F1A,0xFF38073B,0xF13805EB,0xFF140416,0xF11001B6,0xE120034A,0xFEE40615,0xEEE40154,0xDEF001C5,0xD50005ED,0xABF80F1A,
+0xEE8C05EB,0xE070034A,0xD25405ED,0xC4000F1E,0xFF780A99,0xFD880D72,0xFD880DDA,0xFF6C0649,0xFF500261,0xFF3C001F,0xF1400023,0xEB340025,0xFF700A53,0xFF54059A,0xF52C015B,0xDEF001C5,0x95FC0F1A,0x1A805EA,0xFF980303,0xFF8C0162,0xEF8C0153,0xFF8C02DE,0xFF78003B,0xF17C002A,0xF57001A6,0xEB70004B,0xE17001A6,0x7DFC05EA,0xFF5801E4,0xEF640153,0xFF3801BA,0xEF3C0002,
+0xE14C01A5,0xBFFC05EA,0xEEE40153,0xE0CC01A5,0xD20005ED,0x7DFC05EA,0xFF5801E4,0xEF640153,0xFF3801BA,0xEF3C0002,0xE14C01A5,0xBFFC05EA,0xEEE40153,0xE0CC01A5,0xD20005ED,0xBFFC05EA,0xEEE40153,0xE0CC01A5,0xD20005ED,0xD20005ED,0xFF94046D,0xFBA4054E,0xFBA4054B,0xFF8002E8,0xFF680146,0xFF400011,0xF14C0002,0xEF24000B,0xFD940481,0xFF7402C9,0xF71C0152,0xE0CC01A5,
+0xAFFC05EA,0x17005EA,0x17005EA,0x17005EA,0x17005EA,0xFF5C0221,0xFF5C0221,0xFF5C0221,0xE75401A5,0xE75401A5,0xD35401A5,0xFF4401A8,0xFF4401A8,0xFF4401A8,0xED380005,0xED380005,0xD544004C,0xDB380152,0xDB380152,0xCF380029,0xC5380154,0x29FC05EA,0x29FC05EA,0x29FC05EA,0xF90801A5,0xF90801A5,0xD32C01A5,0xECEC0153,0xECEC0153,0xD3000002,0xC5100154,0x97F805EA,
+0x97F805EA,0xD2AC01A5,0xC4900154,0xB60005ED,0xFD6403CC,0xFF6C04ED,0x17005EA,0xFF540211,0xFF4400AD,0xFF3C0006,0xFB3C000C,0xE7380001,0xFF58039E,0xFD4C01E2,0xF12C0152,0xD3000002,0x7BFC05EA,0x18C0152,0x18C0152,0x18C0152,0x18C0152,0xFF740005,0xFF740005,0xFF740005,0xDF740001,0xDF740001,0xD3700001,0x53FC0152,0x53FC0152,0x53FC0152,0xE9440001,0xE9440001,
+0xD3580000,0xABF80152,0xABF80152,0xD3080000,0xC4000154,0x53FC0152,0x53FC0152,0x53FC0152,0xE9440001,0xE9440001,0xD3580000,0xABF80152,0xABF80152,0xD3080000,0xC4000154,0xABF80152,0xABF80152,0xD3080000,0xC4000154,0xC4000154,0xF78000DD,0xFD8800F2,0x18C0152,0xFB700091,0xFF540028,0xFF400001,0xF3480000,0xE7340000,0xFD7400DD,0xFF5C007D,0x95FC0152,0xD3080000,
+0x95FC0152,0x1C401A5,0xFFB00092,0xFDA80001,0xEFA40002,0xA5FC01A5,0xFF880020,0xEF8C0001,0xD3FC01A5,0xEF340001,0xE00001A5,0xA5FC01A5,0xFF880020,0xEF8C0001,0xD3FC01A5,0xEF340001,0xE00001A5,0xD3FC01A5,0xEF340001,0xE00001A5,0xE00001A5,0xA5FC01A5,0xFF880020,0xEF8C0001,0xD3FC01A5,0xEF340001,0xE00001A5,0xD3FC01A5,0xEF340001,0xE00001A5,0xE00001A5,0xD3FC01A5,
+0xEF340001,0xE00001A5,0xE00001A5,0xE00001A5,0xFFB40154,0x1E001A5,0xF9C0016D,0xFFA000FA,0xFF7C0092,0xFF48000A,0xEF540001,0xEF080001,0xFFAC015A,0xFF9400E9,0xF5580000,0xE00001A5,0xC7FC01A5,0x15401A5,0x15401A5,0x15401A5,0x15401A5,0x15401A5,0x15401A5,0x15401A5,0x15401A5,0x15401A5,0x15401A5,0xF3380000,0xF3380000,0xF3380000,0xF3380000,0xF3380000,
+0xF3380000,0xC7380000,0xC7380000,0xC7380000,0xB9380000,0x1F801A5,0x1F801A5,0x1F801A5,0x1F801A5,0x1F801A5,0x1F801A5,0xD5000000,0xD5000000,0xD5000000,0xB91C0000,0x81FC01A5,0x81FC01A5,0x81FC01A5,0xB8C00000,0xAA0001A5,0xFF4C010D,0x15401A5,0x15401A5,0xFD480080,0xFD400034,0xFF3C0005,0xFF3C0005,0xE3380000,0xFF3C00E9,0xFF3C0071,0xD7300000,0xD5000000,
+0x5FFC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table121[] = {
+0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0x79F80000,
+0x79F80000,0x79F80000,0x79F80000,0xA2000001,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x1480000,0x75C0000,0x75C0000,0x75C0000,0x1E80000,0x55FC0000,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x1800001,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,
+0x43FC0000,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xC0000000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0x43FC0000,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xC0000000,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xC0000000,0xC0000000,0x19C0000,0x1800001,0x1800001,0x1C00000,0x1E40000,0x17FC0000,0x17FC0000,0x67FC0000,0x1C00000,0x1E40000,0x8BFC0000,0xA3FC0000,
+0x8BFC0000,0x1B40001,0x1B40001,0x1B40001,0x1B40001,0x93FC0000,0x93FC0000,0x93FC0000,0xCBF80000,0xCBF80000,0xDA000000,0x93FC0000,0x93FC0000,0x93FC0000,0xCBF80000,0xCBF80000,0xDA000000,0xCBF80000,0xCBF80000,0xDA000000,0xDA000000,0x93FC0000,0x93FC0000,0x93FC0000,0xCBF80000,0xCBF80000,0xDA000000,0xCBF80000,0xCBF80000,0xDA000000,0xDA000000,0xCBF80000,
+0xCBF80000,0xDA000000,0xDA000000,0xDA000000,0x3FC0000,0x1D40000,0x1B40001,0x79FC0000,0xA7FC0000,0xBDF80000,0xC3FC0000,0xCFF80000,0x51FC0000,0x93FC0000,0xBDF80000,0xDA000000,0xBDF80000,0x1F00000,0xEBFC0000,0xF5FC0000,0xF6000001,0xEBFC0000,0xF5FC0000,0xF6000001,0xF5FC0000,0xF6000001,0xF6000001,0xEBFC0000,0xF5FC0000,0xF6000001,0xF5FC0000,0xF6000001,
+0xF6000001,0xF5FC0000,0xF6000001,0xF6000001,0xF6000001,0xEBFC0000,0xF5FC0000,0xF6000001,0xF5FC0000,0xF6000001,0xF6000001,0xF5FC0000,0xF6000001,0xF6000001,0xF6000001,0xF5FC0000,0xF6000001,0xF6000001,0xF6000001,0xF6000001,0xDFFC0000,0x97FC0000,0x97FC0000,0xEFFC0000,0xF5F80000,0xF7F40000,0xF6000001,0xF6000001,0xE7FC0000,0xF1FC0000,0xF9C40000,0xF6000001,
+0xF3FC0000,0x19C0F1A,0xFF8C0A17,0xFF84069F,0xF78005EB,0xFF8007FE,0xFF700371,0xFB6C028A,0xFF640362,0xF56401BE,0xE964034A,0xFF740939,0xFF60036B,0xFD58020D,0xFF4C021D,0xF7480006,0xEB4C01BD,0xF74805EA,0xEF3C020F,0xE5400286,0xDB4805ED,0x6BFC0F1A,0xFF4C07E9,0xF94805EB,0xFF2C04BE,0xF92001B6,0xE930034A,0xFF080675,0xF6F40154,0xE70001C5,0xDD1005ED,0xB7F80F1A,
+0xF69C05EB,0xE880034A,0xDA6405ED,0xCC000F1E,0xFF8C0B22,0xF5980DDA,0xF79C0E27,0xFF800738,0xFF680366,0xFF540098,0xF9500023,0xF3440025,0xFF800AF5,0xFF7006AA,0xFD3C015B,0xE70001C5,0xA3FC0F1A,0x1B805EA,0xFFA8037E,0xFFA0019A,0xF79C0153,0xFF980356,0xFF8800A9,0xF98C002A,0xFD8001A6,0xF380004B,0xE98001A6,0x95FC05EA,0xFF7C0248,0xF7740153,0xFF580205,0xF74C0002,
+0xE95C01A5,0xCBFC05EA,0xF6F40153,0xE8DC01A5,0xDA0005ED,0x95FC05EA,0xFF7C0248,0xF7740153,0xFF580205,0xF74C0002,0xE95C01A5,0xCBFC05EA,0xF6F40153,0xE8DC01A5,0xDA0005ED,0xCBFC05EA,0xF6F40153,0xE8DC01A5,0xDA0005ED,0xDA0005ED,0xFBAC04B5,0xFFAC057E,0xF5B8057E,0xFF940349,0xFF7C01D6,0xFF5C005E,0xF95C0002,0xF734000B,0xFFA404B5,0xFF900329,0xFF2C0152,0xE8DC01A5,
+0xBFF805EA,0x18005EA,0x18005EA,0x18005EA,0x18005EA,0xFF6C0266,0xFF6C0266,0xFF6C0266,0xEF6401A5,0xEF6401A5,0xDB6401A5,0xFF5C01E8,0xFF5C01E8,0xFF5C01E8,0xF5480005,0xF5480005,0xDD54004C,0xE3480152,0xE3480152,0xD7480029,0xCD480154,0x41FC05EA,0x41FC05EA,0x41FC05EA,0xFF1C01A6,0xFF1C01A6,0xDB3C01A5,0xF4FC0153,0xF4FC0153,0xDB100002,0xCD200154,0xA1FC05EA,
+0xA1FC05EA,0xDABC01A5,0xCCA00154,0xBE0005ED,0xFF7403FE,0xF77C051E,0x18005EA,0xFF68026D,0xFF5800F9,0xFF50002D,0xFF4C000D,0xEF480001,0xFF6403EA,0xFF5C022E,0xF93C0152,0xDB100002,0x89FC05EA,0x19C0152,0x19C0152,0x19C0152,0x19C0152,0xFD880019,0xFD880019,0xFD880019,0xE7840001,0xE7840001,0xDB800001,0x6BFC0152,0x6BFC0152,0x6BFC0152,0xF1540001,0xF1540001,
+0xDB680000,0xB7F80152,0xB7F80152,0xDB180000,0xCC000154,0x6BFC0152,0x6BFC0152,0x6BFC0152,0xF1540001,0xF1540001,0xDB680000,0xB7F80152,0xB7F80152,0xDB180000,0xCC000154,0xB7F80152,0xB7F80152,0xDB180000,0xCC000154,0xCC000154,0xFF9000DD,0xF5980109,0x19C0152,0xFD8400A2,0xFF70003D,0xFF58000A,0xFB580000,0xEF440000,0xFD8800F2,0xFF740095,0xA3FC0152,0xDB180000,
+0xA3FC0152,0x1D401A5,0xFFC400C1,0xFFB80011,0xF7B40002,0xBDFC01A5,0xFFA00050,0xF79C0001,0xDFF801A5,0xF7440001,0xE80001A5,0xBDFC01A5,0xFFA00050,0xF79C0001,0xDFF801A5,0xF7440001,0xE80001A5,0xDFF801A5,0xF7440001,0xE80001A5,0xE80001A5,0xBDFC01A5,0xFFA00050,0xF79C0001,0xDFF801A5,0xF7440001,0xE80001A5,0xDFF801A5,0xF7440001,0xE80001A5,0xE80001A5,0xDFF801A5,
+0xF7440001,0xE80001A5,0xE80001A5,0xE80001A5,0xFDCC016D,0x1F001A5,0xFFCC0179,0xFDBC0122,0xFFA800C8,0xFF70003A,0xF7640001,0xF7180001,0xF7CC016D,0xFFB80120,0xFD680000,0xE80001A5,0xD7FC01A5,0x16401A5,0x16401A5,0x16401A5,0x16401A5,0x16401A5,0x16401A5,0x16401A5,0x16401A5,0x16401A5,0x16401A5,0xFB480000,0xFB480000,0xFB480000,0xFB480000,0xFB480000,
+0xFB480000,0xCF480000,0xCF480000,0xCF480000,0xC1480000,0x15FC01A5,0x15FC01A5,0x15FC01A5,0x15FC01A5,0x15FC01A5,0x15FC01A5,0xDD100000,0xDD100000,0xDD100000,0xC12C0000,0x8DFC01A5,0x8DFC01A5,0x8DFC01A5,0xC0D00000,0xB20001A5,0xF9600120,0x16401A5,0x16401A5,0xFF580091,0xFF500041,0xFF4C000D,0xFF4C000D,0xEB480000,0xFD5400F2,0xFD4C0082,0xDF400000,0xDD100000,
+0x6FFC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table122[] = {
+0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x3FC0000,0x85F80000,
+0x85F80000,0x85F80000,0x85F80000,0xAA000001,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0xF6C0000,0xF6C0000,0xF6C0000,0x3FC0000,0x63FC0000,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x1900001,0x5BFC0000,0x5BFC0000,0x5BFC0000,0x5BFC0000,0x5BFC0000,
+0x5BFC0000,0xAFFC0000,0xAFFC0000,0xAFFC0000,0xC8000000,0x5BFC0000,0x5BFC0000,0x5BFC0000,0x5BFC0000,0x5BFC0000,0x5BFC0000,0xAFFC0000,0xAFFC0000,0xAFFC0000,0xC8000000,0xAFFC0000,0xAFFC0000,0xAFFC0000,0xC8000000,0xC8000000,0x1AC0000,0x1900001,0x1900001,0x1D40000,0x1F80000,0x35FC0000,0x35FC0000,0x7BFC0000,0x1D40000,0x1F80000,0x9BFC0000,0xAFFC0000,
+0x9BFC0000,0x1C40001,0x1C40001,0x1C40001,0x1C40001,0xABFC0000,0xABFC0000,0xABFC0000,0xD7F80000,0xD7F80000,0xE2000000,0xABFC0000,0xABFC0000,0xABFC0000,0xD7F80000,0xD7F80000,0xE2000000,0xD7F80000,0xD7F80000,0xE2000000,0xE2000000,0xABFC0000,0xABFC0000,0xABFC0000,0xD7F80000,0xD7F80000,0xE2000000,0xD7F80000,0xD7F80000,0xE2000000,0xE2000000,0xD7F80000,
+0xD7F80000,0xE2000000,0xE2000000,0xE2000000,0x3BFC0000,0x1E40000,0x1C40001,0x97FC0000,0xBBFC0000,0xCBFC0000,0xD1FC0000,0xD9FC0000,0x77FC0000,0xABFC0000,0xCBFC0000,0xE2000000,0xCBFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1AC0EC7,0xFF9C0A97,0xFF940717,0xFF9005EA,0xFF9808B1,0xFF84044E,0xFF8002A5,0xFF7C03A7,0xFD7401B9,0xF174032D,0xFF8C09AC,0xFF700455,0xFF680234,0xFF6402A2,0xFF580005,0xF35C01A4,0xFF5805B3,0xF74C01FE,0xED500261,0xE35805B4,0x83FC0EC7,0xFF640876,0xFF5805ED,0xFF4C057F,0xFF3801B9,0xF140032D,0xFF2C06C8,0xFF040153,0xEF1001A4,0xE32005B5,0xC3F80EC7,
+0xFEAC05EA,0xF090032D,0xE27405B4,0xD4000EC9,0xFFA00B5D,0xFDA80D89,0xFDA80DDA,0xFF8807F3,0xFF7C0465,0xFF680153,0xFF600030,0xFB54001C,0xFF980B2F,0xFF800755,0xFF50016C,0xEF1001A4,0xB3FC0EC7,0x1C805B3,0xFFBC03B6,0xFFAC01FB,0xFFAC0152,0xFFB00389,0xFFA00122,0xFF98002D,0xFF94019B,0xFB900042,0xF1900189,0xAFFC05B3,0xFF9402A5,0xFF840152,0xFF70024E,0xFF5C0001,
+0xF16C0188,0xD7FC05B3,0xFF040152,0xF0EC0188,0xE20005B4,0xAFFC05B3,0xFF9402A5,0xFF840152,0xFF70024E,0xFF5C0001,0xF16C0188,0xD7FC05B3,0xFF040152,0xF0EC0188,0xE20005B4,0xD7FC05B3,0xFF040152,0xF0EC0188,0xE20005B4,0xE20005B4,0xFFBC04B5,0xFBC4054B,0xFBC4054B,0xFFB003A2,0xFF900261,0xFF7C00D1,0xFF6C0004,0xFD480009,0xFFB404BE,0xFFA40388,0xFF50016B,0xF0EC0188,
+0xCDFC05B3,0x19005EA,0x19005EA,0x19005EA,0x19005EA,0xFF8002A5,0xFF8002A5,0xFF8002A5,0xF77401A5,0xF77401A5,0xE37401A5,0xFF680234,0xFF680234,0xFF680234,0xFD580005,0xFD580005,0xE564004C,0xEB580152,0xEB580152,0xDF580029,0xD5580154,0x59FC05EA,0x59FC05EA,0x59FC05EA,0xFF3801B9,0xFF3801B9,0xE34C01A5,0xFD0C0153,0xFD0C0153,0xE3200002,0xD5300154,0xADFC05EA,
+0xADFC05EA,0xE2CC01A5,0xD4B00154,0xC60005ED,0xFF84042D,0xFF8C051E,0x19005EA,0xFF7802C9,0xFF6C0155,0xFF64006D,0xFF600030,0xF7580001,0xFF780411,0xFF740289,0xFF500153,0xE3200002,0x99FC05EA,0x1AC0152,0x1AC0152,0x1AC0152,0x1AC0152,0xFF98002D,0xFF98002D,0xFF98002D,0xEF940001,0xEF940001,0xE3900001,0x83FC0152,0x83FC0152,0x83FC0152,0xF9640001,0xF9640001,
+0xE3780000,0xC3F80152,0xC3F80152,0xE3280000,0xD4000154,0x83FC0152,0x83FC0152,0x83FC0152,0xF9640001,0xF9640001,0xE3780000,0xC3F80152,0xC3F80152,0xE3280000,0xD4000154,0xC3F80152,0xC3F80152,0xE3280000,0xD4000154,0xD4000154,0xFFA000F4,0xFDA80109,0x1AC0152,0xFF9800B5,0xFF840059,0xFF740019,0xFF6C0004,0xF7540000,0xFF940104,0xFB9000B5,0xB3FC0152,0xE3280000,
+0xB3FC0152,0x1E0018A,0xFFDC00F2,0xFFCC0049,0xFFC40001,0xD5FC0188,0xFFB80089,0xFFAC0000,0xEBF80188,0xFF540000,0xF0000188,0xD5FC0188,0xFFB80089,0xFFAC0000,0xEBF80188,0xFF540000,0xF0000188,0xEBF80188,0xFF540000,0xF0000188,0xF0000188,0xD5FC0188,0xFFB80089,0xFFAC0000,0xEBF80188,0xFF540000,0xF0000188,0xEBF80188,0xFF540000,0xF0000188,0xF0000188,0xEBF80188,
+0xFF540000,0xF0000188,0xF0000188,0xF0000188,0xF3E0016D,0x27FC0188,0xF9E0016D,0xFDD40139,0xFFBC00E9,0xFF980074,0xFF740000,0xFF280000,0xFDD80154,0xFFCC0122,0xFF90000D,0xF0000188,0xE5FC0188,0x17401A5,0x17401A5,0x17401A5,0x17401A5,0x17401A5,0x17401A5,0x17401A5,0x17401A5,0x17401A5,0x17401A5,0xFD580004,0xFD580004,0xFD580004,0xFD580004,0xFD580004,
+0xFD580004,0xD7580000,0xD7580000,0xD7580000,0xC9580000,0x2FFC01A5,0x2FFC01A5,0x2FFC01A5,0x2FFC01A5,0x2FFC01A5,0x2FFC01A5,0xE5200000,0xE5200000,0xE5200000,0xC93C0000,0x99FC01A5,0x99FC01A5,0x99FC01A5,0xC8E00000,0xBA0001A5,0xFF6C0128,0x17401A5,0x17401A5,0xFF6800A4,0xFF640055,0xFF5C001D,0xFF5C001D,0xF3580000,0xF9680109,0xFD6000A2,0xE7500000,0xE5200000,
+0x7FF801A5,};
+static const uint32_t g_etc1_to_bc7_m6_table123[] = {
+0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x91F80000,
+0x91F80000,0x91F80000,0x91F80000,0xB2000001,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1800000,0x1800000,0x1800000,0x1BFC0000,0x73FC0000,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x1A00001,0x75FC0000,0x75FC0000,0x75FC0000,0x75FC0000,0x75FC0000,
+0x75FC0000,0xBBFC0000,0xBBFC0000,0xBBFC0000,0xD0000000,0x75FC0000,0x75FC0000,0x75FC0000,0x75FC0000,0x75FC0000,0x75FC0000,0xBBFC0000,0xBBFC0000,0xBBFC0000,0xD0000000,0xBBFC0000,0xBBFC0000,0xBBFC0000,0xD0000000,0xD0000000,0x7BC0000,0x1A00001,0x1A00001,0x5E40000,0x1FFC0000,0x53FC0000,0x53FC0000,0x8FFC0000,0x5E40000,0x1FFC0000,0xA9FC0000,0xBBFC0000,
+0xA9FC0000,0x1D40001,0x1D40001,0x1D40001,0x1D40001,0xC3FC0000,0xC3FC0000,0xC3FC0000,0xE1FC0000,0xE1FC0000,0xEA000000,0xC3FC0000,0xC3FC0000,0xC3FC0000,0xE1FC0000,0xE1FC0000,0xEA000000,0xE1FC0000,0xE1FC0000,0xEA000000,0xEA000000,0xC3FC0000,0xC3FC0000,0xC3FC0000,0xE1FC0000,0xE1FC0000,0xEA000000,0xE1FC0000,0xE1FC0000,0xEA000000,0xEA000000,0xE1FC0000,
+0xE1FC0000,0xEA000000,0xEA000000,0xEA000000,0x75FC0000,0x3F40000,0x1D40001,0xB5FC0000,0xCFFC0000,0xDBFC0000,0xDFF80000,0xE5F40000,0x9FFC0000,0xC3FC0000,0xDBFC0000,0xEA000000,0xDBFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1B80C63,0xFFB0094E,0xFFA006CB,0xFFA005EA,0xFFA4076D,0xFF940436,0xFF8C0301,0xFF880313,0xFF8401A5,0xF584026D,0xFF980818,0xFF88041D,0xFF800284,0xFF7C0222,0xFF6C001D,0xF56C00F0,0xFF6C0438,0xFB600192,0xF1640165,0xE9680428,0x95FC0C63,0xFF7C07BE,0xFF7005ED,0xFF6404BF,0xFF4C01F6,0xF554026D,0xFF380594,0xFF280163,0xF32400D8,0xE9340428,0xCBFC0C63,
+0xFEE005EA,0xF4B4026D,0xE88C0428,0xDA000C65,0xFFA809C9,0xFFAC0B85,0xF5B80BDB,0xFF9806E9,0xFF8C041A,0xFF7C0175,0xFF78007A,0xFF680001,0xFFA409B3,0xFF90067F,0xFF640186,0xF32400D8,0xBFF80C63,0x1D0042B,0xFFC402DB,0xFFC001BE,0xFFBC0152,0xFFC4028B,0xFFB400FA,0xFFB00055,0xFFA800F1,0xFDA0000E,0xF5A000C9,0xBDFC0428,0xFFAC022D,0xFF9C0152,0xFF88018E,0xFF780005,
+0xF58000C8,0xDFF80428,0xFF340152,0xF50C00C8,0xE8000428,0xBDFC0428,0xFFAC022D,0xFF9C0152,0xFF88018E,0xFF780005,0xF58000C8,0xDFF80428,0xFF340152,0xF50C00C8,0xE8000428,0xDFF80428,0xFF340152,0xF50C00C8,0xE8000428,0xE8000428,0xFDCC0378,0xFFCC03D3,0xFFCC03E3,0xFFC002B6,0xFFA801D5,0xFF9000C1,0xFF880019,0xFF640000,0xFFC4037B,0xFDBC02B6,0xFF700162,0xF50C00C8,
+0xD7FC0428,0x1A005EA,0x1A005EA,0x1A005EA,0x1A005EA,0xFF8C0301,0xFF8C0301,0xFF8C0301,0xFF8401A5,0xFF8401A5,0xEB8401A5,0xFF800284,0xFF800284,0xFF800284,0xFF6C001D,0xFF6C001D,0xED74004C,0xF3680152,0xF3680152,0xE7680029,0xDD680154,0x71FC05EA,0x71FC05EA,0x71FC05EA,0xFF4C01F6,0xFF4C01F6,0xEB5C01A5,0xFF280163,0xFF280163,0xEB300002,0xDD400154,0xB9FC05EA,
+0xB9FC05EA,0xEADC01A5,0xDCC00154,0xCE0005ED,0xFB980484,0xF79C0551,0x1A005EA,0xFF900321,0xFF8001C1,0xFF7800C2,0xFF78007A,0xFF680001,0xFF900452,0xFF8002F4,0xFF64016D,0xEB300002,0xA7FC05EA,0x1BC0152,0x1BC0152,0x1BC0152,0x1BC0152,0xFFB00055,0xFFB00055,0xFFB00055,0xF7A40001,0xF7A40001,0xEBA00001,0x9BFC0152,0x9BFC0152,0x9BFC0152,0xFF780005,0xFF780005,
+0xEB880000,0xCFF80152,0xCFF80152,0xEB380000,0xDC000154,0x9BFC0152,0x9BFC0152,0x9BFC0152,0xFF780005,0xFF780005,0xEB880000,0xCFF80152,0xCFF80152,0xEB380000,0xDC000154,0xCFF80152,0xCFF80152,0xEB380000,0xDC000154,0xDC000154,0xFBB40109,0xF5B80122,0x1BC0152,0xFFA400DA,0xFF98007D,0xFF8C0041,0xFF880019,0xFF640000,0xFDB00109,0xFFA400C8,0xC1FC0152,0xEB380000,
+0xC1FC0152,0x1E800CA,0xFFE0007D,0xFFD80025,0xFFD40001,0xE3FC00C8,0xFFCC0049,0xFFC00001,0xF1F800C8,0xFF840000,0xF40000C8,0xE3FC00C8,0xFFCC0049,0xFFC00001,0xF1F800C8,0xFF840000,0xF40000C8,0xF1F800C8,0xFF840000,0xF40000C8,0xF40000C8,0xE3FC00C8,0xFFCC0049,0xFFC00001,0xF1F800C8,0xFF840000,0xF40000C8,0xF1F800C8,0xFF840000,0xF40000C8,0xF40000C8,0xF1F800C8,
+0xFF840000,0xF40000C8,0xF40000C8,0xF40000C8,0xF7E800B5,0x67FC00C8,0xFDE800B5,0xFFD8009D,0xFFD00075,0xFFC0003D,0xFF9C0000,0xFF640000,0xFFDC00B4,0xFFD80095,0xFFB00008,0xF40000C8,0xEDFC00C8,0x18401A5,0x18401A5,0x18401A5,0x18401A5,0x18401A5,0x18401A5,0x18401A5,0x18401A5,0x18401A5,0x18401A5,0xFF6C000D,0xFF6C000D,0xFF6C000D,0xFF6C000D,0xFF6C000D,
+0xFF6C000D,0xDF680000,0xDF680000,0xDF680000,0xD1680000,0x47FC01A5,0x47FC01A5,0x47FC01A5,0x47FC01A5,0x47FC01A5,0x47FC01A5,0xED300000,0xED300000,0xED300000,0xD14C0000,0xA5F801A5,0xA5F801A5,0xA5F801A5,0xD0F00000,0xC20001A5,0xF9800139,0x18401A5,0x18401A5,0xFB7C00C8,0xFF780071,0xFF700034,0xFF700034,0xFB680000,0xFF74010D,0xFD7400B5,0xEF600000,0xED300000,
+0x8DFC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table124[] = {
+0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x9DFC0000,
+0x9DFC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1940000,0x1940000,0x1940000,0x37FC0000,0x83FC0000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,
+0x8FFC0000,0xC9F80000,0xC9F80000,0xC9F80000,0xD8000001,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0x8FFC0000,0xC9F80000,0xC9F80000,0xC9F80000,0xD8000001,0xC9F80000,0xC9F80000,0xC9F80000,0xD8000001,0xD8000001,0x1D00000,0x1B40000,0x1B40000,0x1FC0000,0x4BFC0000,0x75FC0000,0x75FC0000,0xA5FC0000,0x1FC0000,0x4BFC0000,0xBBFC0000,0xC9F80000,
+0xBBFC0000,0x1E80000,0x1E80000,0x1E80000,0x1E80000,0xDFFC0000,0xDFFC0000,0xDFFC0000,0xEFFC0000,0xEFFC0000,0xF2000001,0xDFFC0000,0xDFFC0000,0xDFFC0000,0xEFFC0000,0xEFFC0000,0xF2000001,0xEFFC0000,0xEFFC0000,0xF2000001,0xF2000001,0xDFFC0000,0xDFFC0000,0xDFFC0000,0xEFFC0000,0xEFFC0000,0xF2000001,0xEFFC0000,0xEFFC0000,0xF2000001,0xF2000001,0xEFFC0000,
+0xEFFC0000,0xF2000001,0xF2000001,0xF2000001,0xB5FC0000,0x57FC0000,0x1E80000,0xD7FC0000,0xE5FC0000,0xEBFC0000,0xEDFC0000,0xF1F80000,0xCBFC0000,0xDFFC0000,0xEBFC0000,0xF2000001,0xEBFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1C40A26,0xFFBC0819,0xFFB4067D,0xFFB005ED,0xFFB00662,0xFFA8043D,0xFFA40362,0xFFA002BE,0xFF9801C9,0xF99801E2,0xFFA406D7,0xFF9C0415,0xFF9802FB,0xFF8801E3,0xFF84007A,0xFB840073,0xFF84031B,0xFD780159,0xF77000A2,0xEF7802D3,0xA9FC0A26,0xFF940717,0xFF8C05EA,0xFF7C0432,0xFF70024D,0xF96801E2,0xFF640489,0xFF4C01A8,0xF93C003F,0xEF4802D2,0xD5F80A26,
+0xFF1405EA,0xF8D801E2,0xEEAC02D2,0xE2000A26,0xFFBC082A,0xFBC40972,0xFBC409B6,0xFFAC061E,0xFFA003F3,0xFF9001DC,0xFF8C00FA,0xFF7C0029,0xFFB407F7,0xFFA405EA,0xFF7C01C3,0xF93C003F,0xC9FC0A26,0x1DC02D5,0xFFD40228,0xFFCC0194,0xFFCC0154,0xFFD001B5,0xFFC400E4,0xFFC40080,0xFFB8007D,0xFFB40001,0xF9B4003D,0xCFFC02D2,0xFFC001C8,0xFFB80152,0xFFAC00FE,0xFF940025,
+0xF994003E,0xE7FC02D2,0xFF6C0152,0xF934003D,0xEE0002D2,0xCFFC02D2,0xFFC001C8,0xFFB80152,0xFFAC00FE,0xFF940025,0xF994003E,0xE7FC02D2,0xFF6C0152,0xF934003D,0xEE0002D2,0xE7FC02D2,0xFF6C0152,0xF934003D,0xEE0002D2,0xEE0002D2,0xFFD80263,0xF7DC02A9,0xF7DC02B4,0xFDD00209,0xFFC0016A,0xFFAC00B1,0xFFA8003D,0xFF8C0019,0xFDD8026D,0xFFC801D6,0xFF98015B,0xF934003D,
+0xE1FC02D2,0x1B005ED,0x1B005ED,0x1B005ED,0x1B005ED,0xFFA40362,0xFFA40362,0xFFA40362,0xFF9801C9,0xFF9801C9,0xF39801A6,0xFF9802FB,0xFF9802FB,0xFF9802FB,0xFF84007A,0xFF84007A,0xF584004B,0xFB7C0153,0xFB7C0153,0xEF78002A,0xE7780153,0x8DFC05EA,0x8DFC05EA,0x8DFC05EA,0xFF70024D,0xFF70024D,0xF37001A6,0xFF4C01A8,0xFF4C01A8,0xF5440001,0xE7500152,0xC7FC05EA,
+0xC7FC05EA,0xF2F001A6,0xE6CC0152,0xD80005EA,0xFFAC04B2,0xFFAC055A,0x1B005ED,0xFFA403A1,0xFF940252,0xFF900163,0xFF8C00FA,0xFF7C0029,0xFFA00491,0xFF980365,0xFF7C01B3,0xF5440001,0xB9FC05EA,0x1CC0154,0x1CC0154,0x1CC0154,0x1CC0154,0xFFC40080,0xFFC40080,0xFFC40080,0xFFB40001,0xFFB40001,0xF3B40001,0xB7FC0152,0xB7FC0152,0xB7FC0152,0xFF940025,0xFF940025,
+0xF39C0001,0xDDF40152,0xDDF40152,0xF34C0001,0xE6000152,0xB7FC0152,0xB7FC0152,0xB7FC0152,0xFF940025,0xFF940025,0xF39C0001,0xDDF40152,0xDDF40152,0xF34C0001,0xE6000152,0xDDF40152,0xDDF40152,0xF34C0001,0xE6000152,0xE6000152,0xFDC80120,0xFFCC0120,0x1CC0154,0xFDC000F4,0xFFB000B4,0xFFA8006A,0xFFA8003D,0xFF8C0019,0xFFC40120,0xFBC000F2,0xD3FC0152,0xF34C0001,
+0xD3FC0152,0x1F4003D,0xFFEC0028,0xFFEC000D,0xFFE80000,0xEFFC003D,0xFFE40014,0xFFDC0000,0xF7F8003D,0xFFB80000,0xF800003D,0xEFFC003D,0xFFE40014,0xFFDC0000,0xF7F8003D,0xFFB80000,0xF800003D,0xF7F8003D,0xFFB80000,0xF800003D,0xF800003D,0xEFFC003D,0xFFE40014,0xFFDC0000,0xF7F8003D,0xFFB80000,0xF800003D,0xF7F8003D,0xFFB80000,0xF800003D,0xF800003D,0xF7F8003D,
+0xFFB80000,0xF800003D,0xF800003D,0xF800003D,0xFBF00034,0xA7FC003D,0xF3F4003D,0xFFEC0029,0xFFE80020,0xFFD40011,0xFFC80000,0xFFA80000,0xFFF00032,0xFFEC0032,0xFFD00001,0xF800003D,0xF5FC003D,0x19801A5,0x19801A5,0x19801A5,0x19801A5,0x19801A5,0x19801A5,0x19801A5,0x19801A5,0x19801A5,0x19801A5,0xFF800022,0xFF800022,0xFF800022,0xFF800022,0xFF800022,
+0xFF800022,0xE77C0001,0xE77C0001,0xE77C0001,0xD9780002,0x63FC01A5,0x63FC01A5,0x63FC01A5,0x63FC01A5,0x63FC01A5,0x63FC01A5,0xF5440000,0xF5440000,0xF5440000,0xD9600001,0xB3F801A5,0xB3F801A5,0xB3F801A5,0xD9080001,0xCA0001A5,0xFF8C0151,0x19801A5,0x19801A5,0xFF9000DD,0xFF8C0091,0xFF880055,0xFF880055,0xFD7C0005,0xFD8C0120,0xFF8000DA,0xF7740001,0xF5440000,
+0x9FF801A5,};
+static const uint32_t g_etc1_to_bc7_m6_table125[] = {
+0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0xA9FC0000,
+0xA9FC0000,0xA9FC0000,0xA9FC0000,0xC4000000,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1880001,0x1A40000,0x1A40000,0x1A40000,0x4FFC0000,0x93FC0000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0x1C40000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,
+0xA9FC0000,0xD5F80000,0xD5F80000,0xD5F80000,0xE0000001,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xA9FC0000,0xD5F80000,0xD5F80000,0xD5F80000,0xE0000001,0xD5F80000,0xD5F80000,0xD5F80000,0xE0000001,0xE0000001,0x9E00000,0x1C40000,0x1C40000,0x35FC0000,0x73FC0000,0x93FC0000,0x93FC0000,0xB9FC0000,0x35FC0000,0x73FC0000,0xC9FC0000,0xD5F80000,
+0xC9FC0000,0x1F80000,0x1F80000,0x1F80000,0x1F80000,0xF7FC0000,0xF7FC0000,0xF7FC0000,0xFBFC0000,0xFBFC0000,0xFA000001,0xF7FC0000,0xF7FC0000,0xF7FC0000,0xFBFC0000,0xFBFC0000,0xFA000001,0xFBFC0000,0xFBFC0000,0xFA000001,0xFA000001,0xF7FC0000,0xF7FC0000,0xF7FC0000,0xFBFC0000,0xFBFC0000,0xFA000001,0xFBFC0000,0xFBFC0000,0xFA000001,0xFA000001,0xFBFC0000,
+0xFBFC0000,0xFA000001,0xFA000001,0xFA000001,0xEDFC0000,0xD7FC0000,0x1F80000,0xF5FC0000,0xF9FC0000,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xF3FC0000,0xF7FC0000,0xFBFC0000,0xFA000001,0xFBFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1D0088E,0xFFC80749,0xFFC00651,0xFFC005ED,0xFFC405B2,0xFFBC0463,0xFFB403DD,0xFFAC02BE,0xFFAC0215,0xFDA801AA,0xFFBC05EF,0xFFB0042C,0xFFA40383,0xFFA001F3,0xFF9C010A,0xFD94004F,0xFF94028E,0xFF900163,0xFB84003E,0xF58801FF,0xBBFC088E,0xFFAC069F,0xFFA405EA,0xFF9403FA,0xFF8802BD,0xFD7C01AA,0xFF7C0401,0xFF640218,0xFD540005,0xF55C01FE,0xDDFC088E,
+0xFF4805EA,0xFCF801AA,0xF4C401FE,0xE800088E,0xFFCC0739,0xFFCC07F2,0xFFCC0846,0xFFC005B1,0xFFB003FD,0xFFA4024E,0xFFA4019A,0xFF940096,0xFFC4071A,0xFFB40585,0xFF94023D,0xFD540005,0xD5FC088E,0x1E801FD,0xFDE401B5,0xFFE0016D,0xFFDC0154,0xFFDC0149,0xFFD400EA,0xFFD000B4,0xFFCC0069,0xFFC80028,0xFDC40005,0xDFFC01FD,0xFFD80188,0xFFCC0154,0xFFB800D2,0xFFB80059,
+0xFDA80006,0xEFFC01FD,0xFF9C0152,0xFD540005,0xF40001FE,0xDFFC01FD,0xFFD80188,0xFFCC0154,0xFFB800D2,0xFFB80059,0xFDA80006,0xEFFC01FD,0xFF9C0152,0xFD540005,0xF40001FE,0xEFFC01FD,0xFF9C0152,0xFD540005,0xF40001FE,0xF40001FE,0xFFE401C5,0xFDE801D9,0xFDE801E8,0xFFDC0179,0xFFD40132,0xFFC800CE,0xFFBC007D,0xFFA80049,0xFFE001CA,0xFFDC0172,0xFFB80156,0xFD540005,
+0xEBFC01FD,0x1C005ED,0x1C005ED,0x1C005ED,0x1C005ED,0xFFB403DD,0xFFB403DD,0xFFB403DD,0xFFAC0215,0xFFAC0215,0xFBA801A6,0xFFA40383,0xFFA40383,0xFFA40383,0xFF9C010A,0xFF9C010A,0xFD94004B,0xFF900163,0xFF900163,0xF788002A,0xEF880153,0xA5FC05EA,0xA5FC05EA,0xA5FC05EA,0xFF8802BD,0xFF8802BD,0xFB8001A6,0xFF640218,0xFF640218,0xFD540001,0xEF600152,0xD3FC05EA,
+0xD3FC05EA,0xFB0001A6,0xEEDC0152,0xE00005EA,0xFFBC04E6,0xF9C00581,0x1C005ED,0xFFB40402,0xFFAC02EA,0xFFA401FD,0xFFA4019A,0xFF940096,0xFFB404BE,0xFFB003CE,0xFF940234,0xFD540001,0xC7FC05EA,0x1DC0154,0x1DC0154,0x1DC0154,0x1DC0154,0xFFD000B4,0xFFD000B4,0xFFD000B4,0xFFC80028,0xFFC80028,0xFBC40001,0xCFFC0152,0xCFFC0152,0xCFFC0152,0xFFB80059,0xFFB80059,
+0xFBAC0001,0xE7FC0152,0xE7FC0152,0xFB5C0001,0xEE000152,0xCFFC0152,0xCFFC0152,0xCFFC0152,0xFFB80059,0xFFB80059,0xFBAC0001,0xE7FC0152,0xE7FC0152,0xFB5C0001,0xEE000152,0xE7FC0152,0xE7FC0152,0xFB5C0001,0xEE000152,0xEE000152,0xFFD80122,0xF7DC0139,0x1DC0154,0xFDD80109,0xFFC800DA,0xFFBC00A9,0xFFBC007D,0xFFA80049,0xFFD00132,0xFBD40109,0xE1FC0152,0xFB5C0001,
+0xE1FC0152,0x1FC0005,0xFFF80004,0xFFF80001,0xFFF80000,0xFBFC0005,0xFFF80002,0xFFF40000,0xFDF80005,0xFFEC0000,0xFC000005,0xFBFC0005,0xFFF80002,0xFFF40000,0xFDF80005,0xFFEC0000,0xFC000005,0xFDF80005,0xFFEC0000,0xFC000005,0xFC000005,0xFBFC0005,0xFFF80002,0xFFF40000,0xFDF80005,0xFFEC0000,0xFC000005,0xFDF80005,0xFFEC0000,0xFC000005,0xFC000005,0xFDF80005,
+0xFFEC0000,0xFC000005,0xFC000005,0xFC000005,0xFFF80004,0xE7FC0005,0xF7FC0005,0xFBFC0005,0xFFF80002,0xFFF00001,0xFFF00000,0xFFE40000,0xF9FC0005,0xFBFC0005,0xFFF00000,0xFC000005,0xFDF80005,0x1A801A5,0x1A801A5,0x1A801A5,0x1A801A5,0x1A801A5,0x1A801A5,0x1A801A5,0x1A801A5,0x1A801A5,0x1A801A5,0xFF900049,0xFF900049,0xFF900049,0xFF900049,0xFF900049,
+0xFF900049,0xEF8C0001,0xEF8C0001,0xEF8C0001,0xE1880002,0x7BFC01A5,0x7BFC01A5,0x7BFC01A5,0x7BFC01A5,0x7BFC01A5,0x7BFC01A5,0xFD540000,0xFD540000,0xFD540000,0xE1700001,0xBFF801A5,0xBFF801A5,0xBFF801A5,0xE1180001,0xD20001A5,0xFBA40152,0x1A801A5,0x1A801A5,0xFFA000F2,0xFD9C00B5,0xFF980071,0xFF980071,0xFD900019,0xFD9C0139,0xFF9400E9,0xFF840001,0xFD540000,
+0xADFC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table126[] = {
+0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0x69FC0000,0xB5FC0000,
+0xB5FC0000,0xB5FC0000,0xB5FC0000,0xCC000000,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x1980001,0x3B40000,0x3B40000,0x3B40000,0x69FC0000,0xA1FC0000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0x1D40000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,
+0xC1FC0000,0xE1F80000,0xE1F80000,0xE1F80000,0xE8000001,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xE1F80000,0xE1F80000,0xE1F80000,0xE8000001,0xE1F80000,0xE1F80000,0xE1F80000,0xE8000001,0xE8000001,0x1F40000,0x1D40000,0x1D40000,0x6DFC0000,0x9BFC0000,0xB1FC0000,0xB1FC0000,0xCDFC0000,0x6DFC0000,0x9BFC0000,0xD9FC0000,0xE1F80000,
+0xD9FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1DC0693,0xFFD405C6,0xFFD0052E,0xFFD004EE,0xFFD0049F,0xFFC403C6,0xFFC40362,0xFFC00295,0xFFB8021E,0xFFB801A5,0xFFC4048F,0xFFBC037F,0xFFBC0306,0xFFAC01D4,0xFFAC012B,0xFFA4006A,0xFFAC01E3,0xFFA0010E,0xFF980011,0xF798012A,0xC9FC0691,0xFFB80566,0xFFB804ED,0xFFAC0367,0xFFA0029E,0xFF9401A5,0xFF940316,0xFF8801D1,0xFF700008,0xF7700129,0xE5F80691,
+0xFF6C04ED,0xFF2001A5,0xF6EC0129,0xEC000691,0xFFD805AB,0xF5D8064D,0xF5D80672,0xFFCC0496,0xFFC00366,0xFFB8022B,0xFFB401AE,0xFFA800C3,0xFFD00576,0xFFC4045F,0xFFB001FA,0xFF700008,0xDFF80691,0x1F00126,0xFFEC0105,0xFFEC00EA,0xFFE800DD,0xFFE800C6,0xFFE000A1,0xFFE00088,0xFFD8004C,0xFFD80028,0xFFD40000,0xEBFC0126,0xFFE400F1,0xFFDC00DD,0xFFD80088,0xFFCC0050,
+0xFFC00000,0xF5FC0126,0xFFB800DD,0xFF7C0000,0xF6000129,0xEBFC0126,0xFFE400F1,0xFFDC00DD,0xFFD80088,0xFFCC0050,0xFFC00000,0xF5FC0126,0xFFB800DD,0xFF7C0000,0xF6000129,0xF5FC0126,0xFFB800DD,0xFF7C0000,0xF6000129,0xF6000129,0xFDF0010C,0xFFEC0110,0xFFEC0121,0xFFEC00F3,0xFFDC00C6,0xFFD80092,0xFFD00061,0xFFC00049,0xFFEC010B,0xFFE800E5,0xFFD000DE,0xFF7C0000,
+0xF3FC0126,0x1D004EE,0x1D004EE,0x1D004EE,0x1D004EE,0xFFC40362,0xFFC40362,0xFFC40362,0xFFB8021E,0xFFB8021E,0xFFB801A5,0xFFBC0306,0xFFBC0306,0xFFBC0306,0xFFAC012B,0xFFAC012B,0xFFA4006A,0xFFA0010E,0xFFA0010E,0xFD98000E,0xF59800DE,0xB7FC04ED,0xB7FC04ED,0xB7FC04ED,0xFFA0029E,0xFFA0029E,0xFF9401A5,0xFF8801D1,0xFF8801D1,0xFF700008,0xF57400DD,0xDDF404ED,
+0xDDF404ED,0xFF2001A5,0xF4F400DD,0xE60004ED,0xFFCC042E,0xFFCC0492,0x1D004EE,0xFFC40382,0xFFC002BD,0xFFB401EE,0xFFB401AE,0xFFA800C3,0xFBC8042D,0xFFBC0366,0xFFA801F5,0xFF700008,0xD3FC04ED,0x1E800DD,0x1E800DD,0x1E800DD,0x1E800DD,0xFFE00088,0xFFE00088,0xFFE00088,0xFFD80028,0xFFD80028,0xFFD40000,0xDFFC00DD,0xDFFC00DD,0xDFFC00DD,0xFFCC0050,0xFFCC0050,
+0xFFC00000,0xEFFC00DD,0xEFFC00DD,0xFF7C0000,0xF40000DD,0xDFFC00DD,0xDFFC00DD,0xDFFC00DD,0xFFCC0050,0xFFCC0050,0xFFC00000,0xEFFC00DD,0xEFFC00DD,0xFF7C0000,0xF40000DD,0xEFFC00DD,0xEFFC00DD,0xFF7C0000,0xF40000DD,0xF40000DD,0xF9E800C8,0xFDE800C8,0x1E800DD,0xFFDC00B4,0xFFDC0095,0xFFD80082,0xFFD00061,0xFFC00049,0xF7E800C8,0xFFDC00AA,0xEBFC00DD,0xFF7C0000,
+0xEBFC00DD,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1B801A5,0x1B801A5,0x1B801A5,0x1B801A5,0x1B801A5,0x1B801A5,0x1B801A5,0x1B801A5,0x1B801A5,0x1B801A5,0xFFA4006A,0xFFA4006A,0xFFA4006A,0xFFA4006A,0xFFA4006A,
+0xFFA4006A,0xF79C0001,0xF79C0001,0xF79C0001,0xE9980002,0x93FC01A5,0x93FC01A5,0x93FC01A5,0x93FC01A5,0x93FC01A5,0x93FC01A5,0xFF700008,0xFF700008,0xFF700008,0xE9800001,0xCBF801A5,0xCBF801A5,0xCBF801A5,0xE9280001,0xDA0001A5,0xF3B4016D,0x1B801A5,0x1B801A5,0xFFAC0115,0xFFA800DA,0xFFAC00A2,0xFFAC00A2,0xFFA0003A,0xF9B00152,0xFBAC0109,0xFF98000D,0xFF700008,
+0xBDF801A5,};
+static const uint32_t g_etc1_to_bc7_m6_table127[] = {
+0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0xC1FC0000,
+0xC1FC0000,0xC1FC0000,0xC1FC0000,0xD4000000,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0xBC40000,0xBC40000,0xBC40000,0x81FC0000,0xB1FC0000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,
+0xD9FC0000,0xEDF80000,0xEDF80000,0xEDF80000,0xF0000001,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xEDF80000,0xEDF80000,0xEDF80000,0xF0000001,0xEDF80000,0xEDF80000,0xEDF80000,0xF0000001,0xF0000001,0x37FC0000,0x1E40000,0x1E40000,0xA7FC0000,0xC1FC0000,0xCFFC0000,0xCFFC0000,0xE1FC0000,0xA7FC0000,0xC1FC0000,0xE7FC0000,0xEDF80000,
+0xE7FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1E4049B,0xFFDC041B,0xFFD803C2,0xFFD8039E,0xFFDC0373,0xFFD002EE,0xFFD002AE,0xFFCC0231,0xFFCC01F1,0xFFC801A5,0xFFD0032F,0xFFD0028E,0xFFC40236,0xFFC00181,0xFFBC011B,0xFFBC00A2,0xFFB80127,0xFFAC00AA,0xFFAC0001,0xFBA80072,0xD5FC0499,0xFFCC03E2,0xFFC8039D,0xFFB802AF,0xFFB80236,0xFFAC01A5,0xFFAC0216,0xFFA00149,0xFF880028,0xFB840071,0xEBF80499,
+0xFF90039D,0xFF5401A5,0xFB0C0071,0xF0000499,0xFFD8040B,0xF9E00465,0xF9E00482,0xFFD40343,0xFFCC0297,0xFFC401D1,0xFFBC0173,0xFFB800C2,0xFFD803EE,0xFFD0031A,0xFFB8015E,0xFF880028,0xE5FC0499,0x1F40072,0xFFF40062,0xFFF00059,0xFFF00055,0xFFF40052,0xFFEC003D,0xFFEC0034,0xFFE40020,0xFFE40010,0xFFE40000,0xF5FC0071,0xFFF0005D,0xFFE80055,0xFFE40030,0xFFE40020,
+0xFFD80000,0xF9FC0071,0xFFD40055,0xFFAC0000,0xFA000071,0xF5FC0071,0xFFF0005D,0xFFE80055,0xFFE40030,0xFFE40020,0xFFD80000,0xF9FC0071,0xFFD40055,0xFFAC0000,0xFA000071,0xF9FC0071,0xFFD40055,0xFFAC0000,0xFA000071,0xFA000071,0xFFF40060,0xF3F40072,0xF3F40072,0xFFF0005A,0xFFF0004A,0xFFE40036,0xFFE40022,0xFFD8001D,0xFDF40060,0xFFF0005A,0xFFE00056,0xFFAC0000,
+0xF9FC0071,0x1D8039E,0x1D8039E,0x1D8039E,0x1D8039E,0xFFD002AE,0xFFD002AE,0xFFD002AE,0xFFCC01F1,0xFFCC01F1,0xFFC801A5,0xFFC40236,0xFFC40236,0xFFC40236,0xFFBC011B,0xFFBC011B,0xFFBC00A2,0xFFAC00AA,0xFFAC00AA,0xFFAC0001,0xF9A80056,0xC9FC039D,0xC9FC039D,0xC9FC039D,0xFFB80236,0xFFB80236,0xFFAC01A5,0xFFA00149,0xFFA00149,0xFF880028,0xF9880055,0xE5F8039D,
+0xE5F8039D,0xFF5401A5,0xF9140055,0xEC00039D,0xFFD8032A,0xF5D80379,0x1D8039E,0xFFCC02A5,0xFFC4022E,0xFFBC01AB,0xFFBC0173,0xFFB800C2,0xFFD00305,0xFFD0028A,0xFFB8015A,0xFF880028,0xDFF8039D,0x1F00055,0x1F00055,0x1F00055,0x1F00055,0xFFEC0034,0xFFEC0034,0xFFEC0034,0xFFE40010,0xFFE40010,0xFFE40000,0xEBFC0055,0xEBFC0055,0xEBFC0055,0xFFE40020,0xFFE40020,
+0xFFD80000,0xF5FC0055,0xF5FC0055,0xFFAC0000,0xF8000055,0xEBFC0055,0xEBFC0055,0xEBFC0055,0xFFE40020,0xFFE40020,0xFFD80000,0xF5FC0055,0xF5FC0055,0xFFAC0000,0xF8000055,0xF5FC0055,0xF5FC0055,0xFFAC0000,0xF8000055,0xF8000055,0xFDF00048,0xFFEC0050,0x1F00055,0xFBF00048,0xFDEC003D,0xFFE4002D,0xFFE40022,0xFFD8001D,0xFBF00048,0xFFE80041,0xF3FC0055,0xFFAC0000,
+0xF3FC0055,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1C801A5,0x1C801A5,0x1C801A5,0x1C801A5,0x1C801A5,0x1C801A5,0x1C801A5,0x1C801A5,0x1C801A5,0x1C801A5,0xFFBC00A2,0xFFBC00A2,0xFFBC00A2,0xFFBC00A2,0xFFBC00A2,
+0xFFBC00A2,0xFFAC0001,0xFFAC0001,0xFFAC0001,0xF1A80002,0xABFC01A5,0xABFC01A5,0xABFC01A5,0xABFC01A5,0xABFC01A5,0xABFC01A5,0xFF880028,0xFF880028,0xFF880028,0xF1900001,0xD7F801A5,0xD7F801A5,0xD7F801A5,0xF1380001,0xE20001A5,0xFBC4016D,0x1C801A5,0x1C801A5,0xFFBC0132,0xFFBC00FA,0xFFBC00CA,0xFFBC00CA,0xFFB4006A,0xFFBC015A,0xFFBC0122,0xFFB00032,0xFF880028,
+0xCBFC01A5,};
+static const uint32_t g_etc1_to_bc7_m6_table128[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x240000,0x240000,0x240000,0x240000,0x340000,0x340000,0x340000,0x680000,0x680000,0x10000001,0x340000,0x340000,0x340000,0x680000,0x680000,0x10000001,0x680000,0x680000,0x10000001,0x10000001,0x340000,0x340000,0x340000,0x680000,0x680000,0x10000001,0x680000,0x680000,0x10000001,0x10000001,0x680000,
+0x680000,0x10000001,0x10000001,0x10000001,0x2280000,0xA240000,0x240000,0x300000,0x3C0000,0x4C0000,0x540000,0x800000,0x2C0000,0x340000,0x4C0000,0x10000001,0x4C0000,0x780000,0x2B00000,0x1680000,0x3A000001,0x2B00000,0x1680000,0x3A000001,0x1680000,0x3A000001,0x3A000001,0x2B00000,0x1680000,0x3A000001,0x1680000,0x3A000001,
+0x3A000001,0x1680000,0x3A000001,0x3A000001,0x3A000001,0x2B00000,0x1680000,0x3A000001,0x1680000,0x3A000001,0x3A000001,0x1680000,0x3A000001,0x3A000001,0x3A000001,0x1680000,0x3A000001,0x3A000001,0x3A000001,0x3A000001,0x2940000,0x800000,0x800000,0xC80000,0x1240000,0xBF40000,0x3A000001,0x3A000001,0xA40000,0xE00000,0x2FF00000,0x3A000001,
+0xFC0000,0x280964,0xAA0C00D8,0x560C00D8,0x3A0C00D9,0x76000372,0x52000061,0x3A000002,0x38000374,0x32000151,0x26000372,0x4E000768,0x460002BA,0x34000153,0x340004A5,0x2E00024E,0x2400040A,0x26000768,0x2600049D,0x2000059E,0x1800076B,0x380964,0x3A000463,0x2E000274,0x2E000596,0x2800031F,0x22000484,0x220007ED,0x24000543,0x1C000607,0x180007AB,0x700964,
+0x1C000694,0x1C00070C,0x16000864,0x12000964,0xE4000231,0xF41805B2,0xF820054D,0x74000239,0x4A000252,0x3C00023D,0x3000019B,0x2A000306,0x90000413,0x5E000317,0x2E0003AB,0x1C000607,0x500964,0x340768,0xA01400A4,0x541000A4,0x3A1000A5,0x76000372,0x52000061,0x3A000002,0x38000374,0x32000151,0x26000372,0x4C0768,0x460002BA,0x34000153,0x340004A5,0x2E00024E,
+0x2400040A,0x980768,0x2600049D,0x2000059E,0x1800076B,0x4C0768,0x460002BA,0x34000153,0x340004A5,0x2E00024E,0x2400040A,0x980768,0x2600049D,0x2000059E,0x1800076B,0x980768,0x2600049D,0x2000059E,0x1800076B,0x1800076B,0xE4000231,0xF82004F2,0xFC280405,0x74000239,0x4A000252,0x3C00023D,0x3000019B,0x2A000306,0x900003C2,0x5E0002F3,0x2E0003A2,0x2000059E,
+0x6C0768,0xC00D8,0xC00D8,0xC00D8,0xC00D8,0x36000000,0x36000000,0x36000000,0x1A000000,0x1A000000,0x10000001,0x1A0000A2,0x1A0000A2,0x1A0000A2,0x1200003D,0x1200003D,0xE000022,0xC0000A2,0xC0000A2,0xA000062,0x80000A2,0x1000D8,0x1000D8,0x1000D8,0x12000061,0x12000061,0xC000039,0xC0000B2,0xC0000B2,0xA000072,0x80000AB,0x2000D8,
+0x2000D8,0xA000093,0x60000C3,0x40000DB,0x76000032,0xF8000004,0xC00D8,0x32000041,0x1E00003D,0x1A000041,0x16000034,0x12000050,0x3400006B,0x2600005D,0x100000A3,0xA000072,0x1800D8,0x1000A4,0x1000A4,0x1000A4,0x1000A4,0x36000000,0x36000000,0x36000000,0x1A000000,0x1A000000,0x10000001,0x21800A2,0x21800A2,0x21800A2,0x1200003D,0x1200003D,
+0xE000022,0x3000A2,0x3000A2,0xA000062,0x80000A2,0x21800A2,0x21800A2,0x21800A2,0x1200003D,0x1200003D,0xE000022,0x3000A2,0x3000A2,0xA000062,0x80000A2,0x3000A2,0x3000A2,0xA000062,0x80000A2,0x80000A2,0x76000032,0xF8000004,0x1000A4,0x32000041,0x1E00003D,0x1A000041,0x16000034,0x12000050,0x42000061,0x26000059,0x2400A2,0xA000062,
+0x2400A2,0x4C0374,0x90240000,0x50240000,0x3A240001,0x740372,0x52000061,0x3A000002,0xE80372,0x32000151,0x26000372,0x740372,0x52000061,0x3A000002,0xE80372,0x32000151,0x26000372,0xE80372,0x32000151,0x26000372,0x26000372,0x740372,0x52000061,0x3A000002,0xE80372,0x32000151,0x26000372,0xE80372,0x32000151,0x26000372,0x26000372,0xE80372,
+0x32000151,0x26000372,0x26000372,0x26000372,0xF4000164,0x540372,0xF8400188,0x7C000132,0x56000161,0x3C00013D,0x340000DA,0x320001BA,0xB20001D4,0x68000179,0x360000B9,0x26000372,0xA40372,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table129[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x340000,0x340000,0x340000,0x340000,0x4C0000,0x4C0000,0x4C0000,0x980000,0x980000,0x18000001,0x4C0000,0x4C0000,0x4C0000,0x980000,0x980000,0x18000001,0x980000,0x980000,0x18000001,0x18000001,0x4C0000,0x4C0000,0x4C0000,0x980000,0x980000,0x18000001,0x980000,0x980000,0x18000001,0x18000001,0x980000,
+0x980000,0x18000001,0x18000001,0x18000001,0x3C0000,0x380000,0x340000,0x2440000,0x2540000,0x6C0000,0x7C0000,0xBC0000,0x400000,0x4C0000,0x6C0000,0x18000001,0x6C0000,0x880000,0xC80000,0x1980000,0x42000001,0xC80000,0x1980000,0x42000001,0x1980000,0x42000001,0x42000001,0xC80000,0x1980000,0x42000001,0x1980000,0x42000001,
+0x42000001,0x1980000,0x42000001,0x42000001,0x42000001,0xC80000,0x1980000,0x42000001,0x1980000,0x42000001,0x42000001,0x1980000,0x42000001,0x42000001,0x42000001,0x1980000,0x42000001,0x42000001,0x42000001,0x42000001,0x2A80000,0x900000,0x900000,0xE40000,0x14C0000,0x15F40000,0x42000001,0x42000001,0xB80000,0x1000000,0x39C40000,0x42000001,
+0x1200000,0x300C14,0xBE1001C4,0x601001C4,0x421001C5,0x8E000372,0x62000025,0x4400000A,0x44000374,0x38000109,0x2E000372,0x5C000933,0x5200036A,0x400001DB,0x3A00053D,0x34000266,0x2E000453,0x2E000934,0x2C0005A5,0x26000696,0x1E000933,0x440C14,0x460005BB,0x3A000354,0x340006A6,0x34000387,0x2800050C,0x280009FD,0x2C000686,0x2400073B,0x1E000997,0x880C14,
+0x26000891,0x200008C2,0x1C000AAC,0x16000C14,0xFE000264,0xF8200772,0xFC280785,0x8800025D,0x5A000281,0x44000266,0x3C000195,0x36000351,0xB20004DE,0x68000393,0x3600045B,0x2400073B,0x600C14,0x400934,0xB21C0154,0x5E180154,0x42180155,0x8E000372,0x62000025,0x44040009,0x44000374,0x38000109,0x2E000372,0x5C0933,0x5200036A,0x400001DB,0x3A00053D,0x34000266,
+0x2E000453,0xB80933,0x2C0005A5,0x26000696,0x1E000933,0x5C0933,0x5200036A,0x400001DB,0x3A00053D,0x34000266,0x2E000453,0xB80933,0x2C0005A5,0x26000696,0x1E000933,0xB80933,0x2C0005A5,0x26000696,0x1E000933,0x1E000933,0xFE000264,0xFE2C061E,0xF23405B4,0x8800025D,0x5A000281,0x44000266,0x3C000195,0x36000351,0xB2000465,0x68000362,0x36000452,0x26000696,
+0x800933,0x1001C4,0x1001C4,0x1001C4,0x1001C4,0x4E000000,0x4E000000,0x4E000000,0x26000000,0x26000000,0x18000001,0x26000152,0x26000152,0x26000152,0x1E00007D,0x1E00007D,0x18000041,0x12000152,0x12000152,0x100000CA,0xC000152,0x21801C3,0x21801C3,0x21801C3,0x180000D1,0x180000D1,0x12000079,0x12000176,0x12000176,0x100000EE,0xC000162,0x3001C3,
+0x3001C3,0xE000141,0xA00018B,0x80001C3,0x9200006A,0xFC080044,0x1001C4,0x50000089,0x3200007D,0x2600007D,0x2200006A,0x1A00009D,0x560000E9,0x320000BE,0x16000155,0x100000EE,0x2401C3,0x180154,0x180154,0x180154,0x180154,0x4E000000,0x4E000000,0x4E000000,0x26000000,0x26000000,0x18000001,0x2240152,0x2240152,0x2240152,0x1E00007D,0x1E00007D,
+0x18000041,0x4C0152,0x4C0152,0x100000CA,0xC000152,0x2240152,0x2240152,0x2240152,0x1E00007D,0x1E00007D,0x18000041,0x4C0152,0x4C0152,0x100000CA,0xC000152,0x4C0152,0x4C0152,0x100000CA,0xC000152,0xC000152,0x9200006A,0xFC080034,0x180154,0x50000089,0x3200007D,0x2600007D,0x2200006A,0x1A00009D,0x560000D0,0x3C0000B4,0x340152,0x100000CA,
+0x340152,0x5C0374,0x98340000,0x58340000,0x42340001,0x8C0372,0x62000025,0x420C0001,0x1180372,0x38000109,0x2E000372,0x8C0372,0x62000025,0x420C0001,0x1180372,0x38000109,0x2E000372,0x1180372,0x38000109,0x2E000372,0x2E000372,0x8C0372,0x62000025,0x420C0001,0x1180372,0x38000109,0x2E000372,0x1180372,0x38000109,0x2E000372,0x2E000372,0x1180372,
+0x38000109,0x2E000372,0x2E000372,0x2E000372,0xFC080152,0x640372,0xFE4C0190,0x920000E9,0x6000010D,0x4A000104,0x3E000092,0x3600016D,0xD0000190,0x7A000128,0x4200007D,0x2E000372,0xC80372,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table130[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x440000,0x440000,0x440000,0x440000,0x640000,0x640000,0x640000,0xCC0000,0xCC0000,0x20000001,0x640000,0x640000,0x640000,0xCC0000,0xCC0000,0x20000001,0xCC0000,0xCC0000,0x20000001,0x20000001,0x640000,0x640000,0x640000,0xCC0000,0xCC0000,0x20000001,0xCC0000,0xCC0000,0x20000001,0x20000001,0xCC0000,
+0xCC0000,0x20000001,0x20000001,0x20000001,0x64C0000,0x480000,0x440000,0x5C0000,0x700000,0x900000,0xA40000,0xF80000,0x540000,0x640000,0x900000,0x20000001,0x900000,0x980000,0xE00000,0x1CC0000,0x4A000001,0xE00000,0x1CC0000,0x4A000001,0x1CC0000,0x4A000001,0x4A000001,0xE00000,0x1CC0000,0x4A000001,0x1CC0000,0x4A000001,
+0x4A000001,0x1CC0000,0x4A000001,0x4A000001,0x4A000001,0xE00000,0x1CC0000,0x4A000001,0x1CC0000,0x4A000001,0x4A000001,0x1CC0000,0x4A000001,0x4A000001,0x4A000001,0x1CC0000,0x4A000001,0x4A000001,0x4A000001,0x4A000001,0x2BC0000,0x8A00000,0x8A00000,0x1000000,0x1740000,0x1FF80000,0x4A000001,0x4A000001,0x2CC0000,0x11C0000,0x41D40000,0x4A000001,
+0x1400000,0x380F44,0xCE180304,0x6A180304,0x4A180305,0xA6000372,0x6E000005,0x4C04003A,0x50000374,0x440000C1,0x36000372,0x70000B53,0x62000455,0x460002A3,0x460005E5,0x40000296,0x3400049B,0x36000B53,0x320006F5,0x2C0007BE,0x24000B53,0x500F44,0x4C000773,0x40000494,0x400007D6,0x3A000417,0x2E0005B4,0x2E000C75,0x32000816,0x2A00089F,0x22000BD4,0xA00F44,
+0x2C000AD9,0x26000ABA,0x20000D5F,0x1A000F44,0xFE000344,0xFC2809B2,0xFE2C0A49,0x9E00029D,0x6C0002C1,0x4C0002A2,0x440001A6,0x3A0003B2,0xD00005C2,0x7C000403,0x3E000573,0x2A00089F,0x700F44,0x480B54,0xC2240244,0x68200244,0x4A200245,0xA6000372,0x6E000005,0x4E080032,0x50000374,0x440000C1,0x36000372,0x6C0B53,0x62000455,0x460002A3,0x460005E5,0x40000296,
+0x3400049B,0xDC0B53,0x320006F5,0x2C0007BE,0x24000B53,0x6C0B53,0x62000455,0x460002A3,0x460005E5,0x40000296,0x3400049B,0xDC0B53,0x320006F5,0x2C0007BE,0x24000B53,0xDC0B53,0x320006F5,0x2C0007BE,0x24000B53,0x24000B53,0xFE000344,0xF43807D4,0xF8400788,0x9E00029D,0x6C0002C1,0x4C0002A2,0x440001A6,0x3A0003B2,0xD0000519,0x7C0003C3,0x3E000563,0x2C0007BE,
+0x9C0B53,0x180304,0x180304,0x180304,0x180304,0x66000000,0x66000000,0x66000000,0x32000000,0x32000000,0x20000001,0x32000242,0x32000242,0x32000242,0x280000CD,0x280000CD,0x1E00006D,0x18000242,0x18000242,0x1600015A,0x10000242,0x200303,0x200303,0x200303,0x22000156,0x22000156,0x180000D1,0x18000282,0x18000282,0x1600019A,0xE000263,0x3C0303,
+0x3C0303,0x10000213,0xE0002AE,0xA000303,0xC40000B4,0xFE0C00D8,0x180304,0x640000F5,0x460000DD,0x2E0000E1,0x2E0000B4,0x22000104,0x64000191,0x5000014A,0x1E000248,0x1600019A,0x2C0303,0x200244,0x200244,0x200244,0x200244,0x66000000,0x66000000,0x66000000,0x32000000,0x32000000,0x20000001,0x2300242,0x2300242,0x2300242,0x280000CD,0x280000CD,
+0x1E00006D,0x640242,0x640242,0x1600015A,0x10000242,0x2300242,0x2300242,0x2300242,0x280000CD,0x280000CD,0x1E00006D,0x640242,0x640242,0x1600015A,0x10000242,0x640242,0x640242,0x1600015A,0x10000242,0x10000242,0xC40000B4,0xFE0C00B4,0x200244,0x640000F5,0x460000DD,0x2E0000E1,0x2E0000B4,0x22000104,0x74000164,0x50000131,0x480242,0x1600015A,
+0x480242,0x6C0374,0xA0440000,0x60440000,0x4A440001,0xA40372,0x6E000005,0x4A1C0001,0x14C0372,0x440000C1,0x36000372,0xA40372,0x6E000005,0x4A1C0001,0x14C0372,0x440000C1,0x36000372,0x14C0372,0x440000C1,0x36000372,0x36000372,0xA40372,0x6E000005,0x4A1C0001,0x14C0372,0x440000C1,0x36000372,0x14C0372,0x440000C1,0x36000372,0x36000372,0x14C0372,
+0x440000C1,0x36000372,0x36000372,0x36000372,0xFE140164,0x2740372,0xF86001A5,0xA60000A4,0x6C0000DD,0x540000B9,0x46000059,0x42000132,0xF200015A,0x8C0000F4,0x4C000041,0x36000372,0xE80372,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table131[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0x100000,0x100000,0x100000,0x100000,0x100000,
+0x100000,0x200000,0x200000,0x200000,0x4000001,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x200000,0x200000,0x200000,0x4000001,0x200000,0x200000,0x200000,0x4000001,0x4000001,0xC0000,0xC0000,0xC0000,0x20C0000,0x40C0000,0x100000,0x100000,0x140000,0x20C0000,0x40C0000,0x180000,0x200000,
+0x180000,0x540000,0x540000,0x540000,0x540000,0x7C0000,0x7C0000,0x7C0000,0xFC0000,0xFC0000,0x28000001,0x7C0000,0x7C0000,0x7C0000,0xFC0000,0xFC0000,0x28000001,0xFC0000,0xFC0000,0x28000001,0x28000001,0x7C0000,0x7C0000,0x7C0000,0xFC0000,0xFC0000,0x28000001,0xFC0000,0xFC0000,0x28000001,0x28000001,0xFC0000,
+0xFC0000,0x28000001,0x28000001,0x28000001,0x2600000,0x4580000,0x540000,0x2700000,0x8C0000,0xB00000,0xCC0000,0x1340000,0x680000,0x7C0000,0xB00000,0x28000001,0xB00000,0xA80000,0xF80000,0x1FC0000,0x52000001,0xF80000,0x1FC0000,0x52000001,0x1FC0000,0x52000001,0x52000001,0xF80000,0x1FC0000,0x52000001,0x1FC0000,0x52000001,
+0x52000001,0x1FC0000,0x52000001,0x52000001,0x52000001,0xF80000,0x1FC0000,0x52000001,0x1FC0000,0x52000001,0x52000001,0x1FC0000,0x52000001,0x52000001,0x52000001,0x1FC0000,0x52000001,0x52000001,0x52000001,0x52000001,0x4D00000,0xB40000,0xB40000,0x1180000,0x19C0000,0x29F80000,0x52000001,0x52000001,0xE40000,0x13C0000,0x49E40000,0x52000001,
+0x1640000,0x401198,0xDE200408,0x74200408,0x52200409,0xB6080386,0x78080015,0x560C007E,0x5C040386,0x4C0400A9,0x3E040386,0x84000BE8,0x680003F9,0x5200029B,0x5200058D,0x460001EE,0x3A00043B,0x40000BE8,0x3E0006C9,0x320007A2,0x2A000BEB,0x601194,0x62000829,0x4C00052C,0x4C00083E,0x460003FF,0x3A0005A4,0x3A000D81,0x38000852,0x320008C3,0x28000CAC,0xC41194,
+0x32000C15,0x2C000BBE,0x26000ED7,0x20001194,0xFE0C03FE,0xFE2C0B9E,0xF63C0C94,0xB40001F1,0x76000211,0x5A0001E1,0x4C000105,0x4200030B,0xF200058B,0x90000386,0x46000541,0x320008C3,0x8C1194,0x580BE8,0xCE300288,0x70300288,0x52300289,0xB20C0372,0x760C0005,0x54140042,0x5A0C0372,0x4C0400A5,0x3E0C0372,0x2800BE8,0x680003F9,0x5200029B,0x5200058D,0x460001EE,
+0x3A00043B,0x1080BE8,0x3E0006C9,0x320007A2,0x2A000BEB,0x2800BE8,0x680003F9,0x5200029B,0x5200058D,0x460001EE,0x3A00043B,0x1080BE8,0x3E0006C9,0x320007A2,0x2A000BEB,0x1080BE8,0x3E0006C9,0x320007A2,0x2A000BEB,0x2A000BEB,0xFE1403AD,0xFA440844,0xFE4C0810,0xB40001F1,0x76000211,0x5A0001E1,0x4C000105,0x4200030B,0xF20004AA,0x90000335,0x46000531,0x320007A2,
+0xB80BE8,0x200408,0x200408,0x200408,0x200408,0x76080014,0x76080014,0x76080014,0x3C040014,0x3C040014,0x28040015,0x48000288,0x48000288,0x48000288,0x3400009D,0x3400009D,0x28000032,0x22000288,0x22000288,0x20000151,0x1600028A,0x300408,0x300408,0x300408,0x2E000196,0x2E000196,0x220000C3,0x1E0002FE,0x1E0002FE,0x1C0001B6,0x160002CA,0x5C0408,
+0x5C0408,0x1600029B,0x1400035E,0xE00040B,0xF6000082,0xF2140195,0x200408,0x820000C1,0x5A0000A9,0x440000A9,0x40000082,0x2E0000DA,0x960001AB,0x5A000144,0x2C000291,0x1C0001B6,0x400408,0x300288,0x300288,0x300288,0x300288,0x720C0000,0x720C0000,0x720C0000,0x3A0C0000,0x3A0C0000,0x280C0001,0x2440288,0x2440288,0x2440288,0x3400009D,0x3400009D,
+0x28000032,0x8C0288,0x8C0288,0x20000151,0x1600028A,0x2440288,0x2440288,0x2440288,0x3400009D,0x3400009D,0x28000032,0x8C0288,0x8C0288,0x20000151,0x1600028A,0x8C0288,0x8C0288,0x20000151,0x1600028A,0x1600028A,0xF6000082,0xF82000DD,0x300288,0x820000C1,0x5A0000A9,0x440000A9,0x40000082,0x2E0000DA,0x9600015A,0x5A000120,0x640288,0x20000151,
+0x640288,0x7C0374,0xA8540000,0x68540000,0x52540001,0xBC0372,0x78080001,0x522C0001,0x17C0372,0x4A000091,0x3E000372,0xBC0372,0x78080001,0x522C0001,0x17C0372,0x4A000091,0x3E000372,0x17C0372,0x4A000091,0x3E000372,0x3E000372,0xBC0372,0x78080001,0x522C0001,0x17C0372,0x4A000091,0x3E000372,0x17C0372,0x4A000091,0x3E000372,0x3E000372,0x17C0372,
+0x4A000091,0x3E000372,0x3E000372,0x3E000372,0xFC30016D,0xA840372,0xFE6C01B1,0xBC000071,0x80000095,0x5E000080,0x5000002D,0x4A0000FA,0xF80C0152,0x9E0000B5,0x56000014,0x3E000372,0x10C0372,0x40014,0x40014,0x40014,0x40014,0x40014,0x40014,0x40014,0x40014,0x40014,0x40014,0x10000000,0x10000000,0x10000000,0x10000000,0x10000000,
+0x10000000,0x8000000,0x8000000,0x8000000,0x4000001,0x80012,0x80012,0x80012,0x80012,0x80012,0x80012,0x6000005,0x6000005,0x6000005,0x4000005,0xC0012,0xC0012,0xC0012,0x400000A,0x2000012,0x58000000,0x40014,0x40014,0x28000000,0x1C000000,0x14000000,0x14000000,0xE000000,0x20000005,0x16000002,0xA000001,0x6000005,
+0xC0012,};
+static const uint32_t g_etc1_to_bc7_m6_table132[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,
+0x2C0000,0x580000,0x580000,0x580000,0xE000000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x580000,0x580000,0x580000,0xE000000,0x580000,0x580000,0x580000,0xE000000,0xE000000,0x200000,0x1C0001,0x1C0001,0x6200000,0x240000,0x280000,0x280000,0x300000,0x6200000,0x240000,0x3C0000,0x580000,
+0x3C0000,0x640001,0x640001,0x640001,0x640001,0x980000,0x980000,0x980000,0x1300000,0x1300000,0x32000000,0x980000,0x980000,0x980000,0x1300000,0x1300000,0x32000000,0x1300000,0x1300000,0x32000000,0x32000000,0x980000,0x980000,0x980000,0x1300000,0x1300000,0x32000000,0x1300000,0x1300000,0x32000000,0x32000000,0x1300000,
+0x1300000,0x32000000,0x32000000,0x32000000,0x4740000,0x6C0000,0x640001,0x2880000,0xAC0000,0xD80000,0xF80000,0x1780000,0x800000,0x980000,0xD80000,0x32000000,0xD80000,0xB80001,0x1140000,0xFF80000,0x5C000000,0x1140000,0xFF80000,0x5C000000,0xFF80000,0x5C000000,0x5C000000,0x1140000,0xFF80000,0x5C000000,0xFF80000,0x5C000000,
+0x5C000000,0xFF80000,0x5C000000,0x5C000000,0x5C000000,0x1140000,0xFF80000,0x5C000000,0xFF80000,0x5C000000,0x5C000000,0xFF80000,0x5C000000,0x5C000000,0x5C000000,0xFF80000,0x5C000000,0x5C000000,0x5C000000,0x5C000000,0xE80000,0xAC40000,0xAC40000,0x1380000,0x1C80000,0x35F00000,0x5C000000,0x5C000000,0xFC0000,0x15C0000,0x53D80000,0x5C000000,
+0x18C0000,0x501423,0xEC2C055E,0x7E2C055E,0x5C2C055E,0xCA1003E3,0x86100072,0x6014011D,0x661003E3,0x560C00EA,0x461003E5,0xA0000BE8,0x7A00034E,0x5C04028E,0x620004C5,0x5200010D,0x460003B4,0x4E000BE8,0x4A00060E,0x3E0006ED,0x34000BE8,0x2741423,0x6E0008EE,0x58000601,0x5800089F,0x4C0003D6,0x400005B1,0x46000E44,0x4400082B,0x3C000898,0x34000D09,0xF01423,
+0x38000D6E,0x32000CD1,0x2C00102C,0x26001425,0xFE200511,0xF8400DDB,0xFC480EE3,0xD000011D,0x8A000126,0x6A00010D,0x5A00005E,0x50000214,0xFE00052B,0xA80002B6,0x5400046A,0x3C000898,0xA81423,0x680BEB,0xD444028A,0x7A40028A,0x5C40028A,0xBA200373,0x821C0002,0x5E280041,0x62200373,0x561800A6,0x461C0375,0x9C0BE8,0x7A00034E,0x5C080288,0x620004C5,0x5200010D,
+0x460003B4,0x13C0BE8,0x4A00060E,0x3E0006ED,0x34000BE8,0x9C0BE8,0x7A00034E,0x5C080288,0x620004C5,0x5200010D,0x460003B4,0x13C0BE8,0x4A00060E,0x3E0006ED,0x34000BE8,0x13C0BE8,0x4A00060E,0x3E0006ED,0x34000BE8,0x34000BE8,0xFA2C0402,0xF458087D,0xF860084A,0xD000011D,0x8A000126,0x6A00010D,0x5A00005E,0x50000214,0xFC040428,0xA800023D,0x54000451,0x3E0006ED,
+0xE00BE8,0x2C055E,0x2C055E,0x2C055E,0x2C055E,0x8A100071,0x8A100071,0x8A100071,0x46100072,0x46100072,0x32100071,0x64000288,0x64000288,0x64000288,0x46000049,0x46000049,0x32000004,0x30000288,0x30000288,0x2A000104,0x20000288,0x40055E,0x40055E,0x40055E,0x3A0001F2,0x3A0001F2,0x2E0000F1,0x28000363,0x28000363,0x260001B2,0x1E0002F4,0x80055E,
+0x80055E,0x20000359,0x1C000411,0x14000561,0xFC0C00AC,0xF8200291,0x2C055E,0xAC00006A,0x72000050,0x56000059,0x4C000032,0x40000082,0xC2000199,0x84000101,0x3E000298,0x260001B2,0x5C055E,0x40028A,0x40028A,0x40028A,0x40028A,0x7A200001,0x7A200001,0x7A200001,0x441C0001,0x441C0001,0x321C0001,0x600288,0x600288,0x600288,0x46000049,0x46000049,
+0x32000004,0xC40288,0xC40288,0x2A000104,0x20000288,0x600288,0x600288,0x600288,0x46000049,0x46000049,0x32000004,0xC40288,0xC40288,0x2A000104,0x20000288,0xC40288,0xC40288,0x2A000104,0x20000288,0x20000288,0xFE100080,0xF23400F2,0x40028A,0xAC00006A,0x72000050,0x56000059,0x4C000032,0x40000082,0xC2000109,0x840000C1,0x8C0288,0x2A000104,
+0x8C0288,0x900372,0xB0680001,0x70680001,0x5C640001,0xD40372,0x82180001,0x5C3C0000,0x1B00372,0x56000055,0x46000374,0xD40372,0x82180001,0x5C3C0000,0x1B00372,0x56000055,0x46000374,0x1B00372,0x56000055,0x46000374,0x46000374,0xD40372,0x82180001,0x5C3C0000,0x1B00372,0x56000055,0x46000374,0x1B00372,0x56000055,0x46000374,0x46000374,0x1B00372,
+0x56000055,0x46000374,0x46000374,0x46000374,0xFE440188,0x4980372,0xFA8401C2,0xDA000041,0x9600006D,0x6C000055,0x5A00000D,0x540000B9,0xFE180164,0xBA00007D,0x62000004,0x46000374,0x1300372,0x100071,0x100071,0x100071,0x100071,0x100071,0x100071,0x100071,0x100071,0x100071,0x100071,0x2C000000,0x2C000000,0x2C000000,0x2C000000,0x2C000000,
+0x2C000000,0x16000000,0x16000000,0x16000000,0xE000000,0x140071,0x140071,0x140071,0x140071,0x140071,0x140071,0x12000028,0x12000028,0x12000028,0xC000014,0x240071,0x240071,0x240071,0xA000041,0x6000071,0xE8000000,0x100071,0x100071,0x68000000,0x48000000,0x36000000,0x36000000,0x24000000,0x52000022,0x42000011,0x1C000004,0x12000028,
+0x1C0071,};
+static const uint32_t g_etc1_to_bc7_m6_table133[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x440000,0x440000,0x440000,0x440000,0x440000,
+0x440000,0x880000,0x880000,0x880000,0x16000000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x880000,0x880000,0x880000,0x16000000,0x880000,0x880000,0x880000,0x16000000,0x16000000,0x300000,0x2C0001,0x2C0001,0x2340000,0x380000,0x23C0000,0x23C0000,0x4C0000,0x2340000,0x380000,0x600000,0x880000,
+0x600000,0x740001,0x740001,0x740001,0x740001,0xB00000,0xB00000,0xB00000,0x1640000,0x1640000,0x3A000000,0xB00000,0xB00000,0xB00000,0x1640000,0x1640000,0x3A000000,0x1640000,0x1640000,0x3A000000,0x3A000000,0xB00000,0xB00000,0xB00000,0x1640000,0x1640000,0x3A000000,0x1640000,0x1640000,0x3A000000,0x3A000000,0x1640000,
+0x1640000,0x3A000000,0x3A000000,0x3A000000,0x880000,0x67C0000,0x740001,0xA00000,0xC40000,0xF80000,0x1200000,0x1B40000,0x940000,0xB00000,0xF80000,0x3A000000,0xF80000,0xC80001,0x12C0000,0x1BF80000,0x64000000,0x12C0000,0x1BF80000,0x64000000,0x1BF80000,0x64000000,0x64000000,0x12C0000,0x1BF80000,0x64000000,0x1BF80000,0x64000000,
+0x64000000,0x1BF80000,0x64000000,0x64000000,0x64000000,0x12C0000,0x1BF80000,0x64000000,0x1BF80000,0x64000000,0x64000000,0x1BF80000,0x64000000,0x64000000,0x64000000,0x1BF80000,0x64000000,0x64000000,0x64000000,0x64000000,0xFC0000,0xD80000,0xD80000,0x1540000,0x1EC0000,0x3FF00000,0x64000000,0x64000000,0x3100000,0x17C0000,0x5BE80000,0x64000000,
+0x1AC0000,0x5C16CF,0xF83806EA,0x883806EA,0x643806EA,0xDA18047B,0x90180112,0x662001F9,0x7018047B,0x6014016E,0x4E18047D,0xB8000BE8,0x8C0002DE,0x660C02C2,0x6E00044D,0x5E00007D,0x4E00037D,0x5A000BE8,0x5000056A,0x44000675,0x3C000BE8,0x8816CF,0x7A000A0E,0x6200072E,0x68000911,0x580003FE,0x4C0005F9,0x52000F0C,0x4C00082B,0x44000886,0x3A000D5D,0x11416CF,
+0x44000EFE,0x3E000E01,0x32001198,0x2C0016D1,0xFE280685,0xFE4C1017,0xFE4C119F,0xE6000086,0x9A0000A1,0x78000083,0x6200000D,0x5800015D,0xFE00061B,0xBC00020A,0x5E0003DE,0x44000886,0xC016CF,0x780BEB,0xDC54028A,0x8250028A,0x6450028A,0xC2300373,0x8A2C0002,0x66380041,0x6A300373,0x5E2800A6,0x4E2C0375,0xB40BE8,0x8C0002DE,0x64180288,0x6E00044D,0x5E00007D,
+0x4E00037D,0x1700BE8,0x5000056A,0x44000675,0x3C000BE8,0xB40BE8,0x8C0002DE,0x64180288,0x6E00044D,0x5E00007D,0x4E00037D,0x1700BE8,0x5000056A,0x44000675,0x3C000BE8,0x1700BE8,0x5000056A,0x44000675,0x3C000BE8,0x3C000BE8,0xFE340432,0xFC68087D,0xFE6C085E,0xE6000086,0x9A0000A1,0x78000083,0x6200000D,0x5800015D,0xFE180455,0xBC00017A,0x5E0003BA,0x44000675,
+0x1000BE8,0x3806EA,0x3806EA,0x3806EA,0x3806EA,0x9A180109,0x9A180109,0x9A180109,0x5018010A,0x5018010A,0x3A180109,0x7C000288,0x7C000288,0x7C000288,0x52000019,0x52000019,0x3A040008,0x3C000288,0x3C000288,0x320000B9,0x28000288,0x5006E9,0x5006E9,0x5006E9,0x4600028A,0x4600028A,0x34000169,0x340003DB,0x340003DB,0x2E0001C2,0x28000331,0xA006E9,
+0xA006E9,0x2600043D,0x200004EC,0x1A0006E9,0xFE100140,0xFE2C03C9,0x3806EA,0xD000002D,0x86000020,0x6A00001D,0x62000009,0x4A000041,0xE40001A5,0x960000E2,0x4C0002A1,0x2E0001C2,0x7006E9,0x50028A,0x50028A,0x50028A,0x50028A,0x82300001,0x82300001,0x82300001,0x4C2C0001,0x4C2C0001,0x3A2C0001,0x780288,0x780288,0x780288,0x52000019,0x52000019,
+0x3A0C0000,0xF40288,0xF40288,0x320000B9,0x28000288,0x780288,0x780288,0x780288,0x52000019,0x52000019,0x3A0C0000,0xF40288,0xF40288,0x320000B9,0x28000288,0xF40288,0xF40288,0x320000B9,0x28000288,0x28000288,0xFE200091,0xFA4400F2,0x50028A,0xD000002D,0x86000020,0x6A00001D,0x62000009,0x4A000041,0xF40000CA,0x9A000080,0xAC0288,0x320000B9,
+0xAC0288,0xA00372,0xB8780001,0x78780001,0x64740001,0xEC0372,0x8A280001,0x644C0000,0x1E40372,0x60000034,0x4E000374,0xEC0372,0x8A280001,0x644C0000,0x1E40372,0x60000034,0x4E000374,0x1E40372,0x60000034,0x4E000374,0x4E000374,0xEC0372,0x8A280001,0x644C0000,0x1E40372,0x60000034,0x4E000374,0x1E40372,0x60000034,0x4E000374,0x4E000374,0x1E40372,
+0x60000034,0x4E000374,0x4E000374,0x4E000374,0xFE50019A,0xCA80372,0xF29401E1,0xEE000020,0xA000003D,0x7A00002D,0x64000001,0x5C000091,0xFE2C0185,0xCC000059,0x6A080000,0x4E000374,0x1540372,0x180109,0x180109,0x180109,0x180109,0x180109,0x180109,0x180109,0x180109,0x180109,0x180109,0x44000000,0x44000000,0x44000000,0x44000000,0x44000000,
+0x44000000,0x20000001,0x20000001,0x20000001,0x16000000,0x200109,0x200109,0x200109,0x200109,0x200109,0x200109,0x18000064,0x18000064,0x18000064,0x12000034,0x3C0109,0x3C0109,0x3C0109,0x1000009D,0xA000109,0xFC080019,0x180109,0x180109,0xA0000000,0x6E000000,0x54000000,0x54000000,0x38000000,0x84000050,0x64000028,0x26000008,0x18000064,
+0x2C0109,};
+static const uint32_t g_etc1_to_bc7_m6_table134[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,
+0x5C0000,0xB80000,0xB80000,0xB80000,0x1E000000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0xB80000,0xB80000,0xB80000,0x1E000000,0xB80000,0xB80000,0xB80000,0x1E000000,0x1E000000,0x8400000,0x3C0001,0x3C0001,0x480000,0x24C0000,0x540000,0x540000,0x680000,0x480000,0x24C0000,0x800000,0xB80000,
+0x800000,0x840001,0x840001,0x840001,0x840001,0x2C40000,0x2C40000,0x2C40000,0x1940000,0x1940000,0x42000000,0x2C40000,0x2C40000,0x2C40000,0x1940000,0x1940000,0x42000000,0x1940000,0x1940000,0x42000000,0x42000000,0x2C40000,0x2C40000,0x2C40000,0x1940000,0x1940000,0x42000000,0x1940000,0x1940000,0x42000000,0x42000000,0x1940000,
+0x1940000,0x42000000,0x42000000,0x42000000,0x9C0000,0xE8C0000,0x840001,0x2B40000,0xE00000,0x11C0000,0x1480000,0x1F00000,0xA80000,0x2C40000,0x11C0000,0x42000000,0x11C0000,0xD80001,0x1440000,0x27F80000,0x6C000000,0x1440000,0x27F80000,0x6C000000,0x27F80000,0x6C000000,0x6C000000,0x1440000,0x27F80000,0x6C000000,0x27F80000,0x6C000000,
+0x6C000000,0x27F80000,0x6C000000,0x6C000000,0x6C000000,0x1440000,0x27F80000,0x6C000000,0x27F80000,0x6C000000,0x6C000000,0x27F80000,0x6C000000,0x6C000000,0x6C000000,0x27F80000,0x6C000000,0x6C000000,0x6C000000,0x6C000000,0x1100000,0xE80000,0xE80000,0x36C0000,0x9FC0000,0x49F00000,0x6C000000,0x6C000000,0x1280000,0x1980000,0x63F80000,0x6C000000,
+0x1D00000,0x6819DB,0xFE4408D2,0x924008CA,0x6C4008CA,0xEA200553,0x9A2001FA,0x70280319,0x7A200553,0x681C0235,0x56200555,0xD0000BE8,0x9E00029E,0x6E10032E,0x800003ED,0x68000029,0x56000378,0x66000BE8,0x5C0004DA,0x500005E5,0x44000BE8,0x29819DB,0x86000B8E,0x6A0008DD,0x740009E9,0x62000465,0x5200068D,0x5E000FF4,0x58000853,0x4C00088E,0x40000DD1,0x13819DB,
+0x4A0010D2,0x44000F69,0x3E001338,0x320019DD,0xFE340856,0xF65C1329,0xF860148A,0xFE000033,0xAC00003D,0x84000029,0x6C040006,0x640000D5,0xFE1007BB,0xD4000193,0x66000384,0x4C00088E,0xDC19DB,0x880BEB,0xE464028A,0x8A60028A,0x6C60028A,0xCA400373,0x923C0002,0x6E480041,0x72400373,0x663800A6,0x563C0375,0xCC0BE8,0x9E00029E,0x6C280288,0x800003ED,0x68000029,
+0x56080374,0x1A00BE8,0x5C0004DA,0x500005E5,0x44000BE8,0xCC0BE8,0x9E00029E,0x6C280288,0x800003ED,0x68000029,0x56080374,0x1A00BE8,0x5C0004DA,0x500005E5,0x44000BE8,0x1A00BE8,0x5C0004DA,0x500005E5,0x44000BE8,0x44000BE8,0xFE50045E,0xF47808BB,0xF880088B,0xFE000033,0xAC00003D,0x84000029,0x6C040002,0x640000D5,0xFE2404A1,0xDA0000E6,0x6A000359,0x500005E5,
+0x1240BE8,0x4008CA,0x4008CA,0x4008CA,0x4008CA,0xAA2001E1,0xAA2001E1,0xAA2001E1,0x5A2001E2,0x5A2001E2,0x422001E1,0x94000288,0x94000288,0x94000288,0x62000001,0x62000001,0x42080034,0x48000288,0x48000288,0x3C000088,0x30000288,0x6008C9,0x6008C9,0x6008C9,0x52000362,0x52000362,0x40000221,0x40000473,0x40000473,0x360001F8,0x2E000371,0xC408C9,
+0xC408C9,0x2C000569,0x260005F4,0x200008C9,0xFE200221,0xF438058A,0x4008CA,0xF200000D,0x9E000005,0x7C000005,0x70000001,0x56000019,0xFE0001FA,0xB60000CE,0x5C0002AC,0x360001F8,0x8C08C9,0x60028A,0x60028A,0x60028A,0x60028A,0x8A400001,0x8A400001,0x8A400001,0x543C0001,0x543C0001,0x423C0001,0x900288,0x900288,0x900288,0x62000001,0x62000001,
+0x421C0000,0x1240288,0x1240288,0x3C000088,0x30000288,0x900288,0x900288,0x900288,0x62000001,0x62000001,0x421C0000,0x1240288,0x1240288,0x3C000088,0x30000288,0x1240288,0x1240288,0x3C000088,0x30000288,0x30000288,0xFA3400A2,0xF2540109,0x60028A,0xF200000D,0x9E000005,0x7C000005,0x6E040000,0x56000019,0xFE0C00C8,0xBC00004A,0xD00288,0x3C000088,
+0xD00288,0xB00372,0xC0880001,0x80880001,0x6C840001,0x1040372,0x92380001,0x6C5C0000,0x7FC0372,0x6A00001D,0x56000374,0x1040372,0x92380001,0x6C5C0000,0x7FC0372,0x6A00001D,0x56000374,0x7FC0372,0x6A00001D,0x56000374,0x56000374,0x1040372,0x92380001,0x6C5C0000,0x7FC0372,0x6A00001D,0x56000374,0x7FC0372,0x6A00001D,0x56000374,0x56000374,0x7FC0372,
+0x6A00001D,0x56000374,0x56000374,0x56000374,0xF86C01A5,0xBC0372,0xFAA401E1,0xFE040014,0xAC040029,0x84000019,0x6C0C0000,0x64000071,0xFA4C0188,0xDE000034,0x72180000,0x56000374,0x1740372,0x2001E1,0x2001E1,0x2001E1,0x2001E1,0x2001E1,0x2001E1,0x2001E1,0x2001E1,0x2001E1,0x2001E1,0x5C000000,0x5C000000,0x5C000000,0x5C000000,0x5C000000,
+0x5C000000,0x2C000001,0x2C000001,0x2C000001,0x1E000000,0x2C01E1,0x2C01E1,0x2C01E1,0x2C01E1,0x2C01E1,0x2C01E1,0x220000AA,0x220000AA,0x220000AA,0x1A000061,0x5801E1,0x5801E1,0x5801E1,0x16000121,0xE0001E1,0xFE0C0075,0x2001E1,0x2001E1,0xD8000000,0x96000000,0x72000000,0x72000000,0x4C000000,0xB6000092,0x82000050,0x3600000D,0x220000AA,
+0x3C01E1,};
+static const uint32_t g_etc1_to_bc7_m6_table135[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x740000,0x740000,0x740000,0x740000,0x740000,
+0x740000,0xE80000,0xE80000,0xE80000,0x26000000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0xE80000,0xE80000,0xE80000,0x26000000,0xE80000,0xE80000,0xE80000,0x26000000,0x26000000,0x540000,0x4C0001,0x4C0001,0x4580000,0x2600000,0x2680000,0x2680000,0x2800000,0x4580000,0x2600000,0xA40000,0xE80000,
+0xA40000,0x940001,0x940001,0x940001,0x940001,0x2DC0000,0x2DC0000,0x2DC0000,0x1C40000,0x1C40000,0x4A000000,0x2DC0000,0x2DC0000,0x2DC0000,0x1C40000,0x1C40000,0x4A000000,0x1C40000,0x1C40000,0x4A000000,0x4A000000,0x2DC0000,0x2DC0000,0x2DC0000,0x1C40000,0x1C40000,0x4A000000,0x1C40000,0x1C40000,0x4A000000,0x4A000000,0x1C40000,
+0x1C40000,0x4A000000,0x4A000000,0x4A000000,0x4AC0000,0xA00000,0x940001,0xCC0000,0xFC0000,0x13C0000,0x16C0000,0xBF80000,0xBC0000,0x2DC0000,0x13C0000,0x4A000000,0x13C0000,0xE80001,0x15C0000,0x33F80000,0x74000000,0x15C0000,0x33F80000,0x74000000,0x33F80000,0x74000000,0x74000000,0x15C0000,0x33F80000,0x74000000,0x33F80000,0x74000000,
+0x74000000,0x33F80000,0x74000000,0x74000000,0x74000000,0x15C0000,0x33F80000,0x74000000,0x33F80000,0x74000000,0x74000000,0x33F80000,0x74000000,0x74000000,0x74000000,0x33F80000,0x74000000,0x74000000,0x74000000,0x74000000,0x1240000,0x4F80000,0x4F80000,0x1880000,0x17FC0000,0x53F00000,0x74000000,0x74000000,0x33C0000,0x1B80000,0x6DCC0000,0x74000000,
+0x1F00000,0x741D47,0xFE500B2E,0x9A4C0AFE,0x744C0AFE,0xFA28066B,0xA62C0322,0x7A340492,0x8428066B,0x6E24033A,0x5E28066D,0xEA000BE8,0xAC000289,0x781803CA,0x8C0003A5,0x72000009,0x60080394,0x72000BE8,0x6600046C,0x5600057D,0x4C000BE8,0xAC1D47,0x92000D6E,0x74000AFE,0x80000B01,0x6800053D,0x5E000775,0x680010D8,0x5E00088F,0x540008B8,0x48000E58,0x15C1D47,
+0x5000130E,0x4A001121,0x440014EC,0x38001D49,0xFE3C0AD7,0xFC68162D,0xFE6C17C2,0xFE0C0095,0xC000000D,0x90000005,0x7608002D,0x6C000072,0xFE180A0E,0xE6000156,0x7600031A,0x540008B8,0xF41D47,0x980BEB,0xEC74028A,0x9270028A,0x7470028A,0xD2500373,0x9A4C0002,0x76580041,0x7A500373,0x6E4800A6,0x5E4C0375,0xE40BE8,0xAA040289,0x74380288,0x8C0003A5,0x72000009,
+0x5E180374,0x1D00BE8,0x6600046C,0x5600057D,0x4C000BE8,0xE40BE8,0xAA040289,0x74380288,0x8C0003A5,0x72000009,0x5E180374,0x1D00BE8,0x6600046C,0x5600057D,0x4C000BE8,0x1D00BE8,0x6600046C,0x5600057D,0x4C000BE8,0x4C000BE8,0xFC6004C1,0xFC8808BB,0xFE8C08A3,0xFE14004A,0xC000000D,0x90000005,0x74140002,0x6C000072,0xFC4004E8,0xEC00007E,0x760002E9,0x5600057D,
+0x1480BE8,0x4C0AFE,0x4C0AFE,0x4C0AFE,0x4C0AFE,0xBA2802F9,0xBA2802F9,0xBA2802F9,0x642802FA,0x642802FA,0x4A2802F9,0xAC000288,0xAC000288,0xAC000288,0x6E040005,0x6E040005,0x4C100084,0x54000288,0x54000288,0x44000055,0x38000288,0x700AFE,0x700AFE,0x700AFE,0x62000471,0x62000471,0x46000321,0x4C00052B,0x4C00052B,0x40000236,0x340003C9,0xE40AFE,
+0xE40AFE,0x320006DD,0x2C00072C,0x24000B01,0xFE2C0378,0xFA440776,0x4C0AFE,0xFE080020,0xB8000001,0x8E000002,0x80040011,0x62000005,0xFE00031A,0xD40000D2,0x660002B4,0x40000236,0xA00AFE,0x70028A,0x70028A,0x70028A,0x70028A,0x92500001,0x92500001,0x92500001,0x5C4C0001,0x5C4C0001,0x4A4C0001,0xA80288,0xA80288,0xA80288,0x6A0C0001,0x6A0C0001,
+0x4A2C0000,0x1580288,0x1580288,0x44000055,0x38000288,0xA80288,0xA80288,0xA80288,0x6A0C0001,0x6A0C0001,0x4A2C0000,0x1580288,0x1580288,0x44000055,0x38000288,0x1580288,0x1580288,0x44000055,0x38000288,0x38000288,0xF64800B5,0xFA640109,0x70028A,0xFA10000D,0xAE0C0001,0x88080000,0x76140000,0x62000005,0xF62400DD,0xDA000022,0xF00288,0x44000055,
+0xF00288,0xC00372,0xC8980001,0x88980001,0x74940001,0x11C0372,0x9A480001,0x746C0000,0x13FC0372,0x72000008,0x5E000374,0x11C0372,0x9A480001,0x746C0000,0x13FC0372,0x72000008,0x5E000374,0x13FC0372,0x72000008,0x5E000374,0x5E000374,0x11C0372,0x9A480001,0x746C0000,0x13FC0372,0x72000008,0x5E000374,0x13FC0372,0x72000008,0x5E000374,0x5E000374,0x13FC0372,
+0x72000008,0x5E000374,0x5E000374,0x5E000374,0xFE7801B1,0xCC0372,0xF2B40202,0xFE200020,0xC000000D,0x90000005,0x741C0000,0x70000050,0xFE5C018A,0xF400001D,0x7A280000,0x5E000374,0x1980372,0x2802F9,0x2802F9,0x2802F9,0x2802F9,0x2802F9,0x2802F9,0x2802F9,0x2802F9,0x2802F9,0x2802F9,0x76000000,0x76000000,0x76000000,0x76000000,0x76000000,
+0x76000000,0x38000001,0x38000001,0x38000001,0x26000000,0x3802F9,0x3802F9,0x3802F9,0x3802F9,0x3802F9,0x3802F9,0x2E000112,0x2E000112,0x2E000112,0x22000089,0x7002F9,0x7002F9,0x7002F9,0x1C0001CD,0x120002F9,0xF4180120,0x2802F9,0x2802F9,0xFE040005,0xBE000000,0x90000000,0x90000000,0x5E000000,0xF60000F1,0xA400007D,0x46000011,0x2E000112,
+0x5002F9,};
+static const uint32_t g_etc1_to_bc7_m6_table136[] = {
+0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x200000,
+0x200000,0x200000,0x200000,0x4000001,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0x100000,0x180000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,
+0x28C0000,0x1200000,0x1200000,0x1200000,0x2E000001,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x1200000,0x1200000,0x1200000,0x2E000001,0x1200000,0x1200000,0x1200000,0x2E000001,0x2E000001,0xA640000,0x600000,0x600000,0x700000,0x780000,0x2800000,0x2800000,0xA00000,0x700000,0x780000,0xCC0000,0x1200000,
+0xCC0000,0xA80000,0xA80000,0xA80000,0xA80000,0xF80000,0xF80000,0xF80000,0x1FC0000,0x1FC0000,0x52000001,0xF80000,0xF80000,0xF80000,0x1FC0000,0x1FC0000,0x52000001,0x1FC0000,0x1FC0000,0x52000001,0x52000001,0xF80000,0xF80000,0xF80000,0x1FC0000,0x1FC0000,0x52000001,0x1FC0000,0x1FC0000,0x52000001,0x52000001,0x1FC0000,
+0x1FC0000,0x52000001,0x52000001,0x52000001,0xC40000,0xB40000,0xA80000,0xE40000,0x1180000,0x1640000,0x19C0000,0x17F80000,0x4D00000,0xF80000,0x1640000,0x52000001,0x1640000,0xFC0000,0x3740000,0x3FFC0000,0x7C000001,0x3740000,0x3FFC0000,0x7C000001,0x3FFC0000,0x7C000001,0x7C000001,0x3740000,0x3FFC0000,0x7C000001,0x3FFC0000,0x7C000001,
+0x7C000001,0x3FFC0000,0x7C000001,0x7C000001,0x7C000001,0x3740000,0x3FFC0000,0x7C000001,0x3FFC0000,0x7C000001,0x7C000001,0x3FFC0000,0x7C000001,0x7C000001,0x7C000001,0x3FFC0000,0x7C000001,0x7C000001,0x7C000001,0x7C000001,0x13C0000,0x10C0000,0x10C0000,0x1A80000,0x27F80000,0x5DFC0000,0x7C000001,0x7C000001,0x3540000,0x1D80000,0x75FC0000,0x7C000001,
+0xDFC0000,0x841EA8,0xFE600C58,0xA45C0BE8,0x7C5C0BE9,0xFC3806F8,0xB23803A1,0x82440531,0x8E3406E6,0x7A3403AE,0x683406E6,0xF80C0BE8,0xB80C028A,0x84240411,0x9608038E,0x7C0C000E,0x6A1403AE,0x7C0C0BE8,0x72000417,0x62040533,0x540C0BEB,0xC41EA8,0xA8000D6B,0x7C100BE9,0x8C000A7E,0x740004CE,0x68000746,0x7400107B,0x6A000782,0x5E0007AB,0x52000DBC,0x18C1EA8,
+0x5C001329,0x560010EE,0x4A0014E3,0x40001EAC,0xFE500C45,0xFE6C17DE,0xF67C1978,0xFE1C0128,0xCA0C0011,0x9A0C0006,0x80140046,0x78040046,0xFE340B52,0xFE000098,0x820002B5,0x5E0007AB,0x1181EA8,0xAC0BE8,0xF8840288,0x9A840288,0x7C840289,0xDC600372,0xA0600005,0x7E680042,0x84600372,0x765800A5,0x68600372,0x1000BE8,0xB4140289,0x7E480289,0x9A00037D,0x7C14000A,
+0x68280372,0x5F80BE8,0x720003F3,0x60000513,0x54000BEB,0x1000BE8,0xB4140289,0x7E480289,0x9A00037D,0x7C14000A,0x68280372,0x5F80BE8,0x720003F3,0x60000513,0x54000BEB,0x5F80BE8,0x720003F3,0x60000513,0x54000BEB,0x54000BEB,0xFE7804ED,0xF69C08F6,0xFAA408C9,0xFE300081,0xCA10000D,0x98100006,0x7E280001,0x7A000031,0xFC580519,0xFE040033,0x820002B1,0x60000513,
+0x16C0BE8,0x5C0BE8,0x5C0BE8,0x5C0BE8,0x5C0BE8,0xC6380374,0xC6380374,0xC6380374,0x6E380374,0x6E380374,0x52340375,0xBC0C0288,0xBC0C0288,0xBC0C0288,0x7A100009,0x7A100009,0x561800A6,0x5E0C0288,0x5E0C0288,0x4E080041,0x400C028A,0x880BE8,0x880BE8,0x880BE8,0x6E000465,0x6E000465,0x52000373,0x580004E1,0x580004E1,0x4C0001AA,0x4000036B,0x1140BE8,
+0x1140BE8,0x3E0006ED,0x3800072A,0x2C000BEB,0xFE3C0434,0xFE4C0864,0x5C0BE8,0xFE180059,0xC80C0005,0x9A0C0005,0x88140021,0x6E0C0002,0xFE1403B9,0xF600005E,0x7C00028C,0x4C0001AA,0xC00BE8,0x840288,0x840288,0x840288,0x840288,0x9C600000,0x9C600000,0x9C600000,0x64600000,0x64600000,0x52600001,0xC40288,0xC40288,0xC40288,0x72200001,0x72200001,
+0x543C0001,0x18C0288,0x18C0288,0x5000002D,0x4000028A,0xC40288,0xC40288,0xC40288,0x72200001,0x72200001,0x543C0001,0x18C0288,0x18C0288,0x5000002D,0x4000028A,0x18C0288,0x18C0288,0x5000002D,0x4000028A,0x4000028A,0xFE5800B5,0xF4780120,0x840288,0xFE240012,0xBC180000,0x92180000,0x7E280000,0x70080000,0xFE3400DD,0xFC00000A,0x1180288,0x5000002D,
+0x1180288,0xD00374,0xD2A80000,0x92A80000,0x7CA80001,0x1380372,0xA25C0001,0x7C800001,0x21F80372,0x7C000001,0x68000372,0x1380372,0xA25C0001,0x7C800001,0x21F80372,0x7C000001,0x68000372,0x21F80372,0x7C000001,0x68000372,0x68000372,0x1380372,0xA25C0001,0x7C800001,0x21F80372,0x7C000001,0x68000372,0x21F80372,0x7C000001,0x68000372,0x68000372,0x21F80372,
+0x7C000001,0x68000372,0x68000372,0x68000372,0xFE9401C2,0xE00372,0xFCC80200,0xFC3C0032,0xCE040005,0x9C040000,0x7C300001,0x7A00002D,0xFE7001B1,0xFE080014,0x84380000,0x68000372,0x1BC0372,0x340374,0x340374,0x340374,0x340374,0x340374,0x340374,0x340374,0x340374,0x340374,0x340374,0x840C0000,0x840C0000,0x840C0000,0x840C0000,0x840C0000,
+0x840C0000,0x440C0000,0x440C0000,0x440C0000,0x2E0C0001,0x500372,0x500372,0x500372,0x500372,0x500372,0x500372,0x3A0000E9,0x3A0000E9,0x3A0000E9,0x2E000052,0xA00372,0xA00372,0xA00372,0x200001E1,0x1A000372,0xFC28016D,0x340374,0x340374,0xFE10001D,0xD20C0000,0xA20C0000,0xA20C0000,0x6C0C0000,0xF80400F2,0xD6000041,0x5A000000,0x3A0000E9,
+0x700372,};
+static const uint32_t g_etc1_to_bc7_m6_table137[] = {
+0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x280000,0x500000,
+0x500000,0x500000,0x500000,0xC000001,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x61C0000,0x61C0000,0x61C0000,0x280000,0x380000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,
+0x2A40000,0x1500000,0x1500000,0x1500000,0x36000001,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x1500000,0x1500000,0x1500000,0x36000001,0x1500000,0x1500000,0x1500000,0x36000001,0x36000001,0x780000,0x700000,0x700000,0x4800000,0x8C0000,0x980000,0x980000,0xBC0000,0x4800000,0x8C0000,0xEC0000,0x1500000,
+0xEC0000,0xB80000,0xB80000,0xB80000,0xB80000,0x1100000,0x1100000,0x1100000,0xDFC0000,0xDFC0000,0x5A000001,0x1100000,0x1100000,0x1100000,0xDFC0000,0xDFC0000,0x5A000001,0xDFC0000,0xDFC0000,0x5A000001,0x5A000001,0x1100000,0x1100000,0x1100000,0xDFC0000,0xDFC0000,0x5A000001,0xDFC0000,0xDFC0000,0x5A000001,0x5A000001,0xDFC0000,
+0xDFC0000,0x5A000001,0x5A000001,0x5A000001,0x2D40000,0xC40000,0xB80000,0x2F80000,0x1340000,0x1880000,0x1C00000,0x21FC0000,0x4E40000,0x1100000,0x1880000,0x5A000001,0x1880000,0x10C0000,0x38C0000,0x4BFC0000,0x84000001,0x38C0000,0x4BFC0000,0x84000001,0x4BFC0000,0x84000001,0x84000001,0x38C0000,0x4BFC0000,0x84000001,0x4BFC0000,0x84000001,
+0x84000001,0x4BFC0000,0x84000001,0x84000001,0x84000001,0x38C0000,0x4BFC0000,0x84000001,0x4BFC0000,0x84000001,0x84000001,0x4BFC0000,0x84000001,0x84000001,0x84000001,0x4BFC0000,0x84000001,0x84000001,0x84000001,0x84000001,0x1500000,0x71C0000,0x71C0000,0x3C00000,0x35F80000,0x67FC0000,0x84000001,0x84000001,0x16C0000,0x1F80000,0x7FD00000,0x84000001,
+0x1DF80000,0x941EA8,0xFE740C91,0xAC6C0BE8,0x846C0BE9,0xFC4C0716,0xBA4803A1,0x8A540531,0x964406E6,0x824403AE,0x704406E6,0xFE1C0BEB,0xC01C028A,0x8C340411,0x9E18038E,0x841C000E,0x722403AE,0x841C0BE8,0x780C0413,0x6A140533,0x5C1C0BEB,0xDC1EA8,0xBA000CBB,0x84200BE9,0x9800096E,0x80000406,0x700006EC,0x86000F87,0x7400061B,0x68000663,0x5A000D03,0x1BC1EA8,
+0x6600124C,0x5C000FB6,0x5600140B,0x48001EAC,0xFE640CCE,0xFC8817E8,0xFE8C1978,0xFE34018E,0xD21C0011,0xA21C0006,0x88240046,0x80140046,0xFE440C0F,0xFE1000C2,0x8A08029D,0x68000663,0x1381EA8,0xBC0BE8,0xFC940289,0xA2940288,0x84940289,0xE4700372,0xA8700005,0x86780042,0x8C700372,0x7E6800A5,0x70700372,0x1180BE8,0xBC240289,0x86580289,0xA6040372,0x8424000A,
+0x70380372,0x11F80BE8,0x78000393,0x6C0004B3,0x5C000BEB,0x1180BE8,0xBC240289,0x86580289,0xA6040372,0x8424000A,0x70380372,0x11F80BE8,0x78000393,0x6C0004B3,0x5C000BEB,0x11F80BE8,0x78000393,0x6C0004B3,0x5C000BEB,0x5C000BEB,0xFE800552,0xFEAC08F6,0xFEAC0901,0xFE4000AB,0xD220000D,0xA0200006,0x86380001,0x82000022,0xFE5C0579,0xFE180059,0x8C00028E,0x6C0004B3,
+0x1900BE8,0x6C0BE8,0x6C0BE8,0x6C0BE8,0x6C0BE8,0xCE480374,0xCE480374,0xCE480374,0x76480374,0x76480374,0x5A440375,0xC41C0288,0xC41C0288,0xC41C0288,0x82200009,0x82200009,0x5E2800A6,0x661C0288,0x661C0288,0x56180041,0x481C028A,0xA00BE8,0xA00BE8,0xA00BE8,0x800003ED,0x800003ED,0x5A100373,0x6800042A,0x6800042A,0x540000F6,0x460002EB,0x1440BE8,
+0x1440BE8,0x4A000655,0x3E00068A,0x34000BEB,0xFE4C0461,0xFA64087D,0x6C0BE8,0xFE2C0081,0xD01C0005,0xA21C0005,0x90240021,0x761C0002,0xFA2C03F9,0xFC080049,0x840C028A,0x540000F6,0xE40BE8,0x940288,0x940288,0x940288,0x940288,0xA4700000,0xA4700000,0xA4700000,0x6C700000,0x6C700000,0x5A700001,0xDC0288,0xDC0288,0xDC0288,0x7A300001,0x7A300001,
+0x5C4C0001,0x1BC0288,0x1BC0288,0x58000019,0x4800028A,0xDC0288,0xDC0288,0xDC0288,0x7A300001,0x7A300001,0x5C4C0001,0x1BC0288,0x1BC0288,0x58000019,0x4800028A,0x1BC0288,0x1BC0288,0x58000019,0x4800028A,0x4800028A,0xFA6C00C8,0xFC880120,0x940288,0xFE34001D,0xC4280000,0x9A280000,0x86380000,0x78180000,0xFA4800F4,0xFC14000D,0x1380288,0x58000019,
+0x1380288,0xE00374,0xDAB80000,0x9AB80000,0x84B80001,0x1500372,0xAA6C0001,0x84900001,0x2DF80372,0x84100001,0x70000372,0x1500372,0xAA6C0001,0x84900001,0x2DF80372,0x84100001,0x70000372,0x2DF80372,0x84100001,0x70000372,0x70000372,0x1500372,0xAA6C0001,0x84900001,0x2DF80372,0x84100001,0x70000372,0x2DF80372,0x84100001,0x70000372,0x70000372,0x2DF80372,
+0x84100001,0x70000372,0x70000372,0x70000372,0xF8A801E1,0xF00372,0xF4D80221,0xFC540048,0xDC080001,0xA4140000,0x84400001,0x82000019,0xFC8C01C2,0xFE200028,0x8C480000,0x70000372,0x1E00372,0x440374,0x440374,0x440374,0x440374,0x440374,0x440374,0x440374,0x440374,0x440374,0x440374,0x8C1C0000,0x8C1C0000,0x8C1C0000,0x8C1C0000,0x8C1C0000,
+0x8C1C0000,0x4C1C0000,0x4C1C0000,0x4C1C0000,0x361C0001,0x680372,0x680372,0x680372,0x680372,0x680372,0x680372,0x4C000089,0x4C000089,0x4C000089,0x36000011,0xD00372,0xD00372,0xD00372,0x2C000179,0x22000372,0xF4380188,0x440374,0x440374,0xFE200028,0xDA1C0000,0xAA1C0000,0xAA1C0000,0x741C0000,0xFE1000FA,0xFE000014,0x62100000,0x4C000089,
+0x940372,};
+static const uint32_t g_etc1_to_bc7_m6_table138[] = {
+0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x800000,
+0x800000,0x800000,0x800000,0x14000001,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0xE2C0000,0xE2C0000,0xE2C0000,0x400000,0x5C0000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,
+0x2BC0000,0x1800000,0x1800000,0x1800000,0x3E000001,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x1800000,0x1800000,0x1800000,0x3E000001,0x1800000,0x1800000,0x1800000,0x3E000001,0x3E000001,0x880000,0x800000,0x800000,0x940000,0xA00000,0x2AC0000,0x2AC0000,0x2D40000,0x940000,0xA00000,0x1100000,0x1800000,
+0x1100000,0xC80000,0xC80000,0xC80000,0xC80000,0x1280000,0x1280000,0x1280000,0x19FC0000,0x19FC0000,0x62000001,0x1280000,0x1280000,0x1280000,0x19FC0000,0x19FC0000,0x62000001,0x19FC0000,0x19FC0000,0x62000001,0x62000001,0x1280000,0x1280000,0x1280000,0x19FC0000,0x19FC0000,0x62000001,0x19FC0000,0x19FC0000,0x62000001,0x62000001,0x19FC0000,
+0x19FC0000,0x62000001,0x62000001,0x62000001,0xE80000,0x2D40000,0xC80000,0x1100000,0x1500000,0x1A80000,0x1E80000,0x2DF80000,0x4F80000,0x1280000,0x1A80000,0x62000001,0x1A80000,0x11C0000,0x3A40000,0x57FC0000,0x8C000001,0x3A40000,0x57FC0000,0x8C000001,0x57FC0000,0x8C000001,0x8C000001,0x3A40000,0x57FC0000,0x8C000001,0x57FC0000,0x8C000001,
+0x8C000001,0x57FC0000,0x8C000001,0x8C000001,0x8C000001,0x3A40000,0x57FC0000,0x8C000001,0x57FC0000,0x8C000001,0x8C000001,0x57FC0000,0x8C000001,0x8C000001,0x8C000001,0x57FC0000,0x8C000001,0x8C000001,0x8C000001,0x8C000001,0x1640000,0xF2C0000,0xF2C0000,0x1DC0000,0x41FC0000,0x71FC0000,0x8C000001,0x8C000001,0x3800000,0xFFC0000,0x87E00000,0x8C000001,
+0x2BFC0000,0xA41EA8,0xFE800CD5,0xB47C0BE8,0x8C7C0BE9,0xFE5C073E,0xC25803A1,0x92640531,0x9E5406E6,0x8A5403AE,0x785406E6,0xFE300BF8,0xC82C028A,0x94440411,0xA628038E,0x8C2C000E,0x7A3403AE,0x8C2C0BE8,0x801C0413,0x72240533,0x642C0BEB,0xF41EA8,0xC6000C43,0x8C300BE9,0xA8000866,0x8C00039E,0x780806E6,0x92000EA7,0x800004F3,0x70000563,0x64000C64,0x1F01EA8,
+0x72001164,0x66000EB4,0x5C00131B,0x50001EAC,0xFE780D71,0xF498186E,0xF8A019DD,0xFE440206,0xDA2C0011,0xAA2C0006,0x90340046,0x88240046,0xFE540C9B,0xFE240136,0x9218029D,0x70000563,0x15C1EA8,0xCC0BE8,0xFEA40291,0xAAA40288,0x8CA40289,0xEC800372,0xB0800005,0x8E880042,0x94800372,0x867800A5,0x78800372,0x1300BE8,0xC4340289,0x8E680289,0xAE140372,0x8C34000A,
+0x78480372,0x1DF40BE8,0x8400033B,0x72000463,0x64000BEB,0x1300BE8,0xC4340289,0x8E680289,0xAE140372,0x8C34000A,0x78480372,0x1DF40BE8,0x8400033B,0x72000463,0x64000BEB,0x1DF40BE8,0x8400033B,0x72000463,0x64000BEB,0x64000BEB,0xFE94057B,0xF8C00934,0xFAC4090C,0xFE5400EA,0xDA30000D,0xA8300006,0x8E480001,0x8A100022,0xFE780595,0xFE300095,0x96080288,0x72000463,
+0x1B00BE8,0x7C0BE8,0x7C0BE8,0x7C0BE8,0x7C0BE8,0xD6580374,0xD6580374,0xD6580374,0x7E580374,0x7E580374,0x62540375,0xCC2C0288,0xCC2C0288,0xCC2C0288,0x8A300009,0x8A300009,0x663800A6,0x6E2C0288,0x6E2C0288,0x5E280041,0x502C028A,0xB80BE8,0xB80BE8,0xB80BE8,0x8C00039D,0x8C00039D,0x62200373,0x7400039A,0x7400039A,0x5E00006A,0x500002A3,0x1740BE8,
+0x1740BE8,0x500005CD,0x4A0005FA,0x3C000BEB,0xFE5804B9,0xFE6C08A5,0x7C0BE8,0xFE3C00A8,0xD82C0005,0xAA2C0005,0x98340021,0x7E2C0002,0xFE3C0428,0xFE180062,0x8C1C028A,0x5E00006A,0x1080BE8,0xA40288,0xA40288,0xA40288,0xA40288,0xAC800000,0xAC800000,0xAC800000,0x74800000,0x74800000,0x62800001,0xF40288,0xF40288,0xF40288,0x82400001,0x82400001,
+0x645C0001,0x1F00288,0x1F00288,0x6000000A,0x5000028A,0xF40288,0xF40288,0xF40288,0x82400001,0x82400001,0x645C0001,0x1F00288,0x1F00288,0x6000000A,0x5000028A,0x1F00288,0x1F00288,0x6000000A,0x5000028A,0x5000028A,0xF68000DD,0xF4980139,0xA40288,0xF8500029,0xCC380000,0xA2380000,0x8E480000,0x80280000,0xF2600109,0xFE240014,0x15C0288,0x6000000A,
+0x15C0288,0xF00374,0xE2C80000,0xA2C80000,0x8CC80001,0x1680372,0xB27C0001,0x8CA00001,0x39F80372,0x8C200001,0x78000372,0x1680372,0xB27C0001,0x8CA00001,0x39F80372,0x8C200001,0x78000372,0x39F80372,0x8C200001,0x78000372,0x78000372,0x1680372,0xB27C0001,0x8CA00001,0x39F80372,0x8C200001,0x78000372,0x39F80372,0x8C200001,0x78000372,0x78000372,0x39F80372,
+0x8C200001,0x78000372,0x78000372,0x78000372,0xFEB401ED,0x9000372,0xFCE80221,0xFE6C0055,0xE4180001,0xAC240000,0x8C500001,0x8A00000D,0xFE9801D4,0xFE400032,0x94580000,0x78000372,0x3FC0372,0x540374,0x540374,0x540374,0x540374,0x540374,0x540374,0x540374,0x540374,0x540374,0x540374,0x942C0000,0x942C0000,0x942C0000,0x942C0000,0x942C0000,
+0x942C0000,0x542C0000,0x542C0000,0x542C0000,0x3E2C0001,0x800372,0x800372,0x800372,0x800372,0x800372,0x800372,0x58000041,0x58000041,0x58000041,0x3E040001,0x1000372,0x1000372,0x1000372,0x38000131,0x2A000372,0xFC480188,0x540374,0x540374,0xFA340034,0xE22C0000,0xB22C0000,0xB22C0000,0x7C2C0000,0xFE200115,0xFE140019,0x6A200000,0x58000041,
+0xB40372,};
+static const uint32_t g_etc1_to_bc7_m6_table139[] = {
+0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0x580000,0xB00000,
+0xB00000,0xB00000,0xB00000,0x1C000001,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x3C0000,0x400000,0x400000,0x400000,0x580000,0x7C0000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,
+0xD40000,0x1B00000,0x1B00000,0x1B00000,0x46000001,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0x1B00000,0x1B00000,0x1B00000,0x46000001,0x1B00000,0x1B00000,0x1B00000,0x46000001,0x46000001,0x4980000,0x900000,0x900000,0xA80000,0xB40000,0xC40000,0xC40000,0xF00000,0xA80000,0xB40000,0x1300000,0x1B00000,
+0x1300000,0xD80000,0xD80000,0xD80000,0xD80000,0x1400000,0x1400000,0x1400000,0x25F80000,0x25F80000,0x6A000001,0x1400000,0x1400000,0x1400000,0x25F80000,0x25F80000,0x6A000001,0x25F80000,0x25F80000,0x6A000001,0x6A000001,0x1400000,0x1400000,0x1400000,0x25F80000,0x25F80000,0x6A000001,0x25F80000,0x25F80000,0x6A000001,0x6A000001,0x25F80000,
+0x25F80000,0x6A000001,0x6A000001,0x6A000001,0xFC0000,0xAE40000,0xD80000,0x3240000,0x16C0000,0x1CC0000,0x9F80000,0x37FC0000,0x50C0000,0x1400000,0x1CC0000,0x6A000001,0x1CC0000,0x12C0000,0x3BC0000,0x63FC0000,0x94000001,0x3BC0000,0x63FC0000,0x94000001,0x63FC0000,0x94000001,0x94000001,0x3BC0000,0x63FC0000,0x94000001,0x63FC0000,0x94000001,
+0x94000001,0x63FC0000,0x94000001,0x94000001,0x94000001,0x3BC0000,0x63FC0000,0x94000001,0x63FC0000,0x94000001,0x94000001,0x63FC0000,0x94000001,0x94000001,0x94000001,0x63FC0000,0x94000001,0x94000001,0x94000001,0x94000001,0x1780000,0x1400000,0x1400000,0x1F80000,0x4FFC0000,0x7BFC0000,0x94000001,0x94000001,0x1980000,0x21FC0000,0x8FF00000,0x94000001,
+0x3BFC0000,0xB41EA8,0xFE980D35,0xBC8C0BE8,0x948C0BE9,0xFE74078E,0xCA6803A1,0x9A740531,0xA66406E6,0x926403AE,0x806406E6,0xFE440C13,0xD03C028A,0x9C540411,0xAE38038E,0x943C000E,0x824403AE,0x943C0BE8,0x882C0413,0x7A340533,0x6C3C0BEB,0x10C1EA8,0xD8000BFB,0x94400BE9,0xBA0007BE,0x9608038E,0x801806E6,0x9E000DE7,0x8C00040B,0x7A000497,0x6C000C0F,0xBF81EA8,
+0x7800109C,0x72000DB4,0x6600126C,0x58001EAC,0xFE8C0E18,0xFCA8186E,0xFEAC19E1,0xFE5C0296,0xE23C0011,0xB23C0006,0x98440046,0x90340046,0xFE700D55,0xFE3401B7,0x9A28029D,0x7A000497,0x17C1EA8,0xDC0BE8,0xFCB802A9,0xB2B40288,0x94B40289,0xF4900372,0xB8900005,0x96980042,0x9C900372,0x8E8800A5,0x80900372,0x3440BE8,0xCC440289,0x96780289,0xB6240372,0x9444000A,
+0x80580372,0x27FC0BE8,0x8E000301,0x7C000422,0x6C000BEB,0x3440BE8,0xCC440289,0x96780289,0xB6240372,0x9444000A,0x80580372,0x27FC0BE8,0x8E000301,0x7C000422,0x6C000BEB,0x27FC0BE8,0x8E000301,0x7C000422,0x6C000BEB,0x6C000BEB,0xFCB005BD,0xFECC0938,0xFECC094C,0xFE6C0129,0xE240000D,0xB0400006,0x96580001,0x92200022,0xFE8805E8,0xFE4800B9,0x9E180288,0x7C000422,
+0x1D40BE8,0x8C0BE8,0x8C0BE8,0x8C0BE8,0x8C0BE8,0xDE680374,0xDE680374,0xDE680374,0x86680374,0x86680374,0x6A640375,0xD43C0288,0xD43C0288,0xD43C0288,0x92400009,0x92400009,0x6E4800A6,0x763C0288,0x763C0288,0x66380041,0x583C028A,0xD00BE8,0xD00BE8,0xD00BE8,0x9E000375,0x9E000375,0x6A300373,0x8000032A,0x8000032A,0x6800001A,0x5A00028A,0x1A40BE8,
+0x1A40BE8,0x5C000545,0x5000056A,0x44000BEB,0xFE6804EE,0xFA8408B8,0x8C0BE8,0xFE4C00D9,0xE03C0005,0xB23C0005,0xA0440021,0x863C0002,0xFE500455,0xFE300081,0x942C028A,0x6800001A,0x1280BE8,0xB40288,0xB40288,0xB40288,0xB40288,0xB4900000,0xB4900000,0xB4900000,0x7C900000,0x7C900000,0x6A900001,0x10C0288,0x10C0288,0x10C0288,0x8A500001,0x8A500001,
+0x6C6C0001,0xBF80288,0xBF80288,0x6A000001,0x5800028A,0x10C0288,0x10C0288,0x10C0288,0x8A500001,0x8A500001,0x6C6C0001,0xBF80288,0xBF80288,0x6A000001,0x5800028A,0xBF80288,0xBF80288,0x6A000001,0x5800028A,0x5800028A,0xFE9000DD,0xFCA80139,0xB40288,0xFE5C002D,0xD4480000,0xAA480000,0x96580000,0x88380000,0xFA700109,0xFA400020,0x17C0288,0x6A000001,
+0x17C0288,0x1000374,0xEAD80000,0xAAD80000,0x94D80001,0x1800372,0xBA8C0001,0x94B00001,0x45F80372,0x94300001,0x80000372,0x1800372,0xBA8C0001,0x94B00001,0x45F80372,0x94300001,0x80000372,0x45F80372,0x94300001,0x80000372,0x80000372,0x1800372,0xBA8C0001,0x94B00001,0x45F80372,0x94300001,0x80000372,0x45F80372,0x94300001,0x80000372,0x80000372,0x45F80372,
+0x94300001,0x80000372,0x80000372,0x80000372,0xFCCC0202,0x1140372,0xF4F80244,0xFE800071,0xEC280001,0xB4340000,0x94600001,0x94000002,0xFEAC01F9,0xFE58004A,0x9C680000,0x80000372,0x13FC0372,0x640374,0x640374,0x640374,0x640374,0x640374,0x640374,0x640374,0x640374,0x640374,0x640374,0x9C3C0000,0x9C3C0000,0x9C3C0000,0x9C3C0000,0x9C3C0000,
+0x9C3C0000,0x5C3C0000,0x5C3C0000,0x5C3C0000,0x463C0001,0x980372,0x980372,0x980372,0x980372,0x980372,0x980372,0x68000011,0x68000011,0x68000011,0x46140001,0x1300372,0x1300372,0x1300372,0x3E0000E1,0x32000372,0xF45801A5,0x640374,0x640374,0xFC48003D,0xEA3C0000,0xBA3C0000,0xBA3C0000,0x843C0000,0xFC380120,0xF8280029,0x72300000,0x68000011,
+0xD80372,};
+static const uint32_t g_etc1_to_bc7_m6_table140[] = {
+0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0xE80000,
+0xE80000,0xE80000,0xE80000,0x26000000,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x540000,0x540000,0x540000,0x740000,0xA40000,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xA00001,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,
+0xF00000,0x1E80000,0x1E80000,0x1E80000,0x50000000,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,0xF00000,0x1E80000,0x1E80000,0x1E80000,0x50000000,0x1E80000,0x1E80000,0x1E80000,0x50000000,0x50000000,0xAC0000,0xA00001,0xA00001,0xBC0000,0xCC0000,0xDC0000,0xDC0000,0x1100000,0xBC0000,0xCC0000,0x1580000,0x1E80000,
+0x1580000,0xE80001,0xE80001,0xE80001,0xE80001,0x15C0000,0x15C0000,0x15C0000,0x33F80000,0x33F80000,0x74000000,0x15C0000,0x15C0000,0x15C0000,0x33F80000,0x33F80000,0x74000000,0x33F80000,0x33F80000,0x74000000,0x74000000,0x15C0000,0x15C0000,0x15C0000,0x33F80000,0x33F80000,0x74000000,0x33F80000,0x33F80000,0x74000000,0x74000000,0x33F80000,
+0x33F80000,0x74000000,0x74000000,0x74000000,0x1100000,0x4F80000,0xE80001,0x33C0000,0x1880000,0x1F00000,0x17FC0000,0x43FC0000,0x1240000,0x15C0000,0x1F00000,0x74000000,0x1F00000,0x13C0001,0x1D80000,0x71F80000,0x9E000000,0x1D80000,0x71F80000,0x9E000000,0x71F80000,0x9E000000,0x9E000000,0x1D80000,0x71F80000,0x9E000000,0x71F80000,0x9E000000,
+0x9E000000,0x71F80000,0x9E000000,0x9E000000,0x9E000000,0x1D80000,0x71F80000,0x9E000000,0x71F80000,0x9E000000,0x9E000000,0x71F80000,0x9E000000,0x9E000000,0x9E000000,0x71F80000,0x9E000000,0x9E000000,0x9E000000,0x9E000000,0x58C0000,0x1540000,0x1540000,0x13FC0000,0x5FF80000,0x87F80000,0x9E000000,0x9E000000,0x1B00000,0x33FC0000,0x99E40000,0x9E000000,
+0x4BFC0000,0xC41EAC,0xFEA40D93,0xC4A00BEB,0x9E9C0BEB,0xFE8407F4,0xD47C03A3,0xA2840533,0xAE7806E6,0x9A7403AE,0x887806E6,0xFE5C0C49,0xDA50028A,0xA6680413,0xB84C038E,0x9E4C000E,0x8A5403AE,0x9C500BE9,0x92400411,0x82440531,0x764C0BE9,0x3241EA8,0xE8080BE9,0x9E500BE8,0xC6000736,0xA01C038E,0x882C06E6,0xAE000D2F,0x98000345,0x840003FD,0x76000BE8,0x17FC1EA8,
+0x84000FB8,0x78000C98,0x6C001198,0x62001EA8,0xFEA00EBE,0xF6BC18F4,0xF8C01A44,0xFE70034E,0xF04C000E,0xBC500006,0xA2580046,0x9A480046,0xFE800E11,0xFE500235,0xA438029D,0x840003FD,0x1A41EA8,0xEC0BEB,0xFEC802CA,0xBCC4028A,0x9EC4028A,0xFCA40373,0xC4A00002,0xA0AC0041,0xA4A40373,0x989C00A6,0x88A00375,0x1600BE8,0xD4580289,0x9E8C0288,0xBE380372,0x9C540009,
+0x886C0374,0x35FC0BE8,0x9A0002CA,0x840003E4,0x76000BE8,0x1600BE8,0xD4580289,0x9E8C0288,0xBE380372,0x9C540009,0x886C0374,0x35FC0BE8,0x9A0002CA,0x840003E4,0x76000BE8,0x35FC0BE8,0x9A0002CA,0x840003E4,0x76000BE8,0x76000BE8,0xFEBC0611,0xF8E00975,0xFCE8094E,0xFE800189,0xEA54000D,0xBA540005,0x9E680002,0x9A380021,0xFEA40632,0xFE5C0116,0xA62C0289,0x840003E4,
+0x1F80BE8,0x9C0BEB,0x9C0BEB,0x9C0BEB,0x9C0BEB,0xE8780372,0xE8780372,0xE8780372,0x90780372,0x90780372,0x74780372,0xDA500289,0xDA500289,0xDA500289,0x9A50000A,0x9A50000A,0x785C00A5,0x804C0289,0x804C0289,0x704C0042,0x624C0289,0x2E80BE8,0x2E80BE8,0x2E80BE8,0xAA0C0372,0xAA0C0372,0x74400372,0x8C0002D9,0x8C0002D9,0x74000005,0x62140288,0x1DC0BE8,
+0x1DC0BE8,0x660004D8,0x5C0004E1,0x4E000BE8,0xFE840522,0xF49808F6,0x9C0BEB,0xFE680122,0xE6500006,0xB8500005,0xA8540022,0x904C0001,0xFE6404B5,0xFE4400B9,0x9E3C0289,0x74000005,0x1500BE8,0xC4028A,0xC4028A,0xC4028A,0xC4028A,0xBCA40001,0xBCA40001,0xBCA40001,0x86A00001,0x86A00001,0x74A00001,0x3240288,0x3240288,0x3240288,0x94600001,0x94600001,
+0x74800000,0x17FC0288,0x17FC0288,0x740C0000,0x62000288,0x3240288,0x3240288,0x3240288,0x94600001,0x94600001,0x74800000,0x17FC0288,0x17FC0288,0x740C0000,0x62000288,0x17FC0288,0x17FC0288,0x740C0000,0x62000288,0x62000288,0xFEA000F4,0xF6BC0152,0xC4028A,0xFE78003D,0xD8600001,0xB25C0000,0xA0680000,0x904C0000,0xF8880120,0xFC580029,0x1A40288,0x740C0000,
+0x1A40288,0x1140372,0xF2EC0001,0xB2EC0001,0x9EE80001,0x3980372,0xC49C0001,0x9EC00000,0x51FC0372,0x9E3C0000,0x88000374,0x3980372,0xC49C0001,0x9EC00000,0x51FC0372,0x9E3C0000,0x88000374,0x51FC0372,0x9E3C0000,0x88000374,0x88000374,0x3980372,0xC49C0001,0x9EC00000,0x51FC0372,0x9E3C0000,0x88000374,0x51FC0372,0x9E3C0000,0x88000374,0x88000374,0x51FC0372,
+0x9E3C0000,0x88000374,0x88000374,0x88000374,0xF6E80221,0xB240372,0xFF0C0242,0xFE9C0091,0xF43C0001,0xBE440000,0x9E700000,0x9E000000,0xF8D00200,0xFA7C0071,0xA47C0000,0x88000374,0x23FC0372,0x780372,0x780372,0x780372,0x780372,0x780372,0x780372,0x780372,0x780372,0x780372,0x780372,0xA4500001,0xA4500001,0xA4500001,0xA4500001,0xA4500001,
+0xA4500001,0x64500001,0x64500001,0x64500001,0x504C0001,0x2B00372,0x2B00372,0x2B00372,0x2B00372,0x2B00372,0x2B00372,0x76000001,0x76000001,0x76000001,0x50240000,0x1680372,0x1680372,0x1680372,0x4A00009D,0x3A000374,0xFE6C01A5,0x780372,0x780372,0xFE58004A,0xF0500001,0xC0500001,0xC0500001,0x8C500001,0xF84C0139,0xFE3C0032,0x78440001,0x76000001,
+0xFC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table141[] = {
+0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x8C0000,0x1180000,
+0x1180000,0x1180000,0x1180000,0x2E000000,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x640000,0x640000,0x640000,0x8C0000,0xC80000,0xB00001,0xB00001,0xB00001,0xB00001,0xB00001,0xB00001,0xB00001,0xB00001,0xB00001,0xB00001,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,
+0x1080000,0x9F80000,0x9F80000,0x9F80000,0x58000000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x9F80000,0x9F80000,0x9F80000,0x58000000,0x9F80000,0x9F80000,0x9F80000,0x58000000,0x58000000,0x6BC0000,0xB00001,0xB00001,0x6CC0000,0xE00000,0x2F00000,0x2F00000,0x12C0000,0x6CC0000,0xE00000,0x1780000,0x9F80000,
+0x1780000,0xF80001,0xF80001,0xF80001,0xF80001,0x1740000,0x1740000,0x1740000,0x3FF80000,0x3FF80000,0x7C000000,0x1740000,0x1740000,0x1740000,0x3FF80000,0x3FF80000,0x7C000000,0x3FF80000,0x3FF80000,0x7C000000,0x7C000000,0x1740000,0x1740000,0x1740000,0x3FF80000,0x3FF80000,0x7C000000,0x3FF80000,0x3FF80000,0x7C000000,0x7C000000,0x3FF80000,
+0x3FF80000,0x7C000000,0x7C000000,0x7C000000,0x7200000,0xD080000,0xF80001,0x1540000,0x1A40000,0xBFC0000,0x25FC0000,0x4FF80000,0x1380000,0x1740000,0xBFC0000,0x7C000000,0xBFC0000,0x14C0001,0x1F00000,0x7DF80000,0xA6000000,0x1F00000,0x7DF80000,0xA6000000,0x7DF80000,0xA6000000,0xA6000000,0x1F00000,0x7DF80000,0xA6000000,0x7DF80000,0xA6000000,
+0xA6000000,0x7DF80000,0xA6000000,0xA6000000,0xA6000000,0x1F00000,0x7DF80000,0xA6000000,0x7DF80000,0xA6000000,0xA6000000,0x7DF80000,0xA6000000,0xA6000000,0xA6000000,0x7DF80000,0xA6000000,0xA6000000,0xA6000000,0xA6000000,0x5A00000,0x1640000,0x1640000,0x27FC0000,0x6BFC0000,0x91F80000,0xA6000000,0xA6000000,0x3C40000,0x45FC0000,0xA1F40000,0xA6000000,
+0x5BFC0000,0xD41EAC,0xFEBC0E0B,0xCCB00BEB,0xA6AC0BEB,0xFE980856,0xDC8C03A3,0xAA940533,0xB68806E6,0xA28403AE,0x908806E6,0xFE740C91,0xE260028A,0xAE780413,0xC05C038E,0xA65C000E,0x926403AE,0xA4600BE9,0x9A500411,0x8A540531,0x7E5C0BE9,0x33C1EA8,0xF0180BE9,0xA6600BE8,0xD80006F6,0xA82C038E,0x903C06E6,0xBA000CAF,0xA20002CE,0x8E0003B5,0x7E100BE8,0x23FC1EA8,
+0x90000EF8,0x84000BA8,0x780010D8,0x6A001EA8,0xFEB40F7B,0xFECC18F4,0xFECC1A5C,0xFE8003FA,0xF85C000E,0xC4600006,0xAA680046,0xA2580046,0xFE900EA5,0xFE6002FA,0xAC48029D,0x8E0003B5,0x1C81EA8,0xFC0BEB,0xFEDC02EB,0xC4D4028A,0xA6D4028A,0xFEB4037B,0xCCB00002,0xA8BC0041,0xACB40373,0xA0AC00A6,0x90B00375,0x1780BE8,0xDC680289,0xA69C0288,0xC6480372,0xA4640009,
+0x907C0374,0x41FC0BE8,0xA20002AA,0x900003B4,0x7E000BE8,0x1780BE8,0xDC680289,0xA69C0288,0xC6480372,0xA4640009,0x907C0374,0x41FC0BE8,0xA20002AA,0x900003B4,0x7E000BE8,0x41FC0BE8,0xA20002AA,0x900003B4,0x7E000BE8,0x7E000BE8,0xFED00640,0xFEEC098D,0xF4F80993,0xFE9801D5,0xF264000D,0xC2640005,0xA6780002,0xA2480021,0xFEB40682,0xFC80016E,0xAE3C0289,0x900003B4,
+0xFFC0BE8,0xAC0BEB,0xAC0BEB,0xAC0BEB,0xAC0BEB,0xF0880372,0xF0880372,0xF0880372,0x98880372,0x98880372,0x7C880372,0xE2600289,0xE2600289,0xE2600289,0xA260000A,0xA260000A,0x806C00A5,0x885C0289,0x885C0289,0x785C0042,0x6A5C0289,0x3000BE8,0x3000BE8,0x3000BE8,0xB21C0372,0xB21C0372,0x7C500372,0x9E0002A1,0x9E0002A1,0x7C100005,0x6A240288,0x5FC0BE8,
+0x5FC0BE8,0x72000478,0x64000489,0x56000BE8,0xFE90056E,0xFCA808F6,0xAC0BEB,0xFE780156,0xEE600006,0xC0600005,0xB0640022,0x985C0001,0xFE7804E6,0xFE5C00F5,0xA64C0289,0x7C100005,0x1700BE8,0xD4028A,0xD4028A,0xD4028A,0xD4028A,0xC4B40001,0xC4B40001,0xC4B40001,0x8EB00001,0x8EB00001,0x7CB00001,0x33C0288,0x33C0288,0x33C0288,0x9C700001,0x9C700001,
+0x7C900000,0x23FC0288,0x23FC0288,0x7C1C0000,0x6A000288,0x33C0288,0x33C0288,0x33C0288,0x9C700001,0x9C700001,0x7C900000,0x23FC0288,0x23FC0288,0x7C1C0000,0x6A000288,0x23FC0288,0x23FC0288,0x7C1C0000,0x6A000288,0x6A000288,0xFAB40109,0xFECC0152,0xD4028A,0xFE88004A,0xE0700001,0xBA6C0000,0xA8780000,0x985C0000,0xFE940128,0xFE680034,0x1C80288,0x7C1C0000,
+0x1C80288,0x1240372,0xFAFC0001,0xBAFC0001,0xA6F80001,0x3B00372,0xCCAC0001,0xA6D00000,0x5DFC0372,0xA64C0000,0x90000374,0x3B00372,0xCCAC0001,0xA6D00000,0x5DFC0372,0xA64C0000,0x90000374,0x5DFC0372,0xA64C0000,0x90000374,0x90000374,0x3B00372,0xCCAC0001,0xA6D00000,0x5DFC0372,0xA64C0000,0x90000374,0x5DFC0372,0xA64C0000,0x90000374,0x90000374,0x5DFC0372,
+0xA64C0000,0x90000374,0x90000374,0x90000374,0xFEF80221,0x1380372,0xF71C0265,0xFEB000AA,0xFC4C0001,0xC6540000,0xA6800000,0xA6100000,0xFEDC0208,0xFE940080,0xAC8C0000,0x90000374,0x33FC0372,0x880372,0x880372,0x880372,0x880372,0x880372,0x880372,0x880372,0x880372,0x880372,0x880372,0xAC600001,0xAC600001,0xAC600001,0xAC600001,0xAC600001,
+0xAC600001,0x6C600001,0x6C600001,0x6C600001,0x585C0001,0xC80372,0xC80372,0xC80372,0xC80372,0xC80372,0xC80372,0x7E100001,0x7E100001,0x7E100001,0x58340000,0x1980372,0x1980372,0x1980372,0x50000071,0x42000374,0xF67C01C2,0x880372,0x880372,0xFE680059,0xF8600001,0xC8600001,0xC8600001,0x94600001,0xFE580145,0xFE50003D,0x80540001,0x7E100001,
+0x1200372,};
+static const uint32_t g_etc1_to_bc7_m6_table142[] = {
+0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0x14C0000,
+0x14C0000,0x14C0000,0x14C0000,0x36000000,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0x2740000,0x2740000,0x2740000,0xA40000,0xE80000,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0xC00001,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,
+0x1200000,0x15F80000,0x15F80000,0x15F80000,0x60000000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x1200000,0x15F80000,0x15F80000,0x15F80000,0x60000000,0x15F80000,0x15F80000,0x15F80000,0x60000000,0x60000000,0xECC0000,0xC00001,0xC00001,0x2E00000,0xF40000,0x1080000,0x1080000,0x1440000,0x2E00000,0xF40000,0x19C0000,0x15F80000,
+0x19C0000,0x1080001,0x1080001,0x1080001,0x1080001,0x18C0000,0x18C0000,0x18C0000,0x4BF80000,0x4BF80000,0x84000000,0x18C0000,0x18C0000,0x18C0000,0x4BF80000,0x4BF80000,0x84000000,0x4BF80000,0x4BF80000,0x84000000,0x84000000,0x18C0000,0x18C0000,0x18C0000,0x4BF80000,0x4BF80000,0x84000000,0x4BF80000,0x4BF80000,0x84000000,0x84000000,0x4BF80000,
+0x4BF80000,0x84000000,0x84000000,0x84000000,0x3340000,0x11C0000,0x1080001,0x3680000,0x1C00000,0x1BFC0000,0x33F80000,0x59FC0000,0x34C0000,0x18C0000,0x1BFC0000,0x84000000,0x1BFC0000,0x15C0001,0xDFC0000,0x89F80000,0xAE000000,0xDFC0000,0x89F80000,0xAE000000,0x89F80000,0xAE000000,0xAE000000,0xDFC0000,0x89F80000,0xAE000000,0x89F80000,0xAE000000,
+0xAE000000,0x89F80000,0xAE000000,0xAE000000,0xAE000000,0xDFC0000,0x89F80000,0xAE000000,0x89F80000,0xAE000000,0xAE000000,0x89F80000,0xAE000000,0xAE000000,0xAE000000,0x89F80000,0xAE000000,0xAE000000,0xAE000000,0xAE000000,0x5B40000,0x3740000,0x3740000,0x3BFC0000,0x79FC0000,0x9BF80000,0xAE000000,0xAE000000,0x1DC0000,0x55FC0000,0xABC80000,0xAE000000,
+0x69FC0000,0xE41EAC,0xFEC80E73,0xD4C00BEB,0xAEBC0BEB,0xFEA808EC,0xE49C03A3,0xB2A40533,0xBE9806E6,0xAA9403AE,0x989806E6,0xFE840CF4,0xEA70028A,0xB6880413,0xC86C038E,0xAE6C000E,0x9A7403AE,0xAC700BE9,0xA2600411,0x92640531,0x866C0BE9,0x1541EA8,0xF8280BE9,0xAE700BE8,0xE20406E6,0xB03C038E,0x984C06E6,0xC6000C4F,0xAC000292,0x980403A1,0x86200BE8,0x2FFC1EA8,
+0x9C000E58,0x8A000AE8,0x7E00102C,0x72001EA8,0xFEBC1022,0xF6DC197E,0xF8E01AAF,0xFE9804BE,0xFA70000F,0xCC700006,0xB2780046,0xAA680046,0xFEA40F96,0xFE7403B7,0xB458029D,0x980403A1,0x1E81EA8,0x10C0BEB,0xFEEC032A,0xCCE4028A,0xAEE4028A,0xFEC8038D,0xD4C00002,0xB0CC0041,0xB4C40373,0xA8BC00A6,0x98C00375,0x1900BE8,0xE4780289,0xAEAC0288,0xCE580372,0xAC740009,
+0x988C0374,0x4DFC0BE8,0xAC00028E,0x96000394,0x86000BE8,0x1900BE8,0xE4780289,0xAEAC0288,0xCE580372,0xAC740009,0x988C0374,0x4DFC0BE8,0xAC00028E,0x96000394,0x86000BE8,0x4DFC0BE8,0xAC00028E,0x96000394,0x86000BE8,0x86000BE8,0xFEE406A5,0xFB0409B3,0xFD080993,0xFEB0022E,0xFA74000D,0xCA740005,0xAE880002,0xAA580021,0xFAD406D1,0xFE9001B2,0xB64C0289,0x96000394,
+0x1FF80BE8,0xBC0BEB,0xBC0BEB,0xBC0BEB,0xBC0BEB,0xF8980372,0xF8980372,0xF8980372,0xA0980372,0xA0980372,0x84980372,0xEA700289,0xEA700289,0xEA700289,0xAA70000A,0xAA70000A,0x887C00A5,0x906C0289,0x906C0289,0x806C0042,0x726C0289,0x3180BE8,0x3180BE8,0x3180BE8,0xBA2C0372,0xBA2C0372,0x84600372,0xAA000289,0xAA000289,0x84200005,0x72340288,0x11FC0BE8,
+0x11FC0BE8,0x7C000432,0x6C000414,0x5E000BE8,0xFEA005A5,0xF4B80933,0xBC0BEB,0xFE880193,0xF6700006,0xC8700005,0xB8740022,0xA06C0001,0xFC8C0549,0xFE680138,0xAE5C0289,0x84200005,0x1940BE8,0xE4028A,0xE4028A,0xE4028A,0xE4028A,0xCCC40001,0xCCC40001,0xCCC40001,0x96C00001,0x96C00001,0x84C00001,0x1540288,0x1540288,0x1540288,0xA4800001,0xA4800001,
+0x84A00000,0x2FFC0288,0x2FFC0288,0x842C0000,0x72000288,0x1540288,0x1540288,0x1540288,0xA4800001,0xA4800001,0x84A00000,0x2FFC0288,0x2FFC0288,0x842C0000,0x72000288,0x2FFC0288,0x2FFC0288,0x842C0000,0x72000288,0x72000288,0xF6C80120,0xF6DC016D,0xE4028A,0xFE980061,0xE8800001,0xC27C0000,0xB0880000,0xA06C0000,0xFAAC0139,0xFE800048,0x1E80288,0x842C0000,
+0x1E80288,0x1340372,0xFF0C0002,0xC30C0001,0xAF080001,0x1C80372,0xD4BC0001,0xAEE00000,0x69FC0372,0xAE5C0000,0x98000374,0x1C80372,0xD4BC0001,0xAEE00000,0x69FC0372,0xAE5C0000,0x98000374,0x69FC0372,0xAE5C0000,0x98000374,0x98000374,0x1C80372,0xD4BC0001,0xAEE00000,0x69FC0372,0xAE5C0000,0x98000374,0x69FC0372,0xAE5C0000,0x98000374,0x98000374,0x69FC0372,
+0xAE5C0000,0x98000374,0x98000374,0x98000374,0xFB0C0242,0x1480372,0xFF2C0265,0xFEC800D0,0xFE680005,0xCE640000,0xAE900000,0xAE200000,0xFEF0022D,0xFEAC00A4,0xB49C0000,0x98000374,0x41FC0372,0x980372,0x980372,0x980372,0x980372,0x980372,0x980372,0x980372,0x980372,0x980372,0x980372,0xB4700001,0xB4700001,0xB4700001,0xB4700001,0xB4700001,
+0xB4700001,0x74700001,0x74700001,0x74700001,0x606C0001,0xE00372,0xE00372,0xE00372,0xE00372,0xE00372,0xE00372,0x86200001,0x86200001,0x86200001,0x60440000,0x1CC0372,0x1CC0372,0x1CC0372,0x5C000041,0x4A000374,0xFE8C01C2,0x980372,0x980372,0xFA7C0071,0xFA700002,0xD0700001,0xD0700001,0x9C700001,0xFC700152,0xFC600055,0x88640001,0x86200001,
+0x1400372,};
+static const uint32_t g_etc1_to_bc7_m6_table143[] = {
+0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0xBC0000,0x17C0000,
+0x17C0000,0x17C0000,0x17C0000,0x3E000000,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0xA840000,0xA840000,0xA840000,0xBC0000,0x10C0000,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,
+0x1380000,0x21F80000,0x21F80000,0x21F80000,0x68000000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x21F80000,0x21F80000,0x21F80000,0x68000000,0x21F80000,0x21F80000,0x21F80000,0x68000000,0x68000000,0xE00000,0xD00001,0xD00001,0xF40000,0x1080000,0x11C0000,0x11C0000,0x1600000,0xF40000,0x1080000,0x1BC0000,0x21F80000,
+0x1BC0000,0x1180001,0x1180001,0x1180001,0x1180001,0x1A40000,0x1A40000,0x1A40000,0x57F80000,0x57F80000,0x8C000000,0x1A40000,0x1A40000,0x1A40000,0x57F80000,0x57F80000,0x8C000000,0x57F80000,0x57F80000,0x8C000000,0x8C000000,0x1A40000,0x1A40000,0x1A40000,0x57F80000,0x57F80000,0x8C000000,0x57F80000,0x57F80000,0x8C000000,0x8C000000,0x57F80000,
+0x57F80000,0x8C000000,0x8C000000,0x8C000000,0x1480000,0x12C0000,0x1180001,0x1800000,0x1D80000,0x29FC0000,0x3FFC0000,0x65F40000,0x3600000,0x1A40000,0x29FC0000,0x8C000000,0x29FC0000,0x16C0001,0x25FC0000,0x95F80000,0xB6000000,0x25FC0000,0x95F80000,0xB6000000,0x95F80000,0xB6000000,0xB6000000,0x25FC0000,0x95F80000,0xB6000000,0x95F80000,0xB6000000,
+0xB6000000,0x95F80000,0xB6000000,0xB6000000,0xB6000000,0x25FC0000,0x95F80000,0xB6000000,0x95F80000,0xB6000000,0xB6000000,0x95F80000,0xB6000000,0xB6000000,0xB6000000,0x95F80000,0xB6000000,0xB6000000,0xB6000000,0xB6000000,0x1CC0000,0xB840000,0xB840000,0x4FFC0000,0x87F80000,0xA5F80000,0xB6000000,0xB6000000,0x3F00000,0x67FC0000,0xB3D80000,0xB6000000,
+0x79FC0000,0xF41EAC,0xFEDC0EEC,0xDCD00BEB,0xB6CC0BEB,0xFEBC096E,0xECAC03A3,0xBAB40533,0xC6A806E6,0xB2A403AE,0xA0A806E6,0xFE980D51,0xF280028A,0xBE980413,0xD07C038E,0xB67C000E,0xA28403AE,0xB4800BE9,0xAA700411,0x9A740531,0x8E7C0BE9,0x16C1EA8,0xFE380BEF,0xB6800BE8,0xEA1406E6,0xB84C038E,0xA05C06E6,0xD2000C0F,0xB608028A,0xA01403A1,0x8E300BE8,0x3BFC1EA8,
+0xA6000DDB,0x96000A18,0x8A000F9C,0x7A001EA8,0xFED010D1,0xFEEC197E,0xFEEC1ACB,0xFEAC059E,0xFE840027,0xD4800006,0xBA880046,0xB2780046,0xFEB4101B,0xFE900462,0xBC68029D,0xA01403A1,0x7FC1EA8,0x11C0BEB,0xFF000363,0xD4F4028A,0xB6F4028A,0xFEDC03AB,0xDCD00002,0xB8DC0041,0xBCD40373,0xB0CC00A6,0xA0D00375,0x1A80BE8,0xEC880289,0xB6BC0288,0xD6680372,0xB4840009,
+0xA09C0374,0x59FC0BE8,0xB6000288,0xA000037D,0x8E000BE8,0x1A80BE8,0xEC880289,0xB6BC0288,0xD6680372,0xB4840009,0xA09C0374,0x59FC0BE8,0xB6000288,0xA000037D,0x8E000BE8,0x59FC0BE8,0xB6000288,0xA000037D,0x8E000BE8,0x8E000BE8,0xFEF806DA,0xFF0C09DB,0xF51809DA,0xFEC00296,0xFE88001A,0xD2840005,0xB6980002,0xB2680021,0xFEDC06F9,0xFEA40224,0xBE5C0289,0xA000037D,
+0x2DFC0BE8,0xCC0BEB,0xCC0BEB,0xCC0BEB,0xCC0BEB,0xFEA80373,0xFEA80373,0xFEA80373,0xA8A80372,0xA8A80372,0x8CA80372,0xF2800289,0xF2800289,0xF2800289,0xB280000A,0xB280000A,0x908C00A5,0x987C0289,0x987C0289,0x887C0042,0x7A7C0289,0x3300BE8,0x3300BE8,0x3300BE8,0xC23C0372,0xC23C0372,0x8C700372,0xB2100289,0xB2100289,0x8C300005,0x7A440288,0x1DFC0BE8,
+0x1DFC0BE8,0x840003E4,0x760003C9,0x66000BE8,0xFCB805F6,0xFCC80933,0xCC0BEB,0xFE9801DA,0xFE800006,0xD0800005,0xC0840022,0xA87C0001,0xFC9C0581,0xFE800171,0xB66C0289,0x8C300005,0x1B40BE8,0xF4028A,0xF4028A,0xF4028A,0xF4028A,0xD4D40001,0xD4D40001,0xD4D40001,0x9ED00001,0x9ED00001,0x8CD00001,0x16C0288,0x16C0288,0x16C0288,0xAC900001,0xAC900001,
+0x8CB00000,0x3BFC0288,0x3BFC0288,0x8C3C0000,0x7A000288,0x16C0288,0x16C0288,0x16C0288,0xAC900001,0xAC900001,0x8CB00000,0x3BFC0288,0x3BFC0288,0x8C3C0000,0x7A000288,0x3BFC0288,0x3BFC0288,0x8C3C0000,0x7A000288,0x7A000288,0xFED80120,0xFEEC016D,0xF4028A,0xFEB40071,0xF0900001,0xCA8C0000,0xB8980000,0xA87C0000,0xFCC00152,0xFE980055,0x7FC0288,0x8C3C0000,
+0x7FC0288,0x1440372,0xFF1C0011,0xCB1C0001,0xB7180001,0x1E00372,0xDCCC0001,0xB6F00000,0x75FC0372,0xB66C0000,0xA0000374,0x1E00372,0xDCCC0001,0xB6F00000,0x75FC0372,0xB66C0000,0xA0000374,0x75FC0372,0xB66C0000,0xA0000374,0xA0000374,0x1E00372,0xDCCC0001,0xB6F00000,0x75FC0372,0xB66C0000,0xA0000374,0x75FC0372,0xB66C0000,0xA0000374,0xA0000374,0x75FC0372,
+0xB66C0000,0xA0000374,0xA0000374,0xA0000374,0xFF140262,0x5580372,0xF73C028A,0xFCE800F2,0xFC8C0019,0xD6740000,0xB6A00000,0xB6300000,0xFD0C0242,0xFEC000C1,0xBCAC0000,0xA0000374,0x51FC0372,0xA80372,0xA80372,0xA80372,0xA80372,0xA80372,0xA80372,0xA80372,0xA80372,0xA80372,0xA80372,0xBC800001,0xBC800001,0xBC800001,0xBC800001,0xBC800001,
+0xBC800001,0x7C800001,0x7C800001,0x7C800001,0x687C0001,0xF80372,0xF80372,0xF80372,0xF80372,0xF80372,0xF80372,0x8E300001,0x8E300001,0x8E300001,0x68540000,0x1FC0372,0x1FC0372,0x1FC0372,0x66000028,0x52000374,0xF69C01E1,0xA80372,0xA80372,0xFC8C0082,0xFE800005,0xD8800001,0xD8800001,0xA4800001,0xF884016D,0xFC740062,0x90740001,0x8E300001,
+0x1640372,};
+static const uint32_t g_etc1_to_bc7_m6_table144[] = {
+0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0x1B00000,
+0x1B00000,0x1B00000,0x1B00000,0x46000001,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x4980000,0x4980000,0x4980000,0xD40000,0x1300000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0xE40000,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,
+0x3500000,0x2DFC0000,0x2DFC0000,0x2DFC0000,0x70000001,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,0x3500000,0x2DFC0000,0x2DFC0000,0x2DFC0000,0x70000001,0x2DFC0000,0x2DFC0000,0x2DFC0000,0x70000001,0x70000001,0xF40000,0xE40000,0xE40000,0x1080000,0x31C0000,0x3340000,0x3340000,0x1800000,0x1080000,0x31C0000,0x1E40000,0x2DFC0000,
+0x1E40000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x3BC0000,0x3BC0000,0x3BC0000,0x63FC0000,0x63FC0000,0x94000001,0x3BC0000,0x3BC0000,0x3BC0000,0x63FC0000,0x63FC0000,0x94000001,0x63FC0000,0x63FC0000,0x94000001,0x94000001,0x3BC0000,0x3BC0000,0x3BC0000,0x63FC0000,0x63FC0000,0x94000001,0x63FC0000,0x63FC0000,0x94000001,0x94000001,0x63FC0000,
+0x63FC0000,0x94000001,0x94000001,0x94000001,0x15C0000,0x1400000,0x12C0000,0x1980000,0x1F80000,0x3BFC0000,0x4FFC0000,0x71F80000,0x1780000,0x3BC0000,0x3BFC0000,0x94000001,0x3BFC0000,0x1800000,0x41FC0000,0xA1FC0000,0xBE000001,0x41FC0000,0xA1FC0000,0xBE000001,0xA1FC0000,0xBE000001,0xBE000001,0x41FC0000,0xA1FC0000,0xBE000001,0xA1FC0000,0xBE000001,
+0xBE000001,0xA1FC0000,0xBE000001,0xBE000001,0xBE000001,0x41FC0000,0xA1FC0000,0xBE000001,0xA1FC0000,0xBE000001,0xBE000001,0xA1FC0000,0xBE000001,0xBE000001,0xBE000001,0xA1FC0000,0xBE000001,0xBE000001,0xBE000001,0xBE000001,0x3E00000,0x5980000,0x5980000,0x65FC0000,0x95FC0000,0xB1F40000,0xBE000001,0xBE000001,0x13FC0000,0x79FC0000,0xBDCC0000,0xBE000001,
+0x89FC0000,0x1081EA8,0xFEE80F9C,0xE6E00BE8,0xBEE00BE9,0xFED00A18,0xF4BC03A1,0xC4C80531,0xD0B806E6,0xBCB803AE,0xAAB806E6,0xFEB00DDB,0xFA90028A,0xC6A80411,0xD88C038E,0xBE90000E,0xAC9803AE,0xBE900BE8,0xB2800413,0xA4880533,0x96900BEB,0x1881EA8,0xFE580C0F,0xBE940BE9,0xF22806E6,0xC05C038E,0xAA6C06E6,0xE0000BEF,0xBE18028A,0xA82403A3,0x96440BEB,0x49F81EA8,
+0xB2000D51,0xA000096E,0x90000EEC,0x82001EAC,0xFEE41196,0xF9001A08,0xFB041B18,0xFEC006A1,0xFE9C0075,0xDC900006,0xC2980046,0xBA880046,0xFED410EA,0xFEA40584,0xC47C029D,0xA82403A3,0x19FC1EA8,0x1300BE8,0xFF1003C9,0xDD080288,0xBF080289,0xFEF403E4,0xE2E40005,0xC0EC0042,0xC6E40372,0xB8DC00A5,0xAAE40372,0x1C40BE8,0xF6980289,0xC0CC0289,0xE0780372,0xBE98000A,
+0xAAAC0372,0x67F80BE8,0xBE140289,0xAA000373,0x96000BEB,0x1C40BE8,0xF6980289,0xC0CC0289,0xE0780372,0xBE98000A,0xAAAC0372,0x67F80BE8,0xBE140289,0xAA000373,0x96000BEB,0x67F80BE8,0xBE140289,0xAA000373,0x96000BEB,0x96000BEB,0xFD10074D,0xFD2809F6,0xFF2C09D9,0xFEDC0312,0xFEA4003E,0xDA940006,0xC0AC0001,0xBC740022,0xFEF80752,0xFEC00281,0xC86C0288,0xAA000373,
+0x3FF80BE8,0xE00BE8,0xE00BE8,0xE00BE8,0xE00BE8,0xFEBC037D,0xFEBC037D,0xFEBC037D,0xB0BC0374,0xB0BC0374,0x94B80375,0xFE900288,0xFE900288,0xFE900288,0xBC940009,0xBC940009,0x989C00A6,0xA0900288,0xA0900288,0x908C0041,0x8290028A,0x14C0BE8,0x14C0BE8,0x14C0BE8,0xCA500372,0xCA500372,0x94840373,0xBA240289,0xBA240289,0x96440002,0x8454028A,0x2BF80BE8,
+0x2BF80BE8,0x900003AB,0x7E000363,0x6E000BEB,0xFECC062C,0xF4D80975,0xE00BE8,0xFEAC023D,0xFE940011,0xDC900005,0xCA980021,0xB0900002,0xFEB405B5,0xFE9801C6,0xBE80028A,0x96440002,0x1DC0BE8,0x1080288,0x1080288,0x1080288,0x1080288,0xDEE40000,0xDEE40000,0xDEE40000,0xA6E40000,0xA6E40000,0x94E40001,0x1880288,0x1880288,0x1880288,0xB4A40001,0xB4A40001,
+0x96C00001,0x49F80288,0x49F80288,0x94540001,0x8200028A,0x1880288,0x1880288,0x1880288,0xB4A40001,0xB4A40001,0x96C00001,0x49F80288,0x49F80288,0x94540001,0x8200028A,0x49F80288,0x49F80288,0x94540001,0x8200028A,0x8200028A,0xFAEC0139,0xF9000188,0x1080288,0xFEC40088,0xFE9C0000,0xD49C0000,0xC0AC0000,0xB28C0000,0xFED0015A,0xFEB00071,0x19FC0288,0x94540001,
+0x19FC0288,0x1540374,0xFF300028,0xD52C0000,0xBF2C0001,0x1FC0372,0xE4E00001,0xBF040001,0x83F80372,0xBE840001,0xAA000372,0x1FC0372,0xE4E00001,0xBF040001,0x83F80372,0xBE840001,0xAA000372,0x83F80372,0xBE840001,0xAA000372,0xAA000372,0x1FC0372,0xE4E00001,0xBF040001,0x83F80372,0xBE840001,0xAA000372,0x83F80372,0xBE840001,0xAA000372,0xAA000372,0x83F80372,
+0xBE840001,0xAA000372,0xAA000372,0xAA000372,0xFF340265,0x16C0372,0xFF4C0290,0xFF000120,0xFEA8002D,0xDE880000,0xBEB40001,0xBE480001,0xFF180262,0xFEE400F4,0xC6BC0000,0xAA000372,0x61FC0372,0xB80374,0xB80374,0xB80374,0xB80374,0xB80374,0xB80374,0xB80374,0xB80374,0xB80374,0xB80374,0xC6900000,0xC6900000,0xC6900000,0xC6900000,0xC6900000,
+0xC6900000,0x86900000,0x86900000,0x86900000,0x70900001,0x1140372,0x1140372,0x1140372,0x1140372,0x1140372,0x1140372,0x96440001,0x96440001,0x96440001,0x70680001,0xFF80372,0xFF80372,0xFF80372,0x70000011,0x5C000372,0xFEAC01E5,0xB80374,0xB80374,0xFEA00091,0xFE94000D,0xE4900000,0xE4900000,0xAE900000,0xFE900179,0xFC880080,0x9C840000,0x96440001,
+0x18C0372,};
+static const uint32_t g_etc1_to_bc7_m6_table145[] = {
+0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0x1E40000,
+0x1E40000,0x1E40000,0x1E40000,0x4E000001,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xA00000,0xCA80000,0xCA80000,0xCA80000,0xEC0000,0x1540000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0x3680000,0x3680000,0x3680000,0x3680000,0x3680000,
+0x3680000,0x39FC0000,0x39FC0000,0x39FC0000,0x78000001,0x3680000,0x3680000,0x3680000,0x3680000,0x3680000,0x3680000,0x39FC0000,0x39FC0000,0x39FC0000,0x78000001,0x39FC0000,0x39FC0000,0x39FC0000,0x78000001,0x78000001,0x1040000,0xF40000,0xF40000,0x11C0000,0x3300000,0x14C0000,0x14C0000,0x1980000,0x11C0000,0x3300000,0x5FC0000,0x39FC0000,
+0x5FC0000,0x13C0000,0x13C0000,0x13C0000,0x13C0000,0x1D40000,0x1D40000,0x1D40000,0x6FFC0000,0x6FFC0000,0x9C000001,0x1D40000,0x1D40000,0x1D40000,0x6FFC0000,0x6FFC0000,0x9C000001,0x6FFC0000,0x6FFC0000,0x9C000001,0x9C000001,0x1D40000,0x1D40000,0x1D40000,0x6FFC0000,0x6FFC0000,0x9C000001,0x6FFC0000,0x6FFC0000,0x9C000001,0x9C000001,0x6FFC0000,
+0x6FFC0000,0x9C000001,0x9C000001,0x9C000001,0x1700000,0x1500000,0x13C0000,0x3AC0000,0x11FC0000,0x49FC0000,0x5DF80000,0x7BFC0000,0x18C0000,0x1D40000,0x49FC0000,0x9C000001,0x49FC0000,0x1900000,0x59FC0000,0xADFC0000,0xC6000001,0x59FC0000,0xADFC0000,0xC6000001,0xADFC0000,0xC6000001,0xC6000001,0x59FC0000,0xADFC0000,0xC6000001,0xADFC0000,0xC6000001,
+0xC6000001,0xADFC0000,0xC6000001,0xC6000001,0xC6000001,0x59FC0000,0xADFC0000,0xC6000001,0xADFC0000,0xC6000001,0xC6000001,0xADFC0000,0xC6000001,0xC6000001,0xC6000001,0xADFC0000,0xC6000001,0xC6000001,0xC6000001,0xC6000001,0x3F40000,0xDA80000,0xDA80000,0x79FC0000,0xA3FC0000,0xBBF40000,0xC6000001,0xC6000001,0x31FC0000,0x8BFC0000,0xC5DC0000,0xC6000001,
+0x99FC0000,0x1181EA8,0xFF00102C,0xEEF00BE8,0xC6F00BE9,0xFEE80AE8,0xFCCC03A1,0xCCD80531,0xD8C806E6,0xC4C803AE,0xB2C806E6,0xFEC40E58,0xFEA40292,0xCEB80411,0xE09C038E,0xC6A0000E,0xB4A803AE,0xC6A00BE8,0xBA900413,0xAC980533,0x9EA00BEB,0x1A01EA8,0xFE700C4F,0xC6A40BE9,0xFA3806E6,0xC86C038E,0xB27C06E6,0xEA0C0BE9,0xC628028A,0xB03403A3,0x9E540BEB,0x55F81EA8,
+0xBC000CF4,0xAA0008EC,0x9A000E73,0x8A001EAC,0xFEF81255,0xFF0C1A18,0xFF0C1B58,0xFED4078E,0xFEB000ED,0xE4A00006,0xCAA80046,0xC2980046,0xFEDC11C3,0xFEC00675,0xCC8C029D,0xB03403A3,0x27FC1EA8,0x1400BE8,0xFF240414,0xE5180288,0xC7180289,0xFF040432,0xEAF40005,0xC8FC0042,0xCEF40372,0xC0EC00A5,0xB2F40372,0x1DC0BE8,0xFEA80289,0xC8DC0289,0xE8880372,0xC6A8000A,
+0xB2BC0372,0x73F80BE8,0xC6240289,0xB2080372,0x9E000BEB,0x1DC0BE8,0xFEA80289,0xC8DC0289,0xE8880372,0xC6A8000A,0xB2BC0372,0x73F80BE8,0xC6240289,0xB2080372,0x9E000BEB,0x73F80BE8,0xC6240289,0xB2080372,0x9E000BEB,0x9E000BEB,0xFF20078E,0xF5380A38,0xF73C0A20,0xFEEC0395,0xFEBC007E,0xE2A40006,0xC8BC0001,0xC4840022,0xFF0807A3,0xFEDC0305,0xD07C0288,0xB2080372,
+0x4DFC0BE8,0xF00BE8,0xF00BE8,0xF00BE8,0xF00BE8,0xFED00394,0xFED00394,0xFED00394,0xB8CC0374,0xB8CC0374,0x9CC80375,0xFEA4028E,0xFEA4028E,0xFEA4028E,0xC4A40009,0xC4A40009,0xA0AC00A6,0xA8A00288,0xA8A00288,0x989C0041,0x8AA0028A,0x1640BE8,0x1640BE8,0x1640BE8,0xD2600372,0xD2600372,0x9C940373,0xC2340289,0xC2340289,0x9E540002,0x8C64028A,0x37F80BE8,
+0x37F80BE8,0x9A00038D,0x8800032A,0x76000BEB,0xFED80672,0xFCE80975,0xF00BE8,0xFEC4028C,0xFEAC0031,0xE4A00005,0xD2A80021,0xB8A00002,0xFEBC061A,0xFCAC0225,0xC690028A,0x9E540002,0x1FC0BE8,0x1180288,0x1180288,0x1180288,0x1180288,0xE6F40000,0xE6F40000,0xE6F40000,0xAEF40000,0xAEF40000,0x9CF40001,0x1A00288,0x1A00288,0x1A00288,0xBCB40001,0xBCB40001,
+0x9ED00001,0x55F80288,0x55F80288,0x9C640001,0x8A00028A,0x1A00288,0x1A00288,0x1A00288,0xBCB40001,0xBCB40001,0x9ED00001,0x55F80288,0x55F80288,0x9C640001,0x8A00028A,0x55F80288,0x55F80288,0x9C640001,0x8A00028A,0x8A00028A,0xF7000152,0xFF0C0190,0x1180288,0xFEDC0091,0xFEB00004,0xDCAC0000,0xC8BC0000,0xBA9C0000,0xF8EC016D,0xFEC40080,0x27FC0288,0x9C640001,
+0x27FC0288,0x1640374,0xFF440041,0xDD3C0000,0xC73C0001,0x19FC0372,0xECF00001,0xC7140001,0x8FF80372,0xC6940001,0xB2000372,0x19FC0372,0xECF00001,0xC7140001,0x8FF80372,0xC6940001,0xB2000372,0x8FF80372,0xC6940001,0xB2000372,0xB2000372,0x19FC0372,0xECF00001,0xC7140001,0x8FF80372,0xC6940001,0xB2000372,0x8FF80372,0xC6940001,0xB2000372,0xB2000372,0x8FF80372,
+0xC6940001,0xB2000372,0xB2000372,0xB2000372,0xFB480288,0x77C0372,0xF96002AD,0xFF14013D,0xFECC0055,0xE6980000,0xC6C40001,0xC6580001,0xF1400288,0xFD040120,0xCECC0000,0xB2000372,0x71FC0372,0xC80374,0xC80374,0xC80374,0xC80374,0xC80374,0xC80374,0xC80374,0xC80374,0xC80374,0xC80374,0xCEA00000,0xCEA00000,0xCEA00000,0xCEA00000,0xCEA00000,
+0xCEA00000,0x8EA00000,0x8EA00000,0x8EA00000,0x78A00001,0x12C0372,0x12C0372,0x12C0372,0x12C0372,0x12C0372,0x12C0372,0x9E540001,0x9E540001,0x9E540001,0x78780001,0x1BF80372,0x1BF80372,0x1BF80372,0x78000002,0x64000372,0xF8C00200,0xC80374,0xC80374,0xFEAC00B4,0xFEA80019,0xECA00000,0xECA00000,0xB6A00000,0xFEA0019A,0xFC9C0091,0xA4940000,0x9E540001,
+0x1AC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table146[] = {
+0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x7FC0000,
+0x7FC0000,0x7FC0000,0x7FC0000,0x56000001,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xBC0000,0xBC0000,0xBC0000,0x1040000,0x1740000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x1040000,0x3800000,0x3800000,0x3800000,0x3800000,0x3800000,
+0x3800000,0x45FC0000,0x45FC0000,0x45FC0000,0x80000001,0x3800000,0x3800000,0x3800000,0x3800000,0x3800000,0x3800000,0x45FC0000,0x45FC0000,0x45FC0000,0x80000001,0x45FC0000,0x45FC0000,0x45FC0000,0x80000001,0x80000001,0x3140000,0x1040000,0x1040000,0x52C0000,0x3440000,0x1600000,0x1600000,0x1B40000,0x52C0000,0x3440000,0x15FC0000,0x45FC0000,
+0x15FC0000,0x14C0000,0x14C0000,0x14C0000,0x14C0000,0x1EC0000,0x1EC0000,0x1EC0000,0x7BFC0000,0x7BFC0000,0xA4000001,0x1EC0000,0x1EC0000,0x1EC0000,0x7BFC0000,0x7BFC0000,0xA4000001,0x7BFC0000,0x7BFC0000,0xA4000001,0xA4000001,0x1EC0000,0x1EC0000,0x1EC0000,0x7BFC0000,0x7BFC0000,0xA4000001,0x7BFC0000,0x7BFC0000,0xA4000001,0xA4000001,0x7BFC0000,
+0x7BFC0000,0xA4000001,0xA4000001,0xA4000001,0x5800000,0x9600000,0x14C0000,0x1C40000,0x25FC0000,0x59FC0000,0x69FC0000,0x87F40000,0x1A00000,0x1EC0000,0x59FC0000,0xA4000001,0x59FC0000,0x1A00000,0x71FC0000,0xB9FC0000,0xCE000001,0x71FC0000,0xB9FC0000,0xCE000001,0xB9FC0000,0xCE000001,0xCE000001,0x71FC0000,0xB9FC0000,0xCE000001,0xB9FC0000,0xCE000001,
+0xCE000001,0xB9FC0000,0xCE000001,0xCE000001,0xCE000001,0x71FC0000,0xB9FC0000,0xCE000001,0xB9FC0000,0xCE000001,0xCE000001,0xB9FC0000,0xCE000001,0xCE000001,0xCE000001,0xB9FC0000,0xCE000001,0xCE000001,0xCE000001,0xCE000001,0x1BFC0000,0x1BC0000,0x1BC0000,0x8DFC0000,0xB1FC0000,0xC5F40000,0xCE000001,0xCE000001,0x4FFC0000,0x9BFC0000,0xCDEC0000,0xCE000001,
+0xA7FC0000,0x1281EA8,0xFF0C10D8,0xF7000BE8,0xCF000BE9,0xFEF40BA8,0xFEDC03B5,0xD4E80531,0xE0D806E6,0xCCD803AE,0xBAD806E6,0xFEDC0EF8,0xFEB802CE,0xD6C80411,0xE8AC038E,0xCEB0000E,0xBCB803AE,0xCEB00BE8,0xC2A00413,0xB4A80533,0xA6B00BEB,0x1B81EA8,0xFE880CAF,0xCEB40BE9,0xFE4C06F6,0xD07C038E,0xBA8C06E6,0xF21C0BE9,0xCE38028A,0xB84403A3,0xA6640BEB,0x61F81EA8,
+0xC4000C91,0xB2000856,0xA0000E0B,0x92001EAC,0xFF0C1316,0xF9201A96,0xFB241B85,0xFEEC08C9,0xFEC40195,0xECB00006,0xD2B80046,0xCAA80046,0xFEF81262,0xFED0075B,0xD49C029D,0xB84403A3,0x37FC1EA8,0x1500BE8,0xFF340489,0xED280288,0xCF280289,0xFF180478,0xF3040005,0xD10C0042,0xD7040372,0xC8FC00A5,0xBB040372,0x1F40BE8,0xFEC002A1,0xD0EC0289,0xF0980372,0xCEB8000A,
+0xBACC0372,0x7FF80BE8,0xCE340289,0xBA180372,0xA6000BEB,0x1F40BE8,0xFEC002A1,0xD0EC0289,0xF0980372,0xCEB8000A,0xBACC0372,0x7FF80BE8,0xCE340289,0xBA180372,0xA6000BEB,0x7FF80BE8,0xCE340289,0xBA180372,0xA6000BEB,0xA6000BEB,0xFF3407C9,0xFD480A38,0xFF4C0A20,0xFF08040E,0xFED000DE,0xEAB40006,0xD0CC0001,0xCC940022,0xFF180806,0xFEF00396,0xD88C0288,0xBA180372,
+0x5DF80BE8,0x1000BE8,0x1000BE8,0x1000BE8,0x1000BE8,0xFEDC03B4,0xFEDC03B4,0xFEDC03B4,0xC0DC0374,0xC0DC0374,0xA4D80375,0xFCB802AA,0xFCB802AA,0xFCB802AA,0xCCB40009,0xCCB40009,0xA8BC00A6,0xB0B00288,0xB0B00288,0xA0AC0041,0x92B0028A,0x17C0BE8,0x17C0BE8,0x17C0BE8,0xDA700372,0xDA700372,0xA4A40373,0xCA440289,0xCA440289,0xA6640002,0x9474028A,0x43F80BE8,
+0x43F80BE8,0xA400037B,0x900002EB,0x7E000BEB,0xFEE806AD,0xF6FC09B4,0x1000BE8,0xFED402DD,0xFEC0005D,0xECB00005,0xDAB80021,0xC0B00002,0xFED0064B,0xFEBC0272,0xCEA0028A,0xA6640002,0x11FC0BE8,0x1280288,0x1280288,0x1280288,0x1280288,0xEF040000,0xEF040000,0xEF040000,0xB7040000,0xB7040000,0xA5040001,0x1B80288,0x1B80288,0x1B80288,0xC4C40001,0xC4C40001,
+0xA6E00001,0x61F80288,0x61F80288,0xA4740001,0x9200028A,0x1B80288,0x1B80288,0x1B80288,0xC4C40001,0xC4C40001,0xA6E00001,0x61F80288,0x61F80288,0xA4740001,0x9200028A,0x61F80288,0x61F80288,0xA4740001,0x9200028A,0x9200028A,0xFF100152,0xF92001A5,0x1280288,0xFCF400B5,0xFEC8000A,0xE4BC0000,0xD0CC0000,0xC2AC0000,0xFEF80171,0xFEDC0091,0x37FC0288,0xA4740001,
+0x37FC0288,0x1740374,0xFF5C0071,0xE54C0000,0xCF4C0001,0x31FC0372,0xF5000001,0xCF240001,0x9BF80372,0xCEA40001,0xBA000372,0x31FC0372,0xF5000001,0xCF240001,0x9BF80372,0xCEA40001,0xBA000372,0x9BF80372,0xCEA40001,0xBA000372,0xBA000372,0x31FC0372,0xF5000001,0xCF240001,0x9BF80372,0xCEA40001,0xBA000372,0x9BF80372,0xCEA40001,0xBA000372,0xBA000372,0x9BF80372,
+0xCEA40001,0xBA000372,0xBA000372,0xBA000372,0xFF5002A8,0xF8C0372,0xFF6C02B9,0xFF30016D,0xFEE80075,0xEEA80000,0xCED40001,0xCE680001,0xF9500288,0xFF140145,0xD6DC0000,0xBA000372,0x7FFC0372,0xD80374,0xD80374,0xD80374,0xD80374,0xD80374,0xD80374,0xD80374,0xD80374,0xD80374,0xD80374,0xD6B00000,0xD6B00000,0xD6B00000,0xD6B00000,0xD6B00000,
+0xD6B00000,0x96B00000,0x96B00000,0x96B00000,0x80B00001,0x1440372,0x1440372,0x1440372,0x1440372,0x1440372,0x1440372,0xA6640001,0xA6640001,0xA6640001,0x80880001,0x27F80372,0x27F80372,0x27F80372,0x80080001,0x6C000372,0xFECC0208,0xD80374,0xD80374,0xFAC400C8,0xFEB40028,0xF4B00000,0xF4B00000,0xBEB00000,0xFCB801A5,0xFAAC00A4,0xACA40000,0xA6640001,
+0x1D00372,};
+static const uint32_t g_etc1_to_bc7_m6_table147[] = {
+0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x13FC0000,
+0x13FC0000,0x13FC0000,0x13FC0000,0x5E000001,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xC00000,0xCC0000,0xCC0000,0xCC0000,0x11C0000,0x1980000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,
+0x3980000,0x51FC0000,0x51FC0000,0x51FC0000,0x88000001,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,0x51FC0000,0x51FC0000,0x51FC0000,0x88000001,0x51FC0000,0x51FC0000,0x51FC0000,0x88000001,0x88000001,0xB240000,0x1140000,0x1140000,0x1400000,0x3580000,0x1780000,0x1780000,0x1D00000,0x1400000,0x3580000,0x23FC0000,0x51FC0000,
+0x23FC0000,0x15C0000,0x15C0000,0x15C0000,0x15C0000,0x9FC0000,0x9FC0000,0x9FC0000,0x87FC0000,0x87FC0000,0xAC000001,0x9FC0000,0x9FC0000,0x9FC0000,0x87FC0000,0x87FC0000,0xAC000001,0x87FC0000,0x87FC0000,0xAC000001,0xAC000001,0x9FC0000,0x9FC0000,0x9FC0000,0x87FC0000,0x87FC0000,0xAC000001,0x87FC0000,0x87FC0000,0xAC000001,0xAC000001,0x87FC0000,
+0x87FC0000,0xAC000001,0xAC000001,0xAC000001,0x1940000,0x1740000,0x15C0000,0x1D80000,0x39FC0000,0x67FC0000,0x77FC0000,0x91FC0000,0x1B40000,0x9FC0000,0x67FC0000,0xAC000001,0x67FC0000,0x1B00000,0x89FC0000,0xC5FC0000,0xD6000001,0x89FC0000,0xC5FC0000,0xD6000001,0xC5FC0000,0xD6000001,0xD6000001,0x89FC0000,0xC5FC0000,0xD6000001,0xC5FC0000,0xD6000001,
+0xD6000001,0xC5FC0000,0xD6000001,0xD6000001,0xD6000001,0x89FC0000,0xC5FC0000,0xD6000001,0xC5FC0000,0xD6000001,0xD6000001,0xC5FC0000,0xD6000001,0xD6000001,0xD6000001,0xC5FC0000,0xD6000001,0xD6000001,0xD6000001,0xD6000001,0x41FC0000,0x1CC0000,0x1CC0000,0xA1FC0000,0xBFF80000,0xCFF40000,0xD6000001,0xD6000001,0x6FFC0000,0xADFC0000,0xD5FC0000,0xD6000001,
+0xB7FC0000,0x1381EA8,0xFF241198,0xFF100BE8,0xD7100BE9,0xFF0C0C98,0xFEF403FD,0xDCF80531,0xE8E806E6,0xD4E803AE,0xC2E806E6,0xFEF40FB8,0xFECC0345,0xDED80411,0xF0BC038E,0xD6C0000E,0xC4C803AE,0xD6C00BE8,0xCAB00413,0xBCB80533,0xAEC00BEB,0x1D01EA8,0xFEA00D2F,0xD6C40BE9,0xFE700736,0xD88C038E,0xC29C06E6,0xFA2C0BE9,0xD648028A,0xC05403A3,0xAE740BEB,0x6DF81EA8,
+0xD0000C49,0xBC0007F4,0xAC000D93,0x9A001EAC,0xFF2013CE,0xFF2C1AAE,0xFF2C1BCD,0xFF0009E0,0xFED8026D,0xF4C00006,0xDAC80046,0xD2B80046,0xFF101346,0xFEE008B4,0xDCAC029D,0xC05403A3,0x45FC1EA8,0x1600BE8,0xFF4404E1,0xF5380288,0xD7380289,0xFF3004D8,0xFB140005,0xD91C0042,0xDF140372,0xD10C00A5,0xC3140372,0xFFC0BE8,0xFED802D9,0xD8FC0289,0xF8A80372,0xD6C8000A,
+0xC2DC0372,0x8BF80BE8,0xD6440289,0xC2280372,0xAE000BEB,0xFFC0BE8,0xFED802D9,0xD8FC0289,0xF8A80372,0xD6C8000A,0xC2DC0372,0x8BF80BE8,0xD6440289,0xC2280372,0xAE000BEB,0x8BF80BE8,0xD6440289,0xC2280372,0xAE000BEB,0xAE000BEB,0xFB480849,0xF5580A7E,0xF75C0A69,0xFF180496,0xFEE80149,0xF2C40006,0xD8DC0001,0xD4A40022,0xFF34084E,0xFF040403,0xE09C0288,0xC2280372,
+0x6BFC0BE8,0x1100BE8,0x1100BE8,0x1100BE8,0x1100BE8,0xFEF403E4,0xFEF403E4,0xFEF403E4,0xC8EC0374,0xC8EC0374,0xACE80375,0xFEC802CA,0xFEC802CA,0xFEC802CA,0xD4C40009,0xD4C40009,0xB0CC00A6,0xB8C00288,0xB8C00288,0xA8BC0041,0x9AC0028A,0x1940BE8,0x1940BE8,0x1940BE8,0xE2800372,0xE2800372,0xACB40373,0xD2540289,0xD2540289,0xAE740002,0x9C84028A,0x4FF80BE8,
+0x4FF80BE8,0xAC040373,0x9A0002CA,0x86000BEB,0xFD000714,0xFF0C09B4,0x1100BE8,0xFEE8034D,0xFED40099,0xF4C00005,0xE2C80021,0xC8C00002,0xFEE406AA,0xFED002BA,0xD6B0028A,0xAE740002,0x1FFC0BE8,0x1380288,0x1380288,0x1380288,0x1380288,0xF7140000,0xF7140000,0xF7140000,0xBF140000,0xBF140000,0xAD140001,0x1D00288,0x1D00288,0x1D00288,0xCCD40001,0xCCD40001,
+0xAEF00001,0x6DF80288,0x6DF80288,0xAC840001,0x9A00028A,0x1D00288,0x1D00288,0x1D00288,0xCCD40001,0xCCD40001,0xAEF00001,0x6DF80288,0x6DF80288,0xAC840001,0x9A00028A,0x6DF80288,0x6DF80288,0xAC840001,0x9A00028A,0x9A00028A,0xFF20016D,0xFF2C01B1,0x1380288,0xFD0400CA,0xFEE00019,0xECCC0000,0xD8DC0000,0xCABC0000,0xFD100188,0xFEE800B4,0x45FC0288,0xAC840001,
+0x45FC0288,0x1840374,0xFF68009D,0xED5C0000,0xD75C0001,0x49FC0372,0xFD100001,0xD7340001,0xA7F80372,0xD6B40001,0xC2000372,0x49FC0372,0xFD100001,0xD7340001,0xA7F80372,0xD6B40001,0xC2000372,0xA7F80372,0xD6B40001,0xC2000372,0xC2000372,0x49FC0372,0xFD100001,0xD7340001,0xA7F80372,0xD6B40001,0xC2000372,0xA7F80372,0xD6B40001,0xC2000372,0xC2000372,0xA7F80372,
+0xD6B40001,0xC2000372,0xC2000372,0xC2000372,0xFB7002AD,0x1A00372,0xF98002D4,0xFF40019A,0xFF0C00B5,0xF6B80000,0xD6E40001,0xD6780001,0xFF5C0290,0xFF2C0185,0xDEEC0000,0xC2000372,0x8FFC0372,0xE80374,0xE80374,0xE80374,0xE80374,0xE80374,0xE80374,0xE80374,0xE80374,0xE80374,0xE80374,0xDEC00000,0xDEC00000,0xDEC00000,0xDEC00000,0xDEC00000,
+0xDEC00000,0x9EC00000,0x9EC00000,0x9EC00000,0x88C00001,0x15C0372,0x15C0372,0x15C0372,0x15C0372,0x15C0372,0x15C0372,0xAE740001,0xAE740001,0xAE740001,0x88980001,0x33F80372,0x33F80372,0x33F80372,0x88180001,0x74000372,0xF8E00221,0xE80374,0xE80374,0xFCD400DD,0xFCCC003D,0xFCC00000,0xFCC00000,0xC6C00000,0xF8CC01C2,0xFEBC00B9,0xB4B40000,0xAE740001,
+0x1F00372,};
+static const uint32_t g_etc1_to_bc7_m6_table148[] = {
+0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x21F80000,
+0x21F80000,0x21F80000,0x21F80000,0x68000000,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xD00001,0xE00000,0xE00000,0xE00000,0x1380000,0x1BC0000,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1240001,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,
+0x1B40000,0x5FF80000,0x5FF80000,0x5FF80000,0x92000000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x1B40000,0x5FF80000,0x5FF80000,0x5FF80000,0x92000000,0x5FF80000,0x5FF80000,0x5FF80000,0x92000000,0x92000000,0x5380000,0x1240001,0x1240001,0x3540000,0x1700000,0x1900000,0x1900000,0x3EC0000,0x3540000,0x1700000,0x35FC0000,0x5FF80000,
+0x35FC0000,0x16C0001,0x16C0001,0x16C0001,0x16C0001,0x25FC0000,0x25FC0000,0x25FC0000,0x95F80000,0x95F80000,0xB6000000,0x25FC0000,0x25FC0000,0x25FC0000,0x95F80000,0x95F80000,0xB6000000,0x95F80000,0x95F80000,0xB6000000,0xB6000000,0x25FC0000,0x25FC0000,0x25FC0000,0x95F80000,0x95F80000,0xB6000000,0x95F80000,0x95F80000,0xB6000000,0xB6000000,0x95F80000,
+0x95F80000,0xB6000000,0xB6000000,0xB6000000,0x3A80000,0xB840000,0x16C0001,0x3F00000,0x4FFC0000,0x79FC0000,0x87F80000,0x9DFC0000,0x1CC0000,0x25FC0000,0x79FC0000,0xB6000000,0x79FC0000,0x1C00001,0xA5FC0000,0xD3FC0000,0xE0000000,0xA5FC0000,0xD3FC0000,0xE0000000,0xD3FC0000,0xE0000000,0xE0000000,0xA5FC0000,0xD3FC0000,0xE0000000,0xD3FC0000,0xE0000000,
+0xE0000000,0xD3FC0000,0xE0000000,0xE0000000,0xE0000000,0xA5FC0000,0xD3FC0000,0xE0000000,0xD3FC0000,0xE0000000,0xE0000000,0xD3FC0000,0xE0000000,0xE0000000,0xE0000000,0xD3FC0000,0xE0000000,0xE0000000,0xE0000000,0xE0000000,0x6DFC0000,0x1E00000,0x1E00000,0xB7FC0000,0xCDFC0000,0xD9FC0000,0xE0000000,0xE0000000,0x8FFC0000,0xC1FC0000,0xDFF00000,0xE0000000,
+0xC7FC0000,0x1481EAC,0xFF30126C,0xFF200C0F,0xE1200BEB,0xFF180DB4,0xFF080497,0xE5080533,0xF0FC06E6,0xDCF803AE,0xCAFC06E6,0xFF00109C,0xFEE4040B,0xE8EC0413,0xFAD0038E,0xE0D0000E,0xCCD803AE,0xDED40BE9,0xD4C40411,0xC4C80531,0xB8D00BE9,0x3E81EA8,0xFEC00DE7,0xE0D40BE8,0xFE8807BE,0xE2A0038E,0xCAB006E6,0xFE4C0BFB,0xE05C028A,0xCA6803A1,0xB8840BE8,0x79FC1EA8,
+0xDC000C13,0xC400078E,0xB2000D35,0xA4001EA8,0xFF3414AF,0xFB441B24,0xFD481BF4,0xFF140B27,0xFEF00392,0xFED40006,0xE4DC0046,0xDCCC0046,0xFF181429,0xFF0009F4,0xE6BC029D,0xCA6803A1,0x57FC1EA8,0x1700BEB,0xFF5C056A,0xFF48028A,0xE148028A,0xFF440545,0xFF28001A,0xE3300041,0xE7280373,0xDB2000A6,0xCB240375,0x2BFC0BE8,0xFEFC032A,0xE1100288,0xFEC00375,0xDED80009,
+0xCAF00374,0x97FC0BE8,0xE0540288,0xCA400374,0xB8000BE8,0x2BFC0BE8,0xFEFC032A,0xE1100288,0xFEC00375,0xDED80009,0xCAF00374,0x97FC0BE8,0xE0540288,0xCA400374,0xB8000BE8,0x97FC0BE8,0xE0540288,0xCA400374,0xB8000BE8,0xB8000BE8,0xFF580895,0xFF6C0A7D,0xFF6C0A6E,0xFF30053A,0xFF1001EE,0xFCD80005,0xE0EC0002,0xDCBC0021,0xFF4408B8,0xFF2404CA,0xE8B00289,0xCA400374,
+0x7DF80BE8,0x1200BEB,0x1200BEB,0x1200BEB,0x1200BEB,0xFF040422,0xFF040422,0xFF040422,0xD2FC0372,0xD2FC0372,0xB6FC0372,0xFEE00301,0xFEE00301,0xFEE00301,0xDCD4000A,0xDCD4000A,0xBAE000A5,0xC2D00289,0xC2D00289,0xB2D00042,0xA4D00289,0x1B00BE8,0x1B00BE8,0x1B00BE8,0xEC900372,0xEC900372,0xB6C40372,0xDC640289,0xDC640289,0xB6840005,0xA4980288,0x5DF40BE8,
+0x5DF40BE8,0xB6100372,0xA20002A9,0x90000BE8,0xFF100755,0xF71C09F6,0x1200BEB,0xFEF803C2,0xFEE400F1,0xFAD40005,0xEAD80022,0xD2D00001,0xFEF806F2,0xFEE80352,0xE0C00289,0xB6840005,0x31FC0BE8,0x148028A,0x148028A,0x148028A,0x148028A,0xFF280001,0xFF280001,0xFF280001,0xC9240001,0xC9240001,0xB7240001,0x3E80288,0x3E80288,0x3E80288,0xD6E40001,0xD6E40001,
+0xB7040000,0x79FC0288,0x79FC0288,0xB6900000,0xA4000288,0x3E80288,0x3E80288,0x3E80288,0xD6E40001,0xD6E40001,0xB7040000,0x79FC0288,0x79FC0288,0xB6900000,0xA4000288,0x79FC0288,0x79FC0288,0xB6900000,0xA4000288,0xA4000288,0xFB34018A,0xFB4401C2,0x148028A,0xFF1800E1,0xFCFC0032,0xF4E00000,0xE2EC0000,0xD2D00000,0xF92801A5,0xFF0400D0,0x57FC0288,0xB6900000,
+0x57FC0288,0x1980372,0xFF8000E1,0xF5700001,0xE16C0001,0x65FC0372,0xFF2C0011,0xE1440000,0xB3FC0372,0xE0C00000,0xCA000374,0x65FC0372,0xFF2C0011,0xE1440000,0xB3FC0372,0xE0C00000,0xCA000374,0xB3FC0372,0xE0C00000,0xCA000374,0xCA000374,0x65FC0372,0xFF2C0011,0xE1440000,0xB3FC0372,0xE0C00000,0xCA000374,0xB3FC0372,0xE0C00000,0xCA000374,0xCA000374,0xB3FC0372,
+0xE0C00000,0xCA000374,0xCA000374,0xCA000374,0xFB8402D2,0x1B40372,0xFF8C02F2,0xFD6801E1,0xFF2800E9,0xFECC0001,0xE0F40000,0xE0840000,0xFF7002C5,0xFF4C01B1,0xE7000000,0xCA000374,0x9FFC0372,0xFC0372,0xFC0372,0xFC0372,0xFC0372,0xFC0372,0xFC0372,0xFC0372,0xFC0372,0xFC0372,0xFC0372,0xE6D40001,0xE6D40001,0xE6D40001,0xE6D40001,0xE6D40001,
+0xE6D40001,0xA6D40001,0xA6D40001,0xA6D40001,0x92D00001,0x3740372,0x3740372,0x3740372,0x3740372,0x3740372,0x3740372,0xB8840001,0xB8840001,0xB8840001,0x92A80000,0x3FFC0372,0x3FFC0372,0x3FFC0372,0x92240000,0x7C000374,0xFEEC0239,0xFC0372,0xFC0372,0xFEE800F2,0xFCE00055,0xFED40002,0xFED40002,0xCED40001,0xFED801D4,0xFED000D0,0xBAC80001,0xB8840001,
+0xDFC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table149[] = {
+0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x1500000,0x2DF80000,
+0x2DF80000,0x2DF80000,0x2DF80000,0x70000000,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xE00001,0xF00000,0xF00000,0xF00000,0x1500000,0x1E00000,0x1340001,0x1340001,0x1340001,0x1340001,0x1340001,0x1340001,0x1340001,0x1340001,0x1340001,0x1340001,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,
+0x1CC0000,0x6BF80000,0x6BF80000,0x6BF80000,0x9A000000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x6BF80000,0x6BF80000,0x6BF80000,0x9A000000,0x6BF80000,0x6BF80000,0x6BF80000,0x9A000000,0x9A000000,0xD480000,0x1340001,0x1340001,0x1680000,0x1840000,0x3A40000,0x3A40000,0xBFC0000,0x1680000,0x1840000,0x43FC0000,0x6BF80000,
+0x43FC0000,0x17C0001,0x17C0001,0x17C0001,0x17C0001,0x3DFC0000,0x3DFC0000,0x3DFC0000,0xA1F80000,0xA1F80000,0xBE000000,0x3DFC0000,0x3DFC0000,0x3DFC0000,0xA1F80000,0xA1F80000,0xBE000000,0xA1F80000,0xA1F80000,0xBE000000,0xBE000000,0x3DFC0000,0x3DFC0000,0x3DFC0000,0xA1F80000,0xA1F80000,0xBE000000,0xA1F80000,0xA1F80000,0xBE000000,0xBE000000,0xA1F80000,
+0xA1F80000,0xBE000000,0xBE000000,0xBE000000,0x1BC0000,0x1980000,0x17C0001,0xFFC0000,0x63FC0000,0x87FC0000,0x95F80000,0xA9F40000,0x1E00000,0x3DFC0000,0x87FC0000,0xBE000000,0x87FC0000,0x1D00001,0xBDFC0000,0xDFF80000,0xE8000000,0xBDFC0000,0xDFF80000,0xE8000000,0xDFF80000,0xE8000000,0xE8000000,0xBDFC0000,0xDFF80000,0xE8000000,0xDFF80000,0xE8000000,
+0xE8000000,0xDFF80000,0xE8000000,0xE8000000,0xE8000000,0xBDFC0000,0xDFF80000,0xE8000000,0xDFF80000,0xE8000000,0xE8000000,0xDFF80000,0xE8000000,0xE8000000,0xE8000000,0xDFF80000,0xE8000000,0xE8000000,0xE8000000,0xE8000000,0x95FC0000,0x1F00000,0x1F00000,0xCBFC0000,0xDBFC0000,0xE5F00000,0xE8000000,0xE8000000,0xAFFC0000,0xD1FC0000,0xE9C40000,0xE8000000,
+0xD7FC0000,0x1581EAC,0xFF44131B,0xFF340C64,0xE9300BEB,0xFF300EB4,0xFF180563,0xED180533,0xF90C06E6,0xE50803AE,0xD30C06E6,0xFF181164,0xFEFC04F3,0xF0FC0413,0xFEE4039E,0xE8E0000E,0xD4E803AE,0xE6E40BE9,0xDCD40411,0xCCD80531,0xC0E00BE9,0x7FC1EA8,0xFED80EA7,0xE8E40BE8,0xFEAC0866,0xEAB0038E,0xD2C006E6,0xFE640C43,0xE86C028A,0xD27803A1,0xC0940BE8,0x85FC1EA8,
+0xE6000BF8,0xD000073E,0xBE000CD5,0xAC001EA8,0xFF3C1574,0xFF4C1B64,0xF5581C63,0xFF240C9E,0xFF0404CE,0xFEE80032,0xECEC0046,0xE4DC0046,0xFF3414DA,0xFF100B2E,0xEECC029D,0xD27803A1,0x65FC1EA8,0x1800BEB,0xFF6805FA,0xFF5802A3,0xE958028A,0xFF5C05CD,0xFF40006A,0xEB400041,0xEF380373,0xE33000A6,0xD3340375,0x43FC0BE8,0xFF14039A,0xE9200288,0xFEE4039D,0xE6E80009,
+0xD3000374,0xA3FC0BE8,0xE8640288,0xD2500374,0xC0000BE8,0x43FC0BE8,0xFF14039A,0xE9200288,0xFEE4039D,0xE6E80009,0xD3000374,0xA3FC0BE8,0xE8640288,0xD2500374,0xC0000BE8,0xA3FC0BE8,0xE8640288,0xD2500374,0xC0000BE8,0xC0000BE8,0xFF640905,0xF77C0AC3,0xF9800AB3,0xFF4405E1,0xFF24028E,0xFEF0001B,0xE8FC0002,0xE4CC0021,0xFF5C08DE,0xFF400550,0xF0C00289,0xD2500374,
+0x8BFC0BE8,0x1300BEB,0x1300BEB,0x1300BEB,0x1300BEB,0xFF180463,0xFF180463,0xFF180463,0xDB0C0372,0xDB0C0372,0xBF0C0372,0xFEF4033B,0xFEF4033B,0xFEF4033B,0xE4E4000A,0xE4E4000A,0xC2F000A5,0xCAE00289,0xCAE00289,0xBAE00042,0xACE00289,0x3C40BE8,0x3C40BE8,0x3C40BE8,0xF4A00372,0xF4A00372,0xBED40372,0xE4740289,0xE4740289,0xBE940005,0xACA80288,0x67FC0BE8,
+0x67FC0BE8,0xBE200372,0xAC000291,0x98000BE8,0xFF200792,0xFF2C09F6,0x1300BEB,0xFF100426,0xFEF8014D,0xFEE8000E,0xF2E80022,0xDAE00001,0xFF100749,0xFEF403B6,0xE8D00289,0xBE940005,0x3FFC0BE8,0x158028A,0x158028A,0x158028A,0x158028A,0xFD38000A,0xFD38000A,0xFD38000A,0xD1340001,0xD1340001,0xBF340001,0x7FC0288,0x7FC0288,0x7FC0288,0xDEF40001,0xDEF40001,
+0xBF140000,0x85FC0288,0x85FC0288,0xBEA00000,0xAC000288,0x7FC0288,0x7FC0288,0x7FC0288,0xDEF40001,0xDEF40001,0xBF140000,0x85FC0288,0x85FC0288,0xBEA00000,0xAC000288,0x85FC0288,0x85FC0288,0xBEA00000,0xAC000288,0xAC000288,0xF74801A5,0xF35401E1,0x158028A,0xFD300109,0xFD140048,0xFCF00000,0xEAFC0000,0xDAE00000,0xFF3401A9,0xFF1800E9,0x65FC0288,0xBEA00000,
+0x65FC0288,0x1A80372,0xFF8C0131,0xFD800001,0xE97C0001,0x7DFC0372,0xFF4C0041,0xE9540000,0xBFFC0372,0xE8D00000,0xD2000374,0x7DFC0372,0xFF4C0041,0xE9540000,0xBFFC0372,0xE8D00000,0xD2000374,0xBFFC0372,0xE8D00000,0xD2000374,0xD2000374,0x7DFC0372,0xFF4C0041,0xE9540000,0xBFFC0372,0xE8D00000,0xD2000374,0xBFFC0372,0xE8D00000,0xD2000374,0xD2000374,0xBFFC0372,
+0xE8D00000,0xD2000374,0xD2000374,0xD2000374,0xFF9402D4,0x1C40372,0xFBA402F9,0xFF740212,0xFF500139,0xFEF0001A,0xE9040000,0xE8940000,0xFB9002D2,0xFF6401F9,0xEF100000,0xD2000374,0xAFFC0372,0x10C0372,0x10C0372,0x10C0372,0x10C0372,0x10C0372,0x10C0372,0x10C0372,0x10C0372,0x10C0372,0x10C0372,0xEEE40001,0xEEE40001,0xEEE40001,0xEEE40001,0xEEE40001,
+0xEEE40001,0xAEE40001,0xAEE40001,0xAEE40001,0x9AE00001,0x38C0372,0x38C0372,0x38C0372,0x38C0372,0x38C0372,0x38C0372,0xC0940001,0xC0940001,0xC0940001,0x9AB80000,0x4BFC0372,0x4BFC0372,0x4BFC0372,0x9A340000,0x84000374,0xFB040242,0x10C0372,0x10C0372,0xFEF40115,0xFEEC006A,0xFEE8000D,0xFEE8000D,0xD6E40001,0xFCF001E1,0xFEE400F4,0xC2D80001,0xC0940001,
+0x1DF80372,};
+static const uint32_t g_etc1_to_bc7_m6_table150[] = {
+0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x39F80000,
+0x39F80000,0x39F80000,0x39F80000,0x78000000,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0xF00001,0x9000000,0x9000000,0x9000000,0x1680000,0x3FC0000,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1440001,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,
+0x1E40000,0x77F80000,0x77F80000,0x77F80000,0xA2000000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x1E40000,0x77F80000,0x77F80000,0x77F80000,0xA2000000,0x77F80000,0x77F80000,0x77F80000,0xA2000000,0xA2000000,0x15C0000,0x1440001,0x1440001,0x17C0000,0x1980000,0x1BC0000,0x1BC0000,0x1DFC0000,0x17C0000,0x1980000,0x53FC0000,0x77F80000,
+0x53FC0000,0x18C0001,0x18C0001,0x18C0001,0x18C0001,0x55FC0000,0x55FC0000,0x55FC0000,0xADF80000,0xADF80000,0xC6000000,0x55FC0000,0x55FC0000,0x55FC0000,0xADF80000,0xADF80000,0xC6000000,0xADF80000,0xADF80000,0xC6000000,0xC6000000,0x55FC0000,0x55FC0000,0x55FC0000,0xADF80000,0xADF80000,0xC6000000,0xADF80000,0xADF80000,0xC6000000,0xC6000000,0xADF80000,
+0xADF80000,0xC6000000,0xC6000000,0xC6000000,0x7CC0000,0x1A80000,0x18C0001,0x2FFC0000,0x77FC0000,0x97FC0000,0xA1FC0000,0xB3FC0000,0x1F40000,0x55FC0000,0x97FC0000,0xC6000000,0x97FC0000,0x1E00001,0xD5FC0000,0xEBF80000,0xF0000000,0xD5FC0000,0xEBF80000,0xF0000000,0xEBF80000,0xF0000000,0xF0000000,0xD5FC0000,0xEBF80000,0xF0000000,0xEBF80000,0xF0000000,
+0xF0000000,0xEBF80000,0xF0000000,0xF0000000,0xF0000000,0xD5FC0000,0xEBF80000,0xF0000000,0xEBF80000,0xF0000000,0xF0000000,0xEBF80000,0xF0000000,0xF0000000,0xF0000000,0xEBF80000,0xF0000000,0xF0000000,0xF0000000,0xF0000000,0xBDFC0000,0x27FC0000,0x27FC0000,0xDDFC0000,0xE9F80000,0xEFF00000,0xF0000000,0xF0000000,0xCDFC0000,0xE3FC0000,0xF1D40000,0xF0000000,
+0xE5FC0000,0x1681EAC,0xFF50140B,0xFF480D03,0xF1400BEB,0xFF440FB6,0xFF2C0663,0xF5280533,0xFF1C06EC,0xED1803AE,0xDB1C06E6,0xFF30124C,0xFF14061B,0xF90C0413,0xFEFC0406,0xF0F0000E,0xDCF803AE,0xEEF40BE9,0xE4E40411,0xD4E80531,0xC8F00BE9,0x1FFC1EA8,0xFEF00F87,0xF0F40BE8,0xFEC0096E,0xF2C0038E,0xDAD006E6,0xFE880CBB,0xF07C028A,0xDA8803A1,0xC8A40BE8,0x91FC1EA8,
+0xF0000BEB,0xD8000716,0xC4000C91,0xB4001EA8,0xFF50163F,0xFB641BB6,0xFD681C63,0xFF340DE2,0xFF1C0636,0xFEFC00C2,0xF4FC0046,0xECEC0046,0xFF4415D9,0xFF240CCA,0xF6DC029D,0xDA8803A1,0x75FC1EA8,0x1900BEB,0xFF80068A,0xFF7002EB,0xF168028A,0xFF680655,0xFF5400F6,0xF3500041,0xF7480373,0xEB4000A6,0xDB440375,0x5BFC0BE8,0xFF2C042A,0xF1300288,0xFEFC03ED,0xEEF80009,
+0xDB100374,0xAFFC0BE8,0xF0740288,0xDA600374,0xC8000BE8,0x5BFC0BE8,0xFF2C042A,0xF1300288,0xFEFC03ED,0xEEF80009,0xDB100374,0xAFFC0BE8,0xF0740288,0xDA600374,0xC8000BE8,0xAFFC0BE8,0xF0740288,0xDA600374,0xC8000BE8,0xC8000BE8,0xFF78093E,0xFF8C0AC3,0xFF8C0ABB,0xFF5C0671,0xFF380356,0xFF10007D,0xF10C0002,0xECDC0021,0xFF780956,0xFF540602,0xF8D00289,0xDA600374,
+0x9BFC0BE8,0x1400BEB,0x1400BEB,0x1400BEB,0x1400BEB,0xFF2404B3,0xFF2404B3,0xFF2404B3,0xE31C0372,0xE31C0372,0xC71C0372,0xFF0C0393,0xFF0C0393,0xFF0C0393,0xECF4000A,0xECF4000A,0xCB0000A5,0xD2F00289,0xD2F00289,0xC2F00042,0xB4F00289,0x3DC0BE8,0x3DC0BE8,0x3DC0BE8,0xFCB00372,0xFCB00372,0xC6E40372,0xEC840289,0xEC840289,0xC6A40005,0xB4B80288,0x73FC0BE8,
+0x73FC0BE8,0xC6300372,0xB4000289,0xA0000BE8,0xFF2C07F1,0xF73C0A3B,0x1400BEB,0xFF1804AA,0xFF0C01B9,0xFEF80032,0xFAF80022,0xE2F00001,0xFF20078D,0xFF10042D,0xF0E00289,0xC6A40005,0x4FFC0BE8,0x168028A,0x168028A,0x168028A,0x168028A,0xFD4C0019,0xFD4C0019,0xFD4C0019,0xD9440001,0xD9440001,0xC7440001,0x1FFC0288,0x1FFC0288,0x1FFC0288,0xE7040001,0xE7040001,
+0xC7240000,0x91FC0288,0x91FC0288,0xC6B00000,0xB4000288,0x1FFC0288,0x1FFC0288,0x1FFC0288,0xE7040001,0xE7040001,0xC7240000,0x91FC0288,0x91FC0288,0xC6B00000,0xB4000288,0x91FC0288,0x91FC0288,0xC6B00000,0xB4000288,0xB4000288,0xFF5801A5,0xFB6401E1,0x168028A,0xFF440120,0xFD280064,0xFF080008,0xF30C0000,0xE2F00000,0xFD4C01C2,0xFF30010D,0x75FC0288,0xC6B00000,
+0x75FC0288,0x1B80372,0xFFA40179,0xFF900011,0xF18C0001,0x95FC0372,0xFF640089,0xF1640000,0xCBFC0372,0xF0E00000,0xDA000374,0x95FC0372,0xFF640089,0xF1640000,0xCBFC0372,0xF0E00000,0xDA000374,0xCBFC0372,0xF0E00000,0xDA000374,0xDA000374,0x95FC0372,0xFF640089,0xF1640000,0xCBFC0372,0xF0E00000,0xDA000374,0xCBFC0372,0xF0E00000,0xDA000374,0xDA000374,0xCBFC0372,
+0xF0E00000,0xDA000374,0xDA000374,0xDA000374,0xFBAC02F9,0x3D40372,0xFFAC0321,0xFF940242,0xFF680179,0xFF180055,0xF1140000,0xF0A40000,0xFF9802F2,0xFF880221,0xF7200000,0xDA000374,0xBFF80372,0x11C0372,0x11C0372,0x11C0372,0x11C0372,0x11C0372,0x11C0372,0x11C0372,0x11C0372,0x11C0372,0x11C0372,0xF6F40001,0xF6F40001,0xF6F40001,0xF6F40001,0xF6F40001,
+0xF6F40001,0xB6F40001,0xB6F40001,0xB6F40001,0xA2F00001,0x3A40372,0x3A40372,0x3A40372,0x3A40372,0x3A40372,0x3A40372,0xC8A40001,0xC8A40001,0xC8A40001,0xA2C80000,0x57FC0372,0x57FC0372,0x57FC0372,0xA2440000,0x8C000374,0xFF0C0262,0x11C0372,0x11C0372,0xFF040132,0xFF000082,0xFEF80019,0xFEF80019,0xDEF40001,0xF9040200,0xFEF80109,0xCAE80001,0xC8A40001,
+0x2BFC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table151[] = {
+0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x45F80000,
+0x45F80000,0x45F80000,0x45F80000,0x80000000,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1000001,0x1140000,0x1140000,0x1140000,0x1800000,0x13FC0000,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,
+0x1FC0000,0x83F80000,0x83F80000,0x83F80000,0xAA000000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x83F80000,0x83F80000,0x83F80000,0xAA000000,0x83F80000,0x83F80000,0x83F80000,0xAA000000,0xAA000000,0x16C0000,0x1540001,0x1540001,0x38C0000,0x1AC0000,0x1D00000,0x1D00000,0x31FC0000,0x38C0000,0x1AC0000,0x61FC0000,0x83F80000,
+0x61FC0000,0x19C0001,0x19C0001,0x19C0001,0x19C0001,0x6FFC0000,0x6FFC0000,0x6FFC0000,0xB9F80000,0xB9F80000,0xCE000000,0x6FFC0000,0x6FFC0000,0x6FFC0000,0xB9F80000,0xB9F80000,0xCE000000,0xB9F80000,0xB9F80000,0xCE000000,0xCE000000,0x6FFC0000,0x6FFC0000,0x6FFC0000,0xB9F80000,0xB9F80000,0xCE000000,0xB9F80000,0xB9F80000,0xCE000000,0xCE000000,0xB9F80000,
+0xB9F80000,0xCE000000,0xCE000000,0xCE000000,0x3E00000,0x5B80000,0x19C0001,0x4DFC0000,0x8BFC0000,0xA5FC0000,0xAFFC0000,0xBFF40000,0x15FC0000,0x6FFC0000,0xA5FC0000,0xCE000000,0xA5FC0000,0x1F00001,0xEFFC0000,0xF7F80000,0xF8000000,0xEFFC0000,0xF7F80000,0xF8000000,0xF7F80000,0xF8000000,0xF8000000,0xEFFC0000,0xF7F80000,0xF8000000,0xF7F80000,0xF8000000,
+0xF8000000,0xF7F80000,0xF8000000,0xF8000000,0xF8000000,0xEFFC0000,0xF7F80000,0xF8000000,0xF7F80000,0xF8000000,0xF8000000,0xF7F80000,0xF8000000,0xF8000000,0xF8000000,0xF7F80000,0xF8000000,0xF8000000,0xF8000000,0xF8000000,0xE3FC0000,0xA7FC0000,0xA7FC0000,0xF1FC0000,0xF5FC0000,0xF9F00000,0xF8000000,0xF8000000,0xEBFC0000,0xF3FC0000,0xF9E40000,0xF8000000,
+0xF5FC0000,0x1781EAC,0xFF6814E3,0xFF580DBC,0xF9500BEB,0xFF5010EE,0xFF4007AB,0xFD380533,0xFF2C0746,0xF52803AE,0xE32C06E6,0xFF441329,0xFF280782,0xFF180417,0xFF0804CE,0xF900000E,0xE50803AE,0xF7040BE9,0xECF40411,0xDCF80531,0xD1000BE9,0x37FC1EA8,0xFF14107B,0xF9040BE8,0xFEE40A7E,0xFAD0038E,0xE2E006E6,0xFEAC0D6B,0xF88C028A,0xE29803A1,0xD0B40BE8,0x9DFC1EA8,
+0xF8080BE8,0xE00006F8,0xCE000C58,0xBC001EA8,0xFF641706,0xFF6C1C06,0xF5781CD4,0xFF440F42,0xFF2807C3,0xFF1001BE,0xFD0C0046,0xF4FC0046,0xFF54168D,0xFF400E29,0xFEEC029D,0xE29803A1,0x83FC1EA8,0x1A00BEB,0xFF8C072A,0xFF7C036B,0xF978028A,0xFF8006ED,0xFF6401AA,0xFB600041,0xFF580373,0xF35000A6,0xE3540375,0x75FC0BE8,0xFF4C04E1,0xF9400288,0xFF200465,0xF7080009,
+0xE3200374,0xBBFC0BE8,0xF8840288,0xE2700374,0xD0000BE8,0x75FC0BE8,0xFF4C04E1,0xF9400288,0xFF200465,0xF7080009,0xE3200374,0xBBFC0BE8,0xF8840288,0xE2700374,0xD0000BE8,0xBBFC0BE8,0xF8840288,0xE2700374,0xD0000BE8,0xD0000BE8,0xFF940998,0xF79C0B0D,0xF9A00AFE,0xFF780729,0xFF50043A,0xFF2C0113,0xF91C0002,0xF4EC0021,0xFF88099B,0xFF6806C8,0xFEE40291,0xE2700374,
+0xA9FC0BE8,0x1500BEB,0x1500BEB,0x1500BEB,0x1500BEB,0xFF3C0513,0xFF3C0513,0xFF3C0513,0xEB2C0372,0xEB2C0372,0xCF2C0372,0xFF1803F3,0xFF1803F3,0xFF1803F3,0xF504000A,0xF504000A,0xD31000A5,0xDB000289,0xDB000289,0xCB000042,0xBD000289,0x3F40BE8,0x3F40BE8,0x3F40BE8,0xFEC8037D,0xFEC8037D,0xCEF40372,0xF4940289,0xF4940289,0xCEB40005,0xBCC80288,0x7FFC0BE8,
+0x7FFC0BE8,0xCE400372,0xBC0C0288,0xA8000BE8,0xFF3C0843,0xFF4C0A3B,0x1500BEB,0xFF34051E,0xFF200235,0xFF10007A,0xFF080031,0xEB000001,0xFF3407CA,0xFF2404BA,0xF8F00289,0xCEB40005,0x5FF80BE8,0x178028A,0x178028A,0x178028A,0x178028A,0xFF5C002D,0xFF5C002D,0xFF5C002D,0xE1540001,0xE1540001,0xCF540001,0x37FC0288,0x37FC0288,0x37FC0288,0xEF140001,0xEF140001,
+0xCF340000,0x9DFC0288,0x9DFC0288,0xCEC00000,0xBC000288,0x37FC0288,0x37FC0288,0x37FC0288,0xEF140001,0xEF140001,0xCF340000,0x9DFC0288,0x9DFC0288,0xCEC00000,0xBC000288,0x9DFC0288,0x9DFC0288,0xCEC00000,0xBC000288,0xBC000288,0xFB6C01C2,0xF3740202,0x178028A,0xFD580139,0xFF400080,0xFF200014,0xFB1C0000,0xEB000000,0xF56401E1,0xFF480122,0x83FC0288,0xCEC00000,
+0x83FC0288,0x1C80372,0xFFB001E1,0xFFA00052,0xF99C0001,0xAFFC0372,0xFF8800E9,0xF9740000,0xD7FC0372,0xF8F00000,0xE2000374,0xAFFC0372,0xFF8800E9,0xF9740000,0xD7FC0372,0xF8F00000,0xE2000374,0xD7FC0372,0xF8F00000,0xE2000374,0xE2000374,0xAFFC0372,0xFF8800E9,0xF9740000,0xD7FC0372,0xF8F00000,0xE2000374,0xD7FC0372,0xF8F00000,0xE2000374,0xE2000374,0xD7FC0372,
+0xF8F00000,0xE2000374,0xE2000374,0xE2000374,0xFFB40311,0xBE40372,0xFBC40322,0xFFAC0288,0xFF7C01E1,0xFF4800A9,0xF9240000,0xF8B40000,0xF1C00320,0xFFA00269,0xFF300000,0xE2000374,0xCDFC0372,0x12C0372,0x12C0372,0x12C0372,0x12C0372,0x12C0372,0x12C0372,0x12C0372,0x12C0372,0x12C0372,0x12C0372,0xFF040001,0xFF040001,0xFF040001,0xFF040001,0xFF040001,
+0xFF040001,0xBF040001,0xBF040001,0xBF040001,0xAB000001,0x3BC0372,0x3BC0372,0x3BC0372,0x3BC0372,0x3BC0372,0x3BC0372,0xD0B40001,0xD0B40001,0xD0B40001,0xAAD80000,0x63FC0372,0x63FC0372,0x63FC0372,0xAA540000,0x94000374,0xFB240265,0x12C0372,0x12C0372,0xFD1C0152,0xFF1400A2,0xFF08002D,0xFF08002D,0xE7040001,0xFF100208,0xFB0C0139,0xD2F80001,0xD0B40001,
+0x3BFC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table152[] = {
+0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,0x3980000,0x51FC0000,
+0x51FC0000,0x51FC0000,0x51FC0000,0x88000001,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0xB240000,0xB240000,0xB240000,0x3980000,0x23FC0000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1680000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,
+0x1BFC0000,0x91F80000,0x91F80000,0x91F80000,0xB2000001,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x91F80000,0x91F80000,0x91F80000,0xB2000001,0x91F80000,0x91F80000,0x91F80000,0xB2000001,0xB2000001,0x1800000,0x1680000,0x1680000,0x7A00000,0x1C40000,0x3E80000,0x3E80000,0x47FC0000,0x7A00000,0x1C40000,0x73FC0000,0x91F80000,
+0x73FC0000,0x1B00000,0x1B00000,0x1B00000,0x1B00000,0x89FC0000,0x89FC0000,0x89FC0000,0xC5FC0000,0xC5FC0000,0xD6000001,0x89FC0000,0x89FC0000,0x89FC0000,0xC5FC0000,0xC5FC0000,0xD6000001,0xC5FC0000,0xC5FC0000,0xD6000001,0xD6000001,0x89FC0000,0x89FC0000,0x89FC0000,0xC5FC0000,0xC5FC0000,0xD6000001,0xC5FC0000,0xC5FC0000,0xD6000001,0xD6000001,0xC5FC0000,
+0xC5FC0000,0xD6000001,0xD6000001,0xD6000001,0x5F40000,0x1CC0000,0x1B00000,0x6FFC0000,0xA1FC0000,0xB7FC0000,0xBFF80000,0xCBF80000,0x41FC0000,0x89FC0000,0xB7FC0000,0xD6000001,0xB7FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x18C1D49,0xFF7414EC,0xFF6C0E58,0xFF640BE8,0xFF681121,0xFF5408B8,0xFF50057D,0xFF400775,0xFB3C0394,0xEB3C066D,0xFF5C130E,0xFF40088F,0xFF30046C,0xFF20053D,0xFF180009,0xEB1C033A,0xFF140AFE,0xF30C03CA,0xE5080492,0xD9140AFE,0x4FFC1D47,0xFF2C10D8,0xFF180BE8,0xFEFC0B01,0xFEE403A5,0xEAF4066B,0xFED80D6E,0xFEA00289,0xE8B00322,0xD8C80AFE,0xA9FC1D47,
+0xFE280BE8,0xEA04066B,0xD6000B2E,0xC4001D47,0xFF7816B6,0xFD881AF5,0xFD881B85,0xFF5C0FB9,0xFF4808E2,0xFF2C02B1,0xFF240072,0xFB10002D,0xFF70165C,0xFF500E9A,0xFF0802CE,0xE8B00322,0x93FC1D47,0x1B00B01,0xFFA4072C,0xFF9403C9,0xFF8C0288,0xFF9806DD,0xFF7C0236,0xFF740055,0xFF700321,0xF7640084,0xEB6802F9,0x8DFC0AFE,0xFF64052B,0xFF540288,0xFF380471,0xFD200005,
+0xEB3002FA,0xC7FC0AFE,0xFEA00288,0xEA8402F9,0xD8000AFE,0x8DFC0AFE,0xFF64052B,0xFF540288,0xFF380471,0xFD200005,0xEB3002FA,0xC7FC0AFE,0xFEA00288,0xEA8402F9,0xD8000AFE,0xC7FC0AFE,0xFEA00288,0xEA8402F9,0xD8000AFE,0xD8000AFE,0xFFA0091B,0xFFAC0A29,0xFFAC0A2C,0xFF94070A,0xFF680489,0xFF480194,0xFF340005,0xFCFC0011,0xFF98091E,0xFF8406A8,0xFF1002BB,0xEA8402F9,
+0xB9FC0AFE,0x1640BE8,0x1640BE8,0x1640BE8,0x1640BE8,0xFF50057D,0xFF50057D,0xFF50057D,0xF3400374,0xF3400374,0xD73C0375,0xFF30046C,0xFF30046C,0xFF30046C,0xFF180009,0xFF180009,0xDB2000A6,0xE3140288,0xE3140288,0xD3100041,0xC514028A,0x15FC0BE8,0x15FC0BE8,0x15FC0BE8,0xFEE403A5,0xFEE403A5,0xD7080373,0xFCA80289,0xFCA80289,0xD8C80002,0xC6D8028A,0x8DFC0BE8,
+0x8DFC0BE8,0xD6580373,0xC420028A,0xB0000BEB,0xFF58088D,0xF9600A7D,0x1640BE8,0xFF4405A2,0xFF3402D2,0xFF2400E9,0xFF240072,0xF3140002,0xFD4C0845,0xFF300545,0xFF08028E,0xD8C80002,0x6FFC0BE8,0x18C0288,0x18C0288,0x18C0288,0x18C0288,0xFF740055,0xFF740055,0xFF740055,0xE9680000,0xE9680000,0xD7680001,0x53FC0288,0x53FC0288,0x53FC0288,0xF7280001,0xF7280001,
+0xD9440001,0xABF80288,0xABF80288,0xD6D80001,0xC400028A,0x53FC0288,0x53FC0288,0x53FC0288,0xF7280001,0xF7280001,0xD9440001,0xABF80288,0xABF80288,0xD6D80001,0xC400028A,0xABF80288,0xABF80288,0xD6D80001,0xC400028A,0xC400028A,0xF78001E1,0xFD880200,0x18C0288,0xFB70016D,0xFF5400AA,0xFF3C0034,0xFF340005,0xF5100000,0xFD7401E1,0xFF5C0145,0x95FC0288,0xD6D80001,
+0x95FC0288,0x1D802F9,0xFFC401CD,0xFFB80089,0xFFB00000,0xC3FC02F9,0xFFA00112,0xFF880001,0xE1FC02F9,0xFF100000,0xEA0002F9,0xC3FC02F9,0xFFA00112,0xFF880001,0xE1FC02F9,0xFF100000,0xEA0002F9,0xE1FC02F9,0xFF100000,0xEA0002F9,0xEA0002F9,0xC3FC02F9,0xFFA00112,0xFF880001,0xE1FC02F9,0xFF100000,0xEA0002F9,0xE1FC02F9,0xFF100000,0xEA0002F9,0xEA0002F9,0xE1FC02F9,
+0xFF100000,0xEA0002F9,0xEA0002F9,0xEA0002F9,0xFFD002AD,0x1F802F9,0xF3D402D4,0xFFC00244,0xFFA801CA,0xFF7000E8,0xFF3C0000,0xFED80000,0xF9D002AD,0xFDBC0244,0xFF580019,0xEA0002F9,0xDBFC02F9,0x13C0374,0x13C0374,0x13C0374,0x13C0374,0x13C0374,0x13C0374,0x13C0374,0x13C0374,0x13C0374,0x13C0374,0xFF180008,0xFF180008,0xFF180008,0xFF180008,0xFF180008,
+0xFF180008,0xC9140000,0xC9140000,0xC9140000,0xB3140001,0x1D80372,0x1D80372,0x1D80372,0x1D80372,0x1D80372,0x1D80372,0xD8C80001,0xD8C80001,0xD8C80001,0xB2EC0001,0x71F80372,0x71F80372,0x71F80372,0xB26C0001,0x9E000372,0xF5380288,0x13C0374,0x13C0374,0xFF2C0171,0xFF2800C8,0xFF1C0050,0xFF1C0050,0xF1140000,0xFF200239,0xFF200152,0xDF080000,0xD8C80001,
+0x4BFC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table153[] = {
+0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x3B00000,0x5DFC0000,
+0x5DFC0000,0x5DFC0000,0x5DFC0000,0x90000001,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1240000,0x1380000,0x1380000,0x1380000,0x3B00000,0x33FC0000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x1780000,0x35FC0000,0x35FC0000,0x35FC0000,0x35FC0000,0x35FC0000,
+0x35FC0000,0x9DF40000,0x9DF40000,0x9DF40000,0xBA000001,0x35FC0000,0x35FC0000,0x35FC0000,0x35FC0000,0x35FC0000,0x35FC0000,0x9DF40000,0x9DF40000,0x9DF40000,0xBA000001,0x9DF40000,0x9DF40000,0x9DF40000,0xBA000001,0xBA000001,0x1900000,0x1780000,0x1780000,0x3B40000,0x1D80000,0x5FC0000,0x5FC0000,0x5BFC0000,0x3B40000,0x1D80000,0x81FC0000,0x9DF40000,
+0x81FC0000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xD1FC0000,0xD1FC0000,0xDE000001,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xD1FC0000,0xD1FC0000,0xDE000001,0xD1FC0000,0xD1FC0000,0xDE000001,0xDE000001,0xA3FC0000,0xA3FC0000,0xA3FC0000,0xD1FC0000,0xD1FC0000,0xDE000001,0xD1FC0000,0xD1FC0000,0xDE000001,0xDE000001,0xD1FC0000,
+0xD1FC0000,0xDE000001,0xDE000001,0xDE000001,0x27FC0000,0x7DC0000,0x1C00000,0x8DFC0000,0xB3FC0000,0xC5FC0000,0xCBFC0000,0xD5FC0000,0x69FC0000,0xA3FC0000,0xC5FC0000,0xDE000001,0xC5FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x19819DD,0xFF801338,0xFF7C0DD1,0xFF740BE8,0xFF740F69,0xFF64088E,0xFF5C05E5,0xFF58068D,0xFD4C0378,0xEF4C0555,0xFF6810D2,0xFF4C0853,0xFF4404DA,0xFF380465,0xFF2C0029,0xF12C0235,0xFF2808DD,0xF51C032E,0xEB1C0319,0xDF2408CA,0x63FC19DB,0xFF380FF4,0xFF300BE8,0xFF1409E9,0xFEFC03ED,0xEF080553,0xFEF00B8E,0xFEC0029E,0xECC401FA,0xDED808CA,0xB3F819DB,
+0xFE580BE8,0xEE280553,0xDC0008D2,0xCA0019DB,0xFF801459,0xFF8C17D1,0xFF8C1891,0xFF700E65,0xFF50086A,0xFF3C02F4,0xFF3400D5,0xFD240006,0xFF7813DA,0xFF5C0D8F,0xFF1C02E2,0xECC401FA,0x9FF819DB,0x1BC08C9,0xFFB005F4,0xFFA00371,0xFF9C0288,0xFFA40569,0xFF9001F8,0xFF840088,0xFF7C0221,0xFB780034,0xEF7801E1,0x9BFC08C9,0xFF7C0473,0xFF6C0288,0xFF580362,0xFF380001,
+0xEF4401E2,0xCFF808C9,0xFED40288,0xEEA801E1,0xDE0008CA,0x9BFC08C9,0xFF7C0473,0xFF6C0288,0xFF580362,0xFF380001,0xEF4401E2,0xCFF808C9,0xFED40288,0xEEA801E1,0xDE0008CA,0xCFF808C9,0xFED40288,0xEEA801E1,0xDE0008CA,0xDE0008CA,0xFFB4074A,0xF5B80845,0xF7BC0849,0xFF9805B9,0xFF7C03C5,0xFF5C0171,0xFF500019,0xFF180001,0xFFA4076A,0xFF90057E,0xFF3002AE,0xEEA801E1,
+0xC1FC08C9,0x1740BE8,0x1740BE8,0x1740BE8,0x1740BE8,0xFF5C05E5,0xFF5C05E5,0xFF5C05E5,0xFB500374,0xFB500374,0xDF4C0375,0xFF4404DA,0xFF4404DA,0xFF4404DA,0xFF2C0029,0xFF2C0029,0xE33000A6,0xEB240288,0xEB240288,0xDB200041,0xCD24028A,0x2FFC0BE8,0x2FFC0BE8,0x2FFC0BE8,0xFEFC03ED,0xFEFC03ED,0xDF180373,0xFEC0029E,0xFEC0029E,0xE0D80002,0xCEE8028A,0x99FC0BE8,
+0x99FC0BE8,0xDE680373,0xCC30028A,0xB8000BEB,0xFF6808CE,0xFF6C0A8D,0x1740BE8,0xFF540625,0xFF440371,0xFF3C0164,0xFF3400D5,0xFB240002,0xFF58089A,0xFF5005B6,0xFF1C02B1,0xE0D80002,0x7FF80BE8,0x19C0288,0x19C0288,0x19C0288,0x19C0288,0xFF840088,0xFF840088,0xFF840088,0xF1780000,0xF1780000,0xDF780001,0x6BFC0288,0x6BFC0288,0x6BFC0288,0xFF380001,0xFF380001,
+0xE1540001,0xB7F80288,0xB7F80288,0xDEE80001,0xCC00028A,0x6BFC0288,0x6BFC0288,0x6BFC0288,0xFF380001,0xFF380001,0xE1540001,0xB7F80288,0xB7F80288,0xDEE80001,0xCC00028A,0xB7F80288,0xB7F80288,0xDEE80001,0xCC00028A,0xCC00028A,0xFF9001E1,0xF5980221,0x19C0288,0xFD840188,0xFF7000DD,0xFF580064,0xFF500019,0xFD200000,0xFD880200,0xFF740171,0xA3FC0288,0xDEE80001,
+0xA3FC0288,0x1E001E1,0xFFD00121,0xFFC80061,0xFFC00000,0xCFFC01E1,0xFFB800AA,0xFFA00001,0xE7FC01E1,0xFF400000,0xEE0001E1,0xCFFC01E1,0xFFB800AA,0xFFA00001,0xE7FC01E1,0xFF400000,0xEE0001E1,0xE7FC01E1,0xFF400000,0xEE0001E1,0xEE0001E1,0xCFFC01E1,0xFFB800AA,0xFFA00001,0xE7FC01E1,0xFF400000,0xEE0001E1,0xE7FC01E1,0xFF400000,0xEE0001E1,0xEE0001E1,0xE7FC01E1,
+0xFF400000,0xEE0001E1,0xEE0001E1,0xEE0001E1,0xFFD001BD,0x7FC01E1,0xF7DC01C4,0xFFC80179,0xFFBC0122,0xFF900092,0xFF640000,0xFF140000,0xFDD801A5,0xFFC00164,0xFF780010,0xEE0001E1,0xE1FC01E1,0x14C0374,0x14C0374,0x14C0374,0x14C0374,0x14C0374,0x14C0374,0x14C0374,0x14C0374,0x14C0374,0x14C0374,0xFF28001D,0xFF28001D,0xFF28001D,0xFF28001D,0xFF28001D,
+0xFF28001D,0xD1240000,0xD1240000,0xD1240000,0xBB240001,0x1F00372,0x1F00372,0x1F00372,0x1F00372,0x1F00372,0x1F00372,0xE0D80001,0xE0D80001,0xE0D80001,0xBAFC0001,0x7DF80372,0x7DF80372,0x7DF80372,0xBA7C0001,0xA6000372,0xFD480288,0x14C0374,0x14C0374,0xFF3C0190,0xFF3400E9,0xFF340071,0xFF340071,0xF9240000,0xFD380244,0xFF34016D,0xE7180000,0xE0D80001,
+0x5BFC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table154[] = {
+0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0x69FC0000,
+0x69FC0000,0x69FC0000,0x69FC0000,0x98000001,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1340000,0x1480000,0x1480000,0x1480000,0x1C80000,0x41FC0000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x4DFC0000,
+0x4DFC0000,0xA7FC0000,0xA7FC0000,0xA7FC0000,0xC2000001,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0x4DFC0000,0xA7FC0000,0xA7FC0000,0xA7FC0000,0xC2000001,0xA7FC0000,0xA7FC0000,0xA7FC0000,0xC2000001,0xC2000001,0x9A00000,0x1880000,0x1880000,0x1C80000,0x1EC0000,0x23FC0000,0x23FC0000,0x6FFC0000,0x1C80000,0x1EC0000,0x91FC0000,0xA7FC0000,
+0x91FC0000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0xBBFC0000,0xBBFC0000,0xBBFC0000,0xDDFC0000,0xDDFC0000,0xE6000001,0xBBFC0000,0xBBFC0000,0xBBFC0000,0xDDFC0000,0xDDFC0000,0xE6000001,0xDDFC0000,0xDDFC0000,0xE6000001,0xE6000001,0xBBFC0000,0xBBFC0000,0xBBFC0000,0xDDFC0000,0xDDFC0000,0xE6000001,0xDDFC0000,0xDDFC0000,0xE6000001,0xE6000001,0xDDFC0000,
+0xDDFC0000,0xE6000001,0xE6000001,0xE6000001,0x5FFC0000,0xFEC0000,0x1D00000,0xABFC0000,0xC7FC0000,0xD5FC0000,0xD9FC0000,0xE1F40000,0x91FC0000,0xBBFC0000,0xD5FC0000,0xE6000001,0xD5FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1A416D1,0xFF981198,0xFF880D5D,0xFF840BE8,0xFF800E01,0xFF740886,0xFF740675,0xFF6405F9,0xFF60037D,0xF35C047D,0xFF740EFE,0xFF64082B,0xFF5C056A,0xFF4C03FE,0xFF40007D,0xF53C016E,0xFF38072E,0xF93002C2,0xEF3001F9,0xE33406EA,0x75FC16CF,0xFF580F0C,0xFF480BE8,0xFF2C0911,0xFF20044D,0xF31C047B,0xFF080A0E,0xFEE402DE,0xF2DC0112,0xE2EC06EA,0xBBFC16CF,
+0xFE880BE8,0xF248047B,0xE20806EA,0xD00016CF,0xFF8C1241,0xF9A0153D,0xF9A015C4,0xFF800D27,0xFF68080D,0xFF54034B,0xFF4C015D,0xFF38000D,0xFF9011EA,0xFF740C8A,0xFF340318,0xF2DC0112,0xA9FC16CF,0x1C806E9,0xFFBC04EC,0xFFAC0331,0xFFAC0288,0xFFB0043D,0xFFA001C2,0xFF9800B9,0xFF940169,0xFD880008,0xF3880109,0xAFFC06E9,0xFF9403DB,0xFF840288,0xFF70028A,0xFF580019,
+0xF358010A,0xD7FC06E9,0xFF040288,0xF2C80109,0xE20006EA,0xAFFC06E9,0xFF9403DB,0xFF840288,0xFF70028A,0xFF580019,0xF358010A,0xD7FC06E9,0xFF040288,0xF2C80109,0xE20006EA,0xD7FC06E9,0xFF040288,0xF2C80109,0xE20006EA,0xE20006EA,0xFFBC05CD,0xFBC4066D,0xFBC40681,0xFFB004A6,0xFF900329,0xFF7C0153,0xFF680041,0xFF380009,0xFFB405D6,0xFFA40482,0xFF5002A1,0xF2C80109,
+0xCDFC06E9,0x1840BE8,0x1840BE8,0x1840BE8,0x1840BE8,0xFF740675,0xFF740675,0xFF740675,0xFF60037D,0xFF60037D,0xE75C0375,0xFF5C056A,0xFF5C056A,0xFF5C056A,0xFF40007D,0xFF40007D,0xEB4000A6,0xF3340288,0xF3340288,0xE3300041,0xD534028A,0x47FC0BE8,0x47FC0BE8,0x47FC0BE8,0xFF20044D,0xFF20044D,0xE7280373,0xFEE402DE,0xFEE402DE,0xE8E80002,0xD6F8028A,0xA5F80BE8,
+0xA5F80BE8,0xE6780373,0xD440028A,0xC0000BEB,0xFF740934,0xF9800AC4,0x1840BE8,0xFF6806BD,0xFF580419,0xFF4C021D,0xFF4C015D,0xFF38000D,0xFD70090C,0xFF5C0656,0xFF3402F4,0xE8E80002,0x8DFC0BE8,0x1AC0288,0x1AC0288,0x1AC0288,0x1AC0288,0xFF9800B9,0xFF9800B9,0xFF9800B9,0xF9880000,0xF9880000,0xE7880001,0x83FC0288,0x83FC0288,0x83FC0288,0xFF580019,0xFF580019,
+0xE9640001,0xC3F80288,0xC3F80288,0xE6F80001,0xD400028A,0x83FC0288,0x83FC0288,0x83FC0288,0xFF580019,0xFF580019,0xE9640001,0xC3F80288,0xC3F80288,0xE6F80001,0xD400028A,0xC3F80288,0xC3F80288,0xE6F80001,0xD400028A,0xD400028A,0xFFA00202,0xFDA80221,0x1AC0288,0xFF9801A5,0xFF84010D,0xFF740091,0xFF680041,0xFF380009,0xFF940212,0xFB9001A5,0xB3FC0288,0xE6F80001,
+0xB3FC0288,0x1E80109,0xFFDC009D,0xFFD80034,0xFFD00000,0xDBFC0109,0xFFCC0064,0xFFB80001,0xEDFC0109,0xFF700000,0xF2000109,0xDBFC0109,0xFFCC0064,0xFFB80001,0xEDFC0109,0xFF700000,0xF2000109,0xEDFC0109,0xFF700000,0xF2000109,0xF2000109,0xDBFC0109,0xFFCC0064,0xFFB80001,0xEDFC0109,0xFF700000,0xF2000109,0xEDFC0109,0xFF700000,0xF2000109,0xF2000109,0xEDFC0109,
+0xFF700000,0xF2000109,0xF2000109,0xF2000109,0xFBE400F2,0x47FC0109,0xFBE400F4,0xFFD800CA,0xFFD000A2,0xFFAC0050,0xFF8C0000,0xFF500000,0xFFDC00E1,0xFFD800C8,0xFF9C0009,0xF2000109,0xE9FC0109,0x15C0374,0x15C0374,0x15C0374,0x15C0374,0x15C0374,0x15C0374,0x15C0374,0x15C0374,0x15C0374,0x15C0374,0xFF3C0034,0xFF3C0034,0xFF3C0034,0xFF3C0034,0xFF3C0034,
+0xFF3C0034,0xD9340000,0xD9340000,0xD9340000,0xC3340001,0xDFC0372,0xDFC0372,0xDFC0372,0xDFC0372,0xDFC0372,0xDFC0372,0xE8E80001,0xE8E80001,0xE8E80001,0xC30C0001,0x89F80372,0x89F80372,0x89F80372,0xC28C0001,0xAE000372,0xF55802AD,0x15C0374,0x15C0374,0xFF4C01B1,0xFD4C0120,0xFF440091,0xFF440091,0xFF340001,0xF94C0265,0xFB4801A5,0xEF280000,0xE8E80001,
+0x69FC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table155[] = {
+0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1E00000,0x1E00000,0x1E00000,0x1E00000,0x1E00000,0x1E00000,0x1E00000,0x1E00000,0x1E00000,0x1E00000,0x75FC0000,
+0x75FC0000,0x75FC0000,0x75FC0000,0xA0000001,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x5580000,0x5580000,0x5580000,0x1E00000,0x51FC0000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x1980000,0x65FC0000,0x65FC0000,0x65FC0000,0x65FC0000,0x65FC0000,
+0x65FC0000,0xB3FC0000,0xB3FC0000,0xB3FC0000,0xCA000001,0x65FC0000,0x65FC0000,0x65FC0000,0x65FC0000,0x65FC0000,0x65FC0000,0xB3FC0000,0xB3FC0000,0xB3FC0000,0xCA000001,0xB3FC0000,0xB3FC0000,0xB3FC0000,0xCA000001,0xCA000001,0x1B40000,0x1980000,0x1980000,0x5D80000,0x7FC0000,0x41FC0000,0x41FC0000,0x83FC0000,0x5D80000,0x7FC0000,0x9FFC0000,0xB3FC0000,
+0x9FFC0000,0x1E00000,0x1E00000,0x1E00000,0x1E00000,0xD3FC0000,0xD3FC0000,0xD3FC0000,0xE9FC0000,0xE9FC0000,0xEE000001,0xD3FC0000,0xD3FC0000,0xD3FC0000,0xE9FC0000,0xE9FC0000,0xEE000001,0xE9FC0000,0xE9FC0000,0xEE000001,0xEE000001,0xD3FC0000,0xD3FC0000,0xD3FC0000,0xE9FC0000,0xE9FC0000,0xEE000001,0xE9FC0000,0xE9FC0000,0xEE000001,0xEE000001,0xE9FC0000,
+0xE9FC0000,0xEE000001,0xEE000001,0xEE000001,0x97FC0000,0x17FC0000,0x1E00000,0xC9FC0000,0xDBFC0000,0xE3FC0000,0xE7F80000,0xEBF80000,0xB7FC0000,0xD3FC0000,0xE3FC0000,0xEE000001,0xE3FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1B01425,0xFFA4102C,0xFF940D09,0xFF940BE8,0xFF980CD1,0xFF840898,0xFF8006ED,0xFF7C05B1,0xFF7003B4,0xF76C03E5,0xFF8C0D6E,0xFF74082B,0xFF68060E,0xFF6403D6,0xFF54010D,0xF95000EA,0xFF4C0601,0xFD44028E,0xF53C011D,0xE944055E,0x87FC1423,0xFF700E44,0xFF600BE8,0xFF4C089F,0xFF3804C5,0xF73003E3,0xFF2008EE,0xFEFC034E,0xF6F00072,0xE900055E,0xC5F81423,
+0xFEB80BE8,0xF66803E3,0xE820055E,0xD6001423,0xFFA0103F,0xFFAC12A9,0xFFAC133C,0xFF940C5A,0xFF7807F2,0xFF6803C5,0xFF5C0214,0xFF48005E,0xFF981017,0xFF800B9F,0xFF50039A,0xF6F00072,0xB5FC1423,0x1D00561,0xFFC40411,0xFFC002F4,0xFFBC0288,0xFFBC0359,0xFFB001B2,0xFFA80104,0xFFA000F1,0xFF980004,0xF7980071,0xBDFC055E,0xFFAC0363,0xFF9C0288,0xFF8801F2,0xFF700049,
+0xF76C0072,0xDFF8055E,0xFF340288,0xF6E80071,0xE800055E,0xBDFC055E,0xFFAC0363,0xFF9C0288,0xFF8801F2,0xFF700049,0xF76C0072,0xDFF8055E,0xFF340288,0xF6E80071,0xE800055E,0xDFF8055E,0xFF340288,0xF6E80071,0xE800055E,0xE800055E,0xFDCC049A,0xFFCC04F5,0xFFCC0519,0xFFC003C4,0xFFA402B5,0xFF90016B,0xFF7C0082,0xFF640032,0xFFC4049D,0xFFB003C2,0xFF700298,0xF6E80071,
+0xD7FC055E,0x1940BE8,0x1940BE8,0x1940BE8,0x1940BE8,0xFF8006ED,0xFF8006ED,0xFF8006ED,0xFF7003B4,0xFF7003B4,0xEF6C0375,0xFF68060E,0xFF68060E,0xFF68060E,0xFF54010D,0xFF54010D,0xF35000A6,0xFB440288,0xFB440288,0xEB400041,0xDD44028A,0x5FFC0BE8,0x5FFC0BE8,0x5FFC0BE8,0xFF3804C5,0xFF3804C5,0xEF380373,0xFEFC034E,0xFEFC034E,0xF0F80002,0xDF08028A,0xB1F80BE8,
+0xB1F80BE8,0xEE880373,0xDC50028A,0xC8000BEB,0xFF84097D,0xFF8C0AD8,0x1940BE8,0xFF80074E,0xFF6C04D1,0xFF6002D9,0xFF5C0214,0xFF48005E,0xFF800956,0xFF7406E1,0xFF500381,0xF0F80002,0x9DF80BE8,0x1BC0288,0x1BC0288,0x1BC0288,0x1BC0288,0xFFA80104,0xFFA80104,0xFFA80104,0xFF980004,0xFF980004,0xEF980001,0x9BFC0288,0x9BFC0288,0x9BFC0288,0xFF700049,0xFF700049,
+0xF1740001,0xCFF80288,0xCFF80288,0xEF080001,0xDC00028A,0x9BFC0288,0x9BFC0288,0x9BFC0288,0xFF700049,0xFF700049,0xF1740001,0xCFF80288,0xCFF80288,0xEF080001,0xDC00028A,0xCFF80288,0xCFF80288,0xEF080001,0xDC00028A,0xDC00028A,0xFBB40221,0xF5B80244,0x1BC0288,0xFFA401D4,0xFF980145,0xFF8C00E1,0xFF7C0082,0xFF640032,0xFDB00221,0xFFA401C2,0xC1FC0288,0xEF080001,
+0xC1FC0288,0x1F00071,0xFFE80041,0xFFE40014,0xFFE00000,0xE9FC0071,0xFFD80028,0xFFD00000,0xF3FC0071,0xFFA00000,0xF6000071,0xE9FC0071,0xFFD80028,0xFFD00000,0xF3FC0071,0xFFA00000,0xF6000071,0xF3FC0071,0xFFA00000,0xF6000071,0xF6000071,0xE9FC0071,0xFFD80028,0xFFD00000,0xF3FC0071,0xFFA00000,0xF6000071,0xF3FC0071,0xFFA00000,0xF6000071,0xF6000071,0xF3FC0071,
+0xFFA00000,0xF6000071,0xF6000071,0xF6000071,0xFFEC0062,0x87FC0071,0xFFEC0064,0xFDE80055,0xFDE40048,0xFFC8001D,0xFFB40000,0xFF8C0000,0xFDEC0062,0xFFE40055,0xFFBC0004,0xF6000071,0xF1FC0071,0x16C0374,0x16C0374,0x16C0374,0x16C0374,0x16C0374,0x16C0374,0x16C0374,0x16C0374,0x16C0374,0x16C0374,0xFF500055,0xFF500055,0xFF500055,0xFF500055,0xFF500055,
+0xFF500055,0xE1440000,0xE1440000,0xE1440000,0xCB440001,0x25FC0372,0x25FC0372,0x25FC0372,0x25FC0372,0x25FC0372,0x25FC0372,0xF0F80001,0xF0F80001,0xF0F80001,0xCB1C0001,0x95F80372,0x95F80372,0x95F80372,0xCA9C0001,0xB6000372,0xFD6802AD,0x16C0374,0x16C0374,0xFD6401E1,0xFF580145,0xFF5400B9,0xFF5400B9,0xFF48000D,0xFF580271,0xFF5001BD,0xF7380000,0xF0F80001,
+0x79FC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table156[] = {
+0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x1FC0000,0x83F80000,
+0x83F80000,0x83F80000,0x83F80000,0xAA000000,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x1540001,0x16C0000,0x16C0000,0x16C0000,0x1FC0000,0x61FC0000,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,
+0x81FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xD4000000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0x81FC0000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xD4000000,0xC1FC0000,0xC1FC0000,0xC1FC0000,0xD4000000,0xD4000000,0xBC40000,0x1A80001,0x1A80001,0x1F00000,0x33FC0000,0x63FC0000,0x63FC0000,0x99FC0000,0x1F00000,0x33FC0000,0xB1FC0000,0xC1FC0000,
+0xB1FC0000,0x1F00001,0x1F00001,0x1F00001,0x1F00001,0xEFFC0000,0xEFFC0000,0xEFFC0000,0xF7F80000,0xF7F80000,0xF8000000,0xEFFC0000,0xEFFC0000,0xEFFC0000,0xF7F80000,0xF7F80000,0xF8000000,0xF7F80000,0xF7F80000,0xF8000000,0xF8000000,0xEFFC0000,0xEFFC0000,0xEFFC0000,0xF7F80000,0xF7F80000,0xF8000000,0xF7F80000,0xF7F80000,0xF8000000,0xF8000000,0xF7F80000,
+0xF7F80000,0xF8000000,0xF8000000,0xF8000000,0xD7FC0000,0xA7FC0000,0x1F00001,0xEBFC0000,0xF1FC0000,0xF5FC0000,0xF5FC0000,0xF7FC0000,0xE3FC0000,0xEFFC0000,0xF5FC0000,0xF8000000,0xF5FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1BC1194,0xFFB00ED7,0xFFAC0CAC,0xFFA40BEB,0xFFA40BBE,0xFF9808C3,0xFF9807A2,0xFF8805A4,0xFF88043B,0xFB800386,0xFF980C15,0xFF8C0852,0xFF8006C9,0xFF7003FF,0xFF6C01EE,0xFD6400A9,0xFF64052C,0xFF58029B,0xF950007E,0xEF540409,0x9BFC1194,0xFF880D81,0xFF7C0BE8,0xFF64083E,0xFF58058D,0xFD440386,0xFF380829,0xFF2003F9,0xFB080015,0xEF140408,0xCFF81194,
+0xFEF00BE8,0xFA8C0386,0xEE400408,0xDC001198,0xFFB40EBF,0xF5B810AC,0xF7BC1114,0xFF980B8A,0xFF8C0803,0xFF7C0476,0xFF78030B,0xFF640105,0xFDB00E9B,0xFF980AFA,0xFF640451,0xFB080015,0xC1FC1194,0x1DC040B,0xFFD4035E,0xFFCC02CA,0xFFCC028A,0xFFD0029B,0xFFC401B6,0xFFBC0151,0xFFB800C3,0xFFAC0032,0xFBA80015,0xCFFC0408,0xFFC002FE,0xFFB80288,0xFFA00196,0xFF94009D,
+0xFB840014,0xE7FC0408,0xFF6C0288,0xFB0C0014,0xEE000408,0xCFFC0408,0xFFC002FE,0xFFB80288,0xFFA00196,0xFF94009D,0xFB840014,0xE7FC0408,0xFF6C0288,0xFB0C0014,0xEE000408,0xE7FC0408,0xFF6C0288,0xFB0C0014,0xEE000408,0xEE000408,0xFFD80385,0xF7DC03D5,0xF7DC03EA,0xFDD00321,0xFFC0025A,0xFFA80179,0xFFA000DA,0xFF7C0082,0xFFD00395,0xFFC802E4,0xFF980291,0xFB0C0014,
+0xE1FC0408,0x1A40BEB,0x1A40BEB,0x1A40BEB,0x1A40BEB,0xFF9807A2,0xFF9807A2,0xFF9807A2,0xFF88043B,0xFF88043B,0xF9800372,0xFF8006C9,0xFF8006C9,0xFF8006C9,0xFF6C01EE,0xFF6C01EE,0xFD6400A5,0xFF58029B,0xFF58029B,0xF5540042,0xE7540289,0x7BFC0BE8,0x7BFC0BE8,0x7BFC0BE8,0xFF58058D,0xFF58058D,0xF9480372,0xFF2003F9,0xFF2003F9,0xF9080005,0xE71C0288,0xBFF80BE8,
+0xBFF80BE8,0xF8940372,0xE6600288,0xD2000BE8,0xFFA009E1,0xFBA40B0A,0x1A40BEB,0xFF9007E6,0xFF8005BA,0xFF7803C3,0xFF78030B,0xFF640105,0xFF9409A4,0xFF8007C1,0xFF640438,0xF9080005,0xADFC0BE8,0x1CC028A,0x1CC028A,0x1CC028A,0x1CC028A,0xFFBC0151,0xFFBC0151,0xFFBC0151,0xFFAC0032,0xFFAC0032,0xF9A80001,0xB7FC0288,0xB7FC0288,0xB7FC0288,0xFF94009D,0xFF94009D,
+0xF9880000,0xDDF40288,0xDDF40288,0xF9140000,0xE6000288,0xB7FC0288,0xB7FC0288,0xB7FC0288,0xFF94009D,0xFF94009D,0xF9880000,0xDDF40288,0xDDF40288,0xF9140000,0xE6000288,0xDDF40288,0xDDF40288,0xF9140000,0xE6000288,0xE6000288,0xFDC80242,0xFFCC0242,0x1CC028A,0xFDC00202,0xFFAC0195,0xFFA80128,0xFFA000DA,0xFF7C0082,0xFFC40242,0xFBC00200,0xD3FC0288,0xF9140000,
+0xD3FC0288,0x1F80012,0xFFF4000A,0xFFF00005,0xFFF00001,0xF7FC0012,0xFFF00005,0xFFEC0000,0xFBFC0012,0xFFD80000,0xFA000014,0xF7FC0012,0xFFF00005,0xFFEC0000,0xFBFC0012,0xFFD80000,0xFA000014,0xFBFC0012,0xFFD80000,0xFA000014,0xFA000014,0xF7FC0012,0xFFF00005,0xFFEC0000,0xFBFC0012,0xFFD80000,0xFA000014,0xFBFC0012,0xFFD80000,0xFA000014,0xFA000014,0xFBFC0012,
+0xFFD80000,0xFA000014,0xFA000014,0xFA000014,0xFFF8000D,0xD7FC0012,0xF5F80012,0xFFF4000D,0xFDF4000D,0xFFE80005,0xFFE00000,0xFFD00000,0xF5FC0012,0xFFF00011,0xFFE40001,0xFA000014,0xFBFC0012,0x1800372,0x1800372,0x1800372,0x1800372,0x1800372,0x1800372,0x1800372,0x1800372,0x1800372,0x1800372,0xFF680091,0xFF680091,0xFF680091,0xFF680091,0xFF680091,
+0xFF680091,0xE9580001,0xE9580001,0xE9580001,0xD5540001,0x41FC0372,0x41FC0372,0x41FC0372,0x41FC0372,0x41FC0372,0x41FC0372,0xFB080001,0xFB080001,0xFB080001,0xD52C0000,0xA1FC0372,0xA1FC0372,0xA1FC0372,0xD4A80000,0xBE000374,0xF77C02D2,0x1800372,0x1800372,0xFF740202,0xFF6C0179,0xFF6800FA,0xFF6800FA,0xFF5C002D,0xFD70028A,0xFF6401F9,0xFD4C0001,0xFB080001,
+0x89FC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table157[] = {
+0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x19FC0000,0x8FF80000,
+0x8FF80000,0x8FF80000,0x8FF80000,0xB2000000,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x1640001,0x77C0000,0x77C0000,0x77C0000,0x19FC0000,0x71FC0000,0x1B80001,0x1B80001,0x1B80001,0x1B80001,0x1B80001,0x1B80001,0x1B80001,0x1B80001,0x1B80001,0x1B80001,0x99FC0000,0x99FC0000,0x99FC0000,0x99FC0000,0x99FC0000,
+0x99FC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xDC000000,0x99FC0000,0x99FC0000,0x99FC0000,0x99FC0000,0x99FC0000,0x99FC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xDC000000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xDC000000,0xDC000000,0x1D80000,0x1B80001,0x1B80001,0x11FC0000,0x5BFC0000,0x81FC0000,0x81FC0000,0xADFC0000,0x11FC0000,0x5BFC0000,0xBFFC0000,0xCDFC0000,
+0xBFFC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1C80F44,0xFFBC0D5F,0xFFB80BD4,0xFFB40B53,0xFFB00ABA,0xFFA4089F,0xFFA407BE,0xFFA005B4,0xFF94049B,0xFF900372,0xFFA40AD9,0xFF980816,0xFF9806F5,0xFF880417,0xFF7C0296,0xFF7400C1,0xFF7C0494,0xFF7002A3,0xFD64003A,0xF3640305,0xABFC0F44,0xFF940C75,0xFF900B53,0xFF7C07D6,0xFF7005E5,0xFF580374,0xFF580773,0xFF380455,0xFF200005,0xF3280304,0xD7F80F44,
+0xFF1C0B53,0xFEAC0372,0xF2600304,0xE2000F44,0xFFBC0CF6,0xFBC40E6C,0xFBC40EDC,0xFFAC0A8E,0xFF9C07CB,0xFF9004FA,0xFF8803B2,0xFF7401A6,0xFFB40CB7,0xFFA40A4C,0xFF780483,0xFF200005,0xCBFC0F44,0x1E80303,0xFFE002AE,0xFFE00263,0xFFDC0242,0xFFDC0213,0xFFD0019A,0xFFD0015A,0xFFC000D1,0xFFC0006D,0xFFB80001,0xDFFC0303,0xFFCC0282,0xFFCC0242,0xFFB80156,0xFFAC00CD,
+0xFF980000,0xEFFC0303,0xFF940242,0xFF2C0000,0xF2000304,0xDFFC0303,0xFFCC0282,0xFFCC0242,0xFFB80156,0xFFAC00CD,0xFF980000,0xEFFC0303,0xFF940242,0xFF2C0000,0xF2000304,0xEFFC0303,0xFF940242,0xFF2C0000,0xF2000304,0xF2000304,0xFFE402C1,0xFBE402D9,0xFDE802EE,0xFFDC025D,0xFFD40202,0xFFB80171,0xFFB80104,0xFFA000B4,0xFFDC02BD,0xFFDC025A,0xFFB40246,0xFF2C0000,
+0xEBFC0303,0x1B40B53,0x1B40B53,0x1B40B53,0x1B40B53,0xFFA407BE,0xFFA407BE,0xFFA407BE,0xFF94049B,0xFF94049B,0xFF900372,0xFF9806F5,0xFF9806F5,0xFF9806F5,0xFF7C0296,0xFF7C0296,0xFF7400C1,0xFF7002A3,0xFF7002A3,0xFB600032,0xED640245,0x8FFC0B53,0x8FFC0B53,0x8FFC0B53,0xFF7005E5,0xFF7005E5,0xFF580374,0xFF380455,0xFF380455,0xFF200005,0xED2C0244,0xC9F80B53,
+0xC9F80B53,0xFEAC0372,0xEC780244,0xDA000B54,0xFFAC09A2,0xFFAC0A9E,0x1B40B53,0xFFA4081B,0xFF940612,0xFF900481,0xFF8803B2,0xFF7401A6,0xFFA0097D,0xFF9807C5,0xFF780473,0xFF200005,0xBBFC0B53,0x1DC0242,0x1DC0242,0x1DC0242,0x1DC0242,0xFFD0015A,0xFFD0015A,0xFFD0015A,0xFFC0006D,0xFFC0006D,0xFFB80001,0xCDFC0242,0xCDFC0242,0xCDFC0242,0xFFAC00CD,0xFFAC00CD,
+0xFF980000,0xE7F80242,0xE7F80242,0xFF2C0000,0xEC000244,0xCDFC0242,0xCDFC0242,0xCDFC0242,0xFFAC00CD,0xFFAC00CD,0xFF980000,0xE7F80242,0xE7F80242,0xFF2C0000,0xEC000244,0xE7F80242,0xE7F80242,0xFF2C0000,0xEC000244,0xEC000244,0xFFD80200,0xF7DC0221,0x1DC0242,0xFBD401E1,0xFFC80190,0xFFB80140,0xFFB80104,0xFFA000B4,0xFFD00208,0xFFC801D4,0xDFFC0242,0xFF2C0000,
+0xDFFC0242,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1900372,0x1900372,0x1900372,0x1900372,0x1900372,0x1900372,0x1900372,0x1900372,0x1900372,0x1900372,0xFF7400C1,0xFF7400C1,0xFF7400C1,0xFF7400C1,0xFF7400C1,
+0xFF7400C1,0xF1680001,0xF1680001,0xF1680001,0xDD640001,0x59FC0372,0x59FC0372,0x59FC0372,0x59FC0372,0x59FC0372,0x59FC0372,0xFF200005,0xFF200005,0xFF200005,0xDD3C0000,0xADFC0372,0xADFC0372,0xADFC0372,0xDCB80000,0xC6000374,0xFF8C02D2,0x1900372,0x1900372,0xFF840225,0xFF8001A9,0xFF780132,0xFF780132,0xFF700059,0xF98402AD,0xFF780212,0xFF60000D,0xFF200005,
+0x99FC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table158[] = {
+0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x31FC0000,0x9BF80000,
+0x9BF80000,0x9BF80000,0x9BF80000,0xBA000000,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0x1740001,0xF8C0000,0xF8C0000,0xF8C0000,0x31FC0000,0x7FFC0000,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0x1C80001,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xB1FC0000,
+0xB1FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xE4000000,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xB1FC0000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xE4000000,0xD9FC0000,0xD9FC0000,0xD9FC0000,0xE4000000,0xE4000000,0x1E80000,0x1C80001,0x1C80001,0x49FC0000,0x81FC0000,0x9FFC0000,0x9FFC0000,0xC1FC0000,0x49FC0000,0x81FC0000,0xCFFC0000,0xD9FC0000,
+0xCFFC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1D00C14,0xFFC40AAC,0xFFC00997,0xFFC00933,0xFFBC08C2,0xFFB4073B,0xFFB00696,0xFFAC050C,0xFFA00453,0xFFA00372,0xFFB00891,0xFFA40686,0xFFA405A5,0xFF940387,0xFF900266,0xFF8C0109,0xFF880354,0xFF7C01DB,0xFF74000A,0xF77401C5,0xB7FC0C14,0xFFAC09FD,0xFFA00934,0xFF8806A6,0xFF7C053D,0xFF700374,0xFF7005BB,0xFF58036A,0xFF380025,0xF73C01C4,0xDDF40C14,
+0xFF400933,0xFEE00372,0xF68001C4,0xE6000C14,0xFFC40A74,0xFFCC0B5C,0xFFCC0BBC,0xFFBC089D,0xFFAC066B,0xFF98043E,0xFF900351,0xFF840195,0xFFBC0A41,0xFFB00837,0xFF9003AD,0xFF380025,0xD3FC0C14,0x1EC01C3,0xFFE8018B,0xFFE40162,0xFFE40152,0xFFE00141,0xFFDC00EE,0xFFDC00CA,0xFFD80079,0xFFCC0041,0xFFC80001,0xE5FC01C3,0xFFD80176,0xFFD80152,0xFFCC00D1,0xFFB8007D,
+0xFFB00000,0xF3F801C3,0xFFAC0152,0xFF600000,0xF60001C4,0xE5FC01C3,0xFFD80176,0xFFD80152,0xFFCC00D1,0xFFB8007D,0xFFB00000,0xF3F801C3,0xFFAC0152,0xFF600000,0xF60001C4,0xF3F801C3,0xFFAC0152,0xFF600000,0xF60001C4,0xF60001C4,0xFBEC01A1,0xFFEC01A1,0xFFEC01B2,0xFFDC016D,0xFFDC0125,0xFFD000E3,0xFFC8009D,0xFFB8006A,0xF9EC01A1,0xFFDC015A,0xFFC80156,0xFF600000,
+0xEFFC01C3,0x1C00933,0x1C00933,0x1C00933,0x1C00933,0xFFB00696,0xFFB00696,0xFFB00696,0xFFA00453,0xFFA00453,0xFFA00372,0xFFA405A5,0xFFA405A5,0xFFA405A5,0xFF900266,0xFF900266,0xFF8C0109,0xFF7C01DB,0xFF7C01DB,0xFD740009,0xF1740155,0xA3FC0933,0xA3FC0933,0xA3FC0933,0xFF7C053D,0xFF7C053D,0xFF700374,0xFF58036A,0xFF58036A,0xFF380025,0xF1400154,0xD1FC0933,
+0xD1FC0933,0xFEE00372,0xF0980154,0xDE000934,0xFFBC07F2,0xF7BC08BB,0x1C00933,0xFFAC06AE,0xFFA00542,0xFF9803DA,0xFF900351,0xFF840195,0xFFB407AE,0xFFB0067E,0xFF9003A4,0xFF380025,0xC5FC0933,0x1E40152,0x1E40152,0x1E40152,0x1E40152,0xFFDC00CA,0xFFDC00CA,0xFFDC00CA,0xFFCC0041,0xFFCC0041,0xFFC80001,0xD9FC0152,0xD9FC0152,0xD9FC0152,0xFFB8007D,0xFFB8007D,
+0xFFB00000,0xEDF80152,0xEDF80152,0xFF600000,0xF0000154,0xD9FC0152,0xD9FC0152,0xD9FC0152,0xFFB8007D,0xFFB8007D,0xFFB00000,0xEDF80152,0xEDF80152,0xFF600000,0xF0000154,0xEDF80152,0xEDF80152,0xFF600000,0xF0000154,0xF0000154,0xF7E40139,0xFBE40139,0x1E40152,0xFFDC0109,0xFFD400E1,0xFFD000CA,0xFFC8009D,0xFFB8006A,0xF5E40139,0xFFDC0109,0xE7FC0152,0xFF600000,
+0xE7FC0152,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1A00372,0x1A00372,0x1A00372,0x1A00372,0x1A00372,0x1A00372,0x1A00372,0x1A00372,0x1A00372,0x1A00372,0xFF8C0109,0xFF8C0109,0xFF8C0109,0xFF8C0109,0xFF8C0109,
+0xFF8C0109,0xF9780001,0xF9780001,0xF9780001,0xE5740001,0x71FC0372,0x71FC0372,0x71FC0372,0x71FC0372,0x71FC0372,0x71FC0372,0xFF380025,0xFF380025,0xFF380025,0xE54C0000,0xB9FC0372,0xB9FC0372,0xB9FC0372,0xE4C80000,0xCE000374,0xF79C02F9,0x1A00372,0x1A00372,0xFF900262,0xFF9401E1,0xFF90016D,0xFF90016D,0xFF800092,0xFF9002B9,0xFD900244,0xFF74002D,0xFF380025,
+0xA7FC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table159[] = {
+0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x49FC0000,0x49FC0000,0x49FC0000,0x49FC0000,0x49FC0000,0x49FC0000,0x49FC0000,0x49FC0000,0x49FC0000,0x49FC0000,0xA7F80000,
+0xA7F80000,0xA7F80000,0xA7F80000,0xC2000000,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1840001,0x1A00000,0x1A00000,0x1A00000,0x49FC0000,0x8FFC0000,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0x1D80001,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xC9FC0000,
+0xC9FC0000,0xE5F80000,0xE5F80000,0xE5F80000,0xEC000000,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xC9FC0000,0xE5F80000,0xE5F80000,0xE5F80000,0xEC000000,0xE5F80000,0xE5F80000,0xE5F80000,0xEC000000,0xEC000000,0x5F80000,0x1D80001,0x1D80001,0x83FC0000,0xA9FC0000,0xBDFC0000,0xBDFC0000,0xD3FC0000,0x83FC0000,0xA9FC0000,0xDFF80000,0xE5F80000,
+0xDFF80000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1D80964,0xFFD00864,0xFFCC07AB,0xFFC8076B,0xFFC4070C,0xFFC40607,0xFFBC059E,0xFFB80484,0xFFB4040A,0xFFB00372,0xFFC40694,0xFFB40543,0xFFB0049D,0xFFAC031F,0xFFA0024E,0xFF980151,0xFF940274,0xFF940153,0xFF880002,0xF98400D9,0xC3FC0964,0xFFB807ED,0xFFB00768,0xFFA00596,0xFF9404A5,0xFF880374,0xFF880463,0xFF7002BA,0xFF580061,0xF95000D8,0xE1FC0964,
+0xFF600768,0xFF100372,0xF8A800D8,0xEA000964,0xFFCC082B,0xF3D4091A,0xF5D8093F,0xFFC406CC,0xFFB4054F,0xFFAC03A2,0xFFA40306,0xFF9C019B,0xFFD0080D,0xFFC406A4,0xFF9C02F7,0xFF580061,0xDBFC0964,0x1F000DB,0xFDF000C3,0xFFEC00AB,0xFFEC00A2,0xFFE80093,0xFFE80072,0xFFE80062,0xFFE40039,0xFFE00022,0xFFD80001,0xEFFC00D8,0xFFE400B2,0xFFE400A2,0xFFD80061,0xFFD8003D,
+0xFFC80000,0xF7F800D8,0xFFC800A2,0xFF900000,0xF80000D8,0xEFFC00D8,0xFFE400B2,0xFFE400A2,0xFFD80061,0xFFD8003D,0xFFC80000,0xF7F800D8,0xFFC800A2,0xFF900000,0xF80000D8,0xF7F800D8,0xFFC800A2,0xFF900000,0xF80000D8,0xF80000D8,0xFDF000C1,0xFFEC00D1,0xF1F000DB,0xFFEC00AE,0xFFE80092,0xFFE0006B,0xFFD80050,0xFFD00034,0xFBF000C1,0xFFE800A6,0xFFD800A3,0xFF900000,
+0xF5FC00D8,0x1C8076B,0x1C8076B,0x1C8076B,0x1C8076B,0xFFBC059E,0xFFBC059E,0xFFBC059E,0xFFB4040A,0xFFB4040A,0xFFB00372,0xFFB0049D,0xFFB0049D,0xFFB0049D,0xFFA0024E,0xFFA0024E,0xFF980151,0xFF940153,0xFF940153,0xFF880002,0xF58400A5,0xB1FC0768,0xB1FC0768,0xB1FC0768,0xFF9404A5,0xFF9404A5,0xFF880374,0xFF7002BA,0xFF7002BA,0xFF580061,0xF55400A4,0xD9FC0768,
+0xD9FC0768,0xFF100372,0xF4B800A4,0xE4000768,0xFBC40683,0xFDC80703,0x1C8076B,0xFFBC057D,0xFFB4046E,0xFFAC0362,0xFFA40306,0xFF9C019B,0xFFBC0651,0xFFB4055B,0xFF9C02EE,0xFF580061,0xCFFC0768,0x1EC00A2,0x1EC00A2,0x1EC00A2,0x1EC00A2,0xFFE80062,0xFFE80062,0xFFE80062,0xFFE00022,0xFFE00022,0xFFD80001,0xE5FC00A2,0xE5FC00A2,0xE5FC00A2,0xFFD8003D,0xFFD8003D,
+0xFFC80000,0xF3F800A2,0xF3F800A2,0xFF900000,0xF40000A4,0xE5FC00A2,0xE5FC00A2,0xE5FC00A2,0xFFD8003D,0xFFD8003D,0xFFC80000,0xF3F800A2,0xF3F800A2,0xFF900000,0xF40000A4,0xF3F800A2,0xF3F800A2,0xFF900000,0xF40000A4,0xF40000A4,0xFBEC0091,0xFFEC0091,0x1EC00A2,0xF9EC0091,0xFFDC0074,0xFFD80061,0xFFD80050,0xFFD00034,0xF9EC0091,0xFDE40082,0xEFFC00A2,0xFF900000,
+0xEFFC00A2,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1B00372,0x1B00372,0x1B00372,0x1B00372,0x1B00372,0x1B00372,0x1B00372,0x1B00372,0x1B00372,0x1B00372,0xFF980151,0xFF980151,0xFF980151,0xFF980151,0xFF980151,
+0xFF980151,0xFF880002,0xFF880002,0xFF880002,0xED840001,0x89FC0372,0x89FC0372,0x89FC0372,0x89FC0372,0x89FC0372,0x89FC0372,0xFF580061,0xFF580061,0xFF580061,0xED5C0000,0xC5FC0372,0xC5FC0372,0xC5FC0372,0xECD80000,0xD6000374,0xFFAC02F9,0x1B00372,0x1B00372,0xFDA8028A,0xFFA00212,0xFF9801BA,0xFF9801BA,0xFF9400DA,0xFFA002E4,0xFFA00269,0xFF88007D,0xFF580061,
+0xB7FC0372,};
+static const uint32_t g_etc1_to_bc7_m6_table160[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x300000,0x300000,0x300000,0x300000,0x2440000,0x2440000,0x2440000,0x8C0000,0x8C0000,0x16000001,0x2440000,0x2440000,0x2440000,0x8C0000,0x8C0000,0x16000001,0x8C0000,0x8C0000,0x16000001,0x16000001,0x2440000,0x2440000,0x2440000,0x8C0000,0x8C0000,0x16000001,0x8C0000,0x8C0000,0x16000001,0x16000001,0x8C0000,
+0x8C0000,0x16000001,0x16000001,0x16000001,0x380000,0x340000,0x300000,0x400000,0x500000,0x640000,0x740000,0xAC0000,0x3C0000,0x2440000,0x640000,0x16000001,0x640000,0xA00000,0xEC0000,0x1E40000,0x4E000001,0xEC0000,0x1E40000,0x4E000001,0x1E40000,0x4E000001,0x4E000001,0xEC0000,0x1E40000,0x4E000001,0x1E40000,0x4E000001,
+0x4E000001,0x1E40000,0x4E000001,0x4E000001,0x4E000001,0xEC0000,0x1E40000,0x4E000001,0x1E40000,0x4E000001,0x4E000001,0x1E40000,0x4E000001,0x4E000001,0x4E000001,0x1E40000,0x4E000001,0x4E000001,0x4E000001,0x4E000001,0xC80000,0xCA80000,0xCA80000,0x10C0000,0x1880000,0x25F00000,0x4E000001,0x4E000001,0xD80000,0x12C0000,0x45DC0000,0x4E000001,
+0x1540000,0x3410B0,0xE2100180,0x72100180,0x4E100181,0x9C000620,0x6E0000A9,0x4E000005,0x4C000620,0x4400025D,0x32000622,0x6A000D2B,0x620004E9,0x46000263,0x46000851,0x3C00041A,0x30000732,0x32000D2C,0x32000831,0x2C000A06,0x22000D2B,0x4C10B0,0x4C0007F3,0x4000045C,0x3A000A12,0x3A00058B,0x2E000814,0x2E000E21,0x2C000952,0x26000ABF,0x22000DA4,0x9810B0,
+0x26000BDD,0x20000CBA,0x1C000EF4,0x180010B4,0xFE0004A0,0xFA240B7A,0xFE2C0B05,0x9E000409,0x62000449,0x4C00041A,0x440002DE,0x36000555,0xD0000776,0x7C00058B,0x3E00065B,0x26000ABF,0x6C10B0,0x440D2C,0xDA180120,0x70180120,0x4E180121,0x9C000620,0x6E0000A9,0x4E000005,0x4C000620,0x4400025D,0x32000622,0x680D2B,0x620004E9,0x46000263,0x46000851,0x3C00041A,
+0x30000732,0xD00D2B,0x32000831,0x2C000A06,0x22000D2B,0x680D2B,0x620004E9,0x46000263,0x46000851,0x3C00041A,0x30000732,0xD00D2B,0x32000831,0x2C000A06,0x22000D2B,0xD00D2B,0x32000831,0x2C000A06,0x22000D2B,0x22000D2B,0xFE0004A0,0xFE2C09C6,0xF63C08B8,0x9E000409,0x62000449,0x4C00041A,0x440002DE,0x36000555,0xD00006CD,0x7C00054B,0x3E00064B,0x2C000A06,
+0x940D2B,0x100180,0x100180,0x100180,0x100180,0x48000000,0x48000000,0x48000000,0x22000000,0x22000000,0x16000001,0x24000120,0x24000120,0x24000120,0x1E00006D,0x1E00006D,0x1400003A,0x10000122,0x10000122,0x100000AA,0xA000122,0x180180,0x180180,0x180180,0x180000B1,0x180000B1,0x12000061,0xE000141,0xE000141,0xE0000CE,0xA000132,0x2C0180,
+0x2C0180,0xA00010B,0xA000153,0x6000183,0x84000059,0xFA04002C,0x100180,0x42000075,0x3200006D,0x2200006A,0x2200005A,0x16000082,0x420000C5,0x3200009E,0x16000121,0xE0000CE,0x200180,0x180120,0x180120,0x180120,0x180120,0x48000000,0x48000000,0x48000000,0x22000000,0x22000000,0x16000001,0x240120,0x240120,0x240120,0x1E00006D,0x1E00006D,
+0x1400003A,0x440120,0x440120,0x100000AA,0xA000122,0x240120,0x240120,0x240120,0x1E00006D,0x1E00006D,0x1400003A,0x440120,0x440120,0x100000AA,0xA000122,0x440120,0x440120,0x100000AA,0xA000122,0xA000122,0x84000059,0xFC080020,0x180120,0x42000075,0x3200006D,0x2200006A,0x2200005A,0x16000082,0x560000B4,0x32000095,0x300120,0x100000AA,
+0x300120,0x680620,0xC2300000,0x6A300000,0x4E300001,0x2980620,0x6E0000A9,0x4E000005,0x1380620,0x4400025D,0x32000622,0x2980620,0x6E0000A9,0x4E000005,0x1380620,0x4400025D,0x32000622,0x1380620,0x4400025D,0x32000622,0x32000622,0x2980620,0x6E0000A9,0x4E000005,0x1380620,0x4400025D,0x32000622,0x1380620,0x4400025D,0x32000622,0x32000622,0x1380620,
+0x4400025D,0x32000622,0x32000622,0x32000622,0xFE140320,0xE6C0620,0xF65C039D,0xA6000220,0x6A000269,0x54000249,0x46000195,0x3E000305,0xF2000352,0x8C0002A8,0x4C000161,0x32000622,0xDC0620,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table161[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x400000,0x400000,0x400000,0x400000,0x25C0000,0x25C0000,0x25C0000,0xBC0000,0xBC0000,0x1E000001,0x25C0000,0x25C0000,0x25C0000,0xBC0000,0xBC0000,0x1E000001,0xBC0000,0xBC0000,0x1E000001,0x1E000001,0x25C0000,0x25C0000,0x25C0000,0xBC0000,0xBC0000,0x1E000001,0xBC0000,0xBC0000,0x1E000001,0x1E000001,0xBC0000,
+0xBC0000,0x1E000001,0x1E000001,0x1E000001,0x4480000,0x440000,0x400000,0x2540000,0x6C0000,0x880000,0x9C0000,0xE80000,0x500000,0x25C0000,0x880000,0x1E000001,0x880000,0xB00000,0x1040000,0x7FC0000,0x56000001,0x1040000,0x7FC0000,0x56000001,0x7FC0000,0x56000001,0x56000001,0x1040000,0x7FC0000,0x56000001,0x7FC0000,0x56000001,
+0x56000001,0x7FC0000,0x56000001,0x56000001,0x56000001,0x1040000,0x7FC0000,0x56000001,0x7FC0000,0x56000001,0x56000001,0x7FC0000,0x56000001,0x56000001,0x56000001,0x7FC0000,0x56000001,0x56000001,0x56000001,0x56000001,0xDC0000,0xBC0000,0xBC0000,0x1280000,0x1AC0000,0x2FF00000,0x56000001,0x56000001,0xF00000,0x1480000,0x4DEC0000,0x56000001,
+0x1740000,0x3C1430,0xF61402AC,0x7C1402AD,0x561402AD,0xB6000620,0x7A000059,0x5600000A,0x58000620,0x4A0001ED,0x3A000622,0x78000F80,0x680005A9,0x5200030B,0x4C000911,0x46000432,0x3A00078B,0x3A000F80,0x38000989,0x32000B46,0x26000F83,0x581430,0x580009AB,0x4C00058C,0x46000B62,0x40000613,0x340008C4,0x340010D1,0x38000AF2,0x2C000C47,0x2400102B,0xB01430,
+0x2C000E45,0x26000EDA,0x200011F7,0x1C001434,0xFC080612,0xFE2C0E0A,0xFE2C0E55,0xA6000431,0x76000461,0x5A000421,0x480002C3,0x420005B3,0xD0000856,0x8600061A,0x46000791,0x2C000C47,0x7C1430,0x500F80,0xEA200200,0x7A200200,0x56200201,0xB6000620,0x7A000059,0x58040006,0x58000620,0x4A0001ED,0x3A000622,0x2740F80,0x680005A9,0x5200030B,0x4C000911,0x46000432,
+0x3A00078B,0xF00F80,0x38000989,0x32000B46,0x26000F83,0x2740F80,0x680005A9,0x5200030B,0x4C000911,0x46000432,0x3A00078B,0xF00F80,0x38000989,0x32000B46,0x26000F83,0xF00F80,0x38000989,0x32000B46,0x26000F83,0x26000F83,0xFE0C05F6,0xF63C0BA4,0xFC480AC4,0xA6000431,0x76000461,0x5A000421,0x480002C3,0x420005B3,0xD00007AD,0x900005D9,0x46000781,0x32000B46,
+0xA80F80,0x1402AC,0x1402AC,0x1402AC,0x1402AC,0x60000000,0x60000000,0x60000000,0x2E000000,0x2E000000,0x1E000001,0x30000200,0x30000200,0x30000200,0x220000B9,0x220000B9,0x1E000065,0x16000202,0x16000202,0x16000132,0xE000202,0x2002AB,0x2002AB,0x2002AB,0x22000132,0x22000132,0x180000B1,0x12000236,0x12000236,0x1400016E,0xE00021B,0x3C02AB,
+0x3C02AB,0x100001D3,0xA000263,0xA0002AB,0xB600009D,0xFE0C00AC,0x1402AC,0x5C0000DA,0x3C0000C1,0x2E0000C1,0x2A00009D,0x220000E8,0x64000161,0x44000125,0x1E000204,0x1400016E,0x2C02AB,0x200200,0x200200,0x200200,0x200200,0x60000000,0x60000000,0x60000000,0x2E000000,0x2E000000,0x1E000001,0x300200,0x300200,0x300200,0x220000B9,0x220000B9,
+0x1E000065,0x5C0200,0x5C0200,0x16000132,0xE000202,0x300200,0x300200,0x300200,0x220000B9,0x220000B9,0x1E000065,0x5C0200,0x5C0200,0x16000132,0xE000202,0x5C0200,0x5C0200,0x16000132,0xE000202,0xE000202,0xB600009D,0xFE0C0088,0x200200,0x5C0000DA,0x3C0000C1,0x2E0000C1,0x2A00009D,0x220000E8,0x6400013D,0x4A000112,0x400200,0x16000132,
+0x400200,0x780620,0xCA400000,0x72400000,0x56400001,0x2B00620,0x7A000059,0x58080001,0x1680620,0x4A0001ED,0x3A000622,0x2B00620,0x7A000059,0x58080001,0x1680620,0x4A0001ED,0x3A000622,0x1680620,0x4A0001ED,0x3A000622,0x3A000622,0x2B00620,0x7A000059,0x58080001,0x1680620,0x4A0001ED,0x3A000622,0x1680620,0x4A0001ED,0x3A000622,0x3A000622,0x1680620,
+0x4A0001ED,0x3A000622,0x3A000622,0x3A000622,0xF8280349,0x800620,0xFE6C039D,0xBC0001BD,0x80000209,0x5E0001D4,0x50000131,0x460002B1,0xF8040320,0x9E000239,0x560000E8,0x3A000622,0xFC0620,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table162[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x500000,0x500000,0x500000,0x500000,0x2740000,0x2740000,0x2740000,0xF00000,0xF00000,0x26000001,0x2740000,0x2740000,0x2740000,0xF00000,0xF00000,0x26000001,0xF00000,0xF00000,0x26000001,0x26000001,0x2740000,0x2740000,0x2740000,0xF00000,0xF00000,0x26000001,0xF00000,0xF00000,0x26000001,0x26000001,0xF00000,
+0xF00000,0x26000001,0x26000001,0x26000001,0x5C0000,0x2540000,0x500000,0x6C0000,0x840000,0xA80000,0xC00000,0x1240000,0x640000,0x2740000,0xA80000,0x26000001,0xA80000,0xC00000,0x11C0000,0x13FC0000,0x5E000001,0x11C0000,0x13FC0000,0x5E000001,0x13FC0000,0x5E000001,0x5E000001,0x11C0000,0x13FC0000,0x5E000001,0x13FC0000,0x5E000001,
+0x5E000001,0x13FC0000,0x5E000001,0x5E000001,0x5E000001,0x11C0000,0x13FC0000,0x5E000001,0x13FC0000,0x5E000001,0x5E000001,0x13FC0000,0x5E000001,0x5E000001,0x5E000001,0x13FC0000,0x5E000001,0x5E000001,0x5E000001,0x5E000001,0xF00000,0xCC0000,0xCC0000,0x3400000,0x1D40000,0x39F00000,0x5E000001,0x5E000001,0x1040000,0x1680000,0x55FC0000,0x5E000001,
+0x1980000,0x441830,0xFE1C0435,0x861C042D,0x5E1C042D,0xCE000620,0x8C000025,0x62040035,0x64000620,0x56000195,0x42000622,0x8800122B,0x740006C9,0x580003F3,0x580009E9,0x4C00046A,0x400007EB,0x4200122B,0x3E000B29,0x38000CB6,0x2C00122B,0x641830,0x62000B89,0x52000704,0x52000CF2,0x460006D3,0x3A000994,0x3A0013E9,0x3E000CE2,0x32000E07,0x2A0012FF,0xCC1830,
+0x32001115,0x2C00114A,0x26001547,0x20001834,0xFE1407F5,0xFE2C116A,0xF63C11FC,0xC800047D,0x8000049D,0x5E000465,0x520002DE,0x4A00061E,0xF2000977,0x9E0006AD,0x4E0008E5,0x32000E07,0x901830,0x5C122C,0xFA280320,0x84280320,0x5E280321,0xCE000620,0x8C000025,0x6008002A,0x64000620,0x56000195,0x42000622,0x84122B,0x740006C9,0x580003F3,0x580009E9,0x4C00046A,
+0x400007EB,0x10C122B,0x3E000B29,0x38000CB6,0x2C00122B,0x84122B,0x740006C9,0x580003F3,0x580009E9,0x4C00046A,0x400007EB,0x10C122B,0x3E000B29,0x38000CB6,0x2C00122B,0x10C122B,0x3E000B29,0x38000CB6,0x2C00122B,0x2C00122B,0xFE140791,0xFC480DB8,0xFE4C0D38,0xC800047D,0x8000049D,0x5E000465,0x520002DE,0x4A00061E,0xFA00088B,0x9E000649,0x4E0008CC,0x38000CB6,
+0xBC122B,0x1C042C,0x1C042C,0x1C042C,0x1C042C,0x78000000,0x78000000,0x78000000,0x3A000000,0x3A000000,0x26000001,0x3C000320,0x3C000320,0x3C000320,0x2E000121,0x2E000121,0x22000092,0x1C000322,0x1C000322,0x1C0001E2,0x12000322,0x224042B,0x224042B,0x224042B,0x280001E2,0x280001E2,0x2200010B,0x18000372,0x18000372,0x1A00023E,0x12000346,0x4C042B,
+0x4C042B,0x160002E3,0x100003AB,0xC00042B,0xF60000FA,0xFE0C018C,0x1C042C,0x72000151,0x50000131,0x4000013A,0x38000105,0x2A000161,0x8200022D,0x500001C2,0x24000324,0x1A00023E,0x34042B,0x280320,0x280320,0x280320,0x280320,0x78000000,0x78000000,0x78000000,0x3A000000,0x3A000000,0x26000001,0x3C0320,0x3C0320,0x3C0320,0x2E000121,0x2E000121,
+0x22000092,0x740320,0x740320,0x1C0001E2,0x12000322,0x3C0320,0x3C0320,0x3C0320,0x2E000121,0x2E000121,0x22000092,0x740320,0x740320,0x1C0001E2,0x12000322,0x740320,0x740320,0x1C0001E2,0x12000322,0x12000322,0xF60000FA,0xF4180139,0x280320,0x72000151,0x50000131,0x4000013A,0x38000105,0x2A000161,0x820001ED,0x5A0001A8,0x540320,0x1C0001E2,
+0x540320,0x880620,0xD2500000,0x7A500000,0x5E500001,0xC80620,0x8C000025,0x60180001,0x1980620,0x56000195,0x42000622,0xC80620,0x8C000025,0x60180001,0x1980620,0x56000195,0x42000622,0x1980620,0x56000195,0x42000622,0x42000622,0xC80620,0x8C000025,0x60180001,0x1980620,0x56000195,0x42000622,0x1980620,0x56000195,0x42000622,0x42000622,0x1980620,
+0x56000195,0x42000622,0x42000622,0x42000622,0xFE340355,0x900620,0xF67C03C8,0xD2000164,0x8A0001A9,0x68000190,0x580000DA,0x5000024A,0xFC140322,0xB40001E2,0x5E000095,0x42000622,0x1200620,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table163[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x600000,0x600000,0x600000,0x600000,0x28C0000,0x28C0000,0x28C0000,0x1200000,0x1200000,0x2E000001,0x28C0000,0x28C0000,0x28C0000,0x1200000,0x1200000,0x2E000001,0x1200000,0x1200000,0x2E000001,0x2E000001,0x28C0000,0x28C0000,0x28C0000,0x1200000,0x1200000,0x2E000001,0x1200000,0x1200000,0x2E000001,0x2E000001,0x1200000,
+0x1200000,0x2E000001,0x2E000001,0x2E000001,0x700000,0xA640000,0x600000,0x2800000,0xA00000,0xCC0000,0xE80000,0x1640000,0x780000,0x28C0000,0xCC0000,0x2E000001,0xCC0000,0xD00000,0x1340000,0x1FF80000,0x66000001,0x1340000,0x1FF80000,0x66000001,0x1FF80000,0x66000001,0x66000001,0x1340000,0x1FF80000,0x66000001,0x1FF80000,0x66000001,
+0x66000001,0x1FF80000,0x66000001,0x66000001,0x66000001,0x1340000,0x1FF80000,0x66000001,0x1FF80000,0x66000001,0x66000001,0x1FF80000,0x66000001,0x66000001,0x66000001,0x1FF80000,0x66000001,0x66000001,0x66000001,0x66000001,0x1040000,0x6DC0000,0x6DC0000,0x15C0000,0x1FC0000,0x43F00000,0x66000001,0x66000001,0x3180000,0x1840000,0x5FD00000,0x66000001,
+0x1B80000,0x4C1CB0,0xFE24064C,0x92200600,0x66200601,0xE6000620,0x98000005,0x6A08008D,0x70000620,0x5C00013D,0x4A000622,0x9A00152B,0x80000829,0x62000519,0x62000AC2,0x580004BA,0x46000863,0x4A00152C,0x44000D11,0x3E000E56,0x3200152B,0x701CB0,0x6E000DF9,0x580008DC,0x58000EB2,0x520007AB,0x46000A74,0x46001751,0x44000F22,0x38000FFF,0x30001633,0xE41CB0,
+0x3800144D,0x3200140A,0x2C00190F,0x24001CB4,0xFE140A75,0xF63C1528,0xFA44160C,0xDE0004E3,0x90000506,0x6E0004C2,0x5E000302,0x500006CB,0xFA000B2B,0xB2000792,0x56000A45,0x38000FFF,0xA01CB0,0x64152C,0xFE300490,0x8E300480,0x66300481,0xE6000620,0x98000005,0x6A08007D,0x70000620,0x5C00013D,0x4A000622,0x98152B,0x80000829,0x62000519,0x62000AC2,0x580004BA,
+0x46000863,0x130152B,0x44000D11,0x3E000E56,0x3200152B,0x98152B,0x80000829,0x62000519,0x62000AC2,0x580004BA,0x46000863,0x130152B,0x44000D11,0x3E000E56,0x3200152B,0x130152B,0x44000D11,0x3E000E56,0x3200152B,0x3200152B,0xFE2009B6,0xFE4C1044,0xF65C1031,0xDE0004E3,0x90000506,0x6E0004C2,0x5E000302,0x500006CB,0xFA000A2B,0xB2000719,0x56000A2C,0x3E000E56,
+0xD8152B,0x200600,0x200600,0x200600,0x200600,0x90000000,0x90000000,0x90000000,0x46000000,0x46000000,0x2E000001,0x48000480,0x48000480,0x48000480,0x3A0001A9,0x3A0001A9,0x280000DA,0x22000480,0x22000480,0x200002C5,0x16000482,0x300600,0x300600,0x300600,0x2E0002C2,0x2E0002C2,0x28000183,0x1E0004F6,0x1E0004F6,0x1C000336,0x160004C2,0x5C0600,
+0x5C0600,0x16000433,0x14000556,0xE000603,0xF600018A,0xF21402D9,0x200600,0x900001E1,0x5E0001BA,0x480001BA,0x40000172,0x2E000212,0x9600032B,0x660002A1,0x2C000489,0x1C000336,0x400600,0x300480,0x300480,0x300480,0x300480,0x90000000,0x90000000,0x90000000,0x46000000,0x46000000,0x2E000001,0x2440480,0x2440480,0x2440480,0x3A0001A9,0x3A0001A9,
+0x280000DA,0x8C0480,0x8C0480,0x200002C5,0x16000482,0x2440480,0x2440480,0x2440480,0x3A0001A9,0x3A0001A9,0x280000DA,0x8C0480,0x8C0480,0x200002C5,0x16000482,0x8C0480,0x8C0480,0x200002C5,0x16000482,0x16000482,0xF600018A,0xF8200221,0x300480,0x900001E1,0x5E0001BA,0x480001BA,0x40000172,0x2E000212,0xA40002D5,0x6C000274,0x640480,0x200002C5,
+0x640480,0x980620,0xDA600000,0x82600000,0x66600001,0xE00620,0x98000005,0x68280001,0x1CC0620,0x5C00013D,0x4A000622,0xE00620,0x98000005,0x68280001,0x1CC0620,0x5C00013D,0x4A000622,0x1CC0620,0x5C00013D,0x4A000622,0x4A000622,0xE00620,0x98000005,0x68280001,0x1CC0620,0x5C00013D,0x4A000622,0x1CC0620,0x5C00013D,0x4A000622,0x4A000622,0x1CC0620,
+0x5C00013D,0x4A000622,0x4A000622,0x4A000622,0xFC4C0374,0x8A00620,0xFE8C03C8,0xE600010D,0xA0000161,0x76000132,0x5E000091,0x58000202,0xFE2C0349,0xC600019A,0x6A000061,0x4A000622,0x1400620,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table164[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x2180000,0x2180000,0x2180000,0x2180000,0x2180000,
+0x2180000,0x300000,0x300000,0x300000,0x8000000,0x2180000,0x2180000,0x2180000,0x2180000,0x2180000,0x2180000,0x300000,0x300000,0x300000,0x8000000,0x300000,0x300000,0x300000,0x8000000,0x8000000,0x140000,0x100001,0x100001,0x140000,0x2140000,0x180000,0x180000,0x1C0000,0x140000,0x2140000,0x240000,0x300000,
+0x240000,0x700001,0x700001,0x700001,0x700001,0xA80000,0xA80000,0xA80000,0x1580000,0x1580000,0x38000000,0xA80000,0xA80000,0xA80000,0x1580000,0x1580000,0x38000000,0x1580000,0x1580000,0x38000000,0x38000000,0xA80000,0xA80000,0xA80000,0x1580000,0x1580000,0x38000000,0x1580000,0x1580000,0x38000000,0x38000000,0x1580000,
+0x1580000,0x38000000,0x38000000,0x38000000,0x840000,0x4780000,0x700001,0x2980000,0xC00000,0xF00000,0x1140000,0x1A40000,0x48C0000,0xA80000,0xF00000,0x38000000,0xF00000,0xE00001,0x1500000,0x2DF80000,0x70000000,0x1500000,0x2DF80000,0x70000000,0x2DF80000,0x70000000,0x70000000,0x1500000,0x2DF80000,0x70000000,0x2DF80000,0x70000000,
+0x70000000,0x2DF80000,0x70000000,0x70000000,0x70000000,0x1500000,0x2DF80000,0x70000000,0x2DF80000,0x70000000,0x70000000,0x2DF80000,0x70000000,0x70000000,0x70000000,0x2DF80000,0x70000000,0x70000000,0x70000000,0x70000000,0x11C0000,0xF00000,0xF00000,0x17C0000,0x11FC0000,0x4DF80000,0x70000000,0x70000000,0x1340000,0x1A80000,0x69C40000,0x70000000,
+0x1E00000,0x581F9B,0xFE30080B,0x9C2C0756,0x702C0756,0xFA080649,0xA408002A,0x741000FA,0x7C080649,0x68040139,0x54080649,0xB600152B,0x92000706,0x6E000496,0x740009B1,0x62000339,0x5200076C,0x5800152B,0x50000BF2,0x44000D79,0x3A00152C,0x841F99,0x7A000EA6,0x62000946,0x68000E9D,0x5E00071A,0x4C000A11,0x5200182C,0x4E000EC8,0x44000F8A,0x3A001695,0x10C1F99,
+0x440015A6,0x3E00150D,0x32001A90,0x2C001F99,0xFE200C15,0xFE4C178F,0xFE4C18DF,0xF400035A,0xA2000391,0x7C00033A,0x660001B8,0x60000548,0xFE000BDB,0xC6000621,0x5E000926,0x44000F8A,0xBC1F99,0x78152B,0xFE4404A6,0x96440482,0x70400482,0xEE140621,0xA0100006,0x741C007A,0x78140621,0x660C0131,0x54100621,0x2B0152B,0x92000706,0x6E000496,0x740009B1,0x62000339,
+0x5200076C,0x168152B,0x50000BF2,0x44000D79,0x3A00152C,0x2B0152B,0x92000706,0x6E000496,0x740009B1,0x62000339,0x5200076C,0x168152B,0x50000BF2,0x44000D79,0x3A00152C,0x168152B,0x50000BF2,0x44000D79,0x3A00152C,0x3A00152C,0xFE340A02,0xFA641079,0xFE6C1036,0xF400035A,0xA2000391,0x7C00033A,0x660001B8,0x60000548,0xFE080A6C,0xC6000591,0x5E000902,0x44000D79,
+0xFC152B,0x2C0756,0x2C0756,0x2C0756,0x2C0756,0xA4080029,0xA4080029,0xA4080029,0x52080029,0x52080029,0x38080029,0x64000480,0x64000480,0x64000480,0x46000115,0x46000115,0x34000050,0x30000480,0x30000480,0x2C000249,0x20000480,0x400756,0x400756,0x400756,0x3A0002EE,0x3A0002EE,0x2E000169,0x2800055B,0x2800055B,0x2600030E,0x1E0004EC,0x800756,
+0x800756,0x200004CD,0x1C000609,0x14000759,0xFC0C01B4,0xF82003D5,0x2C0756,0xB2000151,0x7C000124,0x5E000131,0x560000DD,0x40000172,0xC20002F5,0x8400022D,0x3E000490,0x2600030E,0x5C0756,0x400482,0x400482,0x400482,0x400482,0x98140001,0x98140001,0x98140001,0x50100001,0x50100001,0x38100001,0x600480,0x600480,0x600480,0x46000115,0x46000115,
+0x34000050,0xC40480,0xC40480,0x2C000249,0x20000480,0x600480,0x600480,0x600480,0x46000115,0x46000115,0x34000050,0xC40480,0xC40480,0x2C000249,0x20000480,0xC40480,0xC40480,0x2C000249,0x20000480,0x20000480,0xFE100188,0xFE2C0239,0x400482,0xB2000151,0x7C000124,0x5E000131,0x560000DD,0x40000172,0xD6000262,0x900001E1,0x8C0480,0x2C000249,
+0x8C0480,0xA80622,0xE0740001,0x8C700001,0x70700001,0xFC0620,0xA4080001,0x703C0000,0x3F80620,0x660000F4,0x54000620,0xFC0620,0xA4080001,0x703C0000,0x3F80620,0x660000F4,0x54000620,0x3F80620,0x660000F4,0x54000620,0x54000620,0xFC0620,0xA4080001,0x703C0000,0x3F80620,0x660000F4,0x54000620,0x3F80620,0x660000F4,0x54000620,0x54000620,0x3F80620,
+0x660000F4,0x54000620,0x54000620,0x54000620,0xF668039D,0x2B40620,0xF8A003F5,0xFC0000C8,0xAA000109,0x7E0400F2,0x6C000050,0x640001B1,0xF4480372,0xD800013D,0x74000022,0x54000620,0x1680620,0x80029,0x80029,0x80029,0x80029,0x80029,0x80029,0x80029,0x80029,0x80029,0x80029,0x1A000000,0x1A000000,0x1A000000,0x1A000000,0x1A000000,
+0x1A000000,0xC000000,0xC000000,0xC000000,0x8000000,0xC0029,0xC0029,0xC0029,0xC0029,0xC0029,0xC0029,0xC000010,0xC000010,0xC000010,0x6000008,0x140029,0x140029,0x140029,0x4000019,0x4000029,0x88000000,0x80029,0x80029,0x3C000000,0x2A000000,0x20000000,0x20000000,0x14000000,0x3600000A,0x24000005,0x10000001,0xC000010,
+0x100029,};
+static const uint32_t g_etc1_to_bc7_m6_table165[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x2300000,0x2300000,0x2300000,0x2300000,0x2300000,
+0x2300000,0x640000,0x640000,0x640000,0x10000000,0x2300000,0x2300000,0x2300000,0x2300000,0x2300000,0x2300000,0x640000,0x640000,0x640000,0x10000000,0x640000,0x640000,0x640000,0x10000000,0x10000000,0x240000,0x200001,0x200001,0x280000,0x2280000,0x22C0000,0x22C0000,0x380000,0x280000,0x2280000,0x480000,0x640000,
+0x480000,0x800001,0x800001,0x800001,0x800001,0xC00000,0xC00000,0xC00000,0x1880000,0x1880000,0x40000000,0xC00000,0xC00000,0xC00000,0x1880000,0x1880000,0x40000000,0x1880000,0x1880000,0x40000000,0x40000000,0xC00000,0xC00000,0xC00000,0x1880000,0x1880000,0x40000000,0x1880000,0x1880000,0x40000000,0x40000000,0x1880000,
+0x1880000,0x40000000,0x40000000,0x40000000,0x980000,0xC880000,0x800001,0xB00000,0xD80000,0x1140000,0x13C0000,0x1E40000,0x4A00000,0xC00000,0x1140000,0x40000000,0x1140000,0xF00001,0x1680000,0x39F80000,0x78000000,0x1680000,0x39F80000,0x78000000,0x39F80000,0x78000000,0x78000000,0x1680000,0x39F80000,0x78000000,0x39F80000,0x78000000,
+0x78000000,0x39F80000,0x78000000,0x78000000,0x78000000,0x1680000,0x39F80000,0x78000000,0x39F80000,0x78000000,0x78000000,0x39F80000,0x78000000,0x78000000,0x78000000,0x39F80000,0x78000000,0x78000000,0x78000000,0x78000000,0x1300000,0x9000000,0x9000000,0x3940000,0x1FF80000,0x57F80000,0x78000000,0x78000000,0x1480000,0x1C40000,0x71D40000,0x78000000,
+0x3FC0000,0x642297,0xFE3C0A17,0xA63808E2,0x783808E2,0xFC1406C7,0xAE100096,0x7E1801AE,0x861006B1,0x6E100185,0x5C1006B1,0xCE00152B,0xA2000619,0x78000482,0x800008D9,0x6E000231,0x580006D0,0x6400152B,0x5C000B02,0x50000C99,0x4200152C,0x982295,0x8C000F9A,0x6E000A26,0x74000F05,0x620006C9,0x58000A19,0x5E001914,0x56000E8F,0x4A000F5A,0x400016F9,0x1302295,
+0x4A00172A,0x4400162D,0x38001C24,0x32002295,0xFE340DE6,0xFE4C1A9F,0xF8601BF2,0xFE000293,0xB6000271,0x88000239,0x740000E4,0x64000421,0xFE100D87,0xDA000512,0x6E00085A,0x4A000F5A,0xD82295,0x88152B,0xFC5804D2,0x9E540482,0x78500482,0xF6240621,0xA8200006,0x7C2C007A,0x80240621,0x6E1C0131,0x5C200621,0xC8152B,0xA2000619,0x78040480,0x800008D9,0x6E000231,
+0x580006D0,0x198152B,0x5C000B02,0x50000C99,0x4200152C,0xC8152B,0xA2000619,0x78040480,0x800008D9,0x6E000231,0x580006D0,0x198152B,0x5C000B02,0x50000C99,0x4200152C,0x198152B,0x5C000B02,0x50000C99,0x4200152C,0x4200152C,0xFC4C0A7E,0xFE6C10C1,0xF880108B,0xFE000293,0xB6000271,0x88000239,0x740000E4,0x64000421,0xFE240AC5,0xDA00044E,0x6E000829,0x50000C99,
+0x120152B,0x3808E2,0x3808E2,0x3808E2,0x3808E2,0xB4100091,0xB4100091,0xB4100091,0x5C100091,0x5C100091,0x40100091,0x7C000480,0x7C000480,0x7C000480,0x580000A9,0x580000A9,0x40000010,0x3C000480,0x3C000480,0x320001E5,0x28000480,0x5008E1,0x5008E1,0x5008E1,0x46000356,0x46000356,0x3A000191,0x340005D3,0x340005D3,0x30000300,0x28000529,0xA008E1,
+0xA008E1,0x26000599,0x200006E4,0x1A0008E1,0xFE100248,0xFE2C050D,0x3808E2,0xD00000E1,0x900000B4,0x6E0000B4,0x66000074,0x4C000104,0xF40002E3,0xA60001E9,0x4C000499,0x30000300,0x7008E1,0x500482,0x500482,0x500482,0x500482,0xA0240001,0xA0240001,0xA0240001,0x58200001,0x58200001,0x40200001,0x780480,0x780480,0x780480,0x580000A9,0x580000A9,
+0x40000010,0xF40480,0xF40480,0x320001E5,0x28000480,0x780480,0x780480,0x780480,0x580000A9,0x580000A9,0x40000010,0xF40480,0xF40480,0x320001E5,0x28000480,0xF40480,0xF40480,0x320001E5,0x28000480,0x28000480,0xFE2001A5,0xFA440242,0x500482,0xD00000E1,0x900000B4,0x6E0000B4,0x66000074,0x4C000104,0xF4000202,0xAC000184,0xAC0480,0x320001E5,
+0xAC0480,0xB80622,0xE8840001,0x94800001,0x78800001,0x1140620,0xAC180001,0x784C0000,0xFF80620,0x720000B4,0x5C000620,0x1140620,0xAC180001,0x784C0000,0xFF80620,0x720000B4,0x5C000620,0xFF80620,0x720000B4,0x5C000620,0x5C000620,0x1140620,0xAC180001,0x784C0000,0xFF80620,0x720000B4,0x5C000620,0xFF80620,0x720000B4,0x5C000620,0x5C000620,0xFF80620,
+0x720000B4,0x5C000620,0x5C000620,0x5C000620,0xFE78039D,0xAC40620,0xFEAC03F9,0xFE1400DD,0xC00000CD,0x900000A9,0x74000020,0x6C000171,0xFC580372,0xEE0000FA,0x7E000008,0x5C000620,0x18C0620,0x100091,0x100091,0x100091,0x100091,0x100091,0x100091,0x100091,0x100091,0x100091,0x100091,0x32000000,0x32000000,0x32000000,0x32000000,0x32000000,
+0x32000000,0x18000000,0x18000000,0x18000000,0x10000000,0x180091,0x180091,0x180091,0x180091,0x180091,0x180091,0x12000034,0x12000034,0x12000034,0xE00001D,0x2C0091,0x2C0091,0x2C0091,0xA000055,0x8000091,0xF8000001,0x100091,0x100091,0x76000000,0x52000000,0x3E000000,0x3E000000,0x28000000,0x6000002D,0x42000019,0x1E000005,0x12000034,
+0x200091,};
+static const uint32_t g_etc1_to_bc7_m6_table166[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x300001,0x480000,0x480000,0x480000,0x480000,0x480000,
+0x480000,0x940000,0x940000,0x940000,0x18000000,0x480000,0x480000,0x480000,0x480000,0x480000,0x480000,0x940000,0x940000,0x940000,0x18000000,0x940000,0x940000,0x940000,0x18000000,0x18000000,0x2340000,0x300001,0x300001,0x4380000,0x23C0000,0x440000,0x440000,0x540000,0x4380000,0x23C0000,0x680000,0x940000,
+0x680000,0x900001,0x900001,0x900001,0x900001,0xD80000,0xD80000,0xD80000,0x1B80000,0x1B80000,0x48000000,0xD80000,0xD80000,0xD80000,0x1B80000,0x1B80000,0x48000000,0x1B80000,0x1B80000,0x48000000,0x48000000,0xD80000,0xD80000,0xD80000,0x1B80000,0x1B80000,0x48000000,0x1B80000,0x1B80000,0x48000000,0x48000000,0x1B80000,
+0x1B80000,0x48000000,0x48000000,0x48000000,0x2A80000,0x9C0000,0x900001,0x2C40000,0xF40000,0x1340000,0x1640000,0x7FC0000,0x4B40000,0xD80000,0x1340000,0x48000000,0x1340000,0x1000001,0x1800000,0x45F80000,0x80000000,0x1800000,0x45F80000,0x80000000,0x45F80000,0x80000000,0x80000000,0x1800000,0x45F80000,0x80000000,0x45F80000,0x80000000,
+0x80000000,0x45F80000,0x80000000,0x80000000,0x80000000,0x1800000,0x45F80000,0x80000000,0x45F80000,0x80000000,0x80000000,0x45F80000,0x80000000,0x80000000,0x80000000,0x45F80000,0x80000000,0x80000000,0x80000000,0x80000000,0x1440000,0x1140000,0x1140000,0x1B00000,0x2BFC0000,0x61FC0000,0x80000000,0x80000000,0x35C0000,0x1E40000,0x79E40000,0x80000000,
+0x13FC0000,0x7025F3,0xFE480C9B,0xB0400AC2,0x80400AC2,0xFE2407C7,0xBA1C0142,0x842402A6,0x90180759,0x78180209,0x64180759,0xE600152B,0xAE000579,0x820804A6,0x8C000821,0x76000159,0x62000659,0x7000152B,0x66000A44,0x56000BE9,0x4A00152C,0xA825F1,0x980010EA,0x7A000B86,0x80000FAD,0x6E0006D1,0x5E000A4D,0x680019F0,0x60000E80,0x54000F30,0x4600177D,0x15825F1,
+0x50001916,0x4A00179D,0x3E001DF0,0x380025F1,0xFE3C105F,0xFA641D9D,0xFE6C1F1A,0xFE0802E9,0xCA000191,0x96000163,0x7C000051,0x7000031D,0xFE180FB2,0xF2000433,0x7600075A,0x54000F30,0xF025F1,0x98152B,0xFE6804F6,0xA6640482,0x80600482,0xFE340621,0xB0300006,0x843C007A,0x88340621,0x762C0131,0x64300621,0xE0152B,0xAE000579,0x80140480,0x8C000821,0x76000159,
+0x62000659,0x1CC152B,0x66000A44,0x56000BE9,0x4A00152C,0xE0152B,0xAE000579,0x80140480,0x8C000821,0x76000159,0x62000659,0x1CC152B,0x66000A44,0x56000BE9,0x4A00152C,0x1CC152B,0x66000A44,0x56000BE9,0x4A00152C,0x4A00152C,0xFE580AE5,0xFC8810CB,0xFE8C1093,0xFE1402D6,0xCA000191,0x96000163,0x7C000051,0x7000031D,0xFE340B25,0xF2000352,0x76000729,0x56000BE9,
+0x140152B,0x400AC2,0x400AC2,0x400AC2,0x400AC2,0xC4180139,0xC4180139,0xC4180139,0x66180139,0x66180139,0x48180139,0x94000480,0x94000480,0x94000480,0x62000055,0x62000055,0x48000001,0x48000480,0x48000480,0x3E000185,0x30000480,0x600AC1,0x600AC1,0x600AC1,0x520003FE,0x520003FE,0x40000209,0x4000066B,0x4000066B,0x3A00030E,0x2E000569,0xC40AC1,
+0xC40AC1,0x2C0006AD,0x260007EC,0x20000AC1,0xFE200335,0xF43806DA,0x400AC2,0xFA000088,0xA8000061,0x80000061,0x78000032,0x5A0000B4,0xFE000332,0xC40001B1,0x5C0004A4,0x3A00030E,0x8C0AC1,0x600482,0x600482,0x600482,0x600482,0xA8340001,0xA8340001,0xA8340001,0x60300001,0x60300001,0x48300001,0x900480,0x900480,0x900480,0x62000055,0x62000055,
+0x48040000,0x1240480,0x1240480,0x3E000185,0x30000480,0x900480,0x900480,0x900480,0x62000055,0x62000055,0x48040000,0x1240480,0x1240480,0x3E000185,0x30000480,0x1240480,0x1240480,0x3E000185,0x30000480,0x30000480,0xFA3401C2,0xFE4C0262,0x600482,0xFA000088,0xA8000061,0x80000061,0x78000032,0x5A0000B4,0xFE0C0200,0xC4000121,0xD00480,0x3E000185,
+0xD00480,0xC80622,0xF0940001,0x9C900001,0x80900001,0x12C0620,0xB4280001,0x805C0000,0x1BF80620,0x78000080,0x64000620,0x12C0620,0xB4280001,0x805C0000,0x1BF80620,0x78000080,0x64000620,0x1BF80620,0x78000080,0x64000620,0x64000620,0x12C0620,0xB4280001,0x805C0000,0x1BF80620,0x78000080,0x64000620,0x1BF80620,0x78000080,0x64000620,0x64000620,0x1BF80620,
+0x78000080,0x64000620,0x64000620,0x64000620,0xFA8C03C8,0xD80620,0xF8C00422,0xFE2C0109,0xCA000091,0x9A00006A,0x7E000008,0x76000128,0xFC6C039D,0xFC0000C8,0x88000001,0x64000620,0x1AC0620,0x180139,0x180139,0x180139,0x180139,0x180139,0x180139,0x180139,0x180139,0x180139,0x180139,0x4A000000,0x4A000000,0x4A000000,0x4A000000,0x4A000000,
+0x4A000000,0x24000000,0x24000000,0x24000000,0x18000000,0x240139,0x240139,0x240139,0x240139,0x240139,0x240139,0x1E000074,0x1E000074,0x1E000074,0x18000040,0x440139,0x440139,0x440139,0x100000B9,0xC000139,0xFC080029,0x180139,0x180139,0xAE000000,0x78000000,0x5C000000,0x5C000000,0x3C000000,0x92000061,0x74000032,0x2E000009,0x1E000074,
+0x300139,};
+static const uint32_t g_etc1_to_bc7_m6_table167[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x600000,0x600000,0x600000,0x600000,0x600000,
+0x600000,0xC40000,0xC40000,0xC40000,0x20000000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0xC40000,0xC40000,0xC40000,0x20000000,0xC40000,0xC40000,0xC40000,0x20000000,0x20000000,0xA440000,0x400001,0x400001,0x4C0000,0x4500000,0x580000,0x580000,0x26C0000,0x4C0000,0x4500000,0x8C0000,0xC40000,
+0x8C0000,0xA00001,0xA00001,0xA00001,0xA00001,0xF00000,0xF00000,0xF00000,0x1E80000,0x1E80000,0x50000000,0xF00000,0xF00000,0xF00000,0x1E80000,0x1E80000,0x50000000,0x1E80000,0x1E80000,0x50000000,0x50000000,0xF00000,0xF00000,0xF00000,0x1E80000,0x1E80000,0x50000000,0x1E80000,0x1E80000,0x50000000,0x50000000,0x1E80000,
+0x1E80000,0x50000000,0x50000000,0x50000000,0xBC0000,0xAC0000,0xA00001,0xDC0000,0x1100000,0x1580000,0x18C0000,0x13F80000,0xCC0000,0xF00000,0x1580000,0x50000000,0x1580000,0x1100001,0x1980000,0x51F80000,0x88000000,0x1980000,0x51F80000,0x88000000,0x51F80000,0x88000000,0x88000000,0x1980000,0x51F80000,0x88000000,0x51F80000,0x88000000,
+0x88000000,0x51F80000,0x88000000,0x88000000,0x88000000,0x1980000,0x51F80000,0x88000000,0x51F80000,0x88000000,0x88000000,0x51F80000,0x88000000,0x88000000,0x88000000,0x51F80000,0x88000000,0x88000000,0x88000000,0x88000000,0x1580000,0x1240000,0x1240000,0x1CC0000,0x39FC0000,0x6BFC0000,0x88000000,0x88000000,0x1740000,0x5FC0000,0x81F40000,0x88000000,
+0x21FC0000,0x7C29AF,0xFE540F97,0xB84C0CF6,0x884C0CF6,0xFE300953,0xC4240236,0x8E2C03EA,0x9A200841,0x801C02D1,0x6C200841,0xFE00152B,0xC00004F9,0x8C100502,0x98000789,0x800000B5,0x6C000629,0x7C00152B,0x72000984,0x60000B40,0x5200152C,0xBC29AD,0xA800126A,0x82000D65,0x8C001095,0x7A000739,0x68000AC5,0x74001B10,0x68000E8C,0x5C000F2A,0x52001805,0x17C29AD,
+0x5C001B46,0x5000195D,0x4A001FD0,0x3E0029AD,0xFE501342,0xFE6C2105,0xFE6C231A,0xFE1403DA,0xD80000EA,0xA20000B9,0x88000009,0x7A000236,0xFE2412A6,0xFC00038C,0x7E0006CC,0x5C000F2A,0x10C29AD,0xA8152B,0xFE78053B,0xAE740482,0x88700482,0xFE440629,0xB8400006,0x8C4C007A,0x90440621,0x7E3C0131,0x6C400621,0xF8152B,0xC00004F9,0x88240480,0x98000789,0x800000B5,
+0x6C000629,0x1FC152B,0x72000984,0x60000B40,0x5200152C,0xF8152B,0xC00004F9,0x88240480,0x98000789,0x800000B5,0x6C000629,0x1FC152B,0x72000984,0x60000B40,0x5200152C,0x1FC152B,0x72000984,0x60000B40,0x5200152C,0x5200152C,0xFC740B5A,0xF4981121,0xF8A010E6,0xFE240355,0xD80000EA,0xA20000B9,0x88000009,0x7A000236,0xFE440B94,0xFC00028C,0x7E00068C,0x60000B40,
+0x164152B,0x4C0CF6,0x4C0CF6,0x4C0CF6,0x4C0CF6,0xD4200221,0xD4200221,0xD4200221,0x70200221,0x70200221,0x50200221,0xAC000480,0xAC000480,0xAC000480,0x7400001D,0x7400001D,0x52040018,0x54000480,0x54000480,0x44000139,0x38000480,0x700CF6,0x700CF6,0x700CF6,0x620004C5,0x620004C5,0x4C0002C1,0x4C000723,0x4C000723,0x40000332,0x340005C1,0xE40CF6,
+0xE40CF6,0x380007FD,0x2C000924,0x24000CF9,0xFE2C0498,0xFA4408C6,0x4C0CF6,0xFE080098,0xBC000029,0x9200002D,0x84000008,0x6A000068,0xFE000452,0xD4000186,0x660004AC,0x40000332,0xA00CF6,0x700482,0x700482,0x700482,0x700482,0xB0440001,0xB0440001,0xB0440001,0x68400001,0x68400001,0x50400001,0xA80480,0xA80480,0xA80480,0x7400001D,0x7400001D,
+0x50140000,0x1580480,0x1580480,0x44000139,0x38000480,0xA80480,0xA80480,0xA80480,0x7400001D,0x7400001D,0x50140000,0x1580480,0x1580480,0x44000139,0x38000480,0x1580480,0x1580480,0x44000139,0x38000480,0x38000480,0xF64801E1,0xFA640265,0x700482,0xFE080088,0xBC000029,0x9200002D,0x84000008,0x6A000068,0xF6240221,0xDA0000CA,0xF00480,0x44000139,
+0xF00480,0xD80622,0xF8A40001,0xA4A00001,0x88A00001,0x1440620,0xBC380001,0x886C0000,0x27F80620,0x84000050,0x6C000620,0x1440620,0xBC380001,0x886C0000,0x27F80620,0x84000050,0x6C000620,0x27F80620,0x84000050,0x6C000620,0x6C000620,0x1440620,0xBC380001,0x886C0000,0x27F80620,0x84000050,0x6C000620,0x27F80620,0x84000050,0x6C000620,0x6C000620,0x27F80620,
+0x84000050,0x6C000620,0x6C000620,0x6C000620,0xFE9403E8,0xE80620,0xFECC042A,0xFE400128,0xE000006D,0xA6000050,0x88000000,0x7E0000F4,0xF88403C8,0xFE1400E1,0x90100001,0x6C000620,0x1D00620,0x200221,0x200221,0x200221,0x200221,0x200221,0x200221,0x200221,0x200221,0x200221,0x200221,0x64000000,0x64000000,0x64000000,0x64000000,0x64000000,
+0x64000000,0x30000000,0x30000000,0x30000000,0x20000000,0x300221,0x300221,0x300221,0x300221,0x300221,0x300221,0x280000C2,0x280000C2,0x280000C2,0x1E000068,0x5C0221,0x5C0221,0x5C0221,0x16000145,0x10000221,0xFE0C009D,0x200221,0x200221,0xE8000000,0xA0000000,0x7A000000,0x7A000000,0x50000000,0xC40000A9,0x96000055,0x3E000010,0x280000C2,
+0x400221,};
+static const uint32_t g_etc1_to_bc7_m6_table168[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,
+0x7C0000,0xFC0000,0xFC0000,0xFC0000,0x28000001,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0xFC0000,0xFC0000,0xFC0000,0x28000001,0xFC0000,0xFC0000,0xFC0000,0x28000001,0x28000001,0x4580000,0x540000,0x540000,0x2600000,0x680000,0x2700000,0x2700000,0x8C0000,0x2600000,0x680000,0xB00000,0xFC0000,
+0xB00000,0xB40000,0xB40000,0xB40000,0xB40000,0x10C0000,0x10C0000,0x10C0000,0xBF80000,0xBF80000,0x58000001,0x10C0000,0x10C0000,0x10C0000,0xBF80000,0xBF80000,0x58000001,0xBF80000,0xBF80000,0x58000001,0x58000001,0x10C0000,0x10C0000,0x10C0000,0xBF80000,0xBF80000,0x58000001,0xBF80000,0xBF80000,0x58000001,0x58000001,0xBF80000,
+0xBF80000,0x58000001,0x58000001,0x58000001,0xD00000,0xC00000,0xB40000,0xF40000,0x32C0000,0x17C0000,0x1B80000,0x1FF80000,0x2E00000,0x10C0000,0x17C0000,0x58000001,0x17C0000,0x1240000,0x3B00000,0x5DFC0000,0x90000001,0x3B00000,0x5DFC0000,0x90000001,0x5DFC0000,0x90000001,0x90000001,0x3B00000,0x5DFC0000,0x90000001,0x5DFC0000,0x90000001,
+0x90000001,0x5DFC0000,0x90000001,0x90000001,0x90000001,0x3B00000,0x5DFC0000,0x90000001,0x5DFC0000,0x90000001,0x90000001,0x5DFC0000,0x90000001,0x90000001,0x90000001,0x5DFC0000,0x90000001,0x90000001,0x90000001,0x90000001,0x36C0000,0x1380000,0x1380000,0x1EC0000,0x49F80000,0x77F40000,0x90000001,0x90000001,0x18C0000,0x17FC0000,0x8BE80000,0x90000001,
+0x33FC0000,0x8C2E54,0xFE681371,0xC2580FD9,0x90580FD9,0xFE3C0BBC,0xD42C039D,0x9A3805B5,0xA42C0994,0x8A240406,0x74280996,0xFE0C1590,0xD20004A2,0x961805A9,0xA80006E9,0x8C000042,0x7404062A,0x8A00152B,0x780008B3,0x6C000A83,0x5C00152B,0xCC2E54,0xB40014BB,0x8E000FFC,0x980011E6,0x8000080E,0x6E000BB6,0x80001C6F,0x74000EBF,0x66000F3F,0x5800189C,0x1A02E54,
+0x60001E64,0x5C001B96,0x50002227,0x44002E54,0xFE58170A,0xF88025CC,0xFA842794,0xFE2405E6,0xEA000061,0xB0000042,0x9204000A,0x86000173,0xFE3415FA,0xFE00042C,0x90000627,0x66000F3F,0x1242E54,0xB8152C,0xFE8C0581,0xB8840480,0x90840481,0xFE5C0642,0xC2540005,0x945C007D,0x9A540620,0x864C0132,0x74540622,0x114152B,0xD20004A2,0x90380481,0xA80006E9,0x8C000042,
+0x740C0622,0xFF8152B,0x780008B3,0x6C000A83,0x5C00152B,0x114152B,0xD20004A2,0x90380481,0xA80006E9,0x8C000042,0x740C0622,0xFF8152B,0x780008B3,0x6C000A83,0x5C00152B,0xFF8152B,0x780008B3,0x6C000A83,0x5C00152B,0x5C00152B,0xFE800BBE,0xFEAC1122,0xFEAC1101,0xFE4003CB,0xEA000061,0xB0000042,0x92080002,0x86000173,0xFE5C0BD5,0xFE1002E5,0x900005D6,0x6C000A83,
+0x18C152B,0x580FD8,0x580FD8,0x580FD8,0x580FD8,0xE42C0374,0xE42C0374,0xE42C0374,0x7A2C0374,0x7A2C0374,0x58280375,0xC8000480,0xC8000480,0xC8000480,0x82000005,0x82000005,0x5C0C005E,0x60000482,0x60000482,0x500000E1,0x40000482,0x2800FD8,0x2800FD8,0x2800FD8,0x6E000615,0x6E000615,0x520003EB,0x58000811,0x58000811,0x4C00037E,0x4000063B,0x1080FD8,
+0x1080FD8,0x3E0009BD,0x32000AC6,0x2A000FDB,0xFC380694,0xFE4C0B58,0x580FD8,0xFE100141,0xDA000005,0xA6000005,0x98000002,0x7600002D,0xFE1405F9,0xF6000172,0x7C0004C0,0x4C00037E,0xB80FD8,0x840480,0x840480,0x840480,0x840480,0xBA540000,0xBA540000,0xBA540000,0x70540000,0x70540000,0x58540001,0xC40480,0xC40480,0xC40480,0x82000005,0x82000005,
+0x5A240001,0x18C0480,0x18C0480,0x500000E1,0x40000482,0xC40480,0xC40480,0xC40480,0x82000005,0x82000005,0x5A240001,0x18C0480,0x18C0480,0x500000E1,0x40000482,0x18C0480,0x18C0480,0x500000E1,0x40000482,0x40000482,0xFE5801E1,0xF4780288,0x840480,0xFE2400A2,0xDA000005,0xA6000005,0x96040000,0x7600002D,0xFE340221,0xFC000082,0x1180480,0x500000E1,
+0x1180480,0xEC0620,0xFEB40004,0xACB40000,0x90B40001,0x35C0620,0xC44C0001,0x927C0001,0x33FC0620,0x8E00002D,0x74000622,0x35C0620,0xC44C0001,0x927C0001,0x33FC0620,0x8E00002D,0x74000622,0x33FC0620,0x8E00002D,0x74000622,0x74000622,0x35C0620,0xC44C0001,0x927C0001,0x33FC0620,0x8E00002D,0x74000622,0x33FC0620,0x8E00002D,0x74000622,0x74000622,0x33FC0620,
+0x8E00002D,0x74000622,0x74000622,0x74000622,0xFEB403F5,0xFC0620,0xFAE40451,0xFE580164,0xEA00003D,0xB2000022,0x90140001,0x8A0000C1,0xFE9803C8,0xFE380120,0x9A200000,0x74000622,0x1F40620,0x280374,0x280374,0x280374,0x280374,0x280374,0x280374,0x280374,0x280374,0x280374,0x280374,0x7E000000,0x7E000000,0x7E000000,0x7E000000,0x7E000000,
+0x7E000000,0x3E000000,0x3E000000,0x3E000000,0x28000001,0x23C0372,0x23C0372,0x23C0372,0x23C0372,0x23C0372,0x23C0372,0x2E000145,0x2E000145,0x2E000145,0x240000A9,0x7C0372,0x7C0372,0x7C0372,0x1C000212,0x14000372,0xF61C016D,0x280374,0x280374,0xFE040014,0xCC000000,0x9C000000,0x9C000000,0x66000000,0xF6000112,0xB4000092,0x4E000019,0x2E000145,
+0x580372,};
+static const uint32_t g_etc1_to_bc7_m6_table169[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x940000,0x940000,0x940000,0x940000,0x940000,
+0x940000,0x12C0000,0x12C0000,0x12C0000,0x30000001,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x12C0000,0x12C0000,0x12C0000,0x30000001,0x12C0000,0x12C0000,0x12C0000,0x30000001,0x30000001,0xC680000,0x640000,0x640000,0x740000,0x7C0000,0x880000,0x880000,0xA80000,0x740000,0x7C0000,0xD40000,0x12C0000,
+0xD40000,0xC40000,0xC40000,0xC40000,0xC40000,0x1240000,0x1240000,0x1240000,0x17F80000,0x17F80000,0x60000001,0x1240000,0x1240000,0x1240000,0x17F80000,0x17F80000,0x60000001,0x17F80000,0x17F80000,0x60000001,0x60000001,0x1240000,0x1240000,0x1240000,0x17F80000,0x17F80000,0x60000001,0x17F80000,0x17F80000,0x60000001,0x60000001,0x17F80000,
+0x17F80000,0x60000001,0x60000001,0x60000001,0xE40000,0xD00000,0xC40000,0x3080000,0x1480000,0x1A00000,0x1E00000,0x29FC0000,0x2F40000,0x1240000,0x1A00000,0x60000001,0x1A00000,0x1340000,0x1C80000,0x69FC0000,0x98000001,0x1C80000,0x69FC0000,0x98000001,0x69FC0000,0x98000001,0x98000001,0x1C80000,0x69FC0000,0x98000001,0x69FC0000,0x98000001,
+0x98000001,0x69FC0000,0x98000001,0x98000001,0x98000001,0x1C80000,0x69FC0000,0x98000001,0x69FC0000,0x98000001,0x98000001,0x69FC0000,0x98000001,0x98000001,0x98000001,0x69FC0000,0x98000001,0x98000001,0x98000001,0x98000001,0x3800000,0x1480000,0x1480000,0x7FC0000,0x55FC0000,0x81F40000,0x98000001,0x98000001,0x1A40000,0x29FC0000,0x93F80000,0x98000001,
+0x41FC0000,0x9832DC,0xFE741765,0xCC6412C4,0x986412C5,0xFE440E76,0xDE340525,0xA0440799,0xAE340B04,0x942C055E,0x7C300B06,0xFE18169C,0xE2000481,0xA0200679,0xB4000691,0x96000012,0x7C080656,0x9600152B,0x840007FB,0x720009EB,0x6400152B,0xE032DC,0xC0001733,0x980012C5,0xA2001322,0x8C000906,0x7A000CD6,0x8C001DCF,0x7C000F22,0x6E000F63,0x62001933,0x1C432DC,
+0x6C00213C,0x60001E14,0x5600247F,0x4A0032DC,0xFE641ADA,0xFE8C29F4,0xFE8C2C04,0xFE2C081A,0xFA00002A,0xBC00000D,0x9C08003B,0x900000E2,0xFE4419D3,0xFE100626,0x960005A9,0x6E000F63,0x13C32DC,0xC8152C,0xFEA405E1,0xC0940480,0x98940481,0xFE740672,0xCA640005,0x9C6C007D,0xA2640620,0x8E5C0132,0x7C640622,0x12C152B,0xE2000481,0x98480481,0xB4000691,0x96000012,
+0x7C1C0622,0x1BF8152B,0x840007FB,0x720009EB,0x6400152B,0x12C152B,0xE2000481,0x98480481,0xB4000691,0x96000012,0x7C1C0622,0x1BF8152B,0x840007FB,0x720009EB,0x6400152B,0x1BF8152B,0x840007FB,0x720009EB,0x6400152B,0x6400152B,0xFE940C03,0xF6BC1178,0xFAC41144,0xFE540456,0xFA00002A,0xBC00000D,0x9A180002,0x900000E2,0xFE780C41,0xFE240375,0x9A000551,0x720009EB,
+0x1AC152B,0x6412C4,0x6412C4,0x6412C4,0x6412C4,0xF43404E4,0xF43404E4,0xF43404E4,0x843404E4,0x843404E4,0x603004E5,0xE0000480,0xE0000480,0xE0000480,0x90000005,0x90000005,0x641000C2,0x6C000482,0x6C000482,0x5C0000A9,0x48000482,0x9012C3,0x9012C3,0x9012C3,0x7A000785,0x7A000785,0x5E000533,0x620008E2,0x620008E2,0x520003DE,0x460006A3,0x12412C3,
+0x12412C3,0x44000B9D,0x3E000C56,0x300012C3,0xFE3C08B8,0xF4580E45,0x6412C4,0xFE1C0258,0xF0000001,0xB8000001,0xA6040018,0x8000000D,0xFE200802,0xFE0001C8,0x860004C8,0x520003DE,0xD012C3,0x940480,0x940480,0x940480,0x940480,0xC2640000,0xC2640000,0xC2640000,0x78640000,0x78640000,0x60640001,0xDC0480,0xDC0480,0xDC0480,0x8C0C0001,0x8C0C0001,
+0x62340001,0x1BC0480,0x1BC0480,0x5C0000A9,0x48000482,0xDC0480,0xDC0480,0xDC0480,0x8C0C0001,0x8C0C0001,0x62340001,0x1BC0480,0x1BC0480,0x5C0000A9,0x48000482,0x1BC0480,0x1BC0480,0x5C0000A9,0x48000482,0x48000482,0xFA6C0200,0xFC880288,0x940480,0xFE3400B9,0xEE040000,0xB6040000,0x9E140000,0x8000000D,0xFA480244,0xFC140091,0x1380480,0x5C0000A9,
+0x1380480,0xFC0620,0xFEC8000D,0xB4C40000,0x98C40001,0x3740620,0xCC5C0001,0x9A8C0001,0x3FFC0620,0x96000012,0x7C000622,0x3740620,0xCC5C0001,0x9A8C0001,0x3FFC0620,0x96000012,0x7C000622,0x3FFC0620,0x96000012,0x7C000622,0x7C000622,0x3740620,0xCC5C0001,0x9A8C0001,0x3FFC0620,0x96000012,0x7C000622,0x3FFC0620,0x96000012,0x7C000622,0x7C000622,0x3FFC0620,
+0x96000012,0x7C000622,0x7C000622,0x7C000622,0xFAC80422,0x10C0620,0xFEEC0469,0xFE740190,0xF8040029,0xBC00000D,0x98240001,0x90000091,0xFEAC03F5,0xFE4C013D,0xA2300000,0x7C000622,0xDFC0620,0x3004E4,0x3004E4,0x3004E4,0x3004E4,0x3004E4,0x3004E4,0x3004E4,0x3004E4,0x3004E4,0x3004E4,0x96000000,0x96000000,0x96000000,0x96000000,0x96000000,
+0x96000000,0x4A000000,0x4A000000,0x4A000000,0x30000001,0x4804E2,0x4804E2,0x4804E2,0x4804E2,0x4804E2,0x4804E2,0x3A0001CD,0x3A0001CD,0x3A0001CD,0x2E0000EA,0x9404E2,0x9404E2,0x9404E2,0x20000305,0x180004E2,0xFA240265,0x3004E4,0x3004E4,0xFE100071,0xF4000000,0xBA000000,0xBA000000,0x7A000000,0xF60001C2,0xD60000CD,0x5E000024,0x3A0001CD,
+0x6804E2,};
+static const uint32_t g_etc1_to_bc7_m6_table170[] = {
+0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x80000,
+0x80000,0x80000,0x80000,0x1,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x80000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,
+0xAC0000,0x15C0000,0x15C0000,0x15C0000,0x38000001,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0xAC0000,0x15C0000,0x15C0000,0x15C0000,0x38000001,0x15C0000,0x15C0000,0x15C0000,0x38000001,0x38000001,0x7C0000,0x740000,0x740000,0x6840000,0x900000,0x9C0000,0x9C0000,0x2C00000,0x6840000,0x900000,0xF40000,0x15C0000,
+0xF40000,0xD40000,0xD40000,0xD40000,0xD40000,0x13C0000,0x13C0000,0x13C0000,0x21FC0000,0x21FC0000,0x68000001,0x13C0000,0x13C0000,0x13C0000,0x21FC0000,0x21FC0000,0x68000001,0x21FC0000,0x21FC0000,0x68000001,0x68000001,0x13C0000,0x13C0000,0x13C0000,0x21FC0000,0x21FC0000,0x68000001,0x21FC0000,0x21FC0000,0x68000001,0x68000001,0x21FC0000,
+0x21FC0000,0x68000001,0x68000001,0x68000001,0x4F40000,0x8E00000,0xD40000,0x1200000,0x1640000,0x1C00000,0x5FC0000,0x35F80000,0x3080000,0x13C0000,0x1C00000,0x68000001,0x1C00000,0x1440000,0x1E00000,0x75FC0000,0xA0000001,0x1E00000,0x75FC0000,0xA0000001,0x75FC0000,0xA0000001,0xA0000001,0x1E00000,0x75FC0000,0xA0000001,0x75FC0000,0xA0000001,
+0xA0000001,0x75FC0000,0xA0000001,0xA0000001,0xA0000001,0x1E00000,0x75FC0000,0xA0000001,0x75FC0000,0xA0000001,0xA0000001,0x75FC0000,0xA0000001,0xA0000001,0xA0000001,0x75FC0000,0xA0000001,0xA0000001,0xA0000001,0xA0000001,0x3940000,0x5580000,0x5580000,0x1BFC0000,0x63FC0000,0x8BF40000,0xA0000001,0xA0000001,0x1B80000,0x39FC0000,0x9DCC0000,0xA0000001,
+0x51FC0000,0xA43680,0xFE801AD5,0xD470152D,0xA070152D,0xFE5C1112,0xE440067D,0xAA4C0931,0xB83C0C40,0x9A38068A,0x843C0C42,0xFE3017F0,0xF0080485,0xAA280735,0xC6000655,0xA0080012,0x86100686,0xA004152B,0x90000767,0x7E00095F,0x6C04152B,0xF43680,0xD20018EB,0xA204152C,0xAE0013F2,0x9800099A,0x80000D92,0x92001E87,0x86000EDF,0x76000F1F,0x68001953,0x1F03680,
+0x7200234C,0x6C001F94,0x5C00261B,0x50003684,0xFE781E55,0xFE8C2DE0,0xF8A02FFD,0xFE400A6F,0xFE0C0052,0xC804000E,0xA4100086,0x98000089,0xFE541CF7,0xFE18084E,0xA4000539,0x76000F1F,0x15C3680,0xD8152C,0xFEB00631,0xC8A40480,0xA0A40481,0xFE8006A6,0xD2740005,0xA47C007D,0xAA740620,0x966C0132,0x84740622,0x144152B,0xEA100481,0xA0580481,0xC6000651,0xA008000E,
+0x842C0622,0x27F8152B,0x90000763,0x7E00095B,0x6C00152B,0x144152B,0xEA100481,0xA0580481,0xC6000651,0xA008000E,0x842C0622,0x27F8152B,0x90000763,0x7E00095B,0x6C00152B,0x27F8152B,0x90000763,0x7E00095B,0x6C00152B,0x6C00152B,0xFEA00C86,0xFECC1178,0xFECC1164,0xFE6C04E5,0xFE100035,0xC410000D,0xA2280002,0x98000085,0xFE880CA0,0xFE4003DB,0xA40004F9,0x7E00095B,
+0x1D0152B,0x70152C,0x70152C,0x70152C,0x70152C,0xFE3C0624,0xFE3C0624,0xFE3C0624,0x8E3C0620,0x8E3C0620,0x683C0621,0xF4040480,0xF4040480,0xF4040480,0x9E040011,0x9E040011,0x6C180131,0x78040480,0x78040480,0x64000081,0x50040482,0xA4152B,0xA4152B,0xA4152B,0x86000889,0x86000889,0x68000641,0x6E000966,0x6E000966,0x5E0003E6,0x4C0006C3,0x14C152B,
+0x14C152B,0x4A000D01,0x44000D62,0x3600152B,0xFE4C0A8D,0xFA641079,0x70152C,0xFE2C037D,0xFE08000D,0xC608000C,0xB6080038,0x8E040001,0xFC3009DD,0xFE0002CC,0x960004B9,0x5E0003E6,0xE8152B,0xA40480,0xA40480,0xA40480,0xA40480,0xCA740000,0xCA740000,0xCA740000,0x80740000,0x80740000,0x68740001,0xF40480,0xF40480,0xF40480,0x941C0001,0x941C0001,
+0x6A440001,0x1F00480,0x1F00480,0x6400007D,0x50000482,0xF40480,0xF40480,0xF40480,0x941C0001,0x941C0001,0x6A440001,0x1F00480,0x1F00480,0x6400007D,0x50000482,0x1F00480,0x1F00480,0x6400007D,0x50000482,0x50000482,0xFE740220,0xF49802AD,0xA40480,0xFE4400DA,0xF6140000,0xBE140000,0xA6240000,0x8E000001,0xF2600265,0xFE2400A4,0x15C0480,0x6400007D,
+0x15C0480,0x10C0620,0xFEDC0020,0xBCD40000,0xA0D40001,0x38C0620,0xD46C0001,0xA29C0001,0x4BFC0620,0xA0000005,0x84000622,0x38C0620,0xD46C0001,0xA29C0001,0x4BFC0620,0xA0000005,0x84000622,0x4BFC0620,0xA0000005,0x84000622,0x84000622,0x38C0620,0xD46C0001,0xA29C0001,0x4BFC0620,0xA0000005,0x84000622,0x4BFC0620,0xA0000005,0x84000622,0x84000622,0x4BFC0620,
+0xA0000005,0x84000622,0x84000622,0x84000622,0xFED00442,0x71C0620,0xFB040480,0xFC9001C4,0xFE100035,0xCA000004,0xA0340001,0x9C00006A,0xF4C80422,0xFE640179,0xAA400000,0x84000622,0x1DF80620,0x3C0620,0x3C0620,0x3C0620,0x3C0620,0x3C0620,0x3C0620,0x3C0620,0x3C0620,0x3C0620,0x3C0620,0xAC040000,0xAC040000,0xAC040000,0xAC040000,0xAC040000,
+0xAC040000,0x54040000,0x54040000,0x54040000,0x38040001,0x580620,0x580620,0x580620,0x580620,0x580620,0x580620,0x4600021D,0x4600021D,0x4600021D,0x340000FA,0xB00620,0xB00620,0xB00620,0x260003A9,0x1C000622,0xFE2C0349,0x3C0620,0x3C0620,0xFA1800F4,0xFC08000D,0xD2040000,0xD2040000,0x8A040000,0xFA08028A,0xFE0000E8,0x66000019,0x4600021D,
+0x7C0620,};
+static const uint32_t g_etc1_to_bc7_m6_table171[] = {
+0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x380000,
+0x380000,0x380000,0x380000,0x8000001,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x2140000,0x2140000,0x2140000,0x1C0000,0x280000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,
+0xC40000,0x18C0000,0x18C0000,0x18C0000,0x40000001,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0x18C0000,0x18C0000,0x18C0000,0x40000001,0x18C0000,0x18C0000,0x18C0000,0x40000001,0x40000001,0x8C0000,0x840000,0x840000,0x2980000,0xA40000,0xB40000,0xB40000,0xDC0000,0x2980000,0xA40000,0x1180000,0x18C0000,
+0x1180000,0xE40000,0xE40000,0xE40000,0xE40000,0x3500000,0x3500000,0x3500000,0x2DFC0000,0x2DFC0000,0x70000001,0x3500000,0x3500000,0x3500000,0x2DFC0000,0x2DFC0000,0x70000001,0x2DFC0000,0x2DFC0000,0x70000001,0x70000001,0x3500000,0x3500000,0x3500000,0x2DFC0000,0x2DFC0000,0x70000001,0x2DFC0000,0x2DFC0000,0x70000001,0x70000001,0x2DFC0000,
+0x2DFC0000,0x70000001,0x70000001,0x70000001,0x1080000,0xF40000,0xE40000,0x3340000,0x1800000,0x1E40000,0x13F80000,0x3FFC0000,0x31C0000,0x3500000,0x1E40000,0x70000001,0x1E40000,0x1540000,0x1F80000,0x81FC0000,0xA8000001,0x1F80000,0x81FC0000,0xA8000001,0x81FC0000,0xA8000001,0xA8000001,0x1F80000,0x81FC0000,0xA8000001,0x81FC0000,0xA8000001,
+0xA8000001,0x81FC0000,0xA8000001,0xA8000001,0xA8000001,0x1F80000,0x81FC0000,0xA8000001,0x81FC0000,0xA8000001,0xA8000001,0x81FC0000,0xA8000001,0xA8000001,0xA8000001,0x81FC0000,0xA8000001,0xA8000001,0xA8000001,0xA8000001,0x3A80000,0xD680000,0xD680000,0x2FFC0000,0x71FC0000,0x95F40000,0xA8000001,0xA8000001,0x3CC0000,0x4BFC0000,0xA5DC0000,0xA8000001,
+0x5FFC0000,0xB43680,0xFE8C1BA1,0xDC80152D,0xA880152D,0xFE6811EA,0xEC50067D,0xB25C0931,0xC04C0C40,0xA248068A,0x8C4C0C42,0xFE441883,0xF8180485,0xB2380735,0xCC0C0651,0xA8180012,0x8E200686,0xA814152B,0x98040733,0x86040933,0x7414152B,0x10C3680,0xE20017A1,0xAA14152C,0xC0001242,0xA2000823,0x8C000CC2,0xA2001CE9,0x92000CD7,0x80000D2B,0x7000182C,0xBF83680,
+0x7E0021E4,0x72001DD4,0x660024F4,0x58003684,0xFE8C1F58,0xFCA82E0A,0xFEAC3001,0xFE540B96,0xFE2000B6,0xD014000E,0xAC200086,0xA20C0082,0xFE701E35,0xFE300991,0xB00004B1,0x80000D2B,0x17C3680,0xE8152C,0xFEC40690,0xD0B40480,0xA8B40481,0xFE9806E6,0xDA840005,0xAC8C007D,0xB2840620,0x9E7C0132,0x8C840622,0x15C152B,0xF2200481,0xA8680481,0xD2000629,0xA818000E,
+0x8C3C0622,0x33F8152B,0x960006DB,0x840008D3,0x7400152B,0x15C152B,0xF2200481,0xA8680481,0xD2000629,0xA818000E,0x8C3C0622,0x33F8152B,0x960006DB,0x840008D3,0x7400152B,0x33F8152B,0x960006DB,0x840008D3,0x7400152B,0x7400152B,0xFEB40CC9,0xF6DC11D2,0xFAE411A1,0xFE78057E,0xFE280069,0xCC20000D,0xAA380002,0xA400004B,0xFE980D11,0xFE54047D,0xB00004B0,0x840008D3,
+0x1F0152B,0x80152C,0x80152C,0x80152C,0x80152C,0xFE500631,0xFE500631,0xFE500631,0x964C0620,0x964C0620,0x704C0621,0xFC140480,0xFC140480,0xFC140480,0xA6140011,0xA6140011,0x74280131,0x80140480,0x80140480,0x6C0C007A,0x58140482,0xBC152B,0xBC152B,0xBC152B,0x980007B9,0x980007B9,0x70040621,0x7A000866,0x7A000866,0x680002AA,0x580005EB,0x17C152B,
+0x17C152B,0x56000C19,0x4A000C82,0x3E00152B,0xFC640B12,0xFE6C10C1,0x80152C,0xFE3C03E0,0xFE1C001D,0xCE18000C,0xBE180038,0x96140001,0xFE3C0A38,0xFE18031E,0xA8000481,0x680002AA,0x10C152B,0xB40480,0xB40480,0xB40480,0xB40480,0xD2840000,0xD2840000,0xD2840000,0x88840000,0x88840000,0x70840001,0x10C0480,0x10C0480,0x10C0480,0x9C2C0001,0x9C2C0001,
+0x72540001,0xBF80480,0xBF80480,0x6C00004A,0x58000482,0x10C0480,0x10C0480,0x10C0480,0x9C2C0001,0x9C2C0001,0x72540001,0xBF80480,0xBF80480,0x6C00004A,0x58000482,0xBF80480,0xBF80480,0x6C00004A,0x58000482,0x58000482,0xFE900221,0xFCA802AD,0xB40480,0xFE5C00E1,0xFE240000,0xC6240000,0xAE340000,0x980C0000,0xFA700265,0xFA4000C8,0x17C0480,0x6C00004A,
+0x17C0480,0x11C0620,0xFEEC0041,0xC4E40000,0xA8E40001,0x3A40620,0xDC7C0001,0xAAAC0001,0x57FC0620,0xA8000001,0x8C000622,0x3A40620,0xDC7C0001,0xAAAC0001,0x57FC0620,0xA8000001,0x8C000622,0x57FC0620,0xA8000001,0x8C000622,0x8C000622,0x3A40620,0xDC7C0001,0xAAAC0001,0x57FC0620,0xA8000001,0x8C000622,0x57FC0620,0xA8000001,0x8C000622,0x8C000622,0x57FC0620,
+0xA8000001,0x8C000622,0x8C000622,0x8C000622,0xFAF00451,0xF2C0620,0xFF0C04A0,0xFEA001F9,0xFE380055,0xD4040000,0xA8440001,0xA400004A,0xFCD80422,0xFE8401A5,0xB2500000,0x8C000622,0x2BFC0620,0x4C0620,0x4C0620,0x4C0620,0x4C0620,0x4C0620,0x4C0620,0x4C0620,0x4C0620,0x4C0620,0x4C0620,0xB4140000,0xB4140000,0xB4140000,0xB4140000,0xB4140000,
+0xB4140000,0x5C140000,0x5C140000,0x5C140000,0x40140001,0x700620,0x700620,0x700620,0x700620,0x700620,0x700620,0x52000185,0x52000185,0x52000185,0x4000007A,0xE40620,0xE40620,0xE40620,0x32000321,0x24000622,0xF63C0374,0x4C0620,0x4C0620,0xFE2C0109,0xFC1C0019,0xDA140000,0xDA140000,0x92140000,0xFC1C02AD,0xFA0C00DD,0x7A040000,0x52000185,
+0xA00620,};
+static const uint32_t g_etc1_to_bc7_m6_table172[] = {
+0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x700000,
+0x700000,0x700000,0x700000,0x12000000,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x280000,0x280000,0x280000,0x380000,0x500000,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,
+0x2DC0000,0x1C40000,0x1C40000,0x1C40000,0x4A000000,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x1C40000,0x1C40000,0x1C40000,0x4A000000,0x1C40000,0x1C40000,0x1C40000,0x4A000000,0x4A000000,0xA00000,0x940001,0x940001,0x4AC0000,0xBC0000,0xCC0000,0xCC0000,0xFC0000,0x4AC0000,0xBC0000,0x13C0000,0x1C40000,
+0x13C0000,0xF40001,0xF40001,0xF40001,0xF40001,0x16C0000,0x16C0000,0x16C0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x16C0000,0x16C0000,0x16C0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x3BFC0000,0x3BFC0000,0x7A000000,0x7A000000,0x16C0000,0x16C0000,0x16C0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x3BFC0000,0x3BFC0000,0x7A000000,0x7A000000,0x3BFC0000,
+0x3BFC0000,0x7A000000,0x7A000000,0x7A000000,0x51C0000,0xB040000,0xF40001,0x34C0000,0x19C0000,0x7FC0000,0x21FC0000,0x4BFC0000,0x1340000,0x16C0000,0x7FC0000,0x7A000000,0x7FC0000,0x1640001,0x19FC0000,0x8FF80000,0xB2000000,0x19FC0000,0x8FF80000,0xB2000000,0x8FF80000,0xB2000000,0xB2000000,0x19FC0000,0x8FF80000,0xB2000000,0x8FF80000,0xB2000000,
+0xB2000000,0x8FF80000,0xB2000000,0xB2000000,0xB2000000,0x19FC0000,0x8FF80000,0xB2000000,0x8FF80000,0xB2000000,0xB2000000,0x8FF80000,0xB2000000,0xB2000000,0xB2000000,0x8FF80000,0xB2000000,0xB2000000,0xB2000000,0xB2000000,0x1C00000,0x77C0000,0x77C0000,0x45FC0000,0x7FFC0000,0xA1F00000,0xB2000000,0xB2000000,0x1E80000,0x5DFC0000,0xAFD00000,0xB2000000,
+0x71FC0000,0xC43684,0xFEA41C83,0xE690152B,0xB290152B,0xFE801302,0xF664067B,0xBA6C0933,0xC8600C42,0xAC5C0686,0x965C0C42,0xFE5C1959,0xFE28048A,0xBA480733,0xD620064F,0xB0280012,0x9630068A,0xB224152C,0xA0140735,0x8E140931,0x7C24152D,0x3243680,0xF400169F,0xB228152B,0xD20010AA,0xAE000711,0x94000C50,0xAE001B7F,0x9E000AD1,0x8C000B51,0x7A0016F9,0x17FC3680,
+0x8A00206C,0x7E001C08,0x720023A4,0x62003680,0xFEA0204E,0xF6BC2EC4,0xF8C0308C,0xFE6C0D33,0xFE38015B,0xDA28000E,0xB6340082,0xAA1C0086,0xFE781F23,0xFE440AEA,0xBA0C049F,0x8C000B51,0x1A43680,0xFC152B,0xFED40722,0xD8C80482,0xB2C40482,0xFEB00749,0xE2940006,0xB6A0007A,0xBA980621,0xA8900131,0x96940621,0x374152B,0xFC300481,0xB2780480,0xDE080621,0xB0280011,
+0x964C0620,0x3FFC152B,0xA6000662,0x9000084C,0x7C00152C,0x374152B,0xFC300481,0xB2780480,0xDE080621,0xB0280011,0x964C0620,0x3FFC152B,0xA6000662,0x9000084C,0x7C00152C,0x3FFC152B,0xA6000662,0x9000084C,0x7C00152C,0x7C00152C,0xFED00D38,0xFEEC11D9,0xFEEC11E2,0xFE940602,0xFE4800C6,0xD630000D,0xB24C0001,0xAE04003D,0xFEB40D8E,0xFE700541,0xBC000486,0x9000084C,
+0xDFC152B,0x90152B,0x90152B,0x90152B,0x90152B,0xFE600653,0xFE600653,0xFE600653,0x9E600622,0x9E600622,0x7A5C0622,0xFE280489,0xFE280489,0xFE280489,0xB028000E,0xB028000E,0x7E3C0132,0x88280481,0x88280481,0x741C007D,0x62240481,0xD4152B,0xD4152B,0xD4152B,0xA80006F1,0xA80006F1,0x7A140620,0x86000771,0x86000771,0x7400019D,0x62000529,0x1B0152B,
+0x1B0152B,0x60000B4C,0x56000B91,0x4800152C,0xFE740B63,0xFC8810CB,0x90152B,0xFE54045A,0xFE300042,0xD628000B,0xC628003B,0x9E240002,0xFE500A8E,0xFE30038A,0xB2100480,0x7400019D,0x130152B,0xC40482,0xC40482,0xC40482,0xC40482,0xDA980001,0xDA980001,0xDA980001,0x92940001,0x92940001,0x7A940001,0x3240480,0x3240480,0x3240480,0xA63C0001,0xA63C0001,
+0x7A680000,0x17FC0480,0x17FC0480,0x78000028,0x62000480,0x3240480,0x3240480,0x3240480,0xA63C0001,0xA63C0001,0x7A680000,0x17FC0480,0x17FC0480,0x78000028,0x62000480,0x17FC0480,0x17FC0480,0x78000028,0x62000480,0x62000480,0xFEA00244,0xF6BC02D2,0xC40482,0xFE780109,0xFC3C0004,0xD0340000,0xB6480000,0xA21C0000,0xF8880288,0xFC5800DD,0x1A40480,0x78000028,
+0x1A40480,0x12C0622,0xFF00006A,0xCEF40001,0xB2F40001,0x1C00620,0xE68C0001,0xB2C00000,0x65F80620,0xB2100000,0x96000620,0x1C00620,0xE68C0001,0xB2C00000,0x65F80620,0xB2100000,0x96000620,0x65F80620,0xB2100000,0x96000620,0x96000620,0x1C00620,0xE68C0001,0xB2C00000,0x65F80620,0xB2100000,0x96000620,0x65F80620,0xB2100000,0x96000620,0x96000620,0x65F80620,
+0xB2100000,0x96000620,0x96000620,0x96000620,0xFEF80479,0x9400620,0xFD2804B1,0xFEC00225,0xFE500089,0xDC180000,0xB2500000,0xAC000034,0xFEF00451,0xFEA001E5,0xBA640001,0x96000620,0x3DF80620,0x5C0622,0x5C0622,0x5C0622,0x5C0622,0x5C0622,0x5C0622,0x5C0622,0x5C0622,0x5C0622,0x5C0622,0xBA280001,0xBA280001,0xBA280001,0xBA280001,0xBA280001,
+0xBA280001,0x66240001,0x66240001,0x66240001,0x4A240001,0x8C0620,0x8C0620,0x8C0620,0x8C0620,0x8C0620,0x8C0620,0x620000E9,0x620000E9,0x620000E9,0x4800001D,0x1180620,0x1180620,0x1180620,0x3E0002A1,0x2E000620,0xFE4C037A,0x5C0622,0x5C0622,0xFE3C0122,0xFC300029,0xE2280001,0xE2280001,0x9A280001,0xF83002D2,0xFC1C00F4,0x82180000,0x620000E9,
+0xC80620,};
+static const uint32_t g_etc1_to_bc7_m6_table173[] = {
+0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0xA00000,
+0xA00000,0xA00000,0xA00000,0x1A000000,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x4380000,0x4380000,0x4380000,0x500000,0x700000,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x2F40000,
+0x2F40000,0x1F40000,0x1F40000,0x1F40000,0x52000000,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x1F40000,0x1F40000,0x1F40000,0x52000000,0x1F40000,0x1F40000,0x1F40000,0x52000000,0x52000000,0xB00000,0xA40001,0xA40001,0xC00000,0xD00000,0xE00000,0xE00000,0x3140000,0xC00000,0xD00000,0x1600000,0x1F40000,
+0x1600000,0x1040001,0x1040001,0x1040001,0x1040001,0x1840000,0x1840000,0x1840000,0x47FC0000,0x47FC0000,0x82000000,0x1840000,0x1840000,0x1840000,0x47FC0000,0x47FC0000,0x82000000,0x47FC0000,0x47FC0000,0x82000000,0x82000000,0x1840000,0x1840000,0x1840000,0x47FC0000,0x47FC0000,0x82000000,0x47FC0000,0x47FC0000,0x82000000,0x82000000,0x47FC0000,
+0x47FC0000,0x82000000,0x82000000,0x82000000,0x1300000,0x1180000,0x1040001,0x1640000,0x1B80000,0x17FC0000,0x2FFC0000,0x57F80000,0x1480000,0x1840000,0x17FC0000,0x82000000,0x17FC0000,0x1740001,0x31FC0000,0x9BF80000,0xBA000000,0x31FC0000,0x9BF80000,0xBA000000,0x9BF80000,0xBA000000,0xBA000000,0x31FC0000,0x9BF80000,0xBA000000,0x9BF80000,0xBA000000,
+0xBA000000,0x9BF80000,0xBA000000,0xBA000000,0xBA000000,0x31FC0000,0x9BF80000,0xBA000000,0x9BF80000,0xBA000000,0xBA000000,0x9BF80000,0xBA000000,0xBA000000,0xBA000000,0x9BF80000,0xBA000000,0xBA000000,0xBA000000,0xBA000000,0x1D40000,0xF8C0000,0xF8C0000,0x59FC0000,0x8DFC0000,0xABF00000,0xBA000000,0xBA000000,0x1FC0000,0x6FFC0000,0xB7E00000,0xBA000000,
+0x7FFC0000,0xD43684,0xFEB01D6B,0xEEA0152B,0xBAA0152B,0xFE8C1422,0xFE74067B,0xC27C0933,0xD0700C42,0xB46C0686,0x9E6C0C42,0xFE681A21,0xFE4004BA,0xC2580733,0xDE30064F,0xB8380012,0x9E40068A,0xBA34152C,0xA8240735,0x96240931,0x8434152D,0x33C3680,0xFE04164D,0xBA38152B,0xE2000F5A,0xBA000681,0x9E080C40,0xBA001A5F,0xA8000936,0x940009ED,0x82001640,0x23FC3680,
+0x96001F3C,0x84001A90,0x78002270,0x6A003680,0xFEA82162,0xFECC2EC4,0xFECC30A4,0xFE800E82,0xFE4C0223,0xE238000E,0xBE440082,0xB22C0086,0xFE902009,0xFE5C0C52,0xC21C049F,0x940009ED,0x1C83680,0x10C152B,0xFEE80793,0xE0D80482,0xBAD40482,0xFEC407A3,0xEAA40006,0xBEB0007A,0xC2A80621,0xB0A00131,0x9EA40621,0x38C152B,0xFE4C0491,0xBA880480,0xE6180621,0xB8380011,
+0x9E5C0620,0x4BFC152B,0xAC0005E6,0x960007E4,0x8400152C,0x38C152B,0xFE4C0491,0xBA880480,0xE6180621,0xB8380011,0x9E5C0620,0x4BFC152B,0xAC0005E6,0x960007E4,0x8400152C,0x4BFC152B,0xAC0005E6,0x960007E4,0x8400152C,0x8400152C,0xFEE40DD9,0xF900122B,0xFB041203,0xFEB006D2,0xFE680131,0xDE40000D,0xBA5C0001,0xB80C0038,0xFEC40DFB,0xFE8405C2,0xC6040480,0x960007E4,
+0x1DF8152B,0xA0152B,0xA0152B,0xA0152B,0xA0152B,0xFE740672,0xFE740672,0xFE740672,0xA6700622,0xA6700622,0x826C0622,0xFE3C049B,0xFE3C049B,0xFE3C049B,0xB838000E,0xB838000E,0x864C0132,0x90380481,0x90380481,0x7C2C007D,0x6A340481,0xEC152B,0xEC152B,0xEC152B,0xBA000681,0xBA000681,0x82240620,0x980006B1,0x980006B1,0x7A0000E9,0x680004B9,0x1E4152B,
+0x1E4152B,0x6C000A8C,0x5C000AD1,0x5000152C,0xFE840BAE,0xF4981122,0xA0152B,0xFE6804E6,0xFE440072,0xDE38000B,0xCE38003B,0xA6340002,0xFE640B11,0xFE440409,0xBA200480,0x7A0000E9,0x154152B,0xD40482,0xD40482,0xD40482,0xD40482,0xE2A80001,0xE2A80001,0xE2A80001,0x9AA40001,0x9AA40001,0x82A40001,0x33C0480,0x33C0480,0x33C0480,0xAE4C0001,0xAE4C0001,
+0x82780000,0x23FC0480,0x23FC0480,0x7E000014,0x6A000480,0x33C0480,0x33C0480,0x33C0480,0xAE4C0001,0xAE4C0001,0x82780000,0x23FC0480,0x23FC0480,0x7E000014,0x6A000480,0x23FC0480,0x23FC0480,0x7E000014,0x6A000480,0x6A000480,0xFAB40265,0xFECC02D2,0xD40482,0xFE880122,0xFE540008,0xD8440000,0xBE580000,0xAA2C0000,0xFE940290,0xFE6800F4,0x1C80480,0x7E000014,
+0x1C80480,0x13C0622,0xFF1800A2,0xD7040001,0xBB040001,0x1D80620,0xEE9C0001,0xBAD00000,0x71F80620,0xBA200000,0x9E000620,0x1D80620,0xEE9C0001,0xBAD00000,0x71F80620,0xBA200000,0x9E000620,0x71F80620,0xBA200000,0x9E000620,0x9E000620,0x1D80620,0xEE9C0001,0xBAD00000,0x71F80620,0xBA200000,0x9E000620,0x71F80620,0xBA200000,0x9E000620,0x9E000620,0x71F80620,
+0xBA200000,0x9E000620,0x9E000620,0x9E000620,0xFF140482,0x1540620,0xF53804E2,0xFED80269,0xFE7C00B5,0xE4280000,0xBA600000,0xB6000019,0xF7080480,0xFEC00221,0xC2740001,0x9E000620,0x4BFC0620,0x6C0622,0x6C0622,0x6C0622,0x6C0622,0x6C0622,0x6C0622,0x6C0622,0x6C0622,0x6C0622,0x6C0622,0xC2380001,0xC2380001,0xC2380001,0xC2380001,0xC2380001,
+0xC2380001,0x6E340001,0x6E340001,0x6E340001,0x52340001,0xA40620,0xA40620,0xA40620,0xA40620,0xA40620,0xA40620,0x74000089,0x74000089,0x74000089,0x52000000,0x14C0620,0x14C0620,0x14C0620,0x4400022D,0x36000620,0xF860039D,0x6C0622,0x6C0622,0xFE4C013D,0xFE3C003A,0xEA380001,0xEA380001,0xA2380001,0xFE3C02DA,0xFC300109,0x8A280000,0x74000089,
+0xE80620,};
+static const uint32_t g_etc1_to_bc7_m6_table174[] = {
+0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0xD00000,
+0xD00000,0xD00000,0xD00000,0x22000000,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0xC480000,0xC480000,0xC480000,0x680000,0x940000,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0xB40001,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0x30C0000,
+0x30C0000,0xBFC0000,0xBFC0000,0xBFC0000,0x5A000000,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0x30C0000,0xBFC0000,0xBFC0000,0xBFC0000,0x5A000000,0xBFC0000,0xBFC0000,0xBFC0000,0x5A000000,0x5A000000,0x8C00000,0xB40001,0xB40001,0xD40000,0xE40000,0xF80000,0xF80000,0x1300000,0xD40000,0xE40000,0x1800000,0xBFC0000,
+0x1800000,0x1140001,0x1140001,0x1140001,0x1140001,0x19C0000,0x19C0000,0x19C0000,0x53FC0000,0x53FC0000,0x8A000000,0x19C0000,0x19C0000,0x19C0000,0x53FC0000,0x53FC0000,0x8A000000,0x53FC0000,0x53FC0000,0x8A000000,0x8A000000,0x19C0000,0x19C0000,0x19C0000,0x53FC0000,0x53FC0000,0x8A000000,0x53FC0000,0x53FC0000,0x8A000000,0x8A000000,0x53FC0000,
+0x53FC0000,0x8A000000,0x8A000000,0x8A000000,0x1440000,0x1280000,0x1140001,0x3780000,0x1D40000,0x25FC0000,0x3DF80000,0x61FC0000,0x15C0000,0x19C0000,0x25FC0000,0x8A000000,0x25FC0000,0x1840001,0x49FC0000,0xA7F80000,0xC2000000,0x49FC0000,0xA7F80000,0xC2000000,0xA7F80000,0xC2000000,0xC2000000,0x49FC0000,0xA7F80000,0xC2000000,0xA7F80000,0xC2000000,
+0xC2000000,0xA7F80000,0xC2000000,0xC2000000,0xC2000000,0x49FC0000,0xA7F80000,0xC2000000,0xA7F80000,0xC2000000,0xC2000000,0xA7F80000,0xC2000000,0xC2000000,0xC2000000,0xA7F80000,0xC2000000,0xC2000000,0xC2000000,0xC2000000,0x1E80000,0x1A00000,0x1A00000,0x6DFC0000,0x9BFC0000,0xB5F00000,0xC2000000,0xC2000000,0x1FFC0000,0x81FC0000,0xBFF00000,0xC2000000,
+0x8FFC0000,0xE43684,0xFEC41E2C,0xF6B0152B,0xC2B0152B,0xFEA41532,0xFE8406AF,0xCA8C0933,0xD8800C42,0xBC7C0686,0xA67C0C42,0xFE801AF9,0xFE540527,0xCA680733,0xE640064F,0xC0480012,0xA650068A,0xC244152C,0xB0340735,0x9E340931,0x8C44152D,0x1543680,0xFE1416C3,0xC248152B,0xEE000E4A,0xC6000651,0xA6180C40,0xCC001953,0xB40007E6,0x9E0008C1,0x8C0015A5,0x2FFC3680,
+0x9C001E10,0x90001910,0x84002170,0x72003680,0xFEBC2236,0xF6DC2F82,0xF8E0311F,0xFE940FF3,0xFE640317,0xEA48000E,0xC6540082,0xBA3C0086,0xFEA42172,0xFE700DE2,0xCA2C049F,0x9E0008C1,0x1E83680,0x11C152B,0xFEF4082B,0xE8E80482,0xC2E40482,0xFED0081B,0xF2B40006,0xC6C0007A,0xCAB80621,0xB8B00131,0xA6B40621,0x3A4152B,0xFE6404B9,0xC2980480,0xEE280621,0xC0480011,
+0xA66C0620,0x57FC152B,0xB8000586,0xA0000789,0x8C00152C,0x3A4152B,0xFE6404B9,0xC2980480,0xEE280621,0xC0480011,0xA66C0620,0x57FC152B,0xB8000586,0xA0000789,0x8C00152C,0x57FC152B,0xB8000586,0xA0000789,0x8C00152C,0x8C00152C,0xFEF80E2A,0xFF0C123B,0xFF0C124B,0xFEC0075E,0xFE7C01A9,0xE650000D,0xC26C0001,0xC01C0038,0xFEDC0E35,0xFE980692,0xCE140480,0xA0000789,
+0x2BFC152B,0xB0152B,0xB0152B,0xB0152B,0xB0152B,0xFE8406AB,0xFE8406AB,0xFE8406AB,0xAE800622,0xAE800622,0x8A7C0622,0xFE5004B9,0xFE5004B9,0xFE5004B9,0xC048000E,0xC048000E,0x8E5C0132,0x98480481,0x98480481,0x843C007D,0x72440481,0x104152B,0x104152B,0x104152B,0xC6000641,0xC6000641,0x8A340620,0xA20005F6,0xA20005F6,0x86000061,0x72000489,0x7FC152B,
+0x7FC152B,0x720009E8,0x66000A24,0x5800152C,0xFE900C2A,0xFCA81122,0xB0152B,0xFE78055A,0xFE5800B2,0xE648000B,0xD648003B,0xAE440002,0xFE780B5A,0xFE500485,0xC2300480,0x86000061,0x174152B,0xE40482,0xE40482,0xE40482,0xE40482,0xEAB80001,0xEAB80001,0xEAB80001,0xA2B40001,0xA2B40001,0x8AB40001,0x1540480,0x1540480,0x1540480,0xB65C0001,0xB65C0001,
+0x8A880000,0x2FFC0480,0x2FFC0480,0x8A000004,0x72000480,0x1540480,0x1540480,0x1540480,0xB65C0001,0xB65C0001,0x8A880000,0x2FFC0480,0x2FFC0480,0x8A000004,0x72000480,0x2FFC0480,0x2FFC0480,0x8A000004,0x72000480,0x72000480,0xF6C80288,0xF6DC02F9,0xE40482,0xFE980145,0xFC6C0019,0xE0540000,0xC6680000,0xB23C0000,0xFAAC02AD,0xFE800120,0x1E80480,0x8A000004,
+0x1E80480,0x14C0622,0xFF2400DA,0xDF140001,0xC3140001,0x1F00620,0xF6AC0001,0xC2E00000,0x7DF80620,0xC2300000,0xA6000620,0x1F00620,0xF6AC0001,0xC2E00000,0x7DF80620,0xC2300000,0xA6000620,0x7DF80620,0xC2300000,0xA6000620,0xA6000620,0x1F00620,0xF6AC0001,0xC2E00000,0x7DF80620,0xC2300000,0xA6000620,0x7DF80620,0xC2300000,0xA6000620,0xA6000620,0x7DF80620,
+0xC2300000,0xA6000620,0xA6000620,0xA6000620,0xFB2C04B1,0x1640620,0xFD4804E2,0xFEEC029A,0xFE9000F5,0xEC380000,0xC2700000,0xC000000D,0xFF180480,0xFECC0262,0xCA840001,0xA6000620,0x5BFC0620,0x7C0622,0x7C0622,0x7C0622,0x7C0622,0x7C0622,0x7C0622,0x7C0622,0x7C0622,0x7C0622,0x7C0622,0xCA480001,0xCA480001,0xCA480001,0xCA480001,0xCA480001,
+0xCA480001,0x76440001,0x76440001,0x76440001,0x5A440001,0xBC0620,0xBC0620,0xBC0620,0xBC0620,0xBC0620,0xBC0620,0x80000041,0x80000041,0x80000041,0x5A100000,0x17C0620,0x17C0620,0x17C0620,0x500001CD,0x3E000620,0xFE6C03A9,0x7C0622,0x7C0622,0xFA60016D,0xFE50004A,0xF2480001,0xF2480001,0xAA480001,0xFC5402F9,0xFE3C0132,0x92380000,0x80000041,
+0x10C0620,};
+static const uint32_t g_etc1_to_bc7_m6_table175[] = {
+0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x1000000,
+0x1000000,0x1000000,0x1000000,0x2A000000,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x5C0000,0x5C0000,0x5C0000,0x800000,0xB40000,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,
+0x3240000,0x17FC0000,0x17FC0000,0x17FC0000,0x62000000,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,0x17FC0000,0x17FC0000,0x17FC0000,0x62000000,0x17FC0000,0x17FC0000,0x17FC0000,0x62000000,0x62000000,0xD40000,0xC40001,0xC40001,0x4E40000,0xF80000,0x10C0000,0x10C0000,0x14C0000,0x4E40000,0xF80000,0x1A40000,0x17FC0000,
+0x1A40000,0x1240001,0x1240001,0x1240001,0x1240001,0x1B40000,0x1B40000,0x1B40000,0x5FF80000,0x5FF80000,0x92000000,0x1B40000,0x1B40000,0x1B40000,0x5FF80000,0x5FF80000,0x92000000,0x5FF80000,0x5FF80000,0x92000000,0x92000000,0x1B40000,0x1B40000,0x1B40000,0x5FF80000,0x5FF80000,0x92000000,0x5FF80000,0x5FF80000,0x92000000,0x92000000,0x5FF80000,
+0x5FF80000,0x92000000,0x92000000,0x92000000,0x3540000,0x5380000,0x1240001,0x1900000,0x3EC0000,0x35FC0000,0x49FC0000,0x6DF80000,0x1700000,0x1B40000,0x35FC0000,0x92000000,0x35FC0000,0x1940001,0x63FC0000,0xB3F80000,0xCA000000,0x63FC0000,0xB3F80000,0xCA000000,0xB3F80000,0xCA000000,0xCA000000,0x63FC0000,0xB3F80000,0xCA000000,0xB3F80000,0xCA000000,
+0xCA000000,0xB3F80000,0xCA000000,0xCA000000,0xCA000000,0x63FC0000,0xB3F80000,0xCA000000,0xB3F80000,0xCA000000,0xCA000000,0xB3F80000,0xCA000000,0xCA000000,0xCA000000,0xB3F80000,0xCA000000,0xCA000000,0xCA000000,0xCA000000,0x1FC0000,0x1B00000,0x1B00000,0x81FC0000,0xA9F80000,0xBFF00000,0xCA000000,0xCA000000,0x3DFC0000,0x91FC0000,0xC9C40000,0xCA000000,
+0x9FF80000,0xF43684,0xFED01F3C,0xFEC0152B,0xCAC0152B,0xFEB01682,0xFE980713,0xD29C0933,0xE0900C42,0xC48C0686,0xAE8C0C42,0xFE981BF1,0xFE6C05CF,0xD2780733,0xEE50064F,0xC8580012,0xAE60068A,0xCA54152C,0xB8440735,0xA6440931,0x9454152D,0x16C3680,0xFE38176F,0xCA58152B,0xFA000D7A,0xCE100651,0xAE280C40,0xD8001863,0xBC0006CD,0xA60007D9,0x94001550,0x3BFC3680,
+0xA6001D1B,0x960017C8,0x8A002044,0x7A003680,0xFED02341,0xFEEC2F82,0xFEEC313B,0xFEAC11B2,0xFE78043B,0xF258000E,0xCE640082,0xC24C0086,0xFEB4221F,0xFE800F42,0xD23C049F,0xA60007D9,0x7FC3680,0x12C152B,0xFF0C08BB,0xF0F80482,0xCAF40482,0xFEE80893,0xFAC40006,0xCED0007A,0xD2C80621,0xC0C00131,0xAEC40621,0x3BC152B,0xFE7C0501,0xCAA80480,0xF6380621,0xC8580011,
+0xAE7C0620,0x63FC152B,0xC2000540,0xAA000740,0x9400152C,0x3BC152B,0xFE7C0501,0xCAA80480,0xF6380621,0xC8580011,0xAE7C0620,0x63FC152B,0xC2000540,0xAA000740,0x9400152C,0x63FC152B,0xC2000540,0xAA000740,0x9400152C,0x9400152C,0xFF000EBB,0xF9201289,0xFD281262,0xFED40821,0xFE900249,0xEE60000D,0xCA7C0001,0xC82C0038,0xFCF40ED9,0xFEC0074A,0xD6240480,0xAA000740,
+0x3BFC152B,0xC0152B,0xC0152B,0xC0152B,0xC0152B,0xFE9806E2,0xFE9806E2,0xFE9806E2,0xB6900622,0xB6900622,0x928C0622,0xFE6804F1,0xFE6804F1,0xFE6804F1,0xC858000E,0xC858000E,0x966C0132,0xA0580481,0xA0580481,0x8C4C007D,0x7A540481,0x11C152B,0x11C152B,0x11C152B,0xD8000621,0xD8000621,0x92440620,0xAE000576,0xAE000576,0x92000019,0x7A080480,0x13FC152B,
+0x13FC152B,0x7E000938,0x72000984,0x6000152C,0xFEA00C7D,0xF4B8117B,0xC0152B,0xFE8805D3,0xFE6C0102,0xEE58000B,0xDE58003B,0xB6540002,0xFE900BE5,0xFE680518,0xCA400480,0x92000019,0x198152B,0xF40482,0xF40482,0xF40482,0xF40482,0xF2C80001,0xF2C80001,0xF2C80001,0xAAC40001,0xAAC40001,0x92C40001,0x16C0480,0x16C0480,0x16C0480,0xBE6C0001,0xBE6C0001,
+0x92980000,0x3BFC0480,0x3BFC0480,0x92000000,0x7A000480,0x16C0480,0x16C0480,0x16C0480,0xBE6C0001,0xBE6C0001,0x92980000,0x3BFC0480,0x3BFC0480,0x92000000,0x7A000480,0x3BFC0480,0x3BFC0480,0x92000000,0x7A000480,0x7A000480,0xFED80288,0xFEEC02F9,0xF40482,0xFEB4016D,0xFE800029,0xE8640000,0xCE780000,0xBA4C0000,0xFCC002D2,0xFE980139,0x7FC0480,0x92000000,
+0x7FC0480,0x15C0622,0xFF3C0122,0xE7240001,0xCB240001,0xDFC0620,0xFEBC0001,0xCAF00000,0x89F80620,0xCA400000,0xAE000620,0xDFC0620,0xFEBC0001,0xCAF00000,0x89F80620,0xCA400000,0xAE000620,0x89F80620,0xCA400000,0xAE000620,0xAE000620,0xDFC0620,0xFEBC0001,0xCAF00000,0x89F80620,0xCA400000,0xAE000620,0x89F80620,0xCA400000,0xAE000620,0xAE000620,0x89F80620,
+0xCA400000,0xAE000620,0xAE000620,0xAE000620,0xFF3404C9,0x3740620,0xF5580515,0xFF0402E4,0xFEBC0139,0xF4480000,0xCA800000,0xCA000004,0xFF2C04B1,0xFEF002B1,0xD2940001,0xAE000620,0x69FC0620,0x8C0622,0x8C0622,0x8C0622,0x8C0622,0x8C0622,0x8C0622,0x8C0622,0x8C0622,0x8C0622,0x8C0622,0xD2580001,0xD2580001,0xD2580001,0xD2580001,0xD2580001,
+0xD2580001,0x7E540001,0x7E540001,0x7E540001,0x62540001,0x2D00620,0x2D00620,0x2D00620,0x2D00620,0x2D00620,0x2D00620,0x8C000019,0x8C000019,0x8C000019,0x62200000,0x1AC0620,0x1AC0620,0x1AC0620,0x56000171,0x46000620,0xF88003CA,0x8C0622,0x8C0622,0xFC70018A,0xFE640062,0xFA580001,0xFA580001,0xB2580001,0xFC640320,0xFE500145,0x9A480000,0x8C000019,
+0x12C0620,};
+static const uint32_t g_etc1_to_bc7_m6_table176[] = {
+0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,0x1380000,
+0x1380000,0x1380000,0x1380000,0x32000001,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0xE6C0000,0xE6C0000,0xE6C0000,0x2980000,0xDC0000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,
+0x1400000,0x25F80000,0x25F80000,0x25F80000,0x6A000001,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x25F80000,0x25F80000,0x25F80000,0x6A000001,0x25F80000,0x25F80000,0x25F80000,0x6A000001,0x6A000001,0xAE40000,0xD80000,0xD80000,0xFC0000,0x50C0000,0x3240000,0x3240000,0x16C0000,0xFC0000,0x50C0000,0x1CC0000,0x25F80000,
+0x1CC0000,0x1380000,0x1380000,0x1380000,0x1380000,0x1D00000,0x1D00000,0x1D00000,0x6DF80000,0x6DF80000,0x9A000001,0x1D00000,0x1D00000,0x1D00000,0x6DF80000,0x6DF80000,0x9A000001,0x6DF80000,0x6DF80000,0x9A000001,0x9A000001,0x1D00000,0x1D00000,0x1D00000,0x6DF80000,0x6DF80000,0x9A000001,0x6DF80000,0x6DF80000,0x9A000001,0x9A000001,0x6DF80000,
+0x6DF80000,0x9A000001,0x9A000001,0x9A000001,0x7680000,0x14C0000,0x1380000,0x1A80000,0xDFC0000,0x45FC0000,0x59FC0000,0x79F80000,0x1880000,0x1D00000,0x45FC0000,0x9A000001,0x45FC0000,0x1A80000,0x7DFC0000,0xBFFC0000,0xD2000001,0x7DFC0000,0xBFFC0000,0xD2000001,0xBFFC0000,0xD2000001,0xD2000001,0x7DFC0000,0xBFFC0000,0xD2000001,0xBFFC0000,0xD2000001,
+0xD2000001,0xBFFC0000,0xD2000001,0xD2000001,0xD2000001,0x7DFC0000,0xBFFC0000,0xD2000001,0xBFFC0000,0xD2000001,0xD2000001,0xBFFC0000,0xD2000001,0xD2000001,0xD2000001,0xBFFC0000,0xD2000001,0xD2000001,0xD2000001,0xD2000001,0x2DFC0000,0x1C40000,0x1C40000,0x97FC0000,0xB7FC0000,0xC9FC0000,0xD2000001,0xD2000001,0x5FFC0000,0xA5FC0000,0xD1F40000,0xD2000001,
+0xAFFC0000,0x1083680,0xFEE82044,0xFED41550,0xD2D4152D,0xFED017C8,0xFEAC07D9,0xDCB00931,0xEAA00C40,0xCC9C068A,0xB6A00C42,0xFEB01D1B,0xFE8406CD,0xDC8C0735,0xF6600651,0xD26C0012,0xB8740686,0xD268152B,0xC2580733,0xB0580933,0x9E68152B,0x1883680,0xFE4C1863,0xD468152C,0xFE080D7A,0xD620064F,0xB63C0C42,0xE200176F,0xC80005CF,0xB2000713,0x9E00152B,0x49F83680,
+0xB2001BF1,0xA0001682,0x96001F3C,0x82003684,0xFEE42462,0xF9003040,0xFB0431B0,0xFEC01361,0xFE9005B6,0xFA68000E,0xD6740086,0xCC600082,0xFED02373,0xFE981122,0xDC4C049F,0xB2000713,0x19FC3680,0x13C152C,0xFF180984,0xFB080480,0xD3080481,0xFF000938,0xFED80019,0xD6E0007D,0xDCD80620,0xC8D00132,0xB6D80622,0x1D8152B,0xFEA00576,0xD2BC0481,0xFE4C0621,0xD26C000E,
+0xB6900622,0x71F8152B,0xCA0004F1,0xB20006E2,0x9E00152B,0x1D8152B,0xFEA00576,0xD2BC0481,0xFE4C0621,0xD26C000E,0xB6900622,0x71F8152B,0xCA0004F1,0xB20006E2,0x9E00152B,0x71F8152B,0xCA0004F1,0xB20006E2,0x9E00152B,0x9E00152B,0xFF140F21,0xFF2C12B6,0xF53812C4,0xFEEC08F1,0xFEA80326,0xF674000D,0xD48C0002,0xD03C003B,0xFF080F33,0xFEC8081B,0xDE380481,0xB20006E2,
+0x4BFC152B,0xD4152C,0xD4152C,0xD4152C,0xD4152C,0xFEA80740,0xFEA80740,0xFEA80740,0xC0A00620,0xC0A00620,0x9AA00621,0xFE780540,0xFE780540,0xFE780540,0xD0680011,0xD0680011,0x9E7C0131,0xAA680480,0xAA680480,0x9660007A,0x82680482,0x138152B,0x138152B,0x138152B,0xE2100621,0xE2100621,0x9A580621,0xC0000501,0xC0000501,0x9C040006,0x821C0482,0x21F8152B,
+0x21F8152B,0x8A000893,0x780008BB,0x6800152B,0xFEBC0CE5,0xFECC1178,0xD4152C,0xFE980671,0xFE80016D,0xF86C000C,0xE86C0038,0xC0680001,0xFEA00C3A,0xFE8005A2,0xD2540481,0x9C040006,0x1BC152B,0x1080480,0x1080480,0x1080480,0x1080480,0xFCD80000,0xFCD80000,0xFCD80000,0xB2D80000,0xB2D80000,0x9AD80001,0x1880480,0x1880480,0x1880480,0xC6800001,0xC6800001,
+0x9CA80001,0x49F80480,0x49F80480,0x9A180001,0x82000482,0x1880480,0x1880480,0x1880480,0xC6800001,0xC6800001,0x9CA80001,0x49F80480,0x49F80480,0x9A180001,0x82000482,0x49F80480,0x49F80480,0x9A180001,0x82000482,0x82000482,0xFAEC02AD,0xF9000320,0x1080480,0xFEC40190,0xFE980041,0xF0780000,0xD8880000,0xC2600000,0xFED002DA,0xFEB0016D,0x19FC0480,0x9A180001,
+0x19FC0480,0x1700620,0xFF500171,0xEF380000,0xD3380001,0x29FC0620,0xFED80019,0xD5000001,0x97F80620,0xD2540001,0xB6000622,0x29FC0620,0xFED80019,0xD5000001,0x97F80620,0xD2540001,0xB6000622,0x97F80620,0xD2540001,0xB6000622,0xB6000622,0x29FC0620,0xFED80019,0xD5000001,0x97F80620,0xD2540001,0xB6000622,0x97F80620,0xD2540001,0xB6000622,0xB6000622,0x97F80620,
+0xD2540001,0xB6000622,0xB6000622,0xB6000622,0xFF5004E4,0x1880620,0xFF6C0515,0xFF200332,0xFED00195,0xFE580000,0xD2980001,0xD2080001,0xF94804E2,0xFF0802E4,0xDCA40000,0xB6000622,0x7BFC0620,0xA00620,0xA00620,0xA00620,0xA00620,0xA00620,0xA00620,0xA00620,0xA00620,0xA00620,0xA00620,0xDE680000,0xDE680000,0xDE680000,0xDE680000,0xDE680000,
+0xDE680000,0x86680000,0x86680000,0x86680000,0x6A680001,0xEC0620,0xEC0620,0xEC0620,0xEC0620,0xEC0620,0xEC0620,0x9E000001,0x9E000001,0x9E000001,0x6C300001,0x1E40620,0x1E40620,0x1E40620,0x60000122,0x4E000622,0xFE8C03E8,0xA00620,0xA00620,0xFE8401A5,0xFE780080,0xFE680004,0xFE680004,0xBC680000,0xFE740328,0xFE640179,0xA4580000,0x9E000001,
+0x1540620,};
+static const uint32_t g_etc1_to_bc7_m6_table177[] = {
+0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x1680000,
+0x1680000,0x1680000,0x1680000,0x3A000001,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x800000,0x800000,0x800000,0x2B00000,0xFC0000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,
+0x1580000,0x31F80000,0x31F80000,0x31F80000,0x72000001,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x31F80000,0x31F80000,0x31F80000,0x72000001,0x31F80000,0x31F80000,0x31F80000,0x72000001,0x72000001,0xF80000,0xE80000,0xE80000,0x30C0000,0x5200000,0x13C0000,0x13C0000,0x1840000,0x30C0000,0x5200000,0x1EC0000,0x31F80000,
+0x1EC0000,0x1480000,0x1480000,0x1480000,0x1480000,0x1E80000,0x1E80000,0x1E80000,0x79F80000,0x79F80000,0xA2000001,0x1E80000,0x1E80000,0x1E80000,0x79F80000,0x79F80000,0xA2000001,0x79F80000,0x79F80000,0xA2000001,0xA2000001,0x1E80000,0x1E80000,0x1E80000,0x79F80000,0x79F80000,0xA2000001,0x79F80000,0x79F80000,0xA2000001,0xA2000001,0x79F80000,
+0x79F80000,0xA2000001,0xA2000001,0xA2000001,0x37C0000,0x75C0000,0x1480000,0x3BC0000,0x21FC0000,0x55FC0000,0x67F80000,0x83FC0000,0x19C0000,0x1E80000,0x55FC0000,0xA2000001,0x55FC0000,0x1B80000,0x95FC0000,0xCBFC0000,0xDA000001,0x95FC0000,0xCBFC0000,0xDA000001,0xCBFC0000,0xDA000001,0xDA000001,0x95FC0000,0xCBFC0000,0xDA000001,0xCBFC0000,0xDA000001,
+0xDA000001,0xCBFC0000,0xDA000001,0xDA000001,0xDA000001,0x95FC0000,0xCBFC0000,0xDA000001,0xCBFC0000,0xDA000001,0xDA000001,0xCBFC0000,0xDA000001,0xDA000001,0xDA000001,0xCBFC0000,0xDA000001,0xDA000001,0xDA000001,0xDA000001,0x55FC0000,0x3D40000,0x3D40000,0xABFC0000,0xC5FC0000,0xD3FC0000,0xDA000001,0xDA000001,0x7DFC0000,0xB5FC0000,0xDBC80000,0xDA000001,
+0xBFF80000,0x1183680,0xFEF42170,0xFEE415A5,0xDAE4152D,0xFEDC1910,0xFEC008C1,0xE4C00931,0xF2B00C40,0xD4AC068A,0xBEB00C42,0xFEC41E10,0xFE9407E6,0xE49C0735,0xFE700651,0xDA7C0012,0xC0840686,0xDA78152B,0xCA680733,0xB8680933,0xA678152B,0x1A03680,0xFE641953,0xDC78152C,0xFE200E4A,0xDE30064F,0xBE4C0C42,0xF40016C3,0xD4000527,0xBC0006AF,0xA610152B,0x55F83680,
+0xBE001AF9,0xAC001532,0x9C001E2C,0x8A003684,0xFEF8257D,0xFF0C3050,0xFF0C31F0,0xFED414FA,0xFEA4073E,0xFE7C001E,0xDE840086,0xD4700082,0xFEDC247F,0xFEB012E5,0xE45C049F,0xBC0006AF,0x27FC3680,0x14C152C,0xFF300A24,0xFF180489,0xDB180481,0xFF1809E8,0xFEF00061,0xDEF0007D,0xE4E80620,0xD0E00132,0xBEE80622,0x1F0152B,0xFEB805F6,0xDACC0481,0xFE640641,0xDA7C000E,
+0xBEA00622,0x7DF8152B,0xD60004B9,0xBC0006AB,0xA600152B,0x1F0152B,0xFEB805F6,0xDACC0481,0xFE640641,0xDA7C000E,0xBEA00622,0x7DF8152B,0xD60004B9,0xBC0006AB,0xA600152B,0x7DF8152B,0xD60004B9,0xBC0006AB,0xA600152B,0xA600152B,0xFD300F89,0xFB4412E4,0xFD4812C4,0xFF0009C8,0xFEC803F2,0xFE84000D,0xDC9C0002,0xD84C003B,0xFF180FA2,0xFEE80905,0xE6480481,0xBC0006AB,
+0x5BFC152B,0xE4152C,0xE4152C,0xE4152C,0xE4152C,0xFEBC0789,0xFEBC0789,0xFEBC0789,0xC8B00620,0xC8B00620,0xA2B00621,0xFE8C0586,0xFE8C0586,0xFE8C0586,0xD8780011,0xD8780011,0xA68C0131,0xB2780480,0xB2780480,0x9E70007A,0x8A780482,0x150152B,0x150152B,0x150152B,0xEA200621,0xEA200621,0xA2680621,0xCC0004B9,0xCC0004B9,0xA4140006,0x8A2C0482,0x2DF8152B,
+0x2DF8152B,0x9600081B,0x8400082B,0x7000152B,0xFECC0D34,0xF6DC11D1,0xE4152C,0xFEAC0709,0xFE9401DD,0xFC7C000E,0xF07C0038,0xC8780001,0xFEB40C89,0xFE980632,0xDA640481,0xA4140006,0x1E0152B,0x1180480,0x1180480,0x1180480,0x1180480,0xFEE80004,0xFEE80004,0xFEE80004,0xBAE80000,0xBAE80000,0xA2E80001,0x1A00480,0x1A00480,0x1A00480,0xCE900001,0xCE900001,
+0xA4B80001,0x55F80480,0x55F80480,0xA2280001,0x8A000482,0x1A00480,0x1A00480,0x1A00480,0xCE900001,0xCE900001,0xA4B80001,0x55F80480,0x55F80480,0xA2280001,0x8A000482,0x55F80480,0x55F80480,0xA2280001,0x8A000482,0x8A000482,0xF70002D2,0xFF0C0328,0x1180480,0xFEDC01A5,0xFEAC0061,0xF8880000,0xE0980000,0xCA700000,0xF8EC02F9,0xFEC40188,0x27FC0480,0xA2280001,
+0x27FC0480,0x1800620,0xFF5C01CD,0xF7480000,0xDB480001,0x41FC0620,0xFEFC0041,0xDD100001,0xA1FC0620,0xDA640001,0xBE000622,0x41FC0620,0xFEFC0041,0xDD100001,0xA1FC0620,0xDA640001,0xBE000622,0xA1FC0620,0xDA640001,0xBE000622,0xBE000622,0x41FC0620,0xFEFC0041,0xDD100001,0xA1FC0620,0xDA640001,0xBE000622,0xA1FC0620,0xDA640001,0xBE000622,0xBE000622,0xA1FC0620,
+0xDA640001,0xBE000622,0xBE000622,0xBE000622,0xF7680515,0x5980620,0xF77C0548,0xFF400372,0xFEFC01E5,0xFE84000D,0xDAA80001,0xDA180001,0xFD5804E4,0xFF200340,0xE4B40000,0xBE000622,0x89FC0620,0xB00620,0xB00620,0xB00620,0xB00620,0xB00620,0xB00620,0xB00620,0xB00620,0xB00620,0xB00620,0xE6780000,0xE6780000,0xE6780000,0xE6780000,0xE6780000,
+0xE6780000,0x8E780000,0x8E780000,0x8E780000,0x72780001,0x1040620,0x1040620,0x1040620,0x1040620,0x1040620,0x1040620,0xA6100001,0xA6100001,0xA6100001,0x74400001,0x7FC0620,0x7FC0620,0x7FC0620,0x6C0000DA,0x56000622,0xFAA403F5,0xB00620,0xB00620,0xFE9001D4,0xFC8800A4,0xFC7C000D,0xFC7C000D,0xC4780000,0xFC8C0349,0xFE780190,0xAC680000,0xA6100001,
+0x1740620,};
+static const uint32_t g_etc1_to_bc7_m6_table178[] = {
+0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0x1980000,
+0x1980000,0x1980000,0x1980000,0x42000001,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x900000,0x900000,0x900000,0xC80000,0x1200000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0xF80000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,
+0x1700000,0x3DF80000,0x3DF80000,0x3DF80000,0x7A000001,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x3DF80000,0x3DF80000,0x3DF80000,0x7A000001,0x3DF80000,0x3DF80000,0x3DF80000,0x7A000001,0x7A000001,0x1080000,0xF80000,0xF80000,0x1200000,0x5340000,0x1500000,0x1500000,0x1A00000,0x1200000,0x5340000,0x9FC0000,0x3DF80000,
+0x9FC0000,0x1580000,0x1580000,0x1580000,0x1580000,0x3FC0000,0x3FC0000,0x3FC0000,0x85F80000,0x85F80000,0xAA000001,0x3FC0000,0x3FC0000,0x3FC0000,0x85F80000,0x85F80000,0xAA000001,0x85F80000,0x85F80000,0xAA000001,0xAA000001,0x3FC0000,0x3FC0000,0x3FC0000,0x85F80000,0x85F80000,0xAA000001,0x85F80000,0x85F80000,0xAA000001,0xAA000001,0x85F80000,
+0x85F80000,0xAA000001,0xAA000001,0xAA000001,0x1900000,0xF6C0000,0x1580000,0x1D40000,0x33FC0000,0x63FC0000,0x75F80000,0x8FF80000,0x1B00000,0x3FC0000,0x63FC0000,0xAA000001,0x63FC0000,0x1C80000,0xAFFC0000,0xD7FC0000,0xE2000001,0xAFFC0000,0xD7FC0000,0xE2000001,0xD7FC0000,0xE2000001,0xE2000001,0xAFFC0000,0xD7FC0000,0xE2000001,0xD7FC0000,0xE2000001,
+0xE2000001,0xD7FC0000,0xE2000001,0xE2000001,0xE2000001,0xAFFC0000,0xD7FC0000,0xE2000001,0xD7FC0000,0xE2000001,0xE2000001,0xD7FC0000,0xE2000001,0xE2000001,0xE2000001,0xD7FC0000,0xE2000001,0xE2000001,0xE2000001,0xE2000001,0x7DFC0000,0xBE40000,0xBE40000,0xBDFC0000,0xD3F80000,0xDDFC0000,0xE2000001,0xE2000001,0x9BFC0000,0xC7FC0000,0xE3D80000,0xE2000001,
+0xCDFC0000,0x1283680,0xFF0C2270,0xFEF81640,0xE2F4152D,0xFEF41A90,0xFED409ED,0xECD00931,0xFAC00C40,0xDCBC068A,0xC6C00C42,0xFED01F3C,0xFEAC0936,0xECAC0735,0xFE880681,0xE28C0012,0xC8940686,0xE288152B,0xD2780733,0xC0780933,0xAE88152B,0x1B83680,0xFE881A5F,0xE488152C,0xFE380F5A,0xE640064F,0xC65C0C42,0xFC00164D,0xDE0004BA,0xC400067B,0xAE20152B,0x61F83680,
+0xCA001A21,0xB8001422,0xA6001D6B,0x92003684,0xFF0C269A,0xF9203102,0xFB243245,0xFEDC16B2,0xFEB808F6,0xFE900086,0xE6940086,0xDC800082,0xFEF82596,0xFEC41488,0xEC6C049F,0xC400067B,0x37FC3680,0x15C152C,0xFF440AD1,0xFF2C04B9,0xE3280481,0xFF240A8C,0xFF0400E9,0xE700007D,0xECF80620,0xD8F00132,0xC6F80622,0xDFC152B,0xFECC06B1,0xE2DC0481,0xFE880681,0xE28C000E,
+0xC6B00622,0x89F8152B,0xE000049B,0xC4000672,0xAE00152B,0xDFC152B,0xFECC06B1,0xE2DC0481,0xFE880681,0xE28C000E,0xC6B00622,0x89F8152B,0xE000049B,0xC4000672,0xAE00152B,0x89F8152B,0xE000049B,0xC4000672,0xAE00152B,0xAE00152B,0xFF3C1004,0xFF4C1324,0xF5581329,0xFF140A71,0xFEE804D9,0xFE980052,0xE4AC0002,0xE05C003B,0xFF34103A,0xFF0409B3,0xEE580481,0xC4000672,
+0x69FC152B,0xF4152C,0xF4152C,0xF4152C,0xF4152C,0xFED007E4,0xFED007E4,0xFED007E4,0xD0C00620,0xD0C00620,0xAAC00621,0xFEA405E6,0xFEA405E6,0xFEA405E6,0xE0880011,0xE0880011,0xAE9C0131,0xBA880480,0xBA880480,0xA680007A,0x92880482,0x168152B,0x168152B,0x168152B,0xF2300621,0xF2300621,0xAA780621,0xD8000491,0xD8000491,0xAC240006,0x923C0482,0x39F8152B,
+0x39F8152B,0x9C0007A3,0x8A000793,0x7800152B,0xFED80DAA,0xFEEC11D1,0xF4152C,0xFEC40794,0xFEAC0275,0xFE900022,0xF88C0038,0xD0880001,0xFEBC0D2A,0xFEB006D1,0xE2740481,0xAC240006,0x3FC152B,0x1280480,0x1280480,0x1280480,0x1280480,0xFCFC0014,0xFCFC0014,0xFCFC0014,0xC2F80000,0xC2F80000,0xAAF80001,0x1B80480,0x1B80480,0x1B80480,0xD6A00001,0xD6A00001,
+0xACC80001,0x61F80480,0x61F80480,0xAA380001,0x92000482,0x1B80480,0x1B80480,0x1B80480,0xD6A00001,0xD6A00001,0xACC80001,0x61F80480,0x61F80480,0xAA380001,0x92000482,0x61F80480,0x61F80480,0xAA380001,0x92000482,0x92000482,0xFF1002D2,0xF9200349,0x1280480,0xFCF401E1,0xFEC80082,0xFC9C0001,0xE8A80000,0xD2800000,0xFEF802FD,0xFEDC01A5,0x37FC0480,0xAA380001,
+0x37FC0480,0x1900620,0xFF74022D,0xFF580000,0xE3580001,0x59FC0620,0xFF140089,0xE5200001,0xADFC0620,0xE2740001,0xC6000622,0x59FC0620,0xFF140089,0xE5200001,0xADFC0620,0xE2740001,0xC6000622,0xADFC0620,0xE2740001,0xC6000622,0xC6000622,0x59FC0620,0xFF140089,0xE5200001,0xADFC0620,0xE2740001,0xC6000622,0xADFC0620,0xE2740001,0xC6000622,0xC6000622,0xADFC0620,
+0xE2740001,0xC6000622,0xC6000622,0xC6000622,0xFF780515,0xDA80620,0xFF8C0548,0xFF5803C8,0xFF100249,0xFEAC0041,0xE2B80001,0xE2280001,0xFF700515,0xFF40037A,0xECC40000,0xC6000622,0x99FC0620,0xC00620,0xC00620,0xC00620,0xC00620,0xC00620,0xC00620,0xC00620,0xC00620,0xC00620,0xC00620,0xEE880000,0xEE880000,0xEE880000,0xEE880000,0xEE880000,
+0xEE880000,0x96880000,0x96880000,0x96880000,0x7A880001,0x11C0620,0x11C0620,0x11C0620,0x11C0620,0x11C0620,0x11C0620,0xAE200001,0xAE200001,0xAE200001,0x7C500001,0x13FC0620,0x13FC0620,0x13FC0620,0x720000A2,0x5E000622,0xFEAC041D,0xC00620,0xC00620,0xFEA001F9,0xFC9C00C8,0xFE900019,0xFE900019,0xCC880000,0xFC9C0372,0xFC9001C2,0xB4780000,0xAE200001,
+0x1980620,};
+static const uint32_t g_etc1_to_bc7_m6_table179[] = {
+0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0xE00000,0xE00000,0xE00000,0xE00000,0xE00000,0xE00000,0xE00000,0xE00000,0xE00000,0xE00000,0x1CC0000,
+0x1CC0000,0x1CC0000,0x1CC0000,0x4A000001,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x8A00000,0x8A00000,0x8A00000,0xE00000,0x1400000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,
+0x1880000,0x49F80000,0x49F80000,0x49F80000,0x82000001,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x49F80000,0x49F80000,0x49F80000,0x82000001,0x49F80000,0x49F80000,0x49F80000,0x82000001,0x82000001,0x5180000,0x1080000,0x1080000,0x1340000,0x14C0000,0x1680000,0x1680000,0x1BC0000,0x1340000,0x14C0000,0x19FC0000,0x49F80000,
+0x19FC0000,0x1680000,0x1680000,0x1680000,0x1680000,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x91F80000,0x91F80000,0xB2000001,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x91F80000,0x91F80000,0xB2000001,0x91F80000,0x91F80000,0xB2000001,0xB2000001,0x1BFC0000,0x1BFC0000,0x1BFC0000,0x91F80000,0x91F80000,0xB2000001,0x91F80000,0x91F80000,0xB2000001,0xB2000001,0x91F80000,
+0x91F80000,0xB2000001,0xB2000001,0xB2000001,0x7A00000,0x1800000,0x1680000,0x3E80000,0x47FC0000,0x73FC0000,0x81FC0000,0x99FC0000,0x1C40000,0x1BFC0000,0x73FC0000,0xB2000001,0x73FC0000,0x1D80000,0xC7FC0000,0xE3FC0000,0xEA000001,0xC7FC0000,0xE3FC0000,0xEA000001,0xE3FC0000,0xEA000001,0xEA000001,0xC7FC0000,0xE3FC0000,0xEA000001,0xE3FC0000,0xEA000001,
+0xEA000001,0xE3FC0000,0xEA000001,0xEA000001,0xEA000001,0xC7FC0000,0xE3FC0000,0xEA000001,0xE3FC0000,0xEA000001,0xEA000001,0xE3FC0000,0xEA000001,0xEA000001,0xEA000001,0xE3FC0000,0xEA000001,0xEA000001,0xEA000001,0xEA000001,0xA3FC0000,0x1F80000,0x1F80000,0xD1FC0000,0xDFFC0000,0xE7FC0000,0xEA000001,0xEA000001,0xB9FC0000,0xD7FC0000,0xEBE80000,0xEA000001,
+0xDDF80000,0x1383680,0xFF1823A4,0xFF0816F9,0xEB04152D,0xFF001C08,0xFEE40B51,0xF4E00931,0xFED40C50,0xE4CC068A,0xCED00C42,0xFEE8206C,0xFEC00AD1,0xF4BC0735,0xFEA00711,0xEA9C0012,0xD0A40686,0xEA98152B,0xDA880733,0xC8880933,0xB698152B,0x1D03680,0xFEA01B7F,0xEC98152C,0xFE5810AA,0xEE50064F,0xCE6C0C42,0xFE14169F,0xEA00048A,0xCC10067B,0xB630152B,0x6DF83680,
+0xD0001959,0xBE001302,0xAC001C83,0x9A003684,0xFF2027A2,0xFF2C311A,0xFF2C328D,0xFEF0188A,0xFECC0ADE,0xFEAC0156,0xEEA40086,0xE4900082,0xFF0026DC,0xFEDC1672,0xF47C049F,0xCC10067B,0x45FC3680,0x16C152C,0xFF500B91,0xFF380529,0xEB380481,0xFF3C0B4C,0xFF14019D,0xEF10007D,0xF5080620,0xE1000132,0xCF080622,0x25FC152B,0xFEF00771,0xEAEC0481,0xFEAC06F1,0xEA9C000E,
+0xCEC00622,0x95F8152B,0xEA000489,0xCE000653,0xB600152B,0x25FC152B,0xFEF00771,0xEAEC0481,0xFEAC06F1,0xEA9C000E,0xCEC00622,0x95F8152B,0xEA000489,0xCE000653,0xB600152B,0x95F8152B,0xEA000489,0xCE000653,0xB600152B,0xB600152B,0xFF501055,0xFD681342,0xFD681329,0xFF300B69,0xFEFC05D5,0xFEC000CD,0xECBC0002,0xE86C003B,0xFF44109B,0xFF180AA9,0xF6680481,0xCE000653,
+0x79FC152B,0x104152C,0x104152C,0x104152C,0x104152C,0xFEDC084C,0xFEDC084C,0xFEDC084C,0xD8D00620,0xD8D00620,0xB2D00621,0xFEB00662,0xFEB00662,0xFEB00662,0xE8980011,0xE8980011,0xB6AC0131,0xC2980480,0xC2980480,0xAE90007A,0x9A980482,0x180152B,0x180152B,0x180152B,0xFA400621,0xFA400621,0xB2880621,0xE6040481,0xE6040481,0xB4340006,0x9A4C0482,0x45F8152B,
+0x45F8152B,0xA6000749,0x94000722,0x8000152B,0xFEE80E01,0xF6FC122C,0x104152C,0xFED40821,0xFEC00309,0xFEA40058,0xFCA0003D,0xD8980001,0xFED00D73,0xFEBC076A,0xEA840481,0xB4340006,0x13FC152B,0x1380480,0x1380480,0x1380480,0x1380480,0xFF0C0028,0xFF0C0028,0xFF0C0028,0xCB080000,0xCB080000,0xB3080001,0x1D00480,0x1D00480,0x1D00480,0xDEB00001,0xDEB00001,
+0xB4D80001,0x6DF80480,0x6DF80480,0xB2480001,0x9A000482,0x1D00480,0x1D00480,0x1D00480,0xDEB00001,0xDEB00001,0xB4D80001,0x6DF80480,0x6DF80480,0xB2480001,0x9A000482,0x6DF80480,0x6DF80480,0xB2480001,0x9A000482,0x9A000482,0xFF2002F9,0xFF2C0355,0x1380480,0xFD040202,0xFEDC00AA,0xFEB40008,0xF0B80000,0xDA900000,0xFD100320,0xFEE801D4,0x45FC0480,0xB2480001,
+0x45FC0480,0x1A00620,0xFF8002A1,0xFF6C001D,0xEB680001,0x71FC0620,0xFF3800E9,0xED300001,0xB9FC0620,0xEA840001,0xCE000622,0x71FC0620,0xFF3800E9,0xED300001,0xB9FC0620,0xEA840001,0xCE000622,0xB9FC0620,0xEA840001,0xCE000622,0xCE000622,0x71FC0620,0xFF3800E9,0xED300001,0xB9FC0620,0xEA840001,0xCE000622,0xB9FC0620,0xEA840001,0xCE000622,0xCE000622,0xB9FC0620,
+0xEA840001,0xCE000622,0xCE000622,0xCE000622,0xFF8C0548,0x1BC0620,0xF79C057D,0xFF6C03F9,0xFF3C02B1,0xFED40092,0xEAC80001,0xEA380001,0xF7880548,0xFF5803DA,0xF4D40000,0xCE000622,0xA7FC0620,0xD00620,0xD00620,0xD00620,0xD00620,0xD00620,0xD00620,0xD00620,0xD00620,0xD00620,0xD00620,0xF6980000,0xF6980000,0xF6980000,0xF6980000,0xF6980000,
+0xF6980000,0x9E980000,0x9E980000,0x9E980000,0x82980001,0x1340620,0x1340620,0x1340620,0x1340620,0x1340620,0x1340620,0xB6300001,0xB6300001,0xB6300001,0x84600001,0x1FF80620,0x1FF80620,0x1FF80620,0x7E00006A,0x66000622,0xFAC40424,0xD00620,0xD00620,0xFCB80221,0xFEA800E9,0xFCA00034,0xFCA00034,0xD4980000,0xF8B0039D,0xFEA001E1,0xBC880000,0xB6300001,
+0x1B80620,};
+static const uint32_t g_etc1_to_bc7_m6_table180[] = {
+0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0x3F80000,
+0x3F80000,0x3F80000,0x3F80000,0x54000000,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0x2B40000,0x2B40000,0x2B40000,0xFC0000,0x1680000,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,
+0x1A40000,0x57F80000,0x57F80000,0x57F80000,0x8C000000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x57F80000,0x57F80000,0x57F80000,0x8C000000,0x57F80000,0x57F80000,0x57F80000,0x8C000000,0x8C000000,0x12C0000,0x1180001,0x1180001,0x1480000,0x3600000,0x1800000,0x1800000,0x1D80000,0x1480000,0x3600000,0x29FC0000,0x57F80000,
+0x29FC0000,0x1780001,0x1780001,0x1780001,0x1780001,0x37FC0000,0x37FC0000,0x37FC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x37FC0000,0x37FC0000,0x37FC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x9DFC0000,0x9DFC0000,0xBC000000,0xBC000000,0x37FC0000,0x37FC0000,0x37FC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x9DFC0000,0x9DFC0000,0xBC000000,0xBC000000,0x9DFC0000,
+0x9DFC0000,0xBC000000,0xBC000000,0xBC000000,0x1B80000,0x1940000,0x1780001,0x9FC0000,0x5DFC0000,0x83FC0000,0x91FC0000,0xA5FC0000,0x3D80000,0x37FC0000,0x83FC0000,0xBC000000,0x83FC0000,0x1E80001,0xE3FC0000,0xF1F80000,0xF4000000,0xE3FC0000,0xF1F80000,0xF4000000,0xF1F80000,0xF4000000,0xF4000000,0xE3FC0000,0xF1F80000,0xF4000000,0xF1F80000,0xF4000000,
+0xF4000000,0xF1F80000,0xF4000000,0xF4000000,0xF4000000,0xE3FC0000,0xF1F80000,0xF4000000,0xF1F80000,0xF4000000,0xF4000000,0xF1F80000,0xF4000000,0xF4000000,0xF4000000,0xF1F80000,0xF4000000,0xF4000000,0xF4000000,0xF4000000,0xD1FC0000,0x67FC0000,0x67FC0000,0xE7FC0000,0xEFFC0000,0xF3F80000,0xF4000000,0xF4000000,0xDBFC0000,0xEBFC0000,0xF5DC0000,0xF4000000,
+0xEDFC0000,0x1483684,0xFF3024F4,0xFF1C182C,0xF514152B,0xFF181DD4,0xFEFC0D2B,0xFCF00933,0xFEE40CC2,0xEEE00686,0xD8E00C42,0xFF0021E4,0xFED80CD7,0xFCCC0733,0xFEB80823,0xF2AC0012,0xD8B4068A,0xF4A8152C,0xE2980735,0xD0980931,0xBEA8152D,0x3E83680,0xFEB81CE9,0xF4AC152B,0xFE7C1242,0xF8640651,0xD87C0C40,0xFE3817A1,0xF20C0485,0xD618067D,0xBE40152D,0x79FC3680,
+0xDC001883,0xCA0011EA,0xB8001BA1,0xA4003680,0xFF3428DF,0xFB4431C4,0xFD4832DC,0xFF081AA2,0xFEE80D2F,0xFEC002B7,0xF8B80082,0xECA00086,0xFF1827ED,0xFEF418C3,0xFC90049F,0xD618067D,0x57FC3680,0x180152B,0xFF680C82,0xFF4C05EB,0xF5480482,0xFF500C19,0xFF2C02AA,0xF924007A,0xFD1C0621,0xEB140131,0xD9180621,0x41FC152B,0xFF080866,0xF4FC0480,0xFECC07B9,0xF2AC0011,
+0xD8D00620,0xA1FC152B,0xF4000480,0xD6000631,0xBE00152C,0x41FC152B,0xFF080866,0xF4FC0480,0xFECC07B9,0xF2AC0011,0xD8D00620,0xA1FC152B,0xF4000480,0xD6000631,0xBE00152C,0xA1FC152B,0xF4000480,0xD6000631,0xBE00152C,0xBE00152C,0xFF64110D,0xF57813A3,0xF77C138B,0xFF400C54,0xFF100726,0xFEDC01AD,0xF4D00001,0xF2800038,0xFF5C10F2,0xFF2C0BE1,0xFE7C0484,0xD6000631,
+0x89FC152B,0x114152B,0x114152B,0x114152B,0x114152B,0xFEF408D3,0xFEF408D3,0xFEF408D3,0xE0E40622,0xE0E40622,0xBCE00622,0xFED006DB,0xFED006DB,0xFED006DB,0xF2AC000E,0xF2AC000E,0xC0C00132,0xCAAC0481,0xCAAC0481,0xB6A0007D,0xA4A80481,0x398152B,0x398152B,0x398152B,0xFE580629,0xFE580629,0xBC980620,0xEE180481,0xEE180481,0xBC480005,0xA45C0480,0x51FC152B,
+0x51FC152B,0xB20006E6,0x9C000690,0x8A00152C,0xFF040E83,0xFF0C1233,0x114152B,0xFEE808EA,0xFED403B6,0xFEBC00B2,0xFEB4004B,0xE0A80002,0xFEE40E19,0xFED007FD,0xF4940480,0xBC480005,0x23FC152B,0x1480482,0x1480482,0x1480482,0x1480482,0xFF24004A,0xFF24004A,0xFF24004A,0xD5180001,0xD5180001,0xBD180001,0x3E80480,0x3E80480,0x3E80480,0xE8C00001,0xE8C00001,
+0xBCEC0000,0x79FC0480,0x79FC0480,0xBC540000,0xA4000480,0x3E80480,0x3E80480,0x3E80480,0xE8C00001,0xE8C00001,0xBCEC0000,0x79FC0480,0x79FC0480,0xBC540000,0xA4000480,0x79FC0480,0x79FC0480,0xBC540000,0xA4000480,0xA4000480,0xFB340322,0xFB440372,0x1480482,0xFF180225,0xFEF000E8,0xFED00022,0xF8CC0000,0xE4A00000,0xF9280349,0xFF040208,0x57FC0480,0xBC540000,
+0x57FC0480,0x1B00622,0xFF980321,0xFF7C007A,0xF5780001,0x8DFC0620,0xFF580185,0xF5440000,0xC7FC0620,0xF4940000,0xD8000620,0x8DFC0620,0xFF580185,0xF5440000,0xC7FC0620,0xF4940000,0xD8000620,0xC7FC0620,0xF4940000,0xD8000620,0xD8000620,0x8DFC0620,0xFF580185,0xF5440000,0xC7FC0620,0xF4940000,0xD8000620,0xC7FC0620,0xF4940000,0xD8000620,0xD8000620,0xC7FC0620,
+0xF4940000,0xD8000620,0xD8000620,0xD8000620,0xF7A4057D,0xFCC0620,0xFFAC0581,0xFF84045D,0xFF500335,0xFF040112,0xF4D40000,0xF4440000,0xFF98054A,0xFD800451,0xFCE80001,0xD8000620,0xB9FC0620,0xE00622,0xE00622,0xE00622,0xE00622,0xE00622,0xE00622,0xE00622,0xE00622,0xE00622,0xE00622,0xFCAC0001,0xFCAC0001,0xFCAC0001,0xFCAC0001,0xFCAC0001,
+0xFCAC0001,0xA8A80001,0xA8A80001,0xA8A80001,0x8CA80001,0x1500620,0x1500620,0x1500620,0x1500620,0x1500620,0x1500620,0xC0400001,0xC0400001,0xC0400001,0x8C740000,0x2DF80620,0x2DF80620,0x2DF80620,0x88000041,0x70000620,0xF4D80451,0xE00622,0xE00622,0xFECC0242,0xFEBC0115,0xFEB4004A,0xFEB4004A,0xDCAC0001,0xFEBC03A9,0xFEB40202,0xC49C0000,0xC0400001,
+0x1E00620,};
+static const uint32_t g_etc1_to_bc7_m6_table181[] = {
+0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0xFF80000,
+0xFF80000,0xFF80000,0xFF80000,0x5C000000,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xAC40000,0xAC40000,0xAC40000,0x1140000,0x18C0000,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,
+0x1BC0000,0x61FC0000,0x61FC0000,0x61FC0000,0x94000000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x61FC0000,0x61FC0000,0x61FC0000,0x94000000,0x61FC0000,0x61FC0000,0x61FC0000,0x94000000,0x94000000,0x73C0000,0x1280001,0x1280001,0x5580000,0x3740000,0x1940000,0x1940000,0x1F40000,0x5580000,0x3740000,0x39FC0000,0x61FC0000,
+0x39FC0000,0x1880001,0x1880001,0x1880001,0x1880001,0x4FFC0000,0x4FFC0000,0x4FFC0000,0xA9FC0000,0xA9FC0000,0xC4000000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0xA9FC0000,0xA9FC0000,0xC4000000,0xA9FC0000,0xA9FC0000,0xC4000000,0xC4000000,0x4FFC0000,0x4FFC0000,0x4FFC0000,0xA9FC0000,0xA9FC0000,0xC4000000,0xA9FC0000,0xA9FC0000,0xC4000000,0xC4000000,0xA9FC0000,
+0xA9FC0000,0xC4000000,0xC4000000,0xC4000000,0x5C80000,0x1A40000,0x1880001,0x27FC0000,0x71FC0000,0x93FC0000,0x9FF80000,0xB1F80000,0x3EC0000,0x4FFC0000,0x93FC0000,0xC4000000,0x93FC0000,0x1F80001,0xFBFC0000,0xFDF80000,0xFC000000,0xFBFC0000,0xFDF80000,0xFC000000,0xFDF80000,0xFC000000,0xFC000000,0xFBFC0000,0xFDF80000,0xFC000000,0xFDF80000,0xFC000000,
+0xFC000000,0xFDF80000,0xFC000000,0xFC000000,0xFC000000,0xFBFC0000,0xFDF80000,0xFC000000,0xFDF80000,0xFC000000,0xFC000000,0xFDF80000,0xFC000000,0xFC000000,0xFC000000,0xFDF80000,0xFC000000,0xFC000000,0xFC000000,0xFC000000,0xF7FC0000,0xE7FC0000,0xE7FC0000,0xFBFC0000,0xFDF80000,0xFDF80000,0xFC000000,0xFC000000,0xF9FC0000,0xFBFC0000,0xFDEC0000,0xFC000000,
+0xFDF80000,0x1583684,0xFF44261B,0xFF2C1953,0xFD24152B,0xFF241F94,0xFF100F1F,0xFF00095F,0xFEFC0D92,0xF6F00686,0xE0F00C42,0xFF18234C,0xFEF00EDF,0xFEDC0767,0xFECC099A,0xFABC0012,0xE0C4068A,0xFCB8152C,0xEAA80735,0xD8A80931,0xC6B8152D,0x7FC3680,0xFED81E87,0xFCBC152B,0xFE9413F2,0xFE700655,0xE08C0C40,0xFE5818EB,0xFA1C0485,0xDE28067D,0xC650152D,0x85FC3680,
+0xE60017F0,0xD0001112,0xBE001AD5,0xAC003680,0xFF3C29CC,0xFF4C3204,0xFF4C3354,0xFF181C7A,0xFEFC0F77,0xFED40452,0xFECC0089,0xF4B00086,0xFF342916,0xFF101AAA,0xFEA404D3,0xDE28067D,0x65FC3680,0x190152B,0xFF740D62,0xFF6406C3,0xFD580482,0xFF680D01,0xFF4003E6,0xFF340081,0xFF2C0641,0xF3240131,0xE1280621,0x59FC152B,0xFF200966,0xFD0C0480,0xFEF00889,0xFABC0011,
+0xE0E00620,0xADFC152B,0xFC100480,0xE0000624,0xC600152C,0x59FC152B,0xFF200966,0xFD0C0480,0xFEF00889,0xFABC0011,0xE0E00620,0xADFC152B,0xFC100480,0xE0000624,0xC600152C,0xADFC152B,0xFC100480,0xE0000624,0xC600152C,0xC600152C,0xFF781162,0xFD8813A3,0xFF8C138B,0xFF540D51,0xFF28086E,0xFEF002BB,0xFCE00001,0xFA900038,0xFD7411AE,0xFF480C8E,0xFEA004D1,0xE0000624,
+0x99FC152B,0x124152B,0x124152B,0x124152B,0x124152B,0xFF00095B,0xFF00095B,0xFF00095B,0xE8F40622,0xE8F40622,0xC4F00622,0xFEDC0763,0xFEDC0763,0xFEDC0763,0xFABC000E,0xFABC000E,0xC8D00132,0xD2BC0481,0xD2BC0481,0xBEB0007D,0xACB80481,0x3B0152B,0x3B0152B,0x3B0152B,0xFE700651,0xFE700651,0xC4A80620,0xF6280481,0xF6280481,0xC4580005,0xAC6C0480,0x5DFC152B,
+0x5DFC152B,0xBE0006A6,0xA6000631,0x9200152C,0xFF100EED,0xF9201286,0x124152B,0xFEF80996,0xFEE40481,0xFECC0139,0xFECC0085,0xE8B80002,0xFEF80E66,0xFEE808E2,0xFCA40480,0xC4580005,0x33FC152B,0x1580482,0x1580482,0x1580482,0x1580482,0xFF34007D,0xFF34007D,0xFF34007D,0xDD280001,0xDD280001,0xC5280001,0x7FC0480,0x7FC0480,0x7FC0480,0xF0D00001,0xF0D00001,
+0xC4FC0000,0x85FC0480,0x85FC0480,0xC4640000,0xAC000480,0x7FC0480,0x7FC0480,0x7FC0480,0xF0D00001,0xF0D00001,0xC4FC0000,0x85FC0480,0x85FC0480,0xC4640000,0xAC000480,0x85FC0480,0x85FC0480,0xC4640000,0xAC000480,0xAC000480,0xF7480349,0xFF4C0392,0x1580482,0xFD300265,0xFD140120,0xFEEC003D,0xFCE00001,0xECB00000,0xFF34034D,0xFF18022D,0x65FC0480,0xC4640000,
+0x65FC0480,0x1C00622,0xFFB003A9,0xFF9400FA,0xFD880001,0xA5FC0620,0xFF70021D,0xFD540000,0xD3FC0620,0xFCA40000,0xE0000620,0xA5FC0620,0xFF70021D,0xFD540000,0xD3FC0620,0xFCA40000,0xE0000620,0xD3FC0620,0xFCA40000,0xE0000620,0xE0000620,0xA5FC0620,0xFF70021D,0xFD540000,0xD3FC0620,0xFCA40000,0xE0000620,0xD3FC0620,0xFCA40000,0xE0000620,0xE0000620,0xD3FC0620,
+0xFCA40000,0xE0000620,0xE0000620,0xE0000620,0xFFB4057D,0x1E00620,0xF9C005B2,0xFF9404B2,0xFF7C03A9,0xFF2C01BA,0xFCE40000,0xFC540000,0xFFAC0581,0xFF940488,0xFF10001D,0xE0000620,0xC7FC0620,0xF00622,0xF00622,0xF00622,0xF00622,0xF00622,0xF00622,0xF00622,0xF00622,0xF00622,0xF00622,0xFEBC0005,0xFEBC0005,0xFEBC0005,0xFEBC0005,0xFEBC0005,
+0xFEBC0005,0xB0B80001,0xB0B80001,0xB0B80001,0x94B80001,0x1680620,0x1680620,0x1680620,0x1680620,0x1680620,0x1680620,0xC8500001,0xC8500001,0xC8500001,0x94840000,0x39F80620,0x39F80620,0x39F80620,0x90000020,0x78000620,0xFCE80451,0xF00622,0xF00622,0xFED80271,0xFED0013D,0xFEC4006A,0xFEC4006A,0xE4BC0001,0xFCD403C8,0xFAC80244,0xCCAC0000,0xC8500001,
+0x3FC0620,};
+static const uint32_t g_etc1_to_bc7_m6_table182[] = {
+0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x1BF80000,
+0x1BF80000,0x1BF80000,0x1BF80000,0x64000000,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xD80000,0xD80000,0xD80000,0x12C0000,0x1AC0000,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x1380001,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x3D00000,
+0x3D00000,0x6DFC0000,0x6DFC0000,0x6DFC0000,0x9C000000,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x3D00000,0x6DFC0000,0x6DFC0000,0x6DFC0000,0x9C000000,0x6DFC0000,0x6DFC0000,0x6DFC0000,0x9C000000,0x9C000000,0xF4C0000,0x1380001,0x1380001,0x16C0000,0x3880000,0x1AC0000,0x1AC0000,0xFFC0000,0x16C0000,0x3880000,0x47FC0000,0x6DFC0000,
+0x47FC0000,0x1980001,0x1980001,0x1980001,0x1980001,0x69FC0000,0x69FC0000,0x69FC0000,0xB5FC0000,0xB5FC0000,0xCC000000,0x69FC0000,0x69FC0000,0x69FC0000,0xB5FC0000,0xB5FC0000,0xCC000000,0xB5FC0000,0xB5FC0000,0xCC000000,0xCC000000,0x69FC0000,0x69FC0000,0x69FC0000,0xB5FC0000,0xB5FC0000,0xCC000000,0xB5FC0000,0xB5FC0000,0xCC000000,0xCC000000,0xB5FC0000,
+0xB5FC0000,0xCC000000,0xCC000000,0xCC000000,0x1DC0000,0x3B40000,0x1980001,0x45FC0000,0x85FC0000,0xA1FC0000,0xABFC0000,0xBBFC0000,0xBFC0000,0x69FC0000,0xA1FC0000,0xCC000000,0xA1FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x16832DC,0xFF50247F,0xFF381933,0xFF34152B,0xFF3C1E14,0xFF200F63,0xFF1809EB,0xFF080CD6,0xF9000656,0xE5000B06,0xFF24213C,0xFF040F22,0xFEF407FB,0xFEE40906,0xFED00012,0xE8D4055E,0xFECC12C5,0xEEBC0679,0xDCBC0799,0xCCC812C5,0x19FC32DC,0xFEE41DCF,0xFED0152B,0xFEB81322,0xFE940691,0xE4A00B04,0xFE701733,0xFE380481,0xE4400525,0xCC6412C4,0x8FF832DC,
+0xF200169C,0xDC000E76,0xC4001765,0xB20032DC,0xFF502793,0xF9602F06,0xFB642FFB,0xFF2C1B7E,0xFF0C0F8A,0xFEE804E2,0xFEDC00E2,0xFAC4003B,0xFF3C26EC,0xFF1819CA,0xFEB804ED,0xE4400525,0x71FC32DC,0x19C12C3,0xFF800C56,0xFF7006A3,0xFF680482,0xFF740B9D,0xFF5803DE,0xFF4400A9,0xFF400533,0xF73400C2,0xE53804E5,0x6BFC12C3,0xFF3808E2,0xFF200482,0xFF080785,0xFCD80005,
+0xE4F404E4,0xB7F812C3,0xFE380480,0xE41404E4,0xCC0012C4,0x6BFC12C3,0xFF3808E2,0xFF200482,0xFF080785,0xFCD80005,0xE4F404E4,0xB7F812C3,0xFE380480,0xE41404E4,0xCC0012C4,0xB7F812C3,0xFE380480,0xE41404E4,0xCC0012C4,0xCC0012C4,0xFF800FC5,0xFF8C1193,0xF59811A2,0xFF6C0C12,0xFF4807DA,0xFF1002DD,0xFEF8000D,0xFCB00018,0xFF780FAA,0xFF5C0B8A,0xFED004E3,0xE41404E4,
+0xA3FC12C3,0x134152B,0x134152B,0x134152B,0x134152B,0xFF1809EB,0xFF1809EB,0xFF1809EB,0xF1040622,0xF1040622,0xCD000622,0xFEF407FB,0xFEF407FB,0xFEF407FB,0xFED00012,0xFED00012,0xD0E00132,0xDACC0481,0xDACC0481,0xC6C0007D,0xB4C80481,0x1C8152B,0x1C8152B,0x1C8152B,0xFE940691,0xFE940691,0xCCB80620,0xFE380481,0xFE380481,0xCC680005,0xB47C0480,0x69FC152B,
+0x69FC152B,0xC4000672,0xAC0005E1,0x9A00152C,0xFF200F46,0xFF2C1292,0x134152B,0xFF100A32,0xFEF40542,0xFEE001CB,0xFEDC00E2,0xF0C80002,0xFF140ED2,0xFEF4097A,0xFEB80489,0xCC680005,0x41FC152B,0x1680482,0x1680482,0x1680482,0x1680482,0xFF4400A9,0xFF4400A9,0xFF4400A9,0xE5380001,0xE5380001,0xCD380001,0x1FFC0480,0x1FFC0480,0x1FFC0480,0xF8E00001,0xF8E00001,
+0xCD0C0000,0x91FC0480,0x91FC0480,0xCC740000,0xB4000480,0x1FFC0480,0x1FFC0480,0x1FFC0480,0xF8E00001,0xF8E00001,0xCD0C0000,0x91FC0480,0x91FC0480,0xCC740000,0xB4000480,0x91FC0480,0x91FC0480,0xCC740000,0xB4000480,0xB4000480,0xFF580349,0xFB64039D,0x1680482,0xFF440288,0xFD280154,0xFEFC006D,0xFEF8000D,0xF4C00000,0xFD4C0372,0xFF300269,0x75FC0480,0xCC740000,
+0x75FC0480,0x1CC04E2,0xFFBC0305,0xFFA000EA,0xFF980001,0xB5FC04E2,0xFF8801CD,0xFF680000,0xDBF804E2,0xFECC0000,0xE40004E4,0xB5FC04E2,0xFF8801CD,0xFF680000,0xDBF804E2,0xFECC0000,0xE40004E4,0xDBF804E2,0xFECC0000,0xE40004E4,0xE40004E4,0xB5FC04E2,0xFF8801CD,0xFF680000,0xDBF804E2,0xFECC0000,0xE40004E4,0xDBF804E2,0xFECC0000,0xE40004E4,0xE40004E4,0xDBF804E2,
+0xFECC0000,0xE40004E4,0xE40004E4,0xE40004E4,0xF9C40480,0xDE804E2,0xFDC80482,0xFFB003CA,0xFF900305,0xFF480175,0xFF080000,0xFE840000,0xF3C40480,0xFFA003B5,0xFF300028,0xE40004E4,0xD1FC04E2,0x1000622,0x1000622,0x1000622,0x1000622,0x1000622,0x1000622,0x1000622,0x1000622,0x1000622,0x1000622,0xFED00012,0xFED00012,0xFED00012,0xFED00012,0xFED00012,
+0xFED00012,0xB8C80001,0xB8C80001,0xB8C80001,0x9CC80001,0x1800620,0x1800620,0x1800620,0x1800620,0x1800620,0x1800620,0xD0600001,0xD0600001,0xD0600001,0x9C940000,0x45F80620,0x45F80620,0x45F80620,0x9A00000D,0x80000620,0xF4F80482,0x1000622,0x1000622,0xFEE8029A,0xFEE4016D,0xFEDC0091,0xFEDC0091,0xECCC0001,0xF8E803F5,0xFED80269,0xD4BC0000,0xD0600001,
+0x13FC0620,};
+static const uint32_t g_etc1_to_bc7_m6_table183[] = {
+0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x27F80000,
+0x27F80000,0x27F80000,0x27F80000,0x6C000000,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xE80000,0xE80000,0xE80000,0x1440000,0x1D00000,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,
+0x3E80000,0x79FC0000,0x79FC0000,0x79FC0000,0xA4000000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x79FC0000,0x79FC0000,0x79FC0000,0xA4000000,0x79FC0000,0x79FC0000,0x79FC0000,0xA4000000,0xA4000000,0x1600000,0x1480001,0x1480001,0x1800000,0x39C0000,0x1C00000,0x1C00000,0x23FC0000,0x1800000,0x39C0000,0x57FC0000,0x79FC0000,
+0x57FC0000,0x1A80001,0x1A80001,0x1A80001,0x1A80001,0x81FC0000,0x81FC0000,0x81FC0000,0xC1FC0000,0xC1FC0000,0xD4000000,0x81FC0000,0x81FC0000,0x81FC0000,0xC1FC0000,0xC1FC0000,0xD4000000,0xC1FC0000,0xC1FC0000,0xD4000000,0xD4000000,0x81FC0000,0x81FC0000,0x81FC0000,0xC1FC0000,0xC1FC0000,0xD4000000,0xC1FC0000,0xC1FC0000,0xD4000000,0xD4000000,0xC1FC0000,
+0xC1FC0000,0xD4000000,0xD4000000,0xD4000000,0x1F00000,0xBC40000,0x1A80001,0x63FC0000,0x99FC0000,0xB1FC0000,0xB9FC0000,0xC7F40000,0x33FC0000,0x81FC0000,0xB1FC0000,0xD4000000,0xB1FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1742E54,0xFF5C2227,0xFF4C189C,0xFF44152B,0xFF441B96,0xFF2C0F3F,0xFF240A83,0xFF200BB6,0xFD10062A,0xE9100996,0xFF301E64,0xFF140EBF,0xFF0C08B3,0xFEF0080E,0xFEE40042,0xEAE40406,0xFEE00FFC,0xF2D005A9,0xE2C805B5,0xD2D80FD9,0x2BFC2E54,0xFEFC1C6F,0xFEE8152B,0xFECC11E6,0xFEAC06E9,0xE8B40994,0xFE9414BB,0xFE5804A2,0xE854039D,0xD2740FD9,0x97FC2E54,
+0xF8001590,0xE0000BBC,0xCA001371,0xB8002E54,0xFF58245E,0xFF6C2AA6,0xFF6C2BC3,0xFF4019B9,0xFF1C0EF6,0xFEFC0522,0xFEF00173,0xFCD8000A,0xFF5023BA,0xFF30184B,0xFED00513,0xE854039D,0x7DF82E54,0x1A40FDB,0xFF8C0AC6,0xFF7C063B,0xFF780482,0xFF8009BD,0xFF64037E,0xFF5C00E1,0xFF5803EB,0xF944005E,0xE9480375,0x7BFC0FD8,0xFF4C0811,0xFF380482,0xFF200615,0xFEF00005,
+0xE9080374,0xBFF80FD8,0xFE6C0480,0xE8340374,0xD2000FD8,0x7BFC0FD8,0xFF4C0811,0xFF380482,0xFF200615,0xFEF00005,0xE9080374,0xBFF80FD8,0xFE6C0480,0xE8340374,0xD2000FD8,0xBFF80FD8,0xFE6C0480,0xE8340374,0xD2000FD8,0xD2000FD8,0xFF940D34,0xF9A00ECD,0xFBA40ED6,0xFF780A71,0xFF5C06D6,0xFF2C0293,0xFF10002D,0xFECC0002,0xFF880D43,0xFF680A04,0xFEE404D1,0xE8340374,
+0xADFC0FD8,0x144152B,0x144152B,0x144152B,0x144152B,0xFF240A83,0xFF240A83,0xFF240A83,0xF9140622,0xF9140622,0xD5100622,0xFF0C08B3,0xFF0C08B3,0xFF0C08B3,0xFEE40042,0xFEE40042,0xD8F00132,0xE2DC0481,0xE2DC0481,0xCED0007D,0xBCD80481,0x1E0152B,0x1E0152B,0x1E0152B,0xFEAC06E9,0xFEAC06E9,0xD4C80620,0xFE5804A2,0xFE5804A2,0xD4780005,0xBC8C0480,0x75FC152B,
+0x75FC152B,0xD0000642,0xB8000581,0xA200152C,0xFF2C0FD1,0xF94012E3,0x144152B,0xFF180AF6,0xFF080612,0xFEF8026E,0xFEF00173,0xF8D80002,0xFF200F41,0xFF100A41,0xFED004C2,0xD4780005,0x51FC152B,0x1780482,0x1780482,0x1780482,0x1780482,0xFF5C00E1,0xFF5C00E1,0xFF5C00E1,0xED480001,0xED480001,0xD5480001,0x37FC0480,0x37FC0480,0x37FC0480,0xFCF80005,0xFCF80005,
+0xD51C0000,0x9DFC0480,0x9DFC0480,0xD4840000,0xBC000480,0x37FC0480,0x37FC0480,0x37FC0480,0xFCF80005,0xFCF80005,0xD51C0000,0x9DFC0480,0x9DFC0480,0xD4840000,0xBC000480,0x9DFC0480,0x9DFC0480,0xD4840000,0xBC000480,0xBC000480,0xFB6C0372,0xFF6C03C5,0x1780482,0xFD5802AD,0xFF400188,0xFF2000A4,0xFF10002D,0xFCD00000,0xF564039D,0xFF48028A,0x83FC0480,0xD4840000,
+0x83FC0480,0x1D40372,0xFFC40212,0xFFB400A9,0xFFA80001,0xC1FC0372,0xFF940145,0xFF800000,0xE1F80372,0xFEFC0000,0xE8000374,0xC1FC0372,0xFF940145,0xFF800000,0xE1F80372,0xFEFC0000,0xE8000374,0xE1F80372,0xFEFC0000,0xE8000374,0xE8000374,0xC1FC0372,0xFF940145,0xFF800000,0xE1F80372,0xFEFC0000,0xE8000374,0xE1F80372,0xFEFC0000,0xE8000374,0xE8000374,0xE1F80372,
+0xFEFC0000,0xE8000374,0xE8000374,0xE8000374,0xFDCC0320,0x1F40372,0xFFCC0332,0xFFC002AD,0xFFA80221,0xFF5C0110,0xFF300000,0xFEC00000,0xF7CC0320,0xFFAC02A8,0xFF50001A,0xE8000374,0xD9FC0372,0x1100622,0x1100622,0x1100622,0x1100622,0x1100622,0x1100622,0x1100622,0x1100622,0x1100622,0x1100622,0xFEE0002D,0xFEE0002D,0xFEE0002D,0xFEE0002D,0xFEE0002D,
+0xFEE0002D,0xC0D80001,0xC0D80001,0xC0D80001,0xA4D80001,0x1980620,0x1980620,0x1980620,0x1980620,0x1980620,0x1980620,0xD8700001,0xD8700001,0xD8700001,0xA4A40000,0x51F80620,0x51F80620,0x51F80620,0xA4000004,0x88000620,0xFD080482,0x1100622,0x1100622,0xFD0002D2,0xFEF801A5,0xFEE800C1,0xFEE800C1,0xF4DC0001,0xFEF403F9,0xFEE402A8,0xDCCC0000,0xD8700001,
+0x21FC0620,};
+static const uint32_t g_etc1_to_bc7_m6_table184[] = {
+0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x33FC0000,
+0x33FC0000,0x33FC0000,0x33FC0000,0x74000001,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xFC0000,0xFC0000,0xFC0000,0x35C0000,0x1F40000,0x15C0000,0x15C0000,0x15C0000,0x15C0000,0x15C0000,0x15C0000,0x15C0000,0x15C0000,0x15C0000,0x15C0000,0x9FC0000,0x9FC0000,0x9FC0000,0x9FC0000,0x9FC0000,
+0x9FC0000,0x87FC0000,0x87FC0000,0x87FC0000,0xAC000001,0x9FC0000,0x9FC0000,0x9FC0000,0x9FC0000,0x9FC0000,0x9FC0000,0x87FC0000,0x87FC0000,0x87FC0000,0xAC000001,0x87FC0000,0x87FC0000,0x87FC0000,0xAC000001,0xAC000001,0x1740000,0x15C0000,0x15C0000,0x1940000,0x1B40000,0x1D80000,0x1D80000,0x39FC0000,0x1940000,0x1B40000,0x67FC0000,0x87FC0000,
+0x67FC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0xCFF80000,0xCFF80000,0xDC000001,0x9BFC0000,0x9BFC0000,0x9BFC0000,0xCFF80000,0xCFF80000,0xDC000001,0xCFF80000,0xCFF80000,0xDC000001,0xDC000001,0x9BFC0000,0x9BFC0000,0x9BFC0000,0xCFF80000,0xCFF80000,0xDC000001,0xCFF80000,0xCFF80000,0xDC000001,0xDC000001,0xCFF80000,
+0xCFF80000,0xDC000001,0xDC000001,0xDC000001,0x17FC0000,0x5D80000,0x1BC0000,0x85FC0000,0xAFFC0000,0xC1FC0000,0xC9F80000,0xD3F80000,0x5FFC0000,0x9BFC0000,0xC1FC0000,0xDC000001,0xC1FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x18029AD,0xFF681FD0,0xFF581805,0xFF58152C,0xFF5C195D,0xFF400F2A,0xFF3C0B40,0xFF2C0AC5,0xFF240629,0xEF240841,0xFF441B46,0xFF2C0E8C,0xFF180984,0xFF080739,0xFEFC00B5,0xF0FC02D1,0xFEF80D65,0xF6E40502,0xE8E003EA,0xD8EC0CF6,0x41FC29AD,0xFF141B10,0xFF04152B,0xFEE41095,0xFECC0789,0xEEC80841,0xFEAC126A,0xFE7C04F9,0xEC740236,0xD88C0CF6,0xA1FC29AD,
+0xFE00152B,0xE6000953,0xD4000F97,0xC00029AF,0xFF64212B,0xF77C26D9,0xF98027C5,0xFF5417DD,0xFF300E79,0xFF1805B7,0xFF080236,0xFEEC0009,0xFF5C209B,0xFF40169E,0xFEF0056C,0xEC740236,0x89FC29AD,0x1B00CF9,0xFFA40924,0xFF9405C1,0xFF8C0480,0xFF8C07FD,0xFF7C0332,0xFF740139,0xFF6402C1,0xFD580018,0xEF5C0221,0x8DFC0CF6,0xFF640723,0xFF540480,0xFF3804C5,0xFF14001D,
+0xEF1C0221,0xC7FC0CF6,0xFEA00480,0xEE500221,0xD8000CF6,0x8DFC0CF6,0xFF640723,0xFF540480,0xFF3804C5,0xFF14001D,0xEF1C0221,0xC7FC0CF6,0xFEA00480,0xEE500221,0xD8000CF6,0xC7FC0CF6,0xFEA00480,0xEE500221,0xD8000CF6,0xD8000CF6,0xFFA00AE3,0xFFAC0BFD,0xFFAC0C24,0xFF9408AE,0xFF6805CD,0xFF48026C,0xFF280068,0xFEF40008,0xFF980AF2,0xFF840840,0xFF1004B3,0xEE500221,
+0xB9FC0CF6,0x158152C,0x158152C,0x158152C,0x158152C,0xFF3C0B40,0xFF3C0B40,0xFF3C0B40,0xFF240629,0xFF240629,0xDD240621,0xFF180984,0xFF180984,0xFF180984,0xFEFC00B5,0xFEFC00B5,0xE1000131,0xECEC0480,0xECEC0480,0xD8E4007A,0xC4EC0482,0x1FC152B,0x1FC152B,0x1FC152B,0xFECC0789,0xFECC0789,0xDCDC0621,0xFE7C04F9,0xFE7C04F9,0xDE880006,0xC4A00482,0x83F8152B,
+0x83F8152B,0xDC000629,0xC200053B,0xAA00152B,0xFD48103D,0xFF4C1304,0x158152C,0xFF340BC5,0xFF1C0715,0xFF100379,0xFF080236,0xFEEC0009,0xFF340FA9,0xFF240B2D,0xFEF0052C,0xDE880006,0x61FC152B,0x18C0480,0x18C0480,0x18C0480,0x18C0480,0xFF740139,0xFF740139,0xFF740139,0xF55C0000,0xF55C0000,0xDD5C0001,0x53FC0480,0x53FC0480,0x53FC0480,0xFF14001D,0xFF14001D,
+0xDF2C0001,0xABF80480,0xABF80480,0xDC9C0001,0xC4000482,0x53FC0480,0x53FC0480,0x53FC0480,0xFF14001D,0xFF14001D,0xDF2C0001,0xABF80480,0xABF80480,0xDC9C0001,0xC4000482,0xABF80480,0xABF80480,0xDC9C0001,0xC4000482,0xC4000482,0xF780039D,0xFD8803C8,0x18C0480,0xFB7002F9,0xFF5401CA,0xFF3800E9,0xFF280068,0xFEF40008,0xFD74039D,0xFF5C02B9,0x95FC0480,0xDC9C0001,
+0x95FC0480,0x1DC0221,0xFFD00145,0xFFC00068,0xFFBC0000,0xCDFC0221,0xFFAC00C2,0xFF9C0000,0xE7F80221,0xFF340000,0xEE000221,0xCDFC0221,0xFFAC00C2,0xFF9C0000,0xE7F80221,0xFF340000,0xEE000221,0xE7F80221,0xFF340000,0xEE000221,0xEE000221,0xCDFC0221,0xFFAC00C2,0xFF9C0000,0xE7F80221,0xFF340000,0xEE000221,0xE7F80221,0xFF340000,0xEE000221,0xEE000221,0xE7F80221,
+0xFF340000,0xEE000221,0xEE000221,0xEE000221,0xFFD001ED,0x1FC0221,0xF7DC0200,0xFFC001A8,0xFFA80152,0xFF8400A0,0xFF5C0000,0xFF040000,0xFBD401E1,0xFFC00190,0xFF700010,0xEE000221,0xDFFC0221,0x1240620,0x1240620,0x1240620,0x1240620,0x1240620,0x1240620,0x1240620,0x1240620,0x1240620,0x1240620,0xFEF40050,0xFEF40050,0xFEF40050,0xFEF40050,0xFEF40050,
+0xFEF40050,0xC8EC0000,0xC8EC0000,0xC8EC0000,0xACEC0001,0x3B00620,0x3B00620,0x3B00620,0x3B00620,0x3B00620,0x3B00620,0xE0840001,0xE0840001,0xE0840001,0xAEB40001,0x5DFC0620,0x5DFC0620,0x5DFC0620,0xAC080001,0x90000622,0xF71C04B1,0x1240620,0x1240620,0xFF1002FD,0xFF0C01E1,0xFF0000F4,0xFF0000F4,0xFEEC0000,0xFD0C0422,0xFF0002D4,0xE6DC0000,0xE0840001,
+0x33FC0620,};
+static const uint32_t g_etc1_to_bc7_m6_table185[] = {
+0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0x3740000,0x3740000,0x3740000,0x3740000,0x3740000,0x3740000,0x3740000,0x3740000,0x3740000,0x3740000,0x3FFC0000,
+0x3FFC0000,0x3FFC0000,0x3FFC0000,0x7C000001,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0x10C0000,0x10C0000,0x10C0000,0x3740000,0xDFC0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x23FC0000,0x23FC0000,0x23FC0000,0x23FC0000,0x23FC0000,
+0x23FC0000,0x93FC0000,0x93FC0000,0x93FC0000,0xB4000001,0x23FC0000,0x23FC0000,0x23FC0000,0x23FC0000,0x23FC0000,0x23FC0000,0x93FC0000,0x93FC0000,0x93FC0000,0xB4000001,0x93FC0000,0x93FC0000,0x93FC0000,0xB4000001,0xB4000001,0x1840000,0x16C0000,0x16C0000,0x1A80000,0x1C80000,0x1F00000,0x1F00000,0x4DFC0000,0x1A80000,0x1C80000,0x77FC0000,0x93FC0000,
+0x77FC0000,0x1CC0000,0x1CC0000,0x1CC0000,0x1CC0000,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xDBF80000,0xDBF80000,0xE4000001,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xDBF80000,0xDBF80000,0xE4000001,0xDBF80000,0xDBF80000,0xE4000001,0xE4000001,0xB5FC0000,0xB5FC0000,0xB5FC0000,0xDBF80000,0xDBF80000,0xE4000001,0xDBF80000,0xDBF80000,0xE4000001,0xE4000001,0xDBF80000,
+0xDBF80000,0xE4000001,0xE4000001,0xE4000001,0x51FC0000,0xDE80000,0x1CC0000,0xA3FC0000,0xC3FC0000,0xD1FC0000,0xD5FC0000,0xDDFC0000,0x87FC0000,0xB5FC0000,0xD1FC0000,0xE4000001,0xD1FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x18C25F1,0xFF801DF0,0xFF70177D,0xFF68152C,0xFF68179D,0xFF540F30,0xFF500BE9,0xFF400A4D,0xFF380659,0xF3340759,0xFF5C1916,0xFF3C0E80,0xFF300A44,0xFF2006D1,0xFF100159,0xF30C0209,0xFF080B86,0xFAF804A6,0xECF402A6,0xDEFC0AC2,0x53FC25F1,0xFF2C19F0,0xFF1C152B,0xFEFC0FAD,0xFEE40821,0xF2DC0759,0xFECC10EA,0xFE940579,0xF0880142,0xDE9C0AC2,0xABF825F1,
+0xFE2C152B,0xEC0007C7,0xDA000C9B,0xC60025F3,0xFF781EA2,0xFD88233D,0xFF8C2439,0xFF5C168D,0xFF440E39,0xFF240649,0xFF1C031D,0xFF040051,0xFF701E24,0xFF501536,0xFEFC05F2,0xF0880142,0x95FC25F1,0x1BC0AC1,0xFFB007EC,0xFFA00569,0xFF9C0480,0xFFA406AD,0xFF88030E,0xFF800185,0xFF7C0209,0xFF6C0001,0xF36C0139,0x9BFC0AC1,0xFF7C066B,0xFF6C0480,0xFF5803FE,0xFF2C0055,
+0xF3300139,0xCFF80AC1,0xFED40480,0xF2700139,0xDE000AC2,0x9BFC0AC1,0xFF7C066B,0xFF6C0480,0xFF5803FE,0xFF2C0055,0xF3300139,0xCFF80AC1,0xFED40480,0xF2700139,0xDE000AC2,0xCFF80AC1,0xFED40480,0xF2700139,0xDE000AC2,0xDE000AC2,0xFFB4091E,0xF5B80A25,0xF7BC0A41,0xFF98075D,0xFF7C0521,0xFF5C026D,0xFF4800B4,0xFF0C0032,0xFFA4093E,0xFF900722,0xFF3004A6,0xF2700139,
+0xC1FC0AC1,0x168152C,0x168152C,0x168152C,0x168152C,0xFF500BE9,0xFF500BE9,0xFF500BE9,0xFF380659,0xFF380659,0xE5340621,0xFF300A44,0xFF300A44,0xFF300A44,0xFF100159,0xFF100159,0xE9100131,0xF4FC0480,0xF4FC0480,0xE0F4007A,0xCCFC0482,0x19FC152B,0x19FC152B,0x19FC152B,0xFEE40821,0xFEE40821,0xE4EC0621,0xFE940579,0xFE940579,0xE6980006,0xCCB00482,0x8FF8152B,
+0x8FF8152B,0xE4000621,0xCA0004F6,0xB200152B,0xFF5810A1,0xFB641341,0x168152C,0xFF440C7A,0xFF300805,0xFF240465,0xFF1C031D,0xFF040051,0xFF501035,0xFF300BE1,0xFEFC05B2,0xE6980006,0x71FC152B,0x19C0480,0x19C0480,0x19C0480,0x19C0480,0xFF800185,0xFF800185,0xFF800185,0xFD6C0000,0xFD6C0000,0xE56C0001,0x6BFC0480,0x6BFC0480,0x6BFC0480,0xFF2C0055,0xFF2C0055,
+0xE73C0001,0xB7F80480,0xB7F80480,0xE4AC0001,0xCC000482,0x6BFC0480,0x6BFC0480,0x6BFC0480,0xFF2C0055,0xFF2C0055,0xE73C0001,0xB7F80480,0xB7F80480,0xE4AC0001,0xCC000482,0xB7F80480,0xB7F80480,0xE4AC0001,0xCC000482,0xCC000482,0xFF90039D,0xF59803F5,0x19C0480,0xFD840320,0xFF700221,0xFF500151,0xFF4800B4,0xFF0C0032,0xFD8803C8,0xFF7402FD,0xA3FC0480,0xE4AC0001,
+0xA3FC0480,0x1E40139,0xFFDC00B9,0xFFCC0040,0xFFCC0000,0xD9FC0139,0xFFC00074,0xFFB40000,0xEDF80139,0xFF640000,0xF2000139,0xD9FC0139,0xFFC00074,0xFFB40000,0xEDF80139,0xFF640000,0xF2000139,0xEDF80139,0xFF640000,0xF2000139,0xF2000139,0xD9FC0139,0xFFC00074,0xFFB40000,0xEDF80139,0xFF640000,0xF2000139,0xEDF80139,0xFF640000,0xF2000139,0xF2000139,0xEDF80139,
+0xFF640000,0xF2000139,0xF2000139,0xF2000139,0xF5E40120,0x37FC0139,0xFBE40120,0xFFD800F2,0xFFBC00C2,0xFFA40061,0xFF840000,0xFF400000,0xFFDC0109,0xFFCC00E9,0xFF940009,0xF2000139,0xE7FC0139,0x1340620,0x1340620,0x1340620,0x1340620,0x1340620,0x1340620,0x1340620,0x1340620,0x1340620,0x1340620,0xFF0C0080,0xFF0C0080,0xFF0C0080,0xFF0C0080,0xFF0C0080,
+0xFF0C0080,0xD0FC0000,0xD0FC0000,0xD0FC0000,0xB4FC0001,0x1C80620,0x1C80620,0x1C80620,0x1C80620,0x1C80620,0x1C80620,0xE8940001,0xE8940001,0xE8940001,0xB6C40001,0x69FC0620,0x69FC0620,0x69FC0620,0xB4180001,0x98000622,0xFF2C04B1,0x1340620,0x1340620,0xFF200328,0xFF140220,0xFF100128,0xFF100128,0xFF000008,0xFD1C0451,0xFF1402F9,0xEEEC0000,0xE8940001,
+0x41FC0620,};
+static const uint32_t g_etc1_to_bc7_m6_table186[] = {
+0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x4BFC0000,
+0x4BFC0000,0x4BFC0000,0x4BFC0000,0x84000001,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x71C0000,0x71C0000,0x71C0000,0x38C0000,0x1DF80000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x17C0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,
+0x3BFC0000,0x9FF80000,0x9FF80000,0x9FF80000,0xBC000001,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x9FF80000,0x9FF80000,0x9FF80000,0xBC000001,0x9FF80000,0x9FF80000,0x9FF80000,0xBC000001,0xBC000001,0x3940000,0x17C0000,0x17C0000,0x5B80000,0x1DC0000,0xDFC0000,0xDFC0000,0x61FC0000,0x5B80000,0x1DC0000,0x85FC0000,0x9FF80000,
+0x85FC0000,0x1DC0000,0x1DC0000,0x1DC0000,0x1DC0000,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xE7F80000,0xE7F80000,0xEC000001,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xE7F80000,0xE7F80000,0xEC000001,0xE7F80000,0xE7F80000,0xEC000001,0xEC000001,0xCDFC0000,0xCDFC0000,0xCDFC0000,0xE7F80000,0xE7F80000,0xEC000001,0xE7F80000,0xE7F80000,0xEC000001,0xEC000001,0xE7F80000,
+0xE7F80000,0xEC000001,0xEC000001,0xEC000001,0x89FC0000,0x1FC0000,0x1DC0000,0xC1FC0000,0xD7FC0000,0xDFFC0000,0xE3FC0000,0xE9F40000,0xADFC0000,0xCDFC0000,0xDFFC0000,0xEC000001,0xDFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1982295,0xFF8C1C24,0xFF7C16F9,0xFF78152C,0xFF74162D,0xFF640F5A,0xFF5C0C99,0xFF4C0A19,0xFF4C06D0,0xF74406B1,0xFF68172A,0xFF500E8F,0xFF440B02,0xFF2C06C9,0xFF200231,0xF7200185,0xFF200A26,0xFF0C0482,0xF30001AE,0xE30C08E2,0x65FC2295,0xFF401914,0xFF34152B,0xFF140F05,0xFEFC08D9,0xF6F006B1,0xFEE40F9A,0xFEB80619,0xF49C0096,0xE2B008E2,0xB3FC2295,
+0xFE60152B,0xF40006C7,0xE0000A17,0xCC002297,0xFF801C65,0xFF8C2049,0xF598216C,0xFF701581,0xFF540E23,0xFF3806FD,0xFF340421,0xFF1400E4,0xFF781BC6,0xFF5C147B,0xFF1806AC,0xF49C0096,0x9FFC2295,0x1C808E1,0xFFBC06E4,0xFFAC0529,0xFFAC0480,0xFFB00599,0xFF9C0300,0xFF9801E5,0xFF880191,0xFF7C0010,0xF77C0091,0xAFFC08E1,0xFF9405D3,0xFF840480,0xFF700356,0xFF4C00A9,
+0xF7440091,0xD7FC08E1,0xFF040480,0xF6900091,0xE20008E2,0xAFFC08E1,0xFF9405D3,0xFF840480,0xFF700356,0xFF4C00A9,0xF7440091,0xD7FC08E1,0xFF040480,0xF6900091,0xE20008E2,0xD7FC08E1,0xFF040480,0xF6900091,0xE20008E2,0xE20008E2,0xFFBC07A1,0xFBC4084D,0xFBC40879,0xFFB00662,0xFF90049D,0xFF740269,0xFF640104,0xFF300074,0xFFB407AA,0xFFA40632,0xFF500499,0xF6900091,
+0xCDFC08E1,0x178152C,0x178152C,0x178152C,0x178152C,0xFF5C0C99,0xFF5C0C99,0xFF5C0C99,0xFF4C06D0,0xFF4C06D0,0xED440621,0xFF440B02,0xFF440B02,0xFF440B02,0xFF200231,0xFF200231,0xF1200131,0xFD0C0480,0xFD0C0480,0xE904007A,0xD50C0482,0x31FC152B,0x31FC152B,0x31FC152B,0xFEFC08D9,0xFEFC08D9,0xECFC0621,0xFEB80619,0xFEB80619,0xEEA80006,0xD4C00482,0x9BF8152B,
+0x9BF8152B,0xEC100621,0xD20004D2,0xBA00152B,0xFF6810FE,0xFF6C1369,0x178152C,0xFF540D39,0xFF440905,0xFF340565,0xFF340421,0xFF1400E4,0xFF5810BE,0xFF500C92,0xFF18067B,0xEEA80006,0x7FFC152B,0x1AC0480,0x1AC0480,0x1AC0480,0x1AC0480,0xFF9801E5,0xFF9801E5,0xFF9801E5,0xFF7C0010,0xFF7C0010,0xED7C0001,0x83FC0480,0x83FC0480,0x83FC0480,0xFF4C00A9,0xFF4C00A9,
+0xEF4C0001,0xC3F80480,0xC3F80480,0xECBC0001,0xD4000482,0x83FC0480,0x83FC0480,0x83FC0480,0xFF4C00A9,0xFF4C00A9,0xEF4C0001,0xC3F80480,0xC3F80480,0xECBC0001,0xD4000482,0xC3F80480,0xC3F80480,0xECBC0001,0xD4000482,0xD4000482,0xFFA003CA,0xFDA803F5,0x1AC0480,0xFF980349,0xFF840269,0xFF6C019A,0xFF640104,0xFF300074,0xFF9403DA,0xFF840340,0xB3FC0480,0xECBC0001,
+0xB3FC0480,0x1EC0091,0xFFE80055,0xFFE0001D,0xFFDC0000,0xE5FC0091,0xFFD80034,0xFFCC0000,0xF3F80091,0xFF940000,0xF6000091,0xE5FC0091,0xFFD80034,0xFFCC0000,0xF3F80091,0xFF940000,0xF6000091,0xF3F80091,0xFF940000,0xF6000091,0xF6000091,0xE5FC0091,0xFFD80034,0xFFCC0000,0xF3F80091,0xFF940000,0xF6000091,0xF3F80091,0xFF940000,0xF6000091,0xF6000091,0xF3F80091,
+0xFF940000,0xF6000091,0xF6000091,0xF6000091,0xF9EC0080,0x77FC0091,0xFFEC0080,0xFDE80071,0xFFD0005A,0xFFC00028,0xFFA80000,0xFF7C0000,0xFFE80080,0xFFE00071,0xFFB40004,0xF6000091,0xEFFC0091,0x1440620,0x1440620,0x1440620,0x1440620,0x1440620,0x1440620,0x1440620,0x1440620,0x1440620,0x1440620,0xFF1800B4,0xFF1800B4,0xFF1800B4,0xFF1800B4,0xFF1800B4,
+0xFF1800B4,0xD90C0000,0xD90C0000,0xD90C0000,0xBD0C0001,0x1E00620,0x1E00620,0x1E00620,0x1E00620,0x1E00620,0x1E00620,0xF0A40001,0xF0A40001,0xF0A40001,0xBED40001,0x75FC0620,0x75FC0620,0x75FC0620,0xBC280001,0xA0000622,0xF73C04E4,0x1440620,0x1440620,0xFF2C0371,0xFF280254,0xFF240171,0xFF240171,0xFF140020,0xF9300480,0xFF200332,0xF6FC0000,0xF0A40001,
+0x51FC0620,};
+static const uint32_t g_etc1_to_bc7_m6_table187[] = {
+0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x57FC0000,
+0x57FC0000,0x57FC0000,0x57FC0000,0x8C000001,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0xF2C0000,0xF2C0000,0xF2C0000,0x3A40000,0x2BFC0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,
+0x53FC0000,0xABF80000,0xABF80000,0xABF80000,0xC4000001,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0xABF80000,0xABF80000,0xABF80000,0xC4000001,0xABF80000,0xABF80000,0xABF80000,0xC4000001,0xC4000001,0xBA40000,0x18C0000,0x18C0000,0x1CC0000,0x1F00000,0x2BFC0000,0x2BFC0000,0x73FC0000,0x1CC0000,0x1F00000,0x95FC0000,0xABF80000,
+0x95FC0000,0x1EC0000,0x1EC0000,0x1EC0000,0x1EC0000,0xE5FC0000,0xE5FC0000,0xE5FC0000,0xF3F80000,0xF3F80000,0xF4000001,0xE5FC0000,0xE5FC0000,0xE5FC0000,0xF3F80000,0xF3F80000,0xF4000001,0xF3F80000,0xF3F80000,0xF4000001,0xF4000001,0xE5FC0000,0xE5FC0000,0xE5FC0000,0xF3F80000,0xF3F80000,0xF4000001,0xF3F80000,0xF3F80000,0xF4000001,0xF4000001,0xF3F80000,
+0xF3F80000,0xF4000001,0xF4000001,0xF4000001,0xC3FC0000,0x77FC0000,0x1EC0000,0xDFFC0000,0xEBFC0000,0xEFFC0000,0xF1FC0000,0xF3FC0000,0xD5FC0000,0xE5FC0000,0xEFFC0000,0xF4000001,0xEFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1A41F99,0xFF981A90,0xFF881695,0xFF88152C,0xFF80150D,0xFF740F8A,0xFF680D79,0xFF640A11,0xFF58076C,0xFB540649,0xFF7415A6,0xFF600EC8,0xFF5C0BF2,0xFF40071A,0xFF380339,0xFD2C0139,0xFF2C0946,0xFF200496,0xF71400FA,0xE91C0756,0x77FC1F99,0xFF58182C,0xFF4C152B,0xFF2C0E9D,0xFF1409B1,0xFB040649,0xFF080EA6,0xFED80706,0xFAB0002A,0xE8C40756,0xBDF81F99,
+0xFE90152B,0xFA080649,0xE600080B,0xD2001F9B,0xFF901A71,0xF9A01DC1,0xFBA41E94,0xFF80147F,0xFF640E3A,0xFF4C0805,0xFF3C0548,0xFF3001B8,0xFF9019F6,0xFF7413B6,0xFF300766,0xFAB0002A,0xABFC1F99,0x1D00759,0xFFC40609,0xFFC004EC,0xFFBC0480,0xFFBC04CD,0xFFB0030E,0xFFA40249,0xFFA00169,0xFF940050,0xFB8C0029,0xBDFC0756,0xFFAC055B,0xFF9C0480,0xFF8802EE,0xFF700115,
+0xFB580029,0xDFF80756,0xFF340480,0xFAB00029,0xE8000756,0xBDFC0756,0xFFAC055B,0xFF9C0480,0xFF8802EE,0xFF700115,0xFB580029,0xDFF80756,0xFF340480,0xFAB00029,0xE8000756,0xDFF80756,0xFF340480,0xFAB00029,0xE8000756,0xE8000756,0xFDCC067A,0xFFCC06D5,0xFFCC0711,0xFFC0058C,0xFFA40441,0xFF8402B0,0xFF7C0172,0xFF5000DD,0xFFC4067D,0xFFB0057E,0xFF700490,0xFAB00029,
+0xD7FC0756,0x188152C,0x188152C,0x188152C,0x188152C,0xFF680D79,0xFF680D79,0xFF680D79,0xFF58076C,0xFF58076C,0xF5540621,0xFF5C0BF2,0xFF5C0BF2,0xFF5C0BF2,0xFF380339,0xFF380339,0xF9300131,0xFF200496,0xFF200496,0xF114007A,0xDD1C0482,0x49FC152B,0x49FC152B,0x49FC152B,0xFF1409B1,0xFF1409B1,0xF50C0621,0xFED80706,0xFED80706,0xF6B80006,0xDCD00482,0xA7F8152B,
+0xA7F8152B,0xF4200621,0xDC0004A6,0xC200152B,0xFF741194,0xFB8413A0,0x188152C,0xFF680E19,0xFF580A15,0xFF4C06C1,0xFF3C0548,0xFF3001B8,0xFF741148,0xFF5C0D82,0xFF300742,0xF6B80006,0x8FFC152B,0x1BC0480,0x1BC0480,0x1BC0480,0x1BC0480,0xFFA40249,0xFFA40249,0xFFA40249,0xFF940050,0xFF940050,0xF58C0001,0x9BFC0480,0x9BFC0480,0x9BFC0480,0xFF700115,0xFF700115,
+0xF75C0001,0xCFF80480,0xCFF80480,0xF4CC0001,0xDC000482,0x9BFC0480,0x9BFC0480,0x9BFC0480,0xFF700115,0xFF700115,0xF75C0001,0xCFF80480,0xCFF80480,0xF4CC0001,0xDC000482,0xCFF80480,0xCFF80480,0xF4CC0001,0xDC000482,0xDC000482,0xFBB403F5,0xF5B80424,0x1BC0480,0xFFA40384,0xFF9802B9,0xFF7C020A,0xFF7C0172,0xFF5000DD,0xFDB003F5,0xFF980371,0xC1FC0480,0xF4CC0001,
+0xC1FC0480,0x1F40029,0xFFF40019,0xFFF00008,0xFFEC0000,0xF1FC0029,0xFFE40010,0xFFE40000,0xF9F80029,0xFFC80000,0xFA000029,0xF1FC0029,0xFFE40010,0xFFE40000,0xF9F80029,0xFFC80000,0xFA000029,0xF9F80029,0xFFC80000,0xFA000029,0xFA000029,0xF1FC0029,0xFFE40010,0xFFE40000,0xF9F80029,0xFFC80000,0xFA000029,0xF9F80029,0xFFC80000,0xFA000029,0xFA000029,0xF9F80029,
+0xFFC80000,0xFA000029,0xFA000029,0xFA000029,0xFDF40020,0xB7FC0029,0xF3F40029,0xFFEC001D,0xFFE80014,0xFFDC000A,0xFFD00000,0xFFB80000,0xFFF00022,0xFFF00020,0xFFD80001,0xFA000029,0xF7FC0029,0x1540620,0x1540620,0x1540620,0x1540620,0x1540620,0x1540620,0x1540620,0x1540620,0x1540620,0x1540620,0xFF3000F4,0xFF3000F4,0xFF3000F4,0xFF3000F4,0xFF3000F4,
+0xFF3000F4,0xE11C0000,0xE11C0000,0xE11C0000,0xC51C0001,0x1F80620,0x1F80620,0x1F80620,0x1F80620,0x1F80620,0x1F80620,0xF8B40001,0xF8B40001,0xF8B40001,0xC6E40001,0x81FC0620,0x81FC0620,0x81FC0620,0xC4380001,0xA8000622,0xFF4C04E4,0x1540620,0x1540620,0xFD48039D,0xFF3C0290,0xFF3401B1,0xFF3401B1,0xFF240050,0xFF3C0488,0xFF340355,0xFF0C0000,0xF8B40001,
+0x5FFC0620,};
+static const uint32_t g_etc1_to_bc7_m6_table188[] = {
+0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x65F80000,
+0x65F80000,0x65F80000,0x65F80000,0x96000000,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x9400000,0x9400000,0x9400000,0x1C00000,0x3DF80000,0x19C0001,0x19C0001,0x19C0001,0x19C0001,0x19C0001,0x19C0001,0x19C0001,0x19C0001,0x19C0001,0x19C0001,0x6FFC0000,0x6FFC0000,0x6FFC0000,0x6FFC0000,0x6FFC0000,
+0x6FFC0000,0xB9F80000,0xB9F80000,0xB9F80000,0xCE000000,0x6FFC0000,0x6FFC0000,0x6FFC0000,0x6FFC0000,0x6FFC0000,0x6FFC0000,0xB9F80000,0xB9F80000,0xB9F80000,0xCE000000,0xB9F80000,0xB9F80000,0xB9F80000,0xCE000000,0xCE000000,0x5B80000,0x19C0001,0x19C0001,0x3E00000,0x15FC0000,0x4DFC0000,0x4DFC0000,0x8BFC0000,0x3E00000,0x15FC0000,0xA5FC0000,0xB9F80000,
+0xA5FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1B01CB4,0xFFA4190F,0xFF9C1633,0xFF98152B,0xFF98140A,0xFF8C0FFF,0xFF800E56,0xFF700A74,0xFF700863,0xFF640622,0xFF8C144D,0xFF740F22,0xFF680D11,0xFF5807AB,0xFF4C04BA,0xFF44013D,0xFF4C08DC,0xFF380519,0xFB28008D,0xEF2C0601,0x8DFC1CB0,0xFF701751,0xFF68152C,0xFF4C0EB2,0xFF380AC2,0xFF1C0620,0xFF200DF9,0xFEFC0829,0xFECC0005,0xEED80600,0xC7FC1CB0,
+0xFEC8152B,0xFE2C0620,0xEC00064C,0xD8001CB0,0xFFA0185A,0xFFAC1AFA,0xFFAC1BE7,0xFF9413DF,0xFF780E8B,0xFF680924,0xFF5C06CB,0xFF400302,0xFF98183A,0xFF801312,0xFF3C08BF,0xFECC0005,0xB9FC1CB0,0x1DC0603,0xFFD40556,0xFFCC04C2,0xFFCC0482,0xFFD00433,0xFFC40336,0xFFBC02C5,0xFFAC0183,0xFFAC00DA,0xFF9C0001,0xCFFC0600,0xFFC004F6,0xFFB80480,0xFFA002C2,0xFF8801A9,
+0xFF700000,0xE7FC0600,0xFF6C0480,0xFED80000,0xEE000600,0xCFFC0600,0xFFC004F6,0xFFB80480,0xFFA002C2,0xFF8801A9,0xFF700000,0xE7FC0600,0xFF6C0480,0xFED80000,0xEE000600,0xE7FC0600,0xFF6C0480,0xFED80000,0xEE000600,0xEE000600,0xFFD80565,0xF7DC05C1,0xF7DC05E2,0xFFC404EB,0xFFC003FE,0xFFA802E1,0xFFA00212,0xFF7C0172,0xFFD00575,0xFFC804AC,0xFF980489,0xFED80000,
+0xE1FC0600,0x198152B,0x198152B,0x198152B,0x198152B,0xFF800E56,0xFF800E56,0xFF800E56,0xFF700863,0xFF700863,0xFF640622,0xFF680D11,0xFF680D11,0xFF680D11,0xFF4C04BA,0xFF4C04BA,0xFF44013D,0xFF380519,0xFF380519,0xF924007D,0xE72C0481,0x65FC152B,0x65FC152B,0x65FC152B,0xFF380AC2,0xFF380AC2,0xFF1C0620,0xFEFC0829,0xFEFC0829,0xFECC0005,0xE6E00480,0xB3FC152B,
+0xB3FC152B,0xFE2C0620,0xE6000490,0xCC00152C,0xFF901212,0xFF8C13EB,0x198152B,0xFF800EF9,0xFF6C0B5E,0xFF5C082E,0xFF5C06CB,0xFF400302,0xFF8011D1,0xFF740E66,0xFF3C089B,0xFECC0005,0x9FFC152B,0x1CC0482,0x1CC0482,0x1CC0482,0x1CC0482,0xFFBC02C5,0xFFBC02C5,0xFFBC02C5,0xFFAC00DA,0xFFAC00DA,0xFF9C0001,0xB7FC0480,0xB7FC0480,0xB7FC0480,0xFF8801A9,0xFF8801A9,
+0xFF700000,0xDDF40480,0xDDF40480,0xFED80000,0xE6000480,0xB7FC0480,0xB7FC0480,0xB7FC0480,0xFF8801A9,0xFF8801A9,0xFF700000,0xDDF40480,0xDDF40480,0xFED80000,0xE6000480,0xDDF40480,0xDDF40480,0xFED80000,0xE6000480,0xE6000480,0xFDC80422,0xFFCC0422,0x1CC0482,0xFDC003CA,0xFFAC0321,0xFFA0028D,0xFFA00212,0xFF7C0172,0xFFC40422,0xFFB003C5,0xD3FC0480,0xFED80000,
+0xD3FC0480,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1640622,0x1640622,0x1640622,0x1640622,0x1640622,0x1640622,0x1640622,0x1640622,0x1640622,0x1640622,0xFF44013D,0xFF44013D,0xFF44013D,0xFF44013D,0xFF44013D,
+0xFF44013D,0xEB2C0001,0xEB2C0001,0xEB2C0001,0xCF2C0001,0x19FC0620,0x19FC0620,0x19FC0620,0x19FC0620,0x19FC0620,0x19FC0620,0xFECC0005,0xFECC0005,0xFECC0005,0xCEF80000,0x8FF80620,0x8FF80620,0x8FF80620,0xCE480000,0xB2000620,0xF9600515,0x1640622,0x1640622,0xFF5803CA,0xFF5002DA,0xFF4C0202,0xFF4C0202,0xFF400091,0xFD5404B1,0xFF50039D,0xFF24000D,0xFECC0005,
+0x71FC0620,};
+static const uint32_t g_etc1_to_bc7_m6_table189[] = {
+0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x71F80000,
+0x71F80000,0x71F80000,0x71F80000,0x9E000000,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x1540000,0x1540000,0x1540000,0x1D80000,0x4BFC0000,0x1AC0001,0x1AC0001,0x1AC0001,0x1AC0001,0x1AC0001,0x1AC0001,0x1AC0001,0x1AC0001,0x1AC0001,0x1AC0001,0x87FC0000,0x87FC0000,0x87FC0000,0x87FC0000,0x87FC0000,
+0x87FC0000,0xC5F80000,0xC5F80000,0xC5F80000,0xD6000000,0x87FC0000,0x87FC0000,0x87FC0000,0x87FC0000,0x87FC0000,0x87FC0000,0xC5F80000,0xC5F80000,0xC5F80000,0xD6000000,0xC5F80000,0xC5F80000,0xC5F80000,0xD6000000,0xD6000000,0xDC80000,0x1AC0001,0x1AC0001,0x1F40000,0x3DFC0000,0x6BFC0000,0x6BFC0000,0x9DFC0000,0x1F40000,0x3DFC0000,0xB5FC0000,0xC5F80000,
+0xB5FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1B81834,0xFFB01547,0xFFA812FF,0xFFA4122B,0xFFA4114A,0xFF980E07,0xFF8C0CB6,0xFF880994,0xFF7C07EB,0xFF740622,0xFF981115,0xFF800CE2,0xFF800B29,0xFF7006D3,0xFF64046A,0xFF500195,0xFF580704,0xFF4C03F3,0xFD380035,0xF13C042D,0x99FC1830,0xFF7C13E9,0xFF78122B,0xFF580CF2,0xFF4C09E9,0xFF340620,0xFF380B89,0xFF1406C9,0xFEE40025,0xF0EC042D,0xCDFC1830,
+0xFEEC122B,0xFE600620,0xF0000435,0xDC001830,0xFFA814D6,0xFFAC171A,0xF5B817AC,0xFF9810D6,0xFF880C93,0xFF700806,0xFF68061E,0xFF5802DE,0xFFA014B2,0xFF901042,0xFF58074F,0xFEE40025,0xBFFC1830,0x1E4042B,0xFFDC03AB,0xFFD80346,0xFFD40322,0xFFD002E3,0xFFC8023E,0xFFC401E2,0xFFB8010B,0xFFB80092,0xFFAC0001,0xD9FC042B,0xFFCC0372,0xFFC00322,0xFFAC01E2,0xFFA00121,
+0xFF880000,0xEDF8042B,0xFF840320,0xFF080000,0xF000042C,0xD9FC042B,0xFFCC0372,0xFFC00322,0xFFAC01E2,0xFFA00121,0xFF880000,0xEDF8042B,0xFF840320,0xFF080000,0xF000042C,0xEDF8042B,0xFF840320,0xFF080000,0xF000042C,0xF000042C,0xFFD803C5,0xF9E003F9,0xFBE40412,0xFFD40355,0xFFC802BD,0xFFB801F5,0xFFA80161,0xFF8C0105,0xFFDC03C5,0xFFC8034C,0xFFA80329,0xFF080000,
+0xE7FC042B,0x1A4122B,0x1A4122B,0x1A4122B,0x1A4122B,0xFF8C0CB6,0xFF8C0CB6,0xFF8C0CB6,0xFF7C07EB,0xFF7C07EB,0xFF740622,0xFF800B29,0xFF800B29,0xFF800B29,0xFF64046A,0xFF64046A,0xFF500195,0xFF4C03F3,0xFF4C03F3,0xFB3C002A,0xEB3C0321,0x77FC122B,0x77FC122B,0x77FC122B,0xFF4C09E9,0xFF4C09E9,0xFF340620,0xFF1406C9,0xFF1406C9,0xFEE40025,0xEAF40320,0xBDF8122B,
+0xBDF8122B,0xFE600620,0xEA040320,0xD000122C,0xFD9C0FA9,0xF9A01122,0x1A4122B,0xFF900D02,0xFF8009FE,0xFF700742,0xFF68061E,0xFF5802DE,0xFF940F4C,0xFF800CA1,0xFF580736,0xFEE40025,0xABFC122B,0x1D40322,0x1D40322,0x1D40322,0x1D40322,0xFFC401E2,0xFFC401E2,0xFFC401E2,0xFFB80092,0xFFB80092,0xFFAC0001,0xC3FC0320,0xC3FC0320,0xC3FC0320,0xFFA00121,0xFFA00121,
+0xFF880000,0xE1FC0320,0xE1FC0320,0xFF080000,0xEA000320,0xC3FC0320,0xC3FC0320,0xC3FC0320,0xFFA00121,0xFFA00121,0xFF880000,0xE1FC0320,0xE1FC0320,0xFF080000,0xEA000320,0xE1FC0320,0xE1FC0320,0xFF080000,0xEA000320,0xEA000320,0xFBD002D4,0xFFCC02F2,0x1D40322,0xFFC4029A,0xFFC00225,0xFFB001BD,0xFFA80161,0xFF8C0105,0xFDCC02D4,0xFFC80288,0xDBFC0320,0xFF080000,
+0xDBFC0320,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1740622,0x1740622,0x1740622,0x1740622,0x1740622,0x1740622,0x1740622,0x1740622,0x1740622,0x1740622,0xFF500195,0xFF500195,0xFF500195,0xFF500195,0xFF500195,
+0xFF500195,0xF33C0001,0xF33C0001,0xF33C0001,0xD73C0001,0x31FC0620,0x31FC0620,0x31FC0620,0x31FC0620,0x31FC0620,0x31FC0620,0xFEE40025,0xFEE40025,0xFEE40025,0xD7080000,0x9BF80620,0x9BF80620,0x9BF80620,0xD6580000,0xBA000620,0xFF6C0521,0x1740622,0x1740622,0xFF6803F9,0xFF640322,0xFF5C024A,0xFF5C024A,0xFF4C00DA,0xF96804E2,0xFF5803E8,0xFF38002D,0xFEE40025,
+0x7FFC0620,};
+static const uint32_t g_etc1_to_bc7_m6_table190[] = {
+0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x7DF80000,
+0x7DF80000,0x7DF80000,0x7DF80000,0xA6000000,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x1640000,0x1640000,0x1640000,0x1F00000,0x5BFC0000,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x1BC0001,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,
+0x9FFC0000,0xD1F80000,0xD1F80000,0xD1F80000,0xDE000000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0x9FFC0000,0xD1F80000,0xD1F80000,0xD1F80000,0xDE000000,0xD1F80000,0xD1F80000,0xD1F80000,0xDE000000,0xDE000000,0x1DC0000,0x1BC0001,0x1BC0001,0x1FFC0000,0x63FC0000,0x89FC0000,0x89FC0000,0xB1FC0000,0x1FFC0000,0x63FC0000,0xC3FC0000,0xD1F80000,
+0xC3FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1C01434,0xFFBC11F7,0xFFB4102B,0xFFAC0F83,0xFFB00EDA,0xFFA40C47,0xFF980B46,0xFF9408C4,0xFF88078B,0xFF840622,0xFFA40E45,0xFF8C0AF2,0xFF8C0989,0xFF7C0613,0xFF700432,0xFF6801ED,0xFF64058C,0xFF58030B,0xFD4C000A,0xF54C02AD,0xA5FC1430,0xFF9410D1,0xFF880F80,0xFF700B62,0xFF640911,0xFF4C0620,0xFF4C09AB,0xFF2C05A9,0xFF080059,0xF50002AD,0xD3FC1430,
+0xFF080F80,0xFE900620,0xF40C02AC,0xE0001430,0xFFB4117B,0xF9C01344,0xF9C013BC,0xFFAC0E6E,0xFF940AD2,0xFF7C073E,0xFF7805B3,0xFF6C02C3,0xFFB4111B,0xFF980DEE,0xFF70060B,0xFF080059,0xC7FC1430,0x1E802AB,0xFDE40263,0xFFE0021B,0xFFDC0202,0xFFDC01D3,0xFFD4016E,0xFFD00132,0xFFCC00B1,0xFFC00065,0xFFBC0001,0xDFFC02AB,0xFFD80236,0xFFCC0202,0xFFB80132,0xFFAC00B9,
+0xFFA00000,0xEFFC02AB,0xFF9C0200,0xFF380000,0xF40002AC,0xDFFC02AB,0xFFD80236,0xFFCC0202,0xFFB80132,0xFFAC00B9,0xFFA00000,0xEFFC02AB,0xFF9C0200,0xFF380000,0xF40002AC,0xEFFC02AB,0xFF9C0200,0xFF380000,0xF40002AC,0xF40002AC,0xFFE4026D,0xFDE80281,0xFDE80296,0xFFDC0215,0xFFD401C2,0xFFBC0152,0xFFB800E8,0xFFA8009D,0xFFE00272,0xFFDC020E,0xFFB80204,0xFF380000,
+0xEBFC02AB,0x1AC0F83,0x1AC0F83,0x1AC0F83,0x1AC0F83,0xFF980B46,0xFF980B46,0xFF980B46,0xFF88078B,0xFF88078B,0xFF840622,0xFF8C0989,0xFF8C0989,0xFF8C0989,0xFF700432,0xFF700432,0xFF6801ED,0xFF58030B,0xFF58030B,0xFD4C0006,0xEF4C0201,0x87FC0F80,0x87FC0F80,0x87FC0F80,0xFF640911,0xFF640911,0xFF4C0620,0xFF2C05A9,0xFF2C05A9,0xFF080059,0xEF080200,0xC5F80F80,
+0xC5F80F80,0xFE900620,0xEE280200,0xD6000F80,0xFFA00D61,0xFFAC0E96,0x1AC0F83,0xFF980B42,0xFF8C08EE,0xFF7C0695,0xFF7805B3,0xFF6C02C3,0xFFA00D29,0xFF900AF9,0xFF7005FB,0xFF080059,0xB5FC0F80,0x1DC0202,0x1DC0202,0x1DC0202,0x1DC0202,0xFFD00132,0xFFD00132,0xFFD00132,0xFFC00065,0xFFC00065,0xFFBC0001,0xCFFC0200,0xCFFC0200,0xCFFC0200,0xFFAC00B9,0xFFAC00B9,
+0xFFA00000,0xE7FC0200,0xE7FC0200,0xFF380000,0xEE000200,0xCFFC0200,0xCFFC0200,0xCFFC0200,0xFFAC00B9,0xFFAC00B9,0xFFA00000,0xE7FC0200,0xE7FC0200,0xFF380000,0xEE000200,0xE7FC0200,0xE7FC0200,0xFF380000,0xEE000200,0xEE000200,0xFFD801C4,0xF7DC01E1,0x1DC0202,0xFDD801A5,0xFFC80164,0xFFBC0121,0xFFB800E8,0xFFA8009D,0xFFD001D4,0xFBD401A5,0xE1FC0200,0xFF380000,
+0xE1FC0200,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1840622,0x1840622,0x1840622,0x1840622,0x1840622,0x1840622,0x1840622,0x1840622,0x1840622,0x1840622,0xFF6801ED,0xFF6801ED,0xFF6801ED,0xFF6801ED,0xFF6801ED,
+0xFF6801ED,0xFB4C0001,0xFB4C0001,0xFB4C0001,0xDF4C0001,0x49FC0620,0x49FC0620,0x49FC0620,0x49FC0620,0x49FC0620,0x49FC0620,0xFF080059,0xFF080059,0xFF080059,0xDF180000,0xA7F80620,0xA7F80620,0xA7F80620,0xDE680000,0xC2000620,0xF980054A,0x1840622,0x1840622,0xFF740442,0xFF780372,0xFF7002B1,0xFF7002B1,0xFF5C0131,0xFF7404EA,0xFD740422,0xFF500075,0xFF080059,
+0x8FFC0620,};
+static const uint32_t g_etc1_to_bc7_m6_table191[] = {
+0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0x89F80000,
+0x89F80000,0x89F80000,0x89F80000,0xAE000000,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x3740000,0x3740000,0x3740000,0xDFC0000,0x69FC0000,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,
+0xB7FC0000,0xDDF40000,0xDDF40000,0xDDF40000,0xE6000000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xDDF40000,0xDDF40000,0xDDF40000,0xE6000000,0xDDF40000,0xDDF40000,0xDDF40000,0xE6000000,0xE6000000,0x1EC0000,0x1CC0001,0x1CC0001,0x57FC0000,0x8BFC0000,0xA7FC0000,0xA7FC0000,0xC5FC0000,0x57FC0000,0x8BFC0000,0xD3FC0000,0xDDF40000,
+0xD3FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1C810B4,0xFFC40EF4,0xFFB80DA4,0xFFB80D2B,0xFFB00CBA,0xFFB00ABF,0xFFA40A06,0xFFA00814,0xFF9C0732,0xFF940622,0xFFB00BDD,0xFF980952,0xFF980831,0xFF88058B,0xFF84041A,0xFF74025D,0xFF7C045C,0xFF700263,0xFF600005,0xF75C0181,0xB1FC10B0,0xFFA00E21,0xFF980D2C,0xFF7C0A12,0xFF700851,0xFF640620,0xFF6407F3,0xFF3804E9,0xFF2000A9,0xF7180180,0xD9FC10B0,
+0xFF280D2B,0xFEC00620,0xF6380180,0xE40010B0,0xFFBC0E86,0xFDC80FE4,0xFDC8104C,0xFFAC0C2E,0xFFA00963,0xFF90068E,0xFF900555,0xFF7402DE,0xFFB40E4B,0xFFB00BC7,0xFF7C0521,0xFF2000A9,0xCFFC10B0,0x1EC0183,0xFFE80153,0xFFE40132,0xFFE40122,0xFFE8010B,0xFFDC00CE,0xFFDC00AA,0xFFD80061,0xFFD4003A,0xFFCC0001,0xE9FC0180,0xFFE00141,0xFFD80122,0xFFCC00B1,0xFFC0006D,
+0xFFB80000,0xF3FC0180,0xFFB40120,0xFF6C0000,0xF6000180,0xE9FC0180,0xFFE00141,0xFFD80122,0xFFCC00B1,0xFFC0006D,0xFFB80000,0xF3FC0180,0xFFB40120,0xFF6C0000,0xF6000180,0xF3FC0180,0xFFB40120,0xFF6C0000,0xF6000180,0xF6000180,0xFBEC0161,0xFFEC0161,0xFFEC0172,0xFFE00143,0xFFDC00F9,0xFFD000C3,0xFFD00082,0xFFB8005A,0xF9EC0161,0xFFDC012E,0xFFD00123,0xFF6C0000,
+0xF1FC0180,0x1B80D2B,0x1B80D2B,0x1B80D2B,0x1B80D2B,0xFFA40A06,0xFFA40A06,0xFFA40A06,0xFF9C0732,0xFF9C0732,0xFF940622,0xFF980831,0xFF980831,0xFF980831,0xFF84041A,0xFF84041A,0xFF74025D,0xFF700263,0xFF700263,0xFF600005,0xF35C0121,0x95FC0D2B,0x95FC0D2B,0x95FC0D2B,0xFF700851,0xFF700851,0xFF640620,0xFF3804E9,0xFF3804E9,0xFF2000A9,0xF31C0120,0xCBFC0D2B,
+0xCBFC0D2B,0xFEC00620,0xF2480120,0xDC000D2C,0xFFAC0B7E,0xF5B80CA3,0x1B80D2B,0xFFA409EB,0xFF9407DE,0xFF900615,0xFF900555,0xFF7402DE,0xFDB00B5E,0xFF9809A5,0xFF7C0511,0xFF2000A9,0xBFF80D2B,0x1E40122,0x1E40122,0x1E40122,0x1E40122,0xFFDC00AA,0xFFDC00AA,0xFFDC00AA,0xFFD4003A,0xFFD4003A,0xFFCC0001,0xDBFC0120,0xDBFC0120,0xDBFC0120,0xFFC0006D,0xFFC0006D,
+0xFFB80000,0xEDFC0120,0xEDFC0120,0xFF6C0000,0xF2000120,0xDBFC0120,0xDBFC0120,0xDBFC0120,0xFFC0006D,0xFFC0006D,0xFFB80000,0xEDFC0120,0xEDFC0120,0xFF6C0000,0xF2000120,0xEDFC0120,0xEDFC0120,0xFF6C0000,0xF2000120,0xF2000120,0xF7E40109,0xFBE40109,0x1E40122,0xFFDC00E1,0xFFD400C1,0xFFD000AA,0xFFD00082,0xFFB8005A,0xF5E40109,0xFFDC00DD,0xE9FC0120,0xFF6C0000,
+0xE9FC0120,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1940622,0x1940622,0x1940622,0x1940622,0x1940622,0x1940622,0x1940622,0x1940622,0x1940622,0x1940622,0xFF74025D,0xFF74025D,0xFF74025D,0xFF74025D,0xFF74025D,
+0xFF74025D,0xFF600005,0xFF600005,0xFF600005,0xE75C0001,0x63FC0620,0x63FC0620,0x63FC0620,0x63FC0620,0x63FC0620,0x63FC0620,0xFF2000A9,0xFF2000A9,0xFF2000A9,0xE7280000,0xB3F80620,0xB3F80620,0xB3F80620,0xE6780000,0xCA000620,0xFF8C055A,0x1940622,0x1940622,0xFF840479,0xFF8003C5,0xFF800305,0xFF800305,0xFF700195,0xFD8C0515,0xFF80045D,0xFF6000CD,0xFF2000A9,
+0x9FF80620,};
+static const uint32_t g_etc1_to_bc7_m6_table192[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x400001,0x400001,0x400001,0x400001,0x600000,0x600000,0x600000,0xC40000,0xC40000,0x20000000,0x600000,0x600000,0x600000,0xC40000,0xC40000,0x20000000,0xC40000,0xC40000,0x20000000,0x20000000,0x600000,0x600000,0x600000,0xC40000,0xC40000,0x20000000,0xC40000,0xC40000,0x20000000,0x20000000,0xC40000,
+0xC40000,0x20000000,0x20000000,0x20000000,0x4C0000,0xA440000,0x400001,0x580000,0x26C0000,0x8C0000,0xA00000,0xF00000,0x4500000,0x600000,0x8C0000,0x20000000,0x8C0000,0xD40000,0x13C0000,0x21FC0000,0x68000001,0x13C0000,0x21FC0000,0x68000001,0x21FC0000,0x68000001,0x68000001,0x13C0000,0x21FC0000,0x68000001,0x21FC0000,0x68000001,
+0x68000001,0x21FC0000,0x68000001,0x68000001,0x68000001,0x13C0000,0x21FC0000,0x68000001,0x21FC0000,0x68000001,0x68000001,0x21FC0000,0x68000001,0x68000001,0x68000001,0x21FC0000,0x68000001,0x68000001,0x68000001,0x68000001,0x3080000,0x8E00000,0x8E00000,0x1640000,0x5FC0000,0x45F40000,0x68000001,0x68000001,0x1200000,0x18C0000,0x61D40000,0x68000001,
+0x1C00000,0x441D49,0xFE1C039A,0x981402D9,0x681402DA,0xD0000A69,0x92000112,0x68000002,0x66000A69,0x560003DA,0x44000A69,0x8A0016FD,0x7A000882,0x62000432,0x58000E66,0x520006FB,0x40000C4A,0x440016FD,0x44000E46,0x38001145,0x2E0016FE,0x681D47,0x68000DD2,0x580007C3,0x52001187,0x4C000994,0x40000E03,0x400018C6,0x3E001027,0x360012AA,0x2E0017DF,0xD01D47,
+0x380014C2,0x3200161D,0x26001A42,0x22001D47,0xFE140B92,0xF4381671,0xF8401611,0xC80006E0,0x8A000732,0x660006FD,0x5A0004DA,0x4A000929,0xF2000CF6,0x9E00098E,0x52000B32,0x360012AA,0x941D47,0x5C16FD,0xFE240289,0x94200222,0x68200222,0xD0000A69,0x92000112,0x68000002,0x66000A69,0x560003DA,0x44000A69,0x8816FD,0x7A000882,0x62000432,0x58000E66,0x520006FB,
+0x40000C4A,0x11416FD,0x44000E46,0x38001145,0x2E0016FE,0x8816FD,0x7A000882,0x62000432,0x58000E66,0x520006FB,0x40000C4A,0x11416FD,0x44000E46,0x38001145,0x2E0016FE,0x11416FD,0x44000E46,0x38001145,0x2E0016FE,0x2E0016FE,0xFE140B2E,0xFC481271,0xFE4C1121,0xC80006E0,0x8A000732,0x660006FD,0x5A0004DA,0x4A000929,0xFA000BFE,0x9E00092A,0x52000B19,0x38001145,
+0xC016FD,0x1402D9,0x1402D9,0x1402D9,0x1402D9,0x64000000,0x64000000,0x64000000,0x30000000,0x30000000,0x20000000,0x30000221,0x30000221,0x30000221,0x280000C2,0x280000C2,0x1E000068,0x18000221,0x18000221,0x16000145,0x10000221,0x2002D6,0x2002D6,0x2002D6,0x22000143,0x22000143,0x180000C0,0x1200025D,0x1200025D,0x14000185,0xE00023E,0x3C02D6,
+0x3C02D6,0x100001F2,0xE000289,0xA0002D6,0xC40000A9,0xFE0C00C1,0x1402D9,0x640000E8,0x3C0000D0,0x2E0000D0,0x2E0000A9,0x220000F5,0x64000178,0x44000138,0x1E000225,0x14000185,0x2C02D6,0x200221,0x200221,0x200221,0x200221,0x64000000,0x64000000,0x64000000,0x30000000,0x30000000,0x20000000,0x300221,0x300221,0x300221,0x280000C2,0x280000C2,
+0x1E000068,0x5C0221,0x5C0221,0x16000145,0x10000221,0x300221,0x300221,0x300221,0x280000C2,0x280000C2,0x1E000068,0x5C0221,0x5C0221,0x16000145,0x10000221,0x5C0221,0x5C0221,0x16000145,0x10000221,0x10000221,0xC40000A9,0xFE0C009D,0x200221,0x640000E8,0x3C0000D0,0x2E0000D0,0x2E0000A9,0x220000F5,0x74000151,0x4A000121,0x400221,0x16000145,
+0x400221,0x8C0A69,0xFC440001,0x8C440001,0x68400002,0xCC0A69,0x92000112,0x68000002,0x1A00A69,0x560003DA,0x44000A69,0xCC0A69,0x92000112,0x68000002,0x1A00A69,0x560003DA,0x44000A69,0x1A00A69,0x560003DA,0x44000A69,0x44000A69,0xCC0A69,0x92000112,0x68000002,0x1A00A69,0x560003DA,0x44000A69,0x1A00A69,0x560003DA,0x44000A69,0x44000A69,0x1A00A69,
+0x560003DA,0x44000A69,0x44000A69,0x44000A69,0xFE3406B2,0x940A69,0xF8800745,0xDE000385,0x96000410,0x720003D4,0x5E00028A,0x54000502,0xFE180659,0xBA000454,0x64000232,0x44000A69,0x1240A69,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table193[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x500001,0x500001,0x500001,0x500001,0x780000,0x780000,0x780000,0xF40000,0xF40000,0x28000000,0x780000,0x780000,0x780000,0xF40000,0xF40000,0x28000000,0xF40000,0xF40000,0x28000000,0x28000000,0x780000,0x780000,0x780000,0xF40000,0xF40000,0x28000000,0xF40000,0xF40000,0x28000000,0x28000000,0xF40000,
+0xF40000,0x28000000,0x28000000,0x28000000,0x600000,0x580000,0x500001,0x700000,0x880000,0xAC0000,0xC80000,0x12C0000,0x4640000,0x780000,0xAC0000,0x28000000,0xAC0000,0xE40000,0x3500000,0x2DFC0000,0x70000001,0x3500000,0x2DFC0000,0x70000001,0x2DFC0000,0x70000001,0x70000001,0x3500000,0x2DFC0000,0x70000001,0x2DFC0000,0x70000001,
+0x70000001,0x2DFC0000,0x70000001,0x70000001,0x70000001,0x3500000,0x2DFC0000,0x70000001,0x2DFC0000,0x70000001,0x70000001,0x2DFC0000,0x70000001,0x70000001,0x70000001,0x2DFC0000,0x70000001,0x70000001,0x70000001,0x70000001,0x31C0000,0xF40000,0xF40000,0x1800000,0x13F80000,0x4FF40000,0x70000001,0x70000001,0x3340000,0x1AC0000,0x69E40000,0x70000001,
+0x1E40000,0x4C21E1,0xFE2405DD,0xA21C0461,0x701C0462,0xEA000A69,0xA20000A0,0x7200000A,0x72000A69,0x60000361,0x4C000A69,0x9C001A0D,0x860009AA,0x68000506,0x68000F41,0x58000723,0x46000CCE,0x4C001A0D,0x4A001006,0x3E0012F1,0x32001A0E,0x7421DF,0x7400101A,0x62000932,0x62001345,0x52000A54,0x46000EDF,0x46001C46,0x44001257,0x3C0014AA,0x30001B22,0xE821DF,
+0x3E0017F2,0x320018ED,0x2C001E16,0x260021DF,0xFE140E42,0xF8401A29,0xFC481A39,0xDE000716,0x9A000789,0x7000072D,0x5E0004BB,0x560009B3,0xFE000ECD,0xB6000A4B,0x56000C76,0x3C0014AA,0xA421DF,0x681A0D,0xFE300425,0x9E28034A,0x7028034A,0xEA000A69,0xA20000A0,0x72040009,0x72000A69,0x60000361,0x4C000A69,0x2981A0D,0x860009AA,0x68000506,0x68000F41,0x58000723,
+0x46000CCE,0x1381A0D,0x4A001006,0x3E0012F1,0x32001A0E,0x2981A0D,0x860009AA,0x68000506,0x68000F41,0x58000723,0x46000CCE,0x1381A0D,0x4A001006,0x3E0012F1,0x32001A0E,0x1381A0D,0x4A001006,0x3E0012F1,0x32001A0E,0x32001A0E,0xFE200D73,0xFE4C1521,0xF860142A,0xDE000716,0x9A000789,0x7000072D,0x5E0004BB,0x560009B3,0xFE000DCD,0xBC0009CE,0x56000C5D,0x3E0012F1,
+0xDC1A0D,0x1C0461,0x1C0461,0x1C0461,0x1C0461,0x7C000000,0x7C000000,0x7C000000,0x3C000000,0x3C000000,0x28000000,0x3C000349,0x3C000349,0x3C000349,0x2E000132,0x2E000132,0x2200009D,0x1E000349,0x1E000349,0x1C0001F9,0x14000349,0x280461,0x280461,0x280461,0x280001FB,0x280001FB,0x22000116,0x180003A1,0x180003A1,0x1A000259,0x12000371,0x500461,
+0x500461,0x16000306,0x100003DA,0xC000462,0xF6000105,0xFE0C01B1,0x1C0461,0x7A000161,0x50000140,0x40000145,0x38000112,0x2A000172,0x82000248,0x500001DD,0x2400034D,0x1A000259,0x380461,0x280349,0x280349,0x280349,0x280349,0x7C000000,0x7C000000,0x7C000000,0x3C000000,0x3C000000,0x28000000,0x3C0349,0x3C0349,0x3C0349,0x2E000132,0x2E000132,
+0x2200009D,0x740349,0x740349,0x1C0001F9,0x14000349,0x3C0349,0x3C0349,0x3C0349,0x2E000132,0x2E000132,0x2200009D,0x740349,0x740349,0x1C0001F9,0x14000349,0x740349,0x740349,0x1C0001F9,0x14000349,0x14000349,0xF6000105,0xF4180154,0x280349,0x7A000161,0x50000140,0x40000145,0x38000112,0x2A000172,0x82000208,0x5A0001BD,0x540349,0x1C0001F9,
+0x540349,0x9C0A69,0xFE540005,0x94540001,0x70500002,0xE40A69,0xA20000A0,0x700C0001,0x1D00A69,0x60000361,0x4C000A69,0xE40A69,0xA20000A0,0x700C0001,0x1D00A69,0x60000361,0x4C000A69,0x1D00A69,0x60000361,0x4C000A69,0x4C000A69,0xE40A69,0xA20000A0,0x700C0001,0x1D00A69,0x60000361,0x4C000A69,0x1D00A69,0x60000361,0x4C000A69,0x4C000A69,0x1D00A69,
+0x60000361,0x4C000A69,0x4C000A69,0x4C000A69,0xFE5006CD,0xA40A69,0xFE8C0749,0xF4000304,0xA0000384,0x7C000335,0x66000209,0x5C000492,0xFE2C0694,0xCC0003E8,0x6E0001A8,0x4C000A69,0x1480A69,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table194[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x600001,0x600001,0x600001,0x600001,0x900000,0x900000,0x900000,0x1240000,0x1240000,0x30000000,0x900000,0x900000,0x900000,0x1240000,0x1240000,0x30000000,0x1240000,0x1240000,0x30000000,0x30000000,0x900000,0x900000,0x900000,0x1240000,0x1240000,0x30000000,0x1240000,0x1240000,0x30000000,0x30000000,0x1240000,
+0x1240000,0x30000000,0x30000000,0x30000000,0x2700000,0x680000,0x600001,0x840000,0xA40000,0xD00000,0xEC0000,0x1680000,0x4780000,0x900000,0xD00000,0x30000000,0xD00000,0xF40000,0x3680000,0x39FC0000,0x78000001,0x3680000,0x39FC0000,0x78000001,0x39FC0000,0x78000001,0x78000001,0x3680000,0x39FC0000,0x78000001,0x39FC0000,0x78000001,
+0x78000001,0x39FC0000,0x78000001,0x78000001,0x78000001,0x3680000,0x39FC0000,0x78000001,0x39FC0000,0x78000001,0x78000001,0x39FC0000,0x78000001,0x78000001,0x78000001,0x39FC0000,0x78000001,0x78000001,0x78000001,0x78000001,0x3300000,0x1040000,0x1040000,0x1980000,0x1FFC0000,0x59F40000,0x78000001,0x78000001,0x14C0000,0x1C80000,0x71F40000,0x78000001,
+0x5FC0000,0x5426F9,0xFE3008D5,0xAC200642,0x78200642,0xFE000A6D,0xAE000050,0x7A04003A,0x7E000A69,0x6C0002E9,0x54000A69,0xAC001D72,0x92000B12,0x6E000632,0x6E001055,0x62000755,0x52000D4E,0x54001D72,0x5000120E,0x440014CD,0x38001D72,0x8026F7,0x7A0012C2,0x68000B0A,0x62001515,0x5E000B3C,0x4C000FDB,0x4C00202E,0x4A0014D7,0x440016DE,0x36001EC2,0x10026F7,
+0x44001B8A,0x38001C09,0x32002262,0x2A0026F7,0xFE201173,0xFC481E61,0xFE4C1EE5,0xF4000768,0xA20007D3,0x7C000746,0x660004D2,0x60000A46,0xFE00117D,0xC6000B19,0x5E000E2A,0x440016DE,0xB426F7,0x701D75,0xFE3C0631,0xA83004B2,0x783004B2,0xFE000A6D,0xAE000050,0x7C080032,0x7E000A69,0x6C0002E9,0x54000A69,0xA81D72,0x92000B12,0x6E000632,0x6E001055,0x62000755,
+0x52000D4E,0x1581D72,0x5000120E,0x440014CD,0x38001D72,0xA81D72,0x92000B12,0x6E000632,0x6E001055,0x62000755,0x52000D4E,0x1581D72,0x5000120E,0x440014CD,0x38001D72,0x1581D72,0x5000120E,0x440014CD,0x38001D72,0x38001D72,0xFE340FF2,0xF8601819,0xFC68174A,0xF4000768,0xA20007D3,0x7C000746,0x660004D2,0x60000A46,0xFE08103E,0xC6000A89,0x5E000E06,0x440014CD,
+0xF01D72,0x200641,0x200641,0x200641,0x200641,0x94000000,0x94000000,0x94000000,0x48000000,0x48000000,0x30000000,0x480004B1,0x480004B1,0x480004B1,0x3A0001BA,0x3A0001BA,0x2E0000E5,0x220004B1,0x220004B1,0x200002E4,0x180004B1,0x300641,0x300641,0x300641,0x2E0002E3,0x2E0002E3,0x28000192,0x2200052A,0x2200052A,0x1C00035D,0x180004F1,0x5C0641,
+0x5C0641,0x1C000462,0x1400058D,0x10000642,0xF60001A5,0xF4180304,0x200641,0x900001F4,0x5E0001CD,0x480001CD,0x44000184,0x2E00022D,0x9600034E,0x720002BB,0x2C0004BA,0x1C00035D,0x400641,0x3004B1,0x3004B1,0x3004B1,0x3004B1,0x94000000,0x94000000,0x94000000,0x48000000,0x48000000,0x30000000,0x4804B1,0x4804B1,0x4804B1,0x3A0001BA,0x3A0001BA,
+0x2E0000E5,0x8C04B1,0x8C04B1,0x200002E4,0x180004B1,0x4804B1,0x4804B1,0x4804B1,0x3A0001BA,0x3A0001BA,0x2E0000E5,0x8C04B1,0x8C04B1,0x200002E4,0x180004B1,0x8C04B1,0x8C04B1,0x200002E4,0x180004B1,0x180004B1,0xF60001A5,0xF8200244,0x3004B1,0x900001F4,0x5E0001CD,0x480001CD,0x44000184,0x2E00022D,0xA40002F2,0x7200028A,0x6404B1,0x200002E4,
+0x6404B1,0xAC0A69,0xFE680012,0x9C640001,0x78600002,0xFC0A69,0xAE000050,0x781C0001,0x3F80A69,0x6C0002E9,0x54000A69,0xFC0A69,0xAE000050,0x781C0001,0x3F80A69,0x6C0002E9,0x54000A69,0x3F80A69,0x6C0002E9,0x54000A69,0x54000A69,0xFC0A69,0xAE000050,0x781C0001,0x3F80A69,0x6C0002E9,0x54000A69,0x3F80A69,0x6C0002E9,0x54000A69,0x54000A69,0x3F80A69,
+0x6C0002E9,0x54000A69,0x54000A69,0x54000A69,0xF6680708,0xB80A69,0xF8A00782,0xFC0002AD,0xB600031A,0x860002D5,0x70000195,0x6400042A,0xF44806CD,0xDE000361,0x76000128,0x54000A69,0x1680A69,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table195[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x700001,0x700001,0x700001,0x700001,0xA80000,0xA80000,0xA80000,0x1580000,0x1580000,0x38000000,0xA80000,0xA80000,0xA80000,0x1580000,0x1580000,0x38000000,0x1580000,0x1580000,0x38000000,0x38000000,0xA80000,0xA80000,0xA80000,0x1580000,0x1580000,0x38000000,0x1580000,0x1580000,0x38000000,0x38000000,0x1580000,
+0x1580000,0x38000000,0x38000000,0x38000000,0x840000,0x4780000,0x700001,0x2980000,0xC00000,0xF00000,0x1140000,0x1A40000,0x48C0000,0xA80000,0xF00000,0x38000000,0xF00000,0x1040000,0x3800000,0x45FC0000,0x80000001,0x3800000,0x45FC0000,0x80000001,0x45FC0000,0x80000001,0x80000001,0x3800000,0x45FC0000,0x80000001,0x45FC0000,0x80000001,
+0x80000001,0x45FC0000,0x80000001,0x80000001,0x80000001,0x3800000,0x45FC0000,0x80000001,0x45FC0000,0x80000001,0x80000001,0x45FC0000,0x80000001,0x80000001,0x80000001,0x45FC0000,0x80000001,0x80000001,0x80000001,0x80000001,0x3440000,0x3140000,0x3140000,0x1B40000,0x2DFC0000,0x63F40000,0x80000001,0x80000001,0x1600000,0x1E80000,0x7BC80000,0x80000001,
+0x15FC0000,0x5C2C91,0xFE300C45,0xB6280879,0x8024087A,0xFE0C0AED,0xBA000020,0x8208009A,0x8A000A69,0x72000271,0x5C000A69,0xBC00212D,0xA2000C99,0x7A000792,0x7A001185,0x680007B9,0x58000DDA,0x5C00212D,0x5600145E,0x4A0016D9,0x3E00212E,0x8C2C8F,0x860015BA,0x6E000D42,0x6E001735,0x62000C25,0x520010F7,0x5200247E,0x500017A7,0x4A00194A,0x3A0022B7,0x1182C8F,
+0x44001F8A,0x3E001F75,0x38002726,0x2E002C8F,0xFE28156D,0xFE4C2325,0xFE4C2475,0xFE00082D,0xB6000833,0x880007C9,0x740004FA,0x60000AF6,0xFE08151E,0xDA000C0E,0x6600103A,0x4A00194A,0xC82C8F,0x7C212D,0xFE4408A6,0xB238065A,0x8038065A,0xFE0C0AC9,0xBA000020,0x840C007E,0x8A000A69,0x72000271,0x5C000A69,0xB8212D,0xA2000C99,0x7A000792,0x7A001185,0x680007B9,
+0x58000DDA,0x174212D,0x5600145E,0x4A0016D9,0x3E00212E,0xB8212D,0xA2000C99,0x7A000792,0x7A001185,0x680007B9,0x58000DDA,0x174212D,0x5600145E,0x4A0016D9,0x3E00212E,0x174212D,0x5600145E,0x4A0016D9,0x3E00212E,0x3E00212E,0xFE3412F2,0xFE6C1B49,0xFE6C1AEE,0xFE00082D,0xB6000833,0x880007C9,0x740004FA,0x60000AF6,0xFE18134D,0xDA000B4A,0x66001016,0x4A0016D9,
+0x108212D,0x240879,0x240879,0x240879,0x240879,0xAC000000,0xAC000000,0xAC000000,0x54000000,0x54000000,0x38000000,0x54000659,0x54000659,0x54000659,0x40000262,0x40000262,0x34000131,0x28000659,0x28000659,0x260003E8,0x1C000659,0x380876,0x380876,0x380876,0x3A0003F3,0x3A0003F3,0x2E000226,0x220006FA,0x220006FA,0x24000491,0x1A0006AE,0x700876,
+0x700876,0x1C0005E2,0x16000776,0x12000876,0xFE0402B1,0xF61C0498,0x240879,0xAC0002B9,0x72000275,0x5600028A,0x4C000209,0x380002F2,0xB400047A,0x720003AB,0x34000662,0x24000491,0x500876,0x380659,0x380659,0x380659,0x380659,0xAC000000,0xAC000000,0xAC000000,0x54000000,0x54000000,0x38000000,0x540659,0x540659,0x540659,0x40000262,0x40000262,
+0x34000131,0xA40659,0xA40659,0x260003E8,0x1C000659,0x540659,0x540659,0x540659,0x40000262,0x40000262,0x34000131,0xA40659,0xA40659,0x260003E8,0x1C000659,0xA40659,0xA40659,0x260003E8,0x1C000659,0x1C000659,0xFA0802AD,0xFC280374,0x380659,0xAC0002B9,0x72000275,0x5600028A,0x4C000209,0x380002F2,0xC20003FA,0x7C000371,0x740659,0x260003E8,
+0x740659,0xBC0A69,0xFE78002D,0xA4740001,0x80700002,0x1140A69,0xBA000020,0x802C0001,0xFF80A69,0x72000271,0x5C000A69,0x1140A69,0xBA000020,0x802C0001,0xFF80A69,0x72000271,0x5C000A69,0xFF80A69,0x72000271,0x5C000A69,0x5C000A69,0x1140A69,0xBA000020,0x802C0001,0xFF80A69,0x72000271,0x5C000A69,0xFF80A69,0x72000271,0x5C000A69,0x5C000A69,0xFF80A69,
+0x72000271,0x5C000A69,0x5C000A69,0x5C000A69,0xFE780708,0xC80A69,0xFEAC078A,0xFE1402D4,0xC000029A,0x90000254,0x7A000131,0x720003BA,0xFC5806CD,0xF40002F2,0x820000DA,0x5C000A69,0x18C0A69,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table196[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x840000,0x840000,0x840000,0x840000,0xC40000,0xC40000,0xC40000,0x18C0000,0x18C0000,0x40000001,0xC40000,0xC40000,0xC40000,0x18C0000,0x18C0000,0x40000001,0x18C0000,0x18C0000,0x40000001,0x40000001,0xC40000,0xC40000,0xC40000,0x18C0000,0x18C0000,0x40000001,0x18C0000,0x18C0000,0x40000001,0x40000001,0x18C0000,
+0x18C0000,0x40000001,0x40000001,0x40000001,0x2980000,0x8C0000,0x840000,0xB40000,0xDC0000,0x1180000,0x1400000,0x1E80000,0xA40000,0xC40000,0x1180000,0x40000001,0x1180000,0x1140001,0x19C0000,0x53FC0000,0x8A000000,0x19C0000,0x53FC0000,0x8A000000,0x53FC0000,0x8A000000,0x8A000000,0x19C0000,0x53FC0000,0x8A000000,0x53FC0000,0x8A000000,
+0x8A000000,0x53FC0000,0x8A000000,0x8A000000,0x8A000000,0x19C0000,0x53FC0000,0x8A000000,0x53FC0000,0x8A000000,0x8A000000,0x53FC0000,0x8A000000,0x8A000000,0x8A000000,0x53FC0000,0x8A000000,0x8A000000,0x8A000000,0x8A000000,0x15C0000,0x1280000,0x1280000,0x1D40000,0x3DF80000,0x6FF00000,0x8A000000,0x8A000000,0x3780000,0x9FC0000,0x83F80000,0x8A000000,
+0x25FC0000,0x683375,0xFE3C10E1,0xC22C0B59,0x8A2C0B58,0xFE0C0C55,0xCC000002,0x8E080130,0x98000A69,0x7E0001F9,0x66000A69,0xCE0025C5,0xA8000EBB,0x86000984,0x86001301,0x74000831,0x62000E81,0x640025C5,0x5C001758,0x50001969,0x440025C6,0x983373,0x92001984,0x7A001024,0x7A0019E1,0x6E000D81,0x5E00125B,0x5E0029BE,0x5C001B19,0x50001C42,0x4000279F,0x1303373,
+0x5000247C,0x440023B5,0x38002CEA,0x32003373,0xFE341A28,0xFE4C299D,0xF8602B08,0xFE0009DD,0xC00008C1,0x92000865,0x7C000545,0x6C000BD8,0xFE081A0A,0xDE000D62,0x7400128E,0x50001C42,0xD83373,0x8825C5,0xFE500BF4,0xBE400884,0x8A400884,0xFE180BD5,0xCC000002,0x8E140104,0x98000A69,0x7E0001F9,0x66000A69,0xC825C5,0xA8000EBB,0x86000984,0x86001301,0x74000831,
+0x62000E81,0x19825C5,0x5C001758,0x50001969,0x440025C6,0xC825C5,0xA8000EBB,0x86000984,0x86001301,0x74000831,0x62000E81,0x19825C5,0x5C001758,0x50001969,0x440025C6,0x19825C5,0x5C001758,0x50001969,0x440025C6,0x440025C6,0xFE5016DA,0xFE6C1FA5,0xF8801F85,0xFE0009DD,0xC00008C1,0x92000865,0x7C000545,0x6C000BD8,0xFE24174D,0xE8000C89,0x7400125D,0x50001969,
+0x12025C5,0x2C0B58,0x2C0B58,0x2C0B58,0x2C0B58,0xC8000000,0xC8000000,0xC8000000,0x60000001,0x60000001,0x40000001,0x64000882,0x64000882,0x64000882,0x4C000335,0x4C000335,0x3A00019A,0x30000882,0x30000882,0x2C00053D,0x20000882,0x400B58,0x400B58,0x400B58,0x40000556,0x40000556,0x340002EB,0x2800095D,0x2800095D,0x2A00061E,0x1E0008EE,0x800B58,
+0x800B58,0x20000809,0x1C000A0B,0x14000B5B,0xFC0C044E,0xF82006C9,0x2C0B58,0xC200039D,0x7C000352,0x6200034D,0x5A0002D0,0x400003E8,0xC200060D,0x900004DE,0x3E000892,0x2A00061E,0x5C0B58,0x400884,0x400884,0x400884,0x400884,0xC8000000,0xC8000000,0xC8000000,0x60000001,0x60000001,0x40000001,0x600882,0x600882,0x600882,0x4C000335,0x4C000335,
+0x3A00019A,0xC40882,0xC40882,0x2C00053D,0x20000882,0x600882,0x600882,0x600882,0x4C000335,0x4C000335,0x3A00019A,0xC40882,0xC40882,0x2C00053D,0x20000882,0xC40882,0xC40882,0x2C00053D,0x20000882,0x20000882,0xFE100422,0xFE2C052D,0x400884,0xC200039D,0x7C000352,0x6200034D,0x5A0002D0,0x400003E8,0xD6000568,0x9000048D,0x8C0882,0x2C00053D,
+0x8C0882,0xCC0A69,0xFE8C0050,0xAE840000,0x8A840000,0x1300A69,0xCC000002,0x8A3C0000,0x1DF40A69,0x7E0001F9,0x66000A69,0x1300A69,0xCC000002,0x8A3C0000,0x1DF40A69,0x7E0001F9,0x66000A69,0x1DF40A69,0x7E0001F9,0x66000A69,0x66000A69,0x1300A69,0xCC000002,0x8A3C0000,0x1DF40A69,0x7E0001F9,0x66000A69,0x1DF40A69,0x7E0001F9,0x66000A69,0x66000A69,0x1DF40A69,
+0x7E0001F9,0x66000A69,0x66000A69,0x66000A69,0xFC900745,0xDC0A69,0xFAC407C1,0xFE300322,0xD6000232,0x9E0001D4,0x840000CD,0x7A000340,0xFE700708,0xFC0402AD,0x8E00007D,0x66000A69,0x1B00A69,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table197[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x180000,0x180000,0x180000,0x180000,0x180000,
+0x180000,0x2C0000,0x2C0000,0x2C0000,0x6000001,0x180000,0x180000,0x180000,0x180000,0x180000,0x180000,0x2C0000,0x2C0000,0x2C0000,0x6000001,0x2C0000,0x2C0000,0x2C0000,0x6000001,0x6000001,0x100000,0x100000,0x100000,0x4100000,0x140000,0x140000,0x140000,0x180000,0x4100000,0x140000,0x200000,0x2C0000,
+0x200000,0x940000,0x940000,0x940000,0x940000,0xDC0000,0xDC0000,0xDC0000,0x1BC0000,0x1BC0000,0x48000001,0xDC0000,0xDC0000,0xDC0000,0x1BC0000,0x1BC0000,0x48000001,0x1BC0000,0x1BC0000,0x48000001,0x48000001,0xDC0000,0xDC0000,0xDC0000,0x1BC0000,0x1BC0000,0x48000001,0x1BC0000,0x1BC0000,0x48000001,0x48000001,0x1BC0000,
+0x1BC0000,0x48000001,0x48000001,0x48000001,0xAC0000,0x69C0000,0x940000,0xC80000,0xF80000,0x1380000,0x1680000,0x9F80000,0xB80000,0xDC0000,0x1380000,0x48000001,0x1380000,0x1240001,0x1B40000,0x5FF80000,0x92000000,0x1B40000,0x5FF80000,0x92000000,0x5FF80000,0x92000000,0x92000000,0x1B40000,0x5FF80000,0x92000000,0x5FF80000,0x92000000,
+0x92000000,0x5FF80000,0x92000000,0x92000000,0x92000000,0x1B40000,0x5FF80000,0x92000000,0x5FF80000,0x92000000,0x92000000,0x5FF80000,0x92000000,0x92000000,0x92000000,0x5FF80000,0x92000000,0x92000000,0x92000000,0x92000000,0x1700000,0x5380000,0x5380000,0x3EC0000,0x49FC0000,0x79F00000,0x92000000,0x92000000,0x1900000,0x19FC0000,0x8DCC0000,0x92000000,
+0x35FC0000,0x7436D9,0xFE4413A8,0xCC380CE4,0x92380CE4,0xFE180DB5,0xD8080020,0x981001A8,0xA2080A89,0x860401D9,0x6E080A89,0xE60025C5,0xBA000D5B,0x8C0008D8,0x920011B1,0x80000671,0x68000D49,0x700025C5,0x6C001626,0x5C001831,0x4C0025C6,0xA836D7,0xA20019F4,0x800010AC,0x86001A01,0x74000CC5,0x620011B1,0x68002A9E,0x66001AB6,0x56001BC6,0x48002826,0x15836D7,
+0x560025F8,0x500024DD,0x44002EAA,0x380036D7,0xFE3C1CD5,0xFA642CB1,0xFE6C2E38,0xFE080A6B,0xD000070E,0x9E000678,0x880003A5,0x760009F9,0xFE181C4A,0xFC000B9A,0x7E00111A,0x56001BC6,0xF036D7,0x9825C5,0xFE680C84,0xC6500884,0x92500884,0xFE300C45,0xD4100002,0x96240104,0xA0100A69,0x860401D5,0x6E100A69,0xE025C5,0xBA000D5B,0x8C0008D8,0x920011B1,0x80000671,
+0x68000D49,0x1CC25C5,0x6C001626,0x5C001831,0x4C0025C6,0xE025C5,0xBA000D5B,0x8C0008D8,0x920011B1,0x80000671,0x68000D49,0x1CC25C5,0x6C001626,0x5C001831,0x4C0025C6,0x1CC25C5,0x6C001626,0x5C001831,0x4C0025C6,0x4C0025C6,0xFE581771,0xFC881FBD,0xFE8C1F95,0xFE080A5B,0xD000070E,0x9E000678,0x880003A5,0x760009F9,0xFE3417D5,0xFC000A9A,0x7E0010DA,0x5C001831,
+0x14025C5,0x380CE4,0x380CE4,0x380CE4,0x380CE4,0xD8080020,0xD8080020,0xD8080020,0x6A080021,0x6A080021,0x48080021,0x7C000882,0x7C000882,0x7C000882,0x62000271,0x62000271,0x460000EA,0x3C000882,0x3C000882,0x380004A5,0x28000882,0x500CE3,0x500CE3,0x500CE3,0x4C000576,0x4C000576,0x400002B3,0x340009D5,0x340009D5,0x320005D6,0x2800092B,0xA00CE3,
+0xA00CE3,0x260008B1,0x20000AE6,0x1A000CE3,0xFE1004E2,0xFE2C0801,0x380CE4,0xE40002E9,0x9A00028A,0x6E00029A,0x6A0001F4,0x4C000332,0xF40005C5,0xB200046A,0x4C00089B,0x320005D6,0x700CE3,0x500884,0x500884,0x500884,0x500884,0xD0100000,0xD0100000,0xD0100000,0x68100001,0x68100001,0x48100001,0x780882,0x780882,0x780882,0x62000271,0x62000271,
+0x460000EA,0xF40882,0xF40882,0x380004A5,0x28000882,0x780882,0x780882,0x780882,0x62000271,0x62000271,0x460000EA,0xF40882,0xF40882,0x380004A5,0x28000882,0xF40882,0xF40882,0x380004A5,0x28000882,0x28000882,0xFE200451,0xFA440548,0x500884,0xE40002E9,0x9A00028A,0x6E00029A,0x6A0001F4,0x4C000332,0xF40004E4,0xB20003F1,0xAC0882,0x380004A5,
+0xAC0882,0xDC0A69,0xFEA40080,0xB6940000,0x92940000,0x1480A69,0xD8080000,0x924C0000,0x27FC0A69,0x840001A5,0x6E000A69,0x1480A69,0xD8080000,0x924C0000,0x27FC0A69,0x840001A5,0x6E000A69,0x27FC0A69,0x840001A5,0x6E000A69,0x6E000A69,0x1480A69,0xD8080000,0x924C0000,0x27FC0A69,0x840001A5,0x6E000A69,0x27FC0A69,0x840001A5,0x6E000A69,0x6E000A69,0x27FC0A69,
+0x840001A5,0x6E000A69,0x6E000A69,0x6E000A69,0xFE940781,0xEC0A69,0xFECC07D9,0xFE400361,0xE00001CA,0xA8000190,0x8C000088,0x820002E4,0xF6880745,0xFE1402E4,0x9600003D,0x6E000A69,0x1D40A69,0x80020,0x80020,0x80020,0x80020,0x80020,0x80020,0x80020,0x80020,0x80020,0x80020,0x16000000,0x16000000,0x16000000,0x16000000,0x16000000,
+0x16000000,0xA000001,0xA000001,0xA000001,0x6000001,0xC0020,0xC0020,0xC0020,0xC0020,0xC0020,0xC0020,0x600000D,0x600000D,0x600000D,0x6000005,0x140020,0x140020,0x140020,0x4000012,0x2000022,0x78000000,0x80020,0x80020,0x36000000,0x24000000,0x1C000000,0x1C000000,0x12000000,0x36000009,0x24000004,0xE000001,0x600000D,
+0x100020,};
+static const uint32_t g_etc1_to_bc7_m6_table198[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x200000,0x300000,0x300000,0x300000,0x300000,0x300000,
+0x300000,0x5C0000,0x5C0000,0x5C0000,0xE000001,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x5C0000,0x5C0000,0x5C0000,0xE000001,0x5C0000,0x5C0000,0x5C0000,0xE000001,0xE000001,0x8200000,0x200000,0x200000,0x240000,0x280000,0x2C0000,0x2C0000,0x340000,0x240000,0x280000,0x400000,0x5C0000,
+0x400000,0xA40000,0xA40000,0xA40000,0xA40000,0xF40000,0xF40000,0xF40000,0x1F00000,0x1F00000,0x50000001,0xF40000,0xF40000,0xF40000,0x1F00000,0x1F00000,0x50000001,0x1F00000,0x1F00000,0x50000001,0x50000001,0xF40000,0xF40000,0xF40000,0x1F00000,0x1F00000,0x50000001,0x1F00000,0x1F00000,0x50000001,0x50000001,0x1F00000,
+0x1F00000,0x50000001,0x50000001,0x50000001,0x6BC0000,0xEAC0000,0xA40000,0x2DC0000,0x1140000,0x15C0000,0x1900000,0x15F40000,0x2CC0000,0xF40000,0x15C0000,0x50000001,0x15C0000,0x1340001,0x1CC0000,0x6BF80000,0x9A000000,0x1CC0000,0x6BF80000,0x9A000000,0x6BF80000,0x9A000000,0x9A000000,0x1CC0000,0x6BF80000,0x9A000000,0x6BF80000,0x9A000000,
+0x9A000000,0x6BF80000,0x9A000000,0x9A000000,0x9A000000,0x1CC0000,0x6BF80000,0x9A000000,0x6BF80000,0x9A000000,0x9A000000,0x6BF80000,0x9A000000,0x9A000000,0x9A000000,0x6BF80000,0x9A000000,0x9A000000,0x9A000000,0x9A000000,0x1840000,0xD480000,0xD480000,0xBFC0000,0x57FC0000,0x83F00000,0x9A000000,0x9A000000,0x3A40000,0x2BFC0000,0x95DC0000,0x9A000000,
+0x43FC0000,0x803A9D,0xFE5016F4,0xD6400EC4,0x9A400EC4,0xFE300F95,0xE4100082,0x9E1C0268,0xAA100AE9,0x900C020D,0x76100AE9,0xFE0025C5,0xCC000C2B,0x98000888,0xA2001052,0x860004F1,0x74000C51,0x7C0025C5,0x720014E2,0x66001742,0x540025C6,0xBC3A9B,0xAE001B0C,0x8C00119C,0x92001A61,0x80000C45,0x6E001179,0x74002BBE,0x6C001A56,0x60001B66,0x520028A3,0x17C3A9B,
+0x5C0027DC,0x56002631,0x4A00308E,0x3E003A9B,0xFE501FDA,0xFE6C3029,0xFE6C3258,0xFE140B8E,0xE2000578,0xAE0004FD,0x9200026A,0x8000085D,0xFE241F6E,0xFC000ADA,0x86000FF4,0x60001B66,0x10C3A9B,0xA825C5,0xFE740D24,0xCE600884,0x9A600884,0xFE440CB5,0xDC200002,0x9E340104,0xA8200A69,0x8E1401D5,0x76200A69,0xF825C5,0xCC000C2B,0x98000888,0xA2001052,0x860004F1,
+0x74000C51,0x1FC25C5,0x720014E2,0x66001742,0x540025C6,0xF825C5,0xCC000C2B,0x98000888,0xA2001052,0x860004F1,0x74000C51,0x1FC25C5,0x720014E2,0x66001742,0x540025C6,0x1FC25C5,0x720014E2,0x66001742,0x540025C6,0x540025C6,0xFC74181E,0xFE8C2035,0xF8A02004,0xFE140B2A,0xE2000578,0xAE0004FD,0x9200026A,0x8000085D,0xFE44186E,0xFC0009DA,0x86000FB4,0x66001742,
+0x16425C5,0x400EC4,0x400EC4,0x400EC4,0x400EC4,0xE8100080,0xE8100080,0xE8100080,0x74100081,0x74100081,0x50100081,0x94000882,0x94000882,0x94000882,0x680001BD,0x680001BD,0x4C00006A,0x48000882,0x48000882,0x3E00040D,0x30000882,0x600EC3,0x600EC3,0x600EC3,0x580005D6,0x580005D6,0x460002BB,0x40000A6D,0x40000A6D,0x3A0005BA,0x2E00096B,0xC40EC3,
+0xC40EC3,0x32000989,0x26000BEE,0x20000EC3,0xFE2005E1,0xF43809E0,0x400EC4,0xFA00024A,0xB20001E1,0x880001E1,0x8000015D,0x6000028A,0xFE000614,0xC40003F1,0x5C0008A6,0x3A0005BA,0x8C0EC3,0x600884,0x600884,0x600884,0x600884,0xD8200000,0xD8200000,0xD8200000,0x70200001,0x70200001,0x50200001,0x900882,0x900882,0x900882,0x680001BD,0x680001BD,
+0x4C00006A,0x1240882,0x1240882,0x3E00040D,0x30000882,0x900882,0x900882,0x900882,0x680001BD,0x680001BD,0x4C00006A,0x1240882,0x1240882,0x3E00040D,0x30000882,0x1240882,0x1240882,0x3E00040D,0x30000882,0x30000882,0xFA340480,0xFE4C0568,0x600884,0xFA00024A,0xB20001E1,0x880001E1,0x8000015D,0x6000028A,0xFE0C04E2,0xD000034D,0xD00882,0x3E00040D,
+0xD00882,0xEC0A69,0xFEB000B4,0xBEA40000,0x9AA40000,0x1600A69,0xE0180000,0x9A5C0000,0x33FC0A69,0x90000145,0x76000A69,0x1600A69,0xE0180000,0x9A5C0000,0x33FC0A69,0x90000145,0x76000A69,0x33FC0A69,0x90000145,0x76000A69,0x76000A69,0x1600A69,0xE0180000,0x9A5C0000,0x33FC0A69,0x90000145,0x76000A69,0x33FC0A69,0x90000145,0x76000A69,0x76000A69,0x33FC0A69,
+0x90000145,0x76000A69,0x76000A69,0x76000A69,0xFEB40782,0xFC0A69,0xFAE40800,0xFE5803B5,0xF6000184,0xB6000132,0x94000048,0x8A000290,0xFE980745,0xFE2C0340,0xA200001D,0x76000A69,0x1F40A69,0x100080,0x100080,0x100080,0x100080,0x100080,0x100080,0x100080,0x100080,0x100080,0x100080,0x30000000,0x30000000,0x30000000,0x30000000,0x30000000,
+0x30000000,0x16000001,0x16000001,0x16000001,0xE000001,0x180080,0x180080,0x180080,0x180080,0x180080,0x180080,0x1200002D,0x1200002D,0x1200002D,0xC000019,0x2C0080,0x2C0080,0x2C0080,0xA00004A,0x6000082,0xF8000000,0x100080,0x100080,0x6E000000,0x4C000000,0x3A000000,0x3A000000,0x26000000,0x60000028,0x42000014,0x1E000004,0x1200002D,
+0x200080,};
+static const uint32_t g_etc1_to_bc7_m6_table199[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x300000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,
+0x2440000,0x8C0000,0x8C0000,0x8C0000,0x16000001,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x2440000,0x8C0000,0x8C0000,0x8C0000,0x16000001,0x8C0000,0x8C0000,0x8C0000,0x16000001,0x16000001,0x340000,0x300000,0x300000,0x380000,0x3C0000,0x400000,0x400000,0x500000,0x380000,0x3C0000,0x640000,0x8C0000,
+0x640000,0xB40000,0xB40000,0xB40000,0xB40000,0x10C0000,0x10C0000,0x10C0000,0xBF80000,0xBF80000,0x58000001,0x10C0000,0x10C0000,0x10C0000,0xBF80000,0xBF80000,0x58000001,0xBF80000,0xBF80000,0x58000001,0x58000001,0x10C0000,0x10C0000,0x10C0000,0xBF80000,0xBF80000,0x58000001,0xBF80000,0xBF80000,0x58000001,0x58000001,0xBF80000,
+0xBF80000,0x58000001,0x58000001,0x58000001,0xD00000,0xC00000,0xB40000,0xF40000,0x32C0000,0x17C0000,0x1B80000,0x1FF80000,0x2E00000,0x10C0000,0x17C0000,0x58000001,0x17C0000,0x1440001,0x1E40000,0x77F80000,0xA2000000,0x1E40000,0x77F80000,0xA2000000,0x77F80000,0xA2000000,0xA2000000,0x1E40000,0x77F80000,0xA2000000,0x77F80000,0xA2000000,
+0xA2000000,0x77F80000,0xA2000000,0xA2000000,0xA2000000,0x1E40000,0x77F80000,0xA2000000,0x77F80000,0xA2000000,0xA2000000,0x77F80000,0xA2000000,0xA2000000,0xA2000000,0x77F80000,0xA2000000,0xA2000000,0xA2000000,0xA2000000,0x1980000,0x15C0000,0x15C0000,0x1DFC0000,0x65FC0000,0x8DF00000,0xA2000000,0xA2000000,0x1BC0000,0x3BFC0000,0x9DEC0000,0xA2000000,
+0x53FC0000,0x8C3EC1,0xFE5C1AB8,0xDE4C10F9,0xA24C10F8,0xFE3C1205,0xEC180130,0xA8240370,0xB4180B89,0x98100285,0x7E180B89,0xFE0C2621,0xE2000B28,0xA204088E,0xAE000F3A,0x92000391,0x7A000B81,0x880025C5,0x7E0013B2,0x6C00162E,0x5C0025C6,0xCC3EBF,0xBA001C84,0x9800130C,0xA2001ACB,0x8C000C25,0x74001185,0x80002CFE,0x76001A25,0x66001B26,0x5800292F,0x1A03EBF,
+0x66002A4B,0x5C0027D5,0x500032AA,0x44003EBF,0xFE582361,0xF8803495,0xFA843661,0xFE180DAD,0xF6000408,0xBC000398,0x9E000164,0x8A0006D0,0xFE342275,0xFE000B6D,0x94000EAC,0x66001B26,0x1243EBF,0xB825C5,0xFE8C0DD4,0xD6700884,0xA2700884,0xFE500D49,0xE4300002,0xA6440104,0xB0300A69,0x962401D5,0x7E300A69,0x11025C5,0xE2000B28,0xA2080884,0xAE000F3A,0x92000391,
+0x7A000B81,0xDFC25C5,0x7E0013B2,0x6C00162E,0x5C0025C6,0x11025C5,0xE2000B28,0xA2080884,0xAE000F3A,0x92000391,0x7A000B81,0xDFC25C5,0x7E0013B2,0x6C00162E,0x5C0025C6,0xDFC25C5,0x7E0013B2,0x6C00162E,0x5C0025C6,0x5C0025C6,0xFE78188A,0xFCA82039,0xFEAC2018,0xFE300C02,0xF6000408,0xBC000398,0x9E000164,0x8A0006D0,0xFE5C18B6,0xFE040A46,0x94000E5B,0x6C00162E,
+0x18825C5,0x4C10F8,0x4C10F8,0x4C10F8,0x4C10F8,0xF8180120,0xF8180120,0xF8180120,0x7E180121,0x7E180121,0x58180121,0xAC000882,0xAC000882,0xAC000882,0x7A000131,0x7A000131,0x5800001A,0x54000882,0x54000882,0x4A000385,0x38000882,0x7010F8,0x7010F8,0x7010F8,0x62000651,0x62000651,0x52000313,0x4C000B25,0x4C000B25,0x420005AE,0x340009C3,0xE410F8,
+0xE410F8,0x38000AA9,0x2C000D26,0x240010FB,0xFE2C0756,0xFA440BCC,0x4C10F8,0xFE08025A,0xC6000151,0x9A000161,0x8C0000CD,0x6A0001E2,0xFE000734,0xDA000398,0x660008AE,0x420005AE,0xA010F8,0x700884,0x700884,0x700884,0x700884,0xE0300000,0xE0300000,0xE0300000,0x78300001,0x78300001,0x58300001,0xA80882,0xA80882,0xA80882,0x7A000131,0x7A000131,
+0x5800001A,0x1580882,0x1580882,0x4A000385,0x38000882,0xA80882,0xA80882,0xA80882,0x7A000131,0x7A000131,0x5800001A,0x1580882,0x1580882,0x4A000385,0x38000882,0x1580882,0x1580882,0x4A000385,0x38000882,0x38000882,0xFE3C04A0,0xFA64057D,0x700884,0xFE08024A,0xC6000151,0x9A000161,0x8C0000CD,0x6A0001E2,0xFE140514,0xEC0002D0,0xF00882,0x4A000385,
+0xF00882,0xFC0A69,0xFEC400E9,0xC6B40000,0xA2B40000,0x1780A69,0xE8280000,0xA26C0000,0x3FFC0A69,0x9A000104,0x7E000A69,0x1780A69,0xE8280000,0xA26C0000,0x3FFC0A69,0x9A000104,0x7E000A69,0x3FFC0A69,0x9A000104,0x7E000A69,0x7E000A69,0x1780A69,0xE8280000,0xA26C0000,0x3FFC0A69,0x9A000104,0x7E000A69,0x3FFC0A69,0x9A000104,0x7E000A69,0x7E000A69,0x3FFC0A69,
+0x9A000104,0x7E000A69,0x7E000A69,0x7E000A69,0xFAC807C1,0x10C0A69,0xFEEC0820,0xFE6C03FA,0xFA040152,0xBE0000F2,0x9E000020,0x9400022D,0xFEAC0784,0xFE4C037A,0xAC000005,0x7E000A69,0xDFC0A69,0x180120,0x180120,0x180120,0x180120,0x180120,0x180120,0x180120,0x180120,0x180120,0x180120,0x48000000,0x48000000,0x48000000,0x48000000,0x48000000,
+0x48000000,0x22000000,0x22000000,0x22000000,0x16000001,0x240120,0x240120,0x240120,0x240120,0x240120,0x240120,0x1E00006D,0x1E00006D,0x1E00006D,0x1400003A,0x440120,0x440120,0x440120,0x100000AA,0xA000122,0xFC080020,0x180120,0x180120,0xA8000000,0x74000000,0x58000000,0x58000000,0x3A000000,0x84000059,0x6400002D,0x2C000009,0x1E00006D,
+0x300120,};
+static const uint32_t g_etc1_to_bc7_m6_table200[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x400001,0x600000,0x600000,0x600000,0x600000,0x600000,
+0x600000,0xC40000,0xC40000,0xC40000,0x20000000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0xC40000,0xC40000,0xC40000,0x20000000,0xC40000,0xC40000,0xC40000,0x20000000,0x20000000,0xA440000,0x400001,0x400001,0x4C0000,0x4500000,0x580000,0x580000,0x26C0000,0x4C0000,0x4500000,0x8C0000,0xC40000,
+0x8C0000,0xC40001,0xC40001,0xC40001,0xC40001,0x3240000,0x3240000,0x3240000,0x17FC0000,0x17FC0000,0x62000000,0x3240000,0x3240000,0x3240000,0x17FC0000,0x17FC0000,0x62000000,0x17FC0000,0x17FC0000,0x62000000,0x62000000,0x3240000,0x3240000,0x3240000,0x17FC0000,0x17FC0000,0x62000000,0x17FC0000,0x17FC0000,0x62000000,0x62000000,0x17FC0000,
+0x17FC0000,0x62000000,0x62000000,0x62000000,0x4E40000,0xD40000,0xC40001,0x10C0000,0x14C0000,0x1A40000,0x1E40000,0x2BF80000,0xF80000,0x3240000,0x1A40000,0x62000000,0x1A40000,0x1580000,0x3FC0000,0x85F80000,0xAA000001,0x3FC0000,0x85F80000,0xAA000001,0x85F80000,0xAA000001,0xAA000001,0x3FC0000,0x85F80000,0xAA000001,0x85F80000,0xAA000001,
+0xAA000001,0x85F80000,0xAA000001,0xAA000001,0xAA000001,0x3FC0000,0x85F80000,0xAA000001,0x85F80000,0xAA000001,0xAA000001,0x85F80000,0xAA000001,0xAA000001,0xAA000001,0x85F80000,0xAA000001,0xAA000001,0xAA000001,0xAA000001,0x1B00000,0xF6C0000,0xF6C0000,0x33FC0000,0x75F80000,0x97F80000,0xAA000001,0xAA000001,0x1D40000,0x4FFC0000,0xA7E00000,0xAA000001,
+0x63FC0000,0x9843DA,0xFE741F87,0xEA5813DA,0xAA5813DB,0xFE441546,0xF824023F,0xB43004F3,0xC0200C8A,0xA020035E,0x86200C8A,0xFE1C2759,0xEE000A1B,0xAC0C08D9,0xC0000E29,0x9E000252,0x86000AE2,0x960025C5,0x8A001275,0x7800150D,0x640025C5,0xE043DA,0xCC001E91,0xA200151E,0xA8001BBA,0x92000C52,0x800011F2,0x8C002E81,0x80001A11,0x72001AE5,0x620029D5,0x1CC43DA,
+0x6C002D36,0x66002A52,0x56003551,0x4A0043DE,0xFE6427D8,0xFE8C3942,0xFE8C3B6A,0xFE301079,0xFC000338,0xC8000260,0xA6000092,0x96000559,0xFE4426F1,0xFE040DC1,0x9E000D7F,0x72001AE5,0x14043DA,0xCC25C6,0xFE980EA3,0xDE840883,0xAA840883,0xFE680DF2,0xEE400003,0xAE540103,0xB8400A6A,0xA03801D6,0x86400A6A,0x12C25C5,0xEE000A1B,0xAA1C0883,0xC0000E29,0x9E000252,
+0x86000AE2,0x1BF825C5,0x8A001275,0x7800150D,0x640025C5,0x12C25C5,0xEE000A1B,0xAA1C0883,0xC0000E29,0x9E000252,0x86000AE2,0x1BF825C5,0x8A001275,0x7800150D,0x640025C5,0x1BF825C5,0x8A001275,0x7800150D,0x640025C5,0x640025C5,0xFE941919,0xF6BC20B2,0xFAC42082,0xFE440D24,0xFC000338,0xC8000260,0xA6000092,0x96000559,0xFE781975,0xFE240B83,0x9E000D1B,0x7800150D,
+0x1AC25C5,0x5813DA,0x5813DA,0x5813DA,0x5813DA,0xFE24022E,0xFE24022E,0xFE24022E,0x8A200221,0x8A200221,0x62200221,0xC8000882,0xC8000882,0xC8000882,0x860000B9,0x860000B9,0x62000001,0x60000884,0x60000884,0x500002FD,0x40000884,0x28013DA,0x28013DA,0x28013DA,0x7400074D,0x7400074D,0x580003BD,0x58000C13,0x58000C13,0x4C0005BE,0x40000A3D,0x10813DA,
+0x10813DA,0x3E000C45,0x32000EC8,0x2A0013DD,0xFC380952,0xFE4C0E5E,0x5813DA,0xFE100315,0xDE0000D0,0xAE0000CD,0xA2000068,0x78000164,0xFE1408DB,0xFC000344,0x7C0008C2,0x4C0005BE,0xB813DA,0x840882,0x840882,0x840882,0x840882,0xE6440001,0xE6440001,0xE6440001,0x82400001,0x82400001,0x62400001,0xC40882,0xC40882,0xC40882,0x860000B9,0x860000B9,
+0x62000001,0x18C0882,0x18C0882,0x500002FD,0x40000884,0xC40882,0xC40882,0xC40882,0x860000B9,0x860000B9,0x62000001,0x18C0882,0x18C0882,0x500002FD,0x40000884,0x18C0882,0x18C0882,0x500002FD,0x40000884,0x40000884,0xFE5804B1,0xF47805B2,0x840882,0xFE240288,0xDE0000D0,0xAE0000CD,0xA2000068,0x78000164,0xFE340515,0xFC000244,0x1180882,0x500002FD,
+0x1180882,0x1100A69,0xFEDC013D,0xCEC80001,0xAAC40002,0x1900A69,0xF03C0000,0xAA800001,0x4DFC0A69,0xA40000C1,0x86000A69,0x1900A69,0xF03C0000,0xAA800001,0x4DFC0A69,0xA40000C1,0x86000A69,0x4DFC0A69,0xA40000C1,0x86000A69,0x86000A69,0x1900A69,0xF03C0000,0xAA800001,0x4DFC0A69,0xA40000C1,0x86000A69,0x4DFC0A69,0xA40000C1,0x86000A69,0x86000A69,0x4DFC0A69,
+0xA40000C1,0x86000A69,0x86000A69,0x86000A69,0xFED007FD,0x1200A69,0xFD080841,0xFE940451,0xFE100172,0xD00000A9,0xA800000A,0x9C0001E1,0xF6CC07C1,0xFE6403E8,0xB6080000,0x86000A69,0x1FF80A69,0x200221,0x200221,0x200221,0x200221,0x200221,0x200221,0x200221,0x200221,0x200221,0x200221,0x64000000,0x64000000,0x64000000,0x64000000,0x64000000,
+0x64000000,0x30000000,0x30000000,0x30000000,0x20000000,0x300221,0x300221,0x300221,0x300221,0x300221,0x300221,0x280000C2,0x280000C2,0x280000C2,0x1E000068,0x5C0221,0x5C0221,0x5C0221,0x16000145,0x10000221,0xFE0C009D,0x200221,0x200221,0xE8000000,0xA0000000,0x7A000000,0x7A000000,0x50000000,0xC40000A9,0x96000055,0x3E000010,0x280000C2,
+0x400221,};
+static const uint32_t g_etc1_to_bc7_m6_table201[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x500001,0x780000,0x780000,0x780000,0x780000,0x780000,
+0x780000,0xF40000,0xF40000,0xF40000,0x28000000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0xF40000,0xF40000,0xF40000,0x28000000,0xF40000,0xF40000,0xF40000,0x28000000,0x28000000,0x580000,0x500001,0x500001,0x600000,0x4640000,0x700000,0x700000,0x880000,0x600000,0x4640000,0xAC0000,0xF40000,
+0xAC0000,0xD40001,0xD40001,0xD40001,0xD40001,0x33C0000,0x33C0000,0x33C0000,0x23FC0000,0x23FC0000,0x6A000000,0x33C0000,0x33C0000,0x33C0000,0x23FC0000,0x23FC0000,0x6A000000,0x23FC0000,0x23FC0000,0x6A000000,0x6A000000,0x33C0000,0x33C0000,0x33C0000,0x23FC0000,0x23FC0000,0x6A000000,0x23FC0000,0x23FC0000,0x6A000000,0x6A000000,0x23FC0000,
+0x23FC0000,0x6A000000,0x6A000000,0x6A000000,0xF80000,0xE40000,0xD40001,0x1240000,0x1680000,0x1C80000,0x7F80000,0x37F40000,0x10C0000,0x33C0000,0x1C80000,0x6A000000,0x1C80000,0x1680000,0x1BFC0000,0x91F80000,0xB2000001,0x1BFC0000,0x91F80000,0xB2000001,0x91F80000,0xB2000001,0xB2000001,0x1BFC0000,0x91F80000,0xB2000001,0x91F80000,0xB2000001,
+0xB2000001,0x91F80000,0xB2000001,0xB2000001,0xB2000001,0x1BFC0000,0x91F80000,0xB2000001,0x91F80000,0xB2000001,0xB2000001,0x91F80000,0xB2000001,0xB2000001,0xB2000001,0x91F80000,0xB2000001,0xB2000001,0xB2000001,0xB2000001,0x1C40000,0x1800000,0x1800000,0x47FC0000,0x81FC0000,0xA1FC0000,0xB2000001,0xB2000001,0x3E80000,0x61FC0000,0xAFF00000,0xB2000001,
+0x73FC0000,0xA448CA,0xFE802443,0xF26416C6,0xB26416C7,0xFE5018EA,0xFE300393,0xBA3C069F,0xCA280DB2,0xA824045E,0x8E280DB2,0xFE30290A,0xFA00097B,0xB6140951,0xCC000D49,0xA800016E,0x8E000A8D,0xA20025C6,0x9000116D,0x7E001419,0x6C0025C5,0xF448CA,0xE20020BF,0xAE00178E,0xB4001CE2,0xA2000CB3,0x86001292,0x98003001,0x8A001A29,0x7A001AD5,0x68002A81,0x1F048CA,
+0x7800301E,0x6C002C86,0x5C0037E9,0x500048CE,0xFE782C61,0xFE8C3E62,0xF8A040BB,0xFE401395,0xFE0403A8,0xD6000182,0xB0000031,0xA0000422,0xFE542B17,0xFE1810AE,0xA6000CB9,0x7A001AD5,0x15C48CA,0xDC25C6,0xFEB00F63,0xE6940883,0xB2940883,0xFE800E9A,0xF6500003,0xB6640103,0xC0500A6A,0xA84801D6,0x8E500A6A,0x14425C5,0xFA00097B,0xB22C0883,0xCC000D49,0xA800016E,
+0x8E000A8D,0x27F825C5,0x9000116D,0x7E001419,0x6C0025C5,0x14425C5,0xFA00097B,0xB22C0883,0xCC000D49,0xA800016E,0x8E000A8D,0x27F825C5,0x9000116D,0x7E001419,0x6C0025C5,0x27F825C5,0x9000116D,0x7E001419,0x6C0025C5,0x6C0025C5,0xFEA019C8,0xFECC20B2,0xFECC20B2,0xFE5C0DFE,0xFE100393,0xD6000182,0xB0000031,0xA0000422,0xFE8819FE,0xFE400C4D,0xAC000C4E,0x7E001419,
+0x1D025C5,0x6416C6,0x6416C6,0x6416C6,0x6416C6,0xFE300392,0xFE300392,0xFE300392,0x94280349,0x94280349,0x6A280349,0xE0000882,0xE0000882,0xE0000882,0x98000061,0x98000061,0x6C040018,0x6C000884,0x6C000884,0x5C00027D,0x48000884,0x9016C5,0x9016C5,0x9016C5,0x80000875,0x80000875,0x62000491,0x62000CE4,0x62000CE4,0x540005F4,0x46000AA5,0x12416C5,
+0x12416C5,0x44000E01,0x3E001058,0x300016C5,0xFE3C0B76,0xF458115D,0x6416C6,0xFE18042D,0xFC000074,0xC0000074,0xAE000022,0x840000FA,0xFE200AF6,0xFE00038A,0x860008CA,0x540005F4,0xD016C5,0x940882,0x940882,0x940882,0x940882,0xEE540001,0xEE540001,0xEE540001,0x8A500001,0x8A500001,0x6A500001,0xDC0882,0xDC0882,0xDC0882,0x98000061,0x98000061,
+0x6A100001,0x1BC0882,0x1BC0882,0x5C00027D,0x48000884,0xDC0882,0xDC0882,0xDC0882,0x98000061,0x98000061,0x6A100001,0x1BC0882,0x1BC0882,0x5C00027D,0x48000884,0x1BC0882,0x1BC0882,0x5C00027D,0x48000884,0x48000884,0xFA6C04E2,0xFC8805B2,0x940882,0xFE3402B1,0xFC000074,0xC0000074,0xAE000022,0x840000FA,0xFA48054A,0xFC140265,0x1380882,0x5C00027D,
+0x1380882,0x1200A69,0xFEE80195,0xD6D80001,0xB2D40002,0x1A80A69,0xF84C0000,0xB2900001,0x59FC0A69,0xAC000082,0x8E000A69,0x1A80A69,0xF84C0000,0xB2900001,0x59FC0A69,0xAC000082,0x8E000A69,0x59FC0A69,0xAC000082,0x8E000A69,0x8E000A69,0x1A80A69,0xF84C0000,0xB2900001,0x59FC0A69,0xAC000082,0x8E000A69,0x59FC0A69,0xAC000082,0x8E000A69,0x8E000A69,0x59FC0A69,
+0xAC000082,0x8E000A69,0x8E000A69,0x8E000A69,0xFAF00802,0x1300A69,0xFF0C087D,0xFEAC04B1,0xFE3C01C4,0xDA00006A,0xB2040001,0xA800019A,0xFEDC07C1,0xFE880424,0xBE180000,0x8E000A69,0x2DFC0A69,0x280349,0x280349,0x280349,0x280349,0x280349,0x280349,0x280349,0x280349,0x280349,0x280349,0x7C000000,0x7C000000,0x7C000000,0x7C000000,0x7C000000,
+0x7C000000,0x3C000000,0x3C000000,0x3C000000,0x28000000,0x3C0349,0x3C0349,0x3C0349,0x3C0349,0x3C0349,0x3C0349,0x2E000132,0x2E000132,0x2E000132,0x2200009D,0x740349,0x740349,0x740349,0x1C0001F9,0x14000349,0xF4180154,0x280349,0x280349,0xFE04000D,0xC8000000,0x98000000,0x98000000,0x64000000,0xF6000105,0xB4000089,0x46000019,0x2E000132,
+0x540349,};
+static const uint32_t g_etc1_to_bc7_m6_table202[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x600001,0x900000,0x900000,0x900000,0x900000,0x900000,
+0x900000,0x1240000,0x1240000,0x1240000,0x30000000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x1240000,0x1240000,0x1240000,0x30000000,0x1240000,0x1240000,0x1240000,0x30000000,0x30000000,0x680000,0x600001,0x600001,0x2700000,0x4780000,0x840000,0x840000,0xA40000,0x2700000,0x4780000,0xD00000,0x1240000,
+0xD00000,0xE40001,0xE40001,0xE40001,0xE40001,0x1540000,0x1540000,0x1540000,0x2FFC0000,0x2FFC0000,0x72000000,0x1540000,0x1540000,0x1540000,0x2FFC0000,0x2FFC0000,0x72000000,0x2FFC0000,0x2FFC0000,0x72000000,0x72000000,0x1540000,0x1540000,0x1540000,0x2FFC0000,0x2FFC0000,0x72000000,0x2FFC0000,0x2FFC0000,0x72000000,0x72000000,0x2FFC0000,
+0x2FFC0000,0x72000000,0x72000000,0x72000000,0x10C0000,0x2F40000,0xE40001,0x1380000,0x3800000,0x1E80000,0x15F80000,0x41F80000,0x1200000,0x1540000,0x1E80000,0x72000000,0x1E80000,0x1780000,0x35FC0000,0x9DF40000,0xBA000001,0x35FC0000,0x9DF40000,0xBA000001,0x9DF40000,0xBA000001,0xBA000001,0x35FC0000,0x9DF40000,0xBA000001,0x9DF40000,0xBA000001,
+0xBA000001,0x9DF40000,0xBA000001,0xBA000001,0xBA000001,0x35FC0000,0x9DF40000,0xBA000001,0x9DF40000,0xBA000001,0xBA000001,0x9DF40000,0xBA000001,0xBA000001,0xBA000001,0x9DF40000,0xBA000001,0xBA000001,0xBA000001,0xBA000001,0x1D80000,0x1900000,0x1900000,0x5BFC0000,0x8FFC0000,0xABFC0000,0xBA000001,0xBA000001,0x5FC0000,0x71FC0000,0xB9C40000,0xBA000001,
+0x81FC0000,0xB04E1A,0xFE8C2977,0xFC6C1A06,0xBA6C1A07,0xFE5C1D1E,0xFE3C0597,0xC24408A6,0xD4300F1A,0xB22C059E,0x96300F1A,0xFE3C2B5E,0xFE080993,0xC01C0A01,0xD8000C89,0xB40000C6,0x96000A6A,0xAE0025C6,0x9C001065,0x8A001331,0x740025C5,0x1044E1A,0xE800231B,0xB4001A6E,0xC0001E4A,0xA8000D5F,0x8C001392,0xA200315F,0x92001A55,0x82001ADB,0x6E002B4D,0x7FC4E1A,
+0x7E003356,0x72002F0A,0x66003AC6,0x56004E1E,0xFE803152,0xFAA443AA,0xFEAC45DF,0xFE441768,0xFE100503,0xE20000CE,0xBC00000B,0xAA00032A,0xFE5C2FFA,0xFE241464,0xB6000BBD,0x82001ADB,0x1744E1A,0xEC25C6,0xFEC41026,0xEEA40883,0xBAA40883,0xFE980F62,0xFE600003,0xBE740103,0xC8600A6A,0xB05801D6,0x96600A6A,0x15C25C5,0xFE080983,0xBA3C0883,0xD8000C89,0xB40000C6,
+0x96000A6A,0x33F825C5,0x9C001065,0x8A001331,0x740025C5,0x15C25C5,0xFE080983,0xBA3C0883,0xD8000C89,0xB40000C6,0x96000A6A,0x33F825C5,0x9C001065,0x8A001331,0x740025C5,0x33F825C5,0x9C001065,0x8A001331,0x740025C5,0x740025C5,0xFEB41A2D,0xF8E0212E,0xFAE42103,0xFE780F0E,0xFE24046B,0xE20000CE,0xBC00000B,0xAA00032A,0xFE981A99,0xFE480D53,0xB6000B44,0x8A001331,
+0x1F025C5,0x6C1A06,0x6C1A06,0x6C1A06,0x6C1A06,0xFE3C0566,0xFE3C0566,0xFE3C0566,0x9E3004B1,0x9E3004B1,0x723004B1,0xF8000882,0xF8000882,0xF8000882,0xA8000025,0xA8000025,0x76080051,0x78000884,0x78000884,0x66000220,0x50000884,0xA41A05,0xA41A05,0xA41A05,0x8C0009DD,0x8C0009DD,0x680005C9,0x6E000DF4,0x6E000DF4,0x5E000632,0x4C000B25,0x14C1A05,
+0x14C1A05,0x50001001,0x44001218,0x36001A05,0xFE4C0DF1,0xFA641455,0x6C1A06,0xFE2C05C9,0xFE040078,0xD200003A,0xC0000004,0x960000A0,0xFC300D65,0xFE0004CA,0x960008DB,0x5E000632,0xE81A05,0xA40882,0xA40882,0xA40882,0xA40882,0xF6640001,0xF6640001,0xF6640001,0x92600001,0x92600001,0x72600001,0xF40882,0xF40882,0xF40882,0xA8000025,0xA8000025,
+0x72200001,0x1F00882,0x1F00882,0x66000220,0x50000884,0xF40882,0xF40882,0xF40882,0xA8000025,0xA8000025,0x72200001,0x1F00882,0x1F00882,0x66000220,0x50000884,0x1F00882,0x1F00882,0x66000220,0x50000884,0x50000884,0xFE740502,0xF49805E9,0xA40882,0xFE4402E4,0xFE040074,0xD200003A,0xC0000004,0x960000A0,0xFE50057A,0xFE24028A,0x15C0882,0x66000220,
+0x15C0882,0x1300A69,0xFF0001ED,0xDEE80001,0xBAE40002,0x1C00A69,0xFE600002,0xBAA00001,0x65F80A69,0xB6000059,0x96000A69,0x1C00A69,0xFE600002,0xBAA00001,0x65F80A69,0xB6000059,0x96000A69,0x65F80A69,0xB6000059,0x96000A69,0x96000A69,0x1C00A69,0xFE600002,0xBAA00001,0x65F80A69,0xB6000059,0x96000A69,0x65F80A69,0xB6000059,0x96000A69,0x96000A69,0x65F80A69,
+0xB6000059,0x96000A69,0x96000A69,0x96000A69,0xFEF80832,0x1440A69,0xFD280882,0xFEC004EA,0xFE500220,0xE6000050,0xBA140001,0xB2000151,0xFEF00800,0xFEA00488,0xC6280000,0x96000A69,0x3DF80A69,0x3004B1,0x3004B1,0x3004B1,0x3004B1,0x3004B1,0x3004B1,0x3004B1,0x3004B1,0x3004B1,0x3004B1,0x94000000,0x94000000,0x94000000,0x94000000,0x94000000,
+0x94000000,0x48000000,0x48000000,0x48000000,0x30000000,0x4804B1,0x4804B1,0x4804B1,0x4804B1,0x4804B1,0x4804B1,0x3A0001BA,0x3A0001BA,0x3A0001BA,0x2E0000E5,0x8C04B1,0x8C04B1,0x8C04B1,0x200002E4,0x180004B1,0xF8200244,0x3004B1,0x3004B1,0xFC0C0064,0xEE000000,0xB6000000,0xB6000000,0x78000000,0xF60001A5,0xD60000C2,0x56000022,0x3A0001BA,
+0x6404B1,};
+static const uint32_t g_etc1_to_bc7_m6_table203[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0x700001,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,
+0xA80000,0x1580000,0x1580000,0x1580000,0x38000000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0xA80000,0x1580000,0x1580000,0x1580000,0x38000000,0x1580000,0x1580000,0x1580000,0x38000000,0x38000000,0x4780000,0x700001,0x700001,0x840000,0x48C0000,0x2980000,0x2980000,0xC00000,0x840000,0x48C0000,0xF00000,0x1580000,
+0xF00000,0xF40001,0xF40001,0xF40001,0xF40001,0x16C0000,0x16C0000,0x16C0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x16C0000,0x16C0000,0x16C0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x3BFC0000,0x3BFC0000,0x7A000000,0x7A000000,0x16C0000,0x16C0000,0x16C0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x3BFC0000,0x3BFC0000,0x7A000000,0x7A000000,0x3BFC0000,
+0x3BFC0000,0x7A000000,0x7A000000,0x7A000000,0x51C0000,0xB040000,0xF40001,0x34C0000,0x19C0000,0x7FC0000,0x21FC0000,0x4BFC0000,0x1340000,0x16C0000,0x7FC0000,0x7A000000,0x7FC0000,0x1880000,0x4DFC0000,0xA7FC0000,0xC2000001,0x4DFC0000,0xA7FC0000,0xC2000001,0xA7FC0000,0xC2000001,0xC2000001,0x4DFC0000,0xA7FC0000,0xC2000001,0xA7FC0000,0xC2000001,
+0xC2000001,0xA7FC0000,0xC2000001,0xC2000001,0xC2000001,0x4DFC0000,0xA7FC0000,0xC2000001,0xA7FC0000,0xC2000001,0xC2000001,0xA7FC0000,0xC2000001,0xC2000001,0xC2000001,0xA7FC0000,0xC2000001,0xC2000001,0xC2000001,0xC2000001,0x1EC0000,0x9A00000,0x9A00000,0x6FFC0000,0x9DF80000,0xB5FC0000,0xC2000001,0xC2000001,0x23FC0000,0x83FC0000,0xC1D40000,0xC2000001,
+0x91FC0000,0xBC53CA,0xFE982F23,0xFE781DB3,0xC2781D9B,0xFE6821E2,0xFE480853,0xCC4C0AE2,0xDE3810C2,0xBA34072F,0x9E3810C2,0xFE442E39,0xFE140A9F,0xCA240AE9,0xE2000BDE,0xBE000056,0x9E040A76,0xBA0025C6,0xA6000F93,0x9000124D,0x7C0025C5,0x11853CA,0xF400260B,0xC0001DBE,0xCC001FF2,0xB4000E7F,0x980014B2,0xA8003317,0x9E001AAD,0x8C001AFD,0x7A002C15,0x11F853CA,
+0x840036F6,0x780031DE,0x6C003DB6,0x5C0053CE,0xFE8C36AE,0xFEAC491A,0xFEAC4BCF,0xFE541B8E,0xFE24073F,0xEE000058,0xC6080023,0xB6000243,0xFE703553,0xFE301879,0xBE000B25,0x8C001AFD,0x19053CA,0xFC25C6,0xFED010EE,0xF6B40883,0xC2B40883,0xFEA41022,0xFE780023,0xC6840103,0xD0700A6A,0xB86801D6,0x9E700A6A,0x17425C5,0xFE200A0B,0xC24C0883,0xE2000BDE,0xBE000056,
+0x9E0C0A6A,0x3FF825C5,0xA6000F93,0x9000124D,0x7C0025C5,0x17425C5,0xFE200A0B,0xC24C0883,0xE2000BDE,0xBE000056,0x9E0C0A6A,0x3FF825C5,0xA6000F93,0x9000124D,0x7C0025C5,0x3FF825C5,0xA6000F93,0x9000124D,0x7C0025C5,0x7C0025C5,0xFED01ACD,0xFEEC2132,0xFEEC213B,0xFE940FE5,0xFE38056B,0xEE000058,0xC410000B,0xB6000243,0xFEB41B45,0xFE680E81,0xBE000A95,0x9000124D,
+0xBFC25C5,0x781D9A,0x781D9A,0x781D9A,0x781D9A,0xFE440795,0xFE440795,0xFE440795,0xA8380659,0xA8380659,0x7A380659,0xFE0C08AE,0xFE0C08AE,0xFE0C08AE,0xB4000005,0xB4000005,0x7E0C00AD,0x84000884,0x84000884,0x6C0001C4,0x58000884,0x2B01D9A,0x2B01D9A,0x2B01D9A,0x98000B85,0x98000B85,0x74000731,0x74000F18,0x74000F18,0x6800068C,0x52000BBD,0x1681D9A,
+0x1681D9A,0x56001235,0x4A001408,0x3A001D9D,0xFE5810F1,0xFE6C17AD,0x781D9A,0xFE3407B5,0xFE140116,0xE200000D,0xD0000002,0xA0000059,0xFE341005,0xFE100696,0xA60008E8,0x6800068C,0xFC1D9A,0xB40882,0xB40882,0xB40882,0xB40882,0xFE740001,0xFE740001,0xFE740001,0x9A700001,0x9A700001,0x7A700001,0x10C0882,0x10C0882,0x10C0882,0xB4000005,0xB4000005,
+0x7A300001,0xBF80882,0xBF80882,0x6C0001C4,0x58000884,0x10C0882,0x10C0882,0x10C0882,0xB4000005,0xB4000005,0x7A300001,0xBF80882,0xBF80882,0x6C0001C4,0x58000884,0xBF80882,0xBF80882,0x6C0001C4,0x58000884,0x58000884,0xFE900515,0xFCA805E9,0xB40882,0xFE5C02FD,0xFE1C009D,0xE200000D,0xCC080000,0xA0000059,0xFA70057D,0xFA4002D2,0x17C0882,0x6C0001C4,
+0x17C0882,0x1400A69,0xFF0C025D,0xE6F80001,0xC2F40002,0x1D80A69,0xFE7C0014,0xC2B00001,0x71F80A69,0xBE000032,0x9E000A69,0x1D80A69,0xFE7C0014,0xC2B00001,0x71F80A69,0xBE000032,0x9E000A69,0x71F80A69,0xBE000032,0x9E000A69,0x9E000A69,0x1D80A69,0xFE7C0014,0xC2B00001,0x71F80A69,0xBE000032,0x9E000A69,0x71F80A69,0xBE000032,0x9E000A69,0x9E000A69,0x71F80A69,
+0xBE000032,0x9E000A69,0x9E000A69,0x9E000A69,0xFF140845,0x1540A69,0xF53808C5,0xFED80550,0xFE68028A,0xF2000028,0xC2240001,0xBA000115,0xF7080841,0xFEC004E2,0xCE380000,0x9E000A69,0x4BFC0A69,0x380659,0x380659,0x380659,0x380659,0x380659,0x380659,0x380659,0x380659,0x380659,0x380659,0xAC000000,0xAC000000,0xAC000000,0xAC000000,0xAC000000,
+0xAC000000,0x54000000,0x54000000,0x54000000,0x38000000,0x540659,0x540659,0x540659,0x540659,0x540659,0x540659,0x40000262,0x40000262,0x40000262,0x34000131,0xA40659,0xA40659,0xA40659,0x260003E8,0x1C000659,0xFC280374,0x380659,0x380659,0xFE100104,0xFA040014,0xD4000000,0xD4000000,0x8C000000,0xFA0802AD,0xF4000112,0x66000028,0x40000262,
+0x740659,};
+static const uint32_t g_etc1_to_bc7_m6_table204[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0x840000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,
+0xC40000,0x18C0000,0x18C0000,0x18C0000,0x40000001,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0xC40000,0x18C0000,0x18C0000,0x18C0000,0x40000001,0x18C0000,0x18C0000,0x18C0000,0x40000001,0x40000001,0x8C0000,0x840000,0x840000,0x2980000,0xA40000,0xB40000,0xB40000,0xDC0000,0x2980000,0xA40000,0x1180000,0x18C0000,
+0x1180000,0x1080000,0x1080000,0x1080000,0x1080000,0x1880000,0x1880000,0x1880000,0x49F80000,0x49F80000,0x82000001,0x1880000,0x1880000,0x1880000,0x49F80000,0x49F80000,0x82000001,0x49F80000,0x49F80000,0x82000001,0x82000001,0x1880000,0x1880000,0x1880000,0x49F80000,0x49F80000,0x82000001,0x49F80000,0x49F80000,0x82000001,0x82000001,0x49F80000,
+0x49F80000,0x82000001,0x82000001,0x82000001,0x1340000,0x5180000,0x1080000,0x1680000,0x1BC0000,0x19FC0000,0x31FC0000,0x59F40000,0x14C0000,0x1880000,0x19FC0000,0x82000001,0x19FC0000,0x1980001,0x69FC0000,0xB5FC0000,0xCC000000,0x69FC0000,0xB5FC0000,0xCC000000,0xB5FC0000,0xCC000000,0xCC000000,0x69FC0000,0xB5FC0000,0xCC000000,0xB5FC0000,0xCC000000,
+0xCC000000,0xB5FC0000,0xCC000000,0xCC000000,0xCC000000,0x69FC0000,0xB5FC0000,0xCC000000,0xB5FC0000,0xCC000000,0xCC000000,0xB5FC0000,0xCC000000,0xCC000000,0xCC000000,0xB5FC0000,0xCC000000,0xCC000000,0xCC000000,0xCC000000,0xBFC0000,0x3B40000,0x3B40000,0x85FC0000,0xABFC0000,0xC1F40000,0xCC000000,0xCC000000,0x45FC0000,0x95FC0000,0xCBC80000,0xCC000000,
+0xA1FC0000,0xC85AA5,0xFEA4360C,0xFE88228D,0xCC842208,0xFE8027E1,0xFE540C44,0xD8580DC5,0xE84412ED,0xC43C0938,0xA84012ED,0xFE503266,0xFE200CC4,0xD6240C2A,0xF4000B45,0xCA000015,0xAA080AB6,0xC60025C5,0xB2000E98,0x9C001162,0x860025C6,0x12C5AA3,0xFA002A18,0xCC00220B,0xE20021ED,0xBA00100A,0xA2001647,0xBA00351E,0xA8001B25,0x92001B46,0x80002CFE,0x1BF85AA3,
+0x90003B5B,0x84003543,0x7200414F,0x64005AA3,0xFEA03D3B,0xF8C05071,0xFAC452C9,0xFE6C216E,0xFE280A9E,0xFC00000E,0xD00C0071,0xC0000184,0xFE783BC2,0xFE441DA3,0xCE000A96,0x92001B46,0x1AC5AA3,0x10C25C5,0xFEE811FD,0xFEC80885,0xCCC40884,0xFEBC1115,0xFE880086,0xD0980104,0xDA840A69,0xC07801D5,0xA8840A69,0x38C25C5,0xFE380AD4,0xCC5C0884,0xF4000B45,0xCA000015,
+0xA8200A69,0x4BFC25C5,0xB2000E98,0x9C001162,0x860025C6,0x38C25C5,0xFE380AD4,0xCC5C0884,0xF4000B45,0xCA000015,0xA8200A69,0x4BFC25C5,0xB2000E98,0x9C001162,0x860025C6,0x4BFC25C5,0xB2000E98,0x9C001162,0x860025C6,0x860025C6,0xFEE41BB9,0xF90021AD,0xFD082185,0xFE981149,0xFE5C06AE,0xFC00000E,0xCE24000C,0xC0000184,0xFEC41BE9,0xFE840F78,0xCE0009ED,0x9C001162,
+0x1DF825C5,0x842208,0x842208,0x842208,0x842208,0xFE500A9D,0xFE500A9D,0xFE500A9D,0xB4400884,0xB4400884,0x82400885,0xFE180974,0xFE180974,0xFE180974,0xC4000001,0xC4000001,0x88140141,0x92000882,0x92000882,0x7800015A,0x62000882,0xC42208,0xC42208,0xC42208,0xA2000D86,0xA2000D86,0x8000092D,0x80001086,0x80001086,0x6E00071A,0x5E000C63,0x18C2208,
+0x18C2208,0x5C001505,0x5000166E,0x4000220B,0xFE6814BA,0xF67C1C38,0x842208,0xFE440A76,0xFE1C025D,0xF8000000,0xDE04001E,0xAE000022,0xFE3C13E0,0xFE180932,0xB6000903,0x6E00071A,0x1182208,0xC40884,0xC40884,0xC40884,0xC40884,0xFC88000D,0xFC88000D,0xFC88000D,0xA2840001,0xA2840001,0x82840001,0x3240882,0x3240882,0x3240882,0xC0080001,0xC0080001,
+0x82440001,0x17FC0882,0x17FC0882,0x7800015A,0x62000882,0x3240882,0x3240882,0x3240882,0xC0080001,0xC0080001,0x82440001,0x17FC0882,0x17FC0882,0x7800015A,0x62000882,0x17FC0882,0x17FC0882,0x7800015A,0x62000882,0x62000882,0xFEA0054A,0xF6BC0620,0xC40884,0xFE780349,0xFC3C00CA,0xF8000000,0xD21C0001,0xAE000022,0xF88805B2,0xFC5802F9,0x1A40882,0x7800015A,
+0x1A40882,0x1500A69,0xFF2402D5,0xF1080000,0xCD080000,0x1F40A69,0xFEA0004A,0xCCC00000,0x7FF80A69,0xCA000014,0xA8000A69,0x1F40A69,0xFEA0004A,0xCCC00000,0x7FF80A69,0xCA000014,0xA8000A69,0x7FF80A69,0xCA000014,0xA8000A69,0xA8000A69,0x1F40A69,0xFEA0004A,0xCCC00000,0x7FF80A69,0xCA000014,0xA8000A69,0x7FF80A69,0xCA000014,0xA8000A69,0xA8000A69,0x7FF80A69,
+0xCA000014,0xA8000A69,0xA8000A69,0xA8000A69,0xFB2C0884,0x1680A69,0xFF4C08C5,0xFEEC05A5,0xFE900304,0xFC00000D,0xCC340000,0xC20000DD,0xFF180845,0xFED80550,0xD64C0001,0xA8000A69,0x5DF80A69,0x400884,0x400884,0x400884,0x400884,0x400884,0x400884,0x400884,0x400884,0x400884,0x400884,0xC8000000,0xC8000000,0xC8000000,0xC8000000,0xC8000000,
+0xC8000000,0x60000001,0x60000001,0x60000001,0x40000001,0x600882,0x600882,0x600882,0x600882,0x600882,0x600882,0x4C000335,0x4C000335,0x4C000335,0x3A00019A,0xC40882,0xC40882,0xC40882,0x2C00053D,0x20000882,0xFE2C052D,0x400884,0x400884,0xFE200200,0xFE0C0075,0xF6000000,0xF6000000,0xA2000000,0xFE100422,0xFE0001C4,0x7600003A,0x4C000335,
+0x8C0882,};
+static const uint32_t g_etc1_to_bc7_m6_table205[] = {
+0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x2000000,0x2000000,0x2000000,0x2000000,0x2000000,0x2000000,0x2000000,0x2000000,0x2000000,0x2000000,0x0,
+0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x8000000,0x8000000,0x8000000,0x2000000,0x0,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,
+0xDC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x48000001,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0xDC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x48000001,0x1BC0000,0x1BC0000,0x1BC0000,0x48000001,0x48000001,0x69C0000,0x940000,0x940000,0xAC0000,0xB80000,0xC80000,0xC80000,0xF80000,0xAC0000,0xB80000,0x1380000,0x1BC0000,
+0x1380000,0x1180000,0x1180000,0x1180000,0x1180000,0x1A00000,0x1A00000,0x1A00000,0x55F80000,0x55F80000,0x8A000001,0x1A00000,0x1A00000,0x1A00000,0x55F80000,0x55F80000,0x8A000001,0x55F80000,0x55F80000,0x8A000001,0x8A000001,0x1A00000,0x1A00000,0x1A00000,0x55F80000,0x55F80000,0x8A000001,0x55F80000,0x55F80000,0x8A000001,0x8A000001,0x55F80000,
+0x55F80000,0x8A000001,0x8A000001,0x8A000001,0x3440000,0xD280000,0x1180000,0x17C0000,0x3D40000,0x27FC0000,0x3FF80000,0x63F80000,0x1600000,0x1A00000,0x27FC0000,0x8A000001,0x27FC0000,0x1A80001,0x81FC0000,0xC1FC0000,0xD4000000,0x81FC0000,0xC1FC0000,0xD4000000,0xC1FC0000,0xD4000000,0xD4000000,0x81FC0000,0xC1FC0000,0xD4000000,0xC1FC0000,0xD4000000,
+0xD4000000,0xC1FC0000,0xD4000000,0xD4000000,0xD4000000,0x81FC0000,0xC1FC0000,0xD4000000,0xC1FC0000,0xD4000000,0xD4000000,0xC1FC0000,0xD4000000,0xD4000000,0xD4000000,0xC1FC0000,0xD4000000,0xD4000000,0xD4000000,0xD4000000,0x33FC0000,0xBC40000,0xBC40000,0x99FC0000,0xB9FC0000,0xCBF40000,0xD4000000,0xD4000000,0x63FC0000,0xA7FC0000,0xD3D80000,0xD4000000,
+0xB1FC0000,0xD4604E,0xFEB03C09,0xFE9426F6,0xD49025C5,0xFE8C2D3E,0xFE641023,0xDE641046,0xF24C14D2,0xCE440B09,0xB04C14D2,0xFE68364F,0xFE2C0F61,0xE02C0D53,0xFC040B0A,0xD2040012,0xB20C0B07,0xD20025C6,0xB8000DD5,0xA60010C2,0x8E0025C7,0x33C604A,0xFE042E6B,0xD40425C6,0xE800235E,0xC6001139,0xA80017A6,0xC0003691,0xAE001B58,0x9E001B37,0x86002D9F,0x23FC604A,
+0x96003EDE,0x8A0037DE,0x7E004416,0x6A00604A,0xFEA0430C,0xFECC55D2,0xFECC5866,0xFE702686,0xFE3C0E17,0xFE08006C,0xDA1400D9,0xCA0000F6,0xFE904155,0xFE50227D,0xD60009ED,0x9E001B37,0x1C8604A,0x11C25C5,0xFEF412E5,0xFED808A8,0xD4D40884,0xFED011E1,0xFEA0010E,0xD8A80104,0xE2940A69,0xC88801D5,0xB0940A69,0x3A425C5,0xFE580BA3,0xD46C0884,0xFC040B09,0xD2040011,
+0xB0300A69,0x57FC25C5,0xB8000DD4,0xA60010C1,0x8E0025C6,0x3A425C5,0xFE580BA3,0xD46C0884,0xFC040B09,0xD2040011,0xB0300A69,0x57FC25C5,0xB8000DD4,0xA60010C1,0x8E0025C6,0x57FC25C5,0xB8000DD4,0xA60010C1,0x8E0025C6,0x8E0025C6,0xFEF81C2C,0xFF0C21C5,0xFF0C21E5,0xFEC01224,0xFE6807CD,0xFE18003B,0xD634000C,0xCA0000F5,0xFEDC1C41,0xFE9810B6,0xD600095D,0xA60010C1,
+0x2BFC25C5,0x9025C5,0x9025C5,0x9025C5,0x9025C5,0xFE5C0D6A,0xFE5C0D6A,0xFE5C0D6A,0xBC4C0A6A,0xBC4C0A6A,0x8A4C0A6A,0xFE240A95,0xFE240A95,0xFE240A95,0xD204000E,0xD204000E,0x901801D6,0x9E000883,0x9E000883,0x84000113,0x6A000883,0xD425C5,0xD425C5,0xD425C5,0xAE000F45,0xAE000F45,0x86000AD6,0x8C00118B,0x8C00118B,0x7A000763,0x62000CC3,0x1B025C5,
+0x1B025C5,0x66001782,0x56001853,0x460025C6,0xFE681813,0xFC881FBD,0x9025C5,0xFE4C0D02,0xFE2C03E3,0xFE08001B,0xEC08004D,0xBC00000B,0xFE5016E0,0xFE300BA2,0xC60008FD,0x7A000763,0x13025C5,0xD40884,0xD40884,0xD40884,0xD40884,0xFE98001D,0xFE98001D,0xFE98001D,0xAA940001,0xAA940001,0x8A940001,0x33C0882,0x33C0882,0x33C0882,0xC8180001,0xC8180001,
+0x8A540001,0x23FC0882,0x23FC0882,0x84000112,0x6A000882,0x33C0882,0x33C0882,0x33C0882,0xC8180001,0xC8180001,0x8A540001,0x23FC0882,0x23FC0882,0x84000112,0x6A000882,0x23FC0882,0x23FC0882,0x84000112,0x6A000882,0x6A000882,0xFAB4057D,0xFECC0620,0xD40884,0xFE880374,0xFE5400F2,0xFE100001,0xDA2C0001,0xBC00000A,0xFE9405BA,0xFE680322,0x1C80882,0x84000112,
+0x1C80882,0x1600A69,0xFF3C0355,0xF9180000,0xD5180000,0xFFC0A69,0xFEB80092,0xD4D00000,0x8BF80A69,0xD2000008,0xB0000A69,0xFFC0A69,0xFEB80092,0xD4D00000,0x8BF80A69,0xD2000008,0xB0000A69,0x8BF80A69,0xD2000008,0xB0000A69,0xB0000A69,0xFFC0A69,0xFEB80092,0xD4D00000,0x8BF80A69,0xD2000008,0xB0000A69,0x8BF80A69,0xD2000008,0xB0000A69,0xB0000A69,0x8BF80A69,
+0xD2000008,0xB0000A69,0xB0000A69,0xB0000A69,0xFF3408B4,0x1780A69,0xF75C0908,0xFF040611,0xFEBC037A,0xFE180032,0xD4440000,0xCE0000B4,0xFF2C088A,0xFEF005C4,0xDE5C0001,0xB0000A69,0x6BFC0A69,0x4C0A69,0x4C0A69,0x4C0A69,0x4C0A69,0x4C0A69,0x4C0A69,0x4C0A69,0x4C0A69,0x4C0A69,0x4C0A69,0xDC040001,0xDC040001,0xDC040001,0xDC040001,0xDC040001,
+0xDC040001,0x6C040001,0x6C040001,0x6C040001,0x48000002,0x6C0A69,0x6C0A69,0x6C0A69,0x6C0A69,0x6C0A69,0x6C0A69,0x580003D4,0x580003D4,0x580003D4,0x400001E1,0xDC0A69,0xDC0A69,0xDC0A69,0x32000652,0x24000A69,0xF63C06CD,0x4C0A69,0x4C0A69,0xFE200321,0xFE140115,0xFE080012,0xFE080012,0xB2040001,0xFE1005A5,0xFE0002C5,0x86000035,0x580003D4,
+0x9C0A69,};
+static const uint32_t g_etc1_to_bc7_m6_table206[] = {
+0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x2180000,0x2180000,0x2180000,0x2180000,0x2180000,0x2180000,0x2180000,0x2180000,0x2180000,0x2180000,0x300000,
+0x300000,0x300000,0x300000,0x8000000,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x100001,0x140000,0x140000,0x140000,0x2180000,0x240000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xA40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,
+0xF40000,0x1F00000,0x1F00000,0x1F00000,0x50000001,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0xF40000,0x1F00000,0x1F00000,0x1F00000,0x50000001,0x1F00000,0x1F00000,0x1F00000,0x50000001,0x50000001,0xEAC0000,0xA40000,0xA40000,0x6BC0000,0x2CC0000,0x2DC0000,0x2DC0000,0x1140000,0x6BC0000,0x2CC0000,0x15C0000,0x1F00000,
+0x15C0000,0x1280000,0x1280000,0x1280000,0x1280000,0x1B80000,0x1B80000,0x1B80000,0x61F80000,0x61F80000,0x92000001,0x1B80000,0x1B80000,0x1B80000,0x61F80000,0x61F80000,0x92000001,0x61F80000,0x61F80000,0x92000001,0x92000001,0x1B80000,0x1B80000,0x1B80000,0x61F80000,0x61F80000,0x92000001,0x61F80000,0x61F80000,0x92000001,0x92000001,0x61F80000,
+0x61F80000,0x92000001,0x92000001,0x92000001,0x1580000,0x13C0000,0x1280000,0x3900000,0x1F00000,0x37FC0000,0x4BFC0000,0x6DFC0000,0x1740000,0x1B80000,0x37FC0000,0x92000001,0x37FC0000,0x1B80001,0x99FC0000,0xCDFC0000,0xDC000000,0x99FC0000,0xCDFC0000,0xDC000000,0xCDFC0000,0xDC000000,0xDC000000,0x99FC0000,0xCDFC0000,0xDC000000,0xCDFC0000,0xDC000000,
+0xDC000000,0xCDFC0000,0xDC000000,0xDC000000,0xDC000000,0x99FC0000,0xCDFC0000,0xDC000000,0xCDFC0000,0xDC000000,0xDC000000,0xCDFC0000,0xDC000000,0xDC000000,0xDC000000,0xCDFC0000,0xDC000000,0xDC000000,0xDC000000,0xDC000000,0x5BFC0000,0x1D80000,0x1D80000,0xADFC0000,0xC7F80000,0xD5F40000,0xDC000000,0xDC000000,0x81FC0000,0xB7FC0000,0xDBE80000,0xDC000000,
+0xBFFC0000,0xE4604E,0xFEC43D66,0xFEA027D6,0xDCA025C5,0xFE982F3A,0xFE7811D1,0xE6741046,0xFA5C14D2,0xD6540B09,0xB85C14D2,0xFE7437E7,0xFE40114C,0xE83C0D53,0xFE140B5E,0xDA140012,0xBA1C0B07,0xDA1025C6,0xC4000D55,0xAC001046,0x961025C7,0x154604A,0xFE082F3D,0xDC1425C6,0xF4002116,0xD2000F41,0xB4001656,0xD20034A5,0xBA001888,0xA800188D,0x92002BD7,0x2FFC604A,
+0xA0003D3D,0x960035A6,0x8400424A,0x7200604A,0xFEBC4462,0xFECC56D2,0xF8E05915,0xFE8028C4,0xFE501077,0xFE240126,0xE22400D9,0xD40800DB,0xFE9842FE,0xFE5C2552,0xE4000921,0xA800188D,0x1E8604A,0x12C25C5,0xFF0C13F5,0xFEEC090D,0xDCE40884,0xFEE812E1,0xFEB801D6,0xE0B80104,0xEAA40A69,0xD09801D5,0xB8A40A69,0x3BC25C5,0xFE700C8B,0xDC7C0884,0xFE140B5D,0xDA140011,
+0xB8400A69,0x63FC25C5,0xC4000D04,0xAC000FF5,0x960025C6,0x3BC25C5,0xFE700C8B,0xDC7C0884,0xFE140B5D,0xDA140011,0xB8400A69,0x63FC25C5,0xC4000D04,0xAC000FF5,0x960025C6,0x63FC25C5,0xC4000D04,0xAC000FF5,0x960025C6,0x960025C6,0xFF001CF1,0xFB242229,0xFD282208,0xFED41351,0xFE90091D,0xFE2C00B1,0xDE44000C,0xD4000099,0xFEF81D1D,0xFEC01208,0xE4000908,0xAC000FF5,
+0x3BFC25C5,0xA025C5,0xA025C5,0xA025C5,0xA025C5,0xFE680E06,0xFE680E06,0xFE680E06,0xC45C0A6A,0xC45C0A6A,0x925C0A6A,0xFE300B25,0xFE300B25,0xFE300B25,0xDA14000E,0xDA14000E,0x982801D6,0xA6100883,0xA6100883,0x8A0C0103,0x72100883,0xEC25C5,0xEC25C5,0xEC25C5,0xC0000E11,0xC0000E11,0x92000A76,0x98001033,0x98001033,0x800005C3,0x6E000B7B,0x1E425C5,
+0x1E425C5,0x6C001642,0x5C001743,0x4E0025C6,0xFE841892,0xFE8C201D,0xA025C5,0xFE5C0DCE,0xFE40049B,0xFE1C004D,0xF418004D,0xC410000B,0xFE6417AD,0xFE3C0C7D,0xD6000894,0x800005C3,0x15425C5,0xE40884,0xE40884,0xE40884,0xE40884,0xFEB0003D,0xFEB0003D,0xFEB0003D,0xB2A40001,0xB2A40001,0x92A40001,0x1540882,0x1540882,0x1540882,0xD0280001,0xD0280001,
+0x92640001,0x2FFC0882,0x2FFC0882,0x8A0000CA,0x72000882,0x1540882,0x1540882,0x1540882,0xD0280001,0xD0280001,0x92640001,0x2FFC0882,0x2FFC0882,0x8A0000CA,0x72000882,0x2FFC0882,0x2FFC0882,0x8A0000CA,0x72000882,0x72000882,0xFEBC05A5,0xF6DC0659,0xE40884,0xFE9803A9,0xFC6C0139,0xFE2C0008,0xE23C0001,0xC8000000,0xFAAC05E9,0xFE740371,0x1E80882,0x8A0000CA,
+0x1E80882,0x1700A69,0xFF5003D0,0xFF280001,0xDD280000,0x29FC0A69,0xFED80104,0xDCE00000,0x97F80A69,0xDC000000,0xB8000A69,0x29FC0A69,0xFED80104,0xDCE00000,0x97F80A69,0xDC000000,0xB8000A69,0x97F80A69,0xDC000000,0xB8000A69,0xB8000A69,0x29FC0A69,0xFED80104,0xDCE00000,0x97F80A69,0xDC000000,0xB8000A69,0x97F80A69,0xDC000000,0xB8000A69,0xB8000A69,0x97F80A69,
+0xDC000000,0xB8000A69,0xB8000A69,0xB8000A69,0xFF5008C9,0x1880A69,0xFF6C0908,0xFF200671,0xFED003FA,0xFE480074,0xDC540000,0xD4000080,0xF74C08C5,0xFF080601,0xE66C0001,0xB8000A69,0x7BFC0A69,0x5C0A69,0x5C0A69,0x5C0A69,0x5C0A69,0x5C0A69,0x5C0A69,0x5C0A69,0x5C0A69,0x5C0A69,0x5C0A69,0xE4140001,0xE4140001,0xE4140001,0xE4140001,0xE4140001,
+0xE4140001,0x74140001,0x74140001,0x74140001,0x50100002,0x840A69,0x840A69,0x840A69,0x840A69,0x840A69,0x840A69,0x680002EA,0x680002EA,0x680002EA,0x4C000119,0x10C0A69,0x10C0A69,0x10C0A69,0x3E0005AA,0x2C000A69,0xFE4C06CD,0x5C0A69,0x5C0A69,0xFE3C0349,0xFE28013D,0xFE180022,0xFE180022,0xBA140001,0xFE2005E4,0xFE1402E4,0x9A000001,0x680002EA,
+0xBC0A69,};
+static const uint32_t g_etc1_to_bc7_m6_table207[] = {
+0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x2300000,0x2300000,0x2300000,0x2300000,0x2300000,0x2300000,0x2300000,0x2300000,0x2300000,0x2300000,0x640000,
+0x640000,0x640000,0x640000,0x10000000,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x200001,0x240000,0x240000,0x240000,0x2300000,0x480000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0xB40000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,
+0x10C0000,0xBF80000,0xBF80000,0xBF80000,0x58000001,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0xBF80000,0xBF80000,0xBF80000,0x58000001,0xBF80000,0xBF80000,0xBF80000,0x58000001,0x58000001,0xC00000,0xB40000,0xB40000,0xD00000,0x2E00000,0xF40000,0xF40000,0x32C0000,0xD00000,0x2E00000,0x17C0000,0xBF80000,
+0x17C0000,0x1380000,0x1380000,0x1380000,0x1380000,0x1D00000,0x1D00000,0x1D00000,0x6DF80000,0x6DF80000,0x9A000001,0x1D00000,0x1D00000,0x1D00000,0x6DF80000,0x6DF80000,0x9A000001,0x6DF80000,0x6DF80000,0x9A000001,0x9A000001,0x1D00000,0x1D00000,0x1D00000,0x6DF80000,0x6DF80000,0x9A000001,0x6DF80000,0x6DF80000,0x9A000001,0x9A000001,0x6DF80000,
+0x6DF80000,0x9A000001,0x9A000001,0x9A000001,0x7680000,0x14C0000,0x1380000,0x1A80000,0xDFC0000,0x45FC0000,0x59FC0000,0x79F80000,0x1880000,0x1D00000,0x45FC0000,0x9A000001,0x45FC0000,0x1C80001,0xB1FC0000,0xD9FC0000,0xE4000000,0xB1FC0000,0xD9FC0000,0xE4000000,0xD9FC0000,0xE4000000,0xE4000000,0xB1FC0000,0xD9FC0000,0xE4000000,0xD9FC0000,0xE4000000,
+0xE4000000,0xD9FC0000,0xE4000000,0xE4000000,0xE4000000,0xB1FC0000,0xD9FC0000,0xE4000000,0xD9FC0000,0xE4000000,0xE4000000,0xD9FC0000,0xE4000000,0xE4000000,0xE4000000,0xD9FC0000,0xE4000000,0xE4000000,0xE4000000,0xE4000000,0x81FC0000,0x1E80000,0x1E80000,0xC1FC0000,0xD5F80000,0xDFF80000,0xE4000000,0xE4000000,0x9FFC0000,0xC9FC0000,0xE3F80000,0xE4000000,
+0xCFFC0000,0xF4604E,0xFED03EDE,0xFEB828D6,0xE4B025C5,0xFEB03142,0xFE8813AF,0xEE841046,0xFE6C14EA,0xDE640B09,0xC06C14D2,0xFE8C397F,0xFE58135C,0xF04C0D53,0xFE2C0C2E,0xE2240012,0xC22C0B07,0xE22025C6,0xCE080D51,0xB4101046,0x9E2025C7,0x16C604A,0xFE2C30C9,0xE42425C6,0xFA001F7A,0xDE000DA9,0xBC00157A,0xE20032CB,0xC60015F8,0xAE00161D,0x98002A5B,0x3BFC604A,
+0xAC003B6D,0x9C003362,0x8A0040B6,0x7A00604A,0xFED045E7,0xFEEC56D6,0xFEEC5931,0xFE982B12,0xFE6812F6,0xFE38023E,0xEA3400D9,0xDC1800DB,0xFEB4443B,0xFE802784,0xEE0008BF,0xAE00161D,0x7FC604A,0x13C25C5,0xFF1814ED,0xFEFC0994,0xE4F40884,0xFEF413E5,0xFECC02E0,0xE8C80104,0xF2B40A69,0xD8A801D5,0xC0B40A69,0x1D425C5,0xFE940D8B,0xE48C0884,0xFE380C01,0xE2240011,
+0xC0500A69,0x6FFC25C5,0xD0000C54,0xB2000F59,0x9E0025C6,0x1D425C5,0xFE940D8B,0xE48C0884,0xFE380C01,0xE2240011,0xC0500A69,0x6FFC25C5,0xD0000C54,0xB2000F59,0x9E0025C6,0x6FFC25C5,0xD0000C54,0xB2000F59,0x9E0025C6,0x9E0025C6,0xFF141D5E,0xFF2C2251,0xFF2C2274,0xFEEC1476,0xFEA40A79,0xFE480164,0xE654000C,0xE0000062,0xFF081D9A,0xFEC812EA,0xEE0008BB,0xB2000F59,
+0x49FC25C5,0xB025C5,0xB025C5,0xB025C5,0xB025C5,0xFE800E8E,0xFE800E8E,0xFE800E8E,0xCC6C0A6A,0xCC6C0A6A,0x9A6C0A6A,0xFE440BA3,0xFE440BA3,0xFE440BA3,0xE224000E,0xE224000E,0xA03801D6,0xAE200883,0xAE200883,0x921C0103,0x7A200883,0x10425C5,0x10425C5,0x10425C5,0xD2000D0D,0xD2000D0D,0x9A080A6A,0xA8000EC8,0xA8000EC8,0x8C000443,0x74000A83,0x7FC25C5,
+0x7FC25C5,0x7800151A,0x66001632,0x560025C6,0xFE901926,0xFCA82036,0xB025C5,0xFE700EB6,0xFE540563,0xFE34009A,0xFC28004D,0xCC20000B,0xFE78181A,0xFE500D1D,0xE4040883,0x8C000443,0x17425C5,0xF40884,0xF40884,0xF40884,0xF40884,0xFEBC0061,0xFEBC0061,0xFEBC0061,0xBAB40001,0xBAB40001,0x9AB40001,0x16C0882,0x16C0882,0x16C0882,0xD8380001,0xD8380001,
+0x9A740001,0x3BFC0882,0x3BFC0882,0x96000092,0x7A000882,0x16C0882,0x16C0882,0x16C0882,0xD8380001,0xD8380001,0x9A740001,0x3BFC0882,0x3BFC0882,0x96000092,0x7A000882,0x3BFC0882,0x3BFC0882,0x96000092,0x7A000882,0x7A000882,0xFED805B2,0xFEEC0659,0xF40884,0xFEB403F5,0xFE80016D,0xFE480020,0xEA4C0001,0xD0100000,0xFEB40611,0xFE98039D,0x7FC0882,0x96000092,
+0x7FC0882,0x1800A69,0xFF5C0454,0xFF380024,0xE5380000,0x41FC0A69,0xFEF00184,0xE4F00000,0xA1FC0A69,0xE40C0000,0xC0000A69,0x41FC0A69,0xFEF00184,0xE4F00000,0xA1FC0A69,0xE40C0000,0xC0000A69,0xA1FC0A69,0xE40C0000,0xC0000A69,0xC0000A69,0x41FC0A69,0xFEF00184,0xE4F00000,0xA1FC0A69,0xE40C0000,0xC0000A69,0xA1FC0A69,0xE40C0000,0xC0000A69,0xC0000A69,0xA1FC0A69,
+0xE40C0000,0xC0000A69,0xC0000A69,0xC0000A69,0xFD680908,0x19C0A69,0xF77C094D,0xFF4006CD,0xFEE80484,0xFE7000E8,0xE4640000,0xE0000061,0xFF5C08C5,0xFF200681,0xEE7C0001,0xC0000A69,0x89FC0A69,0x6C0A69,0x6C0A69,0x6C0A69,0x6C0A69,0x6C0A69,0x6C0A69,0x6C0A69,0x6C0A69,0x6C0A69,0x6C0A69,0xEC240001,0xEC240001,0xEC240001,0xEC240001,0xEC240001,
+0xEC240001,0x7C240001,0x7C240001,0x7C240001,0x58200002,0x9C0A69,0x9C0A69,0x9C0A69,0x9C0A69,0x9C0A69,0x9C0A69,0x74000232,0x74000232,0x74000232,0x58000091,0x13C0A69,0x13C0A69,0x13C0A69,0x44000502,0x34000A69,0xF65C070A,0x6C0A69,0x6C0A69,0xFE4C0372,0xFE3C016D,0xFE2C003D,0xFE2C003D,0xC2240001,0xFE3C05E9,0xFA2C0322,0xA2100001,0x74000232,
+0xE00A69,};
+static const uint32_t g_etc1_to_bc7_m6_table208[] = {
+0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x4C0000,0x4C0000,0x4C0000,0x4C0000,0x4C0000,0x4C0000,0x4C0000,0x4C0000,0x4C0000,0x4C0000,0x980000,
+0x980000,0x980000,0x980000,0x18000001,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x340000,0x380000,0x380000,0x380000,0x4C0000,0x6C0000,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0xC40001,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,
+0x3240000,0x17FC0000,0x17FC0000,0x17FC0000,0x62000000,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,0x3240000,0x17FC0000,0x17FC0000,0x17FC0000,0x62000000,0x17FC0000,0x17FC0000,0x17FC0000,0x62000000,0x62000000,0xD40000,0xC40001,0xC40001,0x4E40000,0xF80000,0x10C0000,0x10C0000,0x14C0000,0x4E40000,0xF80000,0x1A40000,0x17FC0000,
+0x1A40000,0x1480001,0x1480001,0x1480001,0x1480001,0x3E80000,0x3E80000,0x3E80000,0x79FC0000,0x79FC0000,0xA4000000,0x3E80000,0x3E80000,0x3E80000,0x79FC0000,0x79FC0000,0xA4000000,0x79FC0000,0x79FC0000,0xA4000000,0xA4000000,0x3E80000,0x3E80000,0x3E80000,0x79FC0000,0x79FC0000,0xA4000000,0x79FC0000,0x79FC0000,0xA4000000,0xA4000000,0x79FC0000,
+0x79FC0000,0xA4000000,0xA4000000,0xA4000000,0x1800000,0x1600000,0x1480001,0x1C00000,0x23FC0000,0x57FC0000,0x69F80000,0x85F80000,0x39C0000,0x3E80000,0x57FC0000,0xA4000000,0x57FC0000,0x1DC0000,0xCDFC0000,0xE7F80000,0xEC000001,0xCDFC0000,0xE7F80000,0xEC000001,0xE7F80000,0xEC000001,0xEC000001,0xCDFC0000,0xE7F80000,0xEC000001,0xE7F80000,0xEC000001,
+0xEC000001,0xE7F80000,0xEC000001,0xEC000001,0xEC000001,0xCDFC0000,0xE7F80000,0xEC000001,0xE7F80000,0xEC000001,0xEC000001,0xE7F80000,0xEC000001,0xEC000001,0xEC000001,0xE7F80000,0xEC000001,0xEC000001,0xEC000001,0xEC000001,0xADFC0000,0x1FC0000,0x1FC0000,0xD7FC0000,0xE3FC0000,0xEBF00000,0xEC000001,0xEC000001,0xC1FC0000,0xDBFC0000,0xEDEC0000,0xEC000001,
+0xDFFC0000,0x108604A,0xFEE840B6,0xFECC2A5B,0xECC025C7,0xFEC43362,0xFEA0161D,0xF6941046,0xFE84157A,0xE8780B07,0xC87C14D2,0xFEA43B6D,0xFE7015F8,0xFA600D51,0xFE400DA9,0xEC380012,0xCC400B09,0xEC3425C6,0xD81C0D53,0xBC201046,0xA63425C5,0x188604A,0xFE3832CB,0xEC3825C6,0xFE081F7A,0xE8000C2E,0xC60014EA,0xE80030C9,0xD200135C,0xBA0013AF,0xA20028D6,0x49F8604A,
+0xB800397F,0xA6003142,0x96003EDE,0x8200604E,0xFEE44782,0xF90057DA,0xFB0459DA,0xFEAC2DF6,0xFE7C160E,0xFE4803FF,0xF24400DB,0xE42800D9,0xFED0463D,0xFE902A56,0xF81008BB,0xBA0013AF,0x19FC604A,0x15025C6,0xFF301632,0xFF140A83,0xED080883,0xFF0C151A,0xFEE40443,0xF0D80103,0xFAC40A6A,0xE2BC01D6,0xC8C40A6A,0x1F025C5,0xFEAC0EC8,0xECA00883,0xFE580D0D,0xEC38000E,
+0xC8600A6A,0x7DF825C5,0xDC000BA3,0xBE000E8E,0xA60025C5,0x1F025C5,0xFEAC0EC8,0xECA00883,0xFE580D0D,0xEC38000E,0xC8600A6A,0x7DF825C5,0xDC000BA3,0xBE000E8E,0xA60025C5,0x7DF825C5,0xDC000BA3,0xBE000E8E,0xA60025C5,0xA60025C5,0xFF341E13,0xFD4822AA,0xFF4C228E,0xFF0015CE,0xFEBC0C34,0xFE70027E,0xEE64000B,0xE800004D,0xFF181E3E,0xFEDC1481,0xFC00088B,0xBE000E8E,
+0x5BFC25C5,0xC025C6,0xC025C6,0xC025C6,0xC025C6,0xFE980F59,0xFE980F59,0xFE980F59,0xD67C0A69,0xD67C0A69,0xA47C0A69,0xFE5C0C54,0xFE5C0C54,0xFE5C0C54,0xEA340011,0xEA340011,0xAA4C01D5,0xB6340884,0xB6340884,0x9A2C0104,0x82340884,0x12025C5,0x12025C5,0x12025C5,0xE2000C01,0xE2000C01,0xA4180A69,0xB4000D8B,0xB4000D8B,0x980002E0,0x80000994,0x15F825C5,
+0x15F825C5,0x840013E5,0x720014ED,0x600025C5,0xFEA019B4,0xF6BC20B2,0xC025C6,0xFE880F9E,0xFE6C0669,0xFE480126,0xFE3C0062,0xD430000C,0xFE9018F2,0xFE680E59,0xEC180882,0x980002E0,0x19C25C5,0x1080882,0x1080882,0x1080882,0x1080882,0xFED00092,0xFED00092,0xFED00092,0xC4C40001,0xC4C40001,0xA4C40001,0x1880882,0x1880882,0x1880882,0xE04C0001,0xE04C0001,
+0xA4840001,0x49F80882,0x49F80882,0xA0000061,0x82000884,0x1880882,0x1880882,0x1880882,0xE04C0001,0xE04C0001,0xA4840001,0x49F80882,0x49F80882,0xA0000061,0x82000884,0x49F80882,0x49F80882,0xA0000061,0x82000884,0x82000884,0xFAEC05E9,0xF9000692,0x1080882,0xFEC4042A,0xFE9801A9,0xFE64003D,0xF65C0000,0xD8240001,0xFED00628,0xFEA403E8,0x19FC0882,0xA0000061,
+0x19FC0882,0x1940A69,0xFF740502,0xFF4C0091,0xED480002,0x5BFC0A69,0xFF140232,0xED040001,0xAFFC0A69,0xEC240001,0xC8000A69,0x5BFC0A69,0xFF140232,0xED040001,0xAFFC0A69,0xEC240001,0xC8000A69,0xAFFC0A69,0xEC240001,0xC8000A69,0xC8000A69,0x5BFC0A69,0xFF140232,0xED040001,0xAFFC0A69,0xEC240001,0xC8000A69,0xAFFC0A69,0xEC240001,0xC8000A69,0xC8000A69,0xAFFC0A69,
+0xEC240001,0xC8000A69,0xC8000A69,0xC8000A69,0xFF780910,0x1AC0A69,0xFF8C0951,0xFF580749,0xFF10052A,0xFE98018D,0xEC780001,0xE800003D,0xFF70090A,0xFF4006E5,0xF88C0000,0xC8000A69,0x9BFC0A69,0x7C0A69,0x7C0A69,0x7C0A69,0x7C0A69,0x7C0A69,0x7C0A69,0x7C0A69,0x7C0A69,0x7C0A69,0x7C0A69,0xF6340000,0xF6340000,0xF6340000,0xF6340000,0xF6340000,
+0xF6340000,0x86340000,0x86340000,0x86340000,0x62340000,0xB80A69,0xB80A69,0xB80A69,0xB80A69,0xB80A69,0xB80A69,0x86000184,0x86000184,0x86000184,0x62000024,0x1740A69,0x1740A69,0x1740A69,0x50000454,0x3E000A69,0xFE6C0710,0x7C0A69,0x7C0A69,0xFE5803B5,0xFE5001A5,0xFE3C0061,0xFE3C0061,0xCC340000,0xFA500622,0xFE3C0355,0xAC200000,0x86000184,
+0x1080A69,};
+static const uint32_t g_etc1_to_bc7_m6_table209[] = {
+0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0xCC0000,
+0xCC0000,0xCC0000,0xCC0000,0x20000001,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x480000,0x480000,0x480000,0x640000,0x900000,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0xD40001,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x33C0000,
+0x33C0000,0x23FC0000,0x23FC0000,0x23FC0000,0x6A000000,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x33C0000,0x23FC0000,0x23FC0000,0x23FC0000,0x6A000000,0x23FC0000,0x23FC0000,0x23FC0000,0x6A000000,0x6A000000,0xE40000,0xD40001,0xD40001,0xF80000,0x10C0000,0x1240000,0x1240000,0x1680000,0xF80000,0x10C0000,0x1C80000,0x23FC0000,
+0x1C80000,0x1580001,0x1580001,0x1580001,0x1580001,0x7FC0000,0x7FC0000,0x7FC0000,0x85FC0000,0x85FC0000,0xAC000000,0x7FC0000,0x7FC0000,0x7FC0000,0x85FC0000,0x85FC0000,0xAC000000,0x85FC0000,0x85FC0000,0xAC000000,0xAC000000,0x7FC0000,0x7FC0000,0x7FC0000,0x85FC0000,0x85FC0000,0xAC000000,0x85FC0000,0x85FC0000,0xAC000000,0xAC000000,0x85FC0000,
+0x85FC0000,0xAC000000,0xAC000000,0xAC000000,0x5900000,0x1700000,0x1580001,0x3D40000,0x37FC0000,0x65FC0000,0x75FC0000,0x91F40000,0x3B00000,0x7FC0000,0x65FC0000,0xAC000000,0x65FC0000,0x1EC0000,0xE5FC0000,0xF3F80000,0xF4000001,0xE5FC0000,0xF3F80000,0xF4000001,0xF3F80000,0xF4000001,0xF4000001,0xE5FC0000,0xF3F80000,0xF4000001,0xF3F80000,0xF4000001,
+0xF4000001,0xF3F80000,0xF4000001,0xF4000001,0xF4000001,0xE5FC0000,0xF3F80000,0xF4000001,0xF3F80000,0xF4000001,0xF4000001,0xF3F80000,0xF4000001,0xF4000001,0xF4000001,0xF3F80000,0xF4000001,0xF4000001,0xF4000001,0xF4000001,0xD5FC0000,0x77FC0000,0x77FC0000,0xEBFC0000,0xF1FC0000,0xF5F00000,0xF4000001,0xF4000001,0xDFFC0000,0xEDFC0000,0xF5FC0000,0xF4000001,
+0xEFFC0000,0x118604A,0xFEF4424A,0xFED82BD7,0xF4D025C7,0xFED035A6,0xFEAC188D,0xFEA41046,0xFE941656,0xF0880B07,0xD08C14D2,0xFEBC3D3D,0xFE881888,0xFE740D55,0xFE580F41,0xF4480012,0xD4500B09,0xF44425C6,0xE02C0D53,0xC4301046,0xAE4425C5,0x1A0604A,0xFE5834A5,0xF44825C6,0xFE142116,0xF4000B5E,0xD00414D2,0xFA002F3D,0xDE00114C,0xC20011D1,0xAE0027D6,0x55F8604A,
+0xC40037E7,0xB2002F3A,0x9C003D66,0x8A00604E,0xFEF44912,0xFF0C57EA,0xFF0C5A1A,0xFEC4307A,0xFE901902,0xFE5C05EA,0xFA5400DB,0xEC3800D9,0xFEDC478F,0xFEB02D65,0xFE2008C1,0xC20011D1,0x27FC604A,0x16025C6,0xFF441743,0xFF200B7B,0xF5180883,0xFF241642,0xFEF005C3,0xF8E80103,0xFED80A76,0xEACC01D6,0xD0D40A6A,0xDFC25C5,0xFECC1033,0xF4B00883,0xFE7C0E11,0xF448000E,
+0xD0700A6A,0x89F825C5,0xE6000B25,0xCA000E06,0xAE0025C5,0xDFC25C5,0xFECC1033,0xF4B00883,0xFE7C0E11,0xF448000E,0xD0700A6A,0x89F825C5,0xE6000B25,0xCA000E06,0xAE0025C5,0x89F825C5,0xE6000B25,0xCA000E06,0xAE0025C5,0xAE0025C5,0xFF3C1EC2,0xFF4C22FE,0xF75C2313,0xFF1416C1,0xFEDC0DD4,0xFE8403CB,0xF674000B,0xF010004D,0xFF341F0E,0xFF0415B5,0xFE1408A6,0xCA000E06,
+0x69FC25C5,0xD025C6,0xD025C6,0xD025C6,0xD025C6,0xFEA40FF5,0xFEA40FF5,0xFEA40FF5,0xDE8C0A69,0xDE8C0A69,0xAC8C0A69,0xFE740D04,0xFE740D04,0xFE740D04,0xF2440011,0xF2440011,0xB25C01D5,0xBE440884,0xBE440884,0xA23C0104,0x8A440884,0x13825C5,0x13825C5,0x13825C5,0xF4000B5D,0xF4000B5D,0xAC280A69,0xC6000C8B,0xC6000C8B,0xA20001D6,0x8800090D,0x21F825C5,
+0x21F825C5,0x8A0012E1,0x780013F5,0x680025C5,0xFEBC1A59,0xFECC20B2,0xD025C6,0xFE981069,0xFE800755,0xFE5C01A9,0xFE540099,0xDC40000C,0xFEA01966,0xFE740F25,0xF4280882,0xA20001D6,0x1BC25C5,0x1180882,0x1180882,0x1180882,0x1180882,0xFEE800CA,0xFEE800CA,0xFEE800CA,0xCCD40001,0xCCD40001,0xACD40001,0x1A00882,0x1A00882,0x1A00882,0xE85C0001,0xE85C0001,
+0xAC940001,0x55F80882,0x55F80882,0xA600003D,0x8A000884,0x1A00882,0x1A00882,0x1A00882,0xE85C0001,0xE85C0001,0xAC940001,0x55F80882,0x55F80882,0xA600003D,0x8A000884,0x55F80882,0x55F80882,0xA600003D,0x8A000884,0x8A000884,0xFEF40611,0xFF0C069A,0x1180882,0xFEDC0451,0xFEAC01ED,0xFE7C0064,0xFE6C0000,0xE0340001,0xF8EC0659,0xFEC40422,0x27FC0882,0xA600003D,
+0x27FC0882,0x1A40A69,0xFF8005AA,0xFF640119,0xF5580002,0x75FC0A69,0xFF2C02EA,0xF5140001,0xBBFC0A69,0xF4340001,0xD0000A69,0x75FC0A69,0xFF2C02EA,0xF5140001,0xBBFC0A69,0xF4340001,0xD0000A69,0xBBFC0A69,0xF4340001,0xD0000A69,0xD0000A69,0x75FC0A69,0xFF2C02EA,0xF5140001,0xBBFC0A69,0xF4340001,0xD0000A69,0xBBFC0A69,0xF4340001,0xD0000A69,0xD0000A69,0xBBFC0A69,
+0xF4340001,0xD0000A69,0xD0000A69,0xD0000A69,0xFD90094D,0x1C00A69,0xF9A00992,0xFF6C0794,0xFF3C05C4,0xFEC80235,0xF4880001,0xF2000022,0xF98C094D,0xFF58076D,0xFEA00004,0xD0000A69,0xA9FC0A69,0x8C0A69,0x8C0A69,0x8C0A69,0x8C0A69,0x8C0A69,0x8C0A69,0x8C0A69,0x8C0A69,0x8C0A69,0x8C0A69,0xFE440000,0xFE440000,0xFE440000,0xFE440000,0xFE440000,
+0xFE440000,0x8E440000,0x8E440000,0x8E440000,0x6A440000,0xD00A69,0xD00A69,0xD00A69,0xD00A69,0xD00A69,0xD00A69,0x92000104,0x92000104,0x92000104,0x6A000001,0x1A40A69,0x1A40A69,0x1A40A69,0x560003D0,0x46000A69,0xF8800745,0x8C0A69,0x8C0A69,0xFE6803E8,0xFE6401E1,0xFE540080,0xFE540080,0xD4440000,0xFE580652,0xFE50037A,0xB4300000,0x92000104,
+0x1280A69,};
+static const uint32_t g_etc1_to_bc7_m6_table210[] = {
+0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0x7C0000,0xFC0000,
+0xFC0000,0xFC0000,0xFC0000,0x28000001,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x540000,0x4580000,0x4580000,0x4580000,0x7C0000,0xB00000,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0xE40001,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,
+0x1540000,0x2FFC0000,0x2FFC0000,0x2FFC0000,0x72000000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x1540000,0x2FFC0000,0x2FFC0000,0x2FFC0000,0x72000000,0x2FFC0000,0x2FFC0000,0x2FFC0000,0x72000000,0x72000000,0x2F40000,0xE40001,0xE40001,0x10C0000,0x1200000,0x1380000,0x1380000,0x3800000,0x10C0000,0x1200000,0x1E80000,0x2FFC0000,
+0x1E80000,0x1680001,0x1680001,0x1680001,0x1680001,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x91FC0000,0x91FC0000,0xB4000000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x91FC0000,0x91FC0000,0xB4000000,0x91FC0000,0x91FC0000,0xB4000000,0xB4000000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x91FC0000,0x91FC0000,0xB4000000,0x91FC0000,0x91FC0000,0xB4000000,0xB4000000,0x91FC0000,
+0x91FC0000,0xB4000000,0xB4000000,0xB4000000,0x1A40000,0x9800000,0x1680001,0x1EC0000,0x4BFC0000,0x75FC0000,0x83FC0000,0x9BF80000,0x3C40000,0x1FFC0000,0x75FC0000,0xB4000000,0x75FC0000,0x1FC0000,0xFDFC0000,0xFFF80000,0xFC000001,0xFDFC0000,0xFFF80000,0xFC000001,0xFFF80000,0xFC000001,0xFC000001,0xFDFC0000,0xFFF80000,0xFC000001,0xFFF80000,0xFC000001,
+0xFC000001,0xFFF80000,0xFC000001,0xFC000001,0xFC000001,0xFDFC0000,0xFFF80000,0xFC000001,0xFFF80000,0xFC000001,0xFC000001,0xFFF80000,0xFC000001,0xFC000001,0xFC000001,0xFFF80000,0xFC000001,0xFC000001,0xFC000001,0xFC000001,0xFDFC0000,0xF7FC0000,0xF7FC0000,0xFDFC0000,0xFFF80000,0xFFF00000,0xFC000001,0xFC000001,0xFDFC0000,0xFDFC0000,0xFFD00000,0xFC000001,
+0xFFF80000,0x128604A,0xFF004416,0xFEF02D9F,0xFCE025C7,0xFEE837DE,0xFEC01B37,0xFEB010C2,0xFEAC17A6,0xF8980B07,0xD89C14D2,0xFED03EDE,0xFEA01B58,0xFE8C0DD5,0xFE701139,0xFC580012,0xDC600B09,0xFC5425C6,0xE83C0D53,0xCC401046,0xB65425C5,0x1B8604A,0xFE7C3691,0xFC5825C6,0xFE2C235E,0xFC040B0A,0xD81414D2,0xFC002E6B,0xE8000F61,0xCC001023,0xB40026F6,0x61F8604A,
+0xCA00364F,0xB8002D3E,0xA6003C09,0x9200604E,0xFF004A76,0xF92058E2,0xFB245AA3,0xFED432EA,0xFEA81C14,0xFE7C0838,0xFE6800F6,0xF44800D9,0xFEF0492C,0xFEC02FD3,0xFE38092D,0xCC001023,0x37FC604A,0x17025C6,0xFF501853,0xFF380CC3,0xFD280883,0xFF301782,0xFF080763,0xFEF40113,0xFEF00AD6,0xF2DC01D6,0xD8E40A6A,0x25FC25C5,0xFEE4118B,0xFCC00883,0xFEA00F45,0xFC58000E,
+0xD8800A6A,0x95F825C5,0xEC000A95,0xD0000D6A,0xB60025C5,0x25FC25C5,0xFEE4118B,0xFCC00883,0xFEA00F45,0xFC58000E,0xD8800A6A,0x95F825C5,0xEC000A95,0xD0000D6A,0xB60025C5,0x95F825C5,0xEC000A95,0xD0000D6A,0xB60025C5,0xB60025C5,0xFF501F35,0xFD68232A,0xFF6C2313,0xFF30183D,0xFEE80F6B,0xFEAC055A,0xFE84000B,0xF820004D,0xFF441F99,0xFF101711,0xFE34092B,0xD0000D6A,
+0x79FC25C5,0xE025C6,0xE025C6,0xE025C6,0xE025C6,0xFEB010C1,0xFEB010C1,0xFEB010C1,0xE69C0A69,0xE69C0A69,0xB49C0A69,0xFE8C0DD4,0xFE8C0DD4,0xFE8C0DD4,0xFA540011,0xFA540011,0xBA6C01D5,0xC6540884,0xC6540884,0xAA4C0104,0x92540884,0x15025C5,0x15025C5,0x15025C5,0xFC040B09,0xFC040B09,0xB4380A69,0xD2000BA3,0xD2000BA3,0xAE00010E,0x920008A8,0x2DF825C5,
+0x2DF825C5,0x960011E1,0x840012E5,0x700025C5,0xFECC1ACA,0xF6DC212D,0xE025C6,0xFEAC116D,0xFE88084E,0xFE700251,0xFE6800F5,0xE450000C,0xFEB419D9,0xFE901016,0xFC380882,0xAE00010E,0x1E025C5,0x1280882,0x1280882,0x1280882,0x1280882,0xFEF40112,0xFEF40112,0xFEF40112,0xD4E40001,0xD4E40001,0xB4E40001,0x1B80882,0x1B80882,0x1B80882,0xF06C0001,0xF06C0001,
+0xB4A40001,0x61F80882,0x61F80882,0xB200001D,0x92000884,0x1B80882,0x1B80882,0x1B80882,0xF06C0001,0xF06C0001,0xB4A40001,0x61F80882,0x61F80882,0xB200001D,0x92000884,0x61F80882,0x61F80882,0xB200001D,0x92000884,0x92000884,0xFF100620,0xF92006CD,0x1280882,0xFCF404B1,0xFEC00239,0xFE9400AA,0xFE84000A,0xE8440001,0xFEF8065D,0xFEDC0451,0x37FC0882,0xB200001D,
+0x37FC0882,0x1B40A69,0xFF980652,0xFF7C01E1,0xFD680002,0x8DFC0A69,0xFF4C03D4,0xFD240001,0xC7FC0A69,0xFC440001,0xD8000A69,0x8DFC0A69,0xFF4C03D4,0xFD240001,0xC7FC0A69,0xFC440001,0xD8000A69,0xC7FC0A69,0xFC440001,0xD8000A69,0xD8000A69,0x8DFC0A69,0xFF4C03D4,0xFD240001,0xC7FC0A69,0xFC440001,0xD8000A69,0xC7FC0A69,0xFC440001,0xD8000A69,0xD8000A69,0xC7FC0A69,
+0xFC440001,0xD8000A69,0xD8000A69,0xD8000A69,0xFDA40992,0x1D00A69,0xFFAC099A,0xFF840812,0xFF500668,0xFEF0031D,0xFC980001,0xFA000012,0xFF980951,0xFF7007FD,0xFED00049,0xD8000A69,0xB9FC0A69,0x9C0A69,0x9C0A69,0x9C0A69,0x9C0A69,0x9C0A69,0x9C0A69,0x9C0A69,0x9C0A69,0x9C0A69,0x9C0A69,0xFC580008,0xFC580008,0xFC580008,0xFC580008,0xFC580008,
+0xFC580008,0x96540000,0x96540000,0x96540000,0x72540000,0xE80A69,0xE80A69,0xE80A69,0xE80A69,0xE80A69,0xE80A69,0xA2000092,0xA2000092,0xA2000092,0x720C0000,0x1D80A69,0x1D80A69,0x1D80A69,0x60000355,0x4E000A69,0xFE8C0751,0x9C0A69,0x9C0A69,0xFC800424,0xFE6C0220,0xFE6000B4,0xFE6000B4,0xDC540000,0xFE740659,0xFE6403CA,0xBC400000,0xA2000092,
+0x14C0A69,};
+static const uint32_t g_etc1_to_bc7_m6_table211[] = {
+0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x940000,0x12C0000,
+0x12C0000,0x12C0000,0x12C0000,0x30000001,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0x640000,0xC680000,0xC680000,0xC680000,0x940000,0xD40000,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0xF40001,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,
+0x16C0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x16C0000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x3BFC0000,0x3BFC0000,0x3BFC0000,0x7A000000,0x7A000000,0xB040000,0xF40001,0xF40001,0x51C0000,0x1340000,0x34C0000,0x34C0000,0x19C0000,0x51C0000,0x1340000,0x7FC0000,0x3BFC0000,
+0x7FC0000,0x1780001,0x1780001,0x1780001,0x1780001,0x37FC0000,0x37FC0000,0x37FC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x37FC0000,0x37FC0000,0x37FC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x9DFC0000,0x9DFC0000,0xBC000000,0xBC000000,0x37FC0000,0x37FC0000,0x37FC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x9DFC0000,0x9DFC0000,0xBC000000,0xBC000000,0x9DFC0000,
+0x9DFC0000,0xBC000000,0xBC000000,0xBC000000,0x1B80000,0x1940000,0x1780001,0x9FC0000,0x5DFC0000,0x83FC0000,0x91FC0000,0xA5FC0000,0x3D80000,0x37FC0000,0x83FC0000,0xBC000000,0x83FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1345AA3,0xFF18414F,0xFEFC2CFE,0xFEF025C6,0xFEF43543,0xFED41B46,0xFEC41162,0xFEB81647,0xFAA80AB6,0xDCAC12ED,0xFEDC3B5B,0xFEAC1B25,0xFE980E98,0xFE88100A,0xFE680015,0xDE700938,0xFE64220B,0xEA4C0C2A,0xD24C0DC5,0xBC642208,0x1C85AA3,0xFE88351E,0xFE7025C5,0xFE3821ED,0xFE140B45,0xDC2812ED,0xFE082A18,0xEE000CC4,0xD4000C44,0xBA00228D,0x69FC5AA3,
+0xD6003266,0xBE0027E1,0xAC00360C,0x9A005AA5,0xFF0C469D,0xFF2C536D,0xFF2C555E,0xFEEC313E,0xFEBC1BA5,0xFE9008D1,0xFE7C0184,0xF85C0071,0xFEF84551,0xFED02DDA,0xFE50093C,0xD4000C44,0x41FC5AA3,0x178220B,0xFF5C166E,0xFF400C63,0xFF380882,0xFF441505,0xFF20071A,0xFF0C015A,0xFEFC092D,0xF4EC0141,0xDCF40885,0x37FC2208,0xFEFC1086,0xFED80882,0xFEB80D86,0xFE740001,
+0xDE940884,0x9DFC2208,0xF2000974,0xD6000A9D,0xBC002208,0x37FC2208,0xFEFC1086,0xFED80882,0xFEB80D86,0xFE740001,0xDE940884,0x9DFC2208,0xF2000974,0xD6000A9D,0xBC002208,0x9DFC2208,0xF2000974,0xD6000A9D,0xBC002208,0xBC002208,0xFF581C81,0xFF6C1FAD,0xFF6C1FDA,0xFF401614,0xFEFC0E52,0xFEC00532,0xFEA00022,0xFC40001E,0xFD581C9A,0xFF24153E,0xFE58092B,0xD6000A9D,
+0x83FC2208,0xF025C6,0xF025C6,0xF025C6,0xF025C6,0xFEC41162,0xFEC41162,0xFEC41162,0xEEAC0A69,0xEEAC0A69,0xBCAC0A69,0xFE980E98,0xFE980E98,0xFE980E98,0xFE680015,0xFE680015,0xC27C01D5,0xCE640884,0xCE640884,0xB25C0104,0x9A640884,0x16825C5,0x16825C5,0x16825C5,0xFE140B45,0xFE140B45,0xBC480A69,0xE2000AD4,0xE2000AD4,0xBA000086,0x9A000885,0x39F825C5,
+0x39F825C5,0x9C001115,0x8A0011FD,0x780025C5,0xFED81B58,0xFEEC212D,0xF025C6,0xFEBC1244,0xFE9C0952,0xFE7C0334,0xFE7C0184,0xEC60000C,0xFEBC1A8C,0xFEA41121,0xFE500893,0xBA000086,0x3FC25C5,0x1380882,0x1380882,0x1380882,0x1380882,0xFF0C015A,0xFF0C015A,0xFF0C015A,0xDCF40001,0xDCF40001,0xBCF40001,0x1D00882,0x1D00882,0x1D00882,0xF87C0001,0xF87C0001,
+0xBCB40001,0x6DF80882,0x6DF80882,0xBA00000D,0x9A000884,0x1D00882,0x1D00882,0x1D00882,0xF87C0001,0xF87C0001,0xBCB40001,0x6DF80882,0x6DF80882,0xBA00000D,0x9A000884,0x6DF80882,0x6DF80882,0xBA00000D,0x9A000884,0x9A000884,0xFF200659,0xFF2C06D9,0x1380882,0xFD0404E4,0xFED4028D,0xFEB000E1,0xFEA00022,0xF0540001,0xFD100692,0xFEE80492,0x45FC0882,0xBA00000D,
+0x45FC0882,0x1BC0882,0xFFA4053D,0xFF88019A,0xFF780001,0x9BFC0882,0xFF640335,0xFF380001,0xCFF80882,0xFE6C0000,0xDC000884,0x9BFC0882,0xFF640335,0xFF380001,0xCFF80882,0xFE6C0000,0xDC000884,0xCFF80882,0xFE6C0000,0xDC000884,0xDC000884,0x9BFC0882,0xFF640335,0xFF380001,0xCFF80882,0xFE6C0000,0xDC000884,0xCFF80882,0xFE6C0000,0xDC000884,0xDC000884,0xCFF80882,
+0xFE6C0000,0xDC000884,0xDC000884,0xDC000884,0xFDB007C1,0x5D80882,0xF5B80802,0xFF94069A,0xFF68053D,0xFF1802A1,0xFEB80000,0xFE0C0000,0xFDA807C1,0xFF880665,0xFEF00049,0xDC000884,0xC1FC0882,0xAC0A69,0xAC0A69,0xAC0A69,0xAC0A69,0xAC0A69,0xAC0A69,0xAC0A69,0xAC0A69,0xAC0A69,0xAC0A69,0xFE680014,0xFE680014,0xFE680014,0xFE680014,0xFE680014,
+0xFE680014,0x9E640000,0x9E640000,0x9E640000,0x7A640000,0x1000A69,0x1000A69,0x1000A69,0x1000A69,0x1000A69,0x1000A69,0xAE00004A,0xAE00004A,0xAE00004A,0x7A1C0000,0x5F80A69,0x5F80A69,0x5F80A69,0x6C0002D5,0x56000A69,0xF8A00784,0xAC0A69,0xAC0A69,0xFE900455,0xFE800254,0xFE7800DD,0xFE7800DD,0xE4640000,0xFA880692,0xFE7803F5,0xC4500000,0xAE00004A,
+0x16C0A69,};
+static const uint32_t g_etc1_to_bc7_m6_table212[] = {
+0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0xB00000,0x1640000,
+0x1640000,0x1640000,0x1640000,0x3A000000,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x740001,0x67C0000,0x67C0000,0x67C0000,0xB00000,0xF80000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1080000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,
+0x1880000,0x49F80000,0x49F80000,0x49F80000,0x82000001,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x1880000,0x49F80000,0x49F80000,0x49F80000,0x82000001,0x49F80000,0x49F80000,0x49F80000,0x82000001,0x82000001,0x5180000,0x1080000,0x1080000,0x1340000,0x14C0000,0x1680000,0x1680000,0x1BC0000,0x1340000,0x14C0000,0x19FC0000,0x49F80000,
+0x19FC0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x53FC0000,0x53FC0000,0x53FC0000,0xABF80000,0xABF80000,0xC4000001,0x53FC0000,0x53FC0000,0x53FC0000,0xABF80000,0xABF80000,0xC4000001,0xABF80000,0xABF80000,0xC4000001,0xC4000001,0x53FC0000,0x53FC0000,0x53FC0000,0xABF80000,0xABF80000,0xC4000001,0xABF80000,0xABF80000,0xC4000001,0xC4000001,0xABF80000,
+0xABF80000,0xC4000001,0xC4000001,0xC4000001,0x1CC0000,0xBA40000,0x18C0000,0x2BFC0000,0x73FC0000,0x95FC0000,0x9FFC0000,0xB3F40000,0x1F00000,0x53FC0000,0x95FC0000,0xC4000001,0x95FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x14053CE,0xFF243DB6,0xFF082C15,0xFF0425C5,0xFF0C31DE,0xFEE41AFD,0xFEDC124D,0xFECC14B2,0xFCC00A76,0xE2C010C2,0xFEF436F6,0xFEC01AAD,0xFEB00F93,0xFE940E7F,0xFE800056,0xE488072F,0xFE7C1DBE,0xEC680AE9,0xD8640AE2,0xC2741D9B,0x3DC53CA,0xFEA03317,0xFE8825C6,0xFE641FF2,0xFE2C0BDE,0xE23C10C2,0xFE14260B,0xF4000A9F,0xDA000853,0xC2001DB3,0x73FC53CA,
+0xDC002E39,0xCA0021E2,0xB2002F23,0xA00053CA,0xFF204186,0xFF2C4DB2,0xF9404F7E,0xFF002E66,0xFED01ABC,0xFEA4092A,0xFE900243,0xFA700023,0xFF10407E,0xFEDC2BAA,0xFE700975,0xDA000853,0x4FFC53CA,0x1841D9D,0xFF681408,0xFF580BBD,0xFF480884,0xFF501235,0xFF2C068C,0xFF2401C4,0xFF140731,0xF90000AD,0xE3080659,0x49FC1D9A,0xFF140F18,0xFEF00884,0xFECC0B85,0xFE940005,
+0xE2AC0659,0xA7F81D9A,0xF80008AE,0xDC000795,0xC2001D9A,0x49FC1D9A,0xFF140F18,0xFEF00884,0xFECC0B85,0xFE940005,0xE2AC0659,0xA7F81D9A,0xF80008AE,0xDC000795,0xC2001D9A,0xA7F81D9A,0xF80008AE,0xDC000795,0xC2001D9A,0xC2001D9A,0xFF7418F9,0xF9801BAD,0xFB841BC5,0xFF40137A,0xFF100CD4,0xFEDC04E3,0xFEBC0059,0xFE5C0002,0xFF5C18D2,0xFF401296,0xFE7C0912,0xDC000795,
+0x8FFC1D9A,0x10425C5,0x10425C5,0x10425C5,0x10425C5,0xFEDC124D,0xFEDC124D,0xFEDC124D,0xF6C00A6A,0xF6C00A6A,0xC4C00A6A,0xFEB00F93,0xFEB00F93,0xFEB00F93,0xFE800056,0xFE800056,0xCA8C01D6,0xD8740883,0xD8740883,0xBC700103,0xA4740883,0x38025C5,0x38025C5,0x38025C5,0xFE2C0BDE,0xFE2C0BDE,0xC45C0A6A,0xEE000A0B,0xEE000A0B,0xC2000023,0xA40C0883,0x45FC25C5,
+0x45FC25C5,0xAC001022,0x960010EE,0x800025C6,0xFEE81BE6,0xF6FC21AD,0x10425C5,0xFECC134A,0xFEB00A91,0xFE98043A,0xFE900243,0xF674000B,0xFED01B16,0xFEB01226,0xFE6808D8,0xC2000023,0x15FC25C5,0x1480884,0x1480884,0x1480884,0x1480884,0xFF2401C4,0xFF2401C4,0xFF2401C4,0xE5080001,0xE5080001,0xC5080001,0x3E80882,0x3E80882,0x3E80882,0xFE940005,0xFE940005,
+0xC4C80001,0x79FC0882,0x79FC0882,0xC4000001,0xA4000882,0x3E80882,0x3E80882,0x3E80882,0xFE940005,0xFE940005,0xC4C80001,0x79FC0882,0x79FC0882,0xC4000001,0xA4000882,0x79FC0882,0x79FC0882,0xC4000001,0xA4000882,0xA4000882,0xFB340694,0xFB440708,0x1480884,0xFF180519,0xFEF002F2,0xFEC80151,0xFEBC0059,0xFA640000,0xF92806CD,0xFF0404EA,0x57FC0882,0xC4000001,
+0x57FC0882,0x1C40659,0xFFB003E8,0xFF940131,0xFF8C0000,0xA9FC0659,0xFF700262,0xFF540000,0xD5F80659,0xFEA00000,0xE2000659,0xA9FC0659,0xFF700262,0xFF540000,0xD5F80659,0xFEA00000,0xE2000659,0xD5F80659,0xFEA00000,0xE2000659,0xE2000659,0xA9FC0659,0xFF700262,0xFF540000,0xD5F80659,0xFEA00000,0xE2000659,0xD5F80659,0xFEA00000,0xE2000659,0xE2000659,0xD5F80659,
+0xFEA00000,0xE2000659,0xE2000659,0xE2000659,0xFFB405BA,0x1E40659,0xFBC405E9,0xFFA004F4,0xFF7C03E8,0xFF2C01F9,0xFEE40000,0xFE500000,0xFFAC05C4,0xFF9404C9,0xFF100032,0xE2000659,0xC9FC0659,0xC00A69,0xC00A69,0xC00A69,0xC00A69,0xC00A69,0xC00A69,0xC00A69,0xC00A69,0xC00A69,0xC00A69,0xFE800032,0xFE800032,0xFE800032,0xFE800032,0xFE800032,
+0xFE800032,0xA6780001,0xA6780001,0xA6780001,0x82740002,0x11C0A69,0x11C0A69,0x11C0A69,0x11C0A69,0x11C0A69,0x11C0A69,0xC0000014,0xC0000014,0xC0000014,0x82300001,0x11FC0A69,0x11FC0A69,0x11FC0A69,0x7800025D,0x5E000A69,0xFEAC07A2,0xC00A69,0xC00A69,0xFEA00492,0xFE94029A,0xFE880115,0xFE880115,0xEC780001,0xFE9006C4,0xFC900451,0xCC640001,0xC0000014,
+0x1940A69,};
+static const uint32_t g_etc1_to_bc7_m6_table213[] = {
+0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x2C40000,0x2C40000,0x2C40000,0x2C40000,0x2C40000,0x2C40000,0x2C40000,0x2C40000,0x2C40000,0x2C40000,0x1940000,
+0x1940000,0x1940000,0x1940000,0x42000000,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0x840001,0xE8C0000,0xE8C0000,0xE8C0000,0x2C40000,0x11C0000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1180000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,
+0x1A00000,0x55F80000,0x55F80000,0x55F80000,0x8A000001,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x55F80000,0x55F80000,0x55F80000,0x8A000001,0x55F80000,0x55F80000,0x55F80000,0x8A000001,0x8A000001,0xD280000,0x1180000,0x1180000,0x3440000,0x1600000,0x17C0000,0x17C0000,0x3D40000,0x3440000,0x1600000,0x27FC0000,0x55F80000,
+0x27FC0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0xB7F80000,0xB7F80000,0xCC000001,0x6BFC0000,0x6BFC0000,0x6BFC0000,0xB7F80000,0xB7F80000,0xCC000001,0xB7F80000,0xB7F80000,0xCC000001,0xCC000001,0x6BFC0000,0x6BFC0000,0x6BFC0000,0xB7F80000,0xB7F80000,0xCC000001,0xB7F80000,0xB7F80000,0xCC000001,0xCC000001,0xB7F80000,
+0xB7F80000,0xCC000001,0xCC000001,0xCC000001,0x1E00000,0x1B80000,0x19C0000,0x49FC0000,0x87FC0000,0xA3FC0000,0xADFC0000,0xBDF80000,0x11FC0000,0x6BFC0000,0xA3FC0000,0xCC000001,0xA3FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x14C4E1E,0xFF303AC6,0xFF202B4D,0xFF1425C5,0xFF182F0A,0xFEF81ADB,0xFEE81331,0xFED81392,0xFED00A6A,0xE6D00F1A,0xFF003356,0xFED81A55,0xFEC41065,0xFEAC0D5F,0xFE9400C6,0xE898059E,0xFE941A6E,0xF07C0A01,0xDC7808A6,0xC8841A07,0x1F04E1A,0xFEB8315F,0xFEA025C6,0xFE7C1E4A,0xFE4C0C89,0xE6500F1A,0xFE2C231B,0xFA000993,0xE0000597,0xC8041A06,0x7DF84E1A,
+0xE0002B5E,0xD0001D1E,0xB8002977,0xA6004E1A,0xFF343DC5,0xFD48484A,0xFF4C4A16,0xFF082C34,0xFEE01A1E,0xFEB809A4,0xFEA4032A,0xFE84000B,0xFF183CC9,0xFEF429C3,0xFE7C09C3,0xE0000597,0x5BFC4E1A,0x1901A05,0xFF741218,0xFF640B25,0xFF580884,0xFF5C1001,0xFF400632,0xFF300220,0xFF2005C9,0xFB100051,0xE71804B1,0x59FC1A05,0xFF200DF4,0xFF080884,0xFEE409DD,0xFEAC0025,
+0xE6C004B1,0xADFC1A05,0xFE080882,0xE0000566,0xC8001A06,0x59FC1A05,0xFF200DF4,0xFF080884,0xFEE409DD,0xFEAC0025,0xE6C004B1,0xADFC1A05,0xFE080882,0xE0000566,0xC8001A06,0xADFC1A05,0xFE080882,0xE0000566,0xC8001A06,0xC8001A06,0xFF7815DA,0xFF8C182D,0xFF8C185D,0xFF5C114D,0xFF280B9E,0xFEF0049D,0xFED000A0,0xFE7C0004,0xFD74161E,0xFF481074,0xFEA008FB,0xE0000566,
+0x99FC1A05,0x11425C5,0x11425C5,0x11425C5,0x11425C5,0xFEE81331,0xFEE81331,0xFEE81331,0xFED00A6A,0xFED00A6A,0xCCD00A6A,0xFEC41065,0xFEC41065,0xFEC41065,0xFE9400C6,0xFE9400C6,0xD29C01D6,0xE0840883,0xE0840883,0xC4800103,0xAC840883,0x39825C5,0x39825C5,0x39825C5,0xFE4C0C89,0xFE4C0C89,0xCC6C0A6A,0xFA000983,0xFA000983,0xCE000003,0xAC1C0883,0x51FC25C5,
+0x51FC25C5,0xB2000F62,0x9C001026,0x880025C6,0xFD001CA9,0xFF0C21AD,0x11425C5,0xFEDC144E,0xFEC40BB5,0xFEAC053E,0xFEA4032A,0xFE84000B,0xFEE41BE5,0xFED012ED,0xFE7C0933,0xCE000003,0x23FC25C5,0x1580884,0x1580884,0x1580884,0x1580884,0xFF300220,0xFF300220,0xFF300220,0xED180001,0xED180001,0xCD180001,0x7FC0882,0x7FC0882,0x7FC0882,0xFEAC0025,0xFEAC0025,
+0xCCD80001,0x85FC0882,0x85FC0882,0xCC0C0001,0xAC000882,0x7FC0882,0x7FC0882,0x7FC0882,0xFEAC0025,0xFEAC0025,0xCCD80001,0x85FC0882,0x85FC0882,0xCC0C0001,0xAC000882,0x85FC0882,0x85FC0882,0xCC0C0001,0xAC000882,0xAC000882,0xFF3C06C4,0xFF4C0728,0x1580884,0xFF24057A,0xFF040352,0xFEE4019A,0xFED000A0,0xFE7C0004,0xFF3406D1,0xFF180521,0x65FC0882,0xCC0C0001,
+0x65FC0882,0x1CC04B1,0xFFBC02E4,0xFFA000E5,0xFF9C0000,0xB5FC04B1,0xFF8801BA,0xFF6C0000,0xDBF804B1,0xFED40000,0xE60004B1,0xB5FC04B1,0xFF8801BA,0xFF6C0000,0xDBF804B1,0xFED40000,0xE60004B1,0xDBF804B1,0xFED40000,0xE60004B1,0xE60004B1,0xB5FC04B1,0xFF8801BA,0xFF6C0000,0xDBF804B1,0xFED40000,0xE60004B1,0xDBF804B1,0xFED40000,0xE60004B1,0xE60004B1,0xDBF804B1,
+0xFED40000,0xE60004B1,0xE60004B1,0xE60004B1,0xF9C40451,0x1EC04B1,0xFFCC0451,0xFFB003A1,0xFF9002E4,0xFF480168,0xFF0C0000,0xFE8C0000,0xF3C40451,0xFFA00392,0xFF300025,0xE60004B1,0xD1FC04B1,0xD00A69,0xD00A69,0xD00A69,0xD00A69,0xD00A69,0xD00A69,0xD00A69,0xD00A69,0xD00A69,0xD00A69,0xFE900059,0xFE900059,0xFE900059,0xFE900059,0xFE900059,
+0xFE900059,0xAE880001,0xAE880001,0xAE880001,0x8A840002,0x1340A69,0x1340A69,0x1340A69,0x1340A69,0x1340A69,0x1340A69,0xCE000002,0xCE000002,0xCE000002,0x8A400001,0x1DFC0A69,0x1DFC0A69,0x1DFC0A69,0x7E0001ED,0x66000A69,0xFAC407C1,0xD00A69,0xD00A69,0xFCB804E2,0xFEA802DA,0xFE980151,0xFE980151,0xF4880001,0xFEAC0708,0xFEA00480,0xD4740001,0xCE000002,
+0x1B40A69,};
+static const uint32_t g_etc1_to_bc7_m6_table214[] = {
+0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x2DC0000,0x1C40000,
+0x1C40000,0x1C40000,0x1C40000,0x4A000000,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0x940001,0xA00000,0xA00000,0xA00000,0x2DC0000,0x13C0000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,
+0x1B80000,0x61F80000,0x61F80000,0x61F80000,0x92000001,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x61F80000,0x61F80000,0x61F80000,0x92000001,0x61F80000,0x61F80000,0x61F80000,0x92000001,0x92000001,0x13C0000,0x1280000,0x1280000,0x1580000,0x1740000,0x3900000,0x3900000,0x1F00000,0x1580000,0x1740000,0x37FC0000,0x61F80000,
+0x37FC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x83FC0000,0x83FC0000,0x83FC0000,0xC3F80000,0xC3F80000,0xD4000001,0x83FC0000,0x83FC0000,0x83FC0000,0xC3F80000,0xC3F80000,0xD4000001,0xC3F80000,0xC3F80000,0xD4000001,0xD4000001,0x83FC0000,0x83FC0000,0x83FC0000,0xC3F80000,0xC3F80000,0xD4000001,0xC3F80000,0xC3F80000,0xD4000001,0xD4000001,0xC3F80000,
+0xC3F80000,0xD4000001,0xD4000001,0xD4000001,0x3F00000,0x1C80000,0x1AC0000,0x67FC0000,0x9BFC0000,0xB3FC0000,0xBBFC0000,0xC7FC0000,0x37FC0000,0x83FC0000,0xB3FC0000,0xD4000001,0xB3FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x15848CE,0xFF4437E9,0xFF2C2A81,0xFF2425C5,0xFF242C86,0xFF081AD5,0xFF001419,0xFEF01292,0xFEE00A8D,0xEAE00DB2,0xFF0C301E,0xFEE41A29,0xFEDC116D,0xFEB80CB3,0xFEAC016E,0xEAA8045E,0xFEA0178E,0xF4900951,0xE088069F,0xCC9416C7,0x7FC48CA,0xFECC3001,0xFEB825C6,0xFE941CE2,0xFE640D49,0xEA640DB2,0xFE3820BF,0xFE08097B,0xE6000393,0xCC1816C6,0x85FC48CA,
+0xE600290A,0xD60018EA,0xBE002443,0xAC0048CA,0xFF3C39F6,0xFF4C436A,0xFF4C4586,0xFF182A0A,0xFEF419AA,0xFEC80A63,0xFEBC0422,0xFE9C0031,0xFF34391E,0xFF0027C6,0xFE940A51,0xE6000393,0x65FC48CA,0x19C16C5,0xFF801058,0xFF700AA5,0xFF680884,0xFF740E01,0xFF5405F4,0xFF44027D,0xFF380491,0xFD240018,0xEB280349,0x6BFC16C5,0xFF380CE4,0xFF200884,0xFEFC0875,0xFECC0061,
+0xEAD40349,0xB7F816C5,0xFE380882,0xE6000392,0xCC0016C6,0x6BFC16C5,0xFF380CE4,0xFF200884,0xFEFC0875,0xFECC0061,0xEAD40349,0xB7F816C5,0xFE380882,0xE6000392,0xCC0016C6,0xB7F816C5,0xFE380882,0xE6000392,0xCC0016C6,0xCC0016C6,0xFF80136D,0xFF8C154D,0xF59815A4,0xFF6C0F72,0xFF480A86,0xFF040496,0xFEE800FA,0xFEA00022,0xFF781352,0xFF5C0EC6,0xFED008E5,0xE6000392,
+0xA3FC16C5,0x12425C5,0x12425C5,0x12425C5,0x12425C5,0xFF001419,0xFF001419,0xFF001419,0xFEE00A8D,0xFEE00A8D,0xD4E00A6A,0xFEDC116D,0xFEDC116D,0xFEDC116D,0xFEAC016E,0xFEAC016E,0xDAAC01D6,0xE8940883,0xE8940883,0xCC900103,0xB4940883,0x3B025C5,0x3B025C5,0x3B025C5,0xFE640D49,0xFE640D49,0xD47C0A6A,0xFE08097B,0xFE08097B,0xD6100003,0xB42C0883,0x5DFC25C5,
+0x5DFC25C5,0xBE000E9A,0xA6000F63,0x900025C6,0xFF101D2B,0xF920222A,0x12425C5,0xFEF81556,0xFED80CE9,0xFEBC0666,0xFEBC0422,0xFE9C0031,0xFEF81C56,0xFEDC1421,0xFE9409D8,0xD6100003,0x33FC25C5,0x1680884,0x1680884,0x1680884,0x1680884,0xFF44027D,0xFF44027D,0xFF44027D,0xF5280001,0xF5280001,0xD5280001,0x1FFC0882,0x1FFC0882,0x1FFC0882,0xFECC0061,0xFECC0061,
+0xD4E80001,0x91FC0882,0x91FC0882,0xD41C0001,0xB4000882,0x1FFC0882,0x1FFC0882,0x1FFC0882,0xFECC0061,0xFECC0061,0xD4E80001,0x91FC0882,0x91FC0882,0xD41C0001,0xB4000882,0x91FC0882,0x91FC0882,0xD41C0001,0xB4000882,0xB4000882,0xFF5806CD,0xFB640745,0x1680884,0xFF4405B2,0xFF1803BA,0xFEFC01F9,0xFEE800FA,0xFEA00022,0xFD4C0708,0xFF300581,0x75FC0882,0xD41C0001,
+0x75FC0882,0x1D40349,0xFFC401F9,0xFFB8009D,0xFFAC0000,0xC1FC0349,0xFFA00132,0xFF840000,0xE1F80349,0xFF040000,0xEA000349,0xC1FC0349,0xFFA00132,0xFF840000,0xE1F80349,0xFF040000,0xEA000349,0xE1F80349,0xFF040000,0xEA000349,0xEA000349,0xC1FC0349,0xFFA00132,0xFF840000,0xE1F80349,0xFF040000,0xEA000349,0xE1F80349,0xFF040000,0xEA000349,0xEA000349,0xE1F80349,
+0xFF040000,0xEA000349,0xEA000349,0xEA000349,0xFDCC02F9,0x1F40349,0xFFCC0311,0xFFC00288,0xFFA80202,0xFF700104,0xFF340000,0xFEC80000,0xF7CC02F9,0xFDBC0288,0xFF500019,0xEA000349,0xD9FC0349,0xE00A69,0xE00A69,0xE00A69,0xE00A69,0xE00A69,0xE00A69,0xE00A69,0xE00A69,0xE00A69,0xE00A69,0xFEA40082,0xFEA40082,0xFEA40082,0xFEA40082,0xFEA40082,
+0xFEA40082,0xB6980001,0xB6980001,0xB6980001,0x92940002,0x1480A69,0x1480A69,0x1480A69,0x1480A69,0x1480A69,0x1480A69,0xD80C0000,0xD80C0000,0xD80C0000,0x92500001,0x29FC0A69,0x29FC0A69,0x29FC0A69,0x8A000195,0x6E000A69,0xFECC07E9,0xE00A69,0xE00A69,0xFCC80515,0xFEB40321,0xFEAC019A,0xFEAC019A,0xFC980001,0xFEBC070A,0xFEB404B1,0xDC840001,0xD80C0000,
+0x1D80A69,};
+static const uint32_t g_etc1_to_bc7_m6_table215[] = {
+0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x2F40000,0x1F40000,
+0x1F40000,0x1F40000,0x1F40000,0x52000000,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xA40001,0xB00000,0xB00000,0xB00000,0x2F40000,0x1600000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1380000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,
+0x1D00000,0x6DF80000,0x6DF80000,0x6DF80000,0x9A000001,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x1D00000,0x6DF80000,0x6DF80000,0x6DF80000,0x9A000001,0x6DF80000,0x6DF80000,0x6DF80000,0x9A000001,0x9A000001,0x14C0000,0x1380000,0x1380000,0x7680000,0x1880000,0x1A80000,0x1A80000,0xDFC0000,0x7680000,0x1880000,0x45FC0000,0x6DF80000,
+0x45FC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0xCFF80000,0xCFF80000,0xDC000001,0x9BFC0000,0x9BFC0000,0x9BFC0000,0xCFF80000,0xCFF80000,0xDC000001,0xCFF80000,0xCFF80000,0xDC000001,0xDC000001,0x9BFC0000,0x9BFC0000,0x9BFC0000,0xCFF80000,0xCFF80000,0xDC000001,0xCFF80000,0xCFF80000,0xDC000001,0xDC000001,0xCFF80000,
+0xCFF80000,0xDC000001,0xDC000001,0xDC000001,0x17FC0000,0x5D80000,0x1BC0000,0x85FC0000,0xAFFC0000,0xC1FC0000,0xC9F80000,0xD3F80000,0x5FFC0000,0x9BFC0000,0xC1FC0000,0xDC000001,0xC1FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x16443DE,0xFF503551,0xFF3829D5,0xFF3425C5,0xFF302A52,0xFF181AE5,0xFF0C150D,0xFEFC11F2,0xFEF00AE2,0xEEF00C8A,0xFF242D36,0xFEFC1A11,0xFEE81275,0xFED80C52,0xFEC00252,0xEEBC035E,0xFEB8151E,0xF8A408D9,0xE69404F3,0xD2A413DB,0x19FC43DA,0xFEE42E81,0xFED025C5,0xFEAC1BBA,0xFE7C0E29,0xEE780C8A,0xFE641E91,0xFE200A1B,0xEC0C023F,0xD22813DA,0x8FF843DA,
+0xF0002759,0xDC001546,0xC4001F87,0xB20043DA,0xFF4C36D3,0xF9603F4E,0xFB6440F5,0xFF2C286E,0xFF04195C,0xFEDC0B1C,0xFED00559,0xFEB00092,0xFF3435BE,0xFF102642,0xFEB00AE7,0xEC0C023F,0x71FC43DA,0x1A413DD,0xFF8C0EC8,0xFF7C0A3D,0xFF780884,0xFF800C45,0xFF6405BE,0xFF5C02FD,0xFF4C03BD,0xFF380001,0xEF380221,0x7BFC13DA,0xFF4C0C13,0xFF380884,0xFF14074D,0xFEE400B9,
+0xEEE80221,0xBFF813DA,0xFE6C0882,0xEC00022E,0xD20013DA,0x7BFC13DA,0xFF4C0C13,0xFF380884,0xFF14074D,0xFEE400B9,0xEEE80221,0xBFF813DA,0xFE6C0882,0xEC00022E,0xD20013DA,0xBFF813DA,0xFE6C0882,0xEC00022E,0xD20013DA,0xD20013DA,0xFF9410EE,0xF9A01299,0xFBA412D8,0xFF780DD1,0xFF5C09A6,0xFF240491,0xFF0C0164,0xFEB80068,0xFF8810FD,0xFF680D52,0xFEE408D3,0xEC00022E,
+0xADFC13DA,0x13425C5,0x13425C5,0x13425C5,0x13425C5,0xFF0C150D,0xFF0C150D,0xFF0C150D,0xFEF00AE2,0xFEF00AE2,0xDCF00A6A,0xFEE81275,0xFEE81275,0xFEE81275,0xFEC00252,0xFEC00252,0xE2BC01D6,0xF0A40883,0xF0A40883,0xD4A00103,0xBCA40883,0x1C825C5,0x1C825C5,0x1C825C5,0xFE7C0E29,0xFE7C0E29,0xDC8C0A6A,0xFE200A1B,0xFE200A1B,0xDE200003,0xBC3C0883,0x69FC25C5,
+0x69FC25C5,0xCA000DF2,0xB2000EA3,0x980025C6,0xFF201DA6,0xFF2C222E,0x13425C5,0xFF081643,0xFEEC0E2D,0xFED407CE,0xFED00559,0xFEB00092,0xFF141D18,0xFEF41512,0xFEB00A83,0xDE200003,0x41FC25C5,0x1780884,0x1780884,0x1780884,0x1780884,0xFF5C02FD,0xFF5C02FD,0xFF5C02FD,0xFD380001,0xFD380001,0xDD380001,0x37FC0882,0x37FC0882,0x37FC0882,0xFEE400B9,0xFEE400B9,
+0xDCF80001,0x9DFC0882,0x9DFC0882,0xDC2C0001,0xBC000882,0x37FC0882,0x37FC0882,0x37FC0882,0xFEE400B9,0xFEE400B9,0xDCF80001,0x9DFC0882,0x9DFC0882,0xDC2C0001,0xBC000882,0x9DFC0882,0x9DFC0882,0xDC2C0001,0xBC000882,0xBC000882,0xFB6C0708,0xFF6C076D,0x1780884,0xFD5805E9,0xFF400422,0xFF20028A,0xFF0C0164,0xFEB80068,0xF5640745,0xFF4805B4,0x83FC0882,0xDC2C0001,
+0x83FC0882,0x1DC0221,0xFFD00145,0xFFC00068,0xFFBC0000,0xCDFC0221,0xFFAC00C2,0xFF9C0000,0xE7F80221,0xFF340000,0xEE000221,0xCDFC0221,0xFFAC00C2,0xFF9C0000,0xE7F80221,0xFF340000,0xEE000221,0xE7F80221,0xFF340000,0xEE000221,0xEE000221,0xCDFC0221,0xFFAC00C2,0xFF9C0000,0xE7F80221,0xFF340000,0xEE000221,0xE7F80221,0xFF340000,0xEE000221,0xEE000221,0xE7F80221,
+0xFF340000,0xEE000221,0xEE000221,0xEE000221,0xFFD001ED,0x1FC0221,0xF7DC0200,0xFFC001A8,0xFFA80152,0xFF8400A0,0xFF5C0000,0xFF040000,0xFBD401E1,0xFFC00190,0xFF700010,0xEE000221,0xDFFC0221,0xF00A69,0xF00A69,0xF00A69,0xF00A69,0xF00A69,0xF00A69,0xF00A69,0xF00A69,0xF00A69,0xF00A69,0xFEB400C1,0xFEB400C1,0xFEB400C1,0xFEB400C1,0xFEB400C1,
+0xFEB400C1,0xBEA80001,0xBEA80001,0xBEA80001,0x9AA40002,0x1600A69,0x1600A69,0x1600A69,0x1600A69,0x1600A69,0x1600A69,0xE01C0000,0xE01C0000,0xE01C0000,0x9A600001,0x35FC0A69,0x35FC0A69,0x35FC0A69,0x9000013D,0x76000A69,0xFAE40802,0xF00A69,0xF00A69,0xFED8054A,0xFED00372,0xFEC401E1,0xFEC401E1,0xFCA8000A,0xFAD00745,0xFEBC0502,0xE4940001,0xE01C0000,
+0x1F80A69,};
+static const uint32_t g_etc1_to_bc7_m6_table216[] = {
+0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0x1100000,0xDFC0000,
+0xDFC0000,0xDFC0000,0xDFC0000,0x5A000001,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xB80000,0xC40000,0xC40000,0xC40000,0x1100000,0x1880000,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x1480001,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,
+0x3E80000,0x79FC0000,0x79FC0000,0x79FC0000,0xA4000000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x3E80000,0x79FC0000,0x79FC0000,0x79FC0000,0xA4000000,0x79FC0000,0x79FC0000,0x79FC0000,0xA4000000,0xA4000000,0x1600000,0x1480001,0x1480001,0x1800000,0x39C0000,0x1C00000,0x1C00000,0x23FC0000,0x1800000,0x39C0000,0x57FC0000,0x79FC0000,
+0x57FC0000,0x1CC0001,0x1CC0001,0x1CC0001,0x1CC0001,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xDDF40000,0xDDF40000,0xE6000000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xDDF40000,0xDDF40000,0xE6000000,0xDDF40000,0xDDF40000,0xE6000000,0xE6000000,0xB7FC0000,0xB7FC0000,0xB7FC0000,0xDDF40000,0xDDF40000,0xE6000000,0xDDF40000,0xDDF40000,0xE6000000,0xE6000000,0xDDF40000,
+0xDDF40000,0xE6000000,0xE6000000,0xE6000000,0x57FC0000,0x1EC0000,0x1CC0001,0xA7FC0000,0xC5FC0000,0xD3FC0000,0xD7FC0000,0xDFF80000,0x8BFC0000,0xB7FC0000,0xD3FC0000,0xE6000000,0xD3FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1743EBF,0xFF5C32AA,0xFF4C292F,0xFF4425C6,0xFF4427D5,0xFF301B26,0xFF24162E,0xFF141185,0xFF080B81,0xF3000B89,0xFF302A4B,0xFF101A25,0xFF0013B2,0xFEE40C25,0xFED80391,0xF6CC0285,0xFECC130C,0xFCB8088E,0xEAA80370,0xD8B810F8,0x2FFC3EBF,0xFEFC2CFE,0xFEEC25C5,0xFEB81ACB,0xFEA00F3A,0xF2900B89,0xFE881C84,0xFE380B28,0xF0200130,0xD83C10F9,0x99FC3EBF,
+0xF8002621,0xE0001205,0xD0001AB8,0xB8003EC1,0xFF583335,0xFF6C3A65,0xFF6C3C36,0xFF4026D4,0xFF181935,0xFEF00C2B,0xFEE806D0,0xFEC00164,0xFF50326B,0xFF3024FE,0xFEBC0BFE,0xF0200130,0x7FF83EBF,0x1B010FB,0xFFA40D26,0xFF9409C3,0xFF8C0882,0xFF8C0AA9,0xFF7405AE,0xFF680385,0xFF580313,0xFF4C001A,0xF3480121,0x8DFC10F8,0xFF640B25,0xFF540882,0xFF2C0651,0xFF080131,
+0xF2FC0121,0xC7FC10F8,0xFEA00882,0xF2080120,0xD80010F8,0x8DFC10F8,0xFF640B25,0xFF540882,0xFF2C0651,0xFF080131,0xF2FC0121,0xC7FC10F8,0xFEA00882,0xF2080120,0xD80010F8,0xC7FC10F8,0xFEA00882,0xF2080120,0xD80010F8,0xD80010F8,0xFFA00E9D,0xFFAC0FC9,0xFFAC1026,0xFF880C23,0xFF6808C1,0xFF380495,0xFF2801E2,0xFEE400CD,0xFF980EBE,0xFF840BB2,0xFF1008B5,0xF2080120,
+0xB9FC10F8,0x14425C6,0x14425C6,0x14425C6,0x14425C6,0xFF24162E,0xFF24162E,0xFF24162E,0xFF080B81,0xFF080B81,0xE7000A69,0xFF0013B2,0xFF0013B2,0xFF0013B2,0xFED80391,0xFED80391,0xECD001D5,0xF8B80884,0xF8B80884,0xDCB00104,0xC4B80884,0x1E425C5,0x1E425C5,0x1E425C5,0xFEA00F3A,0xFEA00F3A,0xE69C0A69,0xFE380B28,0xFE380B28,0xE6340002,0xC4500884,0x77F825C5,
+0x77F825C5,0xD6000D49,0xB8000DD4,0xA20025C5,0xFF2C1E68,0xF94022AA,0x14425C6,0xFF181761,0xFF000FB2,0xFEF00952,0xFEE806D0,0xFEC00164,0xFF201DB2,0xFF101682,0xFEBC0B9A,0xE6340002,0x53FC25C5,0x18C0882,0x18C0882,0x18C0882,0x18C0882,0xFF680385,0xFF680385,0xFF680385,0xFF4C001A,0xFF4C001A,0xE7480001,0x53FC0882,0x53FC0882,0x53FC0882,0xFF080131,0xFF080131,
+0xE7080001,0xABF80882,0xABF80882,0xE63C0000,0xC4000884,0x53FC0882,0x53FC0882,0x53FC0882,0xFF080131,0xFF080131,0xE7080001,0xABF80882,0xABF80882,0xE63C0000,0xC4000884,0xABF80882,0xABF80882,0xE63C0000,0xC4000884,0xC4000884,0xFF74073A,0xFD880782,0x18C0882,0xFB700659,0xFF540488,0xFF300304,0xFF2801E2,0xFEE400CD,0xFD740745,0xFF5C05F5,0x95FC0882,0xE63C0000,
+0x95FC0882,0x1E40122,0xFFDC00AA,0xFFD4003A,0xFFCC0001,0xDBFC0120,0xFFC0006D,0xFFB80000,0xEDFC0120,0xFF6C0000,0xF2000120,0xDBFC0120,0xFFC0006D,0xFFB80000,0xEDFC0120,0xFF6C0000,0xF2000120,0xEDFC0120,0xFF6C0000,0xF2000120,0xF2000120,0xDBFC0120,0xFFC0006D,0xFFB80000,0xEDFC0120,0xFF6C0000,0xF2000120,0xEDFC0120,0xFF6C0000,0xF2000120,0xF2000120,0xEDFC0120,
+0xFF6C0000,0xF2000120,0xF2000120,0xF2000120,0xF5E40109,0x47FC0120,0xFBE40109,0xFFD800DD,0xFFCC00B5,0xFFAC0059,0xFF880000,0xFF480000,0xFFDC00F4,0xFFCC00DA,0xFF980009,0xF2000120,0xE9FC0120,0x1000A69,0x1000A69,0x1000A69,0x1000A69,0x1000A69,0x1000A69,0x1000A69,0x1000A69,0x1000A69,0x1000A69,0xFEC80104,0xFEC80104,0xFEC80104,0xFEC80104,0xFEC80104,
+0xFEC80104,0xC8B80000,0xC8B80000,0xC8B80000,0xA4B80000,0x17C0A69,0x17C0A69,0x17C0A69,0x17C0A69,0x17C0A69,0x17C0A69,0xEA2C0000,0xEA2C0000,0xEA2C0000,0xA4700000,0x43F80A69,0x43F80A69,0x43F80A69,0x9C0000E9,0x80000A69,0xF4F80841,0x1000A69,0x1000A69,0xFEE80589,0xFEE403C8,0xFED4022D,0xFED4022D,0xFEC00020,0xFED80781,0xFED0053D,0xEEA40000,0xEA2C0000,
+0x11FC0A69,};
+static const uint32_t g_etc1_to_bc7_m6_table217[] = {
+0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x1280000,0x19FC0000,
+0x19FC0000,0x19FC0000,0x19FC0000,0x62000001,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0x2D40000,0x2D40000,0x2D40000,0x1280000,0x1A80000,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x1580001,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,
+0x7FC0000,0x85FC0000,0x85FC0000,0x85FC0000,0xAC000000,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x7FC0000,0x85FC0000,0x85FC0000,0x85FC0000,0xAC000000,0x85FC0000,0x85FC0000,0x85FC0000,0xAC000000,0xAC000000,0x1700000,0x1580001,0x1580001,0x5900000,0x3B00000,0x3D40000,0x3D40000,0x37FC0000,0x5900000,0x3B00000,0x65FC0000,0x85FC0000,
+0x65FC0000,0x1DC0001,0x1DC0001,0x1DC0001,0x1DC0001,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xE7FC0000,0xE7FC0000,0xEE000000,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xE7FC0000,0xE7FC0000,0xEE000000,0xE7FC0000,0xE7FC0000,0xEE000000,0xEE000000,0xCFFC0000,0xCFFC0000,0xCFFC0000,0xE7FC0000,0xE7FC0000,0xEE000000,0xE7FC0000,0xE7FC0000,0xEE000000,0xEE000000,0xE7FC0000,
+0xE7FC0000,0xEE000000,0xEE000000,0xEE000000,0x91FC0000,0x7FC0000,0x1DC0001,0xC5FC0000,0xD9FC0000,0xE1FC0000,0xE5FC0000,0xE9FC0000,0xB3FC0000,0xCFFC0000,0xE1FC0000,0xEE000000,0xE1FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1803A9B,0xFF68308E,0xFF5828A3,0xFF5425C6,0xFF502631,0xFF3C1B66,0xFF301742,0xFF201179,0xFF140C51,0xF7100AE9,0xFF4427DC,0xFF241A56,0xFF1814E2,0xFEFC0C45,0xFEE404F1,0xF8DC020D,0xFEE4119C,0xFECC0888,0xEEBC0268,0xDEC80EC4,0x41FC3A9B,0xFF142BBE,0xFF0425C5,0xFED81A61,0xFEB81052,0xF6A40AE9,0xFEA01B0C,0xFE640C2B,0xF6340082,0xDE500EC4,0xA1FC3A9B,
+0xFE0025C5,0xE6000F95,0xD60016F4,0xBE003A9D,0xFF643075,0xFF6C3735,0xF77C38AF,0xFF442569,0xFF281942,0xFEFC0D81,0xFEF8085D,0xFED8026A,0xFF542FDE,0xFF4023EC,0xFEDC0D0E,0xF6340082,0x89FC3A9B,0x1BC0EC3,0xFFB00BEE,0xFFA0096B,0xFF9C0882,0xFF980989,0xFF8405BA,0xFF80040D,0xFF7002BB,0xFF64006A,0xF7580081,0x9BFC0EC3,0xFF7C0A6D,0xFF6C0882,0xFF4C05D6,0xFF2C01BD,
+0xF7100081,0xCFF80EC3,0xFED40882,0xF6280080,0xDE000EC4,0x9BFC0EC3,0xFF7C0A6D,0xFF6C0882,0xFF4C05D6,0xFF2C01BD,0xF7100081,0xCFF80EC3,0xFED40882,0xF6280080,0xDE000EC4,0xCFF80EC3,0xFED40882,0xF6280080,0xDE000EC4,0xDE000EC4,0xFFB40CEA,0xF5B80E03,0xF7BC0E43,0xFF980AE1,0xFF7C0839,0xFF5804EB,0xFF3C028A,0xFEFC015D,0xFFA40D0A,0xFF900AA6,0xFF3008A8,0xF6280080,
+0xC1FC0EC3,0x15425C6,0x15425C6,0x15425C6,0x15425C6,0xFF301742,0xFF301742,0xFF301742,0xFF140C51,0xFF140C51,0xEF100A69,0xFF1814E2,0xFF1814E2,0xFF1814E2,0xFEE404F1,0xFEE404F1,0xF4E001D5,0xFECC0888,0xFECC0888,0xE4C00104,0xCCC80884,0x1FC25C5,0x1FC25C5,0x1FC25C5,0xFEB81052,0xFEB81052,0xEEAC0A69,0xFE640C2B,0xFE640C2B,0xEE440002,0xCC600884,0x83F825C5,
+0x83F825C5,0xDC000CB5,0xC4000D24,0xAA0025C5,0xFF3C1EFE,0xFF4C22BE,0x15425C6,0xFF2C188D,0xFF141116,0xFEFC0ADD,0xFEF8085D,0xFED8026A,0xFF341E29,0xFF18178E,0xFEDC0CBD,0xEE440002,0x61FC25C5,0x19C0882,0x19C0882,0x19C0882,0x19C0882,0xFF80040D,0xFF80040D,0xFF80040D,0xFF64006A,0xFF64006A,0xEF580001,0x6BFC0882,0x6BFC0882,0x6BFC0882,0xFF2C01BD,0xFF2C01BD,
+0xEF180001,0xB7F80882,0xB7F80882,0xEE4C0000,0xCC000884,0x6BFC0882,0x6BFC0882,0x6BFC0882,0xFF2C01BD,0xFF2C01BD,0xEF180001,0xB7F80882,0xB7F80882,0xEE4C0000,0xCC000884,0xB7F80882,0xB7F80882,0xEE4C0000,0xCC000884,0xCC000884,0xFF900745,0xF59807C1,0x19C0882,0xFF780681,0xFF700515,0xFF5003B5,0xFF3C028A,0xFEFC015D,0xFD880782,0xFF74065D,0xA3FC0882,0xEE4C0000,
+0xA3FC0882,0x1EC0082,0xFFE8004A,0xFFE40019,0xFFDC0001,0xE9FC0080,0xFFD8002D,0xFFCC0001,0xF3FC0080,0xFF9C0000,0xF6000080,0xE9FC0080,0xFFD8002D,0xFFCC0001,0xF3FC0080,0xFF9C0000,0xF6000080,0xF3FC0080,0xFF9C0000,0xF6000080,0xF6000080,0xE9FC0080,0xFFD8002D,0xFFCC0001,0xF3FC0080,0xFF9C0000,0xF6000080,0xF3FC0080,0xFF9C0000,0xF6000080,0xF6000080,0xF3FC0080,
+0xFF9C0000,0xF6000080,0xF6000080,0xF6000080,0xF9EC0071,0x87FC0080,0xFFEC0071,0xFDE80062,0xFDE00055,0xFFC80022,0xFFB00000,0xFF840000,0xFDEC0071,0xFFE40062,0xFFB80004,0xF6000080,0xF1FC0080,0x1100A69,0x1100A69,0x1100A69,0x1100A69,0x1100A69,0x1100A69,0x1100A69,0x1100A69,0x1100A69,0x1100A69,0xFEDC0145,0xFEDC0145,0xFEDC0145,0xFEDC0145,0xFEDC0145,
+0xFEDC0145,0xD0C80000,0xD0C80000,0xD0C80000,0xACC80000,0x1940A69,0x1940A69,0x1940A69,0x1940A69,0x1940A69,0x1940A69,0xF23C0000,0xF23C0000,0xF23C0000,0xAC800000,0x4FF80A69,0x4FF80A69,0x4FF80A69,0xA60000B4,0x88000A69,0xFD080841,0x1100A69,0x1100A69,0xFEF405E4,0xFEEC041D,0xFEE80290,0xFEE80290,0xFED40048,0xFEF40784,0xFEE40595,0xF6B40000,0xF23C0000,
+0x1FFC0A69,};
+static const uint32_t g_etc1_to_bc7_m6_table218[] = {
+0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x1400000,0x25F80000,
+0x25F80000,0x25F80000,0x25F80000,0x6A000001,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xD80000,0xAE40000,0xAE40000,0xAE40000,0x1400000,0x1CC0000,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1680001,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,
+0x1FFC0000,0x91FC0000,0x91FC0000,0x91FC0000,0xB4000000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x1FFC0000,0x91FC0000,0x91FC0000,0x91FC0000,0xB4000000,0x91FC0000,0x91FC0000,0x91FC0000,0xB4000000,0xB4000000,0x9800000,0x1680001,0x1680001,0x1A40000,0x3C40000,0x1EC0000,0x1EC0000,0x4BFC0000,0x1A40000,0x3C40000,0x75FC0000,0x91FC0000,
+0x75FC0000,0x1EC0001,0x1EC0001,0x1EC0001,0x1EC0001,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xF3FC0000,0xF3FC0000,0xF6000000,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xF3FC0000,0xF3FC0000,0xF6000000,0xF3FC0000,0xF3FC0000,0xF6000000,0xF6000000,0xE9FC0000,0xE9FC0000,0xE9FC0000,0xF3FC0000,0xF3FC0000,0xF6000000,0xF3FC0000,0xF3FC0000,0xF6000000,0xF6000000,0xF3FC0000,
+0xF3FC0000,0xF6000000,0xF6000000,0xF6000000,0xC9FC0000,0x87FC0000,0x1EC0001,0xE3FC0000,0xEDFC0000,0xF1FC0000,0xF3F80000,0xF5F80000,0xDBFC0000,0xE9FC0000,0xF1FC0000,0xF6000000,0xF1FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x18C36D7,0xFF742EAA,0xFF6C2826,0xFF6425C6,0xFF5C24DD,0xFF501BC6,0xFF441831,0xFF3811B1,0xFF2C0D49,0xFB200A89,0xFF5025F8,0xFF301AB6,0xFF241626,0xFF140CC5,0xFEFC0671,0xFCF001D9,0xFEFC10AC,0xFEE408D8,0xF4C801A8,0xE2D80CE4,0x53FC36D7,0xFF2C2A9E,0xFF1C25C5,0xFEF01A01,0xFED811B1,0xFAB80A89,0xFEB819F4,0xFE880D5B,0xFA4C0020,0xE2640CE4,0xABF836D7,
+0xFE2C25C5,0xEC000DB5,0xDC0013A8,0xC40036D9,0xFF742E0F,0xFD883393,0xFD88351B,0xFF54242D,0xFF381982,0xFF180EB9,0xFF1009F9,0xFEEC03A5,0xFF702D9A,0xFF5022A2,0xFEF40E18,0xFA4C0020,0x95FC36D7,0x1C80CE3,0xFFBC0AE6,0xFFAC092B,0xFFAC0882,0xFFA408B1,0xFF9805D6,0xFF8C04A5,0xFF7C02B3,0xFF7000EA,0xFB680021,0xAFFC0CE3,0xFF9409D5,0xFF840882,0xFF640576,0xFF380271,
+0xFB240021,0xD7FC0CE3,0xFF040882,0xFA4C0020,0xE2000CE4,0xAFFC0CE3,0xFF9409D5,0xFF840882,0xFF640576,0xFF380271,0xFB240021,0xD7FC0CE3,0xFF040882,0xFA4C0020,0xE2000CE4,0xD7FC0CE3,0xFF040882,0xFA4C0020,0xE2000CE4,0xE2000CE4,0xFFBC0B6D,0xFBC40C2B,0xFBC40C7B,0xFFB00A0A,0xFF9007D9,0xFF6C0515,0xFF640332,0xFF2801F4,0xFFB40B76,0xFF9809BE,0xFF50089B,0xFA4C0020,
+0xCDFC0CE3,0x16425C6,0x16425C6,0x16425C6,0x16425C6,0xFF441831,0xFF441831,0xFF441831,0xFF2C0D49,0xFF2C0D49,0xF7200A69,0xFF241626,0xFF241626,0xFF241626,0xFEFC0671,0xFEFC0671,0xFCF001D5,0xFEE408D8,0xFEE408D8,0xECD00104,0xD4D80884,0x19FC25C5,0x19FC25C5,0x19FC25C5,0xFED811B1,0xFED811B1,0xF6BC0A69,0xFE880D5B,0xFE880D5B,0xF6540002,0xD4700884,0x8FF825C5,
+0x8FF825C5,0xE6000C45,0xCA000C84,0xB20025C5,0xFF4C1F85,0xF960232D,0x16425C6,0xFF3C1996,0xFF2C12AC,0xFF180CA8,0xFF1009F9,0xFEEC03A5,0xFD4C1F0B,0xFF30188D,0xFEF40DD8,0xF6540002,0x71FC25C5,0x1AC0882,0x1AC0882,0x1AC0882,0x1AC0882,0xFF8C04A5,0xFF8C04A5,0xFF8C04A5,0xFF7000EA,0xFF7000EA,0xF7680001,0x83FC0882,0x83FC0882,0x83FC0882,0xFF380271,0xFF380271,
+0xF7280001,0xC3F80882,0xC3F80882,0xF65C0000,0xD4000884,0x83FC0882,0x83FC0882,0x83FC0882,0xFF380271,0xFF380271,0xF7280001,0xC3F80882,0xC3F80882,0xF65C0000,0xD4000884,0xC3F80882,0xC3F80882,0xF65C0000,0xD4000884,0xD4000884,0xFFA00784,0xFDA807C1,0x1AC0882,0xFF9806CD,0xFF840581,0xFF640431,0xFF640332,0xFF2801F4,0xFF940794,0xFF8406B2,0xB3FC0882,0xF65C0000,
+0xB3FC0882,0x1F40022,0xFFF40012,0xFFF00005,0xFFEC0001,0xF5FC0020,0xFFEC000D,0xFFE40001,0xF9FC0020,0xFFCC0000,0xFA000020,0xF5FC0020,0xFFEC000D,0xFFE40001,0xF9FC0020,0xFFCC0000,0xFA000020,0xF9FC0020,0xFFCC0000,0xFA000020,0xFA000020,0xF5FC0020,0xFFEC000D,0xFFE40001,0xF9FC0020,0xFFCC0000,0xFA000020,0xF9FC0020,0xFFCC0000,0xFA000020,0xFA000020,0xF9FC0020,
+0xFFCC0000,0xFA000020,0xFA000020,0xFA000020,0xFDF40019,0xC7FC0020,0xF3F40022,0xFFF00019,0xFFE80011,0xFFDC0009,0xFFD80000,0xFFC00000,0xFFF0001D,0xFFF00019,0xFFDC0001,0xFA000020,0xF9FC0020,0x1200A69,0x1200A69,0x1200A69,0x1200A69,0x1200A69,0x1200A69,0x1200A69,0x1200A69,0x1200A69,0x1200A69,0xFEF401A5,0xFEF401A5,0xFEF401A5,0xFEF401A5,0xFEF401A5,
+0xFEF401A5,0xD8D80000,0xD8D80000,0xD8D80000,0xB4D80000,0x1AC0A69,0x1AC0A69,0x1AC0A69,0x1AC0A69,0x1AC0A69,0x1AC0A69,0xFA4C0000,0xFA4C0000,0xFA4C0000,0xB4900000,0x5BF80A69,0x5BF80A69,0x5BF80A69,0xAC000080,0x90000A69,0xF5180884,0x1200A69,0x1200A69,0xFF100620,0xFF000469,0xFEF802E4,0xFEF802E4,0xFEE40088,0xFB0807C1,0xFEF805C4,0xFEC40000,0xFA4C0000,
+0x2FFC0A69,};
+static const uint32_t g_etc1_to_bc7_m6_table219[] = {
+0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x1580000,0x31F80000,
+0x31F80000,0x31F80000,0x31F80000,0x72000001,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xE80000,0xF80000,0xF80000,0xF80000,0x1580000,0x1EC0000,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x1780001,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,
+0x37FC0000,0x9DFC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x37FC0000,0x9DFC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0x9DFC0000,0x9DFC0000,0x9DFC0000,0xBC000000,0xBC000000,0x1940000,0x1780001,0x1780001,0x1B80000,0x3D80000,0x9FC0000,0x9FC0000,0x5DFC0000,0x1B80000,0x3D80000,0x83FC0000,0x9DFC0000,
+0x83FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1983373,0xFF8C2CEA,0xFF7C279F,0xFF7425C6,0xFF7423B5,0xFF5C1C42,0xFF5C1969,0xFF40125B,0xFF380E81,0xFF300A69,0xFF5C247C,0xFF441B19,0xFF441758,0xFF200D81,0xFF140831,0xFF0001F9,0xFF081024,0xFEF00984,0xF8DC0130,0xE8E80B58,0x65FC3373,0xFF4029BE,0xFF3425C5,0xFF0819E1,0xFEF01301,0xFECC0A69,0xFED81984,0xFEA00EBB,0xFE640002,0xE8740B59,0xB3FC3373,
+0xFE6025C5,0xF6000C55,0xE00010E1,0xCA003375,0xFF802BE9,0xFF8C3087,0xFF8C323F,0xFF70239D,0xFF4C19E6,0xFF2C1017,0xFF240BD8,0xFF040545,0xFF782B2A,0xFF5C221F,0xFF100FAE,0xFE640002,0x9FFC3373,0x1D00B5B,0xFFC40A0B,0xFFC008EE,0xFFBC0882,0xFFBC0809,0xFFA4061E,0xFFA4053D,0xFF9402EB,0xFF88019A,0xFF780001,0xBDFC0B58,0xFFAC095D,0xFF9C0882,0xFF7C0556,0xFF640335,
+0xFF380001,0xDFF80B58,0xFF340882,0xFE6C0000,0xE8000B58,0xBDFC0B58,0xFFAC095D,0xFF9C0882,0xFF7C0556,0xFF640335,0xFF380001,0xDFF80B58,0xFF340882,0xFE6C0000,0xE8000B58,0xDFF80B58,0xFF340882,0xFE6C0000,0xE8000B58,0xE8000B58,0xFDCC0A58,0xFFCC0AB3,0xFFCC0B13,0xFFB40941,0xFFA407A1,0xFF7C0571,0xFF7C03E8,0xFF4802D0,0xFFC40A5B,0xFFB00926,0xFF700892,0xFE6C0000,
+0xD7FC0B58,0x17425C6,0x17425C6,0x17425C6,0x17425C6,0xFF5C1969,0xFF5C1969,0xFF5C1969,0xFF380E81,0xFF380E81,0xFF300A69,0xFF441758,0xFF441758,0xFF441758,0xFF140831,0xFF140831,0xFF0001F9,0xFEF00984,0xFEF00984,0xF4E00104,0xDCE80884,0x31FC25C5,0x31FC25C5,0x31FC25C5,0xFEF01301,0xFEF01301,0xFECC0A69,0xFEA00EBB,0xFEA00EBB,0xFE640002,0xDC800884,0x9BF825C5,
+0x9BF825C5,0xF2000BD5,0xD6000BF4,0xBA0025C5,0xFF682010,0xFF6C2345,0x17425C6,0xFF541A99,0xFF401434,0xFF2C0E5E,0xFF240BD8,0xFF040545,0xFF501F9B,0xFF4419D4,0xFEFC0F78,0xFE640002,0x7FFC25C5,0x1BC0882,0x1BC0882,0x1BC0882,0x1BC0882,0xFFA4053D,0xFFA4053D,0xFFA4053D,0xFF88019A,0xFF88019A,0xFF780001,0x9BFC0882,0x9BFC0882,0x9BFC0882,0xFF640335,0xFF640335,
+0xFF380001,0xCFF80882,0xCFF80882,0xFE6C0000,0xDC000884,0x9BFC0882,0x9BFC0882,0x9BFC0882,0xFF640335,0xFF640335,0xFF380001,0xCFF80882,0xCFF80882,0xFE6C0000,0xDC000884,0xCFF80882,0xCFF80882,0xFE6C0000,0xDC000884,0xDC000884,0xFBB407C1,0xF5B80802,0x1BC0882,0xFFA4071A,0xFF9805F5,0xFF7C04C8,0xFF7C03E8,0xFF4802D0,0xFDB007C1,0xFF9806F5,0xC1FC0882,0xFE6C0000,
+0xC1FC0882,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1300A69,0x1300A69,0x1300A69,0x1300A69,0x1300A69,0x1300A69,0x1300A69,0x1300A69,0x1300A69,0x1300A69,0xFF0001F9,0xFF0001F9,0xFF0001F9,0xFF0001F9,0xFF0001F9,
+0xFF0001F9,0xE0E80000,0xE0E80000,0xE0E80000,0xBCE80000,0x1C40A69,0x1C40A69,0x1C40A69,0x1C40A69,0x1C40A69,0x1C40A69,0xFE640002,0xFE640002,0xFE640002,0xBCA00000,0x67F80A69,0x67F80A69,0x67F80A69,0xB8000050,0x98000A69,0xFD280884,0x1300A69,0x1300A69,0xFF200659,0xFF1404BD,0xFF080340,0xFF080340,0xFEF400CD,0xFF1007E9,0xFD100622,0xFED8000A,0xFE640002,
+0x3FF80A69,};
+static const uint32_t g_etc1_to_bc7_m6_table220[] = {
+0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0x1740000,0x1740000,0x1740000,0x1740000,0x1740000,0x1740000,0x1740000,0x1740000,0x1740000,0x1740000,0x3FF80000,
+0x3FF80000,0x3FF80000,0x3FF80000,0x7C000000,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xF80001,0xD080000,0xD080000,0xD080000,0x1740000,0xBFC0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,
+0x53FC0000,0xABF80000,0xABF80000,0xABF80000,0xC4000001,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0x53FC0000,0xABF80000,0xABF80000,0xABF80000,0xC4000001,0xABF80000,0xABF80000,0xABF80000,0xC4000001,0xC4000001,0xBA40000,0x18C0000,0x18C0000,0x1CC0000,0x1F00000,0x2BFC0000,0x2BFC0000,0x73FC0000,0x1CC0000,0x1F00000,0x95FC0000,0xABF80000,
+0x95FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1A02C8F,0xFF8C2726,0xFF8822B7,0xFF80212E,0xFF801F75,0xFF68194A,0xFF6816D9,0xFF5810F7,0xFF4C0DDA,0xFF440A69,0xFF681F8A,0xFF5017A7,0xFF50145E,0xFF380C25,0xFF2C07B9,0xFF180271,0xFF200D42,0xFF080792,0xFAF8009A,0xEAF8087A,0x71FC2C8F,0xFF58247E,0xFF44212D,0xFF201735,0xFF081185,0xFEE80A69,0xFEF015BA,0xFEB80C99,0xFE880020,0xEA900879,0xB9FC2C8F,
+0xFE84212D,0xF8000AED,0xE6000C45,0xD0002C91,0xFF8C262B,0xF79C2A69,0xF9A02B7E,0xFF701F1D,0xFF5816D7,0xFF3C0E7E,0xFF3C0AF6,0xFF1404FA,0xFF8025C2,0xFF681E1D,0xFF1C0D7A,0xFE880020,0xA7FC2C8F,0x1D80876,0xFFD00776,0xFFC806AE,0xFFC40659,0xFFC405E2,0xFFB00491,0xFFB003E8,0xFFA00226,0xFF940131,0xFF8C0000,0xC7FC0876,0xFFB806FA,0xFFA80659,0xFF8803F3,0xFF700262,
+0xFF540000,0xE3FC0876,0xFF4C0659,0xFEA00000,0xEA000879,0xC7FC0876,0xFFB806FA,0xFFA80659,0xFF8803F3,0xFF700262,0xFF540000,0xE3FC0876,0xFF4C0659,0xFEA00000,0xEA000879,0xE3FC0876,0xFF4C0659,0xFEA00000,0xEA000879,0xEA000879,0xFFD0079D,0xFFCC0822,0xF5D80851,0xFFC006D9,0xFFAC05A1,0xFFA0042C,0xFF8C02F2,0xFF640209,0xFFD007BE,0xFFC006B9,0xFF840669,0xFEA00000,
+0xDDF80876,0x180212E,0x180212E,0x180212E,0x180212E,0xFF6816D9,0xFF6816D9,0xFF6816D9,0xFF4C0DDA,0xFF4C0DDA,0xFF440A69,0xFF50145E,0xFF50145E,0xFF50145E,0xFF2C07B9,0xFF2C07B9,0xFF180271,0xFF080792,0xFF080792,0xF8F4007E,0xE2F8065A,0x43FC212D,0x43FC212D,0x43FC212D,0xFF081185,0xFF081185,0xFEE80A69,0xFEB80C99,0xFEB80C99,0xFE880020,0xE294065A,0xA3FC212D,
+0xA3FC212D,0xF8000AC9,0xDC0008A6,0xC000212D,0xFF741C62,0xF9801F46,0x180212E,0xFF5C17A3,0xFF541226,0xFF3C0CEE,0xFF3C0AF6,0xFF1404FA,0xFF641BFE,0xFF5016B4,0xFF1C0D49,0xFE880020,0x8BFC212D,0x1C40659,0x1C40659,0x1C40659,0x1C40659,0xFFB003E8,0xFFB003E8,0xFFB003E8,0xFF940131,0xFF940131,0xFF8C0000,0xA9FC0659,0xA9FC0659,0xA9FC0659,0xFF700262,0xFF700262,
+0xFF540000,0xD5F80659,0xD5F80659,0xFEA00000,0xE2000659,0xA9FC0659,0xA9FC0659,0xA9FC0659,0xFF700262,0xFF700262,0xFF540000,0xD5F80659,0xD5F80659,0xFEA00000,0xE2000659,0xD5F80659,0xD5F80659,0xFEA00000,0xE2000659,0xE2000659,0xFFBC05B4,0xFBC405E9,0x1C40659,0xFFB4054A,0xFFAC0480,0xFF9403B5,0xFF8C02F2,0xFF640209,0xFFB405BA,0xFFA4053D,0xC9FC0659,0xFEA00000,
+0xC9FC0659,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1440A69,0x1440A69,0x1440A69,0x1440A69,0x1440A69,0x1440A69,0x1440A69,0x1440A69,0x1440A69,0x1440A69,0xFF180271,0xFF180271,0xFF180271,0xFF180271,0xFF180271,
+0xFF180271,0xE8FC0001,0xE8FC0001,0xE8FC0001,0xC4F80002,0x1E00A69,0x1E00A69,0x1E00A69,0x1E00A69,0x1E00A69,0x1E00A69,0xFE880020,0xFE880020,0xFE880020,0xC4B40001,0x73FC0A69,0x73FC0A69,0x73FC0A69,0xC200002D,0xA0000A69,0xF73C08C5,0x1440A69,0x1440A69,0xFF2C06B2,0xFF280521,0xFF1803BA,0xFF1803BA,0xFF080131,0xF9300841,0xFF200665,0xFEF0002D,0xFE880020,
+0x4FFC0A69,};
+static const uint32_t g_etc1_to_bc7_m6_table221[] = {
+0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x18C0000,0x4BF80000,
+0x4BF80000,0x4BF80000,0x4BF80000,0x84000000,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x1080001,0x11C0000,0x11C0000,0x11C0000,0x18C0000,0x1BFC0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x19C0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,
+0x6BFC0000,0xB7F80000,0xB7F80000,0xB7F80000,0xCC000001,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0x6BFC0000,0xB7F80000,0xB7F80000,0xB7F80000,0xCC000001,0xB7F80000,0xB7F80000,0xB7F80000,0xCC000001,0xCC000001,0x1B80000,0x19C0000,0x19C0000,0x1E00000,0x11FC0000,0x49FC0000,0x49FC0000,0x87FC0000,0x1E00000,0x11FC0000,0xA3FC0000,0xB7F80000,
+0xA3FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1A826F7,0xFF982262,0xFF901EC2,0xFF8C1D72,0xFF8C1C09,0xFF7416DE,0xFF7414CD,0xFF640FDB,0xFF580D4E,0xFF540A69,0xFF741B8A,0xFF6814D7,0xFF5C120E,0xFF400B3C,0xFF380755,0xFF2402E9,0xFF2C0B0A,0xFF200632,0xFD08003A,0xEF080642,0x7DFC26F7,0xFF64202E,0xFF541D72,0xFF2C1515,0xFF201055,0xFF000A69,0xFEFC12C2,0xFED80B12,0xFEA00050,0xEEA00642,0xBFFC26F7,
+0xFEA01D72,0xFE000A6D,0xE60008D5,0xD40026F9,0xFFA021AB,0xFBA42501,0xFDA825FE,0xFF801B4F,0xFF6C146F,0xFF540D63,0xFF3C0A46,0xFF2804D2,0xFF9020F8,0xFF741A72,0xFF300B96,0xFEA00050,0xAFFC26F7,0x1DC0642,0xFFD4058D,0xFFCC04F1,0xFFCC04B1,0xFFC40462,0xFFBC035D,0xFFBC02E4,0xFFAC0192,0xFFA000E5,0xFF9C0000,0xCFFC0641,0xFFB8052A,0xFFB404B1,0xFFA002E3,0xFF8801BA,
+0xFF6C0000,0xE7FC0641,0xFF6404B1,0xFED40000,0xEE000641,0xCFFC0641,0xFFB8052A,0xFFB404B1,0xFFA002E3,0xFF8801BA,0xFF6C0000,0xE7FC0641,0xFF6404B1,0xFED40000,0xEE000641,0xE7FC0641,0xFF6404B1,0xFED40000,0xEE000641,0xEE000641,0xFFD805A2,0xF7DC0600,0xF7DC0621,0xFFC4051A,0xFFC0042D,0xFFA80302,0xFFA0022D,0xFF740184,0xFFD005AE,0xFFC804E1,0xFF9404BA,0xFED40000,
+0xE1FC0641,0x18C1D72,0x18C1D72,0x18C1D72,0x18C1D72,0xFF7414CD,0xFF7414CD,0xFF7414CD,0xFF580D4E,0xFF580D4E,0xFF540A69,0xFF5C120E,0xFF5C120E,0xFF5C120E,0xFF380755,0xFF380755,0xFF2402E9,0xFF200632,0xFF200632,0xFB040032,0xE70804B2,0x53FC1D72,0x53FC1D72,0x53FC1D72,0xFF201055,0xFF201055,0xFF000A69,0xFED80B12,0xFED80B12,0xFEA00050,0xE6A804B2,0xABF81D72,
+0xABF81D72,0xFC000A6D,0xE0000631,0xC4001D75,0xFF841959,0xFD881BB6,0x18C1D72,0xFF701549,0xFF581073,0xFF4C0C25,0xFF3C0A46,0xFF2804D2,0xFF7818E3,0xFF5C14A8,0xFF300B72,0xFEA00050,0x95FC1D72,0x1CC04B1,0x1CC04B1,0x1CC04B1,0x1CC04B1,0xFFBC02E4,0xFFBC02E4,0xFFBC02E4,0xFFA000E5,0xFFA000E5,0xFF9C0000,0xB5FC04B1,0xB5FC04B1,0xB5FC04B1,0xFF8801BA,0xFF8801BA,
+0xFF6C0000,0xDBF804B1,0xDBF804B1,0xFED40000,0xE60004B1,0xB5FC04B1,0xB5FC04B1,0xB5FC04B1,0xFF8801BA,0xFF8801BA,0xFF6C0000,0xDBF804B1,0xDBF804B1,0xFED40000,0xE60004B1,0xDBF804B1,0xDBF804B1,0xFED40000,0xE60004B1,0xE60004B1,0xF7C80451,0xFFCC0451,0x1CC04B1,0xFDC003F5,0xFFAC0340,0xFFA002A8,0xFFA0022D,0xFF740184,0xF9C40451,0xFFB003E8,0xD1FC04B1,0xFED40000,
+0xD1FC04B1,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1540A69,0x1540A69,0x1540A69,0x1540A69,0x1540A69,0x1540A69,0x1540A69,0x1540A69,0x1540A69,0x1540A69,0xFF2402E9,0xFF2402E9,0xFF2402E9,0xFF2402E9,0xFF2402E9,
+0xFF2402E9,0xF10C0001,0xF10C0001,0xF10C0001,0xCD080002,0x1F80A69,0x1F80A69,0x1F80A69,0x1F80A69,0x1F80A69,0x1F80A69,0xFEA00050,0xFEA00050,0xFEA00050,0xCCC40001,0x7FFC0A69,0x7FFC0A69,0x7FFC0A69,0xCA000012,0xA8000A69,0xFF4C08C5,0x1540A69,0x1540A69,0xFF3C06F5,0xFF34057A,0xFF34042A,0xFF34042A,0xFF1C0195,0xFF3C0845,0xFF34069A,0xFEFC007A,0xFEA00050,
+0x5FF80A69,};
+static const uint32_t g_etc1_to_bc7_m6_table222[] = {
+0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x1A40000,0x57F80000,
+0x57F80000,0x57F80000,0x57F80000,0x8C000000,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x1180001,0x12C0000,0x12C0000,0x12C0000,0x1A40000,0x29FC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x1AC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,
+0x83FC0000,0xC3F80000,0xC3F80000,0xC3F80000,0xD4000001,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0x83FC0000,0xC3F80000,0xC3F80000,0xC3F80000,0xD4000001,0xC3F80000,0xC3F80000,0xC3F80000,0xD4000001,0xD4000001,0x1C80000,0x1AC0000,0x1AC0000,0x3F00000,0x37FC0000,0x67FC0000,0x67FC0000,0x9BFC0000,0x3F00000,0x37FC0000,0xB3FC0000,0xC3F80000,
+0xB3FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1B021DF,0xFFA41E16,0xFF9C1B22,0xFF981A0E,0xFF9818ED,0xFF8014AA,0xFF8012F1,0xFF700EDF,0xFF700CCE,0xFF640A69,0xFF8017F2,0xFF741257,0xFF681006,0xFF580A54,0xFF4C0723,0xFF3C0361,0xFF380932,0xFF2C0506,0xFF18000A,0xF1180462,0x89FC21DF,0xFF701C46,0xFF641A0D,0xFF381345,0xFF2C0F41,0xFF180A69,0xFF14101A,0xFEF009AA,0xFEB800A0,0xF0B80461,0xC5FC21DF,
+0xFEC01A0D,0xFE200A69,0xEC0005DD,0xD80021E1,0xFFA01D2B,0xFFAC2019,0xFFAC2106,0xFF881837,0xFF78124A,0xFF5C0C29,0xFF5009B3,0xFF4004BB,0xFF941CEE,0xFF801747,0xFF3C0A2E,0xFEB800A0,0xB7FC21DF,0x1E40462,0xFFDC03DA,0xFFD80371,0xFFD40349,0xFFD00306,0xFFC80259,0xFFC401F9,0xFFB80116,0xFFB8009D,0xFFAC0000,0xD5FC0461,0xFFCC03A1,0xFFC00349,0xFFAC01FB,0xFFA00132,
+0xFF840000,0xEBF80461,0xFF7C0349,0xFF040000,0xF0000461,0xD5FC0461,0xFFCC03A1,0xFFC00349,0xFFAC01FB,0xFFA00132,0xFF840000,0xEBF80461,0xFF7C0349,0xFF040000,0xF0000461,0xEBF80461,0xFF7C0349,0xFF040000,0xF0000461,0xF0000461,0xFFD803F2,0xF9E0042C,0xF9E00449,0xFFD40382,0xFFC802E2,0xFFB80212,0xFFA80172,0xFF8C0112,0xFFDC03F8,0xFFC80371,0xFFA40352,0xFF040000,
+0xE5FC0461,0x1981A0E,0x1981A0E,0x1981A0E,0x1981A0E,0xFF8012F1,0xFF8012F1,0xFF8012F1,0xFF700CCE,0xFF700CCE,0xFF640A69,0xFF681006,0xFF681006,0xFF681006,0xFF4C0723,0xFF4C0723,0xFF3C0361,0xFF2C0506,0xFF2C0506,0xFD180009,0xEB18034A,0x63FC1A0D,0x63FC1A0D,0x63FC1A0D,0xFF2C0F41,0xFF2C0F41,0xFF180A69,0xFEF009AA,0xFEF009AA,0xFEB800A0,0xEABC034A,0xB3F81A0D,
+0xB3F81A0D,0xFE200A69,0xE6000425,0xCA001A0D,0xFF841689,0xFF8C18AA,0x1981A0E,0xFF801316,0xFF6C0EEB,0xFF5C0B29,0xFF5009B3,0xFF4004BB,0xFF80163E,0xFF741269,0xFF3C0A0A,0xFEB800A0,0x9FF81A0D,0x1D40349,0x1D40349,0x1D40349,0x1D40349,0xFFC401F9,0xFFC401F9,0xFFC401F9,0xFFB8009D,0xFFB8009D,0xFFAC0000,0xC1FC0349,0xC1FC0349,0xC1FC0349,0xFFA00132,0xFFA00132,
+0xFF840000,0xE1F80349,0xE1F80349,0xFF040000,0xEA000349,0xC1FC0349,0xC1FC0349,0xC1FC0349,0xFFA00132,0xFFA00132,0xFF840000,0xE1F80349,0xE1F80349,0xFF040000,0xEA000349,0xE1F80349,0xE1F80349,0xFF040000,0xEA000349,0xEA000349,0xFBD002F9,0xFFCC0311,0x1D40349,0xFFC402B9,0xFFC00244,0xFFB001D4,0xFFA80172,0xFF8C0112,0xFDCC02F9,0xFFC402AD,0xD9FC0349,0xFF040000,
+0xD9FC0349,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1640A69,0x1640A69,0x1640A69,0x1640A69,0x1640A69,0x1640A69,0x1640A69,0x1640A69,0x1640A69,0x1640A69,0xFF3C0361,0xFF3C0361,0xFF3C0361,0xFF3C0361,0xFF3C0361,
+0xFF3C0361,0xF91C0001,0xF91C0001,0xF91C0001,0xD5180002,0x13FC0A69,0x13FC0A69,0x13FC0A69,0x13FC0A69,0x13FC0A69,0x13FC0A69,0xFEB800A0,0xFEB800A0,0xFEB800A0,0xD4D40001,0x8BFC0A69,0x8BFC0A69,0x8BFC0A69,0xD4000005,0xB0000A69,0xF75C090A,0x1640A69,0x1640A69,0xFF4C073A,0xFF5005E9,0xFF440492,0xFF440492,0xFF300209,0xFB500884,0xFD4C0708,0xFF1800CD,0xFEB800A0,
+0x6DFC0A69,};
+static const uint32_t g_etc1_to_bc7_m6_table223[] = {
+0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x61FC0000,
+0x61FC0000,0x61FC0000,0x61FC0000,0x94000000,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x1280001,0x73C0000,0x73C0000,0x73C0000,0x1BC0000,0x39FC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x1BC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,
+0x9BFC0000,0xCFF80000,0xCFF80000,0xCFF80000,0xDC000001,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0x9BFC0000,0xCFF80000,0xCFF80000,0xCFF80000,0xDC000001,0xCFF80000,0xCFF80000,0xCFF80000,0xDC000001,0xDC000001,0x5D80000,0x1BC0000,0x1BC0000,0x17FC0000,0x5FFC0000,0x85FC0000,0x85FC0000,0xAFFC0000,0x17FC0000,0x5FFC0000,0xC1FC0000,0xCFF80000,
+0xC1FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1B81D47,0xFFB01A42,0xFFA017DF,0xFFA016FE,0xFF98161D,0xFF9012AA,0xFF8C1145,0xFF7C0E03,0xFF7C0C4A,0xFF740A69,0xFF8C14C2,0xFF801027,0xFF740E46,0xFF640994,0xFF5806FB,0xFF5003DA,0xFF4C07C3,0xFF380432,0xFF2C0002,0xF32802DA,0x95FC1D47,0xFF7C18C6,0xFF7416FD,0xFF581187,0xFF400E66,0xFF300A69,0xFF2C0DD2,0xFF080882,0xFED80112,0xF4CC02D9,0xCBFC1D47,
+0xFEE416FD,0xFE540A69,0xF000039A,0xDC001D49,0xFFA8198F,0xFFAC1C09,0xF5B81CBF,0xFF981527,0xFF801057,0xFF700B37,0xFF680929,0xFF4804DA,0xFFA01957,0xFF90147F,0xFF50092A,0xFED80112,0xBFF81D47,0x1E802D6,0xFFE00289,0xFFE0023E,0xFFDC0221,0xFFDC01F2,0xFFD00185,0xFFD00145,0xFFCC00C0,0xFFC00068,0xFFBC0000,0xDFFC02D6,0xFFD8025D,0xFFCC0221,0xFFB80143,0xFFAC00C2,
+0xFF9C0000,0xEFFC02D6,0xFF940221,0xFF340000,0xF20002D9,0xDFFC02D6,0xFFD8025D,0xFFCC0221,0xFFB80143,0xFFAC00C2,0xFF9C0000,0xEFFC02D6,0xFF940221,0xFF340000,0xF20002D9,0xEFFC02D6,0xFF940221,0xFF340000,0xF20002D9,0xF20002D9,0xFFE40296,0xFDE802AC,0xFDE802C1,0xFFDC0238,0xFFD401E1,0xFFB80162,0xFFB800F5,0xFFA000A9,0xFFDC0298,0xFFDC0233,0xFFB40225,0xFF340000,
+0xEBFC02D6,0x1A016FE,0x1A016FE,0x1A016FE,0x1A016FE,0xFF8C1145,0xFF8C1145,0xFF8C1145,0xFF7C0C4A,0xFF7C0C4A,0xFF740A69,0xFF740E46,0xFF740E46,0xFF740E46,0xFF5806FB,0xFF5806FB,0xFF5003DA,0xFF380432,0xFF380432,0xFF2C0002,0xEF280222,0x75FC16FD,0x75FC16FD,0x75FC16FD,0xFF400E66,0xFF400E66,0xFF300A69,0xFF080882,0xFF080882,0xFED80112,0xEED00222,0xBBFC16FD,
+0xBBFC16FD,0xFE540A69,0xEC000289,0xD00016FD,0xFF901433,0xF9A015ED,0x1A016FE,0xFF88111E,0xFF800DB3,0xFF680A6E,0xFF680929,0xFF4804DA,0xFF9013B8,0xFF8010A6,0xFF500911,0xFED80112,0xA9FC16FD,0x1DC0221,0x1DC0221,0x1DC0221,0x1DC0221,0xFFD00145,0xFFD00145,0xFFD00145,0xFFC00068,0xFFC00068,0xFFBC0000,0xCDFC0221,0xCDFC0221,0xCDFC0221,0xFFAC00C2,0xFFAC00C2,
+0xFF9C0000,0xE7F80221,0xE7F80221,0xFF340000,0xEE000221,0xCDFC0221,0xCDFC0221,0xCDFC0221,0xFFAC00C2,0xFFAC00C2,0xFF9C0000,0xE7F80221,0xE7F80221,0xFF340000,0xEE000221,0xE7F80221,0xE7F80221,0xFF340000,0xEE000221,0xEE000221,0xFFD801E1,0xF7DC0200,0x1DC0221,0xFFD401C2,0xFFC80179,0xFFB80131,0xFFB800F5,0xFFA000A9,0xFFD001ED,0xFFC801BD,0xDFFC0221,0xFF340000,
+0xDFFC0221,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1740A69,0x1740A69,0x1740A69,0x1740A69,0x1740A69,0x1740A69,0x1740A69,0x1740A69,0x1740A69,0x1740A69,0xFF5003DA,0xFF5003DA,0xFF5003DA,0xFF5003DA,0xFF5003DA,
+0xFF5003DA,0xFF2C0002,0xFF2C0002,0xFF2C0002,0xDD280002,0x2BFC0A69,0x2BFC0A69,0x2BFC0A69,0x2BFC0A69,0x2BFC0A69,0x2BFC0A69,0xFED80112,0xFED80112,0xFED80112,0xDCE40001,0x97FC0A69,0x97FC0A69,0x97FC0A69,0xDC040001,0xB8000A69,0xFF6C090A,0x1740A69,0x1740A69,0xFF680782,0xFF580652,0xFF540502,0xFF540502,0xFF40028A,0xFF5808B4,0xFF500750,0xFF300132,0xFED80112,
+0x7DF80A69,};
+static const uint32_t g_etc1_to_bc7_m6_table224[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x5C0001,0x5C0001,0x5C0001,0x5C0001,0x8C0000,0x8C0000,0x8C0000,0x1180000,0x1180000,0x2E000000,0x8C0000,0x8C0000,0x8C0000,0x1180000,0x1180000,0x2E000000,0x1180000,0x1180000,0x2E000000,0x2E000000,0x8C0000,0x8C0000,0x8C0000,0x1180000,0x1180000,0x2E000000,0x1180000,0x1180000,0x2E000000,0x2E000000,0x1180000,
+0x1180000,0x2E000000,0x2E000000,0x2E000000,0x6C0000,0x640000,0x5C0001,0x800000,0x9C0000,0xC80000,0xE40000,0x15C0000,0x2740000,0x8C0000,0xC80000,0x2E000000,0xC80000,0x16C0001,0x25FC0000,0x95F80000,0xB6000000,0x25FC0000,0x95F80000,0xB6000000,0x95F80000,0xB6000000,0xB6000000,0x25FC0000,0x95F80000,0xB6000000,0x95F80000,0xB6000000,
+0xB6000000,0x95F80000,0xB6000000,0xB6000000,0xB6000000,0x25FC0000,0x95F80000,0xB6000000,0x95F80000,0xB6000000,0xB6000000,0x95F80000,0xB6000000,0xB6000000,0xB6000000,0x95F80000,0xB6000000,0xB6000000,0xB6000000,0xB6000000,0x1CC0000,0xB840000,0xB840000,0x4FFC0000,0x87F80000,0xA5F80000,0xB6000000,0xB6000000,0x3F00000,0x67FC0000,0xB3D80000,0xB6000000,
+0x79FC0000,0x7457CA,0xFE442041,0xFE2005E5,0xB62005C1,0xFE182962,0xF4000585,0xB4000094,0xAA002420,0x96000F64,0x72002420,0xEA004691,0xCC001B02,0xA2000CAD,0x98002F04,0x88001816,0x6E002950,0x72004691,0x72002CBD,0x5C0036EC,0x4C004691,0xA857CA,0xAE002A47,0x92001711,0x860037C0,0x80001F6C,0x68002DF0,0x68004B75,0x6C0031E9,0x56003AAD,0x480048F9,0x15857CA,
+0x5C003E8D,0x500043F0,0x44004F85,0x380057CA,0xFE3438A1,0xFA644CC8,0xFE6C4B89,0xFE001F2A,0xE200192D,0xAC001816,0x92001141,0x82001EEA,0xFE1837C5,0xFC002039,0x86002331,0x56003AAD,0xF057CA,0x984692,0xFE5C1A55,0xFE300461,0xB6300451,0xFE302822,0xF4000585,0xB4000094,0xAA002420,0x96000F64,0x72002420,0xE44691,0xCC001B02,0xA2000CAD,0x98002F04,0x88001816,
+0x6E002950,0x1D04691,0x72002CBD,0x5C0036EC,0x4C004691,0xE44691,0xCC001B02,0xA2000CAD,0x98002F04,0x88001816,0x6E002950,0x1D04691,0x72002CBD,0x5C0036EC,0x4C004691,0x1D04691,0x72002CBD,0x5C0036EC,0x4C004691,0x4C004691,0xFE503353,0xFC883FC2,0xFE8C3D0E,0xFE001F2A,0xE200192D,0xAC001816,0x92001141,0x82001EEA,0xFE3433C8,0xFC001F39,0x860022F1,0x5C0036EC,
+0x1484691,0x2005C1,0x2005C1,0x2005C1,0x2005C1,0x8E000000,0x8E000000,0x8E000000,0x44000001,0x44000001,0x2E000000,0x44000451,0x44000451,0x44000451,0x3400019A,0x3400019A,0x280000CD,0x22000451,0x22000451,0x200002A8,0x16000451,0x3005C1,0x3005C1,0x3005C1,0x2E0002A3,0x2E0002A3,0x28000176,0x1E0004C1,0x1E0004C1,0x1C000311,0x1400048E,0x5C05C1,
+0x5C05C1,0x16000402,0x1000051E,0xE0005C2,0xF6000171,0xF21402AC,0x2005C1,0x900001D0,0x5A0001A8,0x440001A8,0x40000161,0x2E0001F9,0x9600030A,0x66000286,0x2A00045A,0x1C000311,0x4005C1,0x300451,0x300451,0x300451,0x300451,0x8E000000,0x8E000000,0x8E000000,0x44000001,0x44000001,0x2E000000,0x440451,0x440451,0x440451,0x3400019A,0x3400019A,
+0x280000CD,0x880451,0x880451,0x200002A8,0x16000451,0x440451,0x440451,0x440451,0x3400019A,0x3400019A,0x280000CD,0x880451,0x880451,0x200002A8,0x16000451,0x880451,0x880451,0x200002A8,0x16000451,0x16000451,0xF6000171,0xF8200200,0x300451,0x900001D0,0x5A0001A8,0x440001A8,0x40000161,0x2E0001F9,0x960002B9,0x6C00025D,0x600451,0x200002A8,
+0x600451,0xE42422,0xFE980C49,0xF8600001,0xB65C0001,0x1542420,0xF4000585,0xB4000094,0x2FFC2420,0x96000F64,0x72002420,0x1542420,0xF4000585,0xB4000094,0x2FFC2420,0x96000F64,0x72002420,0x2FFC2420,0x96000F64,0x72002420,0x72002420,0x1542420,0xF4000585,0xB4000094,0x2FFC2420,0x96000F64,0x72002420,0x2FFC2420,0x96000F64,0x72002420,0x72002420,0x2FFC2420,
+0x96000F64,0x72002420,0x72002420,0x72002420,0xFAAC1E85,0x2F42420,0xF6DC1F81,0xFE4015A0,0xF6001009,0xBC000EF9,0x9E000AE1,0x9000133D,0xFE901E08,0xFE14145D,0xA6000988,0x72002420,0x1E82420,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table225[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x6C0001,0x6C0001,0x6C0001,0x6C0001,0xA40000,0xA40000,0xA40000,0x14C0000,0x14C0000,0x36000000,0xA40000,0xA40000,0xA40000,0x14C0000,0x14C0000,0x36000000,0x14C0000,0x14C0000,0x36000000,0x36000000,0xA40000,0xA40000,0xA40000,0x14C0000,0x14C0000,0x36000000,0x14C0000,0x14C0000,0x36000000,0x36000000,0x14C0000,
+0x14C0000,0x36000000,0x36000000,0x36000000,0x800000,0x2740000,0x6C0001,0x940000,0xB80000,0xE80000,0x10C0000,0x1980000,0x2880000,0xA40000,0xE80000,0x36000000,0xE80000,0x17C0001,0x3DFC0000,0xA1F80000,0xBE000000,0x3DFC0000,0xA1F80000,0xBE000000,0xA1F80000,0xBE000000,0xBE000000,0x3DFC0000,0xA1F80000,0xBE000000,0xA1F80000,0xBE000000,
+0xBE000000,0xA1F80000,0xBE000000,0xBE000000,0xBE000000,0x3DFC0000,0xA1F80000,0xBE000000,0xA1F80000,0xBE000000,0xBE000000,0xA1F80000,0xBE000000,0xBE000000,0xBE000000,0xA1F80000,0xBE000000,0xBE000000,0xBE000000,0xBE000000,0x1E00000,0x1980000,0x1980000,0x63FC0000,0x95F80000,0xAFF80000,0xBE000000,0xBE000000,0xFFC0000,0x77FC0000,0xBBE80000,0xBE000000,
+0x87FC0000,0x7C5F3A,0xFE442651,0xFE280892,0xBE2407E1,0xFE242C5A,0xFA0004BD,0xBA000034,0xB6002420,0x9C000E48,0x7A002420,0xF8004B86,0xE2001C71,0xA8000DB5,0xA200306B,0x92001820,0x74002A0C,0x78004B89,0x78002F69,0x660039D9,0x50004B89,0xB45F3A,0xBA002DB7,0xA2001906,0x92003AA0,0x86002070,0x6E002F60,0x6E005129,0x72003541,0x60003DE9,0x4C004E42,0x1705F3A,
+0x5C0043BD,0x56004888,0x440055C5,0x3C005F3A,0xFE503ED3,0xFE6C5368,0xFE6C52D9,0xFE142325,0xF600193D,0xBC0017ED,0x9E0010D5,0x8A001F71,0xFE183E05,0xFC002279,0x9400251B,0x60003DE9,0x1005F3A,0xA44B86,0xFE681ED9,0xFE38064D,0xBE3805E9,0xFE3C2A76,0xFA0004BD,0xBA000034,0xB6002420,0x9C000E48,0x7A002420,0xF44B86,0xE2001C71,0xA8000DB5,0xA200306B,0x92001820,
+0x74002A0C,0x1F04B86,0x78002F69,0x660039D9,0x50004B89,0xF44B86,0xE2001C71,0xA8000DB5,0xA200306B,0x92001820,0x74002A0C,0x1F04B86,0x78002F69,0x660039D9,0x50004B89,0x1F04B86,0x78002F69,0x660039D9,0x50004B89,0x50004B89,0xFE64380A,0xFE8C4466,0xFE8C426E,0xFE1422C1,0xF600193D,0xBC0017ED,0x9E0010D5,0x8A001F71,0xFE443845,0xFC002179,0x940024CA,0x660039D9,
+0x15C4B86,0x2407E1,0x2407E1,0x2407E1,0x2407E1,0xA6000000,0xA6000000,0xA6000000,0x50000001,0x50000001,0x36000000,0x500005E9,0x500005E9,0x500005E9,0x40000232,0x40000232,0x2E000121,0x280005E9,0x280005E9,0x260003A4,0x1A0005E9,0x3407E1,0x3407E1,0x3407E1,0x340003AB,0x340003AB,0x2E000202,0x2200067A,0x2200067A,0x20000441,0x18000635,0x6807E1,
+0x6807E1,0x1C000576,0x160006F2,0x120007E2,0xF8040269,0xF61C042C,0x2407E1,0xA400028A,0x68000249,0x4C000254,0x4C0001E1,0x380002BA,0xA400042E,0x72000363,0x320005F2,0x20000441,0x4C07E1,0x3805E9,0x3805E9,0x3805E9,0x3805E9,0xA6000000,0xA6000000,0xA6000000,0x50000001,0x50000001,0x36000000,0x5005E9,0x5005E9,0x5005E9,0x40000232,0x40000232,
+0x2E000121,0xA005E9,0xA005E9,0x260003A4,0x1A0005E9,0x5005E9,0x5005E9,0x5005E9,0x40000232,0x40000232,0x2E000121,0xA005E9,0xA005E9,0x260003A4,0x1A0005E9,0xA005E9,0xA005E9,0x260003A4,0x1A0005E9,0x1A0005E9,0xF8040265,0xFC280320,0x3805E9,0xA400028A,0x68000249,0x4C000254,0x4C0001E1,0x380002BA,0xB40003B5,0x72000332,0x7005E9,0x260003A4,
+0x7005E9,0xF42422,0xFEB00D41,0xFE700002,0xBE6C0001,0x16C2420,0xFA0004BD,0xBA000034,0x3BFC2420,0x9C000E48,0x7A002420,0x16C2420,0xFA0004BD,0xBA000034,0x3BFC2420,0x9C000E48,0x7A002420,0x3BFC2420,0x9C000E48,0x7A002420,0x7A002420,0x16C2420,0xFA0004BD,0xBA000034,0x3BFC2420,0x9C000E48,0x7A002420,0x3BFC2420,0x9C000E48,0x7A002420,0x7A002420,0x3BFC2420,
+0x9C000E48,0x7A002420,0x7A002420,0x7A002420,0xFEB41EAD,0xB042420,0xFEEC1F81,0xFE6C1661,0xF6000F79,0xBC000E29,0xA80009CD,0x94001248,0xFE981E3A,0xFE401528,0xB400084A,0x7A002420,0x7FC2420,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table226[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x7C0001,0x7C0001,0x7C0001,0x7C0001,0xBC0000,0xBC0000,0xBC0000,0x17C0000,0x17C0000,0x3E000000,0xBC0000,0xBC0000,0xBC0000,0x17C0000,0x17C0000,0x3E000000,0x17C0000,0x17C0000,0x3E000000,0x3E000000,0xBC0000,0xBC0000,0xBC0000,0x17C0000,0x17C0000,0x3E000000,0x17C0000,0x17C0000,0x3E000000,0x3E000000,0x17C0000,
+0x17C0000,0x3E000000,0x3E000000,0x3E000000,0x4900000,0xA840000,0x7C0001,0xAC0000,0xD40000,0x10C0000,0x1340000,0x1D40000,0x29C0000,0xBC0000,0x10C0000,0x3E000000,0x10C0000,0x18C0001,0x55FC0000,0xADF80000,0xC6000000,0x55FC0000,0xADF80000,0xC6000000,0xADF80000,0xC6000000,0xC6000000,0x55FC0000,0xADF80000,0xC6000000,0xADF80000,0xC6000000,
+0xC6000000,0xADF80000,0xC6000000,0xC6000000,0xC6000000,0x55FC0000,0xADF80000,0xC6000000,0xADF80000,0xC6000000,0xC6000000,0xADF80000,0xC6000000,0xC6000000,0xC6000000,0xADF80000,0xC6000000,0xC6000000,0xC6000000,0xC6000000,0x1F40000,0x1A80000,0x1A80000,0x77FC0000,0xA1FC0000,0xB9F80000,0xC6000000,0xC6000000,0x2FFC0000,0x89FC0000,0xC3F80000,0xC6000000,
+0x97FC0000,0x84672A,0xFE502CD1,0xFE2C0BE9,0xC6280A59,0xFE303022,0xFE0404C5,0xC6000004,0xC2002420,0xA6000D61,0x82002420,0xFE0450E5,0xE8001E1D,0xB4000EED,0xAE003223,0x98001848,0x7A002AE0,0x800050D1,0x7E00325D,0x6C003CB9,0x560050D1,0xC0672A,0xC6003187,0xA2001B66,0xA2003D84,0x920021A0,0x740030F0,0x74005745,0x780038E9,0x6600415D,0x520053E2,0x188672A,
+0x66004956,0x5C004D70,0x4A005C5D,0x4000672A,0xFE504513,0xFE6C5AE8,0xF67C5B12,0xFE142775,0xF60019AD,0xBC00181D,0xA60010A0,0x90002036,0xFE3444C8,0xFE0025AA,0x96002723,0x6600415D,0x114672A,0xB050D2,0xFE7423CD,0xFE4008E2,0xC64007C1,0xFE442D24,0xFE0404C1,0xC6000004,0xC2002420,0xA6000D61,0x82002420,0x30050D1,0xE8001E1D,0xB4000EED,0xAE003223,0x98001848,
+0x7A002AE0,0x5FC50D1,0x7E00325D,0x6C003CB9,0x560050D1,0x30050D1,0xE8001E1D,0xB4000EED,0xAE003223,0x98001848,0x7A002AE0,0x5FC50D1,0x7E00325D,0x6C003CB9,0x560050D1,0x5FC50D1,0x7E00325D,0x6C003CB9,0x560050D1,0x560050D1,0xFE783CC9,0xF8A049A0,0xFCA84789,0xFE142711,0xF60019AD,0xBC00181D,0xA60010A0,0x90002036,0xFC583D2B,0xFE0424A1,0x960026D2,0x6C003CB9,
+0x17050D1,0x280A59,0x280A59,0x280A59,0x280A59,0xBE000000,0xBE000000,0xBE000000,0x5C000001,0x5C000001,0x3E000000,0x5C0007C1,0x5C0007C1,0x5C0007C1,0x4C0002EA,0x4C0002EA,0x3A000179,0x2E0007C1,0x2E0007C1,0x2C0004C8,0x1E0007C1,0x23C0A56,0x23C0A56,0x23C0A56,0x400004DB,0x400004DB,0x340002A6,0x28000882,0x28000882,0x2600058D,0x1E000825,0x7C0A56,
+0x7C0A56,0x2000074C,0x1A00092D,0x14000A56,0xFA0803B9,0xF8200600,0x280A59,0xBA00034D,0x7C000301,0x62000308,0x5600028A,0x40000385,0xC200057A,0x9000047B,0x3A0007D1,0x2600058D,0x580A56,0x4007C1,0x4007C1,0x4007C1,0x4007C1,0xBE000000,0xBE000000,0xBE000000,0x5C000001,0x5C000001,0x3E000000,0x5C07C1,0x5C07C1,0x5C07C1,0x4C0002EA,0x4C0002EA,
+0x3A000179,0xB807C1,0xB807C1,0x2C0004C8,0x1E0007C1,0x5C07C1,0x5C07C1,0x5C07C1,0x4C0002EA,0x4C0002EA,0x3A000179,0xB807C1,0xB807C1,0x2C0004C8,0x1E0007C1,0xB807C1,0xB807C1,0x2C0004C8,0x1E0007C1,0x1E0007C1,0xFC0C039D,0xFE2C0488,0x4007C1,0xBA00034D,0x7C000301,0x62000308,0x5600028A,0x40000385,0xC20004EA,0x9000042A,0x8007C1,0x2C0004C8,
+0x8007C1,0x1042422,0xFEC40E2A,0xFE84002D,0xC67C0001,0x1842420,0xFE0804B5,0xC6000004,0x47FC2420,0xA6000D61,0x82002420,0x1842420,0xFE0804B5,0xC6000004,0x47FC2420,0xA6000D61,0x82002420,0x47FC2420,0xA6000D61,0x82002420,0x82002420,0x1842420,0xFE0804B5,0xC6000004,0x47FC2420,0xA6000D61,0x82002420,0x47FC2420,0xA6000D61,0x82002420,0x82002420,0x47FC2420,
+0xA6000D61,0x82002420,0x82002420,0x82002420,0xFED01F04,0x1182420,0xF6FC2002,0xFE6C1711,0xFE0C0F79,0xD0000D00,0xB00008C8,0x9C001174,0xFEAC1EC1,0xFE4C15DD,0xBE000734,0x82002420,0x17FC2420,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table227[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0x8C0001,0x8C0001,0x8C0001,0x8C0001,0x2D00000,0x2D00000,0x2D00000,0x1AC0000,0x1AC0000,0x46000000,0x2D00000,0x2D00000,0x2D00000,0x1AC0000,0x1AC0000,0x46000000,0x1AC0000,0x1AC0000,0x46000000,0x46000000,0x2D00000,0x2D00000,0x2D00000,0x1AC0000,0x1AC0000,0x46000000,0x1AC0000,0x1AC0000,0x46000000,0x46000000,0x1AC0000,
+0x1AC0000,0x46000000,0x46000000,0x46000000,0xA40000,0x980000,0x8C0001,0xC00000,0x2EC0000,0x12C0000,0x15C0000,0x5F80000,0x2B00000,0x2D00000,0x12C0000,0x46000000,0x12C0000,0x19C0001,0x6FFC0000,0xB9F80000,0xCE000000,0x6FFC0000,0xB9F80000,0xCE000000,0xB9F80000,0xCE000000,0xCE000000,0x6FFC0000,0xB9F80000,0xCE000000,0xB9F80000,0xCE000000,
+0xCE000000,0xB9F80000,0xCE000000,0xCE000000,0xCE000000,0x6FFC0000,0xB9F80000,0xCE000000,0xB9F80000,0xCE000000,0xCE000000,0xB9F80000,0xCE000000,0xCE000000,0xCE000000,0xB9F80000,0xCE000000,0xCE000000,0xCE000000,0xCE000000,0x15FC0000,0x5B80000,0x5B80000,0x8BFC0000,0xAFFC0000,0xC3F80000,0xCE000000,0xCE000000,0x4DFC0000,0x99FC0000,0xCDCC0000,0xCE000000,
+0xA5FC0000,0x8C6F9A,0xFE5C3409,0xFE380FFD,0xCE300D21,0xFE303482,0xFE080585,0xD0000008,0xCE002420,0xAC000C6D,0x8A002420,0xFE0C56D6,0xF4002035,0xBA00107D,0xB40033FB,0xA200187A,0x80002BCC,0x8A005671,0x84003599,0x72003FC9,0x5C005671,0xCC6F9A,0xD20035B7,0xAE001E26,0xA20040A4,0x980022EC,0x7A0032A0,0x80005DB5,0x7E003CE1,0x6C004509,0x580059E2,0x1A06F9A,
+0x6C004F2A,0x5C0052B0,0x5000636D,0x44006F9A,0xFE504C53,0xF8806322,0xFA846322,0xFE142CC5,0xFC001ADA,0xCC001898,0xAE001085,0x980020F9,0xFE344BA8,0xFE0029CA,0x9E0029C1,0x6C004509,0x1246F9A,0xB85672,0xFE802931,0xFE4C0BF6,0xCE4809D9,0xFE503080,0xFE080575,0xCE040008,0xCE002420,0xAC000C6D,0x8A002420,0x1145671,0xF4002035,0xBA00107D,0xB40033FB,0xA200187A,
+0x80002BCC,0xFF85671,0x84003599,0x72003FC9,0x5C005671,0x1145671,0xF4002035,0xBA00107D,0xB40033FB,0xA200187A,0x80002BCC,0xFF85671,0x84003599,0x72003FC9,0x5C005671,0xFF85671,0x84003599,0x72003FC9,0x5C005671,0x5C005671,0xFE7841F9,0xFEAC4ECC,0xFEAC4D09,0xFE302BF5,0xFC001ADA,0xCC001898,0xAE001085,0x980020F9,0xFE5C422B,0xFE0428A1,0x9E00295D,0x72003FC9,
+0x18C5671,0x300D21,0x300D21,0x300D21,0x300D21,0xD6000000,0xD6000000,0xD6000000,0x68000000,0x68000000,0x46000000,0x6A0009D9,0x6A0009D9,0x6A0009D9,0x520003BA,0x520003BA,0x400001DD,0x340009D9,0x340009D9,0x32000614,0x220009D9,0x2440D21,0x2440D21,0x2440D21,0x46000633,0x46000633,0x3A000362,0x2E000AD2,0x2E000AD2,0x2C000709,0x22000A52,0x8C0D21,
+0x8C0D21,0x26000948,0x1C000B96,0x16000D22,0xFC0C0561,0xFA24082C,0x300D21,0xD000042A,0x860003D9,0x6A0003D4,0x62000334,0x4A000484,0xE4000704,0x900005AB,0x400009E9,0x2C000709,0x640D21,0x4809D9,0x4809D9,0x4809D9,0x4809D9,0xD6000000,0xD6000000,0xD6000000,0x68000000,0x68000000,0x46000000,0x6809D9,0x6809D9,0x6809D9,0x520003BA,0x520003BA,
+0x400001DD,0xD009D9,0xD009D9,0x32000614,0x220009D9,0x6809D9,0x6809D9,0x6809D9,0x520003BA,0x520003BA,0x400001DD,0xD009D9,0xD009D9,0x32000614,0x220009D9,0xD009D9,0xD009D9,0x32000614,0x220009D9,0x220009D9,0xFE100521,0xF4380659,0x4809D9,0xD000042A,0x860003D9,0x6A0003D4,0x62000334,0x4A000484,0xF400063D,0x9A000551,0x9409D9,0x32000614,
+0x9409D9,0x1142422,0xFED00F3A,0xFE940082,0xCE8C0001,0x19C2420,0xFE080565,0xCE080000,0x53FC2420,0xAC000C6D,0x8A002420,0x19C2420,0xFE080565,0xCE080000,0x53FC2420,0xAC000C6D,0x8A002420,0x53FC2420,0xAC000C6D,0x8A002420,0x8A002420,0x19C2420,0xFE080565,0xCE080000,0x53FC2420,0xAC000C6D,0x8A002420,0x53FC2420,0xAC000C6D,0x8A002420,0x8A002420,0x53FC2420,
+0xAC000C6D,0x8A002420,0x8A002420,0x8A002420,0xF6E81F81,0x1282420,0xFF0C2002,0xFE9417C2,0xFE100FE9,0xDA000BE9,0xB40007B4,0xA800109D,0xFCD01F02,0xFE6416CD,0xC6000659,0x8A002420,0x25FC2420,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table228[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0xA00000,0xA00000,0xA00000,0xA00000,0xEC0000,0xEC0000,0xEC0000,0x1E40000,0x1E40000,0x4E000001,0xEC0000,0xEC0000,0xEC0000,0x1E40000,0x1E40000,0x4E000001,0x1E40000,0x1E40000,0x4E000001,0x4E000001,0xEC0000,0xEC0000,0xEC0000,0x1E40000,0x1E40000,0x4E000001,0x1E40000,0x1E40000,0x4E000001,0x4E000001,0x1E40000,
+0x1E40000,0x4E000001,0x4E000001,0x4E000001,0x4B80000,0xCA80000,0xA00000,0xD80000,0x10C0000,0x1540000,0x1880000,0x11FC0000,0xC80000,0xEC0000,0x1540000,0x4E000001,0x1540000,0x1B00000,0x89FC0000,0xC5FC0000,0xD6000001,0x89FC0000,0xC5FC0000,0xD6000001,0xC5FC0000,0xD6000001,0xD6000001,0x89FC0000,0xC5FC0000,0xD6000001,0xC5FC0000,0xD6000001,
+0xD6000001,0xC5FC0000,0xD6000001,0xD6000001,0xD6000001,0x89FC0000,0xC5FC0000,0xD6000001,0xC5FC0000,0xD6000001,0xD6000001,0xC5FC0000,0xD6000001,0xD6000001,0xD6000001,0xC5FC0000,0xD6000001,0xD6000001,0xD6000001,0xD6000001,0x41FC0000,0x1CC0000,0x1CC0000,0xA1FC0000,0xBFF80000,0xCFF40000,0xD6000001,0xD6000001,0x6FFC0000,0xADFC0000,0xD5FC0000,0xD6000001,
+0xB7FC0000,0x9479B0,0xFE5C3CE5,0xFE381579,0xD63410AD,0xFE3C3A48,0xFE08077D,0xD804003A,0xDC002420,0xB8000B51,0x92002422,0xFE185E40,0xFA0022E9,0xC6001283,0xC0003629,0xAE0018E6,0x8C002CC6,0x92005D2B,0x90003993,0x78004373,0x62005D2B,0xDC79B0,0xE2003A6D,0xB40021B4,0xAE00448A,0xA200246F,0x86003492,0x8600656B,0x840041BB,0x7200496F,0x5E006114,0x1BC79B0,
+0x72005634,0x66005924,0x56006BE7,0x480079B4,0xFE645556,0xFC886C60,0xFE8C6CD0,0xFE1833EE,0xFC001D3E,0xDA0018C5,0xBC00109D,0xA00021F6,0xFE345496,0xFE042F97,0xA6002D3F,0x7200496F,0x13879B0,0xC45D2C,0xFE8C2FC1,0xFE581024,0xD6500C81,0xFE5C34E6,0xFE140759,0xDA080032,0xDC002420,0xB8000B51,0x92002422,0x3245D2B,0xFA0022E9,0xC6001283,0xC0003629,0xAE0018E6,
+0x8C002CC6,0x17FC5D2B,0x90003993,0x78004373,0x62005D2B,0x3245D2B,0xFA0022E9,0xC6001283,0xC0003629,0xAE0018E6,0x8C002CC6,0x17FC5D2B,0x90003993,0x78004373,0x62005D2B,0x17FC5D2B,0x90003993,0x78004373,0x62005D2B,0x62005D2B,0xFE9448B3,0xFEAC5556,0xF8C05444,0xFE4031C3,0xFC001D3E,0xDA0018C5,0xBC00109D,0xA00021F6,0xFE5C48FD,0xFE042E53,0xA6002CDB,0x78004373,
+0x1A45D2B,0x3410AC,0x3410AC,0x3410AC,0x3410AC,0xF2000000,0xF2000000,0xF2000000,0x76000000,0x76000000,0x4E000001,0x78000C80,0x78000C80,0x78000C80,0x620004A9,0x620004A9,0x46000262,0x3A000C80,0x3A000C80,0x380007B5,0x26000C82,0x5010AB,0x5010AB,0x5010AB,0x4C0007F2,0x4C0007F2,0x40000453,0x34000DC1,0x34000DC1,0x320008EE,0x24000D22,0xA010AB,
+0xA010AB,0x2C000BD1,0x20000EC6,0x1A0010AB,0xFE1007AA,0xFE2C0B01,0x3410AC,0xEC000562,0x9E0004E1,0x800004FD,0x6E00040D,0x560005C9,0xF40008E9,0xB2000742,0x46000C98,0x320008EE,0x7010AB,0x500C80,0x500C80,0x500C80,0x500C80,0xF2000000,0xF2000000,0xF2000000,0x76000000,0x76000000,0x4E000001,0x2740C80,0x2740C80,0x2740C80,0x620004A9,0x620004A9,
+0x46000262,0xF00C80,0xF00C80,0x380007B5,0x26000C82,0x2740C80,0x2740C80,0x2740C80,0x620004A9,0x620004A9,0x46000262,0xF00C80,0xF00C80,0x380007B5,0x26000C82,0xF00C80,0xF00C80,0x380007B5,0x26000C82,0x26000C82,0xFE200745,0xF8400884,0x500C80,0xEC000562,0x9E0004E1,0x800004FD,0x6E00040D,0x560005C9,0xF4000808,0xB20006C9,0xA80C80,0x380007B5,
+0xA80C80,0x1282420,0xFEE81074,0xFEAC0124,0xD6A00001,0x1B82420,0xFE2C069D,0xD61C0001,0x61F82420,0xB8000B51,0x92002422,0x1B82420,0xFE2C069D,0xD61C0001,0x61F82420,0xB8000B51,0x92002422,0x61F82420,0xB8000B51,0x92002422,0x92002422,0x1B82420,0xFE2C069D,0xD61C0001,0x61F82420,0xB8000B51,0x92002422,0x61F82420,0xB8000B51,0x92002422,0x92002422,0x61F82420,
+0xB8000B51,0x92002422,0x92002422,0x92002422,0xFEF81F85,0x13C2420,0xF9202081,0xFEB018A0,0xFE281109,0xE8000B14,0xBE0006B2,0xB2000F82,0xFEDC1F22,0xFE881771,0xD4000541,0x92002422,0x37FC2420,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table229[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x1,0xB00000,0xB00000,0xB00000,0xB00000,0x1040000,0x1040000,0x1040000,0x7FC0000,0x7FC0000,0x56000001,0x1040000,0x1040000,0x1040000,0x7FC0000,0x7FC0000,0x56000001,0x7FC0000,0x7FC0000,0x56000001,0x56000001,0x1040000,0x1040000,0x1040000,0x7FC0000,0x7FC0000,0x56000001,0x7FC0000,0x7FC0000,0x56000001,0x56000001,0x7FC0000,
+0x7FC0000,0x56000001,0x56000001,0x56000001,0xCC0000,0xBC0000,0xB00000,0xF00000,0x1280000,0x1740000,0x1AC0000,0x1DF40000,0xDC0000,0x1040000,0x1740000,0x56000001,0x1740000,0x1C00000,0xA3FC0000,0xD1FC0000,0xDE000001,0xA3FC0000,0xD1FC0000,0xDE000001,0xD1FC0000,0xDE000001,0xDE000001,0xA3FC0000,0xD1FC0000,0xDE000001,0xD1FC0000,0xDE000001,
+0xDE000001,0xD1FC0000,0xDE000001,0xDE000001,0xDE000001,0xA3FC0000,0xD1FC0000,0xDE000001,0xD1FC0000,0xDE000001,0xDE000001,0xD1FC0000,0xDE000001,0xDE000001,0xDE000001,0xD1FC0000,0xDE000001,0xDE000001,0xDE000001,0xDE000001,0x69FC0000,0x7DC0000,0x7DC0000,0xB3FC0000,0xCBFC0000,0xD9F40000,0xDE000001,0xDE000001,0x8DFC0000,0xBDFC0000,0xDFD00000,0xDE000001,
+0xC5FC0000,0x9C8330,0xFE684541,0xFE401B24,0xDE3C142D,0xFE443FEA,0xFE140A2D,0xE008009A,0xE6002422,0xC4000A69,0x9A002422,0xFE246584,0xFA002639,0xCC0014AB,0xCC003831,0xB4001956,0x92002DC2,0x9A006380,0x96003D53,0x7E0046EB,0x66006383,0xE88330,0xE8003F39,0xC0002534,0xBA00483A,0xA8002617,0x8C00366A,0x8C006CB7,0x8A00465F,0x78004D93,0x620067CB,0x1D88330,
+0x78005CE4,0x6C005F04,0x5C0073EF,0x4C008334,0xFE645DA6,0xFE8C7530,0xFE8C7650,0xFE303A6D,0xFE04205E,0xDE001961,0xC40010B2,0xAA002336,0xFE445CDB,0xFE0435B7,0xB600301B,0x78004D93,0x14C8330,0xD06380,0xFE983611,0xFE641478,0xDE580F21,0xFE683962,0xFE2009C5,0xE20C007E,0xE6002422,0xC4000A69,0x9A002422,0x1346380,0xFA002639,0xCC0014AB,0xCC003831,0xB4001956,
+0x92002DC2,0x1FF86380,0x96003D53,0x7E0046EB,0x66006383,0x1346380,0xFA002639,0xCC0014AB,0xCC003831,0xB4001956,0x92002DC2,0x1FF86380,0x96003D53,0x7E0046EB,0x66006383,0x1FF86380,0x96003D53,0x7E0046EB,0x66006383,0x66006383,0xFE944E93,0xFAC45BA4,0xFCC85A64,0xFE403763,0xFE04205A,0xDE001961,0xC40010B2,0xAA002336,0xFE784F21,0xFE18341D,0xB6002FA2,0x7E0046EB,
+0x1B86380,0x3C142C,0x3C142C,0x3C142C,0x3C142C,0xFE000010,0xFE000010,0xFE000010,0x82000000,0x82000000,0x56000001,0x84000F20,0x84000F20,0x84000F20,0x680005A5,0x680005A5,0x4C0002EA,0x40000F20,0x40000F20,0x3E000955,0x2A000F22,0x54142B,0x54142B,0x54142B,0x580009A2,0x580009A2,0x46000543,0x3A0010A9,0x3A0010A9,0x38000ACE,0x28000FDB,0xAC142B,
+0xAC142B,0x2C000E41,0x240011F3,0x1C00142B,0xFE100A3A,0xFE2C0DF1,0x3C142C,0xFA000682,0xA80005ED,0x840005EA,0x800004FD,0x56000709,0xF4000B09,0xB20008D2,0x52000F39,0x38000ACE,0x78142B,0x580F20,0x580F20,0x580F20,0x580F20,0xFE04000D,0xFE04000D,0xFE04000D,0x82000000,0x82000000,0x56000001,0x2800F20,0x2800F20,0x2800F20,0x680005A5,0x680005A5,
+0x4C0002EA,0x1080F20,0x1080F20,0x3E000955,0x2A000F22,0x2800F20,0x2800F20,0x2800F20,0x680005A5,0x680005A5,0x4C0002EA,0x1080F20,0x1080F20,0x3E000955,0x2A000F22,0x1080F20,0x1080F20,0x3E000955,0x2A000F22,0x2A000F22,0xFE200965,0xFC480AB4,0x580F20,0xFA000682,0xA80005ED,0x840005EA,0x800004FD,0x56000709,0xF6040A20,0xBC000848,0xB80F20,0x3E000955,
+0xB80F20,0x1382420,0xFF0011A4,0xFEB801F4,0xDEB00001,0x1D02420,0xFE4C07F9,0xDE2C0001,0x6DF82420,0xC4000A69,0x9A002422,0x1D02420,0xFE4C07F9,0xDE2C0001,0x6DF82420,0xC4000A69,0x9A002422,0x6DF82420,0xC4000A69,0x9A002422,0x9A002422,0x1D02420,0xFE4C07F9,0xDE2C0001,0x6DF82420,0xC4000A69,0x9A002422,0x6DF82420,0xC4000A69,0x9A002422,0x9A002422,0x6DF82420,
+0xC4000A69,0x9A002422,0x9A002422,0x9A002422,0xFD102000,0x14C2420,0xFF2C208D,0xFEC01945,0xFE501231,0xF6000A12,0xC80005D2,0xBA000EBA,0xFEF01FA9,0xFEA01865,0xDE000465,0x9A002422,0x45FC2420,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table230[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,
+0x40000,0x80000,0x80000,0x80000,0x1,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x80000,0x80000,0x80000,0x1,0x80000,0x80000,0x80000,0x1,0x1,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x40000,0x80000,0x80000,
+0x80000,0xC00000,0xC00000,0xC00000,0xC00000,0x11C0000,0x11C0000,0x11C0000,0x13FC0000,0x13FC0000,0x5E000001,0x11C0000,0x11C0000,0x11C0000,0x13FC0000,0x13FC0000,0x5E000001,0x13FC0000,0x13FC0000,0x5E000001,0x5E000001,0x11C0000,0x11C0000,0x11C0000,0x13FC0000,0x13FC0000,0x5E000001,0x13FC0000,0x13FC0000,0x5E000001,0x5E000001,0x13FC0000,
+0x13FC0000,0x5E000001,0x5E000001,0x5E000001,0xE00000,0xCC0000,0xC00000,0x1040000,0x3400000,0x1980000,0x1D40000,0x27F80000,0xF00000,0x11C0000,0x1980000,0x5E000001,0x1980000,0x1D00000,0xBBFC0000,0xDDFC0000,0xE6000001,0xBBFC0000,0xDDFC0000,0xE6000001,0xDDFC0000,0xE6000001,0xE6000001,0xBBFC0000,0xDDFC0000,0xE6000001,0xDDFC0000,0xE6000001,
+0xE6000001,0xDDFC0000,0xE6000001,0xE6000001,0xE6000001,0xBBFC0000,0xDDFC0000,0xE6000001,0xDDFC0000,0xE6000001,0xE6000001,0xDDFC0000,0xE6000001,0xE6000001,0xE6000001,0xDDFC0000,0xE6000001,0xE6000001,0xE6000001,0xE6000001,0x91FC0000,0xFEC0000,0xFEC0000,0xC7FC0000,0xD9FC0000,0xE3F40000,0xE6000001,0xE6000001,0xABFC0000,0xCFFC0000,0xE7E00000,0xE6000001,
+0xD5FC0000,0xA48BEC,0xFE744D71,0xFE4C20D8,0xE6401785,0xFE5045F6,0xFE140D79,0xEC0C0111,0xF2042424,0xCA00098D,0xA2002426,0xFE306BE4,0xFA002945,0xD80015EB,0xD8003941,0xC00018FE,0x98002E12,0xA2006878,0x9C003FBB,0x84004933,0x6C00687B,0xF48BEC,0xEE004349,0xC6002804,0xC6004B2A,0xAE002717,0x920037A6,0x980072CF,0x960049C7,0x7E00509F,0x68006D47,0x1F08BEC,
+0x7E0062AC,0x72006404,0x5C007ADF,0x52008BEC,0xFE786595,0xFE8C7DDC,0xF8A07F6D,0xFE3040E1,0xFE04237E,0xEE00192E,0xC8000FFB,0xB6002345,0xFE546487,0xFE043C07,0xB60031CB,0x7E00509F,0x15C8BEC,0xDC6878,0xFEA43B8D,0xFE701888,0xE6601145,0xFE743D82,0xFE2C0C8D,0xEA1400D9,0xF2042420,0xCA00098D,0xA2042422,0x3446878,0xFA002945,0xD80015EB,0xD8003941,0xC00018FE,
+0x98002E12,0x27FC6878,0x9C003FBB,0x84004933,0x6C00687B,0x3446878,0xFA002945,0xD80015EB,0xD8003941,0xC00018FE,0x98002E12,0x27FC6878,0x9C003FBB,0x84004933,0x6C00687B,0x27FC6878,0x9C003FBB,0x84004933,0x6C00687B,0x6C00687B,0xFEA053D2,0xFECC6050,0xFECC5F74,0xFE543C9E,0xFE04237A,0xEE00192E,0xC8000FFB,0xB6002345,0xFE885438,0xFE2C3966,0xB6003152,0x84004933,
+0x1D46878,0x401784,0x401784,0x401784,0x401784,0xFE0C0074,0xFE0C0074,0xFE0C0074,0x8E000004,0x8E000004,0x5E000005,0x94001142,0x94001142,0x94001142,0x74000631,0x74000631,0x5800030A,0x48001142,0x48001142,0x44000A69,0x30001142,0x601783,0x601783,0x601783,0x62000ACD,0x62000ACD,0x4C0005EB,0x4000132D,0x4000132D,0x3E000C3A,0x2E00122B,0xC41783,
+0xC41783,0x3200106D,0x260014AE,0x20001783,0xFE200C8D,0xFE2C110D,0x401784,0xFA00078A,0xBC000679,0x8C000682,0x8C000559,0x6A0007B2,0xFE000D14,0xD00009C2,0x5C001166,0x3E000C3A,0x8C1783,0x601144,0x601144,0x601144,0x601144,0xFE0C0050,0xFE0C0050,0xFE0C0050,0x8C040001,0x8C040001,0x5E040001,0x901142,0x901142,0x901142,0x74000631,0x74000631,
+0x5800030A,0x1241142,0x1241142,0x44000A69,0x30001142,0x901142,0x901142,0x901142,0x74000631,0x74000631,0x5800030A,0x1241142,0x1241142,0x44000A69,0x30001142,0x1241142,0x1241142,0x44000A69,0x30001142,0x30001142,0xFA340B48,0xFE4C0CA0,0x601144,0xFA00078A,0xBC000679,0x8C000682,0x8C000559,0x6A0007B2,0xFE0C0BE2,0xD0000919,0xD01142,0x44000A69,
+0xD01142,0x1482420,0xFF0C12C8,0xFECC02FD,0xE6C00001,0x1E82420,0xFE640949,0xE63C0001,0x79F82420,0xCA000989,0xA2002422,0x1E82420,0xFE640949,0xE63C0001,0x79F82420,0xCA000989,0xA2002422,0x79F82420,0xCA000989,0xA2002422,0xA2002422,0x1E82420,0xFE640949,0xE63C0001,0x79F82420,0xCA000989,0xA2002422,0x79F82420,0xCA000989,0xA2002422,0xA2002422,0x79F82420,
+0xCA000989,0xA2002422,0xA2002422,0xA2002422,0xFF142048,0x75C2420,0xF9402104,0xFED81A29,0xFE68133D,0xFC000928,0xD40004ED,0xC2000DFA,0xFF102000,0xFEC01919,0xE60003BA,0xA2002422,0x55FC2420,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4000000,0x4000000,0x4000000,0x4000000,0x4000000,
+0x4000000,0x2000000,0x2000000,0x2000000,0x1,0x2000002,0x2000002,0x2000002,0x2000002,0x2000002,0x2000002,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x18000000,0x4,0x4,0xA000000,0x8000000,0x6000000,0x6000000,0x4000000,0x4000001,0x2000001,0x2000000,0x1,
+0x2,};
+static const uint32_t g_etc1_to_bc7_m6_table231[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x140000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,
+0x1C0000,0x380000,0x380000,0x380000,0x8000001,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x1C0000,0x380000,0x380000,0x380000,0x8000001,0x380000,0x380000,0x380000,0x8000001,0x8000001,0x2140000,0x140000,0x140000,0x180000,0x180000,0x2180000,0x2180000,0x200000,0x180000,0x180000,0x280000,0x380000,
+0x280000,0xD00000,0xD00000,0xD00000,0xD00000,0x1340000,0x1340000,0x1340000,0x1FF80000,0x1FF80000,0x66000001,0x1340000,0x1340000,0x1340000,0x1FF80000,0x1FF80000,0x66000001,0x1FF80000,0x1FF80000,0x66000001,0x66000001,0x1340000,0x1340000,0x1340000,0x1FF80000,0x1FF80000,0x66000001,0x1FF80000,0x1FF80000,0x66000001,0x66000001,0x1FF80000,
+0x1FF80000,0x66000001,0x66000001,0x66000001,0x2F00000,0x6DC0000,0xD00000,0x3180000,0x15C0000,0x1B80000,0x1FC0000,0x33F40000,0x1040000,0x1340000,0x1B80000,0x66000001,0x1B80000,0x1E00000,0xD3FC0000,0xE9FC0000,0xEE000001,0xD3FC0000,0xE9FC0000,0xEE000001,0xE9FC0000,0xEE000001,0xEE000001,0xD3FC0000,0xE9FC0000,0xEE000001,0xE9FC0000,0xEE000001,
+0xEE000001,0xE9FC0000,0xEE000001,0xEE000001,0xEE000001,0xD3FC0000,0xE9FC0000,0xEE000001,0xE9FC0000,0xEE000001,0xEE000001,0xE9FC0000,0xEE000001,0xEE000001,0xEE000001,0xE9FC0000,0xEE000001,0xEE000001,0xEE000001,0xEE000001,0xB7FC0000,0x17FC0000,0x17FC0000,0xDBFC0000,0xE7F80000,0xEDF40000,0xEE000001,0xEE000001,0xC9FC0000,0xE1FC0000,0xEFF00000,0xEE000001,
+0xE3FC0000,0xB09144,0xFE805385,0xFE582588,0xEE4C19B9,0xFE5C4AD6,0xFE201109,0xF6140195,0xFC0C2454,0xD6000915,0xAA082456,0xFE3C6E48,0xFE08296D,0xE200142D,0xE80036E6,0xC60015E6,0xA2002BFB,0xAE006878,0xA6003DB5,0x90004763,0x7400687B,0x1049144,0xFA004419,0xD2002844,0xD2004B5A,0xBA00258F,0x9E0036E6,0xA2007431,0x9C0048BB,0x8A004FCF,0x6E006E1B,0x7FC9144,
+0x840064EC,0x780065C4,0x66007DB4,0x58009144,0xFE786AC5,0xFAA48366,0xFEAC8499,0xFE40451B,0xFE04257E,0xFC0015D9,0xD2000D46,0xB6002035,0xFE5C697E,0xFE184056,0xBE002F7B,0x8A004FCF,0x1749144,0xEC6878,0xFEB03D85,0xFE7C1A74,0xEE701145,0xFE8C3F52,0xFE380EE1,0xF22400D9,0xFA142420,0xD6000915,0xAA142422,0x35C6878,0xFE08295D,0xE200142D,0xE80036E6,0xC60015E6,
+0xA2002BFB,0x33FC6878,0xA6003DB5,0x90004763,0x7400687B,0x35C6878,0xFE08295D,0xE200142D,0xE80036E6,0xC60015E6,0xA2002BFB,0x33FC6878,0xA6003DB5,0x90004763,0x7400687B,0x33FC6878,0xA6003DB5,0x90004763,0x7400687B,0x7400687B,0xFEB45485,0xF8E06116,0xFAE4601D,0xFE6C3E89,0xFE102549,0xFC0015D9,0xD2000D46,0xB6002035,0xFE985529,0xFE403AFB,0xBE002EEB,0x90004763,
+0x1F46878,0x4C19B8,0x4C19B8,0x4C19B8,0x4C19B8,0xFE180124,0xFE180124,0xFE180124,0x98080034,0x98080034,0x66080035,0xAC001142,0xAC001142,0xAC001142,0x80000521,0x80000521,0x620001FD,0x54001142,0x54001142,0x4A000989,0x38001142,0x7019B8,0x7019B8,0x7019B8,0x6E000AFD,0x6E000AFD,0x58000593,0x4C0013E5,0x4C0013E5,0x44000BEA,0x34001283,0xE419B8,
+0xE419B8,0x38001155,0x2C0015E6,0x240019BB,0xFE200E1D,0xFA441304,0x4C19B8,0xFE08079A,0xD4000562,0xA2000562,0x96000448,0x6E0006AD,0xFE000E34,0xF2000912,0x6600116E,0x44000BEA,0xA019B8,0x701144,0x701144,0x701144,0x701144,0xFE240080,0xFE240080,0xFE240080,0x94140001,0x94140001,0x66140001,0xA81142,0xA81142,0xA81142,0x80000521,0x80000521,
+0x620001FD,0x1581142,0x1581142,0x4A000989,0x38001142,0xA81142,0xA81142,0xA81142,0x80000521,0x80000521,0x620001FD,0x1581142,0x1581142,0x4A000989,0x38001142,0x1581142,0x1581142,0x4A000989,0x38001142,0x38001142,0xFE3C0B68,0xFA640CD1,0x701144,0xFE08078A,0xD4000562,0xA2000562,0x96000448,0x6E0006AD,0xFE140C14,0xF2000831,0xF01142,0x4A000989,
+0xF01142,0x1582420,0xFF241408,0xFEE40425,0xEED00001,0x3FC2420,0xFE880AB5,0xEE4C0001,0x85F82420,0xD60008B1,0xAA002422,0x3FC2420,0xFE880AB5,0xEE4C0001,0x85F82420,0xD60008B1,0xAA002422,0x85F82420,0xD60008B1,0xAA002422,0xAA002422,0x3FC2420,0xFE880AB5,0xEE4C0001,0x85F82420,0xD60008B1,0xAA002422,0x85F82420,0xD60008B1,0xAA002422,0xAA002422,0x85F82420,
+0xD60008B1,0xAA002422,0xAA002422,0xAA002422,0xFF342081,0xF6C2420,0xFF4C2114,0xFEEC1AC8,0xFE90147D,0xFE040910,0xDE000431,0xD0000D22,0xFF182032,0xFECC1A04,0xF2000301,0xAA002422,0x63FC2420,0x80034,0x80034,0x80034,0x80034,0x80034,0x80034,0x80034,0x80034,0x80034,0x80034,0x1C000000,0x1C000000,0x1C000000,0x1C000000,0x1C000000,
+0x1C000000,0xE000000,0xE000000,0xE000000,0x8000001,0x20C0032,0x20C0032,0x20C0032,0x20C0032,0x20C0032,0x20C0032,0xC000011,0xC000011,0xC000011,0x800000A,0x180032,0x180032,0x180032,0x4000022,0x4000032,0x98000000,0x80034,0x80034,0x44000000,0x2E000000,0x24000000,0x24000000,0x18000000,0x3600000D,0x24000008,0x12000001,0xC000011,
+0x140032,};
+static const uint32_t g_etc1_to_bc7_m6_table232[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x240001,0x380000,0x380000,0x380000,0x380000,0x380000,
+0x380000,0x700000,0x700000,0x700000,0x12000000,0x380000,0x380000,0x380000,0x380000,0x380000,0x380000,0x700000,0x700000,0x700000,0x12000000,0x700000,0x700000,0x700000,0x12000000,0x12000000,0x280000,0x240001,0x240001,0x2C0000,0x300000,0x340000,0x340000,0x400000,0x2C0000,0x300000,0x500000,0x700000,
+0x500000,0xE00001,0xE00001,0xE00001,0xE00001,0x1500000,0x1500000,0x1500000,0x2DF80000,0x2DF80000,0x70000000,0x1500000,0x1500000,0x1500000,0x2DF80000,0x2DF80000,0x70000000,0x2DF80000,0x2DF80000,0x70000000,0x70000000,0x1500000,0x1500000,0x1500000,0x2DF80000,0x2DF80000,0x70000000,0x2DF80000,0x2DF80000,0x70000000,0x70000000,0x2DF80000,
+0x2DF80000,0x70000000,0x70000000,0x70000000,0x7040000,0xF00000,0xE00001,0x1340000,0x17C0000,0x1E00000,0x11FC0000,0x3FF40000,0x11C0000,0x1500000,0x1E00000,0x70000000,0x1E00000,0x1F00001,0xEFFC0000,0xF7F80000,0xF8000000,0xEFFC0000,0xF7F80000,0xF8000000,0xF7F80000,0xF8000000,0xF8000000,0xEFFC0000,0xF7F80000,0xF8000000,0xF7F80000,0xF8000000,
+0xF8000000,0xF7F80000,0xF8000000,0xF8000000,0xF8000000,0xEFFC0000,0xF7F80000,0xF8000000,0xF7F80000,0xF8000000,0xF8000000,0xF7F80000,0xF8000000,0xF8000000,0xF8000000,0xF7F80000,0xF8000000,0xF8000000,0xF8000000,0xF8000000,0xE3FC0000,0xA7FC0000,0xA7FC0000,0xF1FC0000,0xF5FC0000,0xF9F00000,0xF8000000,0xF8000000,0xEBFC0000,0xF3FC0000,0xF9E40000,0xF8000000,
+0xF5FC0000,0xC097BB,0xFE8C5AEA,0xFE642B8F,0xF8581C9A,0xFE6850F9,0xFE3815EA,0xFC200282,0xFE14251D,0xDE040922,0xB41424D5,0xFE4471AC,0xFE082B02,0xEE0012C6,0xF40034A9,0xD20012B1,0xAE002A0C,0xBC006878,0xB2003B2E,0x9600456C,0x7E006878,0x31897B9,0xFA004686,0xE200290A,0xE2004B75,0xC6002442,0xA8003621,0xAE00761C,0xA60047DF,0x90004F04,0x7A006EE8,0x11FC97B9,
+0x900067C5,0x7E006825,0x6C008115,0x5E0097B9,0xFE8C716F,0xFEAC89AD,0xFEAC8B86,0xFE544AE1,0xFE1028CE,0xFC00135A,0xDE000A4D,0xCA001CD5,0xFE707042,0xFE244643,0xD6002C8C,0x90004F04,0x19497B9,0xFC687B,0xFEC43F8B,0xFE941CBB,0xF8841142,0xFE984159,0xFE5811F2,0xFC3800DA,0xFE2C2431,0xDE10090E,0xB4242421,0x1786878,0xFE082AF2,0xEE0012C6,0xF40034A9,0xD20012B1,
+0xAE002A0C,0x41FC6878,0xB2003B2E,0x9600456C,0x7E006878,0x1786878,0xFE082AF2,0xEE0012C6,0xF40034A9,0xD20012B1,0xAE002A0C,0x41FC6878,0xB2003B2E,0x9600456C,0x7E006878,0x41FC6878,0xB2003B2E,0x9600456C,0x7E006878,0x7E006878,0xFED055D8,0xFEEC6131,0xFEEC6086,0xFE8040FD,0xFE242846,0xFC00135A,0xDE000A4D,0xCA001CD5,0xFEB456A6,0xFE5C3DAE,0xD6002BE3,0x9600456C,
+0xFFC6878,0x581C9A,0x581C9A,0x581C9A,0x581C9A,0xFE240266,0xFE240266,0xFE240266,0xA21400B5,0xA21400B5,0x701400B5,0xC8001142,0xC8001142,0xC8001142,0x9200040D,0x9200040D,0x68000121,0x60001144,0x60001144,0x56000895,0x40001144,0x2801C9A,0x2801C9A,0x2801C9A,0x7A000B7D,0x7A000B7D,0x6200056D,0x580014D3,0x580014D3,0x50000BA2,0x400012FD,0x1081C9A,
+0x1081C9A,0x440012AD,0x32001788,0x2A001C9D,0xFC38101A,0xFE4C1596,0x581C9A,0xFE100871,0xF2000448,0xC0000464,0xAA00031D,0x80000585,0xFE140FDB,0xFC000884,0x7C001182,0x50000BA2,0xB81C9A,0x841142,0x841142,0x841142,0x841142,0xFE3400C1,0xFE3400C1,0xFE3400C1,0x9E240001,0x9E240001,0x70240001,0xC41142,0xC41142,0xC41142,0x9200040D,0x9200040D,
+0x68000121,0x18C1142,0x18C1142,0x56000895,0x40001144,0xC41142,0xC41142,0xC41142,0x9200040D,0x9200040D,0x68000121,0x18C1142,0x18C1142,0x56000895,0x40001144,0x18C1142,0x18C1142,0x56000895,0x40001144,0x40001144,0xFE580B95,0xFE6C0D0D,0x841142,0xFE1807E9,0xF2000448,0xC0000464,0xAA00031D,0x80000585,0xFE340C31,0xFC000784,0x1181142,0x56000895,
+0x1181142,0x1682422,0xFF301572,0xFEFC05B9,0xF8E00001,0x1FFC2420,0xFEA00C69,0xF85C0000,0x91FC2420,0xDC0007D9,0xB4002420,0x1FFC2420,0xFEA00C69,0xF85C0000,0x91FC2420,0xDC0007D9,0xB4002420,0x91FC2420,0xDC0007D9,0xB4002420,0xB4002420,0x1FFC2420,0xFEA00C69,0xF85C0000,0x91FC2420,0xDC0007D9,0xB4002420,0x91FC2420,0xDC0007D9,0xB4002420,0xB4002420,0x91FC2420,
+0xDC0007D9,0xB4002420,0xB4002420,0xB4002420,0xFD4C2102,0x9802420,0xFB642185,0xFF141BC1,0xFEA815C1,0xFE0409FA,0xE8000371,0xD8000C44,0xFF2C20D5,0xFEF01B2D,0xFE000248,0xB4002420,0x75FC2420,0x1400B5,0x1400B5,0x1400B5,0x1400B5,0x1400B5,0x1400B5,0x1400B5,0x1400B5,0x1400B5,0x1400B5,0x38000000,0x38000000,0x38000000,0x38000000,0x38000000,
+0x38000000,0x1C000000,0x1C000000,0x1C000000,0x12000000,0x1C00B5,0x1C00B5,0x1C00B5,0x1C00B5,0x1C00B5,0x1C00B5,0x18000044,0x18000044,0x18000044,0x12000024,0x3000B5,0x3000B5,0x3000B5,0xA000071,0x80000B5,0xFA040005,0x1400B5,0x1400B5,0x84000000,0x5C000000,0x46000000,0x46000000,0x2E000000,0x76000035,0x5600001A,0x22000004,0x18000044,
+0x2400B5,};
+static const uint32_t g_etc1_to_bc7_m6_table233[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x340001,0x500000,0x500000,0x500000,0x500000,0x500000,
+0x500000,0xA00000,0xA00000,0xA00000,0x1A000000,0x500000,0x500000,0x500000,0x500000,0x500000,0x500000,0xA00000,0xA00000,0xA00000,0x1A000000,0xA00000,0xA00000,0xA00000,0x1A000000,0x1A000000,0x4380000,0x340001,0x340001,0x63C0000,0x440000,0x480000,0x480000,0x580000,0x63C0000,0x440000,0x700000,0xA00000,
+0x700000,0xF00001,0xF00001,0xF00001,0xF00001,0x1680000,0x1680000,0x1680000,0x39F80000,0x39F80000,0x78000000,0x1680000,0x1680000,0x1680000,0x39F80000,0x39F80000,0x78000000,0x39F80000,0x39F80000,0x78000000,0x78000000,0x1680000,0x1680000,0x1680000,0x39F80000,0x39F80000,0x78000000,0x39F80000,0x39F80000,0x78000000,0x78000000,0x39F80000,
+0x39F80000,0x78000000,0x78000000,0x78000000,0x3180000,0x9000000,0xF00001,0x1480000,0x3940000,0x3FC0000,0x1FF80000,0x49F80000,0x1300000,0x1680000,0x3FC0000,0x78000000,0x3FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0xC89B73,0xFE98601A,0xFE70308B,0xFE641F86,0xFE7454F9,0xFE3819DE,0xFE280401,0xFE20257D,0xE4100916,0xBA1C2481,0xFE507334,0xFE142CA6,0xFA0011D2,0xFA0031B5,0xDE000F8D,0xB4002774,0xC6006693,0xB80037EE,0x9C004258,0x86006694,0x12C9B71,0xFA0048EA,0xE20029B6,0xE8004A85,0xCC0022AE,0xAE003499,0xBA0075EC,0xB20045F3,0x9A004CE6,0x80006DCC,0x1BF89B71,
+0x9600690D,0x8A0068A1,0x7200821D,0x64009B71,0xFE94756C,0xF8C08E33,0xFAC48FAF,0xFE544EB5,0xFE242B66,0xFC0011E2,0xEA0007C2,0xD0001968,0xFE7873EA,0xFE40496C,0xD6002964,0x9A004CE6,0x1AC9B71,0x10C6693,0xFED04023,0xFEAC1E33,0xFE941142,0xFEB0416D,0xFE6413AA,0xFE4400F5,0xFE402373,0xE41C08A6,0xBA342315,0x38C6693,0xFE202C26,0xFA0011D2,0xFA0031B5,0xDE000F8D,
+0xB4002774,0x4BFC6693,0xB80037EE,0x9C004258,0x86006694,0x38C6693,0xFE202C26,0xFA0011D2,0xFA0031B5,0xDE000F8D,0xB4002774,0x4BFC6693,0xB80037EE,0x9C004258,0x86006694,0x4BFC6693,0xB80037EE,0x9C004258,0x86006694,0x86006694,0xFED05534,0xF900600B,0xFD085F33,0xFE9440FA,0xFE3829B2,0xFC0011E2,0xEA0007C2,0xD0001968,0xFEC455C3,0xFE843E6A,0xDE0028A6,0x9C004258,
+0x1DF86693,0x641F86,0x641F86,0x641F86,0x641F86,0xFE280401,0xFE280401,0xFE280401,0xAC1C016D,0xAC1C016D,0x781C016D,0xE0001142,0xE0001142,0xE0001142,0xA200031D,0xA200031D,0x74000089,0x6C001144,0x6C001144,0x5C0007D9,0x48001144,0x901F85,0x901F85,0x901F85,0x86000C35,0x86000C35,0x680005B5,0x620015A4,0x620015A4,0x58000B8A,0x46001365,0x1241F85,
+0x1241F85,0x4A001419,0x3E001918,0x30001F85,0xFE3C123E,0xF45818B1,0x641F86,0xFE180989,0xFC000384,0xC8000368,0xB800025D,0x8C0004A5,0xFE201212,0xFE0008CA,0x8600118A,0x58000B8A,0xD01F85,0x941142,0x941142,0x941142,0x941142,0xFE4400F5,0xFE4400F5,0xFE4400F5,0xA6340001,0xA6340001,0x78340001,0xDC1142,0xDC1142,0xDC1142,0xA200031D,0xA200031D,
+0x74000089,0x1BC1142,0x1BC1142,0x5C0007D9,0x48001144,0xDC1142,0xDC1142,0xDC1142,0xA200031D,0xA200031D,0x74000089,0x1BC1142,0x1BC1142,0x5C0007D9,0x48001144,0x1BC1142,0x1BC1142,0x5C0007D9,0x48001144,0x48001144,0xFA6C0BE2,0xFC880D22,0x941142,0xFE340845,0xFC000384,0xC8000368,0xB800025D,0x8C0004A5,0xFA480C82,0xFE0407B4,0x1381142,0x5C0007D9,
+0x1381142,0x1782312,0xFF441595,0xFF0806B9,0xFEF00001,0x35FC2312,0xFEB80D39,0xFE700000,0x9DF42312,0xE60006C4,0xBA002314,0x35FC2312,0xFEB80D39,0xFE700000,0x9DF42312,0xE60006C4,0xBA002314,0x9DF42312,0xE60006C4,0xBA002314,0xBA002314,0x35FC2312,0xFEB80D39,0xFE700000,0x9DF42312,0xE60006C4,0xBA002314,0x9DF42312,0xE60006C4,0xBA002314,0xBA002314,0x9DF42312,
+0xE60006C4,0xBA002314,0xBA002314,0xBA002314,0xFF502032,0x1902312,0xFF6C2099,0xFF201B94,0xFED01619,0xFE180AF1,0xF20002A1,0xE0000B14,0xFD502000,0xFF081AAA,0xFE0001C4,0xBA002314,0x81FC2312,0x1C016D,0x1C016D,0x1C016D,0x1C016D,0x1C016D,0x1C016D,0x1C016D,0x1C016D,0x1C016D,0x1C016D,0x50000000,0x50000000,0x50000000,0x50000000,0x50000000,
+0x50000000,0x26000001,0x26000001,0x26000001,0x1A000000,0x28016D,0x28016D,0x28016D,0x28016D,0x28016D,0x28016D,0x22000082,0x22000082,0x22000082,0x18000044,0x4C016D,0x4C016D,0x4C016D,0x100000DD,0xC00016D,0xFE0C003D,0x1C016D,0x1C016D,0xBC000000,0x82000000,0x64000000,0x64000000,0x42000000,0xA0000074,0x7400003A,0x32000009,0x22000082,
+0x34016D,};
+static const uint32_t g_etc1_to_bc7_m6_table234[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x440001,0x680000,0x680000,0x680000,0x680000,0x680000,
+0x680000,0xD00000,0xD00000,0xD00000,0x22000000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0xD00000,0xD00000,0xD00000,0x22000000,0xD00000,0xD00000,0xD00000,0x22000000,0x22000000,0xC480000,0x440001,0x440001,0x500000,0x580000,0x25C0000,0x25C0000,0x740000,0x500000,0x580000,0x940000,0xD00000,
+0x940000,0x1000001,0x1000001,0x1000001,0x1000001,0x1800000,0x1800000,0x1800000,0x45F80000,0x45F80000,0x80000000,0x1800000,0x1800000,0x1800000,0x45F80000,0x45F80000,0x80000000,0x45F80000,0x45F80000,0x80000000,0x80000000,0x1800000,0x1800000,0x1800000,0x45F80000,0x45F80000,0x80000000,0x45F80000,0x45F80000,0x80000000,0x80000000,0x45F80000,
+0x45F80000,0x80000000,0x80000000,0x80000000,0x12C0000,0x1140000,0x1000001,0x35C0000,0x1B00000,0x13FC0000,0x2BFC0000,0x55F40000,0x1440000,0x1800000,0x13FC0000,0x80000000,0x13FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0xD0985B,0xFEA46016,0xFE7C32E7,0xFE6C22C6,0xFE80534D,0xFE4C1AEE,0xFE300602,0xFE2C22E1,0xE8180846,0xBE242169,0xFE5C6E98,0xFE142B26,0xFC001148,0xFA002BC5,0xE2000B41,0xBA0021D8,0xD0005F33,0xBE0031CA,0xA6003B0D,0x8A005F34,0x1389859,0xFC004866,0xE80029FE,0xEE004581,0xD2001F56,0xB4002FCD,0xC0006FCC,0xB20040B3,0x9C004648,0x86006704,0x21F89859,
+0x9C0065F9,0x8A0063E1,0x78007CE9,0x68009859,0xFEA072F9,0xFCC88B1B,0xFECC8CE7,0xFE6C4D3A,0xFE2829D6,0xFE040EE2,0xEE0004B9,0xD6001419,0xFE7871FA,0xFE4047CC,0xDE00246A,0x9C004648,0x1BC9859,0x1185F33,0xFEE83C13,0xFEB81D03,0xFEA41142,0xFEC43C4B,0xFE7C126A,0xFE5C013D,0xFE4C1F8B,0xE8300726,0xBE441F05,0x1A05F33,0xFE3829C6,0xFC001148,0xFA002BC5,0xE2000B41,
+0xBA0021D8,0x55F85F33,0xBE0031CA,0xA6003B0D,0x8A005F34,0x1A05F33,0xFE3829C6,0xFC001148,0xFA002BC5,0xE2000B41,0xBA0021D8,0x55F85F33,0xBE0031CA,0xA6003B0D,0x8A005F34,0x55F85F33,0xBE0031CA,0xA6003B0D,0x8A005F34,0x8A005F34,0xFEE44F59,0xFF0C58D3,0xFF0C5843,0xFEB03CE2,0xFE4826EA,0xFE040EDE,0xEE0004B9,0xD6001419,0xFEDC4F89,0xFE8439AA,0xDE0023A6,0xA6003B0D,
+0x27FC5F33,0x6C22C6,0x6C22C6,0x6C22C6,0x6C22C6,0xFE300602,0xFE300602,0xFE300602,0xB6240265,0xB6240265,0x80240265,0xF8001142,0xF8001142,0xF8001142,0xAE00025D,0xAE00025D,0x80000031,0x78001144,0x78001144,0x66000728,0x50001144,0xA422C5,0xA422C5,0xA422C5,0x92000D2D,0x92000D2D,0x7400063D,0x6E0016B4,0x6E0016B4,0x60000B84,0x4C0013E5,0x14C22C5,
+0x14C22C5,0x500015CD,0x44001AD8,0x360022C5,0xFE4C14D5,0xFA641BA9,0x6C22C6,0xFE240B44,0xFE040388,0xE20002B1,0xCC00019A,0x960003E8,0xFC301481,0xFE000A0A,0x9600119B,0x60000B84,0xE822C5,0xA41142,0xA41142,0xA41142,0xA41142,0xFE5C013D,0xFE5C013D,0xFE5C013D,0xAE440001,0xAE440001,0x80440001,0xF41142,0xF41142,0xF41142,0xAE00025D,0xAE00025D,
+0x80000031,0x1F01142,0x1F01142,0x66000728,0x50001144,0xF41142,0xF41142,0xF41142,0xAE00025D,0xAE00025D,0x80000031,0x1F01142,0x1F01142,0x66000728,0x50001144,0x1F01142,0x1F01142,0x66000728,0x50001144,0x50001144,0xFE740C02,0xFE8C0D6A,0xA41142,0xFE440894,0xFE040384,0xE20002B1,0xCC00019A,0x960003E8,0xFE500CB2,0xFE1807FD,0x15C1142,0x66000728,
+0x15C1142,0x1801F02,0xFF501315,0xFF2005F1,0xFF000001,0x41FC1F02,0xFECC0BD5,0xFE880000,0xA1FC1F02,0xEC0004C8,0xBE001F04,0x41FC1F02,0xFECC0BD5,0xFE880000,0xA1FC1F02,0xEC0004C8,0xBE001F04,0xA1FC1F02,0xEC0004C8,0xBE001F04,0xBE001F04,0x41FC1F02,0xFECC0BD5,0xFE880000,0xA1FC1F02,0xEC0004C8,0xBE001F04,0xA1FC1F02,0xEC0004C8,0xBE001F04,0xBE001F04,0xA1FC1F02,
+0xEC0004C8,0xBE001F04,0xBE001F04,0xBE001F04,0xF7681C99,0x5981F02,0xFF6C1D09,0xFF30184D,0xFEE81379,0xFE4809A1,0xF4000164,0xE0000894,0xFD581C22,0xFF1417A5,0xFE000124,0xBE001F04,0x89FC1F02,0x240265,0x240265,0x240265,0x240265,0x240265,0x240265,0x240265,0x240265,0x240265,0x240265,0x6A000000,0x6A000000,0x6A000000,0x6A000000,0x6A000000,
+0x6A000000,0x32000001,0x32000001,0x32000001,0x22000000,0x340265,0x340265,0x340265,0x340265,0x340265,0x340265,0x280000DA,0x280000DA,0x280000DA,0x1E000074,0x640265,0x640265,0x640265,0x16000171,0x10000265,0xF21400C8,0x240265,0x240265,0xF6000000,0xAA000000,0x82000000,0x82000000,0x54000000,0xC40000C1,0x96000061,0x40000010,0x280000DA,
+0x480265,};
+static const uint32_t g_etc1_to_bc7_m6_table235[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x540001,0x800000,0x800000,0x800000,0x800000,0x800000,
+0x800000,0x1000000,0x1000000,0x1000000,0x2A000000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x1000000,0x1000000,0x1000000,0x2A000000,0x1000000,0x1000000,0x1000000,0x2A000000,0x2A000000,0x5C0000,0x540001,0x540001,0x640000,0x6C0000,0x740000,0x740000,0x900000,0x640000,0x6C0000,0xB40000,0x1000000,
+0xB40000,0x1100001,0x1100001,0x1100001,0x1100001,0x1980000,0x1980000,0x1980000,0x51F80000,0x51F80000,0x88000000,0x1980000,0x1980000,0x1980000,0x51F80000,0x51F80000,0x88000000,0x51F80000,0x51F80000,0x88000000,0x88000000,0x1980000,0x1980000,0x1980000,0x51F80000,0x51F80000,0x88000000,0x51F80000,0x51F80000,0x88000000,0x88000000,0x51F80000,
+0x51F80000,0x88000000,0x88000000,0x88000000,0x73C0000,0x1240000,0x1100001,0x1740000,0x1CC0000,0x21FC0000,0x39FC0000,0x5FF80000,0x1580000,0x1980000,0x21FC0000,0x88000000,0x21FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0xD895C3,0xFEB0608A,0xFE8835A3,0xFE78265A,0xFE80521D,0xFE581C6A,0xFE440859,0xFE3820E5,0xEC2007F6,0xC22C1ED1,0xFE686AA4,0xFE202A26,0xFE0C116E,0xFE04269A,0xE80007B5,0xC0001CD4,0xD600582B,0xC4002C2E,0xAC003425,0x90005828,0x14495C1,0xFE08488A,0xEE002B26,0xF400410D,0xD8001CB6,0xB4002B8D,0xC6006A14,0xB8003BF7,0xA4004028,0x8C00609C,0x27F895C1,
+0x9C006399,0x90005FA9,0x7E00782D,0x6C0095C1,0xFEA07179,0xFECC888F,0xFECC8AE7,0xFE6C4C2A,0xFE382902,0xFE040CD2,0xF4000288,0xD8000F71,0xFE906FEE,0xFE5046F2,0xE600202C,0xA4004028,0x1D095C1,0x120582B,0xFEF43833,0xFEC01C1A,0xFEB41142,0xFED03783,0xFE88113A,0xFE680195,0xFE641BE3,0xEA4005CA,0xC2541B35,0x1B05828,0xFE4C27C5,0xFE141142,0xFE08268D,0xE80007B5,
+0xC0001CD4,0x5DF45828,0xC4002C2E,0xAC003425,0x90005828,0x1B05828,0xFE4C27C5,0xFE141142,0xFE08268D,0xE80007B5,0xC0001CD4,0x5DF45828,0xC4002C2E,0xAC003425,0x90005828,0x5DF45828,0xC4002C2E,0xAC003425,0x90005828,0x90005828,0xFEF8494A,0xFF0C5253,0xFF0C5243,0xFEB03872,0xFE682411,0xFE040CCE,0xF4000288,0xD8000F71,0xFEDC4979,0xFE9035DE,0xE6001F68,0xAC003425,
+0x31FC5828,0x78265A,0x78265A,0x78265A,0x78265A,0xFE440859,0xFE440859,0xFE440859,0xC02C039D,0xC02C039D,0x882C039D,0xFE0C116E,0xFE0C116E,0xFE0C116E,0xBA0001BD,0xBA0001BD,0x88000004,0x84001144,0x84001144,0x72000668,0x58001144,0x2B0265A,0x2B0265A,0x2B0265A,0xA2000E36,0xA2000E36,0x7A00070D,0x740017D8,0x740017D8,0x68000B94,0x5200147D,0x168265A,
+0x168265A,0x560017C9,0x4A001CC8,0x3A00265D,0xFE5817D5,0xFE6C1F01,0x78265A,0xFE340D49,0xFE14045E,0xEE0001F4,0xDA000112,0xAA00031D,0xFE341721,0xFE100BF2,0xA60011A8,0x68000B94,0xFC265A,0xB41142,0xB41142,0xB41142,0xB41142,0xFE680195,0xFE680195,0xFE680195,0xB6540001,0xB6540001,0x88540001,0x10C1142,0x10C1142,0x10C1142,0xBA0001BD,0xBA0001BD,
+0x88000004,0xBF81142,0xBF81142,0x72000668,0x58001144,0x10C1142,0x10C1142,0x10C1142,0xBA0001BD,0xBA0001BD,0x88000004,0xBF81142,0xBF81142,0x72000668,0x58001144,0xBF81142,0xBF81142,0x72000668,0x58001144,0x58001144,0xFE900C31,0xFCA80D75,0xB41142,0xFE5C08C9,0xFE1803E8,0xEE0001F4,0xDA000112,0xAA00031D,0xFA700CD1,0xFE300869,0x17C1142,0x72000668,
+0x17C1142,0x1881B32,0xFF5C10BD,0xFF2C052D,0xFF100001,0x4DFC1B32,0xFEE40A55,0xFEA00000,0xA7FC1B32,0xEC000328,0xC2001B34,0x4DFC1B32,0xFEE40A55,0xFEA00000,0xA7FC1B32,0xEC000328,0xC2001B34,0xA7FC1B32,0xEC000328,0xC2001B34,0xC2001B34,0x4DFC1B32,0xFEE40A55,0xFEA00000,0xA7FC1B32,0xEC000328,0xC2001B34,0xA7FC1B32,0xEC000328,0xC2001B34,0xC2001B34,0xA7FC1B32,
+0xEC000328,0xC2001B34,0xC2001B34,0xC2001B34,0xFB7018F1,0x9A01B32,0xFB841962,0xFF401540,0xFEE81109,0xFE480871,0xF800009D,0xE4000665,0xFF5C1892,0xFF2014D2,0xFE1000E5,0xC2001B34,0x91FC1B32,0x2C039D,0x2C039D,0x2C039D,0x2C039D,0x2C039D,0x2C039D,0x2C039D,0x2C039D,0x2C039D,0x2C039D,0x82000000,0x82000000,0x82000000,0x82000000,0x82000000,
+0x82000000,0x3E000001,0x3E000001,0x3E000001,0x2A000000,0x40039D,0x40039D,0x40039D,0x40039D,0x40039D,0x40039D,0x34000152,0x34000152,0x34000152,0x280000AD,0x7C039D,0x7C039D,0x7C039D,0x1C00022D,0x1400039D,0xF61C0188,0x2C039D,0x2C039D,0xFE04001D,0xD2000000,0xA0000000,0xA0000000,0x68000000,0xF6000121,0xC2000099,0x50000019,0x34000152,
+0x58039D,};
+static const uint32_t g_etc1_to_bc7_m6_table236[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x680000,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,
+0x2980000,0x1380000,0x1380000,0x1380000,0x32000001,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,0x2980000,0x1380000,0x1380000,0x1380000,0x32000001,0x1380000,0x1380000,0x1380000,0x32000001,0x32000001,0xE6C0000,0x680000,0x680000,0x780000,0x2800000,0x8C0000,0x8C0000,0x2AC0000,0x780000,0x2800000,0xDC0000,0x1380000,
+0xDC0000,0x1240000,0x1240000,0x1240000,0x1240000,0x3B00000,0x3B00000,0x3B00000,0x5DFC0000,0x5DFC0000,0x90000001,0x3B00000,0x3B00000,0x3B00000,0x5DFC0000,0x5DFC0000,0x90000001,0x5DFC0000,0x5DFC0000,0x90000001,0x90000001,0x3B00000,0x3B00000,0x3B00000,0x5DFC0000,0x5DFC0000,0x90000001,0x5DFC0000,0x5DFC0000,0x90000001,0x90000001,0x5DFC0000,
+0x5DFC0000,0x90000001,0x90000001,0x90000001,0x1540000,0x1380000,0x1240000,0x18C0000,0x1EC0000,0x33FC0000,0x49F80000,0x6BF80000,0x36C0000,0x3B00000,0x33FC0000,0x90000001,0x33FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0xE49371,0xFEB06174,0xFE943921,0xFE842AC8,0xFE8C5159,0xFE641E9A,0xFE500B99,0xFE401F71,0xEE300834,0xC8341C7D,0xFE7466F6,0xFE2C29B8,0xFE181234,0xFE0821B1,0xEE000485,0xC60017E2,0xE00050A2,0xCA002684,0xB2002CE1,0x960050A2,0x150936F,0xFE0849BC,0xEE002D78,0xFA003CBD,0xE2001A89,0xBA00277B,0xCC006426,0xC0003749,0xAA0039C2,0x920059D2,0x2DF8936F,
+0xA60061D4,0x96005B93,0x8400735F,0x7000936F,0xFEB46FEE,0xFECC86CD,0xF6DC89B8,0xFE804B93,0xFE3C288E,0xFE040BB2,0xF80000EC,0xE0000ADE,0xFE986E7F,0xFE544677,0xF0001BFE,0xAA0039C2,0x1E0936F,0x12C50A5,0xFF00340D,0xFED81AE4,0xFEC41144,0xFEDC3275,0xFEA01012,0xFE8001F9,0xFE701821,0xEA580474,0xC8681735,0x1C050A2,0xFE642553,0xFE2C1144,0xFE0821A1,0xEE000485,
+0xC60017E2,0x65F850A2,0xCA002684,0xB2002CE1,0x960050A2,0x1C050A2,0xFE642553,0xFE2C1144,0xFE0821A1,0xEE000485,0xC60017E2,0x65F850A2,0xCA002684,0xB2002CE1,0x960050A2,0x65F850A2,0xCA002684,0xB2002CE1,0x960050A2,0x960050A2,0xFEF84350,0xFB244B59,0xFD284B14,0xFEC033C8,0xFE7C2149,0xFE040BAE,0xF80000EC,0xE0000ADE,0xFEF843BD,0xFEA431C2,0xF0001B1D,0xB2002CE1,
+0x3DF850A2,0x842AC8,0x842AC8,0x842AC8,0x842AC8,0xFE500B99,0xFE500B99,0xFE500B99,0xCC340548,0xCC340548,0x90340549,0xFE181234,0xFE181234,0xFE181234,0xCC000121,0xCC000121,0x92040009,0x92001142,0x92001142,0x7E0005AA,0x62001142,0xC42AC8,0xC42AC8,0xC42AC8,0xA8000FDA,0xA8000FDA,0x86000849,0x80001946,0x80001946,0x74000BC6,0x5E001523,0x18C2AC8,
+0x18C2AC8,0x5C001A61,0x50001F2E,0x40002ACB,0xFE681BBA,0xF67C23A8,0x842AC8,0xFE441026,0xFE1805AA,0xFC000171,0xEA000088,0xB6000274,0xFE3C1B18,0xFE180E8E,0xB60011C3,0x74000BC6,0x1182AC8,0xC41144,0xC41144,0xC41144,0xC41144,0xFE8001F9,0xFE8001F9,0xFE8001F9,0xBE680001,0xBE680001,0x90680001,0x3241142,0x3241142,0x3241142,0xCC000121,0xCC000121,
+0x900C0001,0x17FC1142,0x17FC1142,0x7E0005AA,0x62001142,0x3241142,0x3241142,0x3241142,0xCC000121,0xCC000121,0x900C0001,0x17FC1142,0x17FC1142,0x7E0005AA,0x62001142,0x17FC1142,0x17FC1142,0x7E0005AA,0x62001142,0x62001142,0xFEA00C82,0xF6BC0DC8,0xC41144,0xFE78094D,0xFE2C046A,0xFC000171,0xEA000088,0xB6000274,0xFE780D0D,0xFE4808B4,0x1A41142,0x7E0005AA,
+0x1A41142,0x1901735,0xFF680E48,0xFF380464,0xFF240000,0x59FC1735,0xFEFC08C8,0xFEB80001,0xADFC1735,0xF20001B1,0xC8001735,0x59FC1735,0xFEFC08C8,0xFEB80001,0xADFC1735,0xF20001B1,0xC8001735,0xADFC1735,0xF20001B1,0xC8001735,0xC8001735,0x59FC1735,0xFEFC08C8,0xFEB80001,0xADFC1735,0xF20001B1,0xC8001735,0xADFC1735,0xF20001B1,0xC8001735,0xC8001735,0xADFC1735,
+0xF20001B1,0xC8001735,0xC8001735,0xC8001735,0xFF781522,0x1AC1735,0xFF8C1589,0xFF401231,0xFEFC0E90,0xFE840734,0xFC000014,0xEC000454,0xFF701520,0xFF4011AD,0xFE3000C5,0xC8001735,0x99FC1735,0x340548,0x340548,0x340548,0x340548,0x340548,0x340548,0x340548,0x340548,0x340548,0x340548,0x9C000000,0x9C000000,0x9C000000,0x9C000000,0x9C000000,
+0x9C000000,0x4C000000,0x4C000000,0x4C000000,0x32000001,0x4C0548,0x4C0548,0x4C0548,0x4C0548,0x4C0548,0x4C0548,0x3A0001F9,0x3A0001F9,0x3A0001F9,0x2E0000FA,0x980548,0x980548,0x980548,0x2000034D,0x1800054A,0xFA2402AD,0x340548,0x340548,0xFE100091,0xFE000000,0xC2000000,0xC2000000,0x7E000000,0xFC000200,0xE40000DD,0x60000024,0x3A0001F9,
+0x6C0548,};
+static const uint32_t g_etc1_to_bc7_m6_table237[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x780000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,
+0x2B00000,0x1680000,0x1680000,0x1680000,0x3A000001,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x2B00000,0x1680000,0x1680000,0x1680000,0x3A000001,0x1680000,0x1680000,0x1680000,0x3A000001,0x3A000001,0x800000,0x780000,0x780000,0x8C0000,0x2940000,0xA40000,0xA40000,0xC80000,0x8C0000,0x2940000,0xFC0000,0x1680000,
+0xFC0000,0x1340000,0x1340000,0x1340000,0x1340000,0x1C80000,0x1C80000,0x1C80000,0x69FC0000,0x69FC0000,0x98000001,0x1C80000,0x1C80000,0x1C80000,0x69FC0000,0x69FC0000,0x98000001,0x69FC0000,0x69FC0000,0x98000001,0x98000001,0x1C80000,0x1C80000,0x1C80000,0x69FC0000,0x69FC0000,0x98000001,0x69FC0000,0x69FC0000,0x98000001,0x98000001,0x69FC0000,
+0x69FC0000,0x98000001,0x98000001,0x98000001,0x5640000,0x1480000,0x1340000,0x1A40000,0x7FC0000,0x41FC0000,0x55FC0000,0x77F40000,0x3800000,0x1C80000,0x41FC0000,0x98000001,0x41FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0xEC91E9,0xFEC46279,0xFEA03CA5,0xFE902F14,0xFE985139,0xFE64210A,0xFE5C0EF9,0xFE4C1EBD,0xF23808E4,0xCC3C1AF5,0xFE806462,0xFE3829E8,0xFE241378,0xFE081E61,0xF000026D,0xCC00141E,0xE8004A4E,0xD0002208,0xB80026E5,0x9C004A4E,0x15C91E7,0xFE084BDC,0xF4003058,0xFA0039ED,0xE2001939,0xC000247F,0xD8005F3E,0xC60033B5,0xAE00348E,0x98005432,0x33F891E7,
+0xA60060B4,0x9C005887,0x8A006F9B,0x740091E7,0xFEBC6F6D,0xF8E085F5,0xFAE48878,0xFE804B93,0xFE4C28D8,0xFE100BA9,0xFC000045,0xE40007A9,0xFE986E0F,0xFE5C46BB,0xF60018B4,0xAE00348E,0x1F091E7,0x1384A4D,0xFF0C3095,0xFEE419E8,0xFED41144,0xFEE82E49,0xFEAC0F1E,0xFE980269,0xFE881509,0xEE6C0364,0xCC7813ED,0x1D04A4D,0xFE70234B,0xFE441142,0xFE141E3D,0xF000026D,
+0xCC00141E,0x6DF84A4D,0xD0002208,0xB80026E5,0x9C004A4E,0x1D04A4D,0xFE70234B,0xFE441142,0xFE141E3D,0xF000026D,0xCC00141E,0x6DF84A4D,0xD0002208,0xB80026E5,0x9C004A4E,0x6DF84A4D,0xD0002208,0xB80026E5,0x9C004A4E,0x9C004A4E,0xFF143E02,0xFF2C4531,0xFF2C4538,0xFED43009,0xFE901F05,0xFE240B1D,0xFC000045,0xE40007A9,0xFEF83E4D,0xFEC02DC4,0xF60017D3,0xB80026E5,
+0x45FC4A4D,0x902F14,0x902F14,0x902F14,0x902F14,0xFE5C0EF9,0xFE5C0EF9,0xFE5C0EF9,0xD63C0708,0xD63C0708,0x983C0709,0xFE241378,0xFE241378,0xFE241378,0xD80000B9,0xD80000B9,0x9A080035,0x9E001142,0x9E001142,0x84000502,0x6A001142,0x2D02F13,0x2D02F13,0x2D02F13,0xB400119A,0xB400119A,0x8C0009B1,0x8C001AA6,0x8C001AA6,0x7A000C12,0x620015C2,0x1AC2F13,
+0x1AC2F13,0x66001D13,0x56002186,0x46002F13,0xFE681F7A,0xFC8827B4,0x902F14,0xFE4C1319,0xFE2C078E,0xFE040199,0xFC000041,0xC00001D4,0xFE501E81,0xFE301181,0xC60011D4,0x7A000C12,0x12C2F13,0xD41144,0xD41144,0xD41144,0xD41144,0xFE980269,0xFE980269,0xFE980269,0xC6780001,0xC6780001,0x98780001,0x33C1142,0x33C1142,0x33C1142,0xD80000B9,0xD80000B9,
+0x981C0001,0x23FC1142,0x23FC1142,0x84000502,0x6A001142,0x33C1142,0x33C1142,0x33C1142,0xD80000B9,0xD80000B9,0x981C0001,0x23FC1142,0x23FC1142,0x84000502,0x6A001142,0x23FC1142,0x23FC1142,0x84000502,0x6A001142,0x6A001142,0xFAB40CD1,0xFECC0DC8,0xD41144,0xFE880994,0xFE4804D9,0xFE0C0190,0xFC000041,0xC00001D4,0xFE940D2A,0xFE5C0901,0x1C81142,0x84000502,
+0x1C81142,0x19813ED,0xFF740C44,0xFF4C03D9,0xFF340000,0x65FC13ED,0xFF080784,0xFED00000,0xB3FC13ED,0xF80000CD,0xCC0013ED,0x65FC13ED,0xFF080784,0xFED00000,0xB3FC13ED,0xF80000CD,0xCC0013ED,0xB3FC13ED,0xF80000CD,0xCC0013ED,0xCC0013ED,0x65FC13ED,0xFF080784,0xFED00000,0xB3FC13ED,0xF80000CD,0xCC0013ED,0xB3FC13ED,0xF80000CD,0xCC0013ED,0xCC0013ED,0xB3FC13ED,
+0xF80000CD,0xCC0013ED,0xCC0013ED,0xCC0013ED,0xFF781232,0x1B413ED,0xFF8C1289,0xFF580FA1,0xFF100C84,0xFE980631,0xFE0C0000,0xF20002D0,0xFF701220,0xFF400F1D,0xFE5000A9,0xCC0013ED,0x9FFC13ED,0x3C0708,0x3C0708,0x3C0708,0x3C0708,0x3C0708,0x3C0708,0x3C0708,0x3C0708,0x3C0708,0x3C0708,0xB6000000,0xB6000000,0xB6000000,0xB6000000,0xB6000000,
+0xB6000000,0x58000000,0x58000000,0x58000000,0x3A000001,0x580708,0x580708,0x580708,0x580708,0x580708,0x580708,0x460002A1,0x460002A1,0x460002A1,0x34000152,0xB00708,0xB00708,0xB00708,0x2600045D,0x1C00070A,0xFE2C03F5,0x3C0708,0x3C0708,0xFA180154,0xFC080029,0xE0000000,0xE0000000,0x92000000,0xFA080322,0xFE000140,0x70000031,0x460002A1,
+0x7C0708,};
+static const uint32_t g_etc1_to_bc7_m6_table238[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0x880000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,
+0xC80000,0x1980000,0x1980000,0x1980000,0x42000001,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0xC80000,0x1980000,0x1980000,0x1980000,0x42000001,0x1980000,0x1980000,0x1980000,0x42000001,0x42000001,0x900000,0x880000,0x880000,0x49C0000,0x2A80000,0xB80000,0xB80000,0xE40000,0x49C0000,0x2A80000,0x1200000,0x1980000,
+0x1200000,0x1440000,0x1440000,0x1440000,0x1440000,0x1E00000,0x1E00000,0x1E00000,0x75FC0000,0x75FC0000,0xA0000001,0x1E00000,0x1E00000,0x1E00000,0x75FC0000,0x75FC0000,0xA0000001,0x75FC0000,0x75FC0000,0xA0000001,0xA0000001,0x1E00000,0x1E00000,0x1E00000,0x75FC0000,0x75FC0000,0xA0000001,0x75FC0000,0x75FC0000,0xA0000001,0xA0000001,0x75FC0000,
+0x75FC0000,0xA0000001,0xA0000001,0xA0000001,0x1780000,0x5580000,0x1440000,0x1B80000,0x1BFC0000,0x51FC0000,0x63FC0000,0x81F80000,0x3940000,0x1E00000,0x51FC0000,0xA0000001,0x51FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0xF490E1,0xFEC46419,0xFEA04085,0xFE9833B4,0xFEA451A9,0xFE7023E2,0xFE5C12C9,0xFE581EA9,0xF6400A14,0xD04419ED,0xFE806262,0xFE402ADB,0xFE301544,0xFE141BF1,0xF60000F9,0xD00010E6,0xF000444D,0xD6001E14,0xBE002159,0xA000444E,0x16890DF,0xFE144EC8,0xFA003418,0xFA00381D,0xE80018CD,0xC6002223,0xE2005A92,0xCC0030B1,0xB4002FCA,0x98004EF2,0x39F890DF,
+0xAC006018,0x9C005607,0x8A006C1B,0x780090DF,0xFEBC6F7D,0xFCE884ED,0xFEEC87B8,0xFE944C1E,0xFE50299A,0xFE180BFB,0xFE040069,0xEA0004E2,0xFEB46DCE,0xFE704795,0xF6001634,0xB4002FCA,0x3FC90DF,0x144444D,0xFF182D4D,0xFEF01904,0xFEE41144,0xFEF42A65,0xFEB80E5A,0xFEA402D5,0xFE941241,0xF07C0278,0xD08810E5,0x1E0444D,0xFE882153,0xFE5C1142,0xFE2C1B35,0xF60000F9,
+0xD00010E6,0x75FC444D,0xD6001E14,0xBE002159,0xA000444E,0x1E0444D,0xFE882153,0xFE5C1142,0xFE2C1B35,0xF60000F9,0xD00010E6,0x75FC444D,0xD6001E14,0xBE002159,0xA000444E,0x75FC444D,0xD6001E14,0xBE002159,0xA000444E,0xA000444E,0xFF20392D,0xFF2C3FE1,0xF9404005,0xFEEC2C7A,0xFEA41CE9,0xFE380A7D,0xFE0C0050,0xEA0004E2,0xFF08395E,0xFEC82A3E,0xF6001553,0xBE002159,
+0x51FC444D,0x9833B4,0x9833B4,0x9833B4,0x9833B4,0xFE5C12C9,0xFE5C12C9,0xFE5C12C9,0xE0440908,0xE0440908,0xA0440909,0xFE301544,0xFE301544,0xFE301544,0xE8000059,0xE8000059,0xA20C0089,0xAA001142,0xAA001142,0x9000046A,0x72001142,0xE433B3,0xE433B3,0xE433B3,0xC000139A,0xC000139A,0x98000B59,0x98001C26,0x98001C26,0x86000C7A,0x6E001672,0x1D033B3,
+0x1D033B3,0x6C001FE3,0x5C00240E,0x4C0033B3,0xFE7423B8,0xFE8C2C28,0x9833B4,0xFE541675,0xFE2C09CE,0xFE0C0274,0xFE040069,0xCC00015A,0xFE5022C1,0xFE3014B1,0xD60011ED,0x86000C7A,0x14833B3,0xE41144,0xE41144,0xE41144,0xE41144,0xFEA402D5,0xFEA402D5,0xFEA402D5,0xCE880001,0xCE880001,0xA0880001,0x1541142,0x1541142,0x1541142,0xE8000059,0xE8000059,
+0xA02C0001,0x2FFC1142,0x2FFC1142,0x9000046A,0x72001142,0x1541142,0x1541142,0x1541142,0xE8000059,0xE8000059,0xA02C0001,0x2FFC1142,0x2FFC1142,0x9000046A,0x72001142,0x2FFC1142,0x2FFC1142,0x9000046A,0x72001142,0x72001142,0xFEBC0CF9,0xF6DC0E1D,0xE41144,0xFE9809E5,0xFE5C0551,0xFE2001E2,0xFE0C0050,0xCC00015A,0xFAAC0D75,0xFE740975,0x1E81142,0x9000046A,
+0x1E81142,0x1A010E5,0xFF800A68,0xFF58033D,0xFF440000,0x71FC10E5,0xFF200654,0xFEE80000,0xB9FC10E5,0xF800003D,0xD00010E5,0x71FC10E5,0xFF200654,0xFEE80000,0xB9FC10E5,0xF800003D,0xD00010E5,0xB9FC10E5,0xF800003D,0xD00010E5,0xD00010E5,0x71FC10E5,0xFF200654,0xFEE80000,0xB9FC10E5,0xF800003D,0xD00010E5,0xB9FC10E5,0xF800003D,0xD00010E5,0xD00010E5,0xB9FC10E5,
+0xF800003D,0xD00010E5,0xD00010E5,0xD00010E5,0xFD900F79,0x1BC10E5,0xF79C0FD4,0xFF6C0D2A,0xFF280A82,0xFEC00544,0xFE340000,0xF2000190,0xF7880F79,0xFF4C0CE2,0xFE700090,0xD00010E5,0xA7FC10E5,0x440908,0x440908,0x440908,0x440908,0x440908,0x440908,0x440908,0x440908,0x440908,0x440908,0xCE000000,0xCE000000,0xCE000000,0xCE000000,0xCE000000,
+0xCE000000,0x64000000,0x64000000,0x64000000,0x42000001,0x640908,0x640908,0x640908,0x640908,0x640908,0x640908,0x52000369,0x52000369,0x52000369,0x3A0001BA,0xCC0908,0xCC0908,0xCC0908,0x2C000595,0x2000090A,0xFE2C05A5,0x440908,0x440908,0xFE200244,0xFE0C009D,0xFE000000,0xFE000000,0xA6000000,0xFE100482,0xFE000200,0x7E000041,0x52000369,
+0x900908,};
+static const uint32_t g_etc1_to_bc7_m6_table239[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0x980000,0xE00000,0xE00000,0xE00000,0xE00000,0xE00000,
+0xE00000,0x1CC0000,0x1CC0000,0x1CC0000,0x4A000001,0xE00000,0xE00000,0xE00000,0xE00000,0xE00000,0xE00000,0x1CC0000,0x1CC0000,0x1CC0000,0x4A000001,0x1CC0000,0x1CC0000,0x1CC0000,0x4A000001,0x4A000001,0x8A00000,0x980000,0x980000,0xB00000,0x2BC0000,0x2CC0000,0x2CC0000,0x1000000,0xB00000,0x2BC0000,0x1400000,0x1CC0000,
+0x1400000,0x1540000,0x1540000,0x1540000,0x1540000,0x1F80000,0x1F80000,0x1F80000,0x81FC0000,0x81FC0000,0xA8000001,0x1F80000,0x1F80000,0x1F80000,0x81FC0000,0x81FC0000,0xA8000001,0x81FC0000,0x81FC0000,0xA8000001,0xA8000001,0x1F80000,0x1F80000,0x1F80000,0x81FC0000,0x81FC0000,0xA8000001,0x81FC0000,0x81FC0000,0xA8000001,0xA8000001,0x81FC0000,
+0x81FC0000,0xA8000001,0xA8000001,0xA8000001,0x18C0000,0xD680000,0x1540000,0x3CC0000,0x2FFC0000,0x5FFC0000,0x71FC0000,0x8BFC0000,0x3A80000,0x1F80000,0x5FFC0000,0xA8000001,0x5FFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0xFC9059,0xFED0662D,0xFEAC44A9,0xFEA438A8,0xFEB052A9,0xFE7C2732,0xFE6816F9,0xFE581F29,0xFA480BC4,0xD44C1965,0xFE8C60F6,0xFE4C2C1F,0xFE3C1798,0xFE201A39,0xFA000035,0xD4080E36,0xF8003EA2,0xDC001AA8,0xC4001C3D,0xA6003EA2,0x1749057,0xFE20521C,0xFC0038AF,0xFA00374D,0xEE001919,0xCC002067,0xE2005652,0xD2002E3D,0xBA002B7E,0xA20049CB,0x3FF89057,
+0xB2006024,0xA6005459,0x9000690F,0x7C009057,0xFED06FC2,0xFEEC8481,0xFEEC87D8,0xFE984D29,0xFE602AF8,0xFE240D01,0xFE100125,0xF00002D9,0xFEB46DDE,0xFE80487B,0xFE001462,0xBA002B7E,0xBFC9057,0x14C3EA5,0xFF242A35,0xFF081824,0xFEF41144,0xFF0026C9,0xFECC0DAC,0xFEBC0355,0xFEAC0FB9,0xF28C01B4,0xD4980E1D,0x1F03EA2,0xFEA01F7B,0xFE741142,0xFE381881,0xFA000035,
+0xD4100E1E,0x7DF83EA2,0xDC001AA8,0xC4001C3D,0xA6003EA2,0x1F03EA2,0xFEA01F7B,0xFE741142,0xFE381881,0xFA000035,0xD4100E1E,0x7DF83EA2,0xDC001AA8,0xC4001C3D,0xA6003EA2,0x7DF83EA2,0xDC001AA8,0xC4001C3D,0xA6003EA2,0xA6003EA2,0xFF343494,0xFB443A79,0xFD483A9D,0xFEEC292A,0xFEA81AF3,0xFE480A18,0xFE280088,0xF00002D9,0xFF1834C1,0xFEDC273A,0xFE001362,0xC4001C3D,
+0x5BFC3EA2,0xA438A8,0xA438A8,0xA438A8,0xA438A8,0xFE6816F9,0xFE6816F9,0xFE6816F9,0xEA4C0B48,0xEA4C0B48,0xA84C0B49,0xFE3C1798,0xFE3C1798,0xFE3C1798,0xFA000025,0xFA000025,0xAE100102,0xB6001142,0xB6001142,0x960003DA,0x7A001142,0xF438A8,0xF438A8,0xF438A8,0xCC0015DA,0xCC0015DA,0xA2000D3B,0xA2001D8D,0xA2001D8D,0x8C000CF6,0x7400172E,0x1F038A8,
+0x1F038A8,0x720022FB,0x660026FB,0x500038AB,0xFE842831,0xF69C3169,0xA438A8,0xFE5C1A55,0xFE400CA2,0xFE1C03D8,0xFE100125,0xDA0000FA,0xFE64274E,0xFE44188A,0xE6001206,0x8C000CF6,0x15C38A8,0xF41144,0xF41144,0xF41144,0xF41144,0xFEBC0355,0xFEBC0355,0xFEBC0355,0xD6980001,0xD6980001,0xA8980001,0x16C1142,0x16C1142,0x16C1142,0xFA000025,0xFA000025,
+0xA83C0001,0x3BFC1142,0x3BFC1142,0x960003DA,0x7A001142,0x16C1142,0x16C1142,0x16C1142,0xFA000025,0xFA000025,0xA83C0001,0x3BFC1142,0x3BFC1142,0x960003DA,0x7A001142,0x3BFC1142,0x3BFC1142,0x960003DA,0x7A001142,0x7A001142,0xFED80D22,0xFEEC0E1D,0xF41144,0xFEA40A68,0xFE7005D1,0xFE380249,0xFE280088,0xDA0000FA,0xFEB40D9D,0xFE9809D9,0x7FC1142,0x960003DA,
+0x7FC1142,0x1A80E1D,0xFF8C08B4,0xFF6402B1,0xFF540000,0x7DFC0E1D,0xFF380544,0xFF000000,0xBFFC0E1D,0xFE000001,0xD4000E1D,0x7DFC0E1D,0xFF380544,0xFF000000,0xBFFC0E1D,0xFE000001,0xD4000E1D,0xBFFC0E1D,0xFE000001,0xD4000E1D,0xD4000E1D,0x7DFC0E1D,0xFF380544,0xFF000000,0xBFFC0E1D,0xFE000001,0xD4000E1D,0xBFFC0E1D,0xFE000001,0xD4000E1D,0xD4000E1D,0xBFFC0E1D,
+0xFE000001,0xD4000E1D,0xD4000E1D,0xD4000E1D,0xFF940CD5,0x1C40E1D,0xFBA40D24,0xFF6C0AFA,0xFF3C08CA,0xFEC80451,0xFE5C0000,0xF60000B9,0xFB900CD1,0xFF640AD2,0xFE940079,0xD4000E1D,0xAFFC0E1D,0x4C0B48,0x4C0B48,0x4C0B48,0x4C0B48,0x4C0B48,0x4C0B48,0x4C0B48,0x4C0B48,0x4C0B48,0x4C0B48,0xE6000000,0xE6000000,0xE6000000,0xE6000000,0xE6000000,
+0xE6000000,0x70000000,0x70000000,0x70000000,0x4A000001,0x700B48,0x700B48,0x700B48,0x700B48,0x700B48,0x700B48,0x58000449,0x58000449,0x58000449,0x4600022A,0xE40B48,0xE40B48,0xE40B48,0x320006F5,0x24000B4A,0xF63C0784,0x4C0B48,0x4C0B48,0xFE2C039D,0xFE140164,0xFE080029,0xFE080029,0xBA000000,0xFE100652,0xFE000340,0x86000050,0x58000449,
+0xA00B48,};
+static const uint32_t g_etc1_to_bc7_m6_table240[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xA80001,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,
+0xFC0000,0x3F80000,0x3F80000,0x3F80000,0x54000000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0x3F80000,0x3F80000,0x3F80000,0x54000000,0x3F80000,0x3F80000,0x3F80000,0x54000000,0x54000000,0x2B40000,0xA80001,0xA80001,0x2C40000,0xD40000,0xE80000,0xE80000,0x11C0000,0x2C40000,0xD40000,0x1680000,0x3F80000,
+0x1680000,0x1640001,0x1640001,0x1640001,0x1640001,0x19FC0000,0x19FC0000,0x19FC0000,0x8FF80000,0x8FF80000,0xB2000000,0x19FC0000,0x19FC0000,0x19FC0000,0x8FF80000,0x8FF80000,0xB2000000,0x8FF80000,0x8FF80000,0xB2000000,0xB2000000,0x19FC0000,0x19FC0000,0x19FC0000,0x8FF80000,0x8FF80000,0xB2000000,0x8FF80000,0x8FF80000,0xB2000000,0xB2000000,0x8FF80000,
+0x8FF80000,0xB2000000,0xB2000000,0xB2000000,0x1A00000,0x77C0000,0x1640001,0x1E80000,0x45FC0000,0x71FC0000,0x7FFC0000,0x99F40000,0x1C00000,0x19FC0000,0x71FC0000,0xB2000000,0x71FC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1049057,0xFEDC690F,0xFEB849CB,0xFEB03EA2,0xFEB05459,0xFE882B7E,0xFE741C3D,0xFE642067,0xFA540E36,0xD8541965,0xFE986024,0xFE582E3D,0xFE441AA8,0xFE201919,0xFE040035,0xDA080BC4,0xFE0438AF,0xE0001798,0xCA0016F9,0xAC0038A8,0x3809057,0xFE385652,0xFE0C3EA2,0xFE08374D,0xEE001A39,0xD2001F29,0xEE00521C,0xD8002C1F,0xC0002732,0xA80044A9,0x45FC9057,
+0xB80060F6,0xA60052A9,0x9600662D,0x80009059,0xFED870CD,0xFEEC8535,0xF90088B3,0xFE984F45,0xFE682CFD,0xFE2C0EC7,0xFE1C02D9,0xF6000125,0xFEB46F22,0xFE804A3D,0xFE001354,0xC0002732,0x15FC9057,0x15838AB,0xFF3026FB,0xFF14172E,0xFF081142,0xFF1822FB,0xFEE40CF6,0xFED003DA,0xFEB80D3B,0xF6A00102,0xD8A80B49,0x7FC38A8,0xFEB81D8D,0xFE901142,0xFE5815DA,0xFE080025,
+0xD8280B48,0x85FC38A8,0xE0001798,0xCA0016F9,0xAC0038A8,0x7FC38A8,0xFEB81D8D,0xFE901142,0xFE5815DA,0xFE080025,0xD8280B48,0x85FC38A8,0xE0001798,0xCA0016F9,0xAC0038A8,0x85FC38A8,0xE0001798,0xCA0016F9,0xAC0038A8,0xAC0038A8,0xFF342F72,0xFF4C34BB,0xFF4C3533,0xFF082595,0xFEC818C5,0xFE7009A1,0xFE3C00FA,0xF6000125,0xFF243009,0xFEE8241E,0xFE001254,0xCA0016F9,
+0x65FC38A8,0xB03EA2,0xB03EA2,0xB03EA2,0xB03EA2,0xFE741C3D,0xFE741C3D,0xFE741C3D,0xF4540E1E,0xF4540E1E,0xB2540E1D,0xFE441AA8,0xFE441AA8,0xFE441AA8,0xFE040035,0xFE040035,0xB81801B4,0xC4001142,0xC4001142,0xA0000355,0x82001144,0x1043EA2,0x1043EA2,0x1043EA2,0xE2001881,0xE2001881,0xA8000FB9,0xAE001F7B,0xAE001F7B,0x98000DAC,0x7A001824,0x7FC3EA2,
+0x7FC3EA2,0x7E0026C9,0x6C002A35,0x56003EA5,0xFE902DE5,0xFCA83721,0xB03EA2,0xFE701F65,0xFE441079,0xFE24061D,0xFE1C02D9,0xEA000088,0xFE782CA5,0xFE501D0A,0xF6001225,0x98000DAC,0x1743EA2,0x1081142,0x1081142,0x1081142,0x1081142,0xFED003DA,0xFED003DA,0xFED003DA,0xE0A80001,0xE0A80001,0xB2A80001,0x1881142,0x1881142,0x1881142,0xFE080025,0xFE080025,
+0xB24C0001,0x49F81142,0x49F81142,0xA0000355,0x82001144,0x1881142,0x1881142,0x1881142,0xFE080025,0xFE080025,0xB24C0001,0x49F81142,0x49F81142,0xA0000355,0x82001144,0x49F81142,0x49F81142,0xA0000355,0x82001144,0x82001144,0xFAEC0D75,0xF9000E72,0x1081142,0xFEC40ABA,0xFE98065D,0xFE5802F2,0xFE3C00FA,0xEA000088,0xFED00DD0,0xFEA40A40,0x19FC1142,0xA0000355,
+0x19FC1142,0x1B00B4A,0xFF9806F5,0xFF70022A,0xFF640001,0x8DFC0B48,0xFF4C0449,0xFF1C0000,0xC7FC0B48,0xFE2C0000,0xD8000B48,0x8DFC0B48,0xFF4C0449,0xFF1C0000,0xC7FC0B48,0xFE2C0000,0xD8000B48,0xC7FC0B48,0xFE2C0000,0xD8000B48,0xD8000B48,0x8DFC0B48,0xFF4C0449,0xFF1C0000,0xC7FC0B48,0xFE2C0000,0xD8000B48,0xC7FC0B48,0xFE2C0000,0xD8000B48,0xD8000B48,0xC7FC0B48,
+0xFE2C0000,0xD8000B48,0xD8000B48,0xD8000B48,0xFF940A68,0xFCC0B48,0xFFAC0A6D,0xFF8408D1,0xFF500709,0xFEF00382,0xFE880000,0xFA000029,0xFF980A22,0xFF7008B4,0xFEB80064,0xD8000B48,0xB9FC0B48,0x540E1D,0x540E1D,0x540E1D,0x540E1D,0x540E1D,0x540E1D,0x540E1D,0x540E1D,0x540E1D,0x540E1D,0xFE000001,0xFE000001,0xFE000001,0xFE000001,0xFE000001,
+0xFE000001,0x7E000000,0x7E000000,0x7E000000,0x54000000,0x7C0E1D,0x7C0E1D,0x7C0E1D,0x7C0E1D,0x7C0E1D,0x7C0E1D,0x62000544,0x62000544,0x62000544,0x4C0002B1,0xFC0E1D,0xFC0E1D,0xFC0E1D,0x380008B4,0x2A000E1D,0xFC4809D9,0x540E1D,0x540E1D,0xFE2C0568,0xFE200290,0xFE1000B9,0xFE1000B9,0xD0000000,0xFE20088A,0xFE1404E2,0x9E000065,0x62000544,
+0xB00E1D,};
+static const uint32_t g_etc1_to_bc7_m6_table241[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0xB80001,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,
+0x1140000,0xFF80000,0xFF80000,0xFF80000,0x5C000000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0x1140000,0xFF80000,0xFF80000,0xFF80000,0x5C000000,0xFF80000,0xFF80000,0xFF80000,0x5C000000,0x5C000000,0xAC40000,0xB80001,0xB80001,0xD80000,0xE80000,0xFC0000,0xFC0000,0x1380000,0xD80000,0xE80000,0x18C0000,0xFF80000,
+0x18C0000,0x1740001,0x1740001,0x1740001,0x1740001,0x31FC0000,0x31FC0000,0x31FC0000,0x9BF80000,0x9BF80000,0xBA000000,0x31FC0000,0x31FC0000,0x31FC0000,0x9BF80000,0x9BF80000,0xBA000000,0x9BF80000,0x9BF80000,0xBA000000,0xBA000000,0x31FC0000,0x31FC0000,0x31FC0000,0x9BF80000,0x9BF80000,0xBA000000,0x9BF80000,0x9BF80000,0xBA000000,0xBA000000,0x9BF80000,
+0x9BF80000,0xBA000000,0xBA000000,0xBA000000,0x1B40000,0xF8C0000,0x1740001,0x1FC0000,0x59FC0000,0x7FFC0000,0x8DFC0000,0xA3F80000,0x1D40000,0x31FC0000,0x7FFC0000,0xBA000000,0x7FFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x10C90DF,0xFEE86C1B,0xFEC04EF2,0xFEBC444E,0xFEC45607,0xFE942FCA,0xFE802159,0xFE702223,0xFE5C10E6,0xDC5C19ED,0xFEA46018,0xFE6430B1,0xFE501E14,0xFE2C18CD,0xFE1000F9,0xDE100A14,0xFE083418,0xE6001544,0xCA0012C9,0xB20033B4,0x38C90DF,0xFE385A92,0xFE1C444D,0xFE08381D,0xF4001BF1,0xD2001EA9,0xF4004EC8,0xDE002ADB,0xC60023E2,0xAE004085,0x4BFC90DF,
+0xBE006262,0xAC0051A9,0x9C006419,0x840090E1,0xFEE47241,0xFB048637,0xFD08897B,0xFEAC5155,0xFE742F9E,0xFE381111,0xFE2804E2,0xFC000069,0xFED07092,0xFE904C7B,0xFE001374,0xC60023E2,0x1DF890DF,0x16433B3,0xFF44240E,0xFF201672,0xFF181142,0xFF241FE3,0xFEF00C7A,0xFEDC046A,0xFECC0B59,0xF6B40089,0xDCB80909,0x15FC33B3,0xFECC1C26,0xFEA81142,0xFE70139A,0xFE2C0059,
+0xDC3C0908,0x8DFC33B3,0xE6001544,0xCA0012C9,0xB20033B4,0x15FC33B3,0xFECC1C26,0xFEA81142,0xFE70139A,0xFE2C0059,0xDC3C0908,0x8DFC33B3,0xE6001544,0xCA0012C9,0xB20033B4,0x8DFC33B3,0xE6001544,0xCA0012C9,0xB20033B4,0xB20033B4,0xFF3C2BBB,0xF75C3071,0xF96030C6,0xFF142266,0xFEDC1721,0xFE7C0965,0xFE64015A,0xFC000069,0xFF342BED,0xFF042108,0xFE141223,0xCA0012C9,
+0x6FFC33B3,0xBC444E,0xBC444E,0xBC444E,0xBC444E,0xFE802159,0xFE802159,0xFE802159,0xFE5C10E6,0xFE5C10E6,0xBA5C10E5,0xFE501E14,0xFE501E14,0xFE501E14,0xFE1000F9,0xFE1000F9,0xC01C0278,0xD0001142,0xD0001142,0xAC0002D5,0x8A001144,0x114444D,0x114444D,0x114444D,0xE8001B35,0xE8001B35,0xB4001241,0xBA002153,0xBA002153,0xA2000E5A,0x86001904,0xFF8444D,
+0xFF8444D,0x84002A65,0x72002D4D,0x5C00444D,0xFEA03348,0xFEAC3CB9,0xBC444E,0xFE78242D,0xFE541448,0xFE3408B9,0xFE2804E2,0xF8000050,0xFE7831F5,0xFE5021DA,0xFE001274,0xA2000E5A,0x18C444D,0x1181142,0x1181142,0x1181142,0x1181142,0xFEDC046A,0xFEDC046A,0xFEDC046A,0xE8B80001,0xE8B80001,0xBAB80001,0x1A01142,0x1A01142,0x1A01142,0xFE2C0059,0xFE2C0059,
+0xBA5C0001,0x55F81142,0x55F81142,0xAC0002D5,0x8A001144,0x1A01142,0x1A01142,0x1A01142,0xFE2C0059,0xFE2C0059,0xBA5C0001,0x55F81142,0x55F81142,0xAC0002D5,0x8A001144,0x55F81142,0x55F81142,0xAC0002D5,0x8A001144,0x8A001144,0xFEF40D9D,0xFF0C0E7A,0x1181142,0xFEDC0AFD,0xFEAC06D9,0xFE740361,0xFE64015A,0xF8000050,0xF8EC0E1D,0xFEC40AB2,0x27FC1142,0xAC0002D5,
+0x27FC1142,0x1B8090A,0xFFA40595,0xFF8801BA,0xFF740001,0x99FC0908,0xFF580369,0xFF340000,0xCDFC0908,0xFE600000,0xDC000908,0x99FC0908,0xFF580369,0xFF340000,0xCDFC0908,0xFE600000,0xDC000908,0xCDFC0908,0xFE600000,0xDC000908,0xDC000908,0x99FC0908,0xFF580369,0xFF340000,0xCDFC0908,0xFE600000,0xDC000908,0xCDFC0908,0xFE600000,0xDC000908,0xDC000908,0xCDFC0908,
+0xFE600000,0xDC000908,0xDC000908,0xDC000908,0xFBAC0841,0x1D80908,0xFFAC087D,0xFF94070A,0xFF680595,0xFF0402C2,0xFEB00000,0xFE000000,0xFF980832,0xFF8806D1,0xFEDC0051,0xDC000908,0xBFFC0908,0x5C10E5,0x5C10E5,0x5C10E5,0x5C10E5,0x5C10E5,0x5C10E5,0x5C10E5,0x5C10E5,0x5C10E5,0x5C10E5,0xFE0C003D,0xFE0C003D,0xFE0C003D,0xFE0C003D,0xFE0C003D,
+0xFE0C003D,0x8A000000,0x8A000000,0x8A000000,0x5C000000,0x8810E5,0x8810E5,0x8810E5,0x8810E5,0x8810E5,0x8810E5,0x6E000654,0x6E000654,0x6E000654,0x5200033D,0x11410E5,0x11410E5,0x11410E5,0x3E000A68,0x2E0010E5,0xFE4C0C35,0x5C10E5,0x5C10E5,0xFE3C0745,0xFE280401,0xFE180190,0xFE180190,0xE4000000,0xFE200AFA,0xFE1406B2,0xA6000074,0x6E000654,
+0xC010E5,};
+static const uint32_t g_etc1_to_bc7_m6_table242[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0xC80001,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,
+0x12C0000,0x1BF80000,0x1BF80000,0x1BF80000,0x64000000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x12C0000,0x1BF80000,0x1BF80000,0x1BF80000,0x64000000,0x1BF80000,0x1BF80000,0x1BF80000,0x64000000,0x64000000,0xD80000,0xC80001,0xC80001,0x6E80000,0xFC0000,0x3100000,0x3100000,0x1540000,0x6E80000,0xFC0000,0x1AC0000,0x1BF80000,
+0x1AC0000,0x1840001,0x1840001,0x1840001,0x1840001,0x49FC0000,0x49FC0000,0x49FC0000,0xA7F80000,0xA7F80000,0xC2000000,0x49FC0000,0x49FC0000,0x49FC0000,0xA7F80000,0xA7F80000,0xC2000000,0xA7F80000,0xA7F80000,0xC2000000,0xC2000000,0x49FC0000,0x49FC0000,0x49FC0000,0xA7F80000,0xA7F80000,0xC2000000,0xA7F80000,0xA7F80000,0xC2000000,0xC2000000,0xA7F80000,
+0xA7F80000,0xC2000000,0xC2000000,0xC2000000,0x3C40000,0x1A00000,0x1840001,0x1FFC0000,0x6DFC0000,0x8FFC0000,0x9BFC0000,0xADFC0000,0x1E80000,0x49FC0000,0x8FFC0000,0xC2000000,0x8FFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x11491E7,0xFEE86F9B,0xFECC5432,0xFEC44A4E,0xFEC45887,0xFEA0348E,0xFE8C26E5,0xFE7C247F,0xFE64141E,0xE0641AF5,0xFEB060B4,0xFE7033B5,0xFE5C2208,0xFE381939,0xFE14026D,0xE21808E4,0xFE143058,0xEC001378,0xD0000EF9,0xB6002F14,0x39891E7,0xFE4C5F3E,0xFE2C4A4E,0xFE0839ED,0xFA001E61,0xD8001EBD,0xFA004BDC,0xE20029E8,0xCC00210A,0xAE003CA5,0x51FC91E7,
+0xBE006462,0xB2005139,0x9C006279,0x880091E9,0xFEE47431,0xFF0C873F,0xFF0C8ACF,0xFEB45441,0xFE7C3299,0xFE48140A,0xFE3407A9,0xFE040045,0xFED4724F,0xFE984F5B,0xFE001494,0xCC00210A,0x23FC91E7,0x1702F13,0xFF502186,0xFF3815C2,0xFF281142,0xFF301D13,0xFF080C12,0xFEF40502,0xFEE409B1,0xFAC80035,0xE0C80709,0x29FC2F13,0xFEE41AA6,0xFEC01142,0xFE88119A,0xFE4000B9,
+0xE0500708,0x97F82F13,0xEC001378,0xD0000EF9,0xB6002F14,0x29FC2F13,0xFEE41AA6,0xFEC01142,0xFE88119A,0xFE4000B9,0xE0500708,0x97F82F13,0xEC001378,0xD0000EF9,0xB6002F14,0x97F82F13,0xEC001378,0xD0000EF9,0xB6002F14,0xB6002F14,0xFF5027BA,0xFD682BE9,0xFF6C2C5A,0xFF30200A,0xFEE8158A,0xFEA4095B,0xFE7C01D4,0xFE040041,0xFF442838,0xFF041EA8,0xFE341206,0xD0000EF9,
+0x7BFC2F13,0xC44A4E,0xC44A4E,0xC44A4E,0xC44A4E,0xFE8C26E5,0xFE8C26E5,0xFE8C26E5,0xFE64141E,0xFE64141E,0xC26413ED,0xFE5C2208,0xFE5C2208,0xFE5C2208,0xFE14026D,0xFE14026D,0xC8200364,0xDC001142,0xDC001142,0xB2000269,0x92001144,0x3244A4D,0x3244A4D,0x3244A4D,0xF4001E3D,0xF4001E3D,0xBA001509,0xC000234B,0xC000234B,0xA8000F1E,0x8C0019E8,0x17FC4A4D,
+0x17FC4A4D,0x8A002E49,0x78003095,0x62004A4D,0xFEA03908,0xF8C0430A,0xC44A4E,0xFE802964,0xFE5818D5,0xFE3C0BE6,0xFE3407A9,0xFE040045,0xFE9437CD,0xFE5C2742,0xFE001394,0xA8000F1E,0x1A44A4D,0x1281142,0x1281142,0x1281142,0x1281142,0xFEF40502,0xFEF40502,0xFEF40502,0xF0C80001,0xF0C80001,0xC2C80001,0x1B81142,0x1B81142,0x1B81142,0xFE4000B9,0xFE4000B9,
+0xC26C0001,0x61F81142,0x61F81142,0xB2000269,0x92001144,0x1B81142,0x1B81142,0x1B81142,0xFE4000B9,0xFE4000B9,0xC26C0001,0x61F81142,0x61F81142,0xB2000269,0x92001144,0x61F81142,0x61F81142,0xB2000269,0x92001144,0x92001144,0xFF100DC8,0xF9200EC9,0x1281142,0xFEDC0B8D,0xFEC0075D,0xFE7C0414,0xFE7C01D4,0xFE040041,0xFEF80E21,0xFEDC0AFD,0x37FC1142,0xB2000269,
+0x37FC1142,0x1C0070A,0xFFB0045D,0xFF940152,0xFF840001,0xA5FC0708,0xFF7002A1,0xFF4C0000,0xD3FC0708,0xFE900000,0xE0000708,0xA5FC0708,0xFF7002A1,0xFF4C0000,0xD3FC0708,0xFE900000,0xE0000708,0xD3FC0708,0xFE900000,0xE0000708,0xE0000708,0xA5FC0708,0xFF7002A1,0xFF4C0000,0xD3FC0708,0xFE900000,0xE0000708,0xD3FC0708,0xFE900000,0xE0000708,0xE0000708,0xD3FC0708,
+0xFE900000,0xE0000708,0xE0000708,0xE0000708,0xFFB40659,0x1E00708,0xF9C00692,0xFF94057A,0xFF7C045D,0xFF2C0232,0xFED80000,0xFE380000,0xFFAC065D,0xFF940550,0xFEFC0040,0xE0000708,0xC7FC0708,0x6413ED,0x6413ED,0x6413ED,0x6413ED,0x6413ED,0x6413ED,0x6413ED,0x6413ED,0x6413ED,0x6413ED,0xFE0C00CD,0xFE0C00CD,0xFE0C00CD,0xFE0C00CD,0xFE0C00CD,
+0xFE0C00CD,0x96000000,0x96000000,0x96000000,0x64000000,0x9413ED,0x9413ED,0x9413ED,0x9413ED,0x9413ED,0x9413ED,0x7A000784,0x7A000784,0x7A000784,0x580003D9,0x12C13ED,0x12C13ED,0x12C13ED,0x44000C44,0x320013ED,0xFE4C0F05,0x6413ED,0x6413ED,0xFE3C0975,0xFE3405B4,0xFE1802D0,0xFE1802D0,0xF8000000,0xFC380D75,0xFE2008D1,0xB6000089,0x7A000784,
+0xD413ED,};
+static const uint32_t g_etc1_to_bc7_m6_table243[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0xD80001,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,
+0x1440000,0x27F80000,0x27F80000,0x27F80000,0x6C000000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x1440000,0x27F80000,0x27F80000,0x27F80000,0x6C000000,0x27F80000,0x27F80000,0x27F80000,0x6C000000,0x6C000000,0xE80000,0xD80001,0xD80001,0x2FC0000,0x1100000,0x1280000,0x1280000,0x36C0000,0x2FC0000,0x1100000,0x1D00000,0x27F80000,
+0x1D00000,0x1940001,0x1940001,0x1940001,0x1940001,0x63FC0000,0x63FC0000,0x63FC0000,0xB3F80000,0xB3F80000,0xCA000000,0x63FC0000,0x63FC0000,0x63FC0000,0xB3F80000,0xB3F80000,0xCA000000,0xB3F80000,0xB3F80000,0xCA000000,0xCA000000,0x63FC0000,0x63FC0000,0x63FC0000,0xB3F80000,0xB3F80000,0xCA000000,0xB3F80000,0xB3F80000,0xCA000000,0xCA000000,0xB3F80000,
+0xB3F80000,0xCA000000,0xCA000000,0xCA000000,0x1D80000,0x1B00000,0x1940001,0x3DFC0000,0x81FC0000,0x9FF80000,0xA9F80000,0xB9F80000,0x1FC0000,0x63FC0000,0x9FF80000,0xCA000000,0x9FF80000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x11C936F,0xFEF4735F,0xFED859D2,0xFED050A2,0xFED05B93,0xFEA839C2,0xFE982CE1,0xFE88277B,0xFE7017E2,0xE46C1C7D,0xFEB061D4,0xFE7C3749,0xFE682684,0xFE381A89,0xFE200485,0xE6200834,0xFE142D78,0xF2001234,0xD6000B99,0xBC002AC8,0x3A4936F,0xFE646426,0xFE3C50A2,0xFE083CBD,0xFA0021B1,0xDE001F71,0xFA0049BC,0xE80029B8,0xCC001E9A,0xB4003921,0x57FC936F,
+0xC40066F6,0xB8005159,0xA6006174,0x8C009371,0xFEF476C5,0xFF0C88FF,0xFF0C8D0F,0xFEC45747,0xFE883642,0xFE541781,0xFE3C0ADE,0xFE0C00EC,0xFED474DF,0xFE9852EB,0xFE101676,0xCC001E9A,0x2BFC936F,0x1782ACB,0xFF5C1F2E,0xFF401523,0xFF381142,0xFF441A61,0xFF140BC6,0xFF0005AA,0xFEF00849,0xFCD80009,0xE4D80549,0x37FC2AC8,0xFEFC1946,0xFED81142,0xFEA00FDA,0xFE640121,
+0xE4640548,0x9DFC2AC8,0xF2001234,0xD6000B99,0xBC002AC8,0x37FC2AC8,0xFEFC1946,0xFED81142,0xFEA00FDA,0xFE640121,0xE4640548,0x9DFC2AC8,0xF2001234,0xD6000B99,0xBC002AC8,0x9DFC2AC8,0xF2001234,0xD6000B99,0xBC002AC8,0xBC002AC8,0xFF58247D,0xFF6C27E1,0xFF6C289A,0xFF301D7A,0xFEFC143A,0xFEB80925,0xFE900274,0xFE280088,0xFD5824CE,0xFF181C5E,0xFE5811EB,0xD6000B99,
+0x83FC2AC8,0xD050A2,0xD050A2,0xD050A2,0xD050A2,0xFE982CE1,0xFE982CE1,0xFE982CE1,0xFE7017E2,0xFE7017E2,0xCA6C1735,0xFE682684,0xFE682684,0xFE682684,0xFE200485,0xFE200485,0xD2280474,0xE6001144,0xE6001144,0xBE0001F9,0x9A001144,0x13450A2,0x13450A2,0x13450A2,0xFA0021A1,0xFA0021A1,0xC6001821,0xCC002553,0xCC002553,0xAE001012,0x92001AE4,0x1FF850A2,
+0x1FF850A2,0x90003275,0x7E00340D,0x660050A5,0xFEAC3F3D,0xFCC8492A,0xD050A2,0xFE902EFD,0xFE6C1DB1,0xFE3C0FE6,0xFE3C0ADE,0xFE0C00EC,0xFE943DAD,0xFE742C9D,0xFE101595,0xAE001012,0x1B850A2,0x1381142,0x1381142,0x1381142,0x1381142,0xFF0005AA,0xFF0005AA,0xFF0005AA,0xF8D80001,0xF8D80001,0xCAD80001,0x1D01142,0x1D01142,0x1D01142,0xFE640121,0xFE640121,
+0xCA7C0001,0x6DF81142,0x6DF81142,0xBE0001F9,0x9A001144,0x1D01142,0x1D01142,0x1D01142,0xFE640121,0xFE640121,0xCA7C0001,0x6DF81142,0x6DF81142,0xBE0001F9,0x9A001144,0x6DF81142,0x6DF81142,0xBE0001F9,0x9A001144,0x9A001144,0xFF200E1D,0xFF2C0ED5,0x1381142,0xFEF80BD1,0xFED407E9,0xFEA804A0,0xFE900274,0xFE280088,0xFD100E72,0xFEE80B5A,0x45FC1142,0xBE0001F9,
+0x45FC1142,0x1C8054A,0xFFB0034D,0xFFA000FA,0xFF940001,0xB1FC0548,0xFF7C01F9,0xFF640000,0xD9FC0548,0xFEC00000,0xE4000548,0xB1FC0548,0xFF7C01F9,0xFF640000,0xD9FC0548,0xFEC00000,0xE4000548,0xD9FC0548,0xFEC00000,0xE4000548,0xE4000548,0xB1FC0548,0xFF7C01F9,0xFF640000,0xD9FC0548,0xFEC00000,0xE4000548,0xD9FC0548,0xFEC00000,0xE4000548,0xE4000548,0xD9FC0548,
+0xFEC00000,0xE4000548,0xE4000548,0xE4000548,0xFFB404D9,0x1E80548,0xFDC804E2,0xFFB00422,0xFF7C034D,0xFF480195,0xFEFC0000,0xFE740000,0xF5C004E2,0xFFA00401,0xFF200031,0xE4000548,0xCFFC0548,0x6C1735,0x6C1735,0x6C1735,0x6C1735,0x6C1735,0x6C1735,0x6C1735,0x6C1735,0x6C1735,0x6C1735,0xFE1801B1,0xFE1801B1,0xFE1801B1,0xFE1801B1,0xFE1801B1,
+0xFE1801B1,0xA0000001,0xA0000001,0xA0000001,0x6C000000,0xA01735,0xA01735,0xA01735,0xA01735,0xA01735,0xA01735,0x800008C8,0x800008C8,0x800008C8,0x62000464,0x1441735,0x1441735,0x1441735,0x4A000E48,0x36001735,0xF8601200,0x6C1735,0x6C1735,0xFE4C0BE4,0xFE3407B4,0xFE240454,0xFE240454,0xFE040014,0xFE3C1031,0xFC300B48,0xC6000099,0x800008C8,
+0xE41735,};
+static const uint32_t g_etc1_to_bc7_m6_table244[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0xEC0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,
+0x35C0000,0x33FC0000,0x33FC0000,0x33FC0000,0x74000001,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x35C0000,0x33FC0000,0x33FC0000,0x33FC0000,0x74000001,0x33FC0000,0x33FC0000,0x33FC0000,0x74000001,0x74000001,0xFC0000,0xEC0000,0xEC0000,0x5100000,0x1280000,0x1400000,0x1400000,0x18C0000,0x5100000,0x1280000,0x1F40000,0x33FC0000,
+0x1F40000,0x1A80000,0x1A80000,0x1A80000,0x1A80000,0x7DFC0000,0x7DFC0000,0x7DFC0000,0xBFFC0000,0xBFFC0000,0xD2000001,0x7DFC0000,0x7DFC0000,0x7DFC0000,0xBFFC0000,0xBFFC0000,0xD2000001,0xBFFC0000,0xBFFC0000,0xD2000001,0xD2000001,0x7DFC0000,0x7DFC0000,0x7DFC0000,0xBFFC0000,0xBFFC0000,0xD2000001,0xBFFC0000,0xBFFC0000,0xD2000001,0xD2000001,0xBFFC0000,
+0xBFFC0000,0xD2000001,0xD2000001,0xD2000001,0x1EC0000,0x1C40000,0x1A80000,0x5FFC0000,0x97FC0000,0xAFFC0000,0xB7FC0000,0xC5F80000,0x2DFC0000,0x7DFC0000,0xAFFC0000,0xD2000001,0xAFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x12495C1,0xFF00782D,0xFEE4609C,0xFEDC5828,0xFEDC5FA9,0xFEB44028,0xFEA43425,0xFE942B8D,0xFE7C1CD4,0xE8741ED1,0xFEC46399,0xFE8C3BF7,0xFE742C2E,0xFE4C1CB6,0xFE2C07B5,0xEE2407F6,0xFE202B26,0xF800116E,0xDC000859,0xC200265A,0x3B095C1,0xFE706A14,0xFE4C582B,0xFE14410D,0xFC00269A,0xE20020E5,0xFA00488A,0xEE002A26,0xD2001C6A,0xBA0035A3,0x5DFC95C1,
+0xCA006AA4,0xBE00521D,0xA600608A,0x920095C3,0xFF007A21,0xFF0C8C29,0xF9208FF4,0xFED45B79,0xFE903AF9,0xFE5C1BF9,0xFE4C0F71,0xFE140288,0xFEF07883,0xFEB0571E,0xFE141976,0xD2001C6A,0x33FC95C1,0x184265D,0xFF681CC8,0xFF58147D,0xFF481144,0xFF5017C9,0xFF2C0B94,0xFF180668,0xFF08070D,0xFEEC0004,0xE8EC039D,0x49FC265A,0xFF1417D8,0xFEF01144,0xFEB80E36,0xFE8801BD,
+0xE87C039D,0xA7F8265A,0xF800116E,0xDC000859,0xC200265A,0x49FC265A,0xFF1417D8,0xFEF01144,0xFEB80E36,0xFE8801BD,0xE87C039D,0xA7F8265A,0xF800116E,0xDC000859,0xC200265A,0xA7F8265A,0xF800116E,0xDC000859,0xC200265A,0xC200265A,0xFF742111,0xF98023FD,0xFB842485,0xFF401AEA,0xFF1012F4,0xFEC80956,0xFEA8031D,0xFE480112,0xFF5C2106,0xFF401A06,0xFE7C11D2,0xDC000859,
+0x8FFC265A,0xDC5828,0xDC5828,0xDC5828,0xDC5828,0xFEA43425,0xFEA43425,0xFEA43425,0xFE7C1CD4,0xFE7C1CD4,0xD2741B35,0xFE742C2E,0xFE742C2E,0xFE742C2E,0xFE2C07B5,0xFE2C07B5,0xDE2805CA,0xF4001142,0xF4001142,0xCA000195,0xA4001142,0x3445828,0x3445828,0x3445828,0xFA00268D,0xFA00268D,0xCC001BE3,0xD80027C5,0xD80027C5,0xBA00113A,0x9E001C1A,0x27FC5828,
+0x27FC5828,0x96003783,0x84003833,0x6C00582B,0xFEBC4689,0xFECC50B4,0xDC5828,0xFE9835F1,0xFE6C2405,0xFE5414FE,0xFE4C0F71,0xFE140288,0xFEA04502,0xFE7433A5,0xFE141895,0xBA00113A,0x1D45828,0x1481144,0x1481144,0x1481144,0x1481144,0xFF180668,0xFF180668,0xFF180668,0xFEEC0004,0xFEEC0004,0xD2EC0001,0x3E81142,0x3E81142,0x3E81142,0xFE8801BD,0xFE8801BD,
+0xD2900001,0x79FC1142,0x79FC1142,0xCA000195,0xA4001142,0x3E81142,0x3E81142,0x3E81142,0xFE8801BD,0xFE8801BD,0xD2900001,0x79FC1142,0x79FC1142,0xCA000195,0xA4001142,0x79FC1142,0x79FC1142,0xCA000195,0xA4001142,0xA4001142,0xFB340E74,0xFB440F20,0x1481144,0xFF180C35,0xFEF008A2,0xFEB80562,0xFEA8031D,0xFE480112,0xF9280EC9,0xFF040BEA,0x57FC1142,0xCA000195,
+0x57FC1142,0x1D4039D,0xFFC4022D,0xFFAC00AD,0xFFA80000,0xBDFC039D,0xFF940152,0xFF7C0001,0xDFF8039D,0xFEF80000,0xE800039D,0xBDFC039D,0xFF940152,0xFF7C0001,0xDFF8039D,0xFEF80000,0xE800039D,0xDFF8039D,0xFEF80000,0xE800039D,0xE800039D,0xBDFC039D,0xFF940152,0xFF7C0001,0xDFF8039D,0xFEF80000,0xE800039D,0xDFF8039D,0xFEF80000,0xE800039D,0xE800039D,0xDFF8039D,
+0xFEF80000,0xE800039D,0xE800039D,0xE800039D,0xFDCC0349,0x1F0039D,0xFFCC0355,0xFDBC02D4,0xFFA80242,0xFF5C0119,0xFF280000,0xFEB80000,0xF7CC0349,0xFFAC02C5,0xFF50001D,0xE800039D,0xD7FC039D,0x741B34,0x741B34,0x741B34,0x741B34,0x741B34,0x741B34,0x741B34,0x741B34,0x741B34,0x741B34,0xFE240328,0xFE240328,0xFE240328,0xFE240328,0xFE240328,
+0xFE240328,0xAE000000,0xAE000000,0xAE000000,0x74000001,0xB01B32,0xB01B32,0xB01B32,0xB01B32,0xB01B32,0xB01B32,0x8C000A55,0x8C000A55,0x8C000A55,0x6800052D,0x1641B32,0x1641B32,0x1641B32,0x500010BD,0x3A001B32,0xFC681589,0x741B34,0x741B34,0xFE4C0F05,0xFE3C0A68,0xFE340665,0xFE340665,0xFE0C009D,0xFE3C13D0,0xFE340E29,0xD60000B9,0x8C000A55,
+0xF81B32,};
+static const uint32_t g_etc1_to_bc7_m6_table245[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0xFC0000,0x3740000,0x3740000,0x3740000,0x3740000,0x3740000,
+0x3740000,0x3FFC0000,0x3FFC0000,0x3FFC0000,0x7C000001,0x3740000,0x3740000,0x3740000,0x3740000,0x3740000,0x3740000,0x3FFC0000,0x3FFC0000,0x3FFC0000,0x7C000001,0x3FFC0000,0x3FFC0000,0x3FFC0000,0x7C000001,0x7C000001,0x10C0000,0xFC0000,0xFC0000,0x1240000,0x13C0000,0x3540000,0x3540000,0x1A80000,0x1240000,0x13C0000,0xDFC0000,0x3FFC0000,
+0xDFC0000,0x1B80000,0x1B80000,0x1B80000,0x1B80000,0x95FC0000,0x95FC0000,0x95FC0000,0xCBFC0000,0xCBFC0000,0xDA000001,0x95FC0000,0x95FC0000,0x95FC0000,0xCBFC0000,0xCBFC0000,0xDA000001,0xCBFC0000,0xCBFC0000,0xDA000001,0xDA000001,0x95FC0000,0x95FC0000,0x95FC0000,0xCBFC0000,0xCBFC0000,0xDA000001,0xCBFC0000,0xCBFC0000,0xDA000001,0xDA000001,0xCBFC0000,
+0xCBFC0000,0xDA000001,0xDA000001,0xDA000001,0x9FC0000,0x3D40000,0x1B80000,0x7DFC0000,0xABFC0000,0xBFF80000,0xC5FC0000,0xD1F40000,0x55FC0000,0x95FC0000,0xBFF80000,0xDA000001,0xBFF80000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x12C9859,0xFF0C7CE9,0xFEF06704,0xFEE85F34,0xFEE863E1,0xFEC44648,0xFEB03B0D,0xFE942FCD,0xFE8821D8,0xEC7C2169,0xFEC465F9,0xFE9840B3,0xFE8031CA,0xFE581F56,0xFE380B41,0xF22C0846,0xFE2C29FE,0xFE041148,0xE6000602,0xC80022C6,0x3BC9859,0xFE7C6FCC,0xFE5C5F33,0xFE204581,0xFE082BC5,0xE80022E1,0xFE044866,0xEE002B26,0xD8001AEE,0xC00032E7,0x63FC9859,
+0xD0006E98,0xBE00534D,0xAC006016,0x9600985B,0xFF007DA1,0xFB248F01,0xFD2892C4,0xFED45F89,0xFEA03FAE,0xFE6820C1,0xFE501419,0xFE2004B9,0xFEF87BA9,0xFEC45BAD,0xFE201CEC,0xD8001AEE,0x3BFC9859,0x19022C5,0xFF741AD8,0xFF6413E5,0xFF581144,0xFF5C15CD,0xFF380B84,0xFF300728,0xFF14063D,0xFEFC0031,0xECFC0265,0x59FC22C5,0xFF2016B4,0xFF081144,0xFED80D2D,0xFEA0025D,
+0xEC900265,0xADFC22C5,0xFE081142,0xE6000602,0xC80022C6,0x59FC22C5,0xFF2016B4,0xFF081144,0xFED80D2D,0xFEA0025D,0xEC900265,0xADFC22C5,0xFE081142,0xE6000602,0xC80022C6,0xADFC22C5,0xFE081142,0xE6000602,0xC80022C6,0xC80022C6,0xFF781E0E,0xFF8C207D,0xFF8C211D,0xFF5C18D9,0xFF2411F8,0xFEEC0969,0xFED003E8,0xFE64019A,0xFD741E52,0xFF4817E4,0xFEA011BB,0xE6000602,
+0x99FC22C5,0xE85F34,0xE85F34,0xE85F34,0xE85F34,0xFEB03B0D,0xFEB03B0D,0xFEB03B0D,0xFE8821D8,0xFE8821D8,0xDA7C1F05,0xFE8031CA,0xFE8031CA,0xFE8031CA,0xFE380B41,0xFE380B41,0xE62C0726,0xFE041148,0xFE041148,0xD000013D,0xAC001142,0x1545F33,0x1545F33,0x1545F33,0xFE082BC5,0xFE082BC5,0xD8001F8B,0xE20029C6,0xE20029C6,0xC000126A,0xA2001D03,0x2FFC5F33,
+0x2FFC5F33,0x9C003C4B,0x8A003C13,0x72005F33,0xFECC4D68,0xF8E0580D,0xE85F34,0xFEAC3CD5,0xFE8029D5,0xFE5C1A05,0xFE501419,0xFE2004B9,0xFEB44BB9,0xFE903A4A,0xFE201C0B,0xC000126A,0x1E85F33,0x1581144,0x1581144,0x1581144,0x1581144,0xFF300728,0xFF300728,0xFF300728,0xFEFC0031,0xFEFC0031,0xDAFC0001,0x7FC1142,0x7FC1142,0x7FC1142,0xFEA0025D,0xFEA0025D,
+0xDAA00001,0x85FC1142,0x85FC1142,0xD000013D,0xAC001142,0x7FC1142,0x7FC1142,0x7FC1142,0xFEA0025D,0xFEA0025D,0xDAA00001,0x85FC1142,0x85FC1142,0xD000013D,0xAC001142,0x85FC1142,0x85FC1142,0xD000013D,0xAC001142,0xAC001142,0xFF3C0EA4,0xFF4C0F40,0x1581144,0xFF240CB2,0xFF04093A,0xFEE40632,0xFED003E8,0xFE64019A,0xFF340ECD,0xFF180C3D,0x65FC1142,0xD000013D,
+0x65FC1142,0x1DC0265,0xFFD00171,0xFFC00074,0xFFB80000,0xC9FC0265,0xFFAC00DA,0xFF940001,0xE5F80265,0xFF280000,0xEC000265,0xC9FC0265,0xFFAC00DA,0xFF940001,0xE5F80265,0xFF280000,0xEC000265,0xE5F80265,0xFF280000,0xEC000265,0xEC000265,0xC9FC0265,0xFFAC00DA,0xFF940001,0xE5F80265,0xFF280000,0xEC000265,0xE5F80265,0xFF280000,0xEC000265,0xEC000265,0xE5F80265,
+0xFF280000,0xEC000265,0xEC000265,0xEC000265,0xFFD00225,0x1FC0265,0xF5D80244,0xFFC001D4,0xFFA80172,0xFF8400B4,0xFF500000,0xFEF40000,0xFBD40221,0xFFC001C4,0xFF700014,0xEC000265,0xDFF80265,0x7C1F04,0x7C1F04,0x7C1F04,0x7C1F04,0x7C1F04,0x7C1F04,0x7C1F04,0x7C1F04,0x7C1F04,0x7C1F04,0xFE2404C8,0xFE2404C8,0xFE2404C8,0xFE2404C8,0xFE2404C8,
+0xFE2404C8,0xBA000000,0xBA000000,0xBA000000,0x7C000001,0xBC1F02,0xBC1F02,0xBC1F02,0xBC1F02,0xBC1F02,0xBC1F02,0x98000BD5,0x98000BD5,0x98000BD5,0x6E0005F1,0x17C1F02,0x17C1F02,0x17C1F02,0x56001315,0x3E001F02,0xFE6C18FD,0x7C1F04,0x7C1F04,0xFE581220,0xFE500D24,0xFE3C0894,0xFE3C0894,0xFE140164,0xFC541735,0xFE341139,0xE60000CD,0x98000BD5,
+0x10C1F02,};
+static const uint32_t g_etc1_to_bc7_m6_table246[] = {
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x10C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,
+0x38C0000,0x4BFC0000,0x4BFC0000,0x4BFC0000,0x84000001,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x38C0000,0x4BFC0000,0x4BFC0000,0x4BFC0000,0x84000001,0x4BFC0000,0x4BFC0000,0x4BFC0000,0x84000001,0x84000001,0x71C0000,0x10C0000,0x10C0000,0x1380000,0x1500000,0x16C0000,0x16C0000,0x3C00000,0x1380000,0x1500000,0x1DF80000,0x4BFC0000,
+0x1DF80000,0x1C80000,0x1C80000,0x1C80000,0x1C80000,0xAFFC0000,0xAFFC0000,0xAFFC0000,0xD7FC0000,0xD7FC0000,0xE2000001,0xAFFC0000,0xAFFC0000,0xAFFC0000,0xD7FC0000,0xD7FC0000,0xE2000001,0xD7FC0000,0xD7FC0000,0xE2000001,0xE2000001,0xAFFC0000,0xAFFC0000,0xAFFC0000,0xD7FC0000,0xD7FC0000,0xE2000001,0xD7FC0000,0xD7FC0000,0xE2000001,0xE2000001,0xD7FC0000,
+0xD7FC0000,0xE2000001,0xE2000001,0xE2000001,0x43FC0000,0xBE40000,0x1C80000,0x9BFC0000,0xBDFC0000,0xCDFC0000,0xD3F80000,0xDBF80000,0x7DFC0000,0xAFFC0000,0xCDFC0000,0xE2000001,0xCDFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1349B71,0xFF18821D,0xFEFC6DCC,0xFEF06694,0xFEE868A1,0xFEC84CE6,0xFEC44258,0xFEA03499,0xFE942774,0xF0842481,0xFED0690D,0xFE9845F3,0xFE8C37EE,0xFE6422AE,0xFE400F8D,0xF6340916,0xFE3829B6,0xFE0811D2,0xEA000401,0xCC001F86,0x1C89B71,0xFE8875EC,0xFE706693,0xFE2C4A85,0xFE0831B5,0xEE00257D,0xFE0848EA,0xF4002CA6,0xE20019DE,0xC600308B,0x69FC9B71,
+0xD6007334,0xC40054F9,0xB200601A,0x9A009B73,0xFF0C818D,0xFF2C9219,0xFF2C962C,0xFED46499,0xFEA84503,0xFE7025F5,0xFE5C1968,0xFE2807C2,0xFEF87F79,0xFED06046,0xFE3020B2,0xE20019DE,0x41FC9B71,0x19C1F85,0xFF801918,0xFF701365,0xFF681144,0xFF681419,0xFF4C0B8A,0xFF4407D9,0xFF2C05B5,0xFF140089,0xF10C016D,0x6BFC1F85,0xFF3815A4,0xFF201144,0xFEF00C35,0xFEB8031D,
+0xF0A4016D,0xB7F81F85,0xFE381142,0xEA000401,0xCC001F86,0x6BFC1F85,0xFF3815A4,0xFF201144,0xFEF00C35,0xFEB8031D,0xF0A4016D,0xB7F81F85,0xFE381142,0xEA000401,0xCC001F86,0xB7F81F85,0xFE381142,0xEA000401,0xCC001F86,0xCC001F86,0xFF801BA1,0xFF8C1D9D,0xF5981E64,0xFF5C1729,0xFF401123,0xFEFC0989,0xFEE404A5,0xFE8C025D,0xFF781B86,0xFF5C1652,0xFED011A5,0xEA000401,
+0xA3FC1F85,0xF06694,0xF06694,0xF06694,0xF06694,0xFEC44258,0xFEC44258,0xFEC44258,0xFE942774,0xFE942774,0xE2842315,0xFE8C37EE,0xFE8C37EE,0xFE8C37EE,0xFE400F8D,0xFE400F8D,0xF03408A6,0xFE0811D2,0xFE0811D2,0xDC0000F5,0xB4001142,0x1686693,0x1686693,0x1686693,0xFE0831B5,0xFE0831B5,0xDE002373,0xEE002C26,0xEE002C26,0xCC0013AA,0xA8001E33,0x39F86693,
+0x39F86693,0xA600416D,0x90004023,0x78006693,0xFECC54C8,0xFEEC5F3D,0xF06694,0xFEB443E1,0xFE943075,0xFE681FB0,0xFE5C1968,0xFE2807C2,0xFEB45309,0xFE98413E,0xFE301FEE,0xCC0013AA,0x3FC6693,0x1681144,0x1681144,0x1681144,0x1681144,0xFF4407D9,0xFF4407D9,0xFF4407D9,0xFF140089,0xFF140089,0xE30C0001,0x1FFC1142,0x1FFC1142,0x1FFC1142,0xFEB8031D,0xFEB8031D,
+0xE2B00001,0x91FC1142,0x91FC1142,0xDC0000F5,0xB4001142,0x1FFC1142,0x1FFC1142,0x1FFC1142,0xFEB8031D,0xFEB8031D,0xE2B00001,0x91FC1142,0x91FC1142,0xDC0000F5,0xB4001142,0x91FC1142,0x91FC1142,0xDC0000F5,0xB4001142,0xB4001142,0xFF580EC9,0xFB640F79,0x1681144,0xFF440D22,0xFF1809DA,0xFEF406DA,0xFEE404A5,0xFE8C025D,0xFD4C0F20,0xFF240CC8,0x75FC1142,0xDC0000F5,
+0x75FC1142,0x1E4016D,0xFFDC00DD,0xFFCC0044,0xFFC80000,0xD5FC016D,0xFFB80082,0xFFAC0001,0xEBF8016D,0xFF580000,0xF000016D,0xD5FC016D,0xFFB80082,0xFFAC0001,0xEBF8016D,0xFF580000,0xF000016D,0xEBF8016D,0xFF580000,0xF000016D,0xF000016D,0xD5FC016D,0xFFB80082,0xFFAC0001,0xEBF8016D,0xFF580000,0xF000016D,0xEBF8016D,0xFF580000,0xF000016D,0xF000016D,0xEBF8016D,
+0xFF580000,0xF000016D,0xF000016D,0xF000016D,0xF9E00152,0x27FC016D,0xF9E00154,0xFFD40120,0xFFBC00DA,0xFF98006D,0xFF780000,0xFF300000,0xFFDC0139,0xFFCC010D,0xFF90000A,0xF000016D,0xE5FC016D,0x842314,0x842314,0x842314,0x842314,0x842314,0x842314,0x842314,0x842314,0x842314,0x842314,0xFE3006C4,0xFE3006C4,0xFE3006C4,0xFE3006C4,0xFE3006C4,
+0xFE3006C4,0xC6000000,0xC6000000,0xC6000000,0x84000001,0x2C42312,0x2C42312,0x2C42312,0x2C42312,0x2C42312,0x2C42312,0xA2000D39,0xA2000D39,0xA2000D39,0x7A0006B9,0x1942312,0x1942312,0x1942312,0x5C001595,0x42002312,0xFE6C1CED,0x842314,0x842314,0xFE681589,0xFE501004,0xFE3C0B14,0xFE3C0B14,0xFE1802A1,0xFE581AC1,0xFE3C14B4,0xF60000EA,0xA2000D39,
+0x11C2312,};
+static const uint32_t g_etc1_to_bc7_m6_table247[] = {
+0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x100000,0x200000,
+0x200000,0x200000,0x200000,0x4000001,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0xC0000,0x100000,0x180000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x11C0000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,
+0x3A40000,0x57FC0000,0x57FC0000,0x57FC0000,0x8C000001,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x3A40000,0x57FC0000,0x57FC0000,0x57FC0000,0x8C000001,0x57FC0000,0x57FC0000,0x57FC0000,0x8C000001,0x8C000001,0xF2C0000,0x11C0000,0x11C0000,0x5480000,0x1640000,0x3800000,0x3800000,0x1DC0000,0x5480000,0x1640000,0x2BFC0000,0x57FC0000,
+0x2BFC0000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0xC7FC0000,0xC7FC0000,0xC7FC0000,0xE3FC0000,0xE3FC0000,0xEA000001,0xC7FC0000,0xC7FC0000,0xC7FC0000,0xE3FC0000,0xE3FC0000,0xEA000001,0xE3FC0000,0xE3FC0000,0xEA000001,0xEA000001,0xC7FC0000,0xC7FC0000,0xC7FC0000,0xE3FC0000,0xE3FC0000,0xEA000001,0xE3FC0000,0xE3FC0000,0xEA000001,0xEA000001,0xE3FC0000,
+0xE3FC0000,0xEA000001,0xEA000001,0xEA000001,0x7BFC0000,0x1F80000,0x1D80000,0xB9FC0000,0xD1FC0000,0xDDF80000,0xDFFC0000,0xE5FC0000,0xA3FC0000,0xC7FC0000,0xDDF80000,0xEA000001,0xDDF80000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x14097B9,0xFF248115,0xFF086EE8,0xFF006878,0xFF006825,0xFEDC4F04,0xFED0456C,0xFEAC3621,0xFEA02A0C,0xF49424D5,0xFEDC67C5,0xFEB047DF,0xFE983B2E,0xFE702442,0xFE5812B1,0xFA3C0922,0xFE38290A,0xFE2012C6,0xEE040282,0xD20C1C9A,0x1DC97B9,0xFEA0761C,0xFE846878,0xFE384B75,0xFE1434A9,0xF400251D,0xFE084686,0xFA002B02,0xE20015EA,0xCC002B8F,0x73F897B9,
+0xDC0071AC,0xCA0050F9,0xB8005AEA,0x9E0097BB,0xFF207F85,0xFF2C8F25,0xF73C935D,0xFEF064CD,0xFEB446BE,0xFE7C292B,0xFE681CD5,0xFE400A4D,0xFF107DEB,0xFED0602E,0xFE3C238C,0xE20015EA,0x4DFC97B9,0x1A41C9D,0xFF8C1788,0xFF7C12FD,0xFF781144,0xFF7412AD,0xFF5C0BA2,0xFF500895,0xFF38056D,0xFF2C0121,0xF51C00B5,0x7BFC1C9A,0xFF4C14D3,0xFF381144,0xFF080B7D,0xFED8040D,
+0xF4B800B5,0xBFF81C9A,0xFE6C1142,0xEC000266,0xD2001C9A,0x7BFC1C9A,0xFF4C14D3,0xFF381144,0xFF080B7D,0xFED8040D,0xF4B800B5,0xBFF81C9A,0xFE6C1142,0xEC000266,0xD2001C9A,0xBFF81C9A,0xFE6C1142,0xEC000266,0xD2001C9A,0xD2001C9A,0xFF901929,0xF9A01B05,0xFBA41B98,0xFF781595,0xFF481062,0xFF200A13,0xFEFC0585,0xFEA8031D,0xFF88194D,0xFF6814FA,0xFEE41193,0xEC000266,
+0xADFC1C9A,0x1006878,0x1006878,0x1006878,0x1006878,0xFED0456C,0xFED0456C,0xFED0456C,0xFEA02A0C,0xFEA02A0C,0xEA942421,0xFE983B2E,0xFE983B2E,0xFE983B2E,0xFE5812B1,0xFE5812B1,0xF640090E,0xFE2012C6,0xFE2012C6,0xE20400DA,0xBC0C1142,0x17C6878,0x17C6878,0x17C6878,0xFE1434A9,0xFE1434A9,0xE8002431,0xFA002AF2,0xFA002AF2,0xD20011F2,0xB4001CBB,0x43F86878,
+0x43F86878,0xB2004159,0x9C003F8B,0x7E00687B,0xFEE85775,0xFEEC61A9,0x1006878,0xFEC446F4,0xFE943411,0xFE782328,0xFE681CD5,0xFE400A4D,0xFED055B3,0xFEB04469,0xFE3C22C8,0xD20011F2,0x11FC6878,0x1781144,0x1781144,0x1781144,0x1781144,0xFF500895,0xFF500895,0xFF500895,0xFF2C0121,0xFF2C0121,0xEB1C0001,0x37FC1142,0x37FC1142,0x37FC1142,0xFED8040D,0xFED8040D,
+0xEAC00001,0x9DFC1142,0x9DFC1142,0xE40000C1,0xBC001142,0x37FC1142,0x37FC1142,0x37FC1142,0xFED8040D,0xFED8040D,0xEAC00001,0x9DFC1142,0x9DFC1142,0xE40000C1,0xBC001142,0x9DFC1142,0x9DFC1142,0xE40000C1,0xBC001142,0xBC001142,0xFB6C0F20,0xFF6C0FA1,0x1781144,0xFD580D75,0xFF2C0A82,0xFEFC07D5,0xFEFC0585,0xFEA8031D,0xFF500F68,0xFF480D24,0x83FC1142,0xE40000C1,
+0x83FC1142,0x1EC00B5,0xFFE80071,0xFFD80024,0xFFD80000,0xE3FC00B5,0xFFCC0044,0xFFC40000,0xF1F800B5,0xFF880000,0xF40000B5,0xE3FC00B5,0xFFCC0044,0xFFC40000,0xF1F800B5,0xFF880000,0xF40000B5,0xF1F800B5,0xFF880000,0xF40000B5,0xF40000B5,0xE3FC00B5,0xFFCC0044,0xFFC40000,0xF1F800B5,0xFF880000,0xF40000B5,0xF1F800B5,0xFF880000,0xF40000B5,0xF40000B5,0xF1F800B5,
+0xFF880000,0xF40000B5,0xF40000B5,0xF40000B5,0xFDE800A2,0x67FC00B5,0xFDE800A4,0xFBE40091,0xFFD0006A,0xFFC00034,0xFFA00000,0xFF6C0000,0xFBE800A2,0xFFD80088,0xFFB00005,0xF40000B5,0xEDFC00B5,0x942420,0x942420,0x942420,0x942420,0x942420,0x942420,0x942420,0x942420,0x942420,0x942420,0xFE4407D9,0xFE4407D9,0xFE4407D9,0xFE4407D9,0xFE4407D9,
+0xFE4407D9,0xD00C0000,0xD00C0000,0xD00C0000,0x8C0C0001,0xDC2420,0xDC2420,0xDC2420,0xDC2420,0xDC2420,0xDC2420,0xAE000C69,0xAE000C69,0xAE000C69,0x800005B9,0x1BC2420,0x1BC2420,0x1BC2420,0x66001572,0x48002422,0xFC881E08,0x942420,0x942420,0xFE6816CD,0xFE641154,0xFE4C0C44,0xFE4C0C44,0xFE2C0371,0xFA6C1C20,0xFE5015C5,0xFE000095,0xAE000C69,
+0x1382420,};
+static const uint32_t g_etc1_to_bc7_m6_table248[] = {
+0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x2C0000,0x580000,
+0x580000,0x580000,0x580000,0xE000000,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x1C0001,0x200000,0x200000,0x200000,0x2C0000,0x3C0000,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x12C0001,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,
+0x1C00000,0x65F80000,0x65F80000,0x65F80000,0x96000000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x1C00000,0x65F80000,0x65F80000,0x65F80000,0x96000000,0x65F80000,0x65F80000,0x65F80000,0x96000000,0x96000000,0x9400000,0x12C0001,0x12C0001,0x1600000,0x5780000,0x3980000,0x3980000,0x1FC0000,0x1600000,0x5780000,0x3DF80000,0x65F80000,
+0x3DF80000,0x1E80001,0x1E80001,0x1E80001,0x1E80001,0xE3FC0000,0xE3FC0000,0xE3FC0000,0xF1F80000,0xF1F80000,0xF4000000,0xE3FC0000,0xE3FC0000,0xE3FC0000,0xF1F80000,0xF1F80000,0xF4000000,0xF1F80000,0xF1F80000,0xF4000000,0xF4000000,0xE3FC0000,0xE3FC0000,0xE3FC0000,0xF1F80000,0xF1F80000,0xF4000000,0xF1F80000,0xF1F80000,0xF4000000,0xF4000000,0xF1F80000,
+0xF1F80000,0xF4000000,0xF4000000,0xF4000000,0xBBFC0000,0x67FC0000,0x1E80001,0xDBFC0000,0xE7FC0000,0xEDFC0000,0xEFFC0000,0xF3F40000,0xD1FC0000,0xE3FC0000,0xEDFC0000,0xF4000000,0xEDFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x14C9144,0xFF307DB4,0xFF206E1B,0xFF10687B,0xFF0C65C4,0xFEE84FCF,0xFEDC4763,0xFEC036E6,0xFEB82BFB,0xF8A42456,0xFEF464EC,0xFEC448BB,0xFEB03DB5,0xFE88258F,0xFE7015E6,0xFE500915,0xFE582844,0xFE38142D,0xF4100195,0xD81C19B9,0x1EC9144,0xFEB87431,0xFEA06878,0xFE584B5A,0xFE2C36E6,0xF8042454,0xFE084419,0xFA00296D,0xEE001109,0xD2002588,0x7BFC9144,
+0xE0006E48,0xD0004AD6,0xBE005385,0xA6009144,0xFF207B7A,0xFD488994,0xFD488D3C,0xFF0062DC,0xFECC477A,0xFE982BD6,0xFE902035,0xFE580D46,0xFF1079CE,0xFEDC5F8A,0xFE582697,0xEE001109,0x59FC9144,0x1B019BB,0xFFA415E6,0xFF941283,0xFF8C1142,0xFF8C1155,0xFF740BEA,0xFF680989,0xFF4C0593,0xFF3801FD,0xF92C0035,0x8DFC19B8,0xFF6413E5,0xFF541142,0xFF200AFD,0xFEFC0521,
+0xFACC0034,0xC7FC19B8,0xFEA01142,0xF2000124,0xD80019B8,0x8DFC19B8,0xFF6413E5,0xFF541142,0xFF200AFD,0xFEFC0521,0xFACC0034,0xC7FC19B8,0xFEA01142,0xF2000124,0xD80019B8,0xC7FC19B8,0xFEA01142,0xF2000124,0xD80019B8,0xD80019B8,0xFFA016ED,0xFFAC1835,0xFFAC18E6,0xFF881403,0xFF5C0FD6,0xFF380A61,0xFF2006AD,0xFED00448,0xFF941715,0xFF841392,0xFF101175,0xF2000124,
+0xB9FC19B8,0x110687B,0x110687B,0x110687B,0x110687B,0xFEDC4763,0xFEDC4763,0xFEDC4763,0xFEB82BFB,0xFEB82BFB,0xF4A42422,0xFEB03DB5,0xFEB03DB5,0xFEB03DB5,0xFE7015E6,0xFE7015E6,0xFE500915,0xFE38142D,0xFE38142D,0xEC1800D9,0xC41C1145,0x1986878,0x1986878,0x1986878,0xFE2C36E6,0xFE2C36E6,0xF4082420,0xFA00295D,0xFA00295D,0xE2000EE1,0xC0001A74,0x51F86878,
+0x51F86878,0xB8003F52,0xA6003D85,0x88006878,0xFEF458B2,0xFF0C61E3,0x110687B,0xFED448E2,0xFEB0370B,0xFE9026C5,0xFE902035,0xFE580D46,0xFED85741,0xFEBC46B5,0xFE5825EE,0xE2000EE1,0x21FC6878,0x18C1142,0x18C1142,0x18C1142,0x18C1142,0xFF680989,0xFF680989,0xFF680989,0xFF3801FD,0xFF3801FD,0xF52C0001,0x53FC1142,0x53FC1142,0x53FC1142,0xFEFC0521,0xFEFC0521,
+0xF4D00001,0xABF81142,0xABF81142,0xEC000080,0xC4001144,0x53FC1142,0x53FC1142,0x53FC1142,0xFEFC0521,0xFEFC0521,0xF4D00001,0xABF81142,0xABF81142,0xEC000080,0xC4001144,0xABF81142,0xABF81142,0xEC000080,0xC4001144,0xC4001144,0xFF740F52,0xFD880FD2,0x18C1142,0xFF5C0DE5,0xFF540B50,0xFF2808B1,0xFF2006AD,0xFED00448,0xFD740F79,0xFF5C0D81,0x95FC1142,0xEC000080,
+0x95FC1142,0x1F40032,0xFDF00022,0xFFEC000A,0xFFE80001,0xF1FC0032,0xFFE40011,0xFFE00000,0xF9F80032,0xFFC00000,0xF8000034,0xF1FC0032,0xFFE40011,0xFFE00000,0xF9F80032,0xFFC00000,0xF8000034,0xF9F80032,0xFFC00000,0xF8000034,0xF8000034,0xF1FC0032,0xFFE40011,0xFFE00000,0xF9F80032,0xFFC00000,0xF8000034,0xF9F80032,0xFFC00000,0xF8000034,0xF8000034,0xF9F80032,
+0xFFC00000,0xF8000034,0xF8000034,0xF8000034,0xFDF40029,0xB7FC0032,0xF3F40032,0xFFEC0022,0xFFE80019,0xFFDC000D,0xFFCC0000,0xFFB00000,0xFFF00029,0xFFEC0029,0xFFD40001,0xF8000034,0xF7FC0032,0xA42422,0xA42422,0xA42422,0xA42422,0xA42422,0xA42422,0xA42422,0xA42422,0xA42422,0xA42422,0xFE5008B1,0xFE5008B1,0xFE5008B1,0xFE5008B1,0xFE5008B1,
+0xFE5008B1,0xD8200001,0xD8200001,0xD8200001,0x961C0001,0x2F42420,0x2F42420,0x2F42420,0x2F42420,0x2F42420,0x2F42420,0xBA000AB5,0xBA000AB5,0xBA000AB5,0x8C000425,0x1F42420,0x1F42420,0x1F42420,0x6C001408,0x52002420,0xFE8C1E6A,0xA42422,0xA42422,0xFE84174D,0xFE781212,0xFE5C0D22,0xFE5C0D22,0xFE400431,0xFE741C52,0xFE641699,0xFE1000D0,0xBA000AB5,
+0x1602420,};
+static const uint32_t g_etc1_to_bc7_m6_table249[] = {
+0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x440000,0x880000,
+0x880000,0x880000,0x880000,0x16000000,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x2C0001,0x300000,0x300000,0x300000,0x440000,0x600000,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x13C0001,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,
+0x1D80000,0x71F80000,0x71F80000,0x71F80000,0x9E000000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x1D80000,0x71F80000,0x71F80000,0x71F80000,0x9E000000,0x71F80000,0x71F80000,0x71F80000,0x9E000000,0x9E000000,0x1540000,0x13C0001,0x13C0001,0x3700000,0x58C0000,0x1B00000,0x1B00000,0x13FC0000,0x3700000,0x58C0000,0x4BFC0000,0x71F80000,
+0x4BFC0000,0x1F80001,0x1F80001,0x1F80001,0x1F80001,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xFDF80000,0xFDF80000,0xFC000000,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xFDF80000,0xFDF80000,0xFC000000,0xFDF80000,0xFDF80000,0xFC000000,0xFC000000,0xFBFC0000,0xFBFC0000,0xFBFC0000,0xFDF80000,0xFDF80000,0xFC000000,0xFDF80000,0xFDF80000,0xFC000000,0xFC000000,0xFDF80000,
+0xFDF80000,0xFC000000,0xFC000000,0xFC000000,0xF5FC0000,0xE7FC0000,0x1F80001,0xF9FC0000,0xFBFC0000,0xFDF80000,0xFDF80000,0xFDF80000,0xF7FC0000,0xFBFC0000,0xFDF80000,0xFC000000,0xFDF80000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1588BEC,0xFF447ADF,0xFF2C6D47,0xFF20687B,0xFF186404,0xFF00509F,0xFEF44933,0xFED837A6,0xFECC2E12,0xFCB42426,0xFF0062AC,0xFED049C7,0xFEC43FBB,0xFE942717,0xFE7C18FE,0xFE68098D,0xFE702804,0xFE4C15EB,0xF8240111,0xDE2C1785,0x3FC8BEC,0xFECC72CF,0xFEB86878,0xFE704B2A,0xFE4C3941,0xFC182424,0xFE204349,0xFE082945,0xF4000D79,0xD80020D8,0x85F88BEC,
+0xE6006BE4,0xD60045F6,0xC4004D71,0xAC008BEC,0xFF3C7814,0xFF4C849C,0xFF4C888C,0xFF1861D6,0xFED8483B,0xFEAC2E3E,0xFE902345,0xFE6C0FFB,0xFF3476CA,0xFEF45E5F,0xFE7028DB,0xF4000D79,0x63FC8BEC,0x1BC1783,0xFFB014AE,0xFFA0122B,0xFF9C1142,0xFF98106D,0xFF800C3A,0xFF740A69,0xFF6405EB,0xFF4C030A,0xFD3C0005,0x9BFC1783,0xFF7C132D,0xFF6C1142,0xFF380ACD,0xFF140631,
+0xFEE00004,0xCFF81783,0xFED41142,0xF8000074,0xDE001784,0x9BFC1783,0xFF7C132D,0xFF6C1142,0xFF380ACD,0xFF140631,0xFEE00004,0xCFF81783,0xFED41142,0xF8000074,0xDE001784,0xCFF81783,0xFED41142,0xF8000074,0xDE001784,0xDE001784,0xFFB41556,0xFFAC1685,0xF7BC1703,0xFF9812DD,0xFF700F7A,0xFF480B1E,0xFF2807B2,0xFEE40559,0xFFA41576,0xFF841292,0xFF301168,0xF8000074,
+0xC1FC1783,0x120687B,0x120687B,0x120687B,0x120687B,0xFEF44933,0xFEF44933,0xFEF44933,0xFECC2E12,0xFECC2E12,0xFCB42422,0xFEC43FBB,0xFEC43FBB,0xFEC43FBB,0xFE7C18FE,0xFE7C18FE,0xFE68098D,0xFE4C15EB,0xFE4C15EB,0xF42800D9,0xCC2C1145,0x1B06878,0x1B06878,0x1B06878,0xFE4C3941,0xFE4C3941,0xFC182420,0xFE082945,0xFE082945,0xE8000C8D,0xC6001888,0x5DF46878,
+0x5DF46878,0xC4003D82,0xAC003B8D,0x90006878,0xFF045983,0xF71C62B2,0x120687B,0xFEE84AEA,0xFEC4399B,0xFEAC29BA,0xFE902345,0xFE6C0FFB,0xFEF8582E,0xFED0482D,0xFE70284B,0xE8000C8D,0x31FC6878,0x19C1142,0x19C1142,0x19C1142,0x19C1142,0xFF740A69,0xFF740A69,0xFF740A69,0xFF4C030A,0xFF4C030A,0xFD3C0001,0x6BFC1142,0x6BFC1142,0x6BFC1142,0xFF140631,0xFF140631,
+0xFCE00001,0xB7F81142,0xB7F81142,0xF8000050,0xCC001144,0x6BFC1142,0x6BFC1142,0x6BFC1142,0xFF140631,0xFF140631,0xFCE00001,0xB7F81142,0xB7F81142,0xF8000050,0xCC001144,0xB7F81142,0xB7F81142,0xF8000050,0xCC001144,0xCC001144,0xFF900F79,0xFF8C101A,0x19C1142,0xFF780E45,0xFF5C0C05,0xFF3809A1,0xFF2807B2,0xFEE40559,0xFF780FCD,0xFF680E10,0xA3FC1142,0xF8000050,
+0xA3FC1142,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFF80001,0xFDFC0002,0xFFF80001,0xFFF80000,0xFFF80002,0xFFF00000,0xFC000004,0xFDFC0002,0xFFF80001,0xFFF80000,0xFFF80002,0xFFF00000,0xFC000004,0xFFF80002,0xFFF00000,0xFC000004,0xFC000004,0xFDFC0002,0xFFF80001,0xFFF80000,0xFFF80002,0xFFF00000,0xFC000004,0xFFF80002,0xFFF00000,0xFC000004,0xFC000004,0xFFF80002,
+0xFFF00000,0xFC000004,0xFC000004,0xFC000004,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFF80001,0xFFF40001,0xFFF40000,0xFFEC0000,0xFDFC0002,0xFDFC0002,0xFFF40000,0xFC000004,0xFFF80002,0xB42422,0xB42422,0xB42422,0xB42422,0xB42422,0xB42422,0xB42422,0xB42422,0xB42422,0xB42422,0xFE680989,0xFE680989,0xFE680989,0xFE680989,0xFE680989,
+0xFE680989,0xE0300001,0xE0300001,0xE0300001,0x9E2C0001,0x30C2420,0x30C2420,0x30C2420,0x30C2420,0x30C2420,0x30C2420,0xCC000949,0xCC000949,0xCC000949,0x980002FD,0xBFC2420,0xBFC2420,0xBFC2420,0x780012C8,0x5A002420,0xFEAC1E85,0xB42422,0xB42422,0xFE9017EA,0xFE8C12CA,0xFE780DFA,0xFE780DFA,0xFE5404ED,0xFE901C99,0xFE7816FA,0xFE200140,0xCC000949,
+0x1802420,};
+static const uint32_t g_etc1_to_bc7_m6_table250[] = {
+0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0x5C0000,0xB80000,
+0xB80000,0xB80000,0xB80000,0x1E000000,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x3C0001,0x8400000,0x8400000,0x8400000,0x5C0000,0x800000,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x14C0001,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,
+0x1F00000,0x7DF80000,0x7DF80000,0x7DF80000,0xA6000000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x1F00000,0x7DF80000,0x7DF80000,0x7DF80000,0xA6000000,0x7DF80000,0x7DF80000,0x7DF80000,0xA6000000,0xA6000000,0x1640000,0x14C0001,0x14C0001,0x1840000,0x5A00000,0x3C40000,0x3C40000,0x27FC0000,0x1840000,0x5A00000,0x5BFC0000,0x7DF80000,
+0x5BFC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1608334,0xFF4473EF,0xFF3867CB,0xFF2C6383,0xFF245F04,0xFF0C4D93,0xFF0046EB,0xFEE4366A,0xFED82DC2,0xFEC42422,0xFF0C5CE4,0xFEE8465F,0xFED03D53,0xFEAC2617,0xFE941956,0xFE740A69,0xFE7C2534,0xFE5814AB,0xFA3C009A,0xE03C142D,0x13FC8330,0xFEE46CB7,0xFEC86380,0xFE88483A,0xFE643831,0xFE2C2422,0xFE2C3F39,0xFE082639,0xF4000A2D,0xDE001B24,0x8BFC8330,
+0xEC006584,0xDC003FEA,0xCA004541,0xB0008330,0xFF3C711C,0xFF4C7D04,0xF9608037,0xFF185C82,0xFEEC452B,0xFEBC2D3F,0xFEA82336,0xFE7410B2,0xFF346F66,0xFF00597C,0xFE7C2771,0xF4000A2D,0x6DFC8330,0x1C4142B,0xFFB411F3,0xFFAC0FDB,0xFFA40F22,0xFFA40E41,0xFF8C0ACE,0xFF800955,0xFF700543,0xFF6402EA,0xFF4C0001,0xA9FC142B,0xFF8810A9,0xFF7C0F20,0xFF4C09A2,0xFF2C05A5,
+0xFEF80000,0xD5F8142B,0xFEF00F20,0xFE000010,0xE000142C,0xA9FC142B,0xFF8810A9,0xFF7C0F20,0xFF4C09A2,0xFF2C05A5,0xFEF80000,0xD5F8142B,0xFEF00F20,0xFE000010,0xE000142C,0xD5F8142B,0xFEF00F20,0xFE000010,0xE000142C,0xE000142C,0xFFB41242,0xF9C01343,0xF9C013BB,0xFF98106D,0xFF840D72,0xFF6409D1,0xFF500709,0xFEFC04FD,0xFFB41262,0xFF980FFE,0xFF440F44,0xFE000010,
+0xC9FC142B,0x12C6383,0x12C6383,0x12C6383,0x12C6383,0xFF0046EB,0xFF0046EB,0xFF0046EB,0xFED82DC2,0xFED82DC2,0xFEC42422,0xFED03D53,0xFED03D53,0xFED03D53,0xFE941956,0xFE941956,0xFE740A69,0xFE5814AB,0xFE5814AB,0xF838007E,0xD23C0F21,0x1C06380,0x1C06380,0x1C06380,0xFE643831,0xFE643831,0xFE2C2422,0xFE082639,0xFE082639,0xEE0009C5,0xCC001478,0x65F86380,
+0x65F86380,0xCA003962,0xB2003611,0x96006380,0xFF1055F5,0xFD285DF2,0x12C6383,0xFEF8483A,0xFED437FA,0xFEBC28FE,0xFEA82336,0xFE7410B2,0xFEF8548A,0xFEDC4611,0xFE7C26E1,0xEE0009C5,0x3DF86380,0x1A40F22,0x1A40F22,0x1A40F22,0x1A40F22,0xFF800955,0xFF800955,0xFF800955,0xFF6402EA,0xFF6402EA,0xFF4C0001,0x7BFC0F20,0x7BFC0F20,0x7BFC0F20,0xFF2C05A5,0xFF2C05A5,
+0xFEF80000,0xBFF80F20,0xBFF80F20,0xFC00000D,0xD2000F20,0x7BFC0F20,0x7BFC0F20,0x7BFC0F20,0xFF2C05A5,0xFF2C05A5,0xFEF80000,0xBFF80F20,0xBFF80F20,0xFC00000D,0xD2000F20,0xBFF80F20,0xBFF80F20,0xFC00000D,0xD2000F20,0xD2000F20,0xFF900DB1,0xFBA40E1D,0x1A40F22,0xFF880C92,0xFF700AA5,0xFF5808CA,0xFF500709,0xFEFC04FD,0xFF940DC8,0xFF840C82,0xADFC0F20,0xFC00000D,
+0xADFC0F20,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0xC42422,0xC42422,0xC42422,0xC42422,0xC42422,0xC42422,0xC42422,0xC42422,0xC42422,0xC42422,0xFE740A69,0xFE740A69,0xFE740A69,0xFE740A69,0xFE740A69,
+0xFE740A69,0xE8400001,0xE8400001,0xE8400001,0xA63C0001,0x3242420,0x3242420,0x3242420,0x3242420,0x3242420,0x3242420,0xD80007F9,0xD80007F9,0xD80007F9,0xA20001F4,0x17FC2420,0x17FC2420,0x17FC2420,0x7E0011A4,0x62002420,0xFEAC1EF5,0xC42422,0xC42422,0xFEA01865,0xFE941379,0xFE880EBA,0xFE880EBA,0xFE6C05D2,0xFEA01D14,0xFE9417A4,0xFE3401BA,0xD80007F9,
+0x1A42420,};
+static const uint32_t g_etc1_to_bc7_m6_table251[] = {
+0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0x740000,0xE80000,
+0xE80000,0xE80000,0xE80000,0x26000000,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x4C0001,0x540000,0x540000,0x540000,0x740000,0xA40000,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0x15C0001,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,
+0xDFC0000,0x89F80000,0x89F80000,0x89F80000,0xAE000000,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0xDFC0000,0x89F80000,0x89F80000,0x89F80000,0xAE000000,0x89F80000,0x89F80000,0x89F80000,0xAE000000,0xAE000000,0x3740000,0x15C0001,0x15C0001,0x1980000,0x5B40000,0x1DC0000,0x1DC0000,0x3BFC0000,0x1980000,0x5B40000,0x69FC0000,0x89F80000,
+0x69FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x16879B4,0xFF506BE7,0xFF406114,0xFF385D2B,0xFF305924,0xFF18496F,0xFF0C4373,0xFEF03492,0xFEE42CC6,0xFED42422,0xFF185634,0xFEF441BB,0xFEDC3993,0xFEB8246F,0xFEA018E6,0xFE8C0B51,0xFE9421B4,0xFE701283,0xFC4C003A,0xE44C10AD,0x1FFC79B0,0xFEF0656B,0xFED85D2B,0xFEA0448A,0xFE703629,0xFE442420,0xFE383A6D,0xFE0822E9,0xFA00077D,0xE2001579,0x91FC79B0,
+0xF2005E40,0xE0003A48,0xD0003CE5,0xB40079B0,0xFF4C694B,0xFB647402,0xFD6876DF,0xFF2C56B2,0xFF004133,0xFED42B7A,0xFEBC21F6,0xFE84109D,0xFF3467C6,0xFF1053A2,0xFE94250F,0xFA00077D,0x75FC79B0,0x1C810AB,0xFFBC0EC6,0xFFB40D22,0xFFAC0C82,0xFFA40BD1,0xFF9808EE,0xFF8C07B5,0xFF7C0453,0xFF700262,0xFF5C0001,0xAFFC10AB,0xFF940DC1,0xFF880C80,0xFF5807F2,0xFF3804A9,
+0xFF100000,0xD7FC10AB,0xFF080C80,0xFE140000,0xE40010AC,0xAFFC10AB,0xFF940DC1,0xFF880C80,0xFF5807F2,0xFF3804A9,0xFF100000,0xD7FC10AB,0xFF080C80,0xFE140000,0xE40010AC,0xD7FC10AB,0xFF080C80,0xFE140000,0xE40010AC,0xE40010AC,0xFFBC0F15,0xFBC40FDB,0xFDC81043,0xFFB00D9E,0xFF980B2E,0xFF6C0809,0xFF5005C9,0xFF20040D,0xFFB40F22,0xFF980D4E,0xFF540C99,0xFE140000,
+0xCDFC10AB,0x1385D2B,0x1385D2B,0x1385D2B,0x1385D2B,0xFF0C4373,0xFF0C4373,0xFF0C4373,0xFEE42CC6,0xFEE42CC6,0xFED42422,0xFEDC3993,0xFEDC3993,0xFEDC3993,0xFEA018E6,0xFEA018E6,0xFE8C0B51,0xFE701283,0xFE701283,0xFA480032,0xD64C0C81,0x1D05D2B,0x1D05D2B,0x1D05D2B,0xFE703629,0xFE703629,0xFE442420,0xFE0822E9,0xFE0822E9,0xF4000759,0xD2001024,0x6DF85D2B,
+0x6DF85D2B,0xD00034E6,0xB8002FC1,0x9C005D2C,0xFF205092,0xFF2C5816,0x1385D2B,0xFF004403,0xFEEC354B,0xFEBC276E,0xFEBC21F6,0xFE84109D,0xFF104F65,0xFEF441EE,0xFE942496,0xF4000759,0x45FC5D2B,0x1AC0C82,0x1AC0C82,0x1AC0C82,0x1AC0C82,0xFF8C07B5,0xFF8C07B5,0xFF8C07B5,0xFF700262,0xFF700262,0xFF5C0001,0x87FC0C80,0x87FC0C80,0x87FC0C80,0xFF3804A9,0xFF3804A9,
+0xFF100000,0xC5F80C80,0xC5F80C80,0xFE140000,0xD6000C80,0x87FC0C80,0x87FC0C80,0x87FC0C80,0xFF3804A9,0xFF3804A9,0xFF100000,0xC5F80C80,0xC5F80C80,0xFE140000,0xD6000C80,0xC5F80C80,0xC5F80C80,0xFE140000,0xD6000C80,0xD6000C80,0xFFA00B50,0xFFAC0B95,0x1AC0C82,0xFF980A69,0xFF8408D1,0xFF640721,0xFF5005C9,0xFF20040D,0xFF940B68,0xFF840A52,0xB5FC0C80,0xFE140000,
+0xB5FC0C80,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0xD42422,0xD42422,0xD42422,0xD42422,0xD42422,0xD42422,0xD42422,0xD42422,0xD42422,0xD42422,0xFE8C0B51,0xFE8C0B51,0xFE8C0B51,0xFE8C0B51,0xFE8C0B51,
+0xFE8C0B51,0xF0500001,0xF0500001,0xF0500001,0xAE4C0001,0x33C2420,0x33C2420,0x33C2420,0x33C2420,0x33C2420,0x33C2420,0xE800069D,0xE800069D,0xE800069D,0xA8000124,0x23FC2420,0x23FC2420,0x23FC2420,0x8A001074,0x6A002420,0xFECC1F02,0xD42422,0xD42422,0xFEBC18F5,0xFEA81429,0xFE980F82,0xFE980F82,0xFE8006B2,0xFAB41D8D,0xFEA01829,0xFE50027D,0xE800069D,
+0x1C82420,};
+static const uint32_t g_etc1_to_bc7_m6_table252[] = {
+0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x28C0000,0x1200000,
+0x1200000,0x1200000,0x1200000,0x2E000001,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0x600000,0xA640000,0xA640000,0xA640000,0x28C0000,0xCC0000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x1700000,0x29FC0000,0x29FC0000,0x29FC0000,0x29FC0000,0x29FC0000,
+0x29FC0000,0x97F80000,0x97F80000,0x97F80000,0xB6000001,0x29FC0000,0x29FC0000,0x29FC0000,0x29FC0000,0x29FC0000,0x29FC0000,0x97F80000,0x97F80000,0x97F80000,0xB6000001,0x97F80000,0x97F80000,0x97F80000,0xB6000001,0xB6000001,0x1880000,0x1700000,0x1700000,0x1AC0000,0x3CC0000,0x1F40000,0x1F40000,0x51FC0000,0x1AC0000,0x3CC0000,0x7BFC0000,0x97F80000,
+0x7BFC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1746F9A,0xFF5C636D,0xFF4C59E2,0xFF445671,0xFF4452B0,0xFF244509,0xFF183FC9,0xFF0832A0,0xFEFC2BCC,0xFEE82420,0xFF244F2A,0xFF003CE1,0xFEF43599,0xFECC22EC,0xFEB8187A,0xFEA40C6D,0xFEA01E26,0xFE88107D,0xFE5C0008,0xE6600D21,0x2BFC6F9A,0xFEFC5DB5,0xFEE85671,0xFEAC40A4,0xFE8833FB,0xFE602420,0xFE5835B7,0xFE142035,0xFA000585,0xE2000FFD,0x97FC6F9A,
+0xF80056D6,0xE6003482,0xD0003409,0xB8006F9A,0xFF5860F6,0xFF6C6A48,0xFF6C6D09,0xFF2C503A,0xFF0C3CF6,0xFEDC2926,0xFECC20F9,0xFEA01085,0xFF505FB2,0xFF184DB4,0xFEB0221D,0xFA000585,0x7DF86F9A,0x1D00D22,0xFFC40B96,0xFFB80A52,0xFFB809D9,0xFFB00948,0xFFA40709,0xFF980614,0xFF880362,0xFF7C01DD,0xFF700000,0xB7FC0D21,0xFFA00AD2,0xFF9409D9,0xFF700633,0xFF5803BA,
+0xFF2C0000,0xDDF40D21,0xFF2009D9,0xFE4C0000,0xE6000D21,0xB7FC0D21,0xFFA00AD2,0xFF9409D9,0xFF700633,0xFF5803BA,0xFF2C0000,0xDDF40D21,0xFF2009D9,0xFE4C0000,0xE6000D21,0xDDF40D21,0xFF2009D9,0xFE4C0000,0xE6000D21,0xE6000D21,0xFFBC0BF4,0xFFCC0C66,0xFFCC0CC6,0xFFB40AAE,0xFF9808C1,0xFF7C063E,0xFF680484,0xFF380334,0xFFC40C0E,0xFFA40A8D,0xFF6409F2,0xFE4C0000,
+0xD3FC0D21,0x1445671,0x1445671,0x1445671,0x1445671,0xFF183FC9,0xFF183FC9,0xFF183FC9,0xFEFC2BCC,0xFEFC2BCC,0xFEE82420,0xFEF43599,0xFEF43599,0xFEF43599,0xFEB8187A,0xFEB8187A,0xFEA40C6D,0xFE88107D,0xFE88107D,0xFC600008,0xDA6009D9,0x1E05671,0x1E05671,0x1E05671,0xFE8833FB,0xFE8833FB,0xFE602420,0xFE142035,0xFE142035,0xFA000575,0xD8000BF6,0x75FC5671,
+0x75FC5671,0xD6003080,0xBE002931,0xA2005672,0xFF2C4B21,0xF9405231,0x1445671,0xFF103F92,0xFEEC3269,0xFEDC25DD,0xFECC20F9,0xFEA01085,0xFF2049F1,0xFF003DFD,0xFEB021B9,0xFA000575,0x51FC5671,0x1B809D9,0x1B809D9,0x1B809D9,0x1B809D9,0xFF980614,0xFF980614,0xFF980614,0xFF7C01DD,0xFF7C01DD,0xFF700000,0x93FC09D9,0x93FC09D9,0x93FC09D9,0xFF5803BA,0xFF5803BA,
+0xFF2C0000,0xCBF809D9,0xCBF809D9,0xFE4C0000,0xDA0009D9,0x93FC09D9,0x93FC09D9,0x93FC09D9,0xFF5803BA,0xFF5803BA,0xFF2C0000,0xCBF809D9,0xCBF809D9,0xFE4C0000,0xDA0009D9,0xCBF809D9,0xCBF809D9,0xFE4C0000,0xDA0009D9,0xDA0009D9,0xF9B00908,0xFFAC0928,0x1B809D9,0xFF980832,0xFF8406F4,0xFF740590,0xFF680484,0xFF380334,0xFFA80908,0xFF980808,0xBDF809D9,0xFE4C0000,
+0xBDF809D9,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0xE82420,0xE82420,0xE82420,0xE82420,0xE82420,0xE82420,0xE82420,0xE82420,0xE82420,0xE82420,0xFEA40C6D,0xFEA40C6D,0xFEA40C6D,0xFEA40C6D,0xFEA40C6D,
+0xFEA40C6D,0xFA600000,0xFA600000,0xFA600000,0xB6600001,0x1582420,0x1582420,0x1582420,0x1582420,0x1582420,0x1582420,0xFA000565,0xFA000565,0xFA000565,0xB4000082,0x31F82420,0x31F82420,0x31F82420,0x96000F3A,0x72002422,0xF8E01F81,0xE82420,0xE82420,0xFECC1974,0xFEB414F4,0xFEAC109D,0xFEAC109D,0xFE9407B4,0xFEBC1DC9,0xFEB418A0,0xFE60034D,0xFA000565,
+0x1EC2420,};
+static const uint32_t g_etc1_to_bc7_m6_table253[] = {
+0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x2A40000,0x1500000,
+0x1500000,0x1500000,0x1500000,0x36000001,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x700000,0x780000,0x780000,0x780000,0x2A40000,0xEC0000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x1800000,0x41FC0000,0x41FC0000,0x41FC0000,0x41FC0000,0x41FC0000,
+0x41FC0000,0xA1FC0000,0xA1FC0000,0xA1FC0000,0xBE000001,0x41FC0000,0x41FC0000,0x41FC0000,0x41FC0000,0x41FC0000,0x41FC0000,0xA1FC0000,0xA1FC0000,0xA1FC0000,0xBE000001,0xA1FC0000,0xA1FC0000,0xA1FC0000,0xBE000001,0xBE000001,0x5980000,0x1800000,0x1800000,0x7BC0000,0x3E00000,0x13FC0000,0x13FC0000,0x65FC0000,0x7BC0000,0x3E00000,0x89FC0000,0xA1FC0000,
+0x89FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x17C672A,0xFF685C5D,0xFF5853E2,0xFF5050D1,0xFF444D70,0xFF30415D,0xFF243CB9,0xFF1430F0,0xFF082AE0,0xFEF82420,0xFF304956,0xFF0C38E9,0xFF00325D,0xFED821A0,0xFECC1848,0xFEB00D61,0xFEAC1B66,0xFE940EED,0xFE700004,0xE8700A59,0x37FC672A,0xFF145745,0xFEFC50D1,0xFEB83D84,0xFEA03223,0xFE782420,0xFE703187,0xFE2C1E1D,0xFC0004C5,0xE8000BE9,0x9DFC672A,
+0xFC0050E5,0xE6003022,0xD6002CD1,0xBC00672A,0xFF645A02,0xFF6C6288,0xF578652A,0xFF444AE6,0xFF143961,0xFEF0276A,0xFEDC2036,0xFEB010A0,0xFF5058A2,0xFF304877,0xFEB41FE1,0xFC0004C5,0x83FC672A,0x1D40A56,0xFFC8092D,0xFFC00825,0xFFC007C1,0xFFBC074C,0xFFB0058D,0xFFA404C8,0xFF9402A6,0xFF880179,0xFF800000,0xC1FC0A56,0xFFAC0882,0xFFA007C1,0xFF7C04DB,0xFF6402EA,
+0xFF400001,0xE1F80A56,0xFF3807C1,0xFE7C0000,0xE8000A59,0xC1FC0A56,0xFFAC0882,0xFFA007C1,0xFF7C04DB,0xFF6402EA,0xFF400001,0xE1F80A56,0xFF3807C1,0xFE7C0000,0xE8000A59,0xE1F80A56,0xFF3807C1,0xFE7C0000,0xE8000A59,0xE8000A59,0xFDCC0965,0xFFCC09C6,0xFFCC0A26,0xFFC00865,0xFFAC06E5,0xFF7C050E,0xFF7C0385,0xFF50028A,0xFFC4096E,0xFFB0085D,0xFF7407D1,0xFE7C0000,
+0xD9FC0A56,0x15050D1,0x15050D1,0x15050D1,0x15050D1,0xFF243CB9,0xFF243CB9,0xFF243CB9,0xFF082AE0,0xFF082AE0,0xFEF82420,0xFF00325D,0xFF00325D,0xFF00325D,0xFECC1848,0xFECC1848,0xFEB00D61,0xFE940EED,0xFE940EED,0xFE700004,0xDE7007C1,0x1F450D1,0x1F450D1,0x1F450D1,0xFEA03223,0xFEA03223,0xFE782420,0xFE2C1E1D,0xFE2C1E1D,0xFC0004C1,0xDE0008E2,0x7FF850D1,
+0x7FF850D1,0xDC002D24,0xC40023CD,0xA60050D2,0xFF3C469D,0xFF4C4CD1,0x15050D1,0xFF183C30,0xFF002FDD,0xFEE82482,0xFEDC2036,0xFEB010A0,0xFF344580,0xFF103A91,0xFEB41F7D,0xFC0004C1,0x5DF850D1,0x1C007C1,0x1C007C1,0x1C007C1,0x1C007C1,0xFFA404C8,0xFFA404C8,0xFFA404C8,0xFF880179,0xFF880179,0xFF800000,0x9FFC07C1,0x9FFC07C1,0x9FFC07C1,0xFF6402EA,0xFF6402EA,
+0xFF400001,0xD1F807C1,0xD1F807C1,0xFE7C0000,0xDE0007C1,0x9FFC07C1,0x9FFC07C1,0x9FFC07C1,0xFF6402EA,0xFF6402EA,0xFF400001,0xD1F807C1,0xD1F807C1,0xFE7C0000,0xDE0007C1,0xD1F807C1,0xD1F807C1,0xFE7C0000,0xDE0007C1,0xDE0007C1,0xFDB80708,0xF7BC0745,0x1C007C1,0xFFA40681,0xFF980568,0xFF7C0465,0xFF7C0385,0xFF50028A,0xFDB0070A,0xFFA4065D,0xC3FC07C1,0xFE7C0000,
+0xC3FC07C1,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0xF82420,0xF82420,0xF82420,0xF82420,0xF82420,0xF82420,0xF82420,0xF82420,0xF82420,0xF82420,0xFEB00D61,0xFEB00D61,0xFEB00D61,0xFEB00D61,0xFEB00D61,
+0xFEB00D61,0xFE700004,0xFE700004,0xFE700004,0xBE700001,0x1702420,0x1702420,0x1702420,0x1702420,0x1702420,0x1702420,0xFA0004B5,0xFA0004B5,0xFA0004B5,0xBC00002D,0x3DF82420,0x3DF82420,0x3DF82420,0x9C000E2A,0x7A002422,0xFEEC1F85,0xF82420,0xF82420,0xFED81A11,0xFED015B1,0xFEC41174,0xFEC41174,0xFE9C08C8,0xFED81E0A,0xFED01962,0xFE74040D,0xFA0004B5,
+0x9FC2420,};
+static const uint32_t g_etc1_to_bc7_m6_table254[] = {
+0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x2BC0000,0x1800000,
+0x1800000,0x1800000,0x1800000,0x3E000001,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x880000,0x880000,0x880000,0x2BC0000,0x1100000,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,0x1900000,0x59FC0000,0x59FC0000,0x59FC0000,0x59FC0000,0x59FC0000,
+0x59FC0000,0xADFC0000,0xADFC0000,0xADFC0000,0xC6000001,0x59FC0000,0x59FC0000,0x59FC0000,0x59FC0000,0x59FC0000,0x59FC0000,0xADFC0000,0xADFC0000,0xADFC0000,0xC6000001,0xADFC0000,0xADFC0000,0xADFC0000,0xC6000001,0xC6000001,0xDA80000,0x1900000,0x1900000,0x1D00000,0x3F40000,0x31FC0000,0x31FC0000,0x79FC0000,0x1D00000,0x3F40000,0x99FC0000,0xADFC0000,
+0x99FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x1845F3A,0xFF7455C5,0xFF644E42,0xFF584B89,0xFF504888,0xFF3C3DE9,0xFF3039D9,0xFF202F60,0xFF142A0C,0xFF082420,0xFF4443BD,0xFF183541,0xFF0C2F69,0xFEF02070,0xFED81820,0xFEC40E48,0xFEB81906,0xFEA00DB5,0xFE880034,0xEC8007E1,0x43FC5F3A,0xFF205129,0xFF084B89,0xFED83AA0,0xFEB8306B,0xFE902420,0xFE882DB7,0xFE381C71,0xFE0804BD,0xEA000892,0xA3FC5F3A,
+0xFE084B86,0xEC002C5A,0xDC002651,0xC0005F3A,0xFF645372,0xF9805B72,0xF9805D5A,0xFF4445D6,0xFF20362E,0xFEFC25F8,0xFEE81F71,0xFEC010D5,0xFF58526E,0xFF3043C7,0xFEBC1E2D,0xFE0804BD,0x8BFC5F3A,0x1D807E2,0xFFD006F2,0xFFCC0635,0xFFC805E9,0xFFC40576,0xFFBC0441,0xFFB003A4,0xFFA00202,0xFFA00121,0xFF900000,0xC9FC07E1,0xFFB8067A,0xFFAC05E9,0xFF9403AB,0xFF7C0232,
+0xFF580001,0xE5F807E1,0xFF5405E9,0xFEAC0000,0xEC0007E1,0xC9FC07E1,0xFFB8067A,0xFFAC05E9,0xFF9403AB,0xFF7C0232,0xFF580001,0xE5F807E1,0xFF5405E9,0xFEAC0000,0xEC0007E1,0xE5F807E1,0xFF5405E9,0xFEAC0000,0xEC0007E1,0xEC0007E1,0xFFD00715,0xF5D80798,0xF5D807BD,0xFFC4065E,0xFFAC0545,0xFFA003D8,0xFF8C02BA,0xFF6401E1,0xFFD0072E,0xFFC0063D,0xFF9005F6,0xFEAC0000,
+0xDFF807E1,0x1584B89,0x1584B89,0x1584B89,0x1584B89,0xFF3039D9,0xFF3039D9,0xFF3039D9,0xFF142A0C,0xFF142A0C,0xFF082420,0xFF0C2F69,0xFF0C2F69,0xFF0C2F69,0xFED81820,0xFED81820,0xFEC40E48,0xFEA00DB5,0xFEA00DB5,0xFE880034,0xE28005E9,0x7FC4B86,0x7FC4B86,0x7FC4B86,0xFEB8306B,0xFEB8306B,0xFE902420,0xFE381C71,0xFE381C71,0xFE0804BD,0xE200064D,0x85FC4B86,
+0x85FC4B86,0xE0002A76,0xCA001ED9,0xAC004B86,0xFF4C4244,0xFF4C4811,0x1584B89,0xFF2C38D6,0xFF142DA1,0xFEF8232A,0xFEE81F71,0xFEC010D5,0xFF344100,0xFF18376B,0xFEBC1DC9,0xFE0804BD,0x65FC4B86,0x1C805E9,0x1C805E9,0x1C805E9,0x1C805E9,0xFFB003A4,0xFFB003A4,0xFFB003A4,0xFFA00121,0xFFA00121,0xFF900000,0xABFC05E9,0xABFC05E9,0xABFC05E9,0xFF7C0232,0xFF7C0232,
+0xFF580001,0xD7F805E9,0xD7F805E9,0xFEAC0000,0xE20005E9,0xABFC05E9,0xABFC05E9,0xABFC05E9,0xFF7C0232,0xFF7C0232,0xFF580001,0xD7F805E9,0xD7F805E9,0xFEAC0000,0xE20005E9,0xD7F805E9,0xD7F805E9,0xFEAC0000,0xE20005E9,0xE20005E9,0xFFBC0550,0xFBC4057D,0x1C805E9,0xFFB404EA,0xFFAC0424,0xFF940371,0xFF8C02BA,0xFF6401E1,0xFFB4055A,0xFFB004E4,0xCBFC05E9,0xFEAC0000,
+0xCBFC05E9,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1082420,0x1082420,0x1082420,0x1082420,0x1082420,0x1082420,0x1082420,0x1082420,0x1082420,0x1082420,0xFEC40E48,0xFEC40E48,0xFEC40E48,0xFEC40E48,0xFEC40E48,
+0xFEC40E48,0xFE880034,0xFE880034,0xFE880034,0xC6800001,0x1882420,0x1882420,0x1882420,0x1882420,0x1882420,0x1882420,0xFE0804BD,0xFE0804BD,0xFE0804BD,0xC6000002,0x49F82420,0x49F82420,0x49F82420,0xA6000D41,0x82002422,0xF9002000,0x1082420,0x1082420,0xFEE81A90,0xFEE41675,0xFED41248,0xFED41248,0xFEAC09CD,0xFAEC1E85,0xFED019E2,0xFE90052A,0xFE0804BD,
+0x19FC2420,};
+static const uint32_t g_etc1_to_bc7_m6_table255[] = {
+0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0xD40000,0x1B00000,
+0x1B00000,0x1B00000,0x1B00000,0x46000001,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x900000,0x4980000,0x4980000,0x4980000,0xD40000,0x1300000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x1A00000,0x71FC0000,0x71FC0000,0x71FC0000,0x71FC0000,0x71FC0000,
+0x71FC0000,0xB9FC0000,0xB9FC0000,0xB9FC0000,0xCE000001,0x71FC0000,0x71FC0000,0x71FC0000,0x71FC0000,0x71FC0000,0x71FC0000,0xB9FC0000,0xB9FC0000,0xB9FC0000,0xCE000001,0xB9FC0000,0xB9FC0000,0xB9FC0000,0xCE000001,0xCE000001,0x1BC0000,0x1A00000,0x1A00000,0x1E40000,0x1BFC0000,0x4FFC0000,0x4FFC0000,0x8DFC0000,0x1E40000,0x1BFC0000,0xA7FC0000,0xB9FC0000,
+0xA7FC0000,0x1FC0001,0x1FC0001,0x1FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFBFC0001,0xF7FC0001,0x1FC0001,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0x1FC0001,0xFDFC0001,0xFFFC0000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,
+0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xFFFC0000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0001,0xF7FC0001,0xF7FC0001,0xFDFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0001,0xFDFC0001,0xFFF00000,0xFE000000,
+0xFFFC0000,0x18C57CA,0xFF744F85,0xFF6C48F9,0xFF644691,0xFF5C43F0,0xFF443AAD,0xFF4436EC,0xFF2C2DF0,0xFF202950,0xFF182420,0xFF443E8D,0xFF2431E9,0xFF182CBD,0xFEFC1F6C,0xFEEC1816,0xFED00F64,0xFED81711,0xFEB80CAD,0xFE940094,0xEE9005C1,0x4FFC57CA,0xFF2C4B75,0xFF184691,0xFEF037C0,0xFECC2F04,0xFEA82420,0xFEA02A47,0xFE641B02,0xFE140585,0xEE0005E5,0xA9FC57CA,
+0xFE284691,0xF2002962,0xDC002041,0xC40057CA,0xFF744D72,0xFD885442,0xFD88560A,0xFF5440F0,0xFF343326,0xFF1024C0,0xFEF81EEA,0xFED81141,0xFF704C95,0xFF503F25,0xFED81CB7,0xFE140585,0x93FC57CA,0x1E005C2,0xFFDC051E,0xFFD4048E,0xFFD00451,0xFFD00402,0xFFC40311,0xFFBC02A8,0xFFAC0176,0xFFAC00CD,0xFFA00000,0xCFFC05C1,0xFFC004C1,0xFFB80451,0xFFA002A3,0xFF88019A,
+0xFF700001,0xE7FC05C1,0xFF6C0451,0xFEE00000,0xEE0005C1,0xCFFC05C1,0xFFC004C1,0xFFB80451,0xFFA002A3,0xFF88019A,0xFF700001,0xE7FC05C1,0xFF6C0451,0xFEE00000,0xEE0005C1,0xE7FC05C1,0xFF6C0451,0xFEE00000,0xEE0005C1,0xEE0005C1,0xFFD8052A,0xF7DC0584,0xF7DC05A5,0xFFD404BA,0xFFC003D1,0xFFA802C2,0xFFA001F9,0xFF7C0161,0xFFD0053E,0xFFC80479,0xFF98045A,0xFEE00000,
+0xE1FC05C1,0x1644691,0x1644691,0x1644691,0x1644691,0xFF4436EC,0xFF4436EC,0xFF4436EC,0xFF202950,0xFF202950,0xFF182420,0xFF182CBD,0xFF182CBD,0xFF182CBD,0xFEEC1816,0xFEEC1816,0xFED00F64,0xFEB80CAD,0xFEB80CAD,0xFE940094,0xE6900451,0x15FC4691,0x15FC4691,0x15FC4691,0xFECC2F04,0xFECC2F04,0xFEA82420,0xFE641B02,0xFE641B02,0xFE140585,0xE6000461,0x8DFC4691,
+0x8DFC4691,0xE6002822,0xD0001A55,0xB2004692,0xFF4C3E24,0xF96043A4,0x1644691,0xFF3C35A5,0xFF202BD5,0xFF08226D,0xFEF81EEA,0xFED81141,0xFF3C3D49,0xFF303446,0xFED81C66,0xFE140585,0x6FFC4691,0x1D00451,0x1D00451,0x1D00451,0x1D00451,0xFFBC02A8,0xFFBC02A8,0xFFBC02A8,0xFFAC00CD,0xFFAC00CD,0xFFA00000,0xB7FC0451,0xB7FC0451,0xB7FC0451,0xFF88019A,0xFF88019A,
+0xFF700001,0xDDF40451,0xDDF40451,0xFEE00000,0xE6000451,0xB7FC0451,0xB7FC0451,0xB7FC0451,0xFF88019A,0xFF88019A,0xFF700001,0xDDF40451,0xDDF40451,0xFEE00000,0xE6000451,0xDDF40451,0xDDF40451,0xFEE00000,0xE6000451,0xE6000451,0xF9CC03F5,0xFFCC03F5,0x1D00451,0xFFC4039D,0xFFAC0304,0xFFA80271,0xFFA001F9,0xFF7C0161,0xFBC803F5,0xFBC0039D,0xD3FC0451,0xFEE00000,
+0xD3FC0451,0x1FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFDFC0002,0xFFFC0001,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFE000000,0xFFFC0000,0xFFFC0000,0xFE000000,0xFE000000,0xFFFC0000,
+0xFFFC0000,0xFE000000,0xFE000000,0xFE000000,0xFDFC0002,0xF7FC0002,0xF7FC0002,0xFDFC0002,0xFFFC0001,0xFFFC0000,0xFFFC0000,0xFFFC0000,0xFDFC0002,0xFDFC0002,0xFFFC0000,0xFE000000,0xFFFC0000,0x1182420,0x1182420,0x1182420,0x1182420,0x1182420,0x1182420,0x1182420,0x1182420,0x1182420,0x1182420,0xFED00F64,0xFED00F64,0xFED00F64,0xFED00F64,0xFED00F64,
+0xFED00F64,0xFE940094,0xFE940094,0xFE940094,0xCE900001,0x1A02420,0x1A02420,0x1A02420,0x1A02420,0x1A02420,0x1A02420,0xFE140585,0xFE140585,0xFE140585,0xCE0C0001,0x55F82420,0x55F82420,0x55F82420,0xB2000C49,0x8A002422,0xFF0C2008,0x1182420,0x1182420,0xFF041B34,0xFEF81741,0xFEDC133D,0xFEDC133D,0xFEC00AE1,0xFEF41EAD,0xFEE41AAA,0xFE9C0631,0xFE140585,
+0x27FC2420,};
+const uint32_t *g_etc1_to_bc7_m6_table[] = {
+g_etc1_to_bc7_m6_table0, g_etc1_to_bc7_m6_table1, g_etc1_to_bc7_m6_table2, g_etc1_to_bc7_m6_table3, g_etc1_to_bc7_m6_table4, g_etc1_to_bc7_m6_table5, g_etc1_to_bc7_m6_table6, g_etc1_to_bc7_m6_table7, g_etc1_to_bc7_m6_table8, g_etc1_to_bc7_m6_table9, g_etc1_to_bc7_m6_table10, g_etc1_to_bc7_m6_table11, g_etc1_to_bc7_m6_table12, g_etc1_to_bc7_m6_table13, g_etc1_to_bc7_m6_table14, g_etc1_to_bc7_m6_table15,
+g_etc1_to_bc7_m6_table16, g_etc1_to_bc7_m6_table17, g_etc1_to_bc7_m6_table18, g_etc1_to_bc7_m6_table19, g_etc1_to_bc7_m6_table20, g_etc1_to_bc7_m6_table21, g_etc1_to_bc7_m6_table22, g_etc1_to_bc7_m6_table23, g_etc1_to_bc7_m6_table24, g_etc1_to_bc7_m6_table25, g_etc1_to_bc7_m6_table26, g_etc1_to_bc7_m6_table27, g_etc1_to_bc7_m6_table28, g_etc1_to_bc7_m6_table29, g_etc1_to_bc7_m6_table30, g_etc1_to_bc7_m6_table31,
+g_etc1_to_bc7_m6_table32, g_etc1_to_bc7_m6_table33, g_etc1_to_bc7_m6_table34, g_etc1_to_bc7_m6_table35, g_etc1_to_bc7_m6_table36, g_etc1_to_bc7_m6_table37, g_etc1_to_bc7_m6_table38, g_etc1_to_bc7_m6_table39, g_etc1_to_bc7_m6_table40, g_etc1_to_bc7_m6_table41, g_etc1_to_bc7_m6_table42, g_etc1_to_bc7_m6_table43, g_etc1_to_bc7_m6_table44, g_etc1_to_bc7_m6_table45, g_etc1_to_bc7_m6_table46, g_etc1_to_bc7_m6_table47,
+g_etc1_to_bc7_m6_table48, g_etc1_to_bc7_m6_table49, g_etc1_to_bc7_m6_table50, g_etc1_to_bc7_m6_table51, g_etc1_to_bc7_m6_table52, g_etc1_to_bc7_m6_table53, g_etc1_to_bc7_m6_table54, g_etc1_to_bc7_m6_table55, g_etc1_to_bc7_m6_table56, g_etc1_to_bc7_m6_table57, g_etc1_to_bc7_m6_table58, g_etc1_to_bc7_m6_table59, g_etc1_to_bc7_m6_table60, g_etc1_to_bc7_m6_table61, g_etc1_to_bc7_m6_table62, g_etc1_to_bc7_m6_table63,
+g_etc1_to_bc7_m6_table64, g_etc1_to_bc7_m6_table65, g_etc1_to_bc7_m6_table66, g_etc1_to_bc7_m6_table67, g_etc1_to_bc7_m6_table68, g_etc1_to_bc7_m6_table69, g_etc1_to_bc7_m6_table70, g_etc1_to_bc7_m6_table71, g_etc1_to_bc7_m6_table72, g_etc1_to_bc7_m6_table73, g_etc1_to_bc7_m6_table74, g_etc1_to_bc7_m6_table75, g_etc1_to_bc7_m6_table76, g_etc1_to_bc7_m6_table77, g_etc1_to_bc7_m6_table78, g_etc1_to_bc7_m6_table79,
+g_etc1_to_bc7_m6_table80, g_etc1_to_bc7_m6_table81, g_etc1_to_bc7_m6_table82, g_etc1_to_bc7_m6_table83, g_etc1_to_bc7_m6_table84, g_etc1_to_bc7_m6_table85, g_etc1_to_bc7_m6_table86, g_etc1_to_bc7_m6_table87, g_etc1_to_bc7_m6_table88, g_etc1_to_bc7_m6_table89, g_etc1_to_bc7_m6_table90, g_etc1_to_bc7_m6_table91, g_etc1_to_bc7_m6_table92, g_etc1_to_bc7_m6_table93, g_etc1_to_bc7_m6_table94, g_etc1_to_bc7_m6_table95,
+g_etc1_to_bc7_m6_table96, g_etc1_to_bc7_m6_table97, g_etc1_to_bc7_m6_table98, g_etc1_to_bc7_m6_table99, g_etc1_to_bc7_m6_table100, g_etc1_to_bc7_m6_table101, g_etc1_to_bc7_m6_table102, g_etc1_to_bc7_m6_table103, g_etc1_to_bc7_m6_table104, g_etc1_to_bc7_m6_table105, g_etc1_to_bc7_m6_table106, g_etc1_to_bc7_m6_table107, g_etc1_to_bc7_m6_table108, g_etc1_to_bc7_m6_table109, g_etc1_to_bc7_m6_table110, g_etc1_to_bc7_m6_table111,
+g_etc1_to_bc7_m6_table112, g_etc1_to_bc7_m6_table113, g_etc1_to_bc7_m6_table114, g_etc1_to_bc7_m6_table115, g_etc1_to_bc7_m6_table116, g_etc1_to_bc7_m6_table117, g_etc1_to_bc7_m6_table118, g_etc1_to_bc7_m6_table119, g_etc1_to_bc7_m6_table120, g_etc1_to_bc7_m6_table121, g_etc1_to_bc7_m6_table122, g_etc1_to_bc7_m6_table123, g_etc1_to_bc7_m6_table124, g_etc1_to_bc7_m6_table125, g_etc1_to_bc7_m6_table126, g_etc1_to_bc7_m6_table127,
+g_etc1_to_bc7_m6_table128, g_etc1_to_bc7_m6_table129, g_etc1_to_bc7_m6_table130, g_etc1_to_bc7_m6_table131, g_etc1_to_bc7_m6_table132, g_etc1_to_bc7_m6_table133, g_etc1_to_bc7_m6_table134, g_etc1_to_bc7_m6_table135, g_etc1_to_bc7_m6_table136, g_etc1_to_bc7_m6_table137, g_etc1_to_bc7_m6_table138, g_etc1_to_bc7_m6_table139, g_etc1_to_bc7_m6_table140, g_etc1_to_bc7_m6_table141, g_etc1_to_bc7_m6_table142, g_etc1_to_bc7_m6_table143,
+g_etc1_to_bc7_m6_table144, g_etc1_to_bc7_m6_table145, g_etc1_to_bc7_m6_table146, g_etc1_to_bc7_m6_table147, g_etc1_to_bc7_m6_table148, g_etc1_to_bc7_m6_table149, g_etc1_to_bc7_m6_table150, g_etc1_to_bc7_m6_table151, g_etc1_to_bc7_m6_table152, g_etc1_to_bc7_m6_table153, g_etc1_to_bc7_m6_table154, g_etc1_to_bc7_m6_table155, g_etc1_to_bc7_m6_table156, g_etc1_to_bc7_m6_table157, g_etc1_to_bc7_m6_table158, g_etc1_to_bc7_m6_table159,
+g_etc1_to_bc7_m6_table160, g_etc1_to_bc7_m6_table161, g_etc1_to_bc7_m6_table162, g_etc1_to_bc7_m6_table163, g_etc1_to_bc7_m6_table164, g_etc1_to_bc7_m6_table165, g_etc1_to_bc7_m6_table166, g_etc1_to_bc7_m6_table167, g_etc1_to_bc7_m6_table168, g_etc1_to_bc7_m6_table169, g_etc1_to_bc7_m6_table170, g_etc1_to_bc7_m6_table171, g_etc1_to_bc7_m6_table172, g_etc1_to_bc7_m6_table173, g_etc1_to_bc7_m6_table174, g_etc1_to_bc7_m6_table175,
+g_etc1_to_bc7_m6_table176, g_etc1_to_bc7_m6_table177, g_etc1_to_bc7_m6_table178, g_etc1_to_bc7_m6_table179, g_etc1_to_bc7_m6_table180, g_etc1_to_bc7_m6_table181, g_etc1_to_bc7_m6_table182, g_etc1_to_bc7_m6_table183, g_etc1_to_bc7_m6_table184, g_etc1_to_bc7_m6_table185, g_etc1_to_bc7_m6_table186, g_etc1_to_bc7_m6_table187, g_etc1_to_bc7_m6_table188, g_etc1_to_bc7_m6_table189, g_etc1_to_bc7_m6_table190, g_etc1_to_bc7_m6_table191,
+g_etc1_to_bc7_m6_table192, g_etc1_to_bc7_m6_table193, g_etc1_to_bc7_m6_table194, g_etc1_to_bc7_m6_table195, g_etc1_to_bc7_m6_table196, g_etc1_to_bc7_m6_table197, g_etc1_to_bc7_m6_table198, g_etc1_to_bc7_m6_table199, g_etc1_to_bc7_m6_table200, g_etc1_to_bc7_m6_table201, g_etc1_to_bc7_m6_table202, g_etc1_to_bc7_m6_table203, g_etc1_to_bc7_m6_table204, g_etc1_to_bc7_m6_table205, g_etc1_to_bc7_m6_table206, g_etc1_to_bc7_m6_table207,
+g_etc1_to_bc7_m6_table208, g_etc1_to_bc7_m6_table209, g_etc1_to_bc7_m6_table210, g_etc1_to_bc7_m6_table211, g_etc1_to_bc7_m6_table212, g_etc1_to_bc7_m6_table213, g_etc1_to_bc7_m6_table214, g_etc1_to_bc7_m6_table215, g_etc1_to_bc7_m6_table216, g_etc1_to_bc7_m6_table217, g_etc1_to_bc7_m6_table218, g_etc1_to_bc7_m6_table219, g_etc1_to_bc7_m6_table220, g_etc1_to_bc7_m6_table221, g_etc1_to_bc7_m6_table222, g_etc1_to_bc7_m6_table223,
+g_etc1_to_bc7_m6_table224, g_etc1_to_bc7_m6_table225, g_etc1_to_bc7_m6_table226, g_etc1_to_bc7_m6_table227, g_etc1_to_bc7_m6_table228, g_etc1_to_bc7_m6_table229, g_etc1_to_bc7_m6_table230, g_etc1_to_bc7_m6_table231, g_etc1_to_bc7_m6_table232, g_etc1_to_bc7_m6_table233, g_etc1_to_bc7_m6_table234, g_etc1_to_bc7_m6_table235, g_etc1_to_bc7_m6_table236, g_etc1_to_bc7_m6_table237, g_etc1_to_bc7_m6_table238, g_etc1_to_bc7_m6_table239,
+g_etc1_to_bc7_m6_table240, g_etc1_to_bc7_m6_table241, g_etc1_to_bc7_m6_table242, g_etc1_to_bc7_m6_table243, g_etc1_to_bc7_m6_table244, g_etc1_to_bc7_m6_table245, g_etc1_to_bc7_m6_table246, g_etc1_to_bc7_m6_table247, g_etc1_to_bc7_m6_table248, g_etc1_to_bc7_m6_table249, g_etc1_to_bc7_m6_table250, g_etc1_to_bc7_m6_table251, g_etc1_to_bc7_m6_table252, g_etc1_to_bc7_m6_table253, g_etc1_to_bc7_m6_table254, g_etc1_to_bc7_m6_table255,
+};
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_dxt1_5.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_dxt1_5.inc
new file mode 100644
index 0000000000..3e7610ff53
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_dxt1_5.inc
@@ -0,0 +1,494 @@
+// Copyright (C) 2017-2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+{0,2,18},{0,1,9},{0,1,0},{0,1,9},{0,1,40},{0,1,22},{0,1,13},{0,1,61},{0,1,47},{0,1,65},{0,2,18},{0,1,9},{0,1,0},{0,1,9},{0,1,40},{0,1,22},{0,1,13},{0,1,61},{1,0,40},{0,1,61},{0,1,0},{0,1,0},{0,1,0},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,0},
+{0,1,0},{0,1,0},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{1,0,18},{0,1,9},{0,1,0},{0,1,9},{1,0,18},{2,0,18},{0,1,9},{0,1,36},{2,0,18},{0,1,36},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,5,54},{0,3,40},{0,2,61},
+{0,2,36},{0,4,51},{0,2,37},{0,2,1},{0,2,52},{0,2,77},{0,1,73},{1,3,22},{1,2,13},{1,2,4},{1,2,13},{0,4,51},{1,2,34},{0,2,1},{0,2,52},{4,0,51},{0,2,52},{0,4,37},{0,4,37},{0,4,37},{0,2,36},{0,3,8},{0,2,1},{0,2,1},{0,1,5},{0,1,30},{0,1,9},{1,2,4},{1,2,4},{1,2,4},{1,1,8},{1,1,8},
+{0,2,1},{0,2,1},{0,1,5},{3,0,8},{0,1,5},{2,1,18},{0,3,4},{1,2,0},{0,2,0},{2,1,18},{5,0,18},{0,2,0},{0,2,36},{5,0,18},{0,2,36},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,5},{0,1,5},{1,6,54},{1,4,40},{1,3,61},{1,3,36},{1,5,51},{1,3,37},{1,3,1},
+{1,3,52},{0,3,72},{0,3,40},{2,4,22},{2,3,13},{2,3,4},{2,3,13},{1,5,51},{0,4,29},{1,3,1},{0,3,40},{7,0,51},{0,3,40},{1,5,37},{1,5,37},{1,5,37},{1,3,36},{1,4,8},{1,3,1},{1,3,1},{1,2,5},{0,3,8},{1,2,9},{2,3,4},{2,3,4},{2,3,4},{2,2,8},{3,0,8},{1,3,1},{1,3,1},{1,2,5},{6,0,8},
+{1,2,5},{3,2,18},{1,4,4},{2,3,0},{1,3,0},{3,2,18},{6,1,18},{1,3,0},{0,3,36},{6,1,18},{0,3,36},{1,0,36},{1,0,36},{1,0,36},{1,0,36},{1,3,1},{1,3,1},{1,3,1},{1,2,1},{0,3,4},{0,3,4},{2,7,54},{2,5,40},{2,4,62},{2,4,38},{2,6,51},{2,4,27},{2,4,3},{2,3,69},{0,5,60},{1,4,54},{3,5,22},
+{3,4,9},{3,4,6},{3,4,21},{5,0,51},{2,4,27},{2,4,3},{0,4,50},{10,0,51},{0,4,50},{2,6,37},{2,6,37},{2,6,37},{2,4,37},{2,5,8},{2,4,2},{2,4,2},{2,3,5},{1,4,8},{2,3,9},{3,4,5},{3,4,5},{3,4,5},{3,3,8},{4,1,8},{2,4,2},{2,4,2},{2,3,5},{9,0,8},{2,3,5},{3,5,18},{2,5,4},{3,4,2},
+{2,4,2},{3,5,18},{7,2,18},{2,4,2},{0,4,50},{7,2,18},{0,4,50},{2,0,36},{2,0,36},{2,0,36},{2,0,36},{2,4,1},{2,4,1},{2,4,1},{2,3,1},{1,4,4},{1,4,4},{3,8,68},{3,6,60},{4,5,68},{3,5,50},{3,7,53},{3,6,28},{3,5,5},{3,5,53},{3,5,68},{2,5,38},{4,6,22},{4,5,13},{4,5,4},{4,5,13},{6,1,52},
+{3,6,27},{3,5,4},{1,5,37},{13,0,52},{1,5,37},{3,7,50},{3,7,50},{3,7,50},{3,5,50},{3,6,11},{3,5,5},{3,5,5},{3,4,6},{2,5,11},{3,4,9},{4,5,4},{4,5,4},{4,5,4},{4,4,8},{4,4,8},{3,5,4},{3,5,4},{3,4,5},{12,0,8},{3,4,5},{7,0,18},{4,5,9},{4,5,0},{3,5,0},{7,0,18},{14,0,18},{3,5,0},
+{0,5,36},{14,0,18},{0,5,36},{3,0,50},{3,0,50},{3,0,50},{3,0,50},{3,6,2},{3,6,2},{3,6,2},{3,4,2},{2,5,2},{2,5,2},{4,9,54},{4,7,40},{4,6,61},{4,6,36},{4,8,51},{4,6,37},{4,6,1},{4,6,52},{2,7,68},{3,6,38},{5,7,22},{5,6,13},{5,6,4},{5,6,13},{8,0,51},{5,6,34},{4,6,1},{2,6,37},{16,0,51},
+{2,6,37},{4,8,37},{4,8,37},{4,8,37},{4,6,36},{4,7,8},{4,6,1},{4,6,1},{4,5,5},{3,6,11},{4,5,9},{5,6,4},{5,6,4},{5,6,4},{5,5,8},{5,5,8},{4,6,1},{4,6,1},{4,5,5},{15,0,8},{4,5,5},{8,1,18},{4,7,4},{5,6,0},{4,6,0},{8,1,18},{17,0,18},{4,6,0},{0,6,36},{17,0,18},{0,6,36},{4,0,36},
+{4,0,36},{4,0,36},{4,0,36},{4,6,1},{4,6,1},{4,6,1},{4,5,1},{3,6,2},{3,6,2},{5,10,54},{5,8,40},{5,7,61},{5,7,36},{5,9,51},{5,7,37},{5,7,1},{5,7,52},{3,8,60},{4,7,40},{6,8,22},{6,7,13},{6,7,4},{6,7,13},{9,1,51},{4,8,29},{5,7,1},{3,7,37},{19,0,51},{3,7,37},{5,9,37},{5,9,37},{5,9,37},
+{5,7,36},{5,8,8},{5,7,1},{5,7,1},{5,6,5},{4,7,8},{5,6,9},{6,7,4},{6,7,4},{6,7,4},{6,6,8},{9,0,8},{5,7,1},{5,7,1},{5,6,5},{18,0,8},{5,6,5},{10,0,18},{5,8,4},{6,7,0},{5,7,0},{10,0,18},{18,1,18},{5,7,0},{0,7,36},{18,1,18},{0,7,36},{5,0,36},{5,0,36},{5,0,36},{5,0,36},{5,7,1},
+{5,7,1},{5,7,1},{5,6,1},{4,7,4},{4,7,4},{6,11,54},{6,9,40},{6,8,62},{6,8,38},{6,10,51},{6,8,27},{6,8,3},{6,7,69},{4,9,60},{5,8,54},{7,9,22},{7,8,9},{7,8,6},{7,8,21},{11,0,51},{6,8,27},{6,8,3},{4,8,50},{22,0,51},{4,8,50},{6,10,37},{6,10,37},{6,10,37},{6,8,37},{6,9,8},{6,8,2},{6,8,2},
+{6,7,5},{5,8,8},{6,7,9},{7,8,5},{7,8,5},{7,8,5},{7,7,8},{10,1,8},{6,8,2},{6,8,2},{6,7,5},{21,0,8},{6,7,5},{11,1,18},{6,9,4},{7,8,2},{6,8,2},{11,1,18},{19,2,18},{6,8,2},{0,8,50},{19,2,18},{0,8,50},{6,0,36},{6,0,36},{6,0,36},{6,0,36},{6,8,1},{6,8,1},{6,8,1},{6,7,1},{5,8,4},
+{5,8,4},{7,12,68},{7,10,60},{8,9,68},{7,9,50},{7,11,53},{7,10,28},{7,9,5},{7,9,53},{7,9,68},{6,9,38},{8,10,22},{8,9,13},{8,9,4},{8,9,13},{12,1,52},{7,10,27},{7,9,4},{5,9,37},{25,0,52},{5,9,37},{7,11,50},{7,11,50},{7,11,50},{7,9,50},{7,10,11},{7,9,5},{7,9,5},{7,8,6},{6,9,11},{7,8,9},{8,9,4},
+{8,9,4},{8,9,4},{8,8,8},{12,0,8},{7,9,4},{7,9,4},{7,8,5},{24,0,8},{7,8,5},{13,0,18},{8,9,9},{8,9,0},{7,9,0},{13,0,18},{26,0,18},{7,9,0},{0,9,36},{26,0,18},{0,9,36},{7,0,50},{7,0,50},{7,0,50},{7,0,50},{7,10,2},{7,10,2},{7,10,2},{7,8,2},{6,9,2},{6,9,2},{8,13,54},{8,11,40},{8,10,61},
+{8,10,36},{8,12,51},{8,10,37},{8,10,1},{8,10,52},{6,11,68},{7,10,38},{9,11,22},{9,10,13},{9,10,4},{9,10,13},{12,4,51},{9,10,34},{8,10,1},{6,10,37},{28,0,51},{6,10,37},{8,12,37},{8,12,37},{8,12,37},{8,10,36},{8,11,8},{8,10,1},{8,10,1},{8,9,5},{7,10,11},{8,9,9},{9,10,4},{9,10,4},{9,10,4},{9,9,8},{13,1,8},
+{8,10,1},{8,10,1},{8,9,5},{27,0,8},{8,9,5},{14,1,18},{8,11,4},{9,10,0},{8,10,0},{14,1,18},{29,0,18},{8,10,0},{0,10,36},{29,0,18},{0,10,36},{8,0,36},{8,0,36},{8,0,36},{8,0,36},{8,10,1},{8,10,1},{8,10,1},{8,9,1},{7,10,2},{7,10,2},{9,14,54},{9,12,40},{9,11,61},{9,11,36},{9,13,51},{9,11,37},{9,11,1},
+{9,11,52},{7,12,60},{8,11,40},{10,12,22},{10,11,13},{10,11,4},{10,11,13},{13,5,51},{8,12,29},{9,11,1},{7,11,37},{31,0,51},{7,11,37},{9,13,37},{9,13,37},{9,13,37},{9,11,36},{9,12,8},{9,11,1},{9,11,1},{9,10,5},{8,11,8},{9,10,9},{10,11,4},{10,11,4},{10,11,4},{10,10,8},{15,0,8},{9,11,1},{9,11,1},{9,10,5},{30,0,8},
+{9,10,5},{15,2,18},{9,12,4},{10,11,0},{9,11,0},{15,2,18},{30,1,18},{9,11,0},{0,11,36},{30,1,18},{0,11,36},{9,0,36},{9,0,36},{9,0,36},{9,0,36},{9,11,1},{9,11,1},{9,11,1},{9,10,1},{8,11,4},{8,11,4},{10,15,54},{10,13,40},{10,12,62},{10,12,38},{10,14,51},{10,12,27},{10,12,3},{10,11,69},{8,13,60},{9,12,54},{11,13,22},
+{11,12,9},{11,12,6},{11,12,21},{17,0,51},{10,12,27},{10,12,3},{8,12,50},{30,2,51},{8,12,50},{10,14,37},{10,14,37},{10,14,37},{10,12,37},{10,13,8},{10,12,2},{10,12,2},{10,11,5},{9,12,8},{10,11,9},{11,12,5},{11,12,5},{11,12,5},{11,11,8},{16,1,8},{10,12,2},{10,12,2},{10,11,5},{31,1,8},{10,11,5},{15,5,18},{10,13,4},{11,12,2},
+{10,12,2},{15,5,18},{31,2,18},{10,12,2},{0,12,50},{31,2,18},{0,12,50},{10,0,36},{10,0,36},{10,0,36},{10,0,36},{10,12,1},{10,12,1},{10,12,1},{10,11,1},{9,12,4},{9,12,4},{11,16,68},{11,14,60},{12,13,68},{11,13,50},{11,15,53},{11,14,28},{11,13,5},{11,13,53},{11,13,68},{10,13,38},{12,14,22},{12,13,13},{12,13,4},{12,13,13},{18,1,52},
+{11,14,27},{11,13,4},{9,13,37},{31,3,52},{9,13,37},{11,15,50},{11,15,50},{11,15,50},{11,13,50},{11,14,11},{11,13,5},{11,13,5},{11,12,6},{10,13,11},{11,12,9},{12,13,4},{12,13,4},{12,13,4},{12,12,8},{16,4,8},{11,13,4},{11,13,4},{11,12,5},{28,4,8},{11,12,5},{19,0,18},{12,13,9},{12,13,0},{11,13,0},{19,0,18},{30,4,18},{11,13,0},
+{0,13,36},{30,4,18},{0,13,36},{11,0,50},{11,0,50},{11,0,50},{11,0,50},{11,14,2},{11,14,2},{11,14,2},{11,12,2},{10,13,2},{10,13,2},{12,17,54},{12,15,40},{12,14,61},{12,14,36},{12,16,51},{12,14,37},{12,14,1},{12,14,52},{10,15,68},{11,14,38},{13,15,22},{13,14,13},{13,14,4},{13,14,13},{20,0,51},{13,14,34},{12,14,1},{10,14,37},{24,8,51},
+{10,14,37},{12,16,37},{12,16,37},{12,16,37},{12,14,36},{12,15,8},{12,14,1},{12,14,1},{12,13,5},{11,14,11},{12,13,9},{13,14,4},{13,14,4},{13,14,4},{13,13,8},{17,5,8},{12,14,1},{12,14,1},{12,13,5},{31,4,8},{12,13,5},{20,1,18},{12,15,4},{13,14,0},{12,14,0},{20,1,18},{31,5,18},{12,14,0},{0,14,36},{31,5,18},{0,14,36},{12,0,36},
+{12,0,36},{12,0,36},{12,0,36},{12,14,1},{12,14,1},{12,14,1},{12,13,1},{11,14,2},{11,14,2},{13,18,54},{13,16,40},{13,15,61},{13,15,36},{13,17,51},{13,15,37},{13,15,1},{13,15,52},{11,16,60},{12,15,40},{14,16,22},{14,15,13},{14,15,4},{14,15,13},{21,1,51},{12,16,29},{13,15,1},{11,15,37},{27,8,51},{11,15,37},{13,17,37},{13,17,37},{13,17,37},
+{13,15,36},{13,16,8},{13,15,1},{13,15,1},{13,14,5},{12,15,8},{13,14,9},{14,15,4},{14,15,4},{14,15,4},{14,14,8},{21,0,8},{13,15,1},{13,15,1},{13,14,5},{30,6,8},{13,14,5},{22,0,18},{13,16,4},{14,15,0},{13,15,0},{22,0,18},{30,7,18},{13,15,0},{0,15,36},{30,7,18},{0,15,36},{13,0,36},{13,0,36},{13,0,36},{13,0,36},{13,15,1},
+{13,15,1},{13,15,1},{13,14,1},{12,15,4},{12,15,4},{14,19,54},{14,17,40},{14,16,62},{14,16,38},{14,18,51},{14,16,27},{14,16,3},{14,15,69},{12,17,60},{13,16,54},{15,17,22},{15,16,9},{15,16,6},{15,16,21},{23,0,51},{14,16,27},{14,16,3},{12,16,50},{30,8,51},{12,16,50},{14,18,37},{14,18,37},{14,18,37},{14,16,37},{14,17,8},{14,16,2},{14,16,2},
+{14,15,5},{13,16,8},{14,15,9},{15,16,5},{15,16,5},{15,16,5},{15,15,8},{22,1,8},{14,16,2},{14,16,2},{14,15,5},{31,7,8},{14,15,5},{23,1,18},{14,17,4},{15,16,2},{14,16,2},{23,1,18},{27,10,18},{14,16,2},{0,16,50},{27,10,18},{0,16,50},{14,0,36},{14,0,36},{14,0,36},{14,0,36},{14,16,1},{14,16,1},{14,16,1},{14,15,1},{13,16,4},
+{13,16,4},{15,20,68},{15,18,60},{16,17,68},{15,17,50},{15,19,53},{15,18,28},{15,17,5},{15,17,53},{15,17,68},{14,17,38},{16,18,22},{16,17,13},{16,17,4},{16,17,13},{24,1,52},{15,18,27},{15,17,4},{13,17,37},{31,9,52},{13,17,37},{15,19,50},{15,19,50},{15,19,50},{15,17,50},{15,18,11},{15,17,5},{15,17,5},{15,16,6},{14,17,11},{15,16,9},{16,17,4},
+{16,17,4},{16,17,4},{16,16,8},{24,0,8},{15,17,4},{15,17,4},{15,16,5},{24,12,8},{15,16,5},{25,0,18},{16,17,9},{16,17,0},{15,17,0},{25,0,18},{30,10,18},{15,17,0},{0,17,36},{30,10,18},{0,17,36},{15,0,50},{15,0,50},{15,0,50},{15,0,50},{15,18,2},{15,18,2},{15,18,2},{15,16,2},{14,17,2},{14,17,2},{16,21,54},{16,19,40},{16,18,61},
+{16,18,36},{16,20,51},{16,18,37},{16,18,1},{16,18,52},{14,19,68},{15,18,38},{17,19,22},{17,18,13},{17,18,4},{17,18,13},{24,4,51},{17,18,34},{16,18,1},{14,18,37},{28,12,51},{14,18,37},{16,20,37},{16,20,37},{16,20,37},{16,18,36},{16,19,8},{16,18,1},{16,18,1},{16,17,5},{15,18,11},{16,17,9},{17,18,4},{17,18,4},{17,18,4},{17,17,8},{25,1,8},
+{16,18,1},{16,18,1},{16,17,5},{27,12,8},{16,17,5},{26,1,18},{16,19,4},{17,18,0},{16,18,0},{26,1,18},{31,11,18},{16,18,0},{0,18,36},{31,11,18},{0,18,36},{16,0,36},{16,0,36},{16,0,36},{16,0,36},{16,18,1},{16,18,1},{16,18,1},{16,17,1},{15,18,2},{15,18,2},{17,22,54},{17,20,40},{17,19,61},{17,19,36},{17,21,51},{17,19,37},{17,19,1},
+{17,19,52},{15,20,60},{16,19,40},{18,20,22},{18,19,13},{18,19,4},{18,19,13},{25,5,51},{16,20,29},{17,19,1},{15,19,37},{31,12,51},{15,19,37},{17,21,37},{17,21,37},{17,21,37},{17,19,36},{17,20,8},{17,19,1},{17,19,1},{17,18,5},{16,19,8},{17,18,9},{18,19,4},{18,19,4},{18,19,4},{18,18,8},{27,0,8},{17,19,1},{17,19,1},{17,18,5},{30,12,8},
+{17,18,5},{27,2,18},{17,20,4},{18,19,0},{17,19,0},{27,2,18},{30,13,18},{17,19,0},{0,19,36},{30,13,18},{0,19,36},{17,0,36},{17,0,36},{17,0,36},{17,0,36},{17,19,1},{17,19,1},{17,19,1},{17,18,1},{16,19,4},{16,19,4},{18,23,54},{18,21,40},{18,20,62},{18,20,38},{18,22,51},{18,20,27},{18,20,3},{18,19,69},{16,21,60},{17,20,54},{19,21,22},
+{19,20,9},{19,20,6},{19,20,21},{29,0,51},{18,20,27},{18,20,3},{16,20,50},{30,14,51},{16,20,50},{18,22,37},{18,22,37},{18,22,37},{18,20,37},{18,21,8},{18,20,2},{18,20,2},{18,19,5},{17,20,8},{18,19,9},{19,20,5},{19,20,5},{19,20,5},{19,19,8},{28,1,8},{18,20,2},{18,20,2},{18,19,5},{31,13,8},{18,19,5},{27,5,18},{18,21,4},{19,20,2},
+{18,20,2},{27,5,18},{31,14,18},{18,20,2},{0,20,50},{31,14,18},{0,20,50},{18,0,36},{18,0,36},{18,0,36},{18,0,36},{18,20,1},{18,20,1},{18,20,1},{18,19,1},{17,20,4},{17,20,4},{19,24,68},{19,22,60},{20,21,68},{19,21,50},{19,23,53},{19,22,28},{19,21,5},{19,21,53},{19,21,68},{18,21,38},{20,22,22},{20,21,13},{20,21,4},{20,21,13},{30,1,52},
+{19,22,27},{19,21,4},{17,21,37},{31,15,52},{17,21,37},{19,23,50},{19,23,50},{19,23,50},{19,21,50},{19,22,11},{19,21,5},{19,21,5},{19,20,6},{18,21,11},{19,20,9},{20,21,4},{20,21,4},{20,21,4},{20,20,8},{28,4,8},{19,21,4},{19,21,4},{19,20,5},{28,16,8},{19,20,5},{31,0,18},{20,21,9},{20,21,0},{19,21,0},{31,0,18},{30,16,18},{19,21,0},
+{0,21,36},{30,16,18},{0,21,36},{19,0,50},{19,0,50},{19,0,50},{19,0,50},{19,22,2},{19,22,2},{19,22,2},{19,20,2},{18,21,2},{18,21,2},{20,25,54},{20,23,40},{20,22,61},{20,22,36},{20,24,51},{20,22,37},{20,22,1},{20,22,52},{18,23,68},{19,22,38},{21,23,22},{21,22,13},{21,22,4},{21,22,13},{28,8,51},{21,22,34},{20,22,1},{18,22,37},{24,20,51},
+{18,22,37},{20,24,37},{20,24,37},{20,24,37},{20,22,36},{20,23,8},{20,22,1},{20,22,1},{20,21,5},{19,22,11},{20,21,9},{21,22,4},{21,22,4},{21,22,4},{21,21,8},{29,5,8},{20,22,1},{20,22,1},{20,21,5},{31,16,8},{20,21,5},{31,3,18},{20,23,4},{21,22,0},{20,22,0},{31,3,18},{31,17,18},{20,22,0},{0,22,36},{31,17,18},{0,22,36},{20,0,36},
+{20,0,36},{20,0,36},{20,0,36},{20,22,1},{20,22,1},{20,22,1},{20,21,1},{19,22,2},{19,22,2},{21,26,54},{21,24,40},{21,23,61},{21,23,36},{21,25,51},{21,23,37},{21,23,1},{21,23,52},{19,24,60},{20,23,40},{22,24,22},{22,23,13},{22,23,4},{22,23,13},{29,9,51},{20,24,29},{21,23,1},{19,23,37},{27,20,51},{19,23,37},{21,25,37},{21,25,37},{21,25,37},
+{21,23,36},{21,24,8},{21,23,1},{21,23,1},{21,22,5},{20,23,8},{21,22,9},{22,23,4},{22,23,4},{22,23,4},{22,22,8},{31,4,8},{21,23,1},{21,23,1},{21,22,5},{30,18,8},{21,22,5},{31,6,18},{21,24,4},{22,23,0},{21,23,0},{31,6,18},{30,19,18},{21,23,0},{0,23,36},{30,19,18},{0,23,36},{21,0,36},{21,0,36},{21,0,36},{21,0,36},{21,23,1},
+{21,23,1},{21,23,1},{21,22,1},{20,23,4},{20,23,4},{22,27,54},{22,25,40},{22,24,62},{22,24,38},{22,26,51},{22,24,27},{22,24,3},{22,23,69},{20,25,60},{21,24,54},{23,25,22},{23,24,9},{23,24,6},{23,24,21},{31,8,51},{22,24,27},{22,24,3},{20,24,50},{30,20,51},{20,24,50},{22,26,37},{22,26,37},{22,26,37},{22,24,37},{22,25,8},{22,24,2},{22,24,2},
+{22,23,5},{21,24,8},{22,23,9},{23,24,5},{23,24,5},{23,24,5},{23,23,8},{31,7,8},{22,24,2},{22,24,2},{22,23,5},{31,19,8},{22,23,5},{31,9,18},{22,25,4},{23,24,2},{22,24,2},{31,9,18},{27,22,18},{22,24,2},{0,24,50},{27,22,18},{0,24,50},{22,0,36},{22,0,36},{22,0,36},{22,0,36},{22,24,1},{22,24,1},{22,24,1},{22,23,1},{21,24,4},
+{21,24,4},{23,28,68},{23,26,60},{24,25,68},{23,25,50},{23,27,53},{23,26,28},{23,25,5},{23,25,53},{23,25,68},{22,25,38},{24,26,22},{24,25,13},{24,25,4},{24,25,13},{31,11,52},{23,26,27},{23,25,4},{21,25,37},{31,21,52},{21,25,37},{23,27,50},{23,27,50},{23,27,50},{23,25,50},{23,26,11},{23,25,5},{23,25,5},{23,24,6},{22,25,11},{23,24,9},{24,25,4},
+{24,25,4},{24,25,4},{24,24,8},{28,16,8},{23,25,4},{23,25,4},{23,24,5},{24,24,8},{23,24,5},{31,12,18},{24,25,9},{24,25,0},{23,25,0},{31,12,18},{30,22,18},{23,25,0},{0,25,36},{30,22,18},{0,25,36},{23,0,50},{23,0,50},{23,0,50},{23,0,50},{23,26,2},{23,26,2},{23,26,2},{23,24,2},{22,25,2},{22,25,2},{24,29,54},{24,27,40},{24,26,61},
+{24,26,36},{24,28,51},{24,26,37},{24,26,1},{24,26,52},{22,27,68},{23,26,38},{25,27,22},{25,26,13},{25,26,4},{25,26,13},{28,20,51},{25,26,34},{24,26,1},{22,26,37},{28,24,51},{22,26,37},{24,28,37},{24,28,37},{24,28,37},{24,26,36},{24,27,8},{24,26,1},{24,26,1},{24,25,5},{23,26,11},{24,25,9},{25,26,4},{25,26,4},{25,26,4},{25,25,8},{29,17,8},
+{24,26,1},{24,26,1},{24,25,5},{27,24,8},{24,25,5},{31,15,18},{24,27,4},{25,26,0},{24,26,0},{31,15,18},{31,23,18},{24,26,0},{0,26,36},{31,23,18},{0,26,36},{24,0,36},{24,0,36},{24,0,36},{24,0,36},{24,26,1},{24,26,1},{24,26,1},{24,25,1},{23,26,2},{23,26,2},{25,30,54},{25,28,40},{25,27,61},{25,27,36},{25,29,51},{25,27,37},{25,27,1},
+{25,27,52},{23,28,60},{24,27,40},{26,28,22},{26,27,13},{26,27,4},{26,27,13},{29,21,51},{24,28,29},{25,27,1},{23,27,37},{31,24,51},{23,27,37},{25,29,37},{25,29,37},{25,29,37},{25,27,36},{25,28,8},{25,27,1},{25,27,1},{25,26,5},{24,27,8},{25,26,9},{26,27,4},{26,27,4},{26,27,4},{26,26,8},{31,16,8},{25,27,1},{25,27,1},{25,26,5},{30,24,8},
+{25,26,5},{31,18,18},{25,28,4},{26,27,0},{25,27,0},{31,18,18},{30,25,18},{25,27,0},{0,27,36},{30,25,18},{0,27,36},{25,0,36},{25,0,36},{25,0,36},{25,0,36},{25,27,1},{25,27,1},{25,27,1},{25,26,1},{24,27,4},{24,27,4},{26,31,54},{26,29,40},{26,28,62},{26,28,38},{26,30,51},{26,28,27},{26,28,3},{26,27,69},{24,29,60},{25,28,54},{27,29,22},
+{27,28,9},{27,28,6},{27,28,21},{31,20,51},{26,28,27},{26,28,3},{24,28,50},{30,26,51},{24,28,50},{26,30,37},{26,30,37},{26,30,37},{26,28,37},{26,29,8},{26,28,2},{26,28,2},{26,27,5},{25,28,8},{26,27,9},{27,28,5},{27,28,5},{27,28,5},{27,27,8},{31,19,8},{26,28,2},{26,28,2},{26,27,5},{31,25,8},{26,27,5},{31,21,18},{26,29,4},{27,28,2},
+{26,28,2},{31,21,18},{31,26,18},{26,28,2},{0,28,50},{31,26,18},{0,28,50},{26,0,36},{26,0,36},{26,0,36},{26,0,36},{26,28,1},{26,28,1},{26,28,1},{26,27,1},{25,28,4},{25,28,4},{28,30,86},{27,30,60},{28,29,68},{27,29,50},{27,31,53},{27,30,28},{27,29,5},{27,29,53},{27,29,68},{26,29,38},{28,30,22},{28,29,13},{28,29,4},{28,29,13},{31,23,52},
+{27,30,27},{27,29,4},{25,29,37},{31,27,52},{25,29,37},{27,31,50},{27,31,50},{27,31,50},{27,29,50},{27,30,11},{27,29,5},{27,29,5},{27,28,6},{26,29,11},{27,28,9},{28,29,4},{28,29,4},{28,29,4},{28,28,8},{28,28,8},{27,29,4},{27,29,4},{27,28,5},{28,28,8},{27,28,5},{31,24,18},{28,29,9},{28,29,0},{27,29,0},{31,24,18},{30,28,18},{27,29,0},
+{0,29,36},{30,28,18},{0,29,36},{27,0,50},{27,0,50},{27,0,50},{27,0,50},{27,30,2},{27,30,2},{27,30,2},{27,28,2},{26,29,2},{26,29,2},{29,31,86},{28,31,40},{28,30,61},{28,30,36},{28,31,72},{28,30,37},{28,30,1},{28,30,52},{26,31,68},{27,30,38},{29,31,22},{29,30,13},{29,30,4},{29,30,13},{31,26,52},{29,30,34},{28,30,1},{26,30,37},{30,29,52},
+{26,30,37},{28,31,40},{28,31,40},{28,31,40},{28,30,36},{28,31,8},{28,30,1},{28,30,1},{28,29,5},{27,30,11},{28,29,9},{29,30,4},{29,30,4},{29,30,4},{29,29,8},{29,29,8},{28,30,1},{28,30,1},{28,29,5},{31,28,8},{28,29,5},{31,27,18},{28,31,4},{29,30,0},{28,30,0},{31,27,18},{31,29,18},{28,30,0},{0,30,36},{31,29,18},{0,30,36},{28,0,36},
+{28,0,36},{28,0,36},{28,0,36},{28,30,1},{28,30,1},{28,30,1},{28,29,1},{27,30,2},{27,30,2},{30,31,104},{30,31,77},{29,31,61},{29,31,36},{30,31,116},{29,31,37},{29,31,1},{29,31,52},{28,31,72},{28,31,40},{30,31,40},{30,31,13},{30,31,4},{30,31,13},{31,29,52},{30,31,34},{29,31,1},{27,31,37},{31,30,52},{27,31,37},{29,31,61},{29,31,61},{29,31,61},
+{29,31,36},{29,31,26},{29,31,1},{29,31,1},{29,30,5},{28,31,8},{29,30,9},{30,31,4},{30,31,4},{30,31,4},{30,30,8},{31,28,8},{29,31,1},{29,31,1},{29,30,5},{30,30,8},{29,30,5},{31,30,18},{30,31,9},{30,31,0},{29,31,0},{31,30,18},{30,31,18},{29,31,0},{0,31,36},{30,31,18},{0,31,36},{29,0,36},{29,0,36},{29,0,36},{29,0,36},{29,31,1},
+{29,31,1},{29,31,1},{29,30,1},{28,31,4},{28,31,4},{31,31,68},{31,31,68},{31,31,68},{30,31,45},{31,31,68},{30,31,34},{30,31,25},{30,31,1},{30,31,23},{30,31,5},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{30,31,1},{31,31,68},{31,31,68},{31,31,68},{30,31,45},{30,31,52},{30,31,25},{30,31,25},
+{30,31,1},{30,31,14},{30,31,5},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{30,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{30,0,36},{30,0,36},{30,0,36},{30,0,36},{30,31,16},{30,31,16},{30,31,16},{30,31,1},{30,31,5},
+{30,31,5},{0,4,72},{0,3,10},{0,2,1},{0,2,26},{0,3,154},{0,2,99},{0,2,51},{0,1,115},{0,1,173},{0,1,119},{0,4,72},{0,3,10},{0,2,1},{0,2,26},{1,1,154},{0,2,99},{0,2,51},{0,1,115},{3,0,154},{0,1,115},{0,2,0},{0,2,0},{0,2,0},{0,1,0},{0,1,13},{0,1,4},{0,1,4},{0,0,25},{0,0,25},{0,0,25},{0,2,0},
+{0,2,0},{0,2,0},{0,1,0},{0,1,13},{0,1,4},{0,1,4},{0,0,25},{1,0,13},{0,0,25},{0,4,72},{0,3,10},{0,2,1},{0,2,26},{0,4,72},{4,0,72},{0,2,26},{0,1,90},{4,0,72},{0,1,90},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,7,81},{0,5,13},{0,3,35},
+{0,3,19},{0,5,244},{0,3,115},{0,3,35},{0,2,139},{0,2,308},{0,2,164},{0,7,81},{0,5,13},{1,3,26},{0,3,19},{2,1,244},{0,3,115},{0,3,35},{0,2,139},{5,0,244},{0,2,139},{0,5,9},{0,5,9},{0,5,9},{0,2,18},{0,3,50},{0,2,13},{0,2,13},{0,1,29},{0,1,72},{0,1,33},{0,5,9},{0,5,9},{0,5,9},{0,2,18},{1,1,50},
+{0,2,13},{0,2,13},{0,1,29},{3,0,50},{0,1,29},{1,5,72},{0,5,4},{1,3,1},{0,3,10},{1,5,72},{7,0,72},{0,3,10},{0,2,90},{7,0,72},{0,2,90},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,1},{0,1,1},{0,1,1},{0,1,4},{0,1,8},{0,1,8},{1,8,145},{1,6,77},{1,4,98},{1,4,82},{0,8,243},{0,5,76},{0,4,1},
+{0,3,115},{0,4,364},{0,3,179},{1,8,81},{1,6,13},{2,4,25},{1,4,18},{4,0,243},{0,5,76},{0,4,1},{0,3,115},{8,0,243},{0,3,115},{1,6,73},{1,6,73},{1,6,73},{1,3,82},{0,6,50},{0,4,1},{0,4,1},{0,2,26},{0,3,114},{0,2,51},{1,6,9},{1,6,9},{1,6,9},{1,3,18},{3,0,50},{0,4,1},{0,4,1},{0,2,26},{6,0,50},
+{0,2,26},{5,0,72},{1,6,4},{2,4,0},{0,4,1},{5,0,72},{10,0,72},{0,4,1},{0,3,90},{10,0,72},{0,3,90},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,4,0},{0,4,0},{0,4,0},{0,2,1},{0,2,26},{0,2,26},{2,9,162},{2,7,94},{2,5,115},{2,5,99},{1,9,244},{1,6,77},{1,5,2},{1,4,106},{0,5,300},{0,4,105},{2,9,81},
+{2,7,13},{3,5,25},{2,5,18},{5,1,243},{1,6,76},{1,5,1},{0,4,89},{11,0,243},{0,4,89},{2,7,90},{2,7,90},{2,7,90},{2,4,94},{1,7,51},{1,5,2},{1,5,2},{1,3,27},{0,4,74},{0,3,35},{2,7,9},{2,7,9},{2,7,9},{2,4,13},{4,1,50},{1,5,1},{1,5,1},{0,4,25},{9,0,50},{0,4,25},{6,1,72},{2,7,4},{3,5,0},
+{1,5,1},{6,1,72},{13,0,72},{1,5,1},{0,4,80},{13,0,72},{0,4,80},{2,0,90},{2,0,90},{2,0,90},{2,0,90},{1,5,1},{1,5,1},{1,5,1},{1,3,2},{0,3,10},{0,3,10},{3,10,154},{3,8,84},{3,6,117},{3,6,85},{2,10,244},{2,7,75},{2,6,2},{2,5,106},{0,7,253},{0,5,100},{3,10,90},{3,8,20},{4,6,26},{3,6,21},{7,0,244},
+{2,7,75},{2,6,2},{0,5,91},{14,0,244},{0,5,91},{3,8,80},{3,8,80},{3,8,80},{3,6,84},{2,8,52},{2,6,1},{2,6,1},{2,5,25},{0,6,52},{0,5,19},{3,8,16},{3,8,16},{3,8,16},{3,6,20},{4,4,50},{2,6,1},{2,6,1},{0,5,10},{12,0,50},{0,5,10},{8,0,72},{3,8,4},{4,6,1},{2,6,1},{8,0,72},{16,0,72},{2,6,1},
+{0,5,90},{16,0,72},{0,5,90},{3,0,80},{3,0,80},{3,0,80},{3,0,80},{2,6,1},{2,6,1},{2,6,1},{2,4,1},{0,5,10},{0,5,10},{4,11,162},{4,9,94},{4,7,116},{4,7,100},{3,11,244},{3,8,76},{3,7,2},{3,6,106},{1,8,253},{1,6,100},{4,11,81},{4,9,13},{5,7,26},{4,7,19},{8,1,244},{3,8,76},{3,7,2},{1,6,91},{17,0,244},
+{1,6,91},{4,9,90},{4,9,90},{4,9,90},{4,6,99},{3,9,52},{3,7,1},{3,7,1},{3,6,25},{1,7,52},{1,6,19},{4,9,9},{4,9,9},{4,9,9},{4,6,18},{5,5,50},{3,7,1},{3,7,1},{1,6,10},{15,0,50},{1,6,10},{9,1,72},{4,9,4},{5,7,1},{3,7,1},{9,1,72},{19,0,72},{3,7,1},{0,6,90},{19,0,72},{0,6,90},{4,0,90},
+{4,0,90},{4,0,90},{4,0,90},{3,7,1},{3,7,1},{3,7,1},{3,5,1},{1,6,10},{1,6,10},{5,12,162},{5,10,94},{5,8,115},{5,8,99},{4,12,244},{4,9,77},{4,8,2},{4,7,116},{2,9,253},{2,7,100},{5,12,81},{5,10,13},{6,8,25},{5,8,18},{8,4,243},{4,9,76},{4,8,1},{2,7,91},{20,0,243},{2,7,91},{5,10,90},{5,10,90},{5,10,90},
+{5,7,99},{4,10,51},{4,8,2},{4,8,2},{4,6,27},{2,8,50},{2,7,19},{5,10,9},{5,10,9},{5,10,9},{5,7,18},{9,0,50},{4,8,1},{4,8,1},{2,7,10},{18,0,50},{2,7,10},{11,0,72},{5,10,4},{6,8,0},{4,8,1},{11,0,72},{22,0,72},{4,8,1},{0,7,90},{22,0,72},{0,7,90},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{4,8,1},
+{4,8,1},{4,8,1},{4,6,2},{2,7,10},{2,7,10},{6,13,162},{6,11,94},{6,9,115},{6,9,99},{5,13,244},{5,10,77},{5,9,2},{5,8,106},{3,10,253},{3,8,84},{6,13,81},{6,11,13},{7,9,25},{6,9,18},{9,5,243},{5,10,76},{5,9,1},{3,8,80},{23,0,243},{3,8,80},{6,11,90},{6,11,90},{6,11,90},{6,8,94},{5,11,51},{5,9,2},{5,9,2},
+{5,7,27},{3,9,50},{3,8,20},{6,11,9},{6,11,9},{6,11,9},{6,8,13},{10,1,50},{5,9,1},{5,9,1},{3,8,16},{21,0,50},{3,8,16},{12,1,72},{6,11,4},{7,9,0},{5,9,1},{12,1,72},{25,0,72},{5,9,1},{0,8,80},{25,0,72},{0,8,80},{6,0,90},{6,0,90},{6,0,90},{6,0,90},{5,9,1},{5,9,1},{5,9,1},{5,7,2},{3,8,4},
+{3,8,4},{7,14,154},{7,12,84},{7,10,117},{7,10,85},{6,14,244},{6,11,75},{6,10,2},{6,9,106},{4,11,253},{4,9,100},{7,14,90},{7,12,20},{8,10,26},{7,10,21},{13,0,244},{6,11,75},{6,10,2},{4,9,91},{26,0,244},{4,9,91},{7,12,80},{7,12,80},{7,12,80},{7,10,84},{6,12,52},{6,10,1},{6,10,1},{6,9,25},{4,10,52},{4,9,19},{7,12,16},
+{7,12,16},{7,12,16},{7,10,20},{12,0,50},{6,10,1},{6,10,1},{4,9,10},{24,0,50},{4,9,10},{12,4,72},{7,12,4},{8,10,1},{6,10,1},{12,4,72},{28,0,72},{6,10,1},{0,9,90},{28,0,72},{0,9,90},{7,0,80},{7,0,80},{7,0,80},{7,0,80},{6,10,1},{6,10,1},{6,10,1},{6,8,1},{4,9,10},{4,9,10},{8,15,162},{8,13,94},{8,11,116},
+{8,11,100},{7,15,244},{7,12,76},{7,11,2},{7,10,106},{5,12,253},{5,10,100},{8,15,81},{8,13,13},{9,11,26},{8,11,19},{14,1,244},{7,12,76},{7,11,2},{5,10,91},{29,0,244},{5,10,91},{8,13,90},{8,13,90},{8,13,90},{8,10,99},{7,13,52},{7,11,1},{7,11,1},{7,10,25},{5,11,52},{5,10,19},{8,13,9},{8,13,9},{8,13,9},{8,10,18},{13,1,50},
+{7,11,1},{7,11,1},{5,10,10},{27,0,50},{5,10,10},{13,5,72},{8,13,4},{9,11,1},{7,11,1},{13,5,72},{31,0,72},{7,11,1},{0,10,90},{31,0,72},{0,10,90},{8,0,90},{8,0,90},{8,0,90},{8,0,90},{7,11,1},{7,11,1},{7,11,1},{7,9,1},{5,10,10},{5,10,10},{9,16,162},{9,14,94},{9,12,115},{9,12,99},{8,16,244},{8,13,77},{8,12,2},
+{8,11,116},{6,13,253},{6,11,100},{9,16,81},{9,14,13},{10,12,25},{9,12,18},{16,0,243},{8,13,76},{8,12,1},{6,11,91},{24,4,243},{6,11,91},{9,14,90},{9,14,90},{9,14,90},{9,11,99},{8,14,51},{8,12,2},{8,12,2},{8,10,27},{6,12,50},{6,11,19},{9,14,9},{9,14,9},{9,14,9},{9,11,18},{15,0,50},{8,12,1},{8,12,1},{6,11,10},{30,0,50},
+{6,11,10},{17,0,72},{9,14,4},{10,12,0},{8,12,1},{17,0,72},{30,2,72},{8,12,1},{0,11,90},{30,2,72},{0,11,90},{9,0,90},{9,0,90},{9,0,90},{9,0,90},{8,12,1},{8,12,1},{8,12,1},{8,10,2},{6,11,10},{6,11,10},{10,17,162},{10,15,94},{10,13,115},{10,13,99},{9,17,244},{9,14,77},{9,13,2},{9,12,106},{7,14,253},{7,12,84},{10,17,81},
+{10,15,13},{11,13,25},{10,13,18},{17,1,243},{9,14,76},{9,13,1},{7,12,80},{27,4,243},{7,12,80},{10,15,90},{10,15,90},{10,15,90},{10,12,94},{9,15,51},{9,13,2},{9,13,2},{9,11,27},{7,13,50},{7,12,20},{10,15,9},{10,15,9},{10,15,9},{10,12,13},{16,1,50},{9,13,1},{9,13,1},{7,12,16},{31,1,50},{7,12,16},{18,1,72},{10,15,4},{11,13,0},
+{9,13,1},{18,1,72},{31,3,72},{9,13,1},{0,12,80},{31,3,72},{0,12,80},{10,0,90},{10,0,90},{10,0,90},{10,0,90},{9,13,1},{9,13,1},{9,13,1},{9,11,2},{7,12,4},{7,12,4},{11,18,154},{11,16,84},{11,14,117},{11,14,85},{10,18,244},{10,15,75},{10,14,2},{10,13,106},{8,15,253},{8,13,100},{11,18,90},{11,16,20},{12,14,26},{11,14,21},{19,0,244},
+{10,15,75},{10,14,2},{8,13,91},{30,4,244},{8,13,91},{11,16,80},{11,16,80},{11,16,80},{11,14,84},{10,16,52},{10,14,1},{10,14,1},{10,13,25},{8,14,52},{8,13,19},{11,16,16},{11,16,16},{11,16,16},{11,14,20},{16,4,50},{10,14,1},{10,14,1},{8,13,10},{28,4,50},{8,13,10},{20,0,72},{11,16,4},{12,14,1},{10,14,1},{20,0,72},{24,8,72},{10,14,1},
+{0,13,90},{24,8,72},{0,13,90},{11,0,80},{11,0,80},{11,0,80},{11,0,80},{10,14,1},{10,14,1},{10,14,1},{10,12,1},{8,13,10},{8,13,10},{12,19,162},{12,17,94},{12,15,116},{12,15,100},{11,19,244},{11,16,76},{11,15,2},{11,14,106},{9,16,253},{9,14,100},{12,19,81},{12,17,13},{13,15,26},{12,15,19},{20,1,244},{11,16,76},{11,15,2},{9,14,91},{31,5,244},
+{9,14,91},{12,17,90},{12,17,90},{12,17,90},{12,14,99},{11,17,52},{11,15,1},{11,15,1},{11,14,25},{9,15,52},{9,14,19},{12,17,9},{12,17,9},{12,17,9},{12,14,18},{17,5,50},{11,15,1},{11,15,1},{9,14,10},{31,4,50},{9,14,10},{21,1,72},{12,17,4},{13,15,1},{11,15,1},{21,1,72},{27,8,72},{11,15,1},{0,14,90},{27,8,72},{0,14,90},{12,0,90},
+{12,0,90},{12,0,90},{12,0,90},{11,15,1},{11,15,1},{11,15,1},{11,13,1},{9,14,10},{9,14,10},{13,20,162},{13,18,94},{13,16,115},{13,16,99},{12,20,244},{12,17,77},{12,16,2},{12,15,116},{10,17,253},{10,15,100},{13,20,81},{13,18,13},{14,16,25},{13,16,18},{20,4,243},{12,17,76},{12,16,1},{10,15,91},{28,8,243},{10,15,91},{13,18,90},{13,18,90},{13,18,90},
+{13,15,99},{12,18,51},{12,16,2},{12,16,2},{12,14,27},{10,16,50},{10,15,19},{13,18,9},{13,18,9},{13,18,9},{13,15,18},{21,0,50},{12,16,1},{12,16,1},{10,15,10},{30,6,50},{10,15,10},{23,0,72},{13,18,4},{14,16,0},{12,16,1},{23,0,72},{30,8,72},{12,16,1},{0,15,90},{30,8,72},{0,15,90},{13,0,90},{13,0,90},{13,0,90},{13,0,90},{12,16,1},
+{12,16,1},{12,16,1},{12,14,2},{10,15,10},{10,15,10},{14,21,162},{14,19,94},{14,17,115},{14,17,99},{13,21,244},{13,18,77},{13,17,2},{13,16,106},{11,18,253},{11,16,84},{14,21,81},{14,19,13},{15,17,25},{14,17,18},{21,5,243},{13,18,76},{13,17,1},{11,16,80},{31,8,243},{11,16,80},{14,19,90},{14,19,90},{14,19,90},{14,16,94},{13,19,51},{13,17,2},{13,17,2},
+{13,15,27},{11,17,50},{11,16,20},{14,19,9},{14,19,9},{14,19,9},{14,16,13},{22,1,50},{13,17,1},{13,17,1},{11,16,16},{31,7,50},{11,16,16},{24,1,72},{14,19,4},{15,17,0},{13,17,1},{24,1,72},{31,9,72},{13,17,1},{0,16,80},{31,9,72},{0,16,80},{14,0,90},{14,0,90},{14,0,90},{14,0,90},{13,17,1},{13,17,1},{13,17,1},{13,15,2},{11,16,4},
+{11,16,4},{15,22,154},{15,20,84},{15,18,117},{15,18,85},{14,22,244},{14,19,75},{14,18,2},{14,17,106},{12,19,253},{12,17,100},{15,22,90},{15,20,20},{16,18,26},{15,18,21},{25,0,244},{14,19,75},{14,18,2},{12,17,91},{30,10,244},{12,17,91},{15,20,80},{15,20,80},{15,20,80},{15,18,84},{14,20,52},{14,18,1},{14,18,1},{14,17,25},{12,18,52},{12,17,19},{15,20,16},
+{15,20,16},{15,20,16},{15,18,20},{24,0,50},{14,18,1},{14,18,1},{12,17,10},{24,12,50},{12,17,10},{24,4,72},{15,20,4},{16,18,1},{14,18,1},{24,4,72},{28,12,72},{14,18,1},{0,17,90},{28,12,72},{0,17,90},{15,0,80},{15,0,80},{15,0,80},{15,0,80},{14,18,1},{14,18,1},{14,18,1},{14,16,1},{12,17,10},{12,17,10},{16,23,162},{16,21,94},{16,19,116},
+{16,19,100},{15,23,244},{15,20,76},{15,19,2},{15,18,106},{13,20,253},{13,18,100},{16,23,81},{16,21,13},{17,19,26},{16,19,19},{26,1,244},{15,20,76},{15,19,2},{13,18,91},{31,11,244},{13,18,91},{16,21,90},{16,21,90},{16,21,90},{16,18,99},{15,21,52},{15,19,1},{15,19,1},{15,18,25},{13,19,52},{13,18,19},{16,21,9},{16,21,9},{16,21,9},{16,18,18},{25,1,50},
+{15,19,1},{15,19,1},{13,18,10},{27,12,50},{13,18,10},{25,5,72},{16,21,4},{17,19,1},{15,19,1},{25,5,72},{31,12,72},{15,19,1},{0,18,90},{31,12,72},{0,18,90},{16,0,90},{16,0,90},{16,0,90},{16,0,90},{15,19,1},{15,19,1},{15,19,1},{15,17,1},{13,18,10},{13,18,10},{17,24,162},{17,22,94},{17,20,115},{17,20,99},{16,24,244},{16,21,77},{16,20,2},
+{16,19,116},{14,21,253},{14,19,100},{17,24,81},{17,22,13},{18,20,25},{17,20,18},{28,0,243},{16,21,76},{16,20,1},{14,19,91},{24,16,243},{14,19,91},{17,22,90},{17,22,90},{17,22,90},{17,19,99},{16,22,51},{16,20,2},{16,20,2},{16,18,27},{14,20,50},{14,19,19},{17,22,9},{17,22,9},{17,22,9},{17,19,18},{27,0,50},{16,20,1},{16,20,1},{14,19,10},{30,12,50},
+{14,19,10},{29,0,72},{17,22,4},{18,20,0},{16,20,1},{29,0,72},{30,14,72},{16,20,1},{0,19,90},{30,14,72},{0,19,90},{17,0,90},{17,0,90},{17,0,90},{17,0,90},{16,20,1},{16,20,1},{16,20,1},{16,18,2},{14,19,10},{14,19,10},{18,25,162},{18,23,94},{18,21,115},{18,21,99},{17,25,244},{17,22,77},{17,21,2},{17,20,106},{15,22,253},{15,20,84},{18,25,81},
+{18,23,13},{19,21,25},{18,21,18},{29,1,243},{17,22,76},{17,21,1},{15,20,80},{27,16,243},{15,20,80},{18,23,90},{18,23,90},{18,23,90},{18,20,94},{17,23,51},{17,21,2},{17,21,2},{17,19,27},{15,21,50},{15,20,20},{18,23,9},{18,23,9},{18,23,9},{18,20,13},{28,1,50},{17,21,1},{17,21,1},{15,20,16},{31,13,50},{15,20,16},{30,1,72},{18,23,4},{19,21,0},
+{17,21,1},{30,1,72},{31,15,72},{17,21,1},{0,20,80},{31,15,72},{0,20,80},{18,0,90},{18,0,90},{18,0,90},{18,0,90},{17,21,1},{17,21,1},{17,21,1},{17,19,2},{15,20,4},{15,20,4},{19,26,154},{19,24,84},{19,22,117},{19,22,85},{18,26,244},{18,23,75},{18,22,2},{18,21,106},{16,23,253},{16,21,100},{19,26,90},{19,24,20},{20,22,26},{19,22,21},{31,0,244},
+{18,23,75},{18,22,2},{16,21,91},{30,16,244},{16,21,91},{19,24,80},{19,24,80},{19,24,80},{19,22,84},{18,24,52},{18,22,1},{18,22,1},{18,21,25},{16,22,52},{16,21,19},{19,24,16},{19,24,16},{19,24,16},{19,22,20},{28,4,50},{18,22,1},{18,22,1},{16,21,10},{28,16,50},{16,21,10},{28,8,72},{19,24,4},{20,22,1},{18,22,1},{28,8,72},{24,20,72},{18,22,1},
+{0,21,90},{24,20,72},{0,21,90},{19,0,80},{19,0,80},{19,0,80},{19,0,80},{18,22,1},{18,22,1},{18,22,1},{18,20,1},{16,21,10},{16,21,10},{20,27,162},{20,25,94},{20,23,116},{20,23,100},{19,27,244},{19,24,76},{19,23,2},{19,22,106},{17,24,253},{17,22,100},{20,27,81},{20,25,13},{21,23,26},{20,23,19},{31,3,244},{19,24,76},{19,23,2},{17,22,91},{31,17,244},
+{17,22,91},{20,25,90},{20,25,90},{20,25,90},{20,22,99},{19,25,52},{19,23,1},{19,23,1},{19,22,25},{17,23,52},{17,22,19},{20,25,9},{20,25,9},{20,25,9},{20,22,18},{29,5,50},{19,23,1},{19,23,1},{17,22,10},{31,16,50},{17,22,10},{29,9,72},{20,25,4},{21,23,1},{19,23,1},{29,9,72},{27,20,72},{19,23,1},{0,22,90},{27,20,72},{0,22,90},{20,0,90},
+{20,0,90},{20,0,90},{20,0,90},{19,23,1},{19,23,1},{19,23,1},{19,21,1},{17,22,10},{17,22,10},{21,28,162},{21,26,94},{21,24,115},{21,24,99},{20,28,244},{20,25,77},{20,24,2},{20,23,116},{18,25,253},{18,23,100},{21,28,81},{21,26,13},{22,24,25},{21,24,18},{28,12,243},{20,25,76},{20,24,1},{18,23,91},{28,20,243},{18,23,91},{21,26,90},{21,26,90},{21,26,90},
+{21,23,99},{20,26,51},{20,24,2},{20,24,2},{20,22,27},{18,24,50},{18,23,19},{21,26,9},{21,26,9},{21,26,9},{21,23,18},{31,4,50},{20,24,1},{20,24,1},{18,23,10},{30,18,50},{18,23,10},{31,8,72},{21,26,4},{22,24,0},{20,24,1},{31,8,72},{30,20,72},{20,24,1},{0,23,90},{30,20,72},{0,23,90},{21,0,90},{21,0,90},{21,0,90},{21,0,90},{20,24,1},
+{20,24,1},{20,24,1},{20,22,2},{18,23,10},{18,23,10},{22,29,162},{22,27,94},{22,25,115},{22,25,99},{21,29,244},{21,26,77},{21,25,2},{21,24,106},{19,26,253},{19,24,84},{22,29,81},{22,27,13},{23,25,25},{22,25,18},{29,13,243},{21,26,76},{21,25,1},{19,24,80},{31,20,243},{19,24,80},{22,27,90},{22,27,90},{22,27,90},{22,24,94},{21,27,51},{21,25,2},{21,25,2},
+{21,23,27},{19,25,50},{19,24,20},{22,27,9},{22,27,9},{22,27,9},{22,24,13},{31,7,50},{21,25,1},{21,25,1},{19,24,16},{31,19,50},{19,24,16},{31,11,72},{22,27,4},{23,25,0},{21,25,1},{31,11,72},{31,21,72},{21,25,1},{0,24,80},{31,21,72},{0,24,80},{22,0,90},{22,0,90},{22,0,90},{22,0,90},{21,25,1},{21,25,1},{21,25,1},{21,23,2},{19,24,4},
+{19,24,4},{23,30,154},{23,28,84},{23,26,117},{23,26,85},{22,30,244},{22,27,75},{22,26,2},{22,25,106},{20,27,253},{20,25,100},{23,30,90},{23,28,20},{24,26,26},{23,26,21},{31,12,244},{22,27,75},{22,26,2},{20,25,91},{30,22,244},{20,25,91},{23,28,80},{23,28,80},{23,28,80},{23,26,84},{22,28,52},{22,26,1},{22,26,1},{22,25,25},{20,26,52},{20,25,19},{23,28,16},
+{23,28,16},{23,28,16},{23,26,20},{28,16,50},{22,26,1},{22,26,1},{20,25,10},{24,24,50},{20,25,10},{28,20,72},{23,28,4},{24,26,1},{22,26,1},{28,20,72},{28,24,72},{22,26,1},{0,25,90},{28,24,72},{0,25,90},{23,0,80},{23,0,80},{23,0,80},{23,0,80},{22,26,1},{22,26,1},{22,26,1},{22,24,1},{20,25,10},{20,25,10},{24,31,162},{24,29,94},{24,27,116},
+{24,27,100},{23,31,244},{23,28,76},{23,27,2},{23,26,106},{21,28,253},{21,26,100},{24,31,81},{24,29,13},{25,27,26},{24,27,19},{31,15,244},{23,28,76},{23,27,2},{21,26,91},{31,23,244},{21,26,91},{24,29,90},{24,29,90},{24,29,90},{24,26,99},{23,29,52},{23,27,1},{23,27,1},{23,26,25},{21,27,52},{21,26,19},{24,29,9},{24,29,9},{24,29,9},{24,26,18},{29,17,50},
+{23,27,1},{23,27,1},{21,26,10},{27,24,50},{21,26,10},{29,21,72},{24,29,4},{25,27,1},{23,27,1},{29,21,72},{31,24,72},{23,27,1},{0,26,90},{31,24,72},{0,26,90},{24,0,90},{24,0,90},{24,0,90},{24,0,90},{23,27,1},{23,27,1},{23,27,1},{23,25,1},{21,26,10},{21,26,10},{25,31,180},{25,30,94},{25,28,115},{25,28,99},{24,31,265},{24,29,77},{24,28,2},
+{24,27,116},{22,29,253},{22,27,100},{26,30,97},{25,30,13},{26,28,25},{25,28,18},{28,24,243},{24,29,76},{24,28,1},{22,27,91},{24,28,243},{22,27,91},{25,30,90},{25,30,90},{25,30,90},{25,27,99},{24,30,51},{24,28,2},{24,28,2},{24,26,27},{22,28,50},{22,27,19},{25,30,9},{25,30,9},{25,30,9},{25,27,18},{31,16,50},{24,28,1},{24,28,1},{22,27,10},{30,24,50},
+{22,27,10},{31,20,72},{25,30,4},{26,28,0},{24,28,1},{31,20,72},{30,26,72},{24,28,1},{0,27,90},{30,26,72},{0,27,90},{25,0,90},{25,0,90},{25,0,90},{25,0,90},{24,28,1},{24,28,1},{24,28,1},{24,26,2},{22,27,10},{22,27,10},{26,31,234},{26,31,94},{26,29,115},{26,29,99},{26,31,325},{25,30,77},{25,29,2},{25,28,106},{23,30,253},{23,28,84},{27,31,97},
+{26,31,13},{27,29,25},{26,29,18},{29,25,243},{25,30,76},{25,29,1},{23,28,80},{27,28,243},{23,28,80},{26,31,90},{26,31,90},{26,31,90},{26,28,94},{25,31,51},{25,29,2},{25,29,2},{25,27,27},{23,29,50},{23,28,20},{26,31,9},{26,31,9},{26,31,9},{26,28,13},{31,19,50},{25,29,1},{25,29,1},{23,28,16},{31,25,50},{23,28,16},{31,23,72},{26,31,4},{27,29,0},
+{25,29,1},{31,23,72},{31,27,72},{25,29,1},{0,28,80},{31,27,72},{0,28,80},{26,0,90},{26,0,90},{26,0,90},{26,0,90},{25,29,1},{25,29,1},{25,29,1},{25,27,2},{23,28,4},{23,28,4},{27,31,314},{27,31,105},{27,30,117},{27,30,85},{27,31,347},{26,31,75},{26,30,2},{26,29,106},{24,31,253},{24,29,100},{28,31,115},{28,31,35},{28,30,26},{27,30,21},{31,24,244},
+{26,31,75},{26,30,2},{24,29,91},{30,28,244},{24,29,91},{27,31,89},{27,31,89},{27,31,89},{27,30,84},{26,31,82},{26,30,1},{26,30,1},{26,29,25},{24,30,52},{24,29,19},{28,30,25},{28,30,25},{28,30,25},{27,30,20},{28,28,50},{26,30,1},{26,30,1},{24,29,10},{28,28,50},{24,29,10},{31,26,74},{28,31,10},{28,30,1},{26,30,1},{31,26,74},{30,29,74},{26,30,1},
+{0,29,90},{30,29,74},{0,29,90},{27,0,80},{27,0,80},{27,0,80},{27,0,80},{26,30,1},{26,30,1},{26,30,1},{26,28,1},{24,29,10},{24,29,10},{28,31,371},{28,31,179},{28,31,115},{28,31,99},{28,31,387},{27,31,122},{27,31,1},{27,30,89},{26,31,279},{25,30,83},{29,31,146},{29,31,61},{29,31,25},{28,31,18},{31,27,221},{28,31,98},{27,31,1},{25,30,74},{31,29,221},
+{25,30,74},{28,31,115},{28,31,115},{28,31,115},{28,30,99},{27,31,122},{27,31,1},{27,31,1},{27,30,25},{25,31,52},{25,30,19},{29,31,25},{29,31,25},{29,31,25},{28,30,18},{29,29,50},{27,31,1},{27,31,1},{25,30,10},{31,28,50},{25,30,10},{31,29,61},{30,31,34},{29,31,0},{27,31,0},{31,29,61},{31,30,61},{27,31,0},{0,30,73},{31,30,61},{0,30,73},{28,0,90},
+{28,0,90},{28,0,90},{28,0,90},{27,31,1},{27,31,1},{27,31,1},{27,29,1},{25,30,10},{25,30,10},{29,31,275},{29,31,190},{29,31,154},{29,31,99},{29,31,270},{28,31,99},{28,31,35},{28,31,35},{28,31,195},{26,31,19},{30,31,70},{30,31,43},{30,31,34},{29,31,18},{31,29,94},{29,31,49},{29,31,13},{26,31,10},{31,30,94},{26,31,10},{29,31,154},{29,31,154},{29,31,154},
+{29,31,99},{29,31,149},{28,31,35},{28,31,35},{28,30,27},{27,31,77},{26,31,19},{30,31,34},{30,31,34},{30,31,34},{29,31,18},{31,28,50},{29,31,13},{29,31,13},{26,31,10},{30,30,50},{26,31,10},{31,30,9},{31,31,9},{30,31,9},{30,31,0},{31,30,9},{30,31,9},{30,31,0},{0,31,9},{30,31,9},{0,31,9},{29,0,90},{29,0,90},{29,0,90},{29,0,90},{28,31,10},
+{28,31,10},{28,31,10},{28,30,2},{26,31,10},{26,31,10},{30,31,162},{30,31,135},{30,31,126},{30,31,99},{30,31,154},{30,31,100},{29,31,73},{29,31,2},{29,31,109},{28,31,10},{31,31,25},{31,31,25},{31,31,25},{30,31,18},{31,30,22},{30,31,19},{30,31,10},{29,31,1},{30,31,22},{29,31,1},{30,31,126},{30,31,126},{30,31,126},{30,31,99},{30,31,118},{29,31,73},{29,31,73},
+{29,31,2},{29,31,73},{28,31,10},{31,31,25},{31,31,25},{31,31,25},{30,31,18},{31,30,13},{30,31,10},{30,31,10},{29,31,1},{30,31,13},{29,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{30,0,90},{30,0,90},{30,0,90},{30,0,90},{29,31,37},{29,31,37},{29,31,37},{29,31,2},{28,31,10},
+{28,31,10},{0,7,200},{0,5,20},{0,4,20},{0,3,74},{0,5,441},{0,3,282},{0,3,138},{0,2,318},{0,2,487},{0,2,343},{0,7,200},{0,5,20},{0,4,20},{0,3,74},{2,1,441},{0,3,282},{0,3,138},{0,2,318},{5,0,441},{0,2,318},{0,3,1},{0,3,1},{0,3,1},{0,2,1},{0,2,41},{0,1,20},{0,1,20},{0,1,26},{0,1,45},{0,1,30},{0,3,1},
+{0,3,1},{0,3,1},{0,2,1},{1,0,41},{0,1,20},{0,1,20},{0,1,26},{2,0,41},{0,1,26},{1,5,200},{0,5,20},{0,4,20},{0,3,74},{1,5,200},{7,0,200},{0,3,74},{0,2,218},{7,0,200},{0,2,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,10,200},{0,7,5},{0,5,32},
+{0,4,41},{0,7,689},{0,5,369},{0,4,162},{0,3,474},{0,3,762},{0,3,538},{0,10,200},{0,7,5},{0,5,32},{0,4,41},{3,1,686},{0,5,369},{0,4,162},{0,3,474},{3,2,686},{0,3,474},{0,6,1},{0,6,1},{0,6,1},{0,3,1},{0,3,145},{0,3,65},{0,3,65},{0,2,101},{0,1,173},{0,1,110},{0,6,1},{0,6,1},{0,6,1},{0,3,1},{1,1,145},
+{0,3,65},{0,3,65},{0,2,101},{3,0,145},{0,2,101},{5,0,200},{0,7,5},{1,4,17},{0,4,41},{5,0,200},{10,0,200},{0,4,41},{0,3,218},{10,0,200},{0,3,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,13,249},{0,8,59},{1,6,97},{0,5,69},{0,10,728},{0,6,299},{0,5,56},
+{0,4,433},{0,4,884},{0,4,554},{1,11,201},{1,8,6},{1,6,33},{1,5,42},{5,0,728},{0,6,299},{0,5,56},{0,4,433},{10,0,728},{0,4,433},{0,9,50},{0,9,50},{0,9,50},{0,5,53},{0,6,162},{0,4,25},{0,4,25},{0,3,82},{0,3,226},{0,2,115},{1,7,2},{1,7,2},{1,7,2},{1,4,2},{3,0,162},{0,4,25},{0,4,25},{0,3,82},{6,0,162},
+{0,3,82},{6,1,200},{1,8,5},{2,5,17},{0,5,20},{6,1,200},{13,0,200},{0,5,20},{0,4,208},{13,0,200},{0,4,208},{0,0,49},{0,0,49},{0,0,49},{0,0,49},{0,3,1},{0,3,1},{0,3,1},{0,1,4},{0,1,8},{0,1,8},{1,14,313},{1,9,123},{1,7,210},{1,6,133},{0,12,724},{0,8,251},{0,6,18},{0,5,352},{0,6,987},{0,5,521},{2,12,201},
+{2,9,6},{2,7,33},{2,6,42},{4,4,724},{0,8,251},{0,6,18},{0,5,352},{12,0,724},{0,5,352},{1,10,114},{1,10,114},{1,10,114},{1,6,117},{0,9,162},{0,6,2},{0,6,2},{0,4,49},{0,4,291},{0,3,146},{2,8,2},{2,8,2},{2,8,2},{2,5,2},{4,1,162},{0,6,2},{0,6,2},{0,4,49},{9,0,162},{0,4,49},{7,2,200},{2,9,5},{3,6,17},
+{0,6,17},{7,2,200},{14,1,200},{0,6,17},{0,5,208},{14,1,200},{0,5,208},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,6,1},{0,6,1},{0,6,1},{0,3,1},{0,2,50},{0,2,50},{2,15,410},{2,11,221},{2,8,324},{2,7,234},{1,14,739},{0,10,233},{0,8,40},{0,6,298},{0,7,1013},{0,6,426},{3,13,202},{3,10,1},{3,8,32},{3,7,41},{7,2,723},
+{0,10,217},{0,8,24},{0,6,282},{14,1,723},{0,6,282},{2,12,209},{2,12,209},{2,12,209},{2,7,209},{0,12,178},{1,7,20},{1,7,20},{0,5,26},{0,6,308},{0,5,91},{3,10,1},{3,10,1},{3,10,1},{3,6,4},{4,4,162},{1,7,4},{1,7,4},{0,5,10},{12,0,162},{0,5,10},{9,1,200},{3,10,1},{4,8,20},{0,8,20},{9,1,200},{19,0,200},{0,8,20},
+{0,6,218},{19,0,200},{0,6,218},{2,0,208},{2,0,208},{2,0,208},{2,0,208},{1,7,16},{1,7,16},{1,7,16},{1,4,16},{0,4,53},{0,4,53},{3,16,408},{3,12,225},{3,9,324},{3,8,228},{2,15,739},{1,11,233},{2,8,33},{1,7,298},{0,9,875},{0,7,303},{4,14,201},{4,11,6},{4,9,33},{4,8,42},{7,5,723},{0,11,204},{2,8,17},{0,7,254},{15,2,723},
+{0,7,254},{3,12,209},{3,12,209},{3,12,209},{3,8,212},{1,13,178},{2,8,17},{2,8,17},{1,6,26},{0,7,229},{0,6,17},{4,10,2},{4,10,2},{4,10,2},{4,7,2},{5,5,162},{2,8,1},{2,8,1},{0,6,1},{15,0,162},{0,6,1},{11,0,200},{4,11,5},{5,8,17},{2,8,17},{11,0,200},{22,0,200},{2,8,17},{0,7,218},{22,0,200},{0,7,218},{3,0,208},
+{3,0,208},{3,0,208},{3,0,208},{2,8,16},{2,8,16},{2,8,16},{2,5,16},{0,6,16},{0,6,16},{4,17,418},{4,12,228},{4,10,315},{4,9,238},{3,16,744},{2,11,234},{3,9,33},{2,8,305},{0,11,828},{0,8,228},{5,15,201},{5,12,6},{5,10,33},{5,9,42},{11,0,728},{1,12,204},{3,9,17},{0,8,224},{22,0,728},{0,8,224},{4,13,219},{4,13,219},{4,13,219},
+{4,9,222},{3,12,178},{3,9,17},{3,9,17},{2,7,26},{0,9,178},{0,7,6},{5,11,2},{5,11,2},{5,11,2},{5,8,2},{9,0,162},{3,9,1},{3,9,1},{1,7,1},{18,0,162},{1,7,1},{12,1,200},{5,12,5},{6,9,17},{3,9,17},{12,1,200},{25,0,200},{3,9,17},{0,8,208},{25,0,200},{0,8,208},{4,0,218},{4,0,218},{4,0,218},{4,0,218},{3,9,16},
+{3,9,16},{3,9,16},{3,6,16},{0,7,5},{0,7,5},{5,18,418},{5,13,228},{5,11,315},{5,10,238},{3,19,744},{3,12,225},{3,11,40},{3,9,305},{0,12,749},{0,9,225},{6,16,201},{6,13,6},{6,11,33},{6,10,42},{12,0,724},{2,13,204},{4,10,18},{0,9,209},{24,0,724},{0,9,209},{5,14,219},{5,14,219},{5,14,219},{5,10,222},{3,15,178},{3,11,24},{3,11,24},
+{3,8,32},{1,10,178},{1,8,5},{6,12,2},{6,12,2},{6,12,2},{6,9,2},{10,1,162},{4,10,2},{4,10,2},{2,8,1},{21,0,162},{2,8,1},{14,0,200},{6,13,5},{7,10,17},{4,10,17},{14,0,200},{26,1,200},{4,10,17},{0,9,208},{26,1,200},{0,9,208},{5,0,218},{5,0,218},{5,0,218},{5,0,218},{3,12,17},{3,12,17},{3,12,17},{3,7,20},{1,8,5},
+{1,8,5},{6,19,410},{6,15,221},{6,12,324},{6,11,234},{5,18,739},{4,14,233},{4,12,40},{4,10,298},{0,14,724},{2,10,228},{7,17,202},{7,14,1},{7,12,32},{7,11,41},{14,0,723},{3,14,211},{4,12,24},{1,10,218},{26,1,723},{1,10,218},{6,16,209},{6,16,209},{6,16,209},{6,11,209},{4,16,178},{5,11,20},{5,11,20},{4,9,26},{1,12,171},{3,9,10},{7,14,1},
+{7,14,1},{7,14,1},{7,10,4},{12,0,162},{5,11,4},{5,11,4},{3,9,1},{24,0,162},{3,9,1},{13,5,200},{7,14,1},{8,12,20},{3,12,17},{13,5,200},{31,0,200},{3,12,17},{0,10,218},{31,0,200},{0,10,218},{6,0,208},{6,0,208},{6,0,208},{6,0,208},{5,11,16},{5,11,16},{5,11,16},{5,8,16},{3,9,9},{3,9,9},{7,20,408},{7,16,225},{7,13,324},
+{7,12,228},{6,19,739},{5,15,233},{6,12,33},{5,11,298},{1,15,724},{3,11,228},{8,18,201},{8,15,6},{8,13,33},{8,12,42},{15,1,723},{4,15,204},{6,12,17},{2,11,218},{27,2,723},{2,11,218},{7,16,209},{7,16,209},{7,16,209},{7,12,212},{5,17,178},{6,12,17},{6,12,17},{5,10,26},{2,13,171},{3,10,14},{8,14,2},{8,14,2},{8,14,2},{8,11,2},{13,1,162},
+{6,12,1},{6,12,1},{4,10,1},{27,0,162},{4,10,1},{17,0,200},{8,15,5},{9,12,17},{6,12,17},{17,0,200},{30,2,200},{6,12,17},{0,11,218},{30,2,200},{0,11,218},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{6,12,16},{6,12,16},{6,12,16},{6,9,16},{3,11,10},{3,11,10},{8,21,418},{8,16,228},{8,14,315},{8,13,238},{7,20,744},{6,15,234},{7,13,33},
+{6,12,305},{2,16,729},{3,12,225},{9,19,201},{9,16,6},{9,14,33},{9,13,42},{17,0,728},{5,16,204},{7,13,17},{3,12,209},{30,2,728},{3,12,209},{8,17,219},{8,17,219},{8,17,219},{8,13,222},{7,16,178},{7,13,17},{7,13,17},{6,11,26},{3,14,171},{4,11,6},{9,15,2},{9,15,2},{9,15,2},{9,12,2},{15,0,162},{7,13,1},{7,13,1},{5,11,1},{30,0,162},
+{5,11,1},{18,1,200},{9,16,5},{10,13,17},{7,13,17},{18,1,200},{31,3,200},{7,13,17},{0,12,208},{31,3,200},{0,12,208},{8,0,218},{8,0,218},{8,0,218},{8,0,218},{7,13,16},{7,13,16},{7,13,16},{7,10,16},{4,11,5},{4,11,5},{9,22,418},{9,17,228},{9,15,315},{9,14,238},{7,23,744},{7,16,225},{7,15,40},{7,13,305},{3,17,729},{4,13,225},{10,20,201},
+{10,17,6},{10,15,33},{10,14,42},{16,4,724},{6,17,204},{8,14,18},{4,13,209},{28,4,724},{4,13,209},{9,18,219},{9,18,219},{9,18,219},{9,14,222},{7,19,178},{7,15,24},{7,15,24},{7,12,32},{5,14,178},{5,12,5},{10,16,2},{10,16,2},{10,16,2},{10,13,2},{16,1,162},{8,14,2},{8,14,2},{6,12,1},{31,1,162},{6,12,1},{19,2,200},{10,17,5},{11,14,17},
+{8,14,17},{19,2,200},{30,5,200},{8,14,17},{0,13,208},{30,5,200},{0,13,208},{9,0,218},{9,0,218},{9,0,218},{9,0,218},{7,16,17},{7,16,17},{7,16,17},{7,11,20},{5,12,5},{5,12,5},{10,23,410},{10,19,221},{10,16,324},{10,15,234},{9,22,739},{8,18,233},{8,16,40},{8,14,298},{4,18,724},{6,14,228},{11,21,202},{11,18,1},{11,16,32},{11,15,41},{19,2,723},
+{7,18,211},{8,16,24},{5,14,218},{30,5,723},{5,14,218},{10,20,209},{10,20,209},{10,20,209},{10,15,209},{8,20,178},{9,15,20},{9,15,20},{8,13,26},{5,16,171},{7,13,10},{11,18,1},{11,18,1},{11,18,1},{11,14,4},{16,4,162},{9,15,4},{9,15,4},{7,13,1},{28,4,162},{7,13,1},{21,1,200},{11,18,1},{12,16,20},{7,16,17},{21,1,200},{27,8,200},{7,16,17},
+{0,14,218},{27,8,200},{0,14,218},{10,0,208},{10,0,208},{10,0,208},{10,0,208},{9,15,16},{9,15,16},{9,15,16},{9,12,16},{7,13,9},{7,13,9},{11,24,408},{11,20,225},{11,17,324},{11,16,228},{10,23,739},{9,19,233},{10,16,33},{9,15,298},{5,19,724},{7,15,228},{12,22,201},{12,19,6},{12,17,33},{12,16,42},{19,5,723},{8,19,204},{10,16,17},{6,15,218},{31,6,723},
+{6,15,218},{11,20,209},{11,20,209},{11,20,209},{11,16,212},{9,21,178},{10,16,17},{10,16,17},{9,14,26},{6,17,171},{7,14,14},{12,18,2},{12,18,2},{12,18,2},{12,15,2},{17,5,162},{10,16,1},{10,16,1},{8,14,1},{31,4,162},{8,14,1},{23,0,200},{12,19,5},{13,16,17},{10,16,17},{23,0,200},{30,8,200},{10,16,17},{0,15,218},{30,8,200},{0,15,218},{11,0,208},
+{11,0,208},{11,0,208},{11,0,208},{10,16,16},{10,16,16},{10,16,16},{10,13,16},{7,15,10},{7,15,10},{12,25,418},{12,20,228},{12,18,315},{12,17,238},{11,24,744},{10,19,234},{11,17,33},{10,16,305},{6,20,729},{7,16,225},{13,23,201},{13,20,6},{13,18,33},{13,17,42},{23,0,728},{9,20,204},{11,17,17},{7,16,209},{30,8,728},{7,16,209},{12,21,219},{12,21,219},{12,21,219},
+{12,17,222},{11,20,178},{11,17,17},{11,17,17},{10,15,26},{7,18,171},{8,15,6},{13,19,2},{13,19,2},{13,19,2},{13,16,2},{21,0,162},{11,17,1},{11,17,1},{9,15,1},{30,6,162},{9,15,1},{24,1,200},{13,20,5},{14,17,17},{11,17,17},{24,1,200},{31,9,200},{11,17,17},{0,16,208},{31,9,200},{0,16,208},{12,0,218},{12,0,218},{12,0,218},{12,0,218},{11,17,16},
+{11,17,16},{11,17,16},{11,14,16},{8,15,5},{8,15,5},{13,26,418},{13,21,228},{13,19,315},{13,18,238},{11,27,744},{11,20,225},{11,19,40},{11,17,305},{7,21,729},{8,17,225},{14,24,201},{14,21,6},{14,19,33},{14,18,42},{24,0,724},{10,21,204},{12,18,18},{8,17,209},{24,12,724},{8,17,209},{13,22,219},{13,22,219},{13,22,219},{13,18,222},{11,23,178},{11,19,24},{11,19,24},
+{11,16,32},{9,18,178},{9,16,5},{14,20,2},{14,20,2},{14,20,2},{14,17,2},{22,1,162},{12,18,2},{12,18,2},{10,16,1},{31,7,162},{10,16,1},{26,0,200},{14,21,5},{15,18,17},{12,18,17},{26,0,200},{30,11,200},{12,18,17},{0,17,208},{30,11,200},{0,17,208},{13,0,218},{13,0,218},{13,0,218},{13,0,218},{11,20,17},{11,20,17},{11,20,17},{11,15,20},{9,16,5},
+{9,16,5},{14,27,410},{14,23,221},{14,20,324},{14,19,234},{13,26,739},{12,22,233},{12,20,40},{12,18,298},{8,22,724},{10,18,228},{15,25,202},{15,22,1},{15,20,32},{15,19,41},{26,0,723},{11,22,211},{12,20,24},{9,18,218},{30,11,723},{9,18,218},{14,24,209},{14,24,209},{14,24,209},{14,19,209},{12,24,178},{13,19,20},{13,19,20},{12,17,26},{9,20,171},{11,17,10},{15,22,1},
+{15,22,1},{15,22,1},{15,18,4},{24,0,162},{13,19,4},{13,19,4},{11,17,1},{24,12,162},{11,17,1},{25,5,200},{15,22,1},{16,20,20},{11,20,17},{25,5,200},{31,12,200},{11,20,17},{0,18,218},{31,12,200},{0,18,218},{14,0,208},{14,0,208},{14,0,208},{14,0,208},{13,19,16},{13,19,16},{13,19,16},{13,16,16},{11,17,9},{11,17,9},{15,28,408},{15,24,225},{15,21,324},
+{15,20,228},{14,27,739},{13,23,233},{14,20,33},{13,19,298},{9,23,724},{11,19,228},{16,26,201},{16,23,6},{16,21,33},{16,20,42},{27,1,723},{12,23,204},{14,20,17},{10,19,218},{27,14,723},{10,19,218},{15,24,209},{15,24,209},{15,24,209},{15,20,212},{13,25,178},{14,20,17},{14,20,17},{13,18,26},{10,21,171},{11,18,14},{16,22,2},{16,22,2},{16,22,2},{16,19,2},{25,1,162},
+{14,20,1},{14,20,1},{12,18,1},{27,12,162},{12,18,1},{29,0,200},{16,23,5},{17,20,17},{14,20,17},{29,0,200},{30,14,200},{14,20,17},{0,19,218},{30,14,200},{0,19,218},{15,0,208},{15,0,208},{15,0,208},{15,0,208},{14,20,16},{14,20,16},{14,20,16},{14,17,16},{11,19,10},{11,19,10},{16,29,418},{16,24,228},{16,22,315},{16,21,238},{15,28,744},{14,23,234},{15,21,33},
+{14,20,305},{10,24,729},{11,20,225},{17,27,201},{17,24,6},{17,22,33},{17,21,42},{29,0,728},{13,24,204},{15,21,17},{11,20,209},{30,14,728},{11,20,209},{16,25,219},{16,25,219},{16,25,219},{16,21,222},{15,24,178},{15,21,17},{15,21,17},{14,19,26},{11,22,171},{12,19,6},{17,23,2},{17,23,2},{17,23,2},{17,20,2},{27,0,162},{15,21,1},{15,21,1},{13,19,1},{30,12,162},
+{13,19,1},{30,1,200},{17,24,5},{18,21,17},{15,21,17},{30,1,200},{31,15,200},{15,21,17},{0,20,208},{31,15,200},{0,20,208},{16,0,218},{16,0,218},{16,0,218},{16,0,218},{15,21,16},{15,21,16},{15,21,16},{15,18,16},{12,19,5},{12,19,5},{17,30,418},{17,25,228},{17,23,315},{17,22,238},{15,31,744},{15,24,225},{15,23,40},{15,21,305},{11,25,729},{12,21,225},{18,28,201},
+{18,25,6},{18,23,33},{18,22,42},{28,4,724},{14,25,204},{16,22,18},{12,21,209},{28,16,724},{12,21,209},{17,26,219},{17,26,219},{17,26,219},{17,22,222},{15,27,178},{15,23,24},{15,23,24},{15,20,32},{13,22,178},{13,20,5},{18,24,2},{18,24,2},{18,24,2},{18,21,2},{28,1,162},{16,22,2},{16,22,2},{14,20,1},{31,13,162},{14,20,1},{31,2,200},{18,25,5},{19,22,17},
+{16,22,17},{31,2,200},{30,17,200},{16,22,17},{0,21,208},{30,17,200},{0,21,208},{17,0,218},{17,0,218},{17,0,218},{17,0,218},{15,24,17},{15,24,17},{15,24,17},{15,19,20},{13,20,5},{13,20,5},{18,31,410},{18,27,221},{18,24,324},{18,23,234},{17,30,739},{16,26,233},{16,24,40},{16,22,298},{12,26,724},{14,22,228},{19,29,202},{19,26,1},{19,24,32},{19,23,41},{31,2,723},
+{15,26,211},{16,24,24},{13,22,218},{30,17,723},{13,22,218},{18,28,209},{18,28,209},{18,28,209},{18,23,209},{16,28,178},{17,23,20},{17,23,20},{16,21,26},{13,24,171},{15,21,10},{19,26,1},{19,26,1},{19,26,1},{19,22,4},{28,4,162},{17,23,4},{17,23,4},{15,21,1},{28,16,162},{15,21,1},{29,9,200},{19,26,1},{20,24,20},{15,24,17},{29,9,200},{27,20,200},{15,24,17},
+{0,22,218},{27,20,200},{0,22,218},{18,0,208},{18,0,208},{18,0,208},{18,0,208},{17,23,16},{17,23,16},{17,23,16},{17,20,16},{15,21,9},{15,21,9},{19,31,426},{19,28,225},{19,25,324},{19,24,228},{18,31,739},{17,27,233},{18,24,33},{17,23,298},{13,27,724},{15,23,228},{20,30,201},{20,27,6},{20,25,33},{20,24,42},{31,5,723},{16,27,204},{18,24,17},{14,23,218},{31,18,723},
+{14,23,218},{19,28,209},{19,28,209},{19,28,209},{19,24,212},{17,29,178},{18,24,17},{18,24,17},{17,22,26},{14,25,171},{15,22,14},{20,26,2},{20,26,2},{20,26,2},{20,23,2},{29,5,162},{18,24,1},{18,24,1},{16,22,1},{31,16,162},{16,22,1},{31,8,200},{20,27,5},{21,24,17},{18,24,17},{31,8,200},{30,20,200},{18,24,17},{0,23,218},{30,20,200},{0,23,218},{19,0,208},
+{19,0,208},{19,0,208},{19,0,208},{18,24,16},{18,24,16},{18,24,16},{18,21,16},{15,23,10},{15,23,10},{20,31,468},{20,28,228},{20,26,315},{20,25,238},{19,31,747},{18,27,234},{19,25,33},{18,24,305},{14,28,729},{15,24,225},{21,31,201},{21,28,6},{21,26,33},{21,25,42},{31,8,728},{17,28,204},{19,25,17},{15,24,209},{30,20,728},{15,24,209},{20,29,219},{20,29,219},{20,29,219},
+{20,25,222},{19,28,178},{19,25,17},{19,25,17},{18,23,26},{15,26,171},{16,23,6},{21,27,2},{21,27,2},{21,27,2},{21,24,2},{31,4,162},{19,25,1},{19,25,1},{17,23,1},{30,18,162},{17,23,1},{31,11,200},{21,28,5},{22,25,17},{19,25,17},{31,11,200},{31,21,200},{19,25,17},{0,24,208},{31,21,200},{0,24,208},{20,0,218},{20,0,218},{20,0,218},{20,0,218},{19,25,16},
+{19,25,16},{19,25,16},{19,22,16},{16,23,5},{16,23,5},{21,31,546},{21,29,228},{21,27,315},{21,26,238},{20,31,788},{19,28,225},{19,27,40},{19,25,305},{15,29,729},{16,25,225},{22,31,219},{22,29,6},{22,27,33},{22,26,42},{28,16,724},{18,29,204},{20,26,18},{16,25,209},{24,24,724},{16,25,209},{21,30,219},{21,30,219},{21,30,219},{21,26,222},{19,31,178},{19,27,24},{19,27,24},
+{19,24,32},{17,26,178},{17,24,5},{22,28,2},{22,28,2},{22,28,2},{22,25,2},{31,7,162},{20,26,2},{20,26,2},{18,24,1},{31,19,162},{18,24,1},{31,14,200},{22,29,5},{23,26,17},{20,26,17},{31,14,200},{30,23,200},{20,26,17},{0,25,208},{30,23,200},{0,25,208},{21,0,218},{21,0,218},{21,0,218},{21,0,218},{19,28,17},{19,28,17},{19,28,17},{19,23,20},{17,24,5},
+{17,24,5},{23,31,672},{22,31,221},{22,28,324},{22,27,234},{22,31,888},{20,30,233},{20,28,40},{20,26,298},{16,30,724},{18,26,228},{23,31,272},{23,30,1},{23,28,32},{23,27,41},{31,14,723},{19,30,211},{20,28,24},{17,26,218},{30,23,723},{17,26,218},{22,31,212},{22,31,212},{22,31,212},{22,27,209},{21,30,180},{21,27,20},{21,27,20},{20,25,26},{17,28,171},{19,25,10},{23,30,1},
+{23,30,1},{23,30,1},{23,26,4},{28,16,162},{21,27,4},{21,27,4},{19,25,1},{24,24,162},{19,25,1},{29,21,200},{23,30,1},{24,28,20},{19,28,17},{29,21,200},{31,24,200},{19,28,17},{0,26,218},{31,24,200},{0,26,218},{22,0,208},{22,0,208},{22,0,208},{22,0,208},{21,27,16},{21,27,16},{21,27,16},{21,24,16},{19,25,9},{19,25,9},{24,31,770},{23,31,228},{23,29,324},
+{23,28,228},{23,31,932},{21,31,233},{22,28,33},{21,27,298},{17,31,724},{19,27,228},{25,31,299},{24,31,6},{24,29,33},{24,28,42},{31,17,723},{20,31,204},{22,28,17},{18,27,218},{27,26,723},{18,27,218},{23,31,224},{23,31,224},{23,31,224},{23,28,212},{22,31,180},{22,28,17},{22,28,17},{21,26,26},{18,29,171},{19,26,14},{24,30,2},{24,30,2},{24,30,2},{24,27,2},{29,17,162},
+{22,28,1},{22,28,1},{20,26,1},{27,24,162},{20,26,1},{31,20,200},{24,31,5},{25,28,17},{22,28,17},{31,20,200},{30,26,200},{22,28,17},{0,27,218},{30,26,200},{0,27,218},{23,0,208},{23,0,208},{23,0,208},{23,0,208},{22,28,16},{22,28,16},{22,28,16},{22,25,16},{19,27,10},{19,27,10},{25,31,884},{24,31,303},{24,30,315},{24,29,238},{24,31,1025},{22,31,234},{23,29,33},
+{22,28,305},{19,31,747},{19,28,225},{26,31,353},{25,31,27},{25,30,33},{25,29,42},{31,20,728},{22,31,218},{23,29,17},{19,28,209},{30,26,728},{19,28,209},{24,31,254},{24,31,254},{24,31,254},{24,29,222},{23,31,196},{23,29,17},{23,29,17},{22,27,26},{19,30,171},{20,27,6},{25,31,2},{25,31,2},{25,31,2},{25,28,2},{31,16,162},{23,29,1},{23,29,1},{21,27,1},{30,24,162},
+{21,27,1},{31,23,200},{26,31,20},{26,29,17},{23,29,17},{31,23,200},{31,27,200},{23,29,17},{0,28,208},{31,27,200},{0,28,208},{24,0,218},{24,0,218},{24,0,218},{24,0,218},{23,29,16},{23,29,16},{23,29,16},{23,26,16},{20,27,5},{20,27,5},{26,31,1034},{25,31,468},{25,31,315},{25,30,238},{25,31,1172},{24,31,291},{23,31,40},{23,29,305},{21,31,837},{20,29,225},{27,31,409},
+{26,31,117},{26,31,33},{26,30,42},{28,28,724},{24,31,266},{24,30,18},{20,29,209},{28,28,724},{20,29,209},{25,31,299},{25,31,299},{25,31,299},{25,30,222},{24,31,237},{23,31,24},{23,31,24},{23,28,32},{21,30,178},{21,28,5},{26,31,17},{26,31,17},{26,31,17},{26,29,2},{31,19,162},{24,30,2},{24,30,2},{22,28,1},{31,25,162},{22,28,1},{31,26,200},{27,31,53},{27,30,17},
+{24,30,17},{31,26,200},{30,29,200},{24,30,17},{0,29,208},{30,29,200},{0,29,208},{25,0,218},{25,0,218},{25,0,218},{25,0,218},{23,31,20},{23,31,20},{23,31,20},{23,27,20},{21,28,5},{21,28,5},{27,31,933},{27,31,570},{26,31,377},{26,31,209},{27,31,1054},{25,31,309},{25,31,20},{24,30,193},{23,31,735},{22,30,123},{28,31,338},{28,31,146},{27,31,49},{27,31,16},{29,29,546},
+{26,31,222},{25,31,4},{21,30,113},{31,28,546},{21,30,113},{26,31,377},{26,31,377},{26,31,377},{26,31,209},{26,31,338},{25,31,20},{25,31,20},{24,29,26},{22,31,173},{23,29,10},{27,31,49},{27,31,49},{27,31,49},{27,30,4},{28,28,162},{25,31,4},{25,31,4},{23,29,1},{28,28,162},{23,29,1},{31,28,113},{29,31,52},{28,31,1},{26,31,1},{31,28,113},{30,30,113},{26,31,1},
+{0,30,113},{30,30,113},{0,30,113},{26,0,208},{26,0,208},{26,0,208},{26,0,208},{25,31,16},{25,31,16},{25,31,16},{25,28,16},{23,29,9},{23,29,9},{28,31,779},{27,31,554},{27,31,433},{27,31,224},{28,31,859},{26,31,270},{26,31,74},{25,30,90},{24,31,590},{23,31,59},{29,31,218},{29,31,133},{28,31,82},{28,31,2},{31,27,333},{27,31,146},{27,31,25},{22,31,49},{31,29,333},
+{22,31,49},{27,31,433},{27,31,433},{27,31,433},{27,31,224},{27,31,378},{26,31,74},{26,31,74},{25,30,26},{24,31,229},{23,30,14},{28,31,82},{28,31,82},{28,31,82},{28,31,2},{29,29,162},{27,31,25},{27,31,25},{24,30,1},{31,28,162},{24,30,1},{31,30,25},{30,31,10},{30,31,1},{28,31,1},{31,30,25},{30,31,25},{28,31,1},{0,31,49},{30,31,25},{0,31,49},{27,0,208},
+{27,0,208},{27,0,208},{27,0,208},{26,31,25},{26,31,25},{26,31,25},{26,29,16},{23,31,10},{23,31,10},{29,31,684},{28,31,538},{28,31,474},{28,31,282},{28,31,682},{27,31,283},{27,31,162},{26,31,25},{26,31,482},{24,31,5},{30,31,153},{30,31,126},{30,31,117},{29,31,37},{31,29,193},{29,31,108},{28,31,65},{25,31,0},{31,30,193},{25,31,0},{28,31,474},{28,31,474},{28,31,474},
+{28,31,282},{28,31,426},{27,31,162},{27,31,162},{26,31,25},{26,31,286},{24,31,5},{30,31,117},{30,31,117},{30,31,117},{29,31,37},{31,28,145},{28,31,65},{28,31,65},{25,31,0},{30,30,145},{25,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{28,0,218},{28,0,218},{28,0,218},{28,0,218},{27,31,41},
+{27,31,41},{27,31,41},{27,30,16},{24,31,5},{24,31,5},{29,31,460},{29,31,375},{29,31,339},{29,31,254},{29,31,415},{28,31,202},{28,31,138},{27,31,20},{27,31,295},{26,31,26},{30,31,73},{30,31,46},{30,31,37},{30,31,10},{31,30,54},{30,31,27},{30,31,18},{28,31,1},{30,31,54},{28,31,1},{29,31,339},{29,31,339},{29,31,339},{29,31,254},{29,31,294},{28,31,138},{28,31,138},
+{27,31,20},{27,31,174},{26,31,26},{30,31,37},{30,31,37},{30,31,37},{30,31,10},{31,29,45},{30,31,18},{30,31,18},{28,31,1},{31,30,45},{28,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{29,0,218},{29,0,218},{29,0,218},{29,0,218},{28,31,74},{28,31,74},{28,31,74},{27,31,20},{26,31,26},
+{26,31,26},{0,10,421},{0,7,52},{0,5,1},{0,4,162},{0,7,926},{0,5,590},{0,4,283},{0,3,701},{0,3,1005},{0,3,765},{0,10,421},{0,7,52},{0,5,1},{0,4,162},{3,1,925},{0,5,590},{0,4,283},{0,3,701},{3,2,925},{0,3,701},{0,5,0},{0,5,0},{0,5,0},{0,2,9},{0,2,89},{0,2,34},{0,2,34},{0,1,50},{0,1,93},{0,1,54},{0,5,0},
+{0,5,0},{0,5,0},{0,2,9},{1,0,89},{0,2,34},{0,2,34},{0,1,50},{2,0,89},{0,1,50},{5,0,421},{0,7,52},{0,5,1},{0,4,162},{5,0,421},{10,0,421},{0,4,162},{0,3,445},{10,0,421},{0,3,445},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,13,421},{0,9,10},{0,6,26},
+{0,5,117},{0,9,1261},{0,6,701},{0,5,286},{0,4,917},{0,4,1390},{0,3,1005},{0,13,421},{0,9,10},{0,6,26},{0,5,117},{4,1,1261},{0,6,701},{0,5,286},{0,4,917},{9,0,1261},{0,4,917},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{0,4,221},{0,3,89},{0,3,89},{0,2,125},{0,2,246},{0,2,150},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{2,0,221},
+{0,3,89},{0,3,89},{0,2,125},{4,0,221},{0,2,125},{6,1,421},{0,9,10},{1,6,1},{0,5,117},{6,1,421},{13,0,421},{0,5,117},{0,4,433},{13,0,421},{0,4,433},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,16,430},{0,11,14},{0,7,110},{0,7,91},{0,11,1514},{0,7,737},{0,6,259},
+{0,4,1002},{0,5,1710},{0,4,1123},{0,16,430},{0,11,14},{1,7,51},{0,7,91},{5,1,1514},{0,7,737},{0,6,259},{0,4,1002},{11,0,1514},{0,4,1002},{0,11,10},{0,11,10},{0,11,10},{0,5,13},{0,6,338},{0,5,104},{0,5,104},{0,3,194},{0,3,402},{0,2,243},{0,11,10},{0,11,10},{0,11,10},{0,5,13},{3,0,338},{0,5,104},{0,5,104},{0,3,194},{6,0,338},
+{0,3,194},{8,0,421},{0,11,5},{2,7,1},{0,7,82},{8,0,421},{16,0,421},{0,7,82},{0,5,433},{16,0,421},{0,5,433},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,1},{0,1,1},{0,1,1},{0,1,4},{0,1,8},{0,1,8},{1,17,494},{1,12,78},{1,8,173},{1,8,154},{0,14,1514},{0,9,602},{0,7,146},{0,6,874},{0,7,1875},{0,5,1066},{1,17,430},
+{1,12,14},{2,8,50},{1,8,90},{7,0,1514},{0,9,602},{0,7,146},{0,6,874},{14,0,1514},{0,6,874},{1,12,74},{1,12,74},{1,12,74},{1,6,77},{0,9,338},{0,6,50},{0,6,50},{0,4,137},{0,4,467},{0,3,258},{1,12,10},{1,12,10},{1,12,10},{1,6,13},{4,1,338},{0,6,50},{0,6,50},{0,4,137},{9,0,338},{0,4,137},{9,1,421},{1,12,5},{3,8,1},
+{0,8,49},{9,1,421},{19,0,421},{0,8,49},{0,6,433},{19,0,421},{0,6,433},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,4,0},{0,4,0},{0,4,0},{0,2,1},{0,2,26},{0,2,26},{1,20,629},{1,14,233},{2,10,385},{1,9,245},{0,17,1517},{0,11,521},{0,9,26},{0,7,769},{0,8,2025},{0,6,1085},{3,16,437},{2,13,17},{3,9,53},{2,9,81},{8,1,1517},
+{0,11,521},{0,9,26},{0,7,769},{17,0,1517},{0,7,769},{1,15,208},{1,15,208},{1,15,208},{1,8,208},{0,12,338},{0,8,8},{0,8,8},{0,5,74},{0,5,579},{0,5,243},{3,11,16},{3,11,16},{3,11,16},{3,7,16},{4,4,338},{0,8,8},{0,8,8},{0,5,74},{12,0,338},{0,5,74},{11,0,421},{2,13,1},{4,9,1},{0,9,10},{11,0,421},{22,0,421},{0,9,10},
+{0,7,445},{22,0,421},{0,7,445},{1,0,208},{1,0,208},{1,0,208},{1,0,208},{0,7,1},{0,7,1},{0,7,1},{0,4,4},{0,3,80},{0,3,80},{2,21,821},{2,15,425},{2,11,645},{2,10,437},{0,20,1514},{0,12,458},{0,10,2},{0,8,689},{0,9,2198},{0,7,1146},{3,19,437},{3,14,17},{4,10,51},{3,10,81},{8,4,1514},{0,12,458},{0,10,2},{0,8,689},{20,0,1514},
+{0,8,689},{2,16,400},{2,16,400},{2,16,400},{2,9,400},{0,15,338},{0,10,1},{0,10,1},{0,6,41},{0,7,717},{0,6,297},{3,14,16},{3,14,16},{3,14,16},{3,8,20},{5,5,338},{0,10,1},{0,10,1},{0,6,41},{15,0,338},{0,6,41},{12,1,421},{3,14,1},{5,10,1},{0,10,1},{12,1,421},{25,0,421},{0,10,1},{0,8,433},{25,0,421},{0,8,433},{2,0,400},
+{2,0,400},{2,0,400},{2,0,400},{0,10,1},{0,10,1},{0,10,1},{0,5,1},{0,4,157},{0,4,157},{3,22,854},{3,15,459},{3,12,666},{3,11,470},{1,21,1515},{1,13,459},{1,11,3},{0,9,651},{0,11,2070},{0,9,891},{4,20,430},{4,15,14},{5,11,51},{4,11,91},{9,5,1514},{0,14,425},{1,11,2},{0,9,602},{23,0,1514},{0,9,602},{3,17,433},{3,17,433},{3,17,433},
+{3,10,433},{1,16,339},{1,11,2},{1,11,2},{1,7,42},{0,8,613},{0,7,173},{4,15,10},{4,15,10},{4,15,10},{4,9,13},{9,0,338},{1,11,1},{1,11,1},{0,7,29},{18,0,338},{0,7,29},{14,0,421},{4,15,5},{6,11,1},{1,11,1},{14,0,421},{28,0,421},{1,11,1},{0,9,433},{28,0,421},{0,9,433},{3,0,433},{3,0,433},{3,0,433},{3,0,433},{1,11,2},
+{1,11,2},{1,11,2},{1,6,2},{0,6,97},{0,6,97},{4,23,866},{4,16,461},{4,12,670},{4,12,494},{2,22,1515},{2,14,459},{2,12,3},{1,10,651},{0,12,1913},{0,10,677},{5,21,430},{5,16,14},{6,12,50},{5,12,90},{13,0,1514},{1,15,425},{2,12,2},{0,10,533},{26,0,1514},{0,10,533},{4,18,446},{4,18,446},{4,18,446},{4,11,446},{2,17,339},{2,12,3},{2,12,3},
+{2,8,42},{0,10,500},{0,8,65},{5,16,10},{5,16,10},{5,16,10},{5,10,13},{10,1,338},{2,12,2},{2,12,2},{0,8,16},{21,0,338},{0,8,16},{15,1,421},{5,16,5},{7,12,1},{2,12,1},{15,1,421},{31,0,421},{2,12,1},{0,10,433},{31,0,421},{0,10,433},{4,0,445},{4,0,445},{4,0,445},{4,0,445},{2,12,2},{2,12,2},{2,12,2},{2,7,2},{0,8,49},
+{0,8,49},{5,24,854},{5,18,458},{5,14,678},{5,13,470},{3,23,1517},{3,15,461},{3,13,5},{2,11,653},{0,14,1758},{0,11,530},{7,20,437},{6,17,17},{7,13,53},{6,13,81},{14,1,1517},{2,16,422},{3,13,5},{0,11,494},{29,0,1517},{0,11,494},{5,19,433},{5,19,433},{5,19,433},{5,12,433},{3,18,340},{3,13,4},{3,13,4},{3,9,41},{0,12,419},{0,10,19},{7,15,16},
+{7,15,16},{7,15,16},{7,11,16},{12,0,338},{3,13,4},{3,13,4},{0,10,10},{24,0,338},{0,10,10},{17,0,421},{6,17,1},{8,13,1},{3,13,1},{17,0,421},{30,2,421},{3,13,1},{0,11,445},{30,2,421},{0,11,445},{5,0,433},{5,0,433},{5,0,433},{5,0,433},{3,14,1},{3,14,1},{3,14,1},{3,8,1},{0,10,10},{0,10,10},{6,25,854},{6,19,458},{6,15,678},
+{6,14,470},{4,24,1515},{4,16,459},{4,14,3},{3,12,666},{0,16,1658},{0,12,459},{7,23,437},{7,18,17},{8,14,51},{7,14,81},{16,0,1514},{3,17,422},{4,14,2},{0,12,458},{24,4,1514},{0,12,458},{6,20,433},{6,20,433},{6,20,433},{6,13,433},{4,19,339},{4,14,2},{4,14,2},{4,10,42},{0,13,365},{0,11,14},{7,18,16},{7,18,16},{7,18,16},{7,12,20},{13,1,338},
+{4,14,1},{4,14,1},{0,11,10},{27,0,338},{0,11,10},{18,1,421},{7,18,1},{9,14,1},{4,14,1},{18,1,421},{31,3,421},{4,14,1},{0,12,433},{31,3,421},{0,12,433},{6,0,433},{6,0,433},{6,0,433},{6,0,433},{4,14,2},{4,14,2},{4,14,2},{4,9,2},{0,11,5},{0,11,5},{7,26,854},{7,19,459},{7,16,666},{7,15,470},{5,25,1515},{5,17,459},{5,15,3},
+{4,13,651},{0,17,1577},{1,13,459},{8,24,430},{8,19,14},{9,15,51},{8,15,91},{17,1,1514},{4,18,425},{5,15,2},{0,13,437},{27,4,1514},{0,13,437},{7,21,433},{7,21,433},{7,21,433},{7,14,433},{5,20,339},{5,15,2},{5,15,2},{5,11,42},{0,15,339},{1,12,21},{8,19,10},{8,19,10},{8,19,10},{8,13,13},{15,0,338},{5,15,1},{5,15,1},{1,12,17},{30,0,338},
+{1,12,17},{20,0,421},{8,19,5},{10,15,1},{5,15,1},{20,0,421},{30,5,421},{5,15,1},{0,13,433},{30,5,421},{0,13,433},{7,0,433},{7,0,433},{7,0,433},{7,0,433},{5,15,2},{5,15,2},{5,15,2},{5,10,2},{1,12,5},{1,12,5},{8,27,866},{8,20,461},{8,16,670},{8,16,494},{6,26,1515},{6,18,459},{6,16,3},{5,14,651},{0,19,1530},{2,14,459},{9,25,430},
+{9,20,14},{10,16,50},{9,16,90},{19,0,1514},{5,19,425},{6,16,2},{0,14,434},{30,4,1514},{0,14,434},{8,22,446},{8,22,446},{8,22,446},{8,15,446},{6,21,339},{6,16,3},{6,16,3},{6,12,42},{1,16,339},{2,13,21},{9,20,10},{9,20,10},{9,20,10},{9,14,13},{16,1,338},{6,16,2},{6,16,2},{4,12,16},{31,1,338},{4,12,16},{21,1,421},{9,20,5},{11,16,1},
+{6,16,1},{21,1,421},{31,6,421},{6,16,1},{0,14,433},{31,6,421},{0,14,433},{8,0,445},{8,0,445},{8,0,445},{8,0,445},{6,16,2},{6,16,2},{6,16,2},{6,11,2},{2,13,5},{2,13,5},{9,28,854},{9,22,458},{9,18,678},{9,17,470},{7,27,1517},{7,19,461},{7,17,5},{6,15,653},{1,20,1526},{3,15,461},{11,24,437},{10,21,17},{11,17,53},{10,17,81},{20,1,1517},
+{6,20,422},{7,17,5},{2,15,446},{31,5,1517},{2,15,446},{9,23,433},{9,23,433},{9,23,433},{9,16,433},{7,22,340},{7,17,4},{7,17,4},{7,13,41},{2,17,340},{4,14,19},{11,19,16},{11,19,16},{11,19,16},{11,15,16},{16,4,338},{7,17,4},{7,17,4},{4,14,10},{28,4,338},{4,14,10},{23,0,421},{10,21,1},{12,17,1},{7,17,1},{23,0,421},{30,8,421},{7,17,1},
+{0,15,445},{30,8,421},{0,15,445},{9,0,433},{9,0,433},{9,0,433},{9,0,433},{7,18,1},{7,18,1},{7,18,1},{7,12,1},{4,14,10},{4,14,10},{10,29,854},{10,23,458},{10,19,678},{10,18,470},{8,28,1515},{8,20,459},{8,18,3},{7,16,666},{2,21,1526},{4,16,459},{11,27,437},{11,22,17},{12,18,51},{11,18,81},{20,4,1514},{7,21,422},{8,18,2},{2,16,434},{28,8,1514},
+{2,16,434},{10,24,433},{10,24,433},{10,24,433},{10,17,433},{8,23,339},{8,18,2},{8,18,2},{8,14,42},{3,18,340},{4,15,14},{11,22,16},{11,22,16},{11,22,16},{11,16,20},{17,5,338},{8,18,1},{8,18,1},{4,15,10},{31,4,338},{4,15,10},{24,1,421},{11,22,1},{13,18,1},{8,18,1},{24,1,421},{31,9,421},{8,18,1},{0,16,433},{31,9,421},{0,16,433},{10,0,433},
+{10,0,433},{10,0,433},{10,0,433},{8,18,2},{8,18,2},{8,18,2},{8,13,2},{4,15,5},{4,15,5},{11,30,854},{11,23,459},{11,20,666},{11,19,470},{9,29,1515},{9,21,459},{9,19,3},{8,17,651},{3,22,1526},{5,17,459},{12,28,430},{12,23,14},{13,19,51},{12,19,91},{21,5,1514},{8,22,425},{9,19,2},{3,17,434},{31,8,1514},{3,17,434},{11,25,433},{11,25,433},{11,25,433},
+{11,18,433},{9,24,339},{9,19,2},{9,19,2},{9,15,42},{4,19,339},{5,16,21},{12,23,10},{12,23,10},{12,23,10},{12,17,13},{21,0,338},{9,19,1},{9,19,1},{5,16,17},{30,6,338},{5,16,17},{26,0,421},{12,23,5},{14,19,1},{9,19,1},{26,0,421},{30,11,421},{9,19,1},{0,17,433},{30,11,421},{0,17,433},{11,0,433},{11,0,433},{11,0,433},{11,0,433},{9,19,2},
+{9,19,2},{9,19,2},{9,14,2},{5,16,5},{5,16,5},{12,31,866},{12,24,461},{12,20,670},{12,20,494},{10,30,1515},{10,22,459},{10,20,3},{9,18,651},{4,23,1530},{6,18,459},{13,29,430},{13,24,14},{14,20,50},{13,20,90},{25,0,1514},{9,23,425},{10,20,2},{4,18,434},{30,10,1514},{4,18,434},{12,26,446},{12,26,446},{12,26,446},{12,19,446},{10,25,339},{10,20,3},{10,20,3},
+{10,16,42},{5,20,339},{6,17,21},{13,24,10},{13,24,10},{13,24,10},{13,18,13},{22,1,338},{10,20,2},{10,20,2},{8,16,16},{31,7,338},{8,16,16},{27,1,421},{13,24,5},{15,20,1},{10,20,1},{27,1,421},{31,12,421},{10,20,1},{0,18,433},{31,12,421},{0,18,433},{12,0,445},{12,0,445},{12,0,445},{12,0,445},{10,20,2},{10,20,2},{10,20,2},{10,15,2},{6,17,5},
+{6,17,5},{13,31,878},{13,26,458},{13,22,678},{13,21,470},{11,31,1517},{11,23,461},{11,21,5},{10,19,653},{5,24,1526},{7,19,461},{15,28,437},{14,25,17},{15,21,53},{14,21,81},{26,1,1517},{10,24,422},{11,21,5},{6,19,446},{31,11,1517},{6,19,446},{13,27,433},{13,27,433},{13,27,433},{13,20,433},{11,26,340},{11,21,4},{11,21,4},{11,17,41},{6,21,340},{8,18,19},{15,23,16},
+{15,23,16},{15,23,16},{15,19,16},{24,0,338},{11,21,4},{11,21,4},{8,18,10},{24,12,338},{8,18,10},{29,0,421},{14,25,1},{16,21,1},{11,21,1},{29,0,421},{30,14,421},{11,21,1},{0,19,445},{30,14,421},{0,19,445},{13,0,433},{13,0,433},{13,0,433},{13,0,433},{11,22,1},{11,22,1},{11,22,1},{11,16,1},{8,18,10},{8,18,10},{14,31,938},{14,27,458},{14,23,678},
+{14,22,470},{12,31,1542},{12,24,459},{12,22,3},{11,20,666},{6,25,1526},{8,20,459},{15,31,437},{15,26,17},{16,22,51},{15,22,81},{28,0,1514},{11,25,422},{12,22,2},{6,20,434},{24,16,1514},{6,20,434},{14,28,433},{14,28,433},{14,28,433},{14,21,433},{12,27,339},{12,22,2},{12,22,2},{12,18,42},{7,22,340},{8,19,14},{15,26,16},{15,26,16},{15,26,16},{15,20,20},{25,1,338},
+{12,22,1},{12,22,1},{8,19,10},{27,12,338},{8,19,10},{30,1,421},{15,26,1},{17,22,1},{12,22,1},{30,1,421},{31,15,421},{12,22,1},{0,20,433},{31,15,421},{0,20,433},{14,0,433},{14,0,433},{14,0,433},{14,0,433},{12,22,2},{12,22,2},{12,22,2},{12,17,2},{8,19,5},{8,19,5},{15,31,998},{15,27,459},{15,24,666},{15,23,470},{14,31,1598},{13,25,459},{13,23,3},
+{12,21,651},{7,26,1526},{9,21,459},{16,31,442},{16,27,14},{17,23,51},{16,23,91},{29,1,1514},{12,26,425},{13,23,2},{7,21,434},{27,16,1514},{7,21,434},{15,29,433},{15,29,433},{15,29,433},{15,22,433},{13,28,339},{13,23,2},{13,23,2},{13,19,42},{8,23,339},{9,20,21},{16,27,10},{16,27,10},{16,27,10},{16,21,13},{27,0,338},{13,23,1},{13,23,1},{9,20,17},{30,12,338},
+{9,20,17},{31,2,421},{16,27,5},{18,23,1},{13,23,1},{31,2,421},{30,17,421},{13,23,1},{0,21,433},{30,17,421},{0,21,433},{15,0,433},{15,0,433},{15,0,433},{15,0,433},{13,23,2},{13,23,2},{13,23,2},{13,18,2},{9,20,5},{9,20,5},{16,31,1086},{16,28,461},{16,24,670},{16,24,494},{15,31,1622},{14,26,459},{14,24,3},{13,22,651},{8,27,1530},{10,22,459},{18,31,446},
+{17,28,14},{18,24,50},{17,24,90},{31,0,1514},{13,27,425},{14,24,2},{8,22,434},{30,16,1514},{8,22,434},{16,30,446},{16,30,446},{16,30,446},{16,23,446},{14,29,339},{14,24,3},{14,24,3},{14,20,42},{9,24,339},{10,21,21},{17,28,10},{17,28,10},{17,28,10},{17,22,13},{28,1,338},{14,24,2},{14,24,2},{12,20,16},{31,13,338},{12,20,16},{31,5,421},{17,28,5},{19,24,1},
+{14,24,1},{31,5,421},{31,18,421},{14,24,1},{0,22,433},{31,18,421},{0,22,433},{16,0,445},{16,0,445},{16,0,445},{16,0,445},{14,24,2},{14,24,2},{14,24,2},{14,19,2},{10,21,5},{10,21,5},{18,31,1242},{17,30,458},{17,26,678},{17,25,470},{16,31,1703},{15,27,461},{15,25,5},{14,23,653},{9,28,1526},{11,23,461},{19,31,461},{18,29,17},{19,25,53},{18,25,81},{31,3,1517},
+{14,28,422},{15,25,5},{10,23,446},{31,17,1517},{10,23,446},{17,31,433},{17,31,433},{17,31,433},{17,24,433},{15,30,340},{15,25,4},{15,25,4},{15,21,41},{10,25,340},{12,22,19},{19,27,16},{19,27,16},{19,27,16},{19,23,16},{28,4,338},{15,25,4},{15,25,4},{12,22,10},{28,16,338},{12,22,10},{31,8,421},{18,29,1},{20,25,1},{15,25,1},{31,8,421},{30,20,421},{15,25,1},
+{0,23,445},{30,20,421},{0,23,445},{17,0,433},{17,0,433},{17,0,433},{17,0,433},{15,26,1},{15,26,1},{15,26,1},{15,20,1},{12,22,10},{12,22,10},{19,31,1326},{18,31,458},{18,27,678},{18,26,470},{17,31,1838},{16,28,459},{16,26,3},{15,24,666},{10,29,1526},{12,24,459},{20,31,506},{19,30,17},{20,26,51},{19,26,81},{28,12,1514},{15,29,422},{16,26,2},{10,24,434},{28,20,1514},
+{10,24,434},{18,31,442},{18,31,442},{18,31,442},{18,25,433},{16,31,339},{16,26,2},{16,26,2},{16,22,42},{11,26,340},{12,23,14},{19,30,16},{19,30,16},{19,30,16},{19,24,20},{29,5,338},{16,26,1},{16,26,1},{12,23,10},{31,16,338},{12,23,10},{31,11,421},{19,30,1},{21,26,1},{16,26,1},{31,11,421},{31,21,421},{16,26,1},{0,24,433},{31,21,421},{0,24,433},{18,0,433},
+{18,0,433},{18,0,433},{18,0,433},{16,26,2},{16,26,2},{16,26,2},{16,21,2},{12,23,5},{12,23,5},{20,31,1470},{19,31,459},{19,28,666},{19,27,470},{19,31,1911},{17,29,459},{17,27,3},{16,25,651},{11,30,1526},{13,25,459},{21,31,590},{20,31,14},{21,27,51},{20,27,91},{29,13,1514},{16,30,425},{17,27,2},{11,25,434},{31,20,1514},{11,25,434},{19,31,458},{19,31,458},{19,31,458},
+{19,26,433},{17,31,357},{17,27,2},{17,27,2},{17,23,42},{12,27,339},{13,24,21},{20,31,10},{20,31,10},{20,31,10},{20,25,13},{31,4,338},{17,27,1},{17,27,1},{13,24,17},{30,18,338},{13,24,17},{31,14,421},{20,31,5},{22,27,1},{17,27,1},{31,14,421},{30,23,421},{17,27,1},{0,25,433},{30,23,421},{0,25,433},{19,0,433},{19,0,433},{19,0,433},{19,0,433},{17,27,2},
+{17,27,2},{17,27,2},{17,22,2},{13,24,5},{13,24,5},{21,31,1650},{20,31,530},{20,28,670},{20,28,494},{20,31,2030},{18,30,459},{18,28,3},{17,26,651},{12,31,1530},{14,26,459},{23,31,650},{21,31,29},{22,28,50},{21,28,90},{31,12,1514},{17,31,425},{18,28,2},{12,26,434},{30,22,1514},{12,26,434},{20,31,494},{20,31,494},{20,31,494},{20,27,446},{18,31,411},{18,28,3},{18,28,3},
+{18,24,42},{13,28,339},{14,25,21},{21,31,13},{21,31,13},{21,31,13},{21,26,13},{31,7,338},{18,28,2},{18,28,2},{16,24,16},{31,19,338},{16,24,16},{31,17,421},{22,31,10},{23,28,1},{18,28,1},{31,17,421},{31,24,421},{18,28,1},{0,26,433},{31,24,421},{0,26,433},{20,0,445},{20,0,445},{20,0,445},{20,0,445},{18,28,2},{18,28,2},{18,28,2},{18,23,2},{14,25,5},
+{14,25,5},{22,31,1902},{21,31,723},{21,30,678},{21,29,470},{21,31,2235},{19,31,461},{19,29,5},{18,27,653},{14,31,1587},{15,27,461},{24,31,734},{23,31,65},{23,29,53},{22,29,81},{31,15,1517},{19,31,461},{19,29,5},{14,27,446},{31,23,1517},{14,27,446},{21,31,554},{21,31,554},{21,31,554},{21,28,433},{20,31,437},{19,29,4},{19,29,4},{19,25,41},{14,29,340},{16,26,19},{23,31,16},
+{23,31,16},{23,31,16},{23,27,16},{28,16,338},{19,29,4},{19,29,4},{16,26,10},{24,24,338},{16,26,10},{31,20,421},{23,31,49},{24,29,1},{19,29,1},{31,20,421},{30,26,421},{19,29,1},{0,27,445},{30,26,421},{0,27,445},{21,0,433},{21,0,433},{21,0,433},{21,0,433},{19,30,1},{19,30,1},{19,30,1},{19,24,1},{16,26,10},{16,26,10},{23,31,2074},{23,31,930},{22,31,678},
+{22,30,470},{23,31,2382},{20,31,570},{20,30,3},{19,28,666},{16,31,1703},{16,28,459},{25,31,854},{24,31,173},{24,30,51},{23,30,81},{28,24,1514},{21,31,554},{20,30,2},{14,28,434},{24,28,1514},{14,28,434},{22,31,629},{22,31,629},{22,31,629},{22,29,433},{21,31,491},{20,30,2},{20,30,2},{20,26,42},{15,30,340},{16,27,14},{24,31,29},{24,31,29},{24,31,29},{23,28,20},{29,17,338},
+{20,30,1},{20,30,1},{16,27,10},{27,24,338},{16,27,10},{31,23,421},{25,31,109},{25,30,1},{20,30,1},{31,23,421},{31,27,421},{20,30,1},{0,28,433},{31,27,421},{0,28,433},{22,0,433},{22,0,433},{22,0,433},{22,0,433},{20,30,2},{20,30,2},{20,30,2},{20,25,2},{16,27,5},{16,27,5},{24,31,2229},{24,31,1146},{23,31,689},{23,31,469},{24,31,2476},{22,31,731},{21,31,2},
+{20,29,618},{18,31,1805},{17,29,426},{26,31,953},{25,31,339},{25,31,50},{24,30,82},{29,25,1459},{23,31,620},{21,31,1},{15,29,401},{27,28,1459},{15,29,401},{23,31,689},{23,31,689},{23,31,689},{23,30,433},{22,31,581},{21,31,2},{21,31,2},{21,27,42},{16,31,339},{17,28,21},{25,31,50},{25,31,50},{25,31,50},{24,29,13},{31,16,338},{21,31,1},{21,31,1},{17,28,17},{30,24,338},
+{17,28,17},{31,26,392},{27,31,157},{26,31,0},{21,31,0},{31,26,392},{30,29,392},{21,31,0},{0,29,400},{30,29,392},{0,29,400},{23,0,433},{23,0,433},{23,0,433},{23,0,433},{21,31,2},{21,31,2},{21,31,2},{21,26,2},{17,28,5},{17,28,5},{25,31,1943},{24,31,1130},{24,31,769},{24,31,446},{25,31,2103},{23,31,573},{22,31,42},{22,29,373},{20,31,1481},{18,30,234},{27,31,657},
+{26,31,285},{26,31,89},{25,31,18},{31,23,1064},{24,31,426},{23,31,8},{16,30,209},{31,27,1064},{16,30,209},{24,31,769},{24,31,769},{24,31,769},{24,31,446},{23,31,661},{22,31,42},{22,31,42},{22,28,42},{18,31,365},{18,29,21},{26,31,89},{26,31,89},{26,31,89},{25,30,13},{31,19,338},{23,31,8},{23,31,8},{20,28,16},{31,25,338},{20,28,16},{31,27,202},{28,31,80},{27,31,4},
+{24,31,1},{31,27,202},{31,29,202},{24,31,1},{0,30,208},{31,29,202},{0,30,208},{24,0,445},{24,0,445},{24,0,445},{24,0,445},{22,31,17},{22,31,17},{22,31,17},{22,27,2},{18,29,5},{18,29,5},{27,31,1710},{26,31,1126},{25,31,917},{25,31,469},{26,31,1779},{24,31,507},{24,31,146},{23,30,154},{22,31,1221},{20,30,83},{28,31,450},{27,31,258},{27,31,137},{27,31,16},{29,29,722},
+{26,31,286},{25,31,52},{20,30,74},{31,28,722},{20,30,74},{25,31,917},{25,31,917},{25,31,917},{25,31,469},{25,31,789},{24,31,146},{24,31,146},{23,29,41},{20,31,446},{20,30,19},{27,31,137},{27,31,137},{27,31,137},{27,31,16},{28,28,338},{25,31,52},{25,31,52},{20,30,10},{28,28,338},{20,30,10},{31,29,61},{30,31,34},{29,31,0},{27,31,0},{31,29,61},{31,30,61},{27,31,0},
+{0,30,73},{31,30,61},{0,30,73},{25,0,433},{25,0,433},{25,0,433},{25,0,433},{23,31,49},{23,31,49},{23,31,49},{23,28,1},{20,30,10},{20,30,10},{27,31,1486},{27,31,1123},{27,31,1002},{26,31,554},{27,31,1519},{25,31,582},{25,31,293},{24,30,106},{23,31,1090},{20,31,14},{29,31,354},{28,31,258},{28,31,194},{28,31,50},{31,27,509},{27,31,234},{27,31,113},{20,31,10},{31,29,509},
+{20,31,10},{27,31,1002},{27,31,1002},{27,31,1002},{26,31,554},{26,31,915},{25,31,293},{25,31,293},{24,30,42},{22,31,564},{20,31,14},{28,31,194},{28,31,194},{28,31,194},{28,31,50},{29,29,338},{27,31,113},{27,31,113},{20,31,10},{31,28,338},{20,31,10},{31,30,9},{31,31,9},{30,31,9},{30,31,0},{31,30,9},{30,31,9},{30,31,0},{0,31,9},{30,31,9},{0,31,9},{26,0,433},
+{26,0,433},{26,0,433},{26,0,433},{24,31,82},{24,31,82},{24,31,82},{24,29,2},{20,31,5},{20,31,5},{28,31,1197},{28,31,1005},{27,31,917},{27,31,554},{28,31,1213},{26,31,522},{26,31,326},{25,31,17},{24,31,870},{22,31,16},{30,31,241},{29,31,182},{29,31,146},{29,31,61},{31,28,297},{28,31,153},{28,31,89},{23,31,1},{30,30,297},{23,31,1},{27,31,917},{27,31,917},{27,31,917},
+{27,31,554},{27,31,774},{26,31,326},{26,31,326},{25,31,17},{24,31,509},{22,31,16},{29,31,146},{29,31,146},{29,31,146},{29,31,61},{31,27,221},{28,31,89},{28,31,89},{23,31,1},{31,29,221},{23,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{27,0,433},{27,0,433},{27,0,433},{27,0,433},{26,31,130},
+{26,31,130},{26,31,130},{25,30,2},{22,31,16},{22,31,16},{29,31,927},{28,31,765},{28,31,701},{28,31,509},{28,31,845},{27,31,404},{27,31,283},{26,31,2},{26,31,589},{24,31,52},{30,31,97},{30,31,70},{30,31,61},{30,31,34},{31,30,118},{30,31,67},{29,31,40},{26,31,1},{30,31,118},{26,31,1},{28,31,701},{28,31,701},{28,31,701},{28,31,509},{28,31,589},{27,31,283},{27,31,283},
+{26,31,2},{25,31,386},{24,31,52},{30,31,61},{30,31,61},{30,31,61},{30,31,34},{31,29,85},{29,31,40},{29,31,40},{26,31,1},{31,30,85},{26,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{28,0,445},{28,0,445},{28,0,445},{28,0,445},{27,31,162},{27,31,162},{27,31,162},{26,31,2},{24,31,52},
+{24,31,52},{0,14,884},{0,10,117},{0,7,10},{0,6,317},{0,10,1899},{0,6,1236},{0,6,573},{0,4,1438},{0,4,2065},{0,4,1559},{0,14,884},{0,10,117},{0,7,10},{0,6,317},{5,0,1899},{0,6,1236},{0,6,573},{0,4,1438},{10,0,1899},{0,4,1438},{0,7,1},{0,7,1},{0,7,1},{0,3,4},{0,3,164},{0,3,68},{0,3,68},{0,2,104},{0,2,189},{0,1,129},{0,7,1},
+{0,7,1},{0,7,1},{0,3,4},{2,0,164},{0,3,68},{0,3,68},{0,2,104},{3,0,164},{0,2,104},{7,0,884},{0,10,117},{0,7,10},{0,6,317},{7,0,884},{14,0,884},{0,6,317},{0,5,890},{14,0,884},{0,5,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,17,884},{0,12,53},{0,8,20},
+{0,7,265},{0,11,2360},{0,8,1384},{0,7,626},{0,5,1683},{0,5,2580},{0,5,1852},{0,17,884},{0,12,53},{0,8,20},{0,7,265},{6,0,2356},{0,8,1384},{0,7,626},{0,5,1683},{10,1,2356},{0,5,1683},{0,10,1},{0,10,1},{0,10,1},{0,5,1},{0,5,338},{0,4,137},{0,4,137},{0,2,200},{0,2,381},{0,2,225},{0,10,1},{0,10,1},{0,10,1},{0,5,1},{2,1,338},
+{0,4,137},{0,4,137},{0,2,200},{5,0,338},{0,2,200},{8,1,884},{0,12,53},{1,8,5},{0,7,265},{8,1,884},{17,0,884},{0,7,265},{0,6,890},{17,0,884},{0,6,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,20,882},{0,14,16},{0,10,85},{0,8,200},{0,14,2904},{0,9,1530},{0,8,684},
+{0,6,1978},{0,6,3220},{0,5,2172},{0,20,882},{0,14,16},{1,9,84},{0,8,200},{7,0,2904},{0,9,1530},{0,8,684},{0,6,1978},{14,0,2904},{0,6,1978},{0,12,1},{0,12,1},{0,12,1},{0,6,4},{0,6,580},{0,5,218},{0,5,218},{0,3,356},{0,3,644},{0,3,420},{0,12,1},{0,12,1},{0,12,1},{0,6,4},{3,0,580},{0,5,218},{0,5,218},{0,3,356},{6,0,580},
+{0,3,356},{8,4,882},{0,14,16},{2,9,5},{0,8,200},{8,4,882},{20,0,882},{0,8,200},{0,7,890},{20,0,882},{0,7,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,23,918},{0,15,41},{1,11,153},{0,10,184},{0,16,3048},{0,11,1476},{0,9,473},{0,6,1950},{0,7,3517},{0,6,2206},{1,21,886},
+{1,15,20},{1,11,89},{0,10,184},{8,0,3048},{0,11,1476},{0,9,473},{0,6,1950},{16,0,3048},{0,6,1950},{0,15,37},{0,15,37},{0,15,37},{0,8,40},{0,9,648},{0,7,185},{0,7,185},{0,4,337},{0,4,777},{0,4,458},{1,13,5},{1,13,5},{1,13,5},{1,7,8},{4,1,648},{0,7,185},{0,7,185},{0,4,337},{9,0,648},{0,4,337},{9,5,882},{0,15,5},{3,10,5},
+{0,10,148},{9,5,882},{23,0,882},{0,10,148},{0,8,900},{23,0,882},{0,8,900},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,5},{0,1,5},{1,24,997},{1,17,123},{1,12,318},{1,11,243},{0,19,3051},{0,12,1278},{0,10,274},{0,8,1795},{0,9,3672},{0,7,2222},{2,22,885},{2,16,10},{2,12,101},{1,11,179},{10,0,3051},
+{0,12,1278},{0,10,274},{0,8,1795},{19,0,3051},{0,8,1795},{1,17,114},{1,17,114},{1,17,114},{1,9,114},{0,12,648},{0,9,85},{0,9,85},{0,5,244},{0,5,889},{0,5,413},{2,15,1},{2,15,1},{2,15,1},{2,8,5},{4,4,648},{0,9,85},{0,9,85},{0,5,244},{12,0,648},{0,5,244},{13,0,884},{2,16,9},{4,11,10},{0,11,90},{13,0,884},{26,0,884},{0,11,90},
+{0,9,890},{26,0,884},{0,9,890},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,6,1},{0,6,1},{0,6,1},{0,3,1},{0,2,50},{0,2,50},{1,27,1173},{1,18,314},{2,13,510},{1,12,374},{0,22,3051},{0,14,1139},{0,12,153},{0,9,1630},{0,10,3924},{0,8,2199},{3,23,885},{3,17,10},{3,13,101},{2,12,197},{11,0,3051},{0,14,1139},{0,12,153},{0,9,1630},{22,0,3051},
+{0,9,1630},{1,20,290},{1,20,290},{1,20,290},{1,10,293},{0,15,648},{0,10,41},{0,10,41},{0,6,181},{0,7,1027},{0,6,437},{3,16,2},{3,16,2},{3,16,2},{3,9,5},{5,5,648},{0,10,41},{0,10,41},{0,6,181},{15,0,648},{0,6,181},{14,1,884},{3,17,9},{5,12,5},{0,12,53},{14,1,884},{29,0,884},{0,12,53},{0,10,890},{29,0,884},{0,10,890},{1,0,289},
+{1,0,289},{1,0,289},{1,0,289},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{0,3,113},{0,3,113},{2,28,1365},{2,19,506},{3,14,830},{2,13,566},{0,25,3051},{0,16,1051},{0,13,36},{0,10,1483},{0,12,4164},{0,9,2174},{4,24,886},{4,18,20},{4,14,89},{3,13,197},{12,1,3051},{0,16,1051},{0,13,36},{0,10,1483},{25,0,3051},{0,10,1483},{2,21,482},{2,21,482},{2,21,482},
+{2,11,485},{0,18,648},{0,12,5},{0,12,5},{0,7,149},{0,8,1182},{0,7,510},{4,16,5},{4,16,5},{4,16,5},{4,10,8},{9,0,648},{0,12,5},{0,12,5},{0,7,149},{18,0,648},{0,7,149},{16,0,882},{3,19,10},{6,13,5},{0,13,20},{16,0,882},{24,4,882},{0,13,20},{0,11,890},{24,4,882},{0,11,890},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{0,11,1},
+{0,11,1},{0,11,1},{0,6,1},{0,5,185},{0,5,185},{2,31,1669},{3,20,818},{3,15,1161},{2,14,838},{0,28,3048},{0,17,949},{0,14,6},{0,11,1395},{0,13,4381},{0,10,2228},{5,25,886},{5,19,20},{5,15,89},{4,14,184},{12,4,3048},{0,17,949},{0,14,6},{0,11,1395},{28,0,3048},{0,11,1395},{2,24,786},{2,24,786},{2,24,786},{2,13,786},{0,21,648},{0,14,2},{0,14,2},
+{0,9,101},{0,9,1352},{0,8,590},{5,17,5},{5,17,5},{5,17,5},{5,11,8},{10,1,648},{0,14,2},{0,14,2},{0,9,101},{21,0,648},{0,9,101},{17,1,882},{4,19,5},{7,14,5},{0,14,5},{17,1,882},{27,4,882},{0,14,5},{0,12,900},{27,4,882},{0,12,900},{2,0,785},{2,0,785},{2,0,785},{2,0,785},{0,14,1},{0,14,1},{0,14,1},{0,7,1},{0,6,305},
+{0,6,305},{3,31,1814},{3,22,968},{4,16,1314},{3,15,945},{1,29,3055},{0,19,936},{1,15,17},{0,12,1314},{0,15,4321},{0,12,2007},{6,26,885},{6,20,10},{6,16,101},{5,15,179},{15,2,3051},{0,19,900},{1,15,13},{0,12,1278},{31,0,3051},{0,12,1278},{3,25,900},{3,25,900},{3,25,900},{3,14,900},{1,22,654},{1,15,8},{1,15,8},{0,10,76},{0,11,1296},{0,9,425},{6,19,1},
+{6,19,1},{6,19,1},{6,12,5},{12,0,648},{1,15,4},{1,15,4},{0,10,40},{24,0,648},{0,10,40},{19,0,884},{6,20,9},{8,15,10},{1,15,9},{19,0,884},{30,4,884},{1,15,9},{0,13,890},{30,4,884},{0,13,890},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{1,16,5},{1,16,5},{1,16,5},{1,8,8},{0,7,269},{0,7,269},{5,31,1838},{4,23,948},{5,17,1314},
+{4,16,943},{2,30,3055},{1,20,936},{2,16,13},{1,13,1314},{0,16,4056},{0,13,1620},{7,27,885},{7,21,10},{7,17,101},{6,16,197},{17,0,3051},{0,21,891},{2,16,9},{0,13,1179},{30,2,3051},{0,13,1179},{4,26,891},{4,26,891},{4,26,891},{4,15,891},{2,23,654},{2,16,9},{2,16,9},{1,11,76},{0,13,1107},{0,10,273},{7,20,2},{7,20,2},{7,20,2},{7,13,5},{13,1,648},
+{3,15,5},{3,15,5},{0,11,20},{27,0,648},{0,11,20},{20,1,884},{7,21,9},{9,16,5},{2,16,5},{20,1,884},{31,5,884},{2,16,5},{0,14,890},{31,5,884},{0,14,890},{4,0,890},{4,0,890},{4,0,890},{4,0,890},{2,17,5},{2,17,5},{2,17,5},{2,9,8},{0,9,149},{0,9,149},{6,31,1868},{5,24,948},{6,18,1314},{5,17,943},{3,31,3055},{2,21,936},{3,17,13},
+{2,14,1314},{0,18,3825},{0,14,1354},{8,28,886},{8,22,20},{8,18,89},{7,17,197},{18,1,3051},{1,22,891},{3,17,9},{0,14,1098},{31,3,3051},{0,14,1098},{5,27,891},{5,27,891},{5,27,891},{5,16,891},{3,24,652},{3,17,9},{3,17,9},{2,12,86},{0,14,976},{0,12,126},{8,20,5},{8,20,5},{8,20,5},{8,14,8},{15,0,648},{4,16,5},{4,16,5},{0,12,5},{30,0,648},
+{0,12,5},{20,4,882},{7,23,10},{10,17,5},{3,17,5},{20,4,882},{28,8,882},{3,17,5},{0,15,890},{28,8,882},{0,15,890},{5,0,890},{5,0,890},{5,0,890},{5,0,890},{3,18,5},{3,18,5},{3,18,5},{3,10,8},{0,11,80},{0,11,80},{7,31,1908},{6,25,948},{7,19,1314},{6,18,943},{4,31,3084},{3,22,936},{4,18,15},{3,15,1314},{0,19,3640},{0,15,1175},{9,29,886},
+{9,23,20},{9,19,89},{8,18,184},{20,0,3048},{2,23,891},{4,18,6},{0,15,1054},{24,8,3048},{0,15,1054},{6,28,891},{6,28,891},{6,28,891},{6,17,891},{4,25,657},{4,18,11},{4,18,11},{3,13,86},{0,16,852},{0,13,27},{9,21,5},{9,21,5},{9,21,5},{9,15,8},{16,1,648},{4,18,2},{4,18,2},{0,13,2},{31,1,648},{0,13,2},{21,5,882},{8,23,5},{11,18,5},
+{4,18,5},{21,5,882},{31,8,882},{4,18,5},{0,16,900},{31,8,882},{0,16,900},{6,0,890},{6,0,890},{6,0,890},{6,0,890},{4,18,10},{4,18,10},{4,18,10},{4,11,10},{0,13,26},{0,13,26},{8,31,1998},{7,26,968},{8,20,1314},{7,19,945},{6,31,3160},{4,23,936},{5,19,17},{4,16,1314},{0,21,3420},{0,16,1028},{10,30,885},{10,24,10},{10,20,101},{9,19,179},{22,0,3051},
+{3,24,891},{5,19,13},{0,16,1003},{30,7,3051},{0,16,1003},{7,29,900},{7,29,900},{7,29,900},{7,18,900},{5,26,654},{5,19,8},{5,19,8},{4,14,76},{0,18,750},{1,14,24},{10,23,1},{10,23,1},{10,23,1},{10,16,5},{16,4,648},{5,19,4},{5,19,4},{2,14,5},{28,4,648},{2,14,5},{25,0,884},{10,24,9},{12,19,10},{5,19,9},{25,0,884},{30,10,884},{5,19,9},
+{0,17,890},{30,10,884},{0,17,890},{7,0,900},{7,0,900},{7,0,900},{7,0,900},{5,20,5},{5,20,5},{5,20,5},{5,12,8},{0,15,5},{0,15,5},{9,31,2124},{8,27,948},{9,21,1314},{8,20,943},{7,31,3196},{5,24,936},{6,20,13},{5,17,1314},{0,23,3307},{0,17,971},{11,31,885},{11,25,10},{11,21,101},{10,20,197},{23,0,3051},{4,25,891},{6,20,9},{0,17,970},{30,8,3051},
+{0,17,970},{8,30,891},{8,30,891},{8,30,891},{8,19,891},{6,27,654},{6,20,9},{6,20,9},{5,15,76},{0,19,691},{2,15,24},{11,24,2},{11,24,2},{11,24,2},{11,17,5},{17,5,648},{7,19,5},{7,19,5},{3,15,5},{31,4,648},{3,15,5},{26,1,884},{11,25,9},{13,20,5},{6,20,5},{26,1,884},{31,11,884},{6,20,5},{0,18,890},{31,11,884},{0,18,890},{8,0,890},
+{8,0,890},{8,0,890},{8,0,890},{6,21,5},{6,21,5},{6,21,5},{6,13,8},{1,16,5},{1,16,5},{10,31,2286},{9,28,948},{10,22,1314},{9,21,943},{8,31,3277},{6,25,936},{7,21,13},{6,18,1314},{0,24,3196},{0,19,948},{12,31,904},{12,26,20},{12,22,89},{11,21,197},{24,1,3051},{5,26,891},{7,21,9},{0,19,939},{31,9,3051},{0,19,939},{9,31,891},{9,31,891},{9,31,891},
+{9,20,891},{7,28,652},{7,21,9},{7,21,9},{6,16,86},{0,21,652},{2,16,18},{12,24,5},{12,24,5},{12,24,5},{12,18,8},{21,0,648},{8,20,5},{8,20,5},{3,16,2},{30,6,648},{3,16,2},{28,0,882},{11,27,10},{14,21,5},{7,21,5},{28,0,882},{24,16,882},{7,21,5},{0,19,890},{24,16,882},{0,19,890},{9,0,890},{9,0,890},{9,0,890},{9,0,890},{7,22,5},
+{7,22,5},{7,22,5},{7,14,8},{2,17,5},{2,17,5},{11,31,2414},{10,29,948},{11,23,1314},{10,22,943},{9,31,3412},{7,26,936},{8,22,15},{7,19,1314},{0,26,3115},{1,20,958},{13,31,958},{13,27,20},{13,23,89},{12,22,184},{24,4,3048},{6,27,891},{8,22,6},{0,20,925},{28,12,3048},{0,20,925},{10,31,894},{10,31,894},{10,31,894},{10,21,891},{8,29,657},{8,22,11},{8,22,11},
+{7,17,86},{1,22,652},{3,17,18},{13,25,5},{13,25,5},{13,25,5},{13,19,8},{22,1,648},{8,22,2},{8,22,2},{4,17,2},{31,7,648},{4,17,2},{29,1,882},{12,27,5},{15,22,5},{8,22,5},{29,1,882},{27,16,882},{8,22,5},{0,20,900},{27,16,882},{0,20,900},{10,0,890},{10,0,890},{10,0,890},{10,0,890},{8,22,10},{8,22,10},{8,22,10},{8,15,10},{3,18,5},
+{3,18,5},{13,31,2606},{11,30,968},{12,24,1314},{11,23,945},{11,31,3519},{8,27,936},{9,23,17},{8,20,1314},{0,28,3085},{2,21,942},{15,31,995},{14,28,10},{14,24,101},{13,23,179},{27,2,3051},{7,28,891},{9,23,13},{0,21,891},{31,12,3051},{0,21,891},{11,31,925},{11,31,925},{11,31,925},{11,22,900},{9,30,654},{9,23,8},{9,23,8},{8,18,76},{2,23,651},{5,18,24},{14,27,1},
+{14,27,1},{14,27,1},{14,20,5},{24,0,648},{9,23,4},{9,23,4},{6,18,5},{24,12,648},{6,18,5},{31,0,884},{14,28,9},{16,23,10},{9,23,9},{31,0,884},{30,16,884},{9,23,9},{0,21,890},{30,16,884},{0,21,890},{11,0,900},{11,0,900},{11,0,900},{11,0,900},{9,24,5},{9,24,5},{9,24,5},{9,16,8},{4,19,5},{4,19,5},{14,31,2804},{12,31,948},{13,25,1314},
+{12,24,943},{12,31,3652},{9,28,936},{10,24,13},{9,21,1314},{0,29,3052},{3,22,942},{16,31,1054},{15,29,10},{15,25,101},{14,24,197},{29,0,3051},{8,29,891},{10,24,9},{1,22,891},{30,14,3051},{1,22,891},{12,31,939},{12,31,939},{12,31,939},{12,23,891},{10,31,654},{10,24,9},{10,24,9},{9,19,76},{3,24,652},{6,19,24},{15,28,2},{15,28,2},{15,28,2},{15,21,5},{25,1,648},
+{11,23,5},{11,23,5},{7,19,5},{27,12,648},{7,19,5},{31,3,884},{15,29,9},{17,24,5},{10,24,5},{31,3,884},{31,17,884},{10,24,5},{0,22,890},{31,17,884},{0,22,890},{12,0,890},{12,0,890},{12,0,890},{12,0,890},{10,25,5},{10,25,5},{10,25,5},{10,17,8},{5,20,5},{5,20,5},{15,31,2956},{14,31,979},{14,26,1314},{13,25,943},{13,31,3841},{10,29,936},{11,25,13},
+{10,22,1314},{1,30,3052},{4,23,948},{17,31,1144},{16,30,20},{16,26,89},{15,25,197},{30,1,3051},{9,30,891},{11,25,9},{2,23,891},{31,15,3051},{2,23,891},{14,31,979},{14,31,979},{14,31,979},{13,24,891},{11,31,670},{11,25,9},{11,25,9},{10,20,86},{4,25,652},{6,20,18},{16,28,5},{16,28,5},{16,28,5},{16,22,8},{27,0,648},{12,24,5},{12,24,5},{7,20,2},{30,12,648},
+{7,20,2},{28,12,882},{15,31,10},{18,25,5},{11,25,5},{28,12,882},{28,20,882},{11,25,5},{0,23,890},{28,20,882},{0,23,890},{13,0,890},{13,0,890},{13,0,890},{13,0,890},{11,26,5},{11,26,5},{11,26,5},{11,18,8},{6,21,5},{6,21,5},{16,31,3182},{15,31,1028},{15,27,1314},{14,26,943},{15,31,4020},{11,30,936},{12,26,15},{11,23,1314},{2,31,3052},{5,24,958},{18,31,1270},
+{17,31,20},{17,27,89},{16,26,184},{28,8,3048},{10,31,891},{12,26,6},{2,24,901},{24,20,3048},{2,24,901},{15,31,1003},{15,31,1003},{15,31,1003},{14,25,891},{12,31,707},{12,26,11},{12,26,11},{11,21,86},{5,26,652},{7,21,18},{17,29,5},{17,29,5},{17,29,5},{17,23,8},{28,1,648},{12,26,2},{12,26,2},{8,21,2},{31,13,648},{8,21,2},{29,13,882},{16,31,5},{19,26,5},
+{12,26,5},{29,13,882},{31,20,882},{12,26,5},{0,24,900},{31,20,882},{0,24,900},{14,0,890},{14,0,890},{14,0,890},{14,0,890},{12,26,10},{12,26,10},{12,26,10},{12,19,10},{7,22,5},{7,22,5},{17,31,3508},{16,31,1175},{16,28,1314},{15,27,945},{16,31,4209},{12,31,936},{13,27,17},{12,24,1314},{4,31,3100},{6,25,942},{20,31,1368},{18,31,37},{18,28,101},{17,27,179},{31,6,3051},
+{12,31,900},{13,27,13},{4,25,891},{30,19,3051},{4,25,891},{16,31,1054},{16,31,1054},{16,31,1054},{15,26,900},{14,31,780},{13,27,8},{13,27,8},{12,22,76},{6,27,651},{9,22,24},{18,31,1},{18,31,1},{18,31,1},{18,24,5},{28,4,648},{13,27,4},{13,27,4},{10,22,5},{28,16,648},{10,22,5},{31,12,884},{18,31,36},{20,27,10},{13,27,9},{31,12,884},{30,22,884},{13,27,9},
+{0,25,890},{30,22,884},{0,25,890},{15,0,900},{15,0,900},{15,0,900},{15,0,900},{13,28,5},{13,28,5},{13,28,5},{13,20,8},{8,23,5},{8,23,5},{19,31,3790},{17,31,1412},{17,29,1314},{16,28,943},{17,31,4452},{14,31,954},{14,28,13},{13,25,1314},{7,31,3196},{7,26,942},{21,31,1494},{19,31,126},{19,29,101},{18,28,197},{31,8,3051},{14,31,950},{14,28,9},{5,26,891},{30,20,3051},
+{5,26,891},{17,31,1123},{17,31,1123},{17,31,1123},{16,27,891},{15,31,820},{14,28,9},{14,28,9},{13,23,76},{7,28,652},{10,23,24},{19,31,5},{19,31,5},{19,31,5},{19,25,5},{29,5,648},{15,27,5},{15,27,5},{11,23,5},{31,16,648},{11,23,5},{31,15,884},{20,31,80},{21,28,5},{14,28,5},{31,15,884},{31,23,884},{14,28,5},{0,26,890},{31,23,884},{0,26,890},{16,0,890},
+{16,0,890},{16,0,890},{16,0,890},{14,29,5},{14,29,5},{14,29,5},{14,21,8},{9,24,5},{9,24,5},{20,31,4072},{18,31,1694},{18,30,1314},{17,29,943},{19,31,4705},{15,31,1064},{15,29,13},{14,26,1314},{8,31,3355},{8,27,948},{22,31,1656},{20,31,276},{20,30,89},{19,29,197},{31,11,3051},{16,31,1054},{15,29,9},{6,27,891},{31,21,3051},{6,27,891},{18,31,1210},{18,31,1210},{18,31,1210},
+{17,28,891},{16,31,897},{15,29,9},{15,29,9},{14,24,86},{8,29,652},{10,24,18},{20,31,20},{20,31,20},{20,31,20},{20,26,8},{31,4,648},{16,28,5},{16,28,5},{11,24,2},{30,18,648},{11,24,2},{28,24,882},{22,31,157},{22,29,5},{15,29,5},{28,24,882},{24,28,882},{15,29,5},{0,27,890},{24,28,882},{0,27,890},{17,0,890},{17,0,890},{17,0,890},{17,0,890},{15,30,5},
+{15,30,5},{15,30,5},{15,22,8},{10,25,5},{10,25,5},{21,31,4390},{19,31,2007},{19,31,1314},{18,30,943},{20,31,4932},{16,31,1287},{16,30,15},{15,27,1314},{11,31,3547},{9,28,958},{23,31,1784},{22,31,465},{21,31,89},{20,30,184},{28,20,3048},{18,31,1188},{16,30,6},{6,28,901},{28,24,3048},{6,28,901},{19,31,1278},{19,31,1278},{19,31,1278},{18,29,891},{17,31,1011},{16,30,11},{16,30,11},
+{15,25,86},{9,30,652},{11,25,18},{21,31,53},{21,31,53},{21,31,53},{21,27,8},{31,7,648},{16,30,2},{16,30,2},{12,25,2},{31,19,648},{12,25,2},{29,25,882},{24,31,269},{23,30,5},{16,30,5},{29,25,882},{27,28,882},{16,30,5},{0,28,900},{27,28,882},{0,28,900},{18,0,890},{18,0,890},{18,0,890},{18,0,890},{16,30,10},{16,30,10},{16,30,10},{16,23,10},{11,26,5},
+{11,26,5},{22,31,4471},{20,31,2295},{20,31,1395},{19,31,936},{21,31,4906},{18,31,1414},{17,31,8},{16,28,1161},{13,31,3570},{11,28,818},{24,31,1769},{23,31,590},{23,31,106},{22,30,146},{29,21,2814},{19,31,1206},{17,31,4},{8,29,786},{31,24,2814},{8,29,786},{20,31,1395},{20,31,1395},{20,31,1395},{19,30,900},{19,31,1134},{17,31,8},{17,31,8},{16,26,76},{10,31,651},{13,26,24},{23,31,106},
+{23,31,106},{23,31,106},{22,28,5},{28,16,648},{17,31,4},{17,31,4},{14,26,5},{24,24,648},{14,26,5},{31,24,761},{26,31,317},{24,31,1},{17,31,0},{31,24,761},{30,28,761},{17,31,0},{0,29,785},{30,28,761},{0,29,785},{19,0,900},{19,0,900},{19,0,900},{19,0,900},{17,31,8},{17,31,8},{17,31,8},{17,24,8},{12,27,5},{12,27,5},{23,31,3955},{22,31,2260},{21,31,1530},
+{20,31,891},{22,31,4375},{19,31,1194},{18,31,54},{17,28,805},{15,31,3075},{12,29,498},{25,31,1417},{24,31,510},{24,31,149},{23,30,74},{31,19,2249},{21,31,937},{19,31,5},{11,29,482},{31,25,2249},{11,29,482},{21,31,1530},{21,31,1530},{21,31,1530},{20,31,891},{20,31,1251},{18,31,54},{18,31,54},{17,27,76},{12,31,691},{14,27,24},{24,31,149},{24,31,149},{24,31,149},{23,29,5},{29,17,648},
+{19,31,5},{19,31,5},{15,27,5},{27,24,648},{15,27,5},{29,29,481},{27,31,202},{25,31,4},{20,31,1},{29,29,481},{31,28,481},{20,31,1},{0,29,481},{31,28,481},{0,29,481},{20,0,890},{20,0,890},{20,0,890},{20,0,890},{18,31,29},{18,31,29},{18,31,29},{18,25,8},{13,28,5},{13,28,5},{24,31,3609},{23,31,2199},{22,31,1683},{21,31,915},{23,31,3827},{20,31,1071},{19,31,153},
+{18,29,485},{16,31,2690},{13,30,306},{26,31,1133},{25,31,489},{25,31,200},{24,31,20},{29,25,1769},{22,31,710},{21,31,41},{12,30,290},{27,28,1769},{12,30,290},{22,31,1683},{22,31,1683},{22,31,1683},{21,31,915},{21,31,1401},{19,31,153},{19,31,153},{18,28,86},{14,31,769},{14,28,18},{25,31,200},{25,31,200},{25,31,200},{24,30,8},{31,16,648},{21,31,41},{21,31,41},{15,28,2},{30,24,648},
+{15,28,2},{31,27,265},{28,31,113},{27,31,1},{23,31,1},{31,27,265},{31,29,265},{23,31,1},{0,30,289},{31,29,265},{0,30,289},{21,0,890},{21,0,890},{21,0,890},{21,0,890},{19,31,53},{19,31,53},{19,31,53},{19,26,8},{14,29,5},{14,29,5},{24,31,3305},{24,31,2222},{23,31,1795},{22,31,990},{24,31,3438},{22,31,1087},{21,31,306},{19,30,293},{18,31,2403},{15,30,118},{27,31,857},
+{26,31,465},{26,31,269},{25,31,8},{31,23,1374},{24,31,546},{23,31,98},{14,30,114},{31,27,1374},{14,30,114},{23,31,1795},{23,31,1795},{23,31,1795},{22,31,990},{22,31,1587},{21,31,306},{21,31,306},{19,29,86},{16,31,897},{15,29,18},{26,31,269},{26,31,269},{26,31,269},{25,31,8},{31,19,648},{23,31,98},{23,31,98},{16,29,2},{31,25,648},{16,29,2},{31,28,113},{29,31,52},{28,31,1},
+{26,31,1},{31,28,113},{30,30,113},{26,31,1},{0,30,113},{30,30,113},{0,30,113},{22,0,890},{22,0,890},{22,0,890},{22,0,890},{20,31,90},{20,31,90},{20,31,90},{20,27,10},{15,30,5},{15,30,5},{25,31,3092},{25,31,2292},{24,31,1978},{24,31,1123},{25,31,3124},{23,31,1068},{22,31,525},{20,30,140},{20,31,2196},{16,31,41},{28,31,680},{27,31,458},{27,31,337},{26,31,65},{29,29,1032},
+{26,31,456},{24,31,185},{16,31,37},{31,28,1032},{16,31,37},{24,31,1978},{24,31,1978},{24,31,1978},{24,31,1123},{24,31,1769},{22,31,525},{22,31,525},{20,30,76},{18,31,1080},{17,30,24},{27,31,337},{27,31,337},{27,31,337},{26,31,65},{28,28,648},{24,31,185},{24,31,185},{18,30,5},{28,28,648},{18,30,5},{31,30,18},{30,31,9},{30,31,0},{29,31,0},{31,30,18},{30,31,18},{29,31,0},
+{0,31,36},{30,31,18},{0,31,36},{23,0,900},{23,0,900},{23,0,900},{23,0,900},{22,31,164},{22,31,164},{22,31,164},{21,28,8},{16,31,5},{16,31,5},{27,31,2818},{26,31,2254},{25,31,2043},{25,31,1243},{26,31,2829},{24,31,1099},{23,31,684},{21,31,72},{22,31,2007},{18,31,20},{29,31,566},{28,31,420},{28,31,356},{27,31,122},{31,27,771},{27,31,386},{26,31,232},{19,31,1},{31,29,771},
+{19,31,1},{25,31,2043},{25,31,2043},{25,31,2043},{25,31,1243},{25,31,1819},{23,31,684},{23,31,684},{21,31,72},{20,31,1172},{18,31,20},{28,31,356},{28,31,356},{28,31,356},{27,31,122},{31,25,578},{26,31,232},{26,31,232},{19,31,1},{27,30,578},{19,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{24,0,890},
+{24,0,890},{24,0,890},{24,0,890},{23,31,200},{23,31,200},{23,31,200},{22,29,8},{18,31,20},{18,31,20},{27,31,2242},{27,31,1879},{26,31,1738},{26,31,1150},{27,31,2209},{24,31,987},{24,31,626},{23,31,20},{23,31,1560},{19,31,53},{29,31,342},{29,31,257},{29,31,221},{28,31,68},{31,28,452},{28,31,228},{27,31,137},{22,31,1},{30,30,452},{22,31,1},{26,31,1738},{26,31,1738},{26,31,1738},
+{26,31,1150},{25,31,1499},{24,31,626},{24,31,626},{23,31,20},{22,31,950},{19,31,53},{29,31,221},{29,31,221},{29,31,221},{28,31,68},{31,26,340},{27,31,137},{27,31,137},{22,31,1},{30,29,340},{22,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{25,0,890},{25,0,890},{25,0,890},{25,0,890},{24,31,265},
+{24,31,265},{24,31,265},{23,30,8},{19,31,53},{19,31,53},{28,31,1844},{27,31,1559},{27,31,1438},{27,31,1075},{27,31,1713},{26,31,853},{25,31,635},{24,31,10},{24,31,1207},{21,31,125},{30,31,172},{30,31,145},{29,31,125},{29,31,40},{31,29,216},{29,31,121},{28,31,68},{24,31,1},{31,30,216},{24,31,1},{27,31,1438},{27,31,1438},{27,31,1438},{27,31,1075},{27,31,1229},{25,31,635},{25,31,635},
+{24,31,10},{23,31,756},{21,31,125},{29,31,125},{29,31,125},{29,31,125},{29,31,40},{31,28,164},{28,31,68},{28,31,68},{24,31,1},{30,30,164},{24,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{26,0,890},{26,0,890},{26,0,890},{26,0,890},{25,31,346},{25,31,346},{25,31,346},{24,31,10},{21,31,125},
+{21,31,125},{0,19,1568},{0,13,202},{0,10,13},{0,8,596},{0,13,3371},{0,9,2162},{0,8,1080},{0,5,2539},{0,6,3648},{0,5,2708},{0,19,1568},{0,13,202},{0,10,13},{0,8,596},{6,1,3371},{0,9,2162},{0,8,1080},{0,5,2539},{13,0,3371},{0,5,2539},{0,9,0},{0,9,0},{0,9,0},{0,4,4},{0,4,290},{0,4,125},{0,4,125},{0,2,164},{0,2,321},{0,2,189},{0,9,0},
+{0,9,0},{0,9,0},{0,4,4},{2,1,290},{0,4,125},{0,4,125},{0,2,164},{4,0,290},{0,2,164},{9,1,1568},{0,13,202},{0,10,13},{0,8,596},{9,1,1568},{19,0,1568},{0,8,596},{0,6,1586},{19,0,1568},{0,6,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,22,1568},{0,15,117},{0,11,8},
+{0,9,485},{0,15,3971},{0,10,2369},{0,9,1061},{0,6,2834},{0,7,4341},{0,6,3090},{0,22,1568},{0,15,117},{0,11,8},{0,9,485},{7,1,3968},{0,10,2369},{0,9,1061},{0,6,2834},{11,2,3968},{0,6,2834},{0,12,1},{0,12,1},{0,12,1},{0,6,0},{0,6,512},{0,5,194},{0,5,194},{0,3,320},{0,3,576},{0,2,381},{0,12,1},{0,12,1},{0,12,1},{0,6,0},{3,0,512},
+{0,5,194},{0,5,194},{0,3,320},{6,0,512},{0,3,320},{11,0,1568},{0,15,117},{0,11,8},{0,9,485},{11,0,1568},{22,0,1568},{0,9,485},{0,7,1586},{22,0,1568},{0,7,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,1568},{0,17,45},{0,12,58},{0,10,392},{0,17,4652},{0,11,2596},{0,10,1121},
+{0,7,3254},{0,8,5140},{0,6,3570},{0,25,1568},{0,17,45},{0,12,58},{0,10,392},{8,1,4652},{0,11,2596},{0,10,1121},{0,7,3254},{17,0,4652},{0,7,3254},{0,15,1},{0,15,1},{0,15,1},{0,7,4},{0,7,802},{0,6,320},{0,6,320},{0,3,512},{0,3,896},{0,3,576},{0,15,1},{0,15,1},{0,15,1},{0,7,4},{3,2,802},{0,6,320},{0,6,320},{0,3,512},{7,0,802},
+{0,3,512},{12,1,1568},{0,17,45},{1,12,13},{0,10,392},{12,1,1568},{25,0,1568},{0,10,392},{0,8,1576},{25,0,1568},{0,8,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,28,1570},{0,19,16},{0,13,178},{0,11,340},{0,19,5424},{0,13,2843},{0,11,1240},{0,8,3704},{0,9,6003},{0,7,4095},{0,28,1570},
+{0,19,16},{1,13,122},{0,11,340},{7,5,5419},{0,13,2843},{0,11,1240},{0,8,3704},{15,2,5419},{0,8,3704},{0,18,1},{0,18,1},{0,18,1},{0,9,1},{0,9,1152},{0,7,461},{0,7,461},{0,4,709},{0,4,1281},{0,4,830},{0,18,1},{0,18,1},{0,18,1},{0,9,1},{4,1,1152},{0,7,461},{0,7,461},{0,4,709},{9,0,1152},{0,4,709},{14,0,1568},{0,19,16},{2,13,13},
+{0,11,340},{14,0,1568},{26,1,1568},{0,11,340},{0,9,1576},{26,1,1568},{0,9,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,29,1633},{1,20,75},{1,14,265},{0,13,313},{0,22,5419},{0,14,2571},{0,12,853},{0,9,3410},{0,10,6244},{0,9,3986},{1,29,1569},{1,20,11},{2,14,117},{0,13,313},{11,0,5419},
+{0,14,2571},{0,12,853},{0,9,3410},{22,0,5419},{0,9,3410},{1,19,65},{1,19,65},{1,19,65},{1,10,65},{0,12,1152},{0,9,289},{0,9,289},{0,5,580},{0,5,1393},{0,5,749},{1,19,1},{1,19,1},{1,19,1},{1,10,1},{4,4,1152},{0,9,289},{0,9,289},{0,5,580},{12,0,1152},{0,5,580},{13,5,1568},{0,21,4},{3,14,13},{0,13,232},{13,5,1568},{31,0,1568},{0,13,232},
+{0,10,1586},{31,0,1568},{0,10,1586},{1,0,65},{1,0,65},{1,0,65},{1,0,65},{0,3,1},{0,3,1},{0,3,1},{0,2,1},{0,1,20},{0,1,20},{1,31,1731},{1,22,149},{2,15,457},{1,14,377},{0,25,5419},{0,16,2347},{0,13,556},{0,10,3179},{0,11,6495},{0,9,3890},{2,30,1569},{2,21,11},{3,15,117},{1,14,313},{12,1,5419},{0,16,2347},{0,13,556},{0,10,3179},{25,0,5419},
+{0,10,3179},{1,22,145},{1,22,145},{1,22,145},{1,11,154},{0,15,1152},{0,11,194},{0,11,194},{0,6,481},{0,7,1531},{0,6,737},{2,20,1},{2,20,1},{2,20,1},{2,11,1},{5,5,1152},{0,11,194},{0,11,194},{0,6,481},{15,0,1152},{0,6,481},{17,0,1568},{1,22,4},{4,15,8},{0,14,157},{17,0,1568},{30,2,1568},{0,14,157},{0,11,1586},{30,2,1568},{0,11,1586},{1,0,145},
+{1,0,145},{1,0,145},{1,0,145},{0,6,1},{0,6,1},{0,6,1},{0,3,1},{0,3,65},{0,3,65},{2,31,1977},{2,23,341},{2,16,707},{1,15,510},{0,28,5424},{0,17,2137},{0,15,373},{0,11,3035},{0,13,6709},{0,10,3860},{3,31,1569},{3,22,11},{4,16,122},{2,15,313},{14,0,5419},{0,17,2137},{0,15,373},{0,11,3035},{26,1,5419},{0,11,3035},{2,23,337},{2,23,337},{2,23,337},
+{2,12,341},{0,18,1152},{0,13,104},{0,13,104},{0,8,410},{0,8,1686},{0,7,786},{3,21,1},{3,21,1},{3,21,1},{3,12,2},{9,0,1152},{0,13,104},{0,13,104},{0,8,410},{18,0,1152},{0,8,410},{18,1,1568},{2,23,4},{5,16,13},{0,15,117},{18,1,1568},{31,3,1568},{0,15,117},{0,12,1576},{31,3,1568},{0,12,1576},{2,0,337},{2,0,337},{2,0,337},{2,0,337},{0,9,1},
+{0,9,1},{0,9,1},{0,5,4},{0,4,130},{0,4,130},{3,31,2353},{2,24,570},{3,17,1027},{2,16,714},{0,31,5424},{0,19,1979},{0,16,195},{0,12,2857},{0,14,7039},{0,11,3919},{4,31,1576},{4,23,16},{5,17,122},{3,16,331},{15,1,5419},{0,19,1979},{0,16,195},{0,12,2857},{27,2,5419},{0,12,2857},{2,26,546},{2,26,546},{2,26,546},{2,14,546},{0,21,1152},{0,14,50},{0,14,50},
+{0,9,305},{0,9,1856},{0,8,830},{4,22,1},{4,22,1},{4,22,1},{4,13,1},{10,1,1152},{0,14,50},{0,14,50},{0,9,305},{21,0,1152},{0,9,305},{19,2,1568},{3,24,10},{6,17,13},{0,16,74},{19,2,1568},{30,5,1568},{0,16,74},{0,13,1576},{30,5,1568},{0,13,1576},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,12,0},{0,12,0},{0,12,0},{0,6,1},{0,5,205},
+{0,5,205},{4,31,2980},{3,26,925},{3,19,1484},{2,17,1032},{1,31,5504},{0,21,1811},{0,17,61},{0,13,2651},{0,16,7420},{0,13,3876},{6,31,1619},{5,24,11},{6,18,117},{4,17,313},{17,0,5419},{0,21,1811},{0,17,61},{0,13,2651},{30,2,5419},{0,13,2651},{3,27,900},{3,27,900},{3,27,900},{3,15,900},{0,24,1152},{0,16,8},{0,16,8},{0,10,208},{0,11,2124},{0,9,881},{5,23,1},
+{5,23,1},{5,23,1},{5,14,1},{12,0,1152},{0,16,8},{0,16,8},{0,10,208},{24,0,1152},{0,10,208},{21,1,1568},{4,25,4},{7,18,13},{0,17,45},{21,1,1568},{27,8,1568},{0,17,45},{0,14,1586},{27,8,1568},{0,14,1586},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{0,15,1},{0,15,1},{0,15,1},{0,8,4},{0,6,356},{0,6,356},{4,31,3668},{3,27,1320},{4,20,1940},
+{3,18,1352},{2,31,5771},{0,23,1737},{0,18,37},{0,14,2486},{0,17,7711},{0,14,3930},{7,31,1635},{6,25,11},{7,19,117},{5,18,313},{18,1,5419},{0,23,1737},{0,18,37},{0,14,2486},{31,3,5419},{0,14,2486},{3,30,1252},{3,30,1252},{3,30,1252},{3,16,1256},{0,27,1152},{0,18,1},{0,18,1},{0,11,164},{0,12,2369},{0,10,1001},{6,24,1},{6,24,1},{6,24,1},{6,15,1},{13,1,1152},
+{0,18,1},{0,18,1},{0,11,164},{27,0,1152},{0,11,164},{23,0,1568},{5,26,4},{8,19,8},{0,18,36},{23,0,1568},{30,8,1568},{0,18,36},{0,15,1586},{30,8,1568},{0,15,1586},{3,0,1252},{3,0,1252},{3,0,1252},{3,0,1252},{0,18,1},{0,18,1},{0,18,1},{0,9,1},{0,7,505},{0,7,505},{5,31,4346},{4,28,1644},{5,21,2372},{4,19,1703},{3,31,6079},{0,24,1644},{0,20,38},
+{0,15,2390},{0,18,7969},{0,15,3907},{8,31,1682},{7,26,11},{8,20,122},{6,19,313},{19,2,5419},{0,24,1640},{0,20,34},{0,15,2386},{30,5,5419},{0,15,2386},{4,31,1587},{4,31,1587},{4,31,1587},{4,17,1590},{0,30,1156},{0,20,29},{0,20,29},{0,12,117},{0,13,2483},{0,11,1044},{7,25,1},{7,25,1},{7,25,1},{7,16,2},{15,0,1152},{1,19,1},{1,19,1},{0,12,113},{30,0,1152},
+{0,12,113},{24,1,1568},{6,27,4},{9,20,13},{0,20,25},{24,1,1568},{31,9,1568},{0,20,25},{0,16,1576},{31,9,1568},{0,16,1576},{4,0,1586},{4,0,1586},{4,0,1586},{4,0,1586},{0,21,5},{0,21,5},{0,21,5},{0,11,8},{0,9,565},{0,9,565},{7,31,4580},{5,29,1644},{6,22,2372},{4,20,1692},{4,31,6228},{1,25,1644},{1,21,38},{1,16,2348},{0,20,7577},{0,16,3408},{9,31,1760},
+{8,27,16},{9,21,122},{7,20,331},{19,5,5419},{0,26,1593},{2,20,27},{0,16,2252},{31,6,5419},{0,16,2252},{5,31,1590},{5,31,1590},{5,31,1590},{5,18,1590},{1,31,1156},{1,21,29},{1,21,29},{1,13,117},{0,15,2241},{0,13,699},{8,26,1},{8,26,1},{8,26,1},{8,17,1},{16,1,1152},{2,20,2},{2,20,2},{0,13,74},{31,1,1152},{0,13,74},{26,0,1568},{7,28,10},{10,21,13},
+{0,21,10},{26,0,1568},{30,11,1568},{0,21,10},{0,17,1576},{30,11,1568},{0,17,1576},{5,0,1586},{5,0,1586},{5,0,1586},{5,0,1586},{1,22,5},{1,22,5},{1,22,5},{1,12,8},{0,10,433},{0,10,433},{8,31,4826},{6,30,1644},{7,23,2352},{6,21,1676},{5,31,6463},{2,26,1644},{2,22,38},{2,17,2348},{0,22,7196},{0,17,2863},{11,31,1865},{9,28,11},{10,22,117},{8,21,313},{23,0,5419},
+{1,27,1586},{2,22,29},{0,18,2115},{30,8,5419},{0,18,2115},{6,31,1612},{6,31,1612},{6,31,1612},{6,19,1585},{3,30,1179},{3,21,29},{3,21,29},{2,14,122},{0,17,1953},{0,14,426},{9,27,1},{9,27,1},{9,27,1},{9,18,1},{16,4,1152},{3,21,4},{3,21,4},{0,15,49},{28,4,1152},{0,15,49},{25,5,1568},{8,29,4},{11,22,13},{1,22,4},{25,5,1568},{31,12,1568},{1,22,4},
+{0,18,1586},{31,12,1568},{0,18,1586},{6,0,1576},{6,0,1576},{6,0,1576},{6,0,1576},{2,24,10},{2,24,10},{2,24,10},{2,13,10},{0,13,272},{0,13,272},{9,31,5108},{7,31,1644},{8,24,2372},{7,22,1676},{7,31,6660},{3,27,1644},{3,23,38},{3,18,2348},{0,23,6891},{0,18,2519},{12,31,1952},{10,29,11},{11,23,117},{9,22,313},{24,1,5419},{2,28,1584},{3,23,29},{0,19,2027},{31,9,5419},
+{0,19,2027},{7,31,1640},{7,31,1640},{7,31,1640},{7,20,1580},{4,31,1188},{3,23,34},{3,23,34},{3,15,122},{0,19,1795},{0,15,261},{10,28,1},{10,28,1},{10,28,1},{10,19,1},{17,5,1152},{4,22,1},{4,22,1},{0,16,26},{31,4,1152},{0,16,26},{29,0,1568},{9,30,4},{12,23,8},{2,23,4},{29,0,1568},{30,14,1568},{2,23,4},{0,19,1586},{30,14,1568},{0,19,1586},{7,0,1576},
+{7,0,1576},{7,0,1576},{7,0,1576},{3,24,10},{3,24,10},{3,24,10},{3,14,10},{0,14,170},{0,14,170},{10,31,5426},{8,31,1695},{9,25,2372},{8,23,1703},{8,31,6861},{4,28,1644},{4,24,38},{3,19,2372},{0,25,6573},{0,19,2268},{13,31,2066},{11,30,11},{12,24,122},{10,23,313},{26,0,5419},{3,29,1584},{4,24,34},{0,20,1937},{30,11,5419},{0,20,1937},{8,31,1686},{8,31,1686},{8,31,1686},
+{8,21,1590},{5,31,1206},{4,24,29},{4,24,29},{4,16,117},{0,20,1602},{0,17,126},{11,29,1},{11,29,1},{11,29,1},{11,20,2},{21,0,1152},{5,23,1},{5,23,1},{0,17,5},{30,6,1152},{0,17,5},{30,1,1568},{10,31,4},{13,24,13},{3,24,10},{30,1,1568},{31,15,1568},{3,24,10},{0,20,1576},{31,15,1568},{0,20,1576},{8,0,1586},{8,0,1586},{8,0,1586},{8,0,1586},{4,25,5},
+{4,25,5},{4,25,5},{4,15,8},{0,16,90},{0,16,90},{11,31,5658},{9,31,1836},{10,26,2372},{8,24,1692},{9,31,7116},{5,29,1644},{5,25,38},{5,20,2348},{0,26,6379},{0,21,2028},{14,31,2216},{12,31,16},{13,25,122},{11,24,331},{27,1,5419},{2,31,1584},{6,24,27},{0,21,1832},{27,14,5419},{0,21,1832},{9,31,1755},{9,31,1755},{9,31,1755},{9,22,1590},{6,31,1260},{5,25,29},{5,25,29},
+{5,17,117},{0,22,1459},{0,18,38},{12,30,1},{12,30,1},{12,30,1},{12,21,1},{22,1,1152},{6,24,2},{6,24,2},{0,18,2},{31,7,1152},{0,18,2},{31,2,1568},{11,31,13},{14,25,13},{4,25,10},{31,2,1568},{30,17,1568},{4,25,10},{0,21,1576},{30,17,1568},{0,21,1576},{9,0,1586},{9,0,1586},{9,0,1586},{9,0,1586},{5,26,5},{5,26,5},{5,26,5},{5,16,8},{0,18,37},
+{0,18,37},{12,31,6036},{11,31,2033},{11,27,2352},{10,25,1676},{11,31,7423},{6,30,1644},{6,26,38},{6,21,2348},{0,28,6109},{0,22,1794},{15,31,2371},{13,31,50},{14,26,117},{12,25,313},{29,0,5419},{5,31,1586},{6,26,29},{0,22,1730},{30,14,5419},{0,22,1730},{10,31,1865},{10,31,1865},{10,31,1865},{10,23,1585},{7,31,1339},{7,25,29},{7,25,29},{6,18,122},{0,23,1345},{0,19,16},{13,31,1},
+{13,31,1},{13,31,1},{13,22,1},{24,0,1152},{7,25,4},{7,25,4},{2,19,1},{24,12,1152},{2,19,1},{29,9,1568},{14,31,41},{15,26,13},{5,26,4},{29,9,1568},{27,20,1568},{5,26,4},{0,22,1586},{27,20,1568},{0,22,1586},{10,0,1576},{10,0,1576},{10,0,1576},{10,0,1576},{6,28,10},{6,28,10},{6,28,10},{6,17,10},{0,20,13},{0,20,13},{13,31,6450},{12,31,2268},{12,28,2372},
+{11,26,1676},{12,31,7676},{7,31,1644},{7,27,38},{7,22,2348},{0,30,5924},{0,23,1695},{17,31,2536},{15,31,139},{15,27,117},{13,26,313},{30,1,5419},{7,31,1635},{7,27,29},{0,23,1686},{31,15,5419},{0,23,1686},{11,31,1937},{11,31,1937},{11,31,1937},{11,24,1580},{9,31,1420},{7,27,34},{7,27,34},{7,19,122},{0,25,1234},{1,20,17},{14,31,10},{14,31,10},{14,31,10},{14,23,1},{25,1,1152},
+{8,26,1},{8,26,1},{2,20,2},{27,12,1152},{2,20,2},{31,8,1568},{15,31,90},{16,27,8},{6,27,4},{31,8,1568},{30,20,1568},{6,27,4},{0,23,1586},{30,20,1568},{0,23,1586},{11,0,1576},{11,0,1576},{11,0,1576},{11,0,1576},{7,28,10},{7,28,10},{7,28,10},{7,18,10},{0,21,10},{0,21,10},{15,31,6772},{13,31,2595},{13,29,2372},{12,27,1703},{13,31,7985},{8,31,1725},{8,28,38},
+{7,23,2372},{0,31,5773},{0,24,1644},{18,31,2722},{16,31,261},{16,28,122},{14,27,313},{31,2,5419},{8,31,1721},{8,28,34},{0,24,1640},{30,17,5419},{0,24,1640},{12,31,2027},{12,31,2027},{12,31,2027},{12,25,1590},{10,31,1510},{8,28,29},{8,28,29},{8,20,117},{0,27,1188},{2,21,17},{15,31,26},{15,31,26},{15,31,26},{15,24,2},{27,0,1152},{9,27,1},{9,27,1},{3,21,2},{30,12,1152},
+{3,21,2},{31,11,1568},{17,31,180},{17,28,13},{7,28,10},{31,11,1568},{31,21,1568},{7,28,10},{0,24,1576},{31,21,1568},{0,24,1576},{12,0,1586},{12,0,1586},{12,0,1586},{12,0,1586},{8,29,5},{8,29,5},{8,29,5},{8,19,8},{1,22,10},{1,22,10},{16,31,7154},{14,31,2955},{14,30,2372},{12,28,1692},{14,31,8348},{10,31,1895},{9,29,38},{9,24,2348},{1,31,5956},{1,25,1644},{19,31,2866},
+{17,31,468},{17,29,122},{15,28,331},{31,5,5419},{10,31,1859},{10,28,27},{0,25,1601},{31,18,5419},{0,25,1601},{13,31,2162},{13,31,2162},{13,31,2162},{13,26,1590},{11,31,1590},{9,29,29},{9,29,29},{9,21,117},{0,28,1161},{3,22,17},{16,31,49},{16,31,49},{16,31,49},{16,25,1},{28,1,1152},{10,28,2},{10,28,2},{4,22,2},{31,13,1152},{4,22,2},{31,14,1568},{19,31,277},{18,29,13},
+{8,29,10},{31,14,1568},{30,23,1568},{8,29,10},{0,25,1576},{30,23,1568},{0,25,1576},{13,0,1586},{13,0,1586},{13,0,1586},{13,0,1586},{9,30,5},{9,30,5},{9,30,5},{9,20,8},{2,23,10},{2,23,10},{17,31,7636},{15,31,3408},{15,31,2352},{14,29,1676},{16,31,8673},{11,31,2187},{10,30,38},{10,25,2348},{3,31,6235},{2,26,1644},{20,31,3112},{19,31,754},{18,30,117},{16,29,313},{31,8,5419},
+{12,31,2060},{10,30,29},{0,26,1587},{30,20,5419},{0,26,1587},{15,31,2252},{15,31,2252},{15,31,2252},{14,27,1585},{12,31,1740},{11,29,29},{11,29,29},{10,22,122},{0,30,1163},{4,23,16},{18,31,85},{18,31,85},{18,31,85},{17,26,1},{28,4,1152},{11,29,4},{11,29,4},{6,23,1},{28,16,1152},{6,23,1},{29,21,1568},{20,31,436},{19,30,13},{9,30,4},{29,21,1568},{31,24,1568},{9,30,4},
+{0,26,1586},{31,24,1568},{0,26,1586},{14,0,1576},{14,0,1576},{14,0,1576},{14,0,1576},{10,31,13},{10,31,13},{10,31,13},{10,21,10},{3,24,10},{3,24,10},{18,31,8122},{16,31,3907},{16,31,2390},{15,30,1676},{17,31,9036},{12,31,2576},{11,31,38},{11,26,2348},{6,31,6555},{3,27,1644},{22,31,3392},{20,31,1044},{19,31,117},{17,30,313},{31,11,5419},{15,31,2284},{11,31,29},{0,27,1587},{31,21,5419},
+{0,27,1587},{16,31,2386},{16,31,2386},{16,31,2386},{15,28,1580},{14,31,1924},{11,31,34},{11,31,34},{11,23,122},{1,31,1163},{5,24,17},{19,31,113},{19,31,113},{19,31,113},{18,27,1},{29,5,1152},{12,30,1},{12,30,1},{6,24,2},{31,16,1152},{6,24,2},{31,20,1568},{22,31,593},{20,31,8},{10,31,4},{31,20,1568},{30,26,1568},{10,31,4},{0,27,1586},{30,26,1568},{0,27,1586},{15,0,1576},
+{15,0,1576},{15,0,1576},{15,0,1576},{11,31,25},{11,31,25},{11,31,25},{11,22,10},{4,25,10},{4,25,10},{19,31,7638},{17,31,4060},{17,31,2539},{16,30,1659},{18,31,8553},{14,31,2430},{13,31,37},{11,27,1940},{7,31,6120},{4,28,1320},{23,31,2996},{20,31,1064},{20,31,164},{19,30,186},{29,17,4803},{16,31,2018},{13,31,1},{1,28,1253},{27,24,4803},{1,28,1253},{17,31,2539},{17,31,2539},{17,31,2539},
+{16,29,1590},{15,31,2028},{13,31,37},{13,31,37},{12,24,117},{3,31,1170},{6,25,17},{20,31,164},{20,31,164},{20,31,164},{19,28,2},{31,4,1152},{13,31,1},{13,31,1},{7,25,2},{30,18,1152},{7,25,2},{31,22,1250},{24,31,505},{22,31,0},{13,31,0},{31,22,1250},{30,27,1250},{13,31,0},{0,28,1252},{30,27,1250},{0,28,1252},{16,0,1586},{16,0,1586},{16,0,1586},{16,0,1586},{13,31,37},
+{13,31,37},{13,31,37},{12,23,8},{5,26,10},{5,26,10},{20,31,7060},{19,31,3955},{18,31,2710},{17,31,1595},{19,31,7717},{15,31,2140},{14,31,77},{13,28,1480},{8,31,5539},{6,28,925},{23,31,2516},{22,31,945},{21,31,233},{20,30,100},{31,15,4056},{18,31,1656},{15,31,8},{4,28,900},{31,23,4056},{4,28,900},{18,31,2710},{18,31,2710},{18,31,2710},{17,30,1590},{16,31,2193},{14,31,77},{14,31,77},
+{13,25,117},{5,31,1233},{7,26,17},{21,31,233},{21,31,233},{21,31,233},{20,29,1},{31,7,1152},{15,31,8},{15,31,8},{8,26,2},{31,19,1152},{8,26,2},{31,23,884},{25,31,370},{23,31,4},{16,31,1},{31,23,884},{31,27,884},{16,31,1},{0,28,900},{31,27,884},{0,28,900},{17,0,1586},{17,0,1586},{17,0,1586},{17,0,1586},{14,31,52},{14,31,52},{14,31,52},{13,24,8},{6,27,10},
+{6,27,10},{21,31,6535},{20,31,3919},{19,31,2857},{18,31,1585},{20,31,6979},{16,31,1942},{15,31,195},{14,28,990},{11,31,4914},{7,29,562},{24,31,2045},{23,31,830},{22,31,338},{21,31,26},{29,21,3318},{19,31,1314},{17,31,52},{5,29,546},{31,24,3318},{5,29,546},{19,31,2857},{19,31,2857},{19,31,2857},{18,31,1585},{17,31,2436},{15,31,195},{15,31,195},{14,26,122},{7,31,1339},{8,27,16},{22,31,338},
+{22,31,338},{22,31,338},{21,30,1},{28,16,1152},{17,31,52},{17,31,52},{10,27,1},{24,24,1152},{10,27,1},{31,25,545},{26,31,221},{25,31,0},{19,31,0},{31,25,545},{31,28,545},{19,31,0},{0,29,545},{31,28,545},{0,29,545},{18,0,1576},{18,0,1576},{18,0,1576},{18,0,1576},{15,31,74},{15,31,74},{15,31,74},{14,25,10},{7,28,10},{7,28,10},{22,31,6151},{20,31,3935},{20,31,3035},
+{19,31,1640},{21,31,6458},{18,31,1902},{16,31,373},{15,29,670},{12,31,4499},{8,29,347},{25,31,1729},{24,31,786},{23,31,410},{22,31,1},{31,19,2753},{20,31,1094},{19,31,113},{8,29,338},{31,25,2753},{8,29,338},{20,31,3035},{20,31,3035},{20,31,3035},{19,31,1640},{19,31,2630},{16,31,373},{16,31,373},{15,27,122},{10,31,1483},{9,28,17},{23,31,410},{23,31,410},{23,31,410},{22,31,1},{29,17,1152},
+{19,31,113},{19,31,113},{10,28,2},{27,24,1152},{10,28,2},{31,26,317},{27,31,130},{26,31,9},{22,31,0},{31,26,317},{30,29,317},{22,31,0},{0,29,337},{30,29,317},{0,29,337},{19,0,1576},{19,0,1576},{19,0,1576},{19,0,1576},{16,31,117},{16,31,117},{16,31,117},{15,26,10},{8,29,10},{8,29,10},{23,31,5691},{22,31,4004},{21,31,3254},{20,31,1755},{22,31,6023},{19,31,1830},{18,31,606},
+{16,29,430},{14,31,4162},{9,30,155},{26,31,1481},{25,31,801},{24,31,505},{23,31,26},{29,25,2273},{22,31,914},{20,31,194},{9,30,146},{27,28,2273},{9,30,146},{21,31,3254},{21,31,3254},{21,31,3254},{20,31,1755},{20,31,2835},{18,31,606},{18,31,606},{16,28,117},{11,31,1665},{10,29,17},{24,31,505},{24,31,505},{24,31,505},{23,31,26},{31,16,1152},{20,31,194},{20,31,194},{11,29,2},{30,24,1152},
+{11,29,2},{31,28,145},{28,31,65},{28,31,1},{25,31,0},{31,28,145},{30,30,145},{25,31,0},{0,30,145},{30,30,145},{0,30,145},{20,0,1586},{20,0,1586},{20,0,1586},{20,0,1586},{17,31,180},{17,31,180},{17,31,180},{16,27,8},{9,30,10},{9,30,10},{24,31,5421},{23,31,3999},{22,31,3491},{21,31,1947},{23,31,5539},{20,31,1879},{19,31,853},{17,30,238},{16,31,3922},{11,30,81},{27,31,1229},
+{26,31,813},{26,31,617},{24,31,100},{31,23,1878},{23,31,822},{22,31,305},{12,30,66},{31,27,1878},{12,30,66},{22,31,3491},{22,31,3491},{22,31,3491},{21,31,1947},{21,31,3081},{19,31,853},{19,31,853},{17,29,117},{14,31,1905},{11,30,17},{26,31,617},{26,31,617},{26,31,617},{24,31,100},{31,19,1152},{22,31,305},{22,31,305},{12,30,2},{31,25,1152},{12,30,2},{31,29,45},{30,31,18},{29,31,4},
+{28,31,1},{31,29,45},{31,30,45},{28,31,1},{0,30,65},{31,30,45},{0,30,65},{21,0,1586},{21,0,1586},{21,0,1586},{21,0,1586},{18,31,261},{18,31,261},{18,31,261},{17,28,8},{10,31,10},{10,31,10},{24,31,5178},{24,31,4095},{23,31,3704},{22,31,2201},{24,31,5197},{21,31,2101},{20,31,1240},{18,31,153},{18,31,3760},{12,31,16},{28,31,1088},{27,31,830},{27,31,709},{26,31,245},{29,29,1536},
+{26,31,792},{24,31,461},{14,31,1},{31,28,1536},{14,31,1},{23,31,3704},{23,31,3704},{23,31,3704},{22,31,2201},{23,31,3396},{20,31,1240},{20,31,1240},{18,30,122},{15,31,2208},{12,31,16},{27,31,709},{27,31,709},{27,31,709},{26,31,245},{28,28,1152},{24,31,461},{24,31,461},{14,31,1},{28,28,1152},{14,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},
+{0,31,0},{31,31,0},{0,31,0},{22,0,1576},{22,0,1576},{22,0,1576},{22,0,1576},{20,31,340},{20,31,340},{20,31,340},{18,29,10},{12,31,16},{12,31,16},{25,31,4468},{24,31,3615},{24,31,3254},{23,31,2060},{24,31,4413},{22,31,1834},{21,31,1205},{19,31,58},{19,31,3127},{14,31,53},{28,31,768},{28,31,576},{28,31,512},{27,31,170},{31,26,1068},{26,31,536},{25,31,338},{16,31,1},{30,29,1068},
+{16,31,1},{24,31,3254},{24,31,3254},{24,31,3254},{23,31,2060},{23,31,2852},{21,31,1205},{21,31,1205},{19,31,58},{16,31,1878},{14,31,53},{28,31,512},{28,31,512},{28,31,512},{27,31,170},{31,24,802},{25,31,338},{25,31,338},{16,31,1},{30,28,802},{16,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{23,0,1576},
+{23,0,1576},{23,0,1576},{23,0,1576},{21,31,421},{21,31,421},{21,31,421},{19,30,10},{14,31,53},{14,31,53},{26,31,3858},{25,31,3188},{25,31,2899},{24,31,1947},{25,31,3700},{23,31,1596},{23,31,1112},{20,31,8},{20,31,2588},{16,31,117},{29,31,498},{28,31,384},{28,31,320},{27,31,122},{31,27,683},{27,31,342},{26,31,212},{19,31,1},{31,29,683},{19,31,1},{25,31,2899},{25,31,2899},{25,31,2899},
+{24,31,1947},{24,31,2441},{23,31,1112},{23,31,1112},{20,31,8},{18,31,1568},{16,31,117},{28,31,320},{28,31,320},{28,31,320},{27,31,122},{29,29,512},{26,31,212},{26,31,212},{19,31,1},{31,28,512},{19,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{24,0,1586},{24,0,1586},{24,0,1586},{24,0,1586},{22,31,520},
+{22,31,520},{22,31,520},{20,31,8},{16,31,117},{16,31,117},{27,31,3258},{26,31,2790},{26,31,2594},{25,31,1875},{26,31,3105},{24,31,1447},{23,31,1080},{21,31,20},{22,31,2151},{18,31,208},{29,31,306},{29,31,221},{29,31,185},{28,31,64},{31,28,384},{28,31,192},{27,31,125},{22,31,1},{30,30,384},{22,31,1},{26,31,2594},{26,31,2594},{26,31,2594},{25,31,1875},{25,31,2131},{23,31,1080},{23,31,1080},
+{21,31,20},{20,31,1336},{18,31,208},{29,31,185},{29,31,185},{29,31,185},{28,31,64},{31,27,290},{27,31,125},{27,31,125},{22,31,1},{31,29,290},{22,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{25,0,1586},{25,0,1586},{25,0,1586},{25,0,1586},{23,31,596},{23,31,596},{23,31,596},{21,31,20},{18,31,208},
+{18,31,208},{0,25,2669},{0,18,320},{0,13,5},{0,11,985},{0,17,5885},{0,11,3745},{0,10,1746},{0,7,4421},{0,8,6385},{0,7,4782},{0,25,2669},{0,18,320},{0,13,5},{0,11,985},{8,1,5885},{0,11,3745},{0,10,1746},{0,7,4421},{17,0,5885},{0,7,4421},{0,12,0},{0,12,0},{0,12,0},{0,6,1},{0,6,545},{0,5,205},{0,5,205},{0,3,337},{0,3,609},{0,3,401},{0,12,0},
+{0,12,0},{0,12,0},{0,6,1},{3,0,545},{0,5,205},{0,5,205},{0,3,337},{6,0,545},{0,3,337},{13,0,2669},{0,18,320},{0,13,5},{0,11,985},{13,0,2669},{25,0,2669},{0,11,985},{0,8,2689},{25,0,2669},{0,8,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,28,2665},{0,20,212},{0,14,10},
+{0,12,850},{0,19,6669},{0,13,3974},{0,11,1837},{0,8,4865},{0,9,7266},{0,7,5310},{0,28,2665},{0,20,212},{0,14,10},{0,12,850},{9,1,6669},{0,13,3974},{0,11,1837},{0,8,4865},{19,0,6669},{0,8,4865},{0,15,0},{0,15,0},{0,15,0},{0,7,9},{0,7,845},{0,6,337},{0,6,337},{0,3,545},{0,3,945},{0,3,609},{0,15,0},{0,15,0},{0,15,0},{0,7,9},{3,2,841},
+{0,6,337},{0,6,337},{0,3,545},{6,1,841},{0,3,545},{12,4,2665},{0,20,212},{1,14,5},{0,12,850},{12,4,2665},{28,0,2665},{0,12,850},{0,9,2689},{28,0,2665},{0,9,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,2665},{0,21,113},{0,15,65},{0,13,709},{0,21,7538},{0,14,4289},{0,12,1907},
+{0,9,5330},{0,10,8294},{0,8,5845},{0,31,2665},{0,21,113},{0,15,65},{0,13,709},{10,1,7538},{0,14,4289},{0,12,1907},{0,9,5330},{21,0,7538},{0,9,5330},{0,18,0},{0,18,0},{0,18,0},{0,9,0},{0,9,1201},{0,7,482},{0,7,482},{0,4,740},{0,4,1334},{0,4,861},{0,18,0},{0,18,0},{0,18,0},{0,9,0},{4,1,1201},{0,7,482},{0,7,482},{0,4,740},{9,0,1201},
+{0,4,740},{13,5,2665},{0,21,113},{2,15,5},{0,13,709},{13,5,2665},{31,0,2665},{0,13,709},{0,10,2689},{31,0,2665},{0,10,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,2809},{0,23,52},{0,16,173},{0,14,586},{0,23,8494},{0,15,4610},{0,13,1950},{0,9,5826},{0,11,9409},{0,9,6402},{1,31,2753},
+{0,23,52},{1,16,132},{0,14,586},{11,1,8493},{0,15,4610},{0,13,1950},{0,9,5826},{19,2,8493},{0,9,5826},{0,21,0},{0,21,0},{0,21,0},{0,10,9},{0,10,1629},{0,9,640},{0,9,640},{0,5,985},{0,5,1798},{0,5,1154},{0,21,0},{0,21,0},{0,21,0},{0,10,9},{3,5,1625},{0,9,640},{0,9,640},{0,5,985},{7,2,1625},{0,5,985},{17,0,2665},{0,23,52},{2,16,13},
+{0,14,586},{17,0,2665},{30,2,2665},{0,14,586},{0,11,2689},{30,2,2665},{0,11,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,31,3105},{0,25,8},{1,17,325},{0,15,512},{0,25,9669},{0,17,4961},{0,14,2120},{0,10,6421},{0,12,10774},{0,10,7150},{2,31,3033},{0,25,8},{1,17,261},{0,15,512},{12,1,9669},
+{0,17,4961},{0,14,2120},{0,10,6421},{25,0,9669},{0,10,6421},{0,24,0},{0,24,0},{0,24,0},{0,12,0},{0,12,2178},{0,9,865},{0,9,865},{0,6,1313},{0,5,2419},{0,5,1523},{0,24,0},{0,24,0},{0,24,0},{0,12,0},{4,4,2178},{0,9,865},{0,9,865},{0,6,1313},{12,0,2178},{0,6,1313},{19,0,2669},{0,25,8},{4,17,5},{0,15,512},{19,0,2669},{31,3,2669},{0,15,512},
+{0,12,2689},{31,3,2669},{0,12,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,31,3465},{0,27,65},{1,19,434},{0,17,474},{0,28,9670},{0,18,4658},{0,16,1717},{0,11,6209},{0,13,10979},{0,11,7109},{3,31,3101},{1,26,8},{2,18,261},{0,17,474},{14,0,9669},{0,18,4658},{0,16,1717},{0,11,6209},{26,1,9669},
+{0,11,6209},{1,25,64},{1,25,64},{1,25,64},{1,13,64},{0,15,2178},{0,11,680},{0,11,680},{0,7,1189},{0,7,2557},{0,6,1457},{1,25,0},{1,25,0},{1,25,0},{1,13,0},{5,5,2178},{0,11,680},{0,11,680},{0,7,1189},{15,0,2178},{0,7,1189},{20,0,2665},{0,27,1},{5,18,5},{0,17,410},{20,0,2665},{24,8,2665},{0,17,410},{0,13,2689},{24,8,2665},{0,13,2689},{0,0,64},
+{0,0,64},{0,0,64},{0,0,64},{0,3,0},{0,3,0},{0,3,0},{0,2,4},{0,1,13},{0,1,13},{3,31,3917},{1,28,129},{2,20,645},{1,18,538},{0,31,9670},{0,20,4330},{0,17,1246},{0,12,5925},{0,14,11321},{0,12,7014},{4,31,3218},{2,27,8},{3,19,261},{1,18,474},{15,1,9669},{0,20,4330},{0,17,1246},{0,12,5925},{27,2,9669},{0,12,5925},{1,28,128},{1,28,128},{1,28,128},
+{1,15,132},{0,18,2178},{0,13,482},{0,13,482},{0,8,1040},{0,8,2712},{0,7,1470},{2,26,0},{2,26,0},{2,26,0},{2,14,0},{9,0,2178},{0,13,482},{0,13,482},{0,8,1040},{18,0,2178},{0,8,1040},{21,1,2665},{1,28,1},{6,19,5},{0,18,305},{21,1,2665},{27,8,2665},{0,18,305},{0,14,2689},{27,8,2665},{0,14,2689},{1,0,128},{1,0,128},{1,0,128},{1,0,128},{0,6,0},
+{0,6,0},{0,6,0},{0,3,0},{0,2,61},{0,2,61},{3,31,4541},{2,29,321},{2,21,904},{1,19,625},{1,31,9749},{0,21,4018},{0,18,914},{0,14,5633},{0,16,11661},{0,13,6859},{5,31,3374},{3,28,10},{4,20,254},{2,19,474},{17,0,9670},{0,21,4018},{0,18,914},{0,14,5633},{30,2,9670},{0,14,5633},{2,29,320},{2,29,320},{2,29,320},{1,16,320},{0,21,2178},{0,15,353},{0,15,353},
+{0,9,881},{0,9,2882},{0,9,1457},{3,27,0},{3,27,0},{3,27,0},{3,15,0},{10,1,2178},{0,15,353},{0,15,353},{0,9,881},{21,0,2178},{0,9,881},{23,0,2665},{2,29,1},{6,20,13},{0,19,245},{23,0,2665},{30,8,2665},{0,19,245},{0,15,2689},{30,8,2665},{0,15,2689},{1,0,320},{1,0,320},{1,0,320},{1,0,320},{0,9,0},{0,9,0},{0,9,0},{0,4,4},{0,4,125},
+{0,4,125},{4,31,5378},{2,31,570},{3,22,1267},{2,20,850},{2,31,10045},{0,23,3745},{0,19,642},{0,14,5354},{0,17,11993},{0,14,6798},{7,31,3553},{4,29,8},{5,21,261},{3,20,491},{18,1,9669},{0,23,3745},{0,19,642},{0,14,5354},{31,3,9669},{0,14,5354},{2,31,561},{2,31,561},{2,31,561},{2,17,546},{0,24,2178},{0,17,205},{0,17,205},{0,10,730},{0,11,3150},{0,9,1457},{4,28,0},
+{4,28,0},{4,28,0},{4,16,0},{12,0,2178},{0,17,205},{0,17,205},{0,10,730},{24,0,2178},{0,10,730},{25,0,2669},{3,30,1},{8,21,5},{0,20,170},{25,0,2669},{31,9,2669},{0,20,170},{0,16,2689},{31,9,2669},{0,16,2689},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,12,0},{0,12,0},{0,12,0},{0,6,1},{0,5,205},{0,5,205},{5,31,6330},{3,31,905},{4,23,1718},
+{2,21,1099},{3,31,10453},{0,25,3478},{0,21,369},{0,16,5138},{0,18,12455},{0,15,6867},{8,31,3710},{5,30,8},{6,22,261},{4,21,474},{19,2,9669},{0,25,3478},{0,21,369},{0,16,5138},{30,5,9669},{0,16,5138},{3,31,901},{3,31,901},{3,31,901},{3,18,866},{0,27,2178},{0,19,130},{0,19,130},{0,11,650},{0,12,3395},{0,10,1523},{5,29,0},{5,29,0},{5,29,0},{5,17,0},{13,1,2178},
+{0,19,130},{0,19,130},{0,11,650},{27,0,2178},{0,11,650},{24,4,2665},{4,31,1},{9,22,5},{0,21,113},{24,4,2665},{28,12,2665},{0,21,113},{0,17,2689},{28,12,2665},{0,17,2689},{3,0,865},{3,0,865},{3,0,865},{3,0,865},{0,15,0},{0,15,0},{0,15,0},{0,7,9},{0,6,337},{0,6,337},{6,31,7446},{4,31,1458},{4,24,2174},{3,22,1419},{3,31,11045},{0,27,3314},{0,22,195},
+{0,17,4865},{0,20,12855},{0,16,6882},{9,31,3902},{6,31,8},{7,23,261},{5,22,474},{19,5,9669},{0,27,3314},{0,22,195},{0,17,4865},{31,6,9669},{0,17,4865},{3,31,1397},{3,31,1397},{3,31,1397},{3,19,1210},{0,30,2178},{0,20,61},{0,20,61},{0,12,545},{0,13,3645},{0,12,1634},{6,30,0},{6,30,0},{6,30,0},{6,18,0},{15,0,2178},{0,20,61},{0,20,61},{0,12,545},{30,0,2178},
+{0,12,545},{25,5,2665},{6,31,8},{10,23,5},{0,22,74},{25,5,2665},{31,12,2665},{0,22,74},{0,18,2689},{31,12,2665},{0,18,2689},{3,0,1201},{3,0,1201},{3,0,1201},{3,0,1201},{0,18,0},{0,18,0},{0,18,0},{0,9,0},{0,7,482},{0,7,482},{7,31,8578},{4,31,2146},{5,25,2766},{3,23,1835},{4,31,11766},{0,28,3125},{0,23,94},{0,18,4610},{0,21,13238},{0,17,6837},{10,31,4130},
+{7,31,49},{8,24,254},{6,23,474},{23,0,9670},{0,28,3125},{0,23,94},{0,18,4610},{30,8,9670},{0,18,4610},{4,31,1921},{4,31,1921},{4,31,1921},{3,21,1665},{0,31,2228},{0,22,18},{0,22,18},{0,14,425},{0,15,3987},{0,13,1677},{7,31,0},{7,31,0},{7,31,0},{7,19,0},{16,1,2178},{0,22,18},{0,22,18},{0,14,425},{31,1,2178},{0,14,425},{29,0,2665},{7,31,49},{10,24,13},
+{0,23,58},{29,0,2665},{30,14,2665},{0,23,58},{0,19,2689},{30,14,2665},{0,19,2689},{3,0,1665},{3,0,1665},{3,0,1665},{3,0,1665},{0,21,0},{0,21,0},{0,21,0},{0,10,9},{0,9,640},{0,9,640},{7,31,10135},{5,31,3190},{5,26,3543},{4,24,2348},{5,31,12846},{0,30,2961},{0,25,30},{0,19,4421},{0,23,13846},{0,18,6930},{11,31,4345},{8,31,178},{9,25,261},{7,24,491},{24,1,9669},
+{0,30,2961},{0,25,30},{0,19,4421},{31,9,9669},{0,19,4421},{5,31,2706},{5,31,2706},{5,31,2706},{4,22,2179},{1,31,2404},{0,24,0},{0,24,0},{0,15,337},{0,16,4356},{0,14,1833},{8,31,9},{8,31,9},{8,31,9},{8,20,0},{16,4,2178},{0,24,0},{0,24,0},{0,15,337},{28,4,2178},{0,15,337},{31,0,2669},{10,31,113},{12,25,5},{0,25,26},{31,0,2669},{31,15,2669},{0,25,26},
+{0,20,2689},{31,15,2669},{0,20,2689},{4,0,2178},{4,0,2178},{4,0,2178},{4,0,2178},{0,24,0},{0,24,0},{0,24,0},{0,12,0},{0,9,865},{0,9,865},{8,31,11466},{6,31,4187},{6,27,4166},{4,25,2818},{6,31,13898},{0,31,2871},{0,26,15},{0,20,4226},{0,24,14214},{0,19,7006},{12,31,4590},{10,31,321},{10,26,261},{8,25,474},{26,0,9669},{0,31,2870},{0,26,14},{0,20,4225},{30,11,9669},
+{0,20,4225},{6,31,3458},{6,31,3458},{6,31,3458},{5,23,2690},{2,31,2691},{0,26,14},{0,26,14},{0,16,261},{0,17,4595},{0,15,1953},{9,31,36},{9,31,36},{9,31,36},{9,21,0},{17,5,2178},{1,25,0},{1,25,0},{0,16,260},{31,4,2178},{0,16,260},{28,8,2665},{11,31,194},{13,26,5},{0,26,5},{28,8,2665},{24,20,2665},{0,26,5},{0,21,2689},{24,20,2665},{0,21,2689},{5,0,2689},
+{5,0,2689},{5,0,2689},{5,0,2689},{0,27,1},{0,27,1},{0,27,1},{0,14,5},{0,11,1037},{0,11,1037},{9,31,12054},{7,31,4578},{7,28,4118},{5,26,2818},{7,31,14214},{1,31,3042},{1,27,15},{0,21,4099},{0,25,13683},{0,21,6322},{14,31,4858},{11,31,514},{11,27,261},{9,26,474},{27,1,9669},{2,31,3014},{1,27,14},{0,21,4018},{27,14,9669},{0,21,4018},{7,31,3554},{7,31,3554},{7,31,3554},
+{6,24,2689},{3,31,2795},{1,27,14},{1,27,14},{1,17,261},{0,19,4269},{0,16,1517},{11,31,73},{11,31,73},{11,31,73},{10,22,0},{21,0,2178},{2,26,0},{2,26,0},{0,17,185},{30,6,2178},{0,17,185},{29,9,2665},{13,31,320},{14,27,5},{0,27,1},{29,9,2665},{27,20,2665},{0,27,1},{0,22,2689},{27,20,2665},{0,22,2689},{6,0,2689},{6,0,2689},{6,0,2689},{6,0,2689},{1,28,1},
+{1,28,1},{1,28,1},{1,15,5},{0,13,797},{0,13,797},{11,31,12506},{8,31,5075},{8,29,4166},{6,27,2818},{8,31,14651},{3,31,3255},{2,28,23},{1,22,4099},{0,27,13238},{0,21,5650},{15,31,5054},{12,31,782},{12,28,254},{10,27,474},{29,0,9670},{3,31,3206},{2,28,22},{0,22,3829},{30,14,9670},{0,22,3829},{8,31,3706},{8,31,3706},{8,31,3706},{7,25,2689},{4,31,2946},{2,28,19},{2,28,19},
+{2,18,261},{0,21,3906},{0,17,1106},{12,31,106},{12,31,106},{12,31,106},{11,23,0},{22,1,2178},{3,27,0},{3,27,0},{0,18,128},{31,7,2178},{0,18,128},{31,8,2665},{15,31,445},{14,28,13},{1,28,4},{31,8,2665},{30,20,2665},{1,28,4},{0,23,2689},{30,20,2665},{0,23,2689},{7,0,2689},{7,0,2689},{7,0,2689},{7,0,2689},{2,29,1},{2,29,1},{2,29,1},{2,15,10},{0,14,637},
+{0,14,637},{12,31,13094},{10,31,5782},{9,30,4166},{7,28,2838},{10,31,15213},{4,31,3618},{3,29,25},{2,23,4101},{0,29,12686},{0,23,5075},{16,31,5378},{14,31,1172},{13,29,261},{11,28,491},{30,1,9669},{6,31,3469},{3,29,21},{0,23,3706},{31,15,9669},{0,23,3706},{9,31,3890},{9,31,3890},{9,31,3890},{8,26,2690},{6,31,3157},{3,29,24},{3,29,24},{3,19,254},{0,23,3619},{0,19,782},{13,31,145},
+{13,31,145},{13,31,145},{12,24,0},{24,0,2178},{4,28,0},{4,28,0},{0,19,106},{24,12,2178},{0,19,106},{31,11,2669},{16,31,640},{16,29,5},{2,29,2},{31,11,2669},{31,21,2669},{2,29,2},{0,24,2689},{31,21,2669},{0,24,2689},{8,0,2689},{8,0,2689},{8,0,2689},{8,0,2689},{3,30,5},{3,30,5},{3,30,5},{3,17,8},{0,17,436},{0,17,436},{13,31,13718},{11,31,6325},{10,31,4166},
+{8,29,2818},{11,31,15565},{6,31,4094},{4,30,15},{3,24,4118},{0,31,12355},{0,24,4578},{17,31,5738},{15,31,1517},{14,30,261},{12,29,474},{31,2,9669},{7,31,3761},{4,30,14},{0,24,3554},{30,17,9669},{0,24,3554},{10,31,4085},{10,31,4085},{10,31,4085},{9,27,2690},{7,31,3285},{4,30,14},{4,30,14},{4,20,261},{0,24,3330},{0,20,514},{14,31,208},{14,31,208},{14,31,208},{13,25,0},{25,1,2178},
+{5,29,0},{5,29,0},{0,21,64},{27,12,2178},{0,21,64},{28,20,2665},{18,31,829},{17,30,5},{3,30,2},{28,20,2665},{28,24,2665},{3,30,2},{0,25,2689},{28,24,2665},{0,25,2689},{9,0,2689},{9,0,2689},{9,0,2689},{9,0,2689},{4,31,1},{4,31,1},{4,31,1},{4,18,5},{0,18,306},{0,18,306},{14,31,14378},{12,31,7006},{11,31,4226},{9,30,2818},{12,31,16054},{7,31,4578},{5,31,15},
+{4,25,4099},{0,31,12051},{0,25,4089},{19,31,5970},{16,31,1953},{15,31,261},{13,30,474},{31,5,9669},{10,31,4081},{5,31,14},{0,25,3413},{31,18,9669},{0,25,3413},{11,31,4225},{11,31,4225},{11,31,4225},{10,28,2689},{8,31,3476},{5,31,14},{5,31,14},{5,21,261},{0,26,3091},{0,21,289},{15,31,260},{15,31,260},{15,31,260},{14,26,0},{27,0,2178},{6,30,0},{6,30,0},{0,22,25},{30,12,2178},
+{0,22,25},{29,21,2665},{20,31,1037},{18,31,5},{4,31,1},{29,21,2665},{31,24,2665},{4,31,1},{0,26,2689},{31,24,2665},{0,26,2689},{10,0,2689},{10,0,2689},{10,0,2689},{10,0,2689},{5,31,10},{5,31,10},{5,31,10},{5,19,5},{0,20,194},{0,20,194},{15,31,13557},{13,31,7094},{12,31,4421},{10,31,2769},{13,31,15228},{8,31,4270},{6,31,46},{5,26,3476},{0,31,11020},{0,26,3108},{20,31,5400},
+{17,31,1931},{16,31,337},{15,30,320},{31,7,8712},{11,31,3630},{7,31,0},{0,26,2667},{31,19,8712},{0,26,2667},{12,31,4421},{12,31,4421},{12,31,4421},{11,29,2689},{9,31,3722},{6,31,46},{6,31,46},{6,22,261},{0,27,2882},{0,22,173},{16,31,337},{16,31,337},{16,31,337},{15,27,0},{28,1,2178},{7,31,0},{7,31,0},{0,23,9},{31,13,2178},{0,23,9},{31,19,2178},{22,31,881},{19,31,0},
+{7,31,0},{31,19,2178},{31,25,2178},{7,31,0},{0,27,2178},{31,25,2178},{0,27,2178},{11,0,2689},{11,0,2689},{11,0,2689},{11,0,2689},{6,31,37},{6,31,37},{6,31,37},{6,19,10},{0,22,109},{0,22,109},{16,31,12678},{14,31,7003},{13,31,4693},{12,31,2714},{15,31,14026},{10,31,3943},{8,31,94},{6,26,2766},{2,31,10074},{0,27,2146},{20,31,4698},{19,31,1746},{17,31,464},{16,30,164},{29,13,7578},
+{12,31,3090},{9,31,20},{0,27,1921},{31,20,7578},{0,27,1921},{13,31,4693},{13,31,4693},{13,31,4693},{12,30,2690},{11,31,3939},{8,31,94},{8,31,94},{7,23,254},{0,29,2650},{0,24,49},{17,31,464},{17,31,464},{17,31,464},{16,28,0},{28,4,2178},{9,31,20},{9,31,20},{0,24,0},{28,16,2178},{0,24,0},{31,21,1625},{23,31,653},{21,31,4},{10,31,1},{31,21,1625},{31,26,1625},{10,31,1},
+{0,27,1665},{31,26,1625},{0,27,1665},{12,0,2689},{12,0,2689},{12,0,2689},{12,0,2689},{8,31,58},{8,31,58},{8,31,58},{7,21,8},{0,24,49},{0,24,49},{17,31,12042},{15,31,6882},{15,31,4946},{13,31,2690},{16,31,13127},{11,31,3615},{9,31,229},{7,27,2174},{3,31,9313},{0,27,1458},{21,31,4150},{19,31,1634},{19,31,545},{17,30,89},{31,11,6661},{14,31,2654},{11,31,61},{0,28,1397},{31,21,6661},
+{0,28,1397},{15,31,4946},{15,31,4946},{15,31,4946},{13,31,2690},{12,31,4170},{9,31,229},{9,31,229},{8,24,261},{0,31,2520},{0,25,10},{19,31,545},{19,31,545},{19,31,545},{17,29,0},{29,5,2178},{11,31,61},{11,31,61},{1,25,0},{31,16,2178},{1,25,0},{31,22,1201},{24,31,482},{22,31,1},{13,31,1},{31,22,1201},{30,27,1201},{13,31,1},{0,28,1201},{30,27,1201},{0,28,1201},{13,0,2689},
+{13,0,2689},{13,0,2689},{13,0,2689},{9,31,85},{9,31,85},{9,31,85},{8,22,5},{0,25,10},{0,25,10},{18,31,11474},{16,31,6867},{15,31,5138},{14,31,2725},{16,31,12279},{12,31,3410},{10,31,419},{8,27,1718},{4,31,8678},{0,28,905},{23,31,3626},{20,31,1550},{20,31,650},{18,31,25},{29,17,5829},{15,31,2306},{12,31,130},{0,28,901},{27,24,5829},{0,28,901},{15,31,5138},{15,31,5138},{15,31,5138},
+{14,31,2725},{13,31,4452},{10,31,419},{10,31,419},{9,25,261},{0,31,2520},{1,26,10},{20,31,650},{20,31,650},{20,31,650},{18,30,0},{31,4,2178},{12,31,130},{12,31,130},{2,26,0},{30,18,2178},{2,26,0},{31,23,845},{25,31,353},{23,31,9},{16,31,0},{31,23,845},{31,27,845},{16,31,0},{0,28,865},{31,27,845},{0,28,865},{14,0,2689},{14,0,2689},{14,0,2689},{14,0,2689},{10,31,130},
+{10,31,130},{10,31,130},{9,23,5},{0,27,1},{0,27,1},{19,31,10774},{17,31,6962},{16,31,5378},{15,31,2810},{17,31,11598},{12,31,3346},{12,31,642},{9,28,1222},{6,31,8113},{0,29,570},{23,31,3146},{22,31,1539},{21,31,773},{19,31,0},{31,15,5082},{16,31,2034},{14,31,221},{0,29,554},{31,23,5082},{0,29,554},{16,31,5378},{16,31,5378},{16,31,5378},{15,31,2810},{15,31,4746},{12,31,642},{12,31,642},
+{10,26,261},{2,31,2714},{2,27,10},{21,31,773},{21,31,773},{21,31,773},{19,31,0},{31,7,2178},{14,31,221},{14,31,221},{3,27,0},{31,19,2178},{3,27,0},{31,25,545},{26,31,221},{25,31,0},{19,31,0},{31,25,545},{31,28,545},{19,31,0},{0,29,545},{31,28,545},{0,29,545},{15,0,2689},{15,0,2689},{15,0,2689},{15,0,2689},{11,31,170},{11,31,170},{11,31,170},{10,23,10},{1,28,1},
+{1,28,1},{20,31,10225},{18,31,7025},{18,31,5729},{16,31,2978},{19,31,10792},{14,31,3283},{13,31,982},{10,29,861},{8,31,7588},{2,29,325},{24,31,2729},{23,31,1460},{22,31,932},{20,31,36},{29,21,4344},{19,31,1746},{16,31,353},{2,29,321},{31,24,4344},{2,29,321},{18,31,5729},{18,31,5729},{18,31,5729},{16,31,2978},{16,31,5028},{13,31,982},{13,31,982},{11,27,254},{4,31,2981},{3,28,10},{22,31,932},
+{22,31,932},{22,31,932},{20,31,36},{28,16,2178},{16,31,353},{16,31,353},{4,28,0},{24,24,2178},{4,28,0},{31,27,290},{27,31,125},{27,31,4},{22,31,1},{31,27,290},{31,29,290},{22,31,1},{0,29,320},{31,29,290},{0,29,320},{16,0,2689},{16,0,2689},{16,0,2689},{16,0,2689},{12,31,245},{12,31,245},{12,31,245},{11,25,8},{2,29,5},{2,29,5},{20,31,9825},{19,31,7014},{19,31,5925},
+{17,31,3218},{20,31,10245},{15,31,3285},{14,31,1330},{11,29,612},{10,31,7225},{3,30,133},{25,31,2467},{24,31,1470},{23,31,1040},{21,31,144},{31,19,3779},{20,31,1580},{18,31,500},{3,30,129},{31,25,3779},{3,30,129},{19,31,5925},{19,31,5925},{19,31,5925},{17,31,3218},{17,31,5346},{14,31,1330},{14,31,1330},{12,28,261},{6,31,3267},{4,29,10},{23,31,1040},{23,31,1040},{23,31,1040},{21,31,144},{29,17,2178},
+{18,31,500},{18,31,500},{5,29,0},{27,24,2178},{5,29,0},{31,28,128},{29,31,61},{28,31,0},{25,31,1},{31,28,128},{30,30,128},{25,31,1},{0,30,128},{30,30,128},{0,30,128},{17,0,2689},{17,0,2689},{17,0,2689},{17,0,2689},{13,31,338},{13,31,338},{13,31,338},{12,26,5},{3,30,5},{3,30,5},{21,31,9523},{20,31,7109},{20,31,6209},{18,31,3473},{20,31,9749},{16,31,3410},{15,31,1717},
+{12,30,401},{11,31,6964},{4,31,65},{26,31,2273},{25,31,1539},{24,31,1189},{23,31,260},{29,25,3299},{22,31,1490},{20,31,680},{6,30,64},{27,28,3299},{6,30,64},{20,31,6209},{20,31,6209},{20,31,6209},{18,31,3473},{18,31,5700},{15,31,1717},{15,31,1717},{13,29,261},{8,31,3587},{5,30,10},{24,31,1189},{24,31,1189},{24,31,1189},{23,31,260},{31,16,2178},{20,31,680},{20,31,680},{6,30,0},{30,24,2178},
+{6,30,0},{31,30,34},{30,31,13},{30,31,4},{28,31,0},{31,30,34},{30,31,34},{28,31,0},{0,30,64},{30,31,34},{0,30,64},{18,0,2689},{18,0,2689},{18,0,2689},{18,0,2689},{15,31,421},{15,31,421},{15,31,421},{13,27,5},{4,31,1},{4,31,1},{23,31,9201},{21,31,7314},{21,31,6530},{19,31,3778},{21,31,9420},{18,31,3652},{16,31,2193},{14,30,325},{14,31,6804},{6,31,10},{27,31,2057},
+{26,31,1605},{25,31,1378},{24,31,442},{31,23,2904},{23,31,1452},{22,31,881},{7,31,0},{31,27,2904},{7,31,0},{21,31,6530},{21,31,6530},{21,31,6530},{19,31,3778},{19,31,5956},{16,31,2193},{16,31,2193},{14,30,261},{10,31,3957},{6,31,10},{25,31,1378},{25,31,1378},{25,31,1378},{24,31,442},{31,19,2178},{22,31,881},{22,31,881},{7,31,0},{31,25,2178},{7,31,0},{31,31,0},{31,31,0},{31,31,0},
+{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{19,0,2689},{19,0,2689},{19,0,2689},{19,0,2689},{16,31,512},{16,31,512},{16,31,512},{14,27,10},{6,31,10},{6,31,10},{23,31,8049},{22,31,6550},{22,31,5925},{20,31,3589},{23,31,8137},{19,31,3220},{18,31,2050},{15,31,173},{15,31,5805},{8,31,52},{27,31,1544},{27,31,1181},{26,31,1040},{25,31,353},{31,24,2166},
+{24,31,1083},{23,31,653},{10,31,1},{30,28,2166},{10,31,1},{22,31,5925},{22,31,5925},{22,31,5925},{20,31,3589},{20,31,5209},{18,31,2050},{18,31,2050},{15,30,117},{12,31,3405},{8,31,52},{26,31,1040},{26,31,1040},{26,31,1040},{25,31,353},{31,21,1625},{23,31,653},{23,31,653},{10,31,1},{31,26,1625},{10,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},
+{0,31,0},{31,31,0},{0,31,0},{20,0,2689},{20,0,2689},{20,0,2689},{20,0,2689},{17,31,625},{17,31,625},{17,31,625},{15,29,8},{8,31,52},{8,31,52},{24,31,7177},{23,31,5845},{23,31,5361},{21,31,3473},{23,31,7033},{20,31,2945},{19,31,1907},{16,31,65},{16,31,5026},{10,31,117},{28,31,1137},{27,31,861},{27,31,740},{26,31,260},{29,29,1601},{26,31,833},{24,31,482},{13,31,1},{31,28,1601},
+{13,31,1},{23,31,5361},{23,31,5361},{23,31,5361},{21,31,3473},{21,31,4661},{19,31,1907},{19,31,1907},{16,31,65},{14,31,2997},{10,31,117},{27,31,740},{27,31,740},{27,31,740},{26,31,260},{31,22,1201},{24,31,482},{24,31,482},{13,31,1},{30,27,1201},{13,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{21,0,2689},
+{21,0,2689},{21,0,2689},{21,0,2689},{18,31,754},{18,31,754},{18,31,754},{16,30,5},{10,31,117},{10,31,117},{24,31,6393},{24,31,5310},{23,31,4865},{22,31,3314},{24,31,6146},{20,31,2737},{20,31,1837},{17,31,5},{18,31,4381},{11,31,212},{28,31,801},{28,31,609},{28,31,545},{27,31,185},{31,26,1121},{26,31,561},{25,31,353},{16,31,0},{30,29,1121},{16,31,0},{23,31,4865},{23,31,4865},{23,31,4865},
+{22,31,3314},{22,31,4181},{20,31,1837},{20,31,1837},{17,31,5},{15,31,2621},{11,31,212},{28,31,545},{28,31,545},{28,31,545},{27,31,185},{31,23,845},{25,31,353},{25,31,353},{16,31,0},{31,27,845},{16,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{22,0,2689},{22,0,2689},{22,0,2689},{22,0,2689},{19,31,850},
+{19,31,850},{19,31,850},{17,31,5},{11,31,212},{11,31,212},{25,31,5683},{24,31,4782},{24,31,4421},{23,31,3173},{24,31,5314},{22,31,2563},{21,31,1844},{18,31,10},{18,31,3757},{13,31,338},{29,31,531},{28,31,401},{28,31,337},{27,31,121},{31,27,726},{27,31,363},{26,31,221},{19,31,0},{31,29,726},{19,31,0},{24,31,4421},{24,31,4421},{24,31,4421},{23,31,3173},{23,31,3657},{21,31,1844},{21,31,1844},
+{18,31,10},{16,31,2321},{13,31,338},{28,31,337},{28,31,337},{28,31,337},{27,31,121},{31,25,545},{26,31,221},{26,31,221},{19,31,0},{31,28,545},{19,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{23,0,2689},{23,0,2689},{23,0,2689},{23,0,2689},{20,31,985},{20,31,985},{20,31,985},{18,31,10},{13,31,338},
+{13,31,338},{2,31,10560},{0,30,1586},{0,22,173},{0,18,3826},{0,28,18065},{0,19,12194},{0,17,6081},{0,11,14098},{0,13,19386},{0,11,14998},{3,31,10216},{0,30,1586},{0,22,173},{0,18,3826},{12,4,18065},{0,19,12194},{0,17,6081},{0,11,14098},{28,0,18065},{0,11,14098},{0,17,1},{0,17,1},{0,17,1},{0,9,4},{0,9,1105},{0,7,442},{0,7,442},{0,4,680},{0,4,1230},{0,4,801},{0,17,1},
+{0,17,1},{0,17,1},{0,9,4},{4,1,1105},{0,7,442},{0,7,442},{0,4,680},{9,0,1105},{0,4,680},{21,0,9248},{0,30,1586},{0,22,173},{0,18,3826},{21,0,9248},{30,6,9248},{0,18,3826},{0,14,9248},{30,6,9248},{0,14,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,31,11328},{0,31,1341},{0,23,68},
+{0,19,3626},{0,30,19334},{0,20,12611},{0,18,6099},{0,12,14756},{0,14,20886},{0,12,15845},{3,31,10792},{0,31,1341},{0,23,68},{0,19,3626},{15,0,19334},{0,20,12611},{0,18,6099},{0,12,14756},{30,0,19334},{0,12,14756},{0,20,0},{0,20,0},{0,20,0},{0,10,1},{0,10,1513},{0,8,605},{0,8,605},{0,5,925},{0,5,1682},{0,4,1089},{0,20,0},{0,20,0},{0,20,0},{0,10,1},{5,0,1513},
+{0,8,605},{0,8,605},{0,5,925},{10,0,1513},{0,5,925},{22,1,9248},{0,31,1341},{0,23,68},{0,19,3626},{22,1,9248},{31,7,9248},{0,19,3626},{0,15,9248},{31,7,9248},{0,15,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,31,12200},{0,31,1325},{0,24,10},{0,20,3365},{0,31,20705},{0,21,13009},{0,18,6227},
+{0,13,15441},{0,15,22455},{0,13,16666},{4,31,11489},{0,31,1325},{0,24,10},{0,20,3365},{15,2,20689},{0,21,13009},{0,18,6227},{0,13,15441},{30,1,20689},{0,13,15441},{0,23,0},{0,23,0},{0,23,0},{0,11,9},{0,11,1989},{0,9,772},{0,9,772},{0,5,1213},{0,5,2194},{0,5,1382},{0,23,0},{0,23,0},{0,23,0},{0,11,9},{6,0,1985},{0,9,772},{0,9,772},{0,5,1213},{10,1,1985},
+{0,5,1213},{23,2,9248},{0,31,1325},{0,24,10},{0,20,3365},{23,2,9248},{30,9,9248},{0,20,3365},{0,16,9250},{30,9,9248},{0,16,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,31,13288},{0,31,1565},{0,25,10},{0,22,3077},{1,31,22214},{0,23,13555},{0,20,6310},{0,14,16176},{0,16,24130},{0,13,17562},{4,31,12385},
+{0,31,1565},{0,25,10},{0,22,3077},{17,0,22129},{0,23,13555},{0,20,6310},{0,14,16176},{30,2,22129},{0,14,16176},{0,26,0},{0,26,0},{0,26,0},{0,13,0},{0,13,2521},{0,10,1018},{0,10,1018},{0,6,1508},{0,6,2801},{0,6,1764},{0,26,0},{0,26,0},{0,26,0},{0,13,0},{6,1,2521},{0,10,1018},{0,10,1018},{0,6,1508},{13,0,2521},{0,6,1508},{23,5,9248},{0,31,1565},{0,25,10},
+{0,22,3077},{23,5,9248},{31,10,9248},{0,22,3077},{0,17,9250},{31,10,9248},{0,17,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,31,14788},{0,31,2141},{0,27,72},{0,22,2825},{1,31,24140},{0,25,14114},{0,21,6323},{0,14,17202},{0,17,26063},{0,14,18646},{5,31,13521},{1,31,2100},{0,27,72},{0,22,2825},{16,4,23851},
+{0,25,14114},{0,21,6323},{0,14,17202},{28,4,23851},{0,14,17202},{0,29,1},{0,29,1},{0,29,1},{0,15,4},{0,15,3202},{0,12,1285},{0,12,1285},{0,7,1973},{0,7,3569},{0,6,2241},{0,29,1},{0,29,1},{0,29,1},{0,15,4},{7,1,3200},{0,12,1285},{0,12,1285},{0,7,1973},{11,2,3200},{0,7,1973},{27,0,9248},{3,31,1885},{2,26,8},{0,22,2825},{27,0,9248},{30,12,9248},{0,22,2825},
+{0,18,9248},{30,12,9248},{0,18,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,31,16228},{1,31,2836},{0,28,170},{0,24,2612},{2,31,25971},{0,25,14594},{0,22,6473},{0,16,18144},{0,17,27951},{0,14,19830},{7,31,14675},{2,31,2706},{1,27,149},{0,24,2612},{19,0,25472},{0,25,14594},{0,22,6473},{0,16,18144},{30,4,25472},
+{0,16,18144},{0,31,9},{0,31,9},{0,31,9},{0,16,0},{0,16,3872},{0,13,1514},{0,13,1514},{0,7,2405},{0,7,4305},{0,7,2766},{0,31,9},{0,31,9},{0,31,9},{0,16,0},{8,0,3872},{0,13,1514},{0,13,1514},{0,7,2405},{16,0,3872},{0,7,2405},{28,1,9248},{4,31,2210},{3,27,8},{0,24,2612},{28,1,9248},{31,13,9248},{0,24,2612},{0,19,9248},{31,13,9248},{0,19,9248},{0,0,0},
+{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,31,17796},{2,31,3702},{1,29,270},{0,25,2361},{3,31,27563},{0,27,14944},{0,23,6470},{0,17,18681},{0,19,29556},{0,16,20628},{7,31,15635},{3,31,3425},{1,29,206},{0,25,2361},{20,0,26744},{0,27,14944},{0,23,6470},{0,17,18681},{24,8,26744},{0,17,18681},{0,31,125},{0,31,125},{0,31,125},
+{0,18,8},{0,18,4418},{0,14,1696},{0,14,1696},{0,8,2664},{0,8,4952},{0,8,3148},{1,31,72},{1,31,72},{1,31,72},{0,18,8},{9,0,4418},{0,14,1696},{0,14,1696},{0,8,2664},{18,0,4418},{0,8,2664},{30,0,9248},{6,31,2557},{3,28,10},{0,25,2357},{30,0,9248},{30,15,9248},{0,25,2357},{0,20,9250},{30,15,9248},{0,20,9250},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,0},
+{0,1,0},{0,1,0},{0,0,4},{0,0,4},{0,0,4},{5,31,19090},{2,31,4598},{1,30,406},{0,26,2220},{3,31,28187},{0,29,14347},{0,25,5609},{0,18,18144},{0,20,29961},{0,17,20301},{8,31,16082},{4,31,4019},{2,30,206},{0,26,2220},{21,1,26744},{0,29,14347},{0,25,5609},{0,18,18144},{27,8,26744},{0,18,18144},{1,31,264},{1,31,264},{1,31,264},{1,19,72},{0,21,4418},{0,16,1412},{0,16,1412},
+{0,10,2420},{0,9,5122},{0,9,2997},{2,31,117},{2,31,117},{2,31,117},{1,19,8},{10,1,4418},{0,16,1412},{0,16,1412},{0,10,2420},{21,0,4418},{0,10,2420},{31,1,9248},{8,31,2929},{4,29,10},{0,26,2120},{31,1,9248},{27,18,9248},{0,26,2120},{0,21,9250},{27,18,9248},{0,21,9250},{1,0,68},{1,0,68},{1,0,68},{1,0,68},{0,4,1},{0,4,1},{0,4,1},{0,2,0},{0,2,25},
+{0,2,25},{7,31,20669},{3,31,5786},{2,31,625},{1,27,2283},{4,31,29033},{0,30,13795},{0,26,4770},{0,18,17667},{0,21,30425},{0,18,20068},{9,31,16691},{5,31,4841},{3,31,205},{1,27,2219},{23,0,26747},{0,30,13795},{0,26,4770},{0,18,17667},{30,8,26747},{0,18,17667},{2,31,589},{2,31,589},{2,31,589},{1,20,186},{0,24,4418},{0,18,1125},{0,18,1125},{0,10,2186},{0,11,5390},{0,10,2915},{3,31,169},
+{3,31,169},{3,31,169},{2,20,13},{12,0,4418},{0,18,1125},{0,18,1125},{0,10,2186},{24,0,4418},{0,10,2186},{31,4,9248},{10,31,3380},{6,30,8},{0,27,1954},{31,4,9248},{30,18,9248},{0,27,1954},{0,22,9248},{30,18,9248},{0,22,9248},{1,0,185},{1,0,185},{1,0,185},{1,0,185},{0,7,0},{0,7,0},{0,7,0},{0,3,9},{0,3,73},{0,3,73},{7,31,21577},{4,31,6797},{3,31,985},
+{1,28,2226},{5,31,29436},{0,31,12990},{0,27,4027},{0,20,16925},{0,23,30436},{0,18,19620},{11,31,16645},{7,31,5260},{4,31,232},{2,28,2141},{24,1,26259},{0,31,12990},{0,27,4027},{0,20,16925},{31,9,26259},{0,20,16925},{3,31,985},{3,31,985},{3,31,985},{2,21,378},{0,27,4418},{0,20,905},{0,20,905},{0,12,2005},{0,12,5635},{0,11,2950},{4,31,232},{4,31,232},{4,31,232},{3,21,13},{13,1,4418},
+{0,20,905},{0,20,905},{0,12,2005},{27,0,4418},{0,12,2005},{31,7,8980},{11,31,3601},{7,31,4},{0,28,1665},{31,7,8980},{31,19,8980},{0,28,1665},{0,23,8980},{31,19,8980},{0,23,8980},{2,0,377},{2,0,377},{2,0,377},{2,0,377},{0,10,0},{0,10,0},{0,10,0},{0,5,0},{0,4,146},{0,4,146},{7,31,21193},{4,31,7053},{3,31,1481},{2,28,2093},{6,31,28313},{0,31,11406},{0,28,2965},
+{0,20,15021},{0,23,28900},{0,19,17995},{11,31,15381},{7,31,4876},{5,31,325},{3,28,1786},{25,1,24371},{0,31,11406},{0,28,2965},{0,20,15021},{27,12,24371},{0,20,15021},{3,31,1481},{3,31,1481},{3,31,1481},{2,23,621},{0,30,4418},{0,21,680},{0,21,680},{0,13,1780},{0,13,5885},{0,12,2950},{5,31,325},{5,31,325},{5,31,325},{4,22,8},{15,0,4418},{0,21,680},{0,21,680},{0,13,1780},{30,0,4418},
+{0,13,1780},{31,8,7938},{12,31,3188},{8,31,0},{0,29,1156},{31,8,7938},{30,20,7938},{0,29,1156},{0,23,7956},{30,20,7938},{0,23,7956},{2,0,617},{2,0,617},{2,0,617},{2,0,617},{0,13,0},{0,13,0},{0,13,0},{0,6,9},{0,5,233},{0,5,233},{8,31,20825},{5,31,7494},{4,31,2089},{2,29,1970},{7,31,27269},{0,31,10078},{0,28,2021},{0,21,13204},{0,25,27384},{0,20,16398},{12,31,14148},
+{8,31,4562},{7,31,392},{4,29,1445},{26,1,22568},{0,31,10078},{0,28,2021},{0,21,13204},{31,11,22568},{0,21,13204},{4,31,2089},{4,31,2089},{4,31,2089},{3,23,946},{0,31,4468},{0,23,521},{0,23,521},{0,14,1573},{0,15,6227},{0,13,2909},{7,31,392},{7,31,392},{7,31,392},{5,23,8},{16,1,4418},{0,23,521},{0,23,521},{0,14,1573},{31,1,4418},{0,14,1573},{31,10,6964},{14,31,2785},{10,31,4},
+{0,29,740},{31,10,6964},{31,20,6964},{0,29,740},{0,24,6970},{31,20,6964},{0,24,6970},{3,0,937},{3,0,937},{3,0,937},{3,0,937},{0,16,1},{0,16,1},{0,16,1},{0,8,1},{0,6,377},{0,6,377},{8,31,20717},{6,31,8012},{5,31,2958},{3,29,2057},{7,31,26243},{0,31,8890},{0,29,1154},{0,22,11325},{0,25,25854},{0,21,14671},{13,31,12926},{10,31,4313},{8,31,485},{5,29,1106},{25,5,20642},
+{0,31,8890},{0,29,1154},{0,22,11325},{31,12,20642},{0,22,11325},{5,31,2958},{5,31,2958},{5,31,2958},{3,25,1361},{1,31,4644},{0,25,337},{0,25,337},{0,15,1429},{0,16,6596},{0,14,2981},{8,31,485},{8,31,485},{8,31,485},{6,24,13},{16,4,4418},{0,25,337},{0,25,337},{0,15,1429},{28,4,4418},{0,15,1429},{31,11,5941},{15,31,2377},{11,31,1},{0,30,388},{31,11,5941},{31,21,5941},{0,30,388},
+{0,24,5953},{31,21,5941},{0,24,5953},{3,0,1360},{3,0,1360},{3,0,1360},{3,0,1360},{0,19,0},{0,19,0},{0,19,0},{0,10,4},{0,8,548},{0,8,548},{9,31,20713},{7,31,8575},{5,31,3806},{3,30,2260},{7,31,25603},{0,31,8106},{0,29,642},{0,22,9805},{0,26,24678},{0,21,13359},{15,31,11882},{11,31,4006},{9,31,596},{6,29,818},{28,1,19021},{2,31,8066},{0,29,642},{0,22,9805},{31,13,19021},
+{0,22,9805},{5,31,3806},{5,31,3806},{5,31,3806},{4,26,1819},{2,31,4962},{0,27,232},{0,27,232},{0,16,1268},{0,17,6926},{0,15,3126},{9,31,596},{9,31,596},{9,31,596},{7,25,13},{17,5,4418},{0,27,232},{0,27,232},{0,16,1268},{31,4,4418},{0,16,1268},{31,13,5101},{16,31,2042},{13,31,4},{0,30,164},{31,13,5101},{31,22,5101},{0,30,164},{0,25,5105},{31,22,5101},{0,25,5105},{4,0,1818},
+{4,0,1818},{4,0,1818},{4,0,1818},{0,22,0},{0,22,0},{0,22,0},{0,11,0},{0,9,697},{0,9,697},{10,31,20905},{7,31,9247},{6,31,4787},{4,30,2547},{8,31,25042},{1,31,7537},{0,30,264},{0,23,8449},{0,27,23521},{0,22,12141},{15,31,10794},{12,31,3786},{10,31,725},{8,29,621},{29,1,17485},{3,31,7274},{0,30,264},{0,23,8449},{27,16,17485},{0,23,8449},{6,31,4787},{6,31,4787},{6,31,4787},
+{4,27,2323},{3,31,5386},{0,29,130},{0,29,130},{0,18,1096},{0,19,7364},{0,17,3225},{10,31,725},{10,31,725},{10,31,725},{8,26,8},{21,0,4418},{0,29,130},{0,29,130},{0,18,1096},{30,6,4418},{0,18,1096},{31,14,4325},{18,31,1737},{14,31,1},{0,31,64},{31,14,4325},{30,23,4325},{0,31,64},{0,25,4337},{30,23,4325},{0,25,4337},{4,0,2314},{4,0,2314},{4,0,2314},{4,0,2314},{0,25,0},
+{0,25,0},{0,25,0},{0,12,4},{0,10,925},{0,10,925},{11,31,21021},{8,31,10106},{7,31,5819},{4,30,3027},{8,31,24722},{2,31,7042},{0,31,81},{0,24,7169},{0,29,22467},{0,22,11133},{16,31,9869},{12,31,3594},{11,31,821},{8,30,420},{30,1,16034},{4,31,6558},{0,31,81},{0,24,7169},{31,15,16034},{0,24,7169},{7,31,5819},{7,31,5819},{7,31,5819},{5,28,2915},{3,31,5962},{0,30,72},{0,30,72},
+{0,18,968},{0,20,7781},{0,17,3305},{11,31,821},{11,31,821},{11,31,821},{9,27,8},{22,1,4418},{0,30,72},{0,30,72},{0,18,968},{31,7,4418},{0,18,968},{31,15,3617},{19,31,1450},{15,31,9},{0,31,0},{31,15,3617},{31,23,3617},{0,31,0},{0,26,3617},{31,23,3617},{0,26,3617},{5,0,2906},{5,0,2906},{5,0,2906},{5,0,2906},{0,28,1},{0,28,1},{0,28,1},{0,14,0},{0,11,1156},
+{0,11,1156},{11,31,21381},{8,31,11186},{7,31,7169},{5,31,3633},{9,31,24543},{3,31,6762},{0,31,81},{0,24,5819},{0,29,21333},{0,23,10106},{17,31,8955},{14,31,3433},{12,31,980},{10,30,242},{29,5,14504},{6,31,5834},{1,31,74},{0,24,5819},{31,16,14504},{0,24,5819},{7,31,7169},{7,31,7169},{7,31,7169},{5,30,3618},{4,31,6757},{0,31,81},{0,31,81},{0,20,821},{0,21,8245},{0,18,3531},{12,31,980},
+{12,31,980},{12,31,980},{10,28,13},{24,0,4418},{1,31,74},{1,31,74},{0,20,821},{24,12,4418},{0,20,821},{29,21,2888},{20,31,1156},{17,31,1},{3,31,1},{29,21,2888},{31,24,2888},{3,31,1},{0,26,2906},{31,24,2888},{0,26,2906},{5,0,3617},{5,0,3617},{5,0,3617},{5,0,3617},{0,31,0},{0,31,0},{0,31,0},{0,15,9},{0,13,1421},{0,13,1421},{12,31,21949},{9,31,12367},{8,31,8449},
+{6,31,4338},{10,31,24600},{3,31,6650},{1,31,298},{0,25,4698},{0,30,20575},{0,24,9247},{17,31,8219},{15,31,3236},{13,31,1157},{11,30,122},{31,3,13235},{7,31,5260},{3,31,145},{0,25,4698},{31,17,13235},{0,25,4698},{8,31,8449},{8,31,8449},{8,31,8449},{6,31,4338},{5,31,7667},{1,31,298},{1,31,298},{0,21,680},{0,23,8779},{0,19,3786},{13,31,1157},{13,31,1157},{13,31,1157},{11,29,13},{25,1,4418},
+{3,31,145},{3,31,145},{0,21,680},{27,12,4418},{0,21,680},{31,19,2314},{22,31,949},{19,31,4},{6,31,1},{31,19,2314},{31,25,2314},{6,31,1},{0,27,2314},{31,25,2314},{0,27,2314},{6,0,4337},{6,0,4337},{6,0,4337},{6,0,4337},{0,31,64},{0,31,64},{0,31,64},{0,17,0},{0,13,1709},{0,13,1709},{12,31,22557},{10,31,13585},{9,31,9926},{6,31,5186},{11,31,24636},{3,31,6794},{2,31,692},
+{0,26,3723},{0,31,19836},{0,25,8442},{19,31,7417},{16,31,3126},{15,31,1268},{12,31,68},{29,9,12051},{8,31,4762},{4,31,232},{0,26,3723},{27,20,12051},{0,26,3723},{9,31,9926},{9,31,9926},{9,31,9926},{6,31,5186},{5,31,8691},{2,31,692},{2,31,692},{0,22,557},{0,25,9284},{0,21,3929},{15,31,1268},{15,31,1268},{15,31,1268},{12,30,8},{27,0,4418},{4,31,232},{4,31,232},{0,22,557},{30,12,4418},
+{0,22,557},{31,20,1800},{22,31,725},{20,31,0},{9,31,1},{31,20,1800},{30,26,1800},{9,31,1},{0,27,1818},{30,26,1800},{0,27,1818},{6,0,5105},{6,0,5105},{6,0,5105},{6,0,5105},{1,31,185},{1,31,185},{1,31,185},{0,18,9},{0,15,2042},{0,15,2042},{12,31,23421},{11,31,14850},{9,31,11462},{7,31,6149},{11,31,24860},{4,31,7053},{2,31,1236},{0,26,2891},{0,31,19260},{0,25,7818},{19,31,6761},
+{17,31,3107},{16,31,1429},{13,31,8},{31,7,10952},{10,31,4300},{6,31,353},{0,26,2891},{31,19,10952},{0,26,2891},{9,31,11462},{9,31,11462},{9,31,11462},{7,31,6149},{7,31,9845},{2,31,1236},{2,31,1236},{0,23,485},{0,25,9764},{0,21,4185},{16,31,1429},{16,31,1429},{16,31,1429},{13,31,8},{28,1,4418},{6,31,353},{6,31,353},{0,23,485},{31,13,4418},{0,23,485},{31,22,1354},{23,31,548},{22,31,4},
+{12,31,0},{31,22,1354},{30,27,1354},{12,31,0},{0,28,1360},{30,27,1354},{0,28,1360},{7,0,5953},{7,0,5953},{7,0,5953},{7,0,5953},{1,31,425},{1,31,425},{1,31,425},{0,20,1},{0,17,2372},{0,17,2372},{13,31,24507},{11,31,16398},{10,31,13349},{8,31,7460},{11,31,25418},{4,31,7647},{3,31,2021},{0,27,2089},{0,31,18918},{0,26,7302},{20,31,6098},{18,31,3037},{17,31,1640},{14,31,25},{29,13,9818},
+{12,31,3874},{8,31,521},{0,27,2089},{31,20,9818},{0,27,2089},{10,31,13349},{10,31,13349},{10,31,13349},{8,31,7460},{7,31,11195},{3,31,2021},{3,31,2021},{0,24,392},{0,27,10472},{0,23,4562},{17,31,1640},{17,31,1640},{17,31,1640},{14,31,25},{28,4,4418},{8,31,521},{8,31,521},{0,24,392},{28,16,4418},{0,24,392},{31,23,925},{24,31,386},{23,31,1},{15,31,1},{31,23,925},{31,27,925},{15,31,1},
+{0,28,937},{31,27,925},{0,28,937},{7,0,6970},{7,0,6970},{7,0,6970},{7,0,6970},{2,31,785},{2,31,785},{2,31,785},{0,22,4},{0,17,2741},{0,17,2741},{14,31,25663},{12,31,17995},{11,31,15021},{8,31,8740},{12,31,26003},{6,31,8399},{3,31,2965},{0,28,1481},{0,31,18886},{0,26,7014},{21,31,5634},{19,31,2950},{18,31,1853},{16,31,72},{31,11,8901},{14,31,3578},{10,31,698},{0,28,1481},{31,21,8901},
+{0,28,1481},{11,31,15021},{11,31,15021},{11,31,15021},{8,31,8740},{8,31,12646},{3,31,2965},{3,31,2965},{0,26,292},{0,29,11051},{0,24,4876},{18,31,1853},{18,31,1853},{18,31,1853},{16,31,72},{29,5,4418},{10,31,698},{10,31,698},{0,26,292},{31,16,4418},{0,26,292},{31,25,613},{26,31,245},{25,31,4},{18,31,1},{31,25,613},{27,30,613},{18,31,1},{0,29,617},{27,30,613},{0,29,617},{8,0,7956},
+{8,0,7956},{8,0,7956},{8,0,7956},{3,31,1201},{3,31,1201},{3,31,1201},{0,23,0},{0,18,3185},{0,18,3185},{15,31,26715},{12,31,19659},{11,31,16925},{9,31,10232},{12,31,26835},{6,31,9215},{4,31,4027},{0,28,985},{0,31,19110},{0,27,6797},{22,31,5238},{20,31,2950},{19,31,2005},{17,31,180},{29,17,8069},{15,31,3314},{11,31,905},{0,28,985},{27,24,8069},{0,28,985},{11,31,16925},{11,31,16925},{11,31,16925},
+{9,31,10232},{8,31,14182},{4,31,4027},{4,31,4027},{0,27,232},{0,29,11627},{0,25,5117},{19,31,2005},{19,31,2005},{19,31,2005},{17,31,180},{31,4,4418},{11,31,905},{11,31,905},{0,27,232},{30,18,4418},{0,27,232},{31,26,365},{27,31,146},{26,31,1},{21,31,1},{31,26,365},{30,29,365},{21,31,1},{0,29,377},{30,29,365},{0,29,377},{8,0,8980},{8,0,8980},{8,0,8980},{8,0,8980},{3,31,1665},
+{3,31,1665},{3,31,1665},{0,24,4},{0,20,3601},{0,20,3601},{15,31,26555},{13,31,20326},{12,31,17723},{10,31,10897},{13,31,26598},{7,31,9527},{5,31,4934},{0,29,590},{0,31,18606},{0,28,5786},{23,31,4770},{21,31,3041},{20,31,2210},{18,31,325},{31,15,7322},{16,31,3126},{14,31,1145},{0,29,554},{31,23,7322},{0,29,554},{12,31,17723},{12,31,17723},{12,31,17723},{10,31,10897},{9,31,15092},{5,31,4934},{5,31,4934},
+{0,28,205},{0,31,11381},{0,26,4709},{20,31,2210},{20,31,2210},{20,31,2210},{18,31,325},{31,7,4418},{14,31,1145},{14,31,1145},{0,28,169},{31,19,4418},{0,28,169},{31,27,185},{28,31,73},{27,31,9},{24,31,0},{31,27,185},{31,29,185},{24,31,0},{0,30,185},{31,29,185},{0,30,185},{9,0,9248},{9,0,9248},{9,0,9248},{9,0,9248},{4,31,1954},{4,31,1954},{4,31,1954},{1,25,8},{0,21,3330},
+{0,21,3330},{16,31,25958},{15,31,20468},{13,31,18321},{11,31,11371},{15,31,25748},{8,31,9863},{7,31,5684},{1,30,373},{0,31,18111},{0,29,4452},{24,31,4437},{23,31,3084},{22,31,2500},{19,31,554},{29,21,6584},{18,31,2996},{15,31,1412},{0,30,237},{31,24,6584},{0,30,237},{13,31,18321},{13,31,18321},{13,31,18321},{11,31,11371},{11,31,15661},{7,31,5684},{7,31,5684},{1,29,206},{0,31,10886},{0,27,4019},{22,31,2500},
+{22,31,2500},{22,31,2500},{19,31,554},{28,16,4418},{15,31,1412},{15,31,1412},{0,29,100},{24,24,4418},{0,29,100},{31,29,52},{30,31,25},{29,31,1},{27,31,1},{31,29,52},{31,30,52},{27,31,1},{0,30,68},{31,30,52},{0,30,68},{10,0,9250},{10,0,9250},{10,0,9250},{10,0,9250},{5,31,2197},{5,31,2197},{5,31,2197},{2,27,5},{0,23,2929},{0,23,2929},{17,31,25604},{15,31,20628},{15,31,18692},
+{12,31,11876},{16,31,25201},{10,31,10381},{8,31,6470},{2,30,270},{2,31,17924},{0,29,3588},{25,31,4259},{23,31,3148},{23,31,2664},{20,31,820},{31,19,6019},{19,31,2950},{16,31,1717},{0,30,125},{31,25,6019},{0,30,125},{15,31,18692},{15,31,18692},{15,31,18692},{12,31,11876},{12,31,16244},{8,31,6470},{8,31,6470},{2,30,206},{0,31,10854},{0,29,3332},{23,31,2664},{23,31,2664},{23,31,2664},{20,31,820},{29,17,4418},
+{16,31,1717},{16,31,1717},{0,30,61},{27,24,4418},{0,30,61},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{31,31,4},{30,31,1},{0,31,4},{31,31,4},{0,31,4},{11,0,9250},{11,0,9250},{11,0,9250},{11,0,9250},{6,31,2440},{6,31,2440},{6,31,2440},{3,27,10},{0,25,2509},{0,25,2509},{18,31,24418},{16,31,19831},{15,31,18144},{13,31,11876},{16,31,23685},{11,31,10015},{8,31,6638},
+{3,31,170},{3,31,16879},{0,30,2738},{25,31,3699},{24,31,2766},{24,31,2405},{21,31,820},{31,20,5164},{20,31,2584},{18,31,1552},{0,31,9},{30,26,5164},{0,31,9},{15,31,18144},{15,31,18144},{15,31,18144},{13,31,11876},{12,31,15696},{8,31,6638},{8,31,6638},{4,30,132},{0,31,10150},{0,29,2624},{24,31,2405},{24,31,2405},{24,31,2405},{21,31,820},{31,15,3872},{18,31,1552},{18,31,1552},{0,31,9},{31,23,3872},
+{0,31,9},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{12,0,9248},{12,0,9248},{12,0,9248},{12,0,9248},{7,31,2612},{7,31,2612},{7,31,2612},{4,28,8},{0,27,2210},{0,27,2210},{19,31,22762},{17,31,18876},{16,31,17222},{14,31,11585},{17,31,22068},{11,31,9551},{10,31,6509},{5,31,68},{4,31,15612},{0,30,2098},{26,31,3089},
+{24,31,2334},{24,31,1973},{22,31,661},{29,25,4267},{22,31,2150},{19,31,1285},{2,31,0},{27,28,4267},{2,31,0},{16,31,17222},{16,31,17222},{16,31,17222},{14,31,11585},{13,31,14786},{10,31,6509},{10,31,6509},{5,31,68},{0,31,9366},{0,30,2034},{24,31,1973},{24,31,1973},{24,31,1973},{22,31,661},{31,16,3202},{19,31,1285},{19,31,1285},{2,31,0},{30,24,3202},{2,31,0},{31,31,0},{31,31,0},{31,31,0},
+{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{13,0,9248},{13,0,9248},{13,0,9248},{13,0,9248},{8,31,2845},{8,31,2845},{8,31,2845},{5,29,8},{0,29,1856},{0,29,1856},{19,31,21160},{18,31,17776},{17,31,16329},{15,31,11282},{17,31,20358},{12,31,9098},{11,31,6310},{6,31,5},{6,31,14287},{0,31,1565},{27,31,2412},{25,31,1862},{25,31,1573},{23,31,509},{28,28,3361},
+{22,31,1691},{20,31,1021},{5,31,1},{28,28,3361},{5,31,1},{17,31,16329},{17,31,16329},{17,31,16329},{15,31,11282},{15,31,13658},{11,31,6310},{11,31,6310},{6,31,5},{2,31,8690},{0,31,1565},{25,31,1573},{25,31,1573},{25,31,1573},{23,31,509},{31,18,2521},{20,31,1021},{20,31,1021},{5,31,1},{30,25,2521},{5,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},
+{0,31,0},{31,31,0},{0,31,0},{14,0,9250},{14,0,9250},{14,0,9250},{14,0,9250},{9,31,3176},{9,31,3176},{9,31,3176},{6,31,5},{0,30,1556},{0,30,1556},{20,31,19810},{19,31,16741},{18,31,15584},{16,31,11057},{19,31,18721},{14,31,8860},{12,31,6234},{7,31,10},{7,31,13210},{0,31,1325},{27,31,1868},{26,31,1464},{26,31,1268},{24,31,397},{31,23,2649},{23,31,1329},{22,31,794},{8,31,0},{31,27,2649},
+{8,31,0},{18,31,15584},{18,31,15584},{18,31,15584},{16,31,11057},{15,31,12858},{12,31,6234},{12,31,6234},{7,31,10},{3,31,8150},{0,31,1325},{26,31,1268},{26,31,1268},{26,31,1268},{24,31,397},{31,19,1989},{22,31,794},{22,31,794},{8,31,0},{31,25,1989},{8,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{15,0,9250},
+{15,0,9250},{15,0,9250},{15,0,9250},{11,31,3365},{11,31,3365},{11,31,3365},{7,31,10},{0,31,1325},{0,31,1325},{20,31,18626},{19,31,15845},{19,31,14756},{17,31,10897},{19,31,17297},{15,31,8442},{13,31,6285},{8,31,68},{8,31,12227},{0,31,1341},{27,31,1452},{27,31,1089},{27,31,968},{25,31,325},{31,24,2018},{24,31,1011},{23,31,605},{11,31,0},{30,28,2018},{11,31,0},{19,31,14756},{19,31,14756},{19,31,14756},
+{17,31,10897},{16,31,12077},{13,31,6285},{13,31,6285},{8,31,68},{4,31,7686},{0,31,1341},{27,31,968},{27,31,968},{27,31,968},{25,31,325},{31,21,1513},{23,31,605},{23,31,605},{11,31,0},{31,26,1513},{11,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{16,0,9248},{16,0,9248},{16,0,9248},{16,0,9248},{12,31,3626},
+{12,31,3626},{12,31,3626},{8,31,68},{0,31,1341},{0,31,1341},{21,31,17476},{20,31,14998},{20,31,14098},{18,31,10672},{20,31,16018},{15,31,8154},{15,31,6218},{9,31,200},{10,31,11338},{0,31,1613},{28,31,1041},{27,31,801},{27,31,680},{26,31,232},{29,29,1473},{26,31,753},{24,31,442},{14,31,0},{31,28,1473},{14,31,0},{20,31,14098},{20,31,14098},{20,31,14098},{18,31,10672},{17,31,11453},{15,31,6218},{15,31,6218},
+{9,31,200},{6,31,7270},{0,31,1613},{27,31,680},{27,31,680},{27,31,680},{26,31,232},{28,28,1105},{24,31,442},{24,31,442},{14,31,0},{28,28,1105},{14,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{17,0,9248},{17,0,9248},{17,0,9248},{17,0,9248},{13,31,3929},{13,31,3929},{13,31,3929},{9,31,200},{0,31,1613},
+{0,31,1613}, \ No newline at end of file
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_dxt1_6.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_dxt1_6.inc
new file mode 100644
index 0000000000..2441fbe859
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_dxt1_6.inc
@@ -0,0 +1,494 @@
+// Copyright (C) 2017-2019 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+{0,4,18},{0,3,4},{0,2,0},{0,2,9},{0,3,36},{0,2,22},{0,2,13},{0,1,24},{0,1,41},{0,1,25},{0,4,18},{0,3,4},{0,2,0},{0,2,9},{1,1,36},{0,2,22},{0,2,13},{0,1,24},{3,0,36},{0,1,24},{0,2,0},{0,2,0},{0,2,0},{0,1,0},{0,1,2},{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,2,0},
+{0,2,0},{0,2,0},{0,1,0},{0,1,2},{0,1,1},{0,1,1},{0,0,4},{1,0,2},{0,0,4},{2,0,18},{0,3,4},{0,2,0},{0,2,9},{2,0,18},{4,0,18},{0,2,9},{0,1,20},{4,0,18},{0,1,20},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,8,38},{1,6,21},{1,4,24},
+{1,4,24},{0,8,52},{0,5,18},{0,4,1},{0,3,24},{0,4,77},{0,3,40},{2,6,22},{1,6,5},{2,4,4},{1,4,8},{4,0,52},{0,5,18},{0,4,1},{0,3,24},{8,0,52},{0,3,24},{1,6,20},{1,6,20},{1,6,20},{1,3,21},{0,6,8},{0,4,1},{0,4,1},{0,2,5},{0,3,24},{0,2,9},{2,4,4},{2,4,4},{2,4,4},{2,3,4},{3,0,8},
+{1,3,1},{1,3,1},{1,2,4},{6,0,8},{1,2,4},{5,0,18},{1,6,1},{2,4,0},{0,4,0},{5,0,18},{10,0,18},{0,4,0},{0,3,20},{10,0,18},{0,3,20},{1,0,20},{1,0,20},{1,0,20},{1,0,20},{0,5,0},{0,5,0},{0,5,0},{0,2,1},{0,2,5},{0,2,5},{3,10,38},{3,8,21},{3,6,24},{3,6,24},{2,10,52},{2,7,18},{2,6,1},
+{2,5,24},{0,7,53},{1,5,21},{4,8,22},{3,8,5},{4,6,4},{3,6,8},{7,0,52},{2,7,18},{2,6,1},{1,5,20},{14,0,52},{1,5,20},{3,8,20},{3,8,20},{3,8,20},{3,5,21},{2,8,8},{2,6,1},{2,6,1},{2,4,5},{0,6,8},{1,5,5},{4,6,4},{4,6,4},{4,6,4},{4,5,4},{6,0,8},{3,5,1},{3,5,1},{3,4,4},{12,0,8},
+{3,4,4},{8,0,18},{3,8,1},{4,6,0},{2,6,0},{8,0,18},{16,0,18},{2,6,0},{0,5,20},{16,0,18},{0,5,20},{3,0,20},{3,0,20},{3,0,20},{3,0,20},{2,7,0},{2,7,0},{2,7,0},{2,4,1},{1,5,1},{1,5,1},{5,12,38},{5,10,21},{5,8,24},{5,8,24},{4,12,52},{4,9,18},{4,8,1},{4,7,24},{2,9,53},{3,7,21},{6,10,22},
+{5,10,5},{6,8,4},{5,8,8},{2,16,51},{4,9,18},{4,8,1},{3,7,20},{20,0,51},{3,7,20},{5,10,20},{5,10,20},{5,10,20},{5,7,21},{4,10,8},{4,8,1},{4,8,1},{4,6,5},{2,8,8},{3,7,5},{6,8,4},{6,8,4},{6,8,4},{6,7,4},{9,0,8},{5,7,1},{5,7,1},{5,6,4},{18,0,8},{5,6,4},{11,0,18},{5,10,1},{6,8,0},
+{4,8,0},{11,0,18},{22,0,18},{4,8,0},{0,7,20},{22,0,18},{0,7,20},{5,0,20},{5,0,20},{5,0,20},{5,0,20},{4,9,0},{4,9,0},{4,9,0},{4,6,1},{3,7,1},{3,7,1},{7,15,36},{7,12,19},{7,10,28},{7,10,20},{6,15,52},{6,11,22},{6,10,7},{6,9,28},{3,12,52},{5,9,27},{8,13,19},{8,11,3},{8,10,3},{8,10,6},{13,1,51},
+{6,11,21},{7,10,3},{5,9,27},{27,0,51},{5,9,27},{7,12,19},{7,12,19},{7,12,19},{7,10,19},{6,13,9},{6,10,6},{6,10,6},{6,9,3},{5,10,9},{5,9,2},{8,10,2},{8,10,2},{8,10,2},{8,9,2},{12,1,8},{7,10,2},{7,10,2},{5,9,2},{25,0,8},{5,9,2},{14,1,18},{7,12,1},{8,10,2},{6,10,2},{14,1,18},{15,7,18},{6,10,2},
+{0,9,26},{15,7,18},{0,9,26},{7,0,18},{7,0,18},{7,0,18},{7,0,18},{6,11,2},{6,11,2},{6,11,2},{6,9,2},{5,9,1},{5,9,1},{9,16,38},{9,14,19},{9,12,28},{9,12,20},{8,17,52},{8,13,22},{8,12,7},{8,11,28},{5,14,52},{7,11,27},{10,15,19},{10,13,3},{10,12,3},{10,12,6},{16,1,51},{8,13,21},{9,12,3},{7,11,27},{33,0,51},
+{7,11,27},{9,14,19},{9,14,19},{9,14,19},{9,12,19},{8,15,9},{8,12,6},{8,12,6},{8,11,3},{7,12,9},{7,11,2},{10,12,2},{10,12,2},{10,12,2},{10,11,2},{15,1,8},{9,12,2},{9,12,2},{7,11,2},{31,0,8},{7,11,2},{17,0,18},{9,14,1},{10,12,2},{8,12,2},{17,0,18},{34,0,18},{8,12,2},{0,11,26},{34,0,18},{0,11,26},{9,0,18},
+{9,0,18},{9,0,18},{9,0,18},{8,13,2},{8,13,2},{8,13,2},{8,11,2},{7,11,1},{7,11,1},{11,18,38},{11,16,19},{11,14,28},{11,14,20},{10,19,52},{10,15,22},{10,14,7},{10,13,28},{7,16,52},{9,13,27},{12,16,21},{12,15,3},{12,14,3},{12,14,6},{19,1,51},{10,15,21},{11,14,3},{9,13,27},{39,0,51},{9,13,27},{11,16,18},{11,16,18},{11,16,18},
+{11,14,19},{10,17,9},{10,14,6},{10,14,6},{10,13,3},{9,14,9},{9,13,2},{12,14,2},{12,14,2},{12,14,2},{12,13,2},{15,7,8},{11,14,2},{11,14,2},{9,13,2},{31,3,8},{9,13,2},{20,0,18},{11,16,1},{12,14,2},{10,14,2},{20,0,18},{40,0,18},{10,14,2},{0,13,26},{40,0,18},{0,13,26},{11,0,18},{11,0,18},{11,0,18},{11,0,18},{10,15,2},
+{10,15,2},{10,15,2},{10,13,2},{9,13,1},{9,13,1},{13,20,38},{13,18,19},{13,16,27},{13,16,19},{12,21,52},{12,17,19},{12,16,5},{12,15,28},{10,17,52},{11,15,27},{14,18,21},{14,17,3},{14,16,1},{13,16,10},{22,1,51},{12,17,18},{13,16,2},{11,15,27},{45,0,51},{11,15,27},{13,18,18},{13,18,18},{13,18,18},{13,16,19},{12,19,9},{12,16,5},{12,16,5},
+{12,15,3},{10,16,11},{11,15,2},{14,16,1},{14,16,1},{14,16,1},{14,15,2},{15,13,8},{13,16,2},{13,16,2},{11,15,2},{31,6,8},{11,15,2},{23,0,18},{13,18,1},{14,16,0},{12,16,0},{23,0,18},{46,0,18},{12,16,0},{0,15,26},{46,0,18},{0,15,26},{13,0,18},{13,0,18},{13,0,18},{13,0,18},{12,17,1},{12,17,1},{12,17,1},{12,15,2},{11,15,1},
+{11,15,1},{15,23,38},{15,20,21},{15,18,37},{15,18,21},{15,22,55},{15,19,23},{15,18,5},{14,17,30},{13,19,56},{13,17,28},{16,21,19},{16,19,3},{16,18,3},{16,18,6},{17,17,51},{15,19,19},{15,18,1},{14,17,26},{51,0,51},{14,17,26},{15,21,20},{15,21,20},{15,21,20},{15,18,20},{15,19,14},{15,18,4},{15,18,4},{14,17,5},{13,18,9},{13,17,3},{16,18,2},
+{16,18,2},{16,18,2},{16,17,2},{24,1,8},{15,18,0},{15,18,0},{14,17,1},{49,0,8},{14,17,1},{26,1,18},{15,20,1},{16,18,2},{15,18,1},{26,1,18},{53,0,18},{15,18,1},{0,17,26},{53,0,18},{0,17,26},{15,0,20},{15,0,20},{15,0,20},{15,0,20},{15,18,4},{15,18,4},{15,18,4},{14,17,4},{13,17,2},{13,17,2},{17,25,36},{17,22,19},{17,20,28},
+{17,20,20},{16,25,52},{16,21,22},{16,20,7},{16,19,28},{15,21,56},{15,19,28},{18,23,19},{18,21,3},{18,20,3},{18,20,6},{20,17,51},{16,21,21},{17,20,3},{14,20,26},{57,0,51},{14,20,26},{17,22,19},{17,22,19},{17,22,19},{17,20,19},{16,23,9},{16,20,6},{16,20,6},{16,19,3},{15,20,9},{15,19,3},{18,20,2},{18,20,2},{18,20,2},{18,19,2},{27,1,8},
+{17,20,2},{17,20,2},{15,19,2},{55,0,8},{15,19,2},{29,1,18},{17,22,1},{18,20,2},{16,20,2},{29,1,18},{59,0,18},{16,20,2},{0,19,26},{59,0,18},{0,19,26},{17,0,18},{17,0,18},{17,0,18},{17,0,18},{16,21,2},{16,21,2},{16,21,2},{16,19,2},{15,19,2},{15,19,2},{19,27,36},{19,24,19},{19,22,28},{19,22,20},{18,27,52},{18,23,22},{18,22,7},
+{18,21,28},{15,24,56},{17,21,27},{20,25,19},{20,23,3},{20,22,3},{20,22,6},{23,17,51},{18,23,21},{19,22,3},{17,21,27},{63,0,51},{17,21,27},{19,24,19},{19,24,19},{19,24,19},{19,22,19},{18,25,9},{18,22,6},{18,22,6},{18,21,3},{17,22,9},{17,21,2},{20,22,2},{20,22,2},{20,22,2},{20,21,2},{30,1,8},{19,22,2},{19,22,2},{17,21,2},{61,0,8},
+{17,21,2},{31,3,18},{19,24,1},{20,22,2},{18,22,2},{31,3,18},{63,1,18},{18,22,2},{0,21,26},{63,1,18},{0,21,26},{19,0,18},{19,0,18},{19,0,18},{19,0,18},{18,23,2},{18,23,2},{18,23,2},{18,21,2},{17,21,1},{17,21,1},{21,29,36},{21,26,19},{21,24,28},{21,24,20},{20,29,52},{20,25,22},{20,24,7},{20,23,28},{17,26,52},{19,23,27},{22,27,19},
+{22,25,3},{22,24,3},{22,24,6},{34,1,51},{20,25,21},{21,24,3},{19,23,27},{63,3,51},{19,23,27},{21,26,19},{21,26,19},{21,26,19},{21,24,19},{20,27,9},{20,24,6},{20,24,6},{20,23,3},{19,24,9},{19,23,2},{22,24,2},{22,24,2},{22,24,2},{22,23,2},{33,1,8},{21,24,2},{21,24,2},{19,23,2},{63,2,8},{19,23,2},{31,9,18},{21,26,1},{22,24,2},
+{20,24,2},{31,9,18},{63,4,18},{20,24,2},{0,23,26},{63,4,18},{0,23,26},{21,0,18},{21,0,18},{21,0,18},{21,0,18},{20,25,2},{20,25,2},{20,25,2},{20,23,2},{19,23,1},{19,23,1},{23,31,40},{23,29,24},{23,27,33},{23,26,24},{23,30,55},{22,28,24},{23,26,8},{22,26,28},{20,28,51},{21,26,21},{24,29,20},{24,28,1},{24,27,4},{24,26,5},{38,0,51},
+{22,28,20},{23,26,4},{20,26,20},{62,7,51},{20,26,20},{23,29,20},{23,29,20},{23,29,20},{23,26,20},{23,28,12},{23,26,4},{23,26,4},{22,25,4},{20,27,9},{22,25,4},{24,27,0},{24,27,0},{24,27,0},{24,26,1},{31,12,8},{23,26,0},{23,26,0},{22,25,0},{62,6,8},{22,25,0},{38,1,18},{24,28,1},{24,27,4},{23,26,4},{38,1,18},{45,16,18},{23,26,4},
+{0,26,20},{45,16,18},{0,26,20},{23,0,20},{23,0,20},{23,0,20},{23,0,20},{23,26,4},{23,26,4},{23,26,4},{22,25,4},{21,26,1},{21,26,1},{25,33,38},{25,31,24},{25,29,33},{25,28,24},{25,32,55},{24,30,24},{25,28,8},{24,28,28},{22,30,51},{23,28,21},{26,31,20},{26,30,1},{26,29,4},{26,28,5},{41,0,51},{24,30,20},{25,28,4},{22,28,20},{62,10,51},
+{22,28,20},{25,31,20},{25,31,20},{25,31,20},{25,28,20},{25,30,12},{25,28,4},{25,28,4},{24,27,4},{22,29,9},{24,27,4},{26,29,0},{26,29,0},{26,29,0},{26,28,1},{31,18,8},{25,28,0},{25,28,0},{24,27,0},{62,9,8},{24,27,0},{41,1,18},{26,30,1},{26,29,4},{25,28,4},{41,1,18},{51,16,18},{25,28,4},{0,28,20},{51,16,18},{0,28,20},{25,0,20},
+{25,0,20},{25,0,20},{25,0,20},{25,28,4},{25,28,4},{25,28,4},{24,27,4},{23,28,1},{23,28,1},{27,35,38},{27,32,21},{27,31,33},{27,30,24},{27,34,55},{26,32,24},{27,30,8},{26,30,28},{25,31,56},{25,30,21},{28,33,18},{28,32,2},{28,31,4},{28,30,5},{44,0,51},{26,32,20},{27,30,4},{24,30,20},{62,13,51},{24,30,20},{27,33,20},{27,33,20},{27,33,20},
+{27,30,20},{27,31,14},{27,30,4},{27,30,4},{26,29,4},{24,31,9},{26,29,4},{28,31,0},{28,31,0},{28,31,0},{28,30,1},{34,17,8},{27,30,0},{27,30,0},{26,29,0},{62,12,8},{26,29,0},{44,1,18},{27,32,1},{28,31,4},{27,30,4},{44,1,18},{57,16,18},{27,30,4},{0,30,20},{57,16,18},{0,30,20},{27,0,20},{27,0,20},{27,0,20},{27,0,20},{27,30,4},
+{27,30,4},{27,30,4},{26,29,4},{25,30,1},{25,30,1},{29,37,38},{29,34,21},{29,32,37},{29,32,21},{29,36,55},{29,33,23},{29,32,5},{28,32,39},{27,33,56},{26,32,30},{30,35,18},{30,34,2},{30,32,2},{30,32,5},{47,0,51},{29,33,19},{29,32,1},{26,32,26},{46,24,51},{26,32,26},{29,35,20},{29,35,20},{29,35,20},{29,32,20},{29,33,14},{29,32,4},{29,32,4},
+{28,31,4},{27,32,9},{28,31,4},{30,33,0},{30,33,0},{30,33,0},{30,31,4},{37,17,8},{29,32,0},{29,32,0},{28,31,0},{62,15,8},{28,31,0},{47,1,18},{29,34,1},{30,32,2},{29,32,1},{47,1,18},{63,16,18},{29,32,1},{0,32,26},{63,16,18},{0,32,26},{29,0,20},{29,0,20},{29,0,20},{29,0,20},{29,32,4},{29,32,4},{29,32,4},{28,31,4},{28,31,4},
+{28,31,4},{31,40,44},{31,37,28},{32,35,40},{31,34,31},{31,38,53},{31,35,21},{31,34,7},{31,34,30},{28,36,51},{29,34,21},{32,37,20},{32,36,1},{32,35,4},{32,34,5},{50,0,51},{30,36,19},{31,34,6},{28,34,21},{62,19,51},{28,34,21},{31,38,26},{31,38,26},{31,38,26},{31,34,27},{31,36,9},{31,34,3},{31,34,3},{31,33,2},{29,34,10},{30,33,2},{32,35,0},
+{32,35,0},{32,35,0},{32,34,1},{49,0,8},{31,34,2},{31,34,2},{30,33,1},{62,18,8},{30,33,1},{47,8,18},{32,36,1},{32,35,4},{31,34,5},{47,8,18},{62,20,18},{31,34,5},{0,34,20},{62,20,18},{0,34,20},{31,0,26},{31,0,26},{31,0,26},{31,0,26},{31,35,1},{31,35,1},{31,35,1},{31,33,2},{29,34,1},{29,34,1},{33,41,40},{33,39,24},{33,37,33},
+{33,36,24},{33,40,55},{32,38,24},{33,36,8},{32,36,28},{30,38,51},{31,36,21},{34,39,20},{34,38,1},{34,37,4},{34,36,5},{53,0,51},{32,38,20},{33,36,4},{30,36,21},{62,22,51},{30,36,21},{33,39,20},{33,39,20},{33,39,20},{33,36,20},{33,38,12},{33,36,4},{33,36,4},{32,35,4},{31,36,10},{32,35,4},{34,37,0},{34,37,0},{34,37,0},{34,36,1},{52,0,8},
+{33,36,0},{33,36,0},{32,35,0},{62,21,8},{32,35,0},{47,14,18},{34,38,1},{34,37,4},{33,36,4},{47,14,18},{62,23,18},{33,36,4},{0,36,20},{62,23,18},{0,36,20},{33,0,20},{33,0,20},{33,0,20},{33,0,20},{33,36,4},{33,36,4},{33,36,4},{32,35,4},{31,36,1},{31,36,1},{35,43,40},{35,41,24},{35,39,33},{35,38,24},{35,42,55},{34,40,24},{35,38,8},
+{34,38,28},{32,40,51},{33,38,21},{36,41,20},{36,40,1},{36,39,4},{36,38,5},{56,0,51},{34,40,20},{35,38,4},{32,38,20},{62,25,51},{32,38,20},{35,41,20},{35,41,20},{35,41,20},{35,38,20},{35,40,12},{35,38,4},{35,38,4},{34,37,4},{32,39,9},{34,37,4},{36,39,0},{36,39,0},{36,39,0},{36,38,1},{55,0,8},{35,38,0},{35,38,0},{34,37,0},{62,24,8},
+{34,37,0},{48,17,18},{36,40,1},{36,39,4},{35,38,4},{48,17,18},{62,26,18},{35,38,4},{0,38,20},{62,26,18},{0,38,20},{35,0,20},{35,0,20},{35,0,20},{35,0,20},{35,38,4},{35,38,4},{35,38,4},{34,37,4},{33,38,1},{33,38,1},{37,45,40},{37,43,24},{37,41,33},{37,40,24},{37,44,55},{36,42,24},{37,40,8},{36,40,28},{34,42,51},{35,40,21},{38,43,20},
+{38,42,1},{38,41,4},{38,40,5},{59,0,51},{36,42,20},{37,40,4},{34,40,20},{62,28,51},{34,40,20},{37,43,20},{37,43,20},{37,43,20},{37,40,20},{37,42,12},{37,40,4},{37,40,4},{36,39,4},{34,41,9},{36,39,4},{38,41,0},{38,41,0},{38,41,0},{38,40,1},{58,0,8},{37,40,0},{37,40,0},{36,39,0},{62,27,8},{36,39,0},{51,17,18},{38,42,1},{38,41,4},
+{37,40,4},{51,17,18},{62,29,18},{37,40,4},{0,40,20},{62,29,18},{0,40,20},{37,0,20},{37,0,20},{37,0,20},{37,0,20},{37,40,4},{37,40,4},{37,40,4},{36,39,4},{35,40,1},{35,40,1},{40,46,44},{40,44,27},{40,43,28},{39,43,28},{39,47,52},{39,44,22},{39,43,3},{38,42,28},{36,44,53},{37,42,19},{40,46,19},{40,44,2},{40,43,3},{40,42,10},{62,1,51},
+{38,44,19},{39,43,2},{37,42,18},{63,31,51},{37,42,18},{40,44,26},{40,44,26},{40,44,26},{40,42,26},{39,44,11},{39,43,2},{39,43,2},{39,41,2},{37,43,11},{38,41,3},{40,44,1},{40,44,1},{40,44,1},{40,42,1},{53,16,8},{40,42,1},{40,42,1},{39,41,1},{63,30,8},{39,41,1},{63,0,18},{40,44,1},{40,43,2},{38,43,1},{63,0,18},{62,32,18},{38,43,1},
+{0,42,18},{62,32,18},{0,42,18},{39,0,26},{39,0,26},{39,0,26},{39,0,26},{39,43,1},{39,43,1},{39,43,1},{39,41,1},{37,42,1},{37,42,1},{42,48,44},{42,46,27},{42,45,28},{41,45,28},{41,48,53},{41,46,22},{41,45,3},{40,44,28},{38,46,53},{39,44,19},{42,48,19},{42,46,2},{42,45,3},{42,44,10},{63,5,51},{40,46,19},{41,45,2},{39,44,18},{47,42,51},
+{39,44,18},{42,46,26},{42,46,26},{42,46,26},{42,44,26},{41,46,11},{41,45,2},{41,45,2},{41,43,2},{39,45,11},{40,43,3},{42,46,1},{42,46,1},{42,46,1},{42,44,1},{56,16,8},{42,44,1},{42,44,1},{41,43,1},{62,33,8},{41,43,1},{63,6,18},{42,46,1},{42,45,2},{40,45,1},{63,6,18},{62,35,18},{40,45,1},{0,44,18},{62,35,18},{0,44,18},{41,0,26},
+{41,0,26},{41,0,26},{41,0,26},{41,45,1},{41,45,1},{41,45,1},{41,43,1},{39,44,1},{39,44,1},{44,50,44},{44,48,26},{44,47,28},{43,47,28},{43,50,53},{43,47,27},{43,47,3},{42,46,28},{40,48,51},{41,46,19},{44,50,19},{44,48,1},{44,47,3},{44,46,10},{63,11,51},{42,48,19},{43,47,2},{41,46,18},{47,45,51},{41,46,18},{44,48,26},{44,48,26},{44,48,26},
+{44,46,26},{43,48,9},{43,47,2},{43,47,2},{43,45,2},{41,47,11},{42,45,3},{44,48,1},{44,48,1},{44,48,1},{44,46,1},{59,16,8},{44,46,1},{44,46,1},{43,45,1},{62,36,8},{43,45,1},{63,12,18},{44,48,0},{44,47,2},{42,47,1},{63,12,18},{62,38,18},{42,47,1},{0,46,18},{62,38,18},{0,46,18},{43,0,26},{43,0,26},{43,0,26},{43,0,26},{43,47,1},
+{43,47,1},{43,47,1},{43,45,1},{41,46,1},{41,46,1},{46,52,44},{46,50,26},{46,49,31},{45,48,31},{45,52,53},{45,49,21},{45,48,7},{45,48,30},{42,50,51},{43,48,21},{46,52,19},{46,50,1},{46,49,6},{46,48,6},{55,32,51},{44,50,19},{45,48,6},{42,48,21},{46,48,51},{42,48,21},{46,50,26},{46,50,26},{46,50,26},{45,48,27},{45,50,9},{45,48,3},{45,48,3},
+{45,47,2},{43,48,10},{44,47,3},{46,50,1},{46,50,1},{46,50,1},{46,48,2},{62,16,8},{45,48,2},{45,48,2},{45,47,1},{62,39,8},{45,47,1},{63,18,18},{46,50,0},{47,48,4},{45,48,5},{63,18,18},{62,41,18},{45,48,5},{0,48,20},{62,41,18},{0,48,20},{45,0,26},{45,0,26},{45,0,26},{45,0,26},{45,49,1},{45,49,1},{45,49,1},{45,47,1},{43,48,1},
+{43,48,1},{48,54,44},{48,52,27},{48,51,28},{48,50,35},{47,55,51},{47,52,21},{47,51,3},{47,50,22},{45,52,52},{45,50,19},{48,54,19},{48,52,2},{48,51,3},{48,50,10},{63,23,51},{47,52,21},{47,51,3},{45,50,18},{63,43,51},{45,50,18},{48,52,26},{48,52,26},{48,52,26},{48,50,26},{47,53,8},{47,51,2},{47,51,2},{47,49,1},{45,51,8},{46,49,5},{48,52,1},
+{48,52,1},{48,52,1},{48,50,1},{63,21,8},{48,50,1},{48,50,1},{47,49,1},{63,42,8},{47,49,1},{63,25,18},{48,52,1},{48,51,2},{46,51,1},{63,25,18},{63,44,18},{46,51,1},{0,50,18},{63,44,18},{0,50,18},{48,0,26},{48,0,26},{48,0,26},{48,0,26},{47,51,1},{47,51,1},{47,51,1},{47,49,0},{45,50,1},{45,50,1},{50,56,44},{50,54,27},{50,53,28},
+{49,53,28},{49,57,52},{49,54,22},{49,53,3},{48,52,28},{47,54,52},{47,52,19},{50,56,19},{50,54,2},{50,53,3},{50,52,10},{63,29,51},{48,54,19},{49,53,2},{47,52,18},{63,46,51},{47,52,18},{50,54,26},{50,54,26},{50,54,26},{50,52,26},{49,54,11},{49,53,2},{49,53,2},{49,51,2},{47,53,8},{48,51,3},{50,54,1},{50,54,1},{50,54,1},{50,52,1},{63,27,8},
+{50,52,1},{50,52,1},{49,51,1},{63,45,8},{49,51,1},{63,31,18},{50,54,1},{50,53,2},{48,53,1},{63,31,18},{63,47,18},{48,53,1},{0,52,18},{63,47,18},{0,52,18},{49,0,26},{49,0,26},{49,0,26},{49,0,26},{49,53,1},{49,53,1},{49,53,1},{49,51,1},{47,52,1},{47,52,1},{52,58,44},{52,56,27},{52,55,28},{51,55,28},{51,59,52},{51,56,22},{51,55,3},
+{50,54,28},{48,56,53},{49,54,19},{52,58,19},{52,56,2},{52,55,3},{52,54,10},{63,35,51},{50,56,19},{51,55,2},{49,54,18},{63,49,51},{49,54,18},{52,56,26},{52,56,26},{52,56,26},{52,54,26},{51,56,11},{51,55,2},{51,55,2},{51,53,2},{49,55,11},{50,53,3},{52,56,1},{52,56,1},{52,56,1},{52,54,1},{63,33,8},{52,54,1},{52,54,1},{51,53,1},{47,56,8},
+{51,53,1},{57,48,18},{52,56,1},{52,55,2},{50,55,1},{57,48,18},{62,50,18},{50,55,1},{0,54,18},{62,50,18},{0,54,18},{51,0,26},{51,0,26},{51,0,26},{51,0,26},{51,55,1},{51,55,1},{51,55,1},{51,53,1},{49,54,1},{49,54,1},{54,60,44},{54,58,27},{54,57,28},{53,57,28},{53,61,52},{53,58,22},{53,57,3},{52,56,28},{50,58,53},{51,56,19},{54,60,19},
+{54,58,2},{54,57,3},{54,56,10},{63,41,51},{52,58,19},{53,57,2},{51,56,18},{63,52,51},{51,56,18},{54,58,26},{54,58,26},{54,58,26},{54,56,26},{53,58,11},{53,57,2},{53,57,2},{53,55,2},{51,57,11},{52,55,3},{54,58,1},{54,58,1},{54,58,1},{54,56,1},{63,39,8},{54,56,1},{54,56,1},{53,55,1},{47,59,8},{53,55,1},{60,48,18},{54,58,1},{54,57,2},
+{52,57,1},{60,48,18},{62,53,18},{52,57,1},{0,56,18},{62,53,18},{0,56,18},{53,0,26},{53,0,26},{53,0,26},{53,0,26},{53,57,1},{53,57,1},{53,57,1},{53,55,1},{51,56,1},{51,56,1},{56,63,38},{56,61,21},{56,59,24},{56,59,24},{55,63,52},{55,60,18},{55,59,1},{55,58,24},{53,60,53},{54,58,21},{57,61,22},{56,61,5},{57,59,4},{56,59,8},{63,47,52},
+{55,60,18},{55,59,1},{54,58,20},{63,55,52},{54,58,20},{56,61,20},{56,61,20},{56,61,20},{56,58,21},{55,61,8},{55,59,1},{55,59,1},{55,57,5},{53,59,8},{54,58,5},{57,59,4},{57,59,4},{57,59,4},{57,58,4},{61,49,8},{56,58,1},{56,58,1},{56,57,4},{63,54,8},{56,57,4},{63,49,18},{56,61,1},{57,59,0},{55,59,0},{63,49,18},{63,56,18},{55,59,0},
+{0,58,20},{63,56,18},{0,58,20},{56,0,20},{56,0,20},{56,0,20},{56,0,20},{55,60,0},{55,60,0},{55,60,0},{55,57,1},{54,58,1},{54,58,1},{58,63,56},{58,63,21},{58,61,24},{58,61,24},{58,63,68},{57,62,18},{57,61,1},{57,60,24},{55,62,53},{56,60,21},{59,63,22},{58,63,5},{59,61,4},{58,61,8},{63,53,52},{57,62,18},{57,61,1},{56,60,20},{63,58,52},
+{56,60,20},{58,63,20},{58,63,20},{58,63,20},{58,60,21},{57,63,8},{57,61,1},{57,61,1},{57,59,5},{55,61,8},{56,60,5},{59,61,4},{59,61,4},{59,61,4},{59,60,4},{63,51,8},{58,60,1},{58,60,1},{58,59,4},{63,57,8},{58,59,4},{63,55,18},{58,63,1},{59,61,0},{57,61,0},{63,55,18},{63,59,18},{57,61,0},{0,60,20},{63,59,18},{0,60,20},{58,0,20},
+{58,0,20},{58,0,20},{58,0,20},{57,62,0},{57,62,0},{57,62,0},{57,59,1},{56,60,1},{56,60,1},{60,63,88},{60,63,40},{60,63,24},{60,63,24},{60,63,88},{59,63,37},{59,63,1},{59,62,24},{58,63,63},{58,62,21},{61,63,40},{61,63,13},{61,63,4},{60,63,8},{63,59,52},{60,63,24},{59,63,1},{58,62,20},{63,61,52},{58,62,20},{60,63,24},{60,63,24},{60,63,24},
+{60,62,21},{60,63,24},{59,63,1},{59,63,1},{59,61,5},{57,63,8},{58,62,5},{61,63,4},{61,63,4},{61,63,4},{61,62,4},{63,57,8},{60,62,1},{60,62,1},{60,61,4},{63,60,8},{60,61,4},{63,61,18},{61,63,9},{61,63,0},{59,63,0},{63,61,18},{63,62,18},{59,63,0},{0,62,20},{63,62,18},{0,62,20},{60,0,20},{60,0,20},{60,0,20},{60,0,20},{59,63,1},
+{59,63,1},{59,63,1},{59,61,1},{58,62,1},{58,62,1},{62,63,38},{62,63,33},{62,63,29},{62,63,24},{62,63,35},{62,63,25},{62,63,21},{61,63,1},{61,63,23},{60,63,4},{63,63,4},{63,63,4},{63,63,4},{63,63,4},{63,63,4},{63,63,4},{63,63,4},{62,63,0},{63,63,4},{62,63,0},{62,63,29},{62,63,29},{62,63,29},{62,63,24},{62,63,26},{62,63,21},{62,63,21},
+{61,63,1},{61,63,14},{60,63,4},{63,63,4},{63,63,4},{63,63,4},{63,63,4},{63,62,4},{63,63,4},{63,63,4},{62,63,0},{62,63,4},{62,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{62,0,20},{62,0,20},{62,0,20},{62,0,20},{61,63,16},{61,63,16},{61,63,16},{61,63,1},{60,63,4},
+{60,63,4},{0,8,74},{0,6,10},{0,4,1},{0,4,26},{0,6,154},{0,4,99},{0,3,50},{0,2,115},{0,3,170},{0,2,119},{0,8,74},{0,6,10},{0,4,1},{0,4,26},{3,0,154},{0,4,99},{0,3,50},{0,2,115},{6,0,154},{0,2,115},{0,4,0},{0,4,0},{0,4,0},{0,2,0},{0,2,13},{0,2,4},{0,2,4},{0,1,5},{0,1,14},{0,1,6},{0,4,0},
+{0,4,0},{0,4,0},{0,2,0},{1,0,13},{0,2,4},{0,2,4},{0,1,5},{2,0,13},{0,1,5},{4,0,74},{0,6,10},{0,4,1},{0,4,26},{4,0,74},{8,0,74},{0,4,26},{0,3,74},{8,0,74},{0,3,74},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,14,83},{0,10,10},{1,6,27},
+{0,6,19},{0,11,243},{0,7,110},{0,5,34},{0,4,139},{0,5,280},{0,4,164},{1,12,75},{1,9,2},{1,6,11},{1,6,18},{5,1,243},{0,7,110},{0,5,34},{0,4,139},{11,0,243},{0,4,139},{0,10,9},{0,10,9},{0,10,9},{0,5,9},{0,6,50},{0,5,9},{0,5,9},{0,3,26},{0,3,66},{0,2,33},{1,8,1},{1,8,1},{1,8,1},{1,4,2},{3,0,50},
+{0,5,9},{0,5,9},{0,3,26},{6,0,50},{0,3,26},{7,0,74},{1,9,1},{2,6,1},{0,6,10},{7,0,74},{14,0,74},{0,6,10},{0,5,74},{14,0,74},{0,5,74},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,2},{0,1,2},{1,18,137},{1,12,74},{2,9,98},{1,8,67},{0,16,244},{0,10,78},{0,8,2},
+{0,6,115},{0,8,344},{0,6,179},{3,14,75},{3,11,2},{3,8,11},{3,8,18},{8,1,243},{0,10,78},{0,8,2},{0,6,115},{15,1,243},{0,6,115},{1,14,65},{1,14,65},{1,14,65},{1,7,66},{0,12,50},{0,8,1},{0,8,1},{0,5,5},{0,5,104},{0,5,41},{3,10,1},{3,10,1},{3,10,1},{3,6,2},{6,0,50},{0,8,1},{0,8,1},{0,5,5},{12,0,50},
+{0,5,5},{2,16,72},{3,11,1},{4,8,1},{0,8,1},{2,16,72},{20,0,72},{0,8,1},{0,7,74},{20,0,72},{0,7,74},{1,0,65},{1,0,65},{1,0,65},{1,0,65},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{0,3,25},{0,3,25},{3,20,146},{3,14,83},{4,11,115},{3,10,76},{2,18,245},{2,12,79},{2,10,3},{1,8,108},{0,11,293},{0,8,103},{5,16,73},
+{5,13,2},{5,10,11},{5,10,18},{11,1,243},{1,13,75},{2,10,2},{0,8,94},{15,4,243},{0,8,94},{3,16,74},{3,16,74},{3,16,74},{3,9,75},{2,14,51},{2,10,2},{2,10,2},{2,7,6},{0,9,75},{0,7,6},{5,12,1},{5,12,1},{5,12,1},{5,8,2},{9,0,50},{2,10,1},{2,10,1},{0,7,2},{18,0,50},{0,7,2},{5,16,72},{5,13,1},{6,10,1},
+{2,10,1},{5,16,72},{26,0,72},{2,10,1},{0,9,74},{26,0,72},{0,9,74},{3,0,74},{3,0,74},{3,0,74},{3,0,74},{2,10,2},{2,10,2},{2,10,2},{2,6,2},{0,7,5},{0,7,5},{6,21,152},{6,16,82},{6,13,109},{5,12,84},{4,21,243},{4,15,78},{4,13,8},{4,11,108},{0,14,255},{0,11,77},{7,19,72},{7,15,1},{7,13,8},{7,12,13},{6,17,243},
+{3,15,72},{5,12,5},{0,11,73},{29,0,243},{0,11,73},{6,16,81},{6,16,81},{6,16,81},{5,12,80},{4,17,50},{4,13,4},{4,13,4},{4,9,5},{0,12,52},{1,10,4},{7,15,0},{7,15,0},{7,15,0},{7,11,0},{12,1,50},{5,12,1},{5,12,1},{3,9,4},{25,0,50},{3,9,4},{16,1,72},{7,15,1},{8,13,4},{5,12,4},{16,1,72},{33,0,72},{5,12,4},
+{0,11,72},{33,0,72},{0,11,72},{5,0,80},{5,0,80},{5,0,80},{5,0,80},{4,13,0},{4,13,0},{4,13,0},{4,9,1},{1,10,0},{1,10,0},{8,23,152},{8,18,82},{8,15,109},{7,14,84},{6,23,243},{6,16,75},{6,15,8},{6,13,108},{1,17,244},{2,13,77},{9,21,72},{9,17,1},{9,15,8},{9,14,13},{17,1,243},{5,17,72},{7,14,5},{1,13,72},{35,0,243},
+{1,13,72},{8,18,81},{8,18,81},{8,18,81},{7,14,80},{6,19,50},{6,15,4},{6,15,4},{6,11,5},{2,14,52},{3,12,4},{9,16,1},{9,16,1},{9,16,1},{9,13,0},{15,1,50},{7,14,1},{7,14,1},{5,11,4},{31,0,50},{5,11,4},{19,1,72},{9,17,1},{10,15,4},{7,14,4},{19,1,72},{39,0,72},{7,14,4},{0,13,72},{39,0,72},{0,13,72},{7,0,80},
+{7,0,80},{7,0,80},{7,0,80},{6,15,0},{6,15,0},{6,15,0},{6,11,1},{3,12,0},{3,12,0},{10,25,152},{10,20,82},{10,17,114},{9,16,82},{8,25,243},{8,18,75},{8,16,2},{8,15,108},{3,19,244},{4,15,77},{11,23,72},{11,19,1},{11,16,10},{11,16,17},{20,1,243},{7,19,72},{8,16,2},{3,15,72},{41,0,243},{3,15,72},{10,20,81},{10,20,81},{10,20,81},
+{10,15,81},{8,21,50},{8,16,1},{8,16,1},{8,13,5},{4,16,52},{5,14,4},{11,18,1},{11,18,1},{11,18,1},{11,15,0},{15,7,50},{8,16,1},{8,16,1},{7,13,4},{31,3,50},{7,13,4},{22,1,72},{11,19,1},{12,16,2},{8,16,1},{22,1,72},{45,0,72},{8,16,1},{0,15,72},{45,0,72},{0,15,72},{9,0,80},{9,0,80},{9,0,80},{9,0,80},{8,17,0},
+{8,17,0},{8,17,0},{8,13,1},{5,14,0},{5,14,0},{12,27,152},{12,22,82},{12,19,114},{11,18,82},{10,27,243},{10,20,75},{10,18,2},{10,16,106},{5,21,244},{6,17,79},{13,25,72},{13,21,1},{13,18,10},{13,18,17},{23,1,243},{9,21,72},{10,18,2},{5,17,74},{47,0,243},{5,17,74},{12,22,81},{12,22,81},{12,22,81},{12,17,80},{10,23,50},{10,18,1},{10,18,1},
+{10,15,5},{6,18,52},{8,15,9},{13,20,1},{13,20,1},{13,20,1},{13,17,1},{15,13,50},{10,18,1},{10,18,1},{9,15,4},{31,6,50},{9,15,4},{25,1,72},{13,21,1},{14,18,2},{10,18,1},{25,1,72},{47,2,72},{10,18,1},{0,17,74},{47,2,72},{0,17,74},{11,0,80},{11,0,80},{11,0,80},{11,0,80},{10,19,0},{10,19,0},{10,19,0},{10,15,1},{7,16,0},
+{7,16,0},{14,30,146},{14,24,78},{14,21,114},{14,20,79},{12,30,244},{12,23,79},{12,21,7},{12,19,109},{7,23,244},{9,19,76},{15,28,73},{15,23,2},{15,21,14},{15,20,14},{27,0,243},{11,23,75},{13,20,4},{7,19,73},{46,4,243},{7,19,73},{14,25,74},{14,25,74},{14,25,74},{14,19,75},{12,25,53},{12,21,3},{12,21,3},{12,17,6},{8,21,52},{9,18,6},{15,23,1},
+{15,23,1},{15,23,1},{15,19,1},{24,1,50},{13,20,0},{13,20,0},{11,17,5},{49,0,50},{11,17,5},{20,17,72},{15,23,1},{16,21,4},{13,20,4},{20,17,72},{57,0,72},{13,20,4},{0,19,72},{57,0,72},{0,19,72},{14,0,74},{14,0,74},{14,0,74},{14,0,74},{12,22,1},{12,22,1},{12,22,1},{12,17,2},{9,18,2},{9,18,2},{16,31,152},{16,26,81},{16,23,109},
+{16,22,88},{14,32,244},{14,25,79},{14,23,7},{14,21,109},{9,25,244},{11,21,76},{17,29,72},{17,25,1},{17,23,8},{17,22,13},{30,0,243},{13,25,75},{15,22,4},{9,21,73},{46,7,243},{9,21,73},{16,27,80},{16,27,80},{16,27,80},{16,21,81},{14,27,53},{14,23,3},{14,23,3},{14,19,6},{10,23,52},{11,20,6},{17,25,0},{17,25,0},{17,25,0},{17,21,0},{27,1,50},
+{15,22,0},{15,22,0},{13,19,5},{55,0,50},{13,19,5},{23,17,72},{17,25,1},{18,23,4},{15,22,4},{23,17,72},{63,0,72},{15,22,4},{0,21,72},{63,0,72},{0,21,72},{16,0,80},{16,0,80},{16,0,80},{16,0,80},{14,24,1},{14,24,1},{14,24,1},{14,19,2},{11,20,2},{11,20,2},{18,33,152},{18,28,81},{18,25,109},{17,24,84},{16,33,243},{16,27,78},{16,25,8},
+{16,23,108},{11,27,244},{13,23,76},{19,31,72},{19,27,1},{19,25,8},{19,24,13},{32,1,243},{15,27,75},{17,24,5},{11,23,73},{46,10,243},{11,23,73},{18,29,80},{18,29,80},{18,29,80},{17,24,80},{16,29,50},{16,25,4},{16,25,4},{16,21,5},{12,25,52},{13,22,6},{19,27,0},{19,27,0},{19,27,0},{19,23,0},{30,1,50},{17,24,1},{17,24,1},{15,21,5},{61,0,50},
+{15,21,5},{34,1,72},{19,27,1},{20,25,4},{17,24,4},{34,1,72},{63,3,72},{17,24,4},{0,23,72},{63,3,72},{0,23,72},{17,0,80},{17,0,80},{17,0,80},{17,0,80},{16,25,0},{16,25,0},{16,25,0},{16,21,1},{13,22,2},{13,22,2},{20,35,152},{20,30,81},{20,27,109},{19,26,84},{18,35,243},{18,29,78},{18,27,8},{18,25,108},{13,29,244},{15,25,76},{21,33,72},
+{21,29,1},{21,27,8},{21,26,13},{35,1,243},{17,29,72},{19,26,5},{13,25,73},{46,13,243},{13,25,73},{20,31,80},{20,31,80},{20,31,80},{19,26,80},{18,31,50},{18,27,4},{18,27,4},{18,23,5},{14,27,52},{15,24,6},{21,29,0},{21,29,0},{21,29,0},{21,25,0},{33,1,50},{19,26,1},{19,26,1},{17,23,4},{63,2,50},{17,23,4},{37,1,72},{21,29,1},{22,27,4},
+{19,26,4},{37,1,72},{63,6,72},{19,26,4},{0,25,72},{63,6,72},{0,25,72},{19,0,80},{19,0,80},{19,0,80},{19,0,80},{18,27,0},{18,27,0},{18,27,0},{18,23,1},{15,24,2},{15,24,2},{22,38,146},{22,32,78},{22,29,111},{22,28,84},{20,38,244},{20,31,74},{20,29,4},{20,27,100},{14,32,247},{17,27,75},{23,36,73},{23,32,3},{23,29,11},{23,28,14},{39,0,243},
+{20,31,73},{20,29,3},{16,27,74},{62,8,243},{16,27,74},{22,33,74},{22,33,74},{22,33,74},{22,28,75},{20,33,53},{20,29,3},{20,29,3},{20,25,10},{16,29,50},{18,26,2},{23,31,2},{23,31,2},{23,31,2},{23,27,2},{31,12,50},{21,28,1},{21,28,1},{18,26,1},{62,6,50},{18,26,1},{41,0,72},{23,32,2},{24,29,2},{19,29,2},{41,0,72},{62,10,72},{19,29,2},
+{0,27,74},{62,10,72},{0,27,74},{22,0,74},{22,0,74},{22,0,74},{22,0,74},{20,30,1},{20,30,1},{20,30,1},{20,25,1},{18,26,1},{18,26,1},{24,40,146},{24,34,78},{24,31,111},{24,30,84},{22,40,244},{22,33,79},{22,31,4},{22,29,100},{17,33,244},{19,29,75},{25,38,73},{25,33,2},{25,31,11},{25,30,14},{42,0,243},{21,33,75},{22,31,3},{18,29,74},{62,11,243},
+{18,29,74},{24,35,74},{24,35,74},{24,35,74},{24,30,75},{22,35,53},{22,31,3},{22,31,3},{22,27,10},{18,31,50},{20,28,2},{25,33,1},{25,33,1},{25,33,1},{25,29,2},{31,18,50},{23,30,1},{23,30,1},{20,28,1},{62,9,50},{20,28,1},{44,0,72},{25,33,1},{26,31,2},{21,31,2},{44,0,72},{62,13,72},{21,31,2},{0,29,74},{62,13,72},{0,29,74},{24,0,74},
+{24,0,74},{24,0,74},{24,0,74},{22,32,1},{22,32,1},{22,32,1},{22,27,1},{20,28,1},{20,28,1},{26,42,146},{26,36,78},{26,33,114},{26,32,79},{24,42,244},{24,35,79},{24,33,7},{24,31,100},{19,35,244},{21,31,75},{27,40,73},{27,35,2},{28,33,13},{27,32,14},{45,0,243},{23,35,75},{25,32,4},{20,31,74},{62,14,243},{20,31,74},{26,37,74},{26,37,74},{26,37,74},
+{26,32,75},{24,37,53},{24,33,3},{24,33,3},{24,29,10},{20,33,52},{22,30,2},{27,35,1},{27,35,1},{27,35,1},{27,31,2},{34,17,50},{25,32,0},{25,32,0},{22,30,1},{62,12,50},{22,30,1},{47,0,72},{27,35,1},{28,33,4},{25,32,4},{47,0,72},{46,24,72},{25,32,4},{0,31,74},{46,24,72},{0,31,74},{26,0,74},{26,0,74},{26,0,74},{26,0,74},{24,34,1},
+{24,34,1},{24,34,1},{24,29,1},{22,30,1},{22,30,1},{28,44,146},{28,38,78},{28,35,114},{28,34,79},{26,44,244},{26,37,79},{26,35,7},{26,33,109},{21,37,244},{23,33,76},{29,42,73},{29,37,2},{30,35,13},{29,34,14},{47,2,243},{25,37,75},{27,34,4},{21,33,73},{62,17,243},{21,33,73},{28,39,74},{28,39,74},{28,39,74},{28,33,75},{26,39,53},{26,35,3},{26,35,3},
+{26,31,10},{22,35,52},{23,32,6},{29,37,1},{29,37,1},{29,37,1},{29,33,1},{37,17,50},{27,34,0},{27,34,0},{23,32,5},{62,15,50},{23,32,5},{49,1,72},{29,37,1},{30,35,4},{27,34,4},{49,1,72},{46,27,72},{27,34,4},{0,33,72},{46,27,72},{0,33,72},{28,0,74},{28,0,74},{28,0,74},{28,0,74},{26,36,1},{26,36,1},{26,36,1},{26,31,1},{23,32,2},
+{23,32,2},{30,46,146},{30,41,77},{31,37,121},{30,36,81},{29,45,247},{28,39,77},{28,37,9},{28,35,103},{24,39,248},{25,35,76},{31,44,78},{31,40,4},{32,37,11},{31,36,17},{51,0,243},{28,39,73},{28,37,5},{24,35,74},{47,28,243},{24,35,74},{30,42,72},{30,42,72},{30,42,72},{30,36,72},{29,40,54},{29,36,6},{29,36,6},{28,34,9},{24,37,51},{26,34,2},{31,40,4},
+{31,40,4},{31,40,4},{31,35,5},{49,0,50},{29,36,2},{29,36,2},{26,34,1},{62,18,50},{26,34,1},{53,0,72},{31,40,0},{32,37,2},{28,37,1},{53,0,72},{62,22,72},{28,37,1},{0,35,74},{62,22,72},{0,35,74},{30,0,72},{30,0,72},{30,0,72},{30,0,72},{29,36,5},{29,36,5},{29,36,5},{28,33,4},{26,34,1},{26,34,1},{32,48,146},{32,42,79},{32,39,111},
+{32,38,84},{31,47,247},{30,41,77},{30,39,9},{30,37,103},{26,41,248},{27,37,76},{33,46,73},{33,42,3},{33,39,11},{33,38,14},{54,0,243},{30,41,73},{30,39,5},{26,37,74},{47,31,243},{26,37,74},{32,43,75},{32,43,75},{32,43,75},{32,38,75},{31,42,54},{31,38,6},{31,38,6},{30,36,9},{26,39,51},{28,36,2},{33,41,2},{33,41,2},{33,41,2},{33,37,2},{52,0,50},
+{31,38,2},{31,38,2},{28,36,1},{62,21,50},{28,36,1},{56,0,72},{33,42,2},{34,39,2},{30,39,1},{56,0,72},{62,25,72},{30,39,1},{0,37,74},{62,25,72},{0,37,74},{32,0,74},{32,0,74},{32,0,74},{32,0,74},{31,38,5},{31,38,5},{31,38,5},{30,35,4},{28,36,1},{28,36,1},{34,50,146},{34,44,79},{34,41,111},{34,40,84},{32,50,244},{32,43,74},{32,41,4},
+{32,39,100},{28,43,248},{29,39,76},{35,48,73},{35,44,3},{35,41,11},{35,40,14},{57,0,243},{32,43,73},{32,41,3},{28,39,74},{50,32,243},{28,39,74},{34,45,75},{34,45,75},{34,45,75},{34,40,75},{32,46,51},{32,41,3},{32,41,3},{32,37,10},{28,41,51},{30,38,2},{35,43,2},{35,43,2},{35,43,2},{35,39,2},{55,0,50},{33,40,1},{33,40,1},{30,38,1},{62,24,50},
+{30,38,1},{59,0,72},{35,44,2},{36,41,2},{31,41,2},{59,0,72},{62,28,72},{31,41,2},{0,39,74},{62,28,72},{0,39,74},{34,0,74},{34,0,74},{34,0,74},{34,0,74},{32,42,1},{32,42,1},{32,42,1},{32,37,1},{30,38,1},{30,38,1},{36,52,146},{36,46,79},{36,43,111},{36,42,84},{34,52,244},{34,45,74},{34,43,4},{34,41,100},{30,45,248},{31,41,76},{37,50,73},
+{37,46,3},{37,43,11},{37,42,14},{60,0,243},{34,45,73},{34,43,3},{30,41,74},{56,32,243},{30,41,74},{36,47,75},{36,47,75},{36,47,75},{36,42,75},{34,47,53},{34,43,3},{34,43,3},{34,39,10},{30,43,51},{32,40,2},{37,45,2},{37,45,2},{37,45,2},{37,41,2},{58,0,50},{35,42,1},{35,42,1},{32,40,1},{62,27,50},{32,40,1},{62,0,72},{37,46,2},{38,43,2},
+{33,43,2},{62,0,72},{62,31,72},{33,43,2},{0,41,74},{62,31,72},{0,41,74},{36,0,74},{36,0,74},{36,0,74},{36,0,74},{34,44,1},{34,44,1},{34,44,1},{34,39,1},{32,40,1},{32,40,1},{38,54,146},{38,49,77},{39,45,120},{38,45,76},{37,53,247},{36,47,78},{37,45,5},{36,43,100},{31,48,243},{33,43,81},{40,50,78},{39,48,4},{40,45,8},{39,45,20},{63,1,243},
+{36,47,74},{37,45,1},{33,43,80},{63,32,243},{33,43,80},{38,50,72},{38,50,72},{38,50,72},{38,44,72},{37,48,54},{37,45,5},{37,45,5},{36,42,8},{32,45,53},{34,42,1},{40,46,4},{40,46,4},{40,46,4},{40,43,4},{53,16,50},{37,45,1},{37,45,1},{35,42,0},{63,30,50},{35,42,0},{63,5,72},{39,48,0},{41,45,1},{36,45,0},{63,5,72},{47,42,72},{36,45,0},
+{0,43,80},{47,42,72},{0,43,80},{38,0,72},{38,0,72},{38,0,72},{38,0,72},{37,45,4},{37,45,4},{37,45,4},{37,41,4},{34,42,1},{34,42,1},{40,56,146},{40,51,77},{41,47,120},{40,47,76},{39,55,247},{38,49,77},{39,47,5},{38,45,100},{34,49,248},{35,45,81},{42,52,78},{41,50,4},{42,47,8},{41,47,20},{63,7,243},{38,49,73},{39,47,1},{35,45,80},{63,35,243},
+{35,45,80},{40,52,72},{40,52,72},{40,52,72},{40,46,72},{39,50,54},{39,47,5},{39,47,5},{38,44,8},{34,47,53},{36,44,1},{42,48,4},{42,48,4},{42,48,4},{42,45,4},{56,16,50},{39,47,1},{39,47,1},{37,44,0},{62,33,50},{37,44,0},{63,11,72},{41,50,0},{43,47,1},{38,47,0},{63,11,72},{47,45,72},{38,47,0},{0,45,80},{47,45,72},{0,45,80},{40,0,72},
+{40,0,72},{40,0,72},{40,0,72},{39,47,4},{39,47,4},{39,47,4},{39,43,4},{36,44,1},{36,44,1},{42,58,146},{42,53,77},{43,49,121},{42,48,81},{41,57,247},{40,51,77},{40,49,9},{40,47,100},{36,51,248},{37,47,81},{44,54,78},{43,52,4},{44,49,6},{43,48,17},{63,13,243},{40,51,73},{40,49,5},{37,47,80},{63,38,243},{37,47,80},{42,54,72},{42,54,72},{42,54,72},
+{42,48,72},{41,52,54},{41,48,6},{41,48,6},{40,46,8},{36,49,51},{38,46,1},{44,50,4},{44,50,4},{44,50,4},{44,47,4},{59,16,50},{41,48,2},{41,48,2},{39,46,0},{62,36,50},{39,46,0},{55,32,72},{43,52,0},{44,49,2},{40,49,1},{55,32,72},{46,48,72},{40,49,1},{0,47,80},{46,48,72},{0,47,80},{42,0,72},{42,0,72},{42,0,72},{42,0,72},{41,48,5},
+{41,48,5},{41,48,5},{41,45,4},{38,46,1},{38,46,1},{44,60,146},{44,55,77},{45,51,121},{44,50,81},{43,59,247},{42,53,77},{42,51,9},{42,49,103},{38,53,248},{39,49,76},{46,56,78},{45,54,4},{46,51,6},{45,50,17},{63,19,243},{42,53,73},{42,51,5},{38,49,74},{63,41,243},{38,49,74},{44,56,72},{44,56,72},{44,56,72},{44,50,72},{43,54,54},{43,50,6},{43,50,6},
+{42,48,9},{38,51,51},{40,48,2},{46,52,4},{46,52,4},{46,52,4},{46,49,4},{62,16,50},{43,50,2},{43,50,2},{40,48,1},{62,39,50},{40,48,1},{58,32,72},{45,54,0},{46,51,2},{42,51,1},{58,32,72},{52,48,72},{42,51,1},{0,49,74},{52,48,72},{0,49,74},{44,0,72},{44,0,72},{44,0,72},{44,0,72},{43,50,5},{43,50,5},{43,50,5},{43,47,4},{40,48,1},
+{40,48,1},{46,63,146},{46,57,79},{47,53,115},{46,53,78},{45,61,245},{45,55,77},{45,53,2},{44,51,105},{39,56,243},{42,51,82},{48,59,76},{48,55,9},{48,53,8},{47,53,18},{59,33,243},{44,55,74},{45,53,1},{41,51,80},{55,48,243},{41,51,80},{46,59,74},{46,59,74},{46,59,74},{46,52,75},{45,57,51},{45,53,2},{45,53,2},{44,50,10},{41,53,51},{42,50,1},{48,54,4},
+{48,54,4},{48,54,4},{48,51,4},{63,21,50},{45,53,1},{45,53,1},{43,50,0},{63,42,50},{43,50,0},{63,29,72},{47,56,2},{49,53,1},{44,53,1},{63,29,72},{63,46,72},{44,53,1},{0,51,80},{63,46,72},{0,51,80},{46,0,74},{46,0,74},{46,0,74},{46,0,74},{45,53,1},{45,53,1},{45,53,1},{45,49,1},{42,50,1},{42,50,1},{48,63,152},{48,59,77},{49,55,120},
+{48,55,76},{47,63,245},{47,57,77},{47,55,2},{46,53,105},{41,58,243},{44,53,82},{50,61,76},{49,58,4},{50,55,8},{49,55,20},{62,33,243},{46,57,74},{47,55,1},{43,53,80},{61,48,243},{43,53,80},{48,60,72},{48,60,72},{48,60,72},{48,54,72},{47,59,51},{47,55,2},{47,55,2},{46,52,10},{43,55,51},{44,52,1},{50,56,4},{50,56,4},{50,56,4},{50,53,4},{63,27,50},
+{47,55,1},{47,55,1},{45,52,0},{63,45,50},{45,52,0},{63,35,72},{49,58,0},{51,55,1},{46,55,1},{63,35,72},{63,49,72},{46,55,1},{0,53,80},{63,49,72},{0,53,80},{48,0,72},{48,0,72},{48,0,72},{48,0,72},{47,55,1},{47,55,1},{47,55,1},{47,51,1},{44,52,1},{44,52,1},{51,63,184},{50,61,77},{51,57,120},{50,57,76},{49,63,268},{48,59,78},{49,57,5},
+{48,55,100},{43,60,243},{46,55,82},{52,63,76},{51,60,4},{52,57,8},{51,57,20},{63,37,243},{48,59,74},{49,57,1},{45,55,80},{63,50,243},{45,55,80},{50,62,72},{50,62,72},{50,62,72},{50,56,72},{49,60,56},{49,57,5},{49,57,5},{48,54,8},{45,57,51},{46,54,1},{52,58,4},{52,58,4},{52,58,4},{52,55,4},{63,33,50},{49,57,1},{49,57,1},{47,54,0},{47,56,50},
+{47,54,0},{63,41,72},{51,60,0},{53,57,1},{48,57,0},{63,41,72},{63,52,72},{48,57,0},{0,55,80},{63,52,72},{0,55,80},{50,0,72},{50,0,72},{50,0,72},{50,0,72},{49,57,4},{49,57,4},{49,57,4},{49,53,4},{46,54,1},{46,54,1},{53,63,226},{52,63,77},{53,59,120},{52,59,76},{52,63,300},{50,61,78},{51,59,5},{50,57,100},{45,62,243},{47,57,84},{54,63,84},
+{53,62,4},{54,59,8},{53,59,20},{63,43,243},{49,62,73},{51,59,1},{47,57,80},{63,53,243},{47,57,80},{52,63,76},{52,63,76},{52,63,76},{52,58,72},{51,62,56},{51,59,5},{51,59,5},{50,56,8},{47,59,51},{48,56,1},{54,60,4},{54,60,4},{54,60,4},{54,57,4},{63,39,50},{51,59,1},{51,59,1},{49,56,0},{47,59,50},{49,56,0},{63,47,72},{53,62,0},{55,59,1},
+{50,59,0},{63,47,72},{63,55,72},{50,59,0},{0,57,80},{63,55,72},{0,57,80},{52,0,72},{52,0,72},{52,0,72},{52,0,72},{51,59,4},{51,59,4},{51,59,4},{51,55,4},{48,56,1},{48,56,1},{56,63,314},{55,63,115},{55,62,115},{54,61,76},{54,63,364},{53,63,79},{53,61,3},{52,59,108},{48,63,252},{49,60,79},{57,63,115},{56,63,10},{56,61,11},{56,61,18},{63,50,243},
+{53,63,78},{53,61,2},{47,60,75},{62,57,243},{47,60,75},{54,63,99},{54,63,99},{54,63,99},{54,60,75},{53,63,69},{53,61,2},{53,61,2},{53,58,6},{49,61,51},{50,58,6},{56,63,1},{56,63,1},{56,63,1},{56,59,2},{61,49,50},{53,61,1},{53,61,1},{51,58,2},{63,54,50},{51,58,2},{63,53,74},{56,63,9},{57,61,1},{53,61,1},{63,53,74},{63,58,74},{53,61,1},
+{0,60,74},{63,58,74},{0,60,74},{54,0,74},{54,0,74},{54,0,74},{54,0,74},{53,61,2},{53,61,2},{53,61,2},{53,57,2},{50,59,2},{50,59,2},{57,63,371},{57,63,179},{57,63,115},{56,63,75},{57,63,387},{55,63,123},{55,63,2},{54,61,91},{52,63,286},{51,62,70},{59,63,146},{58,63,59},{58,63,10},{58,63,17},{63,55,221},{57,63,98},{55,63,1},{49,62,66},{63,59,221},
+{49,62,66},{57,63,115},{57,63,115},{57,63,115},{56,62,75},{56,63,93},{55,63,2},{55,63,2},{55,60,6},{51,63,51},{52,60,6},{58,63,10},{58,63,10},{58,63,10},{58,61,2},{63,51,50},{55,63,1},{55,63,1},{53,60,2},{63,57,50},{53,60,2},{63,59,61},{60,63,25},{59,63,0},{55,63,0},{63,59,61},{63,61,61},{55,63,0},{0,62,65},{63,61,61},{0,62,65},{56,0,74},
+{56,0,74},{56,0,74},{56,0,74},{55,63,2},{55,63,2},{55,63,2},{55,59,2},{52,61,2},{52,61,2},{60,63,259},{59,63,190},{59,63,154},{58,63,90},{59,63,270},{58,63,91},{57,63,35},{57,62,22},{56,63,194},{54,63,11},{61,63,70},{60,63,42},{60,63,26},{60,63,2},{63,59,94},{60,63,42},{59,63,13},{53,63,10},{63,61,94},{53,63,10},{59,63,154},{59,63,154},{59,63,154},
+{58,63,90},{58,63,147},{57,63,35},{57,63,35},{57,62,6},{55,63,77},{54,62,6},{60,63,26},{60,63,26},{60,63,26},{60,63,2},{63,57,50},{59,63,13},{59,63,13},{55,62,2},{63,60,50},{55,62,2},{63,62,5},{62,63,4},{62,63,0},{61,63,0},{63,62,5},{62,63,5},{61,63,0},{0,63,9},{62,63,5},{0,63,9},{58,0,74},{58,0,74},{58,0,74},{58,0,74},{57,63,10},
+{57,63,10},{57,63,10},{57,61,2},{54,63,2},{54,63,2},{61,63,162},{61,63,135},{61,63,126},{60,63,90},{61,63,154},{60,63,66},{60,63,50},{59,63,2},{59,63,109},{57,63,10},{62,63,19},{62,63,14},{62,63,10},{62,63,5},{63,62,17},{62,63,12},{62,63,8},{59,63,1},{62,63,17},{59,63,1},{61,63,126},{61,63,126},{61,63,126},{60,63,90},{60,63,98},{60,63,50},{60,63,50},
+{59,63,2},{58,63,62},{57,63,10},{62,63,10},{62,63,10},{62,63,10},{62,63,5},{63,61,13},{62,63,8},{62,63,8},{59,63,1},{63,62,13},{59,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{60,0,74},{60,0,74},{60,0,74},{60,0,74},{60,63,34},{60,63,34},{60,63,34},{59,63,2},{57,63,10},
+{57,63,10},{0,14,202},{0,10,25},{0,7,1},{0,6,74},{0,10,441},{0,6,282},{0,5,133},{0,4,318},{0,5,477},{0,4,343},{0,14,202},{0,10,25},{0,7,1},{0,6,74},{5,0,441},{0,6,282},{0,5,133},{0,4,318},{10,0,441},{0,4,318},{0,7,0},{0,7,0},{0,7,0},{0,3,1},{0,3,41},{0,3,17},{0,3,17},{0,2,26},{0,2,45},{0,1,30},{0,7,0},
+{0,7,0},{0,7,0},{0,3,1},{2,0,41},{0,3,17},{0,3,17},{0,2,26},{3,0,41},{0,2,26},{7,0,202},{0,10,25},{0,7,1},{0,6,74},{7,0,202},{14,0,202},{0,6,74},{0,5,202},{14,0,202},{0,5,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,20,200},{0,14,1},{0,10,25},
+{0,8,41},{0,14,686},{0,9,362},{0,8,141},{0,5,467},{0,6,762},{0,5,503},{0,20,200},{0,14,1},{0,10,25},{0,8,41},{7,0,686},{0,9,362},{0,8,141},{0,5,467},{14,0,686},{0,5,467},{0,13,0},{0,13,0},{0,13,0},{0,6,1},{0,6,145},{0,5,52},{0,5,52},{0,3,89},{0,3,161},{0,3,105},{0,13,0},{0,13,0},{0,13,0},{0,6,1},{3,0,145},
+{0,5,52},{0,5,52},{0,3,89},{6,0,145},{0,3,89},{2,16,200},{0,14,1},{2,9,1},{0,8,41},{2,16,200},{20,0,200},{0,8,41},{0,7,202},{20,0,200},{0,7,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,24,225},{1,16,27},{1,12,83},{1,11,51},{0,19,724},{0,12,299},{0,10,62},
+{0,8,414},{0,9,875},{0,7,500},{2,22,201},{2,16,6},{2,12,26},{1,11,35},{10,0,723},{0,12,299},{0,10,62},{0,8,414},{14,3,723},{0,8,414},{1,17,25},{1,17,25},{1,17,25},{1,9,25},{0,12,162},{0,8,25},{0,8,25},{0,5,61},{0,5,216},{0,5,97},{2,15,1},{2,15,1},{2,15,1},{2,8,2},{6,0,162},{0,8,25},{0,8,25},{0,5,61},{12,0,162},
+{0,5,61},{5,16,200},{1,16,2},{4,11,1},{0,11,17},{5,16,200},{26,0,200},{0,11,17},{0,9,202},{26,0,200},{0,9,202},{1,0,25},{1,0,25},{1,0,25},{1,0,25},{0,5,1},{0,5,1},{0,5,1},{0,3,1},{0,2,8},{0,2,8},{2,28,313},{2,19,118},{2,14,203},{2,13,130},{0,25,724},{0,16,236},{0,13,6},{0,10,339},{0,11,984},{0,10,508},{4,24,201},
+{4,17,5},{4,14,26},{3,13,35},{13,0,723},{0,16,236},{0,13,6},{0,10,339},{14,6,723},{0,10,339},{2,21,113},{2,21,113},{2,21,113},{2,11,114},{0,18,162},{0,12,2},{0,12,2},{0,7,34},{0,8,280},{0,7,115},{4,17,1},{4,17,1},{4,17,1},{4,10,2},{9,0,162},{0,12,2},{0,12,2},{0,7,34},{18,0,162},{0,7,34},{16,0,200},{3,18,2},{6,13,1},
+{0,13,2},{16,0,200},{32,0,200},{0,13,2},{0,11,202},{32,0,200},{0,11,202},{2,0,113},{2,0,113},{2,0,113},{2,0,113},{0,11,1},{0,11,1},{0,11,1},{0,6,1},{0,5,40},{0,5,40},{4,31,408},{4,22,216},{4,16,317},{3,15,216},{1,30,723},{1,19,216},{1,15,9},{0,12,312},{0,15,1000},{0,12,440},{6,27,200},{6,20,1},{7,16,29},{5,15,36},{16,0,723},
+{0,19,203},{2,15,5},{0,12,296},{32,0,723},{0,12,296},{4,23,209},{4,23,209},{4,23,209},{4,14,208},{1,23,162},{1,16,4},{1,16,4},{1,10,20},{0,11,294},{0,10,89},{6,19,1},{6,19,1},{6,19,1},{6,13,0},{12,1,162},{2,15,1},{2,15,1},{0,10,8},{25,0,162},{0,10,8},{19,1,200},{6,20,1},{8,15,5},{2,15,4},{19,1,200},{39,0,200},{2,15,4},
+{0,13,200},{39,0,200},{0,13,200},{3,0,208},{3,0,208},{3,0,208},{3,0,208},{1,16,0},{1,16,0},{1,16,0},{1,9,1},{0,8,45},{0,8,45},{6,33,408},{6,24,216},{6,18,317},{5,17,213},{3,32,723},{3,21,216},{3,17,2},{2,14,312},{0,18,888},{0,14,293},{8,29,200},{8,22,1},{9,17,26},{8,17,37},{19,0,723},{1,22,200},{3,17,2},{0,14,257},{38,0,723},
+{0,14,257},{6,25,209},{6,25,209},{6,25,209},{5,16,208},{3,25,162},{3,17,1},{3,17,1},{3,12,20},{0,15,228},{0,12,20},{8,21,1},{8,21,1},{8,21,1},{8,15,0},{15,1,162},{3,17,1},{3,17,1},{0,12,4},{31,0,162},{0,12,4},{22,1,200},{8,22,1},{10,17,2},{3,17,1},{22,1,200},{45,0,200},{3,17,1},{0,15,200},{45,0,200},{0,15,200},{5,0,208},
+{5,0,208},{5,0,208},{5,0,208},{3,18,0},{3,18,0},{3,18,0},{3,11,1},{0,11,13},{0,11,13},{8,35,408},{8,26,216},{8,20,317},{7,19,213},{5,34,723},{5,23,216},{5,19,2},{4,16,298},{0,22,804},{0,16,228},{10,31,200},{10,24,1},{11,19,26},{10,19,37},{22,0,723},{3,24,200},{5,19,2},{0,16,227},{44,0,723},{0,16,227},{8,27,209},{8,27,209},{8,27,209},
+{7,18,208},{5,27,162},{5,19,1},{5,19,1},{5,14,20},{0,18,180},{0,15,4},{10,23,1},{10,23,1},{10,23,1},{10,17,1},{15,7,162},{5,19,1},{5,19,1},{2,14,4},{31,3,162},{2,14,4},{25,1,200},{10,24,1},{12,19,2},{5,19,1},{25,1,200},{47,2,200},{5,19,1},{0,17,202},{47,2,200},{0,17,202},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{5,20,0},
+{5,20,0},{5,20,0},{5,13,1},{0,15,0},{0,15,0},{10,37,408},{10,28,216},{10,22,317},{9,21,213},{7,36,723},{7,25,216},{7,21,2},{6,18,298},{0,25,748},{1,19,218},{12,33,200},{12,26,1},{13,21,26},{12,21,37},{25,0,723},{5,26,200},{7,21,2},{0,19,211},{50,0,723},{0,19,211},{10,29,209},{10,29,209},{10,29,209},{9,20,208},{7,29,162},{7,21,1},{7,21,1},
+{7,16,17},{0,21,164},{3,16,3},{12,25,1},{12,25,1},{12,25,1},{12,19,1},{15,13,162},{7,21,1},{7,21,1},{4,16,1},{31,6,162},{4,16,1},{28,1,200},{12,26,1},{14,21,2},{7,21,1},{28,1,200},{47,5,200},{7,21,1},{0,19,202},{47,5,200},{0,19,202},{9,0,208},{9,0,208},{9,0,208},{9,0,208},{7,22,0},{7,22,0},{7,22,0},{7,15,1},{2,17,0},
+{2,17,0},{12,39,404},{12,30,212},{13,24,318},{12,23,215},{9,39,724},{9,27,212},{9,24,7},{8,20,306},{0,28,724},{3,21,210},{14,35,203},{14,28,2},{15,24,22},{14,23,30},{28,1,723},{7,28,203},{10,23,4},{0,21,201},{47,5,723},{0,21,201},{12,32,202},{12,32,202},{12,32,202},{12,22,202},{9,31,165},{9,24,3},{9,24,3},{9,18,14},{2,24,164},{4,19,6},{14,28,1},
+{14,28,1},{14,28,1},{14,21,1},{24,1,162},{10,23,0},{10,23,0},{6,18,5},{49,0,162},{6,18,5},{23,17,200},{14,28,1},{16,24,4},{10,23,4},{23,17,200},{63,0,200},{10,23,4},{0,21,200},{63,0,200},{0,21,200},{12,0,202},{12,0,202},{12,0,202},{12,0,202},{9,25,1},{9,25,1},{9,25,1},{9,17,2},{4,19,2},{4,19,2},{14,41,404},{14,32,215},{15,26,318},
+{14,25,215},{11,41,724},{11,29,212},{11,26,7},{10,22,306},{2,30,724},{5,23,210},{16,37,200},{16,30,1},{17,26,24},{16,25,40},{31,1,723},{9,30,203},{12,25,4},{2,23,201},{47,8,723},{2,23,201},{14,34,202},{14,34,202},{14,34,202},{14,24,202},{11,33,163},{11,26,3},{11,26,3},{11,20,14},{4,26,164},{6,21,6},{16,30,0},{16,30,0},{16,30,0},{16,23,0},{27,1,162},
+{12,25,0},{12,25,0},{8,20,5},{55,0,162},{8,20,5},{34,1,200},{16,30,1},{18,26,4},{12,25,4},{34,1,200},{63,3,200},{12,25,4},{0,23,200},{63,3,200},{0,23,200},{14,0,202},{14,0,202},{14,0,202},{14,0,202},{11,27,1},{11,27,1},{11,27,1},{11,19,2},{6,21,2},{6,21,2},{16,43,408},{16,34,216},{16,28,312},{16,27,221},{13,43,724},{13,31,212},{13,28,7},
+{12,24,306},{4,32,724},{7,25,210},{18,39,200},{18,32,1},{19,28,24},{17,27,36},{34,0,723},{11,32,201},{14,27,4},{4,25,201},{47,11,723},{4,25,201},{16,35,209},{16,35,209},{16,35,209},{16,26,208},{13,35,163},{13,28,3},{13,28,3},{13,22,14},{6,28,164},{8,23,6},{18,31,1},{18,31,1},{18,31,1},{18,25,0},{30,1,162},{14,27,0},{14,27,0},{10,22,5},{61,0,162},
+{10,22,5},{37,1,200},{18,32,1},{20,28,4},{14,27,4},{37,1,200},{63,6,200},{14,27,4},{0,25,200},{63,6,200},{0,25,200},{16,0,208},{16,0,208},{16,0,208},{16,0,208},{13,29,1},{13,29,1},{13,29,1},{13,21,2},{8,23,2},{8,23,2},{18,45,408},{18,36,216},{18,30,312},{17,29,216},{15,45,724},{15,33,210},{15,30,7},{14,26,306},{6,34,724},{9,27,210},{20,41,200},
+{20,34,1},{21,30,24},{19,29,36},{37,0,723},{13,34,201},{16,29,5},{6,27,201},{47,14,723},{6,27,201},{18,37,209},{18,37,209},{18,37,209},{18,28,208},{15,37,163},{15,30,3},{15,30,3},{15,24,14},{8,30,164},{10,25,6},{20,33,1},{20,33,1},{20,33,1},{20,27,0},{33,1,162},{16,29,1},{16,29,1},{12,24,5},{63,2,162},{12,24,5},{40,1,200},{20,34,1},{22,30,4},
+{16,29,4},{40,1,200},{63,9,200},{16,29,4},{0,27,200},{63,9,200},{0,27,200},{17,0,208},{17,0,208},{17,0,208},{17,0,208},{15,31,1},{15,31,1},{15,31,1},{15,23,2},{10,25,2},{10,25,2},{20,47,404},{20,38,212},{21,32,318},{20,31,215},{17,47,724},{17,35,212},{17,32,7},{16,29,308},{8,36,724},{11,29,210},{22,44,201},{22,36,2},{23,32,22},{22,31,35},{40,1,723},
+{15,36,206},{17,32,6},{9,29,202},{63,9,723},{9,29,202},{20,40,202},{20,40,202},{20,40,202},{20,30,203},{17,39,165},{17,32,3},{17,32,3},{17,26,19},{10,32,164},{13,27,2},{22,36,1},{22,36,1},{22,36,1},{22,29,2},{31,12,162},{18,31,1},{18,31,1},{13,27,1},{62,6,162},{13,27,1},{44,0,200},{22,36,1},{24,32,4},{16,32,4},{44,0,200},{62,13,200},{16,32,4},
+{0,29,202},{62,13,200},{0,29,202},{20,0,202},{20,0,202},{20,0,202},{20,0,202},{17,33,1},{17,33,1},{17,33,1},{17,25,1},{13,27,1},{13,27,1},{22,49,404},{22,40,212},{23,34,318},{22,33,215},{19,49,724},{19,37,212},{19,34,7},{18,31,308},{10,38,724},{13,31,210},{24,46,201},{24,38,2},{25,34,22},{24,33,30},{43,1,723},{17,38,203},{20,33,4},{11,31,202},{63,12,723},
+{11,31,202},{22,42,202},{22,42,202},{22,42,202},{22,32,202},{19,41,165},{19,34,3},{19,34,3},{19,28,19},{12,34,164},{15,29,2},{24,38,1},{24,38,1},{24,38,1},{24,31,2},{31,18,162},{20,33,0},{20,33,0},{15,29,1},{62,9,162},{15,29,1},{47,0,200},{24,38,1},{26,34,4},{20,33,4},{47,0,200},{46,24,200},{20,33,4},{0,31,202},{46,24,200},{0,31,202},{22,0,202},
+{22,0,202},{22,0,202},{22,0,202},{19,35,1},{19,35,1},{19,35,1},{19,27,1},{15,29,1},{15,29,1},{24,51,404},{24,42,212},{25,36,318},{24,35,215},{21,51,724},{21,39,212},{21,36,7},{20,32,306},{12,40,724},{15,33,213},{26,47,203},{26,40,2},{27,36,22},{26,35,30},{46,1,723},{19,40,203},{22,35,4},{13,33,200},{63,15,723},{13,33,200},{24,44,202},{24,44,202},{24,44,202},
+{24,34,202},{21,43,165},{21,36,3},{21,36,3},{21,30,19},{14,36,164},{17,31,2},{26,40,1},{26,40,1},{26,40,1},{26,33,1},{34,17,162},{22,35,0},{22,35,0},{17,31,1},{62,12,162},{17,31,1},{49,1,200},{26,40,1},{28,36,4},{22,35,4},{49,1,200},{46,27,200},{22,35,4},{0,33,200},{46,27,200},{0,33,200},{24,0,202},{24,0,202},{24,0,202},{24,0,202},{21,37,1},
+{21,37,1},{21,37,1},{21,29,1},{17,31,1},{17,31,1},{26,53,404},{26,44,212},{27,38,318},{26,37,215},{23,53,724},{23,41,212},{23,38,7},{22,34,306},{14,42,724},{17,35,210},{28,49,203},{28,42,2},{29,38,22},{28,37,30},{47,5,723},{21,42,203},{24,37,4},{15,35,200},{63,18,723},{15,35,200},{26,46,202},{26,46,202},{26,46,202},{26,36,202},{23,45,165},{23,38,3},{23,38,3},
+{23,32,14},{16,38,164},{18,33,6},{28,42,1},{28,42,1},{28,42,1},{28,35,1},{37,17,162},{24,37,0},{24,37,0},{20,32,5},{62,15,162},{20,32,5},{52,1,200},{28,42,1},{30,38,4},{24,37,4},{52,1,200},{46,30,200},{24,37,4},{0,35,200},{46,30,200},{0,35,200},{26,0,202},{26,0,202},{26,0,202},{26,0,202},{23,39,1},{23,39,1},{23,39,1},{23,31,1},{18,33,2},
+{18,33,2},{28,56,400},{28,46,216},{29,40,314},{28,39,213},{26,53,728},{25,44,215},{25,40,9},{25,37,306},{17,44,728},{19,37,210},{31,50,204},{30,45,4},{31,40,21},{30,39,29},{52,1,723},{24,44,201},{25,40,5},{17,37,202},{46,30,723},{17,37,202},{28,49,200},{28,49,200},{28,49,200},{28,38,201},{26,46,166},{26,39,6},{26,39,6},{25,34,17},{18,40,163},{21,35,2},{31,43,4},
+{31,43,4},{31,43,4},{31,37,4},{49,0,162},{26,39,2},{26,39,2},{21,35,1},{62,18,162},{21,35,1},{56,0,200},{30,45,0},{32,40,2},{25,40,1},{56,0,200},{62,25,200},{25,40,1},{0,37,202},{62,25,200},{0,37,202},{28,0,200},{28,0,200},{28,0,200},{28,0,200},{26,39,5},{26,39,5},{26,39,5},{25,33,4},{21,35,1},{21,35,1},{30,58,400},{30,48,217},{31,42,314},
+{30,41,213},{28,55,728},{27,46,215},{27,42,9},{27,39,306},{19,46,728},{21,39,210},{32,54,201},{32,47,3},{33,42,19},{32,41,35},{55,1,723},{26,46,201},{27,42,5},{19,39,202},{47,32,723},{19,39,202},{30,51,200},{30,51,200},{30,51,200},{30,40,201},{28,48,166},{28,41,6},{28,41,6},{27,36,17},{20,42,163},{23,37,2},{32,46,2},{32,46,2},{32,46,2},{32,39,2},{52,0,162},
+{28,41,2},{28,41,2},{23,37,1},{62,21,162},{23,37,1},{59,0,200},{32,47,2},{34,42,2},{27,42,1},{59,0,200},{62,28,200},{27,42,1},{0,39,202},{62,28,200},{0,39,202},{30,0,200},{30,0,200},{30,0,200},{30,0,200},{28,41,5},{28,41,5},{28,41,5},{27,35,4},{23,37,1},{23,37,1},{32,60,402},{32,50,212},{32,44,324},{32,43,215},{30,57,728},{29,47,216},{29,44,9},
+{29,41,306},{20,48,724},{23,41,210},{34,56,201},{34,48,2},{35,44,19},{34,43,35},{58,1,723},{28,48,201},{29,44,5},{21,41,202},{53,32,723},{21,41,202},{32,52,202},{32,52,202},{32,52,202},{32,42,203},{30,50,166},{30,43,6},{30,43,6},{29,38,17},{22,44,163},{25,39,2},{34,48,1},{34,48,1},{34,48,1},{34,41,2},{55,0,162},{30,43,2},{30,43,2},{25,39,1},{62,24,162},
+{25,39,1},{62,0,200},{34,48,1},{36,44,2},{29,44,1},{62,0,200},{62,31,200},{29,44,1},{0,41,202},{62,31,200},{0,41,202},{32,0,202},{32,0,202},{32,0,202},{32,0,202},{30,43,5},{30,43,5},{30,43,5},{29,37,4},{25,39,1},{25,39,1},{34,62,402},{34,52,212},{34,46,324},{34,45,215},{31,61,728},{31,49,210},{31,46,9},{31,43,306},{22,50,724},{25,43,210},{36,58,201},
+{36,50,2},{37,46,19},{36,45,35},{61,1,723},{30,50,201},{31,46,5},{23,43,202},{59,32,723},{23,43,202},{34,54,202},{34,54,202},{34,54,202},{34,44,203},{31,54,166},{31,46,8},{31,46,8},{31,40,17},{24,46,163},{27,41,2},{36,50,1},{36,50,1},{36,50,1},{36,43,2},{58,0,162},{32,45,1},{32,45,1},{27,41,1},{62,27,162},{27,41,1},{63,4,200},{36,50,1},{38,46,2},
+{31,46,1},{63,4,200},{62,34,200},{31,46,1},{0,43,202},{62,34,200},{0,43,202},{34,0,202},{34,0,202},{34,0,202},{34,0,202},{31,47,5},{31,47,5},{31,47,5},{31,39,4},{27,41,1},{27,41,1},{36,63,408},{36,54,216},{37,48,314},{36,47,217},{34,62,727},{33,52,215},{33,48,9},{32,45,308},{24,53,723},{28,45,217},{39,58,206},{38,53,4},{39,48,21},{38,47,36},{63,4,723},
+{32,52,201},{33,48,5},{26,45,208},{62,34,723},{26,45,208},{36,57,200},{36,57,200},{36,57,200},{36,47,201},{34,54,166},{33,48,8},{33,48,8},{33,43,20},{26,48,163},{29,43,1},{39,51,4},{39,51,4},{39,51,4},{39,45,4},{53,16,162},{35,47,4},{35,47,4},{30,43,0},{63,30,162},{30,43,0},{63,11,200},{38,53,0},{40,48,2},{33,48,1},{63,11,200},{47,45,200},{33,48,1},
+{0,45,208},{47,45,200},{0,45,208},{36,0,200},{36,0,200},{36,0,200},{36,0,200},{34,47,5},{34,47,5},{34,47,5},{34,41,4},{29,43,1},{29,43,1},{39,63,440},{38,56,216},{39,50,314},{38,49,213},{36,63,728},{35,54,215},{35,50,9},{34,47,308},{26,55,723},{30,47,217},{41,60,206},{40,55,4},{41,50,21},{40,49,29},{63,10,723},{34,54,201},{35,50,5},{28,47,208},{62,37,723},
+{28,47,208},{38,59,200},{38,59,200},{38,59,200},{38,48,201},{36,56,166},{36,49,6},{36,49,6},{35,45,20},{28,50,163},{31,45,1},{41,53,4},{41,53,4},{41,53,4},{41,47,4},{56,16,162},{36,49,2},{36,49,2},{32,45,0},{62,33,162},{32,45,0},{55,32,200},{40,55,0},{42,50,2},{35,50,1},{55,32,200},{46,48,200},{35,50,1},{0,47,208},{46,48,200},{0,47,208},{38,0,200},
+{38,0,200},{38,0,200},{38,0,200},{36,49,5},{36,49,5},{36,49,5},{36,43,4},{31,45,1},{31,45,1},{41,63,482},{40,58,216},{41,52,314},{40,51,213},{39,63,760},{37,56,215},{37,52,9},{37,49,306},{28,57,723},{31,49,215},{43,62,206},{42,57,4},{43,52,21},{42,51,29},{63,16,723},{36,56,201},{37,52,5},{29,49,203},{62,40,723},{29,49,203},{40,61,200},{40,61,200},{40,61,200},
+{40,50,201},{38,58,166},{38,51,6},{38,51,6},{37,47,20},{30,52,163},{33,47,1},{43,55,4},{43,55,4},{43,55,4},{43,49,4},{59,16,162},{38,51,2},{38,51,2},{34,47,0},{62,36,162},{34,47,0},{58,32,200},{42,57,0},{44,52,2},{37,52,1},{58,32,200},{52,48,200},{37,52,1},{0,49,202},{52,48,200},{0,49,202},{40,0,200},{40,0,200},{40,0,200},{40,0,200},{38,51,5},
+{38,51,5},{38,51,5},{38,45,4},{33,47,1},{33,47,1},{43,63,530},{42,60,216},{43,54,314},{42,53,213},{41,63,799},{39,58,215},{39,54,9},{39,51,306},{30,59,723},{33,51,210},{45,63,212},{44,59,4},{45,54,21},{44,53,29},{63,22,723},{38,58,201},{39,54,5},{31,51,203},{62,43,723},{31,51,203},{42,63,200},{42,63,200},{42,63,200},{42,52,201},{40,60,166},{40,53,6},{40,53,6},
+{39,48,17},{32,54,163},{35,49,2},{45,57,4},{45,57,4},{45,57,4},{45,51,4},{62,16,162},{40,53,2},{40,53,2},{35,49,1},{62,39,162},{35,49,1},{61,32,200},{44,59,0},{46,54,2},{39,54,1},{61,32,200},{58,48,200},{39,54,1},{0,51,202},{58,48,200},{0,51,202},{42,0,200},{42,0,200},{42,0,200},{42,0,200},{40,53,5},{40,53,5},{40,53,5},{40,47,4},{35,49,1},
+{35,49,1},{46,63,626},{44,63,222},{45,57,315},{44,56,211},{44,63,869},{41,60,213},{42,56,2},{41,53,298},{32,61,723},{36,53,217},{48,63,244},{47,60,5},{47,56,26},{46,55,34},{61,32,723},{40,60,202},{42,56,1},{34,53,208},{58,48,723},{34,53,208},{44,63,218},{44,63,218},{44,63,218},{44,55,203},{42,63,163},{42,56,2},{42,56,2},{41,51,25},{35,56,163},{37,51,1},{47,60,1},
+{47,60,1},{47,60,1},{47,53,2},{63,21,162},{42,56,1},{42,56,1},{38,51,0},{63,42,162},{38,51,0},{63,35,200},{46,61,2},{49,56,1},{41,56,1},{63,35,200},{63,49,200},{41,56,1},{0,53,208},{63,49,200},{0,53,208},{44,0,202},{44,0,202},{44,0,202},{44,0,202},{42,56,1},{42,56,1},{42,56,1},{42,49,1},{37,51,1},{37,51,1},{48,63,728},{47,63,238},{47,59,315},
+{46,58,211},{46,63,937},{43,62,213},{44,58,2},{43,55,298},{34,63,723},{38,55,217},{50,63,286},{48,63,4},{49,58,20},{48,57,36},{63,34,723},{42,62,202},{44,58,1},{36,55,208},{62,49,723},{36,55,208},{47,63,234},{47,63,234},{47,63,234},{46,57,203},{44,63,181},{44,58,2},{44,58,2},{43,53,25},{37,58,163},{39,53,1},{49,61,4},{49,61,4},{49,61,4},{49,55,4},{63,27,162},
+{44,58,1},{44,58,1},{40,53,0},{63,45,162},{40,53,0},{63,41,200},{48,63,0},{51,58,1},{43,58,1},{63,41,200},{63,52,200},{43,58,1},{0,55,208},{63,52,200},{0,55,208},{46,0,202},{46,0,202},{46,0,202},{46,0,202},{44,58,1},{44,58,1},{44,58,1},{44,51,1},{39,53,1},{39,53,1},{50,63,866},{49,63,317},{49,61,312},{48,60,216},{48,63,1048},{46,63,219},{46,60,2},
+{45,57,298},{38,63,748},{40,57,217},{53,63,350},{51,63,20},{51,60,20},{50,59,36},{63,40,723},{46,63,218},{46,60,1},{38,57,208},{62,52,723},{38,57,208},{48,63,264},{48,63,264},{48,63,264},{48,59,201},{47,63,205},{46,60,2},{46,60,2},{45,55,25},{39,60,163},{41,55,1},{51,63,4},{51,63,4},{51,63,4},{51,57,4},{63,33,162},{46,60,1},{46,60,1},{42,55,0},{47,56,162},
+{42,55,0},{63,47,200},{52,63,13},{53,60,1},{45,60,1},{63,47,200},{63,55,200},{45,60,1},{0,57,208},{63,55,200},{0,57,208},{48,0,200},{48,0,200},{48,0,200},{48,0,200},{46,60,1},{46,60,1},{46,60,1},{46,53,1},{41,55,1},{41,55,1},{53,63,1026},{51,63,440},{51,63,312},{50,62,216},{51,63,1144},{48,63,280},{48,62,5},{47,59,298},{43,63,827},{42,59,217},{55,63,428},
+{54,63,100},{53,62,20},{52,61,36},{63,46,723},{49,63,266},{48,62,1},{40,59,208},{62,55,723},{40,59,208},{51,63,296},{51,63,296},{51,63,296},{50,61,201},{49,63,248},{48,62,5},{48,62,5},{47,57,25},{41,62,163},{43,57,1},{53,63,13},{53,63,13},{53,63,13},{53,59,4},{63,39,162},{48,62,1},{48,62,1},{44,57,0},{47,59,162},{44,57,0},{63,53,200},{55,63,53},{55,62,1},
+{47,62,1},{63,53,200},{63,58,200},{47,62,1},{0,59,208},{63,58,200},{0,59,208},{50,0,200},{50,0,200},{50,0,200},{50,0,200},{48,62,4},{48,62,4},{48,62,4},{48,55,4},{43,57,1},{43,57,1},{54,63,955},{54,63,523},{53,63,362},{52,63,202},{54,63,1027},{51,63,283},{50,63,14},{49,60,198},{47,63,735},{44,61,118},{57,63,338},{56,63,141},{56,63,41},{55,63,17},{63,51,546},
+{53,63,233},{51,63,2},{43,61,113},{63,57,546},{43,61,113},{53,63,362},{53,63,362},{53,63,362},{52,63,202},{51,63,315},{50,63,14},{50,63,14},{49,59,19},{44,63,171},{46,59,3},{56,63,41},{56,63,41},{56,63,41},{55,61,2},{61,49,162},{51,63,2},{51,63,2},{47,59,1},{63,54,162},{47,59,1},{63,57,113},{58,63,50},{57,63,1},{52,63,0},{63,57,113},{63,60,113},{52,63,0},
+{0,61,113},{63,60,113},{0,61,113},{52,0,202},{52,0,202},{52,0,202},{52,0,202},{50,63,5},{50,63,5},{50,63,5},{50,57,2},{45,60,0},{45,60,0},{57,63,779},{56,63,542},{56,63,442},{54,63,227},{56,63,830},{54,63,251},{53,63,78},{51,62,70},{51,63,587},{47,62,25},{59,63,218},{58,63,123},{58,63,74},{57,63,2},{63,55,333},{56,63,145},{55,63,25},{47,62,25},{63,59,333},
+{47,62,25},{56,63,442},{56,63,442},{56,63,442},{54,63,227},{54,63,371},{53,63,78},{53,63,78},{51,61,19},{48,63,219},{47,61,6},{58,63,74},{58,63,74},{58,63,74},{57,63,2},{63,51,162},{55,63,25},{55,63,25},{48,61,2},{63,57,162},{48,61,2},{63,60,25},{61,63,10},{60,63,1},{58,63,0},{63,60,25},{62,62,25},{58,63,0},{0,62,25},{62,62,25},{0,62,25},{54,0,202},
+{54,0,202},{54,0,202},{54,0,202},{52,63,26},{52,63,26},{52,63,26},{52,59,2},{47,62,0},{47,62,0},{59,63,684},{57,63,538},{57,63,474},{57,63,282},{57,63,682},{56,63,285},{55,63,171},{53,63,18},{54,63,482},{49,63,5},{60,63,153},{60,63,105},{60,63,89},{59,63,37},{63,59,193},{58,63,107},{58,63,58},{50,63,1},{63,61,193},{50,63,1},{57,63,474},{57,63,474},{57,63,474},
+{57,63,282},{57,63,426},{55,63,171},{55,63,171},{53,63,18},{52,63,278},{49,63,5},{60,63,89},{60,63,89},{60,63,89},{59,63,37},{63,57,145},{58,63,58},{58,63,58},{50,63,1},{63,60,145},{50,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{56,0,202},{56,0,202},{56,0,202},{56,0,202},{54,63,50},
+{54,63,50},{54,63,50},{54,61,2},{49,63,5},{49,63,5},{60,63,426},{59,63,375},{59,63,339},{58,63,251},{59,63,415},{57,63,202},{57,63,138},{56,63,2},{55,63,295},{53,63,29},{62,63,43},{62,63,38},{62,63,34},{61,63,10},{63,61,54},{61,63,27},{60,63,17},{56,63,1},{63,62,54},{56,63,1},{59,63,339},{59,63,339},{59,63,339},{58,63,251},{59,63,294},{57,63,138},{57,63,138},
+{56,63,2},{55,63,174},{53,63,29},{62,63,34},{62,63,34},{62,63,34},{61,63,10},{63,60,41},{60,63,17},{60,63,17},{56,63,1},{62,62,41},{56,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{58,0,202},{58,0,202},{58,0,202},{58,0,202},{57,63,74},{57,63,74},{57,63,74},{56,63,2},{53,63,29},
+{53,63,29},{0,20,421},{0,14,50},{0,10,4},{0,9,157},{0,14,925},{0,9,589},{0,8,264},{0,6,701},{0,6,1005},{0,5,738},{0,20,421},{0,14,50},{0,10,4},{0,9,157},{7,0,925},{0,9,589},{0,8,264},{0,6,701},{14,0,925},{0,6,701},{0,10,0},{0,10,0},{0,10,0},{0,5,0},{0,5,85},{0,4,34},{0,4,34},{0,2,50},{0,2,93},{0,2,54},{0,10,0},
+{0,10,0},{0,10,0},{0,5,0},{2,1,85},{0,4,34},{0,4,34},{0,2,50},{5,0,85},{0,2,50},{10,1,421},{0,14,50},{0,10,4},{0,9,157},{10,1,421},{20,0,421},{0,9,157},{0,7,421},{20,0,421},{0,7,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,26,421},{0,18,13},{0,13,20},
+{0,11,100},{0,18,1261},{0,11,701},{0,10,294},{0,7,857},{0,8,1382},{0,7,938},{0,26,421},{0,18,13},{0,13,20},{0,11,100},{9,0,1261},{0,11,701},{0,10,294},{0,7,857},{18,0,1261},{0,7,857},{0,16,0},{0,16,0},{0,16,0},{0,8,0},{0,8,221},{0,6,89},{0,6,89},{0,4,125},{0,4,246},{0,4,150},{0,16,0},{0,16,0},{0,16,0},{0,8,0},{4,0,221},
+{0,6,89},{0,6,89},{0,4,125},{8,0,221},{0,4,125},{13,1,421},{0,18,13},{2,12,4},{0,11,100},{13,1,421},{26,0,421},{0,11,100},{0,9,421},{26,0,421},{0,9,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,32,430},{0,22,10},{1,15,70},{0,13,70},{0,22,1517},{0,14,730},{0,13,257},
+{0,9,974},{0,11,1713},{0,8,1109},{1,30,422},{1,21,5},{2,15,45},{0,13,70},{11,1,1514},{0,14,730},{0,13,257},{0,9,974},{15,4,1514},{0,9,974},{0,22,9},{0,22,9},{0,22,9},{0,11,9},{0,12,338},{0,9,106},{0,9,106},{0,5,181},{0,5,392},{0,5,217},{1,20,1},{1,20,1},{1,20,1},{1,10,2},{6,0,338},{0,9,106},{0,9,106},{0,5,181},{12,0,338},
+{0,5,181},{16,0,421},{0,22,1},{4,14,4},{0,13,61},{16,0,421},{32,0,421},{0,13,61},{0,11,421},{32,0,421},{0,11,421},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,2},{0,1,2},{1,36,486},{1,24,69},{2,17,163},{1,16,115},{0,28,1517},{0,18,614},{0,15,126},{0,11,857},{0,14,1841},{0,11,1053},{3,32,422},
+{3,23,5},{3,17,46},{2,15,70},{14,1,1514},{0,18,614},{0,15,126},{0,11,857},{15,7,1514},{0,11,857},{1,26,65},{1,26,65},{1,26,65},{1,13,66},{0,18,338},{0,13,45},{0,13,45},{0,8,125},{0,8,456},{0,7,211},{3,22,1},{3,22,1},{3,22,1},{3,12,2},{9,0,338},{0,13,45},{0,13,45},{0,8,125},{18,0,338},{0,8,125},{19,0,421},{2,24,1},{6,16,1},
+{0,16,37},{19,0,421},{38,0,421},{0,16,37},{0,13,421},{38,0,421},{0,13,421},{1,0,65},{1,0,65},{1,0,65},{1,0,65},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{0,3,25},{0,3,25},{3,39,629},{3,27,213},{3,20,365},{2,18,237},{0,35,1514},{0,22,506},{0,18,24},{0,14,750},{0,16,2003},{0,13,1050},{5,35,421},{5,25,2},{6,19,45},{5,17,72},{17,1,1514},
+{0,22,506},{0,18,24},{0,14,750},{35,0,1514},{0,14,750},{3,28,209},{3,28,209},{3,28,209},{2,16,208},{0,25,338},{0,17,9},{0,17,9},{0,10,72},{0,11,566},{0,10,241},{5,24,1},{5,24,1},{5,24,1},{5,15,0},{12,1,338},{0,17,9},{0,17,9},{0,10,72},{25,0,338},{0,10,72},{22,1,421},{4,26,1},{8,18,5},{0,18,8},{22,1,421},{45,0,421},{0,18,8},
+{0,15,421},{45,0,421},{0,15,421},{2,0,208},{2,0,208},{2,0,208},{2,0,208},{0,15,0},{0,15,0},{0,15,0},{0,8,1},{0,6,80},{0,6,80},{4,43,821},{4,30,418},{5,22,621},{3,20,420},{0,41,1514},{0,25,450},{0,20,5},{0,16,670},{0,19,2187},{0,15,1109},{7,37,421},{7,27,2},{8,21,45},{7,19,72},{20,1,1514},{0,25,450},{0,20,5},{0,16,670},{41,0,1514},
+{0,16,670},{4,32,400},{4,32,400},{4,32,400},{4,18,400},{0,31,338},{0,20,1},{0,20,1},{0,13,40},{0,14,694},{0,11,297},{7,26,1},{7,26,1},{7,26,1},{7,17,1},{15,1,338},{0,20,1},{0,20,1},{0,13,40},{31,0,338},{0,13,40},{25,1,421},{6,28,1},{10,20,5},{0,20,4},{25,1,421},{51,0,421},{0,20,4},{0,17,421},{51,0,421},{0,17,421},{3,0,400},
+{3,0,400},{3,0,400},{3,0,400},{0,21,0},{0,21,0},{0,21,0},{0,11,1},{0,8,149},{0,8,149},{5,47,846},{6,32,451},{6,23,662},{5,22,445},{2,43,1515},{1,28,446},{2,22,6},{0,18,638},{0,22,2046},{0,18,878},{9,39,421},{9,29,2},{10,23,45},{9,21,72},{23,1,1514},{0,28,426},{2,22,5},{0,18,589},{47,0,1514},{0,18,589},{5,36,425},{5,36,425},{5,36,425},
+{5,21,426},{2,32,341},{2,22,2},{2,22,2},{1,15,38},{0,16,606},{0,14,158},{9,28,1},{9,28,1},{9,28,1},{9,19,1},{15,7,338},{2,22,1},{2,22,1},{0,15,20},{31,3,338},{0,15,20},{28,1,421},{8,30,1},{12,22,5},{2,22,4},{28,1,421},{57,0,421},{2,22,4},{0,19,421},{57,0,421},{0,19,421},{5,0,425},{5,0,425},{5,0,425},{5,0,425},{2,23,1},
+{2,23,1},{2,23,1},{2,13,2},{0,12,97},{0,12,97},{7,49,846},{8,33,450},{8,25,662},{7,24,445},{4,45,1515},{3,30,446},{4,24,6},{2,20,638},{0,25,1886},{0,19,682},{11,41,421},{11,31,2},{12,25,45},{11,23,72},{26,1,1514},{1,31,421},{4,24,5},{0,20,545},{53,0,1514},{0,20,545},{7,38,425},{7,38,425},{7,38,425},{7,23,426},{4,34,341},{4,24,2},{4,24,2},
+{4,16,42},{0,20,500},{0,16,62},{11,30,1},{11,30,1},{11,30,1},{11,21,1},{15,13,338},{4,24,1},{4,24,1},{0,17,5},{31,6,338},{0,17,5},{31,1,421},{10,32,1},{14,24,5},{4,24,4},{31,1,421},{63,0,421},{4,24,4},{0,21,421},{63,0,421},{0,21,421},{7,0,425},{7,0,425},{7,0,425},{7,0,425},{4,25,1},{4,25,1},{4,25,1},{4,15,2},{0,16,37},
+{0,16,37},{10,49,846},{10,36,445},{11,28,650},{10,26,450},{6,47,1517},{5,32,446},{6,27,3},{4,22,646},{0,29,1751},{0,22,522},{13,44,422},{13,34,3},{14,27,46},{13,26,74},{30,0,1514},{3,33,422},{6,27,3},{0,22,497},{46,7,1514},{0,22,497},{10,39,425},{10,39,425},{10,39,425},{10,24,426},{6,37,338},{6,27,2},{6,27,2},{6,19,40},{0,24,410},{0,19,9},{13,33,1},
+{13,33,1},{13,33,1},{13,23,1},{24,1,338},{7,26,0},{7,26,0},{1,19,5},{49,0,338},{1,19,5},{35,0,421},{12,34,1},{16,27,1},{5,27,1},{35,0,421},{63,3,421},{5,27,1},{0,23,421},{63,3,421},{0,23,421},{10,0,425},{10,0,425},{10,0,425},{10,0,425},{6,28,0},{6,28,0},{6,28,0},{6,17,1},{0,19,5},{0,19,5},{12,51,846},{12,38,445},{13,30,650},
+{12,28,450},{8,49,1517},{7,34,446},{8,29,3},{6,24,646},{0,32,1647},{0,25,458},{15,46,422},{15,36,3},{16,29,42},{15,28,74},{32,1,1514},{5,35,422},{8,29,3},{0,25,457},{46,10,1514},{0,25,457},{12,41,425},{12,41,425},{12,41,425},{12,26,426},{8,39,338},{8,29,2},{8,29,2},{8,21,40},{0,27,362},{1,22,5},{15,35,1},{15,35,1},{15,35,1},{15,25,1},{27,1,338},
+{9,28,0},{9,28,0},{3,21,5},{55,0,338},{3,21,5},{38,0,421},{14,36,1},{18,29,1},{7,29,1},{38,0,421},{63,6,421},{7,29,1},{0,25,421},{63,6,421},{0,25,421},{12,0,425},{12,0,425},{12,0,425},{12,0,425},{8,30,0},{8,30,0},{8,30,0},{8,19,1},{1,22,1},{1,22,1},{14,53,846},{14,40,445},{15,32,661},{14,30,450},{10,51,1517},{9,36,446},{10,31,3},
+{8,26,646},{0,35,1575},{0,27,446},{17,47,421},{17,37,2},{18,31,42},{17,30,73},{35,1,1514},{7,37,422},{10,31,3},{0,27,430},{46,13,1514},{0,27,430},{14,43,425},{14,43,425},{14,43,425},{14,28,426},{10,41,338},{10,31,2},{10,31,2},{10,23,40},{0,31,341},{3,24,5},{17,36,1},{17,36,1},{17,36,1},{17,27,0},{30,1,338},{11,30,0},{11,30,0},{5,23,5},{61,0,338},
+{5,23,5},{41,0,421},{16,38,1},{20,31,1},{9,31,1},{41,0,421},{63,9,421},{9,31,1},{0,27,421},{63,9,421},{0,27,421},{14,0,425},{14,0,425},{14,0,425},{14,0,425},{10,31,1},{10,31,1},{10,31,1},{10,21,1},{3,24,1},{3,24,1},{16,55,854},{16,42,451},{16,33,662},{15,32,446},{12,53,1517},{11,38,446},{12,32,9},{10,28,646},{0,39,1533},{2,29,446},{19,49,421},
+{19,39,2},{20,33,45},{18,31,81},{38,1,1514},{9,39,422},{13,32,6},{0,29,422},{45,16,1514},{0,29,422},{15,47,433},{15,47,433},{15,47,433},{15,31,433},{12,43,338},{12,32,5},{12,32,5},{12,25,40},{1,33,339},{5,26,5},{19,38,1},{19,38,1},{19,38,1},{19,29,0},{33,1,338},{13,32,2},{13,32,2},{7,25,5},{63,2,338},{7,25,5},{44,0,421},{18,40,1},{22,32,5},
+{12,32,5},{44,0,421},{63,12,421},{12,32,5},{0,29,421},{63,12,421},{0,29,421},{15,0,433},{15,0,433},{15,0,433},{15,0,433},{12,33,1},{12,33,1},{12,33,1},{12,23,1},{5,26,1},{5,26,1},{18,58,846},{18,44,445},{19,36,650},{18,34,450},{14,56,1515},{14,40,447},{14,35,7},{13,31,646},{0,42,1515},{5,31,445},{21,52,422},{21,42,2},{22,35,46},{21,34,74},{42,0,1514},
+{12,41,422},{14,35,6},{2,31,425},{62,11,1514},{2,31,425},{18,47,425},{18,47,425},{18,47,425},{18,32,426},{14,46,339},{14,35,6},{14,35,6},{14,27,35},{4,35,341},{8,28,5},{21,41,1},{21,41,1},{21,41,1},{21,31,2},{31,12,338},{15,34,0},{15,34,0},{8,28,1},{62,6,338},{8,28,1},{47,0,421},{21,42,1},{24,35,1},{13,35,1},{47,0,421},{62,16,421},{13,35,1},
+{0,31,425},{62,16,421},{0,31,425},{18,0,425},{18,0,425},{18,0,425},{18,0,425},{14,36,1},{14,36,1},{14,36,1},{14,25,1},{7,29,1},{7,29,1},{20,60,846},{20,46,445},{21,38,650},{20,36,450},{16,58,1514},{16,41,449},{16,37,3},{15,32,630},{2,44,1515},{7,33,441},{23,54,422},{23,44,2},{24,37,46},{23,36,74},{45,0,1514},{14,43,422},{16,37,3},{4,33,421},{62,14,1514},
+{4,33,421},{20,49,425},{20,49,425},{20,49,425},{20,34,426},{16,47,340},{16,37,2},{16,37,2},{16,29,34},{6,37,341},{10,30,5},{23,43,1},{23,43,1},{23,43,1},{23,33,1},{31,18,338},{17,36,0},{17,36,0},{10,30,1},{62,9,338},{10,30,1},{50,0,421},{23,44,1},{26,37,1},{15,37,1},{50,0,421},{62,19,421},{15,37,1},{0,33,421},{62,19,421},{0,33,421},{20,0,425},
+{20,0,425},{20,0,425},{20,0,425},{16,38,0},{16,38,0},{16,38,0},{16,27,0},{9,31,1},{9,31,1},{22,62,846},{22,48,445},{23,40,650},{22,38,450},{18,60,1514},{18,43,449},{18,39,3},{16,34,646},{4,46,1515},{9,35,441},{25,56,422},{25,46,2},{26,39,46},{25,38,74},{47,2,1514},{16,45,425},{18,39,3},{6,35,421},{62,17,1514},{6,35,421},{22,51,425},{22,51,425},{22,51,425},
+{22,36,426},{18,49,338},{18,39,2},{18,39,2},{18,31,34},{8,39,341},{11,32,6},{25,45,1},{25,45,1},{25,45,1},{25,35,1},{34,17,338},{19,38,0},{19,38,0},{12,32,4},{62,12,338},{12,32,4},{53,0,421},{25,46,1},{28,39,1},{17,39,1},{53,0,421},{62,22,421},{17,39,1},{0,35,421},{62,22,421},{0,35,421},{22,0,425},{22,0,425},{22,0,425},{22,0,425},{18,40,0},
+{18,40,0},{18,40,0},{18,29,0},{11,32,2},{11,32,2},{24,63,850},{24,50,445},{25,42,650},{24,40,450},{20,62,1514},{20,45,449},{20,41,3},{18,36,646},{6,48,1517},{11,37,441},{27,58,422},{27,48,3},{28,41,46},{27,40,74},{47,8,1514},{18,47,425},{20,41,3},{8,37,421},{62,20,1514},{8,37,421},{24,53,425},{24,53,425},{24,53,425},{24,38,426},{20,51,338},{20,41,2},{20,41,2},
+{20,33,40},{10,41,341},{13,34,6},{27,47,1},{27,47,1},{27,47,1},{27,37,1},{37,17,338},{21,40,0},{21,40,0},{14,34,4},{62,15,338},{14,34,4},{56,0,421},{26,48,1},{30,41,1},{19,41,1},{56,0,421},{62,25,421},{19,41,1},{0,37,421},{62,25,421},{0,37,421},{24,0,425},{24,0,425},{24,0,425},{24,0,425},{20,42,0},{20,42,0},{20,42,0},{20,31,0},{13,34,2},
+{13,34,2},{26,63,882},{26,52,447},{27,44,646},{26,42,446},{23,62,1526},{22,48,447},{22,43,5},{21,39,646},{8,50,1515},{13,39,443},{30,58,425},{29,50,4},{30,44,45},{29,42,69},{54,0,1514},{20,49,422},{22,43,4},{10,39,426},{47,31,1514},{10,39,426},{26,56,421},{26,56,421},{26,56,421},{26,41,421},{22,54,339},{22,43,5},{22,43,5},{22,35,35},{12,43,338},{16,36,5},{30,48,4},
+{30,48,4},{30,48,4},{30,39,4},{49,0,338},{23,42,2},{23,42,2},{16,36,1},{62,18,338},{16,36,1},{59,0,421},{29,50,0},{32,43,1},{22,43,0},{59,0,421},{62,28,421},{22,43,0},{0,39,425},{62,28,421},{0,39,425},{26,0,421},{26,0,421},{26,0,421},{26,0,421},{22,44,2},{22,44,2},{22,44,2},{22,33,1},{15,37,1},{15,37,1},{29,63,922},{28,54,447},{29,46,646},
+{28,44,446},{25,63,1535},{24,50,447},{24,45,5},{23,41,646},{10,52,1515},{15,41,443},{31,62,425},{31,52,4},{32,45,45},{31,44,69},{57,0,1514},{22,51,422},{24,45,4},{12,41,426},{50,32,1514},{12,41,426},{28,58,421},{28,58,421},{28,58,421},{28,43,421},{24,56,339},{24,45,5},{24,45,5},{24,37,35},{14,45,338},{18,38,5},{31,52,4},{31,52,4},{31,52,4},{31,41,5},{52,0,338},
+{25,44,2},{25,44,2},{18,38,1},{62,21,338},{18,38,1},{62,0,421},{31,52,0},{34,45,1},{24,45,0},{62,0,421},{62,31,421},{24,45,0},{0,41,425},{62,31,421},{0,41,425},{28,0,421},{28,0,421},{28,0,421},{28,0,421},{24,46,2},{24,46,2},{24,46,2},{24,35,1},{17,39,1},{17,39,1},{31,63,994},{30,56,447},{31,48,655},{30,46,446},{28,63,1575},{26,52,447},{26,47,5},
+{25,43,646},{12,54,1515},{17,43,445},{33,63,426},{33,54,2},{34,47,45},{33,46,66},{60,0,1514},{24,53,422},{26,47,4},{14,43,426},{56,32,1514},{14,43,426},{30,60,421},{30,60,421},{30,60,421},{30,45,421},{26,58,339},{26,47,5},{26,47,5},{26,39,35},{16,47,338},{20,40,5},{33,53,1},{33,53,1},{33,53,1},{33,43,2},{55,0,338},{27,46,2},{27,46,2},{20,40,1},{62,24,338},
+{20,40,1},{63,4,421},{33,54,1},{36,47,1},{26,47,0},{63,4,421},{62,34,421},{26,47,0},{0,43,425},{62,34,421},{0,43,425},{30,0,421},{30,0,421},{30,0,421},{30,0,421},{26,48,1},{26,48,1},{26,48,1},{26,37,1},{19,41,1},{19,41,1},{33,63,1082},{32,58,445},{33,50,650},{32,48,450},{30,63,1638},{28,54,447},{28,49,7},{27,45,646},{14,56,1515},{19,45,445},{36,63,434},
+{35,56,2},{36,49,46},{35,48,74},{63,0,1514},{26,55,422},{28,49,6},{16,45,425},{62,32,1514},{16,45,425},{32,61,425},{32,61,425},{32,61,425},{32,47,426},{28,60,339},{28,49,6},{28,49,6},{28,41,35},{18,49,341},{22,42,5},{35,55,1},{35,55,1},{35,55,1},{35,45,2},{58,0,338},{29,48,0},{29,48,0},{22,42,1},{62,27,338},{22,42,1},{63,10,421},{35,56,1},{38,49,1},
+{27,49,1},{63,10,421},{62,37,421},{27,49,1},{0,45,425},{62,37,421},{0,45,425},{32,0,425},{32,0,425},{32,0,425},{32,0,425},{28,50,1},{28,50,1},{28,50,1},{28,39,1},{21,43,1},{21,43,1},{36,63,1206},{34,61,446},{35,52,646},{34,50,446},{33,63,1710},{30,56,445},{31,51,5},{29,47,638},{17,58,1515},{22,47,450},{39,63,469},{37,58,5},{38,52,45},{37,50,69},{63,7,1514},
+{27,58,422},{31,51,1},{19,47,433},{63,35,1514},{19,47,433},{34,63,422},{34,63,422},{34,63,422},{34,49,421},{31,61,342},{31,51,5},{31,51,5},{30,43,36},{20,51,338},{24,44,2},{38,56,4},{38,56,4},{38,56,4},{38,47,4},{53,16,338},{31,51,1},{31,51,1},{25,44,0},{63,30,338},{25,44,0},{63,17,421},{37,58,1},{40,51,1},{30,51,0},{63,17,421},{63,40,421},{30,51,0},
+{0,47,433},{63,40,421},{0,47,433},{34,0,421},{34,0,421},{34,0,421},{34,0,421},{31,51,4},{31,51,4},{31,51,4},{31,41,4},{23,45,1},{23,45,1},{38,63,1350},{36,63,446},{37,54,646},{36,52,446},{36,63,1814},{32,58,447},{32,53,5},{31,48,638},{19,60,1515},{23,49,443},{41,63,517},{39,60,5},{40,54,45},{39,52,69},{63,13,1514},{29,60,422},{32,53,4},{20,49,426},{63,38,1514},
+{20,49,426},{36,63,437},{36,63,437},{36,63,437},{36,51,421},{33,62,347},{32,53,5},{32,53,5},{32,45,33},{22,53,338},{26,46,2},{40,58,4},{40,58,4},{40,58,4},{40,49,4},{56,16,338},{33,52,2},{33,52,2},{27,46,0},{62,33,338},{27,46,0},{63,23,421},{39,60,1},{42,53,1},{32,53,0},{63,23,421},{63,43,421},{32,53,0},{0,49,425},{63,43,421},{0,49,425},{36,0,421},
+{36,0,421},{36,0,421},{36,0,421},{32,54,2},{32,54,2},{32,54,2},{32,43,2},{25,47,1},{25,47,1},{40,63,1466},{38,63,474},{39,56,646},{38,54,446},{38,63,1931},{34,60,447},{34,55,5},{33,51,646},{21,62,1515},{25,51,443},{43,63,569},{41,62,5},{42,56,45},{41,54,69},{63,19,1514},{32,61,422},{34,55,4},{22,51,426},{63,41,1514},{22,51,426},{38,63,470},{38,63,470},{38,63,470},
+{38,53,421},{35,63,355},{34,55,5},{34,55,5},{34,47,33},{24,55,338},{28,48,3},{42,60,4},{42,60,4},{42,60,4},{42,51,4},{59,16,338},{35,54,2},{35,54,2},{28,48,2},{62,36,338},{28,48,2},{63,29,421},{41,62,1},{44,55,1},{34,55,0},{63,29,421},{63,46,421},{34,55,0},{0,51,425},{63,46,421},{0,51,425},{38,0,421},{38,0,421},{38,0,421},{38,0,421},{34,56,2},
+{34,56,2},{34,56,2},{34,45,2},{27,49,1},{27,49,1},{43,63,1634},{41,63,546},{41,58,646},{40,56,446},{40,63,2039},{36,62,447},{36,57,5},{35,53,646},{24,63,1521},{27,53,443},{46,63,633},{44,63,9},{44,58,45},{43,56,69},{63,25,1514},{34,63,422},{36,57,4},{24,53,426},{63,44,1514},{24,53,426},{40,63,502},{40,63,502},{40,63,502},{40,55,421},{37,63,379},{36,57,5},{36,57,5},
+{36,49,35},{26,57,338},{30,50,3},{44,62,4},{44,62,4},{44,62,4},{44,53,4},{62,16,338},{37,56,2},{37,56,2},{30,50,2},{62,39,338},{30,50,2},{63,34,421},{44,63,5},{46,57,1},{36,57,0},{63,34,421},{62,49,421},{36,57,0},{0,53,425},{62,49,421},{0,53,425},{40,0,421},{40,0,421},{40,0,421},{40,0,421},{36,58,2},{36,58,2},{36,58,2},{36,47,2},{29,51,1},
+{29,51,1},{45,63,1866},{43,63,689},{43,60,650},{42,59,447},{43,63,2201},{38,63,469},{39,59,6},{37,55,638},{29,63,1590},{30,55,450},{48,63,741},{46,63,69},{46,60,46},{45,58,70},{62,33,1514},{38,63,465},{39,59,2},{25,56,425},{61,48,1514},{25,56,425},{43,63,545},{43,63,545},{43,63,545},{42,57,422},{40,63,424},{39,59,5},{39,59,5},{38,51,36},{29,59,339},{32,52,2},{46,63,5},
+{46,63,5},{46,63,5},{46,55,2},{63,21,338},{39,59,1},{39,59,1},{33,52,0},{63,42,338},{33,52,0},{63,41,421},{48,63,41},{49,59,2},{38,59,2},{63,41,421},{63,52,421},{38,59,2},{0,56,425},{63,52,421},{0,56,425},{42,0,421},{42,0,421},{42,0,421},{42,0,421},{39,59,4},{39,59,4},{39,59,4},{39,49,4},{31,53,1},{31,53,1},{48,63,2070},{46,63,889},{45,62,650},
+{44,61,447},{46,63,2361},{41,63,573},{41,61,6},{39,57,638},{32,63,1710},{32,57,450},{51,63,837},{49,63,184},{48,62,49},{47,60,70},{63,37,1514},{43,63,545},{41,61,2},{27,58,425},{63,50,1514},{27,58,425},{45,63,614},{45,63,614},{45,63,614},{44,59,422},{43,63,488},{41,61,5},{41,61,5},{40,53,36},{31,61,339},{34,54,2},{48,63,20},{48,63,20},{48,63,20},{48,57,4},{63,27,338},
+{41,61,1},{41,61,1},{35,54,0},{63,45,338},{35,54,0},{63,47,421},{51,63,97},{51,61,2},{40,61,2},{63,47,421},{63,55,421},{40,61,2},{0,58,425},{63,55,421},{0,58,425},{44,0,421},{44,0,421},{44,0,421},{44,0,421},{41,61,4},{41,61,4},{41,61,4},{41,51,4},{33,55,1},{33,55,1},{50,63,2239},{48,63,1109},{47,63,701},{46,62,441},{48,63,2469},{44,63,720},{43,63,5},
+{41,59,605},{37,63,1804},{34,59,417},{54,63,916},{51,63,308},{51,63,52},{49,62,56},{63,43,1459},{46,63,618},{43,63,1},{31,59,400},{63,53,1459},{31,59,400},{47,63,701},{47,63,701},{47,63,701},{46,61,422},{45,63,566},{43,63,5},{43,63,5},{42,55,36},{32,63,341},{36,56,2},{51,63,52},{51,63,52},{51,63,52},{50,59,4},{63,33,338},{43,63,1},{43,63,1},{37,56,0},{47,56,338},
+{37,56,0},{63,53,392},{55,63,157},{53,63,1},{42,63,1},{63,53,392},{63,58,392},{42,63,1},{0,59,400},{63,58,392},{0,59,400},{46,0,421},{46,0,421},{46,0,421},{46,0,421},{43,63,4},{43,63,4},{43,63,4},{43,53,4},{35,57,1},{35,57,1},{51,63,1901},{50,63,1114},{49,63,785},{48,63,421},{51,63,2093},{46,63,574},{45,63,38},{44,60,356},{40,63,1476},{36,60,213},{55,63,684},
+{54,63,260},{53,63,85},{51,63,20},{63,47,1064},{49,63,426},{47,63,8},{35,60,208},{63,55,1064},{35,60,208},{49,63,785},{49,63,785},{49,63,785},{48,63,421},{48,63,661},{45,63,38},{45,63,38},{44,57,36},{37,63,371},{38,58,2},{53,63,85},{53,63,85},{53,63,85},{52,61,4},{63,39,338},{47,63,8},{47,63,8},{39,58,0},{47,59,338},{39,58,0},{63,56,200},{57,63,80},{56,63,1},
+{48,63,0},{63,56,200},{62,60,200},{48,63,0},{0,60,208},{62,60,200},{0,60,208},{48,0,421},{48,0,421},{48,0,421},{48,0,421},{45,63,13},{45,63,13},{45,63,13},{45,55,4},{37,59,1},{37,59,1},{54,63,1646},{52,63,1119},{51,63,886},{50,63,470},{53,63,1761},{48,63,526},{48,63,126},{46,61,146},{44,63,1218},{39,62,69},{57,63,450},{56,63,245},{56,63,145},{54,63,2},{63,51,722},
+{52,63,290},{51,63,50},{38,62,65},{63,57,722},{38,62,65},{51,63,886},{51,63,886},{51,63,886},{50,63,470},{50,63,776},{48,63,126},{48,63,126},{47,59,42},{41,63,446},{40,60,5},{56,63,145},{56,63,145},{56,63,145},{54,63,2},{61,49,338},{51,63,50},{51,63,50},{42,60,1},{63,54,338},{42,60,1},{63,59,61},{60,63,25},{59,63,0},{55,63,0},{63,59,61},{63,61,61},{55,63,0},
+{0,62,65},{63,61,61},{0,62,65},{50,0,421},{50,0,421},{50,0,421},{50,0,421},{48,63,45},{48,63,45},{48,63,45},{47,57,2},{40,61,1},{40,61,1},{56,63,1518},{54,63,1118},{54,63,974},{52,63,565},{54,63,1526},{51,63,534},{51,63,278},{48,62,57},{47,63,1090},{42,63,10},{59,63,354},{58,63,251},{57,63,194},{56,63,50},{63,55,509},{55,63,234},{54,63,106},{42,63,9},{63,59,509},
+{42,63,9},{54,63,974},{54,63,974},{54,63,974},{52,63,565},{53,63,904},{51,63,278},{51,63,278},{48,61,38},{44,63,574},{42,62,5},{57,63,194},{57,63,194},{57,63,194},{56,63,50},{63,51,338},{54,63,106},{54,63,106},{44,62,1},{63,57,338},{44,62,1},{63,62,5},{62,63,4},{62,63,0},{61,63,0},{63,62,5},{62,63,5},{61,63,0},{0,63,9},{62,63,5},{0,63,9},{52,0,421},
+{52,0,421},{52,0,421},{52,0,421},{50,63,72},{50,63,72},{50,63,72},{49,59,5},{42,63,1},{42,63,1},{57,63,1197},{56,63,994},{56,63,894},{54,63,565},{56,63,1210},{54,63,493},{53,63,332},{50,63,13},{51,63,861},{45,63,17},{60,63,209},{60,63,161},{60,63,145},{58,63,50},{63,58,294},{58,63,147},{57,63,89},{47,63,1},{62,61,294},{47,63,1},{56,63,894},{56,63,894},{56,63,894},
+{54,63,565},{54,63,781},{53,63,332},{53,63,332},{50,63,13},{48,63,501},{45,63,17},{60,63,145},{60,63,145},{60,63,145},{58,63,50},{63,55,221},{57,63,89},{57,63,89},{47,63,1},{63,59,221},{47,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{54,0,421},{54,0,421},{54,0,421},{54,0,421},{52,63,117},
+{52,63,117},{52,63,117},{51,61,5},{45,63,17},{45,63,17},{58,63,925},{57,63,765},{57,63,701},{57,63,509},{57,63,845},{55,63,423},{54,63,301},{53,63,5},{52,63,598},{49,63,52},{61,63,97},{61,63,70},{61,63,61},{60,63,17},{63,60,113},{60,63,57},{59,63,40},{53,63,1},{62,62,113},{53,63,1},{57,63,701},{57,63,701},{57,63,701},{57,63,509},{57,63,589},{54,63,301},{54,63,301},
+{53,63,5},{51,63,365},{49,63,52},{61,63,61},{61,63,61},{61,63,61},{60,63,17},{63,58,85},{59,63,40},{59,63,40},{53,63,1},{62,61,85},{53,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{56,0,421},{56,0,421},{56,0,421},{56,0,421},{54,63,157},{54,63,157},{54,63,157},{53,63,5},{49,63,52},
+{49,63,52},{0,29,882},{0,21,116},{0,15,4},{0,13,320},{0,19,1899},{0,14,1214},{0,11,573},{0,8,1421},{0,9,2052},{0,8,1521},{0,29,882},{0,21,116},{0,15,4},{0,13,320},{10,0,1896},{0,14,1214},{0,11,573},{0,8,1421},{14,3,1896},{0,8,1421},{0,14,0},{0,14,0},{0,14,0},{0,7,0},{0,7,162},{0,5,61},{0,5,61},{0,3,100},{0,3,180},{0,3,116},{0,14,0},
+{0,14,0},{0,14,0},{0,7,0},{3,1,162},{0,5,61},{0,5,61},{0,3,100},{7,0,162},{0,3,100},{6,17,882},{0,21,116},{0,15,4},{0,13,320},{6,17,882},{29,0,882},{0,13,320},{0,10,884},{29,0,882},{0,10,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,35,882},{0,25,50},{0,17,10},
+{0,15,260},{0,23,2355},{0,16,1355},{0,14,589},{0,10,1656},{0,11,2567},{0,10,1825},{0,35,882},{0,25,50},{0,17,10},{0,15,260},{3,17,2355},{0,16,1355},{0,14,589},{0,10,1656},{23,0,2355},{0,10,1656},{0,19,1},{0,19,1},{0,19,1},{0,10,0},{0,10,338},{0,8,125},{0,8,125},{0,4,200},{0,5,374},{0,4,225},{0,19,1},{0,19,1},{0,19,1},{0,10,0},{5,0,338},
+{0,8,125},{0,8,125},{0,4,200},{10,0,338},{0,4,200},{17,1,882},{0,25,50},{1,17,2},{0,15,260},{17,1,882},{35,0,882},{0,15,260},{0,12,884},{35,0,882},{0,12,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,41,882},{0,28,10},{1,19,69},{0,17,193},{0,28,2899},{0,19,1539},{0,16,643},
+{0,11,1965},{0,13,3209},{0,11,2161},{0,41,882},{0,28,10},{1,19,53},{0,17,193},{14,0,2899},{0,19,1539},{0,16,643},{0,11,1965},{28,0,2899},{0,11,1965},{0,25,1},{0,25,1},{0,25,1},{0,13,0},{0,13,578},{0,11,221},{0,11,221},{0,6,356},{0,6,644},{0,5,401},{0,25,1},{0,25,1},{0,25,1},{0,13,0},{6,1,578},{0,11,221},{0,11,221},{0,6,356},{13,0,578},
+{0,6,356},{20,1,882},{0,28,10},{3,19,2},{0,17,193},{20,1,882},{41,0,882},{0,17,193},{0,14,884},{41,0,882},{0,14,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,45,902},{1,31,24},{1,21,142},{0,19,166},{0,33,3048},{0,22,1443},{0,18,481},{0,13,1908},{0,16,3492},{0,13,2197},{2,43,886},
+{1,31,8},{3,21,73},{1,19,153},{16,1,3048},{0,22,1443},{0,18,481},{0,13,1908},{33,0,3048},{0,13,1908},{1,29,21},{1,29,21},{1,29,21},{1,15,21},{0,18,648},{0,14,169},{0,14,169},{0,8,325},{0,8,766},{0,7,421},{2,27,5},{2,27,5},{2,27,5},{2,15,4},{9,0,648},{0,14,169},{0,14,169},{0,8,325},{18,0,648},{0,8,325},{23,1,882},{0,31,2},{5,21,2},
+{0,19,130},{23,1,882},{47,0,882},{0,19,130},{0,16,890},{47,0,882},{0,16,890},{1,0,20},{1,0,20},{1,0,20},{1,0,20},{0,5,0},{0,5,0},{0,5,0},{0,2,1},{0,2,5},{0,2,5},{2,49,997},{2,34,114},{3,24,290},{1,22,234},{0,39,3051},{0,25,1256},{0,21,258},{0,16,1764},{0,19,3685},{0,15,2195},{4,46,883},{3,33,10},{5,23,74},{3,21,154},{15,10,3048},
+{0,25,1256},{0,21,258},{0,16,1764},{30,5,3048},{0,16,1764},{2,34,113},{2,34,113},{2,34,113},{2,18,113},{0,25,648},{0,17,89},{0,17,89},{0,10,242},{0,11,876},{0,10,411},{4,30,1},{4,30,1},{4,30,1},{4,17,1},{12,1,648},{0,17,89},{0,17,89},{0,10,242},{25,0,648},{0,10,242},{27,0,882},{3,33,1},{8,23,1},{0,22,80},{27,0,882},{46,4,882},{0,22,80},
+{0,18,884},{46,4,882},{0,18,884},{2,0,113},{2,0,113},{2,0,113},{2,0,113},{0,11,1},{0,11,1},{0,11,1},{0,6,1},{0,5,40},{0,5,40},{3,53,1149},{3,36,274},{4,27,513},{3,24,362},{0,45,3051},{0,28,1128},{0,24,122},{0,18,1605},{0,22,3901},{0,16,2173},{6,47,885},{5,35,10},{7,25,74},{5,23,154},{15,16,3048},{0,28,1128},{0,24,122},{0,18,1605},{30,8,3048},
+{0,18,1605},{3,38,265},{3,38,265},{3,38,265},{3,20,266},{0,31,648},{0,21,34},{0,21,34},{0,13,170},{0,14,1004},{0,11,457},{6,32,1},{6,32,1},{6,32,1},{6,19,1},{15,1,648},{0,21,34},{0,21,34},{0,13,170},{31,0,648},{0,13,170},{30,0,882},{5,35,1},{10,25,1},{0,24,41},{30,0,882},{46,7,882},{0,24,41},{0,20,884},{46,7,882},{0,20,884},{3,0,265},
+{3,0,265},{3,0,265},{3,0,265},{0,17,0},{0,17,0},{0,17,0},{0,9,1},{0,8,104},{0,8,104},{4,57,1365},{4,39,498},{5,28,793},{4,26,561},{0,51,3048},{0,31,1032},{0,26,41},{0,20,1509},{0,24,4147},{0,19,2149},{8,49,885},{7,37,10},{9,27,74},{7,25,154},{17,17,3048},{0,31,1032},{0,26,41},{0,20,1509},{51,0,3048},{0,20,1509},{4,42,481},{4,42,481},{4,42,481},
+{4,23,481},{0,36,650},{0,25,4},{0,25,4},{0,15,130},{0,16,1161},{0,14,481},{8,34,1},{8,34,1},{8,34,1},{8,21,1},{15,7,648},{0,25,4},{0,25,4},{0,15,130},{31,3,648},{0,15,130},{32,1,882},{7,37,1},{12,27,1},{0,26,25},{32,1,882},{46,10,882},{0,26,25},{0,22,884},{46,10,882},{0,22,884},{4,0,481},{4,0,481},{4,0,481},{4,0,481},{0,23,0},
+{0,23,0},{0,23,0},{0,12,1},{0,9,193},{0,9,193},{5,61,1645},{5,42,795},{7,30,1177},{4,28,826},{0,57,3048},{0,35,954},{0,29,9},{0,22,1380},{0,27,4419},{0,21,2197},{10,51,885},{9,39,10},{11,29,74},{9,27,154},{20,17,3048},{0,35,954},{0,29,9},{0,22,1380},{57,0,3048},{0,22,1380},{5,46,761},{5,46,761},{5,46,761},{5,25,762},{0,42,650},{0,28,4},{0,28,4},
+{0,17,85},{0,19,1345},{0,16,557},{10,36,1},{10,36,1},{10,36,1},{10,23,1},{15,13,648},{1,27,1},{1,27,1},{0,17,85},{31,6,648},{0,17,85},{35,1,882},{9,39,1},{14,29,1},{0,29,9},{35,1,882},{46,13,882},{0,29,9},{0,24,884},{46,13,882},{0,24,884},{5,0,761},{5,0,761},{5,0,761},{5,0,761},{0,29,0},{0,29,0},{0,29,0},{0,15,1},{0,11,296},
+{0,11,296},{7,63,1774},{7,44,924},{8,33,1320},{6,30,941},{2,60,3052},{1,38,924},{2,31,10},{0,24,1302},{0,31,4300},{0,24,1942},{12,54,882},{12,40,8},{13,32,68},{11,29,161},{32,0,3048},{0,39,898},{2,31,6},{0,24,1266},{62,1,3048},{0,24,1266},{7,48,885},{7,48,885},{7,48,885},{7,28,884},{2,45,652},{2,31,9},{2,31,9},{1,20,62},{0,22,1275},{0,19,419},{12,39,0},
+{12,39,0},{12,39,0},{12,25,1},{24,1,648},{3,30,0},{3,30,0},{0,20,45},{49,0,648},{0,20,45},{39,0,882},{11,41,1},{16,31,2},{1,31,1},{39,0,882},{62,8,882},{1,31,1},{0,26,882},{62,8,882},{0,26,882},{7,0,884},{7,0,884},{7,0,884},{7,0,884},{2,32,4},{2,32,4},{2,32,4},{2,17,4},{0,16,250},{0,16,250},{9,63,1798},{9,46,924},{10,35,1320},
+{9,32,936},{4,62,3052},{3,40,924},{4,33,9},{2,26,1302},{0,33,4023},{0,26,1647},{14,56,882},{14,42,8},{15,34,68},{13,31,161},{35,0,3048},{0,42,882},{4,33,5},{0,27,1170},{62,4,3048},{0,27,1170},{9,50,885},{9,50,885},{9,50,885},{9,30,884},{4,47,652},{4,32,8},{4,32,8},{3,22,62},{0,25,1107},{0,22,243},{14,41,0},{14,41,0},{14,41,0},{14,27,1},{27,1,648},
+{5,32,1},{5,32,1},{0,22,18},{55,0,648},{0,22,18},{42,0,882},{13,43,1},{18,33,1},{2,33,0},{42,0,882},{62,11,882},{2,33,0},{0,28,882},{62,11,882},{0,28,882},{9,0,884},{9,0,884},{9,0,884},{9,0,884},{4,34,4},{4,34,4},{4,34,4},{4,19,4},{0,19,146},{0,19,146},{12,63,1846},{11,48,924},{12,37,1320},{11,34,936},{6,63,3055},{5,42,924},{6,35,9},
+{4,28,1302},{0,36,3799},{0,28,1356},{16,58,883},{16,44,9},{17,35,74},{15,33,161},{38,0,3048},{2,44,882},{6,35,5},{0,29,1110},{62,7,3048},{0,29,1110},{11,52,885},{11,52,885},{11,52,885},{11,32,885},{6,49,652},{6,34,8},{6,34,8},{5,24,62},{0,29,969},{0,24,109},{16,42,1},{16,42,1},{16,42,1},{16,29,2},{30,1,648},{7,34,1},{7,34,1},{0,24,9},{61,0,648},
+{0,24,9},{45,0,882},{15,45,1},{20,35,1},{4,35,0},{45,0,882},{62,14,882},{4,35,0},{0,30,882},{62,14,882},{0,30,882},{11,0,884},{11,0,884},{11,0,884},{11,0,884},{6,36,4},{6,36,4},{6,36,4},{6,21,4},{0,22,74},{0,22,74},{14,63,1912},{13,50,924},{14,39,1320},{13,36,936},{9,63,3087},{7,44,924},{8,37,9},{6,30,1302},{0,39,3607},{0,31,1156},{18,60,883},
+{18,46,9},{19,37,74},{17,35,154},{41,0,3048},{4,46,882},{8,37,5},{0,31,1035},{62,10,3048},{0,31,1035},{13,54,885},{13,54,885},{13,54,885},{13,34,885},{8,51,652},{8,36,8},{8,36,8},{7,26,62},{0,33,846},{0,27,37},{18,44,1},{18,44,1},{18,44,1},{18,31,2},{33,1,648},{9,36,1},{9,36,1},{0,27,1},{63,2,648},{0,27,1},{47,2,882},{16,48,1},{22,37,1},
+{6,37,0},{47,2,882},{62,17,882},{6,37,0},{0,32,884},{62,17,882},{0,32,884},{13,0,884},{13,0,884},{13,0,884},{13,0,884},{8,38,4},{8,38,4},{8,38,4},{8,23,4},{0,26,29},{0,26,29},{16,63,2014},{15,52,932},{16,40,1341},{15,38,932},{12,63,3141},{9,46,924},{10,39,7},{9,32,1308},{0,43,3436},{0,33,1003},{20,62,884},{20,48,8},{21,40,74},{19,37,161},{36,16,3048},
+{6,48,882},{10,39,6},{0,33,978},{63,13,3048},{0,33,978},{15,57,882},{15,57,882},{15,57,882},{15,36,882},{10,54,649},{10,39,6},{10,39,6},{9,28,61},{0,36,737},{1,29,8},{20,47,0},{20,47,0},{20,47,0},{20,33,1},{31,12,648},{11,38,1},{11,38,1},{2,29,1},{62,6,648},{2,29,1},{51,0,882},{19,49,1},{24,39,1},{9,39,1},{51,0,882},{47,28,882},{9,39,1},
+{0,34,882},{47,28,882},{0,34,882},{15,0,882},{15,0,882},{15,0,882},{15,0,882},{10,40,2},{10,40,2},{10,40,2},{10,25,2},{0,30,2},{0,30,2},{19,63,2126},{17,54,924},{18,42,1341},{16,40,941},{14,63,3204},{11,48,924},{12,41,7},{11,34,1308},{0,46,3300},{0,35,939},{22,63,890},{22,50,8},{23,42,74},{21,39,161},{39,16,3048},{8,50,882},{12,41,6},{0,35,939},{62,16,3048},
+{0,35,939},{17,59,884},{17,59,884},{17,59,884},{17,38,884},{12,56,649},{12,41,6},{12,41,6},{11,30,61},{0,39,681},{3,31,8},{22,49,0},{22,49,0},{22,49,0},{22,35,1},{31,18,648},{13,40,1},{13,40,1},{4,31,1},{62,9,648},{4,31,1},{54,0,882},{21,51,1},{26,41,1},{11,41,1},{54,0,882},{47,31,882},{11,41,1},{0,36,882},{47,31,882},{0,36,882},{17,0,884},
+{17,0,884},{17,0,884},{17,0,884},{12,42,2},{12,42,2},{12,42,2},{12,27,2},{2,32,1},{2,32,1},{20,63,2264},{19,56,924},{20,44,1341},{18,42,941},{17,63,3292},{13,50,924},{14,43,7},{13,36,1308},{0,50,3192},{0,38,923},{25,63,906},{24,52,8},{25,44,74},{23,41,161},{50,0,3048},{10,52,882},{14,43,6},{0,38,907},{62,19,3048},{0,38,907},{19,61,884},{19,61,884},{19,61,884},
+{19,40,884},{14,58,649},{14,43,6},{14,43,6},{13,32,67},{0,42,657},{4,33,10},{24,51,0},{24,51,0},{24,51,0},{24,37,1},{34,17,648},{15,42,1},{15,42,1},{6,33,1},{62,12,648},{6,33,1},{57,0,882},{23,53,1},{28,43,1},{13,43,1},{57,0,882},{50,32,882},{13,43,1},{0,38,882},{50,32,882},{0,38,882},{19,0,884},{19,0,884},{19,0,884},{19,0,884},{14,44,2},
+{14,44,2},{14,44,2},{14,29,2},{4,34,1},{4,34,1},{23,63,2376},{21,58,924},{22,46,1341},{20,44,941},{19,63,3391},{15,52,924},{16,45,10},{15,38,1308},{0,53,3112},{2,40,923},{27,63,948},{26,54,8},{27,46,74},{25,43,161},{53,0,3048},{12,54,882},{16,45,6},{0,40,891},{62,22,3048},{0,40,891},{21,63,884},{21,63,884},{21,63,884},{21,42,884},{16,59,652},{16,45,9},{16,45,9},
+{15,34,67},{1,45,650},{6,35,10},{26,53,0},{26,53,0},{26,53,0},{26,39,1},{37,17,648},{17,44,0},{17,44,0},{8,35,1},{62,15,648},{8,35,1},{60,0,882},{25,55,1},{30,45,1},{15,45,1},{60,0,882},{56,32,882},{15,45,1},{0,40,882},{56,32,882},{0,40,882},{21,0,884},{21,0,884},{21,0,884},{21,0,884},{16,46,4},{16,46,4},{16,46,4},{16,31,4},{6,36,1},
+{6,36,1},{26,63,2564},{23,61,927},{24,49,1324},{23,47,935},{22,63,3529},{17,54,924},{18,47,10},{17,41,1302},{0,56,3060},{5,42,924},{30,63,1003},{28,57,6},{29,48,67},{28,46,158},{56,1,3048},{15,56,883},{19,47,8},{1,42,884},{63,25,3048},{1,42,884},{23,63,891},{23,63,891},{23,63,891},{23,44,883},{18,62,649},{18,47,6},{18,47,6},{17,36,61},{4,47,652},{9,37,8},{28,55,2},
+{28,55,2},{28,55,2},{28,42,2},{49,0,648},{19,46,2},{19,46,2},{11,37,0},{62,18,648},{11,37,0},{63,1,882},{27,58,2},{32,47,4},{17,47,5},{63,1,882},{63,32,882},{17,47,5},{0,42,884},{63,32,882},{0,42,884},{23,0,882},{23,0,882},{23,0,882},{23,0,882},{18,48,2},{18,48,2},{18,48,2},{18,33,2},{8,38,1},{8,38,1},{28,63,2774},{25,63,927},{26,51,1324},
+{25,48,932},{25,63,3681},{19,56,924},{20,49,7},{19,43,1302},{0,59,3052},{7,44,924},{32,63,1074},{30,59,6},{31,50,67},{30,48,170},{59,1,3048},{16,58,885},{20,49,6},{3,44,884},{63,28,3048},{3,44,884},{25,63,918},{25,63,918},{25,63,918},{25,46,883},{20,63,651},{20,49,6},{20,49,6},{19,38,61},{5,49,651},{11,39,8},{30,57,2},{30,57,2},{30,57,2},{30,44,2},{52,0,648},
+{21,48,1},{21,48,1},{13,39,0},{62,21,648},{13,39,0},{63,7,882},{29,60,2},{34,49,1},{19,49,1},{63,7,882},{63,35,882},{19,49,1},{0,44,884},{63,35,882},{0,44,884},{25,0,882},{25,0,882},{25,0,882},{25,0,882},{20,50,2},{20,50,2},{20,50,2},{20,35,2},{10,40,1},{10,40,1},{31,63,2998},{28,63,951},{28,53,1324},{27,50,932},{26,63,3844},{21,58,924},{22,51,7},
+{21,45,1302},{2,61,3052},{9,46,924},{34,63,1146},{32,61,9},{33,52,74},{32,50,169},{62,1,3048},{18,60,885},{22,51,6},{5,46,884},{63,31,3048},{5,46,884},{28,63,950},{28,63,950},{28,63,950},{27,48,882},{23,63,675},{22,51,6},{22,51,6},{21,40,61},{7,51,651},{13,41,8},{32,59,0},{32,59,0},{32,59,0},{32,46,1},{55,0,648},{23,50,1},{23,50,1},{15,41,0},{62,24,648},
+{15,41,0},{63,13,882},{31,62,2},{36,51,1},{21,51,1},{63,13,882},{63,38,882},{21,51,1},{0,46,884},{63,38,882},{0,46,884},{27,0,882},{27,0,882},{27,0,882},{27,0,882},{22,52,2},{22,52,2},{22,52,2},{22,37,2},{12,42,1},{12,42,1},{33,63,3224},{30,63,1031},{30,55,1324},{29,52,932},{29,63,3996},{23,60,924},{24,53,7},{23,47,1302},{4,63,3052},{11,48,922},{37,63,1226},
+{34,63,9},{35,54,74},{33,51,161},{63,5,3048},{20,62,885},{24,53,6},{6,48,882},{47,42,3048},{6,48,882},{30,63,995},{30,63,995},{30,63,995},{29,50,882},{25,63,705},{24,53,6},{24,53,6},{23,42,61},{9,53,651},{15,43,8},{34,61,0},{34,61,0},{34,61,0},{34,47,4},{58,0,648},{25,52,1},{25,52,1},{16,43,1},{62,27,648},{16,43,1},{63,19,882},{33,63,4},{38,53,1},
+{23,53,1},{63,19,882},{63,41,882},{23,53,1},{0,48,882},{63,41,882},{0,48,882},{29,0,882},{29,0,882},{29,0,882},{29,0,882},{24,54,2},{24,54,2},{24,54,2},{24,39,2},{14,44,1},{14,44,1},{34,63,3510},{32,63,1202},{33,57,1335},{31,54,936},{33,63,4252},{25,63,925},{26,55,13},{25,49,1309},{9,63,3091},{13,50,918},{40,63,1349},{37,63,38},{37,56,77},{36,54,158},{60,17,3048},
+{24,63,894},{27,55,8},{9,50,884},{63,37,3048},{9,50,884},{32,63,1058},{32,63,1058},{32,63,1058},{31,52,885},{28,63,762},{26,55,9},{26,55,9},{26,44,61},{11,56,650},{17,45,11},{36,63,2},{36,63,2},{36,63,2},{36,50,2},{53,16,648},{28,54,1},{28,54,1},{19,45,1},{63,30,648},{19,45,1},{59,33,882},{37,63,29},{40,56,4},{26,55,4},{59,33,882},{55,48,882},{26,55,4},
+{0,50,884},{55,48,882},{0,50,884},{31,0,884},{31,0,884},{31,0,884},{31,0,884},{26,57,0},{26,57,0},{26,57,0},{26,42,1},{16,47,2},{16,47,2},{37,63,3734},{34,63,1399},{35,59,1335},{33,57,935},{34,63,4441},{28,63,957},{28,57,13},{27,51,1309},{13,63,3192},{15,52,918},{43,63,1485},{39,63,131},{39,58,77},{38,56,158},{63,17,3048},{28,63,957},{29,57,8},{11,52,884},{63,40,3048},
+{11,52,884},{34,63,1110},{34,63,1110},{34,63,1110},{33,54,883},{30,63,840},{28,57,9},{28,57,9},{28,46,61},{13,58,650},{19,47,11},{39,63,10},{39,63,10},{39,63,10},{38,52,2},{56,16,648},{30,56,1},{30,56,1},{21,47,1},{62,33,648},{21,47,1},{62,33,882},{41,63,80},{42,58,4},{28,57,4},{62,33,882},{61,48,882},{28,57,4},{0,52,884},{61,48,882},{0,52,884},{33,0,882},
+{33,0,882},{33,0,882},{33,0,882},{28,59,0},{28,59,0},{28,59,0},{28,44,1},{18,48,1},{18,48,1},{40,63,4022},{37,63,1647},{37,61,1335},{35,59,935},{37,63,4657},{31,63,1085},{30,59,13},{29,53,1309},{18,63,3339},{17,54,924},{45,63,1635},{42,63,275},{41,60,77},{40,58,158},{63,23,3048},{32,63,1044},{31,59,8},{13,54,884},{63,43,3048},{13,54,884},{36,63,1203},{36,63,1203},{36,63,1203},
+{35,56,883},{33,63,915},{30,59,9},{30,59,9},{30,48,65},{15,60,650},{21,49,8},{41,63,25},{41,63,25},{41,63,25},{40,54,2},{59,16,648},{32,57,4},{32,57,4},{23,49,0},{62,36,648},{23,49,0},{63,37,882},{44,63,160},{44,60,4},{30,59,4},{63,37,882},{63,50,882},{30,59,4},{0,54,884},{63,50,882},{0,54,884},{35,0,882},{35,0,882},{35,0,882},{35,0,882},{30,61,0},
+{30,61,0},{30,61,0},{30,46,1},{20,50,1},{20,50,1},{42,63,4364},{40,63,1991},{39,63,1335},{37,61,935},{40,63,4905},{34,63,1287},{32,61,10},{31,55,1309},{21,63,3555},{19,56,924},{48,63,1796},{44,63,465},{43,62,77},{42,60,158},{63,29,3048},{35,63,1188},{33,61,8},{15,56,884},{63,46,3048},{15,56,884},{39,63,1299},{39,63,1299},{39,63,1299},{37,58,883},{34,63,1017},{32,61,6},{32,61,6},
+{32,50,66},{17,62,650},{23,51,8},{43,63,45},{43,63,45},{43,63,45},{42,56,2},{62,16,648},{33,60,2},{33,60,2},{25,51,0},{62,39,648},{25,51,0},{63,43,882},{48,63,260},{46,62,4},{30,62,4},{63,43,882},{63,53,882},{30,62,4},{0,56,884},{63,53,882},{0,56,884},{37,0,882},{37,0,882},{37,0,882},{37,0,882},{32,63,1},{32,63,1},{32,63,1},{32,47,2},{22,52,1},
+{22,52,1},{45,63,4441},{43,63,2286},{41,63,1421},{39,62,916},{43,63,4878},{37,63,1410},{34,63,9},{33,57,1141},{26,63,3535},{21,58,795},{50,63,1770},{47,63,609},{46,63,85},{44,62,120},{63,35,2814},{40,63,1194},{35,63,2},{17,58,762},{63,49,2814},{17,58,762},{41,63,1421},{41,63,1421},{41,63,1421},{39,61,885},{37,63,1130},{34,63,9},{34,63,9},{34,52,61},{20,63,651},{25,53,11},{46,63,85},
+{46,63,85},{46,63,85},{44,58,4},{63,21,648},{36,62,1},{36,62,1},{27,53,2},{63,42,648},{27,53,2},{63,48,761},{51,63,305},{48,63,1},{34,63,0},{63,48,761},{62,56,761},{34,63,0},{0,58,761},{62,56,761},{0,58,761},{39,0,884},{39,0,884},{39,0,884},{39,0,884},{34,63,9},{34,63,9},{34,63,9},{34,50,1},{24,55,2},{24,55,2},{46,63,3945},{43,63,2238},{43,63,1509},
+{41,63,885},{45,63,4345},{38,63,1230},{37,63,41},{34,58,781},{30,63,3066},{24,59,494},{51,63,1386},{48,63,530},{48,63,130},{46,62,45},{63,39,2249},{43,63,914},{39,63,8},{21,59,482},{47,59,2249},{21,59,482},{43,63,1509},{43,63,1509},{43,63,1509},{41,63,885},{40,63,1242},{37,63,41},{37,63,41},{36,54,61},{24,63,689},{27,55,11},{48,63,130},{48,63,130},{48,63,130},{46,60,4},{63,27,648},
+{39,63,8},{39,63,8},{29,55,2},{63,45,648},{29,55,2},{63,51,481},{54,63,193},{51,63,1},{40,63,0},{63,51,481},{63,57,481},{40,63,0},{0,59,481},{63,57,481},{0,59,481},{41,0,884},{41,0,884},{41,0,884},{41,0,884},{37,63,25},{37,63,25},{37,63,25},{36,52,1},{26,57,2},{26,57,2},{48,63,3571},{46,63,2182},{46,63,1653},{43,63,900},{46,63,3838},{41,63,1094},{40,63,137},
+{37,59,490},{32,63,2703},{27,60,270},{53,63,1106},{51,63,458},{50,63,193},{48,63,10},{63,43,1769},{46,63,698},{42,63,40},{25,60,266},{63,53,1769},{25,60,266},{46,63,1653},{46,63,1653},{46,63,1653},{43,63,900},{43,63,1386},{40,63,137},{40,63,137},{38,56,61},{29,63,779},{29,57,11},{50,63,193},{50,63,193},{50,63,193},{48,62,1},{63,33,648},{42,63,40},{42,63,40},{31,57,2},{47,56,648},
+{31,57,2},{63,54,265},{57,63,113},{54,63,1},{46,63,0},{63,54,265},{62,59,265},{46,63,0},{0,60,265},{62,59,265},{0,60,265},{43,0,884},{43,0,884},{43,0,884},{43,0,884},{39,63,52},{39,63,52},{39,63,52},{38,54,1},{28,59,2},{28,59,2},{50,63,3307},{48,63,2195},{48,63,1795},{46,63,964},{48,63,3435},{43,63,1026},{42,63,296},{39,60,269},{37,63,2410},{30,61,115},{54,63,882},
+{54,63,450},{53,63,265},{50,63,10},{63,47,1374},{48,63,546},{46,63,89},{29,61,114},{63,55,1374},{29,61,114},{48,63,1795},{48,63,1795},{48,63,1795},{46,63,964},{45,63,1560},{42,63,296},{42,63,296},{40,58,61},{32,63,891},{31,59,11},{53,63,265},{53,63,265},{53,63,265},{50,63,10},{63,39,648},{46,63,89},{46,63,89},{33,59,1},{47,59,648},{33,59,1},{63,57,113},{58,63,50},{57,63,1},
+{52,63,0},{63,57,113},{63,60,113},{52,63,0},{0,61,113},{63,60,113},{0,61,113},{45,0,884},{45,0,884},{45,0,884},{45,0,884},{41,63,97},{41,63,97},{41,63,97},{40,56,1},{30,61,2},{30,61,2},{51,63,3032},{51,63,2264},{50,63,1965},{48,63,1096},{51,63,3096},{46,63,1059},{46,63,530},{41,62,126},{40,63,2191},{33,62,25},{57,63,680},{56,63,465},{55,63,356},{53,63,68},{63,51,1032},
+{52,63,450},{49,63,185},{34,62,20},{63,57,1032},{34,62,20},{50,63,1965},{50,63,1965},{50,63,1965},{48,63,1096},{48,63,1736},{46,63,530},{46,63,530},{42,60,62},{37,63,1086},{33,62,9},{55,63,356},{55,63,356},{55,63,356},{53,63,68},{61,49,648},{49,63,185},{49,63,185},{36,61,4},{63,54,648},{36,61,4},{63,61,18},{61,63,9},{61,63,0},{59,63,0},{63,61,18},{63,62,18},{59,63,0},
+{0,62,20},{63,62,18},{0,62,20},{47,0,890},{47,0,890},{47,0,890},{47,0,890},{44,63,149},{44,63,149},{44,63,149},{42,58,1},{32,63,0},{32,63,0},{54,63,2756},{52,63,2249},{51,63,2004},{50,63,1224},{53,63,2803},{48,63,1092},{48,63,692},{44,62,58},{43,63,1991},{35,63,16},{59,63,566},{57,63,420},{57,63,356},{55,63,125},{63,55,771},{55,63,386},{52,63,241},{38,63,0},{63,59,771},
+{38,63,0},{51,63,2004},{51,63,2004},{51,63,2004},{50,63,1224},{50,63,1802},{48,63,692},{48,63,692},{44,62,42},{40,63,1166},{35,63,16},{57,63,356},{57,63,356},{57,63,356},{55,63,125},{63,50,580},{52,63,241},{52,63,241},{38,63,0},{62,57,580},{38,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{49,0,884},
+{49,0,884},{49,0,884},{49,0,884},{46,63,193},{46,63,193},{46,63,193},{44,60,1},{35,63,16},{35,63,16},{54,63,2276},{54,63,1844},{54,63,1700},{52,63,1125},{54,63,2180},{51,63,948},{49,63,649},{46,63,10},{46,63,1551},{39,63,58},{60,63,324},{59,63,257},{59,63,221},{57,63,68},{63,57,452},{57,63,228},{55,63,137},{44,63,0},{63,60,452},{44,63,0},{54,63,1700},{54,63,1700},{54,63,1700},
+{52,63,1125},{51,63,1460},{49,63,649},{49,63,649},{46,63,10},{43,63,926},{39,63,58},{59,63,221},{59,63,221},{59,63,221},{57,63,68},{63,53,340},{55,63,137},{55,63,137},{44,63,0},{63,58,340},{44,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{51,0,884},{51,0,884},{51,0,884},{51,0,884},{48,63,260},
+{48,63,260},{48,63,260},{46,62,1},{39,63,58},{39,63,58},{57,63,1844},{55,63,1585},{55,63,1464},{54,63,1044},{56,63,1747},{52,63,850},{51,63,596},{48,63,4},{48,63,1204},{43,63,117},{60,63,164},{60,63,116},{60,63,100},{59,63,40},{63,59,216},{58,63,114},{58,63,65},{50,63,0},{63,61,216},{50,63,0},{55,63,1464},{55,63,1464},{55,63,1464},{54,63,1044},{54,63,1188},{51,63,596},{51,63,596},
+{48,63,4},{46,63,750},{43,63,117},{60,63,100},{60,63,100},{60,63,100},{59,63,40},{63,56,164},{58,63,65},{58,63,65},{50,63,0},{62,60,164},{50,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{53,0,884},{53,0,884},{53,0,884},{53,0,884},{51,63,340},{51,63,340},{51,63,340},{48,63,4},{43,63,117},
+{43,63,117},{0,39,1568},{0,28,194},{0,19,10},{0,16,586},{0,26,3371},{0,17,2169},{0,16,1027},{0,10,2532},{0,12,3648},{0,10,2701},{0,39,1568},{0,28,194},{0,19,10},{0,16,586},{5,16,3371},{0,17,2169},{0,16,1027},{0,10,2532},{26,0,3371},{0,10,2532},{0,18,0},{0,18,0},{0,18,0},{0,9,0},{0,9,288},{0,8,109},{0,8,109},{0,4,164},{0,4,321},{0,4,189},{0,18,0},
+{0,18,0},{0,18,0},{0,9,0},{4,1,288},{0,8,109},{0,8,109},{0,4,164},{9,0,288},{0,4,164},{19,1,1568},{0,28,194},{0,19,10},{0,16,586},{19,1,1568},{39,0,1568},{0,16,586},{0,13,1568},{39,0,1568},{0,13,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,45,1568},{0,31,106},{0,22,10},
+{0,18,481},{0,30,3968},{0,19,2355},{0,18,1057},{0,13,2852},{0,14,4319},{0,11,3117},{0,45,1568},{0,31,106},{0,22,10},{0,18,481},{15,0,3968},{0,19,2355},{0,18,1057},{0,13,2852},{30,0,3968},{0,13,2852},{0,24,0},{0,24,0},{0,24,0},{0,12,0},{0,12,512},{0,10,205},{0,10,205},{0,5,313},{0,5,566},{0,5,349},{0,24,0},{0,24,0},{0,24,0},{0,12,0},{6,0,512},
+{0,10,205},{0,10,205},{0,5,313},{12,0,512},{0,5,313},{22,1,1568},{0,31,106},{1,22,1},{0,18,481},{22,1,1568},{45,0,1568},{0,18,481},{0,15,1568},{45,0,1568},{0,15,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,50,1570},{0,34,52},{1,24,58},{0,21,377},{0,34,4652},{0,22,2571},{0,19,1107},
+{0,14,3225},{0,16,5108},{0,13,3525},{0,50,1570},{0,34,52},{1,24,42},{0,21,377},{15,4,4651},{0,22,2571},{0,19,1107},{0,14,3225},{30,2,4651},{0,14,3225},{0,30,0},{0,30,0},{0,30,0},{0,15,0},{0,15,800},{0,11,317},{0,11,317},{0,7,468},{0,7,889},{0,7,549},{0,30,0},{0,30,0},{0,30,0},{0,15,0},{7,1,800},{0,11,317},{0,11,317},{0,7,468},{15,0,800},
+{0,7,468},{25,1,1568},{0,34,52},{3,24,1},{0,21,377},{25,1,1568},{47,2,1568},{0,21,377},{0,17,1570},{47,2,1568},{0,17,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,56,1570},{0,38,13},{1,27,138},{0,24,305},{0,38,5419},{0,25,2819},{0,22,1187},{0,16,3659},{0,17,6013},{0,14,4061},{0,56,1570},
+{0,38,13},{1,27,122},{0,24,305},{19,0,5419},{0,25,2819},{0,22,1187},{0,16,3659},{38,0,5419},{0,16,3659},{0,36,0},{0,36,0},{0,36,0},{0,18,0},{0,18,1152},{0,14,445},{0,14,445},{0,8,697},{0,8,1270},{0,8,797},{0,36,0},{0,36,0},{0,36,0},{0,18,0},{9,0,1152},{0,14,445},{0,14,445},{0,8,697},{18,0,1152},{0,8,697},{28,1,1568},{0,38,13},{5,26,1},
+{0,24,305},{28,1,1568},{47,5,1568},{0,24,305},{0,19,1570},{47,5,1568},{0,19,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,61,1609},{1,41,43},{2,29,250},{1,26,301},{0,45,5419},{0,28,2552},{0,25,820},{0,18,3377},{0,21,6243},{0,18,3953},{2,59,1569},{2,41,10},{3,29,125},{1,26,285},{22,1,5419},
+{0,28,2552},{0,25,820},{0,18,3377},{45,0,5419},{0,18,3377},{1,40,42},{1,40,42},{1,40,42},{1,21,42},{0,25,1152},{0,19,292},{0,19,292},{0,11,569},{0,11,1380},{0,10,747},{2,38,2},{2,38,2},{2,38,2},{2,20,2},{12,1,1152},{0,19,292},{0,19,292},{0,11,569},{25,0,1152},{0,11,569},{23,17,1568},{0,42,1},{7,28,1},{0,26,233},{23,17,1568},{63,0,1568},{0,26,233},
+{0,21,1568},{63,0,1568},{0,21,1568},{1,0,41},{1,0,41},{1,0,41},{1,0,41},{0,7,0},{0,7,0},{0,7,0},{0,3,1},{0,3,17},{0,3,17},{2,63,1731},{2,44,146},{3,31,441},{1,28,370},{0,50,5420},{0,33,2329},{0,27,554},{0,21,3217},{0,23,6476},{0,19,3861},{4,61,1569},{4,43,10},{5,31,125},{3,28,285},{25,1,5419},{0,33,2329},{0,27,554},{0,21,3217},{47,2,5419},
+{0,21,3217},{2,44,146},{2,44,146},{2,44,146},{2,23,146},{0,31,1152},{0,22,180},{0,22,180},{0,13,458},{0,14,1508},{0,13,747},{4,40,2},{4,40,2},{4,40,2},{4,22,2},{15,1,1152},{0,22,180},{0,22,180},{0,13,458},{31,0,1152},{0,13,458},{34,1,1568},{2,44,1},{9,30,1},{0,28,164},{34,1,1568},{63,3,1568},{0,28,164},{0,23,1568},{63,3,1568},{0,23,1568},{2,0,145},
+{2,0,145},{2,0,145},{2,0,145},{0,13,0},{0,13,0},{0,13,0},{0,6,1},{0,5,52},{0,5,52},{4,63,1977},{3,47,318},{5,33,675},{3,30,498},{0,56,5420},{0,36,2129},{0,30,338},{0,22,3012},{0,25,6733},{0,21,3825},{6,63,1569},{6,45,10},{8,33,123},{5,30,285},{28,1,5419},{0,36,2129},{0,30,338},{0,22,3012},{47,5,5419},{0,22,3012},{3,48,313},{3,48,313},{3,48,313},
+{3,26,314},{0,36,1154},{0,25,100},{0,25,100},{0,16,388},{0,16,1665},{0,14,757},{6,42,2},{6,42,2},{6,42,2},{6,24,2},{15,7,1152},{0,25,100},{0,25,100},{0,16,388},{31,3,1152},{0,16,388},{37,1,1568},{4,46,1},{11,32,2},{0,30,113},{37,1,1568},{63,6,1568},{0,30,113},{0,25,1568},{63,6,1568},{0,25,1568},{3,0,313},{3,0,313},{3,0,313},{3,0,313},{0,19,0},
+{0,19,0},{0,19,0},{0,9,1},{0,8,116},{0,8,116},{6,63,2353},{4,49,562},{6,35,1006},{3,32,715},{0,62,5420},{0,39,1961},{0,32,174},{0,24,2817},{0,28,7013},{0,24,3841},{9,63,1577},{8,47,10},{10,35,123},{7,31,290},{31,1,5419},{0,39,1961},{0,32,174},{0,24,2817},{47,8,5419},{0,24,2817},{4,52,545},{4,52,545},{4,52,545},{4,28,546},{0,42,1154},{0,29,45},{0,29,45},
+{0,18,289},{0,19,1849},{0,16,797},{8,44,2},{8,44,2},{8,44,2},{8,26,2},{15,13,1152},{0,29,45},{0,29,45},{0,18,289},{31,6,1152},{0,18,289},{40,1,1568},{6,48,1},{13,34,2},{0,33,73},{40,1,1568},{63,9,1568},{0,33,73},{0,27,1568},{63,9,1568},{0,27,1568},{4,0,545},{4,0,545},{4,0,545},{4,0,545},{0,25,0},{0,25,0},{0,25,0},{0,12,1},{0,11,212},
+{0,11,212},{8,63,2980},{6,52,920},{7,38,1444},{5,34,1012},{2,63,5504},{0,42,1814},{0,35,57},{0,27,2630},{0,31,7380},{0,25,3860},{11,63,1604},{10,49,13},{12,37,116},{10,33,292},{34,1,5419},{0,42,1814},{0,35,57},{0,27,2630},{63,3,5419},{0,27,2630},{5,57,884},{5,57,884},{5,57,884},{5,31,884},{0,49,1152},{0,33,5},{0,33,5},{0,21,221},{0,22,2091},{0,19,875},{11,45,4},
+{11,45,4},{11,45,4},{11,28,4},{24,1,1152},{0,33,5},{0,33,5},{0,21,221},{49,0,1152},{0,21,221},{44,0,1568},{8,50,1},{15,36,4},{0,35,32},{44,0,1568},{62,13,1568},{0,35,32},{0,29,1570},{62,13,1568},{0,29,1570},{5,0,884},{5,0,884},{5,0,884},{5,0,884},{0,31,1},{0,31,1},{0,31,1},{0,16,1},{0,14,349},{0,14,349},{9,63,3638},{7,55,1309},{8,39,1940},
+{6,36,1365},{3,63,5739},{0,45,1718},{0,38,17},{0,29,2514},{0,34,7760},{0,28,3900},{14,63,1636},{12,51,13},{14,39,116},{12,35,292},{37,1,5419},{0,45,1718},{0,38,17},{0,29,2514},{63,6,5419},{0,29,2514},{6,61,1252},{6,61,1252},{6,61,1252},{6,33,1253},{0,55,1152},{0,37,4},{0,37,4},{0,22,162},{0,25,2339},{0,21,989},{13,47,4},{13,47,4},{13,47,4},{13,30,4},{27,1,1152},
+{1,36,1},{1,36,1},{0,22,162},{55,0,1152},{0,22,162},{47,0,1568},{10,52,1},{17,38,1},{0,38,16},{47,0,1568},{46,24,1568},{0,38,16},{0,31,1570},{46,24,1568},{0,31,1570},{6,0,1252},{6,0,1252},{6,0,1252},{6,0,1252},{0,37,0},{0,37,0},{0,37,0},{0,19,1},{0,16,490},{0,16,490},{11,63,4328},{8,57,1644},{10,41,2360},{7,39,1656},{6,63,6079},{0,49,1644},{1,40,17},
+{0,31,2359},{0,36,7943},{0,30,3834},{16,63,1689},{14,53,13},{16,41,129},{14,37,292},{40,1,5419},{0,49,1640},{1,40,13},{0,31,2355},{63,9,5419},{0,31,2355},{8,63,1576},{8,63,1576},{8,63,1576},{7,36,1576},{1,59,1156},{1,39,13},{1,39,13},{0,25,110},{0,28,2475},{0,24,1017},{15,49,4},{15,49,4},{15,49,4},{15,32,4},{30,1,1152},{3,38,1},{3,38,1},{0,25,106},{61,0,1152},
+{0,25,106},{49,1,1568},{12,54,1},{19,40,1},{0,40,4},{49,1,1568},{46,27,1568},{0,40,4},{0,33,1568},{46,27,1568},{0,33,1568},{7,0,1576},{7,0,1576},{7,0,1576},{7,0,1576},{1,41,4},{1,41,4},{1,41,4},{1,21,4},{0,19,578},{0,19,578},{14,63,4584},{10,59,1644},{12,43,2360},{9,41,1656},{8,63,6244},{2,51,1644},{3,42,17},{1,33,2308},{0,42,7575},{0,32,3345},{19,63,1761},
+{16,55,10},{17,43,125},{16,40,290},{43,1,5419},{0,52,1592},{3,42,13},{0,33,2225},{63,12,5419},{0,33,2225},{10,63,1585},{10,63,1585},{10,63,1585},{9,38,1576},{3,61,1156},{3,41,13},{3,41,13},{2,27,110},{0,31,2211},{0,25,699},{16,52,2},{16,52,2},{16,52,2},{16,34,2},{33,1,1152},{5,40,1},{5,40,1},{0,27,61},{63,2,1152},{0,27,61},{52,1,1568},{14,56,1},{21,42,1},
+{1,42,0},{52,1,1568},{46,30,1568},{1,42,0},{0,35,1568},{46,30,1568},{0,35,1568},{9,0,1576},{9,0,1576},{9,0,1576},{9,0,1576},{3,43,4},{3,43,4},{3,43,4},{3,23,4},{0,22,410},{0,22,410},{15,63,4826},{12,62,1650},{14,46,2355},{11,43,1660},{11,63,6452},{4,54,1641},{5,44,15},{3,35,2308},{0,45,7165},{0,35,2875},{22,63,1862},{18,57,9},{20,45,126},{18,42,281},{47,0,5419},
+{0,56,1568},{6,44,10},{0,35,2091},{46,24,5419},{0,35,2091},{12,63,1606},{12,63,1606},{12,63,1606},{12,40,1571},{5,63,1155},{5,44,14},{5,44,14},{4,29,109},{0,33,1977},{0,28,424},{19,53,4},{19,53,4},{19,53,4},{19,36,4},{31,12,1152},{7,42,1},{7,42,1},{0,30,29},{62,6,1152},{0,30,29},{56,0,1568},{17,58,1},{24,44,2},{3,44,2},{56,0,1568},{62,25,1568},{3,44,2},
+{0,37,1570},{62,25,1568},{0,37,1570},{12,0,1570},{12,0,1570},{12,0,1570},{12,0,1570},{5,46,1},{5,46,1},{5,46,1},{5,25,2},{0,25,260},{0,25,260},{17,63,5096},{14,63,1652},{15,48,2358},{13,45,1660},{14,63,6668},{6,56,1641},{7,46,15},{5,37,2308},{0,47,6891},{0,36,2543},{23,63,1956},{20,59,9},{22,47,126},{20,44,281},{49,1,5419},{2,58,1568},{8,46,10},{0,38,1979},{46,27,5419},
+{0,38,1979},{14,63,1651},{14,63,1651},{14,63,1651},{14,42,1571},{8,63,1179},{7,46,14},{7,46,14},{6,31,109},{0,38,1778},{0,31,232},{21,55,4},{21,55,4},{21,55,4},{21,38,4},{31,18,1152},{9,44,1},{9,44,1},{0,32,10},{62,9,1152},{0,32,10},{59,0,1568},{19,60,1},{26,46,2},{5,46,2},{59,0,1568},{62,28,1568},{5,46,2},{0,39,1570},{62,28,1568},{0,39,1570},{14,0,1570},
+{14,0,1570},{14,0,1570},{14,0,1570},{7,48,1},{7,48,1},{7,48,1},{7,27,2},{0,28,164},{0,28,164},{20,63,5352},{17,63,1708},{18,49,2360},{15,47,1660},{15,63,6877},{8,58,1641},{9,48,14},{7,39,2308},{0,50,6576},{0,39,2215},{26,63,2052},{22,61,9},{24,49,116},{22,46,281},{52,1,5419},{4,60,1568},{9,48,13},{0,40,1907},{46,30,5419},{0,40,1907},{16,63,1697},{16,63,1697},{16,63,1697},
+{16,44,1577},{10,63,1209},{9,48,14},{9,48,14},{8,33,115},{0,42,1601},{0,33,110},{23,57,4},{23,57,4},{23,57,4},{23,40,4},{34,17,1152},{11,46,1},{11,46,1},{0,34,2},{62,12,1152},{0,34,2},{62,0,1568},{21,62,1},{28,48,1},{7,48,0},{62,0,1568},{62,31,1568},{7,48,0},{0,41,1570},{62,31,1568},{0,41,1570},{16,0,1576},{16,0,1576},{16,0,1576},{16,0,1576},{9,50,1},
+{9,50,1},{9,50,1},{9,29,2},{0,33,85},{0,33,85},{23,63,5672},{19,63,1825},{20,51,2360},{17,49,1656},{19,63,7135},{10,60,1641},{11,50,14},{9,41,2308},{0,53,6336},{0,42,1983},{29,63,2180},{24,63,9},{26,51,116},{24,48,293},{55,1,5419},{6,62,1568},{11,50,13},{0,42,1814},{47,32,5419},{0,42,1814},{19,63,1761},{19,63,1761},{19,63,1761},{17,46,1576},{12,63,1249},{11,50,14},{11,50,14},
+{10,35,115},{0,45,1449},{0,36,30},{25,59,4},{25,59,4},{25,59,4},{25,42,4},{37,17,1152},{13,48,0},{13,48,0},{1,36,2},{62,15,1152},{1,36,2},{63,4,1568},{23,63,4},{30,50,1},{9,50,0},{63,4,1568},{62,34,1568},{9,50,0},{0,43,1570},{62,34,1568},{0,43,1570},{17,0,1576},{17,0,1576},{17,0,1576},{17,0,1576},{11,52,1},{11,52,1},{11,52,1},{11,31,2},{0,36,29},
+{0,36,29},{25,63,6066},{21,63,2039},{22,54,2355},{19,51,1660},{20,63,7420},{12,62,1635},{13,52,14},{11,43,2316},{0,57,6109},{0,44,1789},{31,63,2369},{27,63,38},{28,53,115},{26,50,286},{59,0,5419},{9,63,1577},{14,52,11},{0,44,1740},{62,28,5419},{0,44,1740},{21,63,1843},{21,63,1843},{21,63,1843},{20,48,1571},{15,63,1314},{13,52,13},{13,52,13},{12,37,116},{0,48,1329},{0,39,13},{27,62,1},
+{27,62,1},{27,62,1},{27,44,2},{49,0,1152},{15,50,2},{15,50,2},{4,38,4},{62,18,1152},{4,38,4},{63,11,1568},{27,63,37},{32,52,2},{12,52,1},{63,11,1568},{47,45,1568},{12,52,1},{0,45,1576},{47,45,1568},{0,45,1576},{20,0,1570},{20,0,1570},{20,0,1570},{20,0,1570},{13,54,1},{13,54,1},{13,54,1},{13,34,1},{0,40,4},{0,40,4},{28,63,6434},{23,63,2268},{24,56,2355},
+{21,53,1660},{23,63,7668},{14,63,1652},{15,54,14},{13,45,2316},{0,61,5924},{0,47,1685},{34,63,2502},{29,63,123},{30,55,115},{28,52,286},{62,0,5419},{13,63,1627},{16,54,10},{0,47,1676},{62,31,5419},{0,47,1676},{23,63,1907},{23,63,1907},{23,63,1907},{22,50,1571},{17,63,1395},{15,54,13},{15,54,13},{14,39,116},{0,51,1241},{2,41,13},{29,63,2},{29,63,2},{29,63,2},{29,46,2},{52,0,1152},
+{17,52,1},{17,52,1},{6,40,4},{62,21,1152},{6,40,4},{55,32,1568},{31,63,97},{34,54,2},{14,54,1},{55,32,1568},{46,48,1568},{14,54,1},{0,47,1576},{46,48,1568},{0,47,1576},{22,0,1570},{22,0,1570},{22,0,1570},{22,0,1570},{15,56,1},{15,56,1},{15,56,1},{15,36,1},{1,43,1},{1,43,1},{29,63,6756},{26,63,2548},{26,58,2355},{23,55,1660},{26,63,7948},{17,63,1716},{17,56,15},
+{15,47,2316},{0,63,5773},{0,49,1638},{37,63,2694},{32,63,262},{32,57,126},{30,54,286},{63,4,5419},{17,63,1715},{18,56,10},{0,49,1634},{62,34,5419},{0,49,1634},{25,63,2018},{25,63,2018},{25,63,2018},{24,52,1571},{20,63,1483},{17,56,14},{17,56,14},{16,41,109},{0,54,1185},{4,43,13},{31,63,17},{31,63,17},{31,63,17},{31,48,2},{55,0,1152},{19,54,1},{19,54,1},{8,42,4},{62,24,1152},
+{8,42,4},{58,32,1568},{34,63,169},{36,56,2},{15,56,2},{58,32,1568},{52,48,1568},{15,56,2},{0,49,1570},{52,48,1568},{0,49,1570},{24,0,1570},{24,0,1570},{24,0,1570},{24,0,1570},{17,58,1},{17,58,1},{17,58,1},{17,37,2},{3,45,1},{3,45,1},{31,63,7218},{29,63,2924},{28,60,2355},{25,57,1660},{29,63,8260},{20,63,1884},{19,58,15},{17,49,2308},{3,63,5933},{2,51,1638},{39,63,2892},
+{34,63,445},{34,59,126},{32,56,281},{63,10,5419},{21,63,1849},{20,58,10},{0,51,1606},{62,37,5419},{0,51,1606},{28,63,2130},{28,63,2130},{28,63,2130},{26,54,1571},{23,63,1603},{19,58,14},{19,58,14},{18,43,109},{0,58,1156},{6,45,13},{33,63,40},{33,63,40},{33,63,40},{33,50,4},{58,0,1152},{21,56,1},{21,56,1},{10,44,4},{62,27,1152},{10,44,4},{61,32,1568},{38,63,274},{38,58,2},
+{17,58,2},{61,32,1568},{58,48,1568},{17,58,2},{0,51,1570},{58,48,1568},{0,51,1570},{26,0,1570},{26,0,1570},{26,0,1570},{26,0,1570},{19,60,1},{19,60,1},{19,60,1},{19,39,2},{5,47,1},{5,47,1},{34,63,7586},{31,63,3453},{30,62,2357},{28,59,1668},{31,63,8699},{23,63,2180},{21,60,21},{19,51,2316},{7,63,6224},{4,53,1634},{42,63,3131},{37,63,722},{36,62,125},{34,58,278},{55,32,5419},
+{26,63,2052},{22,60,9},{0,53,1580},{46,48,5419},{0,53,1580},{30,63,2272},{30,63,2272},{30,63,2272},{28,56,1568},{25,63,1746},{21,60,17},{21,60,17},{21,45,113},{1,61,1154},{9,47,14},{36,63,74},{36,63,74},{36,63,74},{35,52,2},{53,16,1152},{23,59,1},{23,59,1},{11,47,1},{63,30,1152},{11,47,1},{63,35,1568},{43,63,433},{40,60,4},{20,60,4},{63,35,1568},{63,49,1568},{20,60,4},
+{0,53,1576},{63,49,1568},{0,53,1576},{28,0,1568},{28,0,1568},{28,0,1568},{28,0,1568},{21,63,0},{21,63,0},{21,63,0},{21,42,0},{7,49,1},{7,49,1},{37,63,8018},{34,63,3915},{32,63,2410},{30,61,1668},{34,63,8985},{26,63,2548},{23,62,21},{21,53,2316},{12,63,6555},{6,55,1634},{43,63,3345},{40,63,1026},{38,63,129},{36,60,278},{58,32,5419},{30,63,2274},{24,62,9},{0,55,1577},{52,48,5419},
+{0,55,1577},{32,63,2406},{32,63,2406},{32,63,2406},{30,58,1568},{28,63,1890},{23,62,17},{23,62,17},{23,47,113},{3,63,1154},{11,49,12},{38,63,125},{38,63,125},{38,63,125},{37,54,2},{56,16,1152},{25,61,1},{25,61,1},{14,48,5},{62,33,1152},{14,48,5},{63,41,1568},{46,63,585},{42,62,4},{22,62,4},{63,41,1568},{63,52,1568},{22,62,4},{0,55,1576},{63,52,1568},{0,55,1576},{30,0,1568},
+{30,0,1568},{30,0,1568},{30,0,1568},{23,63,4},{23,63,4},{23,63,4},{23,44,0},{9,51,1},{9,51,1},{39,63,7700},{35,63,4026},{34,63,2514},{32,62,1611},{37,63,8485},{29,63,2424},{26,63,20},{23,55,1896},{15,63,6115},{9,56,1308},{46,63,2973},{43,63,1034},{40,63,169},{37,61,194},{63,27,4803},{32,63,2024},{27,63,1},{2,57,1253},{63,45,4803},{2,57,1253},{34,63,2514},{34,63,2514},{34,63,2514},
+{32,60,1570},{29,63,2056},{26,63,20},{26,63,20},{24,49,116},{7,63,1164},{13,51,12},{40,63,169},{40,63,169},{40,63,169},{39,56,2},{59,16,1152},{27,63,1},{27,63,1},{16,50,4},{62,36,1152},{16,50,4},{63,45,1250},{48,63,500},{45,63,1},{26,63,0},{63,45,1250},{47,62,1250},{26,63,0},{0,57,1252},{47,62,1250},{0,57,1252},{32,0,1570},{32,0,1570},{32,0,1570},{32,0,1570},{26,63,20},
+{26,63,20},{26,63,20},{25,46,0},{11,53,1},{11,53,1},{40,63,7062},{37,63,3915},{37,63,2690},{34,63,1579},{37,63,7765},{30,63,2178},{28,63,77},{26,56,1437},{18,63,5499},{11,57,918},{48,63,2504},{44,63,945},{43,63,225},{40,62,89},{63,31,4056},{35,63,1656},{30,63,9},{6,58,885},{63,47,4056},{6,58,885},{37,63,2690},{37,63,2690},{37,63,2690},{34,62,1570},{33,63,2227},{28,63,77},{28,63,77},
+{26,51,116},{11,63,1227},{15,53,12},{43,63,225},{43,63,225},{43,63,225},{41,58,2},{62,16,1152},{30,63,9},{30,63,9},{18,52,4},{62,39,1152},{18,52,4},{63,47,884},{51,63,356},{47,63,4},{32,63,0},{63,47,884},{63,55,884},{32,63,0},{0,58,884},{63,55,884},{0,58,884},{34,0,1570},{34,0,1570},{34,0,1570},{34,0,1570},{28,63,41},{28,63,41},{28,63,41},{27,48,1},{13,55,1},
+{13,55,1},{43,63,6493},{40,63,3882},{39,63,2880},{36,63,1584},{40,63,6982},{34,63,1966},{31,63,206},{28,57,971},{23,63,4927},{14,59,562},{50,63,2070},{46,63,842},{46,63,313},{43,62,25},{63,35,3318},{38,63,1326},{34,63,45},{11,59,545},{63,49,3318},{11,59,545},{39,63,2880},{39,63,2880},{39,63,2880},{36,63,1584},{34,63,2434},{31,63,206},{31,63,206},{29,53,114},{15,63,1329},{17,55,14},{46,63,313},
+{46,63,313},{46,63,313},{43,61,0},{63,21,1152},{34,63,45},{34,63,45},{19,55,1},{63,42,1152},{19,55,1},{63,51,545},{54,63,225},{51,63,1},{39,63,0},{63,51,545},{63,57,545},{39,63,0},{0,59,545},{63,57,545},{0,59,545},{36,0,1568},{36,0,1568},{36,0,1568},{36,0,1568},{31,63,85},{31,63,85},{31,63,85},{29,50,1},{15,57,1},{15,57,1},{45,63,6113},{43,63,3938},{40,63,3065},
+{38,63,1649},{43,63,6422},{35,63,1878},{34,63,365},{30,59,651},{26,63,4495},{16,60,318},{51,63,1698},{48,63,794},{48,63,394},{45,63,0},{63,39,2753},{41,63,1094},{38,63,106},{15,60,313},{47,59,2753},{15,60,313},{40,63,3065},{40,63,3065},{40,63,3065},{38,63,1649},{37,63,2610},{34,63,365},{34,63,365},{31,55,114},{20,63,1483},{19,57,14},{48,63,394},{48,63,394},{48,63,394},{45,63,0},{63,27,1152},
+{38,63,106},{38,63,106},{21,57,1},{63,45,1152},{21,57,1},{63,54,313},{55,63,130},{54,63,1},{45,63,0},{63,54,313},{62,59,313},{45,63,0},{0,60,313},{62,59,313},{0,60,313},{38,0,1568},{38,0,1568},{38,0,1568},{38,0,1568},{33,63,128},{33,63,128},{33,63,128},{31,52,1},{17,59,1},{17,59,1},{46,63,5677},{43,63,3954},{43,63,3225},{40,63,1764},{45,63,5985},{37,63,1830},{37,63,605},
+{32,60,410},{29,63,4159},{19,61,146},{53,63,1454},{51,63,770},{50,63,493},{47,63,25},{63,43,2273},{44,63,926},{41,63,194},{19,61,145},{63,53,2273},{19,61,145},{43,63,3225},{43,63,3225},{43,63,3225},{40,63,1764},{40,63,2818},{37,63,605},{37,63,605},{33,57,113},{23,63,1659},{21,59,14},{50,63,493},{50,63,493},{50,63,493},{47,63,25},{63,33,1152},{41,63,194},{41,63,194},{23,59,1},{47,56,1152},
+{23,59,1},{63,57,145},{58,63,58},{57,63,1},{50,63,1},{63,57,145},{63,60,145},{50,63,1},{0,61,145},{63,60,145},{0,61,145},{40,0,1568},{40,0,1568},{40,0,1568},{40,0,1568},{34,63,185},{34,63,185},{34,63,185},{33,54,0},{19,61,1},{19,61,1},{48,63,5379},{46,63,3978},{46,63,3449},{43,63,1924},{46,63,5542},{40,63,1870},{38,63,890},{34,61,225},{32,63,3919},{22,62,43},{54,63,1242},
+{53,63,809},{51,63,610},{49,63,101},{63,47,1878},{48,63,810},{44,63,314},{23,62,41},{63,55,1878},{23,62,41},{46,63,3449},{46,63,3449},{46,63,3449},{43,63,1924},{43,63,3058},{38,63,890},{38,63,890},{35,59,113},{27,63,1889},{23,61,14},{51,63,610},{51,63,610},{51,63,610},{49,63,101},{63,39,1152},{44,63,314},{44,63,314},{25,61,1},{47,59,1152},{25,61,1},{63,60,41},{60,63,17},{60,63,1},
+{56,63,1},{63,60,41},{62,62,41},{56,63,1},{0,62,41},{62,62,41},{0,62,41},{42,0,1568},{42,0,1568},{42,0,1568},{42,0,1568},{37,63,233},{37,63,233},{37,63,233},{35,56,0},{21,63,1},{21,63,1},{50,63,5170},{48,63,4080},{48,63,3680},{46,63,2195},{48,63,5200},{43,63,2023},{41,63,1269},{37,62,133},{35,63,3772},{25,63,17},{57,63,1088},{55,63,861},{54,63,720},{52,63,241},{63,51,1536},
+{51,63,768},{49,63,461},{28,63,0},{63,57,1536},{28,63,0},{48,63,3680},{48,63,3680},{48,63,3680},{46,63,2195},{46,63,3345},{41,63,1269},{41,63,1269},{37,61,114},{32,63,2200},{25,63,17},{54,63,720},{54,63,720},{54,63,720},{52,63,241},{61,49,1152},{49,63,461},{49,63,461},{28,63,0},{63,54,1152},{28,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},
+{0,63,0},{63,63,0},{0,63,0},{44,0,1570},{44,0,1570},{44,0,1570},{44,0,1570},{40,63,317},{40,63,317},{40,63,317},{37,58,2},{25,63,17},{25,63,17},{51,63,4416},{50,63,3629},{48,63,3296},{47,63,2070},{50,63,4411},{46,63,1823},{43,63,1150},{39,63,50},{38,63,3132},{29,63,52},{57,63,768},{57,63,576},{56,63,505},{54,63,160},{63,53,1068},{54,63,544},{51,63,320},{33,63,1},{63,58,1068},
+{33,63,1},{48,63,3296},{48,63,3296},{48,63,3296},{47,63,2070},{46,63,2881},{43,63,1150},{43,63,1150},{39,62,42},{34,63,1846},{29,63,52},{56,63,505},{56,63,505},{56,63,505},{54,63,160},{63,48,800},{51,63,320},{51,63,320},{33,63,1},{62,56,800},{33,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{46,0,1570},
+{46,0,1570},{46,0,1570},{46,0,1570},{42,63,410},{42,63,410},{42,63,410},{39,60,2},{29,63,52},{29,63,52},{53,63,3826},{51,63,3136},{51,63,2880},{49,63,1961},{51,63,3648},{46,63,1615},{46,63,1086},{41,63,5},{41,63,2588},{32,63,116},{59,63,498},{57,63,384},{57,63,320},{56,63,116},{63,55,683},{55,63,342},{54,63,208},{39,63,1},{63,59,683},{39,63,1},{51,63,2880},{51,63,2880},{51,63,2880},
+{49,63,1961},{48,63,2448},{46,63,1086},{46,63,1086},{41,63,5},{37,63,1558},{32,63,116},{57,63,320},{57,63,320},{57,63,320},{56,63,116},{63,51,512},{54,63,208},{54,63,208},{39,63,1},{63,57,512},{39,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{48,0,1568},{48,0,1568},{48,0,1568},{48,0,1568},{45,63,514},
+{45,63,514},{45,63,514},{41,62,2},{32,63,116},{32,63,116},{54,63,3232},{53,63,2781},{53,63,2585},{51,63,1856},{53,63,3067},{48,63,1456},{48,63,1056},{43,63,10},{44,63,2140},{35,63,212},{60,63,272},{59,63,221},{59,63,185},{57,63,64},{63,57,384},{57,63,192},{55,63,125},{45,63,1},{63,60,384},{45,63,1},{53,63,2585},{53,63,2585},{53,63,2585},{51,63,1856},{51,63,2112},{48,63,1056},{48,63,1056},
+{43,63,10},{40,63,1334},{35,63,212},{59,63,185},{59,63,185},{59,63,185},{57,63,64},{63,54,288},{55,63,125},{55,63,125},{45,63,1},{62,59,288},{45,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{50,0,1568},{50,0,1568},{50,0,1568},{50,0,1568},{46,63,605},{46,63,605},{46,63,605},{43,63,10},{35,63,212},
+{35,63,212},{0,51,2665},{0,36,306},{0,26,5},{0,22,965},{0,34,5885},{0,22,3726},{0,21,1754},{0,14,4398},{0,16,6359},{0,13,4722},{0,51,2665},{0,36,306},{0,26,5},{0,22,965},{17,0,5885},{0,22,3726},{0,21,1754},{0,14,4398},{34,0,5885},{0,14,4398},{0,25,0},{0,25,0},{0,25,0},{0,12,1},{0,12,545},{0,11,212},{0,11,212},{0,6,337},{0,5,605},{0,5,374},{0,25,0},
+{0,25,0},{0,25,0},{0,12,1},{6,0,545},{0,11,212},{0,11,212},{0,6,337},{12,0,545},{0,6,337},{26,0,2665},{0,36,306},{0,26,5},{0,22,965},{26,0,2665},{51,0,2665},{0,22,965},{0,17,2665},{51,0,2665},{0,17,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,57,2665},{0,39,202},{0,29,13},
+{0,24,818},{0,39,6669},{0,25,3974},{0,22,1790},{0,16,4826},{0,18,7285},{0,16,5267},{0,57,2665},{0,39,202},{0,29,13},{0,24,818},{19,1,6669},{0,25,3974},{0,22,1790},{0,16,4826},{39,0,6669},{0,16,4826},{0,31,0},{0,31,0},{0,31,0},{0,15,1},{0,15,841},{0,12,337},{0,12,337},{0,7,493},{0,7,934},{0,7,574},{0,31,0},{0,31,0},{0,31,0},{0,15,1},{8,0,841},
+{0,12,337},{0,12,337},{0,7,493},{15,0,841},{0,7,493},{29,0,2665},{0,39,202},{1,28,2},{0,24,818},{29,0,2665},{57,0,2665},{0,24,818},{0,19,2665},{57,0,2665},{0,19,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,63,2665},{0,44,116},{1,31,66},{0,27,698},{0,42,7541},{0,28,4254},{0,25,1854},
+{0,18,5281},{0,19,8271},{0,16,5795},{0,63,2665},{0,44,116},{1,31,50},{0,27,698},{15,13,7538},{0,28,4254},{0,25,1854},{0,18,5281},{31,6,7538},{0,18,5281},{0,36,1},{0,36,1},{0,36,1},{0,18,1},{0,18,1201},{0,14,468},{0,14,468},{0,8,730},{0,8,1325},{0,8,830},{0,36,1},{0,36,1},{0,36,1},{0,18,1},{9,0,1201},{0,14,468},{0,14,468},{0,8,730},{18,0,1201},
+{0,8,730},{32,0,2665},{0,44,116},{3,30,2},{0,27,698},{32,0,2665},{63,0,2665},{0,27,698},{0,21,2665},{63,0,2665},{0,21,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,63,2781},{0,47,52},{1,33,148},{0,29,610},{0,46,8493},{0,31,4566},{0,27,1962},{0,18,5809},{0,22,9367},{0,18,6385},{2,63,2753},
+{0,47,52},{2,33,129},{0,29,610},{23,0,8493},{0,31,4566},{0,27,1962},{0,18,5809},{46,0,8493},{0,18,5809},{0,42,1},{0,42,1},{0,42,1},{0,21,1},{0,21,1625},{0,16,637},{0,16,637},{0,10,965},{0,10,1806},{0,10,1134},{0,42,1},{0,42,1},{0,42,1},{0,21,1},{11,0,1625},{0,16,637},{0,16,637},{0,10,965},{21,0,1625},{0,10,965},{35,0,2665},{0,47,52},{5,32,1},
+{0,29,610},{35,0,2665},{63,3,2665},{0,29,610},{0,23,2665},{63,3,2665},{0,23,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,63,3105},{0,51,10},{1,35,297},{0,32,481},{0,51,9670},{0,33,4965},{0,30,2120},{0,21,6413},{0,24,10749},{0,19,7191},{3,63,2989},{0,51,10},{2,36,257},{0,32,481},{25,1,9669},
+{0,33,4965},{0,30,2120},{0,21,6413},{47,2,9669},{0,21,6413},{0,49,0},{0,49,0},{0,49,0},{0,25,1},{0,25,2178},{0,19,850},{0,19,850},{0,11,1325},{0,11,2406},{0,10,1521},{0,49,0},{0,49,0},{0,49,0},{0,25,1},{12,1,2178},{0,19,850},{0,19,850},{0,11,1325},{25,0,2178},{0,11,1325},{38,0,2665},{0,51,10},{8,34,2},{0,32,481},{38,0,2665},{62,7,2665},{0,32,481},
+{0,25,2669},{62,7,2665},{0,25,2669},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,63,3437},{1,54,33},{3,37,425},{1,33,457},{0,57,9670},{0,36,4629},{0,31,1654},{0,24,6165},{0,26,11014},{0,22,7031},{6,63,3101},{2,53,10},{4,38,257},{1,33,441},{28,1,9669},{0,36,4629},{0,31,1654},{0,24,6165},{47,5,9669},
+{0,24,6165},{1,53,32},{1,53,32},{1,53,32},{1,27,32},{0,31,2178},{0,22,666},{0,22,666},{0,13,1160},{0,14,2534},{0,13,1449},{2,51,0},{2,51,0},{2,51,0},{2,27,1},{15,1,2178},{0,22,666},{0,22,666},{0,13,1160},{31,0,2178},{0,13,1160},{41,0,2665},{1,54,1},{10,36,2},{0,33,394},{41,0,2665},{62,10,2665},{0,33,394},{0,27,2669},{62,10,2665},{0,27,2669},{1,0,32},
+{1,0,32},{1,0,32},{1,0,32},{0,6,0},{0,6,0},{0,6,0},{0,3,0},{0,2,13},{0,2,13},{6,63,3917},{2,57,129},{3,40,609},{1,36,497},{0,63,9670},{0,39,4325},{0,33,1274},{0,25,5878},{0,28,11299},{0,24,6917},{8,63,3233},{4,55,10},{6,40,257},{3,35,441},{31,1,9669},{0,39,4325},{0,33,1274},{0,25,5878},{47,8,9669},{0,25,5878},{2,57,128},{2,57,128},{2,57,128},
+{2,30,129},{0,36,2180},{0,28,490},{0,28,490},{0,16,1018},{0,16,2691},{0,14,1441},{4,53,0},{4,53,0},{4,53,0},{4,29,1},{15,7,2178},{0,28,490},{0,28,490},{0,16,1018},{31,3,2178},{0,16,1018},{44,0,2665},{3,56,1},{12,38,2},{0,36,306},{44,0,2665},{62,13,2665},{0,36,306},{0,29,2669},{62,13,2665},{0,29,2669},{2,0,128},{2,0,128},{2,0,128},{2,0,128},{0,12,0},
+{0,12,0},{0,12,0},{0,6,0},{0,5,45},{0,5,45},{6,63,4541},{3,59,297},{5,42,865},{3,38,625},{2,63,9749},{0,45,4021},{0,36,914},{0,27,5581},{0,31,11611},{0,27,6877},{11,63,3377},{6,57,10},{8,42,257},{5,37,441},{34,0,9669},{0,45,4021},{0,36,914},{0,27,5581},{47,11,9669},{0,27,5581},{3,61,288},{3,61,288},{3,61,288},{3,32,288},{0,42,2180},{0,31,338},{0,31,338},
+{0,18,865},{0,19,2875},{0,16,1427},{6,55,0},{6,55,0},{6,55,0},{6,31,1},{15,13,2178},{0,31,338},{0,31,338},{0,18,865},{31,6,2178},{0,18,865},{47,0,2665},{5,58,1},{14,40,2},{0,38,225},{47,0,2665},{62,16,2665},{0,38,225},{0,31,2669},{62,16,2665},{0,31,2669},{3,0,288},{3,0,288},{3,0,288},{3,0,288},{0,18,0},{0,18,0},{0,18,0},{0,9,0},{0,8,109},
+{0,8,109},{9,63,5374},{4,62,570},{6,44,1269},{4,40,841},{3,63,10021},{0,47,3745},{0,39,593},{0,30,5294},{0,36,12029},{0,28,6810},{14,63,3558},{8,59,9},{10,44,254},{7,39,446},{37,1,9669},{0,47,3745},{0,39,593},{0,30,5294},{63,6,9669},{0,30,5294},{4,63,561},{4,63,561},{4,63,561},{4,35,546},{0,49,2178},{0,34,218},{0,34,218},{0,21,725},{0,22,3117},{0,19,1433},{8,58,1},
+{8,58,1},{8,58,1},{8,33,2},{24,1,2178},{0,34,218},{0,34,218},{0,21,725},{49,0,2178},{0,21,725},{50,0,2665},{7,60,1},{16,42,5},{0,41,157},{50,0,2665},{62,19,2665},{0,41,157},{0,33,2669},{62,19,2665},{0,33,2669},{4,0,545},{4,0,545},{4,0,545},{4,0,545},{0,25,0},{0,25,0},{0,25,0},{0,12,1},{0,11,212},{0,11,212},{11,63,6350},{6,63,905},{7,47,1678},
+{4,42,1102},{6,63,10453},{0,50,3485},{0,42,361},{0,32,5054},{0,36,12429},{0,31,6794},{15,63,3710},{10,61,9},{12,46,254},{9,41,446},{40,1,9669},{0,50,3485},{0,42,361},{0,32,5054},{63,9,9669},{0,32,5054},{6,63,901},{6,63,901},{6,63,901},{5,37,842},{0,55,2178},{0,38,125},{0,38,125},{0,24,629},{0,25,3365},{0,22,1489},{10,60,1},{10,60,1},{10,60,1},{10,35,2},{27,1,2178},
+{0,38,125},{0,38,125},{0,24,629},{55,0,2178},{0,24,629},{53,0,2665},{9,62,1},{18,44,5},{0,43,117},{53,0,2665},{62,22,2665},{0,43,117},{0,35,2669},{62,22,2665},{0,35,2669},{5,0,841},{5,0,841},{5,0,841},{5,0,841},{0,31,0},{0,31,0},{0,31,0},{0,15,1},{0,12,337},{0,12,337},{12,63,7350},{7,63,1450},{9,48,2190},{6,44,1422},{6,63,11045},{0,53,3293},{0,45,193},
+{0,35,4870},{0,39,12829},{0,32,6807},{17,63,3905},{12,63,9},{14,48,267},{11,43,446},{43,1,9669},{0,53,3293},{0,45,193},{0,35,4870},{63,12,9669},{0,35,4870},{7,63,1369},{7,63,1369},{7,63,1369},{6,40,1202},{0,61,2178},{0,42,53},{0,42,53},{0,25,520},{0,28,3645},{0,24,1573},{12,62,1},{12,62,1},{12,62,1},{12,37,2},{30,1,2178},{0,42,53},{0,42,53},{0,25,520},{61,0,2178},
+{0,25,520},{56,0,2665},{12,63,8},{20,46,5},{0,45,72},{56,0,2665},{62,25,2665},{0,45,72},{0,37,2669},{62,25,2665},{0,37,2669},{6,0,1201},{6,0,1201},{6,0,1201},{6,0,1201},{0,36,1},{0,36,1},{0,36,1},{0,18,1},{0,14,468},{0,14,468},{14,63,8614},{9,63,2129},{9,51,2758},{6,47,1822},{9,63,11765},{0,57,3125},{0,47,81},{0,36,4629},{0,42,13261},{0,35,6855},{20,63,4081},
+{15,63,49},{16,50,257},{13,45,446},{46,1,9669},{0,57,3125},{0,47,81},{0,36,4629},{63,15,9669},{0,36,4629},{9,63,1933},{9,63,1933},{9,63,1933},{7,42,1626},{1,63,2212},{0,45,13},{0,45,13},{0,27,421},{0,31,3957},{0,25,1673},{14,63,2},{14,63,2},{14,63,2},{14,39,2},{33,1,2178},{0,45,13},{0,45,13},{0,27,421},{63,2,2178},{0,27,421},{59,0,2665},{15,63,40},{22,48,2},
+{0,47,45},{59,0,2665},{62,28,2665},{0,47,45},{0,39,2669},{62,28,2665},{0,39,2669},{7,0,1625},{7,0,1625},{7,0,1625},{7,0,1625},{0,42,1},{0,42,1},{0,42,1},{0,21,1},{0,16,637},{0,16,637},{15,63,10085},{11,63,3185},{11,53,3481},{8,49,2337},{11,63,12845},{0,62,2958},{0,50,14},{0,38,4381},{0,45,13802},{0,36,6942},{23,63,4318},{17,63,154},{18,52,254},{14,48,456},{49,1,9669},
+{0,62,2958},{0,50,14},{0,38,4381},{46,27,9669},{0,38,4381},{10,63,2717},{10,63,2717},{10,63,2717},{8,45,2180},{3,63,2394},{0,49,0},{0,49,0},{0,30,317},{0,33,4314},{0,28,1811},{17,63,10},{17,63,10},{17,63,10},{16,41,1},{31,12,2178},{0,49,0},{0,49,0},{0,30,317},{62,6,2178},{0,30,317},{62,1,2665},{20,63,113},{24,50,4},{0,50,13},{62,1,2665},{63,31,2665},{0,50,13},
+{0,42,2669},{63,31,2665},{0,42,2669},{8,0,2180},{8,0,2180},{8,0,2180},{8,0,2180},{0,49,0},{0,49,0},{0,49,0},{0,25,1},{0,19,850},{0,19,850},{17,63,11454},{12,63,4143},{12,55,4141},{9,51,2805},{12,63,13803},{0,63,2871},{1,52,18},{0,41,4182},{0,50,14186},{0,39,6911},{26,63,4550},{20,63,306},{20,54,254},{17,49,446},{52,1,9669},{0,63,2870},{1,52,9},{0,41,4181},{46,30,9669},
+{0,41,4181},{12,63,3414},{12,63,3414},{12,63,3414},{9,47,2673},{3,63,2691},{1,52,14},{1,52,14},{0,32,245},{0,36,4587},{0,31,1906},{19,63,25},{19,63,25},{19,63,25},{18,43,1},{31,18,2178},{2,51,0},{2,51,0},{0,32,244},{62,9,2178},{0,32,244},{63,5,2665},{23,63,193},{26,52,4},{0,52,4},{63,5,2665},{63,34,2665},{0,52,4},{0,44,2669},{63,34,2665},{0,44,2669},{9,0,2669},
+{9,0,2669},{9,0,2669},{9,0,2669},{0,55,1},{0,55,1},{0,55,1},{0,28,2},{0,22,1009},{0,22,1009},{20,63,11990},{15,63,4575},{14,57,4141},{11,53,2805},{15,63,14195},{3,63,3015},{3,54,18},{0,43,4122},{0,53,13674},{0,41,6249},{29,63,4814},{23,63,522},{22,56,254},{19,51,446},{55,1,9669},{3,63,3006},{3,54,9},{0,43,4041},{47,32,9669},{0,43,4041},{14,63,3561},{14,63,3561},{14,63,3561},
+{11,49,2670},{6,63,2795},{3,54,14},{3,54,14},{2,34,245},{0,39,4227},{0,33,1470},{21,63,58},{21,63,58},{21,63,58},{20,45,1},{34,17,2178},{4,53,0},{4,53,0},{0,35,180},{62,12,2178},{0,35,180},{63,11,2665},{26,63,305},{28,54,4},{2,54,4},{63,11,2665},{63,37,2665},{2,54,4},{0,46,2669},{63,37,2665},{0,46,2669},{11,0,2669},{11,0,2669},{11,0,2669},{11,0,2669},{2,57,1},
+{2,57,1},{2,57,1},{2,30,2},{0,25,801},{0,25,801},{22,63,12554},{17,63,5066},{16,59,4118},{13,55,2805},{17,63,14614},{6,63,3255},{5,56,18},{1,45,4078},{0,56,13194},{0,44,5633},{31,63,5090},{26,63,802},{24,58,254},{21,53,446},{58,1,9669},{7,63,3198},{5,56,9},{0,45,3846},{53,32,9669},{0,45,3846},{15,63,3710},{15,63,3710},{15,63,3710},{13,51,2670},{9,63,2931},{5,56,14},{5,56,14},
+{4,36,245},{0,42,3899},{0,36,1110},{23,63,90},{23,63,90},{23,63,90},{22,47,1},{37,17,2178},{6,55,0},{6,55,0},{0,37,136},{62,15,2178},{0,37,136},{63,17,2665},{30,63,442},{30,56,4},{4,56,4},{63,17,2665},{63,40,2665},{4,56,4},{0,47,2677},{63,40,2665},{0,47,2677},{13,0,2669},{13,0,2669},{13,0,2669},{13,0,2669},{4,59,1},{4,59,1},{4,59,1},{4,31,5},{0,28,625},
+{0,28,625},{23,63,13130},{20,63,5706},{18,61,4122},{15,57,2807},{20,63,15102},{9,63,3625},{7,59,15},{3,47,4086},{0,59,12686},{0,47,5027},{34,63,5386},{29,63,1169},{26,60,257},{23,56,446},{62,0,9669},{12,63,3469},{7,59,11},{0,47,3658},{62,31,9669},{0,47,3658},{17,63,3905},{17,63,3905},{17,63,3905},{16,53,2677},{12,63,3112},{7,58,9},{7,58,9},{6,38,246},{0,45,3576},{0,38,755},{26,63,136},
+{26,63,136},{26,63,136},{24,49,4},{49,0,2178},{8,57,2},{8,57,2},{0,39,85},{62,18,2178},{0,39,85},{63,23,2665},{34,63,628},{32,59,2},{4,59,2},{63,23,2665},{63,43,2665},{4,59,2},{0,50,2669},{63,43,2665},{0,50,2669},{15,0,2677},{15,0,2677},{15,0,2677},{15,0,2677},{7,60,4},{7,60,4},{7,60,4},{7,33,5},{0,33,424},{0,33,424},{26,63,13650},{23,63,6378},{20,63,4122},
+{17,59,2799},{23,63,15558},{12,63,4065},{9,61,15},{6,49,4074},{0,62,12278},{0,49,4534},{36,63,5698},{30,63,1556},{28,62,257},{25,58,446},{63,4,9669},{15,63,3749},{9,61,11},{0,49,3510},{62,34,9669},{0,49,3510},{20,63,4041},{20,63,4041},{20,63,4041},{17,56,2670},{15,63,3304},{9,60,9},{9,60,9},{8,40,246},{0,50,3317},{0,41,499},{29,63,200},{29,63,200},{29,63,200},{26,51,4},{52,0,2178},
+{10,59,2},{10,59,2},{0,42,45},{62,21,2178},{0,42,45},{63,29,2665},{37,63,820},{34,61,2},{6,61,2},{63,29,2665},{63,46,2665},{6,61,2},{0,52,2669},{63,46,2665},{0,52,2669},{17,0,2669},{17,0,2669},{17,0,2669},{17,0,2669},{9,62,4},{9,62,4},{9,62,4},{9,35,5},{0,36,296},{0,36,296},{29,63,14234},{23,63,7050},{23,63,4242},{19,61,2799},{26,63,16046},{15,63,4601},{11,63,15},
+{8,51,4074},{0,63,12051},{0,50,4110},{37,63,6002},{34,63,1989},{31,63,270},{27,60,446},{63,10,9669},{20,63,4081},{11,63,11},{0,52,3374},{62,37,9669},{0,52,3374},{23,63,4241},{23,63,4241},{23,63,4241},{19,58,2670},{17,63,3485},{11,62,9},{11,62,9},{10,42,246},{0,53,3069},{0,43,306},{31,63,269},{31,63,269},{31,63,269},{28,53,4},{55,0,2178},{12,61,2},{12,61,2},{0,44,18},{62,24,2178},
+{0,44,18},{63,35,2665},{41,63,1037},{36,63,2},{8,63,2},{63,35,2665},{63,49,2665},{8,63,2},{0,54,2669},{63,49,2665},{0,54,2669},{19,0,2669},{19,0,2669},{19,0,2669},{19,0,2669},{11,63,5},{11,63,5},{11,63,5},{11,37,5},{0,40,193},{0,40,193},{31,63,13639},{26,63,7005},{25,63,4454},{21,62,2721},{28,63,15204},{17,63,4285},{13,63,24},{9,52,3457},{0,63,11020},{0,52,3109},{40,63,5381},
+{34,63,1890},{33,63,346},{29,61,296},{62,16,8712},{23,63,3636},{14,63,2},{0,53,2676},{62,39,8712},{0,53,2676},{25,63,4454},{25,63,4454},{25,63,4454},{21,60,2670},{19,63,3707},{13,63,24},{13,63,24},{12,44,246},{0,56,2853},{0,45,153},{33,63,346},{33,63,346},{33,63,346},{30,55,4},{58,0,2178},{14,63,2},{14,63,2},{0,46,10},{62,27,2178},{0,46,10},{63,39,2178},{44,63,872},{39,63,1},
+{14,63,1},{63,39,2178},{47,59,2178},{14,63,1},{0,55,2180},{47,59,2178},{0,55,2180},{21,0,2669},{21,0,2669},{21,0,2669},{21,0,2669},{13,63,20},{13,63,20},{13,63,20},{13,39,5},{0,45,104},{0,45,104},{33,63,12766},{29,63,6930},{26,63,4694},{24,63,2685},{29,63,14014},{20,63,3898},{16,63,101},{13,53,2722},{3,63,10057},{0,54,2129},{43,63,4689},{37,63,1718},{36,63,452},{32,62,164},{63,19,7578},
+{26,63,3078},{18,63,17},{0,55,1905},{63,41,7578},{0,55,1905},{26,63,4694},{26,63,4694},{26,63,4694},{24,61,2670},{22,63,3960},{16,63,101},{16,63,101},{14,47,242},{0,59,2650},{0,48,49},{36,63,452},{36,63,452},{36,63,452},{33,57,4},{53,16,2178},{18,63,17},{18,63,17},{0,49,1},{63,30,2178},{0,49,1},{63,42,1625},{46,63,650},{42,63,0},{21,63,0},{63,42,1625},{62,53,1625},{21,63,0},
+{0,56,1625},{62,53,1625},{0,56,1625},{24,0,2669},{24,0,2669},{24,0,2669},{24,0,2669},{15,63,50},{15,63,50},{15,63,50},{15,42,2},{0,48,40},{0,48,40},{34,63,11970},{31,63,6969},{29,63,4878},{26,63,2670},{31,63,13161},{21,63,3638},{18,63,229},{15,55,2146},{6,63,9313},{0,56,1410},{43,63,4097},{40,63,1614},{37,63,541},{34,62,69},{58,32,6661},{29,63,2654},{21,63,65},{0,56,1346},{52,48,6661},
+{0,56,1346},{29,63,4878},{29,63,4878},{29,63,4878},{26,63,2670},{23,63,4206},{18,63,229},{18,63,229},{15,49,242},{0,62,2506},{0,51,9},{37,63,541},{37,63,541},{37,63,541},{35,59,4},{56,16,2178},{21,63,65},{21,63,65},{2,51,1},{62,33,2178},{2,51,1},{63,45,1201},{48,63,481},{45,63,0},{27,63,0},{63,45,1201},{63,54,1201},{27,63,0},{0,57,1201},{63,54,1201},{0,57,1201},{26,0,2669},
+{26,0,2669},{26,0,2669},{26,0,2669},{17,63,85},{17,63,85},{17,63,85},{16,44,4},{0,51,8},{0,51,8},{37,63,11370},{33,63,6958},{31,63,5145},{28,63,2718},{34,63,12263},{23,63,3410},{21,63,405},{17,56,1665},{9,63,8665},{0,57,905},{46,63,3585},{43,63,1574},{40,63,637},{36,63,20},{63,27,5829},{32,63,2294},{26,63,130},{0,57,901},{63,45,5829},{0,57,901},{31,63,5145},{31,63,5145},{31,63,5145},
+{28,63,2718},{26,63,4430},{21,63,405},{21,63,405},{18,50,246},{0,63,2520},{2,53,9},{40,63,637},{40,63,637},{40,63,637},{37,61,4},{59,16,2178},{26,63,130},{26,63,130},{4,53,1},{62,36,2178},{4,53,1},{63,48,841},{51,63,337},{48,63,1},{33,63,0},{63,48,841},{62,56,841},{33,63,0},{0,58,841},{62,56,841},{0,58,841},{28,0,2669},{28,0,2669},{28,0,2669},{28,0,2669},{20,63,117},
+{20,63,117},{20,63,117},{18,46,4},{1,54,1},{1,54,1},{37,63,10794},{34,63,6895},{34,63,5374},{30,63,2813},{36,63,11574},{26,63,3274},{23,63,622},{19,57,1222},{13,63,8106},{1,59,562},{48,63,3170},{43,63,1494},{43,63,765},{39,63,4},{63,31,5082},{34,63,1998},{29,63,218},{0,59,554},{63,47,5082},{0,59,554},{34,63,5374},{34,63,5374},{34,63,5374},{30,63,2813},{29,63,4686},{23,63,622},{23,63,622},
+{20,52,246},{4,63,2714},{4,55,9},{43,63,765},{43,63,765},{43,63,765},{39,63,4},{62,16,2178},{29,63,218},{29,63,218},{6,55,1},{62,39,2178},{6,55,1},{63,51,545},{54,63,225},{51,63,1},{39,63,0},{63,51,545},{63,57,545},{39,63,0},{0,59,545},{63,57,545},{0,59,545},{30,0,2669},{30,0,2669},{30,0,2669},{30,0,2669},{22,63,180},{22,63,180},{22,63,180},{21,47,5},{3,56,1},
+{3,56,1},{40,63,10197},{37,63,6930},{36,63,5678},{32,63,2993},{37,63,10780},{29,63,3229},{26,63,945},{21,59,853},{17,63,7593},{4,60,293},{48,63,2756},{46,63,1454},{45,63,914},{41,63,37},{63,35,4344},{38,63,1740},{32,63,360},{2,60,289},{63,49,4344},{2,60,289},{36,63,5678},{36,63,5678},{36,63,5678},{32,63,2993},{31,63,5067},{26,63,945},{26,63,945},{22,55,242},{9,63,2979},{6,57,10},{45,63,914},
+{45,63,914},{45,63,914},{41,63,37},{63,21,2178},{32,63,360},{32,63,360},{8,57,1},{63,42,2178},{8,57,1},{63,54,288},{55,63,125},{54,63,0},{45,63,1},{63,54,288},{62,59,288},{45,63,1},{0,60,288},{62,59,288},{0,60,288},{32,0,2669},{32,0,2669},{32,0,2669},{32,0,2669},{25,63,250},{25,63,250},{25,63,250},{23,50,2},{5,59,2},{5,59,2},{43,63,9837},{40,63,7042},{37,63,5945},
+{34,63,3198},{40,63,10204},{32,63,3344},{29,63,1289},{24,59,589},{20,63,7225},{7,61,130},{51,63,2436},{48,63,1460},{48,63,1060},{43,63,122},{63,39,3779},{41,63,1580},{37,63,505},{6,61,129},{47,59,3779},{6,61,129},{37,63,5945},{37,63,5945},{37,63,5945},{34,63,3198},{34,63,5304},{29,63,1289},{29,63,1289},{24,57,242},{13,63,3261},{8,59,10},{48,63,1060},{48,63,1060},{48,63,1060},{43,63,122},{63,27,2178},
+{37,63,505},{37,63,505},{10,59,1},{63,45,2178},{10,59,1},{63,57,128},{58,63,53},{57,63,0},{51,63,0},{63,57,128},{63,60,128},{51,63,0},{0,61,128},{63,60,128},{0,61,128},{34,0,2669},{34,0,2669},{34,0,2669},{34,0,2669},{27,63,337},{27,63,337},{27,63,337},{25,52,2},{7,61,2},{7,61,2},{43,63,9437},{40,63,7154},{40,63,6193},{37,63,3454},{42,63,9783},{34,63,3398},{32,63,1740},
+{26,61,397},{23,63,6953},{9,62,37},{53,63,2246},{51,63,1508},{50,63,1213},{46,63,250},{63,43,3299},{44,63,1484},{40,63,673},{10,62,33},{63,53,3299},{10,62,33},{40,63,6193},{40,63,6193},{40,63,6193},{37,63,3454},{37,63,5624},{32,63,1740},{32,63,1740},{26,59,242},{17,63,3589},{10,61,10},{50,63,1213},{50,63,1213},{50,63,1213},{46,63,250},{63,33,2178},{40,63,673},{40,63,673},{12,61,1},{47,56,2178},
+{12,61,1},{63,60,32},{61,63,13},{60,63,0},{57,63,0},{63,60,32},{62,62,32},{57,63,0},{0,62,32},{62,62,32},{0,62,32},{36,0,2669},{36,0,2669},{36,0,2669},{36,0,2669},{29,63,405},{29,63,405},{29,63,405},{27,54,2},{9,63,2},{9,63,2},{46,63,9141},{43,63,7234},{43,63,6505},{40,63,3806},{43,63,9340},{37,63,3622},{34,63,2149},{27,62,277},{27,63,6772},{12,63,10},{54,63,2052},
+{53,63,1601},{51,63,1348},{48,63,436},{63,47,2904},{47,63,1452},{44,63,872},{14,63,1},{63,55,2904},{14,63,1},{43,63,6505},{43,63,6505},{43,63,6505},{40,63,3806},{40,63,5976},{34,63,2149},{34,63,2149},{28,61,242},{21,63,3955},{12,63,10},{51,63,1348},{51,63,1348},{51,63,1348},{48,63,436},{63,39,2178},{44,63,872},{44,63,872},{14,63,1},{47,59,2178},{14,63,1},{63,63,0},{63,63,0},{63,63,0},
+{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{38,0,2669},{38,0,2669},{38,0,2669},{38,0,2669},{32,63,520},{32,63,520},{32,63,520},{29,56,2},{12,63,10},{12,63,10},{46,63,8097},{46,63,6510},{43,63,5893},{41,63,3605},{46,63,8074},{37,63,3244},{37,63,2019},{30,62,129},{30,63,5794},{16,63,58},{56,63,1563},{54,63,1161},{54,63,1017},{51,63,337},{63,49,2166},
+{49,63,1083},{46,63,650},{21,63,0},{63,56,2166},{21,63,0},{43,63,5893},{43,63,5893},{43,63,5893},{41,63,3605},{40,63,5238},{37,63,2019},{37,63,2019},{30,62,113},{24,63,3401},{16,63,58},{54,63,1017},{54,63,1017},{54,63,1017},{51,63,337},{63,42,1625},{46,63,650},{46,63,650},{21,63,0},{62,53,1625},{21,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},
+{0,63,0},{63,63,0},{0,63,0},{40,0,2665},{40,0,2665},{40,0,2665},{40,0,2665},{34,63,610},{34,63,610},{34,63,610},{31,58,0},{16,63,58},{16,63,58},{48,63,7165},{46,63,5854},{46,63,5325},{43,63,3434},{46,63,7050},{40,63,2932},{37,63,1955},{32,62,57},{32,63,5021},{20,63,117},{57,63,1137},{54,63,889},{54,63,745},{52,63,250},{63,51,1601},{51,63,801},{48,63,481},{27,63,0},{63,57,1601},
+{27,63,0},{46,63,5325},{46,63,5325},{46,63,5325},{43,63,3434},{43,63,4622},{37,63,1955},{37,63,1955},{32,62,41},{27,63,2977},{20,63,117},{54,63,745},{54,63,745},{54,63,745},{52,63,250},{63,45,1201},{48,63,481},{48,63,481},{27,63,0},{63,54,1201},{27,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{42,0,2665},
+{42,0,2665},{42,0,2665},{42,0,2665},{37,63,730},{37,63,730},{37,63,730},{33,60,1},{20,63,117},{20,63,117},{50,63,6415},{48,63,5277},{48,63,4877},{45,63,3330},{48,63,6117},{43,63,2716},{40,63,1843},{35,63,10},{35,63,4341},{23,63,205},{57,63,801},{57,63,609},{56,63,530},{54,63,169},{63,53,1121},{52,63,571},{51,63,337},{33,63,0},{63,58,1121},{33,63,0},{48,63,4877},{48,63,4877},{48,63,4877},
+{45,63,3330},{45,63,4146},{40,63,1843},{40,63,1843},{35,63,10},{30,63,2617},{23,63,205},{56,63,530},{56,63,530},{56,63,530},{54,63,169},{63,48,841},{51,63,337},{51,63,337},{33,63,0},{62,56,841},{33,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{44,0,2665},{44,0,2665},{44,0,2665},{44,0,2665},{39,63,865},
+{39,63,865},{39,63,865},{35,62,1},{23,63,205},{23,63,205},{51,63,5637},{50,63,4826},{48,63,4445},{47,63,3189},{48,63,5365},{43,63,2524},{43,63,1795},{37,63,5},{37,63,3750},{27,63,320},{59,63,531},{57,63,401},{57,63,337},{55,63,122},{63,55,726},{55,63,363},{54,63,225},{39,63,0},{63,59,726},{39,63,0},{48,63,4445},{48,63,4445},{48,63,4445},{47,63,3189},{46,63,3654},{43,63,1795},{43,63,1795},
+{37,63,5},{32,63,2329},{27,63,320},{57,63,337},{57,63,337},{57,63,337},{55,63,122},{63,51,545},{54,63,225},{54,63,225},{39,63,0},{63,57,545},{39,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{46,0,2665},{46,0,2665},{46,0,2665},{46,0,2665},{40,63,1010},{40,63,1010},{40,63,1010},{37,63,5},{27,63,320},
+{27,63,320},{3,63,10504},{0,62,1552},{0,44,169},{0,38,3866},{0,57,18065},{0,39,12152},{0,35,6099},{0,24,13992},{0,26,19423},{0,22,14922},{6,63,10216},{0,62,1552},{0,44,169},{0,38,3866},{20,17,18065},{0,39,12152},{0,35,6099},{0,24,13992},{57,0,18065},{0,24,13992},{0,35,0},{0,35,0},{0,35,0},{0,17,1},{0,17,1105},{0,14,424},{0,14,424},{0,8,666},{0,8,1217},{0,7,766},{0,35,0},
+{0,35,0},{0,35,0},{0,17,1},{9,0,1105},{0,14,424},{0,14,424},{0,8,666},{17,0,1105},{0,8,666},{34,17,9248},{0,62,1552},{0,44,169},{0,38,3866},{34,17,9248},{62,12,9248},{0,38,3866},{0,28,9256},{62,12,9248},{0,28,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,63,11298},{0,63,1341},{0,47,65},
+{0,38,3578},{0,61,19334},{0,42,12584},{0,36,6093},{0,24,14696},{0,28,20850},{0,24,15720},{6,63,10792},{0,63,1341},{0,47,65},{0,38,3578},{30,1,19334},{0,42,12584},{0,36,6093},{0,24,14696},{61,0,19334},{0,24,14696},{0,41,0},{0,41,0},{0,41,0},{0,20,1},{0,20,1513},{0,16,585},{0,16,585},{0,10,901},{0,9,1681},{0,8,1070},{0,41,0},{0,41,0},{0,41,0},{0,20,1},{10,1,1513},
+{0,16,585},{0,16,585},{0,10,901},{20,0,1513},{0,10,901},{37,17,9248},{0,63,1341},{0,47,65},{0,38,3578},{37,17,9248},{62,15,9248},{0,38,3578},{0,30,9256},{62,15,9248},{0,30,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,63,12200},{0,63,1325},{0,49,9},{0,41,3298},{0,63,20705},{0,42,13032},{0,38,6147},
+{0,27,15400},{0,31,22426},{0,25,16626},{9,63,11512},{0,63,1325},{0,49,9},{0,41,3298},{31,3,20689},{0,42,13032},{0,38,6147},{0,27,15400},{63,1,20689},{0,27,15400},{0,47,0},{0,47,0},{0,47,0},{0,23,1},{0,23,1985},{0,19,769},{0,19,769},{0,11,1202},{0,11,2193},{0,10,1374},{0,47,0},{0,47,0},{0,47,0},{0,23,1},{12,0,1985},{0,19,769},{0,19,769},{0,11,1202},{23,0,1985},
+{0,11,1202},{48,1,9248},{0,63,1325},{0,49,9},{0,41,3298},{48,1,9248},{63,17,9248},{0,41,3298},{0,32,9250},{63,17,9248},{0,32,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,63,13288},{0,63,1565},{0,51,4},{0,44,3050},{2,63,22214},{0,45,13496},{0,41,6227},{0,28,16225},{0,31,24090},{0,27,17528},{9,63,12344},
+{0,63,1565},{0,51,4},{0,44,3050},{34,1,22129},{0,45,13496},{0,41,6227},{0,28,16225},{63,3,22129},{0,28,16225},{0,53,0},{0,53,0},{0,53,0},{0,26,1},{0,26,2521},{0,22,985},{0,22,985},{0,13,1517},{0,11,2801},{0,11,1766},{0,53,0},{0,53,0},{0,53,0},{0,26,1},{13,1,2521},{0,22,985},{0,22,985},{0,13,1517},{26,0,2521},{0,13,1517},{51,1,9248},{1,63,1552},{1,51,0},
+{0,44,3050},{51,1,9248},{63,20,9248},{0,44,3050},{0,34,9250},{63,20,9248},{0,34,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,63,14818},{1,63,2106},{0,54,58},{0,47,2792},{3,63,24091},{0,50,14075},{0,42,6341},{0,30,17106},{0,33,26067},{0,28,18692},{12,63,13474},{3,63,2077},{1,54,50},{0,47,2792},{31,12,23851},
+{0,50,14075},{0,42,6341},{0,30,17106},{62,6,23851},{0,30,17106},{0,59,1},{0,59,1},{0,59,1},{0,30,0},{0,30,3200},{0,25,1258},{0,25,1258},{0,13,1940},{0,14,3542},{0,13,2229},{0,59,1},{0,59,1},{0,59,1},{0,30,0},{15,0,3200},{0,25,1258},{0,25,1258},{0,13,1940},{30,0,3200},{0,13,1940},{55,0,9248},{6,63,1885},{3,53,2},{0,47,2792},{55,0,9248},{62,24,9248},{0,47,2792},
+{0,36,9256},{62,24,9248},{0,36,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{9,63,16258},{3,63,2813},{1,56,141},{0,49,2561},{4,63,25971},{0,50,14619},{0,45,6453},{0,32,17996},{0,36,27923},{0,30,19698},{12,63,14594},{3,63,2669},{2,56,122},{0,49,2561},{38,1,25472},{0,50,14619},{0,45,6453},{0,32,17996},{45,16,25472},
+{0,32,17996},{0,63,9},{0,63,9},{0,63,9},{0,33,1},{0,33,3872},{0,25,1530},{0,25,1530},{0,16,2378},{0,14,4294},{0,14,2717},{0,63,9},{0,63,9},{0,63,9},{0,33,1},{16,1,3872},{0,25,1530},{0,25,1530},{0,16,2378},{33,0,3872},{0,16,2378},{58,0,9248},{9,63,2205},{5,55,2},{0,49,2561},{58,0,9248},{62,27,9248},{0,49,2561},{0,38,9256},{62,27,9248},{0,38,9256},{0,0,0},
+{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{9,63,17750},{3,63,3617},{1,58,254},{0,50,2366},{6,63,27563},{0,53,14891},{0,47,6385},{0,32,18616},{0,39,29523},{0,32,20465},{15,63,15654},{6,63,3425},{2,59,206},{0,50,2366},{41,0,26744},{0,53,14891},{0,47,6385},{0,32,18616},{62,10,26744},{0,32,18616},{1,63,101},{1,63,101},{1,63,101},
+{0,36,5},{0,36,4420},{0,28,1666},{0,28,1666},{0,16,2642},{0,16,4931},{0,16,3083},{2,63,72},{2,63,72},{2,63,72},{1,35,4},{15,7,4418},{0,28,1666},{0,28,1666},{0,16,2642},{31,3,4418},{0,16,2642},{61,0,9248},{13,63,2554},{7,57,2},{0,50,2362},{61,0,9248},{62,30,9248},{0,50,2362},{0,40,9256},{62,30,9248},{0,40,9256},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,2,0},
+{0,2,0},{0,2,0},{0,1,0},{0,1,1},{0,1,1},{12,63,19046},{4,63,4598},{3,60,382},{0,52,2237},{6,63,28187},{0,59,14347},{0,50,5579},{0,35,18104},{0,39,29955},{0,33,20313},{17,63,16091},{7,63,4046},{4,61,206},{0,52,2237},{44,0,26744},{0,59,14347},{0,50,5579},{0,35,18104},{62,13,26744},{0,35,18104},{2,63,264},{2,63,264},{2,63,264},{1,38,52},{0,42,4420},{0,33,1381},{0,33,1381},
+{0,18,2405},{0,19,5115},{0,18,2981},{4,63,117},{4,63,117},{4,63,117},{3,37,4},{15,13,4418},{0,33,1381},{0,33,1381},{0,18,2405},{31,6,4418},{0,18,2405},{63,2,9248},{17,63,2938},{9,59,2},{0,52,2137},{63,2,9248},{46,41,9248},{0,52,2137},{0,42,9256},{46,41,9248},{0,42,9256},{1,0,52},{1,0,52},{1,0,52},{1,0,52},{0,8,0},{0,8,0},{0,8,0},{0,4,0},{0,3,20},
+{0,3,20},{12,63,20585},{6,63,5786},{4,63,625},{1,56,2246},{9,63,29012},{0,62,13736},{0,53,4760},{0,38,17595},{0,45,30452},{0,36,20086},{20,63,16620},{9,63,4794},{6,63,205},{1,56,2230},{39,16,26744},{0,62,13736},{0,53,4760},{0,38,17595},{62,16,26744},{0,38,17595},{4,63,589},{4,63,589},{4,63,589},{2,41,185},{0,49,4418},{0,36,1097},{0,36,1097},{0,21,2153},{0,22,5357},{0,21,2937},{6,63,169},
+{6,63,169},{6,63,169},{5,39,2},{24,1,4418},{0,36,1097},{0,36,1097},{0,21,2153},{49,0,4418},{0,21,2153},{59,16,9248},{20,63,3380},{11,62,4},{0,55,1901},{59,16,9248},{62,36,9248},{0,55,1901},{0,45,9250},{62,36,9248},{0,45,9250},{2,0,185},{2,0,185},{2,0,185},{2,0,185},{0,14,1},{0,14,1},{0,14,1},{0,7,1},{0,5,72},{0,5,72},{15,63,21605},{9,63,6850},{5,63,978},
+{2,57,2226},{11,63,29435},{0,63,12990},{0,55,3962},{0,41,16835},{0,45,30392},{0,38,19516},{22,63,16694},{12,63,5218},{9,63,225},{4,56,2130},{49,1,26259},{0,63,12990},{0,55,3962},{0,41,16835},{46,27,26259},{0,41,16835},{5,63,978},{5,63,978},{5,63,978},{3,43,370},{0,55,4418},{0,39,881},{0,39,881},{0,24,1945},{0,25,5605},{0,22,2889},{9,63,225},{9,63,225},{9,63,225},{7,41,2},{27,1,4418},
+{0,39,881},{0,39,881},{0,24,1945},{55,0,4418},{0,24,1945},{63,14,8978},{23,63,3592},{14,63,1},{0,58,1625},{63,14,8978},{46,47,8978},{0,58,1625},{0,46,8986},{46,47,8978},{0,46,8986},{3,0,369},{3,0,369},{3,0,369},{3,0,369},{0,20,0},{0,20,0},{0,20,0},{0,10,1},{0,8,136},{0,8,136},{15,63,21141},{9,63,7026},{6,63,1481},{3,58,2034},{12,63,28216},{0,63,11406},{0,56,2868},
+{0,41,14915},{0,48,28876},{0,39,17854},{23,63,15352},{15,63,4866},{11,63,306},{6,58,1746},{52,0,24371},{0,63,11406},{0,56,2868},{0,41,14915},{62,21,24371},{0,41,14915},{6,63,1481},{6,63,1481},{6,63,1481},{4,46,617},{0,61,4418},{0,45,689},{0,45,689},{0,27,1769},{0,28,5885},{0,24,2889},{11,63,306},{11,63,306},{11,63,306},{9,43,2},{30,1,4418},{0,45,689},{0,45,689},{0,27,1769},{61,0,4418},
+{0,27,1769},{55,32,7938},{26,63,3176},{16,63,1},{0,58,1129},{55,32,7938},{46,48,7938},{0,58,1129},{0,47,7946},{46,48,7938},{0,47,7946},{4,0,617},{4,0,617},{4,0,617},{4,0,617},{0,26,0},{0,26,0},{0,26,0},{0,13,1},{0,11,232},{0,11,232},{17,63,20849},{9,63,7458},{8,63,2106},{4,59,1970},{12,63,27224},{0,63,10078},{0,58,1986},{0,42,13214},{0,50,27357},{0,41,16276},{26,63,14168},
+{17,63,4556},{14,63,394},{9,58,1410},{47,14,22568},{0,63,10078},{0,58,1986},{0,42,13214},{62,23,22568},{0,42,13214},{8,63,2106},{8,63,2106},{8,63,2106},{5,48,930},{1,63,4452},{0,47,521},{0,47,521},{0,28,1600},{0,31,6197},{0,27,2921},{14,63,394},{14,63,394},{14,63,394},{11,45,2},{33,1,4418},{0,47,521},{0,47,521},{0,28,1600},{63,2,4418},{0,28,1600},{56,33,6962},{29,63,2792},{19,63,1},
+{0,59,740},{56,33,6962},{49,48,6962},{0,59,740},{0,48,6964},{49,48,6962},{0,48,6964},{5,0,929},{5,0,929},{5,0,929},{5,0,929},{0,32,0},{0,32,0},{0,32,0},{0,16,0},{0,14,360},{0,14,360},{17,63,20651},{12,63,7922},{9,63,2921},{5,60,2052},{15,63,26270},{0,63,8890},{0,59,1154},{0,44,11309},{0,53,25875},{0,42,14658},{26,63,12890},{20,63,4254},{16,63,493},{10,59,1076},{56,0,20642},
+{0,63,8890},{0,59,1154},{0,44,11309},{62,25,20642},{0,44,11309},{9,63,2921},{9,63,2921},{9,63,2921},{6,51,1360},{3,63,4634},{0,50,346},{0,50,346},{0,31,1402},{0,33,6554},{0,28,2987},{16,63,493},{16,63,493},{16,63,493},{13,48,1},{31,12,4418},{0,50,346},{0,50,346},{0,31,1402},{62,6,4418},{0,31,1402},{63,23,5941},{30,63,2386},{23,63,1},{0,61,388},{63,23,5941},{63,43,5941},{0,61,388},
+{0,49,5945},{63,43,5941},{0,49,5945},{6,0,1360},{6,0,1360},{6,0,1360},{6,0,1360},{0,39,0},{0,39,0},{0,39,0},{0,19,1},{0,16,522},{0,16,522},{20,63,20683},{12,63,8578},{11,63,3792},{7,60,2241},{15,63,25566},{1,63,8090},{0,59,642},{0,45,9834},{0,53,24595},{0,44,13350},{29,63,11794},{20,63,4030},{17,63,610},{13,59,804},{58,0,19021},{3,63,8050},{0,59,642},{0,45,9834},{62,27,19021},
+{0,45,9834},{11,63,3792},{11,63,3792},{11,63,3792},{8,53,1808},{3,63,4954},{0,55,232},{0,55,232},{0,33,1241},{0,36,6922},{0,31,3051},{17,63,610},{17,63,610},{17,63,610},{15,50,1},{31,18,4418},{0,55,232},{0,55,232},{0,33,1241},{62,9,4418},{0,33,1241},{63,26,5101},{34,63,2050},{26,63,1},{0,61,164},{63,26,5101},{62,45,5101},{0,61,164},{0,50,5105},{62,45,5101},{0,50,5105},{7,0,1808},
+{7,0,1808},{7,0,1808},{7,0,1808},{0,45,0},{0,45,0},{0,45,0},{0,22,1},{0,19,706},{0,19,706},{20,63,20715},{15,63,9258},{12,63,4729},{8,61,2553},{17,63,25067},{3,63,7474},{0,61,264},{0,47,8373},{0,56,23451},{0,45,12138},{31,63,10854},{23,63,3766},{20,63,698},{16,60,594},{60,0,17485},{6,63,7274},{0,61,264},{0,47,8373},{56,32,17485},{0,47,8373},{12,63,4729},{12,63,4729},{12,63,4729},
+{8,56,2320},{6,63,5386},{0,59,130},{0,59,130},{0,35,1076},{0,39,7322},{0,33,3161},{20,63,698},{20,63,698},{20,63,698},{17,51,2},{34,17,4418},{0,59,130},{0,59,130},{0,35,1076},{62,12,4418},{0,35,1076},{63,29,4325},{35,63,1733},{29,63,1},{0,62,41},{63,29,4325},{63,46,4325},{0,62,41},{0,51,4329},{63,46,4325},{0,51,4329},{8,0,2320},{8,0,2320},{8,0,2320},{8,0,2320},{0,50,1},
+{0,50,1},{0,50,1},{0,25,1},{0,19,914},{0,19,914},{20,63,21003},{15,63,10106},{14,63,5840},{9,62,2993},{17,63,24683},{3,63,7010},{0,62,74},{0,49,7113},{0,56,22427},{0,47,11094},{33,63,9941},{26,63,3566},{23,63,818},{17,61,402},{62,0,16034},{9,63,6562},{0,62,74},{0,49,7113},{62,31,16034},{0,49,7113},{14,63,5840},{14,63,5840},{14,63,5840},{10,58,2896},{6,63,5962},{0,62,58},{0,62,58},
+{0,38,932},{0,42,7754},{0,35,3317},{23,63,818},{23,63,818},{23,63,818},{19,53,2},{37,17,4418},{0,62,58},{0,62,58},{0,38,932},{62,15,4418},{0,38,932},{63,32,3613},{38,63,1445},{32,63,1},{0,63,0},{63,32,3613},{61,48,3613},{0,63,0},{0,52,3617},{61,48,3613},{0,52,3617},{9,0,2896},{9,0,2896},{9,0,2896},{9,0,2896},{0,56,1},{0,56,1},{0,56,1},{0,28,1},{0,22,1130},
+{0,22,1130},{23,63,21401},{17,63,11165},{15,63,7141},{10,63,3641},{20,63,24533},{6,63,6762},{0,63,81},{0,49,5745},{0,59,21333},{0,47,9996},{34,63,8897},{29,63,3396},{26,63,976},{20,61,224},{56,16,14504},{12,63,5834},{1,63,68},{0,49,5745},{62,33,14504},{0,49,5745},{15,63,7141},{15,63,7141},{15,63,7141},{11,61,3617},{9,63,6772},{0,63,81},{0,63,81},{0,41,794},{0,45,8260},{0,38,3515},{26,63,976},
+{26,63,976},{26,63,976},{21,56,0},{49,0,4418},{1,63,68},{1,63,68},{0,41,794},{62,18,4418},{0,41,794},{63,35,2888},{41,63,1156},{35,63,0},{7,63,0},{63,35,2888},{63,49,2888},{7,63,0},{0,53,2896},{63,49,2888},{0,53,2896},{11,0,3617},{11,0,3617},{11,0,3617},{11,0,3617},{0,63,0},{0,63,0},{0,63,0},{0,32,1},{0,25,1413},{0,25,1413},{23,63,21913},{17,63,12317},{17,63,8473},
+{12,63,4330},{20,63,24437},{6,63,6650},{2,63,298},{0,52,4721},{0,62,20509},{0,49,9157},{37,63,8153},{29,63,3268},{28,63,1129},{23,61,128},{63,6,13235},{15,63,5258},{6,63,145},{0,52,4721},{62,35,13235},{0,52,4721},{17,63,8473},{17,63,8473},{17,63,8473},{12,63,4330},{9,63,7636},{2,63,298},{2,63,298},{0,42,689},{0,45,8740},{0,39,3689},{28,63,1129},{28,63,1129},{28,63,1129},{23,58,0},{52,0,4418},
+{6,63,145},{6,63,145},{0,42,689},{62,21,4418},{0,42,689},{63,38,2312},{43,63,925},{38,63,0},{13,63,0},{63,38,2312},{62,51,2312},{13,63,0},{0,54,2320},{62,51,2312},{0,54,2320},{12,0,4329},{12,0,4329},{12,0,4329},{12,0,4329},{1,63,52},{1,63,52},{1,63,52},{0,34,1},{0,28,1693},{0,28,1693},{26,63,22641},{20,63,13461},{17,63,9881},{13,63,5169},{20,63,24597},{6,63,6794},{3,63,649},
+{0,52,3713},{0,62,19773},{0,50,8413},{37,63,7401},{32,63,3181},{29,63,1280},{24,62,48},{63,11,12051},{18,63,4746},{9,63,233},{0,52,3713},{47,45,12051},{0,52,3713},{17,63,9881},{17,63,9881},{17,63,9881},{13,63,5169},{12,63,8644},{3,63,649},{3,63,649},{0,45,569},{0,50,9245},{0,42,3905},{29,63,1280},{29,63,1280},{29,63,1280},{25,60,0},{55,0,4418},{9,63,233},{9,63,233},{0,45,569},{62,24,4418},
+{0,45,569},{63,41,1800},{46,63,725},{41,63,0},{19,63,0},{63,41,1800},{63,52,1800},{19,63,0},{0,55,1808},{63,52,1800},{0,55,1808},{13,0,5105},{13,0,5105},{13,0,5105},{13,0,5105},{2,63,185},{2,63,185},{2,63,185},{0,37,1},{0,31,2005},{0,31,2005},{26,63,23345},{20,63,14805},{20,63,11441},{14,63,6170},{23,63,24893},{9,63,7066},{4,63,1236},{0,53,2900},{0,63,19260},{0,52,7861},{40,63,6753},
+{34,63,3038},{32,63,1465},{27,63,9},{62,16,10952},{21,63,4298},{12,63,353},{0,53,2900},{62,39,10952},{0,53,2900},{20,63,11441},{20,63,11441},{20,63,11441},{14,63,6170},{12,63,9764},{4,63,1236},{4,63,1236},{0,47,458},{0,50,9789},{0,45,4185},{32,63,1465},{32,63,1465},{32,63,1465},{27,62,0},{58,0,4418},{12,63,353},{12,63,353},{0,47,458},{62,27,4418},{0,47,458},{63,44,1352},{48,63,544},{44,63,0},
+{25,63,0},{63,44,1352},{62,54,1352},{25,63,0},{0,56,1360},{62,54,1352},{0,56,1360},{14,0,5945},{14,0,5945},{14,0,5945},{14,0,5945},{3,63,400},{3,63,400},{3,63,400},{0,40,1},{0,33,2336},{0,33,2336},{26,63,24443},{23,63,16415},{20,63,13259},{15,63,7448},{23,63,25379},{9,63,7606},{6,63,2021},{0,55,2045},{0,63,18918},{0,53,7275},{40,63,6141},{37,63,2978},{34,63,1625},{29,63,10},{63,19,9818},
+{24,63,3870},{17,63,530},{0,55,2045},{63,41,9818},{0,55,2045},{20,63,13259},{20,63,13259},{20,63,13259},{15,63,7448},{15,63,11218},{6,63,2021},{6,63,2021},{0,49,365},{0,53,10427},{0,45,4509},{34,63,1625},{34,63,1625},{34,63,1625},{29,63,10},{53,16,4418},{17,63,530},{17,63,530},{0,49,365},{63,30,4418},{0,49,365},{63,47,925},{51,63,377},{47,63,1},{31,63,1},{63,47,925},{63,55,925},{31,63,1},
+{0,58,929},{63,55,925},{0,58,929},{15,0,6964},{15,0,6964},{15,0,6964},{15,0,6964},{3,63,769},{3,63,769},{3,63,769},{0,44,0},{0,36,2745},{0,36,2745},{29,63,25483},{23,63,17983},{22,63,15066},{17,63,8739},{23,63,26083},{12,63,8302},{6,63,2965},{0,56,1458},{0,63,18886},{0,53,6955},{43,63,5581},{40,63,2986},{37,63,1801},{32,63,65},{58,32,8901},{27,63,3558},{20,63,698},{0,56,1458},{52,48,8901},
+{0,56,1458},{22,63,15066},{22,63,15066},{22,63,15066},{17,63,8739},{15,63,12626},{6,63,2965},{6,63,2965},{0,52,277},{0,56,11011},{0,49,4833},{37,63,1801},{37,63,1801},{37,63,1801},{32,63,65},{56,16,4418},{20,63,698},{20,63,698},{0,52,277},{62,33,4418},{0,52,277},{63,50,613},{52,63,250},{50,63,0},{37,63,0},{63,50,613},{62,57,613},{37,63,0},{0,59,617},{62,57,613},{0,59,617},{16,0,7946},
+{16,0,7946},{16,0,7946},{16,0,7946},{5,63,1184},{5,63,1184},{5,63,1184},{0,47,0},{0,36,3145},{0,36,3145},{29,63,26667},{26,63,19695},{23,63,16891},{18,63,10206},{26,63,26795},{12,63,9118},{9,63,4037},{0,58,933},{0,63,19110},{0,56,6699},{46,63,5181},{40,63,2970},{40,63,2009},{34,63,160},{63,27,8069},{30,63,3310},{23,63,898},{0,58,933},{63,45,8069},{0,58,933},{23,63,16891},{23,63,16891},{23,63,16891},
+{18,63,10206},{17,63,14179},{9,63,4037},{9,63,4037},{0,55,221},{0,59,11627},{0,50,5115},{40,63,2009},{40,63,2009},{40,63,2009},{34,63,160},{59,16,4418},{23,63,898},{23,63,898},{0,55,221},{62,36,4418},{0,55,221},{63,53,365},{55,63,146},{53,63,0},{43,63,0},{63,53,365},{63,58,365},{43,63,0},{0,60,369},{63,58,365},{0,60,369},{16,0,8986},{16,0,8986},{16,0,8986},{16,0,8986},{6,63,1665},
+{6,63,1665},{6,63,1665},{0,50,1},{0,39,3545},{0,39,3545},{31,63,26643},{26,63,20231},{26,63,17731},{20,63,10867},{26,63,26531},{15,63,9546},{12,63,4889},{0,59,590},{0,63,18606},{0,56,5707},{46,63,4781},{43,63,2978},{42,63,2228},{37,63,320},{63,31,7322},{32,63,3134},{27,63,1125},{0,59,554},{63,47,7322},{0,59,554},{26,63,17731},{26,63,17731},{26,63,17731},{20,63,10867},{20,63,15043},{12,63,4889},{12,63,4889},
+{1,56,185},{0,62,11315},{0,53,4667},{42,63,2228},{42,63,2228},{42,63,2228},{37,63,320},{62,16,4418},{27,63,1125},{27,63,1125},{0,56,162},{62,39,4418},{0,56,162},{63,56,181},{57,63,73},{56,63,0},{49,63,0},{63,56,181},{62,60,181},{49,63,0},{0,61,185},{62,60,181},{0,61,185},{18,0,9250},{18,0,9250},{18,0,9250},{18,0,9250},{8,63,1972},{8,63,1972},{8,63,1972},{1,52,4},{0,42,3341},
+{0,42,3341},{34,63,26006},{29,63,20400},{28,63,18273},{23,63,11384},{29,63,25736},{17,63,9864},{12,63,5726},{2,60,366},{0,63,18111},{0,59,4452},{48,63,4436},{46,63,3050},{43,63,2465},{40,63,562},{63,35,6584},{37,63,3006},{30,63,1421},{0,61,237},{63,49,6584},{0,61,237},{28,63,18273},{28,63,18273},{28,63,18273},{23,63,11384},{23,63,15704},{12,63,5726},{12,63,5726},{3,59,189},{0,63,10886},{0,56,3924},{43,63,2465},
+{43,63,2465},{43,63,2465},{40,63,562},{63,21,4418},{30,63,1421},{30,63,1421},{0,59,100},{63,42,4418},{0,59,100},{63,59,52},{60,63,20},{59,63,1},{56,63,0},{63,59,52},{63,61,52},{56,63,0},{0,62,52},{63,61,52},{0,62,52},{20,0,9256},{20,0,9256},{20,0,9256},{20,0,9256},{9,63,2205},{9,63,2205},{9,63,2205},{4,54,1},{0,45,2925},{0,45,2925},{34,63,25526},{31,63,20721},{29,63,18700},
+{24,63,11921},{31,63,25279},{20,63,10264},{15,63,6494},{4,62,238},{4,63,17924},{0,59,3588},{51,63,4228},{48,63,3140},{46,63,2665},{41,63,833},{63,39,6019},{40,63,2958},{34,63,1693},{0,62,84},{47,59,6019},{0,62,84},{29,63,18700},{29,63,18700},{29,63,18700},{24,63,11921},{23,63,16280},{15,63,6494},{15,63,6494},{5,61,189},{0,63,10854},{0,59,3332},{46,63,2665},{46,63,2665},{46,63,2665},{41,63,833},{63,27,4418},
+{34,63,1693},{34,63,1693},{0,61,61},{63,45,4418},{0,61,61},{63,62,4},{63,63,4},{62,63,1},{62,63,0},{63,62,4},{62,63,4},{62,63,0},{0,63,4},{62,63,4},{0,63,4},{22,0,9256},{22,0,9256},{22,0,9256},{22,0,9256},{12,63,2389},{12,63,2389},{12,63,2389},{6,56,1},{0,50,2512},{0,50,2512},{37,63,24250},{34,63,19895},{31,63,18169},{26,63,11820},{34,63,23717},{20,63,10012},{17,63,6584},
+{7,62,122},{6,63,16879},{0,62,2736},{51,63,3648},{48,63,2784},{48,63,2384},{43,63,778},{63,42,5163},{41,63,2584},{37,63,1549},{0,63,9},{46,61,5163},{0,63,9},{31,63,18169},{31,63,18169},{31,63,18169},{26,63,11820},{26,63,15620},{17,63,6584},{17,63,6584},{7,62,106},{0,63,10150},{0,59,2624},{48,63,2384},{48,63,2384},{48,63,2384},{43,63,778},{63,31,3872},{37,63,1549},{37,63,1549},{0,63,9},{63,47,3872},
+{0,63,9},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{24,0,9256},{24,0,9256},{24,0,9256},{24,0,9256},{15,63,2605},{15,63,2605},{15,63,2605},{8,58,1},{0,53,2176},{0,53,2176},{37,63,22746},{34,63,18775},{34,63,17254},{29,63,11564},{34,63,21973},{23,63,9532},{20,63,6424},{9,62,57},{9,63,15607},{0,62,2032},{53,63,3058},
+{51,63,2304},{48,63,2000},{46,63,650},{63,43,4267},{43,63,2134},{40,63,1285},{4,63,0},{63,53,4267},{4,63,0},{34,63,17254},{34,63,17254},{34,63,17254},{29,63,11564},{29,63,14692},{20,63,6424},{20,63,6424},{9,62,41},{0,63,9366},{0,62,2016},{48,63,2000},{48,63,2000},{48,63,2000},{46,63,650},{55,49,3200},{40,63,1285},{40,63,1285},{4,63,0},{63,48,3200},{4,63,0},{63,63,0},{63,63,0},{63,63,0},
+{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{26,0,9256},{26,0,9256},{26,0,9256},{26,0,9256},{17,63,2836},{17,63,2836},{17,63,2836},{10,60,1},{0,59,1856},{0,59,1856},{40,63,21168},{37,63,17685},{34,63,16300},{30,63,11323},{37,63,20205},{26,63,9090},{23,63,6310},{12,63,4},{12,63,14287},{0,62,1546},{54,63,2377},{51,63,1809},{51,63,1553},{47,63,520},{61,49,3361},
+{46,63,1683},{43,63,1018},{11,63,0},{63,54,3361},{11,63,0},{34,63,16300},{34,63,16300},{34,63,16300},{30,63,11323},{29,63,13666},{23,63,6310},{23,63,6310},{12,63,4},{3,63,8686},{0,62,1530},{51,63,1553},{51,63,1553},{51,63,1553},{47,63,520},{63,37,2521},{43,63,1018},{43,63,1018},{11,63,0},{62,50,2521},{11,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},
+{0,63,0},{63,63,0},{0,63,0},{29,0,9250},{29,0,9250},{29,0,9250},{29,0,9250},{20,63,3114},{20,63,3114},{20,63,3114},{12,62,1},{0,62,1514},{0,62,1514},{40,63,19824},{37,63,16725},{37,63,15500},{32,63,11084},{37,63,18685},{26,63,8770},{26,63,6270},{14,63,16},{15,63,13215},{0,63,1325},{54,63,1881},{54,63,1449},{51,63,1249},{48,63,409},{63,47,2649},{47,63,1329},{44,63,797},{16,63,1},{63,55,2649},
+{16,63,1},{37,63,15500},{37,63,15500},{37,63,15500},{32,63,11084},{31,63,12906},{26,63,6270},{26,63,6270},{14,63,16},{6,63,8150},{0,63,1325},{51,63,1249},{51,63,1249},{51,63,1249},{48,63,409},{63,40,1985},{44,63,797},{44,63,797},{16,63,1},{63,51,1985},{16,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{31,0,9250},
+{31,0,9250},{31,0,9250},{31,0,9250},{22,63,3393},{22,63,3393},{22,63,3393},{14,63,16},{0,63,1325},{0,63,1325},{43,63,18608},{40,63,15853},{37,63,14796},{34,63,10841},{40,63,17341},{29,63,8410},{26,63,6206},{17,63,74},{17,63,12226},{0,63,1341},{56,63,1451},{54,63,1081},{54,63,937},{51,63,305},{63,50,2017},{49,63,1011},{47,63,605},{22,63,1},{62,57,2017},{22,63,1},{37,63,14796},{37,63,14796},{37,63,14796},
+{34,63,10841},{34,63,12089},{26,63,6206},{26,63,6206},{17,63,74},{9,63,7678},{0,63,1341},{54,63,937},{54,63,937},{54,63,937},{51,63,305},{63,43,1513},{47,63,605},{47,63,605},{22,63,1},{62,53,1513},{22,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{32,0,9256},{32,0,9256},{32,0,9256},{32,0,9256},{23,63,3650},
+{23,63,3650},{23,63,3650},{17,63,74},{0,63,1341},{0,63,1341},{43,63,17392},{40,63,15021},{40,63,14060},{37,63,10673},{40,63,16013},{32,63,8261},{29,63,6166},{19,63,194},{20,63,11338},{1,63,1594},{57,63,1041},{56,63,822},{54,63,697},{52,63,234},{63,51,1473},{51,63,737},{49,63,442},{28,63,1},{63,57,1473},{28,63,1},{40,63,14060},{40,63,14060},{40,63,14060},{37,63,10673},{34,63,11401},{29,63,6166},{29,63,6166},
+{19,63,194},{12,63,7270},{1,63,1594},{54,63,697},{54,63,697},{54,63,697},{52,63,234},{63,46,1105},{49,63,442},{49,63,442},{28,63,1},{63,54,1105},{28,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{34,0,9256},{34,0,9256},{34,0,9256},{34,0,9256},{26,63,3898},{26,63,3898},{26,63,3898},{19,63,194},{1,63,1594},
+{1,63,1594}, \ No newline at end of file
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_pvrtc2_45.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_pvrtc2_45.inc
new file mode 100644
index 0000000000..0bca0bbddc
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_pvrtc2_45.inc
@@ -0,0 +1,481 @@
+{0,2,20},{0,1,10},{0,1,1},{0,1,9},{0,1,35},{0,1,27},{0,1,18},{0,1,61},{0,1,52},{0,0,68},{0,2,20},{0,1,10},{0,1,1},{0,1,9},{0,1,35},{0,1,27},{0,1,18},{0,1,61},{0,1,43},{0,1,61},{0,1,1},{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,1},
+{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,2,20},{0,1,10},{0,1,1},{0,1,9},{0,2,20},{0,1,18},{0,1,9},{0,1,36},{0,1,18},{0,1,36},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,4,56},{0,3,38},{0,2,52},
+{0,2,36},{0,4,56},{0,3,35},{0,2,0},{0,2,52},{0,2,88},{0,1,78},{0,4,56},{0,3,38},{0,2,52},{0,2,36},{1,0,52},{0,3,35},{0,2,0},{0,2,52},{1,1,51},{0,2,52},{0,3,37},{0,3,37},{0,3,37},{0,2,36},{0,3,10},{0,2,0},{0,2,0},{0,1,5},{0,1,35},{0,1,14},{0,3,37},{0,3,37},{0,3,37},{0,2,36},{0,3,10},
+{0,2,0},{0,2,0},{0,1,5},{1,0,16},{0,1,5},{1,1,18},{0,3,2},{0,2,16},{0,2,0},{1,1,18},{2,0,20},{0,2,0},{0,2,36},{2,0,20},{0,2,36},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,10},{0,1,10},{1,4,88},{1,3,78},{1,3,69},{1,3,77},{1,3,115},{0,4,88},{0,3,98},
+{0,3,101},{0,4,72},{0,3,38},{1,4,24},{1,3,14},{1,3,5},{1,3,13},{1,3,51},{0,4,24},{0,3,34},{0,3,37},{3,0,52},{0,3,37},{1,3,69},{1,3,69},{1,3,69},{1,2,72},{1,2,72},{1,2,72},{1,2,72},{1,2,72},{0,3,11},{0,2,24},{1,3,5},{1,3,5},{1,3,5},{1,2,8},{1,2,8},{1,2,8},{1,2,8},{1,2,8},{1,2,8},
+{1,2,8},{0,7,18},{1,3,10},{1,3,1},{0,3,9},{0,7,18},{1,3,18},{0,3,9},{0,3,36},{1,3,18},{0,3,36},{1,0,68},{1,0,68},{1,0,68},{1,0,68},{1,1,65},{1,1,65},{1,1,65},{0,3,65},{0,3,2},{0,3,2},{1,6,56},{1,5,38},{1,4,53},{1,4,37},{1,6,56},{1,5,35},{1,4,1},{1,4,66},{0,5,60},{0,4,70},{1,6,56},
+{1,5,38},{1,4,53},{1,4,37},{0,9,51},{1,5,35},{1,4,1},{0,4,54},{2,3,51},{0,4,54},{1,5,37},{1,5,37},{1,5,37},{1,4,36},{1,5,10},{1,4,0},{1,4,0},{1,3,5},{0,5,11},{1,3,14},{1,5,37},{1,5,37},{1,5,37},{1,4,36},{0,8,8},{1,4,0},{1,4,0},{1,3,5},{4,0,8},{1,3,5},{2,3,18},{1,5,2},{1,4,17},
+{1,4,1},{2,3,18},{4,1,18},{1,4,1},{0,4,50},{4,1,18},{0,4,50},{1,0,36},{1,0,36},{1,0,36},{1,0,36},{1,4,0},{1,4,0},{1,4,0},{1,3,1},{1,3,10},{1,3,10},{2,6,88},{2,5,78},{2,5,69},{2,5,77},{2,5,115},{2,5,107},{2,5,98},{1,5,117},{1,6,60},{1,5,36},{2,6,24},{2,5,14},{2,5,5},{2,5,13},{3,2,51},
+{1,6,35},{2,5,34},{1,5,36},{1,6,51},{1,5,36},{2,5,69},{2,5,69},{2,5,69},{2,4,72},{2,4,72},{2,4,72},{2,4,72},{2,4,72},{1,5,16},{1,5,36},{2,5,5},{2,5,5},{2,5,5},{2,4,8},{3,1,8},{2,4,8},{2,4,8},{2,4,8},{3,3,8},{2,4,8},{3,3,20},{2,5,10},{2,5,1},{2,5,9},{3,3,20},{2,5,18},{2,5,9},
+{0,5,36},{2,5,18},{0,5,36},{2,0,68},{2,0,68},{2,0,68},{2,0,68},{2,3,68},{2,3,68},{2,3,68},{2,4,68},{1,5,0},{1,5,0},{2,8,56},{2,7,38},{2,6,52},{2,6,36},{2,8,56},{2,7,35},{2,6,0},{2,6,52},{1,7,76},{1,6,70},{2,8,56},{2,7,38},{2,6,52},{2,6,36},{4,1,51},{2,7,35},{2,6,0},{1,6,45},{3,5,51},
+{1,6,45},{2,7,37},{2,7,37},{2,7,37},{2,6,36},{2,7,10},{2,6,0},{2,6,0},{2,5,5},{1,7,12},{2,5,14},{2,7,37},{2,7,37},{2,7,37},{2,6,36},{4,0,8},{2,6,0},{2,6,0},{2,5,5},{1,7,8},{2,5,5},{3,5,18},{2,7,2},{2,6,16},{2,6,0},{3,5,18},{0,9,18},{2,6,0},{0,6,36},{0,9,18},{0,6,36},{2,0,36},
+{2,0,36},{2,0,36},{2,0,36},{2,6,0},{2,6,0},{2,6,0},{2,5,1},{1,7,8},{1,7,8},{3,8,88},{3,7,78},{3,7,69},{3,7,77},{3,7,115},{2,8,88},{2,7,98},{2,7,101},{1,9,67},{2,7,38},{3,8,24},{3,7,14},{3,7,5},{3,7,13},{3,7,51},{2,8,24},{2,7,34},{2,7,37},{8,0,51},{2,7,37},{3,7,69},{3,7,69},{3,7,69},
+{3,6,72},{3,6,72},{3,6,72},{3,6,72},{3,6,72},{2,7,11},{2,6,24},{3,7,5},{3,7,5},{3,7,5},{3,6,8},{3,6,8},{3,6,8},{3,6,8},{3,6,8},{3,6,8},{3,6,8},{5,1,18},{3,7,10},{3,7,1},{2,7,9},{5,1,18},{3,7,18},{2,7,9},{0,7,36},{3,7,18},{0,7,36},{3,0,68},{3,0,68},{3,0,68},{3,0,68},{3,5,65},
+{3,5,65},{3,5,65},{2,7,65},{2,7,2},{2,7,2},{3,10,56},{3,9,38},{3,8,53},{3,8,37},{3,10,56},{3,9,35},{3,8,1},{3,8,66},{2,9,60},{2,8,70},{3,10,56},{3,9,38},{3,8,53},{3,8,37},{5,3,51},{3,9,35},{3,8,1},{2,8,54},{4,7,51},{2,8,54},{3,9,37},{3,9,37},{3,9,37},{3,8,36},{3,9,10},{3,8,0},{3,8,0},
+{3,7,5},{2,9,11},{3,7,14},{3,9,37},{3,9,37},{3,9,37},{3,8,36},{5,2,8},{3,8,0},{3,8,0},{3,7,5},{8,1,8},{3,7,5},{4,7,18},{3,9,2},{3,8,17},{3,8,1},{4,7,18},{8,2,18},{3,8,1},{0,8,50},{8,2,18},{0,8,50},{3,0,36},{3,0,36},{3,0,36},{3,0,36},{3,8,0},{3,8,0},{3,8,0},{3,7,1},{3,7,10},
+{3,7,10},{4,10,88},{4,9,78},{4,9,69},{4,9,77},{4,9,115},{4,9,107},{4,9,98},{3,9,117},{3,10,60},{3,9,36},{4,10,24},{4,9,14},{4,9,5},{4,9,13},{5,6,51},{3,10,35},{4,9,34},{3,9,36},{10,1,51},{3,9,36},{4,9,69},{4,9,69},{4,9,69},{4,8,72},{4,8,72},{4,8,72},{4,8,72},{4,8,72},{3,9,16},{3,9,36},{4,9,5},
+{4,9,5},{4,9,5},{4,8,8},{5,5,8},{4,8,8},{4,8,8},{4,8,8},{5,7,8},{4,8,8},{7,0,18},{4,9,10},{4,9,1},{4,9,9},{7,0,18},{4,9,18},{4,9,9},{0,9,36},{4,9,18},{0,9,36},{4,0,68},{4,0,68},{4,0,68},{4,0,68},{4,7,68},{4,7,68},{4,7,68},{4,8,68},{3,9,0},{3,9,0},{4,12,56},{4,11,38},{4,10,52},
+{4,10,36},{4,12,56},{4,11,35},{4,10,0},{4,10,52},{3,11,76},{3,10,70},{4,12,56},{4,11,38},{4,10,52},{4,10,36},{7,2,51},{4,11,35},{4,10,0},{3,10,45},{12,0,51},{3,10,45},{4,11,37},{4,11,37},{4,11,37},{4,10,36},{4,11,10},{4,10,0},{4,10,0},{4,9,5},{3,11,12},{4,9,14},{4,11,37},{4,11,37},{4,11,37},{4,10,36},{7,1,8},
+{4,10,0},{4,10,0},{4,9,5},{10,2,8},{4,9,5},{5,9,18},{4,11,2},{4,10,16},{4,10,0},{5,9,18},{10,3,18},{4,10,0},{0,10,36},{10,3,18},{0,10,36},{4,0,36},{4,0,36},{4,0,36},{4,0,36},{4,10,0},{4,10,0},{4,10,0},{4,9,1},{3,11,8},{3,11,8},{5,12,88},{5,11,78},{5,11,69},{5,11,77},{5,11,115},{4,12,88},{4,11,98},
+{4,11,101},{3,13,67},{4,11,38},{5,12,24},{5,11,14},{5,11,5},{5,11,13},{5,11,51},{4,12,24},{4,11,34},{4,11,37},{11,3,51},{4,11,37},{5,11,69},{5,11,69},{5,11,69},{5,10,72},{5,10,72},{5,10,72},{5,10,72},{5,10,72},{4,11,11},{4,10,24},{5,11,5},{5,11,5},{5,11,5},{5,10,8},{5,10,8},{5,10,8},{5,10,8},{5,10,8},{12,1,8},
+{5,10,8},{8,0,18},{5,11,10},{5,11,1},{4,11,9},{8,0,18},{12,2,18},{4,11,9},{0,11,36},{12,2,18},{0,11,36},{5,0,68},{5,0,68},{5,0,68},{5,0,68},{5,9,65},{5,9,65},{5,9,65},{4,11,65},{4,11,2},{4,11,2},{5,14,56},{5,13,38},{5,12,53},{5,12,37},{5,14,56},{5,13,35},{5,12,1},{5,12,66},{4,13,60},{4,12,70},{5,14,56},
+{5,13,38},{5,12,53},{5,12,37},{8,2,51},{5,13,35},{5,12,1},{4,12,54},{13,2,51},{4,12,54},{5,13,37},{5,13,37},{5,13,37},{5,12,36},{5,13,10},{5,12,0},{5,12,0},{5,11,5},{4,13,11},{5,11,14},{5,13,37},{5,13,37},{5,13,37},{5,12,36},{8,1,8},{5,12,0},{5,12,0},{5,11,5},{10,5,8},{5,11,5},{6,11,18},{5,13,2},{5,12,17},
+{5,12,1},{6,11,18},{15,0,18},{5,12,1},{0,12,50},{15,0,18},{0,12,50},{5,0,36},{5,0,36},{5,0,36},{5,0,36},{5,12,0},{5,12,0},{5,12,0},{5,11,1},{5,11,10},{5,11,10},{6,14,88},{6,13,78},{6,13,69},{6,13,77},{6,13,115},{6,13,107},{6,13,98},{5,13,117},{5,14,60},{5,13,36},{6,14,24},{6,13,14},{6,13,5},{6,13,13},{8,5,51},
+{5,14,35},{6,13,34},{5,13,36},{12,5,51},{5,13,36},{6,13,69},{6,13,69},{6,13,69},{6,12,72},{6,12,72},{6,12,72},{6,12,72},{6,12,72},{5,13,16},{5,13,36},{6,13,5},{6,13,5},{6,13,5},{6,12,8},{8,4,8},{6,12,8},{6,12,8},{6,12,8},{14,2,8},{6,12,8},{3,24,18},{6,13,10},{6,13,1},{6,13,9},{3,24,18},{14,3,18},{6,13,9},
+{0,13,36},{14,3,18},{0,13,36},{6,0,68},{6,0,68},{6,0,68},{6,0,68},{6,11,68},{6,11,68},{6,11,68},{6,12,68},{5,13,0},{5,13,0},{6,16,56},{6,15,38},{6,14,52},{6,14,36},{6,16,56},{6,15,35},{6,14,0},{6,14,52},{5,15,76},{5,14,70},{6,16,56},{6,15,38},{6,14,52},{6,14,36},{3,26,51},{6,15,35},{6,14,0},{5,14,45},{15,3,51},
+{5,14,45},{6,15,37},{6,15,37},{6,15,37},{6,14,36},{6,15,10},{6,14,0},{6,14,0},{6,13,5},{5,15,12},{6,13,14},{6,15,37},{6,15,37},{6,15,37},{6,14,36},{3,25,8},{6,14,0},{6,14,0},{6,13,5},{12,6,8},{6,13,5},{9,5,18},{6,15,2},{6,14,16},{6,14,0},{9,5,18},{12,7,18},{6,14,0},{0,14,36},{12,7,18},{0,14,36},{6,0,36},
+{6,0,36},{6,0,36},{6,0,36},{6,14,0},{6,14,0},{6,14,0},{6,13,1},{5,15,8},{5,15,8},{7,16,88},{7,15,78},{7,15,69},{7,15,77},{7,15,115},{6,16,88},{6,15,98},{6,15,101},{5,17,67},{6,15,38},{7,16,24},{7,15,14},{7,15,5},{7,15,13},{11,0,51},{6,16,24},{6,15,34},{6,15,37},{13,7,51},{6,15,37},{7,15,69},{7,15,69},{7,15,69},
+{7,14,72},{7,14,72},{7,14,72},{7,14,72},{7,14,72},{6,15,11},{6,14,24},{7,15,5},{7,15,5},{7,15,5},{7,14,8},{9,6,8},{7,14,8},{7,14,8},{7,14,8},{14,5,8},{7,14,8},{10,4,18},{7,15,10},{7,15,1},{6,15,9},{10,4,18},{14,6,18},{6,15,9},{0,15,36},{14,6,18},{0,15,36},{7,0,68},{7,0,68},{7,0,68},{7,0,68},{7,13,65},
+{7,13,65},{7,13,65},{6,15,65},{6,15,2},{6,15,2},{7,18,56},{7,17,38},{7,16,53},{7,16,37},{7,18,56},{7,17,35},{7,16,1},{7,16,66},{6,17,60},{6,16,70},{7,18,56},{7,17,38},{7,16,53},{7,16,37},{10,6,51},{7,17,35},{7,16,1},{6,16,54},{15,6,51},{6,16,54},{7,17,37},{7,17,37},{7,17,37},{7,16,36},{7,17,10},{7,16,0},{7,16,0},
+{7,15,5},{6,17,11},{7,15,14},{7,17,37},{7,17,37},{7,17,37},{7,16,36},{10,5,8},{7,16,0},{7,16,0},{7,15,5},{12,9,8},{7,15,5},{12,0,18},{7,17,2},{7,16,17},{7,16,1},{12,0,18},{12,10,18},{7,16,1},{0,16,50},{12,10,18},{0,16,50},{7,0,36},{7,0,36},{7,0,36},{7,0,36},{7,16,0},{7,16,0},{7,16,0},{7,15,1},{7,15,10},
+{7,15,10},{7,21,326},{7,19,322},{8,17,392},{7,17,322},{7,21,137},{7,18,116},{7,17,133},{7,17,117},{7,18,60},{7,17,36},{8,16,118},{8,16,134},{8,17,136},{8,17,136},{10,9,51},{7,18,35},{7,17,52},{7,17,36},{14,9,51},{7,17,36},{7,20,307},{7,20,307},{7,20,307},{7,18,307},{7,20,91},{7,18,91},{7,18,91},{7,16,110},{7,17,16},{7,17,36},{8,15,101},
+{8,15,101},{8,15,101},{8,16,101},{10,8,8},{7,18,10},{7,18,10},{7,16,29},{11,12,8},{7,16,29},{12,3,18},{7,19,16},{8,17,36},{7,17,16},{12,3,18},{11,13,18},{7,17,16},{0,17,36},{11,13,18},{0,17,36},{7,0,306},{7,0,306},{7,0,306},{7,0,306},{7,19,81},{7,19,81},{7,19,81},{7,17,81},{7,17,0},{7,17,0},{8,19,88},{8,18,78},{8,18,69},
+{8,18,77},{8,18,115},{8,18,107},{8,18,98},{8,17,136},{7,19,76},{7,18,70},{8,19,24},{8,18,14},{8,18,5},{8,18,13},{9,15,51},{8,18,43},{8,18,34},{7,18,45},{5,22,51},{7,18,45},{8,18,69},{8,18,69},{8,18,69},{8,17,72},{8,17,72},{8,17,72},{8,17,72},{8,17,72},{7,19,12},{7,18,70},{8,18,5},{8,18,5},{8,18,5},{8,17,8},{9,14,8},
+{8,17,8},{8,17,8},{8,17,8},{14,10,8},{8,17,8},{11,9,18},{8,18,10},{8,18,1},{8,18,9},{11,9,18},{14,11,18},{8,18,9},{0,18,36},{14,11,18},{0,18,36},{8,0,68},{8,0,68},{8,0,68},{8,0,68},{8,16,65},{8,16,65},{8,16,65},{8,17,68},{7,19,8},{7,19,8},{8,21,56},{8,20,38},{8,19,52},{8,19,36},{8,21,56},{8,20,35},{8,19,0},
+{8,19,52},{7,21,67},{8,18,78},{8,21,56},{8,20,38},{8,19,52},{8,19,36},{13,4,51},{8,20,35},{8,19,0},{8,19,52},{15,11,51},{8,19,52},{8,20,37},{8,20,37},{8,20,37},{8,19,36},{8,20,10},{8,19,0},{8,19,0},{8,18,5},{8,18,35},{8,18,14},{8,20,37},{8,20,37},{8,20,37},{8,19,36},{11,10,8},{8,19,0},{8,19,0},{8,18,5},{5,23,8},
+{8,18,5},{12,8,18},{8,20,2},{8,19,16},{8,19,0},{12,8,18},{11,16,18},{8,19,0},{0,19,36},{11,16,18},{0,19,36},{8,0,36},{8,0,36},{8,0,36},{8,0,36},{8,19,0},{8,19,0},{8,19,0},{8,18,1},{8,18,10},{8,18,10},{9,21,88},{9,20,78},{9,20,70},{9,20,78},{9,20,115},{8,21,88},{8,20,99},{8,20,115},{8,21,72},{8,20,52},{9,21,24},
+{9,20,14},{9,20,6},{9,20,14},{15,0,51},{8,21,24},{8,20,35},{8,20,51},{12,16,51},{8,20,51},{9,20,69},{9,20,69},{9,20,69},{9,19,72},{9,19,72},{9,19,72},{9,19,72},{9,19,72},{8,20,11},{8,19,24},{9,20,5},{9,20,5},{9,20,5},{9,19,8},{12,9,8},{9,19,8},{9,19,8},{9,19,8},{14,13,8},{9,19,8},{14,4,18},{9,20,10},{9,20,2},
+{8,20,10},{14,4,18},{14,14,18},{8,20,10},{0,20,50},{14,14,18},{0,20,50},{9,0,68},{9,0,68},{9,0,68},{9,0,68},{9,18,65},{9,18,65},{9,18,65},{8,20,65},{8,20,2},{8,20,2},{9,24,70},{9,22,58},{9,21,75},{9,21,51},{9,23,52},{9,22,25},{9,21,3},{9,21,46},{8,23,68},{8,21,70},{9,24,69},{9,22,57},{9,21,74},{9,21,50},{15,3,51},
+{9,22,24},{9,21,2},{8,21,45},{11,19,51},{8,21,45},{9,23,51},{9,23,51},{9,23,51},{9,21,51},{9,22,9},{9,21,3},{9,21,3},{9,20,9},{8,22,12},{9,20,12},{9,23,50},{9,23,50},{9,23,50},{9,21,50},{15,2,8},{9,21,2},{9,21,2},{9,20,8},{13,16,8},{9,20,8},{14,7,18},{9,22,8},{9,21,25},{9,21,1},{14,7,18},{13,17,18},{9,21,1},
+{0,21,36},{13,17,18},{0,21,36},{9,0,50},{9,0,50},{9,0,50},{9,0,50},{9,21,2},{9,21,2},{9,21,2},{9,20,5},{9,20,8},{9,20,8},{10,23,88},{10,22,78},{10,22,69},{10,22,77},{10,22,115},{10,22,107},{10,22,98},{9,22,117},{9,23,60},{9,22,36},{10,23,24},{10,22,14},{10,22,5},{10,22,13},{11,19,51},{9,23,35},{10,22,34},{9,22,36},{9,23,51},
+{9,22,36},{10,22,69},{10,22,69},{10,22,69},{10,21,72},{10,21,72},{10,21,72},{10,21,72},{10,21,72},{9,22,16},{9,22,36},{10,22,5},{10,22,5},{10,22,5},{10,21,8},{11,18,8},{10,21,8},{10,21,8},{10,21,8},{10,21,8},{10,21,8},{13,13,18},{10,22,10},{10,22,1},{10,22,9},{13,13,18},{15,16,18},{10,22,9},{0,22,36},{15,16,18},{0,22,36},{10,0,68},
+{10,0,68},{10,0,68},{10,0,68},{10,20,65},{10,20,65},{10,20,65},{10,21,68},{9,22,0},{9,22,0},{10,25,56},{10,24,38},{10,23,52},{10,23,36},{10,25,56},{10,24,35},{10,23,0},{10,23,52},{9,24,63},{9,23,70},{10,25,56},{10,24,38},{10,23,52},{10,23,36},{15,8,51},{10,24,35},{10,23,0},{9,23,45},{11,22,51},{9,23,45},{10,24,37},{10,24,37},{10,24,37},
+{10,23,36},{10,24,10},{10,23,0},{10,23,0},{10,22,5},{9,24,14},{10,22,14},{10,24,37},{10,24,37},{10,24,37},{10,23,36},{13,14,8},{10,23,0},{10,23,0},{10,22,5},{8,25,8},{10,22,5},{14,12,18},{10,24,2},{10,23,16},{10,23,0},{14,12,18},{13,20,18},{10,23,0},{0,23,36},{13,20,18},{0,23,36},{10,0,36},{10,0,36},{10,0,36},{10,0,36},{10,23,0},
+{10,23,0},{10,23,0},{10,22,1},{10,22,10},{10,22,10},{11,25,88},{11,24,78},{11,24,70},{11,24,78},{11,24,115},{10,25,88},{10,24,99},{10,24,115},{9,26,67},{10,24,52},{11,25,24},{11,24,14},{11,24,6},{11,24,14},{14,14,51},{10,25,24},{10,24,35},{10,24,51},{14,20,51},{10,24,51},{11,24,69},{11,24,69},{11,24,69},{11,23,72},{11,23,72},{11,23,72},{11,23,72},
+{11,23,72},{10,24,11},{10,23,24},{11,24,5},{11,24,5},{11,24,5},{11,23,8},{14,13,8},{11,23,8},{11,23,8},{11,23,8},{11,23,8},{11,23,8},{13,18,18},{11,24,10},{11,24,2},{10,24,10},{13,18,18},{11,24,18},{10,24,10},{0,24,50},{11,24,18},{0,24,50},{11,0,68},{11,0,68},{11,0,68},{11,0,68},{11,22,65},{11,22,65},{11,22,65},{10,24,65},{10,24,2},
+{10,24,2},{11,28,70},{11,26,58},{11,25,75},{11,25,51},{11,27,52},{11,26,25},{11,25,3},{11,25,46},{10,27,68},{10,25,70},{11,28,69},{11,26,57},{11,25,74},{11,25,50},{14,17,51},{11,26,24},{11,25,2},{10,25,45},{13,23,51},{10,25,45},{11,27,51},{11,27,51},{11,27,51},{11,25,51},{11,26,9},{11,25,3},{11,25,3},{11,24,9},{10,26,12},{11,24,12},{11,27,50},
+{11,27,50},{11,27,50},{11,25,50},{14,16,8},{11,25,2},{11,25,2},{11,24,8},{15,20,8},{11,24,8},{13,21,18},{11,26,8},{11,25,25},{11,25,1},{13,21,18},{15,21,18},{11,25,1},{0,25,36},{15,21,18},{0,25,36},{11,0,50},{11,0,50},{11,0,50},{11,0,50},{11,25,2},{11,25,2},{11,25,2},{11,24,5},{11,24,8},{11,24,8},{12,27,88},{12,26,78},{12,26,69},
+{12,26,77},{12,26,115},{12,26,107},{12,26,98},{11,26,117},{11,27,60},{11,26,36},{12,27,24},{12,26,14},{12,26,5},{12,26,13},{13,23,51},{11,27,35},{12,26,34},{11,26,36},{11,27,51},{11,26,36},{12,26,69},{12,26,69},{12,26,69},{12,25,72},{12,25,72},{12,25,72},{12,25,72},{12,25,72},{11,26,16},{11,26,36},{12,26,5},{12,26,5},{12,26,5},{12,25,8},{13,22,8},
+{12,25,8},{12,25,8},{12,25,8},{12,25,8},{12,25,8},{15,17,18},{12,26,10},{12,26,1},{12,26,9},{15,17,18},{12,26,18},{12,26,9},{0,26,36},{12,26,18},{0,26,36},{12,0,68},{12,0,68},{12,0,68},{12,0,68},{12,24,65},{12,24,65},{12,24,65},{12,25,68},{11,26,0},{11,26,0},{12,29,56},{12,28,38},{12,27,52},{12,27,36},{12,29,56},{12,28,35},{12,27,0},
+{12,27,52},{11,28,63},{11,27,70},{12,29,56},{12,28,38},{12,27,52},{12,27,36},{15,19,51},{12,28,35},{12,27,0},{11,27,45},{13,26,51},{11,27,45},{12,28,37},{12,28,37},{12,28,37},{12,27,36},{12,28,10},{12,27,0},{12,27,0},{12,26,5},{11,28,14},{12,26,14},{12,28,37},{12,28,37},{12,28,37},{12,27,36},{15,18,8},{12,27,0},{12,27,0},{12,26,5},{10,29,8},
+{12,26,5},{13,26,18},{12,28,2},{12,27,16},{12,27,0},{13,26,18},{15,24,18},{12,27,0},{0,27,36},{15,24,18},{0,27,36},{12,0,36},{12,0,36},{12,0,36},{12,0,36},{12,27,0},{12,27,0},{12,27,0},{12,26,1},{12,26,10},{12,26,10},{13,29,88},{13,28,78},{13,28,70},{13,28,78},{13,28,115},{12,29,88},{12,28,99},{12,28,115},{11,30,67},{12,28,52},{13,29,24},
+{13,28,14},{13,28,6},{13,28,14},{13,28,51},{12,29,24},{12,28,35},{12,28,51},{11,30,51},{12,28,51},{13,28,69},{13,28,69},{13,28,69},{13,27,72},{13,27,72},{13,27,72},{13,27,72},{13,27,72},{12,28,11},{12,27,24},{13,28,5},{13,28,5},{13,28,5},{13,27,8},{13,27,8},{13,27,8},{13,27,8},{13,27,8},{13,27,8},{13,27,8},{15,22,18},{13,28,10},{13,28,2},
+{12,28,10},{15,22,18},{13,28,18},{12,28,10},{0,28,50},{13,28,18},{0,28,50},{13,0,68},{13,0,68},{13,0,68},{13,0,68},{13,26,65},{13,26,65},{13,26,65},{12,28,65},{12,28,2},{12,28,2},{13,31,76},{13,30,58},{13,29,75},{13,29,51},{13,31,52},{13,30,25},{13,29,3},{13,29,46},{12,31,68},{12,29,70},{13,31,75},{13,30,57},{13,29,74},{13,29,50},{13,31,51},
+{13,30,24},{13,29,2},{12,29,45},{15,27,51},{12,29,45},{13,31,51},{13,31,51},{13,31,51},{13,29,51},{13,30,9},{13,29,3},{13,29,3},{13,28,9},{12,30,12},{13,28,12},{13,31,50},{13,31,50},{13,31,50},{13,29,50},{13,30,8},{13,29,2},{13,29,2},{13,28,8},{12,30,8},{13,28,8},{15,25,18},{13,30,8},{13,29,25},{13,29,1},{15,25,18},{12,31,18},{13,29,1},
+{0,29,36},{12,31,18},{0,29,36},{13,0,50},{13,0,50},{13,0,50},{13,0,50},{13,29,2},{13,29,2},{13,29,2},{13,28,5},{13,28,8},{13,28,8},{14,31,88},{14,30,78},{14,30,69},{14,30,77},{14,30,115},{14,30,107},{14,30,98},{13,30,117},{13,31,60},{13,30,36},{14,31,24},{14,30,14},{14,30,5},{14,30,13},{15,27,51},{13,31,35},{14,30,34},{13,30,36},{13,31,51},
+{13,30,36},{14,30,69},{14,30,69},{14,30,69},{14,29,72},{14,29,72},{14,29,72},{14,29,72},{14,29,72},{13,30,16},{13,30,36},{14,30,5},{14,30,5},{14,30,5},{14,29,8},{15,26,8},{14,29,8},{14,29,8},{14,29,8},{14,29,8},{14,29,8},{14,31,20},{14,30,10},{14,30,1},{14,30,9},{14,31,20},{14,30,18},{14,30,9},{0,30,36},{14,30,18},{0,30,36},{14,0,68},
+{14,0,68},{14,0,68},{14,0,68},{14,28,65},{14,28,65},{14,28,65},{14,29,68},{13,30,0},{13,30,0},{14,31,152},{14,31,88},{14,31,52},{14,31,36},{14,31,116},{14,31,36},{14,31,0},{14,31,52},{14,31,88},{13,31,70},{15,30,118},{14,31,88},{14,31,52},{14,31,36},{15,29,52},{14,31,36},{14,31,0},{13,31,45},{15,30,51},{13,31,45},{14,31,52},{14,31,52},{14,31,52},
+{14,31,36},{14,31,16},{14,31,0},{14,31,0},{14,30,5},{14,30,35},{14,30,14},{14,31,52},{14,31,52},{14,31,52},{14,31,36},{15,28,10},{14,31,0},{14,31,0},{14,30,5},{15,29,16},{14,30,5},{15,30,18},{15,30,34},{14,31,16},{14,31,0},{15,30,18},{15,30,26},{14,31,0},{0,31,36},{15,30,26},{0,31,36},{14,0,36},{14,0,36},{14,0,36},{14,0,36},{14,31,0},
+{14,31,0},{14,31,0},{14,30,1},{14,30,10},{14,30,10},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{14,31,20},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},
+{15,31,68},{14,31,56},{14,31,20},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{15,0,68},{15,0,68},{15,0,68},{15,0,68},{15,30,65},{15,30,65},{15,30,65},{15,31,68},{14,31,20},
+{14,31,20},{0,4,74},{0,3,20},{0,2,2},{0,2,26},{0,2,158},{0,2,110},{0,2,62},{0,1,115},{0,1,178},{0,1,124},{0,4,74},{0,3,20},{0,2,2},{0,2,26},{0,2,158},{0,2,110},{0,2,62},{0,1,115},{1,0,158},{0,1,115},{0,2,1},{0,2,1},{0,2,1},{0,1,0},{0,1,13},{0,1,9},{0,1,9},{0,0,25},{0,0,25},{0,0,25},{0,2,1},
+{0,2,1},{0,2,1},{0,1,0},{0,1,13},{0,1,9},{0,1,9},{0,0,25},{0,0,25},{0,0,25},{1,0,74},{0,3,20},{0,2,2},{0,2,26},{1,0,74},{1,1,72},{0,2,26},{0,1,90},{1,1,72},{0,1,90},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,6,83},{0,5,13},{0,3,26},
+{0,3,14},{0,5,248},{0,3,140},{0,3,41},{0,2,139},{0,2,319},{0,2,175},{0,6,83},{0,5,13},{0,3,26},{0,3,14},{1,1,244},{0,3,140},{0,3,41},{0,2,139},{0,3,248},{0,2,139},{0,4,10},{0,4,10},{0,4,10},{0,3,13},{0,3,52},{0,2,18},{0,2,18},{0,1,29},{0,1,77},{0,1,38},{0,4,10},{0,4,10},{0,4,10},{0,3,13},{0,3,52},
+{0,2,18},{0,2,18},{0,1,29},{1,0,58},{0,1,29},{1,3,72},{0,5,4},{0,3,17},{0,3,5},{1,3,72},{3,0,74},{0,3,5},{0,2,90},{3,0,74},{0,2,90},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,0},{0,1,0},{0,1,0},{0,1,4},{0,0,9},{0,0,9},{0,9,193},{0,7,125},{0,4,202},{0,4,122},{0,7,244},{0,5,96},{0,4,2},
+{0,3,106},{0,4,395},{0,3,187},{1,6,99},{1,5,45},{1,4,26},{1,4,50},{1,4,243},{0,5,96},{0,4,2},{0,3,106},{2,2,243},{0,3,106},{0,7,121},{0,7,121},{0,7,121},{0,4,122},{0,5,52},{0,4,2},{0,4,2},{0,3,25},{0,3,133},{0,2,62},{1,4,26},{1,4,26},{1,4,26},{1,3,25},{1,2,50},{0,4,2},{0,4,2},{0,3,25},{1,2,50},
+{0,3,25},{0,9,72},{0,7,4},{1,4,1},{0,4,1},{0,9,72},{2,3,72},{0,4,1},{0,3,90},{2,3,72},{0,3,90},{0,0,121},{0,0,121},{0,0,121},{0,0,121},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,2,37},{0,2,37},{1,8,164},{1,7,94},{1,5,106},{1,5,94},{0,10,292},{0,7,125},{0,5,81},{0,4,130},{0,6,364},{0,4,106},{1,8,83},
+{1,7,13},{1,5,25},{1,5,13},{3,0,243},{0,7,76},{0,5,32},{0,4,81},{5,0,243},{0,4,81},{1,6,91},{1,6,91},{1,6,91},{1,5,94},{0,8,99},{0,6,51},{0,6,51},{0,4,66},{0,4,107},{0,4,42},{1,6,10},{1,6,10},{1,6,10},{1,5,13},{0,8,50},{0,6,2},{0,6,2},{0,4,17},{4,0,50},{0,4,17},{3,2,74},{1,7,4},{1,5,16},
+{1,5,4},{3,2,74},{5,1,72},{1,5,4},{0,4,80},{5,1,72},{0,4,80},{1,0,90},{1,0,90},{1,0,90},{1,0,90},{0,6,50},{0,6,50},{0,6,50},{0,4,50},{0,3,20},{0,3,20},{1,11,218},{1,9,149},{1,7,242},{1,6,149},{1,10,248},{1,7,99},{1,6,5},{1,5,99},{0,7,308},{0,5,100},{2,8,99},{2,7,45},{2,6,27},{2,6,51},{3,3,243},
+{0,9,81},{1,6,5},{0,5,99},{4,3,243},{0,5,99},{1,9,145},{1,9,145},{1,9,145},{1,6,148},{1,8,52},{1,6,4},{1,6,4},{1,5,18},{0,6,72},{0,5,19},{2,6,26},{2,6,26},{2,6,26},{2,5,25},{3,1,50},{1,6,4},{1,6,4},{0,5,18},{3,3,50},{0,5,18},{4,1,72},{1,9,5},{2,6,2},{1,6,5},{4,1,72},{3,5,72},{1,6,5},
+{0,5,90},{3,5,72},{0,5,90},{1,0,144},{1,0,144},{1,0,144},{1,0,144},{1,6,0},{1,6,0},{1,6,0},{1,4,4},{0,6,8},{0,6,8},{2,10,164},{2,9,94},{2,7,107},{2,7,95},{1,12,307},{1,9,137},{1,7,115},{1,6,154},{0,9,253},{1,6,106},{2,10,83},{2,9,13},{2,7,26},{2,7,14},{4,2,243},{1,9,73},{2,7,41},{1,6,90},{6,2,243},
+{1,6,90},{2,8,91},{2,8,91},{2,8,91},{2,7,94},{1,10,116},{1,8,69},{1,8,69},{1,6,73},{0,8,50},{1,6,25},{2,8,10},{2,8,10},{2,8,10},{2,7,13},{4,0,50},{1,8,5},{1,8,5},{1,6,9},{1,7,50},{1,6,9},{3,7,72},{2,9,4},{2,7,17},{2,7,5},{3,7,72},{8,0,72},{2,7,5},{0,6,90},{8,0,72},{0,6,90},{2,0,90},
+{2,0,90},{2,0,90},{2,0,90},{1,9,65},{1,9,65},{1,9,65},{1,6,64},{0,7,10},{0,7,10},{2,13,194},{2,11,126},{2,8,203},{2,8,123},{2,11,245},{2,9,97},{2,8,3},{2,7,107},{0,11,249},{1,7,100},{3,10,99},{3,9,45},{3,8,26},{3,8,50},{3,8,243},{1,11,81},{2,8,2},{1,7,99},{4,6,243},{1,7,99},{2,11,122},{2,11,122},{2,11,122},
+{2,8,123},{2,9,53},{2,8,3},{2,8,3},{2,7,26},{1,8,62},{1,7,19},{3,8,26},{3,8,26},{3,8,26},{3,7,25},{3,6,50},{2,8,2},{2,8,2},{1,7,18},{3,6,50},{1,7,18},{5,3,72},{2,11,4},{3,8,1},{2,8,1},{5,3,72},{4,7,72},{2,8,1},{0,7,90},{4,7,72},{0,7,90},{2,0,122},{2,0,122},{2,0,122},{2,0,122},{2,8,2},
+{2,8,2},{2,8,2},{2,6,2},{1,7,10},{1,7,10},{3,12,164},{3,11,94},{3,9,106},{3,9,94},{2,14,292},{2,11,125},{2,9,81},{2,8,130},{1,11,253},{2,8,106},{3,12,83},{3,11,13},{3,9,25},{3,9,13},{5,4,243},{2,11,76},{2,9,32},{2,8,81},{9,1,243},{2,8,81},{3,10,91},{3,10,91},{3,10,91},{3,9,94},{2,12,99},{2,10,51},{2,10,51},
+{2,8,66},{1,10,50},{2,8,42},{3,10,10},{3,10,10},{3,10,10},{3,9,13},{5,2,50},{2,10,2},{2,10,2},{2,8,17},{8,1,50},{2,8,17},{1,19,72},{3,11,4},{3,9,16},{3,9,4},{1,19,72},{9,2,72},{3,9,4},{0,8,80},{9,2,72},{0,8,80},{3,0,90},{3,0,90},{3,0,90},{3,0,90},{2,10,50},{2,10,50},{2,10,50},{2,8,50},{1,9,9},
+{1,9,9},{3,15,218},{3,13,149},{3,11,242},{3,10,149},{3,14,248},{3,11,99},{3,10,5},{3,9,99},{1,13,244},{2,9,100},{4,12,99},{4,11,45},{4,10,27},{4,10,51},{5,7,243},{2,13,81},{3,10,5},{2,9,99},{6,7,243},{2,9,99},{3,13,145},{3,13,145},{3,13,145},{3,10,148},{3,12,52},{3,10,4},{3,10,4},{3,9,18},{1,12,56},{2,9,19},{4,10,26},
+{4,10,26},{4,10,26},{4,9,25},{5,5,50},{3,10,4},{3,10,4},{2,9,18},{5,7,50},{2,9,18},{7,2,72},{3,13,5},{4,10,2},{3,10,5},{7,2,72},{12,0,72},{3,10,5},{0,9,90},{12,0,72},{0,9,90},{3,0,144},{3,0,144},{3,0,144},{3,0,144},{3,10,0},{3,10,0},{3,10,0},{3,8,4},{2,10,8},{2,10,8},{4,14,164},{4,13,94},{4,11,107},
+{4,11,95},{3,16,307},{3,13,137},{3,11,115},{3,10,154},{2,13,253},{3,10,106},{4,14,83},{4,13,13},{4,11,26},{4,11,14},{7,3,243},{3,13,73},{4,11,41},{3,10,90},{11,2,243},{3,10,90},{4,12,91},{4,12,91},{4,12,91},{4,11,94},{3,14,116},{3,12,69},{3,12,69},{3,10,73},{2,12,50},{3,10,25},{4,12,10},{4,12,10},{4,12,10},{4,11,13},{7,1,50},
+{3,12,5},{3,12,5},{3,10,9},{10,2,50},{3,10,9},{5,11,72},{4,13,4},{4,11,17},{4,11,5},{5,11,72},{11,3,72},{4,11,5},{0,10,90},{11,3,72},{0,10,90},{4,0,90},{4,0,90},{4,0,90},{4,0,90},{3,13,65},{3,13,65},{3,13,65},{3,10,64},{2,11,10},{2,11,10},{4,17,194},{4,15,126},{4,12,203},{4,12,123},{4,15,245},{4,13,97},{4,12,3},
+{4,11,107},{2,15,249},{3,11,100},{5,14,99},{5,13,45},{5,12,26},{5,12,50},{5,12,243},{3,15,81},{4,12,2},{3,11,99},{13,1,243},{3,11,99},{4,15,122},{4,15,122},{4,15,122},{4,12,123},{4,13,53},{4,12,3},{4,12,3},{4,11,26},{3,12,62},{3,11,19},{5,12,26},{5,12,26},{5,12,26},{5,11,25},{5,10,50},{4,12,2},{4,12,2},{3,11,18},{12,1,50},
+{3,11,18},{8,2,72},{4,15,4},{5,12,1},{4,12,1},{8,2,72},{13,2,72},{4,12,1},{0,11,90},{13,2,72},{0,11,90},{4,0,122},{4,0,122},{4,0,122},{4,0,122},{4,12,2},{4,12,2},{4,12,2},{4,10,2},{3,11,10},{3,11,10},{5,16,164},{5,15,94},{5,13,106},{5,13,94},{4,18,292},{4,15,125},{4,13,81},{4,12,130},{3,15,253},{4,12,106},{5,16,83},
+{5,15,13},{5,13,25},{5,13,13},{8,3,243},{4,15,76},{4,13,32},{4,12,81},{11,5,243},{4,12,81},{5,14,91},{5,14,91},{5,14,91},{5,13,94},{4,16,99},{4,14,51},{4,14,51},{4,12,66},{3,14,50},{4,12,42},{5,14,10},{5,14,10},{5,14,10},{5,13,13},{8,1,50},{4,14,2},{4,14,2},{4,12,17},{10,5,50},{4,12,17},{3,23,72},{5,15,4},{5,13,16},
+{5,13,4},{3,23,72},{11,6,72},{5,13,4},{0,12,80},{11,6,72},{0,12,80},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{4,14,50},{4,14,50},{4,14,50},{4,12,50},{3,13,9},{3,13,9},{5,19,218},{5,17,149},{5,15,242},{5,14,149},{5,18,248},{5,15,99},{5,14,5},{5,13,99},{3,17,244},{4,13,100},{6,16,99},{6,15,45},{6,14,27},{6,14,51},{8,6,243},
+{4,17,81},{5,14,5},{4,13,99},{15,2,243},{4,13,99},{5,17,145},{5,17,145},{5,17,145},{5,14,148},{5,16,52},{5,14,4},{5,14,4},{5,13,18},{3,16,56},{4,13,19},{6,14,26},{6,14,26},{6,14,26},{6,13,25},{8,4,50},{5,14,4},{5,14,4},{4,13,18},{14,2,50},{4,13,18},{3,26,72},{5,17,5},{6,14,2},{5,14,5},{3,26,72},{15,3,72},{5,14,5},
+{0,13,90},{15,3,72},{0,13,90},{5,0,144},{5,0,144},{5,0,144},{5,0,144},{5,14,0},{5,14,0},{5,14,0},{5,12,4},{4,14,8},{4,14,8},{6,18,164},{6,17,94},{6,15,107},{6,15,95},{5,20,307},{5,17,137},{5,15,115},{5,14,154},{4,17,253},{5,14,106},{6,18,83},{6,17,13},{6,15,26},{6,15,14},{5,20,243},{5,17,73},{6,15,41},{5,14,90},{13,6,243},
+{5,14,90},{6,16,91},{6,16,91},{6,16,91},{6,15,94},{5,18,116},{5,16,69},{5,16,69},{5,14,73},{4,16,50},{5,14,25},{6,16,10},{6,16,10},{6,16,10},{6,15,13},{3,25,50},{5,16,5},{5,16,5},{5,14,9},{12,6,50},{5,14,9},{11,0,72},{6,17,4},{6,15,17},{6,15,5},{11,0,72},{13,7,72},{6,15,5},{0,14,90},{13,7,72},{0,14,90},{6,0,90},
+{6,0,90},{6,0,90},{6,0,90},{5,17,65},{5,17,65},{5,17,65},{5,14,64},{4,15,10},{4,15,10},{6,21,194},{6,19,126},{6,16,203},{6,16,123},{6,19,245},{6,17,97},{6,16,3},{6,15,107},{4,19,249},{5,15,100},{7,18,99},{7,17,45},{7,16,26},{7,16,50},{11,1,243},{5,19,81},{6,16,2},{5,15,99},{15,5,243},{5,15,99},{6,19,122},{6,19,122},{6,19,122},
+{6,16,123},{6,17,53},{6,16,3},{6,16,3},{6,15,26},{5,16,62},{5,15,19},{7,16,26},{7,16,26},{7,16,26},{7,15,25},{9,6,50},{6,16,2},{6,16,2},{5,15,18},{14,5,50},{5,15,18},{10,6,72},{6,19,4},{7,16,1},{6,16,1},{10,6,72},{15,6,72},{6,16,1},{0,15,90},{15,6,72},{0,15,90},{6,0,122},{6,0,122},{6,0,122},{6,0,122},{6,16,2},
+{6,16,2},{6,16,2},{6,14,2},{5,15,10},{5,15,10},{7,20,164},{7,19,94},{7,17,106},{7,17,94},{6,22,292},{6,19,125},{6,17,81},{6,16,130},{5,19,253},{6,16,106},{7,20,83},{7,19,13},{7,17,25},{7,17,13},{10,7,243},{6,19,76},{6,17,32},{6,16,81},{13,9,243},{6,16,81},{7,18,91},{7,18,91},{7,18,91},{7,17,94},{6,20,99},{6,18,51},{6,18,51},
+{6,16,66},{5,18,50},{6,16,42},{7,18,10},{7,18,10},{7,18,10},{7,17,13},{10,5,50},{6,18,2},{6,18,2},{6,16,17},{12,9,50},{6,16,17},{12,2,72},{7,19,4},{7,17,16},{7,17,4},{12,2,72},{13,10,72},{7,17,4},{0,16,80},{13,10,72},{0,16,80},{7,0,90},{7,0,90},{7,0,90},{7,0,90},{6,18,50},{6,18,50},{6,18,50},{6,16,50},{5,17,9},
+{5,17,9},{7,23,218},{7,21,149},{7,19,242},{7,18,149},{7,22,248},{7,19,99},{7,18,5},{7,17,99},{5,21,244},{6,17,100},{7,23,218},{7,21,149},{8,18,206},{7,18,149},{13,0,243},{6,21,81},{7,18,5},{6,17,99},{5,21,243},{6,17,99},{7,21,145},{7,21,145},{7,21,145},{7,18,148},{7,20,52},{7,18,4},{7,18,4},{7,17,18},{5,20,56},{6,17,19},{7,21,145},
+{7,21,145},{7,21,145},{7,18,148},{10,8,50},{7,18,4},{7,18,4},{6,17,18},{11,12,50},{6,17,18},{9,15,72},{7,21,5},{8,18,37},{7,18,5},{9,15,72},{5,22,72},{7,18,5},{0,17,90},{5,22,72},{0,17,90},{7,0,144},{7,0,144},{7,0,144},{7,0,144},{7,18,0},{7,18,0},{7,18,0},{7,16,4},{6,18,8},{6,18,8},{8,21,388},{8,20,334},{8,19,316},
+{8,19,340},{7,24,307},{7,21,137},{7,19,115},{7,18,154},{6,21,253},{7,18,106},{8,21,99},{8,20,45},{8,19,27},{8,19,51},{8,19,243},{7,21,73},{7,19,51},{7,18,90},{15,10,243},{7,18,90},{8,19,315},{8,19,315},{8,19,315},{8,18,314},{7,22,116},{7,20,69},{7,20,69},{7,18,73},{6,20,50},{7,18,25},{8,19,26},{8,19,26},{8,19,26},{8,18,25},{9,14,50},
+{7,20,5},{7,20,5},{7,18,9},{14,10,50},{7,18,9},{13,4,72},{8,20,20},{8,19,2},{7,19,26},{13,4,72},{15,11,72},{7,19,26},{0,18,90},{15,11,72},{0,18,90},{8,0,314},{8,0,314},{8,0,314},{8,0,314},{7,21,65},{7,21,65},{7,21,65},{7,18,64},{6,19,10},{6,19,10},{8,23,164},{8,22,94},{8,20,106},{8,20,94},{8,22,329},{8,20,221},{8,20,121},
+{8,19,220},{6,23,249},{7,19,100},{8,23,83},{8,22,13},{8,20,25},{8,20,13},{13,5,243},{7,23,81},{8,20,40},{7,19,99},{12,15,243},{7,19,99},{8,21,91},{8,21,91},{8,21,91},{8,20,94},{8,20,133},{8,19,99},{8,19,99},{8,18,110},{7,20,62},{7,19,19},{8,21,10},{8,21,10},{8,21,10},{8,20,13},{11,10,50},{8,19,18},{8,19,18},{7,19,18},{5,23,50},
+{7,19,18},{15,0,72},{8,22,4},{8,20,16},{8,20,4},{15,0,72},{12,16,72},{8,20,4},{0,19,90},{12,16,72},{0,19,90},{8,0,90},{8,0,90},{8,0,90},{8,0,90},{8,18,81},{8,18,81},{8,18,81},{8,18,85},{7,19,10},{7,19,10},{8,26,194},{8,24,131},{8,21,203},{8,21,123},{8,24,245},{8,22,97},{8,21,3},{8,20,97},{7,23,253},{7,20,141},{9,23,99},
+{9,22,45},{9,21,26},{9,21,50},{15,1,243},{8,22,96},{8,21,2},{8,20,96},{15,13,243},{8,20,96},{8,24,122},{8,24,122},{8,24,122},{8,21,123},{8,22,53},{8,21,3},{8,21,3},{8,19,27},{7,22,50},{8,19,75},{9,21,26},{9,21,26},{9,21,26},{9,20,25},{12,9,50},{8,21,2},{8,21,2},{8,19,26},{14,13,50},{8,19,26},{14,6,72},{8,24,9},{9,21,1},
+{8,21,1},{14,6,72},{15,14,72},{8,21,1},{0,20,80},{15,14,72},{0,20,80},{8,0,122},{8,0,122},{8,0,122},{8,0,122},{8,21,2},{8,21,2},{8,21,2},{8,19,2},{7,21,9},{7,21,9},{9,26,154},{9,24,81},{9,22,106},{9,22,82},{9,24,307},{8,24,137},{9,22,91},{8,21,154},{7,25,244},{8,21,106},{9,26,90},{9,24,17},{9,22,42},{9,22,18},{15,4,243},
+{8,24,73},{9,22,27},{8,21,90},{9,22,243},{8,21,90},{9,24,81},{9,24,81},{9,24,81},{9,22,81},{9,22,114},{8,23,68},{8,23,68},{8,21,73},{7,24,56},{8,21,25},{9,24,17},{9,24,17},{9,24,17},{9,22,17},{15,2,50},{8,23,4},{8,23,4},{8,21,9},{13,16,50},{8,21,9},{11,19,72},{9,24,1},{9,22,26},{9,22,2},{11,19,72},{9,23,72},{9,22,2},
+{0,21,90},{9,23,72},{0,21,90},{9,0,80},{9,0,80},{9,0,80},{9,0,80},{9,20,65},{9,20,65},{9,20,65},{8,21,64},{8,21,16},{8,21,16},{9,28,216},{9,26,149},{9,23,245},{9,23,149},{9,27,248},{9,24,89},{9,23,5},{9,22,99},{7,27,260},{8,22,100},{10,25,99},{10,24,45},{10,23,27},{10,23,51},{10,23,243},{8,26,81},{9,23,5},{8,22,99},{11,21,243},
+{8,22,99},{9,26,145},{9,26,145},{9,26,145},{9,23,148},{9,25,52},{9,23,4},{9,23,4},{9,22,18},{8,23,72},{8,22,19},{10,23,26},{10,23,26},{10,23,26},{10,22,25},{11,18,50},{9,23,4},{9,23,4},{8,22,18},{10,21,50},{8,22,18},{15,8,72},{9,26,5},{10,23,2},{9,23,5},{15,8,72},{11,22,72},{9,23,5},{0,22,90},{11,22,72},{0,22,90},{9,0,144},
+{9,0,144},{9,0,144},{9,0,144},{9,23,0},{9,23,0},{9,23,0},{9,21,4},{8,23,8},{8,23,8},{10,27,164},{10,26,94},{10,24,106},{10,24,94},{9,29,307},{9,26,137},{9,24,105},{9,23,154},{8,26,253},{9,23,106},{10,27,83},{10,26,13},{10,24,25},{10,24,13},{15,9,243},{9,26,73},{10,24,40},{9,23,90},{14,19,243},{9,23,90},{10,25,91},{10,25,91},{10,25,91},
+{10,24,94},{9,27,116},{9,25,69},{9,25,69},{9,23,73},{8,25,50},{9,23,25},{10,25,10},{10,25,10},{10,25,10},{10,24,13},{13,14,50},{9,25,5},{9,25,5},{9,23,9},{8,25,50},{9,23,9},{14,14,72},{10,26,4},{10,24,16},{10,24,4},{14,14,72},{14,20,72},{10,24,4},{0,23,90},{14,20,72},{0,23,90},{10,0,90},{10,0,90},{10,0,90},{10,0,90},{9,26,65},
+{9,26,65},{9,26,65},{9,23,64},{8,24,9},{8,24,9},{10,30,194},{10,28,131},{10,25,203},{10,25,123},{10,28,245},{10,26,97},{10,25,3},{10,24,97},{8,28,252},{9,24,85},{11,27,99},{11,26,45},{11,25,26},{11,25,50},{14,15,243},{9,28,80},{10,25,2},{9,24,84},{12,23,243},{9,24,84},{10,28,122},{10,28,122},{10,28,122},{10,25,123},{10,26,53},{10,25,3},{10,25,3},
+{10,23,27},{9,25,62},{9,24,21},{11,25,26},{11,25,26},{11,25,26},{11,24,25},{14,13,50},{10,25,2},{10,25,2},{9,24,20},{11,23,50},{9,24,20},{13,20,72},{10,28,9},{11,25,1},{10,25,1},{13,20,72},{13,23,74},{10,25,1},{0,24,80},{13,23,74},{0,24,80},{10,0,122},{10,0,122},{10,0,122},{10,0,122},{10,25,2},{10,25,2},{10,25,2},{10,23,2},{9,24,5},
+{9,24,5},{11,30,154},{11,28,81},{11,26,106},{11,26,82},{11,28,307},{10,28,137},{11,26,91},{10,25,154},{9,28,260},{10,25,106},{11,30,90},{11,28,17},{11,26,42},{11,26,18},{14,18,243},{10,28,73},{11,26,27},{10,25,90},{11,26,243},{10,25,90},{11,28,81},{11,28,81},{11,28,81},{11,26,81},{11,26,114},{10,27,68},{10,27,68},{10,25,73},{9,27,53},{10,25,25},{11,28,17},
+{11,28,17},{11,28,17},{11,26,17},{14,16,50},{10,27,4},{10,27,4},{10,25,9},{15,20,50},{10,25,9},{13,23,72},{11,28,1},{11,26,26},{11,26,2},{13,23,72},{11,27,72},{11,26,2},{0,25,90},{11,27,72},{0,25,90},{11,0,80},{11,0,80},{11,0,80},{11,0,80},{11,24,65},{11,24,65},{11,24,65},{10,25,64},{10,25,16},{10,25,16},{11,31,248},{11,30,149},{11,27,245},
+{11,27,149},{11,31,248},{11,28,89},{11,27,5},{11,26,99},{9,30,244},{10,26,100},{12,29,99},{12,28,45},{12,27,27},{12,27,51},{12,27,243},{10,30,81},{11,27,5},{10,26,99},{13,25,243},{10,26,99},{11,30,145},{11,30,145},{11,30,145},{11,27,148},{11,29,52},{11,27,4},{11,27,4},{11,26,18},{9,29,56},{10,26,19},{12,27,26},{12,27,26},{12,27,26},{12,26,25},{13,22,50},
+{11,27,4},{11,27,4},{10,26,18},{12,25,50},{10,26,18},{15,19,72},{11,30,5},{12,27,2},{11,27,5},{15,19,72},{13,26,72},{11,27,5},{0,26,90},{13,26,72},{0,26,90},{11,0,144},{11,0,144},{11,0,144},{11,0,144},{11,27,0},{11,27,0},{11,27,0},{11,25,4},{10,27,8},{10,27,8},{12,31,164},{12,30,94},{12,28,106},{12,28,94},{12,30,329},{11,30,137},{11,28,105},
+{11,27,154},{10,30,253},{11,27,106},{12,31,83},{12,30,13},{12,28,25},{12,28,13},{14,23,243},{11,30,73},{12,28,40},{11,27,90},{11,29,243},{11,27,90},{12,29,91},{12,29,91},{12,29,91},{12,28,94},{11,31,116},{11,29,69},{11,29,69},{11,27,73},{10,29,50},{11,27,25},{12,29,10},{12,29,10},{12,29,10},{12,28,13},{15,18,50},{11,29,5},{11,29,5},{11,27,9},{10,29,50},
+{11,27,9},{13,28,72},{12,30,4},{12,28,16},{12,28,4},{13,28,72},{11,30,72},{12,28,4},{0,27,90},{11,30,72},{0,27,90},{12,0,90},{12,0,90},{12,0,90},{12,0,90},{11,30,65},{11,30,65},{11,30,65},{11,27,64},{10,28,9},{10,28,9},{12,31,356},{12,31,140},{12,29,203},{12,29,123},{12,31,284},{12,30,97},{12,29,3},{12,28,97},{10,31,287},{11,28,85},{13,31,99},
+{13,30,45},{13,29,26},{13,29,50},{13,29,243},{12,30,96},{12,29,2},{11,28,84},{14,27,243},{11,28,84},{12,31,131},{12,31,131},{12,31,131},{12,29,123},{12,30,53},{12,29,3},{12,29,3},{12,27,27},{11,29,62},{11,28,21},{13,29,26},{13,29,26},{13,29,26},{13,28,25},{13,27,50},{12,29,2},{12,29,2},{11,28,20},{13,27,50},{11,28,20},{15,24,72},{12,31,18},{13,29,1},
+{12,29,1},{15,24,72},{15,27,74},{12,29,1},{0,28,80},{15,27,74},{0,28,80},{12,0,122},{12,0,122},{12,0,122},{12,0,122},{12,29,2},{12,29,2},{12,29,2},{12,27,2},{11,28,5},{11,28,5},{13,31,280},{13,31,120},{13,30,106},{13,30,82},{13,31,328},{13,31,200},{13,30,91},{12,29,154},{12,31,344},{12,29,106},{13,31,216},{13,31,56},{13,30,42},{13,30,18},{15,25,244},
+{13,31,136},{13,30,27},{12,29,90},{13,30,243},{12,29,90},{13,31,84},{13,31,84},{13,31,84},{13,30,81},{13,30,114},{12,31,68},{12,31,68},{12,29,73},{11,31,53},{12,29,25},{13,31,20},{13,31,20},{13,31,20},{13,30,17},{13,30,50},{12,31,4},{12,31,4},{12,29,9},{12,30,50},{12,29,9},{15,27,72},{13,31,40},{13,30,26},{13,30,2},{15,27,72},{13,31,72},{13,30,2},
+{0,29,90},{13,31,72},{0,29,90},{13,0,80},{13,0,80},{13,0,80},{13,0,80},{13,28,65},{13,28,65},{13,28,65},{12,29,64},{12,29,16},{12,29,16},{14,31,415},{14,31,351},{13,31,244},{13,31,148},{14,31,511},{13,31,173},{13,31,4},{13,30,82},{13,31,381},{12,30,83},{14,31,126},{14,31,62},{14,31,26},{14,31,50},{14,31,222},{13,31,173},{13,31,4},{12,30,82},{14,30,221},
+{12,30,82},{13,31,244},{13,31,244},{13,31,244},{13,31,148},{13,31,100},{13,31,4},{13,31,4},{13,30,18},{12,31,72},{12,30,19},{14,31,26},{14,31,26},{14,31,26},{14,30,25},{15,26,50},{13,31,4},{13,31,4},{12,30,18},{14,29,50},{12,30,18},{15,29,61},{14,31,37},{14,31,1},{13,31,4},{15,29,61},{15,30,61},{13,31,4},{0,30,73},{15,30,61},{0,30,73},{13,0,144},
+{13,0,144},{13,0,144},{13,0,144},{13,31,0},{13,31,0},{13,31,0},{13,29,4},{12,31,8},{12,31,8},{14,31,239},{14,31,175},{14,31,139},{14,31,99},{14,31,239},{14,31,135},{14,31,99},{13,31,73},{13,31,285},{13,31,25},{14,31,158},{14,31,94},{14,31,58},{14,31,18},{15,29,94},{14,31,54},{14,31,18},{13,31,9},{15,30,93},{13,31,9},{14,31,139},{14,31,139},{14,31,139},
+{14,31,99},{14,31,139},{14,31,99},{14,31,99},{13,31,73},{13,31,116},{13,31,25},{14,31,58},{14,31,58},{14,31,58},{14,31,18},{15,28,52},{14,31,18},{14,31,18},{13,31,9},{15,29,58},{13,31,9},{15,30,9},{15,31,9},{15,31,9},{14,31,9},{15,30,9},{15,31,9},{14,31,9},{0,31,9},{15,31,9},{0,31,9},{14,0,90},{14,0,90},{14,0,90},{14,0,90},{14,30,81},
+{14,30,81},{14,30,81},{13,31,64},{13,31,16},{13,31,16},{15,31,314},{14,31,258},{14,31,222},{14,31,158},{14,31,226},{14,31,98},{14,31,62},{14,31,2},{14,31,122},{14,31,50},{15,31,25},{15,31,25},{15,31,25},{15,31,25},{15,30,22},{15,31,25},{15,31,25},{14,31,1},{15,31,25},{14,31,1},{14,31,222},{14,31,222},{14,31,222},{14,31,158},{14,31,126},{14,31,62},{14,31,62},
+{14,31,2},{14,31,86},{14,31,50},{15,31,25},{15,31,25},{15,31,25},{15,31,25},{15,30,13},{15,31,25},{15,31,25},{14,31,1},{15,30,25},{14,31,1},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{14,0,122},{14,0,122},{14,0,122},{14,0,122},{14,31,26},{14,31,26},{14,31,26},{14,31,2},{14,31,50},
+{14,31,50},{0,6,202},{0,5,52},{0,3,25},{0,3,61},{0,4,442},{0,3,313},{0,3,142},{0,2,318},{0,2,498},{0,2,354},{0,6,202},{0,5,52},{0,3,25},{0,3,61},{1,1,441},{0,3,313},{0,3,142},{0,2,318},{2,0,442},{0,2,318},{0,3,0},{0,3,0},{0,3,0},{0,2,1},{0,1,45},{0,1,25},{0,1,25},{0,1,26},{0,1,50},{0,1,35},{0,3,0},
+{0,3,0},{0,3,0},{0,2,1},{0,1,45},{0,1,25},{0,1,25},{0,1,26},{0,1,41},{0,1,26},{1,3,200},{0,5,52},{0,3,25},{0,3,61},{1,3,200},{3,0,202},{0,3,61},{0,2,218},{3,0,202},{0,2,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,9,200},{0,7,20},{0,5,20},
+{0,4,25},{0,6,686},{0,5,433},{0,4,169},{0,3,443},{0,3,794},{0,3,524},{0,9,200},{0,7,20},{0,5,20},{0,4,25},{0,6,686},{0,5,433},{0,4,169},{0,3,443},{3,0,686},{0,3,443},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{0,3,145},{0,2,85},{0,2,85},{0,2,101},{0,1,178},{0,1,115},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{0,3,145},
+{0,2,85},{0,2,85},{0,2,101},{0,2,149},{0,2,101},{0,9,200},{0,7,20},{0,5,20},{0,4,25},{0,9,200},{2,3,200},{0,4,25},{0,3,218},{2,3,200},{0,3,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,11,257},{0,9,54},{0,6,114},{0,5,65},{0,9,728},{0,6,371},{0,5,80},
+{0,4,377},{0,5,949},{0,4,521},{0,11,257},{0,9,54},{1,5,97},{0,5,65},{2,2,723},{0,6,371},{0,5,80},{0,4,377},{1,4,723},{0,4,377},{0,8,50},{0,8,50},{0,8,50},{0,5,49},{0,5,164},{0,4,50},{0,4,50},{0,3,65},{0,3,245},{0,2,126},{0,8,50},{0,8,50},{0,8,50},{0,5,49},{1,2,162},{0,4,50},{0,4,50},{0,3,65},{1,2,162},
+{0,3,65},{3,2,202},{0,9,5},{1,5,16},{0,5,16},{3,2,202},{5,1,200},{0,5,16},{0,4,208},{5,1,200},{0,4,208},{0,0,49},{0,0,49},{0,0,49},{0,0,49},{0,2,1},{0,2,1},{0,2,1},{0,1,4},{0,1,13},{0,1,13},{0,14,425},{0,11,234},{1,7,277},{0,7,245},{0,11,724},{0,8,289},{0,6,34},{0,5,308},{0,6,1087},{0,5,533},{1,11,201},
+{1,9,18},{1,7,21},{1,6,26},{1,8,723},{0,8,289},{0,6,34},{0,5,308},{4,2,723},{0,5,308},{0,11,225},{0,11,225},{0,11,225},{0,7,229},{0,8,162},{0,6,18},{0,6,18},{0,4,25},{0,4,338},{0,3,162},{1,8,2},{1,8,2},{1,8,2},{1,5,5},{0,8,162},{0,6,18},{0,6,18},{0,4,25},{4,0,162},{0,4,25},{3,4,200},{0,11,9},{1,7,20},
+{0,7,20},{3,4,200},{7,0,200},{0,7,20},{0,5,208},{7,0,200},{0,5,208},{0,0,225},{0,0,225},{0,0,225},{0,0,225},{0,5,0},{0,5,0},{0,5,0},{0,3,0},{0,2,61},{0,2,61},{1,14,410},{1,11,209},{1,8,288},{1,7,234},{0,14,739},{0,10,254},{0,8,33},{0,6,270},{0,8,1131},{0,6,450},{1,14,266},{1,11,65},{2,7,106},{1,7,90},{3,4,723},
+{0,10,238},{0,8,17},{0,6,254},{7,0,723},{0,6,254},{1,11,209},{1,11,209},{1,11,209},{1,7,209},{0,11,178},{0,8,17},{0,8,17},{0,5,18},{0,6,376},{0,5,123},{1,11,65},{1,11,65},{1,11,65},{1,7,65},{3,1,162},{0,8,1},{0,8,1},{0,5,2},{3,3,162},{0,5,2},{3,7,200},{1,11,1},{2,7,25},{0,8,17},{3,7,200},{8,0,200},{0,8,17},
+{0,6,218},{8,0,200},{0,6,218},{1,0,208},{1,0,208},{1,0,208},{1,0,208},{0,8,16},{0,8,16},{0,8,16},{0,5,17},{0,4,80},{0,4,80},{1,16,474},{1,13,276},{1,9,457},{1,9,292},{1,13,740},{1,10,298},{1,8,45},{1,7,315},{0,9,1013},{0,7,308},{2,13,201},{2,11,21},{2,9,21},{2,8,26},{5,0,723},{0,12,227},{1,8,29},{0,7,227},{5,4,723},
+{0,7,227},{1,13,272},{1,13,272},{1,13,272},{1,9,276},{1,10,180},{1,8,29},{1,8,29},{1,6,33},{0,8,306},{0,6,41},{2,10,2},{2,10,2},{2,10,2},{2,7,5},{4,0,162},{0,10,5},{0,10,5},{0,6,5},{1,7,162},{0,6,5},{5,3,200},{1,13,4},{2,9,20},{1,9,20},{5,3,200},{4,7,200},{1,9,20},{0,7,218},{4,7,200},{0,7,218},{1,0,272},
+{1,0,272},{1,0,272},{1,0,272},{1,7,17},{1,7,17},{1,7,17},{1,5,17},{0,6,40},{0,6,40},{2,15,426},{2,13,223},{2,10,283},{2,9,234},{1,16,739},{1,12,267},{1,10,33},{1,8,273},{0,11,913},{0,8,225},{2,15,257},{2,13,54},{3,9,97},{2,9,65},{4,6,723},{0,13,208},{1,10,17},{0,8,209},{3,8,723},{0,8,209},{2,12,219},{2,12,219},{2,12,219},
+{2,9,218},{1,13,180},{1,10,17},{1,10,17},{1,7,18},{0,9,229},{0,7,27},{2,12,50},{2,12,50},{2,12,50},{2,9,49},{3,6,162},{1,10,1},{1,10,1},{1,7,2},{3,6,162},{1,7,2},{1,19,200},{2,13,5},{3,9,16},{2,9,16},{1,19,200},{9,2,200},{2,9,16},{0,8,208},{9,2,200},{0,8,208},{2,0,218},{2,0,218},{2,0,218},{2,0,218},{1,10,16},
+{1,10,16},{1,10,16},{1,7,17},{0,8,17},{0,8,17},{2,18,450},{2,15,259},{2,11,410},{2,11,270},{2,15,749},{2,12,314},{2,10,59},{2,9,333},{0,13,868},{0,9,213},{3,15,201},{3,13,18},{3,11,21},{3,10,26},{6,2,723},{0,15,204},{2,10,34},{0,9,212},{8,3,723},{0,9,212},{2,15,250},{2,15,250},{2,15,250},{2,11,254},{2,12,187},{2,10,43},{2,10,43},
+{2,8,50},{0,11,189},{1,8,37},{3,12,2},{3,12,2},{3,12,2},{3,9,5},{5,2,162},{1,12,2},{1,12,2},{1,8,1},{8,1,162},{1,8,1},{5,8,200},{2,15,9},{3,11,20},{2,11,20},{5,8,200},{4,10,200},{2,11,20},{0,9,208},{4,10,200},{0,9,208},{2,0,250},{2,0,250},{2,0,250},{2,0,250},{2,9,25},{2,9,25},{2,9,25},{2,7,25},{0,9,5},
+{0,9,5},{3,18,410},{3,15,209},{3,12,288},{3,11,234},{2,18,739},{2,14,254},{2,12,33},{2,10,270},{0,15,804},{1,10,227},{3,18,266},{3,15,65},{4,11,106},{3,11,90},{5,8,723},{1,15,219},{2,12,17},{1,10,218},{4,10,723},{1,10,218},{3,15,209},{3,15,209},{3,15,209},{3,11,209},{2,15,178},{2,12,17},{2,12,17},{2,9,18},{0,13,171},{1,9,26},{3,15,65},
+{3,15,65},{3,15,65},{3,11,65},{5,5,162},{2,12,1},{2,12,1},{2,9,2},{5,7,162},{2,9,2},{5,11,200},{3,15,1},{4,11,25},{2,12,17},{5,11,200},{11,3,200},{2,12,17},{0,10,218},{11,3,200},{0,10,218},{3,0,208},{3,0,208},{3,0,208},{3,0,208},{2,12,16},{2,12,16},{2,12,16},{2,9,17},{1,10,9},{1,10,9},{3,20,474},{3,17,276},{3,13,457},
+{3,13,292},{3,17,740},{3,14,298},{3,12,45},{3,11,315},{0,16,747},{1,11,231},{4,17,201},{4,15,21},{4,13,21},{4,12,26},{7,4,723},{1,17,209},{3,12,29},{1,11,227},{9,5,723},{1,11,227},{3,17,272},{3,17,272},{3,17,272},{3,13,276},{3,14,180},{3,12,29},{3,12,29},{3,10,33},{0,15,171},{2,10,41},{4,14,2},{4,14,2},{4,14,2},{4,11,5},{7,1,162},
+{2,14,5},{2,14,5},{2,10,5},{10,2,162},{2,10,5},{8,2,200},{3,17,4},{4,13,20},{3,13,20},{8,2,200},{13,2,200},{3,13,20},{0,11,218},{13,2,200},{0,11,218},{3,0,272},{3,0,272},{3,0,272},{3,0,272},{3,11,17},{3,11,17},{3,11,17},{3,9,17},{1,12,8},{1,12,8},{4,19,426},{4,17,223},{4,14,283},{4,13,234},{3,20,739},{3,16,267},{3,14,33},
+{3,12,273},{0,18,727},{2,12,225},{4,19,257},{4,17,54},{5,13,97},{4,13,65},{6,10,723},{2,17,208},{3,14,17},{2,12,209},{12,3,723},{2,12,209},{4,16,219},{4,16,219},{4,16,219},{4,13,218},{3,17,180},{3,14,17},{3,14,17},{3,11,18},{1,15,171},{2,11,27},{4,16,50},{4,16,50},{4,16,50},{4,13,49},{5,10,162},{3,14,1},{3,14,1},{3,11,2},{12,1,162},
+{3,11,2},{3,23,200},{4,17,5},{5,13,16},{4,13,16},{3,23,200},{11,6,200},{4,13,16},{0,12,208},{11,6,200},{0,12,208},{4,0,218},{4,0,218},{4,0,218},{4,0,218},{3,14,16},{3,14,16},{3,14,16},{3,11,17},{1,13,10},{1,13,10},{4,22,450},{4,19,259},{4,15,410},{4,15,270},{4,19,749},{4,16,314},{4,14,59},{4,13,333},{1,18,747},{2,13,213},{5,19,201},
+{5,17,18},{5,15,21},{5,14,26},{9,1,723},{2,19,204},{4,14,34},{2,13,212},{15,1,723},{2,13,212},{4,19,250},{4,19,250},{4,19,250},{4,15,254},{4,16,187},{4,14,43},{4,14,43},{4,12,50},{1,16,174},{3,12,37},{5,16,2},{5,16,2},{5,16,2},{5,13,5},{8,1,162},{3,16,2},{3,16,2},{3,12,1},{10,5,162},{3,12,1},{9,4,200},{4,19,9},{5,15,20},
+{4,15,20},{9,4,200},{9,10,200},{4,15,20},{0,13,208},{9,10,200},{0,13,208},{4,0,250},{4,0,250},{4,0,250},{4,0,250},{4,13,25},{4,13,25},{4,13,25},{4,11,25},{2,13,5},{2,13,5},{5,22,410},{5,19,209},{5,16,288},{5,15,234},{4,22,739},{4,18,254},{4,16,33},{4,14,270},{1,20,724},{3,14,227},{5,22,266},{5,19,65},{6,15,106},{5,15,90},{9,4,723},
+{3,19,219},{4,16,17},{3,14,218},{9,10,723},{3,14,218},{5,19,209},{5,19,209},{5,19,209},{5,15,209},{4,19,178},{4,16,17},{4,16,17},{4,13,18},{2,17,171},{3,13,26},{5,19,65},{5,19,65},{5,19,65},{5,15,65},{8,4,162},{4,16,1},{4,16,1},{4,13,2},{14,2,162},{4,13,2},{11,0,200},{5,19,1},{6,15,25},{4,16,17},{11,0,200},{13,7,200},{4,16,17},
+{0,14,218},{13,7,200},{0,14,218},{5,0,208},{5,0,208},{5,0,208},{5,0,208},{4,16,16},{4,16,16},{4,16,16},{4,13,17},{3,14,9},{3,14,9},{5,24,474},{5,21,276},{5,17,457},{5,17,292},{5,21,740},{5,18,298},{5,16,45},{5,15,315},{1,22,740},{3,15,231},{6,21,201},{6,19,21},{6,17,21},{6,16,26},{10,3,723},{3,21,209},{5,16,29},{3,15,227},{11,9,723},
+{3,15,227},{5,21,272},{5,21,272},{5,21,272},{5,17,276},{5,18,180},{5,16,29},{5,16,29},{5,14,33},{2,19,171},{4,14,41},{6,18,2},{6,18,2},{6,18,2},{6,15,5},{3,25,162},{4,18,5},{4,18,5},{4,14,5},{12,6,162},{4,14,5},{10,6,200},{5,21,4},{6,17,20},{5,17,20},{10,6,200},{15,6,200},{5,17,20},{0,15,218},{15,6,200},{0,15,218},{5,0,272},
+{5,0,272},{5,0,272},{5,0,272},{5,15,17},{5,15,17},{5,15,17},{5,13,17},{3,16,8},{3,16,8},{6,23,426},{6,21,223},{6,18,283},{6,17,234},{5,24,739},{5,20,267},{5,18,33},{5,16,273},{2,22,727},{4,16,225},{6,23,257},{6,21,54},{7,17,97},{6,17,65},{9,9,723},{4,21,208},{5,18,17},{4,16,209},{14,7,723},{4,16,209},{6,20,219},{6,20,219},{6,20,219},
+{6,17,218},{5,21,180},{5,18,17},{5,18,17},{5,15,18},{3,19,171},{4,15,27},{6,20,50},{6,20,50},{6,20,50},{6,17,49},{9,6,162},{5,18,1},{5,18,1},{5,15,2},{14,5,162},{5,15,2},{12,2,200},{6,21,5},{7,17,16},{6,17,16},{12,2,200},{13,10,200},{6,17,16},{0,16,208},{13,10,200},{0,16,208},{6,0,218},{6,0,218},{6,0,218},{6,0,218},{5,18,16},
+{5,18,16},{5,18,16},{5,15,17},{3,17,10},{3,17,10},{6,26,450},{6,23,259},{6,19,410},{6,19,270},{6,23,749},{6,20,314},{6,18,59},{6,17,333},{3,22,747},{4,17,213},{7,23,201},{7,21,18},{7,19,21},{7,18,26},{11,5,723},{4,23,204},{6,18,34},{4,17,212},{12,11,723},{4,17,212},{6,23,250},{6,23,250},{6,23,250},{6,19,254},{6,20,187},{6,18,43},{6,18,43},
+{6,16,50},{3,20,174},{5,16,37},{7,20,2},{7,20,2},{7,20,2},{7,17,5},{10,5,162},{5,20,2},{5,20,2},{5,16,1},{12,9,162},{5,16,1},{11,8,200},{6,23,9},{7,19,20},{6,19,20},{11,8,200},{11,14,200},{6,19,20},{0,17,208},{11,14,200},{0,17,208},{6,0,250},{6,0,250},{6,0,250},{6,0,250},{6,17,25},{6,17,25},{6,17,25},{6,15,25},{4,17,5},
+{4,17,5},{7,26,410},{7,23,209},{7,20,288},{7,19,234},{6,26,739},{6,22,254},{6,20,33},{6,18,270},{3,24,724},{5,18,227},{7,26,266},{7,23,65},{7,20,144},{7,19,90},{11,8,723},{5,23,219},{6,20,17},{5,18,218},{11,14,723},{5,18,218},{7,23,209},{7,23,209},{7,23,209},{7,19,209},{6,23,178},{6,20,17},{6,20,17},{6,17,18},{4,21,171},{5,17,26},{7,23,65},
+{7,23,65},{7,23,65},{7,19,65},{10,8,162},{6,20,1},{6,20,1},{6,17,2},{11,12,162},{6,17,2},{13,4,200},{7,23,1},{8,19,50},{6,20,17},{13,4,200},{15,11,200},{6,20,17},{0,18,218},{15,11,200},{0,18,218},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{6,20,16},{6,20,16},{6,20,16},{6,17,17},{5,18,9},{5,18,9},{7,28,474},{7,25,276},{7,21,457},
+{7,21,292},{7,25,740},{7,22,298},{7,20,45},{7,19,315},{3,26,740},{5,19,231},{8,23,283},{8,22,133},{8,20,97},{8,20,133},{12,7,723},{5,25,209},{7,20,29},{5,19,227},{13,13,723},{5,19,227},{7,25,272},{7,25,272},{7,25,272},{7,21,276},{7,22,180},{7,20,29},{7,20,29},{7,18,33},{4,23,171},{6,18,41},{8,20,81},{8,20,81},{8,20,81},{8,19,82},{9,14,162},
+{6,22,5},{6,22,5},{6,18,5},{14,10,162},{6,18,5},{15,0,200},{7,25,4},{8,20,16},{7,21,20},{15,0,200},{12,16,200},{7,21,20},{0,19,218},{12,16,200},{0,19,218},{7,0,272},{7,0,272},{7,0,272},{7,0,272},{7,19,17},{7,19,17},{7,19,17},{7,17,17},{5,20,8},{5,20,8},{8,26,642},{8,24,459},{8,22,462},{8,21,467},{7,28,739},{7,24,267},{7,22,33},
+{7,20,273},{4,26,727},{6,20,225},{8,26,201},{8,24,18},{8,22,21},{8,21,26},{14,3,723},{6,25,208},{7,22,17},{6,20,209},{11,17,723},{6,20,209},{8,23,443},{8,23,443},{8,23,443},{8,20,446},{7,25,180},{7,22,17},{7,22,17},{7,19,18},{5,23,171},{6,19,27},{8,23,2},{8,23,2},{8,23,2},{8,20,5},{11,10,162},{7,22,1},{7,22,1},{7,19,2},{5,23,162},
+{7,19,2},{14,6,200},{8,24,17},{8,22,20},{7,22,17},{14,6,200},{15,14,200},{7,22,17},{0,20,208},{15,14,200},{0,20,208},{8,0,442},{8,0,442},{8,0,442},{8,0,442},{7,22,16},{7,22,16},{7,22,16},{7,19,17},{5,21,10},{5,21,10},{8,28,420},{8,26,223},{8,23,283},{8,22,234},{7,31,872},{7,26,371},{7,23,201},{7,21,368},{5,26,747},{6,21,213},{8,28,251},
+{8,26,54},{9,22,97},{8,22,65},{13,9,723},{6,27,204},{7,23,57},{6,21,212},{14,15,723},{6,21,212},{8,25,219},{8,25,219},{8,25,219},{8,22,218},{7,27,308},{7,24,146},{7,24,146},{7,20,145},{5,24,174},{7,20,37},{8,25,50},{8,25,50},{8,25,50},{8,22,49},{12,9,162},{7,24,2},{7,24,2},{7,20,1},{14,13,162},{7,20,1},{13,12,200},{8,26,5},{9,22,16},
+{8,22,16},{13,12,200},{13,18,200},{8,22,16},{0,21,208},{13,18,200},{0,21,208},{8,0,218},{8,0,218},{8,0,218},{8,0,218},{7,24,145},{7,24,145},{7,24,145},{7,20,145},{6,21,5},{6,21,5},{8,31,474},{8,28,276},{9,24,425},{8,24,292},{8,28,740},{8,25,298},{8,23,61},{8,22,315},{5,28,724},{7,22,227},{9,28,200},{9,26,13},{9,24,25},{9,23,29},{13,12,723},
+{7,27,219},{8,23,45},{7,22,218},{13,18,723},{7,22,218},{8,28,272},{8,28,272},{8,28,272},{8,24,276},{8,25,180},{8,23,36},{8,23,36},{8,21,33},{6,25,171},{7,21,26},{9,25,0},{9,25,0},{9,25,0},{9,23,4},{15,2,162},{8,23,20},{8,23,20},{8,21,17},{13,16,162},{8,21,17},{15,8,200},{8,28,4},{9,24,25},{8,24,20},{15,8,200},{11,22,200},{8,24,20},
+{0,22,218},{11,22,200},{0,22,218},{8,0,272},{8,0,272},{8,0,272},{8,0,272},{8,22,17},{8,22,17},{8,22,17},{8,20,17},{7,22,9},{7,22,9},{9,31,410},{9,28,212},{9,25,288},{9,24,224},{8,31,739},{8,27,254},{8,25,33},{8,23,270},{5,30,740},{7,23,231},{9,31,266},{9,28,68},{10,24,97},{9,24,80},{14,11,723},{7,29,209},{8,25,17},{7,23,227},{15,17,723},
+{7,23,227},{9,27,212},{9,27,212},{9,27,212},{9,24,208},{8,28,180},{8,25,17},{8,25,17},{8,22,18},{6,27,171},{7,23,62},{9,27,68},{9,27,68},{9,27,68},{9,24,64},{11,18,162},{8,25,1},{8,25,1},{8,22,2},{10,21,162},{8,22,2},{14,14,200},{9,28,4},{10,24,16},{9,24,16},{14,14,200},{14,20,200},{9,24,16},{0,23,218},{14,20,200},{0,23,218},{9,0,208},
+{9,0,208},{9,0,208},{9,0,208},{8,25,16},{8,25,16},{8,25,16},{8,22,17},{7,24,8},{7,24,8},{9,31,570},{9,30,276},{9,26,457},{9,26,292},{9,30,740},{9,27,298},{9,25,45},{9,24,324},{6,30,727},{7,24,280},{10,30,201},{10,28,18},{10,26,21},{10,25,26},{13,17,723},{8,29,227},{9,25,29},{8,24,224},{13,21,723},{8,24,224},{9,30,272},{9,30,272},{9,30,272},
+{9,26,276},{9,27,180},{9,25,29},{9,25,29},{9,23,33},{7,27,171},{8,23,41},{10,27,2},{10,27,2},{10,27,2},{10,24,5},{13,14,162},{8,27,5},{8,27,5},{8,23,5},{8,25,162},{8,23,5},{13,20,200},{9,30,4},{10,26,20},{9,26,20},{13,20,200},{13,23,202},{9,26,20},{0,24,208},{13,23,202},{0,24,208},{9,0,272},{9,0,272},{9,0,272},{9,0,272},{9,24,17},
+{9,24,17},{9,24,17},{9,22,17},{7,25,10},{7,25,10},{10,31,468},{10,30,223},{10,27,283},{10,26,234},{9,31,835},{9,29,267},{9,27,33},{9,25,273},{7,30,747},{8,25,225},{11,29,283},{10,30,54},{11,26,97},{10,26,65},{15,13,723},{8,30,208},{9,27,17},{8,25,209},{11,25,723},{8,25,209},{10,29,219},{10,29,219},{10,29,219},{10,26,218},{9,30,180},{9,27,17},{9,27,17},
+{9,24,20},{7,28,174},{8,24,17},{10,29,50},{10,29,50},{10,29,50},{10,26,49},{14,13,162},{9,27,1},{9,27,1},{9,24,4},{11,23,162},{9,24,4},{15,16,200},{10,30,5},{11,26,16},{10,26,16},{15,16,200},{15,22,200},{10,26,16},{0,25,208},{15,22,200},{0,25,208},{10,0,218},{10,0,218},{10,0,218},{10,0,218},{9,27,16},{9,27,16},{9,27,16},{9,24,20},{8,24,17},
+{8,24,17},{11,31,632},{10,31,297},{11,28,425},{10,28,292},{10,31,804},{10,29,298},{10,27,61},{10,26,315},{7,31,823},{8,26,231},{11,31,232},{11,30,13},{11,28,25},{11,27,29},{15,16,723},{9,31,216},{10,27,45},{8,26,227},{15,22,723},{8,26,227},{10,31,288},{10,31,288},{10,31,288},{10,28,276},{10,29,180},{10,27,36},{10,27,36},{10,25,33},{7,30,189},{9,25,30},{11,29,0},
+{11,29,0},{11,29,0},{11,27,4},{14,16,162},{9,29,4},{9,29,4},{9,25,5},{15,20,162},{9,25,5},{15,19,200},{11,30,13},{11,28,25},{10,28,20},{15,19,200},{13,26,200},{10,28,20},{0,26,218},{13,26,200},{0,26,218},{10,0,272},{10,0,272},{10,0,272},{10,0,272},{10,26,17},{10,26,17},{10,26,17},{10,24,17},{8,27,5},{8,27,5},{11,31,696},{11,31,237},{11,29,288},
+{11,28,224},{11,31,888},{10,31,254},{10,29,33},{10,27,270},{8,31,824},{9,27,227},{12,31,283},{11,31,93},{12,28,97},{11,28,80},{13,25,723},{10,31,238},{10,29,17},{9,27,218},{12,27,723},{9,27,218},{11,31,212},{11,31,212},{11,31,212},{11,28,208},{10,31,196},{10,29,17},{10,29,17},{10,26,18},{8,30,171},{9,26,26},{11,31,68},{11,31,68},{11,31,68},{11,28,64},{13,22,162},
+{10,29,1},{10,29,1},{10,26,2},{12,25,162},{10,26,2},{13,28,200},{11,31,29},{12,28,16},{11,28,16},{13,28,200},{11,30,200},{11,28,16},{0,27,218},{11,30,200},{0,27,218},{11,0,208},{11,0,208},{11,0,208},{11,0,208},{10,29,16},{10,29,16},{10,29,16},{10,26,17},{9,27,9},{9,27,9},{12,31,804},{12,31,492},{11,30,457},{11,30,292},{11,31,1080},{11,31,298},{11,29,45},
+{11,28,324},{9,31,920},{9,28,218},{12,31,363},{12,31,51},{12,30,21},{12,29,26},{15,21,723},{11,31,282},{11,29,29},{9,28,217},{15,25,723},{9,28,217},{11,31,372},{11,31,372},{11,31,372},{11,30,276},{11,31,180},{11,29,29},{11,29,29},{11,27,33},{8,31,184},{10,27,41},{12,31,2},{12,31,2},{12,31,2},{12,28,5},{15,18,162},{10,31,5},{10,31,5},{10,27,5},{10,29,162},
+{10,27,5},{15,24,200},{12,31,50},{12,30,20},{11,30,20},{15,24,200},{15,27,202},{11,30,20},{0,28,208},{15,27,202},{0,28,208},{11,0,272},{11,0,272},{11,0,272},{11,0,272},{11,28,17},{11,28,17},{11,28,17},{11,26,17},{9,29,8},{9,29,8},{12,31,996},{12,31,492},{12,31,283},{12,30,234},{12,31,1068},{11,31,458},{11,31,33},{11,29,273},{10,31,999},{10,29,225},{13,31,379},
+{13,31,171},{13,30,97},{12,30,65},{14,27,723},{12,31,371},{11,31,17},{10,29,209},{13,29,723},{10,29,209},{12,31,267},{12,31,267},{12,31,267},{12,30,218},{12,30,333},{11,31,17},{11,31,17},{11,28,20},{9,31,212},{10,28,17},{13,30,81},{13,30,81},{13,30,81},{12,30,49},{13,27,162},{11,31,1},{11,31,1},{11,28,4},{13,27,162},{11,28,4},{15,27,202},{13,31,90},{13,30,16},
+{12,30,16},{15,27,202},{15,28,202},{12,30,16},{0,29,208},{15,28,202},{0,29,208},{12,0,218},{12,0,218},{12,0,218},{12,0,218},{11,31,16},{11,31,16},{11,31,16},{11,28,20},{9,30,10},{9,30,10},{13,31,877},{13,31,605},{13,31,436},{12,31,288},{13,31,1021},{12,31,397},{12,31,36},{12,30,210},{11,31,910},{10,30,126},{14,31,414},{13,31,205},{13,31,36},{13,31,4},{15,26,546},
+{13,31,317},{12,31,20},{10,30,122},{14,29,546},{10,30,122},{13,31,436},{13,31,436},{13,31,436},{12,31,288},{12,31,276},{12,31,36},{12,31,36},{12,29,33},{10,31,261},{11,29,30},{13,31,36},{13,31,36},{13,31,36},{13,31,4},{13,30,162},{12,31,20},{12,31,20},{11,29,5},{12,30,162},{11,29,5},{15,28,117},{14,31,61},{14,31,25},{13,31,4},{15,28,117},{14,31,117},{13,31,4},
+{0,30,113},{14,31,117},{0,30,113},{12,0,272},{12,0,272},{12,0,272},{12,0,272},{12,30,17},{12,30,17},{12,30,17},{12,28,17},{10,31,5},{10,31,5},{13,31,845},{13,31,573},{13,31,404},{13,31,244},{13,31,797},{13,31,365},{12,31,196},{12,30,82},{12,31,737},{11,31,58},{14,31,190},{14,31,126},{14,31,90},{14,31,82},{14,31,334},{13,31,221},{13,31,52},{11,31,49},{14,30,333},
+{11,31,49},{13,31,404},{13,31,404},{13,31,404},{13,31,244},{13,31,356},{12,31,196},{12,31,196},{12,30,18},{11,31,333},{11,30,26},{14,31,90},{14,31,90},{14,31,90},{14,31,82},{15,26,162},{13,31,52},{13,31,52},{12,30,2},{14,29,162},{12,30,2},{15,30,25},{15,30,41},{14,31,9},{14,31,1},{15,30,25},{15,30,29},{14,31,1},{0,31,49},{15,30,29},{0,31,49},{13,0,208},
+{13,0,208},{13,0,208},{13,0,208},{12,31,52},{12,31,52},{12,31,52},{12,30,17},{11,31,9},{11,31,9},{14,31,642},{14,31,578},{14,31,542},{13,31,441},{14,31,690},{13,31,370},{13,31,201},{13,31,32},{13,31,610},{12,31,40},{14,31,201},{14,31,137},{14,31,101},{14,31,37},{15,29,193},{14,31,121},{14,31,85},{12,31,4},{14,31,193},{12,31,4},{14,31,542},{14,31,542},{14,31,542},
+{13,31,441},{13,31,473},{13,31,201},{13,31,201},{13,31,32},{12,31,401},{12,31,40},{14,31,101},{14,31,101},{14,31,101},{14,31,37},{15,28,145},{14,31,85},{14,31,85},{12,31,4},{15,29,149},{12,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{13,0,272},{13,0,272},{13,0,272},{13,0,272},{13,31,32},
+{13,31,32},{13,31,32},{13,30,17},{12,31,40},{12,31,40},{14,31,418},{14,31,354},{14,31,318},{14,31,254},{14,31,370},{14,31,242},{14,31,206},{13,31,32},{13,31,418},{13,31,80},{15,31,81},{15,31,81},{15,31,81},{15,31,81},{15,30,54},{14,31,73},{14,31,37},{14,31,9},{15,30,66},{14,31,9},{14,31,318},{14,31,318},{14,31,318},{14,31,254},{14,31,270},{14,31,206},{14,31,206},
+{13,31,32},{13,31,249},{13,31,80},{15,31,81},{15,31,81},{15,31,81},{15,31,81},{15,29,45},{14,31,37},{14,31,37},{14,31,9},{15,30,41},{14,31,9},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{14,0,218},{14,0,218},{14,0,218},{14,0,218},{13,31,160},{13,31,160},{13,31,160},{13,31,32},{13,31,80},
+{13,31,80},{0,9,421},{0,7,113},{0,5,5},{0,4,130},{0,6,925},{0,5,658},{0,4,274},{0,3,670},{0,3,1039},{0,3,751},{0,9,421},{0,7,113},{0,5,5},{0,4,130},{0,6,925},{0,5,658},{0,4,274},{0,3,670},{3,0,925},{0,3,670},{0,4,1},{0,4,1},{0,4,1},{0,3,4},{0,2,85},{0,2,45},{0,2,45},{0,1,50},{0,1,98},{0,1,59},{0,4,1},
+{0,4,1},{0,4,1},{0,3,4},{0,2,85},{0,2,45},{0,2,45},{0,1,50},{1,0,85},{0,1,50},{1,6,421},{0,7,113},{0,5,5},{0,4,130},{1,6,421},{3,2,421},{0,4,130},{0,3,445},{3,2,421},{0,3,445},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,12,425},{0,9,52},{0,6,10},
+{0,6,82},{0,8,1261},{0,6,805},{0,5,322},{0,4,833},{0,4,1445},{0,4,977},{0,12,425},{0,9,52},{0,6,10},{0,6,82},{0,8,1261},{0,6,805},{0,5,322},{0,4,833},{4,0,1261},{0,4,833},{0,7,0},{0,7,0},{0,7,0},{0,4,1},{0,3,225},{0,3,117},{0,3,117},{0,2,125},{0,2,257},{0,2,161},{0,7,0},{0,7,0},{0,7,0},{0,4,1},{1,0,221},
+{0,3,117},{0,3,117},{0,2,125},{1,1,221},{0,2,125},{3,2,421},{0,9,52},{0,6,10},{0,6,82},{3,2,421},{5,1,421},{0,6,82},{0,4,433},{5,1,421},{0,4,433},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,14,430},{0,11,29},{0,7,74},{0,7,46},{0,10,1514},{0,8,874},{0,6,307},
+{0,5,917},{0,5,1814},{0,4,1074},{0,14,430},{0,11,29},{0,7,74},{0,7,46},{3,0,1514},{0,8,874},{0,6,307},{0,5,917},{5,0,1514},{0,5,917},{0,10,10},{0,10,10},{0,10,10},{0,6,10},{0,5,340},{0,5,160},{0,5,160},{0,3,169},{0,3,421},{0,3,250},{0,10,10},{0,10,10},{0,10,10},{0,6,10},{1,2,338},{0,5,160},{0,5,160},{0,3,169},{1,2,338},
+{0,3,169},{4,1,421},{0,11,20},{1,7,5},{0,7,37},{4,1,421},{7,0,421},{0,7,37},{0,5,433},{7,0,421},{0,5,433},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,0},{0,1,0},{0,1,0},{0,1,4},{0,0,9},{0,0,9},{0,17,542},{0,13,130},{0,9,285},{0,8,137},{0,12,1517},{0,9,737},{0,7,185},{0,6,794},{0,7,1982},{0,5,1062},{1,13,450},
+{1,11,77},{1,8,34},{1,7,122},{3,3,1517},{0,9,737},{0,7,185},{0,6,794},{2,5,1514},{0,6,794},{0,12,121},{0,12,121},{0,12,121},{0,7,125},{0,8,338},{0,6,98},{0,6,98},{0,4,97},{0,4,514},{0,4,241},{1,9,25},{1,9,25},{1,9,25},{1,6,26},{0,8,338},{0,6,98},{0,6,98},{0,4,97},{4,0,338},{0,4,97},{5,0,421},{0,13,9},{1,8,9},
+{0,8,16},{5,0,421},{8,0,421},{0,8,16},{0,6,433},{8,0,421},{0,6,433},{0,0,121},{0,0,121},{0,0,121},{0,0,121},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,2,37},{0,2,37},{1,16,697},{1,13,297},{1,9,354},{1,9,309},{0,15,1517},{0,11,630},{0,9,50},{0,7,670},{0,8,2198},{0,6,1109},{1,16,441},{1,13,41},{1,9,98},{1,9,53},{4,2,1514},
+{0,11,630},{0,9,50},{0,7,670},{6,2,1514},{0,7,670},{1,12,273},{1,12,273},{1,12,273},{1,8,273},{0,11,338},{0,8,41},{0,8,41},{0,5,50},{0,6,680},{0,5,275},{1,12,17},{1,12,17},{1,12,17},{1,8,17},{3,1,338},{0,8,41},{0,8,41},{0,5,50},{3,3,338},{0,5,50},{6,0,421},{0,15,1},{2,9,5},{0,9,1},{6,0,421},{5,6,421},{0,9,1},
+{0,7,445},{5,6,421},{0,7,445},{1,0,272},{1,0,272},{1,0,272},{1,0,272},{0,7,1},{0,7,1},{0,7,1},{0,4,0},{0,3,106},{0,3,106},{1,19,821},{1,15,405},{1,11,570},{1,10,410},{0,18,1514},{0,13,577},{0,10,14},{0,8,602},{0,10,2462},{0,7,1175},{2,16,450},{2,13,77},{2,10,35},{2,10,107},{3,8,1514},{0,13,577},{0,10,14},{0,8,602},{4,6,1514},
+{0,8,602},{1,14,401},{1,14,401},{1,14,401},{1,9,404},{0,13,340},{0,10,13},{0,10,13},{0,6,29},{0,7,851},{0,6,353},{2,11,25},{2,11,25},{2,11,25},{2,8,26},{4,0,338},{0,10,13},{0,10,13},{0,6,29},{1,7,338},{0,6,29},{5,6,421},{1,15,5},{2,10,10},{0,10,10},{5,6,421},{10,1,421},{0,10,10},{0,8,433},{10,1,421},{0,8,433},{1,0,400},
+{1,0,400},{1,0,400},{1,0,400},{0,9,1},{0,9,1},{0,9,1},{0,6,4},{0,4,208},{0,4,208},{1,22,902},{1,17,485},{2,11,750},{1,11,482},{0,21,1566},{0,15,570},{0,11,95},{0,9,582},{0,11,2337},{0,9,933},{2,18,430},{2,15,29},{2,11,74},{2,11,46},{5,4,1514},{0,15,521},{0,11,46},{0,9,533},{9,1,1514},{0,9,533},{1,17,481},{1,17,481},{1,17,481},
+{1,11,481},{0,16,387},{0,12,51},{0,12,51},{0,7,75},{0,8,755},{0,7,222},{2,14,10},{2,14,10},{2,14,10},{2,10,10},{3,6,338},{0,12,2},{0,12,2},{0,7,26},{3,6,338},{0,7,26},{7,2,421},{1,17,4},{3,11,5},{1,11,1},{7,2,421},{12,0,421},{1,11,1},{0,9,433},{12,0,421},{0,9,433},{1,0,481},{1,0,481},{1,0,481},{1,0,481},{0,12,50},
+{0,12,50},{0,12,50},{0,7,50},{0,6,157},{0,6,157},{2,21,866},{2,17,454},{2,13,609},{2,12,461},{1,20,1515},{1,15,578},{1,12,19},{1,10,603},{0,13,2214},{0,10,707},{3,17,450},{3,15,77},{3,12,34},{3,11,122},{7,0,1514},{0,16,458},{1,12,18},{0,10,482},{4,9,1514},{0,10,482},{2,16,445},{2,16,445},{2,16,445},{2,11,449},{1,15,341},{1,12,19},{1,12,19},
+{1,8,26},{0,10,635},{0,8,106},{3,13,25},{3,13,25},{3,13,25},{3,10,26},{5,2,338},{0,14,2},{0,14,2},{0,9,20},{8,1,338},{0,9,20},{7,4,421},{2,17,9},{3,12,9},{1,12,9},{7,4,421},{11,3,421},{1,12,9},{0,10,433},{11,3,421},{0,10,433},{2,0,445},{2,0,445},{2,0,445},{2,0,445},{1,11,2},{1,11,2},{1,11,2},{1,7,10},{0,8,90},
+{0,8,90},{2,24,902},{2,19,482},{3,13,723},{2,13,482},{1,23,1578},{1,17,566},{1,14,117},{1,11,590},{0,15,2046},{0,11,535},{3,20,441},{3,17,41},{3,13,98},{3,13,53},{7,3,1514},{0,18,429},{2,13,50},{0,11,454},{11,2,1514},{0,11,454},{2,19,481},{2,19,481},{2,19,481},{2,13,481},{1,18,404},{1,14,68},{1,14,68},{1,10,89},{0,12,557},{0,10,49},{3,16,17},
+{3,16,17},{3,16,17},{3,12,17},{5,5,338},{1,14,4},{1,14,4},{0,10,13},{5,7,338},{0,10,13},{8,2,421},{2,19,1},{4,13,5},{2,13,1},{8,2,421},{14,1,421},{2,13,1},{0,11,445},{14,1,421},{0,11,445},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{1,14,64},{1,14,64},{1,14,64},{1,9,65},{0,10,40},{0,10,40},{3,23,854},{3,19,438},{3,15,603},
+{3,14,443},{2,22,1515},{2,17,578},{2,14,15},{2,12,603},{0,16,1911},{0,12,458},{4,20,450},{4,17,77},{4,14,35},{4,14,107},{5,12,1514},{0,20,425},{2,14,14},{0,12,433},{13,1,1514},{0,12,433},{3,18,434},{3,18,434},{3,18,434},{3,13,437},{2,17,341},{2,14,14},{2,14,14},{2,10,30},{0,14,477},{0,11,35},{4,15,25},{4,15,25},{4,15,25},{4,12,26},{7,1,338},
+{1,16,5},{1,16,5},{1,11,10},{10,2,338},{1,11,10},{8,5,421},{3,19,5},{4,14,10},{2,14,10},{8,5,421},{12,5,421},{2,14,10},{0,12,433},{12,5,421},{0,12,433},{3,0,433},{3,0,433},{3,0,433},{3,0,433},{2,13,2},{2,13,2},{2,13,2},{2,10,5},{0,12,25},{0,12,25},{3,26,902},{3,21,485},{4,15,750},{3,15,482},{2,25,1566},{2,19,570},{2,15,95},
+{2,13,582},{0,18,1787},{0,13,442},{4,22,430},{4,19,29},{4,15,74},{4,15,46},{8,3,1514},{1,20,425},{2,15,46},{0,13,442},{11,5,1514},{0,13,442},{3,21,481},{3,21,481},{3,21,481},{3,15,481},{2,20,387},{2,16,51},{2,16,51},{2,11,75},{0,16,419},{1,12,69},{4,18,10},{4,18,10},{4,18,10},{4,14,10},{5,10,338},{2,16,2},{2,16,2},{1,12,20},{12,1,338},
+{1,12,20},{9,4,421},{3,21,4},{5,15,5},{3,15,1},{9,4,421},{15,3,421},{3,15,1},{0,13,433},{15,3,421},{0,13,433},{3,0,481},{3,0,481},{3,0,481},{3,0,481},{2,16,50},{2,16,50},{2,16,50},{2,11,50},{0,13,9},{0,13,9},{4,25,866},{4,21,454},{4,17,609},{4,16,461},{3,24,1515},{3,19,578},{3,16,19},{3,14,603},{0,20,1686},{1,14,458},{5,21,450},
+{5,19,77},{5,16,34},{5,15,122},{3,24,1514},{1,22,425},{3,16,18},{1,14,433},{14,3,1514},{1,14,433},{4,20,445},{4,20,445},{4,20,445},{4,15,449},{3,19,341},{3,16,19},{3,16,19},{3,12,26},{0,17,372},{1,13,45},{5,17,25},{5,17,25},{5,17,25},{5,14,26},{8,1,338},{2,18,2},{2,18,2},{2,13,20},{10,5,338},{2,13,20},{11,0,421},{4,21,9},{5,16,9},
+{3,16,9},{11,0,421},{13,7,421},{3,16,9},{0,14,433},{13,7,421},{0,14,433},{4,0,445},{4,0,445},{4,0,445},{4,0,445},{3,15,2},{3,15,2},{3,15,2},{3,11,10},{0,15,5},{0,15,5},{4,28,902},{4,23,482},{5,17,723},{4,17,482},{3,27,1578},{3,21,566},{3,18,117},{3,15,590},{0,22,1614},{1,15,462},{5,24,441},{5,21,41},{5,17,98},{5,17,53},{5,20,1514},
+{2,22,429},{4,17,50},{2,15,454},{13,6,1514},{2,15,454},{4,23,481},{4,23,481},{4,23,481},{4,17,481},{3,22,404},{3,18,68},{3,18,68},{3,14,89},{0,19,347},{2,14,49},{5,20,17},{5,20,17},{5,20,17},{5,16,17},{8,4,338},{3,18,4},{3,18,4},{2,14,13},{14,2,338},{2,14,13},{11,3,421},{4,23,1},{6,17,5},{4,17,1},{11,3,421},{15,6,421},{4,17,1},
+{0,15,445},{15,6,421},{0,15,445},{4,0,481},{4,0,481},{4,0,481},{4,0,481},{3,18,64},{3,18,64},{3,18,64},{3,13,65},{1,16,8},{1,16,8},{5,27,854},{5,23,438},{5,19,603},{5,18,443},{4,26,1515},{4,21,578},{4,18,15},{4,16,603},{0,23,1566},{2,16,458},{6,24,450},{6,21,77},{6,18,35},{6,18,107},{11,1,1514},{2,24,425},{4,18,14},{2,16,433},{15,5,1514},
+{2,16,433},{5,22,434},{5,22,434},{5,22,434},{5,17,437},{4,21,341},{4,18,14},{4,18,14},{4,14,30},{0,21,341},{2,15,35},{6,19,25},{6,19,25},{6,19,25},{6,16,26},{3,25,338},{3,20,5},{3,20,5},{3,15,10},{12,6,338},{3,15,10},{12,2,421},{5,23,5},{6,18,10},{4,18,10},{12,2,421},{14,9,421},{4,18,10},{0,16,433},{14,9,421},{0,16,433},{5,0,433},
+{5,0,433},{5,0,433},{5,0,433},{4,17,2},{4,17,2},{4,17,2},{4,14,5},{1,17,10},{1,17,10},{5,30,902},{5,25,485},{6,19,750},{5,19,482},{4,29,1566},{4,23,570},{4,19,95},{4,17,582},{0,25,1533},{2,17,442},{6,26,430},{6,23,29},{6,19,74},{6,19,46},{10,7,1514},{3,24,425},{4,19,46},{2,17,442},{13,9,1514},{2,17,442},{5,25,481},{5,25,481},{5,25,481},
+{5,19,481},{4,24,387},{4,20,51},{4,20,51},{4,15,75},{1,21,341},{3,16,69},{6,22,10},{6,22,10},{6,22,10},{6,18,10},{9,6,338},{4,20,2},{4,20,2},{3,16,20},{14,5,338},{3,16,20},{11,8,421},{5,25,4},{7,19,5},{5,19,1},{11,8,421},{11,14,421},{5,19,1},{0,17,433},{11,14,421},{0,17,433},{5,0,481},{5,0,481},{5,0,481},{5,0,481},{4,20,50},
+{4,20,50},{4,20,50},{4,15,50},{2,17,9},{2,17,9},{6,29,866},{6,25,454},{6,21,609},{6,20,461},{5,28,1515},{5,23,578},{5,20,19},{5,18,603},{0,27,1521},{3,18,458},{7,25,450},{7,23,77},{7,20,34},{7,19,122},{12,3,1514},{3,26,425},{5,20,18},{3,18,433},{11,13,1514},{3,18,433},{6,24,445},{6,24,445},{6,24,445},{6,19,449},{5,23,341},{5,20,19},{5,20,19},
+{5,16,26},{1,23,341},{3,17,45},{7,21,25},{7,21,25},{7,21,25},{7,18,26},{10,5,338},{4,22,2},{4,22,2},{4,17,20},{12,9,338},{4,17,20},{13,4,421},{6,25,9},{7,20,9},{5,20,9},{13,4,421},{15,11,421},{5,20,9},{0,18,433},{15,11,421},{0,18,433},{6,0,445},{6,0,445},{6,0,445},{6,0,445},{5,19,2},{5,19,2},{5,19,2},{5,15,10},{2,19,5},
+{2,19,5},{6,31,914},{6,27,482},{7,21,723},{6,21,482},{5,31,1578},{5,25,566},{5,22,117},{5,19,590},{1,27,1535},{3,19,462},{7,28,441},{7,25,41},{7,21,98},{7,21,53},{8,19,1514},{4,26,429},{6,21,50},{4,19,454},{15,10,1514},{4,19,454},{6,27,481},{6,27,481},{6,27,481},{6,21,481},{5,26,404},{5,22,68},{5,22,68},{5,18,89},{2,23,347},{4,18,49},{7,24,17},
+{7,24,17},{7,24,17},{7,20,17},{10,8,338},{5,22,4},{5,22,4},{4,18,13},{11,12,338},{4,18,13},{15,0,421},{6,27,1},{8,21,50},{6,21,1},{15,0,421},{13,15,421},{6,21,1},{0,19,445},{13,15,421},{0,19,445},{6,0,481},{6,0,481},{6,0,481},{6,0,481},{5,22,64},{5,22,64},{5,22,64},{5,17,65},{3,20,8},{3,20,8},{7,31,854},{7,27,438},{7,23,603},
+{7,22,443},{6,30,1515},{6,25,578},{6,22,15},{6,20,603},{1,29,1518},{4,20,458},{7,31,565},{7,27,149},{8,22,174},{7,22,154},{13,5,1514},{4,28,425},{6,22,14},{4,20,433},{12,15,1514},{4,20,433},{7,26,434},{7,26,434},{7,26,434},{7,21,437},{6,25,341},{6,22,14},{6,22,14},{6,18,30},{2,25,341},{4,19,35},{7,26,145},{7,26,145},{7,26,145},{7,21,148},{9,14,338},
+{5,24,5},{5,24,5},{5,19,10},{14,10,338},{5,19,10},{15,3,421},{7,27,5},{8,22,5},{6,22,10},{15,3,421},{15,14,421},{6,22,10},{0,20,433},{15,14,421},{0,20,433},{7,0,433},{7,0,433},{7,0,433},{7,0,433},{6,21,2},{6,21,2},{6,21,2},{6,18,5},{3,21,10},{3,21,10},{7,31,1046},{7,29,485},{7,24,770},{7,23,482},{7,29,1598},{6,27,570},{6,23,95},
+{6,21,582},{2,29,1533},{4,21,442},{8,28,450},{8,26,77},{8,23,35},{8,23,107},{15,1,1514},{5,28,425},{6,23,46},{4,21,442},{15,13,1514},{4,21,442},{7,29,481},{7,29,481},{7,29,481},{7,23,481},{6,28,387},{6,24,51},{6,24,51},{6,19,75},{3,25,341},{5,20,69},{8,24,25},{8,24,25},{8,24,25},{8,21,26},{11,10,338},{6,24,2},{6,24,2},{5,20,20},{5,23,338},
+{5,20,20},{13,12,421},{7,29,4},{8,23,10},{7,23,1},{13,12,421},{13,18,421},{7,23,1},{0,21,433},{13,18,421},{0,21,433},{7,0,481},{7,0,481},{7,0,481},{7,0,481},{6,24,50},{6,24,50},{6,24,50},{6,19,50},{4,21,9},{4,21,9},{8,31,1106},{8,28,714},{8,24,749},{8,24,734},{7,31,1542},{7,27,578},{7,24,19},{7,22,603},{2,31,1521},{5,22,458},{8,31,430},
+{8,28,38},{8,24,73},{8,24,58},{14,7,1514},{5,30,425},{7,24,18},{5,22,433},{13,17,1514},{5,22,433},{8,27,686},{8,27,686},{8,27,686},{8,23,686},{7,27,341},{7,24,19},{7,24,19},{7,20,26},{3,27,341},{5,21,45},{8,27,10},{8,27,10},{8,27,10},{8,23,10},{12,9,338},{6,26,2},{6,26,2},{6,21,20},{14,13,338},{6,21,20},{15,8,421},{7,31,20},{9,24,4},
+{7,24,9},{15,8,421},{15,17,421},{7,24,9},{0,22,433},{15,17,421},{0,22,433},{8,0,685},{8,0,685},{8,0,685},{8,0,685},{7,23,2},{7,23,2},{7,23,2},{7,19,10},{4,23,5},{4,23,5},{8,31,1034},{8,30,438},{8,26,603},{8,25,443},{8,30,1806},{7,29,566},{7,26,117},{7,23,590},{3,31,1535},{5,23,462},{9,31,437},{9,28,77},{9,25,33},{9,25,98},{10,23,1514},
+{6,30,429},{7,26,53},{6,23,454},{11,21,1514},{6,23,454},{8,29,434},{8,29,434},{8,29,434},{8,24,437},{7,30,404},{7,26,68},{7,26,68},{7,22,89},{4,27,347},{6,22,49},{9,26,17},{9,26,17},{9,26,17},{9,23,20},{15,2,338},{7,26,4},{7,26,4},{6,22,13},{13,16,338},{6,22,13},{15,11,421},{8,30,5},{9,25,17},{8,25,10},{15,11,421},{15,19,421},{8,25,10},
+{0,23,445},{15,19,421},{0,23,445},{8,0,433},{8,0,433},{8,0,433},{8,0,433},{7,26,64},{7,26,64},{7,26,64},{7,21,65},{5,24,8},{5,24,8},{9,31,1174},{8,31,506},{9,26,723},{8,26,482},{8,31,1643},{7,30,717},{8,26,131},{7,24,725},{4,31,1566},{6,24,458},{9,31,549},{9,30,41},{9,26,98},{9,26,53},{15,9,1514},{7,30,461},{8,26,50},{6,24,433},{14,19,1514},
+{6,24,433},{8,31,490},{8,31,490},{8,31,490},{8,26,481},{8,28,421},{8,25,122},{8,25,122},{8,22,131},{4,29,341},{6,23,35},{9,29,17},{9,29,17},{9,29,17},{9,25,17},{11,18,338},{7,28,5},{7,28,5},{7,23,10},{10,21,338},{7,23,10},{14,17,421},{9,30,25},{10,26,5},{8,26,1},{14,17,421},{13,23,421},{8,26,1},{0,24,433},{13,23,421},{0,24,433},{8,0,481},
+{8,0,481},{8,0,481},{8,0,481},{8,24,82},{8,24,82},{8,24,82},{8,21,81},{5,25,10},{5,25,10},{9,31,1334},{9,31,470},{9,28,597},{9,27,443},{9,31,1815},{8,30,578},{8,27,15},{8,25,603},{5,31,1638},{6,25,442},{10,31,506},{10,30,77},{10,27,35},{10,27,107},{14,15,1514},{7,31,506},{8,27,14},{6,25,442},{12,23,1514},{6,25,442},{9,31,434},{9,31,434},{9,31,434},
+{9,26,437},{8,30,341},{8,27,14},{8,27,14},{8,23,30},{5,29,341},{7,24,69},{10,28,25},{10,28,25},{10,28,25},{10,25,26},{13,14,338},{8,27,13},{8,27,13},{7,24,20},{8,25,338},{7,24,20},{15,16,421},{9,31,37},{10,27,10},{8,27,10},{15,16,421},{15,22,421},{8,27,10},{0,25,433},{15,22,421},{0,25,433},{9,0,433},{9,0,433},{9,0,433},{9,0,433},{8,26,2},
+{8,26,2},{8,26,2},{8,23,5},{6,25,9},{6,25,9},{10,31,1470},{10,31,735},{10,28,749},{9,28,481},{9,31,1895},{8,31,579},{8,28,89},{8,26,582},{6,31,1761},{7,26,458},{11,31,614},{10,31,59},{10,28,73},{10,28,58},{13,21,1514},{8,31,530},{8,28,40},{7,26,433},{15,21,1514},{7,26,433},{9,31,562},{9,31,562},{9,31,562},{9,28,481},{9,30,421},{8,29,51},{8,29,51},
+{8,24,65},{5,31,341},{7,25,45},{10,31,10},{10,31,10},{10,31,10},{10,27,10},{14,13,338},{8,29,2},{8,29,2},{8,24,16},{11,23,338},{8,24,16},{15,19,421},{10,31,50},{11,28,4},{9,28,0},{15,19,421},{13,26,421},{9,28,0},{0,26,433},{13,26,421},{0,26,433},{9,0,481},{9,0,481},{9,0,481},{9,0,481},{8,29,50},{8,29,50},{8,29,50},{8,24,49},{6,27,5},
+{6,27,5},{11,31,1838},{10,31,753},{10,30,603},{10,29,443},{10,31,2046},{9,31,629},{9,29,21},{9,27,589},{7,31,1935},{7,27,462},{11,31,749},{11,31,120},{11,29,33},{11,29,98},{12,27,1514},{9,31,629},{9,29,21},{7,27,461},{13,25,1514},{7,27,461},{10,31,497},{10,31,497},{10,31,497},{10,28,437},{9,31,388},{9,29,20},{9,29,20},{9,25,29},{6,31,347},{8,25,105},{11,30,17},
+{11,30,17},{11,30,17},{11,27,20},{14,16,338},{8,31,4},{8,31,4},{8,26,10},{15,20,338},{8,26,10},{14,25,421},{11,31,104},{11,29,17},{10,29,10},{14,25,421},{12,29,421},{10,29,10},{0,27,445},{12,29,421},{0,27,445},{10,0,433},{10,0,433},{10,0,433},{10,0,433},{9,28,1},{9,28,1},{9,28,1},{9,25,4},{7,28,8},{7,28,8},{11,31,1902},{11,31,1001},{11,30,723},
+{10,30,482},{11,31,2286},{10,31,782},{9,31,117},{9,28,578},{8,31,2118},{7,29,491},{12,31,770},{12,31,338},{11,30,98},{11,30,53},{14,23,1514},{10,31,701},{10,30,50},{8,28,442},{11,29,1514},{8,28,442},{11,31,677},{11,31,677},{11,31,677},{10,30,481},{10,31,437},{9,31,68},{9,31,68},{9,27,89},{7,31,379},{8,27,49},{11,31,52},{11,31,52},{11,31,52},{11,29,17},{13,22,338},
+{9,31,4},{9,31,4},{8,27,13},{12,25,338},{8,27,13},{15,24,421},{12,31,169},{12,30,5},{10,30,1},{15,24,421},{15,27,421},{10,30,1},{0,28,433},{15,27,421},{0,28,433},{10,0,481},{10,0,481},{10,0,481},{10,0,481},{9,31,64},{9,31,64},{9,31,64},{9,26,65},{7,29,10},{7,29,10},{12,31,2151},{11,31,1254},{11,31,629},{11,31,442},{11,31,2393},{10,31,975},{10,31,14},
+{10,29,570},{9,31,2241},{8,29,425},{13,31,931},{12,31,395},{12,31,34},{12,30,105},{13,29,1459},{11,31,778},{10,31,13},{8,29,400},{14,27,1459},{8,29,400},{11,31,629},{11,31,629},{11,31,629},{11,30,437},{10,31,581},{10,31,14},{10,31,14},{10,27,30},{8,31,477},{8,28,45},{12,31,34},{12,31,34},{12,31,34},{12,29,26},{15,18,338},{10,31,13},{10,31,13},{9,28,17},{10,29,338},
+{9,28,17},{15,27,394},{13,31,218},{12,31,9},{10,31,9},{15,27,394},{15,28,394},{10,31,9},{0,29,400},{15,28,394},{0,29,400},{11,0,433},{11,0,433},{11,0,433},{11,0,433},{10,30,2},{10,30,2},{10,30,2},{10,27,5},{8,29,25},{8,29,25},{12,31,1767},{12,31,1167},{12,31,806},{11,31,506},{12,31,1983},{11,31,747},{11,31,122},{10,29,346},{10,31,1836},{8,30,217},{13,31,611},
+{13,31,339},{12,31,130},{12,31,10},{15,24,1064},{12,31,587},{11,31,41},{8,30,217},{15,27,1067},{8,30,217},{12,31,806},{12,31,806},{12,31,806},{11,31,506},{11,31,581},{11,31,122},{11,31,122},{10,28,65},{9,31,557},{9,29,69},{12,31,130},{12,31,130},{12,31,130},{12,31,10},{13,27,338},{11,31,41},{11,31,41},{10,28,16},{13,27,338},{10,28,16},{14,31,200},{14,31,136},{13,31,1},
+{12,31,1},{14,31,200},{15,29,200},{12,31,1},{0,30,208},{15,29,200},{0,30,208},{11,0,481},{11,0,481},{11,0,481},{11,0,481},{11,30,82},{11,30,82},{11,30,82},{10,28,49},{8,30,9},{8,30,9},{13,31,1646},{12,31,1194},{12,31,833},{12,31,497},{12,31,1686},{12,31,750},{11,31,221},{11,30,122},{11,31,1541},{9,30,110},{14,31,542},{13,31,285},{13,31,116},{13,31,20},{15,26,722},
+{13,31,429},{12,31,100},{10,30,74},{14,29,722},{10,30,74},{12,31,833},{12,31,833},{12,31,833},{12,31,497},{12,31,725},{11,31,221},{11,31,221},{11,29,29},{10,31,632},{9,30,46},{13,31,116},{13,31,116},{13,31,116},{13,31,20},{13,30,338},{12,31,100},{12,31,100},{10,30,10},{12,30,338},{10,30,10},{15,29,61},{14,31,37},{14,31,1},{13,31,4},{15,29,61},{15,30,61},{13,31,4},
+{0,30,73},{15,30,61},{0,30,73},{12,0,433},{12,0,433},{12,0,433},{12,0,433},{11,31,25},{11,31,25},{11,31,25},{11,29,4},{9,31,17},{9,31,17},{13,31,1406},{13,31,1134},{13,31,965},{12,31,737},{13,31,1454},{12,31,702},{12,31,341},{11,31,89},{11,31,1381},{10,31,49},{14,31,318},{14,31,254},{14,31,218},{13,31,116},{14,31,510},{13,31,333},{13,31,164},{10,31,13},{14,30,509},
+{10,31,13},{13,31,965},{13,31,965},{13,31,965},{12,31,737},{12,31,869},{12,31,341},{12,31,341},{11,31,89},{11,31,756},{10,31,49},{14,31,218},{14,31,218},{14,31,218},{13,31,116},{15,26,338},{13,31,164},{13,31,164},{10,31,13},{14,29,338},{10,31,13},{15,30,9},{15,31,9},{15,31,9},{14,31,9},{15,30,9},{15,31,9},{14,31,9},{0,31,9},{15,31,9},{0,31,9},{12,0,481},
+{12,0,481},{12,0,481},{12,0,481},{12,31,85},{12,31,85},{12,31,85},{11,30,65},{10,31,40},{10,31,40},{13,31,1315},{13,31,1043},{13,31,874},{13,31,602},{13,31,1171},{13,31,627},{13,31,458},{12,31,5},{12,31,1087},{11,31,80},{14,31,225},{14,31,161},{14,31,125},{14,31,61},{15,29,297},{14,31,193},{14,31,157},{12,31,4},{14,31,297},{12,31,4},{13,31,874},{13,31,874},{13,31,874},
+{13,31,602},{13,31,730},{13,31,458},{13,31,458},{12,31,5},{11,31,705},{11,31,80},{14,31,125},{14,31,125},{14,31,125},{14,31,61},{14,31,221},{14,31,157},{14,31,157},{12,31,4},{15,29,221},{12,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{13,0,433},{13,0,433},{13,0,433},{13,0,433},{12,31,101},
+{12,31,101},{12,31,101},{12,31,5},{11,31,80},{11,31,80},{14,31,885},{14,31,821},{14,31,785},{13,31,650},{14,31,885},{13,31,483},{13,31,314},{13,31,81},{13,31,779},{11,31,144},{15,31,169},{14,31,145},{14,31,109},{14,31,45},{15,30,118},{14,31,81},{14,31,45},{13,31,0},{15,30,114},{13,31,0},{14,31,785},{14,31,785},{14,31,785},{13,31,650},{13,31,586},{13,31,314},{13,31,314},
+{13,31,81},{12,31,518},{11,31,144},{14,31,109},{14,31,109},{14,31,109},{14,31,45},{15,29,85},{14,31,45},{14,31,45},{13,31,0},{14,31,85},{13,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{13,0,481},{13,0,481},{13,0,481},{13,0,481},{13,31,145},{13,31,145},{13,31,145},{13,31,81},{11,31,144},
+{11,31,144},{0,13,884},{0,10,225},{0,7,18},{0,6,265},{0,9,1899},{0,7,1355},{0,6,589},{0,4,1354},{0,5,2124},{0,4,1498},{0,13,884},{0,10,225},{0,7,18},{0,6,265},{2,2,1896},{0,7,1355},{0,6,589},{0,4,1354},{1,4,1896},{0,4,1354},{0,6,0},{0,6,0},{0,6,0},{0,4,4},{0,3,162},{0,3,90},{0,3,90},{0,2,104},{0,2,200},{0,1,134},{0,6,0},
+{0,6,0},{0,6,0},{0,4,4},{0,3,162},{0,3,90},{0,3,90},{0,2,104},{0,2,164},{0,2,104},{3,3,882},{0,10,225},{0,7,18},{0,6,265},{3,3,882},{4,3,882},{0,6,265},{0,5,890},{4,3,882},{0,5,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,15,884},{0,12,170},{0,8,8},
+{0,7,202},{0,10,2360},{0,8,1530},{0,7,643},{0,5,1579},{0,6,2684},{0,5,1804},{0,15,884},{0,12,170},{0,8,8},{0,7,202},{1,7,2355},{0,8,1530},{0,7,643},{0,5,1579},{1,5,2355},{0,5,1579},{0,9,1},{0,9,1},{0,9,1},{0,5,1},{0,4,340},{0,4,180},{0,4,180},{0,2,200},{0,2,392},{0,2,236},{0,9,1},{0,9,1},{0,9,1},{0,5,1},{1,1,338},
+{0,4,180},{0,4,180},{0,2,200},{2,0,340},{0,2,200},{4,2,882},{0,12,170},{0,8,8},{0,7,202},{4,2,882},{6,2,882},{0,7,202},{0,6,890},{6,2,882},{0,6,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,18,882},{0,14,106},{0,10,52},{0,9,148},{0,12,2899},{0,9,1773},{0,8,725},
+{0,6,1854},{0,7,3348},{0,5,2124},{0,18,882},{0,14,106},{0,10,52},{0,9,148},{1,9,2899},{0,9,1773},{0,8,725},{0,6,1854},{6,0,2899},{0,6,1854},{0,11,1},{0,11,1},{0,11,1},{0,7,1},{0,6,580},{0,5,306},{0,5,306},{0,3,325},{0,3,667},{0,3,406},{0,11,1},{0,11,1},{0,11,1},{0,7,1},{1,2,580},{0,5,306},{0,5,306},{0,3,325},{2,1,578},
+{0,3,325},{3,8,882},{0,14,106},{1,9,13},{0,9,148},{3,8,882},{4,6,882},{0,9,148},{0,7,890},{4,6,882},{0,7,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,21,920},{0,16,89},{0,11,153},{0,10,121},{0,14,3051},{0,11,1709},{0,9,557},{0,7,1795},{0,8,3651},{0,6,2174},{0,21,920},
+{0,16,89},{1,10,108},{0,10,121},{4,1,3048},{0,11,1709},{0,9,557},{0,7,1795},{3,5,3048},{0,7,1795},{0,14,37},{0,14,37},{0,14,37},{0,8,37},{0,8,648},{0,7,274},{0,7,274},{0,4,277},{0,4,824},{0,4,421},{0,14,37},{0,14,37},{0,14,37},{0,8,37},{0,8,648},{0,7,274},{0,7,274},{0,4,277},{4,0,648},{0,4,277},{5,4,882},{0,16,53},{1,10,8},
+{0,10,85},{5,4,882},{9,1,882},{0,10,85},{0,8,900},{9,1,882},{0,8,900},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,10},{0,1,10},{0,23,1115},{0,18,242},{1,12,309},{0,11,259},{0,17,3051},{0,13,1579},{0,10,346},{0,8,1630},{0,9,3924},{0,7,2173},{1,20,885},{1,16,90},{1,12,53},{1,11,131},{4,4,3048},
+{0,13,1579},{0,10,346},{0,8,1630},{7,2,3048},{0,8,1630},{0,17,226},{0,17,226},{0,17,226},{0,10,225},{0,11,648},{0,9,169},{0,9,169},{0,5,200},{0,6,990},{0,5,425},{1,13,2},{1,13,2},{1,13,2},{1,9,2},{3,1,648},{0,9,169},{0,9,169},{0,5,200},{3,3,648},{0,5,200},{5,7,882},{0,18,17},{2,11,18},{0,11,34},{5,7,882},{6,7,882},{0,11,34},
+{0,9,890},{6,7,882},{0,9,890},{0,0,225},{0,0,225},{0,0,225},{0,0,225},{0,5,0},{0,5,0},{0,5,0},{0,3,0},{0,2,61},{0,2,61},{1,23,1187},{1,18,350},{1,13,422},{1,12,373},{0,20,3048},{0,15,1443},{0,12,204},{0,9,1483},{0,11,4212},{0,8,2174},{1,23,931},{1,18,94},{2,12,108},{1,12,117},{6,0,3048},{0,15,1443},{0,12,204},{0,9,1483},{5,6,3048},
+{0,9,1483},{1,16,305},{1,16,305},{1,16,305},{1,10,309},{0,13,650},{0,11,109},{0,11,109},{0,7,148},{0,7,1161},{0,6,473},{1,16,49},{1,16,49},{1,16,49},{1,10,53},{4,0,648},{0,11,109},{0,11,109},{0,7,148},{1,7,648},{0,7,148},{7,3,882},{0,20,8},{2,12,8},{0,12,8},{7,3,882},{11,2,882},{0,12,8},{0,10,890},{11,2,882},{0,10,890},{1,0,305},
+{1,0,305},{1,0,305},{1,0,305},{0,8,1},{0,8,1},{0,8,1},{0,5,4},{0,3,145},{0,3,145},{1,25,1365},{1,20,497},{1,14,713},{1,13,510},{0,23,3051},{0,16,1278},{0,13,86},{0,10,1354},{0,12,4609},{0,9,2228},{2,22,886},{2,18,110},{2,14,56},{2,13,152},{5,6,3048},{0,16,1278},{0,13,86},{0,10,1354},{10,1,3048},{0,10,1354},{1,19,482},{1,19,482},{1,19,482},
+{1,12,481},{0,16,648},{0,12,72},{0,12,72},{0,8,101},{0,8,1352},{0,7,557},{2,15,5},{2,15,5},{2,15,5},{2,11,5},{3,6,648},{0,12,72},{0,12,72},{0,8,101},{3,6,648},{0,8,101},{5,12,882},{0,21,10},{3,13,13},{0,13,5},{5,12,882},{13,1,882},{0,13,5},{0,11,890},{13,1,882},{0,11,890},{1,0,481},{1,0,481},{1,0,481},{1,0,481},{0,10,1},
+{0,10,1},{0,10,1},{0,6,1},{0,5,261},{0,5,261},{1,28,1667},{1,22,793},{1,15,1182},{1,14,793},{0,25,3048},{0,18,1170},{0,14,36},{0,11,1243},{0,14,5005},{0,10,2318},{2,25,920},{2,20,89},{3,14,108},{2,14,121},{7,2,3048},{0,18,1170},{0,14,36},{0,11,1243},{12,0,3048},{0,11,1243},{1,21,786},{1,21,786},{1,21,786},{1,14,789},{0,19,650},{0,14,32},{0,14,32},
+{0,9,50},{0,9,1619},{0,8,661},{2,18,37},{2,18,37},{2,18,37},{2,12,37},{5,2,648},{0,14,32},{0,14,32},{0,9,50},{8,1,648},{0,9,50},{8,3,882},{1,22,8},{3,14,8},{1,14,8},{8,3,882},{11,5,882},{1,14,8},{0,12,900},{11,5,882},{0,12,900},{1,0,785},{1,0,785},{1,0,785},{1,0,785},{0,13,1},{0,13,1},{0,13,1},{0,8,4},{0,6,405},
+{0,6,405},{2,27,1844},{2,22,971},{2,16,1186},{2,15,988},{0,28,3084},{0,20,1095},{0,16,77},{0,12,1159},{0,16,4945},{0,12,2084},{3,24,885},{3,20,90},{3,16,53},{3,15,131},{6,8,3048},{0,20,1059},{0,16,41},{0,12,1123},{4,12,3048},{0,12,1123},{2,21,955},{2,21,955},{2,21,955},{2,14,954},{0,22,686},{0,16,41},{0,16,41},{0,10,49},{0,11,1577},{0,9,545},{3,17,2},
+{3,17,2},{3,17,2},{3,13,2},{5,5,648},{0,16,5},{0,16,5},{0,10,13},{5,7,648},{0,10,13},{8,6,882},{1,24,9},{4,15,18},{1,15,13},{8,6,882},{15,2,882},{1,15,13},{0,13,890},{15,2,882},{0,13,890},{2,0,954},{2,0,954},{2,0,954},{2,0,954},{0,16,37},{0,16,37},{0,16,37},{0,9,40},{0,8,373},{0,8,373},{2,30,1772},{2,24,898},{2,17,1287},
+{2,16,898},{1,27,3055},{1,20,1143},{1,16,33},{1,13,1214},{0,17,4639},{0,13,1730},{3,27,931},{3,22,94},{4,16,108},{3,16,117},{5,14,3048},{0,21,996},{1,16,29},{0,13,1054},{14,1,3048},{0,13,1054},{2,23,891},{2,23,891},{2,23,891},{2,16,894},{1,21,652},{1,16,29},{1,16,29},{1,11,44},{0,13,1452},{0,11,365},{3,20,49},{3,20,49},{3,20,49},{3,14,53},{7,1,648},
+{0,18,1},{0,18,1},{0,11,4},{10,2,648},{0,11,4},{5,20,882},{2,24,8},{4,16,8},{2,16,8},{5,20,882},{13,6,882},{2,16,8},{0,14,890},{13,6,882},{0,14,890},{2,0,890},{2,0,890},{2,0,890},{2,0,890},{1,15,4},{1,15,4},{1,15,4},{1,10,5},{0,9,269},{0,9,269},{3,29,1838},{3,24,970},{3,18,1186},{3,17,983},{1,30,3084},{1,22,1095},{1,18,77},
+{1,14,1159},{0,19,4419},{0,14,1444},{4,26,886},{4,22,110},{4,18,56},{4,17,152},{8,5,3048},{0,23,936},{1,18,41},{0,14,1003},{12,5,3048},{0,14,1003},{3,23,955},{3,23,955},{3,23,955},{3,16,954},{1,23,692},{1,18,41},{1,18,41},{1,12,46},{0,15,1296},{0,12,235},{4,19,5},{4,19,5},{4,19,5},{4,15,5},{5,10,648},{1,18,5},{1,18,5},{0,12,10},{12,1,648},
+{0,12,10},{11,1,882},{2,25,10},{5,17,13},{2,17,5},{11,1,882},{15,5,882},{2,17,5},{0,15,890},{15,5,882},{0,15,890},{3,0,954},{3,0,954},{3,0,954},{3,0,954},{1,18,37},{1,18,37},{1,18,37},{1,11,40},{0,11,185},{0,11,185},{3,31,1790},{3,26,898},{3,19,1287},{3,18,898},{2,29,3057},{2,22,1179},{2,18,45},{1,15,1250},{0,20,4156},{0,15,1226},{4,29,920},
+{4,24,89},{5,18,108},{4,18,121},{3,26,3048},{0,25,909},{2,18,36},{0,15,970},{15,3,3048},{0,15,970},{3,25,891},{3,25,891},{3,25,891},{3,18,894},{2,23,659},{2,18,41},{2,18,41},{2,13,59},{0,16,1137},{0,13,137},{4,22,37},{4,22,37},{4,22,37},{4,16,37},{8,1,648},{1,20,2},{1,20,2},{1,13,1},{10,5,648},{1,13,1},{10,7,882},{3,26,8},{5,18,8},
+{3,18,8},{10,7,882},{13,9,882},{3,18,8},{0,16,900},{13,9,882},{0,16,900},{3,0,890},{3,0,890},{3,0,890},{3,0,890},{2,17,10},{2,17,10},{2,17,10},{2,12,13},{0,13,136},{0,13,136},{4,31,1844},{4,26,971},{4,20,1186},{4,19,988},{2,31,3111},{2,24,1095},{2,20,77},{2,16,1159},{0,22,3940},{0,16,1055},{5,28,885},{5,24,90},{5,20,53},{5,19,131},{5,22,3048},
+{0,27,886},{2,20,41},{0,17,926},{8,13,3048},{0,17,926},{4,25,955},{4,25,955},{4,25,955},{4,18,954},{2,26,686},{2,20,41},{2,20,41},{2,14,49},{0,18,1002},{0,15,110},{5,21,2},{5,21,2},{5,21,2},{5,17,2},{8,4,648},{2,20,5},{2,20,5},{2,14,13},{14,2,648},{2,14,13},{13,0,882},{3,28,9},{6,19,18},{3,19,13},{13,0,882},{5,21,882},{3,19,13},
+{0,17,890},{5,21,882},{0,17,890},{4,0,954},{4,0,954},{4,0,954},{4,0,954},{2,20,37},{2,20,37},{2,20,37},{2,13,40},{0,15,74},{0,15,74},{4,31,1972},{4,28,898},{4,21,1287},{4,20,898},{3,31,3055},{3,24,1143},{3,20,33},{3,17,1214},{0,23,3820},{0,18,963},{5,31,931},{5,26,94},{6,20,108},{5,20,117},{11,3,3048},{0,28,899},{3,20,29},{0,18,899},{11,11,3048},
+{0,18,899},{4,27,891},{4,27,891},{4,27,891},{4,20,894},{3,25,652},{3,20,29},{3,20,29},{3,15,44},{0,20,876},{0,16,102},{5,24,49},{5,24,49},{5,24,49},{5,18,53},{3,25,648},{2,22,1},{2,22,1},{2,15,4},{12,6,648},{2,15,4},{8,19,882},{4,28,8},{6,20,8},{4,20,8},{8,19,882},{15,10,882},{4,20,8},{0,18,890},{15,10,882},{0,18,890},{4,0,890},
+{4,0,890},{4,0,890},{4,0,890},{3,19,4},{3,19,4},{3,19,4},{3,14,5},{0,17,29},{0,17,29},{5,31,1964},{5,28,970},{5,22,1186},{5,21,983},{4,31,3172},{3,26,1095},{3,22,77},{3,18,1159},{0,25,3679},{0,19,899},{6,30,886},{6,26,110},{6,22,56},{6,21,152},{10,9,3048},{1,29,888},{3,22,41},{0,19,890},{14,9,3048},{0,19,890},{5,27,955},{5,27,955},{5,27,955},
+{5,20,954},{3,27,692},{3,22,41},{3,22,41},{3,16,46},{0,22,800},{1,16,98},{6,23,5},{6,23,5},{6,23,5},{6,19,5},{9,6,648},{3,22,5},{3,22,5},{2,16,10},{14,5,648},{2,16,10},{13,5,882},{4,29,10},{7,21,13},{4,21,5},{13,5,882},{12,15,882},{4,21,5},{0,19,890},{12,15,882},{0,19,890},{5,0,954},{5,0,954},{5,0,954},{5,0,954},{3,22,37},
+{3,22,37},{3,22,37},{3,15,40},{0,19,9},{0,19,9},{6,31,2264},{5,30,898},{5,23,1287},{5,22,898},{4,31,3204},{4,26,1179},{4,22,45},{3,19,1250},{0,27,3523},{0,20,908},{6,31,968},{6,28,89},{7,22,108},{6,22,121},{9,15,3048},{1,30,899},{4,22,36},{0,20,904},{5,22,3048},{0,20,904},{5,29,891},{5,29,891},{5,29,891},{5,22,894},{4,27,659},{4,22,41},{4,22,41},
+{4,17,59},{0,23,747},{1,18,102},{6,26,37},{6,26,37},{6,26,37},{6,20,37},{10,5,648},{3,24,2},{3,24,2},{3,17,1},{12,9,648},{3,17,1},{15,1,882},{5,30,8},{7,22,8},{5,22,8},{15,1,882},{15,13,882},{5,22,8},{0,20,900},{15,13,882},{0,20,900},{5,0,890},{5,0,890},{5,0,890},{5,0,890},{4,21,10},{4,21,10},{4,21,10},{4,16,13},{0,20,8},
+{0,20,8},{6,31,2228},{6,30,971},{6,24,1186},{6,23,988},{5,31,3256},{4,28,1095},{4,24,77},{4,20,1159},{0,29,3364},{1,21,894},{7,31,915},{7,28,90},{7,24,53},{7,23,131},{14,1,3048},{2,31,886},{4,24,41},{1,21,890},{10,17,3048},{1,21,890},{6,29,955},{6,29,955},{6,29,955},{6,22,954},{4,30,686},{4,24,41},{4,24,41},{4,18,49},{0,25,705},{2,19,110},{7,25,2},
+{7,25,2},{7,25,2},{7,21,2},{10,8,648},{4,24,5},{4,24,5},{4,18,13},{11,12,648},{4,18,13},{15,4,882},{6,30,17},{7,24,52},{5,23,13},{15,4,882},{9,22,882},{5,23,13},{0,21,890},{9,22,882},{0,21,890},{6,0,954},{6,0,954},{6,0,954},{6,0,954},{4,24,37},{4,24,37},{4,24,37},{4,17,40},{1,21,4},{1,21,4},{7,31,2444},{6,31,907},{6,25,1287},
+{6,24,898},{6,31,3436},{5,28,1143},{5,24,33},{5,21,1214},{0,31,3276},{1,22,908},{8,30,1208},{7,30,94},{7,25,166},{7,24,117},{13,7,3048},{3,31,906},{5,24,29},{1,22,899},{13,15,3048},{1,22,899},{6,31,891},{6,31,891},{6,31,891},{6,24,894},{5,29,652},{5,24,29},{5,24,29},{5,19,44},{0,27,665},{2,20,102},{7,28,49},{7,28,49},{7,28,49},{7,22,53},{9,14,648},
+{4,26,1},{4,26,1},{4,19,4},{14,10,648},{4,19,4},{10,23,882},{6,31,17},{8,24,13},{6,24,8},{10,23,882},{11,21,882},{6,24,8},{0,22,890},{11,21,882},{0,22,890},{6,0,890},{6,0,890},{6,0,890},{6,0,890},{5,23,4},{5,23,4},{5,23,4},{5,18,5},{1,23,4},{1,23,4},{7,31,2636},{7,31,991},{7,26,1186},{7,25,983},{6,31,3532},{5,30,1095},{5,26,77},
+{5,22,1159},{0,31,3340},{2,23,899},{8,31,1014},{7,31,262},{8,25,108},{7,25,254},{15,3,3048},{4,31,936},{5,26,41},{2,23,890},{11,19,3048},{2,23,890},{7,31,955},{7,31,955},{7,31,955},{7,24,954},{5,31,692},{5,26,41},{5,26,41},{5,20,46},{0,29,651},{3,20,98},{8,26,101},{8,26,101},{8,26,101},{8,22,101},{11,10,648},{5,26,5},{5,26,5},{4,20,10},{5,23,648},
+{4,20,10},{15,9,882},{7,31,37},{8,25,8},{6,25,5},{15,9,882},{14,19,882},{6,25,5},{0,23,890},{14,19,882},{0,23,890},{7,0,954},{7,0,954},{7,0,954},{7,0,954},{5,26,37},{5,26,37},{5,26,37},{5,19,40},{2,23,9},{2,23,9},{8,31,3110},{7,31,1135},{7,27,1287},{7,26,898},{7,31,3652},{6,30,1179},{6,26,45},{5,23,1250},{1,31,3492},{2,24,908},{8,31,1174},
+{8,31,110},{8,27,56},{8,26,152},{11,19,3048},{5,31,996},{6,26,36},{2,24,904},{9,23,3048},{2,24,904},{7,31,939},{7,31,939},{7,31,939},{7,26,894},{6,31,659},{6,26,41},{6,26,41},{6,21,59},{1,29,659},{3,22,102},{8,28,4},{8,28,4},{8,28,4},{8,24,8},{12,9,648},{5,28,2},{5,28,2},{5,21,1},{14,13,648},{5,21,1},{14,15,882},{8,31,106},{9,26,13},
+{7,26,8},{14,15,882},{12,23,882},{7,26,8},{0,24,900},{12,23,882},{0,24,900},{7,0,890},{7,0,890},{7,0,890},{7,0,890},{6,25,10},{6,25,10},{6,25,10},{6,20,13},{2,24,8},{2,24,8},{8,31,3038},{8,31,1470},{8,28,1391},{7,27,1137},{7,31,4120},{6,31,1146},{6,28,77},{6,24,1159},{3,31,3681},{3,25,894},{9,31,1205},{8,31,245},{9,27,99},{8,27,122},{10,25,3048},
+{6,31,1110},{6,28,41},{3,25,890},{12,21,3048},{3,25,890},{8,31,1274},{8,31,1274},{8,31,1274},{7,27,1128},{7,30,750},{6,28,41},{6,28,41},{6,22,49},{1,31,648},{4,23,110},{8,31,49},{8,31,49},{8,31,49},{8,25,53},{15,2,648},{6,28,5},{6,28,5},{6,22,13},{13,16,648},{6,22,13},{14,18,882},{9,31,164},{9,27,18},{7,27,13},{14,18,882},{11,26,882},{7,27,13},
+{0,25,890},{11,26,882},{0,25,890},{7,0,1124},{7,0,1124},{7,0,1124},{7,0,1124},{6,28,37},{6,28,37},{6,28,37},{6,21,40},{3,25,4},{3,25,4},{9,31,3454},{8,31,1502},{8,29,1186},{8,28,983},{8,31,4077},{7,31,1230},{7,28,33},{7,25,1214},{4,31,3820},{3,26,908},{10,31,1368},{9,31,261},{9,29,53},{9,28,126},{15,11,3048},{7,31,1226},{7,28,29},{3,26,899},{15,19,3048},
+{3,26,899},{8,31,1018},{8,31,1018},{8,31,1018},{8,27,954},{7,31,724},{7,28,29},{7,28,29},{7,23,44},{2,31,665},{4,24,102},{9,30,2},{9,30,2},{9,30,2},{9,26,2},{11,18,648},{6,30,1},{6,30,1},{6,23,4},{10,21,648},{6,23,4},{12,27,882},{10,31,225},{10,28,13},{7,28,20},{12,27,882},{13,25,882},{7,28,20},{0,26,890},{13,25,882},{0,26,890},{8,0,954},
+{8,0,954},{8,0,954},{8,0,954},{7,27,4},{7,27,4},{7,27,4},{7,22,5},{3,27,4},{3,27,4},{9,31,3614},{9,31,1886},{8,30,1287},{8,29,898},{8,31,4381},{7,31,1582},{7,30,77},{7,26,1159},{5,31,4036},{4,27,899},{10,31,1560},{10,31,405},{10,29,108},{9,29,117},{14,17,3048},{8,31,1444},{7,30,41},{4,27,890},{13,23,3048},{4,27,890},{8,31,1146},{8,31,1146},{8,31,1146},
+{8,29,894},{8,30,1011},{7,30,41},{7,30,41},{7,24,46},{3,31,705},{5,24,98},{9,31,85},{9,31,85},{9,31,85},{9,27,53},{13,14,648},{7,30,5},{7,30,5},{6,24,10},{8,25,648},{6,24,10},{14,23,882},{10,31,305},{10,29,8},{8,29,8},{14,23,882},{11,29,882},{8,29,8},{0,27,890},{11,29,882},{0,27,890},{8,0,890},{8,0,890},{8,0,890},{8,0,890},{7,30,37},
+{7,30,37},{7,30,37},{7,23,40},{4,27,9},{4,27,9},{10,31,4072},{9,31,2174},{9,31,1186},{9,30,983},{9,31,4545},{8,31,1725},{8,30,207},{7,27,1250},{6,31,4339},{4,28,908},{11,31,1656},{10,31,645},{10,31,56},{10,30,152},{13,23,3048},{8,31,1604},{7,31,77},{4,28,904},{11,27,3048},{4,28,904},{9,31,1150},{9,31,1150},{9,31,1150},{9,29,954},{8,31,841},{8,29,193},{8,29,193},
+{7,25,197},{4,31,747},{5,26,102},{10,31,20},{10,31,20},{10,31,20},{10,28,8},{14,13,648},{7,31,41},{7,31,41},{7,25,1},{11,23,648},{7,25,1},{13,29,882},{11,31,397},{11,30,13},{8,30,5},{13,29,882},{14,27,882},{8,30,5},{0,28,900},{14,27,882},{0,28,900},{9,0,954},{9,0,954},{9,0,954},{9,0,954},{8,27,122},{8,27,122},{8,27,122},{8,23,122},{4,28,8},
+{4,28,8},{10,31,4147},{10,31,2404},{9,31,1429},{9,31,901},{10,31,4627},{9,31,1938},{8,31,38},{8,28,1061},{7,31,4330},{5,29,789},{12,31,1701},{11,31,715},{11,31,90},{10,31,113},{15,19,2814},{10,31,1554},{8,31,34},{5,29,785},{13,26,2814},{5,29,785},{9,31,1429},{9,31,1429},{9,31,1429},{9,31,901},{9,31,1022},{8,31,38},{8,31,38},{8,26,44},{5,31,840},{6,27,110},{11,31,90},
+{11,31,90},{11,31,90},{10,29,53},{14,16,648},{8,31,34},{8,31,34},{7,26,20},{15,20,648},{7,26,20},{15,25,761},{12,31,425},{11,31,9},{9,31,1},{15,25,761},{12,31,761},{9,31,1},{0,29,785},{12,31,761},{0,29,785},{9,0,900},{9,0,900},{9,0,900},{9,0,900},{8,30,4},{8,30,4},{8,30,4},{8,25,5},{5,29,4},{5,29,4},{11,31,3735},{10,31,2356},{10,31,1395},
+{10,31,954},{10,31,4099},{9,31,1618},{9,31,174},{8,29,686},{7,31,3930},{6,29,510},{12,31,1285},{12,31,685},{11,31,122},{11,31,37},{13,27,2249},{10,31,1186},{9,31,74},{6,29,485},{13,27,2249},{6,29,485},{10,31,1395},{10,31,1395},{10,31,1395},{10,31,954},{9,31,1086},{9,31,174},{9,31,174},{8,27,49},{6,31,969},{6,28,102},{11,31,122},{11,31,122},{11,31,122},{11,30,2},{13,22,648},
+{9,31,74},{9,31,74},{8,27,13},{12,25,648},{8,27,13},{15,26,481},{13,31,269},{12,31,0},{10,31,0},{15,26,481},{15,28,481},{10,31,0},{0,29,481},{15,28,481},{0,29,481},{10,0,954},{10,0,954},{10,0,954},{10,0,954},{8,31,61},{8,31,61},{8,31,61},{8,26,40},{5,31,4},{5,31,4},{11,31,3399},{11,31,2260},{11,31,1635},{10,31,954},{11,31,3639},{10,31,1435},{9,31,238},
+{9,29,430},{8,31,3443},{6,30,314},{13,31,1121},{12,31,525},{12,31,164},{11,31,53},{13,29,1769},{11,31,918},{10,31,113},{7,30,290},{14,27,1769},{7,30,290},{11,31,1635},{11,31,1635},{11,31,1635},{10,31,954},{10,31,1251},{9,31,238},{9,31,238},{9,28,41},{7,31,1105},{7,28,98},{12,31,164},{12,31,164},{12,31,164},{11,31,53},{15,18,648},{10,31,113},{10,31,113},{8,28,1},{10,29,648},
+{8,28,1},{15,27,269},{13,31,173},{13,31,4},{11,31,4},{15,27,269},{14,30,265},{11,31,4},{0,30,289},{14,30,265},{0,30,289},{10,0,890},{10,0,890},{10,0,890},{10,0,890},{9,31,13},{9,31,13},{9,31,13},{9,27,5},{6,31,9},{6,31,9},{12,31,3157},{11,31,2308},{11,31,1683},{11,31,1054},{11,31,3303},{10,31,1339},{10,31,378},{9,30,213},{9,31,3103},{7,30,166},{13,31,801},
+{13,31,529},{12,31,260},{12,31,20},{15,24,1374},{12,31,777},{11,31,181},{8,30,117},{15,27,1377},{8,30,117},{11,31,1683},{11,31,1683},{11,31,1683},{11,31,1054},{10,31,1491},{10,31,378},{10,31,378},{9,29,46},{8,31,1331},{7,30,102},{12,31,260},{12,31,260},{12,31,260},{12,31,20},{13,27,648},{11,31,181},{11,31,181},{8,29,10},{13,27,648},{8,29,10},{15,28,117},{14,31,61},{14,31,25},
+{13,31,4},{15,28,117},{14,31,117},{13,31,4},{0,30,113},{14,31,117},{0,30,113},{11,0,954},{11,0,954},{11,0,954},{11,0,954},{10,31,122},{10,31,122},{10,31,122},{9,28,40},{7,31,29},{7,31,29},{12,31,2860},{12,31,2260},{12,31,1899},{11,31,1261},{12,31,2932},{11,31,1310},{11,31,685},{10,30,108},{10,31,2731},{7,31,173},{13,31,747},{13,31,475},{13,31,306},{13,31,130},{15,26,1032},
+{12,31,651},{12,31,290},{8,31,40},{14,29,1032},{8,31,40},{12,31,1899},{12,31,1899},{12,31,1899},{11,31,1261},{11,31,1620},{11,31,685},{11,31,685},{10,30,44},{9,31,1524},{8,30,134},{13,31,306},{13,31,306},{13,31,306},{13,31,130},{13,30,648},{12,31,290},{12,31,290},{9,30,5},{12,30,648},{9,30,5},{15,30,18},{15,30,34},{14,31,16},{14,31,0},{15,30,18},{15,30,26},{14,31,0},
+{0,31,36},{15,30,26},{0,31,36},{11,0,900},{11,0,900},{11,0,900},{11,0,900},{10,31,104},{10,31,104},{10,31,104},{10,29,5},{8,30,130},{8,30,130},{13,31,2732},{12,31,2276},{12,31,1915},{12,31,1315},{12,31,2660},{11,31,1414},{11,31,789},{10,31,45},{11,31,2487},{8,31,116},{14,31,524},{14,31,460},{14,31,424},{13,31,170},{14,31,776},{13,31,507},{13,31,338},{10,31,9},{14,30,771},
+{10,31,9},{12,31,1915},{12,31,1915},{12,31,1915},{12,31,1315},{12,31,1699},{11,31,789},{11,31,789},{10,31,45},{10,31,1546},{8,31,116},{14,31,424},{14,31,424},{14,31,424},{13,31,170},{15,26,580},{13,31,338},{13,31,338},{10,31,9},{14,29,580},{10,31,9},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{12,0,954},
+{12,0,954},{12,0,954},{12,0,954},{11,31,164},{11,31,164},{11,31,164},{10,30,40},{8,31,116},{8,31,116},{13,31,2156},{13,31,1884},{13,31,1715},{12,31,1251},{13,31,2132},{12,31,1108},{12,31,747},{11,31,5},{11,31,1927},{9,31,180},{14,31,300},{14,31,236},{14,31,200},{14,31,136},{15,28,451},{14,31,328},{13,31,194},{11,31,1},{15,29,456},{11,31,1},{13,31,1715},{13,31,1715},{13,31,1715},
+{12,31,1251},{12,31,1347},{12,31,747},{12,31,747},{11,31,5},{10,31,1242},{9,31,180},{14,31,200},{14,31,200},{14,31,200},{14,31,136},{15,27,338},{13,31,194},{13,31,194},{11,31,1},{13,31,338},{11,31,1},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{12,0,890},{12,0,890},{12,0,890},{12,0,890},{11,31,260},
+{11,31,260},{11,31,260},{11,31,5},{9,31,180},{9,31,180},{13,31,1836},{13,31,1564},{13,31,1395},{13,31,1123},{13,31,1620},{12,31,1012},{12,31,651},{11,31,85},{12,31,1564},{10,31,233},{14,31,204},{14,31,140},{14,31,104},{14,31,40},{15,29,216},{14,31,136},{14,31,100},{12,31,1},{14,31,216},{12,31,1},{13,31,1395},{13,31,1395},{13,31,1395},{13,31,1123},{13,31,1179},{12,31,651},{12,31,651},
+{11,31,85},{11,31,998},{10,31,233},{14,31,104},{14,31,104},{14,31,104},{14,31,40},{15,28,162},{14,31,100},{14,31,100},{12,31,1},{15,29,164},{12,31,1},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{13,0,954},{13,0,954},{13,0,954},{13,0,954},{12,31,290},{12,31,290},{12,31,290},{11,31,85},{10,31,233},
+{10,31,233},{0,17,1568},{0,14,442},{0,10,40},{0,8,485},{0,11,3379},{0,9,2369},{0,8,1061},{0,5,2435},{0,6,3760},{0,5,2660},{0,17,1568},{0,14,442},{0,10,40},{0,8,485},{1,8,3372},{0,9,2369},{0,8,1061},{0,5,2435},{5,1,3371},{0,5,2435},{0,8,0},{0,8,0},{0,8,0},{0,5,1},{0,4,288},{0,4,160},{0,4,160},{0,2,164},{0,2,332},{0,2,200},{0,8,0},
+{0,8,0},{0,8,0},{0,5,1},{0,4,288},{0,4,160},{0,4,160},{0,2,164},{2,0,288},{0,2,164},{3,7,1568},{0,14,442},{0,10,40},{0,8,485},{3,7,1568},{8,0,1568},{0,8,485},{0,6,1586},{8,0,1568},{0,6,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,20,1570},{0,16,325},{0,11,5},
+{0,9,392},{0,13,3968},{0,10,2630},{0,9,1121},{0,6,2710},{0,7,4484},{0,6,3034},{0,20,1570},{0,16,325},{0,11,5},{0,9,392},{1,10,3968},{0,10,2630},{0,9,1121},{0,6,2710},{5,2,3968},{0,6,2710},{0,11,1},{0,11,1},{0,11,1},{0,6,4},{0,5,514},{0,5,274},{0,5,274},{0,3,289},{0,3,595},{0,3,370},{0,11,1},{0,11,1},{0,11,1},{0,6,4},{1,2,512},
+{0,5,274},{0,5,274},{0,3,289},{1,2,512},{0,3,289},{5,3,1568},{0,16,325},{0,11,5},{0,9,392},{5,3,1568},{4,7,1568},{0,9,392},{0,7,1586},{4,7,1568},{0,7,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,22,1570},{0,17,225},{0,12,18},{0,11,292},{0,15,4652},{0,11,2945},{0,10,1217},
+{0,7,3035},{0,8,5283},{0,7,3476},{0,22,1570},{0,17,225},{0,12,18},{0,11,292},{2,8,4651},{0,11,2945},{0,10,1217},{0,7,3035},{5,3,4651},{0,7,3035},{0,13,0},{0,13,0},{0,13,0},{0,8,1},{0,7,802},{0,6,424},{0,6,424},{0,4,449},{0,3,931},{0,3,562},{0,13,0},{0,13,0},{0,13,0},{0,8,1},{2,0,800},{0,6,424},{0,6,424},{0,4,449},{0,4,800},
+{0,4,449},{1,19,1568},{0,17,225},{0,12,18},{0,11,292},{1,19,1568},{9,2,1568},{0,11,292},{0,8,1576},{9,2,1568},{0,8,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,1570},{0,19,149},{0,13,73},{0,12,194},{0,17,5424},{0,13,3368},{0,11,1349},{0,8,3449},{0,9,6213},{0,7,3956},{0,25,1570},
+{0,19,149},{0,13,73},{0,12,194},{5,0,5419},{0,13,3368},{0,11,1349},{0,8,3449},{5,4,5419},{0,8,3449},{0,16,1},{0,16,1},{0,16,1},{0,9,4},{0,8,1152},{0,7,610},{0,7,610},{0,4,625},{0,4,1328},{0,4,769},{0,16,1},{0,16,1},{0,16,1},{0,9,4},{0,8,1152},{0,7,610},{0,7,610},{0,4,625},{4,0,1152},{0,4,625},{5,8,1568},{0,19,149},{1,13,13},
+{0,12,194},{5,8,1568},{4,10,1568},{0,12,194},{0,9,1576},{4,10,1568},{0,9,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,28,1651},{0,21,155},{0,14,281},{0,13,198},{0,20,5424},{0,15,3099},{0,12,996},{0,9,3179},{0,10,6544},{0,8,3890},{1,24,1619},{0,21,155},{1,14,69},{0,13,198},{5,3,5419},
+{0,15,3099},{0,12,996},{0,9,3179},{4,7,5419},{0,9,3179},{0,19,82},{0,19,82},{0,19,82},{0,11,82},{0,11,1152},{0,9,445},{0,9,445},{0,6,505},{0,6,1494},{0,5,737},{1,15,50},{1,15,50},{1,15,50},{1,10,49},{3,1,1152},{0,9,445},{0,9,445},{0,6,505},{3,3,1152},{0,6,505},{5,11,1568},{0,21,74},{1,14,20},{0,13,117},{5,11,1568},{11,3,1568},{0,13,117},
+{0,10,1586},{11,3,1568},{0,10,1586},{0,0,81},{0,0,81},{0,0,81},{0,0,81},{0,3,0},{0,3,0},{0,3,0},{0,2,1},{0,1,25},{0,1,25},{1,27,1825},{0,23,323},{1,15,342},{0,14,361},{0,22,5420},{0,16,2834},{0,13,726},{0,10,2966},{0,11,6916},{0,9,3860},{1,27,1569},{1,21,131},{1,15,86},{1,14,181},{1,19,5419},{0,16,2834},{0,13,726},{0,10,2966},{9,2,5419},
+{0,10,2966},{1,18,257},{1,18,257},{1,18,257},{1,12,261},{0,13,1154},{0,11,337},{0,11,337},{0,7,388},{0,7,1665},{0,6,749},{1,18,1},{1,18,1},{1,18,1},{1,12,5},{4,0,1152},{0,11,337},{0,11,337},{0,7,388},{1,7,1152},{0,7,388},{8,2,1568},{0,23,34},{2,15,5},{0,14,72},{8,2,1568},{13,2,1568},{0,14,72},{0,11,1586},{13,2,1568},{0,11,1586},{1,0,257},
+{1,0,257},{1,0,257},{1,0,257},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{0,2,85},{0,2,85},{1,30,1907},{1,23,411},{1,16,542},{1,15,454},{0,25,5424},{0,18,2630},{0,15,486},{0,11,2771},{0,13,7299},{0,11,3860},{2,26,1634},{1,23,155},{2,16,82},{1,15,198},{5,8,5419},{0,18,2630},{0,15,486},{0,11,2771},{4,10,5419},{0,11,2771},{1,21,338},{1,21,338},{1,21,338},
+{1,13,338},{0,16,1152},{0,13,274},{0,13,274},{0,8,305},{0,8,1856},{0,7,797},{2,17,64},{2,17,64},{2,17,64},{2,12,65},{3,6,1152},{0,13,274},{0,13,274},{0,8,305},{3,6,1152},{0,8,305},{3,23,1568},{0,25,17},{2,16,18},{0,15,45},{3,23,1568},{11,6,1568},{0,15,45},{0,12,1576},{11,6,1568},{0,12,1576},{1,0,337},{1,0,337},{1,0,337},{1,0,337},{0,8,1},
+{0,8,1},{0,8,1},{0,5,0},{0,4,169},{0,4,169},{1,31,2145},{1,25,590},{1,17,915},{1,16,619},{0,27,5420},{0,20,2424},{0,16,282},{0,12,2552},{0,15,7711},{0,11,3908},{2,29,1570},{2,23,149},{2,17,73},{2,16,194},{7,4,5419},{0,20,2424},{0,16,282},{0,12,2552},{9,5,5419},{0,12,2552},{1,23,546},{1,23,546},{1,23,546},{1,15,546},{0,19,1154},{0,15,194},{0,15,194},
+{0,9,218},{0,9,2123},{0,8,865},{2,20,1},{2,20,1},{2,20,1},{2,13,4},{5,2,1152},{0,15,194},{0,15,194},{0,9,218},{8,1,1152},{0,9,218},{9,4,1568},{0,27,5},{3,17,13},{0,16,26},{9,4,1568},{9,10,1568},{0,16,26},{0,13,1576},{9,10,1568},{0,13,1576},{1,0,545},{1,0,545},{1,0,545},{1,0,545},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,289},
+{0,5,289},{2,31,2746},{1,27,945},{2,18,1370},{1,17,977},{0,30,5420},{0,22,2243},{0,17,145},{0,13,2386},{0,16,8161},{0,13,3986},{3,28,1619},{2,25,155},{3,18,69},{2,17,198},{8,2,5419},{0,22,2243},{0,17,145},{0,13,2386},{13,2,5419},{0,13,2386},{1,26,932},{1,26,932},{1,26,932},{1,16,936},{0,22,1154},{0,17,109},{0,17,109},{0,10,145},{0,11,2441},{0,9,1001},{3,19,50},
+{3,19,50},{3,19,50},{3,14,49},{5,5,1152},{0,17,109},{0,17,109},{0,10,145},{5,7,1152},{0,10,145},{11,0,1568},{0,29,10},{3,18,20},{0,18,8},{11,0,1568},{13,7,1568},{0,18,8},{0,14,1586},{13,7,1568},{0,14,1586},{1,0,932},{1,0,932},{1,0,932},{1,0,932},{0,14,1},{0,14,1},{0,14,1},{0,8,1},{0,6,468},{0,6,468},{2,31,3146},{2,27,1412},{2,19,1743},
+{1,19,1441},{0,31,5515},{0,23,2096},{0,19,69},{0,14,2251},{0,18,8669},{0,14,4100},{3,31,1569},{3,25,131},{3,19,86},{3,18,181},{3,23,5419},{0,23,2096},{0,19,69},{0,14,2251},{11,6,5419},{0,14,2251},{2,25,1379},{2,25,1379},{2,25,1379},{2,17,1379},{0,24,1152},{0,18,61},{0,18,61},{0,11,100},{0,12,2859},{0,10,1157},{3,22,1},{3,22,1},{3,22,1},{3,16,5},{7,1,1152},
+{0,18,61},{0,18,61},{0,11,100},{10,2,1152},{0,11,100},{10,6,1568},{1,29,2},{4,19,5},{0,19,5},{10,6,1568},{15,6,1568},{0,19,5},{0,15,1586},{15,6,1568},{0,15,1586},{2,0,1378},{2,0,1378},{2,0,1378},{2,0,1378},{0,16,1},{0,16,1},{0,16,1},{0,10,1},{0,8,657},{0,8,657},{2,31,3802},{2,29,1603},{2,21,2148},{2,19,1631},{1,31,5655},{0,25,2005},{0,20,31},
+{0,15,2138},{0,19,8963},{0,15,4070},{4,30,1634},{3,27,155},{4,20,82},{3,19,198},{9,4,5419},{0,25,2001},{0,20,27},{0,15,2134},{9,10,5419},{0,15,2134},{2,28,1587},{2,28,1587},{2,28,1587},{2,18,1590},{0,27,1158},{0,20,22},{0,20,22},{0,12,62},{0,14,3075},{0,11,1221},{4,21,64},{4,21,64},{4,21,64},{4,16,65},{5,10,1152},{0,20,18},{0,20,18},{0,12,58},{12,1,1152},
+{0,12,58},{12,2,1568},{1,31,10},{4,20,18},{0,20,18},{12,2,1568},{13,10,1568},{0,20,18},{0,16,1576},{13,10,1568},{0,16,1576},{2,0,1586},{2,0,1586},{2,0,1586},{2,0,1586},{0,19,4},{0,19,4},{0,19,4},{0,11,8},{0,9,769},{0,9,769},{3,31,3890},{2,31,1623},{3,21,2180},{2,20,1644},{1,31,5863},{0,27,1989},{1,21,109},{0,17,2117},{0,21,8560},{0,16,3545},{4,31,1640},
+{4,27,149},{4,21,73},{4,20,194},{10,3,5419},{0,27,1889},{0,21,49},{0,17,2017},{11,9,5419},{0,17,2017},{2,30,1619},{2,30,1619},{2,30,1619},{2,20,1619},{1,26,1188},{1,20,86},{1,20,86},{1,13,121},{0,16,2801},{0,13,949},{4,24,1},{4,24,1},{4,24,1},{4,17,4},{8,1,1152},{0,22,2},{0,22,2},{0,14,26},{10,5,1152},{0,14,26},{11,8,1568},{2,31,5},{5,21,13},
+{1,21,9},{11,8,1568},{11,14,1568},{1,21,9},{0,17,1576},{11,14,1568},{0,17,1576},{2,0,1618},{2,0,1618},{2,0,1618},{2,0,1618},{1,18,37},{1,18,37},{1,18,37},{1,12,37},{0,10,625},{0,10,625},{4,31,4308},{3,31,1589},{3,23,2160},{3,21,1621},{2,31,5895},{1,27,1999},{1,22,33},{1,18,2124},{0,23,8196},{0,17,3043},{5,31,1667},{4,29,155},{5,22,69},{4,21,198},{10,6,5419},
+{0,29,1772},{1,22,24},{0,18,1875},{15,6,5419},{0,18,1875},{3,30,1576},{3,30,1576},{3,30,1576},{3,20,1580},{1,29,1161},{1,22,29},{1,22,29},{1,15,58},{0,17,2529},{0,14,656},{5,23,50},{5,23,50},{5,23,50},{5,18,49},{8,4,1152},{0,24,1},{0,24,1},{0,15,1},{14,2,1152},{0,15,1},{13,4,1568},{3,31,13},{5,22,20},{2,22,8},{13,4,1568},{15,11,1568},{2,22,8},
+{0,18,1586},{15,11,1568},{0,18,1586},{3,0,1576},{3,0,1576},{3,0,1576},{3,0,1576},{1,21,10},{1,21,10},{1,21,10},{1,14,13},{0,12,520},{0,12,520},{4,31,4436},{3,31,1765},{4,23,2175},{3,23,1669},{3,31,6079},{1,29,1977},{2,23,105},{1,19,2107},{0,24,7969},{0,18,2675},{6,31,1832},{5,29,131},{5,23,86},{5,22,181},{12,2,5419},{0,30,1699},{1,23,62},{0,19,1782},{13,10,5419},
+{0,19,1782},{3,31,1665},{3,31,1665},{3,31,1665},{3,22,1640},{2,28,1188},{2,22,97},{2,22,97},{2,15,136},{0,19,2313},{0,15,474},{5,26,1},{5,26,1},{5,26,1},{5,20,5},{3,25,1152},{1,24,5},{1,24,5},{0,16,2},{12,6,1152},{0,16,2},{15,0,1568},{4,31,34},{6,23,5},{2,23,5},{15,0,1568},{12,16,1568},{2,23,5},{0,19,1586},{12,16,1568},{0,19,1586},{3,0,1640},
+{3,0,1640},{3,0,1640},{3,0,1640},{2,20,37},{2,20,37},{2,20,37},{2,14,37},{0,14,400},{0,14,400},{5,31,4740},{4,31,1716},{4,25,2148},{4,23,1631},{3,31,6351},{2,29,2005},{2,24,31},{2,19,2138},{0,26,7669},{0,19,2375},{6,31,1832},{5,31,155},{6,24,82},{5,23,198},{11,8,5419},{0,31,1712},{2,24,27},{0,20,1720},{11,14,5419},{0,20,1720},{4,31,1595},{4,31,1595},{4,31,1595},
+{4,22,1590},{2,31,1158},{2,24,22},{2,24,22},{2,16,62},{0,21,2091},{0,17,306},{6,25,64},{6,25,64},{6,25,64},{6,20,65},{9,6,1152},{1,26,1},{1,26,1},{1,17,5},{14,5,1152},{1,17,5},{14,6,1568},{5,31,74},{6,24,18},{2,24,18},{14,6,1568},{15,14,1568},{2,24,18},{0,20,1576},{15,14,1568},{0,20,1576},{4,0,1586},{4,0,1586},{4,0,1586},{4,0,1586},{2,23,4},
+{2,23,4},{2,23,4},{2,15,8},{0,16,277},{0,16,277},{5,31,5060},{5,31,1980},{5,25,2180},{4,24,1644},{4,31,6508},{2,31,1989},{3,25,109},{2,21,2117},{0,28,7364},{0,21,2098},{7,31,1952},{6,31,149},{6,25,73},{6,24,194},{12,7,5419},{1,31,1804},{2,25,49},{0,21,1657},{13,13,5419},{0,21,1657},{4,31,1739},{4,31,1739},{4,31,1739},{4,24,1619},{3,30,1188},{3,24,86},{3,24,86},
+{3,17,121},{0,22,1928},{0,18,194},{6,28,1},{6,28,1},{6,28,1},{6,21,4},{10,5,1152},{2,26,2},{2,26,2},{1,18,2},{12,9,1152},{1,18,2},{13,12,1568},{6,31,149},{7,25,13},{3,25,9},{13,12,1568},{13,18,1568},{3,25,9},{0,21,1576},{13,18,1568},{0,21,1576},{4,0,1618},{4,0,1618},{4,0,1618},{4,0,1618},{3,22,37},{3,22,37},{3,22,37},{3,16,37},{0,18,193},
+{0,18,193},{6,31,5316},{5,31,2160},{5,27,2160},{5,25,1621},{5,31,6800},{3,31,1999},{3,26,33},{3,22,2124},{0,29,7068},{0,22,1836},{7,31,2195},{7,31,270},{7,26,69},{6,25,198},{15,0,5419},{2,31,1970},{3,26,24},{0,22,1611},{12,16,5419},{0,22,1611},{5,31,1676},{5,31,1676},{5,31,1676},{5,24,1580},{3,31,1233},{3,26,29},{3,26,29},{3,19,58},{0,24,1798},{0,19,157},{7,27,50},
+{7,27,50},{7,27,50},{7,22,49},{10,8,1152},{2,28,1},{2,28,1},{2,19,1},{11,12,1152},{2,19,1},{15,8,1568},{7,31,221},{7,26,20},{4,26,8},{15,8,1568},{11,22,1568},{4,26,8},{0,22,1586},{11,22,1568},{0,22,1586},{5,0,1576},{5,0,1576},{5,0,1576},{5,0,1576},{3,25,10},{3,25,10},{3,25,10},{3,18,13},{0,20,106},{0,20,106},{6,31,5828},{6,31,2435},{6,27,2175},
+{5,27,1669},{5,31,7184},{4,31,2132},{4,27,105},{3,23,2107},{0,31,6820},{0,23,1690},{8,31,2306},{7,31,334},{7,27,86},{7,26,181},{14,6,5419},{4,31,2096},{3,27,62},{0,23,1590},{15,14,5419},{0,23,1590},{6,31,1859},{6,31,1859},{6,31,1859},{5,26,1640},{4,31,1220},{4,26,97},{4,26,97},{4,19,136},{0,26,1650},{0,21,161},{7,30,1},{7,30,1},{7,30,1},{7,24,5},{9,14,1152},
+{3,28,5},{3,28,5},{2,20,2},{14,10,1152},{2,20,2},{14,14,1568},{7,31,333},{8,27,40},{4,27,5},{14,14,1568},{14,20,1568},{4,27,5},{0,23,1586},{14,20,1568},{0,23,1586},{5,0,1640},{5,0,1640},{5,0,1640},{5,0,1640},{4,24,37},{4,24,37},{4,24,37},{4,18,37},{0,22,58},{0,22,58},{7,31,6036},{6,31,2835},{6,29,2148},{6,27,1631},{6,31,7316},{4,31,2228},{4,28,31},
+{4,23,2138},{0,31,6884},{0,24,1613},{8,31,2402},{8,31,666},{8,28,269},{7,27,198},{13,12,5419},{4,31,2224},{4,28,27},{0,24,1577},{13,18,5419},{0,24,1577},{6,31,1811},{6,31,1811},{6,31,1811},{6,26,1590},{5,31,1356},{4,28,22},{4,28,22},{4,20,62},{0,28,1508},{1,21,137},{7,31,106},{7,31,106},{7,31,106},{7,25,82},{11,10,1152},{3,30,1},{3,30,1},{3,21,5},{5,23,1152},
+{3,21,5},{13,20,1568},{8,31,410},{8,28,13},{4,28,18},{13,20,1568},{13,23,1570},{4,28,18},{0,24,1576},{13,23,1570},{0,24,1576},{6,0,1586},{6,0,1586},{6,0,1586},{6,0,1586},{4,27,4},{4,27,4},{4,27,4},{4,19,8},{0,24,37},{0,24,37},{7,31,6740},{7,31,3135},{7,29,2180},{6,28,1644},{7,31,7676},{5,31,2448},{5,29,109},{4,25,2117},{1,31,7196},{0,25,1593},{9,31,2594},
+{8,31,698},{8,29,82},{8,28,345},{14,11,5419},{5,31,2412},{4,29,49},{1,25,1580},{15,17,5419},{1,25,1580},{7,31,1979},{7,31,1979},{7,31,1979},{6,28,1619},{5,31,1388},{5,28,86},{5,28,86},{5,21,121},{0,30,1416},{1,23,161},{8,30,64},{8,30,64},{8,30,64},{8,25,65},{12,9,1152},{4,30,2},{4,30,2},{3,22,2},{14,13,1152},{3,22,2},{15,16,1568},{9,31,530},{8,29,18},
+{5,29,9},{15,16,1568},{15,22,1568},{5,29,9},{0,25,1576},{15,22,1568},{0,25,1576},{6,0,1618},{6,0,1618},{6,0,1618},{6,0,1618},{5,26,37},{5,26,37},{5,26,37},{5,20,37},{0,25,17},{0,25,17},{8,31,6906},{7,31,3909},{7,31,2160},{7,29,1621},{7,31,8144},{6,31,2902},{5,30,33},{5,26,2124},{2,31,7661},{1,26,1615},{9,31,2945},{9,31,1025},{8,30,86},{8,29,181},{14,14,5419},
+{7,31,2694},{5,30,24},{1,26,1590},{14,20,5419},{1,26,1590},{7,31,2060},{7,31,2060},{7,31,2060},{7,28,1580},{6,31,1476},{5,30,29},{5,30,29},{5,23,58},{0,31,1324},{2,23,157},{8,31,37},{8,31,37},{8,31,37},{8,27,5},{15,2,1152},{5,30,20},{5,30,20},{4,23,1},{13,16,1152},{4,23,1},{15,19,1568},{10,31,637},{9,30,5},{6,30,8},{15,19,1568},{13,26,1568},{6,30,8},
+{0,26,1586},{13,26,1568},{0,26,1586},{7,0,1576},{7,0,1576},{7,0,1576},{7,0,1576},{5,29,10},{5,29,10},{5,29,10},{5,22,13},{0,28,10},{0,28,10},{8,31,7386},{8,31,4250},{8,31,2490},{7,31,1669},{8,31,8461},{6,31,3350},{6,31,105},{5,27,2107},{4,31,8004},{1,27,1611},{10,31,3112},{9,31,1361},{9,31,69},{8,30,198},{13,20,5419},{7,31,2950},{5,31,62},{2,27,1590},{11,25,5420},
+{2,27,1590},{8,31,2486},{8,31,2486},{8,31,2486},{7,30,1640},{6,31,1700},{6,30,97},{6,30,97},{6,23,136},{1,31,1424},{2,25,161},{9,31,65},{9,31,65},{9,31,65},{9,27,49},{11,18,1152},{5,31,58},{5,31,58},{4,24,2},{10,21,1152},{4,24,2},{13,28,1568},{11,31,785},{9,31,20},{6,31,5},{13,28,1568},{11,30,1568},{6,31,5},{0,27,1586},{11,30,1568},{0,27,1586},{7,0,1640},
+{7,0,1640},{7,0,1640},{7,0,1640},{6,28,37},{6,28,37},{6,28,37},{6,22,37},{1,28,10},{1,28,10},{9,31,7014},{8,31,4230},{8,31,2294},{8,31,1846},{8,31,7865},{7,31,3114},{6,31,85},{6,27,1706},{4,31,7436},{2,28,1289},{11,31,2852},{10,31,1221},{9,31,145},{9,30,114},{13,22,4803},{8,31,2648},{6,31,81},{2,28,1253},{12,25,4803},{2,28,1253},{8,31,2294},{8,31,2294},{8,31,2294},
+{8,30,1811},{7,31,1740},{6,31,85},{6,31,85},{6,24,62},{2,31,1577},{3,25,137},{9,31,145},{9,31,145},{9,31,145},{9,29,5},{13,14,1152},{6,31,81},{6,31,81},{5,25,5},{8,25,1152},{5,25,5},{15,23,1250},{11,31,689},{10,31,4},{7,31,9},{15,23,1250},{11,31,1250},{7,31,9},{0,28,1252},{11,31,1250},{0,28,1252},{8,0,1810},{8,0,1810},{8,0,1810},{8,0,1810},{6,31,4},
+{6,31,4},{6,31,4},{6,23,8},{1,29,8},{1,29,8},{9,31,6534},{9,31,4134},{8,31,2486},{8,31,1590},{9,31,7237},{7,31,2970},{7,31,161},{6,28,1256},{5,31,6748},{2,29,949},{11,31,2340},{10,31,1125},{10,31,164},{9,31,97},{15,17,4056},{9,31,2244},{7,31,125},{3,28,909},{12,26,4056},{3,28,909},{8,31,2486},{8,31,2486},{8,31,2486},{8,31,1590},{7,31,2156},{7,31,161},{7,31,161},
+{7,25,121},{3,31,1729},{3,27,161},{10,31,164},{10,31,164},{10,31,164},{10,29,65},{14,13,1152},{7,31,125},{7,31,125},{5,26,2},{11,23,1152},{5,26,2},{13,31,882},{12,31,482},{11,31,0},{8,31,4},{13,31,882},{15,27,882},{8,31,4},{0,28,900},{15,27,882},{0,28,900},{8,0,1586},{8,0,1586},{8,0,1586},{8,0,1586},{7,30,37},{7,30,37},{7,30,37},{7,24,37},{1,31,16},
+{1,31,16},{10,31,6091},{9,31,4053},{9,31,2609},{8,31,1761},{9,31,6490},{8,31,2622},{7,31,458},{7,28,835},{6,31,6162},{3,29,598},{12,31,1989},{11,31,931},{11,31,306},{10,31,5},{15,19,3318},{10,31,1806},{8,31,202},{4,29,545},{13,26,3318},{4,29,545},{9,31,2609},{9,31,2609},{9,31,2609},{8,31,1761},{8,31,2086},{7,31,458},{7,31,458},{7,27,58},{4,31,1868},{4,27,157},{11,31,306},
+{11,31,306},{11,31,306},{10,31,5},{14,16,1152},{8,31,202},{8,31,202},{6,27,1},{15,20,1152},{6,27,1},{15,26,545},{13,31,313},{12,31,4},{10,31,4},{15,26,545},{14,29,545},{10,31,4},{0,29,545},{14,29,545},{0,29,545},{8,0,1640},{8,0,1640},{8,0,1640},{8,0,1640},{7,31,58},{7,31,58},{7,31,58},{7,26,13},{2,31,13},{2,31,13},{10,31,5723},{10,31,3980},{9,31,2945},
+{9,31,1745},{10,31,6083},{8,31,2494},{8,31,558},{7,29,558},{7,31,5674},{4,30,411},{12,31,1573},{11,31,963},{11,31,338},{11,31,49},{13,27,2753},{10,31,1438},{9,31,290},{5,29,341},{13,27,2753},{5,29,341},{9,31,2945},{9,31,2945},{9,31,2945},{9,31,1745},{9,31,2390},{8,31,558},{8,31,558},{7,28,147},{5,31,2064},{4,29,161},{11,31,338},{11,31,338},{11,31,338},{11,31,49},{13,22,1152},
+{9,31,290},{9,31,290},{6,28,2},{12,25,1152},{6,28,2},{15,27,313},{13,31,185},{13,31,16},{11,31,0},{15,27,313},{13,31,313},{11,31,0},{0,29,337},{13,31,313},{0,29,337},{9,0,1576},{9,0,1576},{9,0,1576},{9,0,1576},{8,31,197},{8,31,197},{8,31,197},{7,27,122},{3,31,25},{3,31,25},{11,31,5415},{10,31,3996},{10,31,3035},{10,31,2006},{10,31,5619},{9,31,2378},{8,31,814},
+{8,29,414},{7,31,5338},{5,30,251},{12,31,1413},{12,31,813},{12,31,452},{11,31,65},{13,29,2273},{11,31,1218},{10,31,365},{6,30,146},{14,27,2273},{6,30,146},{10,31,3035},{10,31,3035},{10,31,3035},{10,31,2006},{9,31,2518},{8,31,814},{8,31,814},{8,28,121},{6,31,2329},{5,29,137},{12,31,452},{12,31,452},{12,31,452},{11,31,65},{15,18,1152},{10,31,365},{10,31,365},{7,29,5},{10,29,1152},
+{7,29,5},{15,28,145},{14,31,85},{13,31,16},{12,31,4},{15,28,145},{15,29,149},{12,31,4},{0,30,145},{15,29,149},{0,30,145},{9,0,1640},{9,0,1640},{9,0,1640},{9,0,1640},{8,31,85},{8,31,85},{8,31,85},{8,27,37},{4,31,40},{4,31,40},{11,31,5143},{11,31,4004},{11,31,3379},{10,31,2070},{11,31,5287},{10,31,2431},{9,31,1062},{8,30,133},{8,31,5011},{5,31,161},{13,31,1161},
+{13,31,889},{12,31,548},{12,31,164},{15,24,1878},{11,31,1106},{11,31,481},{7,30,66},{15,27,1881},{7,30,66},{11,31,3379},{11,31,3379},{11,31,3379},{10,31,2070},{10,31,2835},{9,31,1062},{9,31,1062},{8,29,62},{7,31,2577},{5,31,161},{12,31,548},{12,31,548},{12,31,548},{12,31,164},{13,27,1152},{11,31,481},{11,31,481},{7,30,2},{13,27,1152},{7,30,2},{15,29,45},{14,31,37},{14,31,1},
+{14,31,9},{15,29,45},{15,30,41},{14,31,9},{0,30,65},{15,30,41},{0,30,65},{10,0,1586},{10,0,1586},{10,0,1586},{10,0,1586},{9,31,221},{9,31,221},{9,31,221},{8,28,8},{5,31,80},{5,31,80},{12,31,4948},{11,31,4157},{11,31,3532},{11,31,2393},{11,31,5008},{10,31,2422},{10,31,1461},{9,31,125},{9,31,4752},{6,31,157},{13,31,1107},{13,31,835},{13,31,666},{12,31,362},{15,26,1536},
+{12,31,1011},{12,31,650},{8,31,16},{14,29,1536},{8,31,16},{11,31,3532},{11,31,3532},{11,31,3532},{11,31,2393},{10,31,3204},{10,31,1461},{10,31,1461},{9,30,114},{8,31,2976},{6,31,157},{13,31,666},{13,31,666},{13,31,666},{12,31,362},{13,30,1152},{12,31,650},{12,31,650},{8,31,16},{12,30,1152},{8,31,16},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},
+{0,31,0},{15,31,0},{0,31,0},{10,0,1640},{10,0,1640},{10,0,1640},{10,0,1640},{9,31,221},{9,31,221},{9,31,221},{9,29,25},{6,31,157},{6,31,157},{12,31,4212},{12,31,3612},{12,31,3251},{11,31,2201},{12,31,4212},{11,31,2154},{10,31,1301},{9,31,13},{10,31,3939},{7,31,233},{14,31,776},{13,31,659},{13,31,490},{13,31,218},{15,27,1067},{13,31,699},{12,31,442},{9,31,4},{13,31,1067},
+{9,31,4},{12,31,3251},{12,31,3251},{12,31,3251},{11,31,2201},{11,31,2668},{10,31,1301},{10,31,1301},{9,31,13},{8,31,2528},{7,31,233},{13,31,490},{13,31,490},{13,31,490},{13,31,218},{15,25,802},{12,31,442},{12,31,442},{9,31,4},{15,27,802},{9,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{11,0,1576},
+{11,0,1576},{11,0,1576},{11,0,1576},{10,31,340},{10,31,340},{10,31,340},{9,31,13},{7,31,233},{7,31,233},{12,31,3732},{12,31,3132},{12,31,2771},{12,31,2171},{12,31,3444},{11,31,1834},{11,31,1209},{10,31,37},{10,31,3219},{8,31,400},{14,31,456},{14,31,392},{14,31,356},{13,31,170},{14,31,684},{13,31,459},{13,31,290},{10,31,1},{14,30,683},{10,31,1},{12,31,2771},{12,31,2771},{12,31,2771},
+{12,31,2171},{11,31,2348},{11,31,1209},{11,31,1209},{10,31,37},{9,31,2156},{8,31,400},{14,31,356},{14,31,356},{14,31,356},{13,31,170},{15,26,512},{13,31,290},{13,31,290},{10,31,1},{14,29,512},{10,31,1},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{11,0,1640},{11,0,1640},{11,0,1640},{11,0,1640},{10,31,436},
+{10,31,436},{10,31,436},{10,31,37},{8,31,400},{8,31,400},{13,31,3172},{13,31,2900},{12,31,2547},{12,31,1947},{12,31,2932},{12,31,1732},{11,31,1145},{10,31,53},{11,31,2695},{8,31,464},{14,31,264},{14,31,200},{14,31,164},{14,31,100},{15,28,387},{14,31,268},{13,31,178},{11,31,1},{15,29,396},{11,31,1},{12,31,2547},{12,31,2547},{12,31,2547},{12,31,1947},{12,31,1971},{11,31,1145},{11,31,1145},
+{10,31,53},{10,31,1794},{8,31,464},{14,31,164},{14,31,164},{14,31,164},{14,31,100},{15,27,290},{13,31,178},{13,31,178},{11,31,1},{14,30,290},{11,31,1},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{12,0,1586},{12,0,1586},{12,0,1586},{12,0,1586},{11,31,520},{11,31,520},{11,31,520},{10,31,53},{8,31,464},
+{8,31,464},{0,23,2665},{0,18,680},{0,13,50},{0,11,785},{0,15,5885},{0,11,4118},{0,10,1800},{0,7,4202},{0,8,6546},{0,7,4643},{0,23,2665},{0,18,680},{0,13,50},{0,11,785},{3,5,5885},{0,11,4118},{0,10,1800},{0,7,4202},{0,9,5885},{0,7,4202},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,549},{0,5,289},{0,5,289},{0,3,306},{0,3,630},{0,3,387},{0,11,0},
+{0,11,0},{0,11,0},{0,7,4},{1,2,545},{0,5,289},{0,5,289},{0,3,306},{2,1,545},{0,3,306},{6,3,2665},{0,18,680},{0,13,50},{0,11,785},{6,3,2665},{11,0,2665},{0,11,785},{0,8,2689},{11,0,2665},{0,8,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,2665},{0,20,521},{0,14,5},
+{0,12,625},{0,17,6669},{0,13,4529},{0,11,1890},{0,8,4610},{0,9,7494},{0,7,5171},{0,25,2665},{0,20,521},{0,14,5},{0,12,625},{3,7,6669},{0,13,4529},{0,11,1890},{0,8,4610},{8,0,6669},{0,8,4610},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{0,7,841},{0,6,445},{0,6,445},{0,4,464},{0,3,982},{0,3,595},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{2,0,841},
+{0,6,445},{0,6,445},{0,4,464},{1,3,841},{0,4,464},{7,2,2665},{0,20,521},{0,14,5},{0,12,625},{7,2,2665},{12,0,2665},{0,12,625},{0,9,2689},{12,0,2665},{0,9,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,28,2665},{0,22,405},{0,15,10},{0,13,514},{0,19,7541},{0,14,4934},{0,12,2042},
+{0,9,5045},{0,10,8546},{0,8,5682},{0,28,2665},{0,22,405},{0,15,10},{0,13,514},{5,2,7538},{0,14,4934},{0,12,2042},{0,9,5045},{8,1,7538},{0,9,5045},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{0,8,1201},{0,7,637},{0,7,637},{0,4,656},{0,4,1385},{0,4,800},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{1,5,1201},{0,7,637},{0,7,637},{0,4,656},{4,0,1201},
+{0,4,656},{6,8,2665},{0,22,405},{0,15,10},{0,13,514},{6,8,2665},{11,3,2665},{0,13,514},{0,10,2689},{11,3,2665},{0,10,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,30,2669},{0,23,313},{0,16,68},{0,15,410},{0,20,8498},{0,16,5330},{0,13,2210},{0,10,5530},{0,11,9702},{0,9,6270},{0,30,2669},
+{0,23,313},{0,16,68},{0,15,410},{4,7,8493},{0,16,5330},{0,13,2210},{0,10,5530},{8,2,8493},{0,10,5530},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{0,9,1629},{0,8,832},{0,8,832},{0,5,881},{0,5,1874},{0,5,1106},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{2,3,1625},{0,8,832},{0,8,832},{0,5,881},{4,1,1625},{0,5,881},{8,2,2665},{0,23,313},{1,16,8},
+{0,15,410},{8,2,2665},{14,1,2665},{0,15,410},{0,11,2689},{14,1,2665},{0,11,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,2777},{0,26,232},{0,17,197},{0,16,305},{0,22,9674},{0,17,5849},{0,14,2450},{0,10,6106},{0,12,11199},{0,10,7006},{0,31,2777},{0,26,232},{0,17,197},{0,16,305},{1,19,9669},
+{0,17,5849},{0,14,2450},{0,10,6106},{9,2,9669},{0,10,6106},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{0,11,2178},{0,10,1125},{0,10,1125},{0,6,1189},{0,6,2520},{0,5,1475},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{3,1,2178},{0,10,1125},{0,10,1125},{0,6,1189},{3,3,2178},{0,6,1189},{9,2,2665},{0,26,232},{1,17,17},{0,16,305},{9,2,2665},{13,4,2665},{0,16,305},
+{0,12,2689},{13,4,2665},{0,12,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,31,3045},{0,28,217},{0,19,401},{0,17,282},{0,25,9670},{0,19,5529},{0,16,1970},{0,12,5738},{0,13,11589},{0,11,6898},{1,31,2789},{0,28,217},{1,18,146},{0,17,282},{5,8,9669},{0,19,5529},{0,16,1970},{0,12,5738},{4,10,9669},
+{0,12,5738},{0,24,64},{0,24,64},{0,24,64},{0,15,68},{0,13,2180},{0,11,949},{0,11,949},{0,7,1018},{0,7,2691},{0,6,1433},{1,21,64},{1,21,64},{1,21,64},{1,13,68},{4,0,2178},{0,11,949},{0,11,949},{0,7,1018},{1,7,2178},{0,7,1018},{10,1,2665},{0,28,153},{2,18,5},{0,17,218},{10,1,2665},{15,3,2665},{0,17,218},{0,13,2689},{15,3,2665},{0,13,2689},{0,0,64},
+{0,0,64},{0,0,64},{0,0,64},{0,3,1},{0,3,1},{0,3,1},{0,2,4},{0,1,18},{0,1,18},{1,31,3285},{0,29,341},{1,19,453},{0,18,405},{0,27,9674},{0,20,5170},{0,17,1546},{0,13,5429},{0,15,11993},{0,12,6819},{2,31,2966},{1,28,221},{1,19,197},{1,18,305},{7,4,9669},{0,20,5170},{0,17,1546},{0,13,5429},{9,5,9669},{0,13,5429},{0,27,257},{0,27,257},{0,27,257},
+{1,15,256},{0,16,2178},{0,13,832},{0,13,832},{0,8,881},{0,8,2882},{0,7,1427},{1,23,4},{1,23,4},{1,23,4},{1,15,0},{3,6,2178},{0,13,832},{0,13,832},{0,8,881},{3,6,2178},{0,8,881},{11,0,2665},{0,29,85},{2,19,10},{0,18,149},{11,0,2665},{13,7,2665},{0,18,149},{0,14,2689},{13,7,2665},{0,14,2689},{0,0,256},{0,0,256},{0,0,256},{0,0,256},{0,5,1},
+{0,5,1},{0,5,1},{0,3,1},{0,2,72},{0,2,72},{1,31,3909},{1,29,465},{1,21,676},{1,19,538},{0,30,9669},{0,22,4878},{0,18,1190},{0,14,5138},{0,16,12390},{0,13,6789},{2,31,2966},{1,29,209},{2,20,149},{1,19,282},{6,10,9669},{0,22,4878},{0,18,1190},{0,14,5138},{12,3,9669},{0,14,5138},{1,26,320},{1,26,320},{1,26,320},{1,16,324},{0,19,2180},{0,15,680},{0,15,680},
+{0,9,740},{0,9,3149},{0,8,1441},{1,26,64},{1,26,64},{1,26,64},{1,16,68},{5,2,2178},{0,15,680},{0,15,680},{0,9,740},{8,1,2178},{0,9,740},{11,3,2665},{0,31,41},{3,20,8},{0,19,98},{11,3,2665},{15,6,2665},{0,19,98},{0,15,2689},{15,6,2665},{0,15,2689},{1,0,320},{1,0,320},{1,0,320},{1,0,320},{0,8,0},{0,8,0},{0,8,0},{0,5,1},{0,4,160},
+{0,4,160},{2,31,4514},{1,31,630},{1,22,1110},{1,20,694},{0,31,9789},{0,23,4646},{0,20,849},{0,15,4826},{0,18,12955},{0,14,6798},{3,31,3101},{2,30,232},{2,21,197},{2,20,305},{3,23,9669},{0,23,4646},{0,20,849},{0,15,4826},{11,6,9669},{0,15,4826},{1,29,545},{1,29,545},{1,29,545},{1,18,546},{0,22,2180},{0,17,505},{0,17,505},{0,11,610},{0,11,3467},{0,10,1513},{2,26,1},
+{2,26,1},{2,26,1},{2,17,0},{5,5,2178},{0,17,505},{0,17,505},{0,11,610},{5,7,2178},{0,11,610},{11,6,2665},{1,31,85},{3,21,17},{0,20,65},{11,6,2665},{15,8,2665},{0,20,65},{0,16,2689},{15,8,2665},{0,16,2689},{1,0,545},{1,0,545},{1,0,545},{1,0,545},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,289},{0,5,289},{2,31,5330},{1,31,1110},{2,23,1490},
+{1,21,979},{1,31,9981},{0,26,4406},{0,21,579},{0,16,4610},{0,19,13489},{0,15,6846},{3,31,3341},{2,31,226},{3,22,146},{2,21,282},{9,4,9669},{0,26,4406},{0,21,579},{0,16,4610},{9,10,9669},{0,16,4610},{1,31,885},{1,31,885},{1,31,885},{1,20,885},{0,24,2178},{0,19,389},{0,19,389},{0,12,464},{0,12,3885},{0,11,1603},{3,25,64},{3,25,64},{3,25,64},{3,17,68},{7,1,2178},
+{0,19,389},{0,19,389},{0,12,464},{10,2,2178},{0,12,464},{13,2,2665},{2,31,162},{4,22,5},{0,22,37},{13,2,2665},{12,13,2665},{0,22,37},{0,17,2689},{12,13,2665},{0,17,2689},{1,0,881},{1,0,881},{1,0,881},{1,0,881},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{0,6,445},{0,6,445},{3,31,6366},{2,31,1635},{2,24,1886},{1,22,1410},{1,31,10381},{0,28,4146},{0,22,377},
+{0,17,4373},{0,20,14006},{0,16,6915},{4,31,3434},{3,31,242},{3,23,197},{3,22,305},{10,3,9669},{0,28,4146},{0,22,377},{0,17,4373},{11,9,9669},{0,17,4373},{2,31,1346},{2,31,1346},{2,31,1346},{2,20,1345},{0,27,2180},{0,21,274},{0,21,274},{0,13,353},{0,14,4269},{0,11,1763},{3,27,4},{3,27,4},{3,27,4},{3,19,0},{5,10,2178},{0,21,274},{0,21,274},{0,13,353},{12,1,2178},
+{0,13,353},{14,1,2665},{3,31,242},{4,23,10},{0,23,10},{14,1,2665},{15,11,2665},{0,23,10},{0,18,2689},{15,11,2665},{0,18,2689},{1,0,1345},{1,0,1345},{1,0,1345},{1,0,1345},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{0,7,637},{0,7,637},{3,31,7374},{2,31,2339},{2,25,2441},{2,23,1763},{2,31,11019},{0,29,3909},{0,23,243},{0,18,4154},{0,22,14614},{0,17,7029},{5,31,3654},
+{4,31,394},{4,24,149},{3,23,282},{9,9,9669},{0,29,3909},{0,23,243},{0,18,4154},{14,7,9669},{0,18,4154},{2,31,1714},{2,31,1714},{2,31,1714},{2,22,1669},{0,29,2180},{0,23,194},{0,23,194},{0,14,260},{0,15,4686},{0,13,1937},{3,30,64},{3,30,64},{3,30,64},{3,20,68},{8,1,2178},{0,23,194},{0,23,194},{0,14,260},{10,5,2178},{0,14,260},{15,0,2665},{4,31,313},{5,24,8},
+{0,24,4},{15,0,2665},{13,15,2665},{0,24,4},{0,19,2689},{13,15,2665},{0,19,2689},{2,0,1665},{2,0,1665},{2,0,1665},{2,0,1665},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{0,8,832},{0,8,832},{3,31,8967},{3,31,3510},{3,26,3255},{2,24,2243},{2,31,11766},{0,31,3686},{0,25,138},{0,19,3938},{0,23,15369},{0,18,7206},{5,31,3933},{4,31,457},{4,25,197},{4,24,305},{12,2,9669},
+{0,31,3686},{0,25,138},{0,19,3938},{13,10,9669},{0,19,3938},{2,31,2434},{2,31,2434},{2,31,2434},{2,23,2182},{0,31,2210},{0,25,137},{0,25,137},{0,15,181},{0,16,5157},{0,14,2163},{4,30,1},{4,30,1},{4,30,1},{4,21,0},{8,4,2178},{0,25,137},{0,25,137},{0,15,181},{14,2,2178},{0,15,181},{15,3,2665},{5,31,421},{5,25,17},{1,25,5},{15,3,2665},{12,18,2665},{1,25,5},
+{0,20,2689},{12,18,2665},{0,20,2689},{2,0,2178},{2,0,2178},{2,0,2178},{2,0,2178},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{0,10,1125},{0,10,1125},{4,31,10234},{3,31,4421},{3,27,3739},{2,26,2742},{2,31,12773},{0,31,3719},{0,26,87},{0,20,3771},{0,25,16061},{0,19,7283},{6,31,4050},{5,31,629},{5,26,146},{4,25,282},{11,8,9669},{0,31,3718},{0,26,86},{0,20,3770},{11,14,9669},
+{0,20,3770},{3,31,3125},{3,31,3125},{3,31,3125},{2,25,2706},{1,31,2411},{0,26,86},{0,26,86},{0,16,129},{0,18,5544},{0,15,2318},{5,29,64},{5,29,64},{5,29,64},{5,21,68},{3,25,2178},{0,26,85},{0,26,85},{0,16,128},{12,6,2178},{0,16,128},{15,6,2665},{5,31,565},{6,26,5},{1,26,2},{15,6,2665},{14,17,2665},{1,26,2},{0,21,2689},{14,17,2665},{0,21,2689},{2,0,2705},
+{2,0,2705},{2,0,2705},{2,0,2705},{0,24,1},{0,24,1},{0,24,1},{0,15,5},{0,11,1348},{0,11,1348},{4,31,10874},{4,31,5018},{3,28,3750},{3,26,2754},{3,31,13045},{1,31,4003},{0,27,183},{0,21,3686},{0,27,15601},{0,20,6570},{7,31,4366},{5,31,965},{5,27,197},{5,26,305},{12,7,9669},{1,31,3954},{0,27,102},{0,21,3605},{13,13,9669},{0,21,3605},{3,31,3173},{3,31,3173},{3,31,3173},
+{3,25,2690},{1,31,2427},{0,28,113},{0,28,113},{0,17,170},{0,20,5170},{0,16,1856},{5,31,4},{5,31,4},{5,31,4},{5,23,0},{9,6,2178},{0,28,32},{0,28,32},{0,17,89},{14,5,2178},{0,17,89},{15,8,2665},{6,31,706},{6,27,10},{2,27,10},{15,8,2665},{12,21,2665},{2,27,10},{0,22,2689},{12,21,2665},{0,22,2689},{3,0,2689},{3,0,2689},{3,0,2689},{3,0,2689},{1,23,53},
+{1,23,53},{1,23,53},{1,15,49},{0,13,1217},{0,13,1217},{5,31,11278},{4,31,5402},{4,29,3753},{3,28,2745},{4,31,13566},{1,31,4403},{1,28,77},{0,22,3747},{0,28,15046},{0,21,5958},{7,31,4590},{6,31,1171},{6,28,149},{5,27,282},{14,3,9669},{2,31,4265},{1,28,76},{0,22,3458},{11,17,9669},{0,22,3458},{4,31,3377},{4,31,3377},{4,31,3377},{3,27,2706},{2,31,2532},{1,28,73},{1,28,73},
+{1,18,129},{0,21,4837},{0,17,1490},{6,31,82},{6,31,82},{6,31,82},{5,24,68},{10,5,2178},{0,30,8},{0,30,8},{0,19,49},{12,9,2178},{0,19,49},{15,11,2665},{7,31,850},{7,28,8},{2,28,4},{15,11,2665},{15,19,2665},{2,28,4},{0,23,2689},{15,19,2665},{0,23,2689},{3,0,2705},{3,0,2705},{3,0,2705},{3,0,2705},{1,26,1},{1,26,1},{1,26,1},{1,16,5},{0,14,1037},
+{0,14,1037},{6,31,11954},{5,31,6090},{4,30,3794},{4,28,2754},{5,31,14170},{2,31,4863},{2,29,187},{1,24,3689},{0,30,14558},{0,23,5274},{8,31,5030},{7,31,1556},{6,29,197},{6,28,305},{14,6,9669},{3,31,4594},{1,29,101},{0,24,3265},{15,14,9669},{0,24,3265},{4,31,3530},{4,31,3530},{4,31,3530},{4,27,2693},{2,31,2739},{1,30,134},{1,30,134},{1,19,197},{0,23,4506},{0,19,1109},{6,31,64},
+{6,31,64},{6,31,64},{6,25,0},{10,8,2178},{1,30,34},{1,30,34},{0,20,16},{11,12,2178},{0,20,16},{15,14,2665},{8,31,1053},{7,29,17},{3,29,5},{15,14,2665},{14,22,2665},{3,29,5},{0,24,2689},{14,22,2665},{0,24,2689},{4,0,2689},{4,0,2689},{4,0,2689},{4,0,2689},{2,26,50},{2,26,50},{2,26,50},{2,17,49},{0,16,818},{0,16,818},{6,31,12466},{5,31,6794},{5,31,3739},
+{4,30,2742},{5,31,14554},{3,31,5363},{2,30,87},{1,24,3737},{0,31,14190},{0,24,4785},{8,31,5158},{7,31,2036},{7,30,146},{6,29,282},{13,12,9669},{4,31,4806},{2,30,86},{0,25,3130},{13,18,9669},{0,25,3130},{5,31,3658},{5,31,3658},{5,31,3658},{4,29,2706},{3,31,2795},{2,30,86},{2,30,86},{2,20,129},{0,25,4315},{0,20,809},{7,31,100},{7,31,100},{7,31,100},{7,25,68},{9,14,2178},
+{1,31,68},{1,31,68},{0,21,1},{14,10,2178},{0,21,1},{13,23,2665},{9,31,1241},{8,30,50},{3,30,2},{13,23,2665},{11,27,2665},{3,30,2},{0,25,2689},{11,27,2665},{0,25,2689},{4,0,2705},{4,0,2705},{4,0,2705},{4,0,2705},{2,28,1},{2,28,1},{2,28,1},{2,19,5},{0,18,666},{0,18,666},{7,31,13094},{6,31,7445},{5,31,3915},{5,30,2754},{6,31,14998},{4,31,5926},{2,31,183},
+{2,25,3686},{0,31,14254},{0,25,4323},{9,31,5546},{8,31,2478},{7,31,197},{7,30,305},{14,11,9669},{5,31,5138},{2,31,102},{0,26,3013},{15,17,9669},{0,26,3013},{5,31,3914},{5,31,3914},{5,31,3914},{5,29,2690},{4,31,3042},{2,31,182},{2,31,182},{2,21,170},{0,27,4059},{0,21,597},{7,31,196},{7,31,196},{7,31,196},{7,27,0},{11,10,2178},{2,31,101},{2,31,101},{0,22,4},{5,23,2178},
+{0,22,4},{15,19,2665},{10,31,1384},{8,31,5},{4,31,10},{15,19,2665},{14,25,2665},{4,31,10},{0,26,2689},{14,25,2665},{0,26,2689},{5,0,2689},{5,0,2689},{5,0,2689},{5,0,2689},{3,27,53},{3,27,53},{3,27,53},{3,19,49},{0,20,505},{0,20,505},{7,31,12517},{6,31,7482},{6,31,4001},{5,31,2706},{6,31,14185},{4,31,5491},{3,31,154},{2,26,3124},{0,31,13437},{0,26,3306},{9,31,4949},
+{8,31,2261},{8,31,325},{7,30,192},{14,13,8712},{6,31,4686},{3,31,153},{0,27,2403},{11,23,8712},{0,27,2403},{6,31,4001},{6,31,4001},{6,31,4001},{5,31,2706},{4,31,3234},{3,31,154},{3,31,154},{3,22,129},{0,28,3762},{0,23,425},{8,31,325},{8,31,325},{8,31,325},{7,28,68},{12,9,2178},{3,31,153},{3,31,153},{1,23,1},{14,13,2178},{1,23,1},{13,27,2178},{10,31,1157},{9,31,16},
+{5,31,1},{13,27,2178},{13,27,2178},{5,31,1},{0,27,2178},{13,27,2178},{0,27,2178},{5,0,2705},{5,0,2705},{5,0,2705},{5,0,2705},{3,30,1},{3,30,1},{3,30,1},{3,20,5},{0,22,389},{0,22,389},{8,31,12034},{7,31,7195},{6,31,4370},{6,31,2693},{7,31,13066},{5,31,5014},{4,31,261},{3,27,2390},{1,31,12394},{0,27,2277},{10,31,4410},{9,31,2045},{8,31,289},{8,30,192},{14,15,7578},
+{7,31,4050},{4,31,212},{0,27,1701},{12,23,7578},{0,27,1701},{6,31,4370},{6,31,4370},{6,31,4370},{6,31,2693},{5,31,3429},{4,31,261},{4,31,261},{3,23,197},{0,30,3509},{0,24,306},{8,31,289},{8,31,289},{8,31,289},{8,28,68},{15,2,2178},{4,31,212},{4,31,212},{1,24,9},{13,16,2178},{1,24,9},{15,22,1625},{11,31,850},{9,31,25},{6,31,4},{15,22,1625},{13,28,1625},{6,31,4},
+{0,27,1665},{13,28,1625},{0,27,1665},{6,0,2689},{6,0,2689},{6,0,2689},{6,0,2689},{4,30,50},{4,30,50},{4,30,50},{4,21,49},{0,24,306},{0,24,306},{8,31,11042},{7,31,7259},{7,31,4450},{6,31,2805},{7,31,12298},{5,31,4742},{4,31,501},{4,27,1875},{2,31,11643},{0,28,1578},{10,31,3802},{9,31,1869},{9,31,425},{8,31,25},{13,20,6661},{7,31,3554},{5,31,292},{0,28,1217},{13,23,6662},
+{0,28,1217},{7,31,4450},{7,31,4450},{7,31,4450},{6,31,2805},{6,31,3714},{4,31,501},{4,31,501},{4,24,129},{0,31,3354},{0,25,244},{9,31,425},{9,31,425},{9,31,425},{8,30,0},{11,18,2178},{5,31,292},{5,31,292},{2,25,1},{10,21,2178},{2,25,1},{15,23,1201},{11,31,674},{10,31,9},{7,31,16},{15,23,1201},{12,30,1201},{7,31,16},{0,28,1201},{12,30,1201},{0,28,1201},{6,0,2705},
+{6,0,2705},{6,0,2705},{6,0,2705},{4,31,17},{4,31,17},{4,31,17},{4,23,5},{0,26,218},{0,26,218},{8,31,10434},{8,31,7186},{7,31,4898},{7,31,2833},{8,31,11595},{6,31,4462},{5,31,629},{4,28,1387},{3,31,10895},{0,28,1002},{11,31,3446},{10,31,1707},{9,31,505},{8,31,73},{13,22,5829},{8,31,3170},{6,31,405},{1,28,869},{12,25,5829},{1,28,869},{7,31,4898},{7,31,4898},{7,31,4898},
+{7,31,2833},{6,31,3906},{5,31,629},{5,31,629},{4,25,170},{0,31,3546},{0,27,228},{9,31,505},{9,31,505},{9,31,505},{9,30,68},{13,14,2178},{6,31,405},{6,31,405},{2,26,4},{8,25,2178},{2,26,4},{13,31,841},{12,31,461},{11,31,1},{8,31,9},{13,31,841},{15,27,841},{8,31,9},{0,28,865},{15,27,841},{0,28,865},{7,0,2689},{7,0,2689},{7,0,2689},{7,0,2689},{5,31,53},
+{5,31,53},{5,31,53},{5,23,49},{0,28,137},{0,28,137},{9,31,10014},{8,31,6962},{8,31,5026},{7,31,3105},{8,31,10683},{7,31,4354},{6,31,933},{5,28,1019},{4,31,10078},{0,29,630},{11,31,2934},{10,31,1611},{10,31,650},{9,31,25},{15,17,5082},{8,31,2786},{7,31,521},{1,29,546},{12,26,5082},{1,29,546},{8,31,5026},{8,31,5026},{8,31,5026},{7,31,3105},{7,31,4170},{6,31,933},{6,31,933},
+{5,26,129},{1,31,3814},{0,28,234},{10,31,650},{10,31,650},{10,31,650},{9,31,25},{14,13,2178},{7,31,521},{7,31,521},{3,27,1},{11,23,2178},{3,27,1},{15,26,545},{13,31,313},{12,31,4},{10,31,4},{15,26,545},{14,29,545},{10,31,4},{0,29,545},{14,29,545},{0,29,545},{7,0,2705},{7,0,2705},{7,0,2705},{7,0,2705},{5,31,101},{5,31,101},{5,31,101},{5,24,5},{0,29,85},
+{0,29,85},{9,31,9465},{9,31,7065},{8,31,5233},{8,31,3329},{8,31,10116},{7,31,4183},{6,31,1338},{5,29,645},{5,31,9447},{0,30,441},{11,31,2664},{11,31,1525},{10,31,848},{10,31,113},{15,19,4344},{9,31,2424},{8,31,724},{2,30,321},{13,26,4344},{2,30,321},{8,31,5233},{8,31,5233},{8,31,5233},{8,31,3329},{7,31,4629},{6,31,1338},{6,31,1338},{5,27,197},{2,31,4212},{1,29,213},{10,31,848},
+{10,31,848},{10,31,848},{10,31,113},{14,16,2178},{8,31,724},{8,31,724},{3,28,9},{15,20,2178},{3,28,9},{15,27,290},{13,31,178},{13,31,9},{11,31,1},{15,27,290},{14,30,290},{11,31,1},{0,29,320},{14,30,290},{0,29,320},{8,0,2929},{8,0,2929},{8,0,2929},{8,0,2929},{6,31,113},{6,31,113},{6,31,113},{6,25,49},{0,31,45},{0,31,45},{10,31,9329},{9,31,6985},{9,31,5541},
+{8,31,3473},{9,31,9496},{8,31,4420},{7,31,1630},{6,29,426},{5,31,9031},{1,30,301},{12,31,2275},{11,31,1557},{11,31,932},{10,31,225},{13,27,3779},{10,31,2086},{8,31,884},{3,30,129},{13,27,3779},{3,30,129},{9,31,5541},{9,31,5541},{9,31,5541},{8,31,3473},{8,31,4836},{7,31,1630},{7,31,1630},{6,28,129},{4,31,4442},{1,30,237},{11,31,932},{11,31,932},{11,31,932},{10,31,225},{13,22,2178},
+{8,31,884},{8,31,884},{4,29,1},{12,25,2178},{4,29,1},{15,28,130},{14,31,72},{13,31,25},{12,31,9},{15,28,130},{15,29,136},{12,31,9},{0,30,128},{15,29,136},{0,30,128},{8,0,2689},{8,0,2689},{8,0,2689},{8,0,2689},{6,31,257},{6,31,257},{6,31,257},{6,27,5},{1,31,89},{1,31,89},{10,31,8929},{10,31,7186},{9,31,5845},{9,31,3829},{9,31,9208},{8,31,4260},{7,31,2270},
+{6,30,245},{6,31,8708},{2,31,228},{12,31,2115},{12,31,1515},{12,31,1154},{11,31,353},{13,29,3299},{11,31,1938},{10,31,1013},{4,30,68},{14,27,3299},{4,30,68},{9,31,5845},{9,31,5845},{9,31,5845},{9,31,3829},{8,31,5124},{7,31,2270},{7,31,2270},{6,29,170},{4,31,4762},{2,31,228},{12,31,1154},{12,31,1154},{12,31,1154},{11,31,353},{15,18,2178},{10,31,1013},{10,31,1013},{4,30,4},{10,29,2178},
+{4,30,4},{15,30,34},{14,31,40},{14,31,4},{14,31,4},{15,30,34},{15,30,34},{14,31,4},{0,30,64},{15,30,34},{0,30,64},{8,0,2705},{8,0,2705},{8,0,2705},{8,0,2705},{7,31,245},{7,31,245},{7,31,245},{7,27,49},{2,31,164},{2,31,164},{11,31,8857},{10,31,7170},{10,31,6209},{9,31,4133},{10,31,8853},{8,31,4484},{8,31,2548},{7,31,170},{7,31,8388},{3,31,244},{13,31,1971},
+{12,31,1611},{12,31,1250},{11,31,625},{15,24,2904},{11,31,1826},{10,31,1157},{5,31,1},{15,27,2907},{5,31,1},{10,31,6209},{10,31,6209},{10,31,6209},{9,31,4133},{9,31,5460},{8,31,2548},{8,31,2548},{7,30,129},{5,31,5126},{3,31,244},{12,31,1250},{12,31,1250},{12,31,1250},{11,31,625},{13,27,2178},{10,31,1157},{10,31,1157},{5,31,1},{13,27,2178},{5,31,1},{15,31,0},{15,31,0},{15,31,0},
+{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{9,0,2689},{9,0,2689},{9,0,2689},{9,0,2689},{7,31,485},{7,31,485},{7,31,485},{7,28,5},{3,31,244},{3,31,244},{11,31,7705},{11,31,6566},{10,31,5633},{10,31,3890},{10,31,7737},{9,31,3874},{8,31,2386},{7,31,116},{7,31,7398},{4,31,317},{13,31,1458},{13,31,1186},{13,31,1017},{12,31,425},{15,25,2166},
+{12,31,1398},{11,31,850},{6,31,4},{12,31,2166},{6,31,4},{10,31,5633},{10,31,5633},{10,31,5633},{10,31,3890},{9,31,4830},{8,31,2386},{8,31,2386},{7,31,116},{6,31,4509},{4,31,317},{13,31,1017},{13,31,1017},{13,31,1017},{12,31,425},{15,22,1625},{11,31,850},{11,31,850},{6,31,4},{13,28,1625},{6,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},
+{0,31,0},{15,31,0},{0,31,0},{9,0,2725},{9,0,2725},{9,0,2725},{9,0,2725},{8,31,450},{8,31,450},{8,31,450},{7,30,101},{4,31,317},{4,31,317},{11,31,6953},{11,31,5814},{11,31,5189},{10,31,3650},{11,31,6713},{10,31,3531},{9,31,2142},{8,31,74},{8,31,6397},{5,31,425},{13,31,1138},{13,31,866},{13,31,697},{12,31,361},{15,26,1601},{12,31,1046},{11,31,674},{7,31,16},{14,29,1601},
+{7,31,16},{11,31,5189},{11,31,5189},{11,31,5189},{10,31,3650},{10,31,4313},{9,31,2142},{9,31,2142},{8,31,74},{7,31,3981},{5,31,425},{13,31,697},{13,31,697},{13,31,697},{12,31,361},{15,23,1201},{11,31,674},{11,31,674},{7,31,16},{12,30,1201},{7,31,16},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{10,0,2689},
+{10,0,2689},{10,0,2689},{10,0,2689},{8,31,578},{8,31,578},{8,31,578},{8,30,49},{5,31,425},{5,31,425},{12,31,6211},{11,31,5318},{11,31,4693},{11,31,3554},{11,31,5833},{10,31,3067},{10,31,2106},{8,31,10},{9,31,5601},{6,31,580},{14,31,825},{13,31,674},{13,31,505},{13,31,233},{15,27,1122},{13,31,738},{12,31,461},{8,31,9},{13,31,1122},{8,31,9},{11,31,4693},{11,31,4693},{11,31,4693},
+{11,31,3554},{10,31,3849},{10,31,2106},{10,31,2106},{8,31,10},{7,31,3629},{6,31,580},{13,31,505},{13,31,505},{13,31,505},{13,31,233},{13,31,841},{12,31,461},{12,31,461},{8,31,9},{15,27,841},{8,31,9},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{10,0,2705},{10,0,2705},{10,0,2705},{10,0,2705},{9,31,666},
+{9,31,666},{9,31,666},{8,31,10},{6,31,580},{6,31,580},{12,31,5427},{12,31,4827},{11,31,4453},{11,31,3314},{12,31,5175},{10,31,2859},{10,31,1898},{9,31,74},{10,31,4842},{7,31,724},{14,31,489},{14,31,425},{14,31,389},{13,31,169},{14,31,729},{13,31,482},{13,31,313},{10,31,4},{14,30,726},{10,31,4},{11,31,4453},{11,31,4453},{11,31,4453},{11,31,3314},{11,31,3445},{10,31,1898},{10,31,1898},
+{9,31,74},{8,31,3213},{7,31,724},{14,31,389},{14,31,389},{14,31,389},{13,31,169},{15,26,545},{13,31,313},{13,31,313},{10,31,4},{14,29,545},{10,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{11,0,2689},{11,0,2689},{11,0,2689},{11,0,2689},{9,31,890},{9,31,890},{9,31,890},{9,31,74},{7,31,724},
+{7,31,724},{2,31,33740},{0,31,5184},{0,22,420},{0,21,4221},{1,31,46089},{0,29,24105},{0,21,8317},{0,18,24790},{0,21,63990},{0,16,38959},{1,31,9704},{0,30,2866},{0,21,389},{0,19,3229},{7,2,18065},{0,20,13257},{0,17,6153},{0,12,13481},{12,0,18065},{0,12,13481},{0,15,1},{0,15,1},{0,15,1},{0,9,1},{0,8,1105},{0,7,585},{0,7,585},{0,4,596},{0,4,1273},{0,4,740},{0,15,1},
+{0,15,1},{0,15,1},{0,9,1},{2,1,1105},{0,7,585},{0,7,585},{0,4,596},{4,0,1105},{0,4,596},{9,6,9248},{0,30,2866},{0,21,389},{0,19,3229},{9,6,9248},{14,5,9248},{0,19,3229},{0,14,9248},{14,5,9248},{0,14,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,31,38380},{0,31,6720},{0,23,245},
+{0,22,3864},{2,31,50747},{0,31,24961},{0,22,8353},{0,19,25735},{0,22,65535},{0,17,41319},{1,31,10152},{0,31,2624},{0,23,229},{0,20,2980},{5,10,19334},{0,20,13769},{0,18,6243},{0,13,14116},{12,1,19334},{0,13,14116},{0,18,0},{0,18,0},{0,18,0},{0,11,1},{0,9,1513},{0,8,772},{0,8,772},{0,5,821},{0,5,1750},{0,4,1028},{0,18,0},{0,18,0},{0,18,0},{0,11,1},{1,6,1513},
+{0,8,772},{0,8,772},{0,5,821},{3,2,1513},{0,5,821},{10,5,9248},{0,31,2624},{0,23,229},{0,20,2980},{10,5,9248},{12,9,9248},{0,20,2980},{0,15,9248},{12,9,9248},{0,15,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,31,43788},{0,31,9024},{0,24,126},{0,23,3525},{2,31,56155},{0,31,26241},{0,23,8425},
+{0,20,26793},{0,23,65535},{0,18,43819},{2,31,10787},{0,31,2624},{0,24,122},{0,21,2701},{8,0,20689},{0,22,14385},{0,19,6369},{0,13,14756},{12,2,20689},{0,13,14756},{0,21,1},{0,21,1},{0,21,1},{0,12,4},{0,10,1989},{0,9,1018},{0,9,1018},{0,6,1096},{0,5,2294},{0,5,1334},{0,21,1},{0,21,1},{0,21,1},{0,12,4},{1,7,1985},{0,9,1018},{0,9,1018},{0,6,1096},{1,5,1985},
+{0,6,1096},{12,1,9248},{0,31,2624},{0,24,122},{0,21,2701},{12,1,9248},{15,7,9248},{0,21,2701},{0,16,9250},{15,7,9248},{0,16,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,31,49964},{1,31,11512},{0,25,41},{0,24,3109},{2,31,62331},{0,31,28289},{0,24,8585},{0,21,27848},{0,23,65535},{0,19,46459},{2,31,11395},
+{0,31,2880},{0,25,37},{0,22,2440},{8,2,22129},{0,23,15030},{0,20,6509},{0,14,15441},{13,2,22129},{0,14,15441},{0,23,1},{0,23,1},{0,23,1},{0,14,0},{0,12,2525},{0,10,1300},{0,10,1300},{0,6,1384},{0,6,2905},{0,6,1708},{0,23,1},{0,23,1},{0,23,1},{0,14,0},{3,2,2521},{0,10,1300},{0,10,1300},{0,6,1384},{5,1,2521},{0,6,1384},{11,7,9248},{0,31,2880},{0,25,37},
+{0,22,2440},{11,7,9248},{13,11,9248},{0,22,2440},{0,17,9250},{13,11,9248},{0,17,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,31,57022},{1,31,15166},{0,26,20},{0,25,2804},{2,31,65535},{0,31,31511},{0,25,8733},{0,22,29095},{0,26,65535},{0,20,49444},{2,31,12385},{0,31,3474},{0,26,4},{0,23,2173},{8,4,23851},
+{0,23,15948},{0,21,6729},{0,15,16274},{14,2,23851},{0,15,16274},{0,26,0},{0,26,0},{0,26,0},{0,16,4},{0,13,3200},{0,11,1665},{0,11,1665},{0,7,1754},{0,7,3691},{0,6,2185},{0,26,0},{0,26,0},{0,26,0},{0,16,4},{1,10,3200},{0,11,1665},{0,11,1665},{0,7,1754},{5,2,3200},{0,7,1754},{11,10,9248},{1,31,3226},{0,26,4},{0,23,2173},{11,10,9248},{5,23,9248},{0,23,2173},
+{0,18,9248},{5,23,9248},{0,18,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,31,63870},{1,31,19230},{0,27,45},{0,27,2520},{3,31,65535},{0,31,35191},{0,26,8925},{0,23,30250},{0,28,65535},{0,21,52374},{3,31,13449},{1,31,4026},{0,27,29},{0,24,1901},{3,24,25472},{0,26,16706},{0,22,6963},{0,16,17124},{14,3,25472},
+{0,16,17124},{0,29,1},{0,29,1},{0,29,1},{0,17,1},{0,14,3874},{0,13,2084},{0,13,2084},{0,8,2165},{0,8,4466},{0,7,2627},{0,29,1},{0,29,1},{0,29,1},{0,17,1},{4,1,3872},{0,13,2084},{0,13,2084},{0,8,2165},{3,5,3872},{0,8,2165},{12,9,9248},{2,31,3593},{0,27,29},{0,24,1901},{12,9,9248},{14,13,9248},{0,24,1901},{0,19,9248},{14,13,9248},{0,19,9248},{0,0,0},
+{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,31,65535},{1,31,24002},{0,28,109},{0,27,2268},{3,31,65535},{1,31,39095},{0,27,8825},{0,24,30825},{0,28,65535},{0,22,54996},{3,31,14345},{1,31,4766},{0,29,102},{0,26,1697},{3,26,26744},{0,28,17104},{0,23,6957},{0,17,17625},{15,3,26744},{0,17,17625},{0,31,5},{0,31,5},{0,31,5},
+{0,19,5},{0,16,4418},{0,14,2306},{0,14,2306},{0,9,2420},{0,8,5122},{0,8,2997},{0,31,5},{0,31,5},{0,31,5},{0,19,5},{3,6,4418},{0,14,2306},{0,14,2306},{0,9,2420},{3,6,4418},{0,9,2420},{14,5,9248},{4,31,3904},{1,28,1},{0,26,1693},{14,5,9248},{12,17,9248},{0,26,1693},{0,20,9250},{12,17,9248},{0,20,9250},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,1},
+{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{3,31,65535},{1,31,29442},{0,29,330},{0,28,2105},{3,31,65535},{1,31,42151},{0,28,7781},{0,25,30108},{0,29,65535},{0,22,56388},{4,31,14976},{2,31,5434},{1,29,62},{0,27,1580},{11,0,26744},{0,29,16547},{0,24,6221},{0,18,17124},{13,7,26744},{0,18,17124},{0,31,181},{0,31,181},{0,31,181},{0,20,101},{0,19,4420},{0,16,2005},{0,16,2005},
+{0,10,2165},{0,9,5389},{0,9,2925},{1,31,37},{1,31,37},{1,31,37},{1,19,37},{5,2,4418},{0,16,2005},{0,16,2005},{0,10,2165},{8,1,4418},{0,10,2165},{13,11,9248},{4,31,4160},{1,29,26},{0,27,1480},{13,11,9248},{15,15,9248},{0,27,1480},{0,21,9250},{15,15,9248},{0,21,9250},{0,0,100},{0,0,100},{0,0,100},{0,0,100},{0,3,1},{0,3,1},{0,3,1},{0,2,0},{0,1,34},
+{0,1,34},{4,31,65535},{2,31,36070},{0,30,822},{0,30,2062},{3,31,65535},{1,31,46660},{0,29,6696},{0,26,29322},{0,31,65535},{0,23,58077},{4,31,15507},{3,31,6253},{1,31,109},{0,28,1646},{11,3,26744},{0,31,15992},{0,26,5346},{0,19,16582},{11,11,26744},{0,19,16582},{1,31,329},{1,31,329},{1,31,329},{1,21,266},{0,22,4420},{0,18,1737},{0,18,1737},{0,11,1898},{0,11,5707},{0,10,2885},{1,31,73},
+{1,31,73},{1,31,73},{1,21,10},{5,5,4418},{0,18,1737},{0,18,1737},{0,11,1898},{5,7,4418},{0,11,1898},{13,14,9248},{5,31,4570},{2,30,4},{0,28,1285},{13,14,9248},{8,25,9248},{0,28,1285},{0,22,9248},{8,25,9248},{0,22,9248},{1,0,265},{1,0,265},{1,0,265},{1,0,265},{0,6,1},{0,6,1},{0,6,1},{0,4,1},{0,3,97},{0,3,97},{4,31,65535},{2,31,40786},{0,31,1405},
+{0,30,2138},{4,31,65535},{1,31,49800},{0,30,5634},{0,27,27967},{0,31,65535},{0,24,58770},{5,31,15531},{3,31,6593},{2,31,61},{1,29,1533},{12,2,26259},{0,31,15284},{0,27,4514},{0,20,15812},{13,10,26259},{0,20,15812},{1,31,633},{1,31,633},{1,31,633},{1,22,381},{0,24,4418},{0,20,1480},{0,20,1480},{0,12,1640},{0,12,6125},{0,11,2891},{2,31,61},{2,31,61},{2,31,61},{2,21,37},{7,1,4418},
+{0,20,1480},{0,20,1480},{0,12,1640},{10,2,4418},{0,12,1640},{13,16,8978},{6,31,4777},{2,31,25},{0,29,1040},{13,16,8978},{15,18,8978},{0,29,1040},{0,23,8980},{15,18,8978},{0,23,8980},{1,0,377},{1,0,377},{1,0,377},{1,0,377},{0,9,0},{0,9,0},{0,9,0},{0,5,4},{0,4,193},{0,4,193},{4,31,65535},{2,31,40898},{1,31,2217},{0,31,2125},{4,31,65535},{1,31,47976},{0,30,4194},
+{0,27,24703},{0,31,65535},{0,24,56130},{5,31,14379},{4,31,6051},{2,31,173},{2,29,1284},{9,14,24371},{0,31,13716},{0,28,3402},{0,21,13989},{14,10,24371},{0,21,13989},{1,31,1193},{1,31,1193},{1,31,1193},{1,24,617},{0,27,4420},{0,22,1280},{0,22,1280},{0,13,1445},{0,14,6509},{0,12,2945},{2,31,173},{2,31,173},{2,31,173},{2,23,5},{5,10,4418},{0,22,1280},{0,22,1280},{0,13,1445},{12,1,4418},
+{0,13,1445},{14,14,7938},{7,31,4253},{3,31,9},{0,29,656},{14,14,7938},{14,20,7938},{0,29,656},{0,23,7956},{14,20,7938},{0,23,7956},{1,0,617},{1,0,617},{1,0,617},{1,0,617},{0,11,4},{0,11,4},{0,11,4},{0,7,0},{0,5,325},{0,5,325},{4,31,65535},{2,31,41266},{1,31,3033},{0,31,2333},{4,31,65535},{1,31,46408},{0,30,3010},{0,27,21695},{0,31,65535},{0,25,53636},{6,31,13140},
+{4,31,5571},{3,31,157},{2,29,932},{11,9,22568},{0,31,12404},{0,28,2474},{0,21,12245},{14,11,22568},{0,21,12245},{2,31,1630},{2,31,1630},{2,31,1630},{1,26,989},{0,29,4420},{0,23,1090},{0,23,1090},{0,14,1268},{0,15,6926},{0,13,3029},{3,31,157},{3,31,157},{3,31,157},{3,23,37},{8,1,4418},{0,23,1090},{0,23,1090},{0,14,1268},{10,5,4418},{0,14,1268},{15,12,6962},{7,31,3709},{4,31,1},
+{0,30,353},{15,12,6962},{13,22,6962},{0,30,353},{0,24,6970},{13,22,6962},{0,24,6970},{1,0,985},{1,0,985},{1,0,985},{1,0,985},{0,14,0},{0,14,0},{0,14,0},{0,8,4},{0,6,493},{0,6,493},{4,31,65535},{2,31,41986},{1,31,4257},{0,31,2873},{4,31,65535},{1,31,44950},{0,30,1984},{0,28,18569},{0,31,65535},{0,25,51026},{6,31,11934},{5,31,5125},{4,31,296},{3,29,706},{13,4,20642},
+{0,31,11234},{0,29,1634},{0,22,10422},{15,11,20642},{0,22,10422},{2,31,2350},{2,31,2350},{2,31,2350},{2,26,1450},{0,31,4450},{0,25,949},{0,25,949},{0,16,1096},{0,16,7397},{0,14,3171},{4,31,296},{4,31,296},{4,31,296},{3,25,10},{8,4,4418},{0,25,949},{0,25,949},{0,16,1096},{14,2,4418},{0,16,1096},{14,17,5941},{7,31,3250},{5,31,0},{0,30,128},{14,17,5941},{13,23,5941},{0,30,128},
+{0,24,5953},{13,23,5941},{0,24,5953},{2,0,1450},{2,0,1450},{2,0,1450},{2,0,1450},{0,17,0},{0,17,0},{0,17,0},{0,10,1},{0,8,697},{0,8,697},{4,31,65535},{2,31,42898},{1,31,5617},{1,31,3337},{4,31,65535},{1,31,43926},{0,31,1250},{0,28,15865},{0,31,65535},{0,25,48978},{7,31,10938},{5,31,4773},{4,31,360},{3,30,509},{12,9,19021},{1,31,10246},{0,30,1088},{0,23,8945},{14,13,19021},
+{0,23,8945},{2,31,3262},{2,31,3262},{2,31,3262},{2,28,1822},{1,31,4682},{0,28,776},{0,28,776},{0,17,925},{0,18,7893},{0,15,3333},{4,31,360},{4,31,360},{4,31,360},{4,25,37},{3,25,4418},{0,28,776},{0,28,776},{0,17,925},{12,6,4418},{0,17,925},{15,15,5101},{8,31,2777},{6,31,9},{0,31,25},{15,15,5101},{11,26,5101},{0,31,25},{0,25,5105},{11,26,5101},{0,25,5105},{2,0,1818},
+{2,0,1818},{2,0,1818},{2,0,1818},{0,20,1},{0,20,1},{0,20,1},{0,12,1},{0,9,925},{0,9,925},{4,31,65535},{2,31,44066},{1,31,7233},{1,31,3993},{4,31,65535},{2,31,43110},{0,31,738},{0,28,13417},{0,31,65535},{0,25,47186},{7,31,9978},{6,31,4467},{5,31,452},{4,30,357},{15,1,17485},{2,31,9441},{0,30,704},{0,24,7570},{15,13,17485},{0,24,7570},{3,31,4058},{3,31,4058},{3,31,4058},
+{2,29,2315},{1,31,4874},{0,29,610},{0,29,610},{0,18,772},{0,20,8427},{0,16,3497},{5,31,452},{5,31,452},{5,31,452},{4,27,5},{9,6,4418},{0,29,610},{0,29,610},{0,18,772},{14,5,4418},{0,18,772},{15,16,4325},{8,31,2377},{6,31,25},{0,31,9},{15,16,4325},{15,22,4325},{0,31,9},{0,25,4337},{15,22,4325},{0,25,4337},{2,0,2314},{2,0,2314},{2,0,2314},{2,0,2314},{0,22,1},
+{0,22,1},{0,22,1},{0,13,4},{0,10,1189},{0,10,1189},{5,31,65535},{3,31,45090},{1,31,9105},{1,31,4905},{4,31,65535},{2,31,42326},{0,31,482},{0,28,11225},{0,31,65535},{0,26,45590},{7,31,9274},{6,31,4179},{5,31,612},{4,30,245},{14,6,16034},{3,31,8633},{0,31,482},{0,24,6242},{15,14,16034},{0,24,6242},{3,31,5066},{3,31,5066},{3,31,5066},{2,31,2939},{1,31,5322},{0,31,482},{0,31,482},
+{0,19,637},{0,20,8939},{0,17,3725},{5,31,612},{5,31,612},{5,31,612},{5,27,37},{10,5,4418},{0,31,482},{0,31,482},{0,19,637},{12,9,4418},{0,19,637},{13,24,3613},{9,31,1973},{7,31,9},{2,31,1},{13,24,3613},{15,23,3613},{2,31,1},{0,26,3617},{15,23,3613},{0,26,3617},{2,0,2938},{2,0,2938},{2,0,2938},{2,0,2938},{0,25,1},{0,25,1},{0,25,1},{0,15,0},{0,11,1489},
+{0,11,1489},{5,31,65535},{3,31,46530},{1,31,11517},{1,31,6237},{4,31,65535},{2,31,41750},{0,31,500},{0,29,8976},{0,31,65535},{0,26,43934},{8,31,8225},{7,31,3853},{6,31,680},{5,30,109},{11,18,14504},{4,31,7667},{0,31,500},{0,25,4979},{10,21,14504},{0,25,4979},{3,31,6506},{3,31,6506},{3,31,6506},{3,31,3701},{2,31,6019},{0,31,500},{0,31,500},{0,20,520},{0,22,9629},{0,18,4035},{6,31,680},
+{6,31,680},{6,31,680},{5,29,10},{10,8,4418},{0,31,500},{0,31,500},{0,20,520},{11,12,4418},{0,20,520},{15,19,2888},{10,31,1537},{8,31,16},{3,31,4},{15,19,2888},{13,26,2888},{3,31,4},{0,26,2906},{13,26,2888},{0,26,2906},{3,0,3697},{3,0,3697},{3,0,3697},{3,0,3697},{0,28,1},{0,28,1},{0,28,1},{0,17,4},{0,11,1930},{0,11,1930},{5,31,65535},{3,31,48082},{1,31,13933},
+{1,31,7693},{4,31,65535},{2,31,41510},{0,31,788},{0,29,7120},{0,31,65535},{0,26,42734},{8,31,7409},{7,31,3693},{7,31,884},{6,30,116},{13,13,13235},{4,31,6899},{1,31,628},{0,25,3987},{15,16,13235},{0,25,3987},{4,31,7686},{4,31,7686},{4,31,7686},{3,31,4437},{2,31,6659},{0,31,788},{0,31,788},{0,21,421},{0,23,10286},{0,20,4305},{7,31,884},{7,31,884},{7,31,884},{6,29,37},{9,14,4418},
+{1,31,628},{1,31,628},{0,21,421},{14,10,4418},{0,21,421},{15,20,2312},{10,31,1217},{8,31,16},{4,31,9},{15,20,2312},{12,28,2312},{4,31,9},{0,27,2314},{12,28,2312},{0,27,2314},{3,0,4337},{3,0,4337},{3,0,4337},{3,0,4337},{0,30,1},{0,30,1},{0,30,1},{0,18,1},{0,13,2329},{0,13,2329},{5,31,65535},{3,31,49890},{2,31,16310},{1,31,9405},{4,31,65535},{2,31,41526},{0,31,1332},
+{0,29,5520},{0,31,65535},{0,26,41790},{8,31,6849},{8,31,3601},{7,31,980},{6,31,5},{15,8,12051},{5,31,6275},{2,31,801},{0,26,3066},{11,22,12051},{0,26,3066},{4,31,9062},{4,31,9062},{4,31,9062},{3,31,5429},{2,31,7555},{1,31,1172},{1,31,1172},{0,23,325},{0,23,11118},{0,20,4625},{7,31,980},{7,31,980},{7,31,980},{6,31,5},{11,10,4418},{2,31,801},{2,31,801},{0,23,325},{5,23,4418},
+{0,23,325},{13,28,1800},{11,31,949},{9,31,4},{6,31,1},{13,28,1800},{11,30,1800},{6,31,1},{0,27,1818},{11,30,1800},{0,27,1818},{3,0,5105},{3,0,5105},{3,0,5105},{3,0,5105},{0,31,36},{0,31,36},{0,31,36},{0,20,4},{0,15,2741},{0,15,2741},{5,31,65535},{3,31,51954},{2,31,18790},{1,31,11373},{5,31,65535},{2,31,41798},{0,31,2132},{0,29,4176},{0,31,65535},{0,27,41092},{9,31,6153},
+{8,31,3297},{7,31,1332},{7,31,37},{14,13,10952},{5,31,5763},{3,31,965},{0,27,2291},{11,23,10952},{0,27,2291},{4,31,10694},{4,31,10694},{4,31,10694},{4,31,6566},{3,31,8619},{1,31,1716},{1,31,1716},{0,24,221},{0,26,11876},{0,22,4989},{7,31,1332},{7,31,1332},{7,31,1332},{7,31,37},{12,9,4418},{3,31,965},{3,31,965},{0,24,221},{14,13,4418},{0,24,221},{14,26,1352},{11,31,725},{10,31,0},
+{7,31,1},{14,26,1352},{15,26,1352},{7,31,1},{0,28,1360},{15,26,1352},{0,28,1360},{3,0,6001},{3,0,6001},{3,0,6001},{3,0,6001},{0,31,196},{0,31,196},{0,31,196},{0,21,1},{0,16,3130},{0,16,3130},{5,31,65535},{3,31,54582},{2,31,21886},{1,31,13893},{5,31,65535},{2,31,42410},{0,31,3338},{0,30,2841},{0,31,65535},{0,27,40390},{9,31,5649},{9,31,3249},{8,31,1325},{7,31,109},{14,15,9818},
+{6,31,5258},{4,31,1108},{0,27,1589},{12,23,9818},{0,27,1589},{5,31,12376},{5,31,12376},{5,31,12376},{4,31,7844},{3,31,9861},{1,31,2634},{1,31,2634},{0,25,136},{0,28,12696},{0,23,5429},{8,31,1325},{8,31,1325},{8,31,1325},{7,31,109},{15,2,4418},{4,31,1108},{4,31,1108},{0,25,136},{13,16,4418},{0,25,136},{15,24,925},{12,31,505},{11,31,1},{8,31,1},{15,24,925},{15,27,925},{8,31,1},
+{0,28,937},{15,27,925},{0,28,937},{4,0,7060},{4,0,7060},{4,0,7060},{4,0,7060},{1,31,425},{1,31,425},{1,31,425},{0,23,0},{0,17,3665},{0,17,3665},{5,31,65535},{3,31,57190},{2,31,24910},{1,31,16405},{5,31,65535},{2,31,43226},{0,31,4682},{0,30,1833},{0,31,65535},{0,27,40038},{10,31,5202},{9,31,3073},{8,31,1565},{8,31,277},{13,20,8901},{7,31,4814},{5,31,1300},{0,28,1021},{13,23,8902},
+{0,28,1021},{5,31,14136},{5,31,14136},{5,31,14136},{4,31,9252},{3,31,11237},{2,31,3590},{2,31,3590},{0,26,85},{0,29,13491},{0,23,5925},{8,31,1565},{8,31,1565},{8,31,1565},{8,31,277},{11,18,4418},{5,31,1300},{5,31,1300},{0,26,85},{10,21,4418},{0,26,85},{15,25,617},{13,31,365},{12,31,16},{9,31,9},{15,25,617},{13,30,613},{9,31,9},{0,29,617},{13,30,613},{0,29,617},{4,0,7956},
+{4,0,7956},{4,0,7956},{4,0,7956},{1,31,697},{1,31,697},{1,31,697},{0,25,4},{0,18,4181},{0,18,4181},{5,31,65535},{3,31,60054},{2,31,28190},{2,31,18895},{5,31,65535},{2,31,44298},{1,31,6090},{0,30,1081},{0,31,65535},{0,27,39942},{10,31,4850},{10,31,3107},{9,31,1709},{8,31,325},{13,22,8069},{7,31,4574},{6,31,1553},{0,29,602},{12,25,8069},{0,29,602},{6,31,16067},{6,31,16067},{6,31,16067},
+{5,31,10872},{4,31,12824},{2,31,4662},{2,31,4662},{0,27,52},{0,30,14340},{0,25,6449},{9,31,1709},{9,31,1709},{9,31,1709},{8,31,325},{13,14,4418},{6,31,1553},{6,31,1553},{0,27,52},{8,25,4418},{0,27,52},{15,27,365},{13,31,205},{12,31,16},{11,31,4},{15,27,365},{13,31,365},{11,31,4},{0,29,377},{13,31,365},{0,29,377},{4,0,8980},{4,0,8980},{4,0,8980},{4,0,8980},{1,31,1097},
+{1,31,1097},{1,31,1097},{0,26,1},{0,20,4682},{0,20,4682},{6,31,65535},{4,31,58981},{2,31,29926},{2,31,19751},{5,31,65535},{3,31,43402},{1,31,6910},{0,30,765},{0,31,65535},{0,28,34909},{11,31,4502},{10,31,3011},{9,31,2045},{9,31,557},{15,17,7322},{8,31,4242},{7,31,1781},{0,29,314},{12,26,7322},{0,29,314},{6,31,16739},{6,31,16739},{6,31,16739},{5,31,11492},{4,31,13636},{3,31,5586},{3,31,5586},
+{0,28,65},{0,31,14139},{0,26,6041},{9,31,2045},{9,31,2045},{9,31,2045},{9,31,557},{14,13,4418},{7,31,1781},{7,31,1781},{0,28,29},{11,23,4418},{0,28,29},{15,28,181},{14,31,117},{13,31,4},{12,31,0},{15,28,181},{15,29,181},{12,31,0},{0,30,185},{15,29,181},{0,30,185},{4,0,9376},{4,0,9376},{4,0,9376},{4,0,9376},{2,31,1405},{2,31,1405},{2,31,1405},{0,28,40},{0,21,4520},
+{0,21,4520},{6,31,65535},{4,31,57316},{3,31,30345},{3,31,20808},{6,31,65535},{3,31,41449},{2,31,8321},{1,31,301},{0,31,65535},{0,28,28330},{11,31,4232},{11,31,3093},{10,31,2248},{9,31,809},{15,19,6584},{9,31,3992},{7,31,2105},{0,30,77},{13,26,6584},{0,30,77},{7,31,17380},{7,31,17380},{7,31,17380},{6,31,12161},{5,31,14315},{3,31,6405},{3,31,6405},{1,29,53},{0,31,13860},{0,28,5286},{10,31,2248},
+{10,31,2248},{10,31,2248},{9,31,809},{14,16,4418},{7,31,2105},{7,31,2105},{0,30,13},{15,20,4418},{0,30,13},{15,29,52},{14,31,36},{14,31,0},{13,31,9},{15,29,52},{15,30,50},{13,31,9},{0,30,68},{15,30,50},{0,30,68},{5,0,9250},{5,0,9250},{5,0,9250},{5,0,9250},{2,31,1549},{2,31,1549},{2,31,1549},{1,28,2},{0,23,4114},{0,23,4114},{6,31,65535},{5,31,55908},{4,31,31583},
+{3,31,21256},{6,31,65535},{4,31,39740},{2,31,9073},{1,31,285},{0,31,65535},{0,29,23356},{12,31,4011},{11,31,3125},{11,31,2500},{10,31,1037},{13,27,6019},{10,31,3738},{8,31,2340},{0,31,4},{13,27,6019},{0,31,4},{7,31,17796},{7,31,17796},{7,31,17796},{6,31,12625},{6,31,14996},{4,31,7139},{4,31,7139},{1,30,86},{0,31,14020},{0,29,4652},{11,31,2500},{11,31,2500},{11,31,2500},{10,31,1037},{13,22,4418},
+{8,31,2340},{8,31,2340},{0,31,4},{12,25,4418},{0,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{0,31,4},{15,31,4},{0,31,4},{6,0,9376},{6,0,9376},{6,0,9376},{6,0,9376},{3,31,1765},{3,31,1765},{3,31,1765},{1,30,50},{0,25,3877},{0,25,3877},{7,31,65535},{5,31,53236},{4,31,30487},{4,31,21367},{6,31,65535},{4,31,37332},{3,31,9385},
+{2,31,36},{0,31,65535},{0,29,18680},{12,31,3443},{12,31,2843},{11,31,2248},{10,31,997},{14,25,5163},{10,31,3218},{9,31,2120},{1,31,4},{12,29,5163},{1,31,4},{7,31,17504},{7,31,17504},{7,31,17504},{7,31,12569},{6,31,14328},{4,31,7227},{4,31,7227},{2,31,20},{0,31,13376},{0,29,3944},{11,31,2248},{11,31,2248},{11,31,2248},{10,31,997},{15,17,3872},{9,31,2120},{9,31,2120},{1,31,4},{12,26,3872},
+{1,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{6,0,9248},{6,0,9248},{6,0,9248},{6,0,9248},{3,31,2005},{3,31,2005},{3,31,2005},{2,30,5},{0,27,3545},{0,27,3545},{7,31,65535},{6,31,50785},{4,31,29687},{4,31,20567},{7,31,65535},{4,31,35412},{3,31,8985},{2,31,196},{1,31,65535},{0,29,14712},{12,31,2883},
+{12,31,2283},{12,31,1922},{11,31,821},{13,29,4267},{11,31,2694},{10,31,1745},{3,31,4},{14,27,4267},{3,31,4},{8,31,16610},{8,31,16610},{8,31,16610},{7,31,12185},{6,31,13528},{5,31,6915},{5,31,6915},{2,31,52},{1,31,12556},{0,30,3314},{12,31,1922},{12,31,1922},{12,31,1922},{11,31,821},{12,28,3200},{10,31,1745},{10,31,1745},{3,31,4},{11,28,3200},{3,31,4},{15,31,0},{15,31,0},{15,31,0},
+{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{6,0,9376},{6,0,9376},{6,0,9376},{6,0,9376},{4,31,2250},{4,31,2250},{4,31,2250},{2,31,52},{0,28,3170},{0,28,3170},{7,31,65535},{6,31,47239},{5,31,28065},{5,31,20409},{7,31,65535},{5,31,32574},{4,31,8965},{3,31,54},{1,31,65206},{0,30,10964},{13,31,2326},{12,31,1806},{12,31,1445},{11,31,650},{13,30,3361},
+{11,31,2091},{10,31,1322},{4,31,0},{12,30,3361},{4,31,0},{8,31,15584},{8,31,15584},{8,31,15584},{7,31,12059},{7,31,12522},{6,31,6811},{6,31,6811},{3,31,50},{1,31,11710},{0,31,2834},{12,31,1445},{12,31,1445},{12,31,1445},{11,31,650},{14,23,2521},{10,31,1322},{10,31,1322},{4,31,0},{15,24,2521},{4,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},
+{0,31,0},{15,31,0},{0,31,0},{7,0,9250},{7,0,9250},{7,0,9250},{7,0,9250},{5,31,2600},{5,31,2600},{5,31,2600},{3,31,50},{0,31,2834},{0,31,2834},{8,31,65535},{6,31,44903},{5,31,27361},{5,31,19705},{7,31,64494},{5,31,30846},{4,31,8677},{3,31,470},{2,31,60777},{0,30,8308},{13,31,1782},{13,31,1510},{12,31,1157},{12,31,557},{13,31,2646},{11,31,1691},{11,31,1066},{5,31,4},{15,27,2646},
+{5,31,4},{8,31,14944},{8,31,14944},{8,31,14944},{8,31,11696},{7,31,11850},{6,31,6555},{6,31,6555},{4,31,164},{2,31,11097},{0,31,2610},{12,31,1157},{12,31,1157},{12,31,1157},{12,31,557},{15,21,1985},{11,31,1066},{11,31,1066},{5,31,4},{15,25,1985},{5,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{7,0,9410},
+{7,0,9410},{7,0,9410},{7,0,9410},{5,31,2792},{5,31,2792},{5,31,2792},{4,31,164},{0,31,2610},{0,31,2610},{8,31,63584},{7,31,42019},{6,31,25930},{5,31,19769},{8,31,60273},{6,31,28860},{5,31,8761},{4,31,276},{3,31,56253},{0,30,6420},{13,31,1366},{13,31,1094},{13,31,925},{12,31,397},{15,25,2018},{12,31,1298},{11,31,794},{7,31,4},{13,30,2017},{7,31,4},{9,31,14244},{9,31,14244},{9,31,14244},
+{8,31,11312},{8,31,11249},{7,31,6499},{7,31,6499},{4,31,260},{3,31,10457},{0,31,2642},{13,31,925},{13,31,925},{13,31,925},{12,31,397},{15,22,1513},{11,31,794},{11,31,794},{7,31,4},{14,27,1513},{7,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{8,0,9376},{8,0,9376},{8,0,9376},{8,0,9376},{6,31,3074},
+{6,31,3074},{6,31,3074},{4,31,260},{0,31,2642},{0,31,2642},{8,31,58848},{7,31,39683},{6,31,25130},{6,31,19007},{8,31,54849},{6,31,27132},{5,31,8569},{4,31,756},{4,31,51302},{0,31,5046},{13,31,1078},{13,31,806},{13,31,637},{12,31,365},{15,26,1473},{12,31,978},{12,31,617},{8,31,9},{14,29,1473},{8,31,9},{9,31,13604},{9,31,13604},{9,31,13604},{8,31,11184},{8,31,10433},{7,31,6339},{7,31,6339},
+{5,31,424},{4,31,9713},{0,31,2930},{13,31,637},{13,31,637},{13,31,637},{12,31,365},{14,27,1105},{12,31,617},{12,31,617},{8,31,9},{13,29,1105},{8,31,9},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{8,0,9248},{8,0,9248},{8,0,9248},{8,0,9248},{6,31,3330},{6,31,3330},{6,31,3330},{5,31,424},{0,31,2930},
+{0,31,2930}, \ No newline at end of file
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_pvrtc2_alpha_33.inc b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_pvrtc2_alpha_33.inc
new file mode 100644
index 0000000000..10c94153ad
--- /dev/null
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_tables_pvrtc2_alpha_33.inc
@@ -0,0 +1,481 @@
+{0,0,20},{0,0,20},{0,0,97},{0,0,145},{0,0,56},{0,0,104},{0,0,181},{0,0,406},{0,0,204},{0,0,442},{0,0,20},{0,0,20},{0,0,97},{0,0,145},{0,0,56},{0,0,104},{0,0,181},{0,0,406},{0,0,168},{0,0,406},{0,0,16},{0,0,16},{0,0,16},{0,0,64},{0,0,52},{0,0,100},{0,0,100},{0,0,325},{0,0,200},{0,0,361},{0,0,16},
+{0,0,16},{0,0,16},{0,0,64},{0,0,52},{0,0,100},{0,0,100},{0,0,325},{0,0,164},{0,0,325},{0,0,20},{0,0,20},{0,0,97},{0,0,145},{0,0,20},{0,0,68},{0,0,145},{0,0,306},{0,0,68},{0,0,306},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,1,126},{0,0,88},{0,0,53},
+{0,0,37},{0,0,116},{0,0,36},{0,0,1},{0,0,66},{0,0,88},{0,0,102},{0,1,126},{0,0,88},{0,0,53},{0,0,37},{0,0,116},{0,0,36},{0,0,1},{0,0,66},{0,0,52},{0,0,66},{0,0,52},{0,0,52},{0,0,52},{0,0,36},{0,0,16},{0,0,0},{0,0,0},{0,0,65},{0,0,52},{0,0,101},{0,0,52},{0,0,52},{0,0,52},{0,0,36},{0,0,16},
+{0,0,0},{0,0,0},{0,0,65},{0,0,16},{0,0,65},{0,1,90},{0,0,52},{0,0,17},{0,0,1},{0,1,90},{0,0,36},{0,0,1},{0,0,50},{0,0,36},{0,0,50},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,0,0},{0,0,0},{0,0,0},{0,0,16},{0,0,52},{0,0,52},{0,1,286},{0,1,310},{0,0,453},{0,0,373},{0,1,115},{0,1,307},{0,0,241},
+{0,0,130},{0,0,280},{0,0,70},{0,1,222},{0,1,246},{0,0,389},{0,0,309},{0,1,51},{1,0,195},{0,0,177},{0,0,66},{1,0,107},{0,0,66},{0,1,261},{0,1,261},{0,1,261},{0,0,324},{0,1,90},{0,0,192},{0,0,192},{0,0,81},{0,0,84},{0,0,21},{0,1,197},{0,1,197},{0,1,197},{0,0,260},{0,1,26},{0,0,128},{0,0,128},{0,0,17},{0,0,80},
+{0,0,17},{0,1,26},{0,1,50},{1,0,130},{1,0,74},{0,1,26},{1,0,26},{1,0,74},{0,0,50},{1,0,26},{0,0,50},{0,0,260},{0,0,260},{0,0,260},{0,0,260},{0,1,89},{0,1,89},{0,1,89},{0,0,80},{0,0,20},{0,0,20},{1,0,494},{1,0,550},{1,0,694},{1,0,702},{0,2,363},{0,1,291},{1,0,583},{1,0,631},{0,1,116},{1,0,428},{1,0,170},
+{1,0,226},{1,0,370},{1,0,378},{1,0,51},{0,1,35},{1,0,259},{1,0,307},{1,0,91},{1,0,307},{1,0,469},{1,0,469},{1,0,469},{1,0,477},{0,1,314},{0,1,290},{0,1,290},{1,0,406},{0,1,115},{1,0,203},{1,0,145},{1,0,145},{1,0,145},{1,0,153},{1,0,26},{1,0,34},{1,0,34},{1,0,82},{1,0,10},{1,0,82},{1,0,26},{0,1,50},{1,0,226},
+{1,0,234},{1,0,26},{0,1,26},{1,0,234},{0,0,306},{0,1,26},{0,0,306},{1,0,468},{1,0,468},{1,0,468},{1,0,468},{0,1,265},{0,1,265},{0,1,265},{1,0,325},{0,1,90},{0,1,90},{1,1,116},{1,1,124},{1,1,215},{1,1,271},{1,1,188},{1,1,252},{1,1,343},{1,1,606},{0,1,152},{0,1,392},{1,1,35},{1,1,43},{1,1,134},{1,1,190},{1,1,107},
+{1,1,171},{0,1,260},{0,1,356},{2,0,51},{0,1,356},{1,1,115},{1,1,115},{1,1,115},{1,1,171},{1,0,161},{1,0,241},{1,0,241},{1,0,469},{0,1,52},{0,1,292},{1,1,34},{1,1,34},{1,1,34},{1,1,90},{0,2,16},{1,0,160},{1,0,160},{0,1,256},{0,1,16},{0,1,256},{1,1,26},{1,1,34},{1,1,125},{0,1,116},{1,1,26},{2,0,26},{0,1,116},
+{0,1,356},{2,0,26},{0,1,356},{1,0,90},{1,0,90},{1,0,90},{1,0,90},{1,0,97},{1,0,97},{1,0,97},{1,0,145},{0,1,36},{0,1,36},{1,1,116},{1,1,60},{1,1,39},{1,1,31},{1,1,92},{1,1,28},{1,1,7},{1,1,94},{1,1,100},{1,1,142},{1,1,115},{1,1,59},{1,1,38},{1,1,30},{0,3,51},{1,1,27},{1,1,6},{1,1,93},{1,1,51},
+{1,1,93},{1,1,35},{1,1,35},{1,1,35},{1,1,27},{1,1,11},{1,1,3},{1,1,3},{1,1,90},{1,1,75},{1,1,138},{1,1,34},{1,1,34},{1,1,34},{1,1,26},{1,1,10},{1,1,2},{1,1,2},{1,1,89},{1,1,26},{1,1,89},{2,0,26},{1,1,34},{1,1,13},{1,1,5},{2,0,26},{3,0,26},{1,1,5},{0,1,68},{3,0,26},{0,1,68},{1,0,26},
+{1,0,26},{1,0,26},{1,0,26},{1,1,2},{1,1,2},{1,1,2},{1,1,26},{1,1,74},{1,1,74},{1,2,238},{1,2,286},{1,1,375},{1,1,303},{1,2,105},{1,1,316},{1,1,183},{1,1,94},{0,2,156},{1,1,46},{1,2,189},{1,2,237},{1,1,326},{1,1,254},{1,2,56},{2,1,232},{1,1,134},{1,1,45},{0,2,56},{1,1,45},{1,2,222},{1,2,222},{1,2,222},
+{1,1,267},{1,2,89},{1,1,147},{1,1,147},{1,1,58},{1,1,59},{1,1,10},{1,2,173},{1,2,173},{1,2,173},{1,1,218},{2,0,10},{1,1,98},{1,1,98},{1,1,9},{3,0,10},{1,1,9},{1,2,20},{1,2,68},{2,1,136},{2,1,72},{1,2,20},{0,2,20},{2,1,72},{0,1,36},{0,2,20},{0,1,36},{1,0,218},{1,0,218},{1,0,218},{1,0,218},{1,2,85},
+{1,2,85},{1,2,85},{1,1,58},{1,1,10},{1,1,10},{2,1,550},{2,1,598},{2,1,730},{2,1,730},{1,3,361},{1,2,265},{2,1,597},{1,1,606},{1,2,152},{2,1,408},{2,1,189},{2,1,237},{2,1,369},{2,1,369},{2,1,56},{1,2,40},{2,1,236},{2,1,264},{4,0,56},{2,1,264},{2,1,534},{2,1,534},{2,1,534},{2,1,534},{1,2,265},{1,2,265},{1,2,265},
+{1,1,410},{2,1,152},{2,1,212},{2,1,173},{2,1,173},{2,1,173},{2,1,173},{0,4,8},{2,1,40},{2,1,40},{2,1,68},{2,1,8},{2,1,68},{2,1,20},{1,2,36},{2,1,200},{2,1,200},{2,1,20},{4,0,20},{2,1,200},{0,1,260},{4,0,20},{0,1,260},{2,0,530},{2,0,530},{2,0,530},{2,0,530},{1,2,229},{1,2,229},{1,2,229},{1,2,325},{1,2,116},
+{1,2,116},{2,2,152},{2,2,168},{2,2,273},{2,2,337},{2,2,236},{2,2,316},{2,2,421},{2,2,706},{1,2,116},{1,2,436},{2,2,52},{2,2,68},{2,2,173},{2,2,237},{3,0,56},{1,2,211},{1,2,251},{1,2,411},{3,1,56},{1,2,411},{2,2,152},{2,2,152},{2,2,152},{2,2,216},{2,1,158},{2,1,230},{2,1,230},{2,1,438},{1,2,35},{1,2,315},{2,2,52},
+{2,2,52},{2,2,52},{2,2,116},{1,3,10},{2,1,130},{2,1,130},{1,2,290},{1,2,10},{1,2,290},{3,0,20},{2,2,52},{2,2,157},{1,2,130},{3,0,20},{3,1,20},{1,2,130},{0,2,410},{3,1,20},{0,2,410},{2,0,116},{2,0,116},{2,0,116},{2,0,116},{2,1,109},{2,1,109},{2,1,109},{2,1,149},{1,2,26},{1,2,26},{2,2,88},{2,2,40},{2,2,33},
+{2,2,33},{2,2,76},{2,2,28},{2,2,21},{2,2,130},{2,2,120},{2,2,190},{2,2,84},{2,2,36},{2,2,29},{2,2,29},{1,4,56},{2,2,24},{2,2,17},{2,2,126},{2,2,56},{2,2,126},{2,2,24},{2,2,24},{2,2,24},{2,2,24},{2,2,12},{2,2,12},{2,2,12},{2,2,121},{2,2,104},{2,2,181},{2,2,20},{2,2,20},{2,2,20},{2,2,20},{2,2,8},
+{2,2,8},{2,2,8},{2,2,117},{5,0,8},{2,2,117},{1,4,20},{2,2,20},{2,2,13},{2,2,13},{1,4,20},{2,2,20},{2,2,13},{0,2,90},{2,2,20},{0,2,90},{2,0,20},{2,0,20},{2,0,20},{2,0,20},{2,2,8},{2,2,8},{2,2,8},{2,2,40},{2,2,100},{2,2,100},{2,3,198},{2,3,270},{2,2,305},{2,2,241},{2,3,103},{2,2,252},{2,2,133},
+{2,2,66},{1,3,148},{2,2,30},{2,3,162},{2,3,234},{2,2,269},{2,2,205},{2,3,67},{2,2,216},{2,2,97},{2,2,30},{6,0,67},{2,2,30},{2,3,189},{2,3,189},{2,3,189},{2,2,216},{2,3,94},{2,2,108},{2,2,108},{2,2,41},{2,2,40},{2,2,5},{2,3,153},{2,3,153},{2,3,153},{2,2,180},{3,1,8},{2,2,72},{2,2,72},{2,2,5},{4,1,8},
+{2,2,5},{2,3,18},{2,3,90},{2,2,125},{2,2,61},{2,3,18},{6,0,18},{2,2,61},{0,2,26},{6,0,18},{0,2,26},{2,0,180},{2,0,180},{2,0,180},{2,0,180},{2,2,72},{2,2,72},{2,2,72},{2,2,40},{2,2,4},{2,2,4},{3,2,614},{2,3,622},{3,2,774},{3,2,766},{2,3,343},{2,3,247},{3,2,619},{2,2,514},{2,3,196},{2,2,382},{3,2,214},
+{3,2,254},{3,2,374},{3,2,366},{4,0,59},{2,3,51},{3,2,219},{3,2,227},{3,2,59},{3,2,227},{3,2,605},{3,2,605},{3,2,605},{3,2,597},{2,3,222},{2,3,246},{2,3,246},{2,2,345},{3,2,179},{2,2,213},{3,2,205},{3,2,205},{3,2,205},{3,2,197},{4,0,10},{3,2,50},{3,2,50},{3,2,58},{3,2,10},{3,2,58},{3,2,18},{2,3,26},{3,2,178},
+{3,2,170},{3,2,18},{5,1,18},{3,2,170},{0,2,218},{5,1,18},{0,2,218},{2,0,596},{2,0,596},{2,0,596},{2,0,596},{2,3,197},{2,3,197},{2,3,197},{2,2,296},{2,3,146},{2,3,146},{3,3,196},{3,3,220},{3,3,339},{3,3,411},{3,3,292},{3,3,388},{3,3,507},{3,3,814},{2,3,88},{2,3,488},{3,3,75},{3,3,99},{3,3,218},{3,3,290},{4,1,67},
+{2,3,168},{2,3,248},{2,3,472},{4,2,67},{2,3,472},{3,2,182},{3,2,182},{3,2,182},{3,2,246},{3,2,161},{3,2,225},{3,2,225},{3,2,413},{2,3,24},{3,2,308},{3,2,61},{3,2,61},{3,2,61},{3,2,125},{2,4,8},{3,2,104},{3,2,104},{3,2,292},{7,0,8},{3,2,292},{4,1,18},{3,3,74},{3,3,193},{2,3,148},{4,1,18},{4,2,18},{2,3,148},
+{0,3,468},{4,2,18},{0,3,468},{3,0,146},{3,0,146},{3,0,146},{3,0,146},{3,2,125},{3,2,125},{3,2,125},{3,2,157},{2,3,20},{2,3,20},{3,3,68},{3,3,28},{3,3,35},{3,3,43},{3,3,68},{3,3,36},{3,3,43},{3,3,174},{3,3,148},{3,3,246},{3,3,59},{3,3,19},{3,3,26},{3,3,34},{3,3,59},{3,3,27},{3,3,34},{2,3,152},{6,1,59},
+{2,3,152},{3,3,19},{3,3,19},{3,3,19},{3,3,27},{3,3,19},{3,3,27},{3,3,27},{3,3,158},{3,3,139},{3,3,230},{3,3,10},{3,3,10},{3,3,10},{3,3,18},{3,3,10},{3,3,18},{3,3,18},{2,3,136},{6,1,10},{2,3,136},{5,0,18},{3,3,10},{3,3,17},{3,3,25},{5,0,18},{3,3,18},{3,3,25},{0,3,116},{3,3,18},{0,3,116},{3,0,18},
+{3,0,18},{3,0,18},{3,0,18},{3,3,18},{3,3,18},{3,3,18},{3,3,58},{3,3,130},{3,3,130},{3,4,166},{3,4,262},{3,3,243},{3,3,187},{3,4,109},{3,3,196},{3,3,91},{3,3,46},{3,3,148},{3,3,22},{3,4,141},{3,4,237},{3,3,218},{3,3,162},{4,2,59},{3,3,171},{3,3,66},{3,3,21},{5,2,59},{3,3,21},{3,4,162},{3,4,162},{3,4,162},
+{3,3,171},{3,4,105},{3,3,75},{3,3,75},{3,3,30},{3,3,27},{3,3,6},{3,4,137},{3,4,137},{3,4,137},{3,3,146},{4,2,10},{3,3,50},{3,3,50},{3,3,5},{5,2,10},{3,3,5},{3,4,20},{3,4,116},{3,3,97},{3,3,41},{3,4,20},{7,1,20},{3,3,41},{0,3,20},{7,1,20},{0,3,20},{3,0,146},{3,0,146},{3,0,146},{3,0,146},{3,3,50},
+{3,3,50},{3,3,50},{3,3,26},{3,3,2},{3,3,2},{3,5,598},{3,4,550},{4,3,826},{4,3,810},{3,4,285},{3,4,237},{4,3,649},{3,3,430},{4,3,248},{3,3,310},{4,3,245},{4,3,277},{4,3,385},{4,3,369},{5,1,52},{3,4,68},{4,3,208},{4,3,196},{4,3,52},{4,3,196},{3,4,546},{3,4,546},{3,4,546},{3,4,594},{3,4,185},{3,4,233},{3,4,233},
+{3,3,286},{4,3,212},{3,3,166},{4,3,241},{4,3,241},{4,3,241},{4,3,225},{5,1,16},{4,3,64},{4,3,64},{4,3,52},{7,1,16},{4,3,52},{4,3,20},{3,4,20},{4,3,160},{4,3,144},{4,3,20},{6,2,20},{4,3,144},{0,3,180},{6,2,20},{0,3,180},{3,0,530},{3,0,530},{3,0,530},{3,0,530},{3,4,169},{3,4,169},{3,4,169},{3,3,250},{3,3,130},
+{3,3,130},{4,4,248},{4,4,280},{4,4,413},{4,4,493},{4,3,291},{4,3,451},{4,4,601},{4,3,835},{3,4,68},{3,4,548},{4,4,104},{4,4,136},{4,4,269},{4,4,349},{6,0,59},{3,4,131},{3,4,251},{3,4,539},{3,4,59},{3,4,539},{4,3,205},{4,3,205},{4,3,205},{4,3,261},{4,3,170},{4,3,226},{4,3,226},{4,3,394},{3,4,19},{4,3,275},{4,3,61},
+{4,3,61},{4,3,61},{4,3,117},{6,0,10},{4,3,82},{4,3,82},{4,3,250},{3,4,10},{4,3,250},{5,2,20},{4,4,100},{4,4,233},{3,4,170},{5,2,20},{5,3,20},{3,4,170},{0,4,530},{5,3,20},{0,4,530},{4,0,180},{4,0,180},{4,0,180},{4,0,180},{4,3,145},{4,3,145},{4,3,145},{4,3,169},{3,4,18},{3,4,18},{4,4,56},{4,4,24},{4,4,45},
+{4,4,61},{4,4,68},{4,4,52},{4,4,73},{4,4,226},{4,4,184},{3,4,292},{4,4,40},{4,4,8},{4,4,29},{4,4,45},{4,4,52},{4,4,36},{4,4,57},{3,4,171},{7,2,52},{3,4,171},{4,4,20},{4,4,20},{4,4,20},{4,4,36},{4,4,32},{4,4,48},{4,4,48},{4,4,201},{4,4,180},{3,4,267},{4,4,4},{4,4,4},{4,4,4},{4,4,20},{5,2,16},
+{4,4,32},{4,4,32},{3,4,146},{7,2,16},{3,4,146},{6,1,20},{4,4,4},{4,4,25},{4,4,41},{6,1,20},{4,4,20},{4,4,41},{0,4,146},{4,4,20},{0,4,146},{4,0,20},{4,0,20},{4,0,20},{4,0,20},{4,4,32},{4,4,32},{4,4,32},{4,4,80},{3,4,146},{3,4,146},{4,5,142},{4,5,262},{4,4,189},{4,4,141},{4,5,123},{4,4,148},{4,4,57},
+{4,4,34},{4,4,120},{4,4,22},{4,5,126},{4,5,246},{4,4,173},{4,4,125},{5,3,52},{4,4,132},{4,4,41},{4,4,18},{6,3,52},{4,4,18},{4,5,141},{4,5,141},{4,5,141},{4,4,132},{4,4,96},{4,4,48},{4,4,48},{4,4,25},{4,4,20},{4,4,13},{4,5,125},{4,5,125},{4,5,125},{4,4,116},{6,1,16},{4,4,32},{4,4,32},{4,4,9},{6,3,16},
+{4,4,9},{7,0,26},{4,5,146},{4,4,73},{4,4,25},{7,0,26},{3,5,26},{4,4,25},{0,4,18},{3,5,26},{0,4,18},{4,0,116},{4,0,116},{4,0,116},{4,0,116},{4,4,32},{4,4,32},{4,4,32},{4,4,16},{4,4,4},{4,4,4},{4,5,558},{4,5,486},{4,4,845},{4,4,733},{4,5,235},{4,5,235},{4,4,553},{4,4,354},{5,4,276},{4,4,246},{5,4,282},
+{5,4,306},{5,4,402},{5,4,378},{6,2,51},{4,5,91},{5,4,203},{5,4,171},{5,4,51},{5,4,171},{4,5,477},{4,5,477},{4,5,477},{4,5,549},{4,5,154},{4,5,226},{4,5,226},{4,4,233},{3,5,235},{4,4,125},{5,4,281},{5,4,281},{5,4,281},{5,4,257},{7,0,10},{5,4,82},{5,4,82},{5,4,50},{3,5,10},{5,4,50},{6,2,26},{4,5,18},{5,4,146},
+{5,4,122},{6,2,26},{7,3,26},{5,4,122},{0,4,146},{7,3,26},{0,4,146},{4,0,468},{4,0,468},{4,0,468},{4,0,468},{4,5,145},{4,5,145},{4,5,145},{4,4,208},{4,4,100},{4,4,100},{5,5,308},{5,5,348},{5,5,495},{5,5,583},{5,4,285},{5,4,429},{5,4,633},{5,4,781},{4,5,56},{4,5,616},{5,5,139},{5,5,179},{5,5,326},{5,5,414},{7,1,52},
+{4,5,100},{4,5,260},{5,4,612},{4,5,52},{5,4,612},{5,4,234},{5,4,234},{5,4,234},{5,4,282},{5,4,185},{5,4,233},{5,4,233},{5,4,381},{4,5,20},{5,4,248},{5,4,65},{5,4,65},{5,4,65},{5,4,113},{7,1,16},{5,4,64},{5,4,64},{5,4,212},{7,3,16},{5,4,212},{6,3,26},{5,5,130},{5,5,277},{4,5,196},{6,3,26},{6,4,26},{4,5,196},
+{0,4,596},{6,4,26},{0,4,596},{5,0,218},{5,0,218},{5,0,218},{5,0,218},{5,4,169},{5,4,169},{5,4,169},{5,4,185},{4,5,20},{4,5,20},{5,5,52},{5,5,28},{5,5,63},{5,5,87},{5,5,76},{5,5,76},{5,5,111},{5,5,286},{5,5,228},{4,5,296},{5,5,27},{5,5,3},{5,5,38},{5,5,62},{5,5,51},{5,5,51},{5,5,86},{4,5,196},{3,6,51},
+{4,5,196},{5,5,27},{5,5,27},{5,5,27},{5,5,51},{5,5,51},{5,5,75},{5,5,75},{5,5,250},{4,5,180},{4,5,260},{5,5,2},{5,5,2},{5,5,2},{5,5,26},{6,3,10},{5,5,50},{5,5,50},{4,5,160},{6,4,10},{4,5,160},{7,2,26},{5,5,2},{5,5,37},{5,5,61},{7,2,26},{5,5,26},{5,5,61},{0,5,180},{5,5,26},{0,5,180},{5,0,26},
+{5,0,26},{5,0,26},{5,0,26},{5,5,50},{5,5,50},{5,5,50},{5,5,106},{4,5,116},{4,5,116},{5,6,126},{5,5,220},{5,5,143},{5,5,103},{5,6,145},{5,5,108},{5,5,31},{5,5,30},{5,5,100},{5,5,30},{5,6,117},{5,5,211},{5,5,134},{5,5,94},{6,4,51},{5,5,99},{5,5,22},{5,5,21},{7,4,51},{5,5,21},{5,6,126},{5,6,126},{5,6,126},
+{5,5,99},{5,5,67},{5,5,27},{5,5,27},{5,5,26},{5,5,19},{5,5,26},{5,6,117},{5,6,117},{5,6,117},{5,5,90},{7,2,10},{5,5,18},{5,5,18},{5,5,17},{5,5,10},{5,5,17},{6,4,26},{5,5,130},{5,5,53},{5,5,13},{6,4,26},{7,4,26},{5,5,13},{0,5,20},{7,4,26},{0,5,20},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{5,5,18},
+{5,5,18},{5,5,18},{5,5,10},{5,5,10},{5,5,10},{5,6,478},{5,6,430},{5,5,735},{5,5,631},{5,6,193},{5,6,241},{5,5,463},{5,5,286},{4,6,268},{5,5,190},{6,5,325},{5,6,309},{6,5,425},{6,5,393},{7,3,56},{6,5,120},{6,5,204},{6,5,152},{6,5,56},{6,5,152},{5,6,414},{5,6,414},{5,6,414},{5,6,510},{5,6,129},{5,6,225},{5,6,225},
+{5,5,186},{5,5,195},{5,5,90},{5,6,293},{5,6,293},{5,6,293},{6,5,293},{5,6,8},{6,5,104},{6,5,104},{6,5,52},{4,6,8},{6,5,52},{7,3,20},{5,6,20},{6,5,136},{6,5,104},{7,3,20},{6,5,20},{6,5,104},{0,5,116},{6,5,20},{0,5,116},{5,0,410},{5,0,410},{5,0,410},{5,0,410},{5,6,125},{5,6,125},{5,6,125},{5,5,170},{5,5,74},
+{5,5,74},{6,5,350},{6,6,424},{6,6,585},{6,5,670},{6,5,287},{6,5,415},{6,5,607},{6,5,735},{5,6,52},{6,5,588},{6,5,154},{6,6,228},{6,6,389},{6,5,474},{5,7,51},{5,6,75},{5,6,275},{6,5,539},{5,6,51},{6,5,539},{6,5,269},{6,5,269},{6,5,269},{6,5,309},{6,5,206},{6,5,246},{6,5,246},{6,5,374},{5,6,27},{6,5,227},{6,5,73},
+{6,5,73},{6,5,73},{6,5,113},{6,5,10},{6,5,50},{6,5,50},{6,5,178},{3,7,10},{6,5,178},{5,7,26},{5,6,146},{6,6,325},{5,6,226},{5,7,26},{5,6,26},{5,6,226},{0,5,530},{5,6,26},{0,5,530},{6,0,260},{6,0,260},{6,0,260},{6,0,260},{6,5,197},{6,5,197},{6,5,197},{6,5,205},{5,6,26},{5,6,26},{6,6,56},{6,6,40},{6,6,89},
+{6,6,121},{6,6,92},{6,6,108},{6,6,157},{6,6,354},{6,6,280},{5,6,308},{6,6,20},{6,6,4},{6,6,53},{6,6,85},{6,6,56},{6,6,72},{6,6,121},{5,6,227},{4,7,56},{5,6,227},{6,6,40},{6,6,40},{6,6,40},{6,6,72},{6,6,76},{6,6,108},{6,6,108},{6,6,305},{5,6,139},{5,6,259},{6,6,4},{6,6,4},{6,6,4},{6,6,36},{7,4,8},
+{6,6,72},{6,6,72},{5,6,178},{7,5,8},{5,6,178},{6,6,20},{6,6,4},{6,6,53},{6,6,85},{6,6,20},{4,7,20},{6,6,85},{0,6,218},{4,7,20},{0,6,218},{6,0,36},{6,0,36},{6,0,36},{6,0,36},{6,6,72},{6,6,72},{6,6,72},{6,6,136},{5,6,90},{5,6,90},{6,7,118},{6,6,168},{6,6,105},{6,6,73},{6,7,175},{6,6,76},{6,6,13},
+{6,6,34},{6,6,88},{6,6,46},{6,7,114},{6,6,164},{6,6,101},{6,6,69},{7,5,56},{6,6,72},{6,6,9},{6,6,30},{6,6,72},{6,6,30},{6,6,104},{6,6,104},{6,6,104},{6,6,72},{6,6,44},{6,6,12},{6,6,12},{6,6,33},{6,6,24},{6,6,45},{6,6,100},{6,6,100},{6,6,100},{6,6,68},{7,5,40},{6,6,8},{6,6,8},{6,6,29},{6,6,8},
+{6,6,29},{7,5,20},{6,6,100},{6,6,37},{6,6,5},{7,5,20},{5,7,50},{6,6,5},{0,6,26},{5,7,50},{0,6,26},{6,0,68},{6,0,68},{6,0,68},{6,0,68},{6,6,8},{6,6,8},{6,6,8},{6,6,8},{6,6,20},{6,6,20},{6,7,406},{6,7,382},{6,6,633},{6,6,537},{6,7,159},{6,7,255},{6,6,381},{6,6,226},{5,7,228},{6,6,142},{6,7,306},
+{6,7,282},{7,6,454},{7,6,414},{6,7,59},{7,6,139},{7,6,211},{6,6,126},{5,7,59},{6,6,126},{6,7,357},{6,7,357},{6,7,357},{6,6,456},{6,7,110},{6,7,230},{6,7,230},{6,6,145},{6,6,152},{6,6,61},{6,7,257},{6,7,257},{6,7,257},{7,6,333},{6,7,10},{7,6,130},{7,6,130},{6,6,45},{5,7,10},{6,6,45},{7,6,50},{6,7,26},{7,6,130},
+{7,6,90},{7,6,50},{7,6,18},{7,6,90},{0,6,90},{7,6,18},{0,6,90},{6,0,356},{6,0,356},{6,0,356},{6,0,356},{6,7,109},{6,7,109},{6,7,109},{6,6,136},{6,6,52},{6,6,52},{7,6,374},{7,6,454},{7,6,634},{7,6,666},{7,6,297},{7,6,409},{7,6,589},{7,6,697},{6,7,56},{7,6,536},{7,6,149},{7,6,229},{7,6,409},{7,6,441},{7,6,72},
+{6,7,56},{6,7,296},{7,6,472},{6,7,56},{7,6,472},{7,6,310},{7,6,310},{7,6,310},{7,6,342},{7,6,233},{7,6,265},{7,6,265},{7,6,373},{6,7,40},{7,6,212},{7,6,85},{7,6,85},{7,6,85},{7,6,117},{7,6,8},{7,6,40},{7,6,40},{7,6,148},{7,6,40},{7,6,148},{7,6,68},{6,7,116},{7,6,328},{6,7,260},{7,6,68},{6,7,20},{6,7,260},
+{0,6,468},{6,7,20},{0,6,468},{7,0,306},{7,0,306},{7,0,306},{7,0,306},{7,6,229},{7,6,229},{7,6,229},{7,6,229},{6,7,36},{6,7,36},{7,7,68},{7,7,60},{7,7,123},{7,7,163},{7,7,116},{7,7,148},{7,7,211},{7,7,430},{6,7,248},{6,7,328},{7,7,19},{7,7,11},{7,7,74},{7,7,114},{7,7,67},{7,7,99},{7,7,162},{6,7,264},{7,7,171},
+{6,7,264},{7,7,59},{7,7,59},{7,7,59},{7,7,99},{7,7,107},{7,7,147},{7,7,147},{7,7,366},{6,7,104},{6,7,264},{7,7,10},{7,7,10},{7,7,10},{7,7,50},{7,7,58},{7,7,98},{7,7,98},{6,7,200},{6,7,40},{6,7,200},{7,7,18},{7,7,10},{7,7,73},{6,7,100},{7,7,18},{7,7,50},{6,7,100},{0,7,260},{7,7,50},{0,7,260},{7,0,50},
+{7,0,50},{7,0,50},{7,0,50},{7,6,85},{7,6,85},{7,6,85},{7,6,149},{6,7,68},{6,7,68},{7,7,196},{7,7,124},{7,7,75},{7,7,51},{7,7,148},{7,7,52},{7,7,3},{7,7,46},{7,7,84},{7,7,70},{7,7,195},{7,7,123},{7,7,74},{7,7,50},{7,7,147},{7,7,51},{7,7,2},{7,7,45},{7,7,59},{7,7,45},{7,7,75},{7,7,75},{7,7,75},
+{7,7,51},{7,7,27},{7,7,3},{7,7,3},{7,7,46},{7,7,35},{7,7,70},{7,7,74},{7,7,74},{7,7,74},{7,7,50},{7,7,26},{7,7,2},{7,7,2},{7,7,45},{7,7,10},{7,7,45},{7,7,146},{7,7,74},{7,7,25},{7,7,1},{7,7,146},{7,7,50},{7,7,1},{0,7,36},{7,7,50},{0,7,36},{7,0,50},{7,0,50},{7,0,50},{7,0,50},{7,7,2},
+{7,7,2},{7,7,2},{7,7,10},{7,7,34},{7,7,34},{7,7,548},{7,7,476},{7,7,427},{7,7,355},{7,7,404},{7,7,260},{7,7,211},{7,7,106},{7,7,132},{7,7,34},{7,7,467},{7,7,395},{7,7,346},{7,7,274},{7,7,323},{7,7,179},{7,7,130},{7,7,25},{7,7,123},{7,7,25},{7,7,427},{7,7,427},{7,7,427},{7,7,355},{7,7,283},{7,7,211},{7,7,211},
+{7,7,106},{7,7,83},{7,7,34},{7,7,346},{7,7,346},{7,7,346},{7,7,274},{7,7,202},{7,7,130},{7,7,130},{7,7,25},{7,7,74},{7,7,25},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{7,0,306},{7,0,306},{7,0,306},{7,0,306},{7,7,162},{7,7,162},{7,7,162},{7,7,106},{7,7,34},
+{7,7,34},{0,0,122},{0,0,50},{0,0,1},{0,0,25},{0,0,158},{0,0,110},{0,0,61},{0,0,244},{0,0,210},{0,0,280},{0,0,122},{0,0,50},{0,0,1},{0,0,25},{0,0,158},{0,0,110},{0,0,61},{0,0,244},{0,0,174},{0,0,244},{0,0,1},{0,0,1},{0,0,1},{0,0,25},{0,0,37},{0,0,61},{0,0,61},{0,0,244},{0,0,161},{0,0,280},{0,0,1},
+{0,0,1},{0,0,1},{0,0,25},{0,0,37},{0,0,61},{0,0,61},{0,0,244},{0,0,125},{0,0,244},{0,0,122},{0,0,50},{0,0,1},{0,0,25},{0,0,122},{0,0,74},{0,0,25},{0,0,144},{0,0,74},{0,0,144},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,1,81},{0,1,81},{0,0,122},
+{0,0,82},{0,1,328},{0,0,243},{0,0,82},{0,0,129},{0,0,319},{0,0,165},{0,1,81},{0,1,81},{0,0,122},{0,0,82},{0,1,328},{0,0,243},{0,0,82},{0,0,129},{0,0,283},{0,0,129},{0,1,45},{0,1,45},{0,1,45},{0,0,18},{0,0,58},{0,0,18},{0,0,18},{0,0,65},{0,0,94},{0,0,101},{0,1,45},{0,1,45},{0,1,45},{0,0,18},{0,0,58},
+{0,0,18},{0,0,18},{0,0,65},{0,0,58},{0,0,65},{0,1,72},{0,1,72},{0,0,113},{0,0,73},{0,1,72},{1,0,104},{0,0,73},{0,0,80},{1,0,104},{0,0,80},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,49},{0,0,85},{0,0,85},{0,2,225},{0,1,129},{0,1,449},{0,0,498},{0,1,264},{0,1,168},{0,0,402},
+{0,0,273},{0,0,687},{0,0,309},{0,2,225},{0,1,129},{0,1,449},{0,0,498},{0,1,264},{0,1,168},{0,0,402},{0,0,273},{1,0,248},{0,0,273},{0,1,125},{0,1,125},{0,1,125},{0,1,221},{0,1,68},{0,0,146},{0,0,146},{0,0,17},{0,0,158},{0,0,53},{0,1,125},{0,1,125},{0,1,125},{0,1,221},{0,1,68},{0,0,146},{0,0,146},{0,0,17},{0,0,122},
+{0,0,17},{1,0,72},{0,1,8},{1,0,292},{1,0,260},{1,0,72},{1,0,104},{1,0,260},{0,0,272},{1,0,104},{0,0,272},{0,0,121},{0,0,121},{0,0,121},{0,0,121},{0,0,25},{0,0,25},{0,0,25},{0,0,1},{0,0,37},{0,0,37},{0,2,514},{0,2,558},{0,1,610},{0,1,514},{0,2,297},{0,1,153},{0,1,153},{0,1,777},{0,1,392},{0,0,802},{1,1,347},
+{1,1,355},{1,1,446},{0,1,465},{0,2,248},{0,1,104},{0,1,104},{0,1,728},{0,1,248},{0,1,728},{0,2,414},{0,2,414},{0,2,414},{0,1,414},{0,1,149},{0,1,53},{0,1,53},{0,0,274},{0,1,292},{0,0,226},{1,0,229},{1,0,229},{1,0,229},{1,0,261},{1,0,68},{0,1,4},{0,1,4},{1,0,160},{1,0,52},{1,0,160},{0,2,104},{1,1,130},{0,1,200},
+{0,1,104},{0,2,104},{2,0,74},{0,1,104},{0,1,584},{2,0,74},{0,1,584},{0,0,410},{0,0,410},{0,0,410},{0,0,410},{0,1,49},{0,1,49},{0,1,49},{0,0,130},{0,0,82},{0,0,82},{1,1,464},{1,1,400},{1,1,365},{1,1,397},{1,1,572},{0,2,499},{0,1,387},{0,1,435},{0,1,428},{0,1,188},{1,1,140},{1,1,76},{1,1,41},{1,1,73},{1,1,248},
+{1,1,216},{0,1,131},{0,1,179},{2,0,264},{0,1,179},{1,1,364},{1,1,364},{1,1,364},{1,1,396},{0,2,314},{0,1,386},{0,1,386},{0,1,434},{0,1,67},{0,1,187},{1,1,40},{1,1,40},{1,1,40},{1,1,72},{0,2,58},{0,1,130},{0,1,130},{0,1,178},{0,1,58},{0,1,178},{0,3,72},{1,1,40},{1,1,5},{1,1,37},{0,3,72},{1,1,72},{1,1,37},
+{0,1,170},{1,1,72},{0,1,170},{1,0,360},{1,0,360},{1,0,360},{1,0,360},{0,2,265},{0,2,265},{0,2,265},{0,1,265},{0,1,18},{0,1,18},{1,2,178},{1,2,202},{1,1,189},{1,1,157},{1,2,463},{1,1,316},{1,1,169},{1,1,238},{0,2,412},{0,1,124},{1,2,78},{1,2,102},{1,1,89},{1,1,57},{2,0,248},{0,2,99},{1,1,69},{0,1,99},{3,0,248},
+{0,1,99},{1,1,140},{1,1,140},{1,1,140},{1,1,108},{1,1,152},{1,1,120},{1,1,120},{1,1,189},{0,1,275},{0,1,75},{1,1,40},{1,1,40},{1,1,40},{1,1,8},{1,1,52},{1,1,20},{1,1,20},{0,1,50},{1,1,68},{0,1,50},{1,2,74},{1,2,98},{1,1,85},{1,1,53},{1,2,74},{0,2,74},{1,1,53},{0,1,74},{0,2,74},{0,1,74},{1,0,104},
+{1,0,104},{1,0,104},{1,0,104},{1,1,116},{1,1,116},{1,1,116},{1,1,164},{0,1,50},{0,1,50},{1,3,226},{1,2,106},{1,2,466},{1,1,429},{1,2,255},{1,2,207},{1,1,345},{1,1,238},{0,2,252},{1,1,298},{1,3,222},{1,2,102},{1,2,462},{1,1,425},{1,2,251},{1,2,203},{1,1,341},{1,1,234},{0,2,251},{1,1,234},{1,2,105},{1,2,105},{1,2,105},
+{1,1,204},{1,2,86},{1,1,120},{1,1,120},{1,1,13},{0,2,83},{1,1,73},{1,2,101},{1,2,101},{1,2,101},{1,1,200},{2,0,52},{1,1,116},{1,1,116},{1,1,9},{3,0,52},{1,1,9},{2,1,74},{1,2,2},{2,1,274},{2,1,234},{2,1,74},{4,0,74},{2,1,234},{0,1,234},{4,0,74},{0,1,234},{1,0,104},{1,0,104},{1,0,104},{1,0,104},{1,1,20},
+{1,1,20},{1,1,20},{1,1,4},{1,1,64},{1,1,64},{1,3,450},{1,2,522},{1,2,562},{1,2,490},{1,3,295},{1,2,127},{1,2,167},{1,1,750},{1,2,428},{1,1,714},{2,2,400},{2,2,416},{2,2,521},{1,2,454},{2,1,251},{1,2,91},{1,2,131},{0,2,651},{4,0,251},{0,2,651},{1,3,369},{1,3,369},{1,3,369},{1,2,369},{1,2,118},{1,2,46},{1,2,46},
+{1,1,221},{0,2,163},{1,1,185},{2,1,257},{2,1,257},{2,1,257},{2,1,281},{0,4,50},{1,2,10},{1,2,10},{2,1,146},{2,1,50},{2,1,146},{3,0,80},{2,2,160},{1,2,202},{1,2,130},{3,0,80},{3,1,80},{1,2,130},{0,1,650},{3,1,80},{0,1,650},{1,0,360},{1,0,360},{1,0,360},{1,0,360},{1,2,37},{1,2,37},{1,2,37},{1,1,100},{1,1,64},
+{1,1,64},{2,2,500},{2,2,444},{2,2,423},{2,2,463},{1,4,588},{1,3,513},{1,2,329},{1,2,441},{0,3,284},{1,2,232},{2,2,139},{2,2,83},{2,2,62},{2,2,102},{3,0,251},{2,2,243},{1,2,104},{1,2,216},{3,1,251},{1,2,216},{2,2,419},{2,2,419},{2,2,419},{2,2,459},{1,3,277},{1,2,325},{1,2,325},{1,2,437},{1,2,68},{1,2,228},{2,2,58},
+{2,2,58},{2,2,58},{2,2,98},{1,3,52},{1,2,100},{1,2,100},{1,2,212},{1,2,52},{1,2,212},{1,4,74},{2,2,34},{2,2,13},{1,2,40},{1,4,74},{2,2,74},{1,2,40},{0,2,200},{2,2,74},{0,2,200},{2,0,410},{2,0,410},{2,0,410},{2,0,410},{1,3,241},{1,3,241},{1,3,241},{1,2,241},{1,2,32},{1,2,32},{2,3,202},{2,3,250},{2,2,183},
+{2,2,159},{2,2,460},{2,2,316},{2,2,183},{2,2,274},{1,3,468},{1,2,104},{2,3,81},{2,3,129},{2,2,62},{2,2,38},{1,4,251},{1,3,96},{2,2,62},{1,2,88},{2,2,251},{1,2,88},{2,2,147},{2,2,147},{2,2,147},{2,2,123},{2,2,171},{2,2,147},{2,2,147},{2,2,238},{0,3,219},{1,2,68},{2,2,26},{2,2,26},{2,2,26},{2,2,2},{2,2,50},
+{2,2,26},{2,2,26},{1,2,52},{5,0,50},{1,2,52},{2,3,80},{2,3,128},{2,2,61},{2,2,37},{2,3,80},{6,0,80},{2,2,37},{0,2,72},{6,0,80},{0,2,72},{2,0,122},{2,0,122},{2,0,122},{2,0,122},{2,2,146},{2,2,146},{2,2,146},{2,2,202},{1,2,32},{1,2,32},{2,3,234},{2,3,90},{2,2,455},{2,2,367},{2,3,253},{2,3,253},{2,2,295},
+{2,2,210},{1,3,244},{2,2,282},{2,3,225},{2,3,81},{2,2,446},{2,2,358},{2,3,244},{2,3,244},{2,2,286},{2,2,201},{6,0,244},{2,2,201},{2,3,90},{2,3,90},{2,3,90},{2,2,171},{2,3,109},{2,2,99},{2,2,99},{2,2,14},{1,3,100},{2,2,86},{2,3,81},{2,3,81},{2,3,81},{2,2,162},{3,1,50},{2,2,90},{2,2,90},{2,2,5},{4,1,50},
+{2,2,5},{4,0,80},{2,3,0},{3,2,260},{3,2,212},{4,0,80},{5,1,80},{3,2,212},{0,2,200},{5,1,80},{0,2,200},{2,0,90},{2,0,90},{2,0,90},{2,0,90},{2,2,18},{2,2,18},{2,2,18},{2,2,10},{2,2,82},{2,2,82},{2,4,394},{2,3,442},{2,3,522},{2,3,474},{2,4,301},{2,3,109},{2,3,189},{2,2,658},{2,3,472},{2,2,634},{2,4,369},
+{2,3,417},{2,3,497},{2,3,449},{3,2,244},{2,3,84},{2,3,164},{3,2,620},{5,1,244},{3,2,620},{2,4,330},{2,4,330},{2,4,330},{2,3,330},{2,3,93},{2,3,45},{2,3,45},{2,2,174},{1,3,132},{2,2,150},{3,2,289},{3,2,289},{3,2,289},{3,2,305},{4,0,52},{2,3,20},{2,3,20},{3,2,136},{3,2,52},{3,2,136},{2,4,80},{2,3,128},{2,3,208},
+{2,3,160},{2,4,80},{7,0,80},{2,3,160},{0,2,584},{7,0,80},{0,2,584},{2,0,314},{2,0,314},{2,0,314},{2,0,314},{2,3,29},{2,3,29},{2,3,29},{2,2,74},{2,2,50},{2,2,50},{3,3,544},{3,3,496},{3,3,489},{3,3,537},{2,4,535},{2,4,535},{2,3,279},{2,3,455},{1,4,292},{2,3,284},{3,3,144},{3,3,96},{3,3,89},{3,3,137},{4,1,244},
+{3,3,276},{2,3,83},{2,3,259},{4,2,244},{2,3,259},{3,3,480},{3,3,480},{3,3,480},{3,3,528},{2,4,246},{2,3,270},{2,3,270},{2,3,446},{2,3,75},{2,3,275},{3,3,80},{3,3,80},{3,3,80},{3,3,128},{2,4,50},{2,3,74},{2,3,74},{2,3,250},{7,0,50},{2,3,250},{5,0,80},{3,3,32},{3,3,25},{2,3,34},{5,0,80},{6,1,80},{2,3,34},
+{0,3,234},{6,1,80},{0,3,234},{3,0,464},{3,0,464},{3,0,464},{3,0,464},{2,4,221},{2,4,221},{2,4,221},{2,3,221},{2,3,50},{2,3,50},{3,4,234},{3,3,304},{3,3,185},{3,3,169},{3,3,452},{3,3,324},{3,3,205},{3,3,318},{1,4,452},{2,3,92},{3,4,90},{3,3,160},{3,3,41},{3,3,25},{5,0,244},{2,4,99},{3,3,61},{2,3,83},{3,3,244},
+{2,3,83},{3,3,160},{3,3,160},{3,3,160},{3,3,144},{3,3,196},{3,3,180},{3,3,180},{3,3,293},{2,3,187},{2,3,67},{3,3,16},{3,3,16},{3,3,16},{3,3,0},{3,3,52},{3,3,36},{3,3,36},{2,3,58},{6,1,52},{2,3,58},{4,2,80},{3,3,160},{3,3,41},{3,3,25},{4,2,80},{5,2,80},{3,3,25},{0,3,74},{5,2,80},{0,3,74},{3,0,144},
+{3,0,144},{3,0,144},{3,0,144},{3,3,180},{3,3,180},{3,3,180},{3,3,244},{2,3,18},{2,3,18},{3,4,202},{3,4,82},{3,3,393},{3,3,313},{3,4,259},{3,4,307},{3,3,253},{3,3,190},{2,4,244},{3,3,274},{3,4,186},{3,4,66},{3,3,377},{3,3,297},{3,4,243},{2,4,243},{3,3,237},{3,3,174},{7,1,243},{3,3,174},{3,4,81},{3,4,81},{3,4,81},
+{3,3,144},{3,4,138},{3,3,84},{3,3,84},{3,3,21},{2,4,123},{3,3,105},{3,4,65},{3,4,65},{3,4,65},{3,3,128},{4,2,52},{3,3,68},{3,3,68},{3,3,5},{5,2,52},{3,3,5},{5,1,74},{3,4,2},{4,3,250},{4,3,194},{5,1,74},{4,3,74},{4,3,194},{0,3,170},{4,3,74},{0,3,170},{3,0,80},{3,0,80},{3,0,80},{3,0,80},{3,3,20},
+{3,3,20},{3,3,20},{3,3,20},{3,3,104},{3,3,104},{3,5,346},{3,4,370},{3,4,490},{3,4,466},{3,5,315},{3,4,99},{3,4,219},{3,3,574},{2,4,468},{3,3,562},{3,5,330},{3,4,354},{3,4,474},{3,4,450},{4,3,243},{3,4,83},{3,4,203},{3,3,558},{6,2,243},{3,3,558},{3,5,297},{3,5,297},{3,5,297},{3,4,297},{3,4,74},{3,4,50},{3,4,50},
+{3,3,133},{2,4,107},{3,3,121},{3,5,281},{3,5,281},{3,5,281},{3,4,281},{5,1,58},{3,4,34},{3,4,34},{3,3,117},{7,1,58},{3,3,117},{6,0,74},{3,4,98},{3,4,218},{3,4,194},{6,0,74},{3,4,74},{3,4,194},{0,3,522},{3,4,74},{0,3,522},{3,0,272},{3,0,272},{3,0,272},{3,0,272},{3,4,25},{3,4,25},{3,4,25},{3,3,52},{3,3,40},
+{3,3,40},{4,4,596},{4,4,556},{4,4,563},{4,4,619},{3,5,477},{3,4,477},{3,4,237},{3,4,477},{2,5,308},{3,4,344},{4,4,155},{4,4,115},{4,4,122},{4,4,178},{5,2,243},{2,5,299},{3,4,68},{2,4,308},{5,3,243},{2,4,308},{4,4,547},{4,4,547},{4,4,547},{4,4,603},{3,5,221},{3,4,221},{3,4,221},{3,4,461},{3,4,88},{3,4,328},{4,4,106},
+{4,4,106},{4,4,106},{4,4,162},{6,0,52},{3,4,52},{3,4,52},{2,4,292},{3,4,52},{2,4,292},{4,4,74},{4,4,34},{4,4,41},{3,4,32},{4,4,74},{7,2,74},{3,4,32},{0,4,272},{7,2,74},{0,4,272},{4,0,522},{4,0,522},{4,0,522},{4,0,522},{3,4,205},{3,4,205},{3,4,205},{3,4,205},{3,4,72},{3,4,72},{4,5,274},{4,4,300},{4,4,195},
+{4,4,187},{4,4,452},{4,4,340},{4,4,235},{4,4,370},{2,5,404},{3,4,88},{4,5,105},{4,4,131},{4,4,26},{4,4,18},{6,1,243},{3,5,108},{4,4,66},{3,4,84},{4,4,243},{3,4,84},{4,4,179},{4,4,179},{4,4,179},{4,4,171},{4,4,227},{4,4,219},{4,4,219},{4,4,354},{3,4,152},{3,4,72},{4,4,10},{4,4,10},{4,4,10},{4,4,2},{5,2,58},
+{4,4,50},{4,4,50},{3,4,68},{7,2,58},{3,4,68},{5,3,74},{4,4,130},{4,4,25},{4,4,17},{5,3,74},{6,3,74},{4,4,17},{0,4,80},{6,3,74},{0,4,80},{4,0,170},{4,0,170},{4,0,170},{4,0,170},{4,3,205},{4,3,205},{4,3,205},{4,3,269},{3,4,8},{3,4,8},{4,5,178},{4,5,82},{4,4,339},{4,4,267},{4,5,273},{4,5,369},{4,4,219},
+{4,4,178},{3,5,252},{4,4,274},{4,5,153},{4,5,57},{4,4,314},{4,4,242},{7,0,248},{3,5,204},{4,4,194},{4,4,153},{3,5,248},{4,4,153},{4,5,78},{4,5,78},{4,5,78},{4,4,123},{4,4,147},{4,4,75},{4,4,75},{4,4,34},{3,5,152},{4,4,130},{4,5,53},{4,5,53},{4,5,53},{4,4,98},{6,1,58},{4,4,50},{4,4,50},{4,4,9},{6,3,58},
+{4,4,9},{6,2,72},{4,5,8},{5,4,244},{5,4,180},{6,2,72},{5,4,72},{5,4,180},{0,4,144},{5,4,72},{0,4,144},{4,0,74},{4,0,74},{4,0,74},{4,0,74},{4,4,26},{4,4,26},{4,4,26},{4,4,34},{4,4,130},{4,4,130},{4,6,306},{4,5,306},{4,5,466},{4,5,466},{4,6,337},{4,5,97},{4,5,257},{4,4,498},{3,5,412},{4,4,498},{4,6,297},
+{4,5,297},{4,5,457},{4,5,457},{5,4,248},{4,5,88},{4,5,248},{4,4,489},{7,3,248},{4,4,489},{4,5,270},{4,5,270},{4,5,270},{4,5,270},{4,5,61},{4,5,61},{4,5,61},{4,4,98},{3,5,88},{4,4,98},{4,5,261},{4,5,261},{4,5,261},{4,5,261},{7,0,52},{4,5,52},{4,5,52},{4,4,89},{3,5,52},{4,4,89},{7,1,72},{4,5,72},{4,5,232},
+{3,5,232},{7,1,72},{4,5,72},{3,5,232},{0,4,464},{4,5,72},{0,4,464},{4,0,234},{4,0,234},{4,0,234},{4,0,234},{4,5,25},{4,5,25},{4,5,25},{4,4,34},{4,4,34},{4,4,34},{5,5,656},{5,5,624},{5,5,645},{5,5,709},{4,6,427},{4,5,403},{4,5,203},{4,5,507},{4,5,332},{4,5,412},{5,5,172},{5,5,140},{5,5,161},{5,5,225},{6,3,248},
+{4,5,259},{4,5,59},{3,5,339},{6,4,248},{3,5,339},{5,5,620},{5,5,620},{5,5,620},{5,5,684},{4,6,202},{4,5,178},{4,5,178},{4,5,482},{4,5,107},{4,5,387},{5,5,136},{5,5,136},{5,5,136},{5,5,200},{7,1,58},{4,5,34},{4,5,34},{5,4,290},{7,3,58},{5,4,290},{5,5,72},{5,5,40},{5,5,61},{4,5,34},{5,5,72},{3,6,72},{4,5,34},
+{0,5,314},{3,6,72},{0,5,314},{5,0,584},{5,0,584},{5,0,584},{5,0,584},{4,5,169},{4,5,169},{4,5,169},{4,5,193},{4,5,98},{4,5,98},{5,6,322},{5,5,304},{5,5,213},{5,5,213},{5,5,460},{5,5,364},{5,5,273},{5,5,430},{3,6,364},{4,5,92},{5,6,126},{5,5,108},{5,5,17},{5,5,17},{7,2,248},{4,6,123},{5,5,77},{4,5,91},{5,5,248},
+{4,5,91},{5,5,204},{5,5,204},{5,5,204},{5,5,204},{5,5,264},{5,5,264},{5,5,264},{5,5,421},{4,5,123},{4,5,83},{5,5,8},{5,5,8},{5,5,8},{5,5,8},{6,3,52},{5,5,68},{5,5,68},{4,5,82},{6,4,52},{4,5,82},{6,4,72},{5,5,104},{5,5,13},{5,5,13},{6,4,72},{7,4,72},{5,5,13},{0,5,90},{7,4,72},{0,5,90},{5,0,200},
+{5,0,200},{5,0,200},{5,0,200},{5,4,221},{5,4,221},{5,4,221},{5,4,277},{4,5,2},{4,5,2},{5,6,162},{5,6,90},{5,5,293},{5,5,229},{5,6,295},{5,5,396},{5,5,193},{5,5,174},{4,6,268},{5,5,282},{5,6,126},{5,6,54},{5,5,257},{5,5,193},{5,6,259},{4,6,171},{5,5,157},{5,5,138},{4,6,259},{5,5,138},{5,6,81},{5,6,81},{5,6,81},
+{5,5,108},{5,5,136},{5,5,72},{5,5,72},{5,5,53},{4,6,187},{5,5,161},{5,6,45},{5,6,45},{5,6,45},{5,5,72},{7,2,52},{5,5,36},{5,5,36},{5,5,17},{5,5,52},{5,5,17},{7,3,74},{5,6,18},{5,5,221},{5,5,157},{7,3,74},{6,5,74},{5,5,157},{0,5,122},{6,5,74},{0,5,122},{5,0,72},{5,0,72},{5,0,72},{5,0,72},{5,5,36},
+{5,5,36},{5,5,36},{5,5,52},{5,5,160},{5,5,160},{5,7,274},{5,6,250},{5,6,450},{5,6,474},{5,6,343},{5,6,103},{5,6,303},{5,5,430},{4,6,364},{5,5,442},{5,7,270},{5,6,246},{5,6,446},{5,6,470},{7,3,251},{5,6,99},{5,6,299},{5,5,426},{6,5,251},{5,5,426},{5,6,225},{5,6,225},{5,6,225},{5,6,249},{5,6,54},{5,6,78},{5,6,78},
+{5,5,69},{4,6,75},{5,5,81},{5,6,221},{5,6,221},{5,6,221},{5,6,245},{5,6,50},{5,6,74},{5,6,74},{5,5,65},{4,6,50},{5,5,65},{5,7,74},{5,6,50},{5,6,250},{4,6,250},{5,7,74},{5,6,74},{4,6,250},{0,5,410},{5,6,74},{0,5,410},{5,0,200},{5,0,200},{5,0,200},{5,0,200},{5,6,29},{5,6,29},{5,6,29},{5,5,20},{5,5,32},
+{5,5,32},{6,6,724},{6,6,700},{6,6,735},{5,6,690},{5,7,385},{5,6,337},{5,6,177},{5,6,545},{5,6,328},{5,6,488},{6,6,195},{6,6,171},{6,6,206},{6,6,278},{7,4,259},{5,6,216},{5,6,56},{4,6,376},{7,5,259},{4,6,376},{5,7,654},{5,7,654},{5,7,654},{5,6,654},{5,7,189},{5,6,141},{5,6,141},{5,6,509},{5,6,132},{5,5,450},{6,5,157},
+{6,5,157},{6,5,157},{6,5,221},{6,5,52},{5,6,20},{5,6,20},{6,5,256},{3,7,52},{6,5,256},{6,6,74},{6,6,50},{6,6,85},{5,6,40},{6,6,74},{4,7,74},{5,6,40},{0,6,360},{4,7,74},{0,6,360},{5,0,650},{5,0,650},{5,0,650},{5,0,650},{5,6,137},{5,6,137},{5,6,137},{5,6,185},{5,6,128},{5,6,128},{6,7,378},{6,6,316},{6,6,239},
+{6,6,247},{6,6,476},{6,6,396},{6,6,319},{5,6,465},{4,7,332},{5,6,104},{6,7,153},{6,6,91},{6,6,14},{6,6,22},{6,6,251},{5,7,144},{6,6,94},{5,6,104},{4,7,251},{5,6,104},{6,6,235},{6,6,235},{6,6,235},{6,6,243},{6,6,307},{6,6,315},{6,6,315},{5,6,461},{5,6,100},{5,6,100},{6,6,10},{6,6,10},{6,6,10},{6,6,18},{7,4,50},
+{6,6,90},{6,6,90},{5,6,100},{7,5,50},{5,6,100},{7,5,74},{6,6,82},{6,6,5},{6,6,13},{7,5,74},{6,6,90},{6,6,13},{0,6,104},{6,6,90},{0,6,104},{6,0,234},{6,0,234},{6,0,234},{6,0,234},{6,5,241},{6,5,241},{6,5,241},{6,5,289},{5,6,0},{5,6,0},{6,7,154},{6,7,106},{6,6,255},{6,6,199},{6,7,325},{6,6,364},{6,6,175},
+{6,6,178},{5,7,292},{5,6,232},{6,7,105},{6,7,57},{6,6,206},{6,6,150},{7,5,251},{5,7,144},{6,6,126},{6,6,129},{5,7,276},{6,6,129},{6,7,90},{6,7,90},{6,7,90},{6,6,99},{6,6,131},{6,6,75},{6,6,75},{6,6,78},{6,6,219},{5,6,132},{6,7,41},{6,7,41},{6,7,41},{6,6,50},{7,5,82},{6,6,26},{6,6,26},{6,6,29},{6,6,50},
+{6,6,29},{6,7,80},{6,7,32},{6,6,181},{6,6,125},{6,7,80},{7,6,80},{6,6,125},{0,6,104},{7,6,80},{0,6,104},{6,0,74},{6,0,74},{6,0,74},{6,0,74},{6,6,50},{6,6,50},{6,6,50},{6,6,74},{5,6,128},{5,6,128},{6,7,442},{6,7,202},{6,7,442},{6,7,490},{6,7,309},{6,7,117},{6,7,357},{6,6,370},{5,7,324},{6,6,394},{6,7,441},
+{6,7,201},{6,7,441},{6,7,489},{7,6,276},{6,7,116},{6,7,356},{6,6,369},{7,6,244},{6,6,369},{6,7,186},{6,7,186},{6,7,186},{6,7,234},{6,7,53},{6,7,101},{6,7,101},{6,6,46},{5,7,68},{6,6,70},{6,7,185},{6,7,185},{6,7,185},{6,7,233},{6,7,52},{6,7,100},{6,7,100},{6,6,45},{5,7,52},{6,6,45},{7,6,80},{6,7,32},{6,7,272},
+{5,7,272},{7,6,80},{6,7,80},{5,7,272},{0,6,360},{6,7,80},{0,6,360},{6,0,170},{6,0,170},{6,0,170},{6,0,170},{6,7,37},{6,7,37},{6,7,37},{6,6,10},{6,6,34},{6,6,34},{7,7,800},{7,7,784},{6,7,802},{6,7,634},{6,7,903},{6,7,279},{6,7,159},{6,7,591},{6,7,332},{6,7,572},{7,7,224},{7,7,208},{7,7,257},{7,7,337},{7,6,339},
+{6,7,179},{6,7,59},{5,7,419},{6,7,251},{5,7,419},{7,6,745},{7,6,745},{7,6,745},{6,7,585},{6,7,278},{6,7,110},{6,7,110},{6,6,469},{6,7,163},{6,6,385},{7,6,169},{7,6,169},{7,6,169},{7,6,225},{7,6,50},{6,7,10},{6,7,10},{7,6,226},{7,6,82},{7,6,226},{7,7,80},{7,7,64},{7,7,113},{6,7,50},{7,7,80},{7,7,144},{6,7,50},
+{0,7,410},{7,7,144},{0,7,410},{6,0,584},{6,0,584},{6,0,584},{6,0,584},{6,7,109},{6,7,109},{6,7,109},{6,7,181},{6,6,160},{6,6,160},{7,7,393},{7,7,321},{7,7,272},{7,7,288},{7,7,477},{7,7,421},{7,7,372},{6,7,446},{6,7,483},{6,7,123},{7,7,137},{7,7,65},{7,7,16},{7,7,32},{7,7,221},{7,7,165},{7,7,116},{6,7,122},{7,7,261},
+{6,7,122},{7,7,272},{7,7,272},{7,7,272},{7,7,288},{7,7,356},{7,7,372},{7,7,372},{6,7,446},{6,7,83},{6,7,123},{7,7,16},{7,7,16},{7,7,16},{7,7,32},{7,7,100},{7,7,116},{7,7,116},{6,7,122},{6,7,82},{6,7,122},{7,7,121},{7,7,49},{7,7,0},{7,7,16},{7,7,121},{7,7,65},{7,7,16},{0,7,121},{7,7,65},{0,7,121},{7,0,272},
+{7,0,272},{7,0,272},{7,0,272},{7,6,265},{7,6,265},{7,6,265},{7,6,305},{6,7,2},{6,7,2},{7,7,265},{7,7,193},{7,7,144},{7,7,96},{7,7,253},{7,7,133},{7,7,84},{7,7,109},{7,7,297},{6,7,107},{7,7,201},{7,7,129},{7,7,80},{7,7,32},{7,7,189},{7,7,69},{7,7,20},{7,7,45},{7,7,101},{7,7,45},{7,7,144},{7,7,144},{7,7,144},
+{7,7,96},{7,7,132},{7,7,84},{7,7,84},{7,7,109},{7,7,248},{6,7,107},{7,7,80},{7,7,80},{7,7,80},{7,7,32},{7,7,68},{7,7,20},{7,7,20},{7,7,45},{7,7,52},{7,7,45},{7,7,185},{7,7,113},{7,7,64},{7,7,16},{7,7,185},{7,7,65},{7,7,16},{0,7,9},{7,7,65},{0,7,9},{7,0,80},{7,0,80},{7,0,80},{7,0,80},{7,7,68},
+{7,7,68},{7,7,68},{7,7,100},{6,7,98},{6,7,98},{7,7,386},{7,7,314},{7,7,265},{7,7,193},{7,7,278},{7,7,134},{7,7,85},{7,7,4},{7,7,138},{7,7,40},{7,7,386},{7,7,314},{7,7,265},{7,7,193},{7,7,278},{7,7,134},{7,7,85},{7,7,4},{7,7,102},{7,7,4},{7,7,265},{7,7,265},{7,7,265},{7,7,193},{7,7,157},{7,7,85},{7,7,85},
+{7,7,4},{7,7,89},{7,7,40},{7,7,265},{7,7,265},{7,7,265},{7,7,193},{7,7,157},{7,7,85},{7,7,85},{7,7,4},{7,7,53},{7,7,4},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{7,0,144},{7,0,144},{7,0,144},{7,0,144},{7,7,36},{7,7,36},{7,7,36},{7,7,4},{7,7,40},
+{7,7,40},{0,1,200},{0,1,104},{0,0,153},{0,0,145},{0,1,561},{0,0,398},{0,0,181},{0,0,308},{0,0,498},{0,0,344},{0,1,200},{0,1,104},{0,0,153},{0,0,145},{0,1,561},{0,0,398},{0,0,181},{0,0,308},{0,0,462},{0,0,308},{0,0,9},{0,0,9},{0,0,9},{0,0,1},{0,0,45},{0,0,37},{0,0,37},{0,0,164},{0,0,137},{0,0,200},{0,0,9},
+{0,0,9},{0,0,9},{0,0,1},{0,0,45},{0,0,37},{0,0,37},{0,0,164},{0,0,101},{0,0,164},{0,1,200},{0,1,104},{0,0,153},{0,0,145},{0,1,200},{1,0,232},{0,0,145},{0,0,208},{1,0,232},{0,0,208},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,2,232},{0,1,40},{0,1,200},
+{0,1,392},{0,1,689},{0,1,593},{0,0,485},{0,0,500},{0,0,914},{0,0,536},{0,2,232},{0,1,40},{0,1,200},{0,1,392},{0,1,689},{0,1,593},{0,0,485},{0,0,500},{1,0,761},{0,0,500},{0,1,4},{0,1,4},{0,1,4},{0,0,49},{0,0,157},{0,0,85},{0,0,85},{0,0,100},{0,0,185},{0,0,136},{0,1,4},{0,1,4},{0,1,4},{0,0,49},{0,0,157},
+{0,0,85},{0,0,85},{0,0,100},{0,0,149},{0,0,100},{1,0,200},{0,1,40},{0,1,200},{0,1,392},{1,0,200},{1,0,232},{0,1,392},{0,0,400},{1,0,232},{0,0,400},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,2,281},{0,2,149},{0,1,121},{0,1,121},{0,2,808},{0,1,376},{0,1,216},
+{0,0,857},{0,1,1169},{0,0,893},{0,2,281},{0,2,149},{0,1,121},{0,1,121},{1,0,728},{0,1,376},{0,1,216},{0,0,857},{1,0,744},{0,0,857},{0,1,85},{0,1,85},{0,1,85},{0,1,85},{0,1,180},{0,1,180},{0,1,180},{0,0,73},{0,0,270},{0,0,109},{0,1,85},{0,1,85},{0,1,85},{0,1,85},{0,1,180},{0,1,180},{0,1,180},{0,0,73},{0,0,234},
+{0,0,73},{0,2,232},{0,2,100},{0,1,72},{0,1,72},{0,2,232},{2,0,202},{0,1,72},{0,1,712},{2,0,202},{0,1,712},{0,0,49},{0,0,49},{0,0,49},{0,0,49},{0,0,1},{0,0,1},{0,0,1},{0,0,9},{0,0,45},{0,0,45},{0,3,427},{0,2,229},{0,1,425},{0,1,233},{0,2,744},{0,1,504},{0,1,24},{0,1,584},{0,1,1105},{0,1,945},{0,3,427},
+{0,2,229},{1,1,414},{0,1,233},{0,2,744},{0,1,504},{0,1,24},{0,1,584},{2,0,739},{0,1,584},{0,2,229},{0,2,229},{0,2,229},{0,1,229},{0,1,212},{0,1,20},{0,1,20},{0,0,281},{0,0,590},{0,0,317},{0,2,229},{0,2,229},{0,2,229},{0,1,229},{1,0,180},{0,1,20},{0,1,20},{0,0,281},{1,0,164},{0,0,281},{0,3,202},{0,2,4},{1,1,53},
+{0,1,8},{0,3,202},{1,1,202},{0,1,8},{0,1,328},{1,1,202},{0,1,328},{0,0,225},{0,0,225},{0,0,225},{0,0,225},{0,1,16},{0,1,16},{0,1,16},{0,0,25},{0,0,61},{0,0,61},{0,4,842},{0,3,740},{1,1,1125},{0,1,834},{0,3,744},{0,2,267},{0,1,283},{0,1,267},{0,1,1356},{0,1,476},{1,2,302},{1,2,230},{1,1,225},{1,1,225},{0,3,728},
+{0,2,251},{0,1,267},{0,1,251},{1,1,728},{0,1,251},{0,3,596},{0,3,596},{0,3,596},{0,1,713},{0,2,186},{0,1,162},{0,1,162},{0,1,146},{0,1,395},{0,1,355},{1,1,104},{1,1,104},{1,1,104},{1,1,104},{0,2,170},{0,1,146},{0,1,146},{0,1,130},{0,1,170},{0,1,130},{1,2,202},{1,2,130},{1,1,125},{1,1,125},{1,2,202},{0,2,202},{1,1,125},
+{0,1,202},{0,2,202},{0,1,202},{0,0,592},{0,0,592},{0,0,592},{0,0,592},{0,1,41},{0,1,41},{0,1,41},{0,1,65},{0,0,200},{0,0,200},{1,3,738},{1,2,522},{1,2,722},{1,1,885},{0,4,987},{0,2,443},{0,2,379},{0,1,507},{0,2,1100},{0,1,412},{1,3,254},{1,2,38},{1,2,238},{1,1,401},{1,2,739},{0,2,299},{0,2,235},{0,1,363},{0,2,739},
+{0,1,363},{1,2,497},{1,2,497},{1,2,497},{1,1,524},{0,3,324},{0,2,154},{0,2,154},{0,1,146},{0,1,411},{0,1,51},{1,2,13},{1,2,13},{1,2,13},{1,1,40},{1,1,164},{0,2,10},{0,2,10},{0,1,2},{1,1,180},{0,1,2},{2,1,202},{1,2,34},{1,2,234},{0,2,234},{2,1,202},{4,0,202},{0,2,234},{0,1,362},{4,0,202},{0,1,362},{1,0,488},
+{1,0,488},{1,0,488},{1,0,488},{0,2,145},{0,2,145},{0,2,145},{0,1,145},{0,1,50},{0,1,50},{1,3,450},{1,3,362},{1,2,306},{1,2,330},{1,2,1015},{1,2,583},{1,2,463},{1,1,990},{0,2,940},{0,1,860},{1,3,254},{1,3,166},{1,2,110},{1,2,134},{0,4,731},{0,3,288},{0,2,155},{1,1,794},{2,1,731},{1,1,794},{1,2,257},{1,2,257},{1,2,257},
+{1,2,281},{1,2,390},{1,1,392},{1,1,392},{1,1,261},{0,2,315},{0,1,131},{1,2,61},{1,2,61},{1,2,61},{1,2,85},{2,0,164},{0,2,106},{0,2,106},{1,1,65},{3,0,164},{1,1,65},{3,0,208},{1,3,130},{1,2,74},{0,2,74},{3,0,208},{3,1,208},{0,2,74},{0,1,778},{3,1,208},{0,1,778},{1,0,232},{1,0,232},{1,0,232},{1,0,232},{1,1,196},
+{1,1,196},{1,1,196},{1,1,212},{0,1,82},{0,1,82},{1,4,440},{1,3,234},{1,2,402},{1,2,234},{1,3,767},{1,2,503},{1,2,63},{1,2,687},{0,3,1140},{0,2,396},{1,4,404},{1,3,198},{1,2,366},{1,2,198},{1,3,731},{0,3,224},{1,2,27},{0,2,387},{1,2,731},{0,2,387},{1,3,233},{1,3,233},{1,3,233},{1,2,233},{1,2,230},{1,2,62},{1,2,62},
+{1,1,277},{0,2,203},{1,1,385},{1,3,197},{1,3,197},{1,3,197},{1,2,197},{0,4,162},{1,2,26},{1,2,26},{1,1,241},{2,1,162},{1,1,241},{2,2,208},{1,3,2},{2,2,65},{1,2,2},{2,2,208},{5,0,208},{1,2,2},{0,2,362},{5,0,208},{0,2,362},{1,0,232},{1,0,232},{1,0,232},{1,0,232},{1,2,61},{1,2,61},{1,2,61},{1,1,52},{0,2,34},
+{0,2,34},{1,5,810},{1,3,702},{1,2,1122},{1,2,738},{1,4,748},{1,3,281},{1,2,225},{1,2,273},{0,3,780},{0,2,252},{2,3,329},{2,3,281},{2,2,222},{2,2,230},{2,2,731},{1,3,272},{1,2,216},{0,2,216},{5,0,731},{0,2,216},{1,4,547},{1,4,547},{1,4,547},{1,2,638},{1,3,173},{1,2,125},{1,2,125},{1,2,173},{0,3,339},{0,2,152},{2,2,122},
+{2,2,122},{2,2,122},{2,2,130},{1,3,164},{1,2,116},{1,2,116},{0,2,116},{1,2,164},{0,2,116},{2,3,208},{2,3,160},{2,2,101},{2,2,109},{2,3,208},{6,0,208},{2,2,109},{0,2,200},{6,0,208},{0,2,200},{1,0,538},{1,0,538},{1,0,538},{1,0,538},{1,2,25},{1,2,25},{1,2,25},{1,2,73},{0,2,52},{0,2,52},{2,3,810},{2,3,570},{2,3,810},
+{2,2,887},{1,4,940},{1,3,393},{1,3,393},{1,2,449},{0,3,1004},{1,2,392},{2,3,281},{2,3,41},{2,3,281},{2,2,358},{3,1,731},{1,3,272},{1,3,272},{1,2,328},{4,1,731},{1,2,328},{2,3,554},{2,3,554},{2,3,554},{2,2,563},{1,4,315},{1,3,137},{1,3,137},{1,2,125},{0,3,163},{1,2,68},{2,3,25},{2,3,25},{2,3,25},{2,2,34},{2,2,162},
+{1,3,16},{1,3,16},{1,2,4},{5,0,162},{1,2,4},{4,0,208},{2,3,32},{2,3,272},{1,3,272},{4,0,208},{5,1,208},{1,3,272},{0,2,328},{5,1,208},{0,2,328},{2,0,538},{2,0,538},{2,0,538},{2,0,538},{1,3,121},{1,3,121},{1,3,121},{1,2,121},{1,2,64},{1,2,64},{2,4,458},{2,3,410},{2,3,330},{2,3,378},{2,3,1013},{2,3,629},{1,3,505},
+{2,2,962},{0,4,772},{1,2,776},{2,4,233},{2,3,185},{2,3,105},{2,3,153},{4,0,724},{1,4,323},{1,3,144},{2,2,737},{3,2,724},{2,2,737},{2,3,266},{2,3,266},{2,3,266},{2,3,314},{2,3,437},{2,2,395},{2,2,395},{2,2,286},{1,3,356},{1,2,100},{2,3,41},{2,3,41},{2,3,41},{2,3,89},{3,1,162},{1,3,80},{1,3,80},{2,2,61},{4,1,162},
+{2,2,61},{2,4,208},{2,3,160},{2,3,80},{1,3,80},{2,4,208},{7,0,208},{1,3,80},{0,2,712},{7,0,208},{0,2,712},{2,0,250},{2,0,250},{2,0,250},{2,0,250},{2,2,226},{2,2,226},{2,2,226},{2,2,250},{1,2,64},{1,2,64},{2,5,436},{2,4,222},{2,3,362},{2,3,218},{2,4,773},{2,3,485},{2,3,85},{2,3,773},{0,4,804},{1,3,452},{2,5,387},
+{2,4,173},{2,3,313},{2,3,169},{2,4,724},{1,4,211},{2,3,36},{1,3,436},{7,0,724},{1,3,436},{2,4,218},{2,4,218},{2,4,218},{2,3,218},{2,3,229},{2,3,85},{2,3,85},{2,2,254},{1,3,196},{2,2,374},{2,4,169},{2,4,169},{2,4,169},{2,3,169},{4,0,164},{2,3,36},{2,3,36},{2,2,205},{3,2,164},{2,2,205},{3,3,202},{2,4,4},{3,3,81},
+{2,3,0},{3,3,202},{6,1,202},{2,3,0},{0,3,400},{6,1,202},{0,3,400},{2,0,218},{2,0,218},{2,0,218},{2,0,218},{2,3,85},{2,3,85},{2,3,85},{2,2,58},{1,3,52},{1,3,52},{2,5,760},{2,4,618},{2,3,1010},{2,3,650},{2,5,760},{2,4,303},{2,3,175},{2,3,287},{1,4,788},{1,3,236},{3,4,362},{3,4,338},{3,3,225},{3,3,241},{3,3,724},
+{2,4,299},{2,3,171},{1,3,211},{6,1,724},{1,3,211},{2,5,504},{2,5,504},{2,5,504},{2,3,569},{2,4,166},{2,3,94},{2,3,94},{2,3,206},{0,4,363},{1,3,155},{3,3,144},{3,3,144},{3,3,144},{3,3,160},{2,4,162},{2,3,90},{2,3,90},{1,3,130},{7,0,162},{1,3,130},{4,2,208},{2,4,130},{3,3,81},{3,3,97},{4,2,208},{5,2,208},{3,3,97},
+{0,3,202},{5,2,208},{0,3,202},{2,0,488},{2,0,488},{2,0,488},{2,0,488},{2,3,13},{2,3,13},{2,3,13},{2,3,85},{1,3,34},{1,3,34},{3,4,842},{3,4,626},{3,4,906},{3,3,897},{2,5,888},{2,4,351},{2,4,415},{2,3,399},{0,5,788},{2,3,380},{3,4,266},{3,4,50},{3,4,330},{3,3,321},{4,2,724},{2,4,251},{2,4,315},{2,3,299},{5,2,724},
+{2,3,299},{3,4,617},{3,4,617},{3,4,617},{3,3,608},{2,5,312},{2,4,126},{2,4,126},{2,3,110},{1,4,164},{2,3,91},{3,4,41},{3,4,41},{3,4,41},{3,3,32},{3,3,164},{2,4,26},{2,4,26},{2,3,10},{6,1,164},{2,3,10},{5,1,202},{3,4,34},{3,4,314},{3,3,305},{5,1,202},{4,3,202},{3,3,305},{0,3,298},{4,3,202},{0,3,298},{3,0,592},
+{3,0,592},{3,0,592},{3,0,592},{2,4,101},{2,4,101},{2,4,101},{2,3,101},{2,3,82},{2,3,82},{3,5,474},{3,4,402},{3,4,362},{3,4,434},{3,4,1019},{3,4,683},{2,4,463},{3,3,942},{1,5,804},{2,3,700},{3,5,218},{3,4,146},{3,4,106},{3,4,178},{5,1,723},{2,5,364},{2,4,139},{3,3,686},{4,3,723},{3,3,686},{3,4,281},{3,4,281},{3,4,281},
+{3,4,353},{3,4,490},{2,4,382},{2,4,382},{3,3,317},{1,4,324},{2,3,75},{3,4,25},{3,4,25},{3,4,25},{3,4,97},{4,2,164},{2,4,58},{2,4,58},{3,3,61},{5,2,164},{3,3,61},{6,0,202},{3,4,130},{3,4,90},{2,4,90},{6,0,202},{3,4,202},{2,4,90},{0,3,650},{3,4,202},{0,3,650},{3,0,272},{3,0,272},{3,0,272},{3,0,272},{3,3,260},
+{3,3,260},{3,3,260},{3,3,292},{2,3,50},{2,3,50},{3,6,440},{3,5,218},{3,4,330},{3,4,210},{3,5,787},{3,4,475},{3,4,115},{3,4,867},{1,5,772},{2,4,516},{3,6,376},{3,5,154},{3,4,266},{3,4,146},{6,0,723},{2,5,204},{3,4,51},{1,4,478},{3,4,723},{1,4,478},{3,5,209},{3,5,209},{3,5,209},{3,4,209},{3,4,234},{3,4,114},{3,4,114},
+{3,3,237},{2,4,195},{3,3,369},{3,5,145},{3,5,145},{3,5,145},{3,4,145},{5,1,170},{3,4,50},{3,4,50},{3,3,173},{7,1,170},{3,3,173},{4,4,200},{3,5,10},{4,4,101},{3,4,2},{4,4,200},{7,2,200},{3,4,2},{0,4,442},{7,2,200},{0,4,442},{3,0,208},{3,0,208},{3,0,208},{3,0,208},{3,3,100},{3,3,100},{3,3,100},{3,3,68},{2,4,74},
+{2,4,74},{3,6,692},{3,5,542},{3,4,906},{3,4,570},{3,6,780},{3,5,333},{3,4,133},{3,4,309},{2,5,804},{2,4,228},{4,5,401},{4,4,395},{4,4,234},{4,4,258},{4,4,723},{3,5,332},{3,4,132},{2,4,212},{7,2,723},{2,4,212},{3,6,467},{3,6,467},{3,6,467},{3,4,506},{3,5,165},{3,4,69},{3,4,69},{3,4,245},{1,5,324},{2,4,164},{4,4,170},
+{4,4,170},{4,4,170},{4,4,194},{6,0,164},{3,4,68},{3,4,68},{2,4,148},{3,4,164},{2,4,148},{5,3,202},{3,5,100},{4,4,65},{4,4,89},{5,3,202},{6,3,202},{4,4,89},{0,4,208},{6,3,202},{0,4,208},{3,0,442},{3,0,442},{3,0,442},{3,0,442},{3,4,5},{3,4,5},{3,4,5},{3,4,101},{2,4,20},{2,4,20},{4,5,882},{4,5,690},{4,4,955},
+{4,4,915},{3,6,844},{3,5,317},{3,5,445},{3,4,357},{1,6,772},{3,4,376},{4,5,257},{4,5,65},{4,4,330},{4,4,290},{5,3,723},{3,5,236},{3,5,364},{3,4,276},{6,3,723},{3,4,276},{4,5,686},{4,5,686},{4,5,686},{4,4,659},{3,6,315},{3,5,121},{3,5,121},{3,4,101},{2,5,171},{3,4,120},{4,5,61},{4,5,61},{4,5,61},{4,4,34},{5,2,170},
+{3,5,40},{3,5,40},{3,4,20},{7,2,170},{3,4,20},{6,2,200},{4,5,40},{4,4,305},{4,4,265},{6,2,200},{5,4,200},{4,4,265},{0,4,272},{5,4,200},{0,4,272},{4,0,650},{4,0,650},{4,0,650},{4,0,650},{3,5,85},{3,5,85},{3,5,85},{3,4,85},{3,4,104},{3,4,104},{4,6,498},{4,5,402},{4,5,402},{4,5,498},{3,7,1017},{3,6,700},{3,5,429},
+{3,4,917},{2,6,844},{3,4,632},{4,6,209},{4,5,113},{4,5,113},{4,5,209},{6,2,728},{3,6,411},{3,5,140},{3,4,628},{5,4,728},{3,4,628},{4,5,302},{4,5,302},{4,5,302},{4,5,398},{3,6,459},{3,5,329},{3,5,329},{3,4,341},{2,5,283},{3,4,56},{4,5,13},{4,5,13},{4,5,13},{4,5,109},{6,1,170},{3,5,40},{3,5,40},{3,4,52},{6,3,170},
+{3,4,52},{7,1,200},{4,5,104},{4,5,104},{3,5,104},{7,1,200},{4,5,200},{3,5,104},{0,4,592},{4,5,200},{0,4,592},{4,0,298},{4,0,298},{4,0,298},{4,0,298},{4,4,298},{4,4,298},{4,4,298},{3,4,325},{3,4,40},{3,4,40},{4,7,452},{4,6,222},{4,5,306},{4,5,210},{4,6,809},{4,5,473},{4,5,153},{4,5,969},{2,6,748},{3,5,588},{4,7,371},
+{4,6,141},{4,5,225},{4,5,129},{7,1,728},{3,6,203},{4,5,72},{2,5,513},{4,5,728},{2,5,513},{4,6,206},{4,6,206},{4,6,206},{4,5,206},{4,5,245},{4,5,149},{4,5,149},{4,4,226},{3,5,200},{4,4,370},{4,6,125},{4,6,125},{4,6,125},{4,5,125},{7,0,164},{4,5,68},{4,5,68},{4,4,145},{3,5,164},{4,4,145},{5,5,202},{4,6,20},{4,5,104},
+{4,5,8},{5,5,202},{3,6,202},{4,5,8},{0,5,488},{3,6,202},{0,5,488},{4,0,202},{4,0,202},{4,0,202},{4,0,202},{4,4,106},{4,4,106},{4,4,106},{4,4,82},{3,5,100},{3,5,100},{4,7,632},{4,6,474},{4,5,810},{4,5,498},{4,7,808},{4,6,371},{4,5,99},{4,5,339},{3,6,828},{3,5,228},{5,6,446},{5,5,396},{5,5,249},{5,5,281},{5,5,728},
+{4,6,371},{4,5,99},{3,5,219},{3,6,728},{3,5,219},{4,7,436},{4,7,436},{4,7,436},{4,5,449},{4,6,170},{4,5,50},{4,5,50},{4,5,290},{2,6,291},{3,5,179},{5,5,200},{5,5,200},{5,5,200},{5,5,232},{7,1,170},{4,5,50},{4,5,50},{3,5,170},{7,3,170},{3,5,170},{6,4,200},{4,6,74},{5,5,53},{5,5,85},{6,4,200},{7,4,200},{5,5,85},
+{0,5,218},{7,4,200},{0,5,218},{4,0,400},{4,0,400},{4,0,400},{4,0,400},{4,5,1},{4,5,1},{4,5,1},{4,4,100},{3,5,10},{3,5,10},{5,6,930},{5,6,762},{5,5,973},{5,5,941},{4,7,808},{4,6,291},{4,6,483},{4,5,323},{2,7,764},{4,5,380},{5,6,254},{5,6,86},{5,5,297},{5,5,265},{6,4,728},{4,6,227},{5,5,373},{4,5,259},{7,4,728},
+{4,5,259},{5,5,748},{5,5,748},{5,5,748},{5,5,716},{4,6,298},{4,6,122},{4,6,122},{4,5,98},{3,6,184},{4,5,155},{5,5,72},{5,5,72},{5,5,72},{5,5,40},{6,3,164},{4,6,58},{4,6,58},{4,5,34},{6,4,164},{4,5,34},{7,3,202},{5,6,50},{5,5,261},{5,5,229},{7,3,202},{6,5,202},{5,5,229},{0,5,250},{6,5,202},{0,5,250},{5,0,712},
+{5,0,712},{5,0,712},{5,0,712},{4,6,73},{4,6,73},{4,6,73},{4,5,73},{4,5,130},{4,5,130},{5,7,530},{5,6,410},{5,6,450},{5,6,570},{5,6,1055},{4,7,720},{4,6,403},{4,5,819},{3,7,892},{4,5,572},{5,7,206},{5,6,86},{5,6,126},{5,6,246},{5,6,731},{3,7,387},{4,6,147},{4,5,563},{4,6,731},{4,5,563},{5,6,329},{5,6,329},{5,6,329},
+{5,5,428},{4,7,420},{4,6,282},{4,6,282},{4,5,290},{3,6,248},{4,5,43},{5,6,5},{5,6,5},{5,6,5},{5,5,104},{7,2,164},{4,6,26},{4,6,26},{4,5,34},{5,5,164},{4,5,34},{5,7,202},{5,6,82},{5,6,122},{4,6,122},{5,7,202},{5,6,202},{4,6,122},{0,5,538},{5,6,202},{0,5,538},{5,0,328},{5,0,328},{5,0,328},{5,0,328},{4,6,281},
+{4,6,281},{4,6,281},{4,5,281},{4,5,34},{4,5,34},{5,7,498},{5,7,234},{5,6,290},{5,6,218},{5,7,839},{5,6,479},{5,6,199},{5,6,1079},{3,7,732},{4,6,668},{5,7,398},{5,7,134},{5,6,190},{5,6,118},{6,5,731},{4,7,208},{5,6,99},{3,6,554},{3,7,731},{3,6,554},{5,7,209},{5,7,209},{5,7,209},{5,6,209},{5,6,262},{5,6,190},{5,6,190},
+{5,5,221},{4,6,211},{4,5,315},{5,7,109},{5,7,109},{5,7,109},{5,6,109},{5,6,162},{5,6,90},{5,6,90},{5,5,121},{4,6,162},{5,5,121},{7,4,208},{5,7,34},{5,6,90},{5,6,18},{7,4,208},{7,5,208},{5,6,18},{0,6,538},{7,5,208},{0,6,538},{5,0,200},{5,0,200},{5,0,200},{5,0,200},{5,5,116},{5,5,116},{5,5,116},{5,5,100},{4,6,130},
+{4,6,130},{5,7,1074},{5,7,414},{5,6,722},{5,6,434},{5,7,857},{5,7,417},{5,6,73},{5,6,377},{4,7,860},{4,6,236},{6,7,497},{6,6,403},{6,6,270},{6,6,310},{7,4,731},{4,7,379},{5,6,72},{4,6,232},{7,5,731},{4,6,232},{5,7,398},{5,7,398},{5,7,398},{5,6,398},{5,7,181},{5,6,37},{5,6,37},{5,6,341},{3,7,264},{4,6,200},{6,6,234},
+{6,6,234},{6,6,234},{6,6,274},{6,5,164},{5,6,36},{5,6,36},{4,6,196},{3,7,164},{4,6,196},{7,5,202},{5,7,52},{6,6,45},{5,6,72},{7,5,202},{6,6,218},{5,6,72},{0,6,232},{6,6,218},{0,6,232},{5,0,362},{5,0,362},{5,0,362},{5,0,362},{5,6,1},{5,6,1},{5,6,1},{5,5,82},{4,6,4},{4,6,4},{6,7,986},{6,7,842},{6,6,999},
+{6,6,975},{5,7,1417},{5,7,273},{5,6,505},{5,6,297},{4,7,828},{5,6,392},{6,7,257},{6,7,113},{6,6,270},{6,6,246},{7,5,739},{5,7,224},{6,6,366},{5,6,248},{6,6,731},{5,6,248},{6,6,803},{6,6,803},{6,6,803},{6,6,779},{5,7,261},{5,7,129},{5,7,129},{5,6,101},{4,7,203},{5,6,196},{6,6,74},{6,6,74},{6,6,74},{6,6,50},{7,4,162},
+{5,7,80},{5,7,80},{5,6,52},{7,5,162},{5,6,52},{6,7,208},{6,7,64},{6,6,221},{6,6,197},{6,7,208},{7,6,208},{6,6,197},{0,6,232},{7,6,208},{0,6,232},{5,0,778},{5,0,778},{5,0,778},{5,0,778},{5,7,65},{5,7,65},{5,7,65},{5,6,65},{5,6,160},{5,6,160},{6,7,762},{6,7,426},{6,7,506},{6,7,650},{6,7,1085},{5,7,641},{5,7,385},
+{5,6,729},{5,7,980},{5,6,520},{6,7,401},{6,7,65},{6,7,145},{6,7,289},{6,7,724},{5,7,416},{5,7,160},{5,6,504},{5,7,724},{5,6,504},{6,7,362},{6,7,362},{6,7,362},{6,6,443},{6,6,555},{5,7,241},{5,7,241},{5,6,245},{4,7,219},{5,6,36},{6,7,1},{6,7,1},{6,7,1},{6,6,82},{7,5,194},{5,7,16},{5,7,16},{5,6,20},{6,6,162},
+{5,6,20},{7,6,208},{6,7,64},{6,7,144},{5,7,144},{7,6,208},{6,7,208},{5,7,144},{0,6,488},{6,7,208},{0,6,488},{6,0,362},{6,0,362},{6,0,362},{6,0,362},{5,7,241},{5,7,241},{5,7,241},{5,6,241},{5,6,32},{5,6,32},{6,7,1050},{6,7,522},{6,7,282},{6,7,234},{6,7,1069},{6,7,493},{6,7,253},{6,6,1122},{5,7,1012},{5,7,756},{7,7,843},
+{6,7,401},{6,7,161},{6,7,113},{7,6,724},{6,7,372},{6,7,132},{4,7,601},{6,7,756},{4,7,601},{6,7,266},{6,7,266},{6,7,266},{6,7,218},{6,7,285},{6,7,237},{6,7,237},{6,6,222},{5,7,228},{5,6,260},{6,7,145},{6,7,145},{6,7,145},{6,7,97},{6,7,164},{6,7,116},{6,7,116},{6,6,101},{5,7,164},{6,6,101},{7,7,218},{7,7,178},{6,7,80},
+{6,7,32},{7,7,218},{6,7,272},{6,7,32},{0,7,592},{6,7,272},{0,7,592},{6,0,202},{6,0,202},{6,0,202},{6,0,202},{6,6,130},{6,6,130},{6,6,130},{6,6,122},{5,6,160},{5,6,160},{6,7,1641},{6,7,1017},{6,7,617},{6,7,353},{6,7,1318},{6,7,430},{6,7,30},{6,7,398},{6,7,1035},{5,7,227},{7,7,393},{7,7,321},{7,7,272},{7,7,320},{7,7,621},
+{6,7,426},{6,7,26},{5,7,226},{6,7,594},{5,7,226},{6,7,617},{6,7,617},{6,7,617},{6,7,353},{6,7,294},{6,7,30},{6,7,30},{6,7,398},{5,7,291},{5,7,227},{7,7,272},{7,7,272},{7,7,272},{7,7,320},{7,6,162},{6,7,26},{6,7,26},{5,7,226},{7,6,194},{5,7,226},{7,7,137},{7,7,65},{7,7,16},{6,7,25},{7,7,137},{7,7,113},{6,7,25},
+{0,7,225},{7,7,113},{0,7,225},{6,0,328},{6,0,328},{6,0,328},{6,0,328},{6,7,5},{6,7,5},{6,7,5},{6,6,68},{5,7,2},{5,7,2},{7,7,985},{7,7,913},{7,7,864},{7,7,848},{7,7,1117},{6,7,654},{6,7,254},{6,7,110},{6,7,763},{5,7,179},{7,7,201},{7,7,129},{7,7,80},{7,7,64},{7,7,333},{7,7,245},{7,7,196},{6,7,74},{7,7,373},
+{6,7,74},{7,7,864},{7,7,864},{7,7,864},{7,7,848},{6,7,710},{6,7,254},{6,7,254},{6,7,110},{6,7,363},{5,7,179},{7,7,80},{7,7,80},{7,7,80},{7,7,64},{7,7,212},{7,7,196},{7,7,196},{6,7,74},{6,7,194},{6,7,74},{7,7,137},{7,7,65},{7,7,16},{7,7,0},{7,7,137},{7,7,49},{7,7,0},{0,7,49},{7,7,49},{0,7,49},{6,0,712},
+{6,0,712},{6,0,712},{6,0,712},{6,7,85},{6,7,85},{6,7,85},{6,7,61},{5,7,130},{5,7,130},{7,7,642},{7,7,570},{7,7,521},{7,7,449},{7,7,678},{7,7,534},{7,7,485},{6,7,205},{6,7,834},{6,7,34},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,278},{7,7,134},{7,7,85},{6,7,9},{7,7,198},{6,7,9},{7,7,521},{7,7,521},{7,7,521},
+{7,7,449},{7,7,557},{7,7,485},{7,7,485},{6,7,205},{6,7,434},{6,7,34},{7,7,121},{7,7,121},{7,7,121},{7,7,49},{7,7,157},{7,7,85},{7,7,85},{6,7,9},{7,7,149},{6,7,9},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{7,0,400},{7,0,400},{7,0,400},{7,0,400},{6,7,421},
+{6,7,421},{6,7,421},{6,7,205},{6,7,34},{6,7,34},{7,7,450},{7,7,378},{7,7,329},{7,7,257},{7,7,390},{7,7,246},{7,7,197},{7,7,148},{7,7,426},{6,7,130},{7,7,306},{7,7,234},{7,7,185},{7,7,113},{7,7,246},{7,7,102},{7,7,53},{7,7,4},{7,7,102},{7,7,4},{7,7,329},{7,7,329},{7,7,329},{7,7,257},{7,7,269},{7,7,197},{7,7,197},
+{7,7,148},{7,7,377},{6,7,130},{7,7,185},{7,7,185},{7,7,185},{7,7,113},{7,7,125},{7,7,53},{7,7,53},{7,7,4},{7,7,53},{7,7,4},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{7,7,148},{7,7,148},{7,7,148},{7,7,148},{6,7,130},
+{6,7,130},{0,2,445},{0,1,157},{0,1,117},{0,1,405},{0,1,926},{0,1,806},{0,0,670},{0,0,741},{0,0,1169},{0,0,777},{0,2,445},{0,1,157},{0,1,117},{0,1,405},{0,1,926},{0,1,806},{0,0,670},{0,0,741},{1,0,990},{0,0,741},{0,1,36},{0,1,36},{0,1,36},{0,0,9},{0,0,85},{0,0,45},{0,0,45},{0,0,116},{0,0,145},{0,0,152},{0,1,36},
+{0,1,36},{0,1,36},{0,0,9},{0,0,85},{0,0,45},{0,0,45},{0,0,116},{0,0,109},{0,0,116},{1,0,421},{0,1,157},{0,1,117},{0,1,405},{1,0,421},{0,1,445},{0,1,405},{0,0,641},{0,1,445},{0,0,641},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,2,461},{0,2,109},{0,1,5},
+{0,1,101},{0,1,1326},{0,1,822},{0,1,462},{0,0,1205},{0,1,1783},{0,0,1241},{0,2,461},{0,2,109},{0,1,5},{0,1,101},{1,0,1294},{0,1,822},{0,1,462},{0,0,1205},{1,0,1262},{0,0,1205},{0,1,4},{0,1,4},{0,1,4},{0,1,100},{0,0,261},{0,0,157},{0,0,157},{0,0,116},{0,0,257},{0,0,152},{0,1,4},{0,1,4},{0,1,4},{0,1,100},{0,0,261},
+{0,0,157},{0,0,157},{0,0,116},{0,0,221},{0,0,116},{1,1,461},{0,2,109},{0,1,5},{0,1,101},{1,1,461},{2,0,421},{0,1,101},{0,1,901},{2,0,421},{0,1,901},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,3,430},{0,2,38},{0,1,158},{0,1,62},{0,2,1517},{0,1,989},{0,1,309},
+{0,1,1317},{0,1,1878},{0,1,1678},{0,3,430},{0,2,38},{0,1,158},{0,1,62},{0,2,1517},{0,1,989},{0,1,309},{0,1,1317},{0,1,1517},{0,1,1317},{0,2,13},{0,2,13},{0,2,13},{0,1,13},{0,1,356},{0,1,260},{0,1,260},{0,0,193},{0,0,446},{0,0,229},{0,2,13},{0,2,13},{0,2,13},{0,1,13},{0,1,356},{0,1,260},{0,1,260},{0,0,193},{0,0,410},
+{0,0,193},{0,3,421},{0,2,29},{0,1,149},{0,1,53},{0,3,421},{1,1,421},{0,1,53},{0,1,533},{1,1,421},{0,1,533},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,49},{0,0,85},{0,0,85},{0,4,602},{0,3,234},{0,2,518},{0,1,382},{0,3,1622},{0,2,825},{0,1,325},{0,1,821},{0,1,2022},{0,1,1182},{0,4,602},
+{0,3,234},{0,2,518},{0,1,382},{1,1,1526},{0,2,825},{0,1,325},{0,1,821},{2,0,1526},{0,1,821},{0,2,157},{0,2,157},{0,2,157},{0,1,157},{0,1,388},{0,1,100},{0,1,100},{0,0,401},{0,0,766},{0,0,437},{0,2,157},{0,2,157},{0,2,157},{0,1,157},{1,0,356},{0,1,100},{0,1,100},{0,0,401},{1,0,340},{0,0,401},{1,2,425},{0,3,113},{1,1,234},
+{0,1,261},{1,2,425},{0,2,425},{0,1,261},{0,1,421},{0,2,425},{0,1,421},{0,0,121},{0,0,121},{0,0,121},{0,0,121},{0,0,25},{0,0,25},{0,0,25},{0,0,1},{0,0,37},{0,0,37},{0,4,845},{0,3,405},{0,2,725},{0,2,549},{0,3,1541},{0,2,654},{0,2,270},{0,1,722},{0,2,2583},{0,1,1083},{1,3,657},{1,2,345},{1,2,345},{0,2,549},{2,0,1517},
+{0,2,654},{0,2,270},{0,1,722},{3,0,1517},{0,1,722},{0,3,404},{0,3,404},{0,3,404},{0,2,449},{0,2,346},{0,2,170},{0,2,170},{0,1,146},{0,1,707},{0,1,507},{1,1,232},{1,1,232},{1,1,232},{1,1,200},{0,2,346},{0,2,170},{0,2,170},{0,1,146},{0,1,346},{0,1,146},{2,1,421},{0,3,5},{1,2,149},{0,2,149},{2,1,421},{4,0,421},{0,2,149},
+{0,1,601},{4,0,421},{0,1,601},{0,0,400},{0,0,400},{0,0,400},{0,0,400},{0,1,1},{0,1,1},{0,1,1},{0,0,100},{0,0,136},{0,0,136},{0,5,1209},{0,4,937},{1,2,1197},{0,2,789},{0,4,1526},{0,3,737},{0,2,14},{0,1,1042},{0,2,2487},{0,1,1403},{1,3,481},{1,3,173},{1,2,41},{1,2,161},{1,2,1526},{0,3,737},{0,2,14},{0,1,1042},{2,1,1526},
+{0,1,1042},{0,4,793},{0,4,793},{0,4,793},{0,2,785},{0,3,356},{0,2,10},{0,2,10},{0,1,18},{0,1,899},{0,1,379},{1,2,37},{1,2,37},{1,2,37},{1,1,136},{1,1,340},{0,2,10},{0,2,10},{0,1,18},{1,1,356},{0,1,18},{3,0,425},{1,3,137},{1,2,5},{0,2,5},{3,0,425},{3,1,425},{0,2,5},{0,2,965},{3,1,425},{0,2,965},{0,0,784},
+{0,0,784},{0,0,784},{0,0,784},{0,2,9},{0,2,9},{0,2,9},{0,1,9},{0,0,360},{0,0,360},{1,4,1158},{1,3,758},{1,2,850},{1,2,778},{0,4,1671},{0,3,546},{0,2,191},{0,2,903},{0,2,2390},{0,2,1430},{1,4,429},{1,3,29},{1,2,121},{1,2,49},{2,1,1526},{0,3,497},{0,2,142},{0,2,854},{4,0,1526},{0,2,854},{1,3,742},{1,3,742},{1,3,742},
+{1,2,742},{0,3,437},{0,2,155},{0,2,155},{0,1,195},{0,2,946},{0,1,290},{1,3,13},{1,3,13},{1,3,13},{1,2,13},{2,0,340},{0,2,106},{0,2,106},{0,1,146},{3,0,340},{0,1,146},{1,4,425},{1,3,25},{1,2,117},{1,2,45},{1,4,425},{2,2,425},{1,2,45},{0,2,565},{2,2,425},{0,2,565},{1,0,733},{1,0,733},{1,0,733},{1,0,733},{0,2,74},
+{0,2,74},{0,2,74},{0,1,74},{0,1,169},{0,1,169},{1,4,966},{1,4,606},{1,3,886},{1,2,682},{0,5,1742},{0,3,866},{0,3,641},{0,2,727},{0,3,2382},{0,2,758},{1,4,605},{1,4,245},{1,3,525},{1,2,321},{3,0,1517},{0,3,641},{1,2,302},{0,2,502},{3,1,1517},{0,2,502},{1,3,486},{1,3,486},{1,3,486},{1,2,486},{0,4,563},{0,3,241},{0,3,241},
+{0,2,531},{0,2,626},{0,1,546},{1,3,125},{1,3,125},{1,3,125},{1,2,125},{0,4,338},{0,3,16},{0,3,16},{0,2,306},{2,1,338},{0,2,306},{3,1,433},{1,4,145},{2,2,212},{1,2,221},{3,1,433},{6,0,433},{1,2,221},{0,2,421},{6,0,433},{0,2,421},{1,0,461},{1,0,461},{1,0,461},{1,0,461},{0,3,225},{0,3,225},{0,3,225},{0,2,306},{0,1,185},
+{0,1,185},{1,5,894},{1,4,462},{1,3,778},{1,3,646},{1,4,1626},{1,3,749},{1,3,429},{1,2,809},{0,3,2022},{0,2,614},{2,4,706},{1,4,362},{2,3,410},{1,3,546},{3,1,1526},{0,4,441},{0,3,227},{0,2,565},{4,1,1526},{0,2,565},{1,4,462},{1,4,462},{1,4,462},{1,3,525},{1,3,440},{1,2,296},{1,2,296},{1,2,280},{0,2,725},{0,2,85},{2,2,250},
+{2,2,250},{2,2,250},{2,2,226},{1,3,340},{0,3,106},{0,3,106},{0,2,36},{1,2,340},{0,2,36},{3,2,425},{1,4,1},{2,3,185},{0,3,146},{3,2,425},{5,1,425},{0,3,146},{0,2,565},{5,1,425},{0,2,565},{1,0,461},{1,0,461},{1,0,461},{1,0,461},{1,2,100},{1,2,100},{1,2,100},{1,1,181},{0,2,49},{0,2,49},{1,6,1166},{1,4,878},{1,3,1226},
+{1,3,742},{1,5,1545},{1,4,798},{1,3,29},{1,2,985},{0,3,2246},{0,2,1030},{2,4,482},{2,4,218},{2,3,58},{2,3,202},{2,3,1517},{0,4,521},{1,3,25},{1,2,981},{6,0,1517},{1,2,981},{1,5,749},{1,5,749},{1,5,749},{1,3,733},{1,4,374},{1,3,20},{1,3,20},{1,2,24},{0,3,482},{0,2,69},{2,3,49},{2,3,49},{2,3,49},{2,2,130},{2,2,338},
+{1,3,16},{1,3,16},{1,2,20},{5,0,338},{1,2,20},{4,1,433},{1,4,145},{2,3,9},{1,3,9},{4,1,433},{7,0,433},{1,3,9},{0,2,965},{7,0,433},{0,2,965},{1,0,733},{1,0,733},{1,0,733},{1,0,733},{1,3,20},{1,3,20},{1,3,20},{1,2,20},{0,2,65},{0,2,65},{2,5,1218},{2,4,810},{2,3,874},{2,3,826},{1,5,1625},{1,4,542},{1,3,141},
+{1,3,961},{0,4,1806},{0,3,642},{2,5,434},{2,4,26},{2,3,90},{2,3,42},{3,2,1517},{1,4,506},{1,3,105},{0,3,626},{5,1,1517},{0,3,626},{2,4,801},{2,4,801},{2,4,801},{2,3,801},{1,4,406},{1,3,116},{1,3,116},{1,2,152},{0,3,482},{1,2,285},{2,4,17},{2,4,17},{2,4,17},{2,3,17},{3,1,338},{1,3,80},{1,3,80},{1,2,116},{4,1,338},
+{1,2,116},{3,3,425},{2,4,25},{2,3,89},{2,3,41},{3,3,425},{6,1,425},{2,3,41},{0,3,601},{6,1,425},{0,3,601},{2,0,785},{2,0,785},{2,0,785},{2,0,785},{1,3,52},{1,3,52},{1,3,52},{1,2,52},{0,3,41},{0,3,41},{2,5,962},{2,4,618},{2,3,906},{2,3,666},{1,6,1710},{1,4,798},{1,4,663},{1,3,721},{0,4,1838},{0,3,450},{2,5,562},
+{2,4,218},{2,3,506},{2,3,266},{4,1,1514},{0,5,474},{2,3,285},{0,3,434},{4,2,1514},{0,3,434},{2,4,497},{2,4,497},{2,4,497},{2,3,497},{1,5,536},{1,4,222},{1,4,222},{1,3,552},{0,4,469},{0,3,281},{2,4,97},{2,4,97},{2,4,97},{2,3,97},{4,0,340},{1,4,26},{1,4,26},{0,3,265},{3,2,340},{0,3,265},{4,2,425},{2,4,137},{3,3,194},
+{2,3,185},{4,2,425},{5,2,425},{2,3,185},{0,3,425},{5,2,425},{0,3,425},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{1,4,197},{1,4,197},{1,4,197},{1,3,296},{0,3,25},{0,3,25},{2,6,870},{2,5,446},{2,4,758},{2,4,670},{2,5,1638},{2,4,771},{2,4,515},{2,3,823},{0,5,1710},{1,3,598},{3,4,737},{2,5,325},{3,4,481},{2,4,549},{5,0,1517},
+{1,5,458},{1,4,224},{1,3,534},{3,3,1517},{1,3,534},{2,5,445},{2,5,445},{2,5,445},{2,4,526},{2,4,459},{2,3,291},{2,3,291},{2,3,339},{0,4,370},{1,3,114},{3,3,272},{3,3,272},{3,3,272},{3,3,256},{2,4,338},{1,4,80},{1,4,80},{1,3,50},{7,0,338},{1,3,50},{5,1,425},{2,5,1},{3,4,225},{1,4,160},{5,1,425},{4,3,425},{1,4,160},
+{0,3,533},{4,3,425},{0,3,533},{2,0,445},{2,0,445},{2,0,445},{2,0,445},{2,3,122},{2,3,122},{2,3,122},{2,2,185},{1,3,65},{1,3,65},{2,7,1130},{2,5,798},{2,4,1142},{2,4,702},{2,6,1571},{2,4,819},{2,4,51},{2,3,935},{0,5,1614},{1,3,950},{3,5,489},{3,5,269},{3,4,81},{3,4,249},{3,4,1514},{1,5,490},{2,4,42},{2,3,926},{7,1,1514},
+{2,3,926},{2,6,710},{2,6,710},{2,6,710},{2,4,686},{2,5,397},{2,4,35},{2,4,35},{2,3,35},{1,4,509},{1,3,50},{3,4,65},{3,4,65},{3,4,65},{3,3,128},{3,3,340},{2,4,26},{2,4,26},{2,3,26},{6,1,340},{2,3,26},{6,0,425},{2,5,113},{3,4,17},{2,4,17},{6,0,425},{3,4,425},{2,4,17},{0,3,901},{3,4,425},{0,3,901},{2,0,685},
+{2,0,685},{2,0,685},{2,0,685},{2,4,34},{2,4,34},{2,4,34},{2,3,34},{1,3,49},{1,3,49},{3,6,1286},{3,5,870},{3,4,906},{3,4,882},{2,6,1587},{2,5,546},{2,4,99},{2,4,1027},{1,5,1838},{1,4,702},{3,6,445},{3,5,29},{3,4,65},{3,4,41},{4,3,1514},{2,5,521},{2,4,74},{1,4,677},{6,2,1514},{1,4,677},{3,5,866},{3,5,866},{3,5,866},
+{3,4,866},{2,5,381},{2,4,83},{2,4,83},{2,3,115},{0,5,349},{2,3,286},{3,5,25},{3,5,25},{3,5,25},{3,4,25},{4,2,340},{2,4,58},{2,4,58},{2,3,90},{5,2,340},{2,3,90},{4,4,421},{3,5,29},{3,4,65},{3,4,41},{4,4,421},{7,2,421},{3,4,41},{0,4,641},{7,2,421},{0,4,641},{3,0,841},{3,0,841},{3,0,841},{3,0,841},{2,4,34},
+{2,4,34},{2,4,34},{2,3,34},{1,4,61},{1,4,61},{3,6,966},{3,5,614},{3,4,874},{3,4,658},{2,7,1686},{2,5,738},{2,4,659},{2,4,723},{0,6,1518},{1,4,446},{3,6,525},{3,5,173},{3,4,433},{3,4,217},{5,2,1517},{1,6,457},{3,4,274},{1,4,437},{5,3,1517},{1,4,437},{3,5,514},{3,5,514},{3,5,514},{3,4,514},{2,6,515},{2,5,209},{2,5,209},
+{2,3,579},{1,5,510},{1,4,302},{3,5,73},{3,5,73},{3,5,73},{3,4,73},{5,1,346},{2,5,40},{2,5,40},{3,3,293},{7,1,346},{3,3,293},{5,3,421},{3,5,109},{4,4,180},{3,4,153},{5,3,421},{6,3,421},{3,4,153},{0,4,433},{6,3,421},{0,4,433},{3,0,505},{3,0,505},{3,0,505},{3,0,505},{2,5,173},{2,5,173},{2,5,173},{2,3,290},{1,4,13},
+{1,4,13},{3,7,854},{3,6,438},{3,5,746},{3,5,702},{3,6,1658},{3,5,801},{3,5,609},{3,4,845},{1,6,1758},{2,4,590},{3,7,710},{3,6,294},{4,5,558},{3,5,558},{6,1,1514},{2,6,481},{2,5,227},{2,4,509},{4,4,1514},{2,4,509},{3,6,434},{3,6,434},{3,6,434},{3,5,533},{3,5,484},{3,4,292},{3,4,292},{3,4,404},{1,5,357},{2,4,149},{3,6,290},
+{3,6,290},{3,6,290},{4,4,290},{6,0,340},{2,5,58},{2,5,58},{2,4,68},{3,4,340},{2,4,68},{6,2,421},{3,6,5},{4,5,269},{2,5,178},{6,2,421},{5,4,421},{2,5,178},{0,4,505},{5,4,421},{0,4,505},{3,0,433},{3,0,433},{3,0,433},{3,0,433},{3,4,148},{3,4,148},{3,4,148},{3,3,193},{2,4,85},{2,4,85},{3,7,1206},{3,6,726},{3,5,1066},
+{3,5,670},{3,7,1605},{3,5,785},{3,5,81},{3,4,893},{1,6,1598},{2,4,878},{4,6,502},{4,5,310},{4,5,110},{4,5,302},{7,0,1517},{2,6,465},{3,5,65},{2,4,877},{3,5,1517},{2,4,877},{3,7,677},{3,7,677},{3,7,677},{3,5,645},{3,6,426},{3,5,56},{3,5,56},{3,4,52},{2,5,542},{2,4,37},{4,5,85},{4,5,85},{4,5,85},{4,4,130},{5,2,346},
+{3,5,40},{3,5,40},{2,4,36},{7,2,346},{2,4,36},{7,1,421},{3,6,85},{4,5,29},{3,5,29},{7,1,421},{4,5,421},{3,5,29},{0,4,841},{4,5,421},{0,4,841},{3,0,641},{3,0,641},{3,0,641},{3,0,641},{3,4,52},{3,4,52},{3,4,52},{3,4,52},{2,4,37},{2,4,37},{4,7,1362},{4,6,938},{4,5,946},{4,5,946},{3,7,1557},{3,6,558},{3,5,65},
+{3,5,1101},{0,7,1662},{2,5,770},{4,7,462},{4,6,38},{4,5,46},{4,5,46},{5,4,1517},{3,6,542},{3,5,49},{1,5,721},{7,3,1517},{1,5,721},{4,5,937},{4,5,937},{4,5,937},{4,5,937},{3,6,362},{3,5,56},{3,5,56},{3,4,84},{1,6,350},{3,4,293},{4,5,37},{4,5,37},{4,5,37},{4,5,37},{6,1,346},{3,5,40},{3,5,40},{3,4,68},{6,3,346},
+{3,4,68},{5,5,421},{4,6,37},{4,5,45},{3,5,45},{5,5,421},{3,6,421},{3,5,45},{0,5,685},{3,6,421},{0,5,685},{4,0,901},{4,0,901},{4,0,901},{4,0,901},{3,5,20},{3,5,20},{3,5,20},{3,4,20},{2,5,85},{2,5,85},{4,7,978},{4,6,618},{4,5,850},{4,5,658},{3,7,2021},{3,6,686},{3,5,561},{3,5,733},{1,7,1530},{2,5,450},{4,7,494},
+{4,6,134},{4,5,366},{4,5,174},{6,3,1526},{2,7,446},{4,5,269},{2,5,446},{6,4,1526},{2,5,446},{4,6,537},{4,6,537},{4,6,537},{4,5,537},{3,7,500},{3,6,202},{3,6,202},{3,4,500},{1,6,510},{2,5,329},{4,6,53},{4,6,53},{4,6,53},{4,5,53},{7,0,340},{3,6,58},{3,6,58},{4,4,265},{3,5,340},{4,4,265},{6,4,421},{4,6,85},{5,5,170},
+{4,5,125},{6,4,421},{7,4,421},{4,5,125},{0,5,445},{7,4,421},{0,5,445},{4,0,533},{4,0,533},{4,0,533},{4,0,533},{3,6,153},{3,6,153},{3,6,153},{3,4,244},{2,5,5},{2,5,5},{4,7,1158},{4,7,438},{4,6,742},{4,6,742},{4,7,1686},{4,6,839},{3,6,677},{4,5,875},{1,7,1710},{3,5,590},{5,6,769},{4,7,269},{4,6,573},{4,6,573},{7,2,1517},
+{3,7,510},{3,6,236},{3,5,490},{5,5,1517},{3,5,490},{4,7,429},{4,7,429},{4,7,429},{4,5,546},{4,6,515},{4,5,299},{4,5,299},{4,5,475},{2,6,350},{3,5,190},{4,7,260},{4,7,260},{4,7,260},{5,5,328},{7,1,346},{3,6,40},{3,6,40},{3,5,90},{7,3,346},{3,5,90},{7,3,421},{4,7,13},{4,6,317},{3,6,200},{7,3,421},{6,5,421},{3,6,200},
+{0,5,481},{6,5,421},{0,5,481},{4,0,425},{4,0,425},{4,0,425},{4,0,425},{4,5,178},{4,5,178},{4,5,178},{4,4,205},{3,5,109},{3,5,109},{4,7,1862},{4,7,662},{4,6,998},{4,6,646},{4,7,1686},{4,6,759},{4,6,119},{4,5,859},{2,7,1590},{3,5,814},{5,7,521},{5,6,305},{5,6,145},{5,6,361},{5,6,1526},{3,7,446},{4,6,94},{3,5,810},{4,6,1526},
+{3,5,810},{4,7,637},{4,7,637},{4,7,637},{4,6,610},{4,6,435},{4,6,83},{4,6,83},{4,5,75},{1,7,565},{3,5,30},{5,6,109},{5,6,109},{5,6,109},{5,5,136},{6,3,340},{4,6,58},{4,6,58},{3,5,26},{6,4,340},{3,5,26},{5,7,421},{4,7,61},{5,6,45},{4,6,45},{5,7,421},{5,6,421},{4,6,45},{0,5,785},{5,6,421},{0,5,785},{4,0,601},
+{4,0,601},{4,0,601},{4,0,601},{4,5,50},{4,5,50},{4,5,50},{4,5,74},{3,5,29},{3,5,29},{5,7,1498},{5,7,1014},{5,6,994},{5,6,1018},{4,7,2198},{4,7,578},{4,6,39},{4,6,1183},{2,7,1878},{3,6,846},{5,7,537},{5,7,53},{5,6,33},{5,6,57},{7,3,1526},{4,7,569},{4,6,30},{2,6,758},{6,5,1526},{2,6,758},{5,6,990},{5,6,990},{5,6,990},
+{5,6,1014},{4,7,349},{4,6,35},{4,6,35},{4,5,59},{2,7,357},{3,5,254},{5,6,29},{5,6,29},{5,6,29},{5,6,53},{7,2,340},{4,6,26},{4,6,26},{4,5,50},{5,5,340},{4,5,50},{6,6,425},{5,7,49},{5,6,29},{4,6,29},{6,6,425},{4,7,425},{4,6,29},{0,6,733},{4,7,425},{0,6,733},{5,0,965},{5,0,965},{5,0,965},{5,0,965},{4,6,10},
+{4,6,10},{4,6,10},{4,5,10},{3,6,113},{3,6,113},{5,7,1466},{5,7,630},{5,6,834},{5,6,666},{5,7,2055},{4,7,642},{4,6,471},{4,6,751},{3,7,1766},{3,6,462},{5,7,937},{5,7,101},{5,6,305},{5,6,137},{5,7,1526},{4,7,521},{5,6,270},{3,6,461},{5,6,1526},{3,6,461},{5,7,566},{5,7,566},{5,7,566},{5,6,566},{4,7,621},{4,7,201},{4,7,201},
+{4,5,427},{2,7,469},{3,6,362},{5,7,37},{5,7,37},{5,7,37},{5,6,37},{5,6,338},{4,7,80},{4,7,80},{5,5,241},{4,6,338},{5,5,241},{7,5,425},{5,7,65},{6,6,164},{5,6,101},{7,5,425},{6,6,433},{5,6,101},{0,6,461},{6,6,433},{0,6,461},{5,0,565},{5,0,565},{5,0,565},{5,0,565},{4,7,137},{4,7,137},{4,7,137},{4,5,202},{3,6,1},
+{3,6,1},{5,7,2042},{5,7,810},{5,7,746},{5,7,790},{5,7,2073},{5,7,885},{4,7,651},{4,6,877},{4,7,2102},{4,6,598},{6,7,794},{6,7,530},{5,7,550},{5,7,594},{6,6,1526},{5,7,689},{4,7,251},{4,6,477},{6,6,1526},{4,6,477},{5,7,521},{5,7,521},{5,7,521},{5,6,521},{5,7,552},{5,6,312},{5,6,312},{4,6,516},{3,7,349},{4,6,237},{5,7,325},
+{5,7,325},{5,7,325},{5,6,325},{6,5,340},{4,7,26},{4,7,26},{4,6,116},{3,7,340},{4,6,116},{6,7,433},{6,7,169},{5,7,325},{4,7,226},{6,7,433},{7,6,425},{4,7,226},{0,6,461},{7,6,425},{0,6,461},{5,0,421},{5,0,421},{5,0,421},{5,0,421},{5,6,212},{5,6,212},{5,6,212},{5,5,221},{4,6,137},{4,6,137},{6,7,2362},{5,7,1514},{5,7,938},
+{5,7,630},{5,7,2633},{5,7,741},{5,7,165},{5,6,833},{4,7,2070},{4,6,758},{6,7,762},{6,7,306},{6,7,186},{6,7,426},{7,5,1526},{5,7,705},{5,7,129},{4,6,749},{5,7,1541},{4,6,749},{5,7,889},{5,7,889},{5,7,889},{5,7,581},{5,7,424},{5,7,116},{5,7,116},{5,6,104},{3,7,525},{4,6,29},{6,7,137},{6,7,137},{6,7,137},{6,6,146},{7,4,338},
+{5,7,80},{5,7,80},{4,6,20},{7,5,338},{4,6,20},{7,6,433},{6,7,185},{6,7,65},{5,7,65},{7,6,433},{6,7,425},{5,7,65},{0,6,733},{6,7,425},{0,6,733},{5,0,565},{5,0,565},{5,0,565},{5,0,565},{5,6,52},{5,6,52},{5,6,52},{5,6,100},{4,6,25},{4,6,25},{6,7,2073},{6,7,1449},{6,7,1049},{5,7,981},{6,7,2548},{5,7,1044},{5,7,20},
+{5,6,1196},{5,7,2365},{4,7,929},{6,7,1049},{6,7,425},{6,7,25},{6,7,73},{7,6,1492},{6,7,948},{5,7,16},{3,7,800},{7,6,1460},{3,7,800},{6,7,1049},{6,7,1049},{6,7,1049},{5,7,981},{5,7,680},{5,7,20},{5,7,20},{5,6,40},{4,7,434},{4,6,205},{6,7,25},{6,7,25},{6,7,25},{6,7,73},{7,5,370},{5,7,16},{5,7,16},{5,6,36},{6,6,338},
+{5,6,36},{7,7,410},{7,7,338},{6,7,16},{5,7,16},{7,7,410},{6,7,464},{5,7,16},{0,7,784},{6,7,464},{0,7,784},{5,0,965},{5,0,965},{5,0,965},{5,0,965},{5,7,4},{5,7,4},{5,7,4},{5,6,4},{4,7,145},{4,7,145},{6,7,1769},{6,7,1145},{6,7,745},{6,7,601},{6,7,1940},{6,7,1172},{5,7,308},{5,7,696},{5,7,1805},{4,7,401},{7,7,1043},
+{6,7,569},{6,7,169},{6,7,25},{7,6,1076},{6,7,596},{6,7,196},{4,7,401},{6,7,1076},{4,7,401},{6,7,745},{6,7,745},{6,7,745},{6,7,601},{6,7,916},{5,7,308},{5,7,308},{5,6,360},{4,7,626},{5,6,341},{6,7,169},{6,7,169},{6,7,169},{6,7,25},{6,7,340},{6,7,196},{6,7,196},{6,6,221},{5,7,340},{6,6,221},{7,7,202},{7,7,130},{7,7,81},
+{6,7,0},{7,7,202},{7,7,218},{6,7,0},{0,7,400},{7,7,218},{0,7,400},{6,0,601},{6,0,601},{6,0,601},{6,0,601},{5,7,164},{5,7,164},{5,7,164},{5,6,164},{4,7,1},{4,7,1},{6,7,1886},{6,7,1262},{6,7,862},{6,7,502},{6,7,1715},{6,7,731},{6,7,331},{5,7,507},{5,7,1634},{4,7,266},{7,7,521},{7,7,449},{7,7,400},{6,7,277},{7,7,797},
+{6,7,506},{6,7,106},{5,7,146},{6,7,770},{5,7,146},{6,7,862},{6,7,862},{6,7,862},{6,7,502},{6,7,691},{6,7,331},{6,7,331},{5,7,507},{5,7,610},{4,7,266},{7,7,400},{7,7,400},{7,7,400},{6,7,277},{7,6,338},{6,7,106},{6,7,106},{5,7,146},{7,6,370},{5,7,146},{7,7,121},{7,7,49},{7,7,0},{7,7,16},{7,7,121},{7,7,65},{7,7,16},
+{0,7,121},{7,7,65},{0,7,121},{6,0,421},{6,0,421},{6,0,421},{6,0,421},{6,7,250},{6,7,250},{6,7,250},{6,6,241},{4,7,145},{4,7,145},{7,7,2010},{6,7,1774},{6,7,1374},{6,7,822},{6,7,1923},{6,7,747},{6,7,347},{6,7,139},{6,7,1446},{5,7,34},{7,7,329},{7,7,257},{7,7,208},{7,7,160},{7,7,509},{7,7,389},{6,7,298},{5,7,18},{7,7,549},
+{5,7,18},{6,7,1374},{6,7,1374},{6,7,1374},{6,7,822},{6,7,899},{6,7,347},{6,7,347},{6,7,139},{5,7,866},{5,7,34},{7,7,208},{7,7,208},{7,7,208},{7,7,160},{7,7,388},{6,7,298},{6,7,298},{5,7,18},{6,7,370},{5,7,18},{7,7,185},{7,7,113},{7,7,64},{7,7,16},{7,7,185},{7,7,65},{7,7,16},{0,7,9},{7,7,65},{0,7,9},{6,0,533},
+{6,0,533},{6,0,533},{6,0,533},{6,7,58},{6,7,58},{6,7,58},{6,7,130},{5,7,25},{5,7,25},{7,7,1347},{7,7,1275},{7,7,1226},{7,7,1154},{7,7,1431},{6,7,922},{6,7,522},{6,7,2},{6,7,1125},{5,7,137},{7,7,258},{7,7,186},{7,7,137},{7,7,65},{7,7,342},{7,7,198},{7,7,149},{6,7,1},{7,7,294},{6,7,1},{7,7,1226},{7,7,1226},{7,7,1226},
+{7,7,1154},{6,7,1146},{6,7,522},{6,7,522},{6,7,2},{6,7,725},{5,7,137},{7,7,137},{7,7,137},{7,7,137},{7,7,65},{7,7,221},{7,7,149},{7,7,149},{6,7,1},{7,7,245},{6,7,1},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,901},{6,0,901},{6,0,901},{6,0,901},{6,7,122},
+{6,7,122},{6,7,122},{6,7,2},{5,7,137},{5,7,137},{7,7,883},{7,7,811},{7,7,762},{7,7,690},{7,7,871},{7,7,727},{7,7,678},{6,7,130},{6,7,949},{6,7,149},{7,7,258},{7,7,186},{7,7,137},{7,7,65},{7,7,246},{7,7,102},{7,7,53},{7,7,36},{7,7,134},{7,7,36},{7,7,762},{7,7,762},{7,7,762},{7,7,690},{7,7,750},{7,7,678},{7,7,678},
+{6,7,130},{6,7,549},{6,7,149},{7,7,137},{7,7,137},{7,7,137},{7,7,65},{7,7,125},{7,7,53},{7,7,53},{7,7,36},{7,7,85},{7,7,36},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{7,0,641},{7,0,641},{7,0,641},{7,0,641},{6,7,442},{6,7,442},{6,7,442},{6,7,130},{6,7,149},
+{6,7,149},{0,3,932},{0,2,218},{0,1,82},{0,1,250},{0,2,1971},{0,1,1371},{0,1,611},{0,0,1950},{0,1,2332},{0,0,1986},{0,3,932},{0,2,218},{0,1,82},{0,1,250},{1,0,1899},{0,1,1371},{0,1,611},{0,0,1950},{1,0,1923},{0,0,1950},{0,1,1},{0,1,1},{0,1,1},{0,0,64},{0,0,180},{0,0,100},{0,0,100},{0,0,101},{0,0,200},{0,0,137},{0,1,1},
+{0,1,1},{0,1,1},{0,0,64},{0,0,180},{0,0,100},{0,0,100},{0,0,101},{0,0,164},{0,0,101},{1,1,884},{0,2,218},{0,1,82},{0,1,250},{1,1,884},{2,0,900},{0,1,250},{0,1,1170},{2,0,900},{0,1,1170},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,3,900},{0,2,250},{0,2,314},
+{0,1,314},{0,2,2355},{0,1,1755},{0,1,675},{0,1,1875},{0,1,2716},{0,1,2236},{0,3,900},{0,2,250},{0,2,314},{0,1,314},{0,2,2355},{0,1,1755},{0,1,675},{0,1,1875},{0,1,2355},{0,1,1875},{0,2,25},{0,2,25},{0,2,25},{0,1,25},{0,1,410},{0,0,292},{0,0,292},{0,0,181},{0,0,392},{0,0,217},{0,2,25},{0,2,25},{0,2,25},{0,1,25},{0,1,410},
+{0,0,292},{0,0,292},{0,0,181},{0,0,356},{0,0,181},{2,0,884},{0,2,250},{0,2,314},{0,1,314},{2,0,884},{3,0,884},{0,1,314},{0,1,914},{3,0,884},{0,1,914},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,4,890},{0,3,104},{0,2,90},{0,2,442},{0,2,2995},{0,2,1851},{0,1,995},
+{0,1,1875},{0,1,3356},{0,1,2236},{0,4,890},{0,3,104},{0,2,90},{0,2,442},{1,1,2932},{0,2,1851},{0,1,995},{0,1,1875},{2,0,2900},{0,1,1875},{0,2,9},{0,2,9},{0,2,9},{0,1,9},{0,1,586},{0,1,370},{0,1,370},{0,0,389},{0,0,712},{0,0,425},{0,2,9},{0,2,9},{0,2,9},{0,1,9},{0,1,586},{0,1,370},{0,1,370},{0,0,389},{1,0,650},
+{0,0,389},{1,2,890},{0,3,104},{0,2,90},{0,2,442},{1,2,890},{2,1,890},{0,2,442},{0,1,914},{2,1,890},{0,1,914},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,4,990},{0,3,140},{0,2,158},{0,2,158},{0,3,3048},{0,2,1707},{0,2,747},{0,1,1795},{0,1,3916},{0,1,2156},{0,4,990},
+{0,3,140},{0,2,158},{0,2,158},{0,3,3048},{0,2,1707},{0,2,747},{0,1,1795},{1,1,3048},{0,1,1795},{0,3,40},{0,3,40},{0,3,40},{0,1,157},{0,1,698},{0,1,290},{0,1,290},{0,0,641},{0,0,1076},{0,0,677},{0,3,40},{0,3,40},{0,3,40},{0,1,157},{1,0,666},{0,1,290},{0,1,290},{0,0,641},{1,0,650},{0,0,641},{2,1,890},{0,3,104},{0,2,122},
+{0,2,122},{2,1,890},{4,0,890},{0,2,122},{0,1,1170},{4,0,890},{0,1,1170},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,0,0},{0,0,0},{0,0,0},{0,0,16},{0,0,52},{0,0,52},{0,5,1115},{0,4,265},{0,2,689},{0,2,293},{0,4,3096},{0,3,1731},{0,2,324},{0,1,2020},{0,2,4009},{0,1,2381},{0,5,1115},{0,4,265},{1,2,429},{0,2,293},{1,2,3048},
+{0,3,1731},{0,2,324},{0,1,2020},{0,2,3048},{0,1,2020},{0,4,261},{0,4,261},{0,4,261},{0,2,229},{0,2,656},{0,2,260},{0,2,260},{0,1,256},{0,1,1017},{0,1,617},{0,4,261},{0,4,261},{0,4,261},{0,2,229},{0,2,656},{0,2,260},{0,2,260},{0,1,256},{0,1,656},{0,1,256},{3,0,890},{0,4,40},{1,2,68},{0,2,68},{3,0,890},{5,0,890},{0,2,68},
+{0,2,1220},{5,0,890},{0,2,1220},{0,0,225},{0,0,225},{0,0,225},{0,0,225},{0,1,16},{0,1,16},{0,1,16},{0,0,25},{0,0,61},{0,0,61},{0,6,1419},{0,4,569},{0,3,1078},{0,2,821},{0,4,3096},{0,3,1395},{0,2,356},{0,2,1832},{0,2,4201},{0,2,2793},{1,4,1011},{1,3,353},{1,2,413},{1,2,413},{2,1,3048},{0,3,1395},{0,2,356},{0,2,1832},{4,0,3048},
+{0,2,1832},{0,4,533},{0,4,533},{0,4,533},{0,2,565},{0,3,666},{0,2,100},{0,2,100},{0,1,128},{0,1,1209},{0,1,489},{1,2,157},{1,2,157},{1,2,157},{1,2,157},{1,1,650},{0,2,100},{0,2,100},{0,1,128},{1,1,666},{0,1,128},{3,1,890},{0,4,40},{1,2,292},{0,2,292},{3,1,890},{4,1,890},{0,2,292},{0,2,932},{4,1,890},{0,2,932},{0,0,529},
+{0,0,529},{0,0,529},{0,0,529},{0,1,16},{0,1,16},{0,1,16},{0,1,64},{0,0,205},{0,0,205},{0,6,1915},{0,5,1019},{1,3,1269},{0,3,1110},{0,5,3051},{0,3,1443},{0,3,318},{0,2,1384},{0,2,4777},{0,2,2345},{1,5,909},{1,4,131},{1,3,113},{1,3,509},{3,0,3051},{0,3,1443},{0,3,318},{0,2,1384},{3,1,3051},{0,2,1384},{0,5,970},{0,5,970},{0,5,970},
+{0,3,1010},{0,3,698},{0,2,196},{0,2,196},{0,1,256},{0,2,1641},{0,1,617},{1,3,13},{1,3,13},{1,3,13},{1,2,13},{2,0,650},{0,2,196},{0,2,196},{0,1,256},{3,0,650},{0,1,256},{2,3,884},{0,5,58},{1,3,104},{0,3,149},{2,3,884},{6,0,884},{0,3,149},{0,2,900},{6,0,884},{0,2,900},{0,0,961},{0,0,961},{0,0,961},{0,0,961},{0,2,0},
+{0,2,0},{0,2,0},{0,1,0},{0,1,361},{0,1,361},{1,5,2113},{1,4,1271},{1,3,1285},{1,3,1329},{0,6,3123},{0,4,1208},{0,3,30},{0,2,1320},{0,3,5011},{0,2,2281},{1,5,957},{1,4,115},{1,3,129},{1,3,173},{1,4,3051},{0,4,1208},{0,3,30},{0,2,1320},{2,2,3051},{0,2,1320},{1,4,1190},{1,4,1190},{1,4,1190},{1,2,1281},{0,4,648},{0,3,26},{0,3,26},
+{0,2,296},{0,2,1641},{0,1,1001},{1,4,34},{1,4,34},{1,4,34},{1,2,125},{0,4,648},{0,3,26},{0,3,26},{0,2,296},{2,1,648},{0,2,296},{3,2,884},{0,5,26},{1,3,104},{0,3,5},{3,2,884},{5,1,884},{0,3,5},{0,2,1124},{5,1,884},{0,2,1124},{1,0,1181},{1,0,1181},{1,0,1181},{1,0,1181},{0,3,25},{0,3,25},{0,3,25},{0,1,64},{0,1,425},
+{0,1,425},{1,6,1864},{1,5,1038},{1,3,1390},{1,3,1038},{0,6,3132},{0,4,1199},{0,3,201},{0,2,1743},{0,3,4924},{0,2,2332},{1,6,1080},{1,5,254},{2,3,458},{1,3,254},{2,3,3051},{0,4,1163},{0,3,165},{0,2,1707},{6,0,3051},{0,2,1707},{1,4,1016},{1,4,1016},{1,4,1016},{1,3,989},{0,5,716},{0,3,152},{0,3,152},{0,2,62},{0,2,1611},{0,2,651},{1,4,232},
+{1,4,232},{1,4,232},{1,3,205},{1,3,650},{0,3,116},{0,3,116},{0,2,26},{1,2,650},{0,2,26},{4,1,884},{1,5,58},{2,3,58},{1,3,58},{4,1,884},{4,2,884},{1,3,58},{0,3,1274},{4,2,884},{0,3,1274},{1,0,980},{1,0,980},{1,0,980},{1,0,980},{0,3,52},{0,3,52},{0,3,52},{0,2,61},{0,1,458},{0,1,458},{1,7,1784},{1,5,910},{1,4,1441},
+{1,3,1134},{0,7,3247},{0,5,1292},{0,4,567},{0,3,1474},{0,4,4900},{0,3,2178},{2,5,1028},{2,4,362},{2,3,394},{2,3,418},{3,2,3051},{0,5,1096},{1,3,331},{0,3,1278},{5,1,3051},{0,3,1278},{1,5,885},{1,5,885},{1,5,885},{1,3,909},{0,5,876},{0,4,206},{0,4,206},{0,2,254},{0,3,1548},{0,2,347},{2,3,169},{2,3,169},{2,3,169},{2,3,193},{2,2,648},
+{0,4,10},{0,4,10},{0,2,58},{5,0,648},{0,2,58},{5,0,884},{1,5,26},{2,3,250},{1,3,250},{5,0,884},{3,3,884},{1,3,250},{0,3,954},{3,3,884},{0,3,954},{1,0,884},{1,0,884},{1,0,884},{1,0,884},{0,4,197},{0,4,197},{0,4,197},{0,2,205},{0,2,298},{0,2,298},{1,7,1976},{1,6,1124},{1,4,1649},{1,4,1229},{1,6,3204},{0,5,1452},{1,4,525},
+{0,3,1474},{0,4,4420},{0,3,1474},{2,6,930},{2,5,160},{2,4,138},{2,3,546},{4,1,3060},{0,5,968},{0,4,195},{0,3,990},{4,2,3060},{0,3,990},{1,6,1060},{1,6,1060},{1,6,1060},{1,4,1108},{1,4,824},{1,3,314},{1,3,314},{1,2,370},{0,3,1260},{0,2,427},{2,4,17},{2,4,17},{2,4,17},{2,3,17},{3,1,648},{0,4,74},{0,4,74},{1,2,226},{4,1,648},
+{1,2,226},{3,4,882},{1,6,80},{2,4,122},{0,4,146},{3,4,882},{7,1,882},{0,4,146},{0,3,890},{7,1,882},{0,3,890},{1,0,1044},{1,0,1044},{1,0,1044},{1,0,1044},{1,3,145},{1,3,145},{1,3,145},{1,2,145},{0,2,202},{0,2,202},{2,6,2374},{1,6,1476},{2,4,1550},{1,4,1469},{1,6,3172},{1,5,1259},{1,4,61},{1,3,1323},{0,4,4452},{0,3,1282},{2,6,930},
+{2,5,96},{2,4,106},{2,4,194},{5,0,3060},{0,6,1144},{1,4,45},{0,3,1086},{6,1,3060},{0,3,1086},{2,5,1476},{2,5,1476},{2,5,1476},{1,4,1460},{1,5,666},{1,4,52},{1,4,52},{1,3,362},{0,3,1356},{0,3,321},{2,5,32},{2,5,32},{2,5,32},{2,3,97},{4,0,650},{1,4,36},{1,4,36},{0,3,125},{3,2,650},{0,3,125},{4,3,882},{1,6,16},{2,4,90},
+{1,4,9},{4,3,882},{6,2,882},{1,4,9},{0,3,1082},{6,2,882},{0,3,1082},{1,0,1460},{1,0,1460},{1,0,1460},{1,0,1460},{1,4,52},{1,4,52},{1,4,52},{1,2,65},{0,3,200},{0,3,200},{2,7,1892},{2,6,1090},{2,4,1370},{2,4,1062},{1,7,3100},{1,5,1169},{1,4,151},{1,3,1665},{0,5,4036},{0,3,1678},{2,7,1051},{2,6,249},{3,4,493},{2,4,221},{3,4,3060},
+{0,6,883},{1,4,126},{0,4,1528},{7,1,3060},{0,4,1528},{2,5,1035},{2,5,1035},{2,5,1035},{2,4,1026},{1,6,723},{1,4,115},{1,4,115},{1,3,65},{0,4,1004},{0,3,78},{2,5,194},{2,5,194},{2,5,194},{2,4,185},{2,4,648},{1,4,90},{1,4,90},{1,3,40},{7,0,648},{1,3,40},{5,2,882},{2,6,80},{3,4,52},{2,4,52},{5,2,882},{5,3,882},{2,4,52},
+{0,4,1332},{5,3,882},{0,4,1332},{2,0,1010},{2,0,1010},{2,0,1010},{2,0,1010},{1,4,34},{1,4,34},{1,4,34},{1,3,61},{0,3,74},{0,3,74},{2,7,1892},{2,6,898},{2,5,1451},{2,4,1094},{2,6,3501},{1,6,1308},{1,5,589},{1,4,1510},{0,5,3940},{0,4,1116},{3,6,1051},{3,5,377},{3,4,381},{3,4,429},{5,1,3060},{0,6,1059},{2,4,312},{0,4,1016},{6,2,3060},
+{0,4,1016},{2,6,882},{2,6,882},{2,6,882},{2,4,898},{1,6,835},{1,5,189},{1,5,189},{1,3,209},{0,4,1036},{0,3,270},{3,4,185},{3,4,185},{3,4,185},{3,4,233},{3,3,650},{1,5,20},{1,5,20},{1,3,40},{6,1,650},{1,3,40},{6,1,882},{2,6,16},{3,4,212},{2,4,212},{6,1,882},{4,4,882},{2,4,212},{0,4,980},{4,4,882},{0,4,980},{2,0,882},
+{2,0,882},{2,0,882},{2,0,882},{1,5,173},{1,5,173},{1,5,173},{1,3,173},{0,4,136},{0,4,136},{2,7,2404},{2,7,1116},{2,5,1595},{2,5,1235},{2,7,3244},{1,6,1404},{2,5,619},{1,4,1446},{0,6,3804},{0,4,892},{3,7,957},{3,6,195},{3,5,169},{3,4,509},{6,0,3060},{0,7,936},{1,5,196},{0,4,888},{3,4,3060},{0,4,888},{2,7,1035},{2,7,1035},{2,7,1035},
+{2,5,1091},{2,5,835},{2,4,317},{2,4,317},{2,3,369},{0,5,875},{1,3,396},{3,5,25},{3,5,25},{3,5,25},{3,4,25},{4,2,650},{1,5,52},{1,5,52},{2,3,200},{5,2,650},{2,3,200},{7,0,884},{2,7,106},{3,5,144},{1,5,160},{7,0,884},{3,5,884},{1,5,160},{0,4,884},{3,5,884},{0,4,884},{2,0,1010},{2,0,1010},{2,0,1010},{2,0,1010},{2,4,173},
+{2,4,173},{2,4,173},{2,3,173},{0,4,8},{0,4,8},{3,7,2430},{2,7,1404},{3,5,1610},{2,5,1411},{2,7,3148},{2,6,1309},{2,5,91},{2,4,1325},{0,6,3484},{0,4,1180},{3,7,909},{3,6,83},{3,5,89},{3,5,221},{4,4,3051},{0,7,1000},{2,5,66},{1,4,1053},{7,2,3051},{1,4,1053},{2,7,1403},{2,7,1403},{2,7,1403},{2,5,1395},{2,6,681},{2,5,75},{2,5,75},
+{2,4,425},{0,5,795},{0,4,280},{3,6,34},{3,6,34},{3,6,34},{3,4,73},{5,1,656},{2,5,50},{2,5,50},{1,4,153},{7,1,656},{1,4,153},{5,4,884},{2,7,10},{3,5,80},{2,5,17},{5,4,884},{7,3,884},{2,5,17},{0,4,1044},{7,3,884},{0,4,1044},{2,0,1394},{2,0,1394},{2,0,1394},{2,0,1394},{2,4,61},{2,4,61},{2,4,61},{2,3,61},{0,4,136},
+{0,4,136},{3,7,2214},{3,7,1150},{3,5,1358},{3,5,1094},{2,7,3652},{2,6,1147},{2,5,109},{2,4,1595},{0,7,3724},{0,5,1402},{3,7,1314},{3,7,250},{3,5,458},{3,5,194},{5,3,3060},{1,7,888},{2,5,93},{0,5,1398},{6,3,3060},{0,5,1398},{3,6,1060},{3,6,1060},{3,6,1060},{3,5,1069},{2,7,736},{2,5,84},{2,5,84},{2,4,74},{0,6,820},{1,4,81},{3,6,160},
+{3,6,160},{3,6,160},{3,5,169},{6,0,650},{2,5,68},{2,5,68},{1,4,45},{3,4,650},{1,4,45},{6,3,884},{3,7,106},{4,5,50},{3,5,50},{6,3,884},{6,4,884},{3,5,50},{0,5,1394},{6,4,884},{0,5,1394},{3,0,1044},{3,0,1044},{3,0,1044},{3,0,1044},{2,5,20},{2,5,20},{2,5,20},{2,4,65},{0,5,8},{0,5,8},{3,7,2566},{3,7,894},{3,6,1469},
+{3,5,1062},{3,7,3535},{2,7,1332},{2,6,619},{2,5,1554},{0,7,3276},{0,5,1146},{4,7,1080},{4,6,398},{4,5,374},{4,5,446},{6,2,3051},{1,7,1016},{3,5,299},{0,5,1046},{5,4,3051},{0,5,1046},{3,7,885},{3,7,885},{3,7,885},{3,5,893},{2,7,800},{2,6,178},{2,6,178},{2,4,170},{0,6,660},{1,4,225},{4,5,205},{4,5,205},{4,5,205},{4,5,277},{5,2,656},
+{2,6,34},{2,6,34},{2,4,26},{7,2,656},{2,4,26},{7,2,884},{3,7,10},{4,5,178},{3,5,178},{7,2,884},{5,5,884},{3,5,178},{0,5,1010},{5,5,884},{0,5,1010},{3,0,884},{3,0,884},{3,0,884},{3,0,884},{2,6,153},{2,6,153},{2,6,153},{2,4,145},{0,5,136},{0,5,136},{4,7,3320},{3,7,1150},{3,6,1549},{3,6,1249},{3,7,3487},{2,7,1364},{2,6,603},
+{2,5,1426},{0,7,3340},{1,5,892},{4,7,1016},{4,7,236},{4,6,206},{4,5,478},{7,1,3051},{2,7,964},{2,6,203},{1,5,883},{4,5,3051},{1,5,883},{3,7,1029},{3,7,1029},{3,7,1029},{3,6,1080},{3,6,852},{3,5,326},{3,5,326},{3,4,374},{0,6,884},{2,4,371},{4,6,37},{4,6,37},{4,6,37},{4,5,37},{6,1,656},{2,6,34},{2,6,34},{3,4,178},{6,3,656},
+{3,4,178},{5,6,890},{3,7,170},{4,6,170},{2,6,178},{5,6,890},{4,6,890},{2,6,178},{0,5,882},{4,6,890},{0,5,882},{3,0,980},{3,0,980},{3,0,980},{3,0,980},{3,5,205},{3,5,205},{3,5,205},{3,4,205},{1,5,10},{1,5,10},{4,7,2936},{4,7,1676},{4,6,1678},{3,6,1361},{3,7,3951},{3,7,1367},{3,6,129},{3,5,1335},{1,7,3496},{1,5,1116},{4,7,1336},
+{4,7,76},{4,6,78},{4,6,254},{5,5,3048},{2,7,1124},{3,6,93},{2,5,1026},{3,6,3048},{2,5,1026},{3,7,1557},{3,7,1557},{3,7,1557},{3,6,1336},{3,7,702},{3,6,104},{3,6,104},{3,5,494},{0,7,667},{1,5,275},{4,7,40},{4,7,40},{4,7,40},{4,5,53},{7,0,650},{3,6,68},{3,6,68},{2,5,185},{3,5,650},{2,5,185},{7,3,890},{4,7,72},{4,6,74},
+{3,6,29},{7,3,890},{6,5,890},{3,6,29},{0,5,1010},{6,5,890},{0,5,1010},{3,0,1332},{3,0,1332},{3,0,1332},{3,0,1332},{3,5,61},{3,5,61},{3,5,61},{3,4,61},{1,5,106},{1,5,106},{4,7,3116},{4,7,1316},{4,6,1354},{4,6,1134},{4,7,4084},{3,7,1133},{3,6,75},{3,5,1533},{1,7,3676},{1,6,1470},{5,7,1429},{4,7,355},{4,6,393},{4,6,173},{6,4,3051},
+{3,7,1124},{3,6,66},{1,6,1469},{7,4,3051},{1,6,1469},{4,7,1091},{4,7,1091},{4,7,1091},{4,6,1118},{3,7,729},{3,6,59},{3,6,59},{3,5,89},{0,7,820},{2,5,90},{4,7,130},{4,7,130},{4,7,130},{4,6,157},{7,1,656},{3,6,50},{3,6,50},{2,5,41},{7,3,656},{2,5,41},{7,4,890},{4,7,234},{5,6,52},{4,6,52},{7,4,890},{7,5,890},{4,6,52},
+{0,5,1460},{7,5,890},{0,5,1460},{4,0,1082},{4,0,1082},{4,0,1082},{4,0,1082},{3,6,10},{3,6,10},{3,6,10},{3,5,73},{1,6,10},{1,6,10},{4,7,3820},{4,7,1540},{4,7,1495},{4,6,1038},{4,7,4084},{3,7,1469},{3,6,571},{3,6,1606},{2,7,3916},{1,6,1150},{5,7,1349},{5,7,425},{5,6,373},{5,6,469},{7,3,3048},{3,7,1348},{4,6,292},{1,6,1069},{6,5,3048},
+{1,6,1069},{4,7,1011},{4,7,1011},{4,7,1011},{4,6,894},{3,7,1161},{3,7,173},{3,7,173},{3,5,137},{1,7,659},{2,5,186},{5,6,229},{5,6,229},{5,6,229},{5,6,325},{6,3,650},{3,7,52},{3,7,52},{3,5,16},{6,4,650},{3,5,16},{6,6,890},{5,7,200},{5,6,148},{4,6,148},{6,6,890},{6,6,890},{4,6,148},{0,6,1044},{6,6,890},{0,6,1044},{4,0,890},
+{4,0,890},{4,0,890},{4,0,890},{3,7,137},{3,7,137},{3,7,137},{3,5,121},{1,6,106},{1,6,106},{5,7,4054},{4,7,2276},{4,7,1511},{4,7,1271},{4,7,4596},{4,7,1596},{3,7,577},{3,6,1414},{2,7,4204},{2,6,900},{5,7,1653},{5,7,377},{5,7,249},{5,6,453},{5,7,3048},{4,7,1371},{3,7,216},{2,6,884},{5,6,3048},{2,6,884},{4,7,1315},{4,7,1315},{4,7,1315},
+{4,6,1054},{4,7,875},{4,6,341},{4,6,341},{4,5,385},{1,7,835},{3,5,352},{5,7,53},{5,7,53},{5,7,53},{5,6,53},{7,2,650},{3,7,20},{3,7,20},{4,5,160},{5,5,650},{4,5,160},{7,5,890},{5,7,328},{5,7,200},{3,7,200},{7,5,890},{5,7,900},{3,7,200},{0,6,884},{5,7,900},{0,6,884},{4,0,954},{4,0,954},{4,0,954},{4,0,954},{4,6,241},
+{4,6,241},{4,6,241},{4,5,241},{2,6,16},{2,6,16},{5,7,4022},{5,7,2394},{5,7,1754},{4,7,1319},{5,7,4921},{4,7,1660},{4,7,175},{4,6,1353},{3,7,4380},{2,6,1060},{6,7,2021},{5,7,713},{5,7,73},{5,7,293},{6,6,3051},{4,7,1611},{4,7,126},{3,6,1005},{4,7,3051},{3,6,1005},{5,7,1718},{5,7,1718},{5,7,1718},{4,7,1283},{4,7,859},{4,7,139},{4,7,139},
+{4,5,465},{2,7,779},{2,6,276},{5,7,37},{5,7,37},{5,7,37},{5,6,37},{5,6,648},{4,7,90},{4,7,90},{3,6,221},{4,6,648},{3,6,221},{7,6,900},{6,7,452},{5,7,72},{4,7,45},{7,6,900},{7,6,884},{4,7,45},{0,6,980},{7,6,884},{0,6,980},{4,0,1274},{4,0,1274},{4,0,1274},{4,0,1274},{4,6,65},{4,6,65},{4,6,65},{4,5,65},{2,6,80},
+{2,6,80},{5,7,4265},{5,7,2373},{5,7,1349},{5,7,1173},{5,7,4606},{4,7,2065},{4,7,40},{4,6,1266},{3,7,4455},{3,6,1261},{6,7,1649},{6,7,1025},{5,7,325},{5,7,149},{7,5,2817},{5,7,1514},{4,7,36},{3,6,1197},{6,6,2841},{3,6,1197},{5,7,1349},{5,7,1349},{5,7,1349},{5,7,1173},{4,7,1300},{4,7,40},{4,7,40},{4,6,110},{2,7,1040},{3,6,105},{5,7,325},
+{5,7,325},{5,7,325},{5,7,149},{6,5,650},{4,7,36},{4,7,36},{3,6,41},{3,7,650},{3,6,41},{7,6,801},{6,7,449},{6,7,49},{4,7,36},{7,6,801},{6,7,761},{4,7,36},{0,6,1181},{6,7,761},{0,6,1181},{5,0,1124},{5,0,1124},{5,0,1124},{5,0,1124},{4,7,4},{4,7,4},{4,7,4},{4,6,85},{2,7,16},{2,7,16},{5,7,4345},{5,7,2453},{5,7,1429},
+{5,7,901},{5,7,4190},{5,7,1770},{4,7,360},{4,6,1266},{4,7,3861},{2,7,1041},{6,7,1281},{6,7,657},{6,7,257},{5,7,325},{6,7,2250},{5,7,1194},{5,7,170},{2,7,977},{5,7,2250},{2,7,977},{5,7,1429},{5,7,1429},{5,7,1429},{5,7,901},{5,7,1274},{4,7,360},{4,7,360},{4,6,110},{3,7,979},{3,6,153},{6,7,257},{6,7,257},{6,7,257},{5,7,325},{7,4,648},
+{5,7,170},{5,7,170},{4,6,10},{7,5,648},{4,6,10},{7,7,521},{6,7,401},{6,7,1},{5,7,1},{7,7,521},{6,7,521},{5,7,1},{0,7,961},{6,7,521},{0,7,961},{5,0,900},{5,0,900},{5,0,900},{5,0,900},{4,7,164},{4,7,164},{4,7,164},{4,6,101},{2,7,80},{2,7,80},{6,7,3669},{5,7,2917},{5,7,1893},{5,7,1013},{5,7,4158},{5,7,1386},{5,7,362},
+{4,7,1049},{4,7,3381},{3,7,555},{6,7,1169},{6,7,545},{6,7,145},{6,7,73},{7,6,1802},{5,7,1130},{5,7,106},{3,7,530},{7,6,1770},{3,7,530},{5,7,1893},{5,7,1893},{5,7,1893},{5,7,1013},{5,7,1242},{5,7,362},{5,7,362},{5,6,402},{3,7,1251},{4,6,339},{6,7,145},{6,7,145},{6,7,145},{6,7,73},{7,5,680},{5,7,106},{5,7,106},{5,6,146},{6,6,648},
+{5,6,146},{7,7,265},{7,7,193},{6,7,81},{6,7,9},{7,7,265},{7,7,305},{6,7,9},{0,7,529},{7,7,305},{0,7,529},{5,0,932},{5,0,932},{5,0,932},{5,0,932},{5,7,281},{5,7,281},{5,7,281},{5,6,281},{3,7,26},{3,7,26},{6,7,3077},{6,7,2453},{6,7,2053},{5,7,1509},{6,7,3438},{5,7,1386},{5,7,362},{5,7,650},{5,7,3195},{3,7,283},{7,7,1293},
+{6,7,689},{6,7,289},{6,7,25},{7,6,1386},{6,7,786},{5,7,298},{4,7,261},{6,7,1386},{4,7,261},{6,7,2053},{6,7,2053},{6,7,2053},{5,7,1509},{5,7,1594},{5,7,362},{5,7,362},{5,6,434},{4,7,1260},{3,7,283},{6,7,289},{6,7,289},{6,7,289},{6,7,25},{6,7,650},{5,7,298},{5,7,298},{4,7,261},{5,7,650},{4,7,261},{7,7,137},{7,7,65},{7,7,16},
+{6,7,25},{7,7,137},{7,7,113},{6,7,25},{0,7,225},{7,7,113},{0,7,225},{5,0,1220},{5,0,1220},{5,0,1220},{5,0,1220},{5,7,73},{5,7,73},{5,7,73},{5,6,73},{3,7,58},{3,7,58},{6,7,2870},{6,7,2246},{6,7,1846},{6,7,1366},{6,7,2889},{6,7,1785},{5,7,821},{5,7,137},{5,7,2700},{4,7,126},{7,7,771},{7,7,699},{7,7,650},{6,7,277},{7,7,1107},
+{6,7,696},{6,7,296},{4,7,45},{6,7,1080},{4,7,45},{6,7,1846},{6,7,1846},{6,7,1846},{6,7,1366},{6,7,1865},{5,7,821},{5,7,821},{5,7,137},{4,7,1611},{4,7,126},{7,7,650},{7,7,650},{7,7,650},{6,7,277},{7,6,648},{6,7,296},{6,7,296},{4,7,45},{7,6,680},{4,7,45},{7,7,146},{7,7,74},{7,7,25},{7,7,1},{7,7,146},{7,7,50},{7,7,1},
+{0,7,36},{7,7,50},{0,7,36},{6,0,1170},{6,0,1170},{6,0,1170},{6,0,1170},{5,7,145},{5,7,145},{5,7,145},{5,7,101},{4,7,90},{4,7,90},{6,7,2962},{6,7,2338},{6,7,1938},{6,7,1314},{6,7,2677},{6,7,1429},{6,7,1029},{5,7,85},{5,7,2536},{4,7,122},{7,7,531},{7,7,459},{7,7,410},{7,7,338},{7,7,771},{7,7,627},{6,7,404},{5,7,4},{7,7,827},
+{5,7,4},{6,7,1938},{6,7,1938},{6,7,1938},{6,7,1314},{6,7,1653},{6,7,1029},{6,7,1029},{5,7,85},{5,7,1512},{4,7,122},{7,7,410},{7,7,410},{7,7,410},{7,7,338},{7,7,650},{6,7,404},{6,7,404},{5,7,4},{6,7,596},{5,7,4},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,914},
+{6,0,914},{6,0,914},{6,0,914},{5,7,481},{5,7,481},{5,7,481},{5,7,85},{4,7,122},{4,7,122},{7,7,2924},{6,7,2338},{6,7,1938},{6,7,1314},{6,7,2373},{6,7,1125},{6,7,725},{5,7,325},{6,7,2132},{5,7,232},{7,7,323},{7,7,251},{7,7,202},{7,7,130},{7,7,467},{7,7,323},{7,7,274},{5,7,36},{7,7,459},{5,7,36},{6,7,1938},{6,7,1938},{6,7,1938},
+{6,7,1314},{6,7,1349},{6,7,725},{6,7,725},{5,7,325},{5,7,1256},{5,7,232},{7,7,202},{7,7,202},{7,7,202},{7,7,130},{7,7,346},{7,7,274},{7,7,274},{5,7,36},{7,7,410},{5,7,36},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,914},{6,0,914},{6,0,914},{6,0,914},{6,7,325},
+{6,7,325},{6,7,325},{5,7,325},{5,7,232},{5,7,232},{7,7,2092},{7,7,2020},{7,7,1971},{6,7,1570},{7,7,2140},{6,7,1077},{6,7,677},{6,7,85},{6,7,1588},{5,7,232},{7,7,243},{7,7,171},{7,7,122},{7,7,50},{7,7,291},{7,7,147},{7,7,98},{6,7,4},{7,7,219},{6,7,4},{7,7,1971},{7,7,1971},{7,7,1971},{6,7,1570},{6,7,1301},{6,7,677},{6,7,677},
+{6,7,85},{6,7,1188},{5,7,232},{7,7,122},{7,7,122},{7,7,122},{7,7,50},{7,7,170},{7,7,98},{7,7,98},{6,7,4},{7,7,170},{6,7,4},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,1170},{6,0,1170},{6,0,1170},{6,0,1170},{6,7,277},{6,7,277},{6,7,277},{6,7,85},{5,7,232},
+{5,7,232},{0,4,1618},{0,3,436},{0,2,74},{0,2,866},{0,2,3411},{0,2,2531},{0,1,1251},{0,1,2531},{0,1,3772},{0,1,2892},{0,4,1618},{0,3,436},{0,2,74},{0,2,866},{0,2,3411},{0,2,2531},{0,1,1251},{0,1,2531},{2,0,3376},{0,1,2531},{0,1,25},{0,1,25},{0,1,25},{0,1,49},{0,0,360},{0,0,232},{0,0,232},{0,0,149},{0,0,332},{0,0,185},{0,1,25},
+{0,1,25},{0,1,25},{0,1,49},{0,0,360},{0,0,232},{0,0,232},{0,0,149},{0,0,296},{0,0,149},{1,2,1570},{0,3,436},{0,2,74},{0,2,866},{1,2,1570},{0,2,1570},{0,2,866},{0,1,1570},{0,2,1570},{0,1,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,4,1586},{0,3,340},{0,2,10},
+{0,2,450},{0,3,4016},{0,2,2627},{0,2,1411},{0,1,2691},{0,1,4572},{0,1,3052},{0,4,1586},{0,3,340},{0,2,10},{0,2,450},{1,1,3968},{0,2,2627},{0,2,1411},{0,1,2691},{2,0,4016},{0,1,2691},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,530},{0,1,362},{0,1,362},{0,0,325},{0,0,620},{0,0,361},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,530},
+{0,1,362},{0,1,362},{0,0,325},{0,0,584},{0,0,325},{2,1,1570},{0,3,340},{0,2,10},{0,2,450},{2,1,1570},{4,0,1570},{0,2,450},{0,1,1730},{4,0,1570},{0,1,1730},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,5,1576},{0,4,290},{0,2,202},{0,2,290},{0,3,4656},{0,2,2979},{0,2,1251},
+{0,1,3107},{0,1,5628},{0,1,3468},{0,5,1576},{0,4,290},{0,2,202},{0,2,290},{0,3,4656},{0,2,2979},{0,2,1251},{0,1,3107},{1,1,4656},{0,1,3107},{0,3,16},{0,3,16},{0,3,16},{0,1,81},{0,1,802},{0,1,442},{0,1,442},{0,0,629},{0,0,1036},{0,0,665},{0,3,16},{0,3,16},{0,3,16},{0,1,81},{0,1,802},{0,1,442},{0,1,442},{0,0,629},{1,0,818},
+{0,0,629},{3,0,1576},{0,4,290},{0,2,202},{0,2,290},{3,0,1576},{3,1,1576},{0,2,290},{0,1,2146},{3,1,1576},{0,1,2146},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,5,1640},{0,4,162},{0,3,241},{0,2,386},{0,4,5539},{0,3,3512},{0,2,1347},{0,1,3779},{0,2,6396},{0,1,4140},{0,5,1640},
+{0,4,162},{0,3,241},{0,2,386},{1,2,5435},{0,3,3512},{0,2,1347},{0,1,3779},{0,2,5435},{0,1,3779},{0,3,16},{0,3,16},{0,3,16},{0,2,25},{0,1,1202},{0,1,650},{0,1,650},{0,1,970},{0,0,1580},{0,0,1097},{0,3,16},{0,3,16},{0,3,16},{0,2,25},{1,0,1170},{0,1,650},{0,1,650},{0,1,970},{1,0,1154},{0,1,970},{2,2,1576},{0,4,162},{0,3,241},
+{0,2,386},{2,2,1576},{5,0,1576},{0,2,386},{0,2,1730},{5,0,1576},{0,2,1730},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,6,1667},{0,5,259},{0,3,286},{0,3,406},{0,4,5440},{0,3,3035},{0,2,1284},{0,2,3504},{0,2,6513},{0,2,4465},{0,6,1667},{0,5,259},{0,3,286},{0,3,406},{2,1,5424},
+{0,3,3035},{0,2,1284},{0,2,3504},{4,0,5424},{0,2,3504},{0,4,81},{0,4,81},{0,4,81},{0,2,97},{0,2,1160},{0,2,500},{0,2,500},{0,1,520},{0,1,1521},{0,1,881},{0,4,81},{0,4,81},{0,4,81},{0,2,97},{0,2,1160},{0,2,500},{0,2,500},{0,1,520},{0,1,1160},{0,1,520},{2,3,1576},{0,5,178},{1,3,100},{0,3,325},{2,3,1576},{6,0,1576},{0,3,325},
+{0,2,1568},{6,0,1576},{0,2,1568},{0,0,81},{0,0,81},{0,0,81},{0,0,81},{0,0,9},{0,0,9},{0,0,9},{0,0,1},{0,0,37},{0,0,37},{0,7,1865},{0,5,339},{0,3,734},{0,3,374},{0,5,5435},{0,3,3019},{0,3,814},{0,2,2992},{0,2,7025},{0,2,3953},{1,5,1865},{0,5,339},{1,3,293},{0,3,374},{3,0,5435},{0,3,3019},{0,3,814},{0,2,2992},{3,1,5435},
+{0,2,2992},{0,5,314},{0,5,314},{0,5,314},{0,3,370},{0,3,1170},{0,2,340},{0,2,340},{0,1,392},{0,1,1713},{0,1,753},{1,3,289},{1,3,289},{1,3,289},{1,2,289},{1,1,1154},{0,2,340},{0,2,340},{0,1,392},{1,1,1170},{0,1,392},{4,0,1576},{0,5,50},{1,3,4},{0,3,85},{4,0,1576},{5,1,1576},{0,3,85},{0,2,1696},{5,1,1576},{0,2,1696},{0,0,289},
+{0,0,289},{0,0,289},{0,0,289},{0,1,4},{0,1,4},{0,1,4},{0,0,49},{0,0,85},{0,0,85},{0,7,2265},{0,6,787},{1,3,1401},{0,3,726},{0,5,5515},{0,4,2664},{0,3,462},{0,2,2864},{0,3,7363},{0,2,3825},{1,6,1667},{1,5,405},{1,3,245},{1,3,377},{2,2,5427},{0,4,2664},{0,3,462},{0,2,2864},{5,0,5427},{0,2,2864},{0,5,634},{0,5,634},{0,5,634},
+{0,3,626},{0,3,1202},{0,3,362},{0,3,362},{0,1,520},{0,2,2145},{0,1,881},{1,4,106},{1,4,106},{1,4,106},{1,2,145},{2,0,1154},{0,3,362},{0,3,362},{0,1,520},{3,0,1154},{0,1,520},{2,4,1576},{0,6,162},{1,3,164},{0,3,101},{2,4,1576},{7,0,1576},{0,3,101},{0,2,2080},{7,0,1576},{0,2,2080},{0,0,625},{0,0,625},{0,0,625},{0,0,625},{0,1,36},
+{0,1,36},{0,1,36},{0,1,36},{0,0,261},{0,0,261},{1,6,2775},{0,6,1091},{1,4,1422},{0,3,1462},{0,6,5427},{0,4,2536},{0,3,494},{0,2,3120},{0,3,7635},{0,2,4081},{1,6,1619},{1,5,165},{1,4,266},{1,3,361},{3,1,5427},{0,4,2536},{0,3,494},{0,2,3120},{4,1,5427},{0,2,3120},{0,6,1090},{0,6,1090},{0,6,1090},{0,3,1138},{0,4,1152},{0,3,170},{0,3,170},
+{0,2,416},{0,2,2145},{0,1,1265},{1,4,10},{1,4,10},{1,4,10},{1,3,37},{0,4,1152},{0,3,170},{0,3,170},{0,2,416},{2,1,1152},{0,2,416},{3,3,1570},{0,6,2},{1,4,265},{1,3,360},{3,3,1570},{6,1,1570},{1,3,360},{0,3,1768},{6,1,1570},{0,3,1768},{0,0,1089},{0,0,1089},{0,0,1089},{0,0,1089},{0,2,4},{0,2,4},{0,2,4},{0,1,4},{0,1,365},
+{0,1,365},{1,7,2796},{1,6,1432},{1,4,1413},{1,4,1593},{0,7,5435},{0,5,2360},{0,4,299},{0,3,2594},{0,3,8400},{0,3,4530},{1,7,1640},{1,6,276},{1,4,257},{1,4,437},{4,0,5427},{0,5,2360},{0,4,299},{0,3,2594},{3,2,5427},{0,3,2594},{1,5,1221},{1,5,1221},{1,5,1221},{1,3,1229},{0,5,1184},{0,4,250},{0,4,250},{0,2,146},{0,2,2451},{0,2,1107},{1,5,65},
+{1,5,65},{1,5,65},{1,3,73},{1,3,1154},{0,4,250},{0,4,250},{0,2,146},{1,2,1154},{0,2,146},{4,2,1576},{0,6,128},{2,4,130},{0,4,74},{4,2,1576},{5,2,1576},{0,4,74},{0,3,1570},{5,2,1576},{0,3,1570},{1,0,1220},{1,0,1220},{1,0,1220},{1,0,1220},{0,3,4},{0,3,4},{0,3,4},{0,1,121},{0,1,482},{0,1,482},{1,7,3180},{1,6,1464},{1,4,1813},
+{1,4,1513},{0,7,5515},{0,5,2168},{0,4,59},{0,3,2242},{0,4,8764},{0,3,4178},{2,6,1894},{1,6,308},{2,4,326},{1,4,357},{2,4,5427},{0,5,2168},{0,4,59},{0,3,2242},{7,0,5427},{0,3,2242},{1,6,1448},{1,6,1448},{1,6,1448},{1,4,1512},{0,5,1184},{0,4,58},{0,4,58},{0,2,178},{0,2,2995},{0,2,1139},{1,6,292},{1,6,292},{1,6,292},{2,3,325},{2,2,1152},
+{0,4,58},{0,4,58},{0,2,178},{5,0,1152},{0,2,178},{5,1,1570},{0,7,34},{2,4,2},{0,4,10},{5,1,1570},{4,3,1570},{0,4,10},{0,3,1666},{4,3,1570},{0,3,1666},{1,0,1412},{1,0,1412},{1,0,1412},{1,0,1412},{0,3,36},{0,3,36},{0,3,36},{0,2,9},{0,1,722},{0,1,722},{1,7,3816},{1,6,1748},{1,5,2450},{1,4,1685},{0,7,5983},{0,6,2180},{0,4,207},
+{0,3,2278},{0,4,9004},{0,3,4038},{2,7,1700},{2,6,462},{2,4,230},{2,4,406},{3,3,5420},{0,6,2176},{0,4,203},{0,3,2274},{6,1,5420},{0,3,2274},{1,6,1604},{1,6,1604},{1,6,1604},{1,4,1604},{0,6,1156},{0,4,126},{0,4,126},{0,3,429},{0,3,3044},{0,2,1307},{2,5,136},{2,5,136},{2,5,136},{2,3,149},{3,1,1152},{0,4,122},{0,4,122},{0,3,425},{4,1,1152},
+{0,3,425},{6,0,1570},{0,7,130},{2,4,130},{1,4,85},{6,0,1570},{3,4,1570},{1,4,85},{0,3,2018},{3,4,1570},{0,3,2018},{1,0,1600},{1,0,1600},{1,0,1600},{1,0,1600},{0,4,5},{0,4,5},{0,4,5},{0,2,29},{0,2,866},{0,2,866},{1,7,4520},{1,7,1608},{1,5,2418},{1,4,1925},{1,7,5996},{0,6,1956},{0,5,409},{0,4,2751},{0,5,9020},{0,3,3846},{2,7,1604},
+{2,6,174},{2,5,297},{2,4,342},{4,2,5420},{0,6,1856},{0,5,309},{0,4,2651},{5,2,5420},{0,4,2651},{1,7,1604},{1,7,1604},{1,7,1604},{1,4,1636},{0,7,1302},{0,5,120},{0,5,120},{0,3,189},{0,3,2820},{0,3,1245},{2,5,8},{2,5,8},{2,5,8},{2,4,53},{4,0,1154},{0,5,20},{0,5,20},{0,3,89},{3,2,1154},{0,3,89},{4,4,1568},{1,7,8},{2,5,293},
+{0,5,293},{4,4,1568},{7,2,1568},{0,5,293},{0,4,1810},{7,2,1568},{0,4,1810},{1,0,1600},{1,0,1600},{1,0,1600},{1,0,1600},{0,5,116},{0,5,116},{0,5,116},{0,3,164},{0,2,610},{0,2,610},{2,7,4356},{1,7,2004},{2,5,2635},{1,5,2006},{1,7,5924},{0,6,2316},{0,5,499},{0,4,2337},{0,5,8300},{0,4,3420},{2,7,1955},{2,7,299},{2,5,234},{2,5,474},{5,1,5420},
+{0,6,1955},{0,5,138},{0,4,1976},{4,3,5420},{0,4,1976},{1,7,1955},{1,7,1955},{1,7,1955},{1,5,1942},{1,6,1427},{0,5,435},{0,5,435},{0,3,378},{0,4,2628},{0,3,642},{2,6,53},{2,6,53},{2,6,53},{2,4,53},{2,4,1152},{0,5,74},{0,5,74},{0,3,17},{7,0,1152},{0,3,17},{5,3,1570},{1,7,98},{3,5,164},{1,5,100},{5,3,1570},{6,3,1570},{1,5,100},
+{0,4,1576},{6,3,1570},{0,4,1576},{1,0,1906},{1,0,1906},{1,0,1906},{1,0,1906},{1,4,234},{1,4,234},{1,4,234},{1,2,325},{0,3,626},{0,3,626},{2,7,4356},{2,7,1964},{2,5,2267},{2,5,2027},{1,7,6404},{1,6,2220},{1,5,117},{1,4,2314},{0,5,8204},{0,4,2684},{3,7,1929},{2,7,283},{3,5,365},{2,5,346},{6,0,5420},{0,7,1712},{1,5,68},{0,4,1784},{3,4,5420},
+{0,4,1784},{2,6,1942},{2,6,1942},{2,6,1942},{2,4,2006},{1,6,1219},{1,5,117},{1,5,117},{1,3,209},{0,4,2340},{0,3,514},{2,6,261},{2,6,261},{2,6,261},{2,4,325},{3,3,1154},{0,6,50},{0,6,50},{1,3,160},{6,1,1154},{1,3,160},{6,2,1568},{2,7,58},{3,5,4},{1,5,4},{6,2,1568},{5,4,1568},{1,5,4},{0,4,1640},{5,4,1568},{0,4,1640},{2,0,1906},
+{2,0,1906},{2,0,1906},{2,0,1906},{1,4,74},{1,4,74},{1,4,74},{1,3,65},{0,3,370},{0,3,370},{2,7,4868},{2,7,1740},{2,5,2411},{2,5,1691},{2,7,6548},{1,7,2244},{1,5,165},{1,4,2250},{0,6,7668},{0,4,2460},{3,7,1817},{3,7,525},{3,5,221},{3,5,441},{4,4,5419},{0,7,1712},{1,5,164},{0,4,1976},{7,2,5419},{0,4,1976},{2,7,1619},{2,7,1619},{2,7,1619},
+{2,5,1627},{1,7,1155},{1,5,101},{1,5,101},{1,3,417},{0,5,2379},{0,4,696},{3,5,157},{3,5,157},{3,5,157},{3,4,157},{4,2,1154},{0,6,82},{0,6,82},{0,4,212},{5,2,1154},{0,4,212},{7,1,1568},{2,7,122},{3,5,100},{2,5,73},{7,1,1568},{4,5,1568},{2,5,73},{0,4,1960},{4,5,1568},{0,4,1960},{2,0,1618},{2,0,1618},{2,0,1618},{2,0,1618},{1,5,1},
+{1,5,1},{1,5,1},{1,3,17},{0,3,370},{0,3,370},{3,7,5570},{2,7,2028},{2,6,2394},{2,5,1867},{2,7,6452},{1,7,1956},{1,6,439},{1,4,2698},{0,6,7348},{0,4,2748},{3,7,2089},{3,7,189},{3,6,334},{3,5,329},{5,3,5419},{1,7,1875},{1,6,358},{0,5,2145},{6,3,5419},{0,5,2145},{2,7,1667},{2,7,1667},{2,7,1667},{2,5,1611},{1,7,1331},{1,6,115},{1,6,115},
+{1,4,198},{0,5,1979},{0,4,248},{3,6,10},{3,6,10},{3,6,10},{3,5,73},{5,1,1160},{1,6,34},{1,6,34},{0,4,52},{7,1,1160},{0,4,52},{5,5,1570},{3,7,180},{4,5,320},{2,5,281},{5,5,1570},{3,6,1570},{2,5,281},{0,5,1856},{3,6,1570},{0,5,1856},{2,0,1586},{2,0,1586},{2,0,1586},{2,0,1586},{1,6,106},{1,6,106},{1,6,106},{1,4,162},{0,4,212},
+{0,4,212},{3,7,5354},{3,7,2770},{3,6,2717},{2,6,1986},{2,7,6956},{1,7,2244},{1,6,457},{1,5,2351},{0,7,7268},{0,5,1974},{4,7,2384},{3,7,270},{3,6,217},{3,6,517},{6,2,5419},{1,7,1920},{1,6,133},{0,5,1650},{5,4,5419},{0,5,1650},{2,7,2180},{2,7,2180},{2,7,2180},{2,6,1905},{2,7,1480},{1,6,376},{1,6,376},{1,4,333},{0,5,1988},{0,4,203},{3,7,45},
+{3,7,45},{3,7,45},{3,5,37},{6,0,1154},{1,6,52},{1,6,52},{1,4,9},{3,4,1154},{1,4,9},{6,4,1568},{3,7,234},{3,6,181},{1,6,117},{6,4,1568},{7,4,1568},{1,6,117},{0,5,1586},{7,4,1568},{0,5,1586},{2,0,1856},{2,0,1856},{2,0,1856},{2,0,1856},{2,5,272},{2,5,272},{2,5,272},{1,4,324},{0,4,194},{0,4,194},{3,7,5706},{3,7,2514},{3,6,2285},
+{3,6,2105},{3,7,7359},{2,7,2244},{2,6,147},{2,5,2358},{0,7,6820},{0,5,1718},{4,7,2256},{3,7,750},{4,6,410},{3,6,341},{7,1,5419},{2,7,2180},{2,6,83},{0,5,1618},{4,5,5419},{0,5,1618},{3,7,1985},{3,7,1985},{3,7,1985},{3,5,2041},{2,7,1224},{2,6,146},{2,6,146},{2,4,210},{0,6,1644},{1,4,509},{3,7,221},{3,7,221},{3,7,221},{3,5,277},{5,2,1160},
+{1,7,64},{1,7,64},{2,4,146},{7,2,1160},{2,4,146},{7,3,1570},{4,7,356},{4,6,10},{2,6,2},{7,3,1570},{6,5,1570},{2,6,2},{0,5,1618},{6,5,1570},{0,5,1618},{3,0,1960},{3,0,1960},{3,0,1960},{3,0,1960},{2,5,80},{2,5,80},{2,5,80},{2,4,89},{0,5,100},{0,5,100},{3,7,6570},{3,7,2770},{3,6,2365},{3,6,1705},{3,7,7311},{2,7,2276},{2,6,131},
+{2,5,2230},{0,7,6884},{0,5,1974},{4,7,2512},{4,7,532},{4,6,218},{4,6,482},{5,5,5424},{2,7,2276},{2,6,131},{1,5,1931},{3,6,5424},{1,5,1931},{3,7,1809},{3,7,1809},{3,7,1809},{3,6,1656},{2,7,1352},{2,6,82},{2,6,82},{2,4,370},{0,6,1548},{0,5,293},{4,6,169},{4,6,169},{4,6,169},{4,5,169},{6,1,1160},{1,7,64},{1,7,64},{1,5,250},{6,3,1160},
+{1,5,250},{5,7,1570},{4,7,388},{4,6,74},{3,6,65},{5,7,1570},{5,6,1570},{3,6,65},{0,5,1906},{5,6,1570},{0,5,1906},{3,0,1640},{3,0,1640},{3,0,1640},{3,0,1640},{2,6,1},{2,6,1},{2,6,1},{2,4,9},{0,5,68},{0,5,68},{4,7,6752},{3,7,3538},{3,7,2378},{3,6,1817},{3,7,7775},{2,7,2820},{2,7,477},{2,5,2614},{1,7,7360},{0,6,1978},{5,7,3110},
+{4,7,692},{4,7,377},{4,6,322},{6,4,5424},{3,7,2539},{2,7,413},{0,6,1942},{7,4,5424},{0,6,1942},{3,7,2017},{3,7,2017},{3,7,2017},{3,6,1592},{3,7,1846},{2,7,116},{2,7,116},{2,5,213},{0,7,1531},{1,5,283},{4,7,16},{4,7,16},{4,7,16},{4,6,97},{7,0,1154},{2,7,52},{2,7,52},{1,5,58},{3,5,1154},{1,5,58},{7,4,1576},{5,7,610},{5,6,306},
+{3,6,241},{7,4,1576},{7,5,1576},{3,6,241},{0,6,1906},{7,5,1576},{0,6,1906},{3,0,1576},{3,0,1576},{3,0,1576},{3,0,1576},{2,7,100},{2,7,100},{2,7,100},{2,5,164},{0,6,72},{0,6,72},{4,7,6932},{4,7,3932},{4,7,2807},{3,7,1974},{4,7,8428},{3,7,2981},{2,7,423},{2,6,2373},{1,7,7540},{0,6,1618},{5,7,2921},{4,7,1331},{4,7,206},{4,7,566},{7,3,5424},
+{3,7,2692},{2,7,134},{0,6,1609},{6,5,5424},{0,6,1609},{4,7,2707},{4,7,2707},{4,7,2707},{3,7,1874},{3,7,1513},{2,7,323},{2,7,323},{2,5,294},{0,7,1324},{1,5,184},{4,7,106},{4,7,106},{4,7,106},{4,6,25},{7,1,1160},{2,7,34},{2,7,34},{2,5,5},{7,3,1160},{2,5,5},{7,5,1570},{5,7,628},{4,7,181},{2,7,125},{7,5,1570},{6,6,1586},{2,7,125},
+{0,6,1600},{6,6,1586},{0,6,1600},{3,0,1810},{3,0,1810},{3,0,1810},{3,0,1810},{2,7,298},{2,7,298},{2,7,298},{2,5,290},{0,6,18},{0,6,18},{4,7,7636},{4,7,4156},{4,7,2311},{4,7,2191},{4,7,8428},{3,7,3317},{3,7,185},{3,6,2410},{2,7,8180},{1,6,1722},{5,7,3161},{5,7,1357},{5,7,461},{4,7,342},{5,7,5424},{4,7,2979},{3,7,104},{1,6,1601},{5,6,5424},
+{1,6,1601},{4,7,2307},{4,7,2307},{4,7,2307},{4,6,2082},{3,7,1625},{3,7,181},{3,7,181},{3,5,217},{0,7,1548},{1,5,504},{5,7,457},{5,7,457},{5,7,457},{4,6,233},{6,3,1154},{3,7,100},{3,7,100},{3,5,136},{6,4,1154},{3,5,136},{6,7,1576},{5,7,916},{5,7,20},{3,7,4},{6,7,1576},{7,6,1576},{3,7,4},{0,6,1600},{7,6,1576},{0,6,1600},{4,0,2018},
+{4,0,2018},{4,0,2018},{4,0,2018},{3,6,90},{3,6,90},{3,6,90},{3,5,117},{0,7,104},{0,7,104},{5,7,7862},{4,7,4316},{4,7,2291},{4,7,1691},{4,7,8004},{3,7,3433},{3,7,69},{3,6,1774},{2,7,7580},{1,6,1470},{5,7,3101},{5,7,1209},{5,7,185},{4,7,466},{7,4,4803},{4,7,2579},{3,7,68},{2,6,1448},{7,5,4803},{2,6,1448},{4,7,2291},{4,7,2291},{4,7,2291},
+{4,7,1691},{3,7,2121},{3,7,69},{3,7,69},{3,5,329},{1,7,1539},{1,6,314},{5,7,185},{5,7,185},{5,7,185},{5,6,185},{7,2,1154},{3,7,68},{3,7,68},{2,6,292},{5,5,1154},{2,6,292},{7,6,1252},{6,7,724},{5,7,16},{4,7,25},{7,6,1252},{7,6,1268},{4,7,25},{0,6,1412},{7,6,1268},{0,6,1412},{4,0,1666},{4,0,1666},{4,0,1666},{4,0,1666},{3,7,5},
+{3,7,5},{3,7,5},{3,5,5},{0,7,40},{0,7,40},{5,7,6806},{4,7,4684},{4,7,2659},{4,7,1579},{4,7,7668},{4,7,2988},{3,7,341},{3,6,1390},{2,7,7084},{1,6,1470},{6,7,2645},{5,7,1193},{5,7,169},{5,7,125},{6,6,4059},{4,7,2259},{4,7,234},{2,6,1224},{4,7,4059},{2,6,1224},{4,7,2659},{4,7,2659},{4,7,2659},{4,7,1579},{4,7,2043},{3,7,341},{3,7,341},
+{3,6,234},{1,7,1779},{1,6,314},{5,7,169},{5,7,169},{5,7,169},{5,7,125},{5,6,1152},{4,7,234},{4,7,234},{2,6,68},{4,6,1152},{2,6,68},{7,6,900},{6,7,500},{6,7,100},{4,7,9},{7,6,900},{6,7,884},{4,7,9},{0,6,1220},{6,7,884},{0,6,1220},{4,0,1570},{4,0,1570},{4,0,1570},{4,0,1570},{3,7,85},{3,7,85},{3,7,85},{3,5,149},{1,7,98},
+{1,7,98},{5,7,6077},{5,7,4185},{5,7,3161},{4,7,1912},{5,7,6790},{4,7,2529},{4,7,504},{3,6,1417},{3,7,6199},{1,7,1097},{6,7,1925},{6,7,1301},{5,7,457},{5,7,17},{7,5,3321},{5,7,1754},{4,7,180},{1,7,1093},{6,6,3345},{1,7,1093},{5,7,3161},{5,7,3161},{5,7,3161},{4,7,1912},{4,7,2124},{4,7,504},{4,7,504},{3,6,261},{2,7,1944},{2,6,171},{5,7,457},
+{5,7,457},{5,7,457},{5,7,17},{6,5,1154},{4,7,180},{4,7,180},{3,6,5},{3,7,1154},{3,6,5},{7,7,605},{6,7,401},{6,7,1},{5,7,1},{7,7,605},{6,7,569},{5,7,1},{0,7,1089},{6,7,569},{0,7,1089},{4,0,1768},{4,0,1768},{4,0,1768},{4,0,1768},{4,7,360},{4,7,360},{4,7,360},{3,6,260},{1,7,8},{1,7,8},{5,7,5837},{5,7,3945},{5,7,2921},
+{5,7,2129},{5,7,6054},{4,7,2529},{4,7,504},{4,6,1386},{3,7,5767},{2,7,773},{6,7,1557},{6,7,933},{6,7,533},{5,7,193},{6,7,2754},{5,7,1434},{4,7,404},{2,7,629},{5,7,2754},{2,7,629},{5,7,2921},{5,7,2921},{5,7,2921},{5,7,2129},{4,7,2604},{4,7,504},{4,7,504},{4,6,230},{2,7,2264},{2,6,443},{6,7,533},{6,7,533},{6,7,533},{5,7,193},{7,4,1152},
+{4,7,404},{4,7,404},{3,6,117},{7,5,1152},{3,6,117},{7,7,317},{7,7,245},{6,7,49},{6,7,25},{7,7,317},{7,7,373},{6,7,25},{0,7,625},{7,7,373},{0,7,625},{5,0,2080},{5,0,2080},{5,0,2080},{5,0,2080},{4,7,104},{4,7,104},{4,7,104},{4,6,149},{2,7,148},{2,7,148},{5,7,5981},{5,7,4089},{5,7,3065},{5,7,1921},{5,7,5702},{5,7,2666},{4,7,888},
+{4,7,693},{4,7,5325},{2,7,341},{6,7,1445},{6,7,821},{6,7,421},{6,7,205},{7,6,2306},{5,7,1370},{5,7,346},{2,7,325},{7,6,2274},{2,7,325},{5,7,3065},{5,7,3065},{5,7,3065},{5,7,1921},{5,7,2786},{4,7,888},{4,7,888},{4,6,294},{3,7,2355},{2,7,341},{6,7,421},{6,7,421},{6,7,421},{6,7,205},{7,5,1184},{5,7,346},{5,7,346},{4,6,290},{6,6,1152},
+{4,6,290},{7,7,157},{7,7,85},{7,7,36},{6,7,9},{7,7,157},{7,7,149},{6,7,9},{0,7,289},{7,7,149},{0,7,289},{5,0,1696},{5,0,1696},{5,0,1696},{5,0,1696},{4,7,104},{4,7,104},{4,7,104},{4,6,5},{2,7,52},{2,7,52},{6,7,5433},{5,7,4617},{5,7,3593},{5,7,2097},{5,7,5734},{5,7,2346},{5,7,1322},{4,7,261},{4,7,4909},{2,7,293},{6,7,1589},
+{6,7,965},{6,7,565},{6,7,157},{7,6,1890},{6,7,1146},{5,7,538},{3,7,82},{6,7,1890},{3,7,82},{5,7,3593},{5,7,3593},{5,7,3593},{5,7,2097},{5,7,2818},{5,7,1322},{5,7,1322},{4,7,261},{3,7,2691},{2,7,293},{6,7,565},{6,7,565},{6,7,565},{6,7,157},{6,7,1154},{5,7,538},{5,7,538},{3,7,82},{5,7,1154},{3,7,82},{7,7,125},{7,7,53},{7,7,4},
+{7,7,4},{7,7,125},{7,7,53},{7,7,4},{0,7,81},{7,7,53},{0,7,81},{5,0,1568},{5,0,1568},{5,0,1568},{5,0,1568},{4,7,360},{4,7,360},{4,7,360},{4,6,117},{2,7,212},{2,7,212},{6,7,4866},{6,7,4242},{6,7,3842},{5,7,2754},{6,7,5113},{5,7,2445},{5,7,1421},{4,7,234},{5,7,4804},{3,7,164},{7,7,1203},{7,7,1131},{6,7,1033},{6,7,409},{7,7,1611},
+{6,7,1056},{6,7,656},{4,7,9},{6,7,1584},{4,7,9},{6,7,3842},{6,7,3842},{6,7,3842},{5,7,2754},{5,7,3313},{5,7,1421},{5,7,1421},{4,7,234},{4,7,2875},{3,7,164},{6,7,1033},{6,7,1033},{6,7,1033},{6,7,409},{7,6,1152},{6,7,656},{6,7,656},{4,7,9},{7,6,1184},{4,7,9},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},
+{0,7,0},{7,7,98},{0,7,0},{5,0,1730},{5,0,1730},{5,0,1730},{5,0,1730},{5,7,397},{5,7,397},{5,7,397},{4,7,234},{3,7,164},{3,7,164},{6,7,4194},{6,7,3570},{6,7,3170},{6,7,2546},{6,7,4137},{5,7,2365},{5,7,1341},{5,7,185},{5,7,3876},{3,7,324},{7,7,771},{7,7,699},{7,7,650},{6,7,521},{7,7,1083},{6,7,864},{6,7,464},{4,7,25},{7,7,1187},
+{4,7,25},{6,7,3170},{6,7,3170},{6,7,3170},{6,7,2546},{6,7,3113},{5,7,1341},{5,7,1341},{5,7,185},{4,7,2491},{3,7,324},{7,7,650},{7,7,650},{7,7,650},{6,7,521},{7,6,832},{6,7,464},{6,7,464},{4,7,25},{6,7,800},{4,7,25},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{5,0,2146},
+{5,0,2146},{5,0,2146},{5,0,2146},{5,7,317},{5,7,317},{5,7,317},{5,7,185},{3,7,324},{3,7,324},{6,7,3778},{6,7,3154},{6,7,2754},{6,7,2130},{6,7,3417},{6,7,2169},{5,7,1517},{5,7,9},{5,7,3204},{4,7,338},{7,7,467},{7,7,395},{7,7,346},{7,7,274},{7,7,683},{7,7,539},{6,7,400},{5,7,0},{7,7,723},{5,7,0},{6,7,2754},{6,7,2754},{6,7,2754},
+{6,7,2130},{6,7,2393},{5,7,1517},{5,7,1517},{5,7,9},{5,7,2180},{4,7,338},{7,7,346},{7,7,346},{7,7,346},{7,7,274},{7,7,562},{6,7,400},{6,7,400},{5,7,0},{6,7,544},{5,7,0},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,1730},{6,0,1730},{6,0,1730},{6,0,1730},{5,7,493},
+{5,7,493},{5,7,493},{5,7,9},{4,7,338},{4,7,338},{6,7,3618},{6,7,2994},{6,7,2594},{6,7,1970},{6,7,2953},{6,7,1705},{6,7,1305},{5,7,89},{5,7,2788},{4,7,466},{7,7,291},{7,7,219},{7,7,170},{7,7,98},{7,7,411},{7,7,267},{7,7,218},{6,7,16},{7,7,387},{6,7,16},{6,7,2594},{6,7,2594},{6,7,2594},{6,7,1970},{6,7,1929},{6,7,1305},{6,7,1305},
+{5,7,89},{5,7,1764},{4,7,466},{7,7,170},{7,7,170},{7,7,170},{7,7,98},{7,7,290},{7,7,218},{7,7,218},{6,7,16},{7,7,338},{6,7,16},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,1570},{6,0,1570},{6,0,1570},{6,0,1570},{6,7,905},{6,7,905},{6,7,905},{5,7,89},{4,7,466},
+{4,7,466},{0,5,2665},{0,4,697},{0,3,290},{0,2,841},{0,3,5901},{0,2,4170},{0,2,1802},{0,1,4310},{0,1,6951},{0,1,4671},{0,5,2665},{0,4,697},{0,3,290},{0,2,841},{2,0,5893},{0,2,4170},{0,2,1802},{0,1,4310},{3,0,5893},{0,1,4310},{0,2,4},{0,2,4},{0,2,4},{0,1,4},{0,1,557},{0,1,365},{0,1,365},{0,0,356},{0,0,665},{0,0,392},{0,2,4},
+{0,2,4},{0,2,4},{0,1,4},{0,1,557},{0,1,365},{0,1,365},{0,0,356},{0,0,629},{0,0,356},{3,0,2665},{0,4,697},{0,3,290},{0,2,841},{3,0,2665},{3,1,2665},{0,2,841},{0,2,3145},{3,1,2665},{0,2,3145},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,6,2705},{0,4,617},{0,3,34},
+{0,2,985},{0,4,6754},{0,3,4625},{0,2,1946},{0,1,5030},{0,2,7635},{0,1,5391},{0,6,2705},{0,4,617},{0,3,34},{0,2,985},{1,2,6674},{0,3,4625},{0,2,1946},{0,1,5030},{0,2,6674},{0,1,5030},{0,3,9},{0,3,9},{0,3,9},{0,1,100},{0,1,845},{0,1,461},{0,1,461},{0,0,676},{0,0,1097},{0,0,712},{0,3,9},{0,3,9},{0,3,9},{0,1,100},{0,1,845},
+{0,1,461},{0,1,461},{0,0,676},{1,0,853},{0,0,676},{1,4,2665},{0,4,617},{0,3,34},{0,2,985},{1,4,2665},{2,2,2665},{0,2,985},{0,2,2777},{2,2,2665},{0,2,2777},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,6,2689},{0,5,477},{0,3,34},{0,3,634},{0,4,7538},{0,3,4865},{0,2,2346},
+{0,2,5474},{0,2,8547},{0,1,6367},{0,6,2689},{0,5,477},{0,3,34},{0,3,634},{0,4,7538},{0,3,4865},{0,2,2346},{0,2,5474},{2,1,7538},{0,2,5474},{0,3,25},{0,3,25},{0,3,25},{0,2,16},{0,1,1261},{0,1,685},{0,1,685},{0,1,965},{0,1,1646},{0,0,1160},{0,3,25},{0,3,25},{0,3,25},{0,2,16},{1,0,1213},{0,1,685},{0,1,685},{0,1,965},{1,0,1205},
+{0,1,965},{2,3,2669},{0,5,477},{0,3,34},{0,3,634},{2,3,2669},{6,0,2669},{0,3,634},{0,2,2665},{6,0,2669},{0,2,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,7,2669},{0,5,365},{0,3,290},{0,3,410},{0,4,8578},{0,3,5361},{0,3,2346},{0,2,5618},{0,2,9715},{0,2,6579},{0,7,2669},
+{0,5,365},{0,3,290},{0,3,410},{2,1,8498},{0,3,5361},{0,3,2346},{0,2,5618},{4,0,8498},{0,2,5618},{0,4,0},{0,4,0},{0,4,0},{0,2,16},{0,2,1637},{0,2,977},{0,2,977},{0,1,997},{0,1,1998},{0,1,1358},{0,4,0},{0,4,0},{0,4,0},{0,2,16},{1,0,1629},{0,2,977},{0,2,977},{0,1,997},{0,1,1637},{0,1,997},{3,2,2669},{0,5,365},{1,3,185},
+{0,3,410},{3,2,2669},{5,1,2669},{0,3,410},{0,2,2809},{5,1,2669},{0,2,2809},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,7,2777},{0,6,257},{0,4,277},{0,3,464},{0,5,9677},{0,4,6026},{0,3,2400},{0,2,6086},{0,2,11335},{0,2,7047},{0,7,2777},{0,6,257},{0,4,277},{0,3,464},{3,0,9677},
+{0,4,6026},{0,3,2400},{0,2,6086},{3,1,9677},{0,2,6086},{0,5,16},{0,5,16},{0,5,16},{0,3,64},{0,2,2186},{0,2,1130},{0,2,1130},{0,1,1186},{0,1,2547},{0,1,1547},{0,5,16},{0,5,16},{0,5,16},{0,3,64},{0,2,2186},{0,2,1130},{0,2,1130},{0,1,1186},{0,1,2186},{0,1,1186},{4,1,2669},{0,6,257},{0,4,277},{0,3,464},{4,1,2669},{4,2,2669},{0,3,464},
+{0,3,3209},{4,2,2669},{0,3,3209},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,7,3209},{0,6,209},{0,4,389},{0,4,541},{0,6,9765},{0,4,5546},{0,3,2080},{0,2,5990},{0,3,11621},{0,2,6951},{0,7,3209},{0,6,209},{0,4,389},{0,4,541},{1,4,9677},{0,4,5546},{0,3,2080},{0,2,5990},{2,2,9677},
+{0,2,5990},{0,5,80},{0,5,80},{0,5,80},{0,3,64},{0,3,2196},{0,2,970},{0,2,970},{0,1,1058},{0,1,2739},{0,1,1419},{0,5,80},{0,5,80},{0,5,80},{0,3,64},{1,1,2180},{0,2,970},{0,2,970},{0,1,1058},{1,1,2196},{0,1,1058},{5,0,2669},{0,6,145},{1,4,52},{0,4,477},{5,0,2669},{3,3,2669},{0,4,477},{0,3,2809},{3,3,2669},{0,3,2809},{0,0,64},
+{0,0,64},{0,0,64},{0,0,64},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,40},{0,0,40},{0,7,4025},{0,7,441},{0,4,885},{0,4,429},{0,6,9685},{0,4,5450},{0,4,1854},{0,3,6029},{0,3,11925},{0,2,7239},{1,7,3001},{0,7,441},{1,4,344},{0,4,429},{3,1,9685},{0,4,5450},{0,4,1854},{0,3,6029},{4,1,9685},{0,3,6029},{0,6,256},{0,6,256},{0,6,256},
+{0,3,320},{0,3,2228},{0,3,848},{0,3,848},{0,1,1186},{0,2,3171},{0,1,1547},{0,6,256},{0,6,256},{0,6,256},{0,3,320},{2,0,2180},{0,3,848},{0,3,848},{0,1,1186},{3,0,2180},{0,1,1186},{4,2,2677},{0,7,185},{1,4,20},{0,4,173},{4,2,2677},{7,1,2677},{0,4,173},{0,3,2665},{7,1,2677},{0,3,2665},{0,0,256},{0,0,256},{0,0,256},{0,0,256},{0,1,9},
+{0,1,9},{0,1,9},{0,0,36},{0,0,72},{0,0,72},{1,7,4141},{0,7,617},{1,4,1500},{0,4,701},{0,7,9690},{0,5,5001},{0,4,1214},{0,3,5277},{0,3,12613},{0,3,7213},{1,7,2985},{1,6,465},{1,4,344},{1,4,524},{4,0,9674},{0,5,5001},{0,4,1214},{0,3,5277},{3,2,9674},{0,3,5277},{0,7,601},{0,7,601},{0,7,601},{0,4,601},{0,4,2178},{0,3,656},{0,3,656},
+{0,2,866},{0,2,3171},{0,2,1827},{1,5,101},{1,5,101},{1,5,101},{1,3,109},{0,4,2178},{0,3,656},{0,3,656},{0,2,866},{2,1,2178},{0,2,866},{5,1,2669},{0,7,41},{2,4,181},{0,4,125},{5,1,2669},{4,3,2669},{0,4,125},{0,3,2777},{4,3,2669},{0,3,2777},{0,0,576},{0,0,576},{0,0,576},{0,0,576},{0,1,25},{0,1,25},{0,1,25},{0,1,49},{0,0,232},
+{0,0,232},{1,7,4582},{0,7,1274},{1,5,1446},{0,4,1466},{0,7,9789},{0,5,4794},{0,4,953},{0,3,4890},{0,4,13038},{0,3,6826},{1,7,3426},{1,7,290},{1,5,290},{1,4,443},{2,4,9685},{0,5,4794},{0,4,953},{0,3,4890},{7,0,9685},{0,3,4890},{0,7,1105},{0,7,1105},{0,7,1105},{0,4,1105},{0,5,2210},{0,4,592},{0,4,592},{0,2,596},{0,2,3477},{0,2,1557},{1,6,26},
+{1,6,26},{1,6,26},{1,4,82},{1,3,2180},{0,4,592},{0,4,592},{0,2,596},{1,2,2180},{0,2,596},{6,0,2677},{0,7,185},{1,5,289},{0,4,377},{6,0,2677},{5,3,2677},{0,4,377},{0,3,3209},{5,3,2677},{0,3,3209},{0,0,1089},{0,0,1089},{0,0,1089},{0,0,1089},{0,2,4},{0,2,4},{0,2,4},{0,1,4},{0,1,365},{0,1,365},{1,7,5382},{1,7,1350},{1,5,1510},
+{1,5,1738},{0,7,10285},{0,6,4406},{0,5,971},{0,3,4954},{0,4,13534},{0,3,6890},{2,7,3454},{1,7,194},{1,5,354},{1,5,582},{3,3,9674},{0,6,4406},{0,5,971},{0,3,4954},{6,1,9674},{0,3,4954},{1,6,1214},{1,6,1214},{1,6,1214},{1,4,1206},{0,5,2210},{0,4,400},{0,4,400},{0,2,628},{0,2,4021},{0,2,1589},{1,6,58},{1,6,58},{1,6,58},{1,4,50},{2,2,2178},
+{0,4,400},{0,4,400},{0,2,628},{5,0,2178},{0,2,628},{4,4,2669},{1,7,145},{2,5,74},{0,5,130},{4,4,2669},{7,2,2669},{0,5,130},{0,4,2845},{7,2,2669},{0,4,2845},{1,0,1205},{1,0,1205},{1,0,1205},{1,0,1205},{0,3,9},{0,3,9},{0,3,9},{0,1,100},{0,1,461},{0,1,461},{1,7,6566},{1,7,1638},{1,5,1958},{1,5,1578},{1,7,10830},{0,6,4118},{0,5,443},
+{0,4,4785},{0,4,14414},{0,3,7338},{2,7,3390},{1,7,482},{2,5,371},{1,5,422},{4,2,9674},{0,6,4118},{0,5,443},{0,4,4785},{5,2,9674},{0,4,4785},{1,7,1382},{1,7,1382},{1,7,1382},{1,4,1430},{0,6,2178},{0,5,442},{0,5,442},{0,3,641},{0,3,4242},{0,2,1877},{1,7,226},{1,7,226},{1,7,226},{1,4,274},{3,1,2178},{0,5,442},{0,5,442},{0,3,641},{4,1,2178},
+{0,3,641},{5,3,2669},{1,7,257},{2,5,10},{0,5,2},{5,3,2669},{6,3,2669},{0,5,2},{0,4,2669},{6,3,2669},{0,4,2669},{1,0,1381},{1,0,1381},{1,0,1381},{1,0,1381},{0,3,25},{0,3,25},{0,3,25},{0,2,16},{0,1,685},{0,1,685},{1,7,8134},{1,7,2310},{1,6,2671},{1,5,1802},{1,7,11086},{0,7,4109},{0,5,299},{0,4,4193},{0,5,14830},{0,4,7442},{2,7,3710},
+{2,7,490},{2,5,323},{2,5,563},{5,1,9669},{0,7,4109},{0,5,299},{0,4,4193},{4,3,9669},{0,4,4193},{1,7,1734},{1,7,1734},{1,7,1734},{1,5,1721},{0,7,2228},{0,5,218},{0,5,218},{0,3,305},{0,3,4626},{0,3,2241},{2,6,125},{2,6,125},{2,6,125},{2,4,125},{4,0,2180},{0,5,218},{0,5,218},{0,3,305},{3,2,2180},{0,3,305},{6,2,2665},{2,7,369},{3,5,181},
+{1,5,117},{6,2,2665},{5,4,2665},{1,5,117},{0,4,2749},{5,4,2665},{0,4,2749},{1,0,1685},{1,0,1685},{1,0,1685},{1,0,1685},{0,4,0},{0,4,0},{0,4,0},{0,2,16},{0,2,977},{0,2,977},{2,7,9153},{1,7,3525},{1,6,3220},{1,5,2513},{1,7,11833},{0,7,3686},{0,6,548},{0,4,3986},{0,5,15577},{0,4,7235},{3,7,4141},{2,7,481},{2,6,309},{2,5,428},{6,0,9674},
+{0,7,3686},{0,6,548},{0,4,3986},{3,4,9674},{0,4,3986},{1,7,2436},{1,7,2436},{1,7,2436},{1,5,2189},{0,7,2210},{0,5,272},{0,5,272},{0,3,233},{0,3,5364},{0,3,2169},{2,7,40},{2,7,40},{2,7,40},{2,5,104},{2,4,2178},{0,5,272},{0,5,272},{0,3,233},{7,0,2178},{0,3,233},{7,1,2669},{2,7,477},{2,6,305},{0,6,292},{7,1,2669},{4,5,2669},{0,6,292},
+{0,4,3145},{4,5,2669},{0,4,3145},{1,0,2180},{1,0,2180},{1,0,2180},{1,0,2180},{0,5,16},{0,5,16},{0,5,16},{0,3,64},{0,2,1130},{0,2,1130},{2,7,10154},{1,7,4946},{1,6,4049},{1,6,2853},{1,7,12838},{0,7,3719},{0,6,133},{0,4,4211},{0,6,16286},{0,4,7346},{3,7,4061},{2,7,881},{2,6,325},{2,6,629},{4,4,9669},{0,7,3718},{0,6,132},{0,4,4210},{7,2,9669},
+{0,4,4210},{1,7,3265},{1,7,3265},{1,7,3265},{1,6,2789},{0,7,2467},{0,6,69},{0,6,69},{0,3,442},{0,4,5602},{0,3,2290},{2,7,40},{2,7,40},{2,7,40},{2,5,40},{3,3,2180},{0,6,68},{0,6,68},{0,3,441},{6,1,2180},{0,3,441},{5,5,2665},{3,7,617},{3,6,100},{0,6,68},{5,5,2665},{3,6,2665},{0,6,68},{0,5,2885},{3,6,2665},{0,5,2885},{1,0,2689},
+{1,0,2689},{1,0,2689},{1,0,2689},{0,5,17},{0,5,17},{0,5,17},{0,3,1},{0,2,1341},{0,2,1341},{2,7,10666},{2,7,5146},{2,6,4206},{1,6,2933},{2,7,13606},{0,7,4215},{0,6,181},{0,5,3914},{0,6,15454},{0,4,7122},{3,7,4365},{3,7,1097},{3,6,404},{2,6,421},{5,3,9669},{1,7,4133},{0,6,100},{0,5,3833},{6,3,9669},{0,5,3833},{2,7,3777},{2,7,3777},{2,7,3777},
+{1,6,2933},{1,7,2805},{0,6,181},{0,6,181},{0,4,275},{0,4,5282},{0,3,2130},{2,7,296},{2,7,296},{2,7,296},{2,5,232},{4,2,2180},{0,6,100},{0,6,100},{0,4,194},{5,2,2180},{0,4,194},{6,4,2665},{3,7,697},{3,6,4},{1,6,4},{6,4,2665},{7,4,2665},{1,6,4},{0,5,2677},{7,4,2665},{0,5,2677},{1,0,2929},{1,0,2929},{1,0,2929},{1,0,2929},{0,6,81},
+{0,6,81},{0,6,81},{0,3,145},{0,3,1289},{0,3,1289},{2,7,11690},{2,7,5434},{2,7,4085},{2,6,3198},{2,7,13510},{1,7,4470},{1,6,585},{0,5,3690},{0,6,15134},{0,5,6210},{3,7,5053},{3,7,1177},{3,6,308},{2,6,597},{6,2,9670},{1,7,4181},{1,6,296},{0,5,3401},{5,4,9670},{0,5,3401},{2,7,3409},{2,7,3409},{2,7,3409},{2,6,3134},{1,7,2565},{0,7,323},{0,7,323},
+{0,4,323},{0,5,5085},{0,4,1634},{3,7,153},{3,7,153},{3,7,153},{3,5,145},{5,1,2186},{0,7,34},{0,7,34},{0,4,34},{7,1,2186},{0,4,34},{7,3,2665},{4,7,937},{3,6,164},{1,6,100},{7,3,2665},{6,5,2665},{1,6,100},{0,5,2725},{6,5,2665},{0,5,2725},{2,0,3085},{2,0,3085},{2,0,3085},{2,0,3085},{1,5,290},{1,5,290},{1,5,290},{1,3,298},{0,3,985},
+{0,3,985},{3,7,12062},{2,7,6370},{2,7,3743},{2,6,3018},{2,7,14014},{1,7,4758},{1,6,603},{1,5,4049},{0,7,14638},{0,5,5310},{4,7,4958},{3,7,1726},{3,7,334},{3,6,419},{7,1,9669},{1,7,4694},{0,7,341},{0,5,3374},{4,5,9669},{0,5,3374},{2,7,3454},{2,7,3454},{2,7,3454},{2,6,2729},{1,7,2754},{1,6,314},{1,6,314},{1,4,289},{0,5,4626},{0,4,1121},{3,7,45},
+{3,7,45},{3,7,45},{3,5,109},{6,0,2180},{0,7,52},{0,7,52},{0,4,160},{3,4,2180},{0,4,160},{5,7,2665},{4,7,1009},{4,6,293},{2,6,293},{5,7,2665},{5,6,2665},{2,6,293},{0,5,3085},{5,6,2665},{0,5,3085},{2,0,2725},{2,0,2725},{2,0,2725},{2,0,2725},{1,6,89},{1,6,89},{1,6,89},{1,4,145},{0,3,949},{0,3,949},{3,7,12414},{3,7,7246},{2,7,3983},
+{2,7,2879},{2,7,15006},{1,7,5558},{1,7,163},{1,5,4161},{0,7,14190},{0,5,5054},{4,7,5246},{4,7,2186},{3,7,302},{3,6,659},{5,5,9670},{2,7,4926},{1,7,163},{0,5,3758},{3,6,9670},{0,5,3758},{2,7,3902},{2,7,3902},{2,7,3902},{2,6,2777},{1,7,3330},{1,7,82},{1,7,82},{1,4,401},{0,6,4490},{0,4,1073},{3,7,221},{3,7,221},{3,7,221},{3,6,34},{5,2,2186},
+{1,7,82},{1,7,82},{0,5,277},{7,2,2186},{0,5,277},{6,6,2665},{5,7,1313},{4,7,130},{1,7,82},{6,6,2665},{4,7,2665},{1,7,82},{0,6,2929},{4,7,2665},{0,6,2929},{2,0,2677},{2,0,2677},{2,0,2677},{2,0,2677},{1,6,9},{1,6,9},{1,6,9},{1,4,1},{0,4,673},{0,4,673},{3,7,13278},{3,7,7502},{3,7,4254},{2,7,2895},{3,7,15045},{2,7,6114},{1,7,147},
+{1,6,3978},{0,7,14254},{0,6,4818},{4,7,5918},{4,7,2378},{4,7,443},{3,7,426},{6,4,9670},{2,7,5438},{1,7,83},{0,6,3218},{7,4,9670},{0,6,3218},{3,7,4253},{3,7,4253},{3,7,4253},{2,7,2894},{2,7,3054},{1,7,146},{1,7,146},{1,5,296},{0,6,3978},{0,5,821},{4,7,442},{4,7,442},{4,7,442},{3,6,194},{6,1,2186},{1,7,82},{1,7,82},{0,5,37},{6,3,2186},
+{0,5,37},{7,5,2665},{5,7,1361},{4,7,2},{2,7,10},{7,5,2665},{6,6,2689},{2,7,10},{0,6,2689},{6,6,2689},{0,6,2689},{2,0,2885},{2,0,2885},{2,0,2885},{2,0,2885},{1,7,65},{1,7,65},{1,7,65},{1,4,113},{0,4,625},{0,4,625},{3,7,13261},{3,7,7409},{3,7,4045},{3,7,3209},{3,7,14116},{2,7,5615},{2,7,574},{1,6,3165},{0,7,13437},{0,6,3429},{5,7,5269},
+{4,7,2275},{4,7,250},{3,7,505},{5,6,8712},{3,7,4724},{2,7,250},{0,6,2405},{4,6,8712},{0,6,2405},{3,7,4045},{3,7,4045},{3,7,4045},{3,7,3209},{2,7,3150},{2,7,574},{2,7,574},{1,5,296},{0,6,3850},{0,5,453},{4,7,250},{4,7,250},{4,7,250},{4,6,169},{7,0,2180},{2,7,250},{2,7,250},{1,5,40},{3,5,2180},{1,5,40},{6,7,2180},{5,7,1168},{4,7,81},
+{2,7,25},{6,7,2180},{5,7,2180},{2,7,25},{0,6,2180},{5,7,2180},{0,6,2180},{3,0,3145},{3,0,3145},{3,0,3145},{3,0,3145},{1,7,305},{1,7,305},{1,7,305},{1,5,292},{0,5,449},{0,5,449},{4,7,11894},{3,7,7634},{3,7,4270},{3,7,2750},{3,7,13315},{2,7,5354},{2,7,313},{1,6,2634},{1,7,12414},{0,6,2250},{5,7,4369},{4,7,2365},{4,7,340},{4,7,160},{7,3,7590},
+{3,7,4094},{2,7,232},{0,6,1721},{6,5,7590},{0,6,1721},{3,7,4270},{3,7,4270},{3,7,4270},{3,7,2750},{2,7,3717},{2,7,313},{2,7,313},{2,5,302},{0,7,3546},{0,5,498},{4,7,340},{4,7,340},{4,7,340},{4,6,97},{7,1,2186},{2,7,232},{2,7,232},{1,5,130},{7,3,2186},{1,5,130},{6,7,1649},{6,7,1025},{5,7,9},{3,7,1},{6,7,1649},{7,6,1625},{3,7,1},
+{0,6,1685},{7,6,1625},{0,6,1685},{3,0,2749},{3,0,2749},{3,0,2749},{3,0,2749},{2,7,117},{2,7,117},{2,7,117},{2,5,181},{0,5,377},{0,5,377},{4,7,11078},{4,7,7478},{3,7,4878},{3,7,2750},{4,7,12662},{3,7,5031},{2,7,489},{2,6,1911},{1,7,11470},{0,6,1610},{5,7,3841},{5,7,1949},{4,7,692},{4,7,32},{5,7,6662},{4,7,3641},{3,7,442},{0,6,1385},{5,6,6662},
+{0,6,1385},{3,7,4878},{3,7,4878},{3,7,4878},{3,7,2750},{3,7,3795},{2,7,489},{2,7,489},{2,5,366},{0,7,3354},{0,6,454},{4,7,692},{4,7,692},{4,7,692},{4,7,32},{6,3,2180},{3,7,442},{3,7,442},{0,6,229},{6,4,2180},{0,6,229},{7,6,1201},{6,7,689},{5,7,25},{4,7,16},{7,6,1201},{7,6,1225},{4,7,16},{0,6,1381},{7,6,1225},{0,6,1381},{3,0,2669},
+{3,0,2669},{3,0,2669},{3,0,2669},{2,7,5},{2,7,5},{2,7,5},{2,5,5},{0,6,229},{0,6,229},{4,7,10646},{4,7,7046},{4,7,5021},{3,7,3134},{4,7,11526},{3,7,4503},{2,7,1049},{2,6,1479},{1,7,10910},{0,6,1354},{5,7,3569},{5,7,1677},{5,7,653},{4,7,160},{7,4,5829},{4,7,3065},{3,7,410},{1,6,1209},{7,5,5829},{1,6,1209},{4,7,5021},{4,7,5021},{4,7,5021},
+{3,7,3134},{3,7,3875},{2,7,1049},{2,7,1049},{2,6,323},{0,7,3546},{0,6,198},{5,7,653},{5,7,653},{5,7,653},{4,7,160},{7,2,2180},{3,7,410},{3,7,410},{1,6,53},{5,5,2180},{1,6,53},{7,6,865},{6,7,481},{6,7,81},{4,7,16},{7,6,865},{6,7,841},{4,7,16},{0,6,1205},{6,7,841},{0,6,1205},{3,0,2845},{3,0,2845},{3,0,2845},{3,0,2845},{2,7,149},
+{2,7,149},{2,7,149},{2,5,85},{0,6,149},{0,6,149},{4,7,10598},{4,7,6998},{4,7,4973},{4,7,3353},{4,7,10774},{3,7,4359},{3,7,995},{2,6,1431},{2,7,10294},{0,7,1242},{6,7,3329},{5,7,1661},{5,7,637},{5,7,197},{6,6,5085},{4,7,2745},{3,7,634},{0,7,1098},{4,7,5085},{0,7,1098},{4,7,4973},{4,7,4973},{4,7,4973},{4,7,3353},{3,7,4339},{3,7,995},{3,7,995},
+{2,6,275},{1,7,3845},{0,6,326},{5,7,637},{5,7,637},{5,7,637},{5,7,197},{5,6,2178},{3,7,634},{3,7,634},{1,6,37},{4,6,2178},{1,6,37},{7,7,605},{6,7,401},{6,7,1},{5,7,1},{7,7,605},{6,7,569},{5,7,1},{0,7,1089},{6,7,569},{0,7,1089},{4,0,3209},{4,0,3209},{4,0,3209},{4,0,3209},{3,7,370},{3,7,370},{3,7,370},{2,6,274},{0,7,153},
+{0,7,153},{5,7,9925},{4,7,7403},{4,7,5378},{4,7,3218},{4,7,10387},{4,7,4627},{3,7,1292},{3,6,1477},{2,7,9727},{0,7,621},{6,7,2609},{5,7,1949},{5,7,925},{5,7,89},{7,5,4347},{5,7,2384},{4,7,666},{0,7,612},{6,6,4371},{0,7,612},{4,7,5378},{4,7,5378},{4,7,5378},{4,7,3218},{4,7,4762},{3,7,1292},{3,7,1292},{3,6,321},{1,7,4106},{1,6,469},{5,7,925},
+{5,7,925},{5,7,925},{5,7,89},{6,5,2180},{4,7,666},{4,7,666},{2,6,104},{3,7,2180},{2,6,104},{7,7,290},{7,7,218},{6,7,64},{6,7,16},{7,7,290},{7,7,338},{6,7,16},{0,7,576},{7,7,338},{0,7,576},{4,0,2777},{4,0,2777},{4,0,2777},{4,0,2777},{3,7,136},{3,7,136},{3,7,136},{3,5,200},{0,7,45},{0,7,45},{5,7,9269},{5,7,7377},{4,7,6146},
+{4,7,3506},{5,7,10044},{4,7,4211},{3,7,1964},{3,7,836},{3,7,9185},{0,7,477},{6,7,2241},{6,7,1617},{6,7,1217},{5,7,265},{6,7,3780},{5,7,2064},{4,7,890},{1,7,257},{5,7,3780},{1,7,257},{4,7,6146},{4,7,6146},{4,7,6146},{4,7,3506},{4,7,4826},{3,7,1964},{3,7,1964},{3,6,337},{2,7,4590},{0,7,477},{6,7,1217},{6,7,1217},{6,7,1217},{5,7,265},{7,4,2178},
+{4,7,890},{4,7,890},{1,7,257},{7,5,2178},{1,7,257},{7,7,146},{7,7,74},{7,7,25},{6,7,16},{7,7,146},{7,7,130},{6,7,16},{0,7,256},{7,7,130},{0,7,256},{4,0,2665},{4,0,2665},{4,0,2665},{4,0,2665},{3,7,200},{3,7,200},{3,7,200},{3,6,13},{0,7,221},{0,7,221},{5,7,8997},{5,7,7105},{5,7,6081},{4,7,4178},{5,7,9276},{4,7,4179},{4,7,2154},
+{3,7,356},{3,7,8721},{1,7,209},{6,7,2129},{6,7,1505},{6,7,1105},{6,7,673},{7,6,3332},{5,7,2000},{5,7,976},{2,7,73},{7,6,3300},{2,7,73},{5,7,6081},{5,7,6081},{5,7,6081},{4,7,4178},{4,7,5274},{4,7,2154},{4,7,2154},{3,7,356},{2,7,4878},{1,7,209},{6,7,1105},{6,7,1105},{6,7,1105},{6,7,673},{7,5,2210},{5,7,976},{5,7,976},{2,7,73},{6,6,2178},
+{2,7,73},{7,7,130},{7,7,58},{7,7,9},{7,7,1},{7,7,130},{7,7,50},{7,7,1},{0,7,64},{7,7,50},{0,7,64},{4,0,2809},{4,0,2809},{4,0,2809},{4,0,2809},{3,7,520},{3,7,520},{3,7,520},{3,6,61},{1,7,145},{1,7,145},{5,7,9109},{5,7,7217},{5,7,6193},{5,7,4301},{5,7,8892},{4,7,4531},{4,7,2506},{3,7,260},{4,7,8587},{1,7,289},{6,7,2273},
+{6,7,1649},{6,7,1249},{6,7,625},{7,6,2916},{6,7,1956},{5,7,1168},{2,7,25},{6,7,2916},{2,7,25},{5,7,6193},{5,7,6193},{5,7,6193},{5,7,4301},{5,7,5976},{4,7,2506},{4,7,2506},{3,7,260},{3,7,5277},{1,7,289},{6,7,1249},{6,7,1249},{6,7,1249},{6,7,625},{6,7,2180},{5,7,1168},{5,7,1168},{2,7,25},{5,7,2180},{2,7,25},{7,7,242},{7,7,170},{7,7,121},
+{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{4,0,3209},{4,0,3209},{4,0,3209},{4,0,3209},{4,7,481},{4,7,481},{4,7,481},{3,7,260},{1,7,289},{1,7,289},{6,7,8325},{5,7,6749},{5,7,5725},{5,7,3833},{5,7,7866},{5,7,4082},{4,7,2470},{4,7,265},{4,7,7219},{2,7,365},{7,7,1842},{6,7,1460},{6,7,1060},{6,7,436},{7,6,2241},
+{6,7,1425},{6,7,1025},{3,7,1},{6,7,2169},{3,7,1},{5,7,5725},{5,7,5725},{5,7,5725},{5,7,3833},{5,7,4950},{4,7,2470},{4,7,2470},{4,7,265},{3,7,4521},{2,7,365},{6,7,1060},{6,7,1060},{6,7,1060},{6,7,436},{6,7,1649},{6,7,1025},{6,7,1025},{3,7,1},{7,6,1625},{3,7,1},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},
+{0,7,0},{7,7,98},{0,7,0},{5,0,2809},{5,0,2809},{5,0,2809},{5,0,2809},{4,7,445},{4,7,445},{4,7,445},{4,6,202},{2,7,365},{2,7,365},{6,7,7093},{6,7,6469},{5,7,5581},{5,7,3689},{5,7,7226},{5,7,3442},{5,7,2418},{4,7,25},{4,7,6275},{2,7,509},{7,7,1266},{7,7,1194},{6,7,1028},{6,7,404},{7,7,1686},{6,7,1089},{6,7,689},{4,7,16},{6,7,1641},
+{4,7,16},{5,7,5581},{5,7,5581},{5,7,5581},{5,7,3689},{5,7,4310},{5,7,2418},{5,7,2418},{4,7,25},{3,7,4121},{2,7,509},{6,7,1028},{6,7,1028},{6,7,1028},{6,7,404},{7,6,1201},{6,7,689},{6,7,689},{4,7,16},{7,6,1225},{4,7,16},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{5,0,2665},
+{5,0,2665},{5,0,2665},{5,0,2665},{4,7,685},{4,7,685},{4,7,685},{4,7,25},{2,7,509},{2,7,509},{6,7,6117},{6,7,5493},{6,7,5093},{5,7,3801},{6,7,6098},{5,7,3058},{5,7,2034},{4,7,41},{4,7,5587},{3,7,613},{7,7,818},{7,7,746},{7,7,697},{6,7,500},{7,7,1142},{6,7,881},{6,7,481},{4,7,16},{6,7,1241},{4,7,16},{6,7,5093},{6,7,5093},{6,7,5093},
+{5,7,3801},{5,7,3926},{5,7,2034},{5,7,2034},{4,7,41},{4,7,3562},{3,7,613},{7,7,697},{7,7,697},{7,7,697},{6,7,500},{7,6,865},{6,7,481},{6,7,481},{4,7,16},{6,7,841},{4,7,16},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{5,0,2777},{5,0,2777},{5,0,2777},{5,0,2777},{5,7,1010},
+{5,7,1010},{5,7,1010},{4,7,41},{3,7,613},{3,7,613},{6,7,5397},{6,7,4773},{6,7,4373},{6,7,3749},{6,7,5074},{5,7,2930},{5,7,1906},{4,7,313},{5,7,4753},{3,7,725},{7,7,498},{7,7,426},{7,7,377},{7,7,305},{7,7,726},{7,7,582},{6,7,401},{5,7,1},{7,7,774},{5,7,1},{6,7,4373},{6,7,4373},{6,7,4373},{6,7,3749},{5,7,3798},{5,7,1906},{5,7,1906},
+{4,7,313},{4,7,3130},{3,7,725},{7,7,377},{7,7,377},{7,7,377},{7,7,305},{7,7,605},{6,7,401},{6,7,401},{5,7,1},{6,7,569},{5,7,1},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{5,0,3145},{5,0,3145},{5,0,3145},{5,0,3145},{5,7,882},{5,7,882},{5,7,882},{4,7,313},{3,7,725},
+{3,7,725},{1,7,34142},{0,7,5184},{0,5,609},{0,5,4841},{1,7,46442},{0,7,24449},{0,5,9741},{0,4,24761},{0,5,65162},{0,3,40820},{0,7,10048},{0,7,2880},{0,5,545},{0,4,3204},{1,4,18070},{0,4,13297},{0,4,6453},{0,2,13857},{2,2,18070},{0,2,13857},{0,3,9},{0,3,9},{0,3,9},{0,2,36},{0,1,1145},{0,1,617},{0,1,617},{0,1,977},{0,0,1505},{0,0,1036},{0,3,9},
+{0,3,9},{0,3,9},{0,2,36},{1,0,1129},{0,1,617},{0,1,617},{0,1,977},{1,0,1105},{0,1,977},{4,2,9250},{0,7,2880},{0,5,545},{0,4,3204},{4,2,9250},{5,2,9250},{0,4,3204},{0,3,9280},{5,2,9250},{0,3,9280},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{1,7,38782},{0,7,6720},{0,5,305},
+{0,5,3801},{1,7,51082},{0,7,24961},{0,5,8701},{0,4,25849},{0,5,65535},{0,4,42094},{1,7,10502},{0,7,2624},{0,5,241},{0,4,3044},{3,1,19334},{0,4,14065},{0,4,6293},{0,3,14756},{4,1,19334},{0,3,14756},{0,4,4},{0,4,4},{0,4,4},{0,2,4},{0,2,1537},{0,1,937},{0,1,937},{0,1,977},{0,1,1898},{0,1,1338},{0,4,4},{0,4,4},{0,4,4},{0,2,4},{1,0,1513},
+{0,1,937},{0,1,937},{0,1,977},{0,1,1537},{0,1,977},{5,1,9256},{0,7,2624},{0,5,241},{0,4,3044},{5,1,9256},{7,1,9256},{0,4,3044},{0,3,9280},{7,1,9256},{0,3,9280},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{1,7,44190},{0,7,9024},{0,5,769},{0,5,3529},{1,7,56490},{0,7,26241},{0,5,8429},
+{0,4,27705},{0,5,65535},{0,4,43950},{1,7,10854},{0,7,2624},{0,5,193},{0,5,2953},{2,3,20689},{0,5,14598},{0,4,6389},{0,3,15012},{6,0,20689},{0,3,15012},{0,4,36},{0,4,36},{0,4,36},{0,2,100},{0,2,1985},{0,2,1061},{0,2,1061},{0,1,1105},{0,1,2346},{0,1,1466},{0,4,36},{0,4,36},{0,4,36},{0,2,100},{0,2,1985},{0,2,1061},{0,2,1061},{0,1,1105},{0,1,1985},
+{0,1,1105},{6,0,9256},{0,7,2624},{0,5,193},{0,5,2953},{6,0,9256},{6,2,9256},{0,5,2953},{0,3,9536},{6,2,9256},{0,3,9536},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{1,7,50366},{0,7,12096},{0,6,1101},{0,5,4025},{1,7,62666},{0,7,28289},{0,5,8925},{0,5,28912},{0,6,65535},{0,4,46574},{1,7,11462},
+{0,7,2880},{0,6,317},{0,5,2425},{4,0,22137},{0,5,15206},{0,4,6741},{0,3,15524},{3,2,22137},{0,3,15524},{0,5,1},{0,5,1},{0,5,1},{0,3,9},{0,2,2561},{0,2,1285},{0,2,1285},{0,1,1361},{0,1,2922},{0,1,1722},{0,5,1},{0,5,1},{0,5,1},{0,3,9},{1,1,2561},{0,2,1285},{0,2,1285},{0,1,1361},{2,0,2521},{0,1,1361},{5,2,9250},{0,7,2880},{0,6,317},
+{0,5,2425},{5,2,9250},{5,3,9250},{0,5,2425},{0,4,9640},{5,3,9250},{0,4,9640},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{1,7,58232},{0,7,16470},{0,6,129},{0,6,3489},{1,7,65535},{0,7,31511},{0,6,10213},{0,5,29110},{0,6,65535},{0,4,50444},{1,7,12452},{0,7,3474},{0,6,29},{0,5,2137},{2,4,23851},
+{0,6,16172},{0,5,7037},{0,3,16406},{7,0,23851},{0,3,16406},{0,6,4},{0,6,4},{0,6,4},{0,3,36},{0,3,3232},{0,2,1690},{0,2,1690},{0,1,1802},{0,1,3723},{0,1,2163},{0,6,4},{0,6,4},{0,6,4},{0,3,36},{1,1,3200},{0,2,1690},{0,2,1690},{0,1,1802},{2,0,3232},{0,1,1802},{6,1,9256},{1,7,3232},{0,6,29},{0,5,2137},{6,1,9256},{6,3,9256},{0,5,2137},
+{0,4,9298},{6,3,9256},{0,4,9298},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{1,7,65535},{0,7,21174},{0,6,81},{0,6,2545},{1,7,65535},{0,7,35191},{0,6,9269},{0,5,30102},{0,6,65535},{0,5,54602},{1,7,13604},{0,7,4274},{0,6,45},{0,5,2153},{4,1,25472},{0,6,16620},{0,5,7053},{0,3,17462},{4,2,25472},
+{0,3,17462},{0,6,36},{0,6,36},{0,6,36},{0,4,49},{0,3,3872},{0,3,2132},{0,3,2132},{0,1,2330},{0,1,4571},{0,1,2691},{0,6,36},{0,6,36},{0,6,36},{0,4,49},{0,3,3872},{0,3,2132},{0,3,2132},{0,1,2330},{1,1,3872},{0,1,2330},{7,0,9250},{1,7,3488},{0,6,45},{0,5,2153},{7,0,9250},{3,5,9250},{0,5,2153},{0,4,9266},{3,5,9250},{0,4,9266},{0,0,0},
+{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{2,7,65535},{1,7,25204},{0,6,805},{0,6,2373},{1,7,65535},{0,7,39263},{0,6,8769},{0,5,31402},{0,6,65535},{0,5,55902},{1,7,14880},{1,7,5024},{0,6,321},{0,6,1889},{5,0,26756},{0,6,17000},{0,5,7049},{0,4,18139},{6,1,26756},{0,4,18139},{0,7,5},{0,7,5},{0,7,5},
+{0,4,5},{0,3,4468},{0,3,2248},{0,3,2248},{0,2,2722},{0,2,5411},{0,1,3227},{0,7,5},{0,7,5},{0,7,5},{0,4,5},{2,0,4420},{0,3,2248},{0,3,2248},{0,2,2722},{3,0,4420},{0,2,2722},{5,4,9250},{1,7,4000},{1,6,185},{0,6,1885},{5,4,9250},{7,3,9250},{0,6,1885},{0,4,9490},{7,3,9250},{0,4,9490},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,16},
+{0,0,16},{0,0,16},{0,0,64},{0,0,100},{0,0,100},{2,7,65535},{1,7,29620},{0,7,1306},{0,6,3061},{2,7,65535},{0,7,43055},{0,6,8145},{0,6,31878},{0,7,65535},{0,5,56670},{2,7,14924},{1,7,5344},{0,7,406},{0,6,1617},{4,2,26756},{0,6,16744},{0,5,6553},{0,4,17195},{5,2,26756},{0,4,17195},{0,7,181},{0,7,181},{0,7,181},{0,4,181},{0,4,4418},{0,3,2056},{0,3,2056},
+{0,2,2210},{0,2,5411},{0,2,3171},{0,7,181},{0,7,181},{0,7,181},{0,4,181},{0,4,4418},{0,3,2056},{0,3,2056},{0,2,2210},{2,1,4418},{0,2,2210},{6,3,9248},{2,7,4292},{0,7,306},{0,6,1517},{6,3,9248},{6,4,9248},{0,6,1517},{0,5,9698},{6,4,9248},{0,5,9698},{0,0,100},{0,0,100},{0,0,100},{0,0,100},{0,0,16},{0,0,16},{0,0,16},{0,0,0},{0,0,36},
+{0,0,36},{2,7,65535},{1,7,35659},{0,7,865},{0,7,2657},{2,7,65535},{1,7,48315},{0,7,8072},{0,6,29745},{0,7,65535},{0,5,58605},{2,7,15347},{1,7,6163},{1,7,270},{0,6,1770},{5,1,26756},{0,7,15992},{0,6,5378},{0,4,16592},{6,2,26756},{0,4,16592},{0,7,685},{0,7,685},{0,7,685},{0,5,370},{0,5,4450},{0,4,1768},{0,4,1768},{0,2,1940},{0,2,5717},{0,2,2901},{1,7,234},
+{1,7,234},{1,7,234},{1,4,250},{1,3,4420},{0,4,1768},{0,4,1768},{0,2,1940},{1,2,4420},{0,2,1940},{7,2,9250},{3,7,4820},{1,7,45},{0,6,1409},{7,2,9250},{5,5,9250},{0,6,1409},{0,5,9320},{5,5,9250},{0,5,9320},{0,0,361},{0,0,361},{0,0,361},{0,0,361},{0,1,0},{0,1,0},{0,1,0},{0,0,81},{0,0,117},{0,0,117},{2,7,65535},{1,7,40299},{0,7,1405},
+{0,7,2173},{2,7,65535},{1,7,50747},{0,7,6068},{0,6,28101},{0,7,65535},{0,5,59897},{2,7,15659},{1,7,6963},{1,7,74},{1,6,2046},{6,0,26264},{0,7,15284},{0,6,4470},{0,4,16052},{3,4,26264},{0,4,16052},{1,7,1230},{1,7,1230},{1,7,1230},{0,5,754},{0,5,4450},{0,4,1576},{0,4,1576},{0,2,1972},{0,2,6261},{0,2,2933},{1,7,74},{1,7,74},{1,7,74},{1,5,113},{2,2,4418},
+{0,4,1576},{0,4,1576},{0,2,1972},{5,0,4418},{0,2,1972},{5,6,8980},{3,7,4808},{1,7,25},{0,7,1444},{5,6,8980},{4,6,8980},{0,7,1444},{0,5,8980},{4,6,8980},{0,5,8980},{0,0,729},{0,0,729},{0,0,729},{0,0,729},{0,2,16},{0,2,16},{0,2,16},{0,1,16},{0,0,325},{0,0,325},{2,7,65535},{1,7,40395},{0,7,2381},{0,7,2125},{2,7,65535},{1,7,48635},{0,7,4500},
+{0,6,24853},{0,7,65535},{0,5,57545},{3,7,14605},{2,7,6211},{1,7,170},{1,6,1598},{5,2,24379},{0,7,13716},{0,6,3446},{0,5,14549},{5,3,24379},{0,5,14549},{1,7,1326},{1,7,1326},{1,7,1326},{1,5,1157},{0,6,4418},{0,5,1394},{0,5,1394},{0,3,1621},{0,3,6482},{0,2,3221},{1,7,170},{1,7,170},{1,7,170},{1,5,1},{3,1,4418},{0,5,1394},{0,5,1394},{0,3,1621},{4,1,4418},
+{0,3,1621},{7,3,7940},{3,7,4264},{2,7,81},{0,7,900},{7,3,7940},{6,5,7940},{0,7,900},{0,5,7988},{6,5,7940},{0,5,7988},{1,0,1157},{1,0,1157},{1,0,1157},{1,0,1157},{0,2,16},{0,2,16},{0,2,16},{0,1,16},{0,1,377},{0,1,377},{2,7,65535},{1,7,40747},{0,7,3613},{0,7,2333},{2,7,65535},{1,7,46779},{0,7,3188},{0,6,21861},{0,7,65535},{0,5,55449},{3,7,13181},
+{2,7,5667},{1,7,522},{1,7,1306},{6,1,22571},{0,7,12404},{0,6,2678},{0,5,12453},{4,4,22571},{0,5,12453},{1,7,1678},{1,7,1678},{1,7,1678},{1,5,1301},{0,7,4468},{0,5,1170},{0,5,1170},{0,3,1285},{0,3,6866},{0,3,3221},{1,7,522},{1,7,522},{1,7,522},{1,5,145},{4,0,4420},{0,5,1170},{0,5,1170},{0,3,1285},{3,2,4420},{0,3,1285},{6,5,6964},{3,7,3848},{2,7,1},
+{0,7,484},{6,5,6964},{3,7,6964},{0,7,484},{0,5,7124},{3,7,6964},{0,5,7124},{1,0,1237},{1,0,1237},{1,0,1237},{1,0,1237},{0,3,1},{0,3,1},{0,3,1},{0,2,100},{0,1,505},{0,1,505},{2,7,65535},{1,7,41449},{0,7,5305},{0,7,2873},{2,7,65535},{1,7,44997},{0,7,2018},{0,6,18801},{0,7,65535},{0,6,52421},{3,7,11885},{2,7,5361},{2,7,320},{1,7,1000},{5,3,20645},
+{0,7,11234},{0,7,2018},{0,5,10401},{6,3,20645},{0,5,10401},{1,7,2380},{1,7,2380},{1,7,2380},{1,6,1496},{0,7,4450},{0,6,964},{0,6,964},{0,3,1213},{0,3,7604},{0,3,3149},{2,7,320},{2,7,320},{2,7,320},{2,5,272},{2,4,4418},{0,6,964},{0,6,964},{0,3,1213},{7,0,4418},{0,3,1213},{5,7,5941},{4,7,3181},{2,7,64},{0,7,169},{5,7,5941},{5,6,5941},{0,7,169},
+{0,5,6305},{5,6,5941},{0,5,6305},{1,0,1480},{1,0,1480},{1,0,1480},{1,0,1480},{0,4,25},{0,4,25},{0,4,25},{0,2,1},{0,1,802},{0,1,802},{2,7,65535},{1,7,42345},{0,7,7081},{0,7,3625},{2,7,65535},{1,7,43685},{0,7,1250},{0,6,16353},{0,7,65535},{0,6,49973},{3,7,11005},{3,7,5153},{2,7,320},{2,7,964},{7,0,19026},{1,7,10349},{0,7,1250},{0,5,8849},{3,5,19026},
+{0,5,8849},{1,7,3276},{1,7,3276},{1,7,3276},{1,6,1848},{0,7,4706},{0,6,740},{0,6,740},{0,4,1226},{0,4,7955},{0,3,3357},{2,7,320},{2,7,320},{2,7,320},{2,6,145},{3,3,4420},{0,6,740},{0,6,740},{0,4,1226},{6,1,4420},{0,4,1226},{7,4,5105},{4,7,2701},{3,7,25},{0,7,25},{7,4,5105},{7,5,5105},{0,7,25},{0,6,5645},{7,5,5105},{0,6,5645},{1,0,1832},
+{1,0,1832},{1,0,1832},{1,0,1832},{0,4,9},{0,4,9},{0,4,9},{0,2,49},{0,2,1010},{0,2,1010},{2,7,65535},{1,7,43497},{1,7,9052},{0,7,4633},{2,7,65535},{1,7,42629},{0,7,738},{0,6,14161},{0,7,65535},{0,6,47781},{3,7,10381},{3,7,4529},{2,7,576},{2,7,484},{5,4,17490},{1,7,9293},{0,7,738},{0,5,7553},{7,3,17490},{0,5,7553},{1,7,4428},{1,7,4428},{1,7,4428},
+{1,7,2412},{0,7,5218},{0,7,738},{0,7,738},{0,4,810},{0,4,8467},{0,3,3821},{2,7,576},{2,7,576},{2,7,576},{2,6,1},{4,2,4420},{0,7,738},{0,7,738},{0,4,810},{5,2,4420},{0,4,810},{6,6,4329},{4,7,2349},{3,7,9},{0,7,9},{6,6,4329},{4,7,4329},{0,7,9},{0,6,4637},{4,7,4329},{0,6,4637},{1,0,2312},{1,0,2312},{1,0,2312},{1,0,2312},{0,5,4},
+{0,5,4},{0,5,4},{0,3,36},{0,2,1186},{0,2,1186},{2,7,65535},{1,7,44905},{1,7,10460},{0,7,5897},{2,7,65535},{1,7,41829},{0,7,482},{0,6,12225},{0,7,65535},{0,6,45845},{4,7,9325},{3,7,4161},{3,7,797},{2,7,260},{7,1,16034},{1,7,8493},{0,7,482},{0,5,6513},{4,5,16034},{0,5,6513},{2,7,5712},{2,7,5712},{2,7,5712},{1,7,2924},{1,7,5672},{0,7,482},{0,7,482},
+{0,4,650},{0,4,9235},{0,4,3899},{3,7,797},{3,7,797},{3,7,797},{2,6,113},{5,1,4426},{0,7,482},{0,7,482},{0,4,650},{7,1,4426},{0,4,650},{6,6,3625},{5,7,1985},{4,7,100},{1,7,4},{6,6,3625},{6,6,3617},{1,7,4},{0,6,3757},{6,6,3617},{0,6,3757},{1,0,2920},{1,0,2920},{1,0,2920},{1,0,2920},{0,5,36},{0,5,36},{0,5,36},{0,3,4},{0,2,1490},
+{0,2,1490},{2,7,65535},{1,7,46795},{1,7,12350},{0,7,7625},{2,7,65535},{1,7,41235},{0,7,500},{0,6,10353},{0,7,65535},{0,6,43973},{4,7,8227},{3,7,4053},{3,7,689},{2,7,314},{6,3,14507},{2,7,7875},{0,7,500},{0,5,5649},{6,4,14507},{0,5,5649},{2,7,6594},{2,7,6594},{2,7,6594},{1,7,3806},{1,7,6086},{0,7,500},{0,7,500},{0,4,776},{0,5,9830},{0,4,4025},{3,7,689},
+{3,7,689},{3,7,689},{3,6,298},{6,0,4420},{0,7,500},{0,7,500},{0,4,776},{3,4,4420},{0,4,776},{7,5,2890},{5,7,1508},{4,7,1},{2,7,25},{7,5,2890},{6,6,2906},{2,7,25},{0,6,2920},{6,6,2906},{0,6,2920},{1,0,3757},{1,0,3757},{1,0,3757},{1,0,3757},{0,6,9},{0,6,9},{0,6,9},{0,4,100},{0,2,1985},{0,2,1985},{2,7,65535},{1,7,48747},{1,7,14302},
+{0,7,9433},{2,7,65535},{1,7,40979},{0,7,788},{0,6,8961},{0,7,65535},{0,6,42581},{4,7,7523},{4,7,3923},{3,7,865},{3,7,181},{7,2,13243},{2,7,7075},{1,7,754},{0,6,4337},{5,5,13243},{0,6,4337},{2,7,7650},{2,7,7650},{2,7,7650},{1,7,4862},{1,7,6726},{0,7,788},{0,7,788},{0,5,529},{0,5,10470},{0,4,4409},{3,7,865},{3,7,865},{3,7,865},{3,7,181},{5,2,4426},
+{1,7,754},{1,7,754},{0,5,529},{7,2,4426},{0,5,529},{6,7,2320},{5,7,1220},{4,7,49},{2,7,9},{6,7,2320},{5,7,2320},{2,7,9},{0,6,2312},{5,7,2320},{0,6,2312},{1,0,4637},{1,0,4637},{1,0,4637},{1,0,4637},{0,7,4},{0,7,4},{0,7,4},{0,4,4},{0,3,2297},{0,3,2297},{2,7,65535},{1,7,50955},{1,7,16510},{1,7,10798},{2,7,65535},{1,7,40979},{0,7,1332},
+{0,7,6964},{0,7,65535},{0,6,41445},{4,7,7075},{4,7,3475},{3,7,1297},{3,7,5},{6,4,12051},{2,7,6531},{1,7,754},{0,6,3201},{7,4,12051},{0,6,3201},{2,7,8962},{2,7,8962},{2,7,8962},{2,7,5834},{1,7,7622},{0,7,1332},{0,7,1332},{0,5,289},{0,6,11342},{0,4,5049},{3,7,1297},{3,7,1297},{3,7,1297},{3,7,5},{6,1,4426},{1,7,754},{1,7,754},{0,5,289},{6,3,4426},
+{0,5,289},{6,7,1808},{5,7,1060},{5,7,36},{3,7,4},{6,7,1808},{7,6,1808},{3,7,4},{0,6,1832},{7,6,1808},{0,6,1832},{1,0,5645},{1,0,5645},{1,0,5645},{1,0,5645},{0,7,36},{0,7,36},{0,7,36},{0,4,36},{0,3,2665},{0,3,2665},{2,7,65535},{1,7,53419},{1,7,18974},{1,7,12366},{2,7,65535},{1,7,41235},{0,7,2132},{0,7,5204},{0,7,65535},{0,6,40565},{5,7,6641},
+{4,7,3283},{4,7,1258},{3,7,85},{5,6,10952},{3,7,5900},{1,7,1010},{0,6,2321},{4,6,10952},{0,6,2321},{2,7,10530},{2,7,10530},{2,7,10530},{2,7,6666},{1,7,8774},{0,7,2132},{0,7,2132},{0,5,305},{0,6,11790},{0,5,5205},{4,7,1258},{4,7,1258},{4,7,1258},{3,7,85},{7,0,4420},{1,7,1010},{1,7,1010},{0,5,305},{3,5,4420},{0,5,305},{7,6,1360},{6,7,800},{5,7,4},
+{3,7,36},{7,6,1360},{7,6,1360},{3,7,36},{0,6,1480},{7,6,1360},{0,6,1480},{2,0,6305},{2,0,6305},{2,0,6305},{2,0,6305},{0,7,196},{0,7,196},{0,7,196},{0,5,49},{0,3,3161},{0,3,3161},{2,7,65535},{2,7,56301},{1,7,22052},{1,7,14436},{2,7,65535},{1,7,41829},{0,7,3338},{0,7,3530},{0,7,65535},{0,6,39881},{5,7,5741},{4,7,3373},{4,7,1348},{4,7,328},{7,3,9830},
+{3,7,5270},{2,7,1184},{0,6,1637},{6,5,9830},{0,6,1637},{2,7,12600},{2,7,12600},{2,7,12600},{2,7,7908},{1,7,10376},{1,7,2760},{1,7,2760},{0,6,481},{0,6,12600},{0,5,5529},{4,7,1348},{4,7,1348},{4,7,1348},{4,7,328},{7,1,4426},{2,7,1184},{2,7,1184},{0,6,481},{7,3,4426},{0,6,481},{7,6,937},{6,7,521},{5,7,121},{4,7,4},{7,6,937},{6,7,929},{4,7,4},
+{0,6,1237},{6,7,929},{0,6,1237},{2,0,7124},{2,0,7124},{2,0,7124},{2,0,7124},{0,7,529},{0,7,529},{0,7,529},{0,5,4},{0,4,3778},{0,4,3778},{2,7,65535},{2,7,58413},{1,7,25060},{1,7,16548},{2,7,65535},{1,7,42629},{0,7,4682},{0,7,2314},{0,7,65535},{0,6,39545},{5,7,5213},{5,7,3321},{4,7,1700},{4,7,200},{5,7,8902},{3,7,4982},{2,7,1440},{0,6,1301},{5,6,8902},
+{0,6,1301},{3,7,14701},{3,7,14701},{3,7,14701},{2,7,9284},{2,7,11492},{1,7,3560},{1,7,3560},{0,6,145},{0,6,13592},{0,5,6089},{4,7,1700},{4,7,1700},{4,7,1700},{4,7,200},{6,3,4420},{2,7,1440},{2,7,1440},{0,6,145},{6,4,4420},{0,6,145},{7,6,697},{6,7,409},{6,7,9},{5,7,9},{7,6,697},{6,7,625},{5,7,9},{0,6,1157},{6,7,625},{0,6,1157},{2,0,7988},
+{2,0,7988},{2,0,7988},{2,0,7988},{0,7,961},{0,7,961},{0,7,961},{0,5,100},{0,4,4210},{0,4,4210},{3,7,65535},{2,7,60781},{1,7,28324},{1,7,18916},{2,7,65535},{1,7,43685},{0,7,6282},{0,7,1354},{0,7,65535},{0,6,39465},{5,7,4941},{5,7,3049},{5,7,2025},{4,7,328},{7,4,8069},{4,7,4465},{3,7,1586},{0,6,1221},{7,5,8069},{0,6,1221},{3,7,16189},{3,7,16189},{3,7,16189},
+{2,7,10916},{2,7,12740},{1,7,4616},{1,7,4616},{0,6,65},{0,7,14411},{0,6,6789},{5,7,2025},{5,7,2025},{5,7,2025},{4,7,328},{7,2,4420},{3,7,1586},{3,7,1586},{0,6,65},{5,5,4420},{0,6,65},{7,7,377},{7,7,305},{6,7,25},{5,7,25},{7,7,377},{6,7,449},{5,7,25},{0,7,729},{6,7,449},{0,7,729},{2,0,8980},{2,0,8980},{2,0,8980},{2,0,8980},{1,7,1480},
+{1,7,1480},{1,7,1480},{0,6,16},{0,4,4770},{0,4,4770},{3,7,65535},{2,7,59505},{1,7,29984},{1,7,19680},{2,7,65535},{1,7,43137},{0,7,8318},{0,7,830},{0,7,65535},{0,6,34901},{5,7,4925},{5,7,3033},{5,7,2009},{4,7,712},{6,6,7325},{4,7,4145},{3,7,1810},{0,7,650},{4,7,7325},{0,7,650},{3,7,16745},{3,7,16745},{3,7,16745},{2,7,12024},{2,7,13464},{1,7,5556},{1,7,5556},
+{0,6,277},{0,7,14139},{0,6,6017},{5,7,2009},{5,7,2009},{5,7,2009},{4,7,712},{5,6,4418},{3,7,1810},{3,7,1810},{0,6,241},{4,6,4418},{0,6,241},{7,7,185},{7,7,113},{7,7,64},{6,7,1},{7,7,185},{7,7,193},{6,7,1},{0,7,361},{7,7,193},{0,7,361},{2,0,9320},{2,0,9320},{2,0,9320},{2,0,9320},{1,7,1460},{1,7,1460},{1,7,1460},{0,6,52},{0,5,4772},
+{0,5,4772},{3,7,65535},{2,7,57588},{1,7,32135},{1,7,20823},{3,7,65535},{1,7,42804},{1,7,8359},{0,7,1289},{0,7,65535},{0,6,28970},{6,7,4317},{5,7,3321},{5,7,2297},{5,7,845},{7,5,6587},{5,7,4008},{4,7,2066},{0,7,164},{6,6,6611},{0,7,164},{3,7,17366},{3,7,17366},{3,7,17366},{3,7,12274},{2,7,14427},{2,7,6699},{2,7,6699},{0,7,389},{0,7,13860},{0,6,5234},{5,7,2297},
+{5,7,2297},{5,7,2297},{5,7,845},{6,5,4420},{4,7,2066},{4,7,2066},{0,7,164},{3,7,4420},{0,7,164},{7,7,122},{7,7,50},{7,7,1},{7,7,9},{7,7,122},{7,7,58},{7,7,9},{0,7,100},{7,7,58},{0,7,100},{2,0,9698},{2,0,9698},{2,0,9698},{2,0,9698},{1,7,1586},{1,7,1586},{1,7,1586},{0,7,289},{0,5,4250},{0,5,4250},{3,7,65535},{2,7,56836},{2,7,31631},
+{1,7,22791},{3,7,65535},{2,7,40532},{1,7,9015},{1,7,778},{0,7,65535},{0,6,24650},{6,7,3949},{6,7,3325},{5,7,2825},{5,7,1021},{6,7,6020},{5,7,3688},{4,7,2290},{0,7,4},{5,7,6020},{0,7,4},{3,7,18326},{3,7,18326},{3,7,18326},{3,7,12626},{3,7,15077},{2,7,7227},{2,7,7227},{1,7,294},{0,7,14020},{0,6,4946},{5,7,2825},{5,7,2825},{5,7,2825},{5,7,1021},{7,4,4418},
+{4,7,2290},{4,7,2290},{0,7,4},{7,5,4418},{0,7,4},{7,7,202},{7,7,130},{7,7,81},{7,7,25},{7,7,202},{7,7,74},{7,7,25},{0,7,4},{7,7,74},{0,7,4},{3,0,9490},{3,0,9490},{3,0,9490},{3,0,9490},{1,7,1970},{1,7,1970},{1,7,1970},{1,6,202},{0,6,3922},{0,6,3922},{3,7,65535},{3,7,55466},{2,7,30335},{2,7,21687},{3,7,65535},{2,7,37932},{1,7,9535},
+{1,7,70},{0,7,65535},{0,7,20544},{6,7,3417},{6,7,2793},{6,7,2393},{5,7,1033},{6,7,5184},{5,7,3204},{5,7,2180},{1,7,25},{7,6,5168},{1,7,25},{4,7,17611},{4,7,17611},{4,7,17611},{3,7,12630},{3,7,14321},{2,7,7251},{2,7,7251},{1,7,34},{0,7,13376},{0,7,4160},{6,7,2393},{6,7,2393},{6,7,2393},{5,7,1033},{6,6,3874},{5,7,2180},{5,7,2180},{1,7,25},{4,7,3874},
+{1,7,25},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{3,0,9266},{3,0,9266},{3,0,9266},{3,0,9266},{2,7,2210},{2,7,2210},{2,7,2210},{1,7,34},{0,6,3442},{0,6,3442},{3,7,65535},{3,7,51210},{2,7,29343},{2,7,20695},{3,7,65535},{2,7,35820},{1,7,10495},{1,7,134},{1,7,65535},{0,7,15936},{6,7,2889},
+{6,7,2265},{6,7,1865},{5,7,1049},{7,6,4288},{5,7,2724},{5,7,1700},{1,7,9},{7,6,4272},{1,7,9},{4,7,16555},{4,7,16555},{4,7,16555},{3,7,12662},{3,7,13441},{2,7,7251},{2,7,7251},{1,7,34},{0,7,12608},{0,7,3392},{6,7,1865},{6,7,1865},{6,7,1865},{5,7,1049},{7,5,3218},{5,7,1700},{5,7,1700},{1,7,9},{6,6,3202},{1,7,9},{7,7,242},{7,7,170},{7,7,121},
+{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{3,0,9298},{3,0,9298},{3,0,9298},{3,0,9298},{2,7,2210},{2,7,2210},{2,7,2210},{1,7,34},{0,6,3218},{0,6,3218},{4,7,65535},{3,7,47340},{2,7,29145},{2,7,20497},{3,7,65535},{2,7,34362},{2,7,9157},{1,7,1124},{1,7,64598},{0,7,11670},{6,7,2448},{6,7,1824},{6,7,1424},{6,7,800},{7,6,3361},
+{6,7,2321},{5,7,1313},{2,7,0},{6,7,3401},{2,7,0},{4,7,15673},{4,7,15673},{4,7,15673},{4,7,12073},{3,7,12757},{3,7,6905},{3,7,6905},{1,7,340},{1,7,11657},{0,7,2834},{6,7,1424},{6,7,1424},{6,7,1424},{6,7,800},{7,5,2525},{5,7,1313},{5,7,1313},{2,7,0},{5,7,2545},{2,7,0},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},
+{0,7,0},{7,7,98},{0,7,0},{3,0,9640},{3,0,9640},{3,0,9640},{3,0,9640},{2,7,2516},{2,7,2516},{2,7,2516},{1,7,340},{0,7,2834},{0,7,2834},{4,7,65535},{3,7,44716},{3,7,27896},{2,7,21137},{4,7,65535},{3,7,31853},{2,7,8677},{2,7,784},{1,7,59734},{0,7,8694},{6,7,2192},{6,7,1568},{6,7,1168},{6,7,544},{7,6,2673},{6,7,1761},{5,7,1105},{3,7,25},{6,7,2649},
+{3,7,25},{4,7,15161},{4,7,15161},{4,7,15161},{4,7,11561},{4,7,12169},{3,7,6569},{3,7,6569},{2,7,208},{1,7,10889},{0,7,2610},{6,7,1168},{6,7,1168},{6,7,1168},{6,7,544},{6,7,1985},{5,7,1105},{5,7,1105},{3,7,25},{5,7,1985},{3,7,25},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{4,0,9536},
+{4,0,9536},{4,0,9536},{4,0,9536},{2,7,3060},{2,7,3060},{2,7,3060},{2,7,208},{0,7,2610},{0,7,2610},{4,7,63766},{3,7,42860},{3,7,26040},{3,7,20188},{4,7,60070},{3,7,29085},{2,7,8965},{2,7,336},{1,7,55638},{0,7,6486},{7,7,1686},{6,7,1440},{6,7,1040},{6,7,416},{7,6,2113},{6,7,1329},{6,7,929},{3,7,9},{6,7,2025},{3,7,9},{4,7,14905},{4,7,14905},{4,7,14905},
+{4,7,11305},{4,7,11209},{3,7,6489},{3,7,6489},{2,7,272},{1,7,10377},{0,7,2642},{6,7,1040},{6,7,1040},{6,7,1040},{6,7,416},{7,6,1537},{6,7,929},{6,7,929},{3,7,9},{7,6,1513},{3,7,9},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{4,0,9280},{4,0,9280},{4,0,9280},{4,0,9280},{3,7,3125},
+{3,7,3125},{3,7,3125},{2,7,272},{0,7,2642},{0,7,2642},{4,7,59414},{4,7,41414},{3,7,24952},{3,7,19100},{4,7,55014},{3,7,27085},{2,7,10021},{2,7,656},{1,7,52310},{0,7,5046},{7,7,1142},{7,7,1070},{7,7,1021},{6,7,416},{7,7,1538},{6,7,1025},{6,7,625},{4,7,4},{6,7,1529},{4,7,4},{5,7,13964},{5,7,13964},{5,7,13964},{4,7,11305},{4,7,10505},{3,7,6665},{3,7,6665},
+{2,7,592},{2,7,9973},{0,7,2930},{7,7,1021},{7,7,1021},{7,7,1021},{6,7,416},{7,6,1105},{6,7,625},{6,7,625},{4,7,4},{6,7,1129},{4,7,4},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{4,0,9280},{4,0,9280},{4,0,9280},{4,0,9280},{3,7,3301},{3,7,3301},{3,7,3301},{2,7,592},{0,7,2930},
+{0,7,2930}, \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Common/b3Logging.h b/thirdparty/bullet/Bullet3Common/b3Logging.h
index 9c92b12ebb..f61149de77 100644
--- a/thirdparty/bullet/Bullet3Common/b3Logging.h
+++ b/thirdparty/bullet/Bullet3Common/b3Logging.h
@@ -14,20 +14,8 @@ extern "C"
//#define b3Printf b3OutputPrintfVarArgsInternal
//#define b3Printf(...) printf(__VA_ARGS__)
//#define b3Printf(...)
-
-#define b3Warning(...) \
- do \
- { \
- b3OutputWarningMessageVarArgsInternal("b3Warning[%s,%d]:\n", __FILE__, __LINE__); \
- b3OutputWarningMessageVarArgsInternal(__VA_ARGS__); \
- } while (0)
-#define b3Error(...) \
- do \
- { \
- b3OutputErrorMessageVarArgsInternal("b3Error[%s,%d]:\n", __FILE__, __LINE__); \
- b3OutputErrorMessageVarArgsInternal(__VA_ARGS__); \
- } while (0)
-
+#define b3Warning(...) do{ b3OutputWarningMessageVarArgsInternal("b3Warning[%s,%d]:\n", __FILE__, __LINE__);b3OutputWarningMessageVarArgsInternal(__VA_ARGS__);} while (0)
+#define b3Error(...)do {b3OutputErrorMessageVarArgsInternal("b3Error[%s,%d]:\n", __FILE__, __LINE__);b3OutputErrorMessageVarArgsInternal(__VA_ARGS__);} while (0)
#ifndef B3_NO_PROFILE
void b3EnterProfileZone(const char* name);
diff --git a/thirdparty/bullet/Bullet3Common/b3Scalar.h b/thirdparty/bullet/Bullet3Common/b3Scalar.h
index 0db5eb6f4f..eeb70ed632 100644
--- a/thirdparty/bullet/Bullet3Common/b3Scalar.h
+++ b/thirdparty/bullet/Bullet3Common/b3Scalar.h
@@ -40,8 +40,12 @@ inline int b3GetVersion()
#ifdef _WIN32
-#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined(_MSC_VER) && _MSC_VER < 1300)
-
+#if defined(__GNUC__) // it should handle both MINGW and CYGWIN
+#define B3_FORCE_INLINE __inline__ __attribute__((always_inline))
+#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#elif ( defined(_MSC_VER) && _MSC_VER < 1300 )
#define B3_FORCE_INLINE inline
#define B3_ATTRIBUTE_ALIGNED16(a) a
#define B3_ATTRIBUTE_ALIGNED64(a) a
@@ -67,7 +71,17 @@ inline int b3GetVersion()
#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(B3_USE_DOUBLE_PRECISION))
#if (defined(_M_IX86) || defined(_M_X64))
+
+
+#ifdef __clang__
+//#define B3_NO_SIMD_OPERATOR_OVERLOADS
+#define B3_DISABLE_SSE
+#endif //__clang__
+
+#ifndef B3_DISABLE_SSE
#define B3_USE_SSE
+#endif //B3_DISABLE_SSE
+
#ifdef B3_USE_SSE
//B3_USE_SSE_IN_API is disabled under Windows by default, because
//it makes it harder to integrate Bullet into your application under Windows
@@ -88,17 +102,7 @@ inline int b3GetVersion()
#ifdef B3_DEBUG
#ifdef _MSC_VER
#include <stdio.h>
-#define b3Assert(x) \
- { \
- if (!(x)) \
- { \
- b3Error( \
- "Assert "__FILE__ \
- ":%u (" #x ")\n", \
- __LINE__); \
- __debugbreak(); \
- } \
- }
+#define b3Assert(x) { if(!(x)){b3Error("Assert " __FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }}
#else //_MSC_VER
#include <assert.h>
#define b3Assert assert
@@ -293,7 +297,7 @@ static int b3NanMask = 0x7F800001;
static int b3InfinityMask = 0x7F800000;
#define B3_INFINITY_MASK (*(float *)&b3InfinityMask)
#endif
-
+#ifndef B3_NO_SIMD_OPERATOR_OVERLOADS
inline __m128 operator+(const __m128 A, const __m128 B)
{
return _mm_add_ps(A, B);
@@ -308,7 +312,7 @@ inline __m128 operator*(const __m128 A, const __m128 B)
{
return _mm_mul_ps(A, B);
}
-
+#endif //B3_NO_SIMD_OPERATOR_OVERLOADS
#define b3CastfTo128i(a) (_mm_castps_si128(a))
#define b3CastfTo128d(a) (_mm_castps_pd(a))
#define b3CastiTo128f(a) (_mm_castsi128_ps(a))
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
index 0721928684..616fc34f3a 100644
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
@@ -496,7 +496,7 @@ void b3GpuParallelLinearBvh::constructBinaryRadixTree()
clFinish(m_queue);
}
- //Find the number of nodes seperating each internal node and the root node
+ //Find the number of nodes separating each internal node and the root node
//so that the AABBs can be set using the next kernel.
//Also determine the maximum number of nodes separating an internal node and the root node.
{
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
index 087b30f3e6..2b1e63be75 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
@@ -68,7 +68,7 @@ public:
virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
- /// getNumSubParts returns the number of seperate subparts
+ /// getNumSubParts returns the number of separate subparts
/// each subpart has a continuous array of vertices and indices
virtual int getNumSubParts() const = 0;
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
index b6ceb8df10..57cbf03dc2 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
@@ -100,7 +100,7 @@ public:
virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
- /// getNumSubParts returns the number of seperate subparts
+ /// getNumSubParts returns the number of separate subparts
/// each subpart has a continuous array of vertices and indices
virtual int getNumSubParts() const
{
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
index dae61d4581..8b0a834efe 100644
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
+++ b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
@@ -183,9 +183,9 @@ bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
const b3Vector3& c = m_simplexVectorW[2];
const b3Vector3& d = m_simplexVectorW[3];
- bool hasSeperation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
+ bool hasSeparation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
- if (hasSeperation)
+ if (hasSeparation)
{
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
index 825caeef56..bc0742ad62 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
@@ -187,13 +187,6 @@ btBroadphasePair
BT_DECLARE_ALIGNED_ALLOCATOR();
- btBroadphasePair(const btBroadphasePair& other)
- : m_pProxy0(other.m_pProxy0),
- m_pProxy1(other.m_pProxy1),
- m_algorithm(other.m_algorithm),
- m_internalInfo1(other.m_internalInfo1)
- {
- }
btBroadphasePair(btBroadphaseProxy & proxy0, btBroadphaseProxy & proxy1)
{
//keep them sorted, so the std::set operations work
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
index a316dbf207..55daa7fb57 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
@@ -21,7 +21,6 @@ subject to the following restrictions:
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btAabbUtil2.h"
-
//
// Compile time configuration
//
@@ -131,6 +130,7 @@ subject to the following restrictions:
/* btDbvtAabbMm */
struct btDbvtAabbMm
{
+ DBVT_INLINE btDbvtAabbMm(){}
DBVT_INLINE btVector3 Center() const { return ((mi + mx) / 2); }
DBVT_INLINE btVector3 Lengths() const { return (mx - mi); }
DBVT_INLINE btVector3 Extents() const { return ((mx - mi) / 2); }
@@ -190,6 +190,36 @@ struct btDbvtNode
};
};
+/* btDbv(normal)tNode */
+struct btDbvntNode
+{
+ btDbvtVolume volume;
+ btVector3 normal;
+ btScalar angle;
+ DBVT_INLINE bool isleaf() const { return (childs[1] == 0); }
+ DBVT_INLINE bool isinternal() const { return (!isleaf()); }
+ btDbvntNode* childs[2];
+ void* data;
+
+ btDbvntNode(const btDbvtNode* n)
+ : volume(n->volume)
+ , normal(0,0,0)
+ , angle(0)
+ , data(n->data)
+ {
+ childs[0] = 0;
+ childs[1] = 0;
+ }
+
+ ~btDbvntNode()
+ {
+ if (childs[0])
+ delete childs[0];
+ if (childs[1])
+ delete childs[1];
+ }
+};
+
typedef btAlignedObjectArray<const btDbvtNode*> btNodeStack;
///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
@@ -225,6 +255,14 @@ struct btDbvt
btDbvtNode* parent;
sStkCLN(const btDbvtNode* n, btDbvtNode* p) : node(n), parent(p) {}
};
+
+ struct sStknNN
+ {
+ const btDbvntNode* a;
+ const btDbvntNode* b;
+ sStknNN() {}
+ sStknNN(const btDbvntNode* na, const btDbvntNode* nb) : a(na), b(nb) {}
+ };
// Policies/Interfaces
/* ICollide */
@@ -234,6 +272,7 @@ struct btDbvt
DBVT_VIRTUAL void Process(const btDbvtNode*, const btDbvtNode*) {}
DBVT_VIRTUAL void Process(const btDbvtNode*) {}
DBVT_VIRTUAL void Process(const btDbvtNode* n, btScalar) { Process(n); }
+ DBVT_VIRTUAL void Process(const btDbvntNode*, const btDbvntNode*) {}
DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return (true); }
DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return (true); }
};
@@ -306,6 +345,12 @@ struct btDbvt
void collideTT(const btDbvtNode* root0,
const btDbvtNode* root1,
DBVT_IPOLICY);
+ DBVT_PREFIX
+ void selfCollideT(const btDbvntNode* root,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ void selfCollideTT(const btDbvtNode* root,
+ DBVT_IPOLICY);
DBVT_PREFIX
void collideTTpersistentStack(const btDbvtNode* root0,
@@ -837,6 +882,135 @@ inline void btDbvt::collideTT(const btDbvtNode* root0,
}
}
+//
+DBVT_PREFIX
+inline void btDbvt::selfCollideT(const btDbvntNode* root,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if (root)
+ {
+ int depth = 1;
+ int treshold = DOUBLE_STACKSIZE - 4;
+ btAlignedObjectArray<sStknNN> stkStack;
+ stkStack.resize(DOUBLE_STACKSIZE);
+ stkStack[0] = sStknNN(root, root);
+ do
+ {
+ sStknNN p = stkStack[--depth];
+ if (depth > treshold)
+ {
+ stkStack.resize(stkStack.size() * 2);
+ treshold = stkStack.size() - 4;
+ }
+ if (p.a == p.b)
+ {
+ if (p.a->isinternal() && p.a->angle > SIMD_PI)
+ {
+ stkStack[depth++] = sStknNN(p.a->childs[0], p.a->childs[0]);
+ stkStack[depth++] = sStknNN(p.a->childs[1], p.a->childs[1]);
+ stkStack[depth++] = sStknNN(p.a->childs[0], p.a->childs[1]);
+ }
+ }
+ else if (Intersect(p.a->volume, p.b->volume))
+ {
+ if (p.a->isinternal())
+ {
+ if (p.b->isinternal())
+ {
+ stkStack[depth++] = sStknNN(p.a->childs[0], p.b->childs[0]);
+ stkStack[depth++] = sStknNN(p.a->childs[1], p.b->childs[0]);
+ stkStack[depth++] = sStknNN(p.a->childs[0], p.b->childs[1]);
+ stkStack[depth++] = sStknNN(p.a->childs[1], p.b->childs[1]);
+ }
+ else
+ {
+ stkStack[depth++] = sStknNN(p.a->childs[0], p.b);
+ stkStack[depth++] = sStknNN(p.a->childs[1], p.b);
+ }
+ }
+ else
+ {
+ if (p.b->isinternal())
+ {
+ stkStack[depth++] = sStknNN(p.a, p.b->childs[0]);
+ stkStack[depth++] = sStknNN(p.a, p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a, p.b);
+ }
+ }
+ }
+ } while (depth);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::selfCollideTT(const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if (root)
+ {
+ int depth = 1;
+ int treshold = DOUBLE_STACKSIZE - 4;
+ btAlignedObjectArray<sStkNN> stkStack;
+ stkStack.resize(DOUBLE_STACKSIZE);
+ stkStack[0] = sStkNN(root, root);
+ do
+ {
+ sStkNN p = stkStack[--depth];
+ if (depth > treshold)
+ {
+ stkStack.resize(stkStack.size() * 2);
+ treshold = stkStack.size() - 4;
+ }
+ if (p.a == p.b)
+ {
+ if (p.a->isinternal())
+ {
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
+ }
+ }
+ else if (Intersect(p.a->volume, p.b->volume))
+ {
+ if (p.a->isinternal())
+ {
+ if (p.b->isinternal())
+ {
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+ }
+ else
+ {
+ stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+ stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
+ }
+ }
+ else
+ {
+ if (p.b->isinternal())
+ {
+ stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+ stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a, p.b);
+ }
+ }
+ }
+ } while (depth);
+ }
+}
+
+
DBVT_PREFIX
inline void btDbvt::collideTTpersistentStack(const btDbvtNode* root0,
const btDbvtNode* root1,
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
index a85782bc8a..56011899cb 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
@@ -61,14 +61,15 @@ public:
virtual void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher) = 0;
virtual int getNumOverlappingPairs() const = 0;
-
+ virtual bool needsBroadphaseCollision(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1) const = 0;
+ virtual btOverlapFilterCallback* getOverlapFilterCallback() = 0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher) = 0;
- virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo)
+ virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& /*dispatchInfo*/)
{
processAllOverlappingPairs(callback, dispatcher);
}
@@ -380,6 +381,14 @@ public:
{
}
+ bool needsBroadphaseCollision(btBroadphaseProxy*, btBroadphaseProxy*) const
+ {
+ return true;
+ }
+ btOverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return 0;
+ }
virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
{
}
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
index b814fd84d8..4954e773e2 100644
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
+++ b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
@@ -468,7 +468,7 @@ void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCall
#ifdef RAYAABB2
btVector3 rayDir = (rayTarget - raySource);
- rayDir.normalize();
+ rayDir.safeNormalize();// stephengold changed normalize to safeNormalize 2020-02-17
lambda_max = rayDir.dot(rayTarget - raySource);
///what about division by zero? --> just set rayDirection[i] to 1.0
btVector3 rayDirectionInverse;
@@ -554,7 +554,7 @@ void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback*
#ifdef RAYAABB2
btVector3 rayDirection = (rayTarget - raySource);
- rayDirection.normalize();
+ rayDirection.safeNormalize();// stephengold changed normalize to safeNormalize 2020-02-17
lambda_max = rayDirection.dot(rayTarget - raySource);
///what about division by zero? --> just set rayDirection[i] to 1.0
rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0];
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
index 6b9f5e23a5..04309670cf 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
@@ -46,8 +46,6 @@ protected:
btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
- btManifoldResult m_defaultManifoldResult;
-
btNearCallback m_nearCallback;
btPoolAllocator* m_collisionAlgorithmPoolAllocator;
@@ -95,11 +93,15 @@ public:
btPersistentManifold* getManifoldByIndexInternal(int index)
{
+ btAssert(index>=0);
+ btAssert(index<m_manifoldsPtr.size());
return m_manifoldsPtr[index];
}
const btPersistentManifold* getManifoldByIndexInternal(int index) const
{
+ btAssert(index>=0);
+ btAssert(index<m_manifoldsPtr.size());
return m_manifoldsPtr[index];
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
index 6fe56538d2..89bc8d920e 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
@@ -28,6 +28,7 @@ subject to the following restrictions:
btCollisionDispatcherMt::btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize)
: btCollisionDispatcher(config)
{
+ m_batchManifoldsPtr.resize(btGetTaskScheduler()->getNumThreads());
m_batchUpdating = false;
m_grainSize = grainSize; // iterations per task
}
@@ -65,6 +66,10 @@ btPersistentManifold* btCollisionDispatcherMt::getNewManifold(const btCollisionO
manifold->m_index1a = m_manifoldsPtr.size();
m_manifoldsPtr.push_back(manifold);
}
+ else
+ {
+ m_batchManifoldsPtr[btGetCurrentThreadIndex()].push_back(manifold);
+ }
return manifold;
}
@@ -121,7 +126,7 @@ struct CollisionDispatcherUpdater : public btIParallelForBody
void btCollisionDispatcherMt::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher)
{
- int pairCount = pairCache->getNumOverlappingPairs();
+ const int pairCount = pairCache->getNumOverlappingPairs();
if (pairCount == 0)
{
return;
@@ -136,16 +141,17 @@ void btCollisionDispatcherMt::dispatchAllCollisionPairs(btOverlappingPairCache*
btParallelFor(0, pairCount, m_grainSize, updater);
m_batchUpdating = false;
- // reconstruct the manifolds array to ensure determinism
- m_manifoldsPtr.resizeNoInitialize(0);
-
- btBroadphasePair* pairs = pairCache->getOverlappingPairArrayPtr();
- for (int i = 0; i < pairCount; ++i)
+ // merge new manifolds, if any
+ for (int i = 0; i < m_batchManifoldsPtr.size(); ++i)
{
- if (btCollisionAlgorithm* algo = pairs[i].m_algorithm)
+ btAlignedObjectArray<btPersistentManifold*>& batchManifoldsPtr = m_batchManifoldsPtr[i];
+
+ for (int j = 0; j < batchManifoldsPtr.size(); ++j)
{
- algo->getAllContactManifolds(m_manifoldsPtr);
+ m_manifoldsPtr.push_back(batchManifoldsPtr[j]);
}
+
+ batchManifoldsPtr.resizeNoInitialize(0);
}
// update the indices (used when releasing manifolds)
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
index 28eba7f32a..1155de2cfe 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
@@ -30,6 +30,7 @@ public:
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher) BT_OVERRIDE;
protected:
+ btAlignedObjectArray<btAlignedObjectArray<btPersistentManifold*> > m_batchManifoldsPtr;
bool m_batchUpdating;
int m_grainSize;
};
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
index 1cc4a5ac5f..56341b7d29 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
@@ -27,13 +27,19 @@ public:
const btCollisionShape* m_shape;
const btCollisionObject* m_collisionObject;
const btTransform& m_worldTransform;
+ const btTransform* m_preTransform;
int m_partId;
int m_index;
btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, int partId, int index)
- : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_partId(partId), m_index(index)
+ : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(NULL), m_partId(partId), m_index(index)
{
}
+
+ btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, const btTransform& preTransform, int partId, int index)
+ : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(&preTransform), m_partId(partId), m_index(index)
+ {
+ }
SIMD_FORCE_INLINE const btTransform& getWorldTransform() const { return m_worldTransform; }
SIMD_FORCE_INLINE const btCollisionObject* getCollisionObject() const { return m_collisionObject; }
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
index 9f422dc157..e56e73dcf5 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
@@ -292,8 +292,8 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape(btCollisionSha
}
break;
}
-#endif //SUPPORT_GIMPACT_SHAPE_IMPORT \
- //The btCapsuleShape* API has issue passing the margin/scaling/halfextents unmodified through the API \
+#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
+ //The btCapsuleShape* API has issue passing the margin/scaling/halfextents unmodified through the API
//so deal with this
case CAPSULE_SHAPE_PROXYTYPE:
{
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
index 633bee4825..b5f4a3c869 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
@@ -139,7 +139,12 @@ public:
if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
{
- btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, -1, index);
+ btTransform preTransform = childTrans;
+ if (this->m_compoundColObjWrap->m_preTransform)
+ {
+ preTransform = preTransform *(*(this->m_compoundColObjWrap->m_preTransform));
+ }
+ btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, preTransform, -1, index);
btCollisionAlgorithm* algo = 0;
bool allocatedAlgorithm = false;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
index 44dd3c553e..b48d97f2b2 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
@@ -503,9 +503,9 @@ void btConvexConvexAlgorithm ::processCollision(const btCollisionObjectWrapper*
gjkPairDetector.getClosestPoints(input, withoutMargin, dispatchInfo.m_debugDraw);
//gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
-#endif //ZERO_MARGIN \
- //btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); \
- //if (l2>SIMD_EPSILON)
+#endif //ZERO_MARGIN
+ //btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
+ //if (l2>SIMD_EPSILON)
{
sepNormalWorldSpace = withoutMargin.m_reportedNormalOnWorld; //gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
//minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance();
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
index e74c83f9f1..a4252c296a 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
@@ -1,6 +1,8 @@
#include "btInternalEdgeUtility.h"
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
+
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
@@ -290,6 +292,39 @@ struct btConnectivityProcessor : public btTriangleCallback
}
}
};
+
+
+struct b3ProcessAllTrianglesHeightfield: public btTriangleCallback
+{
+ btHeightfieldTerrainShape* m_heightfieldShape;
+ btTriangleInfoMap* m_triangleInfoMap;
+
+
+ b3ProcessAllTrianglesHeightfield(btHeightfieldTerrainShape* heightFieldShape, btTriangleInfoMap* triangleInfoMap)
+ :m_heightfieldShape(heightFieldShape),
+ m_triangleInfoMap(triangleInfoMap)
+ {
+ }
+ virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+ {
+ btConnectivityProcessor connectivityProcessor;
+ connectivityProcessor.m_partIdA = partId;
+ connectivityProcessor.m_triangleIndexA = triangleIndex;
+ connectivityProcessor.m_triangleVerticesA = triangle;
+ connectivityProcessor.m_triangleInfoMap = m_triangleInfoMap;
+ btVector3 aabbMin, aabbMax;
+ aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+ aabbMin.setMin(triangle[0]);
+ aabbMax.setMax(triangle[0]);
+ aabbMin.setMin(triangle[1]);
+ aabbMax.setMax(triangle[1]);
+ aabbMin.setMin(triangle[2]);
+ aabbMax.setMax(triangle[2]);
+
+ m_heightfieldShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
+ }
+};
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
@@ -361,6 +396,28 @@ void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangle
}
}
+
+void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* heightfieldShape, btTriangleInfoMap* triangleInfoMap)
+{
+
+ //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
+ if (heightfieldShape->getTriangleInfoMap())
+ return;
+
+ heightfieldShape->setTriangleInfoMap(triangleInfoMap);
+
+ //get all the triangles of the heightfield
+
+ btVector3 aabbMin, aabbMax;
+
+ aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+ aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+
+ b3ProcessAllTrianglesHeightfield processHeightfield(heightfieldShape, triangleInfoMap);
+ heightfieldShape->processAllTriangles(&processHeightfield, aabbMin, aabbMax);
+
+}
+
// Given a point and a line segment (defined by two points), compute the closest point
// in the line. Cap the point at the endpoints of the line segment.
void btNearestPointInLineSegment(const btVector3& point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
@@ -426,6 +483,32 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWr
if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
return;
+
+ btTriangleInfoMap* triangleInfoMapPtr = 0;
+
+ if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
+ {
+ btHeightfieldTerrainShape* heightfield = (btHeightfieldTerrainShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
+ triangleInfoMapPtr = heightfield->getTriangleInfoMap();
+
+//#define USE_HEIGHTFIELD_TRIANGLES
+#ifdef USE_HEIGHTFIELD_TRIANGLES
+ btVector3 newNormal = btVector3(0, 0, 1);
+
+ const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
+ btVector3 tri_normal;
+ tri_shape->calcNormal(tri_normal);
+ newNormal = tri_normal;
+ // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+ cp.m_normalWorldOnB = newNormal;
+ // Reproject collision point along normal. (what about cp.m_distance1?)
+ cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ return;
+#endif
+ }
+
+
btBvhTriangleMeshShape* trimesh = 0;
if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
@@ -439,10 +522,12 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWr
trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
}
}
- if (trimesh == 0)
- return;
-
- btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
+ if (trimesh)
+ {
+ triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
+ }
+
+
if (!triangleInfoMapPtr)
return;
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
index 9d9cff040f..cc6d11c241 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
@@ -15,6 +15,7 @@ class btCollisionObject;
struct btCollisionObjectWrapper;
class btManifoldPoint;
class btIDebugDraw;
+class btHeightfieldTerrainShape;
enum btInternalEdgeAdjustFlags
{
@@ -26,6 +27,8 @@ enum btInternalEdgeAdjustFlags
///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
+void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
+
///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
///If this info map is missing, or the triangle is not store in this map, nothing will be done
void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap, const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
index e5097ccbbf..327b3f076a 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
@@ -233,7 +233,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
// printf("error in island management\n");
}
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
if (colObj0->getActivationState() == ACTIVE_TAG ||
@@ -257,7 +257,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
// printf("error in island management\n");
}
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
@@ -278,7 +278,8 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
// printf("error in island management\n");
}
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+ btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
if (colObj0->getIslandTag() == islandId)
{
@@ -337,13 +338,17 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
}
}
+
///@todo: this is random access, it can be walked 'cache friendly'!
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
{
- btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
-
buildIslands(dispatcher, collisionWorld);
+ processIslands(dispatcher, collisionWorld, callback);
+}
+void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
+{
+ btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
int endIslandIndex = 1;
int startIslandIndex;
int numElem = getUnionFind().getNumElements();
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
index 6c2802141c..197bb457cf 100644
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
+++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
@@ -57,9 +57,11 @@ public:
};
void buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
-
+
void buildIslands(btDispatcher* dispatcher, btCollisionWorld* colWorld);
+ void processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
+
bool getSplitIslands()
{
return m_splitIslands;
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
index 34ec2d8c45..34e7926f17 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
@@ -21,6 +21,9 @@ btHeightfieldTerrainShape::btHeightfieldTerrainShape(
int heightStickWidth, int heightStickLength, const void* heightfieldData,
btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
PHY_ScalarType hdt, bool flipQuadEdges)
+ :m_userIndex2(-1),
+ m_userValue3(0),
+ m_triangleInfoMap(0)
{
initialize(heightStickWidth, heightStickLength, heightfieldData,
heightScale, minHeight, maxHeight, upAxis, hdt,
@@ -28,6 +31,9 @@ btHeightfieldTerrainShape::btHeightfieldTerrainShape(
}
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges)
+ :m_userIndex2(-1),
+ m_userValue3(0),
+ m_triangleInfoMap(0)
{
// legacy constructor: support only float or unsigned char,
// and min height is zero
@@ -349,12 +355,12 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
getVertex(x, j, vertices[indices[0]]);
getVertex(x, j + 1, vertices[indices[1]]);
getVertex(x + 1, j + 1, vertices[indices[2]]);
- callback->processTriangle(vertices, x, j);
+ callback->processTriangle(vertices, 2 * x, j);
//second triangle
// getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
getVertex(x + 1, j + 1, vertices[indices[1]]);
getVertex(x + 1, j, vertices[indices[2]]);
- callback->processTriangle(vertices, x, j);
+ callback->processTriangle(vertices, 2 * x+1, j);
}
else
{
@@ -362,12 +368,12 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
getVertex(x, j, vertices[indices[0]]);
getVertex(x, j + 1, vertices[indices[1]]);
getVertex(x + 1, j, vertices[indices[2]]);
- callback->processTriangle(vertices, x, j);
+ callback->processTriangle(vertices, 2 * x, j);
//second triangle
getVertex(x + 1, j, vertices[indices[0]]);
//getVertex(x,j+1,vertices[1]);
getVertex(x + 1, j + 1, vertices[indices[2]]);
- callback->processTriangle(vertices, x, j);
+ callback->processTriangle(vertices, 2 * x+1, j);
}
}
}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
index 43e1d25e3d..8dea98fc6b 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
@@ -114,6 +114,11 @@ protected:
int m_vboundsGridLength;
int m_vboundsChunkSize;
+ int m_userIndex2;
+ btScalar m_userValue3;
+
+ struct btTriangleInfoMap* m_triangleInfoMap;
+
virtual btScalar getRawHeightFieldValue(int x, int y) const;
void quantizeWithClamp(int* out, const btVector3& point, int isMax) const;
@@ -185,6 +190,40 @@ public:
}
//debugging
virtual const char* getName() const { return "HEIGHTFIELD"; }
+
+
+ void setUserIndex2(int index)
+ {
+ m_userIndex2 = index;
+ }
+ int getUserIndex2() const
+ {
+ return m_userIndex2;
+ }
+ void setUserValue3(btScalar value)
+ {
+ m_userValue3 = value;
+ }
+ btScalar getUserValue3() const
+ {
+ return m_userValue3;
+ }
+ const struct btTriangleInfoMap* getTriangleInfoMap() const
+ {
+ return m_triangleInfoMap;
+ }
+ struct btTriangleInfoMap* getTriangleInfoMap()
+ {
+ return m_triangleInfoMap;
+ }
+ void setTriangleInfoMap(btTriangleInfoMap* map)
+ {
+ m_triangleInfoMap = map;
+ }
+ const unsigned char* getHeightfieldRawData() const
+ {
+ return m_heightfieldDataUnsignedChar;
+ }
};
#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H \ No newline at end of file
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
index 7d729ee0d7..68a41dfb45 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
@@ -58,7 +58,7 @@ public:
virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
- /// getNumSubParts returns the number of seperate subparts
+ /// getNumSubParts returns the number of separate subparts
/// each subpart has a continuous array of vertices and indices
virtual int getNumSubParts() const = 0;
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
index 8ebb22baae..556aa3fef4 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
@@ -100,7 +100,7 @@ public:
virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
- /// getNumSubParts returns the number of seperate subparts
+ /// getNumSubParts returns the number of separate subparts
/// each subpart has a continuous array of vertices and indices
virtual int getNumSubParts() const
{
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
index eb33ce05e2..5b85e87041 100644
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
+++ b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
@@ -1,5 +1,5 @@
/*! \file btGImpactShape.h
-\author Francisco Leon Najera
+\author Francisco Len Nßjera
*/
/*
This source file is part of GIMPACT Library.
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
index c94391d816..3c82133037 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
@@ -95,11 +95,11 @@ int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate
for (;;)
//while (true)
{
- btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
- btVector3 seperatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
+ btVector3 separatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
+ btVector3 separatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
- btVector3 pInA = a.getLocalSupportWithoutMargin(seperatingAxisInA);
- btVector3 qInB = b.getLocalSupportWithoutMargin(seperatingAxisInB);
+ btVector3 pInA = a.getLocalSupportWithoutMargin(separatingAxisInA);
+ btVector3 qInB = b.getLocalSupportWithoutMargin(separatingAxisInB);
btVector3 pWorld = localTransA(pInA);
btVector3 qWorld = localTransB(qInB);
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
index 4339b2ea75..5af93cb2fb 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
@@ -79,11 +79,11 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput &input, Result
static void btComputeSupport(const btConvexShape *convexA, const btTransform &localTransA, const btConvexShape *convexB, const btTransform &localTransB, const btVector3 &dir, bool check2d, btVector3 &supAworld, btVector3 &supBworld, btVector3 &aMinb)
{
- btVector3 seperatingAxisInA = (dir)*localTransA.getBasis();
- btVector3 seperatingAxisInB = (-dir) * localTransB.getBasis();
+ btVector3 separatingAxisInA = (dir)*localTransA.getBasis();
+ btVector3 separatingAxisInB = (-dir) * localTransB.getBasis();
- btVector3 pInANoMargin = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- btVector3 qInBNoMargin = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ btVector3 pInANoMargin = convexA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ btVector3 qInBNoMargin = convexB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
btVector3 pInA = pInANoMargin;
btVector3 qInB = qInBNoMargin;
@@ -839,11 +839,11 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &inpu
for (;;)
//while (true)
{
- btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
- btVector3 seperatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
+ btVector3 separatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
+ btVector3 separatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
btVector3 pWorld = localTransA(pInA);
btVector3 qWorld = localTransB(qInB);
@@ -1116,11 +1116,11 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &inpu
btScalar d2 = 0.f;
{
- btVector3 seperatingAxisInA = (-orgNormalInB) * localTransA.getBasis();
- btVector3 seperatingAxisInB = orgNormalInB * localTransB.getBasis();
+ btVector3 separatingAxisInA = (-orgNormalInB) * localTransA.getBasis();
+ btVector3 separatingAxisInB = orgNormalInB * localTransB.getBasis();
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
btVector3 pWorld = localTransA(pInA);
btVector3 qWorld = localTransB(qInB);
@@ -1130,11 +1130,11 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &inpu
btScalar d1 = 0;
{
- btVector3 seperatingAxisInA = (normalInB)*localTransA.getBasis();
- btVector3 seperatingAxisInB = -normalInB * localTransB.getBasis();
+ btVector3 separatingAxisInA = (normalInB)*localTransA.getBasis();
+ btVector3 separatingAxisInB = -normalInB * localTransB.getBasis();
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
btVector3 pWorld = localTransA(pInA);
btVector3 qWorld = localTransB(qInB);
@@ -1143,11 +1143,11 @@ void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &inpu
}
btScalar d0 = 0.f;
{
- btVector3 seperatingAxisInA = (-normalInB) * input.m_transformA.getBasis();
- btVector3 seperatingAxisInB = normalInB * input.m_transformB.getBasis();
+ btVector3 separatingAxisInA = (-normalInB) * input.m_transformA.getBasis();
+ btVector3 separatingAxisInB = normalInB * input.m_transformB.getBasis();
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
btVector3 pWorld = localTransA(pInA);
btVector3 qWorld = localTransB(qInB);
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
index 659b63551e..faa02287ca 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
@@ -64,9 +64,9 @@ public:
{
m_minkowskiB = minkB;
}
- void setCachedSeperatingAxis(const btVector3& seperatingAxis)
+ void setCachedSeparatingAxis(const btVector3& separatingAxis)
{
- m_cachedSeparatingAxis = seperatingAxis;
+ m_cachedSeparatingAxis = separatingAxis;
}
const btVector3& getCachedSeparatingAxis() const
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
index 6d21f66202..573fc86bf9 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
@@ -55,6 +55,7 @@ public:
: m_userPersistentData(0),
m_contactPointFlags(0),
m_appliedImpulse(0.f),
+ m_prevRHS(0.f),
m_appliedImpulseLateral1(0.f),
m_appliedImpulseLateral2(0.f),
m_contactMotion1(0.f),
@@ -79,6 +80,7 @@ public:
m_userPersistentData(0),
m_contactPointFlags(0),
m_appliedImpulse(0.f),
+ m_prevRHS(0.f),
m_appliedImpulseLateral1(0.f),
m_appliedImpulseLateral2(0.f),
m_contactMotion1(0.f),
@@ -114,6 +116,7 @@ public:
int m_contactPointFlags;
btScalar m_appliedImpulse;
+ btScalar m_prevRHS;
btScalar m_appliedImpulseLateral1;
btScalar m_appliedImpulseLateral2;
btScalar m_contactMotion1;
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
index a77449812f..c042c24208 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
@@ -65,7 +65,7 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
btScalar minProj = btScalar(BT_LARGE_FLOAT);
btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.));
btVector3 minA, minB;
- btVector3 seperatingAxisInA, seperatingAxisInB;
+ btVector3 separatingAxisInA, separatingAxisInB;
btVector3 pInA, qInB, pWorld, qWorld, w;
#ifndef __SPU__
@@ -75,8 +75,8 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
- btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
- btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+ btVector3 separatingAxisInABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+ btVector3 separatingAxisInBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
int i;
int numSampleDirections = NUM_UNITSPHERE_POINTS;
@@ -84,8 +84,8 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
for (i = 0; i < numSampleDirections; i++)
{
btVector3 norm = getPenetrationDirections()[i];
- seperatingAxisInABatch[i] = (-norm) * transA.getBasis();
- seperatingAxisInBBatch[i] = norm * transB.getBasis();
+ separatingAxisInABatch[i] = (-norm) * transA.getBasis();
+ separatingAxisInBBatch[i] = norm * transB.getBasis();
}
{
@@ -98,8 +98,8 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
convexA->getPreferredPenetrationDirection(i, norm);
norm = transA.getBasis() * norm;
getPenetrationDirections()[numSampleDirections] = norm;
- seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
- seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+ separatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+ separatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
numSampleDirections++;
}
}
@@ -115,15 +115,15 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
convexB->getPreferredPenetrationDirection(i, norm);
norm = transB.getBasis() * norm;
getPenetrationDirections()[numSampleDirections] = norm;
- seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
- seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+ separatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+ separatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
numSampleDirections++;
}
}
}
- convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch, supportVerticesABatch, numSampleDirections);
- convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch, supportVerticesBBatch, numSampleDirections);
+ convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(separatingAxisInABatch, supportVerticesABatch, numSampleDirections);
+ convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(separatingAxisInBBatch, supportVerticesBBatch, numSampleDirections);
for (i = 0; i < numSampleDirections; i++)
{
@@ -134,8 +134,8 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
}
if (norm.length2() > 0.01)
{
- seperatingAxisInA = seperatingAxisInABatch[i];
- seperatingAxisInB = seperatingAxisInBBatch[i];
+ separatingAxisInA = separatingAxisInABatch[i];
+ separatingAxisInB = separatingAxisInBBatch[i];
pInA = supportVerticesABatch[i];
qInB = supportVerticesBBatch[i];
@@ -199,10 +199,10 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
for (int i = 0; i < numSampleDirections; i++)
{
const btVector3& norm = getPenetrationDirections()[i];
- seperatingAxisInA = (-norm) * transA.getBasis();
- seperatingAxisInB = norm * transB.getBasis();
- pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
- qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+ separatingAxisInA = (-norm) * transA.getBasis();
+ separatingAxisInB = norm * transB.getBasis();
+ pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+ qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
pWorld = transA(pInA);
qWorld = transB(qInB);
w = qWorld - pWorld;
@@ -259,7 +259,7 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT); //minProj;
btIntermediateResult res;
- gjkdet.setCachedSeperatingAxis(-minNorm);
+ gjkdet.setCachedSeparatingAxis(-minNorm);
gjkdet.getClosestPoints(input, res, debugDraw);
btScalar correctedMinNorm = minProj - res.m_depth;
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
index 358bc95d81..534a66d3fa 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
@@ -309,11 +309,11 @@ inline void btMprSupport(const btConvexTemplate &a, const btConvexTemplate &b,
const btMprCollisionDescription &colDesc,
const btVector3 &dir, btMprSupport_t *supp)
{
- btVector3 seperatingAxisInA = dir * a.getWorldTransform().getBasis();
- btVector3 seperatingAxisInB = -dir * b.getWorldTransform().getBasis();
+ btVector3 separatingAxisInA = dir * a.getWorldTransform().getBasis();
+ btVector3 separatingAxisInB = -dir * b.getWorldTransform().getBasis();
- btVector3 pInA = a.getLocalSupportWithMargin(seperatingAxisInA);
- btVector3 qInB = b.getLocalSupportWithMargin(seperatingAxisInB);
+ btVector3 pInA = a.getLocalSupportWithMargin(separatingAxisInA);
+ btVector3 qInB = b.getLocalSupportWithMargin(separatingAxisInB);
supp->v1 = a.getWorldTransform()(pInA);
supp->v2 = b.getWorldTransform()(qInB);
@@ -467,7 +467,7 @@ static int btRefinePortal(const btConvexTemplate &a, const btConvexTemplate &b,
for (int i = 0; i < BT_MPR_MAX_ITERATIONS; i++)
//while (1)
{
- // compute direction outside the portal (from v0 throught v1,v2,v3
+ // compute direction outside the portal (from v0 through v1,v2,v3
// face)
btPortalDir(portal, &dir);
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
index f1422cad4d..dca3e09267 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
@@ -325,6 +325,7 @@ const char* btPersistentManifold::serialize(const class btPersistentManifold* ma
{
const btManifoldPoint& pt = manifold->getContactPoint(i);
dataOut->m_pointCacheAppliedImpulse[i] = pt.m_appliedImpulse;
+ dataOut->m_pointCachePrevRHS[i] = pt.m_prevRHS;
dataOut->m_pointCacheAppliedImpulseLateral1[i] = pt.m_appliedImpulseLateral1;
dataOut->m_pointCacheAppliedImpulseLateral2[i] = pt.m_appliedImpulseLateral2;
pt.m_localPointA.serialize(dataOut->m_pointCacheLocalPointA[i]);
@@ -371,6 +372,7 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldDoubleDa
btManifoldPoint& pt = m_pointCache[i];
pt.m_appliedImpulse = manifoldDataPtr->m_pointCacheAppliedImpulse[i];
+ pt.m_prevRHS = manifoldDataPtr->m_pointCachePrevRHS[i];
pt.m_appliedImpulseLateral1 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral1[i];
pt.m_appliedImpulseLateral2 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral2[i];
pt.m_localPointA.deSerializeDouble(manifoldDataPtr->m_pointCacheLocalPointA[i]);
@@ -416,6 +418,7 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldFloatDat
btManifoldPoint& pt = m_pointCache[i];
pt.m_appliedImpulse = manifoldDataPtr->m_pointCacheAppliedImpulse[i];
+ pt.m_prevRHS = manifoldDataPtr->m_pointCachePrevRHS[i];
pt.m_appliedImpulseLateral1 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral1[i];
pt.m_appliedImpulseLateral2 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral2[i];
pt.m_localPointA.deSerialize(manifoldDataPtr->m_pointCacheLocalPointA[i]);
@@ -444,4 +447,4 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldFloatDat
pt.m_contactMotion1 = manifoldDataPtr->m_pointCacheContactMotion1[i];
pt.m_contactMotion2 = manifoldDataPtr->m_pointCacheContactMotion2[i];
}
-} \ No newline at end of file
+}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
index 8a9134c95c..0e26da0ebe 100644
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
+++ b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
@@ -173,6 +173,7 @@ public:
//get rid of duplicated userPersistentData pointer
m_pointCache[lastUsedIndex].m_userPersistentData = 0;
m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
+ m_pointCache[lastUsedIndex].m_prevRHS = 0.f;
m_pointCache[lastUsedIndex].m_contactPointFlags = 0;
m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f;
m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f;
@@ -195,6 +196,7 @@ public:
#ifdef MAINTAIN_PERSISTENCY
int lifeTime = m_pointCache[insertIndex].getLifeTime();
btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
+ btScalar prevRHS = m_pointCache[insertIndex].m_prevRHS;
btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
@@ -223,6 +225,7 @@ public:
m_pointCache[insertIndex] = newPoint;
m_pointCache[insertIndex].m_userPersistentData = cache;
m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
+ m_pointCache[insertIndex].m_prevRHS = prevRHS;
m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
}
@@ -276,7 +279,8 @@ struct btPersistentManifoldDoubleData
btVector3DoubleData m_pointCacheLateralFrictionDir2[4];
double m_pointCacheDistance[4];
double m_pointCacheAppliedImpulse[4];
- double m_pointCacheCombinedFriction[4];
+ double m_pointCachePrevRHS[4];
+ double m_pointCacheCombinedFriction[4];
double m_pointCacheCombinedRollingFriction[4];
double m_pointCacheCombinedSpinningFriction[4];
double m_pointCacheCombinedRestitution[4];
@@ -322,6 +326,7 @@ struct btPersistentManifoldFloatData
btVector3FloatData m_pointCacheLateralFrictionDir2[4];
float m_pointCacheDistance[4];
float m_pointCacheAppliedImpulse[4];
+ float m_pointCachePrevRHS[4];
float m_pointCacheCombinedFriction[4];
float m_pointCacheCombinedRollingFriction[4];
float m_pointCacheCombinedSpinningFriction[4];
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
index 2a5efc6495..27f76b8425 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
@@ -890,6 +890,8 @@ static void setupSpatialGridBatchesMt(
btVector3 gridExtent = bboxMax - bboxMin;
+ gridExtent.setMax(btVector3(btScalar(1), btScalar(1), btScalar(1)));
+
btVector3 gridCellSize = consExtent;
int gridDim[3];
gridDim[0] = int(1.0 + gridExtent.x() / gridCellSize.x());
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
index 63d7c98e16..4356c12abf 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
@@ -30,7 +30,8 @@ enum btSolverMode
SOLVER_SIMD = 256,
SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512,
SOLVER_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024,
- SOLVER_DISABLE_IMPLICIT_CONE_FRICTION = 2048
+ SOLVER_DISABLE_IMPLICIT_CONE_FRICTION = 2048,
+ SOLVER_USE_ARTICULATED_WARMSTARTING = 4096,
};
struct btContactSolverInfoData
@@ -45,6 +46,7 @@ struct btContactSolverInfoData
btScalar m_sor; //successive over-relaxation term
btScalar m_erp; //error reduction for non-contact constraints
btScalar m_erp2; //error reduction for contact constraints
+ btScalar m_deformable_erp; //error reduction for deformable constraints
btScalar m_globalCfm; //constraint force mixing for contacts and non-contacts
btScalar m_frictionERP; //error reduction for friction constraints
btScalar m_frictionCFM; //constraint force mixing for friction constraints
@@ -54,7 +56,7 @@ struct btContactSolverInfoData
btScalar m_splitImpulseTurnErp;
btScalar m_linearSlop;
btScalar m_warmstartingFactor;
-
+ btScalar m_articulatedWarmstartingFactor;
int m_solverMode;
int m_restingContactRestitutionThreshold;
int m_minimumSolverBatchSize;
@@ -65,6 +67,7 @@ struct btContactSolverInfoData
bool m_jointFeedbackInWorldSpace;
bool m_jointFeedbackInJointFrame;
int m_reportSolverAnalytics;
+ int m_numNonContactInnerIterations;
};
struct btContactSolverInfo : public btContactSolverInfoData
@@ -80,6 +83,7 @@ struct btContactSolverInfo : public btContactSolverInfoData
m_numIterations = 10;
m_erp = btScalar(0.2);
m_erp2 = btScalar(0.2);
+ m_deformable_erp = btScalar(0.1);
m_globalCfm = btScalar(0.);
m_frictionERP = btScalar(0.2); //positional friction 'anchors' are disabled by default
m_frictionCFM = btScalar(0.);
@@ -89,6 +93,7 @@ struct btContactSolverInfo : public btContactSolverInfoData
m_splitImpulseTurnErp = 0.1f;
m_linearSlop = btScalar(0.0);
m_warmstartingFactor = btScalar(0.85);
+ m_articulatedWarmstartingFactor = btScalar(0.85);
//m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD | SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | SOLVER_RANDMIZE_ORDER;
m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD; // | SOLVER_RANDMIZE_ORDER;
m_restingContactRestitutionThreshold = 2; //unused as of 2.81
@@ -100,6 +105,7 @@ struct btContactSolverInfo : public btContactSolverInfoData
m_jointFeedbackInWorldSpace = false;
m_jointFeedbackInJointFrame = false;
m_reportSolverAnalytics = 0;
+ m_numNonContactInnerIterations = 1; // the number of inner iterations for solving motor constraint in a single iteration of the constraint solve
}
};
@@ -120,6 +126,7 @@ struct btContactSolverInfoDoubleData
double m_splitImpulseTurnErp;
double m_linearSlop;
double m_warmstartingFactor;
+ double m_articulatedWarmstartingFactor;
double m_maxGyroscopicForce; ///it is only used for 'explicit' version of gyroscopic force
double m_singleAxisRollingFrictionThreshold;
@@ -150,16 +157,17 @@ struct btContactSolverInfoFloatData
float m_linearSlop;
float m_warmstartingFactor;
+ float m_articulatedWarmstartingFactor;
float m_maxGyroscopicForce;
- float m_singleAxisRollingFrictionThreshold;
+ float m_singleAxisRollingFrictionThreshold;
int m_numIterations;
int m_solverMode;
int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
+ int m_minimumSolverBatchSize;
int m_splitImpulse;
- char m_padding[4];
+
};
#endif //BT_CONTACT_SOLVER_INFO
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
index 9a3b39e6f8..74a13c6249 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
@@ -32,7 +32,7 @@ Cons:
/*
2007-09-09
-btGeneric6DofConstraint Refactored by Francisco Leon
+btGeneric6DofConstraint Refactored by Francisco Le?n
email: projectileman@yahoo.com
http://gimpact.sf.net
*/
@@ -311,9 +311,9 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo()
case RO_XYZ:
{
//Is this the "line of nodes" calculation choosing planes YZ (B coordinate system) and xy (A coordinate system)? (http://en.wikipedia.org/wiki/Euler_angles)
- //The two planes are non-homologous, so this is a Tait-Bryan angle formalism and not a proper Euler
+ //The two planes are non-homologous, so this is a Tait Bryan angle formalism and not a proper Euler
//Extrinsic rotations are equal to the reversed order intrinsic rotations so the above xyz extrinsic rotations (axes are fixed) are the same as the zy'x" intrinsic rotations (axes are refreshed after each rotation)
- //that is why xy and YZ planes are chosen (this will describe a zy'x" intrinsic rotation) (see the figure on the left at http://en.wikipedia.org/wiki/Euler_angles under Tait-Bryan angles)
+ //that is why xy and YZ planes are chosen (this will describe a zy'x" intrinsic rotation) (see the figure on the left at http://en.wikipedia.org/wiki/Euler_angles under Tait Bryan angles)
// x' = Nperp = N.cross(axis2)
// y' = N = axis2.cross(axis0)
// z' = z
@@ -876,7 +876,10 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
// will we not request a velocity with the wrong direction ?
// and the answer is not, because in practice during the solving the current velocity is subtracted from the m_constraintError
// so the sign of the force that is really matters
- info->m_constraintError[srow] = (rotational ? -1 : 1) * (f < 0 ? -SIMD_INFINITY : SIMD_INFINITY);
+ if (m_flags & BT_6DOF_FLAGS_USE_INFINITE_ERROR)
+ info->m_constraintError[srow] = (rotational ? -1 : 1) * (f < 0 ? -SIMD_INFINITY : SIMD_INFINITY);
+ else
+ info->m_constraintError[srow] = vel + f / m * (rotational ? -1 : 1);
btScalar minf = f < fd ? f : fd;
btScalar maxf = f < fd ? fd : f;
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
index 00e24364e0..c86dc373da 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
@@ -265,6 +265,7 @@ enum bt6DofFlags2
BT_6DOF_FLAGS_ERP_STOP2 = 2,
BT_6DOF_FLAGS_CFM_MOTO2 = 4,
BT_6DOF_FLAGS_ERP_MOTO2 = 8,
+ BT_6DOF_FLAGS_USE_INFINITE_ERROR = (1<<16)
};
#define BT_6DOF_FLAGS_AXIS_SHIFT2 4 // bits per axis
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
index d3b71e4583..d2641c582f 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
@@ -14,7 +14,9 @@ subject to the following restrictions:
*/
//#define COMPUTE_IMPULSE_DENOM 1
-//#define BT_ADDITIONAL_DEBUG
+#ifdef BT_DEBUG
+# define BT_ADDITIONAL_DEBUG
+#endif
//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
@@ -394,18 +396,6 @@ btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstr
return gResolveSingleConstraintRowLowerLimit_scalar_reference;
}
-btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarSplitPenetrationImpulseGeneric()
-{
- return gResolveSplitPenetrationImpulse_scalar_reference;
-}
-
-btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2SplitPenetrationImpulseGeneric()
-{
- return gResolveSplitPenetrationImpulse_sse2;
-}
-
-
-
#ifdef USE_SIMD
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
{
@@ -433,11 +423,6 @@ unsigned long btSequentialImpulseConstraintSolver::btRand2()
return m_btSeed2;
}
-unsigned long btSequentialImpulseConstraintSolver::btRand2a(unsigned long& seed)
-{
- seed = (1664525L * seed + 1013904223L) & 0xffffffff;
- return seed;
-}
//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
int btSequentialImpulseConstraintSolver::btRandInt2(int n)
{
@@ -471,44 +456,42 @@ int btSequentialImpulseConstraintSolver::btRandInt2(int n)
return (int)(r % un);
}
-int btSequentialImpulseConstraintSolver::btRandInt2a(int n, unsigned long& seed)
+void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
{
- // seems good; xor-fold and modulus
- const unsigned long un = static_cast<unsigned long>(n);
- unsigned long r = btSequentialImpulseConstraintSolver::btRand2a(seed);
+ btRigidBody* rb = collisionObject ? btRigidBody::upcast(collisionObject) : 0;
- // note: probably more aggressive than it needs to be -- might be
- // able to get away without one or two of the innermost branches.
- if (un <= 0x00010000UL)
+ solverBody->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+ solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+
+ if (rb)
{
- r ^= (r >> 16);
- if (un <= 0x00000100UL)
+ solverBody->m_worldTransform = rb->getWorldTransform();
+ solverBody->internalSetInvMass(btVector3(rb->getInvMass(), rb->getInvMass(), rb->getInvMass()) * rb->getLinearFactor());
+ solverBody->m_originalBody = rb;
+ solverBody->m_angularFactor = rb->getAngularFactor();
+ solverBody->m_linearFactor = rb->getLinearFactor();
+ solverBody->m_linearVelocity = rb->getLinearVelocity();
+ solverBody->m_angularVelocity = rb->getAngularVelocity();
+ solverBody->m_externalForceImpulse = rb->getTotalForce() * rb->getInvMass() * timeStep;
+ solverBody->m_externalTorqueImpulse = rb->getTotalTorque() * rb->getInvInertiaTensorWorld() * timeStep;
+ }
+ else
{
- r ^= (r >> 8);
- if (un <= 0x00000010UL)
- {
- r ^= (r >> 4);
- if (un <= 0x00000004UL)
- {
- r ^= (r >> 2);
- if (un <= 0x00000002UL)
- {
- r ^= (r >> 1);
+ solverBody->m_worldTransform.setIdentity();
+ solverBody->internalSetInvMass(btVector3(0, 0, 0));
+ solverBody->m_originalBody = 0;
+ solverBody->m_angularFactor.setValue(1, 1, 1);
+ solverBody->m_linearFactor.setValue(1, 1, 1);
+ solverBody->m_linearVelocity.setValue(0, 0, 0);
+ solverBody->m_angularVelocity.setValue(0, 0, 0);
+ solverBody->m_externalForceImpulse.setValue(0, 0, 0);
+ solverBody->m_externalTorqueImpulse.setValue(0, 0, 0);
}
}
- }
- }
- }
-
- return (int)(r % un);
-}
-void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
-{
- btSISolverSingleIterationData::initSolverBody(solverBody, collisionObject, timeStep);
-}
-
-btScalar btSequentialImpulseConstraintSolver::restitutionCurveInternal(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
+btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
{
//printf("rel_vel =%f\n", rel_vel);
if (btFabs(rel_vel) < velocityThreshold)
@@ -517,10 +500,6 @@ btScalar btSequentialImpulseConstraintSolver::restitutionCurveInternal(btScalar
btScalar rest = restitution * -rel_vel;
return rest;
}
-btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
-{
- return btSequentialImpulseConstraintSolver::restitutionCurveInternal(rel_vel, restitution, velocityThreshold);
-}
void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj, btVector3& frictionDirection, int frictionMode)
{
@@ -536,13 +515,13 @@ void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionOb
}
}
-void btSequentialImpulseConstraintSolver::setupFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
- btSolverBody& solverBodyA = tmpSolverBodyPool[solverBodyIdA];
- btSolverBody& solverBodyB = tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* body0 = tmpSolverBodyPool[solverBodyIdA].m_originalBody;
- btRigidBody* bodyA = tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+ btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+ btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -628,22 +607,6 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraintInternal(btAlig
}
}
-void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
-{
- btSequentialImpulseConstraintSolver::setupFrictionConstraintInternal(m_tmpSolverBodyPool, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
-}
-
-btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
-{
- btSolverConstraint& solverConstraint = tmpSolverContactFrictionConstraintPool.expandNonInitializing();
- solverConstraint.m_frictionIndex = frictionIndex;
- setupFrictionConstraintInternal(tmpSolverBodyPool, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-
-
-
btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
@@ -653,8 +616,7 @@ btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(c
return solverConstraint;
}
-
-void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
+void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
btScalar desiredVelocity, btScalar cfmSlip)
@@ -664,11 +626,11 @@ void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraintIntern
solverConstraint.m_contactNormal1 = normalAxis;
solverConstraint.m_contactNormal2 = -normalAxis;
- btSolverBody& solverBodyA = tmpSolverBodyPool[solverBodyIdA];
- btSolverBody& solverBodyB = tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* body0 = tmpSolverBodyPool[solverBodyIdA].m_originalBody;
- btRigidBody* bodyA = tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+ btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+ btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -717,30 +679,6 @@ void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraintIntern
}
}
-
-void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
- btScalar desiredVelocity, btScalar cfmSlip)
-
-{
- setupTorsionalFrictionConstraintInternal(m_tmpSolverBodyPool, solverConstraint, normalAxis1, solverBodyIdA, solverBodyIdB,
- cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation,
- desiredVelocity, cfmSlip);
-
-}
-
-btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactRollingFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
-{
- btSolverConstraint& solverConstraint = tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
- solverConstraint.m_frictionIndex = frictionIndex;
- setupTorsionalFrictionConstraintInternal(tmpSolverBodyPool, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-
-
btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
{
btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
@@ -750,223 +688,14 @@ btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionCon
return solverConstraint;
}
-int btSISolverSingleIterationData::getOrInitSolverBody(btCollisionObject & body, btScalar timeStep)
-{
-#if BT_THREADSAFE
- int solverBodyId = -1;
- bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
- if (isRigidBodyType && !body.isStaticOrKinematicObject())
- {
- // dynamic body
- // Dynamic bodies can only be in one island, so it's safe to write to the companionId
- solverBodyId = body.getCompanionId();
- if (solverBodyId < 0)
- {
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- body.setCompanionId(solverBodyId);
- }
- }
- else if (isRigidBodyType && body.isKinematicObject())
- {
- //
- // NOTE: must test for kinematic before static because some kinematic objects also
- // identify as "static"
- //
- // Kinematic bodies can be in multiple islands at once, so it is a
- // race condition to write to them, so we use an alternate method
- // to record the solverBodyId
- int uniqueId = body.getWorldArrayIndex();
- const int INVALID_SOLVER_BODY_ID = -1;
- if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
- {
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
- }
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
- // if no table entry yet,
- if (solverBodyId == INVALID_SOLVER_BODY_ID)
- {
- // create a table entry for this body
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
- }
- }
- else
- {
- bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK);
- // Incorrectly set collision object flags can degrade performance in various ways.
- if (!isMultiBodyType)
- {
- btAssert(body.isStaticOrKinematicObject());
- }
- //it could be a multibody link collider
- // all fixed bodies (inf mass) get mapped to a single solver id
- if (m_fixedBodyId < 0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody, 0, timeStep);
- }
- solverBodyId = m_fixedBodyId;
- }
- btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
- return solverBodyId;
-#else // BT_THREADSAFE
-
- int solverBodyIdA = -1;
-
- if (body.getCompanionId() >= 0)
- {
- //body has already been converted
- solverBodyIdA = body.getCompanionId();
- btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
- }
- else
- {
- btRigidBody* rb = btRigidBody::upcast(&body);
- //convert both active and kinematic objects (for their velocity)
- if (rb && (rb->getInvMass() || rb->isKinematicObject()))
- {
- solverBodyIdA = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- body.setCompanionId(solverBodyIdA);
- }
- else
- {
- if (m_fixedBodyId < 0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody, 0, timeStep);
- }
- return m_fixedBodyId;
- // return 0;//assume first one is a fixed solver body
- }
- }
-
- return solverBodyIdA;
-#endif // BT_THREADSAFE
-}
-void btSISolverSingleIterationData::initSolverBody(btSolverBody * solverBody, btCollisionObject * collisionObject, btScalar timeStep)
-{
- btRigidBody* rb = collisionObject ? btRigidBody::upcast(collisionObject) : 0;
-
- solverBody->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
-
- if (rb)
- {
- solverBody->m_worldTransform = rb->getWorldTransform();
- solverBody->internalSetInvMass(btVector3(rb->getInvMass(), rb->getInvMass(), rb->getInvMass()) * rb->getLinearFactor());
- solverBody->m_originalBody = rb;
- solverBody->m_angularFactor = rb->getAngularFactor();
- solverBody->m_linearFactor = rb->getLinearFactor();
- solverBody->m_linearVelocity = rb->getLinearVelocity();
- solverBody->m_angularVelocity = rb->getAngularVelocity();
- solverBody->m_externalForceImpulse = rb->getTotalForce() * rb->getInvMass() * timeStep;
- solverBody->m_externalTorqueImpulse = rb->getTotalTorque() * rb->getInvInertiaTensorWorld() * timeStep;
- }
- else
- {
- solverBody->m_worldTransform.setIdentity();
- solverBody->internalSetInvMass(btVector3(0, 0, 0));
- solverBody->m_originalBody = 0;
- solverBody->m_angularFactor.setValue(1, 1, 1);
- solverBody->m_linearFactor.setValue(1, 1, 1);
- solverBody->m_linearVelocity.setValue(0, 0, 0);
- solverBody->m_angularVelocity.setValue(0, 0, 0);
- solverBody->m_externalForceImpulse.setValue(0, 0, 0);
- solverBody->m_externalTorqueImpulse.setValue(0, 0, 0);
- }
-}
-
-int btSISolverSingleIterationData::getSolverBody(btCollisionObject& body) const
-{
-#if BT_THREADSAFE
- int solverBodyId = -1;
- bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
- if (isRigidBodyType && !body.isStaticOrKinematicObject())
- {
- // dynamic body
- // Dynamic bodies can only be in one island, so it's safe to write to the companionId
- solverBodyId = body.getCompanionId();
- btAssert(solverBodyId >= 0);
- }
- else if (isRigidBodyType && body.isKinematicObject())
- {
- //
- // NOTE: must test for kinematic before static because some kinematic objects also
- // identify as "static"
- //
- // Kinematic bodies can be in multiple islands at once, so it is a
- // race condition to write to them, so we use an alternate method
- // to record the solverBodyId
- int uniqueId = body.getWorldArrayIndex();
- const int INVALID_SOLVER_BODY_ID = -1;
- if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
- {
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
- }
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
- btAssert(solverBodyId != INVALID_SOLVER_BODY_ID);
- }
- else
- {
- bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK);
- // Incorrectly set collision object flags can degrade performance in various ways.
- if (!isMultiBodyType)
- {
- btAssert(body.isStaticOrKinematicObject());
- }
- btAssert(m_fixedBodyId >= 0);
- solverBodyId = m_fixedBodyId;
- }
- btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
- return solverBodyId;
-#else // BT_THREADSAFE
- int solverBodyIdA = -1;
-
- if (body.getCompanionId() >= 0)
- {
- //body has already been converted
- solverBodyIdA = body.getCompanionId();
- btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
- }
- else
- {
- btRigidBody* rb = btRigidBody::upcast(&body);
- //convert both active and kinematic objects (for their velocity)
- if (rb && (rb->getInvMass() || rb->isKinematicObject()))
- {
- btAssert(0);
- }
- else
- {
- if (m_fixedBodyId < 0)
- {
- btAssert(0);
- }
- return m_fixedBodyId;
- // return 0;//assume first one is a fixed solver body
- }
- }
-
- return solverBodyIdA;
-#endif // BT_THREADSAFE
-}
-
int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body, btScalar timeStep)
{
#if BT_THREADSAFE
int solverBodyId = -1;
- bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
- if (isRigidBodyType && !body.isStaticOrKinematicObject())
+ const bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
+ const bool isStaticOrKinematic = body.isStaticOrKinematicObject();
+ const bool isKinematic = body.isKinematicObject();
+ if (isRigidBodyType && !isStaticOrKinematic)
{
// dynamic body
// Dynamic bodies can only be in one island, so it's safe to write to the companionId
@@ -979,7 +708,7 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject&
body.setCompanionId(solverBodyId);
}
}
- else if (isRigidBodyType && body.isKinematicObject())
+ else if (isRigidBodyType && isKinematic)
{
//
// NOTE: must test for kinematic before static because some kinematic objects also
@@ -1064,10 +793,7 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject&
}
#include <stdio.h>
-
-
-void btSequentialImpulseConstraintSolver::setupContactConstraintInternal(btSISolverSingleIterationData& siData,
- btSolverConstraint& solverConstraint,
+void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
int solverBodyIdA, int solverBodyIdB,
btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
btScalar& relaxation,
@@ -1076,8 +802,8 @@ void btSequentialImpulseConstraintSolver::setupContactConstraintInternal(btSISol
// const btVector3& pos1 = cp.getPositionWorldOnA();
// const btVector3& pos2 = cp.getPositionWorldOnB();
- btSolverBody* bodyA = &siData.m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* bodyB = &siData.m_tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
btRigidBody* rb0 = bodyA->m_originalBody;
btRigidBody* rb1 = bodyB->m_originalBody;
@@ -1184,7 +910,7 @@ void btSequentialImpulseConstraintSolver::setupContactConstraintInternal(btSISol
solverConstraint.m_friction = cp.m_combinedFriction;
- restitution = btSequentialImpulseConstraintSolver::restitutionCurveInternal(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+ restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
if (restitution <= btScalar(0.))
{
restitution = 0.f;
@@ -1252,109 +978,39 @@ void btSequentialImpulseConstraintSolver::setupContactConstraintInternal(btSISol
}
}
-void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- const btVector3& rel_pos1, const btVector3& rel_pos2)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations
- );
-
-
- setupContactConstraintInternal(siData, solverConstraint,
- solverBodyIdA, solverBodyIdB,
- cp, infoGlobal,
- relaxation,
- rel_pos1, rel_pos2);
-}
-
-
-void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulseInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool,
- btSolverConstraint& solverConstraint,
+void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint,
int solverBodyIdA, int solverBodyIdB,
btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
{
- btSolverBody* bodyA = &tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* bodyB = &tmpSolverBodyPool[solverBodyIdB];
-
- btRigidBody* rb0 = bodyA->m_originalBody;
- btRigidBody* rb1 = bodyB->m_originalBody;
-
{
- btSolverConstraint& frictionConstraint1 = tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1 * rb0->getInvMass(), frictionConstraint1.m_angularComponentA, frictionConstraint1.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2 * rb1->getInvMass(), -frictionConstraint1.m_angularComponentB, -(btScalar)frictionConstraint1.m_appliedImpulse);
- }
- else
- {
- frictionConstraint1.m_appliedImpulse = 0.f;
- }
+ btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
+
+ frictionConstraint1.m_appliedImpulse = 0.f;
}
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- btSolverConstraint& frictionConstraint2 = tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal1 * rb0->getInvMass(), frictionConstraint2.m_angularComponentA, frictionConstraint2.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(-frictionConstraint2.m_contactNormal2 * rb1->getInvMass(), -frictionConstraint2.m_angularComponentB, -(btScalar)frictionConstraint2.m_appliedImpulse);
- }
- else
- {
- frictionConstraint2.m_appliedImpulse = 0.f;
- }
+ btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
+
+ frictionConstraint2.m_appliedImpulse = 0.f;
}
}
-void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
-{
- setFrictionConstraintImpulseInternal(m_tmpSolverBodyPool, m_tmpSolverContactFrictionConstraintPool,
- solverConstraint,
- solverBodyIdA, solverBodyIdB,
- cp, infoGlobal);
-
-}
-void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingleIterationData& siData, btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
{
btCollisionObject *colObj0 = 0, *colObj1 = 0;
colObj0 = (btCollisionObject*)manifold->getBody0();
colObj1 = (btCollisionObject*)manifold->getBody1();
- int solverBodyIdA = siData.getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
- int solverBodyIdB = siData.getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
+ int solverBodyIdA = getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+ int solverBodyIdB = getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
// btRigidBody* bodyA = btRigidBody::upcast(colObj0);
// btRigidBody* bodyB = btRigidBody::upcast(colObj1);
- btSolverBody* solverBodyA = &siData.m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* solverBodyB = &siData.m_tmpSolverBodyPool[solverBodyIdB];
+ btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
///avoid collision response between two static objects
if (!solverBodyA || (solverBodyA->m_invMass.fuzzyZero() && (!solverBodyB || solverBodyB->m_invMass.fuzzyZero())))
@@ -1371,8 +1027,8 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
btVector3 rel_pos2;
btScalar relaxation;
- int frictionIndex = siData.m_tmpSolverContactConstraintPool.size();
- btSolverConstraint& solverConstraint = siData.m_tmpSolverContactConstraintPool.expandNonInitializing();
+ int frictionIndex = m_tmpSolverContactConstraintPool.size();
+ btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@@ -1393,20 +1049,16 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
btVector3 vel = vel1 - vel2;
btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
- setupContactConstraintInternal(siData, solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
+ setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
/////setup the friction constraints
- solverConstraint.m_frictionIndex = siData.m_tmpSolverContactFrictionConstraintPool.size();
+ solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0))
{
{
-
- btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(siData.m_tmpSolverBodyPool,
- siData.m_tmpSolverContactRollingFrictionConstraintPool,
- cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, cp.m_combinedSpinningFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
-
+ addTorsionalFrictionConstraint(cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, cp.m_combinedSpinningFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
btVector3 axis0, axis1;
btPlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
axis0.normalize();
@@ -1417,19 +1069,13 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
applyAnisotropicFriction(colObj0, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
applyAnisotropicFriction(colObj1, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
if (axis0.length() > 0.001)
- {
- btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(siData.m_tmpSolverBodyPool,
- siData.m_tmpSolverContactRollingFrictionConstraintPool, axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
+ addTorsionalFrictionConstraint(axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- }
if (axis1.length() > 0.001)
- {
- btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraintInternal(siData.m_tmpSolverBodyPool,
- siData.m_tmpSolverContactRollingFrictionConstraintPool, axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
+ addTorsionalFrictionConstraint(axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
}
}
- }
///Bullet has several options to set the friction directions
///By default, each contact has only a single friction direction that is recomputed automatically very frame
@@ -1456,8 +1102,7 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+ addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
@@ -1465,8 +1110,7 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
cp.m_lateralFrictionDir2.normalize(); //??
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+ addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
}
}
else
@@ -1475,15 +1119,13 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+ addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+ addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
}
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
@@ -1494,43 +1136,15 @@ void btSequentialImpulseConstraintSolver::convertContactInternal(btSISolverSingl
}
else
{
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
+ addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- btSequentialImpulseConstraintSolver::addFrictionConstraintInternal(siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
+ addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
}
+ setFrictionConstraintImpulse(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
}
- btSequentialImpulseConstraintSolver::setFrictionConstraintImpulseInternal(
- siData.m_tmpSolverBodyPool, siData.m_tmpSolverContactFrictionConstraintPool,
- solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
}
}
-}
-
-void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- btSequentialImpulseConstraintSolver::convertContactInternal(siData, manifold, infoGlobal);
-}
void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
{
@@ -1545,9 +1159,7 @@ void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold**
}
}
-void btSequentialImpulseConstraintSolver::convertJointInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool,
- int& maxOverrideNumSolverIterations,
- btSolverConstraint* currentConstraintRow,
+void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow,
btTypedConstraint* constraint,
const btTypedConstraint::btConstraintInfo1& info1,
int solverBodyIdA,
@@ -1557,12 +1169,12 @@ void btSequentialImpulseConstraintSolver::convertJointInternal(btAlignedObjectAr
const btRigidBody& rbA = constraint->getRigidBodyA();
const btRigidBody& rbB = constraint->getRigidBodyB();
- const btSolverBody* bodyAPtr = &tmpSolverBodyPool[solverBodyIdA];
- const btSolverBody* bodyBPtr = &tmpSolverBodyPool[solverBodyIdB];
+ const btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+ const btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
- if (overrideNumSolverIterations > maxOverrideNumSolverIterations)
- maxOverrideNumSolverIterations = overrideNumSolverIterations;
+ if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
+ m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
for (int j = 0; j < info1.m_numConstraintRows; j++)
{
@@ -1679,16 +1291,7 @@ void btSequentialImpulseConstraintSolver::convertJointInternal(btAlignedObjectAr
}
}
-void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow,
- btTypedConstraint* constraint,
- const btTypedConstraint::btConstraintInfo1& info1,
- int solverBodyIdA,
- int solverBodyIdB,
- const btContactSolverInfo& infoGlobal)
-{
-}
-
-void btSequentialImpulseConstraintSolver::convertJointsInternal(btSISolverSingleIterationData& siData, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("convertJoints");
for (int j = 0; j < numConstraints; j++)
@@ -1700,11 +1303,11 @@ void btSequentialImpulseConstraintSolver::convertJointsInternal(btSISolverSingle
int totalNumRows = 0;
- siData.m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
+ m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
//calculate the total number of contraint rows
for (int i = 0; i < numConstraints; i++)
{
- btTypedConstraint::btConstraintInfo1& info1 = siData.m_tmpConstraintSizesPool[i];
+ btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
btJointFeedback* fb = constraints[i]->getJointFeedback();
if (fb)
{
@@ -1725,58 +1328,34 @@ void btSequentialImpulseConstraintSolver::convertJointsInternal(btSISolverSingle
}
totalNumRows += info1.m_numConstraintRows;
}
- siData.m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
///setup the btSolverConstraints
int currentRow = 0;
for (int i = 0; i < numConstraints; i++)
{
- const btTypedConstraint::btConstraintInfo1& info1 = siData.m_tmpConstraintSizesPool[i];
+ const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
if (info1.m_numConstraintRows)
{
btAssert(currentRow < totalNumRows);
- btSolverConstraint* currentConstraintRow = &siData.m_tmpSolverNonContactConstraintPool[currentRow];
+ btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
btTypedConstraint* constraint = constraints[i];
btRigidBody& rbA = constraint->getRigidBodyA();
btRigidBody& rbB = constraint->getRigidBodyB();
- int solverBodyIdA = siData.getOrInitSolverBody(rbA, infoGlobal.m_timeStep);
- int solverBodyIdB = siData.getOrInitSolverBody(rbB, infoGlobal.m_timeStep);
+ int solverBodyIdA = getOrInitSolverBody(rbA, infoGlobal.m_timeStep);
+ int solverBodyIdB = getOrInitSolverBody(rbB, infoGlobal.m_timeStep);
- convertJointInternal(siData.m_tmpSolverBodyPool, siData.m_maxOverrideNumSolverIterations,
- currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
+ convertJoint(currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
}
currentRow += info1.m_numConstraintRows;
}
}
-void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- convertJointsInternal(siData, constraints, numConstraints, infoGlobal);
-}
-
-
-void btSequentialImpulseConstraintSolver::convertBodiesInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("convertBodies");
for (int i = 0; i < numBodies; i++)
@@ -1784,23 +1363,23 @@ void btSequentialImpulseConstraintSolver::convertBodiesInternal(btSISolverSingle
bodies[i]->setCompanionId(-1);
}
#if BT_THREADSAFE
- siData.m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
+ m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
#endif // BT_THREADSAFE
- siData.m_tmpSolverBodyPool.reserve(numBodies + 1);
- siData.m_tmpSolverBodyPool.resize(0);
+ m_tmpSolverBodyPool.reserve(numBodies + 1);
+ m_tmpSolverBodyPool.resize(0);
//btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
//initSolverBody(&fixedBody,0);
for (int i = 0; i < numBodies; i++)
{
- int bodyId = siData.getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
+ int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
btRigidBody* body = btRigidBody::upcast(bodies[i]);
if (body && body->getInvMass())
{
- btSolverBody& solverBody = siData.m_tmpSolverBodyPool[bodyId];
+ btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
btVector3 gyroForce(0, 0, 0);
if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
{
@@ -1821,29 +1400,6 @@ void btSequentialImpulseConstraintSolver::convertBodiesInternal(btSISolverSingle
}
}
-
-void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- convertBodiesInternal(siData, bodies, numBodies, infoGlobal);
-}
-
btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
m_fixedBodyId = -1;
@@ -1967,14 +1523,14 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
return 0.f;
}
-btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSISolverSingleIterationData& siData, int iteration, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
+btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
{
BT_PROFILE("solveSingleIteration");
btScalar leastSquaresResidual = 0.f;
- int numNonContactPool = siData.m_tmpSolverNonContactConstraintPool.size();
- int numConstraintPool = siData.m_tmpSolverContactConstraintPool.size();
- int numFrictionPool = siData.m_tmpSolverContactFrictionConstraintPool.size();
+ int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+ int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+ int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
{
@@ -1982,10 +1538,10 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
{
for (int j = 0; j < numNonContactPool; ++j)
{
- int tmp = siData.m_orderNonContactConstraintPool[j];
- int swapi = btRandInt2a(j + 1, siData.m_seed);
- siData.m_orderNonContactConstraintPool[j] = siData.m_orderNonContactConstraintPool[swapi];
- siData.m_orderNonContactConstraintPool[swapi] = tmp;
+ int tmp = m_orderNonContactConstraintPool[j];
+ int swapi = btRandInt2(j + 1);
+ m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
+ m_orderNonContactConstraintPool[swapi] = tmp;
}
//contact/friction constraints are not solved more than
@@ -1993,30 +1549,30 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
{
for (int j = 0; j < numConstraintPool; ++j)
{
- int tmp = siData.m_orderTmpConstraintPool[j];
- int swapi = btRandInt2a(j + 1, siData.m_seed);
- siData.m_orderTmpConstraintPool[j] = siData.m_orderTmpConstraintPool[swapi];
- siData.m_orderTmpConstraintPool[swapi] = tmp;
+ int tmp = m_orderTmpConstraintPool[j];
+ int swapi = btRandInt2(j + 1);
+ m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
+ m_orderTmpConstraintPool[swapi] = tmp;
}
for (int j = 0; j < numFrictionPool; ++j)
{
- int tmp = siData.m_orderFrictionConstraintPool[j];
- int swapi = btRandInt2a(j + 1, siData.m_seed);
- siData.m_orderFrictionConstraintPool[j] = siData.m_orderFrictionConstraintPool[swapi];
- siData.m_orderFrictionConstraintPool[swapi] = tmp;
+ int tmp = m_orderFrictionConstraintPool[j];
+ int swapi = btRandInt2(j + 1);
+ m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
+ m_orderFrictionConstraintPool[swapi] = tmp;
}
}
}
}
///solve all joint constraints
- for (int j = 0; j < siData.m_tmpSolverNonContactConstraintPool.size(); j++)
+ for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
{
- btSolverConstraint& constraint = siData.m_tmpSolverNonContactConstraintPool[siData.m_orderNonContactConstraintPool[j]];
+ btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
if (iteration < constraint.m_overrideNumSolverIterations)
{
- btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[constraint.m_solverBodyIdA], siData.m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -2027,10 +1583,10 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
{
if (constraints[j]->isEnabled())
{
- int bodyAid = siData.getSolverBody(constraints[j]->getRigidBodyA());
- int bodyBid = siData.getSolverBody(constraints[j]->getRigidBodyB());
- btSolverBody& bodyA = siData.m_tmpSolverBodyPool[bodyAid];
- btSolverBody& bodyB = siData.m_tmpSolverBodyPool[bodyBid];
+ int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
+ int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
+ btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
}
}
@@ -2038,7 +1594,7 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
///solve all contact constraints
if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
{
- int numPoolConstraints = siData.m_tmpSolverContactConstraintPool.size();
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
for (int c = 0; c < numPoolConstraints; c++)
@@ -2046,8 +1602,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
btScalar totalImpulse = 0;
{
- const btSolverConstraint& solveManifold = siData.m_tmpSolverContactConstraintPool[siData.m_orderTmpConstraintPool[c]];
- btScalar residual = siData.m_resolveSingleConstraintRowLowerLimit(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
+ btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
totalImpulse = solveManifold.m_appliedImpulse;
@@ -2056,28 +1612,28 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
if (applyFriction)
{
{
- btSolverConstraint& solveManifold = siData.m_tmpSolverContactFrictionConstraintPool[siData.m_orderFrictionConstraintPool[c * multiplier]];
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
if (totalImpulse > btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
{
- btSolverConstraint& solveManifold = siData.m_tmpSolverContactFrictionConstraintPool[siData.m_orderFrictionConstraintPool[c * multiplier + 1]];
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
if (totalImpulse > btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -2087,40 +1643,40 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
{
//solve the friction constraints after all contact constraints, don't interleave them
- int numPoolConstraints = siData.m_tmpSolverContactConstraintPool.size();
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
for (j = 0; j < numPoolConstraints; j++)
{
- const btSolverConstraint& solveManifold = siData.m_tmpSolverContactConstraintPool[siData.m_orderTmpConstraintPool[j]];
- btScalar residual = siData.m_resolveSingleConstraintRowLowerLimit(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+ btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
///solve all friction constraints
- int numFrictionPoolConstraints = siData.m_tmpSolverContactFrictionConstraintPool.size();
+ int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
for (j = 0; j < numFrictionPoolConstraints; j++)
{
- btSolverConstraint& solveManifold = siData.m_tmpSolverContactFrictionConstraintPool[siData.m_orderFrictionConstraintPool[j]];
- btScalar totalImpulse = siData.m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
if (totalImpulse > btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
}
- int numRollingFrictionPoolConstraints = siData.m_tmpSolverContactRollingFrictionConstraintPool.size();
+ int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
{
- btSolverConstraint& rollingFrictionConstraint = siData.m_tmpSolverContactRollingFrictionConstraintPool[j];
- btScalar totalImpulse = siData.m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
if (totalImpulse > btScalar(0))
{
btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
@@ -2130,7 +1686,7 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
- btScalar residual = siData.m_resolveSingleConstraintRowGeneric(siData.m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], siData.m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+ btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -2138,56 +1694,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIterationInternal(btSIS
return leastSquaresResidual;
}
-
-btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- btScalar leastSquaresResidual = btSequentialImpulseConstraintSolver::solveSingleIterationInternal(siData,
- iteration, constraints, numConstraints, infoGlobal);
- return leastSquaresResidual;
-}
-
void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- solveGroupCacheFriendlySplitImpulseIterationsInternal(siData,
- bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
-}
-void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterationsInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
int iteration;
if (infoGlobal.m_splitImpulse)
@@ -2197,13 +1705,13 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
{
btScalar leastSquaresResidual = 0.f;
{
- int numPoolConstraints = siData.m_tmpSolverContactConstraintPool.size();
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
for (j = 0; j < numPoolConstraints; j++)
{
- const btSolverConstraint& solveManifold = siData.m_tmpSolverContactConstraintPool[siData.m_orderTmpConstraintPool[j]];
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- btScalar residual = siData.m_resolveSplitPenetrationImpulse(siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], siData.m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
}
}
@@ -2254,42 +1762,31 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
return 0.f;
}
-void btSequentialImpulseConstraintSolver::writeBackContactsInternal(btConstraintArray& tmpSolverContactConstraintPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
for (int j = iBegin; j < iEnd; j++)
{
- const btSolverConstraint& solveManifold = tmpSolverContactConstraintPool[j];
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
btManifoldPoint* pt = (btManifoldPoint*)solveManifold.m_originalContactPoint;
btAssert(pt);
pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
// float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
// printf("pt->m_appliedImpulseLateral1 = %f\n", f);
- pt->m_appliedImpulseLateral1 = tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
//printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- pt->m_appliedImpulseLateral2 = tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
+ pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
}
//do a callback here?
}
}
-void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
- writeBackContactsInternal(m_tmpSolverContactConstraintPool, m_tmpSolverContactFrictionConstraintPool, iBegin, iEnd, infoGlobal);
-
-}
-
void btSequentialImpulseConstraintSolver::writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
- writeBackJointsInternal(m_tmpSolverNonContactConstraintPool, iBegin, iEnd, infoGlobal);
-}
-
-void btSequentialImpulseConstraintSolver::writeBackJointsInternal(btConstraintArray& tmpSolverNonContactConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
for (int j = iBegin; j < iEnd; j++)
{
- const btSolverConstraint& solverConstr = tmpSolverNonContactConstraintPool[j];
+ const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
btJointFeedback* fb = constr->getJointFeedback();
if (fb)
@@ -2310,79 +1807,53 @@ void btSequentialImpulseConstraintSolver::writeBackJointsInternal(btConstraintAr
void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
{
- writeBackBodiesInternal(m_tmpSolverBodyPool, iBegin, iEnd, infoGlobal);
-}
-void btSequentialImpulseConstraintSolver::writeBackBodiesInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
for (int i = iBegin; i < iEnd; i++)
{
- btRigidBody* body = tmpSolverBodyPool[i].m_originalBody;
+ btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
if (body)
{
if (infoGlobal.m_splitImpulse)
- tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
+ m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
else
- tmpSolverBodyPool[i].writebackVelocity();
+ m_tmpSolverBodyPool[i].writebackVelocity();
- tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
- tmpSolverBodyPool[i].m_linearVelocity +
- tmpSolverBodyPool[i].m_externalForceImpulse);
+ m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
+ m_tmpSolverBodyPool[i].m_linearVelocity +
+ m_tmpSolverBodyPool[i].m_externalForceImpulse);
- tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
- tmpSolverBodyPool[i].m_angularVelocity +
- tmpSolverBodyPool[i].m_externalTorqueImpulse);
+ m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
+ m_tmpSolverBodyPool[i].m_angularVelocity +
+ m_tmpSolverBodyPool[i].m_externalTorqueImpulse);
if (infoGlobal.m_splitImpulse)
- tmpSolverBodyPool[i].m_originalBody->setWorldTransform(tmpSolverBodyPool[i].m_worldTransform);
+ m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform);
- tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
+ m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
}
}
}
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinishInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
{
BT_PROFILE("solveGroupCacheFriendlyFinish");
if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
- writeBackContactsInternal(siData.m_tmpSolverContactConstraintPool, siData.m_tmpSolverContactFrictionConstraintPool, 0, siData.m_tmpSolverContactConstraintPool.size(), infoGlobal);
+ writeBackContacts(0, m_tmpSolverContactConstraintPool.size(), infoGlobal);
}
- writeBackJointsInternal(siData.m_tmpSolverNonContactConstraintPool, 0, siData.m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
- writeBackBodiesInternal(siData.m_tmpSolverBodyPool, 0, siData.m_tmpSolverBodyPool.size(), infoGlobal);
+ writeBackJoints(0, m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
+ writeBackBodies(0, m_tmpSolverBodyPool.size(), infoGlobal);
- siData.m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
- siData.m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
- siData.m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
- siData.m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
- siData.m_tmpSolverBodyPool.resizeNoInitialize(0);
+ m_tmpSolverBodyPool.resizeNoInitialize(0);
return 0.f;
}
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- btSISolverSingleIterationData siData(m_tmpSolverBodyPool,
- m_tmpSolverContactConstraintPool,
- m_tmpSolverNonContactConstraintPool,
- m_tmpSolverContactFrictionConstraintPool,
- m_tmpSolverContactRollingFrictionConstraintPool,
- m_orderTmpConstraintPool,
- m_orderNonContactConstraintPool,
- m_orderFrictionConstraintPool,
- m_tmpConstraintSizesPool,
- m_resolveSingleConstraintRowGeneric,
- m_resolveSingleConstraintRowLowerLimit,
- m_resolveSplitPenetrationImpulse,
- m_kinematicBodyUniqueIdToSolverBodyTable,
- m_btSeed2,
- m_fixedBodyId,
- m_maxOverrideNumSolverIterations);
-
- return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinishInternal(siData, bodies, numBodies, infoGlobal);
-}
-
/// btSequentialImpulseConstraintSolver Sequentially applies impulses
btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btDispatcher* /*dispatcher*/)
{
@@ -2401,4 +1872,4 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
void btSequentialImpulseConstraintSolver::reset()
{
m_btSeed2 = 0;
-} \ No newline at end of file
+}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
index 2b88e25be7..f3ef02fccc 100644
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
@@ -29,68 +29,6 @@ class btCollisionObject;
typedef btScalar (*btSingleConstraintRowSolver)(btSolverBody&, btSolverBody&, const btSolverConstraint&);
-struct btSISolverSingleIterationData
-{
- btAlignedObjectArray<btSolverBody>& m_tmpSolverBodyPool;
- btConstraintArray& m_tmpSolverContactConstraintPool;
- btConstraintArray& m_tmpSolverNonContactConstraintPool;
- btConstraintArray& m_tmpSolverContactFrictionConstraintPool;
- btConstraintArray& m_tmpSolverContactRollingFrictionConstraintPool;
-
- btAlignedObjectArray<int>& m_orderTmpConstraintPool;
- btAlignedObjectArray<int>& m_orderNonContactConstraintPool;
- btAlignedObjectArray<int>& m_orderFrictionConstraintPool;
- btAlignedObjectArray<btTypedConstraint::btConstraintInfo1>& m_tmpConstraintSizesPool;
- unsigned long& m_seed;
-
- btSingleConstraintRowSolver& m_resolveSingleConstraintRowGeneric;
- btSingleConstraintRowSolver& m_resolveSingleConstraintRowLowerLimit;
- btSingleConstraintRowSolver& m_resolveSplitPenetrationImpulse;
- btAlignedObjectArray<int>& m_kinematicBodyUniqueIdToSolverBodyTable;
- int& m_fixedBodyId;
- int& m_maxOverrideNumSolverIterations;
- int getOrInitSolverBody(btCollisionObject & body, btScalar timeStep);
- static void initSolverBody(btSolverBody * solverBody, btCollisionObject * collisionObject, btScalar timeStep);
- int getSolverBody(btCollisionObject& body) const;
-
-
- btSISolverSingleIterationData(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool,
- btConstraintArray& tmpSolverContactConstraintPool,
- btConstraintArray& tmpSolverNonContactConstraintPool,
- btConstraintArray& tmpSolverContactFrictionConstraintPool,
- btConstraintArray& tmpSolverContactRollingFrictionConstraintPool,
- btAlignedObjectArray<int>& orderTmpConstraintPool,
- btAlignedObjectArray<int>& orderNonContactConstraintPool,
- btAlignedObjectArray<int>& orderFrictionConstraintPool,
- btAlignedObjectArray<btTypedConstraint::btConstraintInfo1>& tmpConstraintSizesPool,
- btSingleConstraintRowSolver& resolveSingleConstraintRowGeneric,
- btSingleConstraintRowSolver& resolveSingleConstraintRowLowerLimit,
- btSingleConstraintRowSolver& resolveSplitPenetrationImpulse,
- btAlignedObjectArray<int>& kinematicBodyUniqueIdToSolverBodyTable,
- unsigned long& seed,
- int& fixedBodyId,
- int& maxOverrideNumSolverIterations
- )
- :m_tmpSolverBodyPool(tmpSolverBodyPool),
- m_tmpSolverContactConstraintPool(tmpSolverContactConstraintPool),
- m_tmpSolverNonContactConstraintPool(tmpSolverNonContactConstraintPool),
- m_tmpSolverContactFrictionConstraintPool(tmpSolverContactFrictionConstraintPool),
- m_tmpSolverContactRollingFrictionConstraintPool(tmpSolverContactRollingFrictionConstraintPool),
- m_orderTmpConstraintPool(orderTmpConstraintPool),
- m_orderNonContactConstraintPool(orderNonContactConstraintPool),
- m_orderFrictionConstraintPool(orderFrictionConstraintPool),
- m_tmpConstraintSizesPool(tmpConstraintSizesPool),
- m_seed(seed),
- m_resolveSingleConstraintRowGeneric(resolveSingleConstraintRowGeneric),
- m_resolveSingleConstraintRowLowerLimit(resolveSingleConstraintRowLowerLimit),
- m_resolveSplitPenetrationImpulse(resolveSplitPenetrationImpulse),
- m_kinematicBodyUniqueIdToSolverBodyTable(kinematicBodyUniqueIdToSolverBodyTable),
- m_fixedBodyId(fixedBodyId),
- m_maxOverrideNumSolverIterations(maxOverrideNumSolverIterations)
- {
- }
-};
-
struct btSolverAnalyticsData
{
btSolverAnalyticsData()
@@ -178,7 +116,6 @@ protected:
virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
void convertJoint(btSolverConstraint * currentConstraintRow, btTypedConstraint * constraint, const btTypedConstraint::btConstraintInfo1& info1, int solverBodyIdA, int solverBodyIdB, const btContactSolverInfo& infoGlobal);
-
virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
btScalar resolveSplitPenetrationSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
@@ -204,8 +141,7 @@ protected:
return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
}
-public:
-
+protected:
void writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
void writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
void writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
@@ -213,7 +149,6 @@ public:
virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
@@ -225,51 +160,12 @@ public:
virtual btScalar solveGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
- static btScalar solveSingleIterationInternal(btSISolverSingleIterationData& siData, int iteration, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
- static void convertBodiesInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal);
- static void convertJointsInternal(btSISolverSingleIterationData& siData, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
- static void convertContactInternal(btSISolverSingleIterationData& siData, btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
- static void setupContactConstraintInternal(btSISolverSingleIterationData& siData, btSolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, btScalar& relaxation,
- const btVector3& rel_pos1, const btVector3& rel_pos2);
- static btScalar restitutionCurveInternal(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold);
- static btSolverConstraint& addTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactRollingFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity = 0, btScalar cfmSlip = 0.);
- static void setupTorsionalFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
- btScalar desiredVelocity, btScalar cfmSlip);
- static void setupFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip);
- static btSolverConstraint& addFrictionConstraintInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
- static void setFrictionConstraintImpulseInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, btConstraintArray& tmpSolverContactFrictionConstraintPool,
-
- btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
- static void convertJointInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool,
- int& maxOverrideNumSolverIterations,
- btSolverConstraint* currentConstraintRow,
- btTypedConstraint* constraint,
- const btTypedConstraint::btConstraintInfo1& info1,
- int solverBodyIdA,
- int solverBodyIdB,
- const btContactSolverInfo& infoGlobal);
-
- static btScalar solveGroupCacheFriendlyFinishInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal);
-
- static void writeBackContactsInternal(btConstraintArray& tmpSolverContactConstraintPool, btConstraintArray& tmpSolverContactFrictionConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
-
- static void writeBackJointsInternal(btConstraintArray& tmpSolverNonContactConstraintPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- static void writeBackBodiesInternal(btAlignedObjectArray<btSolverBody>& tmpSolverBodyPool, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- static void solveGroupCacheFriendlySplitImpulseIterationsInternal(btSISolverSingleIterationData& siData, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
-
///clear internal cached data and reset random seed
virtual void reset();
unsigned long btRand2();
- int btRandInt2(int n);
- static unsigned long btRand2a(unsigned long& seed);
- static int btRandInt2a(int n, unsigned long& seed);
+ int btRandInt2(int n);
void setRandSeed(unsigned long seed)
{
@@ -305,18 +201,14 @@ public:
///Various implementations of solving a single constraint row using a generic equality constraint, using scalar reference, SSE2 or SSE4
- static btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric();
- static btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric();
- static btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric();
+ btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric();
+ btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric();
+ btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric();
///Various implementations of solving a single constraint row using an inequality (lower limit) constraint, using scalar reference, SSE2 or SSE4
- static btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit();
- static btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit();
- static btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit();
-
- static btSingleConstraintRowSolver getScalarSplitPenetrationImpulseGeneric();
- static btSingleConstraintRowSolver getSSE2SplitPenetrationImpulseGeneric();
-
+ btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit();
+ btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit();
+ btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit();
btSolverAnalyticsData m_analyticsData;
};
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
index dfbbdb154f..fb15ae31eb 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
@@ -800,6 +800,14 @@ public:
///don't do CCD when the collision filters are not matching
if (!ClosestConvexResultCallback::needsCollision(proxy0))
return false;
+ if (m_pairCache->getOverlapFilterCallback()) {
+ btBroadphaseProxy* proxy1 = m_me->getBroadphaseHandle();
+ bool collides = m_pairCache->needsBroadphaseCollision(proxy0, proxy1);
+ if (!collides)
+ {
+ return false;
+ }
+ }
btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
@@ -1436,9 +1444,7 @@ void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serialize
worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
- // Fill padding with zeros to appease msan.
- memset(worldInfo->m_solverInfo.m_padding, 0, sizeof(worldInfo->m_solverInfo.m_padding));
-
+
#ifdef BT_USE_DOUBLE_PRECISION
const char* structType = "btDynamicsWorldDoubleData";
#else //BT_USE_DOUBLE_PRECISION
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
index 7fe9619213..73607c61fd 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
@@ -17,7 +17,6 @@ subject to the following restrictions:
#define BT_DISCRETE_DYNAMICS_WORLD_H
#include "btDynamicsWorld.h"
-
class btDispatcher;
class btOverlappingPairCache;
class btConstraintSolver;
@@ -26,6 +25,7 @@ class btTypedConstraint;
class btActionInterface;
class btPersistentManifold;
class btIDebugDraw;
+
struct InplaceSolverIslandCallback;
#include "LinearMath/btAlignedObjectArray.h"
@@ -76,7 +76,7 @@ protected:
virtual void calculateSimulationIslands();
- virtual void solveConstraints(btContactSolverInfo & solverInfo);
+
virtual void updateActivationState(btScalar timeStep);
@@ -95,7 +95,7 @@ protected:
void serializeRigidBodies(btSerializer * serializer);
void serializeDynamicsWorldInfo(btSerializer * serializer);
-
+
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
@@ -107,6 +107,8 @@ public:
///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
+ virtual void solveConstraints(btContactSolverInfo & solverInfo);
+
virtual void synchronizeMotionStates();
///this can be useful to synchronize a single rigid body -> graphics object
@@ -227,6 +229,16 @@ public:
{
return m_latencyMotionStateInterpolation;
}
+
+ btAlignedObjectArray<btRigidBody*>& getNonStaticRigidBodies()
+ {
+ return m_nonStaticRigidBodies;
+ }
+
+ const btAlignedObjectArray<btRigidBody*>& getNonStaticRigidBodies() const
+ {
+ return m_nonStaticRigidBodies;
+ }
};
#endif //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
index eadd8c12e7..3c55234a8a 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
@@ -34,7 +34,8 @@ enum btDynamicsWorldType
BT_CONTINUOUS_DYNAMICS_WORLD = 3,
BT_SOFT_RIGID_DYNAMICS_WORLD = 4,
BT_GPU_DYNAMICS_WORLD = 5,
- BT_SOFT_MULTIBODY_DYNAMICS_WORLD = 6
+ BT_SOFT_MULTIBODY_DYNAMICS_WORLD = 6,
+ BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD = 7
};
///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
index f4bcabada2..27fdead761 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
@@ -136,8 +136,13 @@ void btRigidBody::setGravity(const btVector3& acceleration)
void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
{
- m_linearDamping = btClamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
- m_angularDamping = btClamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+#ifdef BT_USE_OLD_DAMPING_METHOD
+ m_linearDamping = btMax(lin_damping, btScalar(0.0));
+ m_angularDamping = btMax(ang_damping, btScalar(0.0));
+#else
+ m_linearDamping = btClamped(lin_damping, btScalar(0.0), btScalar(1.0));
+ m_angularDamping = btClamped(ang_damping, btScalar(0.0), btScalar(1.0));
+#endif
}
///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
@@ -146,10 +151,9 @@ void btRigidBody::applyDamping(btScalar timeStep)
//On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
//todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
-//#define USE_OLD_DAMPING_METHOD 1
-#ifdef USE_OLD_DAMPING_METHOD
- m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
- m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+#ifdef BT_USE_OLD_DAMPING_METHOD
+ m_linearVelocity *= btMax((btScalar(1.0) - timeStep * m_linearDamping), btScalar(0.0));
+ m_angularVelocity *= btMax((btScalar(1.0) - timeStep * m_angularDamping), btScalar(0.0));
#else
m_linearVelocity *= btPow(btScalar(1) - m_linearDamping, timeStep);
m_angularVelocity *= btPow(btScalar(1) - m_angularDamping, timeStep);
@@ -206,6 +210,14 @@ void btRigidBody::applyGravity()
applyCentralForce(m_gravity);
}
+void btRigidBody::clearGravity()
+{
+ if (isStaticOrKinematicObject())
+ return;
+
+ applyCentralForce(-m_gravity);
+}
+
void btRigidBody::proceedToTransform(const btTransform& newTrans)
{
setCenterOfMassTransform(newTrans);
@@ -372,6 +384,9 @@ void btRigidBody::integrateVelocities(btScalar step)
{
m_angularVelocity *= (MAX_ANGVEL / step) / angvel;
}
+ #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+ clampVelocity(m_angularVelocity);
+ #endif
}
btQuaternion btRigidBody::getOrientation() const
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
index 05f270a4b8..943d724cce 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
@@ -205,6 +205,8 @@ public:
void saveKinematicState(btScalar step);
void applyGravity();
+
+ void clearGravity();
void setGravity(const btVector3& acceleration);
@@ -259,6 +261,7 @@ public:
m_invMass = m_linearFactor * m_inverseMass;
}
btScalar getInvMass() const { return m_inverseMass; }
+ btScalar getMass() const { return m_inverseMass == btScalar(0.) ? btScalar(0.) : btScalar(1.0) / m_inverseMass; }
const btMatrix3x3& getInvInertiaTensorWorld() const
{
return m_invInertiaTensorWorld;
@@ -302,6 +305,9 @@ public:
void applyTorque(const btVector3& torque)
{
m_totalTorque += torque * m_angularFactor;
+ #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+ clampVelocity(m_totalTorque);
+ #endif
}
void applyForce(const btVector3& force, const btVector3& rel_pos)
@@ -313,11 +319,17 @@ public:
void applyCentralImpulse(const btVector3& impulse)
{
m_linearVelocity += impulse * m_linearFactor * m_inverseMass;
+ #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+ clampVelocity(m_linearVelocity);
+ #endif
}
void applyTorqueImpulse(const btVector3& torque)
{
m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+ #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+ clampVelocity(m_angularVelocity);
+ #endif
}
void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
@@ -331,6 +343,74 @@ public:
}
}
}
+
+ void applyPushImpulse(const btVector3& impulse, const btVector3& rel_pos)
+ {
+ if (m_inverseMass != btScalar(0.))
+ {
+ applyCentralPushImpulse(impulse);
+ if (m_angularFactor)
+ {
+ applyTorqueTurnImpulse(rel_pos.cross(impulse * m_linearFactor));
+ }
+ }
+ }
+
+ btVector3 getPushVelocity()
+ {
+ return m_pushVelocity;
+ }
+
+ btVector3 getTurnVelocity()
+ {
+ return m_turnVelocity;
+ }
+
+ void setPushVelocity(const btVector3& v)
+ {
+ m_pushVelocity = v;
+ }
+
+ #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+ void clampVelocity(btVector3& v) const {
+ v.setX(
+ fmax(-BT_CLAMP_VELOCITY_TO,
+ fmin(BT_CLAMP_VELOCITY_TO, v.getX()))
+ );
+ v.setY(
+ fmax(-BT_CLAMP_VELOCITY_TO,
+ fmin(BT_CLAMP_VELOCITY_TO, v.getY()))
+ );
+ v.setZ(
+ fmax(-BT_CLAMP_VELOCITY_TO,
+ fmin(BT_CLAMP_VELOCITY_TO, v.getZ()))
+ );
+ }
+ #endif
+
+ void setTurnVelocity(const btVector3& v)
+ {
+ m_turnVelocity = v;
+ #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+ clampVelocity(m_turnVelocity);
+ #endif
+ }
+
+ void applyCentralPushImpulse(const btVector3& impulse)
+ {
+ m_pushVelocity += impulse * m_linearFactor * m_inverseMass;
+ #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+ clampVelocity(m_pushVelocity);
+ #endif
+ }
+
+ void applyTorqueTurnImpulse(const btVector3& torque)
+ {
+ m_turnVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+ #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+ clampVelocity(m_turnVelocity);
+ #endif
+ }
void clearForces()
{
@@ -363,12 +443,18 @@ public:
{
m_updateRevision++;
m_linearVelocity = lin_vel;
+ #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+ clampVelocity(m_linearVelocity);
+ #endif
}
inline void setAngularVelocity(const btVector3& ang_vel)
{
m_updateRevision++;
m_angularVelocity = ang_vel;
+ #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+ clampVelocity(m_angularVelocity);
+ #endif
}
btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
index 5353fe009e..772b774202 100644
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
+++ b/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
@@ -171,6 +171,8 @@ void btSimulationIslandManagerMt::initIslandPools()
btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::getIsland(int id)
{
+ btAssert(id >= 0);
+ btAssert(id < m_lookupIslandFromId.size());
Island* island = m_lookupIslandFromId[id];
if (island == NULL)
{
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
index 3e210d7520..a1d5bb9ca8 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
@@ -100,6 +100,8 @@ btMultiBody::btMultiBody(int n_links,
m_baseName(0),
m_basePos(0, 0, 0),
m_baseQuat(0, 0, 0, 1),
+ m_basePos_interpolate(0, 0, 0),
+ m_baseQuat_interpolate(0, 0, 0, 1),
m_baseMass(mass),
m_baseInertia(inertia),
@@ -449,6 +451,16 @@ const btQuaternion &btMultiBody::getParentToLocalRot(int i) const
return m_links[i].m_cachedRotParentToThis;
}
+const btVector3 &btMultiBody::getInterpolateRVector(int i) const
+{
+ return m_links[i].m_cachedRVector_interpolate;
+}
+
+const btQuaternion &btMultiBody::getInterpolateParentToLocalRot(int i) const
+{
+ return m_links[i].m_cachedRotParentToThis_interpolate;
+}
+
btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const
{
btAssert(i >= -1);
@@ -571,52 +583,6 @@ void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
}
}
-btScalar btMultiBody::getKineticEnergy() const
-{
- int num_links = getNumLinks();
- // TODO: would be better not to allocate memory here
- btAlignedObjectArray<btVector3> omega;
- omega.resize(num_links + 1);
- btAlignedObjectArray<btVector3> vel;
- vel.resize(num_links + 1);
- compTreeLinkVelocities(&omega[0], &vel[0]);
-
- // we will do the factor of 0.5 at the end
- btScalar result = m_baseMass * vel[0].dot(vel[0]);
- result += omega[0].dot(m_baseInertia * omega[0]);
-
- for (int i = 0; i < num_links; ++i)
- {
- result += m_links[i].m_mass * vel[i + 1].dot(vel[i + 1]);
- result += omega[i + 1].dot(m_links[i].m_inertiaLocal * omega[i + 1]);
- }
-
- return 0.5f * result;
-}
-
-btVector3 btMultiBody::getAngularMomentum() const
-{
- int num_links = getNumLinks();
- // TODO: would be better not to allocate memory here
- btAlignedObjectArray<btVector3> omega;
- omega.resize(num_links + 1);
- btAlignedObjectArray<btVector3> vel;
- vel.resize(num_links + 1);
- btAlignedObjectArray<btQuaternion> rot_from_world;
- rot_from_world.resize(num_links + 1);
- compTreeLinkVelocities(&omega[0], &vel[0]);
-
- rot_from_world[0] = m_baseQuat;
- btVector3 result = quatRotate(rot_from_world[0].inverse(), (m_baseInertia * omega[0]));
-
- for (int i = 0; i < num_links; ++i)
- {
- rot_from_world[i + 1] = m_links[i].m_cachedRotParentToThis * rot_from_world[m_links[i].m_parent + 1];
- result += (quatRotate(rot_from_world[i + 1].inverse(), (m_links[i].m_inertiaLocal * omega[i + 1])));
- }
-
- return result;
-}
void btMultiBody::clearConstraintForces()
{
@@ -1581,6 +1547,158 @@ void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar
//printf("]\n");
/////////////////
}
+void btMultiBody::predictPositionsMultiDof(btScalar dt)
+{
+ int num_links = getNumLinks();
+ // step position by adding dt * velocity
+ //btVector3 v = getBaseVel();
+ //m_basePos += dt * v;
+ //
+ btScalar *pBasePos;
+ btScalar *pBaseVel = &m_realBuf[3]; //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
+
+ // reset to current position
+ for (int i = 0; i < 3; ++i)
+ {
+ m_basePos_interpolate[i] = m_basePos[i];
+ }
+ pBasePos = m_basePos_interpolate;
+
+ pBasePos[0] += dt * pBaseVel[0];
+ pBasePos[1] += dt * pBaseVel[1];
+ pBasePos[2] += dt * pBaseVel[2];
+
+ ///////////////////////////////
+ //local functor for quaternion integration (to avoid error prone redundancy)
+ struct
+ {
+ //"exponential map" based on btTransformUtil::integrateTransform(..)
+ void operator()(const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
+ {
+ //baseBody => quat is alias and omega is global coor
+ //!baseBody => quat is alibi and omega is local coor
+
+ btVector3 axis;
+ btVector3 angvel;
+
+ if (!baseBody)
+ angvel = quatRotate(quat, omega); //if quat is not m_baseQuat, it is alibi => ok
+ else
+ angvel = omega;
+
+ btScalar fAngle = angvel.length();
+ //limit the angular motion
+ if (fAngle * dt > ANGULAR_MOTION_THRESHOLD)
+ {
+ fAngle = btScalar(0.5) * SIMD_HALF_PI / dt;
+ }
+
+ if (fAngle < btScalar(0.001))
+ {
+ // use Taylor's expansions of sync function
+ axis = angvel * (btScalar(0.5) * dt - (dt * dt * dt) * (btScalar(0.020833333333)) * fAngle * fAngle);
+ }
+ else
+ {
+ // sync(fAngle) = sin(c*fAngle)/t
+ axis = angvel * (btSin(btScalar(0.5) * fAngle * dt) / fAngle);
+ }
+
+ if (!baseBody)
+ quat = btQuaternion(axis.x(), axis.y(), axis.z(), btCos(fAngle * dt * btScalar(0.5))) * quat;
+ else
+ quat = quat * btQuaternion(-axis.x(), -axis.y(), -axis.z(), btCos(fAngle * dt * btScalar(0.5)));
+ //equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();
+
+ quat.normalize();
+ }
+ } pQuatUpdateFun;
+ ///////////////////////////////
+
+ //pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
+ //
+ btScalar *pBaseQuat;
+
+ // reset to current orientation
+ for (int i = 0; i < 4; ++i)
+ {
+ m_baseQuat_interpolate[i] = m_baseQuat[i];
+ }
+ pBaseQuat = m_baseQuat_interpolate;
+
+ btScalar *pBaseOmega = &m_realBuf[0]; //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
+ //
+ btQuaternion baseQuat;
+ baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
+ btVector3 baseOmega;
+ baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
+ pQuatUpdateFun(baseOmega, baseQuat, true, dt);
+ pBaseQuat[0] = baseQuat.x();
+ pBaseQuat[1] = baseQuat.y();
+ pBaseQuat[2] = baseQuat.z();
+ pBaseQuat[3] = baseQuat.w();
+
+ // Finally we can update m_jointPos for each of the m_links
+ for (int i = 0; i < num_links; ++i)
+ {
+ btScalar *pJointPos;
+ pJointPos = &m_links[i].m_jointPos_interpolate[0];
+
+ btScalar *pJointVel = getJointVelMultiDof(i);
+
+ switch (m_links[i].m_jointType)
+ {
+ case btMultibodyLink::ePrismatic:
+ case btMultibodyLink::eRevolute:
+ {
+ //reset to current pos
+ pJointPos[0] = m_links[i].m_jointPos[0];
+ btScalar jointVel = pJointVel[0];
+ pJointPos[0] += dt * jointVel;
+ break;
+ }
+ case btMultibodyLink::eSpherical:
+ {
+ //reset to current pos
+
+ for (int j = 0; j < 4; ++j)
+ {
+ pJointPos[j] = m_links[i].m_jointPos[j];
+ }
+
+ btVector3 jointVel;
+ jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
+ btQuaternion jointOri;
+ jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
+ pQuatUpdateFun(jointVel, jointOri, false, dt);
+ pJointPos[0] = jointOri.x();
+ pJointPos[1] = jointOri.y();
+ pJointPos[2] = jointOri.z();
+ pJointPos[3] = jointOri.w();
+ break;
+ }
+ case btMultibodyLink::ePlanar:
+ {
+ for (int j = 0; j < 3; ++j)
+ {
+ pJointPos[j] = m_links[i].m_jointPos[j];
+ }
+ pJointPos[0] += dt * getJointVelMultiDof(i)[0];
+
+ btVector3 q0_coors_qd1qd2 = getJointVelMultiDof(i)[1] * m_links[i].getAxisBottom(1) + getJointVelMultiDof(i)[2] * m_links[i].getAxisBottom(2);
+ btVector3 no_q0_coors_qd1qd2 = quatRotate(btQuaternion(m_links[i].getAxisTop(0), pJointPos[0]), q0_coors_qd1qd2);
+ pJointPos[1] += m_links[i].getAxisBottom(1).dot(no_q0_coors_qd1qd2) * dt;
+ pJointPos[2] += m_links[i].getAxisBottom(2).dot(no_q0_coors_qd1qd2) * dt;
+ break;
+ }
+ default:
+ {
+ }
+ }
+
+ m_links[i].updateInterpolationCacheMultiDof();
+ }
+}
void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd)
{
@@ -1589,9 +1707,9 @@ void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd
//btVector3 v = getBaseVel();
//m_basePos += dt * v;
//
- btScalar *pBasePos = (pq ? &pq[4] : m_basePos);
- btScalar *pBaseVel = (pqd ? &pqd[3] : &m_realBuf[3]); //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
- //
+ btScalar *pBasePos = (pq ? &pq[4] : m_basePos);
+ btScalar *pBaseVel = (pqd ? &pqd[3] : &m_realBuf[3]); //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
+
pBasePos[0] += dt * pBaseVel[0];
pBasePos[1] += dt * pBaseVel[1];
pBasePos[2] += dt * pBaseVel[2];
@@ -1645,7 +1763,7 @@ void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd
//pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
//
- btScalar *pBaseQuat = pq ? pq : m_baseQuat;
+ btScalar *pBaseQuat = pq ? pq : m_baseQuat;
btScalar *pBaseOmega = pqd ? pqd : &m_realBuf[0]; //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
//
btQuaternion baseQuat;
@@ -1670,7 +1788,9 @@ void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd
// Finally we can update m_jointPos for each of the m_links
for (int i = 0; i < num_links; ++i)
{
- btScalar *pJointPos = (pq ? pq : &m_links[i].m_jointPos[0]);
+ btScalar *pJointPos;
+ pJointPos= (pq ? pq : &m_links[i].m_jointPos[0]);
+
btScalar *pJointVel = (pqd ? pqd : getJointVelMultiDof(i));
switch (m_links[i].m_jointType)
@@ -1678,12 +1798,14 @@ void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd
case btMultibodyLink::ePrismatic:
case btMultibodyLink::eRevolute:
{
+ //reset to current pos
btScalar jointVel = pJointVel[0];
pJointPos[0] += dt * jointVel;
break;
}
case btMultibodyLink::eSpherical:
{
+ //reset to current pos
btVector3 jointVel;
jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
btQuaternion jointOri;
@@ -1974,6 +2096,7 @@ void btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQu
tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
getBaseCollider()->setWorldTransform(tr);
+ getBaseCollider()->setInterpolationWorldTransform(tr);
}
for (int k = 0; k < getNumLinks(); k++)
@@ -2002,10 +2125,62 @@ void btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQu
tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
col->setWorldTransform(tr);
+ col->setInterpolationWorldTransform(tr);
}
}
}
+void btMultiBody::updateCollisionObjectInterpolationWorldTransforms(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
+{
+ world_to_local.resize(getNumLinks() + 1);
+ local_origin.resize(getNumLinks() + 1);
+
+ world_to_local[0] = getInterpolateWorldToBaseRot();
+ local_origin[0] = getInterpolateBasePos();
+
+ if (getBaseCollider())
+ {
+ btVector3 posr = local_origin[0];
+ // float pos[4]={posr.x(),posr.y(),posr.z(),1};
+ btScalar quat[4] = {-world_to_local[0].x(), -world_to_local[0].y(), -world_to_local[0].z(), world_to_local[0].w()};
+ btTransform tr;
+ tr.setIdentity();
+ tr.setOrigin(posr);
+ tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+
+ getBaseCollider()->setInterpolationWorldTransform(tr);
+ }
+
+ for (int k = 0; k < getNumLinks(); k++)
+ {
+ const int parent = getParent(k);
+ world_to_local[k + 1] = getInterpolateParentToLocalRot(k) * world_to_local[parent + 1];
+ local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getInterpolateRVector(k)));
+ }
+
+ for (int m = 0; m < getNumLinks(); m++)
+ {
+ btMultiBodyLinkCollider *col = getLink(m).m_collider;
+ if (col)
+ {
+ int link = col->m_link;
+ btAssert(link == m);
+
+ int index = link + 1;
+
+ btVector3 posr = local_origin[index];
+ // float pos[4]={posr.x(),posr.y(),posr.z(),1};
+ btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
+ btTransform tr;
+ tr.setIdentity();
+ tr.setOrigin(posr);
+ tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+
+ col->setInterpolationWorldTransform(tr);
+ }
+ }
+}
+
int btMultiBody::calculateSerializeBufferSize() const
{
int sz = sizeof(btMultiBodyData);
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
index c0b0d003be..be795633fd 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
@@ -193,12 +193,24 @@ public:
const btQuaternion &getWorldToBaseRot() const
{
return m_baseQuat;
- } // rotates world vectors into base frame
+ }
+
+ const btVector3 &getInterpolateBasePos() const
+ {
+ return m_basePos_interpolate;
+ } // in world frame
+ const btQuaternion &getInterpolateWorldToBaseRot() const
+ {
+ return m_baseQuat_interpolate;
+ }
+
+ // rotates world vectors into base frame
btVector3 getBaseOmega() const { return btVector3(m_realBuf[0], m_realBuf[1], m_realBuf[2]); } // in world frame
void setBasePos(const btVector3 &pos)
{
m_basePos = pos;
+ m_basePos_interpolate = pos;
}
void setBaseWorldTransform(const btTransform &tr)
@@ -224,6 +236,7 @@ public:
void setWorldToBaseRot(const btQuaternion &rot)
{
m_baseQuat = rot; //m_baseQuat asumed to ba alias!?
+ m_baseQuat_interpolate = rot;
}
void setBaseOmega(const btVector3 &omega)
{
@@ -260,6 +273,11 @@ public:
{
return &m_realBuf[0];
}
+
+ const btScalar *getDeltaVelocityVector() const
+ {
+ return &m_deltaV[0];
+ }
/* btScalar * getVelocityVector()
{
return &real_buf[0];
@@ -273,6 +291,8 @@ public:
const btVector3 &getRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords
const btQuaternion &getParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i.
+ const btVector3 &getInterpolateRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords
+ const btQuaternion &getInterpolateParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i.
//
// transform vectors in local frame of link i to world frame (or vice versa)
@@ -287,13 +307,6 @@ public:
//
btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &local_frame) const;
- //
- // calculate kinetic energy and angular momentum
- // useful for debugging.
- //
-
- btScalar getKineticEnergy() const;
- btVector3 getAngularMomentum() const;
//
// set external forces and torques. Note all external forces/torques are given in the WORLD frame.
@@ -421,6 +434,9 @@ public:
// timestep the positions (given current velocities).
void stepPositionsMultiDof(btScalar dt, btScalar *pq = 0, btScalar *pqd = 0);
+
+ // predict the positions
+ void predictPositionsMultiDof(btScalar dt);
//
// contacts
@@ -581,6 +597,7 @@ public:
void compTreeLinkVelocities(btVector3 * omega, btVector3 * vel) const;
void updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> & world_to_local, btAlignedObjectArray<btVector3> & local_origin);
+ void updateCollisionObjectInterpolationWorldTransforms(btAlignedObjectArray<btQuaternion> & world_to_local, btAlignedObjectArray<btVector3> & local_origin);
virtual int calculateSerializeBufferSize() const;
@@ -664,7 +681,9 @@ private:
const char *m_baseName; //memory needs to be manager by user!
btVector3 m_basePos; // position of COM of base (world frame)
+ btVector3 m_basePos_interpolate; // position of interpolated COM of base (world frame)
btQuaternion m_baseQuat; // rotates world points into base frame
+ btQuaternion m_baseQuat_interpolate;
btScalar m_baseMass; // mass of the base
btVector3 m_baseInertia; // inertia of the base (in local frame; diagonal)
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
index e17ab94d98..d7ed05ce57 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
@@ -342,40 +342,6 @@ btScalar btMultiBodyConstraint::fillMultiBodyConstraint(btMultiBodySolverConstra
solverConstraint.m_friction = 0.f; //cp.m_combinedFriction;
}
- ///warm starting (or zero if disabled)
- /*
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
-
- if (solverConstraint.m_appliedImpulse)
- {
- if (multiBodyA)
- {
- btScalar impulse = solverConstraint.m_appliedImpulse;
- btScalar* deltaV = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- multiBodyA->applyDeltaVee(deltaV,impulse);
- applyDeltaVee(data,deltaV,impulse,solverConstraint.m_deltaVelAindex,ndofA);
- } else
- {
- if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
- }
- if (multiBodyB)
- {
- btScalar impulse = solverConstraint.m_appliedImpulse;
- btScalar* deltaV = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- multiBodyB->applyDeltaVee(deltaV,impulse);
- applyDeltaVee(data,deltaV,impulse,solverConstraint.m_deltaVelBindex,ndofB);
- } else
- {
- if (rb1)
- bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse);
- }
- }
- } else
- */
-
solverConstraint.m_appliedImpulse = 0.f;
solverConstraint.m_appliedPushImpulse = 0.f;
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
index 23e163f0e8..2788367431 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
@@ -22,29 +22,36 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
#include "LinearMath/btQuickprof.h"
+#include "BulletDynamics/Featherstone/btMultiBodySolverConstraint.h"
+#include "LinearMath/btScalar.h"
btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
{
btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
//solve featherstone non-contact constraints
-
+ btScalar nonContactResidual = 0;
//printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size());
-
- for (int j = 0; j < m_multiBodyNonContactConstraints.size(); j++)
+ for (int i = 0; i < infoGlobal.m_numNonContactInnerIterations; ++i)
{
- int index = iteration & 1 ? j : m_multiBodyNonContactConstraints.size() - 1 - j;
+ // reset the nonContactResdual to 0 at start of each inner iteration
+ nonContactResidual = 0;
+ for (int j = 0; j < m_multiBodyNonContactConstraints.size(); j++)
+ {
+ int index = iteration & 1 ? j : m_multiBodyNonContactConstraints.size() - 1 - j;
- btMultiBodySolverConstraint& constraint = m_multiBodyNonContactConstraints[index];
+ btMultiBodySolverConstraint& constraint = m_multiBodyNonContactConstraints[index];
- btScalar residual = resolveSingleConstraintRowGeneric(constraint);
- leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
+ btScalar residual = resolveSingleConstraintRowGeneric(constraint);
+ nonContactResidual = btMax(nonContactResidual, residual * residual);
- if (constraint.m_multiBodyA)
- constraint.m_multiBodyA->setPosUpdated(false);
- if (constraint.m_multiBodyB)
- constraint.m_multiBodyB->setPosUpdated(false);
+ if (constraint.m_multiBodyA)
+ constraint.m_multiBodyA->setPosUpdated(false);
+ if (constraint.m_multiBodyB)
+ constraint.m_multiBodyB->setPosUpdated(false);
+ }
}
+ leastSquaredResidual = btMax(leastSquaredResidual, nonContactResidual);
//solve featherstone normal contact
for (int j0 = 0; j0 < m_multiBodyNormalContactConstraints.size(); j0++)
@@ -491,11 +498,7 @@ btScalar btMultiBodyConstraintSolver::resolveConeFrictionConstraintRows(const bt
return deltaVel;
}
-void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint,
- const btVector3& contactNormal,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
+void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint, const btVector3& contactNormal, const btScalar& appliedImpulse, btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, btScalar& relaxation, bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
{
BT_PROFILE("setupMultiBodyContactConstraint");
btVector3 rel_pos1;
@@ -781,48 +784,6 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
}
}
- ///warm starting (or zero if disabled)
- //disable warmstarting for btMultiBody, it has issues gaining energy (==explosion)
- if (0) //infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
-
- if (solverConstraint.m_appliedImpulse)
- {
- if (multiBodyA)
- {
- btScalar impulse = solverConstraint.m_appliedImpulse;
- btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- multiBodyA->applyDeltaVeeMultiDof(deltaV, impulse);
-
- applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
- }
- else
- {
- if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass() * rb0->getLinearFactor(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
- }
- if (multiBodyB)
- {
- btScalar impulse = solverConstraint.m_appliedImpulse;
- btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- multiBodyB->applyDeltaVeeMultiDof(deltaV, impulse);
- applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
- }
- else
- {
- if (rb1)
- bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() * rb1->getLinearFactor(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
- }
- }
- }
- else
- {
- solverConstraint.m_appliedImpulse = 0.f;
- }
-
- solverConstraint.m_appliedPushImpulse = 0.f;
-
{
btScalar positionalError = 0.f;
btScalar velocityError = restitution - rel_vel; // * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
@@ -874,6 +835,54 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
}
+
+ if (infoGlobal.m_solverMode & SOLVER_USE_ARTICULATED_WARMSTARTING)
+ {
+ if (btFabs(cp.m_prevRHS) > 1e-5 && cp.m_prevRHS < 2* solverConstraint.m_rhs && solverConstraint.m_rhs < 2*cp.m_prevRHS)
+ {
+ solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse / cp.m_prevRHS * solverConstraint.m_rhs * infoGlobal.m_articulatedWarmstartingFactor;
+ if (solverConstraint.m_appliedImpulse < 0)
+ solverConstraint.m_appliedImpulse = 0;
+ }
+ else
+ {
+ solverConstraint.m_appliedImpulse = 0.f;
+ }
+
+ if (solverConstraint.m_appliedImpulse)
+ {
+ if (multiBodyA)
+ {
+ btScalar impulse = solverConstraint.m_appliedImpulse;
+ btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ multiBodyA->applyDeltaVeeMultiDof2(deltaV, impulse);
+
+ applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
+ }
+ else
+ {
+ if (rb0)
+ bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass() * rb0->getLinearFactor(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
+ }
+ if (multiBodyB)
+ {
+ btScalar impulse = solverConstraint.m_appliedImpulse;
+ btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ multiBodyB->applyDeltaVeeMultiDof2(deltaV, impulse);
+ applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
+ }
+ else
+ {
+ if (rb1)
+ bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() * rb1->getLinearFactor(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
+ }
+ }
+ }
+ else
+ {
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+ }
}
void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint,
@@ -944,13 +953,13 @@ void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMu
btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex], delta, m_data.scratch_r, m_data.scratch_v);
- btVector3 torqueAxis0 = -constraintNormal;
+ btVector3 torqueAxis0 = constraintNormal;
solverConstraint.m_relpos1CrossNormal = torqueAxis0;
solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
}
else
{
- btVector3 torqueAxis0 = -constraintNormal;
+ btVector3 torqueAxis0 = constraintNormal;
solverConstraint.m_relpos1CrossNormal = torqueAxis0;
solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
@@ -986,13 +995,13 @@ void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMu
multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -constraintNormal, btVector3(0, 0, 0), &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex], &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v);
- btVector3 torqueAxis1 = constraintNormal;
+ btVector3 torqueAxis1 = -constraintNormal;
solverConstraint.m_relpos2CrossNormal = torqueAxis1;
solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
}
else
{
- btVector3 torqueAxis1 = constraintNormal;
+ btVector3 torqueAxis1 = -constraintNormal;
solverConstraint.m_relpos2CrossNormal = torqueAxis1;
solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
@@ -1130,7 +1139,7 @@ void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMu
}
}
-btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis, const btScalar& appliedImpulse, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
BT_PROFILE("addMultiBodyFrictionConstraint");
btMultiBodySolverConstraint& solverConstraint = m_multiBodyFrictionContactConstraints.expandNonInitializing();
@@ -1161,7 +1170,7 @@ btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionCo
solverConstraint.m_originalContactPoint = &cp;
- setupMultiBodyContactConstraint(solverConstraint, normalAxis, cp, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
+ setupMultiBodyContactConstraint(solverConstraint, normalAxis, 0, cp, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
return solverConstraint;
}
@@ -1246,7 +1255,7 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
{
const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
-
+
btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
@@ -1266,7 +1275,7 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
// return;
//only a single rollingFriction per manifold
- int rollingFriction = 1;
+ int rollingFriction = 4;
for (int j = 0; j < manifold->getNumContacts(); j++)
{
@@ -1297,7 +1306,7 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
solverConstraint.m_originalContactPoint = &cp;
bool isFriction = false;
- setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB, cp, infoGlobal, relaxation, isFriction);
+ setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB, cp.m_appliedImpulse, cp, infoGlobal, relaxation, isFriction);
// const btVector3& pos1 = cp.getPositionWorldOnA();
// const btVector3& pos2 = cp.getPositionWorldOnB();
@@ -1371,13 +1380,13 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
{
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, cp.m_appliedImpulseLateral1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, cp.m_appliedImpulseLateral2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
}
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
@@ -1388,26 +1397,27 @@ void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold*
}
else
{
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, cp.m_appliedImpulseLateral1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
-
- //setMultiBodyFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
- //todo:
+ addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, cp.m_appliedImpulseLateral2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
solverConstraint.m_appliedImpulse = 0.f;
solverConstraint.m_appliedPushImpulse = 0.f;
- }
+ }
#endif //ENABLE_FRICTION
}
+ else
+ {
+ // Reset quantities related to warmstart as 0.
+ cp.m_appliedImpulse = 0;
+ cp.m_prevRHS = 0;
+ }
}
}
void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
{
- //btPersistentManifold* manifold = 0;
-
for (int i = 0; i < numManifolds; i++)
{
btPersistentManifold* manifold = manifoldPtr[i];
@@ -1434,6 +1444,51 @@ void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifol
c->createConstraintRows(m_multiBodyNonContactConstraints, m_data, infoGlobal);
}
+
+ // Warmstart for noncontact constraints
+ if (infoGlobal.m_solverMode & SOLVER_USE_ARTICULATED_WARMSTARTING)
+ {
+ for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
+ {
+ btMultiBodySolverConstraint& solverConstraint =
+ m_multiBodyNonContactConstraints[i];
+ solverConstraint.m_appliedImpulse =
+ solverConstraint.m_orgConstraint->getAppliedImpulse(solverConstraint.m_orgDofIndex) *
+ infoGlobal.m_articulatedWarmstartingFactor;
+
+ btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+ btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+ if (solverConstraint.m_appliedImpulse)
+ {
+ if (multiBodyA)
+ {
+ int ndofA = multiBodyA->getNumDofs() + 6;
+ btScalar* deltaV =
+ &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+ btScalar impulse = solverConstraint.m_appliedImpulse;
+ multiBodyA->applyDeltaVeeMultiDof2(deltaV, impulse);
+ applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
+ }
+ if (multiBodyB)
+ {
+ int ndofB = multiBodyB->getNumDofs() + 6;
+ btScalar* deltaV =
+ &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+ btScalar impulse = solverConstraint.m_appliedImpulse;
+ multiBodyB->applyDeltaVeeMultiDof2(deltaV, impulse);
+ applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
+ {
+ btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
+ solverConstraint.m_appliedImpulse = 0;
+ }
+ }
}
btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
@@ -1556,7 +1611,7 @@ btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionO
writeBackSolverBodyToMultiBody(solverConstraint, infoGlobal.m_timeStep);
}
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+
{
BT_PROFILE("warm starting write back");
for (int j = 0; j < numPoolConstraints; j++)
@@ -1565,6 +1620,7 @@ btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionO
btManifoldPoint* pt = (btManifoldPoint*)solverConstraint.m_originalContactPoint;
btAssert(pt);
pt->m_appliedImpulse = solverConstraint.m_appliedImpulse;
+ pt->m_prevRHS = solverConstraint.m_rhs;
pt->m_appliedImpulseLateral1 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse;
//printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
@@ -1576,9 +1632,8 @@ btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionO
pt->m_appliedImpulseLateral2 = 0;
}
}
-
- //do a callback here?
}
+
#if 0
//multibody joint feedback
{
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
index abf5718839..f584360e2b 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
@@ -49,7 +49,7 @@ protected:
void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
- btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
+ btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis, const btScalar& appliedImpulse, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
btMultiBodySolverConstraint& addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
btScalar combinedTorsionalFriction,
@@ -66,7 +66,9 @@ protected:
void setupMultiBodyContactConstraint(btMultiBodySolverConstraint & solverConstraint,
const btVector3& contactNormal,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
+ const btScalar& appliedImpulse,
+ btManifoldPoint& cp,
+ const btContactSolverInfo& infoGlobal,
btScalar& relaxation,
bool isFriction, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
@@ -82,7 +84,6 @@ protected:
void convertMultiBodyContact(btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
// virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
-
virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
void applyDeltaVee(btScalar * deltaV, btScalar impulse, int velocityIndex, int ndof);
void writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint & constraint, btScalar deltaTime);
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
index 1131e5378c..cd1bad089e 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
@@ -33,6 +33,12 @@ void btMultiBodyDynamicsWorld::removeMultiBody(btMultiBody* body)
m_multiBodies.remove(body);
}
+void btMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
+ predictMultiBodyTransforms(timeStep);
+
+}
void btMultiBodyDynamicsWorld::calculateSimulationIslands()
{
BT_PROFILE("calculateSimulationIslands");
@@ -163,218 +169,6 @@ void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
btDiscreteDynamicsWorld::updateActivationState(timeStep);
}
-SIMD_FORCE_INLINE int btGetConstraintIslandId2(const btTypedConstraint* lhs)
-{
- int islandId;
-
- const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
- const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
- islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
- return islandId;
-}
-
-class btSortConstraintOnIslandPredicate2
-{
-public:
- bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
- {
- int rIslandId0, lIslandId0;
- rIslandId0 = btGetConstraintIslandId2(rhs);
- lIslandId0 = btGetConstraintIslandId2(lhs);
- return lIslandId0 < rIslandId0;
- }
-};
-
-SIMD_FORCE_INLINE int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint* lhs)
-{
- int islandId;
-
- int islandTagA = lhs->getIslandIdA();
- int islandTagB = lhs->getIslandIdB();
- islandId = islandTagA >= 0 ? islandTagA : islandTagB;
- return islandId;
-}
-
-class btSortMultiBodyConstraintOnIslandPredicate
-{
-public:
- bool operator()(const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs) const
- {
- int rIslandId0, lIslandId0;
- rIslandId0 = btGetMultiBodyConstraintIslandId(rhs);
- lIslandId0 = btGetMultiBodyConstraintIslandId(lhs);
- return lIslandId0 < rIslandId0;
- }
-};
-
-
-struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
-{
- btContactSolverInfo* m_solverInfo;
- btMultiBodyConstraintSolver* m_solver;
- btMultiBodyConstraint** m_multiBodySortedConstraints;
- int m_numMultiBodyConstraints;
-
- btTypedConstraint** m_sortedConstraints;
- int m_numConstraints;
- btIDebugDraw* m_debugDrawer;
- btDispatcher* m_dispatcher;
-
- btAlignedObjectArray<btCollisionObject*> m_bodies;
- btAlignedObjectArray<btPersistentManifold*> m_manifolds;
- btAlignedObjectArray<btTypedConstraint*> m_constraints;
- btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
-
- btAlignedObjectArray<btSolverAnalyticsData> m_islandAnalyticsData;
-
- MultiBodyInplaceSolverIslandCallback(btMultiBodyConstraintSolver* solver,
- btDispatcher* dispatcher)
- : m_solverInfo(NULL),
- m_solver(solver),
- m_multiBodySortedConstraints(NULL),
- m_numConstraints(0),
- m_debugDrawer(NULL),
- m_dispatcher(dispatcher)
- {
- }
-
- MultiBodyInplaceSolverIslandCallback& operator=(const MultiBodyInplaceSolverIslandCallback& other)
- {
- btAssert(0);
- (void)other;
- return *this;
- }
-
- SIMD_FORCE_INLINE void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
- {
- m_islandAnalyticsData.clear();
- btAssert(solverInfo);
- m_solverInfo = solverInfo;
-
- m_multiBodySortedConstraints = sortedMultiBodyConstraints;
- m_numMultiBodyConstraints = numMultiBodyConstraints;
- m_sortedConstraints = sortedConstraints;
- m_numConstraints = numConstraints;
-
- m_debugDrawer = debugDrawer;
- m_bodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.resize(0);
- m_multiBodyConstraints.resize(0);
- }
-
- void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
- {
- m_solver = solver;
- }
-
- virtual void processIsland(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifolds, int numManifolds, int islandId)
- {
- if (islandId < 0)
- {
- ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
- m_solver->solveMultiBodyGroup(bodies, numBodies, manifolds, numManifolds, m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
- if (m_solverInfo->m_reportSolverAnalytics&1)
- {
- m_solver->m_analyticsData.m_islandId = islandId;
- m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
- }
- }
- else
- {
- //also add all non-contact constraints/joints for this island
- btTypedConstraint** startConstraint = 0;
- btMultiBodyConstraint** startMultiBodyConstraint = 0;
-
- int numCurConstraints = 0;
- int numCurMultiBodyConstraints = 0;
-
- int i;
-
- //find the first constraint for this island
-
- for (i = 0; i < m_numConstraints; i++)
- {
- if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
- {
- startConstraint = &m_sortedConstraints[i];
- break;
- }
- }
- //count the number of constraints in this island
- for (; i < m_numConstraints; i++)
- {
- if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
- {
- numCurConstraints++;
- }
- }
-
- for (i = 0; i < m_numMultiBodyConstraints; i++)
- {
- if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
- {
- startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
- break;
- }
- }
- //count the number of multi body constraints in this island
- for (; i < m_numMultiBodyConstraints; i++)
- {
- if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
- {
- numCurMultiBodyConstraints++;
- }
- }
-
- //if (m_solverInfo->m_minimumSolverBatchSize<=1)
- //{
- // m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
- //} else
- {
- for (i = 0; i < numBodies; i++)
- m_bodies.push_back(bodies[i]);
- for (i = 0; i < numManifolds; i++)
- m_manifolds.push_back(manifolds[i]);
- for (i = 0; i < numCurConstraints; i++)
- m_constraints.push_back(startConstraint[i]);
-
- for (i = 0; i < numCurMultiBodyConstraints; i++)
- m_multiBodyConstraints.push_back(startMultiBodyConstraint[i]);
-
- if ((m_multiBodyConstraints.size() + m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
- {
- processConstraints(islandId);
- }
- else
- {
- //printf("deferred\n");
- }
- }
- }
- }
- void processConstraints(int islandId=-1)
- {
- btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
- btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
- btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
- btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
-
- //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
-
- m_solver->solveMultiBodyGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
- if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics&1))
- {
- m_solver->m_analyticsData.m_islandId = islandId;
- m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
- }
- m_bodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.resize(0);
- m_multiBodyConstraints.resize(0);
- }
-};
-
void btMultiBodyDynamicsWorld::getAnalyticsData(btAlignedObjectArray<btSolverAnalyticsData>& islandAnalyticsData) const
{
islandAnalyticsData = m_solverMultiBodyIslandCallback->m_islandAnalyticsData;
@@ -421,350 +215,364 @@ void btMultiBodyDynamicsWorld::forwardKinematics()
}
void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
{
- forwardKinematics();
-
- BT_PROFILE("solveConstraints");
-
- clearMultiBodyConstraintForces();
-
- m_sortedConstraints.resize(m_constraints.size());
- int i;
- for (i = 0; i < getNumConstraints(); i++)
- {
- m_sortedConstraints[i] = m_constraints[i];
- }
- m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
- btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
-
- m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
- for (i = 0; i < m_multiBodyConstraints.size(); i++)
- {
- m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
- }
- m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
+ solveExternalForces(solverInfo);
+ buildIslands();
+ solveInternalConstraints(solverInfo);
+}
- btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
+void btMultiBodyDynamicsWorld::buildIslands()
+{
+ m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverMultiBodyIslandCallback);
+}
- m_solverMultiBodyIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
- m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+void btMultiBodyDynamicsWorld::solveInternalConstraints(btContactSolverInfo& solverInfo)
+{
+ /// solve all the constraints for this island
+ m_solverMultiBodyIslandCallback->processConstraints();
+ m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
+ {
+ BT_PROFILE("btMultiBody stepVelocities");
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+
+ if (bod->internalNeedsJointFeedback())
+ {
+ if (!bod->isUsingRK4Integration())
+ {
+ if (bod->internalNeedsJointFeedback())
+ {
+ bool isConstraintPass = true;
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
+ }
+ }
+ }
+ }
+ }
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+ bod->processDeltaVeeMultiDof2();
+ }
+}
+void btMultiBodyDynamicsWorld::solveExternalForces(btContactSolverInfo& solverInfo)
+{
+ forwardKinematics();
+
+ BT_PROFILE("solveConstraints");
+
+ clearMultiBodyConstraintForces();
+
+ m_sortedConstraints.resize(m_constraints.size());
+ int i;
+ for (i = 0; i < getNumConstraints(); i++)
+ {
+ m_sortedConstraints[i] = m_constraints[i];
+ }
+ m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
+ btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
+
+ m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
+ for (i = 0; i < m_multiBodyConstraints.size(); i++)
+ {
+ m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
+ }
+ m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
+
+ btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
+
+ m_solverMultiBodyIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
+ m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+
#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- {
- BT_PROFILE("btMultiBody addForce");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
-
- bod->addBaseForce(m_gravity * bod->getBaseMass());
-
- for (int j = 0; j < bod->getNumLinks(); ++j)
- {
- bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
- }
- } //if (!isSleeping)
- }
- }
+ {
+ BT_PROFILE("btMultiBody addForce");
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+
+ bod->addBaseForce(m_gravity * bod->getBaseMass());
+
+ for (int j = 0; j < bod->getNumLinks(); ++j)
+ {
+ bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
+ }
+ } //if (!isSleeping)
+ }
+ }
#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
-
- {
- BT_PROFILE("btMultiBody stepVelocities");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
- bool doNotUpdatePos = false;
+
+ {
+ BT_PROFILE("btMultiBody stepVelocities");
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+ bool doNotUpdatePos = false;
bool isConstraintPass = false;
- {
- if (!bod->isUsingRK4Integration())
- {
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep,
- m_scratch_r, m_scratch_v, m_scratch_m,isConstraintPass,
- getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- else
- {
- //
- int numDofs = bod->getNumDofs() + 6;
- int numPosVars = bod->getNumPosVars() + 7;
- btAlignedObjectArray<btScalar> scratch_r2;
- scratch_r2.resize(2 * numPosVars + 8 * numDofs);
- //convenience
- btScalar* pMem = &scratch_r2[0];
- btScalar* scratch_q0 = pMem;
- pMem += numPosVars;
- btScalar* scratch_qx = pMem;
- pMem += numPosVars;
- btScalar* scratch_qd0 = pMem;
- pMem += numDofs;
- btScalar* scratch_qd1 = pMem;
- pMem += numDofs;
- btScalar* scratch_qd2 = pMem;
- pMem += numDofs;
- btScalar* scratch_qd3 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd0 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd1 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd2 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd3 = pMem;
- pMem += numDofs;
- btAssert((pMem - (2 * numPosVars + 8 * numDofs)) == &scratch_r2[0]);
-
- /////
- //copy q0 to scratch_q0 and qd0 to scratch_qd0
- scratch_q0[0] = bod->getWorldToBaseRot().x();
- scratch_q0[1] = bod->getWorldToBaseRot().y();
- scratch_q0[2] = bod->getWorldToBaseRot().z();
- scratch_q0[3] = bod->getWorldToBaseRot().w();
- scratch_q0[4] = bod->getBasePos().x();
- scratch_q0[5] = bod->getBasePos().y();
- scratch_q0[6] = bod->getBasePos().z();
- //
- for (int link = 0; link < bod->getNumLinks(); ++link)
- {
- for (int dof = 0; dof < bod->getLink(link).m_posVarCount; ++dof)
- scratch_q0[7 + bod->getLink(link).m_cfgOffset + dof] = bod->getLink(link).m_jointPos[dof];
- }
- //
- for (int dof = 0; dof < numDofs; ++dof)
- scratch_qd0[dof] = bod->getVelocityVector()[dof];
- ////
- struct
- {
- btMultiBody* bod;
- btScalar *scratch_qx, *scratch_q0;
-
- void operator()()
- {
- for (int dof = 0; dof < bod->getNumPosVars() + 7; ++dof)
- scratch_qx[dof] = scratch_q0[dof];
- }
- } pResetQx = {bod, scratch_qx, scratch_q0};
- //
- struct
- {
- void operator()(btScalar dt, const btScalar* pDer, const btScalar* pCurVal, btScalar* pVal, int size)
- {
- for (int i = 0; i < size; ++i)
- pVal[i] = pCurVal[i] + dt * pDer[i];
- }
-
- } pEulerIntegrate;
- //
- struct
- {
- void operator()(btMultiBody* pBody, const btScalar* pData)
- {
- btScalar* pVel = const_cast<btScalar*>(pBody->getVelocityVector());
-
- for (int i = 0; i < pBody->getNumDofs() + 6; ++i)
- pVel[i] = pData[i];
- }
- } pCopyToVelocityVector;
- //
- struct
- {
- void operator()(const btScalar* pSrc, btScalar* pDst, int start, int size)
- {
- for (int i = 0; i < size; ++i)
- pDst[i] = pSrc[start + i];
- }
- } pCopy;
- //
-
- btScalar h = solverInfo.m_timeStep;
+ {
+ if (!bod->isUsingRK4Integration())
+ {
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep,
+ m_scratch_r, m_scratch_v, m_scratch_m,isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
+ else
+ {
+ //
+ int numDofs = bod->getNumDofs() + 6;
+ int numPosVars = bod->getNumPosVars() + 7;
+ btAlignedObjectArray<btScalar> scratch_r2;
+ scratch_r2.resize(2 * numPosVars + 8 * numDofs);
+ //convenience
+ btScalar* pMem = &scratch_r2[0];
+ btScalar* scratch_q0 = pMem;
+ pMem += numPosVars;
+ btScalar* scratch_qx = pMem;
+ pMem += numPosVars;
+ btScalar* scratch_qd0 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qd1 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qd2 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qd3 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd0 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd1 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd2 = pMem;
+ pMem += numDofs;
+ btScalar* scratch_qdd3 = pMem;
+ pMem += numDofs;
+ btAssert((pMem - (2 * numPosVars + 8 * numDofs)) == &scratch_r2[0]);
+
+ /////
+ //copy q0 to scratch_q0 and qd0 to scratch_qd0
+ scratch_q0[0] = bod->getWorldToBaseRot().x();
+ scratch_q0[1] = bod->getWorldToBaseRot().y();
+ scratch_q0[2] = bod->getWorldToBaseRot().z();
+ scratch_q0[3] = bod->getWorldToBaseRot().w();
+ scratch_q0[4] = bod->getBasePos().x();
+ scratch_q0[5] = bod->getBasePos().y();
+ scratch_q0[6] = bod->getBasePos().z();
+ //
+ for (int link = 0; link < bod->getNumLinks(); ++link)
+ {
+ for (int dof = 0; dof < bod->getLink(link).m_posVarCount; ++dof)
+ scratch_q0[7 + bod->getLink(link).m_cfgOffset + dof] = bod->getLink(link).m_jointPos[dof];
+ }
+ //
+ for (int dof = 0; dof < numDofs; ++dof)
+ scratch_qd0[dof] = bod->getVelocityVector()[dof];
+ ////
+ struct
+ {
+ btMultiBody* bod;
+ btScalar *scratch_qx, *scratch_q0;
+
+ void operator()()
+ {
+ for (int dof = 0; dof < bod->getNumPosVars() + 7; ++dof)
+ scratch_qx[dof] = scratch_q0[dof];
+ }
+ } pResetQx = {bod, scratch_qx, scratch_q0};
+ //
+ struct
+ {
+ void operator()(btScalar dt, const btScalar* pDer, const btScalar* pCurVal, btScalar* pVal, int size)
+ {
+ for (int i = 0; i < size; ++i)
+ pVal[i] = pCurVal[i] + dt * pDer[i];
+ }
+
+ } pEulerIntegrate;
+ //
+ struct
+ {
+ void operator()(btMultiBody* pBody, const btScalar* pData)
+ {
+ btScalar* pVel = const_cast<btScalar*>(pBody->getVelocityVector());
+
+ for (int i = 0; i < pBody->getNumDofs() + 6; ++i)
+ pVel[i] = pData[i];
+ }
+ } pCopyToVelocityVector;
+ //
+ struct
+ {
+ void operator()(const btScalar* pSrc, btScalar* pDst, int start, int size)
+ {
+ for (int i = 0; i < size; ++i)
+ pDst[i] = pSrc[start + i];
+ }
+ } pCopy;
+ //
+
+ btScalar h = solverInfo.m_timeStep;
#define output &m_scratch_r[bod->getNumDofs()]
- //calc qdd0 from: q0 & qd0
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd0, 0, numDofs);
- //calc q1 = q0 + h/2 * qd0
- pResetQx();
- bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd0);
- //calc qd1 = qd0 + h/2 * qdd0
- pEulerIntegrate(btScalar(.5) * h, scratch_qdd0, scratch_qd0, scratch_qd1, numDofs);
- //
- //calc qdd1 from: q1 & qd1
- pCopyToVelocityVector(bod, scratch_qd1);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd1, 0, numDofs);
- //calc q2 = q0 + h/2 * qd1
- pResetQx();
- bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd1);
- //calc qd2 = qd0 + h/2 * qdd1
- pEulerIntegrate(btScalar(.5) * h, scratch_qdd1, scratch_qd0, scratch_qd2, numDofs);
- //
- //calc qdd2 from: q2 & qd2
- pCopyToVelocityVector(bod, scratch_qd2);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd2, 0, numDofs);
- //calc q3 = q0 + h * qd2
- pResetQx();
- bod->stepPositionsMultiDof(h, scratch_qx, scratch_qd2);
- //calc qd3 = qd0 + h * qdd2
- pEulerIntegrate(h, scratch_qdd2, scratch_qd0, scratch_qd3, numDofs);
- //
- //calc qdd3 from: q3 & qd3
- pCopyToVelocityVector(bod, scratch_qd3);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd3, 0, numDofs);
-
- //
- //calc q = q0 + h/6(qd0 + 2*(qd1 + qd2) + qd3)
- //calc qd = qd0 + h/6(qdd0 + 2*(qdd1 + qdd2) + qdd3)
- btAlignedObjectArray<btScalar> delta_q;
- delta_q.resize(numDofs);
- btAlignedObjectArray<btScalar> delta_qd;
- delta_qd.resize(numDofs);
- for (int i = 0; i < numDofs; ++i)
- {
- delta_q[i] = h / btScalar(6.) * (scratch_qd0[i] + 2 * scratch_qd1[i] + 2 * scratch_qd2[i] + scratch_qd3[i]);
- delta_qd[i] = h / btScalar(6.) * (scratch_qdd0[i] + 2 * scratch_qdd1[i] + 2 * scratch_qdd2[i] + scratch_qdd3[i]);
- //delta_q[i] = h*scratch_qd0[i];
- //delta_qd[i] = h*scratch_qdd0[i];
- }
- //
- pCopyToVelocityVector(bod, scratch_qd0);
- bod->applyDeltaVeeMultiDof(&delta_qd[0], 1);
- //
- if (!doNotUpdatePos)
- {
- btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
- pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
-
- for (int i = 0; i < numDofs; ++i)
- pRealBuf[i] = delta_q[i];
-
- //bod->stepPositionsMultiDof(1, 0, &delta_q[0]);
- bod->setPosUpdated(true);
- }
-
- //ugly hack which resets the cached data to t0 (needed for constraint solver)
- {
- for (int link = 0; link < bod->getNumLinks(); ++link)
- bod->getLink(link).updateCacheMultiDof();
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- }
- }
-
+ //calc qdd0 from: q0 & qd0
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ pCopy(output, scratch_qdd0, 0, numDofs);
+ //calc q1 = q0 + h/2 * qd0
+ pResetQx();
+ bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd0);
+ //calc qd1 = qd0 + h/2 * qdd0
+ pEulerIntegrate(btScalar(.5) * h, scratch_qdd0, scratch_qd0, scratch_qd1, numDofs);
+ //
+ //calc qdd1 from: q1 & qd1
+ pCopyToVelocityVector(bod, scratch_qd1);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ pCopy(output, scratch_qdd1, 0, numDofs);
+ //calc q2 = q0 + h/2 * qd1
+ pResetQx();
+ bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd1);
+ //calc qd2 = qd0 + h/2 * qdd1
+ pEulerIntegrate(btScalar(.5) * h, scratch_qdd1, scratch_qd0, scratch_qd2, numDofs);
+ //
+ //calc qdd2 from: q2 & qd2
+ pCopyToVelocityVector(bod, scratch_qd2);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ pCopy(output, scratch_qdd2, 0, numDofs);
+ //calc q3 = q0 + h * qd2
+ pResetQx();
+ bod->stepPositionsMultiDof(h, scratch_qx, scratch_qd2);
+ //calc qd3 = qd0 + h * qdd2
+ pEulerIntegrate(h, scratch_qdd2, scratch_qd0, scratch_qd3, numDofs);
+ //
+ //calc qdd3 from: q3 & qd3
+ pCopyToVelocityVector(bod, scratch_qd3);
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ pCopy(output, scratch_qdd3, 0, numDofs);
+
+ //
+ //calc q = q0 + h/6(qd0 + 2*(qd1 + qd2) + qd3)
+ //calc qd = qd0 + h/6(qdd0 + 2*(qdd1 + qdd2) + qdd3)
+ btAlignedObjectArray<btScalar> delta_q;
+ delta_q.resize(numDofs);
+ btAlignedObjectArray<btScalar> delta_qd;
+ delta_qd.resize(numDofs);
+ for (int i = 0; i < numDofs; ++i)
+ {
+ delta_q[i] = h / btScalar(6.) * (scratch_qd0[i] + 2 * scratch_qd1[i] + 2 * scratch_qd2[i] + scratch_qd3[i]);
+ delta_qd[i] = h / btScalar(6.) * (scratch_qdd0[i] + 2 * scratch_qdd1[i] + 2 * scratch_qdd2[i] + scratch_qdd3[i]);
+ //delta_q[i] = h*scratch_qd0[i];
+ //delta_qd[i] = h*scratch_qdd0[i];
+ }
+ //
+ pCopyToVelocityVector(bod, scratch_qd0);
+ bod->applyDeltaVeeMultiDof(&delta_qd[0], 1);
+ //
+ if (!doNotUpdatePos)
+ {
+ btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
+ pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
+
+ for (int i = 0; i < numDofs; ++i)
+ pRealBuf[i] = delta_q[i];
+
+ //bod->stepPositionsMultiDof(1, 0, &delta_q[0]);
+ bod->setPosUpdated(true);
+ }
+
+ //ugly hack which resets the cached data to t0 (needed for constraint solver)
+ {
+ for (int link = 0; link < bod->getNumLinks(); ++link)
+ bod->getLink(link).updateCacheMultiDof();
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m,
+ isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
+ }
+ }
+
#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- bod->clearForcesAndTorques();
+ bod->clearForcesAndTorques();
#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- } //if (!isSleeping)
- }
- }
-
- /// solve all the constraints for this island
- m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverMultiBodyIslandCallback);
-
- m_solverMultiBodyIslandCallback->processConstraints();
-
- m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
-
- {
- BT_PROFILE("btMultiBody stepVelocities");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
-
- if (bod->internalNeedsJointFeedback())
- {
- if (!bod->isUsingRK4Integration())
- {
- if (bod->internalNeedsJointFeedback())
- {
- bool isConstraintPass = true;
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
- getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- }
- }
- }
- }
- }
-
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
- bod->processDeltaVeeMultiDof2();
- }
+ } //if (!isSleeping)
+ }
+ }
}
+
void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
{
btDiscreteDynamicsWorld::integrateTransforms(timeStep);
+ integrateMultiBodyTransforms(timeStep);
+}
- {
+void btMultiBodyDynamicsWorld::integrateMultiBodyTransforms(btScalar timeStep)
+{
BT_PROFILE("btMultiBody stepPositions");
//integrate and update the Featherstone hierarchies
@@ -787,31 +595,61 @@ void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
int nLinks = bod->getNumLinks();
///base + num m_links
+ if (!bod->isPosUpdated())
+ bod->stepPositionsMultiDof(timeStep);
+ else
+ {
+ btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
+ pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
- {
- if (!bod->isPosUpdated())
- bod->stepPositionsMultiDof(timeStep);
- else
- {
- btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
- pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
+ bod->stepPositionsMultiDof(1, 0, pRealBuf);
+ bod->setPosUpdated(false);
+ }
- bod->stepPositionsMultiDof(1, 0, pRealBuf);
- bod->setPosUpdated(false);
- }
- }
m_scratch_world_to_local.resize(nLinks + 1);
m_scratch_local_origin.resize(nLinks + 1);
-
- bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
+ bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
}
else
{
bod->clearVelocities();
}
}
- }
+}
+
+void btMultiBodyDynamicsWorld::predictMultiBodyTransforms(btScalar timeStep)
+{
+ BT_PROFILE("btMultiBody stepPositions");
+ //integrate and update the Featherstone hierarchies
+
+ for (int b = 0; b < m_multiBodies.size(); b++)
+ {
+ btMultiBody* bod = m_multiBodies[b];
+ bool isSleeping = false;
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ int nLinks = bod->getNumLinks();
+ bod->predictPositionsMultiDof(timeStep);
+ m_scratch_world_to_local.resize(nLinks + 1);
+ m_scratch_local_origin.resize(nLinks + 1);
+ bod->updateCollisionObjectInterpolationWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
+ }
+ else
+ {
+ bod->clearVelocities();
+ }
+ }
}
void btMultiBodyDynamicsWorld::addMultiBodyConstraint(btMultiBodyConstraint* constraint)
@@ -1029,3 +867,8 @@ void btMultiBodyDynamicsWorld::serializeMultiBodies(btSerializer* serializer)
}
}
}
+//
+//void btMultiBodyDynamicsWorld::setSplitIslands(bool split)
+//{
+// m_islandManager->setSplitIslands(split);
+//}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
index e36c2f7aad..9ac46f4b64 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
@@ -17,6 +17,7 @@ subject to the following restrictions:
#define BT_MULTIBODY_DYNAMICS_WORLD_H
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+#include "BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h"
#define BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
@@ -47,7 +48,7 @@ protected:
virtual void calculateSimulationIslands();
virtual void updateActivationState(btScalar timeStep);
- virtual void solveConstraints(btContactSolverInfo& solverInfo);
+
virtual void serializeMultiBodies(btSerializer* serializer);
@@ -55,7 +56,9 @@ public:
btMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration);
virtual ~btMultiBodyDynamicsWorld();
-
+
+ virtual void solveConstraints(btContactSolverInfo& solverInfo);
+
virtual void addMultiBody(btMultiBody* body, int group = btBroadphaseProxy::DefaultFilter, int mask = btBroadphaseProxy::AllFilter);
virtual void removeMultiBody(btMultiBody* body);
@@ -95,7 +98,10 @@ public:
virtual void removeMultiBodyConstraint(btMultiBodyConstraint* constraint);
virtual void integrateTransforms(btScalar timeStep);
-
+ void integrateMultiBodyTransforms(btScalar timeStep);
+ void predictMultiBodyTransforms(btScalar timeStep);
+
+ virtual void predictUnconstraintMotion(btScalar timeStep);
virtual void debugDrawWorld();
virtual void debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint);
@@ -110,6 +116,9 @@ public:
virtual void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver);
virtual void setConstraintSolver(btConstraintSolver* solver);
virtual void getAnalyticsData(btAlignedObjectArray<struct btSolverAnalyticsData>& m_islandAnalyticsData) const;
-
+
+ virtual void solveExternalForces(btContactSolverInfo& solverInfo);
+ virtual void solveInternalConstraints(btContactSolverInfo& solverInfo);
+ void buildIslands();
};
#endif //BT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h
new file mode 100644
index 0000000000..3169b86e61
--- /dev/null
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h
@@ -0,0 +1,247 @@
+/*
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H
+#define BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H
+
+#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
+#include "btMultiBodyConstraintSolver.h"
+
+SIMD_FORCE_INLINE int btGetConstraintIslandId2(const btTypedConstraint* lhs)
+{
+ int islandId;
+
+ const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
+ const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
+ islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
+ return islandId;
+}
+class btSortConstraintOnIslandPredicate2
+{
+public:
+ bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
+ {
+ int rIslandId0, lIslandId0;
+ rIslandId0 = btGetConstraintIslandId2(rhs);
+ lIslandId0 = btGetConstraintIslandId2(lhs);
+ return lIslandId0 < rIslandId0;
+ }
+};
+
+SIMD_FORCE_INLINE int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint* lhs)
+{
+ int islandId;
+
+ int islandTagA = lhs->getIslandIdA();
+ int islandTagB = lhs->getIslandIdB();
+ islandId = islandTagA >= 0 ? islandTagA : islandTagB;
+ return islandId;
+}
+
+class btSortMultiBodyConstraintOnIslandPredicate
+{
+public:
+ bool operator()(const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs) const
+ {
+ int rIslandId0, lIslandId0;
+ rIslandId0 = btGetMultiBodyConstraintIslandId(rhs);
+ lIslandId0 = btGetMultiBodyConstraintIslandId(lhs);
+ return lIslandId0 < rIslandId0;
+ }
+};
+
+struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
+{
+
+ btContactSolverInfo* m_solverInfo;
+ btMultiBodyConstraintSolver* m_solver;
+ btMultiBodyConstraint** m_multiBodySortedConstraints;
+ int m_numMultiBodyConstraints;
+
+ btTypedConstraint** m_sortedConstraints;
+ int m_numConstraints;
+ btIDebugDraw* m_debugDrawer;
+ btDispatcher* m_dispatcher;
+
+ btAlignedObjectArray<btCollisionObject*> m_bodies;
+ btAlignedObjectArray<btCollisionObject*> m_softBodies;
+ btAlignedObjectArray<btPersistentManifold*> m_manifolds;
+ btAlignedObjectArray<btTypedConstraint*> m_constraints;
+ btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
+
+ btAlignedObjectArray<btSolverAnalyticsData> m_islandAnalyticsData;
+
+ MultiBodyInplaceSolverIslandCallback(btMultiBodyConstraintSolver* solver,
+ btDispatcher* dispatcher)
+ : m_solverInfo(NULL),
+ m_solver(solver),
+ m_multiBodySortedConstraints(NULL),
+ m_numConstraints(0),
+ m_debugDrawer(NULL),
+ m_dispatcher(dispatcher)
+ {
+ }
+
+ MultiBodyInplaceSolverIslandCallback& operator=(const MultiBodyInplaceSolverIslandCallback& other)
+ {
+ btAssert(0);
+ (void)other;
+ return *this;
+ }
+
+ SIMD_FORCE_INLINE virtual void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
+ {
+ m_islandAnalyticsData.clear();
+ btAssert(solverInfo);
+ m_solverInfo = solverInfo;
+
+ m_multiBodySortedConstraints = sortedMultiBodyConstraints;
+ m_numMultiBodyConstraints = numMultiBodyConstraints;
+ m_sortedConstraints = sortedConstraints;
+ m_numConstraints = numConstraints;
+
+ m_debugDrawer = debugDrawer;
+ m_bodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
+ m_multiBodyConstraints.resize(0);
+ }
+
+ void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
+ {
+ m_solver = solver;
+ }
+
+ virtual void processIsland(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifolds, int numManifolds, int islandId)
+ {
+ if (islandId < 0)
+ {
+ ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
+ m_solver->solveMultiBodyGroup(bodies, numBodies, manifolds, numManifolds, m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
+ if (m_solverInfo->m_reportSolverAnalytics&1)
+ {
+ m_solver->m_analyticsData.m_islandId = islandId;
+ m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+ }
+ }
+ else
+ {
+ //also add all non-contact constraints/joints for this island
+ btTypedConstraint** startConstraint = 0;
+ btMultiBodyConstraint** startMultiBodyConstraint = 0;
+
+ int numCurConstraints = 0;
+ int numCurMultiBodyConstraints = 0;
+
+ int i;
+
+ //find the first constraint for this island
+
+ for (i = 0; i < m_numConstraints; i++)
+ {
+ if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
+ {
+ startConstraint = &m_sortedConstraints[i];
+ break;
+ }
+ }
+ //count the number of constraints in this island
+ for (; i < m_numConstraints; i++)
+ {
+ if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
+ {
+ numCurConstraints++;
+ }
+ }
+
+ for (i = 0; i < m_numMultiBodyConstraints; i++)
+ {
+ if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
+ {
+ startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
+ break;
+ }
+ }
+ //count the number of multi body constraints in this island
+ for (; i < m_numMultiBodyConstraints; i++)
+ {
+ if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
+ {
+ numCurMultiBodyConstraints++;
+ }
+ }
+
+ //if (m_solverInfo->m_minimumSolverBatchSize<=1)
+ //{
+ // m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
+ //} else
+ {
+ for (i = 0; i < numBodies; i++)
+ {
+ bool isSoftBodyType = (bodies[i]->getInternalType() & btCollisionObject::CO_SOFT_BODY);
+ if (!isSoftBodyType)
+ {
+ m_bodies.push_back(bodies[i]);
+ }
+ else
+ {
+ m_softBodies.push_back(bodies[i]);
+ }
+ }
+ for (i = 0; i < numManifolds; i++)
+ m_manifolds.push_back(manifolds[i]);
+ for (i = 0; i < numCurConstraints; i++)
+ m_constraints.push_back(startConstraint[i]);
+
+ for (i = 0; i < numCurMultiBodyConstraints; i++)
+ m_multiBodyConstraints.push_back(startMultiBodyConstraint[i]);
+
+ if ((m_multiBodyConstraints.size() + m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
+ {
+ processConstraints(islandId);
+ }
+ else
+ {
+ //printf("deferred\n");
+ }
+ }
+ }
+ }
+
+ virtual void processConstraints(int islandId=-1)
+ {
+ btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
+ btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
+ btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
+ btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
+
+ //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
+
+ m_solver->solveMultiBodyGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
+ if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics&1))
+ {
+ m_solver->m_analyticsData.m_islandId = islandId;
+ m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+ }
+ m_bodies.resize(0);
+ m_softBodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
+ m_multiBodyConstraints.resize(0);
+ }
+};
+
+
+#endif /*BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H */
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
index 92d41dfac2..01d5583c2f 100644
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
+++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
@@ -111,6 +111,10 @@ struct btMultibodyLink
btQuaternion m_cachedRotParentToThis; // rotates vectors in parent frame to vectors in local frame
btVector3 m_cachedRVector; // vector from COM of parent to COM of this link, in local frame.
+
+ // predicted verstion
+ btQuaternion m_cachedRotParentToThis_interpolate; // rotates vectors in parent frame to vectors in local frame
+ btVector3 m_cachedRVector_interpolate; // vector from COM of parent to COM of this link, in local frame.
btVector3 m_appliedForce; // In WORLD frame
btVector3 m_appliedTorque; // In WORLD frame
@@ -119,6 +123,7 @@ struct btMultibodyLink
btVector3 m_appliedConstraintTorque; // In WORLD frame
btScalar m_jointPos[7];
+ btScalar m_jointPos_interpolate[7];
//m_jointTorque is the joint torque applied by the user using 'addJointTorque'.
//It gets set to zero after each internal stepSimulation call
@@ -152,6 +157,7 @@ struct btMultibodyLink
m_parent(-1),
m_zeroRotParentToThis(0, 0, 0, 1),
m_cachedRotParentToThis(0, 0, 0, 1),
+ m_cachedRotParentToThis_interpolate(0, 0, 0, 1),
m_collider(0),
m_flags(0),
m_dofCount(0),
@@ -174,6 +180,7 @@ struct btMultibodyLink
m_dVector.setValue(0, 0, 0);
m_eVector.setValue(0, 0, 0);
m_cachedRVector.setValue(0, 0, 0);
+ m_cachedRVector_interpolate.setValue(0, 0, 0);
m_appliedForce.setValue(0, 0, 0);
m_appliedTorque.setValue(0, 0, 0);
m_appliedConstraintForce.setValue(0, 0, 0);
@@ -188,42 +195,43 @@ struct btMultibodyLink
// routine to update m_cachedRotParentToThis and m_cachedRVector
void updateCacheMultiDof(btScalar *pq = 0)
{
- btScalar *pJointPos = (pq ? pq : &m_jointPos[0]);
-
+ btScalar *pJointPos = (pq ? pq : &m_jointPos[0]);
+ btQuaternion& cachedRot = m_cachedRotParentToThis;
+ btVector3& cachedVector = m_cachedRVector;
switch (m_jointType)
{
case eRevolute:
{
- m_cachedRotParentToThis = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
+ cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
break;
}
case ePrismatic:
{
// m_cachedRotParentToThis never changes, so no need to update
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
+ cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
break;
}
case eSpherical:
{
- m_cachedRotParentToThis = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
+ cachedRot = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
break;
}
case ePlanar:
{
- m_cachedRotParentToThis = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
- m_cachedRVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(m_cachedRotParentToThis, m_eVector);
+ cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+ cachedVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(cachedRot, m_eVector);
break;
}
case eFixed:
{
- m_cachedRotParentToThis = m_zeroRotParentToThis;
- m_cachedRVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
+ cachedRot = m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
break;
}
@@ -233,7 +241,60 @@ struct btMultibodyLink
btAssert(0);
}
}
+ m_cachedRotParentToThis_interpolate = m_cachedRotParentToThis;
+ m_cachedRVector_interpolate = m_cachedRVector;
}
+
+ void updateInterpolationCacheMultiDof()
+ {
+ btScalar *pJointPos = &m_jointPos_interpolate[0];
+
+ btQuaternion& cachedRot = m_cachedRotParentToThis_interpolate;
+ btVector3& cachedVector = m_cachedRVector_interpolate;
+ switch (m_jointType)
+ {
+ case eRevolute:
+ {
+ cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
+
+ break;
+ }
+ case ePrismatic:
+ {
+ // m_cachedRotParentToThis never changes, so no need to update
+ cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
+
+ break;
+ }
+ case eSpherical:
+ {
+ cachedRot = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
+
+ break;
+ }
+ case ePlanar:
+ {
+ cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+ cachedVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(cachedRot, m_eVector);
+
+ break;
+ }
+ case eFixed:
+ {
+ cachedRot = m_zeroRotParentToThis;
+ cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
+
+ break;
+ }
+ default:
+ {
+ //invalid type
+ btAssert(0);
+ }
+ }
+ }
};
#endif //BT_MULTIBODY_LINK_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
index ac2fc46ab0..f18c4ea41b 100644
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
+++ b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
@@ -20,7 +20,7 @@ subject to the following restrictions:
#include "btMLCPSolverInterface.h"
#include "btLemkeAlgorithm.h"
-///The btLemkeSolver is based on "Fast Implementation of Lemke's Algorithm for Rigid Body Contact Simulation (John E. Lloyd) "
+///The btLemkeSolver is based on "Fast Implementation of Lemke’s Algorithm for Rigid Body Contact Simulation (John E. Lloyd) "
///It is a slower but more accurate solver. Increase the m_maxLoops for better convergence, at the cost of more CPU time.
///The original implementation of the btLemkeAlgorithm was done by Kilian Grundl from the MBSim team
class btLemkeSolver : public btMLCPSolverInterface
diff --git a/thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h b/thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h
new file mode 100644
index 0000000000..7b225701f6
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h
@@ -0,0 +1,46 @@
+//
+// DeformableBodyInplaceSolverIslandCallback.h
+// BulletSoftBody
+//
+// Created by Xuchen Han on 12/16/19.
+//
+
+#ifndef DeformableBodyInplaceSolverIslandCallback_h
+#define DeformableBodyInplaceSolverIslandCallback_h
+
+struct DeformableBodyInplaceSolverIslandCallback : public MultiBodyInplaceSolverIslandCallback
+{
+ btDeformableMultiBodyConstraintSolver* m_deformableSolver;
+
+ DeformableBodyInplaceSolverIslandCallback(btDeformableMultiBodyConstraintSolver* solver,
+ btDispatcher* dispatcher)
+ : MultiBodyInplaceSolverIslandCallback(solver, dispatcher), m_deformableSolver(solver)
+ {
+ }
+
+
+ virtual void processConstraints(int islandId=-1)
+ {
+ btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
+ btCollisionObject** softBodies = m_softBodies.size() ? &m_softBodies[0] : 0;
+ btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
+ btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
+ btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
+
+ //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
+
+ m_deformableSolver->solveDeformableBodyGroup(bodies, m_bodies.size(), softBodies, m_softBodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
+ if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics&1))
+ {
+ m_deformableSolver->m_analyticsData.m_islandId = islandId;
+ m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+ }
+ m_bodies.resize(0);
+ m_softBodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
+ m_multiBodyConstraints.resize(0);
+ }
+};
+
+#endif /* DeformableBodyInplaceSolverIslandCallback_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btCGProjection.h b/thirdparty/bullet/BulletSoftBody/btCGProjection.h
new file mode 100644
index 0000000000..d047e6d3d9
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btCGProjection.h
@@ -0,0 +1,106 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_CG_PROJECTION_H
+#define BT_CG_PROJECTION_H
+
+#include "btSoftBody.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+
+struct DeformableContactConstraint
+{
+ const btSoftBody::Node* m_node;
+ btAlignedObjectArray<const btSoftBody::RContact*> m_contact;
+ btAlignedObjectArray<btVector3> m_total_normal_dv;
+ btAlignedObjectArray<btVector3> m_total_tangent_dv;
+ btAlignedObjectArray<bool> m_static;
+ btAlignedObjectArray<bool> m_can_be_dynamic;
+
+ DeformableContactConstraint(const btSoftBody::RContact& rcontact): m_node(rcontact.m_node)
+ {
+ append(rcontact);
+ }
+
+ DeformableContactConstraint(): m_node(NULL)
+ {
+ m_contact.push_back(NULL);
+ }
+
+ void append(const btSoftBody::RContact& rcontact)
+ {
+ m_contact.push_back(&rcontact);
+ m_total_normal_dv.push_back(btVector3(0,0,0));
+ m_total_tangent_dv.push_back(btVector3(0,0,0));
+ m_static.push_back(false);
+ m_can_be_dynamic.push_back(true);
+ }
+
+ void replace(const btSoftBody::RContact& rcontact)
+ {
+ m_contact.clear();
+ m_total_normal_dv.clear();
+ m_total_tangent_dv.clear();
+ m_static.clear();
+ m_can_be_dynamic.clear();
+ append(rcontact);
+ }
+
+ ~DeformableContactConstraint()
+ {
+ }
+};
+
+class btCGProjection
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ typedef btAlignedObjectArray<btAlignedObjectArray<btVector3> > TVArrayStack;
+ typedef btAlignedObjectArray<btAlignedObjectArray<btScalar> > TArrayStack;
+ btAlignedObjectArray<btSoftBody *>& m_softBodies;
+ const btScalar& m_dt;
+ // map from node indices to node pointers
+ const btAlignedObjectArray<btSoftBody::Node*>* m_nodes;
+
+ btCGProjection(btAlignedObjectArray<btSoftBody *>& softBodies, const btScalar& dt)
+ : m_softBodies(softBodies)
+ , m_dt(dt)
+ {
+ }
+
+ virtual ~btCGProjection()
+ {
+ }
+
+ // apply the constraints
+ virtual void project(TVStack& x) = 0;
+
+ virtual void setConstraints() = 0;
+
+ // update the constraints
+ virtual btScalar update() = 0;
+
+ virtual void reinitialize(bool nodeUpdated)
+ {
+ }
+
+ virtual void setIndices(const btAlignedObjectArray<btSoftBody::Node*>* nodes)
+ {
+ m_nodes = nodes;
+ }
+};
+
+
+#endif /* btCGProjection_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btConjugateGradient.h b/thirdparty/bullet/BulletSoftBody/btConjugateGradient.h
new file mode 100644
index 0000000000..bd51e584b9
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btConjugateGradient.h
@@ -0,0 +1,158 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_CONJUGATE_GRADIENT_H
+#define BT_CONJUGATE_GRADIENT_H
+#include <iostream>
+#include <cmath>
+#include <limits>
+#include <LinearMath/btAlignedObjectArray.h>
+#include <LinearMath/btVector3.h>
+#include "LinearMath/btQuickprof.h"
+template <class MatrixX>
+class btConjugateGradient
+{
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ TVStack r,p,z,temp;
+ int max_iterations;
+ btScalar tolerance_squared;
+public:
+ btConjugateGradient(const int max_it_in)
+ : max_iterations(max_it_in)
+ {
+ tolerance_squared = 1e-5;
+ }
+
+ virtual ~btConjugateGradient(){}
+
+ // return the number of iterations taken
+ int solve(MatrixX& A, TVStack& x, const TVStack& b, bool verbose = false)
+ {
+ BT_PROFILE("CGSolve");
+ btAssert(x.size() == b.size());
+ reinitialize(b);
+ // r = b - A * x --with assigned dof zeroed out
+ A.multiply(x, temp);
+ r = sub(b, temp);
+ A.project(r);
+ // z = M^(-1) * r
+ A.precondition(r, z);
+ A.project(z);
+ btScalar r_dot_z = dot(z,r);
+ if (r_dot_z <= tolerance_squared) {
+ if (verbose)
+ {
+ std::cout << "Iteration = 0" << std::endl;
+ std::cout << "Two norm of the residual = " << r_dot_z << std::endl;
+ }
+ return 0;
+ }
+ p = z;
+ btScalar r_dot_z_new = r_dot_z;
+ for (int k = 1; k <= max_iterations; k++) {
+ // temp = A*p
+ A.multiply(p, temp);
+ A.project(temp);
+ if (dot(p,temp) < SIMD_EPSILON)
+ {
+ if (verbose)
+ std::cout << "Encountered negative direction in CG!" << std::endl;
+ if (k == 1)
+ {
+ x = b;
+ }
+ return k;
+ }
+ // alpha = r^T * z / (p^T * A * p)
+ btScalar alpha = r_dot_z_new / dot(p, temp);
+ // x += alpha * p;
+ multAndAddTo(alpha, p, x);
+ // r -= alpha * temp;
+ multAndAddTo(-alpha, temp, r);
+ // z = M^(-1) * r
+ A.precondition(r, z);
+ r_dot_z = r_dot_z_new;
+ r_dot_z_new = dot(r,z);
+ if (r_dot_z_new < tolerance_squared) {
+ if (verbose)
+ {
+ std::cout << "ConjugateGradient iterations " << k << std::endl;
+ }
+ return k;
+ }
+
+ btScalar beta = r_dot_z_new/r_dot_z;
+ p = multAndAdd(beta, p, z);
+ }
+ if (verbose)
+ {
+ std::cout << "ConjugateGradient max iterations reached " << max_iterations << std::endl;
+ }
+ return max_iterations;
+ }
+
+ void reinitialize(const TVStack& b)
+ {
+ r.resize(b.size());
+ p.resize(b.size());
+ z.resize(b.size());
+ temp.resize(b.size());
+ }
+
+ TVStack sub(const TVStack& a, const TVStack& b)
+ {
+ // c = a-b
+ btAssert(a.size() == b.size());
+ TVStack c;
+ c.resize(a.size());
+ for (int i = 0; i < a.size(); ++i)
+ {
+ c[i] = a[i] - b[i];
+ }
+ return c;
+ }
+
+ btScalar squaredNorm(const TVStack& a)
+ {
+ return dot(a,a);
+ }
+
+ btScalar dot(const TVStack& a, const TVStack& b)
+ {
+ btScalar ans(0);
+ for (int i = 0; i < a.size(); ++i)
+ ans += a[i].dot(b[i]);
+ return ans;
+ }
+
+ void multAndAddTo(btScalar s, const TVStack& a, TVStack& result)
+ {
+// result += s*a
+ btAssert(a.size() == result.size());
+ for (int i = 0; i < a.size(); ++i)
+ result[i] += s * a[i];
+ }
+
+ TVStack multAndAdd(btScalar s, const TVStack& a, const TVStack& b)
+ {
+ // result = a*s + b
+ TVStack result;
+ result.resize(a.size());
+ for (int i = 0; i < a.size(); ++i)
+ result[i] = s * a[i] + b[i];
+ return result;
+ }
+};
+#endif /* btConjugateGradient_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btConjugateResidual.h b/thirdparty/bullet/BulletSoftBody/btConjugateResidual.h
new file mode 100644
index 0000000000..7b211c4172
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btConjugateResidual.h
@@ -0,0 +1,188 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_CONJUGATE_RESIDUAL_H
+#define BT_CONJUGATE_RESIDUAL_H
+#include <iostream>
+#include <cmath>
+#include <limits>
+#include <LinearMath/btAlignedObjectArray.h>
+#include <LinearMath/btVector3.h>
+#include <LinearMath/btScalar.h>
+#include "LinearMath/btQuickprof.h"
+template <class MatrixX>
+class btConjugateResidual
+{
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ TVStack r,p,z,temp_p, temp_r, best_x;
+ // temp_r = A*r
+ // temp_p = A*p
+ // z = M^(-1) * temp_p = M^(-1) * A * p
+ int max_iterations;
+ btScalar tolerance_squared, best_r;
+public:
+ btConjugateResidual(const int max_it_in)
+ : max_iterations(max_it_in)
+ {
+ tolerance_squared = 1e-2;
+ }
+
+ virtual ~btConjugateResidual(){}
+
+ // return the number of iterations taken
+ int solve(MatrixX& A, TVStack& x, const TVStack& b, bool verbose = false)
+ {
+ BT_PROFILE("CRSolve");
+ btAssert(x.size() == b.size());
+ reinitialize(b);
+ // r = b - A * x --with assigned dof zeroed out
+ A.multiply(x, temp_r); // borrow temp_r here to store A*x
+ r = sub(b, temp_r);
+ // z = M^(-1) * r
+ A.precondition(r, z); // borrow z to store preconditioned r
+ r = z;
+ btScalar residual_norm = norm(r);
+ if (residual_norm <= tolerance_squared) {
+ if (verbose)
+ {
+ std::cout << "Iteration = 0" << std::endl;
+ std::cout << "Two norm of the residual = " << residual_norm << std::endl;
+ }
+ return 0;
+ }
+ p = r;
+ btScalar r_dot_Ar, r_dot_Ar_new;
+ // temp_p = A*p
+ A.multiply(p, temp_p);
+ // temp_r = A*r
+ temp_r = temp_p;
+ r_dot_Ar = dot(r, temp_r);
+ for (int k = 1; k <= max_iterations; k++) {
+ // z = M^(-1) * Ap
+ A.precondition(temp_p, z);
+ // alpha = r^T * A * r / (Ap)^T * M^-1 * Ap)
+ btScalar alpha = r_dot_Ar / dot(temp_p, z);
+ // x += alpha * p;
+ multAndAddTo(alpha, p, x);
+ // r -= alpha * z;
+ multAndAddTo(-alpha, z, r);
+ btScalar norm_r = norm(r);
+ if (norm_r < best_r)
+ {
+ best_x = x;
+ best_r = norm_r;
+ if (norm_r < tolerance_squared) {
+ if (verbose)
+ {
+ std::cout << "ConjugateResidual iterations " << k << std::endl;
+ }
+ return k;
+ }
+ else
+ {
+ if (verbose)
+ {
+ std::cout << "ConjugateResidual iterations " << k << " has residual "<< norm_r << std::endl;
+ }
+ }
+ }
+ // temp_r = A * r;
+ A.multiply(r, temp_r);
+ r_dot_Ar_new = dot(r, temp_r);
+ btScalar beta = r_dot_Ar_new/r_dot_Ar;
+ r_dot_Ar = r_dot_Ar_new;
+ // p = beta*p + r;
+ p = multAndAdd(beta, p, r);
+ // temp_p = beta*temp_p + temp_r;
+ temp_p = multAndAdd(beta, temp_p, temp_r);
+ }
+ if (verbose)
+ {
+ std::cout << "ConjugateResidual max iterations reached " << max_iterations << std::endl;
+ }
+ x = best_x;
+ return max_iterations;
+ }
+
+ void reinitialize(const TVStack& b)
+ {
+ r.resize(b.size());
+ p.resize(b.size());
+ z.resize(b.size());
+ temp_p.resize(b.size());
+ temp_r.resize(b.size());
+ best_x.resize(b.size());
+ best_r = SIMD_INFINITY;
+ }
+
+ TVStack sub(const TVStack& a, const TVStack& b)
+ {
+ // c = a-b
+ btAssert(a.size() == b.size());
+ TVStack c;
+ c.resize(a.size());
+ for (int i = 0; i < a.size(); ++i)
+ {
+ c[i] = a[i] - b[i];
+ }
+ return c;
+ }
+
+ btScalar squaredNorm(const TVStack& a)
+ {
+ return dot(a,a);
+ }
+
+ btScalar norm(const TVStack& a)
+ {
+ btScalar ret = 0;
+ for (int i = 0; i < a.size(); ++i)
+ {
+ for (int d = 0; d < 3; ++d)
+ {
+ ret = btMax(ret, btFabs(a[i][d]));
+ }
+ }
+ return ret;
+ }
+
+ btScalar dot(const TVStack& a, const TVStack& b)
+ {
+ btScalar ans(0);
+ for (int i = 0; i < a.size(); ++i)
+ ans += a[i].dot(b[i]);
+ return ans;
+ }
+
+ void multAndAddTo(btScalar s, const TVStack& a, TVStack& result)
+ {
+ // result += s*a
+ btAssert(a.size() == result.size());
+ for (int i = 0; i < a.size(); ++i)
+ result[i] += s * a[i];
+ }
+
+ TVStack multAndAdd(btScalar s, const TVStack& a, const TVStack& b)
+ {
+ // result = a*s + b
+ TVStack result;
+ result.resize(a.size());
+ for (int i = 0; i < a.size(); ++i)
+ result[i] = s * a[i] + b[i];
+ return result;
+ }
+};
+#endif /* btConjugateResidual_h */
+
diff --git a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
index 8b7ff9abcd..5a79ef86e2 100644
--- a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
@@ -60,7 +60,7 @@ bool btDefaultSoftBodySolver::checkInitialized()
return true;
}
-void btDefaultSoftBodySolver::solveConstraints(float solverdt)
+void btDefaultSoftBodySolver::solveConstraints(btScalar solverdt)
{
// Solve constraints for non-solver softbodies
for (int i = 0; i < m_softBodySet.size(); ++i)
@@ -132,7 +132,7 @@ void btDefaultSoftBodySolver::processCollision(btSoftBody *softBody, const btCol
softBody->defaultCollisionHandler(collisionObjectWrap);
} // btDefaultSoftBodySolver::processCollision
-void btDefaultSoftBodySolver::predictMotion(float timeStep)
+void btDefaultSoftBodySolver::predictMotion(btScalar timeStep)
{
for (int i = 0; i < m_softBodySet.size(); ++i)
{
diff --git a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
index 50bd735165..3965b07c58 100644
--- a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
+++ b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
@@ -46,9 +46,9 @@ public:
virtual void copyBackToSoftBodies(bool bMove = true);
- virtual void solveConstraints(float solverdt);
+ virtual void solveConstraints(btScalar solverdt);
- virtual void predictMotion(float solverdt);
+ virtual void predictMotion(btScalar solverdt);
virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer);
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp
new file mode 100644
index 0000000000..5381ee6265
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp
@@ -0,0 +1,227 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "btDeformableBackwardEulerObjective.h"
+#include "btPreconditioner.h"
+#include "LinearMath/btQuickprof.h"
+
+btDeformableBackwardEulerObjective::btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody *>& softBodies, const TVStack& backup_v)
+: m_softBodies(softBodies)
+, m_projection(softBodies)
+, m_backupVelocity(backup_v)
+, m_implicit(false)
+{
+ m_massPreconditioner = new MassPreconditioner(m_softBodies);
+ m_KKTPreconditioner = new KKTPreconditioner(m_softBodies, m_projection, m_lf, m_dt, m_implicit);
+ m_preconditioner = m_KKTPreconditioner;
+}
+
+btDeformableBackwardEulerObjective::~btDeformableBackwardEulerObjective()
+{
+ delete m_KKTPreconditioner;
+ delete m_massPreconditioner;
+}
+
+void btDeformableBackwardEulerObjective::reinitialize(bool nodeUpdated, btScalar dt)
+{
+ BT_PROFILE("reinitialize");
+ if (dt > 0)
+ {
+ setDt(dt);
+ }
+ if(nodeUpdated)
+ {
+ updateId();
+ }
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ m_lf[i]->reinitialize(nodeUpdated);
+ }
+ m_projection.reinitialize(nodeUpdated);
+// m_preconditioner->reinitialize(nodeUpdated);
+}
+
+void btDeformableBackwardEulerObjective::setDt(btScalar dt)
+{
+ m_dt = dt;
+}
+
+void btDeformableBackwardEulerObjective::multiply(const TVStack& x, TVStack& b) const
+{
+ BT_PROFILE("multiply");
+ // add in the mass term
+ size_t counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ b[counter] = (node.m_im == 0) ? btVector3(0,0,0) : x[counter] / node.m_im;
+ ++counter;
+ }
+ }
+
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ // add damping matrix
+ m_lf[i]->addScaledDampingForceDifferential(-m_dt, x, b);
+ if (m_implicit)
+ {
+ m_lf[i]->addScaledElasticForceDifferential(-m_dt*m_dt, x, b);
+ }
+ }
+ int offset = m_nodes.size();
+ for (int i = offset; i < b.size(); ++i)
+ {
+ b[i].setZero();
+ }
+ // add in the lagrange multiplier terms
+
+ for (int c = 0; c < m_projection.m_lagrangeMultipliers.size(); ++c)
+ {
+ // C^T * lambda
+ const LagrangeMultiplier& lm = m_projection.m_lagrangeMultipliers[c];
+ for (int i = 0; i < lm.m_num_nodes; ++i)
+ {
+ for (int j = 0; j < lm.m_num_constraints; ++j)
+ {
+ b[lm.m_indices[i]] += x[offset+c][j] * lm.m_weights[i] * lm.m_dirs[j];
+ }
+ }
+ // C * x
+ for (int d = 0; d < lm.m_num_constraints; ++d)
+ {
+ for (int i = 0; i < lm.m_num_nodes; ++i)
+ {
+ b[offset+c][d] += lm.m_weights[i] * x[lm.m_indices[i]].dot(lm.m_dirs[d]);
+ }
+ }
+ }
+}
+
+void btDeformableBackwardEulerObjective::updateVelocity(const TVStack& dv)
+{
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ btSoftBody::Node& node = psb->m_nodes[j];
+ node.m_v = m_backupVelocity[node.index] + dv[node.index];
+ }
+ }
+}
+
+void btDeformableBackwardEulerObjective::applyForce(TVStack& force, bool setZero)
+{
+ size_t counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ counter += psb->m_nodes.size();
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ btScalar one_over_mass = (psb->m_nodes[j].m_im == 0) ? 0 : psb->m_nodes[j].m_im;
+ psb->m_nodes[j].m_v += one_over_mass * force[counter++];
+ }
+ }
+ if (setZero)
+ {
+ for (int i = 0; i < force.size(); ++i)
+ force[i].setZero();
+ }
+}
+
+void btDeformableBackwardEulerObjective::computeResidual(btScalar dt, TVStack &residual)
+{
+ BT_PROFILE("computeResidual");
+ // add implicit force
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ if (m_implicit)
+ {
+ m_lf[i]->addScaledForces(dt, residual);
+ }
+ else
+ {
+ m_lf[i]->addScaledDampingForce(dt, residual);
+ }
+ }
+// m_projection.project(residual);
+}
+
+btScalar btDeformableBackwardEulerObjective::computeNorm(const TVStack& residual) const
+{
+ btScalar mag = 0;
+ for (int i = 0; i < residual.size(); ++i)
+ {
+ mag += residual[i].length2();
+ }
+ return std::sqrt(mag);
+}
+
+btScalar btDeformableBackwardEulerObjective::totalEnergy(btScalar dt)
+{
+ btScalar e = 0;
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ e += m_lf[i]->totalEnergy(dt);
+ }
+ return e;
+}
+
+void btDeformableBackwardEulerObjective::applyExplicitForce(TVStack& force)
+{
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ m_softBodies[i]->advanceDeformation();
+ }
+
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ m_lf[i]->addScaledExplicitForce(m_dt, force);
+ }
+ applyForce(force, true);
+}
+
+void btDeformableBackwardEulerObjective::initialGuess(TVStack& dv, const TVStack& residual)
+{
+ size_t counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ dv[counter] = psb->m_nodes[j].m_im * residual[counter];
+ ++counter;
+ }
+ }
+}
+
+//set constraints as projections
+void btDeformableBackwardEulerObjective::setConstraints(const btContactSolverInfo& infoGlobal)
+{
+ m_projection.setConstraints(infoGlobal);
+}
+
+void btDeformableBackwardEulerObjective::applyDynamicFriction(TVStack& r)
+{
+ m_projection.applyDynamicFriction(r);
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h b/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h
new file mode 100644
index 0000000000..86579e71ac
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h
@@ -0,0 +1,173 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_BACKWARD_EULER_OBJECTIVE_H
+#define BT_BACKWARD_EULER_OBJECTIVE_H
+//#include "btConjugateGradient.h"
+#include "btDeformableLagrangianForce.h"
+#include "btDeformableMassSpringForce.h"
+#include "btDeformableGravityForce.h"
+#include "btDeformableCorotatedForce.h"
+#include "btDeformableMousePickingForce.h"
+#include "btDeformableLinearElasticityForce.h"
+#include "btDeformableNeoHookeanForce.h"
+#include "btDeformableContactProjection.h"
+#include "btPreconditioner.h"
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include "LinearMath/btQuickprof.h"
+
+class btDeformableBackwardEulerObjective
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btScalar m_dt;
+ btAlignedObjectArray<btDeformableLagrangianForce*> m_lf;
+ btAlignedObjectArray<btSoftBody *>& m_softBodies;
+ Preconditioner* m_preconditioner;
+ btDeformableContactProjection m_projection;
+ const TVStack& m_backupVelocity;
+ btAlignedObjectArray<btSoftBody::Node* > m_nodes;
+ bool m_implicit;
+ MassPreconditioner* m_massPreconditioner;
+ KKTPreconditioner* m_KKTPreconditioner;
+
+ btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody *>& softBodies, const TVStack& backup_v);
+
+ virtual ~btDeformableBackwardEulerObjective();
+
+ void initialize(){}
+
+ // compute the rhs for CG solve, i.e, add the dt scaled implicit force to residual
+ void computeResidual(btScalar dt, TVStack& residual);
+
+ // add explicit force to the velocity
+ void applyExplicitForce(TVStack& force);
+
+ // apply force to velocity and optionally reset the force to zero
+ void applyForce(TVStack& force, bool setZero);
+
+ // compute the norm of the residual
+ btScalar computeNorm(const TVStack& residual) const;
+
+ // compute one step of the solve (there is only one solve if the system is linear)
+ void computeStep(TVStack& dv, const TVStack& residual, const btScalar& dt);
+
+ // perform A*x = b
+ void multiply(const TVStack& x, TVStack& b) const;
+
+ // set initial guess for CG solve
+ void initialGuess(TVStack& dv, const TVStack& residual);
+
+ // reset data structure and reset dt
+ void reinitialize(bool nodeUpdated, btScalar dt);
+
+ void setDt(btScalar dt);
+
+ // add friction force to residual
+ void applyDynamicFriction(TVStack& r);
+
+ // add dv to velocity
+ void updateVelocity(const TVStack& dv);
+
+ //set constraints as projections
+ void setConstraints(const btContactSolverInfo& infoGlobal);
+
+ // update the projections and project the residual
+ void project(TVStack& r)
+ {
+ BT_PROFILE("project");
+ m_projection.project(r);
+ }
+
+ // perform precondition M^(-1) x = b
+ void precondition(const TVStack& x, TVStack& b)
+ {
+ m_preconditioner->operator()(x,b);
+ }
+
+ // reindex all the vertices
+ virtual void updateId()
+ {
+ size_t node_id = 0;
+ size_t face_id = 0;
+ m_nodes.clear();
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].index = node_id;
+ m_nodes.push_back(&psb->m_nodes[j]);
+ ++node_id;
+ }
+ for (int j = 0; j < psb->m_faces.size(); ++j)
+ {
+ psb->m_faces[j].m_index = face_id;
+ ++face_id;
+ }
+ }
+ }
+
+ const btAlignedObjectArray<btSoftBody::Node*>* getIndices() const
+ {
+ return &m_nodes;
+ }
+
+ void setImplicit(bool implicit)
+ {
+ m_implicit = implicit;
+ }
+
+ // Calculate the total potential energy in the system
+ btScalar totalEnergy(btScalar dt);
+
+ void addLagrangeMultiplier(const TVStack& vec, TVStack& extended_vec)
+ {
+ extended_vec.resize(vec.size() + m_projection.m_lagrangeMultipliers.size());
+ for (int i = 0; i < vec.size(); ++i)
+ {
+ extended_vec[i] = vec[i];
+ }
+ int offset = vec.size();
+ for (int i = 0; i < m_projection.m_lagrangeMultipliers.size(); ++i)
+ {
+ extended_vec[offset + i].setZero();
+ }
+ }
+
+ void addLagrangeMultiplierRHS(const TVStack& residual, const TVStack& m_dv, TVStack& extended_residual)
+ {
+ extended_residual.resize(residual.size() + m_projection.m_lagrangeMultipliers.size());
+ for (int i = 0; i < residual.size(); ++i)
+ {
+ extended_residual[i] = residual[i];
+ }
+ int offset = residual.size();
+ for (int i = 0; i < m_projection.m_lagrangeMultipliers.size(); ++i)
+ {
+ const LagrangeMultiplier& lm = m_projection.m_lagrangeMultipliers[i];
+ extended_residual[offset + i].setZero();
+ for (int d = 0; d < lm.m_num_constraints; ++d)
+ {
+ for (int n = 0; n < lm.m_num_nodes; ++n)
+ {
+ extended_residual[offset + i][d] += lm.m_weights[n] * m_dv[lm.m_indices[n]].dot(lm.m_dirs[d]);
+ }
+ }
+ }
+ }
+};
+
+#endif /* btBackwardEulerObjective_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp
new file mode 100644
index 0000000000..132699c54f
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp
@@ -0,0 +1,485 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include <stdio.h>
+#include <limits>
+#include "btDeformableBodySolver.h"
+#include "btSoftBodyInternals.h"
+#include "LinearMath/btQuickprof.h"
+static const int kMaxConjugateGradientIterations = 50;
+btDeformableBodySolver::btDeformableBodySolver()
+: m_numNodes(0)
+, m_cg(kMaxConjugateGradientIterations)
+, m_cr(kMaxConjugateGradientIterations)
+, m_maxNewtonIterations(5)
+, m_newtonTolerance(1e-4)
+, m_lineSearch(false)
+, m_useProjection(false)
+{
+ m_objective = new btDeformableBackwardEulerObjective(m_softBodies, m_backupVelocity);
+}
+
+btDeformableBodySolver::~btDeformableBodySolver()
+{
+ delete m_objective;
+}
+
+void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
+{
+ BT_PROFILE("solveDeformableConstraints");
+ if (!m_implicit)
+ {
+ m_objective->computeResidual(solverdt, m_residual);
+ m_objective->applyDynamicFriction(m_residual);
+ if (m_useProjection)
+ {
+ computeStep(m_dv, m_residual);
+ }
+ else
+ {
+ TVStack rhs, x;
+ m_objective->addLagrangeMultiplierRHS(m_residual, m_dv, rhs);
+ m_objective->addLagrangeMultiplier(m_dv, x);
+ m_objective->m_preconditioner->reinitialize(true);
+ computeStep(x, rhs);
+ for (int i = 0; i<m_dv.size(); ++i)
+ {
+ m_dv[i] = x[i];
+ }
+ }
+ updateVelocity();
+ }
+ else
+ {
+ for (int i = 0; i < m_maxNewtonIterations; ++i)
+ {
+ updateState();
+ // add the inertia term in the residual
+ int counter = 0;
+ for (int k = 0; k < m_softBodies.size(); ++k)
+ {
+ btSoftBody* psb = m_softBodies[k];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ if (psb->m_nodes[j].m_im > 0)
+ {
+ m_residual[counter] = (-1./psb->m_nodes[j].m_im) * m_dv[counter];
+ }
+ ++counter;
+ }
+ }
+
+ m_objective->computeResidual(solverdt, m_residual);
+ if (m_objective->computeNorm(m_residual) < m_newtonTolerance && i > 0)
+ {
+ break;
+ }
+ // todo xuchenhan@: this really only needs to be calculated once
+ m_objective->applyDynamicFriction(m_residual);
+ if (m_lineSearch)
+ {
+ btScalar inner_product = computeDescentStep(m_ddv,m_residual);
+ btScalar alpha = 0.01, beta = 0.5; // Boyd & Vandenberghe suggested alpha between 0.01 and 0.3, beta between 0.1 to 0.8
+ btScalar scale = 2;
+ btScalar f0 = m_objective->totalEnergy(solverdt)+kineticEnergy(), f1, f2;
+ backupDv();
+ do {
+ scale *= beta;
+ if (scale < 1e-8) {
+ return;
+ }
+ updateEnergy(scale);
+ f1 = m_objective->totalEnergy(solverdt)+kineticEnergy();
+ f2 = f0 - alpha * scale * inner_product;
+ } while (!(f1 < f2+SIMD_EPSILON)); // if anything here is nan then the search continues
+ revertDv();
+ updateDv(scale);
+ }
+ else
+ {
+ computeStep(m_ddv, m_residual);
+ updateDv();
+ }
+ for (int j = 0; j < m_numNodes; ++j)
+ {
+ m_ddv[j].setZero();
+ m_residual[j].setZero();
+ }
+ }
+ updateVelocity();
+ }
+}
+
+btScalar btDeformableBodySolver::kineticEnergy()
+{
+ btScalar ke = 0;
+ for (int i = 0; i < m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size();++j)
+ {
+ btSoftBody::Node& node = psb->m_nodes[j];
+ if (node.m_im > 0)
+ {
+ ke += m_dv[node.index].length2() * 0.5 / node.m_im;
+ }
+ }
+ }
+ return ke;
+}
+
+void btDeformableBodySolver::backupDv()
+{
+ m_backup_dv.resize(m_dv.size());
+ for (int i = 0; i<m_backup_dv.size(); ++i)
+ {
+ m_backup_dv[i] = m_dv[i];
+ }
+}
+
+void btDeformableBodySolver::revertDv()
+{
+ for (int i = 0; i<m_backup_dv.size(); ++i)
+ {
+ m_dv[i] = m_backup_dv[i];
+ }
+}
+
+void btDeformableBodySolver::updateEnergy(btScalar scale)
+{
+ for (int i = 0; i<m_dv.size(); ++i)
+ {
+ m_dv[i] = m_backup_dv[i] + scale * m_ddv[i];
+ }
+ updateState();
+}
+
+
+btScalar btDeformableBodySolver::computeDescentStep(TVStack& ddv, const TVStack& residual, bool verbose)
+{
+ m_cg.solve(*m_objective, ddv, residual, false);
+ btScalar inner_product = m_cg.dot(residual, m_ddv);
+ btScalar res_norm = m_objective->computeNorm(residual);
+ btScalar tol = 1e-5 * res_norm * m_objective->computeNorm(m_ddv);
+ if (inner_product < -tol)
+ {
+ if (verbose)
+ {
+ std::cout << "Looking backwards!" << std::endl;
+ }
+ for (int i = 0; i < m_ddv.size();++i)
+ {
+ m_ddv[i] = -m_ddv[i];
+ }
+ inner_product = -inner_product;
+ }
+ else if (std::abs(inner_product) < tol)
+ {
+ if (verbose)
+ {
+ std::cout << "Gradient Descent!" << std::endl;
+ }
+ btScalar scale = m_objective->computeNorm(m_ddv) / res_norm;
+ for (int i = 0; i < m_ddv.size();++i)
+ {
+ m_ddv[i] = scale * residual[i];
+ }
+ inner_product = scale * res_norm * res_norm;
+ }
+ return inner_product;
+}
+
+void btDeformableBodySolver::updateState()
+{
+ updateVelocity();
+ updateTempPosition();
+}
+
+void btDeformableBodySolver::updateDv(btScalar scale)
+{
+ for (int i = 0; i < m_numNodes; ++i)
+ {
+ m_dv[i] += scale * m_ddv[i];
+ }
+}
+
+void btDeformableBodySolver::computeStep(TVStack& ddv, const TVStack& residual)
+{
+ if (m_useProjection)
+ m_cg.solve(*m_objective, ddv, residual, false);
+ else
+ m_cr.solve(*m_objective, ddv, residual, false);
+}
+
+void btDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody *>& softBodies, btScalar dt)
+{
+ m_softBodies.copyFromArray(softBodies);
+ bool nodeUpdated = updateNodes();
+
+ if (nodeUpdated)
+ {
+ m_dv.resize(m_numNodes, btVector3(0,0,0));
+ m_ddv.resize(m_numNodes, btVector3(0,0,0));
+ m_residual.resize(m_numNodes, btVector3(0,0,0));
+ m_backupVelocity.resize(m_numNodes, btVector3(0,0,0));
+ }
+
+ // need to setZero here as resize only set value for newly allocated items
+ for (int i = 0; i < m_numNodes; ++i)
+ {
+ m_dv[i].setZero();
+ m_ddv[i].setZero();
+ m_residual[i].setZero();
+ }
+
+ m_dt = dt;
+ m_objective->reinitialize(nodeUpdated, dt);
+ updateSoftBodies();
+}
+
+void btDeformableBodySolver::setConstraints(const btContactSolverInfo& infoGlobal)
+{
+ BT_PROFILE("setConstraint");
+ m_objective->setConstraints(infoGlobal);
+}
+
+btScalar btDeformableBodySolver::solveContactConstraints(btCollisionObject** deformableBodies,int numDeformableBodies, const btContactSolverInfo& infoGlobal)
+{
+ BT_PROFILE("solveContactConstraints");
+ btScalar maxSquaredResidual = m_objective->m_projection.update(deformableBodies,numDeformableBodies, infoGlobal);
+ return maxSquaredResidual;
+}
+
+void btDeformableBodySolver::splitImpulseSetup(const btContactSolverInfo& infoGlobal)
+{
+ m_objective->m_projection.splitImpulseSetup(infoGlobal);
+}
+
+void btDeformableBodySolver::updateVelocity()
+{
+ int counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ psb->m_maxSpeedSquared = 0;
+ if (!psb->isActive())
+ {
+ counter += psb->m_nodes.size();
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ // set NaN to zero;
+ if (m_dv[counter] != m_dv[counter])
+ {
+ m_dv[counter].setZero();
+ }
+ psb->m_nodes[j].m_v = m_backupVelocity[counter]+m_dv[counter];
+ psb->m_maxSpeedSquared = btMax(psb->m_maxSpeedSquared, psb->m_nodes[j].m_v.length2());
+ ++counter;
+ }
+ }
+}
+
+void btDeformableBodySolver::updateTempPosition()
+{
+ int counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ counter += psb->m_nodes.size();
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + m_dt * psb->m_nodes[j].m_v;
+ ++counter;
+ }
+ psb->updateDeformation();
+ }
+}
+
+void btDeformableBodySolver::backupVelocity()
+{
+ int counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ m_backupVelocity[counter++] = psb->m_nodes[j].m_v;
+ }
+ }
+}
+
+void btDeformableBodySolver::setupDeformableSolve(bool implicit)
+{
+ int counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ counter += psb->m_nodes.size();
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ if (implicit)
+ {
+ if ((psb->m_nodes[j].m_v - m_backupVelocity[counter]).norm() < SIMD_EPSILON)
+ m_dv[counter] = psb->m_nodes[j].m_v - m_backupVelocity[counter];
+ else
+ m_dv[counter] = psb->m_nodes[j].m_v - psb->m_nodes[j].m_vn;
+ m_backupVelocity[counter] = psb->m_nodes[j].m_vn;
+ }
+ else
+ {
+ m_dv[counter] = psb->m_nodes[j].m_v - m_backupVelocity[counter];
+ }
+ psb->m_nodes[j].m_v = m_backupVelocity[counter];
+ ++counter;
+ }
+ }
+}
+
+void btDeformableBodySolver::revertVelocity()
+{
+ int counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_v = m_backupVelocity[counter++];
+ }
+ }
+}
+
+bool btDeformableBodySolver::updateNodes()
+{
+ int numNodes = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ numNodes += m_softBodies[i]->m_nodes.size();
+ if (numNodes != m_numNodes)
+ {
+ m_numNodes = numNodes;
+ return true;
+ }
+ return false;
+}
+
+
+void btDeformableBodySolver::predictMotion(btScalar solverdt)
+{
+ // apply explicit forces to velocity
+ m_objective->applyExplicitForce(m_residual);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody *psb = m_softBodies[i];
+
+ if (psb->isActive())
+ {
+ // predict motion for collision detection
+ predictDeformableMotion(psb, solverdt);
+ }
+ }
+}
+
+void btDeformableBodySolver::predictDeformableMotion(btSoftBody* psb, btScalar dt)
+{
+ BT_PROFILE("btDeformableBodySolver::predictDeformableMotion");
+ int i, ni;
+
+ /* Update */
+ if (psb->m_bUpdateRtCst)
+ {
+ psb->m_bUpdateRtCst = false;
+ psb->updateConstants();
+ psb->m_fdbvt.clear();
+ if (psb->m_cfg.collisions & btSoftBody::fCollision::SDF_RD)
+ {
+ psb->initializeFaceTree();
+ }
+ }
+
+ /* Prepare */
+ psb->m_sst.sdt = dt * psb->m_cfg.timescale;
+ psb->m_sst.isdt = 1 / psb->m_sst.sdt;
+ psb->m_sst.velmrg = psb->m_sst.sdt * 3;
+ psb->m_sst.radmrg = psb->getCollisionShape()->getMargin();
+ psb->m_sst.updmrg = psb->m_sst.radmrg * (btScalar)0.25;
+ /* Bounds */
+ psb->updateBounds();
+
+ /* Integrate */
+ // do not allow particles to move more than the bounding box size
+ btScalar max_v = (psb->m_bounds[1]-psb->m_bounds[0]).norm() / dt;
+ for (i = 0, ni = psb->m_nodes.size(); i < ni; ++i)
+ {
+ btSoftBody::Node& n = psb->m_nodes[i];
+ // apply drag
+ n.m_v *= (1 - psb->m_cfg.drag);
+ // scale velocity back
+ if (n.m_v.norm() > max_v)
+ {
+ n.m_v.safeNormalize();
+ n.m_v *= max_v;
+ }
+ n.m_q = n.m_x + n.m_v * dt;
+ n.m_penetration = 0;
+ }
+
+ /* Nodes */
+ psb->updateNodeTree(true, true);
+ if (!psb->m_fdbvt.empty())
+ {
+ psb->updateFaceTree(true, true);
+ }
+ /* Clear contacts */
+ psb->m_nodeRigidContacts.resize(0);
+ psb->m_faceRigidContacts.resize(0);
+ psb->m_faceNodeContacts.resize(0);
+ /* Optimize dbvt's */
+// psb->m_ndbvt.optimizeIncremental(1);
+// psb->m_fdbvt.optimizeIncremental(1);
+}
+
+
+void btDeformableBodySolver::updateSoftBodies()
+{
+ BT_PROFILE("updateSoftBodies");
+ for (int i = 0; i < m_softBodies.size(); i++)
+ {
+ btSoftBody *psb = (btSoftBody *)m_softBodies[i];
+ if (psb->isActive())
+ {
+ psb->updateNormals();
+ }
+ }
+}
+
+void btDeformableBodySolver::setImplicit(bool implicit)
+{
+ m_implicit = implicit;
+ m_objective->setImplicit(implicit);
+}
+
+void btDeformableBodySolver::setLineSearch(bool lineSearch)
+{
+ m_lineSearch = lineSearch;
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h b/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h
new file mode 100644
index 0000000000..d4e5f4c603
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h
@@ -0,0 +1,162 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_DEFORMABLE_BODY_SOLVERS_H
+#define BT_DEFORMABLE_BODY_SOLVERS_H
+
+
+#include "btSoftBodySolvers.h"
+#include "btDeformableBackwardEulerObjective.h"
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+#include "btConjugateResidual.h"
+#include "btConjugateGradient.h"
+struct btCollisionObjectWrapper;
+class btDeformableBackwardEulerObjective;
+class btDeformableMultiBodyDynamicsWorld;
+
+class btDeformableBodySolver : public btSoftBodySolver
+{
+ typedef btAlignedObjectArray<btVector3> TVStack;
+protected:
+ int m_numNodes; // total number of deformable body nodes
+ TVStack m_dv; // v_{n+1} - v_n
+ TVStack m_backup_dv; // backed up dv
+ TVStack m_ddv; // incremental dv
+ TVStack m_residual; // rhs of the linear solve
+ btAlignedObjectArray<btSoftBody *> m_softBodies; // all deformable bodies
+ TVStack m_backupVelocity; // backed up v, equals v_n for implicit, equals v_{n+1}^* for explicit
+ btScalar m_dt; // dt
+ btConjugateGradient<btDeformableBackwardEulerObjective> m_cg; // CG solver
+ btConjugateResidual<btDeformableBackwardEulerObjective> m_cr; // CR solver
+ bool m_implicit; // use implicit scheme if true, explicit scheme if false
+ int m_maxNewtonIterations; // max number of newton iterations
+ btScalar m_newtonTolerance; // stop newton iterations if f(x) < m_newtonTolerance
+ bool m_lineSearch; // If true, use newton's method with line search under implicit scheme
+public:
+ // handles data related to objective function
+ btDeformableBackwardEulerObjective* m_objective;
+ bool m_useProjection;
+
+ btDeformableBodySolver();
+
+ virtual ~btDeformableBodySolver();
+
+ virtual SolverTypes getSolverType() const
+ {
+ return DEFORMABLE_SOLVER;
+ }
+
+ // update soft body normals
+ virtual void updateSoftBodies();
+
+ virtual btScalar solveContactConstraints(btCollisionObject** deformableBodies,int numDeformableBodies, const btContactSolverInfo& infoGlobal);
+
+ // solve the momentum equation
+ virtual void solveDeformableConstraints(btScalar solverdt);
+
+ // set up the position error in split impulse
+ void splitImpulseSetup(const btContactSolverInfo& infoGlobal);
+
+ // resize/clear data structures
+ void reinitialize(const btAlignedObjectArray<btSoftBody *>& softBodies, btScalar dt);
+
+ // set up contact constraints
+ void setConstraints(const btContactSolverInfo& infoGlobal);
+
+ // add in elastic forces and gravity to obtain v_{n+1}^* and calls predictDeformableMotion
+ virtual void predictMotion(btScalar solverdt);
+
+ // move to temporary position x_{n+1}^* = x_n + dt * v_{n+1}^*
+ // x_{n+1}^* is stored in m_q
+ void predictDeformableMotion(btSoftBody* psb, btScalar dt);
+
+ // save the current velocity to m_backupVelocity
+ void backupVelocity();
+
+ // set m_dv and m_backupVelocity to desired value to prepare for momentum solve
+ void setupDeformableSolve(bool implicit);
+
+ // set the current velocity to that backed up in m_backupVelocity
+ void revertVelocity();
+
+ // set velocity to m_dv + m_backupVelocity
+ void updateVelocity();
+
+ // update the node count
+ bool updateNodes();
+
+ // calculate the change in dv resulting from the momentum solve
+ void computeStep(TVStack& ddv, const TVStack& residual);
+
+ // calculate the change in dv resulting from the momentum solve when line search is turned on
+ btScalar computeDescentStep(TVStack& ddv, const TVStack& residual, bool verbose=false);
+
+ virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer) {}
+
+ // process collision between deformable and rigid
+ virtual void processCollision(btSoftBody * softBody, const btCollisionObjectWrapper * collisionObjectWrap)
+ {
+ softBody->defaultCollisionHandler(collisionObjectWrap);
+ }
+
+ // process collision between deformable and deformable
+ virtual void processCollision(btSoftBody * softBody, btSoftBody * otherSoftBody) {
+ softBody->defaultCollisionHandler(otherSoftBody);
+ }
+
+ // If true, implicit time stepping scheme is used.
+ // Otherwise, explicit time stepping scheme is used
+ void setImplicit(bool implicit);
+
+ // If true, newton's method with line search is used when implicit time stepping scheme is turned on
+ void setLineSearch(bool lineSearch);
+
+ // set temporary position x^* = x_n + dt * v
+ // update the deformation gradient at position x^*
+ void updateState();
+
+ // set dv = dv + scale * ddv
+ void updateDv(btScalar scale = 1);
+
+ // set temporary position x^* = x_n + dt * v^*
+ void updateTempPosition();
+
+ // save the current dv to m_backup_dv;
+ void backupDv();
+
+ // set dv to the backed-up value
+ void revertDv();
+
+ // set dv = dv + scale * ddv
+ // set v^* = v_n + dv
+ // set temporary position x^* = x_n + dt * v^*
+ // update the deformation gradient at position x^*
+ void updateEnergy(btScalar scale);
+
+ // calculates the appropriately scaled kinetic energy in the system, which is
+ // 1/2 * dv^T * M * dv
+ // used in line search
+ btScalar kineticEnergy();
+
+ // unused functions
+ virtual void optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate = false){}
+ virtual void solveConstraints(btScalar dt){}
+ virtual bool checkInitialized(){return true;}
+ virtual void copyBackToSoftBodies(bool bMove = true) {}
+};
+
+#endif /* btDeformableBodySolver_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp
new file mode 100644
index 0000000000..2864446de6
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp
@@ -0,0 +1,575 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "btDeformableContactConstraint.h"
+/* ================ Deformable Node Anchor =================== */
+btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& a, const btContactSolverInfo& infoGlobal)
+: m_anchor(&a)
+, btDeformableContactConstraint(a.m_cti.m_normal, infoGlobal)
+{
+}
+
+btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other)
+: m_anchor(other.m_anchor)
+, btDeformableContactConstraint(other)
+{
+}
+
+btVector3 btDeformableNodeAnchorConstraint::getVa() const
+{
+ const btSoftBody::sCti& cti = m_anchor->m_cti;
+ btVector3 va(0, 0, 0);
+ if (cti.m_colObj->hasContactResponse())
+ {
+ btRigidBody* rigidCol = 0;
+ btMultiBodyLinkCollider* multibodyLinkCol = 0;
+
+ // grab the velocity of the rigid body
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ va = rigidCol ? (rigidCol->getVelocityInLocalPoint(m_anchor->m_c1)) : btVector3(0, 0, 0);
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ const btScalar* J_n = &m_anchor->jacobianData_normal.m_jacobians[0];
+ const btScalar* J_t1 = &m_anchor->jacobianData_t1.m_jacobians[0];
+ const btScalar* J_t2 = &m_anchor->jacobianData_t2.m_jacobians[0];
+ const btScalar* local_v = multibodyLinkCol->m_multiBody->getVelocityVector();
+ const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
+ // add in the normal component of the va
+ btScalar vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_n[k];
+ }
+ va = cti.m_normal * vel;
+ // add in the tangential components of the va
+ vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_t1[k];
+ }
+ va += m_anchor->t1 * vel;
+ vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_t2[k];
+ }
+ va += m_anchor->t2 * vel;
+ }
+ }
+ }
+ return va;
+}
+
+btScalar btDeformableNodeAnchorConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
+{
+ const btSoftBody::sCti& cti = m_anchor->m_cti;
+ btVector3 va = getVa();
+ btVector3 vb = getVb();
+ btVector3 vr = (vb - va);
+ // + (m_anchor->m_node->m_x - cti.m_colObj->getWorldTransform() * m_anchor->m_local) * 10.0
+ const btScalar dn = btDot(vr, vr);
+ // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
+ btScalar residualSquare = dn*dn;
+ btVector3 impulse = m_anchor->m_c0 * vr;
+ // apply impulse to deformable nodes involved and change their velocities
+ applyImpulse(impulse);
+
+ // apply impulse to the rigid/multibodies involved and change their velocities
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ btRigidBody* rigidCol = 0;
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ if (rigidCol)
+ {
+ rigidCol->applyImpulse(impulse, m_anchor->m_c1);
+ }
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ btMultiBodyLinkCollider* multibodyLinkCol = 0;
+ multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ const btScalar* deltaV_normal = &m_anchor->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ // apply normal component of the impulse
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, impulse.dot(cti.m_normal));
+ // apply tangential component of the impulse
+ const btScalar* deltaV_t1 = &m_anchor->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, impulse.dot(m_anchor->t1));
+ const btScalar* deltaV_t2 = &m_anchor->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, impulse.dot(m_anchor->t2));
+ }
+ }
+ return residualSquare;
+}
+
+btVector3 btDeformableNodeAnchorConstraint::getVb() const
+{
+ return m_anchor->m_node->m_v;
+}
+
+void btDeformableNodeAnchorConstraint::applyImpulse(const btVector3& impulse)
+{
+ btVector3 dv = impulse * m_anchor->m_c2;
+ m_anchor->m_node->m_v -= dv;
+}
+
+/* ================ Deformable vs. Rigid =================== */
+btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c, const btContactSolverInfo& infoGlobal)
+: m_contact(&c)
+, btDeformableContactConstraint(c.m_cti.m_normal, infoGlobal)
+{
+ m_total_normal_dv.setZero();
+ m_total_tangent_dv.setZero();
+ // The magnitude of penetration is the depth of penetration.
+ m_penetration = c.m_cti.m_offset;
+// m_penetration = btMin(btScalar(0),c.m_cti.m_offset);
+}
+
+btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other)
+: m_contact(other.m_contact)
+, btDeformableContactConstraint(other)
+, m_penetration(other.m_penetration)
+{
+ m_total_normal_dv = other.m_total_normal_dv;
+ m_total_tangent_dv = other.m_total_tangent_dv;
+}
+
+
+btVector3 btDeformableRigidContactConstraint::getVa() const
+{
+ const btSoftBody::sCti& cti = m_contact->m_cti;
+ btVector3 va(0, 0, 0);
+ if (cti.m_colObj->hasContactResponse())
+ {
+ btRigidBody* rigidCol = 0;
+ btMultiBodyLinkCollider* multibodyLinkCol = 0;
+
+ // grab the velocity of the rigid body
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ va = rigidCol ? (rigidCol->getVelocityInLocalPoint(m_contact->m_c1)) : btVector3(0, 0, 0);
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ const btScalar* J_n = &m_contact->jacobianData_normal.m_jacobians[0];
+ const btScalar* J_t1 = &m_contact->jacobianData_t1.m_jacobians[0];
+ const btScalar* J_t2 = &m_contact->jacobianData_t2.m_jacobians[0];
+ const btScalar* local_v = multibodyLinkCol->m_multiBody->getVelocityVector();
+ const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
+ // add in the normal component of the va
+ btScalar vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_n[k];
+ }
+ va = cti.m_normal * vel;
+ // add in the tangential components of the va
+ vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_t1[k];
+ }
+ va += m_contact->t1 * vel;
+ vel = 0.0;
+ for (int k = 0; k < ndof; ++k)
+ {
+ vel += (local_v[k]+local_dv[k]) * J_t2[k];
+ }
+ va += m_contact->t2 * vel;
+ }
+ }
+ }
+ return va;
+}
+
+btScalar btDeformableRigidContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
+{
+ const btSoftBody::sCti& cti = m_contact->m_cti;
+ btVector3 va = getVa();
+ btVector3 vb = getVb();
+ btVector3 vr = vb - va;
+ btScalar dn = btDot(vr, cti.m_normal) + m_penetration * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep;
+ // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
+ btScalar residualSquare = dn*dn;
+ btVector3 impulse = m_contact->m_c0 * (vr + m_penetration * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep * cti.m_normal) ;
+ const btVector3 impulse_normal = m_contact->m_c0 * (cti.m_normal * dn);
+ btVector3 impulse_tangent = impulse - impulse_normal;
+ btVector3 old_total_tangent_dv = m_total_tangent_dv;
+ // m_c2 is the inverse mass of the deformable node/face
+ m_total_normal_dv -= impulse_normal * m_contact->m_c2;
+ m_total_tangent_dv -= impulse_tangent * m_contact->m_c2;
+
+ if (m_total_normal_dv.dot(cti.m_normal) < 0)
+ {
+ // separating in the normal direction
+ m_static = false;
+ m_total_tangent_dv = btVector3(0,0,0);
+ impulse_tangent.setZero();
+ }
+ else
+ {
+ if (m_total_normal_dv.norm() * m_contact->m_c3 < m_total_tangent_dv.norm())
+ {
+ // dynamic friction
+ // with dynamic friction, the impulse are still applied to the two objects colliding, however, it does not pose a constraint in the cg solve, hence the change to dv merely serves to update velocity in the contact iterations.
+ m_static = false;
+ if (m_total_tangent_dv.safeNorm() < SIMD_EPSILON)
+ {
+ m_total_tangent_dv = btVector3(0,0,0);
+ }
+ else
+ {
+ m_total_tangent_dv = m_total_tangent_dv.normalized() * m_total_normal_dv.safeNorm() * m_contact->m_c3;
+ }
+ impulse_tangent = -btScalar(1)/m_contact->m_c2 * (m_total_tangent_dv - old_total_tangent_dv);
+ }
+ else
+ {
+ // static friction
+ m_static = true;
+ }
+ }
+ impulse = impulse_normal + impulse_tangent;
+ // apply impulse to deformable nodes involved and change their velocities
+ applyImpulse(impulse);
+ if (residualSquare < 1e-7)
+ return residualSquare;
+ // apply impulse to the rigid/multibodies involved and change their velocities
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ btRigidBody* rigidCol = 0;
+ rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+ if (rigidCol)
+ {
+ rigidCol->applyImpulse(impulse, m_contact->m_c1);
+ }
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ btMultiBodyLinkCollider* multibodyLinkCol = 0;
+ multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ const btScalar* deltaV_normal = &m_contact->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ // apply normal component of the impulse
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, impulse.dot(cti.m_normal));
+ if (impulse_tangent.norm() > SIMD_EPSILON)
+ {
+ // apply tangential component of the impulse
+ const btScalar* deltaV_t1 = &m_contact->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, impulse.dot(m_contact->t1));
+ const btScalar* deltaV_t2 = &m_contact->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+ multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, impulse.dot(m_contact->t2));
+ }
+ }
+ }
+// va = getVa();
+// vb = getVb();
+// vr = vb - va;
+// btScalar dn1 = btDot(vr, cti.m_normal) / 150;
+// m_penetration += dn1;
+ return residualSquare;
+}
+/* ================ Node vs. Rigid =================== */
+btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact, const btContactSolverInfo& infoGlobal)
+ : m_node(contact.m_node)
+ , btDeformableRigidContactConstraint(contact, infoGlobal)
+ {
+ }
+
+btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other)
+: m_node(other.m_node)
+, btDeformableRigidContactConstraint(other)
+{
+}
+
+btVector3 btDeformableNodeRigidContactConstraint::getVb() const
+{
+ return m_node->m_v;
+}
+
+
+btVector3 btDeformableNodeRigidContactConstraint::getDv(const btSoftBody::Node* node) const
+{
+ return m_total_normal_dv + m_total_tangent_dv;
+}
+
+void btDeformableNodeRigidContactConstraint::applyImpulse(const btVector3& impulse)
+{
+ const btSoftBody::DeformableNodeRigidContact* contact = getContact();
+ btVector3 dv = impulse * contact->m_c2;
+ contact->m_node->m_v -= dv;
+}
+
+/* ================ Face vs. Rigid =================== */
+btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact, const btContactSolverInfo& infoGlobal, bool useStrainLimiting)
+: m_face(contact.m_face)
+, m_useStrainLimiting(useStrainLimiting)
+, btDeformableRigidContactConstraint(contact, infoGlobal)
+{
+}
+
+btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other)
+: m_face(other.m_face)
+, m_useStrainLimiting(other.m_useStrainLimiting)
+, btDeformableRigidContactConstraint(other)
+{
+}
+
+btVector3 btDeformableFaceRigidContactConstraint::getVb() const
+{
+ const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+ btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
+ return vb;
+}
+
+
+btVector3 btDeformableFaceRigidContactConstraint::getDv(const btSoftBody::Node* node) const
+{
+ btVector3 face_dv = m_total_normal_dv + m_total_tangent_dv;
+ const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+ if (m_face->m_n[0] == node)
+ {
+ return face_dv * contact->m_weights[0];
+ }
+ if (m_face->m_n[1] == node)
+ {
+ return face_dv * contact->m_weights[1];
+ }
+ btAssert(node == m_face->m_n[2]);
+ return face_dv * contact->m_weights[2];
+}
+
+void btDeformableFaceRigidContactConstraint::applyImpulse(const btVector3& impulse)
+{
+ const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+ btVector3 dv = impulse * contact->m_c2;
+ btSoftBody::Face* face = contact->m_face;
+
+ btVector3& v0 = face->m_n[0]->m_v;
+ btVector3& v1 = face->m_n[1]->m_v;
+ btVector3& v2 = face->m_n[2]->m_v;
+ const btScalar& im0 = face->m_n[0]->m_im;
+ const btScalar& im1 = face->m_n[1]->m_im;
+ const btScalar& im2 = face->m_n[2]->m_im;
+ if (im0 > 0)
+ v0 -= dv * contact->m_weights[0];
+ if (im1 > 0)
+ v1 -= dv * contact->m_weights[1];
+ if (im2 > 0)
+ v2 -= dv * contact->m_weights[2];
+ if (m_useStrainLimiting)
+ {
+ btScalar relaxation = 1./btScalar(m_infoGlobal->m_numIterations);
+ btScalar m01 = (relaxation/(im0 + im1));
+ btScalar m02 = (relaxation/(im0 + im2));
+ btScalar m12 = (relaxation/(im1 + im2));
+ #ifdef USE_STRAIN_RATE_LIMITING
+ // apply strain limiting to prevent the new velocity to change the current length of the edge by more than 1%.
+ btScalar p = 0.01;
+ btVector3& x0 = face->m_n[0]->m_x;
+ btVector3& x1 = face->m_n[1]->m_x;
+ btVector3& x2 = face->m_n[2]->m_x;
+ const btVector3 x_diff[3] = {x1-x0, x2-x0, x2-x1};
+ const btVector3 v_diff[3] = {v1-v0, v2-v0, v2-v1};
+ btVector3 u[3];
+ btScalar x_diff_dot_u, dn[3];
+ btScalar dt = m_infoGlobal->m_timeStep;
+ for (int i = 0; i < 3; ++i)
+ {
+ btScalar x_diff_norm = x_diff[i].safeNorm();
+ btScalar x_diff_norm_new = (x_diff[i] + v_diff[i] * dt).safeNorm();
+ btScalar strainRate = x_diff_norm_new/x_diff_norm;
+ u[i] = v_diff[i];
+ u[i].safeNormalize();
+ if (x_diff_norm == 0 || (1-p <= strainRate && strainRate <= 1+p))
+ {
+ dn[i] = 0;
+ continue;
+ }
+ x_diff_dot_u = btDot(x_diff[i], u[i]);
+ btScalar s;
+ if (1-p > strainRate)
+ {
+ s = 1/dt * (-x_diff_dot_u - btSqrt(x_diff_dot_u*x_diff_dot_u + (p*p-2*p) * x_diff_norm * x_diff_norm));
+ }
+ else
+ {
+ s = 1/dt * (-x_diff_dot_u + btSqrt(x_diff_dot_u*x_diff_dot_u + (p*p+2*p) * x_diff_norm * x_diff_norm));
+ }
+ // x_diff_norm_new = (x_diff[i] + s * u[i] * dt).safeNorm();
+ // strainRate = x_diff_norm_new/x_diff_norm;
+ dn[i] = s - v_diff[i].safeNorm();
+ }
+ btVector3 dv0 = im0 * (m01 * u[0]*(-dn[0]) + m02 * u[1]*-(dn[1]));
+ btVector3 dv1 = im1 * (m01 * u[0]*(dn[0]) + m12 * u[2]*(-dn[2]));
+ btVector3 dv2 = im2 * (m12 * u[2]*(dn[2]) + m02 * u[1]*(dn[1]));
+ #else
+ // apply strain limiting to prevent undamped modes
+ btVector3 dv0 = im0 * (m01 * (v1-v0) + m02 * (v2-v0));
+ btVector3 dv1 = im1 * (m01 * (v0-v1) + m12 * (v2-v1));
+ btVector3 dv2 = im2 * (m12 * (v1-v2) + m02 * (v0-v2));
+ #endif
+ v0 += dv0;
+ v1 += dv1;
+ v2 += dv2;
+ }
+}
+
+/* ================ Face vs. Node =================== */
+btDeformableFaceNodeContactConstraint::btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact, const btContactSolverInfo& infoGlobal)
+: m_node(contact.m_node)
+, m_face(contact.m_face)
+, m_contact(&contact)
+, btDeformableContactConstraint(contact.m_normal, infoGlobal)
+{
+ m_total_normal_dv.setZero();
+ m_total_tangent_dv.setZero();
+}
+
+btVector3 btDeformableFaceNodeContactConstraint::getVa() const
+{
+ return m_node->m_v;
+}
+
+btVector3 btDeformableFaceNodeContactConstraint::getVb() const
+{
+ const btSoftBody::DeformableFaceNodeContact* contact = getContact();
+ btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
+ return vb;
+}
+
+btVector3 btDeformableFaceNodeContactConstraint::getDv(const btSoftBody::Node* n) const
+{
+ btVector3 dv = m_total_normal_dv + m_total_tangent_dv;
+ if (n == m_node)
+ return dv;
+ const btSoftBody::DeformableFaceNodeContact* contact = getContact();
+ if (m_face->m_n[0] == n)
+ {
+ return dv * contact->m_weights[0];
+ }
+ if (m_face->m_n[1] == n)
+ {
+ return dv * contact->m_weights[1];
+ }
+ btAssert(n == m_face->m_n[2]);
+ return dv * contact->m_weights[2];
+}
+
+btScalar btDeformableFaceNodeContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
+{
+ btVector3 va = getVa();
+ btVector3 vb = getVb();
+ btVector3 vr = vb - va;
+ const btScalar dn = btDot(vr, m_contact->m_normal);
+ // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
+ btScalar residualSquare = dn*dn;
+ btVector3 impulse = m_contact->m_c0 * vr;
+ const btVector3 impulse_normal = m_contact->m_c0 * (m_contact->m_normal * dn);
+ btVector3 impulse_tangent = impulse - impulse_normal;
+
+ btVector3 old_total_tangent_dv = m_total_tangent_dv;
+ // m_c2 is the inverse mass of the deformable node/face
+ if (m_node->m_im > 0)
+ {
+ m_total_normal_dv -= impulse_normal * m_node->m_im;
+ m_total_tangent_dv -= impulse_tangent * m_node->m_im;
+ }
+ else
+ {
+ m_total_normal_dv -= impulse_normal * m_contact->m_imf;
+ m_total_tangent_dv -= impulse_tangent * m_contact->m_imf;
+ }
+
+ if (m_total_normal_dv.dot(m_contact->m_normal) > 0)
+ {
+ // separating in the normal direction
+ m_static = false;
+ m_total_tangent_dv = btVector3(0,0,0);
+ impulse_tangent.setZero();
+ }
+ else
+ {
+ if (m_total_normal_dv.norm() * m_contact->m_friction < m_total_tangent_dv.norm())
+ {
+ // dynamic friction
+ // with dynamic friction, the impulse are still applied to the two objects colliding, however, it does not pose a constraint in the cg solve, hence the change to dv merely serves to update velocity in the contact iterations.
+ m_static = false;
+ if (m_total_tangent_dv.safeNorm() < SIMD_EPSILON)
+ {
+ m_total_tangent_dv = btVector3(0,0,0);
+ }
+ else
+ {
+ m_total_tangent_dv = m_total_tangent_dv.normalized() * m_total_normal_dv.safeNorm() * m_contact->m_friction;
+ }
+ impulse_tangent = -btScalar(1)/m_node->m_im * (m_total_tangent_dv - old_total_tangent_dv);
+ }
+ else
+ {
+ // static friction
+ m_static = true;
+ }
+ }
+ impulse = impulse_normal + impulse_tangent;
+ // apply impulse to deformable nodes involved and change their velocities
+ applyImpulse(impulse);
+ return residualSquare;
+}
+
+void btDeformableFaceNodeContactConstraint::applyImpulse(const btVector3& impulse)
+{
+ const btSoftBody::DeformableFaceNodeContact* contact = getContact();
+ btVector3 dva = impulse * contact->m_node->m_im;
+ btVector3 dvb = impulse * contact->m_imf;
+ if (contact->m_node->m_im > 0)
+ {
+ contact->m_node->m_v += dva;
+ }
+
+ btSoftBody::Face* face = contact->m_face;
+ btVector3& v0 = face->m_n[0]->m_v;
+ btVector3& v1 = face->m_n[1]->m_v;
+ btVector3& v2 = face->m_n[2]->m_v;
+ const btScalar& im0 = face->m_n[0]->m_im;
+ const btScalar& im1 = face->m_n[1]->m_im;
+ const btScalar& im2 = face->m_n[2]->m_im;
+ if (im0 > 0)
+ {
+ v0 -= dvb * contact->m_weights[0];
+ }
+ if (im1 > 0)
+ {
+ v1 -= dvb * contact->m_weights[1];
+ }
+ if (im2 > 0)
+ {
+ v2 -= dvb * contact->m_weights[2];
+ }
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h b/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h
new file mode 100644
index 0000000000..9f9d5bf0a3
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h
@@ -0,0 +1,266 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_DEFORMABLE_CONTACT_CONSTRAINT_H
+#define BT_DEFORMABLE_CONTACT_CONSTRAINT_H
+#include "btSoftBody.h"
+
+// btDeformableContactConstraint is an abstract class specifying the method that each type of contact constraint needs to implement
+class btDeformableContactConstraint
+{
+public:
+ // True if the friction is static
+ // False if the friction is dynamic
+ bool m_static;
+ const btContactSolverInfo* m_infoGlobal;
+
+ // normal of the contact
+ btVector3 m_normal;
+
+ btDeformableContactConstraint(const btVector3& normal, const btContactSolverInfo& infoGlobal): m_static(false), m_normal(normal), m_infoGlobal(&infoGlobal)
+ {
+ }
+
+ btDeformableContactConstraint(bool isStatic, const btVector3& normal, const btContactSolverInfo& infoGlobal): m_static(isStatic), m_normal(normal), m_infoGlobal(&infoGlobal)
+ {
+ }
+
+ btDeformableContactConstraint(){}
+
+ btDeformableContactConstraint(const btDeformableContactConstraint& other)
+ : m_static(other.m_static)
+ , m_normal(other.m_normal)
+ , m_infoGlobal(other.m_infoGlobal)
+ {
+ }
+
+ virtual ~btDeformableContactConstraint(){}
+
+ // solve the constraint with inelastic impulse and return the error, which is the square of normal component of velocity diffrerence
+ // the constraint is solved by calculating the impulse between object A and B in the contact and apply the impulse to both objects involved in the contact
+ virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal) = 0;
+
+ // get the velocity of the object A in the contact
+ virtual btVector3 getVa() const = 0;
+
+ // get the velocity of the object B in the contact
+ virtual btVector3 getVb() const = 0;
+
+ // get the velocity change of the soft body node in the constraint
+ virtual btVector3 getDv(const btSoftBody::Node*) const = 0;
+
+ // apply impulse to the soft body node and/or face involved
+ virtual void applyImpulse(const btVector3& impulse) = 0;
+
+ // scale the penetration depth by erp
+ virtual void setPenetrationScale(btScalar scale) = 0;
+};
+
+//
+// Constraint that a certain node in the deformable objects cannot move
+class btDeformableStaticConstraint : public btDeformableContactConstraint
+{
+public:
+ btSoftBody::Node* m_node;
+
+ btDeformableStaticConstraint(btSoftBody::Node* node, const btContactSolverInfo& infoGlobal): m_node(node), btDeformableContactConstraint(false, btVector3(0,0,0), infoGlobal)
+ {
+ }
+ btDeformableStaticConstraint(){}
+ btDeformableStaticConstraint(const btDeformableStaticConstraint& other)
+ : m_node(other.m_node)
+ , btDeformableContactConstraint(other)
+ {
+ }
+
+ virtual ~btDeformableStaticConstraint(){}
+
+ virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal)
+ {
+ return 0;
+ }
+
+ virtual btVector3 getVa() const
+ {
+ return btVector3(0,0,0);
+ }
+
+ virtual btVector3 getVb() const
+ {
+ return btVector3(0,0,0);
+ }
+
+ virtual btVector3 getDv(const btSoftBody::Node* n) const
+ {
+ return btVector3(0,0,0);
+ }
+
+ virtual void applyImpulse(const btVector3& impulse){}
+ virtual void setPenetrationScale(btScalar scale){}
+};
+
+//
+// Anchor Constraint between rigid and deformable node
+class btDeformableNodeAnchorConstraint : public btDeformableContactConstraint
+{
+public:
+ const btSoftBody::DeformableNodeRigidAnchor* m_anchor;
+
+ btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& c, const btContactSolverInfo& infoGlobal);
+ btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other);
+ btDeformableNodeAnchorConstraint(){}
+ virtual ~btDeformableNodeAnchorConstraint()
+ {
+ }
+ virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
+
+ // object A is the rigid/multi body, and object B is the deformable node/face
+ virtual btVector3 getVa() const;
+ // get the velocity of the deformable node in contact
+ virtual btVector3 getVb() const;
+ virtual btVector3 getDv(const btSoftBody::Node* n) const
+ {
+ return btVector3(0,0,0);
+ }
+ virtual void applyImpulse(const btVector3& impulse);
+
+ virtual void setPenetrationScale(btScalar scale){}
+};
+
+
+//
+// Constraint between rigid/multi body and deformable objects
+class btDeformableRigidContactConstraint : public btDeformableContactConstraint
+{
+public:
+ btVector3 m_total_normal_dv;
+ btVector3 m_total_tangent_dv;
+ btScalar m_penetration;
+ const btSoftBody::DeformableRigidContact* m_contact;
+
+ btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c, const btContactSolverInfo& infoGlobal);
+ btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other);
+ btDeformableRigidContactConstraint(){}
+ virtual ~btDeformableRigidContactConstraint()
+ {
+ }
+
+ // object A is the rigid/multi body, and object B is the deformable node/face
+ virtual btVector3 getVa() const;
+
+ virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
+
+ virtual void setPenetrationScale(btScalar scale)
+ {
+ m_penetration *= scale;
+ }
+};
+
+//
+// Constraint between rigid/multi body and deformable objects nodes
+class btDeformableNodeRigidContactConstraint : public btDeformableRigidContactConstraint
+{
+public:
+ // the deformable node in contact
+ btSoftBody::Node* m_node;
+
+ btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact, const btContactSolverInfo& infoGlobal);
+ btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other);
+ btDeformableNodeRigidContactConstraint(){}
+ virtual ~btDeformableNodeRigidContactConstraint()
+ {
+ }
+
+ // get the velocity of the deformable node in contact
+ virtual btVector3 getVb() const;
+
+ // get the velocity change of the input soft body node in the constraint
+ virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+ // cast the contact to the desired type
+ const btSoftBody::DeformableNodeRigidContact* getContact() const
+ {
+ return static_cast<const btSoftBody::DeformableNodeRigidContact*>(m_contact);
+ }
+
+ virtual void applyImpulse(const btVector3& impulse);
+};
+
+//
+// Constraint between rigid/multi body and deformable objects faces
+class btDeformableFaceRigidContactConstraint : public btDeformableRigidContactConstraint
+{
+public:
+ const btSoftBody::Face* m_face;
+ bool m_useStrainLimiting;
+ btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact, const btContactSolverInfo& infoGlobal, bool useStrainLimiting);
+ btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other);
+ btDeformableFaceRigidContactConstraint(): m_useStrainLimiting(false) {}
+ virtual ~btDeformableFaceRigidContactConstraint()
+ {
+ }
+
+ // get the velocity of the deformable face at the contact point
+ virtual btVector3 getVb() const;
+
+ // get the velocity change of the input soft body node in the constraint
+ virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+ // cast the contact to the desired type
+ const btSoftBody::DeformableFaceRigidContact* getContact() const
+ {
+ return static_cast<const btSoftBody::DeformableFaceRigidContact*>(m_contact);
+ }
+
+ virtual void applyImpulse(const btVector3& impulse);
+};
+
+//
+// Constraint between deformable objects faces and deformable objects nodes
+class btDeformableFaceNodeContactConstraint : public btDeformableContactConstraint
+{
+public:
+ btSoftBody::Node* m_node;
+ btSoftBody::Face* m_face;
+ const btSoftBody::DeformableFaceNodeContact* m_contact;
+ btVector3 m_total_normal_dv;
+ btVector3 m_total_tangent_dv;
+
+ btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact, const btContactSolverInfo& infoGlobal);
+ btDeformableFaceNodeContactConstraint(){}
+ virtual ~btDeformableFaceNodeContactConstraint(){}
+
+ virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
+
+ // get the velocity of the object A in the contact
+ virtual btVector3 getVa() const;
+
+ // get the velocity of the object B in the contact
+ virtual btVector3 getVb() const;
+
+ // get the velocity change of the input soft body node in the constraint
+ virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+ // cast the contact to the desired type
+ const btSoftBody::DeformableFaceNodeContact* getContact() const
+ {
+ return static_cast<const btSoftBody::DeformableFaceNodeContact*>(m_contact);
+ }
+
+ virtual void applyImpulse(const btVector3& impulse);
+
+ virtual void setPenetrationScale(btScalar scale){}
+};
+#endif /* BT_DEFORMABLE_CONTACT_CONSTRAINT_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp
new file mode 100644
index 0000000000..22ca8bf582
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp
@@ -0,0 +1,634 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "btDeformableContactProjection.h"
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include <algorithm>
+#include <cmath>
+btScalar btDeformableContactProjection::update(btCollisionObject** deformableBodies,int numDeformableBodies, const btContactSolverInfo& infoGlobal)
+{
+ btScalar residualSquare = 0;
+ for (int i = 0; i < numDeformableBodies; ++i)
+ {
+ for (int j = 0; j < m_softBodies.size(); ++j)
+ {
+ btCollisionObject* psb = m_softBodies[j];
+ if (psb != deformableBodies[i])
+ {
+ continue;
+ }
+ for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
+ {
+ btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k];
+ btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+ for (int k = 0; k < m_nodeAnchorConstraints[j].size(); ++k)
+ {
+ btDeformableNodeAnchorConstraint& constraint = m_nodeAnchorConstraints[j][k];
+ btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+ for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
+ {
+ btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k];
+ btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+ for (int k = 0; k < m_deformableConstraints[j].size(); ++k)
+ {
+ btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[j][k];
+ btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+ residualSquare = btMax(residualSquare, localResidualSquare);
+ }
+ }
+ }
+ return residualSquare;
+}
+
+void btDeformableContactProjection::splitImpulseSetup(const btContactSolverInfo& infoGlobal)
+{
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ // node constraints
+ for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+ {
+ btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[i][j];
+ constraint.setPenetrationScale(infoGlobal.m_deformable_erp);
+ }
+ // face constraints
+ for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+ {
+ btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[i][j];
+ constraint.setPenetrationScale(infoGlobal.m_deformable_erp);
+ }
+ }
+}
+
+void btDeformableContactProjection::setConstraints(const btContactSolverInfo& infoGlobal)
+{
+ BT_PROFILE("setConstraints");
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+
+ // set Dirichlet constraint
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ if (psb->m_nodes[j].m_im == 0)
+ {
+ btDeformableStaticConstraint static_constraint(&psb->m_nodes[j], infoGlobal);
+ m_staticConstraints[i].push_back(static_constraint);
+ }
+ }
+
+ // set up deformable anchors
+ for (int j = 0; j < psb->m_deformableAnchors.size(); ++j)
+ {
+ btSoftBody::DeformableNodeRigidAnchor& anchor = psb->m_deformableAnchors[j];
+ // skip fixed points
+ if (anchor.m_node->m_im == 0)
+ {
+ continue;
+ }
+ anchor.m_c1 = anchor.m_cti.m_colObj->getWorldTransform().getBasis() * anchor.m_local;
+ btDeformableNodeAnchorConstraint constraint(anchor, infoGlobal);
+ m_nodeAnchorConstraints[i].push_back(constraint);
+ }
+
+ // set Deformable Node vs. Rigid constraint
+ for (int j = 0; j < psb->m_nodeRigidContacts.size(); ++j)
+ {
+ const btSoftBody::DeformableNodeRigidContact& contact = psb->m_nodeRigidContacts[j];
+ // skip fixed points
+ if (contact.m_node->m_im == 0)
+ {
+ continue;
+ }
+ btDeformableNodeRigidContactConstraint constraint(contact, infoGlobal);
+ btVector3 va = constraint.getVa();
+ btVector3 vb = constraint.getVb();
+ const btVector3 vr = vb - va;
+ const btSoftBody::sCti& cti = contact.m_cti;
+ const btScalar dn = btDot(vr, cti.m_normal);
+ if (dn < SIMD_EPSILON)
+ {
+ m_nodeRigidConstraints[i].push_back(constraint);
+ }
+ }
+
+ // set Deformable Face vs. Rigid constraint
+ for (int j = 0; j < psb->m_faceRigidContacts.size(); ++j)
+ {
+ const btSoftBody::DeformableFaceRigidContact& contact = psb->m_faceRigidContacts[j];
+ // skip fixed faces
+ if (contact.m_c2 == 0)
+ {
+ continue;
+ }
+ btDeformableFaceRigidContactConstraint constraint(contact, infoGlobal, m_useStrainLimiting);
+ btVector3 va = constraint.getVa();
+ btVector3 vb = constraint.getVb();
+ const btVector3 vr = vb - va;
+ const btSoftBody::sCti& cti = contact.m_cti;
+ const btScalar dn = btDot(vr, cti.m_normal);
+ if (dn < SIMD_EPSILON)
+ {
+ m_faceRigidConstraints[i].push_back(constraint);
+ }
+ }
+ }
+}
+
+void btDeformableContactProjection::project(TVStack& x)
+{
+#ifndef USE_MGS
+ const int dim = 3;
+ for (int index = 0; index < m_projectionsDict.size(); ++index)
+ {
+ btAlignedObjectArray<btVector3>& projectionDirs = *m_projectionsDict.getAtIndex(index);
+ size_t i = m_projectionsDict.getKeyAtIndex(index).getUid1();
+ if (projectionDirs.size() >= dim)
+ {
+ // static node
+ x[i].setZero();
+ continue;
+ }
+ else if (projectionDirs.size() == 2)
+ {
+ btVector3 dir0 = projectionDirs[0];
+ btVector3 dir1 = projectionDirs[1];
+ btVector3 free_dir = btCross(dir0, dir1);
+ if (free_dir.safeNorm() < SIMD_EPSILON)
+ {
+ x[i] -= x[i].dot(dir0) * dir0;
+ x[i] -= x[i].dot(dir1) * dir1;
+ }
+ else
+ {
+ free_dir.normalize();
+ x[i] = x[i].dot(free_dir) * free_dir;
+ }
+ }
+ else
+ {
+ btAssert(projectionDirs.size() == 1);
+ btVector3 dir0 = projectionDirs[0];
+ x[i] -= x[i].dot(dir0) * dir0;
+ }
+ }
+#else
+ btReducedVector p(x.size());
+ for (int i = 0; i < m_projections.size(); ++i)
+ {
+ p += (m_projections[i].dot(x) * m_projections[i]);
+ }
+ for (int i = 0; i < p.m_indices.size(); ++i)
+ {
+ x[p.m_indices[i]] -= p.m_vecs[i];
+ }
+#endif
+}
+
+void btDeformableContactProjection::setProjection()
+{
+#ifndef USE_MGS
+ BT_PROFILE("btDeformableContactProjection::setProjection");
+ btAlignedObjectArray<btVector3> units;
+ units.push_back(btVector3(1,0,0));
+ units.push_back(btVector3(0,1,0));
+ units.push_back(btVector3(0,0,1));
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+ {
+ int index = m_staticConstraints[i][j].m_node->index;
+ m_staticConstraints[i][j].m_node->m_penetration = SIMD_INFINITY;
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ m_projectionsDict.insert(index, units);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ for (int k = 0; k < 3; ++k)
+ {
+ projections.push_back(units[k]);
+ }
+ }
+ }
+ for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+ {
+ int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
+ m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_penetration = SIMD_INFINITY;
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ m_projectionsDict.insert(index, units);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ for (int k = 0; k < 3; ++k)
+ {
+ projections.push_back(units[k]);
+ }
+ }
+ }
+ for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+ {
+ int index = m_nodeRigidConstraints[i][j].m_node->index;
+ m_nodeRigidConstraints[i][j].m_node->m_penetration = -m_nodeRigidConstraints[i][j].getContact()->m_cti.m_offset;
+ if (m_nodeRigidConstraints[i][j].m_static)
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ m_projectionsDict.insert(index, units);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ for (int k = 0; k < 3; ++k)
+ {
+ projections.push_back(units[k]);
+ }
+ }
+ }
+ else
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ btAlignedObjectArray<btVector3> projections;
+ projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
+ m_projectionsDict.insert(index, projections);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
+ }
+ }
+ }
+ for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+ {
+ const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
+ btScalar penetration = -m_faceRigidConstraints[i][j].getContact()->m_cti.m_offset;
+ for (int k = 0; k < 3; ++k)
+ {
+ face->m_n[k]->m_penetration = btMax(face->m_n[k]->m_penetration, penetration);
+ }
+ for (int k = 0; k < 3; ++k)
+ {
+ btSoftBody::Node* node = face->m_n[k];
+ node->m_penetration = true;
+ int index = node->index;
+ if (m_faceRigidConstraints[i][j].m_static)
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ m_projectionsDict.insert(index, units);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ for (int k = 0; k < 3; ++k)
+ {
+ projections.push_back(units[k]);
+ }
+ }
+ }
+ else
+ {
+ if (m_projectionsDict.find(index) == NULL)
+ {
+ btAlignedObjectArray<btVector3> projections;
+ projections.push_back(m_faceRigidConstraints[i][j].m_normal);
+ m_projectionsDict.insert(index, projections);
+ }
+ else
+ {
+ btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+ projections.push_back(m_faceRigidConstraints[i][j].m_normal);
+ }
+ }
+ }
+ }
+ }
+#else
+ int dof = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ dof += m_softBodies[i]->m_nodes.size();
+ }
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+ {
+ int index = m_staticConstraints[i][j].m_node->index;
+ m_staticConstraints[i][j].m_node->m_penetration = SIMD_INFINITY;
+ btAlignedObjectArray<int> indices;
+ btAlignedObjectArray<btVector3> vecs1,vecs2,vecs3;
+ indices.push_back(index);
+ vecs1.push_back(btVector3(1,0,0));
+ vecs2.push_back(btVector3(0,1,0));
+ vecs3.push_back(btVector3(0,0,1));
+ m_projections.push_back(btReducedVector(dof, indices, vecs1));
+ m_projections.push_back(btReducedVector(dof, indices, vecs2));
+ m_projections.push_back(btReducedVector(dof, indices, vecs3));
+ }
+
+ for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+ {
+ int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
+ m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_penetration = SIMD_INFINITY;
+ btAlignedObjectArray<int> indices;
+ btAlignedObjectArray<btVector3> vecs1,vecs2,vecs3;
+ indices.push_back(index);
+ vecs1.push_back(btVector3(1,0,0));
+ vecs2.push_back(btVector3(0,1,0));
+ vecs3.push_back(btVector3(0,0,1));
+ m_projections.push_back(btReducedVector(dof, indices, vecs1));
+ m_projections.push_back(btReducedVector(dof, indices, vecs2));
+ m_projections.push_back(btReducedVector(dof, indices, vecs3));
+ }
+ for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+ {
+ int index = m_nodeRigidConstraints[i][j].m_node->index;
+ m_nodeRigidConstraints[i][j].m_node->m_penetration = -m_nodeRigidConstraints[i][j].getContact()->m_cti.m_offset;
+ btAlignedObjectArray<int> indices;
+ indices.push_back(index);
+ btAlignedObjectArray<btVector3> vecs1,vecs2,vecs3;
+ if (m_nodeRigidConstraints[i][j].m_static)
+ {
+ vecs1.push_back(btVector3(1,0,0));
+ vecs2.push_back(btVector3(0,1,0));
+ vecs3.push_back(btVector3(0,0,1));
+ m_projections.push_back(btReducedVector(dof, indices, vecs1));
+ m_projections.push_back(btReducedVector(dof, indices, vecs2));
+ m_projections.push_back(btReducedVector(dof, indices, vecs3));
+ }
+ else
+ {
+ vecs1.push_back(m_nodeRigidConstraints[i][j].m_normal);
+ m_projections.push_back(btReducedVector(dof, indices, vecs1));
+ }
+ }
+ for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+ {
+ const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
+ btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
+ btScalar penetration = -m_faceRigidConstraints[i][j].getContact()->m_cti.m_offset;
+ for (int k = 0; k < 3; ++k)
+ {
+ face->m_n[k]->m_penetration = btMax(face->m_n[k]->m_penetration, penetration);
+ }
+ if (m_faceRigidConstraints[i][j].m_static)
+ {
+ for (int l = 0; l < 3; ++l)
+ {
+
+ btReducedVector rv(dof);
+ for (int k = 0; k < 3; ++k)
+ {
+ rv.m_indices.push_back(face->m_n[k]->index);
+ btVector3 v(0,0,0);
+ v[l] = bary[k];
+ rv.m_vecs.push_back(v);
+ rv.sort();
+ }
+ m_projections.push_back(rv);
+ }
+ }
+ else
+ {
+ btReducedVector rv(dof);
+ for (int k = 0; k < 3; ++k)
+ {
+ rv.m_indices.push_back(face->m_n[k]->index);
+ rv.m_vecs.push_back(bary[k] * m_faceRigidConstraints[i][j].m_normal);
+ rv.sort();
+ }
+ m_projections.push_back(rv);
+ }
+ }
+ }
+ btModifiedGramSchmidt<btReducedVector> mgs(m_projections);
+ mgs.solve();
+ m_projections = mgs.m_out;
+#endif
+}
+
+void btDeformableContactProjection::checkConstraints(const TVStack& x)
+{
+ for (int i = 0; i < m_lagrangeMultipliers.size(); ++i)
+ {
+ btVector3 d(0,0,0);
+ const LagrangeMultiplier& lm = m_lagrangeMultipliers[i];
+ for (int j = 0; j < lm.m_num_constraints; ++j)
+ {
+ for (int k = 0; k < lm.m_num_nodes; ++k)
+ {
+ d[j] += lm.m_weights[k] * x[lm.m_indices[k]].dot(lm.m_dirs[j]);
+ }
+ }
+ printf("d = %f, %f, %f\n",d[0],d[1],d[2]);
+ }
+}
+
+void btDeformableContactProjection::setLagrangeMultiplier()
+{
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+ {
+ int index = m_staticConstraints[i][j].m_node->index;
+ m_staticConstraints[i][j].m_node->m_penetration = SIMD_INFINITY;
+ LagrangeMultiplier lm;
+ lm.m_num_nodes = 1;
+ lm.m_indices[0] = index;
+ lm.m_weights[0] = 1.0;
+ lm.m_num_constraints = 3;
+ lm.m_dirs[0] = btVector3(1,0,0);
+ lm.m_dirs[1] = btVector3(0,1,0);
+ lm.m_dirs[2] = btVector3(0,0,1);
+ m_lagrangeMultipliers.push_back(lm);
+ }
+ for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+ {
+ int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
+ m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_penetration = SIMD_INFINITY;
+ LagrangeMultiplier lm;
+ lm.m_num_nodes = 1;
+ lm.m_indices[0] = index;
+ lm.m_weights[0] = 1.0;
+ lm.m_num_constraints = 3;
+ lm.m_dirs[0] = btVector3(1,0,0);
+ lm.m_dirs[1] = btVector3(0,1,0);
+ lm.m_dirs[2] = btVector3(0,0,1);
+ m_lagrangeMultipliers.push_back(lm);
+ }
+ for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+ {
+ int index = m_nodeRigidConstraints[i][j].m_node->index;
+ m_nodeRigidConstraints[i][j].m_node->m_penetration = -m_nodeRigidConstraints[i][j].getContact()->m_cti.m_offset;
+ LagrangeMultiplier lm;
+ lm.m_num_nodes = 1;
+ lm.m_indices[0] = index;
+ lm.m_weights[0] = 1.0;
+ if (m_nodeRigidConstraints[i][j].m_static)
+ {
+ lm.m_num_constraints = 3;
+ lm.m_dirs[0] = btVector3(1,0,0);
+ lm.m_dirs[1] = btVector3(0,1,0);
+ lm.m_dirs[2] = btVector3(0,0,1);
+ }
+ else
+ {
+ lm.m_num_constraints = 1;
+ lm.m_dirs[0] = m_nodeRigidConstraints[i][j].m_normal;
+ }
+ m_lagrangeMultipliers.push_back(lm);
+ }
+ for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+ {
+ const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
+
+ btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
+ btScalar penetration = -m_faceRigidConstraints[i][j].getContact()->m_cti.m_offset;
+ LagrangeMultiplier lm;
+ lm.m_num_nodes = 3;
+ for (int k = 0; k<3; ++k)
+ {
+ face->m_n[k]->m_penetration = btMax(face->m_n[k]->m_penetration, penetration);
+ lm.m_indices[k] = face->m_n[k]->index;
+ lm.m_weights[k] = bary[k];
+ }
+ if (m_faceRigidConstraints[i][j].m_static)
+ {
+ lm.m_num_constraints = 3;
+ lm.m_dirs[0] = btVector3(1,0,0);
+ lm.m_dirs[1] = btVector3(0,1,0);
+ lm.m_dirs[2] = btVector3(0,0,1);
+ }
+ else
+ {
+ lm.m_num_constraints = 1;
+ lm.m_dirs[0] = m_faceRigidConstraints[i][j].m_normal;
+ }
+ m_lagrangeMultipliers.push_back(lm);
+ }
+ }
+}
+
+//
+void btDeformableContactProjection::applyDynamicFriction(TVStack& f)
+{
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+ {
+ const btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[i][j];
+ const btSoftBody::Node* node = constraint.m_node;
+ if (node->m_im != 0)
+ {
+ int index = node->index;
+ f[index] += constraint.getDv(node)* (1./node->m_im);
+ }
+ }
+ for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+ {
+ const btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[i][j];
+ const btSoftBody::Face* face = constraint.getContact()->m_face;
+ for (int k = 0; k < 3; ++k)
+ {
+ const btSoftBody::Node* node = face->m_n[k];
+ if (node->m_im != 0)
+ {
+ int index = node->index;
+ f[index] += constraint.getDv(node)* (1./node->m_im);
+ }
+ }
+ }
+ for (int j = 0; j < m_deformableConstraints[i].size(); ++j)
+ {
+ const btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[i][j];
+ const btSoftBody::Face* face = constraint.getContact()->m_face;
+ const btSoftBody::Node* node = constraint.getContact()->m_node;
+ if (node->m_im != 0)
+ {
+ int index = node->index;
+ f[index] += constraint.getDv(node)* (1./node->m_im);
+ }
+ for (int k = 0; k < 3; ++k)
+ {
+ const btSoftBody::Node* node = face->m_n[k];
+ if (node->m_im != 0)
+ {
+ int index = node->index;
+ f[index] += constraint.getDv(node)* (1./node->m_im);
+ }
+ }
+ }
+ }
+}
+
+void btDeformableContactProjection::reinitialize(bool nodeUpdated)
+{
+ int N = m_softBodies.size();
+ if (nodeUpdated)
+ {
+ m_staticConstraints.resize(N);
+ m_nodeAnchorConstraints.resize(N);
+ m_nodeRigidConstraints.resize(N);
+ m_faceRigidConstraints.resize(N);
+ m_deformableConstraints.resize(N);
+
+ }
+ for (int i = 0 ; i < N; ++i)
+ {
+ m_staticConstraints[i].clear();
+ m_nodeAnchorConstraints[i].clear();
+ m_nodeRigidConstraints[i].clear();
+ m_faceRigidConstraints[i].clear();
+ m_deformableConstraints[i].clear();
+ }
+#ifndef USE_MGS
+ m_projectionsDict.clear();
+#else
+ m_projections.clear();
+#endif
+ m_lagrangeMultipliers.clear();
+}
+
+
+
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h b/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h
new file mode 100644
index 0000000000..8d7e94d4fb
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h
@@ -0,0 +1,100 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_CONTACT_PROJECTION_H
+#define BT_CONTACT_PROJECTION_H
+#include "btCGProjection.h"
+#include "btSoftBody.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+#include "btDeformableContactConstraint.h"
+#include "LinearMath/btHashMap.h"
+#include "LinearMath/btReducedVector.h"
+#include "LinearMath/btModifiedGramSchmidt.h"
+#include <vector>
+
+struct LagrangeMultiplier
+{
+ int m_num_constraints; // Number of constraints
+ int m_num_nodes; // Number of nodes in these constraints
+ btScalar m_weights[3]; // weights of the nodes involved, same size as m_num_nodes
+ btVector3 m_dirs[3]; // Constraint directions, same size of m_num_constraints;
+ int m_indices[3]; // indices of the nodes involved, same size as m_num_nodes;
+};
+
+
+class btDeformableContactProjection
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btAlignedObjectArray<btSoftBody *>& m_softBodies;
+
+ // all constraints involving face
+ btAlignedObjectArray<btDeformableContactConstraint*> m_allFaceConstraints;
+#ifndef USE_MGS
+ // map from node index to projection directions
+ btHashMap<btHashInt, btAlignedObjectArray<btVector3> > m_projectionsDict;
+#else
+ btAlignedObjectArray<btReducedVector> m_projections;
+#endif
+
+ btAlignedObjectArray<LagrangeMultiplier> m_lagrangeMultipliers;
+
+ // map from node index to static constraint
+ btAlignedObjectArray<btAlignedObjectArray<btDeformableStaticConstraint> > m_staticConstraints;
+ // map from node index to node rigid constraint
+ btAlignedObjectArray<btAlignedObjectArray<btDeformableNodeRigidContactConstraint> > m_nodeRigidConstraints;
+ // map from node index to face rigid constraint
+ btAlignedObjectArray<btAlignedObjectArray<btDeformableFaceRigidContactConstraint> > m_faceRigidConstraints;
+ // map from node index to deformable constraint
+ btAlignedObjectArray<btAlignedObjectArray<btDeformableFaceNodeContactConstraint> > m_deformableConstraints;
+ // map from node index to node anchor constraint
+ btAlignedObjectArray<btAlignedObjectArray<btDeformableNodeAnchorConstraint> > m_nodeAnchorConstraints;
+
+ bool m_useStrainLimiting;
+
+ btDeformableContactProjection(btAlignedObjectArray<btSoftBody *>& softBodies)
+ : m_softBodies(softBodies)
+ {
+ }
+
+ virtual ~btDeformableContactProjection()
+ {
+ }
+
+ // apply the constraints to the rhs of the linear solve
+ virtual void project(TVStack& x);
+
+ // add friction force to the rhs of the linear solve
+ virtual void applyDynamicFriction(TVStack& f);
+
+ // update and solve the constraints
+ virtual btScalar update(btCollisionObject** deformableBodies,int numDeformableBodies, const btContactSolverInfo& infoGlobal);
+
+ // Add constraints to m_constraints. In addition, the constraints that each vertex own are recorded in m_constraintsDict.
+ virtual void setConstraints(const btContactSolverInfo& infoGlobal);
+
+ // Set up projections for each vertex by adding the projection direction to
+ virtual void setProjection();
+
+ virtual void reinitialize(bool nodeUpdated);
+
+ virtual void splitImpulseSetup(const btContactSolverInfo& infoGlobal);
+
+ virtual void setLagrangeMultiplier();
+
+ void checkConstraints(const TVStack& x);
+};
+#endif /* btDeformableContactProjection_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h
new file mode 100644
index 0000000000..2d042df729
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h
@@ -0,0 +1,127 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_COROTATED_H
+#define BT_COROTATED_H
+
+#include "btDeformableLagrangianForce.h"
+#include "LinearMath/btPolarDecomposition.h"
+
+static inline int PolarDecomposition(const btMatrix3x3& m, btMatrix3x3& q, btMatrix3x3& s)
+{
+ static const btPolarDecomposition polar;
+ return polar.decompose(m, q, s);
+}
+
+class btDeformableCorotatedForce : public btDeformableLagrangianForce
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btScalar m_mu, m_lambda;
+ btDeformableCorotatedForce(): m_mu(1), m_lambda(1)
+ {
+
+ }
+
+ btDeformableCorotatedForce(btScalar mu, btScalar lambda): m_mu(mu), m_lambda(lambda)
+ {
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ }
+
+ virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btMatrix3x3 P;
+ firstPiola(tetra.m_F,P);
+ btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 force_on_node123 = P * tetra.m_Dm_inverse.transpose();
+
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+
+ // elastic force
+ // explicit elastic force
+ btScalar scale1 = scale * tetra.m_element_measure;
+ force[id0] -= scale1 * force_on_node0;
+ force[id1] -= scale1 * force_on_node123.getColumn(0);
+ force[id2] -= scale1 * force_on_node123.getColumn(1);
+ force[id3] -= scale1 * force_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ void firstPiola(const btMatrix3x3& F, btMatrix3x3& P)
+ {
+ // btMatrix3x3 JFinvT = F.adjoint();
+ btScalar J = F.determinant();
+ P = F.adjoint().transpose() * (m_lambda * (J-1));
+ if (m_mu > SIMD_EPSILON)
+ {
+ btMatrix3x3 R,S;
+ if (J < 1024 * SIMD_EPSILON)
+ R.setIdentity();
+ else
+ PolarDecomposition(F, R, S); // this QR is not robust, consider using implicit shift svd
+ /*https://fuchuyuan.github.io/research/svd/paper.pdf*/
+ P += (F-R) * 2 * m_mu;
+ }
+ }
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ }
+
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ }
+
+ virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA){}
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_COROTATED_FORCE;
+ }
+
+};
+
+
+#endif /* btCorotated_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h
new file mode 100644
index 0000000000..13ee3eacb6
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h
@@ -0,0 +1,107 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_DEFORMABLE_GRAVITY_FORCE_H
+#define BT_DEFORMABLE_GRAVITY_FORCE_H
+
+#include "btDeformableLagrangianForce.h"
+
+class btDeformableGravityForce : public btDeformableLagrangianForce
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btVector3 m_gravity;
+
+ btDeformableGravityForce(const btVector3& g) : m_gravity(g)
+ {
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledGravityForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledGravityForce(scale, force);
+ }
+
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ }
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ }
+
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ }
+
+ virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA){}
+
+ virtual void addScaledGravityForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ btSoftBody::Node& n = psb->m_nodes[j];
+ size_t id = n.index;
+ btScalar mass = (n.m_im == 0) ? 0 : 1. / n.m_im;
+ btVector3 scaled_force = scale * m_gravity * mass;
+ force[id] += scaled_force;
+ }
+ }
+ }
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_GRAVITY_FORCE;
+ }
+
+ // the gravitational potential energy
+ virtual double totalEnergy(btScalar dt)
+ {
+ double e = 0;
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ if (node.m_im > 0)
+ {
+ e -= m_gravity.dot(node.m_q)/node.m_im;
+ }
+ }
+ }
+ return e;
+ }
+
+
+};
+#endif /* BT_DEFORMABLE_GRAVITY_FORCE_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h
new file mode 100644
index 0000000000..0b6447442d
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h
@@ -0,0 +1,373 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_DEFORMABLE_LAGRANGIAN_FORCE_H
+#define BT_DEFORMABLE_LAGRANGIAN_FORCE_H
+
+#include "btSoftBody.h"
+#include <LinearMath/btHashMap.h>
+#include <iostream>
+
+enum btDeformableLagrangianForceType
+{
+ BT_GRAVITY_FORCE = 1,
+ BT_MASSSPRING_FORCE = 2,
+ BT_COROTATED_FORCE = 3,
+ BT_NEOHOOKEAN_FORCE = 4,
+ BT_LINEAR_ELASTICITY_FORCE = 5,
+ BT_MOUSE_PICKING_FORCE = 6
+};
+
+static inline double randomDouble(double low, double high)
+{
+ return low + static_cast<double>(rand()) / RAND_MAX * (high - low);
+}
+
+class btDeformableLagrangianForce
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btAlignedObjectArray<btSoftBody *> m_softBodies;
+ const btAlignedObjectArray<btSoftBody::Node*>* m_nodes;
+
+ btDeformableLagrangianForce()
+ {
+ }
+
+ virtual ~btDeformableLagrangianForce(){}
+
+ // add all forces
+ virtual void addScaledForces(btScalar scale, TVStack& force) = 0;
+
+ // add damping df
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df) = 0;
+
+ // build diagonal of A matrix
+ virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) = 0;
+
+ // add elastic df
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df) = 0;
+
+ // add all forces that are explicit in explicit solve
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force) = 0;
+
+ // add all damping forces
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force) = 0;
+
+ virtual btDeformableLagrangianForceType getForceType() = 0;
+
+ virtual void reinitialize(bool nodeUpdated)
+ {
+ }
+
+ // get number of nodes that have the force
+ virtual int getNumNodes()
+ {
+ int numNodes = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ numNodes += m_softBodies[i]->m_nodes.size();
+ }
+ return numNodes;
+ }
+
+ // add a soft body to be affected by the particular lagrangian force
+ virtual void addSoftBody(btSoftBody* psb)
+ {
+ m_softBodies.push_back(psb);
+ }
+
+ virtual void removeSoftBody(btSoftBody* psb)
+ {
+ m_softBodies.remove(psb);
+ }
+
+ virtual void setIndices(const btAlignedObjectArray<btSoftBody::Node*>* nodes)
+ {
+ m_nodes = nodes;
+ }
+
+ // Calculate the incremental deformable generated from the input dx
+ virtual btMatrix3x3 Ds(int id0, int id1, int id2, int id3, const TVStack& dx)
+ {
+ btVector3 c1 = dx[id1] - dx[id0];
+ btVector3 c2 = dx[id2] - dx[id0];
+ btVector3 c3 = dx[id3] - dx[id0];
+ return btMatrix3x3(c1,c2,c3).transpose();
+ }
+
+ // Calculate the incremental deformable generated from the current velocity
+ virtual btMatrix3x3 DsFromVelocity(const btSoftBody::Node* n0, const btSoftBody::Node* n1, const btSoftBody::Node* n2, const btSoftBody::Node* n3)
+ {
+ btVector3 c1 = n1->m_v - n0->m_v;
+ btVector3 c2 = n2->m_v - n0->m_v;
+ btVector3 c3 = n3->m_v - n0->m_v;
+ return btMatrix3x3(c1,c2,c3).transpose();
+ }
+
+ // test for addScaledElasticForce function
+ virtual void testDerivative()
+ {
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q += btVector3(randomDouble(-.1, .1), randomDouble(-.1, .1), randomDouble(-.1, .1));
+ }
+ psb->updateDeformation();
+ }
+
+ TVStack dx;
+ dx.resize(getNumNodes());
+ TVStack dphi_dx;
+ dphi_dx.resize(dx.size());
+ for (int i =0; i < dphi_dx.size();++i)
+ {
+ dphi_dx[i].setZero();
+ }
+ addScaledForces(-1, dphi_dx);
+
+ // write down the current position
+ TVStack x;
+ x.resize(dx.size());
+ int counter = 0;
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ x[counter] = psb->m_nodes[j].m_q;
+ counter++;
+ }
+ }
+ counter = 0;
+
+ // populate dx with random vectors
+ for (int i = 0; i < dx.size(); ++i)
+ {
+ dx[i].setX(randomDouble(-1, 1));
+ dx[i].setY(randomDouble(-1, 1));
+ dx[i].setZ(randomDouble(-1, 1));
+ }
+
+ btAlignedObjectArray<double> errors;
+ for (int it = 0; it < 10; ++it)
+ {
+ for (int i = 0; i < dx.size(); ++i)
+ {
+ dx[i] *= 0.5;
+ }
+
+ // get dphi/dx * dx
+ double dphi = 0;
+ for (int i = 0; i < dx.size(); ++i)
+ {
+ dphi += dphi_dx[i].dot(dx[i]);
+ }
+
+
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter] + dx[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+ double f1 = totalElasticEnergy(0);
+
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter] - dx[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+
+ double f2 = totalElasticEnergy(0);
+
+ //restore m_q
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+ double error = f1-f2-2*dphi;
+ errors.push_back(error);
+ std::cout << "Iteration = " << it <<", f1 = " << f1 << ", f2 = " << f2 << ", error = " << error << std::endl;
+ }
+ for (int i = 1; i < errors.size(); ++i)
+ {
+ std::cout << "Iteration = " << i << ", ratio = " << errors[i-1]/errors[i] << std::endl;
+ }
+ }
+
+ // test for addScaledElasticForce function
+ virtual void testHessian()
+ {
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q += btVector3(randomDouble(-.1, .1), randomDouble(-.1, .1), randomDouble(-.1, .1));
+ }
+ psb->updateDeformation();
+ }
+
+
+ TVStack dx;
+ dx.resize(getNumNodes());
+ TVStack df;
+ df.resize(dx.size());
+ TVStack f1;
+ f1.resize(dx.size());
+ TVStack f2;
+ f2.resize(dx.size());
+
+
+ // write down the current position
+ TVStack x;
+ x.resize(dx.size());
+ int counter = 0;
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ x[counter] = psb->m_nodes[j].m_q;
+ counter++;
+ }
+ }
+ counter = 0;
+
+ // populate dx with random vectors
+ for (int i = 0; i < dx.size(); ++i)
+ {
+ dx[i].setX(randomDouble(-1, 1));
+ dx[i].setY(randomDouble(-1, 1));
+ dx[i].setZ(randomDouble(-1, 1));
+ }
+
+ btAlignedObjectArray<double> errors;
+ for (int it = 0; it < 10; ++it)
+ {
+ for (int i = 0; i < dx.size(); ++i)
+ {
+ dx[i] *= 0.5;
+ }
+
+ // get df
+ for (int i =0; i < df.size();++i)
+ {
+ df[i].setZero();
+ f1[i].setZero();
+ f2[i].setZero();
+ }
+
+ //set df
+ addScaledElasticForceDifferential(-1, dx, df);
+
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter] + dx[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+
+ //set f1
+ addScaledForces(-1, f1);
+
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter] - dx[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+
+ //set f2
+ addScaledForces(-1, f2);
+
+ //restore m_q
+ for (int i = 0; i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = x[counter];
+ counter++;
+ }
+ psb->updateDeformation();
+ }
+ counter = 0;
+ double error = 0;
+ for (int i = 0; i < df.size();++i)
+ {
+ btVector3 error_vector = f1[i]-f2[i]-2*df[i];
+ error += error_vector.length2();
+ }
+ error = btSqrt(error);
+ errors.push_back(error);
+ std::cout << "Iteration = " << it << ", error = " << error << std::endl;
+ }
+ for (int i = 1; i < errors.size(); ++i)
+ {
+ std::cout << "Iteration = " << i << ", ratio = " << errors[i-1]/errors[i] << std::endl;
+ }
+ }
+
+ //
+ virtual double totalElasticEnergy(btScalar dt)
+ {
+ return 0;
+ }
+
+ //
+ virtual double totalDampingEnergy(btScalar dt)
+ {
+ return 0;
+ }
+
+ // total Energy takes dt as input because certain energies depend on dt
+ virtual double totalEnergy(btScalar dt)
+ {
+ return totalElasticEnergy(dt) + totalDampingEnergy(dt);
+ }
+};
+#endif /* BT_DEFORMABLE_LAGRANGIAN_FORCE */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h
new file mode 100644
index 0000000000..106dc10ad6
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h
@@ -0,0 +1,340 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_LINEAR_ELASTICITY_H
+#define BT_LINEAR_ELASTICITY_H
+
+#include "btDeformableLagrangianForce.h"
+#include "LinearMath/btQuickprof.h"
+class btDeformableLinearElasticityForce : public btDeformableLagrangianForce
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btScalar m_mu, m_lambda;
+ btScalar m_mu_damp, m_lambda_damp;
+ btDeformableLinearElasticityForce(): m_mu(1), m_lambda(1)
+ {
+ btScalar damping = 0.05;
+ m_mu_damp = damping * m_mu;
+ m_lambda_damp = damping * m_lambda;
+ }
+
+ btDeformableLinearElasticityForce(btScalar mu, btScalar lambda, btScalar damping = 0.05): m_mu(mu), m_lambda(lambda)
+ {
+ m_mu_damp = damping * m_mu;
+ m_lambda_damp = damping * m_lambda;
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledDampingForce(scale, force);
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ if (m_mu_damp == 0 && m_lambda_damp == 0)
+ return;
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = DsFromVelocity(node0, node1, node2, node3) * tetra.m_Dm_inverse;
+ btMatrix3x3 I;
+ I.setIdentity();
+ btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0]+dF[1][1]+dF[2][2]) * m_lambda_damp;
+ // firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
+ btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+
+ // damping force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ force[id0] -= scale1 * df_on_node0;
+ force[id1] -= scale1 * df_on_node123.getColumn(0);
+ force[id2] -= scale1 * df_on_node123.getColumn(1);
+ force[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ virtual double totalElasticEnergy(btScalar dt)
+ {
+ double energy = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetraScratches.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::TetraScratch& s = psb->m_tetraScratches[j];
+ energy += tetra.m_element_measure * elasticEnergyDensity(s);
+ }
+ }
+ return energy;
+ }
+
+ // The damping energy is formulated as in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual double totalDampingEnergy(btScalar dt)
+ {
+ double energy = 0;
+ int sz = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ sz = btMax(sz, psb->m_nodes[j].index);
+ }
+ }
+ TVStack dampingForce;
+ dampingForce.resize(sz+1);
+ for (int i = 0; i < dampingForce.size(); ++i)
+ dampingForce[i].setZero();
+ addScaledDampingForce(0.5, dampingForce);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ energy -= dampingForce[node.index].dot(node.m_v) / dt;
+ }
+ }
+ return energy;
+ }
+
+ double elasticEnergyDensity(const btSoftBody::TetraScratch& s)
+ {
+ double density = 0;
+ btMatrix3x3 epsilon = (s.m_F + s.m_F.transpose()) * 0.5 - btMatrix3x3::getIdentity();
+ btScalar trace = epsilon[0][0] + epsilon[1][1] + epsilon[2][2];
+ density += m_mu * (epsilon[0].length2() + epsilon[1].length2() + epsilon[2].length2());
+ density += m_lambda * trace * trace * 0.5;
+ return density;
+ }
+
+ virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ btScalar max_p = psb->m_cfg.m_maxStress;
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btMatrix3x3 P;
+ firstPiola(psb->m_tetraScratches[j],P);
+#if USE_SVD
+ if (max_p > 0)
+ {
+ // since we want to clamp the principal stress to max_p, we only need to
+ // calculate SVD when sigma_0^2 + sigma_1^2 + sigma_2^2 > max_p * max_p
+ btScalar trPTP = (P[0].length2() + P[1].length2() + P[2].length2());
+ if (trPTP > max_p * max_p)
+ {
+ btMatrix3x3 U, V;
+ btVector3 sigma;
+ singularValueDecomposition(P, U, sigma, V);
+ sigma[0] = btMin(sigma[0], max_p);
+ sigma[1] = btMin(sigma[1], max_p);
+ sigma[2] = btMin(sigma[2], max_p);
+ sigma[0] = btMax(sigma[0], -max_p);
+ sigma[1] = btMax(sigma[1], -max_p);
+ sigma[2] = btMax(sigma[2], -max_p);
+ btMatrix3x3 Sigma;
+ Sigma.setIdentity();
+ Sigma[0][0] = sigma[0];
+ Sigma[1][1] = sigma[1];
+ Sigma[2][2] = sigma[2];
+ P = U * Sigma * V.transpose();
+ }
+ }
+#endif
+ // btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 force_on_node123 = P * tetra.m_Dm_inverse.transpose();
+ btVector3 force_on_node0 = force_on_node123 * grad_N_hat_1st_col;
+
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+
+ // elastic force
+ btScalar scale1 = scale * tetra.m_element_measure;
+ force[id0] -= scale1 * force_on_node0;
+ force[id1] -= scale1 * force_on_node123.getColumn(0);
+ force[id2] -= scale1 * force_on_node123.getColumn(1);
+ force[id3] -= scale1 * force_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ if (m_mu_damp == 0 && m_lambda_damp == 0)
+ return;
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= df.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = Ds(id0, id1, id2, id3, dv) * tetra.m_Dm_inverse;
+ btMatrix3x3 I;
+ I.setIdentity();
+ btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0]+dF[1][1]+dF[2][2]) * m_lambda_damp;
+ // firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
+ // btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+ btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+ // damping force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ df[id0] -= scale1 * df_on_node0;
+ df[id1] -= scale1 * df_on_node123.getColumn(0);
+ df[id2] -= scale1 * df_on_node123.getColumn(1);
+ df[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= df.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = Ds(id0, id1, id2, id3, dx) * tetra.m_Dm_inverse;
+ btMatrix3x3 dP;
+ firstPiolaDifferential(psb->m_tetraScratches[j], dF, dP);
+ // btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+ btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+ // elastic force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ df[id0] -= scale1 * df_on_node0;
+ df[id1] -= scale1 * df_on_node123.getColumn(0);
+ df[id2] -= scale1 * df_on_node123.getColumn(1);
+ df[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ void firstPiola(const btSoftBody::TetraScratch& s, btMatrix3x3& P)
+ {
+ btMatrix3x3 epsilon = (s.m_F + s.m_F.transpose()) * 0.5 - btMatrix3x3::getIdentity();
+ btScalar trace = epsilon[0][0] + epsilon[1][1] + epsilon[2][2];
+ P = epsilon * btScalar(2) * m_mu + btMatrix3x3::getIdentity() * m_lambda * trace;
+ }
+
+ // Let P be the first piola stress.
+ // This function calculates the dP = dP/dF * dF
+ void firstPiolaDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+ {
+ btScalar trace = (dF[0][0] + dF[1][1] + dF[2][2]);
+ dP = (dF + dF.transpose()) * m_mu + btMatrix3x3::getIdentity() * m_lambda * trace;
+ }
+
+ // Let Q be the damping stress.
+ // This function calculates the dP = dQ/dF * dF
+ void firstPiolaDampingDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+ {
+ btScalar trace = (dF[0][0] + dF[1][1] + dF[2][2]);
+ dP = (dF + dF.transpose()) * m_mu_damp + btMatrix3x3::getIdentity() * m_lambda_damp * trace;
+ }
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_LINEAR_ELASTICITY_FORCE;
+ }
+
+};
+#endif /* BT_LINEAR_ELASTICITY_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h
new file mode 100644
index 0000000000..b128df92cc
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h
@@ -0,0 +1,301 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_MASS_SPRING_H
+#define BT_MASS_SPRING_H
+
+#include "btDeformableLagrangianForce.h"
+
+class btDeformableMassSpringForce : public btDeformableLagrangianForce
+{
+ // If true, the damping force will be in the direction of the spring
+ // If false, the damping force will be in the direction of the velocity
+ bool m_momentum_conserving;
+ btScalar m_elasticStiffness, m_dampingStiffness, m_bendingStiffness;
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btDeformableMassSpringForce() : m_momentum_conserving(false), m_elasticStiffness(1), m_dampingStiffness(0.05)
+ {
+ }
+ btDeformableMassSpringForce(btScalar k, btScalar d, bool conserve_angular = true, double bending_k = -1) : m_momentum_conserving(conserve_angular), m_elasticStiffness(k), m_dampingStiffness(d), m_bendingStiffness(bending_k)
+ {
+ if (m_bendingStiffness < btScalar(0))
+ {
+ m_bendingStiffness = m_elasticStiffness;
+ }
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledDampingForce(scale, force);
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ const btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+
+ // damping force
+ btVector3 v_diff = (node2->m_v - node1->m_v);
+ btVector3 scaled_force = scale * m_dampingStiffness * v_diff;
+ if (m_momentum_conserving)
+ {
+ if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
+ {
+ btVector3 dir = (node2->m_x - node1->m_x).normalized();
+ scaled_force = scale * m_dampingStiffness * v_diff.dot(dir) * dir;
+ }
+ }
+ force[id1] += scaled_force;
+ force[id2] -= scaled_force;
+ }
+ }
+ }
+
+ virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ const btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ btScalar r = link.m_rl;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+
+ // elastic force
+ btVector3 dir = (node2->m_q - node1->m_q);
+ btVector3 dir_normalized = (dir.norm() > SIMD_EPSILON) ? dir.normalized() : btVector3(0,0,0);
+ btScalar scaled_stiffness = scale * (link.m_bbending ? m_bendingStiffness : m_elasticStiffness);
+ btVector3 scaled_force = scaled_stiffness * (dir - dir_normalized * r);
+ force[id1] += scaled_force;
+ force[id2] -= scaled_force;
+ }
+ }
+ }
+
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ // implicit damping force differential
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ btScalar scaled_k_damp = m_dampingStiffness * scale;
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+
+ btVector3 local_scaled_df = scaled_k_damp * (dv[id2] - dv[id1]);
+ if (m_momentum_conserving)
+ {
+ if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
+ {
+ btVector3 dir = (node2->m_x - node1->m_x).normalized();
+ local_scaled_df= scaled_k_damp * (dv[id2] - dv[id1]).dot(dir) * dir;
+ }
+ }
+ df[id1] += local_scaled_df;
+ df[id2] -= local_scaled_df;
+ }
+ }
+ }
+
+ virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA)
+ {
+ // implicit damping force differential
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ btScalar scaled_k_damp = m_dampingStiffness * scale;
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ if (m_momentum_conserving)
+ {
+ if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
+ {
+ btVector3 dir = (node2->m_x - node1->m_x).normalized();
+ for (int d = 0; d < 3; ++d)
+ {
+ if (node1->m_im > 0)
+ diagA[id1][d] -= scaled_k_damp * dir[d] * dir[d];
+ if (node2->m_im > 0)
+ diagA[id2][d] -= scaled_k_damp * dir[d] * dir[d];
+ }
+ }
+ }
+ else
+ {
+ for (int d = 0; d < 3; ++d)
+ {
+ if (node1->m_im > 0)
+ diagA[id1][d] -= scaled_k_damp;
+ if (node2->m_im > 0)
+ diagA[id2][d] -= scaled_k_damp;
+ }
+ }
+ }
+ }
+ }
+
+ virtual double totalElasticEnergy(btScalar dt)
+ {
+ double energy = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ const btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ btScalar r = link.m_rl;
+
+ // elastic force
+ btVector3 dir = (node2->m_q - node1->m_q);
+ energy += 0.5 * m_elasticStiffness * (dir.norm() - r) * (dir.norm() -r);
+ }
+ }
+ return energy;
+ }
+
+ virtual double totalDampingEnergy(btScalar dt)
+ {
+ double energy = 0;
+ int sz = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ sz = btMax(sz, psb->m_nodes[j].index);
+ }
+ }
+ TVStack dampingForce;
+ dampingForce.resize(sz+1);
+ for (int i = 0; i < dampingForce.size(); ++i)
+ dampingForce[i].setZero();
+ addScaledDampingForce(0.5, dampingForce);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ energy -= dampingForce[node.index].dot(node.m_v) / dt;
+ }
+ }
+ return energy;
+ }
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ // implicit damping force differential
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ const btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_links.size(); ++j)
+ {
+ const btSoftBody::Link& link = psb->m_links[j];
+ btSoftBody::Node* node1 = link.m_n[0];
+ btSoftBody::Node* node2 = link.m_n[1];
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ btScalar r = link.m_rl;
+
+ btVector3 dir = (node1->m_q - node2->m_q);
+ btScalar dir_norm = dir.norm();
+ btVector3 dir_normalized = (dir_norm > SIMD_EPSILON) ? dir.normalized() : btVector3(0,0,0);
+ btVector3 dx_diff = dx[id1] - dx[id2];
+ btVector3 scaled_df = btVector3(0,0,0);
+ btScalar scaled_k = scale * (link.m_bbending ? m_bendingStiffness : m_elasticStiffness);
+ if (dir_norm > SIMD_EPSILON)
+ {
+ scaled_df -= scaled_k * dir_normalized.dot(dx_diff) * dir_normalized;
+ scaled_df += scaled_k * dir_normalized.dot(dx_diff) * ((dir_norm-r)/dir_norm) * dir_normalized;
+ scaled_df -= scaled_k * ((dir_norm-r)/dir_norm) * dx_diff;
+ }
+
+ df[id1] += scaled_df;
+ df[id2] -= scaled_df;
+ }
+ }
+ }
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_MASSSPRING_FORCE;
+ }
+
+};
+
+#endif /* btMassSpring_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMousePickingForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableMousePickingForce.h
new file mode 100644
index 0000000000..07c10935f4
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMousePickingForce.h
@@ -0,0 +1,145 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_MOUSE_PICKING_FORCE_H
+#define BT_MOUSE_PICKING_FORCE_H
+
+#include "btDeformableLagrangianForce.h"
+
+class btDeformableMousePickingForce : public btDeformableLagrangianForce
+{
+ // If true, the damping force will be in the direction of the spring
+ // If false, the damping force will be in the direction of the velocity
+ btScalar m_elasticStiffness, m_dampingStiffness;
+ const btSoftBody::Face& m_face;
+ btVector3 m_mouse_pos;
+ btScalar m_maxForce;
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btDeformableMousePickingForce(btScalar k, btScalar d, const btSoftBody::Face& face, btVector3 mouse_pos, btScalar maxForce = 0.3) : m_elasticStiffness(k), m_dampingStiffness(d), m_face(face), m_mouse_pos(mouse_pos), m_maxForce(maxForce)
+ {
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledDampingForce(scale, force);
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ for (int i = 0; i < 3; ++i)
+ {
+ btVector3 v_diff = m_face.m_n[i]->m_v;
+ btVector3 scaled_force = scale * m_dampingStiffness * v_diff;
+ if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
+ {
+ btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
+ scaled_force = scale * m_dampingStiffness * v_diff.dot(dir) * dir;
+ }
+ force[m_face.m_n[i]->index] -= scaled_force;
+ }
+ }
+
+ virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+ {
+ btScalar scaled_stiffness = scale * m_elasticStiffness;
+ for (int i = 0; i < 3; ++i)
+ {
+ btVector3 dir = (m_face.m_n[i]->m_q - m_mouse_pos);
+ btVector3 scaled_force = scaled_stiffness * dir;
+ if (scaled_force.safeNorm() > m_maxForce)
+ {
+ scaled_force.safeNormalize();
+ scaled_force *= m_maxForce;
+ }
+ force[m_face.m_n[i]->index] -= scaled_force;
+ }
+ }
+
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ btScalar scaled_k_damp = m_dampingStiffness * scale;
+ for (int i = 0; i < 3; ++i)
+ {
+ btVector3 local_scaled_df = scaled_k_damp * dv[m_face.m_n[i]->index];
+ if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
+ {
+ btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
+ local_scaled_df= scaled_k_damp * dv[m_face.m_n[i]->index].dot(dir) * dir;
+ }
+ df[m_face.m_n[i]->index] -= local_scaled_df;
+ }
+ }
+
+ virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA){}
+
+ virtual double totalElasticEnergy(btScalar dt)
+ {
+ double energy = 0;
+ for (int i = 0; i < 3; ++i)
+ {
+ btVector3 dir = (m_face.m_n[i]->m_q - m_mouse_pos);
+ btVector3 scaled_force = m_elasticStiffness * dir;
+ if (scaled_force.safeNorm() > m_maxForce)
+ {
+ scaled_force.safeNormalize();
+ scaled_force *= m_maxForce;
+ }
+ energy += 0.5 * scaled_force.dot(dir);
+ }
+ return energy;
+ }
+
+ virtual double totalDampingEnergy(btScalar dt)
+ {
+ double energy = 0;
+ for (int i = 0; i < 3; ++i)
+ {
+ btVector3 v_diff = m_face.m_n[i]->m_v;
+ btVector3 scaled_force = m_dampingStiffness * v_diff;
+ if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
+ {
+ btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
+ scaled_force = m_dampingStiffness * v_diff.dot(dir) * dir;
+ }
+ energy -= scaled_force.dot(m_face.m_n[i]->m_v) / dt;
+ }
+ return energy;
+ }
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ //TODO
+ }
+
+ void setMousePos(const btVector3& p)
+ {
+ m_mouse_pos = p;
+ }
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_MOUSE_PICKING_FORCE;
+ }
+
+};
+
+#endif /* btMassSpring_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp
new file mode 100644
index 0000000000..c8cc47923e
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp
@@ -0,0 +1,143 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+
+#include "btDeformableMultiBodyConstraintSolver.h"
+#include <iostream>
+// override the iterations method to include deformable/multibody contact
+btScalar btDeformableMultiBodyConstraintSolver::solveDeformableGroupIterations(btCollisionObject** bodies,int numBodies,btCollisionObject** deformableBodies,int numDeformableBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
+{
+ {
+ ///this is a special step to resolve penetrations (just for contacts)
+ solveGroupCacheFriendlySplitImpulseIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+ int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
+ for (int iteration = 0; iteration < maxIterations; iteration++)
+ {
+ // rigid bodies are solved using solver body velocity, but rigid/deformable contact directly uses the velocity of the actual rigid body. So we have to do the following: Solve one iteration of the rigid/rigid contact, get the updated velocity in the solver body and update the velocity of the underlying rigid body. Then solve the rigid/deformable contact. Finally, grab the (once again) updated rigid velocity and update the velocity of the wrapping solver body
+
+ // solve rigid/rigid in solver body
+ m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+ // solver body velocity -> rigid body velocity
+ solverBodyWriteBack(infoGlobal);
+ btScalar deformableResidual = m_deformableSolver->solveContactConstraints(deformableBodies,numDeformableBodies, infoGlobal);
+ // update rigid body velocity in rigid/deformable contact
+ m_leastSquaresResidual = btMax(m_leastSquaresResidual, deformableResidual);
+ // solver body velocity <- rigid body velocity
+ writeToSolverBody(bodies, numBodies, infoGlobal);
+
+ if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1)))
+ {
+#ifdef VERBOSE_RESIDUAL_PRINTF
+ printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
+#endif
+ m_analyticsData.m_numSolverCalls++;
+ m_analyticsData.m_numIterationsUsed = iteration+1;
+ m_analyticsData.m_islandId = -2;
+ if (numBodies>0)
+ m_analyticsData.m_islandId = bodies[0]->getCompanionId();
+ m_analyticsData.m_numBodies = numBodies;
+ m_analyticsData.m_numContactManifolds = numManifolds;
+ m_analyticsData.m_remainingLeastSquaresResidual = m_leastSquaresResidual;
+ break;
+ }
+ }
+ }
+ return 0.f;
+}
+
+void btDeformableMultiBodyConstraintSolver::solveDeformableBodyGroup(btCollisionObject * *bodies, int numBodies, btCollisionObject * *deformableBodies, int numDeformableBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
+{
+ m_tmpMultiBodyConstraints = multiBodyConstraints;
+ m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
+
+ // inherited from MultiBodyConstraintSolver
+ solveGroupCacheFriendlySetup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer);
+
+ // overriden
+ solveDeformableGroupIterations(bodies, numBodies, deformableBodies, numDeformableBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer);
+
+ // inherited from MultiBodyConstraintSolver
+ solveGroupCacheFriendlyFinish(bodies, numBodies, info);
+
+ m_tmpMultiBodyConstraints = 0;
+ m_tmpNumMultiBodyConstraints = 0;
+}
+
+void btDeformableMultiBodyConstraintSolver::writeToSolverBody(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+ for (int i = 0; i < numBodies; i++)
+ {
+ int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
+
+ btRigidBody* body = btRigidBody::upcast(bodies[i]);
+ if (body && body->getInvMass())
+ {
+ btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
+ solverBody.m_linearVelocity = body->getLinearVelocity() - solverBody.m_deltaLinearVelocity;
+ solverBody.m_angularVelocity = body->getAngularVelocity() - solverBody.m_deltaAngularVelocity;
+ }
+ }
+}
+
+void btDeformableMultiBodyConstraintSolver::solverBodyWriteBack(const btContactSolverInfo& infoGlobal)
+{
+ for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
+ {
+ btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
+ if (body)
+ {
+ m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(m_tmpSolverBodyPool[i].m_linearVelocity + m_tmpSolverBodyPool[i].m_deltaLinearVelocity);
+ m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(m_tmpSolverBodyPool[i].m_angularVelocity+m_tmpSolverBodyPool[i].m_deltaAngularVelocity);
+ }
+ }
+}
+
+void btDeformableMultiBodyConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+ BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
+ int iteration;
+ if (infoGlobal.m_splitImpulse)
+ {
+ {
+// m_deformableSolver->splitImpulseSetup(infoGlobal);
+ for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
+ {
+ btScalar leastSquaresResidual = 0.f;
+ {
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int j;
+ for (j = 0; j < numPoolConstraints; j++)
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+
+ btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+ leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+ }
+ // solve the position correction between deformable and rigid/multibody
+// btScalar residual = m_deformableSolver->solveSplitImpulse(infoGlobal);
+// leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+ }
+ if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
+ {
+#ifdef VERBOSE_RESIDUAL_PRINTF
+ printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
+#endif
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h
new file mode 100644
index 0000000000..0c7cc26a83
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h
@@ -0,0 +1,61 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+
+#ifndef BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H
+#define BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H
+
+#include "btDeformableBodySolver.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
+
+class btDeformableBodySolver;
+
+// btDeformableMultiBodyConstraintSolver extendsn btMultiBodyConstraintSolver to solve for the contact among rigid/multibody and deformable bodies. Notice that the following constraints
+// 1. rigid/multibody against rigid/multibody
+// 2. rigid/multibody against deforamble
+// 3. deformable against deformable
+// 4. deformable self collision
+// 5. joint constraints
+// are all coupled in this solve.
+ATTRIBUTE_ALIGNED16(class)
+btDeformableMultiBodyConstraintSolver : public btMultiBodyConstraintSolver
+{
+ btDeformableBodySolver* m_deformableSolver;
+
+protected:
+ // override the iterations method to include deformable/multibody contact
+// virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
+
+ // write the velocity of the the solver body to the underlying rigid body
+ void solverBodyWriteBack(const btContactSolverInfo& infoGlobal);
+
+ // write the velocity of the underlying rigid body to the the the solver body
+ void writeToSolverBody(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+
+ virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+
+ virtual btScalar solveDeformableGroupIterations(btCollisionObject** bodies,int numBodies,btCollisionObject** deformableBodies,int numDeformableBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ void setDeformableSolver(btDeformableBodySolver* deformableSolver)
+ {
+ m_deformableSolver = deformableSolver;
+ }
+
+ virtual void solveDeformableBodyGroup(btCollisionObject * *bodies, int numBodies, btCollisionObject * *deformableBodies, int numDeformableBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
+};
+
+#endif /* BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp
new file mode 100644
index 0000000000..6b742978ef
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp
@@ -0,0 +1,808 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/* ====== Overview of the Deformable Algorithm ====== */
+
+/*
+A single step of the deformable body simulation contains the following main components:
+Call internalStepSimulation multiple times, to achieve 240Hz (4 steps of 60Hz).
+1. Deformable maintaintenance of rest lengths and volume preservation. Forces only depend on position: Update velocity to a temporary state v_{n+1}^* = v_n + explicit_force * dt / mass, where explicit forces include gravity and elastic forces.
+2. Detect discrete collisions between rigid and deformable bodies at position x_{n+1}^* = x_n + dt * v_{n+1}^*.
+
+3a. Solve all constraints, including LCP. Contact, position correction due to numerical drift, friction, and anchors for deformable.
+
+3b. 5 Newton steps (multiple step). Conjugent Gradient solves linear system. Deformable Damping: Then velocities of deformable bodies v_{n+1} are solved in
+ M(v_{n+1} - v_{n+1}^*) = damping_force * dt / mass,
+ by a conjugate gradient solver, where the damping force is implicit and depends on v_{n+1}.
+ Make sure contact constraints are not violated in step b by performing velocity projections as in the paper by Baraff and Witkin https://www.cs.cmu.edu/~baraff/papers/sig98.pdf. Dynamic frictions are treated as a force and added to the rhs of the CG solve, whereas static frictions are treated as constraints similar to contact.
+4. Position is updated via x_{n+1} = x_n + dt * v_{n+1}.
+
+
+The algorithm also closely resembles the one in http://physbam.stanford.edu/~fedkiw/papers/stanford2008-03.pdf
+ */
+
+#include <stdio.h>
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include "DeformableBodyInplaceSolverIslandCallback.h"
+#include "btDeformableBodySolver.h"
+#include "LinearMath/btQuickprof.h"
+#include "btSoftBodyInternals.h"
+btDeformableMultiBodyDynamicsWorld::btDeformableMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btDeformableMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btDeformableBodySolver* deformableBodySolver)
+: btMultiBodyDynamicsWorld(dispatcher, pairCache, (btMultiBodyConstraintSolver*)constraintSolver, collisionConfiguration),
+m_deformableBodySolver(deformableBodySolver), m_solverCallback(0)
+{
+ m_drawFlags = fDrawFlags::Std;
+ m_drawNodeTree = true;
+ m_drawFaceTree = false;
+ m_drawClusterTree = false;
+ m_sbi.m_broadphase = pairCache;
+ m_sbi.m_dispatcher = dispatcher;
+ m_sbi.m_sparsesdf.Initialize();
+ m_sbi.m_sparsesdf.setDefaultVoxelsz(0.005);
+ m_sbi.m_sparsesdf.Reset();
+
+ m_sbi.air_density = (btScalar)1.2;
+ m_sbi.water_density = 0;
+ m_sbi.water_offset = 0;
+ m_sbi.water_normal = btVector3(0, 0, 0);
+ m_sbi.m_gravity.setValue(0, -9.8, 0);
+ m_internalTime = 0.0;
+ m_implicit = false;
+ m_lineSearch = false;
+ m_useProjection = true;
+ m_ccdIterations = 5;
+ m_solverDeformableBodyIslandCallback = new DeformableBodyInplaceSolverIslandCallback(constraintSolver, dispatcher);
+}
+
+btDeformableMultiBodyDynamicsWorld::~btDeformableMultiBodyDynamicsWorld()
+{
+ delete m_solverDeformableBodyIslandCallback;
+}
+
+void btDeformableMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
+{
+ BT_PROFILE("internalSingleStepSimulation");
+ if (0 != m_internalPreTickCallback)
+ {
+ (*m_internalPreTickCallback)(this, timeStep);
+ }
+ reinitialize(timeStep);
+
+ // add gravity to velocity of rigid and multi bodys
+ applyRigidBodyGravity(timeStep);
+
+ ///apply gravity and explicit force to velocity, predict motion
+ predictUnconstraintMotion(timeStep);
+
+ ///perform collision detection that involves rigid/multi bodies
+ btMultiBodyDynamicsWorld::performDiscreteCollisionDetection();
+
+ btMultiBodyDynamicsWorld::calculateSimulationIslands();
+
+ beforeSolverCallbacks(timeStep);
+
+ ///solve contact constraints and then deformable bodies momemtum equation
+ solveConstraints(timeStep);
+
+ afterSolverCallbacks(timeStep);
+
+ performDeformableCollisionDetection();
+
+ applyRepulsionForce(timeStep);
+
+ performGeometricCollisions(timeStep);
+
+ integrateTransforms(timeStep);
+
+ ///update vehicle simulation
+ btMultiBodyDynamicsWorld::updateActions(timeStep);
+
+ updateActivationState(timeStep);
+ // End solver-wise simulation step
+ // ///////////////////////////////
+}
+
+void btDeformableMultiBodyDynamicsWorld::performDeformableCollisionDetection()
+{
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ m_softBodies[i]->m_softSoftCollision = true;
+ }
+
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ for (int j = i; j < m_softBodies.size(); ++j)
+ {
+ m_softBodies[i]->defaultCollisionHandler(m_softBodies[j]);
+ }
+ }
+
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ m_softBodies[i]->m_softSoftCollision = false;
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
+{
+ for (int i = 0; i < m_softBodies.size(); i++)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ psb->updateDeactivation(timeStep);
+ if (psb->wantsSleeping())
+ {
+ if (psb->getActivationState() == ACTIVE_TAG)
+ psb->setActivationState(WANTS_DEACTIVATION);
+ if (psb->getActivationState() == ISLAND_SLEEPING)
+ {
+ psb->setZeroVelocity();
+ }
+ }
+ else
+ {
+ if (psb->getActivationState() != DISABLE_DEACTIVATION)
+ psb->setActivationState(ACTIVE_TAG);
+ }
+ }
+ btMultiBodyDynamicsWorld::updateActivationState(timeStep);
+}
+
+void btDeformableMultiBodyDynamicsWorld::applyRepulsionForce(btScalar timeStep)
+{
+ BT_PROFILE("btDeformableMultiBodyDynamicsWorld::applyRepulsionForce");
+ for (int i = 0; i < m_softBodies.size(); i++)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (psb->isActive())
+ {
+ psb->applyRepulsionForce(timeStep, true);
+ }
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::performGeometricCollisions(btScalar timeStep)
+{
+ BT_PROFILE("btDeformableMultiBodyDynamicsWorld::performGeometricCollisions");
+ // refit the BVH tree for CCD
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (psb->isActive())
+ {
+ m_softBodies[i]->updateFaceTree(true, false);
+ m_softBodies[i]->updateNodeTree(true, false);
+ for (int j = 0; j < m_softBodies[i]->m_faces.size(); ++j)
+ {
+ btSoftBody::Face& f = m_softBodies[i]->m_faces[j];
+ f.m_n0 = (f.m_n[1]->m_x - f.m_n[0]->m_x).cross(f.m_n[2]->m_x - f.m_n[0]->m_x);
+ }
+ }
+ }
+
+ // clear contact points & update DBVT
+ for (int r = 0; r < m_ccdIterations; ++r)
+ {
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (psb->isActive())
+ {
+ // clear contact points in the previous iteration
+ psb->m_faceNodeContacts.clear();
+
+ // update m_q and normals for CCD calculation
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + timeStep * psb->m_nodes[j].m_v;
+ }
+ for (int j = 0; j < psb->m_faces.size(); ++j)
+ {
+ btSoftBody::Face& f = psb->m_faces[j];
+ f.m_n1 = (f.m_n[1]->m_q - f.m_n[0]->m_q).cross(f.m_n[2]->m_q - f.m_n[0]->m_q);
+ f.m_vn = (f.m_n[1]->m_v - f.m_n[0]->m_v).cross(f.m_n[2]->m_v - f.m_n[0]->m_v) * timeStep * timeStep;
+ }
+ }
+ }
+
+ // apply CCD to register new contact points
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ for (int j = i; j < m_softBodies.size(); ++j)
+ {
+ btSoftBody* psb1 = m_softBodies[i];
+ btSoftBody* psb2 = m_softBodies[j];
+ if (psb1->isActive() && psb2->isActive())
+ {
+ m_softBodies[i]->geometricCollisionHandler(m_softBodies[j]);
+ }
+ }
+ }
+
+ int penetration_count = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (psb->isActive())
+ {
+ penetration_count += psb->m_faceNodeContacts.size();
+ }
+ }
+ if (penetration_count == 0)
+ {
+ break;
+ }
+
+ // apply inelastic impulse
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (psb->isActive())
+ {
+ psb->applyRepulsionForce(timeStep, false);
+ }
+ }
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::softBodySelfCollision()
+{
+ BT_PROFILE("btDeformableMultiBodyDynamicsWorld::softBodySelfCollision");
+ for (int i = 0; i < m_softBodies.size(); i++)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (psb->isActive())
+ {
+ psb->defaultCollisionHandler(psb);
+ }
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::positionCorrection(btScalar timeStep)
+{
+ // correct the position of rigid bodies with temporary velocity generated from split impulse
+ btContactSolverInfo infoGlobal;
+ btVector3 zero(0,0,0);
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); ++i)
+ {
+ btRigidBody* rb = m_nonStaticRigidBodies[i];
+ //correct the position/orientation based on push/turn recovery
+ btTransform newTransform;
+ btVector3 pushVelocity = rb->getPushVelocity();
+ btVector3 turnVelocity = rb->getTurnVelocity();
+ if (pushVelocity[0] != 0.f || pushVelocity[1] != 0 || pushVelocity[2] != 0 || turnVelocity[0] != 0.f || turnVelocity[1] != 0 || turnVelocity[2] != 0)
+ {
+ btTransformUtil::integrateTransform(rb->getWorldTransform(), pushVelocity, turnVelocity * infoGlobal.m_splitImpulseTurnErp, timeStep, newTransform);
+ rb->setWorldTransform(newTransform);
+ rb->setPushVelocity(zero);
+ rb->setTurnVelocity(zero);
+ }
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+ BT_PROFILE("integrateTransforms");
+ positionCorrection(timeStep);
+ btMultiBodyDynamicsWorld::integrateTransforms(timeStep);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ btSoftBody::Node& node = psb->m_nodes[j];
+ btScalar maxDisplacement = psb->getWorldInfo()->m_maxDisplacement;
+ btScalar clampDeltaV = maxDisplacement / timeStep;
+ for (int c = 0; c < 3; c++)
+ {
+ if (node.m_v[c] > clampDeltaV)
+ {
+ node.m_v[c] = clampDeltaV;
+ }
+ if (node.m_v[c] < -clampDeltaV)
+ {
+ node.m_v[c] = -clampDeltaV;
+ }
+ }
+ node.m_x = node.m_x + timeStep * node.m_v;
+ node.m_q = node.m_x;
+ node.m_vn = node.m_v;
+ }
+ // enforce anchor constraints
+ for (int j = 0; j < psb->m_deformableAnchors.size();++j)
+ {
+ btSoftBody::DeformableNodeRigidAnchor& a = psb->m_deformableAnchors[j];
+ btSoftBody::Node* n = a.m_node;
+ n->m_x = a.m_cti.m_colObj->getWorldTransform() * a.m_local;
+
+ // update multibody anchor info
+ if (a.m_cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(a.m_cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ btVector3 nrm;
+ const btCollisionShape* shp = multibodyLinkCol->getCollisionShape();
+ const btTransform& wtr = multibodyLinkCol->getWorldTransform();
+ psb->m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(n->m_x),
+ shp,
+ nrm,
+ 0);
+ a.m_cti.m_normal = wtr.getBasis() * nrm;
+ btVector3 normal = a.m_cti.m_normal;
+ btVector3 t1 = generateUnitOrthogonalVector(normal);
+ btVector3 t2 = btCross(normal, t1);
+ btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+ findJacobian(multibodyLinkCol, jacobianData_normal, a.m_node->m_x, normal);
+ findJacobian(multibodyLinkCol, jacobianData_t1, a.m_node->m_x, t1);
+ findJacobian(multibodyLinkCol, jacobianData_t2, a.m_node->m_x, t2);
+
+ btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+ btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+ btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+ btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+ btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+ t1.getX(), t1.getY(), t1.getZ(),
+ t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ btMatrix3x3 local_impulse_matrix = (Diagonal(n->m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+ a.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+ a.jacobianData_normal = jacobianData_normal;
+ a.jacobianData_t1 = jacobianData_t1;
+ a.jacobianData_t2 = jacobianData_t2;
+ a.t1 = t1;
+ a.t2 = t2;
+ }
+ }
+ }
+ psb->interpolateRenderMesh();
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::solveConstraints(btScalar timeStep)
+{
+ BT_PROFILE("btDeformableMultiBodyDynamicsWorld::solveConstraints");
+ // save v_{n+1}^* velocity after explicit forces
+ m_deformableBodySolver->backupVelocity();
+
+ // set up constraints among multibodies and between multibodies and deformable bodies
+ setupConstraints();
+
+ // solve contact constraints
+ solveContactConstraints();
+
+ // set up the directions in which the velocity does not change in the momentum solve
+ if (m_useProjection)
+ m_deformableBodySolver->m_objective->m_projection.setProjection();
+ else
+ m_deformableBodySolver->m_objective->m_projection.setLagrangeMultiplier();
+
+ // for explicit scheme, m_backupVelocity = v_{n+1}^*
+ // for implicit scheme, m_backupVelocity = v_n
+ // Here, set dv = v_{n+1} - v_n for nodes in contact
+ m_deformableBodySolver->setupDeformableSolve(m_implicit);
+
+ // At this point, dv should be golden for nodes in contact
+ // proceed to solve deformable momentum equation
+ m_deformableBodySolver->solveDeformableConstraints(timeStep);
+}
+
+void btDeformableMultiBodyDynamicsWorld::setupConstraints()
+{
+ // set up constraints between multibody and deformable bodies
+ m_deformableBodySolver->setConstraints(m_solverInfo);
+
+ // set up constraints among multibodies
+ {
+ sortConstraints();
+ // setup the solver callback
+ btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
+ btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
+ m_solverDeformableBodyIslandCallback->setup(&m_solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
+
+ // build islands
+ m_islandManager->buildIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld());
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::sortConstraints()
+{
+ m_sortedConstraints.resize(m_constraints.size());
+ int i;
+ for (i = 0; i < getNumConstraints(); i++)
+ {
+ m_sortedConstraints[i] = m_constraints[i];
+ }
+ m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
+
+ m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
+ for (i = 0; i < m_multiBodyConstraints.size(); i++)
+ {
+ m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
+ }
+ m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
+}
+
+
+void btDeformableMultiBodyDynamicsWorld::solveContactConstraints()
+{
+ // process constraints on each island
+ m_islandManager->processIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverDeformableBodyIslandCallback);
+
+ // process deferred
+ m_solverDeformableBodyIslandCallback->processConstraints();
+ m_constraintSolver->allSolved(m_solverInfo, m_debugDrawer);
+
+ // write joint feedback
+ {
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+ m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+
+ if (bod->internalNeedsJointFeedback())
+ {
+ if (!bod->isUsingRK4Integration())
+ {
+ if (bod->internalNeedsJointFeedback())
+ {
+ bool isConstraintPass = true;
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(m_solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+ bod->processDeltaVeeMultiDof2();
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
+{
+ m_softBodies.push_back(body);
+
+ // Set the soft body solver that will deal with this body
+ // to be the world's solver
+ body->setSoftBodySolver(m_deformableBodySolver);
+
+ btCollisionWorld::addCollisionObject(body,
+ collisionFilterGroup,
+ collisionFilterMask);
+}
+
+void btDeformableMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ BT_PROFILE("predictUnconstraintMotion");
+ btMultiBodyDynamicsWorld::predictUnconstraintMotion(timeStep);
+ m_deformableBodySolver->predictMotion(timeStep);
+}
+
+void btDeformableMultiBodyDynamicsWorld::reinitialize(btScalar timeStep)
+{
+ m_internalTime += timeStep;
+ m_deformableBodySolver->setImplicit(m_implicit);
+ m_deformableBodySolver->setLineSearch(m_lineSearch);
+ m_deformableBodySolver->reinitialize(m_softBodies, timeStep);
+ btDispatcherInfo& dispatchInfo = btMultiBodyDynamicsWorld::getDispatchInfo();
+ dispatchInfo.m_timeStep = timeStep;
+ dispatchInfo.m_stepCount = 0;
+ dispatchInfo.m_debugDraw = btMultiBodyDynamicsWorld::getDebugDrawer();
+ btMultiBodyDynamicsWorld::getSolverInfo().m_timeStep = timeStep;
+ if (m_useProjection)
+ {
+ m_deformableBodySolver->m_useProjection = true;
+// m_deformableBodySolver->m_objective->m_projection.m_useStrainLimiting = true;
+ m_deformableBodySolver->m_objective->m_preconditioner = m_deformableBodySolver->m_objective->m_massPreconditioner;
+ }
+ else
+ {
+ m_deformableBodySolver->m_objective->m_preconditioner = m_deformableBodySolver->m_objective->m_KKTPreconditioner;
+ }
+
+}
+
+
+void btDeformableMultiBodyDynamicsWorld::debugDrawWorld()
+{
+
+ btMultiBodyDynamicsWorld::debugDrawWorld();
+
+ for (int i = 0; i < getSoftBodyArray().size(); i++)
+ {
+ btSoftBody* psb = (btSoftBody*)getSoftBodyArray()[i];
+ {
+ btSoftBodyHelpers::DrawFrame(psb, getDebugDrawer());
+ btSoftBodyHelpers::Draw(psb, getDebugDrawer(), getDrawFlags());
+ }
+ }
+
+
+}
+
+void btDeformableMultiBodyDynamicsWorld::applyRigidBodyGravity(btScalar timeStep)
+{
+ // Gravity is applied in stepSimulation and then cleared here and then applied here and then cleared here again
+ // so that 1) gravity is applied to velocity before constraint solve and 2) gravity is applied in each substep
+ // when there are multiple substeps
+ btMultiBodyDynamicsWorld::applyGravity();
+ // integrate rigid body gravity
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); ++i)
+ {
+ btRigidBody* rb = m_nonStaticRigidBodies[i];
+ rb->integrateVelocities(timeStep);
+ }
+
+ // integrate multibody gravity
+ {
+ forwardKinematics();
+ clearMultiBodyConstraintForces();
+ {
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ m_scratch_r.resize(bod->getNumLinks() + 1);
+ m_scratch_v.resize(bod->getNumLinks() + 1);
+ m_scratch_m.resize(bod->getNumLinks() + 1);
+ bool isConstraintPass = false;
+ {
+ if (!bod->isUsingRK4Integration())
+ {
+ bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(m_solverInfo.m_timeStep,
+ m_scratch_r, m_scratch_v, m_scratch_m,isConstraintPass,
+ getSolverInfo().m_jointFeedbackInWorldSpace,
+ getSolverInfo().m_jointFeedbackInJointFrame);
+ }
+ else
+ {
+ btAssert(" RK4Integration is not supported" );
+ }
+ }
+ }
+ }
+ }
+ }
+ clearGravity();
+}
+
+void btDeformableMultiBodyDynamicsWorld::clearGravity()
+{
+ BT_PROFILE("btMultiBody clearGravity");
+ // clear rigid body gravity
+ for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (body->isActive())
+ {
+ body->clearGravity();
+ }
+ }
+ // clear multibody gravity
+ for (int i = 0; i < this->m_multiBodies.size(); i++)
+ {
+ btMultiBody* bod = m_multiBodies[i];
+
+ bool isSleeping = false;
+
+ if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+ {
+ isSleeping = true;
+ }
+ for (int b = 0; b < bod->getNumLinks(); b++)
+ {
+ if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+ isSleeping = true;
+ }
+
+ if (!isSleeping)
+ {
+ bod->addBaseForce(-m_gravity * bod->getBaseMass());
+
+ for (int j = 0; j < bod->getNumLinks(); ++j)
+ {
+ bod->addLinkForce(j, -m_gravity * bod->getLinkMass(j));
+ }
+ }
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::beforeSolverCallbacks(btScalar timeStep)
+{
+ if (0 != m_internalTickCallback)
+ {
+ (*m_internalTickCallback)(this, timeStep);
+ }
+
+ if (0 != m_solverCallback)
+ {
+ (*m_solverCallback)(m_internalTime, this);
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::afterSolverCallbacks(btScalar timeStep)
+{
+ if (0 != m_solverCallback)
+ {
+ (*m_solverCallback)(m_internalTime, this);
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::addForce(btSoftBody* psb, btDeformableLagrangianForce* force)
+{
+ btAlignedObjectArray<btDeformableLagrangianForce*>& forces = m_deformableBodySolver->m_objective->m_lf;
+ bool added = false;
+ for (int i = 0; i < forces.size(); ++i)
+ {
+ if (forces[i]->getForceType() == force->getForceType())
+ {
+ forces[i]->addSoftBody(psb);
+ added = true;
+ break;
+ }
+ }
+ if (!added)
+ {
+ force->addSoftBody(psb);
+ force->setIndices(m_deformableBodySolver->m_objective->getIndices());
+ forces.push_back(force);
+ }
+}
+
+void btDeformableMultiBodyDynamicsWorld::removeForce(btSoftBody* psb, btDeformableLagrangianForce* force)
+{
+ btAlignedObjectArray<btDeformableLagrangianForce*>& forces = m_deformableBodySolver->m_objective->m_lf;
+ int removed_index = -1;
+ for (int i = 0; i < forces.size(); ++i)
+ {
+ if (forces[i]->getForceType() == force->getForceType())
+ {
+ forces[i]->removeSoftBody(psb);
+ if (forces[i]->m_softBodies.size() == 0)
+ removed_index = i;
+ break;
+ }
+ }
+ if (removed_index >= 0)
+ forces.removeAtIndex(removed_index);
+}
+
+void btDeformableMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
+{
+ m_softBodies.remove(body);
+ btCollisionWorld::removeCollisionObject(body);
+ // force a reinitialize so that node indices get updated.
+ m_deformableBodySolver->reinitialize(m_softBodies, btScalar(-1));
+}
+
+void btDeformableMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+ btSoftBody* body = btSoftBody::upcast(collisionObject);
+ if (body)
+ removeSoftBody(body);
+ else
+ btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
+}
+
+
+int btDeformableMultiBodyDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
+{
+ startProfiling(timeStep);
+
+ int numSimulationSubSteps = 0;
+
+ if (maxSubSteps)
+ {
+ //fixed timestep with interpolation
+ m_fixedTimeStep = fixedTimeStep;
+ m_localTime += timeStep;
+ if (m_localTime >= fixedTimeStep)
+ {
+ numSimulationSubSteps = int(m_localTime / fixedTimeStep);
+ m_localTime -= numSimulationSubSteps * fixedTimeStep;
+ }
+ }
+ else
+ {
+ //variable timestep
+ fixedTimeStep = timeStep;
+ m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
+ m_fixedTimeStep = 0;
+ if (btFuzzyZero(timeStep))
+ {
+ numSimulationSubSteps = 0;
+ maxSubSteps = 0;
+ }
+ else
+ {
+ numSimulationSubSteps = 1;
+ maxSubSteps = 1;
+ }
+ }
+
+ //process some debugging flags
+ if (getDebugDrawer())
+ {
+ btIDebugDraw* debugDrawer = getDebugDrawer();
+ gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
+ }
+ if (numSimulationSubSteps)
+ {
+ //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
+ int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps) ? maxSubSteps : numSimulationSubSteps;
+
+ saveKinematicState(fixedTimeStep * clampedSimulationSteps);
+
+ for (int i = 0; i < clampedSimulationSteps; i++)
+ {
+ internalSingleStepSimulation(fixedTimeStep);
+ synchronizeMotionStates();
+ }
+ }
+ else
+ {
+ synchronizeMotionStates();
+ }
+
+ clearForces();
+
+#ifndef BT_NO_PROFILE
+ CProfileManager::Increment_Frame_Counter();
+#endif //BT_NO_PROFILE
+
+ return numSimulationSubSteps;
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h
new file mode 100644
index 0000000000..76b58a0378
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h
@@ -0,0 +1,311 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
+#define BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
+
+#include "btSoftMultiBodyDynamicsWorld.h"
+#include "btDeformableLagrangianForce.h"
+#include "btDeformableMassSpringForce.h"
+#include "btDeformableBodySolver.h"
+#include "btDeformableMultiBodyConstraintSolver.h"
+#include "btSoftBodyHelpers.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include <functional>
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+
+class btDeformableBodySolver;
+class btDeformableLagrangianForce;
+struct MultiBodyInplaceSolverIslandCallback;
+struct DeformableBodyInplaceSolverIslandCallback;
+class btDeformableMultiBodyConstraintSolver;
+
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+
+class btDeformableMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld
+{
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ ///Solver classes that encapsulate multiple deformable bodies for solving
+ btDeformableBodySolver* m_deformableBodySolver;
+ btSoftBodyArray m_softBodies;
+ int m_drawFlags;
+ bool m_drawNodeTree;
+ bool m_drawFaceTree;
+ bool m_drawClusterTree;
+ btSoftBodyWorldInfo m_sbi;
+ btScalar m_internalTime;
+ int m_ccdIterations;
+ bool m_implicit;
+ bool m_lineSearch;
+ bool m_useProjection;
+ DeformableBodyInplaceSolverIslandCallback* m_solverDeformableBodyIslandCallback;
+
+ typedef void (*btSolverCallback)(btScalar time, btDeformableMultiBodyDynamicsWorld* world);
+ btSolverCallback m_solverCallback;
+
+protected:
+ virtual void internalSingleStepSimulation(btScalar timeStep);
+
+ virtual void integrateTransforms(btScalar timeStep);
+
+ void positionCorrection(btScalar timeStep);
+
+ void solveConstraints(btScalar timeStep);
+
+ void updateActivationState(btScalar timeStep);
+
+ void clearGravity();
+
+public:
+ btDeformableMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btDeformableMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btDeformableBodySolver* deformableBodySolver = 0);
+
+ virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
+
+ virtual void debugDrawWorld();
+
+ void setSolverCallback(btSolverCallback cb)
+ {
+ m_solverCallback = cb;
+ }
+
+ virtual ~btDeformableMultiBodyDynamicsWorld();
+
+ virtual btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld()
+ {
+ return (btMultiBodyDynamicsWorld*)(this);
+ }
+
+ virtual const btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld() const
+ {
+ return (const btMultiBodyDynamicsWorld*)(this);
+ }
+
+ virtual btDynamicsWorldType getWorldType() const
+ {
+ return BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD;
+ }
+
+ virtual void predictUnconstraintMotion(btScalar timeStep);
+
+ virtual void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
+
+ btSoftBodyArray& getSoftBodyArray()
+ {
+ return m_softBodies;
+ }
+
+ const btSoftBodyArray& getSoftBodyArray() const
+ {
+ return m_softBodies;
+ }
+
+ btSoftBodyWorldInfo& getWorldInfo()
+ {
+ return m_sbi;
+ }
+
+ const btSoftBodyWorldInfo& getWorldInfo() const
+ {
+ return m_sbi;
+ }
+
+ void reinitialize(btScalar timeStep);
+
+ void applyRigidBodyGravity(btScalar timeStep);
+
+ void beforeSolverCallbacks(btScalar timeStep);
+
+ void afterSolverCallbacks(btScalar timeStep);
+
+ void addForce(btSoftBody* psb, btDeformableLagrangianForce* force);
+
+ void removeForce(btSoftBody* psb, btDeformableLagrangianForce* force);
+
+ void removeSoftBody(btSoftBody* body);
+
+ void removeCollisionObject(btCollisionObject* collisionObject);
+
+ int getDrawFlags() const { return (m_drawFlags); }
+ void setDrawFlags(int f) { m_drawFlags = f; }
+
+ void setupConstraints();
+
+ void performDeformableCollisionDetection();
+
+ void solveMultiBodyConstraints();
+
+ void solveContactConstraints();
+
+ void sortConstraints();
+
+ void softBodySelfCollision();
+
+ void setImplicit(bool implicit)
+ {
+ m_implicit = implicit;
+ }
+
+ void setLineSearch(bool lineSearch)
+ {
+ m_lineSearch = lineSearch;
+ }
+
+ void applyRepulsionForce(btScalar timeStep);
+
+ void performGeometricCollisions(btScalar timeStep);
+
+ struct btDeformableSingleRayCallback : public btBroadphaseRayCallback
+ {
+ btVector3 m_rayFromWorld;
+ btVector3 m_rayToWorld;
+ btTransform m_rayFromTrans;
+ btTransform m_rayToTrans;
+ btVector3 m_hitNormal;
+
+ const btDeformableMultiBodyDynamicsWorld* m_world;
+ btCollisionWorld::RayResultCallback& m_resultCallback;
+
+ btDeformableSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btDeformableMultiBodyDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
+ : m_rayFromWorld(rayFromWorld),
+ m_rayToWorld(rayToWorld),
+ m_world(world),
+ m_resultCallback(resultCallback)
+ {
+ m_rayFromTrans.setIdentity();
+ m_rayFromTrans.setOrigin(m_rayFromWorld);
+ m_rayToTrans.setIdentity();
+ m_rayToTrans.setOrigin(m_rayToWorld);
+
+ btVector3 rayDir = (rayToWorld - rayFromWorld);
+
+ rayDir.normalize();
+ ///what about division by zero? --> just set rayDirection[i] to INF/1e30
+ m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
+ m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
+ m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
+ m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+ m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+ m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+ m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
+ }
+
+ virtual bool process(const btBroadphaseProxy* proxy)
+ {
+ ///terminate further ray tests, once the closestHitFraction reached zero
+ if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+ return false;
+
+ btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+ //only perform raycast if filterMask matches
+ if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+ {
+ //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+ //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+ btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+ collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+ //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+ const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+ const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+ //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+ //culling already done by broadphase
+ //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+ {
+ m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ m_resultCallback);
+ }
+ }
+ return true;
+ }
+ };
+
+
+
+ void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+ {
+ BT_PROFILE("rayTest");
+ /// use the broadphase to accelerate the search for objects, based on their aabb
+ /// and for each object with ray-aabb overlap, perform an exact ray test
+ btDeformableSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+ m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
+#else
+ for (int i = 0; i < this->getNumCollisionObjects(); i++)
+ {
+ rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+ }
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
+ }
+
+ void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+ btCollisionObject* collisionObject,
+ const btCollisionShape* collisionShape,
+ const btTransform& colObjWorldTransform,
+ RayResultCallback& resultCallback) const
+ {
+ if (collisionShape->isSoftBody())
+ {
+ btSoftBody* softBody = btSoftBody::upcast(collisionObject);
+ if (softBody)
+ {
+ btSoftBody::sRayCast softResult;
+ if (softBody->rayFaceTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
+ {
+ if (softResult.fraction <= resultCallback.m_closestHitFraction)
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = 0;
+ shapeInfo.m_triangleIndex = softResult.index;
+ // get the normal
+ btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
+ btVector3 normal = -rayDir;
+ normal.normalize();
+ {
+ normal = softBody->m_faces[softResult.index].m_normal;
+ if (normal.dot(rayDir) > 0)
+ {
+ // normal always point toward origin of the ray
+ normal = -normal;
+ }
+ }
+
+ btCollisionWorld::LocalRayResult rayResult(collisionObject,
+ &shapeInfo,
+ normal,
+ softResult.fraction);
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(rayResult, normalInWorldSpace);
+ }
+ }
+ }
+ }
+ else
+ {
+ btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
+ }
+ }
+};
+
+#endif //BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h
new file mode 100644
index 0000000000..d89bc4aca4
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h
@@ -0,0 +1,421 @@
+/*
+Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2019 Google Inc. http://bulletphysics.org
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_NEOHOOKEAN_H
+#define BT_NEOHOOKEAN_H
+
+#include "btDeformableLagrangianForce.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btImplicitQRSVD.h"
+// This energy is as described in https://graphics.pixar.com/library/StableElasticity/paper.pdf
+class btDeformableNeoHookeanForce : public btDeformableLagrangianForce
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ btScalar m_mu, m_lambda; // Lame Parameters
+ btScalar m_E, m_nu; // Young's modulus and Poisson ratio
+ btScalar m_mu_damp, m_lambda_damp;
+ btDeformableNeoHookeanForce(): m_mu(1), m_lambda(1)
+ {
+ btScalar damping = 0.05;
+ m_mu_damp = damping * m_mu;
+ m_lambda_damp = damping * m_lambda;
+ updateYoungsModulusAndPoissonRatio();
+ }
+
+ btDeformableNeoHookeanForce(btScalar mu, btScalar lambda, btScalar damping = 0.05): m_mu(mu), m_lambda(lambda)
+ {
+ m_mu_damp = damping * m_mu;
+ m_lambda_damp = damping * m_lambda;
+ updateYoungsModulusAndPoissonRatio();
+ }
+
+ void updateYoungsModulusAndPoissonRatio()
+ {
+ // conversion from Lame Parameters to Young's modulus and Poisson ratio
+ // https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
+ m_E = m_mu * (3*m_lambda + 2*m_mu)/(m_lambda + m_mu);
+ m_nu = m_lambda * 0.5 / (m_mu + m_lambda);
+ }
+
+ void updateLameParameters()
+ {
+ // conversion from Young's modulus and Poisson ratio to Lame Parameters
+ // https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
+ m_mu = m_E * 0.5 / (1 + m_nu);
+ m_lambda = m_E * m_nu / ((1 + m_nu) * (1- 2*m_nu));
+ }
+
+ void setYoungsModulus(btScalar E)
+ {
+ m_E = E;
+ updateLameParameters();
+ }
+
+ void setPoissonRatio(btScalar nu)
+ {
+ m_nu = nu;
+ updateLameParameters();
+ }
+
+ void setDamping(btScalar damping)
+ {
+ m_mu_damp = damping * m_mu;
+ m_lambda_damp = damping * m_lambda;
+ }
+
+ void setLameParameters(btScalar mu, btScalar lambda)
+ {
+ m_mu = mu;
+ m_lambda = lambda;
+ updateYoungsModulusAndPoissonRatio();
+ }
+
+ virtual void addScaledForces(btScalar scale, TVStack& force)
+ {
+ addScaledDampingForce(scale, force);
+ addScaledElasticForce(scale, force);
+ }
+
+ virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+ {
+ addScaledElasticForce(scale, force);
+ }
+
+ // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+ {
+ if (m_mu_damp == 0 && m_lambda_damp == 0)
+ return;
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = DsFromVelocity(node0, node1, node2, node3) * tetra.m_Dm_inverse;
+ btMatrix3x3 I;
+ I.setIdentity();
+ btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0]+dF[1][1]+dF[2][2]) * m_lambda_damp;
+// firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
+ btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+
+ // damping force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ force[id0] -= scale1 * df_on_node0;
+ force[id1] -= scale1 * df_on_node123.getColumn(0);
+ force[id2] -= scale1 * df_on_node123.getColumn(1);
+ force[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ virtual double totalElasticEnergy(btScalar dt)
+ {
+ double energy = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetraScratches.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::TetraScratch& s = psb->m_tetraScratches[j];
+ energy += tetra.m_element_measure * elasticEnergyDensity(s);
+ }
+ }
+ return energy;
+ }
+
+ // The damping energy is formulated as in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual double totalDampingEnergy(btScalar dt)
+ {
+ double energy = 0;
+ int sz = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ sz = btMax(sz, psb->m_nodes[j].index);
+ }
+ }
+ TVStack dampingForce;
+ dampingForce.resize(sz+1);
+ for (int i = 0; i < dampingForce.size(); ++i)
+ dampingForce[i].setZero();
+ addScaledDampingForce(0.5, dampingForce);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ energy -= dampingForce[node.index].dot(node.m_v) / dt;
+ }
+ }
+ return energy;
+ }
+
+ double elasticEnergyDensity(const btSoftBody::TetraScratch& s)
+ {
+ double density = 0;
+ density += m_mu * 0.5 * (s.m_trace - 3.);
+ density += m_lambda * 0.5 * (s.m_J - 1. - 0.75 * m_mu / m_lambda)* (s.m_J - 1. - 0.75 * m_mu / m_lambda);
+ density -= m_mu * 0.5 * log(s.m_trace+1);
+ return density;
+ }
+
+ virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= force.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ btScalar max_p = psb->m_cfg.m_maxStress;
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btMatrix3x3 P;
+ firstPiola(psb->m_tetraScratches[j],P);
+#ifdef USE_SVD
+ if (max_p > 0)
+ {
+ // since we want to clamp the principal stress to max_p, we only need to
+ // calculate SVD when sigma_0^2 + sigma_1^2 + sigma_2^2 > max_p * max_p
+ btScalar trPTP = (P[0].length2() + P[1].length2() + P[2].length2());
+ if (trPTP > max_p * max_p)
+ {
+ btMatrix3x3 U, V;
+ btVector3 sigma;
+ singularValueDecomposition(P, U, sigma, V);
+ sigma[0] = btMin(sigma[0], max_p);
+ sigma[1] = btMin(sigma[1], max_p);
+ sigma[2] = btMin(sigma[2], max_p);
+ sigma[0] = btMax(sigma[0], -max_p);
+ sigma[1] = btMax(sigma[1], -max_p);
+ sigma[2] = btMax(sigma[2], -max_p);
+ btMatrix3x3 Sigma;
+ Sigma.setIdentity();
+ Sigma[0][0] = sigma[0];
+ Sigma[1][1] = sigma[1];
+ Sigma[2][2] = sigma[2];
+ P = U * Sigma * V.transpose();
+ }
+ }
+#endif
+// btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 force_on_node123 = P * tetra.m_Dm_inverse.transpose();
+ btVector3 force_on_node0 = force_on_node123 * grad_N_hat_1st_col;
+
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+
+ // elastic force
+ btScalar scale1 = scale * tetra.m_element_measure;
+ force[id0] -= scale1 * force_on_node0;
+ force[id1] -= scale1 * force_on_node123.getColumn(0);
+ force[id2] -= scale1 * force_on_node123.getColumn(1);
+ force[id3] -= scale1 * force_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+ virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+ {
+ if (m_mu_damp == 0 && m_lambda_damp == 0)
+ return;
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= df.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = Ds(id0, id1, id2, id3, dv) * tetra.m_Dm_inverse;
+ btMatrix3x3 I;
+ I.setIdentity();
+ btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0]+dF[1][1]+dF[2][2]) * m_lambda_damp;
+// firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
+// btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+ btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+ // damping force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ df[id0] -= scale1 * df_on_node0;
+ df[id1] -= scale1 * df_on_node123.getColumn(0);
+ df[id2] -= scale1 * df_on_node123.getColumn(1);
+ df[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA){}
+
+ virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+ {
+ int numNodes = getNumNodes();
+ btAssert(numNodes <= df.size());
+ btVector3 grad_N_hat_1st_col = btVector3(-1,-1,-1);
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ if (!psb->isActive())
+ {
+ continue;
+ }
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ btSoftBody::Tetra& tetra = psb->m_tetras[j];
+ btSoftBody::Node* node0 = tetra.m_n[0];
+ btSoftBody::Node* node1 = tetra.m_n[1];
+ btSoftBody::Node* node2 = tetra.m_n[2];
+ btSoftBody::Node* node3 = tetra.m_n[3];
+ size_t id0 = node0->index;
+ size_t id1 = node1->index;
+ size_t id2 = node2->index;
+ size_t id3 = node3->index;
+ btMatrix3x3 dF = Ds(id0, id1, id2, id3, dx) * tetra.m_Dm_inverse;
+ btMatrix3x3 dP;
+ firstPiolaDifferential(psb->m_tetraScratches[j], dF, dP);
+// btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+ btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+ btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+ // elastic force differential
+ btScalar scale1 = scale * tetra.m_element_measure;
+ df[id0] -= scale1 * df_on_node0;
+ df[id1] -= scale1 * df_on_node123.getColumn(0);
+ df[id2] -= scale1 * df_on_node123.getColumn(1);
+ df[id3] -= scale1 * df_on_node123.getColumn(2);
+ }
+ }
+ }
+
+ void firstPiola(const btSoftBody::TetraScratch& s, btMatrix3x3& P)
+ {
+ btScalar c1 = (m_mu * ( 1. - 1. / (s.m_trace + 1.)));
+ btScalar c2 = (m_lambda * (s.m_J - 1.) - 0.75 * m_mu);
+ P = s.m_F * c1 + s.m_cofF * c2;
+ }
+
+ // Let P be the first piola stress.
+ // This function calculates the dP = dP/dF * dF
+ void firstPiolaDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+ {
+ btScalar c1 = m_mu * ( 1. - 1. / (s.m_trace + 1.));
+ btScalar c2 = (2.*m_mu) * DotProduct(s.m_F, dF) * (1./((1.+s.m_trace)*(1.+s.m_trace)));
+ btScalar c3 = (m_lambda * DotProduct(s.m_cofF, dF));
+ dP = dF * c1 + s.m_F * c2;
+ addScaledCofactorMatrixDifferential(s.m_F, dF, m_lambda*(s.m_J-1.) - 0.75*m_mu, dP);
+ dP += s.m_cofF * c3;
+ }
+
+ // Let Q be the damping stress.
+ // This function calculates the dP = dQ/dF * dF
+ void firstPiolaDampingDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+ {
+ btScalar c1 = (m_mu_damp * ( 1. - 1. / (s.m_trace + 1.)));
+ btScalar c2 = ((2.*m_mu_damp) * DotProduct(s.m_F, dF) *(1./((1.+s.m_trace)*(1.+s.m_trace))));
+ btScalar c3 = (m_lambda_damp * DotProduct(s.m_cofF, dF));
+ dP = dF * c1 + s.m_F * c2;
+ addScaledCofactorMatrixDifferential(s.m_F, dF, m_lambda_damp*(s.m_J-1.) - 0.75*m_mu_damp, dP);
+ dP += s.m_cofF * c3;
+ }
+
+ btScalar DotProduct(const btMatrix3x3& A, const btMatrix3x3& B)
+ {
+ btScalar ans = 0;
+ for (int i = 0; i < 3; ++i)
+ {
+ ans += A[i].dot(B[i]);
+ }
+ return ans;
+ }
+
+ // Let C(A) be the cofactor of the matrix A
+ // Let H = the derivative of C(A) with respect to A evaluated at F = A
+ // This function calculates H*dF
+ void addScaledCofactorMatrixDifferential(const btMatrix3x3& F, const btMatrix3x3& dF, btScalar scale, btMatrix3x3& M)
+ {
+ M[0][0] += scale * (dF[1][1] * F[2][2] + F[1][1] * dF[2][2] - dF[2][1] * F[1][2] - F[2][1] * dF[1][2]);
+ M[1][0] += scale * (dF[2][1] * F[0][2] + F[2][1] * dF[0][2] - dF[0][1] * F[2][2] - F[0][1] * dF[2][2]);
+ M[2][0] += scale * (dF[0][1] * F[1][2] + F[0][1] * dF[1][2] - dF[1][1] * F[0][2] - F[1][1] * dF[0][2]);
+ M[0][1] += scale * (dF[2][0] * F[1][2] + F[2][0] * dF[1][2] - dF[1][0] * F[2][2] - F[1][0] * dF[2][2]);
+ M[1][1] += scale * (dF[0][0] * F[2][2] + F[0][0] * dF[2][2] - dF[2][0] * F[0][2] - F[2][0] * dF[0][2]);
+ M[2][1] += scale * (dF[1][0] * F[0][2] + F[1][0] * dF[0][2] - dF[0][0] * F[1][2] - F[0][0] * dF[1][2]);
+ M[0][2] += scale * (dF[1][0] * F[2][1] + F[1][0] * dF[2][1] - dF[2][0] * F[1][1] - F[2][0] * dF[1][1]);
+ M[1][2] += scale * (dF[2][0] * F[0][1] + F[2][0] * dF[0][1] - dF[0][0] * F[2][1] - F[0][0] * dF[2][1]);
+ M[2][2] += scale * (dF[0][0] * F[1][1] + F[0][0] * dF[1][1] - dF[1][0] * F[0][1] - F[1][0] * dF[0][1]);
+ }
+
+ virtual btDeformableLagrangianForceType getForceType()
+ {
+ return BT_NEOHOOKEAN_FORCE;
+ }
+
+};
+#endif /* BT_NEOHOOKEAN_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btPreconditioner.h b/thirdparty/bullet/BulletSoftBody/btPreconditioner.h
new file mode 100644
index 0000000000..c2db448ef8
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/btPreconditioner.h
@@ -0,0 +1,288 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef BT_PRECONDITIONER_H
+#define BT_PRECONDITIONER_H
+
+class Preconditioner
+{
+public:
+ typedef btAlignedObjectArray<btVector3> TVStack;
+ virtual void operator()(const TVStack& x, TVStack& b) = 0;
+ virtual void reinitialize(bool nodeUpdated) = 0;
+ virtual ~Preconditioner(){}
+};
+
+class DefaultPreconditioner : public Preconditioner
+{
+public:
+ virtual void operator()(const TVStack& x, TVStack& b)
+ {
+ btAssert(b.size() == x.size());
+ for (int i = 0; i < b.size(); ++i)
+ b[i] = x[i];
+ }
+ virtual void reinitialize(bool nodeUpdated)
+ {
+ }
+
+ virtual ~DefaultPreconditioner(){}
+};
+
+class MassPreconditioner : public Preconditioner
+{
+ btAlignedObjectArray<btScalar> m_inv_mass;
+ const btAlignedObjectArray<btSoftBody *>& m_softBodies;
+public:
+ MassPreconditioner(const btAlignedObjectArray<btSoftBody *>& softBodies)
+ : m_softBodies(softBodies)
+ {
+ }
+
+ virtual void reinitialize(bool nodeUpdated)
+ {
+ if (nodeUpdated)
+ {
+ m_inv_mass.clear();
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ m_inv_mass.push_back(psb->m_nodes[j].m_im);
+ }
+ }
+ }
+
+ virtual void operator()(const TVStack& x, TVStack& b)
+ {
+ btAssert(b.size() == x.size());
+ btAssert(m_inv_mass.size() <= x.size());
+ for (int i = 0; i < m_inv_mass.size(); ++i)
+ {
+ b[i] = x[i] * m_inv_mass[i];
+ }
+ for (int i = m_inv_mass.size(); i < b.size(); ++i)
+ {
+ b[i] = x[i];
+ }
+ }
+};
+
+
+class KKTPreconditioner : public Preconditioner
+{
+ const btAlignedObjectArray<btSoftBody *>& m_softBodies;
+ const btDeformableContactProjection& m_projections;
+ const btAlignedObjectArray<btDeformableLagrangianForce*>& m_lf;
+ TVStack m_inv_A, m_inv_S;
+ const btScalar& m_dt;
+ const bool& m_implicit;
+public:
+ KKTPreconditioner(const btAlignedObjectArray<btSoftBody *>& softBodies, const btDeformableContactProjection& projections, const btAlignedObjectArray<btDeformableLagrangianForce*>& lf, const btScalar& dt, const bool& implicit)
+ : m_softBodies(softBodies)
+ , m_projections(projections)
+ , m_lf(lf)
+ , m_dt(dt)
+ , m_implicit(implicit)
+ {
+ }
+
+ virtual void reinitialize(bool nodeUpdated)
+ {
+ if (nodeUpdated)
+ {
+ int num_nodes = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ num_nodes += psb->m_nodes.size();
+ }
+ m_inv_A.resize(num_nodes);
+ }
+ buildDiagonalA(m_inv_A);
+ for (int i = 0; i < m_inv_A.size(); ++i)
+ {
+// printf("A[%d] = %f, %f, %f \n", i, m_inv_A[i][0], m_inv_A[i][1], m_inv_A[i][2]);
+ for (int d = 0; d < 3; ++d)
+ {
+ m_inv_A[i][d] = (m_inv_A[i][d] == 0) ? 0.0 : 1.0/ m_inv_A[i][d];
+ }
+ }
+ m_inv_S.resize(m_projections.m_lagrangeMultipliers.size());
+// printf("S.size() = %d \n", m_inv_S.size());
+ buildDiagonalS(m_inv_A, m_inv_S);
+ for (int i = 0; i < m_inv_S.size(); ++i)
+ {
+// printf("S[%d] = %f, %f, %f \n", i, m_inv_S[i][0], m_inv_S[i][1], m_inv_S[i][2]);
+ for (int d = 0; d < 3; ++d)
+ {
+ m_inv_S[i][d] = (m_inv_S[i][d] == 0) ? 0.0 : 1.0/ m_inv_S[i][d];
+ }
+ }
+ }
+
+ void buildDiagonalA(TVStack& diagA) const
+ {
+ size_t counter = 0;
+ for (int i = 0; i < m_softBodies.size(); ++i)
+ {
+ btSoftBody* psb = m_softBodies[i];
+ for (int j = 0; j < psb->m_nodes.size(); ++j)
+ {
+ const btSoftBody::Node& node = psb->m_nodes[j];
+ diagA[counter] = (node.m_im == 0) ? btVector3(0,0,0) : btVector3(1.0/node.m_im, 1.0 / node.m_im, 1.0 / node.m_im);
+ ++counter;
+ }
+ }
+ if (m_implicit)
+ {
+ printf("implicit not implemented\n");
+ btAssert(false);
+ }
+ for (int i = 0; i < m_lf.size(); ++i)
+ {
+ // add damping matrix
+ m_lf[i]->buildDampingForceDifferentialDiagonal(-m_dt, diagA);
+ }
+ }
+
+ void buildDiagonalS(const TVStack& inv_A, TVStack& diagS)
+ {
+ for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+ {
+ // S[k,k] = e_k^T * C A_d^-1 C^T * e_k
+ const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+ btVector3& t = diagS[c];
+ t.setZero();
+ for (int j = 0; j < lm.m_num_constraints; ++j)
+ {
+ for (int i = 0; i < lm.m_num_nodes; ++i)
+ {
+ for (int d = 0; d < 3; ++d)
+ {
+ t[j] += inv_A[lm.m_indices[i]][d] * lm.m_dirs[j][d] * lm.m_dirs[j][d] * lm.m_weights[i] * lm.m_weights[i];
+ }
+ }
+ }
+ }
+ }
+#define USE_FULL_PRECONDITIONER
+#ifndef USE_FULL_PRECONDITIONER
+ virtual void operator()(const TVStack& x, TVStack& b)
+ {
+ btAssert(b.size() == x.size());
+ for (int i = 0; i < m_inv_A.size(); ++i)
+ {
+ b[i] = x[i] * m_inv_A[i];
+ }
+ int offset = m_inv_A.size();
+ for (int i = 0; i < m_inv_S.size(); ++i)
+ {
+ b[i+offset] = x[i+offset] * m_inv_S[i];
+ }
+ }
+#else
+ virtual void operator()(const TVStack& x, TVStack& b)
+ {
+ btAssert(b.size() == x.size());
+ int offset = m_inv_A.size();
+
+ for (int i = 0; i < m_inv_A.size(); ++i)
+ {
+ b[i] = x[i] * m_inv_A[i];
+ }
+
+ for (int i = 0; i < m_inv_S.size(); ++i)
+ {
+ b[i+offset].setZero();
+ }
+
+ for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+ {
+ const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+ // C * x
+ for (int d = 0; d < lm.m_num_constraints; ++d)
+ {
+ for (int i = 0; i < lm.m_num_nodes; ++i)
+ {
+ b[offset+c][d] += lm.m_weights[i] * b[lm.m_indices[i]].dot(lm.m_dirs[d]);
+ }
+ }
+ }
+
+ for (int i = 0; i < m_inv_S.size(); ++i)
+ {
+ b[i+offset] = b[i+offset] * m_inv_S[i];
+ }
+
+ for (int i = 0; i < m_inv_A.size(); ++i)
+ {
+ b[i].setZero();
+ }
+
+ for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+ {
+ // C^T * lambda
+ const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+ for (int i = 0; i < lm.m_num_nodes; ++i)
+ {
+ for (int j = 0; j < lm.m_num_constraints; ++j)
+ {
+ b[lm.m_indices[i]] += b[offset+c][j] * lm.m_weights[i] * lm.m_dirs[j];
+ }
+ }
+ }
+
+ for (int i = 0; i < m_inv_A.size(); ++i)
+ {
+ b[i] = (x[i] - b[i]) * m_inv_A[i];
+ }
+
+ TVStack t;
+ t.resize(b.size());
+ for (int i = 0; i < m_inv_S.size(); ++i)
+ {
+ t[i+offset] = x[i+offset] * m_inv_S[i];
+ }
+ for (int i = 0; i < m_inv_A.size(); ++i)
+ {
+ t[i].setZero();
+ }
+ for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+ {
+ // C^T * lambda
+ const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+ for (int i = 0; i < lm.m_num_nodes; ++i)
+ {
+ for (int j = 0; j < lm.m_num_constraints; ++j)
+ {
+ t[lm.m_indices[i]] += t[offset+c][j] * lm.m_weights[i] * lm.m_dirs[j];
+ }
+ }
+ }
+ for (int i = 0; i < m_inv_A.size(); ++i)
+ {
+ b[i] += t[i] * m_inv_A[i];
+ }
+
+ for (int i = 0; i < m_inv_S.size(); ++i)
+ {
+ b[i+offset] -= x[i+offset] * m_inv_S[i];
+ }
+ }
+#endif
+};
+
+#endif /* BT_PRECONDITIONER_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
index 7463bdc019..81b846d7f8 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
@@ -18,8 +18,113 @@ subject to the following restrictions:
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "btSoftBodyData.h"
#include "LinearMath/btSerializer.h"
+#include "LinearMath/btImplicitQRSVD.h"
+#include "LinearMath/btAlignedAllocator.h"
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include <iostream>
+//
+static inline btDbvtNode* buildTreeBottomUp(btAlignedObjectArray<btDbvtNode*>& leafNodes, btAlignedObjectArray<btAlignedObjectArray<int> >& adj)
+{
+ int N = leafNodes.size();
+ if (N == 0)
+ {
+ return NULL;
+ }
+ while (N > 1)
+ {
+ btAlignedObjectArray<bool> marked;
+ btAlignedObjectArray<btDbvtNode*> newLeafNodes;
+ btAlignedObjectArray<std::pair<int,int> > childIds;
+ btAlignedObjectArray<btAlignedObjectArray<int> > newAdj;
+ marked.resize(N);
+ for (int i = 0; i < N; ++i)
+ marked[i] = false;
+
+ // pair adjacent nodes into new(parent) node
+ for (int i = 0; i < N; ++i)
+ {
+ if (marked[i])
+ continue;
+ bool merged = false;
+ for (int j = 0; j < adj[i].size(); ++j)
+ {
+ int n = adj[i][j];
+ if (!marked[adj[i][j]])
+ {
+ btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
+ node->parent = NULL;
+ node->childs[0] = leafNodes[i];
+ node->childs[1] = leafNodes[n];
+ leafNodes[i]->parent = node;
+ leafNodes[n]->parent = node;
+ newLeafNodes.push_back(node);
+ childIds.push_back(std::make_pair(i,n));
+ merged = true;
+ marked[n] = true;
+ break;
+ }
+ }
+ if (!merged)
+ {
+ newLeafNodes.push_back(leafNodes[i]);
+ childIds.push_back(std::make_pair(i,-1));
+ }
+ marked[i] = true;
+ }
+ // update adjacency matrix
+ newAdj.resize(newLeafNodes.size());
+ for (int i = 0; i < newLeafNodes.size(); ++i)
+ {
+ for (int j = i+1; j < newLeafNodes.size(); ++j)
+ {
+ bool neighbor = false;
+ const btAlignedObjectArray<int>& leftChildNeighbors = adj[childIds[i].first];
+ for (int k = 0; k < leftChildNeighbors.size(); ++k)
+ {
+ if (leftChildNeighbors[k] == childIds[j].first || leftChildNeighbors[k] == childIds[j].second)
+ {
+ neighbor = true;
+ break;
+ }
+ }
+ if (!neighbor && childIds[i].second != -1)
+ {
+ const btAlignedObjectArray<int>& rightChildNeighbors = adj[childIds[i].second];
+ for (int k = 0; k < rightChildNeighbors.size(); ++k)
+ {
+ if (rightChildNeighbors[k] == childIds[j].first || rightChildNeighbors[k] == childIds[j].second)
+ {
+ neighbor = true;
+ break;
+ }
+ }
+ }
+ if (neighbor)
+ {
+ newAdj[i].push_back(j);
+ newAdj[j].push_back(i);
+ }
+ }
+ }
+ leafNodes = newLeafNodes;
+ //this assignment leaks memory, the assignment doesn't do a deep copy, for now a manual copy
+ //adj = newAdj;
+ adj.clear();
+ adj.resize(newAdj.size());
+ for (int i = 0; i < newAdj.size(); i++)
+ {
+ for (int j = 0; j < newAdj[i].size(); j++)
+ {
+ adj[i].push_back(newAdj[i][j]);
+ }
+ }
+ N = leafNodes.size();
+ }
+ return leafNodes[0];
+}
//
btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
@@ -38,6 +143,7 @@ btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btV
/* Nodes */
const btScalar margin = getCollisionShape()->getMargin();
m_nodes.resize(node_count);
+ m_X.resize(node_count);
for (int i = 0, ni = node_count; i < ni; ++i)
{
Node& n = m_nodes[i];
@@ -48,8 +154,11 @@ btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btV
n.m_im = n.m_im > 0 ? 1 / n.m_im : 0;
n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
n.m_material = pm;
+ m_X[i] = n.m_x;
}
updateBounds();
+ setCollisionQuadrature(3);
+ m_fdbvnt = 0;
}
btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
@@ -86,6 +195,8 @@ void btSoftBody::initDefaults()
m_cfg.piterations = 1;
m_cfg.diterations = 0;
m_cfg.citerations = 4;
+ m_cfg.drag = 0;
+ m_cfg.m_maxStress = 0;
m_cfg.collisions = fCollision::Default;
m_pose.m_bvolume = false;
m_pose.m_bframe = false;
@@ -106,10 +217,18 @@ void btSoftBody::initDefaults()
m_collisionShape = new btSoftBodyCollisionShape(this);
m_collisionShape->setMargin(0.25f);
- m_initialWorldTransform.setIdentity();
+ m_worldTransform.setIdentity();
m_windVelocity = btVector3(0, 0, 0);
m_restLengthScale = btScalar(1.0);
+ m_dampingCoefficient = 1.0;
+ m_sleepingThreshold = .4;
+ m_useSelfCollision = false;
+ m_collisionFlags = 0;
+ m_softSoftCollision = false;
+ m_maxSpeedSquared = 0;
+ m_repulsionStiffness = 0.5;
+ m_fdbvnt = 0;
}
//
@@ -124,6 +243,8 @@ btSoftBody::~btSoftBody()
btAlignedFree(m_materials[i]);
for (i = 0; i < m_joints.size(); ++i)
btAlignedFree(m_joints[i]);
+ if (m_fdbvnt)
+ delete m_fdbvnt;
}
//
@@ -315,7 +436,7 @@ void btSoftBody::appendFace(int model, Material* mat)
ZeroInitialize(f);
f.m_material = mat ? mat : m_materials[0];
}
- m_faces.push_back(f);
+ m_faces.push_back(f);
}
//
@@ -402,6 +523,98 @@ void btSoftBody::appendAnchor(int node, btRigidBody* body, const btVector3& loca
}
//
+void btSoftBody::appendDeformableAnchor(int node, btRigidBody* body)
+{
+ DeformableNodeRigidAnchor c;
+ btSoftBody::Node& n = m_nodes[node];
+ const btScalar ima = n.m_im;
+ const btScalar imb = body->getInvMass();
+ btVector3 nrm;
+ const btCollisionShape* shp = body->getCollisionShape();
+ const btTransform& wtr = body->getWorldTransform();
+ btScalar dst =
+ m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(m_nodes[node].m_x),
+ shp,
+ nrm,
+ 0);
+
+ c.m_cti.m_colObj = body;
+ c.m_cti.m_normal = wtr.getBasis() * nrm;
+ c.m_cti.m_offset = dst;
+ c.m_node = &m_nodes[node];
+ const btScalar fc = m_cfg.kDF * body->getFriction();
+ c.m_c2 = ima;
+ c.m_c3 = fc;
+ c.m_c4 = body->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
+ static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const btMatrix3x3& iwi = body->getInvInertiaTensorWorld();
+ const btVector3 ra = n.m_x - wtr.getOrigin();
+
+ c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
+ c.m_c1 = ra;
+ c.m_local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
+ c.m_node->m_battach = 1;
+ m_deformableAnchors.push_back(c);
+}
+
+//
+void btSoftBody::appendDeformableAnchor(int node, btMultiBodyLinkCollider* link)
+{
+ DeformableNodeRigidAnchor c;
+ btSoftBody::Node& n = m_nodes[node];
+ const btScalar ima = n.m_im;
+ btVector3 nrm;
+ const btCollisionShape* shp = link->getCollisionShape();
+ const btTransform& wtr = link->getWorldTransform();
+ btScalar dst =
+ m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(m_nodes[node].m_x),
+ shp,
+ nrm,
+ 0);
+ c.m_cti.m_colObj = link;
+ c.m_cti.m_normal = wtr.getBasis() * nrm;
+ c.m_cti.m_offset = dst;
+ c.m_node = &m_nodes[node];
+ const btScalar fc = m_cfg.kDF * link->getFriction();
+ c.m_c2 = ima;
+ c.m_c3 = fc;
+ c.m_c4 = link->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
+ btVector3 normal = c.m_cti.m_normal;
+ btVector3 t1 = generateUnitOrthogonalVector(normal);
+ btVector3 t2 = btCross(normal, t1);
+ btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+ findJacobian(link, jacobianData_normal, c.m_node->m_x, normal);
+ findJacobian(link, jacobianData_t1, c.m_node->m_x, t1);
+ findJacobian(link, jacobianData_t2, c.m_node->m_x, t2);
+
+ btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+ btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+ btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+ btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+ btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+ t1.getX(), t1.getY(), t1.getZ(),
+ t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
+ const int ndof = link->m_multiBody->getNumDofs() + 6;
+ btMatrix3x3 local_impulse_matrix = (Diagonal(n.m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+ c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+ c.jacobianData_normal = jacobianData_normal;
+ c.jacobianData_t1 = jacobianData_t1;
+ c.jacobianData_t2 = jacobianData_t2;
+ c.t1 = t1;
+ c.t2 = t2;
+ const btVector3 ra = n.m_x - wtr.getOrigin();
+ c.m_c1 = ra;
+ c.m_local = link->getWorldTransform().inverse() * m_nodes[node].m_x;
+ c.m_node->m_battach = 1;
+ m_deformableAnchors.push_back(c);
+}
+//
void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, Cluster* body0, Body body1)
{
LJoint* pj = new (btAlignedAlloc(sizeof(LJoint), 16)) LJoint();
@@ -518,7 +731,7 @@ void btSoftBody::addAeroForceToNode(const btVector3& windVelocity, int nodeIndex
fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
// Check angle of attack
- // cos(10°) = 0.98480
+ // cos(10º) = 0.98480
if (0 < n_dot_v && n_dot_v < 0.98480f)
fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
@@ -604,7 +817,7 @@ void btSoftBody::addAeroForceToFace(const btVector3& windVelocity, int faceIndex
fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
// Check angle of attack
- // cos(10°) = 0.98480
+ // cos(10º) = 0.98480
if (0 < n_dot_v && n_dot_v < 0.98480f)
fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
@@ -795,6 +1008,71 @@ void btSoftBody::setVolumeDensity(btScalar density)
}
//
+btVector3 btSoftBody::getLinearVelocity()
+{
+ btVector3 total_momentum = btVector3(0,0,0);
+ for (int i = 0; i < m_nodes.size(); ++i)
+ {
+ btScalar mass = m_nodes[i].m_im == 0 ? 0 : 1.0/m_nodes[i].m_im;
+ total_momentum += mass * m_nodes[i].m_v;
+ }
+ btScalar total_mass = getTotalMass();
+ return total_mass == 0 ? total_momentum : total_momentum / total_mass;
+}
+
+//
+void btSoftBody::setLinearVelocity(const btVector3& linVel)
+{
+ btVector3 old_vel = getLinearVelocity();
+ btVector3 diff = linVel - old_vel;
+ for (int i = 0; i < m_nodes.size(); ++i)
+ m_nodes[i].m_v += diff;
+}
+
+//
+void btSoftBody::setAngularVelocity(const btVector3& angVel)
+{
+ btVector3 old_vel = getLinearVelocity();
+ btVector3 com = getCenterOfMass();
+ for (int i = 0; i < m_nodes.size(); ++i)
+ {
+ m_nodes[i].m_v = angVel.cross(m_nodes[i].m_x - com) + old_vel;
+ }
+}
+
+//
+btTransform btSoftBody::getRigidTransform()
+{
+ btVector3 t = getCenterOfMass();
+ btMatrix3x3 S;
+ S.setZero();
+ // get rotation that minimizes L2 difference: \sum_i || RX_i + t - x_i ||
+ for (int i = 0; i < m_nodes.size(); ++i)
+ {
+ S += OuterProduct(m_X[i], t-m_nodes[i].m_x);
+ }
+ btVector3 sigma;
+ btMatrix3x3 U,V;
+ singularValueDecomposition(S,U,sigma,V);
+ btMatrix3x3 R = V * U.transpose();
+ btTransform trs;
+ trs.setIdentity();
+ trs.setOrigin(t);
+ trs.setBasis(R);
+ return trs;
+}
+
+//
+void btSoftBody::transformTo(const btTransform& trs)
+{
+ // get the current best rigid fit
+ btTransform current_transform = getRigidTransform();
+ // apply transform in material space
+ btTransform new_transform = trs * current_transform.inverse();
+ transform(new_transform);
+}
+
+//
void btSoftBody::transform(const btTransform& trs)
{
const btScalar margin = getCollisionShape()->getMargin();
@@ -814,7 +1092,6 @@ void btSoftBody::transform(const btTransform& trs)
updateNormals();
updateBounds();
updateConstants();
- m_initialWorldTransform = trs;
}
//
@@ -853,6 +1130,7 @@ void btSoftBody::scale(const btVector3& scl)
updateNormals();
updateBounds();
updateConstants();
+ initializeDmInverse();
}
//
@@ -1731,6 +2009,25 @@ bool btSoftBody::rayTest(const btVector3& rayFrom,
return (rayTest(rayFrom, rayTo, results.fraction, results.feature, results.index, false) != 0);
}
+bool btSoftBody::rayFaceTest(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ sRayCast& results)
+{
+ if (m_faces.size() == 0)
+ return false;
+ else
+ {
+ if (m_fdbvt.empty())
+ initializeFaceTree();
+ }
+
+ results.body = this;
+ results.fraction = 1.f;
+ results.index = -1;
+
+ return (rayFaceTest(rayFrom, rayTo, results.fraction, results.index) != 0);
+}
+
//
void btSoftBody::setSolver(eSolverPresets::_ preset)
{
@@ -1757,115 +2054,115 @@ void btSoftBody::setSolver(eSolverPresets::_ preset)
}
}
-//
void btSoftBody::predictMotion(btScalar dt)
{
- int i, ni;
-
- /* Update */
- if (m_bUpdateRtCst)
- {
- m_bUpdateRtCst = false;
- updateConstants();
- m_fdbvt.clear();
- if (m_cfg.collisions & fCollision::VF_SS)
- {
- initializeFaceTree();
- }
- }
-
- /* Prepare */
- m_sst.sdt = dt * m_cfg.timescale;
- m_sst.isdt = 1 / m_sst.sdt;
- m_sst.velmrg = m_sst.sdt * 3;
- m_sst.radmrg = getCollisionShape()->getMargin();
- m_sst.updmrg = m_sst.radmrg * (btScalar)0.25;
- /* Forces */
- addVelocity(m_worldInfo->m_gravity * m_sst.sdt);
- applyForces();
- /* Integrate */
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- n.m_q = n.m_x;
- btVector3 deltaV = n.m_f * n.m_im * m_sst.sdt;
- {
- btScalar maxDisplacement = m_worldInfo->m_maxDisplacement;
- btScalar clampDeltaV = maxDisplacement / m_sst.sdt;
- for (int c = 0; c < 3; c++)
- {
- if (deltaV[c] > clampDeltaV)
- {
- deltaV[c] = clampDeltaV;
- }
- if (deltaV[c] < -clampDeltaV)
- {
- deltaV[c] = -clampDeltaV;
- }
- }
- }
- n.m_v += deltaV;
- n.m_x += n.m_v * m_sst.sdt;
- n.m_f = btVector3(0, 0, 0);
- }
- /* Clusters */
- updateClusters();
- /* Bounds */
- updateBounds();
- /* Nodes */
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol;
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- vol = btDbvtVolume::FromCR(n.m_x, m_sst.radmrg);
- m_ndbvt.update(n.m_leaf,
- vol,
- n.m_v * m_sst.velmrg,
- m_sst.updmrg);
- }
- /* Faces */
- if (!m_fdbvt.empty())
- {
- for (int i = 0; i < m_faces.size(); ++i)
- {
- Face& f = m_faces[i];
- const btVector3 v = (f.m_n[0]->m_v +
- f.m_n[1]->m_v +
- f.m_n[2]->m_v) /
- 3;
- vol = VolumeOf(f, m_sst.radmrg);
- m_fdbvt.update(f.m_leaf,
- vol,
- v * m_sst.velmrg,
- m_sst.updmrg);
- }
- }
- /* Pose */
- updatePose();
- /* Match */
- if (m_pose.m_bframe && (m_cfg.kMT > 0))
- {
- const btMatrix3x3 posetrs = m_pose.m_rot;
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- if (n.m_im > 0)
- {
- const btVector3 x = posetrs * m_pose.m_pos[i] + m_pose.m_com;
- n.m_x = Lerp(n.m_x, x, m_cfg.kMT);
- }
- }
- }
- /* Clear contacts */
- m_rcontacts.resize(0);
- m_scontacts.resize(0);
- /* Optimize dbvt's */
- m_ndbvt.optimizeIncremental(1);
- m_fdbvt.optimizeIncremental(1);
- m_cdbvt.optimizeIncremental(1);
+ int i, ni;
+
+ /* Update */
+ if (m_bUpdateRtCst)
+ {
+ m_bUpdateRtCst = false;
+ updateConstants();
+ m_fdbvt.clear();
+ if (m_cfg.collisions & fCollision::VF_SS)
+ {
+ initializeFaceTree();
+ }
+ }
+
+ /* Prepare */
+ m_sst.sdt = dt * m_cfg.timescale;
+ m_sst.isdt = 1 / m_sst.sdt;
+ m_sst.velmrg = m_sst.sdt * 3;
+ m_sst.radmrg = getCollisionShape()->getMargin();
+ m_sst.updmrg = m_sst.radmrg * (btScalar)0.25;
+ /* Forces */
+ addVelocity(m_worldInfo->m_gravity * m_sst.sdt);
+ applyForces();
+ /* Integrate */
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
+ {
+ Node& n = m_nodes[i];
+ n.m_q = n.m_x;
+ btVector3 deltaV = n.m_f * n.m_im * m_sst.sdt;
+ {
+ btScalar maxDisplacement = m_worldInfo->m_maxDisplacement;
+ btScalar clampDeltaV = maxDisplacement / m_sst.sdt;
+ for (int c = 0; c < 3; c++)
+ {
+ if (deltaV[c] > clampDeltaV)
+ {
+ deltaV[c] = clampDeltaV;
+ }
+ if (deltaV[c] < -clampDeltaV)
+ {
+ deltaV[c] = -clampDeltaV;
+ }
+ }
+ }
+ n.m_v += deltaV;
+ n.m_x += n.m_v * m_sst.sdt;
+ n.m_f = btVector3(0, 0, 0);
+ }
+ /* Clusters */
+ updateClusters();
+ /* Bounds */
+ updateBounds();
+ /* Nodes */
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ vol;
+ for (i = 0, ni = m_nodes.size(); i < ni; ++i)
+ {
+ Node& n = m_nodes[i];
+ vol = btDbvtVolume::FromCR(n.m_x, m_sst.radmrg);
+ m_ndbvt.update(n.m_leaf,
+ vol,
+ n.m_v * m_sst.velmrg,
+ m_sst.updmrg);
+ }
+ /* Faces */
+ if (!m_fdbvt.empty())
+ {
+ for (int i = 0; i < m_faces.size(); ++i)
+ {
+ Face& f = m_faces[i];
+ const btVector3 v = (f.m_n[0]->m_v +
+ f.m_n[1]->m_v +
+ f.m_n[2]->m_v) /
+ 3;
+ vol = VolumeOf(f, m_sst.radmrg);
+ m_fdbvt.update(f.m_leaf,
+ vol,
+ v * m_sst.velmrg,
+ m_sst.updmrg);
+ }
+ }
+ /* Pose */
+ updatePose();
+ /* Match */
+ if (m_pose.m_bframe && (m_cfg.kMT > 0))
+ {
+ const btMatrix3x3 posetrs = m_pose.m_rot;
+ for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
+ {
+ Node& n = m_nodes[i];
+ if (n.m_im > 0)
+ {
+ const btVector3 x = posetrs * m_pose.m_pos[i] + m_pose.m_com;
+ n.m_x = Lerp(n.m_x, x, m_cfg.kMT);
+ }
+ }
+ }
+ /* Clear contacts */
+ m_rcontacts.resize(0);
+ m_scontacts.resize(0);
+ /* Optimize dbvt's */
+ m_ndbvt.optimizeIncremental(1);
+ m_fdbvt.optimizeIncremental(1);
+ m_cdbvt.optimizeIncremental(1);
}
+
//
void btSoftBody::solveConstraints()
{
@@ -2236,15 +2533,160 @@ int btSoftBody::rayTest(const btVector3& rayFrom, const btVector3& rayTo,
return (cnt);
}
+int btSoftBody::rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo,
+ btScalar& mint, int& index) const
+{
+ int cnt = 0;
+ { /* Use dbvt */
+ RayFromToCaster collider(rayFrom, rayTo, mint);
+
+ btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
+ if (collider.m_face)
+ {
+ mint = collider.m_mint;
+ index = (int)(collider.m_face - &m_faces[0]);
+ cnt = 1;
+ }
+ }
+ return (cnt);
+}
+
+
//
+static inline btDbvntNode* copyToDbvnt(const btDbvtNode* n)
+{
+ if (n == 0)
+ return 0;
+ btDbvntNode* root = new btDbvntNode(n);
+ if (n->isinternal())
+ {
+ btDbvntNode* c0 = copyToDbvnt(n->childs[0]);
+ root->childs[0] = c0;
+ btDbvntNode* c1 = copyToDbvnt(n->childs[1]);
+ root->childs[1] = c1;
+ }
+ return root;
+}
+
+static inline void calculateNormalCone(btDbvntNode* root)
+{
+ if (!root)
+ return;
+ if (root->isleaf())
+ {
+ const btSoftBody::Face* face = (btSoftBody::Face*)root->data;
+ root->normal = face->m_normal;
+ root->angle = 0;
+ }
+ else
+ {
+ btVector3 n0(0,0,0), n1(0,0,0);
+ btScalar a0 = 0, a1 = 0;
+ if (root->childs[0])
+ {
+ calculateNormalCone(root->childs[0]);
+ n0 = root->childs[0]->normal;
+ a0 = root->childs[0]->angle;
+ }
+ if (root->childs[1])
+ {
+ calculateNormalCone(root->childs[1]);
+ n1 = root->childs[1]->normal;
+ a1 = root->childs[1]->angle;
+ }
+ root->normal = (n0+n1).safeNormalize();
+ root->angle = btMax(a0,a1) + btAngle(n0, n1)*0.5;
+ }
+}
+
void btSoftBody::initializeFaceTree()
{
+ BT_PROFILE("btSoftBody::initializeFaceTree");
m_fdbvt.clear();
+ // create leaf nodes;
+ btAlignedObjectArray<btDbvtNode*> leafNodes;
+ leafNodes.resize(m_faces.size());
for (int i = 0; i < m_faces.size(); ++i)
{
Face& f = m_faces[i];
- f.m_leaf = m_fdbvt.insert(VolumeOf(f, 0), &f);
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) vol = VolumeOf(f, 0);
+ btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
+ node->parent = NULL;
+ node->data = &f;
+ node->childs[1] = 0;
+ node->volume = vol;
+ leafNodes[i] = node;
+ f.m_leaf = node;
+ }
+ btAlignedObjectArray<btAlignedObjectArray<int> > adj;
+ adj.resize(m_faces.size());
+ // construct the adjacency list for triangles
+ for (int i = 0; i < adj.size(); ++i)
+ {
+ for (int j = i+1; j < adj.size(); ++j)
+ {
+ int dup = 0;
+ for (int k = 0; k < 3; ++k)
+ {
+ for (int l = 0; l < 3; ++l)
+ {
+ if (m_faces[i].m_n[k] == m_faces[j].m_n[l])
+ {
+ ++dup;
+ break;
+ }
+ }
+ if (dup == 2)
+ {
+ adj[i].push_back(j);
+ adj[j].push_back(i);
+ }
+ }
+ }
}
+ m_fdbvt.m_root = buildTreeBottomUp(leafNodes, adj);
+ if (m_fdbvnt)
+ delete m_fdbvnt;
+ m_fdbvnt = copyToDbvnt(m_fdbvt.m_root);
+ updateFaceTree(false, false);
+ rebuildNodeTree();
+}
+
+//
+void btSoftBody::rebuildNodeTree()
+{
+ m_ndbvt.clear();
+ btAlignedObjectArray<btDbvtNode*> leafNodes;
+ leafNodes.resize(m_nodes.size());
+ for (int i = 0; i < m_nodes.size(); ++i)
+ {
+ Node& n = m_nodes[i];
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) vol = btDbvtVolume::FromCR(n.m_x, 0);
+ btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
+ node->parent = NULL;
+ node->data = &n;
+ node->childs[1] = 0;
+ node->volume = vol;
+ leafNodes[i] = node;
+ n.m_leaf = node;
+ }
+ btAlignedObjectArray<btAlignedObjectArray<int> > adj;
+ adj.resize(m_nodes.size());
+ btAlignedObjectArray<int> old_id;
+ old_id.resize(m_nodes.size());
+ for (int i = 0; i < m_nodes.size(); ++i)
+ old_id[i] = m_nodes[i].index;
+ for (int i = 0; i < m_nodes.size(); ++i)
+ m_nodes[i].index = i;
+ for (int i = 0; i < m_links.size(); ++i)
+ {
+ Link& l = m_links[i];
+ adj[l.m_n[0]->index].push_back(l.m_n[1]->index);
+ adj[l.m_n[1]->index].push_back(l.m_n[0]->index);
+ }
+ m_ndbvt.m_root = buildTreeBottomUp(leafNodes, adj);
+ for (int i = 0; i < m_nodes.size(); ++i)
+ m_nodes[i].index = old_id[i];
}
//
@@ -2261,36 +2703,239 @@ btVector3 btSoftBody::evaluateCom() const
return (com);
}
-//
bool btSoftBody::checkContact(const btCollisionObjectWrapper* colObjWrap,
+ const btVector3& x,
+ btScalar margin,
+ btSoftBody::sCti& cti) const
+{
+ btVector3 nrm;
+ const btCollisionShape* shp = colObjWrap->getCollisionShape();
+ // const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
+ //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
+ const btTransform& wtr = colObjWrap->getWorldTransform();
+ //todo: check which transform is needed here
+
+ btScalar dst =
+ m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(x),
+ shp,
+ nrm,
+ margin);
+ if (dst < 0)
+ {
+ cti.m_colObj = colObjWrap->getCollisionObject();
+ cti.m_normal = wtr.getBasis() * nrm;
+ cti.m_offset = -btDot(cti.m_normal, x - cti.m_normal * dst);
+ return (true);
+ }
+ return (false);
+}
+
+//
+bool btSoftBody::checkDeformableContact(const btCollisionObjectWrapper* colObjWrap,
const btVector3& x,
btScalar margin,
- btSoftBody::sCti& cti) const
+ btSoftBody::sCti& cti, bool predict) const
{
btVector3 nrm;
const btCollisionShape* shp = colObjWrap->getCollisionShape();
- // const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
- //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
- const btTransform& wtr = colObjWrap->getWorldTransform();
- //todo: check which transform is needed here
-
+ const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
+ // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
+ // but resolve contact at x_n
+ btTransform wtr = (predict) ?
+ (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform()*(*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
+ : colObjWrap->getWorldTransform();
btScalar dst =
m_worldInfo->m_sparsesdf.Evaluate(
wtr.invXform(x),
shp,
nrm,
margin);
- if (dst < 0)
+ if (!predict)
{
cti.m_colObj = colObjWrap->getCollisionObject();
cti.m_normal = wtr.getBasis() * nrm;
- cti.m_offset = -btDot(cti.m_normal, x - cti.m_normal * dst);
- return (true);
+ cti.m_offset = dst;
}
+ if (dst < 0)
+ return true;
return (false);
}
//
+// Compute barycentric coordinates (u, v, w) for
+// point p with respect to triangle (a, b, c)
+static void getBarycentric(const btVector3& p, btVector3& a, btVector3& b, btVector3& c, btVector3& bary)
+{
+ btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
+ btScalar d00 = v0.dot(v0);
+ btScalar d01 = v0.dot(v1);
+ btScalar d11 = v1.dot(v1);
+ btScalar d20 = v2.dot(v0);
+ btScalar d21 = v2.dot(v1);
+ btScalar denom = d00 * d11 - d01 * d01;
+ bary.setY((d11 * d20 - d01 * d21) / denom);
+ bary.setZ((d00 * d21 - d01 * d20) / denom);
+ bary.setX(btScalar(1) - bary.getY() - bary.getZ());
+}
+
+//
+bool btSoftBody::checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap,
+ Face& f,
+ btVector3& contact_point,
+ btVector3& bary,
+ btScalar margin,
+ btSoftBody::sCti& cti, bool predict) const
+{
+ btVector3 nrm;
+ const btCollisionShape* shp = colObjWrap->getCollisionShape();
+ const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
+ // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
+ // but resolve contact at x_n
+ btTransform wtr = (predict) ?
+ (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform()*(*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
+ : colObjWrap->getWorldTransform();
+ btScalar dst;
+
+//#define USE_QUADRATURE 1
+//#define CACHE_PREV_COLLISION
+
+ // use the contact position of the previous collision
+#ifdef CACHE_PREV_COLLISION
+ if (f.m_pcontact[3] != 0)
+ {
+ for (int i = 0; i < 3; ++i)
+ bary[i] = f.m_pcontact[i];
+ contact_point = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+ dst = m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(contact_point),
+ shp,
+ nrm,
+ margin);
+ nrm = wtr.getBasis() * nrm;
+ cti.m_colObj = colObjWrap->getCollisionObject();
+ // use cached contact point
+ }
+ else
+ {
+ btGjkEpaSolver2::sResults results;
+ btTransform triangle_transform;
+ triangle_transform.setIdentity();
+ triangle_transform.setOrigin(f.m_n[0]->m_x);
+ btTriangleShape triangle(btVector3(0,0,0), f.m_n[1]->m_x-f.m_n[0]->m_x, f.m_n[2]->m_x-f.m_n[0]->m_x);
+ btVector3 guess(0,0,0);
+ const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
+ btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
+ dst = results.distance - margin;
+ contact_point = results.witnesses[0];
+ getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+ nrm = results.normal;
+ cti.m_colObj = colObjWrap->getCollisionObject();
+ for (int i = 0; i < 3; ++i)
+ f.m_pcontact[i] = bary[i];
+ }
+ return (dst < 0);
+#endif
+
+ // use collision quadrature point
+#ifdef USE_QUADRATURE
+ {
+ dst = SIMD_INFINITY;
+ btVector3 local_nrm;
+ for (int q = 0; q < m_quads.size(); ++q)
+ {
+ btVector3 p;
+ if (predict)
+ p = BaryEval(f.m_n[0]->m_q, f.m_n[1]->m_q, f.m_n[2]->m_q, m_quads[q]);
+ else
+ p = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, m_quads[q]);
+ btScalar local_dst = m_worldInfo->m_sparsesdf.Evaluate(
+ wtr.invXform(p),
+ shp,
+ local_nrm,
+ margin);
+ if (local_dst < dst)
+ {
+ if (local_dst < 0 && predict)
+ return true;
+ dst = local_dst;
+ contact_point = p;
+ bary = m_quads[q];
+ nrm = local_nrm;
+ }
+ if (!predict)
+ {
+ cti.m_colObj = colObjWrap->getCollisionObject();
+ cti.m_normal = wtr.getBasis() * nrm;
+ cti.m_offset = dst;
+ }
+ }
+ return (dst < 0);
+ }
+#endif
+
+// // regular face contact
+// {
+// btGjkEpaSolver2::sResults results;
+// btTransform triangle_transform;
+// triangle_transform.setIdentity();
+// triangle_transform.setOrigin(f.m_n[0]->m_x);
+// btTriangleShape triangle(btVector3(0,0,0), f.m_n[1]->m_x-f.m_n[0]->m_x, f.m_n[2]->m_x-f.m_n[0]->m_x);
+// btVector3 guess(0,0,0);
+// if (predict)
+// {
+// triangle_transform.setOrigin(f.m_n[0]->m_q);
+// triangle = btTriangleShape(btVector3(0,0,0), f.m_n[1]->m_q-f.m_n[0]->m_q, f.m_n[2]->m_q-f.m_n[0]->m_q);
+// }
+// const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
+//// btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
+//// dst = results.distance - margin;
+//// contact_point = results.witnesses[0];
+// btGjkEpaSolver2::Penetration(&triangle, triangle_transform, csh, wtr, guess, results);
+// if (results.status == btGjkEpaSolver2::sResults::Separated)
+// return false;
+// dst = results.distance - margin;
+// contact_point = results.witnesses[1];
+// getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+// nrm = results.normal;
+// for (int i = 0; i < 3; ++i)
+// f.m_pcontact[i] = bary[i];
+// }
+//
+// if (!predict)
+// {
+// cti.m_colObj = colObjWrap->getCollisionObject();
+// cti.m_normal = nrm;
+// cti.m_offset = dst;
+// }
+//
+
+ // regular face contact
+ {
+ btGjkEpaSolver2::sResults results;
+ btTransform triangle_transform;
+ triangle_transform.setIdentity();
+ triangle_transform.setOrigin(f.m_n[0]->m_q);
+ btTriangleShape triangle(btVector3(0,0,0), f.m_n[1]->m_q-f.m_n[0]->m_q, f.m_n[2]->m_q-f.m_n[0]->m_q);
+ btVector3 guess(0,0,0);
+ const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
+ btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
+ dst = results.distance-csh->getMargin();
+ dst -= margin;
+ if (dst >= 0)
+ return false;
+ contact_point = results.witnesses[0];
+ getBarycentric(contact_point, f.m_n[0]->m_q, f.m_n[1]->m_q, f.m_n[2]->m_q, bary);
+ btVector3 curr = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+ nrm = results.normal;
+ cti.m_colObj = colObjWrap->getCollisionObject();
+ cti.m_normal = nrm;
+ cti.m_offset = dst + (curr - contact_point).dot(nrm);
+ }
+ return (dst < 0);
+}
+
+//
void btSoftBody::updateNormals()
{
const btVector3 zv(0, 0, 0);
@@ -2305,7 +2950,8 @@ void btSoftBody::updateNormals()
btSoftBody::Face& f = m_faces[i];
const btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x,
f.m_n[2]->m_x - f.m_n[0]->m_x);
- f.m_normal = n.normalized();
+ f.m_normal = n;
+ f.m_normal.safeNormalize();
f.m_n[0]->m_n += n;
f.m_n[1]->m_n += n;
f.m_n[2]->m_n += n;
@@ -2333,31 +2979,63 @@ void btSoftBody::updateBounds()
m_bounds[1] = btVector3(1000, 1000, 1000);
} else {*/
- if (m_ndbvt.m_root)
- {
- const btVector3& mins = m_ndbvt.m_root->volume.Mins();
- const btVector3& maxs = m_ndbvt.m_root->volume.Maxs();
- const btScalar csm = getCollisionShape()->getMargin();
- const btVector3 mrg = btVector3(csm,
- csm,
- csm) *
- 1; // ??? to investigate...
- m_bounds[0] = mins - mrg;
- m_bounds[1] = maxs + mrg;
- if (0 != getBroadphaseHandle())
- {
- m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
- m_bounds[0],
- m_bounds[1],
- m_worldInfo->m_dispatcher);
- }
- }
- else
- {
- m_bounds[0] =
- m_bounds[1] = btVector3(0, 0, 0);
- }
- //}
+// if (m_ndbvt.m_root)
+// {
+// const btVector3& mins = m_ndbvt.m_root->volume.Mins();
+// const btVector3& maxs = m_ndbvt.m_root->volume.Maxs();
+// const btScalar csm = getCollisionShape()->getMargin();
+// const btVector3 mrg = btVector3(csm,
+// csm,
+// csm) *
+// 1; // ??? to investigate...
+// m_bounds[0] = mins - mrg;
+// m_bounds[1] = maxs + mrg;
+// if (0 != getBroadphaseHandle())
+// {
+// m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
+// m_bounds[0],
+// m_bounds[1],
+// m_worldInfo->m_dispatcher);
+// }
+// }
+// else
+// {
+// m_bounds[0] =
+// m_bounds[1] = btVector3(0, 0, 0);
+// }
+ if (m_nodes.size())
+ {
+ btVector3 mins = m_nodes[0].m_x;
+ btVector3 maxs = m_nodes[0].m_x;
+ for (int i = 1; i < m_nodes.size(); ++i)
+ {
+ for (int d = 0; d < 3; ++d)
+ {
+ if (m_nodes[i].m_x[d] > maxs[d])
+ maxs[d] = m_nodes[i].m_x[d];
+ if (m_nodes[i].m_x[d] < mins[d])
+ mins[d] = m_nodes[i].m_x[d];
+ }
+ }
+ const btScalar csm = getCollisionShape()->getMargin();
+ const btVector3 mrg = btVector3(csm,
+ csm,
+ csm);
+ m_bounds[0] = mins - mrg;
+ m_bounds[1] = maxs + mrg;
+ if (0 != getBroadphaseHandle())
+ {
+ m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
+ m_bounds[0],
+ m_bounds[1],
+ m_worldInfo->m_dispatcher);
+ }
+ }
+ else
+ {
+ m_bounds[0] =
+ m_bounds[1] = btVector3(0, 0, 0);
+ }
}
//
@@ -2774,6 +3452,63 @@ void btSoftBody::dampClusters()
}
}
+void btSoftBody::setSpringStiffness(btScalar k)
+{
+ for (int i = 0; i < m_links.size(); ++i)
+ {
+ m_links[i].Feature::m_material->m_kLST = k;
+ }
+ m_repulsionStiffness = k;
+}
+
+void btSoftBody::initializeDmInverse()
+{
+ btScalar unit_simplex_measure = 1./6.;
+
+ for (int i = 0; i < m_tetras.size(); ++i)
+ {
+ Tetra &t = m_tetras[i];
+ btVector3 c1 = t.m_n[1]->m_x - t.m_n[0]->m_x;
+ btVector3 c2 = t.m_n[2]->m_x - t.m_n[0]->m_x;
+ btVector3 c3 = t.m_n[3]->m_x - t.m_n[0]->m_x;
+ btMatrix3x3 Dm(c1.getX(), c2.getX(), c3.getX(),
+ c1.getY(), c2.getY(), c3.getY(),
+ c1.getZ(), c2.getZ(), c3.getZ());
+ t.m_element_measure = Dm.determinant() * unit_simplex_measure;
+ t.m_Dm_inverse = Dm.inverse();
+ }
+}
+
+void btSoftBody::updateDeformation()
+{
+ for (int i = 0; i < m_tetras.size(); ++i)
+ {
+ btSoftBody::Tetra& t = m_tetras[i];
+ btVector3 c1 = t.m_n[1]->m_q - t.m_n[0]->m_q;
+ btVector3 c2 = t.m_n[2]->m_q - t.m_n[0]->m_q;
+ btVector3 c3 = t.m_n[3]->m_q - t.m_n[0]->m_q;
+ btMatrix3x3 Ds(c1.getX(), c2.getX(), c3.getX(),
+ c1.getY(), c2.getY(), c3.getY(),
+ c1.getZ(), c2.getZ(), c3.getZ());
+ t.m_F = Ds * t.m_Dm_inverse;
+
+ btSoftBody::TetraScratch& s = m_tetraScratches[i];
+ s.m_F = t.m_F;
+ s.m_J = t.m_F.determinant();
+ btMatrix3x3 C = t.m_F.transpose()*t.m_F;
+ s.m_trace = C[0].getX() + C[1].getY() + C[2].getZ();
+ s.m_cofF = t.m_F.adjoint().transpose();
+ }
+}
+
+void btSoftBody::advanceDeformation()
+{
+ updateDeformation();
+ for (int i = 0; i < m_tetras.size(); ++i)
+ {
+ m_tetraScratchesTn[i] = m_tetraScratches[i];
+ }
+}
//
void btSoftBody::Joint::Prepare(btScalar dt, int)
{
@@ -3013,6 +3748,61 @@ void btSoftBody::applyForces()
}
//
+void btSoftBody::setMaxStress(btScalar maxStress)
+{
+ m_cfg.m_maxStress = maxStress;
+}
+
+//
+void btSoftBody::interpolateRenderMesh()
+{
+ if (m_z.size() > 0)
+ {
+ for (int i = 0; i < m_renderNodes.size(); ++i)
+ {
+ const Node* p0 = m_renderNodesParents[i][0];
+ const Node* p1 = m_renderNodesParents[i][1];
+ const Node* p2 = m_renderNodesParents[i][2];
+ btVector3 normal = btCross(p1->m_x - p0->m_x, p2->m_x - p0->m_x);
+ btVector3 unit_normal = normal.normalized();
+ Node& n = m_renderNodes[i];
+ n.m_x.setZero();
+ for (int j = 0; j < 3; ++j)
+ {
+ n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
+ }
+ n.m_x += m_z[i] * unit_normal;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < m_renderNodes.size(); ++i)
+ {
+ Node& n = m_renderNodes[i];
+ n.m_x.setZero();
+ for (int j = 0; j < 4; ++j)
+ {
+ if (m_renderNodesParents[i].size())
+ {
+ n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
+ }
+ }
+ }
+ }
+}
+
+void btSoftBody::setCollisionQuadrature(int N)
+{
+ for (int i = 0; i <= N; ++i)
+ {
+ for (int j = 0; i+j <= N; ++j)
+ {
+ m_quads.push_back(btVector3(btScalar(i)/btScalar(N), btScalar(j)/btScalar(N), btScalar(N-i-j)/btScalar(N)));
+ }
+ }
+}
+
+//
void btSoftBody::PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti)
{
BT_PROFILE("PSolve_Anchors");
@@ -3214,6 +4004,16 @@ btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
return (0);
}
+void btSoftBody::setSelfCollision(bool useSelfCollision)
+{
+ m_useSelfCollision = useSelfCollision;
+}
+
+bool btSoftBody::useSelfCollision()
+{
+ return m_useSelfCollision;
+}
+
//
void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
{
@@ -3252,12 +4052,54 @@ void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap
collider.ProcessColObj(this, pcoWrap);
}
break;
+ case fCollision::SDF_RD:
+ {
+ btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
+ if (pcoWrap->getCollisionObject()->isActive() || this->isActive())
+ {
+ const btTransform wtr = pcoWrap->getWorldTransform();
+ const btScalar timemargin = 0;
+ const btScalar basemargin = getCollisionShape()->getMargin();
+ btVector3 mins;
+ btVector3 maxs;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume)
+ volume;
+ pcoWrap->getCollisionShape()->getAabb(wtr,
+ mins,
+ maxs);
+ volume = btDbvtVolume::FromMM(mins, maxs);
+ volume.Expand(btVector3(basemargin, basemargin, basemargin));
+ if (m_cfg.collisions & fCollision::SDF_RDN)
+ {
+ btSoftColliders::CollideSDF_RD docollideNode;
+ docollideNode.psb = this;
+ docollideNode.m_colObj1Wrap = pcoWrap;
+ docollideNode.m_rigidBody = prb1;
+ docollideNode.dynmargin = basemargin + timemargin;
+ docollideNode.stamargin = basemargin;
+ m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollideNode);
+ }
+
+ if (((pcoWrap->getCollisionObject()->getInternalType() == CO_RIGID_BODY) && (m_cfg.collisions & fCollision::SDF_RDF)) || ((pcoWrap->getCollisionObject()->getInternalType() == CO_FEATHERSTONE_LINK) && (m_cfg.collisions & fCollision::SDF_MDF)))
+ {
+ btSoftColliders::CollideSDF_RDF docollideFace;
+ docollideFace.psb = this;
+ docollideFace.m_colObj1Wrap = pcoWrap;
+ docollideFace.m_rigidBody = prb1;
+ docollideFace.dynmargin = basemargin + timemargin;
+ docollideFace.stamargin = basemargin;
+ m_fdbvt.collideTV(m_fdbvt.m_root, volume, docollideFace);
+ }
+ }
+ }
+ break;
}
}
//
void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
{
+ BT_PROFILE("Deformable Collision");
const int cf = m_cfg.collisions & psb->m_cfg.collisions;
switch (cf & fCollision::SVSmask)
{
@@ -3295,12 +4137,118 @@ void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
}
}
break;
+ case fCollision::VF_DD:
+ {
+ if (!psb->m_softSoftCollision)
+ return;
+ if (psb->isActive() || this->isActive())
+ {
+ if (this != psb)
+ {
+ btSoftColliders::CollideVF_DD docollide;
+ /* common */
+ docollide.mrg = getCollisionShape()->getMargin() +
+ psb->getCollisionShape()->getMargin();
+ /* psb0 nodes vs psb1 faces */
+ if (psb->m_tetras.size() > 0)
+ docollide.useFaceNormal = true;
+ else
+ docollide.useFaceNormal = false;
+ docollide.psb[0] = this;
+ docollide.psb[1] = psb;
+ docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+ docollide.psb[1]->m_fdbvt.m_root,
+ docollide);
+
+ /* psb1 nodes vs psb0 faces */
+ if (this->m_tetras.size() > 0)
+ docollide.useFaceNormal = true;
+ else
+ docollide.useFaceNormal = false;
+ docollide.psb[0] = psb;
+ docollide.psb[1] = this;
+ docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+ docollide.psb[1]->m_fdbvt.m_root,
+ docollide);
+ }
+ else
+ {
+ if (psb->useSelfCollision())
+ {
+ btSoftColliders::CollideFF_DD docollide;
+ docollide.mrg = 2*getCollisionShape()->getMargin();
+ docollide.psb[0] = this;
+ docollide.psb[1] = psb;
+ if (this->m_tetras.size() > 0)
+ docollide.useFaceNormal = true;
+ else
+ docollide.useFaceNormal = false;
+ /* psb0 faces vs psb0 faces */
+ calculateNormalCone(this->m_fdbvnt);
+ this->m_fdbvt.selfCollideT(m_fdbvnt,docollide);
+ }
+ }
+ }
+ }
+ break;
default:
{
}
}
}
+void btSoftBody::geometricCollisionHandler(btSoftBody* psb)
+{
+ if (psb->isActive() || this->isActive())
+ {
+ if (this != psb)
+ {
+ btSoftColliders::CollideCCD docollide;
+ /* common */
+ docollide.mrg = SAFE_EPSILON; // for rounding error instead of actual margin
+ docollide.dt = psb->m_sst.sdt;
+ /* psb0 nodes vs psb1 faces */
+ if (psb->m_tetras.size() > 0)
+ docollide.useFaceNormal = true;
+ else
+ docollide.useFaceNormal = false;
+ docollide.psb[0] = this;
+ docollide.psb[1] = psb;
+ docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+ docollide.psb[1]->m_fdbvt.m_root,
+ docollide);
+ /* psb1 nodes vs psb0 faces */
+ if (this->m_tetras.size() > 0)
+ docollide.useFaceNormal = true;
+ else
+ docollide.useFaceNormal = false;
+ docollide.psb[0] = psb;
+ docollide.psb[1] = this;
+ docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+ docollide.psb[1]->m_fdbvt.m_root,
+ docollide);
+ }
+ else
+ {
+ if (psb->useSelfCollision())
+ {
+ btSoftColliders::CollideCCD docollide;
+ docollide.mrg = SAFE_EPSILON;
+ docollide.psb[0] = this;
+ docollide.psb[1] = psb;
+ docollide.dt = psb->m_sst.sdt;
+ if (this->m_tetras.size() > 0)
+ docollide.useFaceNormal = true;
+ else
+ docollide.useFaceNormal = false;
+ /* psb0 faces vs psb0 faces */
+ calculateNormalCone(this->m_fdbvnt); // should compute this outside of this scope
+ this->m_fdbvt.selfCollideT(m_fdbvnt,docollide);
+ }
+ }
+ }
+}
+
void btSoftBody::setWindVelocity(const btVector3& velocity)
{
m_windVelocity = velocity;
@@ -3434,7 +4382,7 @@ const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializ
for (int j = 0; j < 4; j++)
{
m_tetras[i].m_c0[j].serializeFloat(memPtr->m_c0[j]);
- memPtr->m_nodeIndices[j] = m_tetras[j].m_n[j] ? m_tetras[j].m_n[j] - &m_nodes[0] : -1;
+ memPtr->m_nodeIndices[j] = m_tetras[i].m_n[j] ? m_tetras[i].m_n[j] - &m_nodes[0] : -1;
}
memPtr->m_c1 = m_tetras[i].m_c1;
memPtr->m_c2 = m_tetras[i].m_c2;
@@ -3697,3 +4645,47 @@ const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializ
return btSoftBodyDataName;
}
+
+void btSoftBody::updateDeactivation(btScalar timeStep)
+{
+ if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
+ return;
+
+ if (m_maxSpeedSquared < m_sleepingThreshold * m_sleepingThreshold)
+ {
+ m_deactivationTime += timeStep;
+ }
+ else
+ {
+ m_deactivationTime = btScalar(0.);
+ setActivationState(0);
+ }
+}
+
+
+void btSoftBody::setZeroVelocity()
+{
+ for (int i = 0; i < m_nodes.size(); ++i)
+ {
+ m_nodes[i].m_v.setZero();
+ }
+}
+
+bool btSoftBody::wantsSleeping()
+{
+ if (getActivationState() == DISABLE_DEACTIVATION)
+ return false;
+
+ //disable deactivation
+ if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
+ return false;
+
+ if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
+ return true;
+
+ if (m_deactivationTime > gDeactivationTime)
+ {
+ return true;
+ }
+ return false;
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBody.h b/thirdparty/bullet/BulletSoftBody/btSoftBody.h
index 9b35b799d8..6a55eccbd2 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBody.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBody.h
@@ -20,19 +20,23 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btVector3.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "btSparseSDF.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
-
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
//#ifdef BT_USE_DOUBLE_PRECISION
//#define btRigidBodyData btRigidBodyDoubleData
//#define btRigidBodyDataName "btRigidBodyDoubleData"
//#else
#define btSoftBodyData btSoftBodyFloatData
#define btSoftBodyDataName "btSoftBodyFloatData"
+static const btScalar OVERLAP_REDUCTION_FACTOR = 0.1;
+static unsigned long seed = 243703;
//#endif //BT_USE_DOUBLE_PRECISION
class btBroadphaseInterface;
@@ -159,11 +163,18 @@ public:
RVSmask = 0x000f, ///Rigid versus soft mask
SDF_RS = 0x0001, ///SDF based rigid vs soft
CL_RS = 0x0002, ///Cluster vs convex rigid vs soft
+ SDF_RD = 0x0004, ///rigid vs deformable
- SVSmask = 0x0030, ///Rigid versus soft mask
+ SVSmask = 0x00f0, ///Rigid versus soft mask
VF_SS = 0x0010, ///Vertex vs face soft vs soft handling
CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling
CL_SELF = 0x0040, ///Cluster soft body self collision
+ VF_DD = 0x0080, ///Vertex vs face soft vs soft handling
+
+ RVDFmask = 0x0f00, /// Rigid versus deformable face mask
+ SDF_RDF = 0x0100, /// GJK based Rigid vs. deformable face
+ SDF_MDF = 0x0200, /// GJK based Multibody vs. deformable face
+ SDF_RDN = 0x0400, /// SDF based Rigid vs. deformable node
/* presets */
Default = SDF_RS,
END
@@ -215,6 +226,7 @@ public:
const btCollisionObject* m_colObj; /* Rigid body */
btVector3 m_normal; /* Outward normal */
btScalar m_offset; /* Offset from origin */
+ btVector3 m_bary; /* Barycentric weights for faces */
};
/* sMedium */
@@ -249,14 +261,17 @@ public:
struct Node : Feature
{
btVector3 m_x; // Position
- btVector3 m_q; // Previous step position
+ btVector3 m_q; // Previous step position/Test position
btVector3 m_v; // Velocity
+ btVector3 m_vn; // Previous step velocity
btVector3 m_f; // Force accumulator
btVector3 m_n; // Normal
btScalar m_im; // 1/mass
btScalar m_area; // Area
btDbvtNode* m_leaf; // Leaf data
+ btScalar m_penetration; // depth of penetration
int m_battach : 1; // Attached
+ int index;
};
/* Link */
ATTRIBUTE_ALIGNED16(struct)
@@ -279,6 +294,9 @@ public:
btVector3 m_normal; // Normal
btScalar m_ra; // Rest area
btDbvtNode* m_leaf; // Leaf data
+ btVector4 m_pcontact; // barycentric weights of the persistent contact
+ btVector3 m_n0, m_n1, m_vn;
+ int m_index;
};
/* Tetra */
struct Tetra : Feature
@@ -289,7 +307,20 @@ public:
btVector3 m_c0[4]; // gradients
btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3)
btScalar m_c2; // m_c1/sum(|g0..3|^2)
+ btMatrix3x3 m_Dm_inverse; // rest Dm^-1
+ btMatrix3x3 m_F;
+ btScalar m_element_measure;
};
+
+ /* TetraScratch */
+ struct TetraScratch
+ {
+ btMatrix3x3 m_F; // deformation gradient F
+ btScalar m_trace; // trace of F^T * F
+ btScalar m_J; // det(F)
+ btMatrix3x3 m_cofF; // cofactor of F
+ };
+
/* RContact */
struct RContact
{
@@ -300,7 +331,67 @@ public:
btScalar m_c2; // ima*dt
btScalar m_c3; // Friction
btScalar m_c4; // Hardness
+
+ // jacobians and unit impulse responses for multibody
+ btMultiBodyJacobianData jacobianData_normal;
+ btMultiBodyJacobianData jacobianData_t1;
+ btMultiBodyJacobianData jacobianData_t2;
+ btVector3 t1;
+ btVector3 t2;
};
+
+ class DeformableRigidContact
+ {
+ public:
+ sCti m_cti; // Contact infos
+ btMatrix3x3 m_c0; // Impulse matrix
+ btVector3 m_c1; // Relative anchor
+ btScalar m_c2; // inverse mass of node/face
+ btScalar m_c3; // Friction
+ btScalar m_c4; // Hardness
+
+ // jacobians and unit impulse responses for multibody
+ btMultiBodyJacobianData jacobianData_normal;
+ btMultiBodyJacobianData jacobianData_t1;
+ btMultiBodyJacobianData jacobianData_t2;
+ btVector3 t1;
+ btVector3 t2;
+ };
+
+ class DeformableNodeRigidContact : public DeformableRigidContact
+ {
+ public:
+ Node* m_node; // Owner node
+ };
+
+ class DeformableNodeRigidAnchor : public DeformableNodeRigidContact
+ {
+ public:
+ btVector3 m_local; // Anchor position in body space
+ };
+
+ class DeformableFaceRigidContact : public DeformableRigidContact
+ {
+ public:
+ Face* m_face; // Owner face
+ btVector3 m_contactPoint; // Contact point
+ btVector3 m_bary; // Barycentric weights
+ btVector3 m_weights; // v_contactPoint * m_weights[i] = m_face->m_node[i]->m_v;
+ };
+
+ struct DeformableFaceNodeContact
+ {
+ Node* m_node; // Node
+ Face* m_face; // Face
+ btVector3 m_bary; // Barycentric weights
+ btVector3 m_weights; // v_contactPoint * m_weights[i] = m_face->m_node[i]->m_v;
+ btVector3 m_normal; // Normal
+ btScalar m_margin; // Margin
+ btScalar m_friction; // Friction
+ btScalar m_imf; // inverse mass of the face at contact point
+ btScalar m_c0; // scale of the impulse matrix;
+ };
+
/* SContact */
struct SContact
{
@@ -627,10 +718,21 @@ public:
tVSolverArray m_vsequence; // Velocity solvers sequence
tPSolverArray m_psequence; // Position solvers sequence
tPSolverArray m_dsequence; // Drift solvers sequence
+ btScalar drag; // deformable air drag
+ btScalar m_maxStress; // Maximum principle first Piola stress
};
/* SolverState */
struct SolverState
{
+ //if you add new variables, always initialize them!
+ SolverState()
+ :sdt(0),
+ isdt(0),
+ velmrg(0),
+ radmrg(0),
+ updmrg(0)
+ {
+ }
btScalar sdt; // dt*timescale
btScalar isdt; // 1/sdt
btScalar velmrg; // velocity margin
@@ -689,11 +791,19 @@ public:
btSoftBodyWorldInfo* m_worldInfo; // World info
tNoteArray m_notes; // Notes
tNodeArray m_nodes; // Nodes
+ tNodeArray m_renderNodes; // Nodes
tLinkArray m_links; // Links
tFaceArray m_faces; // Faces
+ tFaceArray m_renderFaces; // Faces
tTetraArray m_tetras; // Tetras
+ btAlignedObjectArray<TetraScratch> m_tetraScratches;
+ btAlignedObjectArray<TetraScratch> m_tetraScratchesTn;
tAnchorArray m_anchors; // Anchors
+ btAlignedObjectArray<DeformableNodeRigidAnchor> m_deformableAnchors;
tRContactArray m_rcontacts; // Rigid contacts
+ btAlignedObjectArray<DeformableNodeRigidContact> m_nodeRigidContacts;
+ btAlignedObjectArray<DeformableFaceNodeContact> m_faceNodeContacts;
+ btAlignedObjectArray<DeformableFaceRigidContact> m_faceRigidContacts;
tSContactArray m_scontacts; // Soft contacts
tJointArray m_joints; // Joints
tMaterialArray m_materials; // Materials
@@ -702,13 +812,24 @@ public:
bool m_bUpdateRtCst; // Update runtime constants
btDbvt m_ndbvt; // Nodes tree
btDbvt m_fdbvt; // Faces tree
+ btDbvntNode* m_fdbvnt; // Faces tree with normals
btDbvt m_cdbvt; // Clusters tree
tClusterArray m_clusters; // Clusters
+ btScalar m_dampingCoefficient; // Damping Coefficient
+ btScalar m_sleepingThreshold;
+ btScalar m_maxSpeedSquared;
+ btAlignedObjectArray<btVector3> m_quads; // quadrature points for collision detection
+ btScalar m_repulsionStiffness;
+ btAlignedObjectArray<btVector3> m_X; // initial positions
+
+ btAlignedObjectArray<btVector4> m_renderNodesInterpolationWeights;
+ btAlignedObjectArray<btAlignedObjectArray<const btSoftBody::Node*> > m_renderNodesParents;
+ btAlignedObjectArray<btScalar> m_z; // vertical distance used in extrapolation
+ bool m_useSelfCollision;
+ bool m_softSoftCollision;
btAlignedObjectArray<bool> m_clusterConnectivity; //cluster connectivity, for self-collision
- btTransform m_initialWorldTransform;
-
btVector3 m_windVelocity;
btScalar m_restLengthScale;
@@ -735,6 +856,11 @@ public:
{
return m_worldInfo;
}
+
+ void setDampingCoefficient(btScalar damping_coeff)
+ {
+ m_dampingCoefficient = damping_coeff;
+ }
///@todo: avoid internal softbody shape hack and move collision code to collision library
virtual void setCollisionShape(btCollisionShape* collisionShape)
@@ -795,7 +921,9 @@ public:
Material* mat = 0);
/* Append anchor */
- void appendAnchor(int node,
+ void appendDeformableAnchor(int node, btRigidBody* body);
+ void appendDeformableAnchor(int node, btMultiBodyLinkCollider* link);
+ void appendAnchor(int node,
btRigidBody* body, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1);
void appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1);
/* Append linear joint */
@@ -842,6 +970,16 @@ public:
void setVolumeMass(btScalar mass);
/* Set volume density (using tetrahedrons) */
void setVolumeDensity(btScalar density);
+ /* Get the linear velocity of the center of mass */
+ btVector3 getLinearVelocity();
+ /* Set the linear velocity of the center of mass */
+ void setLinearVelocity(const btVector3& linVel);
+ /* Set the angular velocity of the center of mass */
+ void setAngularVelocity(const btVector3& angVel);
+ /* Get best fit rigid transform */
+ btTransform getRigidTransform();
+ /* Transform to given pose */
+ void transformTo(const btTransform& trs);
/* Transform */
void transform(const btTransform& trs);
/* Translate */
@@ -862,6 +1000,16 @@ public:
/* Return the volume */
btScalar getVolume() const;
/* Cluster count */
+ btVector3 getCenterOfMass() const
+ {
+ btVector3 com(0, 0, 0);
+ for (int i = 0; i < m_nodes.size(); i++)
+ {
+ com += (m_nodes[i].m_x * this->getMass(i));
+ }
+ com /= this->getTotalMass();
+ return com;
+ }
int clusterCount() const;
/* Cluster center of mass */
static btVector3 clusterCom(const Cluster* cluster);
@@ -898,6 +1046,11 @@ public:
bool rayTest(const btVector3& rayFrom,
const btVector3& rayTo,
sRayCast& results);
+ bool rayFaceTest(const btVector3& rayFrom,
+ const btVector3& rayTo,
+ sRayCast& results);
+ int rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo,
+ btScalar& mint, int& index) const;
/* Solver presets */
void setSolver(eSolverPresets::_ preset);
/* predictMotion */
@@ -915,6 +1068,11 @@ public:
/* defaultCollisionHandlers */
void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap);
void defaultCollisionHandler(btSoftBody* psb);
+ void setSelfCollision(bool useSelfCollision);
+ bool useSelfCollision();
+ void updateDeactivation(btScalar timeStep);
+ void setZeroVelocity();
+ bool wantsSleeping();
//
// Functionality to deal with new accelerated solvers.
@@ -990,8 +1148,11 @@ public:
int rayTest(const btVector3& rayFrom, const btVector3& rayTo,
btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const;
void initializeFaceTree();
+ void rebuildNodeTree();
btVector3 evaluateCom() const;
- bool checkContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti) const;
+ bool checkDeformableContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
+ bool checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap, Face& f, btVector3& contact_point, btVector3& bary, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
+ bool checkContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti) const;
void updateNormals();
void updateBounds();
void updatePose();
@@ -1005,7 +1166,14 @@ public:
void solveClusters(btScalar sor);
void applyClusters(bool drift);
void dampClusters();
+ void setSpringStiffness(btScalar k);
+ void initializeDmInverse();
+ void updateDeformation();
+ void advanceDeformation();
void applyForces();
+ void setMaxStress(btScalar maxStress);
+ void interpolateRenderMesh();
+ void setCollisionQuadrature(int N);
static void PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti);
static void PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti);
static void PSolve_SContacts(btSoftBody* psb, btScalar, btScalar ti);
@@ -1013,13 +1181,184 @@ public:
static void VSolve_Links(btSoftBody* psb, btScalar kst);
static psolver_t getSolver(ePSolver::_ solver);
static vsolver_t getSolver(eVSolver::_ solver);
+ void geometricCollisionHandler(btSoftBody* psb);
+#define SAFE_EPSILON SIMD_EPSILON*100.0
+ void updateNode(btDbvtNode* node, bool use_velocity, bool margin)
+ {
+ if (node->isleaf())
+ {
+ btSoftBody::Node* n = (btSoftBody::Node*)(node->data);
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
+ btScalar pad = margin ? m_sst.radmrg : SAFE_EPSILON; // use user defined margin or margin for floating point precision
+ if (use_velocity)
+ {
+ btVector3 points[2] = {n->m_x, n->m_x + m_sst.sdt * n->m_v};
+ vol = btDbvtVolume::FromPoints(points, 2);
+ vol.Expand(btVector3(pad, pad, pad));
+ }
+ else
+ {
+ vol = btDbvtVolume::FromCR(n->m_x, pad);
+ }
+ node->volume = vol;
+ return;
+ }
+ else
+ {
+ updateNode(node->childs[0], use_velocity, margin);
+ updateNode(node->childs[1], use_velocity, margin);
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
+ Merge(node->childs[0]->volume, node->childs[1]->volume, vol);
+ node->volume = vol;
+ }
+ }
+
+ void updateNodeTree(bool use_velocity, bool margin)
+ {
+ if (m_ndbvt.m_root)
+ updateNode(m_ndbvt.m_root, use_velocity, margin);
+ }
- virtual int calculateSerializeBufferSize() const;
+ template <class DBVTNODE> // btDbvtNode or btDbvntNode
+ void updateFace(DBVTNODE* node, bool use_velocity, bool margin)
+ {
+ if (node->isleaf())
+ {
+ btSoftBody::Face* f = (btSoftBody::Face*)(node->data);
+ btScalar pad = margin ? m_sst.radmrg : SAFE_EPSILON; // use user defined margin or margin for floating point precision
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
+ if (use_velocity)
+ {
+ btVector3 points[6] = {f->m_n[0]->m_x, f->m_n[0]->m_x + m_sst.sdt * f->m_n[0]->m_v,
+ f->m_n[1]->m_x, f->m_n[1]->m_x + m_sst.sdt * f->m_n[1]->m_v,
+ f->m_n[2]->m_x, f->m_n[2]->m_x + m_sst.sdt * f->m_n[2]->m_v};
+ vol = btDbvtVolume::FromPoints(points, 6);
+ }
+ else
+ {
+ btVector3 points[3] = {f->m_n[0]->m_x,
+ f->m_n[1]->m_x,
+ f->m_n[2]->m_x};
+ vol = btDbvtVolume::FromPoints(points, 3);
+ }
+ vol.Expand(btVector3(pad, pad, pad));
+ node->volume = vol;
+ return;
+ }
+ else
+ {
+ updateFace(node->childs[0], use_velocity, margin);
+ updateFace(node->childs[1], use_velocity, margin);
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
+ Merge(node->childs[0]->volume, node->childs[1]->volume, vol);
+ node->volume = vol;
+ }
+ }
+ void updateFaceTree(bool use_velocity, bool margin)
+ {
+ if (m_fdbvt.m_root)
+ updateFace(m_fdbvt.m_root, use_velocity, margin);
+ if (m_fdbvnt)
+ updateFace(m_fdbvnt, use_velocity, margin);
+ }
+ template <typename T>
+ static inline T BaryEval(const T& a,
+ const T& b,
+ const T& c,
+ const btVector3& coord)
+ {
+ return (a * coord.x() + b * coord.y() + c * coord.z());
+ }
+
+ void applyRepulsionForce(btScalar timeStep, bool applySpringForce)
+ {
+ btAlignedObjectArray<int> indices;
+ {
+ // randomize the order of repulsive force
+ indices.resize(m_faceNodeContacts.size());
+ for (int i = 0; i < m_faceNodeContacts.size(); ++i)
+ indices[i] = i;
+#define NEXTRAND (seed = (1664525L * seed + 1013904223L) & 0xffffffff)
+ int i, ni;
+
+ for (i = 0, ni = indices.size(); i < ni; ++i)
+ {
+ btSwap(indices[i], indices[NEXTRAND % ni]);
+ }
+ }
+ for (int k = 0; k < m_faceNodeContacts.size(); ++k)
+ {
+ int i = indices[k];
+ btSoftBody::DeformableFaceNodeContact& c = m_faceNodeContacts[i];
+ btSoftBody::Node* node = c.m_node;
+ btSoftBody::Face* face = c.m_face;
+ const btVector3& w = c.m_bary;
+ const btVector3& n = c.m_normal;
+ btVector3 l = node->m_x - BaryEval(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, w);
+ btScalar d = c.m_margin - n.dot(l);
+ d = btMax(btScalar(0),d);
+
+ const btVector3& va = node->m_v;
+ btVector3 vb = BaryEval(face->m_n[0]->m_v, face->m_n[1]->m_v, face->m_n[2]->m_v, w);
+ btVector3 vr = va - vb;
+ const btScalar vn = btDot(vr, n); // dn < 0 <==> opposing
+ if (vn > OVERLAP_REDUCTION_FACTOR * d / timeStep)
+ continue;
+ btVector3 vt = vr - vn*n;
+ btScalar I = 0;
+ btScalar mass = node->m_im == 0 ? 0 : btScalar(1)/node->m_im;
+ if (applySpringForce)
+ I = -btMin(m_repulsionStiffness * timeStep * d, mass * (OVERLAP_REDUCTION_FACTOR * d / timeStep - vn));
+ if (vn < 0)
+ I += 0.5 * mass * vn;
+ btScalar face_penetration = 0, node_penetration = node->m_penetration;
+ for (int i = 0; i < 3; ++i)
+ face_penetration = btMax(face_penetration, face->m_n[i]->m_penetration);
+ btScalar I_tilde = .5 *I /(1.0+w.length2());
+
+// double the impulse if node or face is constrained.
+ if (face_penetration > 0 || node_penetration > 0)
+ I_tilde *= 2.0;
+ if (face_penetration <= node_penetration)
+ {
+ for (int j = 0; j < 3; ++j)
+ face->m_n[j]->m_v += w[j]*n*I_tilde*node->m_im;
+ }
+ if (face_penetration >= node_penetration)
+ {
+ node->m_v -= I_tilde*node->m_im*n;
+ }
+
+ // apply frictional impulse
+ btScalar vt_norm = vt.safeNorm();
+ if (vt_norm > SIMD_EPSILON)
+ {
+ btScalar delta_vn = -2 * I * node->m_im;
+ btScalar mu = c.m_friction;
+ btScalar vt_new = btMax(btScalar(1) - mu * delta_vn / (vt_norm + SIMD_EPSILON), btScalar(0))*vt_norm;
+ I = 0.5 * mass * (vt_norm-vt_new);
+ vt.safeNormalize();
+ I_tilde = .5 *I /(1.0+w.length2());
+// double the impulse if node or face is constrained.
+// if (face_penetration > 0 || node_penetration > 0)
+// I_tilde *= 2.0;
+ if (face_penetration <= node_penetration)
+ {
+ for (int j = 0; j < 3; ++j)
+ face->m_n[j]->m_v += w[j] * vt * I_tilde * (face->m_n[j])->m_im;
+ }
+ if (face_penetration >= node_penetration)
+ {
+ node->m_v -= I_tilde * node->m_im * vt;
+ }
+ }
+ }
+ }
+ virtual int calculateSerializeBufferSize() const;
+
///fills the dataBuffer and returns the struct name (and 0 on failure)
virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
-
- //virtual void serializeSingleObject(class btSerializer* serializer) const;
};
#endif //_BT_SOFT_BODY_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
index d0a9921d89..c1a87c7d57 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
@@ -16,12 +16,17 @@ subject to the following restrictions:
#include "btSoftBodyInternals.h"
#include <stdio.h>
+#include <string>
+#include <iostream>
+#include <sstream>
#include <string.h>
+#include <algorithm>
#include "btSoftBodyHelpers.h"
#include "LinearMath/btConvexHull.h"
#include "LinearMath/btConvexHullComputer.h"
+#include <map>
+#include <vector>
-//
static void drawVertex(btIDebugDraw* idraw,
const btVector3& x, btScalar s, const btVector3& c)
{
@@ -721,7 +726,8 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo, const
int resx,
int resy,
int fixeds,
- bool gendiags)
+ bool gendiags,
+ btScalar perturbation)
{
#define IDX(_x_, _y_) ((_y_)*rx + (_x_))
/* Create nodes */
@@ -741,7 +747,13 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo, const
for (int ix = 0; ix < rx; ++ix)
{
const btScalar tx = ix / (btScalar)(rx - 1);
- x[IDX(ix, iy)] = lerp(py0, py1, tx);
+ btScalar pert = perturbation * btScalar(rand())/RAND_MAX;
+ btVector3 temp1 = py1;
+ temp1.setY(py1.getY() + pert);
+ btVector3 temp = py0;
+ pert = perturbation * btScalar(rand())/RAND_MAX;
+ temp.setY(py0.getY() + pert);
+ x[IDX(ix, iy)] = lerp(temp, temp1, tx);
m[IDX(ix, iy)] = 1;
}
}
@@ -1221,9 +1233,392 @@ if(face&&face[0])
}
}
}
+ psb->initializeDmInverse();
+ psb->m_tetraScratches.resize(psb->m_tetras.size());
+ psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
printf("Nodes: %u\r\n", psb->m_nodes.size());
printf("Links: %u\r\n", psb->m_links.size());
printf("Faces: %u\r\n", psb->m_faces.size());
printf("Tetras: %u\r\n", psb->m_tetras.size());
return (psb);
}
+
+btSoftBody* btSoftBodyHelpers::CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file)
+{
+ std::ifstream fs;
+ fs.open(vtk_file);
+ btAssert(fs);
+
+ typedef btAlignedObjectArray<int> Index;
+ std::string line;
+ btAlignedObjectArray<btVector3> X;
+ btVector3 position;
+ btAlignedObjectArray<Index> indices;
+ bool reading_points = false;
+ bool reading_tets = false;
+ size_t n_points = 0;
+ size_t n_tets = 0;
+ size_t x_count = 0;
+ size_t indices_count = 0;
+ while (std::getline(fs, line))
+ {
+ std::stringstream ss(line);
+ if (line.size() == (size_t)(0))
+ {
+ }
+ else if (line.substr(0, 6) == "POINTS")
+ {
+ reading_points = true;
+ reading_tets = false;
+ ss.ignore(128, ' '); // ignore "POINTS"
+ ss >> n_points;
+ X.resize(n_points);
+ }
+ else if (line.substr(0, 5) == "CELLS")
+ {
+ reading_points = false;
+ reading_tets = true;
+ ss.ignore(128, ' '); // ignore "CELLS"
+ ss >> n_tets;
+ indices.resize(n_tets);
+ }
+ else if (line.substr(0, 10) == "CELL_TYPES")
+ {
+ reading_points = false;
+ reading_tets = false;
+ }
+ else if (reading_points)
+ {
+ btScalar p;
+ ss >> p;
+ position.setX(p);
+ ss >> p;
+ position.setY(p);
+ ss >> p;
+ position.setZ(p);
+ X[x_count++] = position;
+ }
+ else if (reading_tets)
+ {
+ int d;
+ ss >> d;
+ if (d != 4)
+ {
+ printf("Load deformable failed: Only Tetrahedra are supported in VTK file.\n");
+ fs.close();
+ return 0;
+ }
+ ss.ignore(128, ' '); // ignore "4"
+ Index tet;
+ tet.resize(4);
+ for (size_t i = 0; i < 4; i++)
+ {
+ ss >> tet[i];
+ printf("%d ", tet[i]);
+ }
+ printf("\n");
+ indices[indices_count++] = tet;
+ }
+ }
+ btSoftBody* psb = new btSoftBody(&worldInfo, n_points, &X[0], 0);
+
+ for (int i = 0; i < n_tets; ++i)
+ {
+ const Index& ni = indices[i];
+ psb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
+ {
+ psb->appendLink(ni[0], ni[1], 0, true);
+ psb->appendLink(ni[1], ni[2], 0, true);
+ psb->appendLink(ni[2], ni[0], 0, true);
+ psb->appendLink(ni[0], ni[3], 0, true);
+ psb->appendLink(ni[1], ni[3], 0, true);
+ psb->appendLink(ni[2], ni[3], 0, true);
+ }
+ }
+
+
+ generateBoundaryFaces(psb);
+ psb->initializeDmInverse();
+ psb->m_tetraScratches.resize(psb->m_tetras.size());
+ psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
+ printf("Nodes: %u\r\n", psb->m_nodes.size());
+ printf("Links: %u\r\n", psb->m_links.size());
+ printf("Faces: %u\r\n", psb->m_faces.size());
+ printf("Tetras: %u\r\n", psb->m_tetras.size());
+
+ fs.close();
+ return psb;
+}
+
+void btSoftBodyHelpers::generateBoundaryFaces(btSoftBody* psb)
+{
+ int counter = 0;
+ for (int i = 0; i < psb->m_nodes.size(); ++i)
+ {
+ psb->m_nodes[i].index = counter++;
+ }
+ typedef btAlignedObjectArray<int> Index;
+ btAlignedObjectArray<Index> indices;
+ indices.resize(psb->m_tetras.size());
+ for (int i = 0; i < indices.size(); ++i)
+ {
+ Index index;
+ index.push_back(psb->m_tetras[i].m_n[0]->index);
+ index.push_back(psb->m_tetras[i].m_n[1]->index);
+ index.push_back(psb->m_tetras[i].m_n[2]->index);
+ index.push_back(psb->m_tetras[i].m_n[3]->index);
+ indices[i] = index;
+ }
+
+ std::map<std::vector<int>, std::vector<int> > dict;
+ for (int i = 0; i < indices.size(); ++i)
+ {
+ for (int j = 0; j < 4; ++j)
+ {
+ std::vector<int> f;
+ if (j == 0)
+ {
+ f.push_back(indices[i][1]);
+ f.push_back(indices[i][0]);
+ f.push_back(indices[i][2]);
+ }
+ if (j == 1)
+ {
+ f.push_back(indices[i][3]);
+ f.push_back(indices[i][0]);
+ f.push_back(indices[i][1]);
+ }
+ if (j == 2)
+ {
+ f.push_back(indices[i][3]);
+ f.push_back(indices[i][1]);
+ f.push_back(indices[i][2]);
+ }
+ if (j == 3)
+ {
+ f.push_back(indices[i][2]);
+ f.push_back(indices[i][0]);
+ f.push_back(indices[i][3]);
+ }
+ std::vector<int> f_sorted = f;
+ std::sort(f_sorted.begin(), f_sorted.end());
+ if (dict.find(f_sorted) != dict.end())
+ {
+ dict.erase(f_sorted);
+ }
+ else
+ {
+ dict.insert(std::make_pair(f_sorted, f));
+ }
+ }
+ }
+
+ for (std::map<std::vector<int>, std::vector<int> >::iterator it = dict.begin(); it != dict.end(); ++it)
+ {
+ std::vector<int> f = it->second;
+ psb->appendFace(f[0], f[1], f[2]);
+ }
+}
+
+void btSoftBodyHelpers::writeObj(const char* filename, const btSoftBody* psb)
+{
+ std::ofstream fs;
+ fs.open(filename);
+ btAssert(fs);
+ for (int i = 0; i < psb->m_nodes.size(); ++i)
+ {
+ fs << "v";
+ for (int d = 0; d < 3; d++)
+ {
+ fs << " " << psb->m_nodes[i].m_x[d];
+ }
+ fs << "\n";
+ }
+
+ for (int i = 0; i < psb->m_faces.size(); ++i)
+ {
+ fs << "f";
+ for (int n = 0; n < 3; n++)
+ {
+ fs << " " << psb->m_faces[i].m_n[n]->index + 1;
+ }
+ fs << "\n";
+ }
+ fs.close();
+}
+
+void btSoftBodyHelpers::duplicateFaces(const char* filename, const btSoftBody* psb)
+{
+ std::ifstream fs_read;
+ fs_read.open(filename);
+ std::string line;
+ btVector3 pos;
+ btAlignedObjectArray<btAlignedObjectArray<int> > additional_faces;
+ while (std::getline(fs_read, line))
+ {
+ std::stringstream ss(line);
+ if (line[0] == 'v')
+ {
+ }
+ else if (line[0] == 'f')
+ {
+ ss.ignore();
+ int id0, id1, id2;
+ ss >> id0;
+ ss >> id1;
+ ss >> id2;
+ btAlignedObjectArray<int> new_face;
+ new_face.push_back(id1);
+ new_face.push_back(id0);
+ new_face.push_back(id2);
+ additional_faces.push_back(new_face);
+ }
+ }
+ fs_read.close();
+
+ std::ofstream fs_write;
+ fs_write.open(filename, std::ios_base::app);
+ for (int i = 0; i < additional_faces.size(); ++i)
+ {
+ fs_write << "f";
+ for (int n = 0; n < 3; n++)
+ {
+ fs_write << " " << additional_faces[i][n];
+ }
+ fs_write << "\n";
+ }
+ fs_write.close();
+}
+
+// Given a simplex with vertices a,b,c,d, find the barycentric weights of p in this simplex
+void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary)
+{
+ btVector3 vap = p - a;
+ btVector3 vbp = p - b;
+
+ btVector3 vab = b - a;
+ btVector3 vac = c - a;
+ btVector3 vad = d - a;
+
+ btVector3 vbc = c - b;
+ btVector3 vbd = d - b;
+ btScalar va6 = (vbp.cross(vbd)).dot(vbc);
+ btScalar vb6 = (vap.cross(vac)).dot(vad);
+ btScalar vc6 = (vap.cross(vad)).dot(vab);
+ btScalar vd6 = (vap.cross(vab)).dot(vac);
+ btScalar v6 = btScalar(1) / (vab.cross(vac).dot(vad));
+ bary = btVector4(va6*v6, vb6*v6, vc6*v6, vd6*v6);
+}
+
+// Given a simplex with vertices a,b,c, find the barycentric weights of p in this simplex. bary[3] = 0.
+void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& p, btVector4& bary)
+{
+ btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
+ btScalar d00 = btDot(v0, v0);
+ btScalar d01 = btDot(v0, v1);
+ btScalar d11 = btDot(v1, v1);
+ btScalar d20 = btDot(v2, v0);
+ btScalar d21 = btDot(v2, v1);
+ btScalar invDenom = 1.0 / (d00 * d11 - d01 * d01);
+ bary[1] = (d11 * d20 - d01 * d21) * invDenom;
+ bary[2] = (d00 * d21 - d01 * d20) * invDenom;
+ bary[0] = 1.0 - bary[1] - bary[2];
+ bary[3] = 0;
+}
+
+// Iterate through all render nodes to find the simulation tetrahedron that contains the render node and record the barycentric weights
+// If the node is not inside any tetrahedron, assign it to the tetrahedron in which the node has the least negative barycentric weight
+void btSoftBodyHelpers::interpolateBarycentricWeights(btSoftBody* psb)
+{
+ psb->m_z.resize(0);
+ psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
+ psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
+ for (int i = 0; i < psb->m_renderNodes.size(); ++i)
+ {
+ const btVector3& p = psb->m_renderNodes[i].m_x;
+ btVector4 bary;
+ btVector4 optimal_bary;
+ btScalar min_bary_weight = -1e3;
+ btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
+ for (int j = 0; j < psb->m_tetras.size(); ++j)
+ {
+ const btSoftBody::Tetra& t = psb->m_tetras[j];
+ getBarycentricWeights(t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x, p, bary);
+ btScalar new_min_bary_weight = bary[0];
+ for (int k = 1; k < 4; ++k)
+ {
+ new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
+ }
+ if (new_min_bary_weight > min_bary_weight)
+ {
+ btAlignedObjectArray<const btSoftBody::Node*> parents;
+ parents.push_back(t.m_n[0]);
+ parents.push_back(t.m_n[1]);
+ parents.push_back(t.m_n[2]);
+ parents.push_back(t.m_n[3]);
+ optimal_parents = parents;
+ optimal_bary = bary;
+ min_bary_weight = new_min_bary_weight;
+ // stop searching if p is inside the tetrahedron at hand
+ if (bary[0]>=0. && bary[1]>=0. && bary[2]>=0. && bary[3]>=0.)
+ {
+ break;
+ }
+ }
+ }
+ psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
+ psb->m_renderNodesParents[i] = optimal_parents;
+ }
+}
+
+
+// Iterate through all render nodes to find the simulation triangle that's closest to the node in the barycentric sense.
+void btSoftBodyHelpers::extrapolateBarycentricWeights(btSoftBody* psb)
+{
+ psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
+ psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
+ psb->m_z.resize(psb->m_renderNodes.size());
+ for (int i = 0; i < psb->m_renderNodes.size(); ++i)
+ {
+ const btVector3& p = psb->m_renderNodes[i].m_x;
+ btVector4 bary;
+ btVector4 optimal_bary;
+ btScalar min_bary_weight = -SIMD_INFINITY;
+ btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
+ btScalar dist = 0, optimal_dist = 0;
+ for (int j = 0; j < psb->m_faces.size(); ++j)
+ {
+ const btSoftBody::Face& f = psb->m_faces[j];
+ btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
+ btVector3 unit_n = n.normalized();
+ dist = (p-f.m_n[0]->m_x).dot(unit_n);
+ btVector3 proj_p = p - dist*unit_n;
+ getBarycentricWeights(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, proj_p, bary);
+ btScalar new_min_bary_weight = bary[0];
+ for (int k = 1; k < 3; ++k)
+ {
+ new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
+ }
+
+ // p is out of the current best triangle, we found a traingle that's better
+ bool better_than_closest_outisde = (new_min_bary_weight > min_bary_weight && min_bary_weight<0.);
+ // p is inside of the current best triangle, we found a triangle that's better
+ bool better_than_best_inside = (new_min_bary_weight>=0 && min_bary_weight>=0 && btFabs(dist)<btFabs(optimal_dist));
+
+ if (better_than_closest_outisde || better_than_best_inside)
+ {
+ btAlignedObjectArray<const btSoftBody::Node*> parents;
+ parents.push_back(f.m_n[0]);
+ parents.push_back(f.m_n[1]);
+ parents.push_back(f.m_n[2]);
+ optimal_parents = parents;
+ optimal_bary = bary;
+ optimal_dist = dist;
+ min_bary_weight = new_min_bary_weight;
+ }
+ }
+ psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
+ psb->m_renderNodesParents[i] = optimal_parents;
+ psb->m_z[i] = optimal_dist;
+ }
+}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
index e433558c18..abe1870890 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
@@ -17,7 +17,8 @@ subject to the following restrictions:
#define BT_SOFT_BODY_HELPERS_H
#include "btSoftBody.h"
-
+#include <fstream>
+#include <string>
//
// Helpers
//
@@ -91,7 +92,8 @@ struct btSoftBodyHelpers
int resx,
int resy,
int fixeds,
- bool gendiags);
+ bool gendiags,
+ btScalar perturbation = 0.);
/* Create a patch with UV Texture Coordinates */
static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
const btVector3& corner00,
@@ -140,7 +142,21 @@ struct btSoftBodyHelpers
bool bfacelinks,
bool btetralinks,
bool bfacesfromtetras);
+ static btSoftBody* CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file);
+ static void writeObj(const char* file, const btSoftBody* psb);
+
+ static void getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary);
+
+ static void getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& p, btVector4& bary);
+
+ static void interpolateBarycentricWeights(btSoftBody* psb);
+
+ static void extrapolateBarycentricWeights(btSoftBody* psb);
+
+ static void generateBoundaryFaces(btSoftBody* psb);
+
+ static void duplicateFaces(const char* filename, const btSoftBody* psb);
/// Sort the list of links to move link calculations that are dependent upon earlier
/// ones as far as possible away from the calculation of those values
/// This tends to make adjacent loop iterations not dependent upon one another,
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
index 7efe514f38..b9ebc95b6b 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
@@ -18,14 +18,615 @@ subject to the following restrictions:
#define _BT_SOFT_BODY_INTERNALS_H
#include "btSoftBody.h"
-
#include "LinearMath/btQuickprof.h"
#include "LinearMath/btPolarDecomposition.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
#include <string.h> //for memset
+#include <cmath>
+#include "poly34.h"
+
+// Given a multibody link, a contact point and a contact direction, fill in the jacobian data needed to calculate the velocity change given an impulse in the contact direction
+static SIMD_FORCE_INLINE void findJacobian(const btMultiBodyLinkCollider* multibodyLinkCol,
+ btMultiBodyJacobianData& jacobianData,
+ const btVector3& contact_point,
+ const btVector3& dir)
+{
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ jacobianData.m_jacobians.resize(ndof);
+ jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
+ btScalar* jac = &jacobianData.m_jacobians[0];
+
+ multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, contact_point, dir, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
+ multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], &jacobianData.m_deltaVelocitiesUnitImpulse[0], jacobianData.scratch_r, jacobianData.scratch_v);
+}
+static SIMD_FORCE_INLINE btVector3 generateUnitOrthogonalVector(const btVector3& u)
+{
+ btScalar ux = u.getX();
+ btScalar uy = u.getY();
+ btScalar uz = u.getZ();
+ btScalar ax = std::abs(ux);
+ btScalar ay = std::abs(uy);
+ btScalar az = std::abs(uz);
+ btVector3 v;
+ if (ax <= ay && ax <= az)
+ v = btVector3(0, -uz, uy);
+ else if (ay <= ax && ay <= az)
+ v = btVector3(-uz, 0, ux);
+ else
+ v = btVector3(-uy, ux, 0);
+ v.normalize();
+ return v;
+}
+
+static SIMD_FORCE_INLINE bool proximityTest(const btVector3& x1, const btVector3& x2, const btVector3& x3, const btVector3& x4, const btVector3& normal, const btScalar& mrg, btVector3& bary)
+{
+ btVector3 x43 = x4-x3;
+ if (std::abs(x43.dot(normal)) > mrg)
+ return false;
+ btVector3 x13 = x1-x3;
+ btVector3 x23 = x2-x3;
+ btScalar a11 = x13.length2();
+ btScalar a22 = x23.length2();
+ btScalar a12 = x13.dot(x23);
+ btScalar b1 = x13.dot(x43);
+ btScalar b2 = x23.dot(x43);
+ btScalar det = a11*a22 - a12*a12;
+ if (det < SIMD_EPSILON)
+ return false;
+ btScalar w1 = (b1*a22-b2*a12)/det;
+ btScalar w2 = (b2*a11-b1*a12)/det;
+ btScalar w3 = 1-w1-w2;
+ btScalar delta = mrg / std::sqrt(0.5*std::abs(x13.cross(x23).safeNorm()));
+ bary = btVector3(w1,w2,w3);
+ for (int i = 0; i < 3; ++i)
+ {
+ if (bary[i] < -delta || bary[i] > 1+delta)
+ return false;
+ }
+ return true;
+}
+static const int KDOP_COUNT = 13;
+static btVector3 dop[KDOP_COUNT]={btVector3(1,0,0),
+ btVector3(0,1,0),
+ btVector3(0,0,1),
+ btVector3(1,1,0),
+ btVector3(1,0,1),
+ btVector3(0,1,1),
+ btVector3(1,-1,0),
+ btVector3(1,0,-1),
+ btVector3(0,1,-1),
+ btVector3(1,1,1),
+ btVector3(1,-1,1),
+ btVector3(1,1,-1),
+ btVector3(1,-1,-1)
+};
+
+static inline int getSign(const btVector3& n, const btVector3& x)
+{
+ btScalar d = n.dot(x);
+ if (d>SIMD_EPSILON)
+ return 1;
+ if (d<-SIMD_EPSILON)
+ return -1;
+ return 0;
+}
+
+static SIMD_FORCE_INLINE bool hasSeparatingPlane(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+ btVector3 hex[6] = {face->m_n[0]->m_x - node->m_x,
+ face->m_n[1]->m_x - node->m_x,
+ face->m_n[2]->m_x - node->m_x,
+ face->m_n[0]->m_x + dt*face->m_n[0]->m_v - node->m_x,
+ face->m_n[1]->m_x + dt*face->m_n[1]->m_v - node->m_x,
+ face->m_n[2]->m_x + dt*face->m_n[2]->m_v - node->m_x
+ };
+ btVector3 segment = dt*node->m_v;
+ for (int i = 0; i < KDOP_COUNT; ++i)
+ {
+ int s = getSign(dop[i], segment);
+ int j = 0;
+ for (; j < 6; ++j)
+ {
+ if (getSign(dop[i], hex[j]) == s)
+ break;
+ }
+ if (j == 6)
+ return true;
+ }
+ return false;
+}
+
+static SIMD_FORCE_INLINE bool nearZero(const btScalar& a)
+{
+ return (a>-SAFE_EPSILON && a<SAFE_EPSILON);
+}
+static SIMD_FORCE_INLINE bool sameSign(const btScalar& a, const btScalar& b)
+{
+ return (nearZero(a) || nearZero(b) || (a>SAFE_EPSILON && b>SAFE_EPSILON) || (a<-SAFE_EPSILON && b<-SAFE_EPSILON));
+}
+static SIMD_FORCE_INLINE bool diffSign(const btScalar& a, const btScalar& b)
+{
+ return !sameSign(a, b);
+}
+inline btScalar evaluateBezier2(const btScalar &p0, const btScalar &p1, const btScalar &p2, const btScalar &t, const btScalar &s)
+{
+ btScalar s2 = s*s;
+ btScalar t2 = t*t;
+
+ return p0*s2+p1*btScalar(2.0)*s*t+p2*t2;
+}
+inline btScalar evaluateBezier(const btScalar &p0, const btScalar &p1, const btScalar &p2, const btScalar &p3, const btScalar &t, const btScalar &s)
+{
+ btScalar s2 = s*s;
+ btScalar s3 = s2*s;
+ btScalar t2 = t*t;
+ btScalar t3 = t2*t;
+
+ return p0*s3+p1*btScalar(3.0)*s2*t+p2*btScalar(3.0)*s*t2+p3*t3;
+}
+static SIMD_FORCE_INLINE bool getSigns(bool type_c, const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& t0, const btScalar& t1, btScalar &lt0, btScalar &lt1)
+{
+ if (sameSign(t0, t1)) {
+ lt0 = t0;
+ lt1 = t0;
+ return true;
+ }
+
+ if (type_c || diffSign(k0, k3)) {
+ btScalar ft = evaluateBezier(k0, k1, k2, k3, t0, -t1);
+ if (t0<-0)
+ ft = -ft;
+
+ if (sameSign(ft, k0)) {
+ lt0 = t1;
+ lt1 = t1;
+ }
+ else {
+ lt0 = t0;
+ lt1 = t0;
+ }
+ return true;
+ }
+
+ if (!type_c) {
+ btScalar ft = evaluateBezier(k0, k1, k2, k3, t0, -t1);
+ if (t0<-0)
+ ft = -ft;
+
+ if (diffSign(ft, k0)) {
+ lt0 = t0;
+ lt1 = t1;
+ return true;
+ }
+
+ btScalar fk = evaluateBezier2(k1-k0, k2-k1, k3-k2, t0, -t1);
+
+ if (sameSign(fk, k1-k0))
+ lt0 = lt1 = t1;
+ else
+ lt0 = lt1 = t0;
+
+ return true;
+ }
+ return false;
+}
+
+static SIMD_FORCE_INLINE void getBernsteinCoeff(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, btScalar& k0, btScalar& k1, btScalar& k2, btScalar& k3)
+{
+ const btVector3& n0 = face->m_n0;
+ const btVector3& n1 = face->m_n1;
+ btVector3 n_hat = n0 + n1 - face->m_vn;
+ btVector3 p0ma0 = node->m_x - face->m_n[0]->m_x;
+ btVector3 p1ma1 = node->m_q - face->m_n[0]->m_q;
+ k0 = (p0ma0).dot(n0) * 3.0;
+ k1 = (p0ma0).dot(n_hat) + (p1ma1).dot(n0);
+ k2 = (p1ma1).dot(n_hat) + (p0ma0).dot(n1);
+ k3 = (p1ma1).dot(n1) * 3.0;
+}
+
+static SIMD_FORCE_INLINE void polyDecomposition(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& j0, const btScalar& j1, const btScalar& j2, btScalar& u0, btScalar& u1, btScalar& v0, btScalar& v1)
+{
+ btScalar denom = 4.0 * (j1-j2) * (j1-j0) + (j2-j0) * (j2-j0);
+ u0 = (2.0*(j1-j2)*(3.0*k1-2.0*k0-k3) - (j0-j2)*(3.0*k2-2.0*k3-k0)) / denom;
+ u1 = (2.0*(j1-j0)*(3.0*k2-2.0*k3-k0) - (j2-j0)*(3.0*k1-2.0*k0-k3)) / denom;
+ v0 = k0-u0*j0;
+ v1 = k3-u1*j2;
+}
+
+static SIMD_FORCE_INLINE bool rootFindingLemma(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3)
+{
+ btScalar u0, u1, v0, v1;
+ btScalar j0 = 3.0*(k1-k0);
+ btScalar j1 = 3.0*(k2-k1);
+ btScalar j2 = 3.0*(k3-k2);
+ polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+ if (sameSign(v0, v1))
+ {
+ btScalar Ypa = j0*(1.0-v0)*(1.0-v0) + 2.0*j1*v0*(1.0-v0) + j2*v0*v0; // Y'(v0)
+ if (sameSign(Ypa, j0))
+ {
+ return (diffSign(k0,v1));
+ }
+ }
+ return diffSign(k0,v0);
+}
+
+static SIMD_FORCE_INLINE void getJs(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Node* a, const btSoftBody::Node* b, const btSoftBody::Node* c, const btSoftBody::Node* p, const btScalar& dt, btScalar& j0, btScalar& j1, btScalar& j2)
+{
+ const btVector3& a0 = a->m_x;
+ const btVector3& b0 = b->m_x;
+ const btVector3& c0 = c->m_x;
+ const btVector3& va = a->m_v;
+ const btVector3& vb = b->m_v;
+ const btVector3& vc = c->m_v;
+ const btVector3 a1 = a0 + dt*va;
+ const btVector3 b1 = b0 + dt*vb;
+ const btVector3 c1 = c0 + dt*vc;
+ btVector3 n0 = (b0-a0).cross(c0-a0);
+ btVector3 n1 = (b1-a1).cross(c1-a1);
+ btVector3 n_hat = n0+n1 - dt*dt*(vb-va).cross(vc-va);
+ const btVector3& p0 = p->m_x;
+ const btVector3& vp = p->m_v;
+ btVector3 p1 = p0 + dt*vp;
+ btVector3 m0 = (b0-p0).cross(c0-p0);
+ btVector3 m1 = (b1-p1).cross(c1-p1);
+ btVector3 m_hat = m0+m1 - dt*dt*(vb-vp).cross(vc-vp);
+ btScalar l0 = m0.dot(n0);
+ btScalar l1 = 0.25 * (m0.dot(n_hat) + m_hat.dot(n0));
+ btScalar l2 = btScalar(1)/btScalar(6)*(m0.dot(n1) + m_hat.dot(n_hat) + m1.dot(n0));
+ btScalar l3 = 0.25 * (m_hat.dot(n1) + m1.dot(n_hat));
+ btScalar l4 = m1.dot(n1);
+
+ btScalar k1p = 0.25 * k0 + 0.75 * k1;
+ btScalar k2p = 0.5 * k1 + 0.5 * k2;
+ btScalar k3p = 0.75 * k2 + 0.25 * k3;
+
+ btScalar s0 = (l1 * k0 - l0 * k1p)*4.0;
+ btScalar s1 = (l2 * k0 - l0 * k2p)*2.0;
+ btScalar s2 = (l3 * k0 - l0 * k3p)*btScalar(4)/btScalar(3);
+ btScalar s3 = l4 * k0 - l0 * k3;
+
+ j0 = (s1*k0 - s0*k1) * 3.0;
+ j1 = (s2*k0 - s0*k2) * 1.5;
+ j2 = (s3*k0 - s0*k3);
+}
+
+static SIMD_FORCE_INLINE bool signDetermination1Internal(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& u0, const btScalar& u1, const btScalar& v0, const btScalar& v1)
+{
+ btScalar Yu0 = k0*(1.0-u0)*(1.0-u0)*(1.0-u0) + 3.0*k1*u0*(1.0-u0)*(1.0-u0) + 3.0*k2*u0*u0*(1.0-u0) + k3*u0*u0*u0; // Y(u0)
+ btScalar Yv0 = k0*(1.0-v0)*(1.0-v0)*(1.0-v0) + 3.0*k1*v0*(1.0-v0)*(1.0-v0) + 3.0*k2*v0*v0*(1.0-v0) + k3*v0*v0*v0; // Y(v0)
+
+ btScalar sign_Ytp = (u0 > u1) ? Yu0 : -Yu0;
+ btScalar L = sameSign(sign_Ytp, k0) ? u1 : u0;
+ sign_Ytp = (v0 > v1) ? Yv0 : -Yv0;
+ btScalar K = (sameSign(sign_Ytp,k0)) ? v1 : v0;
+ return diffSign(L,K);
+}
+
+static SIMD_FORCE_INLINE bool signDetermination2Internal(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& j0, const btScalar& j1, const btScalar& j2, const btScalar& u0, const btScalar& u1, const btScalar& v0, const btScalar& v1)
+{
+ btScalar Yu0 = k0*(1.0-u0)*(1.0-u0)*(1.0-u0) + 3.0*k1*u0*(1.0-u0)*(1.0-u0) + 3.0*k2*u0*u0*(1.0-u0) + k3*u0*u0*u0; // Y(u0)
+ btScalar sign_Ytp = (u0 > u1) ? Yu0 : -Yu0, L1, L2;
+ if (diffSign(sign_Ytp,k0))
+ {
+ L1 = u0;
+ L2 = u1;
+ }
+ else
+ {
+ btScalar Yp_u0 = j0*(1.0-u0)*(1.0-u0) + 2.0*j1*(1.0-u0)*u0 + j2*u0*u0;
+ if (sameSign(Yp_u0,j0))
+ {
+ L1 = u1;
+ L2 = u1;
+ }
+ else
+ {
+ L1 = u0;
+ L2 = u0;
+ }
+ }
+ btScalar Yv0 = k0*(1.0-v0)*(1.0-v0)*(1.0-v0) + 3.0*k1*v0*(1.0-v0)*(1.0-v0) + 3.0*k2*v0*v0*(1.0-v0) + k3*v0*v0*v0; // Y(uv0)
+ sign_Ytp = (v0 > v1) ? Yv0 : -Yv0;
+ btScalar K1, K2;
+ if (diffSign(sign_Ytp,k0))
+ {
+ K1 = v0;
+ K2 = v1;
+ }
+ else
+ {
+ btScalar Yp_v0 = j0*(1.0-v0)*(1.0-v0) + 2.0*j1*(1.0-v0)*v0 + j2*v0*v0;
+ if (sameSign(Yp_v0,j0))
+ {
+ K1 = v1;
+ K2 = v1;
+ }
+ else
+ {
+ K1 = v0;
+ K2 = v0;
+ }
+ }
+ return (diffSign(K1, L1) || diffSign(L2, K2));
+}
+
+static SIMD_FORCE_INLINE bool signDetermination1(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+ btScalar j0, j1, j2, u0, u1, v0, v1;
+ // p1
+ getJs(k0,k1,k2,k3,face->m_n[0], face->m_n[1], face->m_n[2], node, dt, j0, j1, j2);
+ if (nearZero(j0+j2-j1*2.0))
+ {
+ btScalar lt0, lt1;
+ getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
+ if (lt0 < -SAFE_EPSILON)
+ return false;
+ }
+ else
+ {
+ polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+ if (!signDetermination1Internal(k0,k1,k2,k3,u0,u1,v0,v1))
+ return false;
+ }
+ // p2
+ getJs(k0,k1,k2,k3,face->m_n[1], face->m_n[2], face->m_n[0], node, dt, j0, j1, j2);
+ if (nearZero(j0+j2-j1*2.0))
+ {
+ btScalar lt0, lt1;
+ getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
+ if (lt0 < -SAFE_EPSILON)
+ return false;
+ }
+ else
+ {
+ polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+ if (!signDetermination1Internal(k0,k1,k2,k3,u0,u1,v0,v1))
+ return false;
+ }
+ // p3
+ getJs(k0,k1,k2,k3,face->m_n[2], face->m_n[0], face->m_n[1], node, dt, j0, j1, j2);
+ if (nearZero(j0+j2-j1*2.0))
+ {
+ btScalar lt0, lt1;
+ getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
+ if (lt0 < -SAFE_EPSILON)
+ return false;
+ }
+ else
+ {
+ polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+ if (!signDetermination1Internal(k0,k1,k2,k3,u0,u1,v0,v1))
+ return false;
+ }
+ return true;
+}
+
+static SIMD_FORCE_INLINE bool signDetermination2(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+ btScalar j0, j1, j2, u0, u1, v0, v1;
+ // p1
+ getJs(k0,k1,k2,k3,face->m_n[0], face->m_n[1], face->m_n[2], node, dt, j0, j1, j2);
+ if (nearZero(j0+j2-j1*2.0))
+ {
+ btScalar lt0, lt1;
+ bool bt0 = true, bt1=true;
+ getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
+ if (lt0 < -SAFE_EPSILON)
+ bt0 = false;
+ if (lt1 < -SAFE_EPSILON)
+ bt1 = false;
+ if (!bt0 && !bt1)
+ return false;
+ }
+ else
+ {
+ polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+ if (!signDetermination2Internal(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1))
+ return false;
+ }
+ // p2
+ getJs(k0,k1,k2,k3,face->m_n[1], face->m_n[2], face->m_n[0], node, dt, j0, j1, j2);
+ if (nearZero(j0+j2-j1*2.0))
+ {
+ btScalar lt0, lt1;
+ bool bt0=true, bt1=true;
+ getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
+ if (lt0 < -SAFE_EPSILON)
+ bt0 = false;
+ if (lt1 < -SAFE_EPSILON)
+ bt1 = false;
+ if (!bt0 && !bt1)
+ return false;
+ }
+ else
+ {
+ polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+ if (!signDetermination2Internal(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1))
+ return false;
+ }
+ // p3
+ getJs(k0,k1,k2,k3,face->m_n[2], face->m_n[0], face->m_n[1], node, dt, j0, j1, j2);
+ if (nearZero(j0+j2-j1*2.0))
+ {
+ btScalar lt0, lt1;
+ bool bt0=true, bt1=true;
+ getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
+ if (lt0 < -SAFE_EPSILON)
+ bt0 = false;
+ if (lt1 < -SAFE_EPSILON)
+ bt1 = false;
+ if (!bt0 && !bt1)
+ return false;
+ }
+ else
+ {
+ polyDecomposition(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1);
+ if (!signDetermination2Internal(k0,k1,k2,k3,j0,j1,j2,u0,u1,v0,v1))
+ return false;
+ }
+ return true;
+}
+
+static SIMD_FORCE_INLINE bool coplanarAndInsideTest(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+ // Coplanar test
+ if (diffSign(k1-k0, k3-k2))
+ {
+ // Case b:
+ if (sameSign(k0, k3) && !rootFindingLemma(k0,k1,k2,k3))
+ return false;
+ // inside test
+ return signDetermination2(k0, k1, k2, k3, face, node, dt);
+ }
+ else
+ {
+ // Case c:
+ if (sameSign(k0, k3))
+ return false;
+ // inside test
+ return signDetermination1(k0, k1, k2, k3, face, node, dt);
+ }
+ return false;
+}
+static SIMD_FORCE_INLINE bool conservativeCulling(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& mrg)
+{
+ if (k0 > mrg && k1 > mrg && k2 > mrg && k3 > mrg)
+ return true;
+ if (k0 < -mrg && k1 < -mrg && k2 < -mrg && k3 < -mrg)
+ return true;
+ return false;
+}
+
+static SIMD_FORCE_INLINE bool bernsteinVFTest(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& mrg, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+ if (conservativeCulling(k0, k1, k2, k3, mrg))
+ return false;
+ return coplanarAndInsideTest(k0, k1, k2, k3, face, node, dt);
+}
+
+static SIMD_FORCE_INLINE void deCasteljau(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& t0, btScalar& k10, btScalar& k20, btScalar& k30, btScalar& k21, btScalar& k12)
+{
+ k10 = k0*(1.0-t0) + k1*t0;
+ btScalar k11 = k1*(1.0-t0) + k2*t0;
+ k12 = k2*(1.0-t0) + k3*t0;
+ k20 = k10*(1.0-t0) + k11*t0;
+ k21 = k11*(1.0-t0) + k12*t0;
+ k30 = k20*(1.0-t0) + k21*t0;
+}
+static SIMD_FORCE_INLINE bool bernsteinVFTest(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg)
+{
+ btScalar k0, k1, k2, k3;
+ getBernsteinCoeff(face, node, dt, k0, k1, k2, k3);
+ if (conservativeCulling(k0, k1, k2, k3, mrg))
+ return false;
+ return true;
+ if (diffSign(k2-2.0*k1+k0, k3-2.0*k2+k1))
+ {
+ btScalar k10, k20, k30, k21, k12;
+ btScalar t0 = (k2-2.0*k1+k0)/(k0-3.0*k1+3.0*k2-k3);
+ deCasteljau(k0, k1, k2, k3, t0, k10, k20, k30, k21, k12);
+ return bernsteinVFTest(k0, k10, k20, k30, mrg, face, node, dt) || bernsteinVFTest(k30, k21, k12, k3, mrg, face, node, dt);
+ }
+ return coplanarAndInsideTest(k0, k1, k2, k3, face, node, dt);
+}
+
+static SIMD_FORCE_INLINE bool continuousCollisionDetection(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg, btVector3& bary)
+{
+ if (hasSeparatingPlane(face, node, dt))
+ return false;
+ btVector3 x21 = face->m_n[1]->m_x - face->m_n[0]->m_x;
+ btVector3 x31 = face->m_n[2]->m_x - face->m_n[0]->m_x;
+ btVector3 x41 = node->m_x - face->m_n[0]->m_x;
+ btVector3 v21 = face->m_n[1]->m_v - face->m_n[0]->m_v;
+ btVector3 v31 = face->m_n[2]->m_v - face->m_n[0]->m_v;
+ btVector3 v41 = node->m_v - face->m_n[0]->m_v;
+ btVector3 a = x21.cross(x31);
+ btVector3 b = x21.cross(v31) + v21.cross(x31);
+ btVector3 c = v21.cross(v31);
+ btVector3 d = x41;
+ btVector3 e = v41;
+ btScalar a0 = a.dot(d);
+ btScalar a1 = a.dot(e) + b.dot(d);
+ btScalar a2 = c.dot(d) + b.dot(e);
+ btScalar a3 = c.dot(e);
+ btScalar eps = SAFE_EPSILON;
+ int num_roots = 0;
+ btScalar roots[3];
+ if (std::abs(a3) < eps)
+ {
+ // cubic term is zero
+ if (std::abs(a2) < eps)
+ {
+ if (std::abs(a1) < eps)
+ {
+ if (std::abs(a0) < eps)
+ {
+ num_roots = 2;
+ roots[0] = 0;
+ roots[1] = dt;
+ }
+ }
+ else
+ {
+ num_roots = 1;
+ roots[0] = -a0/a1;
+ }
+ }
+ else
+ {
+ num_roots = SolveP2(roots, a1/a2, a0/a2);
+ }
+ }
+ else
+ {
+ num_roots = SolveP3(roots, a2/a3, a1/a3, a0/a3);
+ }
+// std::sort(roots, roots+num_roots);
+ if (num_roots > 1)
+ {
+ if (roots[0] > roots[1])
+ btSwap(roots[0], roots[1]);
+ }
+ if (num_roots > 2)
+ {
+ if (roots[0] > roots[2])
+ btSwap(roots[0], roots[2]);
+ if (roots[1] > roots[2])
+ btSwap(roots[1], roots[2]);
+ }
+ for (int r = 0; r < num_roots; ++r)
+ {
+ double root = roots[r];
+ if (root <= 0)
+ continue;
+ if (root > dt + SIMD_EPSILON)
+ return false;
+ btVector3 x1 = face->m_n[0]->m_x + root * face->m_n[0]->m_v;
+ btVector3 x2 = face->m_n[1]->m_x + root * face->m_n[1]->m_v;
+ btVector3 x3 = face->m_n[2]->m_x + root * face->m_n[2]->m_v;
+ btVector3 x4 = node->m_x + root * node->m_v;
+ btVector3 normal = (x2-x1).cross(x3-x1);
+ normal.safeNormalize();
+ if (proximityTest(x1, x2, x3, x4, normal, mrg, bary))
+ return true;
+ }
+ return false;
+}
+static SIMD_FORCE_INLINE bool bernsteinCCD(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg, btVector3& bary)
+{
+ if (!bernsteinVFTest(face, node, dt, mrg))
+ return false;
+ if (!continuousCollisionDetection(face, node, dt, 1e-6, bary))
+ return false;
+ return true;
+}
+
//
// btSymMatrix
//
@@ -298,6 +899,66 @@ static inline btMatrix3x3 Diagonal(btScalar x)
m[2] = btVector3(0, 0, x);
return (m);
}
+
+static inline btMatrix3x3 Diagonal(const btVector3& v)
+{
+ btMatrix3x3 m;
+ m[0] = btVector3(v.getX(), 0, 0);
+ m[1] = btVector3(0, v.getY(), 0);
+ m[2] = btVector3(0, 0, v.getZ());
+ return (m);
+}
+
+static inline btScalar Dot(const btScalar* a,const btScalar* b, int ndof)
+{
+ btScalar result = 0;
+ for (int i = 0; i < ndof; ++i)
+ result += a[i] * b[i];
+ return result;
+}
+
+static inline btMatrix3x3 OuterProduct(const btScalar* v1,const btScalar* v2,const btScalar* v3,
+ const btScalar* u1, const btScalar* u2, const btScalar* u3, int ndof)
+{
+ btMatrix3x3 m;
+ btScalar a11 = Dot(v1,u1,ndof);
+ btScalar a12 = Dot(v1,u2,ndof);
+ btScalar a13 = Dot(v1,u3,ndof);
+
+ btScalar a21 = Dot(v2,u1,ndof);
+ btScalar a22 = Dot(v2,u2,ndof);
+ btScalar a23 = Dot(v2,u3,ndof);
+
+ btScalar a31 = Dot(v3,u1,ndof);
+ btScalar a32 = Dot(v3,u2,ndof);
+ btScalar a33 = Dot(v3,u3,ndof);
+ m[0] = btVector3(a11, a12, a13);
+ m[1] = btVector3(a21, a22, a23);
+ m[2] = btVector3(a31, a32, a33);
+ return (m);
+}
+
+static inline btMatrix3x3 OuterProduct(const btVector3& v1,const btVector3& v2)
+{
+ btMatrix3x3 m;
+ btScalar a11 = v1[0] * v2[0];
+ btScalar a12 = v1[0] * v2[1];
+ btScalar a13 = v1[0] * v2[2];
+
+ btScalar a21 = v1[1] * v2[0];
+ btScalar a22 = v1[1] * v2[1];
+ btScalar a23 = v1[1] * v2[2];
+
+ btScalar a31 = v1[2] * v2[0];
+ btScalar a32 = v1[2] * v2[1];
+ btScalar a33 = v1[2] * v2[2];
+ m[0] = btVector3(a11, a12, a13);
+ m[1] = btVector3(a21, a22, a23);
+ m[2] = btVector3(a31, a32, a33);
+ return (m);
+}
+
+
//
static inline btMatrix3x3 Add(const btMatrix3x3& a,
const btMatrix3x3& b)
@@ -428,6 +1089,77 @@ static inline void ProjectOrigin(const btVector3& a,
}
//
+static inline bool rayIntersectsTriangle(const btVector3& origin, const btVector3& dir, const btVector3& v0, const btVector3& v1, const btVector3& v2, btScalar& t)
+{
+ btScalar a, f, u, v;
+
+ btVector3 e1 = v1 - v0;
+ btVector3 e2 = v2 - v0;
+ btVector3 h = dir.cross(e2);
+ a = e1.dot(h);
+
+ if (a > -0.00001 && a < 0.00001)
+ return (false);
+
+ f = btScalar(1) / a;
+ btVector3 s = origin - v0;
+ u = f * s.dot(h);
+
+ if (u < 0.0 || u > 1.0)
+ return (false);
+
+ btVector3 q = s.cross(e1);
+ v = f * dir.dot(q);
+ if (v < 0.0 || u + v > 1.0)
+ return (false);
+ // at this stage we can compute t to find out where
+ // the intersection point is on the line
+ t = f * e2.dot(q);
+ if (t > 0) // ray intersection
+ return (true);
+ else // this means that there is a line intersection
+ // but not a ray intersection
+ return (false);
+}
+
+static inline bool lineIntersectsTriangle(const btVector3& rayStart, const btVector3& rayEnd, const btVector3& p1, const btVector3& p2, const btVector3& p3, btVector3& sect, btVector3& normal)
+{
+ btVector3 dir = rayEnd - rayStart;
+ btScalar dir_norm = dir.norm();
+ if (dir_norm < SIMD_EPSILON)
+ return false;
+ dir.normalize();
+
+ btScalar t;
+
+ bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t);
+
+ if (ret)
+ {
+ if (t <= dir_norm)
+ {
+ sect = rayStart + dir * t;
+ }
+ else
+ {
+ ret = false;
+ }
+ }
+
+ if (ret)
+ {
+ btVector3 n = (p3-p1).cross(p2-p1);
+ n.safeNormalize();
+ if (n.dot(dir) < 0)
+ normal = n;
+ else
+ normal = -n;
+ }
+ return ret;
+}
+
+
+//
template <typename T>
static inline T BaryEval(const T& a,
const T& b,
@@ -854,10 +1586,62 @@ struct btSoftColliders
psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root, psb->m_cdbvt.m_root, *this);
}
};
+ //
+ // CollideSDF_RS
+ //
+ struct CollideSDF_RS : btDbvt::ICollide
+ {
+ void Process(const btDbvtNode* leaf)
+ {
+ btSoftBody::Node* node = (btSoftBody::Node*)leaf->data;
+ DoNode(*node);
+ }
+ void DoNode(btSoftBody::Node& n) const
+ {
+ const btScalar m = n.m_im > 0 ? dynmargin : stamargin;
+ btSoftBody::RContact c;
+
+ if ((!n.m_battach) &&
+ psb->checkContact(m_colObj1Wrap, n.m_x, m, c.m_cti))
+ {
+ const btScalar ima = n.m_im;
+ const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
+ const btScalar ms = ima + imb;
+ if (ms > 0)
+ {
+ const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
+ static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
+ const btVector3 ra = n.m_x - wtr.getOrigin();
+ const btVector3 va = m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra) * psb->m_sst.sdt : btVector3(0, 0, 0);
+ const btVector3 vb = n.m_x - n.m_q;
+ const btVector3 vr = vb - va;
+ const btScalar dn = btDot(vr, c.m_cti.m_normal);
+ const btVector3 fv = vr - c.m_cti.m_normal * dn;
+ const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
+ c.m_node = &n;
+ c.m_c0 = ImpulseMatrix(psb->m_sst.sdt, ima, imb, iwi, ra);
+ c.m_c1 = ra;
+ c.m_c2 = ima * psb->m_sst.sdt;
+ c.m_c3 = fv.length2() < (dn * fc * dn * fc) ? 0 : 1 - fc;
+ c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
+ psb->m_rcontacts.push_back(c);
+ if (m_rigidBody)
+ m_rigidBody->activate();
+ }
+ }
+ }
+ btSoftBody* psb;
+ const btCollisionObjectWrapper* m_colObj1Wrap;
+ btRigidBody* m_rigidBody;
+ btScalar dynmargin;
+ btScalar stamargin;
+ };
+
//
- // CollideSDF_RS
+ // CollideSDF_RD
//
- struct CollideSDF_RS : btDbvt::ICollide
+ struct CollideSDF_RD : btDbvt::ICollide
{
void Process(const btDbvtNode* leaf)
{
@@ -867,36 +1651,75 @@ struct btSoftColliders
void DoNode(btSoftBody::Node& n) const
{
const btScalar m = n.m_im > 0 ? dynmargin : stamargin;
- btSoftBody::RContact c;
+ btSoftBody::DeformableNodeRigidContact c;
- if ((!n.m_battach) &&
- psb->checkContact(m_colObj1Wrap, n.m_x, m, c.m_cti))
- {
- const btScalar ima = n.m_im;
- const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
- const btScalar ms = ima + imb;
- if (ms > 0)
- {
- const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
- static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
- const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
- const btVector3 ra = n.m_x - wtr.getOrigin();
- const btVector3 va = m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra) * psb->m_sst.sdt : btVector3(0, 0, 0);
- const btVector3 vb = n.m_x - n.m_q;
- const btVector3 vr = vb - va;
- const btScalar dn = btDot(vr, c.m_cti.m_normal);
- const btVector3 fv = vr - c.m_cti.m_normal * dn;
- const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
- c.m_node = &n;
- c.m_c0 = ImpulseMatrix(psb->m_sst.sdt, ima, imb, iwi, ra);
- c.m_c1 = ra;
- c.m_c2 = ima * psb->m_sst.sdt;
- c.m_c3 = fv.length2() < (dn * fc * dn * fc) ? 0 : 1 - fc;
- c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
- psb->m_rcontacts.push_back(c);
- if (m_rigidBody)
- m_rigidBody->activate();
- }
+ if (!n.m_battach)
+ {
+ // check for collision at x_{n+1}^*
+ if (psb->checkDeformableContact(m_colObj1Wrap, n.m_q, m, c.m_cti, /*predict = */ true))
+ {
+ const btScalar ima = n.m_im;
+ // todo: collision between multibody and fixed deformable node will be missed.
+ const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
+ const btScalar ms = ima + imb;
+ if (ms > 0)
+ {
+ // resolve contact at x_n
+ psb->checkDeformableContact(m_colObj1Wrap, n.m_x, m, c.m_cti, /*predict = */ false);
+ btSoftBody::sCti& cti = c.m_cti;
+ c.m_node = &n;
+ const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
+ c.m_c2 = ima;
+ c.m_c3 = fc;
+ c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
+
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
+ static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
+ const btVector3 ra = n.m_x - wtr.getOrigin();
+
+ c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
+ c.m_c1 = ra;
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ btVector3 normal = cti.m_normal;
+ btVector3 t1 = generateUnitOrthogonalVector(normal);
+ btVector3 t2 = btCross(normal, t1);
+ btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+ findJacobian(multibodyLinkCol, jacobianData_normal, c.m_node->m_x, normal);
+ findJacobian(multibodyLinkCol, jacobianData_t1, c.m_node->m_x, t1);
+ findJacobian(multibodyLinkCol, jacobianData_t2, c.m_node->m_x, t2);
+
+ btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+ btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+ btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+ btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+ btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+ t1.getX(), t1.getY(), t1.getZ(),
+ t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ btMatrix3x3 local_impulse_matrix = (Diagonal(n.m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+ c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+ c.jacobianData_normal = jacobianData_normal;
+ c.jacobianData_t1 = jacobianData_t1;
+ c.jacobianData_t2 = jacobianData_t2;
+ c.t1 = t1;
+ c.t2 = t2;
+ }
+ }
+ psb->m_nodeRigidContacts.push_back(c);
+ }
+ }
}
}
btSoftBody* psb;
@@ -905,6 +1728,112 @@ struct btSoftColliders
btScalar dynmargin;
btScalar stamargin;
};
+
+ //
+ // CollideSDF_RDF
+ //
+ struct CollideSDF_RDF : btDbvt::ICollide
+ {
+ void Process(const btDbvtNode* leaf)
+ {
+ btSoftBody::Face* face = (btSoftBody::Face*)leaf->data;
+ DoNode(*face);
+ }
+ void DoNode(btSoftBody::Face& f) const
+ {
+ btSoftBody::Node* n0 = f.m_n[0];
+ btSoftBody::Node* n1 = f.m_n[1];
+ btSoftBody::Node* n2 = f.m_n[2];
+ const btScalar m = (n0->m_im > 0 && n1->m_im > 0 && n2->m_im > 0 )? dynmargin : stamargin;
+ btSoftBody::DeformableFaceRigidContact c;
+ btVector3 contact_point;
+ btVector3 bary;
+ if (psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, true))
+ {
+ f.m_pcontact[3] = 1;
+ btScalar ima = n0->m_im + n1->m_im + n2->m_im;
+ const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
+ // todo: collision between multibody and fixed deformable face will be missed.
+ const btScalar ms = ima + imb;
+ if (ms > 0)
+ {
+ // resolve contact at x_n
+// psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, /*predict = */ false);
+ btSoftBody::sCti& cti = c.m_cti;
+ c.m_contactPoint = contact_point;
+ c.m_bary = bary;
+ // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
+ c.m_weights = btScalar(2)/(btScalar(1) + bary.length2()) * bary;
+ c.m_face = &f;
+ // friction is handled by the nodes to prevent sticking
+// const btScalar fc = 0;
+ const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
+
+ // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
+ ima = bary.getX()*c.m_weights.getX() * n0->m_im + bary.getY()*c.m_weights.getY() * n1->m_im + bary.getZ()*c.m_weights.getZ() * n2->m_im;
+ c.m_c2 = ima;
+ c.m_c3 = fc;
+ c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
+ if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
+ static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
+ const btVector3 ra = contact_point - wtr.getOrigin();
+
+ // we do not scale the impulse matrix by dt
+ c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
+ c.m_c1 = ra;
+ }
+ else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+ {
+ btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+ if (multibodyLinkCol)
+ {
+ btVector3 normal = cti.m_normal;
+ btVector3 t1 = generateUnitOrthogonalVector(normal);
+ btVector3 t2 = btCross(normal, t1);
+ btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+ findJacobian(multibodyLinkCol, jacobianData_normal, contact_point, normal);
+ findJacobian(multibodyLinkCol, jacobianData_t1, contact_point, t1);
+ findJacobian(multibodyLinkCol, jacobianData_t2, contact_point, t2);
+
+ btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+ btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+ btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+ btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+ btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+ btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+ t1.getX(), t1.getY(), t1.getZ(),
+ t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
+ const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+ btMatrix3x3 local_impulse_matrix = (Diagonal(ima) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+ c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+ c.jacobianData_normal = jacobianData_normal;
+ c.jacobianData_t1 = jacobianData_t1;
+ c.jacobianData_t2 = jacobianData_t2;
+ c.t1 = t1;
+ c.t2 = t2;
+ }
+ }
+ psb->m_faceRigidContacts.push_back(c);
+ }
+ }
+ else
+ {
+ f.m_pcontact[3] = 0;
+ }
+ }
+ btSoftBody* psb;
+ const btCollisionObjectWrapper* m_colObj1Wrap;
+ btRigidBody* m_rigidBody;
+ btScalar dynmargin;
+ btScalar stamargin;
+ };
+
//
// CollideVF_SS
//
@@ -915,6 +1844,12 @@ struct btSoftColliders
{
btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
+ for (int i = 0; i < 3; ++i)
+ {
+ if (face->m_n[i] == node)
+ continue;
+ }
+
btVector3 o = node->m_x;
btVector3 p;
btScalar d = SIMD_INFINITY;
@@ -944,7 +1879,7 @@ struct btSoftColliders
c.m_node = node;
c.m_face = face;
c.m_weights = w;
- c.m_friction = btMax(psb[0]->m_cfg.kDF, psb[1]->m_cfg.kDF);
+ c.m_friction = btMax (psb[0]->m_cfg.kDF, psb[1]->m_cfg.kDF);
c.m_cfm[0] = ma / ms * psb[0]->m_cfg.kSHR;
c.m_cfm[1] = mb / ms * psb[1]->m_cfg.kSHR;
psb[0]->m_scontacts.push_back(c);
@@ -954,6 +1889,206 @@ struct btSoftColliders
btSoftBody* psb[2];
btScalar mrg;
};
-};
+
+
+ //
+ // CollideVF_DD
+ //
+ struct CollideVF_DD : btDbvt::ICollide
+ {
+ void Process(const btDbvtNode* lnode,
+ const btDbvtNode* lface)
+ {
+ btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
+ btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
+ btVector3 bary;
+ if (proximityTest(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, node->m_x, face->m_normal, mrg, bary))
+ {
+ const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
+ const btVector3 w = bary;
+ const btScalar ma = node->m_im;
+ btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
+ if ((n[0]->m_im <= 0) ||
+ (n[1]->m_im <= 0) ||
+ (n[2]->m_im <= 0))
+ {
+ mb = 0;
+ }
+ const btScalar ms = ma + mb;
+ if (ms > 0)
+ {
+ btSoftBody::DeformableFaceNodeContact c;
+ c.m_normal = face->m_normal;
+ if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+ c.m_normal = -face->m_normal;
+ c.m_margin = mrg;
+ c.m_node = node;
+ c.m_face = face;
+ c.m_bary = w;
+ c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+ psb[0]->m_faceNodeContacts.push_back(c);
+ }
+ }
+ }
+ btSoftBody* psb[2];
+ btScalar mrg;
+ bool useFaceNormal;
+ };
+
+ //
+ // CollideFF_DD
+ //
+ struct CollideFF_DD : btDbvt::ICollide
+ {
+ void Process(const btDbvntNode* lface1,
+ const btDbvntNode* lface2)
+ {
+ btSoftBody::Face* f1 = (btSoftBody::Face*)lface1->data;
+ btSoftBody::Face* f2 = (btSoftBody::Face*)lface2->data;
+ if (f1 != f2)
+ {
+ Repel(f1, f2);
+ Repel(f2, f1);
+ }
+ }
+ void Repel(btSoftBody::Face* f1, btSoftBody::Face* f2)
+ {
+ //#define REPEL_NEIGHBOR 1
+#ifndef REPEL_NEIGHBOR
+ for (int node_id = 0; node_id < 3; ++node_id)
+ {
+ btSoftBody::Node* node = f1->m_n[node_id];
+ for (int i = 0; i < 3; ++i)
+ {
+ if (f2->m_n[i] == node)
+ return;
+ }
+ }
+#endif
+ bool skip = false;
+ for (int node_id = 0; node_id < 3; ++node_id)
+ {
+ btSoftBody::Node* node = f1->m_n[node_id];
+#ifdef REPEL_NEIGHBOR
+ for (int i = 0; i < 3; ++i)
+ {
+ if (f2->m_n[i] == node)
+ {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ {
+ skip = false;
+ continue;
+ }
+#endif
+ btSoftBody::Face* face = f2;
+ btVector3 bary;
+ if (!proximityTest(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, node->m_x, face->m_normal, mrg, bary))
+ continue;
+ btSoftBody::DeformableFaceNodeContact c;
+ c.m_normal = face->m_normal;
+ if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+ c.m_normal = -face->m_normal;
+ c.m_margin = mrg;
+ c.m_node = node;
+ c.m_face = face;
+ c.m_bary = bary;
+ c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+ psb[0]->m_faceNodeContacts.push_back(c);
+ }
+ }
+ btSoftBody* psb[2];
+ btScalar mrg;
+ bool useFaceNormal;
+ };
+ struct CollideCCD : btDbvt::ICollide
+ {
+ void Process(const btDbvtNode* lnode,
+ const btDbvtNode* lface)
+ {
+ btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
+ btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
+ btVector3 bary;
+ if (bernsteinCCD(face, node, dt, SAFE_EPSILON, bary))
+ {
+ btSoftBody::DeformableFaceNodeContact c;
+ c.m_normal = face->m_normal;
+ if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+ c.m_normal = -face->m_normal;
+ c.m_node = node;
+ c.m_face = face;
+ c.m_bary = bary;
+ c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+ psb[0]->m_faceNodeContacts.push_back(c);
+ }
+ }
+ void Process(const btDbvntNode* lface1,
+ const btDbvntNode* lface2)
+ {
+ btSoftBody::Face* f1 = (btSoftBody::Face*)lface1->data;
+ btSoftBody::Face* f2 = (btSoftBody::Face*)lface2->data;
+ if (f1 != f2)
+ {
+ Repel(f1, f2);
+ Repel(f2, f1);
+ }
+ }
+ void Repel(btSoftBody::Face* f1, btSoftBody::Face* f2)
+ {
+ //#define REPEL_NEIGHBOR 1
+#ifndef REPEL_NEIGHBOR
+ for (int node_id = 0; node_id < 3; ++node_id)
+ {
+ btSoftBody::Node* node = f1->m_n[node_id];
+ for (int i = 0; i < 3; ++i)
+ {
+ if (f2->m_n[i] == node)
+ return;
+ }
+ }
+#endif
+ bool skip = false;
+ for (int node_id = 0; node_id < 3; ++node_id)
+ {
+ btSoftBody::Node* node = f1->m_n[node_id];
+#ifdef REPEL_NEIGHBOR
+ for (int i = 0; i < 3; ++i)
+ {
+ if (f2->m_n[i] == node)
+ {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ {
+ skip = false;
+ continue;
+ }
+#endif
+ btSoftBody::Face* face = f2;
+ btVector3 bary;
+ if (bernsteinCCD(face, node, dt, SAFE_EPSILON, bary))
+ {
+ btSoftBody::DeformableFaceNodeContact c;
+ c.m_normal = face->m_normal;
+ if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+ c.m_normal = -face->m_normal;
+ c.m_node = node;
+ c.m_face = face;
+ c.m_bary = bary;
+ c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+ psb[0]->m_faceNodeContacts.push_back(c);
+ }
+ }
+ }
+ btSoftBody* psb[2];
+ btScalar dt, mrg;
+ bool useFaceNormal;
+ };
+};
#endif //_BT_SOFT_BODY_INTERNALS_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h b/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
index dcf5082650..c4ac4141aa 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
+++ b/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
@@ -35,7 +35,8 @@ public:
CL_SOLVER,
CL_SIMD_SOLVER,
DX_SOLVER,
- DX_SIMD_SOLVER
+ DX_SIMD_SOLVER,
+ DEFORMABLE_SOLVER
};
protected:
@@ -71,10 +72,10 @@ public:
virtual void copyBackToSoftBodies(bool bMove = true) = 0;
/** Predict motion of soft bodies into next timestep */
- virtual void predictMotion(float solverdt) = 0;
+ virtual void predictMotion(btScalar solverdt) = 0;
/** Solve constraints for a set of soft bodies */
- virtual void solveConstraints(float solverdt) = 0;
+ virtual void solveConstraints(btScalar solverdt) = 0;
/** Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes */
virtual void updateSoftBodies() = 0;
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
index 56d8083f22..5b65216e4b 100644
--- a/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
+++ b/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
@@ -48,9 +48,10 @@ btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm()
}
#include <stdio.h>
-
+#include "LinearMath/btQuickprof.h"
void btSoftRigidCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
+ BT_PROFILE("btSoftRigidCollisionAlgorithm::processCollision");
(void)dispatchInfo;
(void)resultOut;
//printf("btSoftRigidCollisionAlgorithm\n");
diff --git a/thirdparty/bullet/BulletSoftBody/btSparseSDF.h b/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
index a52b2cb1cc..eb290a1dbd 100644
--- a/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
+++ b/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
@@ -20,27 +20,38 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
-// Modified Paul Hsieh hash
-template <const int DWORDLEN>
-unsigned int HsiehHash(const void* pdata)
-{
- const unsigned short* data = (const unsigned short*)pdata;
- unsigned hash = DWORDLEN << 2, tmp;
- for (int i = 0; i < DWORDLEN; ++i)
- {
- hash += data[0];
- tmp = (data[1] << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- data += 2;
- hash += hash >> 11;
- }
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 4;
- hash += hash >> 17;
- hash ^= hash << 25;
- hash += hash >> 6;
- return (hash);
+// Fast Hash
+
+#if !defined (get16bits)
+#define get16bits(d) ((((unsigned int)(((const unsigned char *)(d))[1])) << 8)\
++(unsigned int)(((const unsigned char *)(d))[0]) )
+#endif
+//
+// super hash function by Paul Hsieh
+//
+inline unsigned int HsiehHash (const char * data, int len) {
+ unsigned int hash = len, tmp;
+ len>>=2;
+
+ /* Main loop */
+ for (;len > 0; len--) {
+ hash += get16bits (data);
+ tmp = (get16bits (data+2) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ data += 2*sizeof (unsigned short);
+ hash += hash >> 11;
+ }
+
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
}
template <const int CELLSIZE>
@@ -70,12 +81,17 @@ struct btSparseSdf
btAlignedObjectArray<Cell*> cells;
btScalar voxelsz;
+ btScalar m_defaultVoxelsz;
int puid;
int ncells;
int m_clampCells;
int nprobes;
int nqueries;
+ ~btSparseSdf()
+ {
+ Reset();
+ }
//
// Methods
//
@@ -87,9 +103,16 @@ struct btSparseSdf
//if this limit is reached, the SDF is reset (at the cost of some performance during the reset)
m_clampCells = clampCells;
cells.resize(hashsize, 0);
+ m_defaultVoxelsz = 0.25;
Reset();
}
//
+
+ void setDefaultVoxelsz(btScalar sz)
+ {
+ m_defaultVoxelsz = sz;
+ }
+
void Reset()
{
for (int i = 0, ni = cells.size(); i < ni; ++i)
@@ -103,7 +126,7 @@ struct btSparseSdf
pc = pn;
}
}
- voxelsz = 0.25;
+ voxelsz = m_defaultVoxelsz;
puid = 0;
ncells = 0;
nprobes = 1;
@@ -197,6 +220,9 @@ struct btSparseSdf
}
else
{
+ // printf("c->hash/c[0][1][2]=%d,%d,%d,%d\n", c->hash, c->c[0], c->c[1],c->c[2]);
+ //printf("h,ixb,iyb,izb=%d,%d,%d,%d\n", h,ix.b, iy.b, iz.b);
+
c = c->next;
}
}
@@ -248,7 +274,7 @@ struct btSparseSdf
Lerp(gy[2], gy[3], ix.f), iz.f));
normal.setZ(Lerp(Lerp(gz[0], gz[1], ix.f),
Lerp(gz[2], gz[3], ix.f), iy.f));
- normal = normal.normalized();
+ normal.safeNormalize();
#else
normal = btVector3(d[1] - d[0], d[3] - d[0], d[4] - d[0]).normalized();
#endif
@@ -322,19 +348,22 @@ struct btSparseSdf
{
struct btS
{
- int x, y, z;
+ int x, y, z, w;
void* p;
};
btS myset;
+ //memset may be needed in case of additional (uninitialized) padding!
+ //memset(&myset, 0, sizeof(btS));
myset.x = x;
myset.y = y;
myset.z = z;
+ myset.w = 0;
myset.p = (void*)shape;
- const void* ptr = &myset;
+ const char* ptr = (const char*)&myset;
- unsigned int result = HsiehHash<sizeof(btS) / 4>(ptr);
+ unsigned int result = HsiehHash(ptr, sizeof(btS) );
return result;
}
diff --git a/thirdparty/bullet/BulletSoftBody/poly34.cpp b/thirdparty/bullet/BulletSoftBody/poly34.cpp
new file mode 100644
index 0000000000..819d0c79f7
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/poly34.cpp
@@ -0,0 +1,419 @@
+// poly34.cpp : solution of cubic and quartic equation
+// (c) Khashin S.I. http://math.ivanovo.ac.ru/dalgebra/Khashin/index.html
+// khash2 (at) gmail.com
+// Thanks to Alexandr Rakhmanin <rakhmanin (at) gmail.com>
+// public domain
+//
+#include <math.h>
+
+#include "poly34.h" // solution of cubic and quartic equation
+#define TwoPi 6.28318530717958648
+const btScalar eps = SIMD_EPSILON;
+
+//=============================================================================
+// _root3, root3 from http://prografix.narod.ru
+//=============================================================================
+static SIMD_FORCE_INLINE btScalar _root3(btScalar x)
+{
+ btScalar s = 1.;
+ while (x < 1.) {
+ x *= 8.;
+ s *= 0.5;
+ }
+ while (x > 8.) {
+ x *= 0.125;
+ s *= 2.;
+ }
+ btScalar r = 1.5;
+ r -= 1. / 3. * (r - x / (r * r));
+ r -= 1. / 3. * (r - x / (r * r));
+ r -= 1. / 3. * (r - x / (r * r));
+ r -= 1. / 3. * (r - x / (r * r));
+ r -= 1. / 3. * (r - x / (r * r));
+ r -= 1. / 3. * (r - x / (r * r));
+ return r * s;
+}
+
+btScalar SIMD_FORCE_INLINE root3(btScalar x)
+{
+ if (x > 0)
+ return _root3(x);
+ else if (x < 0)
+ return -_root3(-x);
+ else
+ return 0.;
+}
+
+// x - array of size 2
+// return 2: 2 real roots x[0], x[1]
+// return 0: pair of complex roots: x[0]i*x[1]
+int SolveP2(btScalar* x, btScalar a, btScalar b)
+{ // solve equation x^2 + a*x + b = 0
+ btScalar D = 0.25 * a * a - b;
+ if (D >= 0) {
+ D = sqrt(D);
+ x[0] = -0.5 * a + D;
+ x[1] = -0.5 * a - D;
+ return 2;
+ }
+ x[0] = -0.5 * a;
+ x[1] = sqrt(-D);
+ return 0;
+}
+//---------------------------------------------------------------------------
+// x - array of size 3
+// In case 3 real roots: => x[0], x[1], x[2], return 3
+// 2 real roots: x[0], x[1], return 2
+// 1 real root : x[0], x[1] i*x[2], return 1
+int SolveP3(btScalar* x, btScalar a, btScalar b, btScalar c)
+{ // solve cubic equation x^3 + a*x^2 + b*x + c = 0
+ btScalar a2 = a * a;
+ btScalar q = (a2 - 3 * b) / 9;
+ if (q < 0)
+ q = eps;
+ btScalar r = (a * (2 * a2 - 9 * b) + 27 * c) / 54;
+ // equation x^3 + q*x + r = 0
+ btScalar r2 = r * r;
+ btScalar q3 = q * q * q;
+ btScalar A, B;
+ if (r2 <= (q3 + eps)) { //<<-- FIXED!
+ btScalar t = r / sqrt(q3);
+ if (t < -1)
+ t = -1;
+ if (t > 1)
+ t = 1;
+ t = acos(t);
+ a /= 3;
+ q = -2 * sqrt(q);
+ x[0] = q * cos(t / 3) - a;
+ x[1] = q * cos((t + TwoPi) / 3) - a;
+ x[2] = q * cos((t - TwoPi) / 3) - a;
+ return (3);
+ }
+ else {
+ //A =-pow(fabs(r)+sqrt(r2-q3),1./3);
+ A = -root3(fabs(r) + sqrt(r2 - q3));
+ if (r < 0)
+ A = -A;
+ B = (A == 0 ? 0 : q / A);
+
+ a /= 3;
+ x[0] = (A + B) - a;
+ x[1] = -0.5 * (A + B) - a;
+ x[2] = 0.5 * sqrt(3.) * (A - B);
+ if (fabs(x[2]) < eps) {
+ x[2] = x[1];
+ return (2);
+ }
+ return (1);
+ }
+} // SolveP3(btScalar *x,btScalar a,btScalar b,btScalar c) {
+//---------------------------------------------------------------------------
+// a>=0!
+void CSqrt(btScalar x, btScalar y, btScalar& a, btScalar& b) // returns: a+i*s = sqrt(x+i*y)
+{
+ btScalar r = sqrt(x * x + y * y);
+ if (y == 0) {
+ r = sqrt(r);
+ if (x >= 0) {
+ a = r;
+ b = 0;
+ }
+ else {
+ a = 0;
+ b = r;
+ }
+ }
+ else { // y != 0
+ a = sqrt(0.5 * (x + r));
+ b = 0.5 * y / a;
+ }
+}
+//---------------------------------------------------------------------------
+int SolveP4Bi(btScalar* x, btScalar b, btScalar d) // solve equation x^4 + b*x^2 + d = 0
+{
+ btScalar D = b * b - 4 * d;
+ if (D >= 0) {
+ btScalar sD = sqrt(D);
+ btScalar x1 = (-b + sD) / 2;
+ btScalar x2 = (-b - sD) / 2; // x2 <= x1
+ if (x2 >= 0) // 0 <= x2 <= x1, 4 real roots
+ {
+ btScalar sx1 = sqrt(x1);
+ btScalar sx2 = sqrt(x2);
+ x[0] = -sx1;
+ x[1] = sx1;
+ x[2] = -sx2;
+ x[3] = sx2;
+ return 4;
+ }
+ if (x1 < 0) // x2 <= x1 < 0, two pair of imaginary roots
+ {
+ btScalar sx1 = sqrt(-x1);
+ btScalar sx2 = sqrt(-x2);
+ x[0] = 0;
+ x[1] = sx1;
+ x[2] = 0;
+ x[3] = sx2;
+ return 0;
+ }
+ // now x2 < 0 <= x1 , two real roots and one pair of imginary root
+ btScalar sx1 = sqrt(x1);
+ btScalar sx2 = sqrt(-x2);
+ x[0] = -sx1;
+ x[1] = sx1;
+ x[2] = 0;
+ x[3] = sx2;
+ return 2;
+ }
+ else { // if( D < 0 ), two pair of compex roots
+ btScalar sD2 = 0.5 * sqrt(-D);
+ CSqrt(-0.5 * b, sD2, x[0], x[1]);
+ CSqrt(-0.5 * b, -sD2, x[2], x[3]);
+ return 0;
+ } // if( D>=0 )
+} // SolveP4Bi(btScalar *x, btScalar b, btScalar d) // solve equation x^4 + b*x^2 d
+//---------------------------------------------------------------------------
+#define SWAP(a, b) \
+{ \
+t = b; \
+b = a; \
+a = t; \
+}
+static void dblSort3(btScalar& a, btScalar& b, btScalar& c) // make: a <= b <= c
+{
+ btScalar t;
+ if (a > b)
+ SWAP(a, b); // now a<=b
+ if (c < b) {
+ SWAP(b, c); // now a<=b, b<=c
+ if (a > b)
+ SWAP(a, b); // now a<=b
+ }
+}
+//---------------------------------------------------------------------------
+int SolveP4De(btScalar* x, btScalar b, btScalar c, btScalar d) // solve equation x^4 + b*x^2 + c*x + d
+{
+ //if( c==0 ) return SolveP4Bi(x,b,d); // After that, c!=0
+ if (fabs(c) < 1e-14 * (fabs(b) + fabs(d)))
+ return SolveP4Bi(x, b, d); // After that, c!=0
+
+ int res3 = SolveP3(x, 2 * b, b * b - 4 * d, -c * c); // solve resolvent
+ // by Viet theorem: x1*x2*x3=-c*c not equals to 0, so x1!=0, x2!=0, x3!=0
+ if (res3 > 1) // 3 real roots,
+ {
+ dblSort3(x[0], x[1], x[2]); // sort roots to x[0] <= x[1] <= x[2]
+ // Note: x[0]*x[1]*x[2]= c*c > 0
+ if (x[0] > 0) // all roots are positive
+ {
+ btScalar sz1 = sqrt(x[0]);
+ btScalar sz2 = sqrt(x[1]);
+ btScalar sz3 = sqrt(x[2]);
+ // Note: sz1*sz2*sz3= -c (and not equal to 0)
+ if (c > 0) {
+ x[0] = (-sz1 - sz2 - sz3) / 2;
+ x[1] = (-sz1 + sz2 + sz3) / 2;
+ x[2] = (+sz1 - sz2 + sz3) / 2;
+ x[3] = (+sz1 + sz2 - sz3) / 2;
+ return 4;
+ }
+ // now: c<0
+ x[0] = (-sz1 - sz2 + sz3) / 2;
+ x[1] = (-sz1 + sz2 - sz3) / 2;
+ x[2] = (+sz1 - sz2 - sz3) / 2;
+ x[3] = (+sz1 + sz2 + sz3) / 2;
+ return 4;
+ } // if( x[0] > 0) // all roots are positive
+ // now x[0] <= x[1] < 0, x[2] > 0
+ // two pair of comlex roots
+ btScalar sz1 = sqrt(-x[0]);
+ btScalar sz2 = sqrt(-x[1]);
+ btScalar sz3 = sqrt(x[2]);
+
+ if (c > 0) // sign = -1
+ {
+ x[0] = -sz3 / 2;
+ x[1] = (sz1 - sz2) / 2; // x[0]i*x[1]
+ x[2] = sz3 / 2;
+ x[3] = (-sz1 - sz2) / 2; // x[2]i*x[3]
+ return 0;
+ }
+ // now: c<0 , sign = +1
+ x[0] = sz3 / 2;
+ x[1] = (-sz1 + sz2) / 2;
+ x[2] = -sz3 / 2;
+ x[3] = (sz1 + sz2) / 2;
+ return 0;
+ } // if( res3>1 ) // 3 real roots,
+ // now resoventa have 1 real and pair of compex roots
+ // x[0] - real root, and x[0]>0,
+ // x[1]i*x[2] - complex roots,
+ // x[0] must be >=0. But one times x[0]=~ 1e-17, so:
+ if (x[0] < 0)
+ x[0] = 0;
+ btScalar sz1 = sqrt(x[0]);
+ btScalar szr, szi;
+ CSqrt(x[1], x[2], szr, szi); // (szr+i*szi)^2 = x[1]+i*x[2]
+ if (c > 0) // sign = -1
+ {
+ x[0] = -sz1 / 2 - szr; // 1st real root
+ x[1] = -sz1 / 2 + szr; // 2nd real root
+ x[2] = sz1 / 2;
+ x[3] = szi;
+ return 2;
+ }
+ // now: c<0 , sign = +1
+ x[0] = sz1 / 2 - szr; // 1st real root
+ x[1] = sz1 / 2 + szr; // 2nd real root
+ x[2] = -sz1 / 2;
+ x[3] = szi;
+ return 2;
+} // SolveP4De(btScalar *x, btScalar b, btScalar c, btScalar d) // solve equation x^4 + b*x^2 + c*x + d
+//-----------------------------------------------------------------------------
+btScalar N4Step(btScalar x, btScalar a, btScalar b, btScalar c, btScalar d) // one Newton step for x^4 + a*x^3 + b*x^2 + c*x + d
+{
+ btScalar fxs = ((4 * x + 3 * a) * x + 2 * b) * x + c; // f'(x)
+ if (fxs == 0)
+ return x; //return 1e99; <<-- FIXED!
+ btScalar fx = (((x + a) * x + b) * x + c) * x + d; // f(x)
+ return x - fx / fxs;
+}
+//-----------------------------------------------------------------------------
+// x - array of size 4
+// return 4: 4 real roots x[0], x[1], x[2], x[3], possible multiple roots
+// return 2: 2 real roots x[0], x[1] and complex x[2]i*x[3],
+// return 0: two pair of complex roots: x[0]i*x[1], x[2]i*x[3],
+int SolveP4(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d)
+{ // solve equation x^4 + a*x^3 + b*x^2 + c*x + d by Dekart-Euler method
+ // move to a=0:
+ btScalar d1 = d + 0.25 * a * (0.25 * b * a - 3. / 64 * a * a * a - c);
+ btScalar c1 = c + 0.5 * a * (0.25 * a * a - b);
+ btScalar b1 = b - 0.375 * a * a;
+ int res = SolveP4De(x, b1, c1, d1);
+ if (res == 4) {
+ x[0] -= a / 4;
+ x[1] -= a / 4;
+ x[2] -= a / 4;
+ x[3] -= a / 4;
+ }
+ else if (res == 2) {
+ x[0] -= a / 4;
+ x[1] -= a / 4;
+ x[2] -= a / 4;
+ }
+ else {
+ x[0] -= a / 4;
+ x[2] -= a / 4;
+ }
+ // one Newton step for each real root:
+ if (res > 0) {
+ x[0] = N4Step(x[0], a, b, c, d);
+ x[1] = N4Step(x[1], a, b, c, d);
+ }
+ if (res > 2) {
+ x[2] = N4Step(x[2], a, b, c, d);
+ x[3] = N4Step(x[3], a, b, c, d);
+ }
+ return res;
+}
+//-----------------------------------------------------------------------------
+#define F5(t) (((((t + a) * t + b) * t + c) * t + d) * t + e)
+//-----------------------------------------------------------------------------
+btScalar SolveP5_1(btScalar a, btScalar b, btScalar c, btScalar d, btScalar e) // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+{
+ int cnt;
+ if (fabs(e) < eps)
+ return 0;
+
+ btScalar brd = fabs(a); // brd - border of real roots
+ if (fabs(b) > brd)
+ brd = fabs(b);
+ if (fabs(c) > brd)
+ brd = fabs(c);
+ if (fabs(d) > brd)
+ brd = fabs(d);
+ if (fabs(e) > brd)
+ brd = fabs(e);
+ brd++; // brd - border of real roots
+
+ btScalar x0, f0; // less than root
+ btScalar x1, f1; // greater than root
+ btScalar x2, f2, f2s; // next values, f(x2), f'(x2)
+ btScalar dx = 0;
+
+ if (e < 0) {
+ x0 = 0;
+ x1 = brd;
+ f0 = e;
+ f1 = F5(x1);
+ x2 = 0.01 * brd;
+ } // positive root
+ else {
+ x0 = -brd;
+ x1 = 0;
+ f0 = F5(x0);
+ f1 = e;
+ x2 = -0.01 * brd;
+ } // negative root
+
+ if (fabs(f0) < eps)
+ return x0;
+ if (fabs(f1) < eps)
+ return x1;
+
+ // now x0<x1, f(x0)<0, f(x1)>0
+ // Firstly 10 bisections
+ for (cnt = 0; cnt < 10; cnt++) {
+ x2 = (x0 + x1) / 2; // next point
+ //x2 = x0 - f0*(x1 - x0) / (f1 - f0); // next point
+ f2 = F5(x2); // f(x2)
+ if (fabs(f2) < eps)
+ return x2;
+ if (f2 > 0) {
+ x1 = x2;
+ f1 = f2;
+ }
+ else {
+ x0 = x2;
+ f0 = f2;
+ }
+ }
+
+ // At each step:
+ // x0<x1, f(x0)<0, f(x1)>0.
+ // x2 - next value
+ // we hope that x0 < x2 < x1, but not necessarily
+ do {
+ if (cnt++ > 50)
+ break;
+ if (x2 <= x0 || x2 >= x1)
+ x2 = (x0 + x1) / 2; // now x0 < x2 < x1
+ f2 = F5(x2); // f(x2)
+ if (fabs(f2) < eps)
+ return x2;
+ if (f2 > 0) {
+ x1 = x2;
+ f1 = f2;
+ }
+ else {
+ x0 = x2;
+ f0 = f2;
+ }
+ f2s = (((5 * x2 + 4 * a) * x2 + 3 * b) * x2 + 2 * c) * x2 + d; // f'(x2)
+ if (fabs(f2s) < eps) {
+ x2 = 1e99;
+ continue;
+ }
+ dx = f2 / f2s;
+ x2 -= dx;
+ } while (fabs(dx) > eps);
+ return x2;
+} // SolveP5_1(btScalar a,btScalar b,btScalar c,btScalar d,btScalar e) // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+//-----------------------------------------------------------------------------
+int SolveP5(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d, btScalar e) // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+{
+ btScalar r = x[0] = SolveP5_1(a, b, c, d, e);
+ btScalar a1 = a + r, b1 = b + r * a1, c1 = c + r * b1, d1 = d + r * c1;
+ return 1 + SolveP4(x + 1, a1, b1, c1, d1);
+} // SolveP5(btScalar *x,btScalar a,btScalar b,btScalar c,btScalar d,btScalar e) // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+//-----------------------------------------------------------------------------
diff --git a/thirdparty/bullet/BulletSoftBody/poly34.h b/thirdparty/bullet/BulletSoftBody/poly34.h
new file mode 100644
index 0000000000..32ad5d7da5
--- /dev/null
+++ b/thirdparty/bullet/BulletSoftBody/poly34.h
@@ -0,0 +1,38 @@
+// poly34.h : solution of cubic and quartic equation
+// (c) Khashin S.I. http://math.ivanovo.ac.ru/dalgebra/Khashin/index.html
+// khash2 (at) gmail.com
+
+#ifndef POLY_34
+#define POLY_34
+#include "LinearMath/btScalar.h"
+// x - array of size 2
+// return 2: 2 real roots x[0], x[1]
+// return 0: pair of complex roots: x[0]i*x[1]
+int SolveP2(btScalar* x, btScalar a, btScalar b); // solve equation x^2 + a*x + b = 0
+
+// x - array of size 3
+// return 3: 3 real roots x[0], x[1], x[2]
+// return 1: 1 real root x[0] and pair of complex roots: x[1]i*x[2]
+int SolveP3(btScalar* x, btScalar a, btScalar b, btScalar c); // solve cubic equation x^3 + a*x^2 + b*x + c = 0
+
+// x - array of size 4
+// return 4: 4 real roots x[0], x[1], x[2], x[3], possible multiple roots
+// return 2: 2 real roots x[0], x[1] and complex x[2]i*x[3],
+// return 0: two pair of complex roots: x[0]i*x[1], x[2]i*x[3],
+int SolveP4(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d); // solve equation x^4 + a*x^3 + b*x^2 + c*x + d = 0 by Dekart-Euler method
+
+// x - array of size 5
+// return 5: 5 real roots x[0], x[1], x[2], x[3], x[4], possible multiple roots
+// return 3: 3 real roots x[0], x[1], x[2] and complex x[3]i*x[4],
+// return 1: 1 real root x[0] and two pair of complex roots: x[1]i*x[2], x[3]i*x[4],
+int SolveP5(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d, btScalar e); // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+
+//-----------------------------------------------------------------------------
+// And some additional functions for internal use.
+// Your may remove this definitions from here
+int SolveP4Bi(btScalar* x, btScalar b, btScalar d); // solve equation x^4 + b*x^2 + d = 0
+int SolveP4De(btScalar* x, btScalar b, btScalar c, btScalar d); // solve equation x^4 + b*x^2 + c*x + d = 0
+void CSqrt(btScalar x, btScalar y, btScalar& a, btScalar& b); // returns as a+i*s, sqrt(x+i*y)
+btScalar N4Step(btScalar x, btScalar a, btScalar b, btScalar c, btScalar d); // one Newton step for x^4 + a*x^3 + b*x^2 + c*x + d
+btScalar SolveP5_1(btScalar a, btScalar b, btScalar c, btScalar d, btScalar e); // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+#endif
diff --git a/thirdparty/bullet/LinearMath/btImplicitQRSVD.h b/thirdparty/bullet/LinearMath/btImplicitQRSVD.h
new file mode 100644
index 0000000000..aaedc964f6
--- /dev/null
+++ b/thirdparty/bullet/LinearMath/btImplicitQRSVD.h
@@ -0,0 +1,916 @@
+/**
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Copyright (c) 2016 Theodore Gast, Chuyuan Fu, Chenfanfu Jiang, Joseph Teran
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is furnished to do
+ so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ If the code is used in an article, the following paper shall be cited:
+ @techreport{qrsvd:2016,
+ title={Implicit-shifted Symmetric QR Singular Value Decomposition of 3x3 Matrices},
+ author={Gast, Theodore and Fu, Chuyuan and Jiang, Chenfanfu and Teran, Joseph},
+ year={2016},
+ institution={University of California Los Angeles}
+ }
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+**/
+
+#ifndef btImplicitQRSVD_h
+#define btImplicitQRSVD_h
+#include <limits>
+#include "btMatrix3x3.h"
+class btMatrix2x2
+{
+public:
+ btScalar m_00, m_01, m_10, m_11;
+ btMatrix2x2(): m_00(0), m_10(0), m_01(0), m_11(0)
+ {
+ }
+ btMatrix2x2(const btMatrix2x2& other): m_00(other.m_00),m_01(other.m_01),m_10(other.m_10),m_11(other.m_11)
+ {}
+ btScalar& operator()(int i, int j)
+ {
+ if (i == 0 && j == 0)
+ return m_00;
+ if (i == 1 && j == 0)
+ return m_10;
+ if (i == 0 && j == 1)
+ return m_01;
+ if (i == 1 && j == 1)
+ return m_11;
+ btAssert(false);
+ return m_00;
+ }
+ const btScalar& operator()(int i, int j) const
+ {
+ if (i == 0 && j == 0)
+ return m_00;
+ if (i == 1 && j == 0)
+ return m_10;
+ if (i == 0 && j == 1)
+ return m_01;
+ if (i == 1 && j == 1)
+ return m_11;
+ btAssert(false);
+ return m_00;
+ }
+ void setIdentity()
+ {
+ m_00 = 1;
+ m_11 = 1;
+ m_01 = 0;
+ m_10 = 0;
+ }
+};
+
+static inline btScalar copySign(btScalar x, btScalar y) {
+ if ((x < 0 && y > 0) || (x > 0 && y < 0))
+ return -x;
+ return x;
+}
+
+/**
+ Class for givens rotation.
+ Row rotation G*A corresponds to something like
+ c -s 0
+ ( s c 0 ) A
+ 0 0 1
+ Column rotation A G' corresponds to something like
+ c -s 0
+ A ( s c 0 )
+ 0 0 1
+
+ c and s are always computed so that
+ ( c -s ) ( a ) = ( * )
+ s c b ( 0 )
+
+ Assume rowi<rowk.
+ */
+
+class GivensRotation {
+public:
+ int rowi;
+ int rowk;
+ btScalar c;
+ btScalar s;
+
+ inline GivensRotation(int rowi_in, int rowk_in)
+ : rowi(rowi_in)
+ , rowk(rowk_in)
+ , c(1)
+ , s(0)
+ {
+ }
+
+ inline GivensRotation(btScalar a, btScalar b, int rowi_in, int rowk_in)
+ : rowi(rowi_in)
+ , rowk(rowk_in)
+ {
+ compute(a, b);
+ }
+
+ ~GivensRotation() {}
+
+ inline void transposeInPlace()
+ {
+ s = -s;
+ }
+
+ /**
+ Compute c and s from a and b so that
+ ( c -s ) ( a ) = ( * )
+ s c b ( 0 )
+ */
+ inline void compute(const btScalar a, const btScalar b)
+ {
+ btScalar d = a * a + b * b;
+ c = 1;
+ s = 0;
+ if (d > SIMD_EPSILON) {
+ btScalar sqrtd = btSqrt(d);
+ if (sqrtd>SIMD_EPSILON)
+ {
+ btScalar t = btScalar(1.0)/sqrtd;
+ c = a * t;
+ s = -b * t;
+ }
+ }
+ }
+
+ /**
+ This function computes c and s so that
+ ( c -s ) ( a ) = ( 0 )
+ s c b ( * )
+ */
+ inline void computeUnconventional(const btScalar a, const btScalar b)
+ {
+ btScalar d = a * a + b * b;
+ c = 0;
+ s = 1;
+ if (d > SIMD_EPSILON) {
+ btScalar t = btScalar(1.0)/btSqrt(d);
+ s = a * t;
+ c = b * t;
+ }
+ }
+ /**
+ Fill the R with the entries of this rotation
+ */
+ inline void fill(const btMatrix3x3& R) const
+ {
+ btMatrix3x3& A = const_cast<btMatrix3x3&>(R);
+ A.setIdentity();
+ A[rowi][rowi] = c;
+ A[rowk][rowi] = -s;
+ A[rowi][rowk] = s;
+ A[rowk][rowk] = c;
+ }
+
+ inline void fill(const btMatrix2x2& R) const
+ {
+ btMatrix2x2& A = const_cast<btMatrix2x2&>(R);
+ A(rowi,rowi) = c;
+ A(rowk,rowi) = -s;
+ A(rowi,rowk) = s;
+ A(rowk,rowk) = c;
+ }
+
+ /**
+ This function does something like
+ c -s 0
+ ( s c 0 ) A -> A
+ 0 0 1
+ It only affects row i and row k of A.
+ */
+ inline void rowRotation(btMatrix3x3& A) const
+ {
+ for (int j = 0; j < 3; j++) {
+ btScalar tau1 = A[rowi][j];
+ btScalar tau2 = A[rowk][j];
+ A[rowi][j] = c * tau1 - s * tau2;
+ A[rowk][j] = s * tau1 + c * tau2;
+ }
+ }
+ inline void rowRotation(btMatrix2x2& A) const
+ {
+ for (int j = 0; j < 2; j++) {
+ btScalar tau1 = A(rowi,j);
+ btScalar tau2 = A(rowk,j);
+ A(rowi,j) = c * tau1 - s * tau2;
+ A(rowk,j) = s * tau1 + c * tau2;
+ }
+ }
+
+ /**
+ This function does something like
+ c s 0
+ A ( -s c 0 ) -> A
+ 0 0 1
+ It only affects column i and column k of A.
+ */
+ inline void columnRotation(btMatrix3x3& A) const
+ {
+ for (int j = 0; j < 3; j++) {
+ btScalar tau1 = A[j][rowi];
+ btScalar tau2 = A[j][rowk];
+ A[j][rowi] = c * tau1 - s * tau2;
+ A[j][rowk] = s * tau1 + c * tau2;
+ }
+ }
+ inline void columnRotation(btMatrix2x2& A) const
+ {
+ for (int j = 0; j < 2; j++) {
+ btScalar tau1 = A(j,rowi);
+ btScalar tau2 = A(j,rowk);
+ A(j,rowi) = c * tau1 - s * tau2;
+ A(j,rowk) = s * tau1 + c * tau2;
+ }
+ }
+
+ /**
+ Multiply givens must be for same row and column
+ **/
+ inline void operator*=(const GivensRotation& A)
+ {
+ btScalar new_c = c * A.c - s * A.s;
+ btScalar new_s = s * A.c + c * A.s;
+ c = new_c;
+ s = new_s;
+ }
+
+ /**
+ Multiply givens must be for same row and column
+ **/
+ inline GivensRotation operator*(const GivensRotation& A) const
+ {
+ GivensRotation r(*this);
+ r *= A;
+ return r;
+ }
+};
+
+/**
+ \brief zero chasing the 3X3 matrix to bidiagonal form
+ original form of H: x x 0
+ x x x
+ 0 0 x
+ after zero chase:
+ x x 0
+ 0 x x
+ 0 0 x
+ */
+inline void zeroChase(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
+{
+
+ /**
+ Reduce H to of form
+ x x +
+ 0 x x
+ 0 0 x
+ */
+ GivensRotation r1(H[0][0], H[1][0], 0, 1);
+ /**
+ Reduce H to of form
+ x x 0
+ 0 x x
+ 0 + x
+ Can calculate r2 without multiplying by r1 since both entries are in first two
+ rows thus no need to divide by sqrt(a^2+b^2)
+ */
+ GivensRotation r2(1, 2);
+ if (H[1][0] != 0)
+ r2.compute(H[0][0] * H[0][1] + H[1][0] * H[1][1], H[0][0] * H[0][2] + H[1][0] * H[1][2]);
+ else
+ r2.compute(H[0][1], H[0][2]);
+
+ r1.rowRotation(H);
+
+ /* GivensRotation<T> r2(H(0, 1), H(0, 2), 1, 2); */
+ r2.columnRotation(H);
+ r2.columnRotation(V);
+
+ /**
+ Reduce H to of form
+ x x 0
+ 0 x x
+ 0 0 x
+ */
+ GivensRotation r3(H[1][1], H[2][1], 1, 2);
+ r3.rowRotation(H);
+
+ // Save this till end for better cache coherency
+ // r1.rowRotation(u_transpose);
+ // r3.rowRotation(u_transpose);
+ r1.columnRotation(U);
+ r3.columnRotation(U);
+}
+
+/**
+ \brief make a 3X3 matrix to upper bidiagonal form
+ original form of H: x x x
+ x x x
+ x x x
+ after zero chase:
+ x x 0
+ 0 x x
+ 0 0 x
+ */
+inline void makeUpperBidiag(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
+{
+ U.setIdentity();
+ V.setIdentity();
+
+ /**
+ Reduce H to of form
+ x x x
+ x x x
+ 0 x x
+ */
+
+ GivensRotation r(H[1][0], H[2][0], 1, 2);
+ r.rowRotation(H);
+ // r.rowRotation(u_transpose);
+ r.columnRotation(U);
+ // zeroChase(H, u_transpose, V);
+ zeroChase(H, U, V);
+}
+
+/**
+ \brief make a 3X3 matrix to lambda shape
+ original form of H: x x x
+ * x x x
+ * x x x
+ after :
+ * x 0 0
+ * x x 0
+ * x 0 x
+ */
+inline void makeLambdaShape(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
+{
+ U.setIdentity();
+ V.setIdentity();
+
+ /**
+ Reduce H to of form
+ * x x 0
+ * x x x
+ * x x x
+ */
+
+ GivensRotation r1(H[0][1], H[0][2], 1, 2);
+ r1.columnRotation(H);
+ r1.columnRotation(V);
+
+ /**
+ Reduce H to of form
+ * x x 0
+ * x x 0
+ * x x x
+ */
+
+ r1.computeUnconventional(H[1][2], H[2][2]);
+ r1.rowRotation(H);
+ r1.columnRotation(U);
+
+ /**
+ Reduce H to of form
+ * x x 0
+ * x x 0
+ * x 0 x
+ */
+
+ GivensRotation r2(H[2][0], H[2][1], 0, 1);
+ r2.columnRotation(H);
+ r2.columnRotation(V);
+
+ /**
+ Reduce H to of form
+ * x 0 0
+ * x x 0
+ * x 0 x
+ */
+ r2.computeUnconventional(H[0][1], H[1][1]);
+ r2.rowRotation(H);
+ r2.columnRotation(U);
+}
+
+/**
+ \brief 2x2 polar decomposition.
+ \param[in] A matrix.
+ \param[out] R Robustly a rotation matrix.
+ \param[out] S_Sym Symmetric. Whole matrix is stored
+
+ Polar guarantees negative sign is on the small magnitude singular value.
+ S is guaranteed to be the closest one to identity.
+ R is guaranteed to be the closest rotation to A.
+ */
+inline void polarDecomposition(const btMatrix2x2& A,
+ GivensRotation& R,
+ const btMatrix2x2& S_Sym)
+{
+ btScalar a = (A(0, 0) + A(1, 1)), b = (A(1, 0) - A(0, 1));
+ btScalar denominator = btSqrt(a*a+b*b);
+ R.c = (btScalar)1;
+ R.s = (btScalar)0;
+ if (denominator > SIMD_EPSILON) {
+ /*
+ No need to use a tolerance here because x(0) and x(1) always have
+ smaller magnitude then denominator, therefore overflow never happens.
+ In Bullet, we use a tolerance anyway.
+ */
+ R.c = a / denominator;
+ R.s = -b / denominator;
+ }
+ btMatrix2x2& S = const_cast<btMatrix2x2&>(S_Sym);
+ S = A;
+ R.rowRotation(S);
+}
+
+inline void polarDecomposition(const btMatrix2x2& A,
+ const btMatrix2x2& R,
+ const btMatrix2x2& S_Sym)
+{
+ GivensRotation r(0, 1);
+ polarDecomposition(A, r, S_Sym);
+ r.fill(R);
+}
+
+/**
+ \brief 2x2 SVD (singular value decomposition) A=USV'
+ \param[in] A Input matrix.
+ \param[out] U Robustly a rotation matrix in Givens form
+ \param[out] Sigma matrix of singular values sorted with decreasing magnitude. The second one can be negative.
+ \param[out] V Robustly a rotation matrix in Givens form
+ */
+inline void singularValueDecomposition(
+ const btMatrix2x2& A,
+ GivensRotation& U,
+ const btMatrix2x2& Sigma,
+ GivensRotation& V,
+ const btScalar tol = 64 * std::numeric_limits<btScalar>::epsilon())
+{
+ btMatrix2x2& sigma = const_cast<btMatrix2x2&>(Sigma);
+ sigma.setIdentity();
+ btMatrix2x2 S_Sym;
+ polarDecomposition(A, U, S_Sym);
+ btScalar cosine, sine;
+ btScalar x = S_Sym(0, 0);
+ btScalar y = S_Sym(0, 1);
+ btScalar z = S_Sym(1, 1);
+ if (y == 0) {
+ // S is already diagonal
+ cosine = 1;
+ sine = 0;
+ sigma(0,0) = x;
+ sigma(1,1) = z;
+ }
+ else {
+ btScalar tau = 0.5 * (x - z);
+ btScalar val = tau * tau + y * y;
+ if (val > SIMD_EPSILON)
+ {
+ btScalar w = btSqrt(val);
+ // w > y > 0
+ btScalar t;
+ if (tau > 0) {
+ // tau + w > w > y > 0 ==> division is safe
+ t = y / (tau + w);
+ }
+ else {
+ // tau - w < -w < -y < 0 ==> division is safe
+ t = y / (tau - w);
+ }
+ cosine = btScalar(1) / btSqrt(t * t + btScalar(1));
+ sine = -t * cosine;
+ /*
+ V = [cosine -sine; sine cosine]
+ Sigma = V'SV. Only compute the diagonals for efficiency.
+ Also utilize symmetry of S and don't form V yet.
+ */
+ btScalar c2 = cosine * cosine;
+ btScalar csy = 2 * cosine * sine * y;
+ btScalar s2 = sine * sine;
+ sigma(0,0) = c2 * x - csy + s2 * z;
+ sigma(1,1) = s2 * x + csy + c2 * z;
+ } else
+ {
+ cosine = 1;
+ sine = 0;
+ sigma(0,0) = x;
+ sigma(1,1) = z;
+ }
+ }
+
+ // Sorting
+ // Polar already guarantees negative sign is on the small magnitude singular value.
+ if (sigma(0,0) < sigma(1,1)) {
+ std::swap(sigma(0,0), sigma(1,1));
+ V.c = -sine;
+ V.s = cosine;
+ }
+ else {
+ V.c = cosine;
+ V.s = sine;
+ }
+ U *= V;
+}
+
+/**
+ \brief 2x2 SVD (singular value decomposition) A=USV'
+ \param[in] A Input matrix.
+ \param[out] U Robustly a rotation matrix.
+ \param[out] Sigma Vector of singular values sorted with decreasing magnitude. The second one can be negative.
+ \param[out] V Robustly a rotation matrix.
+ */
+inline void singularValueDecomposition(
+ const btMatrix2x2& A,
+ const btMatrix2x2& U,
+ const btMatrix2x2& Sigma,
+ const btMatrix2x2& V,
+ const btScalar tol = 64 * std::numeric_limits<btScalar>::epsilon())
+{
+ GivensRotation gv(0, 1);
+ GivensRotation gu(0, 1);
+ singularValueDecomposition(A, gu, Sigma, gv);
+
+ gu.fill(U);
+ gv.fill(V);
+}
+
+/**
+ \brief compute wilkinsonShift of the block
+ a1 b1
+ b1 a2
+ based on the wilkinsonShift formula
+ mu = c + d - sign (d) \ sqrt (d*d + b*b), where d = (a-c)/2
+
+ */
+inline btScalar wilkinsonShift(const btScalar a1, const btScalar b1, const btScalar a2)
+{
+ btScalar d = (btScalar)0.5 * (a1 - a2);
+ btScalar bs = b1 * b1;
+ btScalar val = d * d + bs;
+ if (val>SIMD_EPSILON)
+ {
+ btScalar denom = btFabs(d) + btSqrt(val);
+
+ btScalar mu = a2 - copySign(bs / (denom), d);
+ // T mu = a2 - bs / ( d + sign_d*sqrt (d*d + bs));
+ return mu;
+ }
+ return a2;
+}
+
+/**
+ \brief Helper function of 3X3 SVD for processing 2X2 SVD
+ */
+template <int t>
+inline void process(btMatrix3x3& B, btMatrix3x3& U, btVector3& sigma, btMatrix3x3& V)
+{
+ int other = (t == 1) ? 0 : 2;
+ GivensRotation u(0, 1);
+ GivensRotation v(0, 1);
+ sigma[other] = B[other][other];
+
+ btMatrix2x2 B_sub, sigma_sub;
+ if (t == 0)
+ {
+ B_sub.m_00 = B[0][0];
+ B_sub.m_10 = B[1][0];
+ B_sub.m_01 = B[0][1];
+ B_sub.m_11 = B[1][1];
+ sigma_sub.m_00 = sigma[0];
+ sigma_sub.m_11 = sigma[1];
+// singularValueDecomposition(B.template block<2, 2>(t, t), u, sigma.template block<2, 1>(t, 0), v);
+ singularValueDecomposition(B_sub, u, sigma_sub, v);
+ B[0][0] = B_sub.m_00;
+ B[1][0] = B_sub.m_10;
+ B[0][1] = B_sub.m_01;
+ B[1][1] = B_sub.m_11;
+ sigma[0] = sigma_sub.m_00;
+ sigma[1] = sigma_sub.m_11;
+ }
+ else
+ {
+ B_sub.m_00 = B[1][1];
+ B_sub.m_10 = B[2][1];
+ B_sub.m_01 = B[1][2];
+ B_sub.m_11 = B[2][2];
+ sigma_sub.m_00 = sigma[1];
+ sigma_sub.m_11 = sigma[2];
+ // singularValueDecomposition(B.template block<2, 2>(t, t), u, sigma.template block<2, 1>(t, 0), v);
+ singularValueDecomposition(B_sub, u, sigma_sub, v);
+ B[1][1] = B_sub.m_00;
+ B[2][1] = B_sub.m_10;
+ B[1][2] = B_sub.m_01;
+ B[2][2] = B_sub.m_11;
+ sigma[1] = sigma_sub.m_00;
+ sigma[2] = sigma_sub.m_11;
+ }
+ u.rowi += t;
+ u.rowk += t;
+ v.rowi += t;
+ v.rowk += t;
+ u.columnRotation(U);
+ v.columnRotation(V);
+}
+
+/**
+ \brief Helper function of 3X3 SVD for flipping signs due to flipping signs of sigma
+ */
+inline void flipSign(int i, btMatrix3x3& U, btVector3& sigma)
+{
+ sigma[i] = -sigma[i];
+ U[0][i] = -U[0][i];
+ U[1][i] = -U[1][i];
+ U[2][i] = -U[2][i];
+}
+
+inline void flipSign(int i, btMatrix3x3& U)
+{
+ U[0][i] = -U[0][i];
+ U[1][i] = -U[1][i];
+ U[2][i] = -U[2][i];
+}
+
+inline void swapCol(btMatrix3x3& A, int i, int j)
+{
+ for (int d = 0; d < 3; ++d)
+ std::swap(A[d][i], A[d][j]);
+}
+/**
+ \brief Helper function of 3X3 SVD for sorting singular values
+ */
+inline void sort(btMatrix3x3& U, btVector3& sigma, btMatrix3x3& V, int t)
+{
+ if (t == 0)
+ {
+ // Case: sigma(0) > |sigma(1)| >= |sigma(2)|
+ if (btFabs(sigma[1]) >= btFabs(sigma[2])) {
+ if (sigma[1] < 0) {
+ flipSign(1, U, sigma);
+ flipSign(2, U, sigma);
+ }
+ return;
+ }
+
+ //fix sign of sigma for both cases
+ if (sigma[2] < 0) {
+ flipSign(1, U, sigma);
+ flipSign(2, U, sigma);
+ }
+
+ //swap sigma(1) and sigma(2) for both cases
+ std::swap(sigma[1], sigma[2]);
+ // swap the col 1 and col 2 for U,V
+ swapCol(U,1,2);
+ swapCol(V,1,2);
+
+ // Case: |sigma(2)| >= sigma(0) > |simga(1)|
+ if (sigma[1] > sigma[0]) {
+ std::swap(sigma[0], sigma[1]);
+ swapCol(U,0,1);
+ swapCol(V,0,1);
+ }
+
+ // Case: sigma(0) >= |sigma(2)| > |simga(1)|
+ else {
+ flipSign(2, U);
+ flipSign(2, V);
+ }
+ }
+ else if (t == 1)
+ {
+ // Case: |sigma(0)| >= sigma(1) > |sigma(2)|
+ if (btFabs(sigma[0]) >= sigma[1]) {
+ if (sigma[0] < 0) {
+ flipSign(0, U, sigma);
+ flipSign(2, U, sigma);
+ }
+ return;
+ }
+
+ //swap sigma(0) and sigma(1) for both cases
+ std::swap(sigma[0], sigma[1]);
+ swapCol(U, 0, 1);
+ swapCol(V, 0, 1);
+
+ // Case: sigma(1) > |sigma(2)| >= |sigma(0)|
+ if (btFabs(sigma[1]) < btFabs(sigma[2])) {
+ std::swap(sigma[1], sigma[2]);
+ swapCol(U, 1, 2);
+ swapCol(V, 1, 2);
+ }
+
+ // Case: sigma(1) >= |sigma(0)| > |sigma(2)|
+ else {
+ flipSign(1, U);
+ flipSign(1, V);
+ }
+
+ // fix sign for both cases
+ if (sigma[1] < 0) {
+ flipSign(1, U, sigma);
+ flipSign(2, U, sigma);
+ }
+ }
+}
+
+/**
+ \brief 3X3 SVD (singular value decomposition) A=USV'
+ \param[in] A Input matrix.
+ \param[out] U is a rotation matrix.
+ \param[out] sigma Diagonal matrix, sorted with decreasing magnitude. The third one can be negative.
+ \param[out] V is a rotation matrix.
+ */
+inline int singularValueDecomposition(const btMatrix3x3& A,
+ btMatrix3x3& U,
+ btVector3& sigma,
+ btMatrix3x3& V,
+ btScalar tol = 128*std::numeric_limits<btScalar>::epsilon())
+{
+// using std::fabs;
+ btMatrix3x3 B = A;
+ U.setIdentity();
+ V.setIdentity();
+
+ makeUpperBidiag(B, U, V);
+
+ int count = 0;
+ btScalar mu = (btScalar)0;
+ GivensRotation r(0, 1);
+
+ btScalar alpha_1 = B[0][0];
+ btScalar beta_1 = B[0][1];
+ btScalar alpha_2 = B[1][1];
+ btScalar alpha_3 = B[2][2];
+ btScalar beta_2 = B[1][2];
+ btScalar gamma_1 = alpha_1 * beta_1;
+ btScalar gamma_2 = alpha_2 * beta_2;
+ btScalar val = alpha_1 * alpha_1 + alpha_2 * alpha_2 + alpha_3 * alpha_3 + beta_1 * beta_1 + beta_2 * beta_2;
+ if (val > SIMD_EPSILON)
+ {
+ tol *= btMax((btScalar)0.5 * btSqrt(val), (btScalar)1);
+ }
+ /**
+ Do implicit shift QR until A^T A is block diagonal
+ */
+ int max_count = 100;
+
+ while (btFabs(beta_2) > tol && btFabs(beta_1) > tol
+ && btFabs(alpha_1) > tol && btFabs(alpha_2) > tol
+ && btFabs(alpha_3) > tol
+ && count < max_count) {
+ mu = wilkinsonShift(alpha_2 * alpha_2 + beta_1 * beta_1, gamma_2, alpha_3 * alpha_3 + beta_2 * beta_2);
+
+ r.compute(alpha_1 * alpha_1 - mu, gamma_1);
+ r.columnRotation(B);
+
+ r.columnRotation(V);
+ zeroChase(B, U, V);
+
+ alpha_1 = B[0][0];
+ beta_1 = B[0][1];
+ alpha_2 = B[1][1];
+ alpha_3 = B[2][2];
+ beta_2 = B[1][2];
+ gamma_1 = alpha_1 * beta_1;
+ gamma_2 = alpha_2 * beta_2;
+ count++;
+ }
+ /**
+ Handle the cases of one of the alphas and betas being 0
+ Sorted by ease of handling and then frequency
+ of occurrence
+
+ If B is of form
+ x x 0
+ 0 x 0
+ 0 0 x
+ */
+ if (btFabs(beta_2) <= tol) {
+ process<0>(B, U, sigma, V);
+ sort(U, sigma, V,0);
+ }
+ /**
+ If B is of form
+ x 0 0
+ 0 x x
+ 0 0 x
+ */
+ else if (btFabs(beta_1) <= tol) {
+ process<1>(B, U, sigma, V);
+ sort(U, sigma, V,1);
+ }
+ /**
+ If B is of form
+ x x 0
+ 0 0 x
+ 0 0 x
+ */
+ else if (btFabs(alpha_2) <= tol) {
+ /**
+ Reduce B to
+ x x 0
+ 0 0 0
+ 0 0 x
+ */
+ GivensRotation r1(1, 2);
+ r1.computeUnconventional(B[1][2], B[2][2]);
+ r1.rowRotation(B);
+ r1.columnRotation(U);
+
+ process<0>(B, U, sigma, V);
+ sort(U, sigma, V, 0);
+ }
+ /**
+ If B is of form
+ x x 0
+ 0 x x
+ 0 0 0
+ */
+ else if (btFabs(alpha_3) <= tol) {
+ /**
+ Reduce B to
+ x x +
+ 0 x 0
+ 0 0 0
+ */
+ GivensRotation r1(1, 2);
+ r1.compute(B[1][1], B[1][2]);
+ r1.columnRotation(B);
+ r1.columnRotation(V);
+ /**
+ Reduce B to
+ x x 0
+ + x 0
+ 0 0 0
+ */
+ GivensRotation r2(0, 2);
+ r2.compute(B[0][0], B[0][2]);
+ r2.columnRotation(B);
+ r2.columnRotation(V);
+
+ process<0>(B, U, sigma, V);
+ sort(U, sigma, V, 0);
+ }
+ /**
+ If B is of form
+ 0 x 0
+ 0 x x
+ 0 0 x
+ */
+ else if (btFabs(alpha_1) <= tol) {
+ /**
+ Reduce B to
+ 0 0 +
+ 0 x x
+ 0 0 x
+ */
+ GivensRotation r1(0, 1);
+ r1.computeUnconventional(B[0][1], B[1][1]);
+ r1.rowRotation(B);
+ r1.columnRotation(U);
+
+ /**
+ Reduce B to
+ 0 0 0
+ 0 x x
+ 0 + x
+ */
+ GivensRotation r2(0, 2);
+ r2.computeUnconventional(B[0][2], B[2][2]);
+ r2.rowRotation(B);
+ r2.columnRotation(U);
+
+ process<1>(B, U, sigma, V);
+ sort(U, sigma, V, 1);
+ }
+
+ return count;
+}
+#endif /* btImplicitQRSVD_h */
diff --git a/thirdparty/bullet/LinearMath/btMatrix3x3.h b/thirdparty/bullet/LinearMath/btMatrix3x3.h
index 0a08ae409a..9c90fee1d2 100644
--- a/thirdparty/bullet/LinearMath/btMatrix3x3.h
+++ b/thirdparty/bullet/LinearMath/btMatrix3x3.h
@@ -26,10 +26,12 @@ subject to the following restrictions:
#endif
#if defined(BT_USE_SSE)
+#define v0000 (_mm_set_ps(0.0f, 0.0f, 0.0f, 0.0f))
#define v1000 (_mm_set_ps(0.0f, 0.0f, 0.0f, 1.0f))
#define v0100 (_mm_set_ps(0.0f, 0.0f, 1.0f, 0.0f))
#define v0010 (_mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f))
#elif defined(BT_USE_NEON)
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0000) = {0.0f, 0.0f, 0.0f, 0.0f};
const btSimdFloat4 ATTRIBUTE_ALIGNED16(v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
@@ -125,6 +127,13 @@ public:
m_el[2] = other.m_el[2];
return *this;
}
+
+ SIMD_FORCE_INLINE btMatrix3x3(const btVector3& v0, const btVector3& v1, const btVector3& v2)
+ {
+ m_el[0] = v0;
+ m_el[1] = v1;
+ m_el[2] = v2;
+ }
#endif
@@ -323,6 +332,20 @@ public:
btScalar(0.0), btScalar(0.0), btScalar(1.0));
#endif
}
+
+ /**@brief Set the matrix to the identity */
+ void setZero()
+ {
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+ m_el[0] = v0000;
+ m_el[1] = v0000;
+ m_el[2] = v0000;
+#else
+ setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0),
+ btScalar(0.0), btScalar(0.0), btScalar(0.0),
+ btScalar(0.0), btScalar(0.0), btScalar(0.0));
+#endif
+ }
static const btMatrix3x3& getIdentity()
{
diff --git a/thirdparty/bullet/LinearMath/btMatrixX.h b/thirdparty/bullet/LinearMath/btMatrixX.h
index 388c57c2d7..bb0f0dd259 100644
--- a/thirdparty/bullet/LinearMath/btMatrixX.h
+++ b/thirdparty/bullet/LinearMath/btMatrixX.h
@@ -338,24 +338,22 @@ struct btMatrixX
btMatrixX res(rows(), other.cols());
res.setZero();
// BT_PROFILE("btMatrixX mul");
- for (int j = 0; j < res.cols(); ++j)
+ for (int i = 0; i < rows(); ++i)
{
{
- for (int i = 0; i < res.rows(); ++i)
+ for (int j = 0; j < other.cols(); ++j)
{
T dotProd = 0;
- // T dotProd2=0;
- //int waste=0,waste2=0;
-
{
- // bool useOtherCol = true;
{
- for (int v = 0; v < rows(); v++)
+ int c = cols();
+
+ for (int k = 0; k < c; k++)
{
- T w = (*this)(i, v);
- if (other(v, j) != 0.f)
+ T w = (*this)(i, k);
+ if (other(k, j) != 0.f)
{
- dotProd += w * other(v, j);
+ dotProd += w * other(k, j);
}
}
}
diff --git a/thirdparty/bullet/LinearMath/btModifiedGramSchmidt.h b/thirdparty/bullet/LinearMath/btModifiedGramSchmidt.h
new file mode 100644
index 0000000000..33bab8d650
--- /dev/null
+++ b/thirdparty/bullet/LinearMath/btModifiedGramSchmidt.h
@@ -0,0 +1,83 @@
+//
+// btModifiedGramSchmidt.h
+// LinearMath
+//
+// Created by Xuchen Han on 4/4/20.
+//
+
+#ifndef btModifiedGramSchmidt_h
+#define btModifiedGramSchmidt_h
+
+#include "btReducedVector.h"
+#include "btAlignedObjectArray.h"
+#include <iostream>
+#include <cmath>
+template<class TV>
+class btModifiedGramSchmidt
+{
+public:
+ btAlignedObjectArray<TV> m_in;
+ btAlignedObjectArray<TV> m_out;
+
+ btModifiedGramSchmidt(const btAlignedObjectArray<TV>& vecs): m_in(vecs)
+ {
+ m_out.resize(0);
+ }
+
+ void solve()
+ {
+ m_out.resize(m_in.size());
+ for (int i = 0; i < m_in.size(); ++i)
+ {
+// printf("========= starting %d ==========\n", i);
+ TV v(m_in[i]);
+// v.print();
+ for (int j = 0; j < i; ++j)
+ {
+ v = v - v.proj(m_out[j]);
+// v.print();
+ }
+ v.normalize();
+ m_out[i] = v;
+// v.print();
+ }
+ }
+
+ void test()
+ {
+ std::cout << SIMD_EPSILON << std::endl;
+ printf("=======inputs=========\n");
+ for (int i = 0; i < m_out.size(); ++i)
+ {
+ m_in[i].print();
+ }
+ printf("=======output=========\n");
+ for (int i = 0; i < m_out.size(); ++i)
+ {
+ m_out[i].print();
+ }
+ btScalar eps = SIMD_EPSILON;
+ for (int i = 0; i < m_out.size(); ++i)
+ {
+ for (int j = 0; j < m_out.size(); ++j)
+ {
+ if (i == j)
+ {
+ if (std::abs(1.0-m_out[i].dot(m_out[j])) > eps)// && std::abs(m_out[i].dot(m_out[j])) > eps)
+ {
+ printf("vec[%d] is not unit, norm squared = %f\n", i,m_out[i].dot(m_out[j]));
+ }
+ }
+ else
+ {
+ if (std::abs(m_out[i].dot(m_out[j])) > eps)
+ {
+ printf("vec[%d] and vec[%d] is not orthogonal, dot product = %f\n", i, j, m_out[i].dot(m_out[j]));
+ }
+ }
+ }
+ }
+ }
+};
+template class btModifiedGramSchmidt<btReducedVector>;
+#endif /* btModifiedGramSchmidt_h */
diff --git a/thirdparty/bullet/LinearMath/btReducedVector.cpp b/thirdparty/bullet/LinearMath/btReducedVector.cpp
new file mode 100644
index 0000000000..1539584e7e
--- /dev/null
+++ b/thirdparty/bullet/LinearMath/btReducedVector.cpp
@@ -0,0 +1,170 @@
+//
+// btReducedVector.cpp
+// LinearMath
+//
+// Created by Xuchen Han on 4/4/20.
+//
+#include <stdio.h>
+#include "btReducedVector.h"
+#include <cmath>
+
+// returns the projection of this onto other
+btReducedVector btReducedVector::proj(const btReducedVector& other) const
+{
+ btReducedVector ret(m_sz);
+ btScalar other_length2 = other.length2();
+ if (other_length2 < SIMD_EPSILON)
+ {
+ return ret;
+ }
+ return other*(this->dot(other))/other_length2;
+}
+
+void btReducedVector::normalize()
+{
+ if (this->length2() < SIMD_EPSILON)
+ {
+ m_indices.clear();
+ m_vecs.clear();
+ return;
+ }
+ *this /= std::sqrt(this->length2());
+}
+
+bool btReducedVector::testAdd() const
+{
+ int sz = 5;
+ btAlignedObjectArray<int> id1;
+ id1.push_back(1);
+ id1.push_back(3);
+ btAlignedObjectArray<btVector3> v1;
+ v1.push_back(btVector3(1,0,1));
+ v1.push_back(btVector3(3,1,5));
+ btAlignedObjectArray<int> id2;
+ id2.push_back(2);
+ id2.push_back(3);
+ id2.push_back(5);
+ btAlignedObjectArray<btVector3> v2;
+ v2.push_back(btVector3(2,3,1));
+ v2.push_back(btVector3(3,4,9));
+ v2.push_back(btVector3(0,4,0));
+ btAlignedObjectArray<int> id3;
+ id3.push_back(1);
+ id3.push_back(2);
+ id3.push_back(3);
+ id3.push_back(5);
+ btAlignedObjectArray<btVector3> v3;
+ v3.push_back(btVector3(1,0,1));
+ v3.push_back(btVector3(2,3,1));
+ v3.push_back(btVector3(6,5,14));
+ v3.push_back(btVector3(0,4,0));
+ btReducedVector rv1(sz, id1, v1);
+ btReducedVector rv2(sz, id2, v2);
+ btReducedVector ans(sz, id3, v3);
+ bool ret = ((ans == rv1+rv2) && (ans == rv2+rv1));
+ if (!ret)
+ printf("btReducedVector testAdd failed\n");
+ return ret;
+}
+
+bool btReducedVector::testMinus() const
+{
+ int sz = 5;
+ btAlignedObjectArray<int> id1;
+ id1.push_back(1);
+ id1.push_back(3);
+ btAlignedObjectArray<btVector3> v1;
+ v1.push_back(btVector3(1,0,1));
+ v1.push_back(btVector3(3,1,5));
+ btAlignedObjectArray<int> id2;
+ id2.push_back(2);
+ id2.push_back(3);
+ id2.push_back(5);
+ btAlignedObjectArray<btVector3> v2;
+ v2.push_back(btVector3(2,3,1));
+ v2.push_back(btVector3(3,4,9));
+ v2.push_back(btVector3(0,4,0));
+ btAlignedObjectArray<int> id3;
+ id3.push_back(1);
+ id3.push_back(2);
+ id3.push_back(3);
+ id3.push_back(5);
+ btAlignedObjectArray<btVector3> v3;
+ v3.push_back(btVector3(-1,-0,-1));
+ v3.push_back(btVector3(2,3,1));
+ v3.push_back(btVector3(0,3,4));
+ v3.push_back(btVector3(0,4,0));
+ btReducedVector rv1(sz, id1, v1);
+ btReducedVector rv2(sz, id2, v2);
+ btReducedVector ans(sz, id3, v3);
+ bool ret = (ans == rv2-rv1);
+ if (!ret)
+ printf("btReducedVector testMinus failed\n");
+ return ret;
+}
+
+bool btReducedVector::testDot() const
+{
+ int sz = 5;
+ btAlignedObjectArray<int> id1;
+ id1.push_back(1);
+ id1.push_back(3);
+ btAlignedObjectArray<btVector3> v1;
+ v1.push_back(btVector3(1,0,1));
+ v1.push_back(btVector3(3,1,5));
+ btAlignedObjectArray<int> id2;
+ id2.push_back(2);
+ id2.push_back(3);
+ id2.push_back(5);
+ btAlignedObjectArray<btVector3> v2;
+ v2.push_back(btVector3(2,3,1));
+ v2.push_back(btVector3(3,4,9));
+ v2.push_back(btVector3(0,4,0));
+ btReducedVector rv1(sz, id1, v1);
+ btReducedVector rv2(sz, id2, v2);
+ btScalar ans = 58;
+ bool ret = (ans == rv2.dot(rv1) && ans == rv1.dot(rv2));
+ ans = 14+16+9+16+81;
+ ret &= (ans==rv2.dot(rv2));
+
+ if (!ret)
+ printf("btReducedVector testDot failed\n");
+ return ret;
+}
+
+bool btReducedVector::testMultiply() const
+{
+ int sz = 5;
+ btAlignedObjectArray<int> id1;
+ id1.push_back(1);
+ id1.push_back(3);
+ btAlignedObjectArray<btVector3> v1;
+ v1.push_back(btVector3(1,0,1));
+ v1.push_back(btVector3(3,1,5));
+ btScalar s = 2;
+ btReducedVector rv1(sz, id1, v1);
+ btAlignedObjectArray<int> id2;
+ id2.push_back(1);
+ id2.push_back(3);
+ btAlignedObjectArray<btVector3> v2;
+ v2.push_back(btVector3(2,0,2));
+ v2.push_back(btVector3(6,2,10));
+ btReducedVector ans(sz, id2, v2);
+ bool ret = (ans == rv1*s);
+ if (!ret)
+ printf("btReducedVector testMultiply failed\n");
+ return ret;
+}
+
+void btReducedVector::test() const
+{
+ bool ans = testAdd() && testMinus() && testDot() && testMultiply();
+ if (ans)
+ {
+ printf("All tests passed\n");
+ }
+ else
+ {
+ printf("Tests failed\n");
+ }
+}
diff --git a/thirdparty/bullet/LinearMath/btReducedVector.h b/thirdparty/bullet/LinearMath/btReducedVector.h
new file mode 100644
index 0000000000..83b5e581e5
--- /dev/null
+++ b/thirdparty/bullet/LinearMath/btReducedVector.h
@@ -0,0 +1,320 @@
+//
+// btReducedVectors.h
+// BulletLinearMath
+//
+// Created by Xuchen Han on 4/4/20.
+//
+#ifndef btReducedVectors_h
+#define btReducedVectors_h
+#include "btVector3.h"
+#include "btMatrix3x3.h"
+#include "btAlignedObjectArray.h"
+#include <stdio.h>
+#include <vector>
+#include <algorithm>
+struct TwoInts
+{
+ int a,b;
+};
+inline bool operator<(const TwoInts& A, const TwoInts& B)
+{
+ return A.b < B.b;
+}
+
+
+// A helper vector type used for CG projections
+class btReducedVector
+{
+public:
+ btAlignedObjectArray<int> m_indices;
+ btAlignedObjectArray<btVector3> m_vecs;
+ int m_sz; // all m_indices value < m_sz
+public:
+ btReducedVector():m_sz(0)
+ {
+ m_indices.resize(0);
+ m_vecs.resize(0);
+ m_indices.clear();
+ m_vecs.clear();
+ }
+
+ btReducedVector(int sz): m_sz(sz)
+ {
+ m_indices.resize(0);
+ m_vecs.resize(0);
+ m_indices.clear();
+ m_vecs.clear();
+ }
+
+ btReducedVector(int sz, const btAlignedObjectArray<int>& indices, const btAlignedObjectArray<btVector3>& vecs): m_sz(sz), m_indices(indices), m_vecs(vecs)
+ {
+ }
+
+ void simplify()
+ {
+ btAlignedObjectArray<int> old_indices(m_indices);
+ btAlignedObjectArray<btVector3> old_vecs(m_vecs);
+ m_indices.resize(0);
+ m_vecs.resize(0);
+ m_indices.clear();
+ m_vecs.clear();
+ for (int i = 0; i < old_indices.size(); ++i)
+ {
+ if (old_vecs[i].length2() > SIMD_EPSILON)
+ {
+ m_indices.push_back(old_indices[i]);
+ m_vecs.push_back(old_vecs[i]);
+ }
+ }
+ }
+
+ btReducedVector operator+(const btReducedVector& other)
+ {
+ btReducedVector ret(m_sz);
+ int i=0, j=0;
+ while (i < m_indices.size() && j < other.m_indices.size())
+ {
+ if (m_indices[i] < other.m_indices[j])
+ {
+ ret.m_indices.push_back(m_indices[i]);
+ ret.m_vecs.push_back(m_vecs[i]);
+ ++i;
+ }
+ else if (m_indices[i] > other.m_indices[j])
+ {
+ ret.m_indices.push_back(other.m_indices[j]);
+ ret.m_vecs.push_back(other.m_vecs[j]);
+ ++j;
+ }
+ else
+ {
+ ret.m_indices.push_back(other.m_indices[j]);
+ ret.m_vecs.push_back(m_vecs[i] + other.m_vecs[j]);
+ ++i; ++j;
+ }
+ }
+ while (i < m_indices.size())
+ {
+ ret.m_indices.push_back(m_indices[i]);
+ ret.m_vecs.push_back(m_vecs[i]);
+ ++i;
+ }
+ while (j < other.m_indices.size())
+ {
+ ret.m_indices.push_back(other.m_indices[j]);
+ ret.m_vecs.push_back(other.m_vecs[j]);
+ ++j;
+ }
+ ret.simplify();
+ return ret;
+ }
+
+ btReducedVector operator-()
+ {
+ btReducedVector ret(m_sz);
+ for (int i = 0; i < m_indices.size(); ++i)
+ {
+ ret.m_indices.push_back(m_indices[i]);
+ ret.m_vecs.push_back(-m_vecs[i]);
+ }
+ ret.simplify();
+ return ret;
+ }
+
+ btReducedVector operator-(const btReducedVector& other)
+ {
+ btReducedVector ret(m_sz);
+ int i=0, j=0;
+ while (i < m_indices.size() && j < other.m_indices.size())
+ {
+ if (m_indices[i] < other.m_indices[j])
+ {
+ ret.m_indices.push_back(m_indices[i]);
+ ret.m_vecs.push_back(m_vecs[i]);
+ ++i;
+ }
+ else if (m_indices[i] > other.m_indices[j])
+ {
+ ret.m_indices.push_back(other.m_indices[j]);
+ ret.m_vecs.push_back(-other.m_vecs[j]);
+ ++j;
+ }
+ else
+ {
+ ret.m_indices.push_back(other.m_indices[j]);
+ ret.m_vecs.push_back(m_vecs[i] - other.m_vecs[j]);
+ ++i; ++j;
+ }
+ }
+ while (i < m_indices.size())
+ {
+ ret.m_indices.push_back(m_indices[i]);
+ ret.m_vecs.push_back(m_vecs[i]);
+ ++i;
+ }
+ while (j < other.m_indices.size())
+ {
+ ret.m_indices.push_back(other.m_indices[j]);
+ ret.m_vecs.push_back(-other.m_vecs[j]);
+ ++j;
+ }
+ ret.simplify();
+ return ret;
+ }
+
+ bool operator==(const btReducedVector& other) const
+ {
+ if (m_sz != other.m_sz)
+ return false;
+ if (m_indices.size() != other.m_indices.size())
+ return false;
+ for (int i = 0; i < m_indices.size(); ++i)
+ {
+ if (m_indices[i] != other.m_indices[i] || m_vecs[i] != other.m_vecs[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator!=(const btReducedVector& other) const
+ {
+ return !(*this == other);
+ }
+
+ btReducedVector& operator=(const btReducedVector& other)
+ {
+ if (this == &other)
+ {
+ return *this;
+ }
+ m_sz = other.m_sz;
+ m_indices.copyFromArray(other.m_indices);
+ m_vecs.copyFromArray(other.m_vecs);
+ return *this;
+ }
+
+ btScalar dot(const btReducedVector& other) const
+ {
+ btScalar ret = 0;
+ int j = 0;
+ for (int i = 0; i < m_indices.size(); ++i)
+ {
+ while (j < other.m_indices.size() && other.m_indices[j] < m_indices[i])
+ {
+ ++j;
+ }
+ if (j < other.m_indices.size() && other.m_indices[j] == m_indices[i])
+ {
+ ret += m_vecs[i].dot(other.m_vecs[j]);
+// ++j;
+ }
+ }
+ return ret;
+ }
+
+ btScalar dot(const btAlignedObjectArray<btVector3>& other) const
+ {
+ btScalar ret = 0;
+ for (int i = 0; i < m_indices.size(); ++i)
+ {
+ ret += m_vecs[i].dot(other[m_indices[i]]);
+ }
+ return ret;
+ }
+
+ btScalar length2() const
+ {
+ return this->dot(*this);
+ }
+
+ void normalize();
+
+ // returns the projection of this onto other
+ btReducedVector proj(const btReducedVector& other) const;
+
+ bool testAdd() const;
+
+ bool testMinus() const;
+
+ bool testDot() const;
+
+ bool testMultiply() const;
+
+ void test() const;
+
+ void print() const
+ {
+ for (int i = 0; i < m_indices.size(); ++i)
+ {
+ printf("%d: (%f, %f, %f)/", m_indices[i], m_vecs[i][0],m_vecs[i][1],m_vecs[i][2]);
+ }
+ printf("\n");
+ }
+
+
+ void sort()
+ {
+ std::vector<TwoInts> tuples;
+ for (int i = 0; i < m_indices.size(); ++i)
+ {
+ TwoInts ti;
+ ti.a = i;
+ ti.b = m_indices[i];
+ tuples.push_back(ti);
+ }
+ std::sort(tuples.begin(), tuples.end());
+ btAlignedObjectArray<int> new_indices;
+ btAlignedObjectArray<btVector3> new_vecs;
+ for (int i = 0; i < tuples.size(); ++i)
+ {
+ new_indices.push_back(tuples[i].b);
+ new_vecs.push_back(m_vecs[tuples[i].a]);
+ }
+ m_indices = new_indices;
+ m_vecs = new_vecs;
+ }
+};
+
+SIMD_FORCE_INLINE btReducedVector operator*(const btReducedVector& v, btScalar s)
+{
+ btReducedVector ret(v.m_sz);
+ for (int i = 0; i < v.m_indices.size(); ++i)
+ {
+ ret.m_indices.push_back(v.m_indices[i]);
+ ret.m_vecs.push_back(s*v.m_vecs[i]);
+ }
+ ret.simplify();
+ return ret;
+}
+
+SIMD_FORCE_INLINE btReducedVector operator*(btScalar s, const btReducedVector& v)
+{
+ return v*s;
+}
+
+SIMD_FORCE_INLINE btReducedVector operator/(const btReducedVector& v, btScalar s)
+{
+ return v * (1.0/s);
+}
+
+SIMD_FORCE_INLINE btReducedVector& operator/=(btReducedVector& v, btScalar s)
+{
+ v = v/s;
+ return v;
+}
+
+SIMD_FORCE_INLINE btReducedVector& operator+=(btReducedVector& v1, const btReducedVector& v2)
+{
+ v1 = v1+v2;
+ return v1;
+}
+
+SIMD_FORCE_INLINE btReducedVector& operator-=(btReducedVector& v1, const btReducedVector& v2)
+{
+ v1 = v1-v2;
+ return v1;
+}
+
+#endif /* btReducedVectors_h */
diff --git a/thirdparty/bullet/LinearMath/btScalar.h b/thirdparty/bullet/LinearMath/btScalar.h
index ba49d6700b..86d94e8974 100644
--- a/thirdparty/bullet/LinearMath/btScalar.h
+++ b/thirdparty/bullet/LinearMath/btScalar.h
@@ -25,13 +25,23 @@ subject to the following restrictions:
#include <float.h>
/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
-#define BT_BULLET_VERSION 288
+#define BT_BULLET_VERSION 289
inline int btGetVersion()
{
return BT_BULLET_VERSION;
}
+inline int btIsDoublePrecision()
+{
+ #ifdef BT_USE_DOUBLE_PRECISION
+ return true;
+ #else
+ return false;
+ #endif
+}
+
+
// The following macro "BT_NOT_EMPTY_FILE" can be put into a file
// in order suppress the MS Visual C++ Linker warning 4221
//
@@ -63,7 +73,12 @@ inline int btGetVersion()
#endif
#ifdef _WIN32
- #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
+ #if defined(__GNUC__) // it should handle both MINGW and CYGWIN
+ #define SIMD_FORCE_INLINE __inline__ __attribute__((always_inline))
+ #define ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+ #define ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+ #define ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+ #elif ( defined(_MSC_VER) && _MSC_VER < 1300 )
#define SIMD_FORCE_INLINE inline
#define ATTRIBUTE_ALIGNED16(a) a
#define ATTRIBUTE_ALIGNED64(a) a
@@ -95,11 +110,16 @@ inline int btGetVersion()
#if defined (_M_ARM)
//Do not turn SSE on for ARM (may want to turn on BT_USE_NEON however)
#elif (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
+
+#ifdef __clang__
+#define __BT_DISABLE_SSE__
+#endif
+#ifndef __BT_DISABLE_SSE__
#if _MSC_VER>1400
#define BT_USE_SIMD_VECTOR3
#endif
-
#define BT_USE_SSE
+#endif//__BT_DISABLE_SSE__
#ifdef BT_USE_SSE
#if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default)
diff --git a/thirdparty/bullet/LinearMath/btSerializer.cpp b/thirdparty/bullet/LinearMath/btSerializer.cpp
index 18683c8fa7..068836f2c4 100644
--- a/thirdparty/bullet/LinearMath/btSerializer.cpp
+++ b/thirdparty/bullet/LinearMath/btSerializer.cpp
@@ -1,6 +1,5 @@
-// clang-format off
char sBulletDNAstr[]= {
-char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-76),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-74),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
@@ -87,606 +86,607 @@ char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),cha
char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(68),char(105),char(115),char(116),
char(97),char(110),char(99),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(91),char(52),char(93),char(0),char(109),char(95),
-char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),
-char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(97),char(114),char(116),
-char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
-char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),
-char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),char(116),char(70),char(108),
-char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(65),
-char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),
-char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(65),char(112),char(112),
-char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(50),char(91),
-char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),
-char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(50),char(91),
-char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),
-char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
-char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),
-char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
-char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),char(77),char(91),char(52),
-char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),char(101),char(84),char(105),
-char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),char(80),char(111),char(105),
-char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(65),char(0),char(109),
-char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),char(110),char(100),char(101),
-char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),
-char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),
-char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),char(101),char(115),char(115),
-char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),
-char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),char(97),char(99),char(116),
-char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),
-char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(117),char(110),char(115),
-char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),char(80),char(116),char(114),
-char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),
-char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),char(95),char(98),char(114),
-char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),char(95),char(99),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),char(111),char(111),char(116),
-char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),char(119),char(111),char(114),
-char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),
-char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
-char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(76),char(105),char(110),
-char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),
-char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),
-char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),
-char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(84),
-char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(111),char(108),
-char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
-char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
-char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),
-char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),
-char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),
-char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
-char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),
-char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),
-char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
-char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),
-char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),
-char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),char(116),char(101),char(114),
-char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
-char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),char(100),char(0),char(109),
-char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(116),char(105),char(109),
-char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),char(101),char(100),char(117),
-char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),char(0),char(109),char(95),
-char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),char(97),char(116),char(105),
-char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
-char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),
-char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),
-char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),
-char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),
-char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),
-char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),
-char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),
-char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),
-char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),
-char(73),char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),
-char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),
-char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),
-char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),
-char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),
-char(101),char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),
-char(105),char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),
-char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),
-char(101),char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),
-char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),
-char(103),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),
-char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),
-char(76),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),
-char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),
-char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),
-char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),
-char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),
-char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),
-char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),
-char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),
-char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),
-char(65),char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),
-char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),
-char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),
-char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),
-char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),
-char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),
-char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),
-char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),
-char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),
-char(108),char(101),char(100),char(0),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),
-char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),
-char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),
-char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),
-char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),
-char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),
-char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),
-char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),
-char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),
-char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),
-char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),
-char(91),char(52),char(93),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),
-char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),
-char(110),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),
-char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),
-char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),
-char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),
-char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),
-char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),
-char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
-char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),
-char(110),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),
-char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),
-char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
-char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),
-char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
-char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),
-char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),
-char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
-char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),
-char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),
-char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),
-char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),
-char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),
-char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
-char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),
-char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),
-char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
-char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
-char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),
-char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),
-char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),
-char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
-char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),
-char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),
-char(101),char(114),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),
-char(110),char(66),char(0),char(109),char(95),char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),
-char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
-char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),
-char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),
-char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),
-char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),
-char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),
-char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),
-char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),
-char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),
-char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),
-char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),
-char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),
-char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),
-char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),
-char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),
-char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),
-char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),
-char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),
-char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),
-char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),
-char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),
-char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),
-char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),
-char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),
-char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
-char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
-char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),
-char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),
-char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),
-char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),
-char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),
-char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),
-char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),
-char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
-char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
-char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
-char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),
-char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),
-char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),
-char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),
-char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),
-char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),
-char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),
-char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),
-char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),
-char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),
-char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),
-char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),
-char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),
-char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),
-char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),
-char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),
-char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),
-char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),
-char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),
-char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),
-char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),
-char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),
-char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),
-char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),
-char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),
-char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),
-char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),
-char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),
-char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),
-char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),
-char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),
-char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),
-char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),
-char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
-char(102),char(105),char(103),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),
-char(111),char(84),char(104),char(105),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),
-char(104),char(105),char(115),char(80),char(105),char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),
-char(115),char(80),char(105),char(118),char(111),char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),
-char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),
-char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),
-char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),
-char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),
-char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),
-char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
-char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),
-char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),
-char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),
-char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),
-char(111),char(115),char(86),char(97),char(114),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),
-char(115),char(91),char(55),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),
-char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),
-char(105),char(110),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),
-char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),
-char(105),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),
-char(95),char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),
-char(95),char(108),char(105),char(110),char(107),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),
-char(109),char(101),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),
-char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),
-char(111),char(114),char(108),char(100),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),
-char(111),char(114),char(108),char(100),char(79),char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),
-char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),
-char(97),char(115),char(101),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),
-char(95),char(98),char(97),char(115),char(101),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),
-char(97),char(115),char(115),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),
-char(97),char(115),char(101),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),
-char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),
-char(108),char(105),char(110),char(107),char(0),char(0),char(0),char(0),char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),
-char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),
-char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),
-char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),
-char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),
-char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),
-char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),
-char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),
-char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),
-char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(114),char(101),char(118),char(82),char(72),char(83),char(91),char(52),char(93),
+char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),
+char(100),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),
+char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
+char(97),char(114),char(116),char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(80),char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
+char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),
+char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),
+char(116),char(70),char(108),char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),
+char(114),char(97),char(108),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
+char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),
+char(108),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
+char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),
+char(110),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),
+char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),
+char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),
+char(101),char(84),char(105),char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),
+char(80),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),
+char(65),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),
+char(110),char(100),char(101),char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),
+char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),
+char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),
+char(111),char(100),char(121),char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),
+char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),
+char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),
+char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),
+char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),
+char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),
+char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),
+char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),
+char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),
+char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),
+char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),
+char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
+char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),
+char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
+char(99),char(116),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),
+char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),
+char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),
+char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),
+char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),
+char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),
+char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),
+char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),
+char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
+char(116),char(101),char(114),char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(105),char(108),char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),
+char(100),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),
+char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),
+char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),
+char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),
+char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),
+char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),
+char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(114),char(116),char(105),char(99),char(117),char(108),
+char(97),char(116),char(101),char(100),char(87),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),
+char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),
+char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
+char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),
+char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),
+char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),
+char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),
+char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
+char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),
+char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),
+char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),
+char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),
+char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),
+char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
+char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),
+char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),
+char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),
+char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),
+char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),
+char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),
+char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
+char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),
+char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),
+char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),
+char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),
+char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),
+char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),
+char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),
+char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
+char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),
+char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),
+char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),
+char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),
+char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),
+char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),
+char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),
+char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),
+char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),
+char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),
+char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),
+char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),
+char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),
+char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),
+char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),
+char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),
+char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
+char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),
+char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),
+char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),
+char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),
+char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),
+char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(97),char(120),char(77),
+char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
+char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),
+char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
+char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
+char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
+char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),
+char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),
+char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),
+char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),
+char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),
+char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),char(114),
+char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),char(101),char(114),char(0),char(109),char(95),
+char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(66),char(0),char(109),char(95),
+char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),
+char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),
+char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),
+char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),
+char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),
+char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),
+char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),
+char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),
+char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),
+char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),
+char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),
+char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),
+char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),
+char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),
+char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),
+char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),
+char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),
+char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
+char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),
+char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),
+char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
+char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),
+char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),
+char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
+char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),
+char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),
+char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),
+char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),
+char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),
+char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),
+char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),
+char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),
+char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),
+char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),
+char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),
+char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),
+char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),
+char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),
+char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
+char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),
+char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),
+char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),
+char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
+char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),
+char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),
+char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
+char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),
+char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),
+char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),
+char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),
+char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),
+char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),
+char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),
+char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),
+char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),
+char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),
+char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
+char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),
+char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(109),
+char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),char(111),char(84),char(104),char(105),char(115),
+char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),char(104),char(105),char(115),char(80),char(105),
+char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),char(115),char(80),char(105),char(118),char(111),
+char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(106),
+char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),
+char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),
+char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),
+char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),
+char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),
+char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
+char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110),char(100),char(101),char(120),
+char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115),char(86),char(97),char(114),
+char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91),char(55),char(93),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
+char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),
+char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),char(109),char(101),char(0),char(42),char(109),
+char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),char(109),char(95),char(112),char(97),char(100),
+char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(80),
+char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(79),
+char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(76),char(105),char(110),
+char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),
+char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(42),
+char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(67),char(111),
+char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),char(68),char(97),char(116),char(97),char(0),
+char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(0),
+char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),
+char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),
+char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),
+char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),
+char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),
+char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
+char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),
+char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),
+char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),
+char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),
-char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),
-char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
-char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),
-char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),
-char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),
-char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),
-char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),
-char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),
-char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),
-char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
-char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),
-char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),
-char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),
-char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),
-char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),
+char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),
+char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),
+char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
+char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),
+char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),
-char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),
-char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),
-char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),
-char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),
-char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),
-char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),
-char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),
-char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),
-char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
-char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
-char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
-char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),
-char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),
+char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),
+char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),
+char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),
+char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),
+char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),
+char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),
+char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),
+char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),
+char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),
+char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
+char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
+char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),
-char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
-char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
+char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),
+char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
+char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),
+char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),
-char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),
-char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
-char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),
-char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),
-char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),
-char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),
-char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),
-char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),
-char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),
-char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
-char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
-char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),
-char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),
-char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),
-char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),
-char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),
-char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),
-char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
-char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
-char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),
-char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),
-char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),
-char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),
-char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0),char(32),char(0),char(16),char(0),
-char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0),
-char(-124),char(0),char(12),char(0),char(52),char(0),char(52),char(0),char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),
-char(32),char(0),char(28),char(0),char(60),char(0),char(56),char(0),char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(60),char(0),
-char(16),char(0),char(-16),char(5),char(-24),char(1),char(56),char(3),char(16),char(1),char(64),char(0),char(68),char(0),char(-104),char(0),char(88),char(0),char(-72),char(0),
-char(104),char(0),char(-8),char(1),char(-72),char(3),char(8),char(0),char(52),char(0),char(52),char(0),char(0),char(0),char(68),char(0),char(84),char(0),char(-124),char(0),
-char(116),char(0),char(92),char(1),char(-36),char(0),char(-116),char(1),char(124),char(1),char(-44),char(0),char(-4),char(0),char(-52),char(1),char(92),char(1),char(116),char(2),
-char(-124),char(2),char(-76),char(4),char(-52),char(0),char(108),char(1),char(92),char(0),char(-116),char(0),char(16),char(0),char(100),char(0),char(20),char(0),char(36),char(0),
-char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0),char(92),char(1),char(104),char(0),char(-68),char(1),char(112),char(3),char(-56),char(1),char(-68),char(0),
-char(100),char(0),char(28),char(1),char(-12),char(1),char(0),char(0),char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),
-char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),
-char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),
-char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),
-char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),
-char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),
-char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),
-char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),
-char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
-char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),
-char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),
-char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),
-char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),
-char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),
-char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
-char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),
-char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),
-char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),
-char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),
-char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),
-char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),
-char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),
-char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),
-char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),
-char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),
-char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),
-char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),
-char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),
-char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),
-char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),
-char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),
-char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),
-char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),
-char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),
-char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),
-char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),
-char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(38),char(0),
-char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),
-char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),
-char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),char(8),char(0),char(108),char(0),char(4),char(0),char(109),char(0),char(4),char(0),char(110),char(0),
-char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),char(4),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),
-char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),
-char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),
-char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),char(4),char(0),char(-128),char(0),char(8),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),
-char(4),char(0),char(44),char(0),char(48),char(0),char(-125),char(0),char(48),char(0),char(-124),char(0),char(49),char(0),char(38),char(0),char(13),char(0),char(96),char(0),
-char(13),char(0),char(97),char(0),char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),
-char(13),char(0),char(102),char(0),char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),
-char(7),char(0),char(107),char(0),char(7),char(0),char(108),char(0),char(4),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),
-char(4),char(0),char(112),char(0),char(4),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),
-char(7),char(0),char(117),char(0),char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),
-char(7),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),
-char(4),char(0),char(127),char(0),char(4),char(0),char(-128),char(0),char(7),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(4),char(0),char(44),char(0),
-char(50),char(0),char(-125),char(0),char(50),char(0),char(-124),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
-char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-123),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
-char(13),char(0),char(-122),char(0),char(14),char(0),char(-121),char(0),char(4),char(0),char(-120),char(0),char(0),char(0),char(-119),char(0),char(48),char(0),char(29),char(0),
-char(9),char(0),char(-118),char(0),char(9),char(0),char(-117),char(0),char(27),char(0),char(-116),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-115),char(0),
-char(20),char(0),char(-114),char(0),char(14),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(8),char(0),char(-126),char(0),
-char(8),char(0),char(-110),char(0),char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),
-char(8),char(0),char(-105),char(0),char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),
-char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),
-char(4),char(0),char(-95),char(0),char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(50),char(0),char(29),char(0),
-char(9),char(0),char(-118),char(0),char(9),char(0),char(-117),char(0),char(27),char(0),char(-116),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-115),char(0),
-char(19),char(0),char(-114),char(0),char(13),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(7),char(0),char(-126),char(0),
-char(7),char(0),char(-110),char(0),char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),
-char(7),char(0),char(-105),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),
-char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),
-char(4),char(0),char(-95),char(0),char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(53),char(0),char(22),char(0),
-char(8),char(0),char(-91),char(0),char(8),char(0),char(-90),char(0),char(8),char(0),char(-109),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-105),char(0),
-char(8),char(0),char(-88),char(0),char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),
-char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),
-char(8),char(0),char(-78),char(0),char(4),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),
-char(4),char(0),char(-73),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-91),char(0),char(7),char(0),char(-90),char(0),
-char(7),char(0),char(-109),char(0),char(7),char(0),char(-89),char(0),char(7),char(0),char(-105),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),
+char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),
+char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),
+char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),
+char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),
+char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),
+char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),
+char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),
+char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),
+char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),
+char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),
+char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
+char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
+char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),
+char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
+char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),
+char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),
+char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),
+char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
+char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0),char(-124),char(0),char(12),char(0),char(52),char(0),char(52),char(0),
+char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(32),char(0),char(28),char(0),char(60),char(0),char(56),char(0),
+char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(60),char(0),char(16),char(0),char(16),char(6),char(-24),char(1),char(72),char(3),
+char(16),char(1),char(64),char(0),char(68),char(0),char(-96),char(0),char(88),char(0),char(-64),char(0),char(104),char(0),char(-8),char(1),char(-72),char(3),char(8),char(0),
+char(52),char(0),char(52),char(0),char(0),char(0),char(68),char(0),char(84),char(0),char(-124),char(0),char(116),char(0),char(92),char(1),char(-36),char(0),char(-116),char(1),
+char(124),char(1),char(-44),char(0),char(-4),char(0),char(-52),char(1),char(92),char(1),char(116),char(2),char(-124),char(2),char(-76),char(4),char(-52),char(0),char(108),char(1),
+char(92),char(0),char(-116),char(0),char(16),char(0),char(100),char(0),char(20),char(0),char(36),char(0),char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0),
+char(92),char(1),char(104),char(0),char(-68),char(1),char(112),char(3),char(-56),char(1),char(-68),char(0),char(100),char(0),char(28),char(1),char(-12),char(1),char(0),char(0),
+char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),
+char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),
+char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),
+char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),
+char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
+char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),
+char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
+char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
+char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
+char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
+char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),
+char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
+char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),
+char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
+char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
+char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),
+char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),
+char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
+char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
+char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),
+char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),
+char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),
+char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
+char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),
+char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),
+char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),
+char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),
+char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
+char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
+char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
+char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),
+char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),
+char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),
+char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),
+char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),
+char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),
+char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(39),char(0),char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),
+char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),
+char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),
+char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),
+char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),
+char(8),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(48),char(0),char(-124),char(0),char(48),char(0),char(-123),char(0),char(49),char(0),char(39),char(0),char(13),char(0),char(96),char(0),char(13),char(0),char(97),char(0),
+char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),char(13),char(0),char(102),char(0),
+char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),char(7),char(0),char(107),char(0),
+char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),char(7),char(0),char(117),char(0),
+char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),char(7),char(0),char(122),char(0),
+char(7),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(7),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(50),char(0),char(-124),char(0),char(50),char(0),char(-123),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
+char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-122),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
+char(13),char(0),char(-121),char(0),char(14),char(0),char(-120),char(0),char(4),char(0),char(-119),char(0),char(0),char(0),char(-118),char(0),char(48),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-114),char(0),
+char(20),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),char(8),char(0),char(-125),char(0),
+char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),char(8),char(0),char(-105),char(0),
+char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(50),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-114),char(0),
+char(19),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(13),char(0),char(-110),char(0),char(7),char(0),char(-125),char(0),
+char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),char(7),char(0),char(-105),char(0),
+char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(53),char(0),char(23),char(0),
+char(8),char(0),char(-90),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-88),char(0),char(8),char(0),char(-104),char(0),
+char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),
+char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),
+char(8),char(0),char(-77),char(0),char(8),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),
+char(4),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-90),char(0),
+char(7),char(0),char(-89),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-87),char(0),
char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0),
-char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(4),char(0),char(-77),char(0),
-char(4),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(0),char(0),char(37),char(0),
-char(55),char(0),char(2),char(0),char(53),char(0),char(-72),char(0),char(14),char(0),char(-71),char(0),char(56),char(0),char(2),char(0),char(54),char(0),char(-72),char(0),
-char(13),char(0),char(-71),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-70),char(0),char(17),char(0),char(-69),char(0),char(13),char(0),char(-68),char(0),
-char(13),char(0),char(-67),char(0),char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-71),char(0),char(13),char(0),char(-64),char(0),
-char(13),char(0),char(-63),char(0),char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(7),char(0),char(-59),char(0),
-char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),
-char(7),char(0),char(-53),char(0),char(7),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(58),char(0),char(22),char(0),char(48),char(0),char(-70),char(0),
-char(18),char(0),char(-69),char(0),char(14),char(0),char(-68),char(0),char(14),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),
-char(14),char(0),char(-71),char(0),char(14),char(0),char(-64),char(0),char(14),char(0),char(-63),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),
-char(8),char(0),char(-60),char(0),char(8),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),
-char(8),char(0),char(-55),char(0),char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),
-char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(60),char(0),char(13),char(0),
-char(57),char(0),char(-48),char(0),char(57),char(0),char(-47),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),
-char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),char(7),char(0),char(-43),char(0),char(7),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),
-char(4),char(0),char(-40),char(0),char(7),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(61),char(0),char(13),char(0),char(62),char(0),char(-48),char(0),
-char(62),char(0),char(-47),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),char(4),char(0),char(-45),char(0),
-char(4),char(0),char(-44),char(0),char(7),char(0),char(-43),char(0),char(7),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),char(4),char(0),char(-40),char(0),
-char(7),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-48),char(0),char(58),char(0),char(-47),char(0),
-char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),
-char(8),char(0),char(-43),char(0),char(8),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),char(4),char(0),char(-40),char(0),char(8),char(0),char(-39),char(0),
-char(4),char(0),char(-38),char(0),char(0),char(0),char(-37),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-36),char(0),char(13),char(0),char(-35),char(0),
-char(13),char(0),char(-34),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0),char(14),char(0),char(-34),char(0),
-char(66),char(0),char(3),char(0),char(61),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0),char(14),char(0),char(-34),char(0),char(67),char(0),char(13),char(0),
-char(61),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),
-char(4),char(0),char(-29),char(0),char(7),char(0),char(-28),char(0),char(7),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),
-char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(68),char(0),char(13),char(0),char(61),char(0),char(-36),char(0),
-char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
-char(7),char(0),char(-28),char(0),char(7),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
-char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),
-char(20),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(8),char(0),char(-28),char(0),
-char(8),char(0),char(-27),char(0),char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),
-char(8),char(0),char(-22),char(0),char(0),char(0),char(-21),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),
-char(20),char(0),char(-32),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-19),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-24),char(0),
-char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),char(8),char(0),char(-90),char(0),char(71),char(0),char(11),char(0),char(61),char(0),char(-36),char(0),
-char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-19),char(0),char(7),char(0),char(-18),char(0),
-char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-90),char(0),char(0),char(0),char(21),char(0),
-char(72),char(0),char(9),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(13),char(0),char(-17),char(0),
-char(13),char(0),char(-16),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),
-char(73),char(0),char(9),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(14),char(0),char(-17),char(0),
-char(14),char(0),char(-16),char(0),char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),
-char(74),char(0),char(5),char(0),char(72),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0),char(7),char(0),char(-8),char(0),
-char(7),char(0),char(-7),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(8),char(0),char(-9),char(0),
-char(8),char(0),char(-8),char(0),char(8),char(0),char(-7),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),
-char(19),char(0),char(-32),char(0),char(13),char(0),char(-17),char(0),char(13),char(0),char(-16),char(0),char(13),char(0),char(-6),char(0),char(13),char(0),char(-5),char(0),
-char(13),char(0),char(-4),char(0),char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),
-char(13),char(0),char(1),char(1),char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(0),char(0),char(5),char(1),
-char(0),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(-21),char(0),
-char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(10),char(1),char(13),char(0),char(11),char(1),char(13),char(0),char(12),char(1),
-char(13),char(0),char(13),char(1),char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),
-char(13),char(0),char(18),char(1),char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(0),char(0),char(21),char(1),char(0),char(0),char(22),char(1),
-char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(4),char(0),char(26),char(1),char(77),char(0),char(41),char(0),
-char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(14),char(0),char(-17),char(0),char(14),char(0),char(-16),char(0),
-char(14),char(0),char(-6),char(0),char(14),char(0),char(-5),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),
-char(14),char(0),char(-1),char(0),char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),
-char(14),char(0),char(4),char(1),char(0),char(0),char(5),char(1),char(0),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),
-char(0),char(0),char(9),char(1),char(0),char(0),char(-21),char(0),char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(10),char(1),
-char(14),char(0),char(11),char(1),char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),
-char(14),char(0),char(16),char(1),char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),
-char(0),char(0),char(21),char(1),char(0),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),
-char(4),char(0),char(26),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),
-char(7),char(0),char(-17),char(0),char(7),char(0),char(-16),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),
-char(4),char(0),char(-12),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),
-char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),
-char(4),char(0),char(-12),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-36),char(0),char(13),char(0),char(27),char(1),char(13),char(0),char(28),char(1),
-char(7),char(0),char(29),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-36),char(0),char(14),char(0),char(27),char(1),
-char(14),char(0),char(28),char(1),char(8),char(0),char(29),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1),
-char(7),char(0),char(32),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(33),char(1),char(13),char(0),char(34),char(1),
-char(13),char(0),char(35),char(1),char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(7),char(0),char(-60),char(0),
-char(7),char(0),char(39),char(1),char(4),char(0),char(40),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),char(82),char(0),char(33),char(1),
-char(4),char(0),char(41),char(1),char(7),char(0),char(42),char(1),char(4),char(0),char(43),char(1),char(85),char(0),char(4),char(0),char(13),char(0),char(38),char(1),
-char(82),char(0),char(33),char(1),char(4),char(0),char(44),char(1),char(7),char(0),char(45),char(1),char(86),char(0),char(7),char(0),char(13),char(0),char(46),char(1),
-char(82),char(0),char(33),char(1),char(4),char(0),char(47),char(1),char(7),char(0),char(48),char(1),char(7),char(0),char(49),char(1),char(7),char(0),char(50),char(1),
-char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(51),char(1),char(13),char(0),char(49),char(1),char(13),char(0),char(52),char(1),
-char(62),char(0),char(53),char(1),char(4),char(0),char(54),char(1),char(7),char(0),char(50),char(1),char(88),char(0),char(26),char(0),char(4),char(0),char(55),char(1),
-char(7),char(0),char(56),char(1),char(7),char(0),char(-90),char(0),char(7),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(59),char(1),
-char(7),char(0),char(60),char(1),char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),
-char(7),char(0),char(65),char(1),char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),
-char(7),char(0),char(70),char(1),char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),
-char(4),char(0),char(75),char(1),char(4),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(-100),char(0),
-char(89),char(0),char(12),char(0),char(17),char(0),char(79),char(1),char(17),char(0),char(80),char(1),char(17),char(0),char(81),char(1),char(13),char(0),char(82),char(1),
-char(13),char(0),char(83),char(1),char(7),char(0),char(84),char(1),char(4),char(0),char(85),char(1),char(4),char(0),char(86),char(1),char(4),char(0),char(87),char(1),
-char(4),char(0),char(88),char(1),char(7),char(0),char(48),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),char(19),char(0),char(89),char(1),
-char(17),char(0),char(90),char(1),char(17),char(0),char(91),char(1),char(13),char(0),char(82),char(1),char(13),char(0),char(92),char(1),char(13),char(0),char(93),char(1),
-char(13),char(0),char(94),char(1),char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(4),char(0),char(97),char(1),char(7),char(0),char(98),char(1),
-char(4),char(0),char(99),char(1),char(4),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(7),char(0),char(102),char(1),char(7),char(0),char(103),char(1),
-char(4),char(0),char(104),char(1),char(4),char(0),char(105),char(1),char(7),char(0),char(106),char(1),char(7),char(0),char(107),char(1),char(7),char(0),char(108),char(1),
-char(7),char(0),char(109),char(1),char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(4),char(0),char(112),char(1),char(4),char(0),char(113),char(1),
-char(4),char(0),char(114),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(115),char(1),char(9),char(0),char(116),char(1),char(13),char(0),char(117),char(1),
-char(7),char(0),char(118),char(1),char(7),char(0),char(-86),char(0),char(7),char(0),char(119),char(1),char(4),char(0),char(120),char(1),char(13),char(0),char(121),char(1),
-char(4),char(0),char(122),char(1),char(4),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(53),char(0),char(92),char(0),char(19),char(0),
-char(50),char(0),char(-70),char(0),char(89),char(0),char(125),char(1),char(82),char(0),char(126),char(1),char(83),char(0),char(127),char(1),char(84),char(0),char(-128),char(1),
-char(85),char(0),char(-127),char(1),char(86),char(0),char(-126),char(1),char(87),char(0),char(-125),char(1),char(90),char(0),char(-124),char(1),char(91),char(0),char(-123),char(1),
-char(4),char(0),char(-122),char(1),char(4),char(0),char(100),char(1),char(4),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(-119),char(1),
-char(4),char(0),char(-118),char(1),char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(88),char(0),char(-115),char(1),char(93),char(0),char(28),char(0),
-char(16),char(0),char(-114),char(1),char(14),char(0),char(-113),char(1),char(14),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),
-char(14),char(0),char(-109),char(1),char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),
-char(8),char(0),char(-104),char(1),char(4),char(0),char(-103),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),
-char(8),char(0),char(-100),char(1),char(8),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),
-char(8),char(0),char(-95),char(1),char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(0),char(0),char(-91),char(1),
-char(0),char(0),char(-90),char(1),char(48),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(94),char(0),char(28),char(0),char(15),char(0),char(-114),char(1),
-char(13),char(0),char(-113),char(1),char(13),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),
-char(13),char(0),char(-108),char(1),char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(4),char(0),char(-102),char(1),
-char(7),char(0),char(-104),char(1),char(4),char(0),char(-103),char(1),char(4),char(0),char(124),char(1),char(7),char(0),char(-100),char(1),char(7),char(0),char(-99),char(1),
-char(7),char(0),char(-98),char(1),char(4),char(0),char(-101),char(1),char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(7),char(0),char(-95),char(1),
-char(7),char(0),char(-94),char(1),char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(0),char(0),char(-91),char(1),char(0),char(0),char(-90),char(1),
-char(50),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-87),char(1),char(16),char(0),char(-86),char(1),
-char(14),char(0),char(-85),char(1),char(14),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(8),char(0),char(-82),char(1),char(4),char(0),char(-121),char(1),
-char(0),char(0),char(37),char(0),char(0),char(0),char(-81),char(1),char(93),char(0),char(-128),char(1),char(48),char(0),char(-80),char(1),char(96),char(0),char(10),char(0),
-char(13),char(0),char(-87),char(1),char(15),char(0),char(-86),char(1),char(13),char(0),char(-85),char(1),char(13),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),
-char(7),char(0),char(-82),char(1),char(4),char(0),char(-121),char(1),char(0),char(0),char(-81),char(1),char(94),char(0),char(-128),char(1),char(50),char(0),char(-80),char(1),
-char(97),char(0),char(4),char(0),char(50),char(0),char(-79),char(1),char(96),char(0),char(-78),char(1),char(4),char(0),char(-77),char(1),char(0),char(0),char(37),char(0),
-char(98),char(0),char(4),char(0),char(48),char(0),char(-79),char(1),char(95),char(0),char(-78),char(1),char(4),char(0),char(-77),char(1),char(0),char(0),char(37),char(0),
-};
+char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
+char(7),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(4),char(0),char(-72),char(0),
+char(4),char(0),char(-71),char(0),char(55),char(0),char(2),char(0),char(53),char(0),char(-70),char(0),char(14),char(0),char(-69),char(0),char(56),char(0),char(2),char(0),
+char(54),char(0),char(-70),char(0),char(13),char(0),char(-69),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-68),char(0),char(17),char(0),char(-67),char(0),
+char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0),char(13),char(0),char(-69),char(0),
+char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(13),char(0),char(-60),char(0),char(13),char(0),char(-59),char(0),char(7),char(0),char(-58),char(0),
+char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),
+char(7),char(0),char(-52),char(0),char(7),char(0),char(-51),char(0),char(7),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(58),char(0),char(22),char(0),
+char(48),char(0),char(-68),char(0),char(18),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),char(14),char(0),char(-64),char(0),
+char(14),char(0),char(-63),char(0),char(14),char(0),char(-69),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),char(14),char(0),char(-60),char(0),
+char(14),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-55),char(0),
+char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(8),char(0),char(-51),char(0),char(8),char(0),char(-50),char(0),
+char(4),char(0),char(-49),char(0),char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-48),char(0),char(4),char(0),char(-47),char(0),
+char(60),char(0),char(13),char(0),char(57),char(0),char(-46),char(0),char(57),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),
+char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),
+char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(61),char(0),char(13),char(0),
+char(62),char(0),char(-46),char(0),char(62),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),
+char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
+char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-46),char(0),
+char(58),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),
+char(4),char(0),char(-42),char(0),char(8),char(0),char(-41),char(0),char(8),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),
+char(8),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),
+char(13),char(0),char(-33),char(0),char(13),char(0),char(-32),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),
+char(14),char(0),char(-32),char(0),char(66),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),char(14),char(0),char(-32),char(0),
+char(67),char(0),char(13),char(0),char(61),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
+char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
+char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(68),char(0),char(13),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),
+char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),
+char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),
+char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),
+char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(0),char(0),char(-19),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),
+char(8),char(0),char(-22),char(0),char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-89),char(0),char(71),char(0),char(11),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(7),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0),
+char(7),char(0),char(-16),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-89),char(0),
+char(0),char(0),char(21),char(0),char(72),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),
+char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(73),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),
+char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(74),char(0),char(5),char(0),char(72),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),
+char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),
+char(8),char(0),char(-7),char(0),char(8),char(0),char(-6),char(0),char(8),char(0),char(-5),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-34),char(0),
+char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-4),char(0),
+char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),char(13),char(0),char(1),char(1),
+char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(13),char(0),char(5),char(1),char(13),char(0),char(6),char(1),
+char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),
+char(0),char(0),char(-19),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(13),char(0),char(12),char(1),char(13),char(0),char(13),char(1),
+char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),char(13),char(0),char(18),char(1),
+char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(13),char(0),char(21),char(1),char(13),char(0),char(22),char(1),char(0),char(0),char(23),char(1),
+char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),
+char(77),char(0),char(41),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(14),char(0),char(-15),char(0),
+char(14),char(0),char(-14),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),char(14),char(0),char(-1),char(0),
+char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),char(14),char(0),char(4),char(1),
+char(14),char(0),char(5),char(1),char(14),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),
+char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),char(0),char(0),char(-19),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),
+char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),char(14),char(0),char(16),char(1),
+char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),char(14),char(0),char(21),char(1),
+char(14),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),
+char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),
+char(19),char(0),char(-30),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),char(7),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),
+char(20),char(0),char(-30),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(8),char(0),char(-13),char(0),char(8),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-34),char(0),char(13),char(0),char(29),char(1),
+char(13),char(0),char(30),char(1),char(7),char(0),char(31),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-34),char(0),
+char(14),char(0),char(29),char(1),char(14),char(0),char(30),char(1),char(8),char(0),char(31),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(32),char(1),
+char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(35),char(1),
+char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(13),char(0),char(39),char(1),char(13),char(0),char(40),char(1),
+char(7),char(0),char(-58),char(0),char(7),char(0),char(41),char(1),char(4),char(0),char(42),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),
+char(82),char(0),char(35),char(1),char(4),char(0),char(43),char(1),char(7),char(0),char(44),char(1),char(4),char(0),char(45),char(1),char(85),char(0),char(4),char(0),
+char(13),char(0),char(40),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(46),char(1),char(7),char(0),char(47),char(1),char(86),char(0),char(7),char(0),
+char(13),char(0),char(48),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(49),char(1),char(7),char(0),char(50),char(1),char(7),char(0),char(51),char(1),
+char(7),char(0),char(52),char(1),char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(53),char(1),char(13),char(0),char(51),char(1),
+char(13),char(0),char(54),char(1),char(62),char(0),char(55),char(1),char(4),char(0),char(56),char(1),char(7),char(0),char(52),char(1),char(88),char(0),char(26),char(0),
+char(4),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(-89),char(0),char(7),char(0),char(59),char(1),char(7),char(0),char(60),char(1),
+char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1),
+char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1),
+char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),char(7),char(0),char(75),char(1),
+char(7),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(79),char(1),char(4),char(0),char(80),char(1),
+char(4),char(0),char(-99),char(0),char(89),char(0),char(12),char(0),char(17),char(0),char(81),char(1),char(17),char(0),char(82),char(1),char(17),char(0),char(83),char(1),
+char(13),char(0),char(84),char(1),char(13),char(0),char(85),char(1),char(7),char(0),char(86),char(1),char(4),char(0),char(87),char(1),char(4),char(0),char(88),char(1),
+char(4),char(0),char(89),char(1),char(4),char(0),char(90),char(1),char(7),char(0),char(50),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),
+char(19),char(0),char(91),char(1),char(17),char(0),char(92),char(1),char(17),char(0),char(93),char(1),char(13),char(0),char(84),char(1),char(13),char(0),char(94),char(1),
+char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(13),char(0),char(97),char(1),char(13),char(0),char(98),char(1),char(4),char(0),char(99),char(1),
+char(7),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(103),char(1),char(7),char(0),char(104),char(1),
+char(7),char(0),char(105),char(1),char(4),char(0),char(106),char(1),char(4),char(0),char(107),char(1),char(7),char(0),char(108),char(1),char(7),char(0),char(109),char(1),
+char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(7),char(0),char(112),char(1),char(7),char(0),char(113),char(1),char(4),char(0),char(114),char(1),
+char(4),char(0),char(115),char(1),char(4),char(0),char(116),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(117),char(1),char(9),char(0),char(118),char(1),
+char(13),char(0),char(119),char(1),char(7),char(0),char(120),char(1),char(7),char(0),char(-85),char(0),char(7),char(0),char(121),char(1),char(4),char(0),char(122),char(1),
+char(13),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(125),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(53),char(0),
+char(92),char(0),char(19),char(0),char(50),char(0),char(-68),char(0),char(89),char(0),char(127),char(1),char(82),char(0),char(-128),char(1),char(83),char(0),char(-127),char(1),
+char(84),char(0),char(-126),char(1),char(85),char(0),char(-125),char(1),char(86),char(0),char(-124),char(1),char(87),char(0),char(-123),char(1),char(90),char(0),char(-122),char(1),
+char(91),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(-119),char(1),char(4),char(0),char(-118),char(1),
+char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(4),char(0),char(-115),char(1),char(4),char(0),char(-114),char(1),char(88),char(0),char(-113),char(1),
+char(93),char(0),char(28),char(0),char(16),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),char(14),char(0),char(-109),char(1),
+char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),char(14),char(0),char(-104),char(1),
+char(14),char(0),char(-103),char(1),char(8),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(-100),char(1),
+char(4),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),char(8),char(0),char(-95),char(1),
+char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(8),char(0),char(-91),char(1),char(8),char(0),char(-90),char(1),
+char(0),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(48),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(94),char(0),char(28),char(0),
+char(15),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),char(13),char(0),char(-108),char(1),
+char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(13),char(0),char(-104),char(1),char(13),char(0),char(-103),char(1),
+char(4),char(0),char(-100),char(1),char(7),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(7),char(0),char(-98),char(1),
+char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(4),char(0),char(-99),char(1),char(7),char(0),char(-95),char(1),char(7),char(0),char(-94),char(1),
+char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(7),char(0),char(-91),char(1),char(7),char(0),char(-90),char(1),char(0),char(0),char(-89),char(1),
+char(0),char(0),char(-88),char(1),char(50),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-85),char(1),
+char(16),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(14),char(0),char(-82),char(1),char(14),char(0),char(-81),char(1),char(8),char(0),char(-80),char(1),
+char(4),char(0),char(-119),char(1),char(0),char(0),char(37),char(0),char(0),char(0),char(-79),char(1),char(93),char(0),char(-126),char(1),char(48),char(0),char(-78),char(1),
+char(96),char(0),char(10),char(0),char(13),char(0),char(-85),char(1),char(15),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),char(13),char(0),char(-82),char(1),
+char(13),char(0),char(-81),char(1),char(7),char(0),char(-80),char(1),char(4),char(0),char(-119),char(1),char(0),char(0),char(-79),char(1),char(94),char(0),char(-126),char(1),
+char(50),char(0),char(-78),char(1),char(97),char(0),char(4),char(0),char(50),char(0),char(-77),char(1),char(96),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),char(98),char(0),char(4),char(0),char(48),char(0),char(-77),char(1),char(95),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),};
int sBulletDNAlen= sizeof(sBulletDNAstr);
-
-// clang-format on
diff --git a/thirdparty/bullet/LinearMath/btSerializer.h b/thirdparty/bullet/LinearMath/btSerializer.h
index ba34441615..2ee712047f 100644
--- a/thirdparty/bullet/LinearMath/btSerializer.h
+++ b/thirdparty/bullet/LinearMath/btSerializer.h
@@ -481,7 +481,7 @@ public:
buffer[9] = '2';
buffer[10] = '8';
- buffer[11] = '8';
+ buffer[11] = '9';
}
virtual void startSerialization()
diff --git a/thirdparty/bullet/LinearMath/btSerializer64.cpp b/thirdparty/bullet/LinearMath/btSerializer64.cpp
index cf281cdb36..6c4bc7031f 100644
--- a/thirdparty/bullet/LinearMath/btSerializer64.cpp
+++ b/thirdparty/bullet/LinearMath/btSerializer64.cpp
@@ -1,6 +1,5 @@
-// clang-format off
char sBulletDNAstr64[]= {
-char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-76),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-74),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
@@ -87,605 +86,607 @@ char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),cha
char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(68),char(105),char(115),char(116),
char(97),char(110),char(99),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(91),char(52),char(93),char(0),char(109),char(95),
-char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),
-char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(97),char(114),char(116),
-char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
-char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),
-char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),char(116),char(70),char(108),
-char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(65),
-char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),
-char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(65),char(112),char(112),
-char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(50),char(91),
-char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),
-char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(50),char(91),
-char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),
-char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
-char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),
-char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
-char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),char(77),char(91),char(52),
-char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),char(101),char(84),char(105),
-char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),char(80),char(111),char(105),
-char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(65),char(0),char(109),
-char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),char(110),char(100),char(101),
-char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),
-char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),
-char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),char(101),char(115),char(115),
-char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),
-char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),char(97),char(99),char(116),
-char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),
-char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(117),char(110),char(115),
-char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),char(80),char(116),char(114),
-char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),
-char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),char(95),char(98),char(114),
-char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),char(95),char(99),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),char(111),char(111),char(116),
-char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),char(119),char(111),char(114),
-char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),
-char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
-char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(76),char(105),char(110),
-char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),
-char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),
-char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),
-char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(84),
-char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(111),char(108),
-char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
-char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
-char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),
-char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),
-char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),
-char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
-char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),
-char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),
-char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),
-char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
-char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),
-char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),
-char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),char(116),char(101),char(114),
-char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
-char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),char(100),char(0),char(109),
-char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(116),char(105),char(109),
-char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),char(101),char(100),char(117),
-char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),char(0),char(109),char(95),
-char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),char(97),char(116),char(105),
-char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
-char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),
-char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),
-char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),
-char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),
-char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),
-char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),
-char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),
-char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),
-char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),
-char(73),char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),
-char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),
-char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),
-char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),
-char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),
-char(101),char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),
-char(105),char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),
-char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),
-char(101),char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),
-char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),
-char(103),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),
-char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),
-char(76),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),
-char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),
-char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),
-char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),
-char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),
-char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),
-char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),
-char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),
-char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),
-char(65),char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),
-char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),
-char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),
-char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),
-char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),
-char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),
-char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),
-char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),
-char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),
-char(108),char(101),char(100),char(0),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),
-char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),
-char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),
-char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),
-char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),
-char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),
-char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),
-char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),
-char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),
-char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),
-char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),
-char(91),char(52),char(93),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),
-char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),
-char(110),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),
-char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),
-char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),
-char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),
-char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),
-char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),
-char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
-char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),
-char(110),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),
-char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),
-char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
-char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),
-char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
-char(114),char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),
-char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),
-char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
-char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),
-char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),
-char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),
-char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),
-char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),
-char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
-char(108),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(77),char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),
-char(116),char(111),char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),
-char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(77),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
-char(108),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
-char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),
-char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),
-char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),
-char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
-char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),
-char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),
-char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),
-char(101),char(114),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),
-char(110),char(66),char(0),char(109),char(95),char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),
-char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
-char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),
-char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),
-char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),
-char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),
-char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),
-char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),
-char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),
-char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),
-char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),
-char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),
-char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),
-char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),
-char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),
-char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),
-char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),
-char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),
-char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),
-char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),
-char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),
-char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),
-char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),
-char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),
-char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),
-char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),
-char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
-char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
-char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),
-char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),
-char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),
-char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),
-char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),
-char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),
-char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),
-char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
-char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
-char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
-char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),
-char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),
-char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),
-char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),
-char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),
-char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),
-char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),
-char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),
-char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),
-char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),
-char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),
-char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),
-char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),
-char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),
-char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),
-char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),
-char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),
-char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),
-char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),
-char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),
-char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),
-char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),
-char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),
-char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),
-char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),
-char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),
-char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),
-char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),
-char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),
-char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),
-char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),
-char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),
-char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),
-char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),
-char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
-char(102),char(105),char(103),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),
-char(111),char(84),char(104),char(105),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),
-char(104),char(105),char(115),char(80),char(105),char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),
-char(115),char(80),char(105),char(118),char(111),char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),
-char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),
-char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),
-char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),
-char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),
-char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),
-char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
-char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),
-char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),
-char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),
-char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),
-char(111),char(115),char(86),char(97),char(114),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),
-char(115),char(91),char(55),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),
-char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),
-char(105),char(110),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),
-char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),
-char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),
-char(105),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),
-char(95),char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),
-char(95),char(108),char(105),char(110),char(107),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),
-char(109),char(101),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),
-char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),
-char(111),char(114),char(108),char(100),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),
-char(111),char(114),char(108),char(100),char(79),char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),
-char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),
-char(97),char(115),char(101),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),
-char(95),char(98),char(97),char(115),char(101),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),
-char(97),char(115),char(115),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),
-char(97),char(115),char(101),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),
-char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),
-char(108),char(105),char(110),char(107),char(0),char(0),char(0),char(0),char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),
-char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),
-char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),
-char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),
-char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),
-char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),
-char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),
-char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),
-char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),
-char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(114),char(101),char(118),char(82),char(72),char(83),char(91),char(52),char(93),
+char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),
+char(100),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),
+char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
+char(97),char(114),char(116),char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(80),char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
+char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),
+char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),
+char(116),char(70),char(108),char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),
+char(114),char(97),char(108),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
+char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),
+char(108),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
+char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),
+char(110),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),
+char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),
+char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),
+char(101),char(84),char(105),char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),
+char(80),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),
+char(65),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),
+char(110),char(100),char(101),char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),
+char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),
+char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),
+char(111),char(100),char(121),char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),
+char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),
+char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),
+char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),
+char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),
+char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),
+char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),
+char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),
+char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),
+char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),
+char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),
+char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
+char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),
+char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
+char(99),char(116),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),
+char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),
+char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),
+char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),
+char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),
+char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),
+char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),
+char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),
+char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
+char(116),char(101),char(114),char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(105),char(108),char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),
+char(100),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),
+char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),
+char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),
+char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),
+char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),
+char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),
+char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(114),char(116),char(105),char(99),char(117),char(108),
+char(97),char(116),char(101),char(100),char(87),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),
+char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),
+char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
+char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),
+char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),
+char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),
+char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),
+char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
+char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),
+char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),
+char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),
+char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),
+char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),
+char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
+char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),
+char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),
+char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),
+char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),
+char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),
+char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),
+char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
+char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),
+char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),
+char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),
+char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),
+char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),
+char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),
+char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),
+char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
+char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),
+char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),
+char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),
+char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),
+char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),
+char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),
+char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),
+char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),
+char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),
+char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),
+char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),
+char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),
+char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),
+char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),
+char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),
+char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),
+char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
+char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),
+char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),
+char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),
+char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),
+char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),
+char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(97),char(120),char(77),
+char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
+char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),
+char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
+char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
+char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
+char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),
+char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),
+char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),
+char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),
+char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),
+char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),char(114),
+char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),char(101),char(114),char(0),char(109),char(95),
+char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(66),char(0),char(109),char(95),
+char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),
+char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),
+char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),
+char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),
+char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),
+char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),
+char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),
+char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),
+char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),
+char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),
+char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),
+char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),
+char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),
+char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),
+char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),
+char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),
+char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),
+char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
+char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),
+char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),
+char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
+char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),
+char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),
+char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
+char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),
+char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),
+char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),
+char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),
+char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),
+char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),
+char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),
+char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),
+char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),
+char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),
+char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),
+char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),
+char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),
+char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),
+char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
+char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),
+char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),
+char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),
+char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
+char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),
+char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),
+char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
+char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),
+char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),
+char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),
+char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),
+char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),
+char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),
+char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),
+char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),
+char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),
+char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),
+char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
+char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),
+char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(109),
+char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),char(111),char(84),char(104),char(105),char(115),
+char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),char(104),char(105),char(115),char(80),char(105),
+char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),char(115),char(80),char(105),char(118),char(111),
+char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(106),
+char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),
+char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),
+char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),
+char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),
+char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),
+char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
+char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110),char(100),char(101),char(120),
+char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115),char(86),char(97),char(114),
+char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91),char(55),char(93),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
+char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),
+char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),char(109),char(101),char(0),char(42),char(109),
+char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),char(109),char(95),char(112),char(97),char(100),
+char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(80),
+char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(79),
+char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(76),char(105),char(110),
+char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),
+char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(42),
+char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(67),char(111),
+char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),char(68),char(97),char(116),char(97),char(0),
+char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(0),
+char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),
+char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),
+char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),
+char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),
+char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),
+char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
+char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),
+char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),
+char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),
+char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),
-char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),
-char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
-char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),
-char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),
-char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),
-char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),
-char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),
-char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),
-char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),
-char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
-char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),
-char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),
-char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),
-char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),
-char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),
+char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),
+char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),
+char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
+char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),
+char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),
-char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),
-char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),
-char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),
-char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),
-char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),
-char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),
-char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),
-char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),
-char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
-char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
-char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
-char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),
-char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),
+char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),
+char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),
+char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),
+char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),
+char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),
+char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),
+char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),
+char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),
+char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),
+char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
+char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
+char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),
-char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
-char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
+char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),
+char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
+char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),
+char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),
-char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),
-char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
-char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),
-char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),
-char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),
-char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),
-char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),
-char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),
-char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),
-char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
-char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
-char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),
-char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),
-char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),
-char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),
-char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),
-char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),
-char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
-char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
-char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),
-char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),
-char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),
-char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),
-char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),
-char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0),char(32),char(0),char(16),char(0),
-char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0),
-char(-112),char(0),char(16),char(0),char(56),char(0),char(56),char(0),char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),
-char(56),char(0),char(32),char(0),char(80),char(0),char(72),char(0),char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(64),char(0),
-char(16),char(0),char(-8),char(5),char(-8),char(1),char(64),char(3),char(32),char(1),char(72),char(0),char(80),char(0),char(-104),char(0),char(88),char(0),char(-72),char(0),
-char(104),char(0),char(8),char(2),char(-56),char(3),char(8),char(0),char(64),char(0),char(64),char(0),char(0),char(0),char(80),char(0),char(96),char(0),char(-112),char(0),
-char(-128),char(0),char(104),char(1),char(-24),char(0),char(-104),char(1),char(-120),char(1),char(-32),char(0),char(8),char(1),char(-40),char(1),char(104),char(1),char(-128),char(2),
-char(-112),char(2),char(-64),char(4),char(-40),char(0),char(120),char(1),char(104),char(0),char(-104),char(0),char(16),char(0),char(104),char(0),char(24),char(0),char(40),char(0),
-char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0),char(104),char(1),char(112),char(0),char(-16),char(1),char(-128),char(3),char(-40),char(1),char(-56),char(0),
-char(112),char(0),char(48),char(1),char(8),char(2),char(0),char(0),char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),
-char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),
-char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),
-char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),
-char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),
-char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),
-char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),
-char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),
-char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
-char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),
-char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),
-char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),
-char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),
-char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),
-char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
-char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),
-char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),
-char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),
-char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),
-char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),
-char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),
-char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),
-char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),
-char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),
-char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),
-char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),
-char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),
-char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),
-char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),
-char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),
-char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),
-char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),
-char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),
-char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),
-char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),
-char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),
-char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(38),char(0),
-char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),
-char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),
-char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),char(8),char(0),char(108),char(0),char(4),char(0),char(109),char(0),char(4),char(0),char(110),char(0),
-char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),char(4),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),
-char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),
-char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),
-char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),char(4),char(0),char(-128),char(0),char(8),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),
-char(4),char(0),char(44),char(0),char(48),char(0),char(-125),char(0),char(48),char(0),char(-124),char(0),char(49),char(0),char(38),char(0),char(13),char(0),char(96),char(0),
-char(13),char(0),char(97),char(0),char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),
-char(13),char(0),char(102),char(0),char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),
-char(7),char(0),char(107),char(0),char(7),char(0),char(108),char(0),char(4),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),
-char(4),char(0),char(112),char(0),char(4),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),
-char(7),char(0),char(117),char(0),char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),
-char(7),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),
-char(4),char(0),char(127),char(0),char(4),char(0),char(-128),char(0),char(7),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(4),char(0),char(44),char(0),
-char(50),char(0),char(-125),char(0),char(50),char(0),char(-124),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
-char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-123),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
-char(13),char(0),char(-122),char(0),char(14),char(0),char(-121),char(0),char(4),char(0),char(-120),char(0),char(0),char(0),char(-119),char(0),char(48),char(0),char(29),char(0),
-char(9),char(0),char(-118),char(0),char(9),char(0),char(-117),char(0),char(27),char(0),char(-116),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-115),char(0),
-char(20),char(0),char(-114),char(0),char(14),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(8),char(0),char(-126),char(0),
-char(8),char(0),char(-110),char(0),char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),
-char(8),char(0),char(-105),char(0),char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),
-char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),
-char(4),char(0),char(-95),char(0),char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(50),char(0),char(29),char(0),
-char(9),char(0),char(-118),char(0),char(9),char(0),char(-117),char(0),char(27),char(0),char(-116),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-115),char(0),
-char(19),char(0),char(-114),char(0),char(13),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(7),char(0),char(-126),char(0),
-char(7),char(0),char(-110),char(0),char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),
-char(7),char(0),char(-105),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),
-char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),
-char(4),char(0),char(-95),char(0),char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(53),char(0),char(22),char(0),
-char(8),char(0),char(-91),char(0),char(8),char(0),char(-90),char(0),char(8),char(0),char(-109),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-105),char(0),
-char(8),char(0),char(-88),char(0),char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),
-char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),
-char(8),char(0),char(-78),char(0),char(4),char(0),char(-77),char(0),char(4),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),
-char(4),char(0),char(-73),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-91),char(0),char(7),char(0),char(-90),char(0),
-char(7),char(0),char(-109),char(0),char(7),char(0),char(-89),char(0),char(7),char(0),char(-105),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),
+char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),
+char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),
+char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),
+char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),
+char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),
+char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),
+char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),
+char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),
+char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),
+char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),
+char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
+char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
+char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),
+char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
+char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),
+char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),
+char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),
+char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
+char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0),char(-112),char(0),char(16),char(0),char(56),char(0),char(56),char(0),
+char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(56),char(0),char(32),char(0),char(80),char(0),char(72),char(0),
+char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(64),char(0),char(16),char(0),char(24),char(6),char(-8),char(1),char(80),char(3),
+char(32),char(1),char(72),char(0),char(80),char(0),char(-96),char(0),char(88),char(0),char(-64),char(0),char(104),char(0),char(8),char(2),char(-56),char(3),char(8),char(0),
+char(64),char(0),char(64),char(0),char(0),char(0),char(80),char(0),char(96),char(0),char(-112),char(0),char(-128),char(0),char(104),char(1),char(-24),char(0),char(-104),char(1),
+char(-120),char(1),char(-32),char(0),char(8),char(1),char(-40),char(1),char(104),char(1),char(-128),char(2),char(-112),char(2),char(-64),char(4),char(-40),char(0),char(120),char(1),
+char(104),char(0),char(-104),char(0),char(16),char(0),char(104),char(0),char(24),char(0),char(40),char(0),char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0),
+char(104),char(1),char(112),char(0),char(-16),char(1),char(-128),char(3),char(-40),char(1),char(-56),char(0),char(112),char(0),char(48),char(1),char(8),char(2),char(0),char(0),
+char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),
+char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),
+char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),
+char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),
+char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
+char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),
+char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
+char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
+char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
+char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
+char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),
+char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
+char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),
+char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
+char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
+char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),
+char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),
+char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
+char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
+char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),
+char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),
+char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),
+char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
+char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),
+char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),
+char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),
+char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),
+char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
+char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
+char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
+char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),
+char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),
+char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),
+char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),
+char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),
+char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),
+char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(39),char(0),char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),
+char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),
+char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),
+char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),
+char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),
+char(8),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(48),char(0),char(-124),char(0),char(48),char(0),char(-123),char(0),char(49),char(0),char(39),char(0),char(13),char(0),char(96),char(0),char(13),char(0),char(97),char(0),
+char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),char(13),char(0),char(102),char(0),
+char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),char(7),char(0),char(107),char(0),
+char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),char(7),char(0),char(117),char(0),
+char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),char(7),char(0),char(122),char(0),
+char(7),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(7),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(50),char(0),char(-124),char(0),char(50),char(0),char(-123),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
+char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-122),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
+char(13),char(0),char(-121),char(0),char(14),char(0),char(-120),char(0),char(4),char(0),char(-119),char(0),char(0),char(0),char(-118),char(0),char(48),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-114),char(0),
+char(20),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),char(8),char(0),char(-125),char(0),
+char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),char(8),char(0),char(-105),char(0),
+char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(50),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-114),char(0),
+char(19),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(13),char(0),char(-110),char(0),char(7),char(0),char(-125),char(0),
+char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),char(7),char(0),char(-105),char(0),
+char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(53),char(0),char(23),char(0),
+char(8),char(0),char(-90),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-88),char(0),char(8),char(0),char(-104),char(0),
+char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),
+char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),
+char(8),char(0),char(-77),char(0),char(8),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),
+char(4),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-90),char(0),
+char(7),char(0),char(-89),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-87),char(0),
char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0),
-char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(4),char(0),char(-77),char(0),
-char(4),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(0),char(0),char(37),char(0),
-char(55),char(0),char(2),char(0),char(53),char(0),char(-72),char(0),char(14),char(0),char(-71),char(0),char(56),char(0),char(2),char(0),char(54),char(0),char(-72),char(0),
-char(13),char(0),char(-71),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-70),char(0),char(17),char(0),char(-69),char(0),char(13),char(0),char(-68),char(0),
-char(13),char(0),char(-67),char(0),char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-71),char(0),char(13),char(0),char(-64),char(0),
-char(13),char(0),char(-63),char(0),char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(7),char(0),char(-59),char(0),
-char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),
-char(7),char(0),char(-53),char(0),char(7),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(58),char(0),char(22),char(0),char(48),char(0),char(-70),char(0),
-char(18),char(0),char(-69),char(0),char(14),char(0),char(-68),char(0),char(14),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),
-char(14),char(0),char(-71),char(0),char(14),char(0),char(-64),char(0),char(14),char(0),char(-63),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),
-char(8),char(0),char(-60),char(0),char(8),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),
-char(8),char(0),char(-55),char(0),char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),
-char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(60),char(0),char(13),char(0),
-char(57),char(0),char(-48),char(0),char(57),char(0),char(-47),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),
-char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),char(7),char(0),char(-43),char(0),char(7),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),
-char(4),char(0),char(-40),char(0),char(7),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(61),char(0),char(13),char(0),char(62),char(0),char(-48),char(0),
-char(62),char(0),char(-47),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),char(4),char(0),char(-45),char(0),
-char(4),char(0),char(-44),char(0),char(7),char(0),char(-43),char(0),char(7),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),char(4),char(0),char(-40),char(0),
-char(7),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-48),char(0),char(58),char(0),char(-47),char(0),
-char(0),char(0),char(35),char(0),char(4),char(0),char(-128),char(0),char(4),char(0),char(-46),char(0),char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),
-char(8),char(0),char(-43),char(0),char(8),char(0),char(-42),char(0),char(4),char(0),char(-41),char(0),char(4),char(0),char(-40),char(0),char(8),char(0),char(-39),char(0),
-char(4),char(0),char(-38),char(0),char(0),char(0),char(-37),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-36),char(0),char(13),char(0),char(-35),char(0),
-char(13),char(0),char(-34),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0),char(14),char(0),char(-34),char(0),
-char(66),char(0),char(3),char(0),char(61),char(0),char(-36),char(0),char(14),char(0),char(-35),char(0),char(14),char(0),char(-34),char(0),char(67),char(0),char(13),char(0),
-char(61),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),
-char(4),char(0),char(-29),char(0),char(7),char(0),char(-28),char(0),char(7),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),
-char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(68),char(0),char(13),char(0),char(61),char(0),char(-36),char(0),
-char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
-char(7),char(0),char(-28),char(0),char(7),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
-char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),
-char(20),char(0),char(-32),char(0),char(4),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(8),char(0),char(-28),char(0),
-char(8),char(0),char(-27),char(0),char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),
-char(8),char(0),char(-22),char(0),char(0),char(0),char(-21),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),
-char(20),char(0),char(-32),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-19),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-24),char(0),
-char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),char(8),char(0),char(-90),char(0),char(71),char(0),char(11),char(0),char(61),char(0),char(-36),char(0),
-char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-19),char(0),char(7),char(0),char(-18),char(0),
-char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-90),char(0),char(0),char(0),char(21),char(0),
-char(72),char(0),char(9),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),char(13),char(0),char(-17),char(0),
-char(13),char(0),char(-16),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),
-char(73),char(0),char(9),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(14),char(0),char(-17),char(0),
-char(14),char(0),char(-16),char(0),char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),char(4),char(0),char(-12),char(0),
-char(74),char(0),char(5),char(0),char(72),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0),char(7),char(0),char(-8),char(0),
-char(7),char(0),char(-7),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(8),char(0),char(-9),char(0),
-char(8),char(0),char(-8),char(0),char(8),char(0),char(-7),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),
-char(19),char(0),char(-32),char(0),char(13),char(0),char(-17),char(0),char(13),char(0),char(-16),char(0),char(13),char(0),char(-6),char(0),char(13),char(0),char(-5),char(0),
-char(13),char(0),char(-4),char(0),char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),
-char(13),char(0),char(1),char(1),char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(0),char(0),char(5),char(1),
-char(0),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(-21),char(0),
-char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(10),char(1),char(13),char(0),char(11),char(1),char(13),char(0),char(12),char(1),
-char(13),char(0),char(13),char(1),char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),
-char(13),char(0),char(18),char(1),char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(0),char(0),char(21),char(1),char(0),char(0),char(22),char(1),
-char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(4),char(0),char(26),char(1),char(77),char(0),char(41),char(0),
-char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),char(14),char(0),char(-17),char(0),char(14),char(0),char(-16),char(0),
-char(14),char(0),char(-6),char(0),char(14),char(0),char(-5),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),
-char(14),char(0),char(-1),char(0),char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),
-char(14),char(0),char(4),char(1),char(0),char(0),char(5),char(1),char(0),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),
-char(0),char(0),char(9),char(1),char(0),char(0),char(-21),char(0),char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(10),char(1),
-char(14),char(0),char(11),char(1),char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),
-char(14),char(0),char(16),char(1),char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),
-char(0),char(0),char(21),char(1),char(0),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),
-char(4),char(0),char(26),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-36),char(0),char(19),char(0),char(-33),char(0),char(19),char(0),char(-32),char(0),
-char(7),char(0),char(-17),char(0),char(7),char(0),char(-16),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),
-char(4),char(0),char(-12),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-36),char(0),char(20),char(0),char(-33),char(0),char(20),char(0),char(-32),char(0),
-char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(4),char(0),char(-13),char(0),
-char(4),char(0),char(-12),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-36),char(0),char(13),char(0),char(27),char(1),char(13),char(0),char(28),char(1),
-char(7),char(0),char(29),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-36),char(0),char(14),char(0),char(27),char(1),
-char(14),char(0),char(28),char(1),char(8),char(0),char(29),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1),
-char(7),char(0),char(32),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(33),char(1),char(13),char(0),char(34),char(1),
-char(13),char(0),char(35),char(1),char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(7),char(0),char(-60),char(0),
-char(7),char(0),char(39),char(1),char(4),char(0),char(40),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),char(82),char(0),char(33),char(1),
-char(4),char(0),char(41),char(1),char(7),char(0),char(42),char(1),char(4),char(0),char(43),char(1),char(85),char(0),char(4),char(0),char(13),char(0),char(38),char(1),
-char(82),char(0),char(33),char(1),char(4),char(0),char(44),char(1),char(7),char(0),char(45),char(1),char(86),char(0),char(7),char(0),char(13),char(0),char(46),char(1),
-char(82),char(0),char(33),char(1),char(4),char(0),char(47),char(1),char(7),char(0),char(48),char(1),char(7),char(0),char(49),char(1),char(7),char(0),char(50),char(1),
-char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(51),char(1),char(13),char(0),char(49),char(1),char(13),char(0),char(52),char(1),
-char(62),char(0),char(53),char(1),char(4),char(0),char(54),char(1),char(7),char(0),char(50),char(1),char(88),char(0),char(26),char(0),char(4),char(0),char(55),char(1),
-char(7),char(0),char(56),char(1),char(7),char(0),char(-90),char(0),char(7),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(59),char(1),
-char(7),char(0),char(60),char(1),char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),
-char(7),char(0),char(65),char(1),char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),
-char(7),char(0),char(70),char(1),char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),
-char(4),char(0),char(75),char(1),char(4),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(-100),char(0),
-char(89),char(0),char(12),char(0),char(17),char(0),char(79),char(1),char(17),char(0),char(80),char(1),char(17),char(0),char(81),char(1),char(13),char(0),char(82),char(1),
-char(13),char(0),char(83),char(1),char(7),char(0),char(84),char(1),char(4),char(0),char(85),char(1),char(4),char(0),char(86),char(1),char(4),char(0),char(87),char(1),
-char(4),char(0),char(88),char(1),char(7),char(0),char(48),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),char(19),char(0),char(89),char(1),
-char(17),char(0),char(90),char(1),char(17),char(0),char(91),char(1),char(13),char(0),char(82),char(1),char(13),char(0),char(92),char(1),char(13),char(0),char(93),char(1),
-char(13),char(0),char(94),char(1),char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(4),char(0),char(97),char(1),char(7),char(0),char(98),char(1),
-char(4),char(0),char(99),char(1),char(4),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(7),char(0),char(102),char(1),char(7),char(0),char(103),char(1),
-char(4),char(0),char(104),char(1),char(4),char(0),char(105),char(1),char(7),char(0),char(106),char(1),char(7),char(0),char(107),char(1),char(7),char(0),char(108),char(1),
-char(7),char(0),char(109),char(1),char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(4),char(0),char(112),char(1),char(4),char(0),char(113),char(1),
-char(4),char(0),char(114),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(115),char(1),char(9),char(0),char(116),char(1),char(13),char(0),char(117),char(1),
-char(7),char(0),char(118),char(1),char(7),char(0),char(-86),char(0),char(7),char(0),char(119),char(1),char(4),char(0),char(120),char(1),char(13),char(0),char(121),char(1),
-char(4),char(0),char(122),char(1),char(4),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(53),char(0),char(92),char(0),char(19),char(0),
-char(50),char(0),char(-70),char(0),char(89),char(0),char(125),char(1),char(82),char(0),char(126),char(1),char(83),char(0),char(127),char(1),char(84),char(0),char(-128),char(1),
-char(85),char(0),char(-127),char(1),char(86),char(0),char(-126),char(1),char(87),char(0),char(-125),char(1),char(90),char(0),char(-124),char(1),char(91),char(0),char(-123),char(1),
-char(4),char(0),char(-122),char(1),char(4),char(0),char(100),char(1),char(4),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(-119),char(1),
-char(4),char(0),char(-118),char(1),char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(88),char(0),char(-115),char(1),char(93),char(0),char(28),char(0),
-char(16),char(0),char(-114),char(1),char(14),char(0),char(-113),char(1),char(14),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),
-char(14),char(0),char(-109),char(1),char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),
-char(8),char(0),char(-104),char(1),char(4),char(0),char(-103),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),
-char(8),char(0),char(-100),char(1),char(8),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),
-char(8),char(0),char(-95),char(1),char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(0),char(0),char(-91),char(1),
-char(0),char(0),char(-90),char(1),char(48),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(94),char(0),char(28),char(0),char(15),char(0),char(-114),char(1),
-char(13),char(0),char(-113),char(1),char(13),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),
-char(13),char(0),char(-108),char(1),char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(4),char(0),char(-102),char(1),
-char(7),char(0),char(-104),char(1),char(4),char(0),char(-103),char(1),char(4),char(0),char(124),char(1),char(7),char(0),char(-100),char(1),char(7),char(0),char(-99),char(1),
-char(7),char(0),char(-98),char(1),char(4),char(0),char(-101),char(1),char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(7),char(0),char(-95),char(1),
-char(7),char(0),char(-94),char(1),char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(0),char(0),char(-91),char(1),char(0),char(0),char(-90),char(1),
-char(50),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-87),char(1),char(16),char(0),char(-86),char(1),
-char(14),char(0),char(-85),char(1),char(14),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(8),char(0),char(-82),char(1),char(4),char(0),char(-121),char(1),
-char(0),char(0),char(37),char(0),char(0),char(0),char(-81),char(1),char(93),char(0),char(-128),char(1),char(48),char(0),char(-80),char(1),char(96),char(0),char(10),char(0),
-char(13),char(0),char(-87),char(1),char(15),char(0),char(-86),char(1),char(13),char(0),char(-85),char(1),char(13),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),
-char(7),char(0),char(-82),char(1),char(4),char(0),char(-121),char(1),char(0),char(0),char(-81),char(1),char(94),char(0),char(-128),char(1),char(50),char(0),char(-80),char(1),
-char(97),char(0),char(4),char(0),char(50),char(0),char(-79),char(1),char(96),char(0),char(-78),char(1),char(4),char(0),char(-77),char(1),char(0),char(0),char(37),char(0),
-char(98),char(0),char(4),char(0),char(48),char(0),char(-79),char(1),char(95),char(0),char(-78),char(1),char(4),char(0),char(-77),char(1),char(0),char(0),char(37),char(0),
-};
+char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
+char(7),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(4),char(0),char(-72),char(0),
+char(4),char(0),char(-71),char(0),char(55),char(0),char(2),char(0),char(53),char(0),char(-70),char(0),char(14),char(0),char(-69),char(0),char(56),char(0),char(2),char(0),
+char(54),char(0),char(-70),char(0),char(13),char(0),char(-69),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-68),char(0),char(17),char(0),char(-67),char(0),
+char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0),char(13),char(0),char(-69),char(0),
+char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(13),char(0),char(-60),char(0),char(13),char(0),char(-59),char(0),char(7),char(0),char(-58),char(0),
+char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),
+char(7),char(0),char(-52),char(0),char(7),char(0),char(-51),char(0),char(7),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(58),char(0),char(22),char(0),
+char(48),char(0),char(-68),char(0),char(18),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),char(14),char(0),char(-64),char(0),
+char(14),char(0),char(-63),char(0),char(14),char(0),char(-69),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),char(14),char(0),char(-60),char(0),
+char(14),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-55),char(0),
+char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(8),char(0),char(-51),char(0),char(8),char(0),char(-50),char(0),
+char(4),char(0),char(-49),char(0),char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-48),char(0),char(4),char(0),char(-47),char(0),
+char(60),char(0),char(13),char(0),char(57),char(0),char(-46),char(0),char(57),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),
+char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),
+char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(61),char(0),char(13),char(0),
+char(62),char(0),char(-46),char(0),char(62),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),
+char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
+char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-46),char(0),
+char(58),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),
+char(4),char(0),char(-42),char(0),char(8),char(0),char(-41),char(0),char(8),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),
+char(8),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),
+char(13),char(0),char(-33),char(0),char(13),char(0),char(-32),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),
+char(14),char(0),char(-32),char(0),char(66),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),char(14),char(0),char(-32),char(0),
+char(67),char(0),char(13),char(0),char(61),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
+char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
+char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(68),char(0),char(13),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),
+char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),
+char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),
+char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),
+char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(0),char(0),char(-19),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),
+char(8),char(0),char(-22),char(0),char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-89),char(0),char(71),char(0),char(11),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(7),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0),
+char(7),char(0),char(-16),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-89),char(0),
+char(0),char(0),char(21),char(0),char(72),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),
+char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(73),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),
+char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(74),char(0),char(5),char(0),char(72),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),
+char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),
+char(8),char(0),char(-7),char(0),char(8),char(0),char(-6),char(0),char(8),char(0),char(-5),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-34),char(0),
+char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-4),char(0),
+char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),char(13),char(0),char(1),char(1),
+char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(13),char(0),char(5),char(1),char(13),char(0),char(6),char(1),
+char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),
+char(0),char(0),char(-19),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(13),char(0),char(12),char(1),char(13),char(0),char(13),char(1),
+char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),char(13),char(0),char(18),char(1),
+char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(13),char(0),char(21),char(1),char(13),char(0),char(22),char(1),char(0),char(0),char(23),char(1),
+char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),
+char(77),char(0),char(41),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(14),char(0),char(-15),char(0),
+char(14),char(0),char(-14),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),char(14),char(0),char(-1),char(0),
+char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),char(14),char(0),char(4),char(1),
+char(14),char(0),char(5),char(1),char(14),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),
+char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),char(0),char(0),char(-19),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),
+char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),char(14),char(0),char(16),char(1),
+char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),char(14),char(0),char(21),char(1),
+char(14),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),
+char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),
+char(19),char(0),char(-30),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),char(7),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),
+char(20),char(0),char(-30),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(8),char(0),char(-13),char(0),char(8),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-34),char(0),char(13),char(0),char(29),char(1),
+char(13),char(0),char(30),char(1),char(7),char(0),char(31),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-34),char(0),
+char(14),char(0),char(29),char(1),char(14),char(0),char(30),char(1),char(8),char(0),char(31),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(32),char(1),
+char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(35),char(1),
+char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(13),char(0),char(39),char(1),char(13),char(0),char(40),char(1),
+char(7),char(0),char(-58),char(0),char(7),char(0),char(41),char(1),char(4),char(0),char(42),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),
+char(82),char(0),char(35),char(1),char(4),char(0),char(43),char(1),char(7),char(0),char(44),char(1),char(4),char(0),char(45),char(1),char(85),char(0),char(4),char(0),
+char(13),char(0),char(40),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(46),char(1),char(7),char(0),char(47),char(1),char(86),char(0),char(7),char(0),
+char(13),char(0),char(48),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(49),char(1),char(7),char(0),char(50),char(1),char(7),char(0),char(51),char(1),
+char(7),char(0),char(52),char(1),char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(53),char(1),char(13),char(0),char(51),char(1),
+char(13),char(0),char(54),char(1),char(62),char(0),char(55),char(1),char(4),char(0),char(56),char(1),char(7),char(0),char(52),char(1),char(88),char(0),char(26),char(0),
+char(4),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(-89),char(0),char(7),char(0),char(59),char(1),char(7),char(0),char(60),char(1),
+char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1),
+char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1),
+char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),char(7),char(0),char(75),char(1),
+char(7),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(79),char(1),char(4),char(0),char(80),char(1),
+char(4),char(0),char(-99),char(0),char(89),char(0),char(12),char(0),char(17),char(0),char(81),char(1),char(17),char(0),char(82),char(1),char(17),char(0),char(83),char(1),
+char(13),char(0),char(84),char(1),char(13),char(0),char(85),char(1),char(7),char(0),char(86),char(1),char(4),char(0),char(87),char(1),char(4),char(0),char(88),char(1),
+char(4),char(0),char(89),char(1),char(4),char(0),char(90),char(1),char(7),char(0),char(50),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),
+char(19),char(0),char(91),char(1),char(17),char(0),char(92),char(1),char(17),char(0),char(93),char(1),char(13),char(0),char(84),char(1),char(13),char(0),char(94),char(1),
+char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(13),char(0),char(97),char(1),char(13),char(0),char(98),char(1),char(4),char(0),char(99),char(1),
+char(7),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(103),char(1),char(7),char(0),char(104),char(1),
+char(7),char(0),char(105),char(1),char(4),char(0),char(106),char(1),char(4),char(0),char(107),char(1),char(7),char(0),char(108),char(1),char(7),char(0),char(109),char(1),
+char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(7),char(0),char(112),char(1),char(7),char(0),char(113),char(1),char(4),char(0),char(114),char(1),
+char(4),char(0),char(115),char(1),char(4),char(0),char(116),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(117),char(1),char(9),char(0),char(118),char(1),
+char(13),char(0),char(119),char(1),char(7),char(0),char(120),char(1),char(7),char(0),char(-85),char(0),char(7),char(0),char(121),char(1),char(4),char(0),char(122),char(1),
+char(13),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(125),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(53),char(0),
+char(92),char(0),char(19),char(0),char(50),char(0),char(-68),char(0),char(89),char(0),char(127),char(1),char(82),char(0),char(-128),char(1),char(83),char(0),char(-127),char(1),
+char(84),char(0),char(-126),char(1),char(85),char(0),char(-125),char(1),char(86),char(0),char(-124),char(1),char(87),char(0),char(-123),char(1),char(90),char(0),char(-122),char(1),
+char(91),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(-119),char(1),char(4),char(0),char(-118),char(1),
+char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(4),char(0),char(-115),char(1),char(4),char(0),char(-114),char(1),char(88),char(0),char(-113),char(1),
+char(93),char(0),char(28),char(0),char(16),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),char(14),char(0),char(-109),char(1),
+char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),char(14),char(0),char(-104),char(1),
+char(14),char(0),char(-103),char(1),char(8),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(-100),char(1),
+char(4),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),char(8),char(0),char(-95),char(1),
+char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(8),char(0),char(-91),char(1),char(8),char(0),char(-90),char(1),
+char(0),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(48),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(94),char(0),char(28),char(0),
+char(15),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),char(13),char(0),char(-108),char(1),
+char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(13),char(0),char(-104),char(1),char(13),char(0),char(-103),char(1),
+char(4),char(0),char(-100),char(1),char(7),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(7),char(0),char(-98),char(1),
+char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(4),char(0),char(-99),char(1),char(7),char(0),char(-95),char(1),char(7),char(0),char(-94),char(1),
+char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(7),char(0),char(-91),char(1),char(7),char(0),char(-90),char(1),char(0),char(0),char(-89),char(1),
+char(0),char(0),char(-88),char(1),char(50),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-85),char(1),
+char(16),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(14),char(0),char(-82),char(1),char(14),char(0),char(-81),char(1),char(8),char(0),char(-80),char(1),
+char(4),char(0),char(-119),char(1),char(0),char(0),char(37),char(0),char(0),char(0),char(-79),char(1),char(93),char(0),char(-126),char(1),char(48),char(0),char(-78),char(1),
+char(96),char(0),char(10),char(0),char(13),char(0),char(-85),char(1),char(15),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),char(13),char(0),char(-82),char(1),
+char(13),char(0),char(-81),char(1),char(7),char(0),char(-80),char(1),char(4),char(0),char(-119),char(1),char(0),char(0),char(-79),char(1),char(94),char(0),char(-126),char(1),
+char(50),char(0),char(-78),char(1),char(97),char(0),char(4),char(0),char(50),char(0),char(-77),char(1),char(96),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),char(98),char(0),char(4),char(0),char(48),char(0),char(-77),char(1),char(95),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),};
int sBulletDNAlen64= sizeof(sBulletDNAstr64);
-// clang-format on
diff --git a/thirdparty/bullet/btBulletCollisionAll.cpp b/thirdparty/bullet/btBulletCollisionAll.cpp
index 2851fb3b73..4a3ec8dd6f 100644
--- a/thirdparty/bullet/btBulletCollisionAll.cpp
+++ b/thirdparty/bullet/btBulletCollisionAll.cpp
@@ -23,6 +23,7 @@
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp"
#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp"
#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp"
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp"
#include "BulletCollision/CollisionDispatch/btCollisionObject.cpp"
diff --git a/thirdparty/bullet/btLinearMathAll.cpp b/thirdparty/bullet/btLinearMathAll.cpp
index 808f412803..d05a19e630 100644
--- a/thirdparty/bullet/btLinearMathAll.cpp
+++ b/thirdparty/bullet/btLinearMathAll.cpp
@@ -8,6 +8,7 @@
#include "LinearMath/btConvexHullComputer.cpp"
#include "LinearMath/btQuickprof.cpp"
#include "LinearMath/btThreads.cpp"
+#include "LinearMath/btReducedVector.cpp"
#include "LinearMath/TaskScheduler/btTaskScheduler.cpp"
#include "LinearMath/TaskScheduler/btThreadSupportPosix.cpp"
#include "LinearMath/TaskScheduler/btThreadSupportWin32.cpp"
diff --git a/thirdparty/enet/LICENSE b/thirdparty/enet/LICENSE
index 39af84a8f6..6906f8eb0b 100644
--- a/thirdparty/enet/LICENSE
+++ b/thirdparty/enet/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2002-2016 Lee Salzman
+Copyright (c) 2002-2020 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h
index 246cbb0a62..3900353c34 100644
--- a/thirdparty/enet/enet/enet.h
+++ b/thirdparty/enet/enet/enet.h
@@ -22,7 +22,7 @@ extern "C"
#define ENET_VERSION_MAJOR 1
#define ENET_VERSION_MINOR 3
-#define ENET_VERSION_PATCH 13
+#define ENET_VERSION_PATCH 15
#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch))
#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF)
#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF)
@@ -248,6 +248,11 @@ typedef struct _ENetChannel
ENetList incomingUnreliableCommands;
} ENetChannel;
+typedef enum _ENetPeerFlag
+{
+ ENET_PEER_FLAG_NEEDS_DISPATCH = (1 << 0)
+} ENetPeerFlag;
+
/**
* An ENet peer which data packets may be sent or received from.
*
@@ -309,7 +314,9 @@ typedef struct _ENetPeer
ENetList outgoingReliableCommands;
ENetList outgoingUnreliableCommands;
ENetList dispatchedCommands;
- int needsDispatch;
+ enet_uint16 flags;
+ enet_uint8 roundTripTimeRemainder;
+ enet_uint8 roundTripTimeVarianceRemainder;
enet_uint16 incomingUnsequencedGroup;
enet_uint16 outgoingUnsequencedGroup;
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
@@ -507,6 +514,17 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock
/** @defgroup Address ENet address functions
@{
*/
+
+/** Attempts to parse the printable form of the IP address in the parameter hostName
+ and sets the host field in the address parameter if successful.
+ @param address destination to store the parsed IP address
+ @param hostName IP address to parse
+ @retval 0 on success
+ @retval < 0 on failure
+ @returns the address of the given hostName in address on success
+*/
+ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostName);
+
/** Attempts to resolve the host named by the parameter hostName and sets
the host field in the address parameter if successful.
@param address destination to store resolved address
@@ -567,6 +585,8 @@ ENET_API void enet_host_channel_limit (ENetHost *, size_t);
ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
extern void enet_host_bandwidth_throttle (ENetHost *);
extern enet_uint32 enet_host_random_seed (void);
+ENET_API void enet_host_dtls_server_setup (ENetHost *, void *, void *);
+ENET_API void enet_host_dtls_client_setup (ENetHost *, void *, uint8_t, const char *);
ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
diff --git a/thirdparty/enet/enet/godot.h b/thirdparty/enet/enet/godot.h
index 9230af428b..4f25ea9c7b 100644
--- a/thirdparty/enet/enet/godot.h
+++ b/thirdparty/enet/enet/godot.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/thirdparty/enet/enet/utility.h b/thirdparty/enet/enet/utility.h
index e48a476be3..b04bb7a5b3 100644
--- a/thirdparty/enet/enet/utility.h
+++ b/thirdparty/enet/enet/utility.h
@@ -7,6 +7,7 @@
#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
+#define ENET_DIFFERENCE(x, y) ((x) < (y) ? (y) - (x) : (x) - (y))
#endif /* __ENET_UTILITY_H__ */
diff --git a/thirdparty/enet/godot.cpp b/thirdparty/enet/godot.cpp
index 822a294781..9fefa53e77 100644
--- a/thirdparty/enet/godot.cpp
+++ b/thirdparty/enet/godot.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,13 +32,313 @@
@brief ENet Godot specific functions
*/
+#include "core/io/dtls_server.h"
#include "core/io/ip.h"
#include "core/io/net_socket.h"
+#include "core/io/packet_peer_dtls.h"
+#include "core/io/udp_server.h"
#include "core/os/os.h"
// This must be last for windows to compile (tested with MinGW)
#include "enet/enet.h"
+/// Abstract ENet interface for UDP/DTLS.
+class ENetGodotSocket {
+
+public:
+ virtual Error bind(IP_Address p_ip, uint16_t p_port) = 0;
+ virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) = 0;
+ virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) = 0;
+ virtual int set_option(ENetSocketOption p_option, int p_value) = 0;
+ virtual void close() = 0;
+ virtual ~ENetGodotSocket(){};
+};
+
+class ENetDTLSClient;
+class ENetDTLSServer;
+
+/// NetSocket interface
+class ENetUDP : public ENetGodotSocket {
+
+ friend class ENetDTLSClient;
+ friend class ENetDTLSServer;
+
+private:
+ Ref<NetSocket> sock;
+ IP_Address address;
+ uint16_t port;
+ bool bound;
+
+public:
+ ENetUDP() {
+ sock = Ref<NetSocket>(NetSocket::create());
+ IP::Type ip_type = IP::TYPE_ANY;
+ bound = false;
+ sock->open(NetSocket::TYPE_UDP, ip_type);
+ }
+
+ ~ENetUDP() {
+ sock->close();
+ }
+
+ Error bind(IP_Address p_ip, uint16_t p_port) {
+ address = p_ip;
+ port = p_port;
+ bound = true;
+ return sock->bind(address, port);
+ }
+
+ Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) {
+ return sock->sendto(p_buffer, p_len, r_sent, p_ip, p_port);
+ }
+
+ Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) {
+ Error err = sock->poll(NetSocket::POLL_TYPE_IN, 0);
+ if (err != OK)
+ return err;
+ return sock->recvfrom(p_buffer, p_len, r_read, r_ip, r_port);
+ }
+
+ int set_option(ENetSocketOption p_option, int p_value) {
+ switch (p_option) {
+ case ENET_SOCKOPT_NONBLOCK: {
+ sock->set_blocking_enabled(p_value ? false : true);
+ return 0;
+ } break;
+
+ case ENET_SOCKOPT_BROADCAST: {
+ sock->set_broadcasting_enabled(p_value ? true : false);
+ return 0;
+ } break;
+
+ case ENET_SOCKOPT_REUSEADDR: {
+ sock->set_reuse_address_enabled(p_value ? true : false);
+ return 0;
+ } break;
+
+ case ENET_SOCKOPT_RCVBUF: {
+ return -1;
+ } break;
+
+ case ENET_SOCKOPT_SNDBUF: {
+ return -1;
+ } break;
+
+ case ENET_SOCKOPT_RCVTIMEO: {
+ return -1;
+ } break;
+
+ case ENET_SOCKOPT_SNDTIMEO: {
+ return -1;
+ } break;
+
+ case ENET_SOCKOPT_NODELAY: {
+ sock->set_tcp_no_delay_enabled(p_value ? true : false);
+ return 0;
+ } break;
+ }
+
+ return -1;
+ }
+
+ void close() {
+ sock->close();
+ }
+};
+
+/// DTLS Client ENet interface
+class ENetDTLSClient : public ENetGodotSocket {
+
+ bool connected;
+ Ref<PacketPeerUDP> udp;
+ Ref<PacketPeerDTLS> dtls;
+ bool verify;
+ String for_hostname;
+ Ref<X509Certificate> cert;
+
+public:
+ ENetDTLSClient(ENetUDP *p_base, Ref<X509Certificate> p_cert, bool p_verify, String p_for_hostname) {
+ verify = p_verify;
+ for_hostname = p_for_hostname;
+ cert = p_cert;
+ udp.instance();
+ dtls = Ref<PacketPeerDTLS>(PacketPeerDTLS::create());
+ p_base->close();
+ if (p_base->bound) {
+ bind(p_base->address, p_base->port);
+ }
+ connected = false;
+ }
+
+ ~ENetDTLSClient() {
+ close();
+ }
+
+ Error bind(IP_Address p_ip, uint16_t p_port) {
+ return udp->listen(p_port, p_ip);
+ }
+
+ Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) {
+ if (!connected) {
+ udp->connect_to_host(p_ip, p_port);
+ dtls->connect_to_peer(udp, verify, for_hostname, cert);
+ connected = true;
+ }
+ dtls->poll();
+ if (dtls->get_status() == PacketPeerDTLS::STATUS_HANDSHAKING)
+ return ERR_BUSY;
+ else if (dtls->get_status() != PacketPeerDTLS::STATUS_CONNECTED)
+ return FAILED;
+ r_sent = p_len;
+ return dtls->put_packet(p_buffer, p_len);
+ }
+
+ Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) {
+ dtls->poll();
+ if (dtls->get_status() == PacketPeerDTLS::STATUS_HANDSHAKING)
+ return ERR_BUSY;
+ if (dtls->get_status() != PacketPeerDTLS::STATUS_CONNECTED)
+ return FAILED;
+ int pc = dtls->get_available_packet_count();
+ if (pc == 0)
+ return ERR_BUSY;
+ else if (pc < 0)
+ return FAILED;
+
+ const uint8_t *buffer;
+ Error err = dtls->get_packet(&buffer, r_read);
+ ERR_FAIL_COND_V(err != OK, err);
+ ERR_FAIL_COND_V(p_len < r_read, ERR_OUT_OF_MEMORY);
+
+ copymem(p_buffer, buffer, r_read);
+ r_ip = udp->get_packet_address();
+ r_port = udp->get_packet_port();
+ return err;
+ }
+
+ int set_option(ENetSocketOption p_option, int p_value) {
+ return -1;
+ }
+
+ void close() {
+ dtls->disconnect_from_peer();
+ udp->close();
+ }
+};
+
+/// DTLSServer - ENet interface
+class ENetDTLSServer : public ENetGodotSocket {
+
+ Ref<DTLSServer> server;
+ Ref<UDPServer> udp_server;
+ Map<String, Ref<PacketPeerDTLS> > peers;
+ int last_service;
+
+public:
+ ENetDTLSServer(ENetUDP *p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert) {
+ last_service = 0;
+ udp_server.instance();
+ p_base->close();
+ if (p_base->bound) {
+ bind(p_base->address, p_base->port);
+ }
+ server = Ref<DTLSServer>(DTLSServer::create());
+ server->setup(p_key, p_cert);
+ }
+
+ ~ENetDTLSServer() {
+ close();
+ }
+
+ Error bind(IP_Address p_ip, uint16_t p_port) {
+ return udp_server->listen(p_port, p_ip);
+ }
+
+ Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) {
+ String key = String(p_ip) + ":" + itos(p_port);
+ ERR_FAIL_COND_V(!peers.has(key), ERR_UNAVAILABLE);
+ Ref<PacketPeerDTLS> peer = peers[key];
+ Error err = peer->put_packet(p_buffer, p_len);
+ if (err == OK)
+ r_sent = p_len;
+ else if (err == ERR_BUSY)
+ r_sent = 0;
+ else
+ r_sent = -1;
+ return err;
+ }
+
+ Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) {
+ // TODO limits? Maybe we can better enforce allowed connections!
+ if (udp_server->is_connection_available()) {
+ Ref<PacketPeerUDP> udp = udp_server->take_connection();
+ IP_Address peer_ip = udp->get_packet_address();
+ int peer_port = udp->get_packet_port();
+ Ref<PacketPeerDTLS> peer = server->take_connection(udp);
+ PacketPeerDTLS::Status status = peer->get_status();
+ if (status == PacketPeerDTLS::STATUS_HANDSHAKING || status == PacketPeerDTLS::STATUS_CONNECTED) {
+ String key = String(peer_ip) + ":" + itos(peer_port);
+ peers[key] = peer;
+ }
+ }
+
+ List<String> remove;
+ Error err = ERR_BUSY;
+ // TODO this needs to be fair!
+ for (Map<String, Ref<PacketPeerDTLS> >::Element *E = peers.front(); E; E = E->next()) {
+ Ref<PacketPeerDTLS> peer = E->get();
+ peer->poll();
+
+ if (peer->get_status() == PacketPeerDTLS::STATUS_HANDSHAKING)
+ continue;
+ else if (peer->get_status() != PacketPeerDTLS::STATUS_CONNECTED) {
+ // Peer disconnected, removing it.
+ remove.push_back(E->key());
+ continue;
+ }
+
+ if (peer->get_available_packet_count() > 0) {
+ const uint8_t *buffer;
+ err = peer->get_packet(&buffer, r_read);
+ if (err != OK || p_len < r_read) {
+ // Something wrong with this peer, removing it.
+ remove.push_back(E->key());
+ err = FAILED;
+ continue;
+ }
+
+ Vector<String> s = E->key().rsplit(":", false, 1);
+ ERR_CONTINUE(s.size() != 2); // BUG!
+
+ copymem(p_buffer, buffer, r_read);
+ r_ip = s[0];
+ r_port = s[1].to_int();
+ break; // err = OK
+ }
+ }
+
+ // Remove disconnected peers from map.
+ for (List<String>::Element *E = remove.front(); E; E = E->next()) {
+ peers.erase(E->get());
+ }
+
+ return err; // OK, ERR_BUSY, or possibly an error.
+ }
+
+ int set_option(ENetSocketOption p_option, int p_value) {
+ return -1;
+ }
+
+ void close() {
+ for (Map<String, Ref<PacketPeerDTLS> >::Element *E = peers.front(); E; E = E->next()) {
+ E->get()->disconnect_from_peer();
+ }
+ peers.clear();
+ udp_server->stop();
+ server->stop();
+ }
+};
+
static enet_uint32 timeBase = 0;
int enet_initialize(void) {
@@ -92,13 +392,23 @@ int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLen
ENetSocket enet_socket_create(ENetSocketType type) {
- NetSocket *socket = NetSocket::create();
- IP::Type ip_type = IP::TYPE_ANY;
- socket->open(NetSocket::TYPE_UDP, ip_type);
+ ENetUDP *socket = memnew(ENetUDP);
return socket;
}
+void enet_host_dtls_server_setup(ENetHost *host, void *p_key, void *p_cert) {
+ ENetUDP *sock = (ENetUDP *)host->socket;
+ host->socket = memnew(ENetDTLSServer(sock, Ref<CryptoKey>((CryptoKey *)p_key), Ref<X509Certificate>((X509Certificate *)p_cert)));
+ memdelete(sock);
+}
+
+void enet_host_dtls_client_setup(ENetHost *host, void *p_cert, uint8_t p_verify, const char *p_for_hostname) {
+ ENetUDP *sock = (ENetUDP *)host->socket;
+ host->socket = memnew(ENetDTLSClient(sock, Ref<X509Certificate>((X509Certificate *)p_cert), p_verify, String(p_for_hostname)));
+ memdelete(sock);
+}
+
int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
IP_Address ip;
@@ -108,7 +418,7 @@ int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
ip.set_ipv6(address->host);
}
- NetSocket *sock = (NetSocket *)socket;
+ ENetGodotSocket *sock = (ENetGodotSocket *)socket;
if (sock->bind(ip, address->port) != OK) {
return -1;
}
@@ -116,7 +426,7 @@ int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
}
void enet_socket_destroy(ENetSocket socket) {
- NetSocket *sock = (NetSocket *)socket;
+ ENetGodotSocket *sock = (ENetGodotSocket *)socket;
sock->close();
memdelete(sock);
}
@@ -125,7 +435,7 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
ERR_FAIL_COND_V(address == NULL, -1);
- NetSocket *sock = (NetSocket *)socket;
+ ENetGodotSocket *sock = (ENetGodotSocket *)socket;
IP_Address dest;
Error err;
size_t i = 0;
@@ -133,8 +443,8 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
dest.set_ipv6(address->host);
// Create a single packet.
- PoolVector<uint8_t> out;
- PoolVector<uint8_t>::Write w;
+ Vector<uint8_t> out;
+ uint8_t* w;
int size = 0;
int pos = 0;
for (i = 0; i < bufferCount; i++) {
@@ -142,7 +452,7 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
}
out.resize(size);
- w = out.write();
+ w = out.ptrw();
for (i = 0; i < bufferCount; i++) {
memcpy(&w[pos], buffers[i].data, buffers[i].dataLength);
pos += buffers[i].dataLength;
@@ -167,15 +477,7 @@ int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buf
ERR_FAIL_COND_V(bufferCount != 1, -1);
- NetSocket *sock = (NetSocket *)socket;
-
- Error ret = sock->poll(NetSocket::POLL_TYPE_IN, 0);
-
- if (ret == ERR_BUSY)
- return 0;
-
- if (ret != OK)
- return -1;
+ ENetGodotSocket *sock = (ENetGodotSocket *)socket;
int read;
IP_Address ip;
@@ -215,47 +517,8 @@ int enet_socket_listen(ENetSocket socket, int backlog) {
int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) {
- NetSocket *sock = (NetSocket *)socket;
-
- switch (option) {
- case ENET_SOCKOPT_NONBLOCK: {
- sock->set_blocking_enabled(value ? false : true);
- return 0;
- } break;
-
- case ENET_SOCKOPT_BROADCAST: {
- sock->set_broadcasting_enabled(value ? true : false);
- return 0;
- } break;
-
- case ENET_SOCKOPT_REUSEADDR: {
- sock->set_reuse_address_enabled(value ? true : false);
- return 0;
- } break;
-
- case ENET_SOCKOPT_RCVBUF: {
- return -1;
- } break;
-
- case ENET_SOCKOPT_SNDBUF: {
- return -1;
- } break;
-
- case ENET_SOCKOPT_RCVTIMEO: {
- return -1;
- } break;
-
- case ENET_SOCKOPT_SNDTIMEO: {
- return -1;
- } break;
-
- case ENET_SOCKOPT_NODELAY: {
- sock->set_tcp_no_delay_enabled(value ? true : false);
- return 0;
- } break;
- }
-
- return -1;
+ ENetGodotSocket *sock = (ENetGodotSocket *)socket;
+ return sock->set_option(option, value);
}
int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) {
diff --git a/thirdparty/enet/patches/dtls_support.patch b/thirdparty/enet/patches/dtls_support.patch
new file mode 100644
index 0000000000..ce3480a858
--- /dev/null
+++ b/thirdparty/enet/patches/dtls_support.patch
@@ -0,0 +1,13 @@
+diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h
+index 966e3a465d..ac7552adb2 100644
+--- a/thirdparty/enet/enet/enet.h
++++ b/thirdparty/enet/enet/enet.h
+@@ -578,6 +578,8 @@ ENET_API void enet_host_channel_limit (ENetHost *, size_t);
+ ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
+ extern void enet_host_bandwidth_throttle (ENetHost *);
+ extern enet_uint32 enet_host_random_seed (void);
++ENET_API void enet_host_dtls_server_setup (ENetHost *, void *, void *);
++ENET_API void enet_host_dtls_client_setup (ENetHost *, void *, uint8_t, const char *);
+
+ ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
+ ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
diff --git a/thirdparty/enet/patches/ipv6_support.patch b/thirdparty/enet/patches/ipv6_support.patch
new file mode 100644
index 0000000000..1f79863645
--- /dev/null
+++ b/thirdparty/enet/patches/ipv6_support.patch
@@ -0,0 +1,105 @@
+diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h
+index 650b199ee5..246cbb0a62 100644
+--- a/thirdparty/enet/enet/enet.h
++++ b/thirdparty/enet/enet/enet.h
+@@ -10,13 +10,10 @@ extern "C"
+ {
+ #endif
+
++#include <stdint.h>
+ #include <stdlib.h>
+
+-#ifdef _WIN32
+-#include "enet/win32.h"
+-#else
+-#include "enet/unix.h"
+-#endif
++#include "enet/godot.h"
+
+ #include "enet/types.h"
+ #include "enet/protocol.h"
+@@ -72,7 +69,6 @@ typedef enum _ENetSocketShutdown
+ ENET_SOCKET_SHUTDOWN_READ_WRITE = 2
+ } ENetSocketShutdown;
+
+-#define ENET_HOST_ANY 0
+ #define ENET_HOST_BROADCAST 0xFFFFFFFFU
+ #define ENET_PORT_ANY 0
+
+@@ -88,9 +84,11 @@ typedef enum _ENetSocketShutdown
+ */
+ typedef struct _ENetAddress
+ {
+- enet_uint32 host;
++ uint8_t host[16];
+ enet_uint16 port;
++ uint8_t wildcard;
+ } ENetAddress;
++#define enet_host_equal(host_a, host_b) (memcmp(&host_a, &host_b,16) == 0)
+
+ /**
+ * Packet flag bit constants.
+@@ -519,6 +517,16 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock
+ */
+ ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
+
++/** Sets the host field in the address parameter from ip struct.
++ @param address destination to store resolved address
++ @param ip the ip struct to read from
++ @param size the size of the ip struct.
++ @retval 0 on success
++ @retval != 0 on failure
++ @returns the address of the given ip in address on success.
++*/
++ENET_API void enet_address_set_ip(ENetAddress * address, const uint8_t * ip, size_t size);
++
+ /** Gives the printable form of the IP address specified in the address parameter.
+ @param address address printed
+ @param hostName destination for name, must not be NULL
+diff --git a/thirdparty/enet/host.c b/thirdparty/enet/host.c
+index 3be6c0922c..fc4da4ca67 100644
+--- a/thirdparty/enet/host.c
++++ b/thirdparty/enet/host.c
+@@ -87,7 +87,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
+ host -> commandCount = 0;
+ host -> bufferCount = 0;
+ host -> checksum = NULL;
+- host -> receivedAddress.host = ENET_HOST_ANY;
++ memset(host -> receivedAddress.host, 0, 16);
+ host -> receivedAddress.port = 0;
+ host -> receivedData = NULL;
+ host -> receivedDataLength = 0;
+diff --git a/thirdparty/enet/protocol.c b/thirdparty/enet/protocol.c
+index 29d648732d..ab26886de4 100644
+--- a/thirdparty/enet/protocol.c
++++ b/thirdparty/enet/protocol.c
+@@ -298,7 +298,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
+ }
+ else
+ if (currentPeer -> state != ENET_PEER_STATE_CONNECTING &&
+- currentPeer -> address.host == host -> receivedAddress.host)
++ enet_host_equal(currentPeer -> address.host, host -> receivedAddress.host))
+ {
+ if (currentPeer -> address.port == host -> receivedAddress.port &&
+ currentPeer -> connectID == command -> connect.connectID)
+@@ -1010,9 +1010,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
+
+ if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
+ peer -> state == ENET_PEER_STATE_ZOMBIE ||
+- ((host -> receivedAddress.host != peer -> address.host ||
+- host -> receivedAddress.port != peer -> address.port) &&
+- peer -> address.host != ENET_HOST_BROADCAST) ||
++ (!enet_host_equal(host -> receivedAddress.host, peer -> address.host) ||
++ host -> receivedAddress.port != peer -> address.port) ||
+ (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
+ sessionID != peer -> incomingSessionID))
+ return 0;
+@@ -1054,7 +1053,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
+
+ if (peer != NULL)
+ {
+- peer -> address.host = host -> receivedAddress.host;
++ enet_address_set_ip(&(peer -> address), host -> receivedAddress.host, 16);
+ peer -> address.port = host -> receivedAddress.port;
+ peer -> incomingDataTotal += host -> receivedDataLength;
+ }
diff --git a/thirdparty/enet/peer.c b/thirdparty/enet/peer.c
index e2d0872bd3..1278b85a80 100644
--- a/thirdparty/enet/peer.c
+++ b/thirdparty/enet/peer.c
@@ -66,7 +66,7 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
peer -> packetThrottle = peer -> packetThrottleLimit;
}
else
- if (rtt < peer -> lastRoundTripTime)
+ if (rtt <= peer -> lastRoundTripTime)
{
peer -> packetThrottle += peer -> packetThrottleAcceleration;
@@ -76,7 +76,7 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
return 1;
}
else
- if (rtt > peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance)
+ if (rtt >= peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance)
{
if (peer -> packetThrottle > peer -> packetThrottleDeceleration)
peer -> packetThrottle -= peer -> packetThrottleDeceleration;
@@ -306,11 +306,11 @@ enet_peer_reset_queues (ENetPeer * peer)
{
ENetChannel * channel;
- if (peer -> needsDispatch)
+ if (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH)
{
enet_list_remove (& peer -> dispatchList);
- peer -> needsDispatch = 0;
+ peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH;
}
while (! enet_list_empty (& peer -> acknowledgements))
@@ -418,6 +418,9 @@ enet_peer_reset (ENetPeer * peer)
peer -> outgoingUnsequencedGroup = 0;
peer -> eventData = 0;
peer -> totalWaitingData = 0;
+ peer -> flags = 0;
+ peer -> roundTripTimeRemainder = 0;
+ peer -> roundTripTimeVarianceRemainder = 0;
memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
@@ -724,11 +727,11 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel *
{
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
- if (! peer -> needsDispatch)
+ if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
- peer -> needsDispatch = 1;
+ peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
}
droppedCommand = currentCommand;
@@ -752,11 +755,11 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel *
{
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
- if (! peer -> needsDispatch)
+ if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
- peer -> needsDispatch = 1;
+ peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
}
}
}
@@ -768,11 +771,11 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel *
{
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
- if (! peer -> needsDispatch)
+ if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
- peer -> needsDispatch = 1;
+ peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
}
droppedCommand = currentCommand;
@@ -809,11 +812,11 @@ enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * ch
enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand));
- if (! peer -> needsDispatch)
+ if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
- peer -> needsDispatch = 1;
+ peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
}
if (! enet_list_empty (& channel -> incomingUnreliableCommands))
diff --git a/thirdparty/enet/protocol.c b/thirdparty/enet/protocol.c
index cbeea1a763..fefc0e6f0a 100644
--- a/thirdparty/enet/protocol.c
+++ b/thirdparty/enet/protocol.c
@@ -9,7 +9,6 @@
#include "enet/time.h"
#include "enet/enet.h"
-
static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
{
0,
@@ -49,11 +48,11 @@ enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState st
{
enet_protocol_change_state (host, peer, state);
- if (! peer -> needsDispatch)
+ if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
{
enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
- peer -> needsDispatch = 1;
+ peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
}
}
@@ -64,7 +63,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
{
ENetPeer * peer = (ENetPeer *) enet_list_remove (enet_list_begin (& host -> dispatchQueue));
- peer -> needsDispatch = 0;
+ peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH;
switch (peer -> state)
{
@@ -102,7 +101,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
if (! enet_list_empty (& peer -> dispatchedCommands))
{
- peer -> needsDispatch = 1;
+ peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
}
@@ -164,7 +163,10 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
{
ENetOutgoingCommand * outgoingCommand;
- while (! enet_list_empty (& peer -> sentUnreliableCommands))
+ if (enet_list_empty (& peer -> sentUnreliableCommands))
+ return;
+
+ do
{
outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
@@ -183,7 +185,13 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
}
enet_free (outgoingCommand);
- }
+ } while (! enet_list_empty (& peer -> sentUnreliableCommands));
+
+ if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
+ enet_list_empty (& peer -> outgoingReliableCommands) &&
+ enet_list_empty (& peer -> outgoingUnreliableCommands) &&
+ enet_list_empty (& peer -> sentReliableCommands))
+ enet_peer_disconnect (peer, peer -> eventData);
}
static ENetProtocolCommand
@@ -843,24 +851,29 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer *
if (ENET_TIME_LESS (host -> serviceTime, receivedSentTime))
return 0;
- peer -> lastReceiveTime = host -> serviceTime;
- peer -> earliestTimeout = 0;
-
roundTripTime = ENET_TIME_DIFFERENCE (host -> serviceTime, receivedSentTime);
+ roundTripTime = ENET_MAX (roundTripTime, 1);
+
+ if (peer -> lastReceiveTime > 0)
+ {
+ enet_uint32 accumRoundTripTime = (peer -> roundTripTime << 8) + peer -> roundTripTimeRemainder;
+ enet_uint32 accumRoundTripTimeVariance = (peer -> roundTripTimeVariance << 8) + peer -> roundTripTimeVarianceRemainder;
- enet_peer_throttle (peer, roundTripTime);
+ enet_peer_throttle (peer, roundTripTime);
- peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
+ roundTripTime <<= 8;
+ accumRoundTripTimeVariance = (accumRoundTripTimeVariance * 3 + ENET_DIFFERENCE (roundTripTime, accumRoundTripTime)) / 4;
+ accumRoundTripTime = (accumRoundTripTime * 7 + roundTripTime) / 8;
- if (roundTripTime >= peer -> roundTripTime)
- {
- peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
- peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
+ peer -> roundTripTime = accumRoundTripTime >> 8;
+ peer -> roundTripTimeRemainder = accumRoundTripTime & 0xFF;
+ peer -> roundTripTimeVariance = accumRoundTripTimeVariance >> 8;
+ peer -> roundTripTimeVarianceRemainder = accumRoundTripTimeVariance & 0xFF;
}
else
{
- peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
- peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
+ peer -> roundTripTime = roundTripTime;
+ peer -> roundTripTimeVariance = (roundTripTime + 1) / 2;
}
if (peer -> roundTripTime < peer -> lowestRoundTripTime)
@@ -873,12 +886,15 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer *
ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval)
{
peer -> lastRoundTripTime = peer -> lowestRoundTripTime;
- peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance;
+ peer -> lastRoundTripTimeVariance = ENET_MAX (peer -> highestRoundTripTimeVariance, 2);
peer -> lowestRoundTripTime = peer -> roundTripTime;
peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
peer -> packetThrottleEpoch = host -> serviceTime;
}
+ peer -> lastReceiveTime = ENET_MAX (host -> serviceTime, 1);
+ peer -> earliestTimeout = 0;
+
receivedReliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedReliableSequenceNumber);
commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID);
@@ -1253,7 +1269,7 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
}
}
- return -1;
+ return 0;
}
static void
@@ -1406,7 +1422,8 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
enet_list_empty (& peer -> outgoingReliableCommands) &&
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
- enet_list_empty (& peer -> sentReliableCommands))
+ enet_list_empty (& peer -> sentReliableCommands) &&
+ enet_list_empty (& peer -> sentUnreliableCommands))
enet_peer_disconnect (peer, peer -> eventData);
}
@@ -1654,19 +1671,9 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
#ifdef ENET_DEBUG
printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0);
#endif
-
- currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
- if (packetLoss >= currentPeer -> packetLoss)
- {
- currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
- currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
- }
- else
- {
- currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
- currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
- }
+ currentPeer -> packetLossVariance = (currentPeer -> packetLossVariance * 3 + ENET_DIFFERENCE (packetLoss, currentPeer -> packetLoss)) / 4;
+ currentPeer -> packetLoss = (currentPeer -> packetLoss * 7 + packetLoss) / 8;
currentPeer -> packetLossEpoch = host -> serviceTime;
currentPeer -> packetsSent = 0;
@@ -1691,7 +1698,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
& host -> buffers [1], host -> bufferCount - 1,
originalSize,
host -> packetData [1],
- originalSize);
+ originalSize);
if (compressedSize > 0 && compressedSize < originalSize)
{
host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED;
diff --git a/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8.cpp b/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8.cpp
index 5656556db9..5c7ebed788 100644
--- a/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8.cpp
+++ b/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8.cpp
@@ -508,7 +508,7 @@ namespace Etc
int iMaxRed1 = iColor1Red + (int)a_uiRadius;
if (iMaxRed1 > 15)
{
- iMinRed1 = 15;
+ iMaxRed1 = 15;
}
int iMinGreen1 = iColor1Green - (int)a_uiRadius;
@@ -519,7 +519,7 @@ namespace Etc
int iMaxGreen1 = iColor1Green + (int)a_uiRadius;
if (iMaxGreen1 > 15)
{
- iMinGreen1 = 15;
+ iMaxGreen1 = 15;
}
int iMinBlue1 = iColor1Blue - (int)a_uiRadius;
@@ -530,7 +530,7 @@ namespace Etc
int iMaxBlue1 = iColor1Blue + (int)a_uiRadius;
if (iMaxBlue1 > 15)
{
- iMinBlue1 = 15;
+ iMaxBlue1 = 15;
}
int iColor2Red = m_frgbaOriginalColor2_TAndH.IntRed(15.0f);
@@ -545,7 +545,7 @@ namespace Etc
int iMaxRed2 = iColor2Red + (int)a_uiRadius;
if (iMaxRed2 > 15)
{
- iMinRed2 = 15;
+ iMaxRed2 = 15;
}
int iMinGreen2 = iColor2Green - (int)a_uiRadius;
@@ -556,7 +556,7 @@ namespace Etc
int iMaxGreen2 = iColor2Green + (int)a_uiRadius;
if (iMaxGreen2 > 15)
{
- iMinGreen2 = 15;
+ iMaxGreen2 = 15;
}
int iMinBlue2 = iColor2Blue - (int)a_uiRadius;
@@ -567,7 +567,7 @@ namespace Etc
int iMaxBlue2 = iColor2Blue + (int)a_uiRadius;
if (iMaxBlue2 > 15)
{
- iMinBlue2 = 15;
+ iMaxBlue2 = 15;
}
for (unsigned int uiDistance = 0; uiDistance < TH_DISTANCES; uiDistance++)
@@ -761,7 +761,7 @@ namespace Etc
int iMaxRed1 = iColor1Red + (int)a_uiRadius;
if (iMaxRed1 > 15)
{
- iMinRed1 = 15;
+ iMaxRed1 = 15;
}
int iMinGreen1 = iColor1Green - (int)a_uiRadius;
@@ -772,7 +772,7 @@ namespace Etc
int iMaxGreen1 = iColor1Green + (int)a_uiRadius;
if (iMaxGreen1 > 15)
{
- iMinGreen1 = 15;
+ iMaxGreen1 = 15;
}
int iMinBlue1 = iColor1Blue - (int)a_uiRadius;
@@ -783,7 +783,7 @@ namespace Etc
int iMaxBlue1 = iColor1Blue + (int)a_uiRadius;
if (iMaxBlue1 > 15)
{
- iMinBlue1 = 15;
+ iMaxBlue1 = 15;
}
int iColor2Red = m_frgbaOriginalColor2_TAndH.IntRed(15.0f);
@@ -798,7 +798,7 @@ namespace Etc
int iMaxRed2 = iColor2Red + (int)a_uiRadius;
if (iMaxRed2 > 15)
{
- iMinRed2 = 15;
+ iMaxRed2 = 15;
}
int iMinGreen2 = iColor2Green - (int)a_uiRadius;
@@ -809,7 +809,7 @@ namespace Etc
int iMaxGreen2 = iColor2Green + (int)a_uiRadius;
if (iMaxGreen2 > 15)
{
- iMinGreen2 = 15;
+ iMaxGreen2 = 15;
}
int iMinBlue2 = iColor2Blue - (int)a_uiRadius;
@@ -820,7 +820,7 @@ namespace Etc
int iMaxBlue2 = iColor2Blue + (int)a_uiRadius;
if (iMaxBlue2 > 15)
{
- iMinBlue2 = 15;
+ iMaxBlue2 = 15;
}
for (unsigned int uiDistance = 0; uiDistance < TH_DISTANCES; uiDistance++)
diff --git a/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8A1.cpp b/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8A1.cpp
index ba2b42fb05..b94b64e68c 100644
--- a/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8A1.cpp
+++ b/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8A1.cpp
@@ -847,7 +847,7 @@ namespace Etc
int iMaxRed1 = iColor1Red + (int)a_uiRadius;
if (iMaxRed1 > 15)
{
- iMinRed1 = 15;
+ iMaxRed1 = 15;
}
int iMinGreen1 = iColor1Green - (int)a_uiRadius;
@@ -858,7 +858,7 @@ namespace Etc
int iMaxGreen1 = iColor1Green + (int)a_uiRadius;
if (iMaxGreen1 > 15)
{
- iMinGreen1 = 15;
+ iMaxGreen1 = 15;
}
int iMinBlue1 = iColor1Blue - (int)a_uiRadius;
@@ -869,7 +869,7 @@ namespace Etc
int iMaxBlue1 = iColor1Blue + (int)a_uiRadius;
if (iMaxBlue1 > 15)
{
- iMinBlue1 = 15;
+ iMaxBlue1 = 15;
}
int iColor2Red = m_frgbaOriginalColor2_TAndH.IntRed(15.0f);
@@ -884,7 +884,7 @@ namespace Etc
int iMaxRed2 = iColor2Red + (int)a_uiRadius;
if (iMaxRed2 > 15)
{
- iMinRed2 = 15;
+ iMaxRed2 = 15;
}
int iMinGreen2 = iColor2Green - (int)a_uiRadius;
@@ -895,7 +895,7 @@ namespace Etc
int iMaxGreen2 = iColor2Green + (int)a_uiRadius;
if (iMaxGreen2 > 15)
{
- iMinGreen2 = 15;
+ iMaxGreen2 = 15;
}
int iMinBlue2 = iColor2Blue - (int)a_uiRadius;
@@ -906,7 +906,7 @@ namespace Etc
int iMaxBlue2 = iColor2Blue + (int)a_uiRadius;
if (iMaxBlue2 > 15)
{
- iMinBlue2 = 15;
+ iMaxBlue2 = 15;
}
for (unsigned int uiDistance = 0; uiDistance < TH_DISTANCES; uiDistance++)
@@ -1108,7 +1108,7 @@ namespace Etc
int iMaxRed1 = iColor1Red + (int)a_uiRadius;
if (iMaxRed1 > 15)
{
- iMinRed1 = 15;
+ iMaxRed1 = 15;
}
int iMinGreen1 = iColor1Green - (int)a_uiRadius;
@@ -1119,7 +1119,7 @@ namespace Etc
int iMaxGreen1 = iColor1Green + (int)a_uiRadius;
if (iMaxGreen1 > 15)
{
- iMinGreen1 = 15;
+ iMaxGreen1 = 15;
}
int iMinBlue1 = iColor1Blue - (int)a_uiRadius;
@@ -1130,7 +1130,7 @@ namespace Etc
int iMaxBlue1 = iColor1Blue + (int)a_uiRadius;
if (iMaxBlue1 > 15)
{
- iMinBlue1 = 15;
+ iMaxBlue1 = 15;
}
int iColor2Red = m_frgbaOriginalColor2_TAndH.IntRed(15.0f);
@@ -1145,7 +1145,7 @@ namespace Etc
int iMaxRed2 = iColor2Red + (int)a_uiRadius;
if (iMaxRed2 > 15)
{
- iMinRed2 = 15;
+ iMaxRed2 = 15;
}
int iMinGreen2 = iColor2Green - (int)a_uiRadius;
@@ -1156,7 +1156,7 @@ namespace Etc
int iMaxGreen2 = iColor2Green + (int)a_uiRadius;
if (iMaxGreen2 > 15)
{
- iMinGreen2 = 15;
+ iMaxGreen2 = 15;
}
int iMinBlue2 = iColor2Blue - (int)a_uiRadius;
@@ -1167,7 +1167,7 @@ namespace Etc
int iMaxBlue2 = iColor2Blue + (int)a_uiRadius;
if (iMaxBlue2 > 15)
{
- iMinBlue2 = 15;
+ iMaxBlue2 = 15;
}
for (unsigned int uiDistance = 0; uiDistance < TH_DISTANCES; uiDistance++)
diff --git a/thirdparty/etc2comp/patches/fix-rgba8-max-channels.patch b/thirdparty/etc2comp/patches/fix-rgba8-max-channels.patch
new file mode 100644
index 0000000000..ea9b5640b6
--- /dev/null
+++ b/thirdparty/etc2comp/patches/fix-rgba8-max-channels.patch
@@ -0,0 +1,224 @@
+diff --git a/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8.cpp b/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8.cpp
+index 5656556db9..5c7ebed788 100644
+--- a/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8.cpp
++++ b/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8.cpp
+@@ -508,7 +508,7 @@ namespace Etc
+ int iMaxRed1 = iColor1Red + (int)a_uiRadius;
+ if (iMaxRed1 > 15)
+ {
+- iMinRed1 = 15;
++ iMaxRed1 = 15;
+ }
+
+ int iMinGreen1 = iColor1Green - (int)a_uiRadius;
+@@ -519,7 +519,7 @@ namespace Etc
+ int iMaxGreen1 = iColor1Green + (int)a_uiRadius;
+ if (iMaxGreen1 > 15)
+ {
+- iMinGreen1 = 15;
++ iMaxGreen1 = 15;
+ }
+
+ int iMinBlue1 = iColor1Blue - (int)a_uiRadius;
+@@ -530,7 +530,7 @@ namespace Etc
+ int iMaxBlue1 = iColor1Blue + (int)a_uiRadius;
+ if (iMaxBlue1 > 15)
+ {
+- iMinBlue1 = 15;
++ iMaxBlue1 = 15;
+ }
+
+ int iColor2Red = m_frgbaOriginalColor2_TAndH.IntRed(15.0f);
+@@ -545,7 +545,7 @@ namespace Etc
+ int iMaxRed2 = iColor2Red + (int)a_uiRadius;
+ if (iMaxRed2 > 15)
+ {
+- iMinRed2 = 15;
++ iMaxRed2 = 15;
+ }
+
+ int iMinGreen2 = iColor2Green - (int)a_uiRadius;
+@@ -556,7 +556,7 @@ namespace Etc
+ int iMaxGreen2 = iColor2Green + (int)a_uiRadius;
+ if (iMaxGreen2 > 15)
+ {
+- iMinGreen2 = 15;
++ iMaxGreen2 = 15;
+ }
+
+ int iMinBlue2 = iColor2Blue - (int)a_uiRadius;
+@@ -567,7 +567,7 @@ namespace Etc
+ int iMaxBlue2 = iColor2Blue + (int)a_uiRadius;
+ if (iMaxBlue2 > 15)
+ {
+- iMinBlue2 = 15;
++ iMaxBlue2 = 15;
+ }
+
+ for (unsigned int uiDistance = 0; uiDistance < TH_DISTANCES; uiDistance++)
+@@ -761,7 +761,7 @@ namespace Etc
+ int iMaxRed1 = iColor1Red + (int)a_uiRadius;
+ if (iMaxRed1 > 15)
+ {
+- iMinRed1 = 15;
++ iMaxRed1 = 15;
+ }
+
+ int iMinGreen1 = iColor1Green - (int)a_uiRadius;
+@@ -772,7 +772,7 @@ namespace Etc
+ int iMaxGreen1 = iColor1Green + (int)a_uiRadius;
+ if (iMaxGreen1 > 15)
+ {
+- iMinGreen1 = 15;
++ iMaxGreen1 = 15;
+ }
+
+ int iMinBlue1 = iColor1Blue - (int)a_uiRadius;
+@@ -783,7 +783,7 @@ namespace Etc
+ int iMaxBlue1 = iColor1Blue + (int)a_uiRadius;
+ if (iMaxBlue1 > 15)
+ {
+- iMinBlue1 = 15;
++ iMaxBlue1 = 15;
+ }
+
+ int iColor2Red = m_frgbaOriginalColor2_TAndH.IntRed(15.0f);
+@@ -798,7 +798,7 @@ namespace Etc
+ int iMaxRed2 = iColor2Red + (int)a_uiRadius;
+ if (iMaxRed2 > 15)
+ {
+- iMinRed2 = 15;
++ iMaxRed2 = 15;
+ }
+
+ int iMinGreen2 = iColor2Green - (int)a_uiRadius;
+@@ -809,7 +809,7 @@ namespace Etc
+ int iMaxGreen2 = iColor2Green + (int)a_uiRadius;
+ if (iMaxGreen2 > 15)
+ {
+- iMinGreen2 = 15;
++ iMaxGreen2 = 15;
+ }
+
+ int iMinBlue2 = iColor2Blue - (int)a_uiRadius;
+@@ -820,7 +820,7 @@ namespace Etc
+ int iMaxBlue2 = iColor2Blue + (int)a_uiRadius;
+ if (iMaxBlue2 > 15)
+ {
+- iMinBlue2 = 15;
++ iMaxBlue2 = 15;
+ }
+
+ for (unsigned int uiDistance = 0; uiDistance < TH_DISTANCES; uiDistance++)
+diff --git a/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8A1.cpp b/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8A1.cpp
+index ba2b42fb05..b94b64e68c 100644
+--- a/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8A1.cpp
++++ b/thirdparty/etc2comp/EtcBlock4x4Encoding_RGB8A1.cpp
+@@ -847,7 +847,7 @@ namespace Etc
+ int iMaxRed1 = iColor1Red + (int)a_uiRadius;
+ if (iMaxRed1 > 15)
+ {
+- iMinRed1 = 15;
++ iMaxRed1 = 15;
+ }
+
+ int iMinGreen1 = iColor1Green - (int)a_uiRadius;
+@@ -858,7 +858,7 @@ namespace Etc
+ int iMaxGreen1 = iColor1Green + (int)a_uiRadius;
+ if (iMaxGreen1 > 15)
+ {
+- iMinGreen1 = 15;
++ iMaxGreen1 = 15;
+ }
+
+ int iMinBlue1 = iColor1Blue - (int)a_uiRadius;
+@@ -869,7 +869,7 @@ namespace Etc
+ int iMaxBlue1 = iColor1Blue + (int)a_uiRadius;
+ if (iMaxBlue1 > 15)
+ {
+- iMinBlue1 = 15;
++ iMaxBlue1 = 15;
+ }
+
+ int iColor2Red = m_frgbaOriginalColor2_TAndH.IntRed(15.0f);
+@@ -884,7 +884,7 @@ namespace Etc
+ int iMaxRed2 = iColor2Red + (int)a_uiRadius;
+ if (iMaxRed2 > 15)
+ {
+- iMinRed2 = 15;
++ iMaxRed2 = 15;
+ }
+
+ int iMinGreen2 = iColor2Green - (int)a_uiRadius;
+@@ -895,7 +895,7 @@ namespace Etc
+ int iMaxGreen2 = iColor2Green + (int)a_uiRadius;
+ if (iMaxGreen2 > 15)
+ {
+- iMinGreen2 = 15;
++ iMaxGreen2 = 15;
+ }
+
+ int iMinBlue2 = iColor2Blue - (int)a_uiRadius;
+@@ -906,7 +906,7 @@ namespace Etc
+ int iMaxBlue2 = iColor2Blue + (int)a_uiRadius;
+ if (iMaxBlue2 > 15)
+ {
+- iMinBlue2 = 15;
++ iMaxBlue2 = 15;
+ }
+
+ for (unsigned int uiDistance = 0; uiDistance < TH_DISTANCES; uiDistance++)
+@@ -1108,7 +1108,7 @@ namespace Etc
+ int iMaxRed1 = iColor1Red + (int)a_uiRadius;
+ if (iMaxRed1 > 15)
+ {
+- iMinRed1 = 15;
++ iMaxRed1 = 15;
+ }
+
+ int iMinGreen1 = iColor1Green - (int)a_uiRadius;
+@@ -1119,7 +1119,7 @@ namespace Etc
+ int iMaxGreen1 = iColor1Green + (int)a_uiRadius;
+ if (iMaxGreen1 > 15)
+ {
+- iMinGreen1 = 15;
++ iMaxGreen1 = 15;
+ }
+
+ int iMinBlue1 = iColor1Blue - (int)a_uiRadius;
+@@ -1130,7 +1130,7 @@ namespace Etc
+ int iMaxBlue1 = iColor1Blue + (int)a_uiRadius;
+ if (iMaxBlue1 > 15)
+ {
+- iMinBlue1 = 15;
++ iMaxBlue1 = 15;
+ }
+
+ int iColor2Red = m_frgbaOriginalColor2_TAndH.IntRed(15.0f);
+@@ -1145,7 +1145,7 @@ namespace Etc
+ int iMaxRed2 = iColor2Red + (int)a_uiRadius;
+ if (iMaxRed2 > 15)
+ {
+- iMinRed2 = 15;
++ iMaxRed2 = 15;
+ }
+
+ int iMinGreen2 = iColor2Green - (int)a_uiRadius;
+@@ -1156,7 +1156,7 @@ namespace Etc
+ int iMaxGreen2 = iColor2Green + (int)a_uiRadius;
+ if (iMaxGreen2 > 15)
+ {
+- iMinGreen2 = 15;
++ iMaxGreen2 = 15;
+ }
+
+ int iMinBlue2 = iColor2Blue - (int)a_uiRadius;
+@@ -1167,7 +1167,7 @@ namespace Etc
+ int iMaxBlue2 = iColor2Blue + (int)a_uiRadius;
+ if (iMaxBlue2 > 15)
+ {
+- iMinBlue2 = 15;
++ iMaxBlue2 = 15;
+ }
+
+ for (unsigned int uiDistance = 0; uiDistance < TH_DISTANCES; uiDistance++)
diff --git a/thirdparty/freetype/include/freetype/config/ftconfig.h b/thirdparty/freetype/include/freetype/config/ftconfig.h
index 9466603377..14eecefc2a 100644
--- a/thirdparty/freetype/include/freetype/config/ftconfig.h
+++ b/thirdparty/freetype/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
*
* ANSI-specific configuration file (specification only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/config/ftheader.h b/thirdparty/freetype/include/freetype/config/ftheader.h
index 696d6ba906..e91598e207 100644
--- a/thirdparty/freetype/include/freetype/config/ftheader.h
+++ b/thirdparty/freetype/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
*
* Build macros of the FreeType 2 library.
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/config/ftoption.h b/thirdparty/freetype/include/freetype/config/ftoption.h
index 12f47a82e8..426806d2e4 100644
--- a/thirdparty/freetype/include/freetype/config/ftoption.h
+++ b/thirdparty/freetype/include/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
*
* User-selectable configuration macros (specification only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -294,6 +294,22 @@ FT_BEGIN_HEADER
/**************************************************************************
*
+ * Brotli support.
+ *
+ * FreeType uses the Brotli library to provide support for decompressing
+ * WOFF2 streams.
+ *
+ * Define this macro if you want to enable this 'feature'.
+ *
+ * If you use a build system like cmake or the `configure` script,
+ * options set by those programs have precedence, overwriting the value
+ * here with the configured one.
+ */
+/* #define FT_CONFIG_OPTION_USE_BROTLI */
+
+
+ /**************************************************************************
+ *
* Glyph Postscript Names handling
*
* By default, FreeType 2 is compiled with the 'psnames' module. This
@@ -871,9 +887,11 @@ FT_BEGIN_HEADER
*
* Compile 'autofit' module with fallback Indic script support, covering
* some scripts that the 'latin' submodule of the 'autofit' module doesn't
- * (yet) handle.
+ * (yet) handle. Currently, this needs option `AF_CONFIG_OPTION_CJK`.
*/
+#ifdef AF_CONFIG_OPTION_CJK
#define AF_CONFIG_OPTION_INDIC
+#endif
/**************************************************************************
diff --git a/thirdparty/freetype/include/freetype/config/ftstdlib.h b/thirdparty/freetype/include/freetype/config/ftstdlib.h
index 438b6145d5..d6091f8b3d 100644
--- a/thirdparty/freetype/include/freetype/config/ftstdlib.h
+++ b/thirdparty/freetype/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
* ANSI-specific library and header configuration file (specification
* only).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/freetype.h b/thirdparty/freetype/include/freetype/freetype.h
index a6bb667e3a..973264b125 100644
--- a/thirdparty/freetype/include/freetype/freetype.h
+++ b/thirdparty/freetype/include/freetype/freetype.h
@@ -4,7 +4,7 @@
*
* FreeType high-level API and common types (specification only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -1239,7 +1239,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_HAS_HORIZONTAL( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_HORIZONTAL )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_HORIZONTAL ) )
/**************************************************************************
@@ -1253,7 +1253,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_HAS_VERTICAL( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_VERTICAL )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_VERTICAL ) )
/**************************************************************************
@@ -1267,7 +1267,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_HAS_KERNING( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_KERNING )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_KERNING ) )
/**************************************************************************
@@ -1282,7 +1282,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_IS_SCALABLE( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_SCALABLE )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_SCALABLE ) )
/**************************************************************************
@@ -1301,7 +1301,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_IS_SFNT( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_SFNT )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_SFNT ) )
/**************************************************************************
@@ -1316,7 +1316,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_IS_FIXED_WIDTH( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) )
/**************************************************************************
@@ -1331,7 +1331,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_HAS_FIXED_SIZES( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES ) )
/**************************************************************************
@@ -1357,7 +1357,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_HAS_GLYPH_NAMES( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) )
/**************************************************************************
@@ -1372,7 +1372,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_HAS_MULTIPLE_MASTERS( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) )
/**************************************************************************
@@ -1394,7 +1394,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_IS_NAMED_INSTANCE( face ) \
- ( (face)->face_index & 0x7FFF0000L )
+ ( !!( (face)->face_index & 0x7FFF0000L ) )
/**************************************************************************
@@ -1412,7 +1412,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_IS_VARIATION( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_VARIATION )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_VARIATION ) )
/**************************************************************************
@@ -1429,7 +1429,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_IS_CID_KEYED( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_CID_KEYED )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_CID_KEYED ) )
/**************************************************************************
@@ -1443,7 +1443,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_IS_TRICKY( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_TRICKY )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_TRICKY ) )
/**************************************************************************
@@ -1460,7 +1460,7 @@ FT_BEGIN_HEADER
*
*/
#define FT_HAS_COLOR( face ) \
- ( (face)->face_flags & FT_FACE_FLAG_COLOR )
+ ( !!( (face)->face_flags & FT_FACE_FLAG_COLOR ) )
/**************************************************************************
@@ -2078,7 +2078,8 @@ FT_BEGIN_HEADER
* The size in bytes of the file in memory.
*
* pathname ::
- * A pointer to an 8-bit file pathname.
+ * A pointer to an 8-bit file pathname. The pointer is not owned by
+ * FreeType.
*
* stream ::
* A handle to a source stream object.
@@ -4781,7 +4782,7 @@ FT_BEGIN_HEADER
*/
#define FREETYPE_MAJOR 2
#define FREETYPE_MINOR 10
-#define FREETYPE_PATCH 1
+#define FREETYPE_PATCH 2
/**************************************************************************
diff --git a/thirdparty/freetype/include/freetype/ftadvanc.h b/thirdparty/freetype/include/freetype/ftadvanc.h
index 95c38f92bd..c30472bfdb 100644
--- a/thirdparty/freetype/include/freetype/ftadvanc.h
+++ b/thirdparty/freetype/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
*
* Quick computation of advance widths (specification only).
*
- * Copyright (C) 2008-2019 by
+ * Copyright (C) 2008-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftbbox.h b/thirdparty/freetype/include/freetype/ftbbox.h
index 22da70c0dc..294f996976 100644
--- a/thirdparty/freetype/include/freetype/ftbbox.h
+++ b/thirdparty/freetype/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
*
* FreeType exact bbox computation (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftbdf.h b/thirdparty/freetype/include/freetype/ftbdf.h
index 1c46da5985..61db27c8f8 100644
--- a/thirdparty/freetype/include/freetype/ftbdf.h
+++ b/thirdparty/freetype/include/freetype/ftbdf.h
@@ -4,7 +4,7 @@
*
* FreeType API for accessing BDF-specific strings (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftbitmap.h b/thirdparty/freetype/include/freetype/ftbitmap.h
index a6acdb9690..6c55455767 100644
--- a/thirdparty/freetype/include/freetype/ftbitmap.h
+++ b/thirdparty/freetype/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
*
* FreeType utility functions for bitmaps (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftbzip2.h b/thirdparty/freetype/include/freetype/ftbzip2.h
index ae88cfdbdb..cb8e8458ef 100644
--- a/thirdparty/freetype/include/freetype/ftbzip2.h
+++ b/thirdparty/freetype/include/freetype/ftbzip2.h
@@ -4,7 +4,7 @@
*
* Bzip2-compressed stream support.
*
- * Copyright (C) 2010-2019 by
+ * Copyright (C) 2010-2020 by
* Joel Klinghed.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftcache.h b/thirdparty/freetype/include/freetype/ftcache.h
index 0d589d0b34..d82c4815cf 100644
--- a/thirdparty/freetype/include/freetype/ftcache.h
+++ b/thirdparty/freetype/include/freetype/ftcache.h
@@ -4,7 +4,7 @@
*
* FreeType Cache subsystem (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftcid.h b/thirdparty/freetype/include/freetype/ftcid.h
index 8eafc1c78f..85b74e0047 100644
--- a/thirdparty/freetype/include/freetype/ftcid.h
+++ b/thirdparty/freetype/include/freetype/ftcid.h
@@ -4,7 +4,7 @@
*
* FreeType API for accessing CID font information (specification).
*
- * Copyright (C) 2007-2019 by
+ * Copyright (C) 2007-2020 by
* Dereg Clegg and Michael Toftdal.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftcolor.h b/thirdparty/freetype/include/freetype/ftcolor.h
index cf18021953..b744939dd8 100644
--- a/thirdparty/freetype/include/freetype/ftcolor.h
+++ b/thirdparty/freetype/include/freetype/ftcolor.h
@@ -4,7 +4,7 @@
*
* FreeType's glyph color management (specification).
*
- * Copyright (C) 2018-2019 by
+ * Copyright (C) 2018-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -125,9 +125,9 @@ FT_BEGIN_HEADER
* The number of palettes.
*
* palette_name_ids ::
- * A read-only array of palette name IDs with `num_palettes` elements,
- * corresponding to entries like 'dark' or 'light' in the font's 'name'
- * table.
+ * An optional read-only array of palette name IDs with `num_palettes`
+ * elements, corresponding to entries like 'dark' or 'light' in the
+ * font's 'name' table.
*
* An empty name ID in the 'CPAL' table gets represented as value
* 0xFFFF.
@@ -135,8 +135,8 @@ FT_BEGIN_HEADER
* `NULL` if the font's 'CPAL' table doesn't contain appropriate data.
*
* palette_flags ::
- * A read-only array of palette flags with `num_palettes` elements.
- * Possible values are an ORed combination of
+ * An optional read-only array of palette flags with `num_palettes`
+ * elements. Possible values are an ORed combination of
* @FT_PALETTE_FOR_LIGHT_BACKGROUND and
* @FT_PALETTE_FOR_DARK_BACKGROUND.
*
@@ -147,7 +147,7 @@ FT_BEGIN_HEADER
* same size.
*
* palette_entry_name_ids ::
- * A read-only array of palette entry name IDs with
+ * An optional read-only array of palette entry name IDs with
* `num_palette_entries`. In each palette, entries with the same index
* have the same function. For example, index~0 might correspond to
* string 'outline' in the font's 'name' table to indicate that this
@@ -163,6 +163,9 @@ FT_BEGIN_HEADER
* Use function @FT_Get_Sfnt_Name to map name IDs and entry name IDs to
* name strings.
*
+ * Use function @FT_Palette_Select to get the colors associated with a
+ * palette entry.
+ *
* @since:
* 2.10
*/
diff --git a/thirdparty/freetype/include/freetype/ftdriver.h b/thirdparty/freetype/include/freetype/ftdriver.h
index 497bde9f6e..19b666ecb0 100644
--- a/thirdparty/freetype/include/freetype/ftdriver.h
+++ b/thirdparty/freetype/include/freetype/ftdriver.h
@@ -4,7 +4,7 @@
*
* FreeType API for controlling driver modules (specification only).
*
- * Copyright (C) 2017-2019 by
+ * Copyright (C) 2017-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/fterrdef.h b/thirdparty/freetype/include/freetype/fterrdef.h
index 9bc7dc65e3..895d2d4dc8 100644
--- a/thirdparty/freetype/include/freetype/fterrdef.h
+++ b/thirdparty/freetype/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
*
* FreeType error codes (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/fterrors.h b/thirdparty/freetype/include/freetype/fterrors.h
index 2b47eb2096..771bc5db52 100644
--- a/thirdparty/freetype/include/freetype/fterrors.h
+++ b/thirdparty/freetype/include/freetype/fterrors.h
@@ -4,7 +4,7 @@
*
* FreeType error code handling (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftfntfmt.h b/thirdparty/freetype/include/freetype/ftfntfmt.h
index aae0b13264..ad5a1d4162 100644
--- a/thirdparty/freetype/include/freetype/ftfntfmt.h
+++ b/thirdparty/freetype/include/freetype/ftfntfmt.h
@@ -4,7 +4,7 @@
*
* Support functions for font formats.
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftgasp.h b/thirdparty/freetype/include/freetype/ftgasp.h
index 24673d8ce1..aca1a1329d 100644
--- a/thirdparty/freetype/include/freetype/ftgasp.h
+++ b/thirdparty/freetype/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
*
* Access of TrueType's 'gasp' table (specification).
*
- * Copyright (C) 2007-2019 by
+ * Copyright (C) 2007-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftglyph.h b/thirdparty/freetype/include/freetype/ftglyph.h
index fedab8491e..ec515a3694 100644
--- a/thirdparty/freetype/include/freetype/ftglyph.h
+++ b/thirdparty/freetype/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
*
* FreeType convenience functions to handle glyphs (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftgxval.h b/thirdparty/freetype/include/freetype/ftgxval.h
index b14f637c56..691a73b94a 100644
--- a/thirdparty/freetype/include/freetype/ftgxval.h
+++ b/thirdparty/freetype/include/freetype/ftgxval.h
@@ -4,7 +4,7 @@
*
* FreeType API for validating TrueTypeGX/AAT tables (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* Masatake YAMATO, Redhat K.K,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/include/freetype/ftgzip.h b/thirdparty/freetype/include/freetype/ftgzip.h
index 418c61228e..f588c8503b 100644
--- a/thirdparty/freetype/include/freetype/ftgzip.h
+++ b/thirdparty/freetype/include/freetype/ftgzip.h
@@ -4,7 +4,7 @@
*
* Gzip-compressed stream support.
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftimage.h b/thirdparty/freetype/include/freetype/ftimage.h
index face34fe49..185967c1b8 100644
--- a/thirdparty/freetype/include/freetype/ftimage.h
+++ b/thirdparty/freetype/include/freetype/ftimage.h
@@ -5,7 +5,7 @@
* FreeType glyph image formats and default raster interface
* (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftincrem.h b/thirdparty/freetype/include/freetype/ftincrem.h
index a4db02b585..8c00cfe41c 100644
--- a/thirdparty/freetype/include/freetype/ftincrem.h
+++ b/thirdparty/freetype/include/freetype/ftincrem.h
@@ -4,7 +4,7 @@
*
* FreeType incremental loading (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftlcdfil.h b/thirdparty/freetype/include/freetype/ftlcdfil.h
index 3a19d043bb..c5516d0e0d 100644
--- a/thirdparty/freetype/include/freetype/ftlcdfil.h
+++ b/thirdparty/freetype/include/freetype/ftlcdfil.h
@@ -5,7 +5,7 @@
* FreeType API for color filtering of subpixel bitmap glyphs
* (specification).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftlist.h b/thirdparty/freetype/include/freetype/ftlist.h
index 4782892d1a..3f6079f243 100644
--- a/thirdparty/freetype/include/freetype/ftlist.h
+++ b/thirdparty/freetype/include/freetype/ftlist.h
@@ -4,7 +4,7 @@
*
* Generic list support for FreeType (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftlzw.h b/thirdparty/freetype/include/freetype/ftlzw.h
index fd22968f5a..37a53c1b3e 100644
--- a/thirdparty/freetype/include/freetype/ftlzw.h
+++ b/thirdparty/freetype/include/freetype/ftlzw.h
@@ -4,7 +4,7 @@
*
* LZW-compressed stream support.
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftmac.h b/thirdparty/freetype/include/freetype/ftmac.h
index 92b9f3dc0f..c1a0aa373e 100644
--- a/thirdparty/freetype/include/freetype/ftmac.h
+++ b/thirdparty/freetype/include/freetype/ftmac.h
@@ -4,7 +4,7 @@
*
* Additional Mac-specific API.
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftmm.h b/thirdparty/freetype/include/freetype/ftmm.h
index f2e16b6408..0d839942b9 100644
--- a/thirdparty/freetype/include/freetype/ftmm.h
+++ b/thirdparty/freetype/include/freetype/ftmm.h
@@ -4,7 +4,7 @@
*
* FreeType Multiple Master font interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftmodapi.h b/thirdparty/freetype/include/freetype/ftmodapi.h
index 8d039c4f3a..01cb5fba88 100644
--- a/thirdparty/freetype/include/freetype/ftmodapi.h
+++ b/thirdparty/freetype/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
*
* FreeType modules public interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftmoderr.h b/thirdparty/freetype/include/freetype/ftmoderr.h
index e16993572c..5e6aeeb43e 100644
--- a/thirdparty/freetype/include/freetype/ftmoderr.h
+++ b/thirdparty/freetype/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
*
* FreeType module error offsets (specification).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftotval.h b/thirdparty/freetype/include/freetype/ftotval.h
index c034f48959..6f46c414bd 100644
--- a/thirdparty/freetype/include/freetype/ftotval.h
+++ b/thirdparty/freetype/include/freetype/ftotval.h
@@ -4,7 +4,7 @@
*
* FreeType API for validating OpenType tables (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftoutln.h b/thirdparty/freetype/include/freetype/ftoutln.h
index b72327b703..fa295b0ab6 100644
--- a/thirdparty/freetype/include/freetype/ftoutln.h
+++ b/thirdparty/freetype/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
* Support for the FT_Outline type used to store glyph shapes of
* most scalable font formats (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftparams.h b/thirdparty/freetype/include/freetype/ftparams.h
index c374ee2f2f..255c6bb160 100644
--- a/thirdparty/freetype/include/freetype/ftparams.h
+++ b/thirdparty/freetype/include/freetype/ftparams.h
@@ -4,7 +4,7 @@
*
* FreeType API for possible FT_Parameter tags (specification only).
*
- * Copyright (C) 2017-2019 by
+ * Copyright (C) 2017-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftpfr.h b/thirdparty/freetype/include/freetype/ftpfr.h
index b4eca76eb7..58fbbb78d3 100644
--- a/thirdparty/freetype/include/freetype/ftpfr.h
+++ b/thirdparty/freetype/include/freetype/ftpfr.h
@@ -4,7 +4,7 @@
*
* FreeType API for accessing PFR-specific data (specification only).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftrender.h b/thirdparty/freetype/include/freetype/ftrender.h
index a01c774272..6845111901 100644
--- a/thirdparty/freetype/include/freetype/ftrender.h
+++ b/thirdparty/freetype/include/freetype/ftrender.h
@@ -4,7 +4,7 @@
*
* FreeType renderer modules public interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftsizes.h b/thirdparty/freetype/include/freetype/ftsizes.h
index 6c63cef2bf..7dc9295211 100644
--- a/thirdparty/freetype/include/freetype/ftsizes.h
+++ b/thirdparty/freetype/include/freetype/ftsizes.h
@@ -4,7 +4,7 @@
*
* FreeType size objects management (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftsnames.h b/thirdparty/freetype/include/freetype/ftsnames.h
index 4d43602a42..2982760635 100644
--- a/thirdparty/freetype/include/freetype/ftsnames.h
+++ b/thirdparty/freetype/include/freetype/ftsnames.h
@@ -7,7 +7,7 @@
*
* This is _not_ used to retrieve glyph names!
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftstroke.h b/thirdparty/freetype/include/freetype/ftstroke.h
index 01a9c1811c..141af7d0ba 100644
--- a/thirdparty/freetype/include/freetype/ftstroke.h
+++ b/thirdparty/freetype/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
*
* FreeType path stroker (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -114,22 +114,19 @@ FT_BEGIN_HEADER
* FT_STROKER_LINEJOIN_MITER_FIXED ::
* Used to render mitered line joins, with fixed bevels if the miter
* limit is exceeded. The outer edges of the strokes for the two
- * segments are extended until they meet at an angle. If the segments
- * meet at too sharp an angle (such that the miter would extend from
- * the intersection of the segments a distance greater than the product
- * of the miter limit value and the border radius), then a bevel join
- * (see above) is used instead. This prevents long spikes being
- * created. `FT_STROKER_LINEJOIN_MITER_FIXED` generates a miter line
- * join as used in PostScript and PDF.
+ * segments are extended until they meet at an angle. A bevel join
+ * (see above) is used if the segments meet at too sharp an angle and
+ * the outer edges meet beyond a distance corresponding to the meter
+ * limit. This prevents long spikes being created.
+ * `FT_STROKER_LINEJOIN_MITER_FIXED` generates a miter line join as
+ * used in PostScript and PDF.
*
* FT_STROKER_LINEJOIN_MITER_VARIABLE ::
* FT_STROKER_LINEJOIN_MITER ::
* Used to render mitered line joins, with variable bevels if the miter
- * limit is exceeded. The intersection of the strokes is clipped at a
- * line perpendicular to the bisector of the angle between the strokes,
- * at the distance from the intersection of the segments equal to the
- * product of the miter limit value and the border radius. This
- * prevents long spikes being created.
+ * limit is exceeded. The intersection of the strokes is clipped
+ * perpendicularly to the bisector, at a distance corresponding to
+ * the miter limit. This prevents long spikes being created.
* `FT_STROKER_LINEJOIN_MITER_VARIABLE` generates a mitered line join
* as used in XPS. `FT_STROKER_LINEJOIN_MITER` is an alias for
* `FT_STROKER_LINEJOIN_MITER_VARIABLE`, retained for backward
@@ -296,12 +293,17 @@ FT_BEGIN_HEADER
* The line join style.
*
* miter_limit ::
- * The miter limit for the `FT_STROKER_LINEJOIN_MITER_FIXED` and
- * `FT_STROKER_LINEJOIN_MITER_VARIABLE` line join styles, expressed as
- * 16.16 fixed-point value.
+ * The maximum reciprocal sine of half-angle at the miter join,
+ * expressed as 16.16 fixed point value.
*
* @note:
- * The radius is expressed in the same units as the outline coordinates.
+ * The `radius` is expressed in the same units as the outline
+ * coordinates.
+ *
+ * The `miter_limit` multiplied by the `radius` gives the maximum size
+ * of a miter spike, at which it is clipped for
+ * @FT_STROKER_LINEJOIN_MITER_VARIABLE or replaced with a bevel join for
+ * @FT_STROKER_LINEJOIN_MITER_FIXED.
*
* This function calls @FT_Stroker_Rewind automatically.
*/
diff --git a/thirdparty/freetype/include/freetype/ftsynth.h b/thirdparty/freetype/include/freetype/ftsynth.h
index 8754f97cee..3882e69e61 100644
--- a/thirdparty/freetype/include/freetype/ftsynth.h
+++ b/thirdparty/freetype/include/freetype/ftsynth.h
@@ -5,7 +5,7 @@
* FreeType synthesizing code for emboldening and slanting
* (specification).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftsystem.h b/thirdparty/freetype/include/freetype/ftsystem.h
index 889a6ba172..f7fecb53f3 100644
--- a/thirdparty/freetype/include/freetype/ftsystem.h
+++ b/thirdparty/freetype/include/freetype/ftsystem.h
@@ -4,7 +4,7 @@
*
* FreeType low-level system interface definition (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/fttrigon.h b/thirdparty/freetype/include/freetype/fttrigon.h
index 37e1412fdf..968df1fbfd 100644
--- a/thirdparty/freetype/include/freetype/fttrigon.h
+++ b/thirdparty/freetype/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
*
* FreeType trigonometric functions (specification).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/fttypes.h b/thirdparty/freetype/include/freetype/fttypes.h
index 10571505a5..cb785d98b2 100644
--- a/thirdparty/freetype/include/freetype/fttypes.h
+++ b/thirdparty/freetype/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
*
* FreeType simple types definitions (specification only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftwinfnt.h b/thirdparty/freetype/include/freetype/ftwinfnt.h
index a2fba903d2..bacb8aa373 100644
--- a/thirdparty/freetype/include/freetype/ftwinfnt.h
+++ b/thirdparty/freetype/include/freetype/ftwinfnt.h
@@ -4,7 +4,7 @@
*
* FreeType API for accessing Windows fnt-specific data.
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/autohint.h b/thirdparty/freetype/include/freetype/internal/autohint.h
index f64c28bb2c..438f9c175e 100644
--- a/thirdparty/freetype/include/freetype/internal/autohint.h
+++ b/thirdparty/freetype/include/freetype/internal/autohint.h
@@ -4,7 +4,7 @@
*
* High-level 'autohint' module-specific interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/cffotypes.h b/thirdparty/freetype/include/freetype/internal/cffotypes.h
index b26893eab3..207eeda5ff 100644
--- a/thirdparty/freetype/include/freetype/internal/cffotypes.h
+++ b/thirdparty/freetype/include/freetype/internal/cffotypes.h
@@ -4,7 +4,7 @@
*
* Basic OpenType/CFF object type definitions (specification).
*
- * Copyright (C) 2017-2019 by
+ * Copyright (C) 2017-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/cfftypes.h b/thirdparty/freetype/include/freetype/internal/cfftypes.h
index 2fc905ec79..40b0fc73c9 100644
--- a/thirdparty/freetype/include/freetype/internal/cfftypes.h
+++ b/thirdparty/freetype/include/freetype/internal/cfftypes.h
@@ -5,7 +5,7 @@
* Basic OpenType/CFF type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftcalc.h b/thirdparty/freetype/include/freetype/internal/ftcalc.h
index 1811fcd1ea..3054a4c497 100644
--- a/thirdparty/freetype/include/freetype/internal/ftcalc.h
+++ b/thirdparty/freetype/include/freetype/internal/ftcalc.h
@@ -4,7 +4,7 @@
*
* Arithmetic computations (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftdebug.h b/thirdparty/freetype/include/freetype/internal/ftdebug.h
index 54a9673afa..00d258e642 100644
--- a/thirdparty/freetype/include/freetype/internal/ftdebug.h
+++ b/thirdparty/freetype/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
*
* Debugging and logging component (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftdrv.h b/thirdparty/freetype/include/freetype/internal/ftdrv.h
index 09e846e1c7..1dd9206c87 100644
--- a/thirdparty/freetype/include/freetype/internal/ftdrv.h
+++ b/thirdparty/freetype/include/freetype/internal/ftdrv.h
@@ -4,7 +4,7 @@
*
* FreeType internal font driver interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftgloadr.h b/thirdparty/freetype/include/freetype/internal/ftgloadr.h
index 770871d81b..6f3793b1c0 100644
--- a/thirdparty/freetype/include/freetype/internal/ftgloadr.h
+++ b/thirdparty/freetype/include/freetype/internal/ftgloadr.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph loader (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftmemory.h b/thirdparty/freetype/include/freetype/internal/ftmemory.h
index 78bd3bc229..e0758c127a 100644
--- a/thirdparty/freetype/include/freetype/internal/ftmemory.h
+++ b/thirdparty/freetype/include/freetype/internal/ftmemory.h
@@ -4,7 +4,7 @@
*
* The FreeType memory management macros (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg
*
* This file is part of the FreeType project, and may only be used,
@@ -57,6 +57,14 @@ FT_BEGIN_HEADER
/*************************************************************************/
+ /* The calculation `NULL + n' is undefined in C. Even if the resulting */
+ /* pointer doesn't get dereferenced, this causes warnings with */
+ /* sanitizers. */
+ /* */
+ /* We thus provide a macro that should be used if `base' can be NULL. */
+#define FT_OFFSET( base, count ) ( (base) ? (base) + (count) : NULL )
+
+
/*
* C++ refuses to handle statements like p = (void*)anything, with `p' a
* typed pointer. Since we don't have a `typeof' operator in standard C++,
@@ -153,10 +161,10 @@ extern "C++"
(FT_Long)(size), \
&error ) )
-#define FT_MEM_FREE( ptr ) \
- FT_BEGIN_STMNT \
- ft_mem_free( memory, (ptr) ); \
- (ptr) = NULL; \
+#define FT_MEM_FREE( ptr ) \
+ FT_BEGIN_STMNT \
+ FT_DEBUG_INNER( ft_mem_free( memory, (ptr) ) ); \
+ (ptr) = NULL; \
FT_END_STMNT
#define FT_MEM_NEW( ptr ) \
diff --git a/thirdparty/freetype/include/freetype/internal/ftobjs.h b/thirdparty/freetype/include/freetype/internal/ftobjs.h
index 0c1d3e5bf2..140eebc7c6 100644
--- a/thirdparty/freetype/include/freetype/internal/ftobjs.h
+++ b/thirdparty/freetype/include/freetype/internal/ftobjs.h
@@ -4,7 +4,7 @@
*
* The FreeType private base classes (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftpsprop.h b/thirdparty/freetype/include/freetype/internal/ftpsprop.h
index 574837f6d4..72907c4c3a 100644
--- a/thirdparty/freetype/include/freetype/internal/ftpsprop.h
+++ b/thirdparty/freetype/include/freetype/internal/ftpsprop.h
@@ -4,7 +4,7 @@
*
* Get and set properties of PostScript drivers (specification).
*
- * Copyright (C) 2017-2019 by
+ * Copyright (C) 2017-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftrfork.h b/thirdparty/freetype/include/freetype/internal/ftrfork.h
index 75b3e531bb..9a275a5155 100644
--- a/thirdparty/freetype/include/freetype/internal/ftrfork.h
+++ b/thirdparty/freetype/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
*
* Embedded resource forks accessor (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* Masatake YAMATO and Redhat K.K.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftserv.h b/thirdparty/freetype/include/freetype/internal/ftserv.h
index 8836cf3f18..bcaf4720d5 100644
--- a/thirdparty/freetype/include/freetype/internal/ftserv.h
+++ b/thirdparty/freetype/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
*
* The FreeType services (specification only).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftstream.h b/thirdparty/freetype/include/freetype/internal/ftstream.h
index a579a039b9..f3b3ef0d02 100644
--- a/thirdparty/freetype/include/freetype/internal/ftstream.h
+++ b/thirdparty/freetype/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
*
* Stream handling (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/fttrace.h b/thirdparty/freetype/include/freetype/internal/fttrace.h
index f5f9598046..58bd77413c 100644
--- a/thirdparty/freetype/include/freetype/internal/fttrace.h
+++ b/thirdparty/freetype/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
*
* Tracing handling (specification only).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -49,6 +49,7 @@ FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */
FT_TRACE_DEF( sfdriver ) /* SFNT font driver (sfdriver.c) */
FT_TRACE_DEF( sfobjs ) /* SFNT object handler (sfobjs.c) */
FT_TRACE_DEF( sfwoff ) /* WOFF format handler (sfwoff.c) */
+FT_TRACE_DEF( sfwoff2 ) /* WOFF2 format handler (sfwoff2.c) */
FT_TRACE_DEF( ttbdf ) /* TrueType embedded BDF (ttbdf.c) */
FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */
FT_TRACE_DEF( ttcolr ) /* glyph layer table (ttcolr.c) */
diff --git a/thirdparty/freetype/include/freetype/internal/ftvalid.h b/thirdparty/freetype/include/freetype/internal/ftvalid.h
index 38aa06cc4e..62aea4dc68 100644
--- a/thirdparty/freetype/include/freetype/internal/ftvalid.h
+++ b/thirdparty/freetype/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
*
* FreeType validation support (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/internal.h b/thirdparty/freetype/include/freetype/internal/internal.h
index 3c8830f7e4..766bf64c23 100644
--- a/thirdparty/freetype/include/freetype/internal/internal.h
+++ b/thirdparty/freetype/include/freetype/internal/internal.h
@@ -4,7 +4,7 @@
*
* Internal header files (specification only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/psaux.h b/thirdparty/freetype/include/freetype/internal/psaux.h
index f962a973de..8248a0ecdb 100644
--- a/thirdparty/freetype/include/freetype/internal/psaux.h
+++ b/thirdparty/freetype/include/freetype/internal/psaux.h
@@ -5,7 +5,7 @@
* Auxiliary functions and data structures related to PostScript fonts
* (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/pshints.h b/thirdparty/freetype/include/freetype/internal/pshints.h
index 699acea6f5..cf0c65298c 100644
--- a/thirdparty/freetype/include/freetype/internal/pshints.h
+++ b/thirdparty/freetype/include/freetype/internal/pshints.h
@@ -6,7 +6,7 @@
* recorders (specification only). These are used to support native
* T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers.
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svbdf.h b/thirdparty/freetype/include/freetype/internal/services/svbdf.h
index e4786ed038..0ec9c7ccb0 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svbdf.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svbdf.h
@@ -4,7 +4,7 @@
*
* The FreeType BDF services (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svcfftl.h b/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
index 6c621732da..c2f42c1d17 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
@@ -4,7 +4,7 @@
*
* The FreeType CFF tables loader service (specification).
*
- * Copyright (C) 2017-2019 by
+ * Copyright (C) 2017-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svcid.h b/thirdparty/freetype/include/freetype/internal/services/svcid.h
index 555a5af5b9..b8efd8147b 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svcid.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svcid.h
@@ -4,7 +4,7 @@
*
* The FreeType CID font services (specification).
*
- * Copyright (C) 2007-2019 by
+ * Copyright (C) 2007-2020 by
* Derek Clegg and Michael Toftdal.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
index 6f4285ea8c..5ec84c933c 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
@@ -4,7 +4,7 @@
*
* The FreeType font format service (specification only).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svgldict.h b/thirdparty/freetype/include/freetype/internal/services/svgldict.h
index 0949621835..5a63883c90 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svgldict.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svgldict.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph dictionary services (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svgxval.h b/thirdparty/freetype/include/freetype/internal/services/svgxval.h
index 0bb76f3144..d0cb10a423 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svgxval.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svgxval.h
@@ -4,7 +4,7 @@
*
* FreeType API for validating TrueTypeGX/AAT tables (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/include/freetype/internal/services/svkern.h b/thirdparty/freetype/include/freetype/internal/services/svkern.h
index f992a327c1..891c61a755 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svkern.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svkern.h
@@ -4,7 +4,7 @@
*
* The FreeType Kerning service (specification).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svmetric.h b/thirdparty/freetype/include/freetype/internal/services/svmetric.h
index d688bc7c60..06faa4b4f8 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svmetric.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svmetric.h
@@ -4,7 +4,7 @@
*
* The FreeType services for metrics variations (specification).
*
- * Copyright (C) 2016-2019 by
+ * Copyright (C) 2016-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svmm.h b/thirdparty/freetype/include/freetype/internal/services/svmm.h
index 3652f2050a..fa044c92dd 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svmm.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svmm.h
@@ -4,7 +4,7 @@
*
* The FreeType Multiple Masters and GX var services (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svotval.h b/thirdparty/freetype/include/freetype/internal/services/svotval.h
index cab4c6efbb..34ad7ca9f1 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svotval.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svotval.h
@@ -4,7 +4,7 @@
*
* The FreeType OpenType validation service (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpfr.h b/thirdparty/freetype/include/freetype/internal/services/svpfr.h
index fd01d614dd..2dd075c5da 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpfr.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpfr.h
@@ -4,7 +4,7 @@
*
* Internal PFR service functions (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpostnm.h b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
index 18e3843cbe..86ab611382 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
@@ -4,7 +4,7 @@
*
* The FreeType PostScript name services (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svprop.h b/thirdparty/freetype/include/freetype/internal/services/svprop.h
index e48d0151ec..8f755436a1 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svprop.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svprop.h
@@ -4,7 +4,7 @@
*
* The FreeType property service (specification).
*
- * Copyright (C) 2012-2019 by
+ * Copyright (C) 2012-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpscmap.h b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
index dfac3bafa9..6c2ffe2e2a 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
@@ -4,7 +4,7 @@
*
* The FreeType PostScript charmap service (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
index fb4e0e3fa9..ade24dc2ba 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
@@ -4,7 +4,7 @@
*
* The FreeType PostScript info service (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svsfnt.h b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
index 464aa209f7..f3e81ca84e 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
@@ -4,7 +4,7 @@
*
* The FreeType SFNT table loading service (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svttcmap.h b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
index 0fcb81371d..fbb3115ed4 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
@@ -4,7 +4,7 @@
*
* The FreeType TrueType/sfnt cmap extra information service.
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* Masatake YAMATO, Redhat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/include/freetype/internal/services/svtteng.h b/thirdparty/freetype/include/freetype/internal/services/svtteng.h
index a852f5c6fb..6218d9efe0 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svtteng.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svtteng.h
@@ -4,7 +4,7 @@
*
* The FreeType TrueType engine query service (specification).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svttglyf.h b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
index c8798771fb..d9894e362d 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
@@ -4,7 +4,7 @@
*
* The FreeType TrueType glyph service.
*
- * Copyright (C) 2007-2019 by
+ * Copyright (C) 2007-2020 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
index 38ee020965..377f73d450 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
@@ -4,7 +4,7 @@
*
* The FreeType Windows FNT/FONT service (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/sfnt.h b/thirdparty/freetype/include/freetype/internal/sfnt.h
index b19241c306..b9c81a8f37 100644
--- a/thirdparty/freetype/include/freetype/internal/sfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/sfnt.h
@@ -4,7 +4,7 @@
*
* High-level 'sfnt' driver interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/t1types.h b/thirdparty/freetype/include/freetype/internal/t1types.h
index d94c8c1284..799c2939fa 100644
--- a/thirdparty/freetype/include/freetype/internal/t1types.h
+++ b/thirdparty/freetype/include/freetype/internal/t1types.h
@@ -5,7 +5,7 @@
* Basic Type1/Type2 type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/tttypes.h b/thirdparty/freetype/include/freetype/internal/tttypes.h
index 23db240e7c..1bddf102be 100644
--- a/thirdparty/freetype/include/freetype/internal/tttypes.h
+++ b/thirdparty/freetype/include/freetype/internal/tttypes.h
@@ -5,7 +5,7 @@
* Basic SFNT/TrueType type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/wofftypes.h b/thirdparty/freetype/include/freetype/internal/wofftypes.h
index ba55bf883e..26159b9d3e 100644
--- a/thirdparty/freetype/include/freetype/internal/wofftypes.h
+++ b/thirdparty/freetype/include/freetype/internal/wofftypes.h
@@ -5,7 +5,7 @@
* Basic WOFF/WOFF2 type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -104,6 +104,207 @@ FT_BEGIN_HEADER
} WOFF_TableRec, *WOFF_Table;
+ /**************************************************************************
+ *
+ * @struct:
+ * WOFF2_TtcFontRec
+ *
+ * @description:
+ * Metadata for a TTC font entry in WOFF2.
+ *
+ * @fields:
+ * flavor ::
+ * TTC font flavor.
+ *
+ * num_tables ::
+ * Number of tables in TTC, indicating number of elements in
+ * `table_indices`.
+ *
+ * table_indices ::
+ * Array of table indices for each TTC font.
+ */
+ typedef struct WOFF2_TtcFontRec_
+ {
+ FT_ULong flavor;
+ FT_UShort num_tables;
+ FT_UShort* table_indices;
+
+ } WOFF2_TtcFontRec, *WOFF2_TtcFont;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * WOFF2_HeaderRec
+ *
+ * @description:
+ * WOFF2 file format header.
+ *
+ * @fields:
+ * See
+ *
+ * https://www.w3.org/TR/WOFF2/#woff20Header
+ *
+ * @note:
+ * We don't care about the fields `reserved`, `majorVersion` and
+ * `minorVersion`, so they are not included. The `totalSfntSize` field
+ * does not necessarily represent the actual size of the uncompressed
+ * SFNT font stream, so that is used as a reference value instead.
+ */
+ typedef struct WOFF2_HeaderRec_
+ {
+ FT_ULong signature;
+ FT_ULong flavor;
+ FT_ULong length;
+ FT_UShort num_tables;
+ FT_ULong totalSfntSize;
+ FT_ULong totalCompressedSize;
+ FT_ULong metaOffset;
+ FT_ULong metaLength;
+ FT_ULong metaOrigLength;
+ FT_ULong privOffset;
+ FT_ULong privLength;
+
+ FT_ULong uncompressed_size; /* uncompressed brotli stream size */
+ FT_ULong compressed_offset; /* compressed stream offset */
+ FT_ULong header_version; /* version of original TTC Header */
+ FT_UShort num_fonts; /* number of fonts in TTC */
+ FT_ULong actual_sfnt_size; /* actual size of sfnt stream */
+
+ WOFF2_TtcFont ttc_fonts; /* metadata for fonts in a TTC */
+
+ } WOFF2_HeaderRec, *WOFF2_Header;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * WOFF2_TableRec
+ *
+ * @description:
+ * This structure describes a given table of a WOFF2 font.
+ *
+ * @fields:
+ * See
+ *
+ * https://www.w3.org/TR/WOFF2/#table_dir_format
+ */
+ typedef struct WOFF2_TableRec_
+ {
+ FT_Byte FlagByte; /* table type and flags */
+ FT_ULong Tag; /* table file offset */
+ FT_ULong dst_length; /* uncompressed table length */
+ FT_ULong TransformLength; /* transformed length */
+
+ FT_ULong flags; /* calculated flags */
+ FT_ULong src_offset; /* compressed table offset */
+ FT_ULong src_length; /* compressed table length */
+ FT_ULong dst_offset; /* uncompressed table offset */
+
+ } WOFF2_TableRec, *WOFF2_Table;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * WOFF2_InfoRec
+ *
+ * @description:
+ * Metadata for WOFF2 font that may be required for reconstruction of
+ * sfnt tables.
+ *
+ * @fields:
+ * header_checksum ::
+ * Checksum of SFNT offset table.
+ *
+ * num_glyphs ::
+ * Number of glyphs in the font.
+ *
+ * num_hmetrics ::
+ * `numberOfHMetrics` field in the 'hhea' table.
+ *
+ * x_mins ::
+ * `xMin` values of glyph bounding box.
+ *
+ * glyf_table ::
+ * A pointer to the `glyf' table record.
+ *
+ * loca_table ::
+ * A pointer to the `loca' table record.
+ *
+ * head_table ::
+ * A pointer to the `head' table record.
+ */
+ typedef struct WOFF2_InfoRec_
+ {
+ FT_ULong header_checksum;
+ FT_UShort num_glyphs;
+ FT_UShort num_hmetrics;
+ FT_Short* x_mins;
+
+ WOFF2_Table glyf_table;
+ WOFF2_Table loca_table;
+ WOFF2_Table head_table;
+
+ } WOFF2_InfoRec, *WOFF2_Info;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * WOFF2_SubstreamRec
+ *
+ * @description:
+ * This structure stores information about a substream in the transformed
+ * 'glyf' table in a WOFF2 stream.
+ *
+ * @fields:
+ * start ::
+ * Beginning of the substream relative to uncompressed table stream.
+ *
+ * offset ::
+ * Offset of the substream relative to uncompressed table stream.
+ *
+ * size ::
+ * Size of the substream.
+ */
+ typedef struct WOFF2_SubstreamRec_
+ {
+ FT_ULong start;
+ FT_ULong offset;
+ FT_ULong size;
+
+ } WOFF2_SubstreamRec, *WOFF2_Substream;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * WOFF2_PointRec
+ *
+ * @description:
+ * This structure stores information about a point in the transformed
+ * 'glyf' table in a WOFF2 stream.
+ *
+ * @fields:
+ * x ::
+ * x-coordinate of point.
+ *
+ * y ::
+ * y-coordinate of point.
+ *
+ * on_curve ::
+ * Set if point is on-curve.
+ */
+ typedef struct WOFF2_PointRec_
+ {
+ FT_Int x;
+ FT_Int y;
+ FT_Bool on_curve;
+
+ } WOFF2_PointRec, *WOFF2_Point;
+
+
FT_END_HEADER
#endif /* WOFFTYPES_H_ */
diff --git a/thirdparty/freetype/include/freetype/t1tables.h b/thirdparty/freetype/include/freetype/t1tables.h
index 645e645720..522d6ae6aa 100644
--- a/thirdparty/freetype/include/freetype/t1tables.h
+++ b/thirdparty/freetype/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
* Basic Type 1/Type 2 tables definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ttnameid.h b/thirdparty/freetype/include/freetype/ttnameid.h
index cc677de75a..9a00913ee7 100644
--- a/thirdparty/freetype/include/freetype/ttnameid.h
+++ b/thirdparty/freetype/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
*
* TrueType name ID definitions (specification only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/tttables.h b/thirdparty/freetype/include/freetype/tttables.h
index d04f810218..8108db7173 100644
--- a/thirdparty/freetype/include/freetype/tttables.h
+++ b/thirdparty/freetype/include/freetype/tttables.h
@@ -5,7 +5,7 @@
* Basic SFNT/TrueType tables definitions and interface
* (specification only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/tttags.h b/thirdparty/freetype/include/freetype/tttags.h
index bd0986eff0..f2b2a45266 100644
--- a/thirdparty/freetype/include/freetype/tttags.h
+++ b/thirdparty/freetype/include/freetype/tttags.h
@@ -4,7 +4,7 @@
*
* Tags for TrueType and OpenType tables (specification only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -107,6 +107,7 @@ FT_BEGIN_HEADER
#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' )
#define TTAG_VVAR FT_MAKE_TAG( 'V', 'V', 'A', 'R' )
#define TTAG_wOFF FT_MAKE_TAG( 'w', 'O', 'F', 'F' )
+#define TTAG_wOF2 FT_MAKE_TAG( 'w', 'O', 'F', '2' )
/* used by "Keyboard.dfont" on legacy Mac OS X */
#define TTAG_0xA5kbd FT_MAKE_TAG( 0xA5, 'k', 'b', 'd' )
diff --git a/thirdparty/freetype/include/ft2build.h b/thirdparty/freetype/include/ft2build.h
index e3f4887943..195e918335 100644
--- a/thirdparty/freetype/include/ft2build.h
+++ b/thirdparty/freetype/include/ft2build.h
@@ -4,7 +4,7 @@
*
* FreeType 2 build and setup macros.
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afangles.c b/thirdparty/freetype/src/autofit/afangles.c
index 9e1f7a21ff..a2d45eb72c 100644
--- a/thirdparty/freetype/src/autofit/afangles.c
+++ b/thirdparty/freetype/src/autofit/afangles.c
@@ -5,7 +5,7 @@
* Routines used to compute vector angles with limited accuracy
* and very high speed. It also contains sorting routines (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afblue.c b/thirdparty/freetype/src/autofit/afblue.c
index b99dbeb19c..63f9ed4589 100644
--- a/thirdparty/freetype/src/autofit/afblue.c
+++ b/thirdparty/freetype/src/autofit/afblue.c
@@ -7,7 +7,7 @@
*
* Auto-fitter data for blue strings (body).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -340,6 +340,12 @@
'\0',
'\xF0', '\x90', '\x92', '\x80', ' ', '\xF0', '\x90', '\x92', '\x82', ' ', '\xF0', '\x90', '\x92', '\x86', ' ', '\xF0', '\x90', '\x92', '\x88', ' ', '\xF0', '\x90', '\x92', '\x8A', ' ', '\xF0', '\x90', '\x92', '\x92', ' ', '\xF0', '\x90', '\x92', '\xA0', ' ', '\xF0', '\x90', '\x92', '\xA9', /* ð’€ ð’‚ ð’† ð’ˆ ð’Š ð’’ ð’  ð’© */
'\0',
+ '\xF0', '\x90', '\xB4', '\x83', ' ', '\xF0', '\x90', '\xB4', '\x80', ' ', '\xF0', '\x90', '\xB4', '\x86', ' ', '\xF0', '\x90', '\xB4', '\x96', ' ', '\xF0', '\x90', '\xB4', '\x95', /* ð´ƒ ð´€ ð´† ð´– ð´• */
+ '\0',
+ '\xF0', '\x90', '\xB4', '\x94', ' ', '\xF0', '\x90', '\xB4', '\x96', ' ', '\xF0', '\x90', '\xB4', '\x95', ' ', '\xF0', '\x90', '\xB4', '\x91', ' ', '\xF0', '\x90', '\xB4', '\x90', /* ð´” ð´– ð´• ð´‘ ð´ */
+ '\0',
+ '\xD9', '\x80', /* Ù€ */
+ '\0',
'\xEA', '\xA2', '\x9C', ' ', '\xEA', '\xA2', '\x9E', ' ', '\xEA', '\xA2', '\xB3', ' ', '\xEA', '\xA2', '\x82', ' ', '\xEA', '\xA2', '\x96', ' ', '\xEA', '\xA2', '\x92', ' ', '\xEA', '\xA2', '\x9D', ' ', '\xEA', '\xA2', '\x9B', /* ꢜ ꢞ ꢳ ꢂ ꢖ ꢒ ê¢ ê¢› */
'\0',
'\xEA', '\xA2', '\x82', ' ', '\xEA', '\xA2', '\xA8', ' ', '\xEA', '\xA2', '\xBA', ' ', '\xEA', '\xA2', '\xA4', ' ', '\xEA', '\xA2', '\x8E', /* ꢂ ꢨ ꢺ ꢤ ꢎ */
@@ -687,6 +693,10 @@
{ AF_BLUE_STRING_OSMANYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_OSMANYA_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_ROHINGYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_ROHINGYA_BOTTOM, 0 },
+ { AF_BLUE_STRING_ROHINGYA_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL },
+ { AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_SAURASHTRA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
diff --git a/thirdparty/freetype/src/autofit/afblue.cin b/thirdparty/freetype/src/autofit/afblue.cin
index 6545d1fd43..c6a697fee0 100644
--- a/thirdparty/freetype/src/autofit/afblue.cin
+++ b/thirdparty/freetype/src/autofit/afblue.cin
@@ -4,7 +4,7 @@
*
* Auto-fitter data for blue strings (body).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afblue.dat b/thirdparty/freetype/src/autofit/afblue.dat
index 46db43fe22..f8356ba3a1 100644
--- a/thirdparty/freetype/src/autofit/afblue.dat
+++ b/thirdparty/freetype/src/autofit/afblue.dat
@@ -2,7 +2,7 @@
//
// Auto-fitter data for blue strings.
//
-// Copyright (C) 2013-2019 by
+// Copyright (C) 2013-2020 by
// David Turner, Robert Wilhelm, and Werner Lemberg.
//
// This file is part of the FreeType project, and may only be used,
@@ -443,6 +443,13 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
AF_BLUE_STRING_OSMANYA_BOTTOM
"ð’€ ð’‚ ð’† ð’ˆ ð’Š ð’’ ð’  ð’©"
+ AF_BLUE_STRING_ROHINGYA_TOP
+ "ð´ƒ ð´€ ð´† ð´– ð´•"
+ AF_BLUE_STRING_ROHINGYA_BOTTOM
+ "ð´” ð´– ð´• ð´‘ ð´"
+ AF_BLUE_STRING_ROHINGYA_JOIN
+ "Ù€"
+
AF_BLUE_STRING_SAURASHTRA_TOP
"ꢜ ꢞ ꢳ ꢂ ꢖ ꢒ ê¢ ê¢›"
AF_BLUE_STRING_SAURASHTRA_BOTTOM
@@ -1002,6 +1009,12 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
{ AF_BLUE_STRING_OSMANYA_BOTTOM, 0 }
{ AF_BLUE_STRING_MAX, 0 }
+ AF_BLUE_STRINGSET_ROHG
+ { AF_BLUE_STRING_ROHINGYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_ROHINGYA_BOTTOM, 0 }
+ { AF_BLUE_STRING_ROHINGYA_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL }
+ { AF_BLUE_STRING_MAX, 0 }
+
AF_BLUE_STRINGSET_SAUR
{ AF_BLUE_STRING_SAURASHTRA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
{ AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0 }
diff --git a/thirdparty/freetype/src/autofit/afblue.h b/thirdparty/freetype/src/autofit/afblue.h
index b69b1df521..2b6a5cdda4 100644
--- a/thirdparty/freetype/src/autofit/afblue.h
+++ b/thirdparty/freetype/src/autofit/afblue.h
@@ -7,7 +7,7 @@
*
* Auto-fitter data for blue strings (specification).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -234,36 +234,39 @@ FT_BEGIN_HEADER
AF_BLUE_STRING_OSAGE_SMALL_DESCENDER = 4095,
AF_BLUE_STRING_OSMANYA_TOP = 4110,
AF_BLUE_STRING_OSMANYA_BOTTOM = 4150,
- AF_BLUE_STRING_SAURASHTRA_TOP = 4190,
- AF_BLUE_STRING_SAURASHTRA_BOTTOM = 4222,
- AF_BLUE_STRING_SHAVIAN_TOP = 4242,
- AF_BLUE_STRING_SHAVIAN_BOTTOM = 4252,
- AF_BLUE_STRING_SHAVIAN_DESCENDER = 4277,
- AF_BLUE_STRING_SHAVIAN_SMALL_TOP = 4287,
- AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM = 4322,
- AF_BLUE_STRING_SINHALA_TOP = 4337,
- AF_BLUE_STRING_SINHALA_BOTTOM = 4369,
- AF_BLUE_STRING_SINHALA_DESCENDER = 4401,
- AF_BLUE_STRING_SUNDANESE_TOP = 4445,
- AF_BLUE_STRING_SUNDANESE_BOTTOM = 4469,
- AF_BLUE_STRING_SUNDANESE_DESCENDER = 4501,
- AF_BLUE_STRING_TAI_VIET_TOP = 4509,
- AF_BLUE_STRING_TAI_VIET_BOTTOM = 4529,
- AF_BLUE_STRING_TAMIL_TOP = 4541,
- AF_BLUE_STRING_TAMIL_BOTTOM = 4573,
- AF_BLUE_STRING_TELUGU_TOP = 4605,
- AF_BLUE_STRING_TELUGU_BOTTOM = 4633,
- AF_BLUE_STRING_THAI_TOP = 4661,
- AF_BLUE_STRING_THAI_BOTTOM = 4685,
- AF_BLUE_STRING_THAI_ASCENDER = 4713,
- AF_BLUE_STRING_THAI_LARGE_ASCENDER = 4725,
- AF_BLUE_STRING_THAI_DESCENDER = 4737,
- AF_BLUE_STRING_THAI_LARGE_DESCENDER = 4753,
- AF_BLUE_STRING_THAI_DIGIT_TOP = 4761,
- AF_BLUE_STRING_TIFINAGH = 4773,
- AF_BLUE_STRING_VAI_TOP = 4805,
- AF_BLUE_STRING_VAI_BOTTOM = 4837,
- af_blue_1_1 = 4868,
+ AF_BLUE_STRING_ROHINGYA_TOP = 4190,
+ AF_BLUE_STRING_ROHINGYA_BOTTOM = 4215,
+ AF_BLUE_STRING_ROHINGYA_JOIN = 4240,
+ AF_BLUE_STRING_SAURASHTRA_TOP = 4243,
+ AF_BLUE_STRING_SAURASHTRA_BOTTOM = 4275,
+ AF_BLUE_STRING_SHAVIAN_TOP = 4295,
+ AF_BLUE_STRING_SHAVIAN_BOTTOM = 4305,
+ AF_BLUE_STRING_SHAVIAN_DESCENDER = 4330,
+ AF_BLUE_STRING_SHAVIAN_SMALL_TOP = 4340,
+ AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM = 4375,
+ AF_BLUE_STRING_SINHALA_TOP = 4390,
+ AF_BLUE_STRING_SINHALA_BOTTOM = 4422,
+ AF_BLUE_STRING_SINHALA_DESCENDER = 4454,
+ AF_BLUE_STRING_SUNDANESE_TOP = 4498,
+ AF_BLUE_STRING_SUNDANESE_BOTTOM = 4522,
+ AF_BLUE_STRING_SUNDANESE_DESCENDER = 4554,
+ AF_BLUE_STRING_TAI_VIET_TOP = 4562,
+ AF_BLUE_STRING_TAI_VIET_BOTTOM = 4582,
+ AF_BLUE_STRING_TAMIL_TOP = 4594,
+ AF_BLUE_STRING_TAMIL_BOTTOM = 4626,
+ AF_BLUE_STRING_TELUGU_TOP = 4658,
+ AF_BLUE_STRING_TELUGU_BOTTOM = 4686,
+ AF_BLUE_STRING_THAI_TOP = 4714,
+ AF_BLUE_STRING_THAI_BOTTOM = 4738,
+ AF_BLUE_STRING_THAI_ASCENDER = 4766,
+ AF_BLUE_STRING_THAI_LARGE_ASCENDER = 4778,
+ AF_BLUE_STRING_THAI_DESCENDER = 4790,
+ AF_BLUE_STRING_THAI_LARGE_DESCENDER = 4806,
+ AF_BLUE_STRING_THAI_DIGIT_TOP = 4814,
+ AF_BLUE_STRING_TIFINAGH = 4826,
+ AF_BLUE_STRING_VAI_TOP = 4858,
+ AF_BLUE_STRING_VAI_BOTTOM = 4890,
+ af_blue_1_1 = 4921,
#ifdef AF_CONFIG_OPTION_CJK
AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1,
AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203,
@@ -365,17 +368,18 @@ FT_BEGIN_HEADER
AF_BLUE_STRINGSET_ORKH = 196,
AF_BLUE_STRINGSET_OSGE = 199,
AF_BLUE_STRINGSET_OSMA = 207,
- AF_BLUE_STRINGSET_SAUR = 210,
- AF_BLUE_STRINGSET_SHAW = 213,
- AF_BLUE_STRINGSET_SINH = 219,
- AF_BLUE_STRINGSET_SUND = 223,
- AF_BLUE_STRINGSET_TAML = 227,
- AF_BLUE_STRINGSET_TAVT = 230,
- AF_BLUE_STRINGSET_TELU = 233,
- AF_BLUE_STRINGSET_TFNG = 236,
- AF_BLUE_STRINGSET_THAI = 239,
- AF_BLUE_STRINGSET_VAII = 247,
- af_blue_2_1 = 250,
+ AF_BLUE_STRINGSET_ROHG = 210,
+ AF_BLUE_STRINGSET_SAUR = 214,
+ AF_BLUE_STRINGSET_SHAW = 217,
+ AF_BLUE_STRINGSET_SINH = 223,
+ AF_BLUE_STRINGSET_SUND = 227,
+ AF_BLUE_STRINGSET_TAML = 231,
+ AF_BLUE_STRINGSET_TAVT = 234,
+ AF_BLUE_STRINGSET_TELU = 237,
+ AF_BLUE_STRINGSET_TFNG = 240,
+ AF_BLUE_STRINGSET_THAI = 243,
+ AF_BLUE_STRINGSET_VAII = 251,
+ af_blue_2_1 = 254,
#ifdef AF_CONFIG_OPTION_CJK
AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0,
af_blue_2_1_1 = af_blue_2_1 + 2,
diff --git a/thirdparty/freetype/src/autofit/afblue.hin b/thirdparty/freetype/src/autofit/afblue.hin
index 30a28dafa5..3957027091 100644
--- a/thirdparty/freetype/src/autofit/afblue.hin
+++ b/thirdparty/freetype/src/autofit/afblue.hin
@@ -4,7 +4,7 @@
*
* Auto-fitter data for blue strings (specification).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afcjk.c b/thirdparty/freetype/src/autofit/afcjk.c
index a61689bee3..ca6ce0c60c 100644
--- a/thirdparty/freetype/src/autofit/afcjk.c
+++ b/thirdparty/freetype/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for CJK writing system (body).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -806,7 +806,7 @@
{
AF_AxisHints axis = &hints->axis[dim];
AF_Segment segments = axis->segments;
- AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments );
FT_Error error;
AF_Segment seg;
diff --git a/thirdparty/freetype/src/autofit/afcjk.h b/thirdparty/freetype/src/autofit/afcjk.h
index 59acae5342..fd0f451aa8 100644
--- a/thirdparty/freetype/src/autofit/afcjk.h
+++ b/thirdparty/freetype/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for CJK writing system (specification).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afcover.h b/thirdparty/freetype/src/autofit/afcover.h
index ff207a97e0..03085ad07e 100644
--- a/thirdparty/freetype/src/autofit/afcover.h
+++ b/thirdparty/freetype/src/autofit/afcover.h
@@ -4,7 +4,7 @@
*
* Auto-fitter coverages (specification only).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afdummy.c b/thirdparty/freetype/src/autofit/afdummy.c
index 7e07a41e7d..77d31df974 100644
--- a/thirdparty/freetype/src/autofit/afdummy.c
+++ b/thirdparty/freetype/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
* Auto-fitter dummy routines to be used if no hinting should be
* performed (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afdummy.h b/thirdparty/freetype/src/autofit/afdummy.h
index ab9227d35d..efd799e84b 100644
--- a/thirdparty/freetype/src/autofit/afdummy.h
+++ b/thirdparty/freetype/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
* Auto-fitter dummy routines to be used if no hinting should be
* performed (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/aferrors.h b/thirdparty/freetype/src/autofit/aferrors.h
index 2ec336f72c..6c7d0e1d70 100644
--- a/thirdparty/freetype/src/autofit/aferrors.h
+++ b/thirdparty/freetype/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
*
* Autofitter error codes (specification only).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afglobal.c b/thirdparty/freetype/src/autofit/afglobal.c
index 6a9a1e5aaa..5ad4ea9211 100644
--- a/thirdparty/freetype/src/autofit/afglobal.c
+++ b/thirdparty/freetype/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
*
* Auto-fitter routines to compute global hinting values (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afglobal.h b/thirdparty/freetype/src/autofit/afglobal.h
index 52f38350db..fecf7af977 100644
--- a/thirdparty/freetype/src/autofit/afglobal.h
+++ b/thirdparty/freetype/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
* Auto-fitter routines to compute global hinting values
* (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afhints.c b/thirdparty/freetype/src/autofit/afhints.c
index ed111c4117..5a123b2ba3 100644
--- a/thirdparty/freetype/src/autofit/afhints.c
+++ b/thirdparty/freetype/src/autofit/afhints.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afhints.h b/thirdparty/freetype/src/autofit/afhints.h
index e0cf612f0c..6397f098f0 100644
--- a/thirdparty/freetype/src/autofit/afhints.h
+++ b/thirdparty/freetype/src/autofit/afhints.h
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afindic.c b/thirdparty/freetype/src/autofit/afindic.c
index a17117c712..bc2837a26d 100644
--- a/thirdparty/freetype/src/autofit/afindic.c
+++ b/thirdparty/freetype/src/autofit/afindic.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for Indic writing system (body).
*
- * Copyright (C) 2007-2019 by
+ * Copyright (C) 2007-2020 by
* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afindic.h b/thirdparty/freetype/src/autofit/afindic.h
index bc5bc59fa5..088b88b19d 100644
--- a/thirdparty/freetype/src/autofit/afindic.h
+++ b/thirdparty/freetype/src/autofit/afindic.h
@@ -5,7 +5,7 @@
* Auto-fitter hinting routines for Indic writing system
* (specification).
*
- * Copyright (C) 2007-2019 by
+ * Copyright (C) 2007-2020 by
* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/aflatin.c b/thirdparty/freetype/src/autofit/aflatin.c
index 27d4024882..b453fcdf69 100644
--- a/thirdparty/freetype/src/autofit/aflatin.c
+++ b/thirdparty/freetype/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for latin writing system (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -1910,7 +1910,7 @@
/* sense -- this is used to better detect and ignore serifs */
{
AF_Segment segments = axis->segments;
- AF_Segment segments_end = segments + axis->num_segments;
+ AF_Segment segments_end = FT_OFFSET( segments, axis->num_segments );
for ( segment = segments; segment < segments_end; segment++ )
@@ -2314,7 +2314,7 @@
*/
{
AF_Edge edges = axis->edges;
- AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges );
AF_Edge edge;
diff --git a/thirdparty/freetype/src/autofit/aflatin.h b/thirdparty/freetype/src/autofit/aflatin.h
index 40479538c2..62bc4c8d44 100644
--- a/thirdparty/freetype/src/autofit/aflatin.h
+++ b/thirdparty/freetype/src/autofit/aflatin.h
@@ -5,7 +5,7 @@
* Auto-fitter hinting routines for latin writing system
* (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/aflatin2.c b/thirdparty/freetype/src/autofit/aflatin2.c
index c601ab8d9a..7bd4156a0f 100644
--- a/thirdparty/freetype/src/autofit/aflatin2.c
+++ b/thirdparty/freetype/src/autofit/aflatin2.c
@@ -9,7 +9,7 @@
*
* Auto-fitter hinting routines for latin writing system (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -21,6 +21,7 @@
*/
+#include <ft2build.h>
#include FT_ADVANCES_H
diff --git a/thirdparty/freetype/src/autofit/aflatin2.h b/thirdparty/freetype/src/autofit/aflatin2.h
index 507cef3df2..c2aebc49ac 100644
--- a/thirdparty/freetype/src/autofit/aflatin2.h
+++ b/thirdparty/freetype/src/autofit/aflatin2.h
@@ -10,7 +10,7 @@
* Auto-fitter hinting routines for latin writing system
* (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afloader.c b/thirdparty/freetype/src/autofit/afloader.c
index 83743b7be1..a53fbf2d21 100644
--- a/thirdparty/freetype/src/autofit/afloader.c
+++ b/thirdparty/freetype/src/autofit/afloader.c
@@ -4,7 +4,7 @@
*
* Auto-fitter glyph loading routines (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afloader.h b/thirdparty/freetype/src/autofit/afloader.h
index d1e0f3c093..97282371cd 100644
--- a/thirdparty/freetype/src/autofit/afloader.h
+++ b/thirdparty/freetype/src/autofit/afloader.h
@@ -4,7 +4,7 @@
*
* Auto-fitter glyph loading routines (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afmodule.c b/thirdparty/freetype/src/autofit/afmodule.c
index 3e46a3655a..0bcae4cc25 100644
--- a/thirdparty/freetype/src/autofit/afmodule.c
+++ b/thirdparty/freetype/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
*
* Auto-fitter module implementation (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afmodule.h b/thirdparty/freetype/src/autofit/afmodule.h
index b410809aa8..efa0240b4b 100644
--- a/thirdparty/freetype/src/autofit/afmodule.h
+++ b/thirdparty/freetype/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
*
* Auto-fitter module implementation (specification).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afranges.c b/thirdparty/freetype/src/autofit/afranges.c
index 45c8bbfc95..d6ecf88910 100644
--- a/thirdparty/freetype/src/autofit/afranges.c
+++ b/thirdparty/freetype/src/autofit/afranges.c
@@ -4,7 +4,7 @@
*
* Auto-fitter Unicode script ranges (body).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -778,6 +778,18 @@
};
+ const AF_Script_UniRangeRec af_rohg_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x10D00, 0x10D3F ), /* Hanifi Rohingya */
+ AF_UNIRANGE_REC( 0, 0 )
+ };
+
+ const AF_Script_UniRangeRec af_rohg_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0, 0 )
+ };
+
+
const AF_Script_UniRangeRec af_saur_uniranges[] =
{
AF_UNIRANGE_REC( 0xA880, 0xA8DF ), /* Saurashtra */
diff --git a/thirdparty/freetype/src/autofit/afranges.h b/thirdparty/freetype/src/autofit/afranges.h
index d5917aefed..c2ffda4b0f 100644
--- a/thirdparty/freetype/src/autofit/afranges.h
+++ b/thirdparty/freetype/src/autofit/afranges.h
@@ -4,7 +4,7 @@
*
* Auto-fitter Unicode script ranges (specification).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afscript.h b/thirdparty/freetype/src/autofit/afscript.h
index 2da8c70183..36caaddc56 100644
--- a/thirdparty/freetype/src/autofit/afscript.h
+++ b/thirdparty/freetype/src/autofit/afscript.h
@@ -4,7 +4,7 @@
*
* Auto-fitter scripts (specification only).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -291,6 +291,12 @@
HINTING_BOTTOM_TO_TOP,
"\xF0\x90\x92\x86 \xF0\x90\x92\xA0" ) /* ð’† ð’  */
+ SCRIPT( rohg, ROHG,
+ "Hanifi Rohingya",
+ HB_SCRIPT_HANIFI_ROHINGYA,
+ HINTING_BOTTOM_TO_TOP,
+ "\xF0\x90\xB4\xB0" ) /* ð´° */
+
SCRIPT( saur, SAUR,
"Saurashtra",
HB_SCRIPT_SAURASHTRA,
diff --git a/thirdparty/freetype/src/autofit/afshaper.c b/thirdparty/freetype/src/autofit/afshaper.c
index a5191c6915..d3902db2ed 100644
--- a/thirdparty/freetype/src/autofit/afshaper.c
+++ b/thirdparty/freetype/src/autofit/afshaper.c
@@ -4,7 +4,7 @@
*
* HarfBuzz interface for accessing OpenType features (body).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afshaper.h b/thirdparty/freetype/src/autofit/afshaper.h
index 06a1e06616..a7dbf34f1a 100644
--- a/thirdparty/freetype/src/autofit/afshaper.h
+++ b/thirdparty/freetype/src/autofit/afshaper.h
@@ -4,7 +4,7 @@
*
* HarfBuzz interface for accessing OpenType features (specification).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afstyles.h b/thirdparty/freetype/src/autofit/afstyles.h
index 8d1d70812f..8d411ab0d7 100644
--- a/thirdparty/freetype/src/autofit/afstyles.h
+++ b/thirdparty/freetype/src/autofit/afstyles.h
@@ -4,7 +4,7 @@
*
* Auto-fitter styles (specification only).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -378,6 +378,13 @@
AF_BLUE_STRINGSET_OSMA,
AF_COVERAGE_DEFAULT )
+ STYLE( rohg_dflt, ROHG_DFLT,
+ "Hanifi Rohingya default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_ROHG,
+ AF_BLUE_STRINGSET_ROHG,
+ AF_COVERAGE_DEFAULT )
+
STYLE( saur_dflt, SAUR_DFLT,
"Saurashtra default style",
AF_WRITING_SYSTEM_LATIN,
diff --git a/thirdparty/freetype/src/autofit/aftypes.h b/thirdparty/freetype/src/autofit/aftypes.h
index 579003d27d..7ca0b59e32 100644
--- a/thirdparty/freetype/src/autofit/aftypes.h
+++ b/thirdparty/freetype/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
*
* Auto-fitter types (specification only).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afwarp.c b/thirdparty/freetype/src/autofit/afwarp.c
index 84e9753ad9..808280df5d 100644
--- a/thirdparty/freetype/src/autofit/afwarp.c
+++ b/thirdparty/freetype/src/autofit/afwarp.c
@@ -4,7 +4,7 @@
*
* Auto-fitter warping algorithm (body).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afwarp.h b/thirdparty/freetype/src/autofit/afwarp.h
index 9a2c9a42c1..cdea23e7de 100644
--- a/thirdparty/freetype/src/autofit/afwarp.h
+++ b/thirdparty/freetype/src/autofit/afwarp.h
@@ -4,7 +4,7 @@
*
* Auto-fitter warping algorithm (specification).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afwrtsys.h b/thirdparty/freetype/src/autofit/afwrtsys.h
index 5611cf441a..3990633d2d 100644
--- a/thirdparty/freetype/src/autofit/afwrtsys.h
+++ b/thirdparty/freetype/src/autofit/afwrtsys.h
@@ -4,7 +4,7 @@
*
* Auto-fitter writing systems (specification only).
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/autofit.c b/thirdparty/freetype/src/autofit/autofit.c
index facfec1744..88be8bf2bc 100644
--- a/thirdparty/freetype/src/autofit/autofit.c
+++ b/thirdparty/freetype/src/autofit/autofit.c
@@ -4,7 +4,7 @@
*
* Auto-fitter module (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/module.mk b/thirdparty/freetype/src/autofit/module.mk
index cf77b169f7..c32781f478 100644
--- a/thirdparty/freetype/src/autofit/module.mk
+++ b/thirdparty/freetype/src/autofit/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2003-2019 by
+# Copyright (C) 2003-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/autofit/rules.mk b/thirdparty/freetype/src/autofit/rules.mk
index c59da33a55..553ddce6b7 100644
--- a/thirdparty/freetype/src/autofit/rules.mk
+++ b/thirdparty/freetype/src/autofit/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2003-2019 by
+# Copyright (C) 2003-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/base/ftadvanc.c b/thirdparty/freetype/src/base/ftadvanc.c
index 0dfba57036..310bbba41e 100644
--- a/thirdparty/freetype/src/base/ftadvanc.c
+++ b/thirdparty/freetype/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
*
* Quick computation of advance widths (body).
*
- * Copyright (C) 2008-2019 by
+ * Copyright (C) 2008-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftbase.c b/thirdparty/freetype/src/base/ftbase.c
index fb8cbfcc27..b8242bb960 100644
--- a/thirdparty/freetype/src/base/ftbase.c
+++ b/thirdparty/freetype/src/base/ftbase.c
@@ -4,7 +4,7 @@
*
* Single object library component (body only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftbase.h b/thirdparty/freetype/src/base/ftbase.h
index 35b1c47fd9..472713addf 100644
--- a/thirdparty/freetype/src/base/ftbase.h
+++ b/thirdparty/freetype/src/base/ftbase.h
@@ -4,7 +4,7 @@
*
* Private functions used in the `base' module (specification).
*
- * Copyright (C) 2008-2019 by
+ * Copyright (C) 2008-2020 by
* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftbbox.c b/thirdparty/freetype/src/base/ftbbox.c
index a0b2c46f7b..9d9f9c4015 100644
--- a/thirdparty/freetype/src/base/ftbbox.c
+++ b/thirdparty/freetype/src/base/ftbbox.c
@@ -4,7 +4,7 @@
*
* FreeType bbox computation (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
@@ -294,10 +294,10 @@
if ( shift > 2 )
shift = 2;
- q1 <<= shift;
- q2 <<= shift;
- q3 <<= shift;
- q4 <<= shift;
+ q1 *= 1 << shift;
+ q2 *= 1 << shift;
+ q3 *= 1 << shift;
+ q4 *= 1 << shift;
}
else
{
diff --git a/thirdparty/freetype/src/base/ftbdf.c b/thirdparty/freetype/src/base/ftbdf.c
index c0fccd7b7c..a239e5f873 100644
--- a/thirdparty/freetype/src/base/ftbdf.c
+++ b/thirdparty/freetype/src/base/ftbdf.c
@@ -4,7 +4,7 @@
*
* FreeType API for accessing BDF-specific strings (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftbitmap.c b/thirdparty/freetype/src/base/ftbitmap.c
index 0e0a76fe40..18ac4c5f34 100644
--- a/thirdparty/freetype/src/base/ftbitmap.c
+++ b/thirdparty/freetype/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
*
* FreeType utility functions for bitmaps (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftcalc.c b/thirdparty/freetype/src/base/ftcalc.c
index 315dc44185..53550057b1 100644
--- a/thirdparty/freetype/src/base/ftcalc.c
+++ b/thirdparty/freetype/src/base/ftcalc.c
@@ -4,7 +4,7 @@
*
* Arithmetic computations (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftcid.c b/thirdparty/freetype/src/base/ftcid.c
index 190b23f357..17c25730e7 100644
--- a/thirdparty/freetype/src/base/ftcid.c
+++ b/thirdparty/freetype/src/base/ftcid.c
@@ -4,7 +4,7 @@
*
* FreeType API for accessing CID font information.
*
- * Copyright (C) 2007-2019 by
+ * Copyright (C) 2007-2020 by
* Derek Clegg and Michael Toftdal.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftcolor.c b/thirdparty/freetype/src/base/ftcolor.c
index 8cb057a365..986e9924a6 100644
--- a/thirdparty/freetype/src/base/ftcolor.c
+++ b/thirdparty/freetype/src/base/ftcolor.c
@@ -4,7 +4,7 @@
*
* FreeType's glyph color management (body).
*
- * Copyright (C) 2018-2019 by
+ * Copyright (C) 2018-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftdbgmem.c b/thirdparty/freetype/src/base/ftdbgmem.c
index 55cd269e1f..7f06c86006 100644
--- a/thirdparty/freetype/src/base/ftdbgmem.c
+++ b/thirdparty/freetype/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
*
* Memory debugger (body).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -621,8 +621,10 @@
if ( node->size < 0 )
ft_mem_debug_panic(
- "freeing memory block at %p more than once at (%s:%ld)\n"
- "block allocated at (%s:%ld) and released at (%s:%ld)",
+ "freeing memory block at %p more than once\n"
+ " at (%s:%ld)!\n"
+ " Block was allocated at (%s:%ld)\n"
+ " and released at (%s:%ld).",
address,
FT_FILENAME( _ft_debug_file ), _ft_debug_lineno,
FT_FILENAME( node->source->file_name ), node->source->line_no,
diff --git a/thirdparty/freetype/src/base/ftdebug.c b/thirdparty/freetype/src/base/ftdebug.c
index ec72337873..da1c1265e3 100644
--- a/thirdparty/freetype/src/base/ftdebug.c
+++ b/thirdparty/freetype/src/base/ftdebug.c
@@ -4,7 +4,7 @@
*
* Debugging and logging component (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/fterrors.c b/thirdparty/freetype/src/base/fterrors.c
index 84fe590289..8aa688fbe2 100644
--- a/thirdparty/freetype/src/base/fterrors.c
+++ b/thirdparty/freetype/src/base/fterrors.c
@@ -4,7 +4,7 @@
*
* FreeType API for error code handling.
*
- * Copyright (C) 2018-2019 by
+ * Copyright (C) 2018-2020 by
* Armin Hasitzka, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftfntfmt.c b/thirdparty/freetype/src/base/ftfntfmt.c
index 54ba537416..95e9b6e4c1 100644
--- a/thirdparty/freetype/src/base/ftfntfmt.c
+++ b/thirdparty/freetype/src/base/ftfntfmt.c
@@ -4,7 +4,7 @@
*
* FreeType utility file for font formats (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftfstype.c b/thirdparty/freetype/src/base/ftfstype.c
index 45e2d8089b..461d857077 100644
--- a/thirdparty/freetype/src/base/ftfstype.c
+++ b/thirdparty/freetype/src/base/ftfstype.c
@@ -4,7 +4,7 @@
*
* FreeType utility file to access FSType data (body).
*
- * Copyright (C) 2008-2019 by
+ * Copyright (C) 2008-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftgasp.c b/thirdparty/freetype/src/base/ftgasp.c
index 720fb113ca..0fd80b9cd6 100644
--- a/thirdparty/freetype/src/base/ftgasp.c
+++ b/thirdparty/freetype/src/base/ftgasp.c
@@ -4,7 +4,7 @@
*
* Access of TrueType's `gasp' table (body).
*
- * Copyright (C) 2007-2019 by
+ * Copyright (C) 2007-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftgloadr.c b/thirdparty/freetype/src/base/ftgloadr.c
index bfeed461a8..6032885c6b 100644
--- a/thirdparty/freetype/src/base/ftgloadr.c
+++ b/thirdparty/freetype/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
*
* The FreeType glyph loader (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg
*
* This file is part of the FreeType project, and may only be used,
@@ -146,9 +146,9 @@
FT_Outline* current = &loader->current.outline;
- current->points = base->points + base->n_points;
- current->tags = base->tags + base->n_points;
- current->contours = base->contours + base->n_contours;
+ current->points = FT_OFFSET( base->points, base->n_points );
+ current->tags = FT_OFFSET( base->tags, base->n_points );
+ current->contours = FT_OFFSET( base->contours, base->n_contours );
/* handle extra points table - if any */
if ( loader->use_extra )
@@ -169,6 +169,10 @@
FT_Memory memory = loader->memory;
+ if ( loader->max_points == 0 ||
+ loader->base.extra_points != NULL )
+ return FT_Err_Ok;
+
if ( !FT_NEW_ARRAY( loader->base.extra_points, 2 * loader->max_points ) )
{
loader->use_extra = 1;
@@ -189,7 +193,7 @@
FT_GlyphLoad current = &loader->current;
- current->subglyphs = base->subglyphs + base->num_subglyphs;
+ current->subglyphs = FT_OFFSET( base->subglyphs, base->num_subglyphs );
}
@@ -211,6 +215,10 @@
FT_UInt new_max, old_max;
+ error = FT_GlyphLoader_CreateExtra( loader );
+ if ( error )
+ return error;
+
/* check points & tags */
new_max = (FT_UInt)base->n_points + (FT_UInt)current->n_points +
n_points;
@@ -244,6 +252,10 @@
loader->max_points = new_max;
}
+ error = FT_GlyphLoader_CreateExtra( loader );
+ if ( error )
+ return error;
+
/* check contours */
old_max = loader->max_contours;
new_max = (FT_UInt)base->n_contours + (FT_UInt)current->n_contours +
diff --git a/thirdparty/freetype/src/base/ftglyph.c b/thirdparty/freetype/src/base/ftglyph.c
index e6b1327901..44654be780 100644
--- a/thirdparty/freetype/src/base/ftglyph.c
+++ b/thirdparty/freetype/src/base/ftglyph.c
@@ -4,7 +4,7 @@
*
* FreeType convenience functions to handle glyphs (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftgxval.c b/thirdparty/freetype/src/base/ftgxval.c
index 0677d26faa..fa32c5f6ca 100644
--- a/thirdparty/freetype/src/base/ftgxval.c
+++ b/thirdparty/freetype/src/base/ftgxval.c
@@ -4,7 +4,7 @@
*
* FreeType API for validating TrueTypeGX/AAT tables (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* Masatake YAMATO, Redhat K.K,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/base/ftinit.c b/thirdparty/freetype/src/base/ftinit.c
index c73cd78b83..1aab09a771 100644
--- a/thirdparty/freetype/src/base/ftinit.c
+++ b/thirdparty/freetype/src/base/ftinit.c
@@ -4,7 +4,7 @@
*
* FreeType initialization layer (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftlcdfil.c b/thirdparty/freetype/src/base/ftlcdfil.c
index d9f4af4293..d4ef93a518 100644
--- a/thirdparty/freetype/src/base/ftlcdfil.c
+++ b/thirdparty/freetype/src/base/ftlcdfil.c
@@ -4,7 +4,7 @@
*
* FreeType API for color filtering of subpixel bitmap glyphs (body).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftmac.c b/thirdparty/freetype/src/base/ftmac.c
index 5f23ceea9f..2de43a0146 100644
--- a/thirdparty/freetype/src/base/ftmac.c
+++ b/thirdparty/freetype/src/base/ftmac.c
@@ -8,7 +8,7 @@
* This file is for Mac OS X only; see builds/mac/ftoldmac.c for
* classic platforms built by MPW.
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftmm.c b/thirdparty/freetype/src/base/ftmm.c
index ba9e67f008..ef2e3d9588 100644
--- a/thirdparty/freetype/src/base/ftmm.c
+++ b/thirdparty/freetype/src/base/ftmm.c
@@ -4,7 +4,7 @@
*
* Multiple Master font support (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftobjs.c b/thirdparty/freetype/src/base/ftobjs.c
index e301f8f11a..1b042614d2 100644
--- a/thirdparty/freetype/src/base/ftobjs.c
+++ b/thirdparty/freetype/src/base/ftobjs.c
@@ -4,7 +4,7 @@
*
* The FreeType private base classes (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftotval.c b/thirdparty/freetype/src/base/ftotval.c
index 007576ce6e..9f69e0c1fd 100644
--- a/thirdparty/freetype/src/base/ftotval.c
+++ b/thirdparty/freetype/src/base/ftotval.c
@@ -4,7 +4,7 @@
*
* FreeType API for validating OpenType tables (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftoutln.c b/thirdparty/freetype/src/base/ftoutln.c
index 0e2ba3475d..faaae83294 100644
--- a/thirdparty/freetype/src/base/ftoutln.c
+++ b/thirdparty/freetype/src/base/ftoutln.c
@@ -4,7 +4,7 @@
*
* FreeType outline management (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -711,7 +711,7 @@
FT_Vector* limit;
- if ( !outline || !matrix )
+ if ( !outline || !matrix || !outline->points )
return;
vec = outline->points;
diff --git a/thirdparty/freetype/src/base/ftpatent.c b/thirdparty/freetype/src/base/ftpatent.c
index 020f4646eb..077a9b03fa 100644
--- a/thirdparty/freetype/src/base/ftpatent.c
+++ b/thirdparty/freetype/src/base/ftpatent.c
@@ -5,7 +5,7 @@
* FreeType API for checking patented TrueType bytecode instructions
* (body). Obsolete, retained for backward compatibility.
*
- * Copyright (C) 2007-2019 by
+ * Copyright (C) 2007-2020 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftpfr.c b/thirdparty/freetype/src/base/ftpfr.c
index aeff1db8bd..57e65665ff 100644
--- a/thirdparty/freetype/src/base/ftpfr.c
+++ b/thirdparty/freetype/src/base/ftpfr.c
@@ -4,7 +4,7 @@
*
* FreeType API for accessing PFR-specific data (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftpsprop.c b/thirdparty/freetype/src/base/ftpsprop.c
index 52b9d453ad..c63f864c1a 100644
--- a/thirdparty/freetype/src/base/ftpsprop.c
+++ b/thirdparty/freetype/src/base/ftpsprop.c
@@ -5,7 +5,7 @@
* Get and set properties of PostScript drivers (body).
* See `ftdriver.h' for available properties.
*
- * Copyright (C) 2017-2019 by
+ * Copyright (C) 2017-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -165,9 +165,9 @@
driver->hinting_engine = *hinting_engine;
else
error = FT_ERR( Unimplemented_Feature );
-
- return error;
}
+
+ return error;
}
else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
diff --git a/thirdparty/freetype/src/base/ftrfork.c b/thirdparty/freetype/src/base/ftrfork.c
index 73b7eb0ded..1bf7800f17 100644
--- a/thirdparty/freetype/src/base/ftrfork.c
+++ b/thirdparty/freetype/src/base/ftrfork.c
@@ -4,7 +4,7 @@
*
* Embedded resource forks accessor (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* Masatake YAMATO and Redhat K.K.
*
* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
diff --git a/thirdparty/freetype/src/base/ftsnames.c b/thirdparty/freetype/src/base/ftsnames.c
index 7ab3fe3cfa..25f5d45be5 100644
--- a/thirdparty/freetype/src/base/ftsnames.c
+++ b/thirdparty/freetype/src/base/ftsnames.c
@@ -7,7 +7,7 @@
*
* This is _not_ used to retrieve glyph names!
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftstream.c b/thirdparty/freetype/src/base/ftstream.c
index 4b0890d7fd..7dbf9b55fc 100644
--- a/thirdparty/freetype/src/base/ftstream.c
+++ b/thirdparty/freetype/src/base/ftstream.c
@@ -4,7 +4,7 @@
*
* I/O stream support (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -286,7 +286,7 @@
}
stream->cursor = stream->base;
- stream->limit = stream->cursor + count;
+ stream->limit = FT_OFFSET( stream->cursor, count );
stream->pos += read_bytes;
}
else
diff --git a/thirdparty/freetype/src/base/ftstroke.c b/thirdparty/freetype/src/base/ftstroke.c
index 1b2c0f657c..3369dc24b1 100644
--- a/thirdparty/freetype/src/base/ftstroke.c
+++ b/thirdparty/freetype/src/base/ftstroke.c
@@ -4,7 +4,7 @@
*
* FreeType path stroker (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -540,63 +540,52 @@
FT_Angle angle_start,
FT_Angle angle_diff )
{
- FT_Angle total, angle, step, rotate, next, theta;
- FT_Vector a, b, a2, b2;
- FT_Fixed length;
+ FT_Fixed coef;
+ FT_Vector a0, a1, a2, a3;
+ FT_Int i, arcs = 1;
FT_Error error = FT_Err_Ok;
- /* compute start point */
- FT_Vector_From_Polar( &a, radius, angle_start );
- a.x += center->x;
- a.y += center->y;
+ /* number of cubic arcs to draw */
+ while ( angle_diff > FT_ARC_CUBIC_ANGLE * arcs ||
+ -angle_diff > FT_ARC_CUBIC_ANGLE * arcs )
+ arcs++;
- total = angle_diff;
- angle = angle_start;
- rotate = ( angle_diff >= 0 ) ? FT_ANGLE_PI2 : -FT_ANGLE_PI2;
+ /* control tangents */
+ coef = FT_Tan( angle_diff / ( 4 * arcs ) );
+ coef += coef / 3;
- while ( total != 0 )
- {
- step = total;
- if ( step > FT_ARC_CUBIC_ANGLE )
- step = FT_ARC_CUBIC_ANGLE;
-
- else if ( step < -FT_ARC_CUBIC_ANGLE )
- step = -FT_ARC_CUBIC_ANGLE;
-
- next = angle + step;
- theta = step;
- if ( theta < 0 )
- theta = -theta;
+ /* compute start and first control point */
+ FT_Vector_From_Polar( &a0, radius, angle_start );
+ a1.x = FT_MulFix( -a0.y, coef );
+ a1.y = FT_MulFix( a0.x, coef );
- theta >>= 1;
+ a0.x += center->x;
+ a0.y += center->y;
+ a1.x += a0.x;
+ a1.y += a0.y;
- /* compute end point */
- FT_Vector_From_Polar( &b, radius, next );
- b.x += center->x;
- b.y += center->y;
-
- /* compute first and second control points */
- length = FT_MulDiv( radius, FT_Sin( theta ) * 4,
- ( 0x10000L + FT_Cos( theta ) ) * 3 );
-
- FT_Vector_From_Polar( &a2, length, angle + rotate );
- a2.x += a.x;
- a2.y += a.y;
+ for ( i = 1; i <= arcs; i++ )
+ {
+ /* compute end and second control point */
+ FT_Vector_From_Polar( &a3, radius,
+ angle_start + i * angle_diff / arcs );
+ a2.x = FT_MulFix( a3.y, coef );
+ a2.y = FT_MulFix( -a3.x, coef );
- FT_Vector_From_Polar( &b2, length, next - rotate );
- b2.x += b.x;
- b2.y += b.y;
+ a3.x += center->x;
+ a3.y += center->y;
+ a2.x += a3.x;
+ a2.y += a3.y;
/* add cubic arc */
- error = ft_stroke_border_cubicto( border, &a2, &b2, &b );
+ error = ft_stroke_border_cubicto( border, &a1, &a2, &a3 );
if ( error )
break;
- /* process the rest of the arc ?? */
- a = b;
- total -= step;
- angle = next;
+ /* a0 = a3; */
+ a1.x = a3.x - a2.x + a3.x;
+ a1.y = a3.y - a2.y + a3.y;
}
return error;
@@ -934,55 +923,40 @@
error = ft_stroker_arcto( stroker, side );
}
- else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
+ else
{
- /* add a square cap */
- FT_Vector delta, delta2;
- FT_Angle rotate = FT_SIDE_TO_ROTATE( side );
+ /* add a square or butt cap */
+ FT_Vector middle, delta;
FT_Fixed radius = stroker->radius;
FT_StrokeBorder border = stroker->borders + side;
- FT_Vector_From_Polar( &delta2, radius, angle + rotate );
- FT_Vector_From_Polar( &delta, radius, angle );
-
- delta.x += stroker->center.x + delta2.x;
- delta.y += stroker->center.y + delta2.y;
-
- error = ft_stroke_border_lineto( border, &delta, FALSE );
- if ( error )
- goto Exit;
-
- FT_Vector_From_Polar( &delta2, radius, angle - rotate );
- FT_Vector_From_Polar( &delta, radius, angle );
-
- delta.x += delta2.x + stroker->center.x;
- delta.y += delta2.y + stroker->center.y;
+ /* compute middle point and first angle point */
+ FT_Vector_From_Polar( &middle, radius, angle );
+ delta.x = side ? middle.y : -middle.y;
+ delta.y = side ? -middle.x : middle.x;
- error = ft_stroke_border_lineto( border, &delta, FALSE );
- }
- else if ( stroker->line_cap == FT_STROKER_LINECAP_BUTT )
- {
- /* add a butt ending */
- FT_Vector delta;
- FT_Angle rotate = FT_SIDE_TO_ROTATE( side );
- FT_Fixed radius = stroker->radius;
- FT_StrokeBorder border = stroker->borders + side;
-
-
- FT_Vector_From_Polar( &delta, radius, angle + rotate );
+ if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
+ {
+ middle.x += stroker->center.x;
+ middle.y += stroker->center.y;
+ }
+ else /* FT_STROKER_LINECAP_BUTT */
+ {
+ middle.x = stroker->center.x;
+ middle.y = stroker->center.y;
+ }
- delta.x += stroker->center.x;
- delta.y += stroker->center.y;
+ delta.x += middle.x;
+ delta.y += middle.y;
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
goto Exit;
- FT_Vector_From_Polar( &delta, radius, angle - rotate );
-
- delta.x += stroker->center.x;
- delta.y += stroker->center.y;
+ /* compute second angle point */
+ delta.x = middle.x - delta.x + middle.x;
+ delta.y = middle.y - delta.y + middle.y;
error = ft_stroke_border_lineto( border, &delta, FALSE );
}
@@ -1000,8 +974,8 @@
{
FT_StrokeBorder border = stroker->borders + side;
FT_Angle phi, theta, rotate;
- FT_Fixed length, thcos;
- FT_Vector delta;
+ FT_Fixed length;
+ FT_Vector sigma, delta;
FT_Error error = FT_Err_Ok;
FT_Bool intersect; /* use intersection of lines? */
@@ -1019,10 +993,13 @@
else
{
/* compute minimum required length of lines */
- FT_Fixed min_length = ft_pos_abs( FT_MulFix( stroker->radius,
- FT_Tan( theta ) ) );
+ FT_Fixed min_length;
+ FT_Vector_Unit( &sigma, theta );
+ min_length =
+ ft_pos_abs( FT_MulDiv( stroker->radius, sigma.y, sigma.x ) );
+
intersect = FT_BOOL( min_length &&
stroker->line_length >= min_length &&
line_length >= min_length );
@@ -1040,13 +1017,11 @@
else
{
/* compute median angle */
- phi = stroker->angle_in + theta;
-
- thcos = FT_Cos( theta );
+ phi = stroker->angle_in + theta + rotate;
- length = FT_DivFix( stroker->radius, thcos );
+ length = FT_DivFix( stroker->radius, sigma.x );
- FT_Vector_From_Polar( &delta, length, phi + rotate );
+ FT_Vector_From_Polar( &delta, length, phi );
delta.x += stroker->center.x;
delta.y += stroker->center.y;
}
@@ -1073,10 +1048,10 @@
else
{
/* this is a mitered (pointed) or beveled (truncated) corner */
- FT_Fixed sigma = 0, radius = stroker->radius;
- FT_Angle theta = 0, phi = 0;
- FT_Fixed thcos = 0;
- FT_Bool bevel, fixed_bevel;
+ FT_Fixed radius = stroker->radius;
+ FT_Vector sigma;
+ FT_Angle theta = 0, phi = 0;
+ FT_Bool bevel, fixed_bevel;
rotate = FT_SIDE_TO_ROTATE( side );
@@ -1087,26 +1062,20 @@
fixed_bevel =
FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE );
+ /* check miter limit first */
if ( !bevel )
{
- theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
+ theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
- if ( theta == FT_ANGLE_PI )
- {
- theta = rotate;
- phi = stroker->angle_in;
- }
- else
- {
- theta /= 2;
- phi = stroker->angle_in + theta + rotate;
- }
+ if ( theta == FT_ANGLE_PI2 )
+ theta = -rotate;
- thcos = FT_Cos( theta );
- sigma = FT_MulFix( stroker->miter_limit, thcos );
+ phi = stroker->angle_in + theta + rotate;
+
+ FT_Vector_From_Polar( &sigma, stroker->miter_limit, theta );
/* is miter limit exceeded? */
- if ( sigma < 0x10000L )
+ if ( sigma.x < 0x10000L )
{
/* don't create variable bevels for very small deviations; */
/* FT_Sin(x) = 0 for x <= 57 */
@@ -1133,36 +1102,34 @@
border->movable = FALSE;
error = ft_stroke_border_lineto( border, &delta, FALSE );
}
- else /* variable bevel */
+ else /* variable bevel or clipped miter */
{
/* the miter is truncated */
FT_Vector middle, delta;
- FT_Fixed length;
+ FT_Fixed coef;
- /* compute middle point */
+ /* compute middle point and first angle point */
FT_Vector_From_Polar( &middle,
FT_MulFix( radius, stroker->miter_limit ),
phi );
- middle.x += stroker->center.x;
- middle.y += stroker->center.y;
- /* compute first angle point */
- length = FT_MulDiv( radius, 0x10000L - sigma,
- ft_pos_abs( FT_Sin( theta ) ) );
+ coef = FT_DivFix( 0x10000L - sigma.x, sigma.y );
+ delta.x = FT_MulFix( middle.y, coef );
+ delta.y = FT_MulFix( -middle.x, coef );
- FT_Vector_From_Polar( &delta, length, phi + rotate );
- delta.x += middle.x;
- delta.y += middle.y;
+ middle.x += stroker->center.x;
+ middle.y += stroker->center.y;
+ delta.x += middle.x;
+ delta.y += middle.y;
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
goto Exit;
/* compute second angle point */
- FT_Vector_From_Polar( &delta, length, phi - rotate );
- delta.x += middle.x;
- delta.y += middle.y;
+ delta.x = middle.x - delta.x + middle.x;
+ delta.y = middle.y - delta.y + middle.y;
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
@@ -1189,7 +1156,7 @@
FT_Vector delta;
- length = FT_DivFix( stroker->radius, thcos );
+ length = FT_MulDiv( stroker->radius, stroker->miter_limit, sigma.x );
FT_Vector_From_Polar( &delta, length, phi );
delta.x += stroker->center.x;
diff --git a/thirdparty/freetype/src/base/ftsynth.c b/thirdparty/freetype/src/base/ftsynth.c
index f87ed65e75..eee6b952b4 100644
--- a/thirdparty/freetype/src/base/ftsynth.c
+++ b/thirdparty/freetype/src/base/ftsynth.c
@@ -4,7 +4,7 @@
*
* FreeType synthesizing code for emboldening and slanting (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftsystem.c b/thirdparty/freetype/src/base/ftsystem.c
index f92b3a03d5..290100613f 100644
--- a/thirdparty/freetype/src/base/ftsystem.c
+++ b/thirdparty/freetype/src/base/ftsystem.c
@@ -4,7 +4,7 @@
*
* ANSI-specific FreeType low-level system interface (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/fttrigon.c b/thirdparty/freetype/src/base/fttrigon.c
index 38721977c7..dbe11107bd 100644
--- a/thirdparty/freetype/src/base/fttrigon.c
+++ b/thirdparty/freetype/src/base/fttrigon.c
@@ -4,7 +4,7 @@
*
* FreeType trigonometric functions (body).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/fttype1.c b/thirdparty/freetype/src/base/fttype1.c
index 26d4f1c3a8..61778faa70 100644
--- a/thirdparty/freetype/src/base/fttype1.c
+++ b/thirdparty/freetype/src/base/fttype1.c
@@ -4,7 +4,7 @@
*
* FreeType utility file for PS names support (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftutil.c b/thirdparty/freetype/src/base/ftutil.c
index 92bd857e92..629af174b1 100644
--- a/thirdparty/freetype/src/base/ftutil.c
+++ b/thirdparty/freetype/src/base/ftutil.c
@@ -4,7 +4,7 @@
*
* FreeType utility file for memory and list management (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftver.rc b/thirdparty/freetype/src/base/ftver.rc
index 1354497423..fcbd9eff5f 100644
--- a/thirdparty/freetype/src/base/ftver.rc
+++ b/thirdparty/freetype/src/base/ftver.rc
@@ -4,7 +4,7 @@
/* */
/* FreeType VERSIONINFO resource for Windows DLLs. */
/* */
-/* Copyright (C) 2018-2019 by */
+/* Copyright (C) 2018-2020 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,8 +18,8 @@
#include<windows.h>
-#define FT_VERSION 2,10,1,0
-#define FT_VERSION_STR "2.10.1"
+#define FT_VERSION 2,10,2,0
+#define FT_VERSION_STR "2.10.2"
VS_VERSION_INFO VERSIONINFO
FILEVERSION FT_VERSION
@@ -45,7 +45,7 @@ BEGIN
VALUE "FileVersion", FT_VERSION_STR
VALUE "ProductName", "FreeType"
VALUE "ProductVersion", FT_VERSION_STR
- VALUE "LegalCopyright", "\251 2018-2019 The FreeType Project www.freetype.org. All rights reserved."
+ VALUE "LegalCopyright", "\251 2000-2020 The FreeType Project www.freetype.org. All rights reserved."
VALUE "InternalName", "freetype"
VALUE "OriginalFilename", FT_FILENAME
END
diff --git a/thirdparty/freetype/src/base/ftwinfnt.c b/thirdparty/freetype/src/base/ftwinfnt.c
index 59daa77031..77527277c2 100644
--- a/thirdparty/freetype/src/base/ftwinfnt.c
+++ b/thirdparty/freetype/src/base/ftwinfnt.c
@@ -4,7 +4,7 @@
*
* FreeType API for accessing Windows FNT specific info (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/rules.mk b/thirdparty/freetype/src/base/rules.mk
index 4b24c6dce7..411c4c821f 100644
--- a/thirdparty/freetype/src/base/rules.mk
+++ b/thirdparty/freetype/src/base/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/bzip2/ftbzip2.c b/thirdparty/freetype/src/bzip2/ftbzip2.c
index 1fda59b60c..e4d7a4901a 100644
--- a/thirdparty/freetype/src/bzip2/ftbzip2.c
+++ b/thirdparty/freetype/src/bzip2/ftbzip2.c
@@ -8,7 +8,7 @@
* parse compressed PCF fonts, as found with many X11 server
* distributions.
*
- * Copyright (C) 2010-2019 by
+ * Copyright (C) 2010-2020 by
* Joel Klinghed.
*
* based on `src/gzip/ftgzip.c'
diff --git a/thirdparty/freetype/src/bzip2/rules.mk b/thirdparty/freetype/src/bzip2/rules.mk
index f365c1f76d..eed0f4baa4 100644
--- a/thirdparty/freetype/src/bzip2/rules.mk
+++ b/thirdparty/freetype/src/bzip2/rules.mk
@@ -2,7 +2,7 @@
# FreeType 2 BZIP2 support configuration rules
#
-# Copyright (C) 2010-2019 by
+# Copyright (C) 2010-2020 by
# Joel Klinghed.
#
# based on `src/lzw/rules.mk'
diff --git a/thirdparty/freetype/src/cache/ftcache.c b/thirdparty/freetype/src/cache/ftcache.c
index a6a3e63ef0..4137f68690 100644
--- a/thirdparty/freetype/src/cache/ftcache.c
+++ b/thirdparty/freetype/src/cache/ftcache.c
@@ -4,7 +4,7 @@
*
* The FreeType Caching sub-system (body only).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcbasic.c b/thirdparty/freetype/src/cache/ftcbasic.c
index a473585ebc..a65a90e867 100644
--- a/thirdparty/freetype/src/cache/ftcbasic.c
+++ b/thirdparty/freetype/src/cache/ftcbasic.c
@@ -4,7 +4,7 @@
*
* The FreeType basic cache interface (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftccache.c b/thirdparty/freetype/src/cache/ftccache.c
index f38ca44ddd..1d406c4200 100644
--- a/thirdparty/freetype/src/cache/ftccache.c
+++ b/thirdparty/freetype/src/cache/ftccache.c
@@ -4,7 +4,7 @@
*
* The FreeType internal cache interface (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftccache.h b/thirdparty/freetype/src/cache/ftccache.h
index 140ceadb11..2996ee8080 100644
--- a/thirdparty/freetype/src/cache/ftccache.h
+++ b/thirdparty/freetype/src/cache/ftccache.h
@@ -4,7 +4,7 @@
*
* FreeType internal cache interface (specification).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftccback.h b/thirdparty/freetype/src/cache/ftccback.h
index 9321bc3d4e..252be7c2b5 100644
--- a/thirdparty/freetype/src/cache/ftccback.h
+++ b/thirdparty/freetype/src/cache/ftccback.h
@@ -4,7 +4,7 @@
*
* Callback functions of the caching sub-system (specification only).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftccmap.c b/thirdparty/freetype/src/cache/ftccmap.c
index 76ba10e3e9..a5da694d56 100644
--- a/thirdparty/freetype/src/cache/ftccmap.c
+++ b/thirdparty/freetype/src/cache/ftccmap.c
@@ -4,7 +4,7 @@
*
* FreeType CharMap cache (body)
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcerror.h b/thirdparty/freetype/src/cache/ftcerror.h
index e2d6417180..15e416ed21 100644
--- a/thirdparty/freetype/src/cache/ftcerror.h
+++ b/thirdparty/freetype/src/cache/ftcerror.h
@@ -4,7 +4,7 @@
*
* Caching sub-system error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcglyph.c b/thirdparty/freetype/src/cache/ftcglyph.c
index 2a0e97d4af..559a2fb4c8 100644
--- a/thirdparty/freetype/src/cache/ftcglyph.c
+++ b/thirdparty/freetype/src/cache/ftcglyph.c
@@ -4,7 +4,7 @@
*
* FreeType Glyph Image (FT_Glyph) cache (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcglyph.h b/thirdparty/freetype/src/cache/ftcglyph.h
index 5a1f0e2a74..ef689f9947 100644
--- a/thirdparty/freetype/src/cache/ftcglyph.h
+++ b/thirdparty/freetype/src/cache/ftcglyph.h
@@ -4,7 +4,7 @@
*
* FreeType abstract glyph cache (specification).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcimage.c b/thirdparty/freetype/src/cache/ftcimage.c
index 9e64d51a22..7696b2e52d 100644
--- a/thirdparty/freetype/src/cache/ftcimage.c
+++ b/thirdparty/freetype/src/cache/ftcimage.c
@@ -4,7 +4,7 @@
*
* FreeType Image cache (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcimage.h b/thirdparty/freetype/src/cache/ftcimage.h
index dcb101fabc..f99c5074cf 100644
--- a/thirdparty/freetype/src/cache/ftcimage.h
+++ b/thirdparty/freetype/src/cache/ftcimage.h
@@ -4,7 +4,7 @@
*
* FreeType Generic Image cache (specification)
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcmanag.c b/thirdparty/freetype/src/cache/ftcmanag.c
index bd585968e3..a6f1733f64 100644
--- a/thirdparty/freetype/src/cache/ftcmanag.c
+++ b/thirdparty/freetype/src/cache/ftcmanag.c
@@ -4,7 +4,7 @@
*
* FreeType Cache Manager (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcmanag.h b/thirdparty/freetype/src/cache/ftcmanag.h
index 60c66c8fc8..17ade7175f 100644
--- a/thirdparty/freetype/src/cache/ftcmanag.h
+++ b/thirdparty/freetype/src/cache/ftcmanag.h
@@ -4,7 +4,7 @@
*
* FreeType Cache Manager (specification).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcmru.c b/thirdparty/freetype/src/cache/ftcmru.c
index 18a7b80054..370ae3be04 100644
--- a/thirdparty/freetype/src/cache/ftcmru.c
+++ b/thirdparty/freetype/src/cache/ftcmru.c
@@ -4,7 +4,7 @@
*
* FreeType MRU support (body).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcmru.h b/thirdparty/freetype/src/cache/ftcmru.h
index 58721ed340..1591c20807 100644
--- a/thirdparty/freetype/src/cache/ftcmru.h
+++ b/thirdparty/freetype/src/cache/ftcmru.h
@@ -4,7 +4,7 @@
*
* Simple MRU list-cache (specification).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcsbits.c b/thirdparty/freetype/src/cache/ftcsbits.c
index 06b46c896e..24e4aa1316 100644
--- a/thirdparty/freetype/src/cache/ftcsbits.c
+++ b/thirdparty/freetype/src/cache/ftcsbits.c
@@ -4,7 +4,7 @@
*
* FreeType sbits manager (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcsbits.h b/thirdparty/freetype/src/cache/ftcsbits.h
index f1b71c2835..2517d15552 100644
--- a/thirdparty/freetype/src/cache/ftcsbits.h
+++ b/thirdparty/freetype/src/cache/ftcsbits.h
@@ -4,7 +4,7 @@
*
* A small-bitmap cache (specification).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/rules.mk b/thirdparty/freetype/src/cache/rules.mk
index 1618d98303..4738b5153a 100644
--- a/thirdparty/freetype/src/cache/rules.mk
+++ b/thirdparty/freetype/src/cache/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2000-2019 by
+# Copyright (C) 2000-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cff/cff.c b/thirdparty/freetype/src/cff/cff.c
index a34ba9b710..755228bb6c 100644
--- a/thirdparty/freetype/src/cff/cff.c
+++ b/thirdparty/freetype/src/cff/cff.c
@@ -4,7 +4,7 @@
*
* FreeType OpenType driver component (body only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffcmap.c b/thirdparty/freetype/src/cff/cffcmap.c
index 15cc94cafb..1a045765de 100644
--- a/thirdparty/freetype/src/cff/cffcmap.c
+++ b/thirdparty/freetype/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
*
* CFF character mapping table (cmap) support (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffcmap.h b/thirdparty/freetype/src/cff/cffcmap.h
index 07366bc748..319be88241 100644
--- a/thirdparty/freetype/src/cff/cffcmap.h
+++ b/thirdparty/freetype/src/cff/cffcmap.h
@@ -4,7 +4,7 @@
*
* CFF character mapping table (cmap) support (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffdrivr.c b/thirdparty/freetype/src/cff/cffdrivr.c
index 2324989811..6d0dcd09d2 100644
--- a/thirdparty/freetype/src/cff/cffdrivr.c
+++ b/thirdparty/freetype/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
*
* OpenType font driver implementation (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffdrivr.h b/thirdparty/freetype/src/cff/cffdrivr.h
index f2bbcfe4f1..25471d511b 100644
--- a/thirdparty/freetype/src/cff/cffdrivr.h
+++ b/thirdparty/freetype/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
*
* High-level OpenType driver interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cfferrs.h b/thirdparty/freetype/src/cff/cfferrs.h
index 78d47a156d..32be8a7637 100644
--- a/thirdparty/freetype/src/cff/cfferrs.h
+++ b/thirdparty/freetype/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
*
* CFF error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffgload.c b/thirdparty/freetype/src/cff/cffgload.c
index 36aa7d1b9c..1c4e1979c4 100644
--- a/thirdparty/freetype/src/cff/cffgload.c
+++ b/thirdparty/freetype/src/cff/cffgload.c
@@ -4,7 +4,7 @@
*
* OpenType Glyph Loader (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffgload.h b/thirdparty/freetype/src/cff/cffgload.h
index 754c55acf9..b4ad61a564 100644
--- a/thirdparty/freetype/src/cff/cffgload.h
+++ b/thirdparty/freetype/src/cff/cffgload.h
@@ -4,7 +4,7 @@
*
* OpenType Glyph Loader (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffload.c b/thirdparty/freetype/src/cff/cffload.c
index 12efd18dc4..9f1d0e2e64 100644
--- a/thirdparty/freetype/src/cff/cffload.c
+++ b/thirdparty/freetype/src/cff/cffload.c
@@ -4,7 +4,7 @@
*
* OpenType and CFF data/program tables loader (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -2057,7 +2057,7 @@
if ( !error )
{
FT_TRACE4(( " top dictionary:\n" ));
- error = cff_parser_run( &parser, dict, dict + dict_len );
+ error = cff_parser_run( &parser, dict, FT_OFFSET( dict, dict_len ) );
}
/* clean up regardless of error */
diff --git a/thirdparty/freetype/src/cff/cffload.h b/thirdparty/freetype/src/cff/cffload.h
index 42d2696f33..1b7971293b 100644
--- a/thirdparty/freetype/src/cff/cffload.h
+++ b/thirdparty/freetype/src/cff/cffload.h
@@ -4,7 +4,7 @@
*
* OpenType & CFF data/program tables loader (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffobjs.c b/thirdparty/freetype/src/cff/cffobjs.c
index f76245f30b..78c3cb3c2d 100644
--- a/thirdparty/freetype/src/cff/cffobjs.c
+++ b/thirdparty/freetype/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
*
* OpenType objects manager (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -1018,9 +1018,9 @@
}
#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
- /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */
- /* has unset this flag because of the 3.0 `post' table. */
- if ( dict->cid_registry == 0xFFFFU )
+ /* CID-keyed CFF or CFF2 fonts don't have glyph names -- the SFNT */
+ /* loader has unset this flag because of the 3.0 `post' table. */
+ if ( dict->cid_registry == 0xFFFFU && !cff2 )
cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
#endif
diff --git a/thirdparty/freetype/src/cff/cffobjs.h b/thirdparty/freetype/src/cff/cffobjs.h
index 03bc78a67f..6f12b95db6 100644
--- a/thirdparty/freetype/src/cff/cffobjs.h
+++ b/thirdparty/freetype/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
*
* OpenType objects manager (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffparse.c b/thirdparty/freetype/src/cff/cffparse.c
index 008752c3ae..0d3bf34592 100644
--- a/thirdparty/freetype/src/cff/cffparse.c
+++ b/thirdparty/freetype/src/cff/cffparse.c
@@ -4,7 +4,7 @@
*
* CFF token stream parser (body)
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffparse.h b/thirdparty/freetype/src/cff/cffparse.h
index 4e74709a2d..887110a748 100644
--- a/thirdparty/freetype/src/cff/cffparse.h
+++ b/thirdparty/freetype/src/cff/cffparse.h
@@ -4,7 +4,7 @@
*
* CFF token stream parser (specification)
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cfftoken.h b/thirdparty/freetype/src/cff/cfftoken.h
index 063a7b3be0..4c6a53eec1 100644
--- a/thirdparty/freetype/src/cff/cfftoken.h
+++ b/thirdparty/freetype/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
*
* CFF token definitions (specification only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/module.mk b/thirdparty/freetype/src/cff/module.mk
index 8c610959d3..bd728c6a34 100644
--- a/thirdparty/freetype/src/cff/module.mk
+++ b/thirdparty/freetype/src/cff/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cff/rules.mk b/thirdparty/freetype/src/cff/rules.mk
index 6e2dc476ef..70bb92d506 100644
--- a/thirdparty/freetype/src/cff/rules.mk
+++ b/thirdparty/freetype/src/cff/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cid/ciderrs.h b/thirdparty/freetype/src/cid/ciderrs.h
index be80bed3be..52ab55d684 100644
--- a/thirdparty/freetype/src/cid/ciderrs.h
+++ b/thirdparty/freetype/src/cid/ciderrs.h
@@ -4,7 +4,7 @@
*
* CID error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidgload.c b/thirdparty/freetype/src/cid/cidgload.c
index f59f2880f0..daa0bddc2a 100644
--- a/thirdparty/freetype/src/cid/cidgload.c
+++ b/thirdparty/freetype/src/cid/cidgload.c
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 Glyph Loader (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidgload.h b/thirdparty/freetype/src/cid/cidgload.h
index 37eba7ca7b..251c93c9f2 100644
--- a/thirdparty/freetype/src/cid/cidgload.h
+++ b/thirdparty/freetype/src/cid/cidgload.h
@@ -4,7 +4,7 @@
*
* OpenType Glyph Loader (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidload.c b/thirdparty/freetype/src/cid/cidload.c
index fce3e37da7..4723966024 100644
--- a/thirdparty/freetype/src/cid/cidload.c
+++ b/thirdparty/freetype/src/cid/cidload.c
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 font loader (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -715,7 +715,7 @@
if ( ft_isdigit( *p ) )
val = (FT_Byte)( *p - '0' );
else if ( *p >= 'a' && *p <= 'f' )
- val = (FT_Byte)( *p - 'a' );
+ val = (FT_Byte)( *p - 'a' + 10 );
else if ( *p >= 'A' && *p <= 'F' )
val = (FT_Byte)( *p - 'A' + 10 );
else if ( *p == ' ' ||
diff --git a/thirdparty/freetype/src/cid/cidload.h b/thirdparty/freetype/src/cid/cidload.h
index fb9d46216d..e639f6ffef 100644
--- a/thirdparty/freetype/src/cid/cidload.h
+++ b/thirdparty/freetype/src/cid/cidload.h
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 font loader (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidobjs.c b/thirdparty/freetype/src/cid/cidobjs.c
index 4e9728719b..34f72b588d 100644
--- a/thirdparty/freetype/src/cid/cidobjs.c
+++ b/thirdparty/freetype/src/cid/cidobjs.c
@@ -4,7 +4,7 @@
*
* CID objects manager (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidobjs.h b/thirdparty/freetype/src/cid/cidobjs.h
index 89c9aa74ab..efe812fd11 100644
--- a/thirdparty/freetype/src/cid/cidobjs.h
+++ b/thirdparty/freetype/src/cid/cidobjs.h
@@ -4,7 +4,7 @@
*
* CID objects manager (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidparse.c b/thirdparty/freetype/src/cid/cidparse.c
index 1be46ec328..94a36e22f5 100644
--- a/thirdparty/freetype/src/cid/cidparse.c
+++ b/thirdparty/freetype/src/cid/cidparse.c
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 parser (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidparse.h b/thirdparty/freetype/src/cid/cidparse.h
index ec1f6a346d..6b2944ff57 100644
--- a/thirdparty/freetype/src/cid/cidparse.h
+++ b/thirdparty/freetype/src/cid/cidparse.h
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 parser (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidriver.c b/thirdparty/freetype/src/cid/cidriver.c
index 4d91e87529..ad2f7b5cf5 100644
--- a/thirdparty/freetype/src/cid/cidriver.c
+++ b/thirdparty/freetype/src/cid/cidriver.c
@@ -4,7 +4,7 @@
*
* CID driver interface (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidriver.h b/thirdparty/freetype/src/cid/cidriver.h
index 3402fd7e99..400c2ae295 100644
--- a/thirdparty/freetype/src/cid/cidriver.h
+++ b/thirdparty/freetype/src/cid/cidriver.h
@@ -4,7 +4,7 @@
*
* High-level CID driver interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidtoken.h b/thirdparty/freetype/src/cid/cidtoken.h
index f505c9e166..e9f068bb50 100644
--- a/thirdparty/freetype/src/cid/cidtoken.h
+++ b/thirdparty/freetype/src/cid/cidtoken.h
@@ -4,7 +4,7 @@
*
* CID token definitions (specification only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/module.mk b/thirdparty/freetype/src/cid/module.mk
index 875c683c72..9fb02235e6 100644
--- a/thirdparty/freetype/src/cid/module.mk
+++ b/thirdparty/freetype/src/cid/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cid/rules.mk b/thirdparty/freetype/src/cid/rules.mk
index 2b68dd48a0..94f663c80e 100644
--- a/thirdparty/freetype/src/cid/rules.mk
+++ b/thirdparty/freetype/src/cid/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cid/type1cid.c b/thirdparty/freetype/src/cid/type1cid.c
index d21801cec1..ba9141075f 100644
--- a/thirdparty/freetype/src/cid/type1cid.c
+++ b/thirdparty/freetype/src/cid/type1cid.c
@@ -4,7 +4,7 @@
*
* FreeType OpenType driver component (body only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/gxvalid/README b/thirdparty/freetype/src/gxvalid/README
index d493587842..2a32bab204 100644
--- a/thirdparty/freetype/src/gxvalid/README
+++ b/thirdparty/freetype/src/gxvalid/README
@@ -518,7 +518,7 @@ gxvalid: TrueType GX validator
------------------------------------------------------------------------
-Copyright (C) 2004-2019 by
+Copyright (C) 2004-2020 by
suzuki toshiya, Masatake YAMATO, Red hat K.K.,
David Turner, Robert Wilhelm, and Werner Lemberg.
diff --git a/thirdparty/freetype/src/gxvalid/gxvalid.c b/thirdparty/freetype/src/gxvalid/gxvalid.c
index 462e461bf2..cb655aeb9d 100644
--- a/thirdparty/freetype/src/gxvalid/gxvalid.c
+++ b/thirdparty/freetype/src/gxvalid/gxvalid.c
@@ -4,7 +4,7 @@
*
* FreeType validator for TrueTypeGX/AAT tables (body only).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvalid.h b/thirdparty/freetype/src/gxvalid/gxvalid.h
index 969cd0927a..cdf1986324 100644
--- a/thirdparty/freetype/src/gxvalid/gxvalid.h
+++ b/thirdparty/freetype/src/gxvalid/gxvalid.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT table validation (specification only).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvbsln.c b/thirdparty/freetype/src/gxvalid/gxvbsln.c
index f22f2545fa..ac58d4615c 100644
--- a/thirdparty/freetype/src/gxvalid/gxvbsln.c
+++ b/thirdparty/freetype/src/gxvalid/gxvbsln.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT bsln table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvcommn.c b/thirdparty/freetype/src/gxvalid/gxvcommn.c
index c5cb8ebe8b..ead0f24cd3 100644
--- a/thirdparty/freetype/src/gxvalid/gxvcommn.c
+++ b/thirdparty/freetype/src/gxvalid/gxvcommn.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT common tables validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvcommn.h b/thirdparty/freetype/src/gxvalid/gxvcommn.h
index 334dc9dfb3..2372fc86fa 100644
--- a/thirdparty/freetype/src/gxvalid/gxvcommn.h
+++ b/thirdparty/freetype/src/gxvalid/gxvcommn.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT common tables validation (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxverror.h b/thirdparty/freetype/src/gxvalid/gxverror.h
index da0edb35f9..475b9f7778 100644
--- a/thirdparty/freetype/src/gxvalid/gxverror.h
+++ b/thirdparty/freetype/src/gxvalid/gxverror.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT validation module error codes (specification only).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvfeat.c b/thirdparty/freetype/src/gxvalid/gxvfeat.c
index e1a12a18ed..400ec8a3fb 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfeat.c
+++ b/thirdparty/freetype/src/gxvalid/gxvfeat.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT feat table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvfeat.h b/thirdparty/freetype/src/gxvalid/gxvfeat.h
index 6c9892910c..435dcefb09 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfeat.h
+++ b/thirdparty/freetype/src/gxvalid/gxvfeat.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT feat table validation (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvfgen.c b/thirdparty/freetype/src/gxvalid/gxvfgen.c
index 5ecb9443c3..fe05a6f3a1 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfgen.c
+++ b/thirdparty/freetype/src/gxvalid/gxvfgen.c
@@ -5,7 +5,7 @@
* Generate feature registry data for gxv `feat' validator.
* This program is derived from gxfeatreg.c in gxlayout.
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* Masatake YAMATO and Redhat K.K.
*
* This file may only be used,
diff --git a/thirdparty/freetype/src/gxvalid/gxvjust.c b/thirdparty/freetype/src/gxvalid/gxvjust.c
index a582377859..d8875b4111 100644
--- a/thirdparty/freetype/src/gxvalid/gxvjust.c
+++ b/thirdparty/freetype/src/gxvalid/gxvjust.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT just table validation (body).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvkern.c b/thirdparty/freetype/src/gxvalid/gxvkern.c
index a7532335a5..ab5643eb83 100644
--- a/thirdparty/freetype/src/gxvalid/gxvkern.c
+++ b/thirdparty/freetype/src/gxvalid/gxvkern.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT kern table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvlcar.c b/thirdparty/freetype/src/gxvalid/gxvlcar.c
index 13b3de3eaa..82ac1907ab 100644
--- a/thirdparty/freetype/src/gxvalid/gxvlcar.c
+++ b/thirdparty/freetype/src/gxvalid/gxvlcar.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT lcar table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmod.c b/thirdparty/freetype/src/gxvalid/gxvmod.c
index eeadeb3e1d..2b8f45d1c2 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmod.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmod.c
@@ -4,7 +4,7 @@
*
* FreeType's TrueTypeGX/AAT validation module implementation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmod.h b/thirdparty/freetype/src/gxvalid/gxvmod.h
index 6ecd7312c9..bdf465f4f0 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmod.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmod.h
@@ -5,7 +5,7 @@
* FreeType's TrueTypeGX/AAT validation module implementation
* (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort.c b/thirdparty/freetype/src/gxvalid/gxvmort.c
index 288ef6988b..aae7f01a89 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT mort table validation (body).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort.h b/thirdparty/freetype/src/gxvalid/gxvmort.h
index 0619e24fb9..35a18e76a6 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmort.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT common definition for mort table (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort0.c b/thirdparty/freetype/src/gxvalid/gxvmort0.c
index 2c01bf95ec..d452c1ccaa 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort0.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort0.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT mort table validation
* body for type0 (Indic Script Rearrangement) subtable.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort1.c b/thirdparty/freetype/src/gxvalid/gxvmort1.c
index c71ba13351..d743f89f6e 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort1.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort1.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT mort table validation
* body for type1 (Contextual Substitution) subtable.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort2.c b/thirdparty/freetype/src/gxvalid/gxvmort2.c
index 889d3bd582..9e69e1269d 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort2.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort2.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT mort table validation
* body for type2 (Ligature Substitution) subtable.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort4.c b/thirdparty/freetype/src/gxvalid/gxvmort4.c
index f8ce6cf789..4584d204cf 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort4.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort4.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT mort table validation
* body for type4 (Non-Contextual Glyph Substitution) subtable.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort5.c b/thirdparty/freetype/src/gxvalid/gxvmort5.c
index 1ba1e5ded0..a15a24fe65 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort5.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort5.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT mort table validation
* body for type5 (Contextual Glyph Insertion) subtable.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx.c b/thirdparty/freetype/src/gxvalid/gxvmorx.c
index 8bd45c27e6..754d9f8bf1 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT morx table validation (body).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx.h b/thirdparty/freetype/src/gxvalid/gxvmorx.h
index e257270342..99be181067 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT common definition for morx table (specification).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx0.c b/thirdparty/freetype/src/gxvalid/gxvmorx0.c
index d7764a0ae8..5a42e552e2 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx0.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx0.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT morx table validation
* body for type0 (Indic Script Rearrangement) subtable.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx1.c b/thirdparty/freetype/src/gxvalid/gxvmorx1.c
index 5b41b3605f..9f8b69067e 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx1.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx1.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT morx table validation
* body for type1 (Contextual Substitution) subtable.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx2.c b/thirdparty/freetype/src/gxvalid/gxvmorx2.c
index ec4c81299d..98b5c49c26 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx2.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx2.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT morx table validation
* body for type2 (Ligature Substitution) subtable.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx4.c b/thirdparty/freetype/src/gxvalid/gxvmorx4.c
index 7b041534c0..857e4d4eb8 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx4.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx4.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT morx table validation
* body for "morx" type4 (Non-Contextual Glyph Substitution) subtable.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx5.c b/thirdparty/freetype/src/gxvalid/gxvmorx5.c
index 70a4623656..7ceba077af 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx5.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx5.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT morx table validation
* body for type5 (Contextual Glyph Insertion) subtable.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvopbd.c b/thirdparty/freetype/src/gxvalid/gxvopbd.c
index f055a22054..a398fe0977 100644
--- a/thirdparty/freetype/src/gxvalid/gxvopbd.c
+++ b/thirdparty/freetype/src/gxvalid/gxvopbd.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT opbd table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvprop.c b/thirdparty/freetype/src/gxvalid/gxvprop.c
index e1911edd48..bee8bab97b 100644
--- a/thirdparty/freetype/src/gxvalid/gxvprop.c
+++ b/thirdparty/freetype/src/gxvalid/gxvprop.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT prop table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvtrak.c b/thirdparty/freetype/src/gxvalid/gxvtrak.c
index b7794b7af4..58a631c9e5 100644
--- a/thirdparty/freetype/src/gxvalid/gxvtrak.c
+++ b/thirdparty/freetype/src/gxvalid/gxvtrak.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT trak table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/module.mk b/thirdparty/freetype/src/gxvalid/module.mk
index 04067ce617..e7d408df9d 100644
--- a/thirdparty/freetype/src/gxvalid/module.mk
+++ b/thirdparty/freetype/src/gxvalid/module.mk
@@ -2,7 +2,7 @@
# FreeType 2 gxvalid module definition
#
-# Copyright (C) 2004-2019 by
+# Copyright (C) 2004-2020 by
# suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
diff --git a/thirdparty/freetype/src/gxvalid/rules.mk b/thirdparty/freetype/src/gxvalid/rules.mk
index 4ef463bc21..d55a4935e2 100644
--- a/thirdparty/freetype/src/gxvalid/rules.mk
+++ b/thirdparty/freetype/src/gxvalid/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2004-2019 by
+# Copyright (C) 2004-2020 by
# suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
diff --git a/thirdparty/freetype/src/gzip/ftgzip.c b/thirdparty/freetype/src/gzip/ftgzip.c
index 5e78bc6f8d..6b1df3a4a7 100644
--- a/thirdparty/freetype/src/gzip/ftgzip.c
+++ b/thirdparty/freetype/src/gzip/ftgzip.c
@@ -8,7 +8,7 @@
* parse compressed PCF fonts, as found with many X11 server
* distributions.
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -746,7 +746,17 @@
stream.zfree = (free_func) ft_gzip_free;
stream.opaque = memory;
+ /* This is a temporary fix and will be removed once the internal
+ * copy of zlib is updated to the newest version. The `|32' flag
+ * is only supported in the new versions of zlib to enable gzip
+ * encoded header.
+ */
+#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB
err = inflateInit2( &stream, MAX_WBITS|32 );
+#else
+ err = inflateInit2( &stream, MAX_WBITS );
+#endif
+
if ( err != Z_OK )
return FT_THROW( Invalid_Argument );
diff --git a/thirdparty/freetype/src/gzip/infutil.h b/thirdparty/freetype/src/gzip/infutil.h
index 7174b6dd0f..cdf18b4f90 100644
--- a/thirdparty/freetype/src/gzip/infutil.h
+++ b/thirdparty/freetype/src/gzip/infutil.h
@@ -86,7 +86,7 @@ struct inflate_blocks_state {
/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
#ifndef NO_INFLATE_MASK
-local uInt inflate_mask[17];
+local const uInt inflate_mask[17];
#endif
/* copy as much as possible from the sliding window to the output area */
diff --git a/thirdparty/freetype/src/gzip/rules.mk b/thirdparty/freetype/src/gzip/rules.mk
index 44206a1dae..4ea823f8d3 100644
--- a/thirdparty/freetype/src/gzip/rules.mk
+++ b/thirdparty/freetype/src/gzip/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2002-2019 by
+# Copyright (C) 2002-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/lzw/ftlzw.c b/thirdparty/freetype/src/lzw/ftlzw.c
index 9805a1e3bd..7d3f3e3f55 100644
--- a/thirdparty/freetype/src/lzw/ftlzw.c
+++ b/thirdparty/freetype/src/lzw/ftlzw.c
@@ -8,7 +8,7 @@
* be used to parse compressed PCF fonts, as found with many X11 server
* distributions.
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* Albert Chin-A-Young.
*
* based on code in `src/gzip/ftgzip.c'
diff --git a/thirdparty/freetype/src/lzw/ftzopen.c b/thirdparty/freetype/src/lzw/ftzopen.c
index 67e6760f95..cdc7f4e683 100644
--- a/thirdparty/freetype/src/lzw/ftzopen.c
+++ b/thirdparty/freetype/src/lzw/ftzopen.c
@@ -8,7 +8,7 @@
* be used to parse compressed PCF fonts, as found with many X11 server
* distributions.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/lzw/ftzopen.h b/thirdparty/freetype/src/lzw/ftzopen.h
index 44fe36d6c5..2866529bd4 100644
--- a/thirdparty/freetype/src/lzw/ftzopen.h
+++ b/thirdparty/freetype/src/lzw/ftzopen.h
@@ -8,7 +8,7 @@
* be used to parse compressed PCF fonts, as found with many X11 server
* distributions.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/lzw/rules.mk b/thirdparty/freetype/src/lzw/rules.mk
index 930b32e6b1..3468ee024d 100644
--- a/thirdparty/freetype/src/lzw/rules.mk
+++ b/thirdparty/freetype/src/lzw/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2004-2019 by
+# Copyright (C) 2004-2020 by
# Albert Chin-A-Young.
#
# based on `src/lzw/rules.mk'
diff --git a/thirdparty/freetype/src/otvalid/module.mk b/thirdparty/freetype/src/otvalid/module.mk
index 5ea5b7b57b..67b9820d84 100644
--- a/thirdparty/freetype/src/otvalid/module.mk
+++ b/thirdparty/freetype/src/otvalid/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2004-2019 by
+# Copyright (C) 2004-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/otvalid/otvalid.c b/thirdparty/freetype/src/otvalid/otvalid.c
index e3964b99ae..487d336a3b 100644
--- a/thirdparty/freetype/src/otvalid/otvalid.c
+++ b/thirdparty/freetype/src/otvalid/otvalid.c
@@ -4,7 +4,7 @@
*
* FreeType validator for OpenType tables (body only).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvalid.h b/thirdparty/freetype/src/otvalid/otvalid.h
index 5ca819f261..3c70268964 100644
--- a/thirdparty/freetype/src/otvalid/otvalid.h
+++ b/thirdparty/freetype/src/otvalid/otvalid.h
@@ -4,7 +4,7 @@
*
* OpenType table validation (specification only).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvbase.c b/thirdparty/freetype/src/otvalid/otvbase.c
index be69d7ca31..250ae98ab5 100644
--- a/thirdparty/freetype/src/otvalid/otvbase.c
+++ b/thirdparty/freetype/src/otvalid/otvbase.c
@@ -4,7 +4,7 @@
*
* OpenType BASE table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvcommn.c b/thirdparty/freetype/src/otvalid/otvcommn.c
index 5ed1723506..faaa846871 100644
--- a/thirdparty/freetype/src/otvalid/otvcommn.c
+++ b/thirdparty/freetype/src/otvalid/otvcommn.c
@@ -4,7 +4,7 @@
*
* OpenType common tables validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -151,6 +151,9 @@
FT_UInt result = 0;
+ if ( !count )
+ return result;
+
switch ( CoverageFormat )
{
case 1:
diff --git a/thirdparty/freetype/src/otvalid/otvcommn.h b/thirdparty/freetype/src/otvalid/otvcommn.h
index bfcc5b974a..1daf7dca79 100644
--- a/thirdparty/freetype/src/otvalid/otvcommn.h
+++ b/thirdparty/freetype/src/otvalid/otvcommn.h
@@ -4,7 +4,7 @@
*
* OpenType common tables validation (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otverror.h b/thirdparty/freetype/src/otvalid/otverror.h
index a7d35acf1a..49c34d6cd8 100644
--- a/thirdparty/freetype/src/otvalid/otverror.h
+++ b/thirdparty/freetype/src/otvalid/otverror.h
@@ -4,7 +4,7 @@
*
* OpenType validation module error codes (specification only).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvgdef.c b/thirdparty/freetype/src/otvalid/otvgdef.c
index 2529b544d2..88874b8474 100644
--- a/thirdparty/freetype/src/otvalid/otvgdef.c
+++ b/thirdparty/freetype/src/otvalid/otvgdef.c
@@ -4,7 +4,7 @@
*
* OpenType GDEF table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvgpos.c b/thirdparty/freetype/src/otvalid/otvgpos.c
index f3bddeac6c..29d56f91e8 100644
--- a/thirdparty/freetype/src/otvalid/otvgpos.c
+++ b/thirdparty/freetype/src/otvalid/otvgpos.c
@@ -4,7 +4,7 @@
*
* OpenType GPOS table validation (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvgpos.h b/thirdparty/freetype/src/otvalid/otvgpos.h
index b3154312eb..06a03a0e6c 100644
--- a/thirdparty/freetype/src/otvalid/otvgpos.h
+++ b/thirdparty/freetype/src/otvalid/otvgpos.h
@@ -4,7 +4,7 @@
*
* OpenType GPOS table validator (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvgsub.c b/thirdparty/freetype/src/otvalid/otvgsub.c
index 97da997d3d..f0d563ba92 100644
--- a/thirdparty/freetype/src/otvalid/otvgsub.c
+++ b/thirdparty/freetype/src/otvalid/otvgsub.c
@@ -4,7 +4,7 @@
*
* OpenType GSUB table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvjstf.c b/thirdparty/freetype/src/otvalid/otvjstf.c
index d4e6d87178..79de7b809d 100644
--- a/thirdparty/freetype/src/otvalid/otvjstf.c
+++ b/thirdparty/freetype/src/otvalid/otvjstf.c
@@ -4,7 +4,7 @@
*
* OpenType JSTF table validation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvmath.c b/thirdparty/freetype/src/otvalid/otvmath.c
index 3aaf0ec0ec..dfdeaaba7e 100644
--- a/thirdparty/freetype/src/otvalid/otvmath.c
+++ b/thirdparty/freetype/src/otvalid/otvmath.c
@@ -4,7 +4,7 @@
*
* OpenType MATH table validation (body).
*
- * Copyright (C) 2007-2019 by
+ * Copyright (C) 2007-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by George Williams.
diff --git a/thirdparty/freetype/src/otvalid/otvmod.c b/thirdparty/freetype/src/otvalid/otvmod.c
index f417bd220f..5f3e7e8d49 100644
--- a/thirdparty/freetype/src/otvalid/otvmod.c
+++ b/thirdparty/freetype/src/otvalid/otvmod.c
@@ -4,7 +4,7 @@
*
* FreeType's OpenType validation module implementation (body).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvmod.h b/thirdparty/freetype/src/otvalid/otvmod.h
index 5539de7ec6..f172c2c8fa 100644
--- a/thirdparty/freetype/src/otvalid/otvmod.h
+++ b/thirdparty/freetype/src/otvalid/otvmod.h
@@ -5,7 +5,7 @@
* FreeType's OpenType validation module implementation
* (specification).
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/rules.mk b/thirdparty/freetype/src/otvalid/rules.mk
index 3c6ece1c19..7f0169fd89 100644
--- a/thirdparty/freetype/src/otvalid/rules.mk
+++ b/thirdparty/freetype/src/otvalid/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2004-2019 by
+# Copyright (C) 2004-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/pfr/module.mk b/thirdparty/freetype/src/pfr/module.mk
index 30d876d4c8..762353dda2 100644
--- a/thirdparty/freetype/src/pfr/module.mk
+++ b/thirdparty/freetype/src/pfr/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2002-2019 by
+# Copyright (C) 2002-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/pfr/pfr.c b/thirdparty/freetype/src/pfr/pfr.c
index 6d885ea47f..5dea6fa34a 100644
--- a/thirdparty/freetype/src/pfr/pfr.c
+++ b/thirdparty/freetype/src/pfr/pfr.c
@@ -4,7 +4,7 @@
*
* FreeType PFR driver component.
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrcmap.c b/thirdparty/freetype/src/pfr/pfrcmap.c
index bfa1b9ea05..3f64ba8b04 100644
--- a/thirdparty/freetype/src/pfr/pfrcmap.c
+++ b/thirdparty/freetype/src/pfr/pfrcmap.c
@@ -4,7 +4,7 @@
*
* FreeType PFR cmap handling (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrcmap.h b/thirdparty/freetype/src/pfr/pfrcmap.h
index 1e203a0514..b90e8a101f 100644
--- a/thirdparty/freetype/src/pfr/pfrcmap.h
+++ b/thirdparty/freetype/src/pfr/pfrcmap.h
@@ -4,7 +4,7 @@
*
* FreeType PFR cmap handling (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrdrivr.c b/thirdparty/freetype/src/pfr/pfrdrivr.c
index f67eebf118..2028c8e11b 100644
--- a/thirdparty/freetype/src/pfr/pfrdrivr.c
+++ b/thirdparty/freetype/src/pfr/pfrdrivr.c
@@ -4,7 +4,7 @@
*
* FreeType PFR driver interface (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrdrivr.h b/thirdparty/freetype/src/pfr/pfrdrivr.h
index 33b7b9413f..865ec8188a 100644
--- a/thirdparty/freetype/src/pfr/pfrdrivr.h
+++ b/thirdparty/freetype/src/pfr/pfrdrivr.h
@@ -4,7 +4,7 @@
*
* High-level Type PFR driver interface (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrerror.h b/thirdparty/freetype/src/pfr/pfrerror.h
index 4829cfc000..2dbeedfe15 100644
--- a/thirdparty/freetype/src/pfr/pfrerror.h
+++ b/thirdparty/freetype/src/pfr/pfrerror.h
@@ -4,7 +4,7 @@
*
* PFR error codes (specification only).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrgload.c b/thirdparty/freetype/src/pfr/pfrgload.c
index 6ef5856a8d..7d57ae1530 100644
--- a/thirdparty/freetype/src/pfr/pfrgload.c
+++ b/thirdparty/freetype/src/pfr/pfrgload.c
@@ -4,7 +4,7 @@
*
* FreeType PFR glyph loader (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrgload.h b/thirdparty/freetype/src/pfr/pfrgload.h
index d0e1420b67..f356b4c75b 100644
--- a/thirdparty/freetype/src/pfr/pfrgload.h
+++ b/thirdparty/freetype/src/pfr/pfrgload.h
@@ -4,7 +4,7 @@
*
* FreeType PFR glyph loader (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrload.c b/thirdparty/freetype/src/pfr/pfrload.c
index ccf0b7e1f8..6eeed28245 100644
--- a/thirdparty/freetype/src/pfr/pfrload.c
+++ b/thirdparty/freetype/src/pfr/pfrload.c
@@ -4,7 +4,7 @@
*
* FreeType PFR loader (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrload.h b/thirdparty/freetype/src/pfr/pfrload.h
index 2e7ffd0127..7d113df270 100644
--- a/thirdparty/freetype/src/pfr/pfrload.h
+++ b/thirdparty/freetype/src/pfr/pfrload.h
@@ -4,7 +4,7 @@
*
* FreeType PFR loader (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrobjs.c b/thirdparty/freetype/src/pfr/pfrobjs.c
index 9765f95c2f..9bc90a4b68 100644
--- a/thirdparty/freetype/src/pfr/pfrobjs.c
+++ b/thirdparty/freetype/src/pfr/pfrobjs.c
@@ -4,7 +4,7 @@
*
* FreeType PFR object methods (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrobjs.h b/thirdparty/freetype/src/pfr/pfrobjs.h
index 39cffd07c5..808822f1c4 100644
--- a/thirdparty/freetype/src/pfr/pfrobjs.h
+++ b/thirdparty/freetype/src/pfr/pfrobjs.h
@@ -4,7 +4,7 @@
*
* FreeType PFR object methods (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrsbit.c b/thirdparty/freetype/src/pfr/pfrsbit.c
index 00a9616455..00669e13ff 100644
--- a/thirdparty/freetype/src/pfr/pfrsbit.c
+++ b/thirdparty/freetype/src/pfr/pfrsbit.c
@@ -4,7 +4,7 @@
*
* FreeType PFR bitmap loader (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrsbit.h b/thirdparty/freetype/src/pfr/pfrsbit.h
index 6568b90943..8cb0de0d25 100644
--- a/thirdparty/freetype/src/pfr/pfrsbit.h
+++ b/thirdparty/freetype/src/pfr/pfrsbit.h
@@ -4,7 +4,7 @@
*
* FreeType PFR bitmap loader (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrtypes.h b/thirdparty/freetype/src/pfr/pfrtypes.h
index 6a5f9d571b..dfc47beff3 100644
--- a/thirdparty/freetype/src/pfr/pfrtypes.h
+++ b/thirdparty/freetype/src/pfr/pfrtypes.h
@@ -4,7 +4,7 @@
*
* FreeType PFR data structures (specification only).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/rules.mk b/thirdparty/freetype/src/pfr/rules.mk
index f14ca699e2..a1fe82baff 100644
--- a/thirdparty/freetype/src/pfr/rules.mk
+++ b/thirdparty/freetype/src/pfr/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2002-2019 by
+# Copyright (C) 2002-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psaux/afmparse.c b/thirdparty/freetype/src/psaux/afmparse.c
index f78adbba3d..b957158aec 100644
--- a/thirdparty/freetype/src/psaux/afmparse.c
+++ b/thirdparty/freetype/src/psaux/afmparse.c
@@ -4,7 +4,7 @@
*
* AFM parser (body).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/afmparse.h b/thirdparty/freetype/src/psaux/afmparse.h
index 2ceb77553b..50f4834b3f 100644
--- a/thirdparty/freetype/src/psaux/afmparse.h
+++ b/thirdparty/freetype/src/psaux/afmparse.h
@@ -4,7 +4,7 @@
*
* AFM parser (specification).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/cffdecode.c b/thirdparty/freetype/src/psaux/cffdecode.c
index 17cccf818b..172e3b23a3 100644
--- a/thirdparty/freetype/src/psaux/cffdecode.c
+++ b/thirdparty/freetype/src/psaux/cffdecode.c
@@ -4,7 +4,7 @@
*
* PostScript CFF (Type 2) decoding routines (body).
*
- * Copyright (C) 2017-2019 by
+ * Copyright (C) 2017-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -330,7 +330,7 @@
builder->left_bearing.x = 0;
builder->left_bearing.y = 0;
- builder->pos_x = adx - asb;
+ builder->pos_x = SUB_LONG( adx, asb );
builder->pos_y = ady;
/* Now load `achar' on top of the base outline. */
@@ -530,6 +530,9 @@
builder->path_begun = 0;
+ if ( !charstring_base )
+ return FT_Err_Ok;
+
zone->base = charstring_base;
limit = zone->limit = charstring_base + charstring_len;
ip = zone->cursor = zone->base;
diff --git a/thirdparty/freetype/src/psaux/cffdecode.h b/thirdparty/freetype/src/psaux/cffdecode.h
index a6691979f0..5dc968b255 100644
--- a/thirdparty/freetype/src/psaux/cffdecode.h
+++ b/thirdparty/freetype/src/psaux/cffdecode.h
@@ -4,7 +4,7 @@
*
* PostScript CFF (Type 2) decoding routines (specification).
*
- * Copyright (C) 2017-2019 by
+ * Copyright (C) 2017-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/module.mk b/thirdparty/freetype/src/psaux/module.mk
index bb0886abdf..651db01426 100644
--- a/thirdparty/freetype/src/psaux/module.mk
+++ b/thirdparty/freetype/src/psaux/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psaux/psaux.c b/thirdparty/freetype/src/psaux/psaux.c
index 1db0462551..96d2484e9d 100644
--- a/thirdparty/freetype/src/psaux/psaux.c
+++ b/thirdparty/freetype/src/psaux/psaux.c
@@ -4,7 +4,7 @@
*
* FreeType auxiliary PostScript driver component (body only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psauxerr.h b/thirdparty/freetype/src/psaux/psauxerr.h
index 523e1886c2..df8b09ff78 100644
--- a/thirdparty/freetype/src/psaux/psauxerr.h
+++ b/thirdparty/freetype/src/psaux/psauxerr.h
@@ -4,7 +4,7 @@
*
* PS auxiliary module error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psauxmod.c b/thirdparty/freetype/src/psaux/psauxmod.c
index 5df8e69056..bb520792e0 100644
--- a/thirdparty/freetype/src/psaux/psauxmod.c
+++ b/thirdparty/freetype/src/psaux/psauxmod.c
@@ -4,7 +4,7 @@
*
* FreeType auxiliary PostScript module implementation (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psauxmod.h b/thirdparty/freetype/src/psaux/psauxmod.h
index a0eda0bfc0..6e2eb67042 100644
--- a/thirdparty/freetype/src/psaux/psauxmod.h
+++ b/thirdparty/freetype/src/psaux/psauxmod.h
@@ -4,7 +4,7 @@
*
* FreeType auxiliary PostScript module implementation (specification).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psconv.c b/thirdparty/freetype/src/psaux/psconv.c
index c88761681c..c813a0596c 100644
--- a/thirdparty/freetype/src/psaux/psconv.c
+++ b/thirdparty/freetype/src/psaux/psconv.c
@@ -4,7 +4,7 @@
*
* Some convenience conversions (body).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psconv.h b/thirdparty/freetype/src/psaux/psconv.h
index 6b24bf6fc9..2cd5c60e4b 100644
--- a/thirdparty/freetype/src/psaux/psconv.h
+++ b/thirdparty/freetype/src/psaux/psconv.h
@@ -4,7 +4,7 @@
*
* Some convenience conversions (specification).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psft.c b/thirdparty/freetype/src/psaux/psft.c
index 54be468343..50b40bf8fe 100644
--- a/thirdparty/freetype/src/psaux/psft.c
+++ b/thirdparty/freetype/src/psaux/psft.c
@@ -313,7 +313,7 @@
FT_Error error = FT_Err_Ok;
CF2_Font font;
- FT_Bool is_t1 = decoder->builder.is_t1;
+ FT_Bool is_t1 = decoder->builder.is_t1;
FT_ASSERT( decoder &&
@@ -385,7 +385,7 @@
FT_ZERO( &buf );
buf.start =
buf.ptr = charstring_base;
- buf.end = charstring_base + charstring_len;
+ buf.end = FT_OFFSET( charstring_base, charstring_len );
FT_ZERO( &transform );
@@ -697,7 +697,7 @@
FT_ASSERT( charstring + len >= charstring );
buf->start = charstring;
- buf->end = charstring + len;
+ buf->end = FT_OFFSET( charstring, len );
buf->ptr = buf->start;
return FT_Err_Ok;
@@ -820,7 +820,7 @@
/* The CID driver stores subroutines with seed bytes. This */
/* case is taken care of when decoder->subrs_len == 0. */
if ( decoder->locals_len )
- buf->end = buf->start + decoder->locals_len[idx];
+ buf->end = FT_OFFSET( buf->start, decoder->locals_len[idx] );
else
{
/* We are using subroutines from a CID font. We must adjust */
diff --git a/thirdparty/freetype/src/psaux/psintrp.c b/thirdparty/freetype/src/psaux/psintrp.c
index e2f3accdd5..0a84145535 100644
--- a/thirdparty/freetype/src/psaux/psintrp.c
+++ b/thirdparty/freetype/src/psaux/psintrp.c
@@ -1433,6 +1433,13 @@
lastError = error2; /* pass FreeType error through */
goto exit;
}
+
+ /* save the left bearing and width of the SEAC */
+ /* glyph as they will be erased by the next load */
+
+ left_bearing = *decoder->builder.left_bearing;
+ advance = *decoder->builder.advance;
+
cf2_interpT2CharString( font,
&component,
callbacks,
@@ -1443,11 +1450,14 @@
&dummyWidth );
cf2_freeT1SeacComponent( decoder, &component );
- /* save the left bearing and width of the base */
- /* character as they will be erased by the next load */
+ /* If the SEAC glyph doesn't have a (H)SBW of its */
+ /* own use the values from the base glyph. */
- left_bearing = *decoder->builder.left_bearing;
- advance = *decoder->builder.advance;
+ if ( !haveWidth )
+ {
+ left_bearing = *decoder->builder.left_bearing;
+ advance = *decoder->builder.advance;
+ }
decoder->builder.left_bearing->x = 0;
decoder->builder.left_bearing->y = 0;
@@ -1473,8 +1483,8 @@
&dummyWidth );
cf2_freeT1SeacComponent( decoder, &component );
- /* restore the left side bearing and */
- /* advance width of the base character */
+ /* restore the left side bearing and advance width */
+ /* of the SEAC glyph or base character (saved above) */
*decoder->builder.left_bearing = left_bearing;
*decoder->builder.advance = advance;
diff --git a/thirdparty/freetype/src/psaux/psobjs.c b/thirdparty/freetype/src/psaux/psobjs.c
index 8bfdb92332..b37a78832c 100644
--- a/thirdparty/freetype/src/psaux/psobjs.c
+++ b/thirdparty/freetype/src/psaux/psobjs.c
@@ -4,7 +4,7 @@
*
* Auxiliary functions for PostScript fonts (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -214,7 +214,7 @@
}
/* add the object to the base block and adjust offset */
- table->elements[idx] = table->block + table->cursor;
+ table->elements[idx] = FT_OFFSET( table->block, table->cursor );
table->lengths [idx] = length;
FT_MEM_COPY( table->block + table->cursor, object, length );
@@ -2577,7 +2577,7 @@
FT_UShort seed )
{
PS_Conv_EexecDecode( &buffer,
- buffer + length,
+ FT_OFFSET( buffer, length ),
buffer,
length,
&seed );
diff --git a/thirdparty/freetype/src/psaux/psobjs.h b/thirdparty/freetype/src/psaux/psobjs.h
index c44dc450ec..d37638d0ca 100644
--- a/thirdparty/freetype/src/psaux/psobjs.h
+++ b/thirdparty/freetype/src/psaux/psobjs.h
@@ -4,7 +4,7 @@
*
* Auxiliary functions for PostScript fonts (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/rules.mk b/thirdparty/freetype/src/psaux/rules.mk
index 2de734d547..f49aecbc79 100644
--- a/thirdparty/freetype/src/psaux/rules.mk
+++ b/thirdparty/freetype/src/psaux/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psaux/t1cmap.c b/thirdparty/freetype/src/psaux/t1cmap.c
index d62d2d5c81..451b276537 100644
--- a/thirdparty/freetype/src/psaux/t1cmap.c
+++ b/thirdparty/freetype/src/psaux/t1cmap.c
@@ -4,7 +4,7 @@
*
* Type 1 character map support (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/t1cmap.h b/thirdparty/freetype/src/psaux/t1cmap.h
index d325e7b5a6..5411913831 100644
--- a/thirdparty/freetype/src/psaux/t1cmap.h
+++ b/thirdparty/freetype/src/psaux/t1cmap.h
@@ -4,7 +4,7 @@
*
* Type 1 character map support (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/t1decode.c b/thirdparty/freetype/src/psaux/t1decode.c
index c2b3729b53..fa1745d9e0 100644
--- a/thirdparty/freetype/src/psaux/t1decode.c
+++ b/thirdparty/freetype/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
*
* PostScript Type 1 decoding routines (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -367,6 +367,12 @@
FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
+ /* save the left bearing and width of the SEAC */
+ /* glyph as they will be erased by the next load */
+
+ left_bearing = decoder->builder.left_bearing;
+ advance = decoder->builder.advance;
+
/* the seac operator must not be nested */
decoder->seac = TRUE;
error = t1_decoder_parse_glyph( decoder, (FT_UInt)bchar_index );
@@ -374,11 +380,14 @@
if ( error )
goto Exit;
- /* save the left bearing and width of the base character */
- /* as they will be erased by the next load. */
+ /* If the SEAC glyph doesn't have a (H)SBW of its */
+ /* own use the values from the base glyph. */
- left_bearing = decoder->builder.left_bearing;
- advance = decoder->builder.advance;
+ if ( decoder->builder.parse_state != T1_Parse_Have_Width )
+ {
+ left_bearing = decoder->builder.left_bearing;
+ advance = decoder->builder.advance;
+ }
decoder->builder.left_bearing.x = 0;
decoder->builder.left_bearing.y = 0;
@@ -396,8 +405,8 @@
if ( error )
goto Exit;
- /* restore the left side bearing and */
- /* advance width of the base character */
+ /* restore the left side bearing and advance width */
+ /* of the SEAC glyph or base character (saved above) */
decoder->builder.left_bearing = left_bearing;
decoder->builder.advance = advance;
@@ -650,10 +659,8 @@
if ( value > 32000 || value < -32000 )
{
if ( large_int )
- {
FT_ERROR(( "t1_decoder_parse_charstrings:"
" no `div' after large integer\n" ));
- }
else
large_int = TRUE;
}
@@ -1690,6 +1697,7 @@
FT_Byte* ip;
FT_Byte* limit;
T1_Builder builder = &decoder->builder;
+ FT_Bool large_int;
#ifdef FT_DEBUG_LEVEL_TRACE
FT_Bool bol = TRUE;
@@ -1707,6 +1715,8 @@
limit = zone->limit = charstring_base + charstring_len;
ip = zone->cursor = zone->base;
+ large_int = FALSE;
+
/* now, execute loop */
while ( ip < limit )
{
@@ -1767,6 +1777,9 @@
case 7:
op = op_sbw;
break;
+ case 12:
+ op = op_div;
+ break;
default:
goto No_Width;
@@ -1796,13 +1809,19 @@
/* anyway. */
if ( value > 32000 || value < -32000 )
{
- FT_ERROR(( "t1_decoder_parse_metrics:"
- " large integer found for width\n" ));
- goto Syntax_Error;
+ if ( large_int )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " no `div' after large integer\n" ));
+ goto Syntax_Error;
+ }
+ else
+ large_int = TRUE;
}
else
{
- value = (FT_Int32)( (FT_UInt32)value << 16 );
+ if ( !large_int )
+ value = (FT_Int32)( (FT_UInt32)value << 16 );
}
break;
@@ -1827,7 +1846,8 @@
value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 );
}
- value = (FT_Int32)( (FT_UInt32)value << 16 );
+ if ( !large_int )
+ value = (FT_Int32)( (FT_UInt32)value << 16 );
}
else
{
@@ -1837,6 +1857,13 @@
}
}
+ if ( large_int && !( op == op_none || op == op_div ) )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " no `div' after large integer\n" ));
+ goto Syntax_Error;
+ }
+
/**********************************************************************
*
* Push value on stack, or process operator
@@ -1851,6 +1878,9 @@
}
#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( large_int )
+ FT_TRACE4(( " %d", value ));
+ else
FT_TRACE4(( " %d", value / 65536 ));
#endif
@@ -1869,11 +1899,14 @@
#ifdef FT_DEBUG_LEVEL_TRACE
- if ( top - decoder->stack != num_args )
- FT_TRACE0(( "t1_decoder_parse_metrics:"
- " too much operands on the stack"
- " (seen %d, expected %d)\n",
- top - decoder->stack, num_args ));
+ if ( op != op_div )
+ {
+ if ( top - decoder->stack != num_args )
+ FT_TRACE0(( "t1_decoder_parse_metrics:"
+ " too much operands on the stack"
+ " (seen %d, expected %d)\n",
+ top - decoder->stack, num_args ));
+ }
#endif /* FT_DEBUG_LEVEL_TRACE */
@@ -1917,12 +1950,26 @@
FT_TRACE4(( "\n" ));
return FT_Err_Ok;
+ case op_div:
+ FT_TRACE4(( " div" ));
+
+ /* if `large_int' is set, we divide unscaled numbers; */
+ /* otherwise, we divide numbers in 16.16 format -- */
+ /* in both cases, it is the same operation */
+ *top = FT_DivFix( top[0], top[1] );
+ top++;
+
+ large_int = FALSE;
+ break;
+
default:
FT_ERROR(( "t1_decoder_parse_metrics:"
" unhandled opcode %d\n", op ));
goto Syntax_Error;
}
+ decoder->top = top;
+
} /* general operator processing */
} /* while ip < limit */
diff --git a/thirdparty/freetype/src/psaux/t1decode.h b/thirdparty/freetype/src/psaux/t1decode.h
index 1b5d6263d3..231947e852 100644
--- a/thirdparty/freetype/src/psaux/t1decode.h
+++ b/thirdparty/freetype/src/psaux/t1decode.h
@@ -4,7 +4,7 @@
*
* PostScript Type 1 decoding routines (specification).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/module.mk b/thirdparty/freetype/src/pshinter/module.mk
index 0a12a260e1..b440d2e76a 100644
--- a/thirdparty/freetype/src/pshinter/module.mk
+++ b/thirdparty/freetype/src/pshinter/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/pshinter/pshalgo.c b/thirdparty/freetype/src/pshinter/pshalgo.c
index 0c5ae62699..57dfa3da96 100644
--- a/thirdparty/freetype/src/pshinter/pshalgo.c
+++ b/thirdparty/freetype/src/pshinter/pshalgo.c
@@ -4,7 +4,7 @@
*
* PostScript hinting algorithm (body).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/thirdparty/freetype/src/pshinter/pshalgo.h b/thirdparty/freetype/src/pshinter/pshalgo.h
index 6859e95cd2..5367a5d164 100644
--- a/thirdparty/freetype/src/pshinter/pshalgo.h
+++ b/thirdparty/freetype/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
*
* PostScript hinting algorithm (specification).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshglob.c b/thirdparty/freetype/src/pshinter/pshglob.c
index b021e6e42a..d9f835f99e 100644
--- a/thirdparty/freetype/src/pshinter/pshglob.c
+++ b/thirdparty/freetype/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
* PostScript hinter global hinting management (body).
* Inspired by the new auto-hinter module.
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/thirdparty/freetype/src/pshinter/pshglob.h b/thirdparty/freetype/src/pshinter/pshglob.h
index 0049d4c0bc..cd2f3122f7 100644
--- a/thirdparty/freetype/src/pshinter/pshglob.h
+++ b/thirdparty/freetype/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
*
* PostScript hinter global hinting management.
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshinter.c b/thirdparty/freetype/src/pshinter/pshinter.c
index 16c3a0a117..6009db5187 100644
--- a/thirdparty/freetype/src/pshinter/pshinter.c
+++ b/thirdparty/freetype/src/pshinter/pshinter.c
@@ -4,7 +4,7 @@
*
* FreeType PostScript Hinting module
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshmod.c b/thirdparty/freetype/src/pshinter/pshmod.c
index 2d36ea2a6a..686859b3ed 100644
--- a/thirdparty/freetype/src/pshinter/pshmod.c
+++ b/thirdparty/freetype/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
*
* FreeType PostScript hinter module implementation (body).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshmod.h b/thirdparty/freetype/src/pshinter/pshmod.h
index ea8771308a..c44112e9d4 100644
--- a/thirdparty/freetype/src/pshinter/pshmod.h
+++ b/thirdparty/freetype/src/pshinter/pshmod.h
@@ -4,7 +4,7 @@
*
* PostScript hinter module interface (specification).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshnterr.h b/thirdparty/freetype/src/pshinter/pshnterr.h
index fb9dbca2b1..c4e9f42d2c 100644
--- a/thirdparty/freetype/src/pshinter/pshnterr.h
+++ b/thirdparty/freetype/src/pshinter/pshnterr.h
@@ -4,7 +4,7 @@
*
* PS Hinter error codes (specification only).
*
- * Copyright (C) 2003-2019 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshrec.c b/thirdparty/freetype/src/pshinter/pshrec.c
index 9dd09efe4c..a81c6f7123 100644
--- a/thirdparty/freetype/src/pshinter/pshrec.c
+++ b/thirdparty/freetype/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
*
* FreeType PostScript hints recorder (body).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshrec.h b/thirdparty/freetype/src/pshinter/pshrec.h
index 02cc2102ec..a8bc5aeecb 100644
--- a/thirdparty/freetype/src/pshinter/pshrec.h
+++ b/thirdparty/freetype/src/pshinter/pshrec.h
@@ -4,7 +4,7 @@
*
* Postscript (Type1/Type2) hints recorder (specification).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/rules.mk b/thirdparty/freetype/src/pshinter/rules.mk
index 58227d10f2..c845c255cd 100644
--- a/thirdparty/freetype/src/pshinter/rules.mk
+++ b/thirdparty/freetype/src/pshinter/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2001-2019 by
+# Copyright (C) 2001-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psnames/module.mk b/thirdparty/freetype/src/psnames/module.mk
index 0806a318a7..675bb37131 100644
--- a/thirdparty/freetype/src/psnames/module.mk
+++ b/thirdparty/freetype/src/psnames/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psnames/psmodule.c b/thirdparty/freetype/src/psnames/psmodule.c
index 0ec440e67b..bb3ff07022 100644
--- a/thirdparty/freetype/src/psnames/psmodule.c
+++ b/thirdparty/freetype/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
*
* psnames module implementation (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psnames/psmodule.h b/thirdparty/freetype/src/psnames/psmodule.h
index 0df9a7d889..955f699f3a 100644
--- a/thirdparty/freetype/src/psnames/psmodule.h
+++ b/thirdparty/freetype/src/psnames/psmodule.h
@@ -4,7 +4,7 @@
*
* High-level psnames module interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psnames/psnamerr.h b/thirdparty/freetype/src/psnames/psnamerr.h
index 67ab1765d3..fb9058e61a 100644
--- a/thirdparty/freetype/src/psnames/psnamerr.h
+++ b/thirdparty/freetype/src/psnames/psnamerr.h
@@ -4,7 +4,7 @@
*
* PS names module error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psnames/psnames.c b/thirdparty/freetype/src/psnames/psnames.c
index 4722f98831..5ac3897d25 100644
--- a/thirdparty/freetype/src/psnames/psnames.c
+++ b/thirdparty/freetype/src/psnames/psnames.c
@@ -4,7 +4,7 @@
*
* FreeType psnames module component (body only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psnames/pstables.h b/thirdparty/freetype/src/psnames/pstables.h
index c0139bbc60..c215f16ffc 100644
--- a/thirdparty/freetype/src/psnames/pstables.h
+++ b/thirdparty/freetype/src/psnames/pstables.h
@@ -4,7 +4,7 @@
*
* PostScript glyph names.
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psnames/rules.mk b/thirdparty/freetype/src/psnames/rules.mk
index dcc203e391..14cdda3ad1 100644
--- a/thirdparty/freetype/src/psnames/rules.mk
+++ b/thirdparty/freetype/src/psnames/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/raster/ftmisc.h b/thirdparty/freetype/src/raster/ftmisc.h
index a246569e3b..6efe4a9a5a 100644
--- a/thirdparty/freetype/src/raster/ftmisc.h
+++ b/thirdparty/freetype/src/raster/ftmisc.h
@@ -5,7 +5,7 @@
* Miscellaneous macros for stand-alone rasterizer (specification
* only).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/thirdparty/freetype/src/raster/ftraster.c b/thirdparty/freetype/src/raster/ftraster.c
index 023b6c1eff..35655a6346 100644
--- a/thirdparty/freetype/src/raster/ftraster.c
+++ b/thirdparty/freetype/src/raster/ftraster.c
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/raster/ftraster.h b/thirdparty/freetype/src/raster/ftraster.h
index 50d34201a1..833d30f234 100644
--- a/thirdparty/freetype/src/raster/ftraster.h
+++ b/thirdparty/freetype/src/raster/ftraster.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/thirdparty/freetype/src/raster/ftrend1.c b/thirdparty/freetype/src/raster/ftrend1.c
index 62c727182a..944279a8d1 100644
--- a/thirdparty/freetype/src/raster/ftrend1.c
+++ b/thirdparty/freetype/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer interface (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/raster/ftrend1.h b/thirdparty/freetype/src/raster/ftrend1.h
index 82ecac686c..dc972b1bc2 100644
--- a/thirdparty/freetype/src/raster/ftrend1.h
+++ b/thirdparty/freetype/src/raster/ftrend1.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/raster/module.mk b/thirdparty/freetype/src/raster/module.mk
index 0a6d4b09d9..3600732b16 100644
--- a/thirdparty/freetype/src/raster/module.mk
+++ b/thirdparty/freetype/src/raster/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/raster/raster.c b/thirdparty/freetype/src/raster/raster.c
index e3ac9e566a..08431c8509 100644
--- a/thirdparty/freetype/src/raster/raster.c
+++ b/thirdparty/freetype/src/raster/raster.c
@@ -4,7 +4,7 @@
*
* FreeType monochrome rasterer module component (body only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/raster/rasterrs.h b/thirdparty/freetype/src/raster/rasterrs.h
index 7266407365..379e1d3e89 100644
--- a/thirdparty/freetype/src/raster/rasterrs.h
+++ b/thirdparty/freetype/src/raster/rasterrs.h
@@ -4,7 +4,7 @@
*
* monochrome renderer error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/raster/rules.mk b/thirdparty/freetype/src/raster/rules.mk
index 7664671e80..3e949d7741 100644
--- a/thirdparty/freetype/src/raster/rules.mk
+++ b/thirdparty/freetype/src/raster/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/sfnt/module.mk b/thirdparty/freetype/src/sfnt/module.mk
index 8c3b44fec7..0f459d8421 100644
--- a/thirdparty/freetype/src/sfnt/module.mk
+++ b/thirdparty/freetype/src/sfnt/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/sfnt/pngshim.c b/thirdparty/freetype/src/sfnt/pngshim.c
index ca85d9751f..523b30a745 100644
--- a/thirdparty/freetype/src/sfnt/pngshim.c
+++ b/thirdparty/freetype/src/sfnt/pngshim.c
@@ -4,7 +4,7 @@
*
* PNG Bitmap glyph support.
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* Google, Inc.
* Written by Stuart Gill and Behdad Esfahbod.
*
@@ -68,6 +68,7 @@
( ( __clang_major__ >= 4 ) || \
( ( __clang_major__ == 3 ) && ( __clang_minor__ >= 2 ) ) ) ) ) && \
defined( __OPTIMIZE__ ) && \
+ defined( __SSE__ ) && \
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#ifdef __clang__
diff --git a/thirdparty/freetype/src/sfnt/pngshim.h b/thirdparty/freetype/src/sfnt/pngshim.h
index 06c6f6b20e..d2c9e2b9b5 100644
--- a/thirdparty/freetype/src/sfnt/pngshim.h
+++ b/thirdparty/freetype/src/sfnt/pngshim.h
@@ -4,7 +4,7 @@
*
* PNG Bitmap glyph support.
*
- * Copyright (C) 2013-2019 by
+ * Copyright (C) 2013-2020 by
* Google, Inc.
* Written by Stuart Gill and Behdad Esfahbod.
*
diff --git a/thirdparty/freetype/src/sfnt/rules.mk b/thirdparty/freetype/src/sfnt/rules.mk
index ee3314eac3..f56ef060ed 100644
--- a/thirdparty/freetype/src/sfnt/rules.mk
+++ b/thirdparty/freetype/src/sfnt/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -28,19 +28,21 @@ SFNT_COMPILE := $(CC) $(ANSIFLAGS) \
# SFNT driver sources (i.e., C files)
#
-SFNT_DRV_SRC := $(SFNT_DIR)/pngshim.c \
- $(SFNT_DIR)/sfdriver.c \
- $(SFNT_DIR)/sfobjs.c \
- $(SFNT_DIR)/sfwoff.c \
- $(SFNT_DIR)/ttbdf.c \
- $(SFNT_DIR)/ttcmap.c \
- $(SFNT_DIR)/ttcolr.c \
- $(SFNT_DIR)/ttcpal.c \
- $(SFNT_DIR)/ttkern.c \
- $(SFNT_DIR)/ttload.c \
- $(SFNT_DIR)/ttmtx.c \
- $(SFNT_DIR)/ttpost.c \
- $(SFNT_DIR)/ttsbit.c
+SFNT_DRV_SRC := $(SFNT_DIR)/pngshim.c \
+ $(SFNT_DIR)/sfdriver.c \
+ $(SFNT_DIR)/sfobjs.c \
+ $(SFNT_DIR)/sfwoff.c \
+ $(SFNT_DIR)/sfwoff2.c \
+ $(SFNT_DIR)/ttbdf.c \
+ $(SFNT_DIR)/ttcmap.c \
+ $(SFNT_DIR)/ttcolr.c \
+ $(SFNT_DIR)/ttcpal.c \
+ $(SFNT_DIR)/ttkern.c \
+ $(SFNT_DIR)/ttload.c \
+ $(SFNT_DIR)/ttmtx.c \
+ $(SFNT_DIR)/ttpost.c \
+ $(SFNT_DIR)/ttsbit.c \
+ $(SFNT_DIR)/woff2tags.c
# SFNT driver headers
#
diff --git a/thirdparty/freetype/src/sfnt/sfdriver.c b/thirdparty/freetype/src/sfnt/sfdriver.c
index 2611685284..6ca4f3c268 100644
--- a/thirdparty/freetype/src/sfnt/sfdriver.c
+++ b/thirdparty/freetype/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
*
* High-level SFNT driver interface (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/sfdriver.h b/thirdparty/freetype/src/sfnt/sfdriver.h
index 8c174634b3..d108ee2000 100644
--- a/thirdparty/freetype/src/sfnt/sfdriver.h
+++ b/thirdparty/freetype/src/sfnt/sfdriver.h
@@ -4,7 +4,7 @@
*
* High-level SFNT driver interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/sferrors.h b/thirdparty/freetype/src/sfnt/sferrors.h
index 43e148d295..fbfca0e525 100644
--- a/thirdparty/freetype/src/sfnt/sferrors.h
+++ b/thirdparty/freetype/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
*
* SFNT error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/sfnt.c b/thirdparty/freetype/src/sfnt/sfnt.c
index b4faf34a3a..9db7935ae4 100644
--- a/thirdparty/freetype/src/sfnt/sfnt.c
+++ b/thirdparty/freetype/src/sfnt/sfnt.c
@@ -4,7 +4,7 @@
*
* Single object library component.
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -23,6 +23,7 @@
#include "sfdriver.c"
#include "sfobjs.c"
#include "sfwoff.c"
+#include "sfwoff2.c"
#include "ttbdf.c"
#include "ttcmap.c"
#include "ttcolr.c"
@@ -33,6 +34,7 @@
#include "ttmtx.c"
#include "ttpost.c"
#include "ttsbit.c"
+#include "woff2tags.c"
/* END */
diff --git a/thirdparty/freetype/src/sfnt/sfobjs.c b/thirdparty/freetype/src/sfnt/sfobjs.c
index 6edf3ae1de..2c66a9b648 100644
--- a/thirdparty/freetype/src/sfnt/sfobjs.c
+++ b/thirdparty/freetype/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
*
* SFNT object management (base).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -22,6 +22,7 @@
#include "ttcmap.h"
#include "ttkern.h"
#include "sfwoff.h"
+#include "sfwoff2.h"
#include FT_INTERNAL_SFNT_H
#include FT_INTERNAL_DEBUG_H
#include FT_TRUETYPE_IDS_H
@@ -341,7 +342,9 @@
/* synthesized into a TTC with one offset table. */
static FT_Error
sfnt_open_font( FT_Stream stream,
- TT_Face face )
+ TT_Face face,
+ FT_Int* face_instance_index,
+ FT_Long* woff2_num_faces )
{
FT_Memory memory = stream->memory;
FT_Error error;
@@ -385,6 +388,25 @@
goto retry;
}
+ if ( tag == TTAG_wOF2 )
+ {
+ FT_TRACE2(( "sfnt_open_font: file is a WOFF2; synthesizing SFNT\n" ));
+
+ if ( FT_STREAM_SEEK( offset ) )
+ return error;
+
+ error = woff2_open_font( stream,
+ face,
+ face_instance_index,
+ woff2_num_faces );
+ if ( error )
+ return error;
+
+ /* Swap out stream and retry! */
+ stream = face->root.stream;
+ goto retry;
+ }
+
if ( tag != 0x00010000UL &&
tag != TTAG_ttcf &&
tag != TTAG_OTTO &&
@@ -461,9 +483,10 @@
FT_Parameter* params )
{
FT_Error error;
- FT_Library library = face->root.driver->root.library;
+ FT_Library library = face->root.driver->root.library;
SFNT_Service sfnt;
FT_Int face_index;
+ FT_Long woff2_num_faces = 0;
/* for now, parameters are unused */
@@ -514,7 +537,10 @@
FT_TRACE2(( "SFNT driver\n" ));
- error = sfnt_open_font( stream, face );
+ error = sfnt_open_font( stream,
+ face,
+ &face_instance_index,
+ &woff2_num_faces );
if ( error )
return error;
@@ -689,6 +715,10 @@
face->root.num_faces = face->ttc_header.count;
face->root.face_index = face_instance_index;
+ /* `num_faces' for a WOFF2 needs to be handled separately. */
+ if ( woff2_num_faces )
+ face->root.num_faces = woff2_num_faces;
+
return error;
}
diff --git a/thirdparty/freetype/src/sfnt/sfobjs.h b/thirdparty/freetype/src/sfnt/sfobjs.h
index 3fbf2dd6bd..d8438a4834 100644
--- a/thirdparty/freetype/src/sfnt/sfobjs.h
+++ b/thirdparty/freetype/src/sfnt/sfobjs.h
@@ -4,7 +4,7 @@
*
* SFNT object management (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/sfwoff.c b/thirdparty/freetype/src/sfnt/sfwoff.c
index ca4821a20a..d1e330f675 100644
--- a/thirdparty/freetype/src/sfnt/sfwoff.c
+++ b/thirdparty/freetype/src/sfnt/sfwoff.c
@@ -4,7 +4,7 @@
*
* WOFF format management (base).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -371,18 +371,18 @@
sfnt + table->OrigOffset, &output_len,
stream->cursor, table->CompLength );
if ( error )
- goto Exit;
+ goto Exit1;
if ( output_len != table->OrigLength )
{
FT_ERROR(( "woff_font_open: compressed table length mismatch\n" ));
error = FT_THROW( Invalid_Table );
- goto Exit;
+ goto Exit1;
}
#else /* !FT_CONFIG_OPTION_USE_ZLIB */
error = FT_THROW( Unimplemented_Feature );
- goto Exit;
+ goto Exit1;
#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
}
@@ -424,6 +424,10 @@
}
return error;
+
+ Exit1:
+ FT_FRAME_EXIT();
+ goto Exit;
}
diff --git a/thirdparty/freetype/src/sfnt/sfwoff.h b/thirdparty/freetype/src/sfnt/sfwoff.h
index 15495c32a2..c1789d33d5 100644
--- a/thirdparty/freetype/src/sfnt/sfwoff.h
+++ b/thirdparty/freetype/src/sfnt/sfwoff.h
@@ -4,7 +4,7 @@
*
* WOFFF format management (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/sfwoff2.c b/thirdparty/freetype/src/sfnt/sfwoff2.c
new file mode 100644
index 0000000000..1b99e7d28c
--- /dev/null
+++ b/thirdparty/freetype/src/sfnt/sfwoff2.c
@@ -0,0 +1,2328 @@
+/****************************************************************************
+ *
+ * sfwoff2.c
+ *
+ * WOFF2 format management (base).
+ *
+ * Copyright (C) 2019-2020 by
+ * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+#include <ft2build.h>
+#include "sfwoff2.h"
+#include "woff2tags.h"
+#include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_BROTLI
+
+#include <brotli/decode.h>
+
+#endif
+
+
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
+#undef FT_COMPONENT
+#define FT_COMPONENT sfwoff2
+
+
+#define READ_255USHORT( var ) FT_SET_ERROR( Read255UShort( stream, &var ) )
+
+#define READ_BASE128( var ) FT_SET_ERROR( ReadBase128( stream, &var ) )
+
+#define ROUND4( var ) ( ( var + 3 ) & ~3 )
+
+#define WRITE_USHORT( p, v ) \
+ do \
+ { \
+ *(p)++ = (FT_Byte)( (v) >> 8 ); \
+ *(p)++ = (FT_Byte)( (v) >> 0 ); \
+ \
+ } while ( 0 )
+
+#define WRITE_ULONG( p, v ) \
+ do \
+ { \
+ *(p)++ = (FT_Byte)( (v) >> 24 ); \
+ *(p)++ = (FT_Byte)( (v) >> 16 ); \
+ *(p)++ = (FT_Byte)( (v) >> 8 ); \
+ *(p)++ = (FT_Byte)( (v) >> 0 ); \
+ \
+ } while ( 0 )
+
+#define WRITE_SHORT( p, v ) \
+ do \
+ { \
+ *(p)++ = ( (v) >> 8 ); \
+ *(p)++ = ( (v) >> 0 ); \
+ \
+ } while ( 0 )
+
+#define WRITE_SFNT_BUF( buf, s ) \
+ write_buf( &sfnt, sfnt_size, &dest_offset, buf, s, memory )
+
+#define WRITE_SFNT_BUF_AT( offset, buf, s ) \
+ write_buf( &sfnt, sfnt_size, &offset, buf, s, memory )
+
+#define N_CONTOUR_STREAM 0
+#define N_POINTS_STREAM 1
+#define FLAG_STREAM 2
+#define GLYPH_STREAM 3
+#define COMPOSITE_STREAM 4
+#define BBOX_STREAM 5
+#define INSTRUCTION_STREAM 6
+
+
+ static void
+ stream_close( FT_Stream stream )
+ {
+ FT_Memory memory = stream->memory;
+
+
+ FT_FREE( stream->base );
+
+ stream->size = 0;
+ stream->base = NULL;
+ stream->close = NULL;
+ }
+
+
+ FT_CALLBACK_DEF( int )
+ compare_tags( const void* a,
+ const void* b )
+ {
+ WOFF2_Table table1 = *(WOFF2_Table*)a;
+ WOFF2_Table table2 = *(WOFF2_Table*)b;
+
+ FT_ULong tag1 = table1->Tag;
+ FT_ULong tag2 = table2->Tag;
+
+
+ if ( tag1 > tag2 )
+ return 1;
+ else if ( tag1 < tag2 )
+ return -1;
+ else
+ return 0;
+ }
+
+
+ static FT_Error
+ Read255UShort( FT_Stream stream,
+ FT_UShort* value )
+ {
+ static const FT_Int oneMoreByteCode1 = 255;
+ static const FT_Int oneMoreByteCode2 = 254;
+ static const FT_Int wordCode = 253;
+ static const FT_Int lowestUCode = 253;
+
+ FT_Error error = FT_Err_Ok;
+ FT_Byte code;
+ FT_Byte result_byte = 0;
+ FT_UShort result_short = 0;
+
+
+ if ( FT_READ_BYTE( code ) )
+ return error;
+ if ( code == wordCode )
+ {
+ /* Read next two bytes and store `FT_UShort' value. */
+ if ( FT_READ_USHORT( result_short ) )
+ return error;
+ *value = result_short;
+ return FT_Err_Ok;
+ }
+ else if ( code == oneMoreByteCode1 )
+ {
+ if ( FT_READ_BYTE( result_byte ) )
+ return error;
+ *value = result_byte + lowestUCode;
+ return FT_Err_Ok;
+ }
+ else if ( code == oneMoreByteCode2 )
+ {
+ if ( FT_READ_BYTE( result_byte ) )
+ return error;
+ *value = result_byte + lowestUCode * 2;
+ return FT_Err_Ok;
+ }
+ else
+ {
+ *value = code;
+ return FT_Err_Ok;
+ }
+ }
+
+
+ static FT_Error
+ ReadBase128( FT_Stream stream,
+ FT_ULong* value )
+ {
+ FT_ULong result = 0;
+ FT_Int i;
+ FT_Byte code;
+ FT_Error error = FT_Err_Ok;
+
+
+ for ( i = 0; i < 5; ++i )
+ {
+ code = 0;
+ if ( FT_READ_BYTE( code ) )
+ return error;
+
+ /* Leading zeros are invalid. */
+ if ( i == 0 && code == 0x80 )
+ return FT_THROW( Invalid_Table );
+
+ /* If any of top seven bits are set then we're about to overflow. */
+ if ( result & 0xfe000000 )
+ return FT_THROW( Invalid_Table );
+
+ result = ( result << 7 ) | ( code & 0x7f );
+
+ /* Spin until most significant bit of data byte is false. */
+ if ( ( code & 0x80 ) == 0 )
+ {
+ *value = result;
+ return FT_Err_Ok;
+ }
+ }
+
+ /* Make sure not to exceed the size bound. */
+ return FT_THROW( Invalid_Table );
+ }
+
+
+ /* Extend memory of `dst_bytes' buffer and copy data from `src'. */
+ static FT_Error
+ write_buf( FT_Byte** dst_bytes,
+ FT_ULong* dst_size,
+ FT_ULong* offset,
+ FT_Byte* src,
+ FT_ULong size,
+ FT_Memory memory )
+ {
+ FT_Error error = FT_Err_Ok;
+ /* We are reallocating memory for `dst', so its pointer may change. */
+ FT_Byte* dst = *dst_bytes;
+
+
+ /* Check whether we are within limits. */
+ if ( ( *offset + size ) > WOFF2_DEFAULT_MAX_SIZE )
+ return FT_THROW( Array_Too_Large );
+
+ /* Reallocate `dst'. */
+ if ( ( *offset + size ) > *dst_size )
+ {
+ FT_TRACE6(( "Reallocating %lu to %lu.\n",
+ *dst_size, (*offset + size) ));
+ if ( FT_REALLOC( dst,
+ (FT_ULong)( *dst_size ),
+ (FT_ULong)( *offset + size ) ) )
+ goto Exit;
+
+ *dst_size = *offset + size;
+ }
+
+ /* Copy data. */
+ ft_memcpy( dst + *offset, src, size );
+
+ *offset += size;
+ /* Set pointer of `dst' to its correct value. */
+ *dst_bytes = dst;
+
+ Exit:
+ return error;
+ }
+
+
+ /* Pad buffer to closest multiple of 4. */
+ static FT_Error
+ pad4( FT_Byte** sfnt_bytes,
+ FT_ULong* sfnt_size,
+ FT_ULong* out_offset,
+ FT_Memory memory )
+ {
+ FT_Byte* sfnt = *sfnt_bytes;
+ FT_ULong dest_offset = *out_offset;
+
+ FT_Byte zeroes[] = { 0, 0, 0 };
+ FT_ULong pad_bytes;
+
+
+ if ( dest_offset + 3 < dest_offset )
+ return FT_THROW( Invalid_Table );
+
+ pad_bytes = ROUND4( dest_offset ) - dest_offset;
+ if ( pad_bytes > 0 )
+ {
+ if ( WRITE_SFNT_BUF( &zeroes[0], pad_bytes ) )
+ return FT_THROW( Invalid_Table );
+ }
+
+ *sfnt_bytes = sfnt;
+ *out_offset = dest_offset;
+ return FT_Err_Ok;
+ }
+
+
+ /* Calculate table checksum of `buf'. */
+ static FT_Long
+ compute_ULong_sum( FT_Byte* buf,
+ FT_ULong size )
+ {
+ FT_ULong checksum = 0;
+ FT_ULong aligned_size = size & ~3;
+ FT_ULong i;
+ FT_ULong v;
+
+
+ for ( i = 0; i < aligned_size; i += 4 )
+ checksum += ( (FT_ULong)buf[i ] << 24 ) |
+ ( (FT_ULong)buf[i + 1] << 16 ) |
+ ( (FT_ULong)buf[i + 2] << 8 ) |
+ ( (FT_ULong)buf[i + 3] << 0 );
+
+ /* If size is not aligned to 4, treat as if it is padded with 0s. */
+ if ( size != aligned_size )
+ {
+ v = 0;
+ for ( i = aligned_size ; i < size; ++i )
+ v |= (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) );
+ checksum += v;
+ }
+
+ return checksum;
+ }
+
+
+ static FT_Error
+ woff2_decompress( FT_Byte* dst,
+ FT_ULong dst_size,
+ const FT_Byte* src,
+ FT_ULong src_size )
+ {
+#ifdef FT_CONFIG_OPTION_USE_BROTLI
+
+ FT_ULong uncompressed_size = dst_size;
+ BrotliDecoderResult result;
+
+
+ result = BrotliDecoderDecompress( src_size,
+ src,
+ &uncompressed_size,
+ dst );
+
+ if ( result != BROTLI_DECODER_RESULT_SUCCESS ||
+ uncompressed_size != dst_size )
+ {
+ FT_ERROR(( "woff2_decompress: Stream length mismatch.\n" ));
+ return FT_THROW( Invalid_Table );
+ }
+
+ FT_TRACE2(( "woff2_decompress: Brotli stream decompressed.\n" ));
+ return FT_Err_Ok;
+
+#else /* !FT_CONFIG_OPTION_USE_BROTLI */
+
+ FT_ERROR(( "woff2_decompress: Brotli support not available.\n" ));
+ return FT_THROW( Unimplemented_Feature );
+
+#endif /* !FT_CONFIG_OPTION_USE_BROTLI */
+ }
+
+
+ static WOFF2_Table
+ find_table( WOFF2_Table* tables,
+ FT_UShort num_tables,
+ FT_ULong tag )
+ {
+ FT_Int i;
+
+
+ for ( i = 0; i < num_tables; i++ )
+ {
+ if ( tables[i]->Tag == tag )
+ return tables[i];
+ }
+ return NULL;
+ }
+
+
+ /* Read `numberOfHMetrics' field from `hhea' table. */
+ static FT_Error
+ read_num_hmetrics( FT_Stream stream,
+ FT_UShort* num_hmetrics )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_UShort num_metrics;
+
+
+ if ( FT_STREAM_SKIP( 34 ) )
+ return FT_THROW( Invalid_Table );
+
+ if ( FT_READ_USHORT( num_metrics ) )
+ return FT_THROW( Invalid_Table );
+
+ *num_hmetrics = num_metrics;
+
+ return error;
+ }
+
+
+ /* An auxiliary function for overflow-safe addition. */
+ static FT_Int
+ with_sign( FT_Byte flag,
+ FT_Int base_val )
+ {
+ /* Precondition: 0 <= base_val < 65536 (to avoid overflow). */
+ return ( flag & 1 ) ? base_val : -base_val;
+ }
+
+
+ /* An auxiliary function for overflow-safe addition. */
+ static FT_Int
+ safe_int_addition( FT_Int a,
+ FT_Int b,
+ FT_Int* result )
+ {
+ if ( ( ( a > 0 ) && ( b > FT_INT_MAX - a ) ) ||
+ ( ( a < 0 ) && ( b < FT_INT_MIN - a ) ) )
+ return FT_THROW( Invalid_Table );
+
+ *result = a + b;
+ return FT_Err_Ok;
+ }
+
+
+ /*
+ * Decode variable-length (flag, xCoordinate, yCoordinate) triplet for a
+ * simple glyph. See
+ *
+ * https://www.w3.org/TR/WOFF2/#triplet_decoding
+ */
+ static FT_Error
+ triplet_decode( const FT_Byte* flags_in,
+ const FT_Byte* in,
+ FT_ULong in_size,
+ FT_ULong n_points,
+ WOFF2_Point result,
+ FT_ULong* in_bytes_used )
+ {
+ FT_Int x = 0;
+ FT_Int y = 0;
+ FT_Int dx;
+ FT_Int dy;
+ FT_Int b0, b1, b2;
+
+ FT_ULong triplet_index = 0;
+ FT_ULong data_bytes;
+
+ FT_UInt i;
+
+
+ if ( n_points > in_size )
+ return FT_THROW( Invalid_Table );
+
+ for ( i = 0; i < n_points; ++i )
+ {
+ FT_Byte flag = flags_in[i];
+ FT_Bool on_curve = !( flag >> 7 );
+
+
+ flag &= 0x7f;
+ if ( flag < 84 )
+ data_bytes = 1;
+ else if ( flag < 120 )
+ data_bytes = 2;
+ else if ( flag < 124 )
+ data_bytes = 3;
+ else
+ data_bytes = 4;
+
+ /* Overflow checks */
+ if ( triplet_index + data_bytes > in_size ||
+ triplet_index + data_bytes < triplet_index )
+ return FT_THROW( Invalid_Table );
+
+ if ( flag < 10 )
+ {
+ dx = 0;
+ dy = with_sign( flag,
+ ( ( flag & 14 ) << 7 ) + in[triplet_index] );
+ }
+ else if ( flag < 20 )
+ {
+ dx = with_sign( flag,
+ ( ( ( flag - 10 ) & 14 ) << 7 ) +
+ in[triplet_index] );
+ dy = 0;
+ }
+ else if ( flag < 84 )
+ {
+ b0 = flag - 20;
+ b1 = in[triplet_index];
+ dx = with_sign( flag,
+ 1 + ( b0 & 0x30 ) + ( b1 >> 4 ) );
+ dy = with_sign( flag >> 1,
+ 1 + ( ( b0 & 0x0c ) << 2 ) + ( b1 & 0x0f ) );
+ }
+ else if ( flag < 120 )
+ {
+ b0 = flag - 84;
+ dx = with_sign( flag,
+ 1 + ( ( b0 / 12 ) << 8 ) + in[triplet_index] );
+ dy = with_sign( flag >> 1,
+ 1 + ( ( ( b0 % 12 ) >> 2 ) << 8 ) +
+ in[triplet_index + 1] );
+ }
+ else if ( flag < 124 )
+ {
+ b2 = in[triplet_index + 1];
+ dx = with_sign( flag,
+ ( in[triplet_index] << 4 ) + ( b2 >> 4 ) );
+ dy = with_sign( flag >> 1,
+ ( ( b2 & 0x0f ) << 8 ) + in[triplet_index + 2] );
+ }
+ else
+ {
+ dx = with_sign( flag,
+ ( in[triplet_index] << 8 ) +
+ in[triplet_index + 1] );
+ dy = with_sign( flag >> 1,
+ ( in[triplet_index + 2] << 8 ) +
+ in[triplet_index + 3] );
+ }
+
+ triplet_index += data_bytes;
+
+ if ( safe_int_addition( x, dx, &x ) )
+ return FT_THROW( Invalid_Table );
+
+ if ( safe_int_addition( y, dy, &y ) )
+ return FT_THROW( Invalid_Table );
+
+ result[i].x = x;
+ result[i].y = y;
+ result[i].on_curve = on_curve;
+ }
+
+ *in_bytes_used = triplet_index;
+ return FT_Err_Ok;
+ }
+
+
+ /* Store decoded points in glyph buffer. */
+ static FT_Error
+ store_points( FT_ULong n_points,
+ const WOFF2_Point points,
+ FT_UShort n_contours,
+ FT_UShort instruction_len,
+ FT_Byte* dst,
+ FT_ULong dst_size,
+ FT_ULong* glyph_size )
+ {
+ FT_UInt flag_offset = 10 + ( 2 * n_contours ) + 2 + instruction_len;
+ FT_Int last_flag = -1;
+ FT_Int repeat_count = 0;
+ FT_Int last_x = 0;
+ FT_Int last_y = 0;
+ FT_UInt x_bytes = 0;
+ FT_UInt y_bytes = 0;
+ FT_UInt xy_bytes;
+ FT_UInt i;
+ FT_UInt x_offset;
+ FT_UInt y_offset;
+ FT_Byte* pointer;
+
+
+ for ( i = 0; i < n_points; ++i )
+ {
+ const WOFF2_PointRec point = points[i];
+
+ FT_Int flag = point.on_curve ? GLYF_ON_CURVE : 0;
+ FT_Int dx = point.x - last_x;
+ FT_Int dy = point.y - last_y;
+
+
+ if ( dx == 0 )
+ flag |= GLYF_THIS_X_IS_SAME;
+ else if ( dx > -256 && dx < 256 )
+ {
+ flag |= GLYF_X_SHORT | ( dx > 0 ? GLYF_THIS_X_IS_SAME : 0 );
+ x_bytes += 1;
+ }
+ else
+ x_bytes += 2;
+
+ if ( dy == 0 )
+ flag |= GLYF_THIS_Y_IS_SAME;
+ else if ( dy > -256 && dy < 256 )
+ {
+ flag |= GLYF_Y_SHORT | ( dy > 0 ? GLYF_THIS_Y_IS_SAME : 0 );
+ y_bytes += 1;
+ }
+ else
+ y_bytes += 2;
+
+ if ( flag == last_flag && repeat_count != 255 )
+ {
+ dst[flag_offset - 1] |= GLYF_REPEAT;
+ repeat_count++;
+ }
+ else
+ {
+ if ( repeat_count != 0 )
+ {
+ if ( flag_offset >= dst_size )
+ return FT_THROW( Invalid_Table );
+
+ dst[flag_offset++] = repeat_count;
+ }
+ if ( flag_offset >= dst_size )
+ return FT_THROW( Invalid_Table );
+
+ dst[flag_offset++] = flag;
+ repeat_count = 0;
+ }
+
+ last_x = point.x;
+ last_y = point.y;
+ last_flag = flag;
+ }
+
+ if ( repeat_count != 0 )
+ {
+ if ( flag_offset >= dst_size )
+ return FT_THROW( Invalid_Table );
+
+ dst[flag_offset++] = repeat_count;
+ }
+
+ xy_bytes = x_bytes + y_bytes;
+ if ( xy_bytes < x_bytes ||
+ flag_offset + xy_bytes < flag_offset ||
+ flag_offset + xy_bytes > dst_size )
+ return FT_THROW( Invalid_Table );
+
+ x_offset = flag_offset;
+ y_offset = flag_offset + x_bytes;
+ last_x = 0;
+ last_y = 0;
+
+ for ( i = 0; i < n_points; ++i )
+ {
+ FT_Int dx = points[i].x - last_x;
+ FT_Int dy = points[i].y - last_y;
+
+
+ if ( dx == 0 )
+ ;
+ else if ( dx > -256 && dx < 256 )
+ dst[x_offset++] = FT_ABS( dx );
+ else
+ {
+ pointer = dst + x_offset;
+ WRITE_SHORT( pointer, dx );
+ x_offset += 2;
+ }
+
+ last_x += dx;
+
+ if ( dy == 0 )
+ ;
+ else if ( dy > -256 && dy < 256 )
+ dst[y_offset++] = FT_ABS( dy );
+ else
+ {
+ pointer = dst + y_offset;
+ WRITE_SHORT( pointer, dy );
+ y_offset += 2;
+ }
+
+ last_y += dy;
+ }
+
+ *glyph_size = y_offset;
+ return FT_Err_Ok;
+ }
+
+
+ static void
+ compute_bbox( FT_ULong n_points,
+ const WOFF2_Point points,
+ FT_Byte* dst,
+ FT_UShort* src_x_min )
+ {
+ FT_Int x_min = 0;
+ FT_Int y_min = 0;
+ FT_Int x_max = 0;
+ FT_Int y_max = 0;
+
+ FT_UInt i;
+
+ FT_ULong offset;
+ FT_Byte* pointer;
+
+
+ if ( n_points > 0 )
+ {
+ x_min = points[0].x;
+ y_min = points[0].y;
+ x_max = points[0].x;
+ y_max = points[0].y;
+ }
+
+ for ( i = 1; i < n_points; ++i )
+ {
+ FT_Int x = points[i].x;
+ FT_Int y = points[i].y;
+
+
+ x_min = FT_MIN( x, x_min );
+ y_min = FT_MIN( y, y_min );
+ x_max = FT_MAX( x, x_max );
+ y_max = FT_MAX( y, y_max );
+ }
+
+ /* Write values to `glyf' record. */
+ offset = 2;
+ pointer = dst + offset;
+
+ WRITE_SHORT( pointer, x_min );
+ WRITE_SHORT( pointer, y_min );
+ WRITE_SHORT( pointer, x_max );
+ WRITE_SHORT( pointer, y_max );
+
+ *src_x_min = (FT_UShort)x_min;
+ }
+
+
+ static FT_Error
+ compositeGlyph_size( FT_Stream stream,
+ FT_ULong offset,
+ FT_ULong* size,
+ FT_Bool* have_instructions )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_ULong start_offset = offset;
+ FT_Bool we_have_inst = FALSE;
+ FT_UShort flags = FLAG_MORE_COMPONENTS;
+
+
+ if ( FT_STREAM_SEEK( start_offset ) )
+ goto Exit;
+ while ( flags & FLAG_MORE_COMPONENTS )
+ {
+ FT_ULong arg_size;
+
+
+ if ( FT_READ_USHORT( flags ) )
+ goto Exit;
+ we_have_inst |= ( flags & FLAG_WE_HAVE_INSTRUCTIONS ) != 0;
+ /* glyph index */
+ arg_size = 2;
+ if ( flags & FLAG_ARG_1_AND_2_ARE_WORDS )
+ arg_size += 4;
+ else
+ arg_size += 2;
+
+ if ( flags & FLAG_WE_HAVE_A_SCALE )
+ arg_size += 2;
+ else if ( flags & FLAG_WE_HAVE_AN_X_AND_Y_SCALE )
+ arg_size += 4;
+ else if ( flags & FLAG_WE_HAVE_A_TWO_BY_TWO )
+ arg_size += 8;
+
+ if ( FT_STREAM_SKIP( arg_size ) )
+ goto Exit;
+ }
+
+ *size = FT_STREAM_POS() - start_offset;
+ *have_instructions = we_have_inst;
+
+ Exit:
+ return error;
+ }
+
+
+ /* Store loca values (provided by `reconstruct_glyf') to output stream. */
+ static FT_Error
+ store_loca( FT_ULong* loca_values,
+ FT_ULong loca_values_size,
+ FT_UShort index_format,
+ FT_ULong* checksum,
+ FT_Byte** sfnt_bytes,
+ FT_ULong* sfnt_size,
+ FT_ULong* out_offset,
+ FT_Memory memory )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Byte* sfnt = *sfnt_bytes;
+ FT_ULong dest_offset = *out_offset;
+
+ FT_Byte* loca_buf = NULL;
+ FT_Byte* dst = NULL;
+
+ FT_UInt i = 0;
+ FT_ULong loca_buf_size;
+
+ const FT_ULong offset_size = index_format ? 4 : 2;
+
+
+ if ( ( loca_values_size << 2 ) >> 2 != loca_values_size )
+ goto Fail;
+
+ loca_buf_size = loca_values_size * offset_size;
+ if ( FT_NEW_ARRAY( loca_buf, loca_buf_size ) )
+ goto Fail;
+
+ dst = loca_buf;
+ for ( i = 0; i < loca_values_size; i++ )
+ {
+ FT_ULong value = loca_values[i];
+
+
+ if ( index_format )
+ WRITE_ULONG( dst, value );
+ else
+ WRITE_USHORT( dst, ( value >> 1 ) );
+ }
+
+ *checksum = compute_ULong_sum( loca_buf, loca_buf_size );
+ /* Write `loca' table to sfnt buffer. */
+ if ( WRITE_SFNT_BUF( loca_buf, loca_buf_size ) )
+ goto Fail;
+
+ /* Set pointer `sfnt_bytes' to its correct value. */
+ *sfnt_bytes = sfnt;
+ *out_offset = dest_offset;
+
+ FT_FREE( loca_buf );
+ return error;
+
+ Fail:
+ if ( !error )
+ error = FT_THROW( Invalid_Table );
+
+ FT_FREE( loca_buf );
+
+ return error;
+ }
+
+
+ static FT_Error
+ reconstruct_glyf( FT_Stream stream,
+ FT_ULong* glyf_checksum,
+ FT_ULong* loca_checksum,
+ FT_Byte** sfnt_bytes,
+ FT_ULong* sfnt_size,
+ FT_ULong* out_offset,
+ WOFF2_Info info,
+ FT_Memory memory )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Byte* sfnt = *sfnt_bytes;
+
+ /* current position in stream */
+ const FT_ULong pos = FT_STREAM_POS();
+
+ FT_UInt num_substreams = 7;
+
+ FT_UShort num_glyphs;
+ FT_UShort index_format;
+ FT_ULong expected_loca_length;
+ FT_UInt offset;
+ FT_UInt i;
+ FT_ULong points_size;
+ FT_ULong bitmap_length;
+ FT_ULong glyph_buf_size;
+ FT_ULong bbox_bitmap_offset;
+
+ const FT_ULong glyf_start = *out_offset;
+ FT_ULong dest_offset = *out_offset;
+
+ WOFF2_Substream substreams = NULL;
+
+ FT_ULong* loca_values = NULL;
+ FT_UShort* n_points_arr = NULL;
+ FT_Byte* glyph_buf = NULL;
+ WOFF2_Point points = NULL;
+
+
+ if ( FT_NEW_ARRAY( substreams, num_substreams ) )
+ goto Fail;
+
+ if ( FT_STREAM_SKIP( 4 ) )
+ goto Fail;
+ if ( FT_READ_USHORT( num_glyphs ) )
+ goto Fail;
+ if ( FT_READ_USHORT( index_format ) )
+ goto Fail;
+
+ FT_TRACE4(( "num_glyphs = %u; index_format = %u\n",
+ num_glyphs, index_format ));
+
+ info->num_glyphs = num_glyphs;
+
+ /* Calculate expected length of loca and compare. */
+ /* See https://www.w3.org/TR/WOFF2/#conform-mustRejectLoca */
+ /* index_format = 0 => Short version `loca'. */
+ /* index_format = 1 => Long version `loca'. */
+ expected_loca_length = ( index_format ? 4 : 2 ) *
+ ( (FT_ULong)num_glyphs + 1 );
+ if ( info->loca_table->dst_length != expected_loca_length )
+ goto Fail;
+
+ offset = ( 2 + num_substreams ) * 4;
+ if ( offset > info->glyf_table->TransformLength )
+ goto Fail;
+
+ for ( i = 0; i < num_substreams; ++i )
+ {
+ FT_ULong substream_size;
+
+
+ if ( FT_READ_ULONG( substream_size ) )
+ goto Fail;
+ if ( substream_size > info->glyf_table->TransformLength - offset )
+ goto Fail;
+
+ substreams[i].start = pos + offset;
+ substreams[i].offset = pos + offset;
+ substreams[i].size = substream_size;
+
+ FT_TRACE5(( " Substream %d: offset = %lu; size = %lu;\n",
+ i, substreams[i].offset, substreams[i].size ));
+ offset += substream_size;
+ }
+
+ if ( FT_NEW_ARRAY( loca_values, num_glyphs + 1 ) )
+ goto Fail;
+
+ points_size = 0;
+ bbox_bitmap_offset = substreams[BBOX_STREAM].offset;
+
+ /* Size of bboxBitmap = 4 * floor((numGlyphs + 31) / 32) */
+ bitmap_length = ( ( num_glyphs + 31 ) >> 5 ) << 2;
+ substreams[BBOX_STREAM].offset += bitmap_length;
+
+ glyph_buf_size = WOFF2_DEFAULT_GLYPH_BUF;
+ if ( FT_NEW_ARRAY( glyph_buf, glyph_buf_size ) )
+ goto Fail;
+
+ if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) )
+ goto Fail;
+
+ for ( i = 0; i < num_glyphs; ++i )
+ {
+ FT_ULong glyph_size = 0;
+ FT_UShort n_contours = 0;
+ FT_Bool have_bbox = FALSE;
+ FT_Byte bbox_bitmap;
+ FT_ULong bbox_offset;
+ FT_UShort x_min = 0;
+
+
+ /* Set `have_bbox'. */
+ bbox_offset = bbox_bitmap_offset + ( i >> 3 );
+ if ( FT_STREAM_SEEK( bbox_offset ) ||
+ FT_READ_BYTE( bbox_bitmap ) )
+ goto Fail;
+ if ( bbox_bitmap & ( 0x80 >> ( i & 7 ) ) )
+ have_bbox = TRUE;
+
+ /* Read value from `nContourStream'. */
+ if ( FT_STREAM_SEEK( substreams[N_CONTOUR_STREAM].offset ) ||
+ FT_READ_USHORT( n_contours ) )
+ goto Fail;
+ substreams[N_CONTOUR_STREAM].offset += 2;
+
+ if ( n_contours == 0xffff )
+ {
+ /* composite glyph */
+ FT_Bool have_instructions = FALSE;
+ FT_UShort instruction_size = 0;
+ FT_ULong composite_size;
+ FT_ULong size_needed;
+ FT_Byte* pointer = NULL;
+
+
+ /* Composite glyphs must have explicit bbox. */
+ if ( !have_bbox )
+ goto Fail;
+
+ if ( compositeGlyph_size( stream,
+ substreams[COMPOSITE_STREAM].offset,
+ &composite_size,
+ &have_instructions) )
+ goto Fail;
+
+ if ( have_instructions )
+ {
+ if ( FT_STREAM_SEEK( substreams[GLYPH_STREAM].offset ) ||
+ READ_255USHORT( instruction_size ) )
+ goto Fail;
+ substreams[GLYPH_STREAM].offset = FT_STREAM_POS();
+ }
+
+ size_needed = 12 + composite_size + instruction_size;
+ if ( glyph_buf_size < size_needed )
+ {
+ if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) )
+ goto Fail;
+ glyph_buf_size = size_needed;
+ }
+
+ pointer = glyph_buf + glyph_size;
+ WRITE_USHORT( pointer, n_contours );
+ glyph_size += 2;
+
+ /* Read x_min for current glyph. */
+ if ( FT_STREAM_SEEK( substreams[BBOX_STREAM].offset ) ||
+ FT_READ_USHORT( x_min ) )
+ goto Fail;
+ /* No increment here because we read again. */
+
+ if ( FT_STREAM_SEEK( substreams[BBOX_STREAM].offset ) ||
+ FT_STREAM_READ( glyph_buf + glyph_size, 8 ) )
+ goto Fail;
+
+ substreams[BBOX_STREAM].offset += 8;
+ glyph_size += 8;
+
+ if ( FT_STREAM_SEEK( substreams[COMPOSITE_STREAM].offset ) ||
+ FT_STREAM_READ( glyph_buf + glyph_size, composite_size ) )
+ goto Fail;
+
+ substreams[COMPOSITE_STREAM].offset += composite_size;
+ glyph_size += composite_size;
+
+ if ( have_instructions )
+ {
+ pointer = glyph_buf + glyph_size;
+ WRITE_USHORT( pointer, instruction_size );
+ glyph_size += 2;
+
+ if ( FT_STREAM_SEEK( substreams[INSTRUCTION_STREAM].offset ) ||
+ FT_STREAM_READ( glyph_buf + glyph_size, instruction_size ) )
+ goto Fail;
+
+ substreams[INSTRUCTION_STREAM].offset += instruction_size;
+ glyph_size += instruction_size;
+ }
+ }
+ else if ( n_contours > 0 )
+ {
+ /* simple glyph */
+ FT_ULong total_n_points = 0;
+ FT_UShort n_points_contour;
+ FT_UInt j;
+ FT_ULong flag_size;
+ FT_ULong triplet_size;
+ FT_ULong triplet_bytes_used;
+ FT_Byte* flags_buf = NULL;
+ FT_Byte* triplet_buf = NULL;
+ FT_UShort instruction_size;
+ FT_ULong size_needed;
+ FT_Int end_point;
+ FT_UInt contour_ix;
+
+ FT_Byte* pointer = NULL;
+
+
+ if ( FT_NEW_ARRAY( n_points_arr, n_contours ) )
+ goto Fail;
+
+ if ( FT_STREAM_SEEK( substreams[N_POINTS_STREAM].offset ) )
+ goto Fail;
+
+ for ( j = 0; j < n_contours; ++j )
+ {
+ if ( READ_255USHORT( n_points_contour ) )
+ goto Fail;
+ n_points_arr[j] = n_points_contour;
+ /* Prevent negative/overflow. */
+ if ( total_n_points + n_points_contour < total_n_points )
+ goto Fail;
+ total_n_points += n_points_contour;
+ }
+ substreams[N_POINTS_STREAM].offset = FT_STREAM_POS();
+
+ flag_size = total_n_points;
+ if ( flag_size > substreams[FLAG_STREAM].size )
+ goto Fail;
+
+ flags_buf = stream->base + substreams[FLAG_STREAM].offset;
+ triplet_buf = stream->base + substreams[GLYPH_STREAM].offset;
+
+ if ( substreams[GLYPH_STREAM].size <
+ ( substreams[GLYPH_STREAM].offset -
+ substreams[GLYPH_STREAM].start ) )
+ goto Fail;
+
+ triplet_size = substreams[GLYPH_STREAM].size -
+ ( substreams[GLYPH_STREAM].offset -
+ substreams[GLYPH_STREAM].start );
+ triplet_bytes_used = 0;
+
+ /* Create array to store point information. */
+ points_size = total_n_points;
+ if ( FT_NEW_ARRAY( points, points_size ) )
+ goto Fail;
+
+ if ( triplet_decode( flags_buf,
+ triplet_buf,
+ triplet_size,
+ total_n_points,
+ points,
+ &triplet_bytes_used ) )
+ goto Fail;
+
+ substreams[FLAG_STREAM].offset += flag_size;
+ substreams[GLYPH_STREAM].offset += triplet_bytes_used;
+
+ if ( FT_STREAM_SEEK( substreams[GLYPH_STREAM].offset ) ||
+ READ_255USHORT( instruction_size ) )
+ goto Fail;
+
+ substreams[GLYPH_STREAM].offset = FT_STREAM_POS();
+
+ if ( total_n_points >= ( 1 << 27 ) )
+ goto Fail;
+
+ size_needed = 12 +
+ ( 2 * n_contours ) +
+ ( 5 * total_n_points ) +
+ instruction_size;
+ if ( glyph_buf_size < size_needed )
+ {
+ if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) )
+ goto Fail;
+ glyph_buf_size = size_needed;
+ }
+
+ pointer = glyph_buf + glyph_size;
+ WRITE_USHORT( pointer, n_contours );
+ glyph_size += 2;
+
+ if ( have_bbox )
+ {
+ /* Read x_min for current glyph. */
+ if ( FT_STREAM_SEEK( substreams[BBOX_STREAM].offset ) ||
+ FT_READ_USHORT( x_min ) )
+ goto Fail;
+ /* No increment here because we read again. */
+
+ if ( FT_STREAM_SEEK( substreams[BBOX_STREAM].offset ) ||
+ FT_STREAM_READ( glyph_buf + glyph_size, 8 ) )
+ goto Fail;
+ substreams[BBOX_STREAM].offset += 8;
+ }
+ else
+ compute_bbox( total_n_points, points, glyph_buf, &x_min );
+
+ glyph_size = CONTOUR_OFFSET_END_POINT;
+
+ pointer = glyph_buf + glyph_size;
+ end_point = -1;
+
+ for ( contour_ix = 0; contour_ix < n_contours; ++contour_ix )
+ {
+ end_point += n_points_arr[contour_ix];
+ if ( end_point >= 65536 )
+ goto Fail;
+
+ WRITE_SHORT( pointer, end_point );
+ glyph_size += 2;
+ }
+
+ WRITE_USHORT( pointer, instruction_size );
+ glyph_size += 2;
+
+ if ( FT_STREAM_SEEK( substreams[INSTRUCTION_STREAM].offset ) ||
+ FT_STREAM_READ( glyph_buf + glyph_size, instruction_size ) )
+ goto Fail;
+
+ substreams[INSTRUCTION_STREAM].offset += instruction_size;
+ glyph_size += instruction_size;
+
+ if ( store_points( total_n_points,
+ points,
+ n_contours,
+ instruction_size,
+ glyph_buf,
+ glyph_buf_size,
+ &glyph_size ) )
+ goto Fail;
+
+ FT_FREE( points );
+ FT_FREE( n_points_arr );
+ }
+ else
+ {
+ /* Empty glyph. */
+ /* Must not have a bbox. */
+ if ( have_bbox )
+ {
+ FT_ERROR(( "Empty glyph has a bbox.\n" ));
+ goto Fail;
+ }
+ }
+
+ loca_values[i] = dest_offset - glyf_start;
+
+ if ( WRITE_SFNT_BUF( glyph_buf, glyph_size ) )
+ goto Fail;
+
+ if ( pad4( &sfnt, sfnt_size, &dest_offset, memory ) )
+ goto Fail;
+
+ *glyf_checksum += compute_ULong_sum( glyph_buf, glyph_size );
+
+ /* Store x_mins, may be required to reconstruct `hmtx'. */
+ if ( n_contours > 0 )
+ info->x_mins[i] = x_min;
+ }
+
+ info->glyf_table->dst_length = dest_offset - info->glyf_table->dst_offset;
+ info->loca_table->dst_offset = dest_offset;
+
+ /* `loca[n]' will be equal to the length of the `glyf' table. */
+ loca_values[num_glyphs] = info->glyf_table->dst_length;
+
+ if ( store_loca( loca_values,
+ num_glyphs + 1,
+ index_format,
+ loca_checksum,
+ &sfnt,
+ sfnt_size,
+ &dest_offset,
+ memory ) )
+ goto Fail;
+
+ info->loca_table->dst_length = dest_offset - info->loca_table->dst_offset;
+
+ FT_TRACE4(( " loca table info:\n" ));
+ FT_TRACE4(( " dst_offset = %lu\n", info->loca_table->dst_offset ));
+ FT_TRACE4(( " dst_length = %lu\n", info->loca_table->dst_length ));
+ FT_TRACE4(( " checksum = %09x\n", *loca_checksum ));
+
+ /* Set pointer `sfnt_bytes' to its correct value. */
+ *sfnt_bytes = sfnt;
+ *out_offset = dest_offset;
+
+ FT_FREE( substreams );
+ FT_FREE( loca_values );
+ FT_FREE( n_points_arr );
+ FT_FREE( glyph_buf );
+ FT_FREE( points );
+
+ return error;
+
+ Fail:
+ if ( !error )
+ error = FT_THROW( Invalid_Table );
+
+ /* Set pointer `sfnt_bytes' to its correct value. */
+ *sfnt_bytes = sfnt;
+
+ FT_FREE( substreams );
+ FT_FREE( loca_values );
+ FT_FREE( n_points_arr );
+ FT_FREE( glyph_buf );
+ FT_FREE( points );
+
+ return error;
+ }
+
+
+ /* Get `x_mins' for untransformed `glyf' table. */
+ static FT_Error
+ get_x_mins( FT_Stream stream,
+ WOFF2_Table* tables,
+ FT_UShort num_tables,
+ WOFF2_Info info,
+ FT_Memory memory )
+ {
+ FT_UShort num_glyphs;
+ FT_UShort index_format;
+ FT_ULong glyf_offset;
+ FT_UShort glyf_offset_short;
+ FT_ULong loca_offset;
+ FT_Int i;
+ FT_Error error = FT_Err_Ok;
+ FT_ULong offset_size;
+
+ /* At this point of time those tables might not have been read yet. */
+ const WOFF2_Table maxp_table = find_table( tables, num_tables,
+ TTAG_maxp );
+ const WOFF2_Table head_table = find_table( tables, num_tables,
+ TTAG_head );
+
+
+ if ( !maxp_table )
+ {
+ FT_ERROR(( "`maxp' table is missing.\n" ));
+ return FT_THROW( Invalid_Table );
+ }
+
+ if ( !head_table )
+ {
+ FT_ERROR(( "`head' table is missing.\n" ));
+ return FT_THROW( Invalid_Table );
+ }
+
+ /* Read `numGlyphs' field from `maxp' table. */
+ if ( FT_STREAM_SEEK( maxp_table->src_offset ) || FT_STREAM_SKIP( 8 ) )
+ return error;
+
+ if ( FT_READ_USHORT( num_glyphs ) )
+ return error;
+
+ info->num_glyphs = num_glyphs;
+
+ /* Read `indexToLocFormat' field from `head' table. */
+ if ( FT_STREAM_SEEK( head_table->src_offset ) ||
+ FT_STREAM_SKIP( 50 ) )
+ return error;
+
+ if ( FT_READ_USHORT( index_format ) )
+ return error;
+
+ offset_size = index_format ? 4 : 2;
+
+ /* Create `x_mins' array. */
+ if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) )
+ return error;
+
+ loca_offset = info->loca_table->src_offset;
+
+ for ( i = 0; i < num_glyphs; ++i )
+ {
+ if ( FT_STREAM_SEEK( loca_offset ) )
+ return error;
+
+ loca_offset += offset_size;
+
+ if ( index_format )
+ {
+ if ( FT_READ_ULONG( glyf_offset ) )
+ return error;
+ }
+ else
+ {
+ if ( FT_READ_USHORT( glyf_offset_short ) )
+ return error;
+
+ glyf_offset = (FT_ULong)( glyf_offset_short );
+ glyf_offset = glyf_offset << 1;
+ }
+
+ glyf_offset += info->glyf_table->src_offset;
+
+ if ( FT_STREAM_SEEK( glyf_offset ) || FT_STREAM_SKIP( 2 ) )
+ return error;
+
+ if ( FT_READ_USHORT( info->x_mins[i] ) )
+ return error;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ reconstruct_hmtx( FT_Stream stream,
+ FT_UShort num_glyphs,
+ FT_UShort num_hmetrics,
+ FT_Short* x_mins,
+ FT_ULong* checksum,
+ FT_Byte** sfnt_bytes,
+ FT_ULong* sfnt_size,
+ FT_ULong* out_offset,
+ FT_Memory memory )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Byte* sfnt = *sfnt_bytes;
+ FT_ULong dest_offset = *out_offset;
+
+ FT_Byte hmtx_flags;
+ FT_Bool has_proportional_lsbs, has_monospace_lsbs;
+ FT_ULong hmtx_table_size;
+ FT_Int i;
+
+ FT_UShort* advance_widths = NULL;
+ FT_Short* lsbs = NULL;
+ FT_Byte* hmtx_table = NULL;
+ FT_Byte* dst = NULL;
+
+
+ if ( FT_READ_BYTE( hmtx_flags ) )
+ goto Fail;
+
+ has_proportional_lsbs = ( hmtx_flags & 1 ) == 0;
+ has_monospace_lsbs = ( hmtx_flags & 2 ) == 0;
+
+ /* Bits 2-7 are reserved and MUST be zero. */
+ if ( ( hmtx_flags & 0xFC ) != 0 )
+ goto Fail;
+
+ /* Are you REALLY transformed? */
+ if ( has_proportional_lsbs && has_monospace_lsbs )
+ goto Fail;
+
+ /* Cannot have a transformed `hmtx' without `glyf'. */
+ if ( ( num_hmetrics > num_glyphs ) ||
+ ( num_hmetrics < 1 ) )
+ goto Fail;
+
+ /* Must have at least one entry. */
+ if ( num_hmetrics < 1 )
+ goto Fail;
+
+ if ( FT_NEW_ARRAY( advance_widths, num_hmetrics ) ||
+ FT_NEW_ARRAY( lsbs, num_glyphs ) )
+ goto Fail;
+
+ /* Read `advanceWidth' stream. Always present. */
+ for ( i = 0; i < num_hmetrics; i++ )
+ {
+ FT_UShort advance_width;
+
+
+ if ( FT_READ_USHORT( advance_width ) )
+ goto Fail;
+
+ advance_widths[i] = advance_width;
+ }
+
+ /* lsb values for proportional glyphs. */
+ for ( i = 0; i < num_hmetrics; i++ )
+ {
+ FT_Short lsb;
+
+
+ if ( has_proportional_lsbs )
+ {
+ if ( FT_READ_SHORT( lsb ) )
+ goto Fail;
+ }
+ else
+ lsb = x_mins[i];
+
+ lsbs[i] = lsb;
+ }
+
+ /* lsb values for monospaced glyphs. */
+ for ( i = num_hmetrics; i < num_glyphs; i++ )
+ {
+ FT_Short lsb;
+
+
+ if ( has_monospace_lsbs )
+ {
+ if ( FT_READ_SHORT( lsb ) )
+ goto Fail;
+ }
+ else
+ lsb = x_mins[i];
+
+ lsbs[i] = lsb;
+ }
+
+ /* Build the hmtx table. */
+ hmtx_table_size = 2 * num_hmetrics + 2 * num_glyphs;
+ if ( FT_NEW_ARRAY( hmtx_table, hmtx_table_size ) )
+ goto Fail;
+
+ dst = hmtx_table;
+ FT_TRACE6(( "hmtx values: \n" ));
+ for ( i = 0; i < num_glyphs; i++ )
+ {
+ if ( i < num_hmetrics )
+ {
+ WRITE_SHORT( dst, advance_widths[i] );
+ FT_TRACE6(( "%d ", advance_widths[i] ));
+ }
+
+ WRITE_SHORT( dst, lsbs[i] );
+ FT_TRACE6(( "%d ", lsbs[i] ));
+ }
+ FT_TRACE6(( "\n" ));
+
+ *checksum = compute_ULong_sum( hmtx_table, hmtx_table_size );
+ /* Write `hmtx' table to sfnt buffer. */
+ if ( WRITE_SFNT_BUF( hmtx_table, hmtx_table_size ) )
+ goto Fail;
+
+ /* Set pointer `sfnt_bytes' to its correct value. */
+ *sfnt_bytes = sfnt;
+ *out_offset = dest_offset;
+
+ FT_FREE( advance_widths );
+ FT_FREE( lsbs );
+ FT_FREE( hmtx_table );
+
+ return error;
+
+ Fail:
+ FT_FREE( advance_widths );
+ FT_FREE( lsbs );
+ FT_FREE( hmtx_table );
+
+ if ( !error )
+ error = FT_THROW( Invalid_Table );
+
+ return error;
+ }
+
+
+ static FT_Error
+ reconstruct_font( FT_Byte* transformed_buf,
+ FT_ULong transformed_buf_size,
+ WOFF2_Table* indices,
+ WOFF2_Header woff2,
+ WOFF2_Info info,
+ FT_Byte** sfnt_bytes,
+ FT_ULong* sfnt_size,
+ FT_Memory memory )
+ {
+ /* Memory management of `transformed_buf' is handled by the caller. */
+
+ FT_Error error = FT_Err_Ok;
+ FT_Stream stream = NULL;
+ FT_Byte* buf_cursor = NULL;
+ FT_Byte* table_entry = NULL;
+
+ /* We are reallocating memory for `sfnt', so its pointer may change. */
+ FT_Byte* sfnt = *sfnt_bytes;
+
+ FT_UShort num_tables = woff2->num_tables;
+ FT_ULong dest_offset = 12 + num_tables * 16UL;
+
+ FT_ULong checksum = 0;
+ FT_ULong loca_checksum = 0;
+ FT_Int nn = 0;
+ FT_UShort num_hmetrics = 0;
+ FT_ULong font_checksum = info->header_checksum;
+ FT_Bool is_glyf_xform = FALSE;
+
+ FT_ULong table_entry_offset = 12;
+
+
+ /* A few table checks before reconstruction. */
+ /* `glyf' must be present with `loca'. */
+ info->glyf_table = find_table( indices, num_tables, TTAG_glyf );
+ info->loca_table = find_table( indices, num_tables, TTAG_loca );
+
+ if ( ( info->glyf_table == NULL ) ^ ( info->loca_table == NULL ) )
+ {
+ FT_ERROR(( "One of `glyf'/`loca' tables missing.\n" ));
+ return FT_THROW( Invalid_Table );
+ }
+
+ /* Both `glyf' and `loca' must have same transformation. */
+ if ( info->glyf_table != NULL )
+ {
+ if ( ( info->glyf_table->flags & WOFF2_FLAGS_TRANSFORM ) !=
+ ( info->loca_table->flags & WOFF2_FLAGS_TRANSFORM ) )
+ {
+ FT_ERROR(( "Transformation mismatch"
+ " between `glyf' and `loca' table." ));
+ return FT_THROW( Invalid_Table );
+ }
+ }
+
+ /* Create buffer for table entries. */
+ if ( FT_NEW_ARRAY( table_entry, 16 ) )
+ goto Fail;
+
+ /* Create a stream for the uncompressed buffer. */
+ if ( FT_NEW( stream ) )
+ goto Fail;
+ FT_Stream_OpenMemory( stream, transformed_buf, transformed_buf_size );
+
+ FT_ASSERT( FT_STREAM_POS() == 0 );
+
+ /* Reconstruct/copy tables to output stream. */
+ for ( nn = 0; nn < num_tables; nn++ )
+ {
+ WOFF2_TableRec table = *( indices[nn] );
+
+
+ FT_TRACE3(( "Seeking to %d with table size %d.\n",
+ table.src_offset, table.src_length ));
+ FT_TRACE3(( "Table tag: %c%c%c%c.\n",
+ (FT_Char)( table.Tag >> 24 ),
+ (FT_Char)( table.Tag >> 16 ),
+ (FT_Char)( table.Tag >> 8 ),
+ (FT_Char)( table.Tag ) ));
+
+ if ( FT_STREAM_SEEK( table.src_offset ) )
+ goto Fail;
+
+ if ( table.src_offset + table.src_length > transformed_buf_size )
+ goto Fail;
+
+ /* Get stream size for fields of `hmtx' table. */
+ if ( table.Tag == TTAG_hhea )
+ {
+ if ( read_num_hmetrics( stream, &num_hmetrics ) )
+ goto Fail;
+ }
+
+ info->num_hmetrics = num_hmetrics;
+
+ checksum = 0;
+ if ( ( table.flags & WOFF2_FLAGS_TRANSFORM ) != WOFF2_FLAGS_TRANSFORM )
+ {
+ /* Check whether `head' is at least 12 bytes. */
+ if ( table.Tag == TTAG_head )
+ {
+ if ( table.src_length < 12 )
+ goto Fail;
+
+ buf_cursor = transformed_buf + table.src_offset + 8;
+ /* Set checkSumAdjustment = 0 */
+ WRITE_ULONG( buf_cursor, 0 );
+ }
+
+ table.dst_offset = dest_offset;
+
+ checksum = compute_ULong_sum( transformed_buf + table.src_offset,
+ table.src_length );
+ FT_TRACE4(( "Checksum = %09x.\n", checksum ));
+
+ if ( WRITE_SFNT_BUF( transformed_buf + table.src_offset,
+ table.src_length ) )
+ goto Fail;
+ }
+ else
+ {
+ FT_TRACE3(( "This table is transformed.\n" ));
+
+ if ( table.Tag == TTAG_glyf )
+ {
+ is_glyf_xform = TRUE;
+ table.dst_offset = dest_offset;
+
+ if ( reconstruct_glyf( stream,
+ &checksum,
+ &loca_checksum,
+ &sfnt,
+ sfnt_size,
+ &dest_offset,
+ info,
+ memory ) )
+ goto Fail;
+
+ FT_TRACE4(( "Checksum = %09x.\n", checksum ));
+ }
+
+ else if ( table.Tag == TTAG_loca )
+ checksum = loca_checksum;
+
+ else if ( table.Tag == TTAG_hmtx )
+ {
+ /* If glyf is not transformed and hmtx is, handle separately. */
+ if ( !is_glyf_xform )
+ {
+ if ( get_x_mins( stream, indices, num_tables, info, memory ) )
+ goto Fail;
+ }
+
+ table.dst_offset = dest_offset;
+
+ if ( reconstruct_hmtx( stream,
+ info->num_glyphs,
+ info->num_hmetrics,
+ info->x_mins,
+ &checksum,
+ &sfnt,
+ sfnt_size,
+ &dest_offset,
+ memory ) )
+ goto Fail;
+ }
+ else
+ {
+ /* Unknown transform. */
+ FT_ERROR(( "Unknown table transform.\n" ));
+ goto Fail;
+ }
+ }
+
+ font_checksum += checksum;
+
+ buf_cursor = &table_entry[0];
+ WRITE_ULONG( buf_cursor, table.Tag );
+ WRITE_ULONG( buf_cursor, checksum );
+ WRITE_ULONG( buf_cursor, table.dst_offset );
+ WRITE_ULONG( buf_cursor, table.dst_length );
+
+ WRITE_SFNT_BUF_AT( table_entry_offset, table_entry, 16 );
+
+ /* Update checksum. */
+ font_checksum += compute_ULong_sum( table_entry, 16 );
+
+ if ( pad4( &sfnt, sfnt_size, &dest_offset, memory ) )
+ goto Fail;
+
+ /* Sanity check. */
+ if ( (FT_ULong)( table.dst_offset + table.dst_length ) > dest_offset )
+ {
+ FT_ERROR(( "Table was partially written.\n" ));
+ goto Fail;
+ }
+ }
+
+ /* Update `head' checkSumAdjustment. */
+ info->head_table = find_table( indices, num_tables, TTAG_head );
+ if ( !info->head_table )
+ {
+ FT_ERROR(( "`head' table is missing.\n" ));
+ goto Fail;
+ }
+
+ if ( info->head_table->dst_length < 12 )
+ goto Fail;
+
+ buf_cursor = sfnt + info->head_table->dst_offset + 8;
+ font_checksum = 0xB1B0AFBA - font_checksum;
+
+ WRITE_ULONG( buf_cursor, font_checksum );
+
+ FT_TRACE2(( "Final checksum = %09x.\n", font_checksum ));
+
+ woff2->actual_sfnt_size = dest_offset;
+
+ /* Set pointer of sfnt stream to its correct value. */
+ *sfnt_bytes = sfnt;
+
+ FT_FREE( table_entry );
+ FT_Stream_Close( stream );
+ FT_FREE( stream );
+
+ return error;
+
+ Fail:
+ if ( !error )
+ error = FT_THROW( Invalid_Table );
+
+ /* Set pointer of sfnt stream to its correct value. */
+ *sfnt_bytes = sfnt;
+
+ FT_FREE( table_entry );
+ FT_Stream_Close( stream );
+ FT_FREE( stream );
+
+ return error;
+ }
+
+
+ /* Replace `face->root.stream' with a stream containing the extracted */
+ /* SFNT of a WOFF2 font. */
+
+ FT_LOCAL_DEF( FT_Error )
+ woff2_open_font( FT_Stream stream,
+ TT_Face face,
+ FT_Int* face_instance_index,
+ FT_Long* num_faces )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Error error = FT_Err_Ok;
+ FT_Int face_index;
+
+ WOFF2_HeaderRec woff2;
+ WOFF2_InfoRec info = { 0, 0, 0, NULL, NULL, NULL, NULL };
+ WOFF2_Table tables = NULL;
+ WOFF2_Table* indices = NULL;
+ WOFF2_Table* temp_indices = NULL;
+ WOFF2_Table last_table;
+
+ FT_Int nn;
+ FT_ULong j;
+ FT_ULong flags;
+ FT_UShort xform_version;
+ FT_ULong src_offset = 0;
+
+ FT_UInt glyf_index;
+ FT_UInt loca_index;
+ FT_UInt32 file_offset;
+
+ FT_Byte* sfnt = NULL;
+ FT_Stream sfnt_stream = NULL;
+ FT_Byte* sfnt_header;
+ FT_ULong sfnt_size;
+
+ FT_Byte* uncompressed_buf = NULL;
+
+ static const FT_Frame_Field woff2_header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE WOFF2_HeaderRec
+
+ FT_FRAME_START( 48 ),
+ FT_FRAME_ULONG ( signature ),
+ FT_FRAME_ULONG ( flavor ),
+ FT_FRAME_ULONG ( length ),
+ FT_FRAME_USHORT ( num_tables ),
+ FT_FRAME_SKIP_BYTES( 2 ),
+ FT_FRAME_ULONG ( totalSfntSize ),
+ FT_FRAME_ULONG ( totalCompressedSize ),
+ FT_FRAME_SKIP_BYTES( 2 * 2 ),
+ FT_FRAME_ULONG ( metaOffset ),
+ FT_FRAME_ULONG ( metaLength ),
+ FT_FRAME_ULONG ( metaOrigLength ),
+ FT_FRAME_ULONG ( privOffset ),
+ FT_FRAME_ULONG ( privLength ),
+ FT_FRAME_END
+ };
+
+
+ FT_ASSERT( stream == face->root.stream );
+ FT_ASSERT( FT_STREAM_POS() == 0 );
+
+ face_index = FT_ABS( *face_instance_index ) & 0xFFFF;
+
+ /* Read WOFF2 Header. */
+ if ( FT_STREAM_READ_FIELDS( woff2_header_fields, &woff2 ) )
+ return error;
+
+ FT_TRACE4(( "signature -> 0x%X\n", woff2.signature ));
+ FT_TRACE2(( "flavor -> 0x%08lx\n", woff2.flavor ));
+ FT_TRACE4(( "length -> %lu\n", woff2.length ));
+ FT_TRACE2(( "num_tables -> %hu\n", woff2.num_tables ));
+ FT_TRACE4(( "totalSfntSize -> %lu\n", woff2.totalSfntSize ));
+ FT_TRACE4(( "metaOffset -> %hu\n", woff2.metaOffset ));
+ FT_TRACE4(( "metaLength -> %hu\n", woff2.metaLength ));
+ FT_TRACE4(( "privOffset -> %hu\n", woff2.privOffset ));
+ FT_TRACE4(( "privLength -> %hu\n", woff2.privLength ));
+
+ /* Make sure we don't recurse back here. */
+ if ( woff2.flavor == TTAG_wOF2 )
+ return FT_THROW( Invalid_Table );
+
+ /* Miscellaneous checks. */
+ if ( woff2.length != stream->size ||
+ woff2.num_tables == 0 ||
+ 48 + woff2.num_tables * 20UL >= woff2.length ||
+ ( woff2.metaOffset == 0 && ( woff2.metaLength != 0 ||
+ woff2.metaOrigLength != 0 ) ) ||
+ ( woff2.metaLength != 0 && woff2.metaOrigLength == 0 ) ||
+ ( woff2.metaOffset >= woff2.length ) ||
+ ( woff2.length - woff2.metaOffset < woff2.metaLength ) ||
+ ( woff2.privOffset == 0 && woff2.privLength != 0 ) ||
+ ( woff2.privOffset >= woff2.length ) ||
+ ( woff2.length - woff2.privOffset < woff2.privLength ) )
+ {
+ FT_ERROR(( "woff2_open_font: invalid WOFF2 header\n" ));
+ return FT_THROW( Invalid_Table );
+ }
+
+ FT_TRACE2(( "woff2_open_font: WOFF2 Header is valid.\n" ));
+
+ woff2.ttc_fonts = NULL;
+
+ /* Read table directory. */
+ if ( FT_NEW_ARRAY( tables, woff2.num_tables ) ||
+ FT_NEW_ARRAY( indices, woff2.num_tables ) )
+ goto Exit;
+
+ FT_TRACE2(( "\n"
+ " tag flags transform origLen transformLen\n"
+ " --------------------------------------------------\n" ));
+
+ for ( nn = 0; nn < woff2.num_tables; nn++ )
+ {
+ WOFF2_Table table = tables + nn;
+
+
+ if ( FT_READ_BYTE( table->FlagByte ) )
+ goto Exit;
+
+ if ( ( table->FlagByte & 0x3f ) == 0x3f )
+ {
+ if ( FT_READ_ULONG( table->Tag ) )
+ goto Exit;
+ }
+ else
+ {
+ table->Tag = woff2_known_tags( table->FlagByte & 0x3f );
+ if ( !table->Tag )
+ {
+ FT_ERROR(( "woff2_open_font: Unknown table tag." ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+ }
+
+ flags = 0;
+ xform_version = ( table->FlagByte >> 6 ) & 0x03;
+
+ /* 0 means xform for glyph/loca, non-0 for others. */
+ if ( table->Tag == TTAG_glyf || table->Tag == TTAG_loca )
+ {
+ if ( xform_version == 0 )
+ flags |= WOFF2_FLAGS_TRANSFORM;
+ }
+ else if ( xform_version != 0 )
+ flags |= WOFF2_FLAGS_TRANSFORM;
+
+ flags |= xform_version;
+
+ if ( READ_BASE128( table->dst_length ) )
+ goto Exit;
+
+ table->TransformLength = table->dst_length;
+
+ if ( ( flags & WOFF2_FLAGS_TRANSFORM ) != 0 )
+ {
+ if ( READ_BASE128( table->TransformLength ) )
+ goto Exit;
+
+ if ( table->Tag == TTAG_loca && table->TransformLength )
+ {
+ FT_ERROR(( "woff2_open_font: Invalid loca `transformLength'.\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+ }
+
+ if ( src_offset + table->TransformLength < src_offset )
+ {
+ FT_ERROR(( "woff2_open_font: invalid WOFF2 table directory.\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ table->src_offset = src_offset;
+ table->src_length = table->TransformLength;
+ src_offset += table->TransformLength;
+ table->flags = flags;
+
+ FT_TRACE2(( " %c%c%c%c %08d %08d %08ld %08ld\n",
+ (FT_Char)( table->Tag >> 24 ),
+ (FT_Char)( table->Tag >> 16 ),
+ (FT_Char)( table->Tag >> 8 ),
+ (FT_Char)( table->Tag ),
+ table->FlagByte & 0x3f,
+ ( table->FlagByte >> 6 ) & 0x03,
+ table->dst_length,
+ table->TransformLength,
+ table->src_length,
+ table->src_offset ));
+
+ indices[nn] = table;
+ }
+
+ /* End of last table is uncompressed size. */
+ last_table = indices[woff2.num_tables - 1];
+
+ woff2.uncompressed_size = last_table->src_offset +
+ last_table->src_length;
+ if ( woff2.uncompressed_size < last_table->src_offset )
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ FT_TRACE2(( "Table directory parsed.\n" ));
+
+ /* Check for and read collection directory. */
+ woff2.num_fonts = 1;
+ woff2.header_version = 0;
+
+ if ( woff2.flavor == TTAG_ttcf )
+ {
+ FT_TRACE2(( "Font is a TTC, reading collection directory.\n" ));
+
+ if ( FT_READ_ULONG( woff2.header_version ) )
+ goto Exit;
+
+ if ( woff2.header_version != 0x00010000 &&
+ woff2.header_version != 0x00020000 )
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ if ( READ_255USHORT( woff2.num_fonts ) )
+ goto Exit;
+
+ if ( !woff2.num_fonts )
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ FT_TRACE4(( "Number of fonts in TTC: %ld\n", woff2.num_fonts ));
+
+ if ( FT_NEW_ARRAY( woff2.ttc_fonts, woff2.num_fonts ) )
+ goto Exit;
+
+ for ( nn = 0; nn < woff2.num_fonts; nn++ )
+ {
+ WOFF2_TtcFont ttc_font = woff2.ttc_fonts + nn;
+
+
+ if ( READ_255USHORT( ttc_font->num_tables ) )
+ goto Exit;
+ if ( FT_READ_ULONG( ttc_font->flavor ) )
+ goto Exit;
+
+ if ( FT_NEW_ARRAY( ttc_font->table_indices, ttc_font->num_tables ) )
+ goto Exit;
+
+ FT_TRACE5(( "Number of tables in font %d: %ld\n",
+ nn, ttc_font->num_tables ));
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( ttc_font->num_tables )
+ FT_TRACE6(( " Indices: " ));
+#endif
+
+ glyf_index = 0;
+ loca_index = 0;
+
+ for ( j = 0; j < ttc_font->num_tables; j++ )
+ {
+ FT_UShort table_index;
+ WOFF2_Table table;
+
+
+ if ( READ_255USHORT( table_index ) )
+ goto Exit;
+
+ FT_TRACE6(( "%hu ", table_index ));
+ if ( table_index >= woff2.num_tables )
+ {
+ FT_ERROR(( "woff2_open_font: invalid table index\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ ttc_font->table_indices[j] = table_index;
+
+ table = indices[table_index];
+ if ( table->Tag == TTAG_loca )
+ loca_index = table_index;
+ if ( table->Tag == TTAG_glyf )
+ glyf_index = table_index;
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( ttc_font->num_tables )
+ FT_TRACE6(( "\n" ));
+#endif
+
+ /* glyf and loca must be consecutive */
+ if ( glyf_index > 0 || loca_index > 0 )
+ {
+ if ( glyf_index > loca_index ||
+ loca_index - glyf_index != 1 )
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+ }
+ }
+
+ /* Collection directory reading complete. */
+ FT_TRACE2(( "WOFF2 collection directory is valid.\n" ));
+ }
+ else
+ woff2.ttc_fonts = NULL;
+
+ woff2.compressed_offset = FT_STREAM_POS();
+ file_offset = ROUND4( woff2.compressed_offset +
+ woff2.totalCompressedSize );
+
+ /* Some more checks before we start reading the tables. */
+ if ( file_offset > woff2.length )
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ if ( woff2.metaOffset )
+ {
+ if ( file_offset != woff2.metaOffset )
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+ file_offset = ROUND4(woff2.metaOffset + woff2.metaLength);
+ }
+
+ if ( woff2.privOffset )
+ {
+ if ( file_offset != woff2.privOffset )
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+ file_offset = ROUND4(woff2.privOffset + woff2.privLength);
+ }
+
+ if ( file_offset != ( ROUND4( woff2.length ) ) )
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ /* Validate requested face index. */
+ *num_faces = woff2.num_fonts;
+ /* value -(N+1) requests information on index N */
+ if ( *face_instance_index < 0 )
+ face_index--;
+
+ if ( face_index >= woff2.num_fonts )
+ {
+ if ( *face_instance_index >= 0 )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+ else
+ face_index = 0;
+ }
+
+ /* Only retain tables of the requested face in a TTC. */
+ if ( woff2.header_version )
+ {
+ WOFF2_TtcFont ttc_font = woff2.ttc_fonts + face_index;
+
+
+ /* Create a temporary array. */
+ if ( FT_NEW_ARRAY( temp_indices,
+ ttc_font->num_tables ) )
+ goto Exit;
+
+ FT_TRACE4(( "Storing tables for TTC face index %d.\n", face_index ));
+ for ( nn = 0; nn < ttc_font->num_tables; nn++ )
+ temp_indices[nn] = indices[ttc_font->table_indices[nn]];
+
+ /* Resize array to required size. */
+ if ( FT_RENEW_ARRAY( indices,
+ woff2.num_tables,
+ ttc_font->num_tables ) )
+ goto Exit;
+
+ for ( nn = 0; nn < ttc_font->num_tables; nn++ )
+ indices[nn] = temp_indices[nn];
+
+ FT_FREE( temp_indices );
+
+ /* Change header values. */
+ woff2.flavor = ttc_font->flavor;
+ woff2.num_tables = ttc_font->num_tables;
+ }
+
+ /* We need to allocate this much at the minimum. */
+ sfnt_size = 12 + woff2.num_tables * 16UL;
+ /* This is what we normally expect. */
+ /* Initially trust `totalSfntSize' and change later as required. */
+ if ( woff2.totalSfntSize > sfnt_size )
+ {
+ /* However, adjust the value to something reasonable. */
+
+ /* Factor 64 is heuristic. */
+ if ( ( woff2.totalSfntSize >> 6 ) > woff2.length )
+ sfnt_size = woff2.length << 6;
+ else
+ sfnt_size = woff2.totalSfntSize;
+
+ /* Value 1<<26 = 67108864 is heuristic. */
+ if (sfnt_size >= (1 << 26))
+ sfnt_size = 1 << 26;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( sfnt_size != woff2.totalSfntSize )
+ FT_TRACE4(( "adjusting estimate of uncompressed font size"
+ " to %lu bytes\n",
+ sfnt_size ));
+#endif
+ }
+
+ /* Write sfnt header. */
+ if ( FT_ALLOC( sfnt, sfnt_size ) ||
+ FT_NEW( sfnt_stream ) )
+ goto Exit;
+
+ sfnt_header = sfnt;
+
+ WRITE_ULONG( sfnt_header, woff2.flavor );
+
+ if ( woff2.num_tables )
+ {
+ FT_UInt searchRange, entrySelector, rangeShift, x;
+
+
+ x = woff2.num_tables;
+ entrySelector = 0;
+ while ( x )
+ {
+ x >>= 1;
+ entrySelector += 1;
+ }
+ entrySelector--;
+
+ searchRange = ( 1 << entrySelector ) * 16;
+ rangeShift = ( woff2.num_tables * 16 ) - searchRange;
+
+ WRITE_USHORT( sfnt_header, woff2.num_tables );
+ WRITE_USHORT( sfnt_header, searchRange );
+ WRITE_USHORT( sfnt_header, entrySelector );
+ WRITE_USHORT( sfnt_header, rangeShift );
+ }
+
+ info.header_checksum = compute_ULong_sum( sfnt, 12 );
+
+ /* Sort tables by tag. */
+ ft_qsort( indices,
+ woff2.num_tables,
+ sizeof ( WOFF2_Table ),
+ compare_tags );
+
+ if ( woff2.uncompressed_size < 1 )
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ if ( woff2.uncompressed_size > sfnt_size )
+ {
+ FT_ERROR(( "woff2_open_font: SFNT table lengths are too large.\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ /* Allocate memory for uncompressed table data. */
+ if ( FT_ALLOC( uncompressed_buf, woff2.uncompressed_size ) ||
+ FT_FRAME_ENTER( woff2.totalCompressedSize ) )
+ goto Exit;
+
+ /* Uncompress the stream. */
+ error = woff2_decompress( uncompressed_buf,
+ woff2.uncompressed_size,
+ stream->cursor,
+ woff2.totalCompressedSize );
+
+ FT_FRAME_EXIT();
+
+ if ( error )
+ goto Exit;
+
+ error = reconstruct_font( uncompressed_buf,
+ woff2.uncompressed_size,
+ indices,
+ &woff2,
+ &info,
+ &sfnt,
+ &sfnt_size,
+ memory );
+
+ if ( error )
+ goto Exit;
+
+ /* Resize `sfnt' to actual size of sfnt stream. */
+ if ( woff2.actual_sfnt_size < sfnt_size )
+ {
+ FT_TRACE5(( "Trimming sfnt stream from %lu to %lu.\n",
+ sfnt_size, woff2.actual_sfnt_size ));
+ if ( FT_REALLOC( sfnt,
+ (FT_ULong)( sfnt_size ),
+ (FT_ULong)( woff2.actual_sfnt_size ) ) )
+ goto Exit;
+ }
+
+ /* `reconstruct_font' has done all the work. */
+ /* Swap out stream and return. */
+ FT_Stream_OpenMemory( sfnt_stream, sfnt, woff2.actual_sfnt_size );
+ sfnt_stream->memory = stream->memory;
+ sfnt_stream->close = stream_close;
+
+ FT_Stream_Free(
+ face->root.stream,
+ ( face->root.face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
+
+ face->root.stream = sfnt_stream;
+ face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
+
+ /* Set face_index to 0 or -1. */
+ if ( *face_instance_index >= 0 )
+ *face_instance_index = 0;
+ else
+ *face_instance_index = -1;
+
+ FT_TRACE2(( "woff2_open_font: SFNT synthesized.\n" ));
+
+ Exit:
+ FT_FREE( tables );
+ FT_FREE( indices );
+ FT_FREE( uncompressed_buf );
+ FT_FREE( info.x_mins );
+
+ if ( woff2.ttc_fonts )
+ {
+ WOFF2_TtcFont ttc_font = woff2.ttc_fonts;
+
+
+ for ( nn = 0; nn < woff2.num_fonts; nn++ )
+ {
+ FT_FREE( ttc_font->table_indices );
+ ttc_font++;
+ }
+
+ FT_FREE( woff2.ttc_fonts );
+ }
+
+ if ( error )
+ {
+ FT_FREE( sfnt );
+ if ( sfnt_stream )
+ {
+ FT_Stream_Close( sfnt_stream );
+ FT_FREE( sfnt_stream );
+ }
+ }
+
+ return error;
+ }
+
+
+#undef READ_255USHORT
+#undef READ_BASE128
+#undef ROUND4
+#undef WRITE_USHORT
+#undef WRITE_ULONG
+#undef WRITE_SHORT
+#undef WRITE_SFNT_BUF
+#undef WRITE_SFNT_BUF_AT
+
+#undef N_CONTOUR_STREAM
+#undef N_POINTS_STREAM
+#undef FLAG_STREAM
+#undef GLYPH_STREAM
+#undef COMPOSITE_STREAM
+#undef BBOX_STREAM
+#undef INSTRUCTION_STREAM
+
+
+/* END */
diff --git a/thirdparty/freetype/src/sfnt/sfwoff2.h b/thirdparty/freetype/src/sfnt/sfwoff2.h
new file mode 100644
index 0000000000..7ae6e2c06d
--- /dev/null
+++ b/thirdparty/freetype/src/sfnt/sfwoff2.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+ *
+ * sfwoff2.h
+ *
+ * WOFFF2 format management (specification).
+ *
+ * Copyright (C) 2019-2020 by
+ * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef SFWOFF2_H_
+#define SFWOFF2_H_
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+ /* Leave the first byte open to store `flag_byte'. */
+#define WOFF2_FLAGS_TRANSFORM 1 << 8
+
+#define WOFF2_SFNT_HEADER_SIZE 12
+#define WOFF2_SFNT_ENTRY_SIZE 16
+
+ /* Suggested maximum size for output. */
+#define WOFF2_DEFAULT_MAX_SIZE 30 * 1024 * 1024
+
+ /* 98% of Google Fonts have no glyph above 5k bytes. */
+#define WOFF2_DEFAULT_GLYPH_BUF 5120
+
+ /* Composite glyph flags. */
+ /* See `CompositeGlyph.java' in `sfntly' for full definitions. */
+#define FLAG_ARG_1_AND_2_ARE_WORDS 1 << 0
+#define FLAG_WE_HAVE_A_SCALE 1 << 3
+#define FLAG_MORE_COMPONENTS 1 << 5
+#define FLAG_WE_HAVE_AN_X_AND_Y_SCALE 1 << 6
+#define FLAG_WE_HAVE_A_TWO_BY_TWO 1 << 7
+#define FLAG_WE_HAVE_INSTRUCTIONS 1 << 8
+
+ /* Simple glyph flags */
+#define GLYF_ON_CURVE 1 << 0
+#define GLYF_X_SHORT 1 << 1
+#define GLYF_Y_SHORT 1 << 2
+#define GLYF_REPEAT 1 << 3
+#define GLYF_THIS_X_IS_SAME 1 << 4
+#define GLYF_THIS_Y_IS_SAME 1 << 5
+
+ /* Other constants */
+#define CONTOUR_OFFSET_END_POINT 10
+
+
+ FT_LOCAL( FT_Error )
+ woff2_open_font( FT_Stream stream,
+ TT_Face face,
+ FT_Int* face_index,
+ FT_Long* num_faces );
+
+
+FT_END_HEADER
+
+#endif /* SFWOFF2_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/sfnt/ttbdf.c b/thirdparty/freetype/src/sfnt/ttbdf.c
index 853599fc43..bc35284cc8 100644
--- a/thirdparty/freetype/src/sfnt/ttbdf.c
+++ b/thirdparty/freetype/src/sfnt/ttbdf.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType embedded BDF properties (body).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttbdf.h b/thirdparty/freetype/src/sfnt/ttbdf.h
index e4164e61fc..c340f6631d 100644
--- a/thirdparty/freetype/src/sfnt/ttbdf.h
+++ b/thirdparty/freetype/src/sfnt/ttbdf.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType embedded BDF properties (specification).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttcmap.c b/thirdparty/freetype/src/sfnt/ttcmap.c
index 683f3b1818..2c34efb5ce 100644
--- a/thirdparty/freetype/src/sfnt/ttcmap.c
+++ b/thirdparty/freetype/src/sfnt/ttcmap.c
@@ -4,7 +4,7 @@
*
* TrueType character mapping table (cmap) support (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -3764,28 +3764,31 @@
FT_LOCAL_DEF( FT_Error )
tt_face_build_cmaps( TT_Face face )
{
- FT_Byte* table = face->cmap_table;
- FT_Byte* limit = table + face->cmap_size;
+ FT_Byte* const table = face->cmap_table;
+ FT_Byte* limit;
FT_UInt volatile num_cmaps;
- FT_Byte* volatile p = table;
+ FT_Byte* volatile p = table;
FT_Library library = FT_FACE_LIBRARY( face );
FT_UNUSED( library );
- if ( !p || p + 4 > limit )
+ if ( !p || face->cmap_size < 4 )
return FT_THROW( Invalid_Table );
- /* only recognize format 0 */
- if ( TT_NEXT_USHORT( p ) != 0 )
- {
- FT_ERROR(( "tt_face_build_cmaps:"
- " unsupported `cmap' table format = %d\n",
- TT_PEEK_USHORT( p - 2 ) ));
- return FT_THROW( Invalid_Table );
- }
+ /* Version 1.8.3 of the OpenType specification contains the following */
+ /* (https://docs.microsoft.com/en-us/typography/opentype/spec/cmap): */
+ /* */
+ /* The 'cmap' table version number remains at 0x0000 for fonts that */
+ /* make use of the newer subtable formats. */
+ /* */
+ /* This essentially means that a version format test is useless. */
+
+ /* ignore format */
+ p += 2;
num_cmaps = TT_NEXT_USHORT( p );
+ limit = table + face->cmap_size;
for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
{
diff --git a/thirdparty/freetype/src/sfnt/ttcmap.h b/thirdparty/freetype/src/sfnt/ttcmap.h
index 36801c939e..4bf49e2d49 100644
--- a/thirdparty/freetype/src/sfnt/ttcmap.h
+++ b/thirdparty/freetype/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
*
* TrueType character mapping table (cmap) support (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttcmapc.h b/thirdparty/freetype/src/sfnt/ttcmapc.h
index ace9e69ca8..2e4ce5075b 100644
--- a/thirdparty/freetype/src/sfnt/ttcmapc.h
+++ b/thirdparty/freetype/src/sfnt/ttcmapc.h
@@ -4,7 +4,7 @@
*
* TT CMAP classes definitions (specification only).
*
- * Copyright (C) 2009-2019 by
+ * Copyright (C) 2009-2020 by
* Oran Agra and Mickey Gabel.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttcolr.c b/thirdparty/freetype/src/sfnt/ttcolr.c
index 6b537d95b8..b37fa7b09a 100644
--- a/thirdparty/freetype/src/sfnt/ttcolr.c
+++ b/thirdparty/freetype/src/sfnt/ttcolr.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType colored glyph layer support (body).
*
- * Copyright (C) 2018-2019 by
+ * Copyright (C) 2018-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff --git a/thirdparty/freetype/src/sfnt/ttcolr.h b/thirdparty/freetype/src/sfnt/ttcolr.h
index 817489a855..8da6b3aa14 100644
--- a/thirdparty/freetype/src/sfnt/ttcolr.h
+++ b/thirdparty/freetype/src/sfnt/ttcolr.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType colored glyph layer support (specification).
*
- * Copyright (C) 2018-2019 by
+ * Copyright (C) 2018-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff --git a/thirdparty/freetype/src/sfnt/ttcpal.c b/thirdparty/freetype/src/sfnt/ttcpal.c
index 3482169a89..165423e305 100644
--- a/thirdparty/freetype/src/sfnt/ttcpal.c
+++ b/thirdparty/freetype/src/sfnt/ttcpal.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType color palette support (body).
*
- * Copyright (C) 2018-2019 by
+ * Copyright (C) 2018-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff --git a/thirdparty/freetype/src/sfnt/ttcpal.h b/thirdparty/freetype/src/sfnt/ttcpal.h
index d1b244f3e3..f2e116ba2c 100644
--- a/thirdparty/freetype/src/sfnt/ttcpal.h
+++ b/thirdparty/freetype/src/sfnt/ttcpal.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType color palette support (specification).
*
- * Copyright (C) 2018-2019 by
+ * Copyright (C) 2018-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff --git a/thirdparty/freetype/src/sfnt/ttkern.c b/thirdparty/freetype/src/sfnt/ttkern.c
index 8d1b781090..1d34acbd13 100644
--- a/thirdparty/freetype/src/sfnt/ttkern.c
+++ b/thirdparty/freetype/src/sfnt/ttkern.c
@@ -5,7 +5,7 @@
* Load the basic TrueType kerning table. This doesn't handle
* kerning data within the GPOS table at the moment.
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttkern.h b/thirdparty/freetype/src/sfnt/ttkern.h
index 5f283e5e62..6560a283a6 100644
--- a/thirdparty/freetype/src/sfnt/ttkern.h
+++ b/thirdparty/freetype/src/sfnt/ttkern.h
@@ -5,7 +5,7 @@
* Load the basic TrueType kerning table. This doesn't handle
* kerning data within the GPOS table at the moment.
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttload.c b/thirdparty/freetype/src/sfnt/ttload.c
index 5443bf4b69..d4e4ee4f10 100644
--- a/thirdparty/freetype/src/sfnt/ttload.c
+++ b/thirdparty/freetype/src/sfnt/ttload.c
@@ -5,7 +5,7 @@
* Load the basic TrueType tables, i.e., tables that can be either in
* TTF or OTF fonts (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -397,7 +397,15 @@
}
}
else
+ {
valid_entries = sfnt.num_tables;
+ if ( !valid_entries )
+ {
+ FT_TRACE2(( "tt_face_load_font_dir: no valid tables found\n" ));
+ error = FT_THROW( Unknown_File_Format );
+ goto Exit;
+ }
+ }
face->num_tables = valid_entries;
face->format_tag = sfnt.format_tag;
@@ -916,7 +924,7 @@
/* load language tags */
{
TT_LangTag entry = table->langTags;
- TT_LangTag limit = entry + table->numLangTagRecords;
+ TT_LangTag limit = FT_OFFSET( entry, table->numLangTagRecords );
for ( ; entry < limit; entry++ )
diff --git a/thirdparty/freetype/src/sfnt/ttload.h b/thirdparty/freetype/src/sfnt/ttload.h
index cc18c18694..49d40655f8 100644
--- a/thirdparty/freetype/src/sfnt/ttload.h
+++ b/thirdparty/freetype/src/sfnt/ttload.h
@@ -5,7 +5,7 @@
* Load the basic TrueType tables, i.e., tables that can be either in
* TTF or OTF fonts (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttmtx.c b/thirdparty/freetype/src/sfnt/ttmtx.c
index b6725c962f..e18ff877ef 100644
--- a/thirdparty/freetype/src/sfnt/ttmtx.c
+++ b/thirdparty/freetype/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
*
* Load the metrics tables common to TTF and OTF fonts (body).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttmtx.h b/thirdparty/freetype/src/sfnt/ttmtx.h
index 5b0b60b641..c98c79ec51 100644
--- a/thirdparty/freetype/src/sfnt/ttmtx.h
+++ b/thirdparty/freetype/src/sfnt/ttmtx.h
@@ -4,7 +4,7 @@
*
* Load the metrics tables common to TTF and OTF fonts (specification).
*
- * Copyright (C) 2006-2019 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttpost.c b/thirdparty/freetype/src/sfnt/ttpost.c
index 636a0a004a..f7be716219 100644
--- a/thirdparty/freetype/src/sfnt/ttpost.c
+++ b/thirdparty/freetype/src/sfnt/ttpost.c
@@ -5,7 +5,7 @@
* PostScript name table processing for TrueType and OpenType fonts
* (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttpost.h b/thirdparty/freetype/src/sfnt/ttpost.h
index 812a0fc92d..547f2ff843 100644
--- a/thirdparty/freetype/src/sfnt/ttpost.h
+++ b/thirdparty/freetype/src/sfnt/ttpost.h
@@ -5,7 +5,7 @@
* PostScript name table processing for TrueType and OpenType fonts
* (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttsbit.c b/thirdparty/freetype/src/sfnt/ttsbit.c
index 23bd9d7eb0..3f8730f7fb 100644
--- a/thirdparty/freetype/src/sfnt/ttsbit.c
+++ b/thirdparty/freetype/src/sfnt/ttsbit.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType embedded bitmap support (body).
*
- * Copyright (C) 2005-2019 by
+ * Copyright (C) 2005-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Copyright 2013 by Google, Inc.
diff --git a/thirdparty/freetype/src/sfnt/ttsbit.h b/thirdparty/freetype/src/sfnt/ttsbit.h
index 5ab8ff5568..dfeb886838 100644
--- a/thirdparty/freetype/src/sfnt/ttsbit.h
+++ b/thirdparty/freetype/src/sfnt/ttsbit.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType embedded bitmap support (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/woff2tags.c b/thirdparty/freetype/src/sfnt/woff2tags.c
new file mode 100644
index 0000000000..246f7fa062
--- /dev/null
+++ b/thirdparty/freetype/src/sfnt/woff2tags.c
@@ -0,0 +1,110 @@
+/****************************************************************************
+ *
+ * woff2tags.c
+ *
+ * WOFF2 Font table tags (base).
+ *
+ * Copyright (C) 2019-2020 by
+ * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include <ft2build.h>
+#include FT_TRUETYPE_TAGS_H
+
+
+ /*
+ * Return tag from index in the order given in WOFF2 specification.
+ *
+ * See
+ *
+ * https://www.w3.org/TR/WOFF2/#table_dir_format
+ *
+ * for details.
+ */
+ FT_LOCAL_DEF( FT_ULong )
+ woff2_known_tags( FT_Byte index )
+ {
+ const FT_ULong known_tags[63] =
+ {
+ FT_MAKE_TAG('c', 'm', 'a', 'p'), /* 0 */
+ FT_MAKE_TAG('h', 'e', 'a', 'd'), /* 1 */
+ FT_MAKE_TAG('h', 'h', 'e', 'a'), /* 2 */
+ FT_MAKE_TAG('h', 'm', 't', 'x'), /* 3 */
+ FT_MAKE_TAG('m', 'a', 'x', 'p'), /* 4 */
+ FT_MAKE_TAG('n', 'a', 'm', 'e'), /* 5 */
+ FT_MAKE_TAG('O', 'S', '/', '2'), /* 6 */
+ FT_MAKE_TAG('p', 'o', 's', 't'), /* 7 */
+ FT_MAKE_TAG('c', 'v', 't', ' '), /* 8 */
+ FT_MAKE_TAG('f', 'p', 'g', 'm'), /* 9 */
+ FT_MAKE_TAG('g', 'l', 'y', 'f'), /* 10 */
+ FT_MAKE_TAG('l', 'o', 'c', 'a'), /* 11 */
+ FT_MAKE_TAG('p', 'r', 'e', 'p'), /* 12 */
+ FT_MAKE_TAG('C', 'F', 'F', ' '), /* 13 */
+ FT_MAKE_TAG('V', 'O', 'R', 'G'), /* 14 */
+ FT_MAKE_TAG('E', 'B', 'D', 'T'), /* 15 */
+ FT_MAKE_TAG('E', 'B', 'L', 'C'), /* 16 */
+ FT_MAKE_TAG('g', 'a', 's', 'p'), /* 17 */
+ FT_MAKE_TAG('h', 'd', 'm', 'x'), /* 18 */
+ FT_MAKE_TAG('k', 'e', 'r', 'n'), /* 19 */
+ FT_MAKE_TAG('L', 'T', 'S', 'H'), /* 20 */
+ FT_MAKE_TAG('P', 'C', 'L', 'T'), /* 21 */
+ FT_MAKE_TAG('V', 'D', 'M', 'X'), /* 22 */
+ FT_MAKE_TAG('v', 'h', 'e', 'a'), /* 23 */
+ FT_MAKE_TAG('v', 'm', 't', 'x'), /* 24 */
+ FT_MAKE_TAG('B', 'A', 'S', 'E'), /* 25 */
+ FT_MAKE_TAG('G', 'D', 'E', 'F'), /* 26 */
+ FT_MAKE_TAG('G', 'P', 'O', 'S'), /* 27 */
+ FT_MAKE_TAG('G', 'S', 'U', 'B'), /* 28 */
+ FT_MAKE_TAG('E', 'B', 'S', 'C'), /* 29 */
+ FT_MAKE_TAG('J', 'S', 'T', 'F'), /* 30 */
+ FT_MAKE_TAG('M', 'A', 'T', 'H'), /* 31 */
+ FT_MAKE_TAG('C', 'B', 'D', 'T'), /* 32 */
+ FT_MAKE_TAG('C', 'B', 'L', 'C'), /* 33 */
+ FT_MAKE_TAG('C', 'O', 'L', 'R'), /* 34 */
+ FT_MAKE_TAG('C', 'P', 'A', 'L'), /* 35 */
+ FT_MAKE_TAG('S', 'V', 'G', ' '), /* 36 */
+ FT_MAKE_TAG('s', 'b', 'i', 'x'), /* 37 */
+ FT_MAKE_TAG('a', 'c', 'n', 't'), /* 38 */
+ FT_MAKE_TAG('a', 'v', 'a', 'r'), /* 39 */
+ FT_MAKE_TAG('b', 'd', 'a', 't'), /* 40 */
+ FT_MAKE_TAG('b', 'l', 'o', 'c'), /* 41 */
+ FT_MAKE_TAG('b', 's', 'l', 'n'), /* 42 */
+ FT_MAKE_TAG('c', 'v', 'a', 'r'), /* 43 */
+ FT_MAKE_TAG('f', 'd', 's', 'c'), /* 44 */
+ FT_MAKE_TAG('f', 'e', 'a', 't'), /* 45 */
+ FT_MAKE_TAG('f', 'm', 't', 'x'), /* 46 */
+ FT_MAKE_TAG('f', 'v', 'a', 'r'), /* 47 */
+ FT_MAKE_TAG('g', 'v', 'a', 'r'), /* 48 */
+ FT_MAKE_TAG('h', 's', 't', 'y'), /* 49 */
+ FT_MAKE_TAG('j', 'u', 's', 't'), /* 50 */
+ FT_MAKE_TAG('l', 'c', 'a', 'r'), /* 51 */
+ FT_MAKE_TAG('m', 'o', 'r', 't'), /* 52 */
+ FT_MAKE_TAG('m', 'o', 'r', 'x'), /* 53 */
+ FT_MAKE_TAG('o', 'p', 'b', 'd'), /* 54 */
+ FT_MAKE_TAG('p', 'r', 'o', 'p'), /* 55 */
+ FT_MAKE_TAG('t', 'r', 'a', 'k'), /* 56 */
+ FT_MAKE_TAG('Z', 'a', 'p', 'f'), /* 57 */
+ FT_MAKE_TAG('S', 'i', 'l', 'f'), /* 58 */
+ FT_MAKE_TAG('G', 'l', 'a', 't'), /* 59 */
+ FT_MAKE_TAG('G', 'l', 'o', 'c'), /* 60 */
+ FT_MAKE_TAG('F', 'e', 'a', 't'), /* 61 */
+ FT_MAKE_TAG('S', 'i', 'l', 'l'), /* 62 */
+ };
+
+
+ if ( index > 62 )
+ return 0;
+
+ return known_tags[index];
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/sfnt/woff2tags.h b/thirdparty/freetype/src/sfnt/woff2tags.h
new file mode 100644
index 0000000000..13d242e11d
--- /dev/null
+++ b/thirdparty/freetype/src/sfnt/woff2tags.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+ *
+ * woff2tags.h
+ *
+ * WOFFF2 Font table tags (specification).
+ *
+ * Copyright (C) 1996-2020 by
+ * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef WOFF2TAGS_H
+#define WOFF2TAGS_H
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_ULong )
+ woff2_known_tags( FT_Byte index );
+
+
+FT_END_HEADER
+
+#endif /* WOFF2TAGS_H */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/smooth/ftgrays.c b/thirdparty/freetype/src/smooth/ftgrays.c
index fd357a50fc..93538331af 100644
--- a/thirdparty/freetype/src/smooth/ftgrays.c
+++ b/thirdparty/freetype/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
*
* A new `perfect' anti-aliasing renderer (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/smooth/ftgrays.h b/thirdparty/freetype/src/smooth/ftgrays.h
index e9f9c7a4ad..e10fd039ac 100644
--- a/thirdparty/freetype/src/smooth/ftgrays.h
+++ b/thirdparty/freetype/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
*
* FreeType smooth renderer declaration
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/smooth/ftsmerrs.h b/thirdparty/freetype/src/smooth/ftsmerrs.h
index d52c0dd9e2..3f8567b0fa 100644
--- a/thirdparty/freetype/src/smooth/ftsmerrs.h
+++ b/thirdparty/freetype/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
*
* smooth renderer error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/smooth/ftsmooth.c b/thirdparty/freetype/src/smooth/ftsmooth.c
index cd034d2b40..072045cbc2 100644
--- a/thirdparty/freetype/src/smooth/ftsmooth.c
+++ b/thirdparty/freetype/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
*
* Anti-aliasing renderer interface (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -155,6 +155,9 @@
goto Exit;
}
+ if ( !bitmap->rows || !bitmap->pitch )
+ goto Exit;
+
/* allocate new one */
if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
goto Exit;
@@ -188,7 +191,7 @@
/* implode outline if needed */
{
FT_Vector* points = outline->points;
- FT_Vector* points_end = points + outline->n_points;
+ FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
FT_Vector* vec;
@@ -207,7 +210,7 @@
/* deflate outline if needed */
{
FT_Vector* points = outline->points;
- FT_Vector* points_end = points + outline->n_points;
+ FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
FT_Vector* vec;
diff --git a/thirdparty/freetype/src/smooth/ftsmooth.h b/thirdparty/freetype/src/smooth/ftsmooth.h
index fbb21a31d0..ee5d2ff61d 100644
--- a/thirdparty/freetype/src/smooth/ftsmooth.h
+++ b/thirdparty/freetype/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
*
* Anti-aliasing renderer interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/smooth/module.mk b/thirdparty/freetype/src/smooth/module.mk
index 44b76dfec6..ad8b47dab6 100644
--- a/thirdparty/freetype/src/smooth/module.mk
+++ b/thirdparty/freetype/src/smooth/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/smooth/rules.mk b/thirdparty/freetype/src/smooth/rules.mk
index 0153ac24a4..b08056fac5 100644
--- a/thirdparty/freetype/src/smooth/rules.mk
+++ b/thirdparty/freetype/src/smooth/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/smooth/smooth.c b/thirdparty/freetype/src/smooth/smooth.c
index 9c543d3360..6ad9424f01 100644
--- a/thirdparty/freetype/src/smooth/smooth.c
+++ b/thirdparty/freetype/src/smooth/smooth.c
@@ -4,7 +4,7 @@
*
* FreeType anti-aliasing rasterer module component (body only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/module.mk b/thirdparty/freetype/src/truetype/module.mk
index 8a841cc956..2d8d39d1f7 100644
--- a/thirdparty/freetype/src/truetype/module.mk
+++ b/thirdparty/freetype/src/truetype/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/truetype/rules.mk b/thirdparty/freetype/src/truetype/rules.mk
index df8dcd4a4e..2f6fecfc44 100644
--- a/thirdparty/freetype/src/truetype/rules.mk
+++ b/thirdparty/freetype/src/truetype/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/truetype/truetype.c b/thirdparty/freetype/src/truetype/truetype.c
index 84928e7321..1f15b29bb2 100644
--- a/thirdparty/freetype/src/truetype/truetype.c
+++ b/thirdparty/freetype/src/truetype/truetype.c
@@ -4,7 +4,7 @@
*
* FreeType TrueType driver component (body only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttdriver.c b/thirdparty/freetype/src/truetype/ttdriver.c
index ff626d53ab..90fab46e28 100644
--- a/thirdparty/freetype/src/truetype/ttdriver.c
+++ b/thirdparty/freetype/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
*
* TrueType font driver implementation (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttdriver.h b/thirdparty/freetype/src/truetype/ttdriver.h
index 3936c6a4de..d1cfa47c8b 100644
--- a/thirdparty/freetype/src/truetype/ttdriver.h
+++ b/thirdparty/freetype/src/truetype/ttdriver.h
@@ -4,7 +4,7 @@
*
* High-level TrueType driver interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/tterrors.h b/thirdparty/freetype/src/truetype/tterrors.h
index 5609d28d68..71d66023cd 100644
--- a/thirdparty/freetype/src/truetype/tterrors.h
+++ b/thirdparty/freetype/src/truetype/tterrors.h
@@ -4,7 +4,7 @@
*
* TrueType error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttgload.c b/thirdparty/freetype/src/truetype/ttgload.c
index a04684086b..2a1742839a 100644
--- a/thirdparty/freetype/src/truetype/ttgload.c
+++ b/thirdparty/freetype/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
*
* TrueType Glyph Loader (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -1102,9 +1102,16 @@
}
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /* if we have a HVAR table, `pp1' and/or `pp2' are already adjusted */
- if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ||
- !IS_HINTED( loader->load_flags ) )
+ /* if we have a HVAR table, `pp1' and/or `pp2' */
+ /* are already adjusted but unscaled */
+ if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) &&
+ IS_HINTED( loader->load_flags ) )
+ {
+ loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
+ loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+ /* pp1.y and pp2.y are always zero */
+ }
+ else
#endif
{
loader->pp1 = outline->points[n_points - 4];
@@ -1112,9 +1119,17 @@
}
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /* if we have a VVAR table, `pp3' and/or `pp4' are already adjusted */
- if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ||
- !IS_HINTED( loader->load_flags ) )
+ /* if we have a VVAR table, `pp3' and/or `pp4' */
+ /* are already adjusted but unscaled */
+ if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) &&
+ IS_HINTED( loader->load_flags ) )
+ {
+ loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
+ loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
+ loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
+ loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
+ }
+ else
#endif
{
loader->pp3 = outline->points[n_points - 2];
@@ -2287,13 +2302,14 @@
if ( face->vertical_info &&
face->vertical.number_Of_VMetrics > 0 )
{
- top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
+ top = (FT_Short)FT_DivFix( SUB_LONG( loader->pp3.y, bbox.yMax ),
y_scale );
if ( loader->pp3.y <= loader->pp4.y )
advance = 0;
else
- advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
+ advance = (FT_UShort)FT_DivFix( SUB_LONG( loader->pp3.y,
+ loader->pp4.y ),
y_scale );
}
else
diff --git a/thirdparty/freetype/src/truetype/ttgload.h b/thirdparty/freetype/src/truetype/ttgload.h
index f1324bc862..9a8c3e71dd 100644
--- a/thirdparty/freetype/src/truetype/ttgload.h
+++ b/thirdparty/freetype/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
*
* TrueType Glyph Loader (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttgxvar.c b/thirdparty/freetype/src/truetype/ttgxvar.c
index 78d87dc097..110f24a116 100644
--- a/thirdparty/freetype/src/truetype/ttgxvar.c
+++ b/thirdparty/freetype/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
*
* TrueType GX Font Variation loader
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
*
* This file is part of the FreeType project, and may only be used,
@@ -1470,6 +1470,7 @@
FT_ULong table_len;
FT_ULong gvar_start;
FT_ULong offsetToData;
+ FT_ULong offsets_len;
GX_GVar_Head gvar_head;
static const FT_Frame_Field gvar_fields[] =
@@ -1530,9 +1531,13 @@
goto Exit;
}
- /* rough sanity check: offsets can be either 2 or 4 bytes */
- if ( (FT_ULong)gvar_head.glyphCount *
- ( ( gvar_head.flags & 1 ) ? 4 : 2 ) > table_len )
+ /* offsets can be either 2 or 4 bytes */
+ /* (one more offset than glyphs, to mark size of last) */
+ offsets_len = ( gvar_head.glyphCount + 1 ) *
+ ( ( gvar_head.flags & 1 ) ? 4L : 2L );
+
+ /* rough sanity check */
+ if (offsets_len > table_len )
{
FT_TRACE1(( "ft_var_load_gvar: invalid number of glyphs\n" ));
error = FT_THROW( Invalid_Table );
@@ -1541,81 +1546,102 @@
FT_TRACE2(( "loaded\n" ));
- blend->gvar_size = table_len;
- blend->tuplecount = gvar_head.globalCoordCount;
- blend->gv_glyphcnt = gvar_head.glyphCount;
- offsetToData = gvar_start + gvar_head.offsetToData;
+ blend->gvar_size = table_len;
+ offsetToData = gvar_start + gvar_head.offsetToData;
FT_TRACE5(( "gvar: there %s %d shared coordinate%s:\n",
- blend->tuplecount == 1 ? "is" : "are",
- blend->tuplecount,
- blend->tuplecount == 1 ? "" : "s" ));
+ gvar_head.globalCoordCount == 1 ? "is" : "are",
+ gvar_head.globalCoordCount,
+ gvar_head.globalCoordCount == 1 ? "" : "s" ));
- if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
+ if ( FT_FRAME_ENTER( offsets_len ) )
goto Exit;
+ /* offsets (one more offset than glyphs, to mark size of last) */
+ if ( FT_NEW_ARRAY( blend->glyphoffsets, gvar_head.glyphCount + 1 ) )
+ goto Fail2;
+
if ( gvar_head.flags & 1 )
{
- FT_ULong limit = gvar_start + table_len;
-
+ FT_ULong limit = gvar_start + table_len;
+ FT_ULong max_offset = 0;
- /* long offsets (one more offset than glyphs, to mark size of last) */
- if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )
- goto Exit;
- for ( i = 0; i <= blend->gv_glyphcnt; i++ )
+ for ( i = 0; i <= gvar_head.glyphCount; i++ )
{
blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG();
- /* use `>', not `>=' */
- if ( blend->glyphoffsets[i] > limit )
+
+ if ( max_offset <= blend->glyphoffsets[i] )
+ max_offset = blend->glyphoffsets[i];
+ else
{
FT_TRACE2(( "ft_var_load_gvar:"
- " invalid glyph variation data offset for index %d\n",
+ " glyph variation data offset %d not monotonic\n",
i ));
- error = FT_THROW( Invalid_Table );
- break;
+ blend->glyphoffsets[i] = max_offset;
+ }
+
+ /* use `<', not `<=' */
+ if ( limit < blend->glyphoffsets[i] )
+ {
+ FT_TRACE2(( "ft_var_load_gvar:"
+ " glyph variation data offset %d out of range\n",
+ i ));
+ blend->glyphoffsets[i] = limit;
}
}
}
else
{
- FT_ULong limit = gvar_start + table_len;
-
+ FT_ULong limit = gvar_start + table_len;
+ FT_ULong max_offset = 0;
- /* short offsets (one more offset than glyphs, to mark size of last) */
- if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )
- goto Exit;
- for ( i = 0; i <= blend->gv_glyphcnt; i++ )
+ for ( i = 0; i <= gvar_head.glyphCount; i++ )
{
blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
- /* use `>', not `>=' */
- if ( blend->glyphoffsets[i] > limit )
+
+ if ( max_offset <= blend->glyphoffsets[i] )
+ max_offset = blend->glyphoffsets[i];
+ else
{
FT_TRACE2(( "ft_var_load_gvar:"
- " invalid glyph variation data offset for index %d\n",
+ " glyph variation data offset %d not monotonic\n",
i ));
- error = FT_THROW( Invalid_Table );
- break;
+ blend->glyphoffsets[i] = max_offset;
+ }
+
+ /* use `<', not `<=' */
+ if ( limit < blend->glyphoffsets[i] )
+ {
+ FT_TRACE2(( "ft_var_load_gvar:"
+ " glyph variation data offset %d out of range\n",
+ i ));
+ blend->glyphoffsets[i] = limit;
}
}
}
+ blend->gv_glyphcnt = gvar_head.glyphCount;
+
FT_FRAME_EXIT();
- if ( error )
- goto Exit;
- if ( blend->tuplecount != 0 )
+ if ( gvar_head.globalCoordCount != 0 )
{
- if ( FT_NEW_ARRAY( blend->tuplecoords,
- gvar_head.axisCount * blend->tuplecount ) )
- goto Exit;
+ if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||
+ FT_FRAME_ENTER( gvar_head.globalCoordCount *
+ gvar_head.axisCount * 2L ) )
+ {
+ FT_TRACE2(( "ft_var_load_gvar:"
+ " glyph variation shared tuples missing\n" ));
+ goto Fail;
+ }
- if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||
- FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) )
- goto Exit;
+ if ( FT_NEW_ARRAY( blend->tuplecoords,
+ gvar_head.axisCount * gvar_head.globalCoordCount ) )
+ goto Fail2;
- for ( i = 0; i < blend->tuplecount; i++ )
+ for ( i = 0; i < gvar_head.globalCoordCount; i++ )
{
FT_TRACE5(( " [ " ));
for ( j = 0; j < (FT_UInt)gvar_head.axisCount; j++ )
@@ -1628,6 +1654,8 @@
FT_TRACE5(( "]\n" ));
}
+ blend->tuplecount = gvar_head.globalCoordCount;
+
FT_TRACE5(( "\n" ));
FT_FRAME_EXIT();
@@ -1635,6 +1663,14 @@
Exit:
return error;
+
+ Fail2:
+ FT_FRAME_EXIT();
+
+ Fail:
+ FT_FREE( blend->glyphoffsets );
+ blend->gv_glyphcnt = 0;
+ goto Exit;
}
@@ -2127,7 +2163,7 @@
/* `fvar' table validity check in `sfnt_init_face' */
/* the various `*_size' variables, which we also use as */
- /* offsets into the `mmlen' array, must be multiples of the */
+ /* offsets into the `mmvar' array, must be multiples of the */
/* pointer size (except the last one); without such an */
/* alignment there might be runtime errors due to */
/* misaligned addresses */
@@ -3037,7 +3073,7 @@
TT_Set_Named_Instance( TT_Face face,
FT_UInt instance_index )
{
- FT_Error error = FT_ERR( Invalid_Argument );
+ FT_Error error;
GX_Blend blend;
FT_MM_Var* mmvar;
@@ -3057,7 +3093,10 @@
/* `instance_index' starts with value 1, thus `>' */
if ( instance_index > num_instances )
+ {
+ error = FT_ERR( Invalid_Argument );
goto Exit;
+ }
if ( instance_index > 0 )
{
@@ -3766,7 +3805,7 @@
blend->glyphoffsets[glyph_index + 1] )
{
FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
- " no variation data for this glyph\n" ));
+ " no variation data for glyph %d\n", glyph_index ));
return FT_Err_Ok;
}
diff --git a/thirdparty/freetype/src/truetype/ttgxvar.h b/thirdparty/freetype/src/truetype/ttgxvar.h
index 07c99b6403..11664e997a 100644
--- a/thirdparty/freetype/src/truetype/ttgxvar.h
+++ b/thirdparty/freetype/src/truetype/ttgxvar.h
@@ -4,7 +4,7 @@
*
* TrueType GX Font Variation loader (specification)
*
- * Copyright (C) 2004-2019 by
+ * Copyright (C) 2004-2020 by
* David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttinterp.c b/thirdparty/freetype/src/truetype/ttinterp.c
index 70434e1729..3215040970 100644
--- a/thirdparty/freetype/src/truetype/ttinterp.c
+++ b/thirdparty/freetype/src/truetype/ttinterp.c
@@ -4,7 +4,7 @@
*
* TrueType bytecode interpreter (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -3718,7 +3718,7 @@
/* We will then parse the current table. */
rec = exc->FDefs;
- limit = rec + exc->numFDefs;
+ limit = FT_OFFSET( rec, exc->numFDefs );
n = (FT_ULong)args[0];
for ( ; rec < limit; rec++ )
@@ -3965,6 +3965,9 @@
if ( BOUNDSL( F, exc->maxFunc + 1 ) )
goto Fail;
+ if ( !exc->FDefs )
+ goto Fail;
+
/* Except for some old Apple fonts, all functions in a TrueType */
/* font are defined in increasing order, starting from 0. This */
/* means that we normally have */
@@ -4062,7 +4065,7 @@
/* */
/* If this isn't true, we need to look up the function table. */
- def = exc->FDefs + F;
+ def = FT_OFFSET( exc->FDefs, F );
if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
{
/* look up the FDefs table */
@@ -4070,7 +4073,7 @@
def = exc->FDefs;
- limit = def + exc->numFDefs;
+ limit = FT_OFFSET( def, exc->numFDefs );
while ( def < limit && def->opc != F )
def++;
@@ -4150,7 +4153,7 @@
/* First of all, look for the same function in our table */
def = exc->IDefs;
- limit = def + exc->numIDefs;
+ limit = FT_OFFSET( def, exc->numIDefs );
for ( ; def < limit; def++ )
if ( def->opc == (FT_ULong)args[0] )
@@ -6346,12 +6349,14 @@
/* twilight points (confirmed by Greg Hitchcock) */
if ( exc->GS.gep1 == 0 )
{
- exc->zp1.org[point].x = exc->zp0.org[exc->GS.rp0].x +
- TT_MulFix14( cvt_dist,
- exc->GS.freeVector.x );
- exc->zp1.org[point].y = exc->zp0.org[exc->GS.rp0].y +
- TT_MulFix14( cvt_dist,
- exc->GS.freeVector.y );
+ exc->zp1.org[point].x = ADD_LONG(
+ exc->zp0.org[exc->GS.rp0].x,
+ TT_MulFix14( cvt_dist,
+ exc->GS.freeVector.x ) );
+ exc->zp1.org[point].y = ADD_LONG(
+ exc->zp0.org[exc->GS.rp0].y,
+ TT_MulFix14( cvt_dist,
+ exc->GS.freeVector.y ) );
exc->zp1.cur[point] = exc->zp1.org[point];
}
@@ -7715,7 +7720,7 @@
Ins_UNKNOWN( TT_ExecContext exc )
{
TT_DefRecord* def = exc->IDefs;
- TT_DefRecord* limit = def + exc->numIDefs;
+ TT_DefRecord* limit = FT_OFFSET( def, exc->numIDefs );
for ( ; def < limit; def++ )
@@ -7867,7 +7872,7 @@
FT_MAX( 50,
exc->cvtSize / 10 );
else
- exc->loopcall_counter_max = 300 + 8 * exc->cvtSize;
+ exc->loopcall_counter_max = 300 + 22 * exc->cvtSize;
/* as a protection against an unreasonable number of CVT entries */
/* we assume at most 100 control values per glyph for the counter */
@@ -8567,7 +8572,7 @@
case FT_ERR( Invalid_Opcode ):
{
TT_DefRecord* def = exc->IDefs;
- TT_DefRecord* limit = def + exc->numIDefs;
+ TT_DefRecord* limit = FT_OFFSET( def, exc->numIDefs );
for ( ; def < limit; def++ )
diff --git a/thirdparty/freetype/src/truetype/ttinterp.h b/thirdparty/freetype/src/truetype/ttinterp.h
index 0cb1e892fb..07e4ad6891 100644
--- a/thirdparty/freetype/src/truetype/ttinterp.h
+++ b/thirdparty/freetype/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
*
* TrueType bytecode interpreter (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttobjs.c b/thirdparty/freetype/src/truetype/ttobjs.c
index e4775a51ed..730a5b8cdf 100644
--- a/thirdparty/freetype/src/truetype/ttobjs.c
+++ b/thirdparty/freetype/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
*
* Objects manager (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttobjs.h b/thirdparty/freetype/src/truetype/ttobjs.h
index 9fc654d5d1..7c3fc7ef8a 100644
--- a/thirdparty/freetype/src/truetype/ttobjs.h
+++ b/thirdparty/freetype/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
*
* Objects manager (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttpload.c b/thirdparty/freetype/src/truetype/ttpload.c
index bc954c2dba..d35393a8b0 100644
--- a/thirdparty/freetype/src/truetype/ttpload.c
+++ b/thirdparty/freetype/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
*
* TrueType-specific tables loader (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -633,7 +633,7 @@
FT_UInt nn;
FT_Byte* result = NULL;
FT_ULong record_size = face->hdmx_record_size;
- FT_Byte* record = face->hdmx_table + 8;
+ FT_Byte* record = FT_OFFSET( face->hdmx_table, 8 );
for ( nn = 0; nn < face->hdmx_record_count; nn++ )
diff --git a/thirdparty/freetype/src/truetype/ttpload.h b/thirdparty/freetype/src/truetype/ttpload.h
index 022750e324..3bbd4add19 100644
--- a/thirdparty/freetype/src/truetype/ttpload.h
+++ b/thirdparty/freetype/src/truetype/ttpload.h
@@ -4,7 +4,7 @@
*
* TrueType-specific tables loader (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttsubpix.c b/thirdparty/freetype/src/truetype/ttsubpix.c
index 23a2e5b440..8289818863 100644
--- a/thirdparty/freetype/src/truetype/ttsubpix.c
+++ b/thirdparty/freetype/src/truetype/ttsubpix.c
@@ -4,7 +4,7 @@
*
* TrueType Subpixel Hinting.
*
- * Copyright (C) 2010-2019 by
+ * Copyright (C) 2010-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttsubpix.h b/thirdparty/freetype/src/truetype/ttsubpix.h
index 4966800c2d..23adf7e8d8 100644
--- a/thirdparty/freetype/src/truetype/ttsubpix.h
+++ b/thirdparty/freetype/src/truetype/ttsubpix.h
@@ -4,7 +4,7 @@
*
* TrueType Subpixel Hinting.
*
- * Copyright (C) 2010-2019 by
+ * Copyright (C) 2010-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/module.mk b/thirdparty/freetype/src/type1/module.mk
index 2f48c65821..cffb774b45 100644
--- a/thirdparty/freetype/src/type1/module.mk
+++ b/thirdparty/freetype/src/type1/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type1/rules.mk b/thirdparty/freetype/src/type1/rules.mk
index 901169c7a5..213e619247 100644
--- a/thirdparty/freetype/src/type1/rules.mk
+++ b/thirdparty/freetype/src/type1/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type1/t1afm.c b/thirdparty/freetype/src/type1/t1afm.c
index 6841184539..0866e7bf97 100644
--- a/thirdparty/freetype/src/type1/t1afm.c
+++ b/thirdparty/freetype/src/type1/t1afm.c
@@ -4,7 +4,7 @@
*
* AFM support for Type 1 fonts (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1afm.h b/thirdparty/freetype/src/type1/t1afm.h
index a8e6a5495a..40ce8f9754 100644
--- a/thirdparty/freetype/src/type1/t1afm.h
+++ b/thirdparty/freetype/src/type1/t1afm.h
@@ -4,7 +4,7 @@
*
* AFM support for Type 1 fonts (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1driver.c b/thirdparty/freetype/src/type1/t1driver.c
index 557733da3b..75a5698e8d 100644
--- a/thirdparty/freetype/src/type1/t1driver.c
+++ b/thirdparty/freetype/src/type1/t1driver.c
@@ -4,7 +4,7 @@
*
* Type 1 driver interface (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1driver.h b/thirdparty/freetype/src/type1/t1driver.h
index 206f64a0bc..84b3e041c4 100644
--- a/thirdparty/freetype/src/type1/t1driver.h
+++ b/thirdparty/freetype/src/type1/t1driver.h
@@ -4,7 +4,7 @@
*
* High-level Type 1 driver interface (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1errors.h b/thirdparty/freetype/src/type1/t1errors.h
index b35f67a24c..1b119b843a 100644
--- a/thirdparty/freetype/src/type1/t1errors.h
+++ b/thirdparty/freetype/src/type1/t1errors.h
@@ -4,7 +4,7 @@
*
* Type 1 error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1gload.c b/thirdparty/freetype/src/type1/t1gload.c
index f9b115b186..fcaf66c401 100644
--- a/thirdparty/freetype/src/type1/t1gload.c
+++ b/thirdparty/freetype/src/type1/t1gload.c
@@ -4,7 +4,7 @@
*
* Type 1 Glyph Loader (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1gload.h b/thirdparty/freetype/src/type1/t1gload.h
index 80440369dc..59fae82b6d 100644
--- a/thirdparty/freetype/src/type1/t1gload.h
+++ b/thirdparty/freetype/src/type1/t1gload.h
@@ -4,7 +4,7 @@
*
* Type 1 Glyph Loader (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1load.c b/thirdparty/freetype/src/type1/t1load.c
index 5cffdfaac4..d0ea36badb 100644
--- a/thirdparty/freetype/src/type1/t1load.c
+++ b/thirdparty/freetype/src/type1/t1load.c
@@ -4,7 +4,7 @@
*
* Type 1 font loader (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -309,31 +309,55 @@
FT_UInt i;
FT_Fixed axiscoords[T1_MAX_MM_AXIS];
PS_Blend blend = face->blend;
+ FT_UShort* axis_flags;
+
+ FT_Offset mmvar_size;
+ FT_Offset axis_flags_size;
+ FT_Offset axis_size;
error = T1_Get_Multi_Master( face, &mmaster );
if ( error )
goto Exit;
- if ( FT_ALLOC( mmvar,
- sizeof ( FT_MM_Var ) +
- mmaster.num_axis * sizeof ( FT_Var_Axis ) ) )
+
+ /* the various `*_size' variables, which we also use as */
+ /* offsets into the `mmvar' array, must be multiples of the */
+ /* pointer size (except the last one); without such an */
+ /* alignment there might be runtime errors due to */
+ /* misaligned addresses */
+#undef ALIGN_SIZE
+#define ALIGN_SIZE( n ) \
+ ( ( (n) + sizeof (void*) - 1 ) & ~( sizeof (void*) - 1 ) )
+
+ mmvar_size = ALIGN_SIZE( sizeof ( FT_MM_Var ) );
+ axis_flags_size = ALIGN_SIZE( mmaster.num_axis *
+ sizeof ( FT_UShort ) );
+ axis_size = mmaster.num_axis * sizeof ( FT_Var_Axis );
+
+ if ( FT_ALLOC( mmvar, mmvar_size +
+ axis_flags_size +
+ axis_size ) )
goto Exit;
mmvar->num_axis = mmaster.num_axis;
mmvar->num_designs = mmaster.num_designs;
mmvar->num_namedstyles = 0; /* Not supported */
- mmvar->axis = (FT_Var_Axis*)&mmvar[1];
- /* Point to axes after MM_Var struct */
- mmvar->namedstyle = NULL;
+
+ /* while axis flags are meaningless here, we have to provide the array */
+ /* to make `FT_Get_Var_Axis_Flags' work: the function expects that the */
+ /* values directly follow the data of `FT_MM_Var' */
+ axis_flags = (FT_UShort*)( (char*)mmvar + mmvar_size );
+ for ( i = 0; i < mmaster.num_axis; i++ )
+ axis_flags[i] = 0;
+
+ mmvar->axis = (FT_Var_Axis*)( (char*)axis_flags + axis_flags_size );
+ mmvar->namedstyle = NULL;
for ( i = 0; i < mmaster.num_axis; i++ )
{
mmvar->axis[i].name = mmaster.axis[i].name;
mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum );
mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum );
- mmvar->axis[i].def = ( mmvar->axis[i].minimum +
- mmvar->axis[i].maximum ) / 2;
- /* Does not apply. But this value is in range */
mmvar->axis[i].strid = ~0U; /* Does not apply */
mmvar->axis[i].tag = ~0U; /* Does not apply */
diff --git a/thirdparty/freetype/src/type1/t1load.h b/thirdparty/freetype/src/type1/t1load.h
index 44f835bde2..9cac0f6fb6 100644
--- a/thirdparty/freetype/src/type1/t1load.h
+++ b/thirdparty/freetype/src/type1/t1load.h
@@ -4,7 +4,7 @@
*
* Type 1 font loader (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1objs.c b/thirdparty/freetype/src/type1/t1objs.c
index 741388a645..80ee0e265e 100644
--- a/thirdparty/freetype/src/type1/t1objs.c
+++ b/thirdparty/freetype/src/type1/t1objs.c
@@ -4,7 +4,7 @@
*
* Type 1 objects manager (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1objs.h b/thirdparty/freetype/src/type1/t1objs.h
index 2161091f77..6bc902cc89 100644
--- a/thirdparty/freetype/src/type1/t1objs.h
+++ b/thirdparty/freetype/src/type1/t1objs.h
@@ -4,7 +4,7 @@
*
* Type 1 objects manager (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1parse.c b/thirdparty/freetype/src/type1/t1parse.c
index 56caeb9e40..ec30355bf8 100644
--- a/thirdparty/freetype/src/type1/t1parse.c
+++ b/thirdparty/freetype/src/type1/t1parse.c
@@ -4,7 +4,7 @@
*
* Type 1 parser (body).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1parse.h b/thirdparty/freetype/src/type1/t1parse.h
index dab8fddc8b..edf79b0a8b 100644
--- a/thirdparty/freetype/src/type1/t1parse.h
+++ b/thirdparty/freetype/src/type1/t1parse.h
@@ -4,7 +4,7 @@
*
* Type 1 parser (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1tokens.h b/thirdparty/freetype/src/type1/t1tokens.h
index 97f2dbe0cf..c09420355d 100644
--- a/thirdparty/freetype/src/type1/t1tokens.h
+++ b/thirdparty/freetype/src/type1/t1tokens.h
@@ -4,7 +4,7 @@
*
* Type 1 tokenizer (specification).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/type1.c b/thirdparty/freetype/src/type1/type1.c
index ce8557a5fb..95dbaeb501 100644
--- a/thirdparty/freetype/src/type1/type1.c
+++ b/thirdparty/freetype/src/type1/type1.c
@@ -4,7 +4,7 @@
*
* FreeType Type 1 driver component (body only).
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/module.mk b/thirdparty/freetype/src/type42/module.mk
index 9e9d15455b..6ef3a95ead 100644
--- a/thirdparty/freetype/src/type42/module.mk
+++ b/thirdparty/freetype/src/type42/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2002-2019 by
+# Copyright (C) 2002-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type42/rules.mk b/thirdparty/freetype/src/type42/rules.mk
index 9d71f5300e..f4ce91a3b7 100644
--- a/thirdparty/freetype/src/type42/rules.mk
+++ b/thirdparty/freetype/src/type42/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2002-2019 by
+# Copyright (C) 2002-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type42/t42drivr.c b/thirdparty/freetype/src/type42/t42drivr.c
index 09ad632e97..4b2cab3474 100644
--- a/thirdparty/freetype/src/type42/t42drivr.c
+++ b/thirdparty/freetype/src/type42/t42drivr.c
@@ -4,7 +4,7 @@
*
* High-level Type 42 driver interface (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42drivr.h b/thirdparty/freetype/src/type42/t42drivr.h
index a35ca28f84..7e7ec70f9d 100644
--- a/thirdparty/freetype/src/type42/t42drivr.h
+++ b/thirdparty/freetype/src/type42/t42drivr.h
@@ -4,7 +4,7 @@
*
* High-level Type 42 driver interface (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42error.h b/thirdparty/freetype/src/type42/t42error.h
index 5fb2143949..6d3617e927 100644
--- a/thirdparty/freetype/src/type42/t42error.h
+++ b/thirdparty/freetype/src/type42/t42error.h
@@ -4,7 +4,7 @@
*
* Type 42 error codes (specification only).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42objs.c b/thirdparty/freetype/src/type42/t42objs.c
index d31bace451..8d1e63ffc7 100644
--- a/thirdparty/freetype/src/type42/t42objs.c
+++ b/thirdparty/freetype/src/type42/t42objs.c
@@ -4,7 +4,7 @@
*
* Type 42 objects manager (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42objs.h b/thirdparty/freetype/src/type42/t42objs.h
index 98300cf348..ecb495e8f0 100644
--- a/thirdparty/freetype/src/type42/t42objs.h
+++ b/thirdparty/freetype/src/type42/t42objs.h
@@ -4,7 +4,7 @@
*
* Type 42 objects manager (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42parse.c b/thirdparty/freetype/src/type42/t42parse.c
index c47a77786d..7f26d04170 100644
--- a/thirdparty/freetype/src/type42/t42parse.c
+++ b/thirdparty/freetype/src/type42/t42parse.c
@@ -4,7 +4,7 @@
*
* Type 42 font parser (body).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42parse.h b/thirdparty/freetype/src/type42/t42parse.h
index 0c7bb48496..de54a46cf1 100644
--- a/thirdparty/freetype/src/type42/t42parse.h
+++ b/thirdparty/freetype/src/type42/t42parse.h
@@ -4,7 +4,7 @@
*
* Type 42 font parser (specification).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42types.h b/thirdparty/freetype/src/type42/t42types.h
index a258144ec3..f66f09db87 100644
--- a/thirdparty/freetype/src/type42/t42types.h
+++ b/thirdparty/freetype/src/type42/t42types.h
@@ -4,7 +4,7 @@
*
* Type 42 font data types (specification only).
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/type42.c b/thirdparty/freetype/src/type42/type42.c
index 0cb7b77eec..4739b3c333 100644
--- a/thirdparty/freetype/src/type42/type42.c
+++ b/thirdparty/freetype/src/type42/type42.c
@@ -4,7 +4,7 @@
*
* FreeType Type 42 driver component.
*
- * Copyright (C) 2002-2019 by
+ * Copyright (C) 2002-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/winfonts/fnterrs.h b/thirdparty/freetype/src/winfonts/fnterrs.h
index af29307c75..f98e68435b 100644
--- a/thirdparty/freetype/src/winfonts/fnterrs.h
+++ b/thirdparty/freetype/src/winfonts/fnterrs.h
@@ -4,7 +4,7 @@
*
* Win FNT/FON error codes (specification only).
*
- * Copyright (C) 2001-2019 by
+ * Copyright (C) 2001-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/winfonts/module.mk b/thirdparty/freetype/src/winfonts/module.mk
index 82fb0151f8..4614c55fd0 100644
--- a/thirdparty/freetype/src/winfonts/module.mk
+++ b/thirdparty/freetype/src/winfonts/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/winfonts/rules.mk b/thirdparty/freetype/src/winfonts/rules.mk
index 998d49bc9f..e73ef5ea99 100644
--- a/thirdparty/freetype/src/winfonts/rules.mk
+++ b/thirdparty/freetype/src/winfonts/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 1996-2019 by
+# Copyright (C) 1996-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/winfonts/winfnt.c b/thirdparty/freetype/src/winfonts/winfnt.c
index 2d771be2cc..9b466e8f28 100644
--- a/thirdparty/freetype/src/winfonts/winfnt.c
+++ b/thirdparty/freetype/src/winfonts/winfnt.c
@@ -4,7 +4,7 @@
*
* FreeType font driver for Windows FNT/FON files
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
* Copyright 2003 Huw D M Davies for Codeweavers
* Copyright 2007 Dmitry Timoshkov for Codeweavers
@@ -331,7 +331,7 @@
{
FT_TRACE2(( "invalid alignment shift count for resource data\n" ));
error = FT_THROW( Invalid_File_Format );
- goto Exit;
+ goto Exit1;
}
@@ -597,6 +597,10 @@
Exit:
return error;
+
+ Exit1:
+ FT_FRAME_EXIT();
+ goto Exit;
}
diff --git a/thirdparty/freetype/src/winfonts/winfnt.h b/thirdparty/freetype/src/winfonts/winfnt.h
index b628ad4c42..391f4448a7 100644
--- a/thirdparty/freetype/src/winfonts/winfnt.h
+++ b/thirdparty/freetype/src/winfonts/winfnt.h
@@ -4,7 +4,7 @@
*
* FreeType font driver for Windows FNT/FON files
*
- * Copyright (C) 1996-2019 by
+ * Copyright (C) 1996-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
* Copyright 2007 Dmitry Timoshkov for Codeweavers
*
diff --git a/thirdparty/glslang/LICENSE.txt b/thirdparty/glslang/LICENSE.txt
new file mode 100644
index 0000000000..a10c0944f8
--- /dev/null
+++ b/thirdparty/glslang/LICENSE.txt
@@ -0,0 +1,108 @@
+Here, glslang proper means core GLSL parsing, HLSL parsing, and SPIR-V code
+generation. Glslang proper requires use of two licenses, one that covers
+non-preprocessing and an additional one that covers preprocessing.
+
+Bison was removed long ago. You can build glslang from the source grammar,
+using tools of your choice, without using bison or any bison files.
+
+Other parts, outside of glslang proper, include:
+
+- gl_types.h, only needed for OpenGL-like reflection, and can be left out of
+ a parse and codegen project. See it for its license.
+
+- update_glslang_sources.py, which is not part of the project proper and does
+ not need to be used.
+
+- the SPIR-V "remapper", which is optional, but has the same license as
+ glslang proper
+
+- Google tests and SPIR-V tools, and anything in the external subdirectory
+ are external and optional; see them for their respective licenses.
+
+--------------------------------------------------------------------------------
+
+The core of glslang-proper, minus the preprocessor is licenced as follows:
+
+//
+// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) <various other dates and companies>
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+--------------------------------------------------------------------------------
+
+The preprocessor has the core license stated above, plus an additional licence:
+
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
diff --git a/thirdparty/glslang/OGLCompilersDLL/InitializeDll.cpp b/thirdparty/glslang/OGLCompilersDLL/InitializeDll.cpp
new file mode 100644
index 0000000000..abea9108b1
--- /dev/null
+++ b/thirdparty/glslang/OGLCompilersDLL/InitializeDll.cpp
@@ -0,0 +1,165 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#define SH_EXPORTING
+
+#include <cassert>
+
+#include "InitializeDll.h"
+#include "../glslang/Include/InitializeGlobals.h"
+#include "../glslang/Public/ShaderLang.h"
+#include "../glslang/Include/PoolAlloc.h"
+
+namespace glslang {
+
+OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+// Per-process initialization.
+// Needs to be called at least once before parsing, etc. is done.
+// Will also do thread initialization for the calling thread; other
+// threads will need to do that explicitly.
+bool InitProcess()
+{
+ glslang::GetGlobalLock();
+
+ if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
+ //
+ // Function is re-entrant.
+ //
+
+ glslang::ReleaseGlobalLock();
+ return true;
+ }
+
+ ThreadInitializeIndex = OS_AllocTLSIndex();
+
+ if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
+
+ glslang::ReleaseGlobalLock();
+ return false;
+ }
+
+ if (! InitializePoolIndex()) {
+ assert(0 && "InitProcess(): Failed to initialize global pool");
+
+ glslang::ReleaseGlobalLock();
+ return false;
+ }
+
+ if (! InitThread()) {
+ assert(0 && "InitProcess(): Failed to initialize thread");
+
+ glslang::ReleaseGlobalLock();
+ return false;
+ }
+
+ glslang::ReleaseGlobalLock();
+ return true;
+}
+
+// Per-thread scoped initialization.
+// Must be called at least once by each new thread sharing the
+// symbol tables, etc., needed to parse.
+bool InitThread()
+{
+ //
+ // This function is re-entrant
+ //
+ if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitThread(): Process hasn't been initalised.");
+ return false;
+ }
+
+ if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
+ return true;
+
+ if (! OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
+ assert(0 && "InitThread(): Unable to set init flag.");
+ return false;
+ }
+
+ glslang::SetThreadPoolAllocator(nullptr);
+
+ return true;
+}
+
+// Not necessary to call this: InitThread() is reentrant, and the need
+// to do per thread tear down has been removed.
+//
+// This is kept, with memory management removed, to satisfy any exiting
+// calls to it that rely on it.
+bool DetachThread()
+{
+ bool success = true;
+
+ if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+ return true;
+
+ //
+ // Function is re-entrant and this thread may not have been initialized.
+ //
+ if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
+ if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
+ assert(0 && "DetachThread(): Unable to clear init flag.");
+ success = false;
+ }
+ }
+
+ return success;
+}
+
+// Not necessary to call this: InitProcess() is reentrant.
+//
+// This is kept, with memory management removed, to satisfy any exiting
+// calls to it that rely on it.
+//
+// Users of glslang should call shFinalize() or glslang::FinalizeProcess() for
+// process-scoped memory tear down.
+bool DetachProcess()
+{
+ bool success = true;
+
+ if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+ return true;
+
+ success = DetachThread();
+
+ OS_FreeTLSIndex(ThreadInitializeIndex);
+ ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+ return success;
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/OGLCompilersDLL/InitializeDll.h b/thirdparty/glslang/OGLCompilersDLL/InitializeDll.h
new file mode 100644
index 0000000000..661cee4d24
--- /dev/null
+++ b/thirdparty/glslang/OGLCompilersDLL/InitializeDll.h
@@ -0,0 +1,49 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+#ifndef __INITIALIZEDLL_H
+#define __INITIALIZEDLL_H
+
+#include "../glslang/OSDependent/osinclude.h"
+
+namespace glslang {
+
+bool InitProcess();
+bool InitThread();
+bool DetachThread(); // not called from standalone, perhaps other tools rely on parts of it
+bool DetachProcess(); // not called from standalone, perhaps other tools rely on parts of it
+
+} // end namespace glslang
+
+#endif // __INITIALIZEDLL_H
+
diff --git a/thirdparty/glslang/SPIRV/GLSL.ext.AMD.h b/thirdparty/glslang/SPIRV/GLSL.ext.AMD.h
new file mode 100644
index 0000000000..009d2f1cf0
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/GLSL.ext.AMD.h
@@ -0,0 +1,108 @@
+/*
+** Copyright (c) 2014-2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and/or associated documentation files (the "Materials"),
+** to deal in the Materials without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute, sublicense,
+** and/or sell copies of the Materials, and to permit persons to whom the
+** Materials are furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Materials.
+**
+** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+** IN THE MATERIALS.
+*/
+
+#ifndef GLSLextAMD_H
+#define GLSLextAMD_H
+
+static const int GLSLextAMDVersion = 100;
+static const int GLSLextAMDRevision = 7;
+
+// SPV_AMD_shader_ballot
+static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot";
+
+enum ShaderBallotAMD {
+ ShaderBallotBadAMD = 0, // Don't use
+
+ SwizzleInvocationsAMD = 1,
+ SwizzleInvocationsMaskedAMD = 2,
+ WriteInvocationAMD = 3,
+ MbcntAMD = 4,
+
+ ShaderBallotCountAMD
+};
+
+// SPV_AMD_shader_trinary_minmax
+static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax";
+
+enum ShaderTrinaryMinMaxAMD {
+ ShaderTrinaryMinMaxBadAMD = 0, // Don't use
+
+ FMin3AMD = 1,
+ UMin3AMD = 2,
+ SMin3AMD = 3,
+ FMax3AMD = 4,
+ UMax3AMD = 5,
+ SMax3AMD = 6,
+ FMid3AMD = 7,
+ UMid3AMD = 8,
+ SMid3AMD = 9,
+
+ ShaderTrinaryMinMaxCountAMD
+};
+
+// SPV_AMD_shader_explicit_vertex_parameter
+static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter";
+
+enum ShaderExplicitVertexParameterAMD {
+ ShaderExplicitVertexParameterBadAMD = 0, // Don't use
+
+ InterpolateAtVertexAMD = 1,
+
+ ShaderExplicitVertexParameterCountAMD
+};
+
+// SPV_AMD_gcn_shader
+static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader";
+
+enum GcnShaderAMD {
+ GcnShaderBadAMD = 0, // Don't use
+
+ CubeFaceIndexAMD = 1,
+ CubeFaceCoordAMD = 2,
+ TimeAMD = 3,
+
+ GcnShaderCountAMD
+};
+
+// SPV_AMD_gpu_shader_half_float
+static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float";
+
+// SPV_AMD_texture_gather_bias_lod
+static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod";
+
+// SPV_AMD_gpu_shader_int16
+static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16";
+
+// SPV_AMD_shader_image_load_store_lod
+static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod";
+
+// SPV_AMD_shader_fragment_mask
+static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask";
+
+// SPV_AMD_gpu_shader_half_float_fetch
+static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch";
+
+#endif // #ifndef GLSLextAMD_H
diff --git a/thirdparty/glslang/SPIRV/GLSL.ext.EXT.h b/thirdparty/glslang/SPIRV/GLSL.ext.EXT.h
new file mode 100644
index 0000000000..40164b6187
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/GLSL.ext.EXT.h
@@ -0,0 +1,39 @@
+/*
+** Copyright (c) 2014-2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and/or associated documentation files (the "Materials"),
+** to deal in the Materials without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute, sublicense,
+** and/or sell copies of the Materials, and to permit persons to whom the
+** Materials are furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Materials.
+**
+** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+** IN THE MATERIALS.
+*/
+
+#ifndef GLSLextEXT_H
+#define GLSLextEXT_H
+
+static const int GLSLextEXTVersion = 100;
+static const int GLSLextEXTRevision = 2;
+
+static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export";
+static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer";
+static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered";
+static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
+static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
+
+#endif // #ifndef GLSLextEXT_H
diff --git a/thirdparty/glslang/SPIRV/GLSL.ext.KHR.h b/thirdparty/glslang/SPIRV/GLSL.ext.KHR.h
new file mode 100644
index 0000000000..e58e836a8d
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/GLSL.ext.KHR.h
@@ -0,0 +1,48 @@
+/*
+** Copyright (c) 2014-2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and/or associated documentation files (the "Materials"),
+** to deal in the Materials without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute, sublicense,
+** and/or sell copies of the Materials, and to permit persons to whom the
+** Materials are furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Materials.
+**
+** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+** IN THE MATERIALS.
+*/
+
+#ifndef GLSLextKHR_H
+#define GLSLextKHR_H
+
+static const int GLSLextKHRVersion = 100;
+static const int GLSLextKHRRevision = 2;
+
+static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot";
+static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote";
+static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group";
+static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview";
+static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters";
+static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage";
+static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage";
+static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class";
+static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage";
+static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model";
+static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer";
+static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer";
+static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock";
+static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock";
+
+#endif // #ifndef GLSLextKHR_H
diff --git a/thirdparty/glslang/SPIRV/GLSL.ext.NV.h b/thirdparty/glslang/SPIRV/GLSL.ext.NV.h
new file mode 100644
index 0000000000..50146da104
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/GLSL.ext.NV.h
@@ -0,0 +1,81 @@
+/*
+** Copyright (c) 2014-2017 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and/or associated documentation files (the "Materials"),
+** to deal in the Materials without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute, sublicense,
+** and/or sell copies of the Materials, and to permit persons to whom the
+** Materials are furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Materials.
+**
+** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+** IN THE MATERIALS.
+*/
+
+#ifndef GLSLextNV_H
+#define GLSLextNV_H
+
+enum BuiltIn;
+enum Decoration;
+enum Op;
+enum Capability;
+
+static const int GLSLextNVVersion = 100;
+static const int GLSLextNVRevision = 11;
+
+//SPV_NV_sample_mask_override_coverage
+const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage";
+
+//SPV_NV_geometry_shader_passthrough
+const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough";
+
+//SPV_NV_viewport_array2
+const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2";
+const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array";
+
+//SPV_NV_stereo_view_rendering
+const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering";
+
+//SPV_NVX_multiview_per_view_attributes
+const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes";
+
+//SPV_NV_shader_subgroup_partitioned
+const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned";
+
+//SPV_NV_fragment_shader_barycentric
+const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric";
+
+//SPV_NV_compute_shader_derivatives
+const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives";
+
+//SPV_NV_shader_image_footprint
+const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint";
+
+//SPV_NV_mesh_shader
+const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader";
+
+//SPV_NV_raytracing
+const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing";
+
+//SPV_NV_shading_rate
+const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate";
+
+//SPV_NV_cooperative_matrix
+const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix";
+
+//SPV_NV_shader_sm_builtins
+const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins";
+
+#endif // #ifndef GLSLextNV_H
diff --git a/thirdparty/glslang/SPIRV/GLSL.std.450.h b/thirdparty/glslang/SPIRV/GLSL.std.450.h
new file mode 100644
index 0000000000..df31092bec
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/GLSL.std.450.h
@@ -0,0 +1,131 @@
+/*
+** Copyright (c) 2014-2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and/or associated documentation files (the "Materials"),
+** to deal in the Materials without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute, sublicense,
+** and/or sell copies of the Materials, and to permit persons to whom the
+** Materials are furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Materials.
+**
+** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+** IN THE MATERIALS.
+*/
+
+#ifndef GLSLstd450_H
+#define GLSLstd450_H
+
+static const int GLSLstd450Version = 100;
+static const int GLSLstd450Revision = 1;
+
+enum GLSLstd450 {
+ GLSLstd450Bad = 0, // Don't use
+
+ GLSLstd450Round = 1,
+ GLSLstd450RoundEven = 2,
+ GLSLstd450Trunc = 3,
+ GLSLstd450FAbs = 4,
+ GLSLstd450SAbs = 5,
+ GLSLstd450FSign = 6,
+ GLSLstd450SSign = 7,
+ GLSLstd450Floor = 8,
+ GLSLstd450Ceil = 9,
+ GLSLstd450Fract = 10,
+
+ GLSLstd450Radians = 11,
+ GLSLstd450Degrees = 12,
+ GLSLstd450Sin = 13,
+ GLSLstd450Cos = 14,
+ GLSLstd450Tan = 15,
+ GLSLstd450Asin = 16,
+ GLSLstd450Acos = 17,
+ GLSLstd450Atan = 18,
+ GLSLstd450Sinh = 19,
+ GLSLstd450Cosh = 20,
+ GLSLstd450Tanh = 21,
+ GLSLstd450Asinh = 22,
+ GLSLstd450Acosh = 23,
+ GLSLstd450Atanh = 24,
+ GLSLstd450Atan2 = 25,
+
+ GLSLstd450Pow = 26,
+ GLSLstd450Exp = 27,
+ GLSLstd450Log = 28,
+ GLSLstd450Exp2 = 29,
+ GLSLstd450Log2 = 30,
+ GLSLstd450Sqrt = 31,
+ GLSLstd450InverseSqrt = 32,
+
+ GLSLstd450Determinant = 33,
+ GLSLstd450MatrixInverse = 34,
+
+ GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
+ GLSLstd450ModfStruct = 36, // no OpVariable operand
+ GLSLstd450FMin = 37,
+ GLSLstd450UMin = 38,
+ GLSLstd450SMin = 39,
+ GLSLstd450FMax = 40,
+ GLSLstd450UMax = 41,
+ GLSLstd450SMax = 42,
+ GLSLstd450FClamp = 43,
+ GLSLstd450UClamp = 44,
+ GLSLstd450SClamp = 45,
+ GLSLstd450FMix = 46,
+ GLSLstd450IMix = 47, // Reserved
+ GLSLstd450Step = 48,
+ GLSLstd450SmoothStep = 49,
+
+ GLSLstd450Fma = 50,
+ GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to
+ GLSLstd450FrexpStruct = 52, // no OpVariable operand
+ GLSLstd450Ldexp = 53,
+
+ GLSLstd450PackSnorm4x8 = 54,
+ GLSLstd450PackUnorm4x8 = 55,
+ GLSLstd450PackSnorm2x16 = 56,
+ GLSLstd450PackUnorm2x16 = 57,
+ GLSLstd450PackHalf2x16 = 58,
+ GLSLstd450PackDouble2x32 = 59,
+ GLSLstd450UnpackSnorm2x16 = 60,
+ GLSLstd450UnpackUnorm2x16 = 61,
+ GLSLstd450UnpackHalf2x16 = 62,
+ GLSLstd450UnpackSnorm4x8 = 63,
+ GLSLstd450UnpackUnorm4x8 = 64,
+ GLSLstd450UnpackDouble2x32 = 65,
+
+ GLSLstd450Length = 66,
+ GLSLstd450Distance = 67,
+ GLSLstd450Cross = 68,
+ GLSLstd450Normalize = 69,
+ GLSLstd450FaceForward = 70,
+ GLSLstd450Reflect = 71,
+ GLSLstd450Refract = 72,
+
+ GLSLstd450FindILsb = 73,
+ GLSLstd450FindSMsb = 74,
+ GLSLstd450FindUMsb = 75,
+
+ GLSLstd450InterpolateAtCentroid = 76,
+ GLSLstd450InterpolateAtSample = 77,
+ GLSLstd450InterpolateAtOffset = 78,
+
+ GLSLstd450NMin = 79,
+ GLSLstd450NMax = 80,
+ GLSLstd450NClamp = 81,
+
+ GLSLstd450Count
+};
+
+#endif // #ifndef GLSLstd450_H
diff --git a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp
new file mode 100755
index 0000000000..0c8a87e3ce
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp
@@ -0,0 +1,8361 @@
+//
+// Copyright (C) 2014-2016 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Visit the nodes in the glslang intermediate tree representation to
+// translate them to SPIR-V.
+//
+
+#include "spirv.hpp"
+#include "GlslangToSpv.h"
+#include "SpvBuilder.h"
+namespace spv {
+ #include "GLSL.std.450.h"
+ #include "GLSL.ext.KHR.h"
+ #include "GLSL.ext.EXT.h"
+ #include "GLSL.ext.AMD.h"
+ #include "GLSL.ext.NV.h"
+}
+
+// Glslang includes
+#include "../glslang/MachineIndependent/localintermediate.h"
+#include "../glslang/MachineIndependent/SymbolTable.h"
+#include "../glslang/Include/Common.h"
+#include "../glslang/Include/revision.h"
+
+#include <fstream>
+#include <iomanip>
+#include <list>
+#include <map>
+#include <stack>
+#include <string>
+#include <vector>
+
+namespace {
+
+namespace {
+class SpecConstantOpModeGuard {
+public:
+ SpecConstantOpModeGuard(spv::Builder* builder)
+ : builder_(builder) {
+ previous_flag_ = builder->isInSpecConstCodeGenMode();
+ }
+ ~SpecConstantOpModeGuard() {
+ previous_flag_ ? builder_->setToSpecConstCodeGenMode()
+ : builder_->setToNormalCodeGenMode();
+ }
+ void turnOnSpecConstantOpMode() {
+ builder_->setToSpecConstCodeGenMode();
+ }
+
+private:
+ spv::Builder* builder_;
+ bool previous_flag_;
+};
+
+struct OpDecorations {
+ public:
+ OpDecorations(spv::Decoration precision, spv::Decoration noContraction, spv::Decoration nonUniform) :
+ precision(precision)
+#ifndef GLSLANG_WEB
+ ,
+ noContraction(noContraction),
+ nonUniform(nonUniform)
+#endif
+ { }
+
+ spv::Decoration precision;
+
+#ifdef GLSLANG_WEB
+ void addNoContraction(spv::Builder&, spv::Id) const { }
+ void addNonUniform(spv::Builder&, spv::Id) const { }
+#else
+ void addNoContraction(spv::Builder& builder, spv::Id t) { builder.addDecoration(t, noContraction); }
+ void addNonUniform(spv::Builder& builder, spv::Id t) { builder.addDecoration(t, nonUniform); }
+ protected:
+ spv::Decoration noContraction;
+ spv::Decoration nonUniform;
+#endif
+
+};
+
+} // namespace
+
+//
+// The main holder of information for translating glslang to SPIR-V.
+//
+// Derives from the AST walking base class.
+//
+class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
+public:
+ TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate*, spv::SpvBuildLogger* logger,
+ glslang::SpvOptions& options);
+ virtual ~TGlslangToSpvTraverser() { }
+
+ bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*);
+ bool visitBinary(glslang::TVisit, glslang::TIntermBinary*);
+ void visitConstantUnion(glslang::TIntermConstantUnion*);
+ bool visitSelection(glslang::TVisit, glslang::TIntermSelection*);
+ bool visitSwitch(glslang::TVisit, glslang::TIntermSwitch*);
+ void visitSymbol(glslang::TIntermSymbol* symbol);
+ bool visitUnary(glslang::TVisit, glslang::TIntermUnary*);
+ bool visitLoop(glslang::TVisit, glslang::TIntermLoop*);
+ bool visitBranch(glslang::TVisit visit, glslang::TIntermBranch*);
+
+ void finishSpv();
+ void dumpSpv(std::vector<unsigned int>& out);
+
+protected:
+ TGlslangToSpvTraverser(TGlslangToSpvTraverser&);
+ TGlslangToSpvTraverser& operator=(TGlslangToSpvTraverser&);
+
+ spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier);
+ spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
+ spv::Decoration TranslateNonUniformDecoration(const glslang::TQualifier& qualifier);
+ spv::Builder::AccessChain::CoherentFlags TranslateCoherent(const glslang::TType& type);
+ spv::MemoryAccessMask TranslateMemoryAccess(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
+ spv::ImageOperandsMask TranslateImageOperands(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
+ spv::Scope TranslateMemoryScope(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
+ spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
+ spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
+ spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const;
+ spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const;
+ spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, std::vector<unsigned int>& operands) const;
+ spv::StorageClass TranslateStorageClass(const glslang::TType&);
+ void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType);
+ spv::Id createSpvVariable(const glslang::TIntermSymbol*, spv::Id forcedType);
+ spv::Id getSampledType(const glslang::TSampler&);
+ spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&);
+ spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult);
+ void convertSwizzle(const glslang::TIntermAggregate&, std::vector<unsigned>& swizzle);
+ spv::Id convertGlslangToSpvType(const glslang::TType& type, bool forwardReferenceOnly = false);
+ spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&,
+ bool lastBufferBlockMember, bool forwardReferenceOnly = false);
+ bool filterMember(const glslang::TType& member);
+ spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct,
+ glslang::TLayoutPacking, const glslang::TQualifier&);
+ void decorateStructType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking,
+ const glslang::TQualifier&, spv::Id);
+ spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim);
+ spv::Id accessChainLoad(const glslang::TType& type);
+ void accessChainStore(const glslang::TType& type, spv::Id rvalue);
+ void multiTypeStore(const glslang::TType&, spv::Id rValue);
+ glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
+ int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
+ int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
+ void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset,
+ int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix);
+ void declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember);
+
+ bool isShaderEntryPoint(const glslang::TIntermAggregate* node);
+ bool writableParam(glslang::TStorageQualifier) const;
+ bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam);
+ void makeFunctions(const glslang::TIntermSequence&);
+ void makeGlobalInitializers(const glslang::TIntermSequence&);
+ void visitFunctions(const glslang::TIntermSequence&);
+ void handleFunctionEntry(const glslang::TIntermAggregate* node);
+ void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
+ void translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments);
+ spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
+ spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
+
+ spv::Id createBinaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right,
+ glslang::TBasicType typeProxy, bool reduceComparison = true);
+ spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right);
+ spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand,
+ glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
+ spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand,
+ glslang::TBasicType typeProxy);
+ spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand,
+ glslang::TBasicType typeProxy);
+ spv::Id createIntWidthConversion(glslang::TOperator op, spv::Id operand, int vectorSize);
+ spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
+ spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
+ spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
+ spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector<spv::Id>& operands);
+ spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
+ spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
+ spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId);
+ spv::Id getSymbolId(const glslang::TIntermSymbol* node);
+ void addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier & qualifier);
+ spv::Id createSpvConstant(const glslang::TIntermTyped&);
+ spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
+ bool isTrivialLeaf(const glslang::TIntermTyped* node);
+ bool isTrivial(const glslang::TIntermTyped* node);
+ spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
+ spv::Id getExtBuiltins(const char* name);
+ std::pair<spv::Id, spv::Id> getForcedType(spv::BuiltIn, const glslang::TType&);
+ spv::Id translateForcedType(spv::Id object);
+ spv::Id createCompositeConstruct(spv::Id typeId, std::vector<spv::Id> constituents);
+
+ glslang::SpvOptions& options;
+ spv::Function* shaderEntry;
+ spv::Function* currentFunction;
+ spv::Instruction* entryPoint;
+ int sequenceDepth;
+
+ spv::SpvBuildLogger* logger;
+
+ // There is a 1:1 mapping between a spv builder and a module; this is thread safe
+ spv::Builder builder;
+ bool inEntryPoint;
+ bool entryPointTerminated;
+ bool linkageOnly; // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used
+ std::set<spv::Id> iOSet; // all input/output variables from either static use or declaration of interface
+ const glslang::TIntermediate* glslangIntermediate;
+ bool nanMinMaxClamp; // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp
+ spv::Id stdBuiltins;
+ std::unordered_map<const char*, spv::Id> extBuiltinMap;
+
+ std::unordered_map<int, spv::Id> symbolValues;
+ std::unordered_set<int> rValueParameters; // set of formal function parameters passed as rValues, rather than a pointer
+ std::unordered_map<std::string, spv::Function*> functionMap;
+ std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
+ // for mapping glslang block indices to spv indices (e.g., due to hidden members):
+ std::unordered_map<int, std::vector<int>> memberRemapper;
+ // for mapping glslang symbol struct to symbol Id
+ std::unordered_map<const glslang::TTypeList*, int> glslangTypeToIdMap;
+ std::stack<bool> breakForLoop; // false means break for switch
+ std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator;
+ // Map pointee types for EbtReference to their forward pointers
+ std::map<const glslang::TType *, spv::Id> forwardPointers;
+ // Type forcing, for when SPIR-V wants a different type than the AST,
+ // requiring local translation to and from SPIR-V type on every access.
+ // Maps <builtin-variable-id -> AST-required-type-id>
+ std::unordered_map<spv::Id, spv::Id> forceType;
+};
+
+//
+// Helper functions for translating glslang representations to SPIR-V enumerants.
+//
+
+// Translate glslang profile to SPIR-V source language.
+spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile profile)
+{
+#ifdef GLSLANG_WEB
+ return spv::SourceLanguageESSL;
+#endif
+
+ switch (source) {
+ case glslang::EShSourceGlsl:
+ switch (profile) {
+ case ENoProfile:
+ case ECoreProfile:
+ case ECompatibilityProfile:
+ return spv::SourceLanguageGLSL;
+ case EEsProfile:
+ return spv::SourceLanguageESSL;
+ default:
+ return spv::SourceLanguageUnknown;
+ }
+ case glslang::EShSourceHlsl:
+ return spv::SourceLanguageHLSL;
+ default:
+ return spv::SourceLanguageUnknown;
+ }
+}
+
+// Translate glslang language (stage) to SPIR-V execution model.
+spv::ExecutionModel TranslateExecutionModel(EShLanguage stage)
+{
+ switch (stage) {
+ case EShLangVertex: return spv::ExecutionModelVertex;
+ case EShLangFragment: return spv::ExecutionModelFragment;
+ case EShLangCompute: return spv::ExecutionModelGLCompute;
+#ifndef GLSLANG_WEB
+ case EShLangTessControl: return spv::ExecutionModelTessellationControl;
+ case EShLangTessEvaluation: return spv::ExecutionModelTessellationEvaluation;
+ case EShLangGeometry: return spv::ExecutionModelGeometry;
+ case EShLangRayGenNV: return spv::ExecutionModelRayGenerationNV;
+ case EShLangIntersectNV: return spv::ExecutionModelIntersectionNV;
+ case EShLangAnyHitNV: return spv::ExecutionModelAnyHitNV;
+ case EShLangClosestHitNV: return spv::ExecutionModelClosestHitNV;
+ case EShLangMissNV: return spv::ExecutionModelMissNV;
+ case EShLangCallableNV: return spv::ExecutionModelCallableNV;
+ case EShLangTaskNV: return spv::ExecutionModelTaskNV;
+ case EShLangMeshNV: return spv::ExecutionModelMeshNV;
+#endif
+ default:
+ assert(0);
+ return spv::ExecutionModelFragment;
+ }
+}
+
+// Translate glslang sampler type to SPIR-V dimensionality.
+spv::Dim TranslateDimensionality(const glslang::TSampler& sampler)
+{
+ switch (sampler.dim) {
+ case glslang::Esd1D: return spv::Dim1D;
+ case glslang::Esd2D: return spv::Dim2D;
+ case glslang::Esd3D: return spv::Dim3D;
+ case glslang::EsdCube: return spv::DimCube;
+ case glslang::EsdRect: return spv::DimRect;
+ case glslang::EsdBuffer: return spv::DimBuffer;
+ case glslang::EsdSubpass: return spv::DimSubpassData;
+ default:
+ assert(0);
+ return spv::Dim2D;
+ }
+}
+
+// Translate glslang precision to SPIR-V precision decorations.
+spv::Decoration TranslatePrecisionDecoration(glslang::TPrecisionQualifier glslangPrecision)
+{
+ switch (glslangPrecision) {
+ case glslang::EpqLow: return spv::DecorationRelaxedPrecision;
+ case glslang::EpqMedium: return spv::DecorationRelaxedPrecision;
+ default:
+ return spv::NoPrecision;
+ }
+}
+
+// Translate glslang type to SPIR-V precision decorations.
+spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type)
+{
+ return TranslatePrecisionDecoration(type.getQualifier().precision);
+}
+
+// Translate glslang type to SPIR-V block decorations.
+spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useStorageBuffer)
+{
+ if (type.getBasicType() == glslang::EbtBlock) {
+ switch (type.getQualifier().storage) {
+ case glslang::EvqUniform: return spv::DecorationBlock;
+ case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock;
+ case glslang::EvqVaryingIn: return spv::DecorationBlock;
+ case glslang::EvqVaryingOut: return spv::DecorationBlock;
+#ifndef GLSLANG_WEB
+ case glslang::EvqPayloadNV: return spv::DecorationBlock;
+ case glslang::EvqPayloadInNV: return spv::DecorationBlock;
+ case glslang::EvqHitAttrNV: return spv::DecorationBlock;
+ case glslang::EvqCallableDataNV: return spv::DecorationBlock;
+ case glslang::EvqCallableDataInNV: return spv::DecorationBlock;
+#endif
+ default:
+ assert(0);
+ break;
+ }
+ }
+
+ return spv::DecorationMax;
+}
+
+// Translate glslang type to SPIR-V memory decorations.
+void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory, bool useVulkanMemoryModel)
+{
+ if (!useVulkanMemoryModel) {
+ if (qualifier.isCoherent())
+ memory.push_back(spv::DecorationCoherent);
+ if (qualifier.isVolatile()) {
+ memory.push_back(spv::DecorationVolatile);
+ memory.push_back(spv::DecorationCoherent);
+ }
+ }
+ if (qualifier.isRestrict())
+ memory.push_back(spv::DecorationRestrict);
+ if (qualifier.isReadOnly())
+ memory.push_back(spv::DecorationNonWritable);
+ if (qualifier.isWriteOnly())
+ memory.push_back(spv::DecorationNonReadable);
+}
+
+// Translate glslang type to SPIR-V layout decorations.
+spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout)
+{
+ if (type.isMatrix()) {
+ switch (matrixLayout) {
+ case glslang::ElmRowMajor:
+ return spv::DecorationRowMajor;
+ case glslang::ElmColumnMajor:
+ return spv::DecorationColMajor;
+ default:
+ // opaque layouts don't need a majorness
+ return spv::DecorationMax;
+ }
+ } else {
+ switch (type.getBasicType()) {
+ default:
+ return spv::DecorationMax;
+ break;
+ case glslang::EbtBlock:
+ switch (type.getQualifier().storage) {
+ case glslang::EvqUniform:
+ case glslang::EvqBuffer:
+ switch (type.getQualifier().layoutPacking) {
+ case glslang::ElpShared: return spv::DecorationGLSLShared;
+ case glslang::ElpPacked: return spv::DecorationGLSLPacked;
+ default:
+ return spv::DecorationMax;
+ }
+ case glslang::EvqVaryingIn:
+ case glslang::EvqVaryingOut:
+ if (type.getQualifier().isTaskMemory()) {
+ switch (type.getQualifier().layoutPacking) {
+ case glslang::ElpShared: return spv::DecorationGLSLShared;
+ case glslang::ElpPacked: return spv::DecorationGLSLPacked;
+ default: break;
+ }
+ } else {
+ assert(type.getQualifier().layoutPacking == glslang::ElpNone);
+ }
+ return spv::DecorationMax;
+#ifndef GLSLANG_WEB
+ case glslang::EvqPayloadNV:
+ case glslang::EvqPayloadInNV:
+ case glslang::EvqHitAttrNV:
+ case glslang::EvqCallableDataNV:
+ case glslang::EvqCallableDataInNV:
+ return spv::DecorationMax;
+#endif
+ default:
+ assert(0);
+ return spv::DecorationMax;
+ }
+ }
+ }
+}
+
+// Translate glslang type to SPIR-V interpolation decorations.
+// Returns spv::DecorationMax when no decoration
+// should be applied.
+spv::Decoration TGlslangToSpvTraverser::TranslateInterpolationDecoration(const glslang::TQualifier& qualifier)
+{
+ if (qualifier.smooth)
+ // Smooth decoration doesn't exist in SPIR-V 1.0
+ return spv::DecorationMax;
+ else if (qualifier.isNonPerspective())
+ return spv::DecorationNoPerspective;
+ else if (qualifier.flat)
+ return spv::DecorationFlat;
+ else if (qualifier.isExplicitInterpolation()) {
+ builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
+ return spv::DecorationExplicitInterpAMD;
+ }
+ else
+ return spv::DecorationMax;
+}
+
+// Translate glslang type to SPIR-V auxiliary storage decorations.
+// Returns spv::DecorationMax when no decoration
+// should be applied.
+spv::Decoration TGlslangToSpvTraverser::TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier)
+{
+ if (qualifier.centroid)
+ return spv::DecorationCentroid;
+#ifndef GLSLANG_WEB
+ else if (qualifier.patch)
+ return spv::DecorationPatch;
+ else if (qualifier.sample) {
+ builder.addCapability(spv::CapabilitySampleRateShading);
+ return spv::DecorationSample;
+ }
+#endif
+
+ return spv::DecorationMax;
+}
+
+// If glslang type is invariant, return SPIR-V invariant decoration.
+spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifier)
+{
+ if (qualifier.invariant)
+ return spv::DecorationInvariant;
+ else
+ return spv::DecorationMax;
+}
+
+// If glslang type is noContraction, return SPIR-V NoContraction decoration.
+spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qualifier)
+{
+#ifndef GLSLANG_WEB
+ if (qualifier.isNoContraction())
+ return spv::DecorationNoContraction;
+ else
+#endif
+ return spv::DecorationMax;
+}
+
+// If glslang type is nonUniform, return SPIR-V NonUniform decoration.
+spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glslang::TQualifier& qualifier)
+{
+#ifndef GLSLANG_WEB
+ if (qualifier.isNonUniform()) {
+ builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityShaderNonUniformEXT);
+ return spv::DecorationNonUniformEXT;
+ } else
+#endif
+ return spv::DecorationMax;
+}
+
+spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess(
+ const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
+{
+ spv::MemoryAccessMask mask = spv::MemoryAccessMaskNone;
+
+#ifndef GLSLANG_WEB
+ if (!glslangIntermediate->usingVulkanMemoryModel() || coherentFlags.isImage)
+ return mask;
+
+ if (coherentFlags.volatil ||
+ coherentFlags.coherent ||
+ coherentFlags.devicecoherent ||
+ coherentFlags.queuefamilycoherent ||
+ coherentFlags.workgroupcoherent ||
+ coherentFlags.subgroupcoherent) {
+ mask = mask | spv::MemoryAccessMakePointerAvailableKHRMask |
+ spv::MemoryAccessMakePointerVisibleKHRMask;
+ }
+ if (coherentFlags.nonprivate) {
+ mask = mask | spv::MemoryAccessNonPrivatePointerKHRMask;
+ }
+ if (coherentFlags.volatil) {
+ mask = mask | spv::MemoryAccessVolatileMask;
+ }
+ if (mask != spv::MemoryAccessMaskNone) {
+ builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
+ }
+#endif
+
+ return mask;
+}
+
+spv::ImageOperandsMask TGlslangToSpvTraverser::TranslateImageOperands(
+ const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
+{
+ spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone;
+
+#ifndef GLSLANG_WEB
+ if (!glslangIntermediate->usingVulkanMemoryModel())
+ return mask;
+
+ if (coherentFlags.volatil ||
+ coherentFlags.coherent ||
+ coherentFlags.devicecoherent ||
+ coherentFlags.queuefamilycoherent ||
+ coherentFlags.workgroupcoherent ||
+ coherentFlags.subgroupcoherent) {
+ mask = mask | spv::ImageOperandsMakeTexelAvailableKHRMask |
+ spv::ImageOperandsMakeTexelVisibleKHRMask;
+ }
+ if (coherentFlags.nonprivate) {
+ mask = mask | spv::ImageOperandsNonPrivateTexelKHRMask;
+ }
+ if (coherentFlags.volatil) {
+ mask = mask | spv::ImageOperandsVolatileTexelKHRMask;
+ }
+ if (mask != spv::ImageOperandsMaskNone) {
+ builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
+ }
+#endif
+
+ return mask;
+}
+
+spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCoherent(const glslang::TType& type)
+{
+ spv::Builder::AccessChain::CoherentFlags flags = {};
+#ifndef GLSLANG_WEB
+ flags.coherent = type.getQualifier().coherent;
+ flags.devicecoherent = type.getQualifier().devicecoherent;
+ flags.queuefamilycoherent = type.getQualifier().queuefamilycoherent;
+ // shared variables are implicitly workgroupcoherent in GLSL.
+ flags.workgroupcoherent = type.getQualifier().workgroupcoherent ||
+ type.getQualifier().storage == glslang::EvqShared;
+ flags.subgroupcoherent = type.getQualifier().subgroupcoherent;
+ flags.volatil = type.getQualifier().volatil;
+ // *coherent variables are implicitly nonprivate in GLSL
+ flags.nonprivate = type.getQualifier().nonprivate ||
+ flags.subgroupcoherent ||
+ flags.workgroupcoherent ||
+ flags.queuefamilycoherent ||
+ flags.devicecoherent ||
+ flags.coherent ||
+ flags.volatil;
+ flags.isImage = type.getBasicType() == glslang::EbtSampler;
+#endif
+ return flags;
+}
+
+spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope(
+ const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
+{
+ spv::Scope scope = spv::ScopeMax;
+
+#ifndef GLSLANG_WEB
+ if (coherentFlags.volatil || coherentFlags.coherent) {
+ // coherent defaults to Device scope in the old model, QueueFamilyKHR scope in the new model
+ scope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice;
+ } else if (coherentFlags.devicecoherent) {
+ scope = spv::ScopeDevice;
+ } else if (coherentFlags.queuefamilycoherent) {
+ scope = spv::ScopeQueueFamilyKHR;
+ } else if (coherentFlags.workgroupcoherent) {
+ scope = spv::ScopeWorkgroup;
+ } else if (coherentFlags.subgroupcoherent) {
+ scope = spv::ScopeSubgroup;
+ }
+ if (glslangIntermediate->usingVulkanMemoryModel() && scope == spv::ScopeDevice) {
+ builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
+ }
+#endif
+
+ return scope;
+}
+
+// Translate a glslang built-in variable to a SPIR-V built in decoration. Also generate
+// associated capabilities when required. For some built-in variables, a capability
+// is generated only when using the variable in an executable instruction, but not when
+// just declaring a struct member variable with it. This is true for PointSize,
+// ClipDistance, and CullDistance.
+spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool memberDeclaration)
+{
+ switch (builtIn) {
+ case glslang::EbvPointSize:
+#ifndef GLSLANG_WEB
+ // Defer adding the capability until the built-in is actually used.
+ if (! memberDeclaration) {
+ switch (glslangIntermediate->getStage()) {
+ case EShLangGeometry:
+ builder.addCapability(spv::CapabilityGeometryPointSize);
+ break;
+ case EShLangTessControl:
+ case EShLangTessEvaluation:
+ builder.addCapability(spv::CapabilityTessellationPointSize);
+ break;
+ default:
+ break;
+ }
+ }
+#endif
+ return spv::BuiltInPointSize;
+
+ case glslang::EbvPosition: return spv::BuiltInPosition;
+ case glslang::EbvVertexId: return spv::BuiltInVertexId;
+ case glslang::EbvInstanceId: return spv::BuiltInInstanceId;
+ case glslang::EbvVertexIndex: return spv::BuiltInVertexIndex;
+ case glslang::EbvInstanceIndex: return spv::BuiltInInstanceIndex;
+
+ case glslang::EbvFragCoord: return spv::BuiltInFragCoord;
+ case glslang::EbvPointCoord: return spv::BuiltInPointCoord;
+ case glslang::EbvFace: return spv::BuiltInFrontFacing;
+ case glslang::EbvFragDepth: return spv::BuiltInFragDepth;
+
+ case glslang::EbvNumWorkGroups: return spv::BuiltInNumWorkgroups;
+ case glslang::EbvWorkGroupSize: return spv::BuiltInWorkgroupSize;
+ case glslang::EbvWorkGroupId: return spv::BuiltInWorkgroupId;
+ case glslang::EbvLocalInvocationId: return spv::BuiltInLocalInvocationId;
+ case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex;
+ case glslang::EbvGlobalInvocationId: return spv::BuiltInGlobalInvocationId;
+
+#ifndef GLSLANG_WEB
+ // These *Distance capabilities logically belong here, but if the member is declared and
+ // then never used, consumers of SPIR-V prefer the capability not be declared.
+ // They are now generated when used, rather than here when declared.
+ // Potentially, the specification should be more clear what the minimum
+ // use needed is to trigger the capability.
+ //
+ case glslang::EbvClipDistance:
+ if (!memberDeclaration)
+ builder.addCapability(spv::CapabilityClipDistance);
+ return spv::BuiltInClipDistance;
+
+ case glslang::EbvCullDistance:
+ if (!memberDeclaration)
+ builder.addCapability(spv::CapabilityCullDistance);
+ return spv::BuiltInCullDistance;
+
+ case glslang::EbvViewportIndex:
+ builder.addCapability(spv::CapabilityMultiViewport);
+ if (glslangIntermediate->getStage() == EShLangVertex ||
+ glslangIntermediate->getStage() == EShLangTessControl ||
+ glslangIntermediate->getStage() == EShLangTessEvaluation) {
+
+ builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
+ }
+ return spv::BuiltInViewportIndex;
+
+ case glslang::EbvSampleId:
+ builder.addCapability(spv::CapabilitySampleRateShading);
+ return spv::BuiltInSampleId;
+
+ case glslang::EbvSamplePosition:
+ builder.addCapability(spv::CapabilitySampleRateShading);
+ return spv::BuiltInSamplePosition;
+
+ case glslang::EbvSampleMask:
+ return spv::BuiltInSampleMask;
+
+ case glslang::EbvLayer:
+ if (glslangIntermediate->getStage() == EShLangMeshNV) {
+ return spv::BuiltInLayer;
+ }
+ builder.addCapability(spv::CapabilityGeometry);
+ if (glslangIntermediate->getStage() == EShLangVertex ||
+ glslangIntermediate->getStage() == EShLangTessControl ||
+ glslangIntermediate->getStage() == EShLangTessEvaluation) {
+
+ builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
+ }
+ return spv::BuiltInLayer;
+
+ case glslang::EbvBaseVertex:
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3);
+ builder.addCapability(spv::CapabilityDrawParameters);
+ return spv::BuiltInBaseVertex;
+
+ case glslang::EbvBaseInstance:
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3);
+ builder.addCapability(spv::CapabilityDrawParameters);
+ return spv::BuiltInBaseInstance;
+
+ case glslang::EbvDrawId:
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3);
+ builder.addCapability(spv::CapabilityDrawParameters);
+ return spv::BuiltInDrawIndex;
+
+ case glslang::EbvPrimitiveId:
+ if (glslangIntermediate->getStage() == EShLangFragment)
+ builder.addCapability(spv::CapabilityGeometry);
+ return spv::BuiltInPrimitiveId;
+
+ case glslang::EbvFragStencilRef:
+ builder.addExtension(spv::E_SPV_EXT_shader_stencil_export);
+ builder.addCapability(spv::CapabilityStencilExportEXT);
+ return spv::BuiltInFragStencilRefEXT;
+
+ case glslang::EbvInvocationId: return spv::BuiltInInvocationId;
+ case glslang::EbvTessLevelInner: return spv::BuiltInTessLevelInner;
+ case glslang::EbvTessLevelOuter: return spv::BuiltInTessLevelOuter;
+ case glslang::EbvTessCoord: return spv::BuiltInTessCoord;
+ case glslang::EbvPatchVertices: return spv::BuiltInPatchVertices;
+ case glslang::EbvHelperInvocation: return spv::BuiltInHelperInvocation;
+
+ case glslang::EbvSubGroupSize:
+ builder.addExtension(spv::E_SPV_KHR_shader_ballot);
+ builder.addCapability(spv::CapabilitySubgroupBallotKHR);
+ return spv::BuiltInSubgroupSize;
+
+ case glslang::EbvSubGroupInvocation:
+ builder.addExtension(spv::E_SPV_KHR_shader_ballot);
+ builder.addCapability(spv::CapabilitySubgroupBallotKHR);
+ return spv::BuiltInSubgroupLocalInvocationId;
+
+ case glslang::EbvSubGroupEqMask:
+ builder.addExtension(spv::E_SPV_KHR_shader_ballot);
+ builder.addCapability(spv::CapabilitySubgroupBallotKHR);
+ return spv::BuiltInSubgroupEqMask;
+
+ case glslang::EbvSubGroupGeMask:
+ builder.addExtension(spv::E_SPV_KHR_shader_ballot);
+ builder.addCapability(spv::CapabilitySubgroupBallotKHR);
+ return spv::BuiltInSubgroupGeMask;
+
+ case glslang::EbvSubGroupGtMask:
+ builder.addExtension(spv::E_SPV_KHR_shader_ballot);
+ builder.addCapability(spv::CapabilitySubgroupBallotKHR);
+ return spv::BuiltInSubgroupGtMask;
+
+ case glslang::EbvSubGroupLeMask:
+ builder.addExtension(spv::E_SPV_KHR_shader_ballot);
+ builder.addCapability(spv::CapabilitySubgroupBallotKHR);
+ return spv::BuiltInSubgroupLeMask;
+
+ case glslang::EbvSubGroupLtMask:
+ builder.addExtension(spv::E_SPV_KHR_shader_ballot);
+ builder.addCapability(spv::CapabilitySubgroupBallotKHR);
+ return spv::BuiltInSubgroupLtMask;
+
+ case glslang::EbvNumSubgroups:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ return spv::BuiltInNumSubgroups;
+
+ case glslang::EbvSubgroupID:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ return spv::BuiltInSubgroupId;
+
+ case glslang::EbvSubgroupSize2:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ return spv::BuiltInSubgroupSize;
+
+ case glslang::EbvSubgroupInvocation2:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ return spv::BuiltInSubgroupLocalInvocationId;
+
+ case glslang::EbvSubgroupEqMask2:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformBallot);
+ return spv::BuiltInSubgroupEqMask;
+
+ case glslang::EbvSubgroupGeMask2:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformBallot);
+ return spv::BuiltInSubgroupGeMask;
+
+ case glslang::EbvSubgroupGtMask2:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformBallot);
+ return spv::BuiltInSubgroupGtMask;
+
+ case glslang::EbvSubgroupLeMask2:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformBallot);
+ return spv::BuiltInSubgroupLeMask;
+
+ case glslang::EbvSubgroupLtMask2:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformBallot);
+ return spv::BuiltInSubgroupLtMask;
+
+ case glslang::EbvBaryCoordNoPersp:
+ builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
+ return spv::BuiltInBaryCoordNoPerspAMD;
+
+ case glslang::EbvBaryCoordNoPerspCentroid:
+ builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
+ return spv::BuiltInBaryCoordNoPerspCentroidAMD;
+
+ case glslang::EbvBaryCoordNoPerspSample:
+ builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
+ return spv::BuiltInBaryCoordNoPerspSampleAMD;
+
+ case glslang::EbvBaryCoordSmooth:
+ builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
+ return spv::BuiltInBaryCoordSmoothAMD;
+
+ case glslang::EbvBaryCoordSmoothCentroid:
+ builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
+ return spv::BuiltInBaryCoordSmoothCentroidAMD;
+
+ case glslang::EbvBaryCoordSmoothSample:
+ builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
+ return spv::BuiltInBaryCoordSmoothSampleAMD;
+
+ case glslang::EbvBaryCoordPullModel:
+ builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
+ return spv::BuiltInBaryCoordPullModelAMD;
+
+ case glslang::EbvDeviceIndex:
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_device_group, spv::Spv_1_3);
+ builder.addCapability(spv::CapabilityDeviceGroup);
+ return spv::BuiltInDeviceIndex;
+
+ case glslang::EbvViewIndex:
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_multiview, spv::Spv_1_3);
+ builder.addCapability(spv::CapabilityMultiView);
+ return spv::BuiltInViewIndex;
+
+ case glslang::EbvFragSizeEXT:
+ builder.addExtension(spv::E_SPV_EXT_fragment_invocation_density);
+ builder.addCapability(spv::CapabilityFragmentDensityEXT);
+ return spv::BuiltInFragSizeEXT;
+
+ case glslang::EbvFragInvocationCountEXT:
+ builder.addExtension(spv::E_SPV_EXT_fragment_invocation_density);
+ builder.addCapability(spv::CapabilityFragmentDensityEXT);
+ return spv::BuiltInFragInvocationCountEXT;
+
+ case glslang::EbvViewportMaskNV:
+ if (!memberDeclaration) {
+ builder.addExtension(spv::E_SPV_NV_viewport_array2);
+ builder.addCapability(spv::CapabilityShaderViewportMaskNV);
+ }
+ return spv::BuiltInViewportMaskNV;
+ case glslang::EbvSecondaryPositionNV:
+ if (!memberDeclaration) {
+ builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
+ builder.addCapability(spv::CapabilityShaderStereoViewNV);
+ }
+ return spv::BuiltInSecondaryPositionNV;
+ case glslang::EbvSecondaryViewportMaskNV:
+ if (!memberDeclaration) {
+ builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
+ builder.addCapability(spv::CapabilityShaderStereoViewNV);
+ }
+ return spv::BuiltInSecondaryViewportMaskNV;
+ case glslang::EbvPositionPerViewNV:
+ if (!memberDeclaration) {
+ builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes);
+ builder.addCapability(spv::CapabilityPerViewAttributesNV);
+ }
+ return spv::BuiltInPositionPerViewNV;
+ case glslang::EbvViewportMaskPerViewNV:
+ if (!memberDeclaration) {
+ builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes);
+ builder.addCapability(spv::CapabilityPerViewAttributesNV);
+ }
+ return spv::BuiltInViewportMaskPerViewNV;
+ case glslang::EbvFragFullyCoveredNV:
+ builder.addExtension(spv::E_SPV_EXT_fragment_fully_covered);
+ builder.addCapability(spv::CapabilityFragmentFullyCoveredEXT);
+ return spv::BuiltInFullyCoveredEXT;
+ case glslang::EbvFragmentSizeNV:
+ builder.addExtension(spv::E_SPV_NV_shading_rate);
+ builder.addCapability(spv::CapabilityShadingRateNV);
+ return spv::BuiltInFragmentSizeNV;
+ case glslang::EbvInvocationsPerPixelNV:
+ builder.addExtension(spv::E_SPV_NV_shading_rate);
+ builder.addCapability(spv::CapabilityShadingRateNV);
+ return spv::BuiltInInvocationsPerPixelNV;
+
+ // ray tracing
+ case glslang::EbvLaunchIdNV:
+ return spv::BuiltInLaunchIdNV;
+ case glslang::EbvLaunchSizeNV:
+ return spv::BuiltInLaunchSizeNV;
+ case glslang::EbvWorldRayOriginNV:
+ return spv::BuiltInWorldRayOriginNV;
+ case glslang::EbvWorldRayDirectionNV:
+ return spv::BuiltInWorldRayDirectionNV;
+ case glslang::EbvObjectRayOriginNV:
+ return spv::BuiltInObjectRayOriginNV;
+ case glslang::EbvObjectRayDirectionNV:
+ return spv::BuiltInObjectRayDirectionNV;
+ case glslang::EbvRayTminNV:
+ return spv::BuiltInRayTminNV;
+ case glslang::EbvRayTmaxNV:
+ return spv::BuiltInRayTmaxNV;
+ case glslang::EbvInstanceCustomIndexNV:
+ return spv::BuiltInInstanceCustomIndexNV;
+ case glslang::EbvHitTNV:
+ return spv::BuiltInHitTNV;
+ case glslang::EbvHitKindNV:
+ return spv::BuiltInHitKindNV;
+ case glslang::EbvObjectToWorldNV:
+ return spv::BuiltInObjectToWorldNV;
+ case glslang::EbvWorldToObjectNV:
+ return spv::BuiltInWorldToObjectNV;
+ case glslang::EbvIncomingRayFlagsNV:
+ return spv::BuiltInIncomingRayFlagsNV;
+
+ // barycentrics
+ case glslang::EbvBaryCoordNV:
+ builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric);
+ builder.addCapability(spv::CapabilityFragmentBarycentricNV);
+ return spv::BuiltInBaryCoordNV;
+ case glslang::EbvBaryCoordNoPerspNV:
+ builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric);
+ builder.addCapability(spv::CapabilityFragmentBarycentricNV);
+ return spv::BuiltInBaryCoordNoPerspNV;
+
+ // mesh shaders
+ case glslang::EbvTaskCountNV:
+ return spv::BuiltInTaskCountNV;
+ case glslang::EbvPrimitiveCountNV:
+ return spv::BuiltInPrimitiveCountNV;
+ case glslang::EbvPrimitiveIndicesNV:
+ return spv::BuiltInPrimitiveIndicesNV;
+ case glslang::EbvClipDistancePerViewNV:
+ return spv::BuiltInClipDistancePerViewNV;
+ case glslang::EbvCullDistancePerViewNV:
+ return spv::BuiltInCullDistancePerViewNV;
+ case glslang::EbvLayerPerViewNV:
+ return spv::BuiltInLayerPerViewNV;
+ case glslang::EbvMeshViewCountNV:
+ return spv::BuiltInMeshViewCountNV;
+ case glslang::EbvMeshViewIndicesNV:
+ return spv::BuiltInMeshViewIndicesNV;
+
+ // sm builtins
+ case glslang::EbvWarpsPerSM:
+ builder.addExtension(spv::E_SPV_NV_shader_sm_builtins);
+ builder.addCapability(spv::CapabilityShaderSMBuiltinsNV);
+ return spv::BuiltInWarpsPerSMNV;
+ case glslang::EbvSMCount:
+ builder.addExtension(spv::E_SPV_NV_shader_sm_builtins);
+ builder.addCapability(spv::CapabilityShaderSMBuiltinsNV);
+ return spv::BuiltInSMCountNV;
+ case glslang::EbvWarpID:
+ builder.addExtension(spv::E_SPV_NV_shader_sm_builtins);
+ builder.addCapability(spv::CapabilityShaderSMBuiltinsNV);
+ return spv::BuiltInWarpIDNV;
+ case glslang::EbvSMID:
+ builder.addExtension(spv::E_SPV_NV_shader_sm_builtins);
+ builder.addCapability(spv::CapabilityShaderSMBuiltinsNV);
+ return spv::BuiltInSMIDNV;
+#endif
+
+ default:
+ return spv::BuiltInMax;
+ }
+}
+
+// Translate glslang image layout format to SPIR-V image format.
+spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TType& type)
+{
+ assert(type.getBasicType() == glslang::EbtSampler);
+
+#ifdef GLSLANG_WEB
+ return spv::ImageFormatUnknown;
+#endif
+
+ // Check for capabilities
+ switch (type.getQualifier().getFormat()) {
+ case glslang::ElfRg32f:
+ case glslang::ElfRg16f:
+ case glslang::ElfR11fG11fB10f:
+ case glslang::ElfR16f:
+ case glslang::ElfRgba16:
+ case glslang::ElfRgb10A2:
+ case glslang::ElfRg16:
+ case glslang::ElfRg8:
+ case glslang::ElfR16:
+ case glslang::ElfR8:
+ case glslang::ElfRgba16Snorm:
+ case glslang::ElfRg16Snorm:
+ case glslang::ElfRg8Snorm:
+ case glslang::ElfR16Snorm:
+ case glslang::ElfR8Snorm:
+
+ case glslang::ElfRg32i:
+ case glslang::ElfRg16i:
+ case glslang::ElfRg8i:
+ case glslang::ElfR16i:
+ case glslang::ElfR8i:
+
+ case glslang::ElfRgb10a2ui:
+ case glslang::ElfRg32ui:
+ case glslang::ElfRg16ui:
+ case glslang::ElfRg8ui:
+ case glslang::ElfR16ui:
+ case glslang::ElfR8ui:
+ builder.addCapability(spv::CapabilityStorageImageExtendedFormats);
+ break;
+
+ default:
+ break;
+ }
+
+ // do the translation
+ switch (type.getQualifier().getFormat()) {
+ case glslang::ElfNone: return spv::ImageFormatUnknown;
+ case glslang::ElfRgba32f: return spv::ImageFormatRgba32f;
+ case glslang::ElfRgba16f: return spv::ImageFormatRgba16f;
+ case glslang::ElfR32f: return spv::ImageFormatR32f;
+ case glslang::ElfRgba8: return spv::ImageFormatRgba8;
+ case glslang::ElfRgba8Snorm: return spv::ImageFormatRgba8Snorm;
+ case glslang::ElfRg32f: return spv::ImageFormatRg32f;
+ case glslang::ElfRg16f: return spv::ImageFormatRg16f;
+ case glslang::ElfR11fG11fB10f: return spv::ImageFormatR11fG11fB10f;
+ case glslang::ElfR16f: return spv::ImageFormatR16f;
+ case glslang::ElfRgba16: return spv::ImageFormatRgba16;
+ case glslang::ElfRgb10A2: return spv::ImageFormatRgb10A2;
+ case glslang::ElfRg16: return spv::ImageFormatRg16;
+ case glslang::ElfRg8: return spv::ImageFormatRg8;
+ case glslang::ElfR16: return spv::ImageFormatR16;
+ case glslang::ElfR8: return spv::ImageFormatR8;
+ case glslang::ElfRgba16Snorm: return spv::ImageFormatRgba16Snorm;
+ case glslang::ElfRg16Snorm: return spv::ImageFormatRg16Snorm;
+ case glslang::ElfRg8Snorm: return spv::ImageFormatRg8Snorm;
+ case glslang::ElfR16Snorm: return spv::ImageFormatR16Snorm;
+ case glslang::ElfR8Snorm: return spv::ImageFormatR8Snorm;
+ case glslang::ElfRgba32i: return spv::ImageFormatRgba32i;
+ case glslang::ElfRgba16i: return spv::ImageFormatRgba16i;
+ case glslang::ElfRgba8i: return spv::ImageFormatRgba8i;
+ case glslang::ElfR32i: return spv::ImageFormatR32i;
+ case glslang::ElfRg32i: return spv::ImageFormatRg32i;
+ case glslang::ElfRg16i: return spv::ImageFormatRg16i;
+ case glslang::ElfRg8i: return spv::ImageFormatRg8i;
+ case glslang::ElfR16i: return spv::ImageFormatR16i;
+ case glslang::ElfR8i: return spv::ImageFormatR8i;
+ case glslang::ElfRgba32ui: return spv::ImageFormatRgba32ui;
+ case glslang::ElfRgba16ui: return spv::ImageFormatRgba16ui;
+ case glslang::ElfRgba8ui: return spv::ImageFormatRgba8ui;
+ case glslang::ElfR32ui: return spv::ImageFormatR32ui;
+ case glslang::ElfRg32ui: return spv::ImageFormatRg32ui;
+ case glslang::ElfRg16ui: return spv::ImageFormatRg16ui;
+ case glslang::ElfRgb10a2ui: return spv::ImageFormatRgb10a2ui;
+ case glslang::ElfRg8ui: return spv::ImageFormatRg8ui;
+ case glslang::ElfR16ui: return spv::ImageFormatR16ui;
+ case glslang::ElfR8ui: return spv::ImageFormatR8ui;
+ default: return spv::ImageFormatMax;
+ }
+}
+
+spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(const glslang::TIntermSelection& selectionNode) const
+{
+ if (selectionNode.getFlatten())
+ return spv::SelectionControlFlattenMask;
+ if (selectionNode.getDontFlatten())
+ return spv::SelectionControlDontFlattenMask;
+ return spv::SelectionControlMaskNone;
+}
+
+spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const
+{
+ if (switchNode.getFlatten())
+ return spv::SelectionControlFlattenMask;
+ if (switchNode.getDontFlatten())
+ return spv::SelectionControlDontFlattenMask;
+ return spv::SelectionControlMaskNone;
+}
+
+// return a non-0 dependency if the dependency argument must be set
+spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang::TIntermLoop& loopNode,
+ std::vector<unsigned int>& operands) const
+{
+ spv::LoopControlMask control = spv::LoopControlMaskNone;
+
+ if (loopNode.getDontUnroll())
+ control = control | spv::LoopControlDontUnrollMask;
+ if (loopNode.getUnroll())
+ control = control | spv::LoopControlUnrollMask;
+ if (unsigned(loopNode.getLoopDependency()) == glslang::TIntermLoop::dependencyInfinite)
+ control = control | spv::LoopControlDependencyInfiniteMask;
+ else if (loopNode.getLoopDependency() > 0) {
+ control = control | spv::LoopControlDependencyLengthMask;
+ operands.push_back((unsigned int)loopNode.getLoopDependency());
+ }
+ if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) {
+ if (loopNode.getMinIterations() > 0) {
+ control = control | spv::LoopControlMinIterationsMask;
+ operands.push_back(loopNode.getMinIterations());
+ }
+ if (loopNode.getMaxIterations() < glslang::TIntermLoop::iterationsInfinite) {
+ control = control | spv::LoopControlMaxIterationsMask;
+ operands.push_back(loopNode.getMaxIterations());
+ }
+ if (loopNode.getIterationMultiple() > 1) {
+ control = control | spv::LoopControlIterationMultipleMask;
+ operands.push_back(loopNode.getIterationMultiple());
+ }
+ if (loopNode.getPeelCount() > 0) {
+ control = control | spv::LoopControlPeelCountMask;
+ operands.push_back(loopNode.getPeelCount());
+ }
+ if (loopNode.getPartialCount() > 0) {
+ control = control | spv::LoopControlPartialCountMask;
+ operands.push_back(loopNode.getPartialCount());
+ }
+ }
+
+ return control;
+}
+
+// Translate glslang type to SPIR-V storage class.
+spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type)
+{
+ if (type.getQualifier().isPipeInput())
+ return spv::StorageClassInput;
+ if (type.getQualifier().isPipeOutput())
+ return spv::StorageClassOutput;
+
+ if (glslangIntermediate->getSource() != glslang::EShSourceHlsl ||
+ type.getQualifier().storage == glslang::EvqUniform) {
+ if (type.isAtomic())
+ return spv::StorageClassAtomicCounter;
+ if (type.containsOpaque())
+ return spv::StorageClassUniformConstant;
+ }
+
+ if (type.getQualifier().isUniformOrBuffer() &&
+ type.getQualifier().isShaderRecordNV()) {
+ return spv::StorageClassShaderRecordBufferNV;
+ }
+
+ if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) {
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_storage_buffer_storage_class, spv::Spv_1_3);
+ return spv::StorageClassStorageBuffer;
+ }
+
+ if (type.getQualifier().isUniformOrBuffer()) {
+ if (type.getQualifier().isPushConstant())
+ return spv::StorageClassPushConstant;
+ if (type.getBasicType() == glslang::EbtBlock)
+ return spv::StorageClassUniform;
+ return spv::StorageClassUniformConstant;
+ }
+
+ switch (type.getQualifier().storage) {
+ case glslang::EvqGlobal: return spv::StorageClassPrivate;
+ case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
+ case glslang::EvqTemporary: return spv::StorageClassFunction;
+ case glslang::EvqShared: return spv::StorageClassWorkgroup;
+#ifndef GLSLANG_WEB
+ case glslang::EvqPayloadNV: return spv::StorageClassRayPayloadNV;
+ case glslang::EvqPayloadInNV: return spv::StorageClassIncomingRayPayloadNV;
+ case glslang::EvqHitAttrNV: return spv::StorageClassHitAttributeNV;
+ case glslang::EvqCallableDataNV: return spv::StorageClassCallableDataNV;
+ case glslang::EvqCallableDataInNV: return spv::StorageClassIncomingCallableDataNV;
+#endif
+ default:
+ assert(0);
+ break;
+ }
+
+ return spv::StorageClassFunction;
+}
+
+// Add capabilities pertaining to how an array is indexed.
+void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TType& baseType,
+ const glslang::TType& indexType)
+{
+#ifndef GLSLANG_WEB
+ if (indexType.getQualifier().isNonUniform()) {
+ // deal with an asserted non-uniform index
+ // SPV_EXT_descriptor_indexing already added in TranslateNonUniformDecoration
+ if (baseType.getBasicType() == glslang::EbtSampler) {
+ if (baseType.getQualifier().hasAttachment())
+ builder.addCapability(spv::CapabilityInputAttachmentArrayNonUniformIndexingEXT);
+ else if (baseType.isImage() && baseType.getSampler().isBuffer())
+ builder.addCapability(spv::CapabilityStorageTexelBufferArrayNonUniformIndexingEXT);
+ else if (baseType.isTexture() && baseType.getSampler().isBuffer())
+ builder.addCapability(spv::CapabilityUniformTexelBufferArrayNonUniformIndexingEXT);
+ else if (baseType.isImage())
+ builder.addCapability(spv::CapabilityStorageImageArrayNonUniformIndexingEXT);
+ else if (baseType.isTexture())
+ builder.addCapability(spv::CapabilitySampledImageArrayNonUniformIndexingEXT);
+ } else if (baseType.getBasicType() == glslang::EbtBlock) {
+ if (baseType.getQualifier().storage == glslang::EvqBuffer)
+ builder.addCapability(spv::CapabilityStorageBufferArrayNonUniformIndexingEXT);
+ else if (baseType.getQualifier().storage == glslang::EvqUniform)
+ builder.addCapability(spv::CapabilityUniformBufferArrayNonUniformIndexingEXT);
+ }
+ } else {
+ // assume a dynamically uniform index
+ if (baseType.getBasicType() == glslang::EbtSampler) {
+ if (baseType.getQualifier().hasAttachment()) {
+ builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityInputAttachmentArrayDynamicIndexingEXT);
+ } else if (baseType.isImage() && baseType.getSampler().isBuffer()) {
+ builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityStorageTexelBufferArrayDynamicIndexingEXT);
+ } else if (baseType.isTexture() && baseType.getSampler().isBuffer()) {
+ builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityUniformTexelBufferArrayDynamicIndexingEXT);
+ }
+ }
+ }
+#endif
+}
+
+// Return whether or not the given type is something that should be tied to a
+// descriptor set.
+bool IsDescriptorResource(const glslang::TType& type)
+{
+ // uniform and buffer blocks are included, unless it is a push_constant
+ if (type.getBasicType() == glslang::EbtBlock)
+ return type.getQualifier().isUniformOrBuffer() &&
+ ! type.getQualifier().isShaderRecordNV() &&
+ ! type.getQualifier().isPushConstant();
+
+ // non block...
+ // basically samplerXXX/subpass/sampler/texture are all included
+ // if they are the global-scope-class, not the function parameter
+ // (or local, if they ever exist) class.
+ if (type.getBasicType() == glslang::EbtSampler)
+ return type.getQualifier().isUniformOrBuffer();
+
+ // None of the above.
+ return false;
+}
+
+void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& parent)
+{
+ if (child.layoutMatrix == glslang::ElmNone)
+ child.layoutMatrix = parent.layoutMatrix;
+
+ if (parent.invariant)
+ child.invariant = true;
+ if (parent.flat)
+ child.flat = true;
+ if (parent.centroid)
+ child.centroid = true;
+#ifndef GLSLANG_WEB
+ if (parent.nopersp)
+ child.nopersp = true;
+ if (parent.explicitInterp)
+ child.explicitInterp = true;
+ if (parent.perPrimitiveNV)
+ child.perPrimitiveNV = true;
+ if (parent.perViewNV)
+ child.perViewNV = true;
+ if (parent.perTaskNV)
+ child.perTaskNV = true;
+ if (parent.patch)
+ child.patch = true;
+ if (parent.sample)
+ child.sample = true;
+ if (parent.coherent)
+ child.coherent = true;
+ if (parent.devicecoherent)
+ child.devicecoherent = true;
+ if (parent.queuefamilycoherent)
+ child.queuefamilycoherent = true;
+ if (parent.workgroupcoherent)
+ child.workgroupcoherent = true;
+ if (parent.subgroupcoherent)
+ child.subgroupcoherent = true;
+ if (parent.nonprivate)
+ child.nonprivate = true;
+ if (parent.volatil)
+ child.volatil = true;
+ if (parent.restrict)
+ child.restrict = true;
+ if (parent.readonly)
+ child.readonly = true;
+ if (parent.writeonly)
+ child.writeonly = true;
+#endif
+}
+
+bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier)
+{
+ // This should list qualifiers that simultaneous satisfy:
+ // - struct members might inherit from a struct declaration
+ // (note that non-block structs don't explicitly inherit,
+ // only implicitly, meaning no decoration involved)
+ // - affect decorations on the struct members
+ // (note smooth does not, and expecting something like volatile
+ // to effect the whole object)
+ // - are not part of the offset/st430/etc or row/column-major layout
+ return qualifier.invariant || (qualifier.hasLocation() && type.getBasicType() == glslang::EbtBlock);
+}
+
+//
+// Implement the TGlslangToSpvTraverser class.
+//
+
+TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate* glslangIntermediate,
+ spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options)
+ : TIntermTraverser(true, false, true),
+ options(options),
+ shaderEntry(nullptr), currentFunction(nullptr),
+ sequenceDepth(0), logger(buildLogger),
+ builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger),
+ inEntryPoint(false), entryPointTerminated(false), linkageOnly(false),
+ glslangIntermediate(glslangIntermediate),
+ nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp())
+{
+ spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage());
+
+ builder.clearAccessChain();
+ builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()),
+ glslangIntermediate->getVersion());
+
+ if (options.generateDebugInfo) {
+ builder.setEmitOpLines();
+ builder.setSourceFile(glslangIntermediate->getSourceFile());
+
+ // Set the source shader's text. If for SPV version 1.0, include
+ // a preamble in comments stating the OpModuleProcessed instructions.
+ // Otherwise, emit those as actual instructions.
+ std::string text;
+ const std::vector<std::string>& processes = glslangIntermediate->getProcesses();
+ for (int p = 0; p < (int)processes.size(); ++p) {
+ if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_1) {
+ text.append("// OpModuleProcessed ");
+ text.append(processes[p]);
+ text.append("\n");
+ } else
+ builder.addModuleProcessed(processes[p]);
+ }
+ if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_1 && (int)processes.size() > 0)
+ text.append("#line 1\n");
+ text.append(glslangIntermediate->getSourceText());
+ builder.setSourceText(text);
+ // Pass name and text for all included files
+ const std::map<std::string, std::string>& include_txt = glslangIntermediate->getIncludeText();
+ for (auto iItr = include_txt.begin(); iItr != include_txt.end(); ++iItr)
+ builder.addInclude(iItr->first, iItr->second);
+ }
+ stdBuiltins = builder.import("GLSL.std.450");
+
+ spv::AddressingModel addressingModel = spv::AddressingModelLogical;
+ spv::MemoryModel memoryModel = spv::MemoryModelGLSL450;
+
+ if (glslangIntermediate->usingPhysicalStorageBuffer()) {
+ addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT;
+ builder.addIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT);
+ };
+ if (glslangIntermediate->usingVulkanMemoryModel()) {
+ memoryModel = spv::MemoryModelVulkanKHR;
+ builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5);
+ }
+ builder.setMemoryModel(addressingModel, memoryModel);
+
+ if (glslangIntermediate->usingVariablePointers()) {
+ builder.addCapability(spv::CapabilityVariablePointers);
+ }
+
+ shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str());
+ entryPoint = builder.addEntryPoint(executionModel, shaderEntry, glslangIntermediate->getEntryPointName().c_str());
+
+ // Add the source extensions
+ const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
+ for (auto it = sourceExtensions.begin(); it != sourceExtensions.end(); ++it)
+ builder.addSourceExtension(it->c_str());
+
+ // Add the top-level modes for this shader.
+
+ if (glslangIntermediate->getXfbMode()) {
+ builder.addCapability(spv::CapabilityTransformFeedback);
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb);
+ }
+
+ unsigned int mode;
+ switch (glslangIntermediate->getStage()) {
+ case EShLangVertex:
+ builder.addCapability(spv::CapabilityShader);
+ break;
+
+ case EShLangFragment:
+ builder.addCapability(spv::CapabilityShader);
+ if (glslangIntermediate->getPixelCenterInteger())
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger);
+
+ if (glslangIntermediate->getOriginUpperLeft())
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft);
+ else
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft);
+
+ if (glslangIntermediate->getEarlyFragmentTests())
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests);
+
+ if (glslangIntermediate->getPostDepthCoverage()) {
+ builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage);
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage);
+ builder.addExtension(spv::E_SPV_KHR_post_depth_coverage);
+ }
+
+ if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing())
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
+
+#ifndef GLSLANG_WEB
+ switch(glslangIntermediate->getDepth()) {
+ case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break;
+ case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break;
+ default: mode = spv::ExecutionModeMax; break;
+ }
+ if (mode != spv::ExecutionModeMax)
+ builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+ switch (glslangIntermediate->getInterlockOrdering()) {
+ case glslang::EioPixelInterlockOrdered: mode = spv::ExecutionModePixelInterlockOrderedEXT;
+ break;
+ case glslang::EioPixelInterlockUnordered: mode = spv::ExecutionModePixelInterlockUnorderedEXT;
+ break;
+ case glslang::EioSampleInterlockOrdered: mode = spv::ExecutionModeSampleInterlockOrderedEXT;
+ break;
+ case glslang::EioSampleInterlockUnordered: mode = spv::ExecutionModeSampleInterlockUnorderedEXT;
+ break;
+ case glslang::EioShadingRateInterlockOrdered: mode = spv::ExecutionModeShadingRateInterlockOrderedEXT;
+ break;
+ case glslang::EioShadingRateInterlockUnordered: mode = spv::ExecutionModeShadingRateInterlockUnorderedEXT;
+ break;
+ default: mode = spv::ExecutionModeMax;
+ break;
+ }
+ if (mode != spv::ExecutionModeMax) {
+ builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+ if (mode == spv::ExecutionModeShadingRateInterlockOrderedEXT ||
+ mode == spv::ExecutionModeShadingRateInterlockUnorderedEXT) {
+ builder.addCapability(spv::CapabilityFragmentShaderShadingRateInterlockEXT);
+ } else if (mode == spv::ExecutionModePixelInterlockOrderedEXT ||
+ mode == spv::ExecutionModePixelInterlockUnorderedEXT) {
+ builder.addCapability(spv::CapabilityFragmentShaderPixelInterlockEXT);
+ } else {
+ builder.addCapability(spv::CapabilityFragmentShaderSampleInterlockEXT);
+ }
+ builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock);
+ }
+#endif
+ break;
+
+ case EShLangCompute:
+ builder.addCapability(spv::CapabilityShader);
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
+ glslangIntermediate->getLocalSize(1),
+ glslangIntermediate->getLocalSize(2));
+ if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) {
+ builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV);
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupQuadsNV);
+ builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives);
+ } else if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupLinear) {
+ builder.addCapability(spv::CapabilityComputeDerivativeGroupLinearNV);
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupLinearNV);
+ builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives);
+ }
+ break;
+#ifndef GLSLANG_WEB
+ case EShLangTessEvaluation:
+ case EShLangTessControl:
+ builder.addCapability(spv::CapabilityTessellation);
+
+ glslang::TLayoutGeometry primitive;
+
+ if (glslangIntermediate->getStage() == EShLangTessControl) {
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
+ primitive = glslangIntermediate->getOutputPrimitive();
+ } else {
+ primitive = glslangIntermediate->getInputPrimitive();
+ }
+
+ switch (primitive) {
+ case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break;
+ case glslang::ElgQuads: mode = spv::ExecutionModeQuads; break;
+ case glslang::ElgIsolines: mode = spv::ExecutionModeIsolines; break;
+ default: mode = spv::ExecutionModeMax; break;
+ }
+ if (mode != spv::ExecutionModeMax)
+ builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+
+ switch (glslangIntermediate->getVertexSpacing()) {
+ case glslang::EvsEqual: mode = spv::ExecutionModeSpacingEqual; break;
+ case glslang::EvsFractionalEven: mode = spv::ExecutionModeSpacingFractionalEven; break;
+ case glslang::EvsFractionalOdd: mode = spv::ExecutionModeSpacingFractionalOdd; break;
+ default: mode = spv::ExecutionModeMax; break;
+ }
+ if (mode != spv::ExecutionModeMax)
+ builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+
+ switch (glslangIntermediate->getVertexOrder()) {
+ case glslang::EvoCw: mode = spv::ExecutionModeVertexOrderCw; break;
+ case glslang::EvoCcw: mode = spv::ExecutionModeVertexOrderCcw; break;
+ default: mode = spv::ExecutionModeMax; break;
+ }
+ if (mode != spv::ExecutionModeMax)
+ builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+
+ if (glslangIntermediate->getPointMode())
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModePointMode);
+ break;
+
+ case EShLangGeometry:
+ builder.addCapability(spv::CapabilityGeometry);
+ switch (glslangIntermediate->getInputPrimitive()) {
+ case glslang::ElgPoints: mode = spv::ExecutionModeInputPoints; break;
+ case glslang::ElgLines: mode = spv::ExecutionModeInputLines; break;
+ case glslang::ElgLinesAdjacency: mode = spv::ExecutionModeInputLinesAdjacency; break;
+ case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break;
+ case glslang::ElgTrianglesAdjacency: mode = spv::ExecutionModeInputTrianglesAdjacency; break;
+ default: mode = spv::ExecutionModeMax; break;
+ }
+ if (mode != spv::ExecutionModeMax)
+ builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeInvocations, glslangIntermediate->getInvocations());
+
+ switch (glslangIntermediate->getOutputPrimitive()) {
+ case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break;
+ case glslang::ElgLineStrip: mode = spv::ExecutionModeOutputLineStrip; break;
+ case glslang::ElgTriangleStrip: mode = spv::ExecutionModeOutputTriangleStrip; break;
+ default: mode = spv::ExecutionModeMax; break;
+ }
+ if (mode != spv::ExecutionModeMax)
+ builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
+ break;
+
+ case EShLangRayGenNV:
+ case EShLangIntersectNV:
+ case EShLangAnyHitNV:
+ case EShLangClosestHitNV:
+ case EShLangMissNV:
+ case EShLangCallableNV:
+ builder.addCapability(spv::CapabilityRayTracingNV);
+ builder.addExtension("SPV_NV_ray_tracing");
+ break;
+ case EShLangTaskNV:
+ case EShLangMeshNV:
+ builder.addCapability(spv::CapabilityMeshShadingNV);
+ builder.addExtension(spv::E_SPV_NV_mesh_shader);
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
+ glslangIntermediate->getLocalSize(1),
+ glslangIntermediate->getLocalSize(2));
+ if (glslangIntermediate->getStage() == EShLangMeshNV) {
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
+ builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, glslangIntermediate->getPrimitives());
+
+ switch (glslangIntermediate->getOutputPrimitive()) {
+ case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break;
+ case glslang::ElgLines: mode = spv::ExecutionModeOutputLinesNV; break;
+ case glslang::ElgTriangles: mode = spv::ExecutionModeOutputTrianglesNV; break;
+ default: mode = spv::ExecutionModeMax; break;
+ }
+ if (mode != spv::ExecutionModeMax)
+ builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+ }
+ break;
+#endif
+
+ default:
+ break;
+ }
+}
+
+// Finish creating SPV, after the traversal is complete.
+void TGlslangToSpvTraverser::finishSpv()
+{
+ // Finish the entry point function
+ if (! entryPointTerminated) {
+ builder.setBuildPoint(shaderEntry->getLastBlock());
+ builder.leaveFunction();
+ }
+
+ // finish off the entry-point SPV instruction by adding the Input/Output <id>
+ for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it)
+ entryPoint->addIdOperand(*it);
+
+ // Add capabilities, extensions, remove unneeded decorations, etc.,
+ // based on the resulting SPIR-V.
+ // Note: WebGPU code generation must have the opportunity to aggressively
+ // prune unreachable merge blocks and continue targets.
+ builder.postProcess();
+}
+
+// Write the SPV into 'out'.
+void TGlslangToSpvTraverser::dumpSpv(std::vector<unsigned int>& out)
+{
+ builder.dump(out);
+}
+
+//
+// Implement the traversal functions.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children. Return false if children were
+// already processed.
+//
+
+//
+// Symbols can turn into
+// - uniform/input reads
+// - output writes
+// - complex lvalue base setups: foo.bar[3].... , where we see foo and start up an access chain
+// - something simple that degenerates into the last bullet
+//
+void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
+{
+ SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
+ if (symbol->getType().isStruct())
+ glslangTypeToIdMap[symbol->getType().getStruct()] = symbol->getId();
+
+ if (symbol->getType().getQualifier().isSpecConstant())
+ spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
+
+ // getSymbolId() will set up all the IO decorations on the first call.
+ // Formal function parameters were mapped during makeFunctions().
+ spv::Id id = getSymbolId(symbol);
+
+ if (builder.isPointer(id)) {
+ // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction
+ // Consider adding to the OpEntryPoint interface list.
+ // Only looking at structures if they have at least one member.
+ if (!symbol->getType().isStruct() || symbol->getType().getStruct()->size() > 0) {
+ spv::StorageClass sc = builder.getStorageClass(id);
+ // Before SPIR-V 1.4, we only want to include Input and Output.
+ // Starting with SPIR-V 1.4, we want all globals.
+ if ((glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4 && sc != spv::StorageClassFunction) ||
+ (sc == spv::StorageClassInput || sc == spv::StorageClassOutput)) {
+ iOSet.insert(id);
+ }
+ }
+
+ // If the SPIR-V type is required to be different than the AST type,
+ // translate now from the SPIR-V type to the AST type, for the consuming
+ // operation.
+ // Note this turns it from an l-value to an r-value.
+ // Currently, all symbols needing this are inputs; avoid the map lookup when non-input.
+ if (symbol->getType().getQualifier().storage == glslang::EvqVaryingIn)
+ id = translateForcedType(id);
+ }
+
+ // Only process non-linkage-only nodes for generating actual static uses
+ if (! linkageOnly || symbol->getQualifier().isSpecConstant()) {
+ // Prepare to generate code for the access
+
+ // L-value chains will be computed left to right. We're on the symbol now,
+ // which is the left-most part of the access chain, so now is "clear" time,
+ // followed by setting the base.
+ builder.clearAccessChain();
+
+ // For now, we consider all user variables as being in memory, so they are pointers,
+ // except for
+ // A) R-Value arguments to a function, which are an intermediate object.
+ // See comments in handleUserFunctionCall().
+ // B) Specialization constants (normal constants don't even come in as a variable),
+ // These are also pure R-values.
+ // C) R-Values from type translation, see above call to translateForcedType()
+ glslang::TQualifier qualifier = symbol->getQualifier();
+ if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end() ||
+ !builder.isPointerType(builder.getTypeId(id)))
+ builder.setAccessChainRValue(id);
+ else
+ builder.setAccessChainLValue(id);
+ }
+
+#ifdef ENABLE_HLSL
+ // Process linkage-only nodes for any special additional interface work.
+ if (linkageOnly) {
+ if (glslangIntermediate->getHlslFunctionality1()) {
+ // Map implicit counter buffers to their originating buffers, which should have been
+ // seen by now, given earlier pruning of unused counters, and preservation of order
+ // of declaration.
+ if (symbol->getType().getQualifier().isUniformOrBuffer()) {
+ if (!glslangIntermediate->hasCounterBufferName(symbol->getName())) {
+ // Save possible originating buffers for counter buffers, keyed by
+ // making the potential counter-buffer name.
+ std::string keyName = symbol->getName().c_str();
+ keyName = glslangIntermediate->addCounterBufferName(keyName);
+ counterOriginator[keyName] = symbol;
+ } else {
+ // Handle a counter buffer, by finding the saved originating buffer.
+ std::string keyName = symbol->getName().c_str();
+ auto it = counterOriginator.find(keyName);
+ if (it != counterOriginator.end()) {
+ id = getSymbolId(it->second);
+ if (id != spv::NoResult) {
+ spv::Id counterId = getSymbolId(symbol);
+ if (counterId != spv::NoResult) {
+ builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
+ builder.addDecorationId(id, spv::DecorationHlslCounterBufferGOOGLE, counterId);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+}
+
+bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
+{
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+ if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) {
+ glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId();
+ }
+ if (node->getRight()->getAsSymbolNode() != nullptr && node->getRight()->getType().isStruct()) {
+ glslangTypeToIdMap[node->getRight()->getType().getStruct()] = node->getRight()->getAsSymbolNode()->getId();
+ }
+
+ SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
+ if (node->getType().getQualifier().isSpecConstant())
+ spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
+
+ // First, handle special cases
+ switch (node->getOp()) {
+ case glslang::EOpAssign:
+ case glslang::EOpAddAssign:
+ case glslang::EOpSubAssign:
+ case glslang::EOpMulAssign:
+ case glslang::EOpVectorTimesMatrixAssign:
+ case glslang::EOpVectorTimesScalarAssign:
+ case glslang::EOpMatrixTimesScalarAssign:
+ case glslang::EOpMatrixTimesMatrixAssign:
+ case glslang::EOpDivAssign:
+ case glslang::EOpModAssign:
+ case glslang::EOpAndAssign:
+ case glslang::EOpInclusiveOrAssign:
+ case glslang::EOpExclusiveOrAssign:
+ case glslang::EOpLeftShiftAssign:
+ case glslang::EOpRightShiftAssign:
+ // A bin-op assign "a += b" means the same thing as "a = a + b"
+ // where a is evaluated before b. For a simple assignment, GLSL
+ // says to evaluate the left before the right. So, always, left
+ // node then right node.
+ {
+ // get the left l-value, save it away
+ builder.clearAccessChain();
+ node->getLeft()->traverse(this);
+ spv::Builder::AccessChain lValue = builder.getAccessChain();
+
+ // evaluate the right
+ builder.clearAccessChain();
+ node->getRight()->traverse(this);
+ spv::Id rValue = accessChainLoad(node->getRight()->getType());
+
+ if (node->getOp() != glslang::EOpAssign) {
+ // the left is also an r-value
+ builder.setAccessChain(lValue);
+ spv::Id leftRValue = accessChainLoad(node->getLeft()->getType());
+
+ // do the operation
+ OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
+ TranslateNoContractionDecoration(node->getType().getQualifier()),
+ TranslateNonUniformDecoration(node->getType().getQualifier()) };
+ rValue = createBinaryOperation(node->getOp(), decorations,
+ convertGlslangToSpvType(node->getType()), leftRValue, rValue,
+ node->getType().getBasicType());
+
+ // these all need their counterparts in createBinaryOperation()
+ assert(rValue != spv::NoResult);
+ }
+
+ // store the result
+ builder.setAccessChain(lValue);
+ multiTypeStore(node->getLeft()->getType(), rValue);
+
+ // assignments are expressions having an rValue after they are evaluated...
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(rValue);
+ }
+ return false;
+ case glslang::EOpIndexDirect:
+ case glslang::EOpIndexDirectStruct:
+ {
+ // Structure, array, matrix, or vector indirection with statically known index.
+ // Get the left part of the access chain.
+ node->getLeft()->traverse(this);
+
+ // Add the next element in the chain
+
+ const int glslangIndex = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
+ if (! node->getLeft()->getType().isArray() &&
+ node->getLeft()->getType().isVector() &&
+ node->getOp() == glslang::EOpIndexDirect) {
+ // This is essentially a hard-coded vector swizzle of size 1,
+ // so short circuit the access-chain stuff with a swizzle.
+ std::vector<unsigned> swizzle;
+ swizzle.push_back(glslangIndex);
+ int dummySize;
+ builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
+ TranslateCoherent(node->getLeft()->getType()),
+ glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
+ } else {
+
+ // Load through a block reference is performed with a dot operator that
+ // is mapped to EOpIndexDirectStruct. When we get to the actual reference,
+ // do a load and reset the access chain.
+ if (node->getLeft()->isReference() &&
+ !node->getLeft()->getType().isArray() &&
+ node->getOp() == glslang::EOpIndexDirectStruct)
+ {
+ spv::Id left = accessChainLoad(node->getLeft()->getType());
+ builder.clearAccessChain();
+ builder.setAccessChainLValue(left);
+ }
+
+ int spvIndex = glslangIndex;
+ if (node->getLeft()->getBasicType() == glslang::EbtBlock &&
+ node->getOp() == glslang::EOpIndexDirectStruct)
+ {
+ // This may be, e.g., an anonymous block-member selection, which generally need
+ // index remapping due to hidden members in anonymous blocks.
+ int glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()];
+ if (memberRemapper.find(glslangId) != memberRemapper.end()) {
+ std::vector<int>& remapper = memberRemapper[glslangId];
+ assert(remapper.size() > 0);
+ spvIndex = remapper[glslangIndex];
+ }
+ }
+
+ // normal case for indexing array or structure or block
+ builder.accessChainPush(builder.makeIntConstant(spvIndex), TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment());
+
+ // Add capabilities here for accessing PointSize and clip/cull distance.
+ // We have deferred generation of associated capabilities until now.
+ if (node->getLeft()->getType().isStruct() && ! node->getLeft()->getType().isArray())
+ declareUseOfStructMember(*(node->getLeft()->getType().getStruct()), glslangIndex);
+ }
+ }
+ return false;
+ case glslang::EOpIndexIndirect:
+ {
+ // Array, matrix, or vector indirection with variable index.
+ // Will use native SPIR-V access-chain for and array indirection;
+ // matrices are arrays of vectors, so will also work for a matrix.
+ // Will use the access chain's 'component' for variable index into a vector.
+
+ // This adapter is building access chains left to right.
+ // Set up the access chain to the left.
+ node->getLeft()->traverse(this);
+
+ // save it so that computing the right side doesn't trash it
+ spv::Builder::AccessChain partial = builder.getAccessChain();
+
+ // compute the next index in the chain
+ builder.clearAccessChain();
+ node->getRight()->traverse(this);
+ spv::Id index = accessChainLoad(node->getRight()->getType());
+
+ addIndirectionIndexCapabilities(node->getLeft()->getType(), node->getRight()->getType());
+
+ // restore the saved access chain
+ builder.setAccessChain(partial);
+
+ if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) {
+ int dummySize;
+ builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()),
+ TranslateCoherent(node->getLeft()->getType()),
+ glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
+ } else
+ builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment());
+ }
+ return false;
+ case glslang::EOpVectorSwizzle:
+ {
+ node->getLeft()->traverse(this);
+ std::vector<unsigned> swizzle;
+ convertSwizzle(*node->getRight()->getAsAggregate(), swizzle);
+ int dummySize;
+ builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
+ TranslateCoherent(node->getLeft()->getType()),
+ glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
+ }
+ return false;
+ case glslang::EOpMatrixSwizzle:
+ logger->missingFunctionality("matrix swizzle");
+ return true;
+ case glslang::EOpLogicalOr:
+ case glslang::EOpLogicalAnd:
+ {
+
+ // These may require short circuiting, but can sometimes be done as straight
+ // binary operations. The right operand must be short circuited if it has
+ // side effects, and should probably be if it is complex.
+ if (isTrivial(node->getRight()->getAsTyped()))
+ break; // handle below as a normal binary operation
+ // otherwise, we need to do dynamic short circuiting on the right operand
+ spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), *node->getRight()->getAsTyped());
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(result);
+ }
+ return false;
+ default:
+ break;
+ }
+
+ // Assume generic binary op...
+
+ // get right operand
+ builder.clearAccessChain();
+ node->getLeft()->traverse(this);
+ spv::Id left = accessChainLoad(node->getLeft()->getType());
+
+ // get left operand
+ builder.clearAccessChain();
+ node->getRight()->traverse(this);
+ spv::Id right = accessChainLoad(node->getRight()->getType());
+
+ // get result
+ OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
+ TranslateNoContractionDecoration(node->getType().getQualifier()),
+ TranslateNonUniformDecoration(node->getType().getQualifier()) };
+ spv::Id result = createBinaryOperation(node->getOp(), decorations,
+ convertGlslangToSpvType(node->getType()), left, right,
+ node->getLeft()->getType().getBasicType());
+
+ builder.clearAccessChain();
+ if (! result) {
+ logger->missingFunctionality("unknown glslang binary operation");
+ return true; // pick up a child as the place-holder result
+ } else {
+ builder.setAccessChainRValue(result);
+ return false;
+ }
+}
+
+// Figure out what, if any, type changes are needed when accessing a specific built-in.
+// Returns <the type SPIR-V requires for declarion, the type to translate to on use>.
+// Also see comment for 'forceType', regarding tracking SPIR-V-required types.
+std::pair<spv::Id, spv::Id> TGlslangToSpvTraverser::getForcedType(spv::BuiltIn builtIn,
+ const glslang::TType& glslangType)
+{
+ switch(builtIn)
+ {
+ case spv::BuiltInSubgroupEqMask:
+ case spv::BuiltInSubgroupGeMask:
+ case spv::BuiltInSubgroupGtMask:
+ case spv::BuiltInSubgroupLeMask:
+ case spv::BuiltInSubgroupLtMask: {
+ // these require changing a 64-bit scaler -> a vector of 32-bit components
+ if (glslangType.isVector())
+ break;
+ std::pair<spv::Id, spv::Id> ret(builder.makeVectorType(builder.makeUintType(32), 4),
+ builder.makeUintType(64));
+ return ret;
+ }
+ default:
+ break;
+ }
+
+ std::pair<spv::Id, spv::Id> ret(spv::NoType, spv::NoType);
+ return ret;
+}
+
+// For an object previously identified (see getForcedType() and forceType)
+// as needing type translations, do the translation needed for a load, turning
+// an L-value into in R-value.
+spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
+{
+ const auto forceIt = forceType.find(object);
+ if (forceIt == forceType.end())
+ return object;
+
+ spv::Id desiredTypeId = forceIt->second;
+ spv::Id objectTypeId = builder.getTypeId(object);
+ assert(builder.isPointerType(objectTypeId));
+ objectTypeId = builder.getContainedTypeId(objectTypeId);
+ if (builder.isVectorType(objectTypeId) &&
+ builder.getScalarTypeWidth(builder.getContainedTypeId(objectTypeId)) == 32) {
+ if (builder.getScalarTypeWidth(desiredTypeId) == 64) {
+ // handle 32-bit v.xy* -> 64-bit
+ builder.clearAccessChain();
+ builder.setAccessChainLValue(object);
+ object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId);
+ std::vector<spv::Id> components;
+ components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 0));
+ components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 1));
+
+ spv::Id vecType = builder.makeVectorType(builder.getContainedTypeId(objectTypeId), 2);
+ return builder.createUnaryOp(spv::OpBitcast, desiredTypeId,
+ builder.createCompositeConstruct(vecType, components));
+ } else {
+ logger->missingFunctionality("forcing 32-bit vector type to non 64-bit scalar");
+ }
+ } else {
+ logger->missingFunctionality("forcing non 32-bit vector type");
+ }
+
+ return object;
+}
+
+bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
+{
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+
+ SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
+ if (node->getType().getQualifier().isSpecConstant())
+ spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
+
+ spv::Id result = spv::NoResult;
+
+ // try texturing first
+ result = createImageTextureFunctionCall(node);
+ if (result != spv::NoResult) {
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(result);
+
+ return false; // done with this node
+ }
+
+ // Non-texturing.
+
+ if (node->getOp() == glslang::EOpArrayLength) {
+ // Quite special; won't want to evaluate the operand.
+
+ // Currently, the front-end does not allow .length() on an array until it is sized,
+ // except for the last block membeor of an SSBO.
+ // TODO: If this changes, link-time sized arrays might show up here, and need their
+ // size extracted.
+
+ // Normal .length() would have been constant folded by the front-end.
+ // So, this has to be block.lastMember.length().
+ // SPV wants "block" and member number as the operands, go get them.
+
+ spv::Id length;
+ if (node->getOperand()->getType().isCoopMat()) {
+ spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
+
+ spv::Id typeId = convertGlslangToSpvType(node->getOperand()->getType());
+ assert(builder.isCooperativeMatrixType(typeId));
+
+ length = builder.createCooperativeMatrixLength(typeId);
+ } else {
+ glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
+ block->traverse(this);
+ unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst();
+ length = builder.createArrayLength(builder.accessChainGetLValue(), member);
+ }
+
+ // GLSL semantics say the result of .length() is an int, while SPIR-V says
+ // signedness must be 0. So, convert from SPIR-V unsigned back to GLSL's
+ // AST expectation of a signed result.
+ if (glslangIntermediate->getSource() == glslang::EShSourceGlsl) {
+ if (builder.isInSpecConstCodeGenMode()) {
+ length = builder.createBinOp(spv::OpIAdd, builder.makeIntType(32), length, builder.makeIntConstant(0));
+ } else {
+ length = builder.createUnaryOp(spv::OpBitcast, builder.makeIntType(32), length);
+ }
+ }
+
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(length);
+
+ return false;
+ }
+
+ // Start by evaluating the operand
+
+ // Does it need a swizzle inversion? If so, evaluation is inverted;
+ // operate first on the swizzle base, then apply the swizzle.
+ spv::Id invertedType = spv::NoType;
+ auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
+ if (node->getOp() == glslang::EOpInterpolateAtCentroid)
+ invertedType = getInvertedSwizzleType(*node->getOperand());
+
+ builder.clearAccessChain();
+ TIntermNode *operandNode;
+ if (invertedType != spv::NoType)
+ operandNode = node->getOperand()->getAsBinaryNode()->getLeft();
+ else
+ operandNode = node->getOperand();
+
+ operandNode->traverse(this);
+
+ spv::Id operand = spv::NoResult;
+
+ spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags;
+
+#ifndef GLSLANG_WEB
+ if (node->getOp() == glslang::EOpAtomicCounterIncrement ||
+ node->getOp() == glslang::EOpAtomicCounterDecrement ||
+ node->getOp() == glslang::EOpAtomicCounter ||
+ node->getOp() == glslang::EOpInterpolateAtCentroid) {
+ operand = builder.accessChainGetLValue(); // Special case l-value operands
+ lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
+ lvalueCoherentFlags |= TranslateCoherent(operandNode->getAsTyped()->getType());
+ } else
+#endif
+ {
+ operand = accessChainLoad(node->getOperand()->getType());
+ }
+
+ OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
+ TranslateNoContractionDecoration(node->getType().getQualifier()),
+ TranslateNonUniformDecoration(node->getType().getQualifier()) };
+
+ // it could be a conversion
+ if (! result)
+ result = createConversion(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType());
+
+ // if not, then possibly an operation
+ if (! result)
+ result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType(), lvalueCoherentFlags);
+
+ if (result) {
+ if (invertedType) {
+ result = createInvertedSwizzle(decorations.precision, *node->getOperand(), result);
+ decorations.addNonUniform(builder, result);
+ }
+
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(result);
+
+ return false; // done with this node
+ }
+
+ // it must be a special case, check...
+ switch (node->getOp()) {
+ case glslang::EOpPostIncrement:
+ case glslang::EOpPostDecrement:
+ case glslang::EOpPreIncrement:
+ case glslang::EOpPreDecrement:
+ {
+ // we need the integer value "1" or the floating point "1.0" to add/subtract
+ spv::Id one = 0;
+ if (node->getBasicType() == glslang::EbtFloat)
+ one = builder.makeFloatConstant(1.0F);
+#ifndef GLSLANG_WEB
+ else if (node->getBasicType() == glslang::EbtDouble)
+ one = builder.makeDoubleConstant(1.0);
+ else if (node->getBasicType() == glslang::EbtFloat16)
+ one = builder.makeFloat16Constant(1.0F);
+ else if (node->getBasicType() == glslang::EbtInt8 || node->getBasicType() == glslang::EbtUint8)
+ one = builder.makeInt8Constant(1);
+ else if (node->getBasicType() == glslang::EbtInt16 || node->getBasicType() == glslang::EbtUint16)
+ one = builder.makeInt16Constant(1);
+ else if (node->getBasicType() == glslang::EbtInt64 || node->getBasicType() == glslang::EbtUint64)
+ one = builder.makeInt64Constant(1);
+#endif
+ else
+ one = builder.makeIntConstant(1);
+ glslang::TOperator op;
+ if (node->getOp() == glslang::EOpPreIncrement ||
+ node->getOp() == glslang::EOpPostIncrement)
+ op = glslang::EOpAdd;
+ else
+ op = glslang::EOpSub;
+
+ spv::Id result = createBinaryOperation(op, decorations,
+ convertGlslangToSpvType(node->getType()), operand, one,
+ node->getType().getBasicType());
+ assert(result != spv::NoResult);
+
+ // The result of operation is always stored, but conditionally the
+ // consumed result. The consumed result is always an r-value.
+ builder.accessChainStore(result);
+ builder.clearAccessChain();
+ if (node->getOp() == glslang::EOpPreIncrement ||
+ node->getOp() == glslang::EOpPreDecrement)
+ builder.setAccessChainRValue(result);
+ else
+ builder.setAccessChainRValue(operand);
+ }
+
+ return false;
+
+#ifndef GLSLANG_WEB
+ case glslang::EOpEmitStreamVertex:
+ builder.createNoResultOp(spv::OpEmitStreamVertex, operand);
+ return false;
+ case glslang::EOpEndStreamPrimitive:
+ builder.createNoResultOp(spv::OpEndStreamPrimitive, operand);
+ return false;
+#endif
+
+ default:
+ logger->missingFunctionality("unknown glslang unary");
+ return true; // pick up operand as placeholder result
+ }
+}
+
+// Construct a composite object, recursively copying members if their types don't match
+spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, std::vector<spv::Id> constituents)
+{
+ for (int c = 0; c < (int)constituents.size(); ++c) {
+ spv::Id& constituent = constituents[c];
+ spv::Id lType = builder.getContainedTypeId(resultTypeId, c);
+ spv::Id rType = builder.getTypeId(constituent);
+ if (lType != rType) {
+ if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) {
+ constituent = builder.createUnaryOp(spv::OpCopyLogical, lType, constituent);
+ } else if (builder.isStructType(rType)) {
+ std::vector<spv::Id> rTypeConstituents;
+ int numrTypeConstituents = builder.getNumTypeConstituents(rType);
+ for (int i = 0; i < numrTypeConstituents; ++i) {
+ rTypeConstituents.push_back(builder.createCompositeExtract(constituent, builder.getContainedTypeId(rType, i), i));
+ }
+ constituents[c] = createCompositeConstruct(lType, rTypeConstituents);
+ } else {
+ assert(builder.isArrayType(rType));
+ std::vector<spv::Id> rTypeConstituents;
+ int numrTypeConstituents = builder.getNumTypeConstituents(rType);
+
+ spv::Id elementRType = builder.getContainedTypeId(rType);
+ for (int i = 0; i < numrTypeConstituents; ++i) {
+ rTypeConstituents.push_back(builder.createCompositeExtract(constituent, elementRType, i));
+ }
+ constituents[c] = createCompositeConstruct(lType, rTypeConstituents);
+ }
+ }
+ }
+ return builder.createCompositeConstruct(resultTypeId, constituents);
+}
+
+bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node)
+{
+ SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
+ if (node->getType().getQualifier().isSpecConstant())
+ spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
+
+ spv::Id result = spv::NoResult;
+ spv::Id invertedType = spv::NoType; // to use to override the natural type of the node
+ auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
+
+ // try texturing
+ result = createImageTextureFunctionCall(node);
+ if (result != spv::NoResult) {
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(result);
+
+ return false;
+ }
+#ifndef GLSLANG_WEB
+ else if (node->getOp() == glslang::EOpImageStore ||
+ node->getOp() == glslang::EOpImageStoreLod ||
+ node->getOp() == glslang::EOpImageAtomicStore) {
+ // "imageStore" is a special case, which has no result
+ return false;
+ }
+#endif
+
+ glslang::TOperator binOp = glslang::EOpNull;
+ bool reduceComparison = true;
+ bool isMatrix = false;
+ bool noReturnValue = false;
+ bool atomic = false;
+
+ spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags;
+
+ assert(node->getOp());
+
+ spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
+
+ switch (node->getOp()) {
+ case glslang::EOpSequence:
+ {
+ if (preVisit)
+ ++sequenceDepth;
+ else
+ --sequenceDepth;
+
+ if (sequenceDepth == 1) {
+ // If this is the parent node of all the functions, we want to see them
+ // early, so all call points have actual SPIR-V functions to reference.
+ // In all cases, still let the traverser visit the children for us.
+ makeFunctions(node->getAsAggregate()->getSequence());
+
+ // Also, we want all globals initializers to go into the beginning of the entry point, before
+ // anything else gets there, so visit out of order, doing them all now.
+ makeGlobalInitializers(node->getAsAggregate()->getSequence());
+
+ // Initializers are done, don't want to visit again, but functions and link objects need to be processed,
+ // so do them manually.
+ visitFunctions(node->getAsAggregate()->getSequence());
+
+ return false;
+ }
+
+ return true;
+ }
+ case glslang::EOpLinkerObjects:
+ {
+ if (visit == glslang::EvPreVisit)
+ linkageOnly = true;
+ else
+ linkageOnly = false;
+
+ return true;
+ }
+ case glslang::EOpComma:
+ {
+ // processing from left to right naturally leaves the right-most
+ // lying around in the access chain
+ glslang::TIntermSequence& glslangOperands = node->getSequence();
+ for (int i = 0; i < (int)glslangOperands.size(); ++i)
+ glslangOperands[i]->traverse(this);
+
+ return false;
+ }
+ case glslang::EOpFunction:
+ if (visit == glslang::EvPreVisit) {
+ if (isShaderEntryPoint(node)) {
+ inEntryPoint = true;
+ builder.setBuildPoint(shaderEntry->getLastBlock());
+ currentFunction = shaderEntry;
+ } else {
+ handleFunctionEntry(node);
+ }
+ } else {
+ if (inEntryPoint)
+ entryPointTerminated = true;
+ builder.leaveFunction();
+ inEntryPoint = false;
+ }
+
+ return true;
+ case glslang::EOpParameters:
+ // Parameters will have been consumed by EOpFunction processing, but not
+ // the body, so we still visited the function node's children, making this
+ // child redundant.
+ return false;
+ case glslang::EOpFunctionCall:
+ {
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+ if (node->isUserDefined())
+ result = handleUserFunctionCall(node);
+ // assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done
+ if (result) {
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(result);
+ } else
+ logger->missingFunctionality("missing user function; linker needs to catch that");
+
+ return false;
+ }
+ case glslang::EOpConstructMat2x2:
+ case glslang::EOpConstructMat2x3:
+ case glslang::EOpConstructMat2x4:
+ case glslang::EOpConstructMat3x2:
+ case glslang::EOpConstructMat3x3:
+ case glslang::EOpConstructMat3x4:
+ case glslang::EOpConstructMat4x2:
+ case glslang::EOpConstructMat4x3:
+ case glslang::EOpConstructMat4x4:
+ case glslang::EOpConstructDMat2x2:
+ case glslang::EOpConstructDMat2x3:
+ case glslang::EOpConstructDMat2x4:
+ case glslang::EOpConstructDMat3x2:
+ case glslang::EOpConstructDMat3x3:
+ case glslang::EOpConstructDMat3x4:
+ case glslang::EOpConstructDMat4x2:
+ case glslang::EOpConstructDMat4x3:
+ case glslang::EOpConstructDMat4x4:
+ case glslang::EOpConstructIMat2x2:
+ case glslang::EOpConstructIMat2x3:
+ case glslang::EOpConstructIMat2x4:
+ case glslang::EOpConstructIMat3x2:
+ case glslang::EOpConstructIMat3x3:
+ case glslang::EOpConstructIMat3x4:
+ case glslang::EOpConstructIMat4x2:
+ case glslang::EOpConstructIMat4x3:
+ case glslang::EOpConstructIMat4x4:
+ case glslang::EOpConstructUMat2x2:
+ case glslang::EOpConstructUMat2x3:
+ case glslang::EOpConstructUMat2x4:
+ case glslang::EOpConstructUMat3x2:
+ case glslang::EOpConstructUMat3x3:
+ case glslang::EOpConstructUMat3x4:
+ case glslang::EOpConstructUMat4x2:
+ case glslang::EOpConstructUMat4x3:
+ case glslang::EOpConstructUMat4x4:
+ case glslang::EOpConstructBMat2x2:
+ case glslang::EOpConstructBMat2x3:
+ case glslang::EOpConstructBMat2x4:
+ case glslang::EOpConstructBMat3x2:
+ case glslang::EOpConstructBMat3x3:
+ case glslang::EOpConstructBMat3x4:
+ case glslang::EOpConstructBMat4x2:
+ case glslang::EOpConstructBMat4x3:
+ case glslang::EOpConstructBMat4x4:
+ case glslang::EOpConstructF16Mat2x2:
+ case glslang::EOpConstructF16Mat2x3:
+ case glslang::EOpConstructF16Mat2x4:
+ case glslang::EOpConstructF16Mat3x2:
+ case glslang::EOpConstructF16Mat3x3:
+ case glslang::EOpConstructF16Mat3x4:
+ case glslang::EOpConstructF16Mat4x2:
+ case glslang::EOpConstructF16Mat4x3:
+ case glslang::EOpConstructF16Mat4x4:
+ isMatrix = true;
+ // fall through
+ case glslang::EOpConstructFloat:
+ case glslang::EOpConstructVec2:
+ case glslang::EOpConstructVec3:
+ case glslang::EOpConstructVec4:
+ case glslang::EOpConstructDouble:
+ case glslang::EOpConstructDVec2:
+ case glslang::EOpConstructDVec3:
+ case glslang::EOpConstructDVec4:
+ case glslang::EOpConstructFloat16:
+ case glslang::EOpConstructF16Vec2:
+ case glslang::EOpConstructF16Vec3:
+ case glslang::EOpConstructF16Vec4:
+ case glslang::EOpConstructBool:
+ case glslang::EOpConstructBVec2:
+ case glslang::EOpConstructBVec3:
+ case glslang::EOpConstructBVec4:
+ case glslang::EOpConstructInt8:
+ case glslang::EOpConstructI8Vec2:
+ case glslang::EOpConstructI8Vec3:
+ case glslang::EOpConstructI8Vec4:
+ case glslang::EOpConstructUint8:
+ case glslang::EOpConstructU8Vec2:
+ case glslang::EOpConstructU8Vec3:
+ case glslang::EOpConstructU8Vec4:
+ case glslang::EOpConstructInt16:
+ case glslang::EOpConstructI16Vec2:
+ case glslang::EOpConstructI16Vec3:
+ case glslang::EOpConstructI16Vec4:
+ case glslang::EOpConstructUint16:
+ case glslang::EOpConstructU16Vec2:
+ case glslang::EOpConstructU16Vec3:
+ case glslang::EOpConstructU16Vec4:
+ case glslang::EOpConstructInt:
+ case glslang::EOpConstructIVec2:
+ case glslang::EOpConstructIVec3:
+ case glslang::EOpConstructIVec4:
+ case glslang::EOpConstructUint:
+ case glslang::EOpConstructUVec2:
+ case glslang::EOpConstructUVec3:
+ case glslang::EOpConstructUVec4:
+ case glslang::EOpConstructInt64:
+ case glslang::EOpConstructI64Vec2:
+ case glslang::EOpConstructI64Vec3:
+ case glslang::EOpConstructI64Vec4:
+ case glslang::EOpConstructUint64:
+ case glslang::EOpConstructU64Vec2:
+ case glslang::EOpConstructU64Vec3:
+ case glslang::EOpConstructU64Vec4:
+ case glslang::EOpConstructStruct:
+ case glslang::EOpConstructTextureSampler:
+ case glslang::EOpConstructReference:
+ case glslang::EOpConstructCooperativeMatrix:
+ {
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+ std::vector<spv::Id> arguments;
+ translateArguments(*node, arguments, lvalueCoherentFlags);
+ spv::Id constructed;
+ if (node->getOp() == glslang::EOpConstructTextureSampler)
+ constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments);
+ else if (node->getOp() == glslang::EOpConstructStruct ||
+ node->getOp() == glslang::EOpConstructCooperativeMatrix ||
+ node->getType().isArray()) {
+ std::vector<spv::Id> constituents;
+ for (int c = 0; c < (int)arguments.size(); ++c)
+ constituents.push_back(arguments[c]);
+ constructed = createCompositeConstruct(resultType(), constituents);
+ } else if (isMatrix)
+ constructed = builder.createMatrixConstructor(precision, arguments, resultType());
+ else
+ constructed = builder.createConstructor(precision, arguments, resultType());
+
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(constructed);
+
+ return false;
+ }
+
+ // These six are component-wise compares with component-wise results.
+ // Forward on to createBinaryOperation(), requesting a vector result.
+ case glslang::EOpLessThan:
+ case glslang::EOpGreaterThan:
+ case glslang::EOpLessThanEqual:
+ case glslang::EOpGreaterThanEqual:
+ case glslang::EOpVectorEqual:
+ case glslang::EOpVectorNotEqual:
+ {
+ // Map the operation to a binary
+ binOp = node->getOp();
+ reduceComparison = false;
+ switch (node->getOp()) {
+ case glslang::EOpVectorEqual: binOp = glslang::EOpVectorEqual; break;
+ case glslang::EOpVectorNotEqual: binOp = glslang::EOpVectorNotEqual; break;
+ default: binOp = node->getOp(); break;
+ }
+
+ break;
+ }
+ case glslang::EOpMul:
+ // component-wise matrix multiply
+ binOp = glslang::EOpMul;
+ break;
+ case glslang::EOpOuterProduct:
+ // two vectors multiplied to make a matrix
+ binOp = glslang::EOpOuterProduct;
+ break;
+ case glslang::EOpDot:
+ {
+ // for scalar dot product, use multiply
+ glslang::TIntermSequence& glslangOperands = node->getSequence();
+ if (glslangOperands[0]->getAsTyped()->getVectorSize() == 1)
+ binOp = glslang::EOpMul;
+ break;
+ }
+ case glslang::EOpMod:
+ // when an aggregate, this is the floating-point mod built-in function,
+ // which can be emitted by the one in createBinaryOperation()
+ binOp = glslang::EOpMod;
+ break;
+
+ case glslang::EOpEmitVertex:
+ case glslang::EOpEndPrimitive:
+ case glslang::EOpBarrier:
+ case glslang::EOpMemoryBarrier:
+ case glslang::EOpMemoryBarrierAtomicCounter:
+ case glslang::EOpMemoryBarrierBuffer:
+ case glslang::EOpMemoryBarrierImage:
+ case glslang::EOpMemoryBarrierShared:
+ case glslang::EOpGroupMemoryBarrier:
+ case glslang::EOpDeviceMemoryBarrier:
+ case glslang::EOpAllMemoryBarrierWithGroupSync:
+ case glslang::EOpDeviceMemoryBarrierWithGroupSync:
+ case glslang::EOpWorkgroupMemoryBarrier:
+ case glslang::EOpWorkgroupMemoryBarrierWithGroupSync:
+ case glslang::EOpSubgroupBarrier:
+ case glslang::EOpSubgroupMemoryBarrier:
+ case glslang::EOpSubgroupMemoryBarrierBuffer:
+ case glslang::EOpSubgroupMemoryBarrierImage:
+ case glslang::EOpSubgroupMemoryBarrierShared:
+ noReturnValue = true;
+ // These all have 0 operands and will naturally finish up in the code below for 0 operands
+ break;
+
+ case glslang::EOpAtomicAdd:
+ case glslang::EOpAtomicMin:
+ case glslang::EOpAtomicMax:
+ case glslang::EOpAtomicAnd:
+ case glslang::EOpAtomicOr:
+ case glslang::EOpAtomicXor:
+ case glslang::EOpAtomicExchange:
+ case glslang::EOpAtomicCompSwap:
+ atomic = true;
+ break;
+
+#ifndef GLSLANG_WEB
+ case glslang::EOpAtomicStore:
+ noReturnValue = true;
+ // fallthrough
+ case glslang::EOpAtomicLoad:
+ atomic = true;
+ break;
+
+ case glslang::EOpAtomicCounterAdd:
+ case glslang::EOpAtomicCounterSubtract:
+ case glslang::EOpAtomicCounterMin:
+ case glslang::EOpAtomicCounterMax:
+ case glslang::EOpAtomicCounterAnd:
+ case glslang::EOpAtomicCounterOr:
+ case glslang::EOpAtomicCounterXor:
+ case glslang::EOpAtomicCounterExchange:
+ case glslang::EOpAtomicCounterCompSwap:
+ builder.addExtension("SPV_KHR_shader_atomic_counter_ops");
+ builder.addCapability(spv::CapabilityAtomicStorageOps);
+ atomic = true;
+ break;
+
+ case glslang::EOpAbsDifference:
+ case glslang::EOpAddSaturate:
+ case glslang::EOpSubSaturate:
+ case glslang::EOpAverage:
+ case glslang::EOpAverageRounded:
+ case glslang::EOpMul32x16:
+ builder.addCapability(spv::CapabilityIntegerFunctions2INTEL);
+ builder.addExtension("SPV_INTEL_shader_integer_functions2");
+ binOp = node->getOp();
+ break;
+
+ case glslang::EOpIgnoreIntersectionNV:
+ case glslang::EOpTerminateRayNV:
+ case glslang::EOpTraceNV:
+ case glslang::EOpExecuteCallableNV:
+ case glslang::EOpWritePackedPrimitiveIndices4x8NV:
+ noReturnValue = true;
+ break;
+ case glslang::EOpCooperativeMatrixLoad:
+ case glslang::EOpCooperativeMatrixStore:
+ noReturnValue = true;
+ break;
+ case glslang::EOpBeginInvocationInterlock:
+ case glslang::EOpEndInvocationInterlock:
+ builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock);
+ noReturnValue = true;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ //
+ // See if it maps to a regular operation.
+ //
+ if (binOp != glslang::EOpNull) {
+ glslang::TIntermTyped* left = node->getSequence()[0]->getAsTyped();
+ glslang::TIntermTyped* right = node->getSequence()[1]->getAsTyped();
+ assert(left && right);
+
+ builder.clearAccessChain();
+ left->traverse(this);
+ spv::Id leftId = accessChainLoad(left->getType());
+
+ builder.clearAccessChain();
+ right->traverse(this);
+ spv::Id rightId = accessChainLoad(right->getType());
+
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+ OpDecorations decorations = { precision,
+ TranslateNoContractionDecoration(node->getType().getQualifier()),
+ TranslateNonUniformDecoration(node->getType().getQualifier()) };
+ result = createBinaryOperation(binOp, decorations,
+ resultType(), leftId, rightId,
+ left->getType().getBasicType(), reduceComparison);
+
+ // code above should only make binOp that exists in createBinaryOperation
+ assert(result != spv::NoResult);
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(result);
+
+ return false;
+ }
+
+ //
+ // Create the list of operands.
+ //
+ glslang::TIntermSequence& glslangOperands = node->getSequence();
+ std::vector<spv::Id> operands;
+ std::vector<spv::IdImmediate> memoryAccessOperands;
+ for (int arg = 0; arg < (int)glslangOperands.size(); ++arg) {
+ // special case l-value operands; there are just a few
+ bool lvalue = false;
+ switch (node->getOp()) {
+ case glslang::EOpModf:
+ if (arg == 1)
+ lvalue = true;
+ break;
+
+ case glslang::EOpAtomicAdd:
+ case glslang::EOpAtomicMin:
+ case glslang::EOpAtomicMax:
+ case glslang::EOpAtomicAnd:
+ case glslang::EOpAtomicOr:
+ case glslang::EOpAtomicXor:
+ case glslang::EOpAtomicExchange:
+ case glslang::EOpAtomicCompSwap:
+ if (arg == 0)
+ lvalue = true;
+ break;
+
+#ifndef GLSLANG_WEB
+ case glslang::EOpFrexp:
+ if (arg == 1)
+ lvalue = true;
+ break;
+ case glslang::EOpInterpolateAtSample:
+ case glslang::EOpInterpolateAtOffset:
+ case glslang::EOpInterpolateAtVertex:
+ if (arg == 0) {
+ lvalue = true;
+
+ // Does it need a swizzle inversion? If so, evaluation is inverted;
+ // operate first on the swizzle base, then apply the swizzle.
+ if (glslangOperands[0]->getAsOperator() &&
+ glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
+ invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType());
+ }
+ break;
+ case glslang::EOpAtomicLoad:
+ case glslang::EOpAtomicStore:
+ case glslang::EOpAtomicCounterAdd:
+ case glslang::EOpAtomicCounterSubtract:
+ case glslang::EOpAtomicCounterMin:
+ case glslang::EOpAtomicCounterMax:
+ case glslang::EOpAtomicCounterAnd:
+ case glslang::EOpAtomicCounterOr:
+ case glslang::EOpAtomicCounterXor:
+ case glslang::EOpAtomicCounterExchange:
+ case glslang::EOpAtomicCounterCompSwap:
+ if (arg == 0)
+ lvalue = true;
+ break;
+ case glslang::EOpAddCarry:
+ case glslang::EOpSubBorrow:
+ if (arg == 2)
+ lvalue = true;
+ break;
+ case glslang::EOpUMulExtended:
+ case glslang::EOpIMulExtended:
+ if (arg >= 2)
+ lvalue = true;
+ break;
+ case glslang::EOpCooperativeMatrixLoad:
+ if (arg == 0 || arg == 1)
+ lvalue = true;
+ break;
+ case glslang::EOpCooperativeMatrixStore:
+ if (arg == 1)
+ lvalue = true;
+ break;
+#endif
+ default:
+ break;
+ }
+ builder.clearAccessChain();
+ if (invertedType != spv::NoType && arg == 0)
+ glslangOperands[0]->getAsBinaryNode()->getLeft()->traverse(this);
+ else
+ glslangOperands[arg]->traverse(this);
+
+#ifndef GLSLANG_WEB
+ if (node->getOp() == glslang::EOpCooperativeMatrixLoad ||
+ node->getOp() == glslang::EOpCooperativeMatrixStore) {
+
+ if (arg == 1) {
+ // fold "element" parameter into the access chain
+ spv::Builder::AccessChain save = builder.getAccessChain();
+ builder.clearAccessChain();
+ glslangOperands[2]->traverse(this);
+
+ spv::Id elementId = accessChainLoad(glslangOperands[2]->getAsTyped()->getType());
+
+ builder.setAccessChain(save);
+
+ // Point to the first element of the array.
+ builder.accessChainPush(elementId, TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()),
+ glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment());
+
+ spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags;
+ unsigned int alignment = builder.getAccessChain().alignment;
+
+ int memoryAccess = TranslateMemoryAccess(coherentFlags);
+ if (node->getOp() == glslang::EOpCooperativeMatrixLoad)
+ memoryAccess &= ~spv::MemoryAccessMakePointerAvailableKHRMask;
+ if (node->getOp() == glslang::EOpCooperativeMatrixStore)
+ memoryAccess &= ~spv::MemoryAccessMakePointerVisibleKHRMask;
+ if (builder.getStorageClass(builder.getAccessChain().base) == spv::StorageClassPhysicalStorageBufferEXT) {
+ memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
+ }
+
+ memoryAccessOperands.push_back(spv::IdImmediate(false, memoryAccess));
+
+ if (memoryAccess & spv::MemoryAccessAlignedMask) {
+ memoryAccessOperands.push_back(spv::IdImmediate(false, alignment));
+ }
+
+ if (memoryAccess & (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) {
+ memoryAccessOperands.push_back(spv::IdImmediate(true, builder.makeUintConstant(TranslateMemoryScope(coherentFlags))));
+ }
+ } else if (arg == 2) {
+ continue;
+ }
+ }
+#endif
+
+ if (lvalue) {
+ operands.push_back(builder.accessChainGetLValue());
+ lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
+ lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType());
+ } else {
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+ operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
+ }
+ }
+
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+#ifndef GLSLANG_WEB
+ if (node->getOp() == glslang::EOpCooperativeMatrixLoad) {
+ std::vector<spv::IdImmediate> idImmOps;
+
+ idImmOps.push_back(spv::IdImmediate(true, operands[1])); // buf
+ idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride
+ idImmOps.push_back(spv::IdImmediate(true, operands[3])); // colMajor
+ idImmOps.insert(idImmOps.end(), memoryAccessOperands.begin(), memoryAccessOperands.end());
+ // get the pointee type
+ spv::Id typeId = builder.getContainedTypeId(builder.getTypeId(operands[0]));
+ assert(builder.isCooperativeMatrixType(typeId));
+ // do the op
+ spv::Id result = builder.createOp(spv::OpCooperativeMatrixLoadNV, typeId, idImmOps);
+ // store the result to the pointer (out param 'm')
+ builder.createStore(result, operands[0]);
+ result = 0;
+ } else if (node->getOp() == glslang::EOpCooperativeMatrixStore) {
+ std::vector<spv::IdImmediate> idImmOps;
+
+ idImmOps.push_back(spv::IdImmediate(true, operands[1])); // buf
+ idImmOps.push_back(spv::IdImmediate(true, operands[0])); // object
+ idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride
+ idImmOps.push_back(spv::IdImmediate(true, operands[3])); // colMajor
+ idImmOps.insert(idImmOps.end(), memoryAccessOperands.begin(), memoryAccessOperands.end());
+
+ builder.createNoResultOp(spv::OpCooperativeMatrixStoreNV, idImmOps);
+ result = 0;
+ } else
+#endif
+ if (atomic) {
+ // Handle all atomics
+ result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags);
+ } else {
+ // Pass through to generic operations.
+ switch (glslangOperands.size()) {
+ case 0:
+ result = createNoArgOperation(node->getOp(), precision, resultType());
+ break;
+ case 1:
+ {
+ OpDecorations decorations = { precision,
+ TranslateNoContractionDecoration(node->getType().getQualifier()),
+ TranslateNonUniformDecoration(node->getType().getQualifier()) };
+ result = createUnaryOperation(
+ node->getOp(), decorations,
+ resultType(), operands.front(),
+ glslangOperands[0]->getAsTyped()->getBasicType(), lvalueCoherentFlags);
+ }
+ break;
+ default:
+ result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
+ break;
+ }
+ if (invertedType)
+ result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result);
+ }
+
+ if (noReturnValue)
+ return false;
+
+ if (! result) {
+ logger->missingFunctionality("unknown glslang aggregate");
+ return true; // pick up a child as a placeholder operand
+ } else {
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(result);
+ return false;
+ }
+}
+
+// This path handles both if-then-else and ?:
+// The if-then-else has a node type of void, while
+// ?: has either a void or a non-void node type
+//
+// Leaving the result, when not void:
+// GLSL only has r-values as the result of a :?, but
+// if we have an l-value, that can be more efficient if it will
+// become the base of a complex r-value expression, because the
+// next layer copies r-values into memory to use the access-chain mechanism
+bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node)
+{
+ // see if OpSelect can handle it
+ const auto isOpSelectable = [&]() {
+ if (node->getBasicType() == glslang::EbtVoid)
+ return false;
+ // OpSelect can do all other types starting with SPV 1.4
+ if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4) {
+ // pre-1.4, only scalars and vectors can be handled
+ if ((!node->getType().isScalar() && !node->getType().isVector()))
+ return false;
+ }
+ return true;
+ };
+
+ // See if it simple and safe, or required, to execute both sides.
+ // Crucially, side effects must be either semantically required or avoided,
+ // and there are performance trade-offs.
+ // Return true if required or a good idea (and safe) to execute both sides,
+ // false otherwise.
+ const auto bothSidesPolicy = [&]() -> bool {
+ // do we have both sides?
+ if (node->getTrueBlock() == nullptr ||
+ node->getFalseBlock() == nullptr)
+ return false;
+
+ // required? (unless we write additional code to look for side effects
+ // and make performance trade-offs if none are present)
+ if (!node->getShortCircuit())
+ return true;
+
+ // if not required to execute both, decide based on performance/practicality...
+
+ if (!isOpSelectable())
+ return false;
+
+ assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() &&
+ node->getType() == node->getFalseBlock()->getAsTyped()->getType());
+
+ // return true if a single operand to ? : is okay for OpSelect
+ const auto operandOkay = [](glslang::TIntermTyped* node) {
+ return node->getAsSymbolNode() || node->getType().getQualifier().isConstant();
+ };
+
+ return operandOkay(node->getTrueBlock() ->getAsTyped()) &&
+ operandOkay(node->getFalseBlock()->getAsTyped());
+ };
+
+ spv::Id result = spv::NoResult; // upcoming result selecting between trueValue and falseValue
+ // emit the condition before doing anything with selection
+ node->getCondition()->traverse(this);
+ spv::Id condition = accessChainLoad(node->getCondition()->getType());
+
+ // Find a way of executing both sides and selecting the right result.
+ const auto executeBothSides = [&]() -> void {
+ // execute both sides
+ node->getTrueBlock()->traverse(this);
+ spv::Id trueValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
+ node->getFalseBlock()->traverse(this);
+ spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
+
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+
+ // done if void
+ if (node->getBasicType() == glslang::EbtVoid)
+ return;
+
+ // emit code to select between trueValue and falseValue
+
+ // see if OpSelect can handle it
+ if (isOpSelectable()) {
+ // Emit OpSelect for this selection.
+
+ // smear condition to vector, if necessary (AST is always scalar)
+ // Before 1.4, smear like for mix(), starting with 1.4, keep it scalar
+ if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4 && builder.isVector(trueValue)) {
+ condition = builder.smearScalar(spv::NoPrecision, condition,
+ builder.makeVectorType(builder.makeBoolType(),
+ builder.getNumComponents(trueValue)));
+ }
+
+ // OpSelect
+ result = builder.createTriOp(spv::OpSelect,
+ convertGlslangToSpvType(node->getType()), condition,
+ trueValue, falseValue);
+
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(result);
+ } else {
+ // We need control flow to select the result.
+ // TODO: Once SPIR-V OpSelect allows arbitrary types, eliminate this path.
+ result = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType()));
+
+ // Selection control:
+ const spv::SelectionControlMask control = TranslateSelectionControl(*node);
+
+ // make an "if" based on the value created by the condition
+ spv::Builder::If ifBuilder(condition, control, builder);
+
+ // emit the "then" statement
+ builder.createStore(trueValue, result);
+ ifBuilder.makeBeginElse();
+ // emit the "else" statement
+ builder.createStore(falseValue, result);
+
+ // finish off the control flow
+ ifBuilder.makeEndIf();
+
+ builder.clearAccessChain();
+ builder.setAccessChainLValue(result);
+ }
+ };
+
+ // Execute the one side needed, as per the condition
+ const auto executeOneSide = [&]() {
+ // Always emit control flow.
+ if (node->getBasicType() != glslang::EbtVoid)
+ result = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType()));
+
+ // Selection control:
+ const spv::SelectionControlMask control = TranslateSelectionControl(*node);
+
+ // make an "if" based on the value created by the condition
+ spv::Builder::If ifBuilder(condition, control, builder);
+
+ // emit the "then" statement
+ if (node->getTrueBlock() != nullptr) {
+ node->getTrueBlock()->traverse(this);
+ if (result != spv::NoResult)
+ builder.createStore(accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()), result);
+ }
+
+ if (node->getFalseBlock() != nullptr) {
+ ifBuilder.makeBeginElse();
+ // emit the "else" statement
+ node->getFalseBlock()->traverse(this);
+ if (result != spv::NoResult)
+ builder.createStore(accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()), result);
+ }
+
+ // finish off the control flow
+ ifBuilder.makeEndIf();
+
+ if (result != spv::NoResult) {
+ builder.clearAccessChain();
+ builder.setAccessChainLValue(result);
+ }
+ };
+
+ // Try for OpSelect (or a requirement to execute both sides)
+ if (bothSidesPolicy()) {
+ SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
+ if (node->getType().getQualifier().isSpecConstant())
+ spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
+ executeBothSides();
+ } else
+ executeOneSide();
+
+ return false;
+}
+
+bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::TIntermSwitch* node)
+{
+ // emit and get the condition before doing anything with switch
+ node->getCondition()->traverse(this);
+ spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType());
+
+ // Selection control:
+ const spv::SelectionControlMask control = TranslateSwitchControl(*node);
+
+ // browse the children to sort out code segments
+ int defaultSegment = -1;
+ std::vector<TIntermNode*> codeSegments;
+ glslang::TIntermSequence& sequence = node->getBody()->getSequence();
+ std::vector<int> caseValues;
+ std::vector<int> valueIndexToSegment(sequence.size()); // note: probably not all are used, it is an overestimate
+ for (glslang::TIntermSequence::iterator c = sequence.begin(); c != sequence.end(); ++c) {
+ TIntermNode* child = *c;
+ if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpDefault)
+ defaultSegment = (int)codeSegments.size();
+ else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) {
+ valueIndexToSegment[caseValues.size()] = (int)codeSegments.size();
+ caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()->getConstArray()[0].getIConst());
+ } else
+ codeSegments.push_back(child);
+ }
+
+ // handle the case where the last code segment is missing, due to no code
+ // statements between the last case and the end of the switch statement
+ if ((caseValues.size() && (int)codeSegments.size() == valueIndexToSegment[caseValues.size() - 1]) ||
+ (int)codeSegments.size() == defaultSegment)
+ codeSegments.push_back(nullptr);
+
+ // make the switch statement
+ std::vector<spv::Block*> segmentBlocks; // returned, as the blocks allocated in the call
+ builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks);
+
+ // emit all the code in the segments
+ breakForLoop.push(false);
+ for (unsigned int s = 0; s < codeSegments.size(); ++s) {
+ builder.nextSwitchSegment(segmentBlocks, s);
+ if (codeSegments[s])
+ codeSegments[s]->traverse(this);
+ else
+ builder.addSwitchBreak();
+ }
+ breakForLoop.pop();
+
+ builder.endSwitch(segmentBlocks);
+
+ return false;
+}
+
+void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node)
+{
+ int nextConst = 0;
+ spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false);
+
+ builder.clearAccessChain();
+ builder.setAccessChainRValue(constant);
+}
+
+bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIntermLoop* node)
+{
+ auto blocks = builder.makeNewLoop();
+ builder.createBranch(&blocks.head);
+
+ // Loop control:
+ std::vector<unsigned int> operands;
+ const spv::LoopControlMask control = TranslateLoopControl(*node, operands);
+
+ // Spec requires back edges to target header blocks, and every header block
+ // must dominate its merge block. Make a header block first to ensure these
+ // conditions are met. By definition, it will contain OpLoopMerge, followed
+ // by a block-ending branch. But we don't want to put any other body/test
+ // instructions in it, since the body/test may have arbitrary instructions,
+ // including merges of its own.
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+ builder.setBuildPoint(&blocks.head);
+ builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands);
+ if (node->testFirst() && node->getTest()) {
+ spv::Block& test = builder.makeNewBlock();
+ builder.createBranch(&test);
+
+ builder.setBuildPoint(&test);
+ node->getTest()->traverse(this);
+ spv::Id condition = accessChainLoad(node->getTest()->getType());
+ builder.createConditionalBranch(condition, &blocks.body, &blocks.merge);
+
+ builder.setBuildPoint(&blocks.body);
+ breakForLoop.push(true);
+ if (node->getBody())
+ node->getBody()->traverse(this);
+ builder.createBranch(&blocks.continue_target);
+ breakForLoop.pop();
+
+ builder.setBuildPoint(&blocks.continue_target);
+ if (node->getTerminal())
+ node->getTerminal()->traverse(this);
+ builder.createBranch(&blocks.head);
+ } else {
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+ builder.createBranch(&blocks.body);
+
+ breakForLoop.push(true);
+ builder.setBuildPoint(&blocks.body);
+ if (node->getBody())
+ node->getBody()->traverse(this);
+ builder.createBranch(&blocks.continue_target);
+ breakForLoop.pop();
+
+ builder.setBuildPoint(&blocks.continue_target);
+ if (node->getTerminal())
+ node->getTerminal()->traverse(this);
+ if (node->getTest()) {
+ node->getTest()->traverse(this);
+ spv::Id condition =
+ accessChainLoad(node->getTest()->getType());
+ builder.createConditionalBranch(condition, &blocks.head, &blocks.merge);
+ } else {
+ // TODO: unless there was a break/return/discard instruction
+ // somewhere in the body, this is an infinite loop, so we should
+ // issue a warning.
+ builder.createBranch(&blocks.head);
+ }
+ }
+ builder.setBuildPoint(&blocks.merge);
+ builder.closeLoop();
+ return false;
+}
+
+bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::TIntermBranch* node)
+{
+ if (node->getExpression())
+ node->getExpression()->traverse(this);
+
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+
+ switch (node->getFlowOp()) {
+ case glslang::EOpKill:
+ builder.makeDiscard();
+ break;
+ case glslang::EOpBreak:
+ if (breakForLoop.top())
+ builder.createLoopExit();
+ else
+ builder.addSwitchBreak();
+ break;
+ case glslang::EOpContinue:
+ builder.createLoopContinue();
+ break;
+ case glslang::EOpReturn:
+ if (node->getExpression()) {
+ const glslang::TType& glslangReturnType = node->getExpression()->getType();
+ spv::Id returnId = accessChainLoad(glslangReturnType);
+ if (builder.getTypeId(returnId) != currentFunction->getReturnType()) {
+ builder.clearAccessChain();
+ spv::Id copyId = builder.createVariable(spv::StorageClassFunction, currentFunction->getReturnType());
+ builder.setAccessChainLValue(copyId);
+ multiTypeStore(glslangReturnType, returnId);
+ returnId = builder.createLoad(copyId);
+ }
+ builder.makeReturn(false, returnId);
+ } else
+ builder.makeReturn(false);
+
+ builder.clearAccessChain();
+ break;
+
+#ifndef GLSLANG_WEB
+ case glslang::EOpDemote:
+ builder.createNoResultOp(spv::OpDemoteToHelperInvocationEXT);
+ builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation);
+ builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT);
+ break;
+#endif
+
+ default:
+ assert(0);
+ break;
+ }
+
+ return false;
+}
+
+spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node, spv::Id forcedType)
+{
+ // First, steer off constants, which are not SPIR-V variables, but
+ // can still have a mapping to a SPIR-V Id.
+ // This includes specialization constants.
+ if (node->getQualifier().isConstant()) {
+ spv::Id result = createSpvConstant(*node);
+ if (result != spv::NoResult)
+ return result;
+ }
+
+ // Now, handle actual variables
+ spv::StorageClass storageClass = TranslateStorageClass(node->getType());
+ spv::Id spvType = forcedType == spv::NoType ? convertGlslangToSpvType(node->getType())
+ : forcedType;
+
+ const bool contains16BitType = node->getType().contains16BitFloat() ||
+ node->getType().contains16BitInt();
+ if (contains16BitType) {
+ switch (storageClass) {
+ case spv::StorageClassInput:
+ case spv::StorageClassOutput:
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
+ builder.addCapability(spv::CapabilityStorageInputOutput16);
+ break;
+ case spv::StorageClassUniform:
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
+ if (node->getType().getQualifier().storage == glslang::EvqBuffer)
+ builder.addCapability(spv::CapabilityStorageUniformBufferBlock16);
+ else
+ builder.addCapability(spv::CapabilityStorageUniform16);
+ break;
+#ifndef GLSLANG_WEB
+ case spv::StorageClassPushConstant:
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
+ builder.addCapability(spv::CapabilityStoragePushConstant16);
+ break;
+ case spv::StorageClassStorageBuffer:
+ case spv::StorageClassPhysicalStorageBufferEXT:
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
+ builder.addCapability(spv::CapabilityStorageUniformBufferBlock16);
+ break;
+#endif
+ default:
+ if (node->getType().contains16BitFloat())
+ builder.addCapability(spv::CapabilityFloat16);
+ if (node->getType().contains16BitInt())
+ builder.addCapability(spv::CapabilityInt16);
+ break;
+ }
+ }
+
+ if (node->getType().contains8BitInt()) {
+ if (storageClass == spv::StorageClassPushConstant) {
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityStoragePushConstant8);
+ } else if (storageClass == spv::StorageClassUniform) {
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityUniformAndStorageBuffer8BitAccess);
+ } else if (storageClass == spv::StorageClassStorageBuffer) {
+ builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityStorageBuffer8BitAccess);
+ } else {
+ builder.addCapability(spv::CapabilityInt8);
+ }
+ }
+
+ const char* name = node->getName().c_str();
+ if (glslang::IsAnonymous(name))
+ name = "";
+
+ return builder.createVariable(storageClass, spvType, name);
+}
+
+// Return type Id of the sampled type.
+spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler)
+{
+ switch (sampler.type) {
+ case glslang::EbtInt: return builder.makeIntType(32);
+ case glslang::EbtUint: return builder.makeUintType(32);
+ case glslang::EbtFloat: return builder.makeFloatType(32);
+#ifndef GLSLANG_WEB
+ case glslang::EbtFloat16:
+ builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch);
+ builder.addCapability(spv::CapabilityFloat16ImageAMD);
+ return builder.makeFloatType(16);
+#endif
+ default:
+ assert(0);
+ return builder.makeFloatType(32);
+ }
+}
+
+// If node is a swizzle operation, return the type that should be used if
+// the swizzle base is first consumed by another operation, before the swizzle
+// is applied.
+spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyped& node)
+{
+ if (node.getAsOperator() &&
+ node.getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
+ return convertGlslangToSpvType(node.getAsBinaryNode()->getLeft()->getType());
+ else
+ return spv::NoType;
+}
+
+// When inverting a swizzle with a parent op, this function
+// will apply the swizzle operation to a completed parent operation.
+spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, spv::Id parentResult)
+{
+ std::vector<unsigned> swizzle;
+ convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle);
+ return builder.createRvalueSwizzle(precision, convertGlslangToSpvType(node.getType()), parentResult, swizzle);
+}
+
+// Convert a glslang AST swizzle node to a swizzle vector for building SPIR-V.
+void TGlslangToSpvTraverser::convertSwizzle(const glslang::TIntermAggregate& node, std::vector<unsigned>& swizzle)
+{
+ const glslang::TIntermSequence& swizzleSequence = node.getSequence();
+ for (int i = 0; i < (int)swizzleSequence.size(); ++i)
+ swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst());
+}
+
+// Convert from a glslang type to an SPV type, by calling into a
+// recursive version of this function. This establishes the inherited
+// layout state rooted from the top-level type.
+spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, bool forwardReferenceOnly)
+{
+ return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier(), false, forwardReferenceOnly);
+}
+
+// Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id.
+// explicitLayout can be kept the same throughout the hierarchical recursive walk.
+// Mutually recursive with convertGlslangStructToSpvType().
+spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type,
+ glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier,
+ bool lastBufferBlockMember, bool forwardReferenceOnly)
+{
+ spv::Id spvType = spv::NoResult;
+
+ switch (type.getBasicType()) {
+ case glslang::EbtVoid:
+ spvType = builder.makeVoidType();
+ assert (! type.isArray());
+ break;
+ case glslang::EbtBool:
+ // "transparent" bool doesn't exist in SPIR-V. The GLSL convention is
+ // a 32-bit int where non-0 means true.
+ if (explicitLayout != glslang::ElpNone)
+ spvType = builder.makeUintType(32);
+ else
+ spvType = builder.makeBoolType();
+ break;
+ case glslang::EbtInt:
+ spvType = builder.makeIntType(32);
+ break;
+ case glslang::EbtUint:
+ spvType = builder.makeUintType(32);
+ break;
+ case glslang::EbtFloat:
+ spvType = builder.makeFloatType(32);
+ break;
+#ifndef GLSLANG_WEB
+ case glslang::EbtDouble:
+ spvType = builder.makeFloatType(64);
+ break;
+ case glslang::EbtFloat16:
+ spvType = builder.makeFloatType(16);
+ break;
+ case glslang::EbtInt8:
+ spvType = builder.makeIntType(8);
+ break;
+ case glslang::EbtUint8:
+ spvType = builder.makeUintType(8);
+ break;
+ case glslang::EbtInt16:
+ spvType = builder.makeIntType(16);
+ break;
+ case glslang::EbtUint16:
+ spvType = builder.makeUintType(16);
+ break;
+ case glslang::EbtInt64:
+ spvType = builder.makeIntType(64);
+ break;
+ case glslang::EbtUint64:
+ spvType = builder.makeUintType(64);
+ break;
+ case glslang::EbtAtomicUint:
+ builder.addCapability(spv::CapabilityAtomicStorage);
+ spvType = builder.makeUintType(32);
+ break;
+ case glslang::EbtAccStructNV:
+ spvType = builder.makeAccelerationStructureNVType();
+ break;
+ case glslang::EbtReference:
+ {
+ // Make the forward pointer, then recurse to convert the structure type, then
+ // patch up the forward pointer with a real pointer type.
+ if (forwardPointers.find(type.getReferentType()) == forwardPointers.end()) {
+ spv::Id forwardId = builder.makeForwardPointer(spv::StorageClassPhysicalStorageBufferEXT);
+ forwardPointers[type.getReferentType()] = forwardId;
+ }
+ spvType = forwardPointers[type.getReferentType()];
+ if (!forwardReferenceOnly) {
+ spv::Id referentType = convertGlslangToSpvType(*type.getReferentType());
+ builder.makePointerFromForwardPointer(spv::StorageClassPhysicalStorageBufferEXT,
+ forwardPointers[type.getReferentType()],
+ referentType);
+ }
+ }
+ break;
+#endif
+ case glslang::EbtSampler:
+ {
+ const glslang::TSampler& sampler = type.getSampler();
+ if (sampler.isPureSampler()) {
+ spvType = builder.makeSamplerType();
+ } else {
+ // an image is present, make its type
+ spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler),
+ sampler.isShadow(), sampler.isArrayed(), sampler.isMultiSample(),
+ sampler.isImageClass() ? 2 : 1, TranslateImageFormat(type));
+ if (sampler.isCombined()) {
+ // already has both image and sampler, make the combined type
+ spvType = builder.makeSampledImageType(spvType);
+ }
+ }
+ }
+ break;
+ case glslang::EbtStruct:
+ case glslang::EbtBlock:
+ {
+ // If we've seen this struct type, return it
+ const glslang::TTypeList* glslangMembers = type.getStruct();
+
+ // Try to share structs for different layouts, but not yet for other
+ // kinds of qualification (primarily not yet including interpolant qualification).
+ if (! HasNonLayoutQualifiers(type, qualifier))
+ spvType = structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers];
+ if (spvType != spv::NoResult)
+ break;
+
+ // else, we haven't seen it...
+ if (type.getBasicType() == glslang::EbtBlock)
+ memberRemapper[glslangTypeToIdMap[glslangMembers]].resize(glslangMembers->size());
+ spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier);
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (type.isMatrix())
+ spvType = builder.makeMatrixType(spvType, type.getMatrixCols(), type.getMatrixRows());
+ else {
+ // If this variable has a vector element count greater than 1, create a SPIR-V vector
+ if (type.getVectorSize() > 1)
+ spvType = builder.makeVectorType(spvType, type.getVectorSize());
+ }
+
+ if (type.isCoopMat()) {
+ builder.addCapability(spv::CapabilityCooperativeMatrixNV);
+ builder.addExtension(spv::E_SPV_NV_cooperative_matrix);
+ if (type.getBasicType() == glslang::EbtFloat16)
+ builder.addCapability(spv::CapabilityFloat16);
+ if (type.getBasicType() == glslang::EbtUint8 ||
+ type.getBasicType() == glslang::EbtInt8) {
+ builder.addCapability(spv::CapabilityInt8);
+ }
+
+ spv::Id scope = makeArraySizeId(*type.getTypeParameters(), 1);
+ spv::Id rows = makeArraySizeId(*type.getTypeParameters(), 2);
+ spv::Id cols = makeArraySizeId(*type.getTypeParameters(), 3);
+
+ spvType = builder.makeCooperativeMatrixType(spvType, scope, rows, cols);
+ }
+
+ if (type.isArray()) {
+ int stride = 0; // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride
+
+ // Do all but the outer dimension
+ if (type.getArraySizes()->getNumDims() > 1) {
+ // We need to decorate array strides for types needing explicit layout, except blocks.
+ if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) {
+ // Use a dummy glslang type for querying internal strides of
+ // arrays of arrays, but using just a one-dimensional array.
+ glslang::TType simpleArrayType(type, 0); // deference type of the array
+ while (simpleArrayType.getArraySizes()->getNumDims() > 1)
+ simpleArrayType.getArraySizes()->dereference();
+
+ // Will compute the higher-order strides here, rather than making a whole
+ // pile of types and doing repetitive recursion on their contents.
+ stride = getArrayStride(simpleArrayType, explicitLayout, qualifier.layoutMatrix);
+ }
+
+ // make the arrays
+ for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
+ spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), dim), stride);
+ if (stride > 0)
+ builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
+ stride *= type.getArraySizes()->getDimSize(dim);
+ }
+ } else {
+ // single-dimensional array, and don't yet have stride
+
+ // We need to decorate array strides for types needing explicit layout, except blocks.
+ if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock)
+ stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix);
+ }
+
+ // Do the outer dimension, which might not be known for a runtime-sized array.
+ // (Unsized arrays that survive through linking will be runtime-sized arrays)
+ if (type.isSizedArray())
+ spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride);
+ else {
+#ifndef GLSLANG_WEB
+ if (!lastBufferBlockMember) {
+ builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
+ builder.addCapability(spv::CapabilityRuntimeDescriptorArrayEXT);
+ }
+#endif
+ spvType = builder.makeRuntimeArray(spvType);
+ }
+ if (stride > 0)
+ builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
+ }
+
+ return spvType;
+}
+
+// TODO: this functionality should exist at a higher level, in creating the AST
+//
+// Identify interface members that don't have their required extension turned on.
+//
+bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member)
+{
+#ifndef GLSLANG_WEB
+ auto& extensions = glslangIntermediate->getRequestedExtensions();
+
+ if (member.getFieldName() == "gl_SecondaryViewportMaskNV" &&
+ extensions.find("GL_NV_stereo_view_rendering") == extensions.end())
+ return true;
+ if (member.getFieldName() == "gl_SecondaryPositionNV" &&
+ extensions.find("GL_NV_stereo_view_rendering") == extensions.end())
+ return true;
+
+ if (glslangIntermediate->getStage() != EShLangMeshNV) {
+ if (member.getFieldName() == "gl_ViewportMask" &&
+ extensions.find("GL_NV_viewport_array2") == extensions.end())
+ return true;
+ if (member.getFieldName() == "gl_PositionPerViewNV" &&
+ extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end())
+ return true;
+ if (member.getFieldName() == "gl_ViewportMaskPerViewNV" &&
+ extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end())
+ return true;
+ }
+#endif
+
+ return false;
+};
+
+// Do full recursive conversion of a glslang structure (or block) type to a SPIR-V Id.
+// explicitLayout can be kept the same throughout the hierarchical recursive walk.
+// Mutually recursive with convertGlslangToSpvType().
+spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TType& type,
+ const glslang::TTypeList* glslangMembers,
+ glslang::TLayoutPacking explicitLayout,
+ const glslang::TQualifier& qualifier)
+{
+ // Create a vector of struct types for SPIR-V to consume
+ std::vector<spv::Id> spvMembers;
+ int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks
+ std::vector<std::pair<glslang::TType*, glslang::TQualifier> > deferredForwardPointers;
+ for (int i = 0; i < (int)glslangMembers->size(); i++) {
+ glslang::TType& glslangMember = *(*glslangMembers)[i].type;
+ if (glslangMember.hiddenMember()) {
+ ++memberDelta;
+ if (type.getBasicType() == glslang::EbtBlock)
+ memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1;
+ } else {
+ if (type.getBasicType() == glslang::EbtBlock) {
+ if (filterMember(glslangMember)) {
+ memberDelta++;
+ memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1;
+ continue;
+ }
+ memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta;
+ }
+ // modify just this child's view of the qualifier
+ glslang::TQualifier memberQualifier = glslangMember.getQualifier();
+ InheritQualifiers(memberQualifier, qualifier);
+
+ // manually inherit location
+ if (! memberQualifier.hasLocation() && qualifier.hasLocation())
+ memberQualifier.layoutLocation = qualifier.layoutLocation;
+
+ // recurse
+ bool lastBufferBlockMember = qualifier.storage == glslang::EvqBuffer &&
+ i == (int)glslangMembers->size() - 1;
+
+ // Make forward pointers for any pointer members, and create a list of members to
+ // convert to spirv types after creating the struct.
+ if (glslangMember.isReference()) {
+ if (forwardPointers.find(glslangMember.getReferentType()) == forwardPointers.end()) {
+ deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier));
+ }
+ spvMembers.push_back(
+ convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, true));
+ } else {
+ spvMembers.push_back(
+ convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, false));
+ }
+ }
+ }
+
+ // Make the SPIR-V type
+ spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str());
+ if (! HasNonLayoutQualifiers(type, qualifier))
+ structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType;
+
+ // Decorate it
+ decorateStructType(type, glslangMembers, explicitLayout, qualifier, spvType);
+
+ for (int i = 0; i < (int)deferredForwardPointers.size(); ++i) {
+ auto it = deferredForwardPointers[i];
+ convertGlslangToSpvType(*it.first, explicitLayout, it.second, false);
+ }
+
+ return spvType;
+}
+
+void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
+ const glslang::TTypeList* glslangMembers,
+ glslang::TLayoutPacking explicitLayout,
+ const glslang::TQualifier& qualifier,
+ spv::Id spvType)
+{
+ // Name and decorate the non-hidden members
+ int offset = -1;
+ int locationOffset = 0; // for use within the members of this struct
+ for (int i = 0; i < (int)glslangMembers->size(); i++) {
+ glslang::TType& glslangMember = *(*glslangMembers)[i].type;
+ int member = i;
+ if (type.getBasicType() == glslang::EbtBlock) {
+ member = memberRemapper[glslangTypeToIdMap[glslangMembers]][i];
+ if (filterMember(glslangMember))
+ continue;
+ }
+
+ // modify just this child's view of the qualifier
+ glslang::TQualifier memberQualifier = glslangMember.getQualifier();
+ InheritQualifiers(memberQualifier, qualifier);
+
+ // using -1 above to indicate a hidden member
+ if (member < 0)
+ continue;
+
+ builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str());
+ builder.addMemberDecoration(spvType, member,
+ TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix));
+ builder.addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember));
+ // Add interpolation and auxiliary storage decorations only to
+ // top-level members of Input and Output storage classes
+ if (type.getQualifier().storage == glslang::EvqVaryingIn ||
+ type.getQualifier().storage == glslang::EvqVaryingOut) {
+ if (type.getBasicType() == glslang::EbtBlock ||
+ glslangIntermediate->getSource() == glslang::EShSourceHlsl) {
+ builder.addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier));
+ builder.addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier));
+#ifndef GLSLANG_WEB
+ addMeshNVDecoration(spvType, member, memberQualifier);
+#endif
+ }
+ }
+ builder.addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier));
+
+#ifndef GLSLANG_WEB
+ if (type.getBasicType() == glslang::EbtBlock &&
+ qualifier.storage == glslang::EvqBuffer) {
+ // Add memory decorations only to top-level members of shader storage block
+ std::vector<spv::Decoration> memory;
+ TranslateMemoryDecoration(memberQualifier, memory, glslangIntermediate->usingVulkanMemoryModel());
+ for (unsigned int i = 0; i < memory.size(); ++i)
+ builder.addMemberDecoration(spvType, member, memory[i]);
+ }
+
+#endif
+
+ // Location assignment was already completed correctly by the front end,
+ // just track whether a member needs to be decorated.
+ // Ignore member locations if the container is an array, as that's
+ // ill-specified and decisions have been made to not allow this.
+ if (! type.isArray() && memberQualifier.hasLocation())
+ builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation);
+
+ if (qualifier.hasLocation()) // track for upcoming inheritance
+ locationOffset += glslangIntermediate->computeTypeLocationSize(
+ glslangMember, glslangIntermediate->getStage());
+
+ // component, XFB, others
+ if (glslangMember.getQualifier().hasComponent())
+ builder.addMemberDecoration(spvType, member, spv::DecorationComponent,
+ glslangMember.getQualifier().layoutComponent);
+ if (glslangMember.getQualifier().hasXfbOffset())
+ builder.addMemberDecoration(spvType, member, spv::DecorationOffset,
+ glslangMember.getQualifier().layoutXfbOffset);
+ else if (explicitLayout != glslang::ElpNone) {
+ // figure out what to do with offset, which is accumulating
+ int nextOffset;
+ updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix);
+ if (offset >= 0)
+ builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset);
+ offset = nextOffset;
+ }
+
+ if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone)
+ builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride,
+ getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix));
+
+ // built-in variable decorations
+ spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true);
+ if (builtIn != spv::BuiltInMax)
+ builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn);
+
+#ifndef GLSLANG_WEB
+ // nonuniform
+ builder.addMemberDecoration(spvType, member, TranslateNonUniformDecoration(glslangMember.getQualifier()));
+
+ if (glslangIntermediate->getHlslFunctionality1() && memberQualifier.semanticName != nullptr) {
+ builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
+ builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE,
+ memberQualifier.semanticName);
+ }
+
+ if (builtIn == spv::BuiltInLayer) {
+ // SPV_NV_viewport_array2 extension
+ if (glslangMember.getQualifier().layoutViewportRelative){
+ builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationViewportRelativeNV);
+ builder.addCapability(spv::CapabilityShaderViewportMaskNV);
+ builder.addExtension(spv::E_SPV_NV_viewport_array2);
+ }
+ if (glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset != -2048){
+ builder.addMemberDecoration(spvType, member,
+ (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV,
+ glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset);
+ builder.addCapability(spv::CapabilityShaderStereoViewNV);
+ builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
+ }
+ }
+ if (glslangMember.getQualifier().layoutPassthrough) {
+ builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationPassthroughNV);
+ builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
+ builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
+ }
+#endif
+ }
+
+ // Decorate the structure
+ builder.addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix));
+ builder.addDecoration(spvType, TranslateBlockDecoration(type, glslangIntermediate->usingStorageBuffer()));
+}
+
+// Turn the expression forming the array size into an id.
+// This is not quite trivial, because of specialization constants.
+// Sometimes, a raw constant is turned into an Id, and sometimes
+// a specialization constant expression is.
+spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arraySizes, int dim)
+{
+ // First, see if this is sized with a node, meaning a specialization constant:
+ glslang::TIntermTyped* specNode = arraySizes.getDimNode(dim);
+ if (specNode != nullptr) {
+ builder.clearAccessChain();
+ specNode->traverse(this);
+ return accessChainLoad(specNode->getAsTyped()->getType());
+ }
+
+ // Otherwise, need a compile-time (front end) size, get it:
+ int size = arraySizes.getDimSize(dim);
+ assert(size > 0);
+ return builder.makeUintConstant(size);
+}
+
+// Wrap the builder's accessChainLoad to:
+// - localize handling of RelaxedPrecision
+// - use the SPIR-V inferred type instead of another conversion of the glslang type
+// (avoids unnecessary work and possible type punning for structures)
+// - do conversion of concrete to abstract type
+spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
+{
+ spv::Id nominalTypeId = builder.accessChainGetInferredType();
+
+ spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags;
+ coherentFlags |= TranslateCoherent(type);
+
+ unsigned int alignment = builder.getAccessChain().alignment;
+ alignment |= type.getBufferReferenceAlignment();
+
+ spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type),
+ TranslateNonUniformDecoration(type.getQualifier()),
+ nominalTypeId,
+ spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
+ TranslateMemoryScope(coherentFlags),
+ alignment);
+
+ // Need to convert to abstract types when necessary
+ if (type.getBasicType() == glslang::EbtBool) {
+ if (builder.isScalarType(nominalTypeId)) {
+ // Conversion for bool
+ spv::Id boolType = builder.makeBoolType();
+ if (nominalTypeId != boolType)
+ loadedId = builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0));
+ } else if (builder.isVectorType(nominalTypeId)) {
+ // Conversion for bvec
+ int vecSize = builder.getNumTypeComponents(nominalTypeId);
+ spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
+ if (nominalTypeId != bvecType)
+ loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, makeSmearedConstant(builder.makeUintConstant(0), vecSize));
+ }
+ }
+
+ return loadedId;
+}
+
+// Wrap the builder's accessChainStore to:
+// - do conversion of concrete to abstract type
+//
+// Implicitly uses the existing builder.accessChain as the storage target.
+void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::Id rvalue)
+{
+ // Need to convert to abstract types when necessary
+ if (type.getBasicType() == glslang::EbtBool) {
+ spv::Id nominalTypeId = builder.accessChainGetInferredType();
+
+ if (builder.isScalarType(nominalTypeId)) {
+ // Conversion for bool
+ spv::Id boolType = builder.makeBoolType();
+ if (nominalTypeId != boolType) {
+ // keep these outside arguments, for determinant order-of-evaluation
+ spv::Id one = builder.makeUintConstant(1);
+ spv::Id zero = builder.makeUintConstant(0);
+ rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero);
+ } else if (builder.getTypeId(rvalue) != boolType)
+ rvalue = builder.createBinOp(spv::OpINotEqual, boolType, rvalue, builder.makeUintConstant(0));
+ } else if (builder.isVectorType(nominalTypeId)) {
+ // Conversion for bvec
+ int vecSize = builder.getNumTypeComponents(nominalTypeId);
+ spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
+ if (nominalTypeId != bvecType) {
+ // keep these outside arguments, for determinant order-of-evaluation
+ spv::Id one = makeSmearedConstant(builder.makeUintConstant(1), vecSize);
+ spv::Id zero = makeSmearedConstant(builder.makeUintConstant(0), vecSize);
+ rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero);
+ } else if (builder.getTypeId(rvalue) != bvecType)
+ rvalue = builder.createBinOp(spv::OpINotEqual, bvecType, rvalue,
+ makeSmearedConstant(builder.makeUintConstant(0), vecSize));
+ }
+ }
+
+ spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags;
+ coherentFlags |= TranslateCoherent(type);
+
+ unsigned int alignment = builder.getAccessChain().alignment;
+ alignment |= type.getBufferReferenceAlignment();
+
+ builder.accessChainStore(rvalue,
+ spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerVisibleKHRMask),
+ TranslateMemoryScope(coherentFlags), alignment);
+}
+
+// For storing when types match at the glslang level, but not might match at the
+// SPIR-V level.
+//
+// This especially happens when a single glslang type expands to multiple
+// SPIR-V types, like a struct that is used in a member-undecorated way as well
+// as in a member-decorated way.
+//
+// NOTE: This function can handle any store request; if it's not special it
+// simplifies to a simple OpStore.
+//
+// Implicitly uses the existing builder.accessChain as the storage target.
+void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id rValue)
+{
+ // we only do the complex path here if it's an aggregate
+ if (! type.isStruct() && ! type.isArray()) {
+ accessChainStore(type, rValue);
+ return;
+ }
+
+ // and, it has to be a case of type aliasing
+ spv::Id rType = builder.getTypeId(rValue);
+ spv::Id lValue = builder.accessChainGetLValue();
+ spv::Id lType = builder.getContainedTypeId(builder.getTypeId(lValue));
+ if (lType == rType) {
+ accessChainStore(type, rValue);
+ return;
+ }
+
+ // Recursively (as needed) copy an aggregate type to a different aggregate type,
+ // where the two types were the same type in GLSL. This requires member
+ // by member copy, recursively.
+
+ // SPIR-V 1.4 added an instruction to do help do this.
+ if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) {
+ // However, bool in uniform space is changed to int, so
+ // OpCopyLogical does not work for that.
+ // TODO: It would be more robust to do a full recursive verification of the types satisfying SPIR-V rules.
+ bool rBool = builder.containsType(builder.getTypeId(rValue), spv::OpTypeBool, 0);
+ bool lBool = builder.containsType(lType, spv::OpTypeBool, 0);
+ if (lBool == rBool) {
+ spv::Id logicalCopy = builder.createUnaryOp(spv::OpCopyLogical, lType, rValue);
+ accessChainStore(type, logicalCopy);
+ return;
+ }
+ }
+
+ // If an array, copy element by element.
+ if (type.isArray()) {
+ glslang::TType glslangElementType(type, 0);
+ spv::Id elementRType = builder.getContainedTypeId(rType);
+ for (int index = 0; index < type.getOuterArraySize(); ++index) {
+ // get the source member
+ spv::Id elementRValue = builder.createCompositeExtract(rValue, elementRType, index);
+
+ // set up the target storage
+ builder.clearAccessChain();
+ builder.setAccessChainLValue(lValue);
+ builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), type.getBufferReferenceAlignment());
+
+ // store the member
+ multiTypeStore(glslangElementType, elementRValue);
+ }
+ } else {
+ assert(type.isStruct());
+
+ // loop over structure members
+ const glslang::TTypeList& members = *type.getStruct();
+ for (int m = 0; m < (int)members.size(); ++m) {
+ const glslang::TType& glslangMemberType = *members[m].type;
+
+ // get the source member
+ spv::Id memberRType = builder.getContainedTypeId(rType, m);
+ spv::Id memberRValue = builder.createCompositeExtract(rValue, memberRType, m);
+
+ // set up the target storage
+ builder.clearAccessChain();
+ builder.setAccessChainLValue(lValue);
+ builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), type.getBufferReferenceAlignment());
+
+ // store the member
+ multiTypeStore(glslangMemberType, memberRValue);
+ }
+ }
+}
+
+// Decide whether or not this type should be
+// decorated with offsets and strides, and if so
+// whether std140 or std430 rules should be applied.
+glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang::TType& type) const
+{
+ // has to be a block
+ if (type.getBasicType() != glslang::EbtBlock)
+ return glslang::ElpNone;
+
+ // has to be a uniform or buffer block or task in/out blocks
+ if (type.getQualifier().storage != glslang::EvqUniform &&
+ type.getQualifier().storage != glslang::EvqBuffer &&
+ !type.getQualifier().isTaskMemory())
+ return glslang::ElpNone;
+
+ // return the layout to use
+ switch (type.getQualifier().layoutPacking) {
+ case glslang::ElpStd140:
+ case glslang::ElpStd430:
+ case glslang::ElpScalar:
+ return type.getQualifier().layoutPacking;
+ default:
+ return glslang::ElpNone;
+ }
+}
+
+// Given an array type, returns the integer stride required for that array
+int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
+{
+ int size;
+ int stride;
+ glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
+
+ return stride;
+}
+
+// Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix
+// when used as a member of an interface block
+int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
+{
+ glslang::TType elementType;
+ elementType.shallowCopy(matrixType);
+ elementType.clearArraySizes();
+
+ int size;
+ int stride;
+ glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
+
+ return stride;
+}
+
+// Given a member type of a struct, realign the current offset for it, and compute
+// the next (not yet aligned) offset for the next member, which will get aligned
+// on the next call.
+// 'currentOffset' should be passed in already initialized, ready to modify, and reflecting
+// the migration of data from nextOffset -> currentOffset. It should be -1 on the first call.
+// -1 means a non-forced member offset (no decoration needed).
+void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset,
+ glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
+{
+ // this will get a positive value when deemed necessary
+ nextOffset = -1;
+
+ // override anything in currentOffset with user-set offset
+ if (memberType.getQualifier().hasOffset())
+ currentOffset = memberType.getQualifier().layoutOffset;
+
+ // It could be that current linker usage in glslang updated all the layoutOffset,
+ // in which case the following code does not matter. But, that's not quite right
+ // once cross-compilation unit GLSL validation is done, as the original user
+ // settings are needed in layoutOffset, and then the following will come into play.
+
+ if (explicitLayout == glslang::ElpNone) {
+ if (! memberType.getQualifier().hasOffset())
+ currentOffset = -1;
+
+ return;
+ }
+
+ // Getting this far means we need explicit offsets
+ if (currentOffset < 0)
+ currentOffset = 0;
+
+ // Now, currentOffset is valid (either 0, or from a previous nextOffset),
+ // but possibly not yet correctly aligned.
+
+ int memberSize;
+ int dummyStride;
+ int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
+
+ // Adjust alignment for HLSL rules
+ // TODO: make this consistent in early phases of code:
+ // adjusting this late means inconsistencies with earlier code, which for reflection is an issue
+ // Until reflection is brought in sync with these adjustments, don't apply to $Global,
+ // which is the most likely to rely on reflection, and least likely to rely implicit layouts
+ if (glslangIntermediate->usingHlslOffsets() &&
+ ! memberType.isArray() && memberType.isVector() && structType.getTypeName().compare("$Global") != 0) {
+ int dummySize;
+ int componentAlignment = glslangIntermediate->getBaseAlignmentScalar(memberType, dummySize);
+ if (componentAlignment <= 4)
+ memberAlignment = componentAlignment;
+ }
+
+ // Bump up to member alignment
+ glslang::RoundToPow2(currentOffset, memberAlignment);
+
+ // Bump up to vec4 if there is a bad straddle
+ if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset))
+ glslang::RoundToPow2(currentOffset, 16);
+
+ nextOffset = currentOffset + memberSize;
+}
+
+void TGlslangToSpvTraverser::declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember)
+{
+ const glslang::TBuiltInVariable glslangBuiltIn = members[glslangMember].type->getQualifier().builtIn;
+ switch (glslangBuiltIn)
+ {
+ case glslang::EbvPointSize:
+#ifndef GLSLANG_WEB
+ case glslang::EbvClipDistance:
+ case glslang::EbvCullDistance:
+ case glslang::EbvViewportMaskNV:
+ case glslang::EbvSecondaryPositionNV:
+ case glslang::EbvSecondaryViewportMaskNV:
+ case glslang::EbvPositionPerViewNV:
+ case glslang::EbvViewportMaskPerViewNV:
+ case glslang::EbvTaskCountNV:
+ case glslang::EbvPrimitiveCountNV:
+ case glslang::EbvPrimitiveIndicesNV:
+ case glslang::EbvClipDistancePerViewNV:
+ case glslang::EbvCullDistancePerViewNV:
+ case glslang::EbvLayerPerViewNV:
+ case glslang::EbvMeshViewCountNV:
+ case glslang::EbvMeshViewIndicesNV:
+#endif
+ // Generate the associated capability. Delegate to TranslateBuiltInDecoration.
+ // Alternately, we could just call this for any glslang built-in, since the
+ // capability already guards against duplicates.
+ TranslateBuiltInDecoration(glslangBuiltIn, false);
+ break;
+ default:
+ // Capabilities were already generated when the struct was declared.
+ break;
+ }
+}
+
+bool TGlslangToSpvTraverser::isShaderEntryPoint(const glslang::TIntermAggregate* node)
+{
+ return node->getName().compare(glslangIntermediate->getEntryPointMangledName().c_str()) == 0;
+}
+
+// Does parameter need a place to keep writes, separate from the original?
+// Assumes called after originalParam(), which filters out block/buffer/opaque-based
+// qualifiers such that we should have only in/out/inout/constreadonly here.
+bool TGlslangToSpvTraverser::writableParam(glslang::TStorageQualifier qualifier) const
+{
+ assert(qualifier == glslang::EvqIn ||
+ qualifier == glslang::EvqOut ||
+ qualifier == glslang::EvqInOut ||
+ qualifier == glslang::EvqConstReadOnly);
+ return qualifier != glslang::EvqConstReadOnly;
+}
+
+// Is parameter pass-by-original?
+bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier, const glslang::TType& paramType,
+ bool implicitThisParam)
+{
+ if (implicitThisParam) // implicit this
+ return true;
+ if (glslangIntermediate->getSource() == glslang::EShSourceHlsl)
+ return paramType.getBasicType() == glslang::EbtBlock;
+ return paramType.containsOpaque() || // sampler, etc.
+ (paramType.getBasicType() == glslang::EbtBlock && qualifier == glslang::EvqBuffer); // SSBO
+}
+
+// Make all the functions, skeletally, without actually visiting their bodies.
+void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions)
+{
+ const auto getParamDecorations = [&](std::vector<spv::Decoration>& decorations, const glslang::TType& type, bool useVulkanMemoryModel) {
+ spv::Decoration paramPrecision = TranslatePrecisionDecoration(type);
+ if (paramPrecision != spv::NoPrecision)
+ decorations.push_back(paramPrecision);
+ TranslateMemoryDecoration(type.getQualifier(), decorations, useVulkanMemoryModel);
+ if (type.isReference()) {
+ // Original and non-writable params pass the pointer directly and
+ // use restrict/aliased, others are stored to a pointer in Function
+ // memory and use RestrictPointer/AliasedPointer.
+ if (originalParam(type.getQualifier().storage, type, false) ||
+ !writableParam(type.getQualifier().storage)) {
+ decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrict :
+ spv::DecorationAliased);
+ } else {
+ decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrictPointerEXT :
+ spv::DecorationAliasedPointerEXT);
+ }
+ }
+ };
+
+ for (int f = 0; f < (int)glslFunctions.size(); ++f) {
+ glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate();
+ if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction || isShaderEntryPoint(glslFunction))
+ continue;
+
+ // We're on a user function. Set up the basic interface for the function now,
+ // so that it's available to call. Translating the body will happen later.
+ //
+ // Typically (except for a "const in" parameter), an address will be passed to the
+ // function. What it is an address of varies:
+ //
+ // - "in" parameters not marked as "const" can be written to without modifying the calling
+ // argument so that write needs to be to a copy, hence the address of a copy works.
+ //
+ // - "const in" parameters can just be the r-value, as no writes need occur.
+ //
+ // - "out" and "inout" arguments can't be done as pointers to the calling argument, because
+ // GLSL has copy-in/copy-out semantics. They can be handled though with a pointer to a copy.
+
+ std::vector<spv::Id> paramTypes;
+ std::vector<std::vector<spv::Decoration>> paramDecorations; // list of decorations per parameter
+ glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence();
+
+#ifdef ENABLE_HLSL
+ bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() ==
+ glslangIntermediate->implicitThisName;
+#else
+ bool implicitThis = false;
+#endif
+
+ paramDecorations.resize(parameters.size());
+ for (int p = 0; p < (int)parameters.size(); ++p) {
+ const glslang::TType& paramType = parameters[p]->getAsTyped()->getType();
+ spv::Id typeId = convertGlslangToSpvType(paramType);
+ if (originalParam(paramType.getQualifier().storage, paramType, implicitThis && p == 0))
+ typeId = builder.makePointer(TranslateStorageClass(paramType), typeId);
+ else if (writableParam(paramType.getQualifier().storage))
+ typeId = builder.makePointer(spv::StorageClassFunction, typeId);
+ else
+ rValueParameters.insert(parameters[p]->getAsSymbolNode()->getId());
+ getParamDecorations(paramDecorations[p], paramType, glslangIntermediate->usingVulkanMemoryModel());
+ paramTypes.push_back(typeId);
+ }
+
+ spv::Block* functionBlock;
+ spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()),
+ convertGlslangToSpvType(glslFunction->getType()),
+ glslFunction->getName().c_str(), paramTypes,
+ paramDecorations, &functionBlock);
+ if (implicitThis)
+ function->setImplicitThis();
+
+ // Track function to emit/call later
+ functionMap[glslFunction->getName().c_str()] = function;
+
+ // Set the parameter id's
+ for (int p = 0; p < (int)parameters.size(); ++p) {
+ symbolValues[parameters[p]->getAsSymbolNode()->getId()] = function->getParamId(p);
+ // give a name too
+ builder.addName(function->getParamId(p), parameters[p]->getAsSymbolNode()->getName().c_str());
+
+ const glslang::TType& paramType = parameters[p]->getAsTyped()->getType();
+ if (paramType.contains8BitInt())
+ builder.addCapability(spv::CapabilityInt8);
+ if (paramType.contains16BitInt())
+ builder.addCapability(spv::CapabilityInt16);
+ if (paramType.contains16BitFloat())
+ builder.addCapability(spv::CapabilityFloat16);
+ }
+ }
+}
+
+// Process all the initializers, while skipping the functions and link objects
+void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequence& initializers)
+{
+ builder.setBuildPoint(shaderEntry->getLastBlock());
+ for (int i = 0; i < (int)initializers.size(); ++i) {
+ glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate();
+ if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != glslang::EOpLinkerObjects) {
+
+ // We're on a top-level node that's not a function. Treat as an initializer, whose
+ // code goes into the beginning of the entry point.
+ initializer->traverse(this);
+ }
+ }
+}
+
+// Process all the functions, while skipping initializers.
+void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions)
+{
+ for (int f = 0; f < (int)glslFunctions.size(); ++f) {
+ glslang::TIntermAggregate* node = glslFunctions[f]->getAsAggregate();
+ if (node && (node->getOp() == glslang::EOpFunction || node->getOp() == glslang::EOpLinkerObjects))
+ node->traverse(this);
+ }
+}
+
+void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate* node)
+{
+ // SPIR-V functions should already be in the functionMap from the prepass
+ // that called makeFunctions().
+ currentFunction = functionMap[node->getName().c_str()];
+ spv::Block* functionBlock = currentFunction->getEntryBlock();
+ builder.setBuildPoint(functionBlock);
+}
+
+void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
+{
+ const glslang::TIntermSequence& glslangArguments = node.getSequence();
+
+ glslang::TSampler sampler = {};
+ bool cubeCompare = false;
+#ifndef GLSLANG_WEB
+ bool f16ShadowCompare = false;
+#endif
+ if (node.isTexture() || node.isImage()) {
+ sampler = glslangArguments[0]->getAsTyped()->getType().getSampler();
+ cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
+#ifndef GLSLANG_WEB
+ f16ShadowCompare = sampler.shadow && glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16;
+#endif
+ }
+
+ for (int i = 0; i < (int)glslangArguments.size(); ++i) {
+ builder.clearAccessChain();
+ glslangArguments[i]->traverse(this);
+
+#ifndef GLSLANG_WEB
+ // Special case l-value operands
+ bool lvalue = false;
+ switch (node.getOp()) {
+ case glslang::EOpImageAtomicAdd:
+ case glslang::EOpImageAtomicMin:
+ case glslang::EOpImageAtomicMax:
+ case glslang::EOpImageAtomicAnd:
+ case glslang::EOpImageAtomicOr:
+ case glslang::EOpImageAtomicXor:
+ case glslang::EOpImageAtomicExchange:
+ case glslang::EOpImageAtomicCompSwap:
+ case glslang::EOpImageAtomicLoad:
+ case glslang::EOpImageAtomicStore:
+ if (i == 0)
+ lvalue = true;
+ break;
+ case glslang::EOpSparseImageLoad:
+ if ((sampler.ms && i == 3) || (! sampler.ms && i == 2))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTexture:
+ if (((cubeCompare || f16ShadowCompare) && i == 3) || (! (cubeCompare || f16ShadowCompare) && i == 2))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureClamp:
+ if (((cubeCompare || f16ShadowCompare) && i == 4) || (! (cubeCompare || f16ShadowCompare) && i == 3))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureLod:
+ case glslang::EOpSparseTextureOffset:
+ if ((f16ShadowCompare && i == 4) || (! f16ShadowCompare && i == 3))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureFetch:
+ if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureFetchOffset:
+ if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureLodOffset:
+ case glslang::EOpSparseTextureGrad:
+ case glslang::EOpSparseTextureOffsetClamp:
+ if ((f16ShadowCompare && i == 5) || (! f16ShadowCompare && i == 4))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureGradOffset:
+ case glslang::EOpSparseTextureGradClamp:
+ if ((f16ShadowCompare && i == 6) || (! f16ShadowCompare && i == 5))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureGradOffsetClamp:
+ if ((f16ShadowCompare && i == 7) || (! f16ShadowCompare && i == 6))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureGather:
+ if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureGatherOffset:
+ case glslang::EOpSparseTextureGatherOffsets:
+ if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3))
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureGatherLod:
+ if (i == 3)
+ lvalue = true;
+ break;
+ case glslang::EOpSparseTextureGatherLodOffset:
+ case glslang::EOpSparseTextureGatherLodOffsets:
+ if (i == 4)
+ lvalue = true;
+ break;
+ case glslang::EOpSparseImageLoadLod:
+ if (i == 3)
+ lvalue = true;
+ break;
+ case glslang::EOpImageSampleFootprintNV:
+ if (i == 4)
+ lvalue = true;
+ break;
+ case glslang::EOpImageSampleFootprintClampNV:
+ case glslang::EOpImageSampleFootprintLodNV:
+ if (i == 5)
+ lvalue = true;
+ break;
+ case glslang::EOpImageSampleFootprintGradNV:
+ if (i == 6)
+ lvalue = true;
+ break;
+ case glslang::EOpImageSampleFootprintGradClampNV:
+ if (i == 7)
+ lvalue = true;
+ break;
+ default:
+ break;
+ }
+
+ if (lvalue) {
+ arguments.push_back(builder.accessChainGetLValue());
+ lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
+ lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType());
+ } else
+#endif
+ arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType()));
+ }
+}
+
+void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments)
+{
+ builder.clearAccessChain();
+ node.getOperand()->traverse(this);
+ arguments.push_back(accessChainLoad(node.getOperand()->getType()));
+}
+
+spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node)
+{
+ if (! node->isImage() && ! node->isTexture())
+ return spv::NoResult;
+
+ builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+
+ // Process a GLSL texturing op (will be SPV image)
+
+ const glslang::TType &imageType = node->getAsAggregate()
+ ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType()
+ : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType();
+ const glslang::TSampler sampler = imageType.getSampler();
+#ifdef GLSLANG_WEB
+ const bool f16ShadowCompare = false;
+#else
+ bool f16ShadowCompare = (sampler.shadow && node->getAsAggregate())
+ ? node->getAsAggregate()->getSequence()[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16
+ : false;
+#endif
+
+ const auto signExtensionMask = [&]() {
+ if (builder.getSpvVersion() >= spv::Spv_1_4) {
+ if (sampler.type == glslang::EbtUint)
+ return spv::ImageOperandsZeroExtendMask;
+ else if (sampler.type == glslang::EbtInt)
+ return spv::ImageOperandsSignExtendMask;
+ }
+ return spv::ImageOperandsMaskNone;
+ };
+
+ spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags;
+
+ std::vector<spv::Id> arguments;
+ if (node->getAsAggregate())
+ translateArguments(*node->getAsAggregate(), arguments, lvalueCoherentFlags);
+ else
+ translateArguments(*node->getAsUnaryNode(), arguments);
+ spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
+
+ spv::Builder::TextureParameters params = { };
+ params.sampler = arguments[0];
+
+ glslang::TCrackedTextureOp cracked;
+ node->crackTexture(sampler, cracked);
+
+ const bool isUnsignedResult = node->getType().getBasicType() == glslang::EbtUint;
+
+ // Check for queries
+ if (cracked.query) {
+ // OpImageQueryLod works on a sampled image, for other queries the image has to be extracted first
+ if (node->getOp() != glslang::EOpTextureQueryLod && builder.isSampledImage(params.sampler))
+ params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
+
+ switch (node->getOp()) {
+ case glslang::EOpImageQuerySize:
+ case glslang::EOpTextureQuerySize:
+ if (arguments.size() > 1) {
+ params.lod = arguments[1];
+ return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params, isUnsignedResult);
+ } else
+ return builder.createTextureQueryCall(spv::OpImageQuerySize, params, isUnsignedResult);
+#ifndef GLSLANG_WEB
+ case glslang::EOpImageQuerySamples:
+ case glslang::EOpTextureQuerySamples:
+ return builder.createTextureQueryCall(spv::OpImageQuerySamples, params, isUnsignedResult);
+ case glslang::EOpTextureQueryLod:
+ params.coords = arguments[1];
+ return builder.createTextureQueryCall(spv::OpImageQueryLod, params, isUnsignedResult);
+ case glslang::EOpTextureQueryLevels:
+ return builder.createTextureQueryCall(spv::OpImageQueryLevels, params, isUnsignedResult);
+ case glslang::EOpSparseTexelsResident:
+ return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]);
+#endif
+ default:
+ assert(0);
+ break;
+ }
+ }
+
+ int components = node->getType().getVectorSize();
+
+ if (node->getOp() == glslang::EOpTextureFetch) {
+ // These must produce 4 components, per SPIR-V spec. We'll add a conversion constructor if needed.
+ // This will only happen through the HLSL path for operator[], so we do not have to handle e.g.
+ // the EOpTexture/Proj/Lod/etc family. It would be harmless to do so, but would need more logic
+ // here around e.g. which ones return scalars or other types.
+ components = 4;
+ }
+
+ glslang::TType returnType(node->getType().getBasicType(), glslang::EvqTemporary, components);
+
+ auto resultType = [&returnType,this]{ return convertGlslangToSpvType(returnType); };
+
+ // Check for image functions other than queries
+ if (node->isImage()) {
+ std::vector<spv::IdImmediate> operands;
+ auto opIt = arguments.begin();
+ spv::IdImmediate image = { true, *(opIt++) };
+ operands.push_back(image);
+
+ // Handle subpass operations
+ // TODO: GLSL should change to have the "MS" only on the type rather than the
+ // built-in function.
+ if (cracked.subpass) {
+ // add on the (0,0) coordinate
+ spv::Id zero = builder.makeIntConstant(0);
+ std::vector<spv::Id> comps;
+ comps.push_back(zero);
+ comps.push_back(zero);
+ spv::IdImmediate coord = { true,
+ builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps) };
+ operands.push_back(coord);
+ spv::IdImmediate imageOperands = { false, spv::ImageOperandsMaskNone };
+ imageOperands.word = imageOperands.word | signExtensionMask();
+ if (sampler.isMultiSample()) {
+ imageOperands.word = imageOperands.word | spv::ImageOperandsSampleMask;
+ }
+ if (imageOperands.word != spv::ImageOperandsMaskNone) {
+ operands.push_back(imageOperands);
+ if (sampler.isMultiSample()) {
+ spv::IdImmediate imageOperand = { true, *(opIt++) };
+ operands.push_back(imageOperand);
+ }
+ }
+ spv::Id result = builder.createOp(spv::OpImageRead, resultType(), operands);
+ builder.setPrecision(result, precision);
+ return result;
+ }
+
+ spv::IdImmediate coord = { true, *(opIt++) };
+ operands.push_back(coord);
+ if (node->getOp() == glslang::EOpImageLoad || node->getOp() == glslang::EOpImageLoadLod) {
+ spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone;
+ if (sampler.isMultiSample()) {
+ mask = mask | spv::ImageOperandsSampleMask;
+ }
+ if (cracked.lod) {
+ builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod);
+ builder.addCapability(spv::CapabilityImageReadWriteLodAMD);
+ mask = mask | spv::ImageOperandsLodMask;
+ }
+ mask = mask | TranslateImageOperands(TranslateCoherent(imageType));
+ mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask);
+ mask = mask | signExtensionMask();
+ if (mask != spv::ImageOperandsMaskNone) {
+ spv::IdImmediate imageOperands = { false, (unsigned int)mask };
+ operands.push_back(imageOperands);
+ }
+ if (mask & spv::ImageOperandsSampleMask) {
+ spv::IdImmediate imageOperand = { true, *opIt++ };
+ operands.push_back(imageOperand);
+ }
+ if (mask & spv::ImageOperandsLodMask) {
+ spv::IdImmediate imageOperand = { true, *opIt++ };
+ operands.push_back(imageOperand);
+ }
+ if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) {
+ spv::IdImmediate imageOperand = { true,
+ builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
+ operands.push_back(imageOperand);
+ }
+
+ if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown)
+ builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat);
+
+ std::vector<spv::Id> result(1, builder.createOp(spv::OpImageRead, resultType(), operands));
+ builder.setPrecision(result[0], precision);
+
+ // If needed, add a conversion constructor to the proper size.
+ if (components != node->getType().getVectorSize())
+ result[0] = builder.createConstructor(precision, result, convertGlslangToSpvType(node->getType()));
+
+ return result[0];
+ } else if (node->getOp() == glslang::EOpImageStore || node->getOp() == glslang::EOpImageStoreLod) {
+
+ // Push the texel value before the operands
+ if (sampler.isMultiSample() || cracked.lod) {
+ spv::IdImmediate texel = { true, *(opIt + 1) };
+ operands.push_back(texel);
+ } else {
+ spv::IdImmediate texel = { true, *opIt };
+ operands.push_back(texel);
+ }
+
+ spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone;
+ if (sampler.isMultiSample()) {
+ mask = mask | spv::ImageOperandsSampleMask;
+ }
+ if (cracked.lod) {
+ builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod);
+ builder.addCapability(spv::CapabilityImageReadWriteLodAMD);
+ mask = mask | spv::ImageOperandsLodMask;
+ }
+ mask = mask | TranslateImageOperands(TranslateCoherent(imageType));
+ mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelVisibleKHRMask);
+ mask = mask | signExtensionMask();
+ if (mask != spv::ImageOperandsMaskNone) {
+ spv::IdImmediate imageOperands = { false, (unsigned int)mask };
+ operands.push_back(imageOperands);
+ }
+ if (mask & spv::ImageOperandsSampleMask) {
+ spv::IdImmediate imageOperand = { true, *opIt++ };
+ operands.push_back(imageOperand);
+ }
+ if (mask & spv::ImageOperandsLodMask) {
+ spv::IdImmediate imageOperand = { true, *opIt++ };
+ operands.push_back(imageOperand);
+ }
+ if (mask & spv::ImageOperandsMakeTexelAvailableKHRMask) {
+ spv::IdImmediate imageOperand = { true,
+ builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
+ operands.push_back(imageOperand);
+ }
+
+ builder.createNoResultOp(spv::OpImageWrite, operands);
+ if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown)
+ builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat);
+ return spv::NoResult;
+ } else if (node->getOp() == glslang::EOpSparseImageLoad ||
+ node->getOp() == glslang::EOpSparseImageLoadLod) {
+ builder.addCapability(spv::CapabilitySparseResidency);
+ if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown)
+ builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat);
+
+ spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone;
+ if (sampler.isMultiSample()) {
+ mask = mask | spv::ImageOperandsSampleMask;
+ }
+ if (cracked.lod) {
+ builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod);
+ builder.addCapability(spv::CapabilityImageReadWriteLodAMD);
+
+ mask = mask | spv::ImageOperandsLodMask;
+ }
+ mask = mask | TranslateImageOperands(TranslateCoherent(imageType));
+ mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask);
+ mask = mask | signExtensionMask();
+ if (mask != spv::ImageOperandsMaskNone) {
+ spv::IdImmediate imageOperands = { false, (unsigned int)mask };
+ operands.push_back(imageOperands);
+ }
+ if (mask & spv::ImageOperandsSampleMask) {
+ spv::IdImmediate imageOperand = { true, *opIt++ };
+ operands.push_back(imageOperand);
+ }
+ if (mask & spv::ImageOperandsLodMask) {
+ spv::IdImmediate imageOperand = { true, *opIt++ };
+ operands.push_back(imageOperand);
+ }
+ if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) {
+ spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
+ operands.push_back(imageOperand);
+ }
+
+ // Create the return type that was a special structure
+ spv::Id texelOut = *opIt;
+ spv::Id typeId0 = resultType();
+ spv::Id typeId1 = builder.getDerefTypeId(texelOut);
+ spv::Id resultTypeId = builder.makeStructResultType(typeId0, typeId1);
+
+ spv::Id resultId = builder.createOp(spv::OpImageSparseRead, resultTypeId, operands);
+
+ // Decode the return type
+ builder.createStore(builder.createCompositeExtract(resultId, typeId1, 1), texelOut);
+ return builder.createCompositeExtract(resultId, typeId0, 0);
+ } else {
+ // Process image atomic operations
+
+ // GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer,
+ // as the first source operand, is required by SPIR-V atomic operations.
+ // For non-MS, the sample value should be 0
+ spv::IdImmediate sample = { true, sampler.isMultiSample() ? *(opIt++) : builder.makeUintConstant(0) };
+ operands.push_back(sample);
+
+ spv::Id resultTypeId;
+ // imageAtomicStore has a void return type so base the pointer type on
+ // the type of the value operand.
+ if (node->getOp() == glslang::EOpImageAtomicStore) {
+ resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(operands[2].word));
+ } else {
+ resultTypeId = builder.makePointer(spv::StorageClassImage, resultType());
+ }
+ spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands);
+
+ std::vector<spv::Id> operands;
+ operands.push_back(pointer);
+ for (; opIt != arguments.end(); ++opIt)
+ operands.push_back(*opIt);
+
+ return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags);
+ }
+ }
+
+#ifndef GLSLANG_WEB
+ // Check for fragment mask functions other than queries
+ if (cracked.fragMask) {
+ assert(sampler.ms);
+
+ auto opIt = arguments.begin();
+ std::vector<spv::Id> operands;
+
+ // Extract the image if necessary
+ if (builder.isSampledImage(params.sampler))
+ params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
+
+ operands.push_back(params.sampler);
+ ++opIt;
+
+ if (sampler.isSubpass()) {
+ // add on the (0,0) coordinate
+ spv::Id zero = builder.makeIntConstant(0);
+ std::vector<spv::Id> comps;
+ comps.push_back(zero);
+ comps.push_back(zero);
+ operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps));
+ }
+
+ for (; opIt != arguments.end(); ++opIt)
+ operands.push_back(*opIt);
+
+ spv::Op fragMaskOp = spv::OpNop;
+ if (node->getOp() == glslang::EOpFragmentMaskFetch)
+ fragMaskOp = spv::OpFragmentMaskFetchAMD;
+ else if (node->getOp() == glslang::EOpFragmentFetch)
+ fragMaskOp = spv::OpFragmentFetchAMD;
+
+ builder.addExtension(spv::E_SPV_AMD_shader_fragment_mask);
+ builder.addCapability(spv::CapabilityFragmentMaskAMD);
+ return builder.createOp(fragMaskOp, resultType(), operands);
+ }
+#endif
+
+ // Check for texture functions other than queries
+ bool sparse = node->isSparseTexture();
+ bool imageFootprint = node->isImageFootprint();
+ bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.isArrayed() && sampler.isShadow();
+
+ // check for bias argument
+ bool bias = false;
+ if (! cracked.lod && ! cracked.grad && ! cracked.fetch && ! cubeCompare) {
+ int nonBiasArgCount = 2;
+ if (cracked.gather)
+ ++nonBiasArgCount; // comp argument should be present when bias argument is present
+
+ if (f16ShadowCompare)
+ ++nonBiasArgCount;
+ if (cracked.offset)
+ ++nonBiasArgCount;
+ else if (cracked.offsets)
+ ++nonBiasArgCount;
+ if (cracked.grad)
+ nonBiasArgCount += 2;
+ if (cracked.lodClamp)
+ ++nonBiasArgCount;
+ if (sparse)
+ ++nonBiasArgCount;
+ if (imageFootprint)
+ //Following three extra arguments
+ // int granularity, bool coarse, out gl_TextureFootprint2DNV footprint
+ nonBiasArgCount += 3;
+ if ((int)arguments.size() > nonBiasArgCount)
+ bias = true;
+ }
+
+ // See if the sampler param should really be just the SPV image part
+ if (cracked.fetch) {
+ // a fetch needs to have the image extracted first
+ if (builder.isSampledImage(params.sampler))
+ params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
+ }
+
+#ifndef GLSLANG_WEB
+ if (cracked.gather) {
+ const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
+ if (bias || cracked.lod ||
+ sourceExtensions.find(glslang::E_GL_AMD_texture_gather_bias_lod) != sourceExtensions.end()) {
+ builder.addExtension(spv::E_SPV_AMD_texture_gather_bias_lod);
+ builder.addCapability(spv::CapabilityImageGatherBiasLodAMD);
+ }
+ }
+#endif
+
+ // set the rest of the arguments
+
+ params.coords = arguments[1];
+ int extraArgs = 0;
+ bool noImplicitLod = false;
+
+ // sort out where Dref is coming from
+ if (cubeCompare || f16ShadowCompare) {
+ params.Dref = arguments[2];
+ ++extraArgs;
+ } else if (sampler.shadow && cracked.gather) {
+ params.Dref = arguments[2];
+ ++extraArgs;
+ } else if (sampler.shadow) {
+ std::vector<spv::Id> indexes;
+ int dRefComp;
+ if (cracked.proj)
+ dRefComp = 2; // "The resulting 3rd component of P in the shadow forms is used as Dref"
+ else
+ dRefComp = builder.getNumComponents(params.coords) - 1;
+ indexes.push_back(dRefComp);
+ params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
+ }
+
+ // lod
+ if (cracked.lod) {
+ params.lod = arguments[2 + extraArgs];
+ ++extraArgs;
+ } else if (glslangIntermediate->getStage() != EShLangFragment &&
+ !(glslangIntermediate->getStage() == EShLangCompute &&
+ glslangIntermediate->hasLayoutDerivativeModeNone())) {
+ // we need to invent the default lod for an explicit lod instruction for a non-fragment stage
+ noImplicitLod = true;
+ }
+
+ // multisample
+ if (sampler.isMultiSample()) {
+ params.sample = arguments[2 + extraArgs]; // For MS, "sample" should be specified
+ ++extraArgs;
+ }
+
+ // gradient
+ if (cracked.grad) {
+ params.gradX = arguments[2 + extraArgs];
+ params.gradY = arguments[3 + extraArgs];
+ extraArgs += 2;
+ }
+
+ // offset and offsets
+ if (cracked.offset) {
+ params.offset = arguments[2 + extraArgs];
+ ++extraArgs;
+ } else if (cracked.offsets) {
+ params.offsets = arguments[2 + extraArgs];
+ ++extraArgs;
+ }
+
+#ifndef GLSLANG_WEB
+ // lod clamp
+ if (cracked.lodClamp) {
+ params.lodClamp = arguments[2 + extraArgs];
+ ++extraArgs;
+ }
+ // sparse
+ if (sparse) {
+ params.texelOut = arguments[2 + extraArgs];
+ ++extraArgs;
+ }
+ // gather component
+ if (cracked.gather && ! sampler.shadow) {
+ // default component is 0, if missing, otherwise an argument
+ if (2 + extraArgs < (int)arguments.size()) {
+ params.component = arguments[2 + extraArgs];
+ ++extraArgs;
+ } else
+ params.component = builder.makeIntConstant(0);
+ }
+ spv::Id resultStruct = spv::NoResult;
+ if (imageFootprint) {
+ //Following three extra arguments
+ // int granularity, bool coarse, out gl_TextureFootprint2DNV footprint
+ params.granularity = arguments[2 + extraArgs];
+ params.coarse = arguments[3 + extraArgs];
+ resultStruct = arguments[4 + extraArgs];
+ extraArgs += 3;
+ }
+#endif
+ // bias
+ if (bias) {
+ params.bias = arguments[2 + extraArgs];
+ ++extraArgs;
+ }
+
+#ifndef GLSLANG_WEB
+ if (imageFootprint) {
+ builder.addExtension(spv::E_SPV_NV_shader_image_footprint);
+ builder.addCapability(spv::CapabilityImageFootprintNV);
+
+
+ //resultStructType(OpenGL type) contains 5 elements:
+ //struct gl_TextureFootprint2DNV {
+ // uvec2 anchor;
+ // uvec2 offset;
+ // uvec2 mask;
+ // uint lod;
+ // uint granularity;
+ //};
+ //or
+ //struct gl_TextureFootprint3DNV {
+ // uvec3 anchor;
+ // uvec3 offset;
+ // uvec2 mask;
+ // uint lod;
+ // uint granularity;
+ //};
+ spv::Id resultStructType = builder.getContainedTypeId(builder.getTypeId(resultStruct));
+ assert(builder.isStructType(resultStructType));
+
+ //resType (SPIR-V type) contains 6 elements:
+ //Member 0 must be a Boolean type scalar(LOD),
+ //Member 1 must be a vector of integer type, whose Signedness operand is 0(anchor),
+ //Member 2 must be a vector of integer type, whose Signedness operand is 0(offset),
+ //Member 3 must be a vector of integer type, whose Signedness operand is 0(mask),
+ //Member 4 must be a scalar of integer type, whose Signedness operand is 0(lod),
+ //Member 5 must be a scalar of integer type, whose Signedness operand is 0(granularity).
+ std::vector<spv::Id> members;
+ members.push_back(resultType());
+ for (int i = 0; i < 5; i++) {
+ members.push_back(builder.getContainedTypeId(resultStructType, i));
+ }
+ spv::Id resType = builder.makeStructType(members, "ResType");
+
+ //call ImageFootprintNV
+ spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj,
+ cracked.gather, noImplicitLod, params, signExtensionMask());
+
+ //copy resType (SPIR-V type) to resultStructType(OpenGL type)
+ for (int i = 0; i < 5; i++) {
+ builder.clearAccessChain();
+ builder.setAccessChainLValue(resultStruct);
+
+ //Accessing to a struct we created, no coherent flag is set
+ spv::Builder::AccessChain::CoherentFlags flags;
+ flags.clear();
+
+ builder.accessChainPush(builder.makeIntConstant(i), flags, 0);
+ builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), i+1));
+ }
+ return builder.createCompositeExtract(res, resultType(), 0);
+ }
+#endif
+
+ // projective component (might not to move)
+ // GLSL: "The texture coordinates consumed from P, not including the last component of P,
+ // are divided by the last component of P."
+ // SPIR-V: "... (u [, v] [, w], q)... It may be a vector larger than needed, but all
+ // unused components will appear after all used components."
+ if (cracked.proj) {
+ int projSourceComp = builder.getNumComponents(params.coords) - 1;
+ int projTargetComp;
+ switch (sampler.dim) {
+ case glslang::Esd1D: projTargetComp = 1; break;
+ case glslang::Esd2D: projTargetComp = 2; break;
+ case glslang::EsdRect: projTargetComp = 2; break;
+ default: projTargetComp = projSourceComp; break;
+ }
+ // copy the projective coordinate if we have to
+ if (projTargetComp != projSourceComp) {
+ spv::Id projComp = builder.createCompositeExtract(params.coords,
+ builder.getScalarTypeId(builder.getTypeId(params.coords)),
+ projSourceComp);
+ params.coords = builder.createCompositeInsert(projComp, params.coords,
+ builder.getTypeId(params.coords), projTargetComp);
+ }
+ }
+
+#ifndef GLSLANG_WEB
+ // nonprivate
+ if (imageType.getQualifier().nonprivate) {
+ params.nonprivate = true;
+ }
+
+ // volatile
+ if (imageType.getQualifier().volatil) {
+ params.volatil = true;
+ }
+#endif
+
+ std::vector<spv::Id> result( 1,
+ builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather,
+ noImplicitLod, params, signExtensionMask())
+ );
+
+ if (components != node->getType().getVectorSize())
+ result[0] = builder.createConstructor(precision, result, convertGlslangToSpvType(node->getType()));
+
+ return result[0];
+}
+
+spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node)
+{
+ // Grab the function's pointer from the previously created function
+ spv::Function* function = functionMap[node->getName().c_str()];
+ if (! function)
+ return 0;
+
+ const glslang::TIntermSequence& glslangArgs = node->getSequence();
+ const glslang::TQualifierList& qualifiers = node->getQualifierList();
+
+ // See comments in makeFunctions() for details about the semantics for parameter passing.
+ //
+ // These imply we need a four step process:
+ // 1. Evaluate the arguments
+ // 2. Allocate and make copies of in, out, and inout arguments
+ // 3. Make the call
+ // 4. Copy back the results
+
+ // 1. Evaluate the arguments and their types
+ std::vector<spv::Builder::AccessChain> lValues;
+ std::vector<spv::Id> rValues;
+ std::vector<const glslang::TType*> argTypes;
+ for (int a = 0; a < (int)glslangArgs.size(); ++a) {
+ argTypes.push_back(&glslangArgs[a]->getAsTyped()->getType());
+ // build l-value
+ builder.clearAccessChain();
+ glslangArgs[a]->traverse(this);
+ // keep outputs and pass-by-originals as l-values, evaluate others as r-values
+ if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0) ||
+ writableParam(qualifiers[a])) {
+ // save l-value
+ lValues.push_back(builder.getAccessChain());
+ } else {
+ // process r-value
+ rValues.push_back(accessChainLoad(*argTypes.back()));
+ }
+ }
+
+ // 2. Allocate space for anything needing a copy, and if it's "in" or "inout"
+ // copy the original into that space.
+ //
+ // Also, build up the list of actual arguments to pass in for the call
+ int lValueCount = 0;
+ int rValueCount = 0;
+ std::vector<spv::Id> spvArgs;
+ for (int a = 0; a < (int)glslangArgs.size(); ++a) {
+ spv::Id arg;
+ if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0)) {
+ builder.setAccessChain(lValues[lValueCount]);
+ arg = builder.accessChainGetLValue();
+ ++lValueCount;
+ } else if (writableParam(qualifiers[a])) {
+ // need space to hold the copy
+ arg = builder.createVariable(spv::StorageClassFunction, builder.getContainedTypeId(function->getParamType(a)), "param");
+ if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
+ // need to copy the input into output space
+ builder.setAccessChain(lValues[lValueCount]);
+ spv::Id copy = accessChainLoad(*argTypes[a]);
+ builder.clearAccessChain();
+ builder.setAccessChainLValue(arg);
+ multiTypeStore(*argTypes[a], copy);
+ }
+ ++lValueCount;
+ } else {
+ // process r-value, which involves a copy for a type mismatch
+ if (function->getParamType(a) != convertGlslangToSpvType(*argTypes[a])) {
+ spv::Id argCopy = builder.createVariable(spv::StorageClassFunction, function->getParamType(a), "arg");
+ builder.clearAccessChain();
+ builder.setAccessChainLValue(argCopy);
+ multiTypeStore(*argTypes[a], rValues[rValueCount]);
+ arg = builder.createLoad(argCopy);
+ } else
+ arg = rValues[rValueCount];
+ ++rValueCount;
+ }
+ spvArgs.push_back(arg);
+ }
+
+ // 3. Make the call.
+ spv::Id result = builder.createFunctionCall(function, spvArgs);
+ builder.setPrecision(result, TranslatePrecisionDecoration(node->getType()));
+
+ // 4. Copy back out an "out" arguments.
+ lValueCount = 0;
+ for (int a = 0; a < (int)glslangArgs.size(); ++a) {
+ if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0))
+ ++lValueCount;
+ else if (writableParam(qualifiers[a])) {
+ if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) {
+ spv::Id copy = builder.createLoad(spvArgs[a]);
+ builder.setAccessChain(lValues[lValueCount]);
+ multiTypeStore(*argTypes[a], copy);
+ }
+ ++lValueCount;
+ }
+ }
+
+ return result;
+}
+
+// Translate AST operation to SPV operation, already having SPV-based operands/types.
+spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpDecorations& decorations,
+ spv::Id typeId, spv::Id left, spv::Id right,
+ glslang::TBasicType typeProxy, bool reduceComparison)
+{
+ bool isUnsigned = isTypeUnsignedInt(typeProxy);
+ bool isFloat = isTypeFloat(typeProxy);
+ bool isBool = typeProxy == glslang::EbtBool;
+
+ spv::Op binOp = spv::OpNop;
+ bool needMatchingVectors = true; // for non-matrix ops, would a scalar need to smear to match a vector?
+ bool comparison = false;
+
+ switch (op) {
+ case glslang::EOpAdd:
+ case glslang::EOpAddAssign:
+ if (isFloat)
+ binOp = spv::OpFAdd;
+ else
+ binOp = spv::OpIAdd;
+ break;
+ case glslang::EOpSub:
+ case glslang::EOpSubAssign:
+ if (isFloat)
+ binOp = spv::OpFSub;
+ else
+ binOp = spv::OpISub;
+ break;
+ case glslang::EOpMul:
+ case glslang::EOpMulAssign:
+ if (isFloat)
+ binOp = spv::OpFMul;
+ else
+ binOp = spv::OpIMul;
+ break;
+ case glslang::EOpVectorTimesScalar:
+ case glslang::EOpVectorTimesScalarAssign:
+ if (isFloat && (builder.isVector(left) || builder.isVector(right))) {
+ if (builder.isVector(right))
+ std::swap(left, right);
+ assert(builder.isScalar(right));
+ needMatchingVectors = false;
+ binOp = spv::OpVectorTimesScalar;
+ } else if (isFloat)
+ binOp = spv::OpFMul;
+ else
+ binOp = spv::OpIMul;
+ break;
+ case glslang::EOpVectorTimesMatrix:
+ case glslang::EOpVectorTimesMatrixAssign:
+ binOp = spv::OpVectorTimesMatrix;
+ break;
+ case glslang::EOpMatrixTimesVector:
+ binOp = spv::OpMatrixTimesVector;
+ break;
+ case glslang::EOpMatrixTimesScalar:
+ case glslang::EOpMatrixTimesScalarAssign:
+ binOp = spv::OpMatrixTimesScalar;
+ break;
+ case glslang::EOpMatrixTimesMatrix:
+ case glslang::EOpMatrixTimesMatrixAssign:
+ binOp = spv::OpMatrixTimesMatrix;
+ break;
+ case glslang::EOpOuterProduct:
+ binOp = spv::OpOuterProduct;
+ needMatchingVectors = false;
+ break;
+
+ case glslang::EOpDiv:
+ case glslang::EOpDivAssign:
+ if (isFloat)
+ binOp = spv::OpFDiv;
+ else if (isUnsigned)
+ binOp = spv::OpUDiv;
+ else
+ binOp = spv::OpSDiv;
+ break;
+ case glslang::EOpMod:
+ case glslang::EOpModAssign:
+ if (isFloat)
+ binOp = spv::OpFMod;
+ else if (isUnsigned)
+ binOp = spv::OpUMod;
+ else
+ binOp = spv::OpSMod;
+ break;
+ case glslang::EOpRightShift:
+ case glslang::EOpRightShiftAssign:
+ if (isUnsigned)
+ binOp = spv::OpShiftRightLogical;
+ else
+ binOp = spv::OpShiftRightArithmetic;
+ break;
+ case glslang::EOpLeftShift:
+ case glslang::EOpLeftShiftAssign:
+ binOp = spv::OpShiftLeftLogical;
+ break;
+ case glslang::EOpAnd:
+ case glslang::EOpAndAssign:
+ binOp = spv::OpBitwiseAnd;
+ break;
+ case glslang::EOpLogicalAnd:
+ needMatchingVectors = false;
+ binOp = spv::OpLogicalAnd;
+ break;
+ case glslang::EOpInclusiveOr:
+ case glslang::EOpInclusiveOrAssign:
+ binOp = spv::OpBitwiseOr;
+ break;
+ case glslang::EOpLogicalOr:
+ needMatchingVectors = false;
+ binOp = spv::OpLogicalOr;
+ break;
+ case glslang::EOpExclusiveOr:
+ case glslang::EOpExclusiveOrAssign:
+ binOp = spv::OpBitwiseXor;
+ break;
+ case glslang::EOpLogicalXor:
+ needMatchingVectors = false;
+ binOp = spv::OpLogicalNotEqual;
+ break;
+
+ case glslang::EOpAbsDifference:
+ binOp = isUnsigned ? spv::OpAbsUSubINTEL : spv::OpAbsISubINTEL;
+ break;
+
+ case glslang::EOpAddSaturate:
+ binOp = isUnsigned ? spv::OpUAddSatINTEL : spv::OpIAddSatINTEL;
+ break;
+
+ case glslang::EOpSubSaturate:
+ binOp = isUnsigned ? spv::OpUSubSatINTEL : spv::OpISubSatINTEL;
+ break;
+
+ case glslang::EOpAverage:
+ binOp = isUnsigned ? spv::OpUAverageINTEL : spv::OpIAverageINTEL;
+ break;
+
+ case glslang::EOpAverageRounded:
+ binOp = isUnsigned ? spv::OpUAverageRoundedINTEL : spv::OpIAverageRoundedINTEL;
+ break;
+
+ case glslang::EOpMul32x16:
+ binOp = isUnsigned ? spv::OpUMul32x16INTEL : spv::OpIMul32x16INTEL;
+ break;
+
+ case glslang::EOpLessThan:
+ case glslang::EOpGreaterThan:
+ case glslang::EOpLessThanEqual:
+ case glslang::EOpGreaterThanEqual:
+ case glslang::EOpEqual:
+ case glslang::EOpNotEqual:
+ case glslang::EOpVectorEqual:
+ case glslang::EOpVectorNotEqual:
+ comparison = true;
+ break;
+ default:
+ break;
+ }
+
+ // handle mapped binary operations (should be non-comparison)
+ if (binOp != spv::OpNop) {
+ assert(comparison == false);
+ if (builder.isMatrix(left) || builder.isMatrix(right) ||
+ builder.isCooperativeMatrix(left) || builder.isCooperativeMatrix(right))
+ return createBinaryMatrixOperation(binOp, decorations, typeId, left, right);
+
+ // No matrix involved; make both operands be the same number of components, if needed
+ if (needMatchingVectors)
+ builder.promoteScalar(decorations.precision, left, right);
+
+ spv::Id result = builder.createBinOp(binOp, typeId, left, right);
+ decorations.addNoContraction(builder, result);
+ decorations.addNonUniform(builder, result);
+ return builder.setPrecision(result, decorations.precision);
+ }
+
+ if (! comparison)
+ return 0;
+
+ // Handle comparison instructions
+
+ if (reduceComparison && (op == glslang::EOpEqual || op == glslang::EOpNotEqual)
+ && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) {
+ spv::Id result = builder.createCompositeCompare(decorations.precision, left, right, op == glslang::EOpEqual);
+ decorations.addNonUniform(builder, result);
+ return result;
+ }
+
+ switch (op) {
+ case glslang::EOpLessThan:
+ if (isFloat)
+ binOp = spv::OpFOrdLessThan;
+ else if (isUnsigned)
+ binOp = spv::OpULessThan;
+ else
+ binOp = spv::OpSLessThan;
+ break;
+ case glslang::EOpGreaterThan:
+ if (isFloat)
+ binOp = spv::OpFOrdGreaterThan;
+ else if (isUnsigned)
+ binOp = spv::OpUGreaterThan;
+ else
+ binOp = spv::OpSGreaterThan;
+ break;
+ case glslang::EOpLessThanEqual:
+ if (isFloat)
+ binOp = spv::OpFOrdLessThanEqual;
+ else if (isUnsigned)
+ binOp = spv::OpULessThanEqual;
+ else
+ binOp = spv::OpSLessThanEqual;
+ break;
+ case glslang::EOpGreaterThanEqual:
+ if (isFloat)
+ binOp = spv::OpFOrdGreaterThanEqual;
+ else if (isUnsigned)
+ binOp = spv::OpUGreaterThanEqual;
+ else
+ binOp = spv::OpSGreaterThanEqual;
+ break;
+ case glslang::EOpEqual:
+ case glslang::EOpVectorEqual:
+ if (isFloat)
+ binOp = spv::OpFOrdEqual;
+ else if (isBool)
+ binOp = spv::OpLogicalEqual;
+ else
+ binOp = spv::OpIEqual;
+ break;
+ case glslang::EOpNotEqual:
+ case glslang::EOpVectorNotEqual:
+ if (isFloat)
+ binOp = spv::OpFOrdNotEqual;
+ else if (isBool)
+ binOp = spv::OpLogicalNotEqual;
+ else
+ binOp = spv::OpINotEqual;
+ break;
+ default:
+ break;
+ }
+
+ if (binOp != spv::OpNop) {
+ spv::Id result = builder.createBinOp(binOp, typeId, left, right);
+ decorations.addNoContraction(builder, result);
+ decorations.addNonUniform(builder, result);
+ return builder.setPrecision(result, decorations.precision);
+ }
+
+ return 0;
+}
+
+//
+// Translate AST matrix operation to SPV operation, already having SPV-based operands/types.
+// These can be any of:
+//
+// matrix * scalar
+// scalar * matrix
+// matrix * matrix linear algebraic
+// matrix * vector
+// vector * matrix
+// matrix * matrix componentwise
+// matrix op matrix op in {+, -, /}
+// matrix op scalar op in {+, -, /}
+// scalar op matrix op in {+, -, /}
+//
+spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecorations& decorations, spv::Id typeId,
+ spv::Id left, spv::Id right)
+{
+ bool firstClass = true;
+
+ // First, handle first-class matrix operations (* and matrix/scalar)
+ switch (op) {
+ case spv::OpFDiv:
+ if (builder.isMatrix(left) && builder.isScalar(right)) {
+ // turn matrix / scalar into a multiply...
+ spv::Id resultType = builder.getTypeId(right);
+ right = builder.createBinOp(spv::OpFDiv, resultType, builder.makeFpConstant(resultType, 1.0), right);
+ op = spv::OpMatrixTimesScalar;
+ } else
+ firstClass = false;
+ break;
+ case spv::OpMatrixTimesScalar:
+ if (builder.isMatrix(right) || builder.isCooperativeMatrix(right))
+ std::swap(left, right);
+ assert(builder.isScalar(right));
+ break;
+ case spv::OpVectorTimesMatrix:
+ assert(builder.isVector(left));
+ assert(builder.isMatrix(right));
+ break;
+ case spv::OpMatrixTimesVector:
+ assert(builder.isMatrix(left));
+ assert(builder.isVector(right));
+ break;
+ case spv::OpMatrixTimesMatrix:
+ assert(builder.isMatrix(left));
+ assert(builder.isMatrix(right));
+ break;
+ default:
+ firstClass = false;
+ break;
+ }
+
+ if (builder.isCooperativeMatrix(left) || builder.isCooperativeMatrix(right))
+ firstClass = true;
+
+ if (firstClass) {
+ spv::Id result = builder.createBinOp(op, typeId, left, right);
+ decorations.addNoContraction(builder, result);
+ decorations.addNonUniform(builder, result);
+ return builder.setPrecision(result, decorations.precision);
+ }
+
+ // Handle component-wise +, -, *, %, and / for all combinations of type.
+ // The result type of all of them is the same type as the (a) matrix operand.
+ // The algorithm is to:
+ // - break the matrix(es) into vectors
+ // - smear any scalar to a vector
+ // - do vector operations
+ // - make a matrix out the vector results
+ switch (op) {
+ case spv::OpFAdd:
+ case spv::OpFSub:
+ case spv::OpFDiv:
+ case spv::OpFMod:
+ case spv::OpFMul:
+ {
+ // one time set up...
+ bool leftMat = builder.isMatrix(left);
+ bool rightMat = builder.isMatrix(right);
+ unsigned int numCols = leftMat ? builder.getNumColumns(left) : builder.getNumColumns(right);
+ int numRows = leftMat ? builder.getNumRows(left) : builder.getNumRows(right);
+ spv::Id scalarType = builder.getScalarTypeId(typeId);
+ spv::Id vecType = builder.makeVectorType(scalarType, numRows);
+ std::vector<spv::Id> results;
+ spv::Id smearVec = spv::NoResult;
+ if (builder.isScalar(left))
+ smearVec = builder.smearScalar(decorations.precision, left, vecType);
+ else if (builder.isScalar(right))
+ smearVec = builder.smearScalar(decorations.precision, right, vecType);
+
+ // do each vector op
+ for (unsigned int c = 0; c < numCols; ++c) {
+ std::vector<unsigned int> indexes;
+ indexes.push_back(c);
+ spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec;
+ spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
+ spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec);
+ decorations.addNoContraction(builder, result);
+ decorations.addNonUniform(builder, result);
+ results.push_back(builder.setPrecision(result, decorations.precision));
+ }
+
+ // put the pieces together
+ spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision);
+ decorations.addNonUniform(builder, result);
+ return result;
+ }
+ default:
+ assert(0);
+ return spv::NoResult;
+ }
+}
+
+spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDecorations& decorations, spv::Id typeId,
+ spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
+{
+ spv::Op unaryOp = spv::OpNop;
+ int extBuiltins = -1;
+ int libCall = -1;
+ bool isUnsigned = isTypeUnsignedInt(typeProxy);
+ bool isFloat = isTypeFloat(typeProxy);
+
+ switch (op) {
+ case glslang::EOpNegative:
+ if (isFloat) {
+ unaryOp = spv::OpFNegate;
+ if (builder.isMatrixType(typeId))
+ return createUnaryMatrixOperation(unaryOp, decorations, typeId, operand, typeProxy);
+ } else
+ unaryOp = spv::OpSNegate;
+ break;
+
+ case glslang::EOpLogicalNot:
+ case glslang::EOpVectorLogicalNot:
+ unaryOp = spv::OpLogicalNot;
+ break;
+ case glslang::EOpBitwiseNot:
+ unaryOp = spv::OpNot;
+ break;
+
+ case glslang::EOpDeterminant:
+ libCall = spv::GLSLstd450Determinant;
+ break;
+ case glslang::EOpMatrixInverse:
+ libCall = spv::GLSLstd450MatrixInverse;
+ break;
+ case glslang::EOpTranspose:
+ unaryOp = spv::OpTranspose;
+ break;
+
+ case glslang::EOpRadians:
+ libCall = spv::GLSLstd450Radians;
+ break;
+ case glslang::EOpDegrees:
+ libCall = spv::GLSLstd450Degrees;
+ break;
+ case glslang::EOpSin:
+ libCall = spv::GLSLstd450Sin;
+ break;
+ case glslang::EOpCos:
+ libCall = spv::GLSLstd450Cos;
+ break;
+ case glslang::EOpTan:
+ libCall = spv::GLSLstd450Tan;
+ break;
+ case glslang::EOpAcos:
+ libCall = spv::GLSLstd450Acos;
+ break;
+ case glslang::EOpAsin:
+ libCall = spv::GLSLstd450Asin;
+ break;
+ case glslang::EOpAtan:
+ libCall = spv::GLSLstd450Atan;
+ break;
+
+ case glslang::EOpAcosh:
+ libCall = spv::GLSLstd450Acosh;
+ break;
+ case glslang::EOpAsinh:
+ libCall = spv::GLSLstd450Asinh;
+ break;
+ case glslang::EOpAtanh:
+ libCall = spv::GLSLstd450Atanh;
+ break;
+ case glslang::EOpTanh:
+ libCall = spv::GLSLstd450Tanh;
+ break;
+ case glslang::EOpCosh:
+ libCall = spv::GLSLstd450Cosh;
+ break;
+ case glslang::EOpSinh:
+ libCall = spv::GLSLstd450Sinh;
+ break;
+
+ case glslang::EOpLength:
+ libCall = spv::GLSLstd450Length;
+ break;
+ case glslang::EOpNormalize:
+ libCall = spv::GLSLstd450Normalize;
+ break;
+
+ case glslang::EOpExp:
+ libCall = spv::GLSLstd450Exp;
+ break;
+ case glslang::EOpLog:
+ libCall = spv::GLSLstd450Log;
+ break;
+ case glslang::EOpExp2:
+ libCall = spv::GLSLstd450Exp2;
+ break;
+ case glslang::EOpLog2:
+ libCall = spv::GLSLstd450Log2;
+ break;
+ case glslang::EOpSqrt:
+ libCall = spv::GLSLstd450Sqrt;
+ break;
+ case glslang::EOpInverseSqrt:
+ libCall = spv::GLSLstd450InverseSqrt;
+ break;
+
+ case glslang::EOpFloor:
+ libCall = spv::GLSLstd450Floor;
+ break;
+ case glslang::EOpTrunc:
+ libCall = spv::GLSLstd450Trunc;
+ break;
+ case glslang::EOpRound:
+ libCall = spv::GLSLstd450Round;
+ break;
+ case glslang::EOpRoundEven:
+ libCall = spv::GLSLstd450RoundEven;
+ break;
+ case glslang::EOpCeil:
+ libCall = spv::GLSLstd450Ceil;
+ break;
+ case glslang::EOpFract:
+ libCall = spv::GLSLstd450Fract;
+ break;
+
+ case glslang::EOpIsNan:
+ unaryOp = spv::OpIsNan;
+ break;
+ case glslang::EOpIsInf:
+ unaryOp = spv::OpIsInf;
+ break;
+ case glslang::EOpIsFinite:
+ unaryOp = spv::OpIsFinite;
+ break;
+
+ case glslang::EOpFloatBitsToInt:
+ case glslang::EOpFloatBitsToUint:
+ case glslang::EOpIntBitsToFloat:
+ case glslang::EOpUintBitsToFloat:
+ case glslang::EOpDoubleBitsToInt64:
+ case glslang::EOpDoubleBitsToUint64:
+ case glslang::EOpInt64BitsToDouble:
+ case glslang::EOpUint64BitsToDouble:
+ case glslang::EOpFloat16BitsToInt16:
+ case glslang::EOpFloat16BitsToUint16:
+ case glslang::EOpInt16BitsToFloat16:
+ case glslang::EOpUint16BitsToFloat16:
+ unaryOp = spv::OpBitcast;
+ break;
+
+ case glslang::EOpPackSnorm2x16:
+ libCall = spv::GLSLstd450PackSnorm2x16;
+ break;
+ case glslang::EOpUnpackSnorm2x16:
+ libCall = spv::GLSLstd450UnpackSnorm2x16;
+ break;
+ case glslang::EOpPackUnorm2x16:
+ libCall = spv::GLSLstd450PackUnorm2x16;
+ break;
+ case glslang::EOpUnpackUnorm2x16:
+ libCall = spv::GLSLstd450UnpackUnorm2x16;
+ break;
+ case glslang::EOpPackHalf2x16:
+ libCall = spv::GLSLstd450PackHalf2x16;
+ break;
+ case glslang::EOpUnpackHalf2x16:
+ libCall = spv::GLSLstd450UnpackHalf2x16;
+ break;
+#ifndef GLSLANG_WEB
+ case glslang::EOpPackSnorm4x8:
+ libCall = spv::GLSLstd450PackSnorm4x8;
+ break;
+ case glslang::EOpUnpackSnorm4x8:
+ libCall = spv::GLSLstd450UnpackSnorm4x8;
+ break;
+ case glslang::EOpPackUnorm4x8:
+ libCall = spv::GLSLstd450PackUnorm4x8;
+ break;
+ case glslang::EOpUnpackUnorm4x8:
+ libCall = spv::GLSLstd450UnpackUnorm4x8;
+ break;
+ case glslang::EOpPackDouble2x32:
+ libCall = spv::GLSLstd450PackDouble2x32;
+ break;
+ case glslang::EOpUnpackDouble2x32:
+ libCall = spv::GLSLstd450UnpackDouble2x32;
+ break;
+#endif
+
+ case glslang::EOpPackInt2x32:
+ case glslang::EOpUnpackInt2x32:
+ case glslang::EOpPackUint2x32:
+ case glslang::EOpUnpackUint2x32:
+ case glslang::EOpPack16:
+ case glslang::EOpPack32:
+ case glslang::EOpPack64:
+ case glslang::EOpUnpack32:
+ case glslang::EOpUnpack16:
+ case glslang::EOpUnpack8:
+ case glslang::EOpPackInt2x16:
+ case glslang::EOpUnpackInt2x16:
+ case glslang::EOpPackUint2x16:
+ case glslang::EOpUnpackUint2x16:
+ case glslang::EOpPackInt4x16:
+ case glslang::EOpUnpackInt4x16:
+ case glslang::EOpPackUint4x16:
+ case glslang::EOpUnpackUint4x16:
+ case glslang::EOpPackFloat2x16:
+ case glslang::EOpUnpackFloat2x16:
+ unaryOp = spv::OpBitcast;
+ break;
+
+ case glslang::EOpDPdx:
+ unaryOp = spv::OpDPdx;
+ break;
+ case glslang::EOpDPdy:
+ unaryOp = spv::OpDPdy;
+ break;
+ case glslang::EOpFwidth:
+ unaryOp = spv::OpFwidth;
+ break;
+
+ case glslang::EOpAny:
+ unaryOp = spv::OpAny;
+ break;
+ case glslang::EOpAll:
+ unaryOp = spv::OpAll;
+ break;
+
+ case glslang::EOpAbs:
+ if (isFloat)
+ libCall = spv::GLSLstd450FAbs;
+ else
+ libCall = spv::GLSLstd450SAbs;
+ break;
+ case glslang::EOpSign:
+ if (isFloat)
+ libCall = spv::GLSLstd450FSign;
+ else
+ libCall = spv::GLSLstd450SSign;
+ break;
+
+#ifndef GLSLANG_WEB
+ case glslang::EOpDPdxFine:
+ unaryOp = spv::OpDPdxFine;
+ break;
+ case glslang::EOpDPdyFine:
+ unaryOp = spv::OpDPdyFine;
+ break;
+ case glslang::EOpFwidthFine:
+ unaryOp = spv::OpFwidthFine;
+ break;
+ case glslang::EOpDPdxCoarse:
+ unaryOp = spv::OpDPdxCoarse;
+ break;
+ case glslang::EOpDPdyCoarse:
+ unaryOp = spv::OpDPdyCoarse;
+ break;
+ case glslang::EOpFwidthCoarse:
+ unaryOp = spv::OpFwidthCoarse;
+ break;
+ case glslang::EOpInterpolateAtCentroid:
+ if (typeProxy == glslang::EbtFloat16)
+ builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
+ libCall = spv::GLSLstd450InterpolateAtCentroid;
+ break;
+ case glslang::EOpAtomicCounterIncrement:
+ case glslang::EOpAtomicCounterDecrement:
+ case glslang::EOpAtomicCounter:
+ {
+ // Handle all of the atomics in one place, in createAtomicOperation()
+ std::vector<spv::Id> operands;
+ operands.push_back(operand);
+ return createAtomicOperation(op, decorations.precision, typeId, operands, typeProxy, lvalueCoherentFlags);
+ }
+
+ case glslang::EOpBitFieldReverse:
+ unaryOp = spv::OpBitReverse;
+ break;
+ case glslang::EOpBitCount:
+ unaryOp = spv::OpBitCount;
+ break;
+ case glslang::EOpFindLSB:
+ libCall = spv::GLSLstd450FindILsb;
+ break;
+ case glslang::EOpFindMSB:
+ if (isUnsigned)
+ libCall = spv::GLSLstd450FindUMsb;
+ else
+ libCall = spv::GLSLstd450FindSMsb;
+ break;
+
+ case glslang::EOpCountLeadingZeros:
+ builder.addCapability(spv::CapabilityIntegerFunctions2INTEL);
+ builder.addExtension("SPV_INTEL_shader_integer_functions2");
+ unaryOp = spv::OpUCountLeadingZerosINTEL;
+ break;
+
+ case glslang::EOpCountTrailingZeros:
+ builder.addCapability(spv::CapabilityIntegerFunctions2INTEL);
+ builder.addExtension("SPV_INTEL_shader_integer_functions2");
+ unaryOp = spv::OpUCountTrailingZerosINTEL;
+ break;
+
+ case glslang::EOpBallot:
+ case glslang::EOpReadFirstInvocation:
+ case glslang::EOpAnyInvocation:
+ case glslang::EOpAllInvocations:
+ case glslang::EOpAllInvocationsEqual:
+ case glslang::EOpMinInvocations:
+ case glslang::EOpMaxInvocations:
+ case glslang::EOpAddInvocations:
+ case glslang::EOpMinInvocationsNonUniform:
+ case glslang::EOpMaxInvocationsNonUniform:
+ case glslang::EOpAddInvocationsNonUniform:
+ case glslang::EOpMinInvocationsInclusiveScan:
+ case glslang::EOpMaxInvocationsInclusiveScan:
+ case glslang::EOpAddInvocationsInclusiveScan:
+ case glslang::EOpMinInvocationsInclusiveScanNonUniform:
+ case glslang::EOpMaxInvocationsInclusiveScanNonUniform:
+ case glslang::EOpAddInvocationsInclusiveScanNonUniform:
+ case glslang::EOpMinInvocationsExclusiveScan:
+ case glslang::EOpMaxInvocationsExclusiveScan:
+ case glslang::EOpAddInvocationsExclusiveScan:
+ case glslang::EOpMinInvocationsExclusiveScanNonUniform:
+ case glslang::EOpMaxInvocationsExclusiveScanNonUniform:
+ case glslang::EOpAddInvocationsExclusiveScanNonUniform:
+ {
+ std::vector<spv::Id> operands;
+ operands.push_back(operand);
+ return createInvocationsOperation(op, typeId, operands, typeProxy);
+ }
+ case glslang::EOpSubgroupAll:
+ case glslang::EOpSubgroupAny:
+ case glslang::EOpSubgroupAllEqual:
+ case glslang::EOpSubgroupBroadcastFirst:
+ case glslang::EOpSubgroupBallot:
+ case glslang::EOpSubgroupInverseBallot:
+ case glslang::EOpSubgroupBallotBitCount:
+ case glslang::EOpSubgroupBallotInclusiveBitCount:
+ case glslang::EOpSubgroupBallotExclusiveBitCount:
+ case glslang::EOpSubgroupBallotFindLSB:
+ case glslang::EOpSubgroupBallotFindMSB:
+ case glslang::EOpSubgroupAdd:
+ case glslang::EOpSubgroupMul:
+ case glslang::EOpSubgroupMin:
+ case glslang::EOpSubgroupMax:
+ case glslang::EOpSubgroupAnd:
+ case glslang::EOpSubgroupOr:
+ case glslang::EOpSubgroupXor:
+ case glslang::EOpSubgroupInclusiveAdd:
+ case glslang::EOpSubgroupInclusiveMul:
+ case glslang::EOpSubgroupInclusiveMin:
+ case glslang::EOpSubgroupInclusiveMax:
+ case glslang::EOpSubgroupInclusiveAnd:
+ case glslang::EOpSubgroupInclusiveOr:
+ case glslang::EOpSubgroupInclusiveXor:
+ case glslang::EOpSubgroupExclusiveAdd:
+ case glslang::EOpSubgroupExclusiveMul:
+ case glslang::EOpSubgroupExclusiveMin:
+ case glslang::EOpSubgroupExclusiveMax:
+ case glslang::EOpSubgroupExclusiveAnd:
+ case glslang::EOpSubgroupExclusiveOr:
+ case glslang::EOpSubgroupExclusiveXor:
+ case glslang::EOpSubgroupQuadSwapHorizontal:
+ case glslang::EOpSubgroupQuadSwapVertical:
+ case glslang::EOpSubgroupQuadSwapDiagonal: {
+ std::vector<spv::Id> operands;
+ operands.push_back(operand);
+ return createSubgroupOperation(op, typeId, operands, typeProxy);
+ }
+ case glslang::EOpMbcnt:
+ extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
+ libCall = spv::MbcntAMD;
+ break;
+
+ case glslang::EOpCubeFaceIndex:
+ extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader);
+ libCall = spv::CubeFaceIndexAMD;
+ break;
+
+ case glslang::EOpCubeFaceCoord:
+ extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader);
+ libCall = spv::CubeFaceCoordAMD;
+ break;
+ case glslang::EOpSubgroupPartition:
+ unaryOp = spv::OpGroupNonUniformPartitionNV;
+ break;
+ case glslang::EOpConstructReference:
+ unaryOp = spv::OpBitcast;
+ break;
+#endif
+
+ case glslang::EOpCopyObject:
+ unaryOp = spv::OpCopyObject;
+ break;
+
+ default:
+ return 0;
+ }
+
+ spv::Id id;
+ if (libCall >= 0) {
+ std::vector<spv::Id> args;
+ args.push_back(operand);
+ id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, args);
+ } else {
+ id = builder.createUnaryOp(unaryOp, typeId, operand);
+ }
+
+ decorations.addNoContraction(builder, id);
+ decorations.addNonUniform(builder, id);
+ return builder.setPrecision(id, decorations.precision);
+}
+
+// Create a unary operation on a matrix
+spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, OpDecorations& decorations, spv::Id typeId,
+ spv::Id operand, glslang::TBasicType /* typeProxy */)
+{
+ // Handle unary operations vector by vector.
+ // The result type is the same type as the original type.
+ // The algorithm is to:
+ // - break the matrix into vectors
+ // - apply the operation to each vector
+ // - make a matrix out the vector results
+
+ // get the types sorted out
+ int numCols = builder.getNumColumns(operand);
+ int numRows = builder.getNumRows(operand);
+ spv::Id srcVecType = builder.makeVectorType(builder.getScalarTypeId(builder.getTypeId(operand)), numRows);
+ spv::Id destVecType = builder.makeVectorType(builder.getScalarTypeId(typeId), numRows);
+ std::vector<spv::Id> results;
+
+ // do each vector op
+ for (int c = 0; c < numCols; ++c) {
+ std::vector<unsigned int> indexes;
+ indexes.push_back(c);
+ spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes);
+ spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec);
+ decorations.addNoContraction(builder, destVec);
+ decorations.addNonUniform(builder, destVec);
+ results.push_back(builder.setPrecision(destVec, decorations.precision));
+ }
+
+ // put the pieces together
+ spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision);
+ decorations.addNonUniform(builder, result);
+ return result;
+}
+
+// For converting integers where both the bitwidth and the signedness could
+// change, but only do the width change here. The caller is still responsible
+// for the signedness conversion.
+spv::Id TGlslangToSpvTraverser::createIntWidthConversion(glslang::TOperator op, spv::Id operand, int vectorSize)
+{
+ // Get the result type width, based on the type to convert to.
+ int width = 32;
+ switch(op) {
+ case glslang::EOpConvInt16ToUint8:
+ case glslang::EOpConvIntToUint8:
+ case glslang::EOpConvInt64ToUint8:
+ case glslang::EOpConvUint16ToInt8:
+ case glslang::EOpConvUintToInt8:
+ case glslang::EOpConvUint64ToInt8:
+ width = 8;
+ break;
+ case glslang::EOpConvInt8ToUint16:
+ case glslang::EOpConvIntToUint16:
+ case glslang::EOpConvInt64ToUint16:
+ case glslang::EOpConvUint8ToInt16:
+ case glslang::EOpConvUintToInt16:
+ case glslang::EOpConvUint64ToInt16:
+ width = 16;
+ break;
+ case glslang::EOpConvInt8ToUint:
+ case glslang::EOpConvInt16ToUint:
+ case glslang::EOpConvInt64ToUint:
+ case glslang::EOpConvUint8ToInt:
+ case glslang::EOpConvUint16ToInt:
+ case glslang::EOpConvUint64ToInt:
+ width = 32;
+ break;
+ case glslang::EOpConvInt8ToUint64:
+ case glslang::EOpConvInt16ToUint64:
+ case glslang::EOpConvIntToUint64:
+ case glslang::EOpConvUint8ToInt64:
+ case glslang::EOpConvUint16ToInt64:
+ case glslang::EOpConvUintToInt64:
+ width = 64;
+ break;
+
+ default:
+ assert(false && "Default missing");
+ break;
+ }
+
+ // Get the conversion operation and result type,
+ // based on the target width, but the source type.
+ spv::Id type = spv::NoType;
+ spv::Op convOp = spv::OpNop;
+ switch(op) {
+ case glslang::EOpConvInt8ToUint16:
+ case glslang::EOpConvInt8ToUint:
+ case glslang::EOpConvInt8ToUint64:
+ case glslang::EOpConvInt16ToUint8:
+ case glslang::EOpConvInt16ToUint:
+ case glslang::EOpConvInt16ToUint64:
+ case glslang::EOpConvIntToUint8:
+ case glslang::EOpConvIntToUint16:
+ case glslang::EOpConvIntToUint64:
+ case glslang::EOpConvInt64ToUint8:
+ case glslang::EOpConvInt64ToUint16:
+ case glslang::EOpConvInt64ToUint:
+ convOp = spv::OpSConvert;
+ type = builder.makeIntType(width);
+ break;
+ default:
+ convOp = spv::OpUConvert;
+ type = builder.makeUintType(width);
+ break;
+ }
+
+ if (vectorSize > 0)
+ type = builder.makeVectorType(type, vectorSize);
+
+ return builder.createUnaryOp(convOp, type, operand);
+}
+
+spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecorations& decorations, spv::Id destType,
+ spv::Id operand, glslang::TBasicType typeProxy)
+{
+ spv::Op convOp = spv::OpNop;
+ spv::Id zero = 0;
+ spv::Id one = 0;
+
+ int vectorSize = builder.isVectorType(destType) ? builder.getNumTypeComponents(destType) : 0;
+
+ switch (op) {
+ case glslang::EOpConvIntToBool:
+ case glslang::EOpConvUintToBool:
+ zero = builder.makeUintConstant(0);
+ zero = makeSmearedConstant(zero, vectorSize);
+ return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
+ case glslang::EOpConvFloatToBool:
+ zero = builder.makeFloatConstant(0.0F);
+ zero = makeSmearedConstant(zero, vectorSize);
+ return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
+ case glslang::EOpConvBoolToFloat:
+ convOp = spv::OpSelect;
+ zero = builder.makeFloatConstant(0.0F);
+ one = builder.makeFloatConstant(1.0F);
+ break;
+
+ case glslang::EOpConvBoolToInt:
+ case glslang::EOpConvBoolToInt64:
+#ifndef GLSLANG_WEB
+ if (op == glslang::EOpConvBoolToInt64) {
+ zero = builder.makeInt64Constant(0);
+ one = builder.makeInt64Constant(1);
+ } else
+#endif
+ {
+ zero = builder.makeIntConstant(0);
+ one = builder.makeIntConstant(1);
+ }
+
+ convOp = spv::OpSelect;
+ break;
+
+ case glslang::EOpConvBoolToUint:
+ case glslang::EOpConvBoolToUint64:
+#ifndef GLSLANG_WEB
+ if (op == glslang::EOpConvBoolToUint64) {
+ zero = builder.makeUint64Constant(0);
+ one = builder.makeUint64Constant(1);
+ } else
+#endif
+ {
+ zero = builder.makeUintConstant(0);
+ one = builder.makeUintConstant(1);
+ }
+
+ convOp = spv::OpSelect;
+ break;
+
+ case glslang::EOpConvInt8ToFloat16:
+ case glslang::EOpConvInt8ToFloat:
+ case glslang::EOpConvInt8ToDouble:
+ case glslang::EOpConvInt16ToFloat16:
+ case glslang::EOpConvInt16ToFloat:
+ case glslang::EOpConvInt16ToDouble:
+ case glslang::EOpConvIntToFloat16:
+ case glslang::EOpConvIntToFloat:
+ case glslang::EOpConvIntToDouble:
+ case glslang::EOpConvInt64ToFloat:
+ case glslang::EOpConvInt64ToDouble:
+ case glslang::EOpConvInt64ToFloat16:
+ convOp = spv::OpConvertSToF;
+ break;
+
+ case glslang::EOpConvUint8ToFloat16:
+ case glslang::EOpConvUint8ToFloat:
+ case glslang::EOpConvUint8ToDouble:
+ case glslang::EOpConvUint16ToFloat16:
+ case glslang::EOpConvUint16ToFloat:
+ case glslang::EOpConvUint16ToDouble:
+ case glslang::EOpConvUintToFloat16:
+ case glslang::EOpConvUintToFloat:
+ case glslang::EOpConvUintToDouble:
+ case glslang::EOpConvUint64ToFloat:
+ case glslang::EOpConvUint64ToDouble:
+ case glslang::EOpConvUint64ToFloat16:
+ convOp = spv::OpConvertUToF;
+ break;
+
+ case glslang::EOpConvFloat16ToInt8:
+ case glslang::EOpConvFloatToInt8:
+ case glslang::EOpConvDoubleToInt8:
+ case glslang::EOpConvFloat16ToInt16:
+ case glslang::EOpConvFloatToInt16:
+ case glslang::EOpConvDoubleToInt16:
+ case glslang::EOpConvFloat16ToInt:
+ case glslang::EOpConvFloatToInt:
+ case glslang::EOpConvDoubleToInt:
+ case glslang::EOpConvFloat16ToInt64:
+ case glslang::EOpConvFloatToInt64:
+ case glslang::EOpConvDoubleToInt64:
+ convOp = spv::OpConvertFToS;
+ break;
+
+ case glslang::EOpConvUint8ToInt8:
+ case glslang::EOpConvInt8ToUint8:
+ case glslang::EOpConvUint16ToInt16:
+ case glslang::EOpConvInt16ToUint16:
+ case glslang::EOpConvUintToInt:
+ case glslang::EOpConvIntToUint:
+ case glslang::EOpConvUint64ToInt64:
+ case glslang::EOpConvInt64ToUint64:
+ if (builder.isInSpecConstCodeGenMode()) {
+ // Build zero scalar or vector for OpIAdd.
+#ifndef GLSLANG_WEB
+ if(op == glslang::EOpConvUint8ToInt8 || op == glslang::EOpConvInt8ToUint8) {
+ zero = builder.makeUint8Constant(0);
+ } else if (op == glslang::EOpConvUint16ToInt16 || op == glslang::EOpConvInt16ToUint16) {
+ zero = builder.makeUint16Constant(0);
+ } else if (op == glslang::EOpConvUint64ToInt64 || op == glslang::EOpConvInt64ToUint64) {
+ zero = builder.makeUint64Constant(0);
+ } else
+#endif
+ {
+ zero = builder.makeUintConstant(0);
+ }
+ zero = makeSmearedConstant(zero, vectorSize);
+ // Use OpIAdd, instead of OpBitcast to do the conversion when
+ // generating for OpSpecConstantOp instruction.
+ return builder.createBinOp(spv::OpIAdd, destType, operand, zero);
+ }
+ // For normal run-time conversion instruction, use OpBitcast.
+ convOp = spv::OpBitcast;
+ break;
+
+ case glslang::EOpConvFloat16ToUint8:
+ case glslang::EOpConvFloatToUint8:
+ case glslang::EOpConvDoubleToUint8:
+ case glslang::EOpConvFloat16ToUint16:
+ case glslang::EOpConvFloatToUint16:
+ case glslang::EOpConvDoubleToUint16:
+ case glslang::EOpConvFloat16ToUint:
+ case glslang::EOpConvFloatToUint:
+ case glslang::EOpConvDoubleToUint:
+ case glslang::EOpConvFloatToUint64:
+ case glslang::EOpConvDoubleToUint64:
+ case glslang::EOpConvFloat16ToUint64:
+ convOp = spv::OpConvertFToU;
+ break;
+
+#ifndef GLSLANG_WEB
+ case glslang::EOpConvInt8ToBool:
+ case glslang::EOpConvUint8ToBool:
+ zero = builder.makeUint8Constant(0);
+ zero = makeSmearedConstant(zero, vectorSize);
+ return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
+ case glslang::EOpConvInt16ToBool:
+ case glslang::EOpConvUint16ToBool:
+ zero = builder.makeUint16Constant(0);
+ zero = makeSmearedConstant(zero, vectorSize);
+ return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
+ case glslang::EOpConvInt64ToBool:
+ case glslang::EOpConvUint64ToBool:
+ zero = builder.makeUint64Constant(0);
+ zero = makeSmearedConstant(zero, vectorSize);
+ return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
+ case glslang::EOpConvDoubleToBool:
+ zero = builder.makeDoubleConstant(0.0);
+ zero = makeSmearedConstant(zero, vectorSize);
+ return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
+ case glslang::EOpConvFloat16ToBool:
+ zero = builder.makeFloat16Constant(0.0F);
+ zero = makeSmearedConstant(zero, vectorSize);
+ return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
+ case glslang::EOpConvBoolToDouble:
+ convOp = spv::OpSelect;
+ zero = builder.makeDoubleConstant(0.0);
+ one = builder.makeDoubleConstant(1.0);
+ break;
+ case glslang::EOpConvBoolToFloat16:
+ convOp = spv::OpSelect;
+ zero = builder.makeFloat16Constant(0.0F);
+ one = builder.makeFloat16Constant(1.0F);
+ break;
+ case glslang::EOpConvBoolToInt8:
+ zero = builder.makeInt8Constant(0);
+ one = builder.makeInt8Constant(1);
+ convOp = spv::OpSelect;
+ break;
+ case glslang::EOpConvBoolToUint8:
+ zero = builder.makeUint8Constant(0);
+ one = builder.makeUint8Constant(1);
+ convOp = spv::OpSelect;
+ break;
+ case glslang::EOpConvBoolToInt16:
+ zero = builder.makeInt16Constant(0);
+ one = builder.makeInt16Constant(1);
+ convOp = spv::OpSelect;
+ break;
+ case glslang::EOpConvBoolToUint16:
+ zero = builder.makeUint16Constant(0);
+ one = builder.makeUint16Constant(1);
+ convOp = spv::OpSelect;
+ break;
+ case glslang::EOpConvDoubleToFloat:
+ case glslang::EOpConvFloatToDouble:
+ case glslang::EOpConvDoubleToFloat16:
+ case glslang::EOpConvFloat16ToDouble:
+ case glslang::EOpConvFloatToFloat16:
+ case glslang::EOpConvFloat16ToFloat:
+ convOp = spv::OpFConvert;
+ if (builder.isMatrixType(destType))
+ return createUnaryMatrixOperation(convOp, decorations, destType, operand, typeProxy);
+ break;
+
+ case glslang::EOpConvInt8ToInt16:
+ case glslang::EOpConvInt8ToInt:
+ case glslang::EOpConvInt8ToInt64:
+ case glslang::EOpConvInt16ToInt8:
+ case glslang::EOpConvInt16ToInt:
+ case glslang::EOpConvInt16ToInt64:
+ case glslang::EOpConvIntToInt8:
+ case glslang::EOpConvIntToInt16:
+ case glslang::EOpConvIntToInt64:
+ case glslang::EOpConvInt64ToInt8:
+ case glslang::EOpConvInt64ToInt16:
+ case glslang::EOpConvInt64ToInt:
+ convOp = spv::OpSConvert;
+ break;
+
+ case glslang::EOpConvUint8ToUint16:
+ case glslang::EOpConvUint8ToUint:
+ case glslang::EOpConvUint8ToUint64:
+ case glslang::EOpConvUint16ToUint8:
+ case glslang::EOpConvUint16ToUint:
+ case glslang::EOpConvUint16ToUint64:
+ case glslang::EOpConvUintToUint8:
+ case glslang::EOpConvUintToUint16:
+ case glslang::EOpConvUintToUint64:
+ case glslang::EOpConvUint64ToUint8:
+ case glslang::EOpConvUint64ToUint16:
+ case glslang::EOpConvUint64ToUint:
+ convOp = spv::OpUConvert;
+ break;
+
+ case glslang::EOpConvInt8ToUint16:
+ case glslang::EOpConvInt8ToUint:
+ case glslang::EOpConvInt8ToUint64:
+ case glslang::EOpConvInt16ToUint8:
+ case glslang::EOpConvInt16ToUint:
+ case glslang::EOpConvInt16ToUint64:
+ case glslang::EOpConvIntToUint8:
+ case glslang::EOpConvIntToUint16:
+ case glslang::EOpConvIntToUint64:
+ case glslang::EOpConvInt64ToUint8:
+ case glslang::EOpConvInt64ToUint16:
+ case glslang::EOpConvInt64ToUint:
+ case glslang::EOpConvUint8ToInt16:
+ case glslang::EOpConvUint8ToInt:
+ case glslang::EOpConvUint8ToInt64:
+ case glslang::EOpConvUint16ToInt8:
+ case glslang::EOpConvUint16ToInt:
+ case glslang::EOpConvUint16ToInt64:
+ case glslang::EOpConvUintToInt8:
+ case glslang::EOpConvUintToInt16:
+ case glslang::EOpConvUintToInt64:
+ case glslang::EOpConvUint64ToInt8:
+ case glslang::EOpConvUint64ToInt16:
+ case glslang::EOpConvUint64ToInt:
+ // OpSConvert/OpUConvert + OpBitCast
+ operand = createIntWidthConversion(op, operand, vectorSize);
+
+ if (builder.isInSpecConstCodeGenMode()) {
+ // Build zero scalar or vector for OpIAdd.
+ switch(op) {
+ case glslang::EOpConvInt16ToUint8:
+ case glslang::EOpConvIntToUint8:
+ case glslang::EOpConvInt64ToUint8:
+ case glslang::EOpConvUint16ToInt8:
+ case glslang::EOpConvUintToInt8:
+ case glslang::EOpConvUint64ToInt8:
+ zero = builder.makeUint8Constant(0);
+ break;
+ case glslang::EOpConvInt8ToUint16:
+ case glslang::EOpConvIntToUint16:
+ case glslang::EOpConvInt64ToUint16:
+ case glslang::EOpConvUint8ToInt16:
+ case glslang::EOpConvUintToInt16:
+ case glslang::EOpConvUint64ToInt16:
+ zero = builder.makeUint16Constant(0);
+ break;
+ case glslang::EOpConvInt8ToUint:
+ case glslang::EOpConvInt16ToUint:
+ case glslang::EOpConvInt64ToUint:
+ case glslang::EOpConvUint8ToInt:
+ case glslang::EOpConvUint16ToInt:
+ case glslang::EOpConvUint64ToInt:
+ zero = builder.makeUintConstant(0);
+ break;
+ case glslang::EOpConvInt8ToUint64:
+ case glslang::EOpConvInt16ToUint64:
+ case glslang::EOpConvIntToUint64:
+ case glslang::EOpConvUint8ToInt64:
+ case glslang::EOpConvUint16ToInt64:
+ case glslang::EOpConvUintToInt64:
+ zero = builder.makeUint64Constant(0);
+ break;
+ default:
+ assert(false && "Default missing");
+ break;
+ }
+ zero = makeSmearedConstant(zero, vectorSize);
+ // Use OpIAdd, instead of OpBitcast to do the conversion when
+ // generating for OpSpecConstantOp instruction.
+ return builder.createBinOp(spv::OpIAdd, destType, operand, zero);
+ }
+ // For normal run-time conversion instruction, use OpBitcast.
+ convOp = spv::OpBitcast;
+ break;
+ case glslang::EOpConvUint64ToPtr:
+ convOp = spv::OpConvertUToPtr;
+ break;
+ case glslang::EOpConvPtrToUint64:
+ convOp = spv::OpConvertPtrToU;
+ break;
+ case glslang::EOpConvPtrToUvec2:
+ case glslang::EOpConvUvec2ToPtr:
+ if (builder.isVector(operand))
+ builder.promoteIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer,
+ spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5);
+ convOp = spv::OpBitcast;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ spv::Id result = 0;
+ if (convOp == spv::OpNop)
+ return result;
+
+ if (convOp == spv::OpSelect) {
+ zero = makeSmearedConstant(zero, vectorSize);
+ one = makeSmearedConstant(one, vectorSize);
+ result = builder.createTriOp(convOp, destType, operand, one, zero);
+ } else
+ result = builder.createUnaryOp(convOp, destType, operand);
+
+ result = builder.setPrecision(result, decorations.precision);
+ decorations.addNonUniform(builder, result);
+ return result;
+}
+
+spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vectorSize)
+{
+ if (vectorSize == 0)
+ return constant;
+
+ spv::Id vectorTypeId = builder.makeVectorType(builder.getTypeId(constant), vectorSize);
+ std::vector<spv::Id> components;
+ for (int c = 0; c < vectorSize; ++c)
+ components.push_back(constant);
+ return builder.makeCompositeConstant(vectorTypeId, components);
+}
+
+// For glslang ops that map to SPV atomic opCodes
+spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
+{
+ spv::Op opCode = spv::OpNop;
+
+ switch (op) {
+ case glslang::EOpAtomicAdd:
+ case glslang::EOpImageAtomicAdd:
+ case glslang::EOpAtomicCounterAdd:
+ opCode = spv::OpAtomicIAdd;
+ break;
+ case glslang::EOpAtomicCounterSubtract:
+ opCode = spv::OpAtomicISub;
+ break;
+ case glslang::EOpAtomicMin:
+ case glslang::EOpImageAtomicMin:
+ case glslang::EOpAtomicCounterMin:
+ opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMin : spv::OpAtomicSMin;
+ break;
+ case glslang::EOpAtomicMax:
+ case glslang::EOpImageAtomicMax:
+ case glslang::EOpAtomicCounterMax:
+ opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMax : spv::OpAtomicSMax;
+ break;
+ case glslang::EOpAtomicAnd:
+ case glslang::EOpImageAtomicAnd:
+ case glslang::EOpAtomicCounterAnd:
+ opCode = spv::OpAtomicAnd;
+ break;
+ case glslang::EOpAtomicOr:
+ case glslang::EOpImageAtomicOr:
+ case glslang::EOpAtomicCounterOr:
+ opCode = spv::OpAtomicOr;
+ break;
+ case glslang::EOpAtomicXor:
+ case glslang::EOpImageAtomicXor:
+ case glslang::EOpAtomicCounterXor:
+ opCode = spv::OpAtomicXor;
+ break;
+ case glslang::EOpAtomicExchange:
+ case glslang::EOpImageAtomicExchange:
+ case glslang::EOpAtomicCounterExchange:
+ opCode = spv::OpAtomicExchange;
+ break;
+ case glslang::EOpAtomicCompSwap:
+ case glslang::EOpImageAtomicCompSwap:
+ case glslang::EOpAtomicCounterCompSwap:
+ opCode = spv::OpAtomicCompareExchange;
+ break;
+ case glslang::EOpAtomicCounterIncrement:
+ opCode = spv::OpAtomicIIncrement;
+ break;
+ case glslang::EOpAtomicCounterDecrement:
+ opCode = spv::OpAtomicIDecrement;
+ break;
+ case glslang::EOpAtomicCounter:
+ case glslang::EOpImageAtomicLoad:
+ case glslang::EOpAtomicLoad:
+ opCode = spv::OpAtomicLoad;
+ break;
+ case glslang::EOpAtomicStore:
+ case glslang::EOpImageAtomicStore:
+ opCode = spv::OpAtomicStore;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (typeProxy == glslang::EbtInt64 || typeProxy == glslang::EbtUint64)
+ builder.addCapability(spv::CapabilityInt64Atomics);
+
+ // Sort out the operands
+ // - mapping from glslang -> SPV
+ // - there are extra SPV operands that are optional in glslang
+ // - compare-exchange swaps the value and comparator
+ // - compare-exchange has an extra memory semantics
+ // - EOpAtomicCounterDecrement needs a post decrement
+ spv::Id pointerId = 0, compareId = 0, valueId = 0;
+ // scope defaults to Device in the old model, QueueFamilyKHR in the new model
+ spv::Id scopeId;
+ if (glslangIntermediate->usingVulkanMemoryModel()) {
+ scopeId = builder.makeUintConstant(spv::ScopeQueueFamilyKHR);
+ } else {
+ scopeId = builder.makeUintConstant(spv::ScopeDevice);
+ }
+ // semantics default to relaxed
+ spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && glslangIntermediate->usingVulkanMemoryModel() ?
+ spv::MemorySemanticsVolatileMask :
+ spv::MemorySemanticsMaskNone);
+ spv::Id semanticsId2 = semanticsId;
+
+ pointerId = operands[0];
+ if (opCode == spv::OpAtomicIIncrement || opCode == spv::OpAtomicIDecrement) {
+ // no additional operands
+ } else if (opCode == spv::OpAtomicCompareExchange) {
+ compareId = operands[1];
+ valueId = operands[2];
+ if (operands.size() > 3) {
+ scopeId = operands[3];
+ semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5]));
+ semanticsId2 = builder.makeUintConstant(builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7]));
+ }
+ } else if (opCode == spv::OpAtomicLoad) {
+ if (operands.size() > 1) {
+ scopeId = operands[1];
+ semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]));
+ }
+ } else {
+ // atomic store or RMW
+ valueId = operands[1];
+ if (operands.size() > 2) {
+ scopeId = operands[2];
+ semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4]));
+ }
+ }
+
+ // Check for capabilities
+ unsigned semanticsImmediate = builder.getConstantScalar(semanticsId) | builder.getConstantScalar(semanticsId2);
+ if (semanticsImmediate & (spv::MemorySemanticsMakeAvailableKHRMask |
+ spv::MemorySemanticsMakeVisibleKHRMask |
+ spv::MemorySemanticsOutputMemoryKHRMask |
+ spv::MemorySemanticsVolatileMask)) {
+ builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
+ }
+
+ if (glslangIntermediate->usingVulkanMemoryModel() && builder.getConstantScalar(scopeId) == spv::ScopeDevice) {
+ builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
+ }
+
+ std::vector<spv::Id> spvAtomicOperands; // hold the spv operands
+ spvAtomicOperands.push_back(pointerId);
+ spvAtomicOperands.push_back(scopeId);
+ spvAtomicOperands.push_back(semanticsId);
+ if (opCode == spv::OpAtomicCompareExchange) {
+ spvAtomicOperands.push_back(semanticsId2);
+ spvAtomicOperands.push_back(valueId);
+ spvAtomicOperands.push_back(compareId);
+ } else if (opCode != spv::OpAtomicLoad && opCode != spv::OpAtomicIIncrement && opCode != spv::OpAtomicIDecrement) {
+ spvAtomicOperands.push_back(valueId);
+ }
+
+ if (opCode == spv::OpAtomicStore) {
+ builder.createNoResultOp(opCode, spvAtomicOperands);
+ return 0;
+ } else {
+ spv::Id resultId = builder.createOp(opCode, typeId, spvAtomicOperands);
+
+ // GLSL and HLSL atomic-counter decrement return post-decrement value,
+ // while SPIR-V returns pre-decrement value. Translate between these semantics.
+ if (op == glslang::EOpAtomicCounterDecrement)
+ resultId = builder.createBinOp(spv::OpISub, typeId, resultId, builder.makeIntConstant(1));
+
+ return resultId;
+ }
+}
+
+// Create group invocation operations.
+spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
+{
+ bool isUnsigned = isTypeUnsignedInt(typeProxy);
+ bool isFloat = isTypeFloat(typeProxy);
+
+ spv::Op opCode = spv::OpNop;
+ std::vector<spv::IdImmediate> spvGroupOperands;
+ spv::GroupOperation groupOperation = spv::GroupOperationMax;
+
+ if (op == glslang::EOpBallot || op == glslang::EOpReadFirstInvocation ||
+ op == glslang::EOpReadInvocation) {
+ builder.addExtension(spv::E_SPV_KHR_shader_ballot);
+ builder.addCapability(spv::CapabilitySubgroupBallotKHR);
+ } else if (op == glslang::EOpAnyInvocation ||
+ op == glslang::EOpAllInvocations ||
+ op == glslang::EOpAllInvocationsEqual) {
+ builder.addExtension(spv::E_SPV_KHR_subgroup_vote);
+ builder.addCapability(spv::CapabilitySubgroupVoteKHR);
+ } else {
+ builder.addCapability(spv::CapabilityGroups);
+ if (op == glslang::EOpMinInvocationsNonUniform ||
+ op == glslang::EOpMaxInvocationsNonUniform ||
+ op == glslang::EOpAddInvocationsNonUniform ||
+ op == glslang::EOpMinInvocationsInclusiveScanNonUniform ||
+ op == glslang::EOpMaxInvocationsInclusiveScanNonUniform ||
+ op == glslang::EOpAddInvocationsInclusiveScanNonUniform ||
+ op == glslang::EOpMinInvocationsExclusiveScanNonUniform ||
+ op == glslang::EOpMaxInvocationsExclusiveScanNonUniform ||
+ op == glslang::EOpAddInvocationsExclusiveScanNonUniform)
+ builder.addExtension(spv::E_SPV_AMD_shader_ballot);
+
+ switch (op) {
+ case glslang::EOpMinInvocations:
+ case glslang::EOpMaxInvocations:
+ case glslang::EOpAddInvocations:
+ case glslang::EOpMinInvocationsNonUniform:
+ case glslang::EOpMaxInvocationsNonUniform:
+ case glslang::EOpAddInvocationsNonUniform:
+ groupOperation = spv::GroupOperationReduce;
+ break;
+ case glslang::EOpMinInvocationsInclusiveScan:
+ case glslang::EOpMaxInvocationsInclusiveScan:
+ case glslang::EOpAddInvocationsInclusiveScan:
+ case glslang::EOpMinInvocationsInclusiveScanNonUniform:
+ case glslang::EOpMaxInvocationsInclusiveScanNonUniform:
+ case glslang::EOpAddInvocationsInclusiveScanNonUniform:
+ groupOperation = spv::GroupOperationInclusiveScan;
+ break;
+ case glslang::EOpMinInvocationsExclusiveScan:
+ case glslang::EOpMaxInvocationsExclusiveScan:
+ case glslang::EOpAddInvocationsExclusiveScan:
+ case glslang::EOpMinInvocationsExclusiveScanNonUniform:
+ case glslang::EOpMaxInvocationsExclusiveScanNonUniform:
+ case glslang::EOpAddInvocationsExclusiveScanNonUniform:
+ groupOperation = spv::GroupOperationExclusiveScan;
+ break;
+ default:
+ break;
+ }
+ spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
+ spvGroupOperands.push_back(scope);
+ if (groupOperation != spv::GroupOperationMax) {
+ spv::IdImmediate groupOp = { false, (unsigned)groupOperation };
+ spvGroupOperands.push_back(groupOp);
+ }
+ }
+
+ for (auto opIt = operands.begin(); opIt != operands.end(); ++opIt) {
+ spv::IdImmediate op = { true, *opIt };
+ spvGroupOperands.push_back(op);
+ }
+
+ switch (op) {
+ case glslang::EOpAnyInvocation:
+ opCode = spv::OpSubgroupAnyKHR;
+ break;
+ case glslang::EOpAllInvocations:
+ opCode = spv::OpSubgroupAllKHR;
+ break;
+ case glslang::EOpAllInvocationsEqual:
+ opCode = spv::OpSubgroupAllEqualKHR;
+ break;
+ case glslang::EOpReadInvocation:
+ opCode = spv::OpSubgroupReadInvocationKHR;
+ if (builder.isVectorType(typeId))
+ return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands);
+ break;
+ case glslang::EOpReadFirstInvocation:
+ opCode = spv::OpSubgroupFirstInvocationKHR;
+ break;
+ case glslang::EOpBallot:
+ {
+ // NOTE: According to the spec, the result type of "OpSubgroupBallotKHR" must be a 4 component vector of 32
+ // bit integer types. The GLSL built-in function "ballotARB()" assumes the maximum number of invocations in
+ // a subgroup is 64. Thus, we have to convert uvec4.xy to uint64_t as follow:
+ //
+ // result = Bitcast(SubgroupBallotKHR(Predicate).xy)
+ //
+ spv::Id uintType = builder.makeUintType(32);
+ spv::Id uvec4Type = builder.makeVectorType(uintType, 4);
+ spv::Id result = builder.createOp(spv::OpSubgroupBallotKHR, uvec4Type, spvGroupOperands);
+
+ std::vector<spv::Id> components;
+ components.push_back(builder.createCompositeExtract(result, uintType, 0));
+ components.push_back(builder.createCompositeExtract(result, uintType, 1));
+
+ spv::Id uvec2Type = builder.makeVectorType(uintType, 2);
+ return builder.createUnaryOp(spv::OpBitcast, typeId,
+ builder.createCompositeConstruct(uvec2Type, components));
+ }
+
+ case glslang::EOpMinInvocations:
+ case glslang::EOpMaxInvocations:
+ case glslang::EOpAddInvocations:
+ case glslang::EOpMinInvocationsInclusiveScan:
+ case glslang::EOpMaxInvocationsInclusiveScan:
+ case glslang::EOpAddInvocationsInclusiveScan:
+ case glslang::EOpMinInvocationsExclusiveScan:
+ case glslang::EOpMaxInvocationsExclusiveScan:
+ case glslang::EOpAddInvocationsExclusiveScan:
+ if (op == glslang::EOpMinInvocations ||
+ op == glslang::EOpMinInvocationsInclusiveScan ||
+ op == glslang::EOpMinInvocationsExclusiveScan) {
+ if (isFloat)
+ opCode = spv::OpGroupFMin;
+ else {
+ if (isUnsigned)
+ opCode = spv::OpGroupUMin;
+ else
+ opCode = spv::OpGroupSMin;
+ }
+ } else if (op == glslang::EOpMaxInvocations ||
+ op == glslang::EOpMaxInvocationsInclusiveScan ||
+ op == glslang::EOpMaxInvocationsExclusiveScan) {
+ if (isFloat)
+ opCode = spv::OpGroupFMax;
+ else {
+ if (isUnsigned)
+ opCode = spv::OpGroupUMax;
+ else
+ opCode = spv::OpGroupSMax;
+ }
+ } else {
+ if (isFloat)
+ opCode = spv::OpGroupFAdd;
+ else
+ opCode = spv::OpGroupIAdd;
+ }
+
+ if (builder.isVectorType(typeId))
+ return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands);
+
+ break;
+ case glslang::EOpMinInvocationsNonUniform:
+ case glslang::EOpMaxInvocationsNonUniform:
+ case glslang::EOpAddInvocationsNonUniform:
+ case glslang::EOpMinInvocationsInclusiveScanNonUniform:
+ case glslang::EOpMaxInvocationsInclusiveScanNonUniform:
+ case glslang::EOpAddInvocationsInclusiveScanNonUniform:
+ case glslang::EOpMinInvocationsExclusiveScanNonUniform:
+ case glslang::EOpMaxInvocationsExclusiveScanNonUniform:
+ case glslang::EOpAddInvocationsExclusiveScanNonUniform:
+ if (op == glslang::EOpMinInvocationsNonUniform ||
+ op == glslang::EOpMinInvocationsInclusiveScanNonUniform ||
+ op == glslang::EOpMinInvocationsExclusiveScanNonUniform) {
+ if (isFloat)
+ opCode = spv::OpGroupFMinNonUniformAMD;
+ else {
+ if (isUnsigned)
+ opCode = spv::OpGroupUMinNonUniformAMD;
+ else
+ opCode = spv::OpGroupSMinNonUniformAMD;
+ }
+ }
+ else if (op == glslang::EOpMaxInvocationsNonUniform ||
+ op == glslang::EOpMaxInvocationsInclusiveScanNonUniform ||
+ op == glslang::EOpMaxInvocationsExclusiveScanNonUniform) {
+ if (isFloat)
+ opCode = spv::OpGroupFMaxNonUniformAMD;
+ else {
+ if (isUnsigned)
+ opCode = spv::OpGroupUMaxNonUniformAMD;
+ else
+ opCode = spv::OpGroupSMaxNonUniformAMD;
+ }
+ }
+ else {
+ if (isFloat)
+ opCode = spv::OpGroupFAddNonUniformAMD;
+ else
+ opCode = spv::OpGroupIAddNonUniformAMD;
+ }
+
+ if (builder.isVectorType(typeId))
+ return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands);
+
+ break;
+ default:
+ logger->missingFunctionality("invocation operation");
+ return spv::NoResult;
+ }
+
+ assert(opCode != spv::OpNop);
+ return builder.createOp(opCode, typeId, spvGroupOperands);
+}
+
+// Create group invocation operations on a vector
+spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation,
+ spv::Id typeId, std::vector<spv::Id>& operands)
+{
+ assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin ||
+ op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax ||
+ op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast ||
+ op == spv::OpSubgroupReadInvocationKHR ||
+ op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD ||
+ op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD ||
+ op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD);
+
+ // Handle group invocation operations scalar by scalar.
+ // The result type is the same type as the original type.
+ // The algorithm is to:
+ // - break the vector into scalars
+ // - apply the operation to each scalar
+ // - make a vector out the scalar results
+
+ // get the types sorted out
+ int numComponents = builder.getNumComponents(operands[0]);
+ spv::Id scalarType = builder.getScalarTypeId(builder.getTypeId(operands[0]));
+ std::vector<spv::Id> results;
+
+ // do each scalar op
+ for (int comp = 0; comp < numComponents; ++comp) {
+ std::vector<unsigned int> indexes;
+ indexes.push_back(comp);
+ spv::IdImmediate scalar = { true, builder.createCompositeExtract(operands[0], scalarType, indexes) };
+ std::vector<spv::IdImmediate> spvGroupOperands;
+ if (op == spv::OpSubgroupReadInvocationKHR) {
+ spvGroupOperands.push_back(scalar);
+ spv::IdImmediate operand = { true, operands[1] };
+ spvGroupOperands.push_back(operand);
+ } else if (op == spv::OpGroupBroadcast) {
+ spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
+ spvGroupOperands.push_back(scope);
+ spvGroupOperands.push_back(scalar);
+ spv::IdImmediate operand = { true, operands[1] };
+ spvGroupOperands.push_back(operand);
+ } else {
+ spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
+ spvGroupOperands.push_back(scope);
+ spv::IdImmediate groupOp = { false, (unsigned)groupOperation };
+ spvGroupOperands.push_back(groupOp);
+ spvGroupOperands.push_back(scalar);
+ }
+
+ results.push_back(builder.createOp(op, scalarType, spvGroupOperands));
+ }
+
+ // put the pieces together
+ return builder.createCompositeConstruct(typeId, results);
+}
+
+// Create subgroup invocation operations.
+spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, spv::Id typeId,
+ std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
+{
+ // Add the required capabilities.
+ switch (op) {
+ case glslang::EOpSubgroupElect:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ break;
+ case glslang::EOpSubgroupAll:
+ case glslang::EOpSubgroupAny:
+ case glslang::EOpSubgroupAllEqual:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformVote);
+ break;
+ case glslang::EOpSubgroupBroadcast:
+ case glslang::EOpSubgroupBroadcastFirst:
+ case glslang::EOpSubgroupBallot:
+ case glslang::EOpSubgroupInverseBallot:
+ case glslang::EOpSubgroupBallotBitExtract:
+ case glslang::EOpSubgroupBallotBitCount:
+ case glslang::EOpSubgroupBallotInclusiveBitCount:
+ case glslang::EOpSubgroupBallotExclusiveBitCount:
+ case glslang::EOpSubgroupBallotFindLSB:
+ case glslang::EOpSubgroupBallotFindMSB:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformBallot);
+ break;
+ case glslang::EOpSubgroupShuffle:
+ case glslang::EOpSubgroupShuffleXor:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformShuffle);
+ break;
+ case glslang::EOpSubgroupShuffleUp:
+ case glslang::EOpSubgroupShuffleDown:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformShuffleRelative);
+ break;
+ case glslang::EOpSubgroupAdd:
+ case glslang::EOpSubgroupMul:
+ case glslang::EOpSubgroupMin:
+ case glslang::EOpSubgroupMax:
+ case glslang::EOpSubgroupAnd:
+ case glslang::EOpSubgroupOr:
+ case glslang::EOpSubgroupXor:
+ case glslang::EOpSubgroupInclusiveAdd:
+ case glslang::EOpSubgroupInclusiveMul:
+ case glslang::EOpSubgroupInclusiveMin:
+ case glslang::EOpSubgroupInclusiveMax:
+ case glslang::EOpSubgroupInclusiveAnd:
+ case glslang::EOpSubgroupInclusiveOr:
+ case glslang::EOpSubgroupInclusiveXor:
+ case glslang::EOpSubgroupExclusiveAdd:
+ case glslang::EOpSubgroupExclusiveMul:
+ case glslang::EOpSubgroupExclusiveMin:
+ case glslang::EOpSubgroupExclusiveMax:
+ case glslang::EOpSubgroupExclusiveAnd:
+ case glslang::EOpSubgroupExclusiveOr:
+ case glslang::EOpSubgroupExclusiveXor:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformArithmetic);
+ break;
+ case glslang::EOpSubgroupClusteredAdd:
+ case glslang::EOpSubgroupClusteredMul:
+ case glslang::EOpSubgroupClusteredMin:
+ case glslang::EOpSubgroupClusteredMax:
+ case glslang::EOpSubgroupClusteredAnd:
+ case glslang::EOpSubgroupClusteredOr:
+ case glslang::EOpSubgroupClusteredXor:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformClustered);
+ break;
+ case glslang::EOpSubgroupQuadBroadcast:
+ case glslang::EOpSubgroupQuadSwapHorizontal:
+ case glslang::EOpSubgroupQuadSwapVertical:
+ case glslang::EOpSubgroupQuadSwapDiagonal:
+ builder.addCapability(spv::CapabilityGroupNonUniform);
+ builder.addCapability(spv::CapabilityGroupNonUniformQuad);
+ break;
+ case glslang::EOpSubgroupPartitionedAdd:
+ case glslang::EOpSubgroupPartitionedMul:
+ case glslang::EOpSubgroupPartitionedMin:
+ case glslang::EOpSubgroupPartitionedMax:
+ case glslang::EOpSubgroupPartitionedAnd:
+ case glslang::EOpSubgroupPartitionedOr:
+ case glslang::EOpSubgroupPartitionedXor:
+ case glslang::EOpSubgroupPartitionedInclusiveAdd:
+ case glslang::EOpSubgroupPartitionedInclusiveMul:
+ case glslang::EOpSubgroupPartitionedInclusiveMin:
+ case glslang::EOpSubgroupPartitionedInclusiveMax:
+ case glslang::EOpSubgroupPartitionedInclusiveAnd:
+ case glslang::EOpSubgroupPartitionedInclusiveOr:
+ case glslang::EOpSubgroupPartitionedInclusiveXor:
+ case glslang::EOpSubgroupPartitionedExclusiveAdd:
+ case glslang::EOpSubgroupPartitionedExclusiveMul:
+ case glslang::EOpSubgroupPartitionedExclusiveMin:
+ case glslang::EOpSubgroupPartitionedExclusiveMax:
+ case glslang::EOpSubgroupPartitionedExclusiveAnd:
+ case glslang::EOpSubgroupPartitionedExclusiveOr:
+ case glslang::EOpSubgroupPartitionedExclusiveXor:
+ builder.addExtension(spv::E_SPV_NV_shader_subgroup_partitioned);
+ builder.addCapability(spv::CapabilityGroupNonUniformPartitionedNV);
+ break;
+ default: assert(0 && "Unhandled subgroup operation!");
+ }
+
+
+ const bool isUnsigned = isTypeUnsignedInt(typeProxy);
+ const bool isFloat = isTypeFloat(typeProxy);
+ const bool isBool = typeProxy == glslang::EbtBool;
+
+ spv::Op opCode = spv::OpNop;
+
+ // Figure out which opcode to use.
+ switch (op) {
+ case glslang::EOpSubgroupElect: opCode = spv::OpGroupNonUniformElect; break;
+ case glslang::EOpSubgroupAll: opCode = spv::OpGroupNonUniformAll; break;
+ case glslang::EOpSubgroupAny: opCode = spv::OpGroupNonUniformAny; break;
+ case glslang::EOpSubgroupAllEqual: opCode = spv::OpGroupNonUniformAllEqual; break;
+ case glslang::EOpSubgroupBroadcast: opCode = spv::OpGroupNonUniformBroadcast; break;
+ case glslang::EOpSubgroupBroadcastFirst: opCode = spv::OpGroupNonUniformBroadcastFirst; break;
+ case glslang::EOpSubgroupBallot: opCode = spv::OpGroupNonUniformBallot; break;
+ case glslang::EOpSubgroupInverseBallot: opCode = spv::OpGroupNonUniformInverseBallot; break;
+ case glslang::EOpSubgroupBallotBitExtract: opCode = spv::OpGroupNonUniformBallotBitExtract; break;
+ case glslang::EOpSubgroupBallotBitCount:
+ case glslang::EOpSubgroupBallotInclusiveBitCount:
+ case glslang::EOpSubgroupBallotExclusiveBitCount: opCode = spv::OpGroupNonUniformBallotBitCount; break;
+ case glslang::EOpSubgroupBallotFindLSB: opCode = spv::OpGroupNonUniformBallotFindLSB; break;
+ case glslang::EOpSubgroupBallotFindMSB: opCode = spv::OpGroupNonUniformBallotFindMSB; break;
+ case glslang::EOpSubgroupShuffle: opCode = spv::OpGroupNonUniformShuffle; break;
+ case glslang::EOpSubgroupShuffleXor: opCode = spv::OpGroupNonUniformShuffleXor; break;
+ case glslang::EOpSubgroupShuffleUp: opCode = spv::OpGroupNonUniformShuffleUp; break;
+ case glslang::EOpSubgroupShuffleDown: opCode = spv::OpGroupNonUniformShuffleDown; break;
+ case glslang::EOpSubgroupAdd:
+ case glslang::EOpSubgroupInclusiveAdd:
+ case glslang::EOpSubgroupExclusiveAdd:
+ case glslang::EOpSubgroupClusteredAdd:
+ case glslang::EOpSubgroupPartitionedAdd:
+ case glslang::EOpSubgroupPartitionedInclusiveAdd:
+ case glslang::EOpSubgroupPartitionedExclusiveAdd:
+ if (isFloat) {
+ opCode = spv::OpGroupNonUniformFAdd;
+ } else {
+ opCode = spv::OpGroupNonUniformIAdd;
+ }
+ break;
+ case glslang::EOpSubgroupMul:
+ case glslang::EOpSubgroupInclusiveMul:
+ case glslang::EOpSubgroupExclusiveMul:
+ case glslang::EOpSubgroupClusteredMul:
+ case glslang::EOpSubgroupPartitionedMul:
+ case glslang::EOpSubgroupPartitionedInclusiveMul:
+ case glslang::EOpSubgroupPartitionedExclusiveMul:
+ if (isFloat) {
+ opCode = spv::OpGroupNonUniformFMul;
+ } else {
+ opCode = spv::OpGroupNonUniformIMul;
+ }
+ break;
+ case glslang::EOpSubgroupMin:
+ case glslang::EOpSubgroupInclusiveMin:
+ case glslang::EOpSubgroupExclusiveMin:
+ case glslang::EOpSubgroupClusteredMin:
+ case glslang::EOpSubgroupPartitionedMin:
+ case glslang::EOpSubgroupPartitionedInclusiveMin:
+ case glslang::EOpSubgroupPartitionedExclusiveMin:
+ if (isFloat) {
+ opCode = spv::OpGroupNonUniformFMin;
+ } else if (isUnsigned) {
+ opCode = spv::OpGroupNonUniformUMin;
+ } else {
+ opCode = spv::OpGroupNonUniformSMin;
+ }
+ break;
+ case glslang::EOpSubgroupMax:
+ case glslang::EOpSubgroupInclusiveMax:
+ case glslang::EOpSubgroupExclusiveMax:
+ case glslang::EOpSubgroupClusteredMax:
+ case glslang::EOpSubgroupPartitionedMax:
+ case glslang::EOpSubgroupPartitionedInclusiveMax:
+ case glslang::EOpSubgroupPartitionedExclusiveMax:
+ if (isFloat) {
+ opCode = spv::OpGroupNonUniformFMax;
+ } else if (isUnsigned) {
+ opCode = spv::OpGroupNonUniformUMax;
+ } else {
+ opCode = spv::OpGroupNonUniformSMax;
+ }
+ break;
+ case glslang::EOpSubgroupAnd:
+ case glslang::EOpSubgroupInclusiveAnd:
+ case glslang::EOpSubgroupExclusiveAnd:
+ case glslang::EOpSubgroupClusteredAnd:
+ case glslang::EOpSubgroupPartitionedAnd:
+ case glslang::EOpSubgroupPartitionedInclusiveAnd:
+ case glslang::EOpSubgroupPartitionedExclusiveAnd:
+ if (isBool) {
+ opCode = spv::OpGroupNonUniformLogicalAnd;
+ } else {
+ opCode = spv::OpGroupNonUniformBitwiseAnd;
+ }
+ break;
+ case glslang::EOpSubgroupOr:
+ case glslang::EOpSubgroupInclusiveOr:
+ case glslang::EOpSubgroupExclusiveOr:
+ case glslang::EOpSubgroupClusteredOr:
+ case glslang::EOpSubgroupPartitionedOr:
+ case glslang::EOpSubgroupPartitionedInclusiveOr:
+ case glslang::EOpSubgroupPartitionedExclusiveOr:
+ if (isBool) {
+ opCode = spv::OpGroupNonUniformLogicalOr;
+ } else {
+ opCode = spv::OpGroupNonUniformBitwiseOr;
+ }
+ break;
+ case glslang::EOpSubgroupXor:
+ case glslang::EOpSubgroupInclusiveXor:
+ case glslang::EOpSubgroupExclusiveXor:
+ case glslang::EOpSubgroupClusteredXor:
+ case glslang::EOpSubgroupPartitionedXor:
+ case glslang::EOpSubgroupPartitionedInclusiveXor:
+ case glslang::EOpSubgroupPartitionedExclusiveXor:
+ if (isBool) {
+ opCode = spv::OpGroupNonUniformLogicalXor;
+ } else {
+ opCode = spv::OpGroupNonUniformBitwiseXor;
+ }
+ break;
+ case glslang::EOpSubgroupQuadBroadcast: opCode = spv::OpGroupNonUniformQuadBroadcast; break;
+ case glslang::EOpSubgroupQuadSwapHorizontal:
+ case glslang::EOpSubgroupQuadSwapVertical:
+ case glslang::EOpSubgroupQuadSwapDiagonal: opCode = spv::OpGroupNonUniformQuadSwap; break;
+ default: assert(0 && "Unhandled subgroup operation!");
+ }
+
+ // get the right Group Operation
+ spv::GroupOperation groupOperation = spv::GroupOperationMax;
+ switch (op) {
+ default:
+ break;
+ case glslang::EOpSubgroupBallotBitCount:
+ case glslang::EOpSubgroupAdd:
+ case glslang::EOpSubgroupMul:
+ case glslang::EOpSubgroupMin:
+ case glslang::EOpSubgroupMax:
+ case glslang::EOpSubgroupAnd:
+ case glslang::EOpSubgroupOr:
+ case glslang::EOpSubgroupXor:
+ groupOperation = spv::GroupOperationReduce;
+ break;
+ case glslang::EOpSubgroupBallotInclusiveBitCount:
+ case glslang::EOpSubgroupInclusiveAdd:
+ case glslang::EOpSubgroupInclusiveMul:
+ case glslang::EOpSubgroupInclusiveMin:
+ case glslang::EOpSubgroupInclusiveMax:
+ case glslang::EOpSubgroupInclusiveAnd:
+ case glslang::EOpSubgroupInclusiveOr:
+ case glslang::EOpSubgroupInclusiveXor:
+ groupOperation = spv::GroupOperationInclusiveScan;
+ break;
+ case glslang::EOpSubgroupBallotExclusiveBitCount:
+ case glslang::EOpSubgroupExclusiveAdd:
+ case glslang::EOpSubgroupExclusiveMul:
+ case glslang::EOpSubgroupExclusiveMin:
+ case glslang::EOpSubgroupExclusiveMax:
+ case glslang::EOpSubgroupExclusiveAnd:
+ case glslang::EOpSubgroupExclusiveOr:
+ case glslang::EOpSubgroupExclusiveXor:
+ groupOperation = spv::GroupOperationExclusiveScan;
+ break;
+ case glslang::EOpSubgroupClusteredAdd:
+ case glslang::EOpSubgroupClusteredMul:
+ case glslang::EOpSubgroupClusteredMin:
+ case glslang::EOpSubgroupClusteredMax:
+ case glslang::EOpSubgroupClusteredAnd:
+ case glslang::EOpSubgroupClusteredOr:
+ case glslang::EOpSubgroupClusteredXor:
+ groupOperation = spv::GroupOperationClusteredReduce;
+ break;
+ case glslang::EOpSubgroupPartitionedAdd:
+ case glslang::EOpSubgroupPartitionedMul:
+ case glslang::EOpSubgroupPartitionedMin:
+ case glslang::EOpSubgroupPartitionedMax:
+ case glslang::EOpSubgroupPartitionedAnd:
+ case glslang::EOpSubgroupPartitionedOr:
+ case glslang::EOpSubgroupPartitionedXor:
+ groupOperation = spv::GroupOperationPartitionedReduceNV;
+ break;
+ case glslang::EOpSubgroupPartitionedInclusiveAdd:
+ case glslang::EOpSubgroupPartitionedInclusiveMul:
+ case glslang::EOpSubgroupPartitionedInclusiveMin:
+ case glslang::EOpSubgroupPartitionedInclusiveMax:
+ case glslang::EOpSubgroupPartitionedInclusiveAnd:
+ case glslang::EOpSubgroupPartitionedInclusiveOr:
+ case glslang::EOpSubgroupPartitionedInclusiveXor:
+ groupOperation = spv::GroupOperationPartitionedInclusiveScanNV;
+ break;
+ case glslang::EOpSubgroupPartitionedExclusiveAdd:
+ case glslang::EOpSubgroupPartitionedExclusiveMul:
+ case glslang::EOpSubgroupPartitionedExclusiveMin:
+ case glslang::EOpSubgroupPartitionedExclusiveMax:
+ case glslang::EOpSubgroupPartitionedExclusiveAnd:
+ case glslang::EOpSubgroupPartitionedExclusiveOr:
+ case glslang::EOpSubgroupPartitionedExclusiveXor:
+ groupOperation = spv::GroupOperationPartitionedExclusiveScanNV;
+ break;
+ }
+
+ // build the instruction
+ std::vector<spv::IdImmediate> spvGroupOperands;
+
+ // Every operation begins with the Execution Scope operand.
+ spv::IdImmediate executionScope = { true, builder.makeUintConstant(spv::ScopeSubgroup) };
+ spvGroupOperands.push_back(executionScope);
+
+ // Next, for all operations that use a Group Operation, push that as an operand.
+ if (groupOperation != spv::GroupOperationMax) {
+ spv::IdImmediate groupOperand = { false, (unsigned)groupOperation };
+ spvGroupOperands.push_back(groupOperand);
+ }
+
+ // Push back the operands next.
+ for (auto opIt = operands.cbegin(); opIt != operands.cend(); ++opIt) {
+ spv::IdImmediate operand = { true, *opIt };
+ spvGroupOperands.push_back(operand);
+ }
+
+ // Some opcodes have additional operands.
+ spv::Id directionId = spv::NoResult;
+ switch (op) {
+ default: break;
+ case glslang::EOpSubgroupQuadSwapHorizontal: directionId = builder.makeUintConstant(0); break;
+ case glslang::EOpSubgroupQuadSwapVertical: directionId = builder.makeUintConstant(1); break;
+ case glslang::EOpSubgroupQuadSwapDiagonal: directionId = builder.makeUintConstant(2); break;
+ }
+ if (directionId != spv::NoResult) {
+ spv::IdImmediate direction = { true, directionId };
+ spvGroupOperands.push_back(direction);
+ }
+
+ return builder.createOp(opCode, typeId, spvGroupOperands);
+}
+
+spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
+{
+ bool isUnsigned = isTypeUnsignedInt(typeProxy);
+ bool isFloat = isTypeFloat(typeProxy);
+
+ spv::Op opCode = spv::OpNop;
+ int extBuiltins = -1;
+ int libCall = -1;
+ size_t consumedOperands = operands.size();
+ spv::Id typeId0 = 0;
+ if (consumedOperands > 0)
+ typeId0 = builder.getTypeId(operands[0]);
+ spv::Id typeId1 = 0;
+ if (consumedOperands > 1)
+ typeId1 = builder.getTypeId(operands[1]);
+ spv::Id frexpIntType = 0;
+
+ switch (op) {
+ case glslang::EOpMin:
+ if (isFloat)
+ libCall = nanMinMaxClamp ? spv::GLSLstd450NMin : spv::GLSLstd450FMin;
+ else if (isUnsigned)
+ libCall = spv::GLSLstd450UMin;
+ else
+ libCall = spv::GLSLstd450SMin;
+ builder.promoteScalar(precision, operands.front(), operands.back());
+ break;
+ case glslang::EOpModf:
+ libCall = spv::GLSLstd450Modf;
+ break;
+ case glslang::EOpMax:
+ if (isFloat)
+ libCall = nanMinMaxClamp ? spv::GLSLstd450NMax : spv::GLSLstd450FMax;
+ else if (isUnsigned)
+ libCall = spv::GLSLstd450UMax;
+ else
+ libCall = spv::GLSLstd450SMax;
+ builder.promoteScalar(precision, operands.front(), operands.back());
+ break;
+ case glslang::EOpPow:
+ libCall = spv::GLSLstd450Pow;
+ break;
+ case glslang::EOpDot:
+ opCode = spv::OpDot;
+ break;
+ case glslang::EOpAtan:
+ libCall = spv::GLSLstd450Atan2;
+ break;
+
+ case glslang::EOpClamp:
+ if (isFloat)
+ libCall = nanMinMaxClamp ? spv::GLSLstd450NClamp : spv::GLSLstd450FClamp;
+ else if (isUnsigned)
+ libCall = spv::GLSLstd450UClamp;
+ else
+ libCall = spv::GLSLstd450SClamp;
+ builder.promoteScalar(precision, operands.front(), operands[1]);
+ builder.promoteScalar(precision, operands.front(), operands[2]);
+ break;
+ case glslang::EOpMix:
+ if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back())))) {
+ assert(isFloat);
+ libCall = spv::GLSLstd450FMix;
+ } else {
+ opCode = spv::OpSelect;
+ std::swap(operands.front(), operands.back());
+ }
+ builder.promoteScalar(precision, operands.front(), operands.back());
+ break;
+ case glslang::EOpStep:
+ libCall = spv::GLSLstd450Step;
+ builder.promoteScalar(precision, operands.front(), operands.back());
+ break;
+ case glslang::EOpSmoothStep:
+ libCall = spv::GLSLstd450SmoothStep;
+ builder.promoteScalar(precision, operands[0], operands[2]);
+ builder.promoteScalar(precision, operands[1], operands[2]);
+ break;
+
+ case glslang::EOpDistance:
+ libCall = spv::GLSLstd450Distance;
+ break;
+ case glslang::EOpCross:
+ libCall = spv::GLSLstd450Cross;
+ break;
+ case glslang::EOpFaceForward:
+ libCall = spv::GLSLstd450FaceForward;
+ break;
+ case glslang::EOpReflect:
+ libCall = spv::GLSLstd450Reflect;
+ break;
+ case glslang::EOpRefract:
+ libCall = spv::GLSLstd450Refract;
+ break;
+ case glslang::EOpBarrier:
+ {
+ // This is for the extended controlBarrier function, with four operands.
+ // The unextended barrier() goes through createNoArgOperation.
+ assert(operands.size() == 4);
+ unsigned int executionScope = builder.getConstantScalar(operands[0]);
+ unsigned int memoryScope = builder.getConstantScalar(operands[1]);
+ unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]);
+ builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics);
+ if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask |
+ spv::MemorySemanticsMakeVisibleKHRMask |
+ spv::MemorySemanticsOutputMemoryKHRMask |
+ spv::MemorySemanticsVolatileMask)) {
+ builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
+ }
+ if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || memoryScope == spv::ScopeDevice)) {
+ builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
+ }
+ return 0;
+ }
+ break;
+ case glslang::EOpMemoryBarrier:
+ {
+ // This is for the extended memoryBarrier function, with three operands.
+ // The unextended memoryBarrier() goes through createNoArgOperation.
+ assert(operands.size() == 3);
+ unsigned int memoryScope = builder.getConstantScalar(operands[0]);
+ unsigned int semantics = builder.getConstantScalar(operands[1]) | builder.getConstantScalar(operands[2]);
+ builder.createMemoryBarrier((spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics);
+ if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask |
+ spv::MemorySemanticsMakeVisibleKHRMask |
+ spv::MemorySemanticsOutputMemoryKHRMask |
+ spv::MemorySemanticsVolatileMask)) {
+ builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
+ }
+ if (glslangIntermediate->usingVulkanMemoryModel() && memoryScope == spv::ScopeDevice) {
+ builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
+ }
+ return 0;
+ }
+ break;
+
+#ifndef GLSLANG_WEB
+ case glslang::EOpInterpolateAtSample:
+ if (typeProxy == glslang::EbtFloat16)
+ builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
+ libCall = spv::GLSLstd450InterpolateAtSample;
+ break;
+ case glslang::EOpInterpolateAtOffset:
+ if (typeProxy == glslang::EbtFloat16)
+ builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
+ libCall = spv::GLSLstd450InterpolateAtOffset;
+ break;
+ case glslang::EOpAddCarry:
+ opCode = spv::OpIAddCarry;
+ typeId = builder.makeStructResultType(typeId0, typeId0);
+ consumedOperands = 2;
+ break;
+ case glslang::EOpSubBorrow:
+ opCode = spv::OpISubBorrow;
+ typeId = builder.makeStructResultType(typeId0, typeId0);
+ consumedOperands = 2;
+ break;
+ case glslang::EOpUMulExtended:
+ opCode = spv::OpUMulExtended;
+ typeId = builder.makeStructResultType(typeId0, typeId0);
+ consumedOperands = 2;
+ break;
+ case glslang::EOpIMulExtended:
+ opCode = spv::OpSMulExtended;
+ typeId = builder.makeStructResultType(typeId0, typeId0);
+ consumedOperands = 2;
+ break;
+ case glslang::EOpBitfieldExtract:
+ if (isUnsigned)
+ opCode = spv::OpBitFieldUExtract;
+ else
+ opCode = spv::OpBitFieldSExtract;
+ break;
+ case glslang::EOpBitfieldInsert:
+ opCode = spv::OpBitFieldInsert;
+ break;
+
+ case glslang::EOpFma:
+ libCall = spv::GLSLstd450Fma;
+ break;
+ case glslang::EOpFrexp:
+ {
+ libCall = spv::GLSLstd450FrexpStruct;
+ assert(builder.isPointerType(typeId1));
+ typeId1 = builder.getContainedTypeId(typeId1);
+ int width = builder.getScalarTypeWidth(typeId1);
+ if (width == 16)
+ // Using 16-bit exp operand, enable extension SPV_AMD_gpu_shader_int16
+ builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16);
+ if (builder.getNumComponents(operands[0]) == 1)
+ frexpIntType = builder.makeIntegerType(width, true);
+ else
+ frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), builder.getNumComponents(operands[0]));
+ typeId = builder.makeStructResultType(typeId0, frexpIntType);
+ consumedOperands = 1;
+ }
+ break;
+ case glslang::EOpLdexp:
+ libCall = spv::GLSLstd450Ldexp;
+ break;
+
+ case glslang::EOpReadInvocation:
+ return createInvocationsOperation(op, typeId, operands, typeProxy);
+
+ case glslang::EOpSubgroupBroadcast:
+ case glslang::EOpSubgroupBallotBitExtract:
+ case glslang::EOpSubgroupShuffle:
+ case glslang::EOpSubgroupShuffleXor:
+ case glslang::EOpSubgroupShuffleUp:
+ case glslang::EOpSubgroupShuffleDown:
+ case glslang::EOpSubgroupClusteredAdd:
+ case glslang::EOpSubgroupClusteredMul:
+ case glslang::EOpSubgroupClusteredMin:
+ case glslang::EOpSubgroupClusteredMax:
+ case glslang::EOpSubgroupClusteredAnd:
+ case glslang::EOpSubgroupClusteredOr:
+ case glslang::EOpSubgroupClusteredXor:
+ case glslang::EOpSubgroupQuadBroadcast:
+ case glslang::EOpSubgroupPartitionedAdd:
+ case glslang::EOpSubgroupPartitionedMul:
+ case glslang::EOpSubgroupPartitionedMin:
+ case glslang::EOpSubgroupPartitionedMax:
+ case glslang::EOpSubgroupPartitionedAnd:
+ case glslang::EOpSubgroupPartitionedOr:
+ case glslang::EOpSubgroupPartitionedXor:
+ case glslang::EOpSubgroupPartitionedInclusiveAdd:
+ case glslang::EOpSubgroupPartitionedInclusiveMul:
+ case glslang::EOpSubgroupPartitionedInclusiveMin:
+ case glslang::EOpSubgroupPartitionedInclusiveMax:
+ case glslang::EOpSubgroupPartitionedInclusiveAnd:
+ case glslang::EOpSubgroupPartitionedInclusiveOr:
+ case glslang::EOpSubgroupPartitionedInclusiveXor:
+ case glslang::EOpSubgroupPartitionedExclusiveAdd:
+ case glslang::EOpSubgroupPartitionedExclusiveMul:
+ case glslang::EOpSubgroupPartitionedExclusiveMin:
+ case glslang::EOpSubgroupPartitionedExclusiveMax:
+ case glslang::EOpSubgroupPartitionedExclusiveAnd:
+ case glslang::EOpSubgroupPartitionedExclusiveOr:
+ case glslang::EOpSubgroupPartitionedExclusiveXor:
+ return createSubgroupOperation(op, typeId, operands, typeProxy);
+
+ case glslang::EOpSwizzleInvocations:
+ extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
+ libCall = spv::SwizzleInvocationsAMD;
+ break;
+ case glslang::EOpSwizzleInvocationsMasked:
+ extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
+ libCall = spv::SwizzleInvocationsMaskedAMD;
+ break;
+ case glslang::EOpWriteInvocation:
+ extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
+ libCall = spv::WriteInvocationAMD;
+ break;
+
+ case glslang::EOpMin3:
+ extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax);
+ if (isFloat)
+ libCall = spv::FMin3AMD;
+ else {
+ if (isUnsigned)
+ libCall = spv::UMin3AMD;
+ else
+ libCall = spv::SMin3AMD;
+ }
+ break;
+ case glslang::EOpMax3:
+ extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax);
+ if (isFloat)
+ libCall = spv::FMax3AMD;
+ else {
+ if (isUnsigned)
+ libCall = spv::UMax3AMD;
+ else
+ libCall = spv::SMax3AMD;
+ }
+ break;
+ case glslang::EOpMid3:
+ extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax);
+ if (isFloat)
+ libCall = spv::FMid3AMD;
+ else {
+ if (isUnsigned)
+ libCall = spv::UMid3AMD;
+ else
+ libCall = spv::SMid3AMD;
+ }
+ break;
+
+ case glslang::EOpInterpolateAtVertex:
+ if (typeProxy == glslang::EbtFloat16)
+ builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
+ extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
+ libCall = spv::InterpolateAtVertexAMD;
+ break;
+
+ case glslang::EOpReportIntersectionNV:
+ {
+ typeId = builder.makeBoolType();
+ opCode = spv::OpReportIntersectionNV;
+ }
+ break;
+ case glslang::EOpTraceNV:
+ {
+ builder.createNoResultOp(spv::OpTraceNV, operands);
+ return 0;
+ }
+ break;
+ case glslang::EOpExecuteCallableNV:
+ {
+ builder.createNoResultOp(spv::OpExecuteCallableNV, operands);
+ return 0;
+ }
+ break;
+ case glslang::EOpWritePackedPrimitiveIndices4x8NV:
+ builder.createNoResultOp(spv::OpWritePackedPrimitiveIndices4x8NV, operands);
+ return 0;
+ case glslang::EOpCooperativeMatrixMulAdd:
+ opCode = spv::OpCooperativeMatrixMulAddNV;
+ break;
+#endif // GLSLANG_WEB
+ default:
+ return 0;
+ }
+
+ spv::Id id = 0;
+ if (libCall >= 0) {
+ // Use an extended instruction from the standard library.
+ // Construct the call arguments, without modifying the original operands vector.
+ // We might need the remaining arguments, e.g. in the EOpFrexp case.
+ std::vector<spv::Id> callArguments(operands.begin(), operands.begin() + consumedOperands);
+ id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, callArguments);
+ } else if (opCode == spv::OpDot && !isFloat) {
+ // int dot(int, int)
+ // NOTE: never called for scalar/vector1, this is turned into simple mul before this can be reached
+ const int componentCount = builder.getNumComponents(operands[0]);
+ spv::Id mulOp = builder.createBinOp(spv::OpIMul, builder.getTypeId(operands[0]), operands[0], operands[1]);
+ builder.setPrecision(mulOp, precision);
+ id = builder.createCompositeExtract(mulOp, typeId, 0);
+ for (int i = 1; i < componentCount; ++i) {
+ builder.setPrecision(id, precision);
+ id = builder.createBinOp(spv::OpIAdd, typeId, id, builder.createCompositeExtract(mulOp, typeId, i));
+ }
+ } else {
+ switch (consumedOperands) {
+ case 0:
+ // should all be handled by visitAggregate and createNoArgOperation
+ assert(0);
+ return 0;
+ case 1:
+ // should all be handled by createUnaryOperation
+ assert(0);
+ return 0;
+ case 2:
+ id = builder.createBinOp(opCode, typeId, operands[0], operands[1]);
+ break;
+ default:
+ // anything 3 or over doesn't have l-value operands, so all should be consumed
+ assert(consumedOperands == operands.size());
+ id = builder.createOp(opCode, typeId, operands);
+ break;
+ }
+ }
+
+#ifndef GLSLANG_WEB
+ // Decode the return types that were structures
+ switch (op) {
+ case glslang::EOpAddCarry:
+ case glslang::EOpSubBorrow:
+ builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]);
+ id = builder.createCompositeExtract(id, typeId0, 0);
+ break;
+ case glslang::EOpUMulExtended:
+ case glslang::EOpIMulExtended:
+ builder.createStore(builder.createCompositeExtract(id, typeId0, 0), operands[3]);
+ builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]);
+ break;
+ case glslang::EOpFrexp:
+ {
+ assert(operands.size() == 2);
+ if (builder.isFloatType(builder.getScalarTypeId(typeId1))) {
+ // "exp" is floating-point type (from HLSL intrinsic)
+ spv::Id member1 = builder.createCompositeExtract(id, frexpIntType, 1);
+ member1 = builder.createUnaryOp(spv::OpConvertSToF, typeId1, member1);
+ builder.createStore(member1, operands[1]);
+ } else
+ // "exp" is integer type (from GLSL built-in function)
+ builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]);
+ id = builder.createCompositeExtract(id, typeId0, 0);
+ }
+ break;
+ default:
+ break;
+ }
+#endif
+
+ return builder.setPrecision(id, precision);
+}
+
+// Intrinsics with no arguments (or no return value, and no precision).
+spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId)
+{
+ // GLSL memory barriers use queuefamily scope in new model, device scope in old model
+ spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice;
+
+ switch (op) {
+ case glslang::EOpBarrier:
+ if (glslangIntermediate->getStage() == EShLangTessControl) {
+ if (glslangIntermediate->usingVulkanMemoryModel()) {
+ builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup,
+ spv::MemorySemanticsOutputMemoryKHRMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
+ } else {
+ builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeInvocation, spv::MemorySemanticsMaskNone);
+ }
+ } else {
+ builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup,
+ spv::MemorySemanticsWorkgroupMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ }
+ return 0;
+ case glslang::EOpMemoryBarrier:
+ builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAllMemory |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+ case glslang::EOpMemoryBarrierBuffer:
+ builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsUniformMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+ case glslang::EOpMemoryBarrierShared:
+ builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsWorkgroupMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+ case glslang::EOpGroupMemoryBarrier:
+ builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsAllMemory |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+#ifndef GLSLANG_WEB
+ case glslang::EOpMemoryBarrierAtomicCounter:
+ builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAtomicCounterMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+ case glslang::EOpMemoryBarrierImage:
+ builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsImageMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+ case glslang::EOpAllMemoryBarrierWithGroupSync:
+ builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice,
+ spv::MemorySemanticsAllMemory |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+ case glslang::EOpDeviceMemoryBarrier:
+ builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask |
+ spv::MemorySemanticsImageMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+ case glslang::EOpDeviceMemoryBarrierWithGroupSync:
+ builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask |
+ spv::MemorySemanticsImageMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+ case glslang::EOpWorkgroupMemoryBarrier:
+ builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsWorkgroupMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+ case glslang::EOpWorkgroupMemoryBarrierWithGroupSync:
+ builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup,
+ spv::MemorySemanticsWorkgroupMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return 0;
+ case glslang::EOpSubgroupBarrier:
+ builder.createControlBarrier(spv::ScopeSubgroup, spv::ScopeSubgroup, spv::MemorySemanticsAllMemory |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return spv::NoResult;
+ case glslang::EOpSubgroupMemoryBarrier:
+ builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsAllMemory |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return spv::NoResult;
+ case glslang::EOpSubgroupMemoryBarrierBuffer:
+ builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsUniformMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return spv::NoResult;
+ case glslang::EOpSubgroupMemoryBarrierImage:
+ builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsImageMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return spv::NoResult;
+ case glslang::EOpSubgroupMemoryBarrierShared:
+ builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsWorkgroupMemoryMask |
+ spv::MemorySemanticsAcquireReleaseMask);
+ return spv::NoResult;
+
+ case glslang::EOpEmitVertex:
+ builder.createNoResultOp(spv::OpEmitVertex);
+ return 0;
+ case glslang::EOpEndPrimitive:
+ builder.createNoResultOp(spv::OpEndPrimitive);
+ return 0;
+
+ case glslang::EOpSubgroupElect: {
+ std::vector<spv::Id> operands;
+ return createSubgroupOperation(op, typeId, operands, glslang::EbtVoid);
+ }
+ case glslang::EOpTime:
+ {
+ std::vector<spv::Id> args; // Dummy arguments
+ spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args);
+ return builder.setPrecision(id, precision);
+ }
+ case glslang::EOpIgnoreIntersectionNV:
+ builder.createNoResultOp(spv::OpIgnoreIntersectionNV);
+ return 0;
+ case glslang::EOpTerminateRayNV:
+ builder.createNoResultOp(spv::OpTerminateRayNV);
+ return 0;
+
+ case glslang::EOpBeginInvocationInterlock:
+ builder.createNoResultOp(spv::OpBeginInvocationInterlockEXT);
+ return 0;
+ case glslang::EOpEndInvocationInterlock:
+ builder.createNoResultOp(spv::OpEndInvocationInterlockEXT);
+ return 0;
+
+ case glslang::EOpIsHelperInvocation:
+ {
+ std::vector<spv::Id> args; // Dummy arguments
+ builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation);
+ builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT);
+ return builder.createOp(spv::OpIsHelperInvocationEXT, typeId, args);
+ }
+
+ case glslang::EOpReadClockSubgroupKHR: {
+ std::vector<spv::Id> args;
+ args.push_back(builder.makeUintConstant(spv::ScopeSubgroup));
+ builder.addExtension(spv::E_SPV_KHR_shader_clock);
+ builder.addCapability(spv::CapabilityShaderClockKHR);
+ return builder.createOp(spv::OpReadClockKHR, typeId, args);
+ }
+
+ case glslang::EOpReadClockDeviceKHR: {
+ std::vector<spv::Id> args;
+ args.push_back(builder.makeUintConstant(spv::ScopeDevice));
+ builder.addExtension(spv::E_SPV_KHR_shader_clock);
+ builder.addCapability(spv::CapabilityShaderClockKHR);
+ return builder.createOp(spv::OpReadClockKHR, typeId, args);
+ }
+#endif
+ default:
+ break;
+ }
+
+ logger->missingFunctionality("unknown operation with no arguments");
+
+ return 0;
+}
+
+spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol)
+{
+ auto iter = symbolValues.find(symbol->getId());
+ spv::Id id;
+ if (symbolValues.end() != iter) {
+ id = iter->second;
+ return id;
+ }
+
+ // it was not found, create it
+ spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false);
+ auto forcedType = getForcedType(builtIn, symbol->getType());
+ id = createSpvVariable(symbol, forcedType.first);
+ symbolValues[symbol->getId()] = id;
+ if (forcedType.second != spv::NoType)
+ forceType[id] = forcedType.second;
+
+ if (symbol->getBasicType() != glslang::EbtBlock) {
+ builder.addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
+ builder.addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier()));
+ builder.addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier()));
+#ifndef GLSLANG_WEB
+ addMeshNVDecoration(id, /*member*/ -1, symbol->getType().getQualifier());
+ if (symbol->getQualifier().hasComponent())
+ builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent);
+ if (symbol->getQualifier().hasIndex())
+ builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex);
+#endif
+ if (symbol->getType().getQualifier().hasSpecConstantId())
+ builder.addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId);
+ // atomic counters use this:
+ if (symbol->getQualifier().hasOffset())
+ builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset);
+ }
+
+ if (symbol->getQualifier().hasLocation())
+ builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation);
+ builder.addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier()));
+ if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) {
+ builder.addCapability(spv::CapabilityGeometryStreams);
+ builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream);
+ }
+ if (symbol->getQualifier().hasSet())
+ builder.addDecoration(id, spv::DecorationDescriptorSet, symbol->getQualifier().layoutSet);
+ else if (IsDescriptorResource(symbol->getType())) {
+ // default to 0
+ builder.addDecoration(id, spv::DecorationDescriptorSet, 0);
+ }
+ if (symbol->getQualifier().hasBinding())
+ builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding);
+ else if (IsDescriptorResource(symbol->getType())) {
+ // default to 0
+ builder.addDecoration(id, spv::DecorationBinding, 0);
+ }
+ if (symbol->getQualifier().hasAttachment())
+ builder.addDecoration(id, spv::DecorationInputAttachmentIndex, symbol->getQualifier().layoutAttachment);
+ if (glslangIntermediate->getXfbMode()) {
+ builder.addCapability(spv::CapabilityTransformFeedback);
+ if (symbol->getQualifier().hasXfbBuffer()) {
+ builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
+ unsigned stride = glslangIntermediate->getXfbStride(symbol->getQualifier().layoutXfbBuffer);
+ if (stride != glslang::TQualifier::layoutXfbStrideEnd)
+ builder.addDecoration(id, spv::DecorationXfbStride, stride);
+ }
+ if (symbol->getQualifier().hasXfbOffset())
+ builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset);
+ }
+
+ // add built-in variable decoration
+ if (builtIn != spv::BuiltInMax) {
+ builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
+ }
+
+#ifndef GLSLANG_WEB
+ if (symbol->getType().isImage()) {
+ std::vector<spv::Decoration> memory;
+ TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, glslangIntermediate->usingVulkanMemoryModel());
+ for (unsigned int i = 0; i < memory.size(); ++i)
+ builder.addDecoration(id, memory[i]);
+ }
+
+ // nonuniform
+ builder.addDecoration(id, TranslateNonUniformDecoration(symbol->getType().getQualifier()));
+
+ if (builtIn == spv::BuiltInSampleMask) {
+ spv::Decoration decoration;
+ // GL_NV_sample_mask_override_coverage extension
+ if (glslangIntermediate->getLayoutOverrideCoverage())
+ decoration = (spv::Decoration)spv::DecorationOverrideCoverageNV;
+ else
+ decoration = (spv::Decoration)spv::DecorationMax;
+ builder.addDecoration(id, decoration);
+ if (decoration != spv::DecorationMax) {
+ builder.addCapability(spv::CapabilitySampleMaskOverrideCoverageNV);
+ builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage);
+ }
+ }
+ else if (builtIn == spv::BuiltInLayer) {
+ // SPV_NV_viewport_array2 extension
+ if (symbol->getQualifier().layoutViewportRelative) {
+ builder.addDecoration(id, (spv::Decoration)spv::DecorationViewportRelativeNV);
+ builder.addCapability(spv::CapabilityShaderViewportMaskNV);
+ builder.addExtension(spv::E_SPV_NV_viewport_array2);
+ }
+ if (symbol->getQualifier().layoutSecondaryViewportRelativeOffset != -2048) {
+ builder.addDecoration(id, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV,
+ symbol->getQualifier().layoutSecondaryViewportRelativeOffset);
+ builder.addCapability(spv::CapabilityShaderStereoViewNV);
+ builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
+ }
+ }
+
+ if (symbol->getQualifier().layoutPassthrough) {
+ builder.addDecoration(id, spv::DecorationPassthroughNV);
+ builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
+ builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
+ }
+ if (symbol->getQualifier().pervertexNV) {
+ builder.addDecoration(id, spv::DecorationPerVertexNV);
+ builder.addCapability(spv::CapabilityFragmentBarycentricNV);
+ builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric);
+ }
+
+ if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) {
+ builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
+ builder.addDecoration(id, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE,
+ symbol->getType().getQualifier().semanticName);
+ }
+
+ if (symbol->isReference()) {
+ builder.addDecoration(id, symbol->getType().getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
+ }
+#endif
+
+ return id;
+}
+
+#ifndef GLSLANG_WEB
+// add per-primitive, per-view. per-task decorations to a struct member (member >= 0) or an object
+void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier& qualifier)
+{
+ if (member >= 0) {
+ if (qualifier.perPrimitiveNV) {
+ // Need to add capability/extension for fragment shader.
+ // Mesh shader already adds this by default.
+ if (glslangIntermediate->getStage() == EShLangFragment) {
+ builder.addCapability(spv::CapabilityMeshShadingNV);
+ builder.addExtension(spv::E_SPV_NV_mesh_shader);
+ }
+ builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerPrimitiveNV);
+ }
+ if (qualifier.perViewNV)
+ builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerViewNV);
+ if (qualifier.perTaskNV)
+ builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerTaskNV);
+ } else {
+ if (qualifier.perPrimitiveNV) {
+ // Need to add capability/extension for fragment shader.
+ // Mesh shader already adds this by default.
+ if (glslangIntermediate->getStage() == EShLangFragment) {
+ builder.addCapability(spv::CapabilityMeshShadingNV);
+ builder.addExtension(spv::E_SPV_NV_mesh_shader);
+ }
+ builder.addDecoration(id, spv::DecorationPerPrimitiveNV);
+ }
+ if (qualifier.perViewNV)
+ builder.addDecoration(id, spv::DecorationPerViewNV);
+ if (qualifier.perTaskNV)
+ builder.addDecoration(id, spv::DecorationPerTaskNV);
+ }
+}
+#endif
+
+// Make a full tree of instructions to build a SPIR-V specialization constant,
+// or regular constant if possible.
+//
+// TBD: this is not yet done, nor verified to be the best design, it does do the leaf symbols though
+//
+// Recursively walk the nodes. The nodes form a tree whose leaves are
+// regular constants, which themselves are trees that createSpvConstant()
+// recursively walks. So, this function walks the "top" of the tree:
+// - emit specialization constant-building instructions for specConstant
+// - when running into a non-spec-constant, switch to createSpvConstant()
+spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node)
+{
+ assert(node.getQualifier().isConstant());
+
+ // Handle front-end constants first (non-specialization constants).
+ if (! node.getQualifier().specConstant) {
+ // hand off to the non-spec-constant path
+ assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
+ int nextConst = 0;
+ return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
+ nextConst, false);
+ }
+
+ // We now know we have a specialization constant to build
+
+ // gl_WorkGroupSize is a special case until the front-end handles hierarchical specialization constants,
+ // even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ...
+ if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) {
+ std::vector<spv::Id> dimConstId;
+ for (int dim = 0; dim < 3; ++dim) {
+ bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet);
+ dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst));
+ if (specConst) {
+ builder.addDecoration(dimConstId.back(), spv::DecorationSpecId,
+ glslangIntermediate->getLocalSizeSpecId(dim));
+ }
+ }
+ return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true);
+ }
+
+ // An AST node labelled as specialization constant should be a symbol node.
+ // Its initializer should either be a sub tree with constant nodes, or a constant union array.
+ if (auto* sn = node.getAsSymbolNode()) {
+ spv::Id result;
+ if (auto* sub_tree = sn->getConstSubtree()) {
+ // Traverse the constant constructor sub tree like generating normal run-time instructions.
+ // During the AST traversal, if the node is marked as 'specConstant', SpecConstantOpModeGuard
+ // will set the builder into spec constant op instruction generating mode.
+ sub_tree->traverse(this);
+ result = accessChainLoad(sub_tree->getType());
+ } else if (auto* const_union_array = &sn->getConstArray()) {
+ int nextConst = 0;
+ result = createSpvConstantFromConstUnionArray(sn->getType(), *const_union_array, nextConst, true);
+ } else {
+ logger->missingFunctionality("Invalid initializer for spec onstant.");
+ return spv::NoResult;
+ }
+ builder.addName(result, sn->getName().c_str());
+ return result;
+ }
+
+ // Neither a front-end constant node, nor a specialization constant node with constant union array or
+ // constant sub tree as initializer.
+ logger->missingFunctionality("Neither a front-end constant nor a spec constant.");
+ return spv::NoResult;
+}
+
+// Use 'consts' as the flattened glslang source of scalar constants to recursively
+// build the aggregate SPIR-V constant.
+//
+// If there are not enough elements present in 'consts', 0 will be substituted;
+// an empty 'consts' can be used to create a fully zeroed SPIR-V constant.
+//
+spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
+{
+ // vector of constants for SPIR-V
+ std::vector<spv::Id> spvConsts;
+
+ // Type is used for struct and array constants
+ spv::Id typeId = convertGlslangToSpvType(glslangType);
+
+ if (glslangType.isArray()) {
+ glslang::TType elementType(glslangType, 0);
+ for (int i = 0; i < glslangType.getOuterArraySize(); ++i)
+ spvConsts.push_back(createSpvConstantFromConstUnionArray(elementType, consts, nextConst, false));
+ } else if (glslangType.isMatrix()) {
+ glslang::TType vectorType(glslangType, 0);
+ for (int col = 0; col < glslangType.getMatrixCols(); ++col)
+ spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false));
+ } else if (glslangType.isCoopMat()) {
+ glslang::TType componentType(glslangType.getBasicType());
+ spvConsts.push_back(createSpvConstantFromConstUnionArray(componentType, consts, nextConst, false));
+ } else if (glslangType.isStruct()) {
+ glslang::TVector<glslang::TTypeLoc>::const_iterator iter;
+ for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter)
+ spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false));
+ } else if (glslangType.getVectorSize() > 1) {
+ for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) {
+ bool zero = nextConst >= consts.size();
+ switch (glslangType.getBasicType()) {
+ case glslang::EbtInt:
+ spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst()));
+ break;
+ case glslang::EbtUint:
+ spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst()));
+ break;
+ case glslang::EbtFloat:
+ spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
+ break;
+ case glslang::EbtBool:
+ spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst()));
+ break;
+#ifndef GLSLANG_WEB
+ case glslang::EbtInt8:
+ spvConsts.push_back(builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const()));
+ break;
+ case glslang::EbtUint8:
+ spvConsts.push_back(builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const()));
+ break;
+ case glslang::EbtInt16:
+ spvConsts.push_back(builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const()));
+ break;
+ case glslang::EbtUint16:
+ spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const()));
+ break;
+ case glslang::EbtInt64:
+ spvConsts.push_back(builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const()));
+ break;
+ case glslang::EbtUint64:
+ spvConsts.push_back(builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const()));
+ break;
+ case glslang::EbtDouble:
+ spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst()));
+ break;
+ case glslang::EbtFloat16:
+ spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
+ break;
+#endif
+ default:
+ assert(0);
+ break;
+ }
+ ++nextConst;
+ }
+ } else {
+ // we have a non-aggregate (scalar) constant
+ bool zero = nextConst >= consts.size();
+ spv::Id scalar = 0;
+ switch (glslangType.getBasicType()) {
+ case glslang::EbtInt:
+ scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant);
+ break;
+ case glslang::EbtUint:
+ scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant);
+ break;
+ case glslang::EbtFloat:
+ scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
+ break;
+ case glslang::EbtBool:
+ scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant);
+ break;
+#ifndef GLSLANG_WEB
+ case glslang::EbtInt8:
+ scalar = builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const(), specConstant);
+ break;
+ case glslang::EbtUint8:
+ scalar = builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const(), specConstant);
+ break;
+ case glslang::EbtInt16:
+ scalar = builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const(), specConstant);
+ break;
+ case glslang::EbtUint16:
+ scalar = builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const(), specConstant);
+ break;
+ case glslang::EbtInt64:
+ scalar = builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const(), specConstant);
+ break;
+ case glslang::EbtUint64:
+ scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant);
+ break;
+ case glslang::EbtDouble:
+ scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant);
+ break;
+ case glslang::EbtFloat16:
+ scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
+ break;
+ case glslang::EbtReference:
+ scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant);
+ scalar = builder.createUnaryOp(spv::OpBitcast, typeId, scalar);
+ break;
+#endif
+ default:
+ assert(0);
+ break;
+ }
+ ++nextConst;
+ return scalar;
+ }
+
+ return builder.makeCompositeConstant(typeId, spvConsts);
+}
+
+// Return true if the node is a constant or symbol whose reading has no
+// non-trivial observable cost or effect.
+bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node)
+{
+ // don't know what this is
+ if (node == nullptr)
+ return false;
+
+ // a constant is safe
+ if (node->getAsConstantUnion() != nullptr)
+ return true;
+
+ // not a symbol means non-trivial
+ if (node->getAsSymbolNode() == nullptr)
+ return false;
+
+ // a symbol, depends on what's being read
+ switch (node->getType().getQualifier().storage) {
+ case glslang::EvqTemporary:
+ case glslang::EvqGlobal:
+ case glslang::EvqIn:
+ case glslang::EvqInOut:
+ case glslang::EvqConst:
+ case glslang::EvqConstReadOnly:
+ case glslang::EvqUniform:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// A node is trivial if it is a single operation with no side effects.
+// HLSL (and/or vectors) are always trivial, as it does not short circuit.
+// Otherwise, error on the side of saying non-trivial.
+// Return true if trivial.
+bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node)
+{
+ if (node == nullptr)
+ return false;
+
+ // count non scalars as trivial, as well as anything coming from HLSL
+ if (! node->getType().isScalarOrVec1() || glslangIntermediate->getSource() == glslang::EShSourceHlsl)
+ return true;
+
+ // symbols and constants are trivial
+ if (isTrivialLeaf(node))
+ return true;
+
+ // otherwise, it needs to be a simple operation or one or two leaf nodes
+
+ // not a simple operation
+ const glslang::TIntermBinary* binaryNode = node->getAsBinaryNode();
+ const glslang::TIntermUnary* unaryNode = node->getAsUnaryNode();
+ if (binaryNode == nullptr && unaryNode == nullptr)
+ return false;
+
+ // not on leaf nodes
+ if (binaryNode && (! isTrivialLeaf(binaryNode->getLeft()) || ! isTrivialLeaf(binaryNode->getRight())))
+ return false;
+
+ if (unaryNode && ! isTrivialLeaf(unaryNode->getOperand())) {
+ return false;
+ }
+
+ switch (node->getAsOperator()->getOp()) {
+ case glslang::EOpLogicalNot:
+ case glslang::EOpConvIntToBool:
+ case glslang::EOpConvUintToBool:
+ case glslang::EOpConvFloatToBool:
+ case glslang::EOpConvDoubleToBool:
+ case glslang::EOpEqual:
+ case glslang::EOpNotEqual:
+ case glslang::EOpLessThan:
+ case glslang::EOpGreaterThan:
+ case glslang::EOpLessThanEqual:
+ case glslang::EOpGreaterThanEqual:
+ case glslang::EOpIndexDirect:
+ case glslang::EOpIndexDirectStruct:
+ case glslang::EOpLogicalXor:
+ case glslang::EOpAny:
+ case glslang::EOpAll:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Emit short-circuiting code, where 'right' is never evaluated unless
+// the left side is true (for &&) or false (for ||).
+spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, glslang::TIntermTyped& right)
+{
+ spv::Id boolTypeId = builder.makeBoolType();
+
+ // emit left operand
+ builder.clearAccessChain();
+ left.traverse(this);
+ spv::Id leftId = accessChainLoad(left.getType());
+
+ // Operands to accumulate OpPhi operands
+ std::vector<spv::Id> phiOperands;
+ // accumulate left operand's phi information
+ phiOperands.push_back(leftId);
+ phiOperands.push_back(builder.getBuildPoint()->getId());
+
+ // Make the two kinds of operation symmetric with a "!"
+ // || => emit "if (! left) result = right"
+ // && => emit "if ( left) result = right"
+ //
+ // TODO: this runtime "not" for || could be avoided by adding functionality
+ // to 'builder' to have an "else" without an "then"
+ if (op == glslang::EOpLogicalOr)
+ leftId = builder.createUnaryOp(spv::OpLogicalNot, boolTypeId, leftId);
+
+ // make an "if" based on the left value
+ spv::Builder::If ifBuilder(leftId, spv::SelectionControlMaskNone, builder);
+
+ // emit right operand as the "then" part of the "if"
+ builder.clearAccessChain();
+ right.traverse(this);
+ spv::Id rightId = accessChainLoad(right.getType());
+
+ // accumulate left operand's phi information
+ phiOperands.push_back(rightId);
+ phiOperands.push_back(builder.getBuildPoint()->getId());
+
+ // finish the "if"
+ ifBuilder.makeEndIf();
+
+ // phi together the two results
+ return builder.createOp(spv::OpPhi, boolTypeId, phiOperands);
+}
+
+#ifndef GLSLANG_WEB
+// Return type Id of the imported set of extended instructions corresponds to the name.
+// Import this set if it has not been imported yet.
+spv::Id TGlslangToSpvTraverser::getExtBuiltins(const char* name)
+{
+ if (extBuiltinMap.find(name) != extBuiltinMap.end())
+ return extBuiltinMap[name];
+ else {
+ builder.addExtension(name);
+ spv::Id extBuiltins = builder.import(name);
+ extBuiltinMap[name] = extBuiltins;
+ return extBuiltins;
+ }
+}
+#endif
+
+}; // end anonymous namespace
+
+namespace glslang {
+
+void GetSpirvVersion(std::string& version)
+{
+ const int bufSize = 100;
+ char buf[bufSize];
+ snprintf(buf, bufSize, "0x%08x, Revision %d", spv::Version, spv::Revision);
+ version = buf;
+}
+
+// For low-order part of the generator's magic number. Bump up
+// when there is a change in the style (e.g., if SSA form changes,
+// or a different instruction sequence to do something gets used).
+int GetSpirvGeneratorVersion()
+{
+ // return 1; // start
+ // return 2; // EOpAtomicCounterDecrement gets a post decrement, to map between GLSL -> SPIR-V
+ // return 3; // change/correct barrier-instruction operands, to match memory model group decisions
+ // return 4; // some deeper access chains: for dynamic vector component, and local Boolean component
+ // return 5; // make OpArrayLength result type be an int with signedness of 0
+ // return 6; // revert version 5 change, which makes a different (new) kind of incorrect code,
+ // versions 4 and 6 each generate OpArrayLength as it has long been done
+ // return 7; // GLSL volatile keyword maps to both SPIR-V decorations Volatile and Coherent
+ return 8; // switch to new dead block eliminator; use OpUnreachable
+}
+
+// Write SPIR-V out to a binary file
+void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName)
+{
+ std::ofstream out;
+ out.open(baseName, std::ios::binary | std::ios::out);
+ if (out.fail())
+ printf("ERROR: Failed to open file: %s\n", baseName);
+ for (int i = 0; i < (int)spirv.size(); ++i) {
+ unsigned int word = spirv[i];
+ out.write((const char*)&word, 4);
+ }
+ out.close();
+}
+
+// Write SPIR-V out to a text file with 32-bit hexadecimal words
+void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName)
+{
+#ifndef GLSLANG_WEB
+ std::ofstream out;
+ out.open(baseName, std::ios::binary | std::ios::out);
+ if (out.fail())
+ printf("ERROR: Failed to open file: %s\n", baseName);
+ out << "\t// " <<
+ GetSpirvGeneratorVersion() << "." << GLSLANG_MINOR_VERSION << "." << GLSLANG_PATCH_LEVEL <<
+ std::endl;
+ if (varName != nullptr) {
+ out << "\t #pragma once" << std::endl;
+ out << "const uint32_t " << varName << "[] = {" << std::endl;
+ }
+ const int WORDS_PER_LINE = 8;
+ for (int i = 0; i < (int)spirv.size(); i += WORDS_PER_LINE) {
+ out << "\t";
+ for (int j = 0; j < WORDS_PER_LINE && i + j < (int)spirv.size(); ++j) {
+ const unsigned int word = spirv[i + j];
+ out << "0x" << std::hex << std::setw(8) << std::setfill('0') << word;
+ if (i + j + 1 < (int)spirv.size()) {
+ out << ",";
+ }
+ }
+ out << std::endl;
+ }
+ if (varName != nullptr) {
+ out << "};";
+ }
+ out.close();
+#endif
+}
+
+//
+// Set up the glslang traversal
+//
+void GlslangToSpv(const TIntermediate& intermediate, std::vector<unsigned int>& spirv, SpvOptions* options)
+{
+ spv::SpvBuildLogger logger;
+ GlslangToSpv(intermediate, spirv, &logger, options);
+}
+
+void GlslangToSpv(const TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+ spv::SpvBuildLogger* logger, SpvOptions* options)
+{
+ TIntermNode* root = intermediate.getTreeRoot();
+
+ if (root == 0)
+ return;
+
+ SpvOptions defaultOptions;
+ if (options == nullptr)
+ options = &defaultOptions;
+
+ GetThreadPoolAllocator().push();
+
+ TGlslangToSpvTraverser it(intermediate.getSpv().spv, &intermediate, logger, *options);
+ root->traverse(&it);
+ it.finishSpv();
+ it.dumpSpv(spirv);
+
+#if ENABLE_OPT
+ // If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan
+ // eg. forward and remove memory writes of opaque types.
+ bool prelegalization = intermediate.getSource() == EShSourceHlsl;
+ if ((intermediate.getSource() == EShSourceHlsl || options->optimizeSize) && !options->disableOptimizer) {
+ SpirvToolsLegalize(intermediate, spirv, logger, options);
+ prelegalization = false;
+ }
+
+ if (options->validate)
+ SpirvToolsValidate(intermediate, spirv, logger, prelegalization);
+
+ if (options->disassemble)
+ SpirvToolsDisassemble(std::cout, spirv);
+
+#endif
+
+ GetThreadPoolAllocator().pop();
+}
+
+}; // end namespace glslang
diff --git a/thirdparty/glslang/SPIRV/GlslangToSpv.h b/thirdparty/glslang/SPIRV/GlslangToSpv.h
new file mode 100755
index 0000000000..3907be43b7
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/GlslangToSpv.h
@@ -0,0 +1,61 @@
+//
+// Copyright (C) 2014 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#if defined(_MSC_VER) && _MSC_VER >= 1900
+ #pragma warning(disable : 4464) // relative include path contains '..'
+#endif
+
+#include "SpvTools.h"
+#include "glslang/Include/intermediate.h"
+
+#include <string>
+#include <vector>
+
+#include "Logger.h"
+
+namespace glslang {
+
+void GetSpirvVersion(std::string&);
+int GetSpirvGeneratorVersion();
+void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+ SpvOptions* options = nullptr);
+void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+ spv::SpvBuildLogger* logger, SpvOptions* options = nullptr);
+void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
+void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName);
+
+}
diff --git a/thirdparty/glslang/SPIRV/InReadableOrder.cpp b/thirdparty/glslang/SPIRV/InReadableOrder.cpp
new file mode 100644
index 0000000000..9d9410be93
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/InReadableOrder.cpp
@@ -0,0 +1,131 @@
+//
+// Copyright (C) 2016 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+// The SPIR-V spec requires code blocks to appear in an order satisfying the
+// dominator-tree direction (ie, dominator before the dominated). This is,
+// actually, easy to achieve: any pre-order CFG traversal algorithm will do it.
+// Because such algorithms visit a block only after traversing some path to it
+// from the root, they necessarily visit the block's idom first.
+//
+// But not every graph-traversal algorithm outputs blocks in an order that
+// appears logical to human readers. The problem is that unrelated branches may
+// be interspersed with each other, and merge blocks may come before some of the
+// branches being merged.
+//
+// A good, human-readable order of blocks may be achieved by performing
+// depth-first search but delaying merge nodes until after all their branches
+// have been visited. This is implemented below by the inReadableOrder()
+// function.
+
+#include "spvIR.h"
+
+#include <cassert>
+#include <unordered_set>
+
+using spv::Block;
+using spv::Id;
+
+namespace {
+// Traverses CFG in a readable order, invoking a pre-set callback on each block.
+// Use by calling visit() on the root block.
+class ReadableOrderTraverser {
+public:
+ ReadableOrderTraverser(std::function<void(Block*, spv::ReachReason, Block*)> callback)
+ : callback_(callback) {}
+ // Visits the block if it hasn't been visited already and isn't currently
+ // being delayed. Invokes callback(block, why, header), then descends into its
+ // successors. Delays merge-block and continue-block processing until all
+ // the branches have been completed. If |block| is an unreachable merge block or
+ // an unreachable continue target, then |header| is the corresponding header block.
+ void visit(Block* block, spv::ReachReason why, Block* header)
+ {
+ assert(block);
+ if (why == spv::ReachViaControlFlow) {
+ reachableViaControlFlow_.insert(block);
+ }
+ if (visited_.count(block) || delayed_.count(block))
+ return;
+ callback_(block, why, header);
+ visited_.insert(block);
+ Block* mergeBlock = nullptr;
+ Block* continueBlock = nullptr;
+ auto mergeInst = block->getMergeInstruction();
+ if (mergeInst) {
+ Id mergeId = mergeInst->getIdOperand(0);
+ mergeBlock = block->getParent().getParent().getInstruction(mergeId)->getBlock();
+ delayed_.insert(mergeBlock);
+ if (mergeInst->getOpCode() == spv::OpLoopMerge) {
+ Id continueId = mergeInst->getIdOperand(1);
+ continueBlock =
+ block->getParent().getParent().getInstruction(continueId)->getBlock();
+ delayed_.insert(continueBlock);
+ }
+ }
+ if (why == spv::ReachViaControlFlow) {
+ const auto& successors = block->getSuccessors();
+ for (auto it = successors.cbegin(); it != successors.cend(); ++it)
+ visit(*it, why, nullptr);
+ }
+ if (continueBlock) {
+ const spv::ReachReason continueWhy =
+ (reachableViaControlFlow_.count(continueBlock) > 0)
+ ? spv::ReachViaControlFlow
+ : spv::ReachDeadContinue;
+ delayed_.erase(continueBlock);
+ visit(continueBlock, continueWhy, block);
+ }
+ if (mergeBlock) {
+ const spv::ReachReason mergeWhy =
+ (reachableViaControlFlow_.count(mergeBlock) > 0)
+ ? spv::ReachViaControlFlow
+ : spv::ReachDeadMerge;
+ delayed_.erase(mergeBlock);
+ visit(mergeBlock, mergeWhy, block);
+ }
+ }
+
+private:
+ std::function<void(Block*, spv::ReachReason, Block*)> callback_;
+ // Whether a block has already been visited or is being delayed.
+ std::unordered_set<Block *> visited_, delayed_;
+
+ // The set of blocks that actually are reached via control flow.
+ std::unordered_set<Block *> reachableViaControlFlow_;
+};
+}
+
+void spv::inReadableOrder(Block* root, std::function<void(Block*, spv::ReachReason, Block*)> callback)
+{
+ ReadableOrderTraverser(callback).visit(root, spv::ReachViaControlFlow, nullptr);
+}
diff --git a/thirdparty/glslang/SPIRV/Logger.cpp b/thirdparty/glslang/SPIRV/Logger.cpp
new file mode 100644
index 0000000000..7ea0c6342b
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/Logger.cpp
@@ -0,0 +1,72 @@
+//
+// Copyright (C) 2016 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GLSLANG_WEB
+
+#include "Logger.h"
+
+#include <algorithm>
+#include <iterator>
+#include <sstream>
+
+namespace spv {
+
+void SpvBuildLogger::tbdFunctionality(const std::string& f)
+{
+ if (std::find(std::begin(tbdFeatures), std::end(tbdFeatures), f) == std::end(tbdFeatures))
+ tbdFeatures.push_back(f);
+}
+
+void SpvBuildLogger::missingFunctionality(const std::string& f)
+{
+ if (std::find(std::begin(missingFeatures), std::end(missingFeatures), f) == std::end(missingFeatures))
+ missingFeatures.push_back(f);
+}
+
+std::string SpvBuildLogger::getAllMessages() const {
+ std::ostringstream messages;
+ for (auto it = tbdFeatures.cbegin(); it != tbdFeatures.cend(); ++it)
+ messages << "TBD functionality: " << *it << "\n";
+ for (auto it = missingFeatures.cbegin(); it != missingFeatures.cend(); ++it)
+ messages << "Missing functionality: " << *it << "\n";
+ for (auto it = warnings.cbegin(); it != warnings.cend(); ++it)
+ messages << "warning: " << *it << "\n";
+ for (auto it = errors.cbegin(); it != errors.cend(); ++it)
+ messages << "error: " << *it << "\n";
+ return messages.str();
+}
+
+} // end spv namespace
+
+#endif \ No newline at end of file
diff --git a/thirdparty/glslang/SPIRV/Logger.h b/thirdparty/glslang/SPIRV/Logger.h
new file mode 100644
index 0000000000..411367c030
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/Logger.h
@@ -0,0 +1,83 @@
+//
+// Copyright (C) 2016 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GLSLANG_SPIRV_LOGGER_H
+#define GLSLANG_SPIRV_LOGGER_H
+
+#include <string>
+#include <vector>
+
+namespace spv {
+
+// A class for holding all SPIR-V build status messages, including
+// missing/TBD functionalities, warnings, and errors.
+class SpvBuildLogger {
+public:
+ SpvBuildLogger() {}
+
+#ifdef GLSLANG_WEB
+ void tbdFunctionality(const std::string& f) { }
+ void missingFunctionality(const std::string& f) { }
+ void warning(const std::string& w) { }
+ void error(const std::string& e) { errors.push_back(e); }
+ std::string getAllMessages() { return ""; }
+#else
+
+ // Registers a TBD functionality.
+ void tbdFunctionality(const std::string& f);
+ // Registers a missing functionality.
+ void missingFunctionality(const std::string& f);
+
+ // Logs a warning.
+ void warning(const std::string& w) { warnings.push_back(w); }
+ // Logs an error.
+ void error(const std::string& e) { errors.push_back(e); }
+
+ // Returns all messages accumulated in the order of:
+ // TBD functionalities, missing functionalities, warnings, errors.
+ std::string getAllMessages() const;
+#endif
+
+private:
+ SpvBuildLogger(const SpvBuildLogger&);
+
+ std::vector<std::string> tbdFeatures;
+ std::vector<std::string> missingFeatures;
+ std::vector<std::string> warnings;
+ std::vector<std::string> errors;
+};
+
+} // end spv namespace
+
+#endif // GLSLANG_SPIRV_LOGGER_H
diff --git a/thirdparty/glslang/SPIRV/SPVRemapper.cpp b/thirdparty/glslang/SPIRV/SPVRemapper.cpp
new file mode 100644
index 0000000000..fd0bb8950c
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/SPVRemapper.cpp
@@ -0,0 +1,1487 @@
+//
+// Copyright (C) 2015 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "SPVRemapper.h"
+#include "doc.h"
+
+#if !defined (use_cpp11)
+// ... not supported before C++11
+#else // defined (use_cpp11)
+
+#include <algorithm>
+#include <cassert>
+#include "../glslang/Include/Common.h"
+
+namespace spv {
+
+ // By default, just abort on error. Can be overridden via RegisterErrorHandler
+ spirvbin_t::errorfn_t spirvbin_t::errorHandler = [](const std::string&) { exit(5); };
+ // By default, eat log messages. Can be overridden via RegisterLogHandler
+ spirvbin_t::logfn_t spirvbin_t::logHandler = [](const std::string&) { };
+
+ // This can be overridden to provide other message behavior if needed
+ void spirvbin_t::msg(int minVerbosity, int indent, const std::string& txt) const
+ {
+ if (verbose >= minVerbosity)
+ logHandler(std::string(indent, ' ') + txt);
+ }
+
+ // hash opcode, with special handling for OpExtInst
+ std::uint32_t spirvbin_t::asOpCodeHash(unsigned word)
+ {
+ const spv::Op opCode = asOpCode(word);
+
+ std::uint32_t offset = 0;
+
+ switch (opCode) {
+ case spv::OpExtInst:
+ offset += asId(word + 4); break;
+ default:
+ break;
+ }
+
+ return opCode * 19 + offset; // 19 = small prime
+ }
+
+ spirvbin_t::range_t spirvbin_t::literalRange(spv::Op opCode) const
+ {
+ static const int maxCount = 1<<30;
+
+ switch (opCode) {
+ case spv::OpTypeFloat: // fall through...
+ case spv::OpTypePointer: return range_t(2, 3);
+ case spv::OpTypeInt: return range_t(2, 4);
+ // TODO: case spv::OpTypeImage:
+ // TODO: case spv::OpTypeSampledImage:
+ case spv::OpTypeSampler: return range_t(3, 8);
+ case spv::OpTypeVector: // fall through
+ case spv::OpTypeMatrix: // ...
+ case spv::OpTypePipe: return range_t(3, 4);
+ case spv::OpConstant: return range_t(3, maxCount);
+ default: return range_t(0, 0);
+ }
+ }
+
+ spirvbin_t::range_t spirvbin_t::typeRange(spv::Op opCode) const
+ {
+ static const int maxCount = 1<<30;
+
+ if (isConstOp(opCode))
+ return range_t(1, 2);
+
+ switch (opCode) {
+ case spv::OpTypeVector: // fall through
+ case spv::OpTypeMatrix: // ...
+ case spv::OpTypeSampler: // ...
+ case spv::OpTypeArray: // ...
+ case spv::OpTypeRuntimeArray: // ...
+ case spv::OpTypePipe: return range_t(2, 3);
+ case spv::OpTypeStruct: // fall through
+ case spv::OpTypeFunction: return range_t(2, maxCount);
+ case spv::OpTypePointer: return range_t(3, 4);
+ default: return range_t(0, 0);
+ }
+ }
+
+ spirvbin_t::range_t spirvbin_t::constRange(spv::Op opCode) const
+ {
+ static const int maxCount = 1<<30;
+
+ switch (opCode) {
+ case spv::OpTypeArray: // fall through...
+ case spv::OpTypeRuntimeArray: return range_t(3, 4);
+ case spv::OpConstantComposite: return range_t(3, maxCount);
+ default: return range_t(0, 0);
+ }
+ }
+
+ // Return the size of a type in 32-bit words. This currently only
+ // handles ints and floats, and is only invoked by queries which must be
+ // integer types. If ever needed, it can be generalized.
+ unsigned spirvbin_t::typeSizeInWords(spv::Id id) const
+ {
+ const unsigned typeStart = idPos(id);
+ const spv::Op opCode = asOpCode(typeStart);
+
+ if (errorLatch)
+ return 0;
+
+ switch (opCode) {
+ case spv::OpTypeInt: // fall through...
+ case spv::OpTypeFloat: return (spv[typeStart+2]+31)/32;
+ default:
+ return 0;
+ }
+ }
+
+ // Looks up the type of a given const or variable ID, and
+ // returns its size in 32-bit words.
+ unsigned spirvbin_t::idTypeSizeInWords(spv::Id id) const
+ {
+ const auto tid_it = idTypeSizeMap.find(id);
+ if (tid_it == idTypeSizeMap.end()) {
+ error("type size for ID not found");
+ return 0;
+ }
+
+ return tid_it->second;
+ }
+
+ // Is this an opcode we should remove when using --strip?
+ bool spirvbin_t::isStripOp(spv::Op opCode) const
+ {
+ switch (opCode) {
+ case spv::OpSource:
+ case spv::OpSourceExtension:
+ case spv::OpName:
+ case spv::OpMemberName:
+ case spv::OpLine: return true;
+ default: return false;
+ }
+ }
+
+ // Return true if this opcode is flow control
+ bool spirvbin_t::isFlowCtrl(spv::Op opCode) const
+ {
+ switch (opCode) {
+ case spv::OpBranchConditional:
+ case spv::OpBranch:
+ case spv::OpSwitch:
+ case spv::OpLoopMerge:
+ case spv::OpSelectionMerge:
+ case spv::OpLabel:
+ case spv::OpFunction:
+ case spv::OpFunctionEnd: return true;
+ default: return false;
+ }
+ }
+
+ // Return true if this opcode defines a type
+ bool spirvbin_t::isTypeOp(spv::Op opCode) const
+ {
+ switch (opCode) {
+ case spv::OpTypeVoid:
+ case spv::OpTypeBool:
+ case spv::OpTypeInt:
+ case spv::OpTypeFloat:
+ case spv::OpTypeVector:
+ case spv::OpTypeMatrix:
+ case spv::OpTypeImage:
+ case spv::OpTypeSampler:
+ case spv::OpTypeArray:
+ case spv::OpTypeRuntimeArray:
+ case spv::OpTypeStruct:
+ case spv::OpTypeOpaque:
+ case spv::OpTypePointer:
+ case spv::OpTypeFunction:
+ case spv::OpTypeEvent:
+ case spv::OpTypeDeviceEvent:
+ case spv::OpTypeReserveId:
+ case spv::OpTypeQueue:
+ case spv::OpTypeSampledImage:
+ case spv::OpTypePipe: return true;
+ default: return false;
+ }
+ }
+
+ // Return true if this opcode defines a constant
+ bool spirvbin_t::isConstOp(spv::Op opCode) const
+ {
+ switch (opCode) {
+ case spv::OpConstantSampler:
+ error("unimplemented constant type");
+ return true;
+
+ case spv::OpConstantNull:
+ case spv::OpConstantTrue:
+ case spv::OpConstantFalse:
+ case spv::OpConstantComposite:
+ case spv::OpConstant:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ const auto inst_fn_nop = [](spv::Op, unsigned) { return false; };
+ const auto op_fn_nop = [](spv::Id&) { };
+
+ // g++ doesn't like these defined in the class proper in an anonymous namespace.
+ // Dunno why. Also MSVC doesn't like the constexpr keyword. Also dunno why.
+ // Defining them externally seems to please both compilers, so, here they are.
+ const spv::Id spirvbin_t::unmapped = spv::Id(-10000);
+ const spv::Id spirvbin_t::unused = spv::Id(-10001);
+ const int spirvbin_t::header_size = 5;
+
+ spv::Id spirvbin_t::nextUnusedId(spv::Id id)
+ {
+ while (isNewIdMapped(id)) // search for an unused ID
+ ++id;
+
+ return id;
+ }
+
+ spv::Id spirvbin_t::localId(spv::Id id, spv::Id newId)
+ {
+ //assert(id != spv::NoResult && newId != spv::NoResult);
+
+ if (id > bound()) {
+ error(std::string("ID out of range: ") + std::to_string(id));
+ return spirvbin_t::unused;
+ }
+
+ if (id >= idMapL.size())
+ idMapL.resize(id+1, unused);
+
+ if (newId != unmapped && newId != unused) {
+ if (isOldIdUnused(id)) {
+ error(std::string("ID unused in module: ") + std::to_string(id));
+ return spirvbin_t::unused;
+ }
+
+ if (!isOldIdUnmapped(id)) {
+ error(std::string("ID already mapped: ") + std::to_string(id) + " -> "
+ + std::to_string(localId(id)));
+
+ return spirvbin_t::unused;
+ }
+
+ if (isNewIdMapped(newId)) {
+ error(std::string("ID already used in module: ") + std::to_string(newId));
+ return spirvbin_t::unused;
+ }
+
+ msg(4, 4, std::string("map: ") + std::to_string(id) + " -> " + std::to_string(newId));
+ setMapped(newId);
+ largestNewId = std::max(largestNewId, newId);
+ }
+
+ return idMapL[id] = newId;
+ }
+
+ // Parse a literal string from the SPIR binary and return it as an std::string
+ // Due to C++11 RValue references, this doesn't copy the result string.
+ std::string spirvbin_t::literalString(unsigned word) const
+ {
+ std::string literal;
+
+ literal.reserve(16);
+
+ const char* bytes = reinterpret_cast<const char*>(spv.data() + word);
+
+ while (bytes && *bytes)
+ literal += *bytes++;
+
+ return literal;
+ }
+
+ void spirvbin_t::applyMap()
+ {
+ msg(3, 2, std::string("Applying map: "));
+
+ // Map local IDs through the ID map
+ process(inst_fn_nop, // ignore instructions
+ [this](spv::Id& id) {
+ id = localId(id);
+
+ if (errorLatch)
+ return;
+
+ assert(id != unused && id != unmapped);
+ }
+ );
+ }
+
+ // Find free IDs for anything we haven't mapped
+ void spirvbin_t::mapRemainder()
+ {
+ msg(3, 2, std::string("Remapping remainder: "));
+
+ spv::Id unusedId = 1; // can't use 0: that's NoResult
+ spirword_t maxBound = 0;
+
+ for (spv::Id id = 0; id < idMapL.size(); ++id) {
+ if (isOldIdUnused(id))
+ continue;
+
+ // Find a new mapping for any used but unmapped IDs
+ if (isOldIdUnmapped(id)) {
+ localId(id, unusedId = nextUnusedId(unusedId));
+ if (errorLatch)
+ return;
+ }
+
+ if (isOldIdUnmapped(id)) {
+ error(std::string("old ID not mapped: ") + std::to_string(id));
+ return;
+ }
+
+ // Track max bound
+ maxBound = std::max(maxBound, localId(id) + 1);
+
+ if (errorLatch)
+ return;
+ }
+
+ bound(maxBound); // reset header ID bound to as big as it now needs to be
+ }
+
+ // Mark debug instructions for stripping
+ void spirvbin_t::stripDebug()
+ {
+ // Strip instructions in the stripOp set: debug info.
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ // remember opcodes we want to strip later
+ if (isStripOp(opCode))
+ stripInst(start);
+ return true;
+ },
+ op_fn_nop);
+ }
+
+ // Mark instructions that refer to now-removed IDs for stripping
+ void spirvbin_t::stripDeadRefs()
+ {
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ // strip opcodes pointing to removed data
+ switch (opCode) {
+ case spv::OpName:
+ case spv::OpMemberName:
+ case spv::OpDecorate:
+ case spv::OpMemberDecorate:
+ if (idPosR.find(asId(start+1)) == idPosR.end())
+ stripInst(start);
+ break;
+ default:
+ break; // leave it alone
+ }
+
+ return true;
+ },
+ op_fn_nop);
+
+ strip();
+ }
+
+ // Update local maps of ID, type, etc positions
+ void spirvbin_t::buildLocalMaps()
+ {
+ msg(2, 2, std::string("build local maps: "));
+
+ mapped.clear();
+ idMapL.clear();
+// preserve nameMap, so we don't clear that.
+ fnPos.clear();
+ fnCalls.clear();
+ typeConstPos.clear();
+ idPosR.clear();
+ entryPoint = spv::NoResult;
+ largestNewId = 0;
+
+ idMapL.resize(bound(), unused);
+
+ int fnStart = 0;
+ spv::Id fnRes = spv::NoResult;
+
+ // build local Id and name maps
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ unsigned word = start+1;
+ spv::Id typeId = spv::NoResult;
+
+ if (spv::InstructionDesc[opCode].hasType())
+ typeId = asId(word++);
+
+ // If there's a result ID, remember the size of its type
+ if (spv::InstructionDesc[opCode].hasResult()) {
+ const spv::Id resultId = asId(word++);
+ idPosR[resultId] = start;
+
+ if (typeId != spv::NoResult) {
+ const unsigned idTypeSize = typeSizeInWords(typeId);
+
+ if (errorLatch)
+ return false;
+
+ if (idTypeSize != 0)
+ idTypeSizeMap[resultId] = idTypeSize;
+ }
+ }
+
+ if (opCode == spv::Op::OpName) {
+ const spv::Id target = asId(start+1);
+ const std::string name = literalString(start+2);
+ nameMap[name] = target;
+
+ } else if (opCode == spv::Op::OpFunctionCall) {
+ ++fnCalls[asId(start + 3)];
+ } else if (opCode == spv::Op::OpEntryPoint) {
+ entryPoint = asId(start + 2);
+ } else if (opCode == spv::Op::OpFunction) {
+ if (fnStart != 0) {
+ error("nested function found");
+ return false;
+ }
+
+ fnStart = start;
+ fnRes = asId(start + 2);
+ } else if (opCode == spv::Op::OpFunctionEnd) {
+ assert(fnRes != spv::NoResult);
+ if (fnStart == 0) {
+ error("function end without function start");
+ return false;
+ }
+
+ fnPos[fnRes] = range_t(fnStart, start + asWordCount(start));
+ fnStart = 0;
+ } else if (isConstOp(opCode)) {
+ if (errorLatch)
+ return false;
+
+ assert(asId(start + 2) != spv::NoResult);
+ typeConstPos.insert(start);
+ } else if (isTypeOp(opCode)) {
+ assert(asId(start + 1) != spv::NoResult);
+ typeConstPos.insert(start);
+ }
+
+ return false;
+ },
+
+ [this](spv::Id& id) { localId(id, unmapped); }
+ );
+ }
+
+ // Validate the SPIR header
+ void spirvbin_t::validate() const
+ {
+ msg(2, 2, std::string("validating: "));
+
+ if (spv.size() < header_size) {
+ error("file too short: ");
+ return;
+ }
+
+ if (magic() != spv::MagicNumber) {
+ error("bad magic number");
+ return;
+ }
+
+ // field 1 = version
+ // field 2 = generator magic
+ // field 3 = result <id> bound
+
+ if (schemaNum() != 0) {
+ error("bad schema, must be 0");
+ return;
+ }
+ }
+
+ int spirvbin_t::processInstruction(unsigned word, instfn_t instFn, idfn_t idFn)
+ {
+ const auto instructionStart = word;
+ const unsigned wordCount = asWordCount(instructionStart);
+ const int nextInst = word++ + wordCount;
+ spv::Op opCode = asOpCode(instructionStart);
+
+ if (nextInst > int(spv.size())) {
+ error("spir instruction terminated too early");
+ return -1;
+ }
+
+ // Base for computing number of operands; will be updated as more is learned
+ unsigned numOperands = wordCount - 1;
+
+ if (instFn(opCode, instructionStart))
+ return nextInst;
+
+ // Read type and result ID from instruction desc table
+ if (spv::InstructionDesc[opCode].hasType()) {
+ idFn(asId(word++));
+ --numOperands;
+ }
+
+ if (spv::InstructionDesc[opCode].hasResult()) {
+ idFn(asId(word++));
+ --numOperands;
+ }
+
+ // Extended instructions: currently, assume everything is an ID.
+ // TODO: add whatever data we need for exceptions to that
+ if (opCode == spv::OpExtInst) {
+ word += 2; // instruction set, and instruction from set
+ numOperands -= 2;
+
+ for (unsigned op=0; op < numOperands; ++op)
+ idFn(asId(word++)); // ID
+
+ return nextInst;
+ }
+
+ // Circular buffer so we can look back at previous unmapped values during the mapping pass.
+ static const unsigned idBufferSize = 4;
+ spv::Id idBuffer[idBufferSize];
+ unsigned idBufferPos = 0;
+
+ // Store IDs from instruction in our map
+ for (int op = 0; numOperands > 0; ++op, --numOperands) {
+ // SpecConstantOp is special: it includes the operands of another opcode which is
+ // given as a literal in the 3rd word. We will switch over to pretending that the
+ // opcode being processed is the literal opcode value of the SpecConstantOp. See the
+ // SPIRV spec for details. This way we will handle IDs and literals as appropriate for
+ // the embedded op.
+ if (opCode == spv::OpSpecConstantOp) {
+ if (op == 0) {
+ opCode = asOpCode(word++); // this is the opcode embedded in the SpecConstantOp.
+ --numOperands;
+ }
+ }
+
+ switch (spv::InstructionDesc[opCode].operands.getClass(op)) {
+ case spv::OperandId:
+ case spv::OperandScope:
+ case spv::OperandMemorySemantics:
+ idBuffer[idBufferPos] = asId(word);
+ idBufferPos = (idBufferPos + 1) % idBufferSize;
+ idFn(asId(word++));
+ break;
+
+ case spv::OperandVariableIds:
+ for (unsigned i = 0; i < numOperands; ++i)
+ idFn(asId(word++));
+ return nextInst;
+
+ case spv::OperandVariableLiterals:
+ // for clarity
+ // if (opCode == spv::OpDecorate && asDecoration(word - 1) == spv::DecorationBuiltIn) {
+ // ++word;
+ // --numOperands;
+ // }
+ // word += numOperands;
+ return nextInst;
+
+ case spv::OperandVariableLiteralId: {
+ if (opCode == OpSwitch) {
+ // word-2 is the position of the selector ID. OpSwitch Literals match its type.
+ // In case the IDs are currently being remapped, we get the word[-2] ID from
+ // the circular idBuffer.
+ const unsigned literalSizePos = (idBufferPos+idBufferSize-2) % idBufferSize;
+ const unsigned literalSize = idTypeSizeInWords(idBuffer[literalSizePos]);
+ const unsigned numLiteralIdPairs = (nextInst-word) / (1+literalSize);
+
+ if (errorLatch)
+ return -1;
+
+ for (unsigned arg=0; arg<numLiteralIdPairs; ++arg) {
+ word += literalSize; // literal
+ idFn(asId(word++)); // label
+ }
+ } else {
+ assert(0); // currentely, only OpSwitch uses OperandVariableLiteralId
+ }
+
+ return nextInst;
+ }
+
+ case spv::OperandLiteralString: {
+ const int stringWordCount = literalStringWords(literalString(word));
+ word += stringWordCount;
+ numOperands -= (stringWordCount-1); // -1 because for() header post-decrements
+ break;
+ }
+
+ // Execution mode might have extra literal operands. Skip them.
+ case spv::OperandExecutionMode:
+ return nextInst;
+
+ // Single word operands we simply ignore, as they hold no IDs
+ case spv::OperandLiteralNumber:
+ case spv::OperandSource:
+ case spv::OperandExecutionModel:
+ case spv::OperandAddressing:
+ case spv::OperandMemory:
+ case spv::OperandStorage:
+ case spv::OperandDimensionality:
+ case spv::OperandSamplerAddressingMode:
+ case spv::OperandSamplerFilterMode:
+ case spv::OperandSamplerImageFormat:
+ case spv::OperandImageChannelOrder:
+ case spv::OperandImageChannelDataType:
+ case spv::OperandImageOperands:
+ case spv::OperandFPFastMath:
+ case spv::OperandFPRoundingMode:
+ case spv::OperandLinkageType:
+ case spv::OperandAccessQualifier:
+ case spv::OperandFuncParamAttr:
+ case spv::OperandDecoration:
+ case spv::OperandBuiltIn:
+ case spv::OperandSelect:
+ case spv::OperandLoop:
+ case spv::OperandFunction:
+ case spv::OperandMemoryAccess:
+ case spv::OperandGroupOperation:
+ case spv::OperandKernelEnqueueFlags:
+ case spv::OperandKernelProfilingInfo:
+ case spv::OperandCapability:
+ ++word;
+ break;
+
+ default:
+ assert(0 && "Unhandled Operand Class");
+ break;
+ }
+ }
+
+ return nextInst;
+ }
+
+ // Make a pass over all the instructions and process them given appropriate functions
+ spirvbin_t& spirvbin_t::process(instfn_t instFn, idfn_t idFn, unsigned begin, unsigned end)
+ {
+ // For efficiency, reserve name map space. It can grow if needed.
+ nameMap.reserve(32);
+
+ // If begin or end == 0, use defaults
+ begin = (begin == 0 ? header_size : begin);
+ end = (end == 0 ? unsigned(spv.size()) : end);
+
+ // basic parsing and InstructionDesc table borrowed from SpvDisassemble.cpp...
+ unsigned nextInst = unsigned(spv.size());
+
+ for (unsigned word = begin; word < end; word = nextInst) {
+ nextInst = processInstruction(word, instFn, idFn);
+
+ if (errorLatch)
+ return *this;
+ }
+
+ return *this;
+ }
+
+ // Apply global name mapping to a single module
+ void spirvbin_t::mapNames()
+ {
+ static const std::uint32_t softTypeIdLimit = 3011; // small prime. TODO: get from options
+ static const std::uint32_t firstMappedID = 3019; // offset into ID space
+
+ for (const auto& name : nameMap) {
+ std::uint32_t hashval = 1911;
+ for (const char c : name.first)
+ hashval = hashval * 1009 + c;
+
+ if (isOldIdUnmapped(name.second)) {
+ localId(name.second, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
+ if (errorLatch)
+ return;
+ }
+ }
+ }
+
+ // Map fn contents to IDs of similar functions in other modules
+ void spirvbin_t::mapFnBodies()
+ {
+ static const std::uint32_t softTypeIdLimit = 19071; // small prime. TODO: get from options
+ static const std::uint32_t firstMappedID = 6203; // offset into ID space
+
+ // Initial approach: go through some high priority opcodes first and assign them
+ // hash values.
+
+ spv::Id fnId = spv::NoResult;
+ std::vector<unsigned> instPos;
+ instPos.reserve(unsigned(spv.size()) / 16); // initial estimate; can grow if needed.
+
+ // Build local table of instruction start positions
+ process(
+ [&](spv::Op, unsigned start) { instPos.push_back(start); return true; },
+ op_fn_nop);
+
+ if (errorLatch)
+ return;
+
+ // Window size for context-sensitive canonicalization values
+ // Empirical best size from a single data set. TODO: Would be a good tunable.
+ // We essentially perform a little convolution around each instruction,
+ // to capture the flavor of nearby code, to hopefully match to similar
+ // code in other modules.
+ static const unsigned windowSize = 2;
+
+ for (unsigned entry = 0; entry < unsigned(instPos.size()); ++entry) {
+ const unsigned start = instPos[entry];
+ const spv::Op opCode = asOpCode(start);
+
+ if (opCode == spv::OpFunction)
+ fnId = asId(start + 2);
+
+ if (opCode == spv::OpFunctionEnd)
+ fnId = spv::NoResult;
+
+ if (fnId != spv::NoResult) { // if inside a function
+ if (spv::InstructionDesc[opCode].hasResult()) {
+ const unsigned word = start + (spv::InstructionDesc[opCode].hasType() ? 2 : 1);
+ const spv::Id resId = asId(word);
+ std::uint32_t hashval = fnId * 17; // small prime
+
+ for (unsigned i = entry-1; i >= entry-windowSize; --i) {
+ if (asOpCode(instPos[i]) == spv::OpFunction)
+ break;
+ hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime
+ }
+
+ for (unsigned i = entry; i <= entry + windowSize; ++i) {
+ if (asOpCode(instPos[i]) == spv::OpFunctionEnd)
+ break;
+ hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime
+ }
+
+ if (isOldIdUnmapped(resId)) {
+ localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
+ if (errorLatch)
+ return;
+ }
+
+ }
+ }
+ }
+
+ spv::Op thisOpCode(spv::OpNop);
+ std::unordered_map<int, int> opCounter;
+ int idCounter(0);
+ fnId = spv::NoResult;
+
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ switch (opCode) {
+ case spv::OpFunction:
+ // Reset counters at each function
+ idCounter = 0;
+ opCounter.clear();
+ fnId = asId(start + 2);
+ break;
+
+ case spv::OpImageSampleImplicitLod:
+ case spv::OpImageSampleExplicitLod:
+ case spv::OpImageSampleDrefImplicitLod:
+ case spv::OpImageSampleDrefExplicitLod:
+ case spv::OpImageSampleProjImplicitLod:
+ case spv::OpImageSampleProjExplicitLod:
+ case spv::OpImageSampleProjDrefImplicitLod:
+ case spv::OpImageSampleProjDrefExplicitLod:
+ case spv::OpDot:
+ case spv::OpCompositeExtract:
+ case spv::OpCompositeInsert:
+ case spv::OpVectorShuffle:
+ case spv::OpLabel:
+ case spv::OpVariable:
+
+ case spv::OpAccessChain:
+ case spv::OpLoad:
+ case spv::OpStore:
+ case spv::OpCompositeConstruct:
+ case spv::OpFunctionCall:
+ ++opCounter[opCode];
+ idCounter = 0;
+ thisOpCode = opCode;
+ break;
+ default:
+ thisOpCode = spv::OpNop;
+ }
+
+ return false;
+ },
+
+ [&](spv::Id& id) {
+ if (thisOpCode != spv::OpNop) {
+ ++idCounter;
+ const std::uint32_t hashval = opCounter[thisOpCode] * thisOpCode * 50047 + idCounter + fnId * 117;
+
+ if (isOldIdUnmapped(id))
+ localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
+ }
+ });
+ }
+
+ // EXPERIMENTAL: forward IO and uniform load/stores into operands
+ // This produces invalid Schema-0 SPIRV
+ void spirvbin_t::forwardLoadStores()
+ {
+ idset_t fnLocalVars; // set of function local vars
+ idmap_t idMap; // Map of load result IDs to what they load
+
+ // EXPERIMENTAL: Forward input and access chain loads into consumptions
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ // Add inputs and uniforms to the map
+ if ((opCode == spv::OpVariable && asWordCount(start) == 4) &&
+ (spv[start+3] == spv::StorageClassUniform ||
+ spv[start+3] == spv::StorageClassUniformConstant ||
+ spv[start+3] == spv::StorageClassInput))
+ fnLocalVars.insert(asId(start+2));
+
+ if (opCode == spv::OpAccessChain && fnLocalVars.count(asId(start+3)) > 0)
+ fnLocalVars.insert(asId(start+2));
+
+ if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) {
+ idMap[asId(start+2)] = asId(start+3);
+ stripInst(start);
+ }
+
+ return false;
+ },
+
+ [&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; }
+ );
+
+ if (errorLatch)
+ return;
+
+ // EXPERIMENTAL: Implicit output stores
+ fnLocalVars.clear();
+ idMap.clear();
+
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ // Add inputs and uniforms to the map
+ if ((opCode == spv::OpVariable && asWordCount(start) == 4) &&
+ (spv[start+3] == spv::StorageClassOutput))
+ fnLocalVars.insert(asId(start+2));
+
+ if (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) {
+ idMap[asId(start+2)] = asId(start+1);
+ stripInst(start);
+ }
+
+ return false;
+ },
+ op_fn_nop);
+
+ if (errorLatch)
+ return;
+
+ process(
+ inst_fn_nop,
+ [&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; }
+ );
+
+ if (errorLatch)
+ return;
+
+ strip(); // strip out data we decided to eliminate
+ }
+
+ // optimize loads and stores
+ void spirvbin_t::optLoadStore()
+ {
+ idset_t fnLocalVars; // candidates for removal (only locals)
+ idmap_t idMap; // Map of load result IDs to what they load
+ blockmap_t blockMap; // Map of IDs to blocks they first appear in
+ int blockNum = 0; // block count, to avoid crossing flow control
+
+ // Find all the function local pointers stored at most once, and not via access chains
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ const int wordCount = asWordCount(start);
+
+ // Count blocks, so we can avoid crossing flow control
+ if (isFlowCtrl(opCode))
+ ++blockNum;
+
+ // Add local variables to the map
+ if ((opCode == spv::OpVariable && spv[start+3] == spv::StorageClassFunction && asWordCount(start) == 4)) {
+ fnLocalVars.insert(asId(start+2));
+ return true;
+ }
+
+ // Ignore process vars referenced via access chain
+ if ((opCode == spv::OpAccessChain || opCode == spv::OpInBoundsAccessChain) && fnLocalVars.count(asId(start+3)) > 0) {
+ fnLocalVars.erase(asId(start+3));
+ idMap.erase(asId(start+3));
+ return true;
+ }
+
+ if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) {
+ const spv::Id varId = asId(start+3);
+
+ // Avoid loads before stores
+ if (idMap.find(varId) == idMap.end()) {
+ fnLocalVars.erase(varId);
+ idMap.erase(varId);
+ }
+
+ // don't do for volatile references
+ if (wordCount > 4 && (spv[start+4] & spv::MemoryAccessVolatileMask)) {
+ fnLocalVars.erase(varId);
+ idMap.erase(varId);
+ }
+
+ // Handle flow control
+ if (blockMap.find(varId) == blockMap.end()) {
+ blockMap[varId] = blockNum; // track block we found it in.
+ } else if (blockMap[varId] != blockNum) {
+ fnLocalVars.erase(varId); // Ignore if crosses flow control
+ idMap.erase(varId);
+ }
+
+ return true;
+ }
+
+ if (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) {
+ const spv::Id varId = asId(start+1);
+
+ if (idMap.find(varId) == idMap.end()) {
+ idMap[varId] = asId(start+2);
+ } else {
+ // Remove if it has more than one store to the same pointer
+ fnLocalVars.erase(varId);
+ idMap.erase(varId);
+ }
+
+ // don't do for volatile references
+ if (wordCount > 3 && (spv[start+3] & spv::MemoryAccessVolatileMask)) {
+ fnLocalVars.erase(asId(start+3));
+ idMap.erase(asId(start+3));
+ }
+
+ // Handle flow control
+ if (blockMap.find(varId) == blockMap.end()) {
+ blockMap[varId] = blockNum; // track block we found it in.
+ } else if (blockMap[varId] != blockNum) {
+ fnLocalVars.erase(varId); // Ignore if crosses flow control
+ idMap.erase(varId);
+ }
+
+ return true;
+ }
+
+ return false;
+ },
+
+ // If local var id used anywhere else, don't eliminate
+ [&](spv::Id& id) {
+ if (fnLocalVars.count(id) > 0) {
+ fnLocalVars.erase(id);
+ idMap.erase(id);
+ }
+ }
+ );
+
+ if (errorLatch)
+ return;
+
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0)
+ idMap[asId(start+2)] = idMap[asId(start+3)];
+ return false;
+ },
+ op_fn_nop);
+
+ if (errorLatch)
+ return;
+
+ // Chase replacements to their origins, in case there is a chain such as:
+ // 2 = store 1
+ // 3 = load 2
+ // 4 = store 3
+ // 5 = load 4
+ // We want to replace uses of 5 with 1.
+ for (const auto& idPair : idMap) {
+ spv::Id id = idPair.first;
+ while (idMap.find(id) != idMap.end()) // Chase to end of chain
+ id = idMap[id];
+
+ idMap[idPair.first] = id; // replace with final result
+ }
+
+ // Remove the load/store/variables for the ones we've discovered
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ if ((opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) ||
+ (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) ||
+ (opCode == spv::OpVariable && fnLocalVars.count(asId(start+2)) > 0)) {
+
+ stripInst(start);
+ return true;
+ }
+
+ return false;
+ },
+
+ [&](spv::Id& id) {
+ if (idMap.find(id) != idMap.end()) id = idMap[id];
+ }
+ );
+
+ if (errorLatch)
+ return;
+
+ strip(); // strip out data we decided to eliminate
+ }
+
+ // remove bodies of uncalled functions
+ void spirvbin_t::dceFuncs()
+ {
+ msg(3, 2, std::string("Removing Dead Functions: "));
+
+ // TODO: There are more efficient ways to do this.
+ bool changed = true;
+
+ while (changed) {
+ changed = false;
+
+ for (auto fn = fnPos.begin(); fn != fnPos.end(); ) {
+ if (fn->first == entryPoint) { // don't DCE away the entry point!
+ ++fn;
+ continue;
+ }
+
+ const auto call_it = fnCalls.find(fn->first);
+
+ if (call_it == fnCalls.end() || call_it->second == 0) {
+ changed = true;
+ stripRange.push_back(fn->second);
+
+ // decrease counts of called functions
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ if (opCode == spv::Op::OpFunctionCall) {
+ const auto call_it = fnCalls.find(asId(start + 3));
+ if (call_it != fnCalls.end()) {
+ if (--call_it->second <= 0)
+ fnCalls.erase(call_it);
+ }
+ }
+
+ return true;
+ },
+ op_fn_nop,
+ fn->second.first,
+ fn->second.second);
+
+ if (errorLatch)
+ return;
+
+ fn = fnPos.erase(fn);
+ } else ++fn;
+ }
+ }
+ }
+
+ // remove unused function variables + decorations
+ void spirvbin_t::dceVars()
+ {
+ msg(3, 2, std::string("DCE Vars: "));
+
+ std::unordered_map<spv::Id, int> varUseCount;
+
+ // Count function variable use
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ if (opCode == spv::OpVariable) {
+ ++varUseCount[asId(start+2)];
+ return true;
+ } else if (opCode == spv::OpEntryPoint) {
+ const int wordCount = asWordCount(start);
+ for (int i = 4; i < wordCount; i++) {
+ ++varUseCount[asId(start+i)];
+ }
+ return true;
+ } else
+ return false;
+ },
+
+ [&](spv::Id& id) { if (varUseCount[id]) ++varUseCount[id]; }
+ );
+
+ if (errorLatch)
+ return;
+
+ // Remove single-use function variables + associated decorations and names
+ process(
+ [&](spv::Op opCode, unsigned start) {
+ spv::Id id = spv::NoResult;
+ if (opCode == spv::OpVariable)
+ id = asId(start+2);
+ if (opCode == spv::OpDecorate || opCode == spv::OpName)
+ id = asId(start+1);
+
+ if (id != spv::NoResult && varUseCount[id] == 1)
+ stripInst(start);
+
+ return true;
+ },
+ op_fn_nop);
+ }
+
+ // remove unused types
+ void spirvbin_t::dceTypes()
+ {
+ std::vector<bool> isType(bound(), false);
+
+ // for speed, make O(1) way to get to type query (map is log(n))
+ for (const auto typeStart : typeConstPos)
+ isType[asTypeConstId(typeStart)] = true;
+
+ std::unordered_map<spv::Id, int> typeUseCount;
+
+ // This is not the most efficient algorithm, but this is an offline tool, and
+ // it's easy to write this way. Can be improved opportunistically if needed.
+ bool changed = true;
+ while (changed) {
+ changed = false;
+ strip();
+ typeUseCount.clear();
+
+ // Count total type usage
+ process(inst_fn_nop,
+ [&](spv::Id& id) { if (isType[id]) ++typeUseCount[id]; }
+ );
+
+ if (errorLatch)
+ return;
+
+ // Remove single reference types
+ for (const auto typeStart : typeConstPos) {
+ const spv::Id typeId = asTypeConstId(typeStart);
+ if (typeUseCount[typeId] == 1) {
+ changed = true;
+ --typeUseCount[typeId];
+ stripInst(typeStart);
+ }
+ }
+
+ if (errorLatch)
+ return;
+ }
+ }
+
+#ifdef NOTDEF
+ bool spirvbin_t::matchType(const spirvbin_t::globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const
+ {
+ // Find the local type id "lt" and global type id "gt"
+ const auto lt_it = typeConstPosR.find(lt);
+ if (lt_it == typeConstPosR.end())
+ return false;
+
+ const auto typeStart = lt_it->second;
+
+ // Search for entry in global table
+ const auto gtype = globalTypes.find(gt);
+ if (gtype == globalTypes.end())
+ return false;
+
+ const auto& gdata = gtype->second;
+
+ // local wordcount and opcode
+ const int wordCount = asWordCount(typeStart);
+ const spv::Op opCode = asOpCode(typeStart);
+
+ // no type match if opcodes don't match, or operand count doesn't match
+ if (opCode != opOpCode(gdata[0]) || wordCount != opWordCount(gdata[0]))
+ return false;
+
+ const unsigned numOperands = wordCount - 2; // all types have a result
+
+ const auto cmpIdRange = [&](range_t range) {
+ for (int x=range.first; x<std::min(range.second, wordCount); ++x)
+ if (!matchType(globalTypes, asId(typeStart+x), gdata[x]))
+ return false;
+ return true;
+ };
+
+ const auto cmpConst = [&]() { return cmpIdRange(constRange(opCode)); };
+ const auto cmpSubType = [&]() { return cmpIdRange(typeRange(opCode)); };
+
+ // Compare literals in range [start,end)
+ const auto cmpLiteral = [&]() {
+ const auto range = literalRange(opCode);
+ return std::equal(spir.begin() + typeStart + range.first,
+ spir.begin() + typeStart + std::min(range.second, wordCount),
+ gdata.begin() + range.first);
+ };
+
+ assert(isTypeOp(opCode) || isConstOp(opCode));
+
+ switch (opCode) {
+ case spv::OpTypeOpaque: // TODO: disable until we compare the literal strings.
+ case spv::OpTypeQueue: return false;
+ case spv::OpTypeEvent: // fall through...
+ case spv::OpTypeDeviceEvent: // ...
+ case spv::OpTypeReserveId: return false;
+ // for samplers, we don't handle the optional parameters yet
+ case spv::OpTypeSampler: return cmpLiteral() && cmpConst() && cmpSubType() && wordCount == 8;
+ default: return cmpLiteral() && cmpConst() && cmpSubType();
+ }
+ }
+
+ // Look for an equivalent type in the globalTypes map
+ spv::Id spirvbin_t::findType(const spirvbin_t::globaltypes_t& globalTypes, spv::Id lt) const
+ {
+ // Try a recursive type match on each in turn, and return a match if we find one
+ for (const auto& gt : globalTypes)
+ if (matchType(globalTypes, lt, gt.first))
+ return gt.first;
+
+ return spv::NoType;
+ }
+#endif // NOTDEF
+
+ // Return start position in SPV of given Id. error if not found.
+ unsigned spirvbin_t::idPos(spv::Id id) const
+ {
+ const auto tid_it = idPosR.find(id);
+ if (tid_it == idPosR.end()) {
+ error("ID not found");
+ return 0;
+ }
+
+ return tid_it->second;
+ }
+
+ // Hash types to canonical values. This can return ID collisions (it's a bit
+ // inevitable): it's up to the caller to handle that gracefully.
+ std::uint32_t spirvbin_t::hashType(unsigned typeStart) const
+ {
+ const unsigned wordCount = asWordCount(typeStart);
+ const spv::Op opCode = asOpCode(typeStart);
+
+ switch (opCode) {
+ case spv::OpTypeVoid: return 0;
+ case spv::OpTypeBool: return 1;
+ case spv::OpTypeInt: return 3 + (spv[typeStart+3]);
+ case spv::OpTypeFloat: return 5;
+ case spv::OpTypeVector:
+ return 6 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
+ case spv::OpTypeMatrix:
+ return 30 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
+ case spv::OpTypeImage:
+ return 120 + hashType(idPos(spv[typeStart+2])) +
+ spv[typeStart+3] + // dimensionality
+ spv[typeStart+4] * 8 * 16 + // depth
+ spv[typeStart+5] * 4 * 16 + // arrayed
+ spv[typeStart+6] * 2 * 16 + // multisampled
+ spv[typeStart+7] * 1 * 16; // format
+ case spv::OpTypeSampler:
+ return 500;
+ case spv::OpTypeSampledImage:
+ return 502;
+ case spv::OpTypeArray:
+ return 501 + hashType(idPos(spv[typeStart+2])) * spv[typeStart+3];
+ case spv::OpTypeRuntimeArray:
+ return 5000 + hashType(idPos(spv[typeStart+2]));
+ case spv::OpTypeStruct:
+ {
+ std::uint32_t hash = 10000;
+ for (unsigned w=2; w < wordCount; ++w)
+ hash += w * hashType(idPos(spv[typeStart+w]));
+ return hash;
+ }
+
+ case spv::OpTypeOpaque: return 6000 + spv[typeStart+2];
+ case spv::OpTypePointer: return 100000 + hashType(idPos(spv[typeStart+3]));
+ case spv::OpTypeFunction:
+ {
+ std::uint32_t hash = 200000;
+ for (unsigned w=2; w < wordCount; ++w)
+ hash += w * hashType(idPos(spv[typeStart+w]));
+ return hash;
+ }
+
+ case spv::OpTypeEvent: return 300000;
+ case spv::OpTypeDeviceEvent: return 300001;
+ case spv::OpTypeReserveId: return 300002;
+ case spv::OpTypeQueue: return 300003;
+ case spv::OpTypePipe: return 300004;
+ case spv::OpConstantTrue: return 300007;
+ case spv::OpConstantFalse: return 300008;
+ case spv::OpConstantComposite:
+ {
+ std::uint32_t hash = 300011 + hashType(idPos(spv[typeStart+1]));
+ for (unsigned w=3; w < wordCount; ++w)
+ hash += w * hashType(idPos(spv[typeStart+w]));
+ return hash;
+ }
+ case spv::OpConstant:
+ {
+ std::uint32_t hash = 400011 + hashType(idPos(spv[typeStart+1]));
+ for (unsigned w=3; w < wordCount; ++w)
+ hash += w * spv[typeStart+w];
+ return hash;
+ }
+ case spv::OpConstantNull:
+ {
+ std::uint32_t hash = 500009 + hashType(idPos(spv[typeStart+1]));
+ return hash;
+ }
+ case spv::OpConstantSampler:
+ {
+ std::uint32_t hash = 600011 + hashType(idPos(spv[typeStart+1]));
+ for (unsigned w=3; w < wordCount; ++w)
+ hash += w * spv[typeStart+w];
+ return hash;
+ }
+
+ default:
+ error("unknown type opcode");
+ return 0;
+ }
+ }
+
+ void spirvbin_t::mapTypeConst()
+ {
+ globaltypes_t globalTypeMap;
+
+ msg(3, 2, std::string("Remapping Consts & Types: "));
+
+ static const std::uint32_t softTypeIdLimit = 3011; // small prime. TODO: get from options
+ static const std::uint32_t firstMappedID = 8; // offset into ID space
+
+ for (auto& typeStart : typeConstPos) {
+ const spv::Id resId = asTypeConstId(typeStart);
+ const std::uint32_t hashval = hashType(typeStart);
+
+ if (errorLatch)
+ return;
+
+ if (isOldIdUnmapped(resId)) {
+ localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
+ if (errorLatch)
+ return;
+ }
+ }
+ }
+
+ // Strip a single binary by removing ranges given in stripRange
+ void spirvbin_t::strip()
+ {
+ if (stripRange.empty()) // nothing to do
+ return;
+
+ // Sort strip ranges in order of traversal
+ std::sort(stripRange.begin(), stripRange.end());
+
+ // Allocate a new binary big enough to hold old binary
+ // We'll step this iterator through the strip ranges as we go through the binary
+ auto strip_it = stripRange.begin();
+
+ int strippedPos = 0;
+ for (unsigned word = 0; word < unsigned(spv.size()); ++word) {
+ while (strip_it != stripRange.end() && word >= strip_it->second)
+ ++strip_it;
+
+ if (strip_it == stripRange.end() || word < strip_it->first || word >= strip_it->second)
+ spv[strippedPos++] = spv[word];
+ }
+
+ spv.resize(strippedPos);
+ stripRange.clear();
+
+ buildLocalMaps();
+ }
+
+ // Strip a single binary by removing ranges given in stripRange
+ void spirvbin_t::remap(std::uint32_t opts)
+ {
+ options = opts;
+
+ // Set up opcode tables from SpvDoc
+ spv::Parameterize();
+
+ validate(); // validate header
+ buildLocalMaps(); // build ID maps
+
+ msg(3, 4, std::string("ID bound: ") + std::to_string(bound()));
+
+ if (options & STRIP) stripDebug();
+ if (errorLatch) return;
+
+ strip(); // strip out data we decided to eliminate
+ if (errorLatch) return;
+
+ if (options & OPT_LOADSTORE) optLoadStore();
+ if (errorLatch) return;
+
+ if (options & OPT_FWD_LS) forwardLoadStores();
+ if (errorLatch) return;
+
+ if (options & DCE_FUNCS) dceFuncs();
+ if (errorLatch) return;
+
+ if (options & DCE_VARS) dceVars();
+ if (errorLatch) return;
+
+ if (options & DCE_TYPES) dceTypes();
+ if (errorLatch) return;
+
+ strip(); // strip out data we decided to eliminate
+ if (errorLatch) return;
+
+ stripDeadRefs(); // remove references to things we DCEed
+ if (errorLatch) return;
+
+ // after the last strip, we must clean any debug info referring to now-deleted data
+
+ if (options & MAP_TYPES) mapTypeConst();
+ if (errorLatch) return;
+
+ if (options & MAP_NAMES) mapNames();
+ if (errorLatch) return;
+
+ if (options & MAP_FUNCS) mapFnBodies();
+ if (errorLatch) return;
+
+ if (options & MAP_ALL) {
+ mapRemainder(); // map any unmapped IDs
+ if (errorLatch) return;
+
+ applyMap(); // Now remap each shader to the new IDs we've come up with
+ if (errorLatch) return;
+ }
+ }
+
+ // remap from a memory image
+ void spirvbin_t::remap(std::vector<std::uint32_t>& in_spv, std::uint32_t opts)
+ {
+ spv.swap(in_spv);
+ remap(opts);
+ spv.swap(in_spv);
+ }
+
+} // namespace SPV
+
+#endif // defined (use_cpp11)
+
diff --git a/thirdparty/glslang/SPIRV/SPVRemapper.h b/thirdparty/glslang/SPIRV/SPVRemapper.h
new file mode 100644
index 0000000000..d6b9c346dd
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/SPVRemapper.h
@@ -0,0 +1,304 @@
+//
+// Copyright (C) 2015 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef SPIRVREMAPPER_H
+#define SPIRVREMAPPER_H
+
+#include <string>
+#include <vector>
+#include <cstdlib>
+#include <exception>
+
+namespace spv {
+
+// MSVC defines __cplusplus as an older value, even when it supports almost all of 11.
+// We handle that here by making our own symbol.
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700)
+# define use_cpp11 1
+#endif
+
+class spirvbin_base_t
+{
+public:
+ enum Options {
+ NONE = 0,
+ STRIP = (1<<0),
+ MAP_TYPES = (1<<1),
+ MAP_NAMES = (1<<2),
+ MAP_FUNCS = (1<<3),
+ DCE_FUNCS = (1<<4),
+ DCE_VARS = (1<<5),
+ DCE_TYPES = (1<<6),
+ OPT_LOADSTORE = (1<<7),
+ OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV
+ MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS),
+ DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES),
+ OPT_ALL = (OPT_LOADSTORE),
+
+ ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL),
+ DO_EVERYTHING = (STRIP | ALL_BUT_STRIP)
+ };
+};
+
+} // namespace SPV
+
+#if !defined (use_cpp11)
+#include <cstdio>
+#include <cstdint>
+
+namespace spv {
+class spirvbin_t : public spirvbin_base_t
+{
+public:
+ spirvbin_t(int /*verbose = 0*/) { }
+
+ void remap(std::vector<std::uint32_t>& /*spv*/, unsigned int /*opts = 0*/)
+ {
+ printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n");
+ exit(5);
+ }
+};
+
+} // namespace SPV
+
+#else // defined (use_cpp11)
+
+#include <functional>
+#include <cstdint>
+#include <unordered_map>
+#include <unordered_set>
+#include <map>
+#include <set>
+#include <cassert>
+
+#include "spirv.hpp"
+#include "spvIR.h"
+
+namespace spv {
+
+// class to hold SPIR-V binary data for remapping, DCE, and debug stripping
+class spirvbin_t : public spirvbin_base_t
+{
+public:
+ spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false)
+ { }
+
+ virtual ~spirvbin_t() { }
+
+ // remap on an existing binary in memory
+ void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING);
+
+ // Type for error/log handler functions
+ typedef std::function<void(const std::string&)> errorfn_t;
+ typedef std::function<void(const std::string&)> logfn_t;
+
+ // Register error/log handling functions (can be lambda fn / functor / etc)
+ static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; }
+ static void registerLogHandler(logfn_t handler) { logHandler = handler; }
+
+protected:
+ // This can be overridden to provide other message behavior if needed
+ virtual void msg(int minVerbosity, int indent, const std::string& txt) const;
+
+private:
+ // Local to global, or global to local ID map
+ typedef std::unordered_map<spv::Id, spv::Id> idmap_t;
+ typedef std::unordered_set<spv::Id> idset_t;
+ typedef std::unordered_map<spv::Id, int> blockmap_t;
+
+ void remap(std::uint32_t opts = DO_EVERYTHING);
+
+ // Map of names to IDs
+ typedef std::unordered_map<std::string, spv::Id> namemap_t;
+
+ typedef std::uint32_t spirword_t;
+
+ typedef std::pair<unsigned, unsigned> range_t;
+ typedef std::function<void(spv::Id&)> idfn_t;
+ typedef std::function<bool(spv::Op, unsigned start)> instfn_t;
+
+ // Special Values for ID map:
+ static const spv::Id unmapped; // unchanged from default value
+ static const spv::Id unused; // unused ID
+ static const int header_size; // SPIR header = 5 words
+
+ class id_iterator_t;
+
+ // For mapping type entries between different shaders
+ typedef std::vector<spirword_t> typeentry_t;
+ typedef std::map<spv::Id, typeentry_t> globaltypes_t;
+
+ // A set that preserves position order, and a reverse map
+ typedef std::set<int> posmap_t;
+ typedef std::unordered_map<spv::Id, int> posmap_rev_t;
+
+ // Maps and ID to the size of its base type, if known.
+ typedef std::unordered_map<spv::Id, unsigned> typesize_map_t;
+
+ // handle error
+ void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); }
+
+ bool isConstOp(spv::Op opCode) const;
+ bool isTypeOp(spv::Op opCode) const;
+ bool isStripOp(spv::Op opCode) const;
+ bool isFlowCtrl(spv::Op opCode) const;
+ range_t literalRange(spv::Op opCode) const;
+ range_t typeRange(spv::Op opCode) const;
+ range_t constRange(spv::Op opCode) const;
+ unsigned typeSizeInWords(spv::Id id) const;
+ unsigned idTypeSizeInWords(spv::Id id) const;
+
+ spv::Id& asId(unsigned word) { return spv[word]; }
+ const spv::Id& asId(unsigned word) const { return spv[word]; }
+ spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); }
+ std::uint32_t asOpCodeHash(unsigned word);
+ spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); }
+ unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); }
+ spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); }
+ unsigned idPos(spv::Id id) const;
+
+ static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; }
+ static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); }
+
+ // Header access & set methods
+ spirword_t magic() const { return spv[0]; } // return magic number
+ spirword_t bound() const { return spv[3]; } // return Id bound from header
+ spirword_t bound(spirword_t b) { return spv[3] = b; }
+ spirword_t genmagic() const { return spv[2]; } // generator magic
+ spirword_t genmagic(spirword_t m) { return spv[2] = m; }
+ spirword_t schemaNum() const { return spv[4]; } // schema number from header
+
+ // Mapping fns: get
+ spv::Id localId(spv::Id id) const { return idMapL[id]; }
+
+ // Mapping fns: set
+ inline spv::Id localId(spv::Id id, spv::Id newId);
+ void countIds(spv::Id id);
+
+ // Return next unused new local ID.
+ // NOTE: boost::dynamic_bitset would be more efficient due to find_next(),
+ // which std::vector<bool> doens't have.
+ inline spv::Id nextUnusedId(spv::Id id);
+
+ void buildLocalMaps();
+ std::string literalString(unsigned word) const; // Return literal as a std::string
+ int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; }
+
+ bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); }
+ bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; }
+ bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; }
+ bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); }
+ bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); }
+
+ // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const;
+ // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const;
+ std::uint32_t hashType(unsigned typeStart) const;
+
+ spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0);
+ int processInstruction(unsigned word, instfn_t, idfn_t);
+
+ void validate() const;
+ void mapTypeConst();
+ void mapFnBodies();
+ void optLoadStore();
+ void dceFuncs();
+ void dceVars();
+ void dceTypes();
+ void mapNames();
+ void foldIds(); // fold IDs to smallest space
+ void forwardLoadStores(); // load store forwarding (EXPERIMENTAL)
+ void offsetIds(); // create relative offset IDs
+
+ void applyMap(); // remap per local name map
+ void mapRemainder(); // map any IDs we haven't touched yet
+ void stripDebug(); // strip all debug info
+ void stripDeadRefs(); // strips debug info for now-dead references after DCE
+ void strip(); // remove debug symbols
+
+ std::vector<spirword_t> spv; // SPIR words
+
+ namemap_t nameMap; // ID names from OpName
+
+ // Since we want to also do binary ops, we can't use std::vector<bool>. we could use
+ // boost::dynamic_bitset, but we're trying to avoid a boost dependency.
+ typedef std::uint64_t bits_t;
+ std::vector<bits_t> mapped; // which new IDs have been mapped
+ static const int mBits = sizeof(bits_t) * 4;
+
+ bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); }
+ void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); }
+ void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); }
+ size_t maxMappedId() const { return mapped.size() * mBits; }
+
+ // Add a strip range for a given instruction starting at 'start'
+ // Note: avoiding brace initializers to please older versions os MSVC.
+ void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); }
+
+ // Function start and end. use unordered_map because we'll have
+ // many fewer functions than IDs.
+ std::unordered_map<spv::Id, range_t> fnPos;
+
+ // Which functions are called, anywhere in the module, with a call count
+ std::unordered_map<spv::Id, int> fnCalls;
+
+ posmap_t typeConstPos; // word positions that define types & consts (ordered)
+ posmap_rev_t idPosR; // reverse map from IDs to positions
+ typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known.
+
+ std::vector<spv::Id> idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs
+
+ spv::Id entryPoint; // module entry point
+ spv::Id largestNewId; // biggest new ID we have mapped anything to
+
+ // Sections of the binary to strip, given as [begin,end)
+ std::vector<range_t> stripRange;
+
+ // processing options:
+ std::uint32_t options;
+ int verbose; // verbosity level
+
+ // Error latch: this is set if the error handler is ever executed. It would be better to
+ // use a try/catch block and throw, but that's not desired for certain environments, so
+ // this is the alternative.
+ mutable bool errorLatch;
+
+ static errorfn_t errorHandler;
+ static logfn_t logHandler;
+};
+
+} // namespace SPV
+
+#endif // defined (use_cpp11)
+#endif // SPIRVREMAPPER_H
diff --git a/thirdparty/glslang/SPIRV/SpvBuilder.cpp b/thirdparty/glslang/SPIRV/SpvBuilder.cpp
new file mode 100644
index 0000000000..bd208952e0
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/SpvBuilder.cpp
@@ -0,0 +1,3094 @@
+//
+// Copyright (C) 2014-2015 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Helper for making SPIR-V IR. Generally, this is documented in the header
+// SpvBuilder.h.
+//
+
+#include <cassert>
+#include <cstdlib>
+
+#include <unordered_set>
+#include <algorithm>
+
+#include "SpvBuilder.h"
+
+#ifndef GLSLANG_WEB
+#include "hex_float.h"
+#endif
+
+#ifndef _WIN32
+ #include <cstdio>
+#endif
+
+namespace spv {
+
+Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) :
+ spvVersion(spvVersion),
+ source(SourceLanguageUnknown),
+ sourceVersion(0),
+ sourceFileStringId(NoResult),
+ currentLine(0),
+ currentFile(nullptr),
+ emitOpLines(false),
+ addressModel(AddressingModelLogical),
+ memoryModel(MemoryModelGLSL450),
+ builderNumber(magicNumber),
+ buildPoint(0),
+ uniqueId(0),
+ entryPointFunction(0),
+ generatingOpCodeForSpecConst(false),
+ logger(buildLogger)
+{
+ clearAccessChain();
+}
+
+Builder::~Builder()
+{
+}
+
+Id Builder::import(const char* name)
+{
+ Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport);
+ import->addStringOperand(name);
+ module.mapInstruction(import);
+
+ imports.push_back(std::unique_ptr<Instruction>(import));
+ return import->getResultId();
+}
+
+// Emit instruction for non-filename-based #line directives (ie. no filename
+// seen yet): emit an OpLine if we've been asked to emit OpLines and the line
+// number has changed since the last time, and is a valid line number.
+void Builder::setLine(int lineNum)
+{
+ if (lineNum != 0 && lineNum != currentLine) {
+ currentLine = lineNum;
+ if (emitOpLines)
+ addLine(sourceFileStringId, currentLine, 0);
+ }
+}
+
+// If no filename, do non-filename-based #line emit. Else do filename-based emit.
+// Emit OpLine if we've been asked to emit OpLines and the line number or filename
+// has changed since the last time, and line number is valid.
+void Builder::setLine(int lineNum, const char* filename)
+{
+ if (filename == nullptr) {
+ setLine(lineNum);
+ return;
+ }
+ if ((lineNum != 0 && lineNum != currentLine) || currentFile == nullptr ||
+ strncmp(filename, currentFile, strlen(currentFile) + 1) != 0) {
+ currentLine = lineNum;
+ currentFile = filename;
+ if (emitOpLines) {
+ spv::Id strId = getStringId(filename);
+ addLine(strId, currentLine, 0);
+ }
+ }
+}
+
+void Builder::addLine(Id fileName, int lineNum, int column)
+{
+ Instruction* line = new Instruction(OpLine);
+ line->addIdOperand(fileName);
+ line->addImmediateOperand(lineNum);
+ line->addImmediateOperand(column);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(line));
+}
+
+// For creating new groupedTypes (will return old type if the requested one was already made).
+Id Builder::makeVoidType()
+{
+ Instruction* type;
+ if (groupedTypes[OpTypeVoid].size() == 0) {
+ type = new Instruction(getUniqueId(), NoType, OpTypeVoid);
+ groupedTypes[OpTypeVoid].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+ } else
+ type = groupedTypes[OpTypeVoid].back();
+
+ return type->getResultId();
+}
+
+Id Builder::makeBoolType()
+{
+ Instruction* type;
+ if (groupedTypes[OpTypeBool].size() == 0) {
+ type = new Instruction(getUniqueId(), NoType, OpTypeBool);
+ groupedTypes[OpTypeBool].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+ } else
+ type = groupedTypes[OpTypeBool].back();
+
+ return type->getResultId();
+}
+
+Id Builder::makeSamplerType()
+{
+ Instruction* type;
+ if (groupedTypes[OpTypeSampler].size() == 0) {
+ type = new Instruction(getUniqueId(), NoType, OpTypeSampler);
+ groupedTypes[OpTypeSampler].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+ } else
+ type = groupedTypes[OpTypeSampler].back();
+
+ return type->getResultId();
+}
+
+Id Builder::makePointer(StorageClass storageClass, Id pointee)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
+ type = groupedTypes[OpTypePointer][t];
+ if (type->getImmediateOperand(0) == (unsigned)storageClass &&
+ type->getIdOperand(1) == pointee)
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), NoType, OpTypePointer);
+ type->addImmediateOperand(storageClass);
+ type->addIdOperand(pointee);
+ groupedTypes[OpTypePointer].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeForwardPointer(StorageClass storageClass)
+{
+ // Caching/uniquifying doesn't work here, because we don't know the
+ // pointee type and there can be multiple forward pointers of the same
+ // storage type. Somebody higher up in the stack must keep track.
+ Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeForwardPointer);
+ type->addImmediateOperand(storageClass);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
+ type = groupedTypes[OpTypePointer][t];
+ if (type->getImmediateOperand(0) == (unsigned)storageClass &&
+ type->getIdOperand(1) == pointee)
+ return type->getResultId();
+ }
+
+ type = new Instruction(forwardPointerType, NoType, OpTypePointer);
+ type->addImmediateOperand(storageClass);
+ type->addIdOperand(pointee);
+ groupedTypes[OpTypePointer].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeIntegerType(int width, bool hasSign)
+{
+#ifdef GLSLANG_WEB
+ assert(width == 32);
+ width = 32;
+#endif
+
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypeInt].size(); ++t) {
+ type = groupedTypes[OpTypeInt][t];
+ if (type->getImmediateOperand(0) == (unsigned)width &&
+ type->getImmediateOperand(1) == (hasSign ? 1u : 0u))
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), NoType, OpTypeInt);
+ type->addImmediateOperand(width);
+ type->addImmediateOperand(hasSign ? 1 : 0);
+ groupedTypes[OpTypeInt].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ // deal with capabilities
+ switch (width) {
+ case 8:
+ case 16:
+ // these are currently handled by storage-type declarations and post processing
+ break;
+ case 64:
+ addCapability(CapabilityInt64);
+ break;
+ default:
+ break;
+ }
+
+ return type->getResultId();
+}
+
+Id Builder::makeFloatType(int width)
+{
+#ifdef GLSLANG_WEB
+ assert(width == 32);
+ width = 32;
+#endif
+
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypeFloat].size(); ++t) {
+ type = groupedTypes[OpTypeFloat][t];
+ if (type->getImmediateOperand(0) == (unsigned)width)
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), NoType, OpTypeFloat);
+ type->addImmediateOperand(width);
+ groupedTypes[OpTypeFloat].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ // deal with capabilities
+ switch (width) {
+ case 16:
+ // currently handled by storage-type declarations and post processing
+ break;
+ case 64:
+ addCapability(CapabilityFloat64);
+ break;
+ default:
+ break;
+ }
+
+ return type->getResultId();
+}
+
+// Make a struct without checking for duplication.
+// See makeStructResultType() for non-decorated structs
+// needed as the result of some instructions, which does
+// check for duplicates.
+Id Builder::makeStructType(const std::vector<Id>& members, const char* name)
+{
+ // Don't look for previous one, because in the general case,
+ // structs can be duplicated except for decorations.
+
+ // not found, make it
+ Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeStruct);
+ for (int op = 0; op < (int)members.size(); ++op)
+ type->addIdOperand(members[op]);
+ groupedTypes[OpTypeStruct].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+ addName(type->getResultId(), name);
+
+ return type->getResultId();
+}
+
+// Make a struct for the simple results of several instructions,
+// checking for duplication.
+Id Builder::makeStructResultType(Id type0, Id type1)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypeStruct].size(); ++t) {
+ type = groupedTypes[OpTypeStruct][t];
+ if (type->getNumOperands() != 2)
+ continue;
+ if (type->getIdOperand(0) != type0 ||
+ type->getIdOperand(1) != type1)
+ continue;
+ return type->getResultId();
+ }
+
+ // not found, make it
+ std::vector<spv::Id> members;
+ members.push_back(type0);
+ members.push_back(type1);
+
+ return makeStructType(members, "ResType");
+}
+
+Id Builder::makeVectorType(Id component, int size)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) {
+ type = groupedTypes[OpTypeVector][t];
+ if (type->getIdOperand(0) == component &&
+ type->getImmediateOperand(1) == (unsigned)size)
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), NoType, OpTypeVector);
+ type->addIdOperand(component);
+ type->addImmediateOperand(size);
+ groupedTypes[OpTypeVector].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeMatrixType(Id component, int cols, int rows)
+{
+ assert(cols <= maxMatrixSize && rows <= maxMatrixSize);
+
+ Id column = makeVectorType(component, rows);
+
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) {
+ type = groupedTypes[OpTypeMatrix][t];
+ if (type->getIdOperand(0) == column &&
+ type->getImmediateOperand(1) == (unsigned)cols)
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), NoType, OpTypeMatrix);
+ type->addIdOperand(column);
+ type->addImmediateOperand(cols);
+ groupedTypes[OpTypeMatrix].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypeCooperativeMatrixNV].size(); ++t) {
+ type = groupedTypes[OpTypeCooperativeMatrixNV][t];
+ if (type->getIdOperand(0) == component &&
+ type->getIdOperand(1) == scope &&
+ type->getIdOperand(2) == rows &&
+ type->getIdOperand(3) == cols)
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), NoType, OpTypeCooperativeMatrixNV);
+ type->addIdOperand(component);
+ type->addIdOperand(scope);
+ type->addIdOperand(rows);
+ type->addIdOperand(cols);
+ groupedTypes[OpTypeCooperativeMatrixNV].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+
+// TODO: performance: track arrays per stride
+// If a stride is supplied (non-zero) make an array.
+// If no stride (0), reuse previous array types.
+// 'size' is an Id of a constant or specialization constant of the array size
+Id Builder::makeArrayType(Id element, Id sizeId, int stride)
+{
+ Instruction* type;
+ if (stride == 0) {
+ // try to find existing type
+ for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) {
+ type = groupedTypes[OpTypeArray][t];
+ if (type->getIdOperand(0) == element &&
+ type->getIdOperand(1) == sizeId)
+ return type->getResultId();
+ }
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), NoType, OpTypeArray);
+ type->addIdOperand(element);
+ type->addIdOperand(sizeId);
+ groupedTypes[OpTypeArray].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeRuntimeArray(Id element)
+{
+ Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray);
+ type->addIdOperand(element);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) {
+ type = groupedTypes[OpTypeFunction][t];
+ if (type->getIdOperand(0) != returnType || (int)paramTypes.size() != type->getNumOperands() - 1)
+ continue;
+ bool mismatch = false;
+ for (int p = 0; p < (int)paramTypes.size(); ++p) {
+ if (paramTypes[p] != type->getIdOperand(p + 1)) {
+ mismatch = true;
+ break;
+ }
+ }
+ if (! mismatch)
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), NoType, OpTypeFunction);
+ type->addIdOperand(returnType);
+ for (int p = 0; p < (int)paramTypes.size(); ++p)
+ type->addIdOperand(paramTypes[p]);
+ groupedTypes[OpTypeFunction].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
+{
+ assert(sampled == 1 || sampled == 2);
+
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) {
+ type = groupedTypes[OpTypeImage][t];
+ if (type->getIdOperand(0) == sampledType &&
+ type->getImmediateOperand(1) == (unsigned int)dim &&
+ type->getImmediateOperand(2) == ( depth ? 1u : 0u) &&
+ type->getImmediateOperand(3) == (arrayed ? 1u : 0u) &&
+ type->getImmediateOperand(4) == ( ms ? 1u : 0u) &&
+ type->getImmediateOperand(5) == sampled &&
+ type->getImmediateOperand(6) == (unsigned int)format)
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), NoType, OpTypeImage);
+ type->addIdOperand(sampledType);
+ type->addImmediateOperand( dim);
+ type->addImmediateOperand( depth ? 1 : 0);
+ type->addImmediateOperand(arrayed ? 1 : 0);
+ type->addImmediateOperand( ms ? 1 : 0);
+ type->addImmediateOperand(sampled);
+ type->addImmediateOperand((unsigned int)format);
+
+ groupedTypes[OpTypeImage].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+#ifndef GLSLANG_WEB
+ // deal with capabilities
+ switch (dim) {
+ case DimBuffer:
+ if (sampled == 1)
+ addCapability(CapabilitySampledBuffer);
+ else
+ addCapability(CapabilityImageBuffer);
+ break;
+ case Dim1D:
+ if (sampled == 1)
+ addCapability(CapabilitySampled1D);
+ else
+ addCapability(CapabilityImage1D);
+ break;
+ case DimCube:
+ if (arrayed) {
+ if (sampled == 1)
+ addCapability(CapabilitySampledCubeArray);
+ else
+ addCapability(CapabilityImageCubeArray);
+ }
+ break;
+ case DimRect:
+ if (sampled == 1)
+ addCapability(CapabilitySampledRect);
+ else
+ addCapability(CapabilityImageRect);
+ break;
+ case DimSubpassData:
+ addCapability(CapabilityInputAttachment);
+ break;
+ default:
+ break;
+ }
+
+ if (ms) {
+ if (sampled == 2) {
+ // Images used with subpass data are not storage
+ // images, so don't require the capability for them.
+ if (dim != Dim::DimSubpassData)
+ addCapability(CapabilityStorageImageMultisample);
+ if (arrayed)
+ addCapability(CapabilityImageMSArray);
+ }
+ }
+#endif
+
+ return type->getResultId();
+}
+
+Id Builder::makeSampledImageType(Id imageType)
+{
+ // try to find it
+ Instruction* type;
+ for (int t = 0; t < (int)groupedTypes[OpTypeSampledImage].size(); ++t) {
+ type = groupedTypes[OpTypeSampledImage][t];
+ if (type->getIdOperand(0) == imageType)
+ return type->getResultId();
+ }
+
+ // not found, make it
+ type = new Instruction(getUniqueId(), NoType, OpTypeSampledImage);
+ type->addIdOperand(imageType);
+
+ groupedTypes[OpTypeSampledImage].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+
+ return type->getResultId();
+}
+
+#ifndef GLSLANG_WEB
+Id Builder::makeAccelerationStructureNVType()
+{
+ Instruction *type;
+ if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) {
+ type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV);
+ groupedTypes[OpTypeAccelerationStructureNV].push_back(type);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+ module.mapInstruction(type);
+ } else {
+ type = groupedTypes[OpTypeAccelerationStructureNV].back();
+ }
+
+ return type->getResultId();
+}
+#endif
+
+Id Builder::getDerefTypeId(Id resultId) const
+{
+ Id typeId = getTypeId(resultId);
+ assert(isPointerType(typeId));
+
+ return module.getInstruction(typeId)->getIdOperand(1);
+}
+
+Op Builder::getMostBasicTypeClass(Id typeId) const
+{
+ Instruction* instr = module.getInstruction(typeId);
+
+ Op typeClass = instr->getOpCode();
+ switch (typeClass)
+ {
+ case OpTypeVector:
+ case OpTypeMatrix:
+ case OpTypeArray:
+ case OpTypeRuntimeArray:
+ return getMostBasicTypeClass(instr->getIdOperand(0));
+ case OpTypePointer:
+ return getMostBasicTypeClass(instr->getIdOperand(1));
+ default:
+ return typeClass;
+ }
+}
+
+int Builder::getNumTypeConstituents(Id typeId) const
+{
+ Instruction* instr = module.getInstruction(typeId);
+
+ switch (instr->getOpCode())
+ {
+ case OpTypeBool:
+ case OpTypeInt:
+ case OpTypeFloat:
+ case OpTypePointer:
+ return 1;
+ case OpTypeVector:
+ case OpTypeMatrix:
+ return instr->getImmediateOperand(1);
+ case OpTypeArray:
+ {
+ Id lengthId = instr->getIdOperand(1);
+ return module.getInstruction(lengthId)->getImmediateOperand(0);
+ }
+ case OpTypeStruct:
+ return instr->getNumOperands();
+ case OpTypeCooperativeMatrixNV:
+ // has only one constituent when used with OpCompositeConstruct.
+ return 1;
+ default:
+ assert(0);
+ return 1;
+ }
+}
+
+// Return the lowest-level type of scalar that an homogeneous composite is made out of.
+// Typically, this is just to find out if something is made out of ints or floats.
+// However, it includes returning a structure, if say, it is an array of structure.
+Id Builder::getScalarTypeId(Id typeId) const
+{
+ Instruction* instr = module.getInstruction(typeId);
+
+ Op typeClass = instr->getOpCode();
+ switch (typeClass)
+ {
+ case OpTypeVoid:
+ case OpTypeBool:
+ case OpTypeInt:
+ case OpTypeFloat:
+ case OpTypeStruct:
+ return instr->getResultId();
+ case OpTypeVector:
+ case OpTypeMatrix:
+ case OpTypeArray:
+ case OpTypeRuntimeArray:
+ case OpTypePointer:
+ return getScalarTypeId(getContainedTypeId(typeId));
+ default:
+ assert(0);
+ return NoResult;
+ }
+}
+
+// Return the type of 'member' of a composite.
+Id Builder::getContainedTypeId(Id typeId, int member) const
+{
+ Instruction* instr = module.getInstruction(typeId);
+
+ Op typeClass = instr->getOpCode();
+ switch (typeClass)
+ {
+ case OpTypeVector:
+ case OpTypeMatrix:
+ case OpTypeArray:
+ case OpTypeRuntimeArray:
+ case OpTypeCooperativeMatrixNV:
+ return instr->getIdOperand(0);
+ case OpTypePointer:
+ return instr->getIdOperand(1);
+ case OpTypeStruct:
+ return instr->getIdOperand(member);
+ default:
+ assert(0);
+ return NoResult;
+ }
+}
+
+// Return the immediately contained type of a given composite type.
+Id Builder::getContainedTypeId(Id typeId) const
+{
+ return getContainedTypeId(typeId, 0);
+}
+
+// Returns true if 'typeId' is or contains a scalar type declared with 'typeOp'
+// of width 'width'. The 'width' is only consumed for int and float types.
+// Returns false otherwise.
+bool Builder::containsType(Id typeId, spv::Op typeOp, unsigned int width) const
+{
+ const Instruction& instr = *module.getInstruction(typeId);
+
+ Op typeClass = instr.getOpCode();
+ switch (typeClass)
+ {
+ case OpTypeInt:
+ case OpTypeFloat:
+ return typeClass == typeOp && instr.getImmediateOperand(0) == width;
+ case OpTypeStruct:
+ for (int m = 0; m < instr.getNumOperands(); ++m) {
+ if (containsType(instr.getIdOperand(m), typeOp, width))
+ return true;
+ }
+ return false;
+ case OpTypePointer:
+ return false;
+ case OpTypeVector:
+ case OpTypeMatrix:
+ case OpTypeArray:
+ case OpTypeRuntimeArray:
+ return containsType(getContainedTypeId(typeId), typeOp, width);
+ default:
+ return typeClass == typeOp;
+ }
+}
+
+// return true if the type is a pointer to PhysicalStorageBufferEXT or an
+// array of such pointers. These require restrict/aliased decorations.
+bool Builder::containsPhysicalStorageBufferOrArray(Id typeId) const
+{
+ const Instruction& instr = *module.getInstruction(typeId);
+
+ Op typeClass = instr.getOpCode();
+ switch (typeClass)
+ {
+ case OpTypePointer:
+ return getTypeStorageClass(typeId) == StorageClassPhysicalStorageBufferEXT;
+ case OpTypeArray:
+ return containsPhysicalStorageBufferOrArray(getContainedTypeId(typeId));
+ default:
+ return false;
+ }
+}
+
+// See if a scalar constant of this type has already been created, so it
+// can be reused rather than duplicated. (Required by the specification).
+Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value)
+{
+ Instruction* constant;
+ for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
+ constant = groupedConstants[typeClass][i];
+ if (constant->getOpCode() == opcode &&
+ constant->getTypeId() == typeId &&
+ constant->getImmediateOperand(0) == value)
+ return constant->getResultId();
+ }
+
+ return 0;
+}
+
+// Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double' or 'int64').
+Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2)
+{
+ Instruction* constant;
+ for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
+ constant = groupedConstants[typeClass][i];
+ if (constant->getOpCode() == opcode &&
+ constant->getTypeId() == typeId &&
+ constant->getImmediateOperand(0) == v1 &&
+ constant->getImmediateOperand(1) == v2)
+ return constant->getResultId();
+ }
+
+ return 0;
+}
+
+// Return true if consuming 'opcode' means consuming a constant.
+// "constant" here means after final transform to executable code,
+// the value consumed will be a constant, so includes specialization.
+bool Builder::isConstantOpCode(Op opcode) const
+{
+ switch (opcode) {
+ case OpUndef:
+ case OpConstantTrue:
+ case OpConstantFalse:
+ case OpConstant:
+ case OpConstantComposite:
+ case OpConstantSampler:
+ case OpConstantNull:
+ case OpSpecConstantTrue:
+ case OpSpecConstantFalse:
+ case OpSpecConstant:
+ case OpSpecConstantComposite:
+ case OpSpecConstantOp:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Return true if consuming 'opcode' means consuming a specialization constant.
+bool Builder::isSpecConstantOpCode(Op opcode) const
+{
+ switch (opcode) {
+ case OpSpecConstantTrue:
+ case OpSpecConstantFalse:
+ case OpSpecConstant:
+ case OpSpecConstantComposite:
+ case OpSpecConstantOp:
+ return true;
+ default:
+ return false;
+ }
+}
+
+Id Builder::makeBoolConstant(bool b, bool specConstant)
+{
+ Id typeId = makeBoolType();
+ Instruction* constant;
+ Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse);
+
+ // See if we already made it. Applies only to regular constants, because specialization constants
+ // must remain distinct for the purpose of applying a SpecId decoration.
+ if (! specConstant) {
+ Id existing = 0;
+ for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) {
+ constant = groupedConstants[OpTypeBool][i];
+ if (constant->getTypeId() == typeId && constant->getOpCode() == opcode)
+ existing = constant->getResultId();
+ }
+
+ if (existing)
+ return existing;
+ }
+
+ // Make it
+ Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
+ groupedConstants[OpTypeBool].push_back(c);
+ module.mapInstruction(c);
+
+ return c->getResultId();
+}
+
+Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant)
+{
+ Op opcode = specConstant ? OpSpecConstant : OpConstant;
+
+ // See if we already made it. Applies only to regular constants, because specialization constants
+ // must remain distinct for the purpose of applying a SpecId decoration.
+ if (! specConstant) {
+ Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value);
+ if (existing)
+ return existing;
+ }
+
+ Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
+ c->addImmediateOperand(value);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
+ groupedConstants[OpTypeInt].push_back(c);
+ module.mapInstruction(c);
+
+ return c->getResultId();
+}
+
+Id Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specConstant)
+{
+ Op opcode = specConstant ? OpSpecConstant : OpConstant;
+
+ unsigned op1 = value & 0xFFFFFFFF;
+ unsigned op2 = value >> 32;
+
+ // See if we already made it. Applies only to regular constants, because specialization constants
+ // must remain distinct for the purpose of applying a SpecId decoration.
+ if (! specConstant) {
+ Id existing = findScalarConstant(OpTypeInt, opcode, typeId, op1, op2);
+ if (existing)
+ return existing;
+ }
+
+ Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
+ c->addImmediateOperand(op1);
+ c->addImmediateOperand(op2);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
+ groupedConstants[OpTypeInt].push_back(c);
+ module.mapInstruction(c);
+
+ return c->getResultId();
+}
+
+Id Builder::makeFloatConstant(float f, bool specConstant)
+{
+ Op opcode = specConstant ? OpSpecConstant : OpConstant;
+ Id typeId = makeFloatType(32);
+ union { float fl; unsigned int ui; } u;
+ u.fl = f;
+ unsigned value = u.ui;
+
+ // See if we already made it. Applies only to regular constants, because specialization constants
+ // must remain distinct for the purpose of applying a SpecId decoration.
+ if (! specConstant) {
+ Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value);
+ if (existing)
+ return existing;
+ }
+
+ Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
+ c->addImmediateOperand(value);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
+ groupedConstants[OpTypeFloat].push_back(c);
+ module.mapInstruction(c);
+
+ return c->getResultId();
+}
+
+Id Builder::makeDoubleConstant(double d, bool specConstant)
+{
+#ifdef GLSLANG_WEB
+ assert(0);
+ return NoResult;
+#else
+ Op opcode = specConstant ? OpSpecConstant : OpConstant;
+ Id typeId = makeFloatType(64);
+ union { double db; unsigned long long ull; } u;
+ u.db = d;
+ unsigned long long value = u.ull;
+ unsigned op1 = value & 0xFFFFFFFF;
+ unsigned op2 = value >> 32;
+
+ // See if we already made it. Applies only to regular constants, because specialization constants
+ // must remain distinct for the purpose of applying a SpecId decoration.
+ if (! specConstant) {
+ Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2);
+ if (existing)
+ return existing;
+ }
+
+ Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
+ c->addImmediateOperand(op1);
+ c->addImmediateOperand(op2);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
+ groupedConstants[OpTypeFloat].push_back(c);
+ module.mapInstruction(c);
+
+ return c->getResultId();
+#endif
+}
+
+Id Builder::makeFloat16Constant(float f16, bool specConstant)
+{
+#ifdef GLSLANG_WEB
+ assert(0);
+ return NoResult;
+#else
+ Op opcode = specConstant ? OpSpecConstant : OpConstant;
+ Id typeId = makeFloatType(16);
+
+ spvutils::HexFloat<spvutils::FloatProxy<float>> fVal(f16);
+ spvutils::HexFloat<spvutils::FloatProxy<spvutils::Float16>> f16Val(0);
+ fVal.castTo(f16Val, spvutils::kRoundToZero);
+
+ unsigned value = f16Val.value().getAsFloat().get_value();
+
+ // See if we already made it. Applies only to regular constants, because specialization constants
+ // must remain distinct for the purpose of applying a SpecId decoration.
+ if (!specConstant) {
+ Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value);
+ if (existing)
+ return existing;
+ }
+
+ Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
+ c->addImmediateOperand(value);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
+ groupedConstants[OpTypeFloat].push_back(c);
+ module.mapInstruction(c);
+
+ return c->getResultId();
+#endif
+}
+
+Id Builder::makeFpConstant(Id type, double d, bool specConstant)
+{
+#ifdef GLSLANG_WEB
+ const int width = 32;
+ assert(width == getScalarTypeWidth(type));
+#else
+ const int width = getScalarTypeWidth(type);
+#endif
+
+ assert(isFloatType(type));
+
+ switch (width) {
+ case 16:
+ return makeFloat16Constant((float)d, specConstant);
+ case 32:
+ return makeFloatConstant((float)d, specConstant);
+ case 64:
+ return makeDoubleConstant(d, specConstant);
+ default:
+ break;
+ }
+
+ assert(false);
+ return NoResult;
+}
+
+Id Builder::findCompositeConstant(Op typeClass, Id typeId, const std::vector<Id>& comps)
+{
+ Instruction* constant = 0;
+ bool found = false;
+ for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
+ constant = groupedConstants[typeClass][i];
+
+ if (constant->getTypeId() != typeId)
+ continue;
+
+ // same contents?
+ bool mismatch = false;
+ for (int op = 0; op < constant->getNumOperands(); ++op) {
+ if (constant->getIdOperand(op) != comps[op]) {
+ mismatch = true;
+ break;
+ }
+ }
+ if (! mismatch) {
+ found = true;
+ break;
+ }
+ }
+
+ return found ? constant->getResultId() : NoResult;
+}
+
+Id Builder::findStructConstant(Id typeId, const std::vector<Id>& comps)
+{
+ Instruction* constant = 0;
+ bool found = false;
+ for (int i = 0; i < (int)groupedStructConstants[typeId].size(); ++i) {
+ constant = groupedStructConstants[typeId][i];
+
+ // same contents?
+ bool mismatch = false;
+ for (int op = 0; op < constant->getNumOperands(); ++op) {
+ if (constant->getIdOperand(op) != comps[op]) {
+ mismatch = true;
+ break;
+ }
+ }
+ if (! mismatch) {
+ found = true;
+ break;
+ }
+ }
+
+ return found ? constant->getResultId() : NoResult;
+}
+
+// Comments in header
+Id Builder::makeCompositeConstant(Id typeId, const std::vector<Id>& members, bool specConstant)
+{
+ Op opcode = specConstant ? OpSpecConstantComposite : OpConstantComposite;
+ assert(typeId);
+ Op typeClass = getTypeClass(typeId);
+
+ switch (typeClass) {
+ case OpTypeVector:
+ case OpTypeArray:
+ case OpTypeMatrix:
+ case OpTypeCooperativeMatrixNV:
+ if (! specConstant) {
+ Id existing = findCompositeConstant(typeClass, typeId, members);
+ if (existing)
+ return existing;
+ }
+ break;
+ case OpTypeStruct:
+ if (! specConstant) {
+ Id existing = findStructConstant(typeId, members);
+ if (existing)
+ return existing;
+ }
+ break;
+ default:
+ assert(0);
+ return makeFloatConstant(0.0);
+ }
+
+ Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
+ for (int op = 0; op < (int)members.size(); ++op)
+ c->addIdOperand(members[op]);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
+ if (typeClass == OpTypeStruct)
+ groupedStructConstants[typeId].push_back(c);
+ else
+ groupedConstants[typeClass].push_back(c);
+ module.mapInstruction(c);
+
+ return c->getResultId();
+}
+
+Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name)
+{
+ Instruction* entryPoint = new Instruction(OpEntryPoint);
+ entryPoint->addImmediateOperand(model);
+ entryPoint->addIdOperand(function->getId());
+ entryPoint->addStringOperand(name);
+
+ entryPoints.push_back(std::unique_ptr<Instruction>(entryPoint));
+
+ return entryPoint;
+}
+
+// Currently relying on the fact that all 'value' of interest are small non-negative values.
+void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3)
+{
+ Instruction* instr = new Instruction(OpExecutionMode);
+ instr->addIdOperand(entryPoint->getId());
+ instr->addImmediateOperand(mode);
+ if (value1 >= 0)
+ instr->addImmediateOperand(value1);
+ if (value2 >= 0)
+ instr->addImmediateOperand(value2);
+ if (value3 >= 0)
+ instr->addImmediateOperand(value3);
+
+ executionModes.push_back(std::unique_ptr<Instruction>(instr));
+}
+
+void Builder::addName(Id id, const char* string)
+{
+ Instruction* name = new Instruction(OpName);
+ name->addIdOperand(id);
+ name->addStringOperand(string);
+
+ names.push_back(std::unique_ptr<Instruction>(name));
+}
+
+void Builder::addMemberName(Id id, int memberNumber, const char* string)
+{
+ Instruction* name = new Instruction(OpMemberName);
+ name->addIdOperand(id);
+ name->addImmediateOperand(memberNumber);
+ name->addStringOperand(string);
+
+ names.push_back(std::unique_ptr<Instruction>(name));
+}
+
+void Builder::addDecoration(Id id, Decoration decoration, int num)
+{
+ if (decoration == spv::DecorationMax)
+ return;
+
+ Instruction* dec = new Instruction(OpDecorate);
+ dec->addIdOperand(id);
+ dec->addImmediateOperand(decoration);
+ if (num >= 0)
+ dec->addImmediateOperand(num);
+
+ decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
+void Builder::addDecoration(Id id, Decoration decoration, const char* s)
+{
+ if (decoration == spv::DecorationMax)
+ return;
+
+ Instruction* dec = new Instruction(OpDecorateStringGOOGLE);
+ dec->addIdOperand(id);
+ dec->addImmediateOperand(decoration);
+ dec->addStringOperand(s);
+
+ decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
+void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
+{
+ if (decoration == spv::DecorationMax)
+ return;
+
+ Instruction* dec = new Instruction(OpDecorateId);
+ dec->addIdOperand(id);
+ dec->addImmediateOperand(decoration);
+ dec->addIdOperand(idDecoration);
+
+ decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
+void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
+{
+ if (decoration == spv::DecorationMax)
+ return;
+
+ Instruction* dec = new Instruction(OpMemberDecorate);
+ dec->addIdOperand(id);
+ dec->addImmediateOperand(member);
+ dec->addImmediateOperand(decoration);
+ if (num >= 0)
+ dec->addImmediateOperand(num);
+
+ decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
+void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const char *s)
+{
+ if (decoration == spv::DecorationMax)
+ return;
+
+ Instruction* dec = new Instruction(OpMemberDecorateStringGOOGLE);
+ dec->addIdOperand(id);
+ dec->addImmediateOperand(member);
+ dec->addImmediateOperand(decoration);
+ dec->addStringOperand(s);
+
+ decorations.push_back(std::unique_ptr<Instruction>(dec));
+}
+
+// Comments in header
+Function* Builder::makeEntryPoint(const char* entryPoint)
+{
+ assert(! entryPointFunction);
+
+ Block* entry;
+ std::vector<Id> params;
+ std::vector<std::vector<Decoration>> decorations;
+
+ entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, decorations, &entry);
+
+ return entryPointFunction;
+}
+
+// Comments in header
+Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
+ const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry)
+{
+ // Make the function and initial instructions in it
+ Id typeId = makeFunctionType(returnType, paramTypes);
+ Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size());
+ Function* function = new Function(getUniqueId(), returnType, typeId, firstParamId, module);
+
+ // Set up the precisions
+ setPrecision(function->getId(), precision);
+ for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) {
+ for (int d = 0; d < (int)decorations[p].size(); ++d)
+ addDecoration(firstParamId + p, decorations[p][d]);
+ }
+
+ // CFG
+ if (entry) {
+ *entry = new Block(getUniqueId(), *function);
+ function->addBlock(*entry);
+ setBuildPoint(*entry);
+ }
+
+ if (name)
+ addName(function->getId(), name);
+
+ functions.push_back(std::unique_ptr<Function>(function));
+
+ return function;
+}
+
+// Comments in header
+void Builder::makeReturn(bool implicit, Id retVal)
+{
+ if (retVal) {
+ Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue);
+ inst->addIdOperand(retVal);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
+ } else
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(NoResult, NoType, OpReturn)));
+
+ if (! implicit)
+ createAndSetNoPredecessorBlock("post-return");
+}
+
+// Comments in header
+void Builder::leaveFunction()
+{
+ Block* block = buildPoint;
+ Function& function = buildPoint->getParent();
+ assert(block);
+
+ // If our function did not contain a return, add a return void now.
+ if (! block->isTerminated()) {
+ if (function.getReturnType() == makeVoidType())
+ makeReturn(true);
+ else {
+ makeReturn(true, createUndefined(function.getReturnType()));
+ }
+ }
+}
+
+// Comments in header
+void Builder::makeDiscard()
+{
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(OpKill)));
+ createAndSetNoPredecessorBlock("post-discard");
+}
+
+// Comments in header
+Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, Id initializer)
+{
+ Id pointerType = makePointer(storageClass, type);
+ Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
+ inst->addImmediateOperand(storageClass);
+ if (initializer != NoResult)
+ inst->addIdOperand(initializer);
+
+ switch (storageClass) {
+ case StorageClassFunction:
+ // Validation rules require the declaration in the entry block
+ buildPoint->getParent().addLocalVariable(std::unique_ptr<Instruction>(inst));
+ break;
+
+ default:
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
+ module.mapInstruction(inst);
+ break;
+ }
+
+ if (name)
+ addName(inst->getResultId(), name);
+
+ return inst->getResultId();
+}
+
+// Comments in header
+Id Builder::createUndefined(Id type)
+{
+ Instruction* inst = new Instruction(getUniqueId(), type, OpUndef);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
+ return inst->getResultId();
+}
+
+// av/vis/nonprivate are unnecessary and illegal for some storage classes.
+spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
+{
+ switch (sc) {
+ case spv::StorageClassUniform:
+ case spv::StorageClassWorkgroup:
+ case spv::StorageClassStorageBuffer:
+ case spv::StorageClassPhysicalStorageBufferEXT:
+ break;
+ default:
+ memoryAccess = spv::MemoryAccessMask(memoryAccess &
+ ~(spv::MemoryAccessMakePointerAvailableKHRMask |
+ spv::MemoryAccessMakePointerVisibleKHRMask |
+ spv::MemoryAccessNonPrivatePointerKHRMask));
+ break;
+ }
+ return memoryAccess;
+}
+
+// Comments in header
+void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+{
+ Instruction* store = new Instruction(OpStore);
+ store->addIdOperand(lValue);
+ store->addIdOperand(rValue);
+
+ memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
+
+ if (memoryAccess != MemoryAccessMaskNone) {
+ store->addImmediateOperand(memoryAccess);
+ if (memoryAccess & spv::MemoryAccessAlignedMask) {
+ store->addImmediateOperand(alignment);
+ }
+ if (memoryAccess & spv::MemoryAccessMakePointerAvailableKHRMask) {
+ store->addIdOperand(makeUintConstant(scope));
+ }
+ }
+
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(store));
+}
+
+// Comments in header
+Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+{
+ Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
+ load->addIdOperand(lValue);
+
+ memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
+
+ if (memoryAccess != MemoryAccessMaskNone) {
+ load->addImmediateOperand(memoryAccess);
+ if (memoryAccess & spv::MemoryAccessAlignedMask) {
+ load->addImmediateOperand(alignment);
+ }
+ if (memoryAccess & spv::MemoryAccessMakePointerVisibleKHRMask) {
+ load->addIdOperand(makeUintConstant(scope));
+ }
+ }
+
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
+
+ return load->getResultId();
+}
+
+// Comments in header
+Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets)
+{
+ // Figure out the final resulting type.
+ spv::Id typeId = getTypeId(base);
+ assert(isPointerType(typeId) && offsets.size() > 0);
+ typeId = getContainedTypeId(typeId);
+ for (int i = 0; i < (int)offsets.size(); ++i) {
+ if (isStructType(typeId)) {
+ assert(isConstantScalar(offsets[i]));
+ typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i]));
+ } else
+ typeId = getContainedTypeId(typeId, offsets[i]);
+ }
+ typeId = makePointer(storageClass, typeId);
+
+ // Make the instruction
+ Instruction* chain = new Instruction(getUniqueId(), typeId, OpAccessChain);
+ chain->addIdOperand(base);
+ for (int i = 0; i < (int)offsets.size(); ++i)
+ chain->addIdOperand(offsets[i]);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(chain));
+
+ return chain->getResultId();
+}
+
+Id Builder::createArrayLength(Id base, unsigned int member)
+{
+ spv::Id intType = makeUintType(32);
+ Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength);
+ length->addIdOperand(base);
+ length->addImmediateOperand(member);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(length));
+
+ return length->getResultId();
+}
+
+Id Builder::createCooperativeMatrixLength(Id type)
+{
+ spv::Id intType = makeUintType(32);
+
+ // Generate code for spec constants if in spec constant operation
+ // generation mode.
+ if (generatingOpCodeForSpecConst) {
+ return createSpecConstantOp(OpCooperativeMatrixLengthNV, intType, std::vector<Id>(1, type), std::vector<Id>());
+ }
+
+ Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthNV);
+ length->addIdOperand(type);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(length));
+
+ return length->getResultId();
+}
+
+Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
+{
+ // Generate code for spec constants if in spec constant operation
+ // generation mode.
+ if (generatingOpCodeForSpecConst) {
+ return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), std::vector<Id>(1, index));
+ }
+ Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
+ extract->addIdOperand(composite);
+ extract->addImmediateOperand(index);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
+
+ return extract->getResultId();
+}
+
+Id Builder::createCompositeExtract(Id composite, Id typeId, const std::vector<unsigned>& indexes)
+{
+ // Generate code for spec constants if in spec constant operation
+ // generation mode.
+ if (generatingOpCodeForSpecConst) {
+ return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), indexes);
+ }
+ Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
+ extract->addIdOperand(composite);
+ for (int i = 0; i < (int)indexes.size(); ++i)
+ extract->addImmediateOperand(indexes[i]);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
+
+ return extract->getResultId();
+}
+
+Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned index)
+{
+ Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert);
+ insert->addIdOperand(object);
+ insert->addIdOperand(composite);
+ insert->addImmediateOperand(index);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
+
+ return insert->getResultId();
+}
+
+Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std::vector<unsigned>& indexes)
+{
+ Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert);
+ insert->addIdOperand(object);
+ insert->addIdOperand(composite);
+ for (int i = 0; i < (int)indexes.size(); ++i)
+ insert->addImmediateOperand(indexes[i]);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
+
+ return insert->getResultId();
+}
+
+Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
+{
+ Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
+ extract->addIdOperand(vector);
+ extract->addIdOperand(componentIndex);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
+
+ return extract->getResultId();
+}
+
+Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex)
+{
+ Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic);
+ insert->addIdOperand(vector);
+ insert->addIdOperand(component);
+ insert->addIdOperand(componentIndex);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
+
+ return insert->getResultId();
+}
+
+// An opcode that has no operands, no result id, and no type
+void Builder::createNoResultOp(Op opCode)
+{
+ Instruction* op = new Instruction(opCode);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+}
+
+// An opcode that has one id operand, no result id, and no type
+void Builder::createNoResultOp(Op opCode, Id operand)
+{
+ Instruction* op = new Instruction(opCode);
+ op->addIdOperand(operand);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+}
+
+// An opcode that has one or more operands, no result id, and no type
+void Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands)
+{
+ Instruction* op = new Instruction(opCode);
+ for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
+ op->addIdOperand(*it);
+ }
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+}
+
+// An opcode that has multiple operands, no result id, and no type
+void Builder::createNoResultOp(Op opCode, const std::vector<IdImmediate>& operands)
+{
+ Instruction* op = new Instruction(opCode);
+ for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
+ if (it->isId)
+ op->addIdOperand(it->word);
+ else
+ op->addImmediateOperand(it->word);
+ }
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+}
+
+void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics)
+{
+ Instruction* op = new Instruction(OpControlBarrier);
+ op->addIdOperand(makeUintConstant(execution));
+ op->addIdOperand(makeUintConstant(memory));
+ op->addIdOperand(makeUintConstant(semantics));
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+}
+
+void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
+{
+ Instruction* op = new Instruction(OpMemoryBarrier);
+ op->addIdOperand(makeUintConstant(executionScope));
+ op->addIdOperand(makeUintConstant(memorySemantics));
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+}
+
+// An opcode that has one operands, a result id, and a type
+Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
+{
+ // Generate code for spec constants if in spec constant operation
+ // generation mode.
+ if (generatingOpCodeForSpecConst) {
+ return createSpecConstantOp(opCode, typeId, std::vector<Id>(1, operand), std::vector<Id>());
+ }
+ Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
+ op->addIdOperand(operand);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+
+ return op->getResultId();
+}
+
+Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
+{
+ // Generate code for spec constants if in spec constant operation
+ // generation mode.
+ if (generatingOpCodeForSpecConst) {
+ std::vector<Id> operands(2);
+ operands[0] = left; operands[1] = right;
+ return createSpecConstantOp(opCode, typeId, operands, std::vector<Id>());
+ }
+ Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
+ op->addIdOperand(left);
+ op->addIdOperand(right);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+
+ return op->getResultId();
+}
+
+Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
+{
+ // Generate code for spec constants if in spec constant operation
+ // generation mode.
+ if (generatingOpCodeForSpecConst) {
+ std::vector<Id> operands(3);
+ operands[0] = op1;
+ operands[1] = op2;
+ operands[2] = op3;
+ return createSpecConstantOp(
+ opCode, typeId, operands, std::vector<Id>());
+ }
+ Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
+ op->addIdOperand(op1);
+ op->addIdOperand(op2);
+ op->addIdOperand(op3);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+
+ return op->getResultId();
+}
+
+Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
+{
+ Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
+ for (auto it = operands.cbegin(); it != operands.cend(); ++it)
+ op->addIdOperand(*it);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+
+ return op->getResultId();
+}
+
+Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& operands)
+{
+ Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
+ for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
+ if (it->isId)
+ op->addIdOperand(it->word);
+ else
+ op->addImmediateOperand(it->word);
+ }
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+
+ return op->getResultId();
+}
+
+Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals)
+{
+ Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
+ op->addImmediateOperand((unsigned) opCode);
+ for (auto it = operands.cbegin(); it != operands.cend(); ++it)
+ op->addIdOperand(*it);
+ for (auto it = literals.cbegin(); it != literals.cend(); ++it)
+ op->addImmediateOperand(*it);
+ module.mapInstruction(op);
+ constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(op));
+
+ return op->getResultId();
+}
+
+Id Builder::createFunctionCall(spv::Function* function, const std::vector<spv::Id>& args)
+{
+ Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall);
+ op->addIdOperand(function->getId());
+ for (int a = 0; a < (int)args.size(); ++a)
+ op->addIdOperand(args[a]);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+
+ return op->getResultId();
+}
+
+// Comments in header
+Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector<unsigned>& channels)
+{
+ if (channels.size() == 1)
+ return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision);
+
+ if (generatingOpCodeForSpecConst) {
+ std::vector<Id> operands(2);
+ operands[0] = operands[1] = source;
+ return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision);
+ }
+ Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
+ assert(isVector(source));
+ swizzle->addIdOperand(source);
+ swizzle->addIdOperand(source);
+ for (int i = 0; i < (int)channels.size(); ++i)
+ swizzle->addImmediateOperand(channels[i]);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
+
+ return setPrecision(swizzle->getResultId(), precision);
+}
+
+// Comments in header
+Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector<unsigned>& channels)
+{
+ if (channels.size() == 1 && getNumComponents(source) == 1)
+ return createCompositeInsert(source, target, typeId, channels.front());
+
+ Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
+
+ assert(isVector(target));
+ swizzle->addIdOperand(target);
+
+ assert(getNumComponents(source) == (int)channels.size());
+ assert(isVector(source));
+ swizzle->addIdOperand(source);
+
+ // Set up an identity shuffle from the base value to the result value
+ unsigned int components[4];
+ int numTargetComponents = getNumComponents(target);
+ for (int i = 0; i < numTargetComponents; ++i)
+ components[i] = i;
+
+ // Punch in the l-value swizzle
+ for (int i = 0; i < (int)channels.size(); ++i)
+ components[channels[i]] = numTargetComponents + i;
+
+ // finish the instruction with these components selectors
+ for (int i = 0; i < numTargetComponents; ++i)
+ swizzle->addImmediateOperand(components[i]);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
+
+ return swizzle->getResultId();
+}
+
+// Comments in header
+void Builder::promoteScalar(Decoration precision, Id& left, Id& right)
+{
+ int direction = getNumComponents(right) - getNumComponents(left);
+
+ if (direction > 0)
+ left = smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right)));
+ else if (direction < 0)
+ right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left)));
+
+ return;
+}
+
+// Comments in header
+Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType)
+{
+ assert(getNumComponents(scalar) == 1);
+ assert(getTypeId(scalar) == getScalarTypeId(vectorType));
+
+ int numComponents = getNumTypeComponents(vectorType);
+ if (numComponents == 1)
+ return scalar;
+
+ Instruction* smear = nullptr;
+ if (generatingOpCodeForSpecConst) {
+ auto members = std::vector<spv::Id>(numComponents, scalar);
+ // Sometime even in spec-constant-op mode, the temporary vector created by
+ // promoting a scalar might not be a spec constant. This should depend on
+ // the scalar.
+ // e.g.:
+ // const vec2 spec_const_result = a_spec_const_vec2 + a_front_end_const_scalar;
+ // In such cases, the temporary vector created from a_front_end_const_scalar
+ // is not a spec constant vector, even though the binary operation node is marked
+ // as 'specConstant' and we are in spec-constant-op mode.
+ auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar));
+ smear = module.getInstruction(result_id);
+ } else {
+ smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
+ for (int c = 0; c < numComponents; ++c)
+ smear->addIdOperand(scalar);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(smear));
+ }
+
+ return setPrecision(smear->getResultId(), precision);
+}
+
+// Comments in header
+Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector<Id>& args)
+{
+ Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst);
+ inst->addIdOperand(builtins);
+ inst->addImmediateOperand(entryPoint);
+ for (int arg = 0; arg < (int)args.size(); ++arg)
+ inst->addIdOperand(args[arg]);
+
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
+
+ return inst->getResultId();
+}
+
+// Accept all parameters needed to create a texture instruction.
+// Create the correct instruction based on the inputs, and make the call.
+Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
+ bool noImplicitLod, const TextureParameters& parameters, ImageOperandsMask signExtensionMask)
+{
+ static const int maxTextureArgs = 10;
+ Id texArgs[maxTextureArgs] = {};
+
+ //
+ // Set up the fixed arguments
+ //
+ int numArgs = 0;
+ bool explicitLod = false;
+ texArgs[numArgs++] = parameters.sampler;
+ texArgs[numArgs++] = parameters.coords;
+ if (parameters.Dref != NoResult)
+ texArgs[numArgs++] = parameters.Dref;
+ if (parameters.component != NoResult)
+ texArgs[numArgs++] = parameters.component;
+
+#ifndef GLSLANG_WEB
+ if (parameters.granularity != NoResult)
+ texArgs[numArgs++] = parameters.granularity;
+ if (parameters.coarse != NoResult)
+ texArgs[numArgs++] = parameters.coarse;
+#endif
+
+ //
+ // Set up the optional arguments
+ //
+ int optArgNum = numArgs; // track which operand, if it exists, is the mask of optional arguments
+ ++numArgs; // speculatively make room for the mask operand
+ ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand
+ if (parameters.bias) {
+ mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask);
+ texArgs[numArgs++] = parameters.bias;
+ }
+ if (parameters.lod) {
+ mask = (ImageOperandsMask)(mask | ImageOperandsLodMask);
+ texArgs[numArgs++] = parameters.lod;
+ explicitLod = true;
+ } else if (parameters.gradX) {
+ mask = (ImageOperandsMask)(mask | ImageOperandsGradMask);
+ texArgs[numArgs++] = parameters.gradX;
+ texArgs[numArgs++] = parameters.gradY;
+ explicitLod = true;
+ } else if (noImplicitLod && ! fetch && ! gather) {
+ // have to explicitly use lod of 0 if not allowed to have them be implicit, and
+ // we would otherwise be about to issue an implicit instruction
+ mask = (ImageOperandsMask)(mask | ImageOperandsLodMask);
+ texArgs[numArgs++] = makeFloatConstant(0.0);
+ explicitLod = true;
+ }
+ if (parameters.offset) {
+ if (isConstant(parameters.offset))
+ mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetMask);
+ else {
+ addCapability(CapabilityImageGatherExtended);
+ mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask);
+ }
+ texArgs[numArgs++] = parameters.offset;
+ }
+ if (parameters.offsets) {
+ addCapability(CapabilityImageGatherExtended);
+ mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask);
+ texArgs[numArgs++] = parameters.offsets;
+ }
+#ifndef GLSLANG_WEB
+ if (parameters.sample) {
+ mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask);
+ texArgs[numArgs++] = parameters.sample;
+ }
+ if (parameters.lodClamp) {
+ // capability if this bit is used
+ addCapability(CapabilityMinLod);
+
+ mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask);
+ texArgs[numArgs++] = parameters.lodClamp;
+ }
+ if (parameters.nonprivate) {
+ mask = mask | ImageOperandsNonPrivateTexelKHRMask;
+ }
+ if (parameters.volatil) {
+ mask = mask | ImageOperandsVolatileTexelKHRMask;
+ }
+#endif
+ mask = mask | signExtensionMask;
+ if (mask == ImageOperandsMaskNone)
+ --numArgs; // undo speculative reservation for the mask argument
+ else
+ texArgs[optArgNum] = mask;
+
+ //
+ // Set up the instruction
+ //
+ Op opCode = OpNop; // All paths below need to set this
+ if (fetch) {
+ if (sparse)
+ opCode = OpImageSparseFetch;
+ else
+ opCode = OpImageFetch;
+#ifndef GLSLANG_WEB
+ } else if (parameters.granularity && parameters.coarse) {
+ opCode = OpImageSampleFootprintNV;
+ } else if (gather) {
+ if (parameters.Dref)
+ if (sparse)
+ opCode = OpImageSparseDrefGather;
+ else
+ opCode = OpImageDrefGather;
+ else
+ if (sparse)
+ opCode = OpImageSparseGather;
+ else
+ opCode = OpImageGather;
+#endif
+ } else if (explicitLod) {
+ if (parameters.Dref) {
+ if (proj)
+ if (sparse)
+ opCode = OpImageSparseSampleProjDrefExplicitLod;
+ else
+ opCode = OpImageSampleProjDrefExplicitLod;
+ else
+ if (sparse)
+ opCode = OpImageSparseSampleDrefExplicitLod;
+ else
+ opCode = OpImageSampleDrefExplicitLod;
+ } else {
+ if (proj)
+ if (sparse)
+ opCode = OpImageSparseSampleProjExplicitLod;
+ else
+ opCode = OpImageSampleProjExplicitLod;
+ else
+ if (sparse)
+ opCode = OpImageSparseSampleExplicitLod;
+ else
+ opCode = OpImageSampleExplicitLod;
+ }
+ } else {
+ if (parameters.Dref) {
+ if (proj)
+ if (sparse)
+ opCode = OpImageSparseSampleProjDrefImplicitLod;
+ else
+ opCode = OpImageSampleProjDrefImplicitLod;
+ else
+ if (sparse)
+ opCode = OpImageSparseSampleDrefImplicitLod;
+ else
+ opCode = OpImageSampleDrefImplicitLod;
+ } else {
+ if (proj)
+ if (sparse)
+ opCode = OpImageSparseSampleProjImplicitLod;
+ else
+ opCode = OpImageSampleProjImplicitLod;
+ else
+ if (sparse)
+ opCode = OpImageSparseSampleImplicitLod;
+ else
+ opCode = OpImageSampleImplicitLod;
+ }
+ }
+
+ // See if the result type is expecting a smeared result.
+ // This happens when a legacy shadow*() call is made, which
+ // gets a vec4 back instead of a float.
+ Id smearedType = resultType;
+ if (! isScalarType(resultType)) {
+ switch (opCode) {
+ case OpImageSampleDrefImplicitLod:
+ case OpImageSampleDrefExplicitLod:
+ case OpImageSampleProjDrefImplicitLod:
+ case OpImageSampleProjDrefExplicitLod:
+ resultType = getScalarTypeId(resultType);
+ break;
+ default:
+ break;
+ }
+ }
+
+ Id typeId0 = 0;
+ Id typeId1 = 0;
+
+ if (sparse) {
+ typeId0 = resultType;
+ typeId1 = getDerefTypeId(parameters.texelOut);
+ resultType = makeStructResultType(typeId0, typeId1);
+ }
+
+ // Build the SPIR-V instruction
+ Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode);
+ for (int op = 0; op < optArgNum; ++op)
+ textureInst->addIdOperand(texArgs[op]);
+ if (optArgNum < numArgs)
+ textureInst->addImmediateOperand(texArgs[optArgNum]);
+ for (int op = optArgNum + 1; op < numArgs; ++op)
+ textureInst->addIdOperand(texArgs[op]);
+ setPrecision(textureInst->getResultId(), precision);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(textureInst));
+
+ Id resultId = textureInst->getResultId();
+
+ if (sparse) {
+ // set capability
+ addCapability(CapabilitySparseResidency);
+
+ // Decode the return type that was a special structure
+ createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut);
+ resultId = createCompositeExtract(resultId, typeId0, 0);
+ setPrecision(resultId, precision);
+ } else {
+ // When a smear is needed, do it, as per what was computed
+ // above when resultType was changed to a scalar type.
+ if (resultType != smearedType)
+ resultId = smearScalar(precision, resultId, smearedType);
+ }
+
+ return resultId;
+}
+
+// Comments in header
+Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters, bool isUnsignedResult)
+{
+ // Figure out the result type
+ Id resultType = 0;
+ switch (opCode) {
+ case OpImageQuerySize:
+ case OpImageQuerySizeLod:
+ {
+ int numComponents = 0;
+ switch (getTypeDimensionality(getImageType(parameters.sampler))) {
+ case Dim1D:
+ case DimBuffer:
+ numComponents = 1;
+ break;
+ case Dim2D:
+ case DimCube:
+ case DimRect:
+ case DimSubpassData:
+ numComponents = 2;
+ break;
+ case Dim3D:
+ numComponents = 3;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+ if (isArrayedImageType(getImageType(parameters.sampler)))
+ ++numComponents;
+
+ Id intType = isUnsignedResult ? makeUintType(32) : makeIntType(32);
+ if (numComponents == 1)
+ resultType = intType;
+ else
+ resultType = makeVectorType(intType, numComponents);
+
+ break;
+ }
+ case OpImageQueryLod:
+ resultType = makeVectorType(getScalarTypeId(getTypeId(parameters.coords)), 2);
+ break;
+ case OpImageQueryLevels:
+ case OpImageQuerySamples:
+ resultType = isUnsignedResult ? makeUintType(32) : makeIntType(32);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ Instruction* query = new Instruction(getUniqueId(), resultType, opCode);
+ query->addIdOperand(parameters.sampler);
+ if (parameters.coords)
+ query->addIdOperand(parameters.coords);
+ if (parameters.lod)
+ query->addIdOperand(parameters.lod);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(query));
+ addCapability(CapabilityImageQuery);
+
+ return query->getResultId();
+}
+
+// External comments in header.
+// Operates recursively to visit the composite's hierarchy.
+Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, bool equal)
+{
+ Id boolType = makeBoolType();
+ Id valueType = getTypeId(value1);
+
+ Id resultId = NoResult;
+
+ int numConstituents = getNumTypeConstituents(valueType);
+
+ // Scalars and Vectors
+
+ if (isScalarType(valueType) || isVectorType(valueType)) {
+ assert(valueType == getTypeId(value2));
+ // These just need a single comparison, just have
+ // to figure out what it is.
+ Op op;
+ switch (getMostBasicTypeClass(valueType)) {
+ case OpTypeFloat:
+ op = equal ? OpFOrdEqual : OpFOrdNotEqual;
+ break;
+ case OpTypeInt:
+ default:
+ op = equal ? OpIEqual : OpINotEqual;
+ break;
+ case OpTypeBool:
+ op = equal ? OpLogicalEqual : OpLogicalNotEqual;
+ precision = NoPrecision;
+ break;
+ }
+
+ if (isScalarType(valueType)) {
+ // scalar
+ resultId = createBinOp(op, boolType, value1, value2);
+ } else {
+ // vector
+ resultId = createBinOp(op, makeVectorType(boolType, numConstituents), value1, value2);
+ setPrecision(resultId, precision);
+ // reduce vector compares...
+ resultId = createUnaryOp(equal ? OpAll : OpAny, boolType, resultId);
+ }
+
+ return setPrecision(resultId, precision);
+ }
+
+ // Only structs, arrays, and matrices should be left.
+ // They share in common the reduction operation across their constituents.
+ assert(isAggregateType(valueType) || isMatrixType(valueType));
+
+ // Compare each pair of constituents
+ for (int constituent = 0; constituent < numConstituents; ++constituent) {
+ std::vector<unsigned> indexes(1, constituent);
+ Id constituentType1 = getContainedTypeId(getTypeId(value1), constituent);
+ Id constituentType2 = getContainedTypeId(getTypeId(value2), constituent);
+ Id constituent1 = createCompositeExtract(value1, constituentType1, indexes);
+ Id constituent2 = createCompositeExtract(value2, constituentType2, indexes);
+
+ Id subResultId = createCompositeCompare(precision, constituent1, constituent2, equal);
+
+ if (constituent == 0)
+ resultId = subResultId;
+ else
+ resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision);
+ }
+
+ return resultId;
+}
+
+// OpCompositeConstruct
+Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
+{
+ assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
+
+ if (generatingOpCodeForSpecConst) {
+ // Sometime, even in spec-constant-op mode, the constant composite to be
+ // constructed may not be a specialization constant.
+ // e.g.:
+ // const mat2 m2 = mat2(a_spec_const, a_front_end_const, another_front_end_const, third_front_end_const);
+ // The first column vector should be a spec constant one, as a_spec_const is a spec constant.
+ // The second column vector should NOT be spec constant, as it does not contain any spec constants.
+ // To handle such cases, we check the constituents of the constant vector to determine whether this
+ // vector should be created as a spec constant.
+ return makeCompositeConstant(typeId, constituents,
+ std::any_of(constituents.begin(), constituents.end(),
+ [&](spv::Id id) { return isSpecConstant(id); }));
+ }
+
+ Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
+ for (int c = 0; c < (int)constituents.size(); ++c)
+ op->addIdOperand(constituents[c]);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
+
+ return op->getResultId();
+}
+
+// Vector or scalar constructor
+Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
+{
+ Id result = NoResult;
+ unsigned int numTargetComponents = getNumTypeComponents(resultTypeId);
+ unsigned int targetComponent = 0;
+
+ // Special case: when calling a vector constructor with a single scalar
+ // argument, smear the scalar
+ if (sources.size() == 1 && isScalar(sources[0]) && numTargetComponents > 1)
+ return smearScalar(precision, sources[0], resultTypeId);
+
+ // accumulate the arguments for OpCompositeConstruct
+ std::vector<Id> constituents;
+ Id scalarTypeId = getScalarTypeId(resultTypeId);
+
+ // lambda to store the result of visiting an argument component
+ const auto latchResult = [&](Id comp) {
+ if (numTargetComponents > 1)
+ constituents.push_back(comp);
+ else
+ result = comp;
+ ++targetComponent;
+ };
+
+ // lambda to visit a vector argument's components
+ const auto accumulateVectorConstituents = [&](Id sourceArg) {
+ unsigned int sourceSize = getNumComponents(sourceArg);
+ unsigned int sourcesToUse = sourceSize;
+ if (sourcesToUse + targetComponent > numTargetComponents)
+ sourcesToUse = numTargetComponents - targetComponent;
+
+ for (unsigned int s = 0; s < sourcesToUse; ++s) {
+ std::vector<unsigned> swiz;
+ swiz.push_back(s);
+ latchResult(createRvalueSwizzle(precision, scalarTypeId, sourceArg, swiz));
+ }
+ };
+
+ // lambda to visit a matrix argument's components
+ const auto accumulateMatrixConstituents = [&](Id sourceArg) {
+ unsigned int sourceSize = getNumColumns(sourceArg) * getNumRows(sourceArg);
+ unsigned int sourcesToUse = sourceSize;
+ if (sourcesToUse + targetComponent > numTargetComponents)
+ sourcesToUse = numTargetComponents - targetComponent;
+
+ int col = 0;
+ int row = 0;
+ for (unsigned int s = 0; s < sourcesToUse; ++s) {
+ if (row >= getNumRows(sourceArg)) {
+ row = 0;
+ col++;
+ }
+ std::vector<Id> indexes;
+ indexes.push_back(col);
+ indexes.push_back(row);
+ latchResult(createCompositeExtract(sourceArg, scalarTypeId, indexes));
+ row++;
+ }
+ };
+
+ // Go through the source arguments, each one could have either
+ // a single or multiple components to contribute.
+ for (unsigned int i = 0; i < sources.size(); ++i) {
+
+ if (isScalar(sources[i]) || isPointer(sources[i]))
+ latchResult(sources[i]);
+ else if (isVector(sources[i]))
+ accumulateVectorConstituents(sources[i]);
+ else if (isMatrix(sources[i]))
+ accumulateMatrixConstituents(sources[i]);
+ else
+ assert(0);
+
+ if (targetComponent >= numTargetComponents)
+ break;
+ }
+
+ // If the result is a vector, make it from the gathered constituents.
+ if (constituents.size() > 0)
+ result = createCompositeConstruct(resultTypeId, constituents);
+
+ return setPrecision(result, precision);
+}
+
+// Comments in header
+Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
+{
+ Id componentTypeId = getScalarTypeId(resultTypeId);
+ int numCols = getTypeNumColumns(resultTypeId);
+ int numRows = getTypeNumRows(resultTypeId);
+
+ Instruction* instr = module.getInstruction(componentTypeId);
+#ifdef GLSLANG_WEB
+ const unsigned bitCount = 32;
+ assert(bitCount == instr->getImmediateOperand(0));
+#else
+ const unsigned bitCount = instr->getImmediateOperand(0);
+#endif
+
+ // Optimize matrix constructed from a bigger matrix
+ if (isMatrix(sources[0]) && getNumColumns(sources[0]) >= numCols && getNumRows(sources[0]) >= numRows) {
+ // To truncate the matrix to a smaller number of rows/columns, we need to:
+ // 1. For each column, extract the column and truncate it to the required size using shuffle
+ // 2. Assemble the resulting matrix from all columns
+ Id matrix = sources[0];
+ Id columnTypeId = getContainedTypeId(resultTypeId);
+ Id sourceColumnTypeId = getContainedTypeId(getTypeId(matrix));
+
+ std::vector<unsigned> channels;
+ for (int row = 0; row < numRows; ++row)
+ channels.push_back(row);
+
+ std::vector<Id> matrixColumns;
+ for (int col = 0; col < numCols; ++col) {
+ std::vector<unsigned> indexes;
+ indexes.push_back(col);
+ Id colv = createCompositeExtract(matrix, sourceColumnTypeId, indexes);
+ setPrecision(colv, precision);
+
+ if (numRows != getNumRows(matrix)) {
+ matrixColumns.push_back(createRvalueSwizzle(precision, columnTypeId, colv, channels));
+ } else {
+ matrixColumns.push_back(colv);
+ }
+ }
+
+ return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision);
+ }
+
+ // Otherwise, will use a two step process
+ // 1. make a compile-time 2D array of values
+ // 2. construct a matrix from that array
+
+ // Step 1.
+
+ // initialize the array to the identity matrix
+ Id ids[maxMatrixSize][maxMatrixSize];
+ Id one = (bitCount == 64 ? makeDoubleConstant(1.0) : makeFloatConstant(1.0));
+ Id zero = (bitCount == 64 ? makeDoubleConstant(0.0) : makeFloatConstant(0.0));
+ for (int col = 0; col < 4; ++col) {
+ for (int row = 0; row < 4; ++row) {
+ if (col == row)
+ ids[col][row] = one;
+ else
+ ids[col][row] = zero;
+ }
+ }
+
+ // modify components as dictated by the arguments
+ if (sources.size() == 1 && isScalar(sources[0])) {
+ // a single scalar; resets the diagonals
+ for (int col = 0; col < 4; ++col)
+ ids[col][col] = sources[0];
+ } else if (isMatrix(sources[0])) {
+ // constructing from another matrix; copy over the parts that exist in both the argument and constructee
+ Id matrix = sources[0];
+ int minCols = std::min(numCols, getNumColumns(matrix));
+ int minRows = std::min(numRows, getNumRows(matrix));
+ for (int col = 0; col < minCols; ++col) {
+ std::vector<unsigned> indexes;
+ indexes.push_back(col);
+ for (int row = 0; row < minRows; ++row) {
+ indexes.push_back(row);
+ ids[col][row] = createCompositeExtract(matrix, componentTypeId, indexes);
+ indexes.pop_back();
+ setPrecision(ids[col][row], precision);
+ }
+ }
+ } else {
+ // fill in the matrix in column-major order with whatever argument components are available
+ int row = 0;
+ int col = 0;
+
+ for (int arg = 0; arg < (int)sources.size(); ++arg) {
+ Id argComp = sources[arg];
+ for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) {
+ if (getNumComponents(sources[arg]) > 1) {
+ argComp = createCompositeExtract(sources[arg], componentTypeId, comp);
+ setPrecision(argComp, precision);
+ }
+ ids[col][row++] = argComp;
+ if (row == numRows) {
+ row = 0;
+ col++;
+ }
+ }
+ }
+ }
+
+ // Step 2: Construct a matrix from that array.
+ // First make the column vectors, then make the matrix.
+
+ // make the column vectors
+ Id columnTypeId = getContainedTypeId(resultTypeId);
+ std::vector<Id> matrixColumns;
+ for (int col = 0; col < numCols; ++col) {
+ std::vector<Id> vectorComponents;
+ for (int row = 0; row < numRows; ++row)
+ vectorComponents.push_back(ids[col][row]);
+ Id column = createCompositeConstruct(columnTypeId, vectorComponents);
+ setPrecision(column, precision);
+ matrixColumns.push_back(column);
+ }
+
+ // make the matrix
+ return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision);
+}
+
+// Comments in header
+Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) :
+ builder(gb),
+ condition(cond),
+ control(ctrl),
+ elseBlock(0)
+{
+ function = &builder.getBuildPoint()->getParent();
+
+ // make the blocks, but only put the then-block into the function,
+ // the else-block and merge-block will be added later, in order, after
+ // earlier code is emitted
+ thenBlock = new Block(builder.getUniqueId(), *function);
+ mergeBlock = new Block(builder.getUniqueId(), *function);
+
+ // Save the current block, so that we can add in the flow control split when
+ // makeEndIf is called.
+ headerBlock = builder.getBuildPoint();
+
+ function->addBlock(thenBlock);
+ builder.setBuildPoint(thenBlock);
+}
+
+// Comments in header
+void Builder::If::makeBeginElse()
+{
+ // Close out the "then" by having it jump to the mergeBlock
+ builder.createBranch(mergeBlock);
+
+ // Make the first else block and add it to the function
+ elseBlock = new Block(builder.getUniqueId(), *function);
+ function->addBlock(elseBlock);
+
+ // Start building the else block
+ builder.setBuildPoint(elseBlock);
+}
+
+// Comments in header
+void Builder::If::makeEndIf()
+{
+ // jump to the merge block
+ builder.createBranch(mergeBlock);
+
+ // Go back to the headerBlock and make the flow control split
+ builder.setBuildPoint(headerBlock);
+ builder.createSelectionMerge(mergeBlock, control);
+ if (elseBlock)
+ builder.createConditionalBranch(condition, thenBlock, elseBlock);
+ else
+ builder.createConditionalBranch(condition, thenBlock, mergeBlock);
+
+ // add the merge block to the function
+ function->addBlock(mergeBlock);
+ builder.setBuildPoint(mergeBlock);
+}
+
+// Comments in header
+void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, const std::vector<int>& caseValues,
+ const std::vector<int>& valueIndexToSegment, int defaultSegment,
+ std::vector<Block*>& segmentBlocks)
+{
+ Function& function = buildPoint->getParent();
+
+ // make all the blocks
+ for (int s = 0; s < numSegments; ++s)
+ segmentBlocks.push_back(new Block(getUniqueId(), function));
+
+ Block* mergeBlock = new Block(getUniqueId(), function);
+
+ // make and insert the switch's selection-merge instruction
+ createSelectionMerge(mergeBlock, control);
+
+ // make the switch instruction
+ Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
+ switchInst->addIdOperand(selector);
+ auto defaultOrMerge = (defaultSegment >= 0) ? segmentBlocks[defaultSegment] : mergeBlock;
+ switchInst->addIdOperand(defaultOrMerge->getId());
+ defaultOrMerge->addPredecessor(buildPoint);
+ for (int i = 0; i < (int)caseValues.size(); ++i) {
+ switchInst->addImmediateOperand(caseValues[i]);
+ switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId());
+ segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint);
+ }
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(switchInst));
+
+ // push the merge block
+ switchMerges.push(mergeBlock);
+}
+
+// Comments in header
+void Builder::addSwitchBreak()
+{
+ // branch to the top of the merge block stack
+ createBranch(switchMerges.top());
+ createAndSetNoPredecessorBlock("post-switch-break");
+}
+
+// Comments in header
+void Builder::nextSwitchSegment(std::vector<Block*>& segmentBlock, int nextSegment)
+{
+ int lastSegment = nextSegment - 1;
+ if (lastSegment >= 0) {
+ // Close out previous segment by jumping, if necessary, to next segment
+ if (! buildPoint->isTerminated())
+ createBranch(segmentBlock[nextSegment]);
+ }
+ Block* block = segmentBlock[nextSegment];
+ block->getParent().addBlock(block);
+ setBuildPoint(block);
+}
+
+// Comments in header
+void Builder::endSwitch(std::vector<Block*>& /*segmentBlock*/)
+{
+ // Close out previous segment by jumping, if necessary, to next segment
+ if (! buildPoint->isTerminated())
+ addSwitchBreak();
+
+ switchMerges.top()->getParent().addBlock(switchMerges.top());
+ setBuildPoint(switchMerges.top());
+
+ switchMerges.pop();
+}
+
+Block& Builder::makeNewBlock()
+{
+ Function& function = buildPoint->getParent();
+ auto block = new Block(getUniqueId(), function);
+ function.addBlock(block);
+ return *block;
+}
+
+Builder::LoopBlocks& Builder::makeNewLoop()
+{
+ // This verbosity is needed to simultaneously get the same behavior
+ // everywhere (id's in the same order), have a syntax that works
+ // across lots of versions of C++, have no warnings from pedantic
+ // compilation modes, and leave the rest of the code alone.
+ Block& head = makeNewBlock();
+ Block& body = makeNewBlock();
+ Block& merge = makeNewBlock();
+ Block& continue_target = makeNewBlock();
+ LoopBlocks blocks(head, body, merge, continue_target);
+ loops.push(blocks);
+ return loops.top();
+}
+
+void Builder::createLoopContinue()
+{
+ createBranch(&loops.top().continue_target);
+ // Set up a block for dead code.
+ createAndSetNoPredecessorBlock("post-loop-continue");
+}
+
+void Builder::createLoopExit()
+{
+ createBranch(&loops.top().merge);
+ // Set up a block for dead code.
+ createAndSetNoPredecessorBlock("post-loop-break");
+}
+
+void Builder::closeLoop()
+{
+ loops.pop();
+}
+
+void Builder::clearAccessChain()
+{
+ accessChain.base = NoResult;
+ accessChain.indexChain.clear();
+ accessChain.instr = NoResult;
+ accessChain.swizzle.clear();
+ accessChain.component = NoResult;
+ accessChain.preSwizzleBaseType = NoType;
+ accessChain.isRValue = false;
+ accessChain.coherentFlags.clear();
+ accessChain.alignment = 0;
+}
+
+// Comments in header
+void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
+{
+ accessChain.coherentFlags |= coherentFlags;
+ accessChain.alignment |= alignment;
+
+ // swizzles can be stacked in GLSL, but simplified to a single
+ // one here; the base type doesn't change
+ if (accessChain.preSwizzleBaseType == NoType)
+ accessChain.preSwizzleBaseType = preSwizzleBaseType;
+
+ // if needed, propagate the swizzle for the current access chain
+ if (accessChain.swizzle.size() > 0) {
+ std::vector<unsigned> oldSwizzle = accessChain.swizzle;
+ accessChain.swizzle.resize(0);
+ for (unsigned int i = 0; i < swizzle.size(); ++i) {
+ assert(swizzle[i] < oldSwizzle.size());
+ accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]);
+ }
+ } else
+ accessChain.swizzle = swizzle;
+
+ // determine if we need to track this swizzle anymore
+ simplifyAccessChainSwizzle();
+}
+
+// Comments in header
+void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+{
+ assert(accessChain.isRValue == false);
+
+ transferAccessChainSwizzle(true);
+ Id base = collapseAccessChain();
+ Id source = rvalue;
+
+ // dynamic component should be gone
+ assert(accessChain.component == NoResult);
+
+ // If swizzle still exists, it is out-of-order or not full, we must load the target vector,
+ // extract and insert elements to perform writeMask and/or swizzle.
+ if (accessChain.swizzle.size() > 0) {
+ Id tempBaseId = createLoad(base);
+ source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
+ }
+
+ // take LSB of alignment
+ alignment = alignment & ~(alignment & (alignment-1));
+ if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
+ memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
+ }
+
+ createStore(source, base, memoryAccess, scope, alignment);
+}
+
+// Comments in header
+Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+{
+ Id id;
+
+ if (accessChain.isRValue) {
+ // transfer access chain, but try to stay in registers
+ transferAccessChainSwizzle(false);
+ if (accessChain.indexChain.size() > 0) {
+ Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType;
+
+ // if all the accesses are constants, we can use OpCompositeExtract
+ std::vector<unsigned> indexes;
+ bool constant = true;
+ for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) {
+ if (isConstantScalar(accessChain.indexChain[i]))
+ indexes.push_back(getConstantScalar(accessChain.indexChain[i]));
+ else {
+ constant = false;
+ break;
+ }
+ }
+
+ if (constant) {
+ id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
+ } else {
+ Id lValue = NoResult;
+ if (spvVersion >= Spv_1_4) {
+ // make a new function variable for this r-value, using an initializer,
+ // and mark it as NonWritable so that downstream it can be detected as a lookup
+ // table
+ lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable",
+ accessChain.base);
+ addDecoration(lValue, DecorationNonWritable);
+ } else {
+ lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
+ // store into it
+ createStore(accessChain.base, lValue);
+ }
+ // move base to the new variable
+ accessChain.base = lValue;
+ accessChain.isRValue = false;
+
+ // load through the access chain
+ id = createLoad(collapseAccessChain());
+ }
+ setPrecision(id, precision);
+ } else
+ id = accessChain.base; // no precision, it was set when this was defined
+ } else {
+ transferAccessChainSwizzle(true);
+
+ // take LSB of alignment
+ alignment = alignment & ~(alignment & (alignment-1));
+ if (getStorageClass(accessChain.base) == StorageClassPhysicalStorageBufferEXT) {
+ memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
+ }
+
+ // load through the access chain
+ id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
+ setPrecision(id, precision);
+ addDecoration(id, nonUniform);
+ }
+
+ // Done, unless there are swizzles to do
+ if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
+ return id;
+
+ // Do remaining swizzling
+
+ // Do the basic swizzle
+ if (accessChain.swizzle.size() > 0) {
+ Id swizzledType = getScalarTypeId(getTypeId(id));
+ if (accessChain.swizzle.size() > 1)
+ swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size());
+ id = createRvalueSwizzle(precision, swizzledType, id, accessChain.swizzle);
+ }
+
+ // Do the dynamic component
+ if (accessChain.component != NoResult)
+ id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
+
+ addDecoration(id, nonUniform);
+ return id;
+}
+
+Id Builder::accessChainGetLValue()
+{
+ assert(accessChain.isRValue == false);
+
+ transferAccessChainSwizzle(true);
+ Id lvalue = collapseAccessChain();
+
+ // If swizzle exists, it is out-of-order or not full, we must load the target vector,
+ // extract and insert elements to perform writeMask and/or swizzle. This does not
+ // go with getting a direct l-value pointer.
+ assert(accessChain.swizzle.size() == 0);
+ assert(accessChain.component == NoResult);
+
+ return lvalue;
+}
+
+// comment in header
+Id Builder::accessChainGetInferredType()
+{
+ // anything to operate on?
+ if (accessChain.base == NoResult)
+ return NoType;
+ Id type = getTypeId(accessChain.base);
+
+ // do initial dereference
+ if (! accessChain.isRValue)
+ type = getContainedTypeId(type);
+
+ // dereference each index
+ for (auto it = accessChain.indexChain.cbegin(); it != accessChain.indexChain.cend(); ++it) {
+ if (isStructType(type))
+ type = getContainedTypeId(type, getConstantScalar(*it));
+ else
+ type = getContainedTypeId(type);
+ }
+
+ // dereference swizzle
+ if (accessChain.swizzle.size() == 1)
+ type = getContainedTypeId(type);
+ else if (accessChain.swizzle.size() > 1)
+ type = makeVectorType(getContainedTypeId(type), (int)accessChain.swizzle.size());
+
+ // dereference component selection
+ if (accessChain.component)
+ type = getContainedTypeId(type);
+
+ return type;
+}
+
+void Builder::dump(std::vector<unsigned int>& out) const
+{
+ // Header, before first instructions:
+ out.push_back(MagicNumber);
+ out.push_back(spvVersion);
+ out.push_back(builderNumber);
+ out.push_back(uniqueId + 1);
+ out.push_back(0);
+
+ // Capabilities
+ for (auto it = capabilities.cbegin(); it != capabilities.cend(); ++it) {
+ Instruction capInst(0, 0, OpCapability);
+ capInst.addImmediateOperand(*it);
+ capInst.dump(out);
+ }
+
+ for (auto it = extensions.cbegin(); it != extensions.cend(); ++it) {
+ Instruction extInst(0, 0, OpExtension);
+ extInst.addStringOperand(it->c_str());
+ extInst.dump(out);
+ }
+
+ dumpInstructions(out, imports);
+ Instruction memInst(0, 0, OpMemoryModel);
+ memInst.addImmediateOperand(addressModel);
+ memInst.addImmediateOperand(memoryModel);
+ memInst.dump(out);
+
+ // Instructions saved up while building:
+ dumpInstructions(out, entryPoints);
+ dumpInstructions(out, executionModes);
+
+ // Debug instructions
+ dumpInstructions(out, strings);
+ dumpSourceInstructions(out);
+ for (int e = 0; e < (int)sourceExtensions.size(); ++e) {
+ Instruction sourceExtInst(0, 0, OpSourceExtension);
+ sourceExtInst.addStringOperand(sourceExtensions[e]);
+ sourceExtInst.dump(out);
+ }
+ dumpInstructions(out, names);
+ dumpModuleProcesses(out);
+
+ // Annotation instructions
+ dumpInstructions(out, decorations);
+
+ dumpInstructions(out, constantsTypesGlobals);
+ dumpInstructions(out, externals);
+
+ // The functions
+ module.dump(out);
+}
+
+//
+// Protected methods.
+//
+
+// Turn the described access chain in 'accessChain' into an instruction(s)
+// computing its address. This *cannot* include complex swizzles, which must
+// be handled after this is called.
+//
+// Can generate code.
+Id Builder::collapseAccessChain()
+{
+ assert(accessChain.isRValue == false);
+
+ // did we already emit an access chain for this?
+ if (accessChain.instr != NoResult)
+ return accessChain.instr;
+
+ // If we have a dynamic component, we can still transfer
+ // that into a final operand to the access chain. We need to remap the
+ // dynamic component through the swizzle to get a new dynamic component to
+ // update.
+ //
+ // This was not done in transferAccessChainSwizzle() because it might
+ // generate code.
+ remapDynamicSwizzle();
+ if (accessChain.component != NoResult) {
+ // transfer the dynamic component to the access chain
+ accessChain.indexChain.push_back(accessChain.component);
+ accessChain.component = NoResult;
+ }
+
+ // note that non-trivial swizzling is left pending
+
+ // do we have an access chain?
+ if (accessChain.indexChain.size() == 0)
+ return accessChain.base;
+
+ // emit the access chain
+ StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
+ accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
+
+ return accessChain.instr;
+}
+
+// For a dynamic component selection of a swizzle.
+//
+// Turn the swizzle and dynamic component into just a dynamic component.
+//
+// Generates code.
+void Builder::remapDynamicSwizzle()
+{
+ // do we have a swizzle to remap a dynamic component through?
+ if (accessChain.component != NoResult && accessChain.swizzle.size() > 1) {
+ // build a vector of the swizzle for the component to map into
+ std::vector<Id> components;
+ for (int c = 0; c < (int)accessChain.swizzle.size(); ++c)
+ components.push_back(makeUintConstant(accessChain.swizzle[c]));
+ Id mapType = makeVectorType(makeUintType(32), (int)accessChain.swizzle.size());
+ Id map = makeCompositeConstant(mapType, components);
+
+ // use it
+ accessChain.component = createVectorExtractDynamic(map, makeUintType(32), accessChain.component);
+ accessChain.swizzle.clear();
+ }
+}
+
+// clear out swizzle if it is redundant, that is reselecting the same components
+// that would be present without the swizzle.
+void Builder::simplifyAccessChainSwizzle()
+{
+ // If the swizzle has fewer components than the vector, it is subsetting, and must stay
+ // to preserve that fact.
+ if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size())
+ return;
+
+ // if components are out of order, it is a swizzle
+ for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) {
+ if (i != accessChain.swizzle[i])
+ return;
+ }
+
+ // otherwise, there is no need to track this swizzle
+ accessChain.swizzle.clear();
+ if (accessChain.component == NoResult)
+ accessChain.preSwizzleBaseType = NoType;
+}
+
+// To the extent any swizzling can become part of the chain
+// of accesses instead of a post operation, make it so.
+// If 'dynamic' is true, include transferring the dynamic component,
+// otherwise, leave it pending.
+//
+// Does not generate code. just updates the access chain.
+void Builder::transferAccessChainSwizzle(bool dynamic)
+{
+ // non existent?
+ if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
+ return;
+
+ // too complex?
+ // (this requires either a swizzle, or generating code for a dynamic component)
+ if (accessChain.swizzle.size() > 1)
+ return;
+
+ // single component, either in the swizzle and/or dynamic component
+ if (accessChain.swizzle.size() == 1) {
+ assert(accessChain.component == NoResult);
+ // handle static component selection
+ accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
+ accessChain.swizzle.clear();
+ accessChain.preSwizzleBaseType = NoType;
+ } else if (dynamic && accessChain.component != NoResult) {
+ assert(accessChain.swizzle.size() == 0);
+ // handle dynamic component
+ accessChain.indexChain.push_back(accessChain.component);
+ accessChain.preSwizzleBaseType = NoType;
+ accessChain.component = NoResult;
+ }
+}
+
+// Utility method for creating a new block and setting the insert point to
+// be in it. This is useful for flow-control operations that need a "dummy"
+// block proceeding them (e.g. instructions after a discard, etc).
+void Builder::createAndSetNoPredecessorBlock(const char* /*name*/)
+{
+ Block* block = new Block(getUniqueId(), buildPoint->getParent());
+ block->setUnreachable();
+ buildPoint->getParent().addBlock(block);
+ setBuildPoint(block);
+
+ // if (name)
+ // addName(block->getId(), name);
+}
+
+// Comments in header
+void Builder::createBranch(Block* block)
+{
+ Instruction* branch = new Instruction(OpBranch);
+ branch->addIdOperand(block->getId());
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(branch));
+ block->addPredecessor(buildPoint);
+}
+
+void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
+{
+ Instruction* merge = new Instruction(OpSelectionMerge);
+ merge->addIdOperand(mergeBlock->getId());
+ merge->addImmediateOperand(control);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
+}
+
+void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
+ const std::vector<unsigned int>& operands)
+{
+ Instruction* merge = new Instruction(OpLoopMerge);
+ merge->addIdOperand(mergeBlock->getId());
+ merge->addIdOperand(continueBlock->getId());
+ merge->addImmediateOperand(control);
+ for (int op = 0; op < (int)operands.size(); ++op)
+ merge->addImmediateOperand(operands[op]);
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
+}
+
+void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock)
+{
+ Instruction* branch = new Instruction(OpBranchConditional);
+ branch->addIdOperand(condition);
+ branch->addIdOperand(thenBlock->getId());
+ branch->addIdOperand(elseBlock->getId());
+ buildPoint->addInstruction(std::unique_ptr<Instruction>(branch));
+ thenBlock->addPredecessor(buildPoint);
+ elseBlock->addPredecessor(buildPoint);
+}
+
+// OpSource
+// [OpSourceContinued]
+// ...
+void Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& text,
+ std::vector<unsigned int>& out) const
+{
+ const int maxWordCount = 0xFFFF;
+ const int opSourceWordCount = 4;
+ const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1;
+
+ if (source != SourceLanguageUnknown) {
+ // OpSource Language Version File Source
+ Instruction sourceInst(NoResult, NoType, OpSource);
+ sourceInst.addImmediateOperand(source);
+ sourceInst.addImmediateOperand(sourceVersion);
+ // File operand
+ if (fileId != NoResult) {
+ sourceInst.addIdOperand(fileId);
+ // Source operand
+ if (text.size() > 0) {
+ int nextByte = 0;
+ std::string subString;
+ while ((int)text.size() - nextByte > 0) {
+ subString = text.substr(nextByte, nonNullBytesPerInstruction);
+ if (nextByte == 0) {
+ // OpSource
+ sourceInst.addStringOperand(subString.c_str());
+ sourceInst.dump(out);
+ } else {
+ // OpSourcContinued
+ Instruction sourceContinuedInst(OpSourceContinued);
+ sourceContinuedInst.addStringOperand(subString.c_str());
+ sourceContinuedInst.dump(out);
+ }
+ nextByte += nonNullBytesPerInstruction;
+ }
+ } else
+ sourceInst.dump(out);
+ } else
+ sourceInst.dump(out);
+ }
+}
+
+// Dump an OpSource[Continued] sequence for the source and every include file
+void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
+{
+ dumpSourceInstructions(sourceFileStringId, sourceText, out);
+ for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr)
+ dumpSourceInstructions(iItr->first, *iItr->second, out);
+}
+
+void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
+{
+ for (int i = 0; i < (int)instructions.size(); ++i) {
+ instructions[i]->dump(out);
+ }
+}
+
+void Builder::dumpModuleProcesses(std::vector<unsigned int>& out) const
+{
+ for (int i = 0; i < (int)moduleProcesses.size(); ++i) {
+ Instruction moduleProcessed(OpModuleProcessed);
+ moduleProcessed.addStringOperand(moduleProcesses[i]);
+ moduleProcessed.dump(out);
+ }
+}
+
+}; // end spv namespace
diff --git a/thirdparty/glslang/SPIRV/SpvBuilder.h b/thirdparty/glslang/SPIRV/SpvBuilder.h
new file mode 100644
index 0000000000..31fee975fc
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/SpvBuilder.h
@@ -0,0 +1,790 @@
+//
+// Copyright (C) 2014-2015 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// "Builder" is an interface to fully build SPIR-V IR. Allocate one of
+// these to build (a thread safe) internal SPIR-V representation (IR),
+// and then dump it as a binary stream according to the SPIR-V specification.
+//
+// A Builder has a 1:1 relationship with a SPIR-V module.
+//
+
+#pragma once
+#ifndef SpvBuilder_H
+#define SpvBuilder_H
+
+#include "Logger.h"
+#include "spirv.hpp"
+#include "spvIR.h"
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <stack>
+#include <unordered_map>
+#include <map>
+
+namespace spv {
+
+typedef enum {
+ Spv_1_0 = (1 << 16),
+ Spv_1_1 = (1 << 16) | (1 << 8),
+ Spv_1_2 = (1 << 16) | (2 << 8),
+ Spv_1_3 = (1 << 16) | (3 << 8),
+ Spv_1_4 = (1 << 16) | (4 << 8),
+ Spv_1_5 = (1 << 16) | (5 << 8),
+} SpvVersion;
+
+class Builder {
+public:
+ Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger);
+ virtual ~Builder();
+
+ static const int maxMatrixSize = 4;
+
+ unsigned int getSpvVersion() const { return spvVersion; }
+
+ void setSource(spv::SourceLanguage lang, int version)
+ {
+ source = lang;
+ sourceVersion = version;
+ }
+ spv::Id getStringId(const std::string& str)
+ {
+ auto sItr = stringIds.find(str);
+ if (sItr != stringIds.end())
+ return sItr->second;
+ spv::Id strId = getUniqueId();
+ Instruction* fileString = new Instruction(strId, NoType, OpString);
+ const char* file_c_str = str.c_str();
+ fileString->addStringOperand(file_c_str);
+ strings.push_back(std::unique_ptr<Instruction>(fileString));
+ stringIds[file_c_str] = strId;
+ return strId;
+ }
+ void setSourceFile(const std::string& file)
+ {
+ sourceFileStringId = getStringId(file);
+ }
+ void setSourceText(const std::string& text) { sourceText = text; }
+ void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
+ void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
+ void setEmitOpLines() { emitOpLines = true; }
+ void addExtension(const char* ext) { extensions.insert(ext); }
+ void removeExtension(const char* ext)
+ {
+ extensions.erase(ext);
+ }
+ void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion)
+ {
+ if (getSpvVersion() < static_cast<unsigned>(incorporatedVersion))
+ addExtension(ext);
+ }
+ void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion)
+ {
+ removeExtension(baseExt);
+ addIncorporatedExtension(promoExt, incorporatedVersion);
+ }
+ void addInclude(const std::string& name, const std::string& text)
+ {
+ spv::Id incId = getStringId(name);
+ includeFiles[incId] = &text;
+ }
+ Id import(const char*);
+ void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
+ {
+ addressModel = addr;
+ memoryModel = mem;
+ }
+
+ void addCapability(spv::Capability cap) { capabilities.insert(cap); }
+
+ // To get a new <id> for anything needing a new one.
+ Id getUniqueId() { return ++uniqueId; }
+
+ // To get a set of new <id>s, e.g., for a set of function parameters
+ Id getUniqueIds(int numIds)
+ {
+ Id id = uniqueId + 1;
+ uniqueId += numIds;
+ return id;
+ }
+
+ // Generate OpLine for non-filename-based #line directives (ie no filename
+ // seen yet): Log the current line, and if different than the last one,
+ // issue a new OpLine using the new line and current source file name.
+ void setLine(int line);
+
+ // If filename null, generate OpLine for non-filename-based line directives,
+ // else do filename-based: Log the current line and file, and if different
+ // than the last one, issue a new OpLine using the new line and file
+ // name.
+ void setLine(int line, const char* filename);
+ // Low-level OpLine. See setLine() for a layered helper.
+ void addLine(Id fileName, int line, int column);
+
+ // For creating new types (will return old type if the requested one was already made).
+ Id makeVoidType();
+ Id makeBoolType();
+ Id makePointer(StorageClass, Id pointee);
+ Id makeForwardPointer(StorageClass);
+ Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee);
+ Id makeIntegerType(int width, bool hasSign); // generic
+ Id makeIntType(int width) { return makeIntegerType(width, true); }
+ Id makeUintType(int width) { return makeIntegerType(width, false); }
+ Id makeFloatType(int width);
+ Id makeStructType(const std::vector<Id>& members, const char*);
+ Id makeStructResultType(Id type0, Id type1);
+ Id makeVectorType(Id component, int size);
+ Id makeMatrixType(Id component, int cols, int rows);
+ Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration
+ Id makeRuntimeArray(Id element);
+ Id makeFunctionType(Id returnType, const std::vector<Id>& paramTypes);
+ Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
+ Id makeSamplerType();
+ Id makeSampledImageType(Id imageType);
+ Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
+
+ // accelerationStructureNV type
+ Id makeAccelerationStructureNVType();
+
+ // For querying about types.
+ Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
+ Id getDerefTypeId(Id resultId) const;
+ Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); }
+ Op getTypeClass(Id typeId) const { return getOpCode(typeId); }
+ Op getMostBasicTypeClass(Id typeId) const;
+ int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
+ int getNumTypeConstituents(Id typeId) const;
+ int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); }
+ Id getScalarTypeId(Id typeId) const;
+ Id getContainedTypeId(Id typeId) const;
+ Id getContainedTypeId(Id typeId, int) const;
+ StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
+ ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
+
+ bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
+ bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
+ bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); }
+ bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); }
+ bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); }
+ bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
+ bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
+
+ bool isBoolType(Id typeId) { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
+ bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
+ bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
+ bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; }
+ bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
+ bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
+ bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
+ bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; }
+ bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; }
+ bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; }
+#ifdef GLSLANG_WEB
+ bool isCooperativeMatrixType(Id typeId)const { return false; }
+#else
+ bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; }
+#endif
+ bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
+ bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
+ bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
+ bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
+ bool containsType(Id typeId, Op typeOp, unsigned int width) const;
+ bool containsPhysicalStorageBufferOrArray(Id typeId) const;
+
+ bool isConstantOpCode(Op opcode) const;
+ bool isSpecConstantOpCode(Op opcode) const;
+ bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
+ bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
+ bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
+ unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
+ StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
+
+ int getScalarTypeWidth(Id typeId) const
+ {
+ Id scalarTypeId = getScalarTypeId(typeId);
+ assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat);
+ return module.getInstruction(scalarTypeId)->getImmediateOperand(0);
+ }
+
+ int getTypeNumColumns(Id typeId) const
+ {
+ assert(isMatrixType(typeId));
+ return getNumTypeConstituents(typeId);
+ }
+ int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
+ int getTypeNumRows(Id typeId) const
+ {
+ assert(isMatrixType(typeId));
+ return getNumTypeComponents(getContainedTypeId(typeId));
+ }
+ int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
+
+ Dim getTypeDimensionality(Id typeId) const
+ {
+ assert(isImageType(typeId));
+ return (Dim)module.getInstruction(typeId)->getImmediateOperand(1);
+ }
+ Id getImageType(Id resultId) const
+ {
+ Id typeId = getTypeId(resultId);
+ assert(isImageType(typeId) || isSampledImageType(typeId));
+ return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId;
+ }
+ bool isArrayedImageType(Id typeId) const
+ {
+ assert(isImageType(typeId));
+ return module.getInstruction(typeId)->getImmediateOperand(3) != 0;
+ }
+
+ // For making new constants (will return old constant if the requested one was already made).
+ Id makeBoolConstant(bool b, bool specConstant = false);
+ Id makeInt8Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
+ Id makeUint8Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(8), u, specConstant); }
+ Id makeInt16Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
+ Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16), u, specConstant); }
+ Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
+ Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); }
+ Id makeInt64Constant(long long i, bool specConstant = false) { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
+ Id makeUint64Constant(unsigned long long u, bool specConstant = false) { return makeInt64Constant(makeUintType(64), u, specConstant); }
+ Id makeFloatConstant(float f, bool specConstant = false);
+ Id makeDoubleConstant(double d, bool specConstant = false);
+ Id makeFloat16Constant(float f16, bool specConstant = false);
+ Id makeFpConstant(Id type, double d, bool specConstant = false);
+
+ // Turn the array of constants into a proper spv constant of the requested type.
+ Id makeCompositeConstant(Id type, const std::vector<Id>& comps, bool specConst = false);
+
+ // Methods for adding information outside the CFG.
+ Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
+ void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
+ void addName(Id, const char* name);
+ void addMemberName(Id, int member, const char* name);
+ void addDecoration(Id, Decoration, int num = -1);
+ void addDecoration(Id, Decoration, const char*);
+ void addDecorationId(Id id, Decoration, Id idDecoration);
+ void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
+ void addMemberDecoration(Id, unsigned int member, Decoration, const char*);
+
+ // At the end of what block do the next create*() instructions go?
+ void setBuildPoint(Block* bp) { buildPoint = bp; }
+ Block* getBuildPoint() const { return buildPoint; }
+
+ // Make the entry-point function. The returned pointer is only valid
+ // for the lifetime of this builder.
+ Function* makeEntryPoint(const char*);
+
+ // Make a shader-style function, and create its entry block if entry is non-zero.
+ // Return the function, pass back the entry.
+ // The returned pointer is only valid for the lifetime of this builder.
+ Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
+ const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
+
+ // Create a return. An 'implicit' return is one not appearing in the source
+ // code. In the case of an implicit return, no post-return block is inserted.
+ void makeReturn(bool implicit, Id retVal = 0);
+
+ // Generate all the code needed to finish up a function.
+ void leaveFunction();
+
+ // Create a discard.
+ void makeDiscard();
+
+ // Create a global or function local or IO variable.
+ Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult);
+
+ // Create an intermediate with an undefined value.
+ Id createUndefined(Id type);
+
+ // Store into an Id and return the l-value
+ void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+
+ // Load from an Id and return it
+ Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+
+ // Create an OpAccessChain instruction
+ Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
+
+ // Create an OpArrayLength instruction
+ Id createArrayLength(Id base, unsigned int member);
+
+ // Create an OpCooperativeMatrixLengthNV instruction
+ Id createCooperativeMatrixLength(Id type);
+
+ // Create an OpCompositeExtract instruction
+ Id createCompositeExtract(Id composite, Id typeId, unsigned index);
+ Id createCompositeExtract(Id composite, Id typeId, const std::vector<unsigned>& indexes);
+ Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
+ Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector<unsigned>& indexes);
+
+ Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex);
+ Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex);
+
+ void createNoResultOp(Op);
+ void createNoResultOp(Op, Id operand);
+ void createNoResultOp(Op, const std::vector<Id>& operands);
+ void createNoResultOp(Op, const std::vector<IdImmediate>& operands);
+ void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask);
+ void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics);
+ Id createUnaryOp(Op, Id typeId, Id operand);
+ Id createBinOp(Op, Id typeId, Id operand1, Id operand2);
+ Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
+ Id createOp(Op, Id typeId, const std::vector<Id>& operands);
+ Id createOp(Op, Id typeId, const std::vector<IdImmediate>& operands);
+ Id createFunctionCall(spv::Function*, const std::vector<spv::Id>&);
+ Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals);
+
+ // Take an rvalue (source) and a set of channels to extract from it to
+ // make a new rvalue, which is returned.
+ Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector<unsigned>& channels);
+
+ // Take a copy of an lvalue (target) and a source of components, and set the
+ // source components into the lvalue where the 'channels' say to put them.
+ // An updated version of the target is returned.
+ // (No true lvalue or stores are used.)
+ Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector<unsigned>& channels);
+
+ // If both the id and precision are valid, the id
+ // gets tagged with the requested precision.
+ // The passed in id is always the returned id, to simplify use patterns.
+ Id setPrecision(Id id, Decoration precision)
+ {
+ if (precision != NoPrecision && id != NoResult)
+ addDecoration(id, precision);
+
+ return id;
+ }
+
+ // Can smear a scalar to a vector for the following forms:
+ // - promoteScalar(scalar, vector) // smear scalar to width of vector
+ // - promoteScalar(vector, scalar) // smear scalar to width of vector
+ // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to
+ // - promoteScalar(scalar, scalar) // do nothing
+ // Other forms are not allowed.
+ //
+ // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'.
+ // The type of the created vector is a vector of components of the same type as the scalar.
+ //
+ // Note: One of the arguments will change, with the result coming back that way rather than
+ // through the return value.
+ void promoteScalar(Decoration precision, Id& left, Id& right);
+
+ // Make a value by smearing the scalar to fill the type.
+ // vectorType should be the correct type for making a vector of scalarVal.
+ // (No conversions are done.)
+ Id smearScalar(Decoration precision, Id scalarVal, Id vectorType);
+
+ // Create a call to a built-in function.
+ Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector<Id>& args);
+
+ // List of parameters used to create a texture operation
+ struct TextureParameters {
+ Id sampler;
+ Id coords;
+ Id bias;
+ Id lod;
+ Id Dref;
+ Id offset;
+ Id offsets;
+ Id gradX;
+ Id gradY;
+ Id sample;
+ Id component;
+ Id texelOut;
+ Id lodClamp;
+ Id granularity;
+ Id coarse;
+ bool nonprivate;
+ bool volatil;
+ };
+
+ // Select the correct texture operation based on all inputs, and emit the correct instruction
+ Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
+ bool noImplicit, const TextureParameters&, ImageOperandsMask);
+
+ // Emit the OpTextureQuery* instruction that was passed in.
+ // Figure out the right return value and type, and return it.
+ Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult);
+
+ Id createSamplePositionCall(Decoration precision, Id, Id);
+
+ Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned);
+ Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id);
+
+ // Reduction comparison for composites: For equal and not-equal resulting in a scalar.
+ Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */);
+
+ // OpCompositeConstruct
+ Id createCompositeConstruct(Id typeId, const std::vector<Id>& constituents);
+
+ // vector or scalar constructor
+ Id createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId);
+
+ // matrix constructor
+ Id createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id constructee);
+
+ // Helper to use for building nested control flow with if-then-else.
+ class If {
+ public:
+ If(Id condition, unsigned int ctrl, Builder& builder);
+ ~If() {}
+
+ void makeBeginElse();
+ void makeEndIf();
+
+ private:
+ If(const If&);
+ If& operator=(If&);
+
+ Builder& builder;
+ Id condition;
+ unsigned int control;
+ Function* function;
+ Block* headerBlock;
+ Block* thenBlock;
+ Block* elseBlock;
+ Block* mergeBlock;
+ };
+
+ // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing
+ // any case/default labels, all separated by one or more case/default labels. Each possible
+ // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this
+ // number space. How to compute the value is given by 'condition', as in switch(condition).
+ //
+ // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches.
+ //
+ // Use a defaultSegment < 0 if there is no default segment (to branch to post switch).
+ //
+ // Returns the right set of basic blocks to start each code segment with, so that the caller's
+ // recursion stack can hold the memory for it.
+ //
+ void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
+ const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument
+
+ // Add a branch to the innermost switch's merge block.
+ void addSwitchBreak();
+
+ // Move to the next code segment, passing in the return argument in makeSwitch()
+ void nextSwitchSegment(std::vector<Block*>& segmentBB, int segment);
+
+ // Finish off the innermost switch.
+ void endSwitch(std::vector<Block*>& segmentBB);
+
+ struct LoopBlocks {
+ LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) :
+ head(head), body(body), merge(merge), continue_target(continue_target) { }
+ Block &head, &body, &merge, &continue_target;
+ private:
+ LoopBlocks();
+ LoopBlocks& operator=(const LoopBlocks&);
+ };
+
+ // Start a new loop and prepare the builder to generate code for it. Until
+ // closeLoop() is called for this loop, createLoopContinue() and
+ // createLoopExit() will target its corresponding blocks.
+ LoopBlocks& makeNewLoop();
+
+ // Create a new block in the function containing the build point. Memory is
+ // owned by the function object.
+ Block& makeNewBlock();
+
+ // Add a branch to the continue_target of the current (innermost) loop.
+ void createLoopContinue();
+
+ // Add an exit (e.g. "break") from the innermost loop that we're currently
+ // in.
+ void createLoopExit();
+
+ // Close the innermost loop that you're in
+ void closeLoop();
+
+ //
+ // Access chain design for an R-Value vs. L-Value:
+ //
+ // There is a single access chain the builder is building at
+ // any particular time. Such a chain can be used to either to a load or
+ // a store, when desired.
+ //
+ // Expressions can be r-values, l-values, or both, or only r-values:
+ // a[b.c].d = .... // l-value
+ // ... = a[b.c].d; // r-value, that also looks like an l-value
+ // ++a[b.c].d; // r-value and l-value
+ // (x + y)[2]; // r-value only, can't possibly be l-value
+ //
+ // Computing an r-value means generating code. Hence,
+ // r-values should only be computed when they are needed, not speculatively.
+ //
+ // Computing an l-value means saving away information for later use in the compiler,
+ // no code is generated until the l-value is later dereferenced. It is okay
+ // to speculatively generate an l-value, just not okay to speculatively dereference it.
+ //
+ // The base of the access chain (the left-most variable or expression
+ // from which everything is based) can be set either as an l-value
+ // or as an r-value. Most efficient would be to set an l-value if one
+ // is available. If an expression was evaluated, the resulting r-value
+ // can be set as the chain base.
+ //
+ // The users of this single access chain can save and restore if they
+ // want to nest or manage multiple chains.
+ //
+
+ struct AccessChain {
+ Id base; // for l-values, pointer to the base object, for r-values, the base object
+ std::vector<Id> indexChain;
+ Id instr; // cache the instruction that generates this access chain
+ std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
+ Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
+ Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
+ bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value
+ unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. Only tracks base and (optional) component selection alignment.
+
+ // Accumulate whether anything in the chain of structures has coherent decorations.
+ struct CoherentFlags {
+ CoherentFlags() { clear(); }
+#ifdef GLSLANG_WEB
+ void clear() { }
+ bool isVolatile() const { return false; }
+ CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
+#else
+ bool isVolatile() const { return volatil; }
+
+ unsigned coherent : 1;
+ unsigned devicecoherent : 1;
+ unsigned queuefamilycoherent : 1;
+ unsigned workgroupcoherent : 1;
+ unsigned subgroupcoherent : 1;
+ unsigned nonprivate : 1;
+ unsigned volatil : 1;
+ unsigned isImage : 1;
+
+ void clear() {
+ coherent = 0;
+ devicecoherent = 0;
+ queuefamilycoherent = 0;
+ workgroupcoherent = 0;
+ subgroupcoherent = 0;
+ nonprivate = 0;
+ volatil = 0;
+ isImage = 0;
+ }
+
+ CoherentFlags operator |=(const CoherentFlags &other) {
+ coherent |= other.coherent;
+ devicecoherent |= other.devicecoherent;
+ queuefamilycoherent |= other.queuefamilycoherent;
+ workgroupcoherent |= other.workgroupcoherent;
+ subgroupcoherent |= other.subgroupcoherent;
+ nonprivate |= other.nonprivate;
+ volatil |= other.volatil;
+ isImage |= other.isImage;
+ return *this;
+ }
+#endif
+ };
+ CoherentFlags coherentFlags;
+ };
+
+ //
+ // the SPIR-V builder maintains a single active chain that
+ // the following methods operate on
+ //
+
+ // for external save and restore
+ AccessChain getAccessChain() { return accessChain; }
+ void setAccessChain(AccessChain newChain) { accessChain = newChain; }
+
+ // clear accessChain
+ void clearAccessChain();
+
+ // set new base as an l-value base
+ void setAccessChainLValue(Id lValue)
+ {
+ assert(isPointer(lValue));
+ accessChain.base = lValue;
+ }
+
+ // set new base value as an r-value
+ void setAccessChainRValue(Id rValue)
+ {
+ accessChain.isRValue = true;
+ accessChain.base = rValue;
+ }
+
+ // push offset onto the end of the chain
+ void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
+ {
+ accessChain.indexChain.push_back(offset);
+ accessChain.coherentFlags |= coherentFlags;
+ accessChain.alignment |= alignment;
+ }
+
+ // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
+ void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
+
+ // push a dynamic component selection onto the access chain, only applicable with a
+ // non-trivial swizzle or no swizzle
+ void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
+ {
+ if (accessChain.swizzle.size() != 1) {
+ accessChain.component = component;
+ if (accessChain.preSwizzleBaseType == NoType)
+ accessChain.preSwizzleBaseType = preSwizzleBaseType;
+ }
+ accessChain.coherentFlags |= coherentFlags;
+ accessChain.alignment |= alignment;
+ }
+
+ // use accessChain and swizzle to store value
+ void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+
+ // use accessChain and swizzle to load an r-value
+ Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+
+ // get the direct pointer for an l-value
+ Id accessChainGetLValue();
+
+ // Get the inferred SPIR-V type of the result of the current access chain,
+ // based on the type of the base and the chain of dereferences.
+ Id accessChainGetInferredType();
+
+ // Add capabilities, extensions, remove unneeded decorations, etc.,
+ // based on the resulting SPIR-V.
+ void postProcess();
+
+ // Prune unreachable blocks in the CFG and remove unneeded decorations.
+ void postProcessCFG();
+
+#ifndef GLSLANG_WEB
+ // Add capabilities, extensions based on instructions in the module.
+ void postProcessFeatures();
+ // Hook to visit each instruction in a block in a function
+ void postProcess(Instruction&);
+ // Hook to visit each non-32-bit sized float/int operation in a block.
+ void postProcessType(const Instruction&, spv::Id typeId);
+#endif
+
+ void dump(std::vector<unsigned int>&) const;
+
+ void createBranch(Block* block);
+ void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
+ void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, const std::vector<unsigned int>& operands);
+
+ // Sets to generate opcode for specialization constants.
+ void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
+ // Sets to generate opcode for non-specialization constants (normal mode).
+ void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; }
+ // Check if the builder is generating code for spec constants.
+ bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; }
+
+ protected:
+ Id makeIntConstant(Id typeId, unsigned value, bool specConstant);
+ Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant);
+ Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value);
+ Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2);
+ Id findCompositeConstant(Op typeClass, Id typeId, const std::vector<Id>& comps);
+ Id findStructConstant(Id typeId, const std::vector<Id>& comps);
+ Id collapseAccessChain();
+ void remapDynamicSwizzle();
+ void transferAccessChainSwizzle(bool dynamic);
+ void simplifyAccessChainSwizzle();
+ void createAndSetNoPredecessorBlock(const char*);
+ void createSelectionMerge(Block* mergeBlock, unsigned int control);
+ void dumpSourceInstructions(std::vector<unsigned int>&) const;
+ void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
+ void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
+ void dumpModuleProcesses(std::vector<unsigned int>&) const;
+ spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const;
+
+ unsigned int spvVersion; // the version of SPIR-V to emit in the header
+ SourceLanguage source;
+ int sourceVersion;
+ spv::Id sourceFileStringId;
+ std::string sourceText;
+ int currentLine;
+ const char* currentFile;
+ bool emitOpLines;
+ std::set<std::string> extensions;
+ std::vector<const char*> sourceExtensions;
+ std::vector<const char*> moduleProcesses;
+ AddressingModel addressModel;
+ MemoryModel memoryModel;
+ std::set<spv::Capability> capabilities;
+ int builderNumber;
+ Module module;
+ Block* buildPoint;
+ Id uniqueId;
+ Function* entryPointFunction;
+ bool generatingOpCodeForSpecConst;
+ AccessChain accessChain;
+
+ // special blocks of instructions for output
+ std::vector<std::unique_ptr<Instruction> > strings;
+ std::vector<std::unique_ptr<Instruction> > imports;
+ std::vector<std::unique_ptr<Instruction> > entryPoints;
+ std::vector<std::unique_ptr<Instruction> > executionModes;
+ std::vector<std::unique_ptr<Instruction> > names;
+ std::vector<std::unique_ptr<Instruction> > decorations;
+ std::vector<std::unique_ptr<Instruction> > constantsTypesGlobals;
+ std::vector<std::unique_ptr<Instruction> > externals;
+ std::vector<std::unique_ptr<Function> > functions;
+
+ // not output, internally used for quick & dirty canonical (unique) creation
+ std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants; // map type opcodes to constant inst.
+ std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants; // map struct-id to constant instructions
+ std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes; // map type opcodes to type instructions
+
+ // stack of switches
+ std::stack<Block*> switchMerges;
+
+ // Our loop stack.
+ std::stack<LoopBlocks> loops;
+
+ // map from strings to their string ids
+ std::unordered_map<std::string, spv::Id> stringIds;
+
+ // map from include file name ids to their contents
+ std::map<spv::Id, const std::string*> includeFiles;
+
+ // The stream for outputting warnings and errors.
+ SpvBuildLogger* logger;
+}; // end Builder class
+
+}; // end spv namespace
+
+#endif // SpvBuilder_H
diff --git a/thirdparty/glslang/SPIRV/SpvPostProcess.cpp b/thirdparty/glslang/SPIRV/SpvPostProcess.cpp
new file mode 100644
index 0000000000..d40174d172
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/SpvPostProcess.cpp
@@ -0,0 +1,450 @@
+//
+// Copyright (C) 2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Post-processing for SPIR-V IR, in internal form, not standard binary form.
+//
+
+#include <cassert>
+#include <cstdlib>
+
+#include <unordered_map>
+#include <unordered_set>
+#include <algorithm>
+
+#include "SpvBuilder.h"
+
+#include "spirv.hpp"
+#include "GlslangToSpv.h"
+#include "SpvBuilder.h"
+namespace spv {
+ #include "GLSL.std.450.h"
+ #include "GLSL.ext.KHR.h"
+ #include "GLSL.ext.EXT.h"
+ #include "GLSL.ext.AMD.h"
+ #include "GLSL.ext.NV.h"
+}
+
+namespace spv {
+
+#ifndef GLSLANG_WEB
+// Hook to visit each operand type and result type of an instruction.
+// Will be called multiple times for one instruction, once for each typed
+// operand and the result.
+void Builder::postProcessType(const Instruction& inst, Id typeId)
+{
+ // Characterize the type being questioned
+ Id basicTypeOp = getMostBasicTypeClass(typeId);
+ int width = 0;
+ if (basicTypeOp == OpTypeFloat || basicTypeOp == OpTypeInt)
+ width = getScalarTypeWidth(typeId);
+
+ // Do opcode-specific checks
+ switch (inst.getOpCode()) {
+ case OpLoad:
+ case OpStore:
+ if (basicTypeOp == OpTypeStruct) {
+ if (containsType(typeId, OpTypeInt, 8))
+ addCapability(CapabilityInt8);
+ if (containsType(typeId, OpTypeInt, 16))
+ addCapability(CapabilityInt16);
+ if (containsType(typeId, OpTypeFloat, 16))
+ addCapability(CapabilityFloat16);
+ } else {
+ StorageClass storageClass = getStorageClass(inst.getIdOperand(0));
+ if (width == 8) {
+ switch (storageClass) {
+ case StorageClassPhysicalStorageBufferEXT:
+ case StorageClassUniform:
+ case StorageClassStorageBuffer:
+ case StorageClassPushConstant:
+ break;
+ default:
+ addCapability(CapabilityInt8);
+ break;
+ }
+ } else if (width == 16) {
+ switch (storageClass) {
+ case StorageClassPhysicalStorageBufferEXT:
+ case StorageClassUniform:
+ case StorageClassStorageBuffer:
+ case StorageClassPushConstant:
+ case StorageClassInput:
+ case StorageClassOutput:
+ break;
+ default:
+ if (basicTypeOp == OpTypeInt)
+ addCapability(CapabilityInt16);
+ if (basicTypeOp == OpTypeFloat)
+ addCapability(CapabilityFloat16);
+ break;
+ }
+ }
+ }
+ break;
+ case OpAccessChain:
+ case OpPtrAccessChain:
+ case OpCopyObject:
+ break;
+ case OpFConvert:
+ case OpSConvert:
+ case OpUConvert:
+ // Look for any 8/16-bit storage capabilities. If there are none, assume that
+ // the convert instruction requires the Float16/Int8/16 capability.
+ if (containsType(typeId, OpTypeFloat, 16) || containsType(typeId, OpTypeInt, 16)) {
+ bool foundStorage = false;
+ for (auto it = capabilities.begin(); it != capabilities.end(); ++it) {
+ spv::Capability cap = *it;
+ if (cap == spv::CapabilityStorageInputOutput16 ||
+ cap == spv::CapabilityStoragePushConstant16 ||
+ cap == spv::CapabilityStorageUniformBufferBlock16 ||
+ cap == spv::CapabilityStorageUniform16) {
+ foundStorage = true;
+ break;
+ }
+ }
+ if (!foundStorage) {
+ if (containsType(typeId, OpTypeFloat, 16))
+ addCapability(CapabilityFloat16);
+ if (containsType(typeId, OpTypeInt, 16))
+ addCapability(CapabilityInt16);
+ }
+ }
+ if (containsType(typeId, OpTypeInt, 8)) {
+ bool foundStorage = false;
+ for (auto it = capabilities.begin(); it != capabilities.end(); ++it) {
+ spv::Capability cap = *it;
+ if (cap == spv::CapabilityStoragePushConstant8 ||
+ cap == spv::CapabilityUniformAndStorageBuffer8BitAccess ||
+ cap == spv::CapabilityStorageBuffer8BitAccess) {
+ foundStorage = true;
+ break;
+ }
+ }
+ if (!foundStorage) {
+ addCapability(CapabilityInt8);
+ }
+ }
+ break;
+ case OpExtInst:
+ switch (inst.getImmediateOperand(1)) {
+ case GLSLstd450Frexp:
+ case GLSLstd450FrexpStruct:
+ if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeInt, 16))
+ addExtension(spv::E_SPV_AMD_gpu_shader_int16);
+ break;
+ case GLSLstd450InterpolateAtCentroid:
+ case GLSLstd450InterpolateAtSample:
+ case GLSLstd450InterpolateAtOffset:
+ if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeFloat, 16))
+ addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ if (basicTypeOp == OpTypeFloat && width == 16)
+ addCapability(CapabilityFloat16);
+ if (basicTypeOp == OpTypeInt && width == 16)
+ addCapability(CapabilityInt16);
+ if (basicTypeOp == OpTypeInt && width == 8)
+ addCapability(CapabilityInt8);
+ break;
+ }
+}
+
+// Called for each instruction that resides in a block.
+void Builder::postProcess(Instruction& inst)
+{
+ // Add capabilities based simply on the opcode.
+ switch (inst.getOpCode()) {
+ case OpExtInst:
+ switch (inst.getImmediateOperand(1)) {
+ case GLSLstd450InterpolateAtCentroid:
+ case GLSLstd450InterpolateAtSample:
+ case GLSLstd450InterpolateAtOffset:
+ addCapability(CapabilityInterpolationFunction);
+ break;
+ default:
+ break;
+ }
+ break;
+ case OpDPdxFine:
+ case OpDPdyFine:
+ case OpFwidthFine:
+ case OpDPdxCoarse:
+ case OpDPdyCoarse:
+ case OpFwidthCoarse:
+ addCapability(CapabilityDerivativeControl);
+ break;
+
+ case OpImageQueryLod:
+ case OpImageQuerySize:
+ case OpImageQuerySizeLod:
+ case OpImageQuerySamples:
+ case OpImageQueryLevels:
+ addCapability(CapabilityImageQuery);
+ break;
+
+ case OpGroupNonUniformPartitionNV:
+ addExtension(E_SPV_NV_shader_subgroup_partitioned);
+ addCapability(CapabilityGroupNonUniformPartitionedNV);
+ break;
+
+ case OpLoad:
+ case OpStore:
+ {
+ // For any load/store to a PhysicalStorageBufferEXT, walk the accesschain
+ // index list to compute the misalignment. The pre-existing alignment value
+ // (set via Builder::AccessChain::alignment) only accounts for the base of
+ // the reference type and any scalar component selection in the accesschain,
+ // and this function computes the rest from the SPIR-V Offset decorations.
+ Instruction *accessChain = module.getInstruction(inst.getIdOperand(0));
+ if (accessChain->getOpCode() == OpAccessChain) {
+ Instruction *base = module.getInstruction(accessChain->getIdOperand(0));
+ // Get the type of the base of the access chain. It must be a pointer type.
+ Id typeId = base->getTypeId();
+ Instruction *type = module.getInstruction(typeId);
+ assert(type->getOpCode() == OpTypePointer);
+ if (type->getImmediateOperand(0) != StorageClassPhysicalStorageBufferEXT) {
+ break;
+ }
+ // Get the pointee type.
+ typeId = type->getIdOperand(1);
+ type = module.getInstruction(typeId);
+ // Walk the index list for the access chain. For each index, find any
+ // misalignment that can apply when accessing the member/element via
+ // Offset/ArrayStride/MatrixStride decorations, and bitwise OR them all
+ // together.
+ int alignment = 0;
+ for (int i = 1; i < accessChain->getNumOperands(); ++i) {
+ Instruction *idx = module.getInstruction(accessChain->getIdOperand(i));
+ if (type->getOpCode() == OpTypeStruct) {
+ assert(idx->getOpCode() == OpConstant);
+ unsigned int c = idx->getImmediateOperand(0);
+
+ const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
+ if (decoration.get()->getOpCode() == OpMemberDecorate &&
+ decoration.get()->getIdOperand(0) == typeId &&
+ decoration.get()->getImmediateOperand(1) == c &&
+ (decoration.get()->getImmediateOperand(2) == DecorationOffset ||
+ decoration.get()->getImmediateOperand(2) == DecorationMatrixStride)) {
+ alignment |= decoration.get()->getImmediateOperand(3);
+ }
+ };
+ std::for_each(decorations.begin(), decorations.end(), function);
+ // get the next member type
+ typeId = type->getIdOperand(c);
+ type = module.getInstruction(typeId);
+ } else if (type->getOpCode() == OpTypeArray ||
+ type->getOpCode() == OpTypeRuntimeArray) {
+ const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
+ if (decoration.get()->getOpCode() == OpDecorate &&
+ decoration.get()->getIdOperand(0) == typeId &&
+ decoration.get()->getImmediateOperand(1) == DecorationArrayStride) {
+ alignment |= decoration.get()->getImmediateOperand(2);
+ }
+ };
+ std::for_each(decorations.begin(), decorations.end(), function);
+ // Get the element type
+ typeId = type->getIdOperand(0);
+ type = module.getInstruction(typeId);
+ } else {
+ // Once we get to any non-aggregate type, we're done.
+ break;
+ }
+ }
+ assert(inst.getNumOperands() >= 3);
+ unsigned int memoryAccess = inst.getImmediateOperand((inst.getOpCode() == OpStore) ? 2 : 1);
+ assert(memoryAccess & MemoryAccessAlignedMask);
+ static_cast<void>(memoryAccess);
+ // Compute the index of the alignment operand.
+ int alignmentIdx = 2;
+ if (inst.getOpCode() == OpStore)
+ alignmentIdx++;
+ // Merge new and old (mis)alignment
+ alignment |= inst.getImmediateOperand(alignmentIdx);
+ // Pick the LSB
+ alignment = alignment & ~(alignment & (alignment-1));
+ // update the Aligned operand
+ inst.setImmediateOperand(alignmentIdx, alignment);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ // Checks based on type
+ if (inst.getTypeId() != NoType)
+ postProcessType(inst, inst.getTypeId());
+ for (int op = 0; op < inst.getNumOperands(); ++op) {
+ if (inst.isIdOperand(op)) {
+ // In blocks, these are always result ids, but we are relying on
+ // getTypeId() to return NoType for things like OpLabel.
+ if (getTypeId(inst.getIdOperand(op)) != NoType)
+ postProcessType(inst, getTypeId(inst.getIdOperand(op)));
+ }
+ }
+}
+#endif
+
+// comment in header
+void Builder::postProcessCFG()
+{
+ // reachableBlocks is the set of blockss reached via control flow, or which are
+ // unreachable continue targert or unreachable merge.
+ std::unordered_set<const Block*> reachableBlocks;
+ std::unordered_map<Block*, Block*> headerForUnreachableContinue;
+ std::unordered_set<Block*> unreachableMerges;
+ std::unordered_set<Id> unreachableDefinitions;
+ // Collect IDs defined in unreachable blocks. For each function, label the
+ // reachable blocks first. Then for each unreachable block, collect the
+ // result IDs of the instructions in it.
+ for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) {
+ Function* f = *fi;
+ Block* entry = f->getEntryBlock();
+ inReadableOrder(entry,
+ [&reachableBlocks, &unreachableMerges, &headerForUnreachableContinue]
+ (Block* b, ReachReason why, Block* header) {
+ reachableBlocks.insert(b);
+ if (why == ReachDeadContinue) headerForUnreachableContinue[b] = header;
+ if (why == ReachDeadMerge) unreachableMerges.insert(b);
+ });
+ for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) {
+ Block* b = *bi;
+ if (unreachableMerges.count(b) != 0 || headerForUnreachableContinue.count(b) != 0) {
+ auto ii = b->getInstructions().cbegin();
+ ++ii; // Keep potential decorations on the label.
+ for (; ii != b->getInstructions().cend(); ++ii)
+ unreachableDefinitions.insert(ii->get()->getResultId());
+ } else if (reachableBlocks.count(b) == 0) {
+ // The normal case for unreachable code. All definitions are considered dead.
+ for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ++ii)
+ unreachableDefinitions.insert(ii->get()->getResultId());
+ }
+ }
+ }
+
+ // Modify unreachable merge blocks and unreachable continue targets.
+ // Delete their contents.
+ for (auto mergeIter = unreachableMerges.begin(); mergeIter != unreachableMerges.end(); ++mergeIter) {
+ (*mergeIter)->rewriteAsCanonicalUnreachableMerge();
+ }
+ for (auto continueIter = headerForUnreachableContinue.begin();
+ continueIter != headerForUnreachableContinue.end();
+ ++continueIter) {
+ Block* continue_target = continueIter->first;
+ Block* header = continueIter->second;
+ continue_target->rewriteAsCanonicalUnreachableContinue(header);
+ }
+
+ // Remove unneeded decorations, for unreachable instructions
+ decorations.erase(std::remove_if(decorations.begin(), decorations.end(),
+ [&unreachableDefinitions](std::unique_ptr<Instruction>& I) -> bool {
+ Id decoration_id = I.get()->getIdOperand(0);
+ return unreachableDefinitions.count(decoration_id) != 0;
+ }),
+ decorations.end());
+}
+
+#ifndef GLSLANG_WEB
+// comment in header
+void Builder::postProcessFeatures() {
+ // Add per-instruction capabilities, extensions, etc.,
+
+ // Look for any 8/16 bit type in physical storage buffer class, and set the
+ // appropriate capability. This happens in createSpvVariable for other storage
+ // classes, but there isn't always a variable for physical storage buffer.
+ for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
+ Instruction* type = groupedTypes[OpTypePointer][t];
+ if (type->getImmediateOperand(0) == (unsigned)StorageClassPhysicalStorageBufferEXT) {
+ if (containsType(type->getIdOperand(1), OpTypeInt, 8)) {
+ addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
+ addCapability(spv::CapabilityStorageBuffer8BitAccess);
+ }
+ if (containsType(type->getIdOperand(1), OpTypeInt, 16) ||
+ containsType(type->getIdOperand(1), OpTypeFloat, 16)) {
+ addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
+ addCapability(spv::CapabilityStorageBuffer16BitAccess);
+ }
+ }
+ }
+
+ // process all block-contained instructions
+ for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) {
+ Function* f = *fi;
+ for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) {
+ Block* b = *bi;
+ for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ii++)
+ postProcess(*ii->get());
+
+ // For all local variables that contain pointers to PhysicalStorageBufferEXT, check whether
+ // there is an existing restrict/aliased decoration. If we don't find one, add Aliased as the
+ // default.
+ for (auto vi = b->getLocalVariables().cbegin(); vi != b->getLocalVariables().cend(); vi++) {
+ const Instruction& inst = *vi->get();
+ Id resultId = inst.getResultId();
+ if (containsPhysicalStorageBufferOrArray(getDerefTypeId(resultId))) {
+ bool foundDecoration = false;
+ const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
+ if (decoration.get()->getIdOperand(0) == resultId &&
+ decoration.get()->getOpCode() == OpDecorate &&
+ (decoration.get()->getImmediateOperand(1) == spv::DecorationAliasedPointerEXT ||
+ decoration.get()->getImmediateOperand(1) == spv::DecorationRestrictPointerEXT)) {
+ foundDecoration = true;
+ }
+ };
+ std::for_each(decorations.begin(), decorations.end(), function);
+ if (!foundDecoration) {
+ addDecoration(resultId, spv::DecorationAliasedPointerEXT);
+ }
+ }
+ }
+ }
+ }
+}
+#endif
+
+// comment in header
+void Builder::postProcess() {
+ postProcessCFG();
+#ifndef GLSLANG_WEB
+ postProcessFeatures();
+#endif
+}
+
+}; // end spv namespace
diff --git a/thirdparty/glslang/SPIRV/SpvTools.cpp b/thirdparty/glslang/SPIRV/SpvTools.cpp
new file mode 100644
index 0000000000..97bd4e7427
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/SpvTools.cpp
@@ -0,0 +1,216 @@
+//
+// Copyright (C) 2014-2016 LunarG, Inc.
+// Copyright (C) 2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Call into SPIRV-Tools to disassemble, validate, and optimize.
+//
+
+#if ENABLE_OPT
+
+#include <cstdio>
+#include <iostream>
+
+#include "SpvTools.h"
+#include "spirv-tools/optimizer.hpp"
+#include "spirv-tools/libspirv.h"
+
+namespace glslang {
+
+// Translate glslang's view of target versioning to what SPIRV-Tools uses.
+spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger)
+{
+ switch (spvVersion.vulkan) {
+ case glslang::EShTargetVulkan_1_0:
+ return spv_target_env::SPV_ENV_VULKAN_1_0;
+ case glslang::EShTargetVulkan_1_1:
+ switch (spvVersion.spv) {
+ case EShTargetSpv_1_0:
+ case EShTargetSpv_1_1:
+ case EShTargetSpv_1_2:
+ case EShTargetSpv_1_3:
+ return spv_target_env::SPV_ENV_VULKAN_1_1;
+ case EShTargetSpv_1_4:
+ return spv_target_env::SPV_ENV_VULKAN_1_1_SPIRV_1_4;
+ default:
+ logger->missingFunctionality("Target version for SPIRV-Tools validator");
+ return spv_target_env::SPV_ENV_VULKAN_1_1;
+ }
+ case glslang::EShTargetVulkan_1_2:
+ return spv_target_env::SPV_ENV_VULKAN_1_2;
+ default:
+ break;
+ }
+
+ if (spvVersion.openGl > 0)
+ return spv_target_env::SPV_ENV_OPENGL_4_5;
+
+ logger->missingFunctionality("Target version for SPIRV-Tools validator");
+ return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
+}
+
+
+// Use the SPIRV-Tools disassembler to print SPIR-V.
+void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
+{
+ // disassemble
+ spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
+ spv_text text;
+ spv_diagnostic diagnostic = nullptr;
+ spvBinaryToText(context, spirv.data(), spirv.size(),
+ SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT,
+ &text, &diagnostic);
+
+ // dump
+ if (diagnostic == nullptr)
+ out << text->str;
+ else
+ spvDiagnosticPrint(diagnostic);
+
+ // teardown
+ spvDiagnosticDestroy(diagnostic);
+ spvContextDestroy(context);
+}
+
+// Apply the SPIRV-Tools validator to generated SPIR-V.
+void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+ spv::SpvBuildLogger* logger, bool prelegalization)
+{
+ // validate
+ spv_context context = spvContextCreate(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
+ spv_const_binary_t binary = { spirv.data(), spirv.size() };
+ spv_diagnostic diagnostic = nullptr;
+ spv_validator_options options = spvValidatorOptionsCreate();
+ spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
+ spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
+ spvValidateWithOptions(context, options, &binary, &diagnostic);
+
+ // report
+ if (diagnostic != nullptr) {
+ logger->error("SPIRV-Tools Validation Errors");
+ logger->error(diagnostic->error);
+ }
+
+ // tear down
+ spvValidatorOptionsDestroy(options);
+ spvDiagnosticDestroy(diagnostic);
+ spvContextDestroy(context);
+}
+
+// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
+// legalizing HLSL SPIR-V.
+void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>& spirv,
+ spv::SpvBuildLogger*, const SpvOptions* options)
+{
+ spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
+
+ spvtools::Optimizer optimizer(target_env);
+ optimizer.SetMessageConsumer(
+ [](spv_message_level_t level, const char *source, const spv_position_t &position, const char *message) {
+ auto &out = std::cerr;
+ switch (level)
+ {
+ case SPV_MSG_FATAL:
+ case SPV_MSG_INTERNAL_ERROR:
+ case SPV_MSG_ERROR:
+ out << "error: ";
+ break;
+ case SPV_MSG_WARNING:
+ out << "warning: ";
+ break;
+ case SPV_MSG_INFO:
+ case SPV_MSG_DEBUG:
+ out << "info: ";
+ break;
+ default:
+ break;
+ }
+ if (source)
+ {
+ out << source << ":";
+ }
+ out << position.line << ":" << position.column << ":" << position.index << ":";
+ if (message)
+ {
+ out << " " << message;
+ }
+ out << std::endl;
+ });
+
+ // If debug (specifically source line info) is being generated, propagate
+ // line information into all SPIR-V instructions. This avoids loss of
+ // information when instructions are deleted or moved. Later, remove
+ // redundant information to minimize final SPRIR-V size.
+ if (options->generateDebugInfo) {
+ optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
+ }
+ optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
+ optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
+ optimizer.RegisterPass(spvtools::CreateMergeReturnPass());
+ optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass());
+ optimizer.RegisterPass(spvtools::CreateEliminateDeadFunctionsPass());
+ optimizer.RegisterPass(spvtools::CreateScalarReplacementPass());
+ optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass());
+ optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass());
+ optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass());
+ optimizer.RegisterPass(spvtools::CreateSimplificationPass());
+ optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
+ optimizer.RegisterPass(spvtools::CreateVectorDCEPass());
+ optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass());
+ optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
+ optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
+ optimizer.RegisterPass(spvtools::CreateBlockMergePass());
+ optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass());
+ optimizer.RegisterPass(spvtools::CreateIfConversionPass());
+ optimizer.RegisterPass(spvtools::CreateSimplificationPass());
+ optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
+ optimizer.RegisterPass(spvtools::CreateVectorDCEPass());
+ optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass());
+ if (options->optimizeSize) {
+ optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass());
+ }
+ optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
+ optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
+ if (options->generateDebugInfo) {
+ optimizer.RegisterPass(spvtools::CreateRedundantLineInfoElimPass());
+ }
+
+ spvtools::OptimizerOptions spvOptOptions;
+ spvOptOptions.set_run_validator(false); // The validator may run as a seperate step later on
+ optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
+}
+
+}; // end namespace glslang
+
+#endif
diff --git a/thirdparty/glslang/SPIRV/SpvTools.h b/thirdparty/glslang/SPIRV/SpvTools.h
new file mode 100644
index 0000000000..59c914da0b
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/SpvTools.h
@@ -0,0 +1,82 @@
+//
+// Copyright (C) 2014-2016 LunarG, Inc.
+// Copyright (C) 2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Call into SPIRV-Tools to disassemble, validate, and optimize.
+//
+
+#pragma once
+#ifndef GLSLANG_SPV_TOOLS_H
+#define GLSLANG_SPV_TOOLS_H
+
+#ifdef ENABLE_OPT
+#include <vector>
+#include <ostream>
+#endif
+
+#include "glslang/MachineIndependent/localintermediate.h"
+#include "Logger.h"
+
+namespace glslang {
+
+struct SpvOptions {
+ SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
+ optimizeSize(false), disassemble(false), validate(false) { }
+ bool generateDebugInfo;
+ bool disableOptimizer;
+ bool optimizeSize;
+ bool disassemble;
+ bool validate;
+};
+
+#ifdef ENABLE_OPT
+
+// Use the SPIRV-Tools disassembler to print SPIR-V.
+void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
+
+// Apply the SPIRV-Tools validator to generated SPIR-V.
+void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+ spv::SpvBuildLogger*, bool prelegalization);
+
+// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
+// legalizing HLSL SPIR-V.
+void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+ spv::SpvBuildLogger*, const SpvOptions*);
+
+#endif
+
+} // end namespace glslang
+
+#endif // GLSLANG_SPV_TOOLS_H
diff --git a/thirdparty/glslang/SPIRV/bitutils.h b/thirdparty/glslang/SPIRV/bitutils.h
new file mode 100644
index 0000000000..22e44cec26
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/bitutils.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2015-2016 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef LIBSPIRV_UTIL_BITUTILS_H_
+#define LIBSPIRV_UTIL_BITUTILS_H_
+
+#include <cstdint>
+#include <cstring>
+
+namespace spvutils {
+
+// Performs a bitwise copy of source to the destination type Dest.
+template <typename Dest, typename Src>
+Dest BitwiseCast(Src source) {
+ Dest dest;
+ static_assert(sizeof(source) == sizeof(dest),
+ "BitwiseCast: Source and destination must have the same size");
+ std::memcpy(static_cast<void*>(&dest), &source, sizeof(dest));
+ return dest;
+}
+
+// SetBits<T, First, Num> returns an integer of type <T> with bits set
+// for position <First> through <First + Num - 1>, counting from the least
+// significant bit. In particular when Num == 0, no positions are set to 1.
+// A static assert will be triggered if First + Num > sizeof(T) * 8, that is,
+// a bit that will not fit in the underlying type is set.
+template <typename T, size_t First = 0, size_t Num = 0>
+struct SetBits {
+ static_assert(First < sizeof(T) * 8,
+ "Tried to set a bit that is shifted too far.");
+ const static T get = (T(1) << First) | SetBits<T, First + 1, Num - 1>::get;
+};
+
+template <typename T, size_t Last>
+struct SetBits<T, Last, 0> {
+ const static T get = T(0);
+};
+
+// This is all compile-time so we can put our tests right here.
+static_assert(SetBits<uint32_t, 0, 0>::get == uint32_t(0x00000000),
+ "SetBits failed");
+static_assert(SetBits<uint32_t, 0, 1>::get == uint32_t(0x00000001),
+ "SetBits failed");
+static_assert(SetBits<uint32_t, 31, 1>::get == uint32_t(0x80000000),
+ "SetBits failed");
+static_assert(SetBits<uint32_t, 1, 2>::get == uint32_t(0x00000006),
+ "SetBits failed");
+static_assert(SetBits<uint32_t, 30, 2>::get == uint32_t(0xc0000000),
+ "SetBits failed");
+static_assert(SetBits<uint32_t, 0, 31>::get == uint32_t(0x7FFFFFFF),
+ "SetBits failed");
+static_assert(SetBits<uint32_t, 0, 32>::get == uint32_t(0xFFFFFFFF),
+ "SetBits failed");
+static_assert(SetBits<uint32_t, 16, 16>::get == uint32_t(0xFFFF0000),
+ "SetBits failed");
+
+static_assert(SetBits<uint64_t, 0, 1>::get == uint64_t(0x0000000000000001LL),
+ "SetBits failed");
+static_assert(SetBits<uint64_t, 63, 1>::get == uint64_t(0x8000000000000000LL),
+ "SetBits failed");
+static_assert(SetBits<uint64_t, 62, 2>::get == uint64_t(0xc000000000000000LL),
+ "SetBits failed");
+static_assert(SetBits<uint64_t, 31, 1>::get == uint64_t(0x0000000080000000LL),
+ "SetBits failed");
+static_assert(SetBits<uint64_t, 16, 16>::get == uint64_t(0x00000000FFFF0000LL),
+ "SetBits failed");
+
+} // namespace spvutils
+
+#endif // LIBSPIRV_UTIL_BITUTILS_H_
diff --git a/thirdparty/glslang/SPIRV/disassemble.cpp b/thirdparty/glslang/SPIRV/disassemble.cpp
new file mode 100644
index 0000000000..930e799493
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/disassemble.cpp
@@ -0,0 +1,736 @@
+//
+// Copyright (C) 2014-2015 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Disassembler for SPIR-V.
+//
+
+#include <cstdlib>
+#include <cstring>
+#include <cassert>
+#include <iomanip>
+#include <stack>
+#include <sstream>
+#include <cstring>
+
+#include "disassemble.h"
+#include "doc.h"
+#include "SpvTools.h"
+
+namespace spv {
+ extern "C" {
+ // Include C-based headers that don't have a namespace
+ #include "GLSL.std.450.h"
+ #include "GLSL.ext.AMD.h"
+ #include "GLSL.ext.NV.h"
+ }
+}
+const char* GlslStd450DebugNames[spv::GLSLstd450Count];
+
+namespace spv {
+
+static const char* GLSLextAMDGetDebugNames(const char*, unsigned);
+static const char* GLSLextNVGetDebugNames(const char*, unsigned);
+
+static void Kill(std::ostream& out, const char* message)
+{
+ out << std::endl << "Disassembly failed: " << message << std::endl;
+ exit(1);
+}
+
+// used to identify the extended instruction library imported when printing
+enum ExtInstSet {
+ GLSL450Inst,
+ GLSLextAMDInst,
+ GLSLextNVInst,
+ OpenCLExtInst,
+};
+
+// Container class for a single instance of a SPIR-V stream, with methods for disassembly.
+class SpirvStream {
+public:
+ SpirvStream(std::ostream& out, const std::vector<unsigned int>& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { }
+ virtual ~SpirvStream() { }
+
+ void validate();
+ void processInstructions();
+
+protected:
+ SpirvStream(const SpirvStream&);
+ SpirvStream& operator=(const SpirvStream&);
+ Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }
+
+ // Output methods
+ void outputIndent();
+ void formatId(Id id, std::stringstream&);
+ void outputResultId(Id id);
+ void outputTypeId(Id id);
+ void outputId(Id id);
+ void outputMask(OperandClass operandClass, unsigned mask);
+ void disassembleImmediates(int numOperands);
+ void disassembleIds(int numOperands);
+ int disassembleString();
+ void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
+
+ // Data
+ std::ostream& out; // where to write the disassembly
+ const std::vector<unsigned int>& stream; // the actual word stream
+ int size; // the size of the word stream
+ int word; // the next word of the stream to read
+
+ // map each <id> to the instruction that created it
+ Id bound;
+ std::vector<unsigned int> idInstruction; // the word offset into the stream where the instruction for result [id] starts; 0 if not yet seen (forward reference or function parameter)
+
+ std::vector<std::string> idDescriptor; // the best text string known for explaining the <id>
+
+ // schema
+ unsigned int schema;
+
+ // stack of structured-merge points
+ std::stack<Id> nestedControl;
+ Id nextNestedControl; // need a slight delay for when we are nested
+};
+
+void SpirvStream::validate()
+{
+ size = (int)stream.size();
+ if (size < 4)
+ Kill(out, "stream is too short");
+
+ // Magic number
+ if (stream[word++] != MagicNumber) {
+ out << "Bad magic number";
+ return;
+ }
+
+ // Version
+ out << "// Module Version " << std::hex << stream[word++] << std::endl;
+
+ // Generator's magic number
+ out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl;
+
+ // Result <id> bound
+ bound = stream[word++];
+ idInstruction.resize(bound);
+ idDescriptor.resize(bound);
+ out << "// Id's are bound by " << bound << std::endl;
+ out << std::endl;
+
+ // Reserved schema, must be 0 for now
+ schema = stream[word++];
+ if (schema != 0)
+ Kill(out, "bad schema, must be 0");
+}
+
+// Loop over all the instructions, in order, processing each.
+// Boiler plate for each is handled here directly, the rest is dispatched.
+void SpirvStream::processInstructions()
+{
+ // Instructions
+ while (word < size) {
+ int instructionStart = word;
+
+ // Instruction wordCount and opcode
+ unsigned int firstWord = stream[word];
+ unsigned wordCount = firstWord >> WordCountShift;
+ Op opCode = (Op)(firstWord & OpCodeMask);
+ int nextInst = word + wordCount;
+ ++word;
+
+ // Presence of full instruction
+ if (nextInst > size)
+ Kill(out, "stream instruction terminated too early");
+
+ // Base for computing number of operands; will be updated as more is learned
+ unsigned numOperands = wordCount - 1;
+
+ // Type <id>
+ Id typeId = 0;
+ if (InstructionDesc[opCode].hasType()) {
+ typeId = stream[word++];
+ --numOperands;
+ }
+
+ // Result <id>
+ Id resultId = 0;
+ if (InstructionDesc[opCode].hasResult()) {
+ resultId = stream[word++];
+ --numOperands;
+
+ // save instruction for future reference
+ idInstruction[resultId] = instructionStart;
+ }
+
+ outputResultId(resultId);
+ outputTypeId(typeId);
+ outputIndent();
+
+ // Hand off the Op and all its operands
+ disassembleInstruction(resultId, typeId, opCode, numOperands);
+ if (word != nextInst) {
+ out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;
+ word = nextInst;
+ }
+ out << std::endl;
+ }
+}
+
+void SpirvStream::outputIndent()
+{
+ for (int i = 0; i < (int)nestedControl.size(); ++i)
+ out << " ";
+}
+
+void SpirvStream::formatId(Id id, std::stringstream& idStream)
+{
+ if (id != 0) {
+ // On instructions with no IDs, this is called with "0", which does not
+ // have to be within ID bounds on null shaders.
+ if (id >= bound)
+ Kill(out, "Bad <id>");
+
+ idStream << id;
+ if (idDescriptor[id].size() > 0)
+ idStream << "(" << idDescriptor[id] << ")";
+ }
+}
+
+void SpirvStream::outputResultId(Id id)
+{
+ const int width = 16;
+ std::stringstream idStream;
+ formatId(id, idStream);
+ out << std::setw(width) << std::right << idStream.str();
+ if (id != 0)
+ out << ":";
+ else
+ out << " ";
+
+ if (nestedControl.size() && id == nestedControl.top())
+ nestedControl.pop();
+}
+
+void SpirvStream::outputTypeId(Id id)
+{
+ const int width = 12;
+ std::stringstream idStream;
+ formatId(id, idStream);
+ out << std::setw(width) << std::right << idStream.str() << " ";
+}
+
+void SpirvStream::outputId(Id id)
+{
+ if (id >= bound)
+ Kill(out, "Bad <id>");
+
+ out << id;
+ if (idDescriptor[id].size() > 0)
+ out << "(" << idDescriptor[id] << ")";
+}
+
+void SpirvStream::outputMask(OperandClass operandClass, unsigned mask)
+{
+ if (mask == 0)
+ out << "None";
+ else {
+ for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {
+ if (mask & (1 << m))
+ out << OperandClassParams[operandClass].getName(m) << " ";
+ }
+ }
+}
+
+void SpirvStream::disassembleImmediates(int numOperands)
+{
+ for (int i = 0; i < numOperands; ++i) {
+ out << stream[word++];
+ if (i < numOperands - 1)
+ out << " ";
+ }
+}
+
+void SpirvStream::disassembleIds(int numOperands)
+{
+ for (int i = 0; i < numOperands; ++i) {
+ outputId(stream[word++]);
+ if (i < numOperands - 1)
+ out << " ";
+ }
+}
+
+// return the number of operands consumed by the string
+int SpirvStream::disassembleString()
+{
+ int startWord = word;
+
+ out << " \"";
+
+ const char* wordString;
+ bool done = false;
+ do {
+ unsigned int content = stream[word];
+ wordString = (const char*)&content;
+ for (int charCount = 0; charCount < 4; ++charCount) {
+ if (*wordString == 0) {
+ done = true;
+ break;
+ }
+ out << *(wordString++);
+ }
+ ++word;
+ } while (! done);
+
+ out << "\"";
+
+ return word - startWord;
+}
+
+void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
+{
+ // Process the opcode
+
+ out << (OpcodeString(opCode) + 2); // leave out the "Op"
+
+ if (opCode == OpLoopMerge || opCode == OpSelectionMerge)
+ nextNestedControl = stream[word];
+ else if (opCode == OpBranchConditional || opCode == OpSwitch) {
+ if (nextNestedControl) {
+ nestedControl.push(nextNestedControl);
+ nextNestedControl = 0;
+ }
+ } else if (opCode == OpExtInstImport) {
+ idDescriptor[resultId] = (const char*)(&stream[word]);
+ }
+ else {
+ if (resultId != 0 && idDescriptor[resultId].size() == 0) {
+ switch (opCode) {
+ case OpTypeInt:
+ switch (stream[word]) {
+ case 8: idDescriptor[resultId] = "int8_t"; break;
+ case 16: idDescriptor[resultId] = "int16_t"; break;
+ default: assert(0); // fallthrough
+ case 32: idDescriptor[resultId] = "int"; break;
+ case 64: idDescriptor[resultId] = "int64_t"; break;
+ }
+ break;
+ case OpTypeFloat:
+ switch (stream[word]) {
+ case 16: idDescriptor[resultId] = "float16_t"; break;
+ default: assert(0); // fallthrough
+ case 32: idDescriptor[resultId] = "float"; break;
+ case 64: idDescriptor[resultId] = "float64_t"; break;
+ }
+ break;
+ case OpTypeBool:
+ idDescriptor[resultId] = "bool";
+ break;
+ case OpTypeStruct:
+ idDescriptor[resultId] = "struct";
+ break;
+ case OpTypePointer:
+ idDescriptor[resultId] = "ptr";
+ break;
+ case OpTypeVector:
+ if (idDescriptor[stream[word]].size() > 0) {
+ idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);
+ if (strstr(idDescriptor[stream[word]].c_str(), "8")) {
+ idDescriptor[resultId].append("8");
+ }
+ if (strstr(idDescriptor[stream[word]].c_str(), "16")) {
+ idDescriptor[resultId].append("16");
+ }
+ if (strstr(idDescriptor[stream[word]].c_str(), "64")) {
+ idDescriptor[resultId].append("64");
+ }
+ }
+ idDescriptor[resultId].append("vec");
+ switch (stream[word + 1]) {
+ case 2: idDescriptor[resultId].append("2"); break;
+ case 3: idDescriptor[resultId].append("3"); break;
+ case 4: idDescriptor[resultId].append("4"); break;
+ case 8: idDescriptor[resultId].append("8"); break;
+ case 16: idDescriptor[resultId].append("16"); break;
+ case 32: idDescriptor[resultId].append("32"); break;
+ default: break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // Process the operands. Note, a new context-dependent set could be
+ // swapped in mid-traversal.
+
+ // Handle images specially, so can put out helpful strings.
+ if (opCode == OpTypeImage) {
+ out << " ";
+ disassembleIds(1);
+ out << " " << DimensionString((Dim)stream[word++]);
+ out << (stream[word++] != 0 ? " depth" : "");
+ out << (stream[word++] != 0 ? " array" : "");
+ out << (stream[word++] != 0 ? " multi-sampled" : "");
+ switch (stream[word++]) {
+ case 0: out << " runtime"; break;
+ case 1: out << " sampled"; break;
+ case 2: out << " nonsampled"; break;
+ }
+ out << " format:" << ImageFormatString((ImageFormat)stream[word++]);
+
+ if (numOperands == 8) {
+ out << " " << AccessQualifierString(stream[word++]);
+ }
+ return;
+ }
+
+ // Handle all the parameterized operands
+ for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) {
+ out << " ";
+ OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);
+ switch (operandClass) {
+ case OperandId:
+ case OperandScope:
+ case OperandMemorySemantics:
+ disassembleIds(1);
+ --numOperands;
+ // Get names for printing "(XXX)" for readability, *after* this id
+ if (opCode == OpName)
+ idDescriptor[stream[word - 1]] = (const char*)(&stream[word]);
+ break;
+ case OperandVariableIds:
+ disassembleIds(numOperands);
+ return;
+ case OperandImageOperands:
+ outputMask(OperandImageOperands, stream[word++]);
+ --numOperands;
+ disassembleIds(numOperands);
+ return;
+ case OperandOptionalLiteral:
+ case OperandVariableLiterals:
+ if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) ||
+ (opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) {
+ out << BuiltInString(stream[word++]);
+ --numOperands;
+ ++op;
+ }
+ disassembleImmediates(numOperands);
+ return;
+ case OperandVariableIdLiteral:
+ while (numOperands > 0) {
+ out << std::endl;
+ outputResultId(0);
+ outputTypeId(0);
+ outputIndent();
+ out << " Type ";
+ disassembleIds(1);
+ out << ", member ";
+ disassembleImmediates(1);
+ numOperands -= 2;
+ }
+ return;
+ case OperandVariableLiteralId:
+ while (numOperands > 0) {
+ out << std::endl;
+ outputResultId(0);
+ outputTypeId(0);
+ outputIndent();
+ out << " case ";
+ disassembleImmediates(1);
+ out << ": ";
+ disassembleIds(1);
+ numOperands -= 2;
+ }
+ return;
+ case OperandLiteralNumber:
+ disassembleImmediates(1);
+ --numOperands;
+ if (opCode == OpExtInst) {
+ ExtInstSet extInstSet = GLSL450Inst;
+ const char* name = idDescriptor[stream[word - 2]].c_str();
+ if (0 == memcmp("OpenCL", name, 6)) {
+ extInstSet = OpenCLExtInst;
+ } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
+ strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
+ strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
+ strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {
+ extInstSet = GLSLextAMDInst;
+ } else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||
+ strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 ||
+ strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 ||
+ strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 ||
+ strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 ||
+ strcmp(spv::E_SPV_NV_mesh_shader, name) == 0) {
+ extInstSet = GLSLextNVInst;
+ }
+ unsigned entrypoint = stream[word - 1];
+ if (extInstSet == GLSL450Inst) {
+ if (entrypoint < GLSLstd450Count) {
+ out << "(" << GlslStd450DebugNames[entrypoint] << ")";
+ }
+ } else if (extInstSet == GLSLextAMDInst) {
+ out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";
+ }
+ else if (extInstSet == GLSLextNVInst) {
+ out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
+ }
+ }
+ break;
+ case OperandOptionalLiteralString:
+ case OperandLiteralString:
+ numOperands -= disassembleString();
+ break;
+ case OperandMemoryAccess:
+ outputMask(OperandMemoryAccess, stream[word++]);
+ --numOperands;
+ // Aligned is the only memory access operand that uses an immediate
+ // value, and it is also the first operand that uses a value at all.
+ if (stream[word-1] & MemoryAccessAlignedMask) {
+ disassembleImmediates(1);
+ numOperands--;
+ if (numOperands)
+ out << " ";
+ }
+ disassembleIds(numOperands);
+ return;
+ default:
+ assert(operandClass >= OperandSource && operandClass < OperandOpcode);
+
+ if (OperandClassParams[operandClass].bitmask)
+ outputMask(operandClass, stream[word++]);
+ else
+ out << OperandClassParams[operandClass].getName(stream[word++]);
+ --numOperands;
+
+ break;
+ }
+ }
+
+ return;
+}
+
+static void GLSLstd450GetDebugNames(const char** names)
+{
+ for (int i = 0; i < GLSLstd450Count; ++i)
+ names[i] = "Unknown";
+
+ names[GLSLstd450Round] = "Round";
+ names[GLSLstd450RoundEven] = "RoundEven";
+ names[GLSLstd450Trunc] = "Trunc";
+ names[GLSLstd450FAbs] = "FAbs";
+ names[GLSLstd450SAbs] = "SAbs";
+ names[GLSLstd450FSign] = "FSign";
+ names[GLSLstd450SSign] = "SSign";
+ names[GLSLstd450Floor] = "Floor";
+ names[GLSLstd450Ceil] = "Ceil";
+ names[GLSLstd450Fract] = "Fract";
+ names[GLSLstd450Radians] = "Radians";
+ names[GLSLstd450Degrees] = "Degrees";
+ names[GLSLstd450Sin] = "Sin";
+ names[GLSLstd450Cos] = "Cos";
+ names[GLSLstd450Tan] = "Tan";
+ names[GLSLstd450Asin] = "Asin";
+ names[GLSLstd450Acos] = "Acos";
+ names[GLSLstd450Atan] = "Atan";
+ names[GLSLstd450Sinh] = "Sinh";
+ names[GLSLstd450Cosh] = "Cosh";
+ names[GLSLstd450Tanh] = "Tanh";
+ names[GLSLstd450Asinh] = "Asinh";
+ names[GLSLstd450Acosh] = "Acosh";
+ names[GLSLstd450Atanh] = "Atanh";
+ names[GLSLstd450Atan2] = "Atan2";
+ names[GLSLstd450Pow] = "Pow";
+ names[GLSLstd450Exp] = "Exp";
+ names[GLSLstd450Log] = "Log";
+ names[GLSLstd450Exp2] = "Exp2";
+ names[GLSLstd450Log2] = "Log2";
+ names[GLSLstd450Sqrt] = "Sqrt";
+ names[GLSLstd450InverseSqrt] = "InverseSqrt";
+ names[GLSLstd450Determinant] = "Determinant";
+ names[GLSLstd450MatrixInverse] = "MatrixInverse";
+ names[GLSLstd450Modf] = "Modf";
+ names[GLSLstd450ModfStruct] = "ModfStruct";
+ names[GLSLstd450FMin] = "FMin";
+ names[GLSLstd450SMin] = "SMin";
+ names[GLSLstd450UMin] = "UMin";
+ names[GLSLstd450FMax] = "FMax";
+ names[GLSLstd450SMax] = "SMax";
+ names[GLSLstd450UMax] = "UMax";
+ names[GLSLstd450FClamp] = "FClamp";
+ names[GLSLstd450SClamp] = "SClamp";
+ names[GLSLstd450UClamp] = "UClamp";
+ names[GLSLstd450FMix] = "FMix";
+ names[GLSLstd450Step] = "Step";
+ names[GLSLstd450SmoothStep] = "SmoothStep";
+ names[GLSLstd450Fma] = "Fma";
+ names[GLSLstd450Frexp] = "Frexp";
+ names[GLSLstd450FrexpStruct] = "FrexpStruct";
+ names[GLSLstd450Ldexp] = "Ldexp";
+ names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8";
+ names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8";
+ names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16";
+ names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16";
+ names[GLSLstd450PackHalf2x16] = "PackHalf2x16";
+ names[GLSLstd450PackDouble2x32] = "PackDouble2x32";
+ names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16";
+ names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16";
+ names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16";
+ names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8";
+ names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8";
+ names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32";
+ names[GLSLstd450Length] = "Length";
+ names[GLSLstd450Distance] = "Distance";
+ names[GLSLstd450Cross] = "Cross";
+ names[GLSLstd450Normalize] = "Normalize";
+ names[GLSLstd450FaceForward] = "FaceForward";
+ names[GLSLstd450Reflect] = "Reflect";
+ names[GLSLstd450Refract] = "Refract";
+ names[GLSLstd450FindILsb] = "FindILsb";
+ names[GLSLstd450FindSMsb] = "FindSMsb";
+ names[GLSLstd450FindUMsb] = "FindUMsb";
+ names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid";
+ names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample";
+ names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";
+ names[GLSLstd450NMin] = "NMin";
+ names[GLSLstd450NMax] = "NMax";
+ names[GLSLstd450NClamp] = "NClamp";
+}
+
+static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint)
+{
+ if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) {
+ switch (entrypoint) {
+ case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD";
+ case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD";
+ case WriteInvocationAMD: return "WriteInvocationAMD";
+ case MbcntAMD: return "MbcntAMD";
+ default: return "Bad";
+ }
+ } else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) {
+ switch (entrypoint) {
+ case FMin3AMD: return "FMin3AMD";
+ case UMin3AMD: return "UMin3AMD";
+ case SMin3AMD: return "SMin3AMD";
+ case FMax3AMD: return "FMax3AMD";
+ case UMax3AMD: return "UMax3AMD";
+ case SMax3AMD: return "SMax3AMD";
+ case FMid3AMD: return "FMid3AMD";
+ case UMid3AMD: return "UMid3AMD";
+ case SMid3AMD: return "SMid3AMD";
+ default: return "Bad";
+ }
+ } else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) {
+ switch (entrypoint) {
+ case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD";
+ default: return "Bad";
+ }
+ }
+ else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) {
+ switch (entrypoint) {
+ case CubeFaceIndexAMD: return "CubeFaceIndexAMD";
+ case CubeFaceCoordAMD: return "CubeFaceCoordAMD";
+ case TimeAMD: return "TimeAMD";
+ default:
+ break;
+ }
+ }
+
+ return "Bad";
+}
+
+static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)
+{
+ if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 ||
+ strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 ||
+ strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 ||
+ strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 ||
+ strcmp(name, spv::E_SPV_NVX_multiview_per_view_attributes) == 0 ||
+ strcmp(name, spv::E_SPV_NV_fragment_shader_barycentric) == 0 ||
+ strcmp(name, spv::E_SPV_NV_mesh_shader) == 0 ||
+ strcmp(name, spv::E_SPV_NV_shader_image_footprint) == 0) {
+ switch (entrypoint) {
+ // NV builtins
+ case BuiltInViewportMaskNV: return "ViewportMaskNV";
+ case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
+ case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
+ case BuiltInPositionPerViewNV: return "PositionPerViewNV";
+ case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
+ case BuiltInBaryCoordNV: return "BaryCoordNV";
+ case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
+ case BuiltInTaskCountNV: return "TaskCountNV";
+ case BuiltInPrimitiveCountNV: return "PrimitiveCountNV";
+ case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV";
+ case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV";
+ case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV";
+ case BuiltInLayerPerViewNV: return "LayerPerViewNV";
+ case BuiltInMeshViewCountNV: return "MeshViewCountNV";
+ case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV";
+
+ // NV Capabilities
+ case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
+ case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV";
+ case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";
+ case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
+ case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
+ case CapabilityMeshShadingNV: return "MeshShadingNV";
+ case CapabilityImageFootprintNV: return "ImageFootprintNV";
+ case CapabilitySampleMaskOverrideCoverageNV:return "SampleMaskOverrideCoverageNV";
+
+ // NV Decorations
+ case DecorationOverrideCoverageNV: return "OverrideCoverageNV";
+ case DecorationPassthroughNV: return "PassthroughNV";
+ case DecorationViewportRelativeNV: return "ViewportRelativeNV";
+ case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";
+ case DecorationPerVertexNV: return "PerVertexNV";
+ case DecorationPerPrimitiveNV: return "PerPrimitiveNV";
+ case DecorationPerViewNV: return "PerViewNV";
+ case DecorationPerTaskNV: return "PerTaskNV";
+
+ default: return "Bad";
+ }
+ }
+ return "Bad";
+}
+
+void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
+{
+ SpirvStream SpirvStream(out, stream);
+ spv::Parameterize();
+ GLSLstd450GetDebugNames(GlslStd450DebugNames);
+ SpirvStream.validate();
+ SpirvStream.processInstructions();
+}
+
+}; // end namespace spv
diff --git a/thirdparty/glslang/SPIRV/disassemble.h b/thirdparty/glslang/SPIRV/disassemble.h
new file mode 100644
index 0000000000..b6a4635775
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/disassemble.h
@@ -0,0 +1,53 @@
+//
+// Copyright (C) 2014-2015 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Disassembler for SPIR-V.
+//
+
+#pragma once
+#ifndef disassembler_H
+#define disassembler_H
+
+#include <iostream>
+#include <vector>
+
+namespace spv {
+
+ // disassemble with glslang custom disassembler
+ void Disassemble(std::ostream& out, const std::vector<unsigned int>&);
+
+} // end namespace spv
+
+#endif // disassembler_H
diff --git a/thirdparty/glslang/SPIRV/doc.cpp b/thirdparty/glslang/SPIRV/doc.cpp
new file mode 100644
index 0000000000..bee5c79729
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/doc.cpp
@@ -0,0 +1,2764 @@
+//
+// Copyright (C) 2014-2015 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// 1) Programmatically fill in instruction/operand information.
+// This can be used for disassembly, printing documentation, etc.
+//
+// 2) Print documentation from this parameterization.
+//
+
+#include "doc.h"
+
+#include <cstdio>
+#include <cstring>
+#include <algorithm>
+
+namespace spv {
+ extern "C" {
+ // Include C-based headers that don't have a namespace
+ #include "GLSL.ext.KHR.h"
+ #include "GLSL.ext.EXT.h"
+ #include "GLSL.ext.AMD.h"
+ #include "GLSL.ext.NV.h"
+ }
+}
+
+namespace spv {
+
+//
+// Whole set of functions that translate enumerants to their text strings for
+// the specification (or their sanitized versions for auto-generating the
+// spirv headers.
+//
+// Also, for masks the ceilings are declared next to these, to help keep them in sync.
+// Ceilings should be
+// - one more than the maximum value an enumerant takes on, for non-mask enumerants
+// (for non-sparse enums, this is the number of enumerants)
+// - the number of bits consumed by the set of masks
+// (for non-sparse mask enums, this is the number of enumerants)
+//
+
+const char* SourceString(int source)
+{
+ switch (source) {
+ case 0: return "Unknown";
+ case 1: return "ESSL";
+ case 2: return "GLSL";
+ case 3: return "OpenCL_C";
+ case 4: return "OpenCL_CPP";
+ case 5: return "HLSL";
+
+ default: return "Bad";
+ }
+}
+
+const char* ExecutionModelString(int model)
+{
+ switch (model) {
+ case 0: return "Vertex";
+ case 1: return "TessellationControl";
+ case 2: return "TessellationEvaluation";
+ case 3: return "Geometry";
+ case 4: return "Fragment";
+ case 5: return "GLCompute";
+ case 6: return "Kernel";
+ case ExecutionModelTaskNV: return "TaskNV";
+ case ExecutionModelMeshNV: return "MeshNV";
+
+ default: return "Bad";
+
+ case ExecutionModelRayGenerationNV: return "RayGenerationNV";
+ case ExecutionModelIntersectionNV: return "IntersectionNV";
+ case ExecutionModelAnyHitNV: return "AnyHitNV";
+ case ExecutionModelClosestHitNV: return "ClosestHitNV";
+ case ExecutionModelMissNV: return "MissNV";
+ case ExecutionModelCallableNV: return "CallableNV";
+ }
+}
+
+const char* AddressingString(int addr)
+{
+ switch (addr) {
+ case 0: return "Logical";
+ case 1: return "Physical32";
+ case 2: return "Physical64";
+
+ case AddressingModelPhysicalStorageBuffer64EXT: return "PhysicalStorageBuffer64EXT";
+
+ default: return "Bad";
+ }
+}
+
+const char* MemoryString(int mem)
+{
+ switch (mem) {
+ case MemoryModelSimple: return "Simple";
+ case MemoryModelGLSL450: return "GLSL450";
+ case MemoryModelOpenCL: return "OpenCL";
+ case MemoryModelVulkanKHR: return "VulkanKHR";
+
+ default: return "Bad";
+ }
+}
+
+const int ExecutionModeCeiling = 33;
+
+const char* ExecutionModeString(int mode)
+{
+ switch (mode) {
+ case 0: return "Invocations";
+ case 1: return "SpacingEqual";
+ case 2: return "SpacingFractionalEven";
+ case 3: return "SpacingFractionalOdd";
+ case 4: return "VertexOrderCw";
+ case 5: return "VertexOrderCcw";
+ case 6: return "PixelCenterInteger";
+ case 7: return "OriginUpperLeft";
+ case 8: return "OriginLowerLeft";
+ case 9: return "EarlyFragmentTests";
+ case 10: return "PointMode";
+ case 11: return "Xfb";
+ case 12: return "DepthReplacing";
+ case 13: return "Bad";
+ case 14: return "DepthGreater";
+ case 15: return "DepthLess";
+ case 16: return "DepthUnchanged";
+ case 17: return "LocalSize";
+ case 18: return "LocalSizeHint";
+ case 19: return "InputPoints";
+ case 20: return "InputLines";
+ case 21: return "InputLinesAdjacency";
+ case 22: return "Triangles";
+ case 23: return "InputTrianglesAdjacency";
+ case 24: return "Quads";
+ case 25: return "Isolines";
+ case 26: return "OutputVertices";
+ case 27: return "OutputPoints";
+ case 28: return "OutputLineStrip";
+ case 29: return "OutputTriangleStrip";
+ case 30: return "VecTypeHint";
+ case 31: return "ContractionOff";
+ case 32: return "Bad";
+
+ case 4446: return "PostDepthCoverage";
+
+ case ExecutionModeOutputLinesNV: return "OutputLinesNV";
+ case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV";
+ case ExecutionModeOutputTrianglesNV: return "OutputTrianglesNV";
+ case ExecutionModeDerivativeGroupQuadsNV: return "DerivativeGroupQuadsNV";
+ case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV";
+
+ case ExecutionModePixelInterlockOrderedEXT: return "PixelInterlockOrderedEXT";
+ case ExecutionModePixelInterlockUnorderedEXT: return "PixelInterlockUnorderedEXT";
+ case ExecutionModeSampleInterlockOrderedEXT: return "SampleInterlockOrderedEXT";
+ case ExecutionModeSampleInterlockUnorderedEXT: return "SampleInterlockUnorderedEXT";
+ case ExecutionModeShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT";
+ case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT";
+
+ case ExecutionModeCeiling:
+ default: return "Bad";
+ }
+}
+
+const char* StorageClassString(int StorageClass)
+{
+ switch (StorageClass) {
+ case 0: return "UniformConstant";
+ case 1: return "Input";
+ case 2: return "Uniform";
+ case 3: return "Output";
+ case 4: return "Workgroup";
+ case 5: return "CrossWorkgroup";
+ case 6: return "Private";
+ case 7: return "Function";
+ case 8: return "Generic";
+ case 9: return "PushConstant";
+ case 10: return "AtomicCounter";
+ case 11: return "Image";
+ case 12: return "StorageBuffer";
+
+ case StorageClassRayPayloadNV: return "RayPayloadNV";
+ case StorageClassHitAttributeNV: return "HitAttributeNV";
+ case StorageClassIncomingRayPayloadNV: return "IncomingRayPayloadNV";
+ case StorageClassShaderRecordBufferNV: return "ShaderRecordBufferNV";
+ case StorageClassCallableDataNV: return "CallableDataNV";
+ case StorageClassIncomingCallableDataNV: return "IncomingCallableDataNV";
+
+ case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
+
+ default: return "Bad";
+ }
+}
+
+const int DecorationCeiling = 45;
+
+const char* DecorationString(int decoration)
+{
+ switch (decoration) {
+ case 0: return "RelaxedPrecision";
+ case 1: return "SpecId";
+ case 2: return "Block";
+ case 3: return "BufferBlock";
+ case 4: return "RowMajor";
+ case 5: return "ColMajor";
+ case 6: return "ArrayStride";
+ case 7: return "MatrixStride";
+ case 8: return "GLSLShared";
+ case 9: return "GLSLPacked";
+ case 10: return "CPacked";
+ case 11: return "BuiltIn";
+ case 12: return "Bad";
+ case 13: return "NoPerspective";
+ case 14: return "Flat";
+ case 15: return "Patch";
+ case 16: return "Centroid";
+ case 17: return "Sample";
+ case 18: return "Invariant";
+ case 19: return "Restrict";
+ case 20: return "Aliased";
+ case 21: return "Volatile";
+ case 22: return "Constant";
+ case 23: return "Coherent";
+ case 24: return "NonWritable";
+ case 25: return "NonReadable";
+ case 26: return "Uniform";
+ case 27: return "Bad";
+ case 28: return "SaturatedConversion";
+ case 29: return "Stream";
+ case 30: return "Location";
+ case 31: return "Component";
+ case 32: return "Index";
+ case 33: return "Binding";
+ case 34: return "DescriptorSet";
+ case 35: return "Offset";
+ case 36: return "XfbBuffer";
+ case 37: return "XfbStride";
+ case 38: return "FuncParamAttr";
+ case 39: return "FP Rounding Mode";
+ case 40: return "FP Fast Math Mode";
+ case 41: return "Linkage Attributes";
+ case 42: return "NoContraction";
+ case 43: return "InputAttachmentIndex";
+ case 44: return "Alignment";
+
+ case DecorationCeiling:
+ default: return "Bad";
+
+ case DecorationExplicitInterpAMD: return "ExplicitInterpAMD";
+ case DecorationOverrideCoverageNV: return "OverrideCoverageNV";
+ case DecorationPassthroughNV: return "PassthroughNV";
+ case DecorationViewportRelativeNV: return "ViewportRelativeNV";
+ case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";
+ case DecorationPerPrimitiveNV: return "PerPrimitiveNV";
+ case DecorationPerViewNV: return "PerViewNV";
+ case DecorationPerTaskNV: return "PerTaskNV";
+ case DecorationPerVertexNV: return "PerVertexNV";
+
+ case DecorationNonUniformEXT: return "DecorationNonUniformEXT";
+ case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
+ case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE";
+ case DecorationRestrictPointerEXT: return "DecorationRestrictPointerEXT";
+ case DecorationAliasedPointerEXT: return "DecorationAliasedPointerEXT";
+ }
+}
+
+const char* BuiltInString(int builtIn)
+{
+ switch (builtIn) {
+ case 0: return "Position";
+ case 1: return "PointSize";
+ case 2: return "Bad";
+ case 3: return "ClipDistance";
+ case 4: return "CullDistance";
+ case 5: return "VertexId";
+ case 6: return "InstanceId";
+ case 7: return "PrimitiveId";
+ case 8: return "InvocationId";
+ case 9: return "Layer";
+ case 10: return "ViewportIndex";
+ case 11: return "TessLevelOuter";
+ case 12: return "TessLevelInner";
+ case 13: return "TessCoord";
+ case 14: return "PatchVertices";
+ case 15: return "FragCoord";
+ case 16: return "PointCoord";
+ case 17: return "FrontFacing";
+ case 18: return "SampleId";
+ case 19: return "SamplePosition";
+ case 20: return "SampleMask";
+ case 21: return "Bad";
+ case 22: return "FragDepth";
+ case 23: return "HelperInvocation";
+ case 24: return "NumWorkgroups";
+ case 25: return "WorkgroupSize";
+ case 26: return "WorkgroupId";
+ case 27: return "LocalInvocationId";
+ case 28: return "GlobalInvocationId";
+ case 29: return "LocalInvocationIndex";
+ case 30: return "WorkDim";
+ case 31: return "GlobalSize";
+ case 32: return "EnqueuedWorkgroupSize";
+ case 33: return "GlobalOffset";
+ case 34: return "GlobalLinearId";
+ case 35: return "Bad";
+ case 36: return "SubgroupSize";
+ case 37: return "SubgroupMaxSize";
+ case 38: return "NumSubgroups";
+ case 39: return "NumEnqueuedSubgroups";
+ case 40: return "SubgroupId";
+ case 41: return "SubgroupLocalInvocationId";
+ case 42: return "VertexIndex"; // TBD: put next to VertexId?
+ case 43: return "InstanceIndex"; // TBD: put next to InstanceId?
+
+ case 4416: return "SubgroupEqMaskKHR";
+ case 4417: return "SubgroupGeMaskKHR";
+ case 4418: return "SubgroupGtMaskKHR";
+ case 4419: return "SubgroupLeMaskKHR";
+ case 4420: return "SubgroupLtMaskKHR";
+ case 4438: return "DeviceIndex";
+ case 4440: return "ViewIndex";
+ case 4424: return "BaseVertex";
+ case 4425: return "BaseInstance";
+ case 4426: return "DrawIndex";
+ case 5014: return "FragStencilRefEXT";
+
+ case 4992: return "BaryCoordNoPerspAMD";
+ case 4993: return "BaryCoordNoPerspCentroidAMD";
+ case 4994: return "BaryCoordNoPerspSampleAMD";
+ case 4995: return "BaryCoordSmoothAMD";
+ case 4996: return "BaryCoordSmoothCentroidAMD";
+ case 4997: return "BaryCoordSmoothSampleAMD";
+ case 4998: return "BaryCoordPullModelAMD";
+ case BuiltInLaunchIdNV: return "LaunchIdNV";
+ case BuiltInLaunchSizeNV: return "LaunchSizeNV";
+ case BuiltInWorldRayOriginNV: return "WorldRayOriginNV";
+ case BuiltInWorldRayDirectionNV: return "WorldRayDirectionNV";
+ case BuiltInObjectRayOriginNV: return "ObjectRayOriginNV";
+ case BuiltInObjectRayDirectionNV: return "ObjectRayDirectionNV";
+ case BuiltInRayTminNV: return "RayTminNV";
+ case BuiltInRayTmaxNV: return "RayTmaxNV";
+ case BuiltInInstanceCustomIndexNV: return "InstanceCustomIndexNV";
+ case BuiltInObjectToWorldNV: return "ObjectToWorldNV";
+ case BuiltInWorldToObjectNV: return "WorldToObjectNV";
+ case BuiltInHitTNV: return "HitTNV";
+ case BuiltInHitKindNV: return "HitKindNV";
+ case BuiltInIncomingRayFlagsNV: return "IncomingRayFlagsNV";
+ case BuiltInViewportMaskNV: return "ViewportMaskNV";
+ case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
+ case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
+ case BuiltInPositionPerViewNV: return "PositionPerViewNV";
+ case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
+// case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT
+// case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
+ case BuiltInBaryCoordNV: return "BaryCoordNV";
+ case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
+
+ case BuiltInFragSizeEXT: return "FragSizeEXT";
+ case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT";
+
+ case 5264: return "FullyCoveredEXT";
+
+ case BuiltInTaskCountNV: return "TaskCountNV";
+ case BuiltInPrimitiveCountNV: return "PrimitiveCountNV";
+ case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV";
+ case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV";
+ case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV";
+ case BuiltInLayerPerViewNV: return "LayerPerViewNV";
+ case BuiltInMeshViewCountNV: return "MeshViewCountNV";
+ case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV";
+ case BuiltInWarpsPerSMNV: return "WarpsPerSMNV";
+ case BuiltInSMCountNV: return "SMCountNV";
+ case BuiltInWarpIDNV: return "WarpIDNV";
+ case BuiltInSMIDNV: return "SMIDNV";
+
+ default: return "Bad";
+ }
+}
+
+const char* DimensionString(int dim)
+{
+ switch (dim) {
+ case 0: return "1D";
+ case 1: return "2D";
+ case 2: return "3D";
+ case 3: return "Cube";
+ case 4: return "Rect";
+ case 5: return "Buffer";
+ case 6: return "SubpassData";
+
+ default: return "Bad";
+ }
+}
+
+const char* SamplerAddressingModeString(int mode)
+{
+ switch (mode) {
+ case 0: return "None";
+ case 1: return "ClampToEdge";
+ case 2: return "Clamp";
+ case 3: return "Repeat";
+ case 4: return "RepeatMirrored";
+
+ default: return "Bad";
+ }
+}
+
+const char* SamplerFilterModeString(int mode)
+{
+ switch (mode) {
+ case 0: return "Nearest";
+ case 1: return "Linear";
+
+ default: return "Bad";
+ }
+}
+
+const char* ImageFormatString(int format)
+{
+ switch (format) {
+ case 0: return "Unknown";
+
+ // ES/Desktop float
+ case 1: return "Rgba32f";
+ case 2: return "Rgba16f";
+ case 3: return "R32f";
+ case 4: return "Rgba8";
+ case 5: return "Rgba8Snorm";
+
+ // Desktop float
+ case 6: return "Rg32f";
+ case 7: return "Rg16f";
+ case 8: return "R11fG11fB10f";
+ case 9: return "R16f";
+ case 10: return "Rgba16";
+ case 11: return "Rgb10A2";
+ case 12: return "Rg16";
+ case 13: return "Rg8";
+ case 14: return "R16";
+ case 15: return "R8";
+ case 16: return "Rgba16Snorm";
+ case 17: return "Rg16Snorm";
+ case 18: return "Rg8Snorm";
+ case 19: return "R16Snorm";
+ case 20: return "R8Snorm";
+
+ // ES/Desktop int
+ case 21: return "Rgba32i";
+ case 22: return "Rgba16i";
+ case 23: return "Rgba8i";
+ case 24: return "R32i";
+
+ // Desktop int
+ case 25: return "Rg32i";
+ case 26: return "Rg16i";
+ case 27: return "Rg8i";
+ case 28: return "R16i";
+ case 29: return "R8i";
+
+ // ES/Desktop uint
+ case 30: return "Rgba32ui";
+ case 31: return "Rgba16ui";
+ case 32: return "Rgba8ui";
+ case 33: return "R32ui";
+
+ // Desktop uint
+ case 34: return "Rgb10a2ui";
+ case 35: return "Rg32ui";
+ case 36: return "Rg16ui";
+ case 37: return "Rg8ui";
+ case 38: return "R16ui";
+ case 39: return "R8ui";
+
+ default:
+ return "Bad";
+ }
+}
+
+const char* ImageChannelOrderString(int format)
+{
+ switch (format) {
+ case 0: return "R";
+ case 1: return "A";
+ case 2: return "RG";
+ case 3: return "RA";
+ case 4: return "RGB";
+ case 5: return "RGBA";
+ case 6: return "BGRA";
+ case 7: return "ARGB";
+ case 8: return "Intensity";
+ case 9: return "Luminance";
+ case 10: return "Rx";
+ case 11: return "RGx";
+ case 12: return "RGBx";
+ case 13: return "Depth";
+ case 14: return "DepthStencil";
+ case 15: return "sRGB";
+ case 16: return "sRGBx";
+ case 17: return "sRGBA";
+ case 18: return "sBGRA";
+
+ default:
+ return "Bad";
+ }
+}
+
+const char* ImageChannelDataTypeString(int type)
+{
+ switch (type)
+ {
+ case 0: return "SnormInt8";
+ case 1: return "SnormInt16";
+ case 2: return "UnormInt8";
+ case 3: return "UnormInt16";
+ case 4: return "UnormShort565";
+ case 5: return "UnormShort555";
+ case 6: return "UnormInt101010";
+ case 7: return "SignedInt8";
+ case 8: return "SignedInt16";
+ case 9: return "SignedInt32";
+ case 10: return "UnsignedInt8";
+ case 11: return "UnsignedInt16";
+ case 12: return "UnsignedInt32";
+ case 13: return "HalfFloat";
+ case 14: return "Float";
+ case 15: return "UnormInt24";
+ case 16: return "UnormInt101010_2";
+
+ default:
+ return "Bad";
+ }
+}
+
+const int ImageOperandsCeiling = 14;
+
+const char* ImageOperandsString(int format)
+{
+ switch (format) {
+ case ImageOperandsBiasShift: return "Bias";
+ case ImageOperandsLodShift: return "Lod";
+ case ImageOperandsGradShift: return "Grad";
+ case ImageOperandsConstOffsetShift: return "ConstOffset";
+ case ImageOperandsOffsetShift: return "Offset";
+ case ImageOperandsConstOffsetsShift: return "ConstOffsets";
+ case ImageOperandsSampleShift: return "Sample";
+ case ImageOperandsMinLodShift: return "MinLod";
+ case ImageOperandsMakeTexelAvailableKHRShift: return "MakeTexelAvailableKHR";
+ case ImageOperandsMakeTexelVisibleKHRShift: return "MakeTexelVisibleKHR";
+ case ImageOperandsNonPrivateTexelKHRShift: return "NonPrivateTexelKHR";
+ case ImageOperandsVolatileTexelKHRShift: return "VolatileTexelKHR";
+ case ImageOperandsSignExtendShift: return "SignExtend";
+ case ImageOperandsZeroExtendShift: return "ZeroExtend";
+
+ case ImageOperandsCeiling:
+ default:
+ return "Bad";
+ }
+}
+
+const char* FPFastMathString(int mode)
+{
+ switch (mode) {
+ case 0: return "NotNaN";
+ case 1: return "NotInf";
+ case 2: return "NSZ";
+ case 3: return "AllowRecip";
+ case 4: return "Fast";
+
+ default: return "Bad";
+ }
+}
+
+const char* FPRoundingModeString(int mode)
+{
+ switch (mode) {
+ case 0: return "RTE";
+ case 1: return "RTZ";
+ case 2: return "RTP";
+ case 3: return "RTN";
+
+ default: return "Bad";
+ }
+}
+
+const char* LinkageTypeString(int type)
+{
+ switch (type) {
+ case 0: return "Export";
+ case 1: return "Import";
+
+ default: return "Bad";
+ }
+}
+
+const char* FuncParamAttrString(int attr)
+{
+ switch (attr) {
+ case 0: return "Zext";
+ case 1: return "Sext";
+ case 2: return "ByVal";
+ case 3: return "Sret";
+ case 4: return "NoAlias";
+ case 5: return "NoCapture";
+ case 6: return "NoWrite";
+ case 7: return "NoReadWrite";
+
+ default: return "Bad";
+ }
+}
+
+const char* AccessQualifierString(int attr)
+{
+ switch (attr) {
+ case 0: return "ReadOnly";
+ case 1: return "WriteOnly";
+ case 2: return "ReadWrite";
+
+ default: return "Bad";
+ }
+}
+
+const int SelectControlCeiling = 2;
+
+const char* SelectControlString(int cont)
+{
+ switch (cont) {
+ case 0: return "Flatten";
+ case 1: return "DontFlatten";
+
+ case SelectControlCeiling:
+ default: return "Bad";
+ }
+}
+
+const int LoopControlCeiling = LoopControlPartialCountShift + 1;
+
+const char* LoopControlString(int cont)
+{
+ switch (cont) {
+ case LoopControlUnrollShift: return "Unroll";
+ case LoopControlDontUnrollShift: return "DontUnroll";
+ case LoopControlDependencyInfiniteShift: return "DependencyInfinite";
+ case LoopControlDependencyLengthShift: return "DependencyLength";
+ case LoopControlMinIterationsShift: return "MinIterations";
+ case LoopControlMaxIterationsShift: return "MaxIterations";
+ case LoopControlIterationMultipleShift: return "IterationMultiple";
+ case LoopControlPeelCountShift: return "PeelCount";
+ case LoopControlPartialCountShift: return "PartialCount";
+
+ case LoopControlCeiling:
+ default: return "Bad";
+ }
+}
+
+const int FunctionControlCeiling = 4;
+
+const char* FunctionControlString(int cont)
+{
+ switch (cont) {
+ case 0: return "Inline";
+ case 1: return "DontInline";
+ case 2: return "Pure";
+ case 3: return "Const";
+
+ case FunctionControlCeiling:
+ default: return "Bad";
+ }
+}
+
+const char* MemorySemanticsString(int mem)
+{
+ // Note: No bits set (None) means "Relaxed"
+ switch (mem) {
+ case 0: return "Bad"; // Note: this is a placeholder for 'Consume'
+ case 1: return "Acquire";
+ case 2: return "Release";
+ case 3: return "AcquireRelease";
+ case 4: return "SequentiallyConsistent";
+ case 5: return "Bad"; // Note: reserved for future expansion
+ case 6: return "UniformMemory";
+ case 7: return "SubgroupMemory";
+ case 8: return "WorkgroupMemory";
+ case 9: return "CrossWorkgroupMemory";
+ case 10: return "AtomicCounterMemory";
+ case 11: return "ImageMemory";
+
+ default: return "Bad";
+ }
+}
+
+const int MemoryAccessCeiling = 6;
+
+const char* MemoryAccessString(int mem)
+{
+ switch (mem) {
+ case MemoryAccessVolatileShift: return "Volatile";
+ case MemoryAccessAlignedShift: return "Aligned";
+ case MemoryAccessNontemporalShift: return "Nontemporal";
+ case MemoryAccessMakePointerAvailableKHRShift: return "MakePointerAvailableKHR";
+ case MemoryAccessMakePointerVisibleKHRShift: return "MakePointerVisibleKHR";
+ case MemoryAccessNonPrivatePointerKHRShift: return "NonPrivatePointerKHR";
+
+ default: return "Bad";
+ }
+}
+
+const char* ScopeString(int mem)
+{
+ switch (mem) {
+ case 0: return "CrossDevice";
+ case 1: return "Device";
+ case 2: return "Workgroup";
+ case 3: return "Subgroup";
+ case 4: return "Invocation";
+
+ default: return "Bad";
+ }
+}
+
+const char* GroupOperationString(int gop)
+{
+
+ switch (gop)
+ {
+ case GroupOperationReduce: return "Reduce";
+ case GroupOperationInclusiveScan: return "InclusiveScan";
+ case GroupOperationExclusiveScan: return "ExclusiveScan";
+ case GroupOperationClusteredReduce: return "ClusteredReduce";
+ case GroupOperationPartitionedReduceNV: return "PartitionedReduceNV";
+ case GroupOperationPartitionedInclusiveScanNV: return "PartitionedInclusiveScanNV";
+ case GroupOperationPartitionedExclusiveScanNV: return "PartitionedExclusiveScanNV";
+
+ default: return "Bad";
+ }
+}
+
+const char* KernelEnqueueFlagsString(int flag)
+{
+ switch (flag)
+ {
+ case 0: return "NoWait";
+ case 1: return "WaitKernel";
+ case 2: return "WaitWorkGroup";
+
+ default: return "Bad";
+ }
+}
+
+const char* KernelProfilingInfoString(int info)
+{
+ switch (info)
+ {
+ case 0: return "CmdExecTime";
+
+ default: return "Bad";
+ }
+}
+
+const char* CapabilityString(int info)
+{
+ switch (info)
+ {
+ case 0: return "Matrix";
+ case 1: return "Shader";
+ case 2: return "Geometry";
+ case 3: return "Tessellation";
+ case 4: return "Addresses";
+ case 5: return "Linkage";
+ case 6: return "Kernel";
+ case 7: return "Vector16";
+ case 8: return "Float16Buffer";
+ case 9: return "Float16";
+ case 10: return "Float64";
+ case 11: return "Int64";
+ case 12: return "Int64Atomics";
+ case 13: return "ImageBasic";
+ case 14: return "ImageReadWrite";
+ case 15: return "ImageMipmap";
+ case 16: return "Bad";
+ case 17: return "Pipes";
+ case 18: return "Groups";
+ case 19: return "DeviceEnqueue";
+ case 20: return "LiteralSampler";
+ case 21: return "AtomicStorage";
+ case 22: return "Int16";
+ case 23: return "TessellationPointSize";
+ case 24: return "GeometryPointSize";
+ case 25: return "ImageGatherExtended";
+ case 26: return "Bad";
+ case 27: return "StorageImageMultisample";
+ case 28: return "UniformBufferArrayDynamicIndexing";
+ case 29: return "SampledImageArrayDynamicIndexing";
+ case 30: return "StorageBufferArrayDynamicIndexing";
+ case 31: return "StorageImageArrayDynamicIndexing";
+ case 32: return "ClipDistance";
+ case 33: return "CullDistance";
+ case 34: return "ImageCubeArray";
+ case 35: return "SampleRateShading";
+ case 36: return "ImageRect";
+ case 37: return "SampledRect";
+ case 38: return "GenericPointer";
+ case 39: return "Int8";
+ case 40: return "InputAttachment";
+ case 41: return "SparseResidency";
+ case 42: return "MinLod";
+ case 43: return "Sampled1D";
+ case 44: return "Image1D";
+ case 45: return "SampledCubeArray";
+ case 46: return "SampledBuffer";
+ case 47: return "ImageBuffer";
+ case 48: return "ImageMSArray";
+ case 49: return "StorageImageExtendedFormats";
+ case 50: return "ImageQuery";
+ case 51: return "DerivativeControl";
+ case 52: return "InterpolationFunction";
+ case 53: return "TransformFeedback";
+ case 54: return "GeometryStreams";
+ case 55: return "StorageImageReadWithoutFormat";
+ case 56: return "StorageImageWriteWithoutFormat";
+ case 57: return "MultiViewport";
+ case 61: return "GroupNonUniform";
+ case 62: return "GroupNonUniformVote";
+ case 63: return "GroupNonUniformArithmetic";
+ case 64: return "GroupNonUniformBallot";
+ case 65: return "GroupNonUniformShuffle";
+ case 66: return "GroupNonUniformShuffleRelative";
+ case 67: return "GroupNonUniformClustered";
+ case 68: return "GroupNonUniformQuad";
+
+ case CapabilitySubgroupBallotKHR: return "SubgroupBallotKHR";
+ case CapabilityDrawParameters: return "DrawParameters";
+ case CapabilitySubgroupVoteKHR: return "SubgroupVoteKHR";
+
+ case CapabilityStorageUniformBufferBlock16: return "StorageUniformBufferBlock16";
+ case CapabilityStorageUniform16: return "StorageUniform16";
+ case CapabilityStoragePushConstant16: return "StoragePushConstant16";
+ case CapabilityStorageInputOutput16: return "StorageInputOutput16";
+
+ case CapabilityStorageBuffer8BitAccess: return "StorageBuffer8BitAccess";
+ case CapabilityUniformAndStorageBuffer8BitAccess: return "UniformAndStorageBuffer8BitAccess";
+ case CapabilityStoragePushConstant8: return "StoragePushConstant8";
+
+ case CapabilityDeviceGroup: return "DeviceGroup";
+ case CapabilityMultiView: return "MultiView";
+
+ case CapabilityStencilExportEXT: return "StencilExportEXT";
+
+ case CapabilityFloat16ImageAMD: return "Float16ImageAMD";
+ case CapabilityImageGatherBiasLodAMD: return "ImageGatherBiasLodAMD";
+ case CapabilityFragmentMaskAMD: return "FragmentMaskAMD";
+ case CapabilityImageReadWriteLodAMD: return "ImageReadWriteLodAMD";
+
+ case CapabilityAtomicStorageOps: return "AtomicStorageOps";
+
+ case CapabilitySampleMaskPostDepthCoverage: return "SampleMaskPostDepthCoverage";
+ case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
+ case CapabilityShaderViewportIndexLayerNV: return "ShaderViewportIndexLayerNV";
+ case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV";
+ case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";
+ case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
+ case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV";
+ case CapabilityRayTracingNV: return "RayTracingNV";
+ case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV";
+ case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV";
+ case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
+ case CapabilityMeshShadingNV: return "MeshShadingNV";
+ case CapabilityImageFootprintNV: return "ImageFootprintNV";
+// case CapabilityShadingRateNV: return "ShadingRateNV"; // superseded by FragmentDensityEXT
+ case CapabilitySampleMaskOverrideCoverageNV: return "SampleMaskOverrideCoverageNV";
+ case CapabilityFragmentDensityEXT: return "FragmentDensityEXT";
+
+ case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT";
+
+ case CapabilityShaderNonUniformEXT: return "ShaderNonUniformEXT";
+ case CapabilityRuntimeDescriptorArrayEXT: return "RuntimeDescriptorArrayEXT";
+ case CapabilityInputAttachmentArrayDynamicIndexingEXT: return "InputAttachmentArrayDynamicIndexingEXT";
+ case CapabilityUniformTexelBufferArrayDynamicIndexingEXT: return "UniformTexelBufferArrayDynamicIndexingEXT";
+ case CapabilityStorageTexelBufferArrayDynamicIndexingEXT: return "StorageTexelBufferArrayDynamicIndexingEXT";
+ case CapabilityUniformBufferArrayNonUniformIndexingEXT: return "UniformBufferArrayNonUniformIndexingEXT";
+ case CapabilitySampledImageArrayNonUniformIndexingEXT: return "SampledImageArrayNonUniformIndexingEXT";
+ case CapabilityStorageBufferArrayNonUniformIndexingEXT: return "StorageBufferArrayNonUniformIndexingEXT";
+ case CapabilityStorageImageArrayNonUniformIndexingEXT: return "StorageImageArrayNonUniformIndexingEXT";
+ case CapabilityInputAttachmentArrayNonUniformIndexingEXT: return "InputAttachmentArrayNonUniformIndexingEXT";
+ case CapabilityUniformTexelBufferArrayNonUniformIndexingEXT: return "UniformTexelBufferArrayNonUniformIndexingEXT";
+ case CapabilityStorageTexelBufferArrayNonUniformIndexingEXT: return "StorageTexelBufferArrayNonUniformIndexingEXT";
+
+ case CapabilityVulkanMemoryModelKHR: return "VulkanMemoryModelKHR";
+ case CapabilityVulkanMemoryModelDeviceScopeKHR: return "VulkanMemoryModelDeviceScopeKHR";
+
+ case CapabilityPhysicalStorageBufferAddressesEXT: return "PhysicalStorageBufferAddressesEXT";
+
+ case CapabilityVariablePointers: return "VariablePointers";
+
+ case CapabilityCooperativeMatrixNV: return "CooperativeMatrixNV";
+ case CapabilityShaderSMBuiltinsNV: return "ShaderSMBuiltinsNV";
+
+ case CapabilityFragmentShaderSampleInterlockEXT: return "CapabilityFragmentShaderSampleInterlockEXT";
+ case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT";
+ case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT";
+
+ case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT";
+ case CapabilityShaderClockKHR: return "ShaderClockKHR";
+
+ case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL";
+
+ default: return "Bad";
+ }
+}
+
+const char* OpcodeString(int op)
+{
+ switch (op) {
+ case 0: return "OpNop";
+ case 1: return "OpUndef";
+ case 2: return "OpSourceContinued";
+ case 3: return "OpSource";
+ case 4: return "OpSourceExtension";
+ case 5: return "OpName";
+ case 6: return "OpMemberName";
+ case 7: return "OpString";
+ case 8: return "OpLine";
+ case 9: return "Bad";
+ case 10: return "OpExtension";
+ case 11: return "OpExtInstImport";
+ case 12: return "OpExtInst";
+ case 13: return "Bad";
+ case 14: return "OpMemoryModel";
+ case 15: return "OpEntryPoint";
+ case 16: return "OpExecutionMode";
+ case 17: return "OpCapability";
+ case 18: return "Bad";
+ case 19: return "OpTypeVoid";
+ case 20: return "OpTypeBool";
+ case 21: return "OpTypeInt";
+ case 22: return "OpTypeFloat";
+ case 23: return "OpTypeVector";
+ case 24: return "OpTypeMatrix";
+ case 25: return "OpTypeImage";
+ case 26: return "OpTypeSampler";
+ case 27: return "OpTypeSampledImage";
+ case 28: return "OpTypeArray";
+ case 29: return "OpTypeRuntimeArray";
+ case 30: return "OpTypeStruct";
+ case 31: return "OpTypeOpaque";
+ case 32: return "OpTypePointer";
+ case 33: return "OpTypeFunction";
+ case 34: return "OpTypeEvent";
+ case 35: return "OpTypeDeviceEvent";
+ case 36: return "OpTypeReserveId";
+ case 37: return "OpTypeQueue";
+ case 38: return "OpTypePipe";
+ case 39: return "OpTypeForwardPointer";
+ case 40: return "Bad";
+ case 41: return "OpConstantTrue";
+ case 42: return "OpConstantFalse";
+ case 43: return "OpConstant";
+ case 44: return "OpConstantComposite";
+ case 45: return "OpConstantSampler";
+ case 46: return "OpConstantNull";
+ case 47: return "Bad";
+ case 48: return "OpSpecConstantTrue";
+ case 49: return "OpSpecConstantFalse";
+ case 50: return "OpSpecConstant";
+ case 51: return "OpSpecConstantComposite";
+ case 52: return "OpSpecConstantOp";
+ case 53: return "Bad";
+ case 54: return "OpFunction";
+ case 55: return "OpFunctionParameter";
+ case 56: return "OpFunctionEnd";
+ case 57: return "OpFunctionCall";
+ case 58: return "Bad";
+ case 59: return "OpVariable";
+ case 60: return "OpImageTexelPointer";
+ case 61: return "OpLoad";
+ case 62: return "OpStore";
+ case 63: return "OpCopyMemory";
+ case 64: return "OpCopyMemorySized";
+ case 65: return "OpAccessChain";
+ case 66: return "OpInBoundsAccessChain";
+ case 67: return "OpPtrAccessChain";
+ case 68: return "OpArrayLength";
+ case 69: return "OpGenericPtrMemSemantics";
+ case 70: return "OpInBoundsPtrAccessChain";
+ case 71: return "OpDecorate";
+ case 72: return "OpMemberDecorate";
+ case 73: return "OpDecorationGroup";
+ case 74: return "OpGroupDecorate";
+ case 75: return "OpGroupMemberDecorate";
+ case 76: return "Bad";
+ case 77: return "OpVectorExtractDynamic";
+ case 78: return "OpVectorInsertDynamic";
+ case 79: return "OpVectorShuffle";
+ case 80: return "OpCompositeConstruct";
+ case 81: return "OpCompositeExtract";
+ case 82: return "OpCompositeInsert";
+ case 83: return "OpCopyObject";
+ case 84: return "OpTranspose";
+ case OpCopyLogical: return "OpCopyLogical";
+ case 85: return "Bad";
+ case 86: return "OpSampledImage";
+ case 87: return "OpImageSampleImplicitLod";
+ case 88: return "OpImageSampleExplicitLod";
+ case 89: return "OpImageSampleDrefImplicitLod";
+ case 90: return "OpImageSampleDrefExplicitLod";
+ case 91: return "OpImageSampleProjImplicitLod";
+ case 92: return "OpImageSampleProjExplicitLod";
+ case 93: return "OpImageSampleProjDrefImplicitLod";
+ case 94: return "OpImageSampleProjDrefExplicitLod";
+ case 95: return "OpImageFetch";
+ case 96: return "OpImageGather";
+ case 97: return "OpImageDrefGather";
+ case 98: return "OpImageRead";
+ case 99: return "OpImageWrite";
+ case 100: return "OpImage";
+ case 101: return "OpImageQueryFormat";
+ case 102: return "OpImageQueryOrder";
+ case 103: return "OpImageQuerySizeLod";
+ case 104: return "OpImageQuerySize";
+ case 105: return "OpImageQueryLod";
+ case 106: return "OpImageQueryLevels";
+ case 107: return "OpImageQuerySamples";
+ case 108: return "Bad";
+ case 109: return "OpConvertFToU";
+ case 110: return "OpConvertFToS";
+ case 111: return "OpConvertSToF";
+ case 112: return "OpConvertUToF";
+ case 113: return "OpUConvert";
+ case 114: return "OpSConvert";
+ case 115: return "OpFConvert";
+ case 116: return "OpQuantizeToF16";
+ case 117: return "OpConvertPtrToU";
+ case 118: return "OpSatConvertSToU";
+ case 119: return "OpSatConvertUToS";
+ case 120: return "OpConvertUToPtr";
+ case 121: return "OpPtrCastToGeneric";
+ case 122: return "OpGenericCastToPtr";
+ case 123: return "OpGenericCastToPtrExplicit";
+ case 124: return "OpBitcast";
+ case 125: return "Bad";
+ case 126: return "OpSNegate";
+ case 127: return "OpFNegate";
+ case 128: return "OpIAdd";
+ case 129: return "OpFAdd";
+ case 130: return "OpISub";
+ case 131: return "OpFSub";
+ case 132: return "OpIMul";
+ case 133: return "OpFMul";
+ case 134: return "OpUDiv";
+ case 135: return "OpSDiv";
+ case 136: return "OpFDiv";
+ case 137: return "OpUMod";
+ case 138: return "OpSRem";
+ case 139: return "OpSMod";
+ case 140: return "OpFRem";
+ case 141: return "OpFMod";
+ case 142: return "OpVectorTimesScalar";
+ case 143: return "OpMatrixTimesScalar";
+ case 144: return "OpVectorTimesMatrix";
+ case 145: return "OpMatrixTimesVector";
+ case 146: return "OpMatrixTimesMatrix";
+ case 147: return "OpOuterProduct";
+ case 148: return "OpDot";
+ case 149: return "OpIAddCarry";
+ case 150: return "OpISubBorrow";
+ case 151: return "OpUMulExtended";
+ case 152: return "OpSMulExtended";
+ case 153: return "Bad";
+ case 154: return "OpAny";
+ case 155: return "OpAll";
+ case 156: return "OpIsNan";
+ case 157: return "OpIsInf";
+ case 158: return "OpIsFinite";
+ case 159: return "OpIsNormal";
+ case 160: return "OpSignBitSet";
+ case 161: return "OpLessOrGreater";
+ case 162: return "OpOrdered";
+ case 163: return "OpUnordered";
+ case 164: return "OpLogicalEqual";
+ case 165: return "OpLogicalNotEqual";
+ case 166: return "OpLogicalOr";
+ case 167: return "OpLogicalAnd";
+ case 168: return "OpLogicalNot";
+ case 169: return "OpSelect";
+ case 170: return "OpIEqual";
+ case 171: return "OpINotEqual";
+ case 172: return "OpUGreaterThan";
+ case 173: return "OpSGreaterThan";
+ case 174: return "OpUGreaterThanEqual";
+ case 175: return "OpSGreaterThanEqual";
+ case 176: return "OpULessThan";
+ case 177: return "OpSLessThan";
+ case 178: return "OpULessThanEqual";
+ case 179: return "OpSLessThanEqual";
+ case 180: return "OpFOrdEqual";
+ case 181: return "OpFUnordEqual";
+ case 182: return "OpFOrdNotEqual";
+ case 183: return "OpFUnordNotEqual";
+ case 184: return "OpFOrdLessThan";
+ case 185: return "OpFUnordLessThan";
+ case 186: return "OpFOrdGreaterThan";
+ case 187: return "OpFUnordGreaterThan";
+ case 188: return "OpFOrdLessThanEqual";
+ case 189: return "OpFUnordLessThanEqual";
+ case 190: return "OpFOrdGreaterThanEqual";
+ case 191: return "OpFUnordGreaterThanEqual";
+ case 192: return "Bad";
+ case 193: return "Bad";
+ case 194: return "OpShiftRightLogical";
+ case 195: return "OpShiftRightArithmetic";
+ case 196: return "OpShiftLeftLogical";
+ case 197: return "OpBitwiseOr";
+ case 198: return "OpBitwiseXor";
+ case 199: return "OpBitwiseAnd";
+ case 200: return "OpNot";
+ case 201: return "OpBitFieldInsert";
+ case 202: return "OpBitFieldSExtract";
+ case 203: return "OpBitFieldUExtract";
+ case 204: return "OpBitReverse";
+ case 205: return "OpBitCount";
+ case 206: return "Bad";
+ case 207: return "OpDPdx";
+ case 208: return "OpDPdy";
+ case 209: return "OpFwidth";
+ case 210: return "OpDPdxFine";
+ case 211: return "OpDPdyFine";
+ case 212: return "OpFwidthFine";
+ case 213: return "OpDPdxCoarse";
+ case 214: return "OpDPdyCoarse";
+ case 215: return "OpFwidthCoarse";
+ case 216: return "Bad";
+ case 217: return "Bad";
+ case 218: return "OpEmitVertex";
+ case 219: return "OpEndPrimitive";
+ case 220: return "OpEmitStreamVertex";
+ case 221: return "OpEndStreamPrimitive";
+ case 222: return "Bad";
+ case 223: return "Bad";
+ case 224: return "OpControlBarrier";
+ case 225: return "OpMemoryBarrier";
+ case 226: return "Bad";
+ case 227: return "OpAtomicLoad";
+ case 228: return "OpAtomicStore";
+ case 229: return "OpAtomicExchange";
+ case 230: return "OpAtomicCompareExchange";
+ case 231: return "OpAtomicCompareExchangeWeak";
+ case 232: return "OpAtomicIIncrement";
+ case 233: return "OpAtomicIDecrement";
+ case 234: return "OpAtomicIAdd";
+ case 235: return "OpAtomicISub";
+ case 236: return "OpAtomicSMin";
+ case 237: return "OpAtomicUMin";
+ case 238: return "OpAtomicSMax";
+ case 239: return "OpAtomicUMax";
+ case 240: return "OpAtomicAnd";
+ case 241: return "OpAtomicOr";
+ case 242: return "OpAtomicXor";
+ case 243: return "Bad";
+ case 244: return "Bad";
+ case 245: return "OpPhi";
+ case 246: return "OpLoopMerge";
+ case 247: return "OpSelectionMerge";
+ case 248: return "OpLabel";
+ case 249: return "OpBranch";
+ case 250: return "OpBranchConditional";
+ case 251: return "OpSwitch";
+ case 252: return "OpKill";
+ case 253: return "OpReturn";
+ case 254: return "OpReturnValue";
+ case 255: return "OpUnreachable";
+ case 256: return "OpLifetimeStart";
+ case 257: return "OpLifetimeStop";
+ case 258: return "Bad";
+ case 259: return "OpGroupAsyncCopy";
+ case 260: return "OpGroupWaitEvents";
+ case 261: return "OpGroupAll";
+ case 262: return "OpGroupAny";
+ case 263: return "OpGroupBroadcast";
+ case 264: return "OpGroupIAdd";
+ case 265: return "OpGroupFAdd";
+ case 266: return "OpGroupFMin";
+ case 267: return "OpGroupUMin";
+ case 268: return "OpGroupSMin";
+ case 269: return "OpGroupFMax";
+ case 270: return "OpGroupUMax";
+ case 271: return "OpGroupSMax";
+ case 272: return "Bad";
+ case 273: return "Bad";
+ case 274: return "OpReadPipe";
+ case 275: return "OpWritePipe";
+ case 276: return "OpReservedReadPipe";
+ case 277: return "OpReservedWritePipe";
+ case 278: return "OpReserveReadPipePackets";
+ case 279: return "OpReserveWritePipePackets";
+ case 280: return "OpCommitReadPipe";
+ case 281: return "OpCommitWritePipe";
+ case 282: return "OpIsValidReserveId";
+ case 283: return "OpGetNumPipePackets";
+ case 284: return "OpGetMaxPipePackets";
+ case 285: return "OpGroupReserveReadPipePackets";
+ case 286: return "OpGroupReserveWritePipePackets";
+ case 287: return "OpGroupCommitReadPipe";
+ case 288: return "OpGroupCommitWritePipe";
+ case 289: return "Bad";
+ case 290: return "Bad";
+ case 291: return "OpEnqueueMarker";
+ case 292: return "OpEnqueueKernel";
+ case 293: return "OpGetKernelNDrangeSubGroupCount";
+ case 294: return "OpGetKernelNDrangeMaxSubGroupSize";
+ case 295: return "OpGetKernelWorkGroupSize";
+ case 296: return "OpGetKernelPreferredWorkGroupSizeMultiple";
+ case 297: return "OpRetainEvent";
+ case 298: return "OpReleaseEvent";
+ case 299: return "OpCreateUserEvent";
+ case 300: return "OpIsValidEvent";
+ case 301: return "OpSetUserEventStatus";
+ case 302: return "OpCaptureEventProfilingInfo";
+ case 303: return "OpGetDefaultQueue";
+ case 304: return "OpBuildNDRange";
+ case 305: return "OpImageSparseSampleImplicitLod";
+ case 306: return "OpImageSparseSampleExplicitLod";
+ case 307: return "OpImageSparseSampleDrefImplicitLod";
+ case 308: return "OpImageSparseSampleDrefExplicitLod";
+ case 309: return "OpImageSparseSampleProjImplicitLod";
+ case 310: return "OpImageSparseSampleProjExplicitLod";
+ case 311: return "OpImageSparseSampleProjDrefImplicitLod";
+ case 312: return "OpImageSparseSampleProjDrefExplicitLod";
+ case 313: return "OpImageSparseFetch";
+ case 314: return "OpImageSparseGather";
+ case 315: return "OpImageSparseDrefGather";
+ case 316: return "OpImageSparseTexelsResident";
+ case 317: return "OpNoLine";
+ case 318: return "OpAtomicFlagTestAndSet";
+ case 319: return "OpAtomicFlagClear";
+ case 320: return "OpImageSparseRead";
+
+ case OpModuleProcessed: return "OpModuleProcessed";
+ case OpDecorateId: return "OpDecorateId";
+
+ case 333: return "OpGroupNonUniformElect";
+ case 334: return "OpGroupNonUniformAll";
+ case 335: return "OpGroupNonUniformAny";
+ case 336: return "OpGroupNonUniformAllEqual";
+ case 337: return "OpGroupNonUniformBroadcast";
+ case 338: return "OpGroupNonUniformBroadcastFirst";
+ case 339: return "OpGroupNonUniformBallot";
+ case 340: return "OpGroupNonUniformInverseBallot";
+ case 341: return "OpGroupNonUniformBallotBitExtract";
+ case 342: return "OpGroupNonUniformBallotBitCount";
+ case 343: return "OpGroupNonUniformBallotFindLSB";
+ case 344: return "OpGroupNonUniformBallotFindMSB";
+ case 345: return "OpGroupNonUniformShuffle";
+ case 346: return "OpGroupNonUniformShuffleXor";
+ case 347: return "OpGroupNonUniformShuffleUp";
+ case 348: return "OpGroupNonUniformShuffleDown";
+ case 349: return "OpGroupNonUniformIAdd";
+ case 350: return "OpGroupNonUniformFAdd";
+ case 351: return "OpGroupNonUniformIMul";
+ case 352: return "OpGroupNonUniformFMul";
+ case 353: return "OpGroupNonUniformSMin";
+ case 354: return "OpGroupNonUniformUMin";
+ case 355: return "OpGroupNonUniformFMin";
+ case 356: return "OpGroupNonUniformSMax";
+ case 357: return "OpGroupNonUniformUMax";
+ case 358: return "OpGroupNonUniformFMax";
+ case 359: return "OpGroupNonUniformBitwiseAnd";
+ case 360: return "OpGroupNonUniformBitwiseOr";
+ case 361: return "OpGroupNonUniformBitwiseXor";
+ case 362: return "OpGroupNonUniformLogicalAnd";
+ case 363: return "OpGroupNonUniformLogicalOr";
+ case 364: return "OpGroupNonUniformLogicalXor";
+ case 365: return "OpGroupNonUniformQuadBroadcast";
+ case 366: return "OpGroupNonUniformQuadSwap";
+
+ case 4421: return "OpSubgroupBallotKHR";
+ case 4422: return "OpSubgroupFirstInvocationKHR";
+ case 4428: return "OpSubgroupAllKHR";
+ case 4429: return "OpSubgroupAnyKHR";
+ case 4430: return "OpSubgroupAllEqualKHR";
+ case 4432: return "OpSubgroupReadInvocationKHR";
+
+ case 5000: return "OpGroupIAddNonUniformAMD";
+ case 5001: return "OpGroupFAddNonUniformAMD";
+ case 5002: return "OpGroupFMinNonUniformAMD";
+ case 5003: return "OpGroupUMinNonUniformAMD";
+ case 5004: return "OpGroupSMinNonUniformAMD";
+ case 5005: return "OpGroupFMaxNonUniformAMD";
+ case 5006: return "OpGroupUMaxNonUniformAMD";
+ case 5007: return "OpGroupSMaxNonUniformAMD";
+
+ case 5011: return "OpFragmentMaskFetchAMD";
+ case 5012: return "OpFragmentFetchAMD";
+
+ case OpReadClockKHR: return "OpReadClockKHR";
+
+ case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE";
+ case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
+
+ case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV";
+ case OpReportIntersectionNV: return "OpReportIntersectionNV";
+ case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV";
+ case OpTerminateRayNV: return "OpTerminateRayNV";
+ case OpTraceNV: return "OpTraceNV";
+ case OpTypeAccelerationStructureNV: return "OpTypeAccelerationStructureNV";
+ case OpExecuteCallableNV: return "OpExecuteCallableNV";
+ case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV";
+ case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
+
+ case OpTypeCooperativeMatrixNV: return "OpTypeCooperativeMatrixNV";
+ case OpCooperativeMatrixLoadNV: return "OpCooperativeMatrixLoadNV";
+ case OpCooperativeMatrixStoreNV: return "OpCooperativeMatrixStoreNV";
+ case OpCooperativeMatrixMulAddNV: return "OpCooperativeMatrixMulAddNV";
+ case OpCooperativeMatrixLengthNV: return "OpCooperativeMatrixLengthNV";
+ case OpDemoteToHelperInvocationEXT: return "OpDemoteToHelperInvocationEXT";
+ case OpIsHelperInvocationEXT: return "OpIsHelperInvocationEXT";
+
+ case OpBeginInvocationInterlockEXT: return "OpBeginInvocationInterlockEXT";
+ case OpEndInvocationInterlockEXT: return "OpEndInvocationInterlockEXT";
+
+ default:
+ return "Bad";
+ }
+}
+
+// The set of objects that hold all the instruction/operand
+// parameterization information.
+InstructionParameters InstructionDesc[OpCodeMask + 1];
+OperandParameters ExecutionModeOperands[ExecutionModeCeiling];
+OperandParameters DecorationOperands[DecorationCeiling];
+
+EnumDefinition OperandClassParams[OperandCount];
+EnumParameters ExecutionModeParams[ExecutionModeCeiling];
+EnumParameters ImageOperandsParams[ImageOperandsCeiling];
+EnumParameters DecorationParams[DecorationCeiling];
+EnumParameters LoopControlParams[FunctionControlCeiling];
+EnumParameters SelectionControlParams[SelectControlCeiling];
+EnumParameters FunctionControlParams[FunctionControlCeiling];
+EnumParameters MemoryAccessParams[MemoryAccessCeiling];
+
+// Set up all the parameterizing descriptions of the opcodes, operands, etc.
+void Parameterize()
+{
+ // only do this once.
+ static bool initialized = false;
+ if (initialized)
+ return;
+ initialized = true;
+
+ // Exceptions to having a result <id> and a resulting type <id>.
+ // (Everything is initialized to have both).
+
+ InstructionDesc[OpNop].setResultAndType(false, false);
+ InstructionDesc[OpSource].setResultAndType(false, false);
+ InstructionDesc[OpSourceContinued].setResultAndType(false, false);
+ InstructionDesc[OpSourceExtension].setResultAndType(false, false);
+ InstructionDesc[OpExtension].setResultAndType(false, false);
+ InstructionDesc[OpExtInstImport].setResultAndType(true, false);
+ InstructionDesc[OpCapability].setResultAndType(false, false);
+ InstructionDesc[OpMemoryModel].setResultAndType(false, false);
+ InstructionDesc[OpEntryPoint].setResultAndType(false, false);
+ InstructionDesc[OpExecutionMode].setResultAndType(false, false);
+ InstructionDesc[OpTypeVoid].setResultAndType(true, false);
+ InstructionDesc[OpTypeBool].setResultAndType(true, false);
+ InstructionDesc[OpTypeInt].setResultAndType(true, false);
+ InstructionDesc[OpTypeFloat].setResultAndType(true, false);
+ InstructionDesc[OpTypeVector].setResultAndType(true, false);
+ InstructionDesc[OpTypeMatrix].setResultAndType(true, false);
+ InstructionDesc[OpTypeImage].setResultAndType(true, false);
+ InstructionDesc[OpTypeSampler].setResultAndType(true, false);
+ InstructionDesc[OpTypeSampledImage].setResultAndType(true, false);
+ InstructionDesc[OpTypeArray].setResultAndType(true, false);
+ InstructionDesc[OpTypeRuntimeArray].setResultAndType(true, false);
+ InstructionDesc[OpTypeStruct].setResultAndType(true, false);
+ InstructionDesc[OpTypeOpaque].setResultAndType(true, false);
+ InstructionDesc[OpTypePointer].setResultAndType(true, false);
+ InstructionDesc[OpTypeForwardPointer].setResultAndType(false, false);
+ InstructionDesc[OpTypeFunction].setResultAndType(true, false);
+ InstructionDesc[OpTypeEvent].setResultAndType(true, false);
+ InstructionDesc[OpTypeDeviceEvent].setResultAndType(true, false);
+ InstructionDesc[OpTypeReserveId].setResultAndType(true, false);
+ InstructionDesc[OpTypeQueue].setResultAndType(true, false);
+ InstructionDesc[OpTypePipe].setResultAndType(true, false);
+ InstructionDesc[OpFunctionEnd].setResultAndType(false, false);
+ InstructionDesc[OpStore].setResultAndType(false, false);
+ InstructionDesc[OpImageWrite].setResultAndType(false, false);
+ InstructionDesc[OpDecorationGroup].setResultAndType(true, false);
+ InstructionDesc[OpDecorate].setResultAndType(false, false);
+ InstructionDesc[OpDecorateId].setResultAndType(false, false);
+ InstructionDesc[OpDecorateStringGOOGLE].setResultAndType(false, false);
+ InstructionDesc[OpMemberDecorate].setResultAndType(false, false);
+ InstructionDesc[OpMemberDecorateStringGOOGLE].setResultAndType(false, false);
+ InstructionDesc[OpGroupDecorate].setResultAndType(false, false);
+ InstructionDesc[OpGroupMemberDecorate].setResultAndType(false, false);
+ InstructionDesc[OpName].setResultAndType(false, false);
+ InstructionDesc[OpMemberName].setResultAndType(false, false);
+ InstructionDesc[OpString].setResultAndType(true, false);
+ InstructionDesc[OpLine].setResultAndType(false, false);
+ InstructionDesc[OpNoLine].setResultAndType(false, false);
+ InstructionDesc[OpCopyMemory].setResultAndType(false, false);
+ InstructionDesc[OpCopyMemorySized].setResultAndType(false, false);
+ InstructionDesc[OpEmitVertex].setResultAndType(false, false);
+ InstructionDesc[OpEndPrimitive].setResultAndType(false, false);
+ InstructionDesc[OpEmitStreamVertex].setResultAndType(false, false);
+ InstructionDesc[OpEndStreamPrimitive].setResultAndType(false, false);
+ InstructionDesc[OpControlBarrier].setResultAndType(false, false);
+ InstructionDesc[OpMemoryBarrier].setResultAndType(false, false);
+ InstructionDesc[OpAtomicStore].setResultAndType(false, false);
+ InstructionDesc[OpLoopMerge].setResultAndType(false, false);
+ InstructionDesc[OpSelectionMerge].setResultAndType(false, false);
+ InstructionDesc[OpLabel].setResultAndType(true, false);
+ InstructionDesc[OpBranch].setResultAndType(false, false);
+ InstructionDesc[OpBranchConditional].setResultAndType(false, false);
+ InstructionDesc[OpSwitch].setResultAndType(false, false);
+ InstructionDesc[OpKill].setResultAndType(false, false);
+ InstructionDesc[OpReturn].setResultAndType(false, false);
+ InstructionDesc[OpReturnValue].setResultAndType(false, false);
+ InstructionDesc[OpUnreachable].setResultAndType(false, false);
+ InstructionDesc[OpLifetimeStart].setResultAndType(false, false);
+ InstructionDesc[OpLifetimeStop].setResultAndType(false, false);
+ InstructionDesc[OpCommitReadPipe].setResultAndType(false, false);
+ InstructionDesc[OpCommitWritePipe].setResultAndType(false, false);
+ InstructionDesc[OpGroupCommitWritePipe].setResultAndType(false, false);
+ InstructionDesc[OpGroupCommitReadPipe].setResultAndType(false, false);
+ InstructionDesc[OpCaptureEventProfilingInfo].setResultAndType(false, false);
+ InstructionDesc[OpSetUserEventStatus].setResultAndType(false, false);
+ InstructionDesc[OpRetainEvent].setResultAndType(false, false);
+ InstructionDesc[OpReleaseEvent].setResultAndType(false, false);
+ InstructionDesc[OpGroupWaitEvents].setResultAndType(false, false);
+ InstructionDesc[OpAtomicFlagClear].setResultAndType(false, false);
+ InstructionDesc[OpModuleProcessed].setResultAndType(false, false);
+ InstructionDesc[OpTypeCooperativeMatrixNV].setResultAndType(true, false);
+ InstructionDesc[OpCooperativeMatrixStoreNV].setResultAndType(false, false);
+ InstructionDesc[OpBeginInvocationInterlockEXT].setResultAndType(false, false);
+ InstructionDesc[OpEndInvocationInterlockEXT].setResultAndType(false, false);
+
+ // Specific additional context-dependent operands
+
+ ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "'Number of <<Invocation,invocations>>'");
+
+ ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'x size'");
+ ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'y size'");
+ ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'z size'");
+
+ ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'x size'");
+ ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'y size'");
+ ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'z size'");
+
+ ExecutionModeOperands[ExecutionModeOutputVertices].push(OperandLiteralNumber, "'Vertex count'");
+ ExecutionModeOperands[ExecutionModeVecTypeHint].push(OperandLiteralNumber, "'Vector type'");
+
+ DecorationOperands[DecorationStream].push(OperandLiteralNumber, "'Stream Number'");
+ DecorationOperands[DecorationLocation].push(OperandLiteralNumber, "'Location'");
+ DecorationOperands[DecorationComponent].push(OperandLiteralNumber, "'Component'");
+ DecorationOperands[DecorationIndex].push(OperandLiteralNumber, "'Index'");
+ DecorationOperands[DecorationBinding].push(OperandLiteralNumber, "'Binding Point'");
+ DecorationOperands[DecorationDescriptorSet].push(OperandLiteralNumber, "'Descriptor Set'");
+ DecorationOperands[DecorationOffset].push(OperandLiteralNumber, "'Byte Offset'");
+ DecorationOperands[DecorationXfbBuffer].push(OperandLiteralNumber, "'XFB Buffer Number'");
+ DecorationOperands[DecorationXfbStride].push(OperandLiteralNumber, "'XFB Stride'");
+ DecorationOperands[DecorationArrayStride].push(OperandLiteralNumber, "'Array Stride'");
+ DecorationOperands[DecorationMatrixStride].push(OperandLiteralNumber, "'Matrix Stride'");
+ DecorationOperands[DecorationBuiltIn].push(OperandLiteralNumber, "See <<BuiltIn,*BuiltIn*>>");
+ DecorationOperands[DecorationFPRoundingMode].push(OperandFPRoundingMode, "'Floating-Point Rounding Mode'");
+ DecorationOperands[DecorationFPFastMathMode].push(OperandFPFastMath, "'Fast-Math Mode'");
+ DecorationOperands[DecorationLinkageAttributes].push(OperandLiteralString, "'Name'");
+ DecorationOperands[DecorationLinkageAttributes].push(OperandLinkageType, "'Linkage Type'");
+ DecorationOperands[DecorationFuncParamAttr].push(OperandFuncParamAttr, "'Function Parameter Attribute'");
+ DecorationOperands[DecorationSpecId].push(OperandLiteralNumber, "'Specialization Constant ID'");
+ DecorationOperands[DecorationInputAttachmentIndex].push(OperandLiteralNumber, "'Attachment Index'");
+ DecorationOperands[DecorationAlignment].push(OperandLiteralNumber, "'Alignment'");
+
+ OperandClassParams[OperandSource].set(0, SourceString, 0);
+ OperandClassParams[OperandExecutionModel].set(0, ExecutionModelString, nullptr);
+ OperandClassParams[OperandAddressing].set(0, AddressingString, nullptr);
+ OperandClassParams[OperandMemory].set(0, MemoryString, nullptr);
+ OperandClassParams[OperandExecutionMode].set(ExecutionModeCeiling, ExecutionModeString, ExecutionModeParams);
+ OperandClassParams[OperandExecutionMode].setOperands(ExecutionModeOperands);
+ OperandClassParams[OperandStorage].set(0, StorageClassString, nullptr);
+ OperandClassParams[OperandDimensionality].set(0, DimensionString, nullptr);
+ OperandClassParams[OperandSamplerAddressingMode].set(0, SamplerAddressingModeString, nullptr);
+ OperandClassParams[OperandSamplerFilterMode].set(0, SamplerFilterModeString, nullptr);
+ OperandClassParams[OperandSamplerImageFormat].set(0, ImageFormatString, nullptr);
+ OperandClassParams[OperandImageChannelOrder].set(0, ImageChannelOrderString, nullptr);
+ OperandClassParams[OperandImageChannelDataType].set(0, ImageChannelDataTypeString, nullptr);
+ OperandClassParams[OperandImageOperands].set(ImageOperandsCeiling, ImageOperandsString, ImageOperandsParams, true);
+ OperandClassParams[OperandFPFastMath].set(0, FPFastMathString, nullptr, true);
+ OperandClassParams[OperandFPRoundingMode].set(0, FPRoundingModeString, nullptr);
+ OperandClassParams[OperandLinkageType].set(0, LinkageTypeString, nullptr);
+ OperandClassParams[OperandFuncParamAttr].set(0, FuncParamAttrString, nullptr);
+ OperandClassParams[OperandAccessQualifier].set(0, AccessQualifierString, nullptr);
+ OperandClassParams[OperandDecoration].set(DecorationCeiling, DecorationString, DecorationParams);
+ OperandClassParams[OperandDecoration].setOperands(DecorationOperands);
+ OperandClassParams[OperandBuiltIn].set(0, BuiltInString, nullptr);
+ OperandClassParams[OperandSelect].set(SelectControlCeiling, SelectControlString, SelectionControlParams, true);
+ OperandClassParams[OperandLoop].set(LoopControlCeiling, LoopControlString, LoopControlParams, true);
+ OperandClassParams[OperandFunction].set(FunctionControlCeiling, FunctionControlString, FunctionControlParams, true);
+ OperandClassParams[OperandMemorySemantics].set(0, MemorySemanticsString, nullptr, true);
+ OperandClassParams[OperandMemoryAccess].set(MemoryAccessCeiling, MemoryAccessString, MemoryAccessParams, true);
+ OperandClassParams[OperandScope].set(0, ScopeString, nullptr);
+ OperandClassParams[OperandGroupOperation].set(0, GroupOperationString, nullptr);
+ OperandClassParams[OperandKernelEnqueueFlags].set(0, KernelEnqueueFlagsString, nullptr);
+ OperandClassParams[OperandKernelProfilingInfo].set(0, KernelProfilingInfoString, nullptr, true);
+ OperandClassParams[OperandCapability].set(0, CapabilityString, nullptr);
+ OperandClassParams[OperandOpcode].set(OpCodeMask + 1, OpcodeString, 0);
+
+ // set name of operator, an initial set of <id> style operands, and the description
+
+ InstructionDesc[OpSource].operands.push(OperandSource, "");
+ InstructionDesc[OpSource].operands.push(OperandLiteralNumber, "'Version'");
+ InstructionDesc[OpSource].operands.push(OperandId, "'File'", true);
+ InstructionDesc[OpSource].operands.push(OperandLiteralString, "'Source'", true);
+
+ InstructionDesc[OpSourceContinued].operands.push(OperandLiteralString, "'Continued Source'");
+
+ InstructionDesc[OpSourceExtension].operands.push(OperandLiteralString, "'Extension'");
+
+ InstructionDesc[OpName].operands.push(OperandId, "'Target'");
+ InstructionDesc[OpName].operands.push(OperandLiteralString, "'Name'");
+
+ InstructionDesc[OpMemberName].operands.push(OperandId, "'Type'");
+ InstructionDesc[OpMemberName].operands.push(OperandLiteralNumber, "'Member'");
+ InstructionDesc[OpMemberName].operands.push(OperandLiteralString, "'Name'");
+
+ InstructionDesc[OpString].operands.push(OperandLiteralString, "'String'");
+
+ InstructionDesc[OpLine].operands.push(OperandId, "'File'");
+ InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Line'");
+ InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Column'");
+
+ InstructionDesc[OpExtension].operands.push(OperandLiteralString, "'Name'");
+
+ InstructionDesc[OpExtInstImport].operands.push(OperandLiteralString, "'Name'");
+
+ InstructionDesc[OpCapability].operands.push(OperandCapability, "'Capability'");
+
+ InstructionDesc[OpMemoryModel].operands.push(OperandAddressing, "");
+ InstructionDesc[OpMemoryModel].operands.push(OperandMemory, "");
+
+ InstructionDesc[OpEntryPoint].operands.push(OperandExecutionModel, "");
+ InstructionDesc[OpEntryPoint].operands.push(OperandId, "'Entry Point'");
+ InstructionDesc[OpEntryPoint].operands.push(OperandLiteralString, "'Name'");
+ InstructionDesc[OpEntryPoint].operands.push(OperandVariableIds, "'Interface'");
+
+ InstructionDesc[OpExecutionMode].operands.push(OperandId, "'Entry Point'");
+ InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'");
+ InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <<Execution_Mode,Execution Mode>>");
+
+ InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'");
+ InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'");
+
+ InstructionDesc[OpTypeFloat].operands.push(OperandLiteralNumber, "'Width'");
+
+ InstructionDesc[OpTypeVector].operands.push(OperandId, "'Component Type'");
+ InstructionDesc[OpTypeVector].operands.push(OperandLiteralNumber, "'Component Count'");
+
+ InstructionDesc[OpTypeMatrix].operands.push(OperandId, "'Column Type'");
+ InstructionDesc[OpTypeMatrix].operands.push(OperandLiteralNumber, "'Column Count'");
+
+ InstructionDesc[OpTypeImage].operands.push(OperandId, "'Sampled Type'");
+ InstructionDesc[OpTypeImage].operands.push(OperandDimensionality, "");
+ InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Depth'");
+ InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Arrayed'");
+ InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'MS'");
+ InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Sampled'");
+ InstructionDesc[OpTypeImage].operands.push(OperandSamplerImageFormat, "");
+ InstructionDesc[OpTypeImage].operands.push(OperandAccessQualifier, "", true);
+
+ InstructionDesc[OpTypeSampledImage].operands.push(OperandId, "'Image Type'");
+
+ InstructionDesc[OpTypeArray].operands.push(OperandId, "'Element Type'");
+ InstructionDesc[OpTypeArray].operands.push(OperandId, "'Length'");
+
+ InstructionDesc[OpTypeRuntimeArray].operands.push(OperandId, "'Element Type'");
+
+ InstructionDesc[OpTypeStruct].operands.push(OperandVariableIds, "'Member 0 type', +\n'member 1 type', +\n...");
+
+ InstructionDesc[OpTypeOpaque].operands.push(OperandLiteralString, "The name of the opaque type.");
+
+ InstructionDesc[OpTypePointer].operands.push(OperandStorage, "");
+ InstructionDesc[OpTypePointer].operands.push(OperandId, "'Type'");
+
+ InstructionDesc[OpTypeForwardPointer].operands.push(OperandId, "'Pointer Type'");
+ InstructionDesc[OpTypeForwardPointer].operands.push(OperandStorage, "");
+
+ InstructionDesc[OpTypePipe].operands.push(OperandAccessQualifier, "'Qualifier'");
+
+ InstructionDesc[OpTypeFunction].operands.push(OperandId, "'Return Type'");
+ InstructionDesc[OpTypeFunction].operands.push(OperandVariableIds, "'Parameter 0 Type', +\n'Parameter 1 Type', +\n...");
+
+ InstructionDesc[OpConstant].operands.push(OperandVariableLiterals, "'Value'");
+
+ InstructionDesc[OpConstantComposite].operands.push(OperandVariableIds, "'Constituents'");
+
+ InstructionDesc[OpConstantSampler].operands.push(OperandSamplerAddressingMode, "");
+ InstructionDesc[OpConstantSampler].operands.push(OperandLiteralNumber, "'Param'");
+ InstructionDesc[OpConstantSampler].operands.push(OperandSamplerFilterMode, "");
+
+ InstructionDesc[OpSpecConstant].operands.push(OperandVariableLiterals, "'Value'");
+
+ InstructionDesc[OpSpecConstantComposite].operands.push(OperandVariableIds, "'Constituents'");
+
+ InstructionDesc[OpSpecConstantOp].operands.push(OperandLiteralNumber, "'Opcode'");
+ InstructionDesc[OpSpecConstantOp].operands.push(OperandVariableIds, "'Operands'");
+
+ InstructionDesc[OpVariable].operands.push(OperandStorage, "");
+ InstructionDesc[OpVariable].operands.push(OperandId, "'Initializer'", true);
+
+ InstructionDesc[OpFunction].operands.push(OperandFunction, "");
+ InstructionDesc[OpFunction].operands.push(OperandId, "'Function Type'");
+
+ InstructionDesc[OpFunctionCall].operands.push(OperandId, "'Function'");
+ InstructionDesc[OpFunctionCall].operands.push(OperandVariableIds, "'Argument 0', +\n'Argument 1', +\n...");
+
+ InstructionDesc[OpExtInst].operands.push(OperandId, "'Set'");
+ InstructionDesc[OpExtInst].operands.push(OperandLiteralNumber, "'Instruction'");
+ InstructionDesc[OpExtInst].operands.push(OperandVariableIds, "'Operand 1', +\n'Operand 2', +\n...");
+
+ InstructionDesc[OpLoad].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpLoad].operands.push(OperandMemoryAccess, "", true);
+ InstructionDesc[OpLoad].operands.push(OperandLiteralNumber, "", true);
+ InstructionDesc[OpLoad].operands.push(OperandId, "", true);
+
+ InstructionDesc[OpStore].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpStore].operands.push(OperandId, "'Object'");
+ InstructionDesc[OpStore].operands.push(OperandMemoryAccess, "", true);
+ InstructionDesc[OpStore].operands.push(OperandLiteralNumber, "", true);
+ InstructionDesc[OpStore].operands.push(OperandId, "", true);
+
+ InstructionDesc[OpPhi].operands.push(OperandVariableIds, "'Variable, Parent, ...'");
+
+ InstructionDesc[OpDecorate].operands.push(OperandId, "'Target'");
+ InstructionDesc[OpDecorate].operands.push(OperandDecoration, "");
+ InstructionDesc[OpDecorate].operands.push(OperandVariableLiterals, "See <<Decoration,'Decoration'>>.");
+
+ InstructionDesc[OpDecorateId].operands.push(OperandId, "'Target'");
+ InstructionDesc[OpDecorateId].operands.push(OperandDecoration, "");
+ InstructionDesc[OpDecorateId].operands.push(OperandVariableIds, "See <<Decoration,'Decoration'>>.");
+
+ InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'");
+ InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, "");
+ InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'");
+
+ InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'");
+ InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'");
+ InstructionDesc[OpMemberDecorate].operands.push(OperandDecoration, "");
+ InstructionDesc[OpMemberDecorate].operands.push(OperandVariableLiterals, "See <<Decoration,'Decoration'>>.");
+
+ InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'");
+ InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'");
+ InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, "");
+ InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'");
+
+ InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'");
+ InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'");
+
+ InstructionDesc[OpGroupMemberDecorate].operands.push(OperandId, "'Decoration Group'");
+ InstructionDesc[OpGroupMemberDecorate].operands.push(OperandVariableIdLiteral, "'Targets'");
+
+ InstructionDesc[OpVectorExtractDynamic].operands.push(OperandId, "'Vector'");
+ InstructionDesc[OpVectorExtractDynamic].operands.push(OperandId, "'Index'");
+
+ InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Vector'");
+ InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Component'");
+ InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Index'");
+
+ InstructionDesc[OpVectorShuffle].operands.push(OperandId, "'Vector 1'");
+ InstructionDesc[OpVectorShuffle].operands.push(OperandId, "'Vector 2'");
+ InstructionDesc[OpVectorShuffle].operands.push(OperandVariableLiterals, "'Components'");
+
+ InstructionDesc[OpCompositeConstruct].operands.push(OperandVariableIds, "'Constituents'");
+
+ InstructionDesc[OpCompositeExtract].operands.push(OperandId, "'Composite'");
+ InstructionDesc[OpCompositeExtract].operands.push(OperandVariableLiterals, "'Indexes'");
+
+ InstructionDesc[OpCompositeInsert].operands.push(OperandId, "'Object'");
+ InstructionDesc[OpCompositeInsert].operands.push(OperandId, "'Composite'");
+ InstructionDesc[OpCompositeInsert].operands.push(OperandVariableLiterals, "'Indexes'");
+
+ InstructionDesc[OpCopyObject].operands.push(OperandId, "'Operand'");
+
+ InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Target'");
+ InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Source'");
+ InstructionDesc[OpCopyMemory].operands.push(OperandMemoryAccess, "", true);
+
+ InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Target'");
+ InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Source'");
+ InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Size'");
+ InstructionDesc[OpCopyMemorySized].operands.push(OperandMemoryAccess, "", true);
+
+ InstructionDesc[OpSampledImage].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpSampledImage].operands.push(OperandId, "'Sampler'");
+
+ InstructionDesc[OpImage].operands.push(OperandId, "'Sampled Image'");
+
+ InstructionDesc[OpImageRead].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpImageRead].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageRead].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageRead].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageWrite].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpImageWrite].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageWrite].operands.push(OperandId, "'Texel'");
+ InstructionDesc[OpImageWrite].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageWrite].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'");
+ InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'");
+ InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'");
+ InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'");
+ InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageFetch].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpImageFetch].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageFetch].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageFetch].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageGather].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageGather].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageGather].operands.push(OperandId, "'Component'");
+ InstructionDesc[OpImageGather].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageGather].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'D~ref~'");
+ InstructionDesc[OpImageDrefGather].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageDrefGather].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'");
+ InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'");
+ InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'");
+ InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'");
+ InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseFetch].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseFetch].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Component'");
+ InstructionDesc[OpImageSparseGather].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseGather].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'D~ref~'");
+ InstructionDesc[OpImageSparseDrefGather].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseDrefGather].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSparseRead].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSparseRead].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpImageSparseTexelsResident].operands.push(OperandId, "'Resident Code'");
+
+ InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Level of Detail'");
+
+ InstructionDesc[OpImageQuerySize].operands.push(OperandId, "'Image'");
+
+ InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Coordinate'");
+
+ InstructionDesc[OpImageQueryLevels].operands.push(OperandId, "'Image'");
+
+ InstructionDesc[OpImageQuerySamples].operands.push(OperandId, "'Image'");
+
+ InstructionDesc[OpImageQueryFormat].operands.push(OperandId, "'Image'");
+
+ InstructionDesc[OpImageQueryOrder].operands.push(OperandId, "'Image'");
+
+ InstructionDesc[OpAccessChain].operands.push(OperandId, "'Base'");
+ InstructionDesc[OpAccessChain].operands.push(OperandVariableIds, "'Indexes'");
+
+ InstructionDesc[OpInBoundsAccessChain].operands.push(OperandId, "'Base'");
+ InstructionDesc[OpInBoundsAccessChain].operands.push(OperandVariableIds, "'Indexes'");
+
+ InstructionDesc[OpPtrAccessChain].operands.push(OperandId, "'Base'");
+ InstructionDesc[OpPtrAccessChain].operands.push(OperandId, "'Element'");
+ InstructionDesc[OpPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'");
+
+ InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Base'");
+ InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Element'");
+ InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'");
+
+ InstructionDesc[OpSNegate].operands.push(OperandId, "'Operand'");
+
+ InstructionDesc[OpFNegate].operands.push(OperandId, "'Operand'");
+
+ InstructionDesc[OpNot].operands.push(OperandId, "'Operand'");
+
+ InstructionDesc[OpAny].operands.push(OperandId, "'Vector'");
+
+ InstructionDesc[OpAll].operands.push(OperandId, "'Vector'");
+
+ InstructionDesc[OpConvertFToU].operands.push(OperandId, "'Float Value'");
+
+ InstructionDesc[OpConvertFToS].operands.push(OperandId, "'Float Value'");
+
+ InstructionDesc[OpConvertSToF].operands.push(OperandId, "'Signed Value'");
+
+ InstructionDesc[OpConvertUToF].operands.push(OperandId, "'Unsigned Value'");
+
+ InstructionDesc[OpUConvert].operands.push(OperandId, "'Unsigned Value'");
+
+ InstructionDesc[OpSConvert].operands.push(OperandId, "'Signed Value'");
+
+ InstructionDesc[OpFConvert].operands.push(OperandId, "'Float Value'");
+
+ InstructionDesc[OpSatConvertSToU].operands.push(OperandId, "'Signed Value'");
+
+ InstructionDesc[OpSatConvertUToS].operands.push(OperandId, "'Unsigned Value'");
+
+ InstructionDesc[OpConvertPtrToU].operands.push(OperandId, "'Pointer'");
+
+ InstructionDesc[OpConvertUToPtr].operands.push(OperandId, "'Integer Value'");
+
+ InstructionDesc[OpPtrCastToGeneric].operands.push(OperandId, "'Pointer'");
+
+ InstructionDesc[OpGenericCastToPtr].operands.push(OperandId, "'Pointer'");
+
+ InstructionDesc[OpGenericCastToPtrExplicit].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpGenericCastToPtrExplicit].operands.push(OperandStorage, "'Storage'");
+
+ InstructionDesc[OpGenericPtrMemSemantics].operands.push(OperandId, "'Pointer'");
+
+ InstructionDesc[OpBitcast].operands.push(OperandId, "'Operand'");
+
+ InstructionDesc[OpQuantizeToF16].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpTranspose].operands.push(OperandId, "'Matrix'");
+
+ InstructionDesc[OpCopyLogical].operands.push(OperandId, "'Operand'");
+
+ InstructionDesc[OpIsNan].operands.push(OperandId, "'x'");
+
+ InstructionDesc[OpIsInf].operands.push(OperandId, "'x'");
+
+ InstructionDesc[OpIsFinite].operands.push(OperandId, "'x'");
+
+ InstructionDesc[OpIsNormal].operands.push(OperandId, "'x'");
+
+ InstructionDesc[OpSignBitSet].operands.push(OperandId, "'x'");
+
+ InstructionDesc[OpLessOrGreater].operands.push(OperandId, "'x'");
+ InstructionDesc[OpLessOrGreater].operands.push(OperandId, "'y'");
+
+ InstructionDesc[OpOrdered].operands.push(OperandId, "'x'");
+ InstructionDesc[OpOrdered].operands.push(OperandId, "'y'");
+
+ InstructionDesc[OpUnordered].operands.push(OperandId, "'x'");
+ InstructionDesc[OpUnordered].operands.push(OperandId, "'y'");
+
+ InstructionDesc[OpArrayLength].operands.push(OperandId, "'Structure'");
+ InstructionDesc[OpArrayLength].operands.push(OperandLiteralNumber, "'Array member'");
+
+ InstructionDesc[OpIAdd].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpIAdd].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFAdd].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFAdd].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpISub].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpISub].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFSub].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFSub].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpIMul].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpIMul].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFMul].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFMul].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpUDiv].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpUDiv].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpSDiv].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpSDiv].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFDiv].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFDiv].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpUMod].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpUMod].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpSRem].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpSRem].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpSMod].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpSMod].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFRem].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFRem].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFMod].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFMod].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpVectorTimesScalar].operands.push(OperandId, "'Vector'");
+ InstructionDesc[OpVectorTimesScalar].operands.push(OperandId, "'Scalar'");
+
+ InstructionDesc[OpMatrixTimesScalar].operands.push(OperandId, "'Matrix'");
+ InstructionDesc[OpMatrixTimesScalar].operands.push(OperandId, "'Scalar'");
+
+ InstructionDesc[OpVectorTimesMatrix].operands.push(OperandId, "'Vector'");
+ InstructionDesc[OpVectorTimesMatrix].operands.push(OperandId, "'Matrix'");
+
+ InstructionDesc[OpMatrixTimesVector].operands.push(OperandId, "'Matrix'");
+ InstructionDesc[OpMatrixTimesVector].operands.push(OperandId, "'Vector'");
+
+ InstructionDesc[OpMatrixTimesMatrix].operands.push(OperandId, "'LeftMatrix'");
+ InstructionDesc[OpMatrixTimesMatrix].operands.push(OperandId, "'RightMatrix'");
+
+ InstructionDesc[OpOuterProduct].operands.push(OperandId, "'Vector 1'");
+ InstructionDesc[OpOuterProduct].operands.push(OperandId, "'Vector 2'");
+
+ InstructionDesc[OpDot].operands.push(OperandId, "'Vector 1'");
+ InstructionDesc[OpDot].operands.push(OperandId, "'Vector 2'");
+
+ InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Base'");
+ InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Shift'");
+
+ InstructionDesc[OpShiftRightArithmetic].operands.push(OperandId, "'Base'");
+ InstructionDesc[OpShiftRightArithmetic].operands.push(OperandId, "'Shift'");
+
+ InstructionDesc[OpShiftLeftLogical].operands.push(OperandId, "'Base'");
+ InstructionDesc[OpShiftLeftLogical].operands.push(OperandId, "'Shift'");
+
+ InstructionDesc[OpLogicalOr].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpLogicalOr].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpLogicalAnd].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpLogicalAnd].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpLogicalEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpLogicalEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpLogicalNotEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpLogicalNotEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpLogicalNot].operands.push(OperandId, "'Operand'");
+
+ InstructionDesc[OpBitwiseOr].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpBitwiseOr].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpBitwiseXor].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpBitwiseXor].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpBitwiseAnd].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpBitwiseAnd].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Base'");
+ InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Insert'");
+ InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Offset'");
+ InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Count'");
+
+ InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Base'");
+ InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Offset'");
+ InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Count'");
+
+ InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Base'");
+ InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Offset'");
+ InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Count'");
+
+ InstructionDesc[OpBitReverse].operands.push(OperandId, "'Base'");
+
+ InstructionDesc[OpBitCount].operands.push(OperandId, "'Base'");
+
+ InstructionDesc[OpSelect].operands.push(OperandId, "'Condition'");
+ InstructionDesc[OpSelect].operands.push(OperandId, "'Object 1'");
+ InstructionDesc[OpSelect].operands.push(OperandId, "'Object 2'");
+
+ InstructionDesc[OpIEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpIEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFOrdEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFOrdEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFUnordEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFUnordEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpINotEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpINotEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFOrdNotEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFOrdNotEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFUnordNotEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFUnordNotEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpULessThan].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpULessThan].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpSLessThan].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpSLessThan].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFOrdLessThan].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFOrdLessThan].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFUnordLessThan].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFUnordLessThan].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpUGreaterThan].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpUGreaterThan].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpSGreaterThan].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpSGreaterThan].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFOrdGreaterThan].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFOrdGreaterThan].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFUnordGreaterThan].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFUnordGreaterThan].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpULessThanEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpULessThanEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpSLessThanEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpSLessThanEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFOrdLessThanEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFOrdLessThanEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFUnordLessThanEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFUnordLessThanEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpUGreaterThanEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpUGreaterThanEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpSGreaterThanEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpSGreaterThanEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFOrdGreaterThanEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFOrdGreaterThanEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpFUnordGreaterThanEqual].operands.push(OperandId, "'Operand 1'");
+ InstructionDesc[OpFUnordGreaterThanEqual].operands.push(OperandId, "'Operand 2'");
+
+ InstructionDesc[OpDPdx].operands.push(OperandId, "'P'");
+
+ InstructionDesc[OpDPdy].operands.push(OperandId, "'P'");
+
+ InstructionDesc[OpFwidth].operands.push(OperandId, "'P'");
+
+ InstructionDesc[OpDPdxFine].operands.push(OperandId, "'P'");
+
+ InstructionDesc[OpDPdyFine].operands.push(OperandId, "'P'");
+
+ InstructionDesc[OpFwidthFine].operands.push(OperandId, "'P'");
+
+ InstructionDesc[OpDPdxCoarse].operands.push(OperandId, "'P'");
+
+ InstructionDesc[OpDPdyCoarse].operands.push(OperandId, "'P'");
+
+ InstructionDesc[OpFwidthCoarse].operands.push(OperandId, "'P'");
+
+ InstructionDesc[OpEmitStreamVertex].operands.push(OperandId, "'Stream'");
+
+ InstructionDesc[OpEndStreamPrimitive].operands.push(OperandId, "'Stream'");
+
+ InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Memory'");
+ InstructionDesc[OpControlBarrier].operands.push(OperandMemorySemantics, "'Semantics'");
+
+ InstructionDesc[OpMemoryBarrier].operands.push(OperandScope, "'Memory'");
+ InstructionDesc[OpMemoryBarrier].operands.push(OperandMemorySemantics, "'Semantics'");
+
+ InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Sample'");
+
+ InstructionDesc[OpAtomicLoad].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicLoad].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicLoad].operands.push(OperandMemorySemantics, "'Semantics'");
+
+ InstructionDesc[OpAtomicStore].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicStore].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicStore].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicStore].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicExchange].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicExchange].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicExchange].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicExchange].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicCompareExchange].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicCompareExchange].operands.push(OperandMemorySemantics, "'Equal'");
+ InstructionDesc[OpAtomicCompareExchange].operands.push(OperandMemorySemantics, "'Unequal'");
+ InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Value'");
+ InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Comparator'");
+
+ InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandMemorySemantics, "'Equal'");
+ InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandMemorySemantics, "'Unequal'");
+ InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Value'");
+ InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Comparator'");
+
+ InstructionDesc[OpAtomicIIncrement].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicIIncrement].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicIIncrement].operands.push(OperandMemorySemantics, "'Semantics'");
+
+ InstructionDesc[OpAtomicIDecrement].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicIDecrement].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicIDecrement].operands.push(OperandMemorySemantics, "'Semantics'");
+
+ InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicIAdd].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicUMin].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicUMin].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicUMin].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicUMin].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicUMax].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicUMax].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicUMax].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicUMax].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicSMin].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicSMin].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicSMin].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicSMin].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicSMax].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicOr].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicOr].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicOr].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicOr].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicXor].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicXor].operands.push(OperandMemorySemantics, "'Semantics'");
+ InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandMemorySemantics, "'Semantics'");
+
+ InstructionDesc[OpAtomicFlagClear].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpAtomicFlagClear].operands.push(OperandScope, "'Scope'");
+ InstructionDesc[OpAtomicFlagClear].operands.push(OperandMemorySemantics, "'Semantics'");
+
+ InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Merge Block'");
+ InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Continue Target'");
+ InstructionDesc[OpLoopMerge].operands.push(OperandLoop, "");
+ InstructionDesc[OpLoopMerge].operands.push(OperandOptionalLiteral, "");
+
+ InstructionDesc[OpSelectionMerge].operands.push(OperandId, "'Merge Block'");
+ InstructionDesc[OpSelectionMerge].operands.push(OperandSelect, "");
+
+ InstructionDesc[OpBranch].operands.push(OperandId, "'Target Label'");
+
+ InstructionDesc[OpBranchConditional].operands.push(OperandId, "'Condition'");
+ InstructionDesc[OpBranchConditional].operands.push(OperandId, "'True Label'");
+ InstructionDesc[OpBranchConditional].operands.push(OperandId, "'False Label'");
+ InstructionDesc[OpBranchConditional].operands.push(OperandVariableLiterals, "'Branch weights'");
+
+ InstructionDesc[OpSwitch].operands.push(OperandId, "'Selector'");
+ InstructionDesc[OpSwitch].operands.push(OperandId, "'Default'");
+ InstructionDesc[OpSwitch].operands.push(OperandVariableLiteralId, "'Target'");
+
+
+ InstructionDesc[OpReturnValue].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpLifetimeStart].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpLifetimeStart].operands.push(OperandLiteralNumber, "'Size'");
+
+ InstructionDesc[OpLifetimeStop].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpLifetimeStop].operands.push(OperandLiteralNumber, "'Size'");
+
+ InstructionDesc[OpGroupAsyncCopy].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Destination'");
+ InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Source'");
+ InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Num Elements'");
+ InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Stride'");
+ InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Event'");
+
+ InstructionDesc[OpGroupWaitEvents].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Num Events'");
+ InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Events List'");
+
+ InstructionDesc[OpGroupAll].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupAll].operands.push(OperandId, "'Predicate'");
+
+ InstructionDesc[OpGroupAny].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupAny].operands.push(OperandId, "'Predicate'");
+
+ InstructionDesc[OpGroupBroadcast].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupBroadcast].operands.push(OperandId, "'Value'");
+ InstructionDesc[OpGroupBroadcast].operands.push(OperandId, "'LocalId'");
+
+ InstructionDesc[OpGroupIAdd].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupIAdd].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupIAdd].operands.push(OperandId, "'X'");
+
+ InstructionDesc[OpGroupFAdd].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupFAdd].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupFAdd].operands.push(OperandId, "'X'");
+
+ InstructionDesc[OpGroupUMin].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupUMin].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupUMin].operands.push(OperandId, "'X'");
+
+ InstructionDesc[OpGroupSMin].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupSMin].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupSMin].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupFMin].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupFMin].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupFMin].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupUMax].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupUMax].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupUMax].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupSMax].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupSMax].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupSMax].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupFMax].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupFMax].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupFMax].operands.push(OperandId, "X");
+
+ InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Reserve Id'");
+ InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Index'");
+ InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Reserve Id'");
+ InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Index'");
+ InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Num Packets'");
+ InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Num Packets'");
+ InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Reserve Id'");
+ InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Reserve Id'");
+ InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpIsValidReserveId].operands.push(OperandId, "'Reserve Id'");
+
+ InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Num Packets'");
+ InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Num Packets'");
+ InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Reserve Id'");
+ InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Pipe'");
+ InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Reserve Id'");
+ InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Size'");
+ InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Alignment'");
+
+ InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkSize'");
+ InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'LocalWorkSize'");
+ InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkOffset'");
+
+ InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Event'");
+ InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Profiling Info'");
+ InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpSetUserEventStatus].operands.push(OperandId, "'Event'");
+ InstructionDesc[OpSetUserEventStatus].operands.push(OperandId, "'Status'");
+
+ InstructionDesc[OpIsValidEvent].operands.push(OperandId, "'Event'");
+
+ InstructionDesc[OpRetainEvent].operands.push(OperandId, "'Event'");
+
+ InstructionDesc[OpReleaseEvent].operands.push(OperandId, "'Event'");
+
+ InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Invoke'");
+ InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param'");
+ InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param Size'");
+ InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param Align'");
+
+ InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Invoke'");
+ InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param'");
+ InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param Size'");
+ InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param Align'");
+
+ InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'ND Range'");
+ InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Invoke'");
+ InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param'");
+ InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param Size'");
+ InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param Align'");
+
+ InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'ND Range'");
+ InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Invoke'");
+ InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param'");
+ InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param Size'");
+ InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param Align'");
+
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Queue'");
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Flags'");
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'ND Range'");
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Num Events'");
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Wait Events'");
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Ret Event'");
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Invoke'");
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param'");
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param Size'");
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param Align'");
+ InstructionDesc[OpEnqueueKernel].operands.push(OperandVariableIds, "'Local Size'");
+
+ InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Queue'");
+ InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Num Events'");
+ InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Wait Events'");
+ InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Ret Event'");
+
+ InstructionDesc[OpGroupNonUniformElect].operands.push(OperandScope, "'Execution'");
+
+ InstructionDesc[OpGroupNonUniformAll].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformAll].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupNonUniformAny].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformAny].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupNonUniformAllEqual].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformAllEqual].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandId, "ID");
+
+ InstructionDesc[OpGroupNonUniformBroadcastFirst].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformBroadcastFirst].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupNonUniformBallot].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformBallot].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupNonUniformInverseBallot].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformInverseBallot].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandId, "Bit");
+
+ InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupNonUniformBallotFindLSB].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformBallotFindLSB].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupNonUniformBallotFindMSB].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformBallotFindMSB].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandId, "'Id'");
+
+ InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandId, "Mask");
+
+ InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandId, "Offset");
+
+ InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandId, "Offset");
+
+ InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandId, "'ClusterSize'", true);
+
+ InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandId, "'Id'");
+
+ InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X");
+ InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandLiteralNumber, "'Direction'");
+
+ InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'");
+
+ InstructionDesc[OpSubgroupFirstInvocationKHR].operands.push(OperandId, "'Value'");
+
+ InstructionDesc[OpSubgroupAnyKHR].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpSubgroupAnyKHR].operands.push(OperandId, "'Predicate'");
+
+ InstructionDesc[OpSubgroupAllKHR].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpSubgroupAllKHR].operands.push(OperandId, "'Predicate'");
+
+ InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandId, "'Predicate'");
+
+ InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Value'");
+ InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Index'");
+
+ InstructionDesc[OpModuleProcessed].operands.push(OperandLiteralString, "'process'");
+
+ InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandId, "'X'");
+
+ InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandId, "'X'");
+
+ InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandId, "'X'");
+
+ InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandId, "X");
+
+ InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandScope, "'Execution'");
+ InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
+ InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandId, "X");
+
+ InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Coordinate'");
+
+ InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Image'");
+ InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Fragment Index'");
+
+ InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
+
+ InstructionDesc[OpTypeAccelerationStructureNV].setResultAndType(true, false);
+
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'NV Acceleration Structure'");
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'");
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'");
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'");
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Stride'");
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'Miss Index'");
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Origin'");
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMin'");
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Direction'");
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMax'");
+ InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'");
+ InstructionDesc[OpTraceNV].setResultAndType(false, false);
+
+ InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Parameter'");
+ InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Kind'");
+
+ InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false);
+
+ InstructionDesc[OpTerminateRayNV].setResultAndType(false, false);
+
+ InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index");
+ InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID");
+ InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false);
+
+ InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'");
+ InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'");
+ InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Granularity'");
+ InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coarse'");
+ InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandImageOperands, "", true);
+ InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandVariableIds, "", true);
+
+ InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Index Offset'");
+ InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Packed Indices'");
+
+ InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Component Type'");
+ InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Scope'");
+ InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Rows'");
+ InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Columns'");
+
+ InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "'Stride'");
+ InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "'Column Major'");
+ InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandMemoryAccess, "'Memory Access'");
+ InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandLiteralNumber, "", true);
+ InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "", true);
+
+ InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Pointer'");
+ InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Object'");
+ InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Stride'");
+ InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Column Major'");
+ InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandMemoryAccess, "'Memory Access'");
+ InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandLiteralNumber, "", true);
+ InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "", true);
+
+ InstructionDesc[OpCooperativeMatrixMulAddNV].operands.push(OperandId, "'A'");
+ InstructionDesc[OpCooperativeMatrixMulAddNV].operands.push(OperandId, "'B'");
+ InstructionDesc[OpCooperativeMatrixMulAddNV].operands.push(OperandId, "'C'");
+
+ InstructionDesc[OpCooperativeMatrixLengthNV].operands.push(OperandId, "'Type'");
+
+ InstructionDesc[OpDemoteToHelperInvocationEXT].setResultAndType(false, false);
+
+ InstructionDesc[OpReadClockKHR].operands.push(OperandScope, "'Scope'");
+}
+
+}; // end spv namespace
diff --git a/thirdparty/glslang/SPIRV/doc.h b/thirdparty/glslang/SPIRV/doc.h
new file mode 100644
index 0000000000..293256a2c6
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/doc.h
@@ -0,0 +1,258 @@
+//
+// Copyright (C) 2014-2015 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Parameterize the SPIR-V enumerants.
+//
+
+#pragma once
+
+#include "spirv.hpp"
+
+#include <vector>
+
+namespace spv {
+
+// Fill in all the parameters
+void Parameterize();
+
+// Return the English names of all the enums.
+const char* SourceString(int);
+const char* AddressingString(int);
+const char* MemoryString(int);
+const char* ExecutionModelString(int);
+const char* ExecutionModeString(int);
+const char* StorageClassString(int);
+const char* DecorationString(int);
+const char* BuiltInString(int);
+const char* DimensionString(int);
+const char* SelectControlString(int);
+const char* LoopControlString(int);
+const char* FunctionControlString(int);
+const char* SamplerAddressingModeString(int);
+const char* SamplerFilterModeString(int);
+const char* ImageFormatString(int);
+const char* ImageChannelOrderString(int);
+const char* ImageChannelTypeString(int);
+const char* ImageChannelDataTypeString(int type);
+const char* ImageOperandsString(int format);
+const char* ImageOperands(int);
+const char* FPFastMathString(int);
+const char* FPRoundingModeString(int);
+const char* LinkageTypeString(int);
+const char* FuncParamAttrString(int);
+const char* AccessQualifierString(int);
+const char* MemorySemanticsString(int);
+const char* MemoryAccessString(int);
+const char* ExecutionScopeString(int);
+const char* GroupOperationString(int);
+const char* KernelEnqueueFlagsString(int);
+const char* KernelProfilingInfoString(int);
+const char* CapabilityString(int);
+const char* OpcodeString(int);
+const char* ScopeString(int mem);
+
+// For grouping opcodes into subsections
+enum OpcodeClass {
+ OpClassMisc,
+ OpClassDebug,
+ OpClassAnnotate,
+ OpClassExtension,
+ OpClassMode,
+ OpClassType,
+ OpClassConstant,
+ OpClassMemory,
+ OpClassFunction,
+ OpClassImage,
+ OpClassConvert,
+ OpClassComposite,
+ OpClassArithmetic,
+ OpClassBit,
+ OpClassRelationalLogical,
+ OpClassDerivative,
+ OpClassFlowControl,
+ OpClassAtomic,
+ OpClassPrimitive,
+ OpClassBarrier,
+ OpClassGroup,
+ OpClassDeviceSideEnqueue,
+ OpClassPipe,
+
+ OpClassCount,
+ OpClassMissing // all instructions start out as missing
+};
+
+// For parameterizing operands.
+enum OperandClass {
+ OperandNone,
+ OperandId,
+ OperandVariableIds,
+ OperandOptionalLiteral,
+ OperandOptionalLiteralString,
+ OperandVariableLiterals,
+ OperandVariableIdLiteral,
+ OperandVariableLiteralId,
+ OperandLiteralNumber,
+ OperandLiteralString,
+ OperandSource,
+ OperandExecutionModel,
+ OperandAddressing,
+ OperandMemory,
+ OperandExecutionMode,
+ OperandStorage,
+ OperandDimensionality,
+ OperandSamplerAddressingMode,
+ OperandSamplerFilterMode,
+ OperandSamplerImageFormat,
+ OperandImageChannelOrder,
+ OperandImageChannelDataType,
+ OperandImageOperands,
+ OperandFPFastMath,
+ OperandFPRoundingMode,
+ OperandLinkageType,
+ OperandAccessQualifier,
+ OperandFuncParamAttr,
+ OperandDecoration,
+ OperandBuiltIn,
+ OperandSelect,
+ OperandLoop,
+ OperandFunction,
+ OperandMemorySemantics,
+ OperandMemoryAccess,
+ OperandScope,
+ OperandGroupOperation,
+ OperandKernelEnqueueFlags,
+ OperandKernelProfilingInfo,
+ OperandCapability,
+
+ OperandOpcode,
+
+ OperandCount
+};
+
+// Any specific enum can have a set of capabilities that allow it:
+typedef std::vector<Capability> EnumCaps;
+
+// Parameterize a set of operands with their OperandClass(es) and descriptions.
+class OperandParameters {
+public:
+ OperandParameters() { }
+ void push(OperandClass oc, const char* d, bool opt = false)
+ {
+ opClass.push_back(oc);
+ desc.push_back(d);
+ optional.push_back(opt);
+ }
+ void setOptional();
+ OperandClass getClass(int op) const { return opClass[op]; }
+ const char* getDesc(int op) const { return desc[op]; }
+ bool isOptional(int op) const { return optional[op]; }
+ int getNum() const { return (int)opClass.size(); }
+
+protected:
+ std::vector<OperandClass> opClass;
+ std::vector<const char*> desc;
+ std::vector<bool> optional;
+};
+
+// Parameterize an enumerant
+class EnumParameters {
+public:
+ EnumParameters() : desc(0) { }
+ const char* desc;
+};
+
+// Parameterize a set of enumerants that form an enum
+class EnumDefinition : public EnumParameters {
+public:
+ EnumDefinition() :
+ ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { }
+ void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false)
+ {
+ ceiling = ceil;
+ getName = name;
+ bitmask = mask;
+ enumParams = ep;
+ }
+ void setOperands(OperandParameters* op) { operandParams = op; }
+ int ceiling; // ceiling of enumerants
+ bool bitmask; // true if these enumerants combine into a bitmask
+ const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift)
+ EnumParameters* enumParams; // parameters for each individual enumerant
+ OperandParameters* operandParams; // sets of operands
+};
+
+// Parameterize an instruction's logical format, including its known set of operands,
+// per OperandParameters above.
+class InstructionParameters {
+public:
+ InstructionParameters() :
+ opDesc("TBD"),
+ opClass(OpClassMissing),
+ typePresent(true), // most normal, only exceptions have to be spelled out
+ resultPresent(true) // most normal, only exceptions have to be spelled out
+ { }
+
+ void setResultAndType(bool r, bool t)
+ {
+ resultPresent = r;
+ typePresent = t;
+ }
+
+ bool hasResult() const { return resultPresent != 0; }
+ bool hasType() const { return typePresent != 0; }
+
+ const char* opDesc;
+ OpcodeClass opClass;
+ OperandParameters operands;
+
+protected:
+ int typePresent : 1;
+ int resultPresent : 1;
+};
+
+// The set of objects that hold all the instruction/operand
+// parameterization information.
+extern InstructionParameters InstructionDesc[];
+
+// These hold definitions of the enumerants used for operands
+extern EnumDefinition OperandClassParams[];
+
+const char* GetOperandDesc(OperandClass operand);
+void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false);
+const char* AccessQualifierString(int attr);
+
+void PrintOperands(const OperandParameters& operands, int reservedOperands);
+
+} // end namespace spv
diff --git a/thirdparty/glslang/SPIRV/hex_float.h b/thirdparty/glslang/SPIRV/hex_float.h
new file mode 100644
index 0000000000..905b21a45a
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/hex_float.h
@@ -0,0 +1,1078 @@
+// Copyright (c) 2015-2016 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_
+#define LIBSPIRV_UTIL_HEX_FLOAT_H_
+
+#include <cassert>
+#include <cctype>
+#include <cmath>
+#include <cstdint>
+#include <iomanip>
+#include <limits>
+#include <sstream>
+
+#if defined(_MSC_VER) && _MSC_VER < 1800
+namespace std {
+bool isnan(double f)
+{
+ return ::_isnan(f) != 0;
+}
+bool isinf(double f)
+{
+ return ::_finite(f) == 0;
+}
+}
+#endif
+
+#include "bitutils.h"
+
+namespace spvutils {
+
+class Float16 {
+ public:
+ Float16(uint16_t v) : val(v) {}
+ Float16() {}
+ static bool isNan(const Float16& val) {
+ return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0);
+ }
+ // Returns true if the given value is any kind of infinity.
+ static bool isInfinity(const Float16& val) {
+ return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0);
+ }
+ Float16(const Float16& other) { val = other.val; }
+ uint16_t get_value() const { return val; }
+
+ // Returns the maximum normal value.
+ static Float16 max() { return Float16(0x7bff); }
+ // Returns the lowest normal value.
+ static Float16 lowest() { return Float16(0xfbff); }
+
+ private:
+ uint16_t val;
+};
+
+// To specialize this type, you must override uint_type to define
+// an unsigned integer that can fit your floating point type.
+// You must also add a isNan function that returns true if
+// a value is Nan.
+template <typename T>
+struct FloatProxyTraits {
+ typedef void uint_type;
+};
+
+template <>
+struct FloatProxyTraits<float> {
+ typedef uint32_t uint_type;
+ static bool isNan(float f) { return std::isnan(f); }
+ // Returns true if the given value is any kind of infinity.
+ static bool isInfinity(float f) { return std::isinf(f); }
+ // Returns the maximum normal value.
+ static float max() { return std::numeric_limits<float>::max(); }
+ // Returns the lowest normal value.
+ static float lowest() { return std::numeric_limits<float>::lowest(); }
+};
+
+template <>
+struct FloatProxyTraits<double> {
+ typedef uint64_t uint_type;
+ static bool isNan(double f) { return std::isnan(f); }
+ // Returns true if the given value is any kind of infinity.
+ static bool isInfinity(double f) { return std::isinf(f); }
+ // Returns the maximum normal value.
+ static double max() { return std::numeric_limits<double>::max(); }
+ // Returns the lowest normal value.
+ static double lowest() { return std::numeric_limits<double>::lowest(); }
+};
+
+template <>
+struct FloatProxyTraits<Float16> {
+ typedef uint16_t uint_type;
+ static bool isNan(Float16 f) { return Float16::isNan(f); }
+ // Returns true if the given value is any kind of infinity.
+ static bool isInfinity(Float16 f) { return Float16::isInfinity(f); }
+ // Returns the maximum normal value.
+ static Float16 max() { return Float16::max(); }
+ // Returns the lowest normal value.
+ static Float16 lowest() { return Float16::lowest(); }
+};
+
+// Since copying a floating point number (especially if it is NaN)
+// does not guarantee that bits are preserved, this class lets us
+// store the type and use it as a float when necessary.
+template <typename T>
+class FloatProxy {
+ public:
+ typedef typename FloatProxyTraits<T>::uint_type uint_type;
+
+ // Since this is to act similar to the normal floats,
+ // do not initialize the data by default.
+ FloatProxy() {}
+
+ // Intentionally non-explicit. This is a proxy type so
+ // implicit conversions allow us to use it more transparently.
+ FloatProxy(T val) { data_ = BitwiseCast<uint_type>(val); }
+
+ // Intentionally non-explicit. This is a proxy type so
+ // implicit conversions allow us to use it more transparently.
+ FloatProxy(uint_type val) { data_ = val; }
+
+ // This is helpful to have and is guaranteed not to stomp bits.
+ FloatProxy<T> operator-() const {
+ return static_cast<uint_type>(data_ ^
+ (uint_type(0x1) << (sizeof(T) * 8 - 1)));
+ }
+
+ // Returns the data as a floating point value.
+ T getAsFloat() const { return BitwiseCast<T>(data_); }
+
+ // Returns the raw data.
+ uint_type data() const { return data_; }
+
+ // Returns true if the value represents any type of NaN.
+ bool isNan() { return FloatProxyTraits<T>::isNan(getAsFloat()); }
+ // Returns true if the value represents any type of infinity.
+ bool isInfinity() { return FloatProxyTraits<T>::isInfinity(getAsFloat()); }
+
+ // Returns the maximum normal value.
+ static FloatProxy<T> max() {
+ return FloatProxy<T>(FloatProxyTraits<T>::max());
+ }
+ // Returns the lowest normal value.
+ static FloatProxy<T> lowest() {
+ return FloatProxy<T>(FloatProxyTraits<T>::lowest());
+ }
+
+ private:
+ uint_type data_;
+};
+
+template <typename T>
+bool operator==(const FloatProxy<T>& first, const FloatProxy<T>& second) {
+ return first.data() == second.data();
+}
+
+// Reads a FloatProxy value as a normal float from a stream.
+template <typename T>
+std::istream& operator>>(std::istream& is, FloatProxy<T>& value) {
+ T float_val;
+ is >> float_val;
+ value = FloatProxy<T>(float_val);
+ return is;
+}
+
+// This is an example traits. It is not meant to be used in practice, but will
+// be the default for any non-specialized type.
+template <typename T>
+struct HexFloatTraits {
+ // Integer type that can store this hex-float.
+ typedef void uint_type;
+ // Signed integer type that can store this hex-float.
+ typedef void int_type;
+ // The numerical type that this HexFloat represents.
+ typedef void underlying_type;
+ // The type needed to construct the underlying type.
+ typedef void native_type;
+ // The number of bits that are actually relevant in the uint_type.
+ // This allows us to deal with, for example, 24-bit values in a 32-bit
+ // integer.
+ static const uint32_t num_used_bits = 0;
+ // Number of bits that represent the exponent.
+ static const uint32_t num_exponent_bits = 0;
+ // Number of bits that represent the fractional part.
+ static const uint32_t num_fraction_bits = 0;
+ // The bias of the exponent. (How much we need to subtract from the stored
+ // value to get the correct value.)
+ static const uint32_t exponent_bias = 0;
+};
+
+// Traits for IEEE float.
+// 1 sign bit, 8 exponent bits, 23 fractional bits.
+template <>
+struct HexFloatTraits<FloatProxy<float>> {
+ typedef uint32_t uint_type;
+ typedef int32_t int_type;
+ typedef FloatProxy<float> underlying_type;
+ typedef float native_type;
+ static const uint_type num_used_bits = 32;
+ static const uint_type num_exponent_bits = 8;
+ static const uint_type num_fraction_bits = 23;
+ static const uint_type exponent_bias = 127;
+};
+
+// Traits for IEEE double.
+// 1 sign bit, 11 exponent bits, 52 fractional bits.
+template <>
+struct HexFloatTraits<FloatProxy<double>> {
+ typedef uint64_t uint_type;
+ typedef int64_t int_type;
+ typedef FloatProxy<double> underlying_type;
+ typedef double native_type;
+ static const uint_type num_used_bits = 64;
+ static const uint_type num_exponent_bits = 11;
+ static const uint_type num_fraction_bits = 52;
+ static const uint_type exponent_bias = 1023;
+};
+
+// Traits for IEEE half.
+// 1 sign bit, 5 exponent bits, 10 fractional bits.
+template <>
+struct HexFloatTraits<FloatProxy<Float16>> {
+ typedef uint16_t uint_type;
+ typedef int16_t int_type;
+ typedef uint16_t underlying_type;
+ typedef uint16_t native_type;
+ static const uint_type num_used_bits = 16;
+ static const uint_type num_exponent_bits = 5;
+ static const uint_type num_fraction_bits = 10;
+ static const uint_type exponent_bias = 15;
+};
+
+enum round_direction {
+ kRoundToZero,
+ kRoundToNearestEven,
+ kRoundToPositiveInfinity,
+ kRoundToNegativeInfinity
+};
+
+// Template class that houses a floating pointer number.
+// It exposes a number of constants based on the provided traits to
+// assist in interpreting the bits of the value.
+template <typename T, typename Traits = HexFloatTraits<T>>
+class HexFloat {
+ public:
+ typedef typename Traits::uint_type uint_type;
+ typedef typename Traits::int_type int_type;
+ typedef typename Traits::underlying_type underlying_type;
+ typedef typename Traits::native_type native_type;
+
+ explicit HexFloat(T f) : value_(f) {}
+
+ T value() const { return value_; }
+ void set_value(T f) { value_ = f; }
+
+ // These are all written like this because it is convenient to have
+ // compile-time constants for all of these values.
+
+ // Pass-through values to save typing.
+ static const uint32_t num_used_bits = Traits::num_used_bits;
+ static const uint32_t exponent_bias = Traits::exponent_bias;
+ static const uint32_t num_exponent_bits = Traits::num_exponent_bits;
+ static const uint32_t num_fraction_bits = Traits::num_fraction_bits;
+
+ // Number of bits to shift left to set the highest relevant bit.
+ static const uint32_t top_bit_left_shift = num_used_bits - 1;
+ // How many nibbles (hex characters) the fractional part takes up.
+ static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4;
+ // If the fractional part does not fit evenly into a hex character (4-bits)
+ // then we have to left-shift to get rid of leading 0s. This is the amount
+ // we have to shift (might be 0).
+ static const uint32_t num_overflow_bits =
+ fraction_nibbles * 4 - num_fraction_bits;
+
+ // The representation of the fraction, not the actual bits. This
+ // includes the leading bit that is usually implicit.
+ static const uint_type fraction_represent_mask =
+ spvutils::SetBits<uint_type, 0,
+ num_fraction_bits + num_overflow_bits>::get;
+
+ // The topmost bit in the nibble-aligned fraction.
+ static const uint_type fraction_top_bit =
+ uint_type(1) << (num_fraction_bits + num_overflow_bits - 1);
+
+ // The least significant bit in the exponent, which is also the bit
+ // immediately to the left of the significand.
+ static const uint_type first_exponent_bit = uint_type(1)
+ << (num_fraction_bits);
+
+ // The mask for the encoded fraction. It does not include the
+ // implicit bit.
+ static const uint_type fraction_encode_mask =
+ spvutils::SetBits<uint_type, 0, num_fraction_bits>::get;
+
+ // The bit that is used as a sign.
+ static const uint_type sign_mask = uint_type(1) << top_bit_left_shift;
+
+ // The bits that represent the exponent.
+ static const uint_type exponent_mask =
+ spvutils::SetBits<uint_type, num_fraction_bits, num_exponent_bits>::get;
+
+ // How far left the exponent is shifted.
+ static const uint32_t exponent_left_shift = num_fraction_bits;
+
+ // How far from the right edge the fraction is shifted.
+ static const uint32_t fraction_right_shift =
+ static_cast<uint32_t>(sizeof(uint_type) * 8) - num_fraction_bits;
+
+ // The maximum representable unbiased exponent.
+ static const int_type max_exponent =
+ (exponent_mask >> num_fraction_bits) - exponent_bias;
+ // The minimum representable exponent for normalized numbers.
+ static const int_type min_exponent = -static_cast<int_type>(exponent_bias);
+
+ // Returns the bits associated with the value.
+ uint_type getBits() const { return spvutils::BitwiseCast<uint_type>(value_); }
+
+ // Returns the bits associated with the value, without the leading sign bit.
+ uint_type getUnsignedBits() const {
+ return static_cast<uint_type>(spvutils::BitwiseCast<uint_type>(value_) &
+ ~sign_mask);
+ }
+
+ // Returns the bits associated with the exponent, shifted to start at the
+ // lsb of the type.
+ const uint_type getExponentBits() const {
+ return static_cast<uint_type>((getBits() & exponent_mask) >>
+ num_fraction_bits);
+ }
+
+ // Returns the exponent in unbiased form. This is the exponent in the
+ // human-friendly form.
+ const int_type getUnbiasedExponent() const {
+ return static_cast<int_type>(getExponentBits() - exponent_bias);
+ }
+
+ // Returns just the significand bits from the value.
+ const uint_type getSignificandBits() const {
+ return getBits() & fraction_encode_mask;
+ }
+
+ // If the number was normalized, returns the unbiased exponent.
+ // If the number was denormal, normalize the exponent first.
+ const int_type getUnbiasedNormalizedExponent() const {
+ if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0
+ return 0;
+ }
+ int_type exp = getUnbiasedExponent();
+ if (exp == min_exponent) { // We are in denorm land.
+ uint_type significand_bits = getSignificandBits();
+ while ((significand_bits & (first_exponent_bit >> 1)) == 0) {
+ significand_bits = static_cast<uint_type>(significand_bits << 1);
+ exp = static_cast<int_type>(exp - 1);
+ }
+ significand_bits &= fraction_encode_mask;
+ }
+ return exp;
+ }
+
+ // Returns the signficand after it has been normalized.
+ const uint_type getNormalizedSignificand() const {
+ int_type unbiased_exponent = getUnbiasedNormalizedExponent();
+ uint_type significand = getSignificandBits();
+ for (int_type i = unbiased_exponent; i <= min_exponent; ++i) {
+ significand = static_cast<uint_type>(significand << 1);
+ }
+ significand &= fraction_encode_mask;
+ return significand;
+ }
+
+ // Returns true if this number represents a negative value.
+ bool isNegative() const { return (getBits() & sign_mask) != 0; }
+
+ // Sets this HexFloat from the individual components.
+ // Note this assumes EVERY significand is normalized, and has an implicit
+ // leading one. This means that the only way that this method will set 0,
+ // is if you set a number so denormalized that it underflows.
+ // Do not use this method with raw bits extracted from a subnormal number,
+ // since subnormals do not have an implicit leading 1 in the significand.
+ // The significand is also expected to be in the
+ // lowest-most num_fraction_bits of the uint_type.
+ // The exponent is expected to be unbiased, meaning an exponent of
+ // 0 actually means 0.
+ // If underflow_round_up is set, then on underflow, if a number is non-0
+ // and would underflow, we round up to the smallest denorm.
+ void setFromSignUnbiasedExponentAndNormalizedSignificand(
+ bool negative, int_type exponent, uint_type significand,
+ bool round_denorm_up) {
+ bool significand_is_zero = significand == 0;
+
+ if (exponent <= min_exponent) {
+ // If this was denormalized, then we have to shift the bit on, meaning
+ // the significand is not zero.
+ significand_is_zero = false;
+ significand |= first_exponent_bit;
+ significand = static_cast<uint_type>(significand >> 1);
+ }
+
+ while (exponent < min_exponent) {
+ significand = static_cast<uint_type>(significand >> 1);
+ ++exponent;
+ }
+
+ if (exponent == min_exponent) {
+ if (significand == 0 && !significand_is_zero && round_denorm_up) {
+ significand = static_cast<uint_type>(0x1);
+ }
+ }
+
+ uint_type new_value = 0;
+ if (negative) {
+ new_value = static_cast<uint_type>(new_value | sign_mask);
+ }
+ exponent = static_cast<int_type>(exponent + exponent_bias);
+ assert(exponent >= 0);
+
+ // put it all together
+ exponent = static_cast<uint_type>((exponent << exponent_left_shift) &
+ exponent_mask);
+ significand = static_cast<uint_type>(significand & fraction_encode_mask);
+ new_value = static_cast<uint_type>(new_value | (exponent | significand));
+ value_ = BitwiseCast<T>(new_value);
+ }
+
+ // Increments the significand of this number by the given amount.
+ // If this would spill the significand into the implicit bit,
+ // carry is set to true and the significand is shifted to fit into
+ // the correct location, otherwise carry is set to false.
+ // All significands and to_increment are assumed to be within the bounds
+ // for a valid significand.
+ static uint_type incrementSignificand(uint_type significand,
+ uint_type to_increment, bool* carry) {
+ significand = static_cast<uint_type>(significand + to_increment);
+ *carry = false;
+ if (significand & first_exponent_bit) {
+ *carry = true;
+ // The implicit 1-bit will have carried, so we should zero-out the
+ // top bit and shift back.
+ significand = static_cast<uint_type>(significand & ~first_exponent_bit);
+ significand = static_cast<uint_type>(significand >> 1);
+ }
+ return significand;
+ }
+
+ // These exist because MSVC throws warnings on negative right-shifts
+ // even if they are not going to be executed. Eg:
+ // constant_number < 0? 0: constant_number
+ // These convert the negative left-shifts into right shifts.
+
+ template <typename int_type>
+ uint_type negatable_left_shift(int_type N, uint_type val)
+ {
+ if(N >= 0)
+ return val << N;
+
+ return val >> -N;
+ }
+
+ template <typename int_type>
+ uint_type negatable_right_shift(int_type N, uint_type val)
+ {
+ if(N >= 0)
+ return val >> N;
+
+ return val << -N;
+ }
+
+ // Returns the significand, rounded to fit in a significand in
+ // other_T. This is shifted so that the most significant
+ // bit of the rounded number lines up with the most significant bit
+ // of the returned significand.
+ template <typename other_T>
+ typename other_T::uint_type getRoundedNormalizedSignificand(
+ round_direction dir, bool* carry_bit) {
+ typedef typename other_T::uint_type other_uint_type;
+ static const int_type num_throwaway_bits =
+ static_cast<int_type>(num_fraction_bits) -
+ static_cast<int_type>(other_T::num_fraction_bits);
+
+ static const uint_type last_significant_bit =
+ (num_throwaway_bits < 0)
+ ? 0
+ : negatable_left_shift(num_throwaway_bits, 1u);
+ static const uint_type first_rounded_bit =
+ (num_throwaway_bits < 1)
+ ? 0
+ : negatable_left_shift(num_throwaway_bits - 1, 1u);
+
+ static const uint_type throwaway_mask_bits =
+ num_throwaway_bits > 0 ? num_throwaway_bits : 0;
+ static const uint_type throwaway_mask =
+ spvutils::SetBits<uint_type, 0, throwaway_mask_bits>::get;
+
+ *carry_bit = false;
+ other_uint_type out_val = 0;
+ uint_type significand = getNormalizedSignificand();
+ // If we are up-casting, then we just have to shift to the right location.
+ if (num_throwaway_bits <= 0) {
+ out_val = static_cast<other_uint_type>(significand);
+ uint_type shift_amount = static_cast<uint_type>(-num_throwaway_bits);
+ out_val = static_cast<other_uint_type>(out_val << shift_amount);
+ return out_val;
+ }
+
+ // If every non-representable bit is 0, then we don't have any casting to
+ // do.
+ if ((significand & throwaway_mask) == 0) {
+ return static_cast<other_uint_type>(
+ negatable_right_shift(num_throwaway_bits, significand));
+ }
+
+ bool round_away_from_zero = false;
+ // We actually have to narrow the significand here, so we have to follow the
+ // rounding rules.
+ switch (dir) {
+ case kRoundToZero:
+ break;
+ case kRoundToPositiveInfinity:
+ round_away_from_zero = !isNegative();
+ break;
+ case kRoundToNegativeInfinity:
+ round_away_from_zero = isNegative();
+ break;
+ case kRoundToNearestEven:
+ // Have to round down, round bit is 0
+ if ((first_rounded_bit & significand) == 0) {
+ break;
+ }
+ if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) {
+ // If any subsequent bit of the rounded portion is non-0 then we round
+ // up.
+ round_away_from_zero = true;
+ break;
+ }
+ // We are exactly half-way between 2 numbers, pick even.
+ if ((significand & last_significant_bit) != 0) {
+ // 1 for our last bit, round up.
+ round_away_from_zero = true;
+ break;
+ }
+ break;
+ }
+
+ if (round_away_from_zero) {
+ return static_cast<other_uint_type>(
+ negatable_right_shift(num_throwaway_bits, incrementSignificand(
+ significand, last_significant_bit, carry_bit)));
+ } else {
+ return static_cast<other_uint_type>(
+ negatable_right_shift(num_throwaway_bits, significand));
+ }
+ }
+
+ // Casts this value to another HexFloat. If the cast is widening,
+ // then round_dir is ignored. If the cast is narrowing, then
+ // the result is rounded in the direction specified.
+ // This number will retain Nan and Inf values.
+ // It will also saturate to Inf if the number overflows, and
+ // underflow to (0 or min depending on rounding) if the number underflows.
+ template <typename other_T>
+ void castTo(other_T& other, round_direction round_dir) {
+ other = other_T(static_cast<typename other_T::native_type>(0));
+ bool negate = isNegative();
+ if (getUnsignedBits() == 0) {
+ if (negate) {
+ other.set_value(-other.value());
+ }
+ return;
+ }
+ uint_type significand = getSignificandBits();
+ bool carried = false;
+ typename other_T::uint_type rounded_significand =
+ getRoundedNormalizedSignificand<other_T>(round_dir, &carried);
+
+ int_type exponent = getUnbiasedExponent();
+ if (exponent == min_exponent) {
+ // If we are denormal, normalize the exponent, so that we can encode
+ // easily.
+ exponent = static_cast<int_type>(exponent + 1);
+ for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0;
+ check_bit = static_cast<uint_type>(check_bit >> 1)) {
+ exponent = static_cast<int_type>(exponent - 1);
+ if (check_bit & significand) break;
+ }
+ }
+
+ bool is_nan =
+ (getBits() & exponent_mask) == exponent_mask && significand != 0;
+ bool is_inf =
+ !is_nan &&
+ ((exponent + carried) > static_cast<int_type>(other_T::exponent_bias) ||
+ (significand == 0 && (getBits() & exponent_mask) == exponent_mask));
+
+ // If we are Nan or Inf we should pass that through.
+ if (is_inf) {
+ other.set_value(BitwiseCast<typename other_T::underlying_type>(
+ static_cast<typename other_T::uint_type>(
+ (negate ? other_T::sign_mask : 0) | other_T::exponent_mask)));
+ return;
+ }
+ if (is_nan) {
+ typename other_T::uint_type shifted_significand;
+ shifted_significand = static_cast<typename other_T::uint_type>(
+ negatable_left_shift(
+ static_cast<int_type>(other_T::num_fraction_bits) -
+ static_cast<int_type>(num_fraction_bits), significand));
+
+ // We are some sort of Nan. We try to keep the bit-pattern of the Nan
+ // as close as possible. If we had to shift off bits so we are 0, then we
+ // just set the last bit.
+ other.set_value(BitwiseCast<typename other_T::underlying_type>(
+ static_cast<typename other_T::uint_type>(
+ (negate ? other_T::sign_mask : 0) | other_T::exponent_mask |
+ (shifted_significand == 0 ? 0x1 : shifted_significand))));
+ return;
+ }
+
+ bool round_underflow_up =
+ isNegative() ? round_dir == kRoundToNegativeInfinity
+ : round_dir == kRoundToPositiveInfinity;
+ typedef typename other_T::int_type other_int_type;
+ // setFromSignUnbiasedExponentAndNormalizedSignificand will
+ // zero out any underflowing value (but retain the sign).
+ other.setFromSignUnbiasedExponentAndNormalizedSignificand(
+ negate, static_cast<other_int_type>(exponent), rounded_significand,
+ round_underflow_up);
+ return;
+ }
+
+ private:
+ T value_;
+
+ static_assert(num_used_bits ==
+ Traits::num_exponent_bits + Traits::num_fraction_bits + 1,
+ "The number of bits do not fit");
+ static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match");
+};
+
+// Returns 4 bits represented by the hex character.
+inline uint8_t get_nibble_from_character(int character) {
+ const char* dec = "0123456789";
+ const char* lower = "abcdef";
+ const char* upper = "ABCDEF";
+ const char* p = nullptr;
+ if ((p = strchr(dec, character))) {
+ return static_cast<uint8_t>(p - dec);
+ } else if ((p = strchr(lower, character))) {
+ return static_cast<uint8_t>(p - lower + 0xa);
+ } else if ((p = strchr(upper, character))) {
+ return static_cast<uint8_t>(p - upper + 0xa);
+ }
+
+ assert(false && "This was called with a non-hex character");
+ return 0;
+}
+
+// Outputs the given HexFloat to the stream.
+template <typename T, typename Traits>
+std::ostream& operator<<(std::ostream& os, const HexFloat<T, Traits>& value) {
+ typedef HexFloat<T, Traits> HF;
+ typedef typename HF::uint_type uint_type;
+ typedef typename HF::int_type int_type;
+
+ static_assert(HF::num_used_bits != 0,
+ "num_used_bits must be non-zero for a valid float");
+ static_assert(HF::num_exponent_bits != 0,
+ "num_exponent_bits must be non-zero for a valid float");
+ static_assert(HF::num_fraction_bits != 0,
+ "num_fractin_bits must be non-zero for a valid float");
+
+ const uint_type bits = spvutils::BitwiseCast<uint_type>(value.value());
+ const char* const sign = (bits & HF::sign_mask) ? "-" : "";
+ const uint_type exponent = static_cast<uint_type>(
+ (bits & HF::exponent_mask) >> HF::num_fraction_bits);
+
+ uint_type fraction = static_cast<uint_type>((bits & HF::fraction_encode_mask)
+ << HF::num_overflow_bits);
+
+ const bool is_zero = exponent == 0 && fraction == 0;
+ const bool is_denorm = exponent == 0 && !is_zero;
+
+ // exponent contains the biased exponent we have to convert it back into
+ // the normal range.
+ int_type int_exponent = static_cast<int_type>(exponent - HF::exponent_bias);
+ // If the number is all zeros, then we actually have to NOT shift the
+ // exponent.
+ int_exponent = is_zero ? 0 : int_exponent;
+
+ // If we are denorm, then start shifting, and decreasing the exponent until
+ // our leading bit is 1.
+
+ if (is_denorm) {
+ while ((fraction & HF::fraction_top_bit) == 0) {
+ fraction = static_cast<uint_type>(fraction << 1);
+ int_exponent = static_cast<int_type>(int_exponent - 1);
+ }
+ // Since this is denormalized, we have to consume the leading 1 since it
+ // will end up being implicit.
+ fraction = static_cast<uint_type>(fraction << 1); // eat the leading 1
+ fraction &= HF::fraction_represent_mask;
+ }
+
+ uint_type fraction_nibbles = HF::fraction_nibbles;
+ // We do not have to display any trailing 0s, since this represents the
+ // fractional part.
+ while (fraction_nibbles > 0 && (fraction & 0xF) == 0) {
+ // Shift off any trailing values;
+ fraction = static_cast<uint_type>(fraction >> 4);
+ --fraction_nibbles;
+ }
+
+ const auto saved_flags = os.flags();
+ const auto saved_fill = os.fill();
+
+ os << sign << "0x" << (is_zero ? '0' : '1');
+ if (fraction_nibbles) {
+ // Make sure to keep the leading 0s in place, since this is the fractional
+ // part.
+ os << "." << std::setw(static_cast<int>(fraction_nibbles))
+ << std::setfill('0') << std::hex << fraction;
+ }
+ os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent;
+
+ os.flags(saved_flags);
+ os.fill(saved_fill);
+
+ return os;
+}
+
+// Returns true if negate_value is true and the next character on the
+// input stream is a plus or minus sign. In that case we also set the fail bit
+// on the stream and set the value to the zero value for its type.
+template <typename T, typename Traits>
+inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value,
+ HexFloat<T, Traits>& value) {
+ if (negate_value) {
+ auto next_char = is.peek();
+ if (next_char == '-' || next_char == '+') {
+ // Fail the parse. Emulate standard behaviour by setting the value to
+ // the zero value, and set the fail bit on the stream.
+ value = HexFloat<T, Traits>(typename HexFloat<T, Traits>::uint_type(0));
+ is.setstate(std::ios_base::failbit);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Parses a floating point number from the given stream and stores it into the
+// value parameter.
+// If negate_value is true then the number may not have a leading minus or
+// plus, and if it successfully parses, then the number is negated before
+// being stored into the value parameter.
+// If the value cannot be correctly parsed or overflows the target floating
+// point type, then set the fail bit on the stream.
+// TODO(dneto): Promise C++11 standard behavior in how the value is set in
+// the error case, but only after all target platforms implement it correctly.
+// In particular, the Microsoft C++ runtime appears to be out of spec.
+template <typename T, typename Traits>
+inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value,
+ HexFloat<T, Traits>& value) {
+ if (RejectParseDueToLeadingSign(is, negate_value, value)) {
+ return is;
+ }
+ T val;
+ is >> val;
+ if (negate_value) {
+ val = -val;
+ }
+ value.set_value(val);
+ // In the failure case, map -0.0 to 0.0.
+ if (is.fail() && value.getUnsignedBits() == 0u) {
+ value = HexFloat<T, Traits>(typename HexFloat<T, Traits>::uint_type(0));
+ }
+ if (val.isInfinity()) {
+ // Fail the parse. Emulate standard behaviour by setting the value to
+ // the closest normal value, and set the fail bit on the stream.
+ value.set_value((value.isNegative() | negate_value) ? T::lowest()
+ : T::max());
+ is.setstate(std::ios_base::failbit);
+ }
+ return is;
+}
+
+// Specialization of ParseNormalFloat for FloatProxy<Float16> values.
+// This will parse the float as it were a 32-bit floating point number,
+// and then round it down to fit into a Float16 value.
+// The number is rounded towards zero.
+// If negate_value is true then the number may not have a leading minus or
+// plus, and if it successfully parses, then the number is negated before
+// being stored into the value parameter.
+// If the value cannot be correctly parsed or overflows the target floating
+// point type, then set the fail bit on the stream.
+// TODO(dneto): Promise C++11 standard behavior in how the value is set in
+// the error case, but only after all target platforms implement it correctly.
+// In particular, the Microsoft C++ runtime appears to be out of spec.
+template <>
+inline std::istream&
+ParseNormalFloat<FloatProxy<Float16>, HexFloatTraits<FloatProxy<Float16>>>(
+ std::istream& is, bool negate_value,
+ HexFloat<FloatProxy<Float16>, HexFloatTraits<FloatProxy<Float16>>>& value) {
+ // First parse as a 32-bit float.
+ HexFloat<FloatProxy<float>> float_val(0.0f);
+ ParseNormalFloat(is, negate_value, float_val);
+
+ // Then convert to 16-bit float, saturating at infinities, and
+ // rounding toward zero.
+ float_val.castTo(value, kRoundToZero);
+
+ // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the
+ // fail bit and set the lowest or highest value.
+ if (Float16::isInfinity(value.value().getAsFloat())) {
+ value.set_value(value.isNegative() ? Float16::lowest() : Float16::max());
+ is.setstate(std::ios_base::failbit);
+ }
+ return is;
+}
+
+// Reads a HexFloat from the given stream.
+// If the float is not encoded as a hex-float then it will be parsed
+// as a regular float.
+// This may fail if your stream does not support at least one unget.
+// Nan values can be encoded with "0x1.<not zero>p+exponent_bias".
+// This would normally overflow a float and round to
+// infinity but this special pattern is the exact representation for a NaN,
+// and therefore is actually encoded as the correct NaN. To encode inf,
+// either 0x0p+exponent_bias can be specified or any exponent greater than
+// exponent_bias.
+// Examples using IEEE 32-bit float encoding.
+// 0x1.0p+128 (+inf)
+// -0x1.0p-128 (-inf)
+//
+// 0x1.1p+128 (+Nan)
+// -0x1.1p+128 (-Nan)
+//
+// 0x1p+129 (+inf)
+// -0x1p+129 (-inf)
+template <typename T, typename Traits>
+std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
+ using HF = HexFloat<T, Traits>;
+ using uint_type = typename HF::uint_type;
+ using int_type = typename HF::int_type;
+
+ value.set_value(static_cast<typename HF::native_type>(0.f));
+
+ if (is.flags() & std::ios::skipws) {
+ // If the user wants to skip whitespace , then we should obey that.
+ while (std::isspace(is.peek())) {
+ is.get();
+ }
+ }
+
+ auto next_char = is.peek();
+ bool negate_value = false;
+
+ if (next_char != '-' && next_char != '0') {
+ return ParseNormalFloat(is, negate_value, value);
+ }
+
+ if (next_char == '-') {
+ negate_value = true;
+ is.get();
+ next_char = is.peek();
+ }
+
+ if (next_char == '0') {
+ is.get(); // We may have to unget this.
+ auto maybe_hex_start = is.peek();
+ if (maybe_hex_start != 'x' && maybe_hex_start != 'X') {
+ is.unget();
+ return ParseNormalFloat(is, negate_value, value);
+ } else {
+ is.get(); // Throw away the 'x';
+ }
+ } else {
+ return ParseNormalFloat(is, negate_value, value);
+ }
+
+ // This "looks" like a hex-float so treat it as one.
+ bool seen_p = false;
+ bool seen_dot = false;
+ uint_type fraction_index = 0;
+
+ uint_type fraction = 0;
+ int_type exponent = HF::exponent_bias;
+
+ // Strip off leading zeros so we don't have to special-case them later.
+ while ((next_char = is.peek()) == '0') {
+ is.get();
+ }
+
+ bool is_denorm =
+ true; // Assume denorm "representation" until we hear otherwise.
+ // NB: This does not mean the value is actually denorm,
+ // it just means that it was written 0.
+ bool bits_written = false; // Stays false until we write a bit.
+ while (!seen_p && !seen_dot) {
+ // Handle characters that are left of the fractional part.
+ if (next_char == '.') {
+ seen_dot = true;
+ } else if (next_char == 'p') {
+ seen_p = true;
+ } else if (::isxdigit(next_char)) {
+ // We know this is not denormalized since we have stripped all leading
+ // zeroes and we are not a ".".
+ is_denorm = false;
+ int number = get_nibble_from_character(next_char);
+ for (int i = 0; i < 4; ++i, number <<= 1) {
+ uint_type write_bit = (number & 0x8) ? 0x1 : 0x0;
+ if (bits_written) {
+ // If we are here the bits represented belong in the fractional
+ // part of the float, and we have to adjust the exponent accordingly.
+ fraction = static_cast<uint_type>(
+ fraction |
+ static_cast<uint_type>(
+ write_bit << (HF::top_bit_left_shift - fraction_index++)));
+ exponent = static_cast<int_type>(exponent + 1);
+ }
+ bits_written |= write_bit != 0;
+ }
+ } else {
+ // We have not found our exponent yet, so we have to fail.
+ is.setstate(std::ios::failbit);
+ return is;
+ }
+ is.get();
+ next_char = is.peek();
+ }
+ bits_written = false;
+ while (seen_dot && !seen_p) {
+ // Handle only fractional parts now.
+ if (next_char == 'p') {
+ seen_p = true;
+ } else if (::isxdigit(next_char)) {
+ int number = get_nibble_from_character(next_char);
+ for (int i = 0; i < 4; ++i, number <<= 1) {
+ uint_type write_bit = (number & 0x8) ? 0x01 : 0x00;
+ bits_written |= write_bit != 0;
+ if (is_denorm && !bits_written) {
+ // Handle modifying the exponent here this way we can handle
+ // an arbitrary number of hex values without overflowing our
+ // integer.
+ exponent = static_cast<int_type>(exponent - 1);
+ } else {
+ fraction = static_cast<uint_type>(
+ fraction |
+ static_cast<uint_type>(
+ write_bit << (HF::top_bit_left_shift - fraction_index++)));
+ }
+ }
+ } else {
+ // We still have not found our 'p' exponent yet, so this is not a valid
+ // hex-float.
+ is.setstate(std::ios::failbit);
+ return is;
+ }
+ is.get();
+ next_char = is.peek();
+ }
+
+ bool seen_sign = false;
+ int8_t exponent_sign = 1;
+ int_type written_exponent = 0;
+ while (true) {
+ if ((next_char == '-' || next_char == '+')) {
+ if (seen_sign) {
+ is.setstate(std::ios::failbit);
+ return is;
+ }
+ seen_sign = true;
+ exponent_sign = (next_char == '-') ? -1 : 1;
+ } else if (::isdigit(next_char)) {
+ // Hex-floats express their exponent as decimal.
+ written_exponent = static_cast<int_type>(written_exponent * 10);
+ written_exponent =
+ static_cast<int_type>(written_exponent + (next_char - '0'));
+ } else {
+ break;
+ }
+ is.get();
+ next_char = is.peek();
+ }
+
+ written_exponent = static_cast<int_type>(written_exponent * exponent_sign);
+ exponent = static_cast<int_type>(exponent + written_exponent);
+
+ bool is_zero = is_denorm && (fraction == 0);
+ if (is_denorm && !is_zero) {
+ fraction = static_cast<uint_type>(fraction << 1);
+ exponent = static_cast<int_type>(exponent - 1);
+ } else if (is_zero) {
+ exponent = 0;
+ }
+
+ if (exponent <= 0 && !is_zero) {
+ fraction = static_cast<uint_type>(fraction >> 1);
+ fraction |= static_cast<uint_type>(1) << HF::top_bit_left_shift;
+ }
+
+ fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask;
+
+ const int_type max_exponent =
+ SetBits<uint_type, 0, HF::num_exponent_bits>::get;
+
+ // Handle actual denorm numbers
+ while (exponent < 0 && !is_zero) {
+ fraction = static_cast<uint_type>(fraction >> 1);
+ exponent = static_cast<int_type>(exponent + 1);
+
+ fraction &= HF::fraction_encode_mask;
+ if (fraction == 0) {
+ // We have underflowed our fraction. We should clamp to zero.
+ is_zero = true;
+ exponent = 0;
+ }
+ }
+
+ // We have overflowed so we should be inf/-inf.
+ if (exponent > max_exponent) {
+ exponent = max_exponent;
+ fraction = 0;
+ }
+
+ uint_type output_bits = static_cast<uint_type>(
+ static_cast<uint_type>(negate_value ? 1 : 0) << HF::top_bit_left_shift);
+ output_bits |= fraction;
+
+ uint_type shifted_exponent = static_cast<uint_type>(
+ static_cast<uint_type>(exponent << HF::exponent_left_shift) &
+ HF::exponent_mask);
+ output_bits |= shifted_exponent;
+
+ T output_float = spvutils::BitwiseCast<T>(output_bits);
+ value.set_value(output_float);
+
+ return is;
+}
+
+// Writes a FloatProxy value to a stream.
+// Zero and normal numbers are printed in the usual notation, but with
+// enough digits to fully reproduce the value. Other values (subnormal,
+// NaN, and infinity) are printed as a hex float.
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const FloatProxy<T>& value) {
+ auto float_val = value.getAsFloat();
+ switch (std::fpclassify(float_val)) {
+ case FP_ZERO:
+ case FP_NORMAL: {
+ auto saved_precision = os.precision();
+ os.precision(std::numeric_limits<T>::digits10);
+ os << float_val;
+ os.precision(saved_precision);
+ } break;
+ default:
+ os << HexFloat<FloatProxy<T>>(value);
+ break;
+ }
+ return os;
+}
+
+template <>
+inline std::ostream& operator<<<Float16>(std::ostream& os,
+ const FloatProxy<Float16>& value) {
+ os << HexFloat<FloatProxy<Float16>>(value);
+ return os;
+}
+}
+
+#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_
diff --git a/thirdparty/glslang/SPIRV/spirv.hpp b/thirdparty/glslang/SPIRV/spirv.hpp
new file mode 100644
index 0000000000..1e96f7b4a9
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/spirv.hpp
@@ -0,0 +1,1981 @@
+// Copyright (c) 2014-2019 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and/or associated documentation files (the "Materials"),
+// to deal in the Materials without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Materials, and to permit persons to whom the
+// Materials are furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+// IN THE MATERIALS.
+
+// This header is automatically generated by the same tool that creates
+// the Binary Section of the SPIR-V specification.
+
+// Enumeration tokens for SPIR-V, in various styles:
+// C, C++, C++11, JSON, Lua, Python, C#, D
+//
+// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
+// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
+// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
+// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
+// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
+// - C# will use enum classes in the Specification class located in the "Spv" namespace,
+// e.g.: Spv.Specification.SourceLanguage.GLSL
+// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL
+//
+// Some tokens act like mask values, which can be OR'd together,
+// while others are mutually exclusive. The mask-like ones have
+// "Mask" in their name, and a parallel enum that has the shift
+// amount (1 << x) for each corresponding enumerant.
+
+#ifndef spirv_HPP
+#define spirv_HPP
+
+namespace spv {
+
+typedef unsigned int Id;
+
+#define SPV_VERSION 0x10400
+#define SPV_REVISION 1
+
+static const unsigned int MagicNumber = 0x07230203;
+static const unsigned int Version = 0x00010400;
+static const unsigned int Revision = 1;
+static const unsigned int OpCodeMask = 0xffff;
+static const unsigned int WordCountShift = 16;
+
+enum SourceLanguage {
+ SourceLanguageUnknown = 0,
+ SourceLanguageESSL = 1,
+ SourceLanguageGLSL = 2,
+ SourceLanguageOpenCL_C = 3,
+ SourceLanguageOpenCL_CPP = 4,
+ SourceLanguageHLSL = 5,
+ SourceLanguageMax = 0x7fffffff,
+};
+
+enum ExecutionModel {
+ ExecutionModelVertex = 0,
+ ExecutionModelTessellationControl = 1,
+ ExecutionModelTessellationEvaluation = 2,
+ ExecutionModelGeometry = 3,
+ ExecutionModelFragment = 4,
+ ExecutionModelGLCompute = 5,
+ ExecutionModelKernel = 6,
+ ExecutionModelTaskNV = 5267,
+ ExecutionModelMeshNV = 5268,
+ ExecutionModelRayGenerationNV = 5313,
+ ExecutionModelIntersectionNV = 5314,
+ ExecutionModelAnyHitNV = 5315,
+ ExecutionModelClosestHitNV = 5316,
+ ExecutionModelMissNV = 5317,
+ ExecutionModelCallableNV = 5318,
+ ExecutionModelMax = 0x7fffffff,
+};
+
+enum AddressingModel {
+ AddressingModelLogical = 0,
+ AddressingModelPhysical32 = 1,
+ AddressingModelPhysical64 = 2,
+ AddressingModelPhysicalStorageBuffer64 = 5348,
+ AddressingModelPhysicalStorageBuffer64EXT = 5348,
+ AddressingModelMax = 0x7fffffff,
+};
+
+enum MemoryModel {
+ MemoryModelSimple = 0,
+ MemoryModelGLSL450 = 1,
+ MemoryModelOpenCL = 2,
+ MemoryModelVulkan = 3,
+ MemoryModelVulkanKHR = 3,
+ MemoryModelMax = 0x7fffffff,
+};
+
+enum ExecutionMode {
+ ExecutionModeInvocations = 0,
+ ExecutionModeSpacingEqual = 1,
+ ExecutionModeSpacingFractionalEven = 2,
+ ExecutionModeSpacingFractionalOdd = 3,
+ ExecutionModeVertexOrderCw = 4,
+ ExecutionModeVertexOrderCcw = 5,
+ ExecutionModePixelCenterInteger = 6,
+ ExecutionModeOriginUpperLeft = 7,
+ ExecutionModeOriginLowerLeft = 8,
+ ExecutionModeEarlyFragmentTests = 9,
+ ExecutionModePointMode = 10,
+ ExecutionModeXfb = 11,
+ ExecutionModeDepthReplacing = 12,
+ ExecutionModeDepthGreater = 14,
+ ExecutionModeDepthLess = 15,
+ ExecutionModeDepthUnchanged = 16,
+ ExecutionModeLocalSize = 17,
+ ExecutionModeLocalSizeHint = 18,
+ ExecutionModeInputPoints = 19,
+ ExecutionModeInputLines = 20,
+ ExecutionModeInputLinesAdjacency = 21,
+ ExecutionModeTriangles = 22,
+ ExecutionModeInputTrianglesAdjacency = 23,
+ ExecutionModeQuads = 24,
+ ExecutionModeIsolines = 25,
+ ExecutionModeOutputVertices = 26,
+ ExecutionModeOutputPoints = 27,
+ ExecutionModeOutputLineStrip = 28,
+ ExecutionModeOutputTriangleStrip = 29,
+ ExecutionModeVecTypeHint = 30,
+ ExecutionModeContractionOff = 31,
+ ExecutionModeInitializer = 33,
+ ExecutionModeFinalizer = 34,
+ ExecutionModeSubgroupSize = 35,
+ ExecutionModeSubgroupsPerWorkgroup = 36,
+ ExecutionModeSubgroupsPerWorkgroupId = 37,
+ ExecutionModeLocalSizeId = 38,
+ ExecutionModeLocalSizeHintId = 39,
+ ExecutionModePostDepthCoverage = 4446,
+ ExecutionModeDenormPreserve = 4459,
+ ExecutionModeDenormFlushToZero = 4460,
+ ExecutionModeSignedZeroInfNanPreserve = 4461,
+ ExecutionModeRoundingModeRTE = 4462,
+ ExecutionModeRoundingModeRTZ = 4463,
+ ExecutionModeStencilRefReplacingEXT = 5027,
+ ExecutionModeOutputLinesNV = 5269,
+ ExecutionModeOutputPrimitivesNV = 5270,
+ ExecutionModeDerivativeGroupQuadsNV = 5289,
+ ExecutionModeDerivativeGroupLinearNV = 5290,
+ ExecutionModeOutputTrianglesNV = 5298,
+ ExecutionModePixelInterlockOrderedEXT = 5366,
+ ExecutionModePixelInterlockUnorderedEXT = 5367,
+ ExecutionModeSampleInterlockOrderedEXT = 5368,
+ ExecutionModeSampleInterlockUnorderedEXT = 5369,
+ ExecutionModeShadingRateInterlockOrderedEXT = 5370,
+ ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
+ ExecutionModeMax = 0x7fffffff,
+};
+
+enum StorageClass {
+ StorageClassUniformConstant = 0,
+ StorageClassInput = 1,
+ StorageClassUniform = 2,
+ StorageClassOutput = 3,
+ StorageClassWorkgroup = 4,
+ StorageClassCrossWorkgroup = 5,
+ StorageClassPrivate = 6,
+ StorageClassFunction = 7,
+ StorageClassGeneric = 8,
+ StorageClassPushConstant = 9,
+ StorageClassAtomicCounter = 10,
+ StorageClassImage = 11,
+ StorageClassStorageBuffer = 12,
+ StorageClassCallableDataNV = 5328,
+ StorageClassIncomingCallableDataNV = 5329,
+ StorageClassRayPayloadNV = 5338,
+ StorageClassHitAttributeNV = 5339,
+ StorageClassIncomingRayPayloadNV = 5342,
+ StorageClassShaderRecordBufferNV = 5343,
+ StorageClassPhysicalStorageBuffer = 5349,
+ StorageClassPhysicalStorageBufferEXT = 5349,
+ StorageClassMax = 0x7fffffff,
+};
+
+enum Dim {
+ Dim1D = 0,
+ Dim2D = 1,
+ Dim3D = 2,
+ DimCube = 3,
+ DimRect = 4,
+ DimBuffer = 5,
+ DimSubpassData = 6,
+ DimMax = 0x7fffffff,
+};
+
+enum SamplerAddressingMode {
+ SamplerAddressingModeNone = 0,
+ SamplerAddressingModeClampToEdge = 1,
+ SamplerAddressingModeClamp = 2,
+ SamplerAddressingModeRepeat = 3,
+ SamplerAddressingModeRepeatMirrored = 4,
+ SamplerAddressingModeMax = 0x7fffffff,
+};
+
+enum SamplerFilterMode {
+ SamplerFilterModeNearest = 0,
+ SamplerFilterModeLinear = 1,
+ SamplerFilterModeMax = 0x7fffffff,
+};
+
+enum ImageFormat {
+ ImageFormatUnknown = 0,
+ ImageFormatRgba32f = 1,
+ ImageFormatRgba16f = 2,
+ ImageFormatR32f = 3,
+ ImageFormatRgba8 = 4,
+ ImageFormatRgba8Snorm = 5,
+ ImageFormatRg32f = 6,
+ ImageFormatRg16f = 7,
+ ImageFormatR11fG11fB10f = 8,
+ ImageFormatR16f = 9,
+ ImageFormatRgba16 = 10,
+ ImageFormatRgb10A2 = 11,
+ ImageFormatRg16 = 12,
+ ImageFormatRg8 = 13,
+ ImageFormatR16 = 14,
+ ImageFormatR8 = 15,
+ ImageFormatRgba16Snorm = 16,
+ ImageFormatRg16Snorm = 17,
+ ImageFormatRg8Snorm = 18,
+ ImageFormatR16Snorm = 19,
+ ImageFormatR8Snorm = 20,
+ ImageFormatRgba32i = 21,
+ ImageFormatRgba16i = 22,
+ ImageFormatRgba8i = 23,
+ ImageFormatR32i = 24,
+ ImageFormatRg32i = 25,
+ ImageFormatRg16i = 26,
+ ImageFormatRg8i = 27,
+ ImageFormatR16i = 28,
+ ImageFormatR8i = 29,
+ ImageFormatRgba32ui = 30,
+ ImageFormatRgba16ui = 31,
+ ImageFormatRgba8ui = 32,
+ ImageFormatR32ui = 33,
+ ImageFormatRgb10a2ui = 34,
+ ImageFormatRg32ui = 35,
+ ImageFormatRg16ui = 36,
+ ImageFormatRg8ui = 37,
+ ImageFormatR16ui = 38,
+ ImageFormatR8ui = 39,
+ ImageFormatMax = 0x7fffffff,
+};
+
+enum ImageChannelOrder {
+ ImageChannelOrderR = 0,
+ ImageChannelOrderA = 1,
+ ImageChannelOrderRG = 2,
+ ImageChannelOrderRA = 3,
+ ImageChannelOrderRGB = 4,
+ ImageChannelOrderRGBA = 5,
+ ImageChannelOrderBGRA = 6,
+ ImageChannelOrderARGB = 7,
+ ImageChannelOrderIntensity = 8,
+ ImageChannelOrderLuminance = 9,
+ ImageChannelOrderRx = 10,
+ ImageChannelOrderRGx = 11,
+ ImageChannelOrderRGBx = 12,
+ ImageChannelOrderDepth = 13,
+ ImageChannelOrderDepthStencil = 14,
+ ImageChannelOrdersRGB = 15,
+ ImageChannelOrdersRGBx = 16,
+ ImageChannelOrdersRGBA = 17,
+ ImageChannelOrdersBGRA = 18,
+ ImageChannelOrderABGR = 19,
+ ImageChannelOrderMax = 0x7fffffff,
+};
+
+enum ImageChannelDataType {
+ ImageChannelDataTypeSnormInt8 = 0,
+ ImageChannelDataTypeSnormInt16 = 1,
+ ImageChannelDataTypeUnormInt8 = 2,
+ ImageChannelDataTypeUnormInt16 = 3,
+ ImageChannelDataTypeUnormShort565 = 4,
+ ImageChannelDataTypeUnormShort555 = 5,
+ ImageChannelDataTypeUnormInt101010 = 6,
+ ImageChannelDataTypeSignedInt8 = 7,
+ ImageChannelDataTypeSignedInt16 = 8,
+ ImageChannelDataTypeSignedInt32 = 9,
+ ImageChannelDataTypeUnsignedInt8 = 10,
+ ImageChannelDataTypeUnsignedInt16 = 11,
+ ImageChannelDataTypeUnsignedInt32 = 12,
+ ImageChannelDataTypeHalfFloat = 13,
+ ImageChannelDataTypeFloat = 14,
+ ImageChannelDataTypeUnormInt24 = 15,
+ ImageChannelDataTypeUnormInt101010_2 = 16,
+ ImageChannelDataTypeMax = 0x7fffffff,
+};
+
+enum ImageOperandsShift {
+ ImageOperandsBiasShift = 0,
+ ImageOperandsLodShift = 1,
+ ImageOperandsGradShift = 2,
+ ImageOperandsConstOffsetShift = 3,
+ ImageOperandsOffsetShift = 4,
+ ImageOperandsConstOffsetsShift = 5,
+ ImageOperandsSampleShift = 6,
+ ImageOperandsMinLodShift = 7,
+ ImageOperandsMakeTexelAvailableShift = 8,
+ ImageOperandsMakeTexelAvailableKHRShift = 8,
+ ImageOperandsMakeTexelVisibleShift = 9,
+ ImageOperandsMakeTexelVisibleKHRShift = 9,
+ ImageOperandsNonPrivateTexelShift = 10,
+ ImageOperandsNonPrivateTexelKHRShift = 10,
+ ImageOperandsVolatileTexelShift = 11,
+ ImageOperandsVolatileTexelKHRShift = 11,
+ ImageOperandsSignExtendShift = 12,
+ ImageOperandsZeroExtendShift = 13,
+ ImageOperandsMax = 0x7fffffff,
+};
+
+enum ImageOperandsMask {
+ ImageOperandsMaskNone = 0,
+ ImageOperandsBiasMask = 0x00000001,
+ ImageOperandsLodMask = 0x00000002,
+ ImageOperandsGradMask = 0x00000004,
+ ImageOperandsConstOffsetMask = 0x00000008,
+ ImageOperandsOffsetMask = 0x00000010,
+ ImageOperandsConstOffsetsMask = 0x00000020,
+ ImageOperandsSampleMask = 0x00000040,
+ ImageOperandsMinLodMask = 0x00000080,
+ ImageOperandsMakeTexelAvailableMask = 0x00000100,
+ ImageOperandsMakeTexelAvailableKHRMask = 0x00000100,
+ ImageOperandsMakeTexelVisibleMask = 0x00000200,
+ ImageOperandsMakeTexelVisibleKHRMask = 0x00000200,
+ ImageOperandsNonPrivateTexelMask = 0x00000400,
+ ImageOperandsNonPrivateTexelKHRMask = 0x00000400,
+ ImageOperandsVolatileTexelMask = 0x00000800,
+ ImageOperandsVolatileTexelKHRMask = 0x00000800,
+ ImageOperandsSignExtendMask = 0x00001000,
+ ImageOperandsZeroExtendMask = 0x00002000,
+};
+
+enum FPFastMathModeShift {
+ FPFastMathModeNotNaNShift = 0,
+ FPFastMathModeNotInfShift = 1,
+ FPFastMathModeNSZShift = 2,
+ FPFastMathModeAllowRecipShift = 3,
+ FPFastMathModeFastShift = 4,
+ FPFastMathModeMax = 0x7fffffff,
+};
+
+enum FPFastMathModeMask {
+ FPFastMathModeMaskNone = 0,
+ FPFastMathModeNotNaNMask = 0x00000001,
+ FPFastMathModeNotInfMask = 0x00000002,
+ FPFastMathModeNSZMask = 0x00000004,
+ FPFastMathModeAllowRecipMask = 0x00000008,
+ FPFastMathModeFastMask = 0x00000010,
+};
+
+enum FPRoundingMode {
+ FPRoundingModeRTE = 0,
+ FPRoundingModeRTZ = 1,
+ FPRoundingModeRTP = 2,
+ FPRoundingModeRTN = 3,
+ FPRoundingModeMax = 0x7fffffff,
+};
+
+enum LinkageType {
+ LinkageTypeExport = 0,
+ LinkageTypeImport = 1,
+ LinkageTypeMax = 0x7fffffff,
+};
+
+enum AccessQualifier {
+ AccessQualifierReadOnly = 0,
+ AccessQualifierWriteOnly = 1,
+ AccessQualifierReadWrite = 2,
+ AccessQualifierMax = 0x7fffffff,
+};
+
+enum FunctionParameterAttribute {
+ FunctionParameterAttributeZext = 0,
+ FunctionParameterAttributeSext = 1,
+ FunctionParameterAttributeByVal = 2,
+ FunctionParameterAttributeSret = 3,
+ FunctionParameterAttributeNoAlias = 4,
+ FunctionParameterAttributeNoCapture = 5,
+ FunctionParameterAttributeNoWrite = 6,
+ FunctionParameterAttributeNoReadWrite = 7,
+ FunctionParameterAttributeMax = 0x7fffffff,
+};
+
+enum Decoration {
+ DecorationRelaxedPrecision = 0,
+ DecorationSpecId = 1,
+ DecorationBlock = 2,
+ DecorationBufferBlock = 3,
+ DecorationRowMajor = 4,
+ DecorationColMajor = 5,
+ DecorationArrayStride = 6,
+ DecorationMatrixStride = 7,
+ DecorationGLSLShared = 8,
+ DecorationGLSLPacked = 9,
+ DecorationCPacked = 10,
+ DecorationBuiltIn = 11,
+ DecorationNoPerspective = 13,
+ DecorationFlat = 14,
+ DecorationPatch = 15,
+ DecorationCentroid = 16,
+ DecorationSample = 17,
+ DecorationInvariant = 18,
+ DecorationRestrict = 19,
+ DecorationAliased = 20,
+ DecorationVolatile = 21,
+ DecorationConstant = 22,
+ DecorationCoherent = 23,
+ DecorationNonWritable = 24,
+ DecorationNonReadable = 25,
+ DecorationUniform = 26,
+ DecorationUniformId = 27,
+ DecorationSaturatedConversion = 28,
+ DecorationStream = 29,
+ DecorationLocation = 30,
+ DecorationComponent = 31,
+ DecorationIndex = 32,
+ DecorationBinding = 33,
+ DecorationDescriptorSet = 34,
+ DecorationOffset = 35,
+ DecorationXfbBuffer = 36,
+ DecorationXfbStride = 37,
+ DecorationFuncParamAttr = 38,
+ DecorationFPRoundingMode = 39,
+ DecorationFPFastMathMode = 40,
+ DecorationLinkageAttributes = 41,
+ DecorationNoContraction = 42,
+ DecorationInputAttachmentIndex = 43,
+ DecorationAlignment = 44,
+ DecorationMaxByteOffset = 45,
+ DecorationAlignmentId = 46,
+ DecorationMaxByteOffsetId = 47,
+ DecorationNoSignedWrap = 4469,
+ DecorationNoUnsignedWrap = 4470,
+ DecorationExplicitInterpAMD = 4999,
+ DecorationOverrideCoverageNV = 5248,
+ DecorationPassthroughNV = 5250,
+ DecorationViewportRelativeNV = 5252,
+ DecorationSecondaryViewportRelativeNV = 5256,
+ DecorationPerPrimitiveNV = 5271,
+ DecorationPerViewNV = 5272,
+ DecorationPerTaskNV = 5273,
+ DecorationPerVertexNV = 5285,
+ DecorationNonUniform = 5300,
+ DecorationNonUniformEXT = 5300,
+ DecorationRestrictPointer = 5355,
+ DecorationRestrictPointerEXT = 5355,
+ DecorationAliasedPointer = 5356,
+ DecorationAliasedPointerEXT = 5356,
+ DecorationCounterBuffer = 5634,
+ DecorationHlslCounterBufferGOOGLE = 5634,
+ DecorationHlslSemanticGOOGLE = 5635,
+ DecorationUserSemantic = 5635,
+ DecorationUserTypeGOOGLE = 5636,
+ DecorationMax = 0x7fffffff,
+};
+
+enum BuiltIn {
+ BuiltInPosition = 0,
+ BuiltInPointSize = 1,
+ BuiltInClipDistance = 3,
+ BuiltInCullDistance = 4,
+ BuiltInVertexId = 5,
+ BuiltInInstanceId = 6,
+ BuiltInPrimitiveId = 7,
+ BuiltInInvocationId = 8,
+ BuiltInLayer = 9,
+ BuiltInViewportIndex = 10,
+ BuiltInTessLevelOuter = 11,
+ BuiltInTessLevelInner = 12,
+ BuiltInTessCoord = 13,
+ BuiltInPatchVertices = 14,
+ BuiltInFragCoord = 15,
+ BuiltInPointCoord = 16,
+ BuiltInFrontFacing = 17,
+ BuiltInSampleId = 18,
+ BuiltInSamplePosition = 19,
+ BuiltInSampleMask = 20,
+ BuiltInFragDepth = 22,
+ BuiltInHelperInvocation = 23,
+ BuiltInNumWorkgroups = 24,
+ BuiltInWorkgroupSize = 25,
+ BuiltInWorkgroupId = 26,
+ BuiltInLocalInvocationId = 27,
+ BuiltInGlobalInvocationId = 28,
+ BuiltInLocalInvocationIndex = 29,
+ BuiltInWorkDim = 30,
+ BuiltInGlobalSize = 31,
+ BuiltInEnqueuedWorkgroupSize = 32,
+ BuiltInGlobalOffset = 33,
+ BuiltInGlobalLinearId = 34,
+ BuiltInSubgroupSize = 36,
+ BuiltInSubgroupMaxSize = 37,
+ BuiltInNumSubgroups = 38,
+ BuiltInNumEnqueuedSubgroups = 39,
+ BuiltInSubgroupId = 40,
+ BuiltInSubgroupLocalInvocationId = 41,
+ BuiltInVertexIndex = 42,
+ BuiltInInstanceIndex = 43,
+ BuiltInSubgroupEqMask = 4416,
+ BuiltInSubgroupEqMaskKHR = 4416,
+ BuiltInSubgroupGeMask = 4417,
+ BuiltInSubgroupGeMaskKHR = 4417,
+ BuiltInSubgroupGtMask = 4418,
+ BuiltInSubgroupGtMaskKHR = 4418,
+ BuiltInSubgroupLeMask = 4419,
+ BuiltInSubgroupLeMaskKHR = 4419,
+ BuiltInSubgroupLtMask = 4420,
+ BuiltInSubgroupLtMaskKHR = 4420,
+ BuiltInBaseVertex = 4424,
+ BuiltInBaseInstance = 4425,
+ BuiltInDrawIndex = 4426,
+ BuiltInDeviceIndex = 4438,
+ BuiltInViewIndex = 4440,
+ BuiltInBaryCoordNoPerspAMD = 4992,
+ BuiltInBaryCoordNoPerspCentroidAMD = 4993,
+ BuiltInBaryCoordNoPerspSampleAMD = 4994,
+ BuiltInBaryCoordSmoothAMD = 4995,
+ BuiltInBaryCoordSmoothCentroidAMD = 4996,
+ BuiltInBaryCoordSmoothSampleAMD = 4997,
+ BuiltInBaryCoordPullModelAMD = 4998,
+ BuiltInFragStencilRefEXT = 5014,
+ BuiltInViewportMaskNV = 5253,
+ BuiltInSecondaryPositionNV = 5257,
+ BuiltInSecondaryViewportMaskNV = 5258,
+ BuiltInPositionPerViewNV = 5261,
+ BuiltInViewportMaskPerViewNV = 5262,
+ BuiltInFullyCoveredEXT = 5264,
+ BuiltInTaskCountNV = 5274,
+ BuiltInPrimitiveCountNV = 5275,
+ BuiltInPrimitiveIndicesNV = 5276,
+ BuiltInClipDistancePerViewNV = 5277,
+ BuiltInCullDistancePerViewNV = 5278,
+ BuiltInLayerPerViewNV = 5279,
+ BuiltInMeshViewCountNV = 5280,
+ BuiltInMeshViewIndicesNV = 5281,
+ BuiltInBaryCoordNV = 5286,
+ BuiltInBaryCoordNoPerspNV = 5287,
+ BuiltInFragSizeEXT = 5292,
+ BuiltInFragmentSizeNV = 5292,
+ BuiltInFragInvocationCountEXT = 5293,
+ BuiltInInvocationsPerPixelNV = 5293,
+ BuiltInLaunchIdNV = 5319,
+ BuiltInLaunchSizeNV = 5320,
+ BuiltInWorldRayOriginNV = 5321,
+ BuiltInWorldRayDirectionNV = 5322,
+ BuiltInObjectRayOriginNV = 5323,
+ BuiltInObjectRayDirectionNV = 5324,
+ BuiltInRayTminNV = 5325,
+ BuiltInRayTmaxNV = 5326,
+ BuiltInInstanceCustomIndexNV = 5327,
+ BuiltInObjectToWorldNV = 5330,
+ BuiltInWorldToObjectNV = 5331,
+ BuiltInHitTNV = 5332,
+ BuiltInHitKindNV = 5333,
+ BuiltInIncomingRayFlagsNV = 5351,
+ BuiltInWarpsPerSMNV = 5374,
+ BuiltInSMCountNV = 5375,
+ BuiltInWarpIDNV = 5376,
+ BuiltInSMIDNV = 5377,
+ BuiltInMax = 0x7fffffff,
+};
+
+enum SelectionControlShift {
+ SelectionControlFlattenShift = 0,
+ SelectionControlDontFlattenShift = 1,
+ SelectionControlMax = 0x7fffffff,
+};
+
+enum SelectionControlMask {
+ SelectionControlMaskNone = 0,
+ SelectionControlFlattenMask = 0x00000001,
+ SelectionControlDontFlattenMask = 0x00000002,
+};
+
+enum LoopControlShift {
+ LoopControlUnrollShift = 0,
+ LoopControlDontUnrollShift = 1,
+ LoopControlDependencyInfiniteShift = 2,
+ LoopControlDependencyLengthShift = 3,
+ LoopControlMinIterationsShift = 4,
+ LoopControlMaxIterationsShift = 5,
+ LoopControlIterationMultipleShift = 6,
+ LoopControlPeelCountShift = 7,
+ LoopControlPartialCountShift = 8,
+ LoopControlMax = 0x7fffffff,
+};
+
+enum LoopControlMask {
+ LoopControlMaskNone = 0,
+ LoopControlUnrollMask = 0x00000001,
+ LoopControlDontUnrollMask = 0x00000002,
+ LoopControlDependencyInfiniteMask = 0x00000004,
+ LoopControlDependencyLengthMask = 0x00000008,
+ LoopControlMinIterationsMask = 0x00000010,
+ LoopControlMaxIterationsMask = 0x00000020,
+ LoopControlIterationMultipleMask = 0x00000040,
+ LoopControlPeelCountMask = 0x00000080,
+ LoopControlPartialCountMask = 0x00000100,
+};
+
+enum FunctionControlShift {
+ FunctionControlInlineShift = 0,
+ FunctionControlDontInlineShift = 1,
+ FunctionControlPureShift = 2,
+ FunctionControlConstShift = 3,
+ FunctionControlMax = 0x7fffffff,
+};
+
+enum FunctionControlMask {
+ FunctionControlMaskNone = 0,
+ FunctionControlInlineMask = 0x00000001,
+ FunctionControlDontInlineMask = 0x00000002,
+ FunctionControlPureMask = 0x00000004,
+ FunctionControlConstMask = 0x00000008,
+};
+
+enum MemorySemanticsShift {
+ MemorySemanticsAcquireShift = 1,
+ MemorySemanticsReleaseShift = 2,
+ MemorySemanticsAcquireReleaseShift = 3,
+ MemorySemanticsSequentiallyConsistentShift = 4,
+ MemorySemanticsUniformMemoryShift = 6,
+ MemorySemanticsSubgroupMemoryShift = 7,
+ MemorySemanticsWorkgroupMemoryShift = 8,
+ MemorySemanticsCrossWorkgroupMemoryShift = 9,
+ MemorySemanticsAtomicCounterMemoryShift = 10,
+ MemorySemanticsImageMemoryShift = 11,
+ MemorySemanticsOutputMemoryShift = 12,
+ MemorySemanticsOutputMemoryKHRShift = 12,
+ MemorySemanticsMakeAvailableShift = 13,
+ MemorySemanticsMakeAvailableKHRShift = 13,
+ MemorySemanticsMakeVisibleShift = 14,
+ MemorySemanticsMakeVisibleKHRShift = 14,
+ MemorySemanticsVolatileShift = 15,
+ MemorySemanticsMax = 0x7fffffff,
+};
+
+enum MemorySemanticsMask {
+ MemorySemanticsMaskNone = 0,
+ MemorySemanticsAcquireMask = 0x00000002,
+ MemorySemanticsReleaseMask = 0x00000004,
+ MemorySemanticsAcquireReleaseMask = 0x00000008,
+ MemorySemanticsSequentiallyConsistentMask = 0x00000010,
+ MemorySemanticsUniformMemoryMask = 0x00000040,
+ MemorySemanticsSubgroupMemoryMask = 0x00000080,
+ MemorySemanticsWorkgroupMemoryMask = 0x00000100,
+ MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200,
+ MemorySemanticsAtomicCounterMemoryMask = 0x00000400,
+ MemorySemanticsImageMemoryMask = 0x00000800,
+ MemorySemanticsOutputMemoryMask = 0x00001000,
+ MemorySemanticsOutputMemoryKHRMask = 0x00001000,
+ MemorySemanticsMakeAvailableMask = 0x00002000,
+ MemorySemanticsMakeAvailableKHRMask = 0x00002000,
+ MemorySemanticsMakeVisibleMask = 0x00004000,
+ MemorySemanticsMakeVisibleKHRMask = 0x00004000,
+ MemorySemanticsVolatileMask = 0x00008000,
+};
+
+enum MemoryAccessShift {
+ MemoryAccessVolatileShift = 0,
+ MemoryAccessAlignedShift = 1,
+ MemoryAccessNontemporalShift = 2,
+ MemoryAccessMakePointerAvailableShift = 3,
+ MemoryAccessMakePointerAvailableKHRShift = 3,
+ MemoryAccessMakePointerVisibleShift = 4,
+ MemoryAccessMakePointerVisibleKHRShift = 4,
+ MemoryAccessNonPrivatePointerShift = 5,
+ MemoryAccessNonPrivatePointerKHRShift = 5,
+ MemoryAccessMax = 0x7fffffff,
+};
+
+enum MemoryAccessMask {
+ MemoryAccessMaskNone = 0,
+ MemoryAccessVolatileMask = 0x00000001,
+ MemoryAccessAlignedMask = 0x00000002,
+ MemoryAccessNontemporalMask = 0x00000004,
+ MemoryAccessMakePointerAvailableMask = 0x00000008,
+ MemoryAccessMakePointerAvailableKHRMask = 0x00000008,
+ MemoryAccessMakePointerVisibleMask = 0x00000010,
+ MemoryAccessMakePointerVisibleKHRMask = 0x00000010,
+ MemoryAccessNonPrivatePointerMask = 0x00000020,
+ MemoryAccessNonPrivatePointerKHRMask = 0x00000020,
+};
+
+enum Scope {
+ ScopeCrossDevice = 0,
+ ScopeDevice = 1,
+ ScopeWorkgroup = 2,
+ ScopeSubgroup = 3,
+ ScopeInvocation = 4,
+ ScopeQueueFamily = 5,
+ ScopeQueueFamilyKHR = 5,
+ ScopeMax = 0x7fffffff,
+};
+
+enum GroupOperation {
+ GroupOperationReduce = 0,
+ GroupOperationInclusiveScan = 1,
+ GroupOperationExclusiveScan = 2,
+ GroupOperationClusteredReduce = 3,
+ GroupOperationPartitionedReduceNV = 6,
+ GroupOperationPartitionedInclusiveScanNV = 7,
+ GroupOperationPartitionedExclusiveScanNV = 8,
+ GroupOperationMax = 0x7fffffff,
+};
+
+enum KernelEnqueueFlags {
+ KernelEnqueueFlagsNoWait = 0,
+ KernelEnqueueFlagsWaitKernel = 1,
+ KernelEnqueueFlagsWaitWorkGroup = 2,
+ KernelEnqueueFlagsMax = 0x7fffffff,
+};
+
+enum KernelProfilingInfoShift {
+ KernelProfilingInfoCmdExecTimeShift = 0,
+ KernelProfilingInfoMax = 0x7fffffff,
+};
+
+enum KernelProfilingInfoMask {
+ KernelProfilingInfoMaskNone = 0,
+ KernelProfilingInfoCmdExecTimeMask = 0x00000001,
+};
+
+enum Capability {
+ CapabilityMatrix = 0,
+ CapabilityShader = 1,
+ CapabilityGeometry = 2,
+ CapabilityTessellation = 3,
+ CapabilityAddresses = 4,
+ CapabilityLinkage = 5,
+ CapabilityKernel = 6,
+ CapabilityVector16 = 7,
+ CapabilityFloat16Buffer = 8,
+ CapabilityFloat16 = 9,
+ CapabilityFloat64 = 10,
+ CapabilityInt64 = 11,
+ CapabilityInt64Atomics = 12,
+ CapabilityImageBasic = 13,
+ CapabilityImageReadWrite = 14,
+ CapabilityImageMipmap = 15,
+ CapabilityPipes = 17,
+ CapabilityGroups = 18,
+ CapabilityDeviceEnqueue = 19,
+ CapabilityLiteralSampler = 20,
+ CapabilityAtomicStorage = 21,
+ CapabilityInt16 = 22,
+ CapabilityTessellationPointSize = 23,
+ CapabilityGeometryPointSize = 24,
+ CapabilityImageGatherExtended = 25,
+ CapabilityStorageImageMultisample = 27,
+ CapabilityUniformBufferArrayDynamicIndexing = 28,
+ CapabilitySampledImageArrayDynamicIndexing = 29,
+ CapabilityStorageBufferArrayDynamicIndexing = 30,
+ CapabilityStorageImageArrayDynamicIndexing = 31,
+ CapabilityClipDistance = 32,
+ CapabilityCullDistance = 33,
+ CapabilityImageCubeArray = 34,
+ CapabilitySampleRateShading = 35,
+ CapabilityImageRect = 36,
+ CapabilitySampledRect = 37,
+ CapabilityGenericPointer = 38,
+ CapabilityInt8 = 39,
+ CapabilityInputAttachment = 40,
+ CapabilitySparseResidency = 41,
+ CapabilityMinLod = 42,
+ CapabilitySampled1D = 43,
+ CapabilityImage1D = 44,
+ CapabilitySampledCubeArray = 45,
+ CapabilitySampledBuffer = 46,
+ CapabilityImageBuffer = 47,
+ CapabilityImageMSArray = 48,
+ CapabilityStorageImageExtendedFormats = 49,
+ CapabilityImageQuery = 50,
+ CapabilityDerivativeControl = 51,
+ CapabilityInterpolationFunction = 52,
+ CapabilityTransformFeedback = 53,
+ CapabilityGeometryStreams = 54,
+ CapabilityStorageImageReadWithoutFormat = 55,
+ CapabilityStorageImageWriteWithoutFormat = 56,
+ CapabilityMultiViewport = 57,
+ CapabilitySubgroupDispatch = 58,
+ CapabilityNamedBarrier = 59,
+ CapabilityPipeStorage = 60,
+ CapabilityGroupNonUniform = 61,
+ CapabilityGroupNonUniformVote = 62,
+ CapabilityGroupNonUniformArithmetic = 63,
+ CapabilityGroupNonUniformBallot = 64,
+ CapabilityGroupNonUniformShuffle = 65,
+ CapabilityGroupNonUniformShuffleRelative = 66,
+ CapabilityGroupNonUniformClustered = 67,
+ CapabilityGroupNonUniformQuad = 68,
+ CapabilityShaderLayer = 69,
+ CapabilityShaderViewportIndex = 70,
+ CapabilitySubgroupBallotKHR = 4423,
+ CapabilityDrawParameters = 4427,
+ CapabilitySubgroupVoteKHR = 4431,
+ CapabilityStorageBuffer16BitAccess = 4433,
+ CapabilityStorageUniformBufferBlock16 = 4433,
+ CapabilityStorageUniform16 = 4434,
+ CapabilityUniformAndStorageBuffer16BitAccess = 4434,
+ CapabilityStoragePushConstant16 = 4435,
+ CapabilityStorageInputOutput16 = 4436,
+ CapabilityDeviceGroup = 4437,
+ CapabilityMultiView = 4439,
+ CapabilityVariablePointersStorageBuffer = 4441,
+ CapabilityVariablePointers = 4442,
+ CapabilityAtomicStorageOps = 4445,
+ CapabilitySampleMaskPostDepthCoverage = 4447,
+ CapabilityStorageBuffer8BitAccess = 4448,
+ CapabilityUniformAndStorageBuffer8BitAccess = 4449,
+ CapabilityStoragePushConstant8 = 4450,
+ CapabilityDenormPreserve = 4464,
+ CapabilityDenormFlushToZero = 4465,
+ CapabilitySignedZeroInfNanPreserve = 4466,
+ CapabilityRoundingModeRTE = 4467,
+ CapabilityRoundingModeRTZ = 4468,
+ CapabilityFloat16ImageAMD = 5008,
+ CapabilityImageGatherBiasLodAMD = 5009,
+ CapabilityFragmentMaskAMD = 5010,
+ CapabilityStencilExportEXT = 5013,
+ CapabilityImageReadWriteLodAMD = 5015,
+ CapabilityShaderClockKHR = 5055,
+ CapabilitySampleMaskOverrideCoverageNV = 5249,
+ CapabilityGeometryShaderPassthroughNV = 5251,
+ CapabilityShaderViewportIndexLayerEXT = 5254,
+ CapabilityShaderViewportIndexLayerNV = 5254,
+ CapabilityShaderViewportMaskNV = 5255,
+ CapabilityShaderStereoViewNV = 5259,
+ CapabilityPerViewAttributesNV = 5260,
+ CapabilityFragmentFullyCoveredEXT = 5265,
+ CapabilityMeshShadingNV = 5266,
+ CapabilityImageFootprintNV = 5282,
+ CapabilityFragmentBarycentricNV = 5284,
+ CapabilityComputeDerivativeGroupQuadsNV = 5288,
+ CapabilityFragmentDensityEXT = 5291,
+ CapabilityShadingRateNV = 5291,
+ CapabilityGroupNonUniformPartitionedNV = 5297,
+ CapabilityShaderNonUniform = 5301,
+ CapabilityShaderNonUniformEXT = 5301,
+ CapabilityRuntimeDescriptorArray = 5302,
+ CapabilityRuntimeDescriptorArrayEXT = 5302,
+ CapabilityInputAttachmentArrayDynamicIndexing = 5303,
+ CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303,
+ CapabilityUniformTexelBufferArrayDynamicIndexing = 5304,
+ CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304,
+ CapabilityStorageTexelBufferArrayDynamicIndexing = 5305,
+ CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305,
+ CapabilityUniformBufferArrayNonUniformIndexing = 5306,
+ CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306,
+ CapabilitySampledImageArrayNonUniformIndexing = 5307,
+ CapabilitySampledImageArrayNonUniformIndexingEXT = 5307,
+ CapabilityStorageBufferArrayNonUniformIndexing = 5308,
+ CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308,
+ CapabilityStorageImageArrayNonUniformIndexing = 5309,
+ CapabilityStorageImageArrayNonUniformIndexingEXT = 5309,
+ CapabilityInputAttachmentArrayNonUniformIndexing = 5310,
+ CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310,
+ CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311,
+ CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311,
+ CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312,
+ CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312,
+ CapabilityRayTracingNV = 5340,
+ CapabilityVulkanMemoryModel = 5345,
+ CapabilityVulkanMemoryModelKHR = 5345,
+ CapabilityVulkanMemoryModelDeviceScope = 5346,
+ CapabilityVulkanMemoryModelDeviceScopeKHR = 5346,
+ CapabilityPhysicalStorageBufferAddresses = 5347,
+ CapabilityPhysicalStorageBufferAddressesEXT = 5347,
+ CapabilityComputeDerivativeGroupLinearNV = 5350,
+ CapabilityCooperativeMatrixNV = 5357,
+ CapabilityFragmentShaderSampleInterlockEXT = 5363,
+ CapabilityFragmentShaderShadingRateInterlockEXT = 5372,
+ CapabilityShaderSMBuiltinsNV = 5373,
+ CapabilityFragmentShaderPixelInterlockEXT = 5378,
+ CapabilityDemoteToHelperInvocationEXT = 5379,
+ CapabilitySubgroupShuffleINTEL = 5568,
+ CapabilitySubgroupBufferBlockIOINTEL = 5569,
+ CapabilitySubgroupImageBlockIOINTEL = 5570,
+ CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
+ CapabilityIntegerFunctions2INTEL = 5584,
+ CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
+ CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
+ CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
+ CapabilityMax = 0x7fffffff,
+};
+
+enum Op {
+ OpNop = 0,
+ OpUndef = 1,
+ OpSourceContinued = 2,
+ OpSource = 3,
+ OpSourceExtension = 4,
+ OpName = 5,
+ OpMemberName = 6,
+ OpString = 7,
+ OpLine = 8,
+ OpExtension = 10,
+ OpExtInstImport = 11,
+ OpExtInst = 12,
+ OpMemoryModel = 14,
+ OpEntryPoint = 15,
+ OpExecutionMode = 16,
+ OpCapability = 17,
+ OpTypeVoid = 19,
+ OpTypeBool = 20,
+ OpTypeInt = 21,
+ OpTypeFloat = 22,
+ OpTypeVector = 23,
+ OpTypeMatrix = 24,
+ OpTypeImage = 25,
+ OpTypeSampler = 26,
+ OpTypeSampledImage = 27,
+ OpTypeArray = 28,
+ OpTypeRuntimeArray = 29,
+ OpTypeStruct = 30,
+ OpTypeOpaque = 31,
+ OpTypePointer = 32,
+ OpTypeFunction = 33,
+ OpTypeEvent = 34,
+ OpTypeDeviceEvent = 35,
+ OpTypeReserveId = 36,
+ OpTypeQueue = 37,
+ OpTypePipe = 38,
+ OpTypeForwardPointer = 39,
+ OpConstantTrue = 41,
+ OpConstantFalse = 42,
+ OpConstant = 43,
+ OpConstantComposite = 44,
+ OpConstantSampler = 45,
+ OpConstantNull = 46,
+ OpSpecConstantTrue = 48,
+ OpSpecConstantFalse = 49,
+ OpSpecConstant = 50,
+ OpSpecConstantComposite = 51,
+ OpSpecConstantOp = 52,
+ OpFunction = 54,
+ OpFunctionParameter = 55,
+ OpFunctionEnd = 56,
+ OpFunctionCall = 57,
+ OpVariable = 59,
+ OpImageTexelPointer = 60,
+ OpLoad = 61,
+ OpStore = 62,
+ OpCopyMemory = 63,
+ OpCopyMemorySized = 64,
+ OpAccessChain = 65,
+ OpInBoundsAccessChain = 66,
+ OpPtrAccessChain = 67,
+ OpArrayLength = 68,
+ OpGenericPtrMemSemantics = 69,
+ OpInBoundsPtrAccessChain = 70,
+ OpDecorate = 71,
+ OpMemberDecorate = 72,
+ OpDecorationGroup = 73,
+ OpGroupDecorate = 74,
+ OpGroupMemberDecorate = 75,
+ OpVectorExtractDynamic = 77,
+ OpVectorInsertDynamic = 78,
+ OpVectorShuffle = 79,
+ OpCompositeConstruct = 80,
+ OpCompositeExtract = 81,
+ OpCompositeInsert = 82,
+ OpCopyObject = 83,
+ OpTranspose = 84,
+ OpSampledImage = 86,
+ OpImageSampleImplicitLod = 87,
+ OpImageSampleExplicitLod = 88,
+ OpImageSampleDrefImplicitLod = 89,
+ OpImageSampleDrefExplicitLod = 90,
+ OpImageSampleProjImplicitLod = 91,
+ OpImageSampleProjExplicitLod = 92,
+ OpImageSampleProjDrefImplicitLod = 93,
+ OpImageSampleProjDrefExplicitLod = 94,
+ OpImageFetch = 95,
+ OpImageGather = 96,
+ OpImageDrefGather = 97,
+ OpImageRead = 98,
+ OpImageWrite = 99,
+ OpImage = 100,
+ OpImageQueryFormat = 101,
+ OpImageQueryOrder = 102,
+ OpImageQuerySizeLod = 103,
+ OpImageQuerySize = 104,
+ OpImageQueryLod = 105,
+ OpImageQueryLevels = 106,
+ OpImageQuerySamples = 107,
+ OpConvertFToU = 109,
+ OpConvertFToS = 110,
+ OpConvertSToF = 111,
+ OpConvertUToF = 112,
+ OpUConvert = 113,
+ OpSConvert = 114,
+ OpFConvert = 115,
+ OpQuantizeToF16 = 116,
+ OpConvertPtrToU = 117,
+ OpSatConvertSToU = 118,
+ OpSatConvertUToS = 119,
+ OpConvertUToPtr = 120,
+ OpPtrCastToGeneric = 121,
+ OpGenericCastToPtr = 122,
+ OpGenericCastToPtrExplicit = 123,
+ OpBitcast = 124,
+ OpSNegate = 126,
+ OpFNegate = 127,
+ OpIAdd = 128,
+ OpFAdd = 129,
+ OpISub = 130,
+ OpFSub = 131,
+ OpIMul = 132,
+ OpFMul = 133,
+ OpUDiv = 134,
+ OpSDiv = 135,
+ OpFDiv = 136,
+ OpUMod = 137,
+ OpSRem = 138,
+ OpSMod = 139,
+ OpFRem = 140,
+ OpFMod = 141,
+ OpVectorTimesScalar = 142,
+ OpMatrixTimesScalar = 143,
+ OpVectorTimesMatrix = 144,
+ OpMatrixTimesVector = 145,
+ OpMatrixTimesMatrix = 146,
+ OpOuterProduct = 147,
+ OpDot = 148,
+ OpIAddCarry = 149,
+ OpISubBorrow = 150,
+ OpUMulExtended = 151,
+ OpSMulExtended = 152,
+ OpAny = 154,
+ OpAll = 155,
+ OpIsNan = 156,
+ OpIsInf = 157,
+ OpIsFinite = 158,
+ OpIsNormal = 159,
+ OpSignBitSet = 160,
+ OpLessOrGreater = 161,
+ OpOrdered = 162,
+ OpUnordered = 163,
+ OpLogicalEqual = 164,
+ OpLogicalNotEqual = 165,
+ OpLogicalOr = 166,
+ OpLogicalAnd = 167,
+ OpLogicalNot = 168,
+ OpSelect = 169,
+ OpIEqual = 170,
+ OpINotEqual = 171,
+ OpUGreaterThan = 172,
+ OpSGreaterThan = 173,
+ OpUGreaterThanEqual = 174,
+ OpSGreaterThanEqual = 175,
+ OpULessThan = 176,
+ OpSLessThan = 177,
+ OpULessThanEqual = 178,
+ OpSLessThanEqual = 179,
+ OpFOrdEqual = 180,
+ OpFUnordEqual = 181,
+ OpFOrdNotEqual = 182,
+ OpFUnordNotEqual = 183,
+ OpFOrdLessThan = 184,
+ OpFUnordLessThan = 185,
+ OpFOrdGreaterThan = 186,
+ OpFUnordGreaterThan = 187,
+ OpFOrdLessThanEqual = 188,
+ OpFUnordLessThanEqual = 189,
+ OpFOrdGreaterThanEqual = 190,
+ OpFUnordGreaterThanEqual = 191,
+ OpShiftRightLogical = 194,
+ OpShiftRightArithmetic = 195,
+ OpShiftLeftLogical = 196,
+ OpBitwiseOr = 197,
+ OpBitwiseXor = 198,
+ OpBitwiseAnd = 199,
+ OpNot = 200,
+ OpBitFieldInsert = 201,
+ OpBitFieldSExtract = 202,
+ OpBitFieldUExtract = 203,
+ OpBitReverse = 204,
+ OpBitCount = 205,
+ OpDPdx = 207,
+ OpDPdy = 208,
+ OpFwidth = 209,
+ OpDPdxFine = 210,
+ OpDPdyFine = 211,
+ OpFwidthFine = 212,
+ OpDPdxCoarse = 213,
+ OpDPdyCoarse = 214,
+ OpFwidthCoarse = 215,
+ OpEmitVertex = 218,
+ OpEndPrimitive = 219,
+ OpEmitStreamVertex = 220,
+ OpEndStreamPrimitive = 221,
+ OpControlBarrier = 224,
+ OpMemoryBarrier = 225,
+ OpAtomicLoad = 227,
+ OpAtomicStore = 228,
+ OpAtomicExchange = 229,
+ OpAtomicCompareExchange = 230,
+ OpAtomicCompareExchangeWeak = 231,
+ OpAtomicIIncrement = 232,
+ OpAtomicIDecrement = 233,
+ OpAtomicIAdd = 234,
+ OpAtomicISub = 235,
+ OpAtomicSMin = 236,
+ OpAtomicUMin = 237,
+ OpAtomicSMax = 238,
+ OpAtomicUMax = 239,
+ OpAtomicAnd = 240,
+ OpAtomicOr = 241,
+ OpAtomicXor = 242,
+ OpPhi = 245,
+ OpLoopMerge = 246,
+ OpSelectionMerge = 247,
+ OpLabel = 248,
+ OpBranch = 249,
+ OpBranchConditional = 250,
+ OpSwitch = 251,
+ OpKill = 252,
+ OpReturn = 253,
+ OpReturnValue = 254,
+ OpUnreachable = 255,
+ OpLifetimeStart = 256,
+ OpLifetimeStop = 257,
+ OpGroupAsyncCopy = 259,
+ OpGroupWaitEvents = 260,
+ OpGroupAll = 261,
+ OpGroupAny = 262,
+ OpGroupBroadcast = 263,
+ OpGroupIAdd = 264,
+ OpGroupFAdd = 265,
+ OpGroupFMin = 266,
+ OpGroupUMin = 267,
+ OpGroupSMin = 268,
+ OpGroupFMax = 269,
+ OpGroupUMax = 270,
+ OpGroupSMax = 271,
+ OpReadPipe = 274,
+ OpWritePipe = 275,
+ OpReservedReadPipe = 276,
+ OpReservedWritePipe = 277,
+ OpReserveReadPipePackets = 278,
+ OpReserveWritePipePackets = 279,
+ OpCommitReadPipe = 280,
+ OpCommitWritePipe = 281,
+ OpIsValidReserveId = 282,
+ OpGetNumPipePackets = 283,
+ OpGetMaxPipePackets = 284,
+ OpGroupReserveReadPipePackets = 285,
+ OpGroupReserveWritePipePackets = 286,
+ OpGroupCommitReadPipe = 287,
+ OpGroupCommitWritePipe = 288,
+ OpEnqueueMarker = 291,
+ OpEnqueueKernel = 292,
+ OpGetKernelNDrangeSubGroupCount = 293,
+ OpGetKernelNDrangeMaxSubGroupSize = 294,
+ OpGetKernelWorkGroupSize = 295,
+ OpGetKernelPreferredWorkGroupSizeMultiple = 296,
+ OpRetainEvent = 297,
+ OpReleaseEvent = 298,
+ OpCreateUserEvent = 299,
+ OpIsValidEvent = 300,
+ OpSetUserEventStatus = 301,
+ OpCaptureEventProfilingInfo = 302,
+ OpGetDefaultQueue = 303,
+ OpBuildNDRange = 304,
+ OpImageSparseSampleImplicitLod = 305,
+ OpImageSparseSampleExplicitLod = 306,
+ OpImageSparseSampleDrefImplicitLod = 307,
+ OpImageSparseSampleDrefExplicitLod = 308,
+ OpImageSparseSampleProjImplicitLod = 309,
+ OpImageSparseSampleProjExplicitLod = 310,
+ OpImageSparseSampleProjDrefImplicitLod = 311,
+ OpImageSparseSampleProjDrefExplicitLod = 312,
+ OpImageSparseFetch = 313,
+ OpImageSparseGather = 314,
+ OpImageSparseDrefGather = 315,
+ OpImageSparseTexelsResident = 316,
+ OpNoLine = 317,
+ OpAtomicFlagTestAndSet = 318,
+ OpAtomicFlagClear = 319,
+ OpImageSparseRead = 320,
+ OpSizeOf = 321,
+ OpTypePipeStorage = 322,
+ OpConstantPipeStorage = 323,
+ OpCreatePipeFromPipeStorage = 324,
+ OpGetKernelLocalSizeForSubgroupCount = 325,
+ OpGetKernelMaxNumSubgroups = 326,
+ OpTypeNamedBarrier = 327,
+ OpNamedBarrierInitialize = 328,
+ OpMemoryNamedBarrier = 329,
+ OpModuleProcessed = 330,
+ OpExecutionModeId = 331,
+ OpDecorateId = 332,
+ OpGroupNonUniformElect = 333,
+ OpGroupNonUniformAll = 334,
+ OpGroupNonUniformAny = 335,
+ OpGroupNonUniformAllEqual = 336,
+ OpGroupNonUniformBroadcast = 337,
+ OpGroupNonUniformBroadcastFirst = 338,
+ OpGroupNonUniformBallot = 339,
+ OpGroupNonUniformInverseBallot = 340,
+ OpGroupNonUniformBallotBitExtract = 341,
+ OpGroupNonUniformBallotBitCount = 342,
+ OpGroupNonUniformBallotFindLSB = 343,
+ OpGroupNonUniformBallotFindMSB = 344,
+ OpGroupNonUniformShuffle = 345,
+ OpGroupNonUniformShuffleXor = 346,
+ OpGroupNonUniformShuffleUp = 347,
+ OpGroupNonUniformShuffleDown = 348,
+ OpGroupNonUniformIAdd = 349,
+ OpGroupNonUniformFAdd = 350,
+ OpGroupNonUniformIMul = 351,
+ OpGroupNonUniformFMul = 352,
+ OpGroupNonUniformSMin = 353,
+ OpGroupNonUniformUMin = 354,
+ OpGroupNonUniformFMin = 355,
+ OpGroupNonUniformSMax = 356,
+ OpGroupNonUniformUMax = 357,
+ OpGroupNonUniformFMax = 358,
+ OpGroupNonUniformBitwiseAnd = 359,
+ OpGroupNonUniformBitwiseOr = 360,
+ OpGroupNonUniformBitwiseXor = 361,
+ OpGroupNonUniformLogicalAnd = 362,
+ OpGroupNonUniformLogicalOr = 363,
+ OpGroupNonUniformLogicalXor = 364,
+ OpGroupNonUniformQuadBroadcast = 365,
+ OpGroupNonUniformQuadSwap = 366,
+ OpCopyLogical = 400,
+ OpPtrEqual = 401,
+ OpPtrNotEqual = 402,
+ OpPtrDiff = 403,
+ OpSubgroupBallotKHR = 4421,
+ OpSubgroupFirstInvocationKHR = 4422,
+ OpSubgroupAllKHR = 4428,
+ OpSubgroupAnyKHR = 4429,
+ OpSubgroupAllEqualKHR = 4430,
+ OpSubgroupReadInvocationKHR = 4432,
+ OpGroupIAddNonUniformAMD = 5000,
+ OpGroupFAddNonUniformAMD = 5001,
+ OpGroupFMinNonUniformAMD = 5002,
+ OpGroupUMinNonUniformAMD = 5003,
+ OpGroupSMinNonUniformAMD = 5004,
+ OpGroupFMaxNonUniformAMD = 5005,
+ OpGroupUMaxNonUniformAMD = 5006,
+ OpGroupSMaxNonUniformAMD = 5007,
+ OpFragmentMaskFetchAMD = 5011,
+ OpFragmentFetchAMD = 5012,
+ OpReadClockKHR = 5056,
+ OpImageSampleFootprintNV = 5283,
+ OpGroupNonUniformPartitionNV = 5296,
+ OpWritePackedPrimitiveIndices4x8NV = 5299,
+ OpReportIntersectionNV = 5334,
+ OpIgnoreIntersectionNV = 5335,
+ OpTerminateRayNV = 5336,
+ OpTraceNV = 5337,
+ OpTypeAccelerationStructureNV = 5341,
+ OpExecuteCallableNV = 5344,
+ OpTypeCooperativeMatrixNV = 5358,
+ OpCooperativeMatrixLoadNV = 5359,
+ OpCooperativeMatrixStoreNV = 5360,
+ OpCooperativeMatrixMulAddNV = 5361,
+ OpCooperativeMatrixLengthNV = 5362,
+ OpBeginInvocationInterlockEXT = 5364,
+ OpEndInvocationInterlockEXT = 5365,
+ OpDemoteToHelperInvocationEXT = 5380,
+ OpIsHelperInvocationEXT = 5381,
+ OpSubgroupShuffleINTEL = 5571,
+ OpSubgroupShuffleDownINTEL = 5572,
+ OpSubgroupShuffleUpINTEL = 5573,
+ OpSubgroupShuffleXorINTEL = 5574,
+ OpSubgroupBlockReadINTEL = 5575,
+ OpSubgroupBlockWriteINTEL = 5576,
+ OpSubgroupImageBlockReadINTEL = 5577,
+ OpSubgroupImageBlockWriteINTEL = 5578,
+ OpSubgroupImageMediaBlockReadINTEL = 5580,
+ OpSubgroupImageMediaBlockWriteINTEL = 5581,
+ OpUCountLeadingZerosINTEL = 5585,
+ OpUCountTrailingZerosINTEL = 5586,
+ OpAbsISubINTEL = 5587,
+ OpAbsUSubINTEL = 5588,
+ OpIAddSatINTEL = 5589,
+ OpUAddSatINTEL = 5590,
+ OpIAverageINTEL = 5591,
+ OpUAverageINTEL = 5592,
+ OpIAverageRoundedINTEL = 5593,
+ OpUAverageRoundedINTEL = 5594,
+ OpISubSatINTEL = 5595,
+ OpUSubSatINTEL = 5596,
+ OpIMul32x16INTEL = 5597,
+ OpUMul32x16INTEL = 5598,
+ OpDecorateString = 5632,
+ OpDecorateStringGOOGLE = 5632,
+ OpMemberDecorateString = 5633,
+ OpMemberDecorateStringGOOGLE = 5633,
+ OpVmeImageINTEL = 5699,
+ OpTypeVmeImageINTEL = 5700,
+ OpTypeAvcImePayloadINTEL = 5701,
+ OpTypeAvcRefPayloadINTEL = 5702,
+ OpTypeAvcSicPayloadINTEL = 5703,
+ OpTypeAvcMcePayloadINTEL = 5704,
+ OpTypeAvcMceResultINTEL = 5705,
+ OpTypeAvcImeResultINTEL = 5706,
+ OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707,
+ OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708,
+ OpTypeAvcImeSingleReferenceStreaminINTEL = 5709,
+ OpTypeAvcImeDualReferenceStreaminINTEL = 5710,
+ OpTypeAvcRefResultINTEL = 5711,
+ OpTypeAvcSicResultINTEL = 5712,
+ OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713,
+ OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714,
+ OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715,
+ OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716,
+ OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717,
+ OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718,
+ OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719,
+ OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720,
+ OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721,
+ OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722,
+ OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723,
+ OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724,
+ OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725,
+ OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726,
+ OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727,
+ OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728,
+ OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729,
+ OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730,
+ OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731,
+ OpSubgroupAvcMceConvertToImePayloadINTEL = 5732,
+ OpSubgroupAvcMceConvertToImeResultINTEL = 5733,
+ OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734,
+ OpSubgroupAvcMceConvertToRefResultINTEL = 5735,
+ OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736,
+ OpSubgroupAvcMceConvertToSicResultINTEL = 5737,
+ OpSubgroupAvcMceGetMotionVectorsINTEL = 5738,
+ OpSubgroupAvcMceGetInterDistortionsINTEL = 5739,
+ OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740,
+ OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741,
+ OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742,
+ OpSubgroupAvcMceGetInterDirectionsINTEL = 5743,
+ OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744,
+ OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745,
+ OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746,
+ OpSubgroupAvcImeInitializeINTEL = 5747,
+ OpSubgroupAvcImeSetSingleReferenceINTEL = 5748,
+ OpSubgroupAvcImeSetDualReferenceINTEL = 5749,
+ OpSubgroupAvcImeRefWindowSizeINTEL = 5750,
+ OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751,
+ OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752,
+ OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753,
+ OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754,
+ OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755,
+ OpSubgroupAvcImeSetWeightedSadINTEL = 5756,
+ OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757,
+ OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758,
+ OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759,
+ OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760,
+ OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761,
+ OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762,
+ OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763,
+ OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764,
+ OpSubgroupAvcImeConvertToMceResultINTEL = 5765,
+ OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766,
+ OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767,
+ OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768,
+ OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769,
+ OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770,
+ OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771,
+ OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772,
+ OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773,
+ OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774,
+ OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775,
+ OpSubgroupAvcImeGetBorderReachedINTEL = 5776,
+ OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777,
+ OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778,
+ OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779,
+ OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780,
+ OpSubgroupAvcFmeInitializeINTEL = 5781,
+ OpSubgroupAvcBmeInitializeINTEL = 5782,
+ OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783,
+ OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784,
+ OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785,
+ OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786,
+ OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787,
+ OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788,
+ OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789,
+ OpSubgroupAvcRefConvertToMceResultINTEL = 5790,
+ OpSubgroupAvcSicInitializeINTEL = 5791,
+ OpSubgroupAvcSicConfigureSkcINTEL = 5792,
+ OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793,
+ OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794,
+ OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795,
+ OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796,
+ OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797,
+ OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798,
+ OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799,
+ OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800,
+ OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801,
+ OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802,
+ OpSubgroupAvcSicEvaluateIpeINTEL = 5803,
+ OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804,
+ OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805,
+ OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806,
+ OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807,
+ OpSubgroupAvcSicConvertToMceResultINTEL = 5808,
+ OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809,
+ OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810,
+ OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811,
+ OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812,
+ OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813,
+ OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
+ OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
+ OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+ OpMax = 0x7fffffff,
+};
+
+#ifdef SPV_ENABLE_UTILITY_CODE
+inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
+ *hasResult = *hasResultType = false;
+ switch (opcode) {
+ default: /* unknown opcode */ break;
+ case OpNop: *hasResult = false; *hasResultType = false; break;
+ case OpUndef: *hasResult = true; *hasResultType = true; break;
+ case OpSourceContinued: *hasResult = false; *hasResultType = false; break;
+ case OpSource: *hasResult = false; *hasResultType = false; break;
+ case OpSourceExtension: *hasResult = false; *hasResultType = false; break;
+ case OpName: *hasResult = false; *hasResultType = false; break;
+ case OpMemberName: *hasResult = false; *hasResultType = false; break;
+ case OpString: *hasResult = true; *hasResultType = false; break;
+ case OpLine: *hasResult = false; *hasResultType = false; break;
+ case OpExtension: *hasResult = false; *hasResultType = false; break;
+ case OpExtInstImport: *hasResult = true; *hasResultType = false; break;
+ case OpExtInst: *hasResult = true; *hasResultType = true; break;
+ case OpMemoryModel: *hasResult = false; *hasResultType = false; break;
+ case OpEntryPoint: *hasResult = false; *hasResultType = false; break;
+ case OpExecutionMode: *hasResult = false; *hasResultType = false; break;
+ case OpCapability: *hasResult = false; *hasResultType = false; break;
+ case OpTypeVoid: *hasResult = true; *hasResultType = false; break;
+ case OpTypeBool: *hasResult = true; *hasResultType = false; break;
+ case OpTypeInt: *hasResult = true; *hasResultType = false; break;
+ case OpTypeFloat: *hasResult = true; *hasResultType = false; break;
+ case OpTypeVector: *hasResult = true; *hasResultType = false; break;
+ case OpTypeMatrix: *hasResult = true; *hasResultType = false; break;
+ case OpTypeImage: *hasResult = true; *hasResultType = false; break;
+ case OpTypeSampler: *hasResult = true; *hasResultType = false; break;
+ case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break;
+ case OpTypeArray: *hasResult = true; *hasResultType = false; break;
+ case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break;
+ case OpTypeStruct: *hasResult = true; *hasResultType = false; break;
+ case OpTypeOpaque: *hasResult = true; *hasResultType = false; break;
+ case OpTypePointer: *hasResult = true; *hasResultType = false; break;
+ case OpTypeFunction: *hasResult = true; *hasResultType = false; break;
+ case OpTypeEvent: *hasResult = true; *hasResultType = false; break;
+ case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break;
+ case OpTypeReserveId: *hasResult = true; *hasResultType = false; break;
+ case OpTypeQueue: *hasResult = true; *hasResultType = false; break;
+ case OpTypePipe: *hasResult = true; *hasResultType = false; break;
+ case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break;
+ case OpConstantTrue: *hasResult = true; *hasResultType = true; break;
+ case OpConstantFalse: *hasResult = true; *hasResultType = true; break;
+ case OpConstant: *hasResult = true; *hasResultType = true; break;
+ case OpConstantComposite: *hasResult = true; *hasResultType = true; break;
+ case OpConstantSampler: *hasResult = true; *hasResultType = true; break;
+ case OpConstantNull: *hasResult = true; *hasResultType = true; break;
+ case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break;
+ case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break;
+ case OpSpecConstant: *hasResult = true; *hasResultType = true; break;
+ case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break;
+ case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break;
+ case OpFunction: *hasResult = true; *hasResultType = true; break;
+ case OpFunctionParameter: *hasResult = true; *hasResultType = true; break;
+ case OpFunctionEnd: *hasResult = false; *hasResultType = false; break;
+ case OpFunctionCall: *hasResult = true; *hasResultType = true; break;
+ case OpVariable: *hasResult = true; *hasResultType = true; break;
+ case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break;
+ case OpLoad: *hasResult = true; *hasResultType = true; break;
+ case OpStore: *hasResult = false; *hasResultType = false; break;
+ case OpCopyMemory: *hasResult = false; *hasResultType = false; break;
+ case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break;
+ case OpAccessChain: *hasResult = true; *hasResultType = true; break;
+ case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break;
+ case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break;
+ case OpArrayLength: *hasResult = true; *hasResultType = true; break;
+ case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break;
+ case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break;
+ case OpDecorate: *hasResult = false; *hasResultType = false; break;
+ case OpMemberDecorate: *hasResult = false; *hasResultType = false; break;
+ case OpDecorationGroup: *hasResult = true; *hasResultType = false; break;
+ case OpGroupDecorate: *hasResult = false; *hasResultType = false; break;
+ case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break;
+ case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break;
+ case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break;
+ case OpVectorShuffle: *hasResult = true; *hasResultType = true; break;
+ case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break;
+ case OpCompositeExtract: *hasResult = true; *hasResultType = true; break;
+ case OpCompositeInsert: *hasResult = true; *hasResultType = true; break;
+ case OpCopyObject: *hasResult = true; *hasResultType = true; break;
+ case OpTranspose: *hasResult = true; *hasResultType = true; break;
+ case OpSampledImage: *hasResult = true; *hasResultType = true; break;
+ case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageFetch: *hasResult = true; *hasResultType = true; break;
+ case OpImageGather: *hasResult = true; *hasResultType = true; break;
+ case OpImageDrefGather: *hasResult = true; *hasResultType = true; break;
+ case OpImageRead: *hasResult = true; *hasResultType = true; break;
+ case OpImageWrite: *hasResult = false; *hasResultType = false; break;
+ case OpImage: *hasResult = true; *hasResultType = true; break;
+ case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break;
+ case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break;
+ case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageQuerySize: *hasResult = true; *hasResultType = true; break;
+ case OpImageQueryLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break;
+ case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break;
+ case OpConvertFToU: *hasResult = true; *hasResultType = true; break;
+ case OpConvertFToS: *hasResult = true; *hasResultType = true; break;
+ case OpConvertSToF: *hasResult = true; *hasResultType = true; break;
+ case OpConvertUToF: *hasResult = true; *hasResultType = true; break;
+ case OpUConvert: *hasResult = true; *hasResultType = true; break;
+ case OpSConvert: *hasResult = true; *hasResultType = true; break;
+ case OpFConvert: *hasResult = true; *hasResultType = true; break;
+ case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break;
+ case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break;
+ case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break;
+ case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break;
+ case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break;
+ case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break;
+ case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break;
+ case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break;
+ case OpBitcast: *hasResult = true; *hasResultType = true; break;
+ case OpSNegate: *hasResult = true; *hasResultType = true; break;
+ case OpFNegate: *hasResult = true; *hasResultType = true; break;
+ case OpIAdd: *hasResult = true; *hasResultType = true; break;
+ case OpFAdd: *hasResult = true; *hasResultType = true; break;
+ case OpISub: *hasResult = true; *hasResultType = true; break;
+ case OpFSub: *hasResult = true; *hasResultType = true; break;
+ case OpIMul: *hasResult = true; *hasResultType = true; break;
+ case OpFMul: *hasResult = true; *hasResultType = true; break;
+ case OpUDiv: *hasResult = true; *hasResultType = true; break;
+ case OpSDiv: *hasResult = true; *hasResultType = true; break;
+ case OpFDiv: *hasResult = true; *hasResultType = true; break;
+ case OpUMod: *hasResult = true; *hasResultType = true; break;
+ case OpSRem: *hasResult = true; *hasResultType = true; break;
+ case OpSMod: *hasResult = true; *hasResultType = true; break;
+ case OpFRem: *hasResult = true; *hasResultType = true; break;
+ case OpFMod: *hasResult = true; *hasResultType = true; break;
+ case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break;
+ case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break;
+ case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break;
+ case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break;
+ case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break;
+ case OpOuterProduct: *hasResult = true; *hasResultType = true; break;
+ case OpDot: *hasResult = true; *hasResultType = true; break;
+ case OpIAddCarry: *hasResult = true; *hasResultType = true; break;
+ case OpISubBorrow: *hasResult = true; *hasResultType = true; break;
+ case OpUMulExtended: *hasResult = true; *hasResultType = true; break;
+ case OpSMulExtended: *hasResult = true; *hasResultType = true; break;
+ case OpAny: *hasResult = true; *hasResultType = true; break;
+ case OpAll: *hasResult = true; *hasResultType = true; break;
+ case OpIsNan: *hasResult = true; *hasResultType = true; break;
+ case OpIsInf: *hasResult = true; *hasResultType = true; break;
+ case OpIsFinite: *hasResult = true; *hasResultType = true; break;
+ case OpIsNormal: *hasResult = true; *hasResultType = true; break;
+ case OpSignBitSet: *hasResult = true; *hasResultType = true; break;
+ case OpLessOrGreater: *hasResult = true; *hasResultType = true; break;
+ case OpOrdered: *hasResult = true; *hasResultType = true; break;
+ case OpUnordered: *hasResult = true; *hasResultType = true; break;
+ case OpLogicalEqual: *hasResult = true; *hasResultType = true; break;
+ case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break;
+ case OpLogicalOr: *hasResult = true; *hasResultType = true; break;
+ case OpLogicalAnd: *hasResult = true; *hasResultType = true; break;
+ case OpLogicalNot: *hasResult = true; *hasResultType = true; break;
+ case OpSelect: *hasResult = true; *hasResultType = true; break;
+ case OpIEqual: *hasResult = true; *hasResultType = true; break;
+ case OpINotEqual: *hasResult = true; *hasResultType = true; break;
+ case OpUGreaterThan: *hasResult = true; *hasResultType = true; break;
+ case OpSGreaterThan: *hasResult = true; *hasResultType = true; break;
+ case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break;
+ case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break;
+ case OpULessThan: *hasResult = true; *hasResultType = true; break;
+ case OpSLessThan: *hasResult = true; *hasResultType = true; break;
+ case OpULessThanEqual: *hasResult = true; *hasResultType = true; break;
+ case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break;
+ case OpFOrdEqual: *hasResult = true; *hasResultType = true; break;
+ case OpFUnordEqual: *hasResult = true; *hasResultType = true; break;
+ case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break;
+ case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break;
+ case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break;
+ case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break;
+ case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break;
+ case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break;
+ case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break;
+ case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break;
+ case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break;
+ case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break;
+ case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break;
+ case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break;
+ case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break;
+ case OpBitwiseOr: *hasResult = true; *hasResultType = true; break;
+ case OpBitwiseXor: *hasResult = true; *hasResultType = true; break;
+ case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break;
+ case OpNot: *hasResult = true; *hasResultType = true; break;
+ case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break;
+ case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break;
+ case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break;
+ case OpBitReverse: *hasResult = true; *hasResultType = true; break;
+ case OpBitCount: *hasResult = true; *hasResultType = true; break;
+ case OpDPdx: *hasResult = true; *hasResultType = true; break;
+ case OpDPdy: *hasResult = true; *hasResultType = true; break;
+ case OpFwidth: *hasResult = true; *hasResultType = true; break;
+ case OpDPdxFine: *hasResult = true; *hasResultType = true; break;
+ case OpDPdyFine: *hasResult = true; *hasResultType = true; break;
+ case OpFwidthFine: *hasResult = true; *hasResultType = true; break;
+ case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break;
+ case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break;
+ case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break;
+ case OpEmitVertex: *hasResult = false; *hasResultType = false; break;
+ case OpEndPrimitive: *hasResult = false; *hasResultType = false; break;
+ case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break;
+ case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break;
+ case OpControlBarrier: *hasResult = false; *hasResultType = false; break;
+ case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break;
+ case OpAtomicLoad: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicStore: *hasResult = false; *hasResultType = false; break;
+ case OpAtomicExchange: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicISub: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicSMin: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicUMin: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicSMax: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicUMax: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicAnd: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicOr: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicXor: *hasResult = true; *hasResultType = true; break;
+ case OpPhi: *hasResult = true; *hasResultType = true; break;
+ case OpLoopMerge: *hasResult = false; *hasResultType = false; break;
+ case OpSelectionMerge: *hasResult = false; *hasResultType = false; break;
+ case OpLabel: *hasResult = true; *hasResultType = false; break;
+ case OpBranch: *hasResult = false; *hasResultType = false; break;
+ case OpBranchConditional: *hasResult = false; *hasResultType = false; break;
+ case OpSwitch: *hasResult = false; *hasResultType = false; break;
+ case OpKill: *hasResult = false; *hasResultType = false; break;
+ case OpReturn: *hasResult = false; *hasResultType = false; break;
+ case OpReturnValue: *hasResult = false; *hasResultType = false; break;
+ case OpUnreachable: *hasResult = false; *hasResultType = false; break;
+ case OpLifetimeStart: *hasResult = false; *hasResultType = false; break;
+ case OpLifetimeStop: *hasResult = false; *hasResultType = false; break;
+ case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break;
+ case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break;
+ case OpGroupAll: *hasResult = true; *hasResultType = true; break;
+ case OpGroupAny: *hasResult = true; *hasResultType = true; break;
+ case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break;
+ case OpGroupIAdd: *hasResult = true; *hasResultType = true; break;
+ case OpGroupFAdd: *hasResult = true; *hasResultType = true; break;
+ case OpGroupFMin: *hasResult = true; *hasResultType = true; break;
+ case OpGroupUMin: *hasResult = true; *hasResultType = true; break;
+ case OpGroupSMin: *hasResult = true; *hasResultType = true; break;
+ case OpGroupFMax: *hasResult = true; *hasResultType = true; break;
+ case OpGroupUMax: *hasResult = true; *hasResultType = true; break;
+ case OpGroupSMax: *hasResult = true; *hasResultType = true; break;
+ case OpReadPipe: *hasResult = true; *hasResultType = true; break;
+ case OpWritePipe: *hasResult = true; *hasResultType = true; break;
+ case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break;
+ case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break;
+ case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break;
+ case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break;
+ case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break;
+ case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break;
+ case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break;
+ case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break;
+ case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break;
+ case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break;
+ case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break;
+ case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break;
+ case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break;
+ case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break;
+ case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break;
+ case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break;
+ case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break;
+ case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break;
+ case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break;
+ case OpRetainEvent: *hasResult = false; *hasResultType = false; break;
+ case OpReleaseEvent: *hasResult = false; *hasResultType = false; break;
+ case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break;
+ case OpIsValidEvent: *hasResult = true; *hasResultType = true; break;
+ case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break;
+ case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break;
+ case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break;
+ case OpBuildNDRange: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseGather: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break;
+ case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break;
+ case OpNoLine: *hasResult = false; *hasResultType = false; break;
+ case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break;
+ case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break;
+ case OpImageSparseRead: *hasResult = true; *hasResultType = true; break;
+ case OpSizeOf: *hasResult = true; *hasResultType = true; break;
+ case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break;
+ case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break;
+ case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break;
+ case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break;
+ case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break;
+ case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break;
+ case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break;
+ case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break;
+ case OpModuleProcessed: *hasResult = false; *hasResultType = false; break;
+ case OpExecutionModeId: *hasResult = false; *hasResultType = false; break;
+ case OpDecorateId: *hasResult = false; *hasResultType = false; break;
+ case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break;
+ case OpCopyLogical: *hasResult = true; *hasResultType = true; break;
+ case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
+ case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;
+ case OpPtrDiff: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
+ case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+ case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+ case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+ case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+ case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+ case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+ case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+ case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+ case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break;
+ case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break;
+ case OpReadClockKHR: *hasResult = true; *hasResultType = true; break;
+ case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break;
+ case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break;
+ case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break;
+ case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break;
+ case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break;
+ case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break;
+ case OpTraceNV: *hasResult = false; *hasResultType = false; break;
+ case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break;
+ case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break;
+ case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break;
+ case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break;
+ case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break;
+ case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break;
+ case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break;
+ case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;
+ case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;
+ case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break;
+ case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;
+ case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;
+ case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;
+ case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
+ case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
+ case OpDecorateString: *hasResult = false; *hasResultType = false; break;
+ case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
+ case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break;
+ case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
+ case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
+ }
+}
+#endif /* SPV_ENABLE_UTILITY_CODE */
+
+// Overload operator| for mask bit combining
+
+inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); }
+inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); }
+inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); }
+inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); }
+inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); }
+inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); }
+inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
+inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
+
+} // end namespace spv
+
+#endif // #ifndef spirv_HPP
+
diff --git a/thirdparty/glslang/SPIRV/spvIR.h b/thirdparty/glslang/SPIRV/spvIR.h
new file mode 100755
index 0000000000..cf6a71159a
--- /dev/null
+++ b/thirdparty/glslang/SPIRV/spvIR.h
@@ -0,0 +1,486 @@
+//
+// Copyright (C) 2014 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+// SPIRV-IR
+//
+// Simple in-memory representation (IR) of SPIRV. Just for holding
+// Each function's CFG of blocks. Has this hierarchy:
+// - Module, which is a list of
+// - Function, which is a list of
+// - Block, which is a list of
+// - Instruction
+//
+
+#pragma once
+#ifndef spvIR_H
+#define spvIR_H
+
+#include "spirv.hpp"
+
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <vector>
+
+namespace spv {
+
+class Block;
+class Function;
+class Module;
+
+const Id NoResult = 0;
+const Id NoType = 0;
+
+const Decoration NoPrecision = DecorationMax;
+
+#ifdef __GNUC__
+# define POTENTIALLY_UNUSED __attribute__((unused))
+#else
+# define POTENTIALLY_UNUSED
+#endif
+
+POTENTIALLY_UNUSED
+const MemorySemanticsMask MemorySemanticsAllMemory =
+ (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask |
+ MemorySemanticsWorkgroupMemoryMask |
+ MemorySemanticsAtomicCounterMemoryMask |
+ MemorySemanticsImageMemoryMask);
+
+struct IdImmediate {
+ bool isId; // true if word is an Id, false if word is an immediate
+ unsigned word;
+ IdImmediate(bool i, unsigned w) : isId(i), word(w) {}
+};
+
+//
+// SPIR-V IR instruction.
+//
+
+class Instruction {
+public:
+ Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { }
+ explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { }
+ virtual ~Instruction() {}
+ void addIdOperand(Id id) {
+ operands.push_back(id);
+ idOperand.push_back(true);
+ }
+ void addImmediateOperand(unsigned int immediate) {
+ operands.push_back(immediate);
+ idOperand.push_back(false);
+ }
+ void setImmediateOperand(unsigned idx, unsigned int immediate) {
+ assert(!idOperand[idx]);
+ operands[idx] = immediate;
+ }
+
+ void addStringOperand(const char* str)
+ {
+ unsigned int word;
+ char* wordString = (char*)&word;
+ char* wordPtr = wordString;
+ int charCount = 0;
+ char c;
+ do {
+ c = *(str++);
+ *(wordPtr++) = c;
+ ++charCount;
+ if (charCount == 4) {
+ addImmediateOperand(word);
+ wordPtr = wordString;
+ charCount = 0;
+ }
+ } while (c != 0);
+
+ // deal with partial last word
+ if (charCount > 0) {
+ // pad with 0s
+ for (; charCount < 4; ++charCount)
+ *(wordPtr++) = 0;
+ addImmediateOperand(word);
+ }
+ }
+ bool isIdOperand(int op) const { return idOperand[op]; }
+ void setBlock(Block* b) { block = b; }
+ Block* getBlock() const { return block; }
+ Op getOpCode() const { return opCode; }
+ int getNumOperands() const
+ {
+ assert(operands.size() == idOperand.size());
+ return (int)operands.size();
+ }
+ Id getResultId() const { return resultId; }
+ Id getTypeId() const { return typeId; }
+ Id getIdOperand(int op) const {
+ assert(idOperand[op]);
+ return operands[op];
+ }
+ unsigned int getImmediateOperand(int op) const {
+ assert(!idOperand[op]);
+ return operands[op];
+ }
+
+ // Write out the binary form.
+ void dump(std::vector<unsigned int>& out) const
+ {
+ // Compute the wordCount
+ unsigned int wordCount = 1;
+ if (typeId)
+ ++wordCount;
+ if (resultId)
+ ++wordCount;
+ wordCount += (unsigned int)operands.size();
+
+ // Write out the beginning of the instruction
+ out.push_back(((wordCount) << WordCountShift) | opCode);
+ if (typeId)
+ out.push_back(typeId);
+ if (resultId)
+ out.push_back(resultId);
+
+ // Write out the operands
+ for (int op = 0; op < (int)operands.size(); ++op)
+ out.push_back(operands[op]);
+ }
+
+protected:
+ Instruction(const Instruction&);
+ Id resultId;
+ Id typeId;
+ Op opCode;
+ std::vector<Id> operands; // operands, both <id> and immediates (both are unsigned int)
+ std::vector<bool> idOperand; // true for operands that are <id>, false for immediates
+ Block* block;
+};
+
+//
+// SPIR-V IR block.
+//
+
+class Block {
+public:
+ Block(Id id, Function& parent);
+ virtual ~Block()
+ {
+ }
+
+ Id getId() { return instructions.front()->getResultId(); }
+
+ Function& getParent() const { return parent; }
+ void addInstruction(std::unique_ptr<Instruction> inst);
+ void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);}
+ void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
+ const std::vector<Block*>& getPredecessors() const { return predecessors; }
+ const std::vector<Block*>& getSuccessors() const { return successors; }
+ const std::vector<std::unique_ptr<Instruction> >& getInstructions() const {
+ return instructions;
+ }
+ const std::vector<std::unique_ptr<Instruction> >& getLocalVariables() const { return localVariables; }
+ void setUnreachable() { unreachable = true; }
+ bool isUnreachable() const { return unreachable; }
+ // Returns the block's merge instruction, if one exists (otherwise null).
+ const Instruction* getMergeInstruction() const {
+ if (instructions.size() < 2) return nullptr;
+ const Instruction* nextToLast = (instructions.cend() - 2)->get();
+ switch (nextToLast->getOpCode()) {
+ case OpSelectionMerge:
+ case OpLoopMerge:
+ return nextToLast;
+ default:
+ return nullptr;
+ }
+ return nullptr;
+ }
+
+ // Change this block into a canonical dead merge block. Delete instructions
+ // as necessary. A canonical dead merge block has only an OpLabel and an
+ // OpUnreachable.
+ void rewriteAsCanonicalUnreachableMerge() {
+ assert(localVariables.empty());
+ // Delete all instructions except for the label.
+ assert(instructions.size() > 0);
+ instructions.resize(1);
+ successors.clear();
+ Instruction* unreachable = new Instruction(OpUnreachable);
+ addInstruction(std::unique_ptr<Instruction>(unreachable));
+ }
+ // Change this block into a canonical dead continue target branching to the
+ // given header ID. Delete instructions as necessary. A canonical dead continue
+ // target has only an OpLabel and an unconditional branch back to the corresponding
+ // header.
+ void rewriteAsCanonicalUnreachableContinue(Block* header) {
+ assert(localVariables.empty());
+ // Delete all instructions except for the label.
+ assert(instructions.size() > 0);
+ instructions.resize(1);
+ successors.clear();
+ // Add OpBranch back to the header.
+ assert(header != nullptr);
+ Instruction* branch = new Instruction(OpBranch);
+ branch->addIdOperand(header->getId());
+ addInstruction(std::unique_ptr<Instruction>(branch));
+ successors.push_back(header);
+ }
+
+ bool isTerminated() const
+ {
+ switch (instructions.back()->getOpCode()) {
+ case OpBranch:
+ case OpBranchConditional:
+ case OpSwitch:
+ case OpKill:
+ case OpReturn:
+ case OpReturnValue:
+ case OpUnreachable:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ void dump(std::vector<unsigned int>& out) const
+ {
+ instructions[0]->dump(out);
+ for (int i = 0; i < (int)localVariables.size(); ++i)
+ localVariables[i]->dump(out);
+ for (int i = 1; i < (int)instructions.size(); ++i)
+ instructions[i]->dump(out);
+ }
+
+protected:
+ Block(const Block&);
+ Block& operator=(Block&);
+
+ // To enforce keeping parent and ownership in sync:
+ friend Function;
+
+ std::vector<std::unique_ptr<Instruction> > instructions;
+ std::vector<Block*> predecessors, successors;
+ std::vector<std::unique_ptr<Instruction> > localVariables;
+ Function& parent;
+
+ // track whether this block is known to be uncreachable (not necessarily
+ // true for all unreachable blocks, but should be set at least
+ // for the extraneous ones introduced by the builder).
+ bool unreachable;
+};
+
+// The different reasons for reaching a block in the inReadableOrder traversal.
+enum ReachReason {
+ // Reachable from the entry block via transfers of control, i.e. branches.
+ ReachViaControlFlow = 0,
+ // A continue target that is not reachable via control flow.
+ ReachDeadContinue,
+ // A merge block that is not reachable via control flow.
+ ReachDeadMerge
+};
+
+// Traverses the control-flow graph rooted at root in an order suited for
+// readable code generation. Invokes callback at every node in the traversal
+// order. The callback arguments are:
+// - the block,
+// - the reason we reached the block,
+// - if the reason was that block is an unreachable continue or unreachable merge block
+// then the last parameter is the corresponding header block.
+void inReadableOrder(Block* root, std::function<void(Block*, ReachReason, Block* header)> callback);
+
+//
+// SPIR-V IR Function.
+//
+
+class Function {
+public:
+ Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent);
+ virtual ~Function()
+ {
+ for (int i = 0; i < (int)parameterInstructions.size(); ++i)
+ delete parameterInstructions[i];
+
+ for (int i = 0; i < (int)blocks.size(); ++i)
+ delete blocks[i];
+ }
+ Id getId() const { return functionInstruction.getResultId(); }
+ Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); }
+ Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); }
+
+ void addBlock(Block* block) { blocks.push_back(block); }
+ void removeBlock(Block* block)
+ {
+ auto found = find(blocks.begin(), blocks.end(), block);
+ assert(found != blocks.end());
+ blocks.erase(found);
+ delete block;
+ }
+
+ Module& getParent() const { return parent; }
+ Block* getEntryBlock() const { return blocks.front(); }
+ Block* getLastBlock() const { return blocks.back(); }
+ const std::vector<Block*>& getBlocks() const { return blocks; }
+ void addLocalVariable(std::unique_ptr<Instruction> inst);
+ Id getReturnType() const { return functionInstruction.getTypeId(); }
+
+ void setImplicitThis() { implicitThis = true; }
+ bool hasImplicitThis() const { return implicitThis; }
+
+ void dump(std::vector<unsigned int>& out) const
+ {
+ // OpFunction
+ functionInstruction.dump(out);
+
+ // OpFunctionParameter
+ for (int p = 0; p < (int)parameterInstructions.size(); ++p)
+ parameterInstructions[p]->dump(out);
+
+ // Blocks
+ inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); });
+ Instruction end(0, 0, OpFunctionEnd);
+ end.dump(out);
+ }
+
+protected:
+ Function(const Function&);
+ Function& operator=(Function&);
+
+ Module& parent;
+ Instruction functionInstruction;
+ std::vector<Instruction*> parameterInstructions;
+ std::vector<Block*> blocks;
+ bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument
+};
+
+//
+// SPIR-V IR Module.
+//
+
+class Module {
+public:
+ Module() {}
+ virtual ~Module()
+ {
+ // TODO delete things
+ }
+
+ void addFunction(Function *fun) { functions.push_back(fun); }
+
+ void mapInstruction(Instruction *instruction)
+ {
+ spv::Id resultId = instruction->getResultId();
+ // map the instruction's result id
+ if (resultId >= idToInstruction.size())
+ idToInstruction.resize(resultId + 16);
+ idToInstruction[resultId] = instruction;
+ }
+
+ Instruction* getInstruction(Id id) const { return idToInstruction[id]; }
+ const std::vector<Function*>& getFunctions() const { return functions; }
+ spv::Id getTypeId(Id resultId) const {
+ return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId();
+ }
+ StorageClass getStorageClass(Id typeId) const
+ {
+ assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer);
+ return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0);
+ }
+
+ void dump(std::vector<unsigned int>& out) const
+ {
+ for (int f = 0; f < (int)functions.size(); ++f)
+ functions[f]->dump(out);
+ }
+
+protected:
+ Module(const Module&);
+ std::vector<Function*> functions;
+
+ // map from result id to instruction having that result id
+ std::vector<Instruction*> idToInstruction;
+
+ // map from a result id to its type id
+};
+
+//
+// Implementation (it's here due to circular type definitions).
+//
+
+// Add both
+// - the OpFunction instruction
+// - all the OpFunctionParameter instructions
+__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
+ : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false)
+{
+ // OpFunction
+ functionInstruction.addImmediateOperand(FunctionControlMaskNone);
+ functionInstruction.addIdOperand(functionType);
+ parent.mapInstruction(&functionInstruction);
+ parent.addFunction(this);
+
+ // OpFunctionParameter
+ Instruction* typeInst = parent.getInstruction(functionType);
+ int numParams = typeInst->getNumOperands() - 1;
+ for (int p = 0; p < numParams; ++p) {
+ Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter);
+ parent.mapInstruction(param);
+ parameterInstructions.push_back(param);
+ }
+}
+
+__inline void Function::addLocalVariable(std::unique_ptr<Instruction> inst)
+{
+ Instruction* raw_instruction = inst.get();
+ blocks[0]->addLocalVariable(std::move(inst));
+ parent.mapInstruction(raw_instruction);
+}
+
+__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false)
+{
+ instructions.push_back(std::unique_ptr<Instruction>(new Instruction(id, NoType, OpLabel)));
+ instructions.back()->setBlock(this);
+ parent.getParent().mapInstruction(instructions.back().get());
+}
+
+__inline void Block::addInstruction(std::unique_ptr<Instruction> inst)
+{
+ Instruction* raw_instruction = inst.get();
+ instructions.push_back(std::move(inst));
+ raw_instruction->setBlock(this);
+ if (raw_instruction->getResultId())
+ parent.getParent().mapInstruction(raw_instruction);
+}
+
+} // end spv namespace
+
+#endif // spvIR_H
diff --git a/thirdparty/glslang/glslang/GenericCodeGen/CodeGen.cpp b/thirdparty/glslang/glslang/GenericCodeGen/CodeGen.cpp
new file mode 100644
index 0000000000..b3c7226dfa
--- /dev/null
+++ b/thirdparty/glslang/glslang/GenericCodeGen/CodeGen.cpp
@@ -0,0 +1,76 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/Common.h"
+#include "../Include/ShHandle.h"
+#include "../MachineIndependent/Versions.h"
+
+//
+// Here is where real machine specific high-level data would be defined.
+//
+class TGenericCompiler : public TCompiler {
+public:
+ TGenericCompiler(EShLanguage l, int dOptions) : TCompiler(l, infoSink), debugOptions(dOptions) { }
+ virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile);
+ TInfoSink infoSink;
+ int debugOptions;
+};
+
+//
+// This function must be provided to create the actual
+// compile object used by higher level code. It returns
+// a subclass of TCompiler.
+//
+TCompiler* ConstructCompiler(EShLanguage language, int debugOptions)
+{
+ return new TGenericCompiler(language, debugOptions);
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+ delete compiler;
+}
+
+//
+// Generate code from the given parse tree
+//
+bool TGenericCompiler::compile(TIntermNode* /*root*/, int /*version*/, EProfile /*profile*/)
+{
+ haveValidObjectCode = true;
+
+ return haveValidObjectCode;
+}
diff --git a/thirdparty/glslang/glslang/GenericCodeGen/Link.cpp b/thirdparty/glslang/glslang/GenericCodeGen/Link.cpp
new file mode 100644
index 0000000000..c38db0f69f
--- /dev/null
+++ b/thirdparty/glslang/glslang/GenericCodeGen/Link.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// The top level algorithms for linking multiple
+// shaders together.
+//
+#include "../Include/Common.h"
+#include "../Include/ShHandle.h"
+
+//
+// Actual link object, derived from the shader handle base classes.
+//
+class TGenericLinker : public TLinker {
+public:
+ TGenericLinker(EShExecutable e, int dOptions) : TLinker(e, infoSink), debugOptions(dOptions) { }
+ bool link(TCompilerList&, TUniformMap*) { return true; }
+ void getAttributeBindings(ShBindingTable const **) const { }
+ TInfoSink infoSink;
+ int debugOptions;
+};
+
+//
+// The internal view of a uniform/float object exchanged with the driver.
+//
+class TUniformLinkedMap : public TUniformMap {
+public:
+ TUniformLinkedMap() { }
+ virtual int getLocation(const char*) { return 0; }
+};
+
+TShHandleBase* ConstructLinker(EShExecutable executable, int debugOptions)
+{
+ return new TGenericLinker(executable, debugOptions);
+}
+
+void DeleteLinker(TShHandleBase* linker)
+{
+ delete linker;
+}
+
+TUniformMap* ConstructUniformMap()
+{
+ return new TUniformLinkedMap();
+}
+
+void DeleteUniformMap(TUniformMap* map)
+{
+ delete map;
+}
+
+TShHandleBase* ConstructBindings()
+{
+ return 0;
+}
+
+void DeleteBindingList(TShHandleBase* bindingList)
+{
+ delete bindingList;
+}
diff --git a/thirdparty/glslang/glslang/Include/BaseTypes.h b/thirdparty/glslang/glslang/Include/BaseTypes.h
new file mode 100644
index 0000000000..6d4b4ff8e3
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/BaseTypes.h
@@ -0,0 +1,559 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _BASICTYPES_INCLUDED_
+#define _BASICTYPES_INCLUDED_
+
+namespace glslang {
+
+//
+// Basic type. Arrays, vectors, sampler details, etc., are orthogonal to this.
+//
+enum TBasicType {
+ EbtVoid,
+ EbtFloat,
+ EbtDouble,
+ EbtFloat16,
+ EbtInt8,
+ EbtUint8,
+ EbtInt16,
+ EbtUint16,
+ EbtInt,
+ EbtUint,
+ EbtInt64,
+ EbtUint64,
+ EbtBool,
+ EbtAtomicUint,
+ EbtSampler,
+ EbtStruct,
+ EbtBlock,
+ EbtAccStructNV,
+ EbtReference,
+
+ // HLSL types that live only temporarily.
+ EbtString,
+
+ EbtNumTypes
+};
+
+//
+// Storage qualifiers. Should align with different kinds of storage or
+// resource or GLSL storage qualifier. Expansion is deprecated.
+//
+// N.B.: You probably DON'T want to add anything here, but rather just add it
+// to the built-in variables. See the comment above TBuiltInVariable.
+//
+// A new built-in variable will normally be an existing qualifier, like 'in', 'out', etc.
+// DO NOT follow the design pattern of, say EvqInstanceId, etc.
+//
+enum TStorageQualifier {
+ EvqTemporary, // For temporaries (within a function), read/write
+ EvqGlobal, // For globals read/write
+ EvqConst, // User-defined constant values, will be semantically constant and constant folded
+ EvqVaryingIn, // pipeline input, read only, also supercategory for all built-ins not included in this enum (see TBuiltInVariable)
+ EvqVaryingOut, // pipeline output, read/write, also supercategory for all built-ins not included in this enum (see TBuiltInVariable)
+ EvqUniform, // read only, shared with app
+ EvqBuffer, // read/write, shared with app
+ EvqShared, // compute shader's read/write 'shared' qualifier
+
+ EvqPayloadNV,
+ EvqPayloadInNV,
+ EvqHitAttrNV,
+ EvqCallableDataNV,
+ EvqCallableDataInNV,
+
+ // parameters
+ EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
+ EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter
+ EvqInOut,
+ EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics
+
+ // built-ins read by vertex shader
+ EvqVertexId,
+ EvqInstanceId,
+
+ // built-ins written by vertex shader
+ EvqPosition,
+ EvqPointSize,
+ EvqClipVertex,
+
+ // built-ins read by fragment shader
+ EvqFace,
+ EvqFragCoord,
+ EvqPointCoord,
+
+ // built-ins written by fragment shader
+ EvqFragColor,
+ EvqFragDepth,
+
+ // end of list
+ EvqLast
+};
+
+//
+// Subcategories of the TStorageQualifier, simply to give a direct mapping
+// between built-in variable names and an numerical value (the enum).
+//
+// For backward compatibility, there is some redundancy between the
+// TStorageQualifier and these. Existing members should both be maintained accurately.
+// However, any new built-in variable (and any existing non-redundant one)
+// must follow the pattern that the specific built-in is here, and only its
+// general qualifier is in TStorageQualifier.
+//
+// Something like gl_Position, which is sometimes 'in' and sometimes 'out'
+// shows up as two different built-in variables in a single stage, but
+// only has a single enum in TBuiltInVariable, so both the
+// TStorageQualifier and the TBuitinVariable are needed to distinguish
+// between them.
+//
+enum TBuiltInVariable {
+ EbvNone,
+ EbvNumWorkGroups,
+ EbvWorkGroupSize,
+ EbvWorkGroupId,
+ EbvLocalInvocationId,
+ EbvGlobalInvocationId,
+ EbvLocalInvocationIndex,
+ EbvNumSubgroups,
+ EbvSubgroupID,
+ EbvSubGroupSize,
+ EbvSubGroupInvocation,
+ EbvSubGroupEqMask,
+ EbvSubGroupGeMask,
+ EbvSubGroupGtMask,
+ EbvSubGroupLeMask,
+ EbvSubGroupLtMask,
+ EbvSubgroupSize2,
+ EbvSubgroupInvocation2,
+ EbvSubgroupEqMask2,
+ EbvSubgroupGeMask2,
+ EbvSubgroupGtMask2,
+ EbvSubgroupLeMask2,
+ EbvSubgroupLtMask2,
+ EbvVertexId,
+ EbvInstanceId,
+ EbvVertexIndex,
+ EbvInstanceIndex,
+ EbvBaseVertex,
+ EbvBaseInstance,
+ EbvDrawId,
+ EbvPosition,
+ EbvPointSize,
+ EbvClipVertex,
+ EbvClipDistance,
+ EbvCullDistance,
+ EbvNormal,
+ EbvVertex,
+ EbvMultiTexCoord0,
+ EbvMultiTexCoord1,
+ EbvMultiTexCoord2,
+ EbvMultiTexCoord3,
+ EbvMultiTexCoord4,
+ EbvMultiTexCoord5,
+ EbvMultiTexCoord6,
+ EbvMultiTexCoord7,
+ EbvFrontColor,
+ EbvBackColor,
+ EbvFrontSecondaryColor,
+ EbvBackSecondaryColor,
+ EbvTexCoord,
+ EbvFogFragCoord,
+ EbvInvocationId,
+ EbvPrimitiveId,
+ EbvLayer,
+ EbvViewportIndex,
+ EbvPatchVertices,
+ EbvTessLevelOuter,
+ EbvTessLevelInner,
+ EbvBoundingBox,
+ EbvTessCoord,
+ EbvColor,
+ EbvSecondaryColor,
+ EbvFace,
+ EbvFragCoord,
+ EbvPointCoord,
+ EbvFragColor,
+ EbvFragData,
+ EbvFragDepth,
+ EbvFragStencilRef,
+ EbvSampleId,
+ EbvSamplePosition,
+ EbvSampleMask,
+ EbvHelperInvocation,
+
+ EbvBaryCoordNoPersp,
+ EbvBaryCoordNoPerspCentroid,
+ EbvBaryCoordNoPerspSample,
+ EbvBaryCoordSmooth,
+ EbvBaryCoordSmoothCentroid,
+ EbvBaryCoordSmoothSample,
+ EbvBaryCoordPullModel,
+
+ EbvViewIndex,
+ EbvDeviceIndex,
+
+ EbvFragSizeEXT,
+ EbvFragInvocationCountEXT,
+
+ EbvViewportMaskNV,
+ EbvSecondaryPositionNV,
+ EbvSecondaryViewportMaskNV,
+ EbvPositionPerViewNV,
+ EbvViewportMaskPerViewNV,
+ EbvFragFullyCoveredNV,
+ EbvFragmentSizeNV,
+ EbvInvocationsPerPixelNV,
+ // ray tracing
+ EbvLaunchIdNV,
+ EbvLaunchSizeNV,
+ EbvInstanceCustomIndexNV,
+ EbvWorldRayOriginNV,
+ EbvWorldRayDirectionNV,
+ EbvObjectRayOriginNV,
+ EbvObjectRayDirectionNV,
+ EbvRayTminNV,
+ EbvRayTmaxNV,
+ EbvHitTNV,
+ EbvHitKindNV,
+ EbvObjectToWorldNV,
+ EbvWorldToObjectNV,
+ EbvIncomingRayFlagsNV,
+ // barycentrics
+ EbvBaryCoordNV,
+ EbvBaryCoordNoPerspNV,
+ // mesh shaders
+ EbvTaskCountNV,
+ EbvPrimitiveCountNV,
+ EbvPrimitiveIndicesNV,
+ EbvClipDistancePerViewNV,
+ EbvCullDistancePerViewNV,
+ EbvLayerPerViewNV,
+ EbvMeshViewCountNV,
+ EbvMeshViewIndicesNV,
+
+ // sm builtins
+ EbvWarpsPerSM,
+ EbvSMCount,
+ EbvWarpID,
+ EbvSMID,
+
+ // HLSL built-ins that live only temporarily, until they get remapped
+ // to one of the above.
+ EbvFragDepthGreater,
+ EbvFragDepthLesser,
+ EbvGsOutputStream,
+ EbvOutputPatch,
+ EbvInputPatch,
+
+ // structbuffer types
+ EbvAppendConsume, // no need to differentiate append and consume
+ EbvRWStructuredBuffer,
+ EbvStructuredBuffer,
+ EbvByteAddressBuffer,
+ EbvRWByteAddressBuffer,
+
+ EbvLast
+};
+
+// In this enum, order matters; users can assume higher precision is a bigger value
+// and EpqNone is 0.
+enum TPrecisionQualifier {
+ EpqNone = 0,
+ EpqLow,
+ EpqMedium,
+ EpqHigh
+};
+
+#ifdef GLSLANG_WEB
+__inline const char* GetStorageQualifierString(TStorageQualifier q) { return ""; }
+__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) { return ""; }
+#else
+// These will show up in error messages
+__inline const char* GetStorageQualifierString(TStorageQualifier q)
+{
+ switch (q) {
+ case EvqTemporary: return "temp"; break;
+ case EvqGlobal: return "global"; break;
+ case EvqConst: return "const"; break;
+ case EvqConstReadOnly: return "const (read only)"; break;
+ case EvqVaryingIn: return "in"; break;
+ case EvqVaryingOut: return "out"; break;
+ case EvqUniform: return "uniform"; break;
+ case EvqBuffer: return "buffer"; break;
+ case EvqShared: return "shared"; break;
+ case EvqIn: return "in"; break;
+ case EvqOut: return "out"; break;
+ case EvqInOut: return "inout"; break;
+ case EvqVertexId: return "gl_VertexId"; break;
+ case EvqInstanceId: return "gl_InstanceId"; break;
+ case EvqPosition: return "gl_Position"; break;
+ case EvqPointSize: return "gl_PointSize"; break;
+ case EvqClipVertex: return "gl_ClipVertex"; break;
+ case EvqFace: return "gl_FrontFacing"; break;
+ case EvqFragCoord: return "gl_FragCoord"; break;
+ case EvqPointCoord: return "gl_PointCoord"; break;
+ case EvqFragColor: return "fragColor"; break;
+ case EvqFragDepth: return "gl_FragDepth"; break;
+ case EvqPayloadNV: return "rayPayloadNV"; break;
+ case EvqPayloadInNV: return "rayPayloadInNV"; break;
+ case EvqHitAttrNV: return "hitAttributeNV"; break;
+ case EvqCallableDataNV: return "callableDataNV"; break;
+ case EvqCallableDataInNV: return "callableDataInNV"; break;
+ default: return "unknown qualifier";
+ }
+}
+
+__inline const char* GetBuiltInVariableString(TBuiltInVariable v)
+{
+ switch (v) {
+ case EbvNone: return "";
+ case EbvNumWorkGroups: return "NumWorkGroups";
+ case EbvWorkGroupSize: return "WorkGroupSize";
+ case EbvWorkGroupId: return "WorkGroupID";
+ case EbvLocalInvocationId: return "LocalInvocationID";
+ case EbvGlobalInvocationId: return "GlobalInvocationID";
+ case EbvLocalInvocationIndex: return "LocalInvocationIndex";
+ case EbvNumSubgroups: return "NumSubgroups";
+ case EbvSubgroupID: return "SubgroupID";
+ case EbvSubGroupSize: return "SubGroupSize";
+ case EbvSubGroupInvocation: return "SubGroupInvocation";
+ case EbvSubGroupEqMask: return "SubGroupEqMask";
+ case EbvSubGroupGeMask: return "SubGroupGeMask";
+ case EbvSubGroupGtMask: return "SubGroupGtMask";
+ case EbvSubGroupLeMask: return "SubGroupLeMask";
+ case EbvSubGroupLtMask: return "SubGroupLtMask";
+ case EbvSubgroupSize2: return "SubgroupSize";
+ case EbvSubgroupInvocation2: return "SubgroupInvocationID";
+ case EbvSubgroupEqMask2: return "SubgroupEqMask";
+ case EbvSubgroupGeMask2: return "SubgroupGeMask";
+ case EbvSubgroupGtMask2: return "SubgroupGtMask";
+ case EbvSubgroupLeMask2: return "SubgroupLeMask";
+ case EbvSubgroupLtMask2: return "SubgroupLtMask";
+ case EbvVertexId: return "VertexId";
+ case EbvInstanceId: return "InstanceId";
+ case EbvVertexIndex: return "VertexIndex";
+ case EbvInstanceIndex: return "InstanceIndex";
+ case EbvBaseVertex: return "BaseVertex";
+ case EbvBaseInstance: return "BaseInstance";
+ case EbvDrawId: return "DrawId";
+ case EbvPosition: return "Position";
+ case EbvPointSize: return "PointSize";
+ case EbvClipVertex: return "ClipVertex";
+ case EbvClipDistance: return "ClipDistance";
+ case EbvCullDistance: return "CullDistance";
+ case EbvNormal: return "Normal";
+ case EbvVertex: return "Vertex";
+ case EbvMultiTexCoord0: return "MultiTexCoord0";
+ case EbvMultiTexCoord1: return "MultiTexCoord1";
+ case EbvMultiTexCoord2: return "MultiTexCoord2";
+ case EbvMultiTexCoord3: return "MultiTexCoord3";
+ case EbvMultiTexCoord4: return "MultiTexCoord4";
+ case EbvMultiTexCoord5: return "MultiTexCoord5";
+ case EbvMultiTexCoord6: return "MultiTexCoord6";
+ case EbvMultiTexCoord7: return "MultiTexCoord7";
+ case EbvFrontColor: return "FrontColor";
+ case EbvBackColor: return "BackColor";
+ case EbvFrontSecondaryColor: return "FrontSecondaryColor";
+ case EbvBackSecondaryColor: return "BackSecondaryColor";
+ case EbvTexCoord: return "TexCoord";
+ case EbvFogFragCoord: return "FogFragCoord";
+ case EbvInvocationId: return "InvocationID";
+ case EbvPrimitiveId: return "PrimitiveID";
+ case EbvLayer: return "Layer";
+ case EbvViewportIndex: return "ViewportIndex";
+ case EbvPatchVertices: return "PatchVertices";
+ case EbvTessLevelOuter: return "TessLevelOuter";
+ case EbvTessLevelInner: return "TessLevelInner";
+ case EbvBoundingBox: return "BoundingBox";
+ case EbvTessCoord: return "TessCoord";
+ case EbvColor: return "Color";
+ case EbvSecondaryColor: return "SecondaryColor";
+ case EbvFace: return "Face";
+ case EbvFragCoord: return "FragCoord";
+ case EbvPointCoord: return "PointCoord";
+ case EbvFragColor: return "FragColor";
+ case EbvFragData: return "FragData";
+ case EbvFragDepth: return "FragDepth";
+ case EbvFragStencilRef: return "FragStencilRef";
+ case EbvSampleId: return "SampleId";
+ case EbvSamplePosition: return "SamplePosition";
+ case EbvSampleMask: return "SampleMaskIn";
+ case EbvHelperInvocation: return "HelperInvocation";
+
+ case EbvBaryCoordNoPersp: return "BaryCoordNoPersp";
+ case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid";
+ case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample";
+ case EbvBaryCoordSmooth: return "BaryCoordSmooth";
+ case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid";
+ case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample";
+ case EbvBaryCoordPullModel: return "BaryCoordPullModel";
+
+ case EbvViewIndex: return "ViewIndex";
+ case EbvDeviceIndex: return "DeviceIndex";
+
+ case EbvFragSizeEXT: return "FragSizeEXT";
+ case EbvFragInvocationCountEXT: return "FragInvocationCountEXT";
+
+ case EbvViewportMaskNV: return "ViewportMaskNV";
+ case EbvSecondaryPositionNV: return "SecondaryPositionNV";
+ case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
+ case EbvPositionPerViewNV: return "PositionPerViewNV";
+ case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
+ case EbvFragFullyCoveredNV: return "FragFullyCoveredNV";
+ case EbvFragmentSizeNV: return "FragmentSizeNV";
+ case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV";
+ case EbvLaunchIdNV: return "LaunchIdNV";
+ case EbvLaunchSizeNV: return "LaunchSizeNV";
+ case EbvInstanceCustomIndexNV: return "InstanceCustomIndexNV";
+ case EbvWorldRayOriginNV: return "WorldRayOriginNV";
+ case EbvWorldRayDirectionNV: return "WorldRayDirectionNV";
+ case EbvObjectRayOriginNV: return "ObjectRayOriginNV";
+ case EbvObjectRayDirectionNV: return "ObjectRayDirectionNV";
+ case EbvRayTminNV: return "ObjectRayTminNV";
+ case EbvRayTmaxNV: return "ObjectRayTmaxNV";
+ case EbvHitTNV: return "HitTNV";
+ case EbvHitKindNV: return "HitKindNV";
+ case EbvIncomingRayFlagsNV: return "IncomingRayFlagsNV";
+ case EbvObjectToWorldNV: return "ObjectToWorldNV";
+ case EbvWorldToObjectNV: return "WorldToObjectNV";
+
+ case EbvBaryCoordNV: return "BaryCoordNV";
+ case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
+
+ case EbvTaskCountNV: return "TaskCountNV";
+ case EbvPrimitiveCountNV: return "PrimitiveCountNV";
+ case EbvPrimitiveIndicesNV: return "PrimitiveIndicesNV";
+ case EbvClipDistancePerViewNV: return "ClipDistancePerViewNV";
+ case EbvCullDistancePerViewNV: return "CullDistancePerViewNV";
+ case EbvLayerPerViewNV: return "LayerPerViewNV";
+ case EbvMeshViewCountNV: return "MeshViewCountNV";
+ case EbvMeshViewIndicesNV: return "MeshViewIndicesNV";
+
+ case EbvWarpsPerSM: return "WarpsPerSMNV";
+ case EbvSMCount: return "SMCountNV";
+ case EbvWarpID: return "WarpIDNV";
+ case EbvSMID: return "SMIDNV";
+
+ default: return "unknown built-in variable";
+ }
+}
+
+__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p)
+{
+ switch (p) {
+ case EpqNone: return ""; break;
+ case EpqLow: return "lowp"; break;
+ case EpqMedium: return "mediump"; break;
+ case EpqHigh: return "highp"; break;
+ default: return "unknown precision qualifier";
+ }
+}
+#endif
+
+__inline bool isTypeSignedInt(TBasicType type)
+{
+ switch (type) {
+ case EbtInt8:
+ case EbtInt16:
+ case EbtInt:
+ case EbtInt64:
+ return true;
+ default:
+ return false;
+ }
+}
+
+__inline bool isTypeUnsignedInt(TBasicType type)
+{
+ switch (type) {
+ case EbtUint8:
+ case EbtUint16:
+ case EbtUint:
+ case EbtUint64:
+ return true;
+ default:
+ return false;
+ }
+}
+
+__inline bool isTypeInt(TBasicType type)
+{
+ return isTypeSignedInt(type) || isTypeUnsignedInt(type);
+}
+
+__inline bool isTypeFloat(TBasicType type)
+{
+ switch (type) {
+ case EbtFloat:
+ case EbtDouble:
+ case EbtFloat16:
+ return true;
+ default:
+ return false;
+ }
+}
+
+__inline int getTypeRank(TBasicType type)
+{
+ int res = -1;
+ switch(type) {
+ case EbtInt8:
+ case EbtUint8:
+ res = 0;
+ break;
+ case EbtInt16:
+ case EbtUint16:
+ res = 1;
+ break;
+ case EbtInt:
+ case EbtUint:
+ res = 2;
+ break;
+ case EbtInt64:
+ case EbtUint64:
+ res = 3;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ return res;
+}
+
+} // end namespace glslang
+
+#endif // _BASICTYPES_INCLUDED_
diff --git a/thirdparty/glslang/glslang/Include/Common.h b/thirdparty/glslang/glslang/Include/Common.h
new file mode 100644
index 0000000000..2c511bc1c5
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/Common.h
@@ -0,0 +1,294 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2013 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _COMMON_INCLUDED_
+#define _COMMON_INCLUDED_
+
+
+#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700)
+#include <sstream>
+namespace std {
+template<typename T>
+std::string to_string(const T& val) {
+ std::ostringstream os;
+ os << val;
+ return os.str();
+}
+}
+#endif
+
+// -- GODOT start --
+#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) /* || defined MINGW_HAS_SECURE_API */
+// -- GODOT end --
+ #include <basetsd.h>
+ #ifndef snprintf
+ #define snprintf sprintf_s
+ #endif
+ #define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args))
+#elif defined (solaris)
+ #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args))
+ #include <sys/int_types.h>
+ #define UINT_PTR uintptr_t
+#else
+ #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args))
+ #include <stdint.h>
+ #define UINT_PTR uintptr_t
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1800
+ #include <stdlib.h>
+ inline long long int strtoll (const char* str, char** endptr, int base)
+ {
+ return _strtoi64(str, endptr, base);
+ }
+ inline unsigned long long int strtoull (const char* str, char** endptr, int base)
+ {
+ return _strtoui64(str, endptr, base);
+ }
+ inline long long int atoll (const char* str)
+ {
+ return strtoll(str, NULL, 10);
+ }
+#endif
+
+#if defined(_MSC_VER)
+#define strdup _strdup
+#endif
+
+/* windows only pragma */
+#ifdef _MSC_VER
+ #pragma warning(disable : 4786) // Don't warn about too long identifiers
+ #pragma warning(disable : 4514) // unused inline method
+ #pragma warning(disable : 4201) // nameless union
+#endif
+
+#include <set>
+#include <unordered_set>
+#include <vector>
+#include <map>
+#include <unordered_map>
+#include <list>
+#include <algorithm>
+#include <string>
+#include <cstdio>
+#include <cstdlib>
+#include <cassert>
+
+#include "PoolAlloc.h"
+
+//
+// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
+//
+#define POOL_ALLOCATOR_NEW_DELETE(A) \
+ void* operator new(size_t s) { return (A).allocate(s); } \
+ void* operator new(size_t, void *_Where) { return (_Where); } \
+ void operator delete(void*) { } \
+ void operator delete(void *, void *) { } \
+ void* operator new[](size_t s) { return (A).allocate(s); } \
+ void* operator new[](size_t, void *_Where) { return (_Where); } \
+ void operator delete[](void*) { } \
+ void operator delete[](void *, void *) { }
+
+namespace glslang {
+
+ //
+ // Pool version of string.
+ //
+ typedef pool_allocator<char> TStringAllocator;
+ typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
+
+} // end namespace glslang
+
+// Repackage the std::hash for use by unordered map/set with a TString key.
+namespace std {
+
+ template<> struct hash<glslang::TString> {
+ std::size_t operator()(const glslang::TString& s) const
+ {
+ const unsigned _FNV_offset_basis = 2166136261U;
+ const unsigned _FNV_prime = 16777619U;
+ unsigned _Val = _FNV_offset_basis;
+ size_t _Count = s.size();
+ const char* _First = s.c_str();
+ for (size_t _Next = 0; _Next < _Count; ++_Next)
+ {
+ _Val ^= (unsigned)_First[_Next];
+ _Val *= _FNV_prime;
+ }
+
+ return _Val;
+ }
+ };
+}
+
+namespace glslang {
+
+inline TString* NewPoolTString(const char* s)
+{
+ void* memory = GetThreadPoolAllocator().allocate(sizeof(TString));
+ return new(memory) TString(s);
+}
+
+template<class T> inline T* NewPoolObject(T*)
+{
+ return new(GetThreadPoolAllocator().allocate(sizeof(T))) T;
+}
+
+template<class T> inline T* NewPoolObject(T, int instances)
+{
+ return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances];
+}
+
+//
+// Pool allocator versions of vectors, lists, and maps
+//
+template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+ typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
+ TVector() : std::vector<T, pool_allocator<T> >() {}
+ TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
+ TVector(size_type i) : std::vector<T, pool_allocator<T> >(i) {}
+ TVector(size_type i, const T& val) : std::vector<T, pool_allocator<T> >(i, val) {}
+};
+
+template <class T> class TList : public std::list<T, pool_allocator<T> > {
+};
+
+template <class K, class D, class CMP = std::less<K> >
+class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<K const, D> > > {
+};
+
+template <class K, class D, class HASH = std::hash<K>, class PRED = std::equal_to<K> >
+class TUnorderedMap : public std::unordered_map<K, D, HASH, PRED, pool_allocator<std::pair<K const, D> > > {
+};
+
+//
+// Persistent string memory. Should only be used for strings that survive
+// across compiles/links.
+//
+typedef std::basic_string<char> TPersistString;
+
+//
+// templatized min and max functions.
+//
+template <class T> T Min(const T a, const T b) { return a < b ? a : b; }
+template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
+
+//
+// Create a TString object from an integer.
+//
+#if defined _MSC_VER || defined MINGW_HAS_SECURE_API
+inline const TString String(const int i, const int base = 10)
+{
+ char text[16]; // 32 bit ints are at most 10 digits in base 10
+ _itoa_s(i, text, sizeof(text), base);
+ return text;
+}
+#else
+inline const TString String(const int i, const int /*base*/ = 10)
+{
+ char text[16]; // 32 bit ints are at most 10 digits in base 10
+
+ // we assume base 10 for all cases
+ snprintf(text, sizeof(text), "%d", i);
+
+ return text;
+}
+#endif
+
+struct TSourceLoc {
+ void init()
+ {
+ name = nullptr; string = 0; line = 0; column = 0;
+ }
+ void init(int stringNum) { init(); string = stringNum; }
+ // Returns the name if it exists. Otherwise, returns the string number.
+ std::string getStringNameOrNum(bool quoteStringName = true) const
+ {
+ if (name != nullptr) {
+ TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name;
+ std::string ret_str(qstr.c_str());
+ return ret_str;
+ }
+ return std::to_string((long long)string);
+ }
+ const char* getFilename() const
+ {
+ if (name == nullptr)
+ return nullptr;
+ return name->c_str();
+ }
+ const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); }
+ TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr
+ int string;
+ int line;
+ int column;
+};
+
+class TPragmaTable : public TMap<TString, TString> {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+};
+
+const int MaxTokenLength = 1024;
+
+template <class T> bool IsPow2(T powerOf2)
+{
+ if (powerOf2 <= 0)
+ return false;
+
+ return (powerOf2 & (powerOf2 - 1)) == 0;
+}
+
+// Round number up to a multiple of the given powerOf2, which is not
+// a power, just a number that must be a power of 2.
+template <class T> void RoundToPow2(T& number, int powerOf2)
+{
+ assert(IsPow2(powerOf2));
+ number = (number + powerOf2 - 1) & ~(powerOf2 - 1);
+}
+
+template <class T> bool IsMultipleOfPow2(T number, int powerOf2)
+{
+ assert(IsPow2(powerOf2));
+ return ! (number & (powerOf2 - 1));
+}
+
+} // end namespace glslang
+
+#endif // _COMMON_INCLUDED_
diff --git a/thirdparty/glslang/glslang/Include/ConstantUnion.h b/thirdparty/glslang/glslang/Include/ConstantUnion.h
new file mode 100644
index 0000000000..76b2d9c08b
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/ConstantUnion.h
@@ -0,0 +1,974 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _CONSTANT_UNION_INCLUDED_
+#define _CONSTANT_UNION_INCLUDED_
+
+#include "../Include/Common.h"
+#include "../Include/BaseTypes.h"
+
+namespace glslang {
+
+class TConstUnion {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+ TConstUnion() : iConst(0), type(EbtInt) { }
+
+ void setI8Const(signed char i)
+ {
+ i8Const = i;
+ type = EbtInt8;
+ }
+
+ void setU8Const(unsigned char u)
+ {
+ u8Const = u;
+ type = EbtUint8;
+ }
+
+ void setI16Const(signed short i)
+ {
+ i16Const = i;
+ type = EbtInt16;
+ }
+
+ void setU16Const(unsigned short u)
+ {
+ u16Const = u;
+ type = EbtUint16;
+ }
+
+ void setIConst(int i)
+ {
+ iConst = i;
+ type = EbtInt;
+ }
+
+ void setUConst(unsigned int u)
+ {
+ uConst = u;
+ type = EbtUint;
+ }
+
+ void setI64Const(long long i64)
+ {
+ i64Const = i64;
+ type = EbtInt64;
+ }
+
+ void setU64Const(unsigned long long u64)
+ {
+ u64Const = u64;
+ type = EbtUint64;
+ }
+
+ void setDConst(double d)
+ {
+ dConst = d;
+ type = EbtDouble;
+ }
+
+ void setBConst(bool b)
+ {
+ bConst = b;
+ type = EbtBool;
+ }
+
+ void setSConst(const TString* s)
+ {
+ sConst = s;
+ type = EbtString;
+ }
+
+ signed char getI8Const() const { return i8Const; }
+ unsigned char getU8Const() const { return u8Const; }
+ signed short getI16Const() const { return i16Const; }
+ unsigned short getU16Const() const { return u16Const; }
+ int getIConst() const { return iConst; }
+ unsigned int getUConst() const { return uConst; }
+ long long getI64Const() const { return i64Const; }
+ unsigned long long getU64Const() const { return u64Const; }
+ double getDConst() const { return dConst; }
+ bool getBConst() const { return bConst; }
+ const TString* getSConst() const { return sConst; }
+
+ bool operator==(const signed char i) const
+ {
+ if (i == i8Const)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const unsigned char u) const
+ {
+ if (u == u8Const)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const signed short i) const
+ {
+ if (i == i16Const)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const unsigned short u) const
+ {
+ if (u == u16Const)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const int i) const
+ {
+ if (i == iConst)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const unsigned int u) const
+ {
+ if (u == uConst)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const long long i64) const
+ {
+ if (i64 == i64Const)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const unsigned long long u64) const
+ {
+ if (u64 == u64Const)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const double d) const
+ {
+ if (d == dConst)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const bool b) const
+ {
+ if (b == bConst)
+ return true;
+
+ return false;
+ }
+
+ bool operator==(const TConstUnion& constant) const
+ {
+ if (constant.type != type)
+ return false;
+
+ switch (type) {
+ case EbtInt:
+ if (constant.iConst == iConst)
+ return true;
+
+ break;
+ case EbtUint:
+ if (constant.uConst == uConst)
+ return true;
+
+ break;
+ case EbtBool:
+ if (constant.bConst == bConst)
+ return true;
+
+ break;
+ case EbtDouble:
+ if (constant.dConst == dConst)
+ return true;
+
+ break;
+
+#ifndef GLSLANG_WEB
+ case EbtInt16:
+ if (constant.i16Const == i16Const)
+ return true;
+
+ break;
+ case EbtUint16:
+ if (constant.u16Const == u16Const)
+ return true;
+
+ break;
+ case EbtInt8:
+ if (constant.i8Const == i8Const)
+ return true;
+
+ break;
+ case EbtUint8:
+ if (constant.u8Const == u8Const)
+ return true;
+
+ break;
+ case EbtInt64:
+ if (constant.i64Const == i64Const)
+ return true;
+
+ break;
+ case EbtUint64:
+ if (constant.u64Const == u64Const)
+ return true;
+
+ break;
+#endif
+ default:
+ assert(false && "Default missing");
+ }
+
+ return false;
+ }
+
+ bool operator!=(const signed char i) const
+ {
+ return !operator==(i);
+ }
+
+ bool operator!=(const unsigned char u) const
+ {
+ return !operator==(u);
+ }
+
+ bool operator!=(const signed short i) const
+ {
+ return !operator==(i);
+ }
+
+ bool operator!=(const unsigned short u) const
+ {
+ return !operator==(u);
+ }
+
+ bool operator!=(const int i) const
+ {
+ return !operator==(i);
+ }
+
+ bool operator!=(const unsigned int u) const
+ {
+ return !operator==(u);
+ }
+
+ bool operator!=(const long long i) const
+ {
+ return !operator==(i);
+ }
+
+ bool operator!=(const unsigned long long u) const
+ {
+ return !operator==(u);
+ }
+
+ bool operator!=(const float f) const
+ {
+ return !operator==(f);
+ }
+
+ bool operator!=(const bool b) const
+ {
+ return !operator==(b);
+ }
+
+ bool operator!=(const TConstUnion& constant) const
+ {
+ return !operator==(constant);
+ }
+
+ bool operator>(const TConstUnion& constant) const
+ {
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt:
+ if (iConst > constant.iConst)
+ return true;
+
+ return false;
+ case EbtUint:
+ if (uConst > constant.uConst)
+ return true;
+
+ return false;
+ case EbtDouble:
+ if (dConst > constant.dConst)
+ return true;
+
+ return false;
+#ifndef GLSLANG_WEB
+ case EbtInt8:
+ if (i8Const > constant.i8Const)
+ return true;
+
+ return false;
+ case EbtUint8:
+ if (u8Const > constant.u8Const)
+ return true;
+
+ return false;
+ case EbtInt16:
+ if (i16Const > constant.i16Const)
+ return true;
+
+ return false;
+ case EbtUint16:
+ if (u16Const > constant.u16Const)
+ return true;
+
+ return false;
+ case EbtInt64:
+ if (i64Const > constant.i64Const)
+ return true;
+
+ return false;
+ case EbtUint64:
+ if (u64Const > constant.u64Const)
+ return true;
+
+ return false;
+#endif
+ default:
+ assert(false && "Default missing");
+ return false;
+ }
+ }
+
+ bool operator<(const TConstUnion& constant) const
+ {
+ assert(type == constant.type);
+ switch (type) {
+#ifndef GLSLANG_WEB
+ case EbtInt8:
+ if (i8Const < constant.i8Const)
+ return true;
+
+ return false;
+ case EbtUint8:
+ if (u8Const < constant.u8Const)
+ return true;
+
+ return false;
+ case EbtInt16:
+ if (i16Const < constant.i16Const)
+ return true;
+
+ return false;
+ case EbtUint16:
+ if (u16Const < constant.u16Const)
+ return true;
+ return false;
+ case EbtInt64:
+ if (i64Const < constant.i64Const)
+ return true;
+
+ return false;
+ case EbtUint64:
+ if (u64Const < constant.u64Const)
+ return true;
+
+ return false;
+#endif
+ case EbtDouble:
+ if (dConst < constant.dConst)
+ return true;
+
+ return false;
+ case EbtInt:
+ if (iConst < constant.iConst)
+ return true;
+
+ return false;
+ case EbtUint:
+ if (uConst < constant.uConst)
+ return true;
+
+ return false;
+ default:
+ assert(false && "Default missing");
+ return false;
+ }
+ }
+
+ TConstUnion operator+(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
+ case EbtUint: returnValue.setUConst(uConst + constant.uConst); break;
+ case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break;
+ case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break;
+ case EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break;
+ case EbtUint8: returnValue.setU8Const(u8Const + constant.u8Const); break;
+ case EbtUint16: returnValue.setU16Const(u16Const + constant.u16Const); break;
+ case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator-(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
+ case EbtUint: returnValue.setUConst(uConst - constant.uConst); break;
+ case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break;
+ case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break;
+ case EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break;
+ case EbtUint8: returnValue.setU8Const(u8Const - constant.u8Const); break;
+ case EbtUint16: returnValue.setU16Const(u16Const - constant.u16Const); break;
+ case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator*(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
+ case EbtUint: returnValue.setUConst(uConst * constant.uConst); break;
+ case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break;
+ case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break;
+ case EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break;
+ case EbtUint8: returnValue.setU8Const(u8Const * constant.u8Const); break;
+ case EbtUint16: returnValue.setU16Const(u16Const * constant.u16Const); break;
+ case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator%(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
+ case EbtUint: returnValue.setUConst(uConst % constant.uConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break;
+ case EbtInt16: returnValue.setI8Const(i8Const % constant.i16Const); break;
+ case EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break;
+ case EbtUint8: returnValue.setU8Const(u8Const % constant.u8Const); break;
+ case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break;
+ case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator>>(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ switch (type) {
+#ifndef GLSLANG_WEB
+ case EbtInt8:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setI8Const(i8Const >> constant.i8Const); break;
+ case EbtUint8: returnValue.setI8Const(i8Const >> constant.u8Const); break;
+ case EbtInt16: returnValue.setI8Const(i8Const >> constant.i16Const); break;
+ case EbtUint16: returnValue.setI8Const(i8Const >> constant.u16Const); break;
+ case EbtInt: returnValue.setI8Const(i8Const >> constant.iConst); break;
+ case EbtUint: returnValue.setI8Const(i8Const >> constant.uConst); break;
+ case EbtInt64: returnValue.setI8Const(i8Const >> constant.i64Const); break;
+ case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtUint8:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setU8Const(u8Const >> constant.i8Const); break;
+ case EbtUint8: returnValue.setU8Const(u8Const >> constant.u8Const); break;
+ case EbtInt16: returnValue.setU8Const(u8Const >> constant.i16Const); break;
+ case EbtUint16: returnValue.setU8Const(u8Const >> constant.u16Const); break;
+ case EbtInt: returnValue.setU8Const(u8Const >> constant.iConst); break;
+ case EbtUint: returnValue.setU8Const(u8Const >> constant.uConst); break;
+ case EbtInt64: returnValue.setU8Const(u8Const >> constant.i64Const); break;
+ case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtInt16:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setI16Const(i16Const >> constant.i8Const); break;
+ case EbtUint8: returnValue.setI16Const(i16Const >> constant.u8Const); break;
+ case EbtInt16: returnValue.setI16Const(i16Const >> constant.i16Const); break;
+ case EbtUint16: returnValue.setI16Const(i16Const >> constant.u16Const); break;
+ case EbtInt: returnValue.setI16Const(i16Const >> constant.iConst); break;
+ case EbtUint: returnValue.setI16Const(i16Const >> constant.uConst); break;
+ case EbtInt64: returnValue.setI16Const(i16Const >> constant.i64Const); break;
+ case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtUint16:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setU16Const(u16Const >> constant.i8Const); break;
+ case EbtUint8: returnValue.setU16Const(u16Const >> constant.u8Const); break;
+ case EbtInt16: returnValue.setU16Const(u16Const >> constant.i16Const); break;
+ case EbtUint16: returnValue.setU16Const(u16Const >> constant.u16Const); break;
+ case EbtInt: returnValue.setU16Const(u16Const >> constant.iConst); break;
+ case EbtUint: returnValue.setU16Const(u16Const >> constant.uConst); break;
+ case EbtInt64: returnValue.setU16Const(u16Const >> constant.i64Const); break;
+ case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+#endif
+ case EbtInt:
+ switch (constant.type) {
+ case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
+ case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setIConst(iConst >> constant.i8Const); break;
+ case EbtUint8: returnValue.setIConst(iConst >> constant.u8Const); break;
+ case EbtInt16: returnValue.setIConst(iConst >> constant.i16Const); break;
+ case EbtUint16: returnValue.setIConst(iConst >> constant.u16Const); break;
+ case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break;
+ case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtUint:
+ switch (constant.type) {
+ case EbtInt: returnValue.setUConst(uConst >> constant.iConst); break;
+ case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setUConst(uConst >> constant.i8Const); break;
+ case EbtUint8: returnValue.setUConst(uConst >> constant.u8Const); break;
+ case EbtInt16: returnValue.setUConst(uConst >> constant.i16Const); break;
+ case EbtUint16: returnValue.setUConst(uConst >> constant.u16Const); break;
+ case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break;
+ case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+ break;
+#ifndef GLSLANG_WEB
+ case EbtInt64:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setI64Const(i64Const >> constant.i8Const); break;
+ case EbtUint8: returnValue.setI64Const(i64Const >> constant.u8Const); break;
+ case EbtInt16: returnValue.setI64Const(i64Const >> constant.i16Const); break;
+ case EbtUint16: returnValue.setI64Const(i64Const >> constant.u16Const); break;
+ case EbtInt: returnValue.setI64Const(i64Const >> constant.iConst); break;
+ case EbtUint: returnValue.setI64Const(i64Const >> constant.uConst); break;
+ case EbtInt64: returnValue.setI64Const(i64Const >> constant.i64Const); break;
+ case EbtUint64: returnValue.setI64Const(i64Const >> constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtUint64:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setU64Const(u64Const >> constant.i8Const); break;
+ case EbtUint8: returnValue.setU64Const(u64Const >> constant.u8Const); break;
+ case EbtInt16: returnValue.setU64Const(u64Const >> constant.i16Const); break;
+ case EbtUint16: returnValue.setU64Const(u64Const >> constant.u16Const); break;
+ case EbtInt: returnValue.setU64Const(u64Const >> constant.iConst); break;
+ case EbtUint: returnValue.setU64Const(u64Const >> constant.uConst); break;
+ case EbtInt64: returnValue.setU64Const(u64Const >> constant.i64Const); break;
+ case EbtUint64: returnValue.setU64Const(u64Const >> constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+#endif
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator<<(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ switch (type) {
+#ifndef GLSLANG_WEB
+ case EbtInt8:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setI8Const(i8Const << constant.i8Const); break;
+ case EbtUint8: returnValue.setI8Const(i8Const << constant.u8Const); break;
+ case EbtInt16: returnValue.setI8Const(i8Const << constant.i16Const); break;
+ case EbtUint16: returnValue.setI8Const(i8Const << constant.u16Const); break;
+ case EbtInt: returnValue.setI8Const(i8Const << constant.iConst); break;
+ case EbtUint: returnValue.setI8Const(i8Const << constant.uConst); break;
+ case EbtInt64: returnValue.setI8Const(i8Const << constant.i64Const); break;
+ case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtUint8:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setU8Const(u8Const << constant.i8Const); break;
+ case EbtUint8: returnValue.setU8Const(u8Const << constant.u8Const); break;
+ case EbtInt16: returnValue.setU8Const(u8Const << constant.i16Const); break;
+ case EbtUint16: returnValue.setU8Const(u8Const << constant.u16Const); break;
+ case EbtInt: returnValue.setU8Const(u8Const << constant.iConst); break;
+ case EbtUint: returnValue.setU8Const(u8Const << constant.uConst); break;
+ case EbtInt64: returnValue.setU8Const(u8Const << constant.i64Const); break;
+ case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtInt16:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setI16Const(i16Const << constant.i8Const); break;
+ case EbtUint8: returnValue.setI16Const(i16Const << constant.u8Const); break;
+ case EbtInt16: returnValue.setI16Const(i16Const << constant.i16Const); break;
+ case EbtUint16: returnValue.setI16Const(i16Const << constant.u16Const); break;
+ case EbtInt: returnValue.setI16Const(i16Const << constant.iConst); break;
+ case EbtUint: returnValue.setI16Const(i16Const << constant.uConst); break;
+ case EbtInt64: returnValue.setI16Const(i16Const << constant.i64Const); break;
+ case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtUint16:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setU16Const(u16Const << constant.i8Const); break;
+ case EbtUint8: returnValue.setU16Const(u16Const << constant.u8Const); break;
+ case EbtInt16: returnValue.setU16Const(u16Const << constant.i16Const); break;
+ case EbtUint16: returnValue.setU16Const(u16Const << constant.u16Const); break;
+ case EbtInt: returnValue.setU16Const(u16Const << constant.iConst); break;
+ case EbtUint: returnValue.setU16Const(u16Const << constant.uConst); break;
+ case EbtInt64: returnValue.setU16Const(u16Const << constant.i64Const); break;
+ case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtInt64:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setI64Const(i64Const << constant.i8Const); break;
+ case EbtUint8: returnValue.setI64Const(i64Const << constant.u8Const); break;
+ case EbtInt16: returnValue.setI64Const(i64Const << constant.i16Const); break;
+ case EbtUint16: returnValue.setI64Const(i64Const << constant.u16Const); break;
+ case EbtInt: returnValue.setI64Const(i64Const << constant.iConst); break;
+ case EbtUint: returnValue.setI64Const(i64Const << constant.uConst); break;
+ case EbtInt64: returnValue.setI64Const(i64Const << constant.i64Const); break;
+ case EbtUint64: returnValue.setI64Const(i64Const << constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtUint64:
+ switch (constant.type) {
+ case EbtInt8: returnValue.setU64Const(u64Const << constant.i8Const); break;
+ case EbtUint8: returnValue.setU64Const(u64Const << constant.u8Const); break;
+ case EbtInt16: returnValue.setU64Const(u64Const << constant.i16Const); break;
+ case EbtUint16: returnValue.setU64Const(u64Const << constant.u16Const); break;
+ case EbtInt: returnValue.setU64Const(u64Const << constant.iConst); break;
+ case EbtUint: returnValue.setU64Const(u64Const << constant.uConst); break;
+ case EbtInt64: returnValue.setU64Const(u64Const << constant.i64Const); break;
+ case EbtUint64: returnValue.setU64Const(u64Const << constant.u64Const); break;
+ default: assert(false && "Default missing");
+ }
+ break;
+#endif
+ case EbtInt:
+ switch (constant.type) {
+ case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
+ case EbtUint: returnValue.setIConst(iConst << constant.uConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setIConst(iConst << constant.i8Const); break;
+ case EbtUint8: returnValue.setIConst(iConst << constant.u8Const); break;
+ case EbtInt16: returnValue.setIConst(iConst << constant.i16Const); break;
+ case EbtUint16: returnValue.setIConst(iConst << constant.u16Const); break;
+ case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break;
+ case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EbtUint:
+ switch (constant.type) {
+ case EbtInt: returnValue.setUConst(uConst << constant.iConst); break;
+ case EbtUint: returnValue.setUConst(uConst << constant.uConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setUConst(uConst << constant.i8Const); break;
+ case EbtUint8: returnValue.setUConst(uConst << constant.u8Const); break;
+ case EbtInt16: returnValue.setUConst(uConst << constant.i16Const); break;
+ case EbtUint16: returnValue.setUConst(uConst << constant.u16Const); break;
+ case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break;
+ case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+ break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator&(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
+ case EbtUint: returnValue.setUConst(uConst & constant.uConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setI8Const(i8Const & constant.i8Const); break;
+ case EbtUint8: returnValue.setU8Const(u8Const & constant.u8Const); break;
+ case EbtInt16: returnValue.setI16Const(i16Const & constant.i16Const); break;
+ case EbtUint16: returnValue.setU16Const(u16Const & constant.u16Const); break;
+ case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break;
+ case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator|(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst | constant.iConst); break;
+ case EbtUint: returnValue.setUConst(uConst | constant.uConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setI8Const(i8Const | constant.i8Const); break;
+ case EbtUint8: returnValue.setU8Const(u8Const | constant.u8Const); break;
+ case EbtInt16: returnValue.setI16Const(i16Const | constant.i16Const); break;
+ case EbtUint16: returnValue.setU16Const(u16Const | constant.u16Const); break;
+ case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break;
+ case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator^(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break;
+ case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setI8Const(i8Const ^ constant.i8Const); break;
+ case EbtUint8: returnValue.setU8Const(u8Const ^ constant.u8Const); break;
+ case EbtInt16: returnValue.setI16Const(i16Const ^ constant.i16Const); break;
+ case EbtUint16: returnValue.setU16Const(u16Const ^ constant.u16Const); break;
+ case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break;
+ case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator~() const
+ {
+ TConstUnion returnValue;
+ switch (type) {
+ case EbtInt: returnValue.setIConst(~iConst); break;
+ case EbtUint: returnValue.setUConst(~uConst); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: returnValue.setI8Const(~i8Const); break;
+ case EbtUint8: returnValue.setU8Const(~u8Const); break;
+ case EbtInt16: returnValue.setI16Const(~i16Const); break;
+ case EbtUint16: returnValue.setU16Const(~u16Const); break;
+ case EbtInt64: returnValue.setI64Const(~i64Const); break;
+ case EbtUint64: returnValue.setU64Const(~u64Const); break;
+#endif
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator&&(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TConstUnion operator||(const TConstUnion& constant) const
+ {
+ TConstUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TBasicType getType() const { return type; }
+
+private:
+ union {
+ signed char i8Const; // used for i8vec, scalar int8s
+ unsigned char u8Const; // used for u8vec, scalar uint8s
+ signed short i16Const; // used for i16vec, scalar int16s
+ unsigned short u16Const; // used for u16vec, scalar uint16s
+ int iConst; // used for ivec, scalar ints
+ unsigned int uConst; // used for uvec, scalar uints
+ long long i64Const; // used for i64vec, scalar int64s
+ unsigned long long u64Const; // used for u64vec, scalar uint64s
+ bool bConst; // used for bvec, scalar bools
+ double dConst; // used for vec, dvec, mat, dmat, scalar floats and doubles
+ const TString* sConst; // string constant
+ };
+
+ TBasicType type;
+};
+
+// Encapsulate having a pointer to an array of TConstUnion,
+// which only needs to be allocated if its size is going to be
+// bigger than 0.
+//
+// One convenience is being able to use [] to go inside the array, instead
+// of C++ assuming it as an array of pointers to vectors.
+//
+// General usage is that the size is known up front, and it is
+// created once with the proper size.
+//
+class TConstUnionArray {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+ TConstUnionArray() : unionArray(nullptr) { }
+ virtual ~TConstUnionArray() { }
+
+ explicit TConstUnionArray(int size)
+ {
+ if (size == 0)
+ unionArray = nullptr;
+ else
+ unionArray = new TConstUnionVector(size);
+ }
+ TConstUnionArray(const TConstUnionArray& a) : unionArray(a.unionArray) { }
+ TConstUnionArray(const TConstUnionArray& a, int start, int size)
+ {
+ unionArray = new TConstUnionVector(size);
+ for (int i = 0; i < size; ++i)
+ (*unionArray)[i] = a[start + i];
+ }
+
+ // Use this constructor for a smear operation
+ TConstUnionArray(int size, const TConstUnion& val)
+ {
+ unionArray = new TConstUnionVector(size, val);
+ }
+
+ int size() const { return unionArray ? (int)unionArray->size() : 0; }
+ TConstUnion& operator[](size_t index) { return (*unionArray)[index]; }
+ const TConstUnion& operator[](size_t index) const { return (*unionArray)[index]; }
+ bool operator==(const TConstUnionArray& rhs) const
+ {
+ // this includes the case that both are unallocated
+ if (unionArray == rhs.unionArray)
+ return true;
+
+ if (! unionArray || ! rhs.unionArray)
+ return false;
+
+ return *unionArray == *rhs.unionArray;
+ }
+ bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); }
+
+ double dot(const TConstUnionArray& rhs)
+ {
+ assert(rhs.unionArray->size() == unionArray->size());
+ double sum = 0.0;
+
+ for (size_t comp = 0; comp < unionArray->size(); ++comp)
+ sum += (*this)[comp].getDConst() * rhs[comp].getDConst();
+
+ return sum;
+ }
+
+ bool empty() const { return unionArray == nullptr; }
+
+protected:
+ typedef TVector<TConstUnion> TConstUnionVector;
+ TConstUnionVector* unionArray;
+};
+
+} // end namespace glslang
+
+#endif // _CONSTANT_UNION_INCLUDED_
diff --git a/thirdparty/glslang/glslang/Include/InfoSink.h b/thirdparty/glslang/glslang/Include/InfoSink.h
new file mode 100644
index 0000000000..dceb603cff
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/InfoSink.h
@@ -0,0 +1,144 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _INFOSINK_INCLUDED_
+#define _INFOSINK_INCLUDED_
+
+#include "../Include/Common.h"
+#include <cmath>
+
+namespace glslang {
+
+//
+// TPrefixType is used to centralize how info log messages start.
+// See below.
+//
+enum TPrefixType {
+ EPrefixNone,
+ EPrefixWarning,
+ EPrefixError,
+ EPrefixInternalError,
+ EPrefixUnimplemented,
+ EPrefixNote
+};
+
+enum TOutputStream {
+ ENull = 0,
+ EDebugger = 0x01,
+ EStdOut = 0x02,
+ EString = 0x04,
+};
+//
+// Encapsulate info logs for all objects that have them.
+//
+// The methods are a general set of tools for getting a variety of
+// messages and types inserted into the log.
+//
+class TInfoSinkBase {
+public:
+ TInfoSinkBase() : outputStream(4) {}
+ void erase() { sink.erase(); }
+ TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; }
+ TInfoSinkBase& operator<<(char c) { append(1, c); return *this; }
+ TInfoSinkBase& operator<<(const char* s) { append(s); return *this; }
+ TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; }
+ TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; }
+ TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size];
+ snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n);
+ append(buf);
+ return *this; }
+ TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; }
+ TInfoSinkBase& operator+(const TString& t) { append(t); return *this; }
+ TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; }
+ TInfoSinkBase& operator+(const char* s) { append(s); return *this; }
+ const char* c_str() const { return sink.c_str(); }
+ void prefix(TPrefixType message) {
+ switch(message) {
+ case EPrefixNone: break;
+ case EPrefixWarning: append("WARNING: "); break;
+ case EPrefixError: append("ERROR: "); break;
+ case EPrefixInternalError: append("INTERNAL ERROR: "); break;
+ case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break;
+ case EPrefixNote: append("NOTE: "); break;
+ default: append("UNKNOWN ERROR: "); break;
+ }
+ }
+ void location(const TSourceLoc& loc) {
+ const int maxSize = 24;
+ char locText[maxSize];
+ snprintf(locText, maxSize, ":%d", loc.line);
+ append(loc.getStringNameOrNum(false).c_str());
+ append(locText);
+ append(": ");
+ }
+ void message(TPrefixType message, const char* s) {
+ prefix(message);
+ append(s);
+ append("\n");
+ }
+ void message(TPrefixType message, const char* s, const TSourceLoc& loc) {
+ prefix(message);
+ location(loc);
+ append(s);
+ append("\n");
+ }
+
+ void setOutputStream(int output = 4)
+ {
+ outputStream = output;
+ }
+
+protected:
+ void append(const char* s);
+
+ void append(int count, char c);
+ void append(const TPersistString& t);
+ void append(const TString& t);
+
+ void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2)
+ sink.reserve(sink.capacity() + sink.capacity() / 2); }
+ void appendToStream(const char* s);
+ TPersistString sink;
+ int outputStream;
+};
+
+} // end namespace glslang
+
+class TInfoSink {
+public:
+ glslang::TInfoSinkBase info;
+ glslang::TInfoSinkBase debug;
+};
+
+#endif // _INFOSINK_INCLUDED_
diff --git a/thirdparty/glslang/glslang/Include/InitializeGlobals.h b/thirdparty/glslang/glslang/Include/InitializeGlobals.h
new file mode 100644
index 0000000000..95d0a40e99
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/InitializeGlobals.h
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef __INITIALIZE_GLOBALS_INCLUDED_
+#define __INITIALIZE_GLOBALS_INCLUDED_
+
+namespace glslang {
+
+bool InitializePoolIndex();
+
+} // end namespace glslang
+
+#endif // __INITIALIZE_GLOBALS_INCLUDED_
diff --git a/thirdparty/glslang/glslang/Include/PoolAlloc.h b/thirdparty/glslang/glslang/Include/PoolAlloc.h
new file mode 100644
index 0000000000..b8eccb8832
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/PoolAlloc.h
@@ -0,0 +1,316 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2013 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _POOLALLOC_INCLUDED_
+#define _POOLALLOC_INCLUDED_
+
+#ifdef _DEBUG
+# define GUARD_BLOCKS // define to enable guard block sanity checking
+#endif
+
+//
+// This header defines an allocator that can be used to efficiently
+// allocate a large number of small requests for heap memory, with the
+// intention that they are not individually deallocated, but rather
+// collectively deallocated at one time.
+//
+// This simultaneously
+//
+// * Makes each individual allocation much more efficient; the
+// typical allocation is trivial.
+// * Completely avoids the cost of doing individual deallocation.
+// * Saves the trouble of tracking down and plugging a large class of leaks.
+//
+// Individual classes can use this allocator by supplying their own
+// new and delete methods.
+//
+// STL containers can use this allocator by using the pool_allocator
+// class as the allocator (second) template argument.
+//
+
+#include <cstddef>
+#include <cstring>
+#include <vector>
+
+namespace glslang {
+
+// If we are using guard blocks, we must track each individual
+// allocation. If we aren't using guard blocks, these
+// never get instantiated, so won't have any impact.
+//
+
+class TAllocation {
+public:
+ TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) :
+ size(size), mem(mem), prevAlloc(prev) {
+ // Allocations are bracketed:
+ // [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
+ // This would be cleaner with if (guardBlockSize)..., but that
+ // makes the compiler print warnings about 0 length memsets,
+ // even with the if() protecting them.
+# ifdef GUARD_BLOCKS
+ memset(preGuard(), guardBlockBeginVal, guardBlockSize);
+ memset(data(), userDataFill, size);
+ memset(postGuard(), guardBlockEndVal, guardBlockSize);
+# endif
+ }
+
+ void check() const {
+ checkGuardBlock(preGuard(), guardBlockBeginVal, "before");
+ checkGuardBlock(postGuard(), guardBlockEndVal, "after");
+ }
+
+ void checkAllocList() const;
+
+ // Return total size needed to accommodate user buffer of 'size',
+ // plus our tracking data.
+ inline static size_t allocationSize(size_t size) {
+ return size + 2 * guardBlockSize + headerSize();
+ }
+
+ // Offset from surrounding buffer to get to user data buffer.
+ inline static unsigned char* offsetAllocation(unsigned char* m) {
+ return m + guardBlockSize + headerSize();
+ }
+
+private:
+ void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const;
+
+ // Find offsets to pre and post guard blocks, and user data buffer
+ unsigned char* preGuard() const { return mem + headerSize(); }
+ unsigned char* data() const { return preGuard() + guardBlockSize; }
+ unsigned char* postGuard() const { return data() + size; }
+
+ size_t size; // size of the user data area
+ unsigned char* mem; // beginning of our allocation (pts to header)
+ TAllocation* prevAlloc; // prior allocation in the chain
+
+ const static unsigned char guardBlockBeginVal;
+ const static unsigned char guardBlockEndVal;
+ const static unsigned char userDataFill;
+
+ const static size_t guardBlockSize;
+# ifdef GUARD_BLOCKS
+ inline static size_t headerSize() { return sizeof(TAllocation); }
+# else
+ inline static size_t headerSize() { return 0; }
+# endif
+};
+
+//
+// There are several stacks. One is to track the pushing and popping
+// of the user, and not yet implemented. The others are simply a
+// repositories of free pages or used pages.
+//
+// Page stacks are linked together with a simple header at the beginning
+// of each allocation obtained from the underlying OS. Multi-page allocations
+// are returned to the OS. Individual page allocations are kept for future
+// re-use.
+//
+// The "page size" used is not, nor must it match, the underlying OS
+// page size. But, having it be about that size or equal to a set of
+// pages is likely most optimal.
+//
+class TPoolAllocator {
+public:
+ TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16);
+
+ //
+ // Don't call the destructor just to free up the memory, call pop()
+ //
+ ~TPoolAllocator();
+
+ //
+ // Call push() to establish a new place to pop memory too. Does not
+ // have to be called to get things started.
+ //
+ void push();
+
+ //
+ // Call pop() to free all memory allocated since the last call to push(),
+ // or if no last call to push, frees all memory since first allocation.
+ //
+ void pop();
+
+ //
+ // Call popAll() to free all memory allocated.
+ //
+ void popAll();
+
+ //
+ // Call allocate() to actually acquire memory. Returns 0 if no memory
+ // available, otherwise a properly aligned pointer to 'numBytes' of memory.
+ //
+ void* allocate(size_t numBytes);
+
+ //
+ // There is no deallocate. The point of this class is that
+ // deallocation can be skipped by the user of it, as the model
+ // of use is to simultaneously deallocate everything at once
+ // by calling pop(), and to not have to solve memory leak problems.
+ //
+
+protected:
+ friend struct tHeader;
+
+ struct tHeader {
+ tHeader(tHeader* nextPage, size_t pageCount) :
+#ifdef GUARD_BLOCKS
+ lastAllocation(0),
+#endif
+ nextPage(nextPage), pageCount(pageCount) { }
+
+ ~tHeader() {
+#ifdef GUARD_BLOCKS
+ if (lastAllocation)
+ lastAllocation->checkAllocList();
+#endif
+ }
+
+#ifdef GUARD_BLOCKS
+ TAllocation* lastAllocation;
+#endif
+ tHeader* nextPage;
+ size_t pageCount;
+ };
+
+ struct tAllocState {
+ size_t offset;
+ tHeader* page;
+ };
+ typedef std::vector<tAllocState> tAllocStack;
+
+ // Track allocations if and only if we're using guard blocks
+#ifndef GUARD_BLOCKS
+ void* initializeAllocation(tHeader*, unsigned char* memory, size_t) {
+#else
+ void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) {
+ new(memory) TAllocation(numBytes, memory, block->lastAllocation);
+ block->lastAllocation = reinterpret_cast<TAllocation*>(memory);
+#endif
+
+ // This is optimized entirely away if GUARD_BLOCKS is not defined.
+ return TAllocation::offsetAllocation(memory);
+ }
+
+ size_t pageSize; // granularity of allocation from the OS
+ size_t alignment; // all returned allocations will be aligned at
+ // this granularity, which will be a power of 2
+ size_t alignmentMask;
+ size_t headerSkip; // amount of memory to skip to make room for the
+ // header (basically, size of header, rounded
+ // up to make it aligned
+ size_t currentPageOffset; // next offset in top of inUseList to allocate from
+ tHeader* freeList; // list of popped memory
+ tHeader* inUseList; // list of all memory currently being used
+ tAllocStack stack; // stack of where to allocate from, to partition pool
+
+ int numCalls; // just an interesting statistic
+ size_t totalBytes; // just an interesting statistic
+private:
+ TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator
+ TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor
+};
+
+//
+// There could potentially be many pools with pops happening at
+// different times. But a simple use is to have a global pop
+// with everyone using the same global allocator.
+//
+extern TPoolAllocator& GetThreadPoolAllocator();
+void SetThreadPoolAllocator(TPoolAllocator* poolAllocator);
+
+//
+// This STL compatible allocator is intended to be used as the allocator
+// parameter to templatized STL containers, like vector and map.
+//
+// It will use the pools for allocation, and not
+// do any deallocation, but will still do destruction.
+//
+template<class T>
+class pool_allocator {
+public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+ template<class Other>
+ struct rebind {
+ typedef pool_allocator<Other> other;
+ };
+ pointer address(reference x) const { return &x; }
+ const_pointer address(const_reference x) const { return &x; }
+
+ pool_allocator() : allocator(GetThreadPoolAllocator()) { }
+ pool_allocator(TPoolAllocator& a) : allocator(a) { }
+ pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
+
+ template<class Other>
+ pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
+
+ pointer allocate(size_type n) {
+ return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
+ pointer allocate(size_type n, const void*) {
+ return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
+
+ void deallocate(void*, size_type) { }
+ void deallocate(pointer, size_type) { }
+
+ pointer _Charalloc(size_t n) {
+ return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
+
+ void construct(pointer p, const T& val) { new ((void *)p) T(val); }
+ void destroy(pointer p) { p->T::~T(); }
+
+ bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); }
+ bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); }
+
+ size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
+ size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
+
+ TPoolAllocator& getAllocator() const { return allocator; }
+
+protected:
+ pool_allocator& operator=(const pool_allocator&) { return *this; }
+ TPoolAllocator& allocator;
+};
+
+} // end namespace glslang
+
+#endif // _POOLALLOC_INCLUDED_
diff --git a/thirdparty/glslang/glslang/Include/ResourceLimits.h b/thirdparty/glslang/glslang/Include/ResourceLimits.h
new file mode 100644
index 0000000000..106b21d9ca
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/ResourceLimits.h
@@ -0,0 +1,149 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _RESOURCE_LIMITS_INCLUDED_
+#define _RESOURCE_LIMITS_INCLUDED_
+
+struct TLimits {
+ bool nonInductiveForLoops;
+ bool whileLoops;
+ bool doWhileLoops;
+ bool generalUniformIndexing;
+ bool generalAttributeMatrixVectorIndexing;
+ bool generalVaryingIndexing;
+ bool generalSamplerIndexing;
+ bool generalVariableIndexing;
+ bool generalConstantMatrixVectorIndexing;
+};
+
+struct TBuiltInResource {
+ int maxLights;
+ int maxClipPlanes;
+ int maxTextureUnits;
+ int maxTextureCoords;
+ int maxVertexAttribs;
+ int maxVertexUniformComponents;
+ int maxVaryingFloats;
+ int maxVertexTextureImageUnits;
+ int maxCombinedTextureImageUnits;
+ int maxTextureImageUnits;
+ int maxFragmentUniformComponents;
+ int maxDrawBuffers;
+ int maxVertexUniformVectors;
+ int maxVaryingVectors;
+ int maxFragmentUniformVectors;
+ int maxVertexOutputVectors;
+ int maxFragmentInputVectors;
+ int minProgramTexelOffset;
+ int maxProgramTexelOffset;
+ int maxClipDistances;
+ int maxComputeWorkGroupCountX;
+ int maxComputeWorkGroupCountY;
+ int maxComputeWorkGroupCountZ;
+ int maxComputeWorkGroupSizeX;
+ int maxComputeWorkGroupSizeY;
+ int maxComputeWorkGroupSizeZ;
+ int maxComputeUniformComponents;
+ int maxComputeTextureImageUnits;
+ int maxComputeImageUniforms;
+ int maxComputeAtomicCounters;
+ int maxComputeAtomicCounterBuffers;
+ int maxVaryingComponents;
+ int maxVertexOutputComponents;
+ int maxGeometryInputComponents;
+ int maxGeometryOutputComponents;
+ int maxFragmentInputComponents;
+ int maxImageUnits;
+ int maxCombinedImageUnitsAndFragmentOutputs;
+ int maxCombinedShaderOutputResources;
+ int maxImageSamples;
+ int maxVertexImageUniforms;
+ int maxTessControlImageUniforms;
+ int maxTessEvaluationImageUniforms;
+ int maxGeometryImageUniforms;
+ int maxFragmentImageUniforms;
+ int maxCombinedImageUniforms;
+ int maxGeometryTextureImageUnits;
+ int maxGeometryOutputVertices;
+ int maxGeometryTotalOutputComponents;
+ int maxGeometryUniformComponents;
+ int maxGeometryVaryingComponents;
+ int maxTessControlInputComponents;
+ int maxTessControlOutputComponents;
+ int maxTessControlTextureImageUnits;
+ int maxTessControlUniformComponents;
+ int maxTessControlTotalOutputComponents;
+ int maxTessEvaluationInputComponents;
+ int maxTessEvaluationOutputComponents;
+ int maxTessEvaluationTextureImageUnits;
+ int maxTessEvaluationUniformComponents;
+ int maxTessPatchComponents;
+ int maxPatchVertices;
+ int maxTessGenLevel;
+ int maxViewports;
+ int maxVertexAtomicCounters;
+ int maxTessControlAtomicCounters;
+ int maxTessEvaluationAtomicCounters;
+ int maxGeometryAtomicCounters;
+ int maxFragmentAtomicCounters;
+ int maxCombinedAtomicCounters;
+ int maxAtomicCounterBindings;
+ int maxVertexAtomicCounterBuffers;
+ int maxTessControlAtomicCounterBuffers;
+ int maxTessEvaluationAtomicCounterBuffers;
+ int maxGeometryAtomicCounterBuffers;
+ int maxFragmentAtomicCounterBuffers;
+ int maxCombinedAtomicCounterBuffers;
+ int maxAtomicCounterBufferSize;
+ int maxTransformFeedbackBuffers;
+ int maxTransformFeedbackInterleavedComponents;
+ int maxCullDistances;
+ int maxCombinedClipAndCullDistances;
+ int maxSamples;
+ int maxMeshOutputVerticesNV;
+ int maxMeshOutputPrimitivesNV;
+ int maxMeshWorkGroupSizeX_NV;
+ int maxMeshWorkGroupSizeY_NV;
+ int maxMeshWorkGroupSizeZ_NV;
+ int maxTaskWorkGroupSizeX_NV;
+ int maxTaskWorkGroupSizeY_NV;
+ int maxTaskWorkGroupSizeZ_NV;
+ int maxMeshViewCountNV;
+
+ TLimits limits;
+};
+
+#endif // _RESOURCE_LIMITS_INCLUDED_
diff --git a/thirdparty/glslang/glslang/Include/ShHandle.h b/thirdparty/glslang/glslang/Include/ShHandle.h
new file mode 100644
index 0000000000..df07bd8eda
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/ShHandle.h
@@ -0,0 +1,176 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _SHHANDLE_INCLUDED_
+#define _SHHANDLE_INCLUDED_
+
+//
+// Machine independent part of the compiler private objects
+// sent as ShHandle to the driver.
+//
+// This should not be included by driver code.
+//
+
+#define SH_EXPORTING
+#include "../Public/ShaderLang.h"
+#include "../MachineIndependent/Versions.h"
+#include "InfoSink.h"
+
+class TCompiler;
+class TLinker;
+class TUniformMap;
+
+//
+// The base class used to back handles returned to the driver.
+//
+class TShHandleBase {
+public:
+ TShHandleBase() { pool = new glslang::TPoolAllocator; }
+ virtual ~TShHandleBase() { delete pool; }
+ virtual TCompiler* getAsCompiler() { return 0; }
+ virtual TLinker* getAsLinker() { return 0; }
+ virtual TUniformMap* getAsUniformMap() { return 0; }
+ virtual glslang::TPoolAllocator* getPool() const { return pool; }
+private:
+ glslang::TPoolAllocator* pool;
+};
+
+//
+// The base class for the machine dependent linker to derive from
+// for managing where uniforms live.
+//
+class TUniformMap : public TShHandleBase {
+public:
+ TUniformMap() { }
+ virtual ~TUniformMap() { }
+ virtual TUniformMap* getAsUniformMap() { return this; }
+ virtual int getLocation(const char* name) = 0;
+ virtual TInfoSink& getInfoSink() { return infoSink; }
+ TInfoSink infoSink;
+};
+
+class TIntermNode;
+
+//
+// The base class for the machine dependent compiler to derive from
+// for managing object code from the compile.
+//
+class TCompiler : public TShHandleBase {
+public:
+ TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { }
+ virtual ~TCompiler() { }
+ EShLanguage getLanguage() { return language; }
+ virtual TInfoSink& getInfoSink() { return infoSink; }
+
+ virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile) = 0;
+
+ virtual TCompiler* getAsCompiler() { return this; }
+ virtual bool linkable() { return haveValidObjectCode; }
+
+ TInfoSink& infoSink;
+protected:
+ TCompiler& operator=(TCompiler&);
+
+ EShLanguage language;
+ bool haveValidObjectCode;
+};
+
+//
+// Link operations are based on a list of compile results...
+//
+typedef glslang::TVector<TCompiler*> TCompilerList;
+typedef glslang::TVector<TShHandleBase*> THandleList;
+
+//
+// The base class for the machine dependent linker to derive from
+// to manage the resulting executable.
+//
+
+class TLinker : public TShHandleBase {
+public:
+ TLinker(EShExecutable e, TInfoSink& iSink) :
+ infoSink(iSink),
+ executable(e),
+ haveReturnableObjectCode(false),
+ appAttributeBindings(0),
+ fixedAttributeBindings(0),
+ excludedAttributes(0),
+ excludedCount(0),
+ uniformBindings(0) { }
+ virtual TLinker* getAsLinker() { return this; }
+ virtual ~TLinker() { }
+ virtual bool link(TCompilerList&, TUniformMap*) = 0;
+ virtual bool link(THandleList&) { return false; }
+ virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; }
+ virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; }
+ virtual void getAttributeBindings(ShBindingTable const **t) const = 0;
+ virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; }
+ virtual ShBindingTable* getUniformBindings() const { return uniformBindings; }
+ virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here
+ virtual TInfoSink& getInfoSink() { return infoSink; }
+ TInfoSink& infoSink;
+protected:
+ TLinker& operator=(TLinker&);
+ EShExecutable executable;
+ bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver
+
+ const ShBindingTable* appAttributeBindings;
+ const ShBindingTable* fixedAttributeBindings;
+ const int* excludedAttributes;
+ int excludedCount;
+ ShBindingTable* uniformBindings; // created by the linker
+};
+
+//
+// This is the interface between the machine independent code
+// and the machine dependent code.
+//
+// The machine dependent code should derive from the classes
+// above. Then Construct*() and Delete*() will create and
+// destroy the machine dependent objects, which contain the
+// above machine independent information.
+//
+TCompiler* ConstructCompiler(EShLanguage, int);
+
+TShHandleBase* ConstructLinker(EShExecutable, int);
+TShHandleBase* ConstructBindings();
+void DeleteLinker(TShHandleBase*);
+void DeleteBindingList(TShHandleBase* bindingList);
+
+TUniformMap* ConstructUniformMap();
+void DeleteCompiler(TCompiler*);
+
+void DeleteUniformMap(TUniformMap*);
+
+#endif // _SHHANDLE_INCLUDED_
diff --git a/thirdparty/glslang/glslang/Include/Types.h b/thirdparty/glslang/glslang/Include/Types.h
new file mode 100644
index 0000000000..3572099e3d
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/Types.h
@@ -0,0 +1,2447 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2016 LunarG, Inc.
+// Copyright (C) 2015-2016 Google, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _TYPES_INCLUDED
+#define _TYPES_INCLUDED
+
+#include "../Include/Common.h"
+#include "../Include/BaseTypes.h"
+#include "../Public/ShaderLang.h"
+#include "arrays.h"
+
+#include <algorithm>
+
+namespace glslang {
+
+const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded
+
+const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed
+inline bool IsAnonymous(const TString& name)
+{
+ return name.compare(0, 5, AnonymousPrefix) == 0;
+}
+
+//
+// Details within a sampler type
+//
+enum TSamplerDim {
+ EsdNone,
+ Esd1D,
+ Esd2D,
+ Esd3D,
+ EsdCube,
+ EsdRect,
+ EsdBuffer,
+ EsdSubpass, // goes only with non-sampled image (image is true)
+ EsdNumDims
+};
+
+struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler
+ TBasicType type : 8; // type returned by sampler
+ TSamplerDim dim : 8;
+ bool arrayed : 1;
+ bool shadow : 1;
+ bool ms : 1;
+ bool image : 1; // image, combined should be false
+ bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler
+ bool sampler : 1; // true means a pure sampler, other fields should be clear()
+
+#ifdef GLSLANG_WEB
+ bool is1D() const { return false; }
+ bool isBuffer() const { return false; }
+ bool isRect() const { return false; }
+ bool isSubpass() const { return false; }
+ bool isCombined() const { return true; }
+ bool isImage() const { return false; }
+ bool isImageClass() const { return false; }
+ bool isMultiSample() const { return false; }
+ bool isExternal() const { return false; }
+ void setExternal(bool e) { }
+ bool isYuv() const { return false; }
+#else
+ unsigned int vectorSize : 3; // vector return type size.
+ // Some languages support structures as sample results. Storing the whole structure in the
+ // TSampler is too large, so there is an index to a separate table.
+ static const unsigned structReturnIndexBits = 4; // number of index bits to use.
+ static const unsigned structReturnSlots = (1<<structReturnIndexBits)-1; // number of valid values
+ static const unsigned noReturnStruct = structReturnSlots; // value if no return struct type.
+ // Index into a language specific table of texture return structures.
+ unsigned int structReturnIndex : structReturnIndexBits;
+
+ bool external : 1; // GL_OES_EGL_image_external
+ bool yuv : 1; // GL_EXT_YUV_target
+
+#ifdef ENABLE_HLSL
+ unsigned int getVectorSize() const { return vectorSize; }
+ void clearReturnStruct() { structReturnIndex = noReturnStruct; }
+ bool hasReturnStruct() const { return structReturnIndex != noReturnStruct; }
+ unsigned getStructReturnIndex() const { return structReturnIndex; }
+#endif
+
+ bool is1D() const { return dim == Esd1D; }
+ bool isBuffer() const { return dim == EsdBuffer; }
+ bool isRect() const { return dim == EsdRect; }
+ bool isSubpass() const { return dim == EsdSubpass; }
+ bool isCombined() const { return combined; }
+ bool isImage() const { return image && !isSubpass(); }
+ bool isImageClass() const { return image; }
+ bool isMultiSample() const { return ms; }
+ bool isExternal() const { return external; }
+ void setExternal(bool e) { external = e; }
+ bool isYuv() const { return yuv; }
+#endif
+ bool isTexture() const { return !sampler && !image; }
+ bool isPureSampler() const { return sampler; }
+
+ void setCombined(bool c) { combined = c; }
+ void setBasicType(TBasicType t) { type = t; }
+ TBasicType getBasicType() const { return type; }
+ bool isShadow() const { return shadow; }
+ bool isArrayed() const { return arrayed; }
+
+ void clear()
+ {
+ type = EbtVoid;
+ dim = EsdNone;
+ arrayed = false;
+ shadow = false;
+ ms = false;
+ image = false;
+ combined = false;
+ sampler = false;
+#ifndef GLSLANG_WEB
+ external = false;
+ yuv = false;
+#endif
+
+#ifdef ENABLE_HLSL
+ clearReturnStruct();
+ // by default, returns a single vec4;
+ vectorSize = 4;
+#endif
+ }
+
+ // make a combined sampler and texture
+ void set(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
+ {
+ clear();
+ type = t;
+ dim = d;
+ arrayed = a;
+ shadow = s;
+ ms = m;
+ combined = true;
+ }
+
+ // make an image
+ void setImage(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
+ {
+ clear();
+ type = t;
+ dim = d;
+ arrayed = a;
+ shadow = s;
+ ms = m;
+ image = true;
+ }
+
+ // make a texture with no sampler
+ void setTexture(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
+ {
+ clear();
+ type = t;
+ dim = d;
+ arrayed = a;
+ shadow = s;
+ ms = m;
+ }
+
+ // make a pure sampler, no texture, no image, nothing combined, the 'sampler' keyword
+ void setPureSampler(bool s)
+ {
+ clear();
+ sampler = true;
+ shadow = s;
+ }
+
+#ifndef GLSLANG_WEB
+ // make a subpass input attachment
+ void setSubpass(TBasicType t, bool m = false)
+ {
+ clear();
+ type = t;
+ image = true;
+ dim = EsdSubpass;
+ ms = m;
+ }
+#endif
+
+ bool operator==(const TSampler& right) const
+ {
+ return type == right.type &&
+ dim == right.dim &&
+ arrayed == right.arrayed &&
+ shadow == right.shadow &&
+ isMultiSample() == right.isMultiSample() &&
+ isImageClass() == right.isImageClass() &&
+ isCombined() == right.isCombined() &&
+ isPureSampler() == right.isPureSampler() &&
+ isExternal() == right.isExternal() &&
+ isYuv() == right.isYuv()
+#ifdef ENABLE_HLSL
+ && getVectorSize() == right.getVectorSize() &&
+ getStructReturnIndex() == right.getStructReturnIndex()
+#endif
+ ;
+ }
+
+ bool operator!=(const TSampler& right) const
+ {
+ return ! operator==(right);
+ }
+
+ TString getString() const
+ {
+ TString s;
+
+ if (isPureSampler()) {
+ s.append("sampler");
+ return s;
+ }
+
+ switch (type) {
+ case EbtInt: s.append("i"); break;
+ case EbtUint: s.append("u"); break;
+#ifndef GLSLANG_WEB
+ case EbtFloat16: s.append("f16"); break;
+ case EbtInt8: s.append("i8"); break;
+ case EbtUint16: s.append("u8"); break;
+ case EbtInt16: s.append("i16"); break;
+ case EbtUint8: s.append("u16"); break;
+ case EbtInt64: s.append("i64"); break;
+ case EbtUint64: s.append("u64"); break;
+#endif
+ default: break;
+ }
+ if (isImageClass()) {
+ if (isSubpass())
+ s.append("subpass");
+ else
+ s.append("image");
+ } else if (isCombined()) {
+ s.append("sampler");
+ } else {
+ s.append("texture");
+ }
+ if (isExternal()) {
+ s.append("ExternalOES");
+ return s;
+ }
+ if (isYuv()) {
+ return "__" + s + "External2DY2YEXT";
+ }
+ switch (dim) {
+ case Esd2D: s.append("2D"); break;
+ case Esd3D: s.append("3D"); break;
+ case EsdCube: s.append("Cube"); break;
+#ifndef GLSLANG_WEB
+ case Esd1D: s.append("1D"); break;
+ case EsdRect: s.append("2DRect"); break;
+ case EsdBuffer: s.append("Buffer"); break;
+ case EsdSubpass: s.append("Input"); break;
+#endif
+ default: break; // some compilers want this
+ }
+ if (isMultiSample())
+ s.append("MS");
+ if (arrayed)
+ s.append("Array");
+ if (shadow)
+ s.append("Shadow");
+
+ return s;
+ }
+};
+
+//
+// Need to have association of line numbers to types in a list for building structs.
+//
+class TType;
+struct TTypeLoc {
+ TType* type;
+ TSourceLoc loc;
+};
+typedef TVector<TTypeLoc> TTypeList;
+
+typedef TVector<TString*> TIdentifierList;
+
+//
+// Following are a series of helper enums for managing layouts and qualifiers,
+// used for TPublicType, TType, others.
+//
+
+enum TLayoutPacking {
+ ElpNone,
+ ElpShared, // default, but different than saying nothing
+ ElpStd140,
+ ElpStd430,
+ ElpPacked,
+ ElpScalar,
+ ElpCount // If expanding, see bitfield width below
+};
+
+enum TLayoutMatrix {
+ ElmNone,
+ ElmRowMajor,
+ ElmColumnMajor, // default, but different than saying nothing
+ ElmCount // If expanding, see bitfield width below
+};
+
+// Union of geometry shader and tessellation shader geometry types.
+// They don't go into TType, but rather have current state per shader or
+// active parser type (TPublicType).
+enum TLayoutGeometry {
+ ElgNone,
+ ElgPoints,
+ ElgLines,
+ ElgLinesAdjacency,
+ ElgLineStrip,
+ ElgTriangles,
+ ElgTrianglesAdjacency,
+ ElgTriangleStrip,
+ ElgQuads,
+ ElgIsolines,
+};
+
+enum TVertexSpacing {
+ EvsNone,
+ EvsEqual,
+ EvsFractionalEven,
+ EvsFractionalOdd
+};
+
+enum TVertexOrder {
+ EvoNone,
+ EvoCw,
+ EvoCcw
+};
+
+// Note: order matters, as type of format is done by comparison.
+enum TLayoutFormat {
+ ElfNone,
+
+ // Float image
+ ElfRgba32f,
+ ElfRgba16f,
+ ElfR32f,
+ ElfRgba8,
+ ElfRgba8Snorm,
+
+ ElfEsFloatGuard, // to help with comparisons
+
+ ElfRg32f,
+ ElfRg16f,
+ ElfR11fG11fB10f,
+ ElfR16f,
+ ElfRgba16,
+ ElfRgb10A2,
+ ElfRg16,
+ ElfRg8,
+ ElfR16,
+ ElfR8,
+ ElfRgba16Snorm,
+ ElfRg16Snorm,
+ ElfRg8Snorm,
+ ElfR16Snorm,
+ ElfR8Snorm,
+
+ ElfFloatGuard, // to help with comparisons
+
+ // Int image
+ ElfRgba32i,
+ ElfRgba16i,
+ ElfRgba8i,
+ ElfR32i,
+
+ ElfEsIntGuard, // to help with comparisons
+
+ ElfRg32i,
+ ElfRg16i,
+ ElfRg8i,
+ ElfR16i,
+ ElfR8i,
+
+ ElfIntGuard, // to help with comparisons
+
+ // Uint image
+ ElfRgba32ui,
+ ElfRgba16ui,
+ ElfRgba8ui,
+ ElfR32ui,
+
+ ElfEsUintGuard, // to help with comparisons
+
+ ElfRg32ui,
+ ElfRg16ui,
+ ElfRgb10a2ui,
+ ElfRg8ui,
+ ElfR16ui,
+ ElfR8ui,
+
+ ElfCount
+};
+
+enum TLayoutDepth {
+ EldNone,
+ EldAny,
+ EldGreater,
+ EldLess,
+ EldUnchanged,
+
+ EldCount
+};
+
+enum TBlendEquationShift {
+ // No 'EBlendNone':
+ // These are used as bit-shift amounts. A mask of such shifts will have type 'int',
+ // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set.
+ EBlendMultiply,
+ EBlendScreen,
+ EBlendOverlay,
+ EBlendDarken,
+ EBlendLighten,
+ EBlendColordodge,
+ EBlendColorburn,
+ EBlendHardlight,
+ EBlendSoftlight,
+ EBlendDifference,
+ EBlendExclusion,
+ EBlendHslHue,
+ EBlendHslSaturation,
+ EBlendHslColor,
+ EBlendHslLuminosity,
+ EBlendAllEquations,
+
+ EBlendCount
+};
+
+enum TInterlockOrdering {
+ EioNone,
+ EioPixelInterlockOrdered,
+ EioPixelInterlockUnordered,
+ EioSampleInterlockOrdered,
+ EioSampleInterlockUnordered,
+ EioShadingRateInterlockOrdered,
+ EioShadingRateInterlockUnordered,
+
+ EioCount,
+};
+
+class TQualifier {
+public:
+ static const int layoutNotSet = -1;
+
+ void clear()
+ {
+ precision = EpqNone;
+ invariant = false;
+ makeTemporary();
+ declaredBuiltIn = EbvNone;
+#ifndef GLSLANG_WEB
+ noContraction = false;
+#endif
+ }
+
+ // drop qualifiers that don't belong in a temporary variable
+ void makeTemporary()
+ {
+ semanticName = nullptr;
+ storage = EvqTemporary;
+ builtIn = EbvNone;
+ clearInterstage();
+ clearMemory();
+ specConstant = false;
+ nonUniform = false;
+ clearLayout();
+ }
+
+ void clearInterstage()
+ {
+ clearInterpolation();
+#ifndef GLSLANG_WEB
+ patch = false;
+ sample = false;
+#endif
+ }
+
+ void clearInterpolation()
+ {
+ centroid = false;
+ smooth = false;
+ flat = false;
+#ifndef GLSLANG_WEB
+ nopersp = false;
+ explicitInterp = false;
+ pervertexNV = false;
+ perPrimitiveNV = false;
+ perViewNV = false;
+ perTaskNV = false;
+#endif
+ }
+
+ void clearMemory()
+ {
+#ifndef GLSLANG_WEB
+ coherent = false;
+ devicecoherent = false;
+ queuefamilycoherent = false;
+ workgroupcoherent = false;
+ subgroupcoherent = false;
+ nonprivate = false;
+ volatil = false;
+ restrict = false;
+ readonly = false;
+ writeonly = false;
+#endif
+ }
+
+ const char* semanticName;
+ TStorageQualifier storage : 6;
+ TBuiltInVariable builtIn : 9;
+ TBuiltInVariable declaredBuiltIn : 9;
+ static_assert(EbvLast < 256, "need to increase size of TBuiltInVariable bitfields!");
+ TPrecisionQualifier precision : 3;
+ bool invariant : 1; // require canonical treatment for cross-shader invariance
+ bool centroid : 1;
+ bool smooth : 1;
+ bool flat : 1;
+ // having a constant_id is not sufficient: expressions have no id, but are still specConstant
+ bool specConstant : 1;
+ bool nonUniform : 1;
+
+#ifdef GLSLANG_WEB
+ bool isWriteOnly() const { return false; }
+ bool isReadOnly() const { return false; }
+ bool isRestrict() const { return false; }
+ bool isCoherent() const { return false; }
+ bool isVolatile() const { return false; }
+ bool isSample() const { return false; }
+ bool isMemory() const { return false; }
+ bool isMemoryQualifierImageAndSSBOOnly() const { return false; }
+ bool bufferReferenceNeedsVulkanMemoryModel() const { return false; }
+ bool isInterpolation() const { return flat || smooth; }
+ bool isExplicitInterpolation() const { return false; }
+ bool isAuxiliary() const { return centroid; }
+ bool isPatch() const { return false; }
+ bool isNoContraction() const { return false; }
+ void setNoContraction() { }
+ bool isPervertexNV() const { return false; }
+#else
+ bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
+ bool nopersp : 1;
+ bool explicitInterp : 1;
+ bool pervertexNV : 1;
+ bool perPrimitiveNV : 1;
+ bool perViewNV : 1;
+ bool perTaskNV : 1;
+ bool patch : 1;
+ bool sample : 1;
+ bool restrict : 1;
+ bool readonly : 1;
+ bool writeonly : 1;
+ bool coherent : 1;
+ bool volatil : 1;
+ bool devicecoherent : 1;
+ bool queuefamilycoherent : 1;
+ bool workgroupcoherent : 1;
+ bool subgroupcoherent : 1;
+ bool nonprivate : 1;
+ bool isWriteOnly() const { return writeonly; }
+ bool isReadOnly() const { return readonly; }
+ bool isRestrict() const { return restrict; }
+ bool isCoherent() const { return coherent; }
+ bool isVolatile() const { return volatil; }
+ bool isSample() const { return sample; }
+ bool isMemory() const
+ {
+ return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
+ }
+ bool isMemoryQualifierImageAndSSBOOnly() const
+ {
+ return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
+ }
+ bool bufferReferenceNeedsVulkanMemoryModel() const
+ {
+ // include qualifiers that map to load/store availability/visibility/nonprivate memory access operands
+ return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate;
+ }
+ bool isInterpolation() const
+ {
+ return flat || smooth || nopersp || explicitInterp;
+ }
+ bool isExplicitInterpolation() const
+ {
+ return explicitInterp;
+ }
+ bool isAuxiliary() const
+ {
+ return centroid || patch || sample || pervertexNV;
+ }
+ bool isPatch() const { return patch; }
+ bool isNoContraction() const { return noContraction; }
+ void setNoContraction() { noContraction = true; }
+ bool isPervertexNV() const { return pervertexNV; }
+#endif
+
+ bool isPipeInput() const
+ {
+ switch (storage) {
+ case EvqVaryingIn:
+ case EvqFragCoord:
+ case EvqPointCoord:
+ case EvqFace:
+ case EvqVertexId:
+ case EvqInstanceId:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isPipeOutput() const
+ {
+ switch (storage) {
+ case EvqPosition:
+ case EvqPointSize:
+ case EvqClipVertex:
+ case EvqVaryingOut:
+ case EvqFragColor:
+ case EvqFragDepth:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isParamInput() const
+ {
+ switch (storage) {
+ case EvqIn:
+ case EvqInOut:
+ case EvqConstReadOnly:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isParamOutput() const
+ {
+ switch (storage) {
+ case EvqOut:
+ case EvqInOut:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isUniformOrBuffer() const
+ {
+ switch (storage) {
+ case EvqUniform:
+ case EvqBuffer:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isIo() const
+ {
+ switch (storage) {
+ case EvqUniform:
+ case EvqBuffer:
+ case EvqVaryingIn:
+ case EvqFragCoord:
+ case EvqPointCoord:
+ case EvqFace:
+ case EvqVertexId:
+ case EvqInstanceId:
+ case EvqPosition:
+ case EvqPointSize:
+ case EvqClipVertex:
+ case EvqVaryingOut:
+ case EvqFragColor:
+ case EvqFragDepth:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // non-built-in symbols that might link between compilation units
+ bool isLinkable() const
+ {
+ switch (storage) {
+ case EvqGlobal:
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ case EvqUniform:
+ case EvqBuffer:
+ case EvqShared:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+#ifdef GLSLANG_WEB
+ bool isPerView() const { return false; }
+ bool isTaskMemory() const { return false; }
+ bool isArrayedIo(EShLanguage language) const { return false; }
+#else
+ bool isPerPrimitive() const { return perPrimitiveNV; }
+ bool isPerView() const { return perViewNV; }
+ bool isTaskMemory() const { return perTaskNV; }
+
+ // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
+ bool isArrayedIo(EShLanguage language) const
+ {
+ switch (language) {
+ case EShLangGeometry:
+ return isPipeInput();
+ case EShLangTessControl:
+ return ! patch && (isPipeInput() || isPipeOutput());
+ case EShLangTessEvaluation:
+ return ! patch && isPipeInput();
+ case EShLangFragment:
+ return pervertexNV && isPipeInput();
+ case EShLangMeshNV:
+ return ! perTaskNV && isPipeOutput();
+
+ default:
+ return false;
+ }
+ }
+#endif
+
+ // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield
+ void clearLayout() // all layout
+ {
+ clearUniformLayout();
+
+#ifndef GLSLANG_WEB
+ layoutPushConstant = false;
+ layoutBufferReference = false;
+ layoutPassthrough = false;
+ layoutViewportRelative = false;
+ // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
+ layoutSecondaryViewportRelativeOffset = -2048;
+ layoutShaderRecordNV = false;
+ layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
+ layoutFormat = ElfNone;
+#endif
+
+ clearInterstageLayout();
+
+ layoutSpecConstantId = layoutSpecConstantIdEnd;
+ }
+ void clearInterstageLayout()
+ {
+ layoutLocation = layoutLocationEnd;
+ layoutComponent = layoutComponentEnd;
+#ifndef GLSLANG_WEB
+ layoutIndex = layoutIndexEnd;
+ clearStreamLayout();
+ clearXfbLayout();
+#endif
+ }
+
+#ifndef GLSLANG_WEB
+ void clearStreamLayout()
+ {
+ layoutStream = layoutStreamEnd;
+ }
+ void clearXfbLayout()
+ {
+ layoutXfbBuffer = layoutXfbBufferEnd;
+ layoutXfbStride = layoutXfbStrideEnd;
+ layoutXfbOffset = layoutXfbOffsetEnd;
+ }
+#endif
+
+ bool hasNonXfbLayout() const
+ {
+ return hasUniformLayout() ||
+ hasAnyLocation() ||
+ hasStream() ||
+ hasFormat() ||
+ isShaderRecordNV() ||
+ isPushConstant() ||
+ hasBufferReference();
+ }
+ bool hasLayout() const
+ {
+ return hasNonXfbLayout() ||
+ hasXfb();
+ }
+ TLayoutMatrix layoutMatrix : 3;
+ TLayoutPacking layoutPacking : 4;
+ int layoutOffset;
+ int layoutAlign;
+
+ unsigned int layoutLocation : 12;
+ static const unsigned int layoutLocationEnd = 0xFFF;
+
+ unsigned int layoutComponent : 3;
+ static const unsigned int layoutComponentEnd = 4;
+
+ unsigned int layoutSet : 7;
+ static const unsigned int layoutSetEnd = 0x3F;
+
+ unsigned int layoutBinding : 16;
+ static const unsigned int layoutBindingEnd = 0xFFFF;
+
+ unsigned int layoutIndex : 8;
+ static const unsigned int layoutIndexEnd = 0xFF;
+
+ unsigned int layoutStream : 8;
+ static const unsigned int layoutStreamEnd = 0xFF;
+
+ unsigned int layoutXfbBuffer : 4;
+ static const unsigned int layoutXfbBufferEnd = 0xF;
+
+ unsigned int layoutXfbStride : 14;
+ static const unsigned int layoutXfbStrideEnd = 0x3FFF;
+
+ unsigned int layoutXfbOffset : 13;
+ static const unsigned int layoutXfbOffsetEnd = 0x1FFF;
+
+ unsigned int layoutAttachment : 8; // for input_attachment_index
+ static const unsigned int layoutAttachmentEnd = 0XFF;
+
+ unsigned int layoutSpecConstantId : 11;
+ static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
+
+#ifndef GLSLANG_WEB
+ // stored as log2 of the actual alignment value
+ unsigned int layoutBufferReferenceAlign : 6;
+ static const unsigned int layoutBufferReferenceAlignEnd = 0x3F;
+
+ TLayoutFormat layoutFormat : 8;
+
+ bool layoutPushConstant;
+ bool layoutBufferReference;
+ bool layoutPassthrough;
+ bool layoutViewportRelative;
+ int layoutSecondaryViewportRelativeOffset;
+ bool layoutShaderRecordNV;
+#endif
+
+ bool hasUniformLayout() const
+ {
+ return hasMatrix() ||
+ hasPacking() ||
+ hasOffset() ||
+ hasBinding() ||
+ hasSet() ||
+ hasAlign();
+ }
+ void clearUniformLayout() // only uniform specific
+ {
+ layoutMatrix = ElmNone;
+ layoutPacking = ElpNone;
+ layoutOffset = layoutNotSet;
+ layoutAlign = layoutNotSet;
+
+ layoutSet = layoutSetEnd;
+ layoutBinding = layoutBindingEnd;
+#ifndef GLSLANG_WEB
+ layoutAttachment = layoutAttachmentEnd;
+#endif
+ }
+
+ bool hasMatrix() const
+ {
+ return layoutMatrix != ElmNone;
+ }
+ bool hasPacking() const
+ {
+ return layoutPacking != ElpNone;
+ }
+ bool hasAlign() const
+ {
+ return layoutAlign != layoutNotSet;
+ }
+ bool hasAnyLocation() const
+ {
+ return hasLocation() ||
+ hasComponent() ||
+ hasIndex();
+ }
+ bool hasLocation() const
+ {
+ return layoutLocation != layoutLocationEnd;
+ }
+ bool hasSet() const
+ {
+ return layoutSet != layoutSetEnd;
+ }
+ bool hasBinding() const
+ {
+ return layoutBinding != layoutBindingEnd;
+ }
+#ifdef GLSLANG_WEB
+ bool hasOffset() const { return false; }
+ bool isNonPerspective() const { return false; }
+ bool hasIndex() const { return false; }
+ unsigned getIndex() const { return 0; }
+ bool hasComponent() const { return false; }
+ bool hasStream() const { return false; }
+ bool hasFormat() const { return false; }
+ bool hasXfb() const { return false; }
+ bool hasXfbBuffer() const { return false; }
+ bool hasXfbStride() const { return false; }
+ bool hasXfbOffset() const { return false; }
+ bool hasAttachment() const { return false; }
+ TLayoutFormat getFormat() const { return ElfNone; }
+ bool isPushConstant() const { return false; }
+ bool isShaderRecordNV() const { return false; }
+ bool hasBufferReference() const { return false; }
+ bool hasBufferReferenceAlign() const { return false; }
+ bool isNonUniform() const { return false; }
+#else
+ bool hasOffset() const
+ {
+ return layoutOffset != layoutNotSet;
+ }
+ bool isNonPerspective() const { return nopersp; }
+ bool hasIndex() const
+ {
+ return layoutIndex != layoutIndexEnd;
+ }
+ unsigned getIndex() const { return layoutIndex; }
+ bool hasComponent() const
+ {
+ return layoutComponent != layoutComponentEnd;
+ }
+ bool hasStream() const
+ {
+ return layoutStream != layoutStreamEnd;
+ }
+ bool hasFormat() const
+ {
+ return layoutFormat != ElfNone;
+ }
+ bool hasXfb() const
+ {
+ return hasXfbBuffer() ||
+ hasXfbStride() ||
+ hasXfbOffset();
+ }
+ bool hasXfbBuffer() const
+ {
+ return layoutXfbBuffer != layoutXfbBufferEnd;
+ }
+ bool hasXfbStride() const
+ {
+ return layoutXfbStride != layoutXfbStrideEnd;
+ }
+ bool hasXfbOffset() const
+ {
+ return layoutXfbOffset != layoutXfbOffsetEnd;
+ }
+ bool hasAttachment() const
+ {
+ return layoutAttachment != layoutAttachmentEnd;
+ }
+ TLayoutFormat getFormat() const { return layoutFormat; }
+ bool isPushConstant() const { return layoutPushConstant; }
+ bool isShaderRecordNV() const { return layoutShaderRecordNV; }
+ bool hasBufferReference() const { return layoutBufferReference; }
+ bool hasBufferReferenceAlign() const
+ {
+ return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd;
+ }
+ bool isNonUniform() const
+ {
+ return nonUniform;
+ }
+#endif
+ bool hasSpecConstantId() const
+ {
+ // Not the same thing as being a specialization constant, this
+ // is just whether or not it was declared with an ID.
+ return layoutSpecConstantId != layoutSpecConstantIdEnd;
+ }
+ bool isSpecConstant() const
+ {
+ // True if type is a specialization constant, whether or not it
+ // had a specialization-constant ID, and false if it is not a
+ // true front-end constant.
+ return specConstant;
+ }
+ bool isFrontEndConstant() const
+ {
+ // True if the front-end knows the final constant value.
+ // This allows front-end constant folding.
+ return storage == EvqConst && ! specConstant;
+ }
+ bool isConstant() const
+ {
+ // True if is either kind of constant; specialization or regular.
+ return isFrontEndConstant() || isSpecConstant();
+ }
+ void makeSpecConstant()
+ {
+ storage = EvqConst;
+ specConstant = true;
+ }
+ static const char* getLayoutPackingString(TLayoutPacking packing)
+ {
+ switch (packing) {
+ case ElpStd140: return "std140";
+#ifndef GLSLANG_WEB
+ case ElpPacked: return "packed";
+ case ElpShared: return "shared";
+ case ElpStd430: return "std430";
+ case ElpScalar: return "scalar";
+#endif
+ default: return "none";
+ }
+ }
+ static const char* getLayoutMatrixString(TLayoutMatrix m)
+ {
+ switch (m) {
+ case ElmColumnMajor: return "column_major";
+ case ElmRowMajor: return "row_major";
+ default: return "none";
+ }
+ }
+#ifdef GLSLANG_WEB
+ static const char* getLayoutFormatString(TLayoutFormat f) { return "none"; }
+#else
+ static const char* getLayoutFormatString(TLayoutFormat f)
+ {
+ switch (f) {
+ case ElfRgba32f: return "rgba32f";
+ case ElfRgba16f: return "rgba16f";
+ case ElfRg32f: return "rg32f";
+ case ElfRg16f: return "rg16f";
+ case ElfR11fG11fB10f: return "r11f_g11f_b10f";
+ case ElfR32f: return "r32f";
+ case ElfR16f: return "r16f";
+ case ElfRgba16: return "rgba16";
+ case ElfRgb10A2: return "rgb10_a2";
+ case ElfRgba8: return "rgba8";
+ case ElfRg16: return "rg16";
+ case ElfRg8: return "rg8";
+ case ElfR16: return "r16";
+ case ElfR8: return "r8";
+ case ElfRgba16Snorm: return "rgba16_snorm";
+ case ElfRgba8Snorm: return "rgba8_snorm";
+ case ElfRg16Snorm: return "rg16_snorm";
+ case ElfRg8Snorm: return "rg8_snorm";
+ case ElfR16Snorm: return "r16_snorm";
+ case ElfR8Snorm: return "r8_snorm";
+
+ case ElfRgba32i: return "rgba32i";
+ case ElfRgba16i: return "rgba16i";
+ case ElfRgba8i: return "rgba8i";
+ case ElfRg32i: return "rg32i";
+ case ElfRg16i: return "rg16i";
+ case ElfRg8i: return "rg8i";
+ case ElfR32i: return "r32i";
+ case ElfR16i: return "r16i";
+ case ElfR8i: return "r8i";
+
+ case ElfRgba32ui: return "rgba32ui";
+ case ElfRgba16ui: return "rgba16ui";
+ case ElfRgba8ui: return "rgba8ui";
+ case ElfRg32ui: return "rg32ui";
+ case ElfRg16ui: return "rg16ui";
+ case ElfRgb10a2ui: return "rgb10_a2ui";
+ case ElfRg8ui: return "rg8ui";
+ case ElfR32ui: return "r32ui";
+ case ElfR16ui: return "r16ui";
+ case ElfR8ui: return "r8ui";
+ default: return "none";
+ }
+ }
+ static const char* getLayoutDepthString(TLayoutDepth d)
+ {
+ switch (d) {
+ case EldAny: return "depth_any";
+ case EldGreater: return "depth_greater";
+ case EldLess: return "depth_less";
+ case EldUnchanged: return "depth_unchanged";
+ default: return "none";
+ }
+ }
+ static const char* getBlendEquationString(TBlendEquationShift e)
+ {
+ switch (e) {
+ case EBlendMultiply: return "blend_support_multiply";
+ case EBlendScreen: return "blend_support_screen";
+ case EBlendOverlay: return "blend_support_overlay";
+ case EBlendDarken: return "blend_support_darken";
+ case EBlendLighten: return "blend_support_lighten";
+ case EBlendColordodge: return "blend_support_colordodge";
+ case EBlendColorburn: return "blend_support_colorburn";
+ case EBlendHardlight: return "blend_support_hardlight";
+ case EBlendSoftlight: return "blend_support_softlight";
+ case EBlendDifference: return "blend_support_difference";
+ case EBlendExclusion: return "blend_support_exclusion";
+ case EBlendHslHue: return "blend_support_hsl_hue";
+ case EBlendHslSaturation: return "blend_support_hsl_saturation";
+ case EBlendHslColor: return "blend_support_hsl_color";
+ case EBlendHslLuminosity: return "blend_support_hsl_luminosity";
+ case EBlendAllEquations: return "blend_support_all_equations";
+ default: return "unknown";
+ }
+ }
+ static const char* getGeometryString(TLayoutGeometry geometry)
+ {
+ switch (geometry) {
+ case ElgPoints: return "points";
+ case ElgLines: return "lines";
+ case ElgLinesAdjacency: return "lines_adjacency";
+ case ElgLineStrip: return "line_strip";
+ case ElgTriangles: return "triangles";
+ case ElgTrianglesAdjacency: return "triangles_adjacency";
+ case ElgTriangleStrip: return "triangle_strip";
+ case ElgQuads: return "quads";
+ case ElgIsolines: return "isolines";
+ default: return "none";
+ }
+ }
+ static const char* getVertexSpacingString(TVertexSpacing spacing)
+ {
+ switch (spacing) {
+ case EvsEqual: return "equal_spacing";
+ case EvsFractionalEven: return "fractional_even_spacing";
+ case EvsFractionalOdd: return "fractional_odd_spacing";
+ default: return "none";
+ }
+ }
+ static const char* getVertexOrderString(TVertexOrder order)
+ {
+ switch (order) {
+ case EvoCw: return "cw";
+ case EvoCcw: return "ccw";
+ default: return "none";
+ }
+ }
+ static int mapGeometryToSize(TLayoutGeometry geometry)
+ {
+ switch (geometry) {
+ case ElgPoints: return 1;
+ case ElgLines: return 2;
+ case ElgLinesAdjacency: return 4;
+ case ElgTriangles: return 3;
+ case ElgTrianglesAdjacency: return 6;
+ default: return 0;
+ }
+ }
+ static const char* getInterlockOrderingString(TInterlockOrdering order)
+ {
+ switch (order) {
+ case EioPixelInterlockOrdered: return "pixel_interlock_ordered";
+ case EioPixelInterlockUnordered: return "pixel_interlock_unordered";
+ case EioSampleInterlockOrdered: return "sample_interlock_ordered";
+ case EioSampleInterlockUnordered: return "sample_interlock_unordered";
+ case EioShadingRateInterlockOrdered: return "shading_rate_interlock_ordered";
+ case EioShadingRateInterlockUnordered: return "shading_rate_interlock_unordered";
+ default: return "none";
+ }
+ }
+#endif
+};
+
+// Qualifiers that don't need to be keep per object. They have shader scope, not object scope.
+// So, they will not be part of TType, TQualifier, etc.
+struct TShaderQualifiers {
+ TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives
+ bool pixelCenterInteger; // fragment shader
+ bool originUpperLeft; // fragment shader
+ int invocations;
+ int vertices; // for tessellation "vertices", geometry & mesh "max_vertices"
+ TVertexSpacing spacing;
+ TVertexOrder order;
+ bool pointMode;
+ int localSize[3]; // compute shader
+ bool localSizeNotDefault[3]; // compute shader
+ int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize
+#ifndef GLSLANG_WEB
+ bool earlyFragmentTests; // fragment input
+ bool postDepthCoverage; // fragment input
+ TLayoutDepth layoutDepth;
+ bool blendEquation; // true if any blend equation was specified
+ int numViews; // multiview extenstions
+ TInterlockOrdering interlockOrdering;
+ bool layoutOverrideCoverage; // true if layout override_coverage set
+ bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set
+ bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set
+ int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set
+ TLayoutDepth getDepth() const { return layoutDepth; }
+#else
+ TLayoutDepth getDepth() const { return EldNone; }
+#endif
+
+ void init()
+ {
+ geometry = ElgNone;
+ originUpperLeft = false;
+ pixelCenterInteger = false;
+ invocations = TQualifier::layoutNotSet;
+ vertices = TQualifier::layoutNotSet;
+ spacing = EvsNone;
+ order = EvoNone;
+ pointMode = false;
+ localSize[0] = 1;
+ localSize[1] = 1;
+ localSize[2] = 1;
+ localSizeNotDefault[0] = false;
+ localSizeNotDefault[1] = false;
+ localSizeNotDefault[2] = false;
+ localSizeSpecId[0] = TQualifier::layoutNotSet;
+ localSizeSpecId[1] = TQualifier::layoutNotSet;
+ localSizeSpecId[2] = TQualifier::layoutNotSet;
+#ifndef GLSLANG_WEB
+ earlyFragmentTests = false;
+ postDepthCoverage = false;
+ layoutDepth = EldNone;
+ blendEquation = false;
+ numViews = TQualifier::layoutNotSet;
+ layoutOverrideCoverage = false;
+ layoutDerivativeGroupQuads = false;
+ layoutDerivativeGroupLinear = false;
+ primitives = TQualifier::layoutNotSet;
+ interlockOrdering = EioNone;
+#endif
+ }
+
+#ifdef GLSLANG_WEB
+ bool hasBlendEquation() const { return false; }
+#else
+ bool hasBlendEquation() const { return blendEquation; }
+#endif
+
+ // Merge in characteristics from the 'src' qualifier. They can override when
+ // set, but never erase when not set.
+ void merge(const TShaderQualifiers& src)
+ {
+ if (src.geometry != ElgNone)
+ geometry = src.geometry;
+ if (src.pixelCenterInteger)
+ pixelCenterInteger = src.pixelCenterInteger;
+ if (src.originUpperLeft)
+ originUpperLeft = src.originUpperLeft;
+ if (src.invocations != TQualifier::layoutNotSet)
+ invocations = src.invocations;
+ if (src.vertices != TQualifier::layoutNotSet)
+ vertices = src.vertices;
+ if (src.spacing != EvsNone)
+ spacing = src.spacing;
+ if (src.order != EvoNone)
+ order = src.order;
+ if (src.pointMode)
+ pointMode = true;
+ for (int i = 0; i < 3; ++i) {
+ if (src.localSize[i] > 1)
+ localSize[i] = src.localSize[i];
+ }
+ for (int i = 0; i < 3; ++i) {
+ localSizeNotDefault[i] = src.localSizeNotDefault[i] || localSizeNotDefault[i];
+ }
+ for (int i = 0; i < 3; ++i) {
+ if (src.localSizeSpecId[i] != TQualifier::layoutNotSet)
+ localSizeSpecId[i] = src.localSizeSpecId[i];
+ }
+#ifndef GLSLANG_WEB
+ if (src.earlyFragmentTests)
+ earlyFragmentTests = true;
+ if (src.postDepthCoverage)
+ postDepthCoverage = true;
+ if (src.layoutDepth)
+ layoutDepth = src.layoutDepth;
+ if (src.blendEquation)
+ blendEquation = src.blendEquation;
+ if (src.numViews != TQualifier::layoutNotSet)
+ numViews = src.numViews;
+ if (src.layoutOverrideCoverage)
+ layoutOverrideCoverage = src.layoutOverrideCoverage;
+ if (src.layoutDerivativeGroupQuads)
+ layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads;
+ if (src.layoutDerivativeGroupLinear)
+ layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear;
+ if (src.primitives != TQualifier::layoutNotSet)
+ primitives = src.primitives;
+ if (src.interlockOrdering != EioNone)
+ interlockOrdering = src.interlockOrdering;
+#endif
+ }
+};
+
+//
+// TPublicType is just temporarily used while parsing and not quite the same
+// information kept per node in TType. Due to the bison stack, it can't have
+// types that it thinks have non-trivial constructors. It should
+// just be used while recognizing the grammar, not anything else.
+// Once enough is known about the situation, the proper information
+// moved into a TType, or the parse context, etc.
+//
+class TPublicType {
+public:
+ TBasicType basicType;
+ TSampler sampler;
+ TQualifier qualifier;
+ TShaderQualifiers shaderQualifiers;
+ int vectorSize : 4;
+ int matrixCols : 4;
+ int matrixRows : 4;
+ bool coopmat : 1;
+ TArraySizes* arraySizes;
+ const TType* userDef;
+ TSourceLoc loc;
+ TArraySizes* typeParameters;
+
+#ifdef GLSLANG_WEB
+ bool isCoopmat() const { return false; }
+#else
+ bool isCoopmat() const { return coopmat; }
+#endif
+
+ void initType(const TSourceLoc& l)
+ {
+ basicType = EbtVoid;
+ vectorSize = 1;
+ matrixRows = 0;
+ matrixCols = 0;
+ arraySizes = nullptr;
+ userDef = nullptr;
+ loc = l;
+ typeParameters = nullptr;
+ coopmat = false;
+ }
+
+ void initQualifiers(bool global = false)
+ {
+ qualifier.clear();
+ if (global)
+ qualifier.storage = EvqGlobal;
+ }
+
+ void init(const TSourceLoc& l, bool global = false)
+ {
+ initType(l);
+ sampler.clear();
+ initQualifiers(global);
+ shaderQualifiers.init();
+ }
+
+ void setVector(int s)
+ {
+ matrixRows = 0;
+ matrixCols = 0;
+ vectorSize = s;
+ }
+
+ void setMatrix(int c, int r)
+ {
+ matrixRows = r;
+ matrixCols = c;
+ vectorSize = 0;
+ }
+
+ bool isScalar() const
+ {
+ return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr;
+ }
+
+ // "Image" is a superset of "Subpass"
+ bool isImage() const { return basicType == EbtSampler && sampler.isImage(); }
+ bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); }
+};
+
+//
+// Base class for things that have a type.
+//
+class TType {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+ // for "empty" type (no args) or simple scalar/vector/matrix
+ explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0,
+ bool isVector = false) :
+ basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
+ arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
+ {
+ sampler.clear();
+ qualifier.clear();
+ qualifier.storage = q;
+ assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices
+ }
+ // for explicit precision qualifier
+ TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0,
+ bool isVector = false) :
+ basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
+ arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
+ {
+ sampler.clear();
+ qualifier.clear();
+ qualifier.storage = q;
+ qualifier.precision = p;
+ assert(p >= EpqNone && p <= EpqHigh);
+ assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices
+ }
+ // for turning a TPublicType into a TType, using a shallow copy
+ explicit TType(const TPublicType& p) :
+ basicType(p.basicType),
+ vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat),
+ arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters)
+ {
+ if (basicType == EbtSampler)
+ sampler = p.sampler;
+ else
+ sampler.clear();
+ qualifier = p.qualifier;
+ if (p.userDef) {
+ if (p.userDef->basicType == EbtReference) {
+ basicType = EbtReference;
+ referentType = p.userDef->referentType;
+ } else {
+ structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues
+ }
+ typeName = NewPoolTString(p.userDef->getTypeName().c_str());
+ }
+ if (p.isCoopmat() && p.typeParameters && p.typeParameters->getNumDims() > 0) {
+ int numBits = p.typeParameters->getDimSize(0);
+ if (p.basicType == EbtFloat && numBits == 16) {
+ basicType = EbtFloat16;
+ qualifier.precision = EpqNone;
+ } else if (p.basicType == EbtUint && numBits == 8) {
+ basicType = EbtUint8;
+ qualifier.precision = EpqNone;
+ } else if (p.basicType == EbtInt && numBits == 8) {
+ basicType = EbtInt8;
+ qualifier.precision = EpqNone;
+ }
+ }
+ }
+ // for construction of sampler types
+ TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) :
+ basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
+ arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
+ sampler(sampler), typeParameters(nullptr)
+ {
+ qualifier.clear();
+ qualifier.storage = q;
+ }
+ // to efficiently make a dereferenced type
+ // without ever duplicating the outer structure that will be thrown away
+ // and using only shallow copy
+ TType(const TType& type, int derefIndex, bool rowMajor = false)
+ {
+ if (type.isArray()) {
+ shallowCopy(type);
+ if (type.getArraySizes()->getNumDims() == 1) {
+ arraySizes = nullptr;
+ } else {
+ // want our own copy of the array, so we can edit it
+ arraySizes = new TArraySizes;
+ arraySizes->copyDereferenced(*type.arraySizes);
+ }
+ } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) {
+ // do a structure dereference
+ const TTypeList& memberList = *type.getStruct();
+ shallowCopy(*memberList[derefIndex].type);
+ return;
+ } else {
+ // do a vector/matrix dereference
+ shallowCopy(type);
+ if (matrixCols > 0) {
+ // dereference from matrix to vector
+ if (rowMajor)
+ vectorSize = matrixCols;
+ else
+ vectorSize = matrixRows;
+ matrixCols = 0;
+ matrixRows = 0;
+ if (vectorSize == 1)
+ vector1 = true;
+ } else if (isVector()) {
+ // dereference from vector to scalar
+ vectorSize = 1;
+ vector1 = false;
+ } else if (isCoopMat()) {
+ coopmat = false;
+ typeParameters = nullptr;
+ }
+ }
+ }
+ // for making structures, ...
+ TType(TTypeList* userDef, const TString& n) :
+ basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
+ arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
+ {
+ sampler.clear();
+ qualifier.clear();
+ typeName = NewPoolTString(n.c_str());
+ }
+ // For interface blocks
+ TType(TTypeList* userDef, const TString& n, const TQualifier& q) :
+ basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
+ qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
+ {
+ sampler.clear();
+ typeName = NewPoolTString(n.c_str());
+ }
+ // for block reference (first parameter must be EbtReference)
+ explicit TType(TBasicType t, const TType &p, const TString& n) :
+ basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
+ arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
+ {
+ assert(t == EbtReference);
+ typeName = NewPoolTString(n.c_str());
+ qualifier.clear();
+ qualifier.storage = p.qualifier.storage;
+ referentType = p.clone();
+ }
+ virtual ~TType() {}
+
+ // Not for use across pool pops; it will cause multiple instances of TType to point to the same information.
+ // This only works if that information (like a structure's list of types) does not change and
+ // the instances are sharing the same pool.
+ void shallowCopy(const TType& copyOf)
+ {
+ basicType = copyOf.basicType;
+ sampler = copyOf.sampler;
+ qualifier = copyOf.qualifier;
+ vectorSize = copyOf.vectorSize;
+ matrixCols = copyOf.matrixCols;
+ matrixRows = copyOf.matrixRows;
+ vector1 = copyOf.vector1;
+ arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents
+ fieldName = copyOf.fieldName;
+ typeName = copyOf.typeName;
+ if (isStruct()) {
+ structure = copyOf.structure;
+ } else {
+ referentType = copyOf.referentType;
+ }
+ typeParameters = copyOf.typeParameters;
+ coopmat = copyOf.isCoopMat();
+ }
+
+ // Make complete copy of the whole type graph rooted at 'copyOf'.
+ void deepCopy(const TType& copyOf)
+ {
+ TMap<TTypeList*,TTypeList*> copied; // to enable copying a type graph as a graph, not a tree
+ deepCopy(copyOf, copied);
+ }
+
+ // Recursively make temporary
+ void makeTemporary()
+ {
+ getQualifier().makeTemporary();
+
+ if (isStruct())
+ for (unsigned int i = 0; i < structure->size(); ++i)
+ (*structure)[i].type->makeTemporary();
+ }
+
+ TType* clone() const
+ {
+ TType *newType = new TType();
+ newType->deepCopy(*this);
+
+ return newType;
+ }
+
+ void makeVector() { vector1 = true; }
+
+ virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
+ virtual bool hiddenMember() const { return basicType == EbtVoid; }
+
+ virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
+ virtual const TString& getTypeName() const
+ {
+ assert(typeName);
+ return *typeName;
+ }
+
+ virtual const TString& getFieldName() const
+ {
+ assert(fieldName);
+ return *fieldName;
+ }
+
+ virtual TBasicType getBasicType() const { return basicType; }
+ virtual const TSampler& getSampler() const { return sampler; }
+ virtual TSampler& getSampler() { return sampler; }
+
+ virtual TQualifier& getQualifier() { return qualifier; }
+ virtual const TQualifier& getQualifier() const { return qualifier; }
+
+ virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both
+ virtual int getMatrixCols() const { return matrixCols; }
+ virtual int getMatrixRows() const { return matrixRows; }
+ virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); }
+ virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); }
+ virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); }
+#ifdef GLSLANG_WEB
+ bool isArrayOfArrays() const { return false; }
+#else
+ bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
+#endif
+ virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
+ virtual const TArraySizes* getArraySizes() const { return arraySizes; }
+ virtual TArraySizes* getArraySizes() { return arraySizes; }
+ virtual TType* getReferentType() const { return referentType; }
+ virtual const TArraySizes* getTypeParameters() const { return typeParameters; }
+ virtual TArraySizes* getTypeParameters() { return typeParameters; }
+
+ virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
+ virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
+ virtual bool isVector() const { return vectorSize > 1 || vector1; }
+ virtual bool isMatrix() const { return matrixCols ? true : false; }
+ virtual bool isArray() const { return arraySizes != nullptr; }
+ virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
+ virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
+ virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
+ virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
+ virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
+ virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; }
+ virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
+ virtual bool isIntegerDomain() const
+ {
+ switch (basicType) {
+ case EbtInt8:
+ case EbtUint8:
+ case EbtInt16:
+ case EbtUint16:
+ case EbtInt:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ case EbtAtomicUint:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+ virtual bool isOpaque() const { return basicType == EbtSampler
+#ifndef GLSLANG_WEB
+ || basicType == EbtAtomicUint || basicType == EbtAccStructNV
+#endif
+ ; }
+ virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
+
+ // "Image" is a superset of "Subpass"
+ virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); }
+ virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
+ virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); }
+ // Check the block-name convention of creating a block without populating it's members:
+ virtual bool isUnusableName() const { return isStruct() && structure == nullptr; }
+ virtual bool isParameterized() const { return typeParameters != nullptr; }
+#ifdef GLSLANG_WEB
+ bool isAtomic() const { return false; }
+ bool isCoopMat() const { return false; }
+ bool isReference() const { return false; }
+#else
+ bool isAtomic() const { return basicType == EbtAtomicUint; }
+ bool isCoopMat() const { return coopmat; }
+ bool isReference() const { return getBasicType() == EbtReference; }
+#endif
+
+ // return true if this type contains any subtype which satisfies the given predicate.
+ template <typename P>
+ bool contains(P predicate) const
+ {
+ if (predicate(this))
+ return true;
+
+ const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); };
+
+ return isStruct() && std::any_of(structure->begin(), structure->end(), hasa);
+ }
+
+ // Recursively checks if the type contains the given basic type
+ virtual bool containsBasicType(TBasicType checkType) const
+ {
+ return contains([checkType](const TType* t) { return t->basicType == checkType; } );
+ }
+
+ // Recursively check the structure for any arrays, needed for some error checks
+ virtual bool containsArray() const
+ {
+ return contains([](const TType* t) { return t->isArray(); } );
+ }
+
+ // Check the structure for any structures, needed for some error checks
+ virtual bool containsStructure() const
+ {
+ return contains([this](const TType* t) { return t != this && t->isStruct(); } );
+ }
+
+ // Recursively check the structure for any unsized arrays, needed for triggering a copyUp().
+ virtual bool containsUnsizedArray() const
+ {
+ return contains([](const TType* t) { return t->isUnsizedArray(); } );
+ }
+
+ virtual bool containsOpaque() const
+ {
+ return contains([](const TType* t) { return t->isOpaque(); } );
+ }
+
+ // Recursively checks if the type contains a built-in variable
+ virtual bool containsBuiltIn() const
+ {
+ return contains([](const TType* t) { return t->isBuiltIn(); } );
+ }
+
+ virtual bool containsNonOpaque() const
+ {
+ const auto nonOpaque = [](const TType* t) {
+ switch (t->basicType) {
+ case EbtVoid:
+ case EbtFloat:
+ case EbtDouble:
+ case EbtFloat16:
+ case EbtInt8:
+ case EbtUint8:
+ case EbtInt16:
+ case EbtUint16:
+ case EbtInt:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ case EbtBool:
+ case EbtReference:
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ return contains(nonOpaque);
+ }
+
+ virtual bool containsSpecializationSize() const
+ {
+ return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
+ }
+
+#ifdef GLSLANG_WEB
+ bool containsDouble() const { return false; }
+ bool contains16BitFloat() const { return false; }
+ bool contains64BitInt() const { return false; }
+ bool contains16BitInt() const { return false; }
+ bool contains8BitInt() const { return false; }
+ bool containsCoopMat() const { return false; }
+ bool containsReference() const { return false; }
+#else
+ bool containsDouble() const
+ {
+ return containsBasicType(EbtDouble);
+ }
+ bool contains16BitFloat() const
+ {
+ return containsBasicType(EbtFloat16);
+ }
+ bool contains64BitInt() const
+ {
+ return containsBasicType(EbtInt64) || containsBasicType(EbtUint64);
+ }
+ bool contains16BitInt() const
+ {
+ return containsBasicType(EbtInt16) || containsBasicType(EbtUint16);
+ }
+ bool contains8BitInt() const
+ {
+ return containsBasicType(EbtInt8) || containsBasicType(EbtUint8);
+ }
+ bool containsCoopMat() const
+ {
+ return contains([](const TType* t) { return t->coopmat; } );
+ }
+ bool containsReference() const
+ {
+ return containsBasicType(EbtReference);
+ }
+#endif
+
+ // Array editing methods. Array descriptors can be shared across
+ // type instances. This allows all uses of the same array
+ // to be updated at once. E.g., all nodes can be explicitly sized
+ // by tracking and correcting one implicit size. Or, all nodes
+ // can get the explicit size on a redeclaration that gives size.
+ //
+ // N.B.: Don't share with the shared symbol tables (symbols are
+ // marked as isReadOnly(). Such symbols with arrays that will be
+ // edited need to copyUp() on first use, so that
+ // A) the edits don't effect the shared symbol table, and
+ // B) the edits are shared across all users.
+ void updateArraySizes(const TType& type)
+ {
+ // For when we may already be sharing existing array descriptors,
+ // keeping the pointers the same, just updating the contents.
+ assert(arraySizes != nullptr);
+ assert(type.arraySizes != nullptr);
+ *arraySizes = *type.arraySizes;
+ }
+ void copyArraySizes(const TArraySizes& s)
+ {
+ // For setting a fresh new set of array sizes, not yet worrying about sharing.
+ arraySizes = new TArraySizes;
+ *arraySizes = s;
+ }
+ void transferArraySizes(TArraySizes* s)
+ {
+ // For setting an already allocated set of sizes that this type can use
+ // (no copy made).
+ arraySizes = s;
+ }
+ void clearArraySizes()
+ {
+ arraySizes = nullptr;
+ }
+
+ // Add inner array sizes, to any existing sizes, via copy; the
+ // sizes passed in can still be reused for other purposes.
+ void copyArrayInnerSizes(const TArraySizes* s)
+ {
+ if (s != nullptr) {
+ if (arraySizes == nullptr)
+ copyArraySizes(*s);
+ else
+ arraySizes->addInnerSizes(*s);
+ }
+ }
+ void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); }
+
+ // Recursively make the implicit array size the explicit array size.
+ // Expicit arrays are compile-time or link-time sized, never run-time sized.
+ // Sometimes, policy calls for an array to be run-time sized even if it was
+ // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into
+ // an explicit array.
+ void adoptImplicitArraySizes(bool skipNonvariablyIndexed)
+ {
+ if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed()))
+ changeOuterArraySize(getImplicitArraySize());
+ // For multi-dim per-view arrays, set unsized inner dimension size to 1
+ if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized())
+ arraySizes->clearInnerUnsized();
+ if (isStruct() && structure->size() > 0) {
+ int lastMember = (int)structure->size() - 1;
+ for (int i = 0; i < lastMember; ++i)
+ (*structure)[i].type->adoptImplicitArraySizes(false);
+ // implement the "last member of an SSBO" policy
+ (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer);
+ }
+ }
+
+
+ void updateTypeParameters(const TType& type)
+ {
+ // For when we may already be sharing existing array descriptors,
+ // keeping the pointers the same, just updating the contents.
+ assert(typeParameters != nullptr);
+ assert(type.typeParameters != nullptr);
+ *typeParameters = *type.typeParameters;
+ }
+ void copyTypeParameters(const TArraySizes& s)
+ {
+ // For setting a fresh new set of type parameters, not yet worrying about sharing.
+ typeParameters = new TArraySizes;
+ *typeParameters = s;
+ }
+ void transferTypeParameters(TArraySizes* s)
+ {
+ // For setting an already allocated set of sizes that this type can use
+ // (no copy made).
+ typeParameters = s;
+ }
+ void clearTypeParameters()
+ {
+ typeParameters = nullptr;
+ }
+
+ // Add inner array sizes, to any existing sizes, via copy; the
+ // sizes passed in can still be reused for other purposes.
+ void copyTypeParametersInnerSizes(const TArraySizes* s)
+ {
+ if (s != nullptr) {
+ if (typeParameters == nullptr)
+ copyTypeParameters(*s);
+ else
+ typeParameters->addInnerSizes(*s);
+ }
+ }
+
+
+
+ const char* getBasicString() const
+ {
+ return TType::getBasicString(basicType);
+ }
+
+ static const char* getBasicString(TBasicType t)
+ {
+ switch (t) {
+ case EbtFloat: return "float";
+ case EbtInt: return "int";
+ case EbtUint: return "uint";
+ case EbtSampler: return "sampler/image";
+#ifndef GLSLANG_WEB
+ case EbtVoid: return "void";
+ case EbtDouble: return "double";
+ case EbtFloat16: return "float16_t";
+ case EbtInt8: return "int8_t";
+ case EbtUint8: return "uint8_t";
+ case EbtInt16: return "int16_t";
+ case EbtUint16: return "uint16_t";
+ case EbtInt64: return "int64_t";
+ case EbtUint64: return "uint64_t";
+ case EbtBool: return "bool";
+ case EbtAtomicUint: return "atomic_uint";
+ case EbtStruct: return "structure";
+ case EbtBlock: return "block";
+ case EbtAccStructNV: return "accelerationStructureNV";
+ case EbtReference: return "reference";
+#endif
+ default: return "unknown type";
+ }
+ }
+
+#ifdef GLSLANG_WEB
+ TString getCompleteString() const { return ""; }
+ const char* getStorageQualifierString() const { return ""; }
+ const char* getBuiltInVariableString() const { return ""; }
+ const char* getPrecisionQualifierString() const { return ""; }
+ TString getBasicTypeString() const { return ""; }
+#else
+ TString getCompleteString() const
+ {
+ TString typeString;
+
+ const auto appendStr = [&](const char* s) { typeString.append(s); };
+ const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); };
+ const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); };
+
+ if (qualifier.hasLayout()) {
+ // To reduce noise, skip this if the only layout is an xfb_buffer
+ // with no triggering xfb_offset.
+ TQualifier noXfbBuffer = qualifier;
+ noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
+ if (noXfbBuffer.hasLayout()) {
+ appendStr("layout(");
+ if (qualifier.hasAnyLocation()) {
+ appendStr(" location=");
+ appendUint(qualifier.layoutLocation);
+ if (qualifier.hasComponent()) {
+ appendStr(" component=");
+ appendUint(qualifier.layoutComponent);
+ }
+ if (qualifier.hasIndex()) {
+ appendStr(" index=");
+ appendUint(qualifier.layoutIndex);
+ }
+ }
+ if (qualifier.hasSet()) {
+ appendStr(" set=");
+ appendUint(qualifier.layoutSet);
+ }
+ if (qualifier.hasBinding()) {
+ appendStr(" binding=");
+ appendUint(qualifier.layoutBinding);
+ }
+ if (qualifier.hasStream()) {
+ appendStr(" stream=");
+ appendUint(qualifier.layoutStream);
+ }
+ if (qualifier.hasMatrix()) {
+ appendStr(" ");
+ appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
+ }
+ if (qualifier.hasPacking()) {
+ appendStr(" ");
+ appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking));
+ }
+ if (qualifier.hasOffset()) {
+ appendStr(" offset=");
+ appendInt(qualifier.layoutOffset);
+ }
+ if (qualifier.hasAlign()) {
+ appendStr(" align=");
+ appendInt(qualifier.layoutAlign);
+ }
+ if (qualifier.hasFormat()) {
+ appendStr(" ");
+ appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat));
+ }
+ if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) {
+ appendStr(" xfb_buffer=");
+ appendUint(qualifier.layoutXfbBuffer);
+ }
+ if (qualifier.hasXfbOffset()) {
+ appendStr(" xfb_offset=");
+ appendUint(qualifier.layoutXfbOffset);
+ }
+ if (qualifier.hasXfbStride()) {
+ appendStr(" xfb_stride=");
+ appendUint(qualifier.layoutXfbStride);
+ }
+ if (qualifier.hasAttachment()) {
+ appendStr(" input_attachment_index=");
+ appendUint(qualifier.layoutAttachment);
+ }
+ if (qualifier.hasSpecConstantId()) {
+ appendStr(" constant_id=");
+ appendUint(qualifier.layoutSpecConstantId);
+ }
+ if (qualifier.layoutPushConstant)
+ appendStr(" push_constant");
+ if (qualifier.layoutBufferReference)
+ appendStr(" buffer_reference");
+ if (qualifier.hasBufferReferenceAlign()) {
+ appendStr(" buffer_reference_align=");
+ appendUint(1u << qualifier.layoutBufferReferenceAlign);
+ }
+
+ if (qualifier.layoutPassthrough)
+ appendStr(" passthrough");
+ if (qualifier.layoutViewportRelative)
+ appendStr(" layoutViewportRelative");
+ if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) {
+ appendStr(" layoutSecondaryViewportRelativeOffset=");
+ appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
+ }
+ if (qualifier.layoutShaderRecordNV)
+ appendStr(" shaderRecordNV");
+
+ appendStr(")");
+ }
+ }
+
+ if (qualifier.invariant)
+ appendStr(" invariant");
+ if (qualifier.noContraction)
+ appendStr(" noContraction");
+ if (qualifier.centroid)
+ appendStr(" centroid");
+ if (qualifier.smooth)
+ appendStr(" smooth");
+ if (qualifier.flat)
+ appendStr(" flat");
+ if (qualifier.nopersp)
+ appendStr(" noperspective");
+ if (qualifier.explicitInterp)
+ appendStr(" __explicitInterpAMD");
+ if (qualifier.pervertexNV)
+ appendStr(" pervertexNV");
+ if (qualifier.perPrimitiveNV)
+ appendStr(" perprimitiveNV");
+ if (qualifier.perViewNV)
+ appendStr(" perviewNV");
+ if (qualifier.perTaskNV)
+ appendStr(" taskNV");
+ if (qualifier.patch)
+ appendStr(" patch");
+ if (qualifier.sample)
+ appendStr(" sample");
+ if (qualifier.coherent)
+ appendStr(" coherent");
+ if (qualifier.devicecoherent)
+ appendStr(" devicecoherent");
+ if (qualifier.queuefamilycoherent)
+ appendStr(" queuefamilycoherent");
+ if (qualifier.workgroupcoherent)
+ appendStr(" workgroupcoherent");
+ if (qualifier.subgroupcoherent)
+ appendStr(" subgroupcoherent");
+ if (qualifier.nonprivate)
+ appendStr(" nonprivate");
+ if (qualifier.volatil)
+ appendStr(" volatile");
+ if (qualifier.restrict)
+ appendStr(" restrict");
+ if (qualifier.readonly)
+ appendStr(" readonly");
+ if (qualifier.writeonly)
+ appendStr(" writeonly");
+ if (qualifier.specConstant)
+ appendStr(" specialization-constant");
+ if (qualifier.nonUniform)
+ appendStr(" nonuniform");
+ appendStr(" ");
+ appendStr(getStorageQualifierString());
+ if (isArray()) {
+ for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
+ int size = arraySizes->getDimSize(i);
+ if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
+ appendStr(" runtime-sized array of");
+ else {
+ if (size == UnsizedArraySize) {
+ appendStr(" unsized");
+ if (i == 0) {
+ appendStr(" ");
+ appendInt(arraySizes->getImplicitSize());
+ }
+ } else {
+ appendStr(" ");
+ appendInt(arraySizes->getDimSize(i));
+ }
+ appendStr("-element array of");
+ }
+ }
+ }
+ if (isParameterized()) {
+ appendStr("<");
+ for(int i = 0; i < (int)typeParameters->getNumDims(); ++i) {
+ appendInt(typeParameters->getDimSize(i));
+ if (i != (int)typeParameters->getNumDims() - 1)
+ appendStr(", ");
+ }
+ appendStr(">");
+ }
+ if (qualifier.precision != EpqNone) {
+ appendStr(" ");
+ appendStr(getPrecisionQualifierString());
+ }
+ if (isMatrix()) {
+ appendStr(" ");
+ appendInt(matrixCols);
+ appendStr("X");
+ appendInt(matrixRows);
+ appendStr(" matrix of");
+ } else if (isVector()) {
+ appendStr(" ");
+ appendInt(vectorSize);
+ appendStr("-component vector of");
+ }
+
+ appendStr(" ");
+ typeString.append(getBasicTypeString());
+
+ if (qualifier.builtIn != EbvNone) {
+ appendStr(" ");
+ appendStr(getBuiltInVariableString());
+ }
+
+ // Add struct/block members
+ if (isStruct() && structure) {
+ appendStr("{");
+ bool hasHiddenMember = true;
+ for (size_t i = 0; i < structure->size(); ++i) {
+ if (! (*structure)[i].type->hiddenMember()) {
+ if (!hasHiddenMember)
+ appendStr(", ");
+ typeString.append((*structure)[i].type->getCompleteString());
+ typeString.append(" ");
+ typeString.append((*structure)[i].type->getFieldName());
+ hasHiddenMember = false;
+ }
+ }
+ appendStr("}");
+ }
+
+ return typeString;
+ }
+
+ TString getBasicTypeString() const
+ {
+ if (basicType == EbtSampler)
+ return sampler.getString();
+ else
+ return getBasicString();
+ }
+
+ const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); }
+ const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); }
+ const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); }
+#endif
+
+ const TTypeList* getStruct() const { assert(isStruct()); return structure; }
+ void setStruct(TTypeList* s) { assert(isStruct()); structure = s; }
+ TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads
+ void setBasicType(const TBasicType& t) { basicType = t; }
+
+ int computeNumComponents() const
+ {
+ int components = 0;
+
+ if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) {
+ for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
+ components += ((*tl).type)->computeNumComponents();
+ } else if (matrixCols)
+ components = matrixCols * matrixRows;
+ else
+ components = vectorSize;
+
+ if (arraySizes != nullptr) {
+ components *= arraySizes->getCumulativeSize();
+ }
+
+ return components;
+ }
+
+ // append this type's mangled name to the passed in 'name'
+ void appendMangledName(TString& name) const
+ {
+ buildMangledName(name);
+ name += ';' ;
+ }
+
+ // Do two structure types match? They could be declared independently,
+ // in different places, but still might satisfy the definition of matching.
+ // From the spec:
+ //
+ // "Structures must have the same name, sequence of type names, and
+ // type definitions, and member names to be considered the same type.
+ // This rule applies recursively for nested or embedded types."
+ //
+ bool sameStructType(const TType& right) const
+ {
+ // Most commonly, they are both nullptr, or the same pointer to the same actual structure
+ if ((!isStruct() && !right.isStruct()) ||
+ (isStruct() && right.isStruct() && structure == right.structure))
+ return true;
+
+ // Both being nullptr was caught above, now they both have to be structures of the same number of elements
+ if (!isStruct() || !right.isStruct() ||
+ structure->size() != right.structure->size())
+ return false;
+
+ // Structure names have to match
+ if (*typeName != *right.typeName)
+ return false;
+
+ // Compare the names and types of all the members, which have to match
+ for (unsigned int i = 0; i < structure->size(); ++i) {
+ if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName())
+ return false;
+
+ if (*(*structure)[i].type != *(*right.structure)[i].type)
+ return false;
+ }
+
+ return true;
+ }
+
+ bool sameReferenceType(const TType& right) const
+ {
+ if (isReference() != right.isReference())
+ return false;
+
+ if (!isReference() && !right.isReference())
+ return true;
+
+ assert(referentType != nullptr);
+ assert(right.referentType != nullptr);
+
+ if (referentType == right.referentType)
+ return true;
+
+ return *referentType == *right.referentType;
+ }
+
+ // See if two types match, in all aspects except arrayness
+ bool sameElementType(const TType& right) const
+ {
+ return basicType == right.basicType && sameElementShape(right);
+ }
+
+ // See if two type's arrayness match
+ bool sameArrayness(const TType& right) const
+ {
+ return ((arraySizes == nullptr && right.arraySizes == nullptr) ||
+ (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes));
+ }
+
+ // See if two type's arrayness match in everything except their outer dimension
+ bool sameInnerArrayness(const TType& right) const
+ {
+ assert(arraySizes != nullptr && right.arraySizes != nullptr);
+ return arraySizes->sameInnerArrayness(*right.arraySizes);
+ }
+
+ // See if two type's parameters match
+ bool sameTypeParameters(const TType& right) const
+ {
+ return ((typeParameters == nullptr && right.typeParameters == nullptr) ||
+ (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters));
+ }
+
+ // See if two type's elements match in all ways except basic type
+ bool sameElementShape(const TType& right) const
+ {
+ return sampler == right.sampler &&
+ vectorSize == right.vectorSize &&
+ matrixCols == right.matrixCols &&
+ matrixRows == right.matrixRows &&
+ vector1 == right.vector1 &&
+ isCoopMat() == right.isCoopMat() &&
+ sameStructType(right) &&
+ sameReferenceType(right);
+ }
+
+ // See if a cooperative matrix type parameter with unspecified parameters is
+ // an OK function parameter
+ bool coopMatParameterOK(const TType& right) const
+ {
+ return isCoopMat() && right.isCoopMat() && (getBasicType() == right.getBasicType()) &&
+ typeParameters == nullptr && right.typeParameters != nullptr;
+ }
+
+ bool sameCoopMatBaseType(const TType &right) const {
+ bool rv = coopmat && right.coopmat;
+ if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16)
+ rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16;
+ else if (getBasicType() == EbtUint || getBasicType() == EbtUint8)
+ rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8;
+ else if (getBasicType() == EbtInt || getBasicType() == EbtInt8)
+ rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8;
+ else
+ rv = false;
+ return rv;
+ }
+
+
+ // See if two types match in all ways (just the actual type, not qualification)
+ bool operator==(const TType& right) const
+ {
+ return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right);
+ }
+
+ bool operator!=(const TType& right) const
+ {
+ return ! operator==(right);
+ }
+
+ unsigned int getBufferReferenceAlignment() const
+ {
+#ifndef GLSLANG_WEB
+ if (getBasicType() == glslang::EbtReference) {
+ return getReferentType()->getQualifier().hasBufferReferenceAlign() ?
+ (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u;
+ }
+#endif
+ return 0;
+ }
+
+protected:
+ // Require consumer to pick between deep copy and shallow copy.
+ TType(const TType& type);
+ TType& operator=(const TType& type);
+
+ // Recursively copy a type graph, while preserving the graph-like
+ // quality. That is, don't make more than one copy of a structure that
+ // gets reused multiple times in the type graph.
+ void deepCopy(const TType& copyOf, TMap<TTypeList*,TTypeList*>& copiedMap)
+ {
+ shallowCopy(copyOf);
+
+ if (copyOf.arraySizes) {
+ arraySizes = new TArraySizes;
+ *arraySizes = *copyOf.arraySizes;
+ }
+
+ if (copyOf.typeParameters) {
+ typeParameters = new TArraySizes;
+ *typeParameters = *copyOf.typeParameters;
+ }
+
+ if (copyOf.isStruct() && copyOf.structure) {
+ auto prevCopy = copiedMap.find(copyOf.structure);
+ if (prevCopy != copiedMap.end())
+ structure = prevCopy->second;
+ else {
+ structure = new TTypeList;
+ copiedMap[copyOf.structure] = structure;
+ for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
+ TTypeLoc typeLoc;
+ typeLoc.loc = (*copyOf.structure)[i].loc;
+ typeLoc.type = new TType();
+ typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap);
+ structure->push_back(typeLoc);
+ }
+ }
+ }
+
+ if (copyOf.fieldName)
+ fieldName = NewPoolTString(copyOf.fieldName->c_str());
+ if (copyOf.typeName)
+ typeName = NewPoolTString(copyOf.typeName->c_str());
+ }
+
+
+ void buildMangledName(TString&) const;
+
+ TBasicType basicType : 8;
+ int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate.
+ int matrixCols : 4;
+ int matrixRows : 4;
+ bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar.
+ // GLSL 4.5 never has a 1-component vector; so this will always be false until such
+ // functionality is added.
+ // HLSL does have a 1-component vectors, so this will be true to disambiguate
+ // from a scalar.
+ bool coopmat : 1;
+ TQualifier qualifier;
+
+ TArraySizes* arraySizes; // nullptr unless an array; can be shared across types
+ // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so
+ // conserve space by making these a union
+ union {
+ TTypeList* structure; // invalid unless this is a struct; can be shared across types
+ TType *referentType; // invalid unless this is an EbtReference
+ };
+ TString *fieldName; // for structure field names
+ TString *typeName; // for structure type name
+ TSampler sampler;
+ TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types
+};
+
+} // end namespace glslang
+
+#endif // _TYPES_INCLUDED_
diff --git a/thirdparty/glslang/glslang/Include/arrays.h b/thirdparty/glslang/glslang/Include/arrays.h
new file mode 100644
index 0000000000..7f047d9fb1
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/arrays.h
@@ -0,0 +1,341 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2013 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Implement types for tracking GLSL arrays, arrays of arrays, etc.
+//
+
+#ifndef _ARRAYS_INCLUDED
+#define _ARRAYS_INCLUDED
+
+#include <algorithm>
+
+namespace glslang {
+
+// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else.
+const int UnsizedArraySize = 0;
+
+class TIntermTyped;
+extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*);
+
+// Specialization constants need both a nominal size and a node that defines
+// the specialization constant being used. Array types are the same when their
+// size and specialization constant nodes are the same.
+struct TArraySize {
+ unsigned int size;
+ TIntermTyped* node; // nullptr means no specialization constant node
+ bool operator==(const TArraySize& rhs) const
+ {
+ if (size != rhs.size)
+ return false;
+ if (node == nullptr || rhs.node == nullptr)
+ return node == rhs.node;
+
+ return SameSpecializationConstants(node, rhs.node);
+ }
+};
+
+//
+// TSmallArrayVector is used as the container for the set of sizes in TArraySizes.
+// It has generic-container semantics, while TArraySizes has array-of-array semantics.
+// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy.
+//
+struct TSmallArrayVector {
+ //
+ // TODO: memory: TSmallArrayVector is intended to be smaller.
+ // Almost all arrays could be handled by two sizes each fitting
+ // in 16 bits, needing a real vector only in the cases where there
+ // are more than 3 sizes or a size needing more than 16 bits.
+ //
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+ TSmallArrayVector() : sizes(nullptr) { }
+ virtual ~TSmallArrayVector() { dealloc(); }
+
+ // For breaking into two non-shared copies, independently modifiable.
+ TSmallArrayVector& operator=(const TSmallArrayVector& from)
+ {
+ if (from.sizes == nullptr)
+ sizes = nullptr;
+ else {
+ alloc();
+ *sizes = *from.sizes;
+ }
+
+ return *this;
+ }
+
+ int size() const
+ {
+ if (sizes == nullptr)
+ return 0;
+ return (int)sizes->size();
+ }
+
+ unsigned int frontSize() const
+ {
+ assert(sizes != nullptr && sizes->size() > 0);
+ return sizes->front().size;
+ }
+
+ TIntermTyped* frontNode() const
+ {
+ assert(sizes != nullptr && sizes->size() > 0);
+ return sizes->front().node;
+ }
+
+ void changeFront(unsigned int s)
+ {
+ assert(sizes != nullptr);
+ // this should only happen for implicitly sized arrays, not specialization constants
+ assert(sizes->front().node == nullptr);
+ sizes->front().size = s;
+ }
+
+ void push_back(unsigned int e, TIntermTyped* n)
+ {
+ alloc();
+ TArraySize pair = { e, n };
+ sizes->push_back(pair);
+ }
+
+ void push_back(const TSmallArrayVector& newDims)
+ {
+ alloc();
+ sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end());
+ }
+
+ void pop_front()
+ {
+ assert(sizes != nullptr && sizes->size() > 0);
+ if (sizes->size() == 1)
+ dealloc();
+ else
+ sizes->erase(sizes->begin());
+ }
+
+ // 'this' should currently not be holding anything, and copyNonFront
+ // will make it hold a copy of all but the first element of rhs.
+ // (This would be useful for making a type that is dereferenced by
+ // one dimension.)
+ void copyNonFront(const TSmallArrayVector& rhs)
+ {
+ assert(sizes == nullptr);
+ if (rhs.size() > 1) {
+ alloc();
+ sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end());
+ }
+ }
+
+ unsigned int getDimSize(int i) const
+ {
+ assert(sizes != nullptr && (int)sizes->size() > i);
+ return (*sizes)[i].size;
+ }
+
+ void setDimSize(int i, unsigned int size) const
+ {
+ assert(sizes != nullptr && (int)sizes->size() > i);
+ assert((*sizes)[i].node == nullptr);
+ (*sizes)[i].size = size;
+ }
+
+ TIntermTyped* getDimNode(int i) const
+ {
+ assert(sizes != nullptr && (int)sizes->size() > i);
+ return (*sizes)[i].node;
+ }
+
+ bool operator==(const TSmallArrayVector& rhs) const
+ {
+ if (sizes == nullptr && rhs.sizes == nullptr)
+ return true;
+ if (sizes == nullptr || rhs.sizes == nullptr)
+ return false;
+ return *sizes == *rhs.sizes;
+ }
+ bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); }
+
+protected:
+ TSmallArrayVector(const TSmallArrayVector&);
+
+ void alloc()
+ {
+ if (sizes == nullptr)
+ sizes = new TVector<TArraySize>;
+ }
+ void dealloc()
+ {
+ delete sizes;
+ sizes = nullptr;
+ }
+
+ TVector<TArraySize>* sizes; // will either hold such a pointer, or in the future, hold the two array sizes
+};
+
+//
+// Represent an array, or array of arrays, to arbitrary depth. This is not
+// done through a hierarchy of types in a type tree, rather all contiguous arrayness
+// in the type hierarchy is localized into this single cumulative object.
+//
+// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero
+// for the vast majority of types that are non-array types.
+//
+// Order Policy: these are all identical:
+// - left to right order within a contiguous set of ...[..][..][..]... in the source language
+// - index order 0, 1, 2, ... within the 'sizes' member below
+// - outer-most to inner-most
+//
+struct TArraySizes {
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+
+ TArraySizes() : implicitArraySize(1), variablyIndexed(false) { }
+
+ // For breaking into two non-shared copies, independently modifiable.
+ TArraySizes& operator=(const TArraySizes& from)
+ {
+ implicitArraySize = from.implicitArraySize;
+ variablyIndexed = from.variablyIndexed;
+ sizes = from.sizes;
+
+ return *this;
+ }
+
+ // translate from array-of-array semantics to container semantics
+ int getNumDims() const { return sizes.size(); }
+ int getDimSize(int dim) const { return sizes.getDimSize(dim); }
+ TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); }
+ void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); }
+ int getOuterSize() const { return sizes.frontSize(); }
+ TIntermTyped* getOuterNode() const { return sizes.frontNode(); }
+ int getCumulativeSize() const
+ {
+ int size = 1;
+ for (int d = 0; d < sizes.size(); ++d) {
+ // this only makes sense in paths that have a known array size
+ assert(sizes.getDimSize(d) != UnsizedArraySize);
+ size *= sizes.getDimSize(d);
+ }
+ return size;
+ }
+ void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); }
+ void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); }
+ void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); }
+ void addInnerSize(TArraySize pair) {
+ sizes.push_back(pair.size, pair.node);
+ }
+ void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); }
+ void changeOuterSize(int s) { sizes.changeFront((unsigned)s); }
+ int getImplicitSize() const { return implicitArraySize; }
+ void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); }
+ bool isInnerUnsized() const
+ {
+ for (int d = 1; d < sizes.size(); ++d) {
+ if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
+ return true;
+ }
+
+ return false;
+ }
+ bool clearInnerUnsized()
+ {
+ for (int d = 1; d < sizes.size(); ++d) {
+ if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
+ setDimSize(d, 1);
+ }
+
+ return false;
+ }
+ bool isInnerSpecialization() const
+ {
+ for (int d = 1; d < sizes.size(); ++d) {
+ if (sizes.getDimNode(d) != nullptr)
+ return true;
+ }
+
+ return false;
+ }
+ bool isOuterSpecialization()
+ {
+ return sizes.getDimNode(0) != nullptr;
+ }
+
+ bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); }
+ bool isSized() const { return getOuterSize() != UnsizedArraySize; }
+ void dereference() { sizes.pop_front(); }
+ void copyDereferenced(const TArraySizes& rhs)
+ {
+ assert(sizes.size() == 0);
+ if (rhs.sizes.size() > 1)
+ sizes.copyNonFront(rhs.sizes);
+ }
+
+ bool sameInnerArrayness(const TArraySizes& rhs) const
+ {
+ if (sizes.size() != rhs.sizes.size())
+ return false;
+
+ for (int d = 1; d < sizes.size(); ++d) {
+ if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) ||
+ sizes.getDimNode(d) != rhs.sizes.getDimNode(d))
+ return false;
+ }
+
+ return true;
+ }
+
+ void setVariablyIndexed() { variablyIndexed = true; }
+ bool isVariablyIndexed() const { return variablyIndexed; }
+
+ bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; }
+ bool operator!=(const TArraySizes& rhs) const { return sizes != rhs.sizes; }
+
+protected:
+ TSmallArrayVector sizes;
+
+ TArraySizes(const TArraySizes&);
+
+ // For tracking maximum referenced compile-time constant index.
+ // Applies only to the outer-most dimension. Potentially becomes
+ // the implicit size of the array, if not variably indexed and
+ // otherwise legal.
+ int implicitArraySize;
+ bool variablyIndexed; // true if array is indexed with a non compile-time constant
+};
+
+} // end namespace glslang
+
+#endif // _ARRAYS_INCLUDED_
diff --git a/thirdparty/glslang/glslang/Include/intermediate.h b/thirdparty/glslang/glslang/Include/intermediate.h
new file mode 100644
index 0000000000..29d58ca635
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/intermediate.h
@@ -0,0 +1,1773 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2016 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Definition of the in-memory high-level intermediate representation
+// of shaders. This is a tree that parser creates.
+//
+// Nodes in the tree are defined as a hierarchy of classes derived from
+// TIntermNode. Each is a node in a tree. There is no preset branching factor;
+// each node can have it's own type of list of children.
+//
+
+#ifndef __INTERMEDIATE_H
+#define __INTERMEDIATE_H
+
+#if defined(_MSC_VER) && _MSC_VER >= 1900
+ #pragma warning(disable : 4464) // relative include path contains '..'
+ #pragma warning(disable : 5026) // 'glslang::TIntermUnary': move constructor was implicitly defined as deleted
+#endif
+
+#include "../Include/Common.h"
+#include "../Include/Types.h"
+#include "../Include/ConstantUnion.h"
+
+namespace glslang {
+
+class TIntermediate;
+
+//
+// Operators used by the high-level (parse tree) representation.
+//
+enum TOperator {
+ EOpNull, // if in a node, should only mean a node is still being built
+ EOpSequence, // denotes a list of statements, or parameters, etc.
+ EOpLinkerObjects, // for aggregate node of objects the linker may need, if not reference by the rest of the AST
+ EOpFunctionCall,
+ EOpFunction, // For function definition
+ EOpParameters, // an aggregate listing the parameters to a function
+
+ //
+ // Unary operators
+ //
+
+ EOpNegative,
+ EOpLogicalNot,
+ EOpVectorLogicalNot,
+ EOpBitwiseNot,
+
+ EOpPostIncrement,
+ EOpPostDecrement,
+ EOpPreIncrement,
+ EOpPreDecrement,
+
+ EOpCopyObject,
+
+ // (u)int* -> bool
+ EOpConvInt8ToBool,
+ EOpConvUint8ToBool,
+ EOpConvInt16ToBool,
+ EOpConvUint16ToBool,
+ EOpConvIntToBool,
+ EOpConvUintToBool,
+ EOpConvInt64ToBool,
+ EOpConvUint64ToBool,
+
+ // float* -> bool
+ EOpConvFloat16ToBool,
+ EOpConvFloatToBool,
+ EOpConvDoubleToBool,
+
+ // bool -> (u)int*
+ EOpConvBoolToInt8,
+ EOpConvBoolToUint8,
+ EOpConvBoolToInt16,
+ EOpConvBoolToUint16,
+ EOpConvBoolToInt,
+ EOpConvBoolToUint,
+ EOpConvBoolToInt64,
+ EOpConvBoolToUint64,
+
+ // bool -> float*
+ EOpConvBoolToFloat16,
+ EOpConvBoolToFloat,
+ EOpConvBoolToDouble,
+
+ // int8_t -> (u)int*
+ EOpConvInt8ToInt16,
+ EOpConvInt8ToInt,
+ EOpConvInt8ToInt64,
+ EOpConvInt8ToUint8,
+ EOpConvInt8ToUint16,
+ EOpConvInt8ToUint,
+ EOpConvInt8ToUint64,
+
+ // uint8_t -> (u)int*
+ EOpConvUint8ToInt8,
+ EOpConvUint8ToInt16,
+ EOpConvUint8ToInt,
+ EOpConvUint8ToInt64,
+ EOpConvUint8ToUint16,
+ EOpConvUint8ToUint,
+ EOpConvUint8ToUint64,
+
+ // int8_t -> float*
+ EOpConvInt8ToFloat16,
+ EOpConvInt8ToFloat,
+ EOpConvInt8ToDouble,
+
+ // uint8_t -> float*
+ EOpConvUint8ToFloat16,
+ EOpConvUint8ToFloat,
+ EOpConvUint8ToDouble,
+
+ // int16_t -> (u)int*
+ EOpConvInt16ToInt8,
+ EOpConvInt16ToInt,
+ EOpConvInt16ToInt64,
+ EOpConvInt16ToUint8,
+ EOpConvInt16ToUint16,
+ EOpConvInt16ToUint,
+ EOpConvInt16ToUint64,
+
+ // uint16_t -> (u)int*
+ EOpConvUint16ToInt8,
+ EOpConvUint16ToInt16,
+ EOpConvUint16ToInt,
+ EOpConvUint16ToInt64,
+ EOpConvUint16ToUint8,
+ EOpConvUint16ToUint,
+ EOpConvUint16ToUint64,
+
+ // int16_t -> float*
+ EOpConvInt16ToFloat16,
+ EOpConvInt16ToFloat,
+ EOpConvInt16ToDouble,
+
+ // uint16_t -> float*
+ EOpConvUint16ToFloat16,
+ EOpConvUint16ToFloat,
+ EOpConvUint16ToDouble,
+
+ // int32_t -> (u)int*
+ EOpConvIntToInt8,
+ EOpConvIntToInt16,
+ EOpConvIntToInt64,
+ EOpConvIntToUint8,
+ EOpConvIntToUint16,
+ EOpConvIntToUint,
+ EOpConvIntToUint64,
+
+ // uint32_t -> (u)int*
+ EOpConvUintToInt8,
+ EOpConvUintToInt16,
+ EOpConvUintToInt,
+ EOpConvUintToInt64,
+ EOpConvUintToUint8,
+ EOpConvUintToUint16,
+ EOpConvUintToUint64,
+
+ // int32_t -> float*
+ EOpConvIntToFloat16,
+ EOpConvIntToFloat,
+ EOpConvIntToDouble,
+
+ // uint32_t -> float*
+ EOpConvUintToFloat16,
+ EOpConvUintToFloat,
+ EOpConvUintToDouble,
+
+ // int64_t -> (u)int*
+ EOpConvInt64ToInt8,
+ EOpConvInt64ToInt16,
+ EOpConvInt64ToInt,
+ EOpConvInt64ToUint8,
+ EOpConvInt64ToUint16,
+ EOpConvInt64ToUint,
+ EOpConvInt64ToUint64,
+
+ // uint64_t -> (u)int*
+ EOpConvUint64ToInt8,
+ EOpConvUint64ToInt16,
+ EOpConvUint64ToInt,
+ EOpConvUint64ToInt64,
+ EOpConvUint64ToUint8,
+ EOpConvUint64ToUint16,
+ EOpConvUint64ToUint,
+
+ // int64_t -> float*
+ EOpConvInt64ToFloat16,
+ EOpConvInt64ToFloat,
+ EOpConvInt64ToDouble,
+
+ // uint64_t -> float*
+ EOpConvUint64ToFloat16,
+ EOpConvUint64ToFloat,
+ EOpConvUint64ToDouble,
+
+ // float16_t -> (u)int*
+ EOpConvFloat16ToInt8,
+ EOpConvFloat16ToInt16,
+ EOpConvFloat16ToInt,
+ EOpConvFloat16ToInt64,
+ EOpConvFloat16ToUint8,
+ EOpConvFloat16ToUint16,
+ EOpConvFloat16ToUint,
+ EOpConvFloat16ToUint64,
+
+ // float16_t -> float*
+ EOpConvFloat16ToFloat,
+ EOpConvFloat16ToDouble,
+
+ // float -> (u)int*
+ EOpConvFloatToInt8,
+ EOpConvFloatToInt16,
+ EOpConvFloatToInt,
+ EOpConvFloatToInt64,
+ EOpConvFloatToUint8,
+ EOpConvFloatToUint16,
+ EOpConvFloatToUint,
+ EOpConvFloatToUint64,
+
+ // float -> float*
+ EOpConvFloatToFloat16,
+ EOpConvFloatToDouble,
+
+ // float64 _t-> (u)int*
+ EOpConvDoubleToInt8,
+ EOpConvDoubleToInt16,
+ EOpConvDoubleToInt,
+ EOpConvDoubleToInt64,
+ EOpConvDoubleToUint8,
+ EOpConvDoubleToUint16,
+ EOpConvDoubleToUint,
+ EOpConvDoubleToUint64,
+
+ // float64_t -> float*
+ EOpConvDoubleToFloat16,
+ EOpConvDoubleToFloat,
+
+ // uint64_t <-> pointer
+ EOpConvUint64ToPtr,
+ EOpConvPtrToUint64,
+
+ // uvec2 <-> pointer
+ EOpConvUvec2ToPtr,
+ EOpConvPtrToUvec2,
+
+ //
+ // binary operations
+ //
+
+ EOpAdd,
+ EOpSub,
+ EOpMul,
+ EOpDiv,
+ EOpMod,
+ EOpRightShift,
+ EOpLeftShift,
+ EOpAnd,
+ EOpInclusiveOr,
+ EOpExclusiveOr,
+ EOpEqual,
+ EOpNotEqual,
+ EOpVectorEqual,
+ EOpVectorNotEqual,
+ EOpLessThan,
+ EOpGreaterThan,
+ EOpLessThanEqual,
+ EOpGreaterThanEqual,
+ EOpComma,
+
+ EOpVectorTimesScalar,
+ EOpVectorTimesMatrix,
+ EOpMatrixTimesVector,
+ EOpMatrixTimesScalar,
+
+ EOpLogicalOr,
+ EOpLogicalXor,
+ EOpLogicalAnd,
+
+ EOpIndexDirect,
+ EOpIndexIndirect,
+ EOpIndexDirectStruct,
+
+ EOpVectorSwizzle,
+
+ EOpMethod,
+ EOpScoping,
+
+ //
+ // Built-in functions mapped to operators
+ //
+
+ EOpRadians,
+ EOpDegrees,
+ EOpSin,
+ EOpCos,
+ EOpTan,
+ EOpAsin,
+ EOpAcos,
+ EOpAtan,
+ EOpSinh,
+ EOpCosh,
+ EOpTanh,
+ EOpAsinh,
+ EOpAcosh,
+ EOpAtanh,
+
+ EOpPow,
+ EOpExp,
+ EOpLog,
+ EOpExp2,
+ EOpLog2,
+ EOpSqrt,
+ EOpInverseSqrt,
+
+ EOpAbs,
+ EOpSign,
+ EOpFloor,
+ EOpTrunc,
+ EOpRound,
+ EOpRoundEven,
+ EOpCeil,
+ EOpFract,
+ EOpModf,
+ EOpMin,
+ EOpMax,
+ EOpClamp,
+ EOpMix,
+ EOpStep,
+ EOpSmoothStep,
+
+ EOpIsNan,
+ EOpIsInf,
+
+ EOpFma,
+
+ EOpFrexp,
+ EOpLdexp,
+
+ EOpFloatBitsToInt,
+ EOpFloatBitsToUint,
+ EOpIntBitsToFloat,
+ EOpUintBitsToFloat,
+ EOpDoubleBitsToInt64,
+ EOpDoubleBitsToUint64,
+ EOpInt64BitsToDouble,
+ EOpUint64BitsToDouble,
+ EOpFloat16BitsToInt16,
+ EOpFloat16BitsToUint16,
+ EOpInt16BitsToFloat16,
+ EOpUint16BitsToFloat16,
+ EOpPackSnorm2x16,
+ EOpUnpackSnorm2x16,
+ EOpPackUnorm2x16,
+ EOpUnpackUnorm2x16,
+ EOpPackSnorm4x8,
+ EOpUnpackSnorm4x8,
+ EOpPackUnorm4x8,
+ EOpUnpackUnorm4x8,
+ EOpPackHalf2x16,
+ EOpUnpackHalf2x16,
+ EOpPackDouble2x32,
+ EOpUnpackDouble2x32,
+ EOpPackInt2x32,
+ EOpUnpackInt2x32,
+ EOpPackUint2x32,
+ EOpUnpackUint2x32,
+ EOpPackFloat2x16,
+ EOpUnpackFloat2x16,
+ EOpPackInt2x16,
+ EOpUnpackInt2x16,
+ EOpPackUint2x16,
+ EOpUnpackUint2x16,
+ EOpPackInt4x16,
+ EOpUnpackInt4x16,
+ EOpPackUint4x16,
+ EOpUnpackUint4x16,
+ EOpPack16,
+ EOpPack32,
+ EOpPack64,
+ EOpUnpack32,
+ EOpUnpack16,
+ EOpUnpack8,
+
+ EOpLength,
+ EOpDistance,
+ EOpDot,
+ EOpCross,
+ EOpNormalize,
+ EOpFaceForward,
+ EOpReflect,
+ EOpRefract,
+
+ EOpMin3,
+ EOpMax3,
+ EOpMid3,
+
+ EOpDPdx, // Fragment only
+ EOpDPdy, // Fragment only
+ EOpFwidth, // Fragment only
+ EOpDPdxFine, // Fragment only
+ EOpDPdyFine, // Fragment only
+ EOpFwidthFine, // Fragment only
+ EOpDPdxCoarse, // Fragment only
+ EOpDPdyCoarse, // Fragment only
+ EOpFwidthCoarse, // Fragment only
+
+ EOpInterpolateAtCentroid, // Fragment only
+ EOpInterpolateAtSample, // Fragment only
+ EOpInterpolateAtOffset, // Fragment only
+ EOpInterpolateAtVertex,
+
+ EOpMatrixTimesMatrix,
+ EOpOuterProduct,
+ EOpDeterminant,
+ EOpMatrixInverse,
+ EOpTranspose,
+
+ EOpFtransform,
+
+ EOpNoise,
+
+ EOpEmitVertex, // geometry only
+ EOpEndPrimitive, // geometry only
+ EOpEmitStreamVertex, // geometry only
+ EOpEndStreamPrimitive, // geometry only
+
+ EOpBarrier,
+ EOpMemoryBarrier,
+ EOpMemoryBarrierAtomicCounter,
+ EOpMemoryBarrierBuffer,
+ EOpMemoryBarrierImage,
+ EOpMemoryBarrierShared, // compute only
+ EOpGroupMemoryBarrier, // compute only
+
+ EOpBallot,
+ EOpReadInvocation,
+ EOpReadFirstInvocation,
+
+ EOpAnyInvocation,
+ EOpAllInvocations,
+ EOpAllInvocationsEqual,
+
+ EOpSubgroupGuardStart,
+ EOpSubgroupBarrier,
+ EOpSubgroupMemoryBarrier,
+ EOpSubgroupMemoryBarrierBuffer,
+ EOpSubgroupMemoryBarrierImage,
+ EOpSubgroupMemoryBarrierShared, // compute only
+ EOpSubgroupElect,
+ EOpSubgroupAll,
+ EOpSubgroupAny,
+ EOpSubgroupAllEqual,
+ EOpSubgroupBroadcast,
+ EOpSubgroupBroadcastFirst,
+ EOpSubgroupBallot,
+ EOpSubgroupInverseBallot,
+ EOpSubgroupBallotBitExtract,
+ EOpSubgroupBallotBitCount,
+ EOpSubgroupBallotInclusiveBitCount,
+ EOpSubgroupBallotExclusiveBitCount,
+ EOpSubgroupBallotFindLSB,
+ EOpSubgroupBallotFindMSB,
+ EOpSubgroupShuffle,
+ EOpSubgroupShuffleXor,
+ EOpSubgroupShuffleUp,
+ EOpSubgroupShuffleDown,
+ EOpSubgroupAdd,
+ EOpSubgroupMul,
+ EOpSubgroupMin,
+ EOpSubgroupMax,
+ EOpSubgroupAnd,
+ EOpSubgroupOr,
+ EOpSubgroupXor,
+ EOpSubgroupInclusiveAdd,
+ EOpSubgroupInclusiveMul,
+ EOpSubgroupInclusiveMin,
+ EOpSubgroupInclusiveMax,
+ EOpSubgroupInclusiveAnd,
+ EOpSubgroupInclusiveOr,
+ EOpSubgroupInclusiveXor,
+ EOpSubgroupExclusiveAdd,
+ EOpSubgroupExclusiveMul,
+ EOpSubgroupExclusiveMin,
+ EOpSubgroupExclusiveMax,
+ EOpSubgroupExclusiveAnd,
+ EOpSubgroupExclusiveOr,
+ EOpSubgroupExclusiveXor,
+ EOpSubgroupClusteredAdd,
+ EOpSubgroupClusteredMul,
+ EOpSubgroupClusteredMin,
+ EOpSubgroupClusteredMax,
+ EOpSubgroupClusteredAnd,
+ EOpSubgroupClusteredOr,
+ EOpSubgroupClusteredXor,
+ EOpSubgroupQuadBroadcast,
+ EOpSubgroupQuadSwapHorizontal,
+ EOpSubgroupQuadSwapVertical,
+ EOpSubgroupQuadSwapDiagonal,
+
+ EOpSubgroupPartition,
+ EOpSubgroupPartitionedAdd,
+ EOpSubgroupPartitionedMul,
+ EOpSubgroupPartitionedMin,
+ EOpSubgroupPartitionedMax,
+ EOpSubgroupPartitionedAnd,
+ EOpSubgroupPartitionedOr,
+ EOpSubgroupPartitionedXor,
+ EOpSubgroupPartitionedInclusiveAdd,
+ EOpSubgroupPartitionedInclusiveMul,
+ EOpSubgroupPartitionedInclusiveMin,
+ EOpSubgroupPartitionedInclusiveMax,
+ EOpSubgroupPartitionedInclusiveAnd,
+ EOpSubgroupPartitionedInclusiveOr,
+ EOpSubgroupPartitionedInclusiveXor,
+ EOpSubgroupPartitionedExclusiveAdd,
+ EOpSubgroupPartitionedExclusiveMul,
+ EOpSubgroupPartitionedExclusiveMin,
+ EOpSubgroupPartitionedExclusiveMax,
+ EOpSubgroupPartitionedExclusiveAnd,
+ EOpSubgroupPartitionedExclusiveOr,
+ EOpSubgroupPartitionedExclusiveXor,
+
+ EOpSubgroupGuardStop,
+
+ EOpMinInvocations,
+ EOpMaxInvocations,
+ EOpAddInvocations,
+ EOpMinInvocationsNonUniform,
+ EOpMaxInvocationsNonUniform,
+ EOpAddInvocationsNonUniform,
+ EOpMinInvocationsInclusiveScan,
+ EOpMaxInvocationsInclusiveScan,
+ EOpAddInvocationsInclusiveScan,
+ EOpMinInvocationsInclusiveScanNonUniform,
+ EOpMaxInvocationsInclusiveScanNonUniform,
+ EOpAddInvocationsInclusiveScanNonUniform,
+ EOpMinInvocationsExclusiveScan,
+ EOpMaxInvocationsExclusiveScan,
+ EOpAddInvocationsExclusiveScan,
+ EOpMinInvocationsExclusiveScanNonUniform,
+ EOpMaxInvocationsExclusiveScanNonUniform,
+ EOpAddInvocationsExclusiveScanNonUniform,
+ EOpSwizzleInvocations,
+ EOpSwizzleInvocationsMasked,
+ EOpWriteInvocation,
+ EOpMbcnt,
+
+ EOpCubeFaceIndex,
+ EOpCubeFaceCoord,
+ EOpTime,
+
+ EOpAtomicAdd,
+ EOpAtomicMin,
+ EOpAtomicMax,
+ EOpAtomicAnd,
+ EOpAtomicOr,
+ EOpAtomicXor,
+ EOpAtomicExchange,
+ EOpAtomicCompSwap,
+ EOpAtomicLoad,
+ EOpAtomicStore,
+
+ EOpAtomicCounterIncrement, // results in pre-increment value
+ EOpAtomicCounterDecrement, // results in post-decrement value
+ EOpAtomicCounter,
+ EOpAtomicCounterAdd,
+ EOpAtomicCounterSubtract,
+ EOpAtomicCounterMin,
+ EOpAtomicCounterMax,
+ EOpAtomicCounterAnd,
+ EOpAtomicCounterOr,
+ EOpAtomicCounterXor,
+ EOpAtomicCounterExchange,
+ EOpAtomicCounterCompSwap,
+
+ EOpAny,
+ EOpAll,
+
+ EOpCooperativeMatrixLoad,
+ EOpCooperativeMatrixStore,
+ EOpCooperativeMatrixMulAdd,
+
+ EOpBeginInvocationInterlock, // Fragment only
+ EOpEndInvocationInterlock, // Fragment only
+
+ EOpIsHelperInvocation,
+
+ //
+ // Branch
+ //
+
+ EOpKill, // Fragment only
+ EOpReturn,
+ EOpBreak,
+ EOpContinue,
+ EOpCase,
+ EOpDefault,
+ EOpDemote, // Fragment only
+
+ //
+ // Constructors
+ //
+
+ EOpConstructGuardStart,
+ EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed
+ EOpConstructUint,
+ EOpConstructInt8,
+ EOpConstructUint8,
+ EOpConstructInt16,
+ EOpConstructUint16,
+ EOpConstructInt64,
+ EOpConstructUint64,
+ EOpConstructBool,
+ EOpConstructFloat,
+ EOpConstructDouble,
+ // Keep vector and matrix constructors in a consistent relative order for
+ // TParseContext::constructBuiltIn, which converts between 8/16/32 bit
+ // vector constructors
+ EOpConstructVec2,
+ EOpConstructVec3,
+ EOpConstructVec4,
+ EOpConstructMat2x2,
+ EOpConstructMat2x3,
+ EOpConstructMat2x4,
+ EOpConstructMat3x2,
+ EOpConstructMat3x3,
+ EOpConstructMat3x4,
+ EOpConstructMat4x2,
+ EOpConstructMat4x3,
+ EOpConstructMat4x4,
+ EOpConstructDVec2,
+ EOpConstructDVec3,
+ EOpConstructDVec4,
+ EOpConstructBVec2,
+ EOpConstructBVec3,
+ EOpConstructBVec4,
+ EOpConstructI8Vec2,
+ EOpConstructI8Vec3,
+ EOpConstructI8Vec4,
+ EOpConstructU8Vec2,
+ EOpConstructU8Vec3,
+ EOpConstructU8Vec4,
+ EOpConstructI16Vec2,
+ EOpConstructI16Vec3,
+ EOpConstructI16Vec4,
+ EOpConstructU16Vec2,
+ EOpConstructU16Vec3,
+ EOpConstructU16Vec4,
+ EOpConstructIVec2,
+ EOpConstructIVec3,
+ EOpConstructIVec4,
+ EOpConstructUVec2,
+ EOpConstructUVec3,
+ EOpConstructUVec4,
+ EOpConstructI64Vec2,
+ EOpConstructI64Vec3,
+ EOpConstructI64Vec4,
+ EOpConstructU64Vec2,
+ EOpConstructU64Vec3,
+ EOpConstructU64Vec4,
+ EOpConstructDMat2x2,
+ EOpConstructDMat2x3,
+ EOpConstructDMat2x4,
+ EOpConstructDMat3x2,
+ EOpConstructDMat3x3,
+ EOpConstructDMat3x4,
+ EOpConstructDMat4x2,
+ EOpConstructDMat4x3,
+ EOpConstructDMat4x4,
+ EOpConstructIMat2x2,
+ EOpConstructIMat2x3,
+ EOpConstructIMat2x4,
+ EOpConstructIMat3x2,
+ EOpConstructIMat3x3,
+ EOpConstructIMat3x4,
+ EOpConstructIMat4x2,
+ EOpConstructIMat4x3,
+ EOpConstructIMat4x4,
+ EOpConstructUMat2x2,
+ EOpConstructUMat2x3,
+ EOpConstructUMat2x4,
+ EOpConstructUMat3x2,
+ EOpConstructUMat3x3,
+ EOpConstructUMat3x4,
+ EOpConstructUMat4x2,
+ EOpConstructUMat4x3,
+ EOpConstructUMat4x4,
+ EOpConstructBMat2x2,
+ EOpConstructBMat2x3,
+ EOpConstructBMat2x4,
+ EOpConstructBMat3x2,
+ EOpConstructBMat3x3,
+ EOpConstructBMat3x4,
+ EOpConstructBMat4x2,
+ EOpConstructBMat4x3,
+ EOpConstructBMat4x4,
+ EOpConstructFloat16,
+ EOpConstructF16Vec2,
+ EOpConstructF16Vec3,
+ EOpConstructF16Vec4,
+ EOpConstructF16Mat2x2,
+ EOpConstructF16Mat2x3,
+ EOpConstructF16Mat2x4,
+ EOpConstructF16Mat3x2,
+ EOpConstructF16Mat3x3,
+ EOpConstructF16Mat3x4,
+ EOpConstructF16Mat4x2,
+ EOpConstructF16Mat4x3,
+ EOpConstructF16Mat4x4,
+ EOpConstructStruct,
+ EOpConstructTextureSampler,
+ EOpConstructNonuniform, // expected to be transformed away, not present in final AST
+ EOpConstructReference,
+ EOpConstructCooperativeMatrix,
+ EOpConstructGuardEnd,
+
+ //
+ // moves
+ //
+
+ EOpAssign,
+ EOpAddAssign,
+ EOpSubAssign,
+ EOpMulAssign,
+ EOpVectorTimesMatrixAssign,
+ EOpVectorTimesScalarAssign,
+ EOpMatrixTimesScalarAssign,
+ EOpMatrixTimesMatrixAssign,
+ EOpDivAssign,
+ EOpModAssign,
+ EOpAndAssign,
+ EOpInclusiveOrAssign,
+ EOpExclusiveOrAssign,
+ EOpLeftShiftAssign,
+ EOpRightShiftAssign,
+
+ //
+ // Array operators
+ //
+
+ // Can apply to arrays, vectors, or matrices.
+ // Can be decomposed to a constant at compile time, but this does not always happen,
+ // due to link-time effects. So, consumer can expect either a link-time sized or
+ // run-time sized array.
+ EOpArrayLength,
+
+ //
+ // Image operations
+ //
+
+ EOpImageGuardBegin,
+
+ EOpImageQuerySize,
+ EOpImageQuerySamples,
+ EOpImageLoad,
+ EOpImageStore,
+ EOpImageLoadLod,
+ EOpImageStoreLod,
+ EOpImageAtomicAdd,
+ EOpImageAtomicMin,
+ EOpImageAtomicMax,
+ EOpImageAtomicAnd,
+ EOpImageAtomicOr,
+ EOpImageAtomicXor,
+ EOpImageAtomicExchange,
+ EOpImageAtomicCompSwap,
+ EOpImageAtomicLoad,
+ EOpImageAtomicStore,
+
+ EOpSubpassLoad,
+ EOpSubpassLoadMS,
+ EOpSparseImageLoad,
+ EOpSparseImageLoadLod,
+
+ EOpImageGuardEnd,
+
+ //
+ // Texture operations
+ //
+
+ EOpTextureGuardBegin,
+
+ EOpTextureQuerySize,
+ EOpTextureQueryLod,
+ EOpTextureQueryLevels,
+ EOpTextureQuerySamples,
+
+ EOpSamplingGuardBegin,
+
+ EOpTexture,
+ EOpTextureProj,
+ EOpTextureLod,
+ EOpTextureOffset,
+ EOpTextureFetch,
+ EOpTextureFetchOffset,
+ EOpTextureProjOffset,
+ EOpTextureLodOffset,
+ EOpTextureProjLod,
+ EOpTextureProjLodOffset,
+ EOpTextureGrad,
+ EOpTextureGradOffset,
+ EOpTextureProjGrad,
+ EOpTextureProjGradOffset,
+ EOpTextureGather,
+ EOpTextureGatherOffset,
+ EOpTextureGatherOffsets,
+ EOpTextureClamp,
+ EOpTextureOffsetClamp,
+ EOpTextureGradClamp,
+ EOpTextureGradOffsetClamp,
+ EOpTextureGatherLod,
+ EOpTextureGatherLodOffset,
+ EOpTextureGatherLodOffsets,
+ EOpFragmentMaskFetch,
+ EOpFragmentFetch,
+
+ EOpSparseTextureGuardBegin,
+
+ EOpSparseTexture,
+ EOpSparseTextureLod,
+ EOpSparseTextureOffset,
+ EOpSparseTextureFetch,
+ EOpSparseTextureFetchOffset,
+ EOpSparseTextureLodOffset,
+ EOpSparseTextureGrad,
+ EOpSparseTextureGradOffset,
+ EOpSparseTextureGather,
+ EOpSparseTextureGatherOffset,
+ EOpSparseTextureGatherOffsets,
+ EOpSparseTexelsResident,
+ EOpSparseTextureClamp,
+ EOpSparseTextureOffsetClamp,
+ EOpSparseTextureGradClamp,
+ EOpSparseTextureGradOffsetClamp,
+ EOpSparseTextureGatherLod,
+ EOpSparseTextureGatherLodOffset,
+ EOpSparseTextureGatherLodOffsets,
+
+ EOpSparseTextureGuardEnd,
+
+ EOpImageFootprintGuardBegin,
+ EOpImageSampleFootprintNV,
+ EOpImageSampleFootprintClampNV,
+ EOpImageSampleFootprintLodNV,
+ EOpImageSampleFootprintGradNV,
+ EOpImageSampleFootprintGradClampNV,
+ EOpImageFootprintGuardEnd,
+ EOpSamplingGuardEnd,
+ EOpTextureGuardEnd,
+
+ //
+ // Integer operations
+ //
+
+ EOpAddCarry,
+ EOpSubBorrow,
+ EOpUMulExtended,
+ EOpIMulExtended,
+ EOpBitfieldExtract,
+ EOpBitfieldInsert,
+ EOpBitFieldReverse,
+ EOpBitCount,
+ EOpFindLSB,
+ EOpFindMSB,
+
+ EOpCountLeadingZeros,
+ EOpCountTrailingZeros,
+ EOpAbsDifference,
+ EOpAddSaturate,
+ EOpSubSaturate,
+ EOpAverage,
+ EOpAverageRounded,
+ EOpMul32x16,
+
+ EOpTraceNV,
+ EOpReportIntersectionNV,
+ EOpIgnoreIntersectionNV,
+ EOpTerminateRayNV,
+ EOpExecuteCallableNV,
+ EOpWritePackedPrimitiveIndices4x8NV,
+ //
+ // HLSL operations
+ //
+
+ EOpClip, // discard if input value < 0
+ EOpIsFinite,
+ EOpLog10, // base 10 log
+ EOpRcp, // 1/x
+ EOpSaturate, // clamp from 0 to 1
+ EOpSinCos, // sin and cos in out parameters
+ EOpGenMul, // mul(x,y) on any of mat/vec/scalars
+ EOpDst, // x = 1, y=src0.y * src1.y, z=src0.z, w=src1.w
+ EOpInterlockedAdd, // atomic ops, but uses [optional] out arg instead of return
+ EOpInterlockedAnd, // ...
+ EOpInterlockedCompareExchange, // ...
+ EOpInterlockedCompareStore, // ...
+ EOpInterlockedExchange, // ...
+ EOpInterlockedMax, // ...
+ EOpInterlockedMin, // ...
+ EOpInterlockedOr, // ...
+ EOpInterlockedXor, // ...
+ EOpAllMemoryBarrierWithGroupSync, // memory barriers without non-hlsl AST equivalents
+ EOpDeviceMemoryBarrier, // ...
+ EOpDeviceMemoryBarrierWithGroupSync, // ...
+ EOpWorkgroupMemoryBarrier, // ...
+ EOpWorkgroupMemoryBarrierWithGroupSync, // ...
+ EOpEvaluateAttributeSnapped, // InterpolateAtOffset with int position on 16x16 grid
+ EOpF32tof16, // HLSL conversion: half of a PackHalf2x16
+ EOpF16tof32, // HLSL conversion: half of an UnpackHalf2x16
+ EOpLit, // HLSL lighting coefficient vector
+ EOpTextureBias, // HLSL texture bias: will be lowered to EOpTexture
+ EOpAsDouble, // slightly different from EOpUint64BitsToDouble
+ EOpD3DCOLORtoUBYTE4, // convert and swizzle 4-component color to UBYTE4 range
+
+ EOpMethodSample, // Texture object methods. These are translated to existing
+ EOpMethodSampleBias, // AST methods, and exist to represent HLSL semantics until that
+ EOpMethodSampleCmp, // translation is performed. See HlslParseContext::decomposeSampleMethods().
+ EOpMethodSampleCmpLevelZero, // ...
+ EOpMethodSampleGrad, // ...
+ EOpMethodSampleLevel, // ...
+ EOpMethodLoad, // ...
+ EOpMethodGetDimensions, // ...
+ EOpMethodGetSamplePosition, // ...
+ EOpMethodGather, // ...
+ EOpMethodCalculateLevelOfDetail, // ...
+ EOpMethodCalculateLevelOfDetailUnclamped, // ...
+
+ // Load already defined above for textures
+ EOpMethodLoad2, // Structure buffer object methods. These are translated to existing
+ EOpMethodLoad3, // AST methods, and exist to represent HLSL semantics until that
+ EOpMethodLoad4, // translation is performed. See HlslParseContext::decomposeSampleMethods().
+ EOpMethodStore, // ...
+ EOpMethodStore2, // ...
+ EOpMethodStore3, // ...
+ EOpMethodStore4, // ...
+ EOpMethodIncrementCounter, // ...
+ EOpMethodDecrementCounter, // ...
+ // EOpMethodAppend is defined for geo shaders below
+ EOpMethodConsume,
+
+ // SM5 texture methods
+ EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about
+ EOpMethodGatherGreen, // translation to existing AST opcodes. They exist temporarily
+ EOpMethodGatherBlue, // because HLSL arguments are slightly different.
+ EOpMethodGatherAlpha, // ...
+ EOpMethodGatherCmp, // ...
+ EOpMethodGatherCmpRed, // ...
+ EOpMethodGatherCmpGreen, // ...
+ EOpMethodGatherCmpBlue, // ...
+ EOpMethodGatherCmpAlpha, // ...
+
+ // geometry methods
+ EOpMethodAppend, // Geometry shader methods
+ EOpMethodRestartStrip, // ...
+
+ // matrix
+ EOpMatrixSwizzle, // select multiple matrix components (non-column)
+
+ // SM6 wave ops
+ EOpWaveGetLaneCount, // Will decompose to gl_SubgroupSize.
+ EOpWaveGetLaneIndex, // Will decompose to gl_SubgroupInvocationID.
+ EOpWaveActiveCountBits, // Will decompose to subgroupBallotBitCount(subgroupBallot()).
+ EOpWavePrefixCountBits, // Will decompose to subgroupBallotInclusiveBitCount(subgroupBallot()).
+
+ // Shader Clock Ops
+ EOpReadClockSubgroupKHR,
+ EOpReadClockDeviceKHR,
+};
+
+class TIntermTraverser;
+class TIntermOperator;
+class TIntermAggregate;
+class TIntermUnary;
+class TIntermBinary;
+class TIntermConstantUnion;
+class TIntermSelection;
+class TIntermSwitch;
+class TIntermBranch;
+class TIntermTyped;
+class TIntermMethod;
+class TIntermSymbol;
+class TIntermLoop;
+
+} // end namespace glslang
+
+//
+// Base class for the tree nodes
+//
+// (Put outside the glslang namespace, as it's used as part of the external interface.)
+//
+class TIntermNode {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
+
+ TIntermNode() { loc.init(); }
+ virtual const glslang::TSourceLoc& getLoc() const { return loc; }
+ virtual void setLoc(const glslang::TSourceLoc& l) { loc = l; }
+ virtual void traverse(glslang::TIntermTraverser*) = 0;
+ virtual glslang::TIntermTyped* getAsTyped() { return 0; }
+ virtual glslang::TIntermOperator* getAsOperator() { return 0; }
+ virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; }
+ virtual glslang::TIntermAggregate* getAsAggregate() { return 0; }
+ virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; }
+ virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; }
+ virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; }
+ virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; }
+ virtual glslang::TIntermMethod* getAsMethodNode() { return 0; }
+ virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; }
+ virtual glslang::TIntermBranch* getAsBranchNode() { return 0; }
+ virtual glslang::TIntermLoop* getAsLoopNode() { return 0; }
+
+ virtual const glslang::TIntermTyped* getAsTyped() const { return 0; }
+ virtual const glslang::TIntermOperator* getAsOperator() const { return 0; }
+ virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; }
+ virtual const glslang::TIntermAggregate* getAsAggregate() const { return 0; }
+ virtual const glslang::TIntermUnary* getAsUnaryNode() const { return 0; }
+ virtual const glslang::TIntermBinary* getAsBinaryNode() const { return 0; }
+ virtual const glslang::TIntermSelection* getAsSelectionNode() const { return 0; }
+ virtual const glslang::TIntermSwitch* getAsSwitchNode() const { return 0; }
+ virtual const glslang::TIntermMethod* getAsMethodNode() const { return 0; }
+ virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return 0; }
+ virtual const glslang::TIntermBranch* getAsBranchNode() const { return 0; }
+ virtual const glslang::TIntermLoop* getAsLoopNode() const { return 0; }
+ virtual ~TIntermNode() { }
+
+protected:
+ TIntermNode(const TIntermNode&);
+ TIntermNode& operator=(const TIntermNode&);
+ glslang::TSourceLoc loc;
+};
+
+namespace glslang {
+
+//
+// This is just to help yacc.
+//
+struct TIntermNodePair {
+ TIntermNode* node1;
+ TIntermNode* node2;
+};
+
+//
+// Intermediate class for nodes that have a type.
+//
+class TIntermTyped : public TIntermNode {
+public:
+ TIntermTyped(const TType& t) { type.shallowCopy(t); }
+ TIntermTyped(TBasicType basicType) { TType bt(basicType); type.shallowCopy(bt); }
+ virtual TIntermTyped* getAsTyped() { return this; }
+ virtual const TIntermTyped* getAsTyped() const { return this; }
+ virtual void setType(const TType& t) { type.shallowCopy(t); }
+ virtual const TType& getType() const { return type; }
+ virtual TType& getWritableType() { return type; }
+
+ virtual TBasicType getBasicType() const { return type.getBasicType(); }
+ virtual TQualifier& getQualifier() { return type.getQualifier(); }
+ virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
+ virtual void propagatePrecision(TPrecisionQualifier);
+ virtual int getVectorSize() const { return type.getVectorSize(); }
+ virtual int getMatrixCols() const { return type.getMatrixCols(); }
+ virtual int getMatrixRows() const { return type.getMatrixRows(); }
+ virtual bool isMatrix() const { return type.isMatrix(); }
+ virtual bool isArray() const { return type.isArray(); }
+ virtual bool isVector() const { return type.isVector(); }
+ virtual bool isScalar() const { return type.isScalar(); }
+ virtual bool isStruct() const { return type.isStruct(); }
+ virtual bool isFloatingDomain() const { return type.isFloatingDomain(); }
+ virtual bool isIntegerDomain() const { return type.isIntegerDomain(); }
+ bool isAtomic() const { return type.isAtomic(); }
+ bool isReference() const { return type.isReference(); }
+ TString getCompleteString() const { return type.getCompleteString(); }
+
+protected:
+ TIntermTyped& operator=(const TIntermTyped&);
+ TType type;
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+class TIntermLoop : public TIntermNode {
+public:
+ TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) :
+ body(aBody),
+ test(aTest),
+ terminal(aTerminal),
+ first(testFirst),
+ unroll(false),
+ dontUnroll(false),
+ dependency(0),
+ minIterations(0),
+ maxIterations(iterationsInfinite),
+ iterationMultiple(1),
+ peelCount(0),
+ partialCount(0)
+ { }
+
+ virtual TIntermLoop* getAsLoopNode() { return this; }
+ virtual const TIntermLoop* getAsLoopNode() const { return this; }
+ virtual void traverse(TIntermTraverser*);
+ TIntermNode* getBody() const { return body; }
+ TIntermTyped* getTest() const { return test; }
+ TIntermTyped* getTerminal() const { return terminal; }
+ bool testFirst() const { return first; }
+
+ void setUnroll() { unroll = true; }
+ void setDontUnroll() {
+ dontUnroll = true;
+ peelCount = 0;
+ partialCount = 0;
+ }
+ bool getUnroll() const { return unroll; }
+ bool getDontUnroll() const { return dontUnroll; }
+
+ static const unsigned int dependencyInfinite = 0xFFFFFFFF;
+ static const unsigned int iterationsInfinite = 0xFFFFFFFF;
+ void setLoopDependency(int d) { dependency = d; }
+ int getLoopDependency() const { return dependency; }
+
+ void setMinIterations(unsigned int v) { minIterations = v; }
+ unsigned int getMinIterations() const { return minIterations; }
+ void setMaxIterations(unsigned int v) { maxIterations = v; }
+ unsigned int getMaxIterations() const { return maxIterations; }
+ void setIterationMultiple(unsigned int v) { iterationMultiple = v; }
+ unsigned int getIterationMultiple() const { return iterationMultiple; }
+ void setPeelCount(unsigned int v) {
+ peelCount = v;
+ dontUnroll = false;
+ }
+ unsigned int getPeelCount() const { return peelCount; }
+ void setPartialCount(unsigned int v) {
+ partialCount = v;
+ dontUnroll = false;
+ }
+ unsigned int getPartialCount() const { return partialCount; }
+
+protected:
+ TIntermNode* body; // code to loop over
+ TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
+ TIntermTyped* terminal; // exists for for-loops
+ bool first; // true for while and for, not for do-while
+ bool unroll; // true if unroll requested
+ bool dontUnroll; // true if request to not unroll
+ unsigned int dependency; // loop dependency hint; 0 means not set or unknown
+ unsigned int minIterations; // as per the SPIR-V specification
+ unsigned int maxIterations; // as per the SPIR-V specification
+ unsigned int iterationMultiple; // as per the SPIR-V specification
+ unsigned int peelCount; // as per the SPIR-V specification
+ unsigned int partialCount; // as per the SPIR-V specification
+};
+
+//
+// Handle case, break, continue, return, and kill.
+//
+class TIntermBranch : public TIntermNode {
+public:
+ TIntermBranch(TOperator op, TIntermTyped* e) :
+ flowOp(op),
+ expression(e) { }
+ virtual TIntermBranch* getAsBranchNode() { return this; }
+ virtual const TIntermBranch* getAsBranchNode() const { return this; }
+ virtual void traverse(TIntermTraverser*);
+ TOperator getFlowOp() const { return flowOp; }
+ TIntermTyped* getExpression() const { return expression; }
+ void setExpression(TIntermTyped* pExpression) { expression = pExpression; }
+protected:
+ TOperator flowOp;
+ TIntermTyped* expression;
+};
+
+//
+// Represent method names before seeing their calling signature
+// or resolving them to operations. Just an expression as the base object
+// and a textural name.
+//
+class TIntermMethod : public TIntermTyped {
+public:
+ TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { }
+ virtual TIntermMethod* getAsMethodNode() { return this; }
+ virtual const TIntermMethod* getAsMethodNode() const { return this; }
+ virtual const TString& getMethodName() const { return method; }
+ virtual TIntermTyped* getObject() const { return object; }
+ virtual void traverse(TIntermTraverser*);
+protected:
+ TIntermTyped* object;
+ TString method;
+};
+
+//
+// Nodes that correspond to symbols or constants in the source code.
+//
+class TIntermSymbol : public TIntermTyped {
+public:
+ // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from
+ // per process threadPoolAllocator, then it causes increased memory usage per compile
+ // it is essential to use "symbol = sym" to assign to symbol
+ TIntermSymbol(int i, const TString& n, const TType& t)
+ : TIntermTyped(t), id(i),
+#ifndef GLSLANG_WEB
+ flattenSubset(-1),
+#endif
+ constSubtree(nullptr)
+ { name = n; }
+ virtual int getId() const { return id; }
+ virtual void changeId(int i) { id = i; }
+ virtual const TString& getName() const { return name; }
+ virtual void traverse(TIntermTraverser*);
+ virtual TIntermSymbol* getAsSymbolNode() { return this; }
+ virtual const TIntermSymbol* getAsSymbolNode() const { return this; }
+ void setConstArray(const TConstUnionArray& c) { constArray = c; }
+ const TConstUnionArray& getConstArray() const { return constArray; }
+ void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
+ TIntermTyped* getConstSubtree() const { return constSubtree; }
+#ifndef GLSLANG_WEB
+ void setFlattenSubset(int subset) { flattenSubset = subset; }
+ int getFlattenSubset() const { return flattenSubset; } // -1 means full object
+#endif
+
+ // This is meant for cases where a node has already been constructed, and
+ // later on, it becomes necessary to switch to a different symbol.
+ virtual void switchId(int newId) { id = newId; }
+
+protected:
+ int id; // the unique id of the symbol this node represents
+#ifndef GLSLANG_WEB
+ int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced
+#endif
+ TString name; // the name of the symbol this node represents
+ TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value
+ TIntermTyped* constSubtree;
+};
+
+class TIntermConstantUnion : public TIntermTyped {
+public:
+ TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { }
+ const TConstUnionArray& getConstArray() const { return constArray; }
+ virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
+ virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; }
+ virtual void traverse(TIntermTraverser*);
+ virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const;
+ virtual TIntermTyped* fold(TOperator, const TType&) const;
+ void setLiteral() { literal = true; }
+ void setExpression() { literal = false; }
+ bool isLiteral() const { return literal; }
+
+protected:
+ TIntermConstantUnion& operator=(const TIntermConstantUnion&);
+
+ const TConstUnionArray constArray;
+ bool literal; // true if node represents a literal in the source code
+};
+
+// Represent the independent aspects of a texturing TOperator
+struct TCrackedTextureOp {
+ bool query;
+ bool proj;
+ bool lod;
+ bool fetch;
+ bool offset;
+ bool offsets;
+ bool gather;
+ bool grad;
+ bool subpass;
+ bool lodClamp;
+ bool fragMask;
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped {
+public:
+ virtual TIntermOperator* getAsOperator() { return this; }
+ virtual const TIntermOperator* getAsOperator() const { return this; }
+ TOperator getOp() const { return op; }
+ void setOp(TOperator newOp) { op = newOp; }
+ bool modifiesState() const;
+ bool isConstructor() const;
+ bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; }
+ bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; }
+#ifdef GLSLANG_WEB
+ bool isImage() const { return false; }
+ bool isSparseTexture() const { return false; }
+ bool isImageFootprint() const { return false; }
+ bool isSparseImage() const { return false; }
+ bool isSubgroup() const { return false; }
+#else
+ bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; }
+ bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; }
+ bool isImageFootprint() const { return op > EOpImageFootprintGuardBegin && op < EOpImageFootprintGuardEnd; }
+ bool isSparseImage() const { return op == EOpSparseImageLoad; }
+ bool isSubgroup() const { return op > EOpSubgroupGuardStart && op < EOpSubgroupGuardStop; }
+#endif
+
+ void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; }
+ TPrecisionQualifier getOperationPrecision() const { return operationPrecision != EpqNone ?
+ operationPrecision :
+ type.getQualifier().precision; }
+ TString getCompleteString() const
+ {
+ TString cs = type.getCompleteString();
+ if (getOperationPrecision() != type.getQualifier().precision) {
+ cs += ", operation at ";
+ cs += GetPrecisionQualifierString(getOperationPrecision());
+ }
+
+ return cs;
+ }
+
+ // Crack the op into the individual dimensions of texturing operation.
+ void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const
+ {
+ cracked.query = false;
+ cracked.proj = false;
+ cracked.lod = false;
+ cracked.fetch = false;
+ cracked.offset = false;
+ cracked.offsets = false;
+ cracked.gather = false;
+ cracked.grad = false;
+ cracked.subpass = false;
+ cracked.lodClamp = false;
+ cracked.fragMask = false;
+
+ switch (op) {
+ case EOpImageQuerySize:
+ case EOpImageQuerySamples:
+ case EOpTextureQuerySize:
+ case EOpTextureQueryLod:
+ case EOpTextureQueryLevels:
+ case EOpTextureQuerySamples:
+ case EOpSparseTexelsResident:
+ cracked.query = true;
+ break;
+ case EOpTexture:
+ case EOpSparseTexture:
+ break;
+ case EOpTextureProj:
+ cracked.proj = true;
+ break;
+ case EOpTextureLod:
+ case EOpSparseTextureLod:
+ cracked.lod = true;
+ break;
+ case EOpTextureOffset:
+ case EOpSparseTextureOffset:
+ cracked.offset = true;
+ break;
+ case EOpTextureFetch:
+ case EOpSparseTextureFetch:
+ cracked.fetch = true;
+ if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D)
+ cracked.lod = true;
+ break;
+ case EOpTextureFetchOffset:
+ case EOpSparseTextureFetchOffset:
+ cracked.fetch = true;
+ cracked.offset = true;
+ if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D)
+ cracked.lod = true;
+ break;
+ case EOpTextureProjOffset:
+ cracked.offset = true;
+ cracked.proj = true;
+ break;
+ case EOpTextureLodOffset:
+ case EOpSparseTextureLodOffset:
+ cracked.offset = true;
+ cracked.lod = true;
+ break;
+ case EOpTextureProjLod:
+ cracked.lod = true;
+ cracked.proj = true;
+ break;
+ case EOpTextureProjLodOffset:
+ cracked.offset = true;
+ cracked.lod = true;
+ cracked.proj = true;
+ break;
+ case EOpTextureGrad:
+ case EOpSparseTextureGrad:
+ cracked.grad = true;
+ break;
+ case EOpTextureGradOffset:
+ case EOpSparseTextureGradOffset:
+ cracked.grad = true;
+ cracked.offset = true;
+ break;
+ case EOpTextureProjGrad:
+ cracked.grad = true;
+ cracked.proj = true;
+ break;
+ case EOpTextureProjGradOffset:
+ cracked.grad = true;
+ cracked.offset = true;
+ cracked.proj = true;
+ break;
+#ifndef GLSLANG_WEB
+ case EOpTextureClamp:
+ case EOpSparseTextureClamp:
+ cracked.lodClamp = true;
+ break;
+ case EOpTextureOffsetClamp:
+ case EOpSparseTextureOffsetClamp:
+ cracked.offset = true;
+ cracked.lodClamp = true;
+ break;
+ case EOpTextureGradClamp:
+ case EOpSparseTextureGradClamp:
+ cracked.grad = true;
+ cracked.lodClamp = true;
+ break;
+ case EOpTextureGradOffsetClamp:
+ case EOpSparseTextureGradOffsetClamp:
+ cracked.grad = true;
+ cracked.offset = true;
+ cracked.lodClamp = true;
+ break;
+ case EOpTextureGather:
+ case EOpSparseTextureGather:
+ cracked.gather = true;
+ break;
+ case EOpTextureGatherOffset:
+ case EOpSparseTextureGatherOffset:
+ cracked.gather = true;
+ cracked.offset = true;
+ break;
+ case EOpTextureGatherOffsets:
+ case EOpSparseTextureGatherOffsets:
+ cracked.gather = true;
+ cracked.offsets = true;
+ break;
+ case EOpTextureGatherLod:
+ case EOpSparseTextureGatherLod:
+ cracked.gather = true;
+ cracked.lod = true;
+ break;
+ case EOpTextureGatherLodOffset:
+ case EOpSparseTextureGatherLodOffset:
+ cracked.gather = true;
+ cracked.offset = true;
+ cracked.lod = true;
+ break;
+ case EOpTextureGatherLodOffsets:
+ case EOpSparseTextureGatherLodOffsets:
+ cracked.gather = true;
+ cracked.offsets = true;
+ cracked.lod = true;
+ break;
+ case EOpImageLoadLod:
+ case EOpImageStoreLod:
+ case EOpSparseImageLoadLod:
+ cracked.lod = true;
+ break;
+ case EOpFragmentMaskFetch:
+ cracked.subpass = sampler.dim == EsdSubpass;
+ cracked.fragMask = true;
+ break;
+ case EOpFragmentFetch:
+ cracked.subpass = sampler.dim == EsdSubpass;
+ cracked.fragMask = true;
+ break;
+ case EOpImageSampleFootprintNV:
+ break;
+ case EOpImageSampleFootprintClampNV:
+ cracked.lodClamp = true;
+ break;
+ case EOpImageSampleFootprintLodNV:
+ cracked.lod = true;
+ break;
+ case EOpImageSampleFootprintGradNV:
+ cracked.grad = true;
+ break;
+ case EOpImageSampleFootprintGradClampNV:
+ cracked.lodClamp = true;
+ cracked.grad = true;
+ break;
+ case EOpSubpassLoad:
+ case EOpSubpassLoadMS:
+ cracked.subpass = true;
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+
+protected:
+ TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o), operationPrecision(EpqNone) {}
+ TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o), operationPrecision(EpqNone) {}
+ TOperator op;
+ // The result precision is in the inherited TType, and is usually meant to be both
+ // the operation precision and the result precision. However, some more complex things,
+ // like built-in function calls, distinguish between the two, in which case non-EqpNone
+ // 'operationPrecision' overrides the result precision as far as operation precision
+ // is concerned.
+ TPrecisionQualifier operationPrecision;
+};
+
+//
+// Nodes for all the basic binary math operators.
+//
+class TIntermBinary : public TIntermOperator {
+public:
+ TIntermBinary(TOperator o) : TIntermOperator(o) {}
+ virtual void traverse(TIntermTraverser*);
+ virtual void setLeft(TIntermTyped* n) { left = n; }
+ virtual void setRight(TIntermTyped* n) { right = n; }
+ virtual TIntermTyped* getLeft() const { return left; }
+ virtual TIntermTyped* getRight() const { return right; }
+ virtual TIntermBinary* getAsBinaryNode() { return this; }
+ virtual const TIntermBinary* getAsBinaryNode() const { return this; }
+ virtual void updatePrecision();
+protected:
+ TIntermTyped* left;
+ TIntermTyped* right;
+};
+
+//
+// Nodes for unary math operators.
+//
+class TIntermUnary : public TIntermOperator {
+public:
+ TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
+ TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
+ virtual void traverse(TIntermTraverser*);
+ virtual void setOperand(TIntermTyped* o) { operand = o; }
+ virtual TIntermTyped* getOperand() { return operand; }
+ virtual const TIntermTyped* getOperand() const { return operand; }
+ virtual TIntermUnary* getAsUnaryNode() { return this; }
+ virtual const TIntermUnary* getAsUnaryNode() const { return this; }
+ virtual void updatePrecision();
+protected:
+ TIntermTyped* operand;
+};
+
+typedef TVector<TIntermNode*> TIntermSequence;
+typedef TVector<TStorageQualifier> TQualifierList;
+//
+// Nodes that operate on an arbitrary sized set of children.
+//
+class TIntermAggregate : public TIntermOperator {
+public:
+ TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(nullptr) { }
+ TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(nullptr) { }
+ ~TIntermAggregate() { delete pragmaTable; }
+ virtual TIntermAggregate* getAsAggregate() { return this; }
+ virtual const TIntermAggregate* getAsAggregate() const { return this; }
+ virtual void setOperator(TOperator o) { op = o; }
+ virtual TIntermSequence& getSequence() { return sequence; }
+ virtual const TIntermSequence& getSequence() const { return sequence; }
+ virtual void setName(const TString& n) { name = n; }
+ virtual const TString& getName() const { return name; }
+ virtual void traverse(TIntermTraverser*);
+ virtual void setUserDefined() { userDefined = true; }
+ virtual bool isUserDefined() { return userDefined; }
+ virtual TQualifierList& getQualifierList() { return qualifier; }
+ virtual const TQualifierList& getQualifierList() const { return qualifier; }
+ void setOptimize(bool o) { optimize = o; }
+ void setDebug(bool d) { debug = d; }
+ bool getOptimize() const { return optimize; }
+ bool getDebug() const { return debug; }
+ void setPragmaTable(const TPragmaTable& pTable);
+ const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
+protected:
+ TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
+ TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
+ TIntermSequence sequence;
+ TQualifierList qualifier;
+ TString name;
+ bool userDefined; // used for user defined function names
+ bool optimize;
+ bool debug;
+ TPragmaTable* pragmaTable;
+};
+
+//
+// For if tests.
+//
+class TIntermSelection : public TIntermTyped {
+public:
+ TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
+ TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB),
+ shortCircuit(true),
+ flatten(false), dontFlatten(false) {}
+ TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
+ TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB),
+ shortCircuit(true),
+ flatten(false), dontFlatten(false) {}
+ virtual void traverse(TIntermTraverser*);
+ virtual TIntermTyped* getCondition() const { return condition; }
+ virtual TIntermNode* getTrueBlock() const { return trueBlock; }
+ virtual TIntermNode* getFalseBlock() const { return falseBlock; }
+ virtual TIntermSelection* getAsSelectionNode() { return this; }
+ virtual const TIntermSelection* getAsSelectionNode() const { return this; }
+
+ void setNoShortCircuit() { shortCircuit = false; }
+ bool getShortCircuit() const { return shortCircuit; }
+
+ void setFlatten() { flatten = true; }
+ void setDontFlatten() { dontFlatten = true; }
+ bool getFlatten() const { return flatten; }
+ bool getDontFlatten() const { return dontFlatten; }
+
+protected:
+ TIntermTyped* condition;
+ TIntermNode* trueBlock;
+ TIntermNode* falseBlock;
+ bool shortCircuit; // normally all if-then-else and all GLSL ?: short-circuit, but HLSL ?: does not
+ bool flatten; // true if flatten requested
+ bool dontFlatten; // true if requested to not flatten
+};
+
+//
+// For switch statements. Designed use is that a switch will have sequence of nodes
+// that are either case/default nodes or a *single* node that represents all the code
+// in between (if any) consecutive case/defaults. So, a traversal need only deal with
+// 0 or 1 nodes per case/default statement.
+//
+class TIntermSwitch : public TIntermNode {
+public:
+ TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b),
+ flatten(false), dontFlatten(false) {}
+ virtual void traverse(TIntermTraverser*);
+ virtual TIntermNode* getCondition() const { return condition; }
+ virtual TIntermAggregate* getBody() const { return body; }
+ virtual TIntermSwitch* getAsSwitchNode() { return this; }
+ virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
+
+ void setFlatten() { flatten = true; }
+ void setDontFlatten() { dontFlatten = true; }
+ bool getFlatten() const { return flatten; }
+ bool getDontFlatten() const { return dontFlatten; }
+
+protected:
+ TIntermTyped* condition;
+ TIntermAggregate* body;
+ bool flatten; // true if flatten requested
+ bool dontFlatten; // true if requested to not flatten
+};
+
+enum TVisit
+{
+ EvPreVisit,
+ EvInVisit,
+ EvPostVisit
+};
+
+//
+// For traversing the tree. User should derive from this,
+// put their traversal specific data in it, and then pass
+// it to a Traverse method.
+//
+// When using this, just fill in the methods for nodes you want visited.
+// Return false from a pre-visit to skip visiting that node's subtree.
+//
+// Explicitly set postVisit to true if you want post visiting, otherwise,
+// filled in methods will only be called at pre-visit time (before processing
+// the subtree). Similarly for inVisit for in-order visiting of nodes with
+// multiple children.
+//
+// If you only want post-visits, explicitly turn off preVisit (and inVisit)
+// and turn on postVisit.
+//
+// In general, for the visit*() methods, return true from interior nodes
+// to have the traversal continue on to children.
+//
+// If you process children yourself, or don't want them processed, return false.
+//
+class TIntermTraverser {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
+ TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
+ preVisit(preVisit),
+ inVisit(inVisit),
+ postVisit(postVisit),
+ rightToLeft(rightToLeft),
+ depth(0),
+ maxDepth(0) { }
+ virtual ~TIntermTraverser() { }
+
+ virtual void visitSymbol(TIntermSymbol*) { }
+ virtual void visitConstantUnion(TIntermConstantUnion*) { }
+ virtual bool visitBinary(TVisit, TIntermBinary*) { return true; }
+ virtual bool visitUnary(TVisit, TIntermUnary*) { return true; }
+ virtual bool visitSelection(TVisit, TIntermSelection*) { return true; }
+ virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; }
+ virtual bool visitLoop(TVisit, TIntermLoop*) { return true; }
+ virtual bool visitBranch(TVisit, TIntermBranch*) { return true; }
+ virtual bool visitSwitch(TVisit, TIntermSwitch*) { return true; }
+
+ int getMaxDepth() const { return maxDepth; }
+
+ void incrementDepth(TIntermNode *current)
+ {
+ depth++;
+ maxDepth = (std::max)(maxDepth, depth);
+ path.push_back(current);
+ }
+
+ void decrementDepth()
+ {
+ depth--;
+ path.pop_back();
+ }
+
+ TIntermNode *getParentNode()
+ {
+ return path.size() == 0 ? NULL : path.back();
+ }
+
+ const bool preVisit;
+ const bool inVisit;
+ const bool postVisit;
+ const bool rightToLeft;
+
+protected:
+ TIntermTraverser& operator=(TIntermTraverser&);
+
+ int depth;
+ int maxDepth;
+
+ // All the nodes from root to the current node's parent during traversing.
+ TVector<TIntermNode *> path;
+};
+
+// KHR_vulkan_glsl says "Two arrays sized with specialization constants are the same type only if
+// sized with the same symbol, involving no operations"
+inline bool SameSpecializationConstants(TIntermTyped* node1, TIntermTyped* node2)
+{
+ return node1->getAsSymbolNode() && node2->getAsSymbolNode() &&
+ node1->getAsSymbolNode()->getId() == node2->getAsSymbolNode()->getId();
+}
+
+} // end namespace glslang
+
+#endif // __INTERMEDIATE_H
diff --git a/thirdparty/glslang/glslang/Include/revision.h b/thirdparty/glslang/glslang/Include/revision.h
new file mode 100644
index 0000000000..a0e4b2066c
--- /dev/null
+++ b/thirdparty/glslang/glslang/Include/revision.h
@@ -0,0 +1,3 @@
+// This header is generated by the make-revision script.
+
+#define GLSLANG_PATCH_LEVEL 3559
diff --git a/thirdparty/glslang/glslang/MachineIndependent/Constant.cpp b/thirdparty/glslang/glslang/MachineIndependent/Constant.cpp
new file mode 100644
index 0000000000..98c2666fbb
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/Constant.cpp
@@ -0,0 +1,1419 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "localintermediate.h"
+#include <cmath>
+#include <cfloat>
+#include <cstdlib>
+#include <climits>
+
+namespace {
+
+using namespace glslang;
+
+typedef union {
+ double d;
+ int i[2];
+} DoubleIntUnion;
+
+// Some helper functions
+
+bool isNan(double x)
+{
+ DoubleIntUnion u;
+ // tough to find a platform independent library function, do it directly
+ u.d = x;
+ int bitPatternL = u.i[0];
+ int bitPatternH = u.i[1];
+ return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
+ ((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
+}
+
+bool isInf(double x)
+{
+ DoubleIntUnion u;
+ // tough to find a platform independent library function, do it directly
+ u.d = x;
+ int bitPatternL = u.i[0];
+ int bitPatternH = u.i[1];
+ return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
+ (bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
+}
+
+const double pi = 3.1415926535897932384626433832795;
+
+} // end anonymous namespace
+
+
+namespace glslang {
+
+//
+// The fold functions see if an operation on a constant can be done in place,
+// without generating run-time code.
+//
+// Returns the node to keep using, which may or may not be the node passed in.
+//
+// Note: As of version 1.2, all constant operations must be folded. It is
+// not opportunistic, but rather a semantic requirement.
+//
+
+//
+// Do folding between a pair of nodes.
+// 'this' is the left-hand operand and 'rightConstantNode' is the right-hand operand.
+//
+// Returns a new node representing the result.
+//
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* rightConstantNode) const
+{
+ // For most cases, the return type matches the argument type, so set that
+ // up and just code to exceptions below.
+ TType returnType;
+ returnType.shallowCopy(getType());
+
+ //
+ // A pair of nodes is to be folded together
+ //
+
+ const TIntermConstantUnion *rightNode = rightConstantNode->getAsConstantUnion();
+ TConstUnionArray leftUnionArray = getConstArray();
+ TConstUnionArray rightUnionArray = rightNode->getConstArray();
+
+ // Figure out the size of the result
+ int newComps;
+ int constComps;
+ switch(op) {
+ case EOpMatrixTimesMatrix:
+ newComps = rightNode->getMatrixCols() * getMatrixRows();
+ break;
+ case EOpMatrixTimesVector:
+ newComps = getMatrixRows();
+ break;
+ case EOpVectorTimesMatrix:
+ newComps = rightNode->getMatrixCols();
+ break;
+ default:
+ newComps = getType().computeNumComponents();
+ constComps = rightConstantNode->getType().computeNumComponents();
+ if (constComps == 1 && newComps > 1) {
+ // for a case like vec4 f = vec4(2,3,4,5) + 1.2;
+ TConstUnionArray smearedArray(newComps, rightNode->getConstArray()[0]);
+ rightUnionArray = smearedArray;
+ } else if (constComps > 1 && newComps == 1) {
+ // for a case like vec4 f = 1.2 + vec4(2,3,4,5);
+ newComps = constComps;
+ rightUnionArray = rightNode->getConstArray();
+ TConstUnionArray smearedArray(newComps, getConstArray()[0]);
+ leftUnionArray = smearedArray;
+ returnType.shallowCopy(rightNode->getType());
+ }
+ break;
+ }
+
+ TConstUnionArray newConstArray(newComps);
+ TType constBool(EbtBool, EvqConst);
+
+ switch(op) {
+ case EOpAdd:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] + rightUnionArray[i];
+ break;
+ case EOpSub:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] - rightUnionArray[i];
+ break;
+
+ case EOpMul:
+ case EOpVectorTimesScalar:
+ case EOpMatrixTimesScalar:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] * rightUnionArray[i];
+ break;
+ case EOpMatrixTimesMatrix:
+ for (int row = 0; row < getMatrixRows(); row++) {
+ for (int column = 0; column < rightNode->getMatrixCols(); column++) {
+ double sum = 0.0f;
+ for (int i = 0; i < rightNode->getMatrixRows(); i++)
+ sum += leftUnionArray[i * getMatrixRows() + row].getDConst() * rightUnionArray[column * rightNode->getMatrixRows() + i].getDConst();
+ newConstArray[column * getMatrixRows() + row].setDConst(sum);
+ }
+ }
+ returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, rightNode->getMatrixCols(), getMatrixRows()));
+ break;
+ case EOpDiv:
+ for (int i = 0; i < newComps; i++) {
+ switch (getType().getBasicType()) {
+ case EbtDouble:
+ case EbtFloat:
+ case EbtFloat16:
+ if (rightUnionArray[i].getDConst() != 0.0)
+ newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst());
+ else if (leftUnionArray[i].getDConst() > 0.0)
+ newConstArray[i].setDConst((double)INFINITY);
+ else if (leftUnionArray[i].getDConst() < 0.0)
+ newConstArray[i].setDConst(-(double)INFINITY);
+ else
+ newConstArray[i].setDConst((double)NAN);
+ break;
+
+ case EbtInt:
+ if (rightUnionArray[i] == 0)
+ newConstArray[i].setIConst(0x7FFFFFFF);
+ else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)-0x80000000ll)
+ newConstArray[i].setIConst((int)-0x80000000ll);
+ else
+ newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
+ break;
+
+ case EbtUint:
+ if (rightUnionArray[i] == 0u)
+ newConstArray[i].setUConst(0xFFFFFFFFu);
+ else
+ newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
+ break;
+
+#ifndef GLSLANG_WEB
+ case EbtInt8:
+ if (rightUnionArray[i] == (signed char)0)
+ newConstArray[i].setI8Const((signed char)0x7F);
+ else if (rightUnionArray[i].getI8Const() == (signed char)-1 && leftUnionArray[i].getI8Const() == (signed char)-0x80)
+ newConstArray[i].setI8Const((signed char)-0x80);
+ else
+ newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const());
+ break;
+
+ case EbtUint8:
+ if (rightUnionArray[i] == (unsigned char)0u)
+ newConstArray[i].setU8Const((unsigned char)0xFFu);
+ else
+ newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const());
+ break;
+
+ case EbtInt16:
+ if (rightUnionArray[i] == (signed short)0)
+ newConstArray[i].setI16Const((signed short)0x7FFF);
+ else if (rightUnionArray[i].getI16Const() == (signed short)-1 && leftUnionArray[i].getI16Const() == (signed short)-0x8000)
+ newConstArray[i].setI16Const((signed short)-0x8000);
+ else
+ newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const());
+ break;
+
+ case EbtUint16:
+ if (rightUnionArray[i] == (unsigned short)0u)
+ newConstArray[i].setU16Const((unsigned short)0xFFFFu);
+ else
+ newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const());
+ break;
+
+ case EbtInt64:
+ if (rightUnionArray[i] == 0ll)
+ newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll);
+ else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)-0x8000000000000000ll)
+ newConstArray[i].setI64Const((long long)-0x8000000000000000ll);
+ else
+ newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
+ break;
+
+ case EbtUint64:
+ if (rightUnionArray[i] == 0ull)
+ newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
+ else
+ newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
+ break;
+ default:
+ return 0;
+#endif
+ }
+ }
+ break;
+
+ case EOpMatrixTimesVector:
+ for (int i = 0; i < getMatrixRows(); i++) {
+ double sum = 0.0f;
+ for (int j = 0; j < rightNode->getVectorSize(); j++) {
+ sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst();
+ }
+ newConstArray[i].setDConst(sum);
+ }
+
+ returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
+ break;
+
+ case EOpVectorTimesMatrix:
+ for (int i = 0; i < rightNode->getMatrixCols(); i++) {
+ double sum = 0.0f;
+ for (int j = 0; j < getVectorSize(); j++)
+ sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst();
+ newConstArray[i].setDConst(sum);
+ }
+
+ returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols()));
+ break;
+
+ case EOpMod:
+ for (int i = 0; i < newComps; i++) {
+ if (rightUnionArray[i] == 0)
+ newConstArray[i] = leftUnionArray[i];
+ else {
+ switch (getType().getBasicType()) {
+ case EbtInt:
+ if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) {
+ newConstArray[i].setIConst(0);
+ break;
+ } else goto modulo_default;
+#ifndef GLSLANG_WEB
+ case EbtInt64:
+ if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) {
+ newConstArray[i].setI64Const(0);
+ break;
+ } else goto modulo_default;
+ case EbtInt16:
+ if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) {
+ newConstArray[i].setIConst(0);
+ break;
+ } else goto modulo_default;
+#endif
+ default:
+ modulo_default:
+ newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
+ }
+ }
+ }
+ break;
+
+ case EOpRightShift:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i];
+ break;
+
+ case EOpLeftShift:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] << rightUnionArray[i];
+ break;
+
+ case EOpAnd:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] & rightUnionArray[i];
+ break;
+ case EOpInclusiveOr:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] | rightUnionArray[i];
+ break;
+ case EOpExclusiveOr:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i];
+ break;
+
+ case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] && rightUnionArray[i];
+ break;
+
+ case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] || rightUnionArray[i];
+ break;
+
+ case EOpLogicalXor:
+ for (int i = 0; i < newComps; i++) {
+ switch (getType().getBasicType()) {
+ case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break;
+ default: assert(false && "Default missing");
+ }
+ }
+ break;
+
+ case EOpLessThan:
+ newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]);
+ returnType.shallowCopy(constBool);
+ break;
+ case EOpGreaterThan:
+ newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]);
+ returnType.shallowCopy(constBool);
+ break;
+ case EOpLessThanEqual:
+ newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0]));
+ returnType.shallowCopy(constBool);
+ break;
+ case EOpGreaterThanEqual:
+ newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0]));
+ returnType.shallowCopy(constBool);
+ break;
+ case EOpEqual:
+ newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray);
+ returnType.shallowCopy(constBool);
+ break;
+ case EOpNotEqual:
+ newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray);
+ returnType.shallowCopy(constBool);
+ break;
+
+ default:
+ return 0;
+ }
+
+ TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
+ newNode->setLoc(getLoc());
+
+ return newNode;
+}
+
+//
+// Do single unary node folding
+//
+// Returns a new node representing the result.
+//
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const
+{
+ // First, size the result, which is mostly the same as the argument's size,
+ // but not always, and classify what is componentwise.
+ // Also, eliminate cases that can't be compile-time constant.
+ int resultSize;
+ bool componentWise = true;
+
+ int objectSize = getType().computeNumComponents();
+ switch (op) {
+ case EOpDeterminant:
+ case EOpAny:
+ case EOpAll:
+ case EOpLength:
+ componentWise = false;
+ resultSize = 1;
+ break;
+
+ case EOpEmitStreamVertex:
+ case EOpEndStreamPrimitive:
+ // These don't fold
+ return nullptr;
+
+ case EOpPackSnorm2x16:
+ case EOpPackUnorm2x16:
+ case EOpPackHalf2x16:
+ componentWise = false;
+ resultSize = 1;
+ break;
+
+ case EOpUnpackSnorm2x16:
+ case EOpUnpackUnorm2x16:
+ case EOpUnpackHalf2x16:
+ componentWise = false;
+ resultSize = 2;
+ break;
+
+ case EOpPack16:
+ case EOpPack32:
+ case EOpPack64:
+ case EOpUnpack32:
+ case EOpUnpack16:
+ case EOpUnpack8:
+ case EOpNormalize:
+ componentWise = false;
+ resultSize = objectSize;
+ break;
+
+ default:
+ resultSize = objectSize;
+ break;
+ }
+
+ // Set up for processing
+ TConstUnionArray newConstArray(resultSize);
+ const TConstUnionArray& unionArray = getConstArray();
+
+ // Process non-component-wise operations
+ switch (op) {
+ case EOpLength:
+ case EOpNormalize:
+ {
+ double sum = 0;
+ for (int i = 0; i < objectSize; i++)
+ sum += unionArray[i].getDConst() * unionArray[i].getDConst();
+ double length = sqrt(sum);
+ if (op == EOpLength)
+ newConstArray[0].setDConst(length);
+ else {
+ for (int i = 0; i < objectSize; i++)
+ newConstArray[i].setDConst(unionArray[i].getDConst() / length);
+ }
+ break;
+ }
+
+ case EOpAny:
+ {
+ bool result = false;
+ for (int i = 0; i < objectSize; i++) {
+ if (unionArray[i].getBConst())
+ result = true;
+ }
+ newConstArray[0].setBConst(result);
+ break;
+ }
+ case EOpAll:
+ {
+ bool result = true;
+ for (int i = 0; i < objectSize; i++) {
+ if (! unionArray[i].getBConst())
+ result = false;
+ }
+ newConstArray[0].setBConst(result);
+ break;
+ }
+
+ case EOpPackSnorm2x16:
+ case EOpPackUnorm2x16:
+ case EOpPackHalf2x16:
+ case EOpPack16:
+ case EOpPack32:
+ case EOpPack64:
+ case EOpUnpack32:
+ case EOpUnpack16:
+ case EOpUnpack8:
+
+ case EOpUnpackSnorm2x16:
+ case EOpUnpackUnorm2x16:
+ case EOpUnpackHalf2x16:
+
+ case EOpDeterminant:
+ case EOpMatrixInverse:
+ case EOpTranspose:
+ return nullptr;
+
+ default:
+ assert(componentWise);
+ break;
+ }
+
+ // Turn off the componentwise loop
+ if (! componentWise)
+ objectSize = 0;
+
+ // Process component-wise operations
+ for (int i = 0; i < objectSize; i++) {
+ switch (op) {
+ case EOpNegative:
+ switch (getType().getBasicType()) {
+ case EbtDouble:
+ case EbtFloat16:
+ case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
+ case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
+ case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
+ case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const()))); break;
+ case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
+ case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const()))); break;
+ case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
+ case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const()))); break;
+#endif
+ default:
+ return nullptr;
+ }
+ break;
+ case EOpLogicalNot:
+ case EOpVectorLogicalNot:
+ switch (getType().getBasicType()) {
+ case EbtBool: newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
+ default:
+ return nullptr;
+ }
+ break;
+ case EOpBitwiseNot:
+ newConstArray[i] = ~unionArray[i];
+ break;
+ case EOpRadians:
+ newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
+ break;
+ case EOpDegrees:
+ newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
+ break;
+ case EOpSin:
+ newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
+ break;
+ case EOpCos:
+ newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
+ break;
+ case EOpTan:
+ newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
+ break;
+ case EOpAsin:
+ newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
+ break;
+ case EOpAcos:
+ newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
+ break;
+ case EOpAtan:
+ newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
+ break;
+
+ case EOpDPdx:
+ case EOpDPdy:
+ case EOpFwidth:
+ case EOpDPdxFine:
+ case EOpDPdyFine:
+ case EOpFwidthFine:
+ case EOpDPdxCoarse:
+ case EOpDPdyCoarse:
+ case EOpFwidthCoarse:
+ // The derivatives are all mandated to create a constant 0.
+ newConstArray[i].setDConst(0.0);
+ break;
+
+ case EOpExp:
+ newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
+ break;
+ case EOpLog:
+ newConstArray[i].setDConst(log(unionArray[i].getDConst()));
+ break;
+ case EOpExp2:
+ {
+ const double inv_log2_e = 0.69314718055994530941723212145818;
+ newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
+ break;
+ }
+ case EOpLog2:
+ {
+ const double log2_e = 1.4426950408889634073599246810019;
+ newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
+ break;
+ }
+ case EOpSqrt:
+ newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
+ break;
+ case EOpInverseSqrt:
+ newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
+ break;
+
+ case EOpAbs:
+ if (unionArray[i].getType() == EbtDouble)
+ newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
+ else if (unionArray[i].getType() == EbtInt)
+ newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
+ else
+ newConstArray[i] = unionArray[i];
+ break;
+ case EOpSign:
+ #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
+ if (unionArray[i].getType() == EbtDouble)
+ newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
+ else
+ newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
+ break;
+ case EOpFloor:
+ newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
+ break;
+ case EOpTrunc:
+ if (unionArray[i].getDConst() > 0)
+ newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
+ else
+ newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
+ break;
+ case EOpRound:
+ newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
+ break;
+ case EOpRoundEven:
+ {
+ double flr = floor(unionArray[i].getDConst());
+ bool even = flr / 2.0 == floor(flr / 2.0);
+ double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
+ newConstArray[i].setDConst(rounded);
+ break;
+ }
+ case EOpCeil:
+ newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
+ break;
+ case EOpFract:
+ {
+ double x = unionArray[i].getDConst();
+ newConstArray[i].setDConst(x - floor(x));
+ break;
+ }
+
+ case EOpIsNan:
+ {
+ newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
+ break;
+ }
+ case EOpIsInf:
+ {
+ newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
+ break;
+ }
+
+ case EOpConvIntToBool:
+ newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break;
+ case EOpConvUintToBool:
+ newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break;
+ case EOpConvBoolToInt:
+ newConstArray[i].setIConst(unionArray[i].getBConst()); break;
+ case EOpConvBoolToUint:
+ newConstArray[i].setUConst(unionArray[i].getBConst()); break;
+ case EOpConvIntToUint:
+ newConstArray[i].setUConst(unionArray[i].getIConst()); break;
+ case EOpConvUintToInt:
+ newConstArray[i].setIConst(unionArray[i].getUConst()); break;
+
+ case EOpConvFloatToBool:
+ case EOpConvDoubleToBool:
+ newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
+
+ case EOpConvBoolToFloat:
+ case EOpConvBoolToDouble:
+ newConstArray[i].setDConst(unionArray[i].getBConst()); break;
+
+ case EOpConvIntToFloat:
+ case EOpConvIntToDouble:
+ newConstArray[i].setDConst(unionArray[i].getIConst()); break;
+
+ case EOpConvUintToFloat:
+ case EOpConvUintToDouble:
+ newConstArray[i].setDConst(unionArray[i].getUConst()); break;
+
+ case EOpConvDoubleToFloat:
+ case EOpConvFloatToDouble:
+ newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+
+ case EOpConvFloatToUint:
+ case EOpConvDoubleToUint:
+ newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
+
+ case EOpConvFloatToInt:
+ case EOpConvDoubleToInt:
+ newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
+
+#ifndef GLSLANG_WEB
+ case EOpConvInt8ToBool:
+ newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break;
+ case EOpConvUint8ToBool:
+ newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break;
+ case EOpConvInt16ToBool:
+ newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break;
+ case EOpConvUint16ToBool:
+ newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break;
+ case EOpConvInt64ToBool:
+ newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
+ case EOpConvUint64ToBool:
+ newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
+ case EOpConvFloat16ToBool:
+ newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
+
+ case EOpConvBoolToInt8:
+ newConstArray[i].setI8Const(unionArray[i].getBConst()); break;
+ case EOpConvBoolToUint8:
+ newConstArray[i].setU8Const(unionArray[i].getBConst()); break;
+ case EOpConvBoolToInt16:
+ newConstArray[i].setI16Const(unionArray[i].getBConst()); break;
+ case EOpConvBoolToUint16:
+ newConstArray[i].setU16Const(unionArray[i].getBConst()); break;
+ case EOpConvBoolToInt64:
+ newConstArray[i].setI64Const(unionArray[i].getBConst()); break;
+ case EOpConvBoolToUint64:
+ newConstArray[i].setU64Const(unionArray[i].getBConst()); break;
+ case EOpConvBoolToFloat16:
+ newConstArray[i].setDConst(unionArray[i].getBConst()); break;
+
+ case EOpConvInt8ToInt16:
+ newConstArray[i].setI16Const(unionArray[i].getI8Const()); break;
+ case EOpConvInt8ToInt:
+ newConstArray[i].setIConst(unionArray[i].getI8Const()); break;
+ case EOpConvInt8ToInt64:
+ newConstArray[i].setI64Const(unionArray[i].getI8Const()); break;
+ case EOpConvInt8ToUint8:
+ newConstArray[i].setU8Const(unionArray[i].getI8Const()); break;
+ case EOpConvInt8ToUint16:
+ newConstArray[i].setU16Const(unionArray[i].getI8Const()); break;
+ case EOpConvInt8ToUint:
+ newConstArray[i].setUConst(unionArray[i].getI8Const()); break;
+ case EOpConvInt8ToUint64:
+ newConstArray[i].setU64Const(unionArray[i].getI8Const()); break;
+ case EOpConvUint8ToInt8:
+ newConstArray[i].setI8Const(unionArray[i].getU8Const()); break;
+ case EOpConvUint8ToInt16:
+ newConstArray[i].setI16Const(unionArray[i].getU8Const()); break;
+ case EOpConvUint8ToInt:
+ newConstArray[i].setIConst(unionArray[i].getU8Const()); break;
+ case EOpConvUint8ToInt64:
+ newConstArray[i].setI64Const(unionArray[i].getU8Const()); break;
+ case EOpConvUint8ToUint16:
+ newConstArray[i].setU16Const(unionArray[i].getU8Const()); break;
+ case EOpConvUint8ToUint:
+ newConstArray[i].setUConst(unionArray[i].getU8Const()); break;
+ case EOpConvUint8ToUint64:
+ newConstArray[i].setU64Const(unionArray[i].getU8Const()); break;
+ case EOpConvInt8ToFloat16:
+ newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
+ case EOpConvInt8ToFloat:
+ newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
+ case EOpConvInt8ToDouble:
+ newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
+ case EOpConvUint8ToFloat16:
+ newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
+ case EOpConvUint8ToFloat:
+ newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
+ case EOpConvUint8ToDouble:
+ newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
+
+ case EOpConvInt16ToInt8:
+ newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI16Const())); break;
+ case EOpConvInt16ToInt:
+ newConstArray[i].setIConst(unionArray[i].getI16Const()); break;
+ case EOpConvInt16ToInt64:
+ newConstArray[i].setI64Const(unionArray[i].getI16Const()); break;
+ case EOpConvInt16ToUint8:
+ newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI16Const())); break;
+ case EOpConvInt16ToUint16:
+ newConstArray[i].setU16Const(unionArray[i].getI16Const()); break;
+ case EOpConvInt16ToUint:
+ newConstArray[i].setUConst(unionArray[i].getI16Const()); break;
+ case EOpConvInt16ToUint64:
+ newConstArray[i].setU64Const(unionArray[i].getI16Const()); break;
+ case EOpConvUint16ToInt8:
+ newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU16Const())); break;
+ case EOpConvUint16ToInt16:
+ newConstArray[i].setI16Const(unionArray[i].getU16Const()); break;
+ case EOpConvUint16ToInt:
+ newConstArray[i].setIConst(unionArray[i].getU16Const()); break;
+ case EOpConvUint16ToInt64:
+ newConstArray[i].setI64Const(unionArray[i].getU16Const()); break;
+ case EOpConvUint16ToUint8:
+ newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU16Const())); break;
+
+ case EOpConvUint16ToUint:
+ newConstArray[i].setUConst(unionArray[i].getU16Const()); break;
+ case EOpConvUint16ToUint64:
+ newConstArray[i].setU64Const(unionArray[i].getU16Const()); break;
+ case EOpConvInt16ToFloat16:
+ newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
+ case EOpConvInt16ToFloat:
+ newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
+ case EOpConvInt16ToDouble:
+ newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
+ case EOpConvUint16ToFloat16:
+ newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
+ case EOpConvUint16ToFloat:
+ newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
+ case EOpConvUint16ToDouble:
+ newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
+
+ case EOpConvIntToInt8:
+ newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break;
+ case EOpConvIntToInt16:
+ newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break;
+ case EOpConvIntToInt64:
+ newConstArray[i].setI64Const(unionArray[i].getIConst()); break;
+ case EOpConvIntToUint8:
+ newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break;
+ case EOpConvIntToUint16:
+ newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break;
+ case EOpConvIntToUint64:
+ newConstArray[i].setU64Const(unionArray[i].getIConst()); break;
+
+ case EOpConvUintToInt8:
+ newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break;
+ case EOpConvUintToInt16:
+ newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break;
+ case EOpConvUintToInt64:
+ newConstArray[i].setI64Const(unionArray[i].getUConst()); break;
+ case EOpConvUintToUint8:
+ newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break;
+ case EOpConvUintToUint16:
+ newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break;
+ case EOpConvUintToUint64:
+ newConstArray[i].setU64Const(unionArray[i].getUConst()); break;
+ case EOpConvIntToFloat16:
+ newConstArray[i].setDConst(unionArray[i].getIConst()); break;
+ case EOpConvUintToFloat16:
+ newConstArray[i].setDConst(unionArray[i].getUConst()); break;
+ case EOpConvInt64ToInt8:
+ newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI64Const())); break;
+ case EOpConvInt64ToInt16:
+ newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getI64Const())); break;
+ case EOpConvInt64ToInt:
+ newConstArray[i].setIConst(static_cast<int>(unionArray[i].getI64Const())); break;
+ case EOpConvInt64ToUint8:
+ newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI64Const())); break;
+ case EOpConvInt64ToUint16:
+ newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getI64Const())); break;
+ case EOpConvInt64ToUint:
+ newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getI64Const())); break;
+ case EOpConvInt64ToUint64:
+ newConstArray[i].setU64Const(unionArray[i].getI64Const()); break;
+ case EOpConvUint64ToInt8:
+ newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU64Const())); break;
+ case EOpConvUint64ToInt16:
+ newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getU64Const())); break;
+ case EOpConvUint64ToInt:
+ newConstArray[i].setIConst(static_cast<int>(unionArray[i].getU64Const())); break;
+ case EOpConvUint64ToInt64:
+ newConstArray[i].setI64Const(unionArray[i].getU64Const()); break;
+ case EOpConvUint64ToUint8:
+ newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU64Const())); break;
+ case EOpConvUint64ToUint16:
+ newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getU64Const())); break;
+ case EOpConvUint64ToUint:
+ newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getU64Const())); break;
+ case EOpConvInt64ToFloat16:
+ newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
+ case EOpConvInt64ToFloat:
+ newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
+ case EOpConvInt64ToDouble:
+ newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
+ case EOpConvUint64ToFloat16:
+ newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
+ case EOpConvUint64ToFloat:
+ newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
+ case EOpConvUint64ToDouble:
+ newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
+ case EOpConvFloat16ToInt8:
+ newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
+ case EOpConvFloat16ToInt16:
+ newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
+ case EOpConvFloat16ToInt:
+ newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
+ case EOpConvFloat16ToInt64:
+ newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
+ case EOpConvFloat16ToUint8:
+ newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
+ case EOpConvFloat16ToUint16:
+ newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
+ case EOpConvFloat16ToUint:
+ newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
+ case EOpConvFloat16ToUint64:
+ newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
+ case EOpConvFloat16ToFloat:
+ newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+ case EOpConvFloat16ToDouble:
+ newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+ case EOpConvFloatToInt8:
+ newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
+ case EOpConvFloatToInt16:
+ newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
+ case EOpConvFloatToInt64:
+ newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
+ case EOpConvFloatToUint8:
+ newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
+ case EOpConvFloatToUint16:
+ newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
+ case EOpConvFloatToUint64:
+ newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
+ case EOpConvFloatToFloat16:
+ newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+ case EOpConvDoubleToInt8:
+ newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
+ case EOpConvDoubleToInt16:
+ newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
+ case EOpConvDoubleToInt64:
+ newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
+ case EOpConvDoubleToUint8:
+ newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
+ case EOpConvDoubleToUint16:
+ newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
+ case EOpConvDoubleToUint64:
+ newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
+ case EOpConvDoubleToFloat16:
+ newConstArray[i].setDConst(unionArray[i].getDConst()); break;
+ case EOpConvPtrToUint64:
+ case EOpConvUint64ToPtr:
+ case EOpConstructReference:
+ newConstArray[i].setU64Const(unionArray[i].getU64Const()); break;
+#endif
+
+ // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
+
+ case EOpSinh:
+ case EOpCosh:
+ case EOpTanh:
+ case EOpAsinh:
+ case EOpAcosh:
+ case EOpAtanh:
+
+ case EOpFloatBitsToInt:
+ case EOpFloatBitsToUint:
+ case EOpIntBitsToFloat:
+ case EOpUintBitsToFloat:
+ case EOpDoubleBitsToInt64:
+ case EOpDoubleBitsToUint64:
+ case EOpInt64BitsToDouble:
+ case EOpUint64BitsToDouble:
+ case EOpFloat16BitsToInt16:
+ case EOpFloat16BitsToUint16:
+ case EOpInt16BitsToFloat16:
+ case EOpUint16BitsToFloat16:
+ default:
+ return nullptr;
+ }
+ }
+
+ TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
+ newNode->getWritableType().getQualifier().storage = EvqConst;
+ newNode->setLoc(getLoc());
+
+ return newNode;
+}
+
+//
+// Do constant folding for an aggregate node that has all its children
+// as constants and an operator that requires constant folding.
+//
+TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
+{
+ if (aggrNode == nullptr)
+ return aggrNode;
+
+ if (! areAllChildConst(aggrNode))
+ return aggrNode;
+
+ if (aggrNode->isConstructor())
+ return foldConstructor(aggrNode);
+
+ TIntermSequence& children = aggrNode->getSequence();
+
+ // First, see if this is an operation to constant fold, kick out if not,
+ // see what size the result is if so.
+
+ bool componentwise = false; // will also say componentwise if a scalar argument gets repeated to make per-component results
+ int objectSize;
+ switch (aggrNode->getOp()) {
+ case EOpAtan:
+ case EOpPow:
+ case EOpMin:
+ case EOpMax:
+ case EOpMix:
+ case EOpClamp:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ case EOpVectorEqual:
+ case EOpVectorNotEqual:
+ componentwise = true;
+ objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
+ break;
+ case EOpCross:
+ case EOpReflect:
+ case EOpRefract:
+ case EOpFaceForward:
+ objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
+ break;
+ case EOpDistance:
+ case EOpDot:
+ objectSize = 1;
+ break;
+ case EOpOuterProduct:
+ objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
+ children[1]->getAsTyped()->getType().getVectorSize();
+ break;
+ case EOpStep:
+ componentwise = true;
+ objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
+ children[1]->getAsTyped()->getType().getVectorSize());
+ break;
+ case EOpSmoothStep:
+ componentwise = true;
+ objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
+ children[2]->getAsTyped()->getType().getVectorSize());
+ break;
+ default:
+ return aggrNode;
+ }
+ TConstUnionArray newConstArray(objectSize);
+
+ TVector<TConstUnionArray> childConstUnions;
+ for (unsigned int arg = 0; arg < children.size(); ++arg)
+ childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
+
+ if (componentwise) {
+ for (int comp = 0; comp < objectSize; comp++) {
+
+ // some arguments are scalars instead of matching vectors; simulate a smear
+ int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
+ int arg1comp = 0;
+ if (children.size() > 1)
+ arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
+ int arg2comp = 0;
+ if (children.size() > 2)
+ arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);
+
+ switch (aggrNode->getOp()) {
+ case EOpAtan:
+ newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
+ break;
+ case EOpPow:
+ newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
+ break;
+ case EOpMin:
+ switch(children[0]->getAsTyped()->getBasicType()) {
+ case EbtFloat16:
+ case EbtFloat:
+ case EbtDouble:
+ newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
+ break;
+ case EbtInt:
+ newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
+ break;
+ case EbtUint:
+ newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
+ break;
+#ifndef GLSLANG_WEB
+ case EbtInt8:
+ newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
+ break;
+ case EbtUint8:
+ newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
+ break;
+ case EbtInt16:
+ newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
+ break;
+ case EbtUint16:
+ newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
+ break;
+ case EbtInt64:
+ newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
+ break;
+ case EbtUint64:
+ newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
+ break;
+#endif
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EOpMax:
+ switch(children[0]->getAsTyped()->getBasicType()) {
+ case EbtFloat16:
+ case EbtFloat:
+ case EbtDouble:
+ newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
+ break;
+ case EbtInt:
+ newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
+ break;
+ case EbtUint:
+ newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
+ break;
+#ifndef GLSLANG_WEB
+ case EbtInt8:
+ newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
+ break;
+ case EbtUint8:
+ newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
+ break;
+ case EbtInt16:
+ newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
+ break;
+ case EbtUint16:
+ newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
+ break;
+ case EbtInt64:
+ newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
+ break;
+ case EbtUint64:
+ newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
+ break;
+#endif
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EOpClamp:
+ switch(children[0]->getAsTyped()->getBasicType()) {
+ case EbtFloat16:
+ case EbtFloat:
+ case EbtDouble:
+ newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
+ childConstUnions[2][arg2comp].getDConst()));
+ break;
+ case EbtUint:
+ newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
+ childConstUnions[2][arg2comp].getUConst()));
+ break;
+#ifndef GLSLANG_WEB
+ case EbtInt8:
+ newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()),
+ childConstUnions[2][arg2comp].getI8Const()));
+ break;
+ case EbtUint8:
+ newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()),
+ childConstUnions[2][arg2comp].getU8Const()));
+ break;
+ case EbtInt16:
+ newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()),
+ childConstUnions[2][arg2comp].getI16Const()));
+ break;
+ case EbtUint16:
+ newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()),
+ childConstUnions[2][arg2comp].getU16Const()));
+ break;
+ case EbtInt:
+ newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
+ childConstUnions[2][arg2comp].getIConst()));
+ break;
+ case EbtInt64:
+ newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
+ childConstUnions[2][arg2comp].getI64Const()));
+ break;
+ case EbtUint64:
+ newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
+ childConstUnions[2][arg2comp].getU64Const()));
+ break;
+#endif
+ default: assert(false && "Default missing");
+ }
+ break;
+ case EOpLessThan:
+ newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
+ break;
+ case EOpGreaterThan:
+ newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
+ break;
+ case EOpLessThanEqual:
+ newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
+ break;
+ case EOpGreaterThanEqual:
+ newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
+ break;
+ case EOpVectorEqual:
+ newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
+ break;
+ case EOpVectorNotEqual:
+ newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
+ break;
+ case EOpMix:
+ if (!children[0]->getAsTyped()->isFloatingDomain())
+ return aggrNode;
+ if (children[2]->getAsTyped()->getBasicType() == EbtBool) {
+ newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst()
+ ? childConstUnions[1][arg1comp].getDConst()
+ : childConstUnions[0][arg0comp].getDConst());
+ } else {
+ newConstArray[comp].setDConst(
+ childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
+ childConstUnions[1][arg1comp].getDConst() * childConstUnions[2][arg2comp].getDConst());
+ }
+ break;
+ case EOpStep:
+ newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
+ break;
+ case EOpSmoothStep:
+ {
+ double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) /
+ (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
+ if (t < 0.0)
+ t = 0.0;
+ if (t > 1.0)
+ t = 1.0;
+ newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
+ break;
+ }
+ default:
+ return aggrNode;
+ }
+ }
+ } else {
+ // Non-componentwise...
+
+ int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
+ double dot;
+
+ switch (aggrNode->getOp()) {
+ case EOpDistance:
+ {
+ double sum = 0.0;
+ for (int comp = 0; comp < numComps; ++comp) {
+ double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
+ sum += diff * diff;
+ }
+ newConstArray[0].setDConst(sqrt(sum));
+ break;
+ }
+ case EOpDot:
+ newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
+ break;
+ case EOpCross:
+ newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
+ newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
+ newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
+ break;
+ case EOpFaceForward:
+ // If dot(Nref, I) < 0 return N, otherwise return -N: Arguments are (N, I, Nref).
+ dot = childConstUnions[1].dot(childConstUnions[2]);
+ for (int comp = 0; comp < numComps; ++comp) {
+ if (dot < 0.0)
+ newConstArray[comp] = childConstUnions[0][comp];
+ else
+ newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
+ }
+ break;
+ case EOpReflect:
+ // I - 2 * dot(N, I) * N: Arguments are (I, N).
+ dot = childConstUnions[0].dot(childConstUnions[1]);
+ dot *= 2.0;
+ for (int comp = 0; comp < numComps; ++comp)
+ newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
+ break;
+ case EOpRefract:
+ {
+ // Arguments are (I, N, eta).
+ // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
+ // if (k < 0.0)
+ // return dvec(0.0)
+ // else
+ // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
+ dot = childConstUnions[0].dot(childConstUnions[1]);
+ double eta = childConstUnions[2][0].getDConst();
+ double k = 1.0 - eta * eta * (1.0 - dot * dot);
+ if (k < 0.0) {
+ for (int comp = 0; comp < numComps; ++comp)
+ newConstArray[comp].setDConst(0.0);
+ } else {
+ for (int comp = 0; comp < numComps; ++comp)
+ newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
+ }
+ break;
+ }
+ case EOpOuterProduct:
+ {
+ int numRows = numComps;
+ int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
+ for (int row = 0; row < numRows; ++row)
+ for (int col = 0; col < numCols; ++col)
+ newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
+ break;
+ }
+ default:
+ return aggrNode;
+ }
+ }
+
+ TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
+ newNode->getWritableType().getQualifier().storage = EvqConst;
+ newNode->setLoc(aggrNode->getLoc());
+
+ return newNode;
+}
+
+bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode)
+{
+ bool allConstant = true;
+
+ // check if all the child nodes are constants so that they can be inserted into
+ // the parent node
+ if (aggrNode) {
+ TIntermSequence& childSequenceVector = aggrNode->getSequence();
+ for (TIntermSequence::iterator p = childSequenceVector.begin();
+ p != childSequenceVector.end(); p++) {
+ if (!(*p)->getAsTyped()->getAsConstantUnion())
+ return false;
+ }
+ }
+
+ return allConstant;
+}
+
+TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
+{
+ bool error = false;
+
+ TConstUnionArray unionArray(aggrNode->getType().computeNumComponents());
+ if (aggrNode->getSequence().size() == 1)
+ error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
+ else
+ error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
+
+ if (error)
+ return aggrNode;
+
+ return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc());
+}
+
+//
+// Constant folding of a bracket (array-style) dereference or struct-like dot
+// dereference. Can handle anything except a multi-character swizzle, though
+// all swizzles may go to foldSwizzle().
+//
+TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc)
+{
+ TType dereferencedType(node->getType(), index);
+ dereferencedType.getQualifier().storage = EvqConst;
+ TIntermTyped* result = 0;
+ int size = dereferencedType.computeNumComponents();
+
+ // arrays, vectors, matrices, all use simple multiplicative math
+ // while structures need to add up heterogeneous members
+ int start;
+ if (node->getType().isCoopMat())
+ start = 0;
+ else if (node->isArray() || ! node->isStruct())
+ start = size * index;
+ else {
+ // it is a structure
+ assert(node->isStruct());
+ start = 0;
+ for (int i = 0; i < index; ++i)
+ start += (*node->getType().getStruct())[i].type->computeNumComponents();
+ }
+
+ result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc);
+
+ if (result == 0)
+ result = node;
+ else
+ result->setType(dereferencedType);
+
+ return result;
+}
+
+//
+// Make a constant vector node or constant scalar node, representing a given
+// constant vector and constant swizzle into it.
+//
+TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& selectors, const TSourceLoc& loc)
+{
+ const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
+ TConstUnionArray constArray(selectors.size());
+
+ for (int i = 0; i < selectors.size(); i++)
+ constArray[i] = unionArray[selectors[i]];
+
+ TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);
+
+ if (result == 0)
+ result = node;
+ else
+ result->setType(TType(node->getBasicType(), EvqConst, selectors.size()));
+
+ return result;
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/InfoSink.cpp b/thirdparty/glslang/glslang/MachineIndependent/InfoSink.cpp
new file mode 100644
index 0000000000..d00c422566
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/InfoSink.cpp
@@ -0,0 +1,113 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/InfoSink.h"
+
+#include <cstring>
+
+namespace glslang {
+
+void TInfoSinkBase::append(const char* s)
+{
+ if (outputStream & EString) {
+ if (s == nullptr)
+ sink.append("(null)");
+ else {
+ checkMem(strlen(s));
+ sink.append(s);
+ }
+ }
+
+//#ifdef _WIN32
+// if (outputStream & EDebugger)
+// OutputDebugString(s);
+//#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%s", s);
+}
+
+void TInfoSinkBase::append(int count, char c)
+{
+ if (outputStream & EString) {
+ checkMem(count);
+ sink.append(count, c);
+ }
+
+//#ifdef _WIN32
+// if (outputStream & EDebugger) {
+// char str[2];
+// str[0] = c;
+// str[1] = '\0';
+// OutputDebugString(str);
+// }
+//#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%c", c);
+}
+
+void TInfoSinkBase::append(const TPersistString& t)
+{
+ if (outputStream & EString) {
+ checkMem(t.size());
+ sink.append(t);
+ }
+
+//#ifdef _WIN32
+// if (outputStream & EDebugger)
+// OutputDebugString(t.c_str());
+//#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%s", t.c_str());
+}
+
+void TInfoSinkBase::append(const TString& t)
+{
+ if (outputStream & EString) {
+ checkMem(t.size());
+ sink.append(t.c_str());
+ }
+
+//#ifdef _WIN32
+// if (outputStream & EDebugger)
+// OutputDebugString(t.c_str());
+//#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%s", t.c_str());
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp b/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp
new file mode 100644
index 0000000000..de55742649
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp
@@ -0,0 +1,8875 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2016 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Create strings that declare built-in definitions, add built-ins programmatically
+// that cannot be expressed in the strings, and establish mappings between
+// built-in functions and operators.
+//
+// Where to put a built-in:
+// TBuiltIns::initialize(version,profile) context-independent textual built-ins; add them to the right string
+// TBuiltIns::initialize(resources,...) context-dependent textual built-ins; add them to the right string
+// TBuiltIns::identifyBuiltIns(...,symbolTable) context-independent programmatic additions/mappings to the symbol table,
+// including identifying what extensions are needed if a version does not allow a symbol
+// TBuiltIns::identifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the symbol table,
+// including identifying what extensions are needed if a version does not allow a symbol
+//
+
+#include "../Include/intermediate.h"
+#include "Initialize.h"
+
+namespace glslang {
+
+// TODO: ARB_Compatability: do full extension support
+const bool ARBCompatibility = true;
+
+const bool ForwardCompatibility = false;
+
+// change this back to false if depending on textual spellings of texturing calls when consuming the AST
+// Using PureOperatorBuiltins=false is deprecated.
+bool PureOperatorBuiltins = true;
+
+namespace {
+
+//
+// A set of definitions for tabling of the built-in functions.
+//
+
+// Order matters here, as does correlation with the subsequent
+// "const int ..." declarations and the ArgType enumerants.
+const char* TypeString[] = {
+ "bool", "bvec2", "bvec3", "bvec4",
+ "float", "vec2", "vec3", "vec4",
+ "int", "ivec2", "ivec3", "ivec4",
+ "uint", "uvec2", "uvec3", "uvec4",
+};
+const int TypeStringCount = sizeof(TypeString) / sizeof(char*); // number of entries in 'TypeString'
+const int TypeStringRowShift = 2; // shift amount to go downe one row in 'TypeString'
+const int TypeStringColumnMask = (1 << TypeStringRowShift) - 1; // reduce type to its column number in 'TypeString'
+const int TypeStringScalarMask = ~TypeStringColumnMask; // take type to its scalar column in 'TypeString'
+
+enum ArgType {
+ // numbers hardcoded to correspond to 'TypeString'; order and value matter
+ TypeB = 1 << 0, // Boolean
+ TypeF = 1 << 1, // float 32
+ TypeI = 1 << 2, // int 32
+ TypeU = 1 << 3, // uint 32
+ TypeF16 = 1 << 4, // float 16
+ TypeF64 = 1 << 5, // float 64
+ TypeI8 = 1 << 6, // int 8
+ TypeI16 = 1 << 7, // int 16
+ TypeI64 = 1 << 8, // int 64
+ TypeU8 = 1 << 9, // uint 8
+ TypeU16 = 1 << 10, // uint 16
+ TypeU64 = 1 << 11, // uint 64
+};
+// Mixtures of the above, to help the function tables
+const ArgType TypeFI = static_cast<ArgType>(TypeF | TypeI);
+const ArgType TypeFIB = static_cast<ArgType>(TypeF | TypeI | TypeB);
+const ArgType TypeIU = static_cast<ArgType>(TypeI | TypeU);
+
+// The relationships between arguments and return type, whether anything is
+// output, or other unusual situations.
+enum ArgClass {
+ ClassRegular = 0, // nothing special, just all vector widths with matching return type; traditional arithmetic
+ ClassLS = 1 << 0, // the last argument is also held fixed as a (type-matched) scalar while the others cycle
+ ClassXLS = 1 << 1, // the last argument is exclusively a (type-matched) scalar while the others cycle
+ ClassLS2 = 1 << 2, // the last two arguments are held fixed as a (type-matched) scalar while the others cycle
+ ClassFS = 1 << 3, // the first argument is held fixed as a (type-matched) scalar while the others cycle
+ ClassFS2 = 1 << 4, // the first two arguments are held fixed as a (type-matched) scalar while the others cycle
+ ClassLO = 1 << 5, // the last argument is an output
+ ClassB = 1 << 6, // return type cycles through only bool/bvec, matching vector width of args
+ ClassLB = 1 << 7, // last argument cycles through only bool/bvec, matching vector width of args
+ ClassV1 = 1 << 8, // scalar only
+ ClassFIO = 1 << 9, // first argument is inout
+ ClassRS = 1 << 10, // the return is held scalar as the arguments cycle
+ ClassNS = 1 << 11, // no scalar prototype
+ ClassCV = 1 << 12, // first argument is 'coherent volatile'
+ ClassFO = 1 << 13, // first argument is output
+ ClassV3 = 1 << 14, // vec3 only
+};
+// Mixtures of the above, to help the function tables
+const ArgClass ClassV1FIOCV = (ArgClass)(ClassV1 | ClassFIO | ClassCV);
+const ArgClass ClassV1FOCV = (ArgClass)(ClassV1 | ClassFO | ClassCV);
+const ArgClass ClassV1CV = (ArgClass)(ClassV1 | ClassCV);
+const ArgClass ClassBNS = (ArgClass)(ClassB | ClassNS);
+const ArgClass ClassRSNS = (ArgClass)(ClassRS | ClassNS);
+
+// A descriptor, for a single profile, of when something is available.
+// If the current profile does not match 'profile' mask below, the other fields
+// do not apply (nor validate).
+// profiles == EBadProfile is the end of an array of these
+struct Versioning {
+ EProfile profiles; // the profile(s) (mask) that the following fields are valid for
+ int minExtendedVersion; // earliest version when extensions are enabled; ignored if numExtensions is 0
+ int minCoreVersion; // earliest version function is in core; 0 means never
+ int numExtensions; // how many extensions are in the 'extensions' list
+ const char** extensions; // list of extension names enabling the function
+};
+
+EProfile EDesktopProfile = static_cast<EProfile>(ENoProfile | ECoreProfile | ECompatibilityProfile);
+
+// Declare pointers to put into the table for versioning.
+#ifdef GLSLANG_WEB
+ const Versioning* Es300Desktop130 = nullptr;
+ const Versioning* Es310Desktop430 = nullptr;
+#else
+ const Versioning Es300Desktop130Version[] = { { EEsProfile, 0, 300, 0, nullptr },
+ { EDesktopProfile, 0, 130, 0, nullptr },
+ { EBadProfile } };
+ const Versioning* Es300Desktop130 = &Es300Desktop130Version[0];
+
+ const Versioning Es310Desktop430Version[] = { { EEsProfile, 0, 310, 0, nullptr },
+ { EDesktopProfile, 0, 430, 0, nullptr },
+ { EBadProfile } };
+ const Versioning* Es310Desktop430 = &Es310Desktop430Version[0];
+
+ const Versioning Es310Desktop450Version[] = { { EEsProfile, 0, 310, 0, nullptr },
+ { EDesktopProfile, 0, 450, 0, nullptr },
+ { EBadProfile } };
+ const Versioning* Es310Desktop450 = &Es310Desktop450Version[0];
+#endif
+
+// The main descriptor of what a set of function prototypes can look like, and
+// a pointer to extra versioning information, when needed.
+struct BuiltInFunction {
+ TOperator op; // operator to map the name to
+ const char* name; // function name
+ int numArguments; // number of arguments (overloads with varying arguments need different entries)
+ ArgType types; // ArgType mask
+ ArgClass classes; // the ways this particular function entry manifests
+ const Versioning* versioning; // nullptr means always a valid version
+};
+
+// The tables can have the same built-in function name more than one time,
+// but the exact same prototype must be indicated at most once.
+// The prototypes that get declared are the union of all those indicated.
+// This is important when different releases add new prototypes for the same name.
+// It also also congnitively simpler tiling of the prototype space.
+// In practice, most names can be fully represented with one entry.
+//
+// Table is terminated by an OpNull TOperator.
+
+const BuiltInFunction BaseFunctions[] = {
+// TOperator, name, arg-count, ArgType, ArgClass, versioning
+// --------- ---- --------- ------- -------- ----------
+ { EOpRadians, "radians", 1, TypeF, ClassRegular, nullptr },
+ { EOpDegrees, "degrees", 1, TypeF, ClassRegular, nullptr },
+ { EOpSin, "sin", 1, TypeF, ClassRegular, nullptr },
+ { EOpCos, "cos", 1, TypeF, ClassRegular, nullptr },
+ { EOpTan, "tan", 1, TypeF, ClassRegular, nullptr },
+ { EOpAsin, "asin", 1, TypeF, ClassRegular, nullptr },
+ { EOpAcos, "acos", 1, TypeF, ClassRegular, nullptr },
+ { EOpAtan, "atan", 2, TypeF, ClassRegular, nullptr },
+ { EOpAtan, "atan", 1, TypeF, ClassRegular, nullptr },
+ { EOpPow, "pow", 2, TypeF, ClassRegular, nullptr },
+ { EOpExp, "exp", 1, TypeF, ClassRegular, nullptr },
+ { EOpLog, "log", 1, TypeF, ClassRegular, nullptr },
+ { EOpExp2, "exp2", 1, TypeF, ClassRegular, nullptr },
+ { EOpLog2, "log2", 1, TypeF, ClassRegular, nullptr },
+ { EOpSqrt, "sqrt", 1, TypeF, ClassRegular, nullptr },
+ { EOpInverseSqrt, "inversesqrt", 1, TypeF, ClassRegular, nullptr },
+ { EOpAbs, "abs", 1, TypeF, ClassRegular, nullptr },
+ { EOpSign, "sign", 1, TypeF, ClassRegular, nullptr },
+ { EOpFloor, "floor", 1, TypeF, ClassRegular, nullptr },
+ { EOpCeil, "ceil", 1, TypeF, ClassRegular, nullptr },
+ { EOpFract, "fract", 1, TypeF, ClassRegular, nullptr },
+ { EOpMod, "mod", 2, TypeF, ClassLS, nullptr },
+ { EOpMin, "min", 2, TypeF, ClassLS, nullptr },
+ { EOpMax, "max", 2, TypeF, ClassLS, nullptr },
+ { EOpClamp, "clamp", 3, TypeF, ClassLS2, nullptr },
+ { EOpMix, "mix", 3, TypeF, ClassLS, nullptr },
+ { EOpStep, "step", 2, TypeF, ClassFS, nullptr },
+ { EOpSmoothStep, "smoothstep", 3, TypeF, ClassFS2, nullptr },
+ { EOpNormalize, "normalize", 1, TypeF, ClassRegular, nullptr },
+ { EOpFaceForward, "faceforward", 3, TypeF, ClassRegular, nullptr },
+ { EOpReflect, "reflect", 2, TypeF, ClassRegular, nullptr },
+ { EOpRefract, "refract", 3, TypeF, ClassXLS, nullptr },
+ { EOpLength, "length", 1, TypeF, ClassRS, nullptr },
+ { EOpDistance, "distance", 2, TypeF, ClassRS, nullptr },
+ { EOpDot, "dot", 2, TypeF, ClassRS, nullptr },
+ { EOpCross, "cross", 2, TypeF, ClassV3, nullptr },
+ { EOpLessThan, "lessThan", 2, TypeFI, ClassBNS, nullptr },
+ { EOpLessThanEqual, "lessThanEqual", 2, TypeFI, ClassBNS, nullptr },
+ { EOpGreaterThan, "greaterThan", 2, TypeFI, ClassBNS, nullptr },
+ { EOpGreaterThanEqual, "greaterThanEqual", 2, TypeFI, ClassBNS, nullptr },
+ { EOpVectorEqual, "equal", 2, TypeFIB, ClassBNS, nullptr },
+ { EOpVectorNotEqual, "notEqual", 2, TypeFIB, ClassBNS, nullptr },
+ { EOpAny, "any", 1, TypeB, ClassRSNS, nullptr },
+ { EOpAll, "all", 1, TypeB, ClassRSNS, nullptr },
+ { EOpVectorLogicalNot, "not", 1, TypeB, ClassNS, nullptr },
+ { EOpSinh, "sinh", 1, TypeF, ClassRegular, Es300Desktop130 },
+ { EOpCosh, "cosh", 1, TypeF, ClassRegular, Es300Desktop130 },
+ { EOpTanh, "tanh", 1, TypeF, ClassRegular, Es300Desktop130 },
+ { EOpAsinh, "asinh", 1, TypeF, ClassRegular, Es300Desktop130 },
+ { EOpAcosh, "acosh", 1, TypeF, ClassRegular, Es300Desktop130 },
+ { EOpAtanh, "atanh", 1, TypeF, ClassRegular, Es300Desktop130 },
+ { EOpAbs, "abs", 1, TypeI, ClassRegular, Es300Desktop130 },
+ { EOpSign, "sign", 1, TypeI, ClassRegular, Es300Desktop130 },
+ { EOpTrunc, "trunc", 1, TypeF, ClassRegular, Es300Desktop130 },
+ { EOpRound, "round", 1, TypeF, ClassRegular, Es300Desktop130 },
+ { EOpRoundEven, "roundEven", 1, TypeF, ClassRegular, Es300Desktop130 },
+ { EOpModf, "modf", 2, TypeF, ClassLO, Es300Desktop130 },
+ { EOpMin, "min", 2, TypeIU, ClassLS, Es300Desktop130 },
+ { EOpMax, "max", 2, TypeIU, ClassLS, Es300Desktop130 },
+ { EOpClamp, "clamp", 3, TypeIU, ClassLS2, Es300Desktop130 },
+ { EOpMix, "mix", 3, TypeF, ClassLB, Es300Desktop130 },
+ { EOpIsInf, "isinf", 1, TypeF, ClassB, Es300Desktop130 },
+ { EOpIsNan, "isnan", 1, TypeF, ClassB, Es300Desktop130 },
+ { EOpLessThan, "lessThan", 2, TypeU, ClassBNS, Es300Desktop130 },
+ { EOpLessThanEqual, "lessThanEqual", 2, TypeU, ClassBNS, Es300Desktop130 },
+ { EOpGreaterThan, "greaterThan", 2, TypeU, ClassBNS, Es300Desktop130 },
+ { EOpGreaterThanEqual, "greaterThanEqual", 2, TypeU, ClassBNS, Es300Desktop130 },
+ { EOpVectorEqual, "equal", 2, TypeU, ClassBNS, Es300Desktop130 },
+ { EOpVectorNotEqual, "notEqual", 2, TypeU, ClassBNS, Es300Desktop130 },
+ { EOpAtomicAdd, "atomicAdd", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 },
+ { EOpAtomicMin, "atomicMin", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 },
+ { EOpAtomicMax, "atomicMax", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 },
+ { EOpAtomicAnd, "atomicAnd", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 },
+ { EOpAtomicOr, "atomicOr", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 },
+ { EOpAtomicXor, "atomicXor", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 },
+ { EOpAtomicExchange, "atomicExchange", 2, TypeIU, ClassV1FIOCV, Es310Desktop430 },
+ { EOpAtomicCompSwap, "atomicCompSwap", 3, TypeIU, ClassV1FIOCV, Es310Desktop430 },
+#ifndef GLSLANG_WEB
+ { EOpMix, "mix", 3, TypeB, ClassRegular, Es310Desktop450 },
+ { EOpMix, "mix", 3, TypeIU, ClassLB, Es310Desktop450 },
+#endif
+
+ { EOpNull }
+};
+
+const BuiltInFunction DerivativeFunctions[] = {
+ { EOpDPdx, "dFdx", 1, TypeF, ClassRegular, nullptr },
+ { EOpDPdy, "dFdy", 1, TypeF, ClassRegular, nullptr },
+ { EOpFwidth, "fwidth", 1, TypeF, ClassRegular, nullptr },
+ { EOpNull }
+};
+
+// For functions declared some other way, but still use the table to relate to operator.
+struct CustomFunction {
+ TOperator op; // operator to map the name to
+ const char* name; // function name
+ const Versioning* versioning; // nullptr means always a valid version
+};
+
+const CustomFunction CustomFunctions[] = {
+ { EOpBarrier, "barrier", nullptr },
+ { EOpMemoryBarrierShared, "memoryBarrierShared", nullptr },
+ { EOpGroupMemoryBarrier, "groupMemoryBarrier", nullptr },
+ { EOpMemoryBarrier, "memoryBarrier", nullptr },
+ { EOpMemoryBarrierBuffer, "memoryBarrierBuffer", nullptr },
+
+ { EOpPackSnorm2x16, "packSnorm2x16", nullptr },
+ { EOpUnpackSnorm2x16, "unpackSnorm2x16", nullptr },
+ { EOpPackUnorm2x16, "packUnorm2x16", nullptr },
+ { EOpUnpackUnorm2x16, "unpackUnorm2x16", nullptr },
+ { EOpPackHalf2x16, "packHalf2x16", nullptr },
+ { EOpUnpackHalf2x16, "unpackHalf2x16", nullptr },
+
+ { EOpMul, "matrixCompMult", nullptr },
+ { EOpOuterProduct, "outerProduct", nullptr },
+ { EOpTranspose, "transpose", nullptr },
+ { EOpDeterminant, "determinant", nullptr },
+ { EOpMatrixInverse, "inverse", nullptr },
+ { EOpFloatBitsToInt, "floatBitsToInt", nullptr },
+ { EOpFloatBitsToUint, "floatBitsToUint", nullptr },
+ { EOpIntBitsToFloat, "intBitsToFloat", nullptr },
+ { EOpUintBitsToFloat, "uintBitsToFloat", nullptr },
+
+ { EOpTextureQuerySize, "textureSize", nullptr },
+ { EOpTextureQueryLod, "textureQueryLod", nullptr },
+ { EOpTextureQueryLevels, "textureQueryLevels", nullptr },
+ { EOpTextureQuerySamples, "textureSamples", nullptr },
+ { EOpTexture, "texture", nullptr },
+ { EOpTextureProj, "textureProj", nullptr },
+ { EOpTextureLod, "textureLod", nullptr },
+ { EOpTextureOffset, "textureOffset", nullptr },
+ { EOpTextureFetch, "texelFetch", nullptr },
+ { EOpTextureFetchOffset, "texelFetchOffset", nullptr },
+ { EOpTextureProjOffset, "textureProjOffset", nullptr },
+ { EOpTextureLodOffset, "textureLodOffset", nullptr },
+ { EOpTextureProjLod, "textureProjLod", nullptr },
+ { EOpTextureProjLodOffset, "textureProjLodOffset", nullptr },
+ { EOpTextureGrad, "textureGrad", nullptr },
+ { EOpTextureGradOffset, "textureGradOffset", nullptr },
+ { EOpTextureProjGrad, "textureProjGrad", nullptr },
+ { EOpTextureProjGradOffset, "textureProjGradOffset", nullptr },
+
+ { EOpNull }
+};
+
+// For the given table of functions, add all the indicated prototypes for each
+// one, to be returned in the passed in decls.
+void AddTabledBuiltin(TString& decls, const BuiltInFunction& function)
+{
+ const auto isScalarType = [](int type) { return (type & TypeStringColumnMask) == 0; };
+
+ // loop across these two:
+ // 0: the varying arg set, and
+ // 1: the fixed scalar args
+ const ArgClass ClassFixed = (ArgClass)(ClassLS | ClassXLS | ClassLS2 | ClassFS | ClassFS2);
+ for (int fixed = 0; fixed < ((function.classes & ClassFixed) > 0 ? 2 : 1); ++fixed) {
+
+ if (fixed == 0 && (function.classes & ClassXLS))
+ continue;
+
+ // walk the type strings in TypeString[]
+ for (int type = 0; type < TypeStringCount; ++type) {
+ // skip types not selected: go from type to row number to type bit
+ if ((function.types & (1 << (type >> TypeStringRowShift))) == 0)
+ continue;
+
+ // if we aren't on a scalar, and should be, skip
+ if ((function.classes & ClassV1) && !isScalarType(type))
+ continue;
+
+ // if we aren't on a 3-vector, and should be, skip
+ if ((function.classes & ClassV3) && (type & TypeStringColumnMask) != 2)
+ continue;
+
+ // skip replication of all arg scalars between the varying arg set and the fixed args
+ if (fixed == 1 && type == (type & TypeStringScalarMask) && (function.classes & ClassXLS) == 0)
+ continue;
+
+ // skip scalars when we are told to
+ if ((function.classes & ClassNS) && isScalarType(type))
+ continue;
+
+ // return type
+ if (function.classes & ClassB)
+ decls.append(TypeString[type & TypeStringColumnMask]);
+ else if (function.classes & ClassRS)
+ decls.append(TypeString[type & TypeStringScalarMask]);
+ else
+ decls.append(TypeString[type]);
+ decls.append(" ");
+ decls.append(function.name);
+ decls.append("(");
+
+ // arguments
+ for (int arg = 0; arg < function.numArguments; ++arg) {
+ if (arg == function.numArguments - 1 && (function.classes & ClassLO))
+ decls.append("out ");
+ if (arg == 0) {
+#ifndef GLSLANG_WEB
+ if (function.classes & ClassCV)
+ decls.append("coherent volatile ");
+#endif
+ if (function.classes & ClassFIO)
+ decls.append("inout ");
+ if (function.classes & ClassFO)
+ decls.append("out ");
+ }
+ if ((function.classes & ClassLB) && arg == function.numArguments - 1)
+ decls.append(TypeString[type & TypeStringColumnMask]);
+ else if (fixed && ((arg == function.numArguments - 1 && (function.classes & (ClassLS | ClassXLS |
+ ClassLS2))) ||
+ (arg == function.numArguments - 2 && (function.classes & ClassLS2)) ||
+ (arg == 0 && (function.classes & (ClassFS | ClassFS2))) ||
+ (arg == 1 && (function.classes & ClassFS2))))
+ decls.append(TypeString[type & TypeStringScalarMask]);
+ else
+ decls.append(TypeString[type]);
+ if (arg < function.numArguments - 1)
+ decls.append(",");
+ }
+ decls.append(");\n");
+ }
+ }
+}
+
+// See if the tabled versioning information allows the current version.
+bool ValidVersion(const BuiltInFunction& function, int version, EProfile profile, const SpvVersion& /* spVersion */)
+{
+#ifdef GLSLANG_WEB
+ // all entries in table are valid
+ return true;
+#endif
+
+ // nullptr means always valid
+ if (function.versioning == nullptr)
+ return true;
+
+ // check for what is said about our current profile
+ for (const Versioning* v = function.versioning; v->profiles != EBadProfile; ++v) {
+ if ((v->profiles & profile) != 0) {
+ if (v->minCoreVersion <= version || (v->numExtensions > 0 && v->minExtendedVersion <= version))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Relate a single table of built-ins to their AST operator.
+// This can get called redundantly (especially for the common built-ins, when
+// called once per stage). This is a performance issue only, not a correctness
+// concern. It is done for quality arising from simplicity, as there are subtleties
+// to get correct if instead trying to do it surgically.
+template<class FunctionT>
+void RelateTabledBuiltins(const FunctionT* functions, TSymbolTable& symbolTable)
+{
+ while (functions->op != EOpNull) {
+ symbolTable.relateToOperator(functions->name, functions->op);
+ ++functions;
+ }
+}
+
+} // end anonymous namespace
+
+// Add declarations for all tables of built-in functions.
+void TBuiltIns::addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion)
+{
+ const auto forEachFunction = [&](TString& decls, const BuiltInFunction* function) {
+ while (function->op != EOpNull) {
+ if (ValidVersion(*function, version, profile, spvVersion))
+ AddTabledBuiltin(decls, *function);
+ ++function;
+ }
+ };
+
+ forEachFunction(commonBuiltins, BaseFunctions);
+ forEachFunction(stageBuiltins[EShLangFragment], DerivativeFunctions);
+
+ if ((profile == EEsProfile && version >= 320) || (profile != EEsProfile && version >= 450))
+ forEachFunction(stageBuiltins[EShLangCompute], DerivativeFunctions);
+}
+
+// Relate all tables of built-ins to the AST operators.
+void TBuiltIns::relateTabledBuiltins(int /* version */, EProfile /* profile */, const SpvVersion& /* spvVersion */, EShLanguage /* stage */, TSymbolTable& symbolTable)
+{
+ RelateTabledBuiltins(BaseFunctions, symbolTable);
+ RelateTabledBuiltins(DerivativeFunctions, symbolTable);
+ RelateTabledBuiltins(CustomFunctions, symbolTable);
+}
+
+inline bool IncludeLegacy(int version, EProfile profile, const SpvVersion& spvVersion)
+{
+ return profile != EEsProfile && (version <= 130 || (spvVersion.spv == 0 && ARBCompatibility) || profile == ECompatibilityProfile);
+}
+
+// Construct TBuiltInParseables base class. This can be used for language-common constructs.
+TBuiltInParseables::TBuiltInParseables()
+{
+}
+
+// Destroy TBuiltInParseables.
+TBuiltInParseables::~TBuiltInParseables()
+{
+}
+
+TBuiltIns::TBuiltIns()
+{
+ // Set up textual representations for making all the permutations
+ // of texturing/imaging functions.
+ prefixes[EbtFloat] = "";
+ prefixes[EbtInt] = "i";
+ prefixes[EbtUint] = "u";
+#ifndef GLSLANG_WEB
+ prefixes[EbtFloat16] = "f16";
+ prefixes[EbtInt8] = "i8";
+ prefixes[EbtUint8] = "u8";
+ prefixes[EbtInt16] = "i16";
+ prefixes[EbtUint16] = "u16";
+#endif
+
+ postfixes[2] = "2";
+ postfixes[3] = "3";
+ postfixes[4] = "4";
+
+ // Map from symbolic class of texturing dimension to numeric dimensions.
+ dimMap[Esd2D] = 2;
+ dimMap[Esd3D] = 3;
+ dimMap[EsdCube] = 3;
+#ifndef GLSLANG_WEB
+ dimMap[Esd1D] = 1;
+ dimMap[EsdRect] = 2;
+ dimMap[EsdBuffer] = 1;
+ dimMap[EsdSubpass] = 2; // potentially unused for now
+#endif
+}
+
+TBuiltIns::~TBuiltIns()
+{
+}
+
+
+//
+// Add all context-independent built-in functions and variables that are present
+// for the given version and profile. Share common ones across stages, otherwise
+// make stage-specific entries.
+//
+// Most built-ins variables can be added as simple text strings. Some need to
+// be added programmatically, which is done later in IdentifyBuiltIns() below.
+//
+void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvVersion)
+{
+#ifdef GLSLANG_WEB
+ version = 310;
+ profile = EEsProfile;
+#endif
+ addTabledBuiltins(version, profile, spvVersion);
+
+ //============================================================================
+ //
+ // Prototypes for built-in functions used repeatly by different shaders
+ //
+ //============================================================================
+
+#ifndef GLSLANG_WEB
+ //
+ // Derivatives Functions.
+ //
+ TString derivativeControls (
+ "float dFdxFine(float p);"
+ "vec2 dFdxFine(vec2 p);"
+ "vec3 dFdxFine(vec3 p);"
+ "vec4 dFdxFine(vec4 p);"
+
+ "float dFdyFine(float p);"
+ "vec2 dFdyFine(vec2 p);"
+ "vec3 dFdyFine(vec3 p);"
+ "vec4 dFdyFine(vec4 p);"
+
+ "float fwidthFine(float p);"
+ "vec2 fwidthFine(vec2 p);"
+ "vec3 fwidthFine(vec3 p);"
+ "vec4 fwidthFine(vec4 p);"
+
+ "float dFdxCoarse(float p);"
+ "vec2 dFdxCoarse(vec2 p);"
+ "vec3 dFdxCoarse(vec3 p);"
+ "vec4 dFdxCoarse(vec4 p);"
+
+ "float dFdyCoarse(float p);"
+ "vec2 dFdyCoarse(vec2 p);"
+ "vec3 dFdyCoarse(vec3 p);"
+ "vec4 dFdyCoarse(vec4 p);"
+
+ "float fwidthCoarse(float p);"
+ "vec2 fwidthCoarse(vec2 p);"
+ "vec3 fwidthCoarse(vec3 p);"
+ "vec4 fwidthCoarse(vec4 p);"
+ );
+
+ TString derivativesAndControl16bits (
+ "float16_t dFdx(float16_t);"
+ "f16vec2 dFdx(f16vec2);"
+ "f16vec3 dFdx(f16vec3);"
+ "f16vec4 dFdx(f16vec4);"
+
+ "float16_t dFdy(float16_t);"
+ "f16vec2 dFdy(f16vec2);"
+ "f16vec3 dFdy(f16vec3);"
+ "f16vec4 dFdy(f16vec4);"
+
+ "float16_t dFdxFine(float16_t);"
+ "f16vec2 dFdxFine(f16vec2);"
+ "f16vec3 dFdxFine(f16vec3);"
+ "f16vec4 dFdxFine(f16vec4);"
+
+ "float16_t dFdyFine(float16_t);"
+ "f16vec2 dFdyFine(f16vec2);"
+ "f16vec3 dFdyFine(f16vec3);"
+ "f16vec4 dFdyFine(f16vec4);"
+
+ "float16_t dFdxCoarse(float16_t);"
+ "f16vec2 dFdxCoarse(f16vec2);"
+ "f16vec3 dFdxCoarse(f16vec3);"
+ "f16vec4 dFdxCoarse(f16vec4);"
+
+ "float16_t dFdyCoarse(float16_t);"
+ "f16vec2 dFdyCoarse(f16vec2);"
+ "f16vec3 dFdyCoarse(f16vec3);"
+ "f16vec4 dFdyCoarse(f16vec4);"
+
+ "float16_t fwidth(float16_t);"
+ "f16vec2 fwidth(f16vec2);"
+ "f16vec3 fwidth(f16vec3);"
+ "f16vec4 fwidth(f16vec4);"
+
+ "float16_t fwidthFine(float16_t);"
+ "f16vec2 fwidthFine(f16vec2);"
+ "f16vec3 fwidthFine(f16vec3);"
+ "f16vec4 fwidthFine(f16vec4);"
+
+ "float16_t fwidthCoarse(float16_t);"
+ "f16vec2 fwidthCoarse(f16vec2);"
+ "f16vec3 fwidthCoarse(f16vec3);"
+ "f16vec4 fwidthCoarse(f16vec4);"
+ );
+
+ TString derivativesAndControl64bits (
+ "float64_t dFdx(float64_t);"
+ "f64vec2 dFdx(f64vec2);"
+ "f64vec3 dFdx(f64vec3);"
+ "f64vec4 dFdx(f64vec4);"
+
+ "float64_t dFdy(float64_t);"
+ "f64vec2 dFdy(f64vec2);"
+ "f64vec3 dFdy(f64vec3);"
+ "f64vec4 dFdy(f64vec4);"
+
+ "float64_t dFdxFine(float64_t);"
+ "f64vec2 dFdxFine(f64vec2);"
+ "f64vec3 dFdxFine(f64vec3);"
+ "f64vec4 dFdxFine(f64vec4);"
+
+ "float64_t dFdyFine(float64_t);"
+ "f64vec2 dFdyFine(f64vec2);"
+ "f64vec3 dFdyFine(f64vec3);"
+ "f64vec4 dFdyFine(f64vec4);"
+
+ "float64_t dFdxCoarse(float64_t);"
+ "f64vec2 dFdxCoarse(f64vec2);"
+ "f64vec3 dFdxCoarse(f64vec3);"
+ "f64vec4 dFdxCoarse(f64vec4);"
+
+ "float64_t dFdyCoarse(float64_t);"
+ "f64vec2 dFdyCoarse(f64vec2);"
+ "f64vec3 dFdyCoarse(f64vec3);"
+ "f64vec4 dFdyCoarse(f64vec4);"
+
+ "float64_t fwidth(float64_t);"
+ "f64vec2 fwidth(f64vec2);"
+ "f64vec3 fwidth(f64vec3);"
+ "f64vec4 fwidth(f64vec4);"
+
+ "float64_t fwidthFine(float64_t);"
+ "f64vec2 fwidthFine(f64vec2);"
+ "f64vec3 fwidthFine(f64vec3);"
+ "f64vec4 fwidthFine(f64vec4);"
+
+ "float64_t fwidthCoarse(float64_t);"
+ "f64vec2 fwidthCoarse(f64vec2);"
+ "f64vec3 fwidthCoarse(f64vec3);"
+ "f64vec4 fwidthCoarse(f64vec4);"
+ );
+
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by both vertex and fragment shaders.
+ //
+ //============================================================================
+
+ //
+ // double functions added to desktop 4.00, but not fma, frexp, ldexp, or pack/unpack
+ //
+ if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64
+ commonBuiltins.append(
+
+ "double sqrt(double);"
+ "dvec2 sqrt(dvec2);"
+ "dvec3 sqrt(dvec3);"
+ "dvec4 sqrt(dvec4);"
+
+ "double inversesqrt(double);"
+ "dvec2 inversesqrt(dvec2);"
+ "dvec3 inversesqrt(dvec3);"
+ "dvec4 inversesqrt(dvec4);"
+
+ "double abs(double);"
+ "dvec2 abs(dvec2);"
+ "dvec3 abs(dvec3);"
+ "dvec4 abs(dvec4);"
+
+ "double sign(double);"
+ "dvec2 sign(dvec2);"
+ "dvec3 sign(dvec3);"
+ "dvec4 sign(dvec4);"
+
+ "double floor(double);"
+ "dvec2 floor(dvec2);"
+ "dvec3 floor(dvec3);"
+ "dvec4 floor(dvec4);"
+
+ "double trunc(double);"
+ "dvec2 trunc(dvec2);"
+ "dvec3 trunc(dvec3);"
+ "dvec4 trunc(dvec4);"
+
+ "double round(double);"
+ "dvec2 round(dvec2);"
+ "dvec3 round(dvec3);"
+ "dvec4 round(dvec4);"
+
+ "double roundEven(double);"
+ "dvec2 roundEven(dvec2);"
+ "dvec3 roundEven(dvec3);"
+ "dvec4 roundEven(dvec4);"
+
+ "double ceil(double);"
+ "dvec2 ceil(dvec2);"
+ "dvec3 ceil(dvec3);"
+ "dvec4 ceil(dvec4);"
+
+ "double fract(double);"
+ "dvec2 fract(dvec2);"
+ "dvec3 fract(dvec3);"
+ "dvec4 fract(dvec4);"
+
+ "double mod(double, double);"
+ "dvec2 mod(dvec2 , double);"
+ "dvec3 mod(dvec3 , double);"
+ "dvec4 mod(dvec4 , double);"
+ "dvec2 mod(dvec2 , dvec2);"
+ "dvec3 mod(dvec3 , dvec3);"
+ "dvec4 mod(dvec4 , dvec4);"
+
+ "double modf(double, out double);"
+ "dvec2 modf(dvec2, out dvec2);"
+ "dvec3 modf(dvec3, out dvec3);"
+ "dvec4 modf(dvec4, out dvec4);"
+
+ "double min(double, double);"
+ "dvec2 min(dvec2, double);"
+ "dvec3 min(dvec3, double);"
+ "dvec4 min(dvec4, double);"
+ "dvec2 min(dvec2, dvec2);"
+ "dvec3 min(dvec3, dvec3);"
+ "dvec4 min(dvec4, dvec4);"
+
+ "double max(double, double);"
+ "dvec2 max(dvec2 , double);"
+ "dvec3 max(dvec3 , double);"
+ "dvec4 max(dvec4 , double);"
+ "dvec2 max(dvec2 , dvec2);"
+ "dvec3 max(dvec3 , dvec3);"
+ "dvec4 max(dvec4 , dvec4);"
+
+ "double clamp(double, double, double);"
+ "dvec2 clamp(dvec2 , double, double);"
+ "dvec3 clamp(dvec3 , double, double);"
+ "dvec4 clamp(dvec4 , double, double);"
+ "dvec2 clamp(dvec2 , dvec2 , dvec2);"
+ "dvec3 clamp(dvec3 , dvec3 , dvec3);"
+ "dvec4 clamp(dvec4 , dvec4 , dvec4);"
+
+ "double mix(double, double, double);"
+ "dvec2 mix(dvec2, dvec2, double);"
+ "dvec3 mix(dvec3, dvec3, double);"
+ "dvec4 mix(dvec4, dvec4, double);"
+ "dvec2 mix(dvec2, dvec2, dvec2);"
+ "dvec3 mix(dvec3, dvec3, dvec3);"
+ "dvec4 mix(dvec4, dvec4, dvec4);"
+ "double mix(double, double, bool);"
+ "dvec2 mix(dvec2, dvec2, bvec2);"
+ "dvec3 mix(dvec3, dvec3, bvec3);"
+ "dvec4 mix(dvec4, dvec4, bvec4);"
+
+ "double step(double, double);"
+ "dvec2 step(dvec2 , dvec2);"
+ "dvec3 step(dvec3 , dvec3);"
+ "dvec4 step(dvec4 , dvec4);"
+ "dvec2 step(double, dvec2);"
+ "dvec3 step(double, dvec3);"
+ "dvec4 step(double, dvec4);"
+
+ "double smoothstep(double, double, double);"
+ "dvec2 smoothstep(dvec2 , dvec2 , dvec2);"
+ "dvec3 smoothstep(dvec3 , dvec3 , dvec3);"
+ "dvec4 smoothstep(dvec4 , dvec4 , dvec4);"
+ "dvec2 smoothstep(double, double, dvec2);"
+ "dvec3 smoothstep(double, double, dvec3);"
+ "dvec4 smoothstep(double, double, dvec4);"
+
+ "bool isnan(double);"
+ "bvec2 isnan(dvec2);"
+ "bvec3 isnan(dvec3);"
+ "bvec4 isnan(dvec4);"
+
+ "bool isinf(double);"
+ "bvec2 isinf(dvec2);"
+ "bvec3 isinf(dvec3);"
+ "bvec4 isinf(dvec4);"
+
+ "double length(double);"
+ "double length(dvec2);"
+ "double length(dvec3);"
+ "double length(dvec4);"
+
+ "double distance(double, double);"
+ "double distance(dvec2 , dvec2);"
+ "double distance(dvec3 , dvec3);"
+ "double distance(dvec4 , dvec4);"
+
+ "double dot(double, double);"
+ "double dot(dvec2 , dvec2);"
+ "double dot(dvec3 , dvec3);"
+ "double dot(dvec4 , dvec4);"
+
+ "dvec3 cross(dvec3, dvec3);"
+
+ "double normalize(double);"
+ "dvec2 normalize(dvec2);"
+ "dvec3 normalize(dvec3);"
+ "dvec4 normalize(dvec4);"
+
+ "double faceforward(double, double, double);"
+ "dvec2 faceforward(dvec2, dvec2, dvec2);"
+ "dvec3 faceforward(dvec3, dvec3, dvec3);"
+ "dvec4 faceforward(dvec4, dvec4, dvec4);"
+
+ "double reflect(double, double);"
+ "dvec2 reflect(dvec2 , dvec2 );"
+ "dvec3 reflect(dvec3 , dvec3 );"
+ "dvec4 reflect(dvec4 , dvec4 );"
+
+ "double refract(double, double, double);"
+ "dvec2 refract(dvec2 , dvec2 , double);"
+ "dvec3 refract(dvec3 , dvec3 , double);"
+ "dvec4 refract(dvec4 , dvec4 , double);"
+
+ "dmat2 matrixCompMult(dmat2, dmat2);"
+ "dmat3 matrixCompMult(dmat3, dmat3);"
+ "dmat4 matrixCompMult(dmat4, dmat4);"
+ "dmat2x3 matrixCompMult(dmat2x3, dmat2x3);"
+ "dmat2x4 matrixCompMult(dmat2x4, dmat2x4);"
+ "dmat3x2 matrixCompMult(dmat3x2, dmat3x2);"
+ "dmat3x4 matrixCompMult(dmat3x4, dmat3x4);"
+ "dmat4x2 matrixCompMult(dmat4x2, dmat4x2);"
+ "dmat4x3 matrixCompMult(dmat4x3, dmat4x3);"
+
+ "dmat2 outerProduct(dvec2, dvec2);"
+ "dmat3 outerProduct(dvec3, dvec3);"
+ "dmat4 outerProduct(dvec4, dvec4);"
+ "dmat2x3 outerProduct(dvec3, dvec2);"
+ "dmat3x2 outerProduct(dvec2, dvec3);"
+ "dmat2x4 outerProduct(dvec4, dvec2);"
+ "dmat4x2 outerProduct(dvec2, dvec4);"
+ "dmat3x4 outerProduct(dvec4, dvec3);"
+ "dmat4x3 outerProduct(dvec3, dvec4);"
+
+ "dmat2 transpose(dmat2);"
+ "dmat3 transpose(dmat3);"
+ "dmat4 transpose(dmat4);"
+ "dmat2x3 transpose(dmat3x2);"
+ "dmat3x2 transpose(dmat2x3);"
+ "dmat2x4 transpose(dmat4x2);"
+ "dmat4x2 transpose(dmat2x4);"
+ "dmat3x4 transpose(dmat4x3);"
+ "dmat4x3 transpose(dmat3x4);"
+
+ "double determinant(dmat2);"
+ "double determinant(dmat3);"
+ "double determinant(dmat4);"
+
+ "dmat2 inverse(dmat2);"
+ "dmat3 inverse(dmat3);"
+ "dmat4 inverse(dmat4);"
+
+ "bvec2 lessThan(dvec2, dvec2);"
+ "bvec3 lessThan(dvec3, dvec3);"
+ "bvec4 lessThan(dvec4, dvec4);"
+
+ "bvec2 lessThanEqual(dvec2, dvec2);"
+ "bvec3 lessThanEqual(dvec3, dvec3);"
+ "bvec4 lessThanEqual(dvec4, dvec4);"
+
+ "bvec2 greaterThan(dvec2, dvec2);"
+ "bvec3 greaterThan(dvec3, dvec3);"
+ "bvec4 greaterThan(dvec4, dvec4);"
+
+ "bvec2 greaterThanEqual(dvec2, dvec2);"
+ "bvec3 greaterThanEqual(dvec3, dvec3);"
+ "bvec4 greaterThanEqual(dvec4, dvec4);"
+
+ "bvec2 equal(dvec2, dvec2);"
+ "bvec3 equal(dvec3, dvec3);"
+ "bvec4 equal(dvec4, dvec4);"
+
+ "bvec2 notEqual(dvec2, dvec2);"
+ "bvec3 notEqual(dvec3, dvec3);"
+ "bvec4 notEqual(dvec4, dvec4);"
+
+ "\n");
+ }
+
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append(
+
+ "int64_t abs(int64_t);"
+ "i64vec2 abs(i64vec2);"
+ "i64vec3 abs(i64vec3);"
+ "i64vec4 abs(i64vec4);"
+
+ "int64_t sign(int64_t);"
+ "i64vec2 sign(i64vec2);"
+ "i64vec3 sign(i64vec3);"
+ "i64vec4 sign(i64vec4);"
+
+ "int64_t min(int64_t, int64_t);"
+ "i64vec2 min(i64vec2, int64_t);"
+ "i64vec3 min(i64vec3, int64_t);"
+ "i64vec4 min(i64vec4, int64_t);"
+ "i64vec2 min(i64vec2, i64vec2);"
+ "i64vec3 min(i64vec3, i64vec3);"
+ "i64vec4 min(i64vec4, i64vec4);"
+ "uint64_t min(uint64_t, uint64_t);"
+ "u64vec2 min(u64vec2, uint64_t);"
+ "u64vec3 min(u64vec3, uint64_t);"
+ "u64vec4 min(u64vec4, uint64_t);"
+ "u64vec2 min(u64vec2, u64vec2);"
+ "u64vec3 min(u64vec3, u64vec3);"
+ "u64vec4 min(u64vec4, u64vec4);"
+
+ "int64_t max(int64_t, int64_t);"
+ "i64vec2 max(i64vec2, int64_t);"
+ "i64vec3 max(i64vec3, int64_t);"
+ "i64vec4 max(i64vec4, int64_t);"
+ "i64vec2 max(i64vec2, i64vec2);"
+ "i64vec3 max(i64vec3, i64vec3);"
+ "i64vec4 max(i64vec4, i64vec4);"
+ "uint64_t max(uint64_t, uint64_t);"
+ "u64vec2 max(u64vec2, uint64_t);"
+ "u64vec3 max(u64vec3, uint64_t);"
+ "u64vec4 max(u64vec4, uint64_t);"
+ "u64vec2 max(u64vec2, u64vec2);"
+ "u64vec3 max(u64vec3, u64vec3);"
+ "u64vec4 max(u64vec4, u64vec4);"
+
+ "int64_t clamp(int64_t, int64_t, int64_t);"
+ "i64vec2 clamp(i64vec2, int64_t, int64_t);"
+ "i64vec3 clamp(i64vec3, int64_t, int64_t);"
+ "i64vec4 clamp(i64vec4, int64_t, int64_t);"
+ "i64vec2 clamp(i64vec2, i64vec2, i64vec2);"
+ "i64vec3 clamp(i64vec3, i64vec3, i64vec3);"
+ "i64vec4 clamp(i64vec4, i64vec4, i64vec4);"
+ "uint64_t clamp(uint64_t, uint64_t, uint64_t);"
+ "u64vec2 clamp(u64vec2, uint64_t, uint64_t);"
+ "u64vec3 clamp(u64vec3, uint64_t, uint64_t);"
+ "u64vec4 clamp(u64vec4, uint64_t, uint64_t);"
+ "u64vec2 clamp(u64vec2, u64vec2, u64vec2);"
+ "u64vec3 clamp(u64vec3, u64vec3, u64vec3);"
+ "u64vec4 clamp(u64vec4, u64vec4, u64vec4);"
+
+ "int64_t mix(int64_t, int64_t, bool);"
+ "i64vec2 mix(i64vec2, i64vec2, bvec2);"
+ "i64vec3 mix(i64vec3, i64vec3, bvec3);"
+ "i64vec4 mix(i64vec4, i64vec4, bvec4);"
+ "uint64_t mix(uint64_t, uint64_t, bool);"
+ "u64vec2 mix(u64vec2, u64vec2, bvec2);"
+ "u64vec3 mix(u64vec3, u64vec3, bvec3);"
+ "u64vec4 mix(u64vec4, u64vec4, bvec4);"
+
+ "int64_t doubleBitsToInt64(double);"
+ "i64vec2 doubleBitsToInt64(dvec2);"
+ "i64vec3 doubleBitsToInt64(dvec3);"
+ "i64vec4 doubleBitsToInt64(dvec4);"
+
+ "uint64_t doubleBitsToUint64(double);"
+ "u64vec2 doubleBitsToUint64(dvec2);"
+ "u64vec3 doubleBitsToUint64(dvec3);"
+ "u64vec4 doubleBitsToUint64(dvec4);"
+
+ "double int64BitsToDouble(int64_t);"
+ "dvec2 int64BitsToDouble(i64vec2);"
+ "dvec3 int64BitsToDouble(i64vec3);"
+ "dvec4 int64BitsToDouble(i64vec4);"
+
+ "double uint64BitsToDouble(uint64_t);"
+ "dvec2 uint64BitsToDouble(u64vec2);"
+ "dvec3 uint64BitsToDouble(u64vec3);"
+ "dvec4 uint64BitsToDouble(u64vec4);"
+
+ "int64_t packInt2x32(ivec2);"
+ "uint64_t packUint2x32(uvec2);"
+ "ivec2 unpackInt2x32(int64_t);"
+ "uvec2 unpackUint2x32(uint64_t);"
+
+ "bvec2 lessThan(i64vec2, i64vec2);"
+ "bvec3 lessThan(i64vec3, i64vec3);"
+ "bvec4 lessThan(i64vec4, i64vec4);"
+ "bvec2 lessThan(u64vec2, u64vec2);"
+ "bvec3 lessThan(u64vec3, u64vec3);"
+ "bvec4 lessThan(u64vec4, u64vec4);"
+
+ "bvec2 lessThanEqual(i64vec2, i64vec2);"
+ "bvec3 lessThanEqual(i64vec3, i64vec3);"
+ "bvec4 lessThanEqual(i64vec4, i64vec4);"
+ "bvec2 lessThanEqual(u64vec2, u64vec2);"
+ "bvec3 lessThanEqual(u64vec3, u64vec3);"
+ "bvec4 lessThanEqual(u64vec4, u64vec4);"
+
+ "bvec2 greaterThan(i64vec2, i64vec2);"
+ "bvec3 greaterThan(i64vec3, i64vec3);"
+ "bvec4 greaterThan(i64vec4, i64vec4);"
+ "bvec2 greaterThan(u64vec2, u64vec2);"
+ "bvec3 greaterThan(u64vec3, u64vec3);"
+ "bvec4 greaterThan(u64vec4, u64vec4);"
+
+ "bvec2 greaterThanEqual(i64vec2, i64vec2);"
+ "bvec3 greaterThanEqual(i64vec3, i64vec3);"
+ "bvec4 greaterThanEqual(i64vec4, i64vec4);"
+ "bvec2 greaterThanEqual(u64vec2, u64vec2);"
+ "bvec3 greaterThanEqual(u64vec3, u64vec3);"
+ "bvec4 greaterThanEqual(u64vec4, u64vec4);"
+
+ "bvec2 equal(i64vec2, i64vec2);"
+ "bvec3 equal(i64vec3, i64vec3);"
+ "bvec4 equal(i64vec4, i64vec4);"
+ "bvec2 equal(u64vec2, u64vec2);"
+ "bvec3 equal(u64vec3, u64vec3);"
+ "bvec4 equal(u64vec4, u64vec4);"
+
+ "bvec2 notEqual(i64vec2, i64vec2);"
+ "bvec3 notEqual(i64vec3, i64vec3);"
+ "bvec4 notEqual(i64vec4, i64vec4);"
+ "bvec2 notEqual(u64vec2, u64vec2);"
+ "bvec3 notEqual(u64vec3, u64vec3);"
+ "bvec4 notEqual(u64vec4, u64vec4);"
+
+ "int64_t findLSB(int64_t);"
+ "i64vec2 findLSB(i64vec2);"
+ "i64vec3 findLSB(i64vec3);"
+ "i64vec4 findLSB(i64vec4);"
+
+ "int64_t findLSB(uint64_t);"
+ "i64vec2 findLSB(u64vec2);"
+ "i64vec3 findLSB(u64vec3);"
+ "i64vec4 findLSB(u64vec4);"
+
+ "int64_t findMSB(int64_t);"
+ "i64vec2 findMSB(i64vec2);"
+ "i64vec3 findMSB(i64vec3);"
+ "i64vec4 findMSB(i64vec4);"
+
+ "int64_t findMSB(uint64_t);"
+ "i64vec2 findMSB(u64vec2);"
+ "i64vec3 findMSB(u64vec3);"
+ "i64vec4 findMSB(u64vec4);"
+
+ "\n"
+ );
+ }
+
+ // GL_AMD_shader_trinary_minmax
+ if (profile != EEsProfile && version >= 430) {
+ commonBuiltins.append(
+ "float min3(float, float, float);"
+ "vec2 min3(vec2, vec2, vec2);"
+ "vec3 min3(vec3, vec3, vec3);"
+ "vec4 min3(vec4, vec4, vec4);"
+
+ "int min3(int, int, int);"
+ "ivec2 min3(ivec2, ivec2, ivec2);"
+ "ivec3 min3(ivec3, ivec3, ivec3);"
+ "ivec4 min3(ivec4, ivec4, ivec4);"
+
+ "uint min3(uint, uint, uint);"
+ "uvec2 min3(uvec2, uvec2, uvec2);"
+ "uvec3 min3(uvec3, uvec3, uvec3);"
+ "uvec4 min3(uvec4, uvec4, uvec4);"
+
+ "float max3(float, float, float);"
+ "vec2 max3(vec2, vec2, vec2);"
+ "vec3 max3(vec3, vec3, vec3);"
+ "vec4 max3(vec4, vec4, vec4);"
+
+ "int max3(int, int, int);"
+ "ivec2 max3(ivec2, ivec2, ivec2);"
+ "ivec3 max3(ivec3, ivec3, ivec3);"
+ "ivec4 max3(ivec4, ivec4, ivec4);"
+
+ "uint max3(uint, uint, uint);"
+ "uvec2 max3(uvec2, uvec2, uvec2);"
+ "uvec3 max3(uvec3, uvec3, uvec3);"
+ "uvec4 max3(uvec4, uvec4, uvec4);"
+
+ "float mid3(float, float, float);"
+ "vec2 mid3(vec2, vec2, vec2);"
+ "vec3 mid3(vec3, vec3, vec3);"
+ "vec4 mid3(vec4, vec4, vec4);"
+
+ "int mid3(int, int, int);"
+ "ivec2 mid3(ivec2, ivec2, ivec2);"
+ "ivec3 mid3(ivec3, ivec3, ivec3);"
+ "ivec4 mid3(ivec4, ivec4, ivec4);"
+
+ "uint mid3(uint, uint, uint);"
+ "uvec2 mid3(uvec2, uvec2, uvec2);"
+ "uvec3 mid3(uvec3, uvec3, uvec3);"
+ "uvec4 mid3(uvec4, uvec4, uvec4);"
+
+ "float16_t min3(float16_t, float16_t, float16_t);"
+ "f16vec2 min3(f16vec2, f16vec2, f16vec2);"
+ "f16vec3 min3(f16vec3, f16vec3, f16vec3);"
+ "f16vec4 min3(f16vec4, f16vec4, f16vec4);"
+
+ "float16_t max3(float16_t, float16_t, float16_t);"
+ "f16vec2 max3(f16vec2, f16vec2, f16vec2);"
+ "f16vec3 max3(f16vec3, f16vec3, f16vec3);"
+ "f16vec4 max3(f16vec4, f16vec4, f16vec4);"
+
+ "float16_t mid3(float16_t, float16_t, float16_t);"
+ "f16vec2 mid3(f16vec2, f16vec2, f16vec2);"
+ "f16vec3 mid3(f16vec3, f16vec3, f16vec3);"
+ "f16vec4 mid3(f16vec4, f16vec4, f16vec4);"
+
+ "int16_t min3(int16_t, int16_t, int16_t);"
+ "i16vec2 min3(i16vec2, i16vec2, i16vec2);"
+ "i16vec3 min3(i16vec3, i16vec3, i16vec3);"
+ "i16vec4 min3(i16vec4, i16vec4, i16vec4);"
+
+ "int16_t max3(int16_t, int16_t, int16_t);"
+ "i16vec2 max3(i16vec2, i16vec2, i16vec2);"
+ "i16vec3 max3(i16vec3, i16vec3, i16vec3);"
+ "i16vec4 max3(i16vec4, i16vec4, i16vec4);"
+
+ "int16_t mid3(int16_t, int16_t, int16_t);"
+ "i16vec2 mid3(i16vec2, i16vec2, i16vec2);"
+ "i16vec3 mid3(i16vec3, i16vec3, i16vec3);"
+ "i16vec4 mid3(i16vec4, i16vec4, i16vec4);"
+
+ "uint16_t min3(uint16_t, uint16_t, uint16_t);"
+ "u16vec2 min3(u16vec2, u16vec2, u16vec2);"
+ "u16vec3 min3(u16vec3, u16vec3, u16vec3);"
+ "u16vec4 min3(u16vec4, u16vec4, u16vec4);"
+
+ "uint16_t max3(uint16_t, uint16_t, uint16_t);"
+ "u16vec2 max3(u16vec2, u16vec2, u16vec2);"
+ "u16vec3 max3(u16vec3, u16vec3, u16vec3);"
+ "u16vec4 max3(u16vec4, u16vec4, u16vec4);"
+
+ "uint16_t mid3(uint16_t, uint16_t, uint16_t);"
+ "u16vec2 mid3(u16vec2, u16vec2, u16vec2);"
+ "u16vec3 mid3(u16vec3, u16vec3, u16vec3);"
+ "u16vec4 mid3(u16vec4, u16vec4, u16vec4);"
+
+ "\n"
+ );
+ }
+
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 430)) {
+ commonBuiltins.append(
+ "uint atomicAdd(coherent volatile inout uint, uint, int, int, int);"
+ " int atomicAdd(coherent volatile inout int, int, int, int, int);"
+
+ "uint atomicMin(coherent volatile inout uint, uint, int, int, int);"
+ " int atomicMin(coherent volatile inout int, int, int, int, int);"
+
+ "uint atomicMax(coherent volatile inout uint, uint, int, int, int);"
+ " int atomicMax(coherent volatile inout int, int, int, int, int);"
+
+ "uint atomicAnd(coherent volatile inout uint, uint, int, int, int);"
+ " int atomicAnd(coherent volatile inout int, int, int, int, int);"
+
+ "uint atomicOr (coherent volatile inout uint, uint, int, int, int);"
+ " int atomicOr (coherent volatile inout int, int, int, int, int);"
+
+ "uint atomicXor(coherent volatile inout uint, uint, int, int, int);"
+ " int atomicXor(coherent volatile inout int, int, int, int, int);"
+
+ "uint atomicExchange(coherent volatile inout uint, uint, int, int, int);"
+ " int atomicExchange(coherent volatile inout int, int, int, int, int);"
+
+ "uint atomicCompSwap(coherent volatile inout uint, uint, uint, int, int, int, int, int);"
+ " int atomicCompSwap(coherent volatile inout int, int, int, int, int, int, int, int);"
+
+ "uint atomicLoad(coherent volatile in uint, int, int, int);"
+ " int atomicLoad(coherent volatile in int, int, int, int);"
+
+ "void atomicStore(coherent volatile out uint, uint, int, int, int);"
+ "void atomicStore(coherent volatile out int, int, int, int, int);"
+
+ "\n");
+ }
+
+ if (profile != EEsProfile && version >= 440) {
+ commonBuiltins.append(
+ "uint64_t atomicMin(coherent volatile inout uint64_t, uint64_t);"
+ " int64_t atomicMin(coherent volatile inout int64_t, int64_t);"
+ "uint64_t atomicMin(coherent volatile inout uint64_t, uint64_t, int, int, int);"
+ " int64_t atomicMin(coherent volatile inout int64_t, int64_t, int, int, int);"
+
+ "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t);"
+ " int64_t atomicMax(coherent volatile inout int64_t, int64_t);"
+ "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t, int, int, int);"
+ " int64_t atomicMax(coherent volatile inout int64_t, int64_t, int, int, int);"
+
+ "uint64_t atomicAnd(coherent volatile inout uint64_t, uint64_t);"
+ " int64_t atomicAnd(coherent volatile inout int64_t, int64_t);"
+ "uint64_t atomicAnd(coherent volatile inout uint64_t, uint64_t, int, int, int);"
+ " int64_t atomicAnd(coherent volatile inout int64_t, int64_t, int, int, int);"
+
+ "uint64_t atomicOr (coherent volatile inout uint64_t, uint64_t);"
+ " int64_t atomicOr (coherent volatile inout int64_t, int64_t);"
+ "uint64_t atomicOr (coherent volatile inout uint64_t, uint64_t, int, int, int);"
+ " int64_t atomicOr (coherent volatile inout int64_t, int64_t, int, int, int);"
+
+ "uint64_t atomicXor(coherent volatile inout uint64_t, uint64_t);"
+ " int64_t atomicXor(coherent volatile inout int64_t, int64_t);"
+ "uint64_t atomicXor(coherent volatile inout uint64_t, uint64_t, int, int, int);"
+ " int64_t atomicXor(coherent volatile inout int64_t, int64_t, int, int, int);"
+
+ "uint64_t atomicAdd(coherent volatile inout uint64_t, uint64_t);"
+ " int64_t atomicAdd(coherent volatile inout int64_t, int64_t);"
+ "uint64_t atomicAdd(coherent volatile inout uint64_t, uint64_t, int, int, int);"
+ " int64_t atomicAdd(coherent volatile inout int64_t, int64_t, int, int, int);"
+
+ "uint64_t atomicExchange(coherent volatile inout uint64_t, uint64_t);"
+ " int64_t atomicExchange(coherent volatile inout int64_t, int64_t);"
+ "uint64_t atomicExchange(coherent volatile inout uint64_t, uint64_t, int, int, int);"
+ " int64_t atomicExchange(coherent volatile inout int64_t, int64_t, int, int, int);"
+
+ "uint64_t atomicCompSwap(coherent volatile inout uint64_t, uint64_t, uint64_t);"
+ " int64_t atomicCompSwap(coherent volatile inout int64_t, int64_t, int64_t);"
+ "uint64_t atomicCompSwap(coherent volatile inout uint64_t, uint64_t, uint64_t, int, int, int, int, int);"
+ " int64_t atomicCompSwap(coherent volatile inout int64_t, int64_t, int64_t, int, int, int, int, int);"
+
+ "uint64_t atomicLoad(coherent volatile in uint64_t, int, int, int);"
+ " int64_t atomicLoad(coherent volatile in int64_t, int, int, int);"
+
+ "void atomicStore(coherent volatile out uint64_t, uint64_t, int, int, int);"
+ "void atomicStore(coherent volatile out int64_t, int64_t, int, int, int);"
+ "\n");
+ }
+#endif
+
+ if ((profile == EEsProfile && version >= 300) ||
+ (profile != EEsProfile && version >= 330)) {
+ commonBuiltins.append(
+ "int floatBitsToInt(highp float value);"
+ "ivec2 floatBitsToInt(highp vec2 value);"
+ "ivec3 floatBitsToInt(highp vec3 value);"
+ "ivec4 floatBitsToInt(highp vec4 value);"
+
+ "uint floatBitsToUint(highp float value);"
+ "uvec2 floatBitsToUint(highp vec2 value);"
+ "uvec3 floatBitsToUint(highp vec3 value);"
+ "uvec4 floatBitsToUint(highp vec4 value);"
+
+ "float intBitsToFloat(highp int value);"
+ "vec2 intBitsToFloat(highp ivec2 value);"
+ "vec3 intBitsToFloat(highp ivec3 value);"
+ "vec4 intBitsToFloat(highp ivec4 value);"
+
+ "float uintBitsToFloat(highp uint value);"
+ "vec2 uintBitsToFloat(highp uvec2 value);"
+ "vec3 uintBitsToFloat(highp uvec3 value);"
+ "vec4 uintBitsToFloat(highp uvec4 value);"
+
+ "\n");
+ }
+
+#ifndef GLSLANG_WEB
+ if ((profile != EEsProfile && version >= 400) ||
+ (profile == EEsProfile && version >= 310)) { // GL_OES_gpu_shader5
+
+ commonBuiltins.append(
+ "float fma(float, float, float );"
+ "vec2 fma(vec2, vec2, vec2 );"
+ "vec3 fma(vec3, vec3, vec3 );"
+ "vec4 fma(vec4, vec4, vec4 );"
+ "\n");
+ }
+
+ if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64
+ commonBuiltins.append(
+ "double fma(double, double, double);"
+ "dvec2 fma(dvec2, dvec2, dvec2 );"
+ "dvec3 fma(dvec3, dvec3, dvec3 );"
+ "dvec4 fma(dvec4, dvec4, dvec4 );"
+ "\n");
+ }
+
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 400)) {
+ commonBuiltins.append(
+ "float frexp(highp float, out highp int);"
+ "vec2 frexp(highp vec2, out highp ivec2);"
+ "vec3 frexp(highp vec3, out highp ivec3);"
+ "vec4 frexp(highp vec4, out highp ivec4);"
+
+ "float ldexp(highp float, highp int);"
+ "vec2 ldexp(highp vec2, highp ivec2);"
+ "vec3 ldexp(highp vec3, highp ivec3);"
+ "vec4 ldexp(highp vec4, highp ivec4);"
+
+ "\n");
+ }
+
+ if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64
+ commonBuiltins.append(
+ "double frexp(double, out int);"
+ "dvec2 frexp( dvec2, out ivec2);"
+ "dvec3 frexp( dvec3, out ivec3);"
+ "dvec4 frexp( dvec4, out ivec4);"
+
+ "double ldexp(double, int);"
+ "dvec2 ldexp( dvec2, ivec2);"
+ "dvec3 ldexp( dvec3, ivec3);"
+ "dvec4 ldexp( dvec4, ivec4);"
+
+ "double packDouble2x32(uvec2);"
+ "uvec2 unpackDouble2x32(double);"
+
+ "\n");
+ }
+#endif
+
+ if ((profile == EEsProfile && version >= 300) ||
+ (profile != EEsProfile && version >= 400)) {
+ commonBuiltins.append(
+ "highp uint packUnorm2x16(vec2);"
+ "vec2 unpackUnorm2x16(highp uint);"
+ "\n");
+ }
+
+ if ((profile == EEsProfile && version >= 300) ||
+ (profile != EEsProfile && version >= 420)) {
+ commonBuiltins.append(
+ "highp uint packSnorm2x16(vec2);"
+ " vec2 unpackSnorm2x16(highp uint);"
+ "highp uint packHalf2x16(vec2);"
+ "\n");
+ }
+
+ if (profile == EEsProfile && version >= 300) {
+ commonBuiltins.append(
+ "mediump vec2 unpackHalf2x16(highp uint);"
+ "\n");
+ } else if (profile != EEsProfile && version >= 420) {
+ commonBuiltins.append(
+ " vec2 unpackHalf2x16(highp uint);"
+ "\n");
+ }
+
+#ifndef GLSLANG_WEB
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 400)) {
+ commonBuiltins.append(
+ "highp uint packSnorm4x8(vec4);"
+ "highp uint packUnorm4x8(vec4);"
+ "\n");
+ }
+
+ if (profile == EEsProfile && version >= 310) {
+ commonBuiltins.append(
+ "mediump vec4 unpackSnorm4x8(highp uint);"
+ "mediump vec4 unpackUnorm4x8(highp uint);"
+ "\n");
+ } else if (profile != EEsProfile && version >= 400) {
+ commonBuiltins.append(
+ "vec4 unpackSnorm4x8(highp uint);"
+ "vec4 unpackUnorm4x8(highp uint);"
+ "\n");
+ }
+#endif
+
+ //
+ // Matrix Functions.
+ //
+ commonBuiltins.append(
+ "mat2 matrixCompMult(mat2 x, mat2 y);"
+ "mat3 matrixCompMult(mat3 x, mat3 y);"
+ "mat4 matrixCompMult(mat4 x, mat4 y);"
+
+ "\n");
+
+ // 120 is correct for both ES and desktop
+ if (version >= 120) {
+ commonBuiltins.append(
+ "mat2 outerProduct(vec2 c, vec2 r);"
+ "mat3 outerProduct(vec3 c, vec3 r);"
+ "mat4 outerProduct(vec4 c, vec4 r);"
+ "mat2x3 outerProduct(vec3 c, vec2 r);"
+ "mat3x2 outerProduct(vec2 c, vec3 r);"
+ "mat2x4 outerProduct(vec4 c, vec2 r);"
+ "mat4x2 outerProduct(vec2 c, vec4 r);"
+ "mat3x4 outerProduct(vec4 c, vec3 r);"
+ "mat4x3 outerProduct(vec3 c, vec4 r);"
+
+ "mat2 transpose(mat2 m);"
+ "mat3 transpose(mat3 m);"
+ "mat4 transpose(mat4 m);"
+ "mat2x3 transpose(mat3x2 m);"
+ "mat3x2 transpose(mat2x3 m);"
+ "mat2x4 transpose(mat4x2 m);"
+ "mat4x2 transpose(mat2x4 m);"
+ "mat3x4 transpose(mat4x3 m);"
+ "mat4x3 transpose(mat3x4 m);"
+
+ "mat2x3 matrixCompMult(mat2x3, mat2x3);"
+ "mat2x4 matrixCompMult(mat2x4, mat2x4);"
+ "mat3x2 matrixCompMult(mat3x2, mat3x2);"
+ "mat3x4 matrixCompMult(mat3x4, mat3x4);"
+ "mat4x2 matrixCompMult(mat4x2, mat4x2);"
+ "mat4x3 matrixCompMult(mat4x3, mat4x3);"
+
+ "\n");
+
+ // 150 is correct for both ES and desktop
+ if (version >= 150) {
+ commonBuiltins.append(
+ "float determinant(mat2 m);"
+ "float determinant(mat3 m);"
+ "float determinant(mat4 m);"
+
+ "mat2 inverse(mat2 m);"
+ "mat3 inverse(mat3 m);"
+ "mat4 inverse(mat4 m);"
+
+ "\n");
+ }
+ }
+
+#ifndef GLSLANG_WEB
+ //
+ // Original-style texture functions existing in all stages.
+ // (Per-stage functions below.)
+ //
+ if ((profile == EEsProfile && version == 100) ||
+ profile == ECompatibilityProfile ||
+ (profile == ECoreProfile && version < 420) ||
+ profile == ENoProfile) {
+ if (spvVersion.spv == 0) {
+ commonBuiltins.append(
+ "vec4 texture2D(sampler2D, vec2);"
+
+ "vec4 texture2DProj(sampler2D, vec3);"
+ "vec4 texture2DProj(sampler2D, vec4);"
+
+ "vec4 texture3D(sampler3D, vec3);" // OES_texture_3D, but caught by keyword check
+ "vec4 texture3DProj(sampler3D, vec4);" // OES_texture_3D, but caught by keyword check
+
+ "vec4 textureCube(samplerCube, vec3);"
+
+ "\n");
+ }
+ }
+
+ if ( profile == ECompatibilityProfile ||
+ (profile == ECoreProfile && version < 420) ||
+ profile == ENoProfile) {
+ if (spvVersion.spv == 0) {
+ commonBuiltins.append(
+ "vec4 texture1D(sampler1D, float);"
+
+ "vec4 texture1DProj(sampler1D, vec2);"
+ "vec4 texture1DProj(sampler1D, vec4);"
+
+ "vec4 shadow1D(sampler1DShadow, vec3);"
+ "vec4 shadow2D(sampler2DShadow, vec3);"
+ "vec4 shadow1DProj(sampler1DShadow, vec4);"
+ "vec4 shadow2DProj(sampler2DShadow, vec4);"
+
+ "vec4 texture2DRect(sampler2DRect, vec2);" // GL_ARB_texture_rectangle, caught by keyword check
+ "vec4 texture2DRectProj(sampler2DRect, vec3);" // GL_ARB_texture_rectangle, caught by keyword check
+ "vec4 texture2DRectProj(sampler2DRect, vec4);" // GL_ARB_texture_rectangle, caught by keyword check
+ "vec4 shadow2DRect(sampler2DRectShadow, vec3);" // GL_ARB_texture_rectangle, caught by keyword check
+ "vec4 shadow2DRectProj(sampler2DRectShadow, vec4);" // GL_ARB_texture_rectangle, caught by keyword check
+
+ "\n");
+ }
+ }
+
+ if (profile == EEsProfile) {
+ if (spvVersion.spv == 0) {
+ if (version < 300) {
+ commonBuiltins.append(
+ "vec4 texture2D(samplerExternalOES, vec2 coord);" // GL_OES_EGL_image_external
+ "vec4 texture2DProj(samplerExternalOES, vec3);" // GL_OES_EGL_image_external
+ "vec4 texture2DProj(samplerExternalOES, vec4);" // GL_OES_EGL_image_external
+ "\n");
+ } else {
+ commonBuiltins.append(
+ "highp ivec2 textureSize(samplerExternalOES, int lod);" // GL_OES_EGL_image_external_essl3
+ "vec4 texture(samplerExternalOES, vec2);" // GL_OES_EGL_image_external_essl3
+ "vec4 texture(samplerExternalOES, vec2, float bias);" // GL_OES_EGL_image_external_essl3
+ "vec4 textureProj(samplerExternalOES, vec3);" // GL_OES_EGL_image_external_essl3
+ "vec4 textureProj(samplerExternalOES, vec3, float bias);" // GL_OES_EGL_image_external_essl3
+ "vec4 textureProj(samplerExternalOES, vec4);" // GL_OES_EGL_image_external_essl3
+ "vec4 textureProj(samplerExternalOES, vec4, float bias);" // GL_OES_EGL_image_external_essl3
+ "vec4 texelFetch(samplerExternalOES, ivec2, int lod);" // GL_OES_EGL_image_external_essl3
+ "\n");
+ }
+ commonBuiltins.append(
+ "highp ivec2 textureSize(__samplerExternal2DY2YEXT, int lod);" // GL_EXT_YUV_target
+ "vec4 texture(__samplerExternal2DY2YEXT, vec2);" // GL_EXT_YUV_target
+ "vec4 texture(__samplerExternal2DY2YEXT, vec2, float bias);" // GL_EXT_YUV_target
+ "vec4 textureProj(__samplerExternal2DY2YEXT, vec3);" // GL_EXT_YUV_target
+ "vec4 textureProj(__samplerExternal2DY2YEXT, vec3, float bias);" // GL_EXT_YUV_target
+ "vec4 textureProj(__samplerExternal2DY2YEXT, vec4);" // GL_EXT_YUV_target
+ "vec4 textureProj(__samplerExternal2DY2YEXT, vec4, float bias);" // GL_EXT_YUV_target
+ "vec4 texelFetch(__samplerExternal2DY2YEXT sampler, ivec2, int lod);" // GL_EXT_YUV_target
+ "\n");
+ commonBuiltins.append(
+ "vec4 texture2DGradEXT(sampler2D, vec2, vec2, vec2);" // GL_EXT_shader_texture_lod
+ "vec4 texture2DProjGradEXT(sampler2D, vec3, vec2, vec2);" // GL_EXT_shader_texture_lod
+ "vec4 texture2DProjGradEXT(sampler2D, vec4, vec2, vec2);" // GL_EXT_shader_texture_lod
+ "vec4 textureCubeGradEXT(samplerCube, vec3, vec3, vec3);" // GL_EXT_shader_texture_lod
+
+ "float shadow2DEXT(sampler2DShadow, vec3);" // GL_EXT_shadow_samplers
+ "float shadow2DProjEXT(sampler2DShadow, vec4);" // GL_EXT_shadow_samplers
+
+ "\n");
+ }
+ }
+
+ //
+ // Noise functions.
+ //
+ if (spvVersion.spv == 0 && profile != EEsProfile) {
+ commonBuiltins.append(
+ "float noise1(float x);"
+ "float noise1(vec2 x);"
+ "float noise1(vec3 x);"
+ "float noise1(vec4 x);"
+
+ "vec2 noise2(float x);"
+ "vec2 noise2(vec2 x);"
+ "vec2 noise2(vec3 x);"
+ "vec2 noise2(vec4 x);"
+
+ "vec3 noise3(float x);"
+ "vec3 noise3(vec2 x);"
+ "vec3 noise3(vec3 x);"
+ "vec3 noise3(vec4 x);"
+
+ "vec4 noise4(float x);"
+ "vec4 noise4(vec2 x);"
+ "vec4 noise4(vec3 x);"
+ "vec4 noise4(vec4 x);"
+
+ "\n");
+ }
+
+ if (spvVersion.vulkan == 0) {
+ //
+ // Atomic counter functions.
+ //
+ if ((profile != EEsProfile && version >= 300) ||
+ (profile == EEsProfile && version >= 310)) {
+ commonBuiltins.append(
+ "uint atomicCounterIncrement(atomic_uint);"
+ "uint atomicCounterDecrement(atomic_uint);"
+ "uint atomicCounter(atomic_uint);"
+
+ "\n");
+ }
+ if (profile != EEsProfile && version >= 460) {
+ commonBuiltins.append(
+ "uint atomicCounterAdd(atomic_uint, uint);"
+ "uint atomicCounterSubtract(atomic_uint, uint);"
+ "uint atomicCounterMin(atomic_uint, uint);"
+ "uint atomicCounterMax(atomic_uint, uint);"
+ "uint atomicCounterAnd(atomic_uint, uint);"
+ "uint atomicCounterOr(atomic_uint, uint);"
+ "uint atomicCounterXor(atomic_uint, uint);"
+ "uint atomicCounterExchange(atomic_uint, uint);"
+ "uint atomicCounterCompSwap(atomic_uint, uint, uint);"
+
+ "\n");
+ }
+ }
+
+ // Bitfield
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 400)) {
+ commonBuiltins.append(
+ " int bitfieldExtract( int, int, int);"
+ "ivec2 bitfieldExtract(ivec2, int, int);"
+ "ivec3 bitfieldExtract(ivec3, int, int);"
+ "ivec4 bitfieldExtract(ivec4, int, int);"
+
+ " uint bitfieldExtract( uint, int, int);"
+ "uvec2 bitfieldExtract(uvec2, int, int);"
+ "uvec3 bitfieldExtract(uvec3, int, int);"
+ "uvec4 bitfieldExtract(uvec4, int, int);"
+
+ " int bitfieldInsert( int base, int, int, int);"
+ "ivec2 bitfieldInsert(ivec2 base, ivec2, int, int);"
+ "ivec3 bitfieldInsert(ivec3 base, ivec3, int, int);"
+ "ivec4 bitfieldInsert(ivec4 base, ivec4, int, int);"
+
+ " uint bitfieldInsert( uint base, uint, int, int);"
+ "uvec2 bitfieldInsert(uvec2 base, uvec2, int, int);"
+ "uvec3 bitfieldInsert(uvec3 base, uvec3, int, int);"
+ "uvec4 bitfieldInsert(uvec4 base, uvec4, int, int);"
+
+ "\n");
+ }
+
+ if (profile != EEsProfile && version >= 400) {
+ commonBuiltins.append(
+ " int findLSB( int);"
+ "ivec2 findLSB(ivec2);"
+ "ivec3 findLSB(ivec3);"
+ "ivec4 findLSB(ivec4);"
+
+ " int findLSB( uint);"
+ "ivec2 findLSB(uvec2);"
+ "ivec3 findLSB(uvec3);"
+ "ivec4 findLSB(uvec4);"
+
+ "\n");
+ } else if (profile == EEsProfile && version >= 310) {
+ commonBuiltins.append(
+ "lowp int findLSB( int);"
+ "lowp ivec2 findLSB(ivec2);"
+ "lowp ivec3 findLSB(ivec3);"
+ "lowp ivec4 findLSB(ivec4);"
+
+ "lowp int findLSB( uint);"
+ "lowp ivec2 findLSB(uvec2);"
+ "lowp ivec3 findLSB(uvec3);"
+ "lowp ivec4 findLSB(uvec4);"
+
+ "\n");
+ }
+
+ if (profile != EEsProfile && version >= 400) {
+ commonBuiltins.append(
+ " int bitCount( int);"
+ "ivec2 bitCount(ivec2);"
+ "ivec3 bitCount(ivec3);"
+ "ivec4 bitCount(ivec4);"
+
+ " int bitCount( uint);"
+ "ivec2 bitCount(uvec2);"
+ "ivec3 bitCount(uvec3);"
+ "ivec4 bitCount(uvec4);"
+
+ " int findMSB(highp int);"
+ "ivec2 findMSB(highp ivec2);"
+ "ivec3 findMSB(highp ivec3);"
+ "ivec4 findMSB(highp ivec4);"
+
+ " int findMSB(highp uint);"
+ "ivec2 findMSB(highp uvec2);"
+ "ivec3 findMSB(highp uvec3);"
+ "ivec4 findMSB(highp uvec4);"
+
+ "\n");
+ }
+
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 400)) {
+ commonBuiltins.append(
+ " uint uaddCarry(highp uint, highp uint, out lowp uint carry);"
+ "uvec2 uaddCarry(highp uvec2, highp uvec2, out lowp uvec2 carry);"
+ "uvec3 uaddCarry(highp uvec3, highp uvec3, out lowp uvec3 carry);"
+ "uvec4 uaddCarry(highp uvec4, highp uvec4, out lowp uvec4 carry);"
+
+ " uint usubBorrow(highp uint, highp uint, out lowp uint borrow);"
+ "uvec2 usubBorrow(highp uvec2, highp uvec2, out lowp uvec2 borrow);"
+ "uvec3 usubBorrow(highp uvec3, highp uvec3, out lowp uvec3 borrow);"
+ "uvec4 usubBorrow(highp uvec4, highp uvec4, out lowp uvec4 borrow);"
+
+ "void umulExtended(highp uint, highp uint, out highp uint, out highp uint lsb);"
+ "void umulExtended(highp uvec2, highp uvec2, out highp uvec2, out highp uvec2 lsb);"
+ "void umulExtended(highp uvec3, highp uvec3, out highp uvec3, out highp uvec3 lsb);"
+ "void umulExtended(highp uvec4, highp uvec4, out highp uvec4, out highp uvec4 lsb);"
+
+ "void imulExtended(highp int, highp int, out highp int, out highp int lsb);"
+ "void imulExtended(highp ivec2, highp ivec2, out highp ivec2, out highp ivec2 lsb);"
+ "void imulExtended(highp ivec3, highp ivec3, out highp ivec3, out highp ivec3 lsb);"
+ "void imulExtended(highp ivec4, highp ivec4, out highp ivec4, out highp ivec4 lsb);"
+
+ " int bitfieldReverse(highp int);"
+ "ivec2 bitfieldReverse(highp ivec2);"
+ "ivec3 bitfieldReverse(highp ivec3);"
+ "ivec4 bitfieldReverse(highp ivec4);"
+
+ " uint bitfieldReverse(highp uint);"
+ "uvec2 bitfieldReverse(highp uvec2);"
+ "uvec3 bitfieldReverse(highp uvec3);"
+ "uvec4 bitfieldReverse(highp uvec4);"
+
+ "\n");
+ }
+
+ if (profile == EEsProfile && version >= 310) {
+ commonBuiltins.append(
+ "lowp int bitCount( int);"
+ "lowp ivec2 bitCount(ivec2);"
+ "lowp ivec3 bitCount(ivec3);"
+ "lowp ivec4 bitCount(ivec4);"
+
+ "lowp int bitCount( uint);"
+ "lowp ivec2 bitCount(uvec2);"
+ "lowp ivec3 bitCount(uvec3);"
+ "lowp ivec4 bitCount(uvec4);"
+
+ "lowp int findMSB(highp int);"
+ "lowp ivec2 findMSB(highp ivec2);"
+ "lowp ivec3 findMSB(highp ivec3);"
+ "lowp ivec4 findMSB(highp ivec4);"
+
+ "lowp int findMSB(highp uint);"
+ "lowp ivec2 findMSB(highp uvec2);"
+ "lowp ivec3 findMSB(highp uvec3);"
+ "lowp ivec4 findMSB(highp uvec4);"
+
+ "\n");
+ }
+
+ // GL_ARB_shader_ballot
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append(
+ "uint64_t ballotARB(bool);"
+
+ "float readInvocationARB(float, uint);"
+ "vec2 readInvocationARB(vec2, uint);"
+ "vec3 readInvocationARB(vec3, uint);"
+ "vec4 readInvocationARB(vec4, uint);"
+
+ "int readInvocationARB(int, uint);"
+ "ivec2 readInvocationARB(ivec2, uint);"
+ "ivec3 readInvocationARB(ivec3, uint);"
+ "ivec4 readInvocationARB(ivec4, uint);"
+
+ "uint readInvocationARB(uint, uint);"
+ "uvec2 readInvocationARB(uvec2, uint);"
+ "uvec3 readInvocationARB(uvec3, uint);"
+ "uvec4 readInvocationARB(uvec4, uint);"
+
+ "float readFirstInvocationARB(float);"
+ "vec2 readFirstInvocationARB(vec2);"
+ "vec3 readFirstInvocationARB(vec3);"
+ "vec4 readFirstInvocationARB(vec4);"
+
+ "int readFirstInvocationARB(int);"
+ "ivec2 readFirstInvocationARB(ivec2);"
+ "ivec3 readFirstInvocationARB(ivec3);"
+ "ivec4 readFirstInvocationARB(ivec4);"
+
+ "uint readFirstInvocationARB(uint);"
+ "uvec2 readFirstInvocationARB(uvec2);"
+ "uvec3 readFirstInvocationARB(uvec3);"
+ "uvec4 readFirstInvocationARB(uvec4);"
+
+ "\n");
+ }
+
+ // GL_ARB_shader_group_vote
+ if (profile != EEsProfile && version >= 430) {
+ commonBuiltins.append(
+ "bool anyInvocationARB(bool);"
+ "bool allInvocationsARB(bool);"
+ "bool allInvocationsEqualARB(bool);"
+
+ "\n");
+ }
+
+ // GL_KHR_shader_subgroup
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 140)) {
+ commonBuiltins.append(
+ "void subgroupBarrier();"
+ "void subgroupMemoryBarrier();"
+ "void subgroupMemoryBarrierBuffer();"
+ "void subgroupMemoryBarrierImage();"
+ "bool subgroupElect();"
+
+ "bool subgroupAll(bool);\n"
+ "bool subgroupAny(bool);\n"
+ "uvec4 subgroupBallot(bool);\n"
+ "bool subgroupInverseBallot(uvec4);\n"
+ "bool subgroupBallotBitExtract(uvec4, uint);\n"
+ "uint subgroupBallotBitCount(uvec4);\n"
+ "uint subgroupBallotInclusiveBitCount(uvec4);\n"
+ "uint subgroupBallotExclusiveBitCount(uvec4);\n"
+ "uint subgroupBallotFindLSB(uvec4);\n"
+ "uint subgroupBallotFindMSB(uvec4);\n"
+ );
+
+ // Generate all flavors of subgroup ops.
+ static const char *subgroupOps[] =
+ {
+ "bool subgroupAllEqual(%s);\n",
+ "%s subgroupBroadcast(%s, uint);\n",
+ "%s subgroupBroadcastFirst(%s);\n",
+ "%s subgroupShuffle(%s, uint);\n",
+ "%s subgroupShuffleXor(%s, uint);\n",
+ "%s subgroupShuffleUp(%s, uint delta);\n",
+ "%s subgroupShuffleDown(%s, uint delta);\n",
+ "%s subgroupAdd(%s);\n",
+ "%s subgroupMul(%s);\n",
+ "%s subgroupMin(%s);\n",
+ "%s subgroupMax(%s);\n",
+ "%s subgroupAnd(%s);\n",
+ "%s subgroupOr(%s);\n",
+ "%s subgroupXor(%s);\n",
+ "%s subgroupInclusiveAdd(%s);\n",
+ "%s subgroupInclusiveMul(%s);\n",
+ "%s subgroupInclusiveMin(%s);\n",
+ "%s subgroupInclusiveMax(%s);\n",
+ "%s subgroupInclusiveAnd(%s);\n",
+ "%s subgroupInclusiveOr(%s);\n",
+ "%s subgroupInclusiveXor(%s);\n",
+ "%s subgroupExclusiveAdd(%s);\n",
+ "%s subgroupExclusiveMul(%s);\n",
+ "%s subgroupExclusiveMin(%s);\n",
+ "%s subgroupExclusiveMax(%s);\n",
+ "%s subgroupExclusiveAnd(%s);\n",
+ "%s subgroupExclusiveOr(%s);\n",
+ "%s subgroupExclusiveXor(%s);\n",
+ "%s subgroupClusteredAdd(%s, uint);\n",
+ "%s subgroupClusteredMul(%s, uint);\n",
+ "%s subgroupClusteredMin(%s, uint);\n",
+ "%s subgroupClusteredMax(%s, uint);\n",
+ "%s subgroupClusteredAnd(%s, uint);\n",
+ "%s subgroupClusteredOr(%s, uint);\n",
+ "%s subgroupClusteredXor(%s, uint);\n",
+ "%s subgroupQuadBroadcast(%s, uint);\n",
+ "%s subgroupQuadSwapHorizontal(%s);\n",
+ "%s subgroupQuadSwapVertical(%s);\n",
+ "%s subgroupQuadSwapDiagonal(%s);\n",
+ "uvec4 subgroupPartitionNV(%s);\n",
+ "%s subgroupPartitionedAddNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedMulNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedMinNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedMaxNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedAndNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedOrNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedXorNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedInclusiveAddNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedInclusiveMulNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedInclusiveMinNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedInclusiveMaxNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedInclusiveAndNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedInclusiveOrNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedInclusiveXorNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedExclusiveAddNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedExclusiveMulNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedExclusiveMinNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedExclusiveMaxNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedExclusiveAndNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedExclusiveOrNV(%s, uvec4 ballot);\n",
+ "%s subgroupPartitionedExclusiveXorNV(%s, uvec4 ballot);\n",
+ };
+
+ static const char *floatTypes[] = {
+ "float", "vec2", "vec3", "vec4",
+ "float16_t", "f16vec2", "f16vec3", "f16vec4",
+ };
+ static const char *doubleTypes[] = {
+ "double", "dvec2", "dvec3", "dvec4",
+ };
+ static const char *intTypes[] = {
+ "int8_t", "i8vec2", "i8vec3", "i8vec4",
+ "int16_t", "i16vec2", "i16vec3", "i16vec4",
+ "int", "ivec2", "ivec3", "ivec4",
+ "int64_t", "i64vec2", "i64vec3", "i64vec4",
+ "uint8_t", "u8vec2", "u8vec3", "u8vec4",
+ "uint16_t", "u16vec2", "u16vec3", "u16vec4",
+ "uint", "uvec2", "uvec3", "uvec4",
+ "uint64_t", "u64vec2", "u64vec3", "u64vec4",
+ };
+ static const char *boolTypes[] = {
+ "bool", "bvec2", "bvec3", "bvec4",
+ };
+
+ for (size_t i = 0; i < sizeof(subgroupOps)/sizeof(subgroupOps[0]); ++i) {
+ const char *op = subgroupOps[i];
+
+ // Logical operations don't support float
+ bool logicalOp = strstr(op, "Or") || strstr(op, "And") ||
+ (strstr(op, "Xor") && !strstr(op, "ShuffleXor"));
+ // Math operations don't support bool
+ bool mathOp = strstr(op, "Add") || strstr(op, "Mul") || strstr(op, "Min") || strstr(op, "Max");
+
+ const int bufSize = 256;
+ char buf[bufSize];
+
+ if (!logicalOp) {
+ for (size_t j = 0; j < sizeof(floatTypes)/sizeof(floatTypes[0]); ++j) {
+ snprintf(buf, bufSize, op, floatTypes[j], floatTypes[j]);
+ commonBuiltins.append(buf);
+ }
+ if (profile != EEsProfile && version >= 400) {
+ for (size_t j = 0; j < sizeof(doubleTypes)/sizeof(doubleTypes[0]); ++j) {
+ snprintf(buf, bufSize, op, doubleTypes[j], doubleTypes[j]);
+ commonBuiltins.append(buf);
+ }
+ }
+ }
+ if (!mathOp) {
+ for (size_t j = 0; j < sizeof(boolTypes)/sizeof(boolTypes[0]); ++j) {
+ snprintf(buf, bufSize, op, boolTypes[j], boolTypes[j]);
+ commonBuiltins.append(buf);
+ }
+ }
+ for (size_t j = 0; j < sizeof(intTypes)/sizeof(intTypes[0]); ++j) {
+ snprintf(buf, bufSize, op, intTypes[j], intTypes[j]);
+ commonBuiltins.append(buf);
+ }
+ }
+
+ stageBuiltins[EShLangCompute].append(
+ "void subgroupMemoryBarrierShared();"
+
+ "\n"
+ );
+ stageBuiltins[EShLangMeshNV].append(
+ "void subgroupMemoryBarrierShared();"
+ "\n"
+ );
+ stageBuiltins[EShLangTaskNV].append(
+ "void subgroupMemoryBarrierShared();"
+ "\n"
+ );
+ }
+
+ if (profile != EEsProfile && version >= 460) {
+ commonBuiltins.append(
+ "bool anyInvocation(bool);"
+ "bool allInvocations(bool);"
+ "bool allInvocationsEqual(bool);"
+
+ "\n");
+ }
+
+ // GL_AMD_shader_ballot
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append(
+ "float minInvocationsAMD(float);"
+ "vec2 minInvocationsAMD(vec2);"
+ "vec3 minInvocationsAMD(vec3);"
+ "vec4 minInvocationsAMD(vec4);"
+
+ "int minInvocationsAMD(int);"
+ "ivec2 minInvocationsAMD(ivec2);"
+ "ivec3 minInvocationsAMD(ivec3);"
+ "ivec4 minInvocationsAMD(ivec4);"
+
+ "uint minInvocationsAMD(uint);"
+ "uvec2 minInvocationsAMD(uvec2);"
+ "uvec3 minInvocationsAMD(uvec3);"
+ "uvec4 minInvocationsAMD(uvec4);"
+
+ "double minInvocationsAMD(double);"
+ "dvec2 minInvocationsAMD(dvec2);"
+ "dvec3 minInvocationsAMD(dvec3);"
+ "dvec4 minInvocationsAMD(dvec4);"
+
+ "int64_t minInvocationsAMD(int64_t);"
+ "i64vec2 minInvocationsAMD(i64vec2);"
+ "i64vec3 minInvocationsAMD(i64vec3);"
+ "i64vec4 minInvocationsAMD(i64vec4);"
+
+ "uint64_t minInvocationsAMD(uint64_t);"
+ "u64vec2 minInvocationsAMD(u64vec2);"
+ "u64vec3 minInvocationsAMD(u64vec3);"
+ "u64vec4 minInvocationsAMD(u64vec4);"
+
+ "float16_t minInvocationsAMD(float16_t);"
+ "f16vec2 minInvocationsAMD(f16vec2);"
+ "f16vec3 minInvocationsAMD(f16vec3);"
+ "f16vec4 minInvocationsAMD(f16vec4);"
+
+ "int16_t minInvocationsAMD(int16_t);"
+ "i16vec2 minInvocationsAMD(i16vec2);"
+ "i16vec3 minInvocationsAMD(i16vec3);"
+ "i16vec4 minInvocationsAMD(i16vec4);"
+
+ "uint16_t minInvocationsAMD(uint16_t);"
+ "u16vec2 minInvocationsAMD(u16vec2);"
+ "u16vec3 minInvocationsAMD(u16vec3);"
+ "u16vec4 minInvocationsAMD(u16vec4);"
+
+ "float minInvocationsInclusiveScanAMD(float);"
+ "vec2 minInvocationsInclusiveScanAMD(vec2);"
+ "vec3 minInvocationsInclusiveScanAMD(vec3);"
+ "vec4 minInvocationsInclusiveScanAMD(vec4);"
+
+ "int minInvocationsInclusiveScanAMD(int);"
+ "ivec2 minInvocationsInclusiveScanAMD(ivec2);"
+ "ivec3 minInvocationsInclusiveScanAMD(ivec3);"
+ "ivec4 minInvocationsInclusiveScanAMD(ivec4);"
+
+ "uint minInvocationsInclusiveScanAMD(uint);"
+ "uvec2 minInvocationsInclusiveScanAMD(uvec2);"
+ "uvec3 minInvocationsInclusiveScanAMD(uvec3);"
+ "uvec4 minInvocationsInclusiveScanAMD(uvec4);"
+
+ "double minInvocationsInclusiveScanAMD(double);"
+ "dvec2 minInvocationsInclusiveScanAMD(dvec2);"
+ "dvec3 minInvocationsInclusiveScanAMD(dvec3);"
+ "dvec4 minInvocationsInclusiveScanAMD(dvec4);"
+
+ "int64_t minInvocationsInclusiveScanAMD(int64_t);"
+ "i64vec2 minInvocationsInclusiveScanAMD(i64vec2);"
+ "i64vec3 minInvocationsInclusiveScanAMD(i64vec3);"
+ "i64vec4 minInvocationsInclusiveScanAMD(i64vec4);"
+
+ "uint64_t minInvocationsInclusiveScanAMD(uint64_t);"
+ "u64vec2 minInvocationsInclusiveScanAMD(u64vec2);"
+ "u64vec3 minInvocationsInclusiveScanAMD(u64vec3);"
+ "u64vec4 minInvocationsInclusiveScanAMD(u64vec4);"
+
+ "float16_t minInvocationsInclusiveScanAMD(float16_t);"
+ "f16vec2 minInvocationsInclusiveScanAMD(f16vec2);"
+ "f16vec3 minInvocationsInclusiveScanAMD(f16vec3);"
+ "f16vec4 minInvocationsInclusiveScanAMD(f16vec4);"
+
+ "int16_t minInvocationsInclusiveScanAMD(int16_t);"
+ "i16vec2 minInvocationsInclusiveScanAMD(i16vec2);"
+ "i16vec3 minInvocationsInclusiveScanAMD(i16vec3);"
+ "i16vec4 minInvocationsInclusiveScanAMD(i16vec4);"
+
+ "uint16_t minInvocationsInclusiveScanAMD(uint16_t);"
+ "u16vec2 minInvocationsInclusiveScanAMD(u16vec2);"
+ "u16vec3 minInvocationsInclusiveScanAMD(u16vec3);"
+ "u16vec4 minInvocationsInclusiveScanAMD(u16vec4);"
+
+ "float minInvocationsExclusiveScanAMD(float);"
+ "vec2 minInvocationsExclusiveScanAMD(vec2);"
+ "vec3 minInvocationsExclusiveScanAMD(vec3);"
+ "vec4 minInvocationsExclusiveScanAMD(vec4);"
+
+ "int minInvocationsExclusiveScanAMD(int);"
+ "ivec2 minInvocationsExclusiveScanAMD(ivec2);"
+ "ivec3 minInvocationsExclusiveScanAMD(ivec3);"
+ "ivec4 minInvocationsExclusiveScanAMD(ivec4);"
+
+ "uint minInvocationsExclusiveScanAMD(uint);"
+ "uvec2 minInvocationsExclusiveScanAMD(uvec2);"
+ "uvec3 minInvocationsExclusiveScanAMD(uvec3);"
+ "uvec4 minInvocationsExclusiveScanAMD(uvec4);"
+
+ "double minInvocationsExclusiveScanAMD(double);"
+ "dvec2 minInvocationsExclusiveScanAMD(dvec2);"
+ "dvec3 minInvocationsExclusiveScanAMD(dvec3);"
+ "dvec4 minInvocationsExclusiveScanAMD(dvec4);"
+
+ "int64_t minInvocationsExclusiveScanAMD(int64_t);"
+ "i64vec2 minInvocationsExclusiveScanAMD(i64vec2);"
+ "i64vec3 minInvocationsExclusiveScanAMD(i64vec3);"
+ "i64vec4 minInvocationsExclusiveScanAMD(i64vec4);"
+
+ "uint64_t minInvocationsExclusiveScanAMD(uint64_t);"
+ "u64vec2 minInvocationsExclusiveScanAMD(u64vec2);"
+ "u64vec3 minInvocationsExclusiveScanAMD(u64vec3);"
+ "u64vec4 minInvocationsExclusiveScanAMD(u64vec4);"
+
+ "float16_t minInvocationsExclusiveScanAMD(float16_t);"
+ "f16vec2 minInvocationsExclusiveScanAMD(f16vec2);"
+ "f16vec3 minInvocationsExclusiveScanAMD(f16vec3);"
+ "f16vec4 minInvocationsExclusiveScanAMD(f16vec4);"
+
+ "int16_t minInvocationsExclusiveScanAMD(int16_t);"
+ "i16vec2 minInvocationsExclusiveScanAMD(i16vec2);"
+ "i16vec3 minInvocationsExclusiveScanAMD(i16vec3);"
+ "i16vec4 minInvocationsExclusiveScanAMD(i16vec4);"
+
+ "uint16_t minInvocationsExclusiveScanAMD(uint16_t);"
+ "u16vec2 minInvocationsExclusiveScanAMD(u16vec2);"
+ "u16vec3 minInvocationsExclusiveScanAMD(u16vec3);"
+ "u16vec4 minInvocationsExclusiveScanAMD(u16vec4);"
+
+ "float maxInvocationsAMD(float);"
+ "vec2 maxInvocationsAMD(vec2);"
+ "vec3 maxInvocationsAMD(vec3);"
+ "vec4 maxInvocationsAMD(vec4);"
+
+ "int maxInvocationsAMD(int);"
+ "ivec2 maxInvocationsAMD(ivec2);"
+ "ivec3 maxInvocationsAMD(ivec3);"
+ "ivec4 maxInvocationsAMD(ivec4);"
+
+ "uint maxInvocationsAMD(uint);"
+ "uvec2 maxInvocationsAMD(uvec2);"
+ "uvec3 maxInvocationsAMD(uvec3);"
+ "uvec4 maxInvocationsAMD(uvec4);"
+
+ "double maxInvocationsAMD(double);"
+ "dvec2 maxInvocationsAMD(dvec2);"
+ "dvec3 maxInvocationsAMD(dvec3);"
+ "dvec4 maxInvocationsAMD(dvec4);"
+
+ "int64_t maxInvocationsAMD(int64_t);"
+ "i64vec2 maxInvocationsAMD(i64vec2);"
+ "i64vec3 maxInvocationsAMD(i64vec3);"
+ "i64vec4 maxInvocationsAMD(i64vec4);"
+
+ "uint64_t maxInvocationsAMD(uint64_t);"
+ "u64vec2 maxInvocationsAMD(u64vec2);"
+ "u64vec3 maxInvocationsAMD(u64vec3);"
+ "u64vec4 maxInvocationsAMD(u64vec4);"
+
+ "float16_t maxInvocationsAMD(float16_t);"
+ "f16vec2 maxInvocationsAMD(f16vec2);"
+ "f16vec3 maxInvocationsAMD(f16vec3);"
+ "f16vec4 maxInvocationsAMD(f16vec4);"
+
+ "int16_t maxInvocationsAMD(int16_t);"
+ "i16vec2 maxInvocationsAMD(i16vec2);"
+ "i16vec3 maxInvocationsAMD(i16vec3);"
+ "i16vec4 maxInvocationsAMD(i16vec4);"
+
+ "uint16_t maxInvocationsAMD(uint16_t);"
+ "u16vec2 maxInvocationsAMD(u16vec2);"
+ "u16vec3 maxInvocationsAMD(u16vec3);"
+ "u16vec4 maxInvocationsAMD(u16vec4);"
+
+ "float maxInvocationsInclusiveScanAMD(float);"
+ "vec2 maxInvocationsInclusiveScanAMD(vec2);"
+ "vec3 maxInvocationsInclusiveScanAMD(vec3);"
+ "vec4 maxInvocationsInclusiveScanAMD(vec4);"
+
+ "int maxInvocationsInclusiveScanAMD(int);"
+ "ivec2 maxInvocationsInclusiveScanAMD(ivec2);"
+ "ivec3 maxInvocationsInclusiveScanAMD(ivec3);"
+ "ivec4 maxInvocationsInclusiveScanAMD(ivec4);"
+
+ "uint maxInvocationsInclusiveScanAMD(uint);"
+ "uvec2 maxInvocationsInclusiveScanAMD(uvec2);"
+ "uvec3 maxInvocationsInclusiveScanAMD(uvec3);"
+ "uvec4 maxInvocationsInclusiveScanAMD(uvec4);"
+
+ "double maxInvocationsInclusiveScanAMD(double);"
+ "dvec2 maxInvocationsInclusiveScanAMD(dvec2);"
+ "dvec3 maxInvocationsInclusiveScanAMD(dvec3);"
+ "dvec4 maxInvocationsInclusiveScanAMD(dvec4);"
+
+ "int64_t maxInvocationsInclusiveScanAMD(int64_t);"
+ "i64vec2 maxInvocationsInclusiveScanAMD(i64vec2);"
+ "i64vec3 maxInvocationsInclusiveScanAMD(i64vec3);"
+ "i64vec4 maxInvocationsInclusiveScanAMD(i64vec4);"
+
+ "uint64_t maxInvocationsInclusiveScanAMD(uint64_t);"
+ "u64vec2 maxInvocationsInclusiveScanAMD(u64vec2);"
+ "u64vec3 maxInvocationsInclusiveScanAMD(u64vec3);"
+ "u64vec4 maxInvocationsInclusiveScanAMD(u64vec4);"
+
+ "float16_t maxInvocationsInclusiveScanAMD(float16_t);"
+ "f16vec2 maxInvocationsInclusiveScanAMD(f16vec2);"
+ "f16vec3 maxInvocationsInclusiveScanAMD(f16vec3);"
+ "f16vec4 maxInvocationsInclusiveScanAMD(f16vec4);"
+
+ "int16_t maxInvocationsInclusiveScanAMD(int16_t);"
+ "i16vec2 maxInvocationsInclusiveScanAMD(i16vec2);"
+ "i16vec3 maxInvocationsInclusiveScanAMD(i16vec3);"
+ "i16vec4 maxInvocationsInclusiveScanAMD(i16vec4);"
+
+ "uint16_t maxInvocationsInclusiveScanAMD(uint16_t);"
+ "u16vec2 maxInvocationsInclusiveScanAMD(u16vec2);"
+ "u16vec3 maxInvocationsInclusiveScanAMD(u16vec3);"
+ "u16vec4 maxInvocationsInclusiveScanAMD(u16vec4);"
+
+ "float maxInvocationsExclusiveScanAMD(float);"
+ "vec2 maxInvocationsExclusiveScanAMD(vec2);"
+ "vec3 maxInvocationsExclusiveScanAMD(vec3);"
+ "vec4 maxInvocationsExclusiveScanAMD(vec4);"
+
+ "int maxInvocationsExclusiveScanAMD(int);"
+ "ivec2 maxInvocationsExclusiveScanAMD(ivec2);"
+ "ivec3 maxInvocationsExclusiveScanAMD(ivec3);"
+ "ivec4 maxInvocationsExclusiveScanAMD(ivec4);"
+
+ "uint maxInvocationsExclusiveScanAMD(uint);"
+ "uvec2 maxInvocationsExclusiveScanAMD(uvec2);"
+ "uvec3 maxInvocationsExclusiveScanAMD(uvec3);"
+ "uvec4 maxInvocationsExclusiveScanAMD(uvec4);"
+
+ "double maxInvocationsExclusiveScanAMD(double);"
+ "dvec2 maxInvocationsExclusiveScanAMD(dvec2);"
+ "dvec3 maxInvocationsExclusiveScanAMD(dvec3);"
+ "dvec4 maxInvocationsExclusiveScanAMD(dvec4);"
+
+ "int64_t maxInvocationsExclusiveScanAMD(int64_t);"
+ "i64vec2 maxInvocationsExclusiveScanAMD(i64vec2);"
+ "i64vec3 maxInvocationsExclusiveScanAMD(i64vec3);"
+ "i64vec4 maxInvocationsExclusiveScanAMD(i64vec4);"
+
+ "uint64_t maxInvocationsExclusiveScanAMD(uint64_t);"
+ "u64vec2 maxInvocationsExclusiveScanAMD(u64vec2);"
+ "u64vec3 maxInvocationsExclusiveScanAMD(u64vec3);"
+ "u64vec4 maxInvocationsExclusiveScanAMD(u64vec4);"
+
+ "float16_t maxInvocationsExclusiveScanAMD(float16_t);"
+ "f16vec2 maxInvocationsExclusiveScanAMD(f16vec2);"
+ "f16vec3 maxInvocationsExclusiveScanAMD(f16vec3);"
+ "f16vec4 maxInvocationsExclusiveScanAMD(f16vec4);"
+
+ "int16_t maxInvocationsExclusiveScanAMD(int16_t);"
+ "i16vec2 maxInvocationsExclusiveScanAMD(i16vec2);"
+ "i16vec3 maxInvocationsExclusiveScanAMD(i16vec3);"
+ "i16vec4 maxInvocationsExclusiveScanAMD(i16vec4);"
+
+ "uint16_t maxInvocationsExclusiveScanAMD(uint16_t);"
+ "u16vec2 maxInvocationsExclusiveScanAMD(u16vec2);"
+ "u16vec3 maxInvocationsExclusiveScanAMD(u16vec3);"
+ "u16vec4 maxInvocationsExclusiveScanAMD(u16vec4);"
+
+ "float addInvocationsAMD(float);"
+ "vec2 addInvocationsAMD(vec2);"
+ "vec3 addInvocationsAMD(vec3);"
+ "vec4 addInvocationsAMD(vec4);"
+
+ "int addInvocationsAMD(int);"
+ "ivec2 addInvocationsAMD(ivec2);"
+ "ivec3 addInvocationsAMD(ivec3);"
+ "ivec4 addInvocationsAMD(ivec4);"
+
+ "uint addInvocationsAMD(uint);"
+ "uvec2 addInvocationsAMD(uvec2);"
+ "uvec3 addInvocationsAMD(uvec3);"
+ "uvec4 addInvocationsAMD(uvec4);"
+
+ "double addInvocationsAMD(double);"
+ "dvec2 addInvocationsAMD(dvec2);"
+ "dvec3 addInvocationsAMD(dvec3);"
+ "dvec4 addInvocationsAMD(dvec4);"
+
+ "int64_t addInvocationsAMD(int64_t);"
+ "i64vec2 addInvocationsAMD(i64vec2);"
+ "i64vec3 addInvocationsAMD(i64vec3);"
+ "i64vec4 addInvocationsAMD(i64vec4);"
+
+ "uint64_t addInvocationsAMD(uint64_t);"
+ "u64vec2 addInvocationsAMD(u64vec2);"
+ "u64vec3 addInvocationsAMD(u64vec3);"
+ "u64vec4 addInvocationsAMD(u64vec4);"
+
+ "float16_t addInvocationsAMD(float16_t);"
+ "f16vec2 addInvocationsAMD(f16vec2);"
+ "f16vec3 addInvocationsAMD(f16vec3);"
+ "f16vec4 addInvocationsAMD(f16vec4);"
+
+ "int16_t addInvocationsAMD(int16_t);"
+ "i16vec2 addInvocationsAMD(i16vec2);"
+ "i16vec3 addInvocationsAMD(i16vec3);"
+ "i16vec4 addInvocationsAMD(i16vec4);"
+
+ "uint16_t addInvocationsAMD(uint16_t);"
+ "u16vec2 addInvocationsAMD(u16vec2);"
+ "u16vec3 addInvocationsAMD(u16vec3);"
+ "u16vec4 addInvocationsAMD(u16vec4);"
+
+ "float addInvocationsInclusiveScanAMD(float);"
+ "vec2 addInvocationsInclusiveScanAMD(vec2);"
+ "vec3 addInvocationsInclusiveScanAMD(vec3);"
+ "vec4 addInvocationsInclusiveScanAMD(vec4);"
+
+ "int addInvocationsInclusiveScanAMD(int);"
+ "ivec2 addInvocationsInclusiveScanAMD(ivec2);"
+ "ivec3 addInvocationsInclusiveScanAMD(ivec3);"
+ "ivec4 addInvocationsInclusiveScanAMD(ivec4);"
+
+ "uint addInvocationsInclusiveScanAMD(uint);"
+ "uvec2 addInvocationsInclusiveScanAMD(uvec2);"
+ "uvec3 addInvocationsInclusiveScanAMD(uvec3);"
+ "uvec4 addInvocationsInclusiveScanAMD(uvec4);"
+
+ "double addInvocationsInclusiveScanAMD(double);"
+ "dvec2 addInvocationsInclusiveScanAMD(dvec2);"
+ "dvec3 addInvocationsInclusiveScanAMD(dvec3);"
+ "dvec4 addInvocationsInclusiveScanAMD(dvec4);"
+
+ "int64_t addInvocationsInclusiveScanAMD(int64_t);"
+ "i64vec2 addInvocationsInclusiveScanAMD(i64vec2);"
+ "i64vec3 addInvocationsInclusiveScanAMD(i64vec3);"
+ "i64vec4 addInvocationsInclusiveScanAMD(i64vec4);"
+
+ "uint64_t addInvocationsInclusiveScanAMD(uint64_t);"
+ "u64vec2 addInvocationsInclusiveScanAMD(u64vec2);"
+ "u64vec3 addInvocationsInclusiveScanAMD(u64vec3);"
+ "u64vec4 addInvocationsInclusiveScanAMD(u64vec4);"
+
+ "float16_t addInvocationsInclusiveScanAMD(float16_t);"
+ "f16vec2 addInvocationsInclusiveScanAMD(f16vec2);"
+ "f16vec3 addInvocationsInclusiveScanAMD(f16vec3);"
+ "f16vec4 addInvocationsInclusiveScanAMD(f16vec4);"
+
+ "int16_t addInvocationsInclusiveScanAMD(int16_t);"
+ "i16vec2 addInvocationsInclusiveScanAMD(i16vec2);"
+ "i16vec3 addInvocationsInclusiveScanAMD(i16vec3);"
+ "i16vec4 addInvocationsInclusiveScanAMD(i16vec4);"
+
+ "uint16_t addInvocationsInclusiveScanAMD(uint16_t);"
+ "u16vec2 addInvocationsInclusiveScanAMD(u16vec2);"
+ "u16vec3 addInvocationsInclusiveScanAMD(u16vec3);"
+ "u16vec4 addInvocationsInclusiveScanAMD(u16vec4);"
+
+ "float addInvocationsExclusiveScanAMD(float);"
+ "vec2 addInvocationsExclusiveScanAMD(vec2);"
+ "vec3 addInvocationsExclusiveScanAMD(vec3);"
+ "vec4 addInvocationsExclusiveScanAMD(vec4);"
+
+ "int addInvocationsExclusiveScanAMD(int);"
+ "ivec2 addInvocationsExclusiveScanAMD(ivec2);"
+ "ivec3 addInvocationsExclusiveScanAMD(ivec3);"
+ "ivec4 addInvocationsExclusiveScanAMD(ivec4);"
+
+ "uint addInvocationsExclusiveScanAMD(uint);"
+ "uvec2 addInvocationsExclusiveScanAMD(uvec2);"
+ "uvec3 addInvocationsExclusiveScanAMD(uvec3);"
+ "uvec4 addInvocationsExclusiveScanAMD(uvec4);"
+
+ "double addInvocationsExclusiveScanAMD(double);"
+ "dvec2 addInvocationsExclusiveScanAMD(dvec2);"
+ "dvec3 addInvocationsExclusiveScanAMD(dvec3);"
+ "dvec4 addInvocationsExclusiveScanAMD(dvec4);"
+
+ "int64_t addInvocationsExclusiveScanAMD(int64_t);"
+ "i64vec2 addInvocationsExclusiveScanAMD(i64vec2);"
+ "i64vec3 addInvocationsExclusiveScanAMD(i64vec3);"
+ "i64vec4 addInvocationsExclusiveScanAMD(i64vec4);"
+
+ "uint64_t addInvocationsExclusiveScanAMD(uint64_t);"
+ "u64vec2 addInvocationsExclusiveScanAMD(u64vec2);"
+ "u64vec3 addInvocationsExclusiveScanAMD(u64vec3);"
+ "u64vec4 addInvocationsExclusiveScanAMD(u64vec4);"
+
+ "float16_t addInvocationsExclusiveScanAMD(float16_t);"
+ "f16vec2 addInvocationsExclusiveScanAMD(f16vec2);"
+ "f16vec3 addInvocationsExclusiveScanAMD(f16vec3);"
+ "f16vec4 addInvocationsExclusiveScanAMD(f16vec4);"
+
+ "int16_t addInvocationsExclusiveScanAMD(int16_t);"
+ "i16vec2 addInvocationsExclusiveScanAMD(i16vec2);"
+ "i16vec3 addInvocationsExclusiveScanAMD(i16vec3);"
+ "i16vec4 addInvocationsExclusiveScanAMD(i16vec4);"
+
+ "uint16_t addInvocationsExclusiveScanAMD(uint16_t);"
+ "u16vec2 addInvocationsExclusiveScanAMD(u16vec2);"
+ "u16vec3 addInvocationsExclusiveScanAMD(u16vec3);"
+ "u16vec4 addInvocationsExclusiveScanAMD(u16vec4);"
+
+ "float minInvocationsNonUniformAMD(float);"
+ "vec2 minInvocationsNonUniformAMD(vec2);"
+ "vec3 minInvocationsNonUniformAMD(vec3);"
+ "vec4 minInvocationsNonUniformAMD(vec4);"
+
+ "int minInvocationsNonUniformAMD(int);"
+ "ivec2 minInvocationsNonUniformAMD(ivec2);"
+ "ivec3 minInvocationsNonUniformAMD(ivec3);"
+ "ivec4 minInvocationsNonUniformAMD(ivec4);"
+
+ "uint minInvocationsNonUniformAMD(uint);"
+ "uvec2 minInvocationsNonUniformAMD(uvec2);"
+ "uvec3 minInvocationsNonUniformAMD(uvec3);"
+ "uvec4 minInvocationsNonUniformAMD(uvec4);"
+
+ "double minInvocationsNonUniformAMD(double);"
+ "dvec2 minInvocationsNonUniformAMD(dvec2);"
+ "dvec3 minInvocationsNonUniformAMD(dvec3);"
+ "dvec4 minInvocationsNonUniformAMD(dvec4);"
+
+ "int64_t minInvocationsNonUniformAMD(int64_t);"
+ "i64vec2 minInvocationsNonUniformAMD(i64vec2);"
+ "i64vec3 minInvocationsNonUniformAMD(i64vec3);"
+ "i64vec4 minInvocationsNonUniformAMD(i64vec4);"
+
+ "uint64_t minInvocationsNonUniformAMD(uint64_t);"
+ "u64vec2 minInvocationsNonUniformAMD(u64vec2);"
+ "u64vec3 minInvocationsNonUniformAMD(u64vec3);"
+ "u64vec4 minInvocationsNonUniformAMD(u64vec4);"
+
+ "float16_t minInvocationsNonUniformAMD(float16_t);"
+ "f16vec2 minInvocationsNonUniformAMD(f16vec2);"
+ "f16vec3 minInvocationsNonUniformAMD(f16vec3);"
+ "f16vec4 minInvocationsNonUniformAMD(f16vec4);"
+
+ "int16_t minInvocationsNonUniformAMD(int16_t);"
+ "i16vec2 minInvocationsNonUniformAMD(i16vec2);"
+ "i16vec3 minInvocationsNonUniformAMD(i16vec3);"
+ "i16vec4 minInvocationsNonUniformAMD(i16vec4);"
+
+ "uint16_t minInvocationsNonUniformAMD(uint16_t);"
+ "u16vec2 minInvocationsNonUniformAMD(u16vec2);"
+ "u16vec3 minInvocationsNonUniformAMD(u16vec3);"
+ "u16vec4 minInvocationsNonUniformAMD(u16vec4);"
+
+ "float minInvocationsInclusiveScanNonUniformAMD(float);"
+ "vec2 minInvocationsInclusiveScanNonUniformAMD(vec2);"
+ "vec3 minInvocationsInclusiveScanNonUniformAMD(vec3);"
+ "vec4 minInvocationsInclusiveScanNonUniformAMD(vec4);"
+
+ "int minInvocationsInclusiveScanNonUniformAMD(int);"
+ "ivec2 minInvocationsInclusiveScanNonUniformAMD(ivec2);"
+ "ivec3 minInvocationsInclusiveScanNonUniformAMD(ivec3);"
+ "ivec4 minInvocationsInclusiveScanNonUniformAMD(ivec4);"
+
+ "uint minInvocationsInclusiveScanNonUniformAMD(uint);"
+ "uvec2 minInvocationsInclusiveScanNonUniformAMD(uvec2);"
+ "uvec3 minInvocationsInclusiveScanNonUniformAMD(uvec3);"
+ "uvec4 minInvocationsInclusiveScanNonUniformAMD(uvec4);"
+
+ "double minInvocationsInclusiveScanNonUniformAMD(double);"
+ "dvec2 minInvocationsInclusiveScanNonUniformAMD(dvec2);"
+ "dvec3 minInvocationsInclusiveScanNonUniformAMD(dvec3);"
+ "dvec4 minInvocationsInclusiveScanNonUniformAMD(dvec4);"
+
+ "int64_t minInvocationsInclusiveScanNonUniformAMD(int64_t);"
+ "i64vec2 minInvocationsInclusiveScanNonUniformAMD(i64vec2);"
+ "i64vec3 minInvocationsInclusiveScanNonUniformAMD(i64vec3);"
+ "i64vec4 minInvocationsInclusiveScanNonUniformAMD(i64vec4);"
+
+ "uint64_t minInvocationsInclusiveScanNonUniformAMD(uint64_t);"
+ "u64vec2 minInvocationsInclusiveScanNonUniformAMD(u64vec2);"
+ "u64vec3 minInvocationsInclusiveScanNonUniformAMD(u64vec3);"
+ "u64vec4 minInvocationsInclusiveScanNonUniformAMD(u64vec4);"
+
+ "float16_t minInvocationsInclusiveScanNonUniformAMD(float16_t);"
+ "f16vec2 minInvocationsInclusiveScanNonUniformAMD(f16vec2);"
+ "f16vec3 minInvocationsInclusiveScanNonUniformAMD(f16vec3);"
+ "f16vec4 minInvocationsInclusiveScanNonUniformAMD(f16vec4);"
+
+ "int16_t minInvocationsInclusiveScanNonUniformAMD(int16_t);"
+ "i16vec2 minInvocationsInclusiveScanNonUniformAMD(i16vec2);"
+ "i16vec3 minInvocationsInclusiveScanNonUniformAMD(i16vec3);"
+ "i16vec4 minInvocationsInclusiveScanNonUniformAMD(i16vec4);"
+
+ "uint16_t minInvocationsInclusiveScanNonUniformAMD(uint16_t);"
+ "u16vec2 minInvocationsInclusiveScanNonUniformAMD(u16vec2);"
+ "u16vec3 minInvocationsInclusiveScanNonUniformAMD(u16vec3);"
+ "u16vec4 minInvocationsInclusiveScanNonUniformAMD(u16vec4);"
+
+ "float minInvocationsExclusiveScanNonUniformAMD(float);"
+ "vec2 minInvocationsExclusiveScanNonUniformAMD(vec2);"
+ "vec3 minInvocationsExclusiveScanNonUniformAMD(vec3);"
+ "vec4 minInvocationsExclusiveScanNonUniformAMD(vec4);"
+
+ "int minInvocationsExclusiveScanNonUniformAMD(int);"
+ "ivec2 minInvocationsExclusiveScanNonUniformAMD(ivec2);"
+ "ivec3 minInvocationsExclusiveScanNonUniformAMD(ivec3);"
+ "ivec4 minInvocationsExclusiveScanNonUniformAMD(ivec4);"
+
+ "uint minInvocationsExclusiveScanNonUniformAMD(uint);"
+ "uvec2 minInvocationsExclusiveScanNonUniformAMD(uvec2);"
+ "uvec3 minInvocationsExclusiveScanNonUniformAMD(uvec3);"
+ "uvec4 minInvocationsExclusiveScanNonUniformAMD(uvec4);"
+
+ "double minInvocationsExclusiveScanNonUniformAMD(double);"
+ "dvec2 minInvocationsExclusiveScanNonUniformAMD(dvec2);"
+ "dvec3 minInvocationsExclusiveScanNonUniformAMD(dvec3);"
+ "dvec4 minInvocationsExclusiveScanNonUniformAMD(dvec4);"
+
+ "int64_t minInvocationsExclusiveScanNonUniformAMD(int64_t);"
+ "i64vec2 minInvocationsExclusiveScanNonUniformAMD(i64vec2);"
+ "i64vec3 minInvocationsExclusiveScanNonUniformAMD(i64vec3);"
+ "i64vec4 minInvocationsExclusiveScanNonUniformAMD(i64vec4);"
+
+ "uint64_t minInvocationsExclusiveScanNonUniformAMD(uint64_t);"
+ "u64vec2 minInvocationsExclusiveScanNonUniformAMD(u64vec2);"
+ "u64vec3 minInvocationsExclusiveScanNonUniformAMD(u64vec3);"
+ "u64vec4 minInvocationsExclusiveScanNonUniformAMD(u64vec4);"
+
+ "float16_t minInvocationsExclusiveScanNonUniformAMD(float16_t);"
+ "f16vec2 minInvocationsExclusiveScanNonUniformAMD(f16vec2);"
+ "f16vec3 minInvocationsExclusiveScanNonUniformAMD(f16vec3);"
+ "f16vec4 minInvocationsExclusiveScanNonUniformAMD(f16vec4);"
+
+ "int16_t minInvocationsExclusiveScanNonUniformAMD(int16_t);"
+ "i16vec2 minInvocationsExclusiveScanNonUniformAMD(i16vec2);"
+ "i16vec3 minInvocationsExclusiveScanNonUniformAMD(i16vec3);"
+ "i16vec4 minInvocationsExclusiveScanNonUniformAMD(i16vec4);"
+
+ "uint16_t minInvocationsExclusiveScanNonUniformAMD(uint16_t);"
+ "u16vec2 minInvocationsExclusiveScanNonUniformAMD(u16vec2);"
+ "u16vec3 minInvocationsExclusiveScanNonUniformAMD(u16vec3);"
+ "u16vec4 minInvocationsExclusiveScanNonUniformAMD(u16vec4);"
+
+ "float maxInvocationsNonUniformAMD(float);"
+ "vec2 maxInvocationsNonUniformAMD(vec2);"
+ "vec3 maxInvocationsNonUniformAMD(vec3);"
+ "vec4 maxInvocationsNonUniformAMD(vec4);"
+
+ "int maxInvocationsNonUniformAMD(int);"
+ "ivec2 maxInvocationsNonUniformAMD(ivec2);"
+ "ivec3 maxInvocationsNonUniformAMD(ivec3);"
+ "ivec4 maxInvocationsNonUniformAMD(ivec4);"
+
+ "uint maxInvocationsNonUniformAMD(uint);"
+ "uvec2 maxInvocationsNonUniformAMD(uvec2);"
+ "uvec3 maxInvocationsNonUniformAMD(uvec3);"
+ "uvec4 maxInvocationsNonUniformAMD(uvec4);"
+
+ "double maxInvocationsNonUniformAMD(double);"
+ "dvec2 maxInvocationsNonUniformAMD(dvec2);"
+ "dvec3 maxInvocationsNonUniformAMD(dvec3);"
+ "dvec4 maxInvocationsNonUniformAMD(dvec4);"
+
+ "int64_t maxInvocationsNonUniformAMD(int64_t);"
+ "i64vec2 maxInvocationsNonUniformAMD(i64vec2);"
+ "i64vec3 maxInvocationsNonUniformAMD(i64vec3);"
+ "i64vec4 maxInvocationsNonUniformAMD(i64vec4);"
+
+ "uint64_t maxInvocationsNonUniformAMD(uint64_t);"
+ "u64vec2 maxInvocationsNonUniformAMD(u64vec2);"
+ "u64vec3 maxInvocationsNonUniformAMD(u64vec3);"
+ "u64vec4 maxInvocationsNonUniformAMD(u64vec4);"
+
+ "float16_t maxInvocationsNonUniformAMD(float16_t);"
+ "f16vec2 maxInvocationsNonUniformAMD(f16vec2);"
+ "f16vec3 maxInvocationsNonUniformAMD(f16vec3);"
+ "f16vec4 maxInvocationsNonUniformAMD(f16vec4);"
+
+ "int16_t maxInvocationsNonUniformAMD(int16_t);"
+ "i16vec2 maxInvocationsNonUniformAMD(i16vec2);"
+ "i16vec3 maxInvocationsNonUniformAMD(i16vec3);"
+ "i16vec4 maxInvocationsNonUniformAMD(i16vec4);"
+
+ "uint16_t maxInvocationsNonUniformAMD(uint16_t);"
+ "u16vec2 maxInvocationsNonUniformAMD(u16vec2);"
+ "u16vec3 maxInvocationsNonUniformAMD(u16vec3);"
+ "u16vec4 maxInvocationsNonUniformAMD(u16vec4);"
+
+ "float maxInvocationsInclusiveScanNonUniformAMD(float);"
+ "vec2 maxInvocationsInclusiveScanNonUniformAMD(vec2);"
+ "vec3 maxInvocationsInclusiveScanNonUniformAMD(vec3);"
+ "vec4 maxInvocationsInclusiveScanNonUniformAMD(vec4);"
+
+ "int maxInvocationsInclusiveScanNonUniformAMD(int);"
+ "ivec2 maxInvocationsInclusiveScanNonUniformAMD(ivec2);"
+ "ivec3 maxInvocationsInclusiveScanNonUniformAMD(ivec3);"
+ "ivec4 maxInvocationsInclusiveScanNonUniformAMD(ivec4);"
+
+ "uint maxInvocationsInclusiveScanNonUniformAMD(uint);"
+ "uvec2 maxInvocationsInclusiveScanNonUniformAMD(uvec2);"
+ "uvec3 maxInvocationsInclusiveScanNonUniformAMD(uvec3);"
+ "uvec4 maxInvocationsInclusiveScanNonUniformAMD(uvec4);"
+
+ "double maxInvocationsInclusiveScanNonUniformAMD(double);"
+ "dvec2 maxInvocationsInclusiveScanNonUniformAMD(dvec2);"
+ "dvec3 maxInvocationsInclusiveScanNonUniformAMD(dvec3);"
+ "dvec4 maxInvocationsInclusiveScanNonUniformAMD(dvec4);"
+
+ "int64_t maxInvocationsInclusiveScanNonUniformAMD(int64_t);"
+ "i64vec2 maxInvocationsInclusiveScanNonUniformAMD(i64vec2);"
+ "i64vec3 maxInvocationsInclusiveScanNonUniformAMD(i64vec3);"
+ "i64vec4 maxInvocationsInclusiveScanNonUniformAMD(i64vec4);"
+
+ "uint64_t maxInvocationsInclusiveScanNonUniformAMD(uint64_t);"
+ "u64vec2 maxInvocationsInclusiveScanNonUniformAMD(u64vec2);"
+ "u64vec3 maxInvocationsInclusiveScanNonUniformAMD(u64vec3);"
+ "u64vec4 maxInvocationsInclusiveScanNonUniformAMD(u64vec4);"
+
+ "float16_t maxInvocationsInclusiveScanNonUniformAMD(float16_t);"
+ "f16vec2 maxInvocationsInclusiveScanNonUniformAMD(f16vec2);"
+ "f16vec3 maxInvocationsInclusiveScanNonUniformAMD(f16vec3);"
+ "f16vec4 maxInvocationsInclusiveScanNonUniformAMD(f16vec4);"
+
+ "int16_t maxInvocationsInclusiveScanNonUniformAMD(int16_t);"
+ "i16vec2 maxInvocationsInclusiveScanNonUniformAMD(i16vec2);"
+ "i16vec3 maxInvocationsInclusiveScanNonUniformAMD(i16vec3);"
+ "i16vec4 maxInvocationsInclusiveScanNonUniformAMD(i16vec4);"
+
+ "uint16_t maxInvocationsInclusiveScanNonUniformAMD(uint16_t);"
+ "u16vec2 maxInvocationsInclusiveScanNonUniformAMD(u16vec2);"
+ "u16vec3 maxInvocationsInclusiveScanNonUniformAMD(u16vec3);"
+ "u16vec4 maxInvocationsInclusiveScanNonUniformAMD(u16vec4);"
+
+ "float maxInvocationsExclusiveScanNonUniformAMD(float);"
+ "vec2 maxInvocationsExclusiveScanNonUniformAMD(vec2);"
+ "vec3 maxInvocationsExclusiveScanNonUniformAMD(vec3);"
+ "vec4 maxInvocationsExclusiveScanNonUniformAMD(vec4);"
+
+ "int maxInvocationsExclusiveScanNonUniformAMD(int);"
+ "ivec2 maxInvocationsExclusiveScanNonUniformAMD(ivec2);"
+ "ivec3 maxInvocationsExclusiveScanNonUniformAMD(ivec3);"
+ "ivec4 maxInvocationsExclusiveScanNonUniformAMD(ivec4);"
+
+ "uint maxInvocationsExclusiveScanNonUniformAMD(uint);"
+ "uvec2 maxInvocationsExclusiveScanNonUniformAMD(uvec2);"
+ "uvec3 maxInvocationsExclusiveScanNonUniformAMD(uvec3);"
+ "uvec4 maxInvocationsExclusiveScanNonUniformAMD(uvec4);"
+
+ "double maxInvocationsExclusiveScanNonUniformAMD(double);"
+ "dvec2 maxInvocationsExclusiveScanNonUniformAMD(dvec2);"
+ "dvec3 maxInvocationsExclusiveScanNonUniformAMD(dvec3);"
+ "dvec4 maxInvocationsExclusiveScanNonUniformAMD(dvec4);"
+
+ "int64_t maxInvocationsExclusiveScanNonUniformAMD(int64_t);"
+ "i64vec2 maxInvocationsExclusiveScanNonUniformAMD(i64vec2);"
+ "i64vec3 maxInvocationsExclusiveScanNonUniformAMD(i64vec3);"
+ "i64vec4 maxInvocationsExclusiveScanNonUniformAMD(i64vec4);"
+
+ "uint64_t maxInvocationsExclusiveScanNonUniformAMD(uint64_t);"
+ "u64vec2 maxInvocationsExclusiveScanNonUniformAMD(u64vec2);"
+ "u64vec3 maxInvocationsExclusiveScanNonUniformAMD(u64vec3);"
+ "u64vec4 maxInvocationsExclusiveScanNonUniformAMD(u64vec4);"
+
+ "float16_t maxInvocationsExclusiveScanNonUniformAMD(float16_t);"
+ "f16vec2 maxInvocationsExclusiveScanNonUniformAMD(f16vec2);"
+ "f16vec3 maxInvocationsExclusiveScanNonUniformAMD(f16vec3);"
+ "f16vec4 maxInvocationsExclusiveScanNonUniformAMD(f16vec4);"
+
+ "int16_t maxInvocationsExclusiveScanNonUniformAMD(int16_t);"
+ "i16vec2 maxInvocationsExclusiveScanNonUniformAMD(i16vec2);"
+ "i16vec3 maxInvocationsExclusiveScanNonUniformAMD(i16vec3);"
+ "i16vec4 maxInvocationsExclusiveScanNonUniformAMD(i16vec4);"
+
+ "uint16_t maxInvocationsExclusiveScanNonUniformAMD(uint16_t);"
+ "u16vec2 maxInvocationsExclusiveScanNonUniformAMD(u16vec2);"
+ "u16vec3 maxInvocationsExclusiveScanNonUniformAMD(u16vec3);"
+ "u16vec4 maxInvocationsExclusiveScanNonUniformAMD(u16vec4);"
+
+ "float addInvocationsNonUniformAMD(float);"
+ "vec2 addInvocationsNonUniformAMD(vec2);"
+ "vec3 addInvocationsNonUniformAMD(vec3);"
+ "vec4 addInvocationsNonUniformAMD(vec4);"
+
+ "int addInvocationsNonUniformAMD(int);"
+ "ivec2 addInvocationsNonUniformAMD(ivec2);"
+ "ivec3 addInvocationsNonUniformAMD(ivec3);"
+ "ivec4 addInvocationsNonUniformAMD(ivec4);"
+
+ "uint addInvocationsNonUniformAMD(uint);"
+ "uvec2 addInvocationsNonUniformAMD(uvec2);"
+ "uvec3 addInvocationsNonUniformAMD(uvec3);"
+ "uvec4 addInvocationsNonUniformAMD(uvec4);"
+
+ "double addInvocationsNonUniformAMD(double);"
+ "dvec2 addInvocationsNonUniformAMD(dvec2);"
+ "dvec3 addInvocationsNonUniformAMD(dvec3);"
+ "dvec4 addInvocationsNonUniformAMD(dvec4);"
+
+ "int64_t addInvocationsNonUniformAMD(int64_t);"
+ "i64vec2 addInvocationsNonUniformAMD(i64vec2);"
+ "i64vec3 addInvocationsNonUniformAMD(i64vec3);"
+ "i64vec4 addInvocationsNonUniformAMD(i64vec4);"
+
+ "uint64_t addInvocationsNonUniformAMD(uint64_t);"
+ "u64vec2 addInvocationsNonUniformAMD(u64vec2);"
+ "u64vec3 addInvocationsNonUniformAMD(u64vec3);"
+ "u64vec4 addInvocationsNonUniformAMD(u64vec4);"
+
+ "float16_t addInvocationsNonUniformAMD(float16_t);"
+ "f16vec2 addInvocationsNonUniformAMD(f16vec2);"
+ "f16vec3 addInvocationsNonUniformAMD(f16vec3);"
+ "f16vec4 addInvocationsNonUniformAMD(f16vec4);"
+
+ "int16_t addInvocationsNonUniformAMD(int16_t);"
+ "i16vec2 addInvocationsNonUniformAMD(i16vec2);"
+ "i16vec3 addInvocationsNonUniformAMD(i16vec3);"
+ "i16vec4 addInvocationsNonUniformAMD(i16vec4);"
+
+ "uint16_t addInvocationsNonUniformAMD(uint16_t);"
+ "u16vec2 addInvocationsNonUniformAMD(u16vec2);"
+ "u16vec3 addInvocationsNonUniformAMD(u16vec3);"
+ "u16vec4 addInvocationsNonUniformAMD(u16vec4);"
+
+ "float addInvocationsInclusiveScanNonUniformAMD(float);"
+ "vec2 addInvocationsInclusiveScanNonUniformAMD(vec2);"
+ "vec3 addInvocationsInclusiveScanNonUniformAMD(vec3);"
+ "vec4 addInvocationsInclusiveScanNonUniformAMD(vec4);"
+
+ "int addInvocationsInclusiveScanNonUniformAMD(int);"
+ "ivec2 addInvocationsInclusiveScanNonUniformAMD(ivec2);"
+ "ivec3 addInvocationsInclusiveScanNonUniformAMD(ivec3);"
+ "ivec4 addInvocationsInclusiveScanNonUniformAMD(ivec4);"
+
+ "uint addInvocationsInclusiveScanNonUniformAMD(uint);"
+ "uvec2 addInvocationsInclusiveScanNonUniformAMD(uvec2);"
+ "uvec3 addInvocationsInclusiveScanNonUniformAMD(uvec3);"
+ "uvec4 addInvocationsInclusiveScanNonUniformAMD(uvec4);"
+
+ "double addInvocationsInclusiveScanNonUniformAMD(double);"
+ "dvec2 addInvocationsInclusiveScanNonUniformAMD(dvec2);"
+ "dvec3 addInvocationsInclusiveScanNonUniformAMD(dvec3);"
+ "dvec4 addInvocationsInclusiveScanNonUniformAMD(dvec4);"
+
+ "int64_t addInvocationsInclusiveScanNonUniformAMD(int64_t);"
+ "i64vec2 addInvocationsInclusiveScanNonUniformAMD(i64vec2);"
+ "i64vec3 addInvocationsInclusiveScanNonUniformAMD(i64vec3);"
+ "i64vec4 addInvocationsInclusiveScanNonUniformAMD(i64vec4);"
+
+ "uint64_t addInvocationsInclusiveScanNonUniformAMD(uint64_t);"
+ "u64vec2 addInvocationsInclusiveScanNonUniformAMD(u64vec2);"
+ "u64vec3 addInvocationsInclusiveScanNonUniformAMD(u64vec3);"
+ "u64vec4 addInvocationsInclusiveScanNonUniformAMD(u64vec4);"
+
+ "float16_t addInvocationsInclusiveScanNonUniformAMD(float16_t);"
+ "f16vec2 addInvocationsInclusiveScanNonUniformAMD(f16vec2);"
+ "f16vec3 addInvocationsInclusiveScanNonUniformAMD(f16vec3);"
+ "f16vec4 addInvocationsInclusiveScanNonUniformAMD(f16vec4);"
+
+ "int16_t addInvocationsInclusiveScanNonUniformAMD(int16_t);"
+ "i16vec2 addInvocationsInclusiveScanNonUniformAMD(i16vec2);"
+ "i16vec3 addInvocationsInclusiveScanNonUniformAMD(i16vec3);"
+ "i16vec4 addInvocationsInclusiveScanNonUniformAMD(i16vec4);"
+
+ "uint16_t addInvocationsInclusiveScanNonUniformAMD(uint16_t);"
+ "u16vec2 addInvocationsInclusiveScanNonUniformAMD(u16vec2);"
+ "u16vec3 addInvocationsInclusiveScanNonUniformAMD(u16vec3);"
+ "u16vec4 addInvocationsInclusiveScanNonUniformAMD(u16vec4);"
+
+ "float addInvocationsExclusiveScanNonUniformAMD(float);"
+ "vec2 addInvocationsExclusiveScanNonUniformAMD(vec2);"
+ "vec3 addInvocationsExclusiveScanNonUniformAMD(vec3);"
+ "vec4 addInvocationsExclusiveScanNonUniformAMD(vec4);"
+
+ "int addInvocationsExclusiveScanNonUniformAMD(int);"
+ "ivec2 addInvocationsExclusiveScanNonUniformAMD(ivec2);"
+ "ivec3 addInvocationsExclusiveScanNonUniformAMD(ivec3);"
+ "ivec4 addInvocationsExclusiveScanNonUniformAMD(ivec4);"
+
+ "uint addInvocationsExclusiveScanNonUniformAMD(uint);"
+ "uvec2 addInvocationsExclusiveScanNonUniformAMD(uvec2);"
+ "uvec3 addInvocationsExclusiveScanNonUniformAMD(uvec3);"
+ "uvec4 addInvocationsExclusiveScanNonUniformAMD(uvec4);"
+
+ "double addInvocationsExclusiveScanNonUniformAMD(double);"
+ "dvec2 addInvocationsExclusiveScanNonUniformAMD(dvec2);"
+ "dvec3 addInvocationsExclusiveScanNonUniformAMD(dvec3);"
+ "dvec4 addInvocationsExclusiveScanNonUniformAMD(dvec4);"
+
+ "int64_t addInvocationsExclusiveScanNonUniformAMD(int64_t);"
+ "i64vec2 addInvocationsExclusiveScanNonUniformAMD(i64vec2);"
+ "i64vec3 addInvocationsExclusiveScanNonUniformAMD(i64vec3);"
+ "i64vec4 addInvocationsExclusiveScanNonUniformAMD(i64vec4);"
+
+ "uint64_t addInvocationsExclusiveScanNonUniformAMD(uint64_t);"
+ "u64vec2 addInvocationsExclusiveScanNonUniformAMD(u64vec2);"
+ "u64vec3 addInvocationsExclusiveScanNonUniformAMD(u64vec3);"
+ "u64vec4 addInvocationsExclusiveScanNonUniformAMD(u64vec4);"
+
+ "float16_t addInvocationsExclusiveScanNonUniformAMD(float16_t);"
+ "f16vec2 addInvocationsExclusiveScanNonUniformAMD(f16vec2);"
+ "f16vec3 addInvocationsExclusiveScanNonUniformAMD(f16vec3);"
+ "f16vec4 addInvocationsExclusiveScanNonUniformAMD(f16vec4);"
+
+ "int16_t addInvocationsExclusiveScanNonUniformAMD(int16_t);"
+ "i16vec2 addInvocationsExclusiveScanNonUniformAMD(i16vec2);"
+ "i16vec3 addInvocationsExclusiveScanNonUniformAMD(i16vec3);"
+ "i16vec4 addInvocationsExclusiveScanNonUniformAMD(i16vec4);"
+
+ "uint16_t addInvocationsExclusiveScanNonUniformAMD(uint16_t);"
+ "u16vec2 addInvocationsExclusiveScanNonUniformAMD(u16vec2);"
+ "u16vec3 addInvocationsExclusiveScanNonUniformAMD(u16vec3);"
+ "u16vec4 addInvocationsExclusiveScanNonUniformAMD(u16vec4);"
+
+ "float swizzleInvocationsAMD(float, uvec4);"
+ "vec2 swizzleInvocationsAMD(vec2, uvec4);"
+ "vec3 swizzleInvocationsAMD(vec3, uvec4);"
+ "vec4 swizzleInvocationsAMD(vec4, uvec4);"
+
+ "int swizzleInvocationsAMD(int, uvec4);"
+ "ivec2 swizzleInvocationsAMD(ivec2, uvec4);"
+ "ivec3 swizzleInvocationsAMD(ivec3, uvec4);"
+ "ivec4 swizzleInvocationsAMD(ivec4, uvec4);"
+
+ "uint swizzleInvocationsAMD(uint, uvec4);"
+ "uvec2 swizzleInvocationsAMD(uvec2, uvec4);"
+ "uvec3 swizzleInvocationsAMD(uvec3, uvec4);"
+ "uvec4 swizzleInvocationsAMD(uvec4, uvec4);"
+
+ "float swizzleInvocationsMaskedAMD(float, uvec3);"
+ "vec2 swizzleInvocationsMaskedAMD(vec2, uvec3);"
+ "vec3 swizzleInvocationsMaskedAMD(vec3, uvec3);"
+ "vec4 swizzleInvocationsMaskedAMD(vec4, uvec3);"
+
+ "int swizzleInvocationsMaskedAMD(int, uvec3);"
+ "ivec2 swizzleInvocationsMaskedAMD(ivec2, uvec3);"
+ "ivec3 swizzleInvocationsMaskedAMD(ivec3, uvec3);"
+ "ivec4 swizzleInvocationsMaskedAMD(ivec4, uvec3);"
+
+ "uint swizzleInvocationsMaskedAMD(uint, uvec3);"
+ "uvec2 swizzleInvocationsMaskedAMD(uvec2, uvec3);"
+ "uvec3 swizzleInvocationsMaskedAMD(uvec3, uvec3);"
+ "uvec4 swizzleInvocationsMaskedAMD(uvec4, uvec3);"
+
+ "float writeInvocationAMD(float, float, uint);"
+ "vec2 writeInvocationAMD(vec2, vec2, uint);"
+ "vec3 writeInvocationAMD(vec3, vec3, uint);"
+ "vec4 writeInvocationAMD(vec4, vec4, uint);"
+
+ "int writeInvocationAMD(int, int, uint);"
+ "ivec2 writeInvocationAMD(ivec2, ivec2, uint);"
+ "ivec3 writeInvocationAMD(ivec3, ivec3, uint);"
+ "ivec4 writeInvocationAMD(ivec4, ivec4, uint);"
+
+ "uint writeInvocationAMD(uint, uint, uint);"
+ "uvec2 writeInvocationAMD(uvec2, uvec2, uint);"
+ "uvec3 writeInvocationAMD(uvec3, uvec3, uint);"
+ "uvec4 writeInvocationAMD(uvec4, uvec4, uint);"
+
+ "uint mbcntAMD(uint64_t);"
+
+ "\n");
+ }
+
+ // GL_AMD_gcn_shader
+ if (profile != EEsProfile && version >= 440) {
+ commonBuiltins.append(
+ "float cubeFaceIndexAMD(vec3);"
+ "vec2 cubeFaceCoordAMD(vec3);"
+ "uint64_t timeAMD();"
+
+ "in int gl_SIMDGroupSizeAMD;"
+ "\n");
+ }
+
+ // GL_AMD_shader_fragment_mask
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append(
+ "uint fragmentMaskFetchAMD(sampler2DMS, ivec2);"
+ "uint fragmentMaskFetchAMD(isampler2DMS, ivec2);"
+ "uint fragmentMaskFetchAMD(usampler2DMS, ivec2);"
+
+ "uint fragmentMaskFetchAMD(sampler2DMSArray, ivec3);"
+ "uint fragmentMaskFetchAMD(isampler2DMSArray, ivec3);"
+ "uint fragmentMaskFetchAMD(usampler2DMSArray, ivec3);"
+
+ "vec4 fragmentFetchAMD(sampler2DMS, ivec2, uint);"
+ "ivec4 fragmentFetchAMD(isampler2DMS, ivec2, uint);"
+ "uvec4 fragmentFetchAMD(usampler2DMS, ivec2, uint);"
+
+ "vec4 fragmentFetchAMD(sampler2DMSArray, ivec3, uint);"
+ "ivec4 fragmentFetchAMD(isampler2DMSArray, ivec3, uint);"
+ "uvec4 fragmentFetchAMD(usampler2DMSArray, ivec3, uint);"
+
+ "\n");
+ }
+
+ if ((profile != EEsProfile && version >= 130) ||
+ (profile == EEsProfile && version >= 300)) {
+ commonBuiltins.append(
+ "uint countLeadingZeros(uint);"
+ "uvec2 countLeadingZeros(uvec2);"
+ "uvec3 countLeadingZeros(uvec3);"
+ "uvec4 countLeadingZeros(uvec4);"
+
+ "uint countTrailingZeros(uint);"
+ "uvec2 countTrailingZeros(uvec2);"
+ "uvec3 countTrailingZeros(uvec3);"
+ "uvec4 countTrailingZeros(uvec4);"
+
+ "uint absoluteDifference(int, int);"
+ "uvec2 absoluteDifference(ivec2, ivec2);"
+ "uvec3 absoluteDifference(ivec3, ivec3);"
+ "uvec4 absoluteDifference(ivec4, ivec4);"
+
+ "uint16_t absoluteDifference(int16_t, int16_t);"
+ "u16vec2 absoluteDifference(i16vec2, i16vec2);"
+ "u16vec3 absoluteDifference(i16vec3, i16vec3);"
+ "u16vec4 absoluteDifference(i16vec4, i16vec4);"
+
+ "uint64_t absoluteDifference(int64_t, int64_t);"
+ "u64vec2 absoluteDifference(i64vec2, i64vec2);"
+ "u64vec3 absoluteDifference(i64vec3, i64vec3);"
+ "u64vec4 absoluteDifference(i64vec4, i64vec4);"
+
+ "uint absoluteDifference(uint, uint);"
+ "uvec2 absoluteDifference(uvec2, uvec2);"
+ "uvec3 absoluteDifference(uvec3, uvec3);"
+ "uvec4 absoluteDifference(uvec4, uvec4);"
+
+ "uint16_t absoluteDifference(uint16_t, uint16_t);"
+ "u16vec2 absoluteDifference(u16vec2, u16vec2);"
+ "u16vec3 absoluteDifference(u16vec3, u16vec3);"
+ "u16vec4 absoluteDifference(u16vec4, u16vec4);"
+
+ "uint64_t absoluteDifference(uint64_t, uint64_t);"
+ "u64vec2 absoluteDifference(u64vec2, u64vec2);"
+ "u64vec3 absoluteDifference(u64vec3, u64vec3);"
+ "u64vec4 absoluteDifference(u64vec4, u64vec4);"
+
+ "int addSaturate(int, int);"
+ "ivec2 addSaturate(ivec2, ivec2);"
+ "ivec3 addSaturate(ivec3, ivec3);"
+ "ivec4 addSaturate(ivec4, ivec4);"
+
+ "int16_t addSaturate(int16_t, int16_t);"
+ "i16vec2 addSaturate(i16vec2, i16vec2);"
+ "i16vec3 addSaturate(i16vec3, i16vec3);"
+ "i16vec4 addSaturate(i16vec4, i16vec4);"
+
+ "int64_t addSaturate(int64_t, int64_t);"
+ "i64vec2 addSaturate(i64vec2, i64vec2);"
+ "i64vec3 addSaturate(i64vec3, i64vec3);"
+ "i64vec4 addSaturate(i64vec4, i64vec4);"
+
+ "uint addSaturate(uint, uint);"
+ "uvec2 addSaturate(uvec2, uvec2);"
+ "uvec3 addSaturate(uvec3, uvec3);"
+ "uvec4 addSaturate(uvec4, uvec4);"
+
+ "uint16_t addSaturate(uint16_t, uint16_t);"
+ "u16vec2 addSaturate(u16vec2, u16vec2);"
+ "u16vec3 addSaturate(u16vec3, u16vec3);"
+ "u16vec4 addSaturate(u16vec4, u16vec4);"
+
+ "uint64_t addSaturate(uint64_t, uint64_t);"
+ "u64vec2 addSaturate(u64vec2, u64vec2);"
+ "u64vec3 addSaturate(u64vec3, u64vec3);"
+ "u64vec4 addSaturate(u64vec4, u64vec4);"
+
+ "int subtractSaturate(int, int);"
+ "ivec2 subtractSaturate(ivec2, ivec2);"
+ "ivec3 subtractSaturate(ivec3, ivec3);"
+ "ivec4 subtractSaturate(ivec4, ivec4);"
+
+ "int16_t subtractSaturate(int16_t, int16_t);"
+ "i16vec2 subtractSaturate(i16vec2, i16vec2);"
+ "i16vec3 subtractSaturate(i16vec3, i16vec3);"
+ "i16vec4 subtractSaturate(i16vec4, i16vec4);"
+
+ "int64_t subtractSaturate(int64_t, int64_t);"
+ "i64vec2 subtractSaturate(i64vec2, i64vec2);"
+ "i64vec3 subtractSaturate(i64vec3, i64vec3);"
+ "i64vec4 subtractSaturate(i64vec4, i64vec4);"
+
+ "uint subtractSaturate(uint, uint);"
+ "uvec2 subtractSaturate(uvec2, uvec2);"
+ "uvec3 subtractSaturate(uvec3, uvec3);"
+ "uvec4 subtractSaturate(uvec4, uvec4);"
+
+ "uint16_t subtractSaturate(uint16_t, uint16_t);"
+ "u16vec2 subtractSaturate(u16vec2, u16vec2);"
+ "u16vec3 subtractSaturate(u16vec3, u16vec3);"
+ "u16vec4 subtractSaturate(u16vec4, u16vec4);"
+
+ "uint64_t subtractSaturate(uint64_t, uint64_t);"
+ "u64vec2 subtractSaturate(u64vec2, u64vec2);"
+ "u64vec3 subtractSaturate(u64vec3, u64vec3);"
+ "u64vec4 subtractSaturate(u64vec4, u64vec4);"
+
+ "int average(int, int);"
+ "ivec2 average(ivec2, ivec2);"
+ "ivec3 average(ivec3, ivec3);"
+ "ivec4 average(ivec4, ivec4);"
+
+ "int16_t average(int16_t, int16_t);"
+ "i16vec2 average(i16vec2, i16vec2);"
+ "i16vec3 average(i16vec3, i16vec3);"
+ "i16vec4 average(i16vec4, i16vec4);"
+
+ "int64_t average(int64_t, int64_t);"
+ "i64vec2 average(i64vec2, i64vec2);"
+ "i64vec3 average(i64vec3, i64vec3);"
+ "i64vec4 average(i64vec4, i64vec4);"
+
+ "uint average(uint, uint);"
+ "uvec2 average(uvec2, uvec2);"
+ "uvec3 average(uvec3, uvec3);"
+ "uvec4 average(uvec4, uvec4);"
+
+ "uint16_t average(uint16_t, uint16_t);"
+ "u16vec2 average(u16vec2, u16vec2);"
+ "u16vec3 average(u16vec3, u16vec3);"
+ "u16vec4 average(u16vec4, u16vec4);"
+
+ "uint64_t average(uint64_t, uint64_t);"
+ "u64vec2 average(u64vec2, u64vec2);"
+ "u64vec3 average(u64vec3, u64vec3);"
+ "u64vec4 average(u64vec4, u64vec4);"
+
+ "int averageRounded(int, int);"
+ "ivec2 averageRounded(ivec2, ivec2);"
+ "ivec3 averageRounded(ivec3, ivec3);"
+ "ivec4 averageRounded(ivec4, ivec4);"
+
+ "int16_t averageRounded(int16_t, int16_t);"
+ "i16vec2 averageRounded(i16vec2, i16vec2);"
+ "i16vec3 averageRounded(i16vec3, i16vec3);"
+ "i16vec4 averageRounded(i16vec4, i16vec4);"
+
+ "int64_t averageRounded(int64_t, int64_t);"
+ "i64vec2 averageRounded(i64vec2, i64vec2);"
+ "i64vec3 averageRounded(i64vec3, i64vec3);"
+ "i64vec4 averageRounded(i64vec4, i64vec4);"
+
+ "uint averageRounded(uint, uint);"
+ "uvec2 averageRounded(uvec2, uvec2);"
+ "uvec3 averageRounded(uvec3, uvec3);"
+ "uvec4 averageRounded(uvec4, uvec4);"
+
+ "uint16_t averageRounded(uint16_t, uint16_t);"
+ "u16vec2 averageRounded(u16vec2, u16vec2);"
+ "u16vec3 averageRounded(u16vec3, u16vec3);"
+ "u16vec4 averageRounded(u16vec4, u16vec4);"
+
+ "uint64_t averageRounded(uint64_t, uint64_t);"
+ "u64vec2 averageRounded(u64vec2, u64vec2);"
+ "u64vec3 averageRounded(u64vec3, u64vec3);"
+ "u64vec4 averageRounded(u64vec4, u64vec4);"
+
+ "int multiply32x16(int, int);"
+ "ivec2 multiply32x16(ivec2, ivec2);"
+ "ivec3 multiply32x16(ivec3, ivec3);"
+ "ivec4 multiply32x16(ivec4, ivec4);"
+
+ "uint multiply32x16(uint, uint);"
+ "uvec2 multiply32x16(uvec2, uvec2);"
+ "uvec3 multiply32x16(uvec3, uvec3);"
+ "uvec4 multiply32x16(uvec4, uvec4);"
+ "\n");
+ }
+
+ if ((profile != EEsProfile && version >= 450) ||
+ (profile == EEsProfile && version >= 320)) {
+ commonBuiltins.append(
+ "struct gl_TextureFootprint2DNV {"
+ "uvec2 anchor;"
+ "uvec2 offset;"
+ "uvec2 mask;"
+ "uint lod;"
+ "uint granularity;"
+ "};"
+
+ "struct gl_TextureFootprint3DNV {"
+ "uvec3 anchor;"
+ "uvec3 offset;"
+ "uvec2 mask;"
+ "uint lod;"
+ "uint granularity;"
+ "};"
+ "bool textureFootprintNV(sampler2D, vec2, int, bool, out gl_TextureFootprint2DNV);"
+ "bool textureFootprintNV(sampler3D, vec3, int, bool, out gl_TextureFootprint3DNV);"
+ "bool textureFootprintNV(sampler2D, vec2, int, bool, out gl_TextureFootprint2DNV, float);"
+ "bool textureFootprintNV(sampler3D, vec3, int, bool, out gl_TextureFootprint3DNV, float);"
+ "bool textureFootprintClampNV(sampler2D, vec2, float, int, bool, out gl_TextureFootprint2DNV);"
+ "bool textureFootprintClampNV(sampler3D, vec3, float, int, bool, out gl_TextureFootprint3DNV);"
+ "bool textureFootprintClampNV(sampler2D, vec2, float, int, bool, out gl_TextureFootprint2DNV, float);"
+ "bool textureFootprintClampNV(sampler3D, vec3, float, int, bool, out gl_TextureFootprint3DNV, float);"
+ "bool textureFootprintLodNV(sampler2D, vec2, float, int, bool, out gl_TextureFootprint2DNV);"
+ "bool textureFootprintLodNV(sampler3D, vec3, float, int, bool, out gl_TextureFootprint3DNV);"
+ "bool textureFootprintGradNV(sampler2D, vec2, vec2, vec2, int, bool, out gl_TextureFootprint2DNV);"
+ "bool textureFootprintGradClampNV(sampler2D, vec2, vec2, vec2, float, int, bool, out gl_TextureFootprint2DNV);"
+ "\n");
+ }
+
+ // GL_AMD_gpu_shader_half_float/Explicit types
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append(
+ "float16_t radians(float16_t);"
+ "f16vec2 radians(f16vec2);"
+ "f16vec3 radians(f16vec3);"
+ "f16vec4 radians(f16vec4);"
+
+ "float16_t degrees(float16_t);"
+ "f16vec2 degrees(f16vec2);"
+ "f16vec3 degrees(f16vec3);"
+ "f16vec4 degrees(f16vec4);"
+
+ "float16_t sin(float16_t);"
+ "f16vec2 sin(f16vec2);"
+ "f16vec3 sin(f16vec3);"
+ "f16vec4 sin(f16vec4);"
+
+ "float16_t cos(float16_t);"
+ "f16vec2 cos(f16vec2);"
+ "f16vec3 cos(f16vec3);"
+ "f16vec4 cos(f16vec4);"
+
+ "float16_t tan(float16_t);"
+ "f16vec2 tan(f16vec2);"
+ "f16vec3 tan(f16vec3);"
+ "f16vec4 tan(f16vec4);"
+
+ "float16_t asin(float16_t);"
+ "f16vec2 asin(f16vec2);"
+ "f16vec3 asin(f16vec3);"
+ "f16vec4 asin(f16vec4);"
+
+ "float16_t acos(float16_t);"
+ "f16vec2 acos(f16vec2);"
+ "f16vec3 acos(f16vec3);"
+ "f16vec4 acos(f16vec4);"
+
+ "float16_t atan(float16_t, float16_t);"
+ "f16vec2 atan(f16vec2, f16vec2);"
+ "f16vec3 atan(f16vec3, f16vec3);"
+ "f16vec4 atan(f16vec4, f16vec4);"
+
+ "float16_t atan(float16_t);"
+ "f16vec2 atan(f16vec2);"
+ "f16vec3 atan(f16vec3);"
+ "f16vec4 atan(f16vec4);"
+
+ "float16_t sinh(float16_t);"
+ "f16vec2 sinh(f16vec2);"
+ "f16vec3 sinh(f16vec3);"
+ "f16vec4 sinh(f16vec4);"
+
+ "float16_t cosh(float16_t);"
+ "f16vec2 cosh(f16vec2);"
+ "f16vec3 cosh(f16vec3);"
+ "f16vec4 cosh(f16vec4);"
+
+ "float16_t tanh(float16_t);"
+ "f16vec2 tanh(f16vec2);"
+ "f16vec3 tanh(f16vec3);"
+ "f16vec4 tanh(f16vec4);"
+
+ "float16_t asinh(float16_t);"
+ "f16vec2 asinh(f16vec2);"
+ "f16vec3 asinh(f16vec3);"
+ "f16vec4 asinh(f16vec4);"
+
+ "float16_t acosh(float16_t);"
+ "f16vec2 acosh(f16vec2);"
+ "f16vec3 acosh(f16vec3);"
+ "f16vec4 acosh(f16vec4);"
+
+ "float16_t atanh(float16_t);"
+ "f16vec2 atanh(f16vec2);"
+ "f16vec3 atanh(f16vec3);"
+ "f16vec4 atanh(f16vec4);"
+
+ "float16_t pow(float16_t, float16_t);"
+ "f16vec2 pow(f16vec2, f16vec2);"
+ "f16vec3 pow(f16vec3, f16vec3);"
+ "f16vec4 pow(f16vec4, f16vec4);"
+
+ "float16_t exp(float16_t);"
+ "f16vec2 exp(f16vec2);"
+ "f16vec3 exp(f16vec3);"
+ "f16vec4 exp(f16vec4);"
+
+ "float16_t log(float16_t);"
+ "f16vec2 log(f16vec2);"
+ "f16vec3 log(f16vec3);"
+ "f16vec4 log(f16vec4);"
+
+ "float16_t exp2(float16_t);"
+ "f16vec2 exp2(f16vec2);"
+ "f16vec3 exp2(f16vec3);"
+ "f16vec4 exp2(f16vec4);"
+
+ "float16_t log2(float16_t);"
+ "f16vec2 log2(f16vec2);"
+ "f16vec3 log2(f16vec3);"
+ "f16vec4 log2(f16vec4);"
+
+ "float16_t sqrt(float16_t);"
+ "f16vec2 sqrt(f16vec2);"
+ "f16vec3 sqrt(f16vec3);"
+ "f16vec4 sqrt(f16vec4);"
+
+ "float16_t inversesqrt(float16_t);"
+ "f16vec2 inversesqrt(f16vec2);"
+ "f16vec3 inversesqrt(f16vec3);"
+ "f16vec4 inversesqrt(f16vec4);"
+
+ "float16_t abs(float16_t);"
+ "f16vec2 abs(f16vec2);"
+ "f16vec3 abs(f16vec3);"
+ "f16vec4 abs(f16vec4);"
+
+ "float16_t sign(float16_t);"
+ "f16vec2 sign(f16vec2);"
+ "f16vec3 sign(f16vec3);"
+ "f16vec4 sign(f16vec4);"
+
+ "float16_t floor(float16_t);"
+ "f16vec2 floor(f16vec2);"
+ "f16vec3 floor(f16vec3);"
+ "f16vec4 floor(f16vec4);"
+
+ "float16_t trunc(float16_t);"
+ "f16vec2 trunc(f16vec2);"
+ "f16vec3 trunc(f16vec3);"
+ "f16vec4 trunc(f16vec4);"
+
+ "float16_t round(float16_t);"
+ "f16vec2 round(f16vec2);"
+ "f16vec3 round(f16vec3);"
+ "f16vec4 round(f16vec4);"
+
+ "float16_t roundEven(float16_t);"
+ "f16vec2 roundEven(f16vec2);"
+ "f16vec3 roundEven(f16vec3);"
+ "f16vec4 roundEven(f16vec4);"
+
+ "float16_t ceil(float16_t);"
+ "f16vec2 ceil(f16vec2);"
+ "f16vec3 ceil(f16vec3);"
+ "f16vec4 ceil(f16vec4);"
+
+ "float16_t fract(float16_t);"
+ "f16vec2 fract(f16vec2);"
+ "f16vec3 fract(f16vec3);"
+ "f16vec4 fract(f16vec4);"
+
+ "float16_t mod(float16_t, float16_t);"
+ "f16vec2 mod(f16vec2, float16_t);"
+ "f16vec3 mod(f16vec3, float16_t);"
+ "f16vec4 mod(f16vec4, float16_t);"
+ "f16vec2 mod(f16vec2, f16vec2);"
+ "f16vec3 mod(f16vec3, f16vec3);"
+ "f16vec4 mod(f16vec4, f16vec4);"
+
+ "float16_t modf(float16_t, out float16_t);"
+ "f16vec2 modf(f16vec2, out f16vec2);"
+ "f16vec3 modf(f16vec3, out f16vec3);"
+ "f16vec4 modf(f16vec4, out f16vec4);"
+
+ "float16_t min(float16_t, float16_t);"
+ "f16vec2 min(f16vec2, float16_t);"
+ "f16vec3 min(f16vec3, float16_t);"
+ "f16vec4 min(f16vec4, float16_t);"
+ "f16vec2 min(f16vec2, f16vec2);"
+ "f16vec3 min(f16vec3, f16vec3);"
+ "f16vec4 min(f16vec4, f16vec4);"
+
+ "float16_t max(float16_t, float16_t);"
+ "f16vec2 max(f16vec2, float16_t);"
+ "f16vec3 max(f16vec3, float16_t);"
+ "f16vec4 max(f16vec4, float16_t);"
+ "f16vec2 max(f16vec2, f16vec2);"
+ "f16vec3 max(f16vec3, f16vec3);"
+ "f16vec4 max(f16vec4, f16vec4);"
+
+ "float16_t clamp(float16_t, float16_t, float16_t);"
+ "f16vec2 clamp(f16vec2, float16_t, float16_t);"
+ "f16vec3 clamp(f16vec3, float16_t, float16_t);"
+ "f16vec4 clamp(f16vec4, float16_t, float16_t);"
+ "f16vec2 clamp(f16vec2, f16vec2, f16vec2);"
+ "f16vec3 clamp(f16vec3, f16vec3, f16vec3);"
+ "f16vec4 clamp(f16vec4, f16vec4, f16vec4);"
+
+ "float16_t mix(float16_t, float16_t, float16_t);"
+ "f16vec2 mix(f16vec2, f16vec2, float16_t);"
+ "f16vec3 mix(f16vec3, f16vec3, float16_t);"
+ "f16vec4 mix(f16vec4, f16vec4, float16_t);"
+ "f16vec2 mix(f16vec2, f16vec2, f16vec2);"
+ "f16vec3 mix(f16vec3, f16vec3, f16vec3);"
+ "f16vec4 mix(f16vec4, f16vec4, f16vec4);"
+ "float16_t mix(float16_t, float16_t, bool);"
+ "f16vec2 mix(f16vec2, f16vec2, bvec2);"
+ "f16vec3 mix(f16vec3, f16vec3, bvec3);"
+ "f16vec4 mix(f16vec4, f16vec4, bvec4);"
+
+ "float16_t step(float16_t, float16_t);"
+ "f16vec2 step(f16vec2, f16vec2);"
+ "f16vec3 step(f16vec3, f16vec3);"
+ "f16vec4 step(f16vec4, f16vec4);"
+ "f16vec2 step(float16_t, f16vec2);"
+ "f16vec3 step(float16_t, f16vec3);"
+ "f16vec4 step(float16_t, f16vec4);"
+
+ "float16_t smoothstep(float16_t, float16_t, float16_t);"
+ "f16vec2 smoothstep(f16vec2, f16vec2, f16vec2);"
+ "f16vec3 smoothstep(f16vec3, f16vec3, f16vec3);"
+ "f16vec4 smoothstep(f16vec4, f16vec4, f16vec4);"
+ "f16vec2 smoothstep(float16_t, float16_t, f16vec2);"
+ "f16vec3 smoothstep(float16_t, float16_t, f16vec3);"
+ "f16vec4 smoothstep(float16_t, float16_t, f16vec4);"
+
+ "bool isnan(float16_t);"
+ "bvec2 isnan(f16vec2);"
+ "bvec3 isnan(f16vec3);"
+ "bvec4 isnan(f16vec4);"
+
+ "bool isinf(float16_t);"
+ "bvec2 isinf(f16vec2);"
+ "bvec3 isinf(f16vec3);"
+ "bvec4 isinf(f16vec4);"
+
+ "float16_t fma(float16_t, float16_t, float16_t);"
+ "f16vec2 fma(f16vec2, f16vec2, f16vec2);"
+ "f16vec3 fma(f16vec3, f16vec3, f16vec3);"
+ "f16vec4 fma(f16vec4, f16vec4, f16vec4);"
+
+ "float16_t frexp(float16_t, out int);"
+ "f16vec2 frexp(f16vec2, out ivec2);"
+ "f16vec3 frexp(f16vec3, out ivec3);"
+ "f16vec4 frexp(f16vec4, out ivec4);"
+
+ "float16_t ldexp(float16_t, in int);"
+ "f16vec2 ldexp(f16vec2, in ivec2);"
+ "f16vec3 ldexp(f16vec3, in ivec3);"
+ "f16vec4 ldexp(f16vec4, in ivec4);"
+
+ "uint packFloat2x16(f16vec2);"
+ "f16vec2 unpackFloat2x16(uint);"
+
+ "float16_t length(float16_t);"
+ "float16_t length(f16vec2);"
+ "float16_t length(f16vec3);"
+ "float16_t length(f16vec4);"
+
+ "float16_t distance(float16_t, float16_t);"
+ "float16_t distance(f16vec2, f16vec2);"
+ "float16_t distance(f16vec3, f16vec3);"
+ "float16_t distance(f16vec4, f16vec4);"
+
+ "float16_t dot(float16_t, float16_t);"
+ "float16_t dot(f16vec2, f16vec2);"
+ "float16_t dot(f16vec3, f16vec3);"
+ "float16_t dot(f16vec4, f16vec4);"
+
+ "f16vec3 cross(f16vec3, f16vec3);"
+
+ "float16_t normalize(float16_t);"
+ "f16vec2 normalize(f16vec2);"
+ "f16vec3 normalize(f16vec3);"
+ "f16vec4 normalize(f16vec4);"
+
+ "float16_t faceforward(float16_t, float16_t, float16_t);"
+ "f16vec2 faceforward(f16vec2, f16vec2, f16vec2);"
+ "f16vec3 faceforward(f16vec3, f16vec3, f16vec3);"
+ "f16vec4 faceforward(f16vec4, f16vec4, f16vec4);"
+
+ "float16_t reflect(float16_t, float16_t);"
+ "f16vec2 reflect(f16vec2, f16vec2);"
+ "f16vec3 reflect(f16vec3, f16vec3);"
+ "f16vec4 reflect(f16vec4, f16vec4);"
+
+ "float16_t refract(float16_t, float16_t, float16_t);"
+ "f16vec2 refract(f16vec2, f16vec2, float16_t);"
+ "f16vec3 refract(f16vec3, f16vec3, float16_t);"
+ "f16vec4 refract(f16vec4, f16vec4, float16_t);"
+
+ "f16mat2 matrixCompMult(f16mat2, f16mat2);"
+ "f16mat3 matrixCompMult(f16mat3, f16mat3);"
+ "f16mat4 matrixCompMult(f16mat4, f16mat4);"
+ "f16mat2x3 matrixCompMult(f16mat2x3, f16mat2x3);"
+ "f16mat2x4 matrixCompMult(f16mat2x4, f16mat2x4);"
+ "f16mat3x2 matrixCompMult(f16mat3x2, f16mat3x2);"
+ "f16mat3x4 matrixCompMult(f16mat3x4, f16mat3x4);"
+ "f16mat4x2 matrixCompMult(f16mat4x2, f16mat4x2);"
+ "f16mat4x3 matrixCompMult(f16mat4x3, f16mat4x3);"
+
+ "f16mat2 outerProduct(f16vec2, f16vec2);"
+ "f16mat3 outerProduct(f16vec3, f16vec3);"
+ "f16mat4 outerProduct(f16vec4, f16vec4);"
+ "f16mat2x3 outerProduct(f16vec3, f16vec2);"
+ "f16mat3x2 outerProduct(f16vec2, f16vec3);"
+ "f16mat2x4 outerProduct(f16vec4, f16vec2);"
+ "f16mat4x2 outerProduct(f16vec2, f16vec4);"
+ "f16mat3x4 outerProduct(f16vec4, f16vec3);"
+ "f16mat4x3 outerProduct(f16vec3, f16vec4);"
+
+ "f16mat2 transpose(f16mat2);"
+ "f16mat3 transpose(f16mat3);"
+ "f16mat4 transpose(f16mat4);"
+ "f16mat2x3 transpose(f16mat3x2);"
+ "f16mat3x2 transpose(f16mat2x3);"
+ "f16mat2x4 transpose(f16mat4x2);"
+ "f16mat4x2 transpose(f16mat2x4);"
+ "f16mat3x4 transpose(f16mat4x3);"
+ "f16mat4x3 transpose(f16mat3x4);"
+
+ "float16_t determinant(f16mat2);"
+ "float16_t determinant(f16mat3);"
+ "float16_t determinant(f16mat4);"
+
+ "f16mat2 inverse(f16mat2);"
+ "f16mat3 inverse(f16mat3);"
+ "f16mat4 inverse(f16mat4);"
+
+ "bvec2 lessThan(f16vec2, f16vec2);"
+ "bvec3 lessThan(f16vec3, f16vec3);"
+ "bvec4 lessThan(f16vec4, f16vec4);"
+
+ "bvec2 lessThanEqual(f16vec2, f16vec2);"
+ "bvec3 lessThanEqual(f16vec3, f16vec3);"
+ "bvec4 lessThanEqual(f16vec4, f16vec4);"
+
+ "bvec2 greaterThan(f16vec2, f16vec2);"
+ "bvec3 greaterThan(f16vec3, f16vec3);"
+ "bvec4 greaterThan(f16vec4, f16vec4);"
+
+ "bvec2 greaterThanEqual(f16vec2, f16vec2);"
+ "bvec3 greaterThanEqual(f16vec3, f16vec3);"
+ "bvec4 greaterThanEqual(f16vec4, f16vec4);"
+
+ "bvec2 equal(f16vec2, f16vec2);"
+ "bvec3 equal(f16vec3, f16vec3);"
+ "bvec4 equal(f16vec4, f16vec4);"
+
+ "bvec2 notEqual(f16vec2, f16vec2);"
+ "bvec3 notEqual(f16vec3, f16vec3);"
+ "bvec4 notEqual(f16vec4, f16vec4);"
+
+ "\n");
+ }
+
+ // Explicit types
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append(
+ "int8_t abs(int8_t);"
+ "i8vec2 abs(i8vec2);"
+ "i8vec3 abs(i8vec3);"
+ "i8vec4 abs(i8vec4);"
+
+ "int8_t sign(int8_t);"
+ "i8vec2 sign(i8vec2);"
+ "i8vec3 sign(i8vec3);"
+ "i8vec4 sign(i8vec4);"
+
+ "int8_t min(int8_t x, int8_t y);"
+ "i8vec2 min(i8vec2 x, int8_t y);"
+ "i8vec3 min(i8vec3 x, int8_t y);"
+ "i8vec4 min(i8vec4 x, int8_t y);"
+ "i8vec2 min(i8vec2 x, i8vec2 y);"
+ "i8vec3 min(i8vec3 x, i8vec3 y);"
+ "i8vec4 min(i8vec4 x, i8vec4 y);"
+
+ "uint8_t min(uint8_t x, uint8_t y);"
+ "u8vec2 min(u8vec2 x, uint8_t y);"
+ "u8vec3 min(u8vec3 x, uint8_t y);"
+ "u8vec4 min(u8vec4 x, uint8_t y);"
+ "u8vec2 min(u8vec2 x, u8vec2 y);"
+ "u8vec3 min(u8vec3 x, u8vec3 y);"
+ "u8vec4 min(u8vec4 x, u8vec4 y);"
+
+ "int8_t max(int8_t x, int8_t y);"
+ "i8vec2 max(i8vec2 x, int8_t y);"
+ "i8vec3 max(i8vec3 x, int8_t y);"
+ "i8vec4 max(i8vec4 x, int8_t y);"
+ "i8vec2 max(i8vec2 x, i8vec2 y);"
+ "i8vec3 max(i8vec3 x, i8vec3 y);"
+ "i8vec4 max(i8vec4 x, i8vec4 y);"
+
+ "uint8_t max(uint8_t x, uint8_t y);"
+ "u8vec2 max(u8vec2 x, uint8_t y);"
+ "u8vec3 max(u8vec3 x, uint8_t y);"
+ "u8vec4 max(u8vec4 x, uint8_t y);"
+ "u8vec2 max(u8vec2 x, u8vec2 y);"
+ "u8vec3 max(u8vec3 x, u8vec3 y);"
+ "u8vec4 max(u8vec4 x, u8vec4 y);"
+
+ "int8_t clamp(int8_t x, int8_t minVal, int8_t maxVal);"
+ "i8vec2 clamp(i8vec2 x, int8_t minVal, int8_t maxVal);"
+ "i8vec3 clamp(i8vec3 x, int8_t minVal, int8_t maxVal);"
+ "i8vec4 clamp(i8vec4 x, int8_t minVal, int8_t maxVal);"
+ "i8vec2 clamp(i8vec2 x, i8vec2 minVal, i8vec2 maxVal);"
+ "i8vec3 clamp(i8vec3 x, i8vec3 minVal, i8vec3 maxVal);"
+ "i8vec4 clamp(i8vec4 x, i8vec4 minVal, i8vec4 maxVal);"
+
+ "uint8_t clamp(uint8_t x, uint8_t minVal, uint8_t maxVal);"
+ "u8vec2 clamp(u8vec2 x, uint8_t minVal, uint8_t maxVal);"
+ "u8vec3 clamp(u8vec3 x, uint8_t minVal, uint8_t maxVal);"
+ "u8vec4 clamp(u8vec4 x, uint8_t minVal, uint8_t maxVal);"
+ "u8vec2 clamp(u8vec2 x, u8vec2 minVal, u8vec2 maxVal);"
+ "u8vec3 clamp(u8vec3 x, u8vec3 minVal, u8vec3 maxVal);"
+ "u8vec4 clamp(u8vec4 x, u8vec4 minVal, u8vec4 maxVal);"
+
+ "int8_t mix(int8_t, int8_t, bool);"
+ "i8vec2 mix(i8vec2, i8vec2, bvec2);"
+ "i8vec3 mix(i8vec3, i8vec3, bvec3);"
+ "i8vec4 mix(i8vec4, i8vec4, bvec4);"
+ "uint8_t mix(uint8_t, uint8_t, bool);"
+ "u8vec2 mix(u8vec2, u8vec2, bvec2);"
+ "u8vec3 mix(u8vec3, u8vec3, bvec3);"
+ "u8vec4 mix(u8vec4, u8vec4, bvec4);"
+
+ "bvec2 lessThan(i8vec2, i8vec2);"
+ "bvec3 lessThan(i8vec3, i8vec3);"
+ "bvec4 lessThan(i8vec4, i8vec4);"
+ "bvec2 lessThan(u8vec2, u8vec2);"
+ "bvec3 lessThan(u8vec3, u8vec3);"
+ "bvec4 lessThan(u8vec4, u8vec4);"
+
+ "bvec2 lessThanEqual(i8vec2, i8vec2);"
+ "bvec3 lessThanEqual(i8vec3, i8vec3);"
+ "bvec4 lessThanEqual(i8vec4, i8vec4);"
+ "bvec2 lessThanEqual(u8vec2, u8vec2);"
+ "bvec3 lessThanEqual(u8vec3, u8vec3);"
+ "bvec4 lessThanEqual(u8vec4, u8vec4);"
+
+ "bvec2 greaterThan(i8vec2, i8vec2);"
+ "bvec3 greaterThan(i8vec3, i8vec3);"
+ "bvec4 greaterThan(i8vec4, i8vec4);"
+ "bvec2 greaterThan(u8vec2, u8vec2);"
+ "bvec3 greaterThan(u8vec3, u8vec3);"
+ "bvec4 greaterThan(u8vec4, u8vec4);"
+
+ "bvec2 greaterThanEqual(i8vec2, i8vec2);"
+ "bvec3 greaterThanEqual(i8vec3, i8vec3);"
+ "bvec4 greaterThanEqual(i8vec4, i8vec4);"
+ "bvec2 greaterThanEqual(u8vec2, u8vec2);"
+ "bvec3 greaterThanEqual(u8vec3, u8vec3);"
+ "bvec4 greaterThanEqual(u8vec4, u8vec4);"
+
+ "bvec2 equal(i8vec2, i8vec2);"
+ "bvec3 equal(i8vec3, i8vec3);"
+ "bvec4 equal(i8vec4, i8vec4);"
+ "bvec2 equal(u8vec2, u8vec2);"
+ "bvec3 equal(u8vec3, u8vec3);"
+ "bvec4 equal(u8vec4, u8vec4);"
+
+ "bvec2 notEqual(i8vec2, i8vec2);"
+ "bvec3 notEqual(i8vec3, i8vec3);"
+ "bvec4 notEqual(i8vec4, i8vec4);"
+ "bvec2 notEqual(u8vec2, u8vec2);"
+ "bvec3 notEqual(u8vec3, u8vec3);"
+ "bvec4 notEqual(u8vec4, u8vec4);"
+
+ " int8_t bitfieldExtract( int8_t, int8_t, int8_t);"
+ "i8vec2 bitfieldExtract(i8vec2, int8_t, int8_t);"
+ "i8vec3 bitfieldExtract(i8vec3, int8_t, int8_t);"
+ "i8vec4 bitfieldExtract(i8vec4, int8_t, int8_t);"
+
+ " uint8_t bitfieldExtract( uint8_t, int8_t, int8_t);"
+ "u8vec2 bitfieldExtract(u8vec2, int8_t, int8_t);"
+ "u8vec3 bitfieldExtract(u8vec3, int8_t, int8_t);"
+ "u8vec4 bitfieldExtract(u8vec4, int8_t, int8_t);"
+
+ " int8_t bitfieldInsert( int8_t base, int8_t, int8_t, int8_t);"
+ "i8vec2 bitfieldInsert(i8vec2 base, i8vec2, int8_t, int8_t);"
+ "i8vec3 bitfieldInsert(i8vec3 base, i8vec3, int8_t, int8_t);"
+ "i8vec4 bitfieldInsert(i8vec4 base, i8vec4, int8_t, int8_t);"
+
+ " uint8_t bitfieldInsert( uint8_t base, uint8_t, int8_t, int8_t);"
+ "u8vec2 bitfieldInsert(u8vec2 base, u8vec2, int8_t, int8_t);"
+ "u8vec3 bitfieldInsert(u8vec3 base, u8vec3, int8_t, int8_t);"
+ "u8vec4 bitfieldInsert(u8vec4 base, u8vec4, int8_t, int8_t);"
+
+ " int8_t bitCount( int8_t);"
+ "i8vec2 bitCount(i8vec2);"
+ "i8vec3 bitCount(i8vec3);"
+ "i8vec4 bitCount(i8vec4);"
+
+ " int8_t bitCount( uint8_t);"
+ "i8vec2 bitCount(u8vec2);"
+ "i8vec3 bitCount(u8vec3);"
+ "i8vec4 bitCount(u8vec4);"
+
+ " int8_t findLSB( int8_t);"
+ "i8vec2 findLSB(i8vec2);"
+ "i8vec3 findLSB(i8vec3);"
+ "i8vec4 findLSB(i8vec4);"
+
+ " int8_t findLSB( uint8_t);"
+ "i8vec2 findLSB(u8vec2);"
+ "i8vec3 findLSB(u8vec3);"
+ "i8vec4 findLSB(u8vec4);"
+
+ " int8_t findMSB( int8_t);"
+ "i8vec2 findMSB(i8vec2);"
+ "i8vec3 findMSB(i8vec3);"
+ "i8vec4 findMSB(i8vec4);"
+
+ " int8_t findMSB( uint8_t);"
+ "i8vec2 findMSB(u8vec2);"
+ "i8vec3 findMSB(u8vec3);"
+ "i8vec4 findMSB(u8vec4);"
+
+ "int16_t abs(int16_t);"
+ "i16vec2 abs(i16vec2);"
+ "i16vec3 abs(i16vec3);"
+ "i16vec4 abs(i16vec4);"
+
+ "int16_t sign(int16_t);"
+ "i16vec2 sign(i16vec2);"
+ "i16vec3 sign(i16vec3);"
+ "i16vec4 sign(i16vec4);"
+
+ "int16_t min(int16_t x, int16_t y);"
+ "i16vec2 min(i16vec2 x, int16_t y);"
+ "i16vec3 min(i16vec3 x, int16_t y);"
+ "i16vec4 min(i16vec4 x, int16_t y);"
+ "i16vec2 min(i16vec2 x, i16vec2 y);"
+ "i16vec3 min(i16vec3 x, i16vec3 y);"
+ "i16vec4 min(i16vec4 x, i16vec4 y);"
+
+ "uint16_t min(uint16_t x, uint16_t y);"
+ "u16vec2 min(u16vec2 x, uint16_t y);"
+ "u16vec3 min(u16vec3 x, uint16_t y);"
+ "u16vec4 min(u16vec4 x, uint16_t y);"
+ "u16vec2 min(u16vec2 x, u16vec2 y);"
+ "u16vec3 min(u16vec3 x, u16vec3 y);"
+ "u16vec4 min(u16vec4 x, u16vec4 y);"
+
+ "int16_t max(int16_t x, int16_t y);"
+ "i16vec2 max(i16vec2 x, int16_t y);"
+ "i16vec3 max(i16vec3 x, int16_t y);"
+ "i16vec4 max(i16vec4 x, int16_t y);"
+ "i16vec2 max(i16vec2 x, i16vec2 y);"
+ "i16vec3 max(i16vec3 x, i16vec3 y);"
+ "i16vec4 max(i16vec4 x, i16vec4 y);"
+
+ "uint16_t max(uint16_t x, uint16_t y);"
+ "u16vec2 max(u16vec2 x, uint16_t y);"
+ "u16vec3 max(u16vec3 x, uint16_t y);"
+ "u16vec4 max(u16vec4 x, uint16_t y);"
+ "u16vec2 max(u16vec2 x, u16vec2 y);"
+ "u16vec3 max(u16vec3 x, u16vec3 y);"
+ "u16vec4 max(u16vec4 x, u16vec4 y);"
+
+ "int16_t clamp(int16_t x, int16_t minVal, int16_t maxVal);"
+ "i16vec2 clamp(i16vec2 x, int16_t minVal, int16_t maxVal);"
+ "i16vec3 clamp(i16vec3 x, int16_t minVal, int16_t maxVal);"
+ "i16vec4 clamp(i16vec4 x, int16_t minVal, int16_t maxVal);"
+ "i16vec2 clamp(i16vec2 x, i16vec2 minVal, i16vec2 maxVal);"
+ "i16vec3 clamp(i16vec3 x, i16vec3 minVal, i16vec3 maxVal);"
+ "i16vec4 clamp(i16vec4 x, i16vec4 minVal, i16vec4 maxVal);"
+
+ "uint16_t clamp(uint16_t x, uint16_t minVal, uint16_t maxVal);"
+ "u16vec2 clamp(u16vec2 x, uint16_t minVal, uint16_t maxVal);"
+ "u16vec3 clamp(u16vec3 x, uint16_t minVal, uint16_t maxVal);"
+ "u16vec4 clamp(u16vec4 x, uint16_t minVal, uint16_t maxVal);"
+ "u16vec2 clamp(u16vec2 x, u16vec2 minVal, u16vec2 maxVal);"
+ "u16vec3 clamp(u16vec3 x, u16vec3 minVal, u16vec3 maxVal);"
+ "u16vec4 clamp(u16vec4 x, u16vec4 minVal, u16vec4 maxVal);"
+
+ "int16_t mix(int16_t, int16_t, bool);"
+ "i16vec2 mix(i16vec2, i16vec2, bvec2);"
+ "i16vec3 mix(i16vec3, i16vec3, bvec3);"
+ "i16vec4 mix(i16vec4, i16vec4, bvec4);"
+ "uint16_t mix(uint16_t, uint16_t, bool);"
+ "u16vec2 mix(u16vec2, u16vec2, bvec2);"
+ "u16vec3 mix(u16vec3, u16vec3, bvec3);"
+ "u16vec4 mix(u16vec4, u16vec4, bvec4);"
+
+ "float16_t frexp(float16_t, out int16_t);"
+ "f16vec2 frexp(f16vec2, out i16vec2);"
+ "f16vec3 frexp(f16vec3, out i16vec3);"
+ "f16vec4 frexp(f16vec4, out i16vec4);"
+
+ "float16_t ldexp(float16_t, int16_t);"
+ "f16vec2 ldexp(f16vec2, i16vec2);"
+ "f16vec3 ldexp(f16vec3, i16vec3);"
+ "f16vec4 ldexp(f16vec4, i16vec4);"
+
+ "int16_t halfBitsToInt16(float16_t);"
+ "i16vec2 halfBitsToInt16(f16vec2);"
+ "i16vec3 halhBitsToInt16(f16vec3);"
+ "i16vec4 halfBitsToInt16(f16vec4);"
+
+ "uint16_t halfBitsToUint16(float16_t);"
+ "u16vec2 halfBitsToUint16(f16vec2);"
+ "u16vec3 halfBitsToUint16(f16vec3);"
+ "u16vec4 halfBitsToUint16(f16vec4);"
+
+ "int16_t float16BitsToInt16(float16_t);"
+ "i16vec2 float16BitsToInt16(f16vec2);"
+ "i16vec3 float16BitsToInt16(f16vec3);"
+ "i16vec4 float16BitsToInt16(f16vec4);"
+
+ "uint16_t float16BitsToUint16(float16_t);"
+ "u16vec2 float16BitsToUint16(f16vec2);"
+ "u16vec3 float16BitsToUint16(f16vec3);"
+ "u16vec4 float16BitsToUint16(f16vec4);"
+
+ "float16_t int16BitsToFloat16(int16_t);"
+ "f16vec2 int16BitsToFloat16(i16vec2);"
+ "f16vec3 int16BitsToFloat16(i16vec3);"
+ "f16vec4 int16BitsToFloat16(i16vec4);"
+
+ "float16_t uint16BitsToFloat16(uint16_t);"
+ "f16vec2 uint16BitsToFloat16(u16vec2);"
+ "f16vec3 uint16BitsToFloat16(u16vec3);"
+ "f16vec4 uint16BitsToFloat16(u16vec4);"
+
+ "float16_t int16BitsToHalf(int16_t);"
+ "f16vec2 int16BitsToHalf(i16vec2);"
+ "f16vec3 int16BitsToHalf(i16vec3);"
+ "f16vec4 int16BitsToHalf(i16vec4);"
+
+ "float16_t uint16BitsToHalf(uint16_t);"
+ "f16vec2 uint16BitsToHalf(u16vec2);"
+ "f16vec3 uint16BitsToHalf(u16vec3);"
+ "f16vec4 uint16BitsToHalf(u16vec4);"
+
+ "int packInt2x16(i16vec2);"
+ "uint packUint2x16(u16vec2);"
+ "int64_t packInt4x16(i16vec4);"
+ "uint64_t packUint4x16(u16vec4);"
+ "i16vec2 unpackInt2x16(int);"
+ "u16vec2 unpackUint2x16(uint);"
+ "i16vec4 unpackInt4x16(int64_t);"
+ "u16vec4 unpackUint4x16(uint64_t);"
+
+ "bvec2 lessThan(i16vec2, i16vec2);"
+ "bvec3 lessThan(i16vec3, i16vec3);"
+ "bvec4 lessThan(i16vec4, i16vec4);"
+ "bvec2 lessThan(u16vec2, u16vec2);"
+ "bvec3 lessThan(u16vec3, u16vec3);"
+ "bvec4 lessThan(u16vec4, u16vec4);"
+
+ "bvec2 lessThanEqual(i16vec2, i16vec2);"
+ "bvec3 lessThanEqual(i16vec3, i16vec3);"
+ "bvec4 lessThanEqual(i16vec4, i16vec4);"
+ "bvec2 lessThanEqual(u16vec2, u16vec2);"
+ "bvec3 lessThanEqual(u16vec3, u16vec3);"
+ "bvec4 lessThanEqual(u16vec4, u16vec4);"
+
+ "bvec2 greaterThan(i16vec2, i16vec2);"
+ "bvec3 greaterThan(i16vec3, i16vec3);"
+ "bvec4 greaterThan(i16vec4, i16vec4);"
+ "bvec2 greaterThan(u16vec2, u16vec2);"
+ "bvec3 greaterThan(u16vec3, u16vec3);"
+ "bvec4 greaterThan(u16vec4, u16vec4);"
+
+ "bvec2 greaterThanEqual(i16vec2, i16vec2);"
+ "bvec3 greaterThanEqual(i16vec3, i16vec3);"
+ "bvec4 greaterThanEqual(i16vec4, i16vec4);"
+ "bvec2 greaterThanEqual(u16vec2, u16vec2);"
+ "bvec3 greaterThanEqual(u16vec3, u16vec3);"
+ "bvec4 greaterThanEqual(u16vec4, u16vec4);"
+
+ "bvec2 equal(i16vec2, i16vec2);"
+ "bvec3 equal(i16vec3, i16vec3);"
+ "bvec4 equal(i16vec4, i16vec4);"
+ "bvec2 equal(u16vec2, u16vec2);"
+ "bvec3 equal(u16vec3, u16vec3);"
+ "bvec4 equal(u16vec4, u16vec4);"
+
+ "bvec2 notEqual(i16vec2, i16vec2);"
+ "bvec3 notEqual(i16vec3, i16vec3);"
+ "bvec4 notEqual(i16vec4, i16vec4);"
+ "bvec2 notEqual(u16vec2, u16vec2);"
+ "bvec3 notEqual(u16vec3, u16vec3);"
+ "bvec4 notEqual(u16vec4, u16vec4);"
+
+ " int16_t bitfieldExtract( int16_t, int16_t, int16_t);"
+ "i16vec2 bitfieldExtract(i16vec2, int16_t, int16_t);"
+ "i16vec3 bitfieldExtract(i16vec3, int16_t, int16_t);"
+ "i16vec4 bitfieldExtract(i16vec4, int16_t, int16_t);"
+
+ " uint16_t bitfieldExtract( uint16_t, int16_t, int16_t);"
+ "u16vec2 bitfieldExtract(u16vec2, int16_t, int16_t);"
+ "u16vec3 bitfieldExtract(u16vec3, int16_t, int16_t);"
+ "u16vec4 bitfieldExtract(u16vec4, int16_t, int16_t);"
+
+ " int16_t bitfieldInsert( int16_t base, int16_t, int16_t, int16_t);"
+ "i16vec2 bitfieldInsert(i16vec2 base, i16vec2, int16_t, int16_t);"
+ "i16vec3 bitfieldInsert(i16vec3 base, i16vec3, int16_t, int16_t);"
+ "i16vec4 bitfieldInsert(i16vec4 base, i16vec4, int16_t, int16_t);"
+
+ " uint16_t bitfieldInsert( uint16_t base, uint16_t, int16_t, int16_t);"
+ "u16vec2 bitfieldInsert(u16vec2 base, u16vec2, int16_t, int16_t);"
+ "u16vec3 bitfieldInsert(u16vec3 base, u16vec3, int16_t, int16_t);"
+ "u16vec4 bitfieldInsert(u16vec4 base, u16vec4, int16_t, int16_t);"
+
+ " int16_t bitCount( int16_t);"
+ "i16vec2 bitCount(i16vec2);"
+ "i16vec3 bitCount(i16vec3);"
+ "i16vec4 bitCount(i16vec4);"
+
+ " int16_t bitCount( uint16_t);"
+ "i16vec2 bitCount(u16vec2);"
+ "i16vec3 bitCount(u16vec3);"
+ "i16vec4 bitCount(u16vec4);"
+
+ " int16_t findLSB( int16_t);"
+ "i16vec2 findLSB(i16vec2);"
+ "i16vec3 findLSB(i16vec3);"
+ "i16vec4 findLSB(i16vec4);"
+
+ " int16_t findLSB( uint16_t);"
+ "i16vec2 findLSB(u16vec2);"
+ "i16vec3 findLSB(u16vec3);"
+ "i16vec4 findLSB(u16vec4);"
+
+ " int16_t findMSB( int16_t);"
+ "i16vec2 findMSB(i16vec2);"
+ "i16vec3 findMSB(i16vec3);"
+ "i16vec4 findMSB(i16vec4);"
+
+ " int16_t findMSB( uint16_t);"
+ "i16vec2 findMSB(u16vec2);"
+ "i16vec3 findMSB(u16vec3);"
+ "i16vec4 findMSB(u16vec4);"
+
+ "int16_t pack16(i8vec2);"
+ "uint16_t pack16(u8vec2);"
+ "int32_t pack32(i8vec4);"
+ "uint32_t pack32(u8vec4);"
+ "int32_t pack32(i16vec2);"
+ "uint32_t pack32(u16vec2);"
+ "int64_t pack64(i16vec4);"
+ "uint64_t pack64(u16vec4);"
+ "int64_t pack64(i32vec2);"
+ "uint64_t pack64(u32vec2);"
+
+ "i8vec2 unpack8(int16_t);"
+ "u8vec2 unpack8(uint16_t);"
+ "i8vec4 unpack8(int32_t);"
+ "u8vec4 unpack8(uint32_t);"
+ "i16vec2 unpack16(int32_t);"
+ "u16vec2 unpack16(uint32_t);"
+ "i16vec4 unpack16(int64_t);"
+ "u16vec4 unpack16(uint64_t);"
+ "i32vec2 unpack32(int64_t);"
+ "u32vec2 unpack32(uint64_t);"
+
+ "float64_t radians(float64_t);"
+ "f64vec2 radians(f64vec2);"
+ "f64vec3 radians(f64vec3);"
+ "f64vec4 radians(f64vec4);"
+
+ "float64_t degrees(float64_t);"
+ "f64vec2 degrees(f64vec2);"
+ "f64vec3 degrees(f64vec3);"
+ "f64vec4 degrees(f64vec4);"
+
+ "float64_t sin(float64_t);"
+ "f64vec2 sin(f64vec2);"
+ "f64vec3 sin(f64vec3);"
+ "f64vec4 sin(f64vec4);"
+
+ "float64_t cos(float64_t);"
+ "f64vec2 cos(f64vec2);"
+ "f64vec3 cos(f64vec3);"
+ "f64vec4 cos(f64vec4);"
+
+ "float64_t tan(float64_t);"
+ "f64vec2 tan(f64vec2);"
+ "f64vec3 tan(f64vec3);"
+ "f64vec4 tan(f64vec4);"
+
+ "float64_t asin(float64_t);"
+ "f64vec2 asin(f64vec2);"
+ "f64vec3 asin(f64vec3);"
+ "f64vec4 asin(f64vec4);"
+
+ "float64_t acos(float64_t);"
+ "f64vec2 acos(f64vec2);"
+ "f64vec3 acos(f64vec3);"
+ "f64vec4 acos(f64vec4);"
+
+ "float64_t atan(float64_t, float64_t);"
+ "f64vec2 atan(f64vec2, f64vec2);"
+ "f64vec3 atan(f64vec3, f64vec3);"
+ "f64vec4 atan(f64vec4, f64vec4);"
+
+ "float64_t atan(float64_t);"
+ "f64vec2 atan(f64vec2);"
+ "f64vec3 atan(f64vec3);"
+ "f64vec4 atan(f64vec4);"
+
+ "float64_t sinh(float64_t);"
+ "f64vec2 sinh(f64vec2);"
+ "f64vec3 sinh(f64vec3);"
+ "f64vec4 sinh(f64vec4);"
+
+ "float64_t cosh(float64_t);"
+ "f64vec2 cosh(f64vec2);"
+ "f64vec3 cosh(f64vec3);"
+ "f64vec4 cosh(f64vec4);"
+
+ "float64_t tanh(float64_t);"
+ "f64vec2 tanh(f64vec2);"
+ "f64vec3 tanh(f64vec3);"
+ "f64vec4 tanh(f64vec4);"
+
+ "float64_t asinh(float64_t);"
+ "f64vec2 asinh(f64vec2);"
+ "f64vec3 asinh(f64vec3);"
+ "f64vec4 asinh(f64vec4);"
+
+ "float64_t acosh(float64_t);"
+ "f64vec2 acosh(f64vec2);"
+ "f64vec3 acosh(f64vec3);"
+ "f64vec4 acosh(f64vec4);"
+
+ "float64_t atanh(float64_t);"
+ "f64vec2 atanh(f64vec2);"
+ "f64vec3 atanh(f64vec3);"
+ "f64vec4 atanh(f64vec4);"
+
+ "float64_t pow(float64_t, float64_t);"
+ "f64vec2 pow(f64vec2, f64vec2);"
+ "f64vec3 pow(f64vec3, f64vec3);"
+ "f64vec4 pow(f64vec4, f64vec4);"
+
+ "float64_t exp(float64_t);"
+ "f64vec2 exp(f64vec2);"
+ "f64vec3 exp(f64vec3);"
+ "f64vec4 exp(f64vec4);"
+
+ "float64_t log(float64_t);"
+ "f64vec2 log(f64vec2);"
+ "f64vec3 log(f64vec3);"
+ "f64vec4 log(f64vec4);"
+
+ "float64_t exp2(float64_t);"
+ "f64vec2 exp2(f64vec2);"
+ "f64vec3 exp2(f64vec3);"
+ "f64vec4 exp2(f64vec4);"
+
+ "float64_t log2(float64_t);"
+ "f64vec2 log2(f64vec2);"
+ "f64vec3 log2(f64vec3);"
+ "f64vec4 log2(f64vec4);"
+ "\n");
+ }
+ if (profile != EEsProfile && version >= 450) {
+ stageBuiltins[EShLangFragment].append(derivativesAndControl64bits);
+ stageBuiltins[EShLangFragment].append(
+ "float64_t interpolateAtCentroid(float64_t);"
+ "f64vec2 interpolateAtCentroid(f64vec2);"
+ "f64vec3 interpolateAtCentroid(f64vec3);"
+ "f64vec4 interpolateAtCentroid(f64vec4);"
+
+ "float64_t interpolateAtSample(float64_t, int);"
+ "f64vec2 interpolateAtSample(f64vec2, int);"
+ "f64vec3 interpolateAtSample(f64vec3, int);"
+ "f64vec4 interpolateAtSample(f64vec4, int);"
+
+ "float64_t interpolateAtOffset(float64_t, f64vec2);"
+ "f64vec2 interpolateAtOffset(f64vec2, f64vec2);"
+ "f64vec3 interpolateAtOffset(f64vec3, f64vec2);"
+ "f64vec4 interpolateAtOffset(f64vec4, f64vec2);"
+
+ "\n");
+
+ }
+
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by vertex shaders only.
+ // (Except legacy lod functions, where it depends which release they are
+ // vertex only.)
+ //
+ //============================================================================
+
+ //
+ // Geometric Functions.
+ //
+ if (spvVersion.vulkan == 0 && IncludeLegacy(version, profile, spvVersion))
+ stageBuiltins[EShLangVertex].append("vec4 ftransform();");
+
+ //
+ // Original-style texture Functions with lod.
+ //
+ TString* s;
+ if (version == 100)
+ s = &stageBuiltins[EShLangVertex];
+ else
+ s = &commonBuiltins;
+ if ((profile == EEsProfile && version == 100) ||
+ profile == ECompatibilityProfile ||
+ (profile == ECoreProfile && version < 420) ||
+ profile == ENoProfile) {
+ if (spvVersion.spv == 0) {
+ s->append(
+ "vec4 texture2DLod(sampler2D, vec2, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DProjLod(sampler2D, vec3, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DProjLod(sampler2D, vec4, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture3DLod(sampler3D, vec3, float);" // GL_ARB_shader_texture_lod // OES_texture_3D, but caught by keyword check
+ "vec4 texture3DProjLod(sampler3D, vec4, float);" // GL_ARB_shader_texture_lod // OES_texture_3D, but caught by keyword check
+ "vec4 textureCubeLod(samplerCube, vec3, float);" // GL_ARB_shader_texture_lod
+
+ "\n");
+ }
+ }
+ if ( profile == ECompatibilityProfile ||
+ (profile == ECoreProfile && version < 420) ||
+ profile == ENoProfile) {
+ if (spvVersion.spv == 0) {
+ s->append(
+ "vec4 texture1DLod(sampler1D, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture1DProjLod(sampler1D, vec2, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture1DProjLod(sampler1D, vec4, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow1DLod(sampler1DShadow, vec3, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DLod(sampler2DShadow, vec3, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow1DProjLod(sampler1DShadow, vec4, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DProjLod(sampler2DShadow, vec4, float);" // GL_ARB_shader_texture_lod
+
+ "vec4 texture1DGradARB(sampler1D, float, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture1DProjGradARB(sampler1D, vec2, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture1DProjGradARB(sampler1D, vec4, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DGradARB(sampler2D, vec2, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DProjGradARB(sampler2D, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DProjGradARB(sampler2D, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture3DGradARB(sampler3D, vec3, vec3, vec3);" // GL_ARB_shader_texture_lod
+ "vec4 texture3DProjGradARB(sampler3D, vec4, vec3, vec3);" // GL_ARB_shader_texture_lod
+ "vec4 textureCubeGradARB(samplerCube, vec3, vec3, vec3);" // GL_ARB_shader_texture_lod
+ "vec4 shadow1DGradARB(sampler1DShadow, vec3, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow1DProjGradARB( sampler1DShadow, vec4, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DGradARB(sampler2DShadow, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DProjGradARB( sampler2DShadow, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DRectGradARB(sampler2DRect, vec2, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DRectProjGradARB( sampler2DRect, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DRectProjGradARB( sampler2DRect, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DRectGradARB( sampler2DRectShadow, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DRectProjGradARB(sampler2DRectShadow, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod
+
+ "\n");
+ }
+ }
+
+ if ((profile != EEsProfile && version >= 150) ||
+ (profile == EEsProfile && version >= 310)) {
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by geometry shaders only.
+ //
+ //============================================================================
+
+ if (profile != EEsProfile && version >= 400) {
+ stageBuiltins[EShLangGeometry].append(
+ "void EmitStreamVertex(int);"
+ "void EndStreamPrimitive(int);"
+ );
+ }
+ stageBuiltins[EShLangGeometry].append(
+ "void EmitVertex();"
+ "void EndPrimitive();"
+ "\n");
+ }
+#endif
+
+ //============================================================================
+ //
+ // Prototypes for all control functions.
+ //
+ //============================================================================
+ bool esBarrier = (profile == EEsProfile && version >= 310);
+ if ((profile != EEsProfile && version >= 150) || esBarrier)
+ stageBuiltins[EShLangTessControl].append(
+ "void barrier();"
+ );
+ if ((profile != EEsProfile && version >= 420) || esBarrier)
+ stageBuiltins[EShLangCompute].append(
+ "void barrier();"
+ );
+ if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
+ stageBuiltins[EShLangMeshNV].append(
+ "void barrier();"
+ );
+ stageBuiltins[EShLangTaskNV].append(
+ "void barrier();"
+ );
+ }
+ if ((profile != EEsProfile && version >= 130) || esBarrier)
+ commonBuiltins.append(
+ "void memoryBarrier();"
+ );
+ if ((profile != EEsProfile && version >= 420) || esBarrier) {
+ commonBuiltins.append(
+ "void memoryBarrierBuffer();"
+ );
+ stageBuiltins[EShLangCompute].append(
+ "void memoryBarrierShared();"
+ "void groupMemoryBarrier();"
+ );
+ }
+#ifndef GLSLANG_WEB
+ if ((profile != EEsProfile && version >= 420) || esBarrier) {
+ commonBuiltins.append(
+ "void memoryBarrierAtomicCounter();"
+ "void memoryBarrierImage();"
+ );
+ }
+ if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
+ stageBuiltins[EShLangMeshNV].append(
+ "void memoryBarrierShared();"
+ "void groupMemoryBarrier();"
+ );
+ stageBuiltins[EShLangTaskNV].append(
+ "void memoryBarrierShared();"
+ "void groupMemoryBarrier();"
+ );
+ }
+
+ commonBuiltins.append("void controlBarrier(int, int, int, int);\n"
+ "void memoryBarrier(int, int, int);\n");
+
+ if (profile != EEsProfile && version >= 450) {
+ // coopMatStoreNV perhaps ought to have "out" on the buf parameter, but
+ // adding it introduces undesirable tempArgs on the stack. What we want
+ // is more like "buf" thought of as a pointer value being an in parameter.
+ stageBuiltins[EShLangCompute].append(
+ "void coopMatLoadNV(out fcoopmatNV m, volatile coherent float16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out fcoopmatNV m, volatile coherent float[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n"
+
+ "void coopMatStoreNV(fcoopmatNV m, volatile coherent float16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(fcoopmatNV m, volatile coherent float[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(fcoopmatNV m, volatile coherent float64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(fcoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(fcoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(fcoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(fcoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(fcoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(fcoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n"
+
+ "fcoopmatNV coopMatMulAddNV(fcoopmatNV A, fcoopmatNV B, fcoopmatNV C);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent int8_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent int16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent int[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent int64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent ivec2[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent ivec4[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out icoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n"
+
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent int8_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent int16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent int[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent int64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent ivec2[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent ivec4[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n"
+
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent int8_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent int16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent int[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent int64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent ivec2[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent ivec4[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(icoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n"
+
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent int8_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent int16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent int[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent int64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent ivec2[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent ivec4[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n"
+ "void coopMatStoreNV(ucoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n"
+
+ "icoopmatNV coopMatMulAddNV(icoopmatNV A, icoopmatNV B, icoopmatNV C);\n"
+ "ucoopmatNV coopMatMulAddNV(ucoopmatNV A, ucoopmatNV B, ucoopmatNV C);\n"
+ );
+ }
+
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by fragment shaders only.
+ //
+ //============================================================================
+
+ //
+ // Original-style texture Functions with bias.
+ //
+ if (spvVersion.spv == 0 && (profile != EEsProfile || version == 100)) {
+ stageBuiltins[EShLangFragment].append(
+ "vec4 texture2D(sampler2D, vec2, float);"
+ "vec4 texture2DProj(sampler2D, vec3, float);"
+ "vec4 texture2DProj(sampler2D, vec4, float);"
+ "vec4 texture3D(sampler3D, vec3, float);" // OES_texture_3D
+ "vec4 texture3DProj(sampler3D, vec4, float);" // OES_texture_3D
+ "vec4 textureCube(samplerCube, vec3, float);"
+
+ "\n");
+ }
+ if (spvVersion.spv == 0 && (profile != EEsProfile && version > 100)) {
+ stageBuiltins[EShLangFragment].append(
+ "vec4 texture1D(sampler1D, float, float);"
+ "vec4 texture1DProj(sampler1D, vec2, float);"
+ "vec4 texture1DProj(sampler1D, vec4, float);"
+ "vec4 shadow1D(sampler1DShadow, vec3, float);"
+ "vec4 shadow2D(sampler2DShadow, vec3, float);"
+ "vec4 shadow1DProj(sampler1DShadow, vec4, float);"
+ "vec4 shadow2DProj(sampler2DShadow, vec4, float);"
+
+ "\n");
+ }
+ if (spvVersion.spv == 0 && profile == EEsProfile) {
+ stageBuiltins[EShLangFragment].append(
+ "vec4 texture2DLodEXT(sampler2D, vec2, float);" // GL_EXT_shader_texture_lod
+ "vec4 texture2DProjLodEXT(sampler2D, vec3, float);" // GL_EXT_shader_texture_lod
+ "vec4 texture2DProjLodEXT(sampler2D, vec4, float);" // GL_EXT_shader_texture_lod
+ "vec4 textureCubeLodEXT(samplerCube, vec3, float);" // GL_EXT_shader_texture_lod
+
+ "\n");
+ }
+
+ // GL_ARB_derivative_control
+ if (profile != EEsProfile && version >= 400) {
+ stageBuiltins[EShLangFragment].append(derivativeControls);
+ stageBuiltins[EShLangFragment].append("\n");
+ }
+
+ // GL_OES_shader_multisample_interpolation
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 400)) {
+ stageBuiltins[EShLangFragment].append(
+ "float interpolateAtCentroid(float);"
+ "vec2 interpolateAtCentroid(vec2);"
+ "vec3 interpolateAtCentroid(vec3);"
+ "vec4 interpolateAtCentroid(vec4);"
+
+ "float interpolateAtSample(float, int);"
+ "vec2 interpolateAtSample(vec2, int);"
+ "vec3 interpolateAtSample(vec3, int);"
+ "vec4 interpolateAtSample(vec4, int);"
+
+ "float interpolateAtOffset(float, vec2);"
+ "vec2 interpolateAtOffset(vec2, vec2);"
+ "vec3 interpolateAtOffset(vec3, vec2);"
+ "vec4 interpolateAtOffset(vec4, vec2);"
+
+ "\n");
+ }
+
+ stageBuiltins[EShLangFragment].append(
+ "void beginInvocationInterlockARB(void);"
+ "void endInvocationInterlockARB(void);");
+
+ stageBuiltins[EShLangFragment].append(
+ "bool helperInvocationEXT();"
+ "\n");
+
+ // GL_AMD_shader_explicit_vertex_parameter
+ if (profile != EEsProfile && version >= 450) {
+ stageBuiltins[EShLangFragment].append(
+ "float interpolateAtVertexAMD(float, uint);"
+ "vec2 interpolateAtVertexAMD(vec2, uint);"
+ "vec3 interpolateAtVertexAMD(vec3, uint);"
+ "vec4 interpolateAtVertexAMD(vec4, uint);"
+
+ "int interpolateAtVertexAMD(int, uint);"
+ "ivec2 interpolateAtVertexAMD(ivec2, uint);"
+ "ivec3 interpolateAtVertexAMD(ivec3, uint);"
+ "ivec4 interpolateAtVertexAMD(ivec4, uint);"
+
+ "uint interpolateAtVertexAMD(uint, uint);"
+ "uvec2 interpolateAtVertexAMD(uvec2, uint);"
+ "uvec3 interpolateAtVertexAMD(uvec3, uint);"
+ "uvec4 interpolateAtVertexAMD(uvec4, uint);"
+
+ "float16_t interpolateAtVertexAMD(float16_t, uint);"
+ "f16vec2 interpolateAtVertexAMD(f16vec2, uint);"
+ "f16vec3 interpolateAtVertexAMD(f16vec3, uint);"
+ "f16vec4 interpolateAtVertexAMD(f16vec4, uint);"
+
+ "\n");
+ }
+
+ // GL_AMD_gpu_shader_half_float
+ if (profile != EEsProfile && version >= 450) {
+ stageBuiltins[EShLangFragment].append(derivativesAndControl16bits);
+ stageBuiltins[EShLangFragment].append("\n");
+
+ stageBuiltins[EShLangFragment].append(
+ "float16_t interpolateAtCentroid(float16_t);"
+ "f16vec2 interpolateAtCentroid(f16vec2);"
+ "f16vec3 interpolateAtCentroid(f16vec3);"
+ "f16vec4 interpolateAtCentroid(f16vec4);"
+
+ "float16_t interpolateAtSample(float16_t, int);"
+ "f16vec2 interpolateAtSample(f16vec2, int);"
+ "f16vec3 interpolateAtSample(f16vec3, int);"
+ "f16vec4 interpolateAtSample(f16vec4, int);"
+
+ "float16_t interpolateAtOffset(float16_t, f16vec2);"
+ "f16vec2 interpolateAtOffset(f16vec2, f16vec2);"
+ "f16vec3 interpolateAtOffset(f16vec3, f16vec2);"
+ "f16vec4 interpolateAtOffset(f16vec4, f16vec2);"
+
+ "\n");
+ }
+
+ // GL_ARB_shader_clock & GL_EXT_shader_realtime_clock
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append(
+ "uvec2 clock2x32ARB();"
+ "uint64_t clockARB();"
+ "uvec2 clockRealtime2x32EXT();"
+ "uint64_t clockRealtimeEXT();"
+ "\n");
+ }
+
+ // GL_AMD_shader_fragment_mask
+ if (profile != EEsProfile && version >= 450 && spvVersion.vulkan > 0) {
+ stageBuiltins[EShLangFragment].append(
+ "uint fragmentMaskFetchAMD(subpassInputMS);"
+ "uint fragmentMaskFetchAMD(isubpassInputMS);"
+ "uint fragmentMaskFetchAMD(usubpassInputMS);"
+
+ "vec4 fragmentFetchAMD(subpassInputMS, uint);"
+ "ivec4 fragmentFetchAMD(isubpassInputMS, uint);"
+ "uvec4 fragmentFetchAMD(usubpassInputMS, uint);"
+
+ "\n");
+ }
+
+ // Builtins for GL_NV_ray_tracing
+ if (profile != EEsProfile && version >= 460) {
+ stageBuiltins[EShLangRayGenNV].append(
+ "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
+ "void executeCallableNV(uint, int);"
+ "\n");
+ stageBuiltins[EShLangIntersectNV].append(
+ "bool reportIntersectionNV(float, uint);"
+ "\n");
+ stageBuiltins[EShLangAnyHitNV].append(
+ "void ignoreIntersectionNV();"
+ "void terminateRayNV();"
+ "\n");
+ stageBuiltins[EShLangClosestHitNV].append(
+ "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
+ "void executeCallableNV(uint, int);"
+ "\n");
+ stageBuiltins[EShLangMissNV].append(
+ "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
+ "void executeCallableNV(uint, int);"
+ "\n");
+ stageBuiltins[EShLangCallableNV].append(
+ "void executeCallableNV(uint, int);"
+ "\n");
+ }
+
+ //E_SPV_NV_compute_shader_derivatives
+ if ((profile == EEsProfile && version >= 320) || (profile != EEsProfile && version >= 450)) {
+ stageBuiltins[EShLangCompute].append(derivativeControls);
+ stageBuiltins[EShLangCompute].append("\n");
+ }
+ if (profile != EEsProfile && version >= 450) {
+ stageBuiltins[EShLangCompute].append(derivativesAndControl16bits);
+ stageBuiltins[EShLangCompute].append(derivativesAndControl64bits);
+ stageBuiltins[EShLangCompute].append("\n");
+ }
+
+ // Builtins for GL_NV_mesh_shader
+ if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
+ stageBuiltins[EShLangMeshNV].append(
+ "void writePackedPrimitiveIndices4x8NV(uint, uint);"
+ "\n");
+ }
+#endif
+
+ //============================================================================
+ //
+ // Standard Uniforms
+ //
+ //============================================================================
+
+ //
+ // Depth range in window coordinates, p. 33
+ //
+ if (spvVersion.spv == 0) {
+ commonBuiltins.append(
+ "struct gl_DepthRangeParameters {"
+ );
+ if (profile == EEsProfile) {
+ commonBuiltins.append(
+ "highp float near;" // n
+ "highp float far;" // f
+ "highp float diff;" // f - n
+ );
+ } else {
+#ifndef GLSLANG_WEB
+ commonBuiltins.append(
+ "float near;" // n
+ "float far;" // f
+ "float diff;" // f - n
+ );
+#endif
+ }
+
+ commonBuiltins.append(
+ "};"
+ "uniform gl_DepthRangeParameters gl_DepthRange;"
+ "\n");
+ }
+
+#ifndef GLSLANG_WEB
+ if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) {
+ //
+ // Matrix state. p. 31, 32, 37, 39, 40.
+ //
+ commonBuiltins.append(
+ "uniform mat4 gl_ModelViewMatrix;"
+ "uniform mat4 gl_ProjectionMatrix;"
+ "uniform mat4 gl_ModelViewProjectionMatrix;"
+
+ //
+ // Derived matrix state that provides inverse and transposed versions
+ // of the matrices above.
+ //
+ "uniform mat3 gl_NormalMatrix;"
+
+ "uniform mat4 gl_ModelViewMatrixInverse;"
+ "uniform mat4 gl_ProjectionMatrixInverse;"
+ "uniform mat4 gl_ModelViewProjectionMatrixInverse;"
+
+ "uniform mat4 gl_ModelViewMatrixTranspose;"
+ "uniform mat4 gl_ProjectionMatrixTranspose;"
+ "uniform mat4 gl_ModelViewProjectionMatrixTranspose;"
+
+ "uniform mat4 gl_ModelViewMatrixInverseTranspose;"
+ "uniform mat4 gl_ProjectionMatrixInverseTranspose;"
+ "uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;"
+
+ //
+ // Normal scaling p. 39.
+ //
+ "uniform float gl_NormalScale;"
+
+ //
+ // Point Size, p. 66, 67.
+ //
+ "struct gl_PointParameters {"
+ "float size;"
+ "float sizeMin;"
+ "float sizeMax;"
+ "float fadeThresholdSize;"
+ "float distanceConstantAttenuation;"
+ "float distanceLinearAttenuation;"
+ "float distanceQuadraticAttenuation;"
+ "};"
+
+ "uniform gl_PointParameters gl_Point;"
+
+ //
+ // Material State p. 50, 55.
+ //
+ "struct gl_MaterialParameters {"
+ "vec4 emission;" // Ecm
+ "vec4 ambient;" // Acm
+ "vec4 diffuse;" // Dcm
+ "vec4 specular;" // Scm
+ "float shininess;" // Srm
+ "};"
+ "uniform gl_MaterialParameters gl_FrontMaterial;"
+ "uniform gl_MaterialParameters gl_BackMaterial;"
+
+ //
+ // Light State p 50, 53, 55.
+ //
+ "struct gl_LightSourceParameters {"
+ "vec4 ambient;" // Acli
+ "vec4 diffuse;" // Dcli
+ "vec4 specular;" // Scli
+ "vec4 position;" // Ppli
+ "vec4 halfVector;" // Derived: Hi
+ "vec3 spotDirection;" // Sdli
+ "float spotExponent;" // Srli
+ "float spotCutoff;" // Crli
+ // (range: [0.0,90.0], 180.0)
+ "float spotCosCutoff;" // Derived: cos(Crli)
+ // (range: [1.0,0.0],-1.0)
+ "float constantAttenuation;" // K0
+ "float linearAttenuation;" // K1
+ "float quadraticAttenuation;"// K2
+ "};"
+
+ "struct gl_LightModelParameters {"
+ "vec4 ambient;" // Acs
+ "};"
+
+ "uniform gl_LightModelParameters gl_LightModel;"
+
+ //
+ // Derived state from products of light and material.
+ //
+ "struct gl_LightModelProducts {"
+ "vec4 sceneColor;" // Derived. Ecm + Acm * Acs
+ "};"
+
+ "uniform gl_LightModelProducts gl_FrontLightModelProduct;"
+ "uniform gl_LightModelProducts gl_BackLightModelProduct;"
+
+ "struct gl_LightProducts {"
+ "vec4 ambient;" // Acm * Acli
+ "vec4 diffuse;" // Dcm * Dcli
+ "vec4 specular;" // Scm * Scli
+ "};"
+
+ //
+ // Fog p. 161
+ //
+ "struct gl_FogParameters {"
+ "vec4 color;"
+ "float density;"
+ "float start;"
+ "float end;"
+ "float scale;" // 1 / (gl_FogEnd - gl_FogStart)
+ "};"
+
+ "uniform gl_FogParameters gl_Fog;"
+
+ "\n");
+ }
+#endif
+
+ //============================================================================
+ //
+ // Define the interface to the compute shader.
+ //
+ //============================================================================
+
+ if ((profile != EEsProfile && version >= 420) ||
+ (profile == EEsProfile && version >= 310)) {
+ stageBuiltins[EShLangCompute].append(
+ "in highp uvec3 gl_NumWorkGroups;"
+ "const highp uvec3 gl_WorkGroupSize = uvec3(1,1,1);"
+
+ "in highp uvec3 gl_WorkGroupID;"
+ "in highp uvec3 gl_LocalInvocationID;"
+
+ "in highp uvec3 gl_GlobalInvocationID;"
+ "in highp uint gl_LocalInvocationIndex;"
+
+ "\n");
+ }
+
+ if ((profile != EEsProfile && version >= 140) ||
+ (profile == EEsProfile && version >= 310)) {
+ stageBuiltins[EShLangCompute].append(
+ "in highp int gl_DeviceIndex;" // GL_EXT_device_group
+ "\n");
+ }
+
+#ifndef GLSLANG_WEB
+ //============================================================================
+ //
+ // Define the interface to the mesh/task shader.
+ //
+ //============================================================================
+
+ if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
+ // per-vertex attributes
+ stageBuiltins[EShLangMeshNV].append(
+ "out gl_MeshPerVertexNV {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ "float gl_CullDistance[];"
+ "perviewNV vec4 gl_PositionPerViewNV[];"
+ "perviewNV float gl_ClipDistancePerViewNV[][];"
+ "perviewNV float gl_CullDistancePerViewNV[][];"
+ "} gl_MeshVerticesNV[];"
+ );
+
+ // per-primitive attributes
+ stageBuiltins[EShLangMeshNV].append(
+ "perprimitiveNV out gl_MeshPerPrimitiveNV {"
+ "int gl_PrimitiveID;"
+ "int gl_Layer;"
+ "int gl_ViewportIndex;"
+ "int gl_ViewportMask[];"
+ "perviewNV int gl_LayerPerViewNV[];"
+ "perviewNV int gl_ViewportMaskPerViewNV[][];"
+ "} gl_MeshPrimitivesNV[];"
+ );
+
+ stageBuiltins[EShLangMeshNV].append(
+ "out uint gl_PrimitiveCountNV;"
+ "out uint gl_PrimitiveIndicesNV[];"
+
+ "in uint gl_MeshViewCountNV;"
+ "in uint gl_MeshViewIndicesNV[4];"
+
+ "const highp uvec3 gl_WorkGroupSize = uvec3(1,1,1);"
+
+ "in highp uvec3 gl_WorkGroupID;"
+ "in highp uvec3 gl_LocalInvocationID;"
+
+ "in highp uvec3 gl_GlobalInvocationID;"
+ "in highp uint gl_LocalInvocationIndex;"
+
+ "\n");
+
+ stageBuiltins[EShLangTaskNV].append(
+ "out uint gl_TaskCountNV;"
+
+ "const highp uvec3 gl_WorkGroupSize = uvec3(1,1,1);"
+
+ "in highp uvec3 gl_WorkGroupID;"
+ "in highp uvec3 gl_LocalInvocationID;"
+
+ "in highp uvec3 gl_GlobalInvocationID;"
+ "in highp uint gl_LocalInvocationIndex;"
+
+ "in uint gl_MeshViewCountNV;"
+ "in uint gl_MeshViewIndicesNV[4];"
+
+ "\n");
+ }
+
+ if (profile != EEsProfile && version >= 450) {
+ stageBuiltins[EShLangMeshNV].append(
+ "in highp int gl_DeviceIndex;" // GL_EXT_device_group
+ "in int gl_DrawIDARB;" // GL_ARB_shader_draw_parameters
+ "\n");
+
+ stageBuiltins[EShLangTaskNV].append(
+ "in highp int gl_DeviceIndex;" // GL_EXT_device_group
+ "in int gl_DrawIDARB;" // GL_ARB_shader_draw_parameters
+ "\n");
+
+ if (version >= 460) {
+ stageBuiltins[EShLangMeshNV].append(
+ "in int gl_DrawID;"
+ "\n");
+
+ stageBuiltins[EShLangTaskNV].append(
+ "in int gl_DrawID;"
+ "\n");
+ }
+ }
+
+ //============================================================================
+ //
+ // Define the interface to the vertex shader.
+ //
+ //============================================================================
+
+ if (profile != EEsProfile) {
+ if (version < 130) {
+ stageBuiltins[EShLangVertex].append(
+ "attribute vec4 gl_Color;"
+ "attribute vec4 gl_SecondaryColor;"
+ "attribute vec3 gl_Normal;"
+ "attribute vec4 gl_Vertex;"
+ "attribute vec4 gl_MultiTexCoord0;"
+ "attribute vec4 gl_MultiTexCoord1;"
+ "attribute vec4 gl_MultiTexCoord2;"
+ "attribute vec4 gl_MultiTexCoord3;"
+ "attribute vec4 gl_MultiTexCoord4;"
+ "attribute vec4 gl_MultiTexCoord5;"
+ "attribute vec4 gl_MultiTexCoord6;"
+ "attribute vec4 gl_MultiTexCoord7;"
+ "attribute float gl_FogCoord;"
+ "\n");
+ } else if (IncludeLegacy(version, profile, spvVersion)) {
+ stageBuiltins[EShLangVertex].append(
+ "in vec4 gl_Color;"
+ "in vec4 gl_SecondaryColor;"
+ "in vec3 gl_Normal;"
+ "in vec4 gl_Vertex;"
+ "in vec4 gl_MultiTexCoord0;"
+ "in vec4 gl_MultiTexCoord1;"
+ "in vec4 gl_MultiTexCoord2;"
+ "in vec4 gl_MultiTexCoord3;"
+ "in vec4 gl_MultiTexCoord4;"
+ "in vec4 gl_MultiTexCoord5;"
+ "in vec4 gl_MultiTexCoord6;"
+ "in vec4 gl_MultiTexCoord7;"
+ "in float gl_FogCoord;"
+ "\n");
+ }
+
+ if (version < 150) {
+ if (version < 130) {
+ stageBuiltins[EShLangVertex].append(
+ " vec4 gl_ClipVertex;" // needs qualifier fixed later
+ "varying vec4 gl_FrontColor;"
+ "varying vec4 gl_BackColor;"
+ "varying vec4 gl_FrontSecondaryColor;"
+ "varying vec4 gl_BackSecondaryColor;"
+ "varying vec4 gl_TexCoord[];"
+ "varying float gl_FogFragCoord;"
+ "\n");
+ } else if (IncludeLegacy(version, profile, spvVersion)) {
+ stageBuiltins[EShLangVertex].append(
+ " vec4 gl_ClipVertex;" // needs qualifier fixed later
+ "out vec4 gl_FrontColor;"
+ "out vec4 gl_BackColor;"
+ "out vec4 gl_FrontSecondaryColor;"
+ "out vec4 gl_BackSecondaryColor;"
+ "out vec4 gl_TexCoord[];"
+ "out float gl_FogFragCoord;"
+ "\n");
+ }
+ stageBuiltins[EShLangVertex].append(
+ "vec4 gl_Position;" // needs qualifier fixed later
+ "float gl_PointSize;" // needs qualifier fixed later
+ );
+
+ if (version == 130 || version == 140)
+ stageBuiltins[EShLangVertex].append(
+ "out float gl_ClipDistance[];"
+ );
+ } else {
+ // version >= 150
+ stageBuiltins[EShLangVertex].append(
+ "out gl_PerVertex {"
+ "vec4 gl_Position;" // needs qualifier fixed later
+ "float gl_PointSize;" // needs qualifier fixed later
+ "float gl_ClipDistance[];"
+ );
+ if (IncludeLegacy(version, profile, spvVersion))
+ stageBuiltins[EShLangVertex].append(
+ "vec4 gl_ClipVertex;" // needs qualifier fixed later
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangVertex].append(
+ "float gl_CullDistance[];"
+ );
+ stageBuiltins[EShLangVertex].append(
+ "};"
+ "\n");
+ }
+ if (version >= 130 && spvVersion.vulkan == 0)
+ stageBuiltins[EShLangVertex].append(
+ "int gl_VertexID;" // needs qualifier fixed later
+ );
+ if (version >= 140 && spvVersion.vulkan == 0)
+ stageBuiltins[EShLangVertex].append(
+ "int gl_InstanceID;" // needs qualifier fixed later
+ );
+ if (spvVersion.vulkan > 0 && version >= 140)
+ stageBuiltins[EShLangVertex].append(
+ "in int gl_VertexIndex;"
+ "in int gl_InstanceIndex;"
+ );
+ if (version >= 440) {
+ stageBuiltins[EShLangVertex].append(
+ "in int gl_BaseVertexARB;"
+ "in int gl_BaseInstanceARB;"
+ "in int gl_DrawIDARB;"
+ );
+ }
+ if (version >= 410) {
+ stageBuiltins[EShLangVertex].append(
+ "out int gl_ViewportIndex;"
+ "out int gl_Layer;"
+ );
+ }
+ if (version >= 460) {
+ stageBuiltins[EShLangVertex].append(
+ "in int gl_BaseVertex;"
+ "in int gl_BaseInstance;"
+ "in int gl_DrawID;"
+ );
+ }
+
+ if (version >= 450)
+ stageBuiltins[EShLangVertex].append(
+ "out int gl_ViewportMask[];" // GL_NV_viewport_array2
+ "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering
+ "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
+ "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ "out int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ );
+ } else {
+ // ES profile
+ if (version == 100) {
+ stageBuiltins[EShLangVertex].append(
+ "highp vec4 gl_Position;" // needs qualifier fixed later
+ "mediump float gl_PointSize;" // needs qualifier fixed later
+ );
+ } else {
+ if (spvVersion.vulkan == 0)
+ stageBuiltins[EShLangVertex].append(
+ "in highp int gl_VertexID;" // needs qualifier fixed later
+ "in highp int gl_InstanceID;" // needs qualifier fixed later
+ );
+ if (spvVersion.vulkan > 0)
+#endif
+ stageBuiltins[EShLangVertex].append(
+ "in highp int gl_VertexIndex;"
+ "in highp int gl_InstanceIndex;"
+ );
+#ifndef GLSLANG_WEB
+ if (version < 310)
+#endif
+ stageBuiltins[EShLangVertex].append(
+ "highp vec4 gl_Position;" // needs qualifier fixed later
+ "highp float gl_PointSize;" // needs qualifier fixed later
+ );
+#ifndef GLSLANG_WEB
+ else
+ stageBuiltins[EShLangVertex].append(
+ "out gl_PerVertex {"
+ "highp vec4 gl_Position;" // needs qualifier fixed later
+ "highp float gl_PointSize;" // needs qualifier fixed later
+ "};"
+ );
+ }
+ }
+
+ if ((profile != EEsProfile && version >= 140) ||
+ (profile == EEsProfile && version >= 310)) {
+ stageBuiltins[EShLangVertex].append(
+ "in highp int gl_DeviceIndex;" // GL_EXT_device_group
+ "in highp int gl_ViewIndex;" // GL_EXT_multiview
+ "\n");
+ }
+
+ if (version >= 300 /* both ES and non-ES */) {
+ stageBuiltins[EShLangVertex].append(
+ "in highp uint gl_ViewID_OVR;" // GL_OVR_multiview, GL_OVR_multiview2
+ "\n");
+ }
+
+
+ //============================================================================
+ //
+ // Define the interface to the geometry shader.
+ //
+ //============================================================================
+
+ if (profile == ECoreProfile || profile == ECompatibilityProfile) {
+ stageBuiltins[EShLangGeometry].append(
+ "in gl_PerVertex {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ );
+ if (profile == ECompatibilityProfile)
+ stageBuiltins[EShLangGeometry].append(
+ "vec4 gl_ClipVertex;"
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangGeometry].append(
+ "float gl_CullDistance[];"
+ "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
+ "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ );
+ stageBuiltins[EShLangGeometry].append(
+ "} gl_in[];"
+
+ "in int gl_PrimitiveIDIn;"
+ "out gl_PerVertex {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ "\n");
+ if (profile == ECompatibilityProfile && version >= 400)
+ stageBuiltins[EShLangGeometry].append(
+ "vec4 gl_ClipVertex;"
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangGeometry].append(
+ "float gl_CullDistance[];"
+ );
+ stageBuiltins[EShLangGeometry].append(
+ "};"
+
+ "out int gl_PrimitiveID;"
+ "out int gl_Layer;");
+
+ if (version >= 150)
+ stageBuiltins[EShLangGeometry].append(
+ "out int gl_ViewportIndex;"
+ );
+
+ if (profile == ECompatibilityProfile && version < 400)
+ stageBuiltins[EShLangGeometry].append(
+ "out vec4 gl_ClipVertex;"
+ );
+
+ if (version >= 400)
+ stageBuiltins[EShLangGeometry].append(
+ "in int gl_InvocationID;"
+ );
+
+ if (version >= 450)
+ stageBuiltins[EShLangGeometry].append(
+ "out int gl_ViewportMask[];" // GL_NV_viewport_array2
+ "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering
+ "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
+ "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ "out int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ );
+
+ stageBuiltins[EShLangGeometry].append("\n");
+ } else if (profile == EEsProfile && version >= 310) {
+ stageBuiltins[EShLangGeometry].append(
+ "in gl_PerVertex {"
+ "highp vec4 gl_Position;"
+ "highp float gl_PointSize;"
+ "} gl_in[];"
+ "\n"
+ "in highp int gl_PrimitiveIDIn;"
+ "in highp int gl_InvocationID;"
+ "\n"
+ "out gl_PerVertex {"
+ "highp vec4 gl_Position;"
+ "highp float gl_PointSize;"
+ "};"
+ "\n"
+ "out highp int gl_PrimitiveID;"
+ "out highp int gl_Layer;"
+ "\n"
+ );
+ }
+
+ if ((profile != EEsProfile && version >= 140) ||
+ (profile == EEsProfile && version >= 310)) {
+ stageBuiltins[EShLangGeometry].append(
+ "in highp int gl_DeviceIndex;" // GL_EXT_device_group
+ "in highp int gl_ViewIndex;" // GL_EXT_multiview
+ "\n");
+ }
+
+ //============================================================================
+ //
+ // Define the interface to the tessellation control shader.
+ //
+ //============================================================================
+
+ if (profile != EEsProfile && version >= 150) {
+ // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below,
+ // as it depends on the resource sizing of gl_MaxPatchVertices.
+
+ stageBuiltins[EShLangTessControl].append(
+ "in int gl_PatchVerticesIn;"
+ "in int gl_PrimitiveID;"
+ "in int gl_InvocationID;"
+
+ "out gl_PerVertex {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ );
+ if (profile == ECompatibilityProfile)
+ stageBuiltins[EShLangTessControl].append(
+ "vec4 gl_ClipVertex;"
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangTessControl].append(
+ "float gl_CullDistance[];"
+ "int gl_ViewportMask[];" // GL_NV_viewport_array2
+ "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
+ "int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering
+ "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ "int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ );
+ stageBuiltins[EShLangTessControl].append(
+ "} gl_out[];"
+
+ "patch out float gl_TessLevelOuter[4];"
+ "patch out float gl_TessLevelInner[2];"
+ "\n");
+
+ if (version >= 410)
+ stageBuiltins[EShLangTessControl].append(
+ "out int gl_ViewportIndex;"
+ "out int gl_Layer;"
+ "\n");
+
+ } else {
+ // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below,
+ // as it depends on the resource sizing of gl_MaxPatchVertices.
+
+ stageBuiltins[EShLangTessControl].append(
+ "in highp int gl_PatchVerticesIn;"
+ "in highp int gl_PrimitiveID;"
+ "in highp int gl_InvocationID;"
+
+ "out gl_PerVertex {"
+ "highp vec4 gl_Position;"
+ "highp float gl_PointSize;"
+ );
+ stageBuiltins[EShLangTessControl].append(
+ "} gl_out[];"
+
+ "patch out highp float gl_TessLevelOuter[4];"
+ "patch out highp float gl_TessLevelInner[2];"
+ "patch out highp vec4 gl_BoundingBoxOES[2];"
+ "patch out highp vec4 gl_BoundingBoxEXT[2];"
+ "\n");
+ if (profile == EEsProfile && version >= 320) {
+ stageBuiltins[EShLangTessControl].append(
+ "patch out highp vec4 gl_BoundingBox[2];"
+ "\n"
+ );
+ }
+ }
+
+ if ((profile != EEsProfile && version >= 140) ||
+ (profile == EEsProfile && version >= 310)) {
+ stageBuiltins[EShLangTessControl].append(
+ "in highp int gl_DeviceIndex;" // GL_EXT_device_group
+ "in highp int gl_ViewIndex;" // GL_EXT_multiview
+ "\n");
+ }
+
+ //============================================================================
+ //
+ // Define the interface to the tessellation evaluation shader.
+ //
+ //============================================================================
+
+ if (profile != EEsProfile && version >= 150) {
+ // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below,
+ // as it depends on the resource sizing of gl_MaxPatchVertices.
+
+ stageBuiltins[EShLangTessEvaluation].append(
+ "in int gl_PatchVerticesIn;"
+ "in int gl_PrimitiveID;"
+ "in vec3 gl_TessCoord;"
+
+ "patch in float gl_TessLevelOuter[4];"
+ "patch in float gl_TessLevelInner[2];"
+
+ "out gl_PerVertex {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ );
+ if (version >= 400 && profile == ECompatibilityProfile)
+ stageBuiltins[EShLangTessEvaluation].append(
+ "vec4 gl_ClipVertex;"
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangTessEvaluation].append(
+ "float gl_CullDistance[];"
+ );
+ stageBuiltins[EShLangTessEvaluation].append(
+ "};"
+ "\n");
+
+ if (version >= 410)
+ stageBuiltins[EShLangTessEvaluation].append(
+ "out int gl_ViewportIndex;"
+ "out int gl_Layer;"
+ "\n");
+
+ if (version >= 450)
+ stageBuiltins[EShLangTessEvaluation].append(
+ "out int gl_ViewportMask[];" // GL_NV_viewport_array2
+ "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
+ "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering
+ "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ "out int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ );
+
+ } else if (profile == EEsProfile && version >= 310) {
+ // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below,
+ // as it depends on the resource sizing of gl_MaxPatchVertices.
+
+ stageBuiltins[EShLangTessEvaluation].append(
+ "in highp int gl_PatchVerticesIn;"
+ "in highp int gl_PrimitiveID;"
+ "in highp vec3 gl_TessCoord;"
+
+ "patch in highp float gl_TessLevelOuter[4];"
+ "patch in highp float gl_TessLevelInner[2];"
+
+ "out gl_PerVertex {"
+ "highp vec4 gl_Position;"
+ "highp float gl_PointSize;"
+ );
+ stageBuiltins[EShLangTessEvaluation].append(
+ "};"
+ "\n");
+ }
+
+ if ((profile != EEsProfile && version >= 140) ||
+ (profile == EEsProfile && version >= 310)) {
+ stageBuiltins[EShLangTessEvaluation].append(
+ "in highp int gl_DeviceIndex;" // GL_EXT_device_group
+ "in highp int gl_ViewIndex;" // GL_EXT_multiview
+ "\n");
+ }
+
+ //============================================================================
+ //
+ // Define the interface to the fragment shader.
+ //
+ //============================================================================
+
+ if (profile != EEsProfile) {
+
+ stageBuiltins[EShLangFragment].append(
+ "vec4 gl_FragCoord;" // needs qualifier fixed later
+ "bool gl_FrontFacing;" // needs qualifier fixed later
+ "float gl_FragDepth;" // needs qualifier fixed later
+ );
+ if (version >= 120)
+ stageBuiltins[EShLangFragment].append(
+ "vec2 gl_PointCoord;" // needs qualifier fixed later
+ );
+ if (version >= 140)
+ stageBuiltins[EShLangFragment].append(
+ "out int gl_FragStencilRefARB;"
+ );
+ if (IncludeLegacy(version, profile, spvVersion) || (! ForwardCompatibility && version < 420))
+ stageBuiltins[EShLangFragment].append(
+ "vec4 gl_FragColor;" // needs qualifier fixed later
+ );
+
+ if (version < 130) {
+ stageBuiltins[EShLangFragment].append(
+ "varying vec4 gl_Color;"
+ "varying vec4 gl_SecondaryColor;"
+ "varying vec4 gl_TexCoord[];"
+ "varying float gl_FogFragCoord;"
+ );
+ } else {
+ stageBuiltins[EShLangFragment].append(
+ "in float gl_ClipDistance[];"
+ );
+
+ if (IncludeLegacy(version, profile, spvVersion)) {
+ if (version < 150)
+ stageBuiltins[EShLangFragment].append(
+ "in float gl_FogFragCoord;"
+ "in vec4 gl_TexCoord[];"
+ "in vec4 gl_Color;"
+ "in vec4 gl_SecondaryColor;"
+ );
+ else
+ stageBuiltins[EShLangFragment].append(
+ "in gl_PerFragment {"
+ "in float gl_FogFragCoord;"
+ "in vec4 gl_TexCoord[];"
+ "in vec4 gl_Color;"
+ "in vec4 gl_SecondaryColor;"
+ "};"
+ );
+ }
+ }
+
+ if (version >= 150)
+ stageBuiltins[EShLangFragment].append(
+ "flat in int gl_PrimitiveID;"
+ );
+
+ if (version >= 130) { // ARB_sample_shading
+ stageBuiltins[EShLangFragment].append(
+ "flat in int gl_SampleID;"
+ " in vec2 gl_SamplePosition;"
+ " out int gl_SampleMask[];"
+ );
+
+ if (spvVersion.spv == 0) {
+ stageBuiltins[EShLangFragment].append(
+ "uniform int gl_NumSamples;"
+ );
+ }
+ }
+
+ if (version >= 400)
+ stageBuiltins[EShLangFragment].append(
+ "flat in int gl_SampleMaskIn[];"
+ );
+
+ if (version >= 430)
+ stageBuiltins[EShLangFragment].append(
+ "flat in int gl_Layer;"
+ "flat in int gl_ViewportIndex;"
+ );
+
+ if (version >= 450)
+ stageBuiltins[EShLangFragment].append(
+ "in float gl_CullDistance[];"
+ "bool gl_HelperInvocation;" // needs qualifier fixed later
+ );
+
+ if (version >= 450)
+ stageBuiltins[EShLangFragment].append( // GL_EXT_fragment_invocation_density
+ "flat in ivec2 gl_FragSizeEXT;"
+ "flat in int gl_FragInvocationCountEXT;"
+ );
+
+ if (version >= 450)
+ stageBuiltins[EShLangFragment].append(
+ "in vec2 gl_BaryCoordNoPerspAMD;"
+ "in vec2 gl_BaryCoordNoPerspCentroidAMD;"
+ "in vec2 gl_BaryCoordNoPerspSampleAMD;"
+ "in vec2 gl_BaryCoordSmoothAMD;"
+ "in vec2 gl_BaryCoordSmoothCentroidAMD;"
+ "in vec2 gl_BaryCoordSmoothSampleAMD;"
+ "in vec3 gl_BaryCoordPullModelAMD;"
+ );
+
+ if (version >= 430)
+ stageBuiltins[EShLangFragment].append(
+ "in bool gl_FragFullyCoveredNV;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangFragment].append(
+ "flat in ivec2 gl_FragmentSizeNV;" // GL_NV_shading_rate_image
+ "flat in int gl_InvocationsPerPixelNV;"
+ "in vec3 gl_BaryCoordNV;" // GL_NV_fragment_shader_barycentric
+ "in vec3 gl_BaryCoordNoPerspNV;"
+ );
+
+ } else {
+ // ES profile
+
+ if (version == 100) {
+ stageBuiltins[EShLangFragment].append(
+ "mediump vec4 gl_FragCoord;" // needs qualifier fixed later
+ " bool gl_FrontFacing;" // needs qualifier fixed later
+ "mediump vec4 gl_FragColor;" // needs qualifier fixed later
+ "mediump vec2 gl_PointCoord;" // needs qualifier fixed later
+ );
+ }
+#endif
+ if (version >= 300) {
+ stageBuiltins[EShLangFragment].append(
+ "highp vec4 gl_FragCoord;" // needs qualifier fixed later
+ " bool gl_FrontFacing;" // needs qualifier fixed later
+ "mediump vec2 gl_PointCoord;" // needs qualifier fixed later
+ "highp float gl_FragDepth;" // needs qualifier fixed later
+ );
+ }
+#ifndef GLSLANG_WEB
+ if (version >= 310) {
+ stageBuiltins[EShLangFragment].append(
+ "bool gl_HelperInvocation;" // needs qualifier fixed later
+ "flat in highp int gl_PrimitiveID;" // needs qualifier fixed later
+ "flat in highp int gl_Layer;" // needs qualifier fixed later
+ );
+
+ stageBuiltins[EShLangFragment].append( // GL_OES_sample_variables
+ "flat in lowp int gl_SampleID;"
+ " in mediump vec2 gl_SamplePosition;"
+ "flat in highp int gl_SampleMaskIn[];"
+ " out highp int gl_SampleMask[];"
+ );
+ if (spvVersion.spv == 0)
+ stageBuiltins[EShLangFragment].append( // GL_OES_sample_variables
+ "uniform lowp int gl_NumSamples;"
+ );
+ }
+ stageBuiltins[EShLangFragment].append(
+ "highp float gl_FragDepthEXT;" // GL_EXT_frag_depth
+ );
+
+ if (version >= 310)
+ stageBuiltins[EShLangFragment].append( // GL_EXT_fragment_invocation_density
+ "flat in ivec2 gl_FragSizeEXT;"
+ "flat in int gl_FragInvocationCountEXT;"
+ );
+ if (version >= 320)
+ stageBuiltins[EShLangFragment].append( // GL_NV_shading_rate_image
+ "flat in ivec2 gl_FragmentSizeNV;"
+ "flat in int gl_InvocationsPerPixelNV;"
+ );
+ if (version >= 320)
+ stageBuiltins[EShLangFragment].append(
+ "in vec3 gl_BaryCoordNV;"
+ "in vec3 gl_BaryCoordNoPerspNV;"
+ );
+ }
+#endif
+
+ stageBuiltins[EShLangFragment].append("\n");
+
+ if (version >= 130)
+ add2ndGenerationSamplingImaging(version, profile, spvVersion);
+
+#ifndef GLSLANG_WEB
+
+ // GL_ARB_shader_ballot
+ if (profile != EEsProfile && version >= 450) {
+ const char* ballotDecls =
+ "uniform uint gl_SubGroupSizeARB;"
+ "in uint gl_SubGroupInvocationARB;"
+ "in uint64_t gl_SubGroupEqMaskARB;"
+ "in uint64_t gl_SubGroupGeMaskARB;"
+ "in uint64_t gl_SubGroupGtMaskARB;"
+ "in uint64_t gl_SubGroupLeMaskARB;"
+ "in uint64_t gl_SubGroupLtMaskARB;"
+ "\n";
+ const char* fragmentBallotDecls =
+ "uniform uint gl_SubGroupSizeARB;"
+ "flat in uint gl_SubGroupInvocationARB;"
+ "flat in uint64_t gl_SubGroupEqMaskARB;"
+ "flat in uint64_t gl_SubGroupGeMaskARB;"
+ "flat in uint64_t gl_SubGroupGtMaskARB;"
+ "flat in uint64_t gl_SubGroupLeMaskARB;"
+ "flat in uint64_t gl_SubGroupLtMaskARB;"
+ "\n";
+ stageBuiltins[EShLangVertex] .append(ballotDecls);
+ stageBuiltins[EShLangTessControl] .append(ballotDecls);
+ stageBuiltins[EShLangTessEvaluation].append(ballotDecls);
+ stageBuiltins[EShLangGeometry] .append(ballotDecls);
+ stageBuiltins[EShLangCompute] .append(ballotDecls);
+ stageBuiltins[EShLangFragment] .append(fragmentBallotDecls);
+ stageBuiltins[EShLangMeshNV] .append(ballotDecls);
+ stageBuiltins[EShLangTaskNV] .append(ballotDecls);
+ }
+
+ if ((profile != EEsProfile && version >= 140) ||
+ (profile == EEsProfile && version >= 310)) {
+ stageBuiltins[EShLangFragment].append(
+ "flat in highp int gl_DeviceIndex;" // GL_EXT_device_group
+ "flat in highp int gl_ViewIndex;" // GL_EXT_multiview
+ "\n");
+ }
+
+ // GL_KHR_shader_subgroup
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 140)) {
+ const char* subgroupDecls =
+ "in mediump uint gl_SubgroupSize;"
+ "in mediump uint gl_SubgroupInvocationID;"
+ "in highp uvec4 gl_SubgroupEqMask;"
+ "in highp uvec4 gl_SubgroupGeMask;"
+ "in highp uvec4 gl_SubgroupGtMask;"
+ "in highp uvec4 gl_SubgroupLeMask;"
+ "in highp uvec4 gl_SubgroupLtMask;"
+ // GL_NV_shader_sm_builtins
+ "in highp uint gl_WarpsPerSMNV;"
+ "in highp uint gl_SMCountNV;"
+ "in highp uint gl_WarpIDNV;"
+ "in highp uint gl_SMIDNV;"
+ "\n";
+ const char* fragmentSubgroupDecls =
+ "flat in mediump uint gl_SubgroupSize;"
+ "flat in mediump uint gl_SubgroupInvocationID;"
+ "flat in highp uvec4 gl_SubgroupEqMask;"
+ "flat in highp uvec4 gl_SubgroupGeMask;"
+ "flat in highp uvec4 gl_SubgroupGtMask;"
+ "flat in highp uvec4 gl_SubgroupLeMask;"
+ "flat in highp uvec4 gl_SubgroupLtMask;"
+ // GL_NV_shader_sm_builtins
+ "flat in highp uint gl_WarpsPerSMNV;"
+ "flat in highp uint gl_SMCountNV;"
+ "flat in highp uint gl_WarpIDNV;"
+ "flat in highp uint gl_SMIDNV;"
+ "\n";
+ const char* computeSubgroupDecls =
+ "in highp uint gl_NumSubgroups;"
+ "in highp uint gl_SubgroupID;"
+ "\n";
+
+ stageBuiltins[EShLangVertex] .append(subgroupDecls);
+ stageBuiltins[EShLangTessControl] .append(subgroupDecls);
+ stageBuiltins[EShLangTessEvaluation].append(subgroupDecls);
+ stageBuiltins[EShLangGeometry] .append(subgroupDecls);
+ stageBuiltins[EShLangCompute] .append(subgroupDecls);
+ stageBuiltins[EShLangCompute] .append(computeSubgroupDecls);
+ stageBuiltins[EShLangFragment] .append(fragmentSubgroupDecls);
+ stageBuiltins[EShLangMeshNV] .append(subgroupDecls);
+ stageBuiltins[EShLangMeshNV] .append(computeSubgroupDecls);
+ stageBuiltins[EShLangTaskNV] .append(subgroupDecls);
+ stageBuiltins[EShLangTaskNV] .append(computeSubgroupDecls);
+ stageBuiltins[EShLangRayGenNV] .append(subgroupDecls);
+ stageBuiltins[EShLangIntersectNV] .append(subgroupDecls);
+ stageBuiltins[EShLangAnyHitNV] .append(subgroupDecls);
+ stageBuiltins[EShLangClosestHitNV] .append(subgroupDecls);
+ stageBuiltins[EShLangMissNV] .append(subgroupDecls);
+ stageBuiltins[EShLangCallableNV] .append(subgroupDecls);
+ }
+
+ // GL_NV_ray_tracing
+ if (profile != EEsProfile && version >= 460) {
+
+ const char *constRayFlags =
+ "const uint gl_RayFlagsNoneNV = 0U;"
+ "const uint gl_RayFlagsOpaqueNV = 1U;"
+ "const uint gl_RayFlagsNoOpaqueNV = 2U;"
+ "const uint gl_RayFlagsTerminateOnFirstHitNV = 4U;"
+ "const uint gl_RayFlagsSkipClosestHitShaderNV = 8U;"
+ "const uint gl_RayFlagsCullBackFacingTrianglesNV = 16U;"
+ "const uint gl_RayFlagsCullFrontFacingTrianglesNV = 32U;"
+ "const uint gl_RayFlagsCullOpaqueNV = 64U;"
+ "const uint gl_RayFlagsCullNoOpaqueNV = 128U;"
+ "\n";
+ const char *rayGenDecls =
+ "in uvec3 gl_LaunchIDNV;"
+ "in uvec3 gl_LaunchSizeNV;"
+ "\n";
+ const char *intersectDecls =
+ "in uvec3 gl_LaunchIDNV;"
+ "in uvec3 gl_LaunchSizeNV;"
+ "in int gl_PrimitiveID;"
+ "in int gl_InstanceID;"
+ "in int gl_InstanceCustomIndexNV;"
+ "in vec3 gl_WorldRayOriginNV;"
+ "in vec3 gl_WorldRayDirectionNV;"
+ "in vec3 gl_ObjectRayOriginNV;"
+ "in vec3 gl_ObjectRayDirectionNV;"
+ "in float gl_RayTminNV;"
+ "in float gl_RayTmaxNV;"
+ "in mat4x3 gl_ObjectToWorldNV;"
+ "in mat4x3 gl_WorldToObjectNV;"
+ "in uint gl_IncomingRayFlagsNV;"
+ "\n";
+ const char *hitDecls =
+ "in uvec3 gl_LaunchIDNV;"
+ "in uvec3 gl_LaunchSizeNV;"
+ "in int gl_PrimitiveID;"
+ "in int gl_InstanceID;"
+ "in int gl_InstanceCustomIndexNV;"
+ "in vec3 gl_WorldRayOriginNV;"
+ "in vec3 gl_WorldRayDirectionNV;"
+ "in vec3 gl_ObjectRayOriginNV;"
+ "in vec3 gl_ObjectRayDirectionNV;"
+ "in float gl_RayTminNV;"
+ "in float gl_RayTmaxNV;"
+ "in float gl_HitTNV;"
+ "in uint gl_HitKindNV;"
+ "in mat4x3 gl_ObjectToWorldNV;"
+ "in mat4x3 gl_WorldToObjectNV;"
+ "in uint gl_IncomingRayFlagsNV;"
+ "\n";
+ const char *missDecls =
+ "in uvec3 gl_LaunchIDNV;"
+ "in uvec3 gl_LaunchSizeNV;"
+ "in vec3 gl_WorldRayOriginNV;"
+ "in vec3 gl_WorldRayDirectionNV;"
+ "in vec3 gl_ObjectRayOriginNV;"
+ "in vec3 gl_ObjectRayDirectionNV;"
+ "in float gl_RayTminNV;"
+ "in float gl_RayTmaxNV;"
+ "in uint gl_IncomingRayFlagsNV;"
+ "\n";
+
+ const char *callableDecls =
+ "in uvec3 gl_LaunchIDNV;"
+ "in uvec3 gl_LaunchSizeNV;"
+ "\n";
+
+ stageBuiltins[EShLangRayGenNV].append(rayGenDecls);
+ stageBuiltins[EShLangRayGenNV].append(constRayFlags);
+
+ stageBuiltins[EShLangIntersectNV].append(intersectDecls);
+ stageBuiltins[EShLangIntersectNV].append(constRayFlags);
+
+ stageBuiltins[EShLangAnyHitNV].append(hitDecls);
+ stageBuiltins[EShLangAnyHitNV].append(constRayFlags);
+
+ stageBuiltins[EShLangClosestHitNV].append(hitDecls);
+ stageBuiltins[EShLangClosestHitNV].append(constRayFlags);
+
+ stageBuiltins[EShLangMissNV].append(missDecls);
+ stageBuiltins[EShLangMissNV].append(constRayFlags);
+
+ stageBuiltins[EShLangCallableNV].append(callableDecls);
+ stageBuiltins[EShLangCallableNV].append(constRayFlags);
+
+ }
+ if ((profile != EEsProfile && version >= 140)) {
+ const char *deviceIndex =
+ "in highp int gl_DeviceIndex;" // GL_EXT_device_group
+ "\n";
+
+ stageBuiltins[EShLangRayGenNV].append(deviceIndex);
+ stageBuiltins[EShLangIntersectNV].append(deviceIndex);
+ stageBuiltins[EShLangAnyHitNV].append(deviceIndex);
+ stageBuiltins[EShLangClosestHitNV].append(deviceIndex);
+ stageBuiltins[EShLangMissNV].append(deviceIndex);
+ }
+
+ if (version >= 300 /* both ES and non-ES */) {
+ stageBuiltins[EShLangFragment].append(
+ "flat in highp uint gl_ViewID_OVR;" // GL_OVR_multiview, GL_OVR_multiview2
+ "\n");
+ }
+
+ if ((profile != EEsProfile && version >= 420) ||
+ (profile == EEsProfile && version >= 310)) {
+ commonBuiltins.append("const int gl_ScopeDevice = 1;\n");
+ commonBuiltins.append("const int gl_ScopeWorkgroup = 2;\n");
+ commonBuiltins.append("const int gl_ScopeSubgroup = 3;\n");
+ commonBuiltins.append("const int gl_ScopeInvocation = 4;\n");
+ commonBuiltins.append("const int gl_ScopeQueueFamily = 5;\n");
+
+ commonBuiltins.append("const int gl_SemanticsRelaxed = 0x0;\n");
+ commonBuiltins.append("const int gl_SemanticsAcquire = 0x2;\n");
+ commonBuiltins.append("const int gl_SemanticsRelease = 0x4;\n");
+ commonBuiltins.append("const int gl_SemanticsAcquireRelease = 0x8;\n");
+ commonBuiltins.append("const int gl_SemanticsMakeAvailable = 0x2000;\n");
+ commonBuiltins.append("const int gl_SemanticsMakeVisible = 0x4000;\n");
+ commonBuiltins.append("const int gl_SemanticsVolatile = 0x8000;\n");
+
+ commonBuiltins.append("const int gl_StorageSemanticsNone = 0x0;\n");
+ commonBuiltins.append("const int gl_StorageSemanticsBuffer = 0x40;\n");
+ commonBuiltins.append("const int gl_StorageSemanticsShared = 0x100;\n");
+ commonBuiltins.append("const int gl_StorageSemanticsImage = 0x800;\n");
+ commonBuiltins.append("const int gl_StorageSemanticsOutput = 0x1000;\n");
+ }
+#endif
+
+ // printf("%s\n", commonBuiltins.c_str());
+ // printf("%s\n", stageBuiltins[EShLangFragment].c_str());
+}
+
+//
+// Helper function for initialize(), to add the second set of names for texturing,
+// when adding context-independent built-in functions.
+//
+void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion)
+{
+ //
+ // In this function proper, enumerate the types, then calls the next set of functions
+ // to enumerate all the uses for that type.
+ //
+
+ // enumerate all the types
+#ifdef GLSLANG_WEB
+ const TBasicType bTypes[] = { EbtFloat, EbtInt, EbtUint };
+ bool skipBuffer = true;
+ bool skipCubeArrayed = true;
+ const int image = 0;
+#else
+ const TBasicType bTypes[] = { EbtFloat, EbtInt, EbtUint, EbtFloat16 };
+ bool skipBuffer = (profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 140);
+ bool skipCubeArrayed = (profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 130);
+ for (int image = 0; image <= 1; ++image) // loop over "bool" image vs sampler
+#endif
+ {
+ for (int shadow = 0; shadow <= 1; ++shadow) { // loop over "bool" shadow or not
+#ifdef GLSLANG_WEB
+ const int ms = 0;
+#else
+ for (int ms = 0; ms <= 1; ++ms) // loop over "bool" multisample or not
+#endif
+ {
+ if ((ms || image) && shadow)
+ continue;
+ if (ms && profile != EEsProfile && version < 150)
+ continue;
+ if (ms && image && profile == EEsProfile)
+ continue;
+ if (ms && profile == EEsProfile && version < 310)
+ continue;
+
+ for (int arrayed = 0; arrayed <= 1; ++arrayed) { // loop over "bool" arrayed or not
+#ifdef GLSLANG_WEB
+ for (int dim = Esd2D; dim <= EsdCube; ++dim) { // 2D, 3D, and Cube
+#else
+ for (int dim = Esd1D; dim < EsdNumDims; ++dim) { // 1D, ..., buffer, subpass
+ if (dim == EsdSubpass && spvVersion.vulkan == 0)
+ continue;
+ if (dim == EsdSubpass && (image || shadow || arrayed))
+ continue;
+ if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile)
+ continue;
+ if (dim == EsdSubpass && spvVersion.vulkan == 0)
+ continue;
+ if (dim == EsdSubpass && (image || shadow || arrayed))
+ continue;
+ if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile)
+ continue;
+ if (dim != Esd2D && dim != EsdSubpass && ms)
+ continue;
+ if (dim == EsdBuffer && skipBuffer)
+ continue;
+ if (dim == EsdBuffer && (shadow || arrayed || ms))
+ continue;
+ if (ms && arrayed && profile == EEsProfile && version < 310)
+ continue;
+#endif
+ if (dim == Esd3D && shadow)
+ continue;
+ if (dim == EsdCube && arrayed && skipCubeArrayed)
+ continue;
+ if ((dim == Esd3D || dim == EsdRect) && arrayed)
+ continue;
+
+ // Loop over the bTypes
+ for (size_t bType = 0; bType < sizeof(bTypes)/sizeof(TBasicType); ++bType) {
+#ifndef GLSLANG_WEB
+ if (bTypes[bType] == EbtFloat16 && (profile == EEsProfile || version < 450))
+ continue;
+ if (dim == EsdRect && version < 140 && bType > 0)
+ continue;
+#endif
+ if (shadow && (bTypes[bType] == EbtInt || bTypes[bType] == EbtUint))
+ continue;
+
+ //
+ // Now, make all the function prototypes for the type we just built...
+ //
+ TSampler sampler;
+#ifndef GLSLANG_WEB
+ if (dim == EsdSubpass) {
+ sampler.setSubpass(bTypes[bType], ms ? true : false);
+ } else
+#endif
+ if (image) {
+ sampler.setImage(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false,
+ shadow ? true : false,
+ ms ? true : false);
+ } else {
+ sampler.set(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false,
+ shadow ? true : false,
+ ms ? true : false);
+ }
+
+ TString typeName = sampler.getString();
+
+#ifndef GLSLANG_WEB
+ if (dim == EsdSubpass) {
+ addSubpassSampling(sampler, typeName, version, profile);
+ continue;
+ }
+#endif
+
+ addQueryFunctions(sampler, typeName, version, profile);
+
+ if (image)
+ addImageFunctions(sampler, typeName, version, profile);
+ else {
+ addSamplingFunctions(sampler, typeName, version, profile);
+#ifndef GLSLANG_WEB
+ addGatherFunctions(sampler, typeName, version, profile);
+ if (spvVersion.vulkan > 0 && sampler.isCombined() && !sampler.shadow) {
+ // Base Vulkan allows texelFetch() for
+ // textureBuffer (i.e. without sampler).
+ //
+ // GL_EXT_samplerless_texture_functions
+ // allows texelFetch() and query functions
+ // (other than textureQueryLod()) for all
+ // texture types.
+ sampler.setTexture(sampler.type, sampler.dim, sampler.arrayed, sampler.shadow,
+ sampler.ms);
+ TString textureTypeName = sampler.getString();
+ addSamplingFunctions(sampler, textureTypeName, version, profile);
+ addQueryFunctions(sampler, textureTypeName, version, profile);
+ }
+#endif
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // sparseTexelsResidentARB()
+ //
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append("bool sparseTexelsResidentARB(int code);\n");
+ }
+}
+
+//
+// Helper function for add2ndGenerationSamplingImaging(),
+// when adding context-independent built-in functions.
+//
+// Add all the query functions for the given type.
+//
+void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
+{
+ //
+ // textureSize() and imageSize()
+ //
+
+ int sizeDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0) - (sampler.dim == EsdCube ? 1 : 0);
+
+#ifdef GLSLANG_WEB
+ commonBuiltins.append("highp ");
+ commonBuiltins.append("ivec");
+ commonBuiltins.append(postfixes[sizeDims]);
+ commonBuiltins.append(" textureSize(");
+ commonBuiltins.append(typeName);
+ commonBuiltins.append(",int);\n");
+ return;
+#endif
+
+ if (sampler.isImage() && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 430)))
+ return;
+
+ if (profile == EEsProfile)
+ commonBuiltins.append("highp ");
+ if (sizeDims == 1)
+ commonBuiltins.append("int");
+ else {
+ commonBuiltins.append("ivec");
+ commonBuiltins.append(postfixes[sizeDims]);
+ }
+ if (sampler.isImage())
+ commonBuiltins.append(" imageSize(readonly writeonly volatile coherent ");
+ else
+ commonBuiltins.append(" textureSize(");
+ commonBuiltins.append(typeName);
+ if (! sampler.isImage() && ! sampler.isRect() && ! sampler.isBuffer() && ! sampler.isMultiSample())
+ commonBuiltins.append(",int);\n");
+ else
+ commonBuiltins.append(");\n");
+
+ //
+ // textureSamples() and imageSamples()
+ //
+
+ // GL_ARB_shader_texture_image_samples
+ // TODO: spec issue? there are no memory qualifiers; how to query a writeonly/readonly image, etc?
+ if (profile != EEsProfile && version >= 430 && sampler.isMultiSample()) {
+ commonBuiltins.append("int ");
+ if (sampler.isImage())
+ commonBuiltins.append("imageSamples(readonly writeonly volatile coherent ");
+ else
+ commonBuiltins.append("textureSamples(");
+ commonBuiltins.append(typeName);
+ commonBuiltins.append(");\n");
+ }
+
+ //
+ // textureQueryLod(), fragment stage only
+ //
+
+ if (profile != EEsProfile && version >= 400 && sampler.isCombined() && sampler.dim != EsdRect &&
+ ! sampler.isMultiSample() && ! sampler.isBuffer()) {
+ for (int f16TexAddr = 0; f16TexAddr < 2; ++f16TexAddr) {
+ if (f16TexAddr && sampler.type != EbtFloat16)
+ continue;
+ stageBuiltins[EShLangFragment].append("vec2 textureQueryLod(");
+ stageBuiltins[EShLangFragment].append(typeName);
+ if (dimMap[sampler.dim] == 1)
+ if (f16TexAddr)
+ stageBuiltins[EShLangFragment].append(", float16_t");
+ else
+ stageBuiltins[EShLangFragment].append(", float");
+ else {
+ if (f16TexAddr)
+ stageBuiltins[EShLangFragment].append(", f16vec");
+ else
+ stageBuiltins[EShLangFragment].append(", vec");
+ stageBuiltins[EShLangFragment].append(postfixes[dimMap[sampler.dim]]);
+ }
+ stageBuiltins[EShLangFragment].append(");\n");
+ }
+
+ stageBuiltins[EShLangCompute].append("vec2 textureQueryLod(");
+ stageBuiltins[EShLangCompute].append(typeName);
+ if (dimMap[sampler.dim] == 1)
+ stageBuiltins[EShLangCompute].append(", float");
+ else {
+ stageBuiltins[EShLangCompute].append(", vec");
+ stageBuiltins[EShLangCompute].append(postfixes[dimMap[sampler.dim]]);
+ }
+ stageBuiltins[EShLangCompute].append(");\n");
+ }
+
+ //
+ // textureQueryLevels()
+ //
+
+ if (profile != EEsProfile && version >= 430 && ! sampler.isImage() && sampler.dim != EsdRect &&
+ ! sampler.isMultiSample() && ! sampler.isBuffer()) {
+ commonBuiltins.append("int textureQueryLevels(");
+ commonBuiltins.append(typeName);
+ commonBuiltins.append(");\n");
+ }
+}
+
+//
+// Helper function for add2ndGenerationSamplingImaging(),
+// when adding context-independent built-in functions.
+//
+// Add all the image access functions for the given type.
+//
+void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
+{
+ int dims = dimMap[sampler.dim];
+ // most things with an array add a dimension, except for cubemaps
+ if (sampler.arrayed && sampler.dim != EsdCube)
+ ++dims;
+
+ TString imageParams = typeName;
+ if (dims == 1)
+ imageParams.append(", int");
+ else {
+ imageParams.append(", ivec");
+ imageParams.append(postfixes[dims]);
+ }
+ if (sampler.isMultiSample())
+ imageParams.append(", int");
+
+ if (profile == EEsProfile)
+ commonBuiltins.append("highp ");
+ commonBuiltins.append(prefixes[sampler.type]);
+ commonBuiltins.append("vec4 imageLoad(readonly volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(");\n");
+
+ commonBuiltins.append("void imageStore(writeonly volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", ");
+ commonBuiltins.append(prefixes[sampler.type]);
+ commonBuiltins.append("vec4);\n");
+
+ if (! sampler.is1D() && ! sampler.isBuffer() && profile != EEsProfile && version >= 450) {
+ commonBuiltins.append("int sparseImageLoadARB(readonly volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", out ");
+ commonBuiltins.append(prefixes[sampler.type]);
+ commonBuiltins.append("vec4");
+ commonBuiltins.append(");\n");
+ }
+
+ if ( profile != EEsProfile ||
+ (profile == EEsProfile && version >= 310)) {
+ if (sampler.type == EbtInt || sampler.type == EbtUint) {
+ const char* dataType = sampler.type == EbtInt ? "highp int" : "highp uint";
+
+ const int numBuiltins = 7;
+
+ static const char* atomicFunc[numBuiltins] = {
+ " imageAtomicAdd(volatile coherent ",
+ " imageAtomicMin(volatile coherent ",
+ " imageAtomicMax(volatile coherent ",
+ " imageAtomicAnd(volatile coherent ",
+ " imageAtomicOr(volatile coherent ",
+ " imageAtomicXor(volatile coherent ",
+ " imageAtomicExchange(volatile coherent "
+ };
+
+ // Loop twice to add prototypes with/without scope/semantics
+ for (int j = 0; j < 2; ++j) {
+ for (size_t i = 0; i < numBuiltins; ++i) {
+ commonBuiltins.append(dataType);
+ commonBuiltins.append(atomicFunc[i]);
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", ");
+ commonBuiltins.append(dataType);
+ if (j == 1) {
+ commonBuiltins.append(", int, int, int");
+ }
+ commonBuiltins.append(");\n");
+ }
+
+ commonBuiltins.append(dataType);
+ commonBuiltins.append(" imageAtomicCompSwap(volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", ");
+ commonBuiltins.append(dataType);
+ commonBuiltins.append(", ");
+ commonBuiltins.append(dataType);
+ if (j == 1) {
+ commonBuiltins.append(", int, int, int, int, int");
+ }
+ commonBuiltins.append(");\n");
+ }
+
+ commonBuiltins.append(dataType);
+ commonBuiltins.append(" imageAtomicLoad(volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", int, int, int);\n");
+
+ commonBuiltins.append("void imageAtomicStore(volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", ");
+ commonBuiltins.append(dataType);
+ commonBuiltins.append(", int, int, int);\n");
+
+ } else {
+ // not int or uint
+ // GL_ARB_ES3_1_compatibility
+ // TODO: spec issue: are there restrictions on the kind of layout() that can be used? what about dropping memory qualifiers?
+ if ((profile != EEsProfile && version >= 450) ||
+ (profile == EEsProfile && version >= 310)) {
+ commonBuiltins.append("float imageAtomicExchange(volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", float);\n");
+ }
+ }
+ }
+
+ if (sampler.dim == EsdRect || sampler.dim == EsdBuffer || sampler.shadow || sampler.isMultiSample())
+ return;
+
+ if (profile == EEsProfile || version < 450)
+ return;
+
+ TString imageLodParams = typeName;
+ if (dims == 1)
+ imageLodParams.append(", int");
+ else {
+ imageLodParams.append(", ivec");
+ imageLodParams.append(postfixes[dims]);
+ }
+ imageLodParams.append(", int");
+
+ commonBuiltins.append(prefixes[sampler.type]);
+ commonBuiltins.append("vec4 imageLoadLodAMD(readonly volatile coherent ");
+ commonBuiltins.append(imageLodParams);
+ commonBuiltins.append(");\n");
+
+ commonBuiltins.append("void imageStoreLodAMD(writeonly volatile coherent ");
+ commonBuiltins.append(imageLodParams);
+ commonBuiltins.append(", ");
+ commonBuiltins.append(prefixes[sampler.type]);
+ commonBuiltins.append("vec4);\n");
+
+ if (! sampler.is1D()) {
+ commonBuiltins.append("int sparseImageLoadLodAMD(readonly volatile coherent ");
+ commonBuiltins.append(imageLodParams);
+ commonBuiltins.append(", out ");
+ commonBuiltins.append(prefixes[sampler.type]);
+ commonBuiltins.append("vec4");
+ commonBuiltins.append(");\n");
+ }
+}
+
+//
+// Helper function for initialize(),
+// when adding context-independent built-in functions.
+//
+// Add all the subpass access functions for the given type.
+//
+void TBuiltIns::addSubpassSampling(TSampler sampler, const TString& typeName, int /*version*/, EProfile /*profile*/)
+{
+ stageBuiltins[EShLangFragment].append(prefixes[sampler.type]);
+ stageBuiltins[EShLangFragment].append("vec4 subpassLoad");
+ stageBuiltins[EShLangFragment].append("(");
+ stageBuiltins[EShLangFragment].append(typeName.c_str());
+ if (sampler.isMultiSample())
+ stageBuiltins[EShLangFragment].append(", int");
+ stageBuiltins[EShLangFragment].append(");\n");
+}
+
+//
+// Helper function for add2ndGenerationSamplingImaging(),
+// when adding context-independent built-in functions.
+//
+// Add all the texture lookup functions for the given type.
+//
+void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
+{
+#ifdef GLSLANG_WEB
+ profile = EEsProfile;
+ version = 310;
+#endif
+
+ //
+ // texturing
+ //
+ for (int proj = 0; proj <= 1; ++proj) { // loop over "bool" projective or not
+
+ if (proj && (sampler.dim == EsdCube || sampler.isBuffer() || sampler.arrayed || sampler.isMultiSample()
+ || !sampler.isCombined()))
+ continue;
+
+ for (int lod = 0; lod <= 1; ++lod) {
+
+ if (lod && (sampler.isBuffer() || sampler.isRect() || sampler.isMultiSample() || !sampler.isCombined()))
+ continue;
+ if (lod && sampler.dim == Esd2D && sampler.arrayed && sampler.shadow)
+ continue;
+ if (lod && sampler.dim == EsdCube && sampler.shadow)
+ continue;
+
+ for (int bias = 0; bias <= 1; ++bias) {
+
+ if (bias && (lod || sampler.isMultiSample() || !sampler.isCombined()))
+ continue;
+ if (bias && (sampler.dim == Esd2D || sampler.dim == EsdCube) && sampler.shadow && sampler.arrayed)
+ continue;
+ if (bias && (sampler.isRect() || sampler.isBuffer()))
+ continue;
+
+ for (int offset = 0; offset <= 1; ++offset) { // loop over "bool" offset or not
+
+ if (proj + offset + bias + lod > 3)
+ continue;
+ if (offset && (sampler.dim == EsdCube || sampler.isBuffer() || sampler.isMultiSample()))
+ continue;
+
+ for (int fetch = 0; fetch <= 1; ++fetch) { // loop over "bool" fetch or not
+
+ if (proj + offset + fetch + bias + lod > 3)
+ continue;
+ if (fetch && (lod || bias))
+ continue;
+ if (fetch && (sampler.shadow || sampler.dim == EsdCube))
+ continue;
+ if (fetch == 0 && (sampler.isMultiSample() || sampler.isBuffer()
+ || !sampler.isCombined()))
+ continue;
+
+ for (int grad = 0; grad <= 1; ++grad) { // loop over "bool" grad or not
+
+ if (grad && (lod || bias || sampler.isMultiSample() || !sampler.isCombined()))
+ continue;
+ if (grad && sampler.isBuffer())
+ continue;
+ if (proj + offset + fetch + grad + bias + lod > 3)
+ continue;
+
+ for (int extraProj = 0; extraProj <= 1; ++extraProj) {
+ bool compare = false;
+ int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0);
+ // skip dummy unused second component for 1D non-array shadows
+ if (sampler.shadow && totalDims < 2)
+ totalDims = 2;
+ totalDims += (sampler.shadow ? 1 : 0) + proj;
+ if (totalDims > 4 && sampler.shadow) {
+ compare = true;
+ totalDims = 4;
+ }
+ assert(totalDims <= 4);
+
+ if (extraProj && ! proj)
+ continue;
+ if (extraProj && (sampler.dim == Esd3D || sampler.shadow || !sampler.isCombined()))
+ continue;
+
+ // loop over 16-bit floating-point texel addressing
+#ifdef GLSLANG_WEB
+ const int f16TexAddr = 0;
+#else
+ for (int f16TexAddr = 0; f16TexAddr <= 1; ++f16TexAddr)
+#endif
+ {
+ if (f16TexAddr && sampler.type != EbtFloat16)
+ continue;
+ if (f16TexAddr && sampler.shadow && ! compare) {
+ compare = true; // compare argument is always present
+ totalDims--;
+ }
+ // loop over "bool" lod clamp
+#ifdef GLSLANG_WEB
+ const int lodClamp = 0;
+#else
+ for (int lodClamp = 0; lodClamp <= 1 ;++lodClamp)
+#endif
+ {
+ if (lodClamp && (profile == EEsProfile || version < 450))
+ continue;
+ if (lodClamp && (proj || lod || fetch))
+ continue;
+
+ // loop over "bool" sparse or not
+#ifdef GLSLANG_WEB
+ const int sparse = 0;
+#else
+ for (int sparse = 0; sparse <= 1; ++sparse)
+#endif
+ {
+ if (sparse && (profile == EEsProfile || version < 450))
+ continue;
+ // Sparse sampling is not for 1D/1D array texture, buffer texture, and
+ // projective texture
+ if (sparse && (sampler.is1D() || sampler.isBuffer() || proj))
+ continue;
+
+ TString s;
+
+ // return type
+ if (sparse)
+ s.append("int ");
+ else {
+ if (sampler.shadow)
+ if (sampler.type == EbtFloat16)
+ s.append("float16_t ");
+ else
+ s.append("float ");
+ else {
+ s.append(prefixes[sampler.type]);
+ s.append("vec4 ");
+ }
+ }
+
+ // name
+ if (sparse) {
+ if (fetch)
+ s.append("sparseTexel");
+ else
+ s.append("sparseTexture");
+ }
+ else {
+ if (fetch)
+ s.append("texel");
+ else
+ s.append("texture");
+ }
+ if (proj)
+ s.append("Proj");
+ if (lod)
+ s.append("Lod");
+ if (grad)
+ s.append("Grad");
+ if (fetch)
+ s.append("Fetch");
+ if (offset)
+ s.append("Offset");
+ if (lodClamp)
+ s.append("Clamp");
+ if (lodClamp || sparse)
+ s.append("ARB");
+ s.append("(");
+
+ // sampler type
+ s.append(typeName);
+ // P coordinate
+ if (extraProj) {
+ if (f16TexAddr)
+ s.append(",f16vec4");
+ else
+ s.append(",vec4");
+ } else {
+ s.append(",");
+ TBasicType t = fetch ? EbtInt : (f16TexAddr ? EbtFloat16 : EbtFloat);
+ if (totalDims == 1)
+ s.append(TType::getBasicString(t));
+ else {
+ s.append(prefixes[t]);
+ s.append("vec");
+ s.append(postfixes[totalDims]);
+ }
+ }
+ // non-optional compare
+ if (compare)
+ s.append(",float");
+
+ // non-optional lod argument (lod that's not driven by lod loop) or sample
+ if ((fetch && !sampler.isBuffer() &&
+ !sampler.isRect() && !sampler.isMultiSample())
+ || (sampler.isMultiSample() && fetch))
+ s.append(",int");
+ // non-optional lod
+ if (lod) {
+ if (f16TexAddr)
+ s.append(",float16_t");
+ else
+ s.append(",float");
+ }
+
+ // gradient arguments
+ if (grad) {
+ if (dimMap[sampler.dim] == 1) {
+ if (f16TexAddr)
+ s.append(",float16_t,float16_t");
+ else
+ s.append(",float,float");
+ } else {
+ if (f16TexAddr)
+ s.append(",f16vec");
+ else
+ s.append(",vec");
+ s.append(postfixes[dimMap[sampler.dim]]);
+ if (f16TexAddr)
+ s.append(",f16vec");
+ else
+ s.append(",vec");
+ s.append(postfixes[dimMap[sampler.dim]]);
+ }
+ }
+ // offset
+ if (offset) {
+ if (dimMap[sampler.dim] == 1)
+ s.append(",int");
+ else {
+ s.append(",ivec");
+ s.append(postfixes[dimMap[sampler.dim]]);
+ }
+ }
+
+ // lod clamp
+ if (lodClamp) {
+ if (f16TexAddr)
+ s.append(",float16_t");
+ else
+ s.append(",float");
+ }
+ // texel out (for sparse texture)
+ if (sparse) {
+ s.append(",out ");
+ if (sampler.shadow)
+ if (sampler.type == EbtFloat16)
+ s.append("float16_t");
+ else
+ s.append("float");
+ else {
+ s.append(prefixes[sampler.type]);
+ s.append("vec4");
+ }
+ }
+ // optional bias
+ if (bias) {
+ if (f16TexAddr)
+ s.append(",float16_t");
+ else
+ s.append(",float");
+ }
+ s.append(");\n");
+
+ // Add to the per-language set of built-ins
+ if (bias || lodClamp) {
+ stageBuiltins[EShLangFragment].append(s);
+ stageBuiltins[EShLangCompute].append(s);
+ } else
+ commonBuiltins.append(s);
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+//
+// Helper function for add2ndGenerationSamplingImaging(),
+// when adding context-independent built-in functions.
+//
+// Add all the texture gather functions for the given type.
+//
+void TBuiltIns::addGatherFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
+{
+#ifdef GLSLANG_WEB
+ profile = EEsProfile;
+ version = 310;
+#endif
+
+ switch (sampler.dim) {
+ case Esd2D:
+ case EsdRect:
+ case EsdCube:
+ break;
+ default:
+ return;
+ }
+
+ if (sampler.isMultiSample())
+ return;
+
+ if (version < 140 && sampler.dim == EsdRect && sampler.type != EbtFloat)
+ return;
+
+ for (int f16TexAddr = 0; f16TexAddr <= 1; ++f16TexAddr) { // loop over 16-bit floating-point texel addressing
+
+ if (f16TexAddr && sampler.type != EbtFloat16)
+ continue;
+ for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name: none, Offset, and Offsets
+
+ for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument
+
+ if (comp > 0 && sampler.shadow)
+ continue;
+
+ if (offset > 0 && sampler.dim == EsdCube)
+ continue;
+
+ for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not
+ if (sparse && (profile == EEsProfile || version < 450))
+ continue;
+
+ TString s;
+
+ // return type
+ if (sparse)
+ s.append("int ");
+ else {
+ s.append(prefixes[sampler.type]);
+ s.append("vec4 ");
+ }
+
+ // name
+ if (sparse)
+ s.append("sparseTextureGather");
+ else
+ s.append("textureGather");
+ switch (offset) {
+ case 1:
+ s.append("Offset");
+ break;
+ case 2:
+ s.append("Offsets");
+ break;
+ default:
+ break;
+ }
+ if (sparse)
+ s.append("ARB");
+ s.append("(");
+
+ // sampler type argument
+ s.append(typeName);
+
+ // P coordinate argument
+ if (f16TexAddr)
+ s.append(",f16vec");
+ else
+ s.append(",vec");
+ int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0);
+ s.append(postfixes[totalDims]);
+
+ // refZ argument
+ if (sampler.shadow)
+ s.append(",float");
+
+ // offset argument
+ if (offset > 0) {
+ s.append(",ivec2");
+ if (offset == 2)
+ s.append("[4]");
+ }
+
+ // texel out (for sparse texture)
+ if (sparse) {
+ s.append(",out ");
+ s.append(prefixes[sampler.type]);
+ s.append("vec4 ");
+ }
+
+ // comp argument
+ if (comp)
+ s.append(",int");
+
+ s.append(");\n");
+ commonBuiltins.append(s);
+ }
+ }
+ }
+ }
+
+ if (sampler.dim == EsdRect || sampler.shadow)
+ return;
+
+ if (profile == EEsProfile || version < 450)
+ return;
+
+ for (int bias = 0; bias < 2; ++bias) { // loop over presence of bias argument
+
+ for (int lod = 0; lod < 2; ++lod) { // loop over presence of lod argument
+
+ if ((lod && bias) || (lod == 0 && bias == 0))
+ continue;
+
+ for (int f16TexAddr = 0; f16TexAddr <= 1; ++f16TexAddr) { // loop over 16-bit floating-point texel addressing
+
+ if (f16TexAddr && sampler.type != EbtFloat16)
+ continue;
+
+ for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name: none, Offset, and Offsets
+
+ for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument
+
+ if (comp == 0 && bias)
+ continue;
+
+ if (offset > 0 && sampler.dim == EsdCube)
+ continue;
+
+ for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not
+ if (sparse && (profile == EEsProfile || version < 450))
+ continue;
+
+ TString s;
+
+ // return type
+ if (sparse)
+ s.append("int ");
+ else {
+ s.append(prefixes[sampler.type]);
+ s.append("vec4 ");
+ }
+
+ // name
+ if (sparse)
+ s.append("sparseTextureGather");
+ else
+ s.append("textureGather");
+
+ if (lod)
+ s.append("Lod");
+
+ switch (offset) {
+ case 1:
+ s.append("Offset");
+ break;
+ case 2:
+ s.append("Offsets");
+ break;
+ default:
+ break;
+ }
+
+ if (lod)
+ s.append("AMD");
+ else if (sparse)
+ s.append("ARB");
+
+ s.append("(");
+
+ // sampler type argument
+ s.append(typeName);
+
+ // P coordinate argument
+ if (f16TexAddr)
+ s.append(",f16vec");
+ else
+ s.append(",vec");
+ int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0);
+ s.append(postfixes[totalDims]);
+
+ // lod argument
+ if (lod) {
+ if (f16TexAddr)
+ s.append(",float16_t");
+ else
+ s.append(",float");
+ }
+
+ // offset argument
+ if (offset > 0) {
+ s.append(",ivec2");
+ if (offset == 2)
+ s.append("[4]");
+ }
+
+ // texel out (for sparse texture)
+ if (sparse) {
+ s.append(",out ");
+ s.append(prefixes[sampler.type]);
+ s.append("vec4 ");
+ }
+
+ // comp argument
+ if (comp)
+ s.append(",int");
+
+ // bias argument
+ if (bias) {
+ if (f16TexAddr)
+ s.append(",float16_t");
+ else
+ s.append(",float");
+ }
+
+ s.append(");\n");
+ if (bias)
+ stageBuiltins[EShLangFragment].append(s);
+ else
+ commonBuiltins.append(s);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+//
+// Add context-dependent built-in functions and variables that are present
+// for the given version and profile. All the results are put into just the
+// commonBuiltins, because it is called for just a specific stage. So,
+// add stage-specific entries to the commonBuiltins, and only if that stage
+// was requested.
+//
+void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language)
+{
+#ifdef GLSLANG_WEB
+ version = 310;
+ profile = EEsProfile;
+#endif
+
+ //
+ // Initialize the context-dependent (resource-dependent) built-in strings for parsing.
+ //
+
+ //============================================================================
+ //
+ // Standard Uniforms
+ //
+ //============================================================================
+
+ TString& s = commonBuiltins;
+ const int maxSize = 200;
+ char builtInConstant[maxSize];
+
+ //
+ // Build string of implementation dependent constants.
+ //
+
+ if (profile == EEsProfile) {
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers);
+ s.append(builtInConstant);
+
+ if (version == 100) {
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors);
+ s.append(builtInConstant);
+ } else {
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexOutputVectors = %d;", resources.maxVertexOutputVectors);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxFragmentInputVectors = %d;", resources.maxFragmentInputVectors);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MinProgramTexelOffset = %d;", resources.minProgramTexelOffset);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxProgramTexelOffset = %d;", resources.maxProgramTexelOffset);
+ s.append(builtInConstant);
+ }
+
+#ifndef GLSLANG_WEB
+ if (version >= 310) {
+ // geometry
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryInputComponents = %d;", resources.maxGeometryInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputComponents = %d;", resources.maxGeometryOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryImageUniforms = %d;", resources.maxGeometryImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTextureImageUnits = %d;", resources.maxGeometryTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputVertices = %d;", resources.maxGeometryOutputVertices);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTotalOutputComponents = %d;", resources.maxGeometryTotalOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryUniformComponents = %d;", resources.maxGeometryUniformComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources.maxGeometryAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources.maxGeometryAtomicCounterBuffers);
+ s.append(builtInConstant);
+
+ // tessellation
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlInputComponents = %d;", resources.maxTessControlInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlOutputComponents = %d;", resources.maxTessControlOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTextureImageUnits = %d;", resources.maxTessControlTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlUniformComponents = %d;", resources.maxTessControlUniformComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTotalOutputComponents = %d;", resources.maxTessControlTotalOutputComponents);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationInputComponents = %d;", resources.maxTessEvaluationInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationOutputComponents = %d;", resources.maxTessEvaluationOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationTextureImageUnits = %d;", resources.maxTessEvaluationTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationUniformComponents = %d;", resources.maxTessEvaluationUniformComponents);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessPatchComponents = %d;", resources.maxTessPatchComponents);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxPatchVertices = %d;", resources.maxPatchVertices);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessGenLevel = %d;", resources.maxTessGenLevel);
+ s.append(builtInConstant);
+
+ // this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxPatchVertices
+ if (language == EShLangTessControl || language == EShLangTessEvaluation) {
+ s.append(
+ "in gl_PerVertex {"
+ "highp vec4 gl_Position;"
+ "highp float gl_PointSize;"
+ "highp vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
+ "highp vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ "} gl_in[gl_MaxPatchVertices];"
+ "\n");
+ }
+ }
+
+ } else {
+ // non-ES profile
+
+ if (version > 400) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors);
+ s.append(builtInConstant);
+ }
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxLights = %d;", resources.maxLights);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxClipPlanes = %d;", resources.maxClipPlanes);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTextureUnits = %d;", resources.maxTextureUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTextureCoords = %d;", resources.maxTextureCoords);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents);
+ s.append(builtInConstant);
+
+ if (version < 150 || ARBCompatibility) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats);
+ s.append(builtInConstant);
+ }
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformComponents = %d;", resources.maxFragmentUniformComponents);
+ s.append(builtInConstant);
+
+ if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) {
+ //
+ // OpenGL'uniform' state. Page numbers are in reference to version
+ // 1.4 of the OpenGL specification.
+ //
+
+ //
+ // Matrix state. p. 31, 32, 37, 39, 40.
+ //
+ s.append("uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];"
+
+ //
+ // Derived matrix state that provides inverse and transposed versions
+ // of the matrices above.
+ //
+ "uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];"
+
+ "uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];"
+
+ "uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];"
+
+ //
+ // Clip planes p. 42.
+ //
+ "uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];"
+
+ //
+ // Light State p 50, 53, 55.
+ //
+ "uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];"
+
+ //
+ // Derived state from products of light.
+ //
+ "uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];"
+ "uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];"
+
+ //
+ // Texture Environment and Generation, p. 152, p. 40-42.
+ //
+ "uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];"
+ "uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];"
+ "uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];"
+ "uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];"
+ "uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];"
+ "uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];"
+ "uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];"
+ "uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];"
+ "uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];");
+ }
+
+ if (version >= 130) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxClipDistances = %d;", resources.maxClipDistances);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingComponents = %d;", resources.maxVaryingComponents);
+ s.append(builtInConstant);
+
+ // GL_ARB_shading_language_420pack
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MinProgramTexelOffset = %d;", resources.minProgramTexelOffset);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxProgramTexelOffset = %d;", resources.maxProgramTexelOffset);
+ s.append(builtInConstant);
+ }
+
+ // geometry
+ if (version >= 150) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryInputComponents = %d;", resources.maxGeometryInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputComponents = %d;", resources.maxGeometryOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTextureImageUnits = %d;", resources.maxGeometryTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputVertices = %d;", resources.maxGeometryOutputVertices);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTotalOutputComponents = %d;", resources.maxGeometryTotalOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryUniformComponents = %d;", resources.maxGeometryUniformComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryVaryingComponents = %d;", resources.maxGeometryVaryingComponents);
+ s.append(builtInConstant);
+
+ }
+
+ if (version >= 150) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexOutputComponents = %d;", resources.maxVertexOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentInputComponents = %d;", resources.maxFragmentInputComponents);
+ s.append(builtInConstant);
+ }
+
+ // tessellation
+ if (version >= 150) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlInputComponents = %d;", resources.maxTessControlInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlOutputComponents = %d;", resources.maxTessControlOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTextureImageUnits = %d;", resources.maxTessControlTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlUniformComponents = %d;", resources.maxTessControlUniformComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTotalOutputComponents = %d;", resources.maxTessControlTotalOutputComponents);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationInputComponents = %d;", resources.maxTessEvaluationInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationOutputComponents = %d;", resources.maxTessEvaluationOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationTextureImageUnits = %d;", resources.maxTessEvaluationTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationUniformComponents = %d;", resources.maxTessEvaluationUniformComponents);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessPatchComponents = %d;", resources.maxTessPatchComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessGenLevel = %d;", resources.maxTessGenLevel);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxPatchVertices = %d;", resources.maxPatchVertices);
+ s.append(builtInConstant);
+
+ // this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxPatchVertices
+ if (language == EShLangTessControl || language == EShLangTessEvaluation) {
+ s.append(
+ "in gl_PerVertex {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ );
+ if (profile == ECompatibilityProfile)
+ s.append(
+ "vec4 gl_ClipVertex;"
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (profile != EEsProfile && version >= 450)
+ s.append(
+ "float gl_CullDistance[];"
+ "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering
+ "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes
+ );
+ s.append(
+ "} gl_in[gl_MaxPatchVertices];"
+ "\n");
+ }
+ }
+
+ if (version >= 150) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxViewports = %d;", resources.maxViewports);
+ s.append(builtInConstant);
+ }
+
+ // images
+ if (version >= 130) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedImageUnitsAndFragmentOutputs = %d;", resources.maxCombinedImageUnitsAndFragmentOutputs);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxImageSamples = %d;", resources.maxImageSamples);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlImageUniforms = %d;", resources.maxTessControlImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationImageUniforms = %d;", resources.maxTessEvaluationImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryImageUniforms = %d;", resources.maxGeometryImageUniforms);
+ s.append(builtInConstant);
+ }
+
+ // enhanced layouts
+ if (version >= 430) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTransformFeedbackBuffers = %d;", resources.maxTransformFeedbackBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTransformFeedbackInterleavedComponents = %d;", resources.maxTransformFeedbackInterleavedComponents);
+ s.append(builtInConstant);
+ }
+#endif
+ }
+
+ // compute
+ if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 420)) {
+ snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupCount = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupCountX,
+ resources.maxComputeWorkGroupCountY,
+ resources.maxComputeWorkGroupCountZ);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupSize = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupSizeX,
+ resources.maxComputeWorkGroupSizeY,
+ resources.maxComputeWorkGroupSizeZ);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxComputeUniformComponents = %d;", resources.maxComputeUniformComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxComputeTextureImageUnits = %d;", resources.maxComputeTextureImageUnits);
+ s.append(builtInConstant);
+
+ s.append("\n");
+ }
+
+#ifndef GLSLANG_WEB
+ // images (some in compute below)
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 130)) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxImageUnits = %d;", resources.maxImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedShaderOutputResources = %d;", resources.maxCombinedShaderOutputResources);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexImageUniforms = %d;", resources.maxVertexImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentImageUniforms = %d;", resources.maxFragmentImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedImageUniforms = %d;", resources.maxCombinedImageUniforms);
+ s.append(builtInConstant);
+ }
+
+ // compute
+ if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 420)) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxComputeImageUniforms = %d;", resources.maxComputeImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounters = %d;", resources.maxComputeAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounterBuffers = %d;", resources.maxComputeAtomicCounterBuffers);
+ s.append(builtInConstant);
+
+ s.append("\n");
+ }
+
+ // atomic counters (some in compute below)
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 420)) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounters = %d;", resources. maxVertexAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounters = %d;", resources. maxFragmentAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounters = %d;", resources. maxCombinedAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBindings = %d;", resources. maxAtomicCounterBindings);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounterBuffers = %d;", resources. maxVertexAtomicCounterBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounterBuffers = %d;", resources. maxFragmentAtomicCounterBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounterBuffers = %d;", resources. maxCombinedAtomicCounterBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBufferSize = %d;", resources. maxAtomicCounterBufferSize);
+ s.append(builtInConstant);
+ }
+ if (profile != EEsProfile && version >= 420) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources. maxTessControlAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources. maxTessEvaluationAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources. maxGeometryAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources. maxTessControlAtomicCounterBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources. maxTessEvaluationAtomicCounterBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources. maxGeometryAtomicCounterBuffers);
+ s.append(builtInConstant);
+
+ s.append("\n");
+ }
+
+ // GL_ARB_cull_distance
+ if (profile != EEsProfile && version >= 450) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCullDistances = %d;", resources.maxCullDistances);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedClipAndCullDistances = %d;", resources.maxCombinedClipAndCullDistances);
+ s.append(builtInConstant);
+ }
+
+ // GL_ARB_ES3_1_compatibility
+ if ((profile != EEsProfile && version >= 450) ||
+ (profile == EEsProfile && version >= 310)) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxSamples = %d;", resources.maxSamples);
+ s.append(builtInConstant);
+ }
+
+ // SPV_NV_mesh_shader
+ if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxMeshOutputVerticesNV = %d;", resources.maxMeshOutputVerticesNV);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxMeshOutputPrimitivesNV = %d;", resources.maxMeshOutputPrimitivesNV);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxMeshWorkGroupSizeNV = ivec3(%d,%d,%d);", resources.maxMeshWorkGroupSizeX_NV,
+ resources.maxMeshWorkGroupSizeY_NV,
+ resources.maxMeshWorkGroupSizeZ_NV);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxTaskWorkGroupSizeNV = ivec3(%d,%d,%d);", resources.maxTaskWorkGroupSizeX_NV,
+ resources.maxTaskWorkGroupSizeY_NV,
+ resources.maxTaskWorkGroupSizeZ_NV);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxMeshViewCountNV = %d;", resources.maxMeshViewCountNV);
+ s.append(builtInConstant);
+
+ s.append("\n");
+ }
+#endif
+
+ s.append("\n");
+}
+
+//
+// To support special built-ins that have a special qualifier that cannot be declared textually
+// in a shader, like gl_Position.
+//
+// This lets the type of the built-in be declared textually, and then have just its qualifier be
+// updated afterward.
+//
+// Safe to call even if name is not present.
+//
+// Only use this for built-in variables that have a special qualifier in TStorageQualifier.
+// New built-in variables should use a generic (textually declarable) qualifier in
+// TStoraregQualifier and only call BuiltInVariable().
+//
+static void SpecialQualifier(const char* name, TStorageQualifier qualifier, TBuiltInVariable builtIn, TSymbolTable& symbolTable)
+{
+ TSymbol* symbol = symbolTable.find(name);
+ if (symbol == nullptr)
+ return;
+
+ TQualifier& symQualifier = symbol->getWritableType().getQualifier();
+ symQualifier.storage = qualifier;
+ symQualifier.builtIn = builtIn;
+}
+
+//
+// To tag built-in variables with their TBuiltInVariable enum. Use this when the
+// normal declaration text already gets the qualifier right, and all that's needed
+// is setting the builtIn field. This should be the normal way for all new
+// built-in variables.
+//
+// If SpecialQualifier() was called, this does not need to be called.
+//
+// Safe to call even if name is not present.
+//
+static void BuiltInVariable(const char* name, TBuiltInVariable builtIn, TSymbolTable& symbolTable)
+{
+ TSymbol* symbol = symbolTable.find(name);
+ if (symbol == nullptr)
+ return;
+
+ TQualifier& symQualifier = symbol->getWritableType().getQualifier();
+ symQualifier.builtIn = builtIn;
+}
+
+//
+// For built-in variables inside a named block.
+// SpecialQualifier() won't ever go inside a block; their member's qualifier come
+// from the qualification of the block.
+//
+// See comments above for other detail.
+//
+static void BuiltInVariable(const char* blockName, const char* name, TBuiltInVariable builtIn, TSymbolTable& symbolTable)
+{
+ TSymbol* symbol = symbolTable.find(blockName);
+ if (symbol == nullptr)
+ return;
+
+ TTypeList& structure = *symbol->getWritableType().getWritableStruct();
+ for (int i = 0; i < (int)structure.size(); ++i) {
+ if (structure[i].type->getFieldName().compare(name) == 0) {
+ structure[i].type->getQualifier().builtIn = builtIn;
+ return;
+ }
+ }
+}
+
+//
+// Finish adding/processing context-independent built-in symbols.
+// 1) Programmatically add symbols that could not be added by simple text strings above.
+// 2) Map built-in functions to operators, for those that will turn into an operation node
+// instead of remaining a function call.
+// 3) Tag extension-related symbols added to their base version with their extensions, so
+// that if an early version has the extension turned off, there is an error reported on use.
+//
+void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable)
+{
+#ifdef GLSLANG_WEB
+ version = 310;
+ profile = EEsProfile;
+#endif
+
+ //
+ // Tag built-in variables and functions with additional qualifier and extension information
+ // that cannot be declared with the text strings.
+ //
+
+ // N.B.: a symbol should only be tagged once, and this function is called multiple times, once
+ // per stage that's used for this profile. So
+ // - generally, stick common ones in the fragment stage to ensure they are tagged exactly once
+ // - for ES, which has different precisions for different stages, the coarsest-grained tagging
+ // for a built-in used in many stages needs to be once for the fragment stage and once for
+ // the vertex stage
+
+ switch(language) {
+ case EShLangVertex:
+ if (spvVersion.vulkan > 0) {
+ BuiltInVariable("gl_VertexIndex", EbvVertexIndex, symbolTable);
+ BuiltInVariable("gl_InstanceIndex", EbvInstanceIndex, symbolTable);
+ }
+
+#ifndef GLSLANG_WEB
+ if (spvVersion.vulkan == 0) {
+ SpecialQualifier("gl_VertexID", EvqVertexId, EbvVertexId, symbolTable);
+ SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable);
+ }
+
+ if (profile != EEsProfile) {
+ if (version >= 440) {
+ symbolTable.setVariableExtensions("gl_BaseVertexARB", 1, &E_GL_ARB_shader_draw_parameters);
+ symbolTable.setVariableExtensions("gl_BaseInstanceARB", 1, &E_GL_ARB_shader_draw_parameters);
+ symbolTable.setVariableExtensions("gl_DrawIDARB", 1, &E_GL_ARB_shader_draw_parameters);
+ BuiltInVariable("gl_BaseVertexARB", EbvBaseVertex, symbolTable);
+ BuiltInVariable("gl_BaseInstanceARB", EbvBaseInstance, symbolTable);
+ BuiltInVariable("gl_DrawIDARB", EbvDrawId, symbolTable);
+ }
+ if (version >= 460) {
+ BuiltInVariable("gl_BaseVertex", EbvBaseVertex, symbolTable);
+ BuiltInVariable("gl_BaseInstance", EbvBaseInstance, symbolTable);
+ BuiltInVariable("gl_DrawID", EbvDrawId, symbolTable);
+ }
+ symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot);
+
+ symbolTable.setFunctionExtensions("ballotARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setFunctionExtensions("readInvocationARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setFunctionExtensions("readFirstInvocationARB", 1, &E_GL_ARB_shader_ballot);
+
+ if (version >= 430) {
+ symbolTable.setFunctionExtensions("anyInvocationARB", 1, &E_GL_ARB_shader_group_vote);
+ symbolTable.setFunctionExtensions("allInvocationsARB", 1, &E_GL_ARB_shader_group_vote);
+ symbolTable.setFunctionExtensions("allInvocationsEqualARB", 1, &E_GL_ARB_shader_group_vote);
+ }
+ }
+
+
+ if (profile != EEsProfile) {
+ symbolTable.setFunctionExtensions("minInvocationsAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("maxInvocationsAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("addInvocationsAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("minInvocationsNonUniformAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("maxInvocationsNonUniformAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("addInvocationsNonUniformAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("swizzleInvocationsAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("swizzleInvocationsWithPatternAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("writeInvocationAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("mbcntAMD", 1, &E_GL_AMD_shader_ballot);
+
+ symbolTable.setFunctionExtensions("minInvocationsInclusiveScanAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("maxInvocationsInclusiveScanAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("addInvocationsInclusiveScanAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("minInvocationsInclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("maxInvocationsInclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("addInvocationsInclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("minInvocationsExclusiveScanAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("maxInvocationsExclusiveScanAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("addInvocationsExclusiveScanAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("minInvocationsExclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("maxInvocationsExclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot);
+ symbolTable.setFunctionExtensions("addInvocationsExclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot);
+ }
+
+ if (profile != EEsProfile) {
+ symbolTable.setFunctionExtensions("min3", 1, &E_GL_AMD_shader_trinary_minmax);
+ symbolTable.setFunctionExtensions("max3", 1, &E_GL_AMD_shader_trinary_minmax);
+ symbolTable.setFunctionExtensions("mid3", 1, &E_GL_AMD_shader_trinary_minmax);
+ }
+
+ if (profile != EEsProfile) {
+ symbolTable.setVariableExtensions("gl_SIMDGroupSizeAMD", 1, &E_GL_AMD_gcn_shader);
+ SpecialQualifier("gl_SIMDGroupSizeAMD", EvqVaryingIn, EbvSubGroupSize, symbolTable);
+
+ symbolTable.setFunctionExtensions("cubeFaceIndexAMD", 1, &E_GL_AMD_gcn_shader);
+ symbolTable.setFunctionExtensions("cubeFaceCoordAMD", 1, &E_GL_AMD_gcn_shader);
+ symbolTable.setFunctionExtensions("timeAMD", 1, &E_GL_AMD_gcn_shader);
+ }
+
+ if (profile != EEsProfile) {
+ symbolTable.setFunctionExtensions("fragmentMaskFetchAMD", 1, &E_GL_AMD_shader_fragment_mask);
+ symbolTable.setFunctionExtensions("fragmentFetchAMD", 1, &E_GL_AMD_shader_fragment_mask);
+ }
+
+ symbolTable.setFunctionExtensions("countLeadingZeros", 1, &E_GL_INTEL_shader_integer_functions2);
+ symbolTable.setFunctionExtensions("countTrailingZeros", 1, &E_GL_INTEL_shader_integer_functions2);
+ symbolTable.setFunctionExtensions("absoluteDifference", 1, &E_GL_INTEL_shader_integer_functions2);
+ symbolTable.setFunctionExtensions("addSaturate", 1, &E_GL_INTEL_shader_integer_functions2);
+ symbolTable.setFunctionExtensions("subtractSaturate", 1, &E_GL_INTEL_shader_integer_functions2);
+ symbolTable.setFunctionExtensions("average", 1, &E_GL_INTEL_shader_integer_functions2);
+ symbolTable.setFunctionExtensions("averageRounded", 1, &E_GL_INTEL_shader_integer_functions2);
+ symbolTable.setFunctionExtensions("multiply32x16", 1, &E_GL_INTEL_shader_integer_functions2);
+
+ symbolTable.setFunctionExtensions("textureFootprintNV", 1, &E_GL_NV_shader_texture_footprint);
+ symbolTable.setFunctionExtensions("textureFootprintClampNV", 1, &E_GL_NV_shader_texture_footprint);
+ symbolTable.setFunctionExtensions("textureFootprintLodNV", 1, &E_GL_NV_shader_texture_footprint);
+ symbolTable.setFunctionExtensions("textureFootprintGradNV", 1, &E_GL_NV_shader_texture_footprint);
+ symbolTable.setFunctionExtensions("textureFootprintGradClampNV", 1, &E_GL_NV_shader_texture_footprint);
+ // Compatibility variables, vertex only
+ if (spvVersion.spv == 0) {
+ BuiltInVariable("gl_Color", EbvColor, symbolTable);
+ BuiltInVariable("gl_SecondaryColor", EbvSecondaryColor, symbolTable);
+ BuiltInVariable("gl_Normal", EbvNormal, symbolTable);
+ BuiltInVariable("gl_Vertex", EbvVertex, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord0", EbvMultiTexCoord0, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord1", EbvMultiTexCoord1, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord2", EbvMultiTexCoord2, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord3", EbvMultiTexCoord3, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord4", EbvMultiTexCoord4, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord5", EbvMultiTexCoord5, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord6", EbvMultiTexCoord6, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord7", EbvMultiTexCoord7, symbolTable);
+ BuiltInVariable("gl_FogCoord", EbvFogFragCoord, symbolTable);
+ }
+
+ if (profile == EEsProfile) {
+ if (spvVersion.spv == 0) {
+ symbolTable.setFunctionExtensions("texture2DGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureCubeGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ if (version == 310)
+ symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5);
+ }
+ if (version == 310)
+ symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5);
+ }
+
+ if (profile == EEsProfile && version < 320) {
+ symbolTable.setFunctionExtensions("imageAtomicAdd", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicMin", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicMax", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicAnd", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicOr", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicXor", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicExchange", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic);
+ }
+
+ if (version >= 300 /* both ES and non-ES */) {
+ symbolTable.setVariableExtensions("gl_ViewID_OVR", Num_OVR_multiview_EXTs, OVR_multiview_EXTs);
+ BuiltInVariable("gl_ViewID_OVR", EbvViewIndex, symbolTable);
+ }
+
+ if (profile == EEsProfile) {
+ symbolTable.setFunctionExtensions("shadow2DEXT", 1, &E_GL_EXT_shadow_samplers);
+ symbolTable.setFunctionExtensions("shadow2DProjEXT", 1, &E_GL_EXT_shadow_samplers);
+ }
+ // Fall through
+
+ case EShLangTessControl:
+ if (profile == EEsProfile && version >= 310) {
+ BuiltInVariable("gl_BoundingBoxEXT", EbvBoundingBox, symbolTable);
+ symbolTable.setVariableExtensions("gl_BoundingBoxEXT", 1,
+ &E_GL_EXT_primitive_bounding_box);
+ BuiltInVariable("gl_BoundingBoxOES", EbvBoundingBox, symbolTable);
+ symbolTable.setVariableExtensions("gl_BoundingBoxOES", 1,
+ &E_GL_OES_primitive_bounding_box);
+
+ if (version >= 320) {
+ BuiltInVariable("gl_BoundingBox", EbvBoundingBox, symbolTable);
+ }
+ }
+ // Fall through
+
+ case EShLangTessEvaluation:
+ case EShLangGeometry:
+#endif
+ SpecialQualifier("gl_Position", EvqPosition, EbvPosition, symbolTable);
+ SpecialQualifier("gl_PointSize", EvqPointSize, EbvPointSize, symbolTable);
+
+ BuiltInVariable("gl_in", "gl_Position", EbvPosition, symbolTable);
+ BuiltInVariable("gl_in", "gl_PointSize", EbvPointSize, symbolTable);
+
+ BuiltInVariable("gl_out", "gl_Position", EbvPosition, symbolTable);
+ BuiltInVariable("gl_out", "gl_PointSize", EbvPointSize, symbolTable);
+
+#ifndef GLSLANG_WEB
+ SpecialQualifier("gl_ClipVertex", EvqClipVertex, EbvClipVertex, symbolTable);
+
+ BuiltInVariable("gl_in", "gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_in", "gl_CullDistance", EbvCullDistance, symbolTable);
+
+ BuiltInVariable("gl_out", "gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_out", "gl_CullDistance", EbvCullDistance, symbolTable);
+
+ BuiltInVariable("gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_CullDistance", EbvCullDistance, symbolTable);
+ BuiltInVariable("gl_PrimitiveIDIn", EbvPrimitiveId, symbolTable);
+ BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable);
+ BuiltInVariable("gl_InvocationID", EbvInvocationId, symbolTable);
+ BuiltInVariable("gl_Layer", EbvLayer, symbolTable);
+ BuiltInVariable("gl_ViewportIndex", EbvViewportIndex, symbolTable);
+
+ if (language != EShLangGeometry) {
+ symbolTable.setVariableExtensions("gl_Layer", Num_viewportEXTs, viewportEXTs);
+ symbolTable.setVariableExtensions("gl_ViewportIndex", Num_viewportEXTs, viewportEXTs);
+ }
+ symbolTable.setVariableExtensions("gl_ViewportMask", 1, &E_GL_NV_viewport_array2);
+ symbolTable.setVariableExtensions("gl_SecondaryPositionNV", 1, &E_GL_NV_stereo_view_rendering);
+ symbolTable.setVariableExtensions("gl_SecondaryViewportMaskNV", 1, &E_GL_NV_stereo_view_rendering);
+ symbolTable.setVariableExtensions("gl_PositionPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes);
+ symbolTable.setVariableExtensions("gl_ViewportMaskPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes);
+
+ BuiltInVariable("gl_ViewportMask", EbvViewportMaskNV, symbolTable);
+ BuiltInVariable("gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable);
+ BuiltInVariable("gl_SecondaryViewportMaskNV", EbvSecondaryViewportMaskNV, symbolTable);
+ BuiltInVariable("gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable);
+ BuiltInVariable("gl_ViewportMaskPerViewNV", EbvViewportMaskPerViewNV, symbolTable);
+
+ if (language == EShLangVertex || language == EShLangGeometry) {
+ symbolTable.setVariableExtensions("gl_in", "gl_SecondaryPositionNV", 1, &E_GL_NV_stereo_view_rendering);
+ symbolTable.setVariableExtensions("gl_in", "gl_PositionPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes);
+
+ BuiltInVariable("gl_in", "gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable);
+ BuiltInVariable("gl_in", "gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable);
+ }
+ symbolTable.setVariableExtensions("gl_out", "gl_ViewportMask", 1, &E_GL_NV_viewport_array2);
+ symbolTable.setVariableExtensions("gl_out", "gl_SecondaryPositionNV", 1, &E_GL_NV_stereo_view_rendering);
+ symbolTable.setVariableExtensions("gl_out", "gl_SecondaryViewportMaskNV", 1, &E_GL_NV_stereo_view_rendering);
+ symbolTable.setVariableExtensions("gl_out", "gl_PositionPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes);
+ symbolTable.setVariableExtensions("gl_out", "gl_ViewportMaskPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes);
+
+ BuiltInVariable("gl_out", "gl_ViewportMask", EbvViewportMaskNV, symbolTable);
+ BuiltInVariable("gl_out", "gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable);
+ BuiltInVariable("gl_out", "gl_SecondaryViewportMaskNV", EbvSecondaryViewportMaskNV, symbolTable);
+ BuiltInVariable("gl_out", "gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable);
+ BuiltInVariable("gl_out", "gl_ViewportMaskPerViewNV", EbvViewportMaskPerViewNV, symbolTable);
+
+ BuiltInVariable("gl_PatchVerticesIn", EbvPatchVertices, symbolTable);
+ BuiltInVariable("gl_TessLevelOuter", EbvTessLevelOuter, symbolTable);
+ BuiltInVariable("gl_TessLevelInner", EbvTessLevelInner, symbolTable);
+ BuiltInVariable("gl_TessCoord", EbvTessCoord, symbolTable);
+
+ if (version < 410)
+ symbolTable.setVariableExtensions("gl_ViewportIndex", 1, &E_GL_ARB_viewport_array);
+
+ // Compatibility variables
+
+ BuiltInVariable("gl_in", "gl_ClipVertex", EbvClipVertex, symbolTable);
+ BuiltInVariable("gl_in", "gl_FrontColor", EbvFrontColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_BackColor", EbvBackColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+
+ BuiltInVariable("gl_out", "gl_ClipVertex", EbvClipVertex, symbolTable);
+ BuiltInVariable("gl_out", "gl_FrontColor", EbvFrontColor, symbolTable);
+ BuiltInVariable("gl_out", "gl_BackColor", EbvBackColor, symbolTable);
+ BuiltInVariable("gl_out", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable);
+ BuiltInVariable("gl_out", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable);
+ BuiltInVariable("gl_out", "gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_out", "gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+
+ BuiltInVariable("gl_ClipVertex", EbvClipVertex, symbolTable);
+ BuiltInVariable("gl_FrontColor", EbvFrontColor, symbolTable);
+ BuiltInVariable("gl_BackColor", EbvBackColor, symbolTable);
+ BuiltInVariable("gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable);
+ BuiltInVariable("gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable);
+ BuiltInVariable("gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+
+ // gl_PointSize, when it needs to be tied to an extension, is always a member of a block.
+ // (Sometimes with an instance name, sometimes anonymous).
+ if (profile == EEsProfile) {
+ if (language == EShLangGeometry) {
+ symbolTable.setVariableExtensions("gl_PointSize", Num_AEP_geometry_point_size, AEP_geometry_point_size);
+ symbolTable.setVariableExtensions("gl_in", "gl_PointSize", Num_AEP_geometry_point_size, AEP_geometry_point_size);
+ } else if (language == EShLangTessEvaluation || language == EShLangTessControl) {
+ // gl_in tessellation settings of gl_PointSize are in the context-dependent paths
+ symbolTable.setVariableExtensions("gl_PointSize", Num_AEP_tessellation_point_size, AEP_tessellation_point_size);
+ symbolTable.setVariableExtensions("gl_out", "gl_PointSize", Num_AEP_tessellation_point_size, AEP_tessellation_point_size);
+ }
+ }
+
+ if ((profile != EEsProfile && version >= 140) ||
+ (profile == EEsProfile && version >= 310)) {
+ symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
+ BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
+ symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
+ BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
+ }
+
+ if (profile != EEsProfile) {
+ BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable);
+ BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable);
+
+ if (spvVersion.vulkan > 0)
+ // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan
+ SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable);
+ else
+ BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable);
+ }
+
+ // GL_KHR_shader_subgroup
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 140)) {
+ symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+
+ BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable);
+ BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable);
+ BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable);
+
+ // GL_NV_shader_sm_builtins
+ symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable);
+ BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable);
+ BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
+ BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
+ }
+#endif
+ break;
+
+ case EShLangFragment:
+ SpecialQualifier("gl_FrontFacing", EvqFace, EbvFace, symbolTable);
+ SpecialQualifier("gl_FragCoord", EvqFragCoord, EbvFragCoord, symbolTable);
+ SpecialQualifier("gl_PointCoord", EvqPointCoord, EbvPointCoord, symbolTable);
+ if (spvVersion.spv == 0)
+ SpecialQualifier("gl_FragColor", EvqFragColor, EbvFragColor, symbolTable);
+ else {
+ TSymbol* symbol = symbolTable.find("gl_FragColor");
+ if (symbol) {
+ symbol->getWritableType().getQualifier().storage = EvqVaryingOut;
+ symbol->getWritableType().getQualifier().layoutLocation = 0;
+ }
+ }
+ SpecialQualifier("gl_FragDepth", EvqFragDepth, EbvFragDepth, symbolTable);
+#ifndef GLSLANG_WEB
+ SpecialQualifier("gl_FragDepthEXT", EvqFragDepth, EbvFragDepth, symbolTable);
+ SpecialQualifier("gl_HelperInvocation", EvqVaryingIn, EbvHelperInvocation, symbolTable);
+
+ BuiltInVariable("gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_CullDistance", EbvCullDistance, symbolTable);
+ BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable);
+
+ if (profile != EEsProfile && version >= 140) {
+ symbolTable.setVariableExtensions("gl_FragStencilRefARB", 1, &E_GL_ARB_shader_stencil_export);
+ BuiltInVariable("gl_FragStencilRefARB", EbvFragStencilRef, symbolTable);
+ }
+
+ if ((profile != EEsProfile && version >= 130) ||
+ (profile == EEsProfile && version >= 310)) {
+ BuiltInVariable("gl_SampleID", EbvSampleId, symbolTable);
+ BuiltInVariable("gl_SamplePosition", EbvSamplePosition, symbolTable);
+ BuiltInVariable("gl_SampleMask", EbvSampleMask, symbolTable);
+
+ if (profile != EEsProfile && version < 400) {
+ BuiltInVariable("gl_NumSamples", EbvSampleMask, symbolTable);
+
+ symbolTable.setVariableExtensions("gl_SampleMask", 1, &E_GL_ARB_sample_shading);
+ symbolTable.setVariableExtensions("gl_SampleID", 1, &E_GL_ARB_sample_shading);
+ symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_ARB_sample_shading);
+ symbolTable.setVariableExtensions("gl_NumSamples", 1, &E_GL_ARB_sample_shading);
+ } else {
+ BuiltInVariable("gl_SampleMaskIn", EbvSampleMask, symbolTable);
+
+ if (profile == EEsProfile && version < 320) {
+ symbolTable.setVariableExtensions("gl_SampleID", 1, &E_GL_OES_sample_variables);
+ symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_OES_sample_variables);
+ symbolTable.setVariableExtensions("gl_SampleMaskIn", 1, &E_GL_OES_sample_variables);
+ symbolTable.setVariableExtensions("gl_SampleMask", 1, &E_GL_OES_sample_variables);
+ symbolTable.setVariableExtensions("gl_NumSamples", 1, &E_GL_OES_sample_variables);
+ }
+ }
+ }
+
+ BuiltInVariable("gl_Layer", EbvLayer, symbolTable);
+ BuiltInVariable("gl_ViewportIndex", EbvViewportIndex, symbolTable);
+
+ // Compatibility variables
+
+ BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+ BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_in", "gl_Color", EbvColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_SecondaryColor", EbvSecondaryColor, symbolTable);
+
+ BuiltInVariable("gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+ BuiltInVariable("gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_Color", EbvColor, symbolTable);
+ BuiltInVariable("gl_SecondaryColor", EbvSecondaryColor, symbolTable);
+
+ // built-in functions
+
+ if (profile == EEsProfile) {
+ if (spvVersion.spv == 0) {
+ symbolTable.setFunctionExtensions("texture2DLodEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DProjLodEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureCubeLodEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureCubeGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ if (version < 320)
+ symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5);
+ }
+ if (version == 100) {
+ symbolTable.setFunctionExtensions("dFdx", 1, &E_GL_OES_standard_derivatives);
+ symbolTable.setFunctionExtensions("dFdy", 1, &E_GL_OES_standard_derivatives);
+ symbolTable.setFunctionExtensions("fwidth", 1, &E_GL_OES_standard_derivatives);
+ }
+ if (version == 310) {
+ symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5);
+ symbolTable.setFunctionExtensions("interpolateAtCentroid", 1, &E_GL_OES_shader_multisample_interpolation);
+ symbolTable.setFunctionExtensions("interpolateAtSample", 1, &E_GL_OES_shader_multisample_interpolation);
+ symbolTable.setFunctionExtensions("interpolateAtOffset", 1, &E_GL_OES_shader_multisample_interpolation);
+ }
+ } else if (version < 130) {
+ if (spvVersion.spv == 0) {
+ symbolTable.setFunctionExtensions("texture1DLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture3DLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureCubeLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture1DProjLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DProjLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture3DProjLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow1DLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow1DProjLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DProjLod", 1, &E_GL_ARB_shader_texture_lod);
+ }
+ }
+
+ // E_GL_ARB_shader_texture_lod functions usable only with the extension enabled
+ if (profile != EEsProfile && spvVersion.spv == 0) {
+ symbolTable.setFunctionExtensions("texture1DGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture1DProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture3DGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture3DProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureCubeGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow1DGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow1DProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DRectGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DRectProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DRectGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DRectProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ }
+
+ // E_GL_ARB_shader_image_load_store
+ if (profile != EEsProfile && version < 420)
+ symbolTable.setFunctionExtensions("memoryBarrier", 1, &E_GL_ARB_shader_image_load_store);
+ // All the image access functions are protected by checks on the type of the first argument.
+
+ // E_GL_ARB_shader_atomic_counters
+ if (profile != EEsProfile && version < 420) {
+ symbolTable.setFunctionExtensions("atomicCounterIncrement", 1, &E_GL_ARB_shader_atomic_counters);
+ symbolTable.setFunctionExtensions("atomicCounterDecrement", 1, &E_GL_ARB_shader_atomic_counters);
+ symbolTable.setFunctionExtensions("atomicCounter" , 1, &E_GL_ARB_shader_atomic_counters);
+ }
+
+ // E_GL_ARB_derivative_control
+ if (profile != EEsProfile && version < 450) {
+ symbolTable.setFunctionExtensions("dFdxFine", 1, &E_GL_ARB_derivative_control);
+ symbolTable.setFunctionExtensions("dFdyFine", 1, &E_GL_ARB_derivative_control);
+ symbolTable.setFunctionExtensions("fwidthFine", 1, &E_GL_ARB_derivative_control);
+ symbolTable.setFunctionExtensions("dFdxCoarse", 1, &E_GL_ARB_derivative_control);
+ symbolTable.setFunctionExtensions("dFdyCoarse", 1, &E_GL_ARB_derivative_control);
+ symbolTable.setFunctionExtensions("fwidthCoarse", 1, &E_GL_ARB_derivative_control);
+ }
+
+ // E_GL_ARB_sparse_texture2
+ if (profile != EEsProfile)
+ {
+ symbolTable.setFunctionExtensions("sparseTextureARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureLodARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureOffsetARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTexelFetchARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTexelFetchOffsetARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureLodOffsetARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureGradARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureGradOffsetARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureGatherARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureGatherOffsetARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureGatherOffsetsARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseImageLoadARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTexelsResident", 1, &E_GL_ARB_sparse_texture2);
+ }
+
+ // E_GL_ARB_sparse_texture_clamp
+ if (profile != EEsProfile)
+ {
+ symbolTable.setFunctionExtensions("sparseTextureClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("sparseTextureOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("sparseTextureGradClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("sparseTextureGradOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("textureClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("textureOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("textureGradClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("textureGradOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ }
+
+ // E_GL_AMD_shader_explicit_vertex_parameter
+ if (profile != EEsProfile) {
+ symbolTable.setVariableExtensions("gl_BaryCoordNoPerspAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter);
+ symbolTable.setVariableExtensions("gl_BaryCoordNoPerspCentroidAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter);
+ symbolTable.setVariableExtensions("gl_BaryCoordNoPerspSampleAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter);
+ symbolTable.setVariableExtensions("gl_BaryCoordSmoothAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter);
+ symbolTable.setVariableExtensions("gl_BaryCoordSmoothCentroidAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter);
+ symbolTable.setVariableExtensions("gl_BaryCoordSmoothSampleAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter);
+ symbolTable.setVariableExtensions("gl_BaryCoordPullModelAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter);
+
+ symbolTable.setFunctionExtensions("interpolateAtVertexAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter);
+
+ BuiltInVariable("gl_BaryCoordNoPerspAMD", EbvBaryCoordNoPersp, symbolTable);
+ BuiltInVariable("gl_BaryCoordNoPerspCentroidAMD", EbvBaryCoordNoPerspCentroid, symbolTable);
+ BuiltInVariable("gl_BaryCoordNoPerspSampleAMD", EbvBaryCoordNoPerspSample, symbolTable);
+ BuiltInVariable("gl_BaryCoordSmoothAMD", EbvBaryCoordSmooth, symbolTable);
+ BuiltInVariable("gl_BaryCoordSmoothCentroidAMD", EbvBaryCoordSmoothCentroid, symbolTable);
+ BuiltInVariable("gl_BaryCoordSmoothSampleAMD", EbvBaryCoordSmoothSample, symbolTable);
+ BuiltInVariable("gl_BaryCoordPullModelAMD", EbvBaryCoordPullModel, symbolTable);
+ }
+
+ // E_GL_AMD_texture_gather_bias_lod
+ if (profile != EEsProfile) {
+ symbolTable.setFunctionExtensions("textureGatherLodAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
+ symbolTable.setFunctionExtensions("textureGatherLodOffsetAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
+ symbolTable.setFunctionExtensions("textureGatherLodOffsetsAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
+ symbolTable.setFunctionExtensions("sparseTextureGatherLodAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
+ symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
+ symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetsAMD", 1, &E_GL_AMD_texture_gather_bias_lod);
+ }
+
+ // E_GL_AMD_shader_image_load_store_lod
+ if (profile != EEsProfile) {
+ symbolTable.setFunctionExtensions("imageLoadLodAMD", 1, &E_GL_AMD_shader_image_load_store_lod);
+ symbolTable.setFunctionExtensions("imageStoreLodAMD", 1, &E_GL_AMD_shader_image_load_store_lod);
+ symbolTable.setFunctionExtensions("sparseImageLoadLodAMD", 1, &E_GL_AMD_shader_image_load_store_lod);
+ }
+ if (profile != EEsProfile && version >= 430) {
+ symbolTable.setVariableExtensions("gl_FragFullyCoveredNV", 1, &E_GL_NV_conservative_raster_underestimation);
+ BuiltInVariable("gl_FragFullyCoveredNV", EbvFragFullyCoveredNV, symbolTable);
+ }
+ if ((profile != EEsProfile && version >= 450) ||
+ (profile == EEsProfile && version >= 320)) {
+ symbolTable.setVariableExtensions("gl_FragmentSizeNV", 1, &E_GL_NV_shading_rate_image);
+ symbolTable.setVariableExtensions("gl_InvocationsPerPixelNV", 1, &E_GL_NV_shading_rate_image);
+ BuiltInVariable("gl_FragmentSizeNV", EbvFragmentSizeNV, symbolTable);
+ BuiltInVariable("gl_InvocationsPerPixelNV", EbvInvocationsPerPixelNV, symbolTable);
+ symbolTable.setVariableExtensions("gl_BaryCoordNV", 1, &E_GL_NV_fragment_shader_barycentric);
+ symbolTable.setVariableExtensions("gl_BaryCoordNoPerspNV", 1, &E_GL_NV_fragment_shader_barycentric);
+ BuiltInVariable("gl_BaryCoordNV", EbvBaryCoordNV, symbolTable);
+ BuiltInVariable("gl_BaryCoordNoPerspNV", EbvBaryCoordNoPerspNV, symbolTable);
+ }
+
+ if ((profile != EEsProfile && version >= 450) ||
+ (profile == EEsProfile && version >= 310)) {
+ symbolTable.setVariableExtensions("gl_FragSizeEXT", 1, &E_GL_EXT_fragment_invocation_density);
+ symbolTable.setVariableExtensions("gl_FragInvocationCountEXT", 1, &E_GL_EXT_fragment_invocation_density);
+ BuiltInVariable("gl_FragSizeEXT", EbvFragSizeEXT, symbolTable);
+ BuiltInVariable("gl_FragInvocationCountEXT", EbvFragInvocationCountEXT, symbolTable);
+ }
+
+ symbolTable.setVariableExtensions("gl_FragDepthEXT", 1, &E_GL_EXT_frag_depth);
+
+ symbolTable.setFunctionExtensions("clockARB", 1, &E_GL_ARB_shader_clock);
+ symbolTable.setFunctionExtensions("clock2x32ARB", 1, &E_GL_ARB_shader_clock);
+
+ symbolTable.setFunctionExtensions("clockRealtimeEXT", 1, &E_GL_EXT_shader_realtime_clock);
+ symbolTable.setFunctionExtensions("clockRealtime2x32EXT", 1, &E_GL_EXT_shader_realtime_clock);
+
+ if (profile == EEsProfile && version < 320) {
+ symbolTable.setVariableExtensions("gl_PrimitiveID", Num_AEP_geometry_shader, AEP_geometry_shader);
+ symbolTable.setVariableExtensions("gl_Layer", Num_AEP_geometry_shader, AEP_geometry_shader);
+ }
+
+ if (profile == EEsProfile && version < 320) {
+ symbolTable.setFunctionExtensions("imageAtomicAdd", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicMin", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicMax", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicAnd", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicOr", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicXor", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicExchange", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic);
+ }
+
+ symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
+ BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
+ symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
+ BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
+ if (version >= 300 /* both ES and non-ES */) {
+ symbolTable.setVariableExtensions("gl_ViewID_OVR", Num_OVR_multiview_EXTs, OVR_multiview_EXTs);
+ BuiltInVariable("gl_ViewID_OVR", EbvViewIndex, symbolTable);
+ }
+
+ // GL_ARB_shader_ballot
+ if (profile != EEsProfile) {
+ symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot);
+
+ BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable);
+ BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable);
+
+ if (spvVersion.vulkan > 0)
+ // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan
+ SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable);
+ else
+ BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable);
+ }
+
+ // GL_KHR_shader_subgroup
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 140)) {
+ symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+
+ BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable);
+ BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable);
+ BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable);
+
+ symbolTable.setFunctionExtensions("subgroupBarrier", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setFunctionExtensions("subgroupMemoryBarrier", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setFunctionExtensions("subgroupMemoryBarrierBuffer", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setFunctionExtensions("subgroupMemoryBarrierImage", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setFunctionExtensions("subgroupElect", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setFunctionExtensions("subgroupAll", 1, &E_GL_KHR_shader_subgroup_vote);
+ symbolTable.setFunctionExtensions("subgroupAny", 1, &E_GL_KHR_shader_subgroup_vote);
+ symbolTable.setFunctionExtensions("subgroupAllEqual", 1, &E_GL_KHR_shader_subgroup_vote);
+ symbolTable.setFunctionExtensions("subgroupBroadcast", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setFunctionExtensions("subgroupBroadcastFirst", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setFunctionExtensions("subgroupBallot", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setFunctionExtensions("subgroupInverseBallot", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setFunctionExtensions("subgroupBallotBitExtract", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setFunctionExtensions("subgroupBallotBitCount", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setFunctionExtensions("subgroupBallotInclusiveBitCount", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setFunctionExtensions("subgroupBallotExclusiveBitCount", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setFunctionExtensions("subgroupBallotFindLSB", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setFunctionExtensions("subgroupBallotFindMSB", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setFunctionExtensions("subgroupShuffle", 1, &E_GL_KHR_shader_subgroup_shuffle);
+ symbolTable.setFunctionExtensions("subgroupShuffleXor", 1, &E_GL_KHR_shader_subgroup_shuffle);
+ symbolTable.setFunctionExtensions("subgroupShuffleUp", 1, &E_GL_KHR_shader_subgroup_shuffle_relative);
+ symbolTable.setFunctionExtensions("subgroupShuffleDown", 1, &E_GL_KHR_shader_subgroup_shuffle_relative);
+ symbolTable.setFunctionExtensions("subgroupAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupMul", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupMin", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupMax", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupAnd", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupOr", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupXor", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupInclusiveAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupInclusiveMul", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupInclusiveMin", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupInclusiveMax", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupInclusiveAnd", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupInclusiveOr", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupInclusiveXor", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupExclusiveAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupExclusiveMul", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupExclusiveMin", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupExclusiveMax", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupExclusiveAnd", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupExclusiveOr", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupExclusiveXor", 1, &E_GL_KHR_shader_subgroup_arithmetic);
+ symbolTable.setFunctionExtensions("subgroupClusteredAdd", 1, &E_GL_KHR_shader_subgroup_clustered);
+ symbolTable.setFunctionExtensions("subgroupClusteredMul", 1, &E_GL_KHR_shader_subgroup_clustered);
+ symbolTable.setFunctionExtensions("subgroupClusteredMin", 1, &E_GL_KHR_shader_subgroup_clustered);
+ symbolTable.setFunctionExtensions("subgroupClusteredMax", 1, &E_GL_KHR_shader_subgroup_clustered);
+ symbolTable.setFunctionExtensions("subgroupClusteredAnd", 1, &E_GL_KHR_shader_subgroup_clustered);
+ symbolTable.setFunctionExtensions("subgroupClusteredOr", 1, &E_GL_KHR_shader_subgroup_clustered);
+ symbolTable.setFunctionExtensions("subgroupClusteredXor", 1, &E_GL_KHR_shader_subgroup_clustered);
+ symbolTable.setFunctionExtensions("subgroupQuadBroadcast", 1, &E_GL_KHR_shader_subgroup_quad);
+ symbolTable.setFunctionExtensions("subgroupQuadSwapHorizontal", 1, &E_GL_KHR_shader_subgroup_quad);
+ symbolTable.setFunctionExtensions("subgroupQuadSwapVertical", 1, &E_GL_KHR_shader_subgroup_quad);
+ symbolTable.setFunctionExtensions("subgroupQuadSwapDiagonal", 1, &E_GL_KHR_shader_subgroup_quad);
+ symbolTable.setFunctionExtensions("subgroupPartitionNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedAddNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedMulNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedMinNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedMaxNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedAndNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedOrNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedXorNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveAddNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveMulNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveMinNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveMaxNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveAndNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveOrNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveXorNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveAddNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveMulNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveMinNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveMaxNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveAndNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveOrNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+ symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveXorNV", 1, &E_GL_NV_shader_subgroup_partitioned);
+
+ // GL_NV_shader_sm_builtins
+ symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable);
+ BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable);
+ BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
+ BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
+ }
+
+ if (profile == EEsProfile) {
+ symbolTable.setFunctionExtensions("shadow2DEXT", 1, &E_GL_EXT_shadow_samplers);
+ symbolTable.setFunctionExtensions("shadow2DProjEXT", 1, &E_GL_EXT_shadow_samplers);
+ }
+
+ if (spvVersion.vulkan > 0) {
+ symbolTable.setVariableExtensions("gl_ScopeDevice", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_ScopeWorkgroup", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_ScopeSubgroup", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_ScopeInvocation", 1, &E_GL_KHR_memory_scope_semantics);
+
+ symbolTable.setVariableExtensions("gl_SemanticsRelaxed", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_SemanticsAcquire", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_SemanticsRelease", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_SemanticsAcquireRelease", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_SemanticsMakeAvailable", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_SemanticsMakeVisible", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_SemanticsVolatile", 1, &E_GL_KHR_memory_scope_semantics);
+
+ symbolTable.setVariableExtensions("gl_StorageSemanticsNone", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_StorageSemanticsBuffer", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_StorageSemanticsShared", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_StorageSemanticsImage", 1, &E_GL_KHR_memory_scope_semantics);
+ symbolTable.setVariableExtensions("gl_StorageSemanticsOutput", 1, &E_GL_KHR_memory_scope_semantics);
+ }
+
+ symbolTable.setFunctionExtensions("helperInvocationEXT", 1, &E_GL_EXT_demote_to_helper_invocation);
+#endif
+ break;
+
+ case EShLangCompute:
+ BuiltInVariable("gl_NumWorkGroups", EbvNumWorkGroups, symbolTable);
+ BuiltInVariable("gl_WorkGroupSize", EbvWorkGroupSize, symbolTable);
+ BuiltInVariable("gl_WorkGroupID", EbvWorkGroupId, symbolTable);
+ BuiltInVariable("gl_LocalInvocationID", EbvLocalInvocationId, symbolTable);
+ BuiltInVariable("gl_GlobalInvocationID", EbvGlobalInvocationId, symbolTable);
+ BuiltInVariable("gl_LocalInvocationIndex", EbvLocalInvocationIndex, symbolTable);
+ BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
+ BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
+
+#ifndef GLSLANG_WEB
+ if ((profile != EEsProfile && version >= 140) ||
+ (profile == EEsProfile && version >= 310)) {
+ symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
+ symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
+ }
+
+ if (profile != EEsProfile && version < 430) {
+ symbolTable.setVariableExtensions("gl_NumWorkGroups", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_WorkGroupSize", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_WorkGroupID", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_LocalInvocationID", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_GlobalInvocationID", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_LocalInvocationIndex", 1, &E_GL_ARB_compute_shader);
+
+ symbolTable.setVariableExtensions("gl_MaxComputeWorkGroupCount", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeWorkGroupSize", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeUniformComponents", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeTextureImageUnits", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeImageUniforms", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeAtomicCounters", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeAtomicCounterBuffers", 1, &E_GL_ARB_compute_shader);
+
+ symbolTable.setFunctionExtensions("barrier", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setFunctionExtensions("memoryBarrierAtomicCounter", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setFunctionExtensions("memoryBarrierBuffer", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setFunctionExtensions("memoryBarrierImage", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setFunctionExtensions("memoryBarrierShared", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_ARB_compute_shader);
+ }
+
+ symbolTable.setFunctionExtensions("controlBarrier", 1, &E_GL_KHR_memory_scope_semantics);
+
+ // GL_ARB_shader_ballot
+ if (profile != EEsProfile) {
+ symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot);
+
+ BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable);
+ BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable);
+
+ if (spvVersion.vulkan > 0)
+ // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan
+ SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable);
+ else
+ BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable);
+ }
+
+ // GL_KHR_shader_subgroup
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 140)) {
+ symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+
+ BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable);
+ BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable);
+ BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable);
+
+ // GL_NV_shader_sm_builtins
+ symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable);
+ BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable);
+ BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
+ BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
+ }
+
+ // GL_KHR_shader_subgroup
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 140)) {
+ symbolTable.setVariableExtensions("gl_NumSubgroups", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupID", 1, &E_GL_KHR_shader_subgroup_basic);
+
+ BuiltInVariable("gl_NumSubgroups", EbvNumSubgroups, symbolTable);
+ BuiltInVariable("gl_SubgroupID", EbvSubgroupID, symbolTable);
+
+ symbolTable.setFunctionExtensions("subgroupMemoryBarrierShared", 1, &E_GL_KHR_shader_subgroup_basic);
+ }
+
+ {
+ const char *coopExt[2] = { E_GL_NV_cooperative_matrix, E_GL_NV_integer_cooperative_matrix };
+ symbolTable.setFunctionExtensions("coopMatLoadNV", 2, coopExt);
+ symbolTable.setFunctionExtensions("coopMatStoreNV", 2, coopExt);
+ symbolTable.setFunctionExtensions("coopMatMulAddNV", 2, coopExt);
+ }
+
+ if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
+ symbolTable.setFunctionExtensions("dFdx", 1, &E_GL_NV_compute_shader_derivatives);
+ symbolTable.setFunctionExtensions("dFdy", 1, &E_GL_NV_compute_shader_derivatives);
+ symbolTable.setFunctionExtensions("fwidth", 1, &E_GL_NV_compute_shader_derivatives);
+ symbolTable.setFunctionExtensions("dFdxFine", 1, &E_GL_NV_compute_shader_derivatives);
+ symbolTable.setFunctionExtensions("dFdyFine", 1, &E_GL_NV_compute_shader_derivatives);
+ symbolTable.setFunctionExtensions("fwidthFine", 1, &E_GL_NV_compute_shader_derivatives);
+ symbolTable.setFunctionExtensions("dFdxCoarse", 1, &E_GL_NV_compute_shader_derivatives);
+ symbolTable.setFunctionExtensions("dFdyCoarse", 1, &E_GL_NV_compute_shader_derivatives);
+ symbolTable.setFunctionExtensions("fwidthCoarse", 1, &E_GL_NV_compute_shader_derivatives);
+ }
+#endif
+ break;
+
+#ifndef GLSLANG_WEB
+ case EShLangRayGenNV:
+ case EShLangIntersectNV:
+ case EShLangAnyHitNV:
+ case EShLangClosestHitNV:
+ case EShLangMissNV:
+ case EShLangCallableNV:
+ if (profile != EEsProfile && version >= 460) {
+ symbolTable.setVariableExtensions("gl_LaunchIDNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_LaunchSizeNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_PrimitiveID", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_InstanceID", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_InstanceCustomIndexNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_WorldRayOriginNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_WorldRayDirectionNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_ObjectRayOriginNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_ObjectRayDirectionNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_RayTminNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_RayTmaxNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_HitTNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_HitKindNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_ObjectToWorldNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_WorldToObjectNV", 1, &E_GL_NV_ray_tracing);
+ symbolTable.setVariableExtensions("gl_IncomingRayFlagsNV", 1, &E_GL_NV_ray_tracing);
+
+ symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
+
+ BuiltInVariable("gl_LaunchIDNV", EbvLaunchIdNV, symbolTable);
+ BuiltInVariable("gl_LaunchSizeNV", EbvLaunchSizeNV, symbolTable);
+ BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable);
+ BuiltInVariable("gl_InstanceID", EbvInstanceId, symbolTable);
+ BuiltInVariable("gl_InstanceCustomIndexNV", EbvInstanceCustomIndexNV,symbolTable);
+ BuiltInVariable("gl_WorldRayOriginNV", EbvWorldRayOriginNV, symbolTable);
+ BuiltInVariable("gl_WorldRayDirectionNV", EbvWorldRayDirectionNV, symbolTable);
+ BuiltInVariable("gl_ObjectRayOriginNV", EbvObjectRayOriginNV, symbolTable);
+ BuiltInVariable("gl_ObjectRayDirectionNV", EbvObjectRayDirectionNV, symbolTable);
+ BuiltInVariable("gl_RayTminNV", EbvRayTminNV, symbolTable);
+ BuiltInVariable("gl_RayTmaxNV", EbvRayTmaxNV, symbolTable);
+ BuiltInVariable("gl_HitTNV", EbvHitTNV, symbolTable);
+ BuiltInVariable("gl_HitKindNV", EbvHitKindNV, symbolTable);
+ BuiltInVariable("gl_ObjectToWorldNV", EbvObjectToWorldNV, symbolTable);
+ BuiltInVariable("gl_WorldToObjectNV", EbvWorldToObjectNV, symbolTable);
+ BuiltInVariable("gl_IncomingRayFlagsNV", EbvIncomingRayFlagsNV, symbolTable);
+ BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
+
+ // GL_ARB_shader_ballot
+ symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot);
+
+ BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable);
+ BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable);
+
+ if (spvVersion.vulkan > 0)
+ // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan
+ SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable);
+ else
+ BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable);
+
+ // GL_KHR_shader_subgroup
+ symbolTable.setVariableExtensions("gl_NumSubgroups", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupID", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+
+ BuiltInVariable("gl_NumSubgroups", EbvNumSubgroups, symbolTable);
+ BuiltInVariable("gl_SubgroupID", EbvSubgroupID, symbolTable);
+ BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable);
+ BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable);
+ BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable);
+
+ // GL_NV_shader_sm_builtins
+ symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable);
+ BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable);
+ BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
+ BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
+ }
+ break;
+
+ case EShLangMeshNV:
+ if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
+ // per-vertex builtins
+ symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_Position", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_PointSize", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_ClipDistance", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_CullDistance", 1, &E_GL_NV_mesh_shader);
+
+ BuiltInVariable("gl_MeshVerticesNV", "gl_Position", EbvPosition, symbolTable);
+ BuiltInVariable("gl_MeshVerticesNV", "gl_PointSize", EbvPointSize, symbolTable);
+ BuiltInVariable("gl_MeshVerticesNV", "gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_MeshVerticesNV", "gl_CullDistance", EbvCullDistance, symbolTable);
+
+ symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_PositionPerViewNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_ClipDistancePerViewNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_CullDistancePerViewNV", 1, &E_GL_NV_mesh_shader);
+
+ BuiltInVariable("gl_MeshVerticesNV", "gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable);
+ BuiltInVariable("gl_MeshVerticesNV", "gl_ClipDistancePerViewNV", EbvClipDistancePerViewNV, symbolTable);
+ BuiltInVariable("gl_MeshVerticesNV", "gl_CullDistancePerViewNV", EbvCullDistancePerViewNV, symbolTable);
+
+ // per-primitive builtins
+ symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_PrimitiveID", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_Layer", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_ViewportIndex", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_ViewportMask", 1, &E_GL_NV_mesh_shader);
+
+ BuiltInVariable("gl_MeshPrimitivesNV", "gl_PrimitiveID", EbvPrimitiveId, symbolTable);
+ BuiltInVariable("gl_MeshPrimitivesNV", "gl_Layer", EbvLayer, symbolTable);
+ BuiltInVariable("gl_MeshPrimitivesNV", "gl_ViewportIndex", EbvViewportIndex, symbolTable);
+ BuiltInVariable("gl_MeshPrimitivesNV", "gl_ViewportMask", EbvViewportMaskNV, symbolTable);
+
+ // per-view per-primitive builtins
+ symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_LayerPerViewNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_ViewportMaskPerViewNV", 1, &E_GL_NV_mesh_shader);
+
+ BuiltInVariable("gl_MeshPrimitivesNV", "gl_LayerPerViewNV", EbvLayerPerViewNV, symbolTable);
+ BuiltInVariable("gl_MeshPrimitivesNV", "gl_ViewportMaskPerViewNV", EbvViewportMaskPerViewNV, symbolTable);
+
+ // other builtins
+ symbolTable.setVariableExtensions("gl_PrimitiveCountNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_PrimitiveIndicesNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshViewCountNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshViewIndicesNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_WorkGroupSize", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_WorkGroupID", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_LocalInvocationID", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_GlobalInvocationID", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_LocalInvocationIndex", 1, &E_GL_NV_mesh_shader);
+
+ BuiltInVariable("gl_PrimitiveCountNV", EbvPrimitiveCountNV, symbolTable);
+ BuiltInVariable("gl_PrimitiveIndicesNV", EbvPrimitiveIndicesNV, symbolTable);
+ BuiltInVariable("gl_MeshViewCountNV", EbvMeshViewCountNV, symbolTable);
+ BuiltInVariable("gl_MeshViewIndicesNV", EbvMeshViewIndicesNV, symbolTable);
+ BuiltInVariable("gl_WorkGroupSize", EbvWorkGroupSize, symbolTable);
+ BuiltInVariable("gl_WorkGroupID", EbvWorkGroupId, symbolTable);
+ BuiltInVariable("gl_LocalInvocationID", EbvLocalInvocationId, symbolTable);
+ BuiltInVariable("gl_GlobalInvocationID", EbvGlobalInvocationId, symbolTable);
+ BuiltInVariable("gl_LocalInvocationIndex", EbvLocalInvocationIndex, symbolTable);
+
+ // builtin constants
+ symbolTable.setVariableExtensions("gl_MaxMeshOutputVerticesNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MaxMeshOutputPrimitivesNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MaxMeshWorkGroupSizeNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MaxMeshViewCountNV", 1, &E_GL_NV_mesh_shader);
+
+ // builtin functions
+ symbolTable.setFunctionExtensions("barrier", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setFunctionExtensions("memoryBarrierShared", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_NV_mesh_shader);
+ }
+
+ if (profile != EEsProfile && version >= 450) {
+ // GL_EXT_device_group
+ symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
+ BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
+
+ // GL_ARB_shader_draw_parameters
+ symbolTable.setVariableExtensions("gl_DrawIDARB", 1, &E_GL_ARB_shader_draw_parameters);
+ BuiltInVariable("gl_DrawIDARB", EbvDrawId, symbolTable);
+ if (version >= 460) {
+ BuiltInVariable("gl_DrawID", EbvDrawId, symbolTable);
+ }
+
+ // GL_ARB_shader_ballot
+ symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot);
+
+ BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable);
+ BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable);
+
+ if (spvVersion.vulkan > 0)
+ // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan
+ SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable);
+ else
+ BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable);
+ }
+
+ // GL_KHR_shader_subgroup
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 140)) {
+ symbolTable.setVariableExtensions("gl_NumSubgroups", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupID", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+
+ BuiltInVariable("gl_NumSubgroups", EbvNumSubgroups, symbolTable);
+ BuiltInVariable("gl_SubgroupID", EbvSubgroupID, symbolTable);
+ BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable);
+ BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable);
+ BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable);
+
+ symbolTable.setFunctionExtensions("subgroupMemoryBarrierShared", 1, &E_GL_KHR_shader_subgroup_basic);
+
+ // GL_NV_shader_sm_builtins
+ symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable);
+ BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable);
+ BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
+ BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
+ }
+ break;
+
+ case EShLangTaskNV:
+ if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
+ symbolTable.setVariableExtensions("gl_TaskCountNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_WorkGroupSize", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_WorkGroupID", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_LocalInvocationID", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_GlobalInvocationID", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_LocalInvocationIndex", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshViewCountNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MeshViewIndicesNV", 1, &E_GL_NV_mesh_shader);
+
+ BuiltInVariable("gl_TaskCountNV", EbvTaskCountNV, symbolTable);
+ BuiltInVariable("gl_WorkGroupSize", EbvWorkGroupSize, symbolTable);
+ BuiltInVariable("gl_WorkGroupID", EbvWorkGroupId, symbolTable);
+ BuiltInVariable("gl_LocalInvocationID", EbvLocalInvocationId, symbolTable);
+ BuiltInVariable("gl_GlobalInvocationID", EbvGlobalInvocationId, symbolTable);
+ BuiltInVariable("gl_LocalInvocationIndex", EbvLocalInvocationIndex, symbolTable);
+ BuiltInVariable("gl_MeshViewCountNV", EbvMeshViewCountNV, symbolTable);
+ BuiltInVariable("gl_MeshViewIndicesNV", EbvMeshViewIndicesNV, symbolTable);
+
+ symbolTable.setVariableExtensions("gl_MaxTaskWorkGroupSizeNV", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setVariableExtensions("gl_MaxMeshViewCountNV", 1, &E_GL_NV_mesh_shader);
+
+ symbolTable.setFunctionExtensions("barrier", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setFunctionExtensions("memoryBarrierShared", 1, &E_GL_NV_mesh_shader);
+ symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_NV_mesh_shader);
+ }
+
+ if (profile != EEsProfile && version >= 450) {
+ // GL_EXT_device_group
+ symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
+ BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
+
+ // GL_ARB_shader_draw_parameters
+ symbolTable.setVariableExtensions("gl_DrawIDARB", 1, &E_GL_ARB_shader_draw_parameters);
+ BuiltInVariable("gl_DrawIDARB", EbvDrawId, symbolTable);
+ if (version >= 460) {
+ BuiltInVariable("gl_DrawID", EbvDrawId, symbolTable);
+ }
+
+ // GL_ARB_shader_ballot
+ symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot);
+
+ BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable);
+ BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable);
+
+ if (spvVersion.vulkan > 0)
+ // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan
+ SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable);
+ else
+ BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable);
+ }
+
+ // GL_KHR_shader_subgroup
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 140)) {
+ symbolTable.setVariableExtensions("gl_NumSubgroups", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupID", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic);
+ symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+ symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot);
+
+ BuiltInVariable("gl_NumSubgroups", EbvNumSubgroups, symbolTable);
+ BuiltInVariable("gl_SubgroupID", EbvSubgroupID, symbolTable);
+ BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable);
+ BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable);
+ BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable);
+ BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable);
+
+ symbolTable.setFunctionExtensions("subgroupMemoryBarrierShared", 1, &E_GL_KHR_shader_subgroup_basic);
+
+ // GL_NV_shader_sm_builtins
+ symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins);
+ BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable);
+ BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable);
+ BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
+ BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
+ }
+ break;
+#endif
+
+ default:
+ assert(false && "Language not supported");
+ break;
+ }
+
+ //
+ // Next, identify which built-ins have a mapping to an operator.
+ // If PureOperatorBuiltins is false, those that are not identified as such are
+ // expected to be resolved through a library of functions, versus as
+ // operations.
+ //
+
+ relateTabledBuiltins(version, profile, spvVersion, language, symbolTable);
+
+#ifndef GLSLANG_WEB
+ symbolTable.relateToOperator("doubleBitsToInt64", EOpDoubleBitsToInt64);
+ symbolTable.relateToOperator("doubleBitsToUint64", EOpDoubleBitsToUint64);
+ symbolTable.relateToOperator("int64BitsToDouble", EOpInt64BitsToDouble);
+ symbolTable.relateToOperator("uint64BitsToDouble", EOpUint64BitsToDouble);
+ symbolTable.relateToOperator("halfBitsToInt16", EOpFloat16BitsToInt16);
+ symbolTable.relateToOperator("halfBitsToUint16", EOpFloat16BitsToUint16);
+ symbolTable.relateToOperator("float16BitsToInt16", EOpFloat16BitsToInt16);
+ symbolTable.relateToOperator("float16BitsToUint16", EOpFloat16BitsToUint16);
+ symbolTable.relateToOperator("int16BitsToFloat16", EOpInt16BitsToFloat16);
+ symbolTable.relateToOperator("uint16BitsToFloat16", EOpUint16BitsToFloat16);
+
+ symbolTable.relateToOperator("int16BitsToHalf", EOpInt16BitsToFloat16);
+ symbolTable.relateToOperator("uint16BitsToHalf", EOpUint16BitsToFloat16);
+
+ symbolTable.relateToOperator("packSnorm4x8", EOpPackSnorm4x8);
+ symbolTable.relateToOperator("unpackSnorm4x8", EOpUnpackSnorm4x8);
+ symbolTable.relateToOperator("packUnorm4x8", EOpPackUnorm4x8);
+ symbolTable.relateToOperator("unpackUnorm4x8", EOpUnpackUnorm4x8);
+
+ symbolTable.relateToOperator("packDouble2x32", EOpPackDouble2x32);
+ symbolTable.relateToOperator("unpackDouble2x32", EOpUnpackDouble2x32);
+
+ symbolTable.relateToOperator("packInt2x32", EOpPackInt2x32);
+ symbolTable.relateToOperator("unpackInt2x32", EOpUnpackInt2x32);
+ symbolTable.relateToOperator("packUint2x32", EOpPackUint2x32);
+ symbolTable.relateToOperator("unpackUint2x32", EOpUnpackUint2x32);
+
+ symbolTable.relateToOperator("packInt2x16", EOpPackInt2x16);
+ symbolTable.relateToOperator("unpackInt2x16", EOpUnpackInt2x16);
+ symbolTable.relateToOperator("packUint2x16", EOpPackUint2x16);
+ symbolTable.relateToOperator("unpackUint2x16", EOpUnpackUint2x16);
+
+ symbolTable.relateToOperator("packInt4x16", EOpPackInt4x16);
+ symbolTable.relateToOperator("unpackInt4x16", EOpUnpackInt4x16);
+ symbolTable.relateToOperator("packUint4x16", EOpPackUint4x16);
+ symbolTable.relateToOperator("unpackUint4x16", EOpUnpackUint4x16);
+ symbolTable.relateToOperator("packFloat2x16", EOpPackFloat2x16);
+ symbolTable.relateToOperator("unpackFloat2x16", EOpUnpackFloat2x16);
+
+ symbolTable.relateToOperator("pack16", EOpPack16);
+ symbolTable.relateToOperator("pack32", EOpPack32);
+ symbolTable.relateToOperator("pack64", EOpPack64);
+
+ symbolTable.relateToOperator("unpack32", EOpUnpack32);
+ symbolTable.relateToOperator("unpack16", EOpUnpack16);
+ symbolTable.relateToOperator("unpack8", EOpUnpack8);
+
+ symbolTable.relateToOperator("controlBarrier", EOpBarrier);
+ symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierAtomicCounter);
+ symbolTable.relateToOperator("memoryBarrierImage", EOpMemoryBarrierImage);
+
+ symbolTable.relateToOperator("atomicLoad", EOpAtomicLoad);
+ symbolTable.relateToOperator("atomicStore", EOpAtomicStore);
+
+ symbolTable.relateToOperator("atomicCounterIncrement", EOpAtomicCounterIncrement);
+ symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement);
+ symbolTable.relateToOperator("atomicCounter", EOpAtomicCounter);
+
+ symbolTable.relateToOperator("clockARB", EOpReadClockSubgroupKHR);
+ symbolTable.relateToOperator("clock2x32ARB", EOpReadClockSubgroupKHR);
+
+ symbolTable.relateToOperator("clockRealtimeEXT", EOpReadClockDeviceKHR);
+ symbolTable.relateToOperator("clockRealtime2x32EXT", EOpReadClockDeviceKHR);
+
+ if (profile != EEsProfile && version >= 460) {
+ symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicCounterAdd);
+ symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicCounterSubtract);
+ symbolTable.relateToOperator("atomicCounterMin", EOpAtomicCounterMin);
+ symbolTable.relateToOperator("atomicCounterMax", EOpAtomicCounterMax);
+ symbolTable.relateToOperator("atomicCounterAnd", EOpAtomicCounterAnd);
+ symbolTable.relateToOperator("atomicCounterOr", EOpAtomicCounterOr);
+ symbolTable.relateToOperator("atomicCounterXor", EOpAtomicCounterXor);
+ symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicCounterExchange);
+ symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap);
+ }
+
+ symbolTable.relateToOperator("fma", EOpFma);
+ symbolTable.relateToOperator("frexp", EOpFrexp);
+ symbolTable.relateToOperator("ldexp", EOpLdexp);
+ symbolTable.relateToOperator("uaddCarry", EOpAddCarry);
+ symbolTable.relateToOperator("usubBorrow", EOpSubBorrow);
+ symbolTable.relateToOperator("umulExtended", EOpUMulExtended);
+ symbolTable.relateToOperator("imulExtended", EOpIMulExtended);
+ symbolTable.relateToOperator("bitfieldExtract", EOpBitfieldExtract);
+ symbolTable.relateToOperator("bitfieldInsert", EOpBitfieldInsert);
+ symbolTable.relateToOperator("bitfieldReverse", EOpBitFieldReverse);
+ symbolTable.relateToOperator("bitCount", EOpBitCount);
+ symbolTable.relateToOperator("findLSB", EOpFindLSB);
+ symbolTable.relateToOperator("findMSB", EOpFindMSB);
+
+ symbolTable.relateToOperator("helperInvocationEXT", EOpIsHelperInvocation);
+
+ symbolTable.relateToOperator("countLeadingZeros", EOpCountLeadingZeros);
+ symbolTable.relateToOperator("countTrailingZeros", EOpCountTrailingZeros);
+ symbolTable.relateToOperator("absoluteDifference", EOpAbsDifference);
+ symbolTable.relateToOperator("addSaturate", EOpAddSaturate);
+ symbolTable.relateToOperator("subtractSaturate", EOpSubSaturate);
+ symbolTable.relateToOperator("average", EOpAverage);
+ symbolTable.relateToOperator("averageRounded", EOpAverageRounded);
+ symbolTable.relateToOperator("multiply32x16", EOpMul32x16);
+
+ if (PureOperatorBuiltins) {
+ symbolTable.relateToOperator("imageSize", EOpImageQuerySize);
+ symbolTable.relateToOperator("imageSamples", EOpImageQuerySamples);
+ symbolTable.relateToOperator("imageLoad", EOpImageLoad);
+ symbolTable.relateToOperator("imageStore", EOpImageStore);
+ symbolTable.relateToOperator("imageAtomicAdd", EOpImageAtomicAdd);
+ symbolTable.relateToOperator("imageAtomicMin", EOpImageAtomicMin);
+ symbolTable.relateToOperator("imageAtomicMax", EOpImageAtomicMax);
+ symbolTable.relateToOperator("imageAtomicAnd", EOpImageAtomicAnd);
+ symbolTable.relateToOperator("imageAtomicOr", EOpImageAtomicOr);
+ symbolTable.relateToOperator("imageAtomicXor", EOpImageAtomicXor);
+ symbolTable.relateToOperator("imageAtomicExchange", EOpImageAtomicExchange);
+ symbolTable.relateToOperator("imageAtomicCompSwap", EOpImageAtomicCompSwap);
+ symbolTable.relateToOperator("imageAtomicLoad", EOpImageAtomicLoad);
+ symbolTable.relateToOperator("imageAtomicStore", EOpImageAtomicStore);
+
+ symbolTable.relateToOperator("subpassLoad", EOpSubpassLoad);
+ symbolTable.relateToOperator("subpassLoadMS", EOpSubpassLoadMS);
+
+ symbolTable.relateToOperator("textureGather", EOpTextureGather);
+ symbolTable.relateToOperator("textureGatherOffset", EOpTextureGatherOffset);
+ symbolTable.relateToOperator("textureGatherOffsets", EOpTextureGatherOffsets);
+
+ symbolTable.relateToOperator("noise1", EOpNoise);
+ symbolTable.relateToOperator("noise2", EOpNoise);
+ symbolTable.relateToOperator("noise3", EOpNoise);
+ symbolTable.relateToOperator("noise4", EOpNoise);
+
+ symbolTable.relateToOperator("textureFootprintNV", EOpImageSampleFootprintNV);
+ symbolTable.relateToOperator("textureFootprintClampNV", EOpImageSampleFootprintClampNV);
+ symbolTable.relateToOperator("textureFootprintLodNV", EOpImageSampleFootprintLodNV);
+ symbolTable.relateToOperator("textureFootprintGradNV", EOpImageSampleFootprintGradNV);
+ symbolTable.relateToOperator("textureFootprintGradClampNV", EOpImageSampleFootprintGradClampNV);
+
+ if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion))
+ symbolTable.relateToOperator("ftransform", EOpFtransform);
+
+ if (spvVersion.spv == 0 && (IncludeLegacy(version, profile, spvVersion) ||
+ (profile == EEsProfile && version == 100))) {
+
+ symbolTable.relateToOperator("texture1D", EOpTexture);
+ symbolTable.relateToOperator("texture1DGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("texture1DProj", EOpTextureProj);
+ symbolTable.relateToOperator("texture1DProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("texture1DLod", EOpTextureLod);
+ symbolTable.relateToOperator("texture1DProjLod", EOpTextureProjLod);
+
+ symbolTable.relateToOperator("texture2DRect", EOpTexture);
+ symbolTable.relateToOperator("texture2DRectProj", EOpTextureProj);
+ symbolTable.relateToOperator("texture2DRectGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("texture2DRectProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("shadow2DRect", EOpTexture);
+ symbolTable.relateToOperator("shadow2DRectProj", EOpTextureProj);
+ symbolTable.relateToOperator("shadow2DRectGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("shadow2DRectProjGradARB", EOpTextureProjGrad);
+
+ symbolTable.relateToOperator("texture2D", EOpTexture);
+ symbolTable.relateToOperator("texture2DProj", EOpTextureProj);
+ symbolTable.relateToOperator("texture2DGradEXT", EOpTextureGrad);
+ symbolTable.relateToOperator("texture2DGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("texture2DProjGradEXT", EOpTextureProjGrad);
+ symbolTable.relateToOperator("texture2DProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("texture2DLod", EOpTextureLod);
+ symbolTable.relateToOperator("texture2DLodEXT", EOpTextureLod);
+ symbolTable.relateToOperator("texture2DProjLod", EOpTextureProjLod);
+ symbolTable.relateToOperator("texture2DProjLodEXT", EOpTextureProjLod);
+
+ symbolTable.relateToOperator("texture3D", EOpTexture);
+ symbolTable.relateToOperator("texture3DGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("texture3DProj", EOpTextureProj);
+ symbolTable.relateToOperator("texture3DProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("texture3DLod", EOpTextureLod);
+ symbolTable.relateToOperator("texture3DProjLod", EOpTextureProjLod);
+ symbolTable.relateToOperator("textureCube", EOpTexture);
+ symbolTable.relateToOperator("textureCubeGradEXT", EOpTextureGrad);
+ symbolTable.relateToOperator("textureCubeGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("textureCubeLod", EOpTextureLod);
+ symbolTable.relateToOperator("textureCubeLodEXT", EOpTextureLod);
+ symbolTable.relateToOperator("shadow1D", EOpTexture);
+ symbolTable.relateToOperator("shadow1DGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("shadow2D", EOpTexture);
+ symbolTable.relateToOperator("shadow2DGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("shadow1DProj", EOpTextureProj);
+ symbolTable.relateToOperator("shadow2DProj", EOpTextureProj);
+ symbolTable.relateToOperator("shadow1DProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("shadow2DProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("shadow1DLod", EOpTextureLod);
+ symbolTable.relateToOperator("shadow2DLod", EOpTextureLod);
+ symbolTable.relateToOperator("shadow1DProjLod", EOpTextureProjLod);
+ symbolTable.relateToOperator("shadow2DProjLod", EOpTextureProjLod);
+ }
+
+ if (profile != EEsProfile) {
+ symbolTable.relateToOperator("sparseTextureARB", EOpSparseTexture);
+ symbolTable.relateToOperator("sparseTextureLodARB", EOpSparseTextureLod);
+ symbolTable.relateToOperator("sparseTextureOffsetARB", EOpSparseTextureOffset);
+ symbolTable.relateToOperator("sparseTexelFetchARB", EOpSparseTextureFetch);
+ symbolTable.relateToOperator("sparseTexelFetchOffsetARB", EOpSparseTextureFetchOffset);
+ symbolTable.relateToOperator("sparseTextureLodOffsetARB", EOpSparseTextureLodOffset);
+ symbolTable.relateToOperator("sparseTextureGradARB", EOpSparseTextureGrad);
+ symbolTable.relateToOperator("sparseTextureGradOffsetARB", EOpSparseTextureGradOffset);
+ symbolTable.relateToOperator("sparseTextureGatherARB", EOpSparseTextureGather);
+ symbolTable.relateToOperator("sparseTextureGatherOffsetARB", EOpSparseTextureGatherOffset);
+ symbolTable.relateToOperator("sparseTextureGatherOffsetsARB", EOpSparseTextureGatherOffsets);
+ symbolTable.relateToOperator("sparseImageLoadARB", EOpSparseImageLoad);
+ symbolTable.relateToOperator("sparseTexelsResidentARB", EOpSparseTexelsResident);
+
+ symbolTable.relateToOperator("sparseTextureClampARB", EOpSparseTextureClamp);
+ symbolTable.relateToOperator("sparseTextureOffsetClampARB", EOpSparseTextureOffsetClamp);
+ symbolTable.relateToOperator("sparseTextureGradClampARB", EOpSparseTextureGradClamp);
+ symbolTable.relateToOperator("sparseTextureGradOffsetClampARB", EOpSparseTextureGradOffsetClamp);
+ symbolTable.relateToOperator("textureClampARB", EOpTextureClamp);
+ symbolTable.relateToOperator("textureOffsetClampARB", EOpTextureOffsetClamp);
+ symbolTable.relateToOperator("textureGradClampARB", EOpTextureGradClamp);
+ symbolTable.relateToOperator("textureGradOffsetClampARB", EOpTextureGradOffsetClamp);
+
+ symbolTable.relateToOperator("ballotARB", EOpBallot);
+ symbolTable.relateToOperator("readInvocationARB", EOpReadInvocation);
+ symbolTable.relateToOperator("readFirstInvocationARB", EOpReadFirstInvocation);
+
+ if (version >= 430) {
+ symbolTable.relateToOperator("anyInvocationARB", EOpAnyInvocation);
+ symbolTable.relateToOperator("allInvocationsARB", EOpAllInvocations);
+ symbolTable.relateToOperator("allInvocationsEqualARB", EOpAllInvocationsEqual);
+ }
+ if (version >= 460) {
+ symbolTable.relateToOperator("anyInvocation", EOpAnyInvocation);
+ symbolTable.relateToOperator("allInvocations", EOpAllInvocations);
+ symbolTable.relateToOperator("allInvocationsEqual", EOpAllInvocationsEqual);
+ }
+ symbolTable.relateToOperator("minInvocationsAMD", EOpMinInvocations);
+ symbolTable.relateToOperator("maxInvocationsAMD", EOpMaxInvocations);
+ symbolTable.relateToOperator("addInvocationsAMD", EOpAddInvocations);
+ symbolTable.relateToOperator("minInvocationsNonUniformAMD", EOpMinInvocationsNonUniform);
+ symbolTable.relateToOperator("maxInvocationsNonUniformAMD", EOpMaxInvocationsNonUniform);
+ symbolTable.relateToOperator("addInvocationsNonUniformAMD", EOpAddInvocationsNonUniform);
+ symbolTable.relateToOperator("minInvocationsInclusiveScanAMD", EOpMinInvocationsInclusiveScan);
+ symbolTable.relateToOperator("maxInvocationsInclusiveScanAMD", EOpMaxInvocationsInclusiveScan);
+ symbolTable.relateToOperator("addInvocationsInclusiveScanAMD", EOpAddInvocationsInclusiveScan);
+ symbolTable.relateToOperator("minInvocationsInclusiveScanNonUniformAMD", EOpMinInvocationsInclusiveScanNonUniform);
+ symbolTable.relateToOperator("maxInvocationsInclusiveScanNonUniformAMD", EOpMaxInvocationsInclusiveScanNonUniform);
+ symbolTable.relateToOperator("addInvocationsInclusiveScanNonUniformAMD", EOpAddInvocationsInclusiveScanNonUniform);
+ symbolTable.relateToOperator("minInvocationsExclusiveScanAMD", EOpMinInvocationsExclusiveScan);
+ symbolTable.relateToOperator("maxInvocationsExclusiveScanAMD", EOpMaxInvocationsExclusiveScan);
+ symbolTable.relateToOperator("addInvocationsExclusiveScanAMD", EOpAddInvocationsExclusiveScan);
+ symbolTable.relateToOperator("minInvocationsExclusiveScanNonUniformAMD", EOpMinInvocationsExclusiveScanNonUniform);
+ symbolTable.relateToOperator("maxInvocationsExclusiveScanNonUniformAMD", EOpMaxInvocationsExclusiveScanNonUniform);
+ symbolTable.relateToOperator("addInvocationsExclusiveScanNonUniformAMD", EOpAddInvocationsExclusiveScanNonUniform);
+ symbolTable.relateToOperator("swizzleInvocationsAMD", EOpSwizzleInvocations);
+ symbolTable.relateToOperator("swizzleInvocationsMaskedAMD", EOpSwizzleInvocationsMasked);
+ symbolTable.relateToOperator("writeInvocationAMD", EOpWriteInvocation);
+ symbolTable.relateToOperator("mbcntAMD", EOpMbcnt);
+
+ symbolTable.relateToOperator("min3", EOpMin3);
+ symbolTable.relateToOperator("max3", EOpMax3);
+ symbolTable.relateToOperator("mid3", EOpMid3);
+
+ symbolTable.relateToOperator("cubeFaceIndexAMD", EOpCubeFaceIndex);
+ symbolTable.relateToOperator("cubeFaceCoordAMD", EOpCubeFaceCoord);
+ symbolTable.relateToOperator("timeAMD", EOpTime);
+
+ symbolTable.relateToOperator("textureGatherLodAMD", EOpTextureGatherLod);
+ symbolTable.relateToOperator("textureGatherLodOffsetAMD", EOpTextureGatherLodOffset);
+ symbolTable.relateToOperator("textureGatherLodOffsetsAMD", EOpTextureGatherLodOffsets);
+ symbolTable.relateToOperator("sparseTextureGatherLodAMD", EOpSparseTextureGatherLod);
+ symbolTable.relateToOperator("sparseTextureGatherLodOffsetAMD", EOpSparseTextureGatherLodOffset);
+ symbolTable.relateToOperator("sparseTextureGatherLodOffsetsAMD", EOpSparseTextureGatherLodOffsets);
+
+ symbolTable.relateToOperator("imageLoadLodAMD", EOpImageLoadLod);
+ symbolTable.relateToOperator("imageStoreLodAMD", EOpImageStoreLod);
+ symbolTable.relateToOperator("sparseImageLoadLodAMD", EOpSparseImageLoadLod);
+
+ symbolTable.relateToOperator("fragmentMaskFetchAMD", EOpFragmentMaskFetch);
+ symbolTable.relateToOperator("fragmentFetchAMD", EOpFragmentFetch);
+ }
+
+ // GL_KHR_shader_subgroup
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 140)) {
+ symbolTable.relateToOperator("subgroupBarrier", EOpSubgroupBarrier);
+ symbolTable.relateToOperator("subgroupMemoryBarrier", EOpSubgroupMemoryBarrier);
+ symbolTable.relateToOperator("subgroupMemoryBarrierBuffer", EOpSubgroupMemoryBarrierBuffer);
+ symbolTable.relateToOperator("subgroupMemoryBarrierImage", EOpSubgroupMemoryBarrierImage);
+ symbolTable.relateToOperator("subgroupElect", EOpSubgroupElect);
+ symbolTable.relateToOperator("subgroupAll", EOpSubgroupAll);
+ symbolTable.relateToOperator("subgroupAny", EOpSubgroupAny);
+ symbolTable.relateToOperator("subgroupAllEqual", EOpSubgroupAllEqual);
+ symbolTable.relateToOperator("subgroupBroadcast", EOpSubgroupBroadcast);
+ symbolTable.relateToOperator("subgroupBroadcastFirst", EOpSubgroupBroadcastFirst);
+ symbolTable.relateToOperator("subgroupBallot", EOpSubgroupBallot);
+ symbolTable.relateToOperator("subgroupInverseBallot", EOpSubgroupInverseBallot);
+ symbolTable.relateToOperator("subgroupBallotBitExtract", EOpSubgroupBallotBitExtract);
+ symbolTable.relateToOperator("subgroupBallotBitCount", EOpSubgroupBallotBitCount);
+ symbolTable.relateToOperator("subgroupBallotInclusiveBitCount", EOpSubgroupBallotInclusiveBitCount);
+ symbolTable.relateToOperator("subgroupBallotExclusiveBitCount", EOpSubgroupBallotExclusiveBitCount);
+ symbolTable.relateToOperator("subgroupBallotFindLSB", EOpSubgroupBallotFindLSB);
+ symbolTable.relateToOperator("subgroupBallotFindMSB", EOpSubgroupBallotFindMSB);
+ symbolTable.relateToOperator("subgroupShuffle", EOpSubgroupShuffle);
+ symbolTable.relateToOperator("subgroupShuffleXor", EOpSubgroupShuffleXor);
+ symbolTable.relateToOperator("subgroupShuffleUp", EOpSubgroupShuffleUp);
+ symbolTable.relateToOperator("subgroupShuffleDown", EOpSubgroupShuffleDown);
+ symbolTable.relateToOperator("subgroupAdd", EOpSubgroupAdd);
+ symbolTable.relateToOperator("subgroupMul", EOpSubgroupMul);
+ symbolTable.relateToOperator("subgroupMin", EOpSubgroupMin);
+ symbolTable.relateToOperator("subgroupMax", EOpSubgroupMax);
+ symbolTable.relateToOperator("subgroupAnd", EOpSubgroupAnd);
+ symbolTable.relateToOperator("subgroupOr", EOpSubgroupOr);
+ symbolTable.relateToOperator("subgroupXor", EOpSubgroupXor);
+ symbolTable.relateToOperator("subgroupInclusiveAdd", EOpSubgroupInclusiveAdd);
+ symbolTable.relateToOperator("subgroupInclusiveMul", EOpSubgroupInclusiveMul);
+ symbolTable.relateToOperator("subgroupInclusiveMin", EOpSubgroupInclusiveMin);
+ symbolTable.relateToOperator("subgroupInclusiveMax", EOpSubgroupInclusiveMax);
+ symbolTable.relateToOperator("subgroupInclusiveAnd", EOpSubgroupInclusiveAnd);
+ symbolTable.relateToOperator("subgroupInclusiveOr", EOpSubgroupInclusiveOr);
+ symbolTable.relateToOperator("subgroupInclusiveXor", EOpSubgroupInclusiveXor);
+ symbolTable.relateToOperator("subgroupExclusiveAdd", EOpSubgroupExclusiveAdd);
+ symbolTable.relateToOperator("subgroupExclusiveMul", EOpSubgroupExclusiveMul);
+ symbolTable.relateToOperator("subgroupExclusiveMin", EOpSubgroupExclusiveMin);
+ symbolTable.relateToOperator("subgroupExclusiveMax", EOpSubgroupExclusiveMax);
+ symbolTable.relateToOperator("subgroupExclusiveAnd", EOpSubgroupExclusiveAnd);
+ symbolTable.relateToOperator("subgroupExclusiveOr", EOpSubgroupExclusiveOr);
+ symbolTable.relateToOperator("subgroupExclusiveXor", EOpSubgroupExclusiveXor);
+ symbolTable.relateToOperator("subgroupClusteredAdd", EOpSubgroupClusteredAdd);
+ symbolTable.relateToOperator("subgroupClusteredMul", EOpSubgroupClusteredMul);
+ symbolTable.relateToOperator("subgroupClusteredMin", EOpSubgroupClusteredMin);
+ symbolTable.relateToOperator("subgroupClusteredMax", EOpSubgroupClusteredMax);
+ symbolTable.relateToOperator("subgroupClusteredAnd", EOpSubgroupClusteredAnd);
+ symbolTable.relateToOperator("subgroupClusteredOr", EOpSubgroupClusteredOr);
+ symbolTable.relateToOperator("subgroupClusteredXor", EOpSubgroupClusteredXor);
+ symbolTable.relateToOperator("subgroupQuadBroadcast", EOpSubgroupQuadBroadcast);
+ symbolTable.relateToOperator("subgroupQuadSwapHorizontal", EOpSubgroupQuadSwapHorizontal);
+ symbolTable.relateToOperator("subgroupQuadSwapVertical", EOpSubgroupQuadSwapVertical);
+ symbolTable.relateToOperator("subgroupQuadSwapDiagonal", EOpSubgroupQuadSwapDiagonal);
+
+ symbolTable.relateToOperator("subgroupPartitionNV", EOpSubgroupPartition);
+ symbolTable.relateToOperator("subgroupPartitionedAddNV", EOpSubgroupPartitionedAdd);
+ symbolTable.relateToOperator("subgroupPartitionedMulNV", EOpSubgroupPartitionedMul);
+ symbolTable.relateToOperator("subgroupPartitionedMinNV", EOpSubgroupPartitionedMin);
+ symbolTable.relateToOperator("subgroupPartitionedMaxNV", EOpSubgroupPartitionedMax);
+ symbolTable.relateToOperator("subgroupPartitionedAndNV", EOpSubgroupPartitionedAnd);
+ symbolTable.relateToOperator("subgroupPartitionedOrNV", EOpSubgroupPartitionedOr);
+ symbolTable.relateToOperator("subgroupPartitionedXorNV", EOpSubgroupPartitionedXor);
+ symbolTable.relateToOperator("subgroupPartitionedInclusiveAddNV", EOpSubgroupPartitionedInclusiveAdd);
+ symbolTable.relateToOperator("subgroupPartitionedInclusiveMulNV", EOpSubgroupPartitionedInclusiveMul);
+ symbolTable.relateToOperator("subgroupPartitionedInclusiveMinNV", EOpSubgroupPartitionedInclusiveMin);
+ symbolTable.relateToOperator("subgroupPartitionedInclusiveMaxNV", EOpSubgroupPartitionedInclusiveMax);
+ symbolTable.relateToOperator("subgroupPartitionedInclusiveAndNV", EOpSubgroupPartitionedInclusiveAnd);
+ symbolTable.relateToOperator("subgroupPartitionedInclusiveOrNV", EOpSubgroupPartitionedInclusiveOr);
+ symbolTable.relateToOperator("subgroupPartitionedInclusiveXorNV", EOpSubgroupPartitionedInclusiveXor);
+ symbolTable.relateToOperator("subgroupPartitionedExclusiveAddNV", EOpSubgroupPartitionedExclusiveAdd);
+ symbolTable.relateToOperator("subgroupPartitionedExclusiveMulNV", EOpSubgroupPartitionedExclusiveMul);
+ symbolTable.relateToOperator("subgroupPartitionedExclusiveMinNV", EOpSubgroupPartitionedExclusiveMin);
+ symbolTable.relateToOperator("subgroupPartitionedExclusiveMaxNV", EOpSubgroupPartitionedExclusiveMax);
+ symbolTable.relateToOperator("subgroupPartitionedExclusiveAndNV", EOpSubgroupPartitionedExclusiveAnd);
+ symbolTable.relateToOperator("subgroupPartitionedExclusiveOrNV", EOpSubgroupPartitionedExclusiveOr);
+ symbolTable.relateToOperator("subgroupPartitionedExclusiveXorNV", EOpSubgroupPartitionedExclusiveXor);
+ }
+
+ if (profile == EEsProfile) {
+ symbolTable.relateToOperator("shadow2DEXT", EOpTexture);
+ symbolTable.relateToOperator("shadow2DProjEXT", EOpTextureProj);
+ }
+ }
+
+ switch(language) {
+ case EShLangVertex:
+ break;
+
+ case EShLangTessControl:
+ case EShLangTessEvaluation:
+ break;
+
+ case EShLangGeometry:
+ symbolTable.relateToOperator("EmitStreamVertex", EOpEmitStreamVertex);
+ symbolTable.relateToOperator("EndStreamPrimitive", EOpEndStreamPrimitive);
+ symbolTable.relateToOperator("EmitVertex", EOpEmitVertex);
+ symbolTable.relateToOperator("EndPrimitive", EOpEndPrimitive);
+ break;
+
+ case EShLangFragment:
+ if (profile != EEsProfile && version >= 400) {
+ symbolTable.relateToOperator("dFdxFine", EOpDPdxFine);
+ symbolTable.relateToOperator("dFdyFine", EOpDPdyFine);
+ symbolTable.relateToOperator("fwidthFine", EOpFwidthFine);
+ symbolTable.relateToOperator("dFdxCoarse", EOpDPdxCoarse);
+ symbolTable.relateToOperator("dFdyCoarse", EOpDPdyCoarse);
+ symbolTable.relateToOperator("fwidthCoarse", EOpFwidthCoarse);
+ }
+ symbolTable.relateToOperator("interpolateAtCentroid", EOpInterpolateAtCentroid);
+ symbolTable.relateToOperator("interpolateAtSample", EOpInterpolateAtSample);
+ symbolTable.relateToOperator("interpolateAtOffset", EOpInterpolateAtOffset);
+
+ if (profile != EEsProfile)
+ symbolTable.relateToOperator("interpolateAtVertexAMD", EOpInterpolateAtVertex);
+
+ symbolTable.relateToOperator("beginInvocationInterlockARB", EOpBeginInvocationInterlock);
+ symbolTable.relateToOperator("endInvocationInterlockARB", EOpEndInvocationInterlock);
+
+ break;
+
+ case EShLangCompute:
+ symbolTable.relateToOperator("subgroupMemoryBarrierShared", EOpSubgroupMemoryBarrierShared);
+ if ((profile != EEsProfile && version >= 450) ||
+ (profile == EEsProfile && version >= 320)) {
+ symbolTable.relateToOperator("dFdx", EOpDPdx);
+ symbolTable.relateToOperator("dFdy", EOpDPdy);
+ symbolTable.relateToOperator("fwidth", EOpFwidth);
+ symbolTable.relateToOperator("dFdxFine", EOpDPdxFine);
+ symbolTable.relateToOperator("dFdyFine", EOpDPdyFine);
+ symbolTable.relateToOperator("fwidthFine", EOpFwidthFine);
+ symbolTable.relateToOperator("dFdxCoarse", EOpDPdxCoarse);
+ symbolTable.relateToOperator("dFdyCoarse", EOpDPdyCoarse);
+ symbolTable.relateToOperator("fwidthCoarse",EOpFwidthCoarse);
+ }
+ symbolTable.relateToOperator("coopMatLoadNV", EOpCooperativeMatrixLoad);
+ symbolTable.relateToOperator("coopMatStoreNV", EOpCooperativeMatrixStore);
+ symbolTable.relateToOperator("coopMatMulAddNV", EOpCooperativeMatrixMulAdd);
+ break;
+
+ case EShLangRayGenNV:
+ case EShLangClosestHitNV:
+ case EShLangMissNV:
+ if (profile != EEsProfile && version >= 460) {
+ symbolTable.relateToOperator("traceNV", EOpTraceNV);
+ symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV);
+ }
+ break;
+ case EShLangIntersectNV:
+ if (profile != EEsProfile && version >= 460)
+ symbolTable.relateToOperator("reportIntersectionNV", EOpReportIntersectionNV);
+ break;
+ case EShLangAnyHitNV:
+ if (profile != EEsProfile && version >= 460) {
+ symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersectionNV);
+ symbolTable.relateToOperator("terminateRayNV", EOpTerminateRayNV);
+ }
+ break;
+ case EShLangCallableNV:
+ if (profile != EEsProfile && version >= 460) {
+ symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV);
+ }
+ break;
+ case EShLangMeshNV:
+ if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
+ symbolTable.relateToOperator("writePackedPrimitiveIndices4x8NV", EOpWritePackedPrimitiveIndices4x8NV);
+ }
+ // fall through
+ case EShLangTaskNV:
+ if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
+ symbolTable.relateToOperator("memoryBarrierShared", EOpMemoryBarrierShared);
+ symbolTable.relateToOperator("groupMemoryBarrier", EOpGroupMemoryBarrier);
+ symbolTable.relateToOperator("subgroupMemoryBarrierShared", EOpSubgroupMemoryBarrierShared);
+ }
+ break;
+
+ default:
+ assert(false && "Language not supported");
+ }
+#endif
+}
+
+//
+// Add context-dependent (resource-specific) built-ins not handled by the above. These
+// would be ones that need to be programmatically added because they cannot
+// be added by simple text strings. For these, also
+// 1) Map built-in functions to operators, for those that will turn into an operation node
+// instead of remaining a function call.
+// 2) Tag extension-related symbols added to their base version with their extensions, so
+// that if an early version has the extension turned off, there is an error reported on use.
+//
+void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources)
+{
+#ifndef GLSLANG_WEB
+ if (profile != EEsProfile && version >= 430 && version < 440) {
+ symbolTable.setVariableExtensions("gl_MaxTransformFeedbackBuffers", 1, &E_GL_ARB_enhanced_layouts);
+ symbolTable.setVariableExtensions("gl_MaxTransformFeedbackInterleavedComponents", 1, &E_GL_ARB_enhanced_layouts);
+ }
+ if (profile != EEsProfile && version >= 130 && version < 420) {
+ symbolTable.setVariableExtensions("gl_MinProgramTexelOffset", 1, &E_GL_ARB_shading_language_420pack);
+ symbolTable.setVariableExtensions("gl_MaxProgramTexelOffset", 1, &E_GL_ARB_shading_language_420pack);
+ }
+ if (profile != EEsProfile && version >= 150 && version < 410)
+ symbolTable.setVariableExtensions("gl_MaxViewports", 1, &E_GL_ARB_viewport_array);
+
+ switch(language) {
+ case EShLangFragment:
+ // Set up gl_FragData based on current array size.
+ if (version == 100 || IncludeLegacy(version, profile, spvVersion) || (! ForwardCompatibility && profile != EEsProfile && version < 420)) {
+ TPrecisionQualifier pq = profile == EEsProfile ? EpqMedium : EpqNone;
+ TType fragData(EbtFloat, EvqFragColor, pq, 4);
+ TArraySizes* arraySizes = new TArraySizes;
+ arraySizes->addInnerSize(resources.maxDrawBuffers);
+ fragData.transferArraySizes(arraySizes);
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
+ SpecialQualifier("gl_FragData", EvqFragColor, EbvFragData, symbolTable);
+ }
+ break;
+
+ case EShLangTessControl:
+ case EShLangTessEvaluation:
+ // Because of the context-dependent array size (gl_MaxPatchVertices),
+ // these variables were added later than the others and need to be mapped now.
+
+ // standard members
+ BuiltInVariable("gl_in", "gl_Position", EbvPosition, symbolTable);
+ BuiltInVariable("gl_in", "gl_PointSize", EbvPointSize, symbolTable);
+ BuiltInVariable("gl_in", "gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_in", "gl_CullDistance", EbvCullDistance, symbolTable);
+
+ // compatibility members
+ BuiltInVariable("gl_in", "gl_ClipVertex", EbvClipVertex, symbolTable);
+ BuiltInVariable("gl_in", "gl_FrontColor", EbvFrontColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_BackColor", EbvBackColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+
+ symbolTable.setVariableExtensions("gl_in", "gl_SecondaryPositionNV", 1, &E_GL_NV_stereo_view_rendering);
+ symbolTable.setVariableExtensions("gl_in", "gl_PositionPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes);
+
+ BuiltInVariable("gl_in", "gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable);
+ BuiltInVariable("gl_in", "gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable);
+
+ // extension requirements
+ if (profile == EEsProfile) {
+ symbolTable.setVariableExtensions("gl_in", "gl_PointSize", Num_AEP_tessellation_point_size, AEP_tessellation_point_size);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+#endif
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/Initialize.h b/thirdparty/glslang/glslang/MachineIndependent/Initialize.h
new file mode 100644
index 0000000000..ac8ec33e99
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/Initialize.h
@@ -0,0 +1,112 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013-2016 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _INITIALIZE_INCLUDED_
+#define _INITIALIZE_INCLUDED_
+
+#include "../Include/ResourceLimits.h"
+#include "../Include/Common.h"
+#include "../Include/ShHandle.h"
+#include "SymbolTable.h"
+#include "Versions.h"
+
+namespace glslang {
+
+//
+// This is made to hold parseable strings for almost all the built-in
+// functions and variables for one specific combination of version
+// and profile. (Some still need to be added programmatically.)
+// This is a base class for language-specific derivations, which
+// can be used for language independent builtins.
+//
+// The strings are organized by
+// commonBuiltins: intersection of all stages' built-ins, processed just once
+// stageBuiltins[]: anything a stage needs that's not in commonBuiltins
+//
+class TBuiltInParseables {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+ TBuiltInParseables();
+ virtual ~TBuiltInParseables();
+ virtual void initialize(int version, EProfile, const SpvVersion& spvVersion) = 0;
+ virtual void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage) = 0;
+ virtual const TString& getCommonString() const { return commonBuiltins; }
+ virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; }
+
+ virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0;
+ virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0;
+
+protected:
+ TString commonBuiltins;
+ TString stageBuiltins[EShLangCount];
+};
+
+//
+// This is a GLSL specific derivation of TBuiltInParseables. To present a stable
+// interface and match other similar code, it is called TBuiltIns, rather
+// than TBuiltInParseablesGlsl.
+//
+class TBuiltIns : public TBuiltInParseables {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+ TBuiltIns();
+ virtual ~TBuiltIns();
+ void initialize(int version, EProfile, const SpvVersion& spvVersion);
+ void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage);
+
+ void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable);
+ void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources);
+
+protected:
+ void addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion);
+ void relateTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage, TSymbolTable&);
+ void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion);
+ void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile);
+ void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile);
+ void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile);
+ void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile);
+ void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile);
+
+ // Helpers for making textual representations of the permutations
+ // of texturing/imaging functions.
+ const char* postfixes[5];
+ const char* prefixes[EbtNumTypes];
+ int dimMap[EsdNumDims];
+};
+
+} // end namespace glslang
+
+#endif // _INITIALIZE_INCLUDED_
diff --git a/thirdparty/glslang/glslang/MachineIndependent/IntermTraverse.cpp b/thirdparty/glslang/glslang/MachineIndependent/IntermTraverse.cpp
new file mode 100644
index 0000000000..f46010b712
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/IntermTraverse.cpp
@@ -0,0 +1,302 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+// Copyright (c) 2002-2010 The ANGLE Project Authors.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/intermediate.h"
+
+namespace glslang {
+
+//
+// Traverse the intermediate representation tree, and
+// call a node type specific function for each node.
+// Done recursively through the member function Traverse().
+// Node types can be skipped if their function to call is 0,
+// but their subtree will still be traversed.
+// Nodes with children can have their whole subtree skipped
+// if preVisit is turned on and the type specific function
+// returns false.
+//
+// preVisit, postVisit, and rightToLeft control what order
+// nodes are visited in.
+//
+
+//
+// Traversal functions for terminals are straightforward....
+//
+void TIntermMethod::traverse(TIntermTraverser*)
+{
+ // Tree should always resolve all methods as a non-method.
+}
+
+void TIntermSymbol::traverse(TIntermTraverser *it)
+{
+ it->visitSymbol(this);
+}
+
+void TIntermConstantUnion::traverse(TIntermTraverser *it)
+{
+ it->visitConstantUnion(this);
+}
+
+//
+// Traverse a binary node.
+//
+void TIntermBinary::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ //
+ // visit the node before children if pre-visiting.
+ //
+ if (it->preVisit)
+ visit = it->visitBinary(EvPreVisit, this);
+
+ //
+ // Visit the children, in the right order.
+ //
+ if (visit) {
+ it->incrementDepth(this);
+
+ if (it->rightToLeft) {
+ if (right)
+ right->traverse(it);
+
+ if (it->inVisit)
+ visit = it->visitBinary(EvInVisit, this);
+
+ if (visit && left)
+ left->traverse(it);
+ } else {
+ if (left)
+ left->traverse(it);
+
+ if (it->inVisit)
+ visit = it->visitBinary(EvInVisit, this);
+
+ if (visit && right)
+ right->traverse(it);
+ }
+
+ it->decrementDepth();
+ }
+
+ //
+ // Visit the node after the children, if requested and the traversal
+ // hasn't been canceled yet.
+ //
+ if (visit && it->postVisit)
+ it->visitBinary(EvPostVisit, this);
+}
+
+//
+// Traverse a unary node. Same comments in binary node apply here.
+//
+void TIntermUnary::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitUnary(EvPreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+ operand->traverse(it);
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitUnary(EvPostVisit, this);
+}
+
+//
+// Traverse an aggregate node. Same comments in binary node apply here.
+//
+void TIntermAggregate::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitAggregate(EvPreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+
+ if (it->rightToLeft) {
+ for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) {
+ (*sit)->traverse(it);
+
+ if (visit && it->inVisit) {
+ if (*sit != sequence.front())
+ visit = it->visitAggregate(EvInVisit, this);
+ }
+ }
+ } else {
+ for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) {
+ (*sit)->traverse(it);
+
+ if (visit && it->inVisit) {
+ if (*sit != sequence.back())
+ visit = it->visitAggregate(EvInVisit, this);
+ }
+ }
+ }
+
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitAggregate(EvPostVisit, this);
+}
+
+//
+// Traverse a selection node. Same comments in binary node apply here.
+//
+void TIntermSelection::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitSelection(EvPreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+ if (it->rightToLeft) {
+ if (falseBlock)
+ falseBlock->traverse(it);
+ if (trueBlock)
+ trueBlock->traverse(it);
+ condition->traverse(it);
+ } else {
+ condition->traverse(it);
+ if (trueBlock)
+ trueBlock->traverse(it);
+ if (falseBlock)
+ falseBlock->traverse(it);
+ }
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitSelection(EvPostVisit, this);
+}
+
+//
+// Traverse a loop node. Same comments in binary node apply here.
+//
+void TIntermLoop::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitLoop(EvPreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+
+ if (it->rightToLeft) {
+ if (terminal)
+ terminal->traverse(it);
+
+ if (body)
+ body->traverse(it);
+
+ if (test)
+ test->traverse(it);
+ } else {
+ if (test)
+ test->traverse(it);
+
+ if (body)
+ body->traverse(it);
+
+ if (terminal)
+ terminal->traverse(it);
+ }
+
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitLoop(EvPostVisit, this);
+}
+
+//
+// Traverse a branch node. Same comments in binary node apply here.
+//
+void TIntermBranch::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitBranch(EvPreVisit, this);
+
+ if (visit && expression) {
+ it->incrementDepth(this);
+ expression->traverse(it);
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitBranch(EvPostVisit, this);
+}
+
+//
+// Traverse a switch node.
+//
+void TIntermSwitch::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitSwitch(EvPreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+ if (it->rightToLeft) {
+ body->traverse(it);
+ condition->traverse(it);
+ } else {
+ condition->traverse(it);
+ body->traverse(it);
+ }
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitSwitch(EvPostVisit, this);
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/Intermediate.cpp b/thirdparty/glslang/glslang/MachineIndependent/Intermediate.cpp
new file mode 100755
index 0000000000..d0f86e6389
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/Intermediate.cpp
@@ -0,0 +1,3957 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2015 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include "localintermediate.h"
+#include "RemoveTree.h"
+#include "SymbolTable.h"
+#include "propagateNoContraction.h"
+
+#include <cfloat>
+#include <utility>
+#include <tuple>
+
+namespace glslang {
+
+////////////////////////////////////////////////////////////////////////////
+//
+// First set of functions are to help build the intermediate representation.
+// These functions are not member functions of the nodes.
+// They are called from parser productions.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Add a terminal node for an identifier in an expression.
+//
+// Returns the added node.
+//
+
+TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray,
+ TIntermTyped* constSubtree, const TSourceLoc& loc)
+{
+ TIntermSymbol* node = new TIntermSymbol(id, name, type);
+ node->setLoc(loc);
+ node->setConstArray(constArray);
+ node->setConstSubtree(constSubtree);
+
+ return node;
+}
+
+TIntermSymbol* TIntermediate::addSymbol(const TIntermSymbol& intermSymbol)
+{
+ return addSymbol(intermSymbol.getId(),
+ intermSymbol.getName(),
+ intermSymbol.getType(),
+ intermSymbol.getConstArray(),
+ intermSymbol.getConstSubtree(),
+ intermSymbol.getLoc());
+}
+
+TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable)
+{
+ glslang::TSourceLoc loc; // just a null location
+ loc.init();
+
+ return addSymbol(variable, loc);
+}
+
+TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable, const TSourceLoc& loc)
+{
+ return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), variable.getConstSubtree(), loc);
+}
+
+TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc)
+{
+ TConstUnionArray unionArray; // just a null constant
+
+ return addSymbol(0, "", type, unionArray, nullptr, loc);
+}
+
+//
+// Connect two nodes with a new parent that does a binary operation on the nodes.
+//
+// Returns the added node.
+//
+// Returns nullptr if the working conversions and promotions could not be found.
+//
+TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
+{
+ // No operations work on blocks
+ if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
+ return nullptr;
+
+ // Convert "reference +/- int" and "reference - reference" to integer math
+ if ((op == EOpAdd || op == EOpSub) && extensionRequested(E_GL_EXT_buffer_reference2)) {
+
+ // No addressing math on struct with unsized array.
+ if ((left->isReference() && left->getType().getReferentType()->containsUnsizedArray()) ||
+ (right->isReference() && right->getType().getReferentType()->containsUnsizedArray())) {
+ return nullptr;
+ }
+
+ if (left->isReference() && isTypeInt(right->getBasicType())) {
+ const TType& referenceType = left->getType();
+ TIntermConstantUnion* size = addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
+ left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
+
+ right = createConversion(EbtInt64, right);
+ right = addBinaryMath(EOpMul, right, size, loc);
+
+ TIntermTyped *node = addBinaryMath(op, left, right, loc);
+ node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
+ return node;
+ }
+
+ if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) {
+ const TType& referenceType = right->getType();
+ TIntermConstantUnion* size = addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true);
+ right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
+
+ left = createConversion(EbtInt64, left);
+ left = addBinaryMath(EOpMul, left, size, loc);
+
+ TIntermTyped *node = addBinaryMath(op, left, right, loc);
+ node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
+ return node;
+ }
+
+ if (op == EOpSub && left->isReference() && right->isReference()) {
+ TIntermConstantUnion* size = addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
+
+ left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
+ right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
+
+ left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64));
+ right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64));
+
+ left = addBinaryMath(EOpSub, left, right, loc);
+
+ TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc);
+ return node;
+ }
+
+ // No other math operators supported on references
+ if (left->isReference() || right->isReference()) {
+ return nullptr;
+ }
+ }
+
+ // Try converting the children's base types to compatible types.
+ auto children = addConversion(op, left, right);
+ left = std::get<0>(children);
+ right = std::get<1>(children);
+
+ if (left == nullptr || right == nullptr)
+ return nullptr;
+
+ // Convert the children's type shape to be compatible.
+ addBiShapeConversion(op, left, right);
+ if (left == nullptr || right == nullptr)
+ return nullptr;
+
+ //
+ // Need a new node holding things together. Make
+ // one and promote it to the right type.
+ //
+ TIntermBinary* node = addBinaryNode(op, left, right, loc);
+ if (! promote(node))
+ return nullptr;
+
+ node->updatePrecision();
+
+ //
+ // If they are both (non-specialization) constants, they must be folded.
+ // (Unless it's the sequence (comma) operator, but that's handled in addComma().)
+ //
+ TIntermConstantUnion *leftTempConstant = node->getLeft()->getAsConstantUnion();
+ TIntermConstantUnion *rightTempConstant = node->getRight()->getAsConstantUnion();
+ if (leftTempConstant && rightTempConstant) {
+ TIntermTyped* folded = leftTempConstant->fold(node->getOp(), rightTempConstant);
+ if (folded)
+ return folded;
+ }
+
+ // If can propagate spec-constantness and if the operation is an allowed
+ // specialization-constant operation, make a spec-constant.
+ if (specConstantPropagates(*node->getLeft(), *node->getRight()) && isSpecializationOperation(*node))
+ node->getWritableType().getQualifier().makeSpecConstant();
+
+ // If must propagate nonuniform, make a nonuniform.
+ if ((node->getLeft()->getQualifier().isNonUniform() || node->getRight()->getQualifier().isNonUniform()) &&
+ isNonuniformPropagating(node->getOp()))
+ node->getWritableType().getQualifier().nonUniform = true;
+
+ return node;
+}
+
+//
+// Low level: add binary node (no promotions or other argument modifications)
+//
+TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) const
+{
+ // build the node
+ TIntermBinary* node = new TIntermBinary(op);
+ if (loc.line == 0)
+ loc = left->getLoc();
+ node->setLoc(loc);
+ node->setLeft(left);
+ node->setRight(right);
+
+ return node;
+}
+
+//
+// like non-type form, but sets node's type.
+//
+TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc, const TType& type) const
+{
+ TIntermBinary* node = addBinaryNode(op, left, right, loc);
+ node->setType(type);
+ return node;
+}
+
+//
+// Low level: add unary node (no promotions or other argument modifications)
+//
+TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc) const
+{
+ TIntermUnary* node = new TIntermUnary(op);
+ if (loc.line == 0)
+ loc = child->getLoc();
+ node->setLoc(loc);
+ node->setOperand(child);
+
+ return node;
+}
+
+//
+// like non-type form, but sets node's type.
+//
+TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc, const TType& type) const
+{
+ TIntermUnary* node = addUnaryNode(op, child, loc);
+ node->setType(type);
+ return node;
+}
+
+//
+// Connect two nodes through an assignment.
+//
+// Returns the added node.
+//
+// Returns nullptr if the 'right' type could not be converted to match the 'left' type,
+// or the resulting operation cannot be properly promoted.
+//
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
+{
+ // No block assignment
+ if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
+ return nullptr;
+
+ // Convert "reference += int" to "reference = reference + int". We need this because the
+ // "reference + int" calculation involves a cast back to the original type, which makes it
+ // not an lvalue.
+ if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference() &&
+ extensionRequested(E_GL_EXT_buffer_reference2)) {
+
+ if (!(right->getType().isScalar() && right->getType().isIntegerDomain()))
+ return nullptr;
+
+ TIntermTyped* node = addBinaryMath(op == EOpAddAssign ? EOpAdd : EOpSub, left, right, loc);
+ if (!node)
+ return nullptr;
+
+ TIntermSymbol* symbol = left->getAsSymbolNode();
+ left = addSymbol(*symbol);
+
+ node = addAssign(EOpAssign, left, node, loc);
+ return node;
+ }
+
+ //
+ // Like adding binary math, except the conversion can only go
+ // from right to left.
+ //
+
+ // convert base types, nullptr return means not possible
+ right = addConversion(op, left->getType(), right);
+ if (right == nullptr)
+ return nullptr;
+
+ // convert shape
+ right = addUniShapeConversion(op, left->getType(), right);
+
+ // build the node
+ TIntermBinary* node = addBinaryNode(op, left, right, loc);
+
+ if (! promote(node))
+ return nullptr;
+
+ node->updatePrecision();
+
+ return node;
+}
+
+//
+// Connect two nodes through an index operator, where the left node is the base
+// of an array or struct, and the right node is a direct or indirect offset.
+//
+// Returns the added node.
+// The caller should set the type of the returned node.
+//
+TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc)
+{
+ // caller should set the type
+ return addBinaryNode(op, base, index, loc);
+}
+
+//
+// Add one node as the parent of another that it operates on.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc)
+{
+ if (child == 0)
+ return nullptr;
+
+ if (child->getType().getBasicType() == EbtBlock)
+ return nullptr;
+
+ switch (op) {
+ case EOpLogicalNot:
+ if (getSource() == EShSourceHlsl) {
+ break; // HLSL can promote logical not
+ }
+
+ if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
+ return nullptr;
+ }
+ break;
+
+ case EOpPostIncrement:
+ case EOpPreIncrement:
+ case EOpPostDecrement:
+ case EOpPreDecrement:
+ case EOpNegative:
+ if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
+ return nullptr;
+ default: break; // some compilers want this
+ }
+
+ //
+ // Do we need to promote the operand?
+ //
+ TBasicType newType = EbtVoid;
+ switch (op) {
+ case EOpConstructBool: newType = EbtBool; break;
+ case EOpConstructFloat: newType = EbtFloat; break;
+ case EOpConstructInt: newType = EbtInt; break;
+ case EOpConstructUint: newType = EbtUint; break;
+#ifndef GLSLANG_WEB
+ case EOpConstructInt8: newType = EbtInt8; break;
+ case EOpConstructUint8: newType = EbtUint8; break;
+ case EOpConstructInt16: newType = EbtInt16; break;
+ case EOpConstructUint16: newType = EbtUint16; break;
+ case EOpConstructInt64: newType = EbtInt64; break;
+ case EOpConstructUint64: newType = EbtUint64; break;
+ case EOpConstructDouble: newType = EbtDouble; break;
+ case EOpConstructFloat16: newType = EbtFloat16; break;
+#endif
+ default: break; // some compilers want this
+ }
+
+ if (newType != EbtVoid) {
+ child = addConversion(op, TType(newType, EvqTemporary, child->getVectorSize(),
+ child->getMatrixCols(),
+ child->getMatrixRows(),
+ child->isVector()),
+ child);
+ if (child == nullptr)
+ return nullptr;
+ }
+
+ //
+ // For constructors, we are now done, it was all in the conversion.
+ // TODO: but, did this bypass constant folding?
+ //
+ switch (op) {
+ case EOpConstructInt8:
+ case EOpConstructUint8:
+ case EOpConstructInt16:
+ case EOpConstructUint16:
+ case EOpConstructInt:
+ case EOpConstructUint:
+ case EOpConstructInt64:
+ case EOpConstructUint64:
+ case EOpConstructBool:
+ case EOpConstructFloat:
+ case EOpConstructDouble:
+ case EOpConstructFloat16:
+ return child;
+ default: break; // some compilers want this
+ }
+
+ //
+ // Make a new node for the operator.
+ //
+ TIntermUnary* node = addUnaryNode(op, child, loc);
+
+ if (! promote(node))
+ return nullptr;
+
+ node->updatePrecision();
+
+ // If it's a (non-specialization) constant, it must be folded.
+ if (node->getOperand()->getAsConstantUnion())
+ return node->getOperand()->getAsConstantUnion()->fold(op, node->getType());
+
+ // If it's a specialization constant, the result is too,
+ // if the operation is allowed for specialization constants.
+ if (node->getOperand()->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*node))
+ node->getWritableType().getQualifier().makeSpecConstant();
+
+ // If must propagate nonuniform, make a nonuniform.
+ if (node->getOperand()->getQualifier().isNonUniform() && isNonuniformPropagating(node->getOp()))
+ node->getWritableType().getQualifier().nonUniform = true;
+
+ return node;
+}
+
+TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOperator op, bool unary,
+ TIntermNode* childNode, const TType& returnType)
+{
+ if (unary) {
+ //
+ // Treat it like a unary operator.
+ // addUnaryMath() should get the type correct on its own;
+ // including constness (which would differ from the prototype).
+ //
+ TIntermTyped* child = childNode->getAsTyped();
+ if (child == nullptr)
+ return nullptr;
+
+ if (child->getAsConstantUnion()) {
+ TIntermTyped* folded = child->getAsConstantUnion()->fold(op, returnType);
+ if (folded)
+ return folded;
+ }
+
+ return addUnaryNode(op, child, child->getLoc(), returnType);
+ } else {
+ // setAggregateOperater() calls fold() for constant folding
+ TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc);
+
+ return node;
+ }
+}
+
+//
+// This is the safe way to change the operator on an aggregate, as it
+// does lots of error checking and fixing. Especially for establishing
+// a function call's operation on its set of parameters. Sequences
+// of instructions are also aggregates, but they just directly set
+// their operator to EOpSequence.
+//
+// Returns an aggregate node, which could be the one passed in if
+// it was already an aggregate.
+//
+TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, TSourceLoc loc)
+{
+ TIntermAggregate* aggNode;
+
+ //
+ // Make sure we have an aggregate. If not turn it into one.
+ //
+ if (node != nullptr) {
+ aggNode = node->getAsAggregate();
+ if (aggNode == nullptr || aggNode->getOp() != EOpNull) {
+ //
+ // Make an aggregate containing this node.
+ //
+ aggNode = new TIntermAggregate();
+ aggNode->getSequence().push_back(node);
+ if (loc.line == 0)
+ loc = node->getLoc();
+ }
+ } else
+ aggNode = new TIntermAggregate();
+
+ //
+ // Set the operator.
+ //
+ aggNode->setOperator(op);
+ if (loc.line != 0)
+ aggNode->setLoc(loc);
+
+ aggNode->setType(type);
+
+ return fold(aggNode);
+}
+
+bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const
+{
+ //
+ // Does the base type even allow the operation?
+ //
+ switch (node->getBasicType()) {
+ case EbtVoid:
+ return false;
+ case EbtAtomicUint:
+ case EbtSampler:
+ case EbtAccStructNV:
+ // opaque types can be passed to functions
+ if (op == EOpFunction)
+ break;
+
+ // HLSL can assign samplers directly (no constructor)
+ if (getSource() == EShSourceHlsl && node->getBasicType() == EbtSampler)
+ break;
+
+ // samplers can get assigned via a sampler constructor
+ // (well, not yet, but code in the rest of this function is ready for it)
+ if (node->getBasicType() == EbtSampler && op == EOpAssign &&
+ node->getAsOperator() != nullptr && node->getAsOperator()->getOp() == EOpConstructTextureSampler)
+ break;
+
+ // otherwise, opaque types can't even be operated on, let alone converted
+ return false;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+bool TIntermediate::buildConvertOp(TBasicType dst, TBasicType src, TOperator& newOp) const
+{
+ switch (dst) {
+#ifndef GLSLANG_WEB
+ case EbtDouble:
+ switch (src) {
+ case EbtUint: newOp = EOpConvUintToDouble; break;
+ case EbtBool: newOp = EOpConvBoolToDouble; break;
+ case EbtFloat: newOp = EOpConvFloatToDouble; break;
+ case EbtInt: newOp = EOpConvIntToDouble; break;
+ case EbtInt8: newOp = EOpConvInt8ToDouble; break;
+ case EbtUint8: newOp = EOpConvUint8ToDouble; break;
+ case EbtInt16: newOp = EOpConvInt16ToDouble; break;
+ case EbtUint16: newOp = EOpConvUint16ToDouble; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToDouble; break;
+ case EbtInt64: newOp = EOpConvInt64ToDouble; break;
+ case EbtUint64: newOp = EOpConvUint64ToDouble; break;
+ default:
+ return false;
+ }
+ break;
+#endif
+ case EbtFloat:
+ switch (src) {
+ case EbtInt: newOp = EOpConvIntToFloat; break;
+ case EbtUint: newOp = EOpConvUintToFloat; break;
+ case EbtBool: newOp = EOpConvBoolToFloat; break;
+#ifndef GLSLANG_WEB
+ case EbtDouble: newOp = EOpConvDoubleToFloat; break;
+ case EbtInt8: newOp = EOpConvInt8ToFloat; break;
+ case EbtUint8: newOp = EOpConvUint8ToFloat; break;
+ case EbtInt16: newOp = EOpConvInt16ToFloat; break;
+ case EbtUint16: newOp = EOpConvUint16ToFloat; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToFloat; break;
+ case EbtInt64: newOp = EOpConvInt64ToFloat; break;
+ case EbtUint64: newOp = EOpConvUint64ToFloat; break;
+#endif
+ default:
+ return false;
+ }
+ break;
+#ifndef GLSLANG_WEB
+ case EbtFloat16:
+ switch (src) {
+ case EbtInt8: newOp = EOpConvInt8ToFloat16; break;
+ case EbtUint8: newOp = EOpConvUint8ToFloat16; break;
+ case EbtInt16: newOp = EOpConvInt16ToFloat16; break;
+ case EbtUint16: newOp = EOpConvUint16ToFloat16; break;
+ case EbtInt: newOp = EOpConvIntToFloat16; break;
+ case EbtUint: newOp = EOpConvUintToFloat16; break;
+ case EbtBool: newOp = EOpConvBoolToFloat16; break;
+ case EbtFloat: newOp = EOpConvFloatToFloat16; break;
+ case EbtDouble: newOp = EOpConvDoubleToFloat16; break;
+ case EbtInt64: newOp = EOpConvInt64ToFloat16; break;
+ case EbtUint64: newOp = EOpConvUint64ToFloat16; break;
+ default:
+ return false;
+ }
+ break;
+#endif
+ case EbtBool:
+ switch (src) {
+ case EbtInt: newOp = EOpConvIntToBool; break;
+ case EbtUint: newOp = EOpConvUintToBool; break;
+ case EbtFloat: newOp = EOpConvFloatToBool; break;
+#ifndef GLSLANG_WEB
+ case EbtDouble: newOp = EOpConvDoubleToBool; break;
+ case EbtInt8: newOp = EOpConvInt8ToBool; break;
+ case EbtUint8: newOp = EOpConvUint8ToBool; break;
+ case EbtInt16: newOp = EOpConvInt16ToBool; break;
+ case EbtUint16: newOp = EOpConvUint16ToBool; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToBool; break;
+ case EbtInt64: newOp = EOpConvInt64ToBool; break;
+ case EbtUint64: newOp = EOpConvUint64ToBool; break;
+#endif
+ default:
+ return false;
+ }
+ break;
+#ifndef GLSLANG_WEB
+ case EbtInt8:
+ switch (src) {
+ case EbtUint8: newOp = EOpConvUint8ToInt8; break;
+ case EbtInt16: newOp = EOpConvInt16ToInt8; break;
+ case EbtUint16: newOp = EOpConvUint16ToInt8; break;
+ case EbtInt: newOp = EOpConvIntToInt8; break;
+ case EbtUint: newOp = EOpConvUintToInt8; break;
+ case EbtInt64: newOp = EOpConvInt64ToInt8; break;
+ case EbtUint64: newOp = EOpConvUint64ToInt8; break;
+ case EbtBool: newOp = EOpConvBoolToInt8; break;
+ case EbtFloat: newOp = EOpConvFloatToInt8; break;
+ case EbtDouble: newOp = EOpConvDoubleToInt8; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToInt8; break;
+ default:
+ return false;
+ }
+ break;
+ case EbtUint8:
+ switch (src) {
+ case EbtInt8: newOp = EOpConvInt8ToUint8; break;
+ case EbtInt16: newOp = EOpConvInt16ToUint8; break;
+ case EbtUint16: newOp = EOpConvUint16ToUint8; break;
+ case EbtInt: newOp = EOpConvIntToUint8; break;
+ case EbtUint: newOp = EOpConvUintToUint8; break;
+ case EbtInt64: newOp = EOpConvInt64ToUint8; break;
+ case EbtUint64: newOp = EOpConvUint64ToUint8; break;
+ case EbtBool: newOp = EOpConvBoolToUint8; break;
+ case EbtFloat: newOp = EOpConvFloatToUint8; break;
+ case EbtDouble: newOp = EOpConvDoubleToUint8; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToUint8; break;
+ default:
+ return false;
+ }
+ break;
+
+ case EbtInt16:
+ switch (src) {
+ case EbtUint8: newOp = EOpConvUint8ToInt16; break;
+ case EbtInt8: newOp = EOpConvInt8ToInt16; break;
+ case EbtUint16: newOp = EOpConvUint16ToInt16; break;
+ case EbtInt: newOp = EOpConvIntToInt16; break;
+ case EbtUint: newOp = EOpConvUintToInt16; break;
+ case EbtInt64: newOp = EOpConvInt64ToInt16; break;
+ case EbtUint64: newOp = EOpConvUint64ToInt16; break;
+ case EbtBool: newOp = EOpConvBoolToInt16; break;
+ case EbtFloat: newOp = EOpConvFloatToInt16; break;
+ case EbtDouble: newOp = EOpConvDoubleToInt16; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToInt16; break;
+ default:
+ return false;
+ }
+ break;
+ case EbtUint16:
+ switch (src) {
+ case EbtInt8: newOp = EOpConvInt8ToUint16; break;
+ case EbtUint8: newOp = EOpConvUint8ToUint16; break;
+ case EbtInt16: newOp = EOpConvInt16ToUint16; break;
+ case EbtInt: newOp = EOpConvIntToUint16; break;
+ case EbtUint: newOp = EOpConvUintToUint16; break;
+ case EbtInt64: newOp = EOpConvInt64ToUint16; break;
+ case EbtUint64: newOp = EOpConvUint64ToUint16; break;
+ case EbtBool: newOp = EOpConvBoolToUint16; break;
+ case EbtFloat: newOp = EOpConvFloatToUint16; break;
+ case EbtDouble: newOp = EOpConvDoubleToUint16; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToUint16; break;
+ default:
+ return false;
+ }
+ break;
+#endif
+
+ case EbtInt:
+ switch (src) {
+ case EbtUint: newOp = EOpConvUintToInt; break;
+ case EbtBool: newOp = EOpConvBoolToInt; break;
+ case EbtFloat: newOp = EOpConvFloatToInt; break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: newOp = EOpConvInt8ToInt; break;
+ case EbtUint8: newOp = EOpConvUint8ToInt; break;
+ case EbtInt16: newOp = EOpConvInt16ToInt; break;
+ case EbtUint16: newOp = EOpConvUint16ToInt; break;
+ case EbtDouble: newOp = EOpConvDoubleToInt; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToInt; break;
+ case EbtInt64: newOp = EOpConvInt64ToInt; break;
+ case EbtUint64: newOp = EOpConvUint64ToInt; break;
+#endif
+ default:
+ return false;
+ }
+ break;
+ case EbtUint:
+ switch (src) {
+ case EbtInt: newOp = EOpConvIntToUint; break;
+ case EbtBool: newOp = EOpConvBoolToUint; break;
+ case EbtFloat: newOp = EOpConvFloatToUint; break;
+#ifndef GLSLANG_WEB
+ case EbtInt8: newOp = EOpConvInt8ToUint; break;
+ case EbtUint8: newOp = EOpConvUint8ToUint; break;
+ case EbtInt16: newOp = EOpConvInt16ToUint; break;
+ case EbtUint16: newOp = EOpConvUint16ToUint; break;
+ case EbtDouble: newOp = EOpConvDoubleToUint; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToUint; break;
+ case EbtInt64: newOp = EOpConvInt64ToUint; break;
+ case EbtUint64: newOp = EOpConvUint64ToUint; break;
+#endif
+ default:
+ return false;
+ }
+ break;
+#ifndef GLSLANG_WEB
+ case EbtInt64:
+ switch (src) {
+ case EbtInt8: newOp = EOpConvInt8ToInt64; break;
+ case EbtUint8: newOp = EOpConvUint8ToInt64; break;
+ case EbtInt16: newOp = EOpConvInt16ToInt64; break;
+ case EbtUint16: newOp = EOpConvUint16ToInt64; break;
+ case EbtInt: newOp = EOpConvIntToInt64; break;
+ case EbtUint: newOp = EOpConvUintToInt64; break;
+ case EbtBool: newOp = EOpConvBoolToInt64; break;
+ case EbtFloat: newOp = EOpConvFloatToInt64; break;
+ case EbtDouble: newOp = EOpConvDoubleToInt64; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToInt64; break;
+ case EbtUint64: newOp = EOpConvUint64ToInt64; break;
+ default:
+ return false;
+ }
+ break;
+ case EbtUint64:
+ switch (src) {
+ case EbtInt8: newOp = EOpConvInt8ToUint64; break;
+ case EbtUint8: newOp = EOpConvUint8ToUint64; break;
+ case EbtInt16: newOp = EOpConvInt16ToUint64; break;
+ case EbtUint16: newOp = EOpConvUint16ToUint64; break;
+ case EbtInt: newOp = EOpConvIntToUint64; break;
+ case EbtUint: newOp = EOpConvUintToUint64; break;
+ case EbtBool: newOp = EOpConvBoolToUint64; break;
+ case EbtFloat: newOp = EOpConvFloatToUint64; break;
+ case EbtDouble: newOp = EOpConvDoubleToUint64; break;
+ case EbtFloat16: newOp = EOpConvFloat16ToUint64; break;
+ case EbtInt64: newOp = EOpConvInt64ToUint64; break;
+ default:
+ return false;
+ }
+ break;
+#endif
+ default:
+ return false;
+ }
+ return true;
+}
+
+// This is 'mechanism' here, it does any conversion told.
+// It is about basic type, not about shape.
+// The policy comes from the shader or the calling code.
+TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped* node) const
+{
+ //
+ // Add a new newNode for the conversion.
+ //
+
+#ifndef GLSLANG_WEB
+ bool convertToIntTypes = (convertTo == EbtInt8 || convertTo == EbtUint8 ||
+ convertTo == EbtInt16 || convertTo == EbtUint16 ||
+ convertTo == EbtInt || convertTo == EbtUint ||
+ convertTo == EbtInt64 || convertTo == EbtUint64);
+
+ bool convertFromIntTypes = (node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8 ||
+ node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16 ||
+ node->getBasicType() == EbtInt || node->getBasicType() == EbtUint ||
+ node->getBasicType() == EbtInt64 || node->getBasicType() == EbtUint64);
+
+ bool convertToFloatTypes = (convertTo == EbtFloat16 || convertTo == EbtFloat || convertTo == EbtDouble);
+
+ bool convertFromFloatTypes = (node->getBasicType() == EbtFloat16 ||
+ node->getBasicType() == EbtFloat ||
+ node->getBasicType() == EbtDouble);
+
+ if (! getArithemeticInt8Enabled()) {
+ if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) ||
+ ((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes))
+ return nullptr;
+ }
+
+ if (! getArithemeticInt16Enabled()) {
+ if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) ||
+ ((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes))
+ return nullptr;
+ }
+
+ if (! getArithemeticFloat16Enabled()) {
+ if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) ||
+ (node->getBasicType() == EbtFloat16 && ! convertToFloatTypes))
+ return nullptr;
+ }
+#endif
+
+ TIntermUnary* newNode = nullptr;
+ TOperator newOp = EOpNull;
+ if (!buildConvertOp(convertTo, node->getBasicType(), newOp)) {
+ return nullptr;
+ }
+
+ TType newType(convertTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows());
+ newNode = addUnaryNode(newOp, node, node->getLoc(), newType);
+
+ if (node->getAsConstantUnion()) {
+#ifndef GLSLANG_WEB
+ // 8/16-bit storage extensions don't support 8/16-bit constants, so don't fold conversions
+ // to those types
+ if ((getArithemeticInt8Enabled() || !(convertTo == EbtInt8 || convertTo == EbtUint8)) &&
+ (getArithemeticInt16Enabled() || !(convertTo == EbtInt16 || convertTo == EbtUint16)) &&
+ (getArithemeticFloat16Enabled() || !(convertTo == EbtFloat16)))
+#endif
+ {
+ TIntermTyped* folded = node->getAsConstantUnion()->fold(newOp, newType);
+ if (folded)
+ return folded;
+ }
+ }
+
+ // Propagate specialization-constant-ness, if allowed
+ if (node->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*newNode))
+ newNode->getWritableType().getQualifier().makeSpecConstant();
+
+ return newNode;
+}
+
+TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* node) const
+{
+ return createConversion(convertTo, node);
+}
+
+// For converting a pair of operands to a binary operation to compatible
+// types with each other, relative to the operation in 'op'.
+// This does not cover assignment operations, which is asymmetric in that the
+// left type is not changeable.
+// See addConversion(op, type, node) for assignments and unary operation
+// conversions.
+//
+// Generally, this is focused on basic type conversion, not shape conversion.
+// See addShapeConversion() for shape conversions.
+//
+// Returns the converted pair of nodes.
+// Returns <nullptr, nullptr> when there is no conversion.
+std::tuple<TIntermTyped*, TIntermTyped*>
+TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1)
+{
+ if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1))
+ return std::make_tuple(nullptr, nullptr);
+
+ if (node0->getType() != node1->getType()) {
+ // If differing structure, then no conversions.
+ if (node0->isStruct() || node1->isStruct())
+ return std::make_tuple(nullptr, nullptr);
+
+ // If differing arrays, then no conversions.
+ if (node0->getType().isArray() || node1->getType().isArray())
+ return std::make_tuple(nullptr, nullptr);
+
+ // No implicit conversions for operations involving cooperative matrices
+ if (node0->getType().isCoopMat() || node1->getType().isCoopMat())
+ return std::make_tuple(node0, node1);
+ }
+
+ auto promoteTo = std::make_tuple(EbtNumTypes, EbtNumTypes);
+
+ switch (op) {
+ //
+ // List all the binary ops that can implicitly convert one operand to the other's type;
+ // This implements the 'policy' for implicit type conversion.
+ //
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ case EOpEqual:
+ case EOpNotEqual:
+
+ case EOpAdd:
+ case EOpSub:
+ case EOpMul:
+ case EOpDiv:
+ case EOpMod:
+
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar:
+
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+
+ case EOpSequence: // used by ?:
+
+ if (node0->getBasicType() == node1->getBasicType())
+ return std::make_tuple(node0, node1);
+
+ promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op);
+ if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes)
+ return std::make_tuple(nullptr, nullptr);
+
+ break;
+
+ case EOpLogicalAnd:
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ if (getSource() == EShSourceHlsl)
+ promoteTo = std::make_tuple(EbtBool, EbtBool);
+ else
+ return std::make_tuple(node0, node1);
+ break;
+
+ // There are no conversions needed for GLSL; the shift amount just needs to be an
+ // integer type, as does the base.
+ // HLSL can promote bools to ints to make this work.
+ case EOpLeftShift:
+ case EOpRightShift:
+ if (getSource() == EShSourceHlsl) {
+ TBasicType node0BasicType = node0->getBasicType();
+ if (node0BasicType == EbtBool)
+ node0BasicType = EbtInt;
+ if (node1->getBasicType() == EbtBool)
+ promoteTo = std::make_tuple(node0BasicType, EbtInt);
+ else
+ promoteTo = std::make_tuple(node0BasicType, node1->getBasicType());
+ } else {
+ if (isTypeInt(node0->getBasicType()) && isTypeInt(node1->getBasicType()))
+ return std::make_tuple(node0, node1);
+ else
+ return std::make_tuple(nullptr, nullptr);
+ }
+ break;
+
+ default:
+ if (node0->getType() == node1->getType())
+ return std::make_tuple(node0, node1);
+
+ return std::make_tuple(nullptr, nullptr);
+ }
+
+ TIntermTyped* newNode0;
+ TIntermTyped* newNode1;
+
+ if (std::get<0>(promoteTo) != node0->getType().getBasicType()) {
+ if (node0->getAsConstantUnion())
+ newNode0 = promoteConstantUnion(std::get<0>(promoteTo), node0->getAsConstantUnion());
+ else
+ newNode0 = createConversion(std::get<0>(promoteTo), node0);
+ } else
+ newNode0 = node0;
+
+ if (std::get<1>(promoteTo) != node1->getType().getBasicType()) {
+ if (node1->getAsConstantUnion())
+ newNode1 = promoteConstantUnion(std::get<1>(promoteTo), node1->getAsConstantUnion());
+ else
+ newNode1 = createConversion(std::get<1>(promoteTo), node1);
+ } else
+ newNode1 = node1;
+
+ return std::make_tuple(newNode0, newNode1);
+}
+
+//
+// Convert the node's type to the given type, as allowed by the operation involved: 'op'.
+// For implicit conversions, 'op' is not the requested conversion, it is the explicit
+// operation requiring the implicit conversion.
+//
+// Binary operation conversions should be handled by addConversion(op, node, node), not here.
+//
+// Returns a node representing the conversion, which could be the same
+// node passed in if no conversion was needed.
+//
+// Generally, this is focused on basic type conversion, not shape conversion.
+// See addShapeConversion() for shape conversions.
+//
+// Return nullptr if a conversion can't be done.
+//
+TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
+{
+ if (!isConversionAllowed(op, node))
+ return nullptr;
+
+ // Otherwise, if types are identical, no problem
+ if (type == node->getType())
+ return node;
+
+ // If one's a structure, then no conversions.
+ if (type.isStruct() || node->isStruct())
+ return nullptr;
+
+ // If one's an array, then no conversions.
+ if (type.isArray() || node->getType().isArray())
+ return nullptr;
+
+ // Note: callers are responsible for other aspects of shape,
+ // like vector and matrix sizes.
+
+ TBasicType promoteTo;
+ // GL_EXT_shader_16bit_storage can't do OpConstantComposite with
+ // 16-bit types, so disable promotion for those types.
+ bool canPromoteConstant = true;
+
+ switch (op) {
+ //
+ // Explicit conversions (unary operations)
+ //
+ case EOpConstructBool:
+ promoteTo = EbtBool;
+ break;
+ case EOpConstructFloat:
+ promoteTo = EbtFloat;
+ break;
+ case EOpConstructInt:
+ promoteTo = EbtInt;
+ break;
+ case EOpConstructUint:
+ promoteTo = EbtUint;
+ break;
+#ifndef GLSLANG_WEB
+ case EOpConstructDouble:
+ promoteTo = EbtDouble;
+ break;
+ case EOpConstructFloat16:
+ promoteTo = EbtFloat16;
+ canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
+ break;
+ case EOpConstructInt8:
+ promoteTo = EbtInt8;
+ canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
+ break;
+ case EOpConstructUint8:
+ promoteTo = EbtUint8;
+ canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
+ break;
+ case EOpConstructInt16:
+ promoteTo = EbtInt16;
+ canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
+ break;
+ case EOpConstructUint16:
+ promoteTo = EbtUint16;
+ canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
+ break;
+ case EOpConstructInt64:
+ promoteTo = EbtInt64;
+ break;
+ case EOpConstructUint64:
+ promoteTo = EbtUint64;
+ break;
+#endif
+
+ case EOpLogicalNot:
+
+ case EOpFunctionCall:
+
+ case EOpReturn:
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+
+ case EOpAtan:
+ case EOpClamp:
+ case EOpCross:
+ case EOpDistance:
+ case EOpDot:
+ case EOpDst:
+ case EOpFaceForward:
+ case EOpFma:
+ case EOpFrexp:
+ case EOpLdexp:
+ case EOpMix:
+ case EOpLit:
+ case EOpMax:
+ case EOpMin:
+ case EOpMod:
+ case EOpModf:
+ case EOpPow:
+ case EOpReflect:
+ case EOpRefract:
+ case EOpSmoothStep:
+ case EOpStep:
+
+ case EOpSequence:
+ case EOpConstructStruct:
+ case EOpConstructCooperativeMatrix:
+
+ if (type.isReference() || node->getType().isReference()) {
+ // types must match to assign a reference
+ if (type == node->getType())
+ return node;
+ else
+ return nullptr;
+ }
+
+ if (type.getBasicType() == node->getType().getBasicType())
+ return node;
+
+ if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
+ promoteTo = type.getBasicType();
+ else
+ return nullptr;
+ break;
+
+ // For GLSL, there are no conversions needed; the shift amount just needs to be an
+ // integer type, as do the base/result.
+ // HLSL can convert the shift from a bool to an int.
+ case EOpLeftShiftAssign:
+ case EOpRightShiftAssign:
+ {
+ if (getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool)
+ promoteTo = type.getBasicType();
+ else {
+ if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType()))
+ return node;
+ else
+ return nullptr;
+ }
+ break;
+ }
+
+ default:
+ // default is to require a match; all exceptions should have case statements above
+
+ if (type.getBasicType() == node->getType().getBasicType())
+ return node;
+ else
+ return nullptr;
+ }
+
+ if (canPromoteConstant && node->getAsConstantUnion())
+ return promoteConstantUnion(promoteTo, node->getAsConstantUnion());
+
+ //
+ // Add a new newNode for the conversion.
+ //
+ TIntermTyped* newNode = createConversion(promoteTo, node);
+
+ return newNode;
+}
+
+// Convert the node's shape of type for the given type, as allowed by the
+// operation involved: 'op'. This is for situations where there is only one
+// direction to consider doing the shape conversion.
+//
+// This implements policy, it call addShapeConversion() for the mechanism.
+//
+// Generally, the AST represents allowed GLSL shapes, so this isn't needed
+// for GLSL. Bad shapes are caught in conversion or promotion.
+//
+// Return 'node' if no conversion was done. Promotion handles final shape
+// checking.
+//
+TIntermTyped* TIntermediate::addUniShapeConversion(TOperator op, const TType& type, TIntermTyped* node)
+{
+ // some source languages don't do this
+ switch (getSource()) {
+ case EShSourceHlsl:
+ break;
+ case EShSourceGlsl:
+ default:
+ return node;
+ }
+
+ // some operations don't do this
+ switch (op) {
+ case EOpFunctionCall:
+ case EOpReturn:
+ break;
+
+ case EOpMulAssign:
+ // want to support vector *= scalar native ops in AST and lower, not smear, similarly for
+ // matrix *= scalar, etc.
+
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ case EOpRightShiftAssign:
+ case EOpLeftShiftAssign:
+ if (node->getVectorSize() == 1)
+ return node;
+ break;
+
+ case EOpAssign:
+ break;
+
+ case EOpMix:
+ break;
+
+ default:
+ return node;
+ }
+
+ return addShapeConversion(type, node);
+}
+
+// Convert the nodes' shapes to be compatible for the operation 'op'.
+//
+// This implements policy, it call addShapeConversion() for the mechanism.
+//
+// Generally, the AST represents allowed GLSL shapes, so this isn't needed
+// for GLSL. Bad shapes are caught in conversion or promotion.
+//
+void TIntermediate::addBiShapeConversion(TOperator op, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode)
+{
+ // some source languages don't do this
+ switch (getSource()) {
+ case EShSourceHlsl:
+ break;
+ case EShSourceGlsl:
+ default:
+ return;
+ }
+
+ // some operations don't do this
+ // 'break' will mean attempt bidirectional conversion
+ switch (op) {
+ case EOpMulAssign:
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ case EOpRightShiftAssign:
+ case EOpLeftShiftAssign:
+ // switch to unidirectional conversion (the lhs can't change)
+ rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode);
+ return;
+
+ case EOpMul:
+ // matrix multiply does not change shapes
+ if (lhsNode->isMatrix() && rhsNode->isMatrix())
+ return;
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ // want to support vector * scalar native ops in AST and lower, not smear, similarly for
+ // matrix * vector, etc.
+ if (lhsNode->getVectorSize() == 1 || rhsNode->getVectorSize() == 1)
+ return;
+ break;
+
+ case EOpRightShift:
+ case EOpLeftShift:
+ // can natively support the right operand being a scalar and the left a vector,
+ // but not the reverse
+ if (rhsNode->getVectorSize() == 1)
+ return;
+ break;
+
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+
+ case EOpEqual:
+ case EOpNotEqual:
+
+ case EOpLogicalAnd:
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+
+ case EOpMix:
+ break;
+
+ default:
+ return;
+ }
+
+ // Do bidirectional conversions
+ if (lhsNode->getType().isScalarOrVec1() || rhsNode->getType().isScalarOrVec1()) {
+ if (lhsNode->getType().isScalarOrVec1())
+ lhsNode = addShapeConversion(rhsNode->getType(), lhsNode);
+ else
+ rhsNode = addShapeConversion(lhsNode->getType(), rhsNode);
+ }
+ lhsNode = addShapeConversion(rhsNode->getType(), lhsNode);
+ rhsNode = addShapeConversion(lhsNode->getType(), rhsNode);
+}
+
+// Convert the node's shape of type for the given type, as allowed by the
+// operation involved: 'op'.
+//
+// Generally, the AST represents allowed GLSL shapes, so this isn't needed
+// for GLSL. Bad shapes are caught in conversion or promotion.
+//
+// Return 'node' if no conversion was done. Promotion handles final shape
+// checking.
+//
+TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped* node)
+{
+ // no conversion needed
+ if (node->getType() == type)
+ return node;
+
+ // structures and arrays don't change shape, either to or from
+ if (node->getType().isStruct() || node->getType().isArray() ||
+ type.isStruct() || type.isArray())
+ return node;
+
+ // The new node that handles the conversion
+ TOperator constructorOp = mapTypeToConstructorOp(type);
+
+ if (getSource() == EShSourceHlsl) {
+ // HLSL rules for scalar, vector and matrix conversions:
+ // 1) scalar can become anything, initializing every component with its value
+ // 2) vector and matrix can become scalar, first element is used (warning: truncation)
+ // 3) matrix can become matrix with less rows and/or columns (warning: truncation)
+ // 4) vector can become vector with less rows size (warning: truncation)
+ // 5a) vector 4 can become 2x2 matrix (special case) (same packing layout, its a reinterpret)
+ // 5b) 2x2 matrix can become vector 4 (special case) (same packing layout, its a reinterpret)
+
+ const TType &sourceType = node->getType();
+
+ // rule 1 for scalar to matrix is special
+ if (sourceType.isScalarOrVec1() && type.isMatrix()) {
+
+ // HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix. Left to its
+ // own devices, the constructor from a scalar would populate the diagonal. This forces replication
+ // to every matrix element.
+
+ // Note that if the node is complex (e.g, a function call), we don't want to duplicate it here
+ // repeatedly, so we copy it to a temp, then use the temp.
+ const int matSize = type.computeNumComponents();
+ TIntermAggregate* rhsAggregate = new TIntermAggregate();
+
+ const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr);
+
+ if (!isSimple) {
+ assert(0); // TODO: use node replicator service when available.
+ }
+
+ for (int x = 0; x < matSize; ++x)
+ rhsAggregate->getSequence().push_back(node);
+
+ return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc());
+ }
+
+ // rule 1 and 2
+ if ((sourceType.isScalar() && !type.isScalar()) || (!sourceType.isScalar() && type.isScalar()))
+ return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
+
+ // rule 3 and 5b
+ if (sourceType.isMatrix()) {
+ // rule 3
+ if (type.isMatrix()) {
+ if ((sourceType.getMatrixCols() != type.getMatrixCols() || sourceType.getMatrixRows() != type.getMatrixRows()) &&
+ sourceType.getMatrixCols() >= type.getMatrixCols() && sourceType.getMatrixRows() >= type.getMatrixRows())
+ return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
+ // rule 5b
+ } else if (type.isVector()) {
+ if (type.getVectorSize() == 4 && sourceType.getMatrixCols() == 2 && sourceType.getMatrixRows() == 2)
+ return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
+ }
+ }
+
+ // rule 4 and 5a
+ if (sourceType.isVector()) {
+ // rule 4
+ if (type.isVector())
+ {
+ if (sourceType.getVectorSize() > type.getVectorSize())
+ return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
+ // rule 5a
+ } else if (type.isMatrix()) {
+ if (sourceType.getVectorSize() == 4 && type.getMatrixCols() == 2 && type.getMatrixRows() == 2)
+ return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
+ }
+ }
+ }
+
+ // scalar -> vector or vec1 -> vector or
+ // vector -> scalar or
+ // bigger vector -> smaller vector
+ if ((node->getType().isScalarOrVec1() && type.isVector()) ||
+ (node->getType().isVector() && type.isScalar()) ||
+ (node->isVector() && type.isVector() && node->getVectorSize() > type.getVectorSize()))
+ return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
+
+ return node;
+}
+
+bool TIntermediate::isIntegralPromotion(TBasicType from, TBasicType to) const
+{
+ // integral promotions
+ if (to == EbtInt) {
+ switch(from) {
+ case EbtInt8:
+ case EbtInt16:
+ case EbtUint8:
+ case EbtUint16:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+bool TIntermediate::isFPPromotion(TBasicType from, TBasicType to) const
+{
+ // floating-point promotions
+ if (to == EbtDouble) {
+ switch(from) {
+ case EbtFloat16:
+ case EbtFloat:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+bool TIntermediate::isIntegralConversion(TBasicType from, TBasicType to) const
+{
+#ifdef GLSLANG_WEB
+ return false;
+#endif
+
+ switch (from) {
+ case EbtInt:
+ switch(to) {
+ case EbtUint:
+ return version >= 400 || getSource() == EShSourceHlsl;
+ case EbtInt64:
+ case EbtUint64:
+ return true;
+ default:
+ break;
+ }
+ break;
+ case EbtUint:
+ switch(to) {
+ case EbtInt64:
+ case EbtUint64:
+ return true;
+ default:
+ break;
+ }
+ break;
+ case EbtInt8:
+ switch (to) {
+ case EbtUint8:
+ case EbtInt16:
+ case EbtUint16:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ return true;
+ default:
+ break;
+ }
+ break;
+ case EbtUint8:
+ switch (to) {
+ case EbtInt16:
+ case EbtUint16:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ return true;
+ default:
+ break;
+ }
+ break;
+ case EbtInt16:
+ switch(to) {
+ case EbtUint16:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ return true;
+ default:
+ break;
+ }
+ break;
+ case EbtUint16:
+ switch(to) {
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ return true;
+ default:
+ break;
+ }
+ break;
+ case EbtInt64:
+ if (to == EbtUint64) {
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool TIntermediate::isFPConversion(TBasicType from, TBasicType to) const
+{
+#ifdef GLSLANG_WEB
+ return false;
+#endif
+
+ if (to == EbtFloat && from == EbtFloat16) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const
+{
+ switch (from) {
+ case EbtInt:
+ case EbtUint:
+ switch(to) {
+ case EbtFloat:
+ case EbtDouble:
+ return true;
+ default:
+ break;
+ }
+ break;
+#ifndef GLSLANG_WEB
+ case EbtInt8:
+ case EbtUint8:
+ case EbtInt16:
+ case EbtUint16:
+ switch (to) {
+ case EbtFloat16:
+ case EbtFloat:
+ case EbtDouble:
+ return true;
+ default:
+ break;
+ }
+ break;
+ case EbtInt64:
+ case EbtUint64:
+ if (to == EbtDouble) {
+ return true;
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+ return false;
+}
+
+//
+// See if the 'from' type is allowed to be implicitly converted to the
+// 'to' type. This is not about vector/array/struct, only about basic type.
+//
+bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const
+{
+ if (isEsProfile() || version == 110)
+ return false;
+
+ if (from == to)
+ return true;
+
+ // TODO: Move more policies into language-specific handlers.
+ // Some languages allow more general (or potentially, more specific) conversions under some conditions.
+ if (getSource() == EShSourceHlsl) {
+ const bool fromConvertable = (from == EbtFloat || from == EbtDouble || from == EbtInt || from == EbtUint || from == EbtBool);
+ const bool toConvertable = (to == EbtFloat || to == EbtDouble || to == EbtInt || to == EbtUint || to == EbtBool);
+
+ if (fromConvertable && toConvertable) {
+ switch (op) {
+ case EOpAndAssign: // assignments can perform arbitrary conversions
+ case EOpInclusiveOrAssign: // ...
+ case EOpExclusiveOrAssign: // ...
+ case EOpAssign: // ...
+ case EOpAddAssign: // ...
+ case EOpSubAssign: // ...
+ case EOpMulAssign: // ...
+ case EOpVectorTimesScalarAssign: // ...
+ case EOpMatrixTimesScalarAssign: // ...
+ case EOpDivAssign: // ...
+ case EOpModAssign: // ...
+ case EOpReturn: // function returns can also perform arbitrary conversions
+ case EOpFunctionCall: // conversion of a calling parameter
+ case EOpLogicalNot:
+ case EOpLogicalAnd:
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ case EOpConstructStruct:
+ return true;
+ default:
+ break;
+ }
+ }
+ }
+
+ bool explicitTypesEnabled = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int32) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int64) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64);
+
+ if (explicitTypesEnabled) {
+ // integral promotions
+ if (isIntegralPromotion(from, to)) {
+ return true;
+ }
+
+ // floating-point promotions
+ if (isFPPromotion(from, to)) {
+ return true;
+ }
+
+ // integral conversions
+ if (isIntegralConversion(from, to)) {
+ return true;
+ }
+
+ // floating-point conversions
+ if (isFPConversion(from, to)) {
+ return true;
+ }
+
+ // floating-integral conversions
+ if (isFPIntegralConversion(from, to)) {
+ return true;
+ }
+
+ // hlsl supported conversions
+ if (getSource() == EShSourceHlsl) {
+ if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
+ return true;
+ }
+ } else {
+ switch (to) {
+ case EbtDouble:
+ switch (from) {
+ case EbtInt:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ case EbtFloat:
+ case EbtDouble:
+ return true;
+ case EbtInt16:
+ case EbtUint16:
+ return extensionRequested(E_GL_AMD_gpu_shader_int16);
+ case EbtFloat16:
+ return extensionRequested(E_GL_AMD_gpu_shader_half_float);
+ default:
+ return false;
+ }
+ case EbtFloat:
+ switch (from) {
+ case EbtInt:
+ case EbtUint:
+ case EbtFloat:
+ return true;
+ case EbtBool:
+ return getSource() == EShSourceHlsl;
+ case EbtInt16:
+ case EbtUint16:
+ return extensionRequested(E_GL_AMD_gpu_shader_int16);
+ case EbtFloat16:
+ return
+ extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
+ getSource() == EShSourceHlsl;
+ default:
+ return false;
+ }
+ case EbtUint:
+ switch (from) {
+ case EbtInt:
+ return version >= 400 || getSource() == EShSourceHlsl;
+ case EbtUint:
+ return true;
+ case EbtBool:
+ return getSource() == EShSourceHlsl;
+ case EbtInt16:
+ case EbtUint16:
+ return extensionRequested(E_GL_AMD_gpu_shader_int16);
+ default:
+ return false;
+ }
+ case EbtInt:
+ switch (from) {
+ case EbtInt:
+ return true;
+ case EbtBool:
+ return getSource() == EShSourceHlsl;
+ case EbtInt16:
+ return extensionRequested(E_GL_AMD_gpu_shader_int16);
+ default:
+ return false;
+ }
+ case EbtUint64:
+ switch (from) {
+ case EbtInt:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ return true;
+ case EbtInt16:
+ case EbtUint16:
+ return extensionRequested(E_GL_AMD_gpu_shader_int16);
+ default:
+ return false;
+ }
+ case EbtInt64:
+ switch (from) {
+ case EbtInt:
+ case EbtInt64:
+ return true;
+ case EbtInt16:
+ return extensionRequested(E_GL_AMD_gpu_shader_int16);
+ default:
+ return false;
+ }
+ case EbtFloat16:
+ switch (from) {
+ case EbtInt16:
+ case EbtUint16:
+ return extensionRequested(E_GL_AMD_gpu_shader_int16);
+ case EbtFloat16:
+ return extensionRequested(E_GL_AMD_gpu_shader_half_float);
+ default:
+ break;
+ }
+ return false;
+ case EbtUint16:
+ switch (from) {
+ case EbtInt16:
+ case EbtUint16:
+ return extensionRequested(E_GL_AMD_gpu_shader_int16);
+ default:
+ break;
+ }
+ return false;
+ default:
+ return false;
+ }
+ }
+
+ return false;
+}
+
+static bool canSignedIntTypeRepresentAllUnsignedValues(TBasicType sintType, TBasicType uintType)
+{
+#ifdef GLSLANG_WEB
+ return false;
+#endif
+
+ switch(sintType) {
+ case EbtInt8:
+ switch(uintType) {
+ case EbtUint8:
+ case EbtUint16:
+ case EbtUint:
+ case EbtUint64:
+ return false;
+ default:
+ assert(false);
+ return false;
+ }
+ break;
+ case EbtInt16:
+ switch(uintType) {
+ case EbtUint8:
+ return true;
+ case EbtUint16:
+ case EbtUint:
+ case EbtUint64:
+ return false;
+ default:
+ assert(false);
+ return false;
+ }
+ break;
+ case EbtInt:
+ switch(uintType) {
+ case EbtUint8:
+ case EbtUint16:
+ return true;
+ case EbtUint:
+ return false;
+ default:
+ assert(false);
+ return false;
+ }
+ break;
+ case EbtInt64:
+ switch(uintType) {
+ case EbtUint8:
+ case EbtUint16:
+ case EbtUint:
+ return true;
+ case EbtUint64:
+ return false;
+ default:
+ assert(false);
+ return false;
+ }
+ break;
+ default:
+ assert(false);
+ return false;
+ }
+}
+
+
+static TBasicType getCorrespondingUnsignedType(TBasicType type)
+{
+#ifdef GLSLANG_WEB
+ assert(type == EbtInt);
+ return EbtUint;
+#endif
+
+ switch(type) {
+ case EbtInt8:
+ return EbtUint8;
+ case EbtInt16:
+ return EbtUint16;
+ case EbtInt:
+ return EbtUint;
+ case EbtInt64:
+ return EbtUint64;
+ default:
+ assert(false);
+ return EbtNumTypes;
+ }
+}
+
+// Implements the following rules
+// - If either operand has type float64_t or derived from float64_t,
+// the other shall be converted to float64_t or derived type.
+// - Otherwise, if either operand has type float32_t or derived from
+// float32_t, the other shall be converted to float32_t or derived type.
+// - Otherwise, if either operand has type float16_t or derived from
+// float16_t, the other shall be converted to float16_t or derived type.
+// - Otherwise, if both operands have integer types the following rules
+// shall be applied to the operands:
+// - If both operands have the same type, no further conversion
+// is needed.
+// - Otherwise, if both operands have signed integer types or both
+// have unsigned integer types, the operand with the type of lesser
+// integer conversion rank shall be converted to the type of the
+// operand with greater rank.
+// - Otherwise, if the operand that has unsigned integer type has rank
+// greater than or equal to the rank of the type of the other
+// operand, the operand with signed integer type shall be converted
+// to the type of the operand with unsigned integer type.
+// - Otherwise, if the type of the operand with signed integer type can
+// represent all of the values of the type of the operand with
+// unsigned integer type, the operand with unsigned integer type
+// shall be converted to the type of the operand with signed
+// integer type.
+// - Otherwise, both operands shall be converted to the unsigned
+// integer type corresponding to the type of the operand with signed
+// integer type.
+
+std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const
+{
+ TBasicType res0 = EbtNumTypes;
+ TBasicType res1 = EbtNumTypes;
+
+ if (isEsProfile() || version == 110)
+ return std::make_tuple(res0, res1);
+
+ if (getSource() == EShSourceHlsl) {
+ if (canImplicitlyPromote(type1, type0, op)) {
+ res0 = type0;
+ res1 = type0;
+ } else if (canImplicitlyPromote(type0, type1, op)) {
+ res0 = type1;
+ res1 = type1;
+ }
+ return std::make_tuple(res0, res1);
+ }
+
+ if ((type0 == EbtDouble && canImplicitlyPromote(type1, EbtDouble, op)) ||
+ (type1 == EbtDouble && canImplicitlyPromote(type0, EbtDouble, op)) ) {
+ res0 = EbtDouble;
+ res1 = EbtDouble;
+ } else if ((type0 == EbtFloat && canImplicitlyPromote(type1, EbtFloat, op)) ||
+ (type1 == EbtFloat && canImplicitlyPromote(type0, EbtFloat, op)) ) {
+ res0 = EbtFloat;
+ res1 = EbtFloat;
+ } else if ((type0 == EbtFloat16 && canImplicitlyPromote(type1, EbtFloat16, op)) ||
+ (type1 == EbtFloat16 && canImplicitlyPromote(type0, EbtFloat16, op)) ) {
+ res0 = EbtFloat16;
+ res1 = EbtFloat16;
+ } else if (isTypeInt(type0) && isTypeInt(type1) &&
+ (canImplicitlyPromote(type0, type1, op) || canImplicitlyPromote(type1, type0, op))) {
+ if ((isTypeSignedInt(type0) && isTypeSignedInt(type1)) ||
+ (isTypeUnsignedInt(type0) && isTypeUnsignedInt(type1))) {
+ if (getTypeRank(type0) < getTypeRank(type1)) {
+ res0 = type1;
+ res1 = type1;
+ } else {
+ res0 = type0;
+ res1 = type0;
+ }
+ } else if (isTypeUnsignedInt(type0) && (getTypeRank(type0) > getTypeRank(type1))) {
+ res0 = type0;
+ res1 = type0;
+ } else if (isTypeUnsignedInt(type1) && (getTypeRank(type1) > getTypeRank(type0))) {
+ res0 = type1;
+ res1 = type1;
+ } else if (isTypeSignedInt(type0)) {
+ if (canSignedIntTypeRepresentAllUnsignedValues(type0, type1)) {
+ res0 = type0;
+ res1 = type0;
+ } else {
+ res0 = getCorrespondingUnsignedType(type0);
+ res1 = getCorrespondingUnsignedType(type0);
+ }
+ } else if (isTypeSignedInt(type1)) {
+ if (canSignedIntTypeRepresentAllUnsignedValues(type1, type0)) {
+ res0 = type1;
+ res1 = type1;
+ } else {
+ res0 = getCorrespondingUnsignedType(type1);
+ res1 = getCorrespondingUnsignedType(type1);
+ }
+ }
+ }
+
+ return std::make_tuple(res0, res1);
+}
+
+//
+// Given a type, find what operation would fully construct it.
+//
+TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
+{
+ TOperator op = EOpNull;
+
+ if (type.getQualifier().isNonUniform())
+ return EOpConstructNonuniform;
+
+ if (type.isCoopMat())
+ return EOpConstructCooperativeMatrix;
+
+ switch (type.getBasicType()) {
+ case EbtStruct:
+ op = EOpConstructStruct;
+ break;
+ case EbtSampler:
+ if (type.getSampler().isCombined())
+ op = EOpConstructTextureSampler;
+ break;
+ case EbtFloat:
+ if (type.isMatrix()) {
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructMat2x2; break;
+ case 3: op = EOpConstructMat2x3; break;
+ case 4: op = EOpConstructMat2x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructMat3x2; break;
+ case 3: op = EOpConstructMat3x3; break;
+ case 4: op = EOpConstructMat3x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructMat4x2; break;
+ case 3: op = EOpConstructMat4x3; break;
+ case 4: op = EOpConstructMat4x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ default: break; // some compilers want this
+ }
+ } else {
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructFloat; break;
+ case 2: op = EOpConstructVec2; break;
+ case 3: op = EOpConstructVec3; break;
+ case 4: op = EOpConstructVec4; break;
+ default: break; // some compilers want this
+ }
+ }
+ break;
+ case EbtInt:
+ if (type.getMatrixCols()) {
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructIMat2x2; break;
+ case 3: op = EOpConstructIMat2x3; break;
+ case 4: op = EOpConstructIMat2x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructIMat3x2; break;
+ case 3: op = EOpConstructIMat3x3; break;
+ case 4: op = EOpConstructIMat3x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructIMat4x2; break;
+ case 3: op = EOpConstructIMat4x3; break;
+ case 4: op = EOpConstructIMat4x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ }
+ } else {
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructInt; break;
+ case 2: op = EOpConstructIVec2; break;
+ case 3: op = EOpConstructIVec3; break;
+ case 4: op = EOpConstructIVec4; break;
+ default: break; // some compilers want this
+ }
+ }
+ break;
+ case EbtUint:
+ if (type.getMatrixCols()) {
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructUMat2x2; break;
+ case 3: op = EOpConstructUMat2x3; break;
+ case 4: op = EOpConstructUMat2x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructUMat3x2; break;
+ case 3: op = EOpConstructUMat3x3; break;
+ case 4: op = EOpConstructUMat3x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructUMat4x2; break;
+ case 3: op = EOpConstructUMat4x3; break;
+ case 4: op = EOpConstructUMat4x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ }
+ } else {
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructUint; break;
+ case 2: op = EOpConstructUVec2; break;
+ case 3: op = EOpConstructUVec3; break;
+ case 4: op = EOpConstructUVec4; break;
+ default: break; // some compilers want this
+ }
+ }
+ break;
+ case EbtBool:
+ if (type.getMatrixCols()) {
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructBMat2x2; break;
+ case 3: op = EOpConstructBMat2x3; break;
+ case 4: op = EOpConstructBMat2x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructBMat3x2; break;
+ case 3: op = EOpConstructBMat3x3; break;
+ case 4: op = EOpConstructBMat3x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructBMat4x2; break;
+ case 3: op = EOpConstructBMat4x3; break;
+ case 4: op = EOpConstructBMat4x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ }
+ } else {
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructBool; break;
+ case 2: op = EOpConstructBVec2; break;
+ case 3: op = EOpConstructBVec3; break;
+ case 4: op = EOpConstructBVec4; break;
+ default: break; // some compilers want this
+ }
+ }
+ break;
+#ifndef GLSLANG_WEB
+ case EbtDouble:
+ if (type.getMatrixCols()) {
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructDMat2x2; break;
+ case 3: op = EOpConstructDMat2x3; break;
+ case 4: op = EOpConstructDMat2x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructDMat3x2; break;
+ case 3: op = EOpConstructDMat3x3; break;
+ case 4: op = EOpConstructDMat3x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructDMat4x2; break;
+ case 3: op = EOpConstructDMat4x3; break;
+ case 4: op = EOpConstructDMat4x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ }
+ } else {
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructDouble; break;
+ case 2: op = EOpConstructDVec2; break;
+ case 3: op = EOpConstructDVec3; break;
+ case 4: op = EOpConstructDVec4; break;
+ default: break; // some compilers want this
+ }
+ }
+ break;
+ case EbtFloat16:
+ if (type.getMatrixCols()) {
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructF16Mat2x2; break;
+ case 3: op = EOpConstructF16Mat2x3; break;
+ case 4: op = EOpConstructF16Mat2x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructF16Mat3x2; break;
+ case 3: op = EOpConstructF16Mat3x3; break;
+ case 4: op = EOpConstructF16Mat3x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructF16Mat4x2; break;
+ case 3: op = EOpConstructF16Mat4x3; break;
+ case 4: op = EOpConstructF16Mat4x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ }
+ }
+ else {
+ switch (type.getVectorSize()) {
+ case 1: op = EOpConstructFloat16; break;
+ case 2: op = EOpConstructF16Vec2; break;
+ case 3: op = EOpConstructF16Vec3; break;
+ case 4: op = EOpConstructF16Vec4; break;
+ default: break; // some compilers want this
+ }
+ }
+ break;
+ case EbtInt8:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructInt8; break;
+ case 2: op = EOpConstructI8Vec2; break;
+ case 3: op = EOpConstructI8Vec3; break;
+ case 4: op = EOpConstructI8Vec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case EbtUint8:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructUint8; break;
+ case 2: op = EOpConstructU8Vec2; break;
+ case 3: op = EOpConstructU8Vec3; break;
+ case 4: op = EOpConstructU8Vec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case EbtInt16:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructInt16; break;
+ case 2: op = EOpConstructI16Vec2; break;
+ case 3: op = EOpConstructI16Vec3; break;
+ case 4: op = EOpConstructI16Vec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case EbtUint16:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructUint16; break;
+ case 2: op = EOpConstructU16Vec2; break;
+ case 3: op = EOpConstructU16Vec3; break;
+ case 4: op = EOpConstructU16Vec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case EbtInt64:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructInt64; break;
+ case 2: op = EOpConstructI64Vec2; break;
+ case 3: op = EOpConstructI64Vec3; break;
+ case 4: op = EOpConstructI64Vec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case EbtUint64:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructUint64; break;
+ case 2: op = EOpConstructU64Vec2; break;
+ case 3: op = EOpConstructU64Vec3; break;
+ case 4: op = EOpConstructU64Vec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case EbtReference:
+ op = EOpConstructReference;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ return op;
+}
+
+//
+// Safe way to combine two nodes into an aggregate. Works with null pointers,
+// a node that's not a aggregate yet, etc.
+//
+// Returns the resulting aggregate, unless nullptr was passed in for
+// both existing nodes.
+//
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right)
+{
+ if (left == nullptr && right == nullptr)
+ return nullptr;
+
+ TIntermAggregate* aggNode = nullptr;
+ if (left != nullptr)
+ aggNode = left->getAsAggregate();
+ if (aggNode == nullptr || aggNode->getOp() != EOpNull) {
+ aggNode = new TIntermAggregate;
+ if (left != nullptr)
+ aggNode->getSequence().push_back(left);
+ }
+
+ if (right != nullptr)
+ aggNode->getSequence().push_back(right);
+
+ return aggNode;
+}
+
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& loc)
+{
+ TIntermAggregate* aggNode = growAggregate(left, right);
+ if (aggNode)
+ aggNode->setLoc(loc);
+
+ return aggNode;
+}
+
+//
+// Turn an existing node into an aggregate.
+//
+// Returns an aggregate, unless nullptr was passed in for the existing node.
+//
+TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node)
+{
+ if (node == nullptr)
+ return nullptr;
+
+ TIntermAggregate* aggNode = new TIntermAggregate;
+ aggNode->getSequence().push_back(node);
+ aggNode->setLoc(node->getLoc());
+
+ return aggNode;
+}
+
+TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& loc)
+{
+ if (node == nullptr)
+ return nullptr;
+
+ TIntermAggregate* aggNode = new TIntermAggregate;
+ aggNode->getSequence().push_back(node);
+ aggNode->setLoc(loc);
+
+ return aggNode;
+}
+
+//
+// Make an aggregate with an empty sequence.
+//
+TIntermAggregate* TIntermediate::makeAggregate(const TSourceLoc& loc)
+{
+ TIntermAggregate* aggNode = new TIntermAggregate;
+ aggNode->setLoc(loc);
+
+ return aggNode;
+}
+
+//
+// For "if" test nodes. There are three children; a condition,
+// a true path, and a false path. The two paths are in the
+// nodePair.
+//
+// Returns the selection node created.
+//
+TIntermSelection* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc)
+{
+ //
+ // Don't prune the false path for compile-time constants; it's needed
+ // for static access analysis.
+ //
+
+ TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
+ node->setLoc(loc);
+
+ return node;
+}
+
+TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc)
+{
+ // However, the lowest precedence operators of the sequence operator ( , ) and the assignment operators
+ // ... are not included in the operators that can create a constant expression.
+ //
+ // if (left->getType().getQualifier().storage == EvqConst &&
+ // right->getType().getQualifier().storage == EvqConst) {
+
+ // return right;
+ //}
+
+ TIntermTyped *commaAggregate = growAggregate(left, right, loc);
+ commaAggregate->getAsAggregate()->setOperator(EOpComma);
+ commaAggregate->setType(right->getType());
+ commaAggregate->getWritableType().getQualifier().makeTemporary();
+
+ return commaAggregate;
+}
+
+TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type, const TString* name, const TSourceLoc& loc)
+{
+ TIntermMethod* method = new TIntermMethod(object, type, *name);
+ method->setLoc(loc);
+
+ return method;
+}
+
+//
+// For "?:" test nodes. There are three children; a condition,
+// a true path, and a false path. The two paths are specified
+// as separate parameters. For vector 'cond', the true and false
+// are not paths, but vectors to mix.
+//
+// Specialization constant operations include
+// - The ternary operator ( ? : )
+//
+// Returns the selection node created, or nullptr if one could not be.
+//
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock,
+ const TSourceLoc& loc)
+{
+ // If it's void, go to the if-then-else selection()
+ if (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) {
+ TIntermNodePair pair = { trueBlock, falseBlock };
+ TIntermSelection* selection = addSelection(cond, pair, loc);
+ if (getSource() == EShSourceHlsl)
+ selection->setNoShortCircuit();
+
+ return selection;
+ }
+
+ //
+ // Get compatible types.
+ //
+ auto children = addConversion(EOpSequence, trueBlock, falseBlock);
+ trueBlock = std::get<0>(children);
+ falseBlock = std::get<1>(children);
+
+ if (trueBlock == nullptr || falseBlock == nullptr)
+ return nullptr;
+
+ // Handle a vector condition as a mix
+ if (!cond->getType().isScalarOrVec1()) {
+ TType targetVectorType(trueBlock->getType().getBasicType(), EvqTemporary,
+ cond->getType().getVectorSize());
+ // smear true/false operands as needed
+ trueBlock = addUniShapeConversion(EOpMix, targetVectorType, trueBlock);
+ falseBlock = addUniShapeConversion(EOpMix, targetVectorType, falseBlock);
+
+ // After conversion, types have to match.
+ if (falseBlock->getType() != trueBlock->getType())
+ return nullptr;
+
+ // make the mix operation
+ TIntermAggregate* mix = makeAggregate(loc);
+ mix = growAggregate(mix, falseBlock);
+ mix = growAggregate(mix, trueBlock);
+ mix = growAggregate(mix, cond);
+ mix->setType(targetVectorType);
+ mix->setOp(EOpMix);
+
+ return mix;
+ }
+
+ // Now have a scalar condition...
+
+ // Convert true and false expressions to matching types
+ addBiShapeConversion(EOpMix, trueBlock, falseBlock);
+
+ // After conversion, types have to match.
+ if (falseBlock->getType() != trueBlock->getType())
+ return nullptr;
+
+ // Eliminate the selection when the condition is a scalar and all operands are constant.
+ if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
+ if (cond->getAsConstantUnion()->getConstArray()[0].getBConst())
+ return trueBlock;
+ else
+ return falseBlock;
+ }
+
+ //
+ // Make a selection node.
+ //
+ TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
+ node->setLoc(loc);
+ node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision);
+
+ if ((cond->getQualifier().isConstant() && specConstantPropagates(*trueBlock, *falseBlock)) ||
+ (cond->getQualifier().isSpecConstant() && trueBlock->getQualifier().isConstant() &&
+ falseBlock->getQualifier().isConstant()))
+ node->getQualifier().makeSpecConstant();
+ else
+ node->getQualifier().makeTemporary();
+
+ if (getSource() == EShSourceHlsl)
+ node->setNoShortCircuit();
+
+ return node;
+}
+
+//
+// Constant terminal nodes. Has a union that contains bool, float or int constants
+//
+// Returns the constant union node created.
+//
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, const TSourceLoc& loc, bool literal) const
+{
+ TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t);
+ node->getQualifier().storage = EvqConst;
+ node->setLoc(loc);
+ if (literal)
+ node->setLiteral();
+
+ return node;
+}
+TIntermConstantUnion* TIntermediate::addConstantUnion(signed char i8, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setI8Const(i8);
+
+ return addConstantUnion(unionArray, TType(EbtInt8, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned char u8, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setUConst(u8);
+
+ return addConstantUnion(unionArray, TType(EbtUint8, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(signed short i16, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setI16Const(i16);
+
+ return addConstantUnion(unionArray, TType(EbtInt16, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned short u16, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setU16Const(u16);
+
+ return addConstantUnion(unionArray, TType(EbtUint16, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(int i, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setIConst(i);
+
+ return addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned int u, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setUConst(u);
+
+ return addConstantUnion(unionArray, TType(EbtUint, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(long long i64, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setI64Const(i64);
+
+ return addConstantUnion(unionArray, TType(EbtInt64, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned long long u64, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setU64Const(u64);
+
+ return addConstantUnion(unionArray, TType(EbtUint64, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(bool b, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setBConst(b);
+
+ return addConstantUnion(unionArray, TType(EbtBool, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseType, const TSourceLoc& loc, bool literal) const
+{
+ assert(baseType == EbtFloat || baseType == EbtDouble || baseType == EbtFloat16);
+
+ TConstUnionArray unionArray(1);
+ unionArray[0].setDConst(d);
+
+ return addConstantUnion(unionArray, TType(baseType, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(const TString* s, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setSConst(s);
+
+ return addConstantUnion(unionArray, TType(EbtString, EvqConst), loc, literal);
+}
+
+// Put vector swizzle selectors onto the given sequence
+void TIntermediate::pushSelector(TIntermSequence& sequence, const TVectorSelector& selector, const TSourceLoc& loc)
+{
+ TIntermConstantUnion* constIntNode = addConstantUnion(selector, loc);
+ sequence.push_back(constIntNode);
+}
+
+// Put matrix swizzle selectors onto the given sequence
+void TIntermediate::pushSelector(TIntermSequence& sequence, const TMatrixSelector& selector, const TSourceLoc& loc)
+{
+ TIntermConstantUnion* constIntNode = addConstantUnion(selector.coord1, loc);
+ sequence.push_back(constIntNode);
+ constIntNode = addConstantUnion(selector.coord2, loc);
+ sequence.push_back(constIntNode);
+}
+
+// Make an aggregate node that has a sequence of all selectors.
+template TIntermTyped* TIntermediate::addSwizzle<TVectorSelector>(TSwizzleSelectors<TVectorSelector>& selector, const TSourceLoc& loc);
+template TIntermTyped* TIntermediate::addSwizzle<TMatrixSelector>(TSwizzleSelectors<TMatrixSelector>& selector, const TSourceLoc& loc);
+template<typename selectorType>
+TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors<selectorType>& selector, const TSourceLoc& loc)
+{
+ TIntermAggregate* node = new TIntermAggregate(EOpSequence);
+
+ node->setLoc(loc);
+ TIntermSequence &sequenceVector = node->getSequence();
+
+ for (int i = 0; i < selector.size(); i++)
+ pushSelector(sequenceVector, selector[i], loc);
+
+ return node;
+}
+
+//
+// Follow the left branches down to the root of an l-value
+// expression (just "." and []).
+//
+// Return the base of the l-value (where following indexing quits working).
+// Return nullptr if a chain following dereferences cannot be followed.
+//
+// 'swizzleOkay' says whether or not it is okay to consider a swizzle
+// a valid part of the dereference chain.
+//
+const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay)
+{
+ do {
+ const TIntermBinary* binary = node->getAsBinaryNode();
+ if (binary == nullptr)
+ return node;
+ TOperator op = binary->getOp();
+ if (op != EOpIndexDirect && op != EOpIndexIndirect && op != EOpIndexDirectStruct && op != EOpVectorSwizzle && op != EOpMatrixSwizzle)
+ return nullptr;
+ if (! swizzleOkay) {
+ if (op == EOpVectorSwizzle || op == EOpMatrixSwizzle)
+ return nullptr;
+ if ((op == EOpIndexDirect || op == EOpIndexIndirect) &&
+ (binary->getLeft()->getType().isVector() || binary->getLeft()->getType().isScalar()) &&
+ ! binary->getLeft()->getType().isArray())
+ return nullptr;
+ }
+ node = node->getAsBinaryNode()->getLeft();
+ } while (true);
+}
+
+//
+// Create while and do-while loop nodes.
+//
+TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst,
+ const TSourceLoc& loc)
+{
+ TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
+ node->setLoc(loc);
+
+ return node;
+}
+
+//
+// Create a for-loop sequence.
+//
+TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test,
+ TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TIntermLoop*& node)
+{
+ node = new TIntermLoop(body, test, terminal, testFirst);
+ node->setLoc(loc);
+
+ // make a sequence of the initializer and statement, but try to reuse the
+ // aggregate already created for whatever is in the initializer, if there is one
+ TIntermAggregate* loopSequence = (initializer == nullptr ||
+ initializer->getAsAggregate() == nullptr) ? makeAggregate(initializer, loc)
+ : initializer->getAsAggregate();
+ if (loopSequence != nullptr && loopSequence->getOp() == EOpSequence)
+ loopSequence->setOp(EOpNull);
+ loopSequence = growAggregate(loopSequence, node);
+ loopSequence->setOperator(EOpSequence);
+
+ return loopSequence;
+}
+
+//
+// Add branches.
+//
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& loc)
+{
+ return addBranch(branchOp, nullptr, loc);
+}
+
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& loc)
+{
+ TIntermBranch* node = new TIntermBranch(branchOp, expression);
+ node->setLoc(loc);
+
+ return node;
+}
+
+//
+// This is to be executed after the final root is put on top by the parsing
+// process.
+//
+bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
+{
+ if (root == nullptr)
+ return true;
+
+ // Finish off the top-level sequence
+ TIntermAggregate* aggRoot = root->getAsAggregate();
+ if (aggRoot && aggRoot->getOp() == EOpNull)
+ aggRoot->setOperator(EOpSequence);
+
+#ifndef GLSLANG_WEB
+ // Propagate 'noContraction' label in backward from 'precise' variables.
+ glslang::PropagateNoContraction(*this);
+
+ switch (textureSamplerTransformMode) {
+ case EShTexSampTransKeep:
+ break;
+ case EShTexSampTransUpgradeTextureRemoveSampler:
+ performTextureUpgradeAndSamplerRemovalTransformation(root);
+ break;
+ }
+#endif
+
+ return true;
+}
+
+void TIntermediate::addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage language, TSymbolTable& symbolTable)
+{
+ // Add top-level nodes for declarations that must be checked cross
+ // compilation unit by a linker, yet might not have been referenced
+ // by the AST.
+ //
+ // Almost entirely, translation of symbols is driven by what's present
+ // in the AST traversal, not by translating the symbol table.
+ //
+ // However, there are some special cases:
+ // - From the specification: "Special built-in inputs gl_VertexID and
+ // gl_InstanceID are also considered active vertex attributes."
+ // - Linker-based type mismatch error reporting needs to see all
+ // uniforms/ins/outs variables and blocks.
+ // - ftransform() can make gl_Vertex and gl_ModelViewProjectionMatrix active.
+ //
+
+ // if (ftransformUsed) {
+ // TODO: 1.1 lowering functionality: track ftransform() usage
+ // addSymbolLinkageNode(root, symbolTable, "gl_Vertex");
+ // addSymbolLinkageNode(root, symbolTable, "gl_ModelViewProjectionMatrix");
+ //}
+
+ if (language == EShLangVertex) {
+ // the names won't be found in the symbol table unless the versions are right,
+ // so version logic does not need to be repeated here
+ addSymbolLinkageNode(linkage, symbolTable, "gl_VertexID");
+ addSymbolLinkageNode(linkage, symbolTable, "gl_InstanceID");
+ }
+
+ // Add a child to the root node for the linker objects
+ linkage->setOperator(EOpLinkerObjects);
+ treeRoot = growAggregate(treeRoot, linkage);
+}
+
+//
+// Add the given name or symbol to the list of nodes at the end of the tree used
+// for link-time checking and external linkage.
+//
+
+void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable& symbolTable, const TString& name)
+{
+ TSymbol* symbol = symbolTable.find(name);
+ if (symbol)
+ addSymbolLinkageNode(linkage, *symbol->getAsVariable());
+}
+
+void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol& symbol)
+{
+ const TVariable* variable = symbol.getAsVariable();
+ if (! variable) {
+ // This must be a member of an anonymous block, and we need to add the whole block
+ const TAnonMember* anon = symbol.getAsAnonMember();
+ variable = &anon->getAnonContainer();
+ }
+ TIntermSymbol* node = addSymbol(*variable);
+ linkage = growAggregate(linkage, node);
+}
+
+//
+// Add a caller->callee relationship to the call graph.
+// Assumes the strings are unique per signature.
+//
+void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& caller, const TString& callee)
+{
+ // Duplicates are okay, but faster to not keep them, and they come grouped by caller,
+ // as long as new ones are push on the same end we check on for duplicates
+ for (TGraph::const_iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
+ if (call->caller != caller)
+ break;
+ if (call->callee == callee)
+ return;
+ }
+
+ callGraph.push_front(TCall(caller, callee));
+}
+
+//
+// This deletes the tree.
+//
+void TIntermediate::removeTree()
+{
+ if (treeRoot)
+ RemoveAllTreeNodes(treeRoot);
+}
+
+//
+// Implement the part of KHR_vulkan_glsl that lists the set of operations
+// that can result in a specialization constant operation.
+//
+// "5.x Specialization Constant Operations"
+//
+// Only some operations discussed in this section may be applied to a
+// specialization constant and still yield a result that is as
+// specialization constant. The operations allowed are listed below.
+// When a specialization constant is operated on with one of these
+// operators and with another constant or specialization constant, the
+// result is implicitly a specialization constant.
+//
+// - int(), uint(), and bool() constructors for type conversions
+// from any of the following types to any of the following types:
+// * int
+// * uint
+// * bool
+// - vector versions of the above conversion constructors
+// - allowed implicit conversions of the above
+// - swizzles (e.g., foo.yx)
+// - The following when applied to integer or unsigned integer types:
+// * unary negative ( - )
+// * binary operations ( + , - , * , / , % )
+// * shift ( <<, >> )
+// * bitwise operations ( & , | , ^ )
+// - The following when applied to integer or unsigned integer scalar types:
+// * comparison ( == , != , > , >= , < , <= )
+// - The following when applied to the Boolean scalar type:
+// * not ( ! )
+// * logical operations ( && , || , ^^ )
+// * comparison ( == , != )"
+//
+// This function just handles binary and unary nodes. Construction
+// rules are handled in construction paths that are not covered by the unary
+// and binary paths, while required conversions will still show up here
+// as unary converters in the from a construction operator.
+//
+bool TIntermediate::isSpecializationOperation(const TIntermOperator& node) const
+{
+ // The operations resulting in floating point are quite limited
+ // (However, some floating-point operations result in bool, like ">",
+ // so are handled later.)
+ if (node.getType().isFloatingDomain()) {
+ switch (node.getOp()) {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ case EOpVectorSwizzle:
+ case EOpConvFloatToDouble:
+ case EOpConvDoubleToFloat:
+ case EOpConvFloat16ToFloat:
+ case EOpConvFloatToFloat16:
+ case EOpConvFloat16ToDouble:
+ case EOpConvDoubleToFloat16:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // Check for floating-point arguments
+ if (const TIntermBinary* bin = node.getAsBinaryNode())
+ if (bin->getLeft() ->getType().isFloatingDomain() ||
+ bin->getRight()->getType().isFloatingDomain())
+ return false;
+
+ // So, for now, we can assume everything left is non-floating-point...
+
+ // Now check for integer/bool-based operations
+ switch (node.getOp()) {
+
+ // dereference/swizzle
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ case EOpVectorSwizzle:
+
+ // (u)int* -> bool
+ case EOpConvInt8ToBool:
+ case EOpConvInt16ToBool:
+ case EOpConvIntToBool:
+ case EOpConvInt64ToBool:
+ case EOpConvUint8ToBool:
+ case EOpConvUint16ToBool:
+ case EOpConvUintToBool:
+ case EOpConvUint64ToBool:
+
+ // bool -> (u)int*
+ case EOpConvBoolToInt8:
+ case EOpConvBoolToInt16:
+ case EOpConvBoolToInt:
+ case EOpConvBoolToInt64:
+ case EOpConvBoolToUint8:
+ case EOpConvBoolToUint16:
+ case EOpConvBoolToUint:
+ case EOpConvBoolToUint64:
+
+ // int8_t -> (u)int*
+ case EOpConvInt8ToInt16:
+ case EOpConvInt8ToInt:
+ case EOpConvInt8ToInt64:
+ case EOpConvInt8ToUint8:
+ case EOpConvInt8ToUint16:
+ case EOpConvInt8ToUint:
+ case EOpConvInt8ToUint64:
+
+ // int16_t -> (u)int*
+ case EOpConvInt16ToInt8:
+ case EOpConvInt16ToInt:
+ case EOpConvInt16ToInt64:
+ case EOpConvInt16ToUint8:
+ case EOpConvInt16ToUint16:
+ case EOpConvInt16ToUint:
+ case EOpConvInt16ToUint64:
+
+ // int32_t -> (u)int*
+ case EOpConvIntToInt8:
+ case EOpConvIntToInt16:
+ case EOpConvIntToInt64:
+ case EOpConvIntToUint8:
+ case EOpConvIntToUint16:
+ case EOpConvIntToUint:
+ case EOpConvIntToUint64:
+
+ // int64_t -> (u)int*
+ case EOpConvInt64ToInt8:
+ case EOpConvInt64ToInt16:
+ case EOpConvInt64ToInt:
+ case EOpConvInt64ToUint8:
+ case EOpConvInt64ToUint16:
+ case EOpConvInt64ToUint:
+ case EOpConvInt64ToUint64:
+
+ // uint8_t -> (u)int*
+ case EOpConvUint8ToInt8:
+ case EOpConvUint8ToInt16:
+ case EOpConvUint8ToInt:
+ case EOpConvUint8ToInt64:
+ case EOpConvUint8ToUint16:
+ case EOpConvUint8ToUint:
+ case EOpConvUint8ToUint64:
+
+ // uint16_t -> (u)int*
+ case EOpConvUint16ToInt8:
+ case EOpConvUint16ToInt16:
+ case EOpConvUint16ToInt:
+ case EOpConvUint16ToInt64:
+ case EOpConvUint16ToUint8:
+ case EOpConvUint16ToUint:
+ case EOpConvUint16ToUint64:
+
+ // uint32_t -> (u)int*
+ case EOpConvUintToInt8:
+ case EOpConvUintToInt16:
+ case EOpConvUintToInt:
+ case EOpConvUintToInt64:
+ case EOpConvUintToUint8:
+ case EOpConvUintToUint16:
+ case EOpConvUintToUint64:
+
+ // uint64_t -> (u)int*
+ case EOpConvUint64ToInt8:
+ case EOpConvUint64ToInt16:
+ case EOpConvUint64ToInt:
+ case EOpConvUint64ToInt64:
+ case EOpConvUint64ToUint8:
+ case EOpConvUint64ToUint16:
+ case EOpConvUint64ToUint:
+
+ // unary operations
+ case EOpNegative:
+ case EOpLogicalNot:
+ case EOpBitwiseNot:
+
+ // binary operations
+ case EOpAdd:
+ case EOpSub:
+ case EOpMul:
+ case EOpVectorTimesScalar:
+ case EOpDiv:
+ case EOpMod:
+ case EOpRightShift:
+ case EOpLeftShift:
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ case EOpLogicalAnd:
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Is the operation one that must propagate nonuniform?
+bool TIntermediate::isNonuniformPropagating(TOperator op) const
+{
+ // "* All Operators in Section 5.1 (Operators), except for assignment,
+ // arithmetic assignment, and sequence
+ // * Component selection in Section 5.5
+ // * Matrix components in Section 5.6
+ // * Structure and Array Operations in Section 5.7, except for the length
+ // method."
+ switch (op) {
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+
+ case EOpNegative:
+ case EOpLogicalNot:
+ case EOpVectorLogicalNot:
+ case EOpBitwiseNot:
+
+ case EOpAdd:
+ case EOpSub:
+ case EOpMul:
+ case EOpDiv:
+ case EOpMod:
+ case EOpRightShift:
+ case EOpLeftShift:
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar:
+
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ case EOpLogicalAnd:
+
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ case EOpVectorSwizzle:
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+////////////////////////////////////////////////////////////////
+//
+// Member functions of the nodes used for building the tree.
+//
+////////////////////////////////////////////////////////////////
+
+//
+// Say whether or not an operation node changes the value of a variable.
+//
+// Returns true if state is modified.
+//
+bool TIntermOperator::modifiesState() const
+{
+ switch (op) {
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ case EOpLeftShiftAssign:
+ case EOpRightShiftAssign:
+ return true;
+ default:
+ return false;
+ }
+}
+
+//
+// returns true if the operator is for one of the constructors
+//
+bool TIntermOperator::isConstructor() const
+{
+ return op > EOpConstructGuardStart && op < EOpConstructGuardEnd;
+}
+
+//
+// Make sure the type of an operator is appropriate for its
+// combination of operation and operand type. This will invoke
+// promoteUnary, promoteBinary, etc as needed.
+//
+// Returns false if nothing makes sense.
+//
+bool TIntermediate::promote(TIntermOperator* node)
+{
+ if (node == nullptr)
+ return false;
+
+ if (node->getAsUnaryNode())
+ return promoteUnary(*node->getAsUnaryNode());
+
+ if (node->getAsBinaryNode())
+ return promoteBinary(*node->getAsBinaryNode());
+
+ if (node->getAsAggregate())
+ return promoteAggregate(*node->getAsAggregate());
+
+ return false;
+}
+
+//
+// See TIntermediate::promote
+//
+bool TIntermediate::promoteUnary(TIntermUnary& node)
+{
+ const TOperator op = node.getOp();
+ TIntermTyped* operand = node.getOperand();
+
+ switch (op) {
+ case EOpLogicalNot:
+ // Convert operand to a boolean type
+ if (operand->getBasicType() != EbtBool) {
+ // Add constructor to boolean type. If that fails, we can't do it, so return false.
+ TIntermTyped* converted = addConversion(op, TType(EbtBool), operand);
+ if (converted == nullptr)
+ return false;
+
+ // Use the result of converting the node to a bool.
+ node.setOperand(operand = converted); // also updates stack variable
+ }
+ break;
+ case EOpBitwiseNot:
+ if (!isTypeInt(operand->getBasicType()))
+ return false;
+ break;
+ case EOpNegative:
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ if (!isTypeInt(operand->getBasicType()) &&
+ operand->getBasicType() != EbtFloat &&
+ operand->getBasicType() != EbtFloat16 &&
+ operand->getBasicType() != EbtDouble)
+
+ return false;
+ break;
+
+ default:
+ if (operand->getBasicType() != EbtFloat)
+
+ return false;
+ }
+
+ node.setType(operand->getType());
+ node.getWritableType().getQualifier().makeTemporary();
+
+ return true;
+}
+
+void TIntermUnary::updatePrecision()
+{
+ if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
+ if (operand->getQualifier().precision > getQualifier().precision)
+ getQualifier().precision = operand->getQualifier().precision;
+ }
+}
+
+//
+// See TIntermediate::promote
+//
+bool TIntermediate::promoteBinary(TIntermBinary& node)
+{
+ TOperator op = node.getOp();
+ TIntermTyped* left = node.getLeft();
+ TIntermTyped* right = node.getRight();
+
+ // Arrays and structures have to be exact matches.
+ if ((left->isArray() || right->isArray() || left->getBasicType() == EbtStruct || right->getBasicType() == EbtStruct)
+ && left->getType() != right->getType())
+ return false;
+
+ // Base assumption: just make the type the same as the left
+ // operand. Only deviations from this will be coded.
+ node.setType(left->getType());
+ node.getWritableType().getQualifier().clear();
+
+ // Composite and opaque types don't having pending operator changes, e.g.,
+ // array, structure, and samplers. Just establish final type and correctness.
+ if (left->isArray() || left->getBasicType() == EbtStruct || left->getBasicType() == EbtSampler) {
+ switch (op) {
+ case EOpEqual:
+ case EOpNotEqual:
+ if (left->getBasicType() == EbtSampler) {
+ // can't compare samplers
+ return false;
+ } else {
+ // Promote to conditional
+ node.setType(TType(EbtBool));
+ }
+
+ return true;
+
+ case EOpAssign:
+ // Keep type from above
+
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ //
+ // We now have only scalars, vectors, and matrices to worry about.
+ //
+
+ // HLSL implicitly promotes bool -> int for numeric operations.
+ // (Implicit conversions to make the operands match each other's types were already done.)
+ if (getSource() == EShSourceHlsl &&
+ (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)) {
+ switch (op) {
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+
+ case EOpRightShift:
+ case EOpLeftShift:
+
+ case EOpMod:
+
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpMul:
+ if (left->getBasicType() == EbtBool)
+ left = createConversion(EbtInt, left);
+ if (right->getBasicType() == EbtBool)
+ right = createConversion(EbtInt, right);
+ if (left == nullptr || right == nullptr)
+ return false;
+ node.setLeft(left);
+ node.setRight(right);
+
+ // Update the original base assumption on result type..
+ node.setType(left->getType());
+ node.getWritableType().getQualifier().clear();
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // Do general type checks against individual operands (comparing left and right is coming up, checking mixed shapes after that)
+ switch (op) {
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ // Relational comparisons need numeric types and will promote to scalar Boolean.
+ if (left->getBasicType() == EbtBool)
+ return false;
+
+ node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize()));
+ break;
+
+ case EOpEqual:
+ case EOpNotEqual:
+ if (getSource() == EShSourceHlsl) {
+ const int resultWidth = std::max(left->getVectorSize(), right->getVectorSize());
+
+ // In HLSL, == or != on vectors means component-wise comparison.
+ if (resultWidth > 1) {
+ op = (op == EOpEqual) ? EOpVectorEqual : EOpVectorNotEqual;
+ node.setOp(op);
+ }
+
+ node.setType(TType(EbtBool, EvqTemporary, resultWidth));
+ } else {
+ // All the above comparisons result in a bool (but not the vector compares)
+ node.setType(TType(EbtBool));
+ }
+ break;
+
+ case EOpLogicalAnd:
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ // logical ops operate only on Booleans or vectors of Booleans.
+ if (left->getBasicType() != EbtBool || left->isMatrix())
+ return false;
+
+ if (getSource() == EShSourceGlsl) {
+ // logical ops operate only on scalar Booleans and will promote to scalar Boolean.
+ if (left->isVector())
+ return false;
+ }
+
+ node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize()));
+ break;
+
+ case EOpRightShift:
+ case EOpLeftShift:
+ case EOpRightShiftAssign:
+ case EOpLeftShiftAssign:
+
+ case EOpMod:
+ case EOpModAssign:
+
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ if (getSource() == EShSourceHlsl)
+ break;
+
+ // Check for integer-only operands.
+ if (!isTypeInt(left->getBasicType()) && !isTypeInt(right->getBasicType()))
+ return false;
+ if (left->isMatrix() || right->isMatrix())
+ return false;
+
+ break;
+
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpMul:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpDivAssign:
+ // check for non-Boolean operands
+ if (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)
+ return false;
+
+ default:
+ break;
+ }
+
+ // Compare left and right, and finish with the cases where the operand types must match
+ switch (op) {
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpVectorEqual:
+ case EOpVectorNotEqual:
+
+ case EOpLogicalAnd:
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ return left->getType() == right->getType();
+
+ case EOpMod:
+ case EOpModAssign:
+
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ // Quick out in case the types do match
+ if (left->getType() == right->getType())
+ return true;
+
+ // Fall through
+
+ case EOpMul:
+ case EOpMulAssign:
+ // At least the basic type has to match
+ if (left->getBasicType() != right->getBasicType())
+ return false;
+
+ default:
+ break;
+ }
+
+ if (left->getType().isCoopMat() || right->getType().isCoopMat()) {
+ if (left->getType().isCoopMat() && right->getType().isCoopMat() &&
+ *left->getType().getTypeParameters() != *right->getType().getTypeParameters()) {
+ return false;
+ }
+ switch (op) {
+ case EOpMul:
+ case EOpMulAssign:
+ if (left->getType().isCoopMat() && right->getType().isCoopMat()) {
+ return false;
+ }
+ if (op == EOpMulAssign && right->getType().isCoopMat()) {
+ return false;
+ }
+ node.setOp(op == EOpMulAssign ? EOpMatrixTimesScalarAssign : EOpMatrixTimesScalar);
+ if (right->getType().isCoopMat()) {
+ node.setType(right->getType());
+ }
+ return true;
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpAssign:
+ // These require both to be cooperative matrices
+ if (!left->getType().isCoopMat() || !right->getType().isCoopMat()) {
+ return false;
+ }
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ // Finish handling the case, for all ops, where both operands are scalars.
+ if (left->isScalar() && right->isScalar())
+ return true;
+
+ // Finish handling the case, for all ops, where there are two vectors of different sizes
+ if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize() && right->getVectorSize() > 1)
+ return false;
+
+ //
+ // We now have a mix of scalars, vectors, or matrices, for non-relational operations.
+ //
+
+ // Can these two operands be combined, what is the resulting type?
+ TBasicType basicType = left->getBasicType();
+ switch (op) {
+ case EOpMul:
+ if (!left->isMatrix() && right->isMatrix()) {
+ if (left->isVector()) {
+ if (left->getVectorSize() != right->getMatrixRows())
+ return false;
+ node.setOp(op = EOpVectorTimesMatrix);
+ node.setType(TType(basicType, EvqTemporary, right->getMatrixCols()));
+ } else {
+ node.setOp(op = EOpMatrixTimesScalar);
+ node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), right->getMatrixRows()));
+ }
+ } else if (left->isMatrix() && !right->isMatrix()) {
+ if (right->isVector()) {
+ if (left->getMatrixCols() != right->getVectorSize())
+ return false;
+ node.setOp(op = EOpMatrixTimesVector);
+ node.setType(TType(basicType, EvqTemporary, left->getMatrixRows()));
+ } else {
+ node.setOp(op = EOpMatrixTimesScalar);
+ }
+ } else if (left->isMatrix() && right->isMatrix()) {
+ if (left->getMatrixCols() != right->getMatrixRows())
+ return false;
+ node.setOp(op = EOpMatrixTimesMatrix);
+ node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), left->getMatrixRows()));
+ } else if (! left->isMatrix() && ! right->isMatrix()) {
+ if (left->isVector() && right->isVector()) {
+ ; // leave as component product
+ } else if (left->isVector() || right->isVector()) {
+ node.setOp(op = EOpVectorTimesScalar);
+ if (right->isVector())
+ node.setType(TType(basicType, EvqTemporary, right->getVectorSize()));
+ }
+ } else {
+ return false;
+ }
+ break;
+ case EOpMulAssign:
+ if (! left->isMatrix() && right->isMatrix()) {
+ if (left->isVector()) {
+ if (left->getVectorSize() != right->getMatrixRows() || left->getVectorSize() != right->getMatrixCols())
+ return false;
+ node.setOp(op = EOpVectorTimesMatrixAssign);
+ } else {
+ return false;
+ }
+ } else if (left->isMatrix() && !right->isMatrix()) {
+ if (right->isVector()) {
+ return false;
+ } else {
+ node.setOp(op = EOpMatrixTimesScalarAssign);
+ }
+ } else if (left->isMatrix() && right->isMatrix()) {
+ if (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixCols() != right->getMatrixRows())
+ return false;
+ node.setOp(op = EOpMatrixTimesMatrixAssign);
+ } else if (!left->isMatrix() && !right->isMatrix()) {
+ if (left->isVector() && right->isVector()) {
+ // leave as component product
+ } else if (left->isVector() || right->isVector()) {
+ if (! left->isVector())
+ return false;
+ node.setOp(op = EOpVectorTimesScalarAssign);
+ }
+ } else {
+ return false;
+ }
+ break;
+
+ case EOpRightShift:
+ case EOpLeftShift:
+ case EOpRightShiftAssign:
+ case EOpLeftShiftAssign:
+ if (right->isVector() && (! left->isVector() || right->getVectorSize() != left->getVectorSize()))
+ return false;
+ break;
+
+ case EOpAssign:
+ if (left->getVectorSize() != right->getVectorSize() || left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows())
+ return false;
+ // fall through
+
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpMod:
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+
+ if ((left->isMatrix() && right->isVector()) ||
+ (left->isVector() && right->isMatrix()) ||
+ left->getBasicType() != right->getBasicType())
+ return false;
+ if (left->isMatrix() && right->isMatrix() && (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows()))
+ return false;
+ if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize())
+ return false;
+ if (right->isVector() || right->isMatrix()) {
+ node.getWritableType().shallowCopy(right->getType());
+ node.getWritableType().getQualifier().makeTemporary();
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ //
+ // One more check for assignment.
+ //
+ switch (op) {
+ // The resulting type has to match the left operand.
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ case EOpLeftShiftAssign:
+ case EOpRightShiftAssign:
+ if (node.getType() != left->getType())
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+//
+// See TIntermediate::promote
+//
+bool TIntermediate::promoteAggregate(TIntermAggregate& node)
+{
+ TOperator op = node.getOp();
+ TIntermSequence& args = node.getSequence();
+ const int numArgs = static_cast<int>(args.size());
+
+ // Presently, only hlsl does intrinsic promotions.
+ if (getSource() != EShSourceHlsl)
+ return true;
+
+ // set of opcodes that can be promoted in this manner.
+ switch (op) {
+ case EOpAtan:
+ case EOpClamp:
+ case EOpCross:
+ case EOpDistance:
+ case EOpDot:
+ case EOpDst:
+ case EOpFaceForward:
+ // case EOpFindMSB: TODO:
+ // case EOpFindLSB: TODO:
+ case EOpFma:
+ case EOpMod:
+ case EOpFrexp:
+ case EOpLdexp:
+ case EOpMix:
+ case EOpLit:
+ case EOpMax:
+ case EOpMin:
+ case EOpModf:
+ // case EOpGenMul: TODO:
+ case EOpPow:
+ case EOpReflect:
+ case EOpRefract:
+ // case EOpSinCos: TODO:
+ case EOpSmoothStep:
+ case EOpStep:
+ break;
+ default:
+ return true;
+ }
+
+ // TODO: array and struct behavior
+
+ // Try converting all nodes to the given node's type
+ TIntermSequence convertedArgs(numArgs, nullptr);
+
+ // Try to convert all types to the nonConvArg type.
+ for (int nonConvArg = 0; nonConvArg < numArgs; ++nonConvArg) {
+ // Try converting all args to this arg's type
+ for (int convArg = 0; convArg < numArgs; ++convArg) {
+ convertedArgs[convArg] = addConversion(op, args[nonConvArg]->getAsTyped()->getType(),
+ args[convArg]->getAsTyped());
+ }
+
+ // If we successfully converted all the args, use the result.
+ if (std::all_of(convertedArgs.begin(), convertedArgs.end(),
+ [](const TIntermNode* node) { return node != nullptr; })) {
+
+ std::swap(args, convertedArgs);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void TIntermBinary::updatePrecision()
+{
+ if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
+ getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
+ if (getQualifier().precision != EpqNone) {
+ left->propagatePrecision(getQualifier().precision);
+ right->propagatePrecision(getQualifier().precision);
+ }
+ }
+}
+
+void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
+{
+ if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat && getBasicType() != EbtFloat16))
+ return;
+
+ getQualifier().precision = newPrecision;
+
+ TIntermBinary* binaryNode = getAsBinaryNode();
+ if (binaryNode) {
+ binaryNode->getLeft()->propagatePrecision(newPrecision);
+ binaryNode->getRight()->propagatePrecision(newPrecision);
+
+ return;
+ }
+
+ TIntermUnary* unaryNode = getAsUnaryNode();
+ if (unaryNode) {
+ unaryNode->getOperand()->propagatePrecision(newPrecision);
+
+ return;
+ }
+
+ TIntermAggregate* aggregateNode = getAsAggregate();
+ if (aggregateNode) {
+ TIntermSequence operands = aggregateNode->getSequence();
+ for (unsigned int i = 0; i < operands.size(); ++i) {
+ TIntermTyped* typedNode = operands[i]->getAsTyped();
+ if (! typedNode)
+ break;
+ typedNode->propagatePrecision(newPrecision);
+ }
+
+ return;
+ }
+
+ TIntermSelection* selectionNode = getAsSelectionNode();
+ if (selectionNode) {
+ TIntermTyped* typedNode = selectionNode->getTrueBlock()->getAsTyped();
+ if (typedNode) {
+ typedNode->propagatePrecision(newPrecision);
+ typedNode = selectionNode->getFalseBlock()->getAsTyped();
+ if (typedNode)
+ typedNode->propagatePrecision(newPrecision);
+ }
+
+ return;
+ }
+}
+
+TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) const
+{
+ const TConstUnionArray& rightUnionArray = node->getConstArray();
+ int size = node->getType().computeNumComponents();
+
+ TConstUnionArray leftUnionArray(size);
+
+ for (int i=0; i < size; i++) {
+
+#define PROMOTE(Set, CType, Get) leftUnionArray[i].Set(static_cast<CType>(rightUnionArray[i].Get()))
+#define PROMOTE_TO_BOOL(Get) leftUnionArray[i].setBConst(rightUnionArray[i].Get() != 0)
+
+#ifdef GLSLANG_WEB
+#define TO_ALL(Get) \
+ switch (promoteTo) { \
+ case EbtFloat: PROMOTE(setDConst, double, Get); break; \
+ case EbtInt: PROMOTE(setIConst, int, Get); break; \
+ case EbtUint: PROMOTE(setUConst, unsigned int, Get); break; \
+ case EbtBool: PROMOTE_TO_BOOL(Get); break; \
+ default: return node; \
+ }
+#else
+#define TO_ALL(Get) \
+ switch (promoteTo) { \
+ case EbtFloat16: PROMOTE(setDConst, double, Get); break; \
+ case EbtFloat: PROMOTE(setDConst, double, Get); break; \
+ case EbtDouble: PROMOTE(setDConst, double, Get); break; \
+ case EbtInt8: PROMOTE(setI8Const, char, Get); break; \
+ case EbtInt16: PROMOTE(setI16Const, short, Get); break; \
+ case EbtInt: PROMOTE(setIConst, int, Get); break; \
+ case EbtInt64: PROMOTE(setI64Const, long long, Get); break; \
+ case EbtUint8: PROMOTE(setU8Const, unsigned char, Get); break; \
+ case EbtUint16: PROMOTE(setU16Const, unsigned short, Get); break; \
+ case EbtUint: PROMOTE(setUConst, unsigned int, Get); break; \
+ case EbtUint64: PROMOTE(setU64Const, unsigned long long, Get); break; \
+ case EbtBool: PROMOTE_TO_BOOL(Get); break; \
+ default: return node; \
+ }
+#endif
+
+ switch (node->getType().getBasicType()) {
+ case EbtFloat: TO_ALL(getDConst); break;
+ case EbtInt: TO_ALL(getIConst); break;
+ case EbtUint: TO_ALL(getUConst); break;
+ case EbtBool: TO_ALL(getBConst); break;
+#ifndef GLSLANG_WEB
+ case EbtFloat16: TO_ALL(getDConst); break;
+ case EbtDouble: TO_ALL(getDConst); break;
+ case EbtInt8: TO_ALL(getI8Const); break;
+ case EbtInt16: TO_ALL(getI16Const); break;
+ case EbtInt64: TO_ALL(getI64Const); break;
+ case EbtUint8: TO_ALL(getU8Const); break;
+ case EbtUint16: TO_ALL(getU16Const); break;
+ case EbtUint64: TO_ALL(getU64Const); break;
+#endif
+ default: return node;
+ }
+ }
+
+ const TType& t = node->getType();
+
+ return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier().storage, t.getVectorSize(), t.getMatrixCols(), t.getMatrixRows()),
+ node->getLoc());
+}
+
+void TIntermAggregate::setPragmaTable(const TPragmaTable& pTable)
+{
+ assert(pragmaTable == nullptr);
+ pragmaTable = new TPragmaTable;
+ *pragmaTable = pTable;
+}
+
+// If either node is a specialization constant, while the other is
+// a constant (or specialization constant), the result is still
+// a specialization constant.
+bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TIntermTyped& node2)
+{
+ return (node1.getType().getQualifier().isSpecConstant() && node2.getType().getQualifier().isConstant()) ||
+ (node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant());
+}
+
+struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser {
+ void visitSymbol(TIntermSymbol* symbol) override {
+ if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) {
+ symbol->getWritableType().getSampler().setCombined(true);
+ }
+ }
+ bool visitAggregate(TVisit, TIntermAggregate* ag) override {
+ using namespace std;
+ TIntermSequence& seq = ag->getSequence();
+ TQualifierList& qual = ag->getQualifierList();
+
+ // qual and seq are indexed using the same indices, so we have to modify both in lock-step
+ assert(seq.size() == qual.size() || qual.empty());
+
+ size_t write = 0;
+ for (size_t i = 0; i < seq.size(); ++i) {
+ TIntermSymbol* symbol = seq[i]->getAsSymbolNode();
+ if (symbol && symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler()) {
+ // remove pure sampler variables
+ continue;
+ }
+
+ TIntermNode* result = seq[i];
+
+ // replace constructors with sampler/textures
+ TIntermAggregate *constructor = seq[i]->getAsAggregate();
+ if (constructor && constructor->getOp() == EOpConstructTextureSampler) {
+ if (!constructor->getSequence().empty())
+ result = constructor->getSequence()[0];
+ }
+
+ // write new node & qualifier
+ seq[write] = result;
+ if (!qual.empty())
+ qual[write] = qual[i];
+ write++;
+ }
+
+ seq.resize(write);
+ if (!qual.empty())
+ qual.resize(write);
+
+ return true;
+ }
+};
+
+void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root)
+{
+ TextureUpgradeAndSamplerRemovalTransform transform;
+ root->traverse(&transform);
+}
+
+const char* TIntermediate::getResourceName(TResourceType res)
+{
+ switch (res) {
+ case EResSampler: return "shift-sampler-binding";
+ case EResTexture: return "shift-texture-binding";
+ case EResImage: return "shift-image-binding";
+ case EResUbo: return "shift-UBO-binding";
+ case EResSsbo: return "shift-ssbo-binding";
+ case EResUav: return "shift-uav-binding";
+ default:
+ assert(0); // internal error: should only be called with valid resource types.
+ return nullptr;
+ }
+}
+
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/LiveTraverser.h b/thirdparty/glslang/glslang/MachineIndependent/LiveTraverser.h
new file mode 100644
index 0000000000..7333bc964e
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/LiveTraverser.h
@@ -0,0 +1,138 @@
+//
+// Copyright (C) 2016 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#pragma once
+
+#include "../Include/Common.h"
+#include "reflection.h"
+#include "localintermediate.h"
+
+#include "gl_types.h"
+
+#include <list>
+#include <unordered_set>
+
+namespace glslang {
+
+//
+// The traverser: mostly pass through, except
+// - processing function-call nodes to push live functions onto the stack of functions to process
+// - processing selection nodes to trim semantically dead code
+//
+// This is in the glslang namespace directly so it can be a friend of TReflection.
+// This can be derived from to implement reflection database traversers or
+// binding mappers: anything that wants to traverse the live subset of the tree.
+//
+
+class TLiveTraverser : public TIntermTraverser {
+public:
+ TLiveTraverser(const TIntermediate& i, bool traverseAll = false,
+ bool preVisit = true, bool inVisit = false, bool postVisit = false) :
+ TIntermTraverser(preVisit, inVisit, postVisit),
+ intermediate(i), traverseAll(traverseAll)
+ { }
+
+ //
+ // Given a function name, find its subroot in the tree, and push it onto the stack of
+ // functions left to process.
+ //
+ void pushFunction(const TString& name)
+ {
+ TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
+ for (unsigned int f = 0; f < globals.size(); ++f) {
+ TIntermAggregate* candidate = globals[f]->getAsAggregate();
+ if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
+ functions.push_back(candidate);
+ break;
+ }
+ }
+ }
+
+ typedef std::list<TIntermAggregate*> TFunctionStack;
+ TFunctionStack functions;
+
+protected:
+ // To catch which function calls are not dead, and hence which functions must be visited.
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node)
+ {
+ if (!traverseAll)
+ if (node->getOp() == EOpFunctionCall)
+ addFunctionCall(node);
+
+ return true; // traverse this subtree
+ }
+
+ // To prune semantically dead paths.
+ virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node)
+ {
+ if (traverseAll)
+ return true; // traverse all code
+
+ TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion();
+ if (constant) {
+ // cull the path that is dead
+ if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock())
+ node->getTrueBlock()->traverse(this);
+ if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock())
+ node->getFalseBlock()->traverse(this);
+
+ return false; // don't traverse any more, we did it all above
+ } else
+ return true; // traverse the whole subtree
+ }
+
+ // Track live functions as well as uniforms, so that we don't visit dead functions
+ // and only visit each function once.
+ void addFunctionCall(TIntermAggregate* call)
+ {
+ // // just use the map to ensure we process each function at most once
+ if (liveFunctions.find(call->getName()) == liveFunctions.end()) {
+ liveFunctions.insert(call->getName());
+ pushFunction(call->getName());
+ }
+ }
+
+ const TIntermediate& intermediate;
+ typedef std::unordered_set<TString> TLiveFunctions;
+ TLiveFunctions liveFunctions;
+ bool traverseAll;
+
+private:
+ // prevent copy & copy construct
+ TLiveTraverser(TLiveTraverser&);
+ TLiveTraverser& operator=(TLiveTraverser&);
+};
+
+} // namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp b/thirdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp
new file mode 100644
index 0000000000..282ecca0e0
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp
@@ -0,0 +1,638 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2016 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+// Implement the TParseContextBase class.
+
+#include <cstdarg>
+
+#include "ParseHelper.h"
+
+extern int yyparse(glslang::TParseContext*);
+
+namespace glslang {
+
+//
+// Used to output syntax, parsing, and semantic errors.
+//
+
+void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReason,
+ const char* szToken,
+ const char* szExtraInfoFormat,
+ TPrefixType prefix, va_list args)
+{
+ const int maxSize = MaxTokenLength + 200;
+ char szExtraInfo[maxSize];
+
+ safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args);
+
+ infoSink.info.prefix(prefix);
+ infoSink.info.location(loc);
+ infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
+
+ if (prefix == EPrefixError) {
+ ++numErrors;
+ }
+}
+
+#if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL)
+
+void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...)
+{
+ if (messages & EShMsgOnlyPreprocessor)
+ return;
+ va_list args;
+ va_start(args, szExtraInfoFormat);
+ outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
+ va_end(args);
+
+ if ((messages & EShMsgCascadingErrors) == 0)
+ currentScanner->setEndOfInput();
+}
+
+void C_DECL TParseContextBase::warn(const TSourceLoc& loc, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...)
+{
+ if (suppressWarnings())
+ return;
+ va_list args;
+ va_start(args, szExtraInfoFormat);
+ outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
+ va_end(args);
+}
+
+void C_DECL TParseContextBase::ppError(const TSourceLoc& loc, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...)
+{
+ va_list args;
+ va_start(args, szExtraInfoFormat);
+ outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
+ va_end(args);
+
+ if ((messages & EShMsgCascadingErrors) == 0)
+ currentScanner->setEndOfInput();
+}
+
+void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...)
+{
+ va_list args;
+ va_start(args, szExtraInfoFormat);
+ outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
+ va_end(args);
+}
+
+#endif
+
+//
+// Both test and if necessary, spit out an error, to see if the node is really
+// an l-value that can be operated on this way.
+//
+// Returns true if there was an error.
+//
+bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
+{
+ TIntermBinary* binaryNode = node->getAsBinaryNode();
+
+ if (binaryNode) {
+ switch(binaryNode->getOp()) {
+ case EOpIndexDirect:
+ case EOpIndexIndirect: // fall through
+ case EOpIndexDirectStruct: // fall through
+ case EOpVectorSwizzle:
+ case EOpMatrixSwizzle:
+ return lValueErrorCheck(loc, op, binaryNode->getLeft());
+ default:
+ break;
+ }
+ error(loc, " l-value required", op, "", "");
+
+ return true;
+ }
+
+ const char* symbol = nullptr;
+ TIntermSymbol* symNode = node->getAsSymbolNode();
+ if (symNode != nullptr)
+ symbol = symNode->getName().c_str();
+
+ const char* message = nullptr;
+ switch (node->getQualifier().storage) {
+ case EvqConst: message = "can't modify a const"; break;
+ case EvqConstReadOnly: message = "can't modify a const"; break;
+ case EvqUniform: message = "can't modify a uniform"; break;
+#ifndef GLSLANG_WEB
+ case EvqBuffer:
+ if (node->getQualifier().isReadOnly())
+ message = "can't modify a readonly buffer";
+ if (node->getQualifier().isShaderRecordNV())
+ message = "can't modify a shaderrecordnv qualified buffer";
+ break;
+ case EvqHitAttrNV:
+ if (language != EShLangIntersectNV)
+ message = "cannot modify hitAttributeNV in this stage";
+ break;
+#endif
+
+ default:
+ //
+ // Type that can't be written to?
+ //
+ switch (node->getBasicType()) {
+ case EbtSampler:
+ message = "can't modify a sampler";
+ break;
+ case EbtVoid:
+ message = "can't modify void";
+ break;
+#ifndef GLSLANG_WEB
+ case EbtAtomicUint:
+ message = "can't modify an atomic_uint";
+ break;
+ case EbtAccStructNV:
+ message = "can't modify accelerationStructureNV";
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+
+ if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
+ error(loc, " l-value required", op, "", "");
+
+ return true;
+ }
+
+ //
+ // Everything else is okay, no error.
+ //
+ if (message == nullptr)
+ return false;
+
+ //
+ // If we get here, we have an error and a message.
+ //
+ if (symNode)
+ error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
+ else
+ error(loc, " l-value required", op, "(%s)", message);
+
+ return true;
+}
+
+// Test for and give an error if the node can't be read from.
+void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
+{
+ if (! node)
+ return;
+
+ TIntermBinary* binaryNode = node->getAsBinaryNode();
+ if (binaryNode) {
+ switch(binaryNode->getOp()) {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ case EOpVectorSwizzle:
+ case EOpMatrixSwizzle:
+ rValueErrorCheck(loc, op, binaryNode->getLeft());
+ default:
+ break;
+ }
+
+ return;
+ }
+
+ TIntermSymbol* symNode = node->getAsSymbolNode();
+ if (symNode && symNode->getQualifier().isWriteOnly())
+ error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
+}
+
+// Add 'symbol' to the list of deferred linkage symbols, which
+// are later processed in finish(), at which point the symbol
+// must still be valid.
+// It is okay if the symbol's type will be subsequently edited;
+// the modifications will be tracked.
+// Order is preserved, to avoid creating novel forward references.
+void TParseContextBase::trackLinkage(TSymbol& symbol)
+{
+ if (!parsingBuiltins)
+ linkageSymbols.push_back(&symbol);
+}
+
+// Ensure index is in bounds, correct if necessary.
+// Give an error if not.
+void TParseContextBase::checkIndex(const TSourceLoc& loc, const TType& type, int& index)
+{
+ const auto sizeIsSpecializationExpression = [&type]() {
+ return type.containsSpecializationSize() &&
+ type.getArraySizes()->getOuterNode() != nullptr &&
+ type.getArraySizes()->getOuterNode()->getAsSymbolNode() == nullptr; };
+
+ if (index < 0) {
+ error(loc, "", "[", "index out of range '%d'", index);
+ index = 0;
+ } else if (type.isArray()) {
+ if (type.isSizedArray() && !sizeIsSpecializationExpression() &&
+ index >= type.getOuterArraySize()) {
+ error(loc, "", "[", "array index out of range '%d'", index);
+ index = type.getOuterArraySize() - 1;
+ }
+ } else if (type.isVector()) {
+ if (index >= type.getVectorSize()) {
+ error(loc, "", "[", "vector index out of range '%d'", index);
+ index = type.getVectorSize() - 1;
+ }
+ } else if (type.isMatrix()) {
+ if (index >= type.getMatrixCols()) {
+ error(loc, "", "[", "matrix index out of range '%d'", index);
+ index = type.getMatrixCols() - 1;
+ }
+ }
+}
+
+// Make a shared symbol have a non-shared version that can be edited by the current
+// compile, such that editing its type will not change the shared version and will
+// effect all nodes already sharing it (non-shallow type),
+// or adopting its full type after being edited (shallow type).
+void TParseContextBase::makeEditable(TSymbol*& symbol)
+{
+ // copyUp() does a deep copy of the type.
+ symbol = symbolTable.copyUp(symbol);
+
+ // Save it (deferred, so it can be edited first) in the AST for linker use.
+ if (symbol)
+ trackLinkage(*symbol);
+}
+
+// Return a writable version of the variable 'name'.
+//
+// Return nullptr if 'name' is not found. This should mean
+// something is seriously wrong (e.g., compiler asking self for
+// built-in that doesn't exist).
+TVariable* TParseContextBase::getEditableVariable(const char* name)
+{
+ bool builtIn;
+ TSymbol* symbol = symbolTable.find(name, &builtIn);
+
+ assert(symbol != nullptr);
+ if (symbol == nullptr)
+ return nullptr;
+
+ if (builtIn)
+ makeEditable(symbol);
+
+ return symbol->getAsVariable();
+}
+
+// Select the best matching function for 'call' from 'candidateList'.
+//
+// Assumptions
+//
+// There is no exact match, so a selection algorithm needs to run. That is, the
+// language-specific handler should check for exact match first, to
+// decide what to do, before calling this selector.
+//
+// Input
+//
+// * list of candidate signatures to select from
+// * the call
+// * a predicate function convertible(from, to) that says whether or not type
+// 'from' can implicitly convert to type 'to' (it includes the case of what
+// the calling language would consider a matching type with no conversion
+// needed)
+// * a predicate function better(from1, from2, to1, to2) that says whether or
+// not a conversion from <-> to2 is considered better than a conversion
+// from <-> to1 (both in and out directions need testing, as declared by the
+// formal parameter)
+//
+// Output
+//
+// * best matching candidate (or none, if no viable candidates found)
+// * whether there was a tie for the best match (ambiguous overload selection,
+// caller's choice for how to report)
+//
+const TFunction* TParseContextBase::selectFunction(
+ const TVector<const TFunction*> candidateList,
+ const TFunction& call,
+ std::function<bool(const TType& from, const TType& to, TOperator op, int arg)> convertible,
+ std::function<bool(const TType& from, const TType& to1, const TType& to2)> better,
+ /* output */ bool& tie)
+{
+//
+// Operation
+//
+// 1. Prune the input list of candidates down to a list of viable candidates,
+// where each viable candidate has
+//
+// * at least as many parameters as there are calling arguments, with any
+// remaining parameters being optional or having default values
+// * each parameter is true under convertible(A, B), where A is the calling
+// type for in and B is the formal type, and in addition, for out B is the
+// calling type and A is the formal type
+//
+// 2. If there are no viable candidates, return with no match.
+//
+// 3. If there is only one viable candidate, it is the best match.
+//
+// 4. If there are multiple viable candidates, select the first viable candidate
+// as the incumbent. Compare the incumbent to the next viable candidate, and if
+// that candidate is better (bullets below), make it the incumbent. Repeat, with
+// a linear walk through the viable candidate list. The final incumbent will be
+// returned as the best match. A viable candidate is better than the incumbent if
+//
+// * it has a function argument with a better(...) conversion than the incumbent,
+// for all directions needed by in and out
+// * the incumbent has no argument with a better(...) conversion then the
+// candidate, for either in or out (as needed)
+//
+// 5. Check for ambiguity by comparing the best match against all other viable
+// candidates. If any other viable candidate has a function argument with a
+// better(...) conversion than the best candidate (for either in or out
+// directions), return that there was a tie for best.
+//
+
+ tie = false;
+
+ // 1. prune to viable...
+ TVector<const TFunction*> viableCandidates;
+ for (auto it = candidateList.begin(); it != candidateList.end(); ++it) {
+ const TFunction& candidate = *(*it);
+
+ // to even be a potential match, number of arguments must be >= the number of
+ // fixed (non-default) parameters, and <= the total (including parameter with defaults).
+ if (call.getParamCount() < candidate.getFixedParamCount() ||
+ call.getParamCount() > candidate.getParamCount())
+ continue;
+
+ // see if arguments are convertible
+ bool viable = true;
+
+ // The call can have fewer parameters than the candidate, if some have defaults.
+ const int paramCount = std::min(call.getParamCount(), candidate.getParamCount());
+ for (int param = 0; param < paramCount; ++param) {
+ if (candidate[param].type->getQualifier().isParamInput()) {
+ if (! convertible(*call[param].type, *candidate[param].type, candidate.getBuiltInOp(), param)) {
+ viable = false;
+ break;
+ }
+ }
+ if (candidate[param].type->getQualifier().isParamOutput()) {
+ if (! convertible(*candidate[param].type, *call[param].type, candidate.getBuiltInOp(), param)) {
+ viable = false;
+ break;
+ }
+ }
+ }
+
+ if (viable)
+ viableCandidates.push_back(&candidate);
+ }
+
+ // 2. none viable...
+ if (viableCandidates.size() == 0)
+ return nullptr;
+
+ // 3. only one viable...
+ if (viableCandidates.size() == 1)
+ return viableCandidates.front();
+
+ // 4. find best...
+ const auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
+ // is call -> can2 better than call -> can1 for any parameter
+ bool hasBetterParam = false;
+ for (int param = 0; param < call.getParamCount(); ++param) {
+ if (better(*call[param].type, *can1[param].type, *can2[param].type)) {
+ hasBetterParam = true;
+ break;
+ }
+ }
+ return hasBetterParam;
+ };
+
+ const auto equivalentParams = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
+ // is call -> can2 equivalent to call -> can1 for all the call parameters?
+ for (int param = 0; param < call.getParamCount(); ++param) {
+ if (better(*call[param].type, *can1[param].type, *can2[param].type) ||
+ better(*call[param].type, *can2[param].type, *can1[param].type))
+ return false;
+ }
+ return true;
+ };
+
+ const TFunction* incumbent = viableCandidates.front();
+ for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) {
+ const TFunction& candidate = *(*it);
+ if (betterParam(*incumbent, candidate) && ! betterParam(candidate, *incumbent))
+ incumbent = &candidate;
+ }
+
+ // 5. ambiguity...
+ for (auto it = viableCandidates.begin(); it != viableCandidates.end(); ++it) {
+ if (incumbent == *it)
+ continue;
+ const TFunction& candidate = *(*it);
+
+ // In the case of default parameters, it may have an identical initial set, which is
+ // also ambiguous
+ if (betterParam(*incumbent, candidate) || equivalentParams(*incumbent, candidate))
+ tie = true;
+ }
+
+ return incumbent;
+}
+
+//
+// Look at a '.' field selector string and change it into numerical selectors
+// for a vector or scalar.
+//
+// Always return some form of swizzle, so the result is always usable.
+//
+void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TString& compString, int vecSize,
+ TSwizzleSelectors<TVectorSelector>& selector)
+{
+ // Too long?
+ if (compString.size() > MaxSwizzleSelectors)
+ error(loc, "vector swizzle too long", compString.c_str(), "");
+
+ // Use this to test that all swizzle characters are from the same swizzle-namespace-set
+ enum {
+ exyzw,
+ ergba,
+ estpq,
+ } fieldSet[MaxSwizzleSelectors];
+
+ // Decode the swizzle string.
+ int size = std::min(MaxSwizzleSelectors, (int)compString.size());
+ for (int i = 0; i < size; ++i) {
+ switch (compString[i]) {
+ case 'x':
+ selector.push_back(0);
+ fieldSet[i] = exyzw;
+ break;
+ case 'r':
+ selector.push_back(0);
+ fieldSet[i] = ergba;
+ break;
+ case 's':
+ selector.push_back(0);
+ fieldSet[i] = estpq;
+ break;
+
+ case 'y':
+ selector.push_back(1);
+ fieldSet[i] = exyzw;
+ break;
+ case 'g':
+ selector.push_back(1);
+ fieldSet[i] = ergba;
+ break;
+ case 't':
+ selector.push_back(1);
+ fieldSet[i] = estpq;
+ break;
+
+ case 'z':
+ selector.push_back(2);
+ fieldSet[i] = exyzw;
+ break;
+ case 'b':
+ selector.push_back(2);
+ fieldSet[i] = ergba;
+ break;
+ case 'p':
+ selector.push_back(2);
+ fieldSet[i] = estpq;
+ break;
+
+ case 'w':
+ selector.push_back(3);
+ fieldSet[i] = exyzw;
+ break;
+ case 'a':
+ selector.push_back(3);
+ fieldSet[i] = ergba;
+ break;
+ case 'q':
+ selector.push_back(3);
+ fieldSet[i] = estpq;
+ break;
+
+ default:
+ error(loc, "unknown swizzle selection", compString.c_str(), "");
+ break;
+ }
+ }
+
+ // Additional error checking.
+ for (int i = 0; i < selector.size(); ++i) {
+ if (selector[i] >= vecSize) {
+ error(loc, "vector swizzle selection out of range", compString.c_str(), "");
+ selector.resize(i);
+ break;
+ }
+
+ if (i > 0 && fieldSet[i] != fieldSet[i-1]) {
+ error(loc, "vector swizzle selectors not from the same set", compString.c_str(), "");
+ selector.resize(i);
+ break;
+ }
+ }
+
+ // Ensure it is valid.
+ if (selector.size() == 0)
+ selector.push_back(0);
+}
+
+#ifdef ENABLE_HLSL
+//
+// Make the passed-in variable information become a member of the
+// global uniform block. If this doesn't exist yet, make it.
+//
+void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
+{
+ // Make the global block, if not yet made.
+ if (globalUniformBlock == nullptr) {
+ TQualifier blockQualifier;
+ blockQualifier.clear();
+ blockQualifier.storage = EvqUniform;
+ TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier);
+ setUniformBlockDefaults(blockType);
+ globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true);
+ firstNewMember = 0;
+ }
+
+ // Update with binding and set
+ globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding;
+ globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet;
+
+ // Add the requested member as a member to the global block.
+ TType* type = new TType;
+ type->shallowCopy(memberType);
+ type->setFieldName(memberName);
+ if (typeList)
+ type->setStruct(typeList);
+ TTypeLoc typeLoc = {type, loc};
+ globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc);
+
+ // Insert into the symbol table.
+ if (firstNewMember == 0) {
+ // This is the first request; we need a normal symbol table insert
+ if (symbolTable.insert(*globalUniformBlock))
+ trackLinkage(*globalUniformBlock);
+ else
+ error(loc, "failed to insert the global constant buffer", "uniform", "");
+ } else {
+ // This is a follow-on request; we need to amend the first insert
+ symbolTable.amend(*globalUniformBlock, firstNewMember);
+ }
+
+ ++firstNewMember;
+}
+#endif
+
+void TParseContextBase::finish()
+{
+ if (parsingBuiltins)
+ return;
+
+ // Transfer the linkage symbols to AST nodes, preserving order.
+ TIntermAggregate* linkage = new TIntermAggregate;
+ for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i)
+ intermediate.addSymbolLinkageNode(linkage, **i);
+ intermediate.addSymbolLinkageNodes(linkage, getLanguage(), symbolTable);
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp b/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp
new file mode 100644
index 0000000000..a2224e1609
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp
@@ -0,0 +1,8326 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2015 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2017, 2019 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "ParseHelper.h"
+#include "Scan.h"
+
+#include "../OSDependent/osinclude.h"
+#include <algorithm>
+
+#include "preprocessor/PpContext.h"
+
+extern int yyparse(glslang::TParseContext*);
+
+namespace glslang {
+
+TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins,
+ int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
+ TInfoSink& infoSink, bool forwardCompatible, EShMessages messages,
+ const TString* entryPoint) :
+ TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language,
+ infoSink, forwardCompatible, messages, entryPoint),
+ inMain(false),
+ blockName(nullptr),
+ limits(resources.limits)
+#ifndef GLSLANG_WEB
+ ,
+ atomicUintOffsets(nullptr), anyIndexLimits(false)
+#endif
+{
+ // decide whether precision qualifiers should be ignored or respected
+ if (isEsProfile() || spvVersion.vulkan > 0) {
+ precisionManager.respectPrecisionQualifiers();
+ if (! parsingBuiltins && language == EShLangFragment && !isEsProfile() && spvVersion.vulkan > 0)
+ precisionManager.warnAboutDefaults();
+ }
+
+ setPrecisionDefaults();
+
+ globalUniformDefaults.clear();
+ globalUniformDefaults.layoutMatrix = ElmColumnMajor;
+ globalUniformDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd140 : ElpShared;
+
+ globalBufferDefaults.clear();
+ globalBufferDefaults.layoutMatrix = ElmColumnMajor;
+ globalBufferDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd430 : ElpShared;
+
+ // use storage buffer on SPIR-V 1.3 and up
+ if (spvVersion.spv >= EShTargetSpv_1_3)
+ intermediate.setUseStorageBuffer();
+
+ globalInputDefaults.clear();
+ globalOutputDefaults.clear();
+
+#ifndef GLSLANG_WEB
+ // "Shaders in the transform
+ // feedback capturing mode have an initial global default of
+ // layout(xfb_buffer = 0) out;"
+ if (language == EShLangVertex ||
+ language == EShLangTessControl ||
+ language == EShLangTessEvaluation ||
+ language == EShLangGeometry)
+ globalOutputDefaults.layoutXfbBuffer = 0;
+
+ if (language == EShLangGeometry)
+ globalOutputDefaults.layoutStream = 0;
+#endif
+
+ if (entryPoint != nullptr && entryPoint->size() > 0 && *entryPoint != "main")
+ infoSink.info.message(EPrefixError, "Source entry point must be \"main\"");
+}
+
+TParseContext::~TParseContext()
+{
+#ifndef GLSLANG_WEB
+ delete [] atomicUintOffsets;
+#endif
+}
+
+// Set up all default precisions as needed by the current environment.
+// Intended just as a TParseContext constructor helper.
+void TParseContext::setPrecisionDefaults()
+{
+ // Set all precision defaults to EpqNone, which is correct for all types
+ // when not obeying precision qualifiers, and correct for types that don't
+ // have defaults (thus getting an error on use) when obeying precision
+ // qualifiers.
+
+ for (int type = 0; type < EbtNumTypes; ++type)
+ defaultPrecision[type] = EpqNone;
+
+ for (int type = 0; type < maxSamplerIndex; ++type)
+ defaultSamplerPrecision[type] = EpqNone;
+
+ // replace with real precision defaults for those that have them
+ if (obeyPrecisionQualifiers()) {
+ if (isEsProfile()) {
+ // Most don't have defaults, a few default to lowp.
+ TSampler sampler;
+ sampler.set(EbtFloat, Esd2D);
+ defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
+ sampler.set(EbtFloat, EsdCube);
+ defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
+ sampler.set(EbtFloat, Esd2D);
+ sampler.setExternal(true);
+ defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
+ }
+
+ // If we are parsing built-in computational variables/functions, it is meaningful to record
+ // whether the built-in has no precision qualifier, as that ambiguity
+ // is used to resolve the precision from the supplied arguments/operands instead.
+ // So, we don't actually want to replace EpqNone with a default precision for built-ins.
+ if (! parsingBuiltins) {
+ if (isEsProfile() && language == EShLangFragment) {
+ defaultPrecision[EbtInt] = EpqMedium;
+ defaultPrecision[EbtUint] = EpqMedium;
+ } else {
+ defaultPrecision[EbtInt] = EpqHigh;
+ defaultPrecision[EbtUint] = EpqHigh;
+ defaultPrecision[EbtFloat] = EpqHigh;
+ }
+
+ if (!isEsProfile()) {
+ // Non-ES profile
+ // All sampler precisions default to highp.
+ for (int type = 0; type < maxSamplerIndex; ++type)
+ defaultSamplerPrecision[type] = EpqHigh;
+ }
+ }
+
+ defaultPrecision[EbtSampler] = EpqLow;
+ defaultPrecision[EbtAtomicUint] = EpqHigh;
+ }
+}
+
+void TParseContext::setLimits(const TBuiltInResource& r)
+{
+ resources = r;
+ intermediate.setLimits(r);
+
+#ifndef GLSLANG_WEB
+ anyIndexLimits = ! limits.generalAttributeMatrixVectorIndexing ||
+ ! limits.generalConstantMatrixVectorIndexing ||
+ ! limits.generalSamplerIndexing ||
+ ! limits.generalUniformIndexing ||
+ ! limits.generalVariableIndexing ||
+ ! limits.generalVaryingIndexing;
+
+
+ // "Each binding point tracks its own current default offset for
+ // inheritance of subsequent variables using the same binding. The initial state of compilation is that all
+ // binding points have an offset of 0."
+ atomicUintOffsets = new int[resources.maxAtomicCounterBindings];
+ for (int b = 0; b < resources.maxAtomicCounterBindings; ++b)
+ atomicUintOffsets[b] = 0;
+#endif
+}
+
+//
+// Parse an array of strings using yyparse, going through the
+// preprocessor to tokenize the shader strings, then through
+// the GLSL scanner.
+//
+// Returns true for successful acceptance of the shader, false if any errors.
+//
+bool TParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner& input, bool versionWillBeError)
+{
+ currentScanner = &input;
+ ppContext.setInput(input, versionWillBeError);
+ yyparse(this);
+
+ finish();
+
+ return numErrors == 0;
+}
+
+// This is called from bison when it has a parse (syntax) error
+// Note though that to stop cascading errors, we set EOF, which
+// will usually cause a syntax error, so be more accurate that
+// compilation is terminating.
+void TParseContext::parserError(const char* s)
+{
+ if (! getScanner()->atEndOfInput() || numErrors == 0)
+ error(getCurrentLoc(), "", "", s, "");
+ else
+ error(getCurrentLoc(), "compilation terminated", "", "");
+}
+
+void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
+{
+#ifndef GLSLANG_WEB
+ if (pragmaCallback)
+ pragmaCallback(loc.line, tokens);
+
+ if (tokens.size() == 0)
+ return;
+
+ if (tokens[0].compare("optimize") == 0) {
+ if (tokens.size() != 4) {
+ error(loc, "optimize pragma syntax is incorrect", "#pragma", "");
+ return;
+ }
+
+ if (tokens[1].compare("(") != 0) {
+ error(loc, "\"(\" expected after 'optimize' keyword", "#pragma", "");
+ return;
+ }
+
+ if (tokens[2].compare("on") == 0)
+ contextPragma.optimize = true;
+ else if (tokens[2].compare("off") == 0)
+ contextPragma.optimize = false;
+ else {
+ error(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", "");
+ return;
+ }
+
+ if (tokens[3].compare(")") != 0) {
+ error(loc, "\")\" expected to end 'optimize' pragma", "#pragma", "");
+ return;
+ }
+ } else if (tokens[0].compare("debug") == 0) {
+ if (tokens.size() != 4) {
+ error(loc, "debug pragma syntax is incorrect", "#pragma", "");
+ return;
+ }
+
+ if (tokens[1].compare("(") != 0) {
+ error(loc, "\"(\" expected after 'debug' keyword", "#pragma", "");
+ return;
+ }
+
+ if (tokens[2].compare("on") == 0)
+ contextPragma.debug = true;
+ else if (tokens[2].compare("off") == 0)
+ contextPragma.debug = false;
+ else {
+ error(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", "");
+ return;
+ }
+
+ if (tokens[3].compare(")") != 0) {
+ error(loc, "\")\" expected to end 'debug' pragma", "#pragma", "");
+ return;
+ }
+ } else if (spvVersion.spv > 0 && tokens[0].compare("use_storage_buffer") == 0) {
+ if (tokens.size() != 1)
+ error(loc, "extra tokens", "#pragma", "");
+ intermediate.setUseStorageBuffer();
+ } else if (spvVersion.spv > 0 && tokens[0].compare("use_vulkan_memory_model") == 0) {
+ if (tokens.size() != 1)
+ error(loc, "extra tokens", "#pragma", "");
+ intermediate.setUseVulkanMemoryModel();
+ } else if (spvVersion.spv > 0 && tokens[0].compare("use_variable_pointers") == 0) {
+ if (tokens.size() != 1)
+ error(loc, "extra tokens", "#pragma", "");
+ if (spvVersion.spv < glslang::EShTargetSpv_1_3)
+ error(loc, "requires SPIR-V 1.3", "#pragma use_variable_pointers", "");
+ intermediate.setUseVariablePointers();
+ } else if (tokens[0].compare("once") == 0) {
+ warn(loc, "not implemented", "#pragma once", "");
+ } else if (tokens[0].compare("glslang_binary_double_output") == 0)
+ intermediate.setBinaryDoubleOutput();
+#endif
+}
+
+//
+// Handle seeing a variable identifier in the grammar.
+//
+TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symbol, const TString* string)
+{
+ TIntermTyped* node = nullptr;
+
+ // Error check for requiring specific extensions present.
+ if (symbol && symbol->getNumExtensions())
+ requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str());
+
+#ifndef GLSLANG_WEB
+ if (symbol && symbol->isReadOnly()) {
+ // All shared things containing an unsized array must be copied up
+ // on first use, so that all future references will share its array structure,
+ // so that editing the implicit size will effect all nodes consuming it,
+ // and so that editing the implicit size won't change the shared one.
+ //
+ // If this is a variable or a block, check it and all it contains, but if this
+ // is a member of an anonymous block, check the whole block, as the whole block
+ // will need to be copied up if it contains an unsized array.
+ //
+ // This check is being done before the block-name check further down, so guard
+ // for that too.
+ if (!symbol->getType().isUnusableName()) {
+ if (symbol->getType().containsUnsizedArray() ||
+ (symbol->getAsAnonMember() &&
+ symbol->getAsAnonMember()->getAnonContainer().getType().containsUnsizedArray()))
+ makeEditable(symbol);
+ }
+ }
+#endif
+
+ const TVariable* variable;
+ const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr;
+ if (anon) {
+ // It was a member of an anonymous container.
+
+ // Create a subtree for its dereference.
+ variable = anon->getAnonContainer().getAsVariable();
+ TIntermTyped* container = intermediate.addSymbol(*variable, loc);
+ TIntermTyped* constNode = intermediate.addConstantUnion(anon->getMemberNumber(), loc);
+ node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc);
+
+ node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type);
+ if (node->getType().hiddenMember())
+ error(loc, "member of nameless block was not redeclared", string->c_str(), "");
+ } else {
+ // Not a member of an anonymous container.
+
+ // The symbol table search was done in the lexical phase.
+ // See if it was a variable.
+ variable = symbol ? symbol->getAsVariable() : nullptr;
+ if (variable) {
+ if (variable->getType().isUnusableName()) {
+ error(loc, "cannot be used (maybe an instance name is needed)", string->c_str(), "");
+ variable = nullptr;
+ }
+ } else {
+ if (symbol)
+ error(loc, "variable name expected", string->c_str(), "");
+ }
+
+ // Recovery, if it wasn't found or was not a variable.
+ if (! variable)
+ variable = new TVariable(string, TType(EbtVoid));
+
+ if (variable->getType().getQualifier().isFrontEndConstant())
+ node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc);
+ else
+ node = intermediate.addSymbol(*variable, loc);
+ }
+
+ if (variable->getType().getQualifier().isIo())
+ intermediate.addIoAccessed(*string);
+
+ if (variable->getType().isReference() &&
+ variable->getType().getQualifier().bufferReferenceNeedsVulkanMemoryModel()) {
+ intermediate.setUseVulkanMemoryModel();
+ }
+
+ return node;
+}
+
+//
+// Handle seeing a base[index] dereference in the grammar.
+//
+TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index)
+{
+ int indexValue = 0;
+ if (index->getQualifier().isFrontEndConstant())
+ indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
+
+ // basic type checks...
+ variableCheck(base);
+
+ if (! base->isArray() && ! base->isMatrix() && ! base->isVector() && ! base->getType().isCoopMat() &&
+ ! base->isReference()) {
+ if (base->getAsSymbolNode())
+ error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), "");
+ else
+ error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", "");
+
+ // Insert dummy error-recovery result
+ return intermediate.addConstantUnion(0.0, EbtFloat, loc);
+ }
+
+ if (!base->isArray() && base->isVector()) {
+ if (base->getType().contains16BitFloat())
+ requireFloat16Arithmetic(loc, "[", "does not operate on types containing float16");
+ if (base->getType().contains16BitInt())
+ requireInt16Arithmetic(loc, "[", "does not operate on types containing (u)int16");
+ if (base->getType().contains8BitInt())
+ requireInt8Arithmetic(loc, "[", "does not operate on types containing (u)int8");
+ }
+
+ // check for constant folding
+ if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) {
+ // both base and index are front-end constants
+ checkIndex(loc, base->getType(), indexValue);
+ return intermediate.foldDereference(base, indexValue, loc);
+ }
+
+ // at least one of base and index is not a front-end constant variable...
+ TIntermTyped* result = nullptr;
+
+#ifndef GLSLANG_WEB
+ if (base->isReference() && ! base->isArray()) {
+ requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference indexing");
+ result = intermediate.addBinaryMath(EOpAdd, base, index, loc);
+ result->setType(base->getType());
+ return result;
+ }
+ if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
+ handleIoResizeArrayAccess(loc, base);
+#endif
+
+ if (index->getQualifier().isFrontEndConstant())
+ checkIndex(loc, base->getType(), indexValue);
+
+ if (index->getQualifier().isFrontEndConstant()) {
+#ifndef GLSLANG_WEB
+ if (base->getType().isUnsizedArray()) {
+ base->getWritableType().updateImplicitArraySize(indexValue + 1);
+ // For 2D per-view builtin arrays, update the inner dimension size in parent type
+ if (base->getQualifier().isPerView() && base->getQualifier().builtIn != EbvNone) {
+ TIntermBinary* binaryNode = base->getAsBinaryNode();
+ if (binaryNode) {
+ TType& leftType = binaryNode->getLeft()->getWritableType();
+ TArraySizes& arraySizes = *leftType.getArraySizes();
+ assert(arraySizes.getNumDims() == 2);
+ arraySizes.setDimSize(1, std::max(arraySizes.getDimSize(1), indexValue + 1));
+ }
+ }
+ } else
+#endif
+ checkIndex(loc, base->getType(), indexValue);
+ result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
+ } else {
+#ifndef GLSLANG_WEB
+ if (base->getType().isUnsizedArray()) {
+ // we have a variable index into an unsized array, which is okay,
+ // depending on the situation
+ if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
+ error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable");
+ else {
+ // it is okay for a run-time sized array
+ checkRuntimeSizable(loc, *base);
+ }
+ base->getWritableType().setArrayVariablyIndexed();
+ }
+#endif
+ if (base->getBasicType() == EbtBlock) {
+ if (base->getQualifier().storage == EvqBuffer)
+ requireProfile(base->getLoc(), ~EEsProfile, "variable indexing buffer block array");
+ else if (base->getQualifier().storage == EvqUniform)
+ profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5,
+ "variable indexing uniform block array");
+ else {
+ // input/output blocks either don't exist or can't be variably indexed
+ }
+ } else if (language == EShLangFragment && base->getQualifier().isPipeOutput())
+ requireProfile(base->getLoc(), ~EEsProfile, "variable indexing fragment shader output array");
+ else if (base->getBasicType() == EbtSampler && version >= 130) {
+ const char* explanation = "variable indexing sampler array";
+ requireProfile(base->getLoc(), EEsProfile | ECoreProfile | ECompatibilityProfile, explanation);
+ profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, explanation);
+ profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, nullptr, explanation);
+ }
+
+ result = intermediate.addIndex(EOpIndexIndirect, base, index, loc);
+ }
+
+ // Insert valid dereferenced result type
+ TType newType(base->getType(), 0);
+ if (base->getType().getQualifier().isConstant() && index->getQualifier().isConstant()) {
+ newType.getQualifier().storage = EvqConst;
+ // If base or index is a specialization constant, the result should also be a specialization constant.
+ if (base->getType().getQualifier().isSpecConstant() || index->getQualifier().isSpecConstant()) {
+ newType.getQualifier().makeSpecConstant();
+ }
+ } else {
+ newType.getQualifier().storage = EvqTemporary;
+ newType.getQualifier().specConstant = false;
+ }
+ result->setType(newType);
+
+#ifndef GLSLANG_WEB
+ inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier());
+
+ // Propagate nonuniform
+ if (base->getQualifier().isNonUniform() || index->getQualifier().isNonUniform())
+ result->getWritableType().getQualifier().nonUniform = true;
+
+ if (anyIndexLimits)
+ handleIndexLimits(loc, base, index);
+#endif
+
+ return result;
+}
+
+#ifndef GLSLANG_WEB
+
+// for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms
+void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* base, TIntermTyped* index)
+{
+ if ((! limits.generalSamplerIndexing && base->getBasicType() == EbtSampler) ||
+ (! limits.generalUniformIndexing && base->getQualifier().isUniformOrBuffer() && language != EShLangVertex) ||
+ (! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) ||
+ (! limits.generalConstantMatrixVectorIndexing && base->getAsConstantUnion()) ||
+ (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniformOrBuffer() &&
+ ! base->getType().getQualifier().isPipeInput() &&
+ ! base->getType().getQualifier().isPipeOutput() &&
+ ! base->getType().getQualifier().isConstant()) ||
+ (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() ||
+ base->getType().getQualifier().isPipeOutput()))) {
+ // it's too early to know what the inductive variables are, save it for post processing
+ needsIndexLimitationChecking.push_back(index);
+ }
+}
+
+// Make a shared symbol have a non-shared version that can be edited by the current
+// compile, such that editing its type will not change the shared version and will
+// effect all nodes sharing it.
+void TParseContext::makeEditable(TSymbol*& symbol)
+{
+ TParseContextBase::makeEditable(symbol);
+
+ // See if it's tied to IO resizing
+ if (isIoResizeArray(symbol->getType()))
+ ioArraySymbolResizeList.push_back(symbol);
+}
+
+// Return true if this is a geometry shader input array or tessellation control output array
+// or mesh shader output array.
+bool TParseContext::isIoResizeArray(const TType& type) const
+{
+ return type.isArray() &&
+ ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) ||
+ (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut &&
+ ! type.getQualifier().patch) ||
+ (language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn &&
+ type.getQualifier().pervertexNV) ||
+ (language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut &&
+ !type.getQualifier().perTaskNV));
+}
+
+// If an array is not isIoResizeArray() but is an io array, make sure it has the right size
+void TParseContext::fixIoArraySize(const TSourceLoc& loc, TType& type)
+{
+ if (! type.isArray() || type.getQualifier().patch || symbolTable.atBuiltInLevel())
+ return;
+
+ assert(! isIoResizeArray(type));
+
+ if (type.getQualifier().storage != EvqVaryingIn || type.getQualifier().patch)
+ return;
+
+ if (language == EShLangTessControl || language == EShLangTessEvaluation) {
+ if (type.getOuterArraySize() != resources.maxPatchVertices) {
+ if (type.isSizedArray())
+ error(loc, "tessellation input array size must be gl_MaxPatchVertices or implicitly sized", "[]", "");
+ type.changeOuterArraySize(resources.maxPatchVertices);
+ }
+ }
+}
+
+// Issue any errors if the non-array object is missing arrayness WRT
+// shader I/O that has array requirements.
+// All arrayness checking is handled in array paths, this is for
+void TParseContext::ioArrayCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
+{
+ if (! type.isArray() && ! symbolTable.atBuiltInLevel()) {
+ if (type.getQualifier().isArrayedIo(language) && !type.getQualifier().layoutPassthrough)
+ error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str());
+ }
+}
+
+// Handle a dereference of a geometry shader input array or tessellation control output array.
+// See ioArraySymbolResizeList comment in ParseHelper.h.
+//
+void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TIntermTyped* base)
+{
+ TIntermSymbol* symbolNode = base->getAsSymbolNode();
+ assert(symbolNode);
+ if (! symbolNode)
+ return;
+
+ // fix array size, if it can be fixed and needs to be fixed (will allow variable indexing)
+ if (symbolNode->getType().isUnsizedArray()) {
+ int newSize = getIoArrayImplicitSize(symbolNode->getType().getQualifier());
+ if (newSize > 0)
+ symbolNode->getWritableType().changeOuterArraySize(newSize);
+ }
+}
+
+// If there has been an input primitive declaration (geometry shader) or an output
+// number of vertices declaration(tessellation shader), make sure all input array types
+// match it in size. Types come either from nodes in the AST or symbols in the
+// symbol table.
+//
+// Types without an array size will be given one.
+// Types already having a size that is wrong will get an error.
+//
+void TParseContext::checkIoArraysConsistency(const TSourceLoc &loc, bool tailOnly)
+{
+ int requiredSize = 0;
+ TString featureString;
+ size_t listSize = ioArraySymbolResizeList.size();
+ size_t i = 0;
+
+ // If tailOnly = true, only check the last array symbol in the list.
+ if (tailOnly) {
+ i = listSize - 1;
+ }
+ for (bool firstIteration = true; i < listSize; ++i) {
+ TType &type = ioArraySymbolResizeList[i]->getWritableType();
+
+ // As I/O array sizes don't change, fetch requiredSize only once,
+ // except for mesh shaders which could have different I/O array sizes based on type qualifiers.
+ if (firstIteration || (language == EShLangMeshNV)) {
+ requiredSize = getIoArrayImplicitSize(type.getQualifier(), &featureString);
+ if (requiredSize == 0)
+ break;
+ firstIteration = false;
+ }
+
+ checkIoArrayConsistency(loc, requiredSize, featureString.c_str(), type,
+ ioArraySymbolResizeList[i]->getName());
+ }
+}
+
+int TParseContext::getIoArrayImplicitSize(const TQualifier &qualifier, TString *featureString) const
+{
+ int expectedSize = 0;
+ TString str = "unknown";
+ unsigned int maxVertices = intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0;
+
+ if (language == EShLangGeometry) {
+ expectedSize = TQualifier::mapGeometryToSize(intermediate.getInputPrimitive());
+ str = TQualifier::getGeometryString(intermediate.getInputPrimitive());
+ }
+ else if (language == EShLangTessControl) {
+ expectedSize = maxVertices;
+ str = "vertices";
+ } else if (language == EShLangFragment) {
+ // Number of vertices for Fragment shader is always three.
+ expectedSize = 3;
+ str = "vertices";
+ } else if (language == EShLangMeshNV) {
+ unsigned int maxPrimitives =
+ intermediate.getPrimitives() != TQualifier::layoutNotSet ? intermediate.getPrimitives() : 0;
+ if (qualifier.builtIn == EbvPrimitiveIndicesNV) {
+ expectedSize = maxPrimitives * TQualifier::mapGeometryToSize(intermediate.getOutputPrimitive());
+ str = "max_primitives*";
+ str += TQualifier::getGeometryString(intermediate.getOutputPrimitive());
+ }
+ else if (qualifier.isPerPrimitive()) {
+ expectedSize = maxPrimitives;
+ str = "max_primitives";
+ }
+ else {
+ expectedSize = maxVertices;
+ str = "max_vertices";
+ }
+ }
+ if (featureString)
+ *featureString = str;
+ return expectedSize;
+}
+
+void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name)
+{
+ if (type.isUnsizedArray())
+ type.changeOuterArraySize(requiredSize);
+ else if (type.getOuterArraySize() != requiredSize) {
+ if (language == EShLangGeometry)
+ error(loc, "inconsistent input primitive for array size of", feature, name.c_str());
+ else if (language == EShLangTessControl)
+ error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str());
+ else if (language == EShLangFragment) {
+ if (type.getOuterArraySize() > requiredSize)
+ error(loc, " cannot be greater than 3 for pervertexNV", feature, name.c_str());
+ }
+ else if (language == EShLangMeshNV)
+ error(loc, "inconsistent output array size of", feature, name.c_str());
+ else
+ assert(0);
+ }
+}
+
+#endif // GLSLANG_WEB
+
+// Handle seeing a binary node with a math operation.
+// Returns nullptr if not semantically allowed.
+TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right)
+{
+ rValueErrorCheck(loc, str, left->getAsTyped());
+ rValueErrorCheck(loc, str, right->getAsTyped());
+
+ bool allowed = true;
+ switch (op) {
+ // TODO: Bring more source language-specific checks up from intermediate.cpp
+ // to the specific parse helpers for that source language.
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ if (! left->isScalar() || ! right->isScalar())
+ allowed = false;
+ break;
+ default:
+ break;
+ }
+
+ if (((left->getType().contains16BitFloat() || right->getType().contains16BitFloat()) && !float16Arithmetic()) ||
+ ((left->getType().contains16BitInt() || right->getType().contains16BitInt()) && !int16Arithmetic()) ||
+ ((left->getType().contains8BitInt() || right->getType().contains8BitInt()) && !int8Arithmetic())) {
+ allowed = false;
+ }
+
+ TIntermTyped* result = nullptr;
+ if (allowed)
+ result = intermediate.addBinaryMath(op, left, right, loc);
+
+ if (result == nullptr)
+ binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString());
+
+ return result;
+}
+
+// Handle seeing a unary node with a math operation.
+TIntermTyped* TParseContext::handleUnaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* childNode)
+{
+ rValueErrorCheck(loc, str, childNode);
+
+ bool allowed = true;
+ if ((childNode->getType().contains16BitFloat() && !float16Arithmetic()) ||
+ (childNode->getType().contains16BitInt() && !int16Arithmetic()) ||
+ (childNode->getType().contains8BitInt() && !int8Arithmetic())) {
+ allowed = false;
+ }
+
+ TIntermTyped* result = nullptr;
+ if (allowed)
+ result = intermediate.addUnaryMath(op, childNode, loc);
+
+ if (result)
+ return result;
+ else
+ unaryOpError(loc, str, childNode->getCompleteString());
+
+ return childNode;
+}
+
+//
+// Handle seeing a base.field dereference in the grammar.
+//
+TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field)
+{
+ variableCheck(base);
+
+ //
+ // .length() can't be resolved until we later see the function-calling syntax.
+ // Save away the name in the AST for now. Processing is completed in
+ // handleLengthMethod().
+ //
+ if (field == "length") {
+ if (base->isArray()) {
+ profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, ".length");
+ profileRequires(loc, EEsProfile, 300, nullptr, ".length");
+ } else if (base->isVector() || base->isMatrix()) {
+ const char* feature = ".length() on vectors and matrices";
+ requireProfile(loc, ~EEsProfile, feature);
+ profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature);
+ } else if (!base->getType().isCoopMat()) {
+ error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString().c_str());
+
+ return base;
+ }
+
+ return intermediate.addMethod(base, TType(EbtInt), &field, loc);
+ }
+
+ // It's not .length() if we get to here.
+
+ if (base->isArray()) {
+ error(loc, "cannot apply to an array:", ".", field.c_str());
+
+ return base;
+ }
+
+ if (base->getType().isCoopMat()) {
+ error(loc, "cannot apply to a cooperative matrix type:", ".", field.c_str());
+ return base;
+ }
+
+ // It's neither an array nor .length() if we get here,
+ // leaving swizzles and struct/block dereferences.
+
+ TIntermTyped* result = base;
+ if ((base->isVector() || base->isScalar()) &&
+ (base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) {
+ if (base->isScalar()) {
+ const char* dotFeature = "scalar swizzle";
+ requireProfile(loc, ~EEsProfile, dotFeature);
+ profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature);
+ }
+
+ TSwizzleSelectors<TVectorSelector> selectors;
+ parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
+
+ if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat())
+ requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16");
+ if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt())
+ requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16");
+ if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt())
+ requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8");
+
+ if (base->isScalar()) {
+ if (selectors.size() == 1)
+ return result;
+ else {
+ TType type(base->getBasicType(), EvqTemporary, selectors.size());
+ // Swizzle operations propagate specialization-constantness
+ if (base->getQualifier().isSpecConstant())
+ type.getQualifier().makeSpecConstant();
+ return addConstructor(loc, base, type);
+ }
+ }
+
+ if (base->getType().getQualifier().isFrontEndConstant())
+ result = intermediate.foldSwizzle(base, selectors, loc);
+ else {
+ if (selectors.size() == 1) {
+ TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc);
+ result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
+ result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision));
+ } else {
+ TIntermTyped* index = intermediate.addSwizzle(selectors, loc);
+ result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc);
+ result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size()));
+ }
+ // Swizzle operations propagate specialization-constantness
+ if (base->getType().getQualifier().isSpecConstant())
+ result->getWritableType().getQualifier().makeSpecConstant();
+ }
+ } else if (base->isStruct() || base->isReference()) {
+ const TTypeList* fields = base->isReference() ?
+ base->getType().getReferentType()->getStruct() :
+ base->getType().getStruct();
+ bool fieldFound = false;
+ int member;
+ for (member = 0; member < (int)fields->size(); ++member) {
+ if ((*fields)[member].type->getFieldName() == field) {
+ fieldFound = true;
+ break;
+ }
+ }
+ if (fieldFound) {
+ if (base->getType().getQualifier().isFrontEndConstant())
+ result = intermediate.foldDereference(base, member, loc);
+ else {
+ blockMemberExtensionCheck(loc, base, member, field);
+ TIntermTyped* index = intermediate.addConstantUnion(member, loc);
+ result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc);
+ result->setType(*(*fields)[member].type);
+ if ((*fields)[member].type->getQualifier().isIo())
+ intermediate.addIoAccessed(field);
+ }
+ inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier());
+ } else
+ error(loc, "no such field in structure", field.c_str(), "");
+ } else
+ error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString().c_str());
+
+ // Propagate noContraction up the dereference chain
+ if (base->getQualifier().isNoContraction())
+ result->getWritableType().getQualifier().setNoContraction();
+
+ // Propagate nonuniform
+ if (base->getQualifier().isNonUniform())
+ result->getWritableType().getQualifier().nonUniform = true;
+
+ return result;
+}
+
+void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* base, int member, const TString& memberName)
+{
+ // a block that needs extension checking is either 'base', or if arrayed,
+ // one level removed to the left
+ const TIntermSymbol* baseSymbol = nullptr;
+ if (base->getAsBinaryNode() == nullptr)
+ baseSymbol = base->getAsSymbolNode();
+ else
+ baseSymbol = base->getAsBinaryNode()->getLeft()->getAsSymbolNode();
+ if (baseSymbol == nullptr)
+ return;
+ const TSymbol* symbol = symbolTable.find(baseSymbol->getName());
+ if (symbol == nullptr)
+ return;
+ const TVariable* variable = symbol->getAsVariable();
+ if (variable == nullptr)
+ return;
+ if (!variable->hasMemberExtensions())
+ return;
+
+ // We now have a variable that is the base of a dot reference
+ // with members that need extension checking.
+ if (variable->getNumMemberExtensions(member) > 0)
+ requireExtensions(loc, variable->getNumMemberExtensions(member), variable->getMemberExtensions(member), memberName.c_str());
+}
+
+//
+// Handle seeing a function declarator in the grammar. This is the precursor
+// to recognizing a function prototype or function definition.
+//
+TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunction& function, bool prototype)
+{
+ // ES can't declare prototypes inside functions
+ if (! symbolTable.atGlobalLevel())
+ requireProfile(loc, ~EEsProfile, "local function declaration");
+
+ //
+ // Multiple declarations of the same function name are allowed.
+ //
+ // If this is a definition, the definition production code will check for redefinitions
+ // (we don't know at this point if it's a definition or not).
+ //
+ // Redeclarations (full signature match) are allowed. But, return types and parameter qualifiers must also match.
+ // - except ES 100, which only allows a single prototype
+ //
+ // ES 100 does not allow redefining, but does allow overloading of built-in functions.
+ // ES 300 does not allow redefining or overloading of built-in functions.
+ //
+ bool builtIn;
+ TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn);
+ if (symbol && symbol->getAsFunction() && builtIn)
+ requireProfile(loc, ~EEsProfile, "redefinition of built-in function");
+ const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
+ if (prevDec) {
+ if (prevDec->isPrototyped() && prototype)
+ profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function");
+ if (prevDec->getType() != function.getType())
+ error(loc, "overloaded functions must have the same return type", function.getName().c_str(), "");
+ for (int i = 0; i < prevDec->getParamCount(); ++i) {
+ if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage)
+ error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1);
+
+ if ((*prevDec)[i].type->getQualifier().precision != function[i].type->getQualifier().precision)
+ error(loc, "overloaded functions must have the same parameter precision qualifiers for argument", function[i].type->getPrecisionQualifierString(), "%d", i+1);
+ }
+ }
+
+ arrayObjectCheck(loc, function.getType(), "array in function return type");
+
+ if (prototype) {
+ // All built-in functions are defined, even though they don't have a body.
+ // Count their prototype as a definition instead.
+ if (symbolTable.atBuiltInLevel())
+ function.setDefined();
+ else {
+ if (prevDec && ! builtIn)
+ symbol->getAsFunction()->setPrototyped(); // need a writable one, but like having prevDec as a const
+ function.setPrototyped();
+ }
+ }
+
+ // This insert won't actually insert it if it's a duplicate signature, but it will still check for
+ // other forms of name collisions.
+ if (! symbolTable.insert(function))
+ error(loc, "function name is redeclaration of existing name", function.getName().c_str(), "");
+
+ //
+ // If this is a redeclaration, it could also be a definition,
+ // in which case, we need to use the parameter names from this one, and not the one that's
+ // being redeclared. So, pass back this declaration, not the one in the symbol table.
+ //
+ return &function;
+}
+
+//
+// Handle seeing the function prototype in front of a function definition in the grammar.
+// The body is handled after this function returns.
+//
+TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function)
+{
+ currentCaller = function.getMangledName();
+ TSymbol* symbol = symbolTable.find(function.getMangledName());
+ TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr;
+
+ if (! prevDec)
+ error(loc, "can't find function", function.getName().c_str(), "");
+ // Note: 'prevDec' could be 'function' if this is the first time we've seen function
+ // as it would have just been put in the symbol table. Otherwise, we're looking up
+ // an earlier occurrence.
+
+ if (prevDec && prevDec->isDefined()) {
+ // Then this function already has a body.
+ error(loc, "function already has a body", function.getName().c_str(), "");
+ }
+ if (prevDec && ! prevDec->isDefined()) {
+ prevDec->setDefined();
+
+ // Remember the return type for later checking for RETURN statements.
+ currentFunctionType = &(prevDec->getType());
+ } else
+ currentFunctionType = new TType(EbtVoid);
+ functionReturnsValue = false;
+
+ // Check for entry point
+ if (function.getName().compare(intermediate.getEntryPointName().c_str()) == 0) {
+ intermediate.setEntryPointMangledName(function.getMangledName().c_str());
+ intermediate.incrementEntryPointCount();
+ inMain = true;
+ } else
+ inMain = false;
+
+ //
+ // Raise error message if main function takes any parameters or returns anything other than void
+ //
+ if (inMain) {
+ if (function.getParamCount() > 0)
+ error(loc, "function cannot take any parameter(s)", function.getName().c_str(), "");
+ if (function.getType().getBasicType() != EbtVoid)
+ error(loc, "", function.getType().getBasicTypeString().c_str(), "entry point cannot return a value");
+ }
+
+ //
+ // New symbol table scope for body of function plus its arguments
+ //
+ symbolTable.push();
+
+ //
+ // Insert parameters into the symbol table.
+ // If the parameter has no name, it's not an error, just don't insert it
+ // (could be used for unused args).
+ //
+ // Also, accumulate the list of parameters into the HIL, so lower level code
+ // knows where to find parameters.
+ //
+ TIntermAggregate* paramNodes = new TIntermAggregate;
+ for (int i = 0; i < function.getParamCount(); i++) {
+ TParameter& param = function[i];
+ if (param.name != nullptr) {
+ TVariable *variable = new TVariable(param.name, *param.type);
+
+ // Insert the parameters with name in the symbol table.
+ if (! symbolTable.insert(*variable))
+ error(loc, "redefinition", variable->getName().c_str(), "");
+ else {
+ // Transfer ownership of name pointer to symbol table.
+ param.name = nullptr;
+
+ // Add the parameter to the HIL
+ paramNodes = intermediate.growAggregate(paramNodes,
+ intermediate.addSymbol(*variable, loc),
+ loc);
+ }
+ } else
+ paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc);
+ }
+ intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc);
+ loopNestingLevel = 0;
+ statementNestingLevel = 0;
+ controlFlowNestingLevel = 0;
+ postEntryPointReturn = false;
+
+ return paramNodes;
+}
+
+//
+// Handle seeing function call syntax in the grammar, which could be any of
+// - .length() method
+// - constructor
+// - a call to a built-in function mapped to an operator
+// - a call to a built-in function that will remain a function call (e.g., texturing)
+// - user function
+// - subroutine call (not implemented yet)
+//
+TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments)
+{
+ TIntermTyped* result = nullptr;
+
+ if (function->getBuiltInOp() == EOpArrayLength)
+ result = handleLengthMethod(loc, function, arguments);
+ else if (function->getBuiltInOp() != EOpNull) {
+ //
+ // Then this should be a constructor.
+ // Don't go through the symbol table for constructors.
+ // Their parameters will be verified algorithmically.
+ //
+ TType type(EbtVoid); // use this to get the type back
+ if (! constructorError(loc, arguments, *function, function->getBuiltInOp(), type)) {
+ //
+ // It's a constructor, of type 'type'.
+ //
+ result = addConstructor(loc, arguments, type);
+ if (result == nullptr)
+ error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), "");
+ }
+ } else {
+ //
+ // Find it in the symbol table.
+ //
+ const TFunction* fnCandidate;
+ bool builtIn;
+ fnCandidate = findFunction(loc, *function, builtIn);
+ if (fnCandidate) {
+ // This is a declared function that might map to
+ // - a built-in operator,
+ // - a built-in function not mapped to an operator, or
+ // - a user function.
+
+ // Error check for a function requiring specific extensions present.
+ if (builtIn && fnCandidate->getNumExtensions())
+ requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str());
+
+ if (builtIn && fnCandidate->getType().contains16BitFloat())
+ requireFloat16Arithmetic(loc, "built-in function", "float16 types can only be in uniform block or buffer storage");
+ if (builtIn && fnCandidate->getType().contains16BitInt())
+ requireInt16Arithmetic(loc, "built-in function", "(u)int16 types can only be in uniform block or buffer storage");
+ if (builtIn && fnCandidate->getType().contains8BitInt())
+ requireInt8Arithmetic(loc, "built-in function", "(u)int8 types can only be in uniform block or buffer storage");
+
+ if (arguments != nullptr) {
+ // Make sure qualifications work for these arguments.
+ TIntermAggregate* aggregate = arguments->getAsAggregate();
+ for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+ // At this early point there is a slight ambiguity between whether an aggregate 'arguments'
+ // is the single argument itself or its children are the arguments. Only one argument
+ // means take 'arguments' itself as the one argument.
+ TIntermNode* arg = fnCandidate->getParamCount() == 1 ? arguments : (aggregate ? aggregate->getSequence()[i] : arguments);
+ TQualifier& formalQualifier = (*fnCandidate)[i].type->getQualifier();
+ if (formalQualifier.isParamOutput()) {
+ if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped()))
+ error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", "");
+ }
+ const TType& argType = arg->getAsTyped()->getType();
+ const TQualifier& argQualifier = argType.getQualifier();
+ if (argQualifier.isMemory() && (argType.containsOpaque() || argType.isReference())) {
+ const char* message = "argument cannot drop memory qualifier when passed to formal parameter";
+#ifndef GLSLANG_WEB
+ if (argQualifier.volatil && ! formalQualifier.volatil)
+ error(arguments->getLoc(), message, "volatile", "");
+ if (argQualifier.coherent && ! (formalQualifier.devicecoherent || formalQualifier.coherent))
+ error(arguments->getLoc(), message, "coherent", "");
+ if (argQualifier.devicecoherent && ! (formalQualifier.devicecoherent || formalQualifier.coherent))
+ error(arguments->getLoc(), message, "devicecoherent", "");
+ if (argQualifier.queuefamilycoherent && ! (formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent))
+ error(arguments->getLoc(), message, "queuefamilycoherent", "");
+ if (argQualifier.workgroupcoherent && ! (formalQualifier.workgroupcoherent || formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent))
+ error(arguments->getLoc(), message, "workgroupcoherent", "");
+ if (argQualifier.subgroupcoherent && ! (formalQualifier.subgroupcoherent || formalQualifier.workgroupcoherent || formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent))
+ error(arguments->getLoc(), message, "subgroupcoherent", "");
+ if (argQualifier.readonly && ! formalQualifier.readonly)
+ error(arguments->getLoc(), message, "readonly", "");
+ if (argQualifier.writeonly && ! formalQualifier.writeonly)
+ error(arguments->getLoc(), message, "writeonly", "");
+ // Don't check 'restrict', it is different than the rest:
+ // "...but only restrict can be taken away from a calling argument, by a formal parameter that
+ // lacks the restrict qualifier..."
+#endif
+ }
+ if (!builtIn && argQualifier.getFormat() != formalQualifier.getFormat()) {
+ // we have mismatched formats, which should only be allowed if writeonly
+ // and at least one format is unknown
+ if (!formalQualifier.isWriteOnly() || (formalQualifier.getFormat() != ElfNone &&
+ argQualifier.getFormat() != ElfNone))
+ error(arguments->getLoc(), "image formats must match", "format", "");
+ }
+ if (builtIn && arg->getAsTyped()->getType().contains16BitFloat())
+ requireFloat16Arithmetic(arguments->getLoc(), "built-in function", "float16 types can only be in uniform block or buffer storage");
+ if (builtIn && arg->getAsTyped()->getType().contains16BitInt())
+ requireInt16Arithmetic(arguments->getLoc(), "built-in function", "(u)int16 types can only be in uniform block or buffer storage");
+ if (builtIn && arg->getAsTyped()->getType().contains8BitInt())
+ requireInt8Arithmetic(arguments->getLoc(), "built-in function", "(u)int8 types can only be in uniform block or buffer storage");
+
+ // TODO 4.5 functionality: A shader will fail to compile
+ // if the value passed to the memargument of an atomic memory function does not correspond to a buffer or
+ // shared variable. It is acceptable to pass an element of an array or a single component of a vector to the
+ // memargument of an atomic memory function, as long as the underlying array or vector is a buffer or
+ // shared variable.
+ }
+
+ // Convert 'in' arguments
+ addInputArgumentConversions(*fnCandidate, arguments); // arguments may be modified if it's just a single argument node
+ }
+
+ if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) {
+ // A function call mapped to a built-in operation.
+ result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate);
+ } else {
+ // This is a function call not mapped to built-in operator.
+ // It could still be a built-in function, but only if PureOperatorBuiltins == false.
+ result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc);
+ TIntermAggregate* call = result->getAsAggregate();
+ call->setName(fnCandidate->getMangledName());
+
+ // this is how we know whether the given function is a built-in function or a user-defined function
+ // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also
+ // if builtIn == true, it's definitely a built-in function with EOpNull
+ if (! builtIn) {
+ call->setUserDefined();
+ if (symbolTable.atGlobalLevel()) {
+ requireProfile(loc, ~EEsProfile, "calling user function from global scope");
+ intermediate.addToCallGraph(infoSink, "main(", fnCandidate->getMangledName());
+ } else
+ intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName());
+ }
+
+#ifndef GLSLANG_WEB
+ if (builtIn)
+ nonOpBuiltInCheck(loc, *fnCandidate, *call);
+ else
+#endif
+ userFunctionCallCheck(loc, *call);
+ }
+
+ // Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore.
+ // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output.
+ // Also, build the qualifier list for user function calls, which are always called with an aggregate.
+ if (result->getAsAggregate()) {
+ TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList();
+ for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+ TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage;
+ qualifierList.push_back(qual);
+ }
+ result = addOutputArgumentConversions(*fnCandidate, *result->getAsAggregate());
+ }
+
+ if (result->getAsTyped()->getType().isCoopMat() &&
+ !result->getAsTyped()->getType().isParameterized()) {
+ assert(fnCandidate->getBuiltInOp() == EOpCooperativeMatrixMulAdd);
+
+ result->setType(result->getAsAggregate()->getSequence()[2]->getAsTyped()->getType());
+ }
+ }
+ }
+
+ // generic error recovery
+ // TODO: simplification: localize all the error recoveries that look like this, and taking type into account to reduce cascades
+ if (result == nullptr)
+ result = intermediate.addConstantUnion(0.0, EbtFloat, loc);
+
+ return result;
+}
+
+TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNode* arguments,
+ const TFunction& function)
+{
+ checkLocation(loc, function.getBuiltInOp());
+ TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(),
+ function.getParamCount() == 1,
+ arguments, function.getType());
+ if (obeyPrecisionQualifiers())
+ computeBuiltinPrecisions(*result, function);
+
+ if (result == nullptr) {
+ if (arguments == nullptr)
+ error(loc, " wrong operand type", "Internal Error",
+ "built in unary operator function. Type: %s", "");
+ else
+ error(arguments->getLoc(), " wrong operand type", "Internal Error",
+ "built in unary operator function. Type: %s",
+ static_cast<TIntermTyped*>(arguments)->getCompleteString().c_str());
+ } else if (result->getAsOperator())
+ builtInOpCheck(loc, function, *result->getAsOperator());
+
+ return result;
+}
+
+// "The operation of a built-in function can have a different precision
+// qualification than the precision qualification of the resulting value.
+// These two precision qualifications are established as follows.
+//
+// The precision qualification of the operation of a built-in function is
+// based on the precision qualification of its input arguments and formal
+// parameters: When a formal parameter specifies a precision qualifier,
+// that is used, otherwise, the precision qualification of the calling
+// argument is used. The highest precision of these will be the precision
+// qualification of the operation of the built-in function. Generally,
+// this is applied across all arguments to a built-in function, with the
+// exceptions being:
+// - bitfieldExtract and bitfieldInsert ignore the 'offset' and 'bits'
+// arguments.
+// - interpolateAt* functions only look at the 'interpolant' argument.
+//
+// The precision qualification of the result of a built-in function is
+// determined in one of the following ways:
+//
+// - For the texture sampling, image load, and image store functions,
+// the precision of the return type matches the precision of the
+// sampler type
+//
+// Otherwise:
+//
+// - For prototypes that do not specify a resulting precision qualifier,
+// the precision will be the same as the precision of the operation.
+//
+// - For prototypes that do specify a resulting precision qualifier,
+// the specified precision qualifier is the precision qualification of
+// the result."
+//
+void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction& function)
+{
+ TPrecisionQualifier operationPrecision = EpqNone;
+ TPrecisionQualifier resultPrecision = EpqNone;
+
+ TIntermOperator* opNode = node.getAsOperator();
+ if (opNode == nullptr)
+ return;
+
+ if (TIntermUnary* unaryNode = node.getAsUnaryNode()) {
+ operationPrecision = std::max(function[0].type->getQualifier().precision,
+ unaryNode->getOperand()->getType().getQualifier().precision);
+ if (function.getType().getBasicType() != EbtBool)
+ resultPrecision = function.getType().getQualifier().precision == EpqNone ?
+ operationPrecision :
+ function.getType().getQualifier().precision;
+ } else if (TIntermAggregate* agg = node.getAsAggregate()) {
+ TIntermSequence& sequence = agg->getSequence();
+ unsigned int numArgs = (unsigned int)sequence.size();
+ switch (agg->getOp()) {
+ case EOpBitfieldExtract:
+ numArgs = 1;
+ break;
+ case EOpBitfieldInsert:
+ numArgs = 2;
+ break;
+ case EOpInterpolateAtCentroid:
+ case EOpInterpolateAtOffset:
+ case EOpInterpolateAtSample:
+ numArgs = 1;
+ break;
+ default:
+ break;
+ }
+ // find the maximum precision from the arguments and parameters
+ for (unsigned int arg = 0; arg < numArgs; ++arg) {
+ operationPrecision = std::max(operationPrecision, sequence[arg]->getAsTyped()->getQualifier().precision);
+ operationPrecision = std::max(operationPrecision, function[arg].type->getQualifier().precision);
+ }
+ // compute the result precision
+ if (agg->isSampling() ||
+ agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore ||
+ agg->getOp() == EOpImageLoadLod || agg->getOp() == EOpImageStoreLod)
+ resultPrecision = sequence[0]->getAsTyped()->getQualifier().precision;
+ else if (function.getType().getBasicType() != EbtBool)
+ resultPrecision = function.getType().getQualifier().precision == EpqNone ?
+ operationPrecision :
+ function.getType().getQualifier().precision;
+ }
+
+ // Propagate precision through this node and its children. That algorithm stops
+ // when a precision is found, so start by clearing this subroot precision
+ opNode->getQualifier().precision = EpqNone;
+ if (operationPrecision != EpqNone) {
+ opNode->propagatePrecision(operationPrecision);
+ opNode->setOperationPrecision(operationPrecision);
+ }
+ // Now, set the result precision, which might not match
+ opNode->getQualifier().precision = resultPrecision;
+}
+
+TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermTyped* value)
+{
+#ifndef GLSLANG_WEB
+ storage16BitAssignmentCheck(loc, value->getType(), "return");
+#endif
+
+ functionReturnsValue = true;
+ if (currentFunctionType->getBasicType() == EbtVoid) {
+ error(loc, "void function cannot return a value", "return", "");
+ return intermediate.addBranch(EOpReturn, loc);
+ } else if (*currentFunctionType != value->getType()) {
+ TIntermTyped* converted = intermediate.addConversion(EOpReturn, *currentFunctionType, value);
+ if (converted) {
+ if (*currentFunctionType != converted->getType())
+ error(loc, "cannot convert return value to function return type", "return", "");
+ if (version < 420)
+ warn(loc, "type conversion on return values was not explicitly allowed until version 420", "return", "");
+ return intermediate.addBranch(EOpReturn, converted, loc);
+ } else {
+ error(loc, "type does not match, or is not convertible to, the function's return type", "return", "");
+ return intermediate.addBranch(EOpReturn, value, loc);
+ }
+ } else
+ return intermediate.addBranch(EOpReturn, value, loc);
+}
+
+// See if the operation is being done in an illegal location.
+void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op)
+{
+#ifndef GLSLANG_WEB
+ switch (op) {
+ case EOpBarrier:
+ if (language == EShLangTessControl) {
+ if (controlFlowNestingLevel > 0)
+ error(loc, "tessellation control barrier() cannot be placed within flow control", "", "");
+ if (! inMain)
+ error(loc, "tessellation control barrier() must be in main()", "", "");
+ else if (postEntryPointReturn)
+ error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", "");
+ }
+ break;
+ case EOpBeginInvocationInterlock:
+ if (language != EShLangFragment)
+ error(loc, "beginInvocationInterlockARB() must be in a fragment shader", "", "");
+ if (! inMain)
+ error(loc, "beginInvocationInterlockARB() must be in main()", "", "");
+ else if (postEntryPointReturn)
+ error(loc, "beginInvocationInterlockARB() cannot be placed after a return from main()", "", "");
+ if (controlFlowNestingLevel > 0)
+ error(loc, "beginInvocationInterlockARB() cannot be placed within flow control", "", "");
+
+ if (beginInvocationInterlockCount > 0)
+ error(loc, "beginInvocationInterlockARB() must only be called once", "", "");
+ if (endInvocationInterlockCount > 0)
+ error(loc, "beginInvocationInterlockARB() must be called before endInvocationInterlockARB()", "", "");
+
+ beginInvocationInterlockCount++;
+
+ // default to pixel_interlock_ordered
+ if (intermediate.getInterlockOrdering() == EioNone)
+ intermediate.setInterlockOrdering(EioPixelInterlockOrdered);
+ break;
+ case EOpEndInvocationInterlock:
+ if (language != EShLangFragment)
+ error(loc, "endInvocationInterlockARB() must be in a fragment shader", "", "");
+ if (! inMain)
+ error(loc, "endInvocationInterlockARB() must be in main()", "", "");
+ else if (postEntryPointReturn)
+ error(loc, "endInvocationInterlockARB() cannot be placed after a return from main()", "", "");
+ if (controlFlowNestingLevel > 0)
+ error(loc, "endInvocationInterlockARB() cannot be placed within flow control", "", "");
+
+ if (endInvocationInterlockCount > 0)
+ error(loc, "endInvocationInterlockARB() must only be called once", "", "");
+ if (beginInvocationInterlockCount == 0)
+ error(loc, "beginInvocationInterlockARB() must be called before endInvocationInterlockARB()", "", "");
+
+ endInvocationInterlockCount++;
+ break;
+ default:
+ break;
+ }
+#endif
+}
+
+// Finish processing object.length(). This started earlier in handleDotDereference(), where
+// the ".length" part was recognized and semantically checked, and finished here where the
+// function syntax "()" is recognized.
+//
+// Return resulting tree node.
+TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction* function, TIntermNode* intermNode)
+{
+ int length = 0;
+
+ if (function->getParamCount() > 0)
+ error(loc, "method does not accept any arguments", function->getName().c_str(), "");
+ else {
+ const TType& type = intermNode->getAsTyped()->getType();
+ if (type.isArray()) {
+ if (type.isUnsizedArray()) {
+#ifndef GLSLANG_WEB
+ if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) {
+ // We could be between a layout declaration that gives a built-in io array implicit size and
+ // a user redeclaration of that array, meaning we have to substitute its implicit size here
+ // without actually redeclaring the array. (It is an error to use a member before the
+ // redeclaration, but not an error to use the array name itself.)
+ const TString& name = intermNode->getAsSymbolNode()->getName();
+ if (name == "gl_in" || name == "gl_out" || name == "gl_MeshVerticesNV" ||
+ name == "gl_MeshPrimitivesNV") {
+ length = getIoArrayImplicitSize(type.getQualifier());
+ }
+ }
+#endif
+ if (length == 0) {
+#ifndef GLSLANG_WEB
+ if (intermNode->getAsSymbolNode() && isIoResizeArray(type))
+ error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier");
+ else if (isRuntimeLength(*intermNode->getAsTyped())) {
+ // Create a unary op and let the back end handle it
+ return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt));
+ } else
+#endif
+ error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method");
+ }
+ } else if (type.getOuterArrayNode()) {
+ // If the array's outer size is specified by an intermediate node, it means the array's length
+ // was specified by a specialization constant. In such a case, we should return the node of the
+ // specialization constants to represent the length.
+ return type.getOuterArrayNode();
+ } else
+ length = type.getOuterArraySize();
+ } else if (type.isMatrix())
+ length = type.getMatrixCols();
+ else if (type.isVector())
+ length = type.getVectorSize();
+ else if (type.isCoopMat())
+ return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt));
+ else {
+ // we should not get here, because earlier semantic checking should have prevented this path
+ error(loc, ".length()", "unexpected use of .length()", "");
+ }
+ }
+
+ if (length == 0)
+ length = 1;
+
+ return intermediate.addConstantUnion(length, loc);
+}
+
+//
+// Add any needed implicit conversions for function-call arguments to input parameters.
+//
+void TParseContext::addInputArgumentConversions(const TFunction& function, TIntermNode*& arguments) const
+{
+#ifndef GLSLANG_WEB
+ TIntermAggregate* aggregate = arguments->getAsAggregate();
+
+ // Process each argument's conversion
+ for (int i = 0; i < function.getParamCount(); ++i) {
+ // At this early point there is a slight ambiguity between whether an aggregate 'arguments'
+ // is the single argument itself or its children are the arguments. Only one argument
+ // means take 'arguments' itself as the one argument.
+ TIntermTyped* arg = function.getParamCount() == 1 ? arguments->getAsTyped() : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped());
+ if (*function[i].type != arg->getType()) {
+ if (function[i].type->getQualifier().isParamInput() &&
+ !function[i].type->isCoopMat()) {
+ // In-qualified arguments just need an extra node added above the argument to
+ // convert to the correct type.
+ arg = intermediate.addConversion(EOpFunctionCall, *function[i].type, arg);
+ if (arg) {
+ if (function.getParamCount() == 1)
+ arguments = arg;
+ else {
+ if (aggregate)
+ aggregate->getSequence()[i] = arg;
+ else
+ arguments = arg;
+ }
+ }
+ }
+ }
+ }
+#endif
+}
+
+//
+// Add any needed implicit output conversions for function-call arguments. This
+// can require a new tree topology, complicated further by whether the function
+// has a return value.
+//
+// Returns a node of a subtree that evaluates to the return value of the function.
+//
+TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& function, TIntermAggregate& intermNode) const
+{
+#ifdef GLSLANG_WEB
+ return &intermNode;
+#else
+ TIntermSequence& arguments = intermNode.getSequence();
+
+ // Will there be any output conversions?
+ bool outputConversions = false;
+ for (int i = 0; i < function.getParamCount(); ++i) {
+ if (*function[i].type != arguments[i]->getAsTyped()->getType() && function[i].type->getQualifier().isParamOutput()) {
+ outputConversions = true;
+ break;
+ }
+ }
+
+ if (! outputConversions)
+ return &intermNode;
+
+ // Setup for the new tree, if needed:
+ //
+ // Output conversions need a different tree topology.
+ // Out-qualified arguments need a temporary of the correct type, with the call
+ // followed by an assignment of the temporary to the original argument:
+ // void: function(arg, ...) -> ( function(tempArg, ...), arg = tempArg, ...)
+ // ret = function(arg, ...) -> ret = (tempRet = function(tempArg, ...), arg = tempArg, ..., tempRet)
+ // Where the "tempArg" type needs no conversion as an argument, but will convert on assignment.
+ TIntermTyped* conversionTree = nullptr;
+ TVariable* tempRet = nullptr;
+ if (intermNode.getBasicType() != EbtVoid) {
+ // do the "tempRet = function(...), " bit from above
+ tempRet = makeInternalVariable("tempReturn", intermNode.getType());
+ TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc());
+ conversionTree = intermediate.addAssign(EOpAssign, tempRetNode, &intermNode, intermNode.getLoc());
+ } else
+ conversionTree = &intermNode;
+
+ conversionTree = intermediate.makeAggregate(conversionTree);
+
+ // Process each argument's conversion
+ for (int i = 0; i < function.getParamCount(); ++i) {
+ if (*function[i].type != arguments[i]->getAsTyped()->getType()) {
+ if (function[i].type->getQualifier().isParamOutput()) {
+ // Out-qualified arguments need to use the topology set up above.
+ // do the " ...(tempArg, ...), arg = tempArg" bit from above
+ TType paramType;
+ paramType.shallowCopy(*function[i].type);
+ if (arguments[i]->getAsTyped()->getType().isParameterized() &&
+ !paramType.isParameterized()) {
+ paramType.shallowCopy(arguments[i]->getAsTyped()->getType());
+ paramType.copyTypeParameters(*arguments[i]->getAsTyped()->getType().getTypeParameters());
+ }
+ TVariable* tempArg = makeInternalVariable("tempArg", paramType);
+ tempArg->getWritableType().getQualifier().makeTemporary();
+ TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc());
+ TIntermTyped* tempAssign = intermediate.addAssign(EOpAssign, arguments[i]->getAsTyped(), tempArgNode, arguments[i]->getLoc());
+ conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc());
+ // replace the argument with another node for the same tempArg variable
+ arguments[i] = intermediate.addSymbol(*tempArg, intermNode.getLoc());
+ }
+ }
+ }
+
+ // Finalize the tree topology (see bigger comment above).
+ if (tempRet) {
+ // do the "..., tempRet" bit from above
+ TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc());
+ conversionTree = intermediate.growAggregate(conversionTree, tempRetNode, intermNode.getLoc());
+ }
+ conversionTree = intermediate.setAggregateOperator(conversionTree, EOpComma, intermNode.getType(), intermNode.getLoc());
+
+ return conversionTree;
+#endif
+}
+
+void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& fnCandidate, const TIntermOperator& callNode)
+{
+ const TIntermSequence* argp = &callNode.getAsAggregate()->getSequence();
+
+ //const int gl_SemanticsRelaxed = 0x0;
+ const int gl_SemanticsAcquire = 0x2;
+ const int gl_SemanticsRelease = 0x4;
+ const int gl_SemanticsAcquireRelease = 0x8;
+ const int gl_SemanticsMakeAvailable = 0x2000;
+ const int gl_SemanticsMakeVisible = 0x4000;
+ const int gl_SemanticsVolatile = 0x8000;
+
+ //const int gl_StorageSemanticsNone = 0x0;
+ const int gl_StorageSemanticsBuffer = 0x40;
+ const int gl_StorageSemanticsShared = 0x100;
+ const int gl_StorageSemanticsImage = 0x800;
+ const int gl_StorageSemanticsOutput = 0x1000;
+
+
+ unsigned int semantics = 0, storageClassSemantics = 0;
+ unsigned int semantics2 = 0, storageClassSemantics2 = 0;
+
+ // Grab the semantics and storage class semantics from the operands, based on opcode
+ switch (callNode.getOp()) {
+ case EOpAtomicAdd:
+ case EOpAtomicMin:
+ case EOpAtomicMax:
+ case EOpAtomicAnd:
+ case EOpAtomicOr:
+ case EOpAtomicXor:
+ case EOpAtomicExchange:
+ case EOpAtomicStore:
+ storageClassSemantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ semantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ break;
+ case EOpAtomicLoad:
+ storageClassSemantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ semantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ break;
+ case EOpAtomicCompSwap:
+ storageClassSemantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ semantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ storageClassSemantics2 = (*argp)[6]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ semantics2 = (*argp)[7]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ break;
+
+ case EOpImageAtomicAdd:
+ case EOpImageAtomicMin:
+ case EOpImageAtomicMax:
+ case EOpImageAtomicAnd:
+ case EOpImageAtomicOr:
+ case EOpImageAtomicXor:
+ case EOpImageAtomicExchange:
+ case EOpImageAtomicStore:
+ storageClassSemantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ semantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ break;
+ case EOpImageAtomicLoad:
+ storageClassSemantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ semantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ break;
+ case EOpImageAtomicCompSwap:
+ storageClassSemantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ semantics = (*argp)[6]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ storageClassSemantics2 = (*argp)[7]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ semantics2 = (*argp)[8]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ break;
+
+ case EOpBarrier:
+ storageClassSemantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ semantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ break;
+ case EOpMemoryBarrier:
+ storageClassSemantics = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ semantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ break;
+ default:
+ break;
+ }
+
+ if ((semantics & gl_SemanticsAcquire) &&
+ (callNode.getOp() == EOpAtomicStore || callNode.getOp() == EOpImageAtomicStore)) {
+ error(loc, "gl_SemanticsAcquire must not be used with (image) atomic store",
+ fnCandidate.getName().c_str(), "");
+ }
+ if ((semantics & gl_SemanticsRelease) &&
+ (callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpImageAtomicLoad)) {
+ error(loc, "gl_SemanticsRelease must not be used with (image) atomic load",
+ fnCandidate.getName().c_str(), "");
+ }
+ if ((semantics & gl_SemanticsAcquireRelease) &&
+ (callNode.getOp() == EOpAtomicStore || callNode.getOp() == EOpImageAtomicStore ||
+ callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpImageAtomicLoad)) {
+ error(loc, "gl_SemanticsAcquireRelease must not be used with (image) atomic load/store",
+ fnCandidate.getName().c_str(), "");
+ }
+ if (((semantics | semantics2) & ~(gl_SemanticsAcquire |
+ gl_SemanticsRelease |
+ gl_SemanticsAcquireRelease |
+ gl_SemanticsMakeAvailable |
+ gl_SemanticsMakeVisible |
+ gl_SemanticsVolatile))) {
+ error(loc, "Invalid semantics value", fnCandidate.getName().c_str(), "");
+ }
+ if (((storageClassSemantics | storageClassSemantics2) & ~(gl_StorageSemanticsBuffer |
+ gl_StorageSemanticsShared |
+ gl_StorageSemanticsImage |
+ gl_StorageSemanticsOutput))) {
+ error(loc, "Invalid storage class semantics value", fnCandidate.getName().c_str(), "");
+ }
+
+ if (callNode.getOp() == EOpMemoryBarrier) {
+ if (!IsPow2(semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) {
+ error(loc, "Semantics must include exactly one of gl_SemanticsRelease, gl_SemanticsAcquire, or "
+ "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), "");
+ }
+ } else {
+ if (semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease)) {
+ if (!IsPow2(semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) {
+ error(loc, "Semantics must not include multiple of gl_SemanticsRelease, gl_SemanticsAcquire, or "
+ "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), "");
+ }
+ }
+ if (semantics2 & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease)) {
+ if (!IsPow2(semantics2 & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) {
+ error(loc, "semUnequal must not include multiple of gl_SemanticsRelease, gl_SemanticsAcquire, or "
+ "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), "");
+ }
+ }
+ }
+ if (callNode.getOp() == EOpMemoryBarrier) {
+ if (storageClassSemantics == 0) {
+ error(loc, "Storage class semantics must not be zero", fnCandidate.getName().c_str(), "");
+ }
+ }
+ if (callNode.getOp() == EOpBarrier && semantics != 0 && storageClassSemantics == 0) {
+ error(loc, "Storage class semantics must not be zero", fnCandidate.getName().c_str(), "");
+ }
+ if ((callNode.getOp() == EOpAtomicCompSwap || callNode.getOp() == EOpImageAtomicCompSwap) &&
+ (semantics2 & (gl_SemanticsRelease | gl_SemanticsAcquireRelease))) {
+ error(loc, "semUnequal must not be gl_SemanticsRelease or gl_SemanticsAcquireRelease",
+ fnCandidate.getName().c_str(), "");
+ }
+ if ((semantics & gl_SemanticsMakeAvailable) &&
+ !(semantics & (gl_SemanticsRelease | gl_SemanticsAcquireRelease))) {
+ error(loc, "gl_SemanticsMakeAvailable requires gl_SemanticsRelease or gl_SemanticsAcquireRelease",
+ fnCandidate.getName().c_str(), "");
+ }
+ if ((semantics & gl_SemanticsMakeVisible) &&
+ !(semantics & (gl_SemanticsAcquire | gl_SemanticsAcquireRelease))) {
+ error(loc, "gl_SemanticsMakeVisible requires gl_SemanticsAcquire or gl_SemanticsAcquireRelease",
+ fnCandidate.getName().c_str(), "");
+ }
+ if ((semantics & gl_SemanticsVolatile) &&
+ (callNode.getOp() == EOpMemoryBarrier || callNode.getOp() == EOpBarrier)) {
+ error(loc, "gl_SemanticsVolatile must not be used with memoryBarrier or controlBarrier",
+ fnCandidate.getName().c_str(), "");
+ }
+ if ((callNode.getOp() == EOpAtomicCompSwap || callNode.getOp() == EOpImageAtomicCompSwap) &&
+ ((semantics ^ semantics2) & gl_SemanticsVolatile)) {
+ error(loc, "semEqual and semUnequal must either both include gl_SemanticsVolatile or neither",
+ fnCandidate.getName().c_str(), "");
+ }
+}
+
+//
+// Do additional checking of built-in function calls that is not caught
+// by normal semantic checks on argument type, extension tagging, etc.
+//
+// Assumes there has been a semantically correct match to a built-in function prototype.
+//
+void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermOperator& callNode)
+{
+ // Set up convenience accessors to the argument(s). There is almost always
+ // multiple arguments for the cases below, but when there might be one,
+ // check the unaryArg first.
+ const TIntermSequence* argp = nullptr; // confusing to use [] syntax on a pointer, so this is to help get a reference
+ const TIntermTyped* unaryArg = nullptr;
+ const TIntermTyped* arg0 = nullptr;
+ if (callNode.getAsAggregate()) {
+ argp = &callNode.getAsAggregate()->getSequence();
+ if (argp->size() > 0)
+ arg0 = (*argp)[0]->getAsTyped();
+ } else {
+ assert(callNode.getAsUnaryNode());
+ unaryArg = callNode.getAsUnaryNode()->getOperand();
+ arg0 = unaryArg;
+ }
+
+ TString featureString;
+ const char* feature = nullptr;
+ switch (callNode.getOp()) {
+#ifndef GLSLANG_WEB
+ case EOpTextureGather:
+ case EOpTextureGatherOffset:
+ case EOpTextureGatherOffsets:
+ {
+ // Figure out which variants are allowed by what extensions,
+ // and what arguments must be constant for which situations.
+
+ featureString = fnCandidate.getName();
+ featureString += "(...)";
+ feature = featureString.c_str();
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ int compArg = -1; // track which argument, if any, is the constant component argument
+ switch (callNode.getOp()) {
+ case EOpTextureGather:
+ // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5,
+ // otherwise, need GL_ARB_texture_gather.
+ if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) {
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 2;
+ } else
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
+ break;
+ case EOpTextureGatherOffset:
+ // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument
+ if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3)
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
+ else
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
+ profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5,
+ "non-constant offset argument");
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 3;
+ break;
+ case EOpTextureGatherOffsets:
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 3;
+ // check for constant offsets
+ if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
+ error(loc, "must be a compile-time constant:", feature, "offsets argument");
+ break;
+ default:
+ break;
+ }
+
+ if (compArg > 0 && compArg < fnCandidate.getParamCount()) {
+ if ((*argp)[compArg]->getAsConstantUnion()) {
+ int value = (*argp)[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ if (value < 0 || value > 3)
+ error(loc, "must be 0, 1, 2, or 3:", feature, "component argument");
+ } else
+ error(loc, "must be a compile-time constant:", feature, "component argument");
+ }
+
+ bool bias = false;
+ if (callNode.getOp() == EOpTextureGather)
+ bias = fnCandidate.getParamCount() > 3;
+ else if (callNode.getOp() == EOpTextureGatherOffset ||
+ callNode.getOp() == EOpTextureGatherOffsets)
+ bias = fnCandidate.getParamCount() > 4;
+
+ if (bias) {
+ featureString = fnCandidate.getName();
+ featureString += "with bias argument";
+ feature = featureString.c_str();
+ profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
+ requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
+ }
+ break;
+ }
+ case EOpSparseTextureGather:
+ case EOpSparseTextureGatherOffset:
+ case EOpSparseTextureGatherOffsets:
+ {
+ bool bias = false;
+ if (callNode.getOp() == EOpSparseTextureGather)
+ bias = fnCandidate.getParamCount() > 4;
+ else if (callNode.getOp() == EOpSparseTextureGatherOffset ||
+ callNode.getOp() == EOpSparseTextureGatherOffsets)
+ bias = fnCandidate.getParamCount() > 5;
+
+ if (bias) {
+ featureString = fnCandidate.getName();
+ featureString += "with bias argument";
+ feature = featureString.c_str();
+ profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
+ requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
+ }
+
+ break;
+ }
+
+ case EOpSparseTextureGatherLod:
+ case EOpSparseTextureGatherLodOffset:
+ case EOpSparseTextureGatherLodOffsets:
+ {
+ requireExtensions(loc, 1, &E_GL_ARB_sparse_texture2, fnCandidate.getName().c_str());
+ break;
+ }
+
+ case EOpSwizzleInvocations:
+ {
+ if (! (*argp)[1]->getAsConstantUnion())
+ error(loc, "argument must be compile-time constant", "offset", "");
+ else {
+ unsigned offset[4] = {};
+ offset[0] = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst();
+ offset[1] = (*argp)[1]->getAsConstantUnion()->getConstArray()[1].getUConst();
+ offset[2] = (*argp)[1]->getAsConstantUnion()->getConstArray()[2].getUConst();
+ offset[3] = (*argp)[1]->getAsConstantUnion()->getConstArray()[3].getUConst();
+ if (offset[0] > 3 || offset[1] > 3 || offset[2] > 3 || offset[3] > 3)
+ error(loc, "components must be in the range [0, 3]", "offset", "");
+ }
+
+ break;
+ }
+
+ case EOpSwizzleInvocationsMasked:
+ {
+ if (! (*argp)[1]->getAsConstantUnion())
+ error(loc, "argument must be compile-time constant", "mask", "");
+ else {
+ unsigned mask[3] = {};
+ mask[0] = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst();
+ mask[1] = (*argp)[1]->getAsConstantUnion()->getConstArray()[1].getUConst();
+ mask[2] = (*argp)[1]->getAsConstantUnion()->getConstArray()[2].getUConst();
+ if (mask[0] > 31 || mask[1] > 31 || mask[2] > 31)
+ error(loc, "components must be in the range [0, 31]", "mask", "");
+ }
+
+ break;
+ }
+#endif
+
+ case EOpTextureOffset:
+ case EOpTextureFetchOffset:
+ case EOpTextureProjOffset:
+ case EOpTextureLodOffset:
+ case EOpTextureProjLodOffset:
+ case EOpTextureGradOffset:
+ case EOpTextureProjGradOffset:
+ {
+ // Handle texture-offset limits checking
+ // Pick which argument has to hold constant offsets
+ int arg = -1;
+ switch (callNode.getOp()) {
+ case EOpTextureOffset: arg = 2; break;
+ case EOpTextureFetchOffset: arg = (arg0->getType().getSampler().isRect()) ? 2 : 3; break;
+ case EOpTextureProjOffset: arg = 2; break;
+ case EOpTextureLodOffset: arg = 3; break;
+ case EOpTextureProjLodOffset: arg = 3; break;
+ case EOpTextureGradOffset: arg = 4; break;
+ case EOpTextureProjGradOffset: arg = 4; break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (arg > 0) {
+
+#ifndef GLSLANG_WEB
+ bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 && arg0->getType().getSampler().shadow;
+ if (f16ShadowCompare)
+ ++arg;
+#endif
+ if (! (*argp)[arg]->getAsConstantUnion())
+ error(loc, "argument must be compile-time constant", "texel offset", "");
+ else {
+ const TType& type = (*argp)[arg]->getAsTyped()->getType();
+ for (int c = 0; c < type.getVectorSize(); ++c) {
+ int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
+ if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
+ error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
+ }
+ }
+ }
+
+ break;
+ }
+
+#ifndef GLSLANG_WEB
+ case EOpTraceNV:
+ if (!(*argp)[10]->getAsConstantUnion())
+ error(loc, "argument must be compile-time constant", "payload number", "");
+ break;
+ case EOpExecuteCallableNV:
+ if (!(*argp)[1]->getAsConstantUnion())
+ error(loc, "argument must be compile-time constant", "callable data number", "");
+ break;
+
+ case EOpTextureQuerySamples:
+ case EOpImageQuerySamples:
+ // GL_ARB_shader_texture_image_samples
+ profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples");
+ break;
+
+ case EOpImageAtomicAdd:
+ case EOpImageAtomicMin:
+ case EOpImageAtomicMax:
+ case EOpImageAtomicAnd:
+ case EOpImageAtomicOr:
+ case EOpImageAtomicXor:
+ case EOpImageAtomicExchange:
+ case EOpImageAtomicCompSwap:
+ case EOpImageAtomicLoad:
+ case EOpImageAtomicStore:
+ {
+ // Make sure the image types have the correct layout() format and correct argument types
+ const TType& imageType = arg0->getType();
+ if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) {
+ if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui)
+ error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
+ } else {
+ if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)
+ error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
+ else if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile())
+ error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
+ }
+
+ const size_t maxArgs = imageType.getSampler().isMultiSample() ? 5 : 4;
+ if (argp->size() > maxArgs) {
+ requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str());
+ memorySemanticsCheck(loc, fnCandidate, callNode);
+ }
+
+ break;
+ }
+
+ case EOpAtomicAdd:
+ case EOpAtomicMin:
+ case EOpAtomicMax:
+ case EOpAtomicAnd:
+ case EOpAtomicOr:
+ case EOpAtomicXor:
+ case EOpAtomicExchange:
+ case EOpAtomicCompSwap:
+ case EOpAtomicLoad:
+ case EOpAtomicStore:
+ {
+ if (argp->size() > 3) {
+ requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str());
+ memorySemanticsCheck(loc, fnCandidate, callNode);
+ } else if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) {
+ const char* const extensions[2] = { E_GL_NV_shader_atomic_int64,
+ E_GL_EXT_shader_atomic_int64 };
+ requireExtensions(loc, 2, extensions, fnCandidate.getName().c_str());
+ }
+ break;
+ }
+
+ case EOpInterpolateAtCentroid:
+ case EOpInterpolateAtSample:
+ case EOpInterpolateAtOffset:
+ case EOpInterpolateAtVertex:
+ // Make sure the first argument is an interpolant, or an array element of an interpolant
+ if (arg0->getType().getQualifier().storage != EvqVaryingIn) {
+ // It might still be an array element.
+ //
+ // We could check more, but the semantics of the first argument are already met; the
+ // only way to turn an array into a float/vec* is array dereference and swizzle.
+ //
+ // ES and desktop 4.3 and earlier: swizzles may not be used
+ // desktop 4.4 and later: swizzles may be used
+ bool swizzleOkay = (!isEsProfile()) && (version >= 440);
+ const TIntermTyped* base = TIntermediate::findLValueBase(arg0, swizzleOkay);
+ if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn)
+ error(loc, "first argument must be an interpolant, or interpolant-array element", fnCandidate.getName().c_str(), "");
+ }
+
+ if (callNode.getOp() == EOpInterpolateAtVertex) {
+ if (!arg0->getType().getQualifier().isExplicitInterpolation())
+ error(loc, "argument must be qualified as __explicitInterpAMD in", "interpolant", "");
+ else {
+ if (! (*argp)[1]->getAsConstantUnion())
+ error(loc, "argument must be compile-time constant", "vertex index", "");
+ else {
+ unsigned vertexIdx = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst();
+ if (vertexIdx > 2)
+ error(loc, "must be in the range [0, 2]", "vertex index", "");
+ }
+ }
+ }
+ break;
+
+ case EOpEmitStreamVertex:
+ case EOpEndStreamPrimitive:
+ intermediate.setMultiStream();
+ break;
+
+ case EOpSubgroupClusteredAdd:
+ case EOpSubgroupClusteredMul:
+ case EOpSubgroupClusteredMin:
+ case EOpSubgroupClusteredMax:
+ case EOpSubgroupClusteredAnd:
+ case EOpSubgroupClusteredOr:
+ case EOpSubgroupClusteredXor:
+ // The <clusterSize> as used in the subgroupClustered<op>() operations must be:
+ // - An integral constant expression.
+ // - At least 1.
+ // - A power of 2.
+ if ((*argp)[1]->getAsConstantUnion() == nullptr)
+ error(loc, "argument must be compile-time constant", "cluster size", "");
+ else {
+ int size = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ if (size < 1)
+ error(loc, "argument must be at least 1", "cluster size", "");
+ else if (!IsPow2(size))
+ error(loc, "argument must be a power of 2", "cluster size", "");
+ }
+ break;
+
+ case EOpSubgroupBroadcast:
+ case EOpSubgroupQuadBroadcast:
+ if (spvVersion.spv < EShTargetSpv_1_5) {
+ // <id> must be an integral constant expression.
+ if ((*argp)[1]->getAsConstantUnion() == nullptr)
+ error(loc, "argument must be compile-time constant", "id", "");
+ }
+ break;
+
+ case EOpBarrier:
+ case EOpMemoryBarrier:
+ if (argp->size() > 0) {
+ requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str());
+ memorySemanticsCheck(loc, fnCandidate, callNode);
+ }
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ // Texture operations on texture objects (aside from texelFetch on a
+ // textureBuffer) require EXT_samplerless_texture_functions.
+ switch (callNode.getOp()) {
+ case EOpTextureQuerySize:
+ case EOpTextureQueryLevels:
+ case EOpTextureQuerySamples:
+ case EOpTextureFetch:
+ case EOpTextureFetchOffset:
+ {
+ const TSampler& sampler = fnCandidate[0].type->getSampler();
+
+ const bool isTexture = sampler.isTexture() && !sampler.isCombined();
+ const bool isBuffer = sampler.isBuffer();
+ const bool isFetch = callNode.getOp() == EOpTextureFetch || callNode.getOp() == EOpTextureFetchOffset;
+
+ if (isTexture && (!isBuffer || !isFetch))
+ requireExtensions(loc, 1, &E_GL_EXT_samplerless_texture_functions, fnCandidate.getName().c_str());
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (callNode.isSubgroup()) {
+ // these require SPIR-V 1.3
+ if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_3)
+ error(loc, "requires SPIR-V 1.3", "subgroup op", "");
+
+ // Check that if extended types are being used that the correct extensions are enabled.
+ if (arg0 != nullptr) {
+ const TType& type = arg0->getType();
+ switch (type.getBasicType()) {
+ default:
+ break;
+ case EbtInt8:
+ case EbtUint8:
+ requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int8, type.getCompleteString().c_str());
+ break;
+ case EbtInt16:
+ case EbtUint16:
+ requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int16, type.getCompleteString().c_str());
+ break;
+ case EbtInt64:
+ case EbtUint64:
+ requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int64, type.getCompleteString().c_str());
+ break;
+ case EbtFloat16:
+ requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_float16, type.getCompleteString().c_str());
+ break;
+ }
+ }
+ }
+}
+
+#ifndef GLSLANG_WEB
+
+extern bool PureOperatorBuiltins;
+
+// Deprecated! Use PureOperatorBuiltins == true instead, in which case this
+// functionality is handled in builtInOpCheck() instead of here.
+//
+// Do additional checking of built-in function calls that were not mapped
+// to built-in operations (e.g., texturing functions).
+//
+// Assumes there has been a semantically correct match to a built-in function.
+//
+void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermAggregate& callNode)
+{
+ // Further maintenance of this function is deprecated, because the "correct"
+ // future-oriented design is to not have to do string compares on function names.
+
+ // If PureOperatorBuiltins == true, then all built-ins should be mapped
+ // to a TOperator, and this function would then never get called.
+
+ assert(PureOperatorBuiltins == false);
+
+ // built-in texturing functions get their return value precision from the precision of the sampler
+ if (fnCandidate.getType().getQualifier().precision == EpqNone &&
+ fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler)
+ callNode.getQualifier().precision = callNode.getSequence()[0]->getAsTyped()->getQualifier().precision;
+
+ if (fnCandidate.getName().compare(0, 7, "texture") == 0) {
+ if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) {
+ TString featureString = fnCandidate.getName() + "(...)";
+ const char* feature = featureString.c_str();
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+
+ int compArg = -1; // track which argument, if any, is the constant component argument
+ if (fnCandidate.getName().compare("textureGatherOffset") == 0) {
+ // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument
+ if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3)
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
+ else
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2;
+ if (! callNode.getSequence()[offsetArg]->getAsConstantUnion())
+ profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5,
+ "non-constant offset argument");
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 3;
+ } else if (fnCandidate.getName().compare("textureGatherOffsets") == 0) {
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 3;
+ // check for constant offsets
+ int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2;
+ if (! callNode.getSequence()[offsetArg]->getAsConstantUnion())
+ error(loc, "must be a compile-time constant:", feature, "offsets argument");
+ } else if (fnCandidate.getName().compare("textureGather") == 0) {
+ // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5,
+ // otherwise, need GL_ARB_texture_gather.
+ if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) {
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 2;
+ } else
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
+ }
+
+ if (compArg > 0 && compArg < fnCandidate.getParamCount()) {
+ if (callNode.getSequence()[compArg]->getAsConstantUnion()) {
+ int value = callNode.getSequence()[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ if (value < 0 || value > 3)
+ error(loc, "must be 0, 1, 2, or 3:", feature, "component argument");
+ } else
+ error(loc, "must be a compile-time constant:", feature, "component argument");
+ }
+ } else {
+ // this is only for functions not starting "textureGather"...
+ if (fnCandidate.getName().find("Offset") != TString::npos) {
+
+ // Handle texture-offset limits checking
+ int arg = -1;
+ if (fnCandidate.getName().compare("textureOffset") == 0)
+ arg = 2;
+ else if (fnCandidate.getName().compare("texelFetchOffset") == 0)
+ arg = 3;
+ else if (fnCandidate.getName().compare("textureProjOffset") == 0)
+ arg = 2;
+ else if (fnCandidate.getName().compare("textureLodOffset") == 0)
+ arg = 3;
+ else if (fnCandidate.getName().compare("textureProjLodOffset") == 0)
+ arg = 3;
+ else if (fnCandidate.getName().compare("textureGradOffset") == 0)
+ arg = 4;
+ else if (fnCandidate.getName().compare("textureProjGradOffset") == 0)
+ arg = 4;
+
+ if (arg > 0) {
+ if (! callNode.getSequence()[arg]->getAsConstantUnion())
+ error(loc, "argument must be compile-time constant", "texel offset", "");
+ else {
+ const TType& type = callNode.getSequence()[arg]->getAsTyped()->getType();
+ for (int c = 0; c < type.getVectorSize(); ++c) {
+ int offset = callNode.getSequence()[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
+ if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
+ error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // GL_ARB_shader_texture_image_samples
+ if (fnCandidate.getName().compare(0, 14, "textureSamples") == 0 || fnCandidate.getName().compare(0, 12, "imageSamples") == 0)
+ profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples");
+
+ if (fnCandidate.getName().compare(0, 11, "imageAtomic") == 0) {
+ const TType& imageType = callNode.getSequence()[0]->getAsTyped()->getType();
+ if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) {
+ if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui)
+ error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
+ } else {
+ if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)
+ error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
+ else if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile())
+ error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
+ }
+ }
+}
+
+#endif
+
+//
+// Do any extra checking for a user function call.
+//
+void TParseContext::userFunctionCallCheck(const TSourceLoc& loc, TIntermAggregate& callNode)
+{
+ TIntermSequence& arguments = callNode.getSequence();
+
+ for (int i = 0; i < (int)arguments.size(); ++i)
+ samplerConstructorLocationCheck(loc, "call argument", arguments[i]);
+}
+
+//
+// Emit an error if this is a sampler constructor
+//
+void TParseContext::samplerConstructorLocationCheck(const TSourceLoc& loc, const char* token, TIntermNode* node)
+{
+ if (node->getAsOperator() && node->getAsOperator()->getOp() == EOpConstructTextureSampler)
+ error(loc, "sampler constructor must appear at point of use", token, "");
+}
+
+//
+// Handle seeing a built-in constructor in a grammar production.
+//
+TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPublicType& publicType)
+{
+ TType type(publicType);
+ type.getQualifier().precision = EpqNone;
+
+ if (type.isArray()) {
+ profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed constructor");
+ profileRequires(loc, EEsProfile, 300, nullptr, "arrayed constructor");
+ }
+
+ TOperator op = intermediate.mapTypeToConstructorOp(type);
+
+ if (op == EOpNull) {
+ error(loc, "cannot construct this type", type.getBasicString(), "");
+ op = EOpConstructFloat;
+ TType errorType(EbtFloat);
+ type.shallowCopy(errorType);
+ }
+
+ TString empty("");
+
+ return new TFunction(&empty, type, op);
+}
+
+// Handle seeing a precision qualifier in the grammar.
+void TParseContext::handlePrecisionQualifier(const TSourceLoc& /*loc*/, TQualifier& qualifier, TPrecisionQualifier precision)
+{
+ if (obeyPrecisionQualifiers())
+ qualifier.precision = precision;
+}
+
+// Check for messages to give on seeing a precision qualifier used in a
+// declaration in the grammar.
+void TParseContext::checkPrecisionQualifier(const TSourceLoc& loc, TPrecisionQualifier)
+{
+ if (precisionManager.shouldWarnAboutDefaults()) {
+ warn(loc, "all default precisions are highp; use precision statements to quiet warning, e.g.:\n"
+ " \"precision mediump int; precision highp float;\"", "", "");
+ precisionManager.defaultWarningGiven();
+ }
+}
+
+//
+// Same error message for all places assignments don't work.
+//
+void TParseContext::assignError(const TSourceLoc& loc, const char* op, TString left, TString right)
+{
+ error(loc, "", op, "cannot convert from '%s' to '%s'",
+ right.c_str(), left.c_str());
+}
+
+//
+// Same error message for all places unary operations don't work.
+//
+void TParseContext::unaryOpError(const TSourceLoc& loc, const char* op, TString operand)
+{
+ error(loc, " wrong operand type", op,
+ "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)",
+ op, operand.c_str());
+}
+
+//
+// Same error message for all binary operations don't work.
+//
+void TParseContext::binaryOpError(const TSourceLoc& loc, const char* op, TString left, TString right)
+{
+ error(loc, " wrong operand types:", op,
+ "no operation '%s' exists that takes a left-hand operand of type '%s' and "
+ "a right operand of type '%s' (or there is no acceptable conversion)",
+ op, left.c_str(), right.c_str());
+}
+
+//
+// A basic type of EbtVoid is a key that the name string was seen in the source, but
+// it was not found as a variable in the symbol table. If so, give the error
+// message and insert a dummy variable in the symbol table to prevent future errors.
+//
+void TParseContext::variableCheck(TIntermTyped*& nodePtr)
+{
+ TIntermSymbol* symbol = nodePtr->getAsSymbolNode();
+ if (! symbol)
+ return;
+
+ if (symbol->getType().getBasicType() == EbtVoid) {
+ const char *extraInfoFormat = "";
+ if (spvVersion.vulkan != 0 && symbol->getName() == "gl_VertexID") {
+ extraInfoFormat = "(Did you mean gl_VertexIndex?)";
+ } else if (spvVersion.vulkan != 0 && symbol->getName() == "gl_InstanceID") {
+ extraInfoFormat = "(Did you mean gl_InstanceIndex?)";
+ }
+ error(symbol->getLoc(), "undeclared identifier", symbol->getName().c_str(), extraInfoFormat);
+
+ // Add to symbol table to prevent future error messages on the same name
+ if (symbol->getName().size() > 0) {
+ TVariable* fakeVariable = new TVariable(&symbol->getName(), TType(EbtFloat));
+ symbolTable.insert(*fakeVariable);
+
+ // substitute a symbol node for this new variable
+ nodePtr = intermediate.addSymbol(*fakeVariable, symbol->getLoc());
+ }
+ } else {
+ switch (symbol->getQualifier().storage) {
+ case EvqPointCoord:
+ profileRequires(symbol->getLoc(), ENoProfile, 120, nullptr, "gl_PointCoord");
+ break;
+ default: break; // some compilers want this
+ }
+ }
+}
+
+//
+// Both test and if necessary, spit out an error, to see if the node is really
+// an l-value that can be operated on this way.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
+{
+ TIntermBinary* binaryNode = node->getAsBinaryNode();
+
+ if (binaryNode) {
+ bool errorReturn = false;
+
+ switch(binaryNode->getOp()) {
+#ifndef GLSLANG_WEB
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ // ... tessellation control shader ...
+ // If a per-vertex output variable is used as an l-value, it is a
+ // compile-time or link-time error if the expression indicating the
+ // vertex index is not the identifier gl_InvocationID.
+ if (language == EShLangTessControl) {
+ const TType& leftType = binaryNode->getLeft()->getType();
+ if (leftType.getQualifier().storage == EvqVaryingOut && ! leftType.getQualifier().patch && binaryNode->getLeft()->getAsSymbolNode()) {
+ // we have a per-vertex output
+ const TIntermSymbol* rightSymbol = binaryNode->getRight()->getAsSymbolNode();
+ if (! rightSymbol || rightSymbol->getQualifier().builtIn != EbvInvocationId)
+ error(loc, "tessellation-control per-vertex output l-value must be indexed with gl_InvocationID", "[]", "");
+ }
+ }
+ break; // left node is checked by base class
+#endif
+ case EOpVectorSwizzle:
+ errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft());
+ if (!errorReturn) {
+ int offset[4] = {0,0,0,0};
+
+ TIntermTyped* rightNode = binaryNode->getRight();
+ TIntermAggregate *aggrNode = rightNode->getAsAggregate();
+
+ for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
+ p != aggrNode->getSequence().end(); p++) {
+ int value = (*p)->getAsTyped()->getAsConstantUnion()->getConstArray()[0].getIConst();
+ offset[value]++;
+ if (offset[value] > 1) {
+ error(loc, " l-value of swizzle cannot have duplicate components", op, "", "");
+
+ return true;
+ }
+ }
+ }
+
+ return errorReturn;
+ default:
+ break;
+ }
+
+ if (errorReturn) {
+ error(loc, " l-value required", op, "", "");
+ return true;
+ }
+ }
+
+ if (binaryNode && binaryNode->getOp() == EOpIndexDirectStruct && binaryNode->getLeft()->isReference())
+ return false;
+
+ // Let the base class check errors
+ if (TParseContextBase::lValueErrorCheck(loc, op, node))
+ return true;
+
+ const char* symbol = nullptr;
+ TIntermSymbol* symNode = node->getAsSymbolNode();
+ if (symNode != nullptr)
+ symbol = symNode->getName().c_str();
+
+ const char* message = nullptr;
+ switch (node->getQualifier().storage) {
+ case EvqVaryingIn: message = "can't modify shader input"; break;
+ case EvqInstanceId: message = "can't modify gl_InstanceID"; break;
+ case EvqVertexId: message = "can't modify gl_VertexID"; break;
+ case EvqFace: message = "can't modify gl_FrontFace"; break;
+ case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
+ case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
+ case EvqFragDepth:
+ intermediate.setDepthReplacing();
+ // "In addition, it is an error to statically write to gl_FragDepth in the fragment shader."
+ if (isEsProfile() && intermediate.getEarlyFragmentTests())
+ message = "can't modify gl_FragDepth if using early_fragment_tests";
+ break;
+
+ default:
+ break;
+ }
+
+ if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
+ error(loc, " l-value required", op, "", "");
+
+ return true;
+ }
+
+ //
+ // Everything else is okay, no error.
+ //
+ if (message == nullptr)
+ return false;
+
+ //
+ // If we get here, we have an error and a message.
+ //
+ if (symNode)
+ error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
+ else
+ error(loc, " l-value required", op, "(%s)", message);
+
+ return true;
+}
+
+// Test for and give an error if the node can't be read from.
+void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
+{
+ // Let the base class check errors
+ TParseContextBase::rValueErrorCheck(loc, op, node);
+
+ TIntermSymbol* symNode = node->getAsSymbolNode();
+ if (!(symNode && symNode->getQualifier().isWriteOnly())) // base class checks
+ if (symNode && symNode->getQualifier().isExplicitInterpolation())
+ error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// a constant.
+//
+void TParseContext::constantValueCheck(TIntermTyped* node, const char* token)
+{
+ if (! node->getQualifier().isConstant())
+ error(node->getLoc(), "constant expression required", token, "");
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// an integer.
+//
+void TParseContext::integerCheck(const TIntermTyped* node, const char* token)
+{
+ if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar())
+ return;
+
+ error(node->getLoc(), "scalar integer expression required", token, "");
+}
+
+//
+// Both test, and if necessary spit out an error, to see if we are currently
+// globally scoped.
+//
+void TParseContext::globalCheck(const TSourceLoc& loc, const char* token)
+{
+ if (! symbolTable.atGlobalLevel())
+ error(loc, "not allowed in nested scope", token, "");
+}
+
+//
+// Reserved errors for GLSL.
+//
+void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& identifier)
+{
+ // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be
+ // declared in a shader; this results in a compile-time error."
+ if (! symbolTable.atBuiltInLevel()) {
+ if (builtInName(identifier))
+ error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), "");
+
+ // "__" are not supposed to be an error. ES 300 (and desktop) added the clarification:
+ // "In addition, all identifiers containing two consecutive underscores (__) are
+ // reserved; using such a name does not itself result in an error, but may result
+ // in undefined behavior."
+ // however, before that, ES tests required an error.
+ if (identifier.find("__") != TString::npos) {
+ if (isEsProfile() && version < 300)
+ error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version < 300", identifier.c_str(), "");
+ else
+ warn(loc, "identifiers containing consecutive underscores (\"__\") are reserved", identifier.c_str(), "");
+ }
+ }
+}
+
+//
+// Reserved errors for the preprocessor.
+//
+void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* identifier, const char* op)
+{
+ // "__" are not supposed to be an error. ES 300 (and desktop) added the clarification:
+ // "All macro names containing two consecutive underscores ( __ ) are reserved;
+ // defining such a name does not itself result in an error, but may result in
+ // undefined behavior. All macro names prefixed with "GL_" ("GL" followed by a
+ // single underscore) are also reserved, and defining such a name results in a
+ // compile-time error."
+ // however, before that, ES tests required an error.
+ if (strncmp(identifier, "GL_", 3) == 0)
+ ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op, identifier);
+ else if (strncmp(identifier, "defined", 8) == 0)
+ ppError(loc, "\"defined\" can't be (un)defined:", op, identifier);
+ else if (strstr(identifier, "__") != 0) {
+ if (isEsProfile() && version >= 300 &&
+ (strcmp(identifier, "__LINE__") == 0 ||
+ strcmp(identifier, "__FILE__") == 0 ||
+ strcmp(identifier, "__VERSION__") == 0))
+ ppError(loc, "predefined names can't be (un)defined:", op, identifier);
+ else {
+ if (isEsProfile() && version < 300)
+ ppError(loc, "names containing consecutive underscores are reserved, and an error if version < 300:", op, identifier);
+ else
+ ppWarn(loc, "names containing consecutive underscores are reserved:", op, identifier);
+ }
+ }
+}
+
+//
+// See if this version/profile allows use of the line-continuation character '\'.
+//
+// Returns true if a line continuation should be done.
+//
+bool TParseContext::lineContinuationCheck(const TSourceLoc& loc, bool endOfComment)
+{
+#ifdef GLSLANG_WEB
+ return true;
+#endif
+
+ const char* message = "line continuation";
+
+ bool lineContinuationAllowed = (isEsProfile() && version >= 300) ||
+ (!isEsProfile() && (version >= 420 || extensionTurnedOn(E_GL_ARB_shading_language_420pack)));
+
+ if (endOfComment) {
+ if (lineContinuationAllowed)
+ warn(loc, "used at end of comment; the following line is still part of the comment", message, "");
+ else
+ warn(loc, "used at end of comment, but this version does not provide line continuation", message, "");
+
+ return lineContinuationAllowed;
+ }
+
+ if (relaxedErrors()) {
+ if (! lineContinuationAllowed)
+ warn(loc, "not allowed in this version", message, "");
+ return true;
+ } else {
+ profileRequires(loc, EEsProfile, 300, nullptr, message);
+ profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, message);
+ }
+
+ return lineContinuationAllowed;
+}
+
+bool TParseContext::builtInName(const TString& identifier)
+{
+ return identifier.compare(0, 3, "gl_") == 0;
+}
+
+//
+// Make sure there is enough data and not too many arguments provided to the
+// constructor to build something of the type of the constructor. Also returns
+// the type of the constructor.
+//
+// Part of establishing type is establishing specialization-constness.
+// We don't yet know "top down" whether type is a specialization constant,
+// but a const constructor can becomes a specialization constant if any of
+// its children are, subject to KHR_vulkan_glsl rules:
+//
+// - int(), uint(), and bool() constructors for type conversions
+// from any of the following types to any of the following types:
+// * int
+// * uint
+// * bool
+// - vector versions of the above conversion constructors
+//
+// Returns true if there was an error in construction.
+//
+bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, TFunction& function, TOperator op, TType& type)
+{
+ // See if the constructor does not establish the main type, only requalifies
+ // it, in which case the type comes from the argument instead of from the
+ // constructor function.
+ switch (op) {
+#ifndef GLSLANG_WEB
+ case EOpConstructNonuniform:
+ if (node != nullptr && node->getAsTyped() != nullptr) {
+ type.shallowCopy(node->getAsTyped()->getType());
+ type.getQualifier().makeTemporary();
+ type.getQualifier().nonUniform = true;
+ }
+ break;
+#endif
+ default:
+ type.shallowCopy(function.getType());
+ break;
+ }
+
+ // See if it's a matrix
+ bool constructingMatrix = false;
+ switch (op) {
+ case EOpConstructTextureSampler:
+ return constructorTextureSamplerError(loc, function);
+ case EOpConstructMat2x2:
+ case EOpConstructMat2x3:
+ case EOpConstructMat2x4:
+ case EOpConstructMat3x2:
+ case EOpConstructMat3x3:
+ case EOpConstructMat3x4:
+ case EOpConstructMat4x2:
+ case EOpConstructMat4x3:
+ case EOpConstructMat4x4:
+#ifndef GLSLANG_WEB
+ case EOpConstructDMat2x2:
+ case EOpConstructDMat2x3:
+ case EOpConstructDMat2x4:
+ case EOpConstructDMat3x2:
+ case EOpConstructDMat3x3:
+ case EOpConstructDMat3x4:
+ case EOpConstructDMat4x2:
+ case EOpConstructDMat4x3:
+ case EOpConstructDMat4x4:
+ case EOpConstructF16Mat2x2:
+ case EOpConstructF16Mat2x3:
+ case EOpConstructF16Mat2x4:
+ case EOpConstructF16Mat3x2:
+ case EOpConstructF16Mat3x3:
+ case EOpConstructF16Mat3x4:
+ case EOpConstructF16Mat4x2:
+ case EOpConstructF16Mat4x3:
+ case EOpConstructF16Mat4x4:
+#endif
+ constructingMatrix = true;
+ break;
+ default:
+ break;
+ }
+
+ //
+ // Walk the arguments for first-pass checks and collection of information.
+ //
+
+ int size = 0;
+ bool constType = true;
+ bool specConstType = false; // value is only valid if constType is true
+ bool full = false;
+ bool overFull = false;
+ bool matrixInMatrix = false;
+ bool arrayArg = false;
+ bool floatArgument = false;
+ for (int arg = 0; arg < function.getParamCount(); ++arg) {
+ if (function[arg].type->isArray()) {
+ if (function[arg].type->isUnsizedArray()) {
+ // Can't construct from an unsized array.
+ error(loc, "array argument must be sized", "constructor", "");
+ return true;
+ }
+ arrayArg = true;
+ }
+ if (constructingMatrix && function[arg].type->isMatrix())
+ matrixInMatrix = true;
+
+ // 'full' will go to true when enough args have been seen. If we loop
+ // again, there is an extra argument.
+ if (full) {
+ // For vectors and matrices, it's okay to have too many components
+ // available, but not okay to have unused arguments.
+ overFull = true;
+ }
+
+ size += function[arg].type->computeNumComponents();
+ if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents())
+ full = true;
+
+ if (! function[arg].type->getQualifier().isConstant())
+ constType = false;
+ if (function[arg].type->getQualifier().isSpecConstant())
+ specConstType = true;
+ if (function[arg].type->isFloatingDomain())
+ floatArgument = true;
+ if (type.isStruct()) {
+ if (function[arg].type->contains16BitFloat()) {
+ requireFloat16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type");
+ }
+ if (function[arg].type->contains16BitInt()) {
+ requireInt16Arithmetic(loc, "constructor", "can't construct structure containing 16-bit type");
+ }
+ if (function[arg].type->contains8BitInt()) {
+ requireInt8Arithmetic(loc, "constructor", "can't construct structure containing 8-bit type");
+ }
+ }
+ }
+ if (op == EOpConstructNonuniform)
+ constType = false;
+
+#ifndef GLSLANG_WEB
+ switch (op) {
+ case EOpConstructFloat16:
+ case EOpConstructF16Vec2:
+ case EOpConstructF16Vec3:
+ case EOpConstructF16Vec4:
+ if (type.isArray())
+ requireFloat16Arithmetic(loc, "constructor", "16-bit arrays not supported");
+ if (type.isVector() && function.getParamCount() != 1)
+ requireFloat16Arithmetic(loc, "constructor", "16-bit vectors only take vector types");
+ break;
+ case EOpConstructUint16:
+ case EOpConstructU16Vec2:
+ case EOpConstructU16Vec3:
+ case EOpConstructU16Vec4:
+ case EOpConstructInt16:
+ case EOpConstructI16Vec2:
+ case EOpConstructI16Vec3:
+ case EOpConstructI16Vec4:
+ if (type.isArray())
+ requireInt16Arithmetic(loc, "constructor", "16-bit arrays not supported");
+ if (type.isVector() && function.getParamCount() != 1)
+ requireInt16Arithmetic(loc, "constructor", "16-bit vectors only take vector types");
+ break;
+ case EOpConstructUint8:
+ case EOpConstructU8Vec2:
+ case EOpConstructU8Vec3:
+ case EOpConstructU8Vec4:
+ case EOpConstructInt8:
+ case EOpConstructI8Vec2:
+ case EOpConstructI8Vec3:
+ case EOpConstructI8Vec4:
+ if (type.isArray())
+ requireInt8Arithmetic(loc, "constructor", "8-bit arrays not supported");
+ if (type.isVector() && function.getParamCount() != 1)
+ requireInt8Arithmetic(loc, "constructor", "8-bit vectors only take vector types");
+ break;
+ default:
+ break;
+ }
+#endif
+
+ // inherit constness from children
+ if (constType) {
+ bool makeSpecConst;
+ // Finish pinning down spec-const semantics
+ if (specConstType) {
+ switch (op) {
+ case EOpConstructInt8:
+ case EOpConstructInt:
+ case EOpConstructUint:
+ case EOpConstructBool:
+ case EOpConstructBVec2:
+ case EOpConstructBVec3:
+ case EOpConstructBVec4:
+ case EOpConstructIVec2:
+ case EOpConstructIVec3:
+ case EOpConstructIVec4:
+ case EOpConstructUVec2:
+ case EOpConstructUVec3:
+ case EOpConstructUVec4:
+#ifndef GLSLANG_WEB
+ case EOpConstructUint8:
+ case EOpConstructInt16:
+ case EOpConstructUint16:
+ case EOpConstructInt64:
+ case EOpConstructUint64:
+ case EOpConstructI8Vec2:
+ case EOpConstructI8Vec3:
+ case EOpConstructI8Vec4:
+ case EOpConstructU8Vec2:
+ case EOpConstructU8Vec3:
+ case EOpConstructU8Vec4:
+ case EOpConstructI16Vec2:
+ case EOpConstructI16Vec3:
+ case EOpConstructI16Vec4:
+ case EOpConstructU16Vec2:
+ case EOpConstructU16Vec3:
+ case EOpConstructU16Vec4:
+ case EOpConstructI64Vec2:
+ case EOpConstructI64Vec3:
+ case EOpConstructI64Vec4:
+ case EOpConstructU64Vec2:
+ case EOpConstructU64Vec3:
+ case EOpConstructU64Vec4:
+#endif
+ // This was the list of valid ones, if they aren't converting from float
+ // and aren't making an array.
+ makeSpecConst = ! floatArgument && ! type.isArray();
+ break;
+ default:
+ // anything else wasn't white-listed in the spec as a conversion
+ makeSpecConst = false;
+ break;
+ }
+ } else
+ makeSpecConst = false;
+
+ if (makeSpecConst)
+ type.getQualifier().makeSpecConstant();
+ else if (specConstType)
+ type.getQualifier().makeTemporary();
+ else
+ type.getQualifier().storage = EvqConst;
+ }
+
+ if (type.isArray()) {
+ if (function.getParamCount() == 0) {
+ error(loc, "array constructor must have at least one argument", "constructor", "");
+ return true;
+ }
+
+ if (type.isUnsizedArray()) {
+ // auto adapt the constructor type to the number of arguments
+ type.changeOuterArraySize(function.getParamCount());
+ } else if (type.getOuterArraySize() != function.getParamCount()) {
+ error(loc, "array constructor needs one argument per array element", "constructor", "");
+ return true;
+ }
+
+ if (type.isArrayOfArrays()) {
+ // Types have to match, but we're still making the type.
+ // Finish making the type, and the comparison is done later
+ // when checking for conversion.
+ TArraySizes& arraySizes = *type.getArraySizes();
+
+ // At least the dimensionalities have to match.
+ if (! function[0].type->isArray() ||
+ arraySizes.getNumDims() != function[0].type->getArraySizes()->getNumDims() + 1) {
+ error(loc, "array constructor argument not correct type to construct array element", "constructor", "");
+ return true;
+ }
+
+ if (arraySizes.isInnerUnsized()) {
+ // "Arrays of arrays ..., and the size for any dimension is optional"
+ // That means we need to adopt (from the first argument) the other array sizes into the type.
+ for (int d = 1; d < arraySizes.getNumDims(); ++d) {
+ if (arraySizes.getDimSize(d) == UnsizedArraySize) {
+ arraySizes.setDimSize(d, function[0].type->getArraySizes()->getDimSize(d - 1));
+ }
+ }
+ }
+ }
+ }
+
+ if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) {
+ error(loc, "constructing non-array constituent from array argument", "constructor", "");
+ return true;
+ }
+
+ if (matrixInMatrix && ! type.isArray()) {
+ profileRequires(loc, ENoProfile, 120, nullptr, "constructing matrix from matrix");
+
+ // "If a matrix argument is given to a matrix constructor,
+ // it is a compile-time error to have any other arguments."
+ if (function.getParamCount() != 1)
+ error(loc, "matrix constructed from matrix can only have one argument", "constructor", "");
+ return false;
+ }
+
+ if (overFull) {
+ error(loc, "too many arguments", "constructor", "");
+ return true;
+ }
+
+ if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) {
+ error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
+ return true;
+ }
+
+ if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) ||
+ (op == EOpConstructStruct && size < type.computeNumComponents())) {
+ error(loc, "not enough data provided for construction", "constructor", "");
+ return true;
+ }
+
+ if (type.isCoopMat() && function.getParamCount() != 1) {
+ error(loc, "wrong number of arguments", "constructor", "");
+ return true;
+ }
+ if (type.isCoopMat() &&
+ !(function[0].type->isScalar() || function[0].type->isCoopMat())) {
+ error(loc, "Cooperative matrix constructor argument must be scalar or cooperative matrix", "constructor", "");
+ return true;
+ }
+
+ TIntermTyped* typed = node->getAsTyped();
+ if (typed == nullptr) {
+ error(loc, "constructor argument does not have a type", "constructor", "");
+ return true;
+ }
+ if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) {
+ error(loc, "cannot convert a sampler", "constructor", "");
+ return true;
+ }
+ if (op != EOpConstructStruct && typed->isAtomic()) {
+ error(loc, "cannot convert an atomic_uint", "constructor", "");
+ return true;
+ }
+ if (typed->getBasicType() == EbtVoid) {
+ error(loc, "cannot convert a void", "constructor", "");
+ return true;
+ }
+
+ return false;
+}
+
+// Verify all the correct semantics for constructing a combined texture/sampler.
+// Return true if the semantics are incorrect.
+bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const TFunction& function)
+{
+ TString constructorName = function.getType().getBasicTypeString(); // TODO: performance: should not be making copy; interface needs to change
+ const char* token = constructorName.c_str();
+
+ // exactly two arguments needed
+ if (function.getParamCount() != 2) {
+ error(loc, "sampler-constructor requires two arguments", token, "");
+ return true;
+ }
+
+ // For now, not allowing arrayed constructors, the rest of this function
+ // is set up to allow them, if this test is removed:
+ if (function.getType().isArray()) {
+ error(loc, "sampler-constructor cannot make an array of samplers", token, "");
+ return true;
+ }
+
+ // first argument
+ // * the constructor's first argument must be a texture type
+ // * the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array)
+ // of the texture type must match that of the constructed sampler type
+ // (that is, the suffixes of the type of the first argument and the
+ // type of the constructor will be spelled the same way)
+ if (function[0].type->getBasicType() != EbtSampler ||
+ ! function[0].type->getSampler().isTexture() ||
+ function[0].type->isArray()) {
+ error(loc, "sampler-constructor first argument must be a scalar textureXXX type", token, "");
+ return true;
+ }
+ // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=()
+ TSampler texture = function.getType().getSampler();
+ texture.setCombined(false);
+ texture.shadow = false;
+ if (texture != function[0].type->getSampler()) {
+ error(loc, "sampler-constructor first argument must match type and dimensionality of constructor type", token, "");
+ return true;
+ }
+
+ // second argument
+ // * the constructor's second argument must be a scalar of type
+ // *sampler* or *samplerShadow*
+ if ( function[1].type->getBasicType() != EbtSampler ||
+ ! function[1].type->getSampler().isPureSampler() ||
+ function[1].type->isArray()) {
+ error(loc, "sampler-constructor second argument must be a scalar type 'sampler'", token, "");
+ return true;
+ }
+
+ return false;
+}
+
+// Checks to see if a void variable has been declared and raise an error message for such a case
+//
+// returns true in case of an error
+//
+bool TParseContext::voidErrorCheck(const TSourceLoc& loc, const TString& identifier, const TBasicType basicType)
+{
+ if (basicType == EbtVoid) {
+ error(loc, "illegal use of type 'void'", identifier.c_str(), "");
+ return true;
+ }
+
+ return false;
+}
+
+// Checks to see if the node (for the expression) contains a scalar boolean expression or not
+void TParseContext::boolCheck(const TSourceLoc& loc, const TIntermTyped* type)
+{
+ if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
+ error(loc, "boolean expression expected", "", "");
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+void TParseContext::boolCheck(const TSourceLoc& loc, const TPublicType& pType)
+{
+ if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1))
+ error(loc, "boolean expression expected", "", "");
+}
+
+void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const TString& identifier, TIntermTyped* /*initializer*/)
+{
+ // Check that the appropriate extension is enabled if external sampler is used.
+ // There are two extensions. The correct one must be used based on GLSL version.
+ if (type.getBasicType() == EbtSampler && type.getSampler().isExternal()) {
+ if (version < 300) {
+ requireExtensions(loc, 1, &E_GL_OES_EGL_image_external, "samplerExternalOES");
+ } else {
+ requireExtensions(loc, 1, &E_GL_OES_EGL_image_external_essl3, "samplerExternalOES");
+ }
+ }
+ if (type.getSampler().isYuv()) {
+ requireExtensions(loc, 1, &E_GL_EXT_YUV_target, "__samplerExternal2DY2YEXT");
+ }
+
+ if (type.getQualifier().storage == EvqUniform)
+ return;
+
+ if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler))
+ error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str());
+ else if (type.getBasicType() == EbtSampler && type.getQualifier().storage != EvqUniform) {
+ // non-uniform sampler
+ // not yet: okay if it has an initializer
+ // if (! initializer)
+ error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
+ }
+}
+
+#ifndef GLSLANG_WEB
+
+void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
+{
+ if (type.getQualifier().storage == EvqUniform)
+ return;
+
+ if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAtomicUint))
+ error(loc, "non-uniform struct contains an atomic_uint:", type.getBasicTypeString().c_str(), identifier.c_str());
+ else if (type.getBasicType() == EbtAtomicUint && type.getQualifier().storage != EvqUniform)
+ error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
+}
+
+void TParseContext::accStructNVCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
+{
+ if (type.getQualifier().storage == EvqUniform)
+ return;
+
+ if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStructNV))
+ error(loc, "non-uniform struct contains an accelerationStructureNV:", type.getBasicTypeString().c_str(), identifier.c_str());
+ else if (type.getBasicType() == EbtAccStructNV && type.getQualifier().storage != EvqUniform)
+ error(loc, "accelerationStructureNV can only be used in uniform variables or function parameters:",
+ type.getBasicTypeString().c_str(), identifier.c_str());
+
+}
+
+#endif // GLSLANG_WEB
+
+void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
+{
+ if (parsingBuiltins)
+ return;
+
+ if (type.getQualifier().storage != EvqUniform)
+ return;
+
+ if (type.containsNonOpaque()) {
+ // Vulkan doesn't allow transparent uniforms outside of blocks
+ if (spvVersion.vulkan > 0)
+ vulkanRemoved(loc, "non-opaque uniforms outside a block");
+ // OpenGL wants locations on these (unless they are getting automapped)
+ if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations())
+ error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), "");
+ }
+}
+
+//
+// Qualifier checks knowing the qualifier and that it is a member of a struct/block.
+//
+void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
+{
+ globalQualifierFixCheck(publicType.loc, publicType.qualifier);
+ checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers);
+ if (publicType.qualifier.isNonUniform()) {
+ error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", "");
+ publicType.qualifier.nonUniform = false;
+ }
+}
+
+//
+// Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
+//
+void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier)
+{
+ bool nonuniformOkay = false;
+
+ // move from parameter/unknown qualifiers to pipeline in/out qualifiers
+ switch (qualifier.storage) {
+ case EvqIn:
+ profileRequires(loc, ENoProfile, 130, nullptr, "in for stage inputs");
+ profileRequires(loc, EEsProfile, 300, nullptr, "in for stage inputs");
+ qualifier.storage = EvqVaryingIn;
+ nonuniformOkay = true;
+ break;
+ case EvqOut:
+ profileRequires(loc, ENoProfile, 130, nullptr, "out for stage outputs");
+ profileRequires(loc, EEsProfile, 300, nullptr, "out for stage outputs");
+ qualifier.storage = EvqVaryingOut;
+ break;
+ case EvqInOut:
+ qualifier.storage = EvqVaryingIn;
+ error(loc, "cannot use 'inout' at global scope", "", "");
+ break;
+ case EvqGlobal:
+ case EvqTemporary:
+ nonuniformOkay = true;
+ break;
+ default:
+ break;
+ }
+
+ if (!nonuniformOkay && qualifier.isNonUniform())
+ error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", "");
+
+ invariantCheck(loc, qualifier);
+}
+
+//
+// Check a full qualifier and type (no variable yet) at global level.
+//
+void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TPublicType& publicType)
+{
+ if (! symbolTable.atGlobalLevel())
+ return;
+
+ if (!(publicType.userDef && publicType.userDef->isReference())) {
+ if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) {
+ error(loc, "memory qualifiers cannot be used on this type", "", "");
+ } else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) {
+ error(loc, "memory qualifiers cannot be used on this type", "", "");
+ }
+ }
+
+ if (qualifier.storage == EvqBuffer &&
+ publicType.basicType != EbtBlock &&
+ !qualifier.hasBufferReference())
+ error(loc, "buffers can be declared only as blocks", "buffer", "");
+
+ if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
+ return;
+
+ if (publicType.shaderQualifiers.hasBlendEquation())
+ error(loc, "can only be applied to a standalone 'out'", "blend equation", "");
+
+ // now, knowing it is a shader in/out, do all the in/out semantic checks
+
+ if (publicType.basicType == EbtBool && !parsingBuiltins) {
+ error(loc, "cannot be bool", GetStorageQualifierString(qualifier.storage), "");
+ return;
+ }
+
+ if (isTypeInt(publicType.basicType) || publicType.basicType == EbtDouble)
+ profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output");
+
+ if (!qualifier.flat && !qualifier.isExplicitInterpolation() && !qualifier.isPervertexNV()) {
+ if (isTypeInt(publicType.basicType) ||
+ publicType.basicType == EbtDouble ||
+ (publicType.userDef && ( publicType.userDef->containsBasicType(EbtInt)
+ || publicType.userDef->containsBasicType(EbtUint)
+ || publicType.userDef->contains16BitInt()
+ || publicType.userDef->contains8BitInt()
+ || publicType.userDef->contains64BitInt()
+ || publicType.userDef->containsDouble()))) {
+ if (qualifier.storage == EvqVaryingIn && language == EShLangFragment)
+ error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage));
+ else if (qualifier.storage == EvqVaryingOut && language == EShLangVertex && version == 300)
+ error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage));
+ }
+ }
+
+ if (qualifier.isPatch() && qualifier.isInterpolation())
+ error(loc, "cannot use interpolation qualifiers with patch", "patch", "");
+
+ if (qualifier.isTaskMemory() && publicType.basicType != EbtBlock)
+ error(loc, "taskNV variables can be declared only as blocks", "taskNV", "");
+
+ if (qualifier.storage == EvqVaryingIn) {
+ switch (language) {
+ case EShLangVertex:
+ if (publicType.basicType == EbtStruct) {
+ error(loc, "cannot be a structure or array", GetStorageQualifierString(qualifier.storage), "");
+ return;
+ }
+ if (publicType.arraySizes) {
+ requireProfile(loc, ~EEsProfile, "vertex input arrays");
+ profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays");
+ }
+ if (publicType.basicType == EbtDouble)
+ profileRequires(loc, ~EEsProfile, 410, nullptr, "vertex-shader `double` type input");
+ if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)
+ error(loc, "vertex input cannot be further qualified", "", "");
+ break;
+ case EShLangFragment:
+ if (publicType.userDef) {
+ profileRequires(loc, EEsProfile, 300, nullptr, "fragment-shader struct input");
+ profileRequires(loc, ~EEsProfile, 150, nullptr, "fragment-shader struct input");
+ if (publicType.userDef->containsStructure())
+ requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing structure");
+ if (publicType.userDef->containsArray())
+ requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing an array");
+ }
+ break;
+ case EShLangCompute:
+ if (! symbolTable.atBuiltInLevel())
+ error(loc, "global storage input qualifier cannot be used in a compute shader", "in", "");
+ break;
+#ifndef GLSLANG_WEB
+ case EShLangTessControl:
+ if (qualifier.patch)
+ error(loc, "can only use on output in tessellation-control shader", "patch", "");
+ break;
+#endif
+ default:
+ break;
+ }
+ } else {
+ // qualifier.storage == EvqVaryingOut
+ switch (language) {
+ case EShLangVertex:
+ if (publicType.userDef) {
+ profileRequires(loc, EEsProfile, 300, nullptr, "vertex-shader struct output");
+ profileRequires(loc, ~EEsProfile, 150, nullptr, "vertex-shader struct output");
+ if (publicType.userDef->containsStructure())
+ requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing structure");
+ if (publicType.userDef->containsArray())
+ requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing an array");
+ }
+
+ break;
+ case EShLangFragment:
+ profileRequires(loc, EEsProfile, 300, nullptr, "fragment shader output");
+ if (publicType.basicType == EbtStruct) {
+ error(loc, "cannot be a structure", GetStorageQualifierString(qualifier.storage), "");
+ return;
+ }
+ if (publicType.matrixRows > 0) {
+ error(loc, "cannot be a matrix", GetStorageQualifierString(qualifier.storage), "");
+ return;
+ }
+ if (qualifier.isAuxiliary())
+ error(loc, "can't use auxiliary qualifier on a fragment output", "centroid/sample/patch", "");
+ if (qualifier.isInterpolation())
+ error(loc, "can't use interpolation qualifier on a fragment output", "flat/smooth/noperspective", "");
+ if (publicType.basicType == EbtDouble || publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64)
+ error(loc, "cannot contain a double, int64, or uint64", GetStorageQualifierString(qualifier.storage), "");
+ break;
+
+ case EShLangCompute:
+ error(loc, "global storage output qualifier cannot be used in a compute shader", "out", "");
+ break;
+#ifndef GLSLANG_WEB
+ case EShLangTessEvaluation:
+ if (qualifier.patch)
+ error(loc, "can only use on input in tessellation-evaluation shader", "patch", "");
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+}
+
+//
+// Merge characteristics of the 'src' qualifier into the 'dst'.
+// If there is duplication, issue error messages, unless 'force'
+// is specified, which means to just override default settings.
+//
+// Also, when force is false, it will be assumed that 'src' follows
+// 'dst', for the purpose of error checking order for versions
+// that require specific orderings of qualifiers.
+//
+void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, const TQualifier& src, bool force)
+{
+ // Multiple auxiliary qualifiers (mostly done later by 'individual qualifiers')
+ if (src.isAuxiliary() && dst.isAuxiliary())
+ error(loc, "can only have one auxiliary qualifier (centroid, patch, and sample)", "", "");
+
+ // Multiple interpolation qualifiers (mostly done later by 'individual qualifiers')
+ if (src.isInterpolation() && dst.isInterpolation())
+ error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective, __explicitInterpAMD)", "", "");
+
+ // Ordering
+ if (! force && ((!isEsProfile() && version < 420) ||
+ (isEsProfile() && version < 310))
+ && ! extensionTurnedOn(E_GL_ARB_shading_language_420pack)) {
+ // non-function parameters
+ if (src.isNoContraction() && (dst.invariant || dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
+ error(loc, "precise qualifier must appear first", "", "");
+ if (src.invariant && (dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
+ error(loc, "invariant qualifier must appear before interpolation, storage, and precision qualifiers ", "", "");
+ else if (src.isInterpolation() && (dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
+ error(loc, "interpolation qualifiers must appear before storage and precision qualifiers", "", "");
+ else if (src.isAuxiliary() && (dst.storage != EvqTemporary || dst.precision != EpqNone))
+ error(loc, "Auxiliary qualifiers (centroid, patch, and sample) must appear before storage and precision qualifiers", "", "");
+ else if (src.storage != EvqTemporary && (dst.precision != EpqNone))
+ error(loc, "precision qualifier must appear as last qualifier", "", "");
+
+ // function parameters
+ if (src.isNoContraction() && (dst.storage == EvqConst || dst.storage == EvqIn || dst.storage == EvqOut))
+ error(loc, "precise qualifier must appear first", "", "");
+ if (src.storage == EvqConst && (dst.storage == EvqIn || dst.storage == EvqOut))
+ error(loc, "in/out must appear before const", "", "");
+ }
+
+ // Storage qualification
+ if (dst.storage == EvqTemporary || dst.storage == EvqGlobal)
+ dst.storage = src.storage;
+ else if ((dst.storage == EvqIn && src.storage == EvqOut) ||
+ (dst.storage == EvqOut && src.storage == EvqIn))
+ dst.storage = EvqInOut;
+ else if ((dst.storage == EvqIn && src.storage == EvqConst) ||
+ (dst.storage == EvqConst && src.storage == EvqIn))
+ dst.storage = EvqConstReadOnly;
+ else if (src.storage != EvqTemporary &&
+ src.storage != EvqGlobal)
+ error(loc, "too many storage qualifiers", GetStorageQualifierString(src.storage), "");
+
+ // Precision qualifiers
+ if (! force && src.precision != EpqNone && dst.precision != EpqNone)
+ error(loc, "only one precision qualifier allowed", GetPrecisionQualifierString(src.precision), "");
+ if (dst.precision == EpqNone || (force && src.precision != EpqNone))
+ dst.precision = src.precision;
+
+#ifndef GLSLANG_WEB
+ if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
+ (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
+ (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
+ (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent)) ||
+ (src.subgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent)))) {
+ error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent qualifier allowed", GetPrecisionQualifierString(src.precision), "");
+ }
+#endif
+ // Layout qualifiers
+ mergeObjectLayoutQualifiers(dst, src, false);
+
+ // individual qualifiers
+ bool repeated = false;
+ #define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field;
+ MERGE_SINGLETON(invariant);
+ MERGE_SINGLETON(centroid);
+ MERGE_SINGLETON(smooth);
+ MERGE_SINGLETON(flat);
+ MERGE_SINGLETON(specConstant);
+#ifndef GLSLANG_WEB
+ MERGE_SINGLETON(noContraction);
+ MERGE_SINGLETON(nopersp);
+ MERGE_SINGLETON(explicitInterp);
+ MERGE_SINGLETON(perPrimitiveNV);
+ MERGE_SINGLETON(perViewNV);
+ MERGE_SINGLETON(perTaskNV);
+ MERGE_SINGLETON(patch);
+ MERGE_SINGLETON(sample);
+ MERGE_SINGLETON(coherent);
+ MERGE_SINGLETON(devicecoherent);
+ MERGE_SINGLETON(queuefamilycoherent);
+ MERGE_SINGLETON(workgroupcoherent);
+ MERGE_SINGLETON(subgroupcoherent);
+ MERGE_SINGLETON(nonprivate);
+ MERGE_SINGLETON(volatil);
+ MERGE_SINGLETON(restrict);
+ MERGE_SINGLETON(readonly);
+ MERGE_SINGLETON(writeonly);
+ MERGE_SINGLETON(nonUniform);
+#endif
+
+ if (repeated)
+ error(loc, "replicated qualifiers", "", "");
+}
+
+void TParseContext::setDefaultPrecision(const TSourceLoc& loc, TPublicType& publicType, TPrecisionQualifier qualifier)
+{
+ TBasicType basicType = publicType.basicType;
+
+ if (basicType == EbtSampler) {
+ defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)] = qualifier;
+
+ return; // all is well
+ }
+
+ if (basicType == EbtInt || basicType == EbtFloat) {
+ if (publicType.isScalar()) {
+ defaultPrecision[basicType] = qualifier;
+ if (basicType == EbtInt) {
+ defaultPrecision[EbtUint] = qualifier;
+ precisionManager.explicitIntDefaultSeen();
+ } else
+ precisionManager.explicitFloatDefaultSeen();
+
+ return; // all is well
+ }
+ }
+
+ if (basicType == EbtAtomicUint) {
+ if (qualifier != EpqHigh)
+ error(loc, "can only apply highp to atomic_uint", "precision", "");
+
+ return;
+ }
+
+ error(loc, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), "");
+}
+
+// used to flatten the sampler type space into a single dimension
+// correlates with the declaration of defaultSamplerPrecision[]
+int TParseContext::computeSamplerTypeIndex(TSampler& sampler)
+{
+ int arrayIndex = sampler.arrayed ? 1 : 0;
+ int shadowIndex = sampler.shadow ? 1 : 0;
+ int externalIndex = sampler.isExternal() ? 1 : 0;
+ int imageIndex = sampler.isImageClass() ? 1 : 0;
+ int msIndex = sampler.isMultiSample() ? 1 : 0;
+
+ int flattened = EsdNumDims * (EbtNumTypes * (2 * (2 * (2 * (2 * arrayIndex + msIndex) + imageIndex) + shadowIndex) +
+ externalIndex) + sampler.type) + sampler.dim;
+ assert(flattened < maxSamplerIndex);
+
+ return flattened;
+}
+
+TPrecisionQualifier TParseContext::getDefaultPrecision(TPublicType& publicType)
+{
+ if (publicType.basicType == EbtSampler)
+ return defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)];
+ else
+ return defaultPrecision[publicType.basicType];
+}
+
+void TParseContext::precisionQualifierCheck(const TSourceLoc& loc, TBasicType baseType, TQualifier& qualifier)
+{
+ // Built-in symbols are allowed some ambiguous precisions, to be pinned down
+ // later by context.
+ if (! obeyPrecisionQualifiers() || parsingBuiltins)
+ return;
+
+#ifndef GLSLANG_WEB
+ if (baseType == EbtAtomicUint && qualifier.precision != EpqNone && qualifier.precision != EpqHigh)
+ error(loc, "atomic counters can only be highp", "atomic_uint", "");
+#endif
+
+ if (baseType == EbtFloat || baseType == EbtUint || baseType == EbtInt || baseType == EbtSampler || baseType == EbtAtomicUint) {
+ if (qualifier.precision == EpqNone) {
+ if (relaxedErrors())
+ warn(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), "substituting 'mediump'");
+ else
+ error(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), "");
+ qualifier.precision = EpqMedium;
+ defaultPrecision[baseType] = EpqMedium;
+ }
+ } else if (qualifier.precision != EpqNone)
+ error(loc, "type cannot have precision qualifier", TType::getBasicString(baseType), "");
+}
+
+void TParseContext::parameterTypeCheck(const TSourceLoc& loc, TStorageQualifier qualifier, const TType& type)
+{
+ if ((qualifier == EvqOut || qualifier == EvqInOut) && type.isOpaque())
+ error(loc, "samplers and atomic_uints cannot be output parameters", type.getBasicTypeString().c_str(), "");
+ if (!parsingBuiltins && type.contains16BitFloat())
+ requireFloat16Arithmetic(loc, type.getBasicTypeString().c_str(), "float16 types can only be in uniform block or buffer storage");
+ if (!parsingBuiltins && type.contains16BitInt())
+ requireInt16Arithmetic(loc, type.getBasicTypeString().c_str(), "(u)int16 types can only be in uniform block or buffer storage");
+ if (!parsingBuiltins && type.contains8BitInt())
+ requireInt8Arithmetic(loc, type.getBasicTypeString().c_str(), "(u)int8 types can only be in uniform block or buffer storage");
+}
+
+bool TParseContext::containsFieldWithBasicType(const TType& type, TBasicType basicType)
+{
+ if (type.getBasicType() == basicType)
+ return true;
+
+ if (type.getBasicType() == EbtStruct) {
+ const TTypeList& structure = *type.getStruct();
+ for (unsigned int i = 0; i < structure.size(); ++i) {
+ if (containsFieldWithBasicType(*structure[i].type, basicType))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//
+// Do size checking for an array type's size.
+//
+void TParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair, const char *sizeType)
+{
+ bool isConst = false;
+ sizePair.node = nullptr;
+
+ int size = 1;
+
+ TIntermConstantUnion* constant = expr->getAsConstantUnion();
+ if (constant) {
+ // handle true (non-specialization) constant
+ size = constant->getConstArray()[0].getIConst();
+ isConst = true;
+ } else {
+ // see if it's a specialization constant instead
+ if (expr->getQualifier().isSpecConstant()) {
+ isConst = true;
+ sizePair.node = expr;
+ TIntermSymbol* symbol = expr->getAsSymbolNode();
+ if (symbol && symbol->getConstArray().size() > 0)
+ size = symbol->getConstArray()[0].getIConst();
+ } else if (expr->getAsUnaryNode() &&
+ expr->getAsUnaryNode()->getOp() == glslang::EOpArrayLength &&
+ expr->getAsUnaryNode()->getOperand()->getType().isCoopMat()) {
+ isConst = true;
+ size = 1;
+ sizePair.node = expr->getAsUnaryNode();
+ }
+ }
+
+ sizePair.size = size;
+
+ if (! isConst || (expr->getBasicType() != EbtInt && expr->getBasicType() != EbtUint)) {
+ error(loc, sizeType, "", "must be a constant integer expression");
+ return;
+ }
+
+ if (size <= 0) {
+ error(loc, sizeType, "", "must be a positive integer");
+ return;
+ }
+}
+
+//
+// See if this qualifier can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayQualifierError(const TSourceLoc& loc, const TQualifier& qualifier)
+{
+ if (qualifier.storage == EvqConst) {
+ profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "const array");
+ profileRequires(loc, EEsProfile, 300, nullptr, "const array");
+ }
+
+ if (qualifier.storage == EvqVaryingIn && language == EShLangVertex) {
+ requireProfile(loc, ~EEsProfile, "vertex input arrays");
+ profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays");
+ }
+
+ return false;
+}
+
+//
+// See if this qualifier and type combination can be an array.
+// Assumes arrayQualifierError() was also called to catch the type-invariant tests.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayError(const TSourceLoc& loc, const TType& type)
+{
+ if (type.getQualifier().storage == EvqVaryingOut && language == EShLangVertex) {
+ if (type.isArrayOfArrays())
+ requireProfile(loc, ~EEsProfile, "vertex-shader array-of-array output");
+ else if (type.isStruct())
+ requireProfile(loc, ~EEsProfile, "vertex-shader array-of-struct output");
+ }
+ if (type.getQualifier().storage == EvqVaryingIn && language == EShLangFragment) {
+ if (type.isArrayOfArrays())
+ requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array input");
+ else if (type.isStruct())
+ requireProfile(loc, ~EEsProfile, "fragment-shader array-of-struct input");
+ }
+ if (type.getQualifier().storage == EvqVaryingOut && language == EShLangFragment) {
+ if (type.isArrayOfArrays())
+ requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array output");
+ }
+
+ return false;
+}
+
+//
+// Require array to be completely sized
+//
+void TParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes)
+{
+ if (!parsingBuiltins && arraySizes.hasUnsized())
+ error(loc, "array size required", "", "");
+}
+
+void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& type)
+{
+ const TTypeList& structure = *type.getStruct();
+ for (int m = 0; m < (int)structure.size(); ++m) {
+ const TType& member = *structure[m].type;
+ if (member.isArray())
+ arraySizeRequiredCheck(structure[m].loc, *member.getArraySizes());
+ }
+}
+
+void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, TArraySizes* arraySizes,
+ const TIntermTyped* initializer, bool lastMember)
+{
+ assert(arraySizes);
+
+ // always allow special built-in ins/outs sized to topologies
+ if (parsingBuiltins)
+ return;
+
+ // initializer must be a sized array, in which case
+ // allow the initializer to set any unknown array sizes
+ if (initializer != nullptr) {
+ if (initializer->getType().isUnsizedArray())
+ error(loc, "array initializer must be sized", "[]", "");
+ return;
+ }
+
+ // No environment allows any non-outer-dimension to be implicitly sized
+ if (arraySizes->isInnerUnsized()) {
+ error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", "");
+ arraySizes->clearInnerUnsized();
+ }
+
+ if (arraySizes->isInnerSpecialization() &&
+ (qualifier.storage != EvqTemporary && qualifier.storage != EvqGlobal && qualifier.storage != EvqShared && qualifier.storage != EvqConst))
+ error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", "");
+
+#ifndef GLSLANG_WEB
+
+ // desktop always allows outer-dimension-unsized variable arrays,
+ if (!isEsProfile())
+ return;
+
+ // for ES, if size isn't coming from an initializer, it has to be explicitly declared now,
+ // with very few exceptions
+
+ // implicitly-sized io exceptions:
+ switch (language) {
+ case EShLangGeometry:
+ if (qualifier.storage == EvqVaryingIn)
+ if ((isEsProfile() && version >= 320) ||
+ extensionsTurnedOn(Num_AEP_geometry_shader, AEP_geometry_shader))
+ return;
+ break;
+ case EShLangTessControl:
+ if ( qualifier.storage == EvqVaryingIn ||
+ (qualifier.storage == EvqVaryingOut && ! qualifier.isPatch()))
+ if ((isEsProfile() && version >= 320) ||
+ extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))
+ return;
+ break;
+ case EShLangTessEvaluation:
+ if ((qualifier.storage == EvqVaryingIn && ! qualifier.isPatch()) ||
+ qualifier.storage == EvqVaryingOut)
+ if ((isEsProfile() && version >= 320) ||
+ extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))
+ return;
+ break;
+ case EShLangMeshNV:
+ if (qualifier.storage == EvqVaryingOut)
+ if ((isEsProfile() && version >= 320) ||
+ extensionTurnedOn(E_GL_NV_mesh_shader))
+ return;
+ break;
+ default:
+ break;
+ }
+
+#endif
+
+ // last member of ssbo block exception:
+ if (qualifier.storage == EvqBuffer && lastMember)
+ return;
+
+ arraySizeRequiredCheck(loc, *arraySizes);
+}
+
+void TParseContext::arrayOfArrayVersionCheck(const TSourceLoc& loc, const TArraySizes* sizes)
+{
+ if (sizes == nullptr || sizes->getNumDims() == 1)
+ return;
+
+ const char* feature = "arrays of arrays";
+
+ requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature);
+}
+
+//
+// Do all the semantic checking for declaring or redeclaring an array, with and
+// without a size, and make the right changes to the symbol table.
+//
+void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifier, const TType& type, TSymbol*& symbol)
+{
+ if (symbol == nullptr) {
+ bool currentScope;
+ symbol = symbolTable.find(identifier, nullptr, &currentScope);
+
+ if (symbol && builtInName(identifier) && ! symbolTable.atBuiltInLevel()) {
+ // bad shader (errors already reported) trying to redeclare a built-in name as an array
+ symbol = nullptr;
+ return;
+ }
+ if (symbol == nullptr || ! currentScope) {
+ //
+ // Successfully process a new definition.
+ // (Redeclarations have to take place at the same scope; otherwise they are hiding declarations)
+ //
+ symbol = new TVariable(&identifier, type);
+ symbolTable.insert(*symbol);
+ if (symbolTable.atGlobalLevel())
+ trackLinkage(*symbol);
+
+#ifndef GLSLANG_WEB
+ if (! symbolTable.atBuiltInLevel()) {
+ if (isIoResizeArray(type)) {
+ ioArraySymbolResizeList.push_back(symbol);
+ checkIoArraysConsistency(loc, true);
+ } else
+ fixIoArraySize(loc, symbol->getWritableType());
+ }
+#endif
+
+ return;
+ }
+ if (symbol->getAsAnonMember()) {
+ error(loc, "cannot redeclare a user-block member array", identifier.c_str(), "");
+ symbol = nullptr;
+ return;
+ }
+ }
+
+ //
+ // Process a redeclaration.
+ //
+
+ if (symbol == nullptr) {
+ error(loc, "array variable name expected", identifier.c_str(), "");
+ return;
+ }
+
+ // redeclareBuiltinVariable() should have already done the copyUp()
+ TType& existingType = symbol->getWritableType();
+
+ if (! existingType.isArray()) {
+ error(loc, "redeclaring non-array as array", identifier.c_str(), "");
+ return;
+ }
+
+ if (! existingType.sameElementType(type)) {
+ error(loc, "redeclaration of array with a different element type", identifier.c_str(), "");
+ return;
+ }
+
+ if (! existingType.sameInnerArrayness(type)) {
+ error(loc, "redeclaration of array with a different array dimensions or sizes", identifier.c_str(), "");
+ return;
+ }
+
+#ifndef GLSLANG_WEB
+ if (existingType.isSizedArray()) {
+ // be more leniant for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size
+ if (! (isIoResizeArray(type) && existingType.getOuterArraySize() == type.getOuterArraySize()))
+ error(loc, "redeclaration of array with size", identifier.c_str(), "");
+ return;
+ }
+
+ arrayLimitCheck(loc, identifier, type.getOuterArraySize());
+
+ existingType.updateArraySizes(type);
+
+ if (isIoResizeArray(type))
+ checkIoArraysConsistency(loc);
+#endif
+}
+
+#ifndef GLSLANG_WEB
+
+// Policy and error check for needing a runtime sized array.
+void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermTyped& base)
+{
+ // runtime length implies runtime sizeable, so no problem
+ if (isRuntimeLength(base))
+ return;
+
+ // Check for last member of a bufferreference type, which is runtime sizeable
+ // but doesn't support runtime length
+ if (base.getType().getQualifier().storage == EvqBuffer) {
+ const TIntermBinary* binary = base.getAsBinaryNode();
+ if (binary != nullptr &&
+ binary->getOp() == EOpIndexDirectStruct &&
+ binary->getLeft()->isReference()) {
+
+ const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
+ const int memberCount = (int)binary->getLeft()->getType().getReferentType()->getStruct()->size();
+ if (index == memberCount - 1)
+ return;
+ }
+ }
+
+ // check for additional things allowed by GL_EXT_nonuniform_qualifier
+ if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStructNV ||
+ (base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer()))
+ requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index");
+ else
+ error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable");
+}
+
+// Policy decision for whether a run-time .length() is allowed.
+bool TParseContext::isRuntimeLength(const TIntermTyped& base) const
+{
+ if (base.getType().getQualifier().storage == EvqBuffer) {
+ // in a buffer block
+ const TIntermBinary* binary = base.getAsBinaryNode();
+ if (binary != nullptr && binary->getOp() == EOpIndexDirectStruct) {
+ // is it the last member?
+ const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
+
+ if (binary->getLeft()->isReference())
+ return false;
+
+ const int memberCount = (int)binary->getLeft()->getType().getStruct()->size();
+ if (index == memberCount - 1)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Check if mesh perviewNV attributes have a view dimension
+// and resize it to gl_MaxMeshViewCountNV when implicitly sized.
+void TParseContext::checkAndResizeMeshViewDim(const TSourceLoc& loc, TType& type, bool isBlockMember)
+{
+ // see if member is a per-view attribute
+ if (!type.getQualifier().isPerView())
+ return;
+
+ if ((isBlockMember && type.isArray()) || (!isBlockMember && type.isArrayOfArrays())) {
+ // since we don't have the maxMeshViewCountNV set during parsing builtins, we hardcode the value.
+ int maxViewCount = parsingBuiltins ? 4 : resources.maxMeshViewCountNV;
+ // For block members, outermost array dimension is the view dimension.
+ // For non-block members, outermost array dimension is the vertex/primitive dimension
+ // and 2nd outermost is the view dimension.
+ int viewDim = isBlockMember ? 0 : 1;
+ int viewDimSize = type.getArraySizes()->getDimSize(viewDim);
+
+ if (viewDimSize != UnsizedArraySize && viewDimSize != maxViewCount)
+ error(loc, "mesh view output array size must be gl_MaxMeshViewCountNV or implicitly sized", "[]", "");
+ else if (viewDimSize == UnsizedArraySize)
+ type.getArraySizes()->setDimSize(viewDim, maxViewCount);
+ }
+ else {
+ error(loc, "requires a view array dimension", "perviewNV", "");
+ }
+}
+
+#endif // GLSLANG_WEB
+
+// Returns true if the first argument to the #line directive is the line number for the next line.
+//
+// Desktop, pre-version 3.30: "After processing this directive
+// (including its new-line), the implementation will behave as if it is compiling at line number line+1 and
+// source string number source-string-number."
+//
+// Desktop, version 3.30 and later, and ES: "After processing this directive
+// (including its new-line), the implementation will behave as if it is compiling at line number line and
+// source string number source-string-number.
+bool TParseContext::lineDirectiveShouldSetNextLine() const
+{
+ return isEsProfile() || version >= 330;
+}
+
+//
+// Enforce non-initializer type/qualifier rules.
+//
+void TParseContext::nonInitConstCheck(const TSourceLoc& loc, TString& identifier, TType& type)
+{
+ //
+ // Make the qualifier make sense, given that there is not an initializer.
+ //
+ if (type.getQualifier().storage == EvqConst ||
+ type.getQualifier().storage == EvqConstReadOnly) {
+ type.getQualifier().makeTemporary();
+ error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
+ }
+}
+
+//
+// See if the identifier is a built-in symbol that can be redeclared, and if so,
+// copy the symbol table's read-only built-in variable to the current
+// global level, where it can be modified based on the passed in type.
+//
+// Returns nullptr if no redeclaration took place; meaning a normal declaration still
+// needs to occur for it, not necessarily an error.
+//
+// Returns a redeclared and type-modified variable if a redeclarated occurred.
+//
+TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TString& identifier,
+ const TQualifier& qualifier, const TShaderQualifiers& publicType)
+{
+#ifndef GLSLANG_WEB
+ if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel())
+ return nullptr;
+
+ bool nonEsRedecls = (!isEsProfile() && (version >= 130 || identifier == "gl_TexCoord"));
+ bool esRedecls = (isEsProfile() &&
+ (version >= 320 || extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks)));
+ if (! esRedecls && ! nonEsRedecls)
+ return nullptr;
+
+ // Special case when using GL_ARB_separate_shader_objects
+ bool ssoPre150 = false; // means the only reason this variable is redeclared is due to this combination
+ if (!isEsProfile() && version <= 140 && extensionTurnedOn(E_GL_ARB_separate_shader_objects)) {
+ if (identifier == "gl_Position" ||
+ identifier == "gl_PointSize" ||
+ identifier == "gl_ClipVertex" ||
+ identifier == "gl_FogFragCoord")
+ ssoPre150 = true;
+ }
+
+ // Potentially redeclaring a built-in variable...
+
+ if (ssoPre150 ||
+ (identifier == "gl_FragDepth" && ((nonEsRedecls && version >= 420) || esRedecls)) ||
+ (identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 150) || esRedecls)) ||
+ identifier == "gl_ClipDistance" ||
+ identifier == "gl_CullDistance" ||
+ identifier == "gl_FrontColor" ||
+ identifier == "gl_BackColor" ||
+ identifier == "gl_FrontSecondaryColor" ||
+ identifier == "gl_BackSecondaryColor" ||
+ identifier == "gl_SecondaryColor" ||
+ (identifier == "gl_Color" && language == EShLangFragment) ||
+ (identifier == "gl_FragStencilRefARB" && (nonEsRedecls && version >= 140)
+ && language == EShLangFragment) ||
+ identifier == "gl_SampleMask" ||
+ identifier == "gl_Layer" ||
+ identifier == "gl_PrimitiveIndicesNV" ||
+ identifier == "gl_TexCoord") {
+
+ // Find the existing symbol, if any.
+ bool builtIn;
+ TSymbol* symbol = symbolTable.find(identifier, &builtIn);
+
+ // If the symbol was not found, this must be a version/profile/stage
+ // that doesn't have it.
+ if (! symbol)
+ return nullptr;
+
+ // If it wasn't at a built-in level, then it's already been redeclared;
+ // that is, this is a redeclaration of a redeclaration; reuse that initial
+ // redeclaration. Otherwise, make the new one.
+ if (builtIn)
+ makeEditable(symbol);
+
+ // Now, modify the type of the copy, as per the type of the current redeclaration.
+
+ TQualifier& symbolQualifier = symbol->getWritableType().getQualifier();
+ if (ssoPre150) {
+ if (intermediate.inIoAccessed(identifier))
+ error(loc, "cannot redeclare after use", identifier.c_str(), "");
+ if (qualifier.hasLayout())
+ error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str());
+ if (qualifier.isMemory() || qualifier.isAuxiliary() || (language == EShLangVertex && qualifier.storage != EvqVaryingOut) ||
+ (language == EShLangFragment && qualifier.storage != EvqVaryingIn))
+ error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str());
+ if (! qualifier.smooth)
+ error(loc, "cannot change interpolation qualification of", "redeclaration", symbol->getName().c_str());
+ } else if (identifier == "gl_FrontColor" ||
+ identifier == "gl_BackColor" ||
+ identifier == "gl_FrontSecondaryColor" ||
+ identifier == "gl_BackSecondaryColor" ||
+ identifier == "gl_SecondaryColor" ||
+ identifier == "gl_Color") {
+ symbolQualifier.flat = qualifier.flat;
+ symbolQualifier.smooth = qualifier.smooth;
+ symbolQualifier.nopersp = qualifier.nopersp;
+ if (qualifier.hasLayout())
+ error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str());
+ if (qualifier.isMemory() || qualifier.isAuxiliary() || symbol->getType().getQualifier().storage != qualifier.storage)
+ error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str());
+ } else if (identifier == "gl_TexCoord" ||
+ identifier == "gl_ClipDistance" ||
+ identifier == "gl_CullDistance") {
+ if (qualifier.hasLayout() || qualifier.isMemory() || qualifier.isAuxiliary() ||
+ qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat ||
+ symbolQualifier.storage != qualifier.storage)
+ error(loc, "cannot change qualification of", "redeclaration", symbol->getName().c_str());
+ } else if (identifier == "gl_FragCoord") {
+ if (intermediate.inIoAccessed("gl_FragCoord"))
+ error(loc, "cannot redeclare after use", "gl_FragCoord", "");
+ if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat ||
+ qualifier.isMemory() || qualifier.isAuxiliary())
+ error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str());
+ if (qualifier.storage != EvqVaryingIn)
+ error(loc, "cannot change input storage qualification of", "redeclaration", symbol->getName().c_str());
+ if (! builtIn && (publicType.pixelCenterInteger != intermediate.getPixelCenterInteger() ||
+ publicType.originUpperLeft != intermediate.getOriginUpperLeft()))
+ error(loc, "cannot redeclare with different qualification:", "redeclaration", symbol->getName().c_str());
+ if (publicType.pixelCenterInteger)
+ intermediate.setPixelCenterInteger();
+ if (publicType.originUpperLeft)
+ intermediate.setOriginUpperLeft();
+ } else if (identifier == "gl_FragDepth") {
+ if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat ||
+ qualifier.isMemory() || qualifier.isAuxiliary())
+ error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str());
+ if (qualifier.storage != EvqVaryingOut)
+ error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str());
+ if (publicType.layoutDepth != EldNone) {
+ if (intermediate.inIoAccessed("gl_FragDepth"))
+ error(loc, "cannot redeclare after use", "gl_FragDepth", "");
+ if (! intermediate.setDepth(publicType.layoutDepth))
+ error(loc, "all redeclarations must use the same depth layout on", "redeclaration", symbol->getName().c_str());
+ }
+ }
+ else if (
+ identifier == "gl_PrimitiveIndicesNV" ||
+ identifier == "gl_FragStencilRefARB") {
+ if (qualifier.hasLayout())
+ error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str());
+ if (qualifier.storage != EvqVaryingOut)
+ error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str());
+ }
+ else if (identifier == "gl_SampleMask") {
+ if (!publicType.layoutOverrideCoverage) {
+ error(loc, "redeclaration only allowed for override_coverage layout", "redeclaration", symbol->getName().c_str());
+ }
+ intermediate.setLayoutOverrideCoverage();
+ }
+ else if (identifier == "gl_Layer") {
+ if (!qualifier.layoutViewportRelative && qualifier.layoutSecondaryViewportRelativeOffset == -2048)
+ error(loc, "redeclaration only allowed for viewport_relative or secondary_view_offset layout", "redeclaration", symbol->getName().c_str());
+ symbolQualifier.layoutViewportRelative = qualifier.layoutViewportRelative;
+ symbolQualifier.layoutSecondaryViewportRelativeOffset = qualifier.layoutSecondaryViewportRelativeOffset;
+ }
+
+ // TODO: semantics quality: separate smooth from nothing declared, then use IsInterpolation for several tests above
+
+ return symbol;
+ }
+#endif
+
+ return nullptr;
+}
+
+//
+// Either redeclare the requested block, or give an error message why it can't be done.
+//
+// TODO: functionality: explicitly sizing members of redeclared blocks is not giving them an explicit size
+void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newTypeList, const TString& blockName,
+ const TString* instanceName, TArraySizes* arraySizes)
+{
+#ifndef GLSLANG_WEB
+ const char* feature = "built-in block redeclaration";
+ profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature);
+ profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
+
+ if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment" &&
+ blockName != "gl_MeshPerVertexNV" && blockName != "gl_MeshPerPrimitiveNV") {
+ error(loc, "cannot redeclare block: ", "block declaration", blockName.c_str());
+ return;
+ }
+
+ // Redeclaring a built-in block...
+
+ if (instanceName && ! builtInName(*instanceName)) {
+ error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), "");
+ return;
+ }
+
+ // Blocks with instance names are easy to find, lookup the instance name,
+ // Anonymous blocks need to be found via a member.
+ bool builtIn;
+ TSymbol* block;
+ if (instanceName)
+ block = symbolTable.find(*instanceName, &builtIn);
+ else
+ block = symbolTable.find(newTypeList.front().type->getFieldName(), &builtIn);
+
+ // If the block was not found, this must be a version/profile/stage
+ // that doesn't have it, or the instance name is wrong.
+ const char* errorName = instanceName ? instanceName->c_str() : newTypeList.front().type->getFieldName().c_str();
+ if (! block) {
+ error(loc, "no declaration found for redeclaration", errorName, "");
+ return;
+ }
+ // Built-in blocks cannot be redeclared more than once, which if happened,
+ // we'd be finding the already redeclared one here, rather than the built in.
+ if (! builtIn) {
+ error(loc, "can only redeclare a built-in block once, and before any use", blockName.c_str(), "");
+ return;
+ }
+
+ // Copy the block to make a writable version, to insert into the block table after editing.
+ block = symbolTable.copyUpDeferredInsert(block);
+
+ if (block->getType().getBasicType() != EbtBlock) {
+ error(loc, "cannot redeclare a non block as a block", errorName, "");
+ return;
+ }
+
+ // Fix XFB stuff up, it applies to the order of the redeclaration, not
+ // the order of the original members.
+ if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) {
+ if (!currentBlockQualifier.hasXfbBuffer())
+ currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
+ if (!currentBlockQualifier.hasStream())
+ currentBlockQualifier.layoutStream = globalOutputDefaults.layoutStream;
+ fixXfbOffsets(currentBlockQualifier, newTypeList);
+ }
+
+ // Edit and error check the container against the redeclaration
+ // - remove unused members
+ // - ensure remaining qualifiers/types match
+
+ TType& type = block->getWritableType();
+
+ // if gl_PerVertex is redeclared for the purpose of passing through "gl_Position"
+ // for passthrough purpose, the redeclared block should have the same qualifers as
+ // the current one
+ if (currentBlockQualifier.layoutPassthrough) {
+ type.getQualifier().layoutPassthrough = currentBlockQualifier.layoutPassthrough;
+ type.getQualifier().storage = currentBlockQualifier.storage;
+ type.getQualifier().layoutStream = currentBlockQualifier.layoutStream;
+ type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer;
+ }
+
+ TTypeList::iterator member = type.getWritableStruct()->begin();
+ size_t numOriginalMembersFound = 0;
+ while (member != type.getStruct()->end()) {
+ // look for match
+ bool found = false;
+ TTypeList::const_iterator newMember;
+ TSourceLoc memberLoc;
+ memberLoc.init();
+ for (newMember = newTypeList.begin(); newMember != newTypeList.end(); ++newMember) {
+ if (member->type->getFieldName() == newMember->type->getFieldName()) {
+ found = true;
+ memberLoc = newMember->loc;
+ break;
+ }
+ }
+
+ if (found) {
+ ++numOriginalMembersFound;
+ // - ensure match between redeclared members' types
+ // - check for things that can't be changed
+ // - update things that can be changed
+ TType& oldType = *member->type;
+ const TType& newType = *newMember->type;
+ if (! newType.sameElementType(oldType))
+ error(memberLoc, "cannot redeclare block member with a different type", member->type->getFieldName().c_str(), "");
+ if (oldType.isArray() != newType.isArray())
+ error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), "");
+ else if (! oldType.getQualifier().isPerView() && ! oldType.sameArrayness(newType) && oldType.isSizedArray())
+ error(memberLoc, "cannot change array size of redeclared block member", member->type->getFieldName().c_str(), "");
+ else if (! oldType.getQualifier().isPerView() && newType.isArray())
+ arrayLimitCheck(loc, member->type->getFieldName(), newType.getOuterArraySize());
+ if (oldType.getQualifier().isPerView() && ! newType.getQualifier().isPerView())
+ error(memberLoc, "missing perviewNV qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
+ else if (! oldType.getQualifier().isPerView() && newType.getQualifier().isPerView())
+ error(memberLoc, "cannot add perviewNV qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
+ else if (newType.getQualifier().isPerView()) {
+ if (oldType.getArraySizes()->getNumDims() != newType.getArraySizes()->getNumDims())
+ error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), "");
+ else if (! newType.isUnsizedArray() && newType.getOuterArraySize() != resources.maxMeshViewCountNV)
+ error(loc, "mesh view output array size must be gl_MaxMeshViewCountNV or implicitly sized", "[]", "");
+ else if (newType.getArraySizes()->getNumDims() == 2) {
+ int innerDimSize = newType.getArraySizes()->getDimSize(1);
+ arrayLimitCheck(memberLoc, member->type->getFieldName(), innerDimSize);
+ oldType.getArraySizes()->setDimSize(1, innerDimSize);
+ }
+ }
+ if (oldType.getQualifier().isPerPrimitive() && ! newType.getQualifier().isPerPrimitive())
+ error(memberLoc, "missing perprimitiveNV qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
+ else if (! oldType.getQualifier().isPerPrimitive() && newType.getQualifier().isPerPrimitive())
+ error(memberLoc, "cannot add perprimitiveNV qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
+ if (newType.getQualifier().isMemory())
+ error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
+ if (newType.getQualifier().hasNonXfbLayout())
+ error(memberLoc, "cannot add non-XFB layout to redeclared block member", member->type->getFieldName().c_str(), "");
+ if (newType.getQualifier().patch)
+ error(memberLoc, "cannot add patch to redeclared block member", member->type->getFieldName().c_str(), "");
+ if (newType.getQualifier().hasXfbBuffer() &&
+ newType.getQualifier().layoutXfbBuffer != currentBlockQualifier.layoutXfbBuffer)
+ error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", "");
+ if (newType.getQualifier().hasStream() &&
+ newType.getQualifier().layoutStream != currentBlockQualifier.layoutStream)
+ error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_stream", "");
+ oldType.getQualifier().centroid = newType.getQualifier().centroid;
+ oldType.getQualifier().sample = newType.getQualifier().sample;
+ oldType.getQualifier().invariant = newType.getQualifier().invariant;
+ oldType.getQualifier().noContraction = newType.getQualifier().noContraction;
+ oldType.getQualifier().smooth = newType.getQualifier().smooth;
+ oldType.getQualifier().flat = newType.getQualifier().flat;
+ oldType.getQualifier().nopersp = newType.getQualifier().nopersp;
+ oldType.getQualifier().layoutXfbOffset = newType.getQualifier().layoutXfbOffset;
+ oldType.getQualifier().layoutXfbBuffer = newType.getQualifier().layoutXfbBuffer;
+ oldType.getQualifier().layoutXfbStride = newType.getQualifier().layoutXfbStride;
+ if (oldType.getQualifier().layoutXfbOffset != TQualifier::layoutXfbBufferEnd) {
+ // If any member has an xfb_offset, then the block's xfb_buffer inherents current xfb_buffer,
+ // and for xfb processing, the member needs it as well, along with xfb_stride.
+ type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer;
+ oldType.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer;
+ }
+ if (oldType.isUnsizedArray() && newType.isSizedArray())
+ oldType.changeOuterArraySize(newType.getOuterArraySize());
+
+ // check and process the member's type, which will include managing xfb information
+ layoutTypeCheck(loc, oldType);
+
+ // go to next member
+ ++member;
+ } else {
+ // For missing members of anonymous blocks that have been redeclared,
+ // hide the original (shared) declaration.
+ // Instance-named blocks can just have the member removed.
+ if (instanceName)
+ member = type.getWritableStruct()->erase(member);
+ else {
+ member->type->hideMember();
+ ++member;
+ }
+ }
+ }
+
+ if (spvVersion.vulkan > 0) {
+ // ...then streams apply to built-in blocks, instead of them being only on stream 0
+ type.getQualifier().layoutStream = currentBlockQualifier.layoutStream;
+ }
+
+ if (numOriginalMembersFound < newTypeList.size())
+ error(loc, "block redeclaration has extra members", blockName.c_str(), "");
+ if (type.isArray() != (arraySizes != nullptr) ||
+ (type.isArray() && arraySizes != nullptr && type.getArraySizes()->getNumDims() != arraySizes->getNumDims()))
+ error(loc, "cannot change arrayness of redeclared block", blockName.c_str(), "");
+ else if (type.isArray()) {
+ // At this point, we know both are arrays and both have the same number of dimensions.
+
+ // It is okay for a built-in block redeclaration to be unsized, and keep the size of the
+ // original block declaration.
+ if (!arraySizes->isSized() && type.isSizedArray())
+ arraySizes->changeOuterSize(type.getOuterArraySize());
+
+ // And, okay to be giving a size to the array, by the redeclaration
+ if (!type.isSizedArray() && arraySizes->isSized())
+ type.changeOuterArraySize(arraySizes->getOuterSize());
+
+ // Now, they must match in all dimensions.
+ if (type.isSizedArray() && *type.getArraySizes() != *arraySizes)
+ error(loc, "cannot change array size of redeclared block", blockName.c_str(), "");
+ }
+
+ symbolTable.insert(*block);
+
+ // Check for general layout qualifier errors
+ layoutObjectCheck(loc, *block);
+
+ // Tracking for implicit sizing of array
+ if (isIoResizeArray(block->getType())) {
+ ioArraySymbolResizeList.push_back(block);
+ checkIoArraysConsistency(loc, true);
+ } else if (block->getType().isArray())
+ fixIoArraySize(loc, block->getWritableType());
+
+ // Save it in the AST for linker use.
+ trackLinkage(*block);
+#endif // GLSLANG_WEB
+}
+
+void TParseContext::paramCheckFixStorage(const TSourceLoc& loc, const TStorageQualifier& qualifier, TType& type)
+{
+ switch (qualifier) {
+ case EvqConst:
+ case EvqConstReadOnly:
+ type.getQualifier().storage = EvqConstReadOnly;
+ break;
+ case EvqIn:
+ case EvqOut:
+ case EvqInOut:
+ type.getQualifier().storage = qualifier;
+ break;
+ case EvqGlobal:
+ case EvqTemporary:
+ type.getQualifier().storage = EvqIn;
+ break;
+ default:
+ type.getQualifier().storage = EvqIn;
+ error(loc, "storage qualifier not allowed on function parameter", GetStorageQualifierString(qualifier), "");
+ break;
+ }
+}
+
+void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& qualifier, TType& type)
+{
+#ifndef GLSLANG_WEB
+ if (qualifier.isMemory()) {
+ type.getQualifier().volatil = qualifier.volatil;
+ type.getQualifier().coherent = qualifier.coherent;
+ type.getQualifier().devicecoherent = qualifier.devicecoherent ;
+ type.getQualifier().queuefamilycoherent = qualifier.queuefamilycoherent;
+ type.getQualifier().workgroupcoherent = qualifier.workgroupcoherent;
+ type.getQualifier().subgroupcoherent = qualifier.subgroupcoherent;
+ type.getQualifier().nonprivate = qualifier.nonprivate;
+ type.getQualifier().readonly = qualifier.readonly;
+ type.getQualifier().writeonly = qualifier.writeonly;
+ type.getQualifier().restrict = qualifier.restrict;
+ }
+#endif
+
+ if (qualifier.isAuxiliary() ||
+ qualifier.isInterpolation())
+ error(loc, "cannot use auxiliary or interpolation qualifiers on a function parameter", "", "");
+ if (qualifier.hasLayout())
+ error(loc, "cannot use layout qualifiers on a function parameter", "", "");
+ if (qualifier.invariant)
+ error(loc, "cannot use invariant qualifier on a function parameter", "", "");
+ if (qualifier.isNoContraction()) {
+ if (qualifier.isParamOutput())
+ type.getQualifier().setNoContraction();
+ else
+ warn(loc, "qualifier has no effect on non-output parameters", "precise", "");
+ }
+ if (qualifier.isNonUniform())
+ type.getQualifier().nonUniform = qualifier.nonUniform;
+
+ paramCheckFixStorage(loc, qualifier.storage, type);
+}
+
+void TParseContext::nestedBlockCheck(const TSourceLoc& loc)
+{
+ if (structNestingLevel > 0)
+ error(loc, "cannot nest a block definition inside a structure or block", "", "");
+ ++structNestingLevel;
+}
+
+void TParseContext::nestedStructCheck(const TSourceLoc& loc)
+{
+ if (structNestingLevel > 0)
+ error(loc, "cannot nest a structure definition inside a structure or block", "", "");
+ ++structNestingLevel;
+}
+
+void TParseContext::arrayObjectCheck(const TSourceLoc& loc, const TType& type, const char* op)
+{
+ // Some versions don't allow comparing arrays or structures containing arrays
+ if (type.containsArray()) {
+ profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, op);
+ profileRequires(loc, EEsProfile, 300, nullptr, op);
+ }
+}
+
+void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const char* op)
+{
+ if (containsFieldWithBasicType(type, EbtSampler))
+ error(loc, "can't use with samplers or structs containing samplers", op, "");
+}
+
+void TParseContext::referenceCheck(const TSourceLoc& loc, const TType& type, const char* op)
+{
+#ifndef GLSLANG_WEB
+ if (containsFieldWithBasicType(type, EbtReference))
+ error(loc, "can't use with reference types", op, "");
+#endif
+}
+
+void TParseContext::storage16BitAssignmentCheck(const TSourceLoc& loc, const TType& type, const char* op)
+{
+#ifndef GLSLANG_WEB
+ if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtFloat16))
+ requireFloat16Arithmetic(loc, op, "can't use with structs containing float16");
+
+ if (type.isArray() && type.getBasicType() == EbtFloat16)
+ requireFloat16Arithmetic(loc, op, "can't use with arrays containing float16");
+
+ if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtInt16))
+ requireInt16Arithmetic(loc, op, "can't use with structs containing int16");
+
+ if (type.isArray() && type.getBasicType() == EbtInt16)
+ requireInt16Arithmetic(loc, op, "can't use with arrays containing int16");
+
+ if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtUint16))
+ requireInt16Arithmetic(loc, op, "can't use with structs containing uint16");
+
+ if (type.isArray() && type.getBasicType() == EbtUint16)
+ requireInt16Arithmetic(loc, op, "can't use with arrays containing uint16");
+
+ if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtInt8))
+ requireInt8Arithmetic(loc, op, "can't use with structs containing int8");
+
+ if (type.isArray() && type.getBasicType() == EbtInt8)
+ requireInt8Arithmetic(loc, op, "can't use with arrays containing int8");
+
+ if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtUint8))
+ requireInt8Arithmetic(loc, op, "can't use with structs containing uint8");
+
+ if (type.isArray() && type.getBasicType() == EbtUint8)
+ requireInt8Arithmetic(loc, op, "can't use with arrays containing uint8");
+#endif
+}
+
+void TParseContext::specializationCheck(const TSourceLoc& loc, const TType& type, const char* op)
+{
+ if (type.containsSpecializationSize())
+ error(loc, "can't use with types containing arrays sized with a specialization constant", op, "");
+}
+
+void TParseContext::structTypeCheck(const TSourceLoc& /*loc*/, TPublicType& publicType)
+{
+ const TTypeList& typeList = *publicType.userDef->getStruct();
+
+ // fix and check for member storage qualifiers and types that don't belong within a structure
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ const TSourceLoc& memberLoc = typeList[member].loc;
+ if (memberQualifier.isAuxiliary() ||
+ memberQualifier.isInterpolation() ||
+ (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal))
+ error(memberLoc, "cannot use storage or interpolation qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
+ if (memberQualifier.isMemory())
+ error(memberLoc, "cannot use memory qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
+ if (memberQualifier.hasLayout()) {
+ error(memberLoc, "cannot use layout qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
+ memberQualifier.clearLayout();
+ }
+ if (memberQualifier.invariant)
+ error(memberLoc, "cannot use invariant qualifier on structure members", typeList[member].type->getFieldName().c_str(), "");
+ }
+}
+
+//
+// See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A:
+//
+// "The loop index has type int or float.
+//
+// "The for statement has the form:
+// for ( init-declaration ; condition ; expression )
+// init-declaration has the form: type-specifier identifier = constant-expression
+// condition has the form: loop-index relational_operator constant-expression
+// where relational_operator is one of: > >= < <= == or !=
+// expression [sic] has one of the following forms:
+// loop-index++
+// loop-index--
+// loop-index += constant-expression
+// loop-index -= constant-expression
+//
+// The body is handled in an AST traversal.
+//
+void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init, TIntermLoop* loop)
+{
+#ifndef GLSLANG_WEB
+ // loop index init must exist and be a declaration, which shows up in the AST as an aggregate of size 1 of the declaration
+ bool badInit = false;
+ if (! init || ! init->getAsAggregate() || init->getAsAggregate()->getSequence().size() != 1)
+ badInit = true;
+ TIntermBinary* binaryInit = 0;
+ if (! badInit) {
+ // get the declaration assignment
+ binaryInit = init->getAsAggregate()->getSequence()[0]->getAsBinaryNode();
+ if (! binaryInit)
+ badInit = true;
+ }
+ if (badInit) {
+ error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", "");
+ return;
+ }
+
+ // loop index must be type int or float
+ if (! binaryInit->getType().isScalar() || (binaryInit->getBasicType() != EbtInt && binaryInit->getBasicType() != EbtFloat)) {
+ error(loc, "inductive loop requires a scalar 'int' or 'float' loop index", "limitations", "");
+ return;
+ }
+
+ // init is the form "loop-index = constant"
+ if (binaryInit->getOp() != EOpAssign || ! binaryInit->getLeft()->getAsSymbolNode() || ! binaryInit->getRight()->getAsConstantUnion()) {
+ error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", "");
+ return;
+ }
+
+ // get the unique id of the loop index
+ int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId();
+ inductiveLoopIds.insert(loopIndex);
+
+ // condition's form must be "loop-index relational-operator constant-expression"
+ bool badCond = ! loop->getTest();
+ if (! badCond) {
+ TIntermBinary* binaryCond = loop->getTest()->getAsBinaryNode();
+ badCond = ! binaryCond;
+ if (! badCond) {
+ switch (binaryCond->getOp()) {
+ case EOpGreaterThan:
+ case EOpGreaterThanEqual:
+ case EOpLessThan:
+ case EOpLessThanEqual:
+ case EOpEqual:
+ case EOpNotEqual:
+ break;
+ default:
+ badCond = true;
+ }
+ }
+ if (binaryCond && (! binaryCond->getLeft()->getAsSymbolNode() ||
+ binaryCond->getLeft()->getAsSymbolNode()->getId() != loopIndex ||
+ ! binaryCond->getRight()->getAsConstantUnion()))
+ badCond = true;
+ }
+ if (badCond) {
+ error(loc, "inductive-loop condition requires the form \"loop-index <comparison-op> constant-expression\"", "limitations", "");
+ return;
+ }
+
+ // loop-index++
+ // loop-index--
+ // loop-index += constant-expression
+ // loop-index -= constant-expression
+ bool badTerminal = ! loop->getTerminal();
+ if (! badTerminal) {
+ TIntermUnary* unaryTerminal = loop->getTerminal()->getAsUnaryNode();
+ TIntermBinary* binaryTerminal = loop->getTerminal()->getAsBinaryNode();
+ if (unaryTerminal || binaryTerminal) {
+ switch(loop->getTerminal()->getAsOperator()->getOp()) {
+ case EOpPostDecrement:
+ case EOpPostIncrement:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ break;
+ default:
+ badTerminal = true;
+ }
+ } else
+ badTerminal = true;
+ if (binaryTerminal && (! binaryTerminal->getLeft()->getAsSymbolNode() ||
+ binaryTerminal->getLeft()->getAsSymbolNode()->getId() != loopIndex ||
+ ! binaryTerminal->getRight()->getAsConstantUnion()))
+ badTerminal = true;
+ if (unaryTerminal && (! unaryTerminal->getOperand()->getAsSymbolNode() ||
+ unaryTerminal->getOperand()->getAsSymbolNode()->getId() != loopIndex))
+ badTerminal = true;
+ }
+ if (badTerminal) {
+ error(loc, "inductive-loop termination requires the form \"loop-index++, loop-index--, loop-index += constant-expression, or loop-index -= constant-expression\"", "limitations", "");
+ return;
+ }
+
+ // the body
+ inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable);
+#endif
+}
+
+#ifndef GLSLANG_WEB
+// Do limit checks for built-in arrays.
+void TParseContext::arrayLimitCheck(const TSourceLoc& loc, const TString& identifier, int size)
+{
+ if (identifier.compare("gl_TexCoord") == 0)
+ limitCheck(loc, size, "gl_MaxTextureCoords", "gl_TexCoord array size");
+ else if (identifier.compare("gl_ClipDistance") == 0)
+ limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistance array size");
+ else if (identifier.compare("gl_CullDistance") == 0)
+ limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistance array size");
+ else if (identifier.compare("gl_ClipDistancePerViewNV") == 0)
+ limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistancePerViewNV array size");
+ else if (identifier.compare("gl_CullDistancePerViewNV") == 0)
+ limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistancePerViewNV array size");
+}
+#endif // GLSLANG_WEB
+
+// See if the provided value is less than or equal to the symbol indicated by limit,
+// which should be a constant in the symbol table.
+void TParseContext::limitCheck(const TSourceLoc& loc, int value, const char* limit, const char* feature)
+{
+ TSymbol* symbol = symbolTable.find(limit);
+ assert(symbol->getAsVariable());
+ const TConstUnionArray& constArray = symbol->getAsVariable()->getConstArray();
+ assert(! constArray.empty());
+ if (value > constArray[0].getIConst())
+ error(loc, "must be less than or equal to", feature, "%s (%d)", limit, constArray[0].getIConst());
+}
+
+#ifndef GLSLANG_WEB
+
+//
+// Do any additional error checking, etc., once we know the parsing is done.
+//
+void TParseContext::finish()
+{
+ TParseContextBase::finish();
+
+ if (parsingBuiltins)
+ return;
+
+ // Check on array indexes for ES 2.0 (version 100) limitations.
+ for (size_t i = 0; i < needsIndexLimitationChecking.size(); ++i)
+ constantIndexExpressionCheck(needsIndexLimitationChecking[i]);
+
+ // Check for stages that are enabled by extension.
+ // Can't do this at the beginning, it is chicken and egg to add a stage by
+ // extension.
+ // Stage-specific features were correctly tested for already, this is just
+ // about the stage itself.
+ switch (language) {
+ case EShLangGeometry:
+ if (isEsProfile() && version == 310)
+ requireExtensions(getCurrentLoc(), Num_AEP_geometry_shader, AEP_geometry_shader, "geometry shaders");
+ break;
+ case EShLangTessControl:
+ case EShLangTessEvaluation:
+ if (isEsProfile() && version == 310)
+ requireExtensions(getCurrentLoc(), Num_AEP_tessellation_shader, AEP_tessellation_shader, "tessellation shaders");
+ else if (!isEsProfile() && version < 400)
+ requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_tessellation_shader, "tessellation shaders");
+ break;
+ case EShLangCompute:
+ if (!isEsProfile() && version < 430)
+ requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_compute_shader, "compute shaders");
+ break;
+ case EShLangTaskNV:
+ requireExtensions(getCurrentLoc(), 1, &E_GL_NV_mesh_shader, "task shaders");
+ break;
+ case EShLangMeshNV:
+ requireExtensions(getCurrentLoc(), 1, &E_GL_NV_mesh_shader, "mesh shaders");
+ break;
+ default:
+ break;
+ }
+
+ // Set default outputs for GL_NV_geometry_shader_passthrough
+ if (language == EShLangGeometry && extensionTurnedOn(E_SPV_NV_geometry_shader_passthrough)) {
+ if (intermediate.getOutputPrimitive() == ElgNone) {
+ switch (intermediate.getInputPrimitive()) {
+ case ElgPoints: intermediate.setOutputPrimitive(ElgPoints); break;
+ case ElgLines: intermediate.setOutputPrimitive(ElgLineStrip); break;
+ case ElgTriangles: intermediate.setOutputPrimitive(ElgTriangleStrip); break;
+ default: break;
+ }
+ }
+ if (intermediate.getVertices() == TQualifier::layoutNotSet) {
+ switch (intermediate.getInputPrimitive()) {
+ case ElgPoints: intermediate.setVertices(1); break;
+ case ElgLines: intermediate.setVertices(2); break;
+ case ElgTriangles: intermediate.setVertices(3); break;
+ default: break;
+ }
+ }
+ }
+}
+#endif // GLSLANG_WEB
+
+//
+// Layout qualifier stuff.
+//
+
+// Put the id's layout qualification into the public type, for qualifiers not having a number set.
+// This is before we know any type information for error checking.
+void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id)
+{
+ std::transform(id.begin(), id.end(), id.begin(), ::tolower);
+
+ if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) {
+ publicType.qualifier.layoutMatrix = ElmColumnMajor;
+ return;
+ }
+ if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) {
+ publicType.qualifier.layoutMatrix = ElmRowMajor;
+ return;
+ }
+ if (id == TQualifier::getLayoutPackingString(ElpPacked)) {
+ if (spvVersion.spv != 0)
+ spvRemoved(loc, "packed");
+ publicType.qualifier.layoutPacking = ElpPacked;
+ return;
+ }
+ if (id == TQualifier::getLayoutPackingString(ElpShared)) {
+ if (spvVersion.spv != 0)
+ spvRemoved(loc, "shared");
+ publicType.qualifier.layoutPacking = ElpShared;
+ return;
+ }
+ if (id == TQualifier::getLayoutPackingString(ElpStd140)) {
+ publicType.qualifier.layoutPacking = ElpStd140;
+ return;
+ }
+#ifndef GLSLANG_WEB
+ if (id == TQualifier::getLayoutPackingString(ElpStd430)) {
+ requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "std430");
+ profileRequires(loc, EEsProfile, 310, nullptr, "std430");
+ publicType.qualifier.layoutPacking = ElpStd430;
+ return;
+ }
+ if (id == TQualifier::getLayoutPackingString(ElpScalar)) {
+ requireVulkan(loc, "scalar");
+ requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "scalar block layout");
+ publicType.qualifier.layoutPacking = ElpScalar;
+ return;
+ }
+ // TODO: compile-time performance: may need to stop doing linear searches
+ for (TLayoutFormat format = (TLayoutFormat)(ElfNone + 1); format < ElfCount; format = (TLayoutFormat)(format + 1)) {
+ if (id == TQualifier::getLayoutFormatString(format)) {
+ if ((format > ElfEsFloatGuard && format < ElfFloatGuard) ||
+ (format > ElfEsIntGuard && format < ElfIntGuard) ||
+ (format > ElfEsUintGuard && format < ElfCount))
+ requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load-store format");
+ profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "image load store");
+ profileRequires(loc, EEsProfile, 310, E_GL_ARB_shader_image_load_store, "image load store");
+ publicType.qualifier.layoutFormat = format;
+ return;
+ }
+ }
+ if (id == "push_constant") {
+ requireVulkan(loc, "push_constant");
+ publicType.qualifier.layoutPushConstant = true;
+ return;
+ }
+ if (id == "buffer_reference") {
+ requireVulkan(loc, "buffer_reference");
+ requireExtensions(loc, 1, &E_GL_EXT_buffer_reference, "buffer_reference");
+ publicType.qualifier.layoutBufferReference = true;
+ intermediate.setUseStorageBuffer();
+ intermediate.setUsePhysicalStorageBuffer();
+ return;
+ }
+ if (language == EShLangGeometry || language == EShLangTessEvaluation || language == EShLangMeshNV) {
+ if (id == TQualifier::getGeometryString(ElgTriangles)) {
+ publicType.shaderQualifiers.geometry = ElgTriangles;
+ return;
+ }
+ if (language == EShLangGeometry || language == EShLangMeshNV) {
+ if (id == TQualifier::getGeometryString(ElgPoints)) {
+ publicType.shaderQualifiers.geometry = ElgPoints;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgLines)) {
+ publicType.shaderQualifiers.geometry = ElgLines;
+ return;
+ }
+ if (language == EShLangGeometry) {
+ if (id == TQualifier::getGeometryString(ElgLineStrip)) {
+ publicType.shaderQualifiers.geometry = ElgLineStrip;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) {
+ publicType.shaderQualifiers.geometry = ElgLinesAdjacency;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) {
+ publicType.shaderQualifiers.geometry = ElgTrianglesAdjacency;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgTriangleStrip)) {
+ publicType.shaderQualifiers.geometry = ElgTriangleStrip;
+ return;
+ }
+ if (id == "passthrough") {
+ requireExtensions(loc, 1, &E_SPV_NV_geometry_shader_passthrough, "geometry shader passthrough");
+ publicType.qualifier.layoutPassthrough = true;
+ intermediate.setGeoPassthroughEXT();
+ return;
+ }
+ }
+ } else {
+ assert(language == EShLangTessEvaluation);
+
+ // input primitive
+ if (id == TQualifier::getGeometryString(ElgTriangles)) {
+ publicType.shaderQualifiers.geometry = ElgTriangles;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgQuads)) {
+ publicType.shaderQualifiers.geometry = ElgQuads;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgIsolines)) {
+ publicType.shaderQualifiers.geometry = ElgIsolines;
+ return;
+ }
+
+ // vertex spacing
+ if (id == TQualifier::getVertexSpacingString(EvsEqual)) {
+ publicType.shaderQualifiers.spacing = EvsEqual;
+ return;
+ }
+ if (id == TQualifier::getVertexSpacingString(EvsFractionalEven)) {
+ publicType.shaderQualifiers.spacing = EvsFractionalEven;
+ return;
+ }
+ if (id == TQualifier::getVertexSpacingString(EvsFractionalOdd)) {
+ publicType.shaderQualifiers.spacing = EvsFractionalOdd;
+ return;
+ }
+
+ // triangle order
+ if (id == TQualifier::getVertexOrderString(EvoCw)) {
+ publicType.shaderQualifiers.order = EvoCw;
+ return;
+ }
+ if (id == TQualifier::getVertexOrderString(EvoCcw)) {
+ publicType.shaderQualifiers.order = EvoCcw;
+ return;
+ }
+
+ // point mode
+ if (id == "point_mode") {
+ publicType.shaderQualifiers.pointMode = true;
+ return;
+ }
+ }
+ }
+ if (language == EShLangFragment) {
+ if (id == "origin_upper_left") {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "origin_upper_left");
+ publicType.shaderQualifiers.originUpperLeft = true;
+ return;
+ }
+ if (id == "pixel_center_integer") {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "pixel_center_integer");
+ publicType.shaderQualifiers.pixelCenterInteger = true;
+ return;
+ }
+ if (id == "early_fragment_tests") {
+ profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "early_fragment_tests");
+ profileRequires(loc, EEsProfile, 310, nullptr, "early_fragment_tests");
+ publicType.shaderQualifiers.earlyFragmentTests = true;
+ return;
+ }
+ if (id == "post_depth_coverage") {
+ requireExtensions(loc, Num_post_depth_coverageEXTs, post_depth_coverageEXTs, "post depth coverage");
+ if (extensionTurnedOn(E_GL_ARB_post_depth_coverage)) {
+ publicType.shaderQualifiers.earlyFragmentTests = true;
+ }
+ publicType.shaderQualifiers.postDepthCoverage = true;
+ return;
+ }
+ for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth+1)) {
+ if (id == TQualifier::getLayoutDepthString(depth)) {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "depth layout qualifier");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, nullptr, "depth layout qualifier");
+ publicType.shaderQualifiers.layoutDepth = depth;
+ return;
+ }
+ }
+ for (TInterlockOrdering order = (TInterlockOrdering)(EioNone + 1); order < EioCount; order = (TInterlockOrdering)(order+1)) {
+ if (id == TQualifier::getInterlockOrderingString(order)) {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "fragment shader interlock layout qualifier");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 450, nullptr, "fragment shader interlock layout qualifier");
+ requireExtensions(loc, 1, &E_GL_ARB_fragment_shader_interlock, TQualifier::getInterlockOrderingString(order));
+ if (order == EioShadingRateInterlockOrdered || order == EioShadingRateInterlockUnordered)
+ requireExtensions(loc, 1, &E_GL_NV_shading_rate_image, TQualifier::getInterlockOrderingString(order));
+ publicType.shaderQualifiers.interlockOrdering = order;
+ return;
+ }
+ }
+ if (id.compare(0, 13, "blend_support") == 0) {
+ bool found = false;
+ for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
+ if (id == TQualifier::getBlendEquationString(be)) {
+ profileRequires(loc, EEsProfile, 320, E_GL_KHR_blend_equation_advanced, "blend equation");
+ profileRequires(loc, ~EEsProfile, 0, E_GL_KHR_blend_equation_advanced, "blend equation");
+ intermediate.addBlendEquation(be);
+ publicType.shaderQualifiers.blendEquation = true;
+ found = true;
+ break;
+ }
+ }
+ if (! found)
+ error(loc, "unknown blend equation", "blend_support", "");
+ return;
+ }
+ if (id == "override_coverage") {
+ requireExtensions(loc, 1, &E_GL_NV_sample_mask_override_coverage, "sample mask override coverage");
+ publicType.shaderQualifiers.layoutOverrideCoverage = true;
+ return;
+ }
+ }
+ if (language == EShLangVertex ||
+ language == EShLangTessControl ||
+ language == EShLangTessEvaluation ||
+ language == EShLangGeometry ) {
+ if (id == "viewport_relative") {
+ requireExtensions(loc, 1, &E_GL_NV_viewport_array2, "view port array2");
+ publicType.qualifier.layoutViewportRelative = true;
+ return;
+ }
+ } else {
+ if (language == EShLangRayGenNV || language == EShLangIntersectNV ||
+ language == EShLangAnyHitNV || language == EShLangClosestHitNV ||
+ language == EShLangMissNV || language == EShLangCallableNV) {
+ if (id == "shaderrecordnv") {
+ publicType.qualifier.layoutShaderRecordNV = true;
+ return;
+ }
+ }
+ }
+ if (language == EShLangCompute) {
+ if (id.compare(0, 17, "derivative_group_") == 0) {
+ requireExtensions(loc, 1, &E_GL_NV_compute_shader_derivatives, "compute shader derivatives");
+ if (id == "derivative_group_quadsnv") {
+ publicType.shaderQualifiers.layoutDerivativeGroupQuads = true;
+ return;
+ } else if (id == "derivative_group_linearnv") {
+ publicType.shaderQualifiers.layoutDerivativeGroupLinear = true;
+ return;
+ }
+ }
+ }
+#endif
+
+ error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
+}
+
+// Put the id's layout qualifier value into the public type, for qualifiers having a number set.
+// This is before we know any type information for error checking.
+void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id, const TIntermTyped* node)
+{
+ const char* feature = "layout-id value";
+ const char* nonLiteralFeature = "non-literal layout-id value";
+
+ integerCheck(node, feature);
+ const TIntermConstantUnion* constUnion = node->getAsConstantUnion();
+ int value;
+ bool nonLiteral = false;
+ if (constUnion) {
+ value = constUnion->getConstArray()[0].getIConst();
+ if (! constUnion->isLiteral()) {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, nonLiteralFeature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, nonLiteralFeature);
+ }
+ } else {
+ // grammar should have give out the error message
+ value = 0;
+ nonLiteral = true;
+ }
+
+ if (value < 0) {
+ error(loc, "cannot be negative", feature, "");
+ return;
+ }
+
+ std::transform(id.begin(), id.end(), id.begin(), ::tolower);
+
+ if (id == "offset") {
+ // "offset" can be for either
+ // - uniform offsets
+ // - atomic_uint offsets
+ const char* feature = "offset";
+ if (spvVersion.spv == 0) {
+ requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
+ const char* exts[2] = { E_GL_ARB_enhanced_layouts, E_GL_ARB_shader_atomic_counters };
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, 2, exts, feature);
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ }
+ publicType.qualifier.layoutOffset = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "offset", "");
+ return;
+ } else if (id == "align") {
+ const char* feature = "uniform buffer-member align";
+ if (spvVersion.spv == 0) {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
+ }
+ // "The specified alignment must be a power of 2, or a compile-time error results."
+ if (! IsPow2(value))
+ error(loc, "must be a power of 2", "align", "");
+ else
+ publicType.qualifier.layoutAlign = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "align", "");
+ return;
+ } else if (id == "location") {
+ profileRequires(loc, EEsProfile, 300, nullptr, "location");
+ const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
+ // GL_ARB_explicit_uniform_location requires 330 or GL_ARB_explicit_attrib_location we do not need to add it here
+ profileRequires(loc, ~EEsProfile, 330, 2, exts, "location");
+ if ((unsigned int)value >= TQualifier::layoutLocationEnd)
+ error(loc, "location is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutLocation = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "location", "");
+ return;
+ } else if (id == "set") {
+ if ((unsigned int)value >= TQualifier::layoutSetEnd)
+ error(loc, "set is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutSet = value;
+ if (value != 0)
+ requireVulkan(loc, "descriptor set");
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "set", "");
+ return;
+ } else if (id == "binding") {
+#ifndef GLSLANG_WEB
+ profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, "binding");
+ profileRequires(loc, EEsProfile, 310, nullptr, "binding");
+#endif
+ if ((unsigned int)value >= TQualifier::layoutBindingEnd)
+ error(loc, "binding is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutBinding = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "binding", "");
+ return;
+ }
+ if (id == "constant_id") {
+ requireSpv(loc, "constant_id");
+ if (value >= (int)TQualifier::layoutSpecConstantIdEnd) {
+ error(loc, "specialization-constant id is too large", id.c_str(), "");
+ } else {
+ publicType.qualifier.layoutSpecConstantId = value;
+ publicType.qualifier.specConstant = true;
+ if (! intermediate.addUsedConstantId(value))
+ error(loc, "specialization-constant id already used", id.c_str(), "");
+ }
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "constant_id", "");
+ return;
+ }
+#ifndef GLSLANG_WEB
+ if (id == "component") {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "component");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "component");
+ if ((unsigned)value >= TQualifier::layoutComponentEnd)
+ error(loc, "component is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutComponent = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "component", "");
+ return;
+ }
+ if (id.compare(0, 4, "xfb_") == 0) {
+ // "Any shader making any static use (after preprocessing) of any of these
+ // *xfb_* qualifiers will cause the shader to be in a transform feedback
+ // capturing mode and hence responsible for describing the transform feedback
+ // setup."
+ intermediate.setXfbMode();
+ const char* feature = "transform feedback qualifier";
+ requireStage(loc, (EShLanguageMask)(EShLangVertexMask | EShLangGeometryMask | EShLangTessControlMask | EShLangTessEvaluationMask), feature);
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
+ if (id == "xfb_buffer") {
+ // "It is a compile-time error to specify an *xfb_buffer* that is greater than
+ // the implementation-dependent constant gl_MaxTransformFeedbackBuffers."
+ if (value >= resources.maxTransformFeedbackBuffers)
+ error(loc, "buffer is too large:", id.c_str(), "gl_MaxTransformFeedbackBuffers is %d", resources.maxTransformFeedbackBuffers);
+ if (value >= (int)TQualifier::layoutXfbBufferEnd)
+ error(loc, "buffer is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbBufferEnd-1);
+ else
+ publicType.qualifier.layoutXfbBuffer = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "xfb_buffer", "");
+ return;
+ } else if (id == "xfb_offset") {
+ if (value >= (int)TQualifier::layoutXfbOffsetEnd)
+ error(loc, "offset is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbOffsetEnd-1);
+ else
+ publicType.qualifier.layoutXfbOffset = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "xfb_offset", "");
+ return;
+ } else if (id == "xfb_stride") {
+ // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the
+ // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents."
+ if (value > 4 * resources.maxTransformFeedbackInterleavedComponents) {
+ error(loc, "1/4 stride is too large:", id.c_str(), "gl_MaxTransformFeedbackInterleavedComponents is %d",
+ resources.maxTransformFeedbackInterleavedComponents);
+ }
+ if (value >= (int)TQualifier::layoutXfbStrideEnd)
+ error(loc, "stride is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbStrideEnd-1);
+ else
+ publicType.qualifier.layoutXfbStride = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "xfb_stride", "");
+ return;
+ }
+ }
+ if (id == "input_attachment_index") {
+ requireVulkan(loc, "input_attachment_index");
+ if (value >= (int)TQualifier::layoutAttachmentEnd)
+ error(loc, "attachment index is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutAttachment = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "input_attachment_index", "");
+ return;
+ }
+ if (id == "num_views") {
+ requireExtensions(loc, Num_OVR_multiview_EXTs, OVR_multiview_EXTs, "num_views");
+ publicType.shaderQualifiers.numViews = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "num_views", "");
+ return;
+ }
+ if (language == EShLangVertex ||
+ language == EShLangTessControl ||
+ language == EShLangTessEvaluation ||
+ language == EShLangGeometry) {
+ if (id == "secondary_view_offset") {
+ requireExtensions(loc, 1, &E_GL_NV_stereo_view_rendering, "stereo view rendering");
+ publicType.qualifier.layoutSecondaryViewportRelativeOffset = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "secondary_view_offset", "");
+ return;
+ }
+ }
+
+ if (id == "buffer_reference_align") {
+ requireExtensions(loc, 1, &E_GL_EXT_buffer_reference, "buffer_reference_align");
+ if (! IsPow2(value))
+ error(loc, "must be a power of 2", "buffer_reference_align", "");
+ else
+ publicType.qualifier.layoutBufferReferenceAlign = (unsigned int)std::log2(value);
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "buffer_reference_align", "");
+ return;
+ }
+#endif
+
+ switch (language) {
+#ifndef GLSLANG_WEB
+ case EShLangTessControl:
+ if (id == "vertices") {
+ if (value == 0)
+ error(loc, "must be greater than 0", "vertices", "");
+ else
+ publicType.shaderQualifiers.vertices = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "vertices", "");
+ return;
+ }
+ break;
+
+ case EShLangGeometry:
+ if (id == "invocations") {
+ profileRequires(loc, ECompatibilityProfile | ECoreProfile, 400, nullptr, "invocations");
+ if (value == 0)
+ error(loc, "must be at least 1", "invocations", "");
+ else
+ publicType.shaderQualifiers.invocations = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "invocations", "");
+ return;
+ }
+ if (id == "max_vertices") {
+ publicType.shaderQualifiers.vertices = value;
+ if (value > resources.maxGeometryOutputVertices)
+ error(loc, "too large, must be less than gl_MaxGeometryOutputVertices", "max_vertices", "");
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "max_vertices", "");
+ return;
+ }
+ if (id == "stream") {
+ requireProfile(loc, ~EEsProfile, "selecting output stream");
+ publicType.qualifier.layoutStream = value;
+ if (value > 0)
+ intermediate.setMultiStream();
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "stream", "");
+ return;
+ }
+ break;
+
+ case EShLangFragment:
+ if (id == "index") {
+ requireProfile(loc, ECompatibilityProfile | ECoreProfile, "index layout qualifier on fragment output");
+ const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
+ profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output");
+
+ // "It is also a compile-time error if a fragment shader sets a layout index to less than 0 or greater than 1."
+ if (value < 0 || value > 1) {
+ value = 0;
+ error(loc, "value must be 0 or 1", "index", "");
+ }
+
+ publicType.qualifier.layoutIndex = value;
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "index", "");
+ return;
+ }
+ break;
+
+ case EShLangMeshNV:
+ if (id == "max_vertices") {
+ requireExtensions(loc, 1, &E_GL_NV_mesh_shader, "max_vertices");
+ publicType.shaderQualifiers.vertices = value;
+ if (value > resources.maxMeshOutputVerticesNV)
+ error(loc, "too large, must be less than gl_MaxMeshOutputVerticesNV", "max_vertices", "");
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "max_vertices", "");
+ return;
+ }
+ if (id == "max_primitives") {
+ requireExtensions(loc, 1, &E_GL_NV_mesh_shader, "max_primitives");
+ publicType.shaderQualifiers.primitives = value;
+ if (value > resources.maxMeshOutputPrimitivesNV)
+ error(loc, "too large, must be less than gl_MaxMeshOutputPrimitivesNV", "max_primitives", "");
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "max_primitives", "");
+ return;
+ }
+ // Fall through
+
+ case EShLangTaskNV:
+ // Fall through
+#endif
+ case EShLangCompute:
+ if (id.compare(0, 11, "local_size_") == 0) {
+#ifndef GLSLANG_WEB
+ if (language == EShLangMeshNV || language == EShLangTaskNV) {
+ requireExtensions(loc, 1, &E_GL_NV_mesh_shader, "gl_WorkGroupSize");
+ } else {
+ profileRequires(loc, EEsProfile, 310, 0, "gl_WorkGroupSize");
+ profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_compute_shader, "gl_WorkGroupSize");
+ }
+#endif
+ if (nonLiteral)
+ error(loc, "needs a literal integer", "local_size", "");
+ if (id.size() == 12 && value == 0) {
+ error(loc, "must be at least 1", id.c_str(), "");
+ return;
+ }
+ if (id == "local_size_x") {
+ publicType.shaderQualifiers.localSize[0] = value;
+ publicType.shaderQualifiers.localSizeNotDefault[0] = true;
+ return;
+ }
+ if (id == "local_size_y") {
+ publicType.shaderQualifiers.localSize[1] = value;
+ publicType.shaderQualifiers.localSizeNotDefault[1] = true;
+ return;
+ }
+ if (id == "local_size_z") {
+ publicType.shaderQualifiers.localSize[2] = value;
+ publicType.shaderQualifiers.localSizeNotDefault[2] = true;
+ return;
+ }
+ if (spvVersion.spv != 0) {
+ if (id == "local_size_x_id") {
+ publicType.shaderQualifiers.localSizeSpecId[0] = value;
+ return;
+ }
+ if (id == "local_size_y_id") {
+ publicType.shaderQualifiers.localSizeSpecId[1] = value;
+ return;
+ }
+ if (id == "local_size_z_id") {
+ publicType.shaderQualifiers.localSizeSpecId[2] = value;
+ return;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), "");
+}
+
+// Merge any layout qualifier information from src into dst, leaving everything else in dst alone
+//
+// "More than one layout qualifier may appear in a single declaration.
+// Additionally, the same layout-qualifier-name can occur multiple times
+// within a layout qualifier or across multiple layout qualifiers in the
+// same declaration. When the same layout-qualifier-name occurs
+// multiple times, in a single declaration, the last occurrence overrides
+// the former occurrence(s). Further, if such a layout-qualifier-name
+// will effect subsequent declarations or other observable behavior, it
+// is only the last occurrence that will have any effect, behaving as if
+// the earlier occurrence(s) within the declaration are not present.
+// This is also true for overriding layout-qualifier-names, where one
+// overrides the other (e.g., row_major vs. column_major); only the last
+// occurrence has any effect."
+void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly)
+{
+ if (src.hasMatrix())
+ dst.layoutMatrix = src.layoutMatrix;
+ if (src.hasPacking())
+ dst.layoutPacking = src.layoutPacking;
+
+#ifndef GLSLANG_WEB
+ if (src.hasStream())
+ dst.layoutStream = src.layoutStream;
+ if (src.hasFormat())
+ dst.layoutFormat = src.layoutFormat;
+ if (src.hasXfbBuffer())
+ dst.layoutXfbBuffer = src.layoutXfbBuffer;
+ if (src.hasBufferReferenceAlign())
+ dst.layoutBufferReferenceAlign = src.layoutBufferReferenceAlign;
+#endif
+
+ if (src.hasAlign())
+ dst.layoutAlign = src.layoutAlign;
+
+ if (! inheritOnly) {
+ if (src.hasLocation())
+ dst.layoutLocation = src.layoutLocation;
+ if (src.hasOffset())
+ dst.layoutOffset = src.layoutOffset;
+ if (src.hasSet())
+ dst.layoutSet = src.layoutSet;
+ if (src.layoutBinding != TQualifier::layoutBindingEnd)
+ dst.layoutBinding = src.layoutBinding;
+
+ if (src.hasSpecConstantId())
+ dst.layoutSpecConstantId = src.layoutSpecConstantId;
+
+#ifndef GLSLANG_WEB
+ if (src.hasComponent())
+ dst.layoutComponent = src.layoutComponent;
+ if (src.hasIndex())
+ dst.layoutIndex = src.layoutIndex;
+ if (src.hasXfbStride())
+ dst.layoutXfbStride = src.layoutXfbStride;
+ if (src.hasXfbOffset())
+ dst.layoutXfbOffset = src.layoutXfbOffset;
+ if (src.hasAttachment())
+ dst.layoutAttachment = src.layoutAttachment;
+ if (src.layoutPushConstant)
+ dst.layoutPushConstant = true;
+
+ if (src.layoutBufferReference)
+ dst.layoutBufferReference = true;
+
+ if (src.layoutPassthrough)
+ dst.layoutPassthrough = true;
+ if (src.layoutViewportRelative)
+ dst.layoutViewportRelative = true;
+ if (src.layoutSecondaryViewportRelativeOffset != -2048)
+ dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset;
+ if (src.layoutShaderRecordNV)
+ dst.layoutShaderRecordNV = true;
+ if (src.pervertexNV)
+ dst.pervertexNV = true;
+#endif
+ }
+}
+
+// Do error layout error checking given a full variable/block declaration.
+void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symbol)
+{
+ const TType& type = symbol.getType();
+ const TQualifier& qualifier = type.getQualifier();
+
+ // first, cross check WRT to just the type
+ layoutTypeCheck(loc, type);
+
+ // now, any remaining error checking based on the object itself
+
+ if (qualifier.hasAnyLocation()) {
+ switch (qualifier.storage) {
+ case EvqUniform:
+ case EvqBuffer:
+ if (symbol.getAsVariable() == nullptr)
+ error(loc, "can only be used on variable declaration", "location", "");
+ break;
+ default:
+ break;
+ }
+ }
+
+ // user-variable location check, which are required for SPIR-V in/out:
+ // - variables have it directly,
+ // - blocks have it on each member (already enforced), so check first one
+ if (spvVersion.spv > 0 && !parsingBuiltins && qualifier.builtIn == EbvNone &&
+ !qualifier.hasLocation() && !intermediate.getAutoMapLocations()) {
+
+ switch (qualifier.storage) {
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ if (!type.getQualifier().isTaskMemory() &&
+ (type.getBasicType() != EbtBlock ||
+ (!(*type.getStruct())[0].type->getQualifier().hasLocation() &&
+ (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone)))
+ error(loc, "SPIR-V requires location for user input/output", "location", "");
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Check packing and matrix
+ if (qualifier.hasUniformLayout()) {
+ switch (qualifier.storage) {
+ case EvqUniform:
+ case EvqBuffer:
+ if (type.getBasicType() != EbtBlock) {
+ if (qualifier.hasMatrix())
+ error(loc, "cannot specify matrix layout on a variable declaration", "layout", "");
+ if (qualifier.hasPacking())
+ error(loc, "cannot specify packing on a variable declaration", "layout", "");
+ // "The offset qualifier can only be used on block members of blocks..."
+ if (qualifier.hasOffset() && !type.isAtomic())
+ error(loc, "cannot specify on a variable declaration", "offset", "");
+ // "The align qualifier can only be used on blocks or block members..."
+ if (qualifier.hasAlign())
+ error(loc, "cannot specify on a variable declaration", "align", "");
+ if (qualifier.isPushConstant())
+ error(loc, "can only specify on a uniform block", "push_constant", "");
+ if (qualifier.isShaderRecordNV())
+ error(loc, "can only specify on a buffer block", "shaderRecordNV", "");
+ }
+ break;
+ default:
+ // these were already filtered by layoutTypeCheck() (or its callees)
+ break;
+ }
+ }
+}
+
+// "For some blocks declared as arrays, the location can only be applied at the block level:
+// When a block is declared as an array where additional locations are needed for each member
+// for each block array element, it is a compile-time error to specify locations on the block
+// members. That is, when locations would be under specified by applying them on block members,
+// they are not allowed on block members. For arrayed interfaces (those generally having an
+// extra level of arrayness due to interface expansion), the outer array is stripped before
+// applying this rule."
+void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool memberWithLocation,
+ TArraySizes* arraySizes)
+{
+ if (memberWithLocation && arraySizes != nullptr) {
+ if (arraySizes->getNumDims() > (currentBlockQualifier.isArrayedIo(language) ? 1 : 0))
+ error(loc, "cannot use in a block array where new locations are needed for each block element",
+ "location", "");
+ }
+}
+
+// Do layout error checking with respect to a type.
+void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
+{
+ const TQualifier& qualifier = type.getQualifier();
+
+ // first, intra-layout qualifier-only error checking
+ layoutQualifierCheck(loc, qualifier);
+
+ // now, error checking combining type and qualifier
+
+ if (qualifier.hasAnyLocation()) {
+ if (qualifier.hasLocation()) {
+ if (qualifier.storage == EvqVaryingOut && language == EShLangFragment) {
+ if (qualifier.layoutLocation >= (unsigned int)resources.maxDrawBuffers)
+ error(loc, "too large for fragment output", "location", "");
+ }
+ }
+ if (qualifier.hasComponent()) {
+ // "It is a compile-time error if this sequence of components gets larger than 3."
+ if (qualifier.layoutComponent + type.getVectorSize() * (type.getBasicType() == EbtDouble ? 2 : 1) > 4)
+ error(loc, "type overflows the available 4 components", "component", "");
+
+ // "It is a compile-time error to apply the component qualifier to a matrix, a structure, a block, or an array containing any of these."
+ if (type.isMatrix() || type.getBasicType() == EbtBlock || type.getBasicType() == EbtStruct)
+ error(loc, "cannot apply to a matrix, structure, or block", "component", "");
+
+ // " It is a compile-time error to use component 1 or 3 as the beginning of a double or dvec2."
+ if (type.getBasicType() == EbtDouble)
+ if (qualifier.layoutComponent & 1)
+ error(loc, "doubles cannot start on an odd-numbered component", "component", "");
+ }
+
+ switch (qualifier.storage) {
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ if (type.getBasicType() == EbtBlock)
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "location qualifier on in/out block");
+ if (type.getQualifier().isTaskMemory())
+ error(loc, "cannot apply to taskNV in/out blocks", "location", "");
+ break;
+ case EvqUniform:
+ case EvqBuffer:
+ if (type.getBasicType() == EbtBlock)
+ error(loc, "cannot apply to uniform or buffer block", "location", "");
+ break;
+#ifndef GLSLANG_WEB
+ case EvqPayloadNV:
+ case EvqPayloadInNV:
+ case EvqHitAttrNV:
+ case EvqCallableDataNV:
+ case EvqCallableDataInNV:
+ break;
+#endif
+ default:
+ error(loc, "can only apply to uniform, buffer, in, or out storage qualifiers", "location", "");
+ break;
+ }
+
+ bool typeCollision;
+ int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision);
+ if (repeated >= 0 && ! typeCollision)
+ error(loc, "overlapping use of location", "location", "%d", repeated);
+ // "fragment-shader outputs ... if two variables are placed within the same
+ // location, they must have the same underlying type (floating-point or integer)"
+ if (typeCollision && language == EShLangFragment && qualifier.isPipeOutput())
+ error(loc, "fragment outputs sharing the same location must be the same basic type", "location", "%d", repeated);
+ }
+
+#ifndef GLSLANG_WEB
+ if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) {
+ int repeated = intermediate.addXfbBufferOffset(type);
+ if (repeated >= 0)
+ error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer);
+
+ // "The offset must be a multiple of the size of the first component of the first
+ // qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate
+ // containing a double or 64-bit integer, the offset must also be a multiple of 8..."
+ if ((type.containsBasicType(EbtDouble) || type.containsBasicType(EbtInt64) || type.containsBasicType(EbtUint64)) &&
+ ! IsMultipleOfPow2(qualifier.layoutXfbOffset, 8))
+ error(loc, "type contains double or 64-bit integer; xfb_offset must be a multiple of 8", "xfb_offset", "");
+ else if ((type.containsBasicType(EbtBool) || type.containsBasicType(EbtFloat) ||
+ type.containsBasicType(EbtInt) || type.containsBasicType(EbtUint)) &&
+ ! IsMultipleOfPow2(qualifier.layoutXfbOffset, 4))
+ error(loc, "must be a multiple of size of first component", "xfb_offset", "");
+ // ..., if applied to an aggregate containing a half float or 16-bit integer, the offset must also be a multiple of 2..."
+ else if ((type.contains16BitFloat() || type.containsBasicType(EbtInt16) || type.containsBasicType(EbtUint16)) &&
+ !IsMultipleOfPow2(qualifier.layoutXfbOffset, 2))
+ error(loc, "type contains half float or 16-bit integer; xfb_offset must be a multiple of 2", "xfb_offset", "");
+ }
+ if (qualifier.hasXfbStride() && qualifier.hasXfbBuffer()) {
+ if (! intermediate.setXfbBufferStride(qualifier.layoutXfbBuffer, qualifier.layoutXfbStride))
+ error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer);
+ }
+#endif
+
+ if (qualifier.hasBinding()) {
+ // Binding checking, from the spec:
+ //
+ // "If the binding point for any uniform or shader storage block instance is less than zero, or greater than or
+ // equal to the implementation-dependent maximum number of uniform buffer bindings, a compile-time
+ // error will occur. When the binding identifier is used with a uniform or shader storage block instanced as
+ // an array of size N, all elements of the array from binding through binding + N - 1 must be within this
+ // range."
+ //
+ if (! type.isOpaque() && type.getBasicType() != EbtBlock)
+ error(loc, "requires block, or sampler/image, or atomic-counter type", "binding", "");
+ if (type.getBasicType() == EbtSampler) {
+ int lastBinding = qualifier.layoutBinding;
+ if (type.isArray()) {
+ if (spvVersion.vulkan > 0)
+ lastBinding += 1;
+ else {
+ if (type.isSizedArray())
+ lastBinding += type.getCumulativeArraySize();
+ else {
+ lastBinding += 1;
+#ifndef GLSLANG_WEB
+ if (spvVersion.vulkan == 0)
+ warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", "");
+#endif
+ }
+ }
+ }
+#ifndef GLSLANG_WEB
+ if (spvVersion.vulkan == 0 && lastBinding >= resources.maxCombinedTextureImageUnits)
+ error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
+#endif
+ }
+ if (type.isAtomic()) {
+ if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
+ error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", "");
+ return;
+ }
+ }
+ } else if (!intermediate.getAutoMapBindings()) {
+ // some types require bindings
+
+ // atomic_uint
+ if (type.isAtomic())
+ error(loc, "layout(binding=X) is required", "atomic_uint", "");
+
+ // SPIR-V
+ if (spvVersion.spv > 0) {
+ if (qualifier.isUniformOrBuffer()) {
+ if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() &&
+ !qualifier.isShaderRecordNV() &&
+ !qualifier.hasAttachment() &&
+ !qualifier.hasBufferReference())
+ error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", "");
+ else if (spvVersion.vulkan > 0 && type.getBasicType() == EbtSampler)
+ error(loc, "sampler/texture/image requires layout(binding=X)", "binding", "");
+ }
+ }
+ }
+
+ // some things can't have arrays of arrays
+ if (type.isArrayOfArrays()) {
+ if (spvVersion.vulkan > 0) {
+ if (type.isOpaque() || (type.getQualifier().isUniformOrBuffer() && type.getBasicType() == EbtBlock))
+ warn(loc, "Generating SPIR-V array-of-arrays, but Vulkan only supports single array level for this resource", "[][]", "");
+ }
+ }
+
+ // "The offset qualifier can only be used on block members of blocks..."
+ if (qualifier.hasOffset()) {
+ if (type.getBasicType() == EbtBlock)
+ error(loc, "only applies to block members, not blocks", "offset", "");
+ }
+
+ // Image format
+ if (qualifier.hasFormat()) {
+ if (! type.isImage())
+ error(loc, "only apply to images", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
+ else {
+ if (type.getSampler().type == EbtFloat && qualifier.getFormat() > ElfFloatGuard)
+ error(loc, "does not apply to floating point images", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
+ if (type.getSampler().type == EbtInt && (qualifier.getFormat() < ElfFloatGuard || qualifier.getFormat() > ElfIntGuard))
+ error(loc, "does not apply to signed integer images", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
+ if (type.getSampler().type == EbtUint && qualifier.getFormat() < ElfIntGuard)
+ error(loc, "does not apply to unsigned integer images", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
+
+ if (isEsProfile()) {
+ // "Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui, image variables must
+ // specify either memory qualifier readonly or the memory qualifier writeonly."
+ if (! (qualifier.getFormat() == ElfR32f || qualifier.getFormat() == ElfR32i || qualifier.getFormat() == ElfR32ui)) {
+ if (! qualifier.isReadOnly() && ! qualifier.isWriteOnly())
+ error(loc, "format requires readonly or writeonly memory qualifier", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
+ }
+ }
+ }
+ } else if (type.isImage() && ! qualifier.isWriteOnly()) {
+ const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier";
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation);
+ }
+
+ if (qualifier.isPushConstant() && type.getBasicType() != EbtBlock)
+ error(loc, "can only be used with a block", "push_constant", "");
+
+ if (qualifier.hasBufferReference() && type.getBasicType() != EbtBlock)
+ error(loc, "can only be used with a block", "buffer_reference", "");
+
+ if (qualifier.isShaderRecordNV() && type.getBasicType() != EbtBlock)
+ error(loc, "can only be used with a block", "shaderRecordNV", "");
+
+ // input attachment
+ if (type.isSubpass()) {
+ if (! qualifier.hasAttachment())
+ error(loc, "requires an input_attachment_index layout qualifier", "subpass", "");
+ } else {
+ if (qualifier.hasAttachment())
+ error(loc, "can only be used with a subpass", "input_attachment_index", "");
+ }
+
+ // specialization-constant id
+ if (qualifier.hasSpecConstantId()) {
+ if (type.getQualifier().storage != EvqConst)
+ error(loc, "can only be applied to 'const'-qualified scalar", "constant_id", "");
+ if (! type.isScalar())
+ error(loc, "can only be applied to a scalar", "constant_id", "");
+ switch (type.getBasicType())
+ {
+ case EbtInt8:
+ case EbtUint8:
+ case EbtInt16:
+ case EbtUint16:
+ case EbtInt:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ case EbtBool:
+ case EbtFloat:
+ case EbtDouble:
+ case EbtFloat16:
+ break;
+ default:
+ error(loc, "cannot be applied to this type", "constant_id", "");
+ break;
+ }
+ }
+}
+
+// Do layout error checking that can be done within a layout qualifier proper, not needing to know
+// if there are blocks, atomic counters, variables, etc.
+void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier)
+{
+ if (qualifier.storage == EvqShared && qualifier.hasLayout())
+ error(loc, "cannot apply layout qualifiers to a shared variable", "shared", "");
+
+ // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)."
+ if (qualifier.hasComponent() && ! qualifier.hasLocation())
+ error(loc, "must specify 'location' to use 'component'", "component", "");
+
+ if (qualifier.hasAnyLocation()) {
+
+ // "As with input layout qualifiers, all shaders except compute shaders
+ // allow *location* layout qualifiers on output variable declarations,
+ // output block declarations, and output block member declarations."
+
+ switch (qualifier.storage) {
+#ifndef GLSLANG_WEB
+ case EvqVaryingIn:
+ {
+ const char* feature = "location qualifier on input";
+ if (isEsProfile() && version < 310)
+ requireStage(loc, EShLangVertex, feature);
+ else
+ requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
+ if (language == EShLangVertex) {
+ const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
+ profileRequires(loc, ~EEsProfile, 330, 2, exts, feature);
+ profileRequires(loc, EEsProfile, 300, nullptr, feature);
+ } else {
+ profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ }
+ break;
+ }
+ case EvqVaryingOut:
+ {
+ const char* feature = "location qualifier on output";
+ if (isEsProfile() && version < 310)
+ requireStage(loc, EShLangFragment, feature);
+ else
+ requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
+ if (language == EShLangFragment) {
+ const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
+ profileRequires(loc, ~EEsProfile, 330, 2, exts, feature);
+ profileRequires(loc, EEsProfile, 300, nullptr, feature);
+ } else {
+ profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ }
+ break;
+ }
+#endif
+ case EvqUniform:
+ case EvqBuffer:
+ {
+ const char* feature = "location qualifier on uniform or buffer";
+ requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile | ENoProfile, feature);
+ profileRequires(loc, ~EEsProfile, 330, E_GL_ARB_explicit_attrib_location, feature);
+ profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_explicit_uniform_location, feature);
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ break;
+ }
+ default:
+ break;
+ }
+ if (qualifier.hasIndex()) {
+ if (qualifier.storage != EvqVaryingOut)
+ error(loc, "can only be used on an output", "index", "");
+ if (! qualifier.hasLocation())
+ error(loc, "can only be used with an explicit location", "index", "");
+ }
+ }
+
+ if (qualifier.hasBinding()) {
+ if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory())
+ error(loc, "requires uniform or buffer storage qualifier", "binding", "");
+ }
+ if (qualifier.hasStream()) {
+ if (!qualifier.isPipeOutput())
+ error(loc, "can only be used on an output", "stream", "");
+ }
+ if (qualifier.hasXfb()) {
+ if (!qualifier.isPipeOutput())
+ error(loc, "can only be used on an output", "xfb layout qualifier", "");
+ }
+ if (qualifier.hasUniformLayout()) {
+ if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) {
+ if (qualifier.hasMatrix() || qualifier.hasPacking())
+ error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", "");
+ if (qualifier.hasOffset() || qualifier.hasAlign())
+ error(loc, "offset/align can only be used on a uniform or buffer", "layout", "");
+ }
+ }
+ if (qualifier.isPushConstant()) {
+ if (qualifier.storage != EvqUniform)
+ error(loc, "can only be used with a uniform", "push_constant", "");
+ if (qualifier.hasSet())
+ error(loc, "cannot be used with push_constant", "set", "");
+ }
+ if (qualifier.hasBufferReference()) {
+ if (qualifier.storage != EvqBuffer)
+ error(loc, "can only be used with buffer", "buffer_reference", "");
+ }
+ if (qualifier.isShaderRecordNV()) {
+ if (qualifier.storage != EvqBuffer)
+ error(loc, "can only be used with a buffer", "shaderRecordNV", "");
+ if (qualifier.hasBinding())
+ error(loc, "cannot be used with shaderRecordNV", "binding", "");
+ if (qualifier.hasSet())
+ error(loc, "cannot be used with shaderRecordNV", "set", "");
+
+ }
+ if (qualifier.storage == EvqHitAttrNV && qualifier.hasLayout()) {
+ error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", "");
+ }
+}
+
+// For places that can't have shader-level layout qualifiers
+void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQualifiers& shaderQualifiers)
+{
+#ifndef GLSLANG_WEB
+ const char* message = "can only apply to a standalone qualifier";
+
+ if (shaderQualifiers.geometry != ElgNone)
+ error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), "");
+ if (shaderQualifiers.spacing != EvsNone)
+ error(loc, message, TQualifier::getVertexSpacingString(shaderQualifiers.spacing), "");
+ if (shaderQualifiers.order != EvoNone)
+ error(loc, message, TQualifier::getVertexOrderString(shaderQualifiers.order), "");
+ if (shaderQualifiers.pointMode)
+ error(loc, message, "point_mode", "");
+ if (shaderQualifiers.invocations != TQualifier::layoutNotSet)
+ error(loc, message, "invocations", "");
+ for (int i = 0; i < 3; ++i) {
+ if (shaderQualifiers.localSize[i] > 1)
+ error(loc, message, "local_size", "");
+ if (shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet)
+ error(loc, message, "local_size id", "");
+ }
+ if (shaderQualifiers.vertices != TQualifier::layoutNotSet) {
+ if (language == EShLangGeometry || language == EShLangMeshNV)
+ error(loc, message, "max_vertices", "");
+ else if (language == EShLangTessControl)
+ error(loc, message, "vertices", "");
+ else
+ assert(0);
+ }
+ if (shaderQualifiers.earlyFragmentTests)
+ error(loc, message, "early_fragment_tests", "");
+ if (shaderQualifiers.postDepthCoverage)
+ error(loc, message, "post_depth_coverage", "");
+ if (shaderQualifiers.primitives != TQualifier::layoutNotSet) {
+ if (language == EShLangMeshNV)
+ error(loc, message, "max_primitives", "");
+ else
+ assert(0);
+ }
+ if (shaderQualifiers.hasBlendEquation())
+ error(loc, message, "blend equation", "");
+ if (shaderQualifiers.numViews != TQualifier::layoutNotSet)
+ error(loc, message, "num_views", "");
+ if (shaderQualifiers.interlockOrdering != EioNone)
+ error(loc, message, TQualifier::getInterlockOrderingString(shaderQualifiers.interlockOrdering), "");
+#endif
+}
+
+// Correct and/or advance an object's offset layout qualifier.
+void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol)
+{
+ const TQualifier& qualifier = symbol.getType().getQualifier();
+#ifndef GLSLANG_WEB
+ if (symbol.getType().isAtomic()) {
+ if (qualifier.hasBinding() && (int)qualifier.layoutBinding < resources.maxAtomicCounterBindings) {
+
+ // Set the offset
+ int offset;
+ if (qualifier.hasOffset())
+ offset = qualifier.layoutOffset;
+ else
+ offset = atomicUintOffsets[qualifier.layoutBinding];
+
+ if (offset % 4 != 0)
+ error(loc, "atomic counters offset should align based on 4:", "offset", "%d", offset);
+
+ symbol.getWritableType().getQualifier().layoutOffset = offset;
+
+ // Check for overlap
+ int numOffsets = 4;
+ if (symbol.getType().isArray()) {
+ if (symbol.getType().isSizedArray() && !symbol.getType().getArraySizes()->isInnerUnsized())
+ numOffsets *= symbol.getType().getCumulativeArraySize();
+ else {
+ // "It is a compile-time error to declare an unsized array of atomic_uint."
+ error(loc, "array must be explicitly sized", "atomic_uint", "");
+ }
+ }
+ int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets);
+ if (repeated >= 0)
+ error(loc, "atomic counters sharing the same offset:", "offset", "%d", repeated);
+
+ // Bump the default offset
+ atomicUintOffsets[qualifier.layoutBinding] = offset + numOffsets;
+ }
+ }
+#endif
+}
+
+//
+// Look up a function name in the symbol table, and make sure it is a function.
+//
+// Return the function symbol if found, otherwise nullptr.
+//
+const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
+{
+ if (symbolTable.isFunctionNameVariable(call.getName())) {
+ error(loc, "can't use function syntax on variable", call.getName().c_str(), "");
+ return nullptr;
+ }
+
+#ifdef GLSLANG_WEB
+ return findFunctionExact(loc, call, builtIn);
+#endif
+
+ const TFunction* function = nullptr;
+ bool explicitTypesEnabled = extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
+ extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||
+ extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32) ||
+ extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64) ||
+ extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
+ extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
+ extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64);
+
+ if (isEsProfile() || version < 120)
+ function = findFunctionExact(loc, call, builtIn);
+ else if (version < 400)
+ function = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn);
+ else if (explicitTypesEnabled)
+ function = findFunctionExplicitTypes(loc, call, builtIn);
+ else
+ function = findFunction400(loc, call, builtIn);
+
+ return function;
+}
+
+// Function finding algorithm for ES and desktop 110.
+const TFunction* TParseContext::findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
+{
+ TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
+ if (symbol == nullptr) {
+ error(loc, "no matching overloaded function found", call.getName().c_str(), "");
+
+ return nullptr;
+ }
+
+ return symbol->getAsFunction();
+}
+
+// Function finding algorithm for desktop versions 120 through 330.
+const TFunction* TParseContext::findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
+{
+ // first, look for an exact match
+ TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
+ if (symbol)
+ return symbol->getAsFunction();
+
+ // exact match not found, look through a list of overloaded functions of the same name
+
+ // "If no exact match is found, then [implicit conversions] will be applied to find a match. Mismatched types
+ // on input parameters (in or inout or default) must have a conversion from the calling argument type to the
+ // formal parameter type. Mismatched types on output parameters (out or inout) must have a conversion
+ // from the formal parameter type to the calling argument type. When argument conversions are used to find
+ // a match, it is a semantic error if there are multiple ways to apply these conversions to make the call match
+ // more than one function."
+
+ const TFunction* candidate = nullptr;
+ TVector<const TFunction*> candidateList;
+ symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
+
+ for (auto it = candidateList.begin(); it != candidateList.end(); ++it) {
+ const TFunction& function = *(*it);
+
+ // to even be a potential match, number of arguments has to match
+ if (call.getParamCount() != function.getParamCount())
+ continue;
+
+ bool possibleMatch = true;
+ for (int i = 0; i < function.getParamCount(); ++i) {
+ // same types is easy
+ if (*function[i].type == *call[i].type)
+ continue;
+
+ // We have a mismatch in type, see if it is implicitly convertible
+
+ if (function[i].type->isArray() || call[i].type->isArray() ||
+ ! function[i].type->sameElementShape(*call[i].type))
+ possibleMatch = false;
+ else {
+ // do direction-specific checks for conversion of basic type
+ if (function[i].type->getQualifier().isParamInput()) {
+ if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType()))
+ possibleMatch = false;
+ }
+ if (function[i].type->getQualifier().isParamOutput()) {
+ if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType()))
+ possibleMatch = false;
+ }
+ }
+ if (! possibleMatch)
+ break;
+ }
+ if (possibleMatch) {
+ if (candidate) {
+ // our second match, meaning ambiguity
+ error(loc, "ambiguous function signature match: multiple signatures match under implicit type conversion", call.getName().c_str(), "");
+ } else
+ candidate = &function;
+ }
+ }
+
+ if (candidate == nullptr)
+ error(loc, "no matching overloaded function found", call.getName().c_str(), "");
+
+ return candidate;
+}
+
+// Function finding algorithm for desktop version 400 and above.
+//
+// "When function calls are resolved, an exact type match for all the arguments
+// is sought. If an exact match is found, all other functions are ignored, and
+// the exact match is used. If no exact match is found, then the implicit
+// conversions in section 4.1.10 Implicit Conversions will be applied to find
+// a match. Mismatched types on input parameters (in or inout or default) must
+// have a conversion from the calling argument type to the formal parameter type.
+// Mismatched types on output parameters (out or inout) must have a conversion
+// from the formal parameter type to the calling argument type.
+//
+// "If implicit conversions can be used to find more than one matching function,
+// a single best-matching function is sought. To determine a best match, the
+// conversions between calling argument and formal parameter types are compared
+// for each function argument and pair of matching functions. After these
+// comparisons are performed, each pair of matching functions are compared.
+// A function declaration A is considered a better match than function
+// declaration B if
+//
+// * for at least one function argument, the conversion for that argument in A
+// is better than the corresponding conversion in B; and
+// * there is no function argument for which the conversion in B is better than
+// the corresponding conversion in A.
+//
+// "If a single function declaration is considered a better match than every
+// other matching function declaration, it will be used. Otherwise, a
+// compile-time semantic error for an ambiguous overloaded function call occurs.
+//
+// "To determine whether the conversion for a single argument in one match is
+// better than that for another match, the following rules are applied, in order:
+//
+// 1. An exact match is better than a match involving any implicit conversion.
+// 2. A match involving an implicit conversion from float to double is better
+// than a match involving any other implicit conversion.
+// 3. A match involving an implicit conversion from either int or uint to float
+// is better than a match involving an implicit conversion from either int
+// or uint to double.
+//
+// "If none of the rules above apply to a particular pair of conversions, neither
+// conversion is considered better than the other."
+//
+const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
+{
+ // first, look for an exact match
+ TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
+ if (symbol)
+ return symbol->getAsFunction();
+
+ // no exact match, use the generic selector, parameterized by the GLSL rules
+
+ // create list of candidates to send
+ TVector<const TFunction*> candidateList;
+ symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
+
+ // can 'from' convert to 'to'?
+ const auto convertible = [this,builtIn](const TType& from, const TType& to, TOperator, int) -> bool {
+ if (from == to)
+ return true;
+ if (from.coopMatParameterOK(to))
+ return true;
+ // Allow a sized array to be passed through an unsized array parameter, for coopMatLoad/Store functions
+ if (builtIn && from.isArray() && to.isUnsizedArray()) {
+ TType fromElementType(from, 0);
+ TType toElementType(to, 0);
+ if (fromElementType == toElementType)
+ return true;
+ }
+ if (from.isArray() || to.isArray() || ! from.sameElementShape(to))
+ return false;
+ if (from.isCoopMat() && to.isCoopMat())
+ return from.sameCoopMatBaseType(to);
+ return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType());
+ };
+
+ // Is 'to2' a better conversion than 'to1'?
+ // Ties should not be considered as better.
+ // Assumes 'convertible' already said true.
+ const auto better = [](const TType& from, const TType& to1, const TType& to2) -> bool {
+ // 1. exact match
+ if (from == to2)
+ return from != to1;
+ if (from == to1)
+ return false;
+
+ // 2. float -> double is better
+ if (from.getBasicType() == EbtFloat) {
+ if (to2.getBasicType() == EbtDouble && to1.getBasicType() != EbtDouble)
+ return true;
+ }
+
+ // 3. -> float is better than -> double
+ return to2.getBasicType() == EbtFloat && to1.getBasicType() == EbtDouble;
+ };
+
+ // for ambiguity reporting
+ bool tie = false;
+
+ // send to the generic selector
+ const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie);
+
+ if (bestMatch == nullptr)
+ error(loc, "no matching overloaded function found", call.getName().c_str(), "");
+ else if (tie)
+ error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), "");
+
+ return bestMatch;
+}
+
+// "To determine whether the conversion for a single argument in one match
+// is better than that for another match, the conversion is assigned of the
+// three ranks ordered from best to worst:
+// 1. Exact match: no conversion.
+// 2. Promotion: integral or floating-point promotion.
+// 3. Conversion: integral conversion, floating-point conversion,
+// floating-integral conversion.
+// A conversion C1 is better than a conversion C2 if the rank of C1 is
+// better than the rank of C2."
+const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
+{
+ // first, look for an exact match
+ TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
+ if (symbol)
+ return symbol->getAsFunction();
+
+ // no exact match, use the generic selector, parameterized by the GLSL rules
+
+ // create list of candidates to send
+ TVector<const TFunction*> candidateList;
+ symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
+
+ // can 'from' convert to 'to'?
+ const auto convertible = [this,builtIn](const TType& from, const TType& to, TOperator, int) -> bool {
+ if (from == to)
+ return true;
+ if (from.coopMatParameterOK(to))
+ return true;
+ // Allow a sized array to be passed through an unsized array parameter, for coopMatLoad/Store functions
+ if (builtIn && from.isArray() && to.isUnsizedArray()) {
+ TType fromElementType(from, 0);
+ TType toElementType(to, 0);
+ if (fromElementType == toElementType)
+ return true;
+ }
+ if (from.isArray() || to.isArray() || ! from.sameElementShape(to))
+ return false;
+ if (from.isCoopMat() && to.isCoopMat())
+ return from.sameCoopMatBaseType(to);
+ return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType());
+ };
+
+ // Is 'to2' a better conversion than 'to1'?
+ // Ties should not be considered as better.
+ // Assumes 'convertible' already said true.
+ const auto better = [this](const TType& from, const TType& to1, const TType& to2) -> bool {
+ // 1. exact match
+ if (from == to2)
+ return from != to1;
+ if (from == to1)
+ return false;
+
+ // 2. Promotion (integral, floating-point) is better
+ TBasicType from_type = from.getBasicType();
+ TBasicType to1_type = to1.getBasicType();
+ TBasicType to2_type = to2.getBasicType();
+ bool isPromotion1 = (intermediate.isIntegralPromotion(from_type, to1_type) ||
+ intermediate.isFPPromotion(from_type, to1_type));
+ bool isPromotion2 = (intermediate.isIntegralPromotion(from_type, to2_type) ||
+ intermediate.isFPPromotion(from_type, to2_type));
+ if (isPromotion2)
+ return !isPromotion1;
+ if(isPromotion1)
+ return false;
+
+ // 3. Conversion (integral, floating-point , floating-integral)
+ bool isConversion1 = (intermediate.isIntegralConversion(from_type, to1_type) ||
+ intermediate.isFPConversion(from_type, to1_type) ||
+ intermediate.isFPIntegralConversion(from_type, to1_type));
+ bool isConversion2 = (intermediate.isIntegralConversion(from_type, to2_type) ||
+ intermediate.isFPConversion(from_type, to2_type) ||
+ intermediate.isFPIntegralConversion(from_type, to2_type));
+
+ return isConversion2 && !isConversion1;
+ };
+
+ // for ambiguity reporting
+ bool tie = false;
+
+ // send to the generic selector
+ const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie);
+
+ if (bestMatch == nullptr)
+ error(loc, "no matching overloaded function found", call.getName().c_str(), "");
+ else if (tie)
+ error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), "");
+
+ return bestMatch;
+}
+
+// When a declaration includes a type, but not a variable name, it can be used
+// to establish defaults.
+void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType)
+{
+#ifndef GLSLANG_WEB
+ if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding()) {
+ if (publicType.qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
+ error(loc, "atomic_uint binding is too large", "binding", "");
+ return;
+ }
+
+ if(publicType.qualifier.hasOffset()) {
+ atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset;
+ }
+ return;
+ }
+
+ if (publicType.qualifier.hasLayout() && !publicType.qualifier.hasBufferReference())
+ warn(loc, "useless application of layout qualifier", "layout", "");
+#endif
+}
+
+//
+// Do everything necessary to handle a variable (non-block) declaration.
+// Either redeclaring a variable, or making a new one, updating the symbol
+// table, and all error checking.
+//
+// Returns a subtree node that computes an initializer, if needed.
+// Returns nullptr if there is no code to execute for initialization.
+//
+// 'publicType' is the type part of the declaration (to the left)
+// 'arraySizes' is the arrayness tagged on the identifier (to the right)
+//
+TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TPublicType& publicType,
+ TArraySizes* arraySizes, TIntermTyped* initializer)
+{
+ // Make a fresh type that combines the characteristics from the individual
+ // identifier syntax and the declaration-type syntax.
+ TType type(publicType);
+ type.transferArraySizes(arraySizes);
+ type.copyArrayInnerSizes(publicType.arraySizes);
+ arrayOfArrayVersionCheck(loc, type.getArraySizes());
+
+ if (type.isCoopMat()) {
+ intermediate.setUseVulkanMemoryModel();
+ intermediate.setUseStorageBuffer();
+
+ if (!publicType.typeParameters || publicType.typeParameters->getNumDims() != 4) {
+ error(loc, "expected four type parameters", identifier.c_str(), "");
+ }
+ if (publicType.typeParameters) {
+ if (isTypeFloat(publicType.basicType) &&
+ publicType.typeParameters->getDimSize(0) != 16 &&
+ publicType.typeParameters->getDimSize(0) != 32 &&
+ publicType.typeParameters->getDimSize(0) != 64) {
+ error(loc, "expected 16, 32, or 64 bits for first type parameter", identifier.c_str(), "");
+ }
+ if (isTypeInt(publicType.basicType) &&
+ publicType.typeParameters->getDimSize(0) != 8 &&
+ publicType.typeParameters->getDimSize(0) != 32) {
+ error(loc, "expected 8 or 32 bits for first type parameter", identifier.c_str(), "");
+ }
+ }
+
+ } else {
+ if (publicType.typeParameters && publicType.typeParameters->getNumDims() != 0) {
+ error(loc, "unexpected type parameters", identifier.c_str(), "");
+ }
+ }
+
+ if (voidErrorCheck(loc, identifier, type.getBasicType()))
+ return nullptr;
+
+ if (initializer)
+ rValueErrorCheck(loc, "initializer", initializer);
+ else
+ nonInitConstCheck(loc, identifier, type);
+
+ samplerCheck(loc, type, identifier, initializer);
+ transparentOpaqueCheck(loc, type, identifier);
+#ifndef GLSLANG_WEB
+ atomicUintCheck(loc, type, identifier);
+ accStructNVCheck(loc, type, identifier);
+ checkAndResizeMeshViewDim(loc, type, /*isBlockMember*/ false);
+#endif
+ if (type.getQualifier().storage == EvqConst && type.containsReference()) {
+ error(loc, "variables with reference type can't have qualifier 'const'", "qualifier", "");
+ }
+
+ if (type.getQualifier().storage != EvqUniform && type.getQualifier().storage != EvqBuffer) {
+ if (type.contains16BitFloat())
+ requireFloat16Arithmetic(loc, "qualifier", "float16 types can only be in uniform block or buffer storage");
+ if (type.contains16BitInt())
+ requireInt16Arithmetic(loc, "qualifier", "(u)int16 types can only be in uniform block or buffer storage");
+ if (type.contains8BitInt())
+ requireInt8Arithmetic(loc, "qualifier", "(u)int8 types can only be in uniform block or buffer storage");
+ }
+
+ if (type.getQualifier().storage == EvqShared && type.containsCoopMat())
+ error(loc, "qualifier", "Cooperative matrix types must not be used in shared memory", "");
+
+ if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
+ error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
+ if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.getDepth() != EldNone)
+ error(loc, "can only apply depth layout to gl_FragDepth", "layout qualifier", "");
+
+ // Check for redeclaration of built-ins and/or attempting to declare a reserved name
+ TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers);
+ if (symbol == nullptr)
+ reservedErrorCheck(loc, identifier);
+
+ inheritGlobalDefaults(type.getQualifier());
+
+ // Declare the variable
+ if (type.isArray()) {
+ // Check that implicit sizing is only where allowed.
+ arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer, false);
+
+ if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type))
+ declareArray(loc, identifier, type, symbol);
+
+ if (initializer) {
+ profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "initializer");
+ profileRequires(loc, EEsProfile, 300, nullptr, "initializer");
+ }
+ } else {
+ // non-array case
+ if (symbol == nullptr)
+ symbol = declareNonArray(loc, identifier, type);
+ else if (type != symbol->getType())
+ error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str());
+ }
+
+ if (symbol == nullptr)
+ return nullptr;
+
+ // Deal with initializer
+ TIntermNode* initNode = nullptr;
+ if (symbol != nullptr && initializer) {
+ TVariable* variable = symbol->getAsVariable();
+ if (! variable) {
+ error(loc, "initializer requires a variable, not a member", identifier.c_str(), "");
+ return nullptr;
+ }
+ initNode = executeInitializer(loc, initializer, variable);
+ }
+
+ // look for errors in layout qualifier use
+ layoutObjectCheck(loc, *symbol);
+
+ // fix up
+ fixOffset(loc, *symbol);
+
+ return initNode;
+}
+
+// Pick up global defaults from the provide global defaults into dst.
+void TParseContext::inheritGlobalDefaults(TQualifier& dst) const
+{
+#ifndef GLSLANG_WEB
+ if (dst.storage == EvqVaryingOut) {
+ if (! dst.hasStream() && language == EShLangGeometry)
+ dst.layoutStream = globalOutputDefaults.layoutStream;
+ if (! dst.hasXfbBuffer())
+ dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
+ }
+#endif
+}
+
+//
+// Make an internal-only variable whose name is for debug purposes only
+// and won't be searched for. Callers will only use the return value to use
+// the variable, not the name to look it up. It is okay if the name
+// is the same as other names; there won't be any conflict.
+//
+TVariable* TParseContext::makeInternalVariable(const char* name, const TType& type) const
+{
+ TString* nameString = NewPoolTString(name);
+ TVariable* variable = new TVariable(nameString, type);
+ symbolTable.makeInternalVariable(*variable);
+
+ return variable;
+}
+
+//
+// Declare a non-array variable, the main point being there is no redeclaration
+// for resizing allowed.
+//
+// Return the successfully declared variable.
+//
+TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString& identifier, const TType& type)
+{
+ // make a new variable
+ TVariable* variable = new TVariable(&identifier, type);
+
+#ifndef GLSLANG_WEB
+ ioArrayCheck(loc, type, identifier);
+#endif
+
+ // add variable to symbol table
+ if (symbolTable.insert(*variable)) {
+ if (symbolTable.atGlobalLevel())
+ trackLinkage(*variable);
+ return variable;
+ }
+
+ error(loc, "redefinition", variable->getName().c_str(), "");
+ return nullptr;
+}
+
+//
+// Handle all types of initializers from the grammar.
+//
+// Returning nullptr just means there is no code to execute to handle the
+// initializer, which will, for example, be the case for constant initializers.
+//
+TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable)
+{
+ //
+ // Identifier must be of type constant, a global, or a temporary, and
+ // starting at version 120, desktop allows uniforms to have initializers.
+ //
+ TStorageQualifier qualifier = variable->getType().getQualifier().storage;
+ if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst ||
+ (qualifier == EvqUniform && !isEsProfile() && version >= 120))) {
+ error(loc, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), "");
+ return nullptr;
+ }
+ arrayObjectCheck(loc, variable->getType(), "array initializer");
+
+ //
+ // If the initializer was from braces { ... }, we convert the whole subtree to a
+ // constructor-style subtree, allowing the rest of the code to operate
+ // identically for both kinds of initializers.
+ //
+ // Type can't be deduced from the initializer list, so a skeletal type to
+ // follow has to be passed in. Constness and specialization-constness
+ // should be deduced bottom up, not dictated by the skeletal type.
+ //
+ TType skeletalType;
+ skeletalType.shallowCopy(variable->getType());
+ skeletalType.getQualifier().makeTemporary();
+#ifndef GLSLANG_WEB
+ initializer = convertInitializerList(loc, skeletalType, initializer);
+#endif
+ if (! initializer) {
+ // error recovery; don't leave const without constant values
+ if (qualifier == EvqConst)
+ variable->getWritableType().getQualifier().makeTemporary();
+ return nullptr;
+ }
+
+ // Fix outer arrayness if variable is unsized, getting size from the initializer
+ if (initializer->getType().isSizedArray() && variable->getType().isUnsizedArray())
+ variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize());
+
+ // Inner arrayness can also get set by an initializer
+ if (initializer->getType().isArrayOfArrays() && variable->getType().isArrayOfArrays() &&
+ initializer->getType().getArraySizes()->getNumDims() ==
+ variable->getType().getArraySizes()->getNumDims()) {
+ // adopt unsized sizes from the initializer's sizes
+ for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) {
+ if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize) {
+ variable->getWritableType().getArraySizes()->setDimSize(d,
+ initializer->getType().getArraySizes()->getDimSize(d));
+ }
+ }
+ }
+
+ // Uniforms require a compile-time constant initializer
+ if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) {
+ error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
+ variable->getWritableType().getQualifier().makeTemporary();
+ return nullptr;
+ }
+ // Global consts require a constant initializer (specialization constant is okay)
+ if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
+ error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
+ variable->getWritableType().getQualifier().makeTemporary();
+ return nullptr;
+ }
+
+ // Const variables require a constant initializer, depending on version
+ if (qualifier == EvqConst) {
+ if (! initializer->getType().getQualifier().isConstant()) {
+ const char* initFeature = "non-constant initializer";
+ requireProfile(loc, ~EEsProfile, initFeature);
+ profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
+ variable->getWritableType().getQualifier().storage = EvqConstReadOnly;
+ qualifier = EvqConstReadOnly;
+ }
+ } else {
+ // Non-const global variables in ES need a const initializer.
+ //
+ // "In declarations of global variables with no storage qualifier or with a const
+ // qualifier any initializer must be a constant expression."
+ if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
+ const char* initFeature = "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)";
+ if (isEsProfile()) {
+ if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers))
+ warn(loc, "not allowed in this version", initFeature, "");
+ else
+ profileRequires(loc, EEsProfile, 0, E_GL_EXT_shader_non_constant_global_initializers, initFeature);
+ }
+ }
+ }
+
+ if (qualifier == EvqConst || qualifier == EvqUniform) {
+ // Compile-time tagging of the variable with its constant value...
+
+ initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer);
+ if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) {
+ error(loc, "non-matching or non-convertible constant type for const initializer",
+ variable->getType().getStorageQualifierString(), "");
+ variable->getWritableType().getQualifier().makeTemporary();
+ return nullptr;
+ }
+
+ // We either have a folded constant in getAsConstantUnion, or we have to use
+ // the initializer's subtree in the AST to represent the computation of a
+ // specialization constant.
+ assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant());
+ if (initializer->getAsConstantUnion())
+ variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
+ else {
+ // It's a specialization constant.
+ variable->getWritableType().getQualifier().makeSpecConstant();
+
+ // Keep the subtree that computes the specialization constant with the variable.
+ // Later, a symbol node will adopt the subtree from the variable.
+ variable->setConstSubtree(initializer);
+ }
+ } else {
+ // normal assigning of a value to a variable...
+ specializationCheck(loc, initializer->getType(), "initializer");
+ TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
+ TIntermTyped* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc);
+ if (! initNode)
+ assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
+
+ return initNode;
+ }
+
+ return nullptr;
+}
+
+//
+// Reprocess any initializer-list (the "{ ... }" syntax) parts of the
+// initializer.
+//
+// Need to hierarchically assign correct types and implicit
+// conversions. Will do this mimicking the same process used for
+// creating a constructor-style initializer, ensuring we get the
+// same form. However, it has to in parallel walk the 'type'
+// passed in, as type cannot be deduced from an initializer list.
+//
+TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type, TIntermTyped* initializer)
+{
+ // Will operate recursively. Once a subtree is found that is constructor style,
+ // everything below it is already good: Only the "top part" of the initializer
+ // can be an initializer list, where "top part" can extend for several (or all) levels.
+
+ // see if we have bottomed out in the tree within the initializer-list part
+ TIntermAggregate* initList = initializer->getAsAggregate();
+ if (! initList || initList->getOp() != EOpNull)
+ return initializer;
+
+ // Of the initializer-list set of nodes, need to process bottom up,
+ // so recurse deep, then process on the way up.
+
+ // Go down the tree here...
+ if (type.isArray()) {
+ // The type's array might be unsized, which could be okay, so base sizes on the size of the aggregate.
+ // Later on, initializer execution code will deal with array size logic.
+ TType arrayType;
+ arrayType.shallowCopy(type); // sharing struct stuff is fine
+ arrayType.copyArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below
+
+ // edit array sizes to fill in unsized dimensions
+ arrayType.changeOuterArraySize((int)initList->getSequence().size());
+ TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped();
+ if (arrayType.isArrayOfArrays() && firstInit->getType().isArray() &&
+ arrayType.getArraySizes()->getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) {
+ for (int d = 1; d < arrayType.getArraySizes()->getNumDims(); ++d) {
+ if (arrayType.getArraySizes()->getDimSize(d) == UnsizedArraySize)
+ arrayType.getArraySizes()->setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1));
+ }
+ }
+
+ TType elementType(arrayType, 0); // dereferenced type
+ for (size_t i = 0; i < initList->getSequence().size(); ++i) {
+ initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped());
+ if (initList->getSequence()[i] == nullptr)
+ return nullptr;
+ }
+
+ return addConstructor(loc, initList, arrayType);
+ } else if (type.isStruct()) {
+ if (type.getStruct()->size() != initList->getSequence().size()) {
+ error(loc, "wrong number of structure members", "initializer list", "");
+ return nullptr;
+ }
+ for (size_t i = 0; i < type.getStruct()->size(); ++i) {
+ initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, initList->getSequence()[i]->getAsTyped());
+ if (initList->getSequence()[i] == nullptr)
+ return nullptr;
+ }
+ } else if (type.isMatrix()) {
+ if (type.getMatrixCols() != (int)initList->getSequence().size()) {
+ error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str());
+ return nullptr;
+ }
+ TType vectorType(type, 0); // dereferenced type
+ for (int i = 0; i < type.getMatrixCols(); ++i) {
+ initList->getSequence()[i] = convertInitializerList(loc, vectorType, initList->getSequence()[i]->getAsTyped());
+ if (initList->getSequence()[i] == nullptr)
+ return nullptr;
+ }
+ } else if (type.isVector()) {
+ if (type.getVectorSize() != (int)initList->getSequence().size()) {
+ error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str());
+ return nullptr;
+ }
+ } else {
+ error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str());
+ return nullptr;
+ }
+
+ // Now that the subtree is processed, process this node as if the
+ // initializer list is a set of arguments to a constructor.
+ TIntermNode* emulatedConstructorArguments;
+ if (initList->getSequence().size() == 1)
+ emulatedConstructorArguments = initList->getSequence()[0];
+ else
+ emulatedConstructorArguments = initList;
+ return addConstructor(loc, emulatedConstructorArguments, type);
+}
+
+//
+// Test for the correctness of the parameters passed to various constructor functions
+// and also convert them to the right data type, if allowed and required.
+//
+// 'node' is what to construct from.
+// 'type' is what type to construct.
+//
+// Returns nullptr for an error or the constructed node (aggregate or typed) for no error.
+//
+TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type)
+{
+ if (node == nullptr || node->getAsTyped() == nullptr)
+ return nullptr;
+ rValueErrorCheck(loc, "constructor", node->getAsTyped());
+
+ TIntermAggregate* aggrNode = node->getAsAggregate();
+ TOperator op = intermediate.mapTypeToConstructorOp(type);
+
+ // Combined texture-sampler constructors are completely semantic checked
+ // in constructorTextureSamplerError()
+ if (op == EOpConstructTextureSampler) {
+ if (aggrNode->getSequence()[1]->getAsTyped()->getType().getSampler().shadow) {
+ // Transfer depth into the texture (SPIR-V image) type, as a hint
+ // for tools to know this texture/image is a depth image.
+ aggrNode->getSequence()[0]->getAsTyped()->getWritableType().getSampler().shadow = true;
+ }
+ return intermediate.setAggregateOperator(aggrNode, op, type, loc);
+ }
+
+ TTypeList::const_iterator memberTypes;
+ if (op == EOpConstructStruct)
+ memberTypes = type.getStruct()->begin();
+
+ TType elementType;
+ if (type.isArray()) {
+ TType dereferenced(type, 0);
+ elementType.shallowCopy(dereferenced);
+ } else
+ elementType.shallowCopy(type);
+
+ bool singleArg;
+ if (aggrNode) {
+ if (aggrNode->getOp() != EOpNull)
+ singleArg = true;
+ else
+ singleArg = false;
+ } else
+ singleArg = true;
+
+ TIntermTyped *newNode;
+ if (singleArg) {
+ // If structure constructor or array constructor is being called
+ // for only one parameter inside the structure, we need to call constructAggregate function once.
+ if (type.isArray())
+ newNode = constructAggregate(node, elementType, 1, node->getLoc());
+ else if (op == EOpConstructStruct)
+ newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc());
+ else
+ newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false);
+
+ if (newNode && (type.isArray() || op == EOpConstructStruct))
+ newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc);
+
+ return newNode;
+ }
+
+ //
+ // Handle list of arguments.
+ //
+ TIntermSequence &sequenceVector = aggrNode->getSequence(); // Stores the information about the parameter to the constructor
+ // if the structure constructor contains more than one parameter, then construct
+ // each parameter
+
+ int paramCount = 0; // keeps track of the constructor parameter number being checked
+
+ // for each parameter to the constructor call, check to see if the right type is passed or convert them
+ // to the right type if possible (and allowed).
+ // for structure constructors, just check if the right type is passed, no conversion is allowed.
+ for (TIntermSequence::iterator p = sequenceVector.begin();
+ p != sequenceVector.end(); p++, paramCount++) {
+ if (type.isArray())
+ newNode = constructAggregate(*p, elementType, paramCount+1, node->getLoc());
+ else if (op == EOpConstructStruct)
+ newNode = constructAggregate(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc());
+ else
+ newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true);
+
+ if (newNode)
+ *p = newNode;
+ else
+ return nullptr;
+ }
+
+ return intermediate.setAggregateOperator(aggrNode, op, type, loc);
+}
+
+// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
+// for the parameter to the constructor (passed to this function). Essentially, it converts
+// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a
+// float, then float is converted to int.
+//
+// Returns nullptr for an error or the constructed node.
+//
+TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermTyped* node, const TSourceLoc& loc,
+ bool subset)
+{
+ // If we are changing a matrix in both domain of basic type and to a non matrix,
+ // do the shape change first (by default, below, basic type is changed before shape).
+ // This avoids requesting a matrix of a new type that is going to be discarded anyway.
+ // TODO: This could be generalized to more type combinations, but that would require
+ // more extensive testing and full algorithm rework. For now, the need to do two changes makes
+ // the recursive call work, and avoids the most egregious case of creating integer matrices.
+ if (node->getType().isMatrix() && (type.isScalar() || type.isVector()) &&
+ type.isFloatingDomain() != node->getType().isFloatingDomain()) {
+ TType transitionType(node->getBasicType(), glslang::EvqTemporary, type.getVectorSize(), 0, 0, node->isVector());
+ TOperator transitionOp = intermediate.mapTypeToConstructorOp(transitionType);
+ node = constructBuiltIn(transitionType, transitionOp, node, loc, false);
+ }
+
+ TIntermTyped* newNode;
+ TOperator basicOp;
+
+ //
+ // First, convert types as needed.
+ //
+ switch (op) {
+ case EOpConstructVec2:
+ case EOpConstructVec3:
+ case EOpConstructVec4:
+ case EOpConstructMat2x2:
+ case EOpConstructMat2x3:
+ case EOpConstructMat2x4:
+ case EOpConstructMat3x2:
+ case EOpConstructMat3x3:
+ case EOpConstructMat3x4:
+ case EOpConstructMat4x2:
+ case EOpConstructMat4x3:
+ case EOpConstructMat4x4:
+ case EOpConstructFloat:
+ basicOp = EOpConstructFloat;
+ break;
+
+ case EOpConstructIVec2:
+ case EOpConstructIVec3:
+ case EOpConstructIVec4:
+ case EOpConstructInt:
+ basicOp = EOpConstructInt;
+ break;
+
+ case EOpConstructUVec2:
+ if (node->getType().getBasicType() == EbtReference) {
+ requireExtensions(loc, 1, &E_GL_EXT_buffer_reference_uvec2, "reference conversion to uvec2");
+ TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUvec2, true, node,
+ type);
+ return newNode;
+ }
+ case EOpConstructUVec3:
+ case EOpConstructUVec4:
+ case EOpConstructUint:
+ basicOp = EOpConstructUint;
+ break;
+
+ case EOpConstructBVec2:
+ case EOpConstructBVec3:
+ case EOpConstructBVec4:
+ case EOpConstructBool:
+ basicOp = EOpConstructBool;
+ break;
+
+#ifndef GLSLANG_WEB
+
+ case EOpConstructDVec2:
+ case EOpConstructDVec3:
+ case EOpConstructDVec4:
+ case EOpConstructDMat2x2:
+ case EOpConstructDMat2x3:
+ case EOpConstructDMat2x4:
+ case EOpConstructDMat3x2:
+ case EOpConstructDMat3x3:
+ case EOpConstructDMat3x4:
+ case EOpConstructDMat4x2:
+ case EOpConstructDMat4x3:
+ case EOpConstructDMat4x4:
+ case EOpConstructDouble:
+ basicOp = EOpConstructDouble;
+ break;
+
+ case EOpConstructF16Vec2:
+ case EOpConstructF16Vec3:
+ case EOpConstructF16Vec4:
+ case EOpConstructF16Mat2x2:
+ case EOpConstructF16Mat2x3:
+ case EOpConstructF16Mat2x4:
+ case EOpConstructF16Mat3x2:
+ case EOpConstructF16Mat3x3:
+ case EOpConstructF16Mat3x4:
+ case EOpConstructF16Mat4x2:
+ case EOpConstructF16Mat4x3:
+ case EOpConstructF16Mat4x4:
+ case EOpConstructFloat16:
+ basicOp = EOpConstructFloat16;
+ // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
+ // so construct a 32-bit type and convert
+ if (!intermediate.getArithemeticFloat16Enabled()) {
+ TType tempType(EbtFloat, EvqTemporary, type.getVectorSize());
+ newNode = node;
+ if (tempType != newNode->getType()) {
+ TOperator aggregateOp;
+ if (op == EOpConstructFloat16)
+ aggregateOp = EOpConstructFloat;
+ else
+ aggregateOp = (TOperator)(EOpConstructVec2 + op - EOpConstructF16Vec2);
+ newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc());
+ }
+ newNode = intermediate.addConversion(EbtFloat16, newNode);
+ return newNode;
+ }
+ break;
+
+ case EOpConstructI8Vec2:
+ case EOpConstructI8Vec3:
+ case EOpConstructI8Vec4:
+ case EOpConstructInt8:
+ basicOp = EOpConstructInt8;
+ // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
+ // so construct a 32-bit type and convert
+ if (!intermediate.getArithemeticInt8Enabled()) {
+ TType tempType(EbtInt, EvqTemporary, type.getVectorSize());
+ newNode = node;
+ if (tempType != newNode->getType()) {
+ TOperator aggregateOp;
+ if (op == EOpConstructInt8)
+ aggregateOp = EOpConstructInt;
+ else
+ aggregateOp = (TOperator)(EOpConstructIVec2 + op - EOpConstructI8Vec2);
+ newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc());
+ }
+ newNode = intermediate.addConversion(EbtInt8, newNode);
+ return newNode;
+ }
+ break;
+
+ case EOpConstructU8Vec2:
+ case EOpConstructU8Vec3:
+ case EOpConstructU8Vec4:
+ case EOpConstructUint8:
+ basicOp = EOpConstructUint8;
+ // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
+ // so construct a 32-bit type and convert
+ if (!intermediate.getArithemeticInt8Enabled()) {
+ TType tempType(EbtUint, EvqTemporary, type.getVectorSize());
+ newNode = node;
+ if (tempType != newNode->getType()) {
+ TOperator aggregateOp;
+ if (op == EOpConstructUint8)
+ aggregateOp = EOpConstructUint;
+ else
+ aggregateOp = (TOperator)(EOpConstructUVec2 + op - EOpConstructU8Vec2);
+ newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc());
+ }
+ newNode = intermediate.addConversion(EbtUint8, newNode);
+ return newNode;
+ }
+ break;
+
+ case EOpConstructI16Vec2:
+ case EOpConstructI16Vec3:
+ case EOpConstructI16Vec4:
+ case EOpConstructInt16:
+ basicOp = EOpConstructInt16;
+ // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
+ // so construct a 32-bit type and convert
+ if (!intermediate.getArithemeticInt16Enabled()) {
+ TType tempType(EbtInt, EvqTemporary, type.getVectorSize());
+ newNode = node;
+ if (tempType != newNode->getType()) {
+ TOperator aggregateOp;
+ if (op == EOpConstructInt16)
+ aggregateOp = EOpConstructInt;
+ else
+ aggregateOp = (TOperator)(EOpConstructIVec2 + op - EOpConstructI16Vec2);
+ newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc());
+ }
+ newNode = intermediate.addConversion(EbtInt16, newNode);
+ return newNode;
+ }
+ break;
+
+ case EOpConstructU16Vec2:
+ case EOpConstructU16Vec3:
+ case EOpConstructU16Vec4:
+ case EOpConstructUint16:
+ basicOp = EOpConstructUint16;
+ // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
+ // so construct a 32-bit type and convert
+ if (!intermediate.getArithemeticInt16Enabled()) {
+ TType tempType(EbtUint, EvqTemporary, type.getVectorSize());
+ newNode = node;
+ if (tempType != newNode->getType()) {
+ TOperator aggregateOp;
+ if (op == EOpConstructUint16)
+ aggregateOp = EOpConstructUint;
+ else
+ aggregateOp = (TOperator)(EOpConstructUVec2 + op - EOpConstructU16Vec2);
+ newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc());
+ }
+ newNode = intermediate.addConversion(EbtUint16, newNode);
+ return newNode;
+ }
+ break;
+
+ case EOpConstructI64Vec2:
+ case EOpConstructI64Vec3:
+ case EOpConstructI64Vec4:
+ case EOpConstructInt64:
+ basicOp = EOpConstructInt64;
+ break;
+
+ case EOpConstructUint64:
+ if (type.isScalar() && node->getType().isReference()) {
+ TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUint64, true, node, type);
+ return newNode;
+ }
+ // fall through
+ case EOpConstructU64Vec2:
+ case EOpConstructU64Vec3:
+ case EOpConstructU64Vec4:
+ basicOp = EOpConstructUint64;
+ break;
+
+ case EOpConstructNonuniform:
+ // Make a nonuniform copy of node
+ newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpCopyObject, true, node, type);
+ return newNode;
+
+ case EOpConstructReference:
+ // construct reference from reference
+ if (node->getType().isReference()) {
+ newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConstructReference, true, node, type);
+ return newNode;
+ // construct reference from uint64
+ } else if (node->getType().isScalar() && node->getType().getBasicType() == EbtUint64) {
+ TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUint64ToPtr, true, node,
+ type);
+ return newNode;
+ // construct reference from uvec2
+ } else if (node->getType().isVector() && node->getType().getBasicType() == EbtUint &&
+ node->getVectorSize() == 2) {
+ requireExtensions(loc, 1, &E_GL_EXT_buffer_reference_uvec2, "uvec2 conversion to reference");
+ TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUvec2ToPtr, true, node,
+ type);
+ return newNode;
+ } else {
+ return nullptr;
+ }
+
+ case EOpConstructCooperativeMatrix:
+ if (!node->getType().isCoopMat()) {
+ if (type.getBasicType() != node->getType().getBasicType()) {
+ node = intermediate.addConversion(type.getBasicType(), node);
+ }
+ node = intermediate.setAggregateOperator(node, EOpConstructCooperativeMatrix, type, node->getLoc());
+ } else {
+ TOperator op = EOpNull;
+ switch (type.getBasicType()) {
+ default:
+ assert(0);
+ break;
+ case EbtInt:
+ switch (node->getType().getBasicType()) {
+ case EbtFloat: op = EOpConvFloatToInt; break;
+ case EbtFloat16: op = EOpConvFloat16ToInt; break;
+ case EbtUint8: op = EOpConvUint8ToInt; break;
+ case EbtInt8: op = EOpConvInt8ToInt; break;
+ case EbtUint: op = EOpConvUintToInt; break;
+ default: assert(0);
+ }
+ break;
+ case EbtUint:
+ switch (node->getType().getBasicType()) {
+ case EbtFloat: op = EOpConvFloatToUint; break;
+ case EbtFloat16: op = EOpConvFloat16ToUint; break;
+ case EbtUint8: op = EOpConvUint8ToUint; break;
+ case EbtInt8: op = EOpConvInt8ToUint; break;
+ case EbtInt: op = EOpConvIntToUint; break;
+ case EbtUint: op = EOpConvUintToInt8; break;
+ default: assert(0);
+ }
+ break;
+ case EbtInt8:
+ switch (node->getType().getBasicType()) {
+ case EbtFloat: op = EOpConvFloatToInt8; break;
+ case EbtFloat16: op = EOpConvFloat16ToInt8; break;
+ case EbtUint8: op = EOpConvUint8ToInt8; break;
+ case EbtInt: op = EOpConvIntToInt8; break;
+ case EbtUint: op = EOpConvUintToInt8; break;
+ default: assert(0);
+ }
+ break;
+ case EbtUint8:
+ switch (node->getType().getBasicType()) {
+ case EbtFloat: op = EOpConvFloatToUint8; break;
+ case EbtFloat16: op = EOpConvFloat16ToUint8; break;
+ case EbtInt8: op = EOpConvInt8ToUint8; break;
+ case EbtInt: op = EOpConvIntToUint8; break;
+ case EbtUint: op = EOpConvUintToUint8; break;
+ default: assert(0);
+ }
+ break;
+ case EbtFloat:
+ switch (node->getType().getBasicType()) {
+ case EbtFloat16: op = EOpConvFloat16ToFloat; break;
+ case EbtInt8: op = EOpConvInt8ToFloat; break;
+ case EbtUint8: op = EOpConvUint8ToFloat; break;
+ case EbtInt: op = EOpConvIntToFloat; break;
+ case EbtUint: op = EOpConvUintToFloat; break;
+ default: assert(0);
+ }
+ break;
+ case EbtFloat16:
+ switch (node->getType().getBasicType()) {
+ case EbtFloat: op = EOpConvFloatToFloat16; break;
+ case EbtInt8: op = EOpConvInt8ToFloat16; break;
+ case EbtUint8: op = EOpConvUint8ToFloat16; break;
+ case EbtInt: op = EOpConvIntToFloat16; break;
+ case EbtUint: op = EOpConvUintToFloat16; break;
+ default: assert(0);
+ }
+ break;
+ }
+
+ node = intermediate.addUnaryNode(op, node, node->getLoc(), type);
+ // If it's a (non-specialization) constant, it must be folded.
+ if (node->getAsUnaryNode()->getOperand()->getAsConstantUnion())
+ return node->getAsUnaryNode()->getOperand()->getAsConstantUnion()->fold(op, node->getType());
+ }
+
+ return node;
+
+#endif // GLSLANG_WEB
+
+ default:
+ error(loc, "unsupported construction", "", "");
+
+ return nullptr;
+ }
+ newNode = intermediate.addUnaryMath(basicOp, node, node->getLoc());
+ if (newNode == nullptr) {
+ error(loc, "can't convert", "constructor", "");
+ return nullptr;
+ }
+
+ //
+ // Now, if there still isn't an operation to do the construction, and we need one, add one.
+ //
+
+ // Otherwise, skip out early.
+ if (subset || (newNode != node && newNode->getType() == type))
+ return newNode;
+
+ // setAggregateOperator will insert a new node for the constructor, as needed.
+ return intermediate.setAggregateOperator(newNode, op, type, loc);
+}
+
+// This function tests for the type of the parameters to the structure or array constructor. Raises
+// an error message if the expected type does not match the parameter passed to the constructor.
+//
+// Returns nullptr for an error or the input node itself if the expected and the given parameter types match.
+//
+TIntermTyped* TParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, const TSourceLoc& loc)
+{
+ TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped());
+ if (! converted || converted->getType() != type) {
+ error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
+ node->getAsTyped()->getType().getCompleteString().c_str(), type.getCompleteString().c_str());
+
+ return nullptr;
+ }
+
+ return converted;
+}
+
+// If a memory qualifier is present in 'to', also make it present in 'from'.
+void TParseContext::inheritMemoryQualifiers(const TQualifier& from, TQualifier& to)
+{
+#ifndef GLSLANG_WEB
+ if (from.isReadOnly())
+ to.readonly = from.readonly;
+ if (from.isWriteOnly())
+ to.writeonly = from.writeonly;
+ if (from.coherent)
+ to.coherent = from.coherent;
+ if (from.volatil)
+ to.volatil = from.volatil;
+ if (from.restrict)
+ to.restrict = from.restrict;
+#endif
+}
+
+//
+// Do everything needed to add an interface block.
+//
+void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName,
+ TArraySizes* arraySizes)
+{
+ blockStageIoCheck(loc, currentBlockQualifier);
+ blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr);
+ if (arraySizes != nullptr) {
+ arraySizesCheck(loc, currentBlockQualifier, arraySizes, nullptr, false);
+ arrayOfArrayVersionCheck(loc, arraySizes);
+ if (arraySizes->getNumDims() > 1)
+ requireProfile(loc, ~EEsProfile, "array-of-array of block");
+ }
+
+ // Inherit and check member storage qualifiers WRT to the block-level qualifier.
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TType& memberType = *typeList[member].type;
+ TQualifier& memberQualifier = memberType.getQualifier();
+ const TSourceLoc& memberLoc = typeList[member].loc;
+ globalQualifierFixCheck(memberLoc, memberQualifier);
+ if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage)
+ error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), "");
+ memberQualifier.storage = currentBlockQualifier.storage;
+#ifndef GLSLANG_WEB
+ inheritMemoryQualifiers(currentBlockQualifier, memberQualifier);
+ if (currentBlockQualifier.perPrimitiveNV)
+ memberQualifier.perPrimitiveNV = currentBlockQualifier.perPrimitiveNV;
+ if (currentBlockQualifier.perViewNV)
+ memberQualifier.perViewNV = currentBlockQualifier.perViewNV;
+ if (currentBlockQualifier.perTaskNV)
+ memberQualifier.perTaskNV = currentBlockQualifier.perTaskNV;
+#endif
+ if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary()))
+ error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), "");
+ if (memberType.isArray())
+ arraySizesCheck(memberLoc, currentBlockQualifier, memberType.getArraySizes(), nullptr, member == typeList.size() - 1);
+ if (memberQualifier.hasOffset()) {
+ if (spvVersion.spv == 0) {
+ requireProfile(memberLoc, ~EEsProfile, "offset on block member");
+ profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "offset on block member");
+ }
+ }
+
+ if (memberType.containsOpaque())
+ error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), "");
+
+ if (memberType.containsCoopMat())
+ error(memberLoc, "member of block cannot be or contain a cooperative matrix type", typeList[member].type->getFieldName().c_str(), "");
+ }
+
+ // This might be a redeclaration of a built-in block. If so, redeclareBuiltinBlock() will
+ // do all the rest.
+ if (! symbolTable.atBuiltInLevel() && builtInName(*blockName)) {
+ redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes);
+ return;
+ }
+
+ // Not a redeclaration of a built-in; check that all names are user names.
+ reservedErrorCheck(loc, *blockName);
+ if (instanceName)
+ reservedErrorCheck(loc, *instanceName);
+ for (unsigned int member = 0; member < typeList.size(); ++member)
+ reservedErrorCheck(typeList[member].loc, typeList[member].type->getFieldName());
+
+ // Make default block qualification, and adjust the member qualifications
+
+ TQualifier defaultQualification;
+ switch (currentBlockQualifier.storage) {
+ case EvqUniform: defaultQualification = globalUniformDefaults; break;
+ case EvqBuffer: defaultQualification = globalBufferDefaults; break;
+ case EvqVaryingIn: defaultQualification = globalInputDefaults; break;
+ case EvqVaryingOut: defaultQualification = globalOutputDefaults; break;
+ default: defaultQualification.clear(); break;
+ }
+
+ // Special case for "push_constant uniform", which has a default of std430,
+ // contrary to normal uniform defaults, and can't have a default tracked for it.
+ if ((currentBlockQualifier.isPushConstant() && !currentBlockQualifier.hasPacking()) ||
+ (currentBlockQualifier.isShaderRecordNV() && !currentBlockQualifier.hasPacking()))
+ currentBlockQualifier.layoutPacking = ElpStd430;
+
+ // Special case for "taskNV in/out", which has a default of std430,
+ if (currentBlockQualifier.isTaskMemory() && !currentBlockQualifier.hasPacking())
+ currentBlockQualifier.layoutPacking = ElpStd430;
+
+ // fix and check for member layout qualifiers
+
+ mergeObjectLayoutQualifiers(defaultQualification, currentBlockQualifier, true);
+
+ // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
+ if (currentBlockQualifier.hasAlign()) {
+ if (defaultQualification.layoutPacking != ElpStd140 &&
+ defaultQualification.layoutPacking != ElpStd430 &&
+ defaultQualification.layoutPacking != ElpScalar) {
+ error(loc, "can only be used with std140, std430, or scalar layout packing", "align", "");
+ defaultQualification.layoutAlign = -1;
+ }
+ }
+
+ bool memberWithLocation = false;
+ bool memberWithoutLocation = false;
+ bool memberWithPerViewQualifier = false;
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ const TSourceLoc& memberLoc = typeList[member].loc;
+#ifndef GLSLANG_WEB
+ if (memberQualifier.hasStream()) {
+ if (defaultQualification.layoutStream != memberQualifier.layoutStream)
+ error(memberLoc, "member cannot contradict block", "stream", "");
+ }
+
+ // "This includes a block's inheritance of the
+ // current global default buffer, a block member's inheritance of the block's
+ // buffer, and the requirement that any *xfb_buffer* declared on a block
+ // member must match the buffer inherited from the block."
+ if (memberQualifier.hasXfbBuffer()) {
+ if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer)
+ error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", "");
+ }
+#endif
+
+ if (memberQualifier.hasPacking())
+ error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), "");
+ if (memberQualifier.hasLocation()) {
+ const char* feature = "location on block member";
+ switch (currentBlockQualifier.storage) {
+#ifndef GLSLANG_WEB
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ requireProfile(memberLoc, ECoreProfile | ECompatibilityProfile | EEsProfile, feature);
+ profileRequires(memberLoc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
+ profileRequires(memberLoc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature);
+ memberWithLocation = true;
+ break;
+#endif
+ default:
+ error(memberLoc, "can only use in an in/out block", feature, "");
+ break;
+ }
+ } else
+ memberWithoutLocation = true;
+
+ // "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts."
+ // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
+ if (memberQualifier.hasAlign() || memberQualifier.hasOffset()) {
+ if (defaultQualification.layoutPacking != ElpStd140 &&
+ defaultQualification.layoutPacking != ElpStd430 &&
+ defaultQualification.layoutPacking != ElpScalar)
+ error(memberLoc, "can only be used with std140, std430, or scalar layout packing", "offset/align", "");
+ }
+
+ if (memberQualifier.isPerView()) {
+ memberWithPerViewQualifier = true;
+ }
+
+ TQualifier newMemberQualification = defaultQualification;
+ mergeQualifiers(memberLoc, newMemberQualification, memberQualifier, false);
+ memberQualifier = newMemberQualification;
+ }
+
+ layoutMemberLocationArrayCheck(loc, memberWithLocation, arraySizes);
+
+#ifndef GLSLANG_WEB
+ // Ensure that the block has an XfbBuffer assigned. This is needed
+ // because if the block has a XfbOffset assigned, then it is
+ // assumed that it has implicitly assigned the current global
+ // XfbBuffer, and because it's members need to be assigned a
+ // XfbOffset if they lack it.
+ if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) {
+ if (!currentBlockQualifier.hasXfbBuffer() && currentBlockQualifier.hasXfbOffset())
+ currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
+ }
+#endif
+
+ // Process the members
+ fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
+ fixXfbOffsets(currentBlockQualifier, typeList);
+ fixBlockUniformOffsets(currentBlockQualifier, typeList);
+ for (unsigned int member = 0; member < typeList.size(); ++member)
+ layoutTypeCheck(typeList[member].loc, *typeList[member].type);
+
+#ifndef GLSLANG_WEB
+ if (memberWithPerViewQualifier) {
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ checkAndResizeMeshViewDim(typeList[member].loc, *typeList[member].type, /*isBlockMember*/ true);
+ }
+ }
+#endif
+
+ // reverse merge, so that currentBlockQualifier now has all layout information
+ // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers)
+ mergeObjectLayoutQualifiers(currentBlockQualifier, defaultQualification, true);
+
+ //
+ // Build and add the interface block as a new type named 'blockName'
+ //
+
+ TType blockType(&typeList, *blockName, currentBlockQualifier);
+ if (arraySizes != nullptr)
+ blockType.transferArraySizes(arraySizes);
+
+#ifndef GLSLANG_WEB
+ if (arraySizes == nullptr)
+ ioArrayCheck(loc, blockType, instanceName ? *instanceName : *blockName);
+ if (currentBlockQualifier.hasBufferReference()) {
+
+ if (currentBlockQualifier.storage != EvqBuffer)
+ error(loc, "can only be used with buffer", "buffer_reference", "");
+
+ // Create the block reference type. If it was forward-declared, detect that
+ // as a referent struct type with no members. Replace the referent type with
+ // blockType.
+ TType blockNameType(EbtReference, blockType, *blockName);
+ TVariable* blockNameVar = new TVariable(blockName, blockNameType, true);
+ if (! symbolTable.insert(*blockNameVar)) {
+ TSymbol* existingName = symbolTable.find(*blockName);
+ if (existingName->getType().isReference() &&
+ existingName->getType().getReferentType()->getStruct() &&
+ existingName->getType().getReferentType()->getStruct()->size() == 0 &&
+ existingName->getType().getQualifier().storage == blockType.getQualifier().storage) {
+ existingName->getType().getReferentType()->deepCopy(blockType);
+ } else {
+ error(loc, "block name cannot be redefined", blockName->c_str(), "");
+ }
+ }
+ if (!instanceName) {
+ return;
+ }
+ } else
+#endif
+ {
+ //
+ // Don't make a user-defined type out of block name; that will cause an error
+ // if the same block name gets reused in a different interface.
+ //
+ // "Block names have no other use within a shader
+ // beyond interface matching; it is a compile-time error to use a block name at global scope for anything
+ // other than as a block name (e.g., use of a block name for a global variable name or function name is
+ // currently reserved)."
+ //
+ // Use the symbol table to prevent normal reuse of the block's name, as a variable entry,
+ // whose type is EbtBlock, but without all the structure; that will come from the type
+ // the instances point to.
+ //
+ TType blockNameType(EbtBlock, blockType.getQualifier().storage);
+ TVariable* blockNameVar = new TVariable(blockName, blockNameType);
+ if (! symbolTable.insert(*blockNameVar)) {
+ TSymbol* existingName = symbolTable.find(*blockName);
+ if (existingName->getType().getBasicType() == EbtBlock) {
+ if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) {
+ error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString());
+ return;
+ }
+ } else {
+ error(loc, "block name cannot redefine a non-block name", blockName->c_str(), "");
+ return;
+ }
+ }
+ }
+
+ // Add the variable, as anonymous or named instanceName.
+ // Make an anonymous variable if no name was provided.
+ if (! instanceName)
+ instanceName = NewPoolTString("");
+
+ TVariable& variable = *new TVariable(instanceName, blockType);
+ if (! symbolTable.insert(variable)) {
+ if (*instanceName == "")
+ error(loc, "nameless block contains a member that already has a name at global scope", blockName->c_str(), "");
+ else
+ error(loc, "block instance name redefinition", variable.getName().c_str(), "");
+
+ return;
+ }
+
+ // Check for general layout qualifier errors
+ layoutObjectCheck(loc, variable);
+
+#ifndef GLSLANG_WEB
+ // fix up
+ if (isIoResizeArray(blockType)) {
+ ioArraySymbolResizeList.push_back(&variable);
+ checkIoArraysConsistency(loc, true);
+ } else
+ fixIoArraySize(loc, variable.getWritableType());
+#endif
+
+ // Save it in the AST for linker use.
+ trackLinkage(variable);
+}
+
+// Do all block-declaration checking regarding the combination of in/out/uniform/buffer
+// with a particular stage.
+void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
+{
+ switch (qualifier.storage) {
+ case EvqUniform:
+ profileRequires(loc, EEsProfile, 300, nullptr, "uniform block");
+ profileRequires(loc, ENoProfile, 140, E_GL_ARB_uniform_buffer_object, "uniform block");
+ if (currentBlockQualifier.layoutPacking == ElpStd430 && ! currentBlockQualifier.isPushConstant())
+ requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "std430 requires the buffer storage qualifier");
+ break;
+ case EvqBuffer:
+ requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "buffer block");
+ profileRequires(loc, EEsProfile, 310, nullptr, "buffer block");
+ break;
+ case EvqVaryingIn:
+ profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "input block");
+ // It is a compile-time error to have an input block in a vertex shader or an output block in a fragment shader
+ // "Compute shaders do not permit user-defined input variables..."
+ requireStage(loc, (EShLanguageMask)(EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask|
+ EShLangFragmentMask|EShLangMeshNVMask), "input block");
+ if (language == EShLangFragment) {
+ profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "fragment input block");
+ } else if (language == EShLangMeshNV && ! qualifier.isTaskMemory()) {
+ error(loc, "input blocks cannot be used in a mesh shader", "out", "");
+ }
+ break;
+ case EvqVaryingOut:
+ profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "output block");
+ requireStage(loc, (EShLanguageMask)(EShLangVertexMask|EShLangTessControlMask|EShLangTessEvaluationMask|
+ EShLangGeometryMask|EShLangMeshNVMask|EShLangTaskNVMask), "output block");
+ // ES 310 can have a block before shader_io is turned on, so skip this test for built-ins
+ if (language == EShLangVertex && ! parsingBuiltins) {
+ profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "vertex output block");
+ } else if (language == EShLangMeshNV && qualifier.isTaskMemory()) {
+ error(loc, "can only use on input blocks in mesh shader", "taskNV", "");
+ } else if (language == EShLangTaskNV && ! qualifier.isTaskMemory()) {
+ error(loc, "output blocks cannot be used in a task shader", "out", "");
+ }
+ break;
+#ifndef GLSLANG_WEB
+ case EvqPayloadNV:
+ profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV block");
+ requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask),
+ "rayPayloadNV block");
+ break;
+ case EvqPayloadInNV:
+ profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV block");
+ requireStage(loc, (EShLanguageMask)(EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask),
+ "rayPayloadInNV block");
+ break;
+ case EvqHitAttrNV:
+ profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV block");
+ requireStage(loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask), "hitAttributeNV block");
+ break;
+ case EvqCallableDataNV:
+ profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataNV block");
+ requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask),
+ "callableDataNV block");
+ break;
+ case EvqCallableDataInNV:
+ profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV block");
+ requireStage(loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV block");
+ break;
+#endif
+ default:
+ error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), "");
+ break;
+ }
+}
+
+// Do all block-declaration checking regarding its qualifiers.
+void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool /*instanceName*/)
+{
+ // The 4.5 specification says:
+ //
+ // interface-block :
+ // layout-qualifieropt interface-qualifier block-name { member-list } instance-nameopt ;
+ //
+ // interface-qualifier :
+ // in
+ // out
+ // patch in
+ // patch out
+ // uniform
+ // buffer
+ //
+ // Note however memory qualifiers aren't included, yet the specification also says
+ //
+ // "...memory qualifiers may also be used in the declaration of shader storage blocks..."
+
+ if (qualifier.isInterpolation())
+ error(loc, "cannot use interpolation qualifiers on an interface block", "flat/smooth/noperspective", "");
+ if (qualifier.centroid)
+ error(loc, "cannot use centroid qualifier on an interface block", "centroid", "");
+ if (qualifier.isSample())
+ error(loc, "cannot use sample qualifier on an interface block", "sample", "");
+ if (qualifier.invariant)
+ error(loc, "cannot use invariant qualifier on an interface block", "invariant", "");
+ if (qualifier.isPushConstant())
+ intermediate.addPushConstantCount();
+ if (qualifier.isShaderRecordNV())
+ intermediate.addShaderRecordNVCount();
+ if (qualifier.isTaskMemory())
+ intermediate.addTaskNVCount();
+}
+
+//
+// "For a block, this process applies to the entire block, or until the first member
+// is reached that has a location layout qualifier. When a block member is declared with a location
+// qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level
+// declaration. Subsequent members are again assigned consecutive locations, based on the newest location,
+// until the next member declared with a location qualifier. The values used for locations do not have to be
+// declared in increasing order."
+void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifier, TTypeList& typeList, bool memberWithLocation, bool memberWithoutLocation)
+{
+ // "If a block has no block-level location layout qualifier, it is required that either all or none of its members
+ // have a location layout qualifier, or a compile-time error results."
+ if (! qualifier.hasLocation() && memberWithLocation && memberWithoutLocation)
+ error(loc, "either the block needs a location, or all members need a location, or no members have a location", "location", "");
+ else {
+ if (memberWithLocation) {
+ // remove any block-level location and make it per *every* member
+ int nextLocation = 0; // by the rule above, initial value is not relevant
+ if (qualifier.hasAnyLocation()) {
+ nextLocation = qualifier.layoutLocation;
+ qualifier.layoutLocation = TQualifier::layoutLocationEnd;
+ if (qualifier.hasComponent()) {
+ // "It is a compile-time error to apply the *component* qualifier to a ... block"
+ error(loc, "cannot apply to a block", "component", "");
+ }
+ if (qualifier.hasIndex()) {
+ error(loc, "cannot apply to a block", "index", "");
+ }
+ }
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ const TSourceLoc& memberLoc = typeList[member].loc;
+ if (! memberQualifier.hasLocation()) {
+ if (nextLocation >= (int)TQualifier::layoutLocationEnd)
+ error(memberLoc, "location is too large", "location", "");
+ memberQualifier.layoutLocation = nextLocation;
+ memberQualifier.layoutComponent = TQualifier::layoutComponentEnd;
+ }
+ nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize(
+ *typeList[member].type, language);
+ }
+ }
+ }
+}
+
+void TParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList)
+{
+#ifndef GLSLANG_WEB
+ // "If a block is qualified with xfb_offset, all its
+ // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any
+ // members of that block not qualified with an xfb_offset will not be assigned transform feedback buffer
+ // offsets."
+
+ if (! qualifier.hasXfbBuffer() || ! qualifier.hasXfbOffset())
+ return;
+
+ int nextOffset = qualifier.layoutXfbOffset;
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ bool contains64BitType = false;
+ bool contains32BitType = false;
+ bool contains16BitType = false;
+ int memberSize = intermediate.computeTypeXfbSize(*typeList[member].type, contains64BitType, contains32BitType, contains16BitType);
+ // see if we need to auto-assign an offset to this member
+ if (! memberQualifier.hasXfbOffset()) {
+ // "if applied to an aggregate containing a double or 64-bit integer, the offset must also be a multiple of 8"
+ if (contains64BitType)
+ RoundToPow2(nextOffset, 8);
+ else if (contains32BitType)
+ RoundToPow2(nextOffset, 4);
+ else if (contains16BitType)
+ RoundToPow2(nextOffset, 2);
+ memberQualifier.layoutXfbOffset = nextOffset;
+ } else
+ nextOffset = memberQualifier.layoutXfbOffset;
+ nextOffset += memberSize;
+ }
+
+ // The above gave all block members an offset, so we can take it off the block now,
+ // which will avoid double counting the offset usage.
+ qualifier.layoutXfbOffset = TQualifier::layoutXfbOffsetEnd;
+#endif
+}
+
+// Calculate and save the offset of each block member, using the recursively
+// defined block offset rules and the user-provided offset and align.
+//
+// Also, compute and save the total size of the block. For the block's size, arrayness
+// is not taken into account, as each element is backed by a separate buffer.
+//
+void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList)
+{
+ if (!qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory())
+ return;
+ if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar)
+ return;
+
+ int offset = 0;
+ int memberSize;
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ const TSourceLoc& memberLoc = typeList[member].loc;
+
+ // "When align is applied to an array, it effects only the start of the array, not the array's internal stride."
+
+ // modify just the children's view of matrix layout, if there is one for this member
+ TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix;
+ int dummyStride;
+ int memberAlignment = intermediate.getMemberAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking,
+ subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor);
+ if (memberQualifier.hasOffset()) {
+ // "The specified offset must be a multiple
+ // of the base alignment of the type of the block member it qualifies, or a compile-time error results."
+ if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment))
+ error(memberLoc, "must be a multiple of the member's alignment", "offset", "");
+
+ // GLSL: "It is a compile-time error to specify an offset that is smaller than the offset of the previous
+ // member in the block or that lies within the previous member of the block"
+ if (spvVersion.spv == 0) {
+ if (memberQualifier.layoutOffset < offset)
+ error(memberLoc, "cannot lie in previous members", "offset", "");
+
+ // "The offset qualifier forces the qualified member to start at or after the specified
+ // integral-constant expression, which will be its byte offset from the beginning of the buffer.
+ // "The actual offset of a member is computed as
+ // follows: If offset was declared, start with that offset, otherwise start with the next available offset."
+ offset = std::max(offset, memberQualifier.layoutOffset);
+ } else {
+ // TODO: Vulkan: "It is a compile-time error to have any offset, explicit or assigned,
+ // that lies within another member of the block."
+
+ offset = memberQualifier.layoutOffset;
+ }
+ }
+
+ // "The actual alignment of a member will be the greater of the specified align alignment and the standard
+ // (e.g., std140) base alignment for the member's type."
+ if (memberQualifier.hasAlign())
+ memberAlignment = std::max(memberAlignment, memberQualifier.layoutAlign);
+
+ // "If the resulting offset is not a multiple of the actual alignment,
+ // increase it to the first offset that is a multiple of
+ // the actual alignment."
+ RoundToPow2(offset, memberAlignment);
+ typeList[member].type->getQualifier().layoutOffset = offset;
+ offset += memberSize;
+ }
+}
+
+// For an identifier that is already declared, add more qualification to it.
+void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier)
+{
+ TSymbol* symbol = symbolTable.find(identifier);
+
+ // A forward declaration of a block reference looks to the grammar like adding
+ // a qualifier to an existing symbol. Detect this and create the block reference
+ // type with an empty type list, which will be filled in later in
+ // TParseContext::declareBlock.
+ if (!symbol && qualifier.hasBufferReference()) {
+ TTypeList typeList;
+ TType blockType(&typeList, identifier, qualifier);;
+ TType blockNameType(EbtReference, blockType, identifier);
+ TVariable* blockNameVar = new TVariable(&identifier, blockNameType, true);
+ if (! symbolTable.insert(*blockNameVar)) {
+ error(loc, "block name cannot redefine a non-block name", blockName->c_str(), "");
+ }
+ return;
+ }
+
+ if (! symbol) {
+ error(loc, "identifier not previously declared", identifier.c_str(), "");
+ return;
+ }
+ if (symbol->getAsFunction()) {
+ error(loc, "cannot re-qualify a function name", identifier.c_str(), "");
+ return;
+ }
+
+ if (qualifier.isAuxiliary() ||
+ qualifier.isMemory() ||
+ qualifier.isInterpolation() ||
+ qualifier.hasLayout() ||
+ qualifier.storage != EvqTemporary ||
+ qualifier.precision != EpqNone) {
+ error(loc, "cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable", identifier.c_str(), "");
+ return;
+ }
+
+ // For read-only built-ins, add a new symbol for holding the modified qualifier.
+ // This will bring up an entire block, if a block type has to be modified (e.g., gl_Position inside a block)
+ if (symbol->isReadOnly())
+ symbol = symbolTable.copyUp(symbol);
+
+ if (qualifier.invariant) {
+ if (intermediate.inIoAccessed(identifier))
+ error(loc, "cannot change qualification after use", "invariant", "");
+ symbol->getWritableType().getQualifier().invariant = true;
+ invariantCheck(loc, symbol->getType().getQualifier());
+ } else if (qualifier.isNoContraction()) {
+ if (intermediate.inIoAccessed(identifier))
+ error(loc, "cannot change qualification after use", "precise", "");
+ symbol->getWritableType().getQualifier().setNoContraction();
+ } else if (qualifier.specConstant) {
+ symbol->getWritableType().getQualifier().makeSpecConstant();
+ if (qualifier.hasSpecConstantId())
+ symbol->getWritableType().getQualifier().layoutSpecConstantId = qualifier.layoutSpecConstantId;
+ } else
+ warn(loc, "unknown requalification", "", "");
+}
+
+void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, TIdentifierList& identifiers)
+{
+ for (unsigned int i = 0; i < identifiers.size(); ++i)
+ addQualifierToExisting(loc, qualifier, *identifiers[i]);
+}
+
+// Make sure 'invariant' isn't being applied to a non-allowed object.
+void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qualifier)
+{
+ if (! qualifier.invariant)
+ return;
+
+ bool pipeOut = qualifier.isPipeOutput();
+ bool pipeIn = qualifier.isPipeInput();
+ if (version >= 300 || (!isEsProfile() && version >= 420)) {
+ if (! pipeOut)
+ error(loc, "can only apply to an output", "invariant", "");
+ } else {
+ if ((language == EShLangVertex && pipeIn) || (! pipeOut && ! pipeIn))
+ error(loc, "can only apply to an output, or to an input in a non-vertex stage\n", "invariant", "");
+ }
+}
+
+//
+// Updating default qualifier for the case of a declaration with just a qualifier,
+// no type, block, or identifier.
+//
+void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, const TPublicType& publicType)
+{
+#ifndef GLSLANG_WEB
+ if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) {
+ assert(language == EShLangTessControl || language == EShLangGeometry || language == EShLangMeshNV);
+ const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices";
+
+ if (publicType.qualifier.storage != EvqVaryingOut)
+ error(loc, "can only apply to 'out'", id, "");
+ if (! intermediate.setVertices(publicType.shaderQualifiers.vertices))
+ error(loc, "cannot change previously set layout value", id, "");
+
+ if (language == EShLangTessControl)
+ checkIoArraysConsistency(loc);
+ }
+ if (publicType.shaderQualifiers.primitives != TQualifier::layoutNotSet) {
+ assert(language == EShLangMeshNV);
+ const char* id = "max_primitives";
+
+ if (publicType.qualifier.storage != EvqVaryingOut)
+ error(loc, "can only apply to 'out'", id, "");
+ if (! intermediate.setPrimitives(publicType.shaderQualifiers.primitives))
+ error(loc, "cannot change previously set layout value", id, "");
+ }
+ if (publicType.shaderQualifiers.invocations != TQualifier::layoutNotSet) {
+ if (publicType.qualifier.storage != EvqVaryingIn)
+ error(loc, "can only apply to 'in'", "invocations", "");
+ if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations))
+ error(loc, "cannot change previously set layout value", "invocations", "");
+ }
+ if (publicType.shaderQualifiers.geometry != ElgNone) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ switch (publicType.shaderQualifiers.geometry) {
+ case ElgPoints:
+ case ElgLines:
+ case ElgLinesAdjacency:
+ case ElgTriangles:
+ case ElgTrianglesAdjacency:
+ case ElgQuads:
+ case ElgIsolines:
+ if (language == EShLangMeshNV) {
+ error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+ break;
+ }
+ if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) {
+ if (language == EShLangGeometry)
+ checkIoArraysConsistency(loc);
+ } else
+ error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+ break;
+ default:
+ error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+ }
+ } else if (publicType.qualifier.storage == EvqVaryingOut) {
+ switch (publicType.shaderQualifiers.geometry) {
+ case ElgLines:
+ case ElgTriangles:
+ if (language != EShLangMeshNV) {
+ error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+ break;
+ }
+ // Fall through
+ case ElgPoints:
+ case ElgLineStrip:
+ case ElgTriangleStrip:
+ if (! intermediate.setOutputPrimitive(publicType.shaderQualifiers.geometry))
+ error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+ break;
+ default:
+ error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+ }
+ } else
+ error(loc, "cannot apply to:", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), GetStorageQualifierString(publicType.qualifier.storage));
+ }
+ if (publicType.shaderQualifiers.spacing != EvsNone) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if (! intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing))
+ error(loc, "cannot change previously set vertex spacing", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), "");
+ } else
+ error(loc, "can only apply to 'in'", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), "");
+ }
+ if (publicType.shaderQualifiers.order != EvoNone) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if (! intermediate.setVertexOrder(publicType.shaderQualifiers.order))
+ error(loc, "cannot change previously set vertex order", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), "");
+ } else
+ error(loc, "can only apply to 'in'", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), "");
+ }
+ if (publicType.shaderQualifiers.pointMode) {
+ if (publicType.qualifier.storage == EvqVaryingIn)
+ intermediate.setPointMode();
+ else
+ error(loc, "can only apply to 'in'", "point_mode", "");
+ }
+#endif
+ for (int i = 0; i < 3; ++i) {
+ if (publicType.shaderQualifiers.localSizeNotDefault[i]) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if (! intermediate.setLocalSize(i, publicType.shaderQualifiers.localSize[i]))
+ error(loc, "cannot change previously set size", "local_size", "");
+ else {
+ int max = 0;
+ if (language == EShLangCompute) {
+ switch (i) {
+ case 0: max = resources.maxComputeWorkGroupSizeX; break;
+ case 1: max = resources.maxComputeWorkGroupSizeY; break;
+ case 2: max = resources.maxComputeWorkGroupSizeZ; break;
+ default: break;
+ }
+ if (intermediate.getLocalSize(i) > (unsigned int)max)
+ error(loc, "too large; see gl_MaxComputeWorkGroupSize", "local_size", "");
+ }
+#ifndef GLSLANG_WEB
+ else if (language == EShLangMeshNV) {
+ switch (i) {
+ case 0: max = resources.maxMeshWorkGroupSizeX_NV; break;
+ case 1: max = resources.maxMeshWorkGroupSizeY_NV; break;
+ case 2: max = resources.maxMeshWorkGroupSizeZ_NV; break;
+ default: break;
+ }
+ if (intermediate.getLocalSize(i) > (unsigned int)max)
+ error(loc, "too large; see gl_MaxMeshWorkGroupSizeNV", "local_size", "");
+ } else if (language == EShLangTaskNV) {
+ switch (i) {
+ case 0: max = resources.maxTaskWorkGroupSizeX_NV; break;
+ case 1: max = resources.maxTaskWorkGroupSizeY_NV; break;
+ case 2: max = resources.maxTaskWorkGroupSizeZ_NV; break;
+ default: break;
+ }
+ if (intermediate.getLocalSize(i) > (unsigned int)max)
+ error(loc, "too large; see gl_MaxTaskWorkGroupSizeNV", "local_size", "");
+ }
+#endif
+ else {
+ assert(0);
+ }
+
+ // Fix the existing constant gl_WorkGroupSize with this new information.
+ TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize");
+ if (workGroupSize != nullptr)
+ workGroupSize->getWritableConstArray()[i].setUConst(intermediate.getLocalSize(i));
+ }
+ } else
+ error(loc, "can only apply to 'in'", "local_size", "");
+ }
+ if (publicType.shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if (! intermediate.setLocalSizeSpecId(i, publicType.shaderQualifiers.localSizeSpecId[i]))
+ error(loc, "cannot change previously set size", "local_size", "");
+ } else
+ error(loc, "can only apply to 'in'", "local_size id", "");
+ // Set the workgroup built-in variable as a specialization constant
+ TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize");
+ if (workGroupSize != nullptr)
+ workGroupSize->getWritableType().getQualifier().specConstant = true;
+ }
+ }
+
+#ifndef GLSLANG_WEB
+ if (publicType.shaderQualifiers.earlyFragmentTests) {
+ if (publicType.qualifier.storage == EvqVaryingIn)
+ intermediate.setEarlyFragmentTests();
+ else
+ error(loc, "can only apply to 'in'", "early_fragment_tests", "");
+ }
+ if (publicType.shaderQualifiers.postDepthCoverage) {
+ if (publicType.qualifier.storage == EvqVaryingIn)
+ intermediate.setPostDepthCoverage();
+ else
+ error(loc, "can only apply to 'in'", "post_coverage_coverage", "");
+ }
+ if (publicType.shaderQualifiers.hasBlendEquation()) {
+ if (publicType.qualifier.storage != EvqVaryingOut)
+ error(loc, "can only apply to 'out'", "blend equation", "");
+ }
+ if (publicType.shaderQualifiers.interlockOrdering) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if (!intermediate.setInterlockOrdering(publicType.shaderQualifiers.interlockOrdering))
+ error(loc, "cannot change previously set fragment shader interlock ordering", TQualifier::getInterlockOrderingString(publicType.shaderQualifiers.interlockOrdering), "");
+ }
+ else
+ error(loc, "can only apply to 'in'", TQualifier::getInterlockOrderingString(publicType.shaderQualifiers.interlockOrdering), "");
+ }
+
+ if (publicType.shaderQualifiers.layoutDerivativeGroupQuads &&
+ publicType.shaderQualifiers.layoutDerivativeGroupLinear) {
+ error(loc, "cannot be both specified", "derivative_group_quadsNV and derivative_group_linearNV", "");
+ }
+
+ if (publicType.shaderQualifiers.layoutDerivativeGroupQuads) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if ((intermediate.getLocalSize(0) & 1) ||
+ (intermediate.getLocalSize(1) & 1))
+ error(loc, "requires local_size_x and local_size_y to be multiple of two", "derivative_group_quadsNV", "");
+ else
+ intermediate.setLayoutDerivativeMode(LayoutDerivativeGroupQuads);
+ }
+ else
+ error(loc, "can only apply to 'in'", "derivative_group_quadsNV", "");
+ }
+ if (publicType.shaderQualifiers.layoutDerivativeGroupLinear) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if((intermediate.getLocalSize(0) *
+ intermediate.getLocalSize(1) *
+ intermediate.getLocalSize(2)) % 4 != 0)
+ error(loc, "requires total group size to be multiple of four", "derivative_group_linearNV", "");
+ else
+ intermediate.setLayoutDerivativeMode(LayoutDerivativeGroupLinear);
+ }
+ else
+ error(loc, "can only apply to 'in'", "derivative_group_linearNV", "");
+ }
+ // Check mesh out array sizes, once all the necessary out qualifiers are defined.
+ if ((language == EShLangMeshNV) &&
+ (intermediate.getVertices() != TQualifier::layoutNotSet) &&
+ (intermediate.getPrimitives() != TQualifier::layoutNotSet) &&
+ (intermediate.getOutputPrimitive() != ElgNone))
+ {
+ checkIoArraysConsistency(loc);
+ }
+#endif
+ const TQualifier& qualifier = publicType.qualifier;
+
+ if (qualifier.isAuxiliary() ||
+ qualifier.isMemory() ||
+ qualifier.isInterpolation() ||
+ qualifier.precision != EpqNone)
+ error(loc, "cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type)", "qualifier", "");
+
+ // "The offset qualifier can only be used on block members of blocks..."
+ // "The align qualifier can only be used on blocks or block members..."
+ if (qualifier.hasOffset() ||
+ qualifier.hasAlign())
+ error(loc, "cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type)", "layout qualifier", "");
+
+ layoutQualifierCheck(loc, qualifier);
+
+ switch (qualifier.storage) {
+ case EvqUniform:
+ if (qualifier.hasMatrix())
+ globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix;
+ if (qualifier.hasPacking())
+ globalUniformDefaults.layoutPacking = qualifier.layoutPacking;
+ break;
+ case EvqBuffer:
+ if (qualifier.hasMatrix())
+ globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix;
+ if (qualifier.hasPacking())
+ globalBufferDefaults.layoutPacking = qualifier.layoutPacking;
+ break;
+ case EvqVaryingIn:
+ break;
+ case EvqVaryingOut:
+#ifndef GLSLANG_WEB
+ if (qualifier.hasStream())
+ globalOutputDefaults.layoutStream = qualifier.layoutStream;
+ if (qualifier.hasXfbBuffer())
+ globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer;
+ if (globalOutputDefaults.hasXfbBuffer() && qualifier.hasXfbStride()) {
+ if (! intermediate.setXfbBufferStride(globalOutputDefaults.layoutXfbBuffer, qualifier.layoutXfbStride))
+ error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer);
+ }
+#endif
+ break;
+ default:
+ error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", "");
+ return;
+ }
+
+ if (qualifier.hasBinding())
+ error(loc, "cannot declare a default, include a type or full declaration", "binding", "");
+ if (qualifier.hasAnyLocation())
+ error(loc, "cannot declare a default, use a full declaration", "location/component/index", "");
+ if (qualifier.hasXfbOffset())
+ error(loc, "cannot declare a default, use a full declaration", "xfb_offset", "");
+ if (qualifier.isPushConstant())
+ error(loc, "cannot declare a default, can only be used on a block", "push_constant", "");
+ if (qualifier.hasBufferReference())
+ error(loc, "cannot declare a default, can only be used on a block", "buffer_reference", "");
+ if (qualifier.hasSpecConstantId())
+ error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", "");
+ if (qualifier.isShaderRecordNV())
+ error(loc, "cannot declare a default, can only be used on a block", "shaderRecordNV", "");
+}
+
+//
+// Take the sequence of statements that has been built up since the last case/default,
+// put it on the list of top-level nodes for the current (inner-most) switch statement,
+// and follow that by the case/default we are on now. (See switch topology comment on
+// TIntermSwitch.)
+//
+void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode)
+{
+ TIntermSequence* switchSequence = switchSequenceStack.back();
+
+ if (statements) {
+ if (switchSequence->size() == 0)
+ error(statements->getLoc(), "cannot have statements before first case/default label", "switch", "");
+ statements->setOperator(EOpSequence);
+ switchSequence->push_back(statements);
+ }
+ if (branchNode) {
+ // check all previous cases for the same label (or both are 'default')
+ for (unsigned int s = 0; s < switchSequence->size(); ++s) {
+ TIntermBranch* prevBranch = (*switchSequence)[s]->getAsBranchNode();
+ if (prevBranch) {
+ TIntermTyped* prevExpression = prevBranch->getExpression();
+ TIntermTyped* newExpression = branchNode->getAsBranchNode()->getExpression();
+ if (prevExpression == nullptr && newExpression == nullptr)
+ error(branchNode->getLoc(), "duplicate label", "default", "");
+ else if (prevExpression != nullptr &&
+ newExpression != nullptr &&
+ prevExpression->getAsConstantUnion() &&
+ newExpression->getAsConstantUnion() &&
+ prevExpression->getAsConstantUnion()->getConstArray()[0].getIConst() ==
+ newExpression->getAsConstantUnion()->getConstArray()[0].getIConst())
+ error(branchNode->getLoc(), "duplicated value", "case", "");
+ }
+ }
+ switchSequence->push_back(branchNode);
+ }
+}
+
+//
+// Turn the top-level node sequence built up of wrapupSwitchSubsequence9)
+// into a switch node.
+//
+TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression, TIntermAggregate* lastStatements)
+{
+ profileRequires(loc, EEsProfile, 300, nullptr, "switch statements");
+ profileRequires(loc, ENoProfile, 130, nullptr, "switch statements");
+
+ wrapupSwitchSubsequence(lastStatements, nullptr);
+
+ if (expression == nullptr ||
+ (expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint) ||
+ expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector())
+ error(loc, "condition must be a scalar integer expression", "switch", "");
+
+ // If there is nothing to do, drop the switch but still execute the expression
+ TIntermSequence* switchSequence = switchSequenceStack.back();
+ if (switchSequence->size() == 0)
+ return expression;
+
+ if (lastStatements == nullptr) {
+ // This was originally an ERRROR, because early versions of the specification said
+ // "it is an error to have no statement between a label and the end of the switch statement."
+ // The specifications were updated to remove this (being ill-defined what a "statement" was),
+ // so, this became a warning. However, 3.0 tests still check for the error.
+ if (isEsProfile() && version <= 300 && ! relaxedErrors())
+ error(loc, "last case/default label not followed by statements", "switch", "");
+ else
+ warn(loc, "last case/default label not followed by statements", "switch", "");
+
+ // emulate a break for error recovery
+ lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc));
+ lastStatements->setOperator(EOpSequence);
+ switchSequence->push_back(lastStatements);
+ }
+
+ TIntermAggregate* body = new TIntermAggregate(EOpSequence);
+ body->getSequence() = *switchSequenceStack.back();
+ body->setLoc(loc);
+
+ TIntermSwitch* switchNode = new TIntermSwitch(expression, body);
+ switchNode->setLoc(loc);
+
+ return switchNode;
+}
+
+} // end namespace glslang
+
diff --git a/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.h b/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.h
new file mode 100644
index 0000000000..39363f1a2a
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/ParseHelper.h
@@ -0,0 +1,525 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// This header defines a two-level parse-helper hierarchy, derived from
+// TParseVersions:
+// - TParseContextBase: sharable across multiple parsers
+// - TParseContext: GLSL specific helper
+//
+
+#ifndef _PARSER_HELPER_INCLUDED_
+#define _PARSER_HELPER_INCLUDED_
+
+#include <cstdarg>
+#include <functional>
+
+#include "parseVersions.h"
+#include "../Include/ShHandle.h"
+#include "SymbolTable.h"
+#include "localintermediate.h"
+#include "Scan.h"
+#include "attribute.h"
+
+namespace glslang {
+
+struct TPragma {
+ TPragma(bool o, bool d) : optimize(o), debug(d) { }
+ bool optimize;
+ bool debug;
+ TPragmaTable pragmaTable;
+};
+
+class TScanContext;
+class TPpContext;
+
+typedef std::set<int> TIdSetType;
+
+//
+// Sharable code (as well as what's in TParseVersions) across
+// parse helpers.
+//
+class TParseContextBase : public TParseVersions {
+public:
+ TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version,
+ EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
+ TInfoSink& infoSink, bool forwardCompatible, EShMessages messages,
+ const TString* entryPoint = nullptr)
+ : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
+ scopeMangler("::"),
+ symbolTable(symbolTable),
+ statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
+ postEntryPointReturn(false),
+ contextPragma(true, false),
+ beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
+ parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
+ limits(resources.limits),
+ globalUniformBlock(nullptr),
+ globalUniformBinding(TQualifier::layoutBindingEnd),
+ globalUniformSet(TQualifier::layoutSetEnd)
+ {
+ if (entryPoint != nullptr)
+ sourceEntryPointName = *entryPoint;
+ }
+ virtual ~TParseContextBase() { }
+
+#if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL)
+ virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...);
+ virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...);
+ virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...);
+ virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...);
+#endif
+
+ virtual void setLimits(const TBuiltInResource&) = 0;
+
+ void checkIndex(const TSourceLoc&, const TType&, int& index);
+
+ EShLanguage getLanguage() const { return language; }
+ void setScanContext(TScanContext* c) { scanContext = c; }
+ TScanContext* getScanContext() const { return scanContext; }
+ void setPpContext(TPpContext* c) { ppContext = c; }
+ TPpContext* getPpContext() const { return ppContext; }
+
+ virtual void setLineCallback(const std::function<void(int, int, bool, int, const char*)>& func) { lineCallback = func; }
+ virtual void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; }
+ virtual void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; }
+ virtual void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
+ virtual void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
+
+ virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0;
+ virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0;
+ virtual bool lineDirectiveShouldSetNextLine() const = 0;
+ virtual void handlePragma(const TSourceLoc&, const TVector<TString>&) = 0;
+
+ virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0;
+
+ virtual void notifyVersion(int line, int version, const char* type_string)
+ {
+ if (versionCallback)
+ versionCallback(line, version, type_string);
+ }
+ virtual void notifyErrorDirective(int line, const char* error_message)
+ {
+ if (errorCallback)
+ errorCallback(line, error_message);
+ }
+ virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName)
+ {
+ if (lineCallback)
+ lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName);
+ }
+ virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior)
+ {
+ if (extensionCallback)
+ extensionCallback(line, extension, behavior);
+ }
+
+#ifdef ENABLE_HLSL
+ // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
+ virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
+#endif
+
+ // Potentially rename shader entry point function
+ void renameShaderFunction(TString*& name) const
+ {
+ // Replace the entry point name given in the shader with the real entry point name,
+ // if there is a substitution.
+ if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0)
+ name = NewPoolTString(intermediate.getEntryPointName().c_str());
+ }
+
+ virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
+ virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
+
+ const char* const scopeMangler;
+
+ // Basic parsing state, easily accessible to the grammar
+
+ TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
+ int statementNestingLevel; // 0 if outside all flow control or compound statements
+ int loopNestingLevel; // 0 if outside all loops
+ int structNestingLevel; // 0 if outside blocks and structures
+ int controlFlowNestingLevel; // 0 if outside all flow control
+ const TType* currentFunctionType; // the return type of the function that's currently being parsed
+ bool functionReturnsValue; // true if a non-void function has a return
+ // if inside a function, true if the function is the entry point and this is after a return statement
+ bool postEntryPointReturn;
+ // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
+ TList<TIntermSequence*> switchSequenceStack;
+ // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
+ TList<int> switchLevel;
+ struct TPragma contextPragma;
+ int beginInvocationInterlockCount;
+ int endInvocationInterlockCount;
+
+protected:
+ TParseContextBase(TParseContextBase&);
+ TParseContextBase& operator=(TParseContextBase&);
+
+ const bool parsingBuiltins; // true if parsing built-in symbols/functions
+ TVector<TSymbol*> linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving
+ TScanContext* scanContext;
+ TPpContext* ppContext;
+ TBuiltInResource resources;
+ TLimits& limits;
+ TString sourceEntryPointName;
+
+ // These, if set, will be called when a line, pragma ... is preprocessed.
+ // They will be called with any parameters to the original directive.
+ std::function<void(int, int, bool, int, const char*)> lineCallback;
+ std::function<void(int, const TVector<TString>&)> pragmaCallback;
+ std::function<void(int, int, const char*)> versionCallback;
+ std::function<void(int, const char*, const char*)> extensionCallback;
+ std::function<void(int, const char*)> errorCallback;
+
+ // see implementation for detail
+ const TFunction* selectFunction(const TVector<const TFunction*>, const TFunction&,
+ std::function<bool(const TType&, const TType&, TOperator, int arg)>,
+ std::function<bool(const TType&, const TType&, const TType&)>,
+ /* output */ bool& tie);
+
+ virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size,
+ TSwizzleSelectors<TVectorSelector>&);
+
+ // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
+ TVariable* globalUniformBlock; // the actual block, inserted into the symbol table
+ unsigned int globalUniformBinding; // the block's binding number
+ unsigned int globalUniformSet; // the block's set number
+ int firstNewMember; // the index of the first member not yet inserted into the symbol table
+ // override this to set the language-specific name
+ virtual const char* getGlobalUniformBlockName() const { return ""; }
+ virtual void setUniformBlockDefaults(TType&) const { }
+ virtual void finalizeGlobalUniformBlockLayout(TVariable&) { }
+ virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, TPrefixType prefix,
+ va_list args);
+ virtual void trackLinkage(TSymbol& symbol);
+ virtual void makeEditable(TSymbol*&);
+ virtual TVariable* getEditableVariable(const char* name);
+ virtual void finish();
+};
+
+//
+// Manage the state for when to respect precision qualifiers and when to warn about
+// the defaults being different than might be expected.
+//
+class TPrecisionManager {
+public:
+ TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ }
+ virtual ~TPrecisionManager() {}
+
+ void respectPrecisionQualifiers() { obey = true; }
+ bool respectingPrecisionQualifiers() const { return obey; }
+ bool shouldWarnAboutDefaults() const { return warn; }
+ void defaultWarningGiven() { warn = false; }
+ void warnAboutDefaults() { warn = true; }
+ void explicitIntDefaultSeen()
+ {
+ explicitIntDefault = true;
+ if (explicitFloatDefault)
+ warn = false;
+ }
+ void explicitFloatDefaultSeen()
+ {
+ explicitFloatDefault = true;
+ if (explicitIntDefault)
+ warn = false;
+ }
+
+protected:
+ bool obey; // respect precision qualifiers
+ bool warn; // need to give a warning about the defaults
+ bool explicitIntDefault; // user set the default for int/uint
+ bool explicitFloatDefault; // user set the default for float
+};
+
+//
+// GLSL-specific parse helper. Should have GLSL in the name, but that's
+// too big of a change for comparing branches at the moment, and perhaps
+// impacts downstream consumers as well.
+//
+class TParseContext : public TParseContextBase {
+public:
+ TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&,
+ bool forwardCompatible = false, EShMessages messages = EShMsgDefault,
+ const TString* entryPoint = nullptr);
+ virtual ~TParseContext();
+
+ bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); }
+ void setPrecisionDefaults();
+
+ void setLimits(const TBuiltInResource&) override;
+ bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
+ void parserError(const char* s); // for bison's yyerror
+
+ void reservedErrorCheck(const TSourceLoc&, const TString&);
+ void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
+ bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
+ bool lineDirectiveShouldSetNextLine() const override;
+ bool builtInName(const TString&);
+
+ void handlePragma(const TSourceLoc&, const TVector<TString>&) override;
+ TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
+ TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
+ void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
+
+#ifndef GLSLANG_WEB
+ void makeEditable(TSymbol*&) override;
+ void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
+#endif
+ bool isIoResizeArray(const TType&) const;
+ void fixIoArraySize(const TSourceLoc&, TType&);
+ void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
+ void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false);
+ int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const;
+ void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
+
+ TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
+ TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
+ TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
+ void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
+ TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
+ TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
+ TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
+ TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function);
+ void computeBuiltinPrecisions(TIntermTyped&, const TFunction&);
+ TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
+ void checkLocation(const TSourceLoc&, TOperator);
+ TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
+ void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
+ TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
+ void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
+ void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
+ void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
+ void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*);
+ TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
+ void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier);
+ void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
+ void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
+
+ void assignError(const TSourceLoc&, const char* op, TString left, TString right);
+ void unaryOpError(const TSourceLoc&, const char* op, TString operand);
+ void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
+ void variableCheck(TIntermTyped*& nodePtr);
+ bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
+ void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
+ void constantValueCheck(TIntermTyped* node, const char* token);
+ void integerCheck(const TIntermTyped* node, const char* token);
+ void globalCheck(const TSourceLoc&, const char* token);
+ bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&);
+ bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&);
+ void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType);
+ bool arrayQualifierError(const TSourceLoc&, const TQualifier&);
+ bool arrayError(const TSourceLoc&, const TType&);
+ void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
+ void structArrayCheck(const TSourceLoc&, const TType& structure);
+ void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember);
+ void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*);
+ bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
+ void boolCheck(const TSourceLoc&, const TIntermTyped*);
+ void boolCheck(const TSourceLoc&, const TPublicType&);
+ void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
+ void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
+ void accStructNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
+ void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
+ void memberQualifierCheck(glslang::TPublicType&);
+ void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
+ void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
+ bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
+ void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
+ void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier);
+ int computeSamplerTypeIndex(TSampler&);
+ TPrecisionQualifier getDefaultPrecision(TPublicType&);
+ void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&);
+ void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type);
+ bool containsFieldWithBasicType(const TType& type ,TBasicType basicType);
+ TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&);
+ void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
+ void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type);
+ void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
+ void nestedBlockCheck(const TSourceLoc&);
+ void nestedStructCheck(const TSourceLoc&);
+ void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
+ void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
+ void referenceCheck(const TSourceLoc&, const TType&, const char* op);
+ void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op);
+ void specializationCheck(const TSourceLoc&, const TType&, const char* op);
+ void structTypeCheck(const TSourceLoc&, TPublicType&);
+ void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop);
+ void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
+ void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
+
+ void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&);
+ void constantIndexExpressionCheck(TIntermNode*);
+
+ void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
+ void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*);
+ void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
+ void layoutObjectCheck(const TSourceLoc&, const TSymbol&);
+ void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes);
+ void layoutTypeCheck(const TSourceLoc&, const TType&);
+ void layoutQualifierCheck(const TSourceLoc&, const TQualifier&);
+ void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
+ void fixOffset(const TSourceLoc&, TSymbol&);
+
+ const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+ const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+ const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+ const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+ const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+ void declareTypeDefaults(const TSourceLoc&, const TPublicType&);
+ TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
+ TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
+ TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
+ TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
+ void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
+ void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
+ void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
+ void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
+ void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
+ void fixXfbOffsets(TQualifier&, TTypeList&);
+ void fixBlockUniformOffsets(TQualifier&, TTypeList&);
+ void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
+ void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
+ void invariantCheck(const TSourceLoc&, const TQualifier&);
+ void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
+ void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
+ TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
+
+#ifndef GLSLANG_WEB
+ TAttributeType attributeFromName(const TString& name) const;
+ TAttributes* makeAttributes(const TString& identifier) const;
+ TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const;
+ TAttributes* mergeAttributes(TAttributes*, TAttributes*) const;
+
+ // Determine selection control from attributes
+ void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*);
+ void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
+ // Determine loop control from attributes
+ void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
+#endif
+
+ void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember);
+
+protected:
+ void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
+ void inheritGlobalDefaults(TQualifier& dst) const;
+ TVariable* makeInternalVariable(const char* name, const TType&) const;
+ TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&);
+ void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&);
+ void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&);
+ bool isRuntimeLength(const TIntermTyped&) const;
+ TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
+ TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
+#ifndef GLSLANG_WEB
+ void finish() override;
+#endif
+
+public:
+ //
+ // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
+ //
+
+ // Current state of parsing
+ bool inMain; // if inside a function, true if the function is main
+ const TString* blockName;
+ TQualifier currentBlockQualifier;
+ TPrecisionQualifier defaultPrecision[EbtNumTypes];
+ TBuiltInResource resources;
+ TLimits& limits;
+
+protected:
+ TParseContext(TParseContext&);
+ TParseContext& operator=(TParseContext&);
+
+ static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex()
+ TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
+ TPrecisionManager precisionManager;
+ TQualifier globalBufferDefaults;
+ TQualifier globalUniformDefaults;
+ TQualifier globalInputDefaults;
+ TQualifier globalOutputDefaults;
+ TString currentCaller; // name of last function body entered (not valid when at global scope)
+#ifndef GLSLANG_WEB
+ int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point
+ bool anyIndexLimits;
+ TIdSetType inductiveLoopIds;
+ TVector<TIntermTyped*> needsIndexLimitationChecking;
+
+ //
+ // Geometry shader input arrays:
+ // - array sizing is based on input primitive and/or explicit size
+ //
+ // Tessellation control output arrays:
+ // - array sizing is based on output layout(vertices=...) and/or explicit size
+ //
+ // Both:
+ // - array sizing is retroactive
+ // - built-in block redeclarations interact with this
+ //
+ // Design:
+ // - use a per-context "resize-list", a list of symbols whose array sizes
+ // can be fixed
+ //
+ // - the resize-list starts empty at beginning of user-shader compilation, it does
+ // not have built-ins in it
+ //
+ // - on built-in array use: copyUp() symbol and add it to the resize-list
+ //
+ // - on user array declaration: add it to the resize-list
+ //
+ // - on block redeclaration: copyUp() symbol and add it to the resize-list
+ // * note, that appropriately gives an error if redeclaring a block that
+ // was already used and hence already copied-up
+ //
+ // - on seeing a layout declaration that sizes the array, fix everything in the
+ // resize-list, giving errors for mismatch
+ //
+ // - on seeing an array size declaration, give errors on mismatch between it and previous
+ // array-sizing declarations
+ //
+ TVector<TSymbol*> ioArraySymbolResizeList;
+#endif
+};
+
+} // end namespace glslang
+
+#endif // _PARSER_HELPER_INCLUDED_
diff --git a/thirdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp b/thirdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp
new file mode 100644
index 0000000000..84c40f4e79
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp
@@ -0,0 +1,315 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/Common.h"
+#include "../Include/PoolAlloc.h"
+
+#include "../Include/InitializeGlobals.h"
+#include "../OSDependent/osinclude.h"
+
+namespace glslang {
+
+// Process-wide TLS index
+OS_TLSIndex PoolIndex;
+
+// Return the thread-specific current pool.
+TPoolAllocator& GetThreadPoolAllocator()
+{
+ return *static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex));
+}
+
+// Set the thread-specific current pool.
+void SetThreadPoolAllocator(TPoolAllocator* poolAllocator)
+{
+ OS_SetTLSValue(PoolIndex, poolAllocator);
+}
+
+// Process-wide set up of the TLS pool storage.
+bool InitializePoolIndex()
+{
+ // Allocate a TLS index.
+ if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
+ return false;
+
+ return true;
+}
+
+//
+// Implement the functionality of the TPoolAllocator class, which
+// is documented in PoolAlloc.h.
+//
+TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) :
+ pageSize(growthIncrement),
+ alignment(allocationAlignment),
+ freeList(nullptr),
+ inUseList(nullptr),
+ numCalls(0)
+{
+ //
+ // Don't allow page sizes we know are smaller than all common
+ // OS page sizes.
+ //
+ if (pageSize < 4*1024)
+ pageSize = 4*1024;
+
+ //
+ // A large currentPageOffset indicates a new page needs to
+ // be obtained to allocate memory.
+ //
+ currentPageOffset = pageSize;
+
+ //
+ // Adjust alignment to be at least pointer aligned and
+ // power of 2.
+ //
+ size_t minAlign = sizeof(void*);
+ alignment &= ~(minAlign - 1);
+ if (alignment < minAlign)
+ alignment = minAlign;
+ size_t a = 1;
+ while (a < alignment)
+ a <<= 1;
+ alignment = a;
+ alignmentMask = a - 1;
+
+ //
+ // Align header skip
+ //
+ headerSkip = minAlign;
+ if (headerSkip < sizeof(tHeader)) {
+ headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
+ }
+
+ push();
+}
+
+TPoolAllocator::~TPoolAllocator()
+{
+ while (inUseList) {
+ tHeader* next = inUseList->nextPage;
+ inUseList->~tHeader();
+ delete [] reinterpret_cast<char*>(inUseList);
+ inUseList = next;
+ }
+
+ //
+ // Always delete the free list memory - it can't be being
+ // (correctly) referenced, whether the pool allocator was
+ // global or not. We should not check the guard blocks
+ // here, because we did it already when the block was
+ // placed into the free list.
+ //
+ while (freeList) {
+ tHeader* next = freeList->nextPage;
+ delete [] reinterpret_cast<char*>(freeList);
+ freeList = next;
+ }
+}
+
+const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
+const unsigned char TAllocation::guardBlockEndVal = 0xfe;
+const unsigned char TAllocation::userDataFill = 0xcd;
+
+# ifdef GUARD_BLOCKS
+ const size_t TAllocation::guardBlockSize = 16;
+# else
+ const size_t TAllocation::guardBlockSize = 0;
+# endif
+
+//
+// Check a single guard block for damage
+//
+#ifdef GUARD_BLOCKS
+void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
+#else
+void TAllocation::checkGuardBlock(unsigned char*, unsigned char, const char*) const
+#endif
+{
+#ifdef GUARD_BLOCKS
+ for (size_t x = 0; x < guardBlockSize; x++) {
+ if (blockMem[x] != val) {
+ const int maxSize = 80;
+ char assertMsg[maxSize];
+
+ // We don't print the assert message. It's here just to be helpful.
+ snprintf(assertMsg, maxSize, "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n",
+ locText, size, data());
+ assert(0 && "PoolAlloc: Damage in guard block");
+ }
+ }
+#else
+ assert(guardBlockSize == 0);
+#endif
+}
+
+void TPoolAllocator::push()
+{
+ tAllocState state = { currentPageOffset, inUseList };
+
+ stack.push_back(state);
+
+ //
+ // Indicate there is no current page to allocate from.
+ //
+ currentPageOffset = pageSize;
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred since the last push(), or since the
+// last pop(), or since the object's creation.
+//
+// The deallocated pages are saved for future allocations.
+//
+void TPoolAllocator::pop()
+{
+ if (stack.size() < 1)
+ return;
+
+ tHeader* page = stack.back().page;
+ currentPageOffset = stack.back().offset;
+
+ while (inUseList != page) {
+ tHeader* nextInUse = inUseList->nextPage;
+ size_t pageCount = inUseList->pageCount;
+
+ // This technically ends the lifetime of the header as C++ object,
+ // but we will still control the memory and reuse it.
+ inUseList->~tHeader(); // currently, just a debug allocation checker
+
+ if (pageCount > 1) {
+ delete [] reinterpret_cast<char*>(inUseList);
+ } else {
+ inUseList->nextPage = freeList;
+ freeList = inUseList;
+ }
+ inUseList = nextInUse;
+ }
+
+ stack.pop_back();
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred.
+//
+void TPoolAllocator::popAll()
+{
+ while (stack.size() > 0)
+ pop();
+}
+
+void* TPoolAllocator::allocate(size_t numBytes)
+{
+ // If we are using guard blocks, all allocations are bracketed by
+ // them: [guardblock][allocation][guardblock]. numBytes is how
+ // much memory the caller asked for. allocationSize is the total
+ // size including guard blocks. In release build,
+ // guardBlockSize=0 and this all gets optimized away.
+ size_t allocationSize = TAllocation::allocationSize(numBytes);
+
+ //
+ // Just keep some interesting statistics.
+ //
+ ++numCalls;
+ totalBytes += numBytes;
+
+ //
+ // Do the allocation, most likely case first, for efficiency.
+ // This step could be moved to be inline sometime.
+ //
+ if (currentPageOffset + allocationSize <= pageSize) {
+ //
+ // Safe to allocate from currentPageOffset.
+ //
+ unsigned char* memory = reinterpret_cast<unsigned char*>(inUseList) + currentPageOffset;
+ currentPageOffset += allocationSize;
+ currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
+
+ return initializeAllocation(inUseList, memory, numBytes);
+ }
+
+ if (allocationSize + headerSkip > pageSize) {
+ //
+ // Do a multi-page allocation. Don't mix these with the others.
+ // The OS is efficient and allocating and free-ing multiple pages.
+ //
+ size_t numBytesToAlloc = allocationSize + headerSkip;
+ tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
+ if (memory == 0)
+ return 0;
+
+ // Use placement-new to initialize header
+ new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
+ inUseList = memory;
+
+ currentPageOffset = pageSize; // make next allocation come from a new page
+
+ // No guard blocks for multi-page allocations (yet)
+ return reinterpret_cast<void*>(reinterpret_cast<UINT_PTR>(memory) + headerSkip);
+ }
+
+ //
+ // Need a simple page to allocate from.
+ //
+ tHeader* memory;
+ if (freeList) {
+ memory = freeList;
+ freeList = freeList->nextPage;
+ } else {
+ memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
+ if (memory == 0)
+ return 0;
+ }
+
+ // Use placement-new to initialize header
+ new(memory) tHeader(inUseList, 1);
+ inUseList = memory;
+
+ unsigned char* ret = reinterpret_cast<unsigned char*>(inUseList) + headerSkip;
+ currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
+
+ return initializeAllocation(inUseList, ret, numBytes);
+}
+
+//
+// Check all allocations in a list for damage by calling check on each.
+//
+void TAllocation::checkAllocList() const
+{
+ for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
+ alloc->check();
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/RemoveTree.cpp b/thirdparty/glslang/glslang/MachineIndependent/RemoveTree.cpp
new file mode 100644
index 0000000000..1d33bfd203
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/RemoveTree.cpp
@@ -0,0 +1,118 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/intermediate.h"
+#include "RemoveTree.h"
+
+namespace glslang {
+
+//
+// Code to recursively delete the intermediate tree.
+//
+struct TRemoveTraverser : TIntermTraverser {
+ TRemoveTraverser() : TIntermTraverser(false, false, true, false) {}
+
+ virtual void visitSymbol(TIntermSymbol* node)
+ {
+ delete node;
+ }
+
+ virtual bool visitBinary(TVisit /* visit*/ , TIntermBinary* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual bool visitUnary(TVisit /* visit */, TIntermUnary* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual bool visitAggregate(TVisit /* visit*/ , TIntermAggregate* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual bool visitSelection(TVisit /* visit*/ , TIntermSelection* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual bool visitSwitch(TVisit /* visit*/ , TIntermSwitch* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual void visitConstantUnion(TIntermConstantUnion* node)
+ {
+ delete node;
+ }
+
+ virtual bool visitLoop(TVisit /* visit*/ , TIntermLoop* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual bool visitBranch(TVisit /* visit*/ , TIntermBranch* node)
+ {
+ delete node;
+
+ return true;
+ }
+};
+
+//
+// Entry point.
+//
+void RemoveAllTreeNodes(TIntermNode* root)
+{
+ TRemoveTraverser it;
+
+ root->traverse(&it);
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/RemoveTree.h b/thirdparty/glslang/glslang/MachineIndependent/RemoveTree.h
new file mode 100644
index 0000000000..1ed015626b
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/RemoveTree.h
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#pragma once
+
+namespace glslang {
+
+void RemoveAllTreeNodes(TIntermNode*);
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/Scan.cpp b/thirdparty/glslang/glslang/MachineIndependent/Scan.cpp
new file mode 100644
index 0000000000..fd18fd4d7d
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/Scan.cpp
@@ -0,0 +1,1797 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// GLSL scanning, leveraging the scanning done by the preprocessor.
+//
+
+#include <cstring>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "../Include/Types.h"
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "attribute.h"
+#include "glslang_tab.cpp.h"
+#include "ScanContext.h"
+#include "Scan.h"
+
+// preprocessor includes
+#include "preprocessor/PpContext.h"
+#include "preprocessor/PpTokens.h"
+
+// Required to avoid missing prototype warnings for some compilers
+int yylex(YYSTYPE*, glslang::TParseContext&);
+
+namespace glslang {
+
+// read past any white space
+void TInputScanner::consumeWhiteSpace(bool& foundNonSpaceTab)
+{
+ int c = peek(); // don't accidentally consume anything other than whitespace
+ while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+ if (c == '\r' || c == '\n')
+ foundNonSpaceTab = true;
+ get();
+ c = peek();
+ }
+}
+
+// return true if a comment was actually consumed
+bool TInputScanner::consumeComment()
+{
+ if (peek() != '/')
+ return false;
+
+ get(); // consume the '/'
+ int c = peek();
+ if (c == '/') {
+
+ // a '//' style comment
+ get(); // consume the second '/'
+ c = get();
+ do {
+ while (c != EndOfInput && c != '\\' && c != '\r' && c != '\n')
+ c = get();
+
+ if (c == EndOfInput || c == '\r' || c == '\n') {
+ while (c == '\r' || c == '\n')
+ c = get();
+
+ // we reached the end of the comment
+ break;
+ } else {
+ // it's a '\', so we need to keep going, after skipping what's escaped
+
+ // read the skipped character
+ c = get();
+
+ // if it's a two-character newline, skip both characters
+ if (c == '\r' && peek() == '\n')
+ get();
+ c = get();
+ }
+ } while (true);
+
+ // put back the last non-comment character
+ if (c != EndOfInput)
+ unget();
+
+ return true;
+ } else if (c == '*') {
+
+ // a '/*' style comment
+ get(); // consume the '*'
+ c = get();
+ do {
+ while (c != EndOfInput && c != '*')
+ c = get();
+ if (c == '*') {
+ c = get();
+ if (c == '/')
+ break; // end of comment
+ // not end of comment
+ } else // end of input
+ break;
+ } while (true);
+
+ return true;
+ } else {
+ // it's not a comment, put the '/' back
+ unget();
+
+ return false;
+ }
+}
+
+// skip whitespace, then skip a comment, rinse, repeat
+void TInputScanner::consumeWhitespaceComment(bool& foundNonSpaceTab)
+{
+ do {
+ consumeWhiteSpace(foundNonSpaceTab);
+
+ // if not starting a comment now, then done
+ int c = peek();
+ if (c != '/' || c == EndOfInput)
+ return;
+
+ // skip potential comment
+ foundNonSpaceTab = true;
+ if (! consumeComment())
+ return;
+
+ } while (true);
+}
+
+// Returns true if there was non-white space (e.g., a comment, newline) before the #version
+// or no #version was found; otherwise, returns false. There is no error case, it always
+// succeeds, but will leave version == 0 if no #version was found.
+//
+// Sets notFirstToken based on whether tokens (beyond white space and comments)
+// appeared before the #version.
+//
+// N.B. does not attempt to leave input in any particular known state. The assumption
+// is that scanning will start anew, following the rules for the chosen version/profile,
+// and with a corresponding parsing context.
+//
+bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstToken)
+{
+ // This function doesn't have to get all the semantics correct,
+ // just find the #version if there is a correct one present.
+ // The preprocessor will have the responsibility of getting all the semantics right.
+
+ bool versionNotFirst = false; // means not first WRT comments and white space, nothing more
+ notFirstToken = false; // means not first WRT to real tokens
+ version = 0; // means not found
+ profile = ENoProfile;
+
+ bool foundNonSpaceTab = false;
+ bool lookingInMiddle = false;
+ int c;
+ do {
+ if (lookingInMiddle) {
+ notFirstToken = true;
+ // make forward progress by finishing off the current line plus extra new lines
+ if (peek() == '\n' || peek() == '\r') {
+ while (peek() == '\n' || peek() == '\r')
+ get();
+ } else
+ do {
+ c = get();
+ } while (c != EndOfInput && c != '\n' && c != '\r');
+ while (peek() == '\n' || peek() == '\r')
+ get();
+ if (peek() == EndOfInput)
+ return true;
+ }
+ lookingInMiddle = true;
+
+ // Nominal start, skipping the desktop allowed comments and white space, but tracking if
+ // something else was found for ES:
+ consumeWhitespaceComment(foundNonSpaceTab);
+ if (foundNonSpaceTab)
+ versionNotFirst = true;
+
+ // "#"
+ if (get() != '#') {
+ versionNotFirst = true;
+ continue;
+ }
+
+ // whitespace
+ do {
+ c = get();
+ } while (c == ' ' || c == '\t');
+
+ // "version"
+ if ( c != 'v' ||
+ get() != 'e' ||
+ get() != 'r' ||
+ get() != 's' ||
+ get() != 'i' ||
+ get() != 'o' ||
+ get() != 'n') {
+ versionNotFirst = true;
+ continue;
+ }
+
+ // whitespace
+ do {
+ c = get();
+ } while (c == ' ' || c == '\t');
+
+ // version number
+ while (c >= '0' && c <= '9') {
+ version = 10 * version + (c - '0');
+ c = get();
+ }
+ if (version == 0) {
+ versionNotFirst = true;
+ continue;
+ }
+
+ // whitespace
+ while (c == ' ' || c == '\t')
+ c = get();
+
+ // profile
+ const int maxProfileLength = 13; // not including any 0
+ char profileString[maxProfileLength];
+ int profileLength;
+ for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) {
+ if (c == EndOfInput || c == ' ' || c == '\t' || c == '\n' || c == '\r')
+ break;
+ profileString[profileLength] = (char)c;
+ c = get();
+ }
+ if (c != EndOfInput && c != ' ' && c != '\t' && c != '\n' && c != '\r') {
+ versionNotFirst = true;
+ continue;
+ }
+
+ if (profileLength == 2 && strncmp(profileString, "es", profileLength) == 0)
+ profile = EEsProfile;
+ else if (profileLength == 4 && strncmp(profileString, "core", profileLength) == 0)
+ profile = ECoreProfile;
+ else if (profileLength == 13 && strncmp(profileString, "compatibility", profileLength) == 0)
+ profile = ECompatibilityProfile;
+
+ return versionNotFirst;
+ } while (true);
+}
+
+// Fill this in when doing glslang-level scanning, to hand back to the parser.
+class TParserToken {
+public:
+ explicit TParserToken(YYSTYPE& b) : sType(b) { }
+
+ YYSTYPE& sType;
+protected:
+ TParserToken(TParserToken&);
+ TParserToken& operator=(TParserToken&);
+};
+
+} // end namespace glslang
+
+// This is the function the glslang parser (i.e., bison) calls to get its next token
+int yylex(YYSTYPE* glslangTokenDesc, glslang::TParseContext& parseContext)
+{
+ glslang::TParserToken token(*glslangTokenDesc);
+
+ return parseContext.getScanContext()->tokenize(parseContext.getPpContext(), token);
+}
+
+namespace {
+
+struct str_eq
+{
+ bool operator()(const char* lhs, const char* rhs) const
+ {
+ return strcmp(lhs, rhs) == 0;
+ }
+};
+
+struct str_hash
+{
+ size_t operator()(const char* str) const
+ {
+ // djb2
+ unsigned long hash = 5381;
+ int c;
+
+ while ((c = *str++) != 0)
+ hash = ((hash << 5) + hash) + c;
+
+ return hash;
+ }
+};
+
+// A single global usable by all threads, by all versions, by all languages.
+// After a single process-level initialization, this is read only and thread safe
+std::unordered_map<const char*, int, str_hash, str_eq>* KeywordMap = nullptr;
+#ifndef GLSLANG_WEB
+std::unordered_set<const char*, str_hash, str_eq>* ReservedSet = nullptr;
+#endif
+
+};
+
+namespace glslang {
+
+void TScanContext::fillInKeywordMap()
+{
+ if (KeywordMap != nullptr) {
+ // this is really an error, as this should called only once per process
+ // but, the only risk is if two threads called simultaneously
+ return;
+ }
+ KeywordMap = new std::unordered_map<const char*, int, str_hash, str_eq>;
+
+ (*KeywordMap)["const"] = CONST;
+ (*KeywordMap)["uniform"] = UNIFORM;
+ (*KeywordMap)["buffer"] = BUFFER;
+ (*KeywordMap)["in"] = IN;
+ (*KeywordMap)["out"] = OUT;
+ (*KeywordMap)["smooth"] = SMOOTH;
+ (*KeywordMap)["flat"] = FLAT;
+ (*KeywordMap)["centroid"] = CENTROID;
+ (*KeywordMap)["invariant"] = INVARIANT;
+ (*KeywordMap)["packed"] = PACKED;
+ (*KeywordMap)["resource"] = RESOURCE;
+ (*KeywordMap)["inout"] = INOUT;
+ (*KeywordMap)["struct"] = STRUCT;
+ (*KeywordMap)["break"] = BREAK;
+ (*KeywordMap)["continue"] = CONTINUE;
+ (*KeywordMap)["do"] = DO;
+ (*KeywordMap)["for"] = FOR;
+ (*KeywordMap)["while"] = WHILE;
+ (*KeywordMap)["switch"] = SWITCH;
+ (*KeywordMap)["case"] = CASE;
+ (*KeywordMap)["default"] = DEFAULT;
+ (*KeywordMap)["if"] = IF;
+ (*KeywordMap)["else"] = ELSE;
+ (*KeywordMap)["discard"] = DISCARD;
+ (*KeywordMap)["return"] = RETURN;
+ (*KeywordMap)["void"] = VOID;
+ (*KeywordMap)["bool"] = BOOL;
+ (*KeywordMap)["float"] = FLOAT;
+ (*KeywordMap)["int"] = INT;
+ (*KeywordMap)["bvec2"] = BVEC2;
+ (*KeywordMap)["bvec3"] = BVEC3;
+ (*KeywordMap)["bvec4"] = BVEC4;
+ (*KeywordMap)["vec2"] = VEC2;
+ (*KeywordMap)["vec3"] = VEC3;
+ (*KeywordMap)["vec4"] = VEC4;
+ (*KeywordMap)["ivec2"] = IVEC2;
+ (*KeywordMap)["ivec3"] = IVEC3;
+ (*KeywordMap)["ivec4"] = IVEC4;
+ (*KeywordMap)["mat2"] = MAT2;
+ (*KeywordMap)["mat3"] = MAT3;
+ (*KeywordMap)["mat4"] = MAT4;
+ (*KeywordMap)["true"] = BOOLCONSTANT;
+ (*KeywordMap)["false"] = BOOLCONSTANT;
+ (*KeywordMap)["layout"] = LAYOUT;
+ (*KeywordMap)["shared"] = SHARED;
+ (*KeywordMap)["highp"] = HIGH_PRECISION;
+ (*KeywordMap)["mediump"] = MEDIUM_PRECISION;
+ (*KeywordMap)["lowp"] = LOW_PRECISION;
+ (*KeywordMap)["superp"] = SUPERP;
+ (*KeywordMap)["precision"] = PRECISION;
+ (*KeywordMap)["mat2x2"] = MAT2X2;
+ (*KeywordMap)["mat2x3"] = MAT2X3;
+ (*KeywordMap)["mat2x4"] = MAT2X4;
+ (*KeywordMap)["mat3x2"] = MAT3X2;
+ (*KeywordMap)["mat3x3"] = MAT3X3;
+ (*KeywordMap)["mat3x4"] = MAT3X4;
+ (*KeywordMap)["mat4x2"] = MAT4X2;
+ (*KeywordMap)["mat4x3"] = MAT4X3;
+ (*KeywordMap)["mat4x4"] = MAT4X4;
+ (*KeywordMap)["uint"] = UINT;
+ (*KeywordMap)["uvec2"] = UVEC2;
+ (*KeywordMap)["uvec3"] = UVEC3;
+ (*KeywordMap)["uvec4"] = UVEC4;
+
+#ifndef GLSLANG_WEB
+ (*KeywordMap)["nonuniformEXT"] = NONUNIFORM;
+ (*KeywordMap)["demote"] = DEMOTE;
+ (*KeywordMap)["attribute"] = ATTRIBUTE;
+ (*KeywordMap)["varying"] = VARYING;
+ (*KeywordMap)["noperspective"] = NOPERSPECTIVE;
+ (*KeywordMap)["coherent"] = COHERENT;
+ (*KeywordMap)["devicecoherent"] = DEVICECOHERENT;
+ (*KeywordMap)["queuefamilycoherent"] = QUEUEFAMILYCOHERENT;
+ (*KeywordMap)["workgroupcoherent"] = WORKGROUPCOHERENT;
+ (*KeywordMap)["subgroupcoherent"] = SUBGROUPCOHERENT;
+ (*KeywordMap)["nonprivate"] = NONPRIVATE;
+ (*KeywordMap)["restrict"] = RESTRICT;
+ (*KeywordMap)["readonly"] = READONLY;
+ (*KeywordMap)["writeonly"] = WRITEONLY;
+ (*KeywordMap)["atomic_uint"] = ATOMIC_UINT;
+ (*KeywordMap)["volatile"] = VOLATILE;
+ (*KeywordMap)["patch"] = PATCH;
+ (*KeywordMap)["sample"] = SAMPLE;
+ (*KeywordMap)["subroutine"] = SUBROUTINE;
+ (*KeywordMap)["dmat2"] = DMAT2;
+ (*KeywordMap)["dmat3"] = DMAT3;
+ (*KeywordMap)["dmat4"] = DMAT4;
+ (*KeywordMap)["dmat2x2"] = DMAT2X2;
+ (*KeywordMap)["dmat2x3"] = DMAT2X3;
+ (*KeywordMap)["dmat2x4"] = DMAT2X4;
+ (*KeywordMap)["dmat3x2"] = DMAT3X2;
+ (*KeywordMap)["dmat3x3"] = DMAT3X3;
+ (*KeywordMap)["dmat3x4"] = DMAT3X4;
+ (*KeywordMap)["dmat4x2"] = DMAT4X2;
+ (*KeywordMap)["dmat4x3"] = DMAT4X3;
+ (*KeywordMap)["dmat4x4"] = DMAT4X4;
+ (*KeywordMap)["image1D"] = IMAGE1D;
+ (*KeywordMap)["iimage1D"] = IIMAGE1D;
+ (*KeywordMap)["uimage1D"] = UIMAGE1D;
+ (*KeywordMap)["image2D"] = IMAGE2D;
+ (*KeywordMap)["iimage2D"] = IIMAGE2D;
+ (*KeywordMap)["uimage2D"] = UIMAGE2D;
+ (*KeywordMap)["image3D"] = IMAGE3D;
+ (*KeywordMap)["iimage3D"] = IIMAGE3D;
+ (*KeywordMap)["uimage3D"] = UIMAGE3D;
+ (*KeywordMap)["image2DRect"] = IMAGE2DRECT;
+ (*KeywordMap)["iimage2DRect"] = IIMAGE2DRECT;
+ (*KeywordMap)["uimage2DRect"] = UIMAGE2DRECT;
+ (*KeywordMap)["imageCube"] = IMAGECUBE;
+ (*KeywordMap)["iimageCube"] = IIMAGECUBE;
+ (*KeywordMap)["uimageCube"] = UIMAGECUBE;
+ (*KeywordMap)["imageBuffer"] = IMAGEBUFFER;
+ (*KeywordMap)["iimageBuffer"] = IIMAGEBUFFER;
+ (*KeywordMap)["uimageBuffer"] = UIMAGEBUFFER;
+ (*KeywordMap)["image1DArray"] = IMAGE1DARRAY;
+ (*KeywordMap)["iimage1DArray"] = IIMAGE1DARRAY;
+ (*KeywordMap)["uimage1DArray"] = UIMAGE1DARRAY;
+ (*KeywordMap)["image2DArray"] = IMAGE2DARRAY;
+ (*KeywordMap)["iimage2DArray"] = IIMAGE2DARRAY;
+ (*KeywordMap)["uimage2DArray"] = UIMAGE2DARRAY;
+ (*KeywordMap)["imageCubeArray"] = IMAGECUBEARRAY;
+ (*KeywordMap)["iimageCubeArray"] = IIMAGECUBEARRAY;
+ (*KeywordMap)["uimageCubeArray"] = UIMAGECUBEARRAY;
+ (*KeywordMap)["image2DMS"] = IMAGE2DMS;
+ (*KeywordMap)["iimage2DMS"] = IIMAGE2DMS;
+ (*KeywordMap)["uimage2DMS"] = UIMAGE2DMS;
+ (*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY;
+ (*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY;
+ (*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY;
+ (*KeywordMap)["double"] = DOUBLE;
+ (*KeywordMap)["dvec2"] = DVEC2;
+ (*KeywordMap)["dvec3"] = DVEC3;
+ (*KeywordMap)["dvec4"] = DVEC4;
+ (*KeywordMap)["int64_t"] = INT64_T;
+ (*KeywordMap)["uint64_t"] = UINT64_T;
+ (*KeywordMap)["i64vec2"] = I64VEC2;
+ (*KeywordMap)["i64vec3"] = I64VEC3;
+ (*KeywordMap)["i64vec4"] = I64VEC4;
+ (*KeywordMap)["u64vec2"] = U64VEC2;
+ (*KeywordMap)["u64vec3"] = U64VEC3;
+ (*KeywordMap)["u64vec4"] = U64VEC4;
+
+ // GL_EXT_shader_explicit_arithmetic_types
+ (*KeywordMap)["int8_t"] = INT8_T;
+ (*KeywordMap)["i8vec2"] = I8VEC2;
+ (*KeywordMap)["i8vec3"] = I8VEC3;
+ (*KeywordMap)["i8vec4"] = I8VEC4;
+ (*KeywordMap)["uint8_t"] = UINT8_T;
+ (*KeywordMap)["u8vec2"] = U8VEC2;
+ (*KeywordMap)["u8vec3"] = U8VEC3;
+ (*KeywordMap)["u8vec4"] = U8VEC4;
+
+ (*KeywordMap)["int16_t"] = INT16_T;
+ (*KeywordMap)["i16vec2"] = I16VEC2;
+ (*KeywordMap)["i16vec3"] = I16VEC3;
+ (*KeywordMap)["i16vec4"] = I16VEC4;
+ (*KeywordMap)["uint16_t"] = UINT16_T;
+ (*KeywordMap)["u16vec2"] = U16VEC2;
+ (*KeywordMap)["u16vec3"] = U16VEC3;
+ (*KeywordMap)["u16vec4"] = U16VEC4;
+
+ (*KeywordMap)["int32_t"] = INT32_T;
+ (*KeywordMap)["i32vec2"] = I32VEC2;
+ (*KeywordMap)["i32vec3"] = I32VEC3;
+ (*KeywordMap)["i32vec4"] = I32VEC4;
+ (*KeywordMap)["uint32_t"] = UINT32_T;
+ (*KeywordMap)["u32vec2"] = U32VEC2;
+ (*KeywordMap)["u32vec3"] = U32VEC3;
+ (*KeywordMap)["u32vec4"] = U32VEC4;
+
+ (*KeywordMap)["float16_t"] = FLOAT16_T;
+ (*KeywordMap)["f16vec2"] = F16VEC2;
+ (*KeywordMap)["f16vec3"] = F16VEC3;
+ (*KeywordMap)["f16vec4"] = F16VEC4;
+ (*KeywordMap)["f16mat2"] = F16MAT2;
+ (*KeywordMap)["f16mat3"] = F16MAT3;
+ (*KeywordMap)["f16mat4"] = F16MAT4;
+ (*KeywordMap)["f16mat2x2"] = F16MAT2X2;
+ (*KeywordMap)["f16mat2x3"] = F16MAT2X3;
+ (*KeywordMap)["f16mat2x4"] = F16MAT2X4;
+ (*KeywordMap)["f16mat3x2"] = F16MAT3X2;
+ (*KeywordMap)["f16mat3x3"] = F16MAT3X3;
+ (*KeywordMap)["f16mat3x4"] = F16MAT3X4;
+ (*KeywordMap)["f16mat4x2"] = F16MAT4X2;
+ (*KeywordMap)["f16mat4x3"] = F16MAT4X3;
+ (*KeywordMap)["f16mat4x4"] = F16MAT4X4;
+
+ (*KeywordMap)["float32_t"] = FLOAT32_T;
+ (*KeywordMap)["f32vec2"] = F32VEC2;
+ (*KeywordMap)["f32vec3"] = F32VEC3;
+ (*KeywordMap)["f32vec4"] = F32VEC4;
+ (*KeywordMap)["f32mat2"] = F32MAT2;
+ (*KeywordMap)["f32mat3"] = F32MAT3;
+ (*KeywordMap)["f32mat4"] = F32MAT4;
+ (*KeywordMap)["f32mat2x2"] = F32MAT2X2;
+ (*KeywordMap)["f32mat2x3"] = F32MAT2X3;
+ (*KeywordMap)["f32mat2x4"] = F32MAT2X4;
+ (*KeywordMap)["f32mat3x2"] = F32MAT3X2;
+ (*KeywordMap)["f32mat3x3"] = F32MAT3X3;
+ (*KeywordMap)["f32mat3x4"] = F32MAT3X4;
+ (*KeywordMap)["f32mat4x2"] = F32MAT4X2;
+ (*KeywordMap)["f32mat4x3"] = F32MAT4X3;
+ (*KeywordMap)["f32mat4x4"] = F32MAT4X4;
+ (*KeywordMap)["float64_t"] = FLOAT64_T;
+ (*KeywordMap)["f64vec2"] = F64VEC2;
+ (*KeywordMap)["f64vec3"] = F64VEC3;
+ (*KeywordMap)["f64vec4"] = F64VEC4;
+ (*KeywordMap)["f64mat2"] = F64MAT2;
+ (*KeywordMap)["f64mat3"] = F64MAT3;
+ (*KeywordMap)["f64mat4"] = F64MAT4;
+ (*KeywordMap)["f64mat2x2"] = F64MAT2X2;
+ (*KeywordMap)["f64mat2x3"] = F64MAT2X3;
+ (*KeywordMap)["f64mat2x4"] = F64MAT2X4;
+ (*KeywordMap)["f64mat3x2"] = F64MAT3X2;
+ (*KeywordMap)["f64mat3x3"] = F64MAT3X3;
+ (*KeywordMap)["f64mat3x4"] = F64MAT3X4;
+ (*KeywordMap)["f64mat4x2"] = F64MAT4X2;
+ (*KeywordMap)["f64mat4x3"] = F64MAT4X3;
+ (*KeywordMap)["f64mat4x4"] = F64MAT4X4;
+#endif
+
+ (*KeywordMap)["sampler2D"] = SAMPLER2D;
+ (*KeywordMap)["samplerCube"] = SAMPLERCUBE;
+ (*KeywordMap)["samplerCubeShadow"] = SAMPLERCUBESHADOW;
+ (*KeywordMap)["sampler2DArray"] = SAMPLER2DARRAY;
+ (*KeywordMap)["sampler2DArrayShadow"] = SAMPLER2DARRAYSHADOW;
+ (*KeywordMap)["isampler2D"] = ISAMPLER2D;
+ (*KeywordMap)["isampler3D"] = ISAMPLER3D;
+ (*KeywordMap)["isamplerCube"] = ISAMPLERCUBE;
+ (*KeywordMap)["isampler2DArray"] = ISAMPLER2DARRAY;
+ (*KeywordMap)["usampler2D"] = USAMPLER2D;
+ (*KeywordMap)["usampler3D"] = USAMPLER3D;
+ (*KeywordMap)["usamplerCube"] = USAMPLERCUBE;
+ (*KeywordMap)["usampler2DArray"] = USAMPLER2DARRAY;
+ (*KeywordMap)["sampler3D"] = SAMPLER3D;
+ (*KeywordMap)["sampler2DShadow"] = SAMPLER2DSHADOW;
+
+ (*KeywordMap)["texture2D"] = TEXTURE2D;
+ (*KeywordMap)["textureCube"] = TEXTURECUBE;
+ (*KeywordMap)["texture2DArray"] = TEXTURE2DARRAY;
+ (*KeywordMap)["itexture2D"] = ITEXTURE2D;
+ (*KeywordMap)["itexture3D"] = ITEXTURE3D;
+ (*KeywordMap)["itextureCube"] = ITEXTURECUBE;
+ (*KeywordMap)["itexture2DArray"] = ITEXTURE2DARRAY;
+ (*KeywordMap)["utexture2D"] = UTEXTURE2D;
+ (*KeywordMap)["utexture3D"] = UTEXTURE3D;
+ (*KeywordMap)["utextureCube"] = UTEXTURECUBE;
+ (*KeywordMap)["utexture2DArray"] = UTEXTURE2DARRAY;
+ (*KeywordMap)["texture3D"] = TEXTURE3D;
+
+ (*KeywordMap)["sampler"] = SAMPLER;
+ (*KeywordMap)["samplerShadow"] = SAMPLERSHADOW;
+
+#ifndef GLSLANG_WEB
+ (*KeywordMap)["textureCubeArray"] = TEXTURECUBEARRAY;
+ (*KeywordMap)["itextureCubeArray"] = ITEXTURECUBEARRAY;
+ (*KeywordMap)["utextureCubeArray"] = UTEXTURECUBEARRAY;
+ (*KeywordMap)["samplerCubeArray"] = SAMPLERCUBEARRAY;
+ (*KeywordMap)["samplerCubeArrayShadow"] = SAMPLERCUBEARRAYSHADOW;
+ (*KeywordMap)["isamplerCubeArray"] = ISAMPLERCUBEARRAY;
+ (*KeywordMap)["usamplerCubeArray"] = USAMPLERCUBEARRAY;
+ (*KeywordMap)["sampler1DArrayShadow"] = SAMPLER1DARRAYSHADOW;
+ (*KeywordMap)["isampler1DArray"] = ISAMPLER1DARRAY;
+ (*KeywordMap)["usampler1D"] = USAMPLER1D;
+ (*KeywordMap)["isampler1D"] = ISAMPLER1D;
+ (*KeywordMap)["usampler1DArray"] = USAMPLER1DARRAY;
+ (*KeywordMap)["samplerBuffer"] = SAMPLERBUFFER;
+ (*KeywordMap)["isampler2DRect"] = ISAMPLER2DRECT;
+ (*KeywordMap)["usampler2DRect"] = USAMPLER2DRECT;
+ (*KeywordMap)["isamplerBuffer"] = ISAMPLERBUFFER;
+ (*KeywordMap)["usamplerBuffer"] = USAMPLERBUFFER;
+ (*KeywordMap)["sampler2DMS"] = SAMPLER2DMS;
+ (*KeywordMap)["isampler2DMS"] = ISAMPLER2DMS;
+ (*KeywordMap)["usampler2DMS"] = USAMPLER2DMS;
+ (*KeywordMap)["sampler2DMSArray"] = SAMPLER2DMSARRAY;
+ (*KeywordMap)["isampler2DMSArray"] = ISAMPLER2DMSARRAY;
+ (*KeywordMap)["usampler2DMSArray"] = USAMPLER2DMSARRAY;
+ (*KeywordMap)["sampler1D"] = SAMPLER1D;
+ (*KeywordMap)["sampler1DShadow"] = SAMPLER1DSHADOW;
+ (*KeywordMap)["sampler2DRect"] = SAMPLER2DRECT;
+ (*KeywordMap)["sampler2DRectShadow"] = SAMPLER2DRECTSHADOW;
+ (*KeywordMap)["sampler1DArray"] = SAMPLER1DARRAY;
+
+ (*KeywordMap)["samplerExternalOES"] = SAMPLEREXTERNALOES; // GL_OES_EGL_image_external
+
+ (*KeywordMap)["__samplerExternal2DY2YEXT"] = SAMPLEREXTERNAL2DY2YEXT; // GL_EXT_YUV_target
+
+ (*KeywordMap)["itexture1DArray"] = ITEXTURE1DARRAY;
+ (*KeywordMap)["utexture1D"] = UTEXTURE1D;
+ (*KeywordMap)["itexture1D"] = ITEXTURE1D;
+ (*KeywordMap)["utexture1DArray"] = UTEXTURE1DARRAY;
+ (*KeywordMap)["textureBuffer"] = TEXTUREBUFFER;
+ (*KeywordMap)["itexture2DRect"] = ITEXTURE2DRECT;
+ (*KeywordMap)["utexture2DRect"] = UTEXTURE2DRECT;
+ (*KeywordMap)["itextureBuffer"] = ITEXTUREBUFFER;
+ (*KeywordMap)["utextureBuffer"] = UTEXTUREBUFFER;
+ (*KeywordMap)["texture2DMS"] = TEXTURE2DMS;
+ (*KeywordMap)["itexture2DMS"] = ITEXTURE2DMS;
+ (*KeywordMap)["utexture2DMS"] = UTEXTURE2DMS;
+ (*KeywordMap)["texture2DMSArray"] = TEXTURE2DMSARRAY;
+ (*KeywordMap)["itexture2DMSArray"] = ITEXTURE2DMSARRAY;
+ (*KeywordMap)["utexture2DMSArray"] = UTEXTURE2DMSARRAY;
+ (*KeywordMap)["texture1D"] = TEXTURE1D;
+ (*KeywordMap)["texture2DRect"] = TEXTURE2DRECT;
+ (*KeywordMap)["texture1DArray"] = TEXTURE1DARRAY;
+
+ (*KeywordMap)["subpassInput"] = SUBPASSINPUT;
+ (*KeywordMap)["subpassInputMS"] = SUBPASSINPUTMS;
+ (*KeywordMap)["isubpassInput"] = ISUBPASSINPUT;
+ (*KeywordMap)["isubpassInputMS"] = ISUBPASSINPUTMS;
+ (*KeywordMap)["usubpassInput"] = USUBPASSINPUT;
+ (*KeywordMap)["usubpassInputMS"] = USUBPASSINPUTMS;
+
+ (*KeywordMap)["f16sampler1D"] = F16SAMPLER1D;
+ (*KeywordMap)["f16sampler2D"] = F16SAMPLER2D;
+ (*KeywordMap)["f16sampler3D"] = F16SAMPLER3D;
+ (*KeywordMap)["f16sampler2DRect"] = F16SAMPLER2DRECT;
+ (*KeywordMap)["f16samplerCube"] = F16SAMPLERCUBE;
+ (*KeywordMap)["f16sampler1DArray"] = F16SAMPLER1DARRAY;
+ (*KeywordMap)["f16sampler2DArray"] = F16SAMPLER2DARRAY;
+ (*KeywordMap)["f16samplerCubeArray"] = F16SAMPLERCUBEARRAY;
+ (*KeywordMap)["f16samplerBuffer"] = F16SAMPLERBUFFER;
+ (*KeywordMap)["f16sampler2DMS"] = F16SAMPLER2DMS;
+ (*KeywordMap)["f16sampler2DMSArray"] = F16SAMPLER2DMSARRAY;
+ (*KeywordMap)["f16sampler1DShadow"] = F16SAMPLER1DSHADOW;
+ (*KeywordMap)["f16sampler2DShadow"] = F16SAMPLER2DSHADOW;
+ (*KeywordMap)["f16sampler2DRectShadow"] = F16SAMPLER2DRECTSHADOW;
+ (*KeywordMap)["f16samplerCubeShadow"] = F16SAMPLERCUBESHADOW;
+ (*KeywordMap)["f16sampler1DArrayShadow"] = F16SAMPLER1DARRAYSHADOW;
+ (*KeywordMap)["f16sampler2DArrayShadow"] = F16SAMPLER2DARRAYSHADOW;
+ (*KeywordMap)["f16samplerCubeArrayShadow"] = F16SAMPLERCUBEARRAYSHADOW;
+
+ (*KeywordMap)["f16image1D"] = F16IMAGE1D;
+ (*KeywordMap)["f16image2D"] = F16IMAGE2D;
+ (*KeywordMap)["f16image3D"] = F16IMAGE3D;
+ (*KeywordMap)["f16image2DRect"] = F16IMAGE2DRECT;
+ (*KeywordMap)["f16imageCube"] = F16IMAGECUBE;
+ (*KeywordMap)["f16image1DArray"] = F16IMAGE1DARRAY;
+ (*KeywordMap)["f16image2DArray"] = F16IMAGE2DARRAY;
+ (*KeywordMap)["f16imageCubeArray"] = F16IMAGECUBEARRAY;
+ (*KeywordMap)["f16imageBuffer"] = F16IMAGEBUFFER;
+ (*KeywordMap)["f16image2DMS"] = F16IMAGE2DMS;
+ (*KeywordMap)["f16image2DMSArray"] = F16IMAGE2DMSARRAY;
+
+ (*KeywordMap)["f16texture1D"] = F16TEXTURE1D;
+ (*KeywordMap)["f16texture2D"] = F16TEXTURE2D;
+ (*KeywordMap)["f16texture3D"] = F16TEXTURE3D;
+ (*KeywordMap)["f16texture2DRect"] = F16TEXTURE2DRECT;
+ (*KeywordMap)["f16textureCube"] = F16TEXTURECUBE;
+ (*KeywordMap)["f16texture1DArray"] = F16TEXTURE1DARRAY;
+ (*KeywordMap)["f16texture2DArray"] = F16TEXTURE2DARRAY;
+ (*KeywordMap)["f16textureCubeArray"] = F16TEXTURECUBEARRAY;
+ (*KeywordMap)["f16textureBuffer"] = F16TEXTUREBUFFER;
+ (*KeywordMap)["f16texture2DMS"] = F16TEXTURE2DMS;
+ (*KeywordMap)["f16texture2DMSArray"] = F16TEXTURE2DMSARRAY;
+
+ (*KeywordMap)["f16subpassInput"] = F16SUBPASSINPUT;
+ (*KeywordMap)["f16subpassInputMS"] = F16SUBPASSINPUTMS;
+ (*KeywordMap)["__explicitInterpAMD"] = EXPLICITINTERPAMD;
+ (*KeywordMap)["pervertexNV"] = PERVERTEXNV;
+ (*KeywordMap)["precise"] = PRECISE;
+
+ (*KeywordMap)["rayPayloadNV"] = PAYLOADNV;
+ (*KeywordMap)["rayPayloadInNV"] = PAYLOADINNV;
+ (*KeywordMap)["hitAttributeNV"] = HITATTRNV;
+ (*KeywordMap)["callableDataNV"] = CALLDATANV;
+ (*KeywordMap)["callableDataInNV"] = CALLDATAINNV;
+ (*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV;
+ (*KeywordMap)["perprimitiveNV"] = PERPRIMITIVENV;
+ (*KeywordMap)["perviewNV"] = PERVIEWNV;
+ (*KeywordMap)["taskNV"] = PERTASKNV;
+
+ (*KeywordMap)["fcoopmatNV"] = FCOOPMATNV;
+ (*KeywordMap)["icoopmatNV"] = ICOOPMATNV;
+ (*KeywordMap)["ucoopmatNV"] = UCOOPMATNV;
+
+ ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
+
+ ReservedSet->insert("common");
+ ReservedSet->insert("partition");
+ ReservedSet->insert("active");
+ ReservedSet->insert("asm");
+ ReservedSet->insert("class");
+ ReservedSet->insert("union");
+ ReservedSet->insert("enum");
+ ReservedSet->insert("typedef");
+ ReservedSet->insert("template");
+ ReservedSet->insert("this");
+ ReservedSet->insert("goto");
+ ReservedSet->insert("inline");
+ ReservedSet->insert("noinline");
+ ReservedSet->insert("public");
+ ReservedSet->insert("static");
+ ReservedSet->insert("extern");
+ ReservedSet->insert("external");
+ ReservedSet->insert("interface");
+ ReservedSet->insert("long");
+ ReservedSet->insert("short");
+ ReservedSet->insert("half");
+ ReservedSet->insert("fixed");
+ ReservedSet->insert("unsigned");
+ ReservedSet->insert("input");
+ ReservedSet->insert("output");
+ ReservedSet->insert("hvec2");
+ ReservedSet->insert("hvec3");
+ ReservedSet->insert("hvec4");
+ ReservedSet->insert("fvec2");
+ ReservedSet->insert("fvec3");
+ ReservedSet->insert("fvec4");
+ ReservedSet->insert("sampler3DRect");
+ ReservedSet->insert("filter");
+ ReservedSet->insert("sizeof");
+ ReservedSet->insert("cast");
+ ReservedSet->insert("namespace");
+ ReservedSet->insert("using");
+#endif
+}
+
+void TScanContext::deleteKeywordMap()
+{
+ delete KeywordMap;
+ KeywordMap = nullptr;
+#ifndef GLSLANG_WEB
+ delete ReservedSet;
+ ReservedSet = nullptr;
+#endif
+}
+
+// Called by yylex to get the next token.
+// Returning 0 implies end of input.
+int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
+{
+ do {
+ parserToken = &token;
+ TPpToken ppToken;
+ int token = pp->tokenize(ppToken);
+ if (token == EndOfInput)
+ return 0;
+
+ tokenText = ppToken.name;
+ loc = ppToken.loc;
+ parserToken->sType.lex.loc = loc;
+ switch (token) {
+ case ';': afterType = false; afterBuffer = false; return SEMICOLON;
+ case ',': afterType = false; return COMMA;
+ case ':': return COLON;
+ case '=': afterType = false; return EQUAL;
+ case '(': afterType = false; return LEFT_PAREN;
+ case ')': afterType = false; return RIGHT_PAREN;
+ case '.': field = true; return DOT;
+ case '!': return BANG;
+ case '-': return DASH;
+ case '~': return TILDE;
+ case '+': return PLUS;
+ case '*': return STAR;
+ case '/': return SLASH;
+ case '%': return PERCENT;
+ case '<': return LEFT_ANGLE;
+ case '>': return RIGHT_ANGLE;
+ case '|': return VERTICAL_BAR;
+ case '^': return CARET;
+ case '&': return AMPERSAND;
+ case '?': return QUESTION;
+ case '[': return LEFT_BRACKET;
+ case ']': return RIGHT_BRACKET;
+ case '{': afterStruct = false; afterBuffer = false; return LEFT_BRACE;
+ case '}': return RIGHT_BRACE;
+ case '\\':
+ parseContext.error(loc, "illegal use of escape character", "\\", "");
+ break;
+
+ case PPAtomAddAssign: return ADD_ASSIGN;
+ case PPAtomSubAssign: return SUB_ASSIGN;
+ case PPAtomMulAssign: return MUL_ASSIGN;
+ case PPAtomDivAssign: return DIV_ASSIGN;
+ case PPAtomModAssign: return MOD_ASSIGN;
+
+ case PpAtomRight: return RIGHT_OP;
+ case PpAtomLeft: return LEFT_OP;
+
+ case PpAtomRightAssign: return RIGHT_ASSIGN;
+ case PpAtomLeftAssign: return LEFT_ASSIGN;
+ case PpAtomAndAssign: return AND_ASSIGN;
+ case PpAtomOrAssign: return OR_ASSIGN;
+ case PpAtomXorAssign: return XOR_ASSIGN;
+
+ case PpAtomAnd: return AND_OP;
+ case PpAtomOr: return OR_OP;
+ case PpAtomXor: return XOR_OP;
+
+ case PpAtomEQ: return EQ_OP;
+ case PpAtomGE: return GE_OP;
+ case PpAtomNE: return NE_OP;
+ case PpAtomLE: return LE_OP;
+
+ case PpAtomDecrement: return DEC_OP;
+ case PpAtomIncrement: return INC_OP;
+
+ case PpAtomColonColon:
+ parseContext.error(loc, "not supported", "::", "");
+ break;
+
+ case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
+ case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
+ case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;
+#ifndef GLSLANG_WEB
+ case PpAtomConstInt16: parserToken->sType.lex.i = ppToken.ival; return INT16CONSTANT;
+ case PpAtomConstUint16: parserToken->sType.lex.i = ppToken.ival; return UINT16CONSTANT;
+ case PpAtomConstInt64: parserToken->sType.lex.i64 = ppToken.i64val; return INT64CONSTANT;
+ case PpAtomConstUint64: parserToken->sType.lex.i64 = ppToken.i64val; return UINT64CONSTANT;
+ case PpAtomConstDouble: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT;
+ case PpAtomConstFloat16: parserToken->sType.lex.d = ppToken.dval; return FLOAT16CONSTANT;
+#endif
+ case PpAtomIdentifier:
+ {
+ int token = tokenizeIdentifier();
+ field = false;
+ return token;
+ }
+
+ case EndOfInput: return 0;
+
+ default:
+ char buf[2];
+ buf[0] = (char)token;
+ buf[1] = 0;
+ parseContext.error(loc, "unexpected token", buf, "");
+ break;
+ }
+ } while (true);
+}
+
+int TScanContext::tokenizeIdentifier()
+{
+#ifndef GLSLANG_WEB
+ if (ReservedSet->find(tokenText) != ReservedSet->end())
+ return reservedWord();
+#endif
+
+ auto it = KeywordMap->find(tokenText);
+ if (it == KeywordMap->end()) {
+ // Should have an identifier of some sort
+ return identifierOrType();
+ }
+ keyword = it->second;
+
+ switch (keyword) {
+ case CONST:
+ case UNIFORM:
+ case IN:
+ case OUT:
+ case INOUT:
+ case BREAK:
+ case CONTINUE:
+ case DO:
+ case FOR:
+ case WHILE:
+ case IF:
+ case ELSE:
+ case DISCARD:
+ case RETURN:
+ case CASE:
+ return keyword;
+
+ case BUFFER:
+ afterBuffer = true;
+ if ((parseContext.isEsProfile() && parseContext.version < 310) ||
+ (!parseContext.isEsProfile() && parseContext.version < 430))
+ return identifierOrType();
+ return keyword;
+
+ case STRUCT:
+ afterStruct = true;
+ return keyword;
+
+ case SWITCH:
+ case DEFAULT:
+ if ((parseContext.isEsProfile() && parseContext.version < 300) ||
+ (!parseContext.isEsProfile() && parseContext.version < 130))
+ reservedWord();
+ return keyword;
+
+ case VOID:
+ case BOOL:
+ case FLOAT:
+ case INT:
+ case BVEC2:
+ case BVEC3:
+ case BVEC4:
+ case VEC2:
+ case VEC3:
+ case VEC4:
+ case IVEC2:
+ case IVEC3:
+ case IVEC4:
+ case MAT2:
+ case MAT3:
+ case MAT4:
+ case SAMPLER2D:
+ case SAMPLERCUBE:
+ afterType = true;
+ return keyword;
+
+ case BOOLCONSTANT:
+ if (strcmp("true", tokenText) == 0)
+ parserToken->sType.lex.b = true;
+ else
+ parserToken->sType.lex.b = false;
+ return keyword;
+
+ case SMOOTH:
+ if ((parseContext.isEsProfile() && parseContext.version < 300) ||
+ (!parseContext.isEsProfile() && parseContext.version < 130))
+ return identifierOrType();
+ return keyword;
+ case FLAT:
+ if (parseContext.isEsProfile() && parseContext.version < 300)
+ reservedWord();
+ else if (!parseContext.isEsProfile() && parseContext.version < 130)
+ return identifierOrType();
+ return keyword;
+ case CENTROID:
+ if (parseContext.version < 120)
+ return identifierOrType();
+ return keyword;
+ case INVARIANT:
+ if (!parseContext.isEsProfile() && parseContext.version < 120)
+ return identifierOrType();
+ return keyword;
+ case PACKED:
+ if ((parseContext.isEsProfile() && parseContext.version < 300) ||
+ (!parseContext.isEsProfile() && parseContext.version < 330))
+ return reservedWord();
+ return identifierOrType();
+
+ case RESOURCE:
+ {
+ bool reserved = (parseContext.isEsProfile() && parseContext.version >= 300) ||
+ (!parseContext.isEsProfile() && parseContext.version >= 420);
+ return identifierOrReserved(reserved);
+ }
+ case SUPERP:
+ {
+ bool reserved = parseContext.isEsProfile() || parseContext.version >= 130;
+ return identifierOrReserved(reserved);
+ }
+
+#ifndef GLSLANG_WEB
+ case NOPERSPECTIVE:
+ if (parseContext.extensionTurnedOn(E_GL_NV_shader_noperspective_interpolation))
+ return keyword;
+ return es30ReservedFromGLSL(130);
+
+ case NONUNIFORM:
+ if (parseContext.extensionTurnedOn(E_GL_EXT_nonuniform_qualifier))
+ return keyword;
+ else
+ return identifierOrType();
+ case ATTRIBUTE:
+ case VARYING:
+ if (parseContext.isEsProfile() && parseContext.version >= 300)
+ reservedWord();
+ return keyword;
+ case PAYLOADNV:
+ case PAYLOADINNV:
+ case HITATTRNV:
+ case CALLDATANV:
+ case CALLDATAINNV:
+ case ACCSTRUCTNV:
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_NV_ray_tracing))
+ return keyword;
+ return identifierOrType();
+ case ATOMIC_UINT:
+ if ((parseContext.isEsProfile() && parseContext.version >= 310) ||
+ parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
+ return keyword;
+ return es30ReservedFromGLSL(420);
+
+ case COHERENT:
+ case DEVICECOHERENT:
+ case QUEUEFAMILYCOHERENT:
+ case WORKGROUPCOHERENT:
+ case SUBGROUPCOHERENT:
+ case NONPRIVATE:
+ case RESTRICT:
+ case READONLY:
+ case WRITEONLY:
+ if (parseContext.isEsProfile() && parseContext.version >= 310)
+ return keyword;
+ return es30ReservedFromGLSL(parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store) ? 130 : 420);
+ case VOLATILE:
+ if (parseContext.isEsProfile() && parseContext.version >= 310)
+ return keyword;
+ if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.isEsProfile() ||
+ (parseContext.version < 420 && ! parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
+ reservedWord();
+ return keyword;
+ case PATCH:
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ (parseContext.isEsProfile() &&
+ (parseContext.version >= 320 ||
+ parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))) ||
+ (!parseContext.isEsProfile() && parseContext.extensionTurnedOn(E_GL_ARB_tessellation_shader)))
+ return keyword;
+
+ return es30ReservedFromGLSL(400);
+
+ case SAMPLE:
+ if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
+ parseContext.extensionsTurnedOn(1, &E_GL_OES_shader_multisample_interpolation))
+ return keyword;
+ return es30ReservedFromGLSL(400);
+
+ case SUBROUTINE:
+ return es30ReservedFromGLSL(400);
+#endif
+ case SHARED:
+ if ((parseContext.isEsProfile() && parseContext.version < 300) ||
+ (!parseContext.isEsProfile() && parseContext.version < 140))
+ return identifierOrType();
+ return keyword;
+ case LAYOUT:
+ {
+ const int numLayoutExts = 2;
+ const char* layoutExts[numLayoutExts] = { E_GL_ARB_shading_language_420pack,
+ E_GL_ARB_explicit_attrib_location };
+ if ((parseContext.isEsProfile() && parseContext.version < 300) ||
+ (!parseContext.isEsProfile() && parseContext.version < 140 &&
+ ! parseContext.extensionsTurnedOn(numLayoutExts, layoutExts)))
+ return identifierOrType();
+ return keyword;
+ }
+
+ case HIGH_PRECISION:
+ case MEDIUM_PRECISION:
+ case LOW_PRECISION:
+ case PRECISION:
+ return precisionKeyword();
+
+ case MAT2X2:
+ case MAT2X3:
+ case MAT2X4:
+ case MAT3X2:
+ case MAT3X3:
+ case MAT3X4:
+ case MAT4X2:
+ case MAT4X3:
+ case MAT4X4:
+ return matNxM();
+
+#ifndef GLSLANG_WEB
+ case DMAT2:
+ case DMAT3:
+ case DMAT4:
+ case DMAT2X2:
+ case DMAT2X3:
+ case DMAT2X4:
+ case DMAT3X2:
+ case DMAT3X3:
+ case DMAT3X4:
+ case DMAT4X2:
+ case DMAT4X3:
+ case DMAT4X4:
+ return dMat();
+
+ case IMAGE1D:
+ case IIMAGE1D:
+ case UIMAGE1D:
+ case IMAGE1DARRAY:
+ case IIMAGE1DARRAY:
+ case UIMAGE1DARRAY:
+ case IMAGE2DRECT:
+ case IIMAGE2DRECT:
+ case UIMAGE2DRECT:
+ afterType = true;
+ return firstGenerationImage(false);
+
+ case IMAGEBUFFER:
+ case IIMAGEBUFFER:
+ case UIMAGEBUFFER:
+ afterType = true;
+ if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
+ parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
+ return keyword;
+ return firstGenerationImage(false);
+
+ case IMAGE2D:
+ case IIMAGE2D:
+ case UIMAGE2D:
+ case IMAGE3D:
+ case IIMAGE3D:
+ case UIMAGE3D:
+ case IMAGECUBE:
+ case IIMAGECUBE:
+ case UIMAGECUBE:
+ case IMAGE2DARRAY:
+ case IIMAGE2DARRAY:
+ case UIMAGE2DARRAY:
+ afterType = true;
+ return firstGenerationImage(true);
+
+ case IMAGECUBEARRAY:
+ case IIMAGECUBEARRAY:
+ case UIMAGECUBEARRAY:
+ afterType = true;
+ if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
+ parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
+ return keyword;
+ return secondGenerationImage();
+
+ case IMAGE2DMS:
+ case IIMAGE2DMS:
+ case UIMAGE2DMS:
+ case IMAGE2DMSARRAY:
+ case IIMAGE2DMSARRAY:
+ case UIMAGE2DMSARRAY:
+ afterType = true;
+ return secondGenerationImage();
+
+ case DOUBLE:
+ case DVEC2:
+ case DVEC3:
+ case DVEC4:
+ afterType = true;
+ if (parseContext.isEsProfile() || parseContext.version < 150 ||
+ (!parseContext.symbolTable.atBuiltInLevel() &&
+ parseContext.version < 400 &&
+ !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)))
+ reservedWord();
+ return keyword;
+
+ case INT64_T:
+ case UINT64_T:
+ case I64VEC2:
+ case I64VEC3:
+ case I64VEC4:
+ case U64VEC2:
+ case U64VEC3:
+ case U64VEC4:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64))
+ return keyword;
+ return identifierOrType();
+
+ case INT8_T:
+ case UINT8_T:
+ case I8VEC2:
+ case I8VEC3:
+ case I8VEC4:
+ case U8VEC2:
+ case U8VEC3:
+ case U8VEC4:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_8bit_storage) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8))
+ return keyword;
+ return identifierOrType();
+
+ case INT16_T:
+ case UINT16_T:
+ case I16VEC2:
+ case I16VEC3:
+ case I16VEC4:
+ case U16VEC2:
+ case U16VEC3:
+ case U16VEC4:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16))
+ return keyword;
+ return identifierOrType();
+ case INT32_T:
+ case UINT32_T:
+ case I32VEC2:
+ case I32VEC3:
+ case I32VEC4:
+ case U32VEC2:
+ case U32VEC3:
+ case U32VEC4:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32))
+ return keyword;
+ return identifierOrType();
+ case FLOAT32_T:
+ case F32VEC2:
+ case F32VEC3:
+ case F32VEC4:
+ case F32MAT2:
+ case F32MAT3:
+ case F32MAT4:
+ case F32MAT2X2:
+ case F32MAT2X3:
+ case F32MAT2X4:
+ case F32MAT3X2:
+ case F32MAT3X3:
+ case F32MAT3X4:
+ case F32MAT4X2:
+ case F32MAT4X3:
+ case F32MAT4X4:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32))
+ return keyword;
+ return identifierOrType();
+
+ case FLOAT64_T:
+ case F64VEC2:
+ case F64VEC3:
+ case F64VEC4:
+ case F64MAT2:
+ case F64MAT3:
+ case F64MAT4:
+ case F64MAT2X2:
+ case F64MAT2X3:
+ case F64MAT2X4:
+ case F64MAT3X2:
+ case F64MAT3X3:
+ case F64MAT3X4:
+ case F64MAT4X2:
+ case F64MAT4X3:
+ case F64MAT4X4:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64))
+ return keyword;
+ return identifierOrType();
+
+ case FLOAT16_T:
+ case F16VEC2:
+ case F16VEC3:
+ case F16VEC4:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16))
+ return keyword;
+
+ return identifierOrType();
+
+ case F16MAT2:
+ case F16MAT3:
+ case F16MAT4:
+ case F16MAT2X2:
+ case F16MAT2X3:
+ case F16MAT2X4:
+ case F16MAT3X2:
+ case F16MAT3X3:
+ case F16MAT3X4:
+ case F16MAT4X2:
+ case F16MAT4X3:
+ case F16MAT4X4:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16))
+ return keyword;
+
+ return identifierOrType();
+
+ case SAMPLERCUBEARRAY:
+ case SAMPLERCUBEARRAYSHADOW:
+ case ISAMPLERCUBEARRAY:
+ case USAMPLERCUBEARRAY:
+ afterType = true;
+ if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
+ parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
+ return keyword;
+ if (parseContext.isEsProfile() || (parseContext.version < 400 && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_cube_map_array)))
+ reservedWord();
+ return keyword;
+
+ case TEXTURECUBEARRAY:
+ case ITEXTURECUBEARRAY:
+ case UTEXTURECUBEARRAY:
+ if (parseContext.spvVersion.vulkan > 0)
+ return keyword;
+ else
+ return identifierOrType();
+#endif
+
+ case UINT:
+ case UVEC2:
+ case UVEC3:
+ case UVEC4:
+ case SAMPLERCUBESHADOW:
+ case SAMPLER2DARRAY:
+ case SAMPLER2DARRAYSHADOW:
+ case ISAMPLER2D:
+ case ISAMPLER3D:
+ case ISAMPLERCUBE:
+ case ISAMPLER2DARRAY:
+ case USAMPLER2D:
+ case USAMPLER3D:
+ case USAMPLERCUBE:
+ case USAMPLER2DARRAY:
+ afterType = true;
+ return nonreservedKeyword(300, 130);
+
+ case SAMPLER3D:
+ afterType = true;
+ if (parseContext.isEsProfile() && parseContext.version < 300) {
+ if (!parseContext.extensionTurnedOn(E_GL_OES_texture_3D))
+ reservedWord();
+ }
+ return keyword;
+
+ case SAMPLER2DSHADOW:
+ afterType = true;
+ if (parseContext.isEsProfile() && parseContext.version < 300) {
+ if (!parseContext.extensionTurnedOn(E_GL_EXT_shadow_samplers))
+ reservedWord();
+ }
+ return keyword;
+
+ case TEXTURE2D:
+ case TEXTURECUBE:
+ case TEXTURE2DARRAY:
+ case ITEXTURE2D:
+ case ITEXTURE3D:
+ case ITEXTURECUBE:
+ case ITEXTURE2DARRAY:
+ case UTEXTURE2D:
+ case UTEXTURE3D:
+ case UTEXTURECUBE:
+ case UTEXTURE2DARRAY:
+ case TEXTURE3D:
+ case SAMPLER:
+ case SAMPLERSHADOW:
+ if (parseContext.spvVersion.vulkan > 0)
+ return keyword;
+ else
+ return identifierOrType();
+
+#ifndef GLSLANG_WEB
+ case ISAMPLER1D:
+ case ISAMPLER1DARRAY:
+ case SAMPLER1DARRAYSHADOW:
+ case USAMPLER1D:
+ case USAMPLER1DARRAY:
+ afterType = true;
+ return es30ReservedFromGLSL(130);
+ case ISAMPLER2DRECT:
+ case USAMPLER2DRECT:
+ afterType = true;
+ return es30ReservedFromGLSL(140);
+
+ case SAMPLERBUFFER:
+ afterType = true;
+ if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
+ parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
+ return keyword;
+ return es30ReservedFromGLSL(130);
+
+ case ISAMPLERBUFFER:
+ case USAMPLERBUFFER:
+ afterType = true;
+ if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
+ parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
+ return keyword;
+ return es30ReservedFromGLSL(140);
+
+ case SAMPLER2DMS:
+ case ISAMPLER2DMS:
+ case USAMPLER2DMS:
+ afterType = true;
+ if (parseContext.isEsProfile() && parseContext.version >= 310)
+ return keyword;
+ if (!parseContext.isEsProfile() && (parseContext.version > 140 ||
+ (parseContext.version == 140 && parseContext.extensionsTurnedOn(1, &E_GL_ARB_texture_multisample))))
+ return keyword;
+ return es30ReservedFromGLSL(150);
+
+ case SAMPLER2DMSARRAY:
+ case ISAMPLER2DMSARRAY:
+ case USAMPLER2DMSARRAY:
+ afterType = true;
+ if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
+ parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array))
+ return keyword;
+ if (!parseContext.isEsProfile() && (parseContext.version > 140 ||
+ (parseContext.version == 140 && parseContext.extensionsTurnedOn(1, &E_GL_ARB_texture_multisample))))
+ return keyword;
+ return es30ReservedFromGLSL(150);
+
+ case SAMPLER1D:
+ case SAMPLER1DSHADOW:
+ afterType = true;
+ if (parseContext.isEsProfile())
+ reservedWord();
+ return keyword;
+
+ case SAMPLER2DRECT:
+ case SAMPLER2DRECTSHADOW:
+ afterType = true;
+ if (parseContext.isEsProfile())
+ reservedWord();
+ else if (parseContext.version < 140 && ! parseContext.symbolTable.atBuiltInLevel() && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_rectangle)) {
+ if (parseContext.relaxedErrors())
+ parseContext.requireExtensions(loc, 1, &E_GL_ARB_texture_rectangle, "texture-rectangle sampler keyword");
+ else
+ reservedWord();
+ }
+ return keyword;
+
+ case SAMPLER1DARRAY:
+ afterType = true;
+ if (parseContext.isEsProfile() && parseContext.version == 300)
+ reservedWord();
+ else if ((parseContext.isEsProfile() && parseContext.version < 300) ||
+ (!parseContext.isEsProfile() && parseContext.version < 130))
+ return identifierOrType();
+ return keyword;
+
+ case SAMPLEREXTERNALOES:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external) ||
+ parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external_essl3))
+ return keyword;
+ return identifierOrType();
+
+ case SAMPLEREXTERNAL2DY2YEXT:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_EXT_YUV_target))
+ return keyword;
+ return identifierOrType();
+
+ case ITEXTURE1DARRAY:
+ case UTEXTURE1D:
+ case ITEXTURE1D:
+ case UTEXTURE1DARRAY:
+ case TEXTUREBUFFER:
+ case ITEXTURE2DRECT:
+ case UTEXTURE2DRECT:
+ case ITEXTUREBUFFER:
+ case UTEXTUREBUFFER:
+ case TEXTURE2DMS:
+ case ITEXTURE2DMS:
+ case UTEXTURE2DMS:
+ case TEXTURE2DMSARRAY:
+ case ITEXTURE2DMSARRAY:
+ case UTEXTURE2DMSARRAY:
+ case TEXTURE1D:
+ case TEXTURE2DRECT:
+ case TEXTURE1DARRAY:
+ if (parseContext.spvVersion.vulkan > 0)
+ return keyword;
+ else
+ return identifierOrType();
+
+ case SUBPASSINPUT:
+ case SUBPASSINPUTMS:
+ case ISUBPASSINPUT:
+ case ISUBPASSINPUTMS:
+ case USUBPASSINPUT:
+ case USUBPASSINPUTMS:
+ if (parseContext.spvVersion.vulkan > 0)
+ return keyword;
+ else
+ return identifierOrType();
+
+ case F16SAMPLER1D:
+ case F16SAMPLER2D:
+ case F16SAMPLER3D:
+ case F16SAMPLER2DRECT:
+ case F16SAMPLERCUBE:
+ case F16SAMPLER1DARRAY:
+ case F16SAMPLER2DARRAY:
+ case F16SAMPLERCUBEARRAY:
+ case F16SAMPLERBUFFER:
+ case F16SAMPLER2DMS:
+ case F16SAMPLER2DMSARRAY:
+ case F16SAMPLER1DSHADOW:
+ case F16SAMPLER2DSHADOW:
+ case F16SAMPLER1DARRAYSHADOW:
+ case F16SAMPLER2DARRAYSHADOW:
+ case F16SAMPLER2DRECTSHADOW:
+ case F16SAMPLERCUBESHADOW:
+ case F16SAMPLERCUBEARRAYSHADOW:
+
+ case F16IMAGE1D:
+ case F16IMAGE2D:
+ case F16IMAGE3D:
+ case F16IMAGE2DRECT:
+ case F16IMAGECUBE:
+ case F16IMAGE1DARRAY:
+ case F16IMAGE2DARRAY:
+ case F16IMAGECUBEARRAY:
+ case F16IMAGEBUFFER:
+ case F16IMAGE2DMS:
+ case F16IMAGE2DMSARRAY:
+
+ case F16TEXTURE1D:
+ case F16TEXTURE2D:
+ case F16TEXTURE3D:
+ case F16TEXTURE2DRECT:
+ case F16TEXTURECUBE:
+ case F16TEXTURE1DARRAY:
+ case F16TEXTURE2DARRAY:
+ case F16TEXTURECUBEARRAY:
+ case F16TEXTUREBUFFER:
+ case F16TEXTURE2DMS:
+ case F16TEXTURE2DMSARRAY:
+
+ case F16SUBPASSINPUT:
+ case F16SUBPASSINPUTMS:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float_fetch))
+ return keyword;
+ return identifierOrType();
+
+ case EXPLICITINTERPAMD:
+ if (parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter))
+ return keyword;
+ return identifierOrType();
+
+ case PERVERTEXNV:
+ if ((!parseContext.isEsProfile() && parseContext.version >= 450) ||
+ parseContext.extensionTurnedOn(E_GL_NV_fragment_shader_barycentric))
+ return keyword;
+ return identifierOrType();
+
+ case PRECISE:
+ if ((parseContext.isEsProfile() &&
+ (parseContext.version >= 320 || parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5))) ||
+ (!parseContext.isEsProfile() && parseContext.version >= 400))
+ return keyword;
+ if (parseContext.isEsProfile() && parseContext.version == 310) {
+ reservedWord();
+ return keyword;
+ }
+ return identifierOrType();
+
+ case PERPRIMITIVENV:
+ case PERVIEWNV:
+ case PERTASKNV:
+ if ((!parseContext.isEsProfile() && parseContext.version >= 450) ||
+ (parseContext.isEsProfile() && parseContext.version >= 320) ||
+ parseContext.extensionTurnedOn(E_GL_NV_mesh_shader))
+ return keyword;
+ return identifierOrType();
+
+ case FCOOPMATNV:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_NV_cooperative_matrix))
+ return keyword;
+ return identifierOrType();
+
+ case UCOOPMATNV:
+ case ICOOPMATNV:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ parseContext.extensionTurnedOn(E_GL_NV_integer_cooperative_matrix))
+ return keyword;
+ return identifierOrType();
+
+ case DEMOTE:
+ if (parseContext.extensionTurnedOn(E_GL_EXT_demote_to_helper_invocation))
+ return keyword;
+ else
+ return identifierOrType();
+#endif
+
+ default:
+ parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
+ return 0;
+ }
+}
+
+int TScanContext::identifierOrType()
+{
+ parserToken->sType.lex.string = NewPoolTString(tokenText);
+ if (field)
+ return IDENTIFIER;
+
+ parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string);
+ if ((afterType == false && afterStruct == false) && parserToken->sType.lex.symbol != nullptr) {
+ if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) {
+ if (variable->isUserType() &&
+ // treat redeclaration of forward-declared buffer/uniform reference as an identifier
+ !(variable->getType().isReference() && afterBuffer)) {
+ afterType = true;
+
+ return TYPE_NAME;
+ }
+ }
+ }
+
+ return IDENTIFIER;
+}
+
+// Give an error for use of a reserved symbol.
+// However, allow built-in declarations to use reserved words, to allow
+// extension support before the extension is enabled.
+int TScanContext::reservedWord()
+{
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.error(loc, "Reserved word.", tokenText, "", "");
+
+ return 0;
+}
+
+int TScanContext::identifierOrReserved(bool reserved)
+{
+ if (reserved) {
+ reservedWord();
+
+ return 0;
+ }
+
+ if (parseContext.isForwardCompatible())
+ parseContext.warn(loc, "using future reserved keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+// For keywords that suddenly showed up on non-ES (not previously reserved)
+// but then got reserved by ES 3.0.
+int TScanContext::es30ReservedFromGLSL(int version)
+{
+ if (parseContext.symbolTable.atBuiltInLevel())
+ return keyword;
+
+ if ((parseContext.isEsProfile() && parseContext.version < 300) ||
+ (!parseContext.isEsProfile() && parseContext.version < version)) {
+ if (parseContext.isForwardCompatible())
+ parseContext.warn(loc, "future reserved word in ES 300 and keyword in GLSL", tokenText, "");
+
+ return identifierOrType();
+ } else if (parseContext.isEsProfile() && parseContext.version >= 300)
+ reservedWord();
+
+ return keyword;
+}
+
+// For a keyword that was never reserved, until it suddenly
+// showed up, both in an es version and a non-ES version.
+int TScanContext::nonreservedKeyword(int esVersion, int nonEsVersion)
+{
+ if ((parseContext.isEsProfile() && parseContext.version < esVersion) ||
+ (!parseContext.isEsProfile() && parseContext.version < nonEsVersion)) {
+ if (parseContext.isForwardCompatible())
+ parseContext.warn(loc, "using future keyword", tokenText, "");
+
+ return identifierOrType();
+ }
+
+ return keyword;
+}
+
+int TScanContext::precisionKeyword()
+{
+ if (parseContext.isEsProfile() || parseContext.version >= 130)
+ return keyword;
+
+ if (parseContext.isForwardCompatible())
+ parseContext.warn(loc, "using ES precision qualifier keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+int TScanContext::matNxM()
+{
+ afterType = true;
+
+ if (parseContext.version > 110)
+ return keyword;
+
+ if (parseContext.isForwardCompatible())
+ parseContext.warn(loc, "using future non-square matrix type keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+int TScanContext::dMat()
+{
+ afterType = true;
+
+ if (parseContext.isEsProfile() && parseContext.version >= 300) {
+ reservedWord();
+
+ return keyword;
+ }
+
+ if (!parseContext.isEsProfile() && (parseContext.version >= 400 ||
+ parseContext.symbolTable.atBuiltInLevel() ||
+ (parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64))))
+ return keyword;
+
+ if (parseContext.isForwardCompatible())
+ parseContext.warn(loc, "using future type keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+int TScanContext::firstGenerationImage(bool inEs310)
+{
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ (!parseContext.isEsProfile() && (parseContext.version >= 420 ||
+ parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))) ||
+ (inEs310 && parseContext.isEsProfile() && parseContext.version >= 310))
+ return keyword;
+
+ if ((parseContext.isEsProfile() && parseContext.version >= 300) ||
+ (!parseContext.isEsProfile() && parseContext.version >= 130)) {
+ reservedWord();
+
+ return keyword;
+ }
+
+ if (parseContext.isForwardCompatible())
+ parseContext.warn(loc, "using future type keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+int TScanContext::secondGenerationImage()
+{
+ if (parseContext.isEsProfile() && parseContext.version >= 310) {
+ reservedWord();
+ return keyword;
+ }
+
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ (!parseContext.isEsProfile() &&
+ (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
+ return keyword;
+
+ if (parseContext.isForwardCompatible())
+ parseContext.warn(loc, "using future type keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/Scan.h b/thirdparty/glslang/glslang/MachineIndependent/Scan.h
new file mode 100644
index 0000000000..24b75cf7ca
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/Scan.h
@@ -0,0 +1,276 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+#ifndef _GLSLANG_SCAN_INCLUDED_
+#define _GLSLANG_SCAN_INCLUDED_
+
+#include "Versions.h"
+
+namespace glslang {
+
+// Use a global end-of-input character, so no translation is needed across
+// layers of encapsulation. Characters are all 8 bit, and positive, so there is
+// no aliasing of character 255 onto -1, for example.
+const int EndOfInput = -1;
+
+//
+// A character scanner that seamlessly, on read-only strings, reads across an
+// array of strings without assuming null termination.
+//
+class TInputScanner {
+public:
+ TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr,
+ int b = 0, int f = 0, bool single = false) :
+ numSources(n),
+ // up to this point, common usage is "char*", but now we need positive 8-bit characters
+ sources(reinterpret_cast<const unsigned char* const *>(s)),
+ lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single),
+ endOfFileReached(false)
+ {
+ loc = new TSourceLoc[numSources];
+ for (int i = 0; i < numSources; ++i) {
+ loc[i].init(i - stringBias);
+ }
+ if (names != nullptr) {
+ for (int i = 0; i < numSources; ++i)
+ loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr;
+ }
+ loc[currentSource].line = 1;
+ logicalSourceLoc.init(1);
+ logicalSourceLoc.name = loc[0].name;
+ }
+
+ virtual ~TInputScanner()
+ {
+ delete [] loc;
+ }
+
+ // retrieve the next character and advance one character
+ int get()
+ {
+ int ret = peek();
+ if (ret == EndOfInput)
+ return ret;
+ ++loc[currentSource].column;
+ ++logicalSourceLoc.column;
+ if (ret == '\n') {
+ ++loc[currentSource].line;
+ ++logicalSourceLoc.line;
+ logicalSourceLoc.column = 0;
+ loc[currentSource].column = 0;
+ }
+ advance();
+
+ return ret;
+ }
+
+ // retrieve the next character, no advance
+ int peek()
+ {
+ if (currentSource >= numSources) {
+ endOfFileReached = true;
+ return EndOfInput;
+ }
+ // Make sure we do not read off the end of a string.
+ // N.B. Sources can have a length of 0.
+ int sourceToRead = currentSource;
+ size_t charToRead = currentChar;
+ while(charToRead >= lengths[sourceToRead]) {
+ charToRead = 0;
+ sourceToRead += 1;
+ if (sourceToRead >= numSources) {
+ return EndOfInput;
+ }
+ }
+
+ // Here, we care about making negative valued characters positive
+ return sources[sourceToRead][charToRead];
+ }
+
+ // go back one character
+ void unget()
+ {
+ // Do not roll back once we've reached the end of the file.
+ if (endOfFileReached)
+ return;
+
+ if (currentChar > 0) {
+ --currentChar;
+ --loc[currentSource].column;
+ --logicalSourceLoc.column;
+ if (loc[currentSource].column < 0) {
+ // We've moved back past a new line. Find the
+ // previous newline (or start of the file) to compute
+ // the column count on the now current line.
+ size_t chIndex = currentChar;
+ while (chIndex > 0) {
+ if (sources[currentSource][chIndex] == '\n') {
+ break;
+ }
+ --chIndex;
+ }
+ logicalSourceLoc.column = (int)(currentChar - chIndex);
+ loc[currentSource].column = (int)(currentChar - chIndex);
+ }
+ } else {
+ do {
+ --currentSource;
+ } while (currentSource > 0 && lengths[currentSource] == 0);
+ if (lengths[currentSource] == 0) {
+ // set to 0 if we've backed up to the start of an empty string
+ currentChar = 0;
+ } else
+ currentChar = lengths[currentSource] - 1;
+ }
+ if (peek() == '\n') {
+ --loc[currentSource].line;
+ --logicalSourceLoc.line;
+ }
+ }
+
+ // for #line override
+ void setLine(int newLine)
+ {
+ logicalSourceLoc.line = newLine;
+ loc[getLastValidSourceIndex()].line = newLine;
+ }
+
+ // for #line override in filename based parsing
+ void setFile(const char* filename)
+ {
+ TString* fn_tstr = NewPoolTString(filename);
+ logicalSourceLoc.name = fn_tstr;
+ loc[getLastValidSourceIndex()].name = fn_tstr;
+ }
+
+ void setFile(const char* filename, int i)
+ {
+ TString* fn_tstr = NewPoolTString(filename);
+ if (i == getLastValidSourceIndex()) {
+ logicalSourceLoc.name = fn_tstr;
+ }
+ loc[i].name = fn_tstr;
+ }
+
+ void setString(int newString)
+ {
+ logicalSourceLoc.string = newString;
+ loc[getLastValidSourceIndex()].string = newString;
+ logicalSourceLoc.name = nullptr;
+ loc[getLastValidSourceIndex()].name = nullptr;
+ }
+
+ // for #include content indentation
+ void setColumn(int col)
+ {
+ logicalSourceLoc.column = col;
+ loc[getLastValidSourceIndex()].column = col;
+ }
+
+ void setEndOfInput()
+ {
+ endOfFileReached = true;
+ currentSource = numSources;
+ }
+
+ bool atEndOfInput() const { return endOfFileReached; }
+
+ const TSourceLoc& getSourceLoc() const
+ {
+ if (singleLogical) {
+ return logicalSourceLoc;
+ } else {
+ return loc[std::max(0, std::min(currentSource, numSources - finale - 1))];
+ }
+ }
+ // Returns the index (starting from 0) of the most recent valid source string we are reading from.
+ int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); }
+
+ void consumeWhiteSpace(bool& foundNonSpaceTab);
+ bool consumeComment();
+ void consumeWhitespaceComment(bool& foundNonSpaceTab);
+ bool scanVersion(int& version, EProfile& profile, bool& notFirstToken);
+
+protected:
+
+ // advance one character
+ void advance()
+ {
+ ++currentChar;
+ if (currentChar >= lengths[currentSource]) {
+ ++currentSource;
+ if (currentSource < numSources) {
+ loc[currentSource].string = loc[currentSource - 1].string + 1;
+ loc[currentSource].line = 1;
+ loc[currentSource].column = 0;
+ }
+ while (currentSource < numSources && lengths[currentSource] == 0) {
+ ++currentSource;
+ if (currentSource < numSources) {
+ loc[currentSource].string = loc[currentSource - 1].string + 1;
+ loc[currentSource].line = 1;
+ loc[currentSource].column = 0;
+ }
+ }
+ currentChar = 0;
+ }
+ }
+
+ int numSources; // number of strings in source
+ const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput
+ const size_t *lengths; // length of each string
+ int currentSource;
+ size_t currentChar;
+
+ // This is for reporting what string/line an error occurred on, and can be overridden by #line.
+ // It remembers the last state of each source string as it is left for the next one, so unget()
+ // can restore that state.
+ TSourceLoc* loc; // an array
+
+ int stringBias; // the first string that is the user's string number 0
+ int finale; // number of internal strings after user's last string
+
+ TSourceLoc logicalSourceLoc;
+ bool singleLogical; // treats the strings as a single logical string.
+ // locations will be reported from the first string.
+
+ // Set to true once peek() returns EndOfFile, so that we won't roll back
+ // once we've reached EndOfFile.
+ bool endOfFileReached;
+};
+
+} // end namespace glslang
+
+#endif // _GLSLANG_SCAN_INCLUDED_
diff --git a/thirdparty/glslang/glslang/MachineIndependent/ScanContext.h b/thirdparty/glslang/glslang/MachineIndependent/ScanContext.h
new file mode 100644
index 0000000000..74b2b3c746
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/ScanContext.h
@@ -0,0 +1,93 @@
+//
+// Copyright (C) 2013 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// This holds context specific to the GLSL scanner, which
+// sits between the preprocessor scanner and parser.
+//
+
+#pragma once
+
+#include "ParseHelper.h"
+
+namespace glslang {
+
+class TPpContext;
+class TPpToken;
+class TParserToken;
+
+class TScanContext {
+public:
+ explicit TScanContext(TParseContextBase& pc) :
+ parseContext(pc),
+ afterType(false), afterStruct(false),
+ field(false), afterBuffer(false) { }
+ virtual ~TScanContext() { }
+
+ static void fillInKeywordMap();
+ static void deleteKeywordMap();
+
+ int tokenize(TPpContext*, TParserToken&);
+
+protected:
+ TScanContext(TScanContext&);
+ TScanContext& operator=(TScanContext&);
+
+ int tokenizeIdentifier();
+ int identifierOrType();
+ int reservedWord();
+ int identifierOrReserved(bool reserved);
+ int es30ReservedFromGLSL(int version);
+ int nonreservedKeyword(int esVersion, int nonEsVersion);
+ int precisionKeyword();
+ int matNxM();
+ int dMat();
+ int firstGenerationImage(bool inEs310);
+ int secondGenerationImage();
+
+ TParseContextBase& parseContext;
+ bool afterType; // true if we've recognized a type, so can only be looking for an identifier
+ bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier
+ bool field; // true if we're on a field, right after a '.'
+ bool afterBuffer; // true if we've recognized the BUFFER keyword
+ TSourceLoc loc;
+ TParserToken* parserToken;
+ TPpToken* ppToken;
+
+ const char* tokenText;
+ int keyword;
+};
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp b/thirdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp
new file mode 100644
index 0000000000..44ce1c19d1
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp
@@ -0,0 +1,2110 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013-2016 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Implement the top-level of interface to the compiler/linker,
+// as defined in ShaderLang.h
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler/linker.
+//
+#include <cstring>
+#include <iostream>
+#include <sstream>
+#include <memory>
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "Scan.h"
+#include "ScanContext.h"
+
+#ifdef ENABLE_HLSL
+#include "../../hlsl/hlslParseHelper.h"
+#include "../../hlsl/hlslParseables.h"
+#include "../../hlsl/hlslScanContext.h"
+#endif
+
+#include "../Include/ShHandle.h"
+#include "../../OGLCompilersDLL/InitializeDll.h"
+
+#include "preprocessor/PpContext.h"
+
+#define SH_EXPORTING
+#include "../Public/ShaderLang.h"
+#include "reflection.h"
+#include "iomapper.h"
+#include "Initialize.h"
+
+// TODO: this really shouldn't be here, it is only because of the trial addition
+// of printing pre-processed tokens, which requires knowing the string literal
+// token to print ", but none of that seems appropriate for this file.
+#include "preprocessor/PpTokens.h"
+
+namespace { // anonymous namespace for file-local functions and symbols
+
+// Total number of successful initializers of glslang: a refcount
+// Shared global; access should be protected by a global mutex/critical section.
+int NumberOfClients = 0;
+
+using namespace glslang;
+
+// Create a language specific version of parseables.
+TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink, EShSource source)
+{
+ switch (source) {
+ case EShSourceGlsl: return new TBuiltIns(); // GLSL builtIns
+#ifdef ENABLE_HLSL
+ case EShSourceHlsl: return new TBuiltInParseablesHlsl(); // HLSL intrinsics
+#endif
+
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
+ return nullptr;
+ }
+}
+
+// Create a language specific version of a parse context.
+TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& intermediate,
+ int version, EProfile profile, EShSource source,
+ EShLanguage language, TInfoSink& infoSink,
+ SpvVersion spvVersion, bool forwardCompatible, EShMessages messages,
+ bool parsingBuiltIns, std::string sourceEntryPointName = "")
+{
+ switch (source) {
+ case EShSourceGlsl: {
+ if (sourceEntryPointName.size() == 0)
+ intermediate.setEntryPointName("main");
+ TString entryPoint = sourceEntryPointName.c_str();
+ return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
+ language, infoSink, forwardCompatible, messages, &entryPoint);
+ }
+#ifdef ENABLE_HLSL
+ case EShSourceHlsl:
+ return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
+ language, infoSink, sourceEntryPointName.c_str(), forwardCompatible, messages);
+#endif
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
+ return nullptr;
+ }
+}
+
+// Local mapping functions for making arrays of symbol tables....
+
+const int VersionCount = 17; // index range in MapVersionToIndex
+
+int MapVersionToIndex(int version)
+{
+ int index = 0;
+
+ switch (version) {
+ case 100: index = 0; break;
+ case 110: index = 1; break;
+ case 120: index = 2; break;
+ case 130: index = 3; break;
+ case 140: index = 4; break;
+ case 150: index = 5; break;
+ case 300: index = 6; break;
+ case 330: index = 7; break;
+ case 400: index = 8; break;
+ case 410: index = 9; break;
+ case 420: index = 10; break;
+ case 430: index = 11; break;
+ case 440: index = 12; break;
+ case 310: index = 13; break;
+ case 450: index = 14; break;
+ case 500: index = 0; break; // HLSL
+ case 320: index = 15; break;
+ case 460: index = 16; break;
+ default: assert(0); break;
+ }
+
+ assert(index < VersionCount);
+
+ return index;
+}
+
+const int SpvVersionCount = 3; // index range in MapSpvVersionToIndex
+
+int MapSpvVersionToIndex(const SpvVersion& spvVersion)
+{
+ int index = 0;
+
+ if (spvVersion.openGl > 0)
+ index = 1;
+ else if (spvVersion.vulkan > 0)
+ index = 2;
+
+ assert(index < SpvVersionCount);
+
+ return index;
+}
+
+const int ProfileCount = 4; // index range in MapProfileToIndex
+
+int MapProfileToIndex(EProfile profile)
+{
+ int index = 0;
+
+ switch (profile) {
+ case ENoProfile: index = 0; break;
+ case ECoreProfile: index = 1; break;
+ case ECompatibilityProfile: index = 2; break;
+ case EEsProfile: index = 3; break;
+ default: break;
+ }
+
+ assert(index < ProfileCount);
+
+ return index;
+}
+
+const int SourceCount = 2;
+
+int MapSourceToIndex(EShSource source)
+{
+ int index = 0;
+
+ switch (source) {
+ case EShSourceGlsl: index = 0; break;
+ case EShSourceHlsl: index = 1; break;
+ default: break;
+ }
+
+ assert(index < SourceCount);
+
+ return index;
+}
+
+// only one of these needed for non-ES; ES needs 2 for different precision defaults of built-ins
+enum EPrecisionClass {
+ EPcGeneral,
+ EPcFragment,
+ EPcCount
+};
+
+// A process-global symbol table per version per profile for built-ins common
+// to multiple stages (languages), and a process-global symbol table per version
+// per profile per stage for built-ins unique to each stage. They will be sparsely
+// populated, so they will only be generated as needed.
+//
+// Each has a different set of built-ins, and we want to preserve that from
+// compile to compile.
+//
+TSymbolTable* CommonSymbolTable[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EPcCount] = {};
+TSymbolTable* SharedSymbolTables[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EShLangCount] = {};
+
+TPoolAllocator* PerProcessGPA = nullptr;
+
+//
+// Parse and add to the given symbol table the content of the given shader string.
+//
+bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
+ EShSource source, TInfoSink& infoSink, TSymbolTable& symbolTable)
+{
+ TIntermediate intermediate(language, version, profile);
+
+ intermediate.setSource(source);
+
+ std::unique_ptr<TParseContextBase> parseContext(CreateParseContext(symbolTable, intermediate, version, profile, source,
+ language, infoSink, spvVersion, true, EShMsgDefault,
+ true));
+
+ TShader::ForbidIncluder includer;
+ TPpContext ppContext(*parseContext, "", includer);
+ TScanContext scanContext(*parseContext);
+ parseContext->setScanContext(&scanContext);
+ parseContext->setPpContext(&ppContext);
+
+ //
+ // Push the symbol table to give it an initial scope. This
+ // push should not have a corresponding pop, so that built-ins
+ // are preserved, and the test for an empty table fails.
+ //
+
+ symbolTable.push();
+
+ const char* builtInShaders[2];
+ size_t builtInLengths[2];
+ builtInShaders[0] = builtIns.c_str();
+ builtInLengths[0] = builtIns.size();
+
+ if (builtInLengths[0] == 0)
+ return true;
+
+ TInputScanner input(1, builtInShaders, builtInLengths);
+ if (! parseContext->parseShaderStrings(ppContext, input) != 0) {
+ infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
+ printf("Unable to parse built-ins\n%s\n", infoSink.info.c_str());
+ printf("%s\n", builtInShaders[0]);
+
+ return false;
+ }
+
+ return true;
+}
+
+int CommonIndex(EProfile profile, EShLanguage language)
+{
+ return (profile == EEsProfile && language == EShLangFragment) ? EPcFragment : EPcGeneral;
+}
+
+//
+// To initialize per-stage shared tables, with the common table already complete.
+//
+void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int version, EProfile profile, const SpvVersion& spvVersion,
+ EShLanguage language, EShSource source, TInfoSink& infoSink, TSymbolTable** commonTable,
+ TSymbolTable** symbolTables)
+{
+#ifdef GLSLANG_WEB
+ profile = EEsProfile;
+ version = 310;
+#endif
+
+ (*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]);
+ InitializeSymbolTable(builtInParseables.getStageString(language), version, profile, spvVersion, language, source,
+ infoSink, *symbolTables[language]);
+ builtInParseables.identifyBuiltIns(version, profile, spvVersion, language, *symbolTables[language]);
+ if (profile == EEsProfile && version >= 300)
+ (*symbolTables[language]).setNoBuiltInRedeclarations();
+ if (version == 110)
+ (*symbolTables[language]).setSeparateNameSpaces();
+}
+
+//
+// Initialize the full set of shareable symbol tables;
+// The common (cross-stage) and those shareable per-stage.
+//
+bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables, int version, EProfile profile, const SpvVersion& spvVersion, EShSource source)
+{
+#ifdef GLSLANG_WEB
+ profile = EEsProfile;
+ version = 310;
+#endif
+
+ std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
+
+ if (builtInParseables == nullptr)
+ return false;
+
+ builtInParseables->initialize(version, profile, spvVersion);
+
+ // do the common tables
+ InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangVertex, source,
+ infoSink, *commonTable[EPcGeneral]);
+ if (profile == EEsProfile)
+ InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangFragment, source,
+ infoSink, *commonTable[EPcFragment]);
+
+ // do the per-stage tables
+
+ // always have vertex and fragment
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangVertex, source,
+ infoSink, commonTable, symbolTables);
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangFragment, source,
+ infoSink, commonTable, symbolTables);
+
+#ifndef GLSLANG_WEB
+ // check for tessellation
+ if ((profile != EEsProfile && version >= 150) ||
+ (profile == EEsProfile && version >= 310)) {
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessControl, source,
+ infoSink, commonTable, symbolTables);
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessEvaluation, source,
+ infoSink, commonTable, symbolTables);
+ }
+
+ // check for geometry
+ if ((profile != EEsProfile && version >= 150) ||
+ (profile == EEsProfile && version >= 310))
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source,
+ infoSink, commonTable, symbolTables);
+#endif
+
+ // check for compute
+ if ((profile != EEsProfile && version >= 420) ||
+ (profile == EEsProfile && version >= 310))
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source,
+ infoSink, commonTable, symbolTables);
+
+ // check for ray tracing stages
+ if (profile != EEsProfile && version >= 450) {
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source,
+ infoSink, commonTable, symbolTables);
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source,
+ infoSink, commonTable, symbolTables);
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source,
+ infoSink, commonTable, symbolTables);
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source,
+ infoSink, commonTable, symbolTables);
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source,
+ infoSink, commonTable, symbolTables);
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source,
+ infoSink, commonTable, symbolTables);
+ }
+
+ // check for mesh
+ if ((profile != EEsProfile && version >= 450) ||
+ (profile == EEsProfile && version >= 320))
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMeshNV, source,
+ infoSink, commonTable, symbolTables);
+
+ // check for task
+ if ((profile != EEsProfile && version >= 450) ||
+ (profile == EEsProfile && version >= 320))
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source,
+ infoSink, commonTable, symbolTables);
+
+ return true;
+}
+
+bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable& symbolTable, int version,
+ EProfile profile, const SpvVersion& spvVersion, EShLanguage language, EShSource source)
+{
+ std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
+
+ if (builtInParseables == nullptr)
+ return false;
+
+ builtInParseables->initialize(*resources, version, profile, spvVersion, language);
+ InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, language, source, infoSink, symbolTable);
+ builtInParseables->identifyBuiltIns(version, profile, spvVersion, language, symbolTable, *resources);
+
+ return true;
+}
+
+//
+// To do this on the fly, we want to leave the current state of our thread's
+// pool allocator intact, so:
+// - Switch to a new pool for parsing the built-ins
+// - Do the parsing, which builds the symbol table, using the new pool
+// - Switch to the process-global pool to save a copy of the resulting symbol table
+// - Free up the new pool used to parse the built-ins
+// - Switch back to the original thread's pool
+//
+// This only gets done the first time any thread needs a particular symbol table
+// (lazy evaluation).
+//
+void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& spvVersion, EShSource source)
+{
+ TInfoSink infoSink;
+
+ // Make sure only one thread tries to do this at a time
+ glslang::GetGlobalLock();
+
+ // See if it's already been done for this version/profile combination
+ int versionIndex = MapVersionToIndex(version);
+ int spvVersionIndex = MapSpvVersionToIndex(spvVersion);
+ int profileIndex = MapProfileToIndex(profile);
+ int sourceIndex = MapSourceToIndex(source);
+ if (CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][EPcGeneral]) {
+ glslang::ReleaseGlobalLock();
+
+ return;
+ }
+
+ // Switch to a new pool
+ TPoolAllocator& previousAllocator = GetThreadPoolAllocator();
+ TPoolAllocator* builtInPoolAllocator = new TPoolAllocator;
+ SetThreadPoolAllocator(builtInPoolAllocator);
+
+ // Dynamically allocate the local symbol tables so we can control when they are deallocated WRT when the pool is popped.
+ TSymbolTable* commonTable[EPcCount];
+ TSymbolTable* stageTables[EShLangCount];
+ for (int precClass = 0; precClass < EPcCount; ++precClass)
+ commonTable[precClass] = new TSymbolTable;
+ for (int stage = 0; stage < EShLangCount; ++stage)
+ stageTables[stage] = new TSymbolTable;
+
+ // Generate the local symbol tables using the new pool
+ InitializeSymbolTables(infoSink, commonTable, stageTables, version, profile, spvVersion, source);
+
+ // Switch to the process-global pool
+ SetThreadPoolAllocator(PerProcessGPA);
+
+ // Copy the local symbol tables from the new pool to the global tables using the process-global pool
+ for (int precClass = 0; precClass < EPcCount; ++precClass) {
+ if (! commonTable[precClass]->isEmpty()) {
+ CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass] = new TSymbolTable;
+ CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->copyTable(*commonTable[precClass]);
+ CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->readOnly();
+ }
+ }
+ for (int stage = 0; stage < EShLangCount; ++stage) {
+ if (! stageTables[stage]->isEmpty()) {
+ SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage] = new TSymbolTable;
+ SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->adoptLevels(*CommonSymbolTable
+ [versionIndex][spvVersionIndex][profileIndex][sourceIndex][CommonIndex(profile, (EShLanguage)stage)]);
+ SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->copyTable(*stageTables[stage]);
+ SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->readOnly();
+ }
+ }
+
+ // Clean up the local tables before deleting the pool they used.
+ for (int precClass = 0; precClass < EPcCount; ++precClass)
+ delete commonTable[precClass];
+ for (int stage = 0; stage < EShLangCount; ++stage)
+ delete stageTables[stage];
+
+ delete builtInPoolAllocator;
+ SetThreadPoolAllocator(&previousAllocator);
+
+ glslang::ReleaseGlobalLock();
+}
+
+// Function to Print all builtins
+void DumpBuiltinSymbolTable(TInfoSink& infoSink, const TSymbolTable& symbolTable)
+{
+#ifndef GLSLANG_WEB
+ infoSink.debug << "BuiltinSymbolTable {\n";
+
+ symbolTable.dump(infoSink, true);
+
+ infoSink.debug << "}\n";
+#endif
+}
+
+// Return true if the shader was correctly specified for version/profile/stage.
+bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNotFirst, int defaultVersion,
+ EShSource source, int& version, EProfile& profile, const SpvVersion& spvVersion)
+{
+ const int FirstProfileVersion = 150;
+ bool correct = true;
+
+ if (source == EShSourceHlsl) {
+ version = 500; // shader model; currently a characteristic of glslang, not the input
+ profile = ECoreProfile; // allow doubles in prototype parsing
+ return correct;
+ }
+
+ // Get a version...
+ if (version == 0) {
+ version = defaultVersion;
+ // infoSink.info.message(EPrefixWarning, "#version: statement missing; use #version on first line of shader");
+ }
+
+ // Get a good profile...
+ if (profile == ENoProfile) {
+ if (version == 300 || version == 310 || version == 320) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 require specifying the 'es' profile");
+ profile = EEsProfile;
+ } else if (version == 100)
+ profile = EEsProfile;
+ else if (version >= FirstProfileVersion)
+ profile = ECoreProfile;
+ else
+ profile = ENoProfile;
+ } else {
+ // a profile was provided...
+ if (version < 150) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: versions before 150 do not allow a profile token");
+ if (version == 100)
+ profile = EEsProfile;
+ else
+ profile = ENoProfile;
+ } else if (version == 300 || version == 310 || version == 320) {
+ if (profile != EEsProfile) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 support only the es profile");
+ }
+ profile = EEsProfile;
+ } else {
+ if (profile == EEsProfile) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: only version 300, 310, and 320 support the es profile");
+ if (version >= FirstProfileVersion)
+ profile = ECoreProfile;
+ else
+ profile = ENoProfile;
+ }
+ // else: typical desktop case... e.g., "#version 410 core"
+ }
+ }
+
+ // Fix version...
+ switch (version) {
+ // ES versions
+ case 100: break;
+ case 300: break;
+ case 310: break;
+ case 320: break;
+
+ // desktop versions
+ case 110: break;
+ case 120: break;
+ case 130: break;
+ case 140: break;
+ case 150: break;
+ case 330: break;
+ case 400: break;
+ case 410: break;
+ case 420: break;
+ case 430: break;
+ case 440: break;
+ case 450: break;
+ case 460: break;
+
+ // unknown version
+ default:
+ correct = false;
+ infoSink.info.message(EPrefixError, "version not supported");
+ if (profile == EEsProfile)
+ version = 310;
+ else {
+ version = 450;
+ profile = ECoreProfile;
+ }
+ break;
+ }
+
+#ifndef GLSLANG_WEB
+ // Correct for stage type...
+ switch (stage) {
+ case EShLangGeometry:
+ if ((profile == EEsProfile && version < 310) ||
+ (profile != EEsProfile && version < 150)) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: geometry shaders require es profile with version 310 or non-es profile with version 150 or above");
+ version = (profile == EEsProfile) ? 310 : 150;
+ if (profile == EEsProfile || profile == ENoProfile)
+ profile = ECoreProfile;
+ }
+ break;
+ case EShLangTessControl:
+ case EShLangTessEvaluation:
+ if ((profile == EEsProfile && version < 310) ||
+ (profile != EEsProfile && version < 150)) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: tessellation shaders require es profile with version 310 or non-es profile with version 150 or above");
+ version = (profile == EEsProfile) ? 310 : 400; // 150 supports the extension, correction is to 400 which does not
+ if (profile == EEsProfile || profile == ENoProfile)
+ profile = ECoreProfile;
+ }
+ break;
+ case EShLangCompute:
+ if ((profile == EEsProfile && version < 310) ||
+ (profile != EEsProfile && version < 420)) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: compute shaders require es profile with version 310 or above, or non-es profile with version 420 or above");
+ version = profile == EEsProfile ? 310 : 420;
+ }
+ break;
+ case EShLangRayGenNV:
+ case EShLangIntersectNV:
+ case EShLangAnyHitNV:
+ case EShLangClosestHitNV:
+ case EShLangMissNV:
+ case EShLangCallableNV:
+ if (profile == EEsProfile || version < 460) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above");
+ version = 460;
+ }
+ break;
+ case EShLangMeshNV:
+ case EShLangTaskNV:
+ if ((profile == EEsProfile && version < 320) ||
+ (profile != EEsProfile && version < 450)) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: mesh/task shaders require es profile with version 320 or above, or non-es profile with version 450 or above");
+ version = profile == EEsProfile ? 320 : 450;
+ }
+ default:
+ break;
+ }
+
+ if (profile == EEsProfile && version >= 300 && versionNotFirst) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: statement must appear first in es-profile shader; before comments or newlines");
+ }
+
+ // Check for SPIR-V compatibility
+ if (spvVersion.spv != 0) {
+ switch (profile) {
+ case EEsProfile:
+ if (version < 310) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: ES shaders for SPIR-V require version 310 or higher");
+ version = 310;
+ }
+ break;
+ case ECompatibilityProfile:
+ infoSink.info.message(EPrefixError, "#version: compilation for SPIR-V does not support the compatibility profile");
+ break;
+ default:
+ if (spvVersion.vulkan > 0 && version < 140) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: Desktop shaders for Vulkan SPIR-V require version 140 or higher");
+ version = 140;
+ }
+ if (spvVersion.openGl >= 100 && version < 330) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: Desktop shaders for OpenGL SPIR-V require version 330 or higher");
+ version = 330;
+ }
+ break;
+ }
+ }
+#endif
+
+ return correct;
+}
+
+// There are multiple paths in for setting environment stuff.
+// TEnvironment takes precedence, for what it sets, so sort all this out.
+// Ideally, the internal code could be made to use TEnvironment, but for
+// now, translate it to the historically used parameters.
+void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages, EShSource& source,
+ EShLanguage& stage, SpvVersion& spvVersion)
+{
+ // Set up environmental defaults, first ignoring 'environment'.
+ if (messages & EShMsgSpvRules)
+ spvVersion.spv = EShTargetSpv_1_0;
+ if (messages & EShMsgVulkanRules) {
+ spvVersion.vulkan = EShTargetVulkan_1_0;
+ spvVersion.vulkanGlsl = 100;
+ } else if (spvVersion.spv != 0)
+ spvVersion.openGl = 100;
+
+ // Now, override, based on any content set in 'environment'.
+ // 'environment' must be cleared to ESh*None settings when items
+ // are not being set.
+ if (environment != nullptr) {
+ // input language
+ if (environment->input.languageFamily != EShSourceNone) {
+ stage = environment->input.stage;
+ switch (environment->input.dialect) {
+ case EShClientNone:
+ break;
+ case EShClientVulkan:
+ spvVersion.vulkanGlsl = environment->input.dialectVersion;
+ break;
+ case EShClientOpenGL:
+ spvVersion.openGl = environment->input.dialectVersion;
+ break;
+ }
+ switch (environment->input.languageFamily) {
+ case EShSourceNone:
+ break;
+ case EShSourceGlsl:
+ source = EShSourceGlsl;
+ messages = static_cast<EShMessages>(messages & ~EShMsgReadHlsl);
+ break;
+ case EShSourceHlsl:
+ source = EShSourceHlsl;
+ messages = static_cast<EShMessages>(messages | EShMsgReadHlsl);
+ break;
+ }
+ }
+
+ // client
+ switch (environment->client.client) {
+ case EShClientVulkan:
+ spvVersion.vulkan = environment->client.version;
+ break;
+ default:
+ break;
+ }
+
+ // generated code
+ switch (environment->target.language) {
+ case EshTargetSpv:
+ spvVersion.spv = environment->target.version;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+// Most processes are recorded when set in the intermediate representation,
+// These are the few that are not.
+void RecordProcesses(TIntermediate& intermediate, EShMessages messages, const std::string& sourceEntryPointName)
+{
+ if ((messages & EShMsgRelaxedErrors) != 0)
+ intermediate.addProcess("relaxed-errors");
+ if ((messages & EShMsgSuppressWarnings) != 0)
+ intermediate.addProcess("suppress-warnings");
+ if ((messages & EShMsgKeepUncalled) != 0)
+ intermediate.addProcess("keep-uncalled");
+ if (sourceEntryPointName.size() > 0) {
+ intermediate.addProcess("source-entrypoint");
+ intermediate.addProcessArgument(sourceEntryPointName);
+ }
+}
+
+// This is the common setup and cleanup code for PreprocessDeferred and
+// CompileDeferred.
+// It takes any callable with a signature of
+// bool (TParseContextBase& parseContext, TPpContext& ppContext,
+// TInputScanner& input, bool versionWillBeError,
+// TSymbolTable& , TIntermediate& ,
+// EShOptimizationLevel , EShMessages );
+// Which returns false if a failure was detected and true otherwise.
+//
+template<typename ProcessingContext>
+bool ProcessDeferred(
+ TCompiler* compiler,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const int* inputLengths,
+ const char* const stringNames[],
+ const char* customPreamble,
+ const EShOptimizationLevel optLevel,
+ const TBuiltInResource* resources,
+ int defaultVersion, // use 100 for ES environment, 110 for desktop; this is the GLSL version, not SPIR-V or Vulkan
+ EProfile defaultProfile,
+ // set version/profile to defaultVersion/defaultProfile regardless of the #version
+ // directive in the source code
+ bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, // give errors for use of deprecated features
+ EShMessages messages, // warnings/errors/AST; things to print out
+ TIntermediate& intermediate, // returned tree, etc.
+ ProcessingContext& processingContext,
+ bool requireNonempty,
+ TShader::Includer& includer,
+ const std::string sourceEntryPointName = "",
+ const TEnvironment* environment = nullptr) // optional way of fully setting all versions, overriding the above
+{
+ // This must be undone (.pop()) by the caller, after it finishes consuming the created tree.
+ GetThreadPoolAllocator().push();
+
+ if (numStrings == 0)
+ return true;
+
+ // Move to length-based strings, rather than null-terminated strings.
+ // Also, add strings to include the preamble and to ensure the shader is not null,
+ // which lets the grammar accept what was a null (post preprocessing) shader.
+ //
+ // Shader will look like
+ // string 0: system preamble
+ // string 1: custom preamble
+ // string 2...numStrings+1: user's shader
+ // string numStrings+2: "int;"
+ const int numPre = 2;
+ const int numPost = requireNonempty? 1 : 0;
+ const int numTotal = numPre + numStrings + numPost;
+ std::unique_ptr<size_t[]> lengths(new size_t[numTotal]);
+ std::unique_ptr<const char*[]> strings(new const char*[numTotal]);
+ std::unique_ptr<const char*[]> names(new const char*[numTotal]);
+ for (int s = 0; s < numStrings; ++s) {
+ strings[s + numPre] = shaderStrings[s];
+ if (inputLengths == nullptr || inputLengths[s] < 0)
+ lengths[s + numPre] = strlen(shaderStrings[s]);
+ else
+ lengths[s + numPre] = inputLengths[s];
+ }
+ if (stringNames != nullptr) {
+ for (int s = 0; s < numStrings; ++s)
+ names[s + numPre] = stringNames[s];
+ } else {
+ for (int s = 0; s < numStrings; ++s)
+ names[s + numPre] = nullptr;
+ }
+
+ // Get all the stages, languages, clients, and other environment
+ // stuff sorted out.
+ EShSource sourceGuess = (messages & EShMsgReadHlsl) != 0 ? EShSourceHlsl : EShSourceGlsl;
+ SpvVersion spvVersion;
+ EShLanguage stage = compiler->getLanguage();
+ TranslateEnvironment(environment, messages, sourceGuess, stage, spvVersion);
+#ifdef ENABLE_HLSL
+ EShSource source = sourceGuess;
+ if (environment != nullptr && environment->target.hlslFunctionality1)
+ intermediate.setHlslFunctionality1();
+#else
+ const EShSource source = EShSourceGlsl;
+#endif
+ // First, without using the preprocessor or parser, find the #version, so we know what
+ // symbol tables, processing rules, etc. to set up. This does not need the extra strings
+ // outlined above, just the user shader, after the system and user preambles.
+ glslang::TInputScanner userInput(numStrings, &strings[numPre], &lengths[numPre]);
+ int version = 0;
+ EProfile profile = ENoProfile;
+ bool versionNotFirstToken = false;
+ bool versionNotFirst = (source == EShSourceHlsl)
+ ? true
+ : userInput.scanVersion(version, profile, versionNotFirstToken);
+ bool versionNotFound = version == 0;
+ if (forceDefaultVersionAndProfile && source == EShSourceGlsl) {
+#ifndef GLSLANG_WEB
+ if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
+ (version != defaultVersion || profile != defaultProfile)) {
+ compiler->infoSink.info << "Warning, (version, profile) forced to be ("
+ << defaultVersion << ", " << ProfileName(defaultProfile)
+ << "), while in source code it is ("
+ << version << ", " << ProfileName(profile) << ")\n";
+ }
+#endif
+ if (versionNotFound) {
+ versionNotFirstToken = false;
+ versionNotFirst = false;
+ versionNotFound = false;
+ }
+ version = defaultVersion;
+ profile = defaultProfile;
+ }
+
+ bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage,
+ versionNotFirst, defaultVersion, source, version, profile, spvVersion);
+#ifdef GLSLANG_WEB
+ profile = EEsProfile;
+ version = 310;
+#endif
+
+ bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
+#ifndef GLSLANG_WEB
+ bool warnVersionNotFirst = false;
+ if (! versionWillBeError && versionNotFirstToken) {
+ if (messages & EShMsgRelaxedErrors)
+ warnVersionNotFirst = true;
+ else
+ versionWillBeError = true;
+ }
+#endif
+
+ intermediate.setSource(source);
+ intermediate.setVersion(version);
+ intermediate.setProfile(profile);
+ intermediate.setSpv(spvVersion);
+ RecordProcesses(intermediate, messages, sourceEntryPointName);
+ if (spvVersion.vulkan > 0)
+ intermediate.setOriginUpperLeft();
+#ifdef ENABLE_HLSL
+ if ((messages & EShMsgHlslOffsets) || source == EShSourceHlsl)
+ intermediate.setHlslOffsets();
+#endif
+ if (messages & EShMsgDebugInfo) {
+ intermediate.setSourceFile(names[numPre]);
+ for (int s = 0; s < numStrings; ++s) {
+ // The string may not be null-terminated, so make sure we provide
+ // the length along with the string.
+ intermediate.addSourceText(strings[numPre + s], lengths[numPre + s]);
+ }
+ }
+ SetupBuiltinSymbolTable(version, profile, spvVersion, source);
+
+ TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)]
+ [MapSpvVersionToIndex(spvVersion)]
+ [MapProfileToIndex(profile)]
+ [MapSourceToIndex(source)]
+ [stage];
+
+ // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool.
+ std::unique_ptr<TSymbolTable> symbolTable(new TSymbolTable);
+ if (cachedTable)
+ symbolTable->adoptLevels(*cachedTable);
+
+ // Add built-in symbols that are potentially context dependent;
+ // they get popped again further down.
+ if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion,
+ stage, source)) {
+ return false;
+ }
+
+ if (messages & EShMsgBuiltinSymbolTable)
+ DumpBuiltinSymbolTable(compiler->infoSink, *symbolTable);
+
+ //
+ // Now we can process the full shader under proper symbols and rules.
+ //
+
+ std::unique_ptr<TParseContextBase> parseContext(CreateParseContext(*symbolTable, intermediate, version, profile, source,
+ stage, compiler->infoSink,
+ spvVersion, forwardCompatible, messages, false, sourceEntryPointName));
+ TPpContext ppContext(*parseContext, names[numPre] ? names[numPre] : "", includer);
+
+ // only GLSL (bison triggered, really) needs an externally set scan context
+ glslang::TScanContext scanContext(*parseContext);
+ if (source == EShSourceGlsl)
+ parseContext->setScanContext(&scanContext);
+
+ parseContext->setPpContext(&ppContext);
+ parseContext->setLimits(*resources);
+ if (! goodVersion)
+ parseContext->addError();
+#ifndef GLSLANG_WEB
+ if (warnVersionNotFirst) {
+ TSourceLoc loc;
+ loc.init();
+ parseContext->warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", "");
+ }
+#endif
+
+ parseContext->initializeExtensionBehavior();
+
+ // Fill in the strings as outlined above.
+ std::string preamble;
+ parseContext->getPreamble(preamble);
+ strings[0] = preamble.c_str();
+ lengths[0] = strlen(strings[0]);
+ names[0] = nullptr;
+ strings[1] = customPreamble;
+ lengths[1] = strlen(strings[1]);
+ names[1] = nullptr;
+ assert(2 == numPre);
+ if (requireNonempty) {
+ const int postIndex = numStrings + numPre;
+ strings[postIndex] = "\n int;";
+ lengths[postIndex] = strlen(strings[numStrings + numPre]);
+ names[postIndex] = nullptr;
+ }
+ TInputScanner fullInput(numStrings + numPre + numPost, strings.get(), lengths.get(), names.get(), numPre, numPost);
+
+ // Push a new symbol allocation scope that will get used for the shader's globals.
+ symbolTable->push();
+
+ bool success = processingContext(*parseContext, ppContext, fullInput,
+ versionWillBeError, *symbolTable,
+ intermediate, optLevel, messages);
+ return success;
+}
+
+#ifndef GLSLANG_WEB
+
+// Responsible for keeping track of the most recent source string and line in
+// the preprocessor and outputting newlines appropriately if the source string
+// or line changes.
+class SourceLineSynchronizer {
+public:
+ SourceLineSynchronizer(const std::function<int()>& lastSourceIndex,
+ std::string* output)
+ : getLastSourceIndex(lastSourceIndex), output(output), lastSource(-1), lastLine(0) {}
+// SourceLineSynchronizer(const SourceLineSynchronizer&) = delete;
+// SourceLineSynchronizer& operator=(const SourceLineSynchronizer&) = delete;
+
+ // Sets the internally tracked source string index to that of the most
+ // recently read token. If we switched to a new source string, returns
+ // true and inserts a newline. Otherwise, returns false and outputs nothing.
+ bool syncToMostRecentString() {
+ if (getLastSourceIndex() != lastSource) {
+ // After switching to a new source string, we need to reset lastLine
+ // because line number resets every time a new source string is
+ // used. We also need to output a newline to separate the output
+ // from the previous source string (if there is one).
+ if (lastSource != -1 || lastLine != 0)
+ *output += '\n';
+ lastSource = getLastSourceIndex();
+ lastLine = -1;
+ return true;
+ }
+ return false;
+ }
+
+ // Calls syncToMostRecentString() and then sets the internally tracked line
+ // number to tokenLine. If we switched to a new line, returns true and inserts
+ // newlines appropriately. Otherwise, returns false and outputs nothing.
+ bool syncToLine(int tokenLine) {
+ syncToMostRecentString();
+ const bool newLineStarted = lastLine < tokenLine;
+ for (; lastLine < tokenLine; ++lastLine) {
+ if (lastLine > 0) *output += '\n';
+ }
+ return newLineStarted;
+ }
+
+ // Sets the internally tracked line number to newLineNum.
+ void setLineNum(int newLineNum) { lastLine = newLineNum; }
+
+private:
+ SourceLineSynchronizer& operator=(const SourceLineSynchronizer&);
+
+ // A function for getting the index of the last valid source string we've
+ // read tokens from.
+ const std::function<int()> getLastSourceIndex;
+ // output string for newlines.
+ std::string* output;
+ // lastSource is the source string index (starting from 0) of the last token
+ // processed. It is tracked in order for newlines to be inserted when a new
+ // source string starts. -1 means we haven't started processing any source
+ // string.
+ int lastSource;
+ // lastLine is the line number (starting from 1) of the last token processed.
+ // It is tracked in order for newlines to be inserted when a token appears
+ // on a new line. 0 means we haven't started processing any line in the
+ // current source string.
+ int lastLine;
+};
+
+// DoPreprocessing is a valid ProcessingContext template argument,
+// which only performs the preprocessing step of compilation.
+// It places the result in the "string" argument to its constructor.
+//
+// This is not an officially supported or fully working path.
+struct DoPreprocessing {
+ explicit DoPreprocessing(std::string* string): outputString(string) {}
+ bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
+ TInputScanner& input, bool versionWillBeError,
+ TSymbolTable&, TIntermediate&,
+ EShOptimizationLevel, EShMessages)
+ {
+ // This is a list of tokens that do not require a space before or after.
+ static const std::string unNeededSpaceTokens = ";()[]";
+ static const std::string noSpaceBeforeTokens = ",";
+ glslang::TPpToken ppToken;
+
+ parseContext.setScanner(&input);
+ ppContext.setInput(input, versionWillBeError);
+
+ std::string outputBuffer;
+ SourceLineSynchronizer lineSync(
+ std::bind(&TInputScanner::getLastValidSourceIndex, &input), &outputBuffer);
+
+ parseContext.setExtensionCallback([&lineSync, &outputBuffer](
+ int line, const char* extension, const char* behavior) {
+ lineSync.syncToLine(line);
+ outputBuffer += "#extension ";
+ outputBuffer += extension;
+ outputBuffer += " : ";
+ outputBuffer += behavior;
+ });
+
+ parseContext.setLineCallback([&lineSync, &outputBuffer, &parseContext](
+ int curLineNum, int newLineNum, bool hasSource, int sourceNum, const char* sourceName) {
+ // SourceNum is the number of the source-string that is being parsed.
+ lineSync.syncToLine(curLineNum);
+ outputBuffer += "#line ";
+ outputBuffer += std::to_string(newLineNum);
+ if (hasSource) {
+ outputBuffer += ' ';
+ if (sourceName != nullptr) {
+ outputBuffer += '\"';
+ outputBuffer += sourceName;
+ outputBuffer += '\"';
+ } else {
+ outputBuffer += std::to_string(sourceNum);
+ }
+ }
+ if (parseContext.lineDirectiveShouldSetNextLine()) {
+ // newLineNum is the new line number for the line following the #line
+ // directive. So the new line number for the current line is
+ newLineNum -= 1;
+ }
+ outputBuffer += '\n';
+ // And we are at the next line of the #line directive now.
+ lineSync.setLineNum(newLineNum + 1);
+ });
+
+ parseContext.setVersionCallback(
+ [&lineSync, &outputBuffer](int line, int version, const char* str) {
+ lineSync.syncToLine(line);
+ outputBuffer += "#version ";
+ outputBuffer += std::to_string(version);
+ if (str) {
+ outputBuffer += ' ';
+ outputBuffer += str;
+ }
+ });
+
+ parseContext.setPragmaCallback([&lineSync, &outputBuffer](
+ int line, const glslang::TVector<glslang::TString>& ops) {
+ lineSync.syncToLine(line);
+ outputBuffer += "#pragma ";
+ for(size_t i = 0; i < ops.size(); ++i) {
+ outputBuffer += ops[i].c_str();
+ }
+ });
+
+ parseContext.setErrorCallback([&lineSync, &outputBuffer](
+ int line, const char* errorMessage) {
+ lineSync.syncToLine(line);
+ outputBuffer += "#error ";
+ outputBuffer += errorMessage;
+ });
+
+ int lastToken = EndOfInput; // lastToken records the last token processed.
+ do {
+ int token = ppContext.tokenize(ppToken);
+ if (token == EndOfInput)
+ break;
+
+ bool isNewString = lineSync.syncToMostRecentString();
+ bool isNewLine = lineSync.syncToLine(ppToken.loc.line);
+
+ if (isNewLine) {
+ // Don't emit whitespace onto empty lines.
+ // Copy any whitespace characters at the start of a line
+ // from the input to the output.
+ outputBuffer += std::string(ppToken.loc.column - 1, ' ');
+ }
+
+ // Output a space in between tokens, but not at the start of a line,
+ // and also not around special tokens. This helps with readability
+ // and consistency.
+ if (!isNewString && !isNewLine && lastToken != EndOfInput &&
+ (unNeededSpaceTokens.find((char)token) == std::string::npos) &&
+ (unNeededSpaceTokens.find((char)lastToken) == std::string::npos) &&
+ (noSpaceBeforeTokens.find((char)token) == std::string::npos)) {
+ outputBuffer += ' ';
+ }
+ lastToken = token;
+ if (token == PpAtomConstString)
+ outputBuffer += "\"";
+ outputBuffer += ppToken.name;
+ if (token == PpAtomConstString)
+ outputBuffer += "\"";
+ } while (true);
+ outputBuffer += '\n';
+ *outputString = std::move(outputBuffer);
+
+ bool success = true;
+ if (parseContext.getNumErrors() > 0) {
+ success = false;
+ parseContext.infoSink.info.prefix(EPrefixError);
+ parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
+ }
+ return success;
+ }
+ std::string* outputString;
+};
+
+#endif
+
+// DoFullParse is a valid ProcessingConext template argument for fully
+// parsing the shader. It populates the "intermediate" with the AST.
+struct DoFullParse{
+ bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
+ TInputScanner& fullInput, bool versionWillBeError,
+ TSymbolTable&, TIntermediate& intermediate,
+ EShOptimizationLevel optLevel, EShMessages messages)
+ {
+ bool success = true;
+ // Parse the full shader.
+ if (! parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError))
+ success = false;
+
+ if (success && intermediate.getTreeRoot()) {
+ if (optLevel == EShOptNoGeneration)
+ parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested.");
+ else
+ success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.getLanguage());
+ } else if (! success) {
+ parseContext.infoSink.info.prefix(EPrefixError);
+ parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
+ }
+
+ if (messages & EShMsgAST)
+ intermediate.output(parseContext.infoSink, true);
+
+ return success;
+ }
+};
+
+#ifndef GLSLANG_WEB
+// Take a single compilation unit, and run the preprocessor on it.
+// Return: True if there were no issues found in preprocessing,
+// False if during preprocessing any unknown version, pragmas or
+// extensions were found.
+//
+// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
+// is not an officially supported or fully working path.
+bool PreprocessDeferred(
+ TCompiler* compiler,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const int* inputLengths,
+ const char* const stringNames[],
+ const char* preamble,
+ const EShOptimizationLevel optLevel,
+ const TBuiltInResource* resources,
+ int defaultVersion, // use 100 for ES environment, 110 for desktop
+ EProfile defaultProfile,
+ bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, // give errors for use of deprecated features
+ EShMessages messages, // warnings/errors/AST; things to print out
+ TShader::Includer& includer,
+ TIntermediate& intermediate, // returned tree, etc.
+ std::string* outputString)
+{
+ DoPreprocessing parser(outputString);
+ return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
+ preamble, optLevel, resources, defaultVersion,
+ defaultProfile, forceDefaultVersionAndProfile,
+ forwardCompatible, messages, intermediate, parser,
+ false, includer);
+}
+#endif
+
+//
+// do a partial compile on the given strings for a single compilation unit
+// for a potential deferred link into a single stage (and deferred full compile of that
+// stage through machine-dependent compilation).
+//
+// all preprocessing, parsing, semantic checks, etc. for a single compilation unit
+// are done here.
+//
+// return: the tree and other information is filled into the intermediate argument,
+// and true is returned by the function for success.
+//
+bool CompileDeferred(
+ TCompiler* compiler,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const int* inputLengths,
+ const char* const stringNames[],
+ const char* preamble,
+ const EShOptimizationLevel optLevel,
+ const TBuiltInResource* resources,
+ int defaultVersion, // use 100 for ES environment, 110 for desktop
+ EProfile defaultProfile,
+ bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, // give errors for use of deprecated features
+ EShMessages messages, // warnings/errors/AST; things to print out
+ TIntermediate& intermediate,// returned tree, etc.
+ TShader::Includer& includer,
+ const std::string sourceEntryPointName = "",
+ TEnvironment* environment = nullptr)
+{
+ DoFullParse parser;
+ return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
+ preamble, optLevel, resources, defaultVersion,
+ defaultProfile, forceDefaultVersionAndProfile,
+ forwardCompatible, messages, intermediate, parser,
+ true, includer, sourceEntryPointName, environment);
+}
+
+} // end anonymous namespace for local functions
+
+//
+// ShInitialize() should be called exactly once per process, not per thread.
+//
+int ShInitialize()
+{
+ glslang::InitGlobalLock();
+
+ if (! InitProcess())
+ return 0;
+
+ glslang::GetGlobalLock();
+ ++NumberOfClients;
+ glslang::ReleaseGlobalLock();
+
+ if (PerProcessGPA == nullptr)
+ PerProcessGPA = new TPoolAllocator();
+
+ glslang::TScanContext::fillInKeywordMap();
+#ifdef ENABLE_HLSL
+ glslang::HlslScanContext::fillInKeywordMap();
+#endif
+
+ return 1;
+}
+
+//
+// Driver calls these to create and destroy compiler/linker
+// objects.
+//
+
+ShHandle ShConstructCompiler(const EShLanguage language, int debugOptions)
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, debugOptions));
+
+ return reinterpret_cast<void*>(base);
+}
+
+ShHandle ShConstructLinker(const EShExecutable executable, int debugOptions)
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructLinker(executable, debugOptions));
+
+ return reinterpret_cast<void*>(base);
+}
+
+ShHandle ShConstructUniformMap()
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructUniformMap());
+
+ return reinterpret_cast<void*>(base);
+}
+
+void ShDestruct(ShHandle handle)
+{
+ if (handle == 0)
+ return;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+
+ if (base->getAsCompiler())
+ DeleteCompiler(base->getAsCompiler());
+ else if (base->getAsLinker())
+ DeleteLinker(base->getAsLinker());
+ else if (base->getAsUniformMap())
+ DeleteUniformMap(base->getAsUniformMap());
+}
+
+//
+// Cleanup symbol tables
+//
+int ShFinalize()
+{
+ glslang::GetGlobalLock();
+ --NumberOfClients;
+ assert(NumberOfClients >= 0);
+ bool finalize = NumberOfClients == 0;
+ glslang::ReleaseGlobalLock();
+ if (! finalize)
+ return 1;
+
+ for (int version = 0; version < VersionCount; ++version) {
+ for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
+ for (int p = 0; p < ProfileCount; ++p) {
+ for (int source = 0; source < SourceCount; ++source) {
+ for (int stage = 0; stage < EShLangCount; ++stage) {
+ delete SharedSymbolTables[version][spvVersion][p][source][stage];
+ SharedSymbolTables[version][spvVersion][p][source][stage] = 0;
+ }
+ }
+ }
+ }
+ }
+
+ for (int version = 0; version < VersionCount; ++version) {
+ for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
+ for (int p = 0; p < ProfileCount; ++p) {
+ for (int source = 0; source < SourceCount; ++source) {
+ for (int pc = 0; pc < EPcCount; ++pc) {
+ delete CommonSymbolTable[version][spvVersion][p][source][pc];
+ CommonSymbolTable[version][spvVersion][p][source][pc] = 0;
+ }
+ }
+ }
+ }
+ }
+
+ if (PerProcessGPA != nullptr) {
+ delete PerProcessGPA;
+ PerProcessGPA = nullptr;
+ }
+
+ glslang::TScanContext::deleteKeywordMap();
+#ifdef ENABLE_HLSL
+ glslang::HlslScanContext::deleteKeywordMap();
+#endif
+
+ return 1;
+}
+
+//
+// Do a full compile on the given strings for a single compilation unit
+// forming a complete stage. The result of the machine dependent compilation
+// is left in the provided compile object.
+//
+// Return: The return value is really boolean, indicating
+// success (1) or failure (0).
+//
+int ShCompile(
+ const ShHandle handle,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const int* inputLengths,
+ const EShOptimizationLevel optLevel,
+ const TBuiltInResource* resources,
+ int /*debugOptions*/,
+ int defaultVersion, // use 100 for ES environment, 110 for desktop
+ bool forwardCompatible, // give errors for use of deprecated features
+ EShMessages messages // warnings/errors/AST; things to print out
+ )
+{
+ // Map the generic handle to the C++ object
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TCompiler* compiler = base->getAsCompiler();
+ if (compiler == 0)
+ return 0;
+
+ SetThreadPoolAllocator(compiler->getPool());
+
+ compiler->infoSink.info.erase();
+ compiler->infoSink.debug.erase();
+
+ TIntermediate intermediate(compiler->getLanguage());
+ TShader::ForbidIncluder includer;
+ bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr,
+ "", optLevel, resources, defaultVersion, ENoProfile, false,
+ forwardCompatible, messages, intermediate, includer);
+
+ //
+ // Call the machine dependent compiler
+ //
+ if (success && intermediate.getTreeRoot() && optLevel != EShOptNoGeneration)
+ success = compiler->compile(intermediate.getTreeRoot(), intermediate.getVersion(), intermediate.getProfile());
+
+ intermediate.removeTree();
+
+ // Throw away all the temporary memory used by the compilation process.
+ // The push was done in the CompileDeferred() call above.
+ GetThreadPoolAllocator().pop();
+
+ return success ? 1 : 0;
+}
+
+//
+// Link the given compile objects.
+//
+// Return: The return value of is really boolean, indicating
+// success or failure.
+//
+int ShLinkExt(
+ const ShHandle linkHandle,
+ const ShHandle compHandles[],
+ const int numHandles)
+{
+ if (linkHandle == 0 || numHandles == 0)
+ return 0;
+
+ THandleList cObjects;
+
+ for (int i = 0; i < numHandles; ++i) {
+ if (compHandles[i] == 0)
+ return 0;
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(compHandles[i]);
+ if (base->getAsLinker()) {
+ cObjects.push_back(base->getAsLinker());
+ }
+ if (base->getAsCompiler())
+ cObjects.push_back(base->getAsCompiler());
+
+ if (cObjects[i] == 0)
+ return 0;
+ }
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+ SetThreadPoolAllocator(linker->getPool());
+
+ if (linker == 0)
+ return 0;
+
+ linker->infoSink.info.erase();
+
+ for (int i = 0; i < numHandles; ++i) {
+ if (cObjects[i]->getAsCompiler()) {
+ if (! cObjects[i]->getAsCompiler()->linkable()) {
+ linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code.");
+ return 0;
+ }
+ }
+ }
+
+ bool ret = linker->link(cObjects);
+
+ return ret ? 1 : 0;
+}
+
+//
+// ShSetEncrpytionMethod is a place-holder for specifying
+// how source code is encrypted.
+//
+void ShSetEncryptionMethod(ShHandle handle)
+{
+ if (handle == 0)
+ return;
+}
+
+//
+// Return any compiler/linker/uniformmap log of messages for the application.
+//
+const char* ShGetInfoLog(const ShHandle handle)
+{
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+ TInfoSink* infoSink;
+
+ if (base->getAsCompiler())
+ infoSink = &(base->getAsCompiler()->getInfoSink());
+ else if (base->getAsLinker())
+ infoSink = &(base->getAsLinker()->getInfoSink());
+ else
+ return 0;
+
+ infoSink->info << infoSink->debug.c_str();
+ return infoSink->info.c_str();
+}
+
+//
+// Return the resulting binary code from the link process. Structure
+// is machine dependent.
+//
+const void* ShGetExecutable(const ShHandle handle)
+{
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+ if (linker == 0)
+ return 0;
+
+ return linker->getObjectCode();
+}
+
+//
+// Let the linker know where the application said it's attributes are bound.
+// The linker does not use these values, they are remapped by the ICD or
+// hardware. It just needs them to know what's aliased.
+//
+// Return: The return value of is really boolean, indicating
+// success or failure.
+//
+int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table)
+{
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+ if (linker == 0)
+ return 0;
+
+ linker->setAppAttributeBindings(table);
+
+ return 1;
+}
+
+//
+// Let the linker know where the predefined attributes have to live.
+//
+int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table)
+{
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+ if (linker == 0)
+ return 0;
+
+ linker->setFixedAttributeBindings(table);
+ return 1;
+}
+
+//
+// Some attribute locations are off-limits to the linker...
+//
+int ShExcludeAttributes(const ShHandle handle, int *attributes, int count)
+{
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+ if (linker == 0)
+ return 0;
+
+ linker->setExcludedAttributes(attributes, count);
+
+ return 1;
+}
+
+//
+// Return the index for OpenGL to use for knowing where a uniform lives.
+//
+// Return: The return value of is really boolean, indicating
+// success or failure.
+//
+int ShGetUniformLocation(const ShHandle handle, const char* name)
+{
+ if (handle == 0)
+ return -1;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TUniformMap* uniformMap= base->getAsUniformMap();
+ if (uniformMap == 0)
+ return -1;
+
+ return uniformMap->getLocation(name);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Deferred-Lowering C++ Interface
+// -----------------------------------
+//
+// Below is a new alternate C++ interface that might potentially replace the above
+// opaque handle-based interface.
+//
+// See more detailed comment in ShaderLang.h
+//
+
+namespace glslang {
+
+#include "../Include/revision.h"
+
+#define QUOTE(s) #s
+#define STR(n) QUOTE(n)
+
+const char* GetEsslVersionString()
+{
+ return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
+}
+
+const char* GetGlslVersionString()
+{
+ return "4.60 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
+}
+
+int GetKhronosToolId()
+{
+ return 8;
+}
+
+bool InitializeProcess()
+{
+ return ShInitialize() != 0;
+}
+
+void FinalizeProcess()
+{
+ ShFinalize();
+}
+
+class TDeferredCompiler : public TCompiler {
+public:
+ TDeferredCompiler(EShLanguage s, TInfoSink& i) : TCompiler(s, i) { }
+ virtual bool compile(TIntermNode*, int = 0, EProfile = ENoProfile) { return true; }
+};
+
+TShader::TShader(EShLanguage s)
+ : stage(s), lengths(nullptr), stringNames(nullptr), preamble("")
+{
+ pool = new TPoolAllocator;
+ infoSink = new TInfoSink;
+ compiler = new TDeferredCompiler(stage, *infoSink);
+ intermediate = new TIntermediate(s);
+
+ // clear environment (avoid constructors in them for use in a C interface)
+ environment.input.languageFamily = EShSourceNone;
+ environment.input.dialect = EShClientNone;
+ environment.client.client = EShClientNone;
+ environment.target.language = EShTargetNone;
+ environment.target.hlslFunctionality1 = false;
+}
+
+TShader::~TShader()
+{
+ delete infoSink;
+ delete compiler;
+ delete intermediate;
+ delete pool;
+}
+
+void TShader::setStrings(const char* const* s, int n)
+{
+ strings = s;
+ numStrings = n;
+ lengths = nullptr;
+}
+
+void TShader::setStringsWithLengths(const char* const* s, const int* l, int n)
+{
+ strings = s;
+ numStrings = n;
+ lengths = l;
+}
+
+void TShader::setStringsWithLengthsAndNames(
+ const char* const* s, const int* l, const char* const* names, int n)
+{
+ strings = s;
+ numStrings = n;
+ lengths = l;
+ stringNames = names;
+}
+
+void TShader::setEntryPoint(const char* entryPoint)
+{
+ intermediate->setEntryPointName(entryPoint);
+}
+
+void TShader::setSourceEntryPoint(const char* name)
+{
+ sourceEntryPointName = name;
+}
+
+void TShader::addProcesses(const std::vector<std::string>& p)
+{
+ intermediate->addProcesses(p);
+}
+
+void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); }
+void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); }
+
+#ifndef GLSLANG_WEB
+
+// Set binding base for given resource type
+void TShader::setShiftBinding(TResourceType res, unsigned int base) {
+ intermediate->setShiftBinding(res, base);
+}
+
+// Set binding base for given resource type for a given binding set.
+void TShader::setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set) {
+ intermediate->setShiftBindingForSet(res, base, set);
+}
+
+// Set binding base for sampler types
+void TShader::setShiftSamplerBinding(unsigned int base) { setShiftBinding(EResSampler, base); }
+// Set binding base for texture types (SRV)
+void TShader::setShiftTextureBinding(unsigned int base) { setShiftBinding(EResTexture, base); }
+// Set binding base for image types
+void TShader::setShiftImageBinding(unsigned int base) { setShiftBinding(EResImage, base); }
+// Set binding base for uniform buffer objects (CBV)
+void TShader::setShiftUboBinding(unsigned int base) { setShiftBinding(EResUbo, base); }
+// Synonym for setShiftUboBinding, to match HLSL language.
+void TShader::setShiftCbufferBinding(unsigned int base) { setShiftBinding(EResUbo, base); }
+// Set binding base for UAV (unordered access view)
+void TShader::setShiftUavBinding(unsigned int base) { setShiftBinding(EResUav, base); }
+// Set binding base for SSBOs
+void TShader::setShiftSsboBinding(unsigned int base) { setShiftBinding(EResSsbo, base); }
+// Enables binding automapping using TIoMapper
+void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); }
+// Enables position.Y output negation in vertex shader
+
+// Fragile: currently within one stage: simple auto-assignment of location
+void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); }
+void TShader::addUniformLocationOverride(const char* name, int loc)
+{
+ intermediate->addUniformLocationOverride(name, loc);
+}
+void TShader::setUniformLocationBase(int base)
+{
+ intermediate->setUniformLocationBase(base);
+}
+void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); }
+void TShader::setResourceSetBinding(const std::vector<std::string>& base) { intermediate->setResourceSetBinding(base); }
+void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
+#endif
+
+#ifdef ENABLE_HLSL
+// See comment above TDefaultHlslIoMapper in iomapper.cpp:
+void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); }
+void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); }
+#endif
+
+//
+// Turn the shader strings into a parse tree in the TIntermediate.
+//
+// Returns true for success.
+//
+bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, EShMessages messages, Includer& includer)
+{
+ if (! InitThread())
+ return false;
+ SetThreadPoolAllocator(pool);
+
+ if (! preamble)
+ preamble = "";
+
+ return CompileDeferred(compiler, strings, numStrings, lengths, stringNames,
+ preamble, EShOptNone, builtInResources, defaultVersion,
+ defaultProfile, forceDefaultVersionAndProfile,
+ forwardCompatible, messages, *intermediate, includer, sourceEntryPointName,
+ &environment);
+}
+
+#ifndef GLSLANG_WEB
+// Fill in a string with the result of preprocessing ShaderStrings
+// Returns true if all extensions, pragmas and version strings were valid.
+//
+// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
+// is not an officially supported or fully working path.
+bool TShader::preprocess(const TBuiltInResource* builtInResources,
+ int defaultVersion, EProfile defaultProfile,
+ bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, EShMessages message,
+ std::string* output_string,
+ Includer& includer)
+{
+ if (! InitThread())
+ return false;
+ SetThreadPoolAllocator(pool);
+
+ if (! preamble)
+ preamble = "";
+
+ return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
+ EShOptNone, builtInResources, defaultVersion,
+ defaultProfile, forceDefaultVersionAndProfile,
+ forwardCompatible, message, includer, *intermediate, output_string);
+}
+#endif
+
+const char* TShader::getInfoLog()
+{
+ return infoSink->info.c_str();
+}
+
+const char* TShader::getInfoDebugLog()
+{
+ return infoSink->debug.c_str();
+}
+
+TProgram::TProgram() :
+#ifndef GLSLANG_WEB
+ reflection(0),
+#endif
+ linked(false)
+{
+ pool = new TPoolAllocator;
+ infoSink = new TInfoSink;
+ for (int s = 0; s < EShLangCount; ++s) {
+ intermediate[s] = 0;
+ newedIntermediate[s] = false;
+ }
+}
+
+TProgram::~TProgram()
+{
+ delete infoSink;
+#ifndef GLSLANG_WEB
+ delete reflection;
+#endif
+
+ for (int s = 0; s < EShLangCount; ++s)
+ if (newedIntermediate[s])
+ delete intermediate[s];
+
+ delete pool;
+}
+
+//
+// Merge the compilation units within each stage into a single TIntermediate.
+// All starting compilation units need to be the result of calling TShader::parse().
+//
+// Return true for success.
+//
+bool TProgram::link(EShMessages messages)
+{
+ if (linked)
+ return false;
+ linked = true;
+
+ bool error = false;
+
+ SetThreadPoolAllocator(pool);
+
+ for (int s = 0; s < EShLangCount; ++s) {
+ if (! linkStage((EShLanguage)s, messages))
+ error = true;
+ }
+
+ // TODO: Link: cross-stage error checking
+
+ return ! error;
+}
+
+//
+// Merge the compilation units within the given stage into a single TIntermediate.
+//
+// Return true for success.
+//
+bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
+{
+ if (stages[stage].size() == 0)
+ return true;
+
+#ifndef GLSLANG_WEB
+ int numEsShaders = 0, numNonEsShaders = 0;
+ for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) {
+ if ((*it)->intermediate->getProfile() == EEsProfile) {
+ numEsShaders++;
+ } else {
+ numNonEsShaders++;
+ }
+ }
+
+ if (numEsShaders > 0 && numNonEsShaders > 0) {
+ infoSink->info.message(EPrefixError, "Cannot mix ES profile with non-ES profile shaders");
+ return false;
+ } else if (numEsShaders > 1) {
+ infoSink->info.message(EPrefixError, "Cannot attach multiple ES shaders of the same type to a single program");
+ return false;
+ }
+
+ //
+ // Be efficient for the common single compilation unit per stage case,
+ // reusing it's TIntermediate instead of merging into a new one.
+ //
+ TIntermediate *firstIntermediate = stages[stage].front()->intermediate;
+ if (stages[stage].size() == 1)
+ intermediate[stage] = firstIntermediate;
+ else {
+ intermediate[stage] = new TIntermediate(stage,
+ firstIntermediate->getVersion(),
+ firstIntermediate->getProfile());
+
+
+ // The new TIntermediate must use the same origin as the original TIntermediates.
+ // Otherwise linking will fail due to different coordinate systems.
+ if (firstIntermediate->getOriginUpperLeft()) {
+ intermediate[stage]->setOriginUpperLeft();
+ }
+ intermediate[stage]->setSpv(firstIntermediate->getSpv());
+
+ newedIntermediate[stage] = true;
+ }
+
+ if (messages & EShMsgAST)
+ infoSink->info << "\nLinked " << StageName(stage) << " stage:\n\n";
+
+ if (stages[stage].size() > 1) {
+ std::list<TShader*>::const_iterator it;
+ for (it = stages[stage].begin(); it != stages[stage].end(); ++it)
+ intermediate[stage]->merge(*infoSink, *(*it)->intermediate);
+ }
+#else
+ intermediate[stage] = stages[stage].front()->intermediate;
+#endif
+ intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0);
+
+ if (messages & EShMsgAST)
+ intermediate[stage]->output(*infoSink, true);
+
+ return intermediate[stage]->getNumErrors() == 0;
+}
+
+const char* TProgram::getInfoLog()
+{
+ return infoSink->info.c_str();
+}
+
+const char* TProgram::getInfoDebugLog()
+{
+ return infoSink->debug.c_str();
+}
+
+#ifndef GLSLANG_WEB
+
+//
+// Reflection implementation.
+//
+
+bool TProgram::buildReflection(int opts)
+{
+ if (! linked || reflection != nullptr)
+ return false;
+
+ int firstStage = EShLangVertex, lastStage = EShLangFragment;
+
+ if (opts & EShReflectionIntermediateIO) {
+ // if we're reflecting intermediate I/O, determine the first and last stage linked and use those as the
+ // boundaries for which stages generate pipeline inputs/outputs
+ firstStage = EShLangCount;
+ lastStage = 0;
+ for (int s = 0; s < EShLangCount; ++s) {
+ if (intermediate[s]) {
+ firstStage = std::min(firstStage, s);
+ lastStage = std::max(lastStage, s);
+ }
+ }
+ }
+
+ reflection = new TReflection((EShReflectionOptions)opts, (EShLanguage)firstStage, (EShLanguage)lastStage);
+
+ for (int s = 0; s < EShLangCount; ++s) {
+ if (intermediate[s]) {
+ if (! reflection->addStage((EShLanguage)s, *intermediate[s]))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+unsigned TProgram::getLocalSize(int dim) const { return reflection->getLocalSize(dim); }
+int TProgram::getReflectionIndex(const char* name) const { return reflection->getIndex(name); }
+int TProgram::getReflectionPipeIOIndex(const char* name, const bool inOrOut) const
+ { return reflection->getPipeIOIndex(name, inOrOut); }
+
+int TProgram::getNumUniformVariables() const { return reflection->getNumUniforms(); }
+const TObjectReflection& TProgram::getUniform(int index) const { return reflection->getUniform(index); }
+int TProgram::getNumUniformBlocks() const { return reflection->getNumUniformBlocks(); }
+const TObjectReflection& TProgram::getUniformBlock(int index) const { return reflection->getUniformBlock(index); }
+int TProgram::getNumPipeInputs() const { return reflection->getNumPipeInputs(); }
+const TObjectReflection& TProgram::getPipeInput(int index) const { return reflection->getPipeInput(index); }
+int TProgram::getNumPipeOutputs() const { return reflection->getNumPipeOutputs(); }
+const TObjectReflection& TProgram::getPipeOutput(int index) const { return reflection->getPipeOutput(index); }
+int TProgram::getNumBufferVariables() const { return reflection->getNumBufferVariables(); }
+const TObjectReflection& TProgram::getBufferVariable(int index) const { return reflection->getBufferVariable(index); }
+int TProgram::getNumBufferBlocks() const { return reflection->getNumStorageBuffers(); }
+const TObjectReflection& TProgram::getBufferBlock(int index) const { return reflection->getStorageBufferBlock(index); }
+int TProgram::getNumAtomicCounters() const { return reflection->getNumAtomicCounters(); }
+const TObjectReflection& TProgram::getAtomicCounter(int index) const { return reflection->getAtomicCounter(index); }
+void TProgram::dumpReflection() { if (reflection != nullptr) reflection->dump(); }
+
+//
+// I/O mapping implementation.
+//
+bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper)
+{
+ if (! linked)
+ return false;
+ TIoMapper* ioMapper = nullptr;
+ TIoMapper defaultIOMapper;
+ if (pIoMapper == nullptr)
+ ioMapper = &defaultIOMapper;
+ else
+ ioMapper = pIoMapper;
+ for (int s = 0; s < EShLangCount; ++s) {
+ if (intermediate[s]) {
+ if (! ioMapper->addStage((EShLanguage)s, *intermediate[s], *infoSink, pResolver))
+ return false;
+ }
+ }
+
+ return ioMapper->doMap(pResolver, *infoSink);
+}
+
+#endif // GLSLANG_WEB
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp b/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp
new file mode 100644
index 0000000000..44682379f7
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp
@@ -0,0 +1,444 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Symbol table for parsing. Most functionality and main ideas
+// are documented in the header file.
+//
+
+#include "SymbolTable.h"
+
+namespace glslang {
+
+//
+// TType helper function needs a place to live.
+//
+
+//
+// Recursively generate mangled names.
+//
+void TType::buildMangledName(TString& mangledName) const
+{
+ if (isMatrix())
+ mangledName += 'm';
+ else if (isVector())
+ mangledName += 'v';
+
+ switch (basicType) {
+ case EbtFloat: mangledName += 'f'; break;
+ case EbtInt: mangledName += 'i'; break;
+ case EbtUint: mangledName += 'u'; break;
+ case EbtBool: mangledName += 'b'; break;
+#ifndef GLSLANG_WEB
+ case EbtDouble: mangledName += 'd'; break;
+ case EbtFloat16: mangledName += "f16"; break;
+ case EbtInt8: mangledName += "i8"; break;
+ case EbtUint8: mangledName += "u8"; break;
+ case EbtInt16: mangledName += "i16"; break;
+ case EbtUint16: mangledName += "u16"; break;
+ case EbtInt64: mangledName += "i64"; break;
+ case EbtUint64: mangledName += "u64"; break;
+ case EbtAtomicUint: mangledName += "au"; break;
+ case EbtAccStructNV: mangledName += "asnv"; break;
+#endif
+ case EbtSampler:
+ switch (sampler.type) {
+#ifndef GLSLANG_WEB
+ case EbtFloat16: mangledName += "f16"; break;
+#endif
+ case EbtInt: mangledName += "i"; break;
+ case EbtUint: mangledName += "u"; break;
+ default: break; // some compilers want this
+ }
+ if (sampler.isImageClass())
+ mangledName += "I"; // a normal image or subpass
+ else if (sampler.isPureSampler())
+ mangledName += "p"; // a "pure" sampler
+ else if (!sampler.isCombined())
+ mangledName += "t"; // a "pure" texture
+ else
+ mangledName += "s"; // traditional combined sampler
+ if (sampler.isArrayed())
+ mangledName += "A";
+ if (sampler.isShadow())
+ mangledName += "S";
+ if (sampler.isExternal())
+ mangledName += "E";
+ if (sampler.isYuv())
+ mangledName += "Y";
+ switch (sampler.dim) {
+ case Esd2D: mangledName += "2"; break;
+ case Esd3D: mangledName += "3"; break;
+ case EsdCube: mangledName += "C"; break;
+#ifndef GLSLANG_WEB
+ case Esd1D: mangledName += "1"; break;
+ case EsdRect: mangledName += "R2"; break;
+ case EsdBuffer: mangledName += "B"; break;
+ case EsdSubpass: mangledName += "P"; break;
+#endif
+ default: break; // some compilers want this
+ }
+
+#ifdef ENABLE_HLSL
+ if (sampler.hasReturnStruct()) {
+ // Name mangle for sampler return struct uses struct table index.
+ mangledName += "-tx-struct";
+
+ char text[16]; // plenty enough space for the small integers.
+ snprintf(text, sizeof(text), "%d-", sampler.getStructReturnIndex());
+ mangledName += text;
+ } else {
+ switch (sampler.getVectorSize()) {
+ case 1: mangledName += "1"; break;
+ case 2: mangledName += "2"; break;
+ case 3: mangledName += "3"; break;
+ case 4: break; // default to prior name mangle behavior
+ }
+ }
+#endif
+
+ if (sampler.isMultiSample())
+ mangledName += "M";
+ break;
+ case EbtStruct:
+ case EbtBlock:
+ if (basicType == EbtStruct)
+ mangledName += "struct-";
+ else
+ mangledName += "block-";
+ if (typeName)
+ mangledName += *typeName;
+ for (unsigned int i = 0; i < structure->size(); ++i) {
+ mangledName += '-';
+ (*structure)[i].type->buildMangledName(mangledName);
+ }
+ default:
+ break;
+ }
+
+ if (getVectorSize() > 0)
+ mangledName += static_cast<char>('0' + getVectorSize());
+ else {
+ mangledName += static_cast<char>('0' + getMatrixCols());
+ mangledName += static_cast<char>('0' + getMatrixRows());
+ }
+
+ if (arraySizes) {
+ const int maxSize = 11;
+ char buf[maxSize];
+ for (int i = 0; i < arraySizes->getNumDims(); ++i) {
+ if (arraySizes->getDimNode(i)) {
+ if (arraySizes->getDimNode(i)->getAsSymbolNode())
+ snprintf(buf, maxSize, "s%d", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
+ else
+ snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i));
+ } else
+ snprintf(buf, maxSize, "%d", arraySizes->getDimSize(i));
+ mangledName += '[';
+ mangledName += buf;
+ mangledName += ']';
+ }
+ }
+}
+
+#ifndef GLSLANG_WEB
+
+//
+// Dump functions.
+//
+
+void TSymbol::dumpExtensions(TInfoSink& infoSink) const
+{
+ int numExtensions = getNumExtensions();
+ if (numExtensions) {
+ infoSink.debug << " <";
+
+ for (int i = 0; i < numExtensions; i++)
+ infoSink.debug << getExtensions()[i] << ",";
+
+ infoSink.debug << ">";
+ }
+}
+
+void TVariable::dump(TInfoSink& infoSink, bool complete) const
+{
+ if (complete) {
+ infoSink.debug << getName().c_str() << ": " << type.getCompleteString();
+ dumpExtensions(infoSink);
+ } else {
+ infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " "
+ << type.getBasicTypeString();
+
+ if (type.isArray())
+ infoSink.debug << "[0]";
+ }
+
+ infoSink.debug << "\n";
+}
+
+void TFunction::dump(TInfoSink& infoSink, bool complete) const
+{
+ if (complete) {
+ infoSink.debug << getName().c_str() << ": " << returnType.getCompleteString() << " " << getName().c_str()
+ << "(";
+
+ int numParams = getParamCount();
+ for (int i = 0; i < numParams; i++) {
+ const TParameter &param = parameters[i];
+ infoSink.debug << param.type->getCompleteString() << " "
+ << (param.type->isStruct() ? "of " + param.type->getTypeName() + " " : "")
+ << (param.name ? *param.name : "") << (i < numParams - 1 ? "," : "");
+ }
+
+ infoSink.debug << ")";
+ dumpExtensions(infoSink);
+ } else {
+ infoSink.debug << getName().c_str() << ": " << returnType.getBasicTypeString() << " "
+ << getMangledName().c_str() << "n";
+ }
+
+ infoSink.debug << "\n";
+}
+
+void TAnonMember::dump(TInfoSink& TInfoSink, bool) const
+{
+ TInfoSink.debug << "anonymous member " << getMemberNumber() << " of " << getAnonContainer().getName().c_str()
+ << "\n";
+}
+
+void TSymbolTableLevel::dump(TInfoSink& infoSink, bool complete) const
+{
+ tLevel::const_iterator it;
+ for (it = level.begin(); it != level.end(); ++it)
+ (*it).second->dump(infoSink, complete);
+}
+
+void TSymbolTable::dump(TInfoSink& infoSink, bool complete) const
+{
+ for (int level = currentLevel(); level >= 0; --level) {
+ infoSink.debug << "LEVEL " << level << "\n";
+ table[level]->dump(infoSink, complete);
+ }
+}
+
+#endif
+
+//
+// Functions have buried pointers to delete.
+//
+TFunction::~TFunction()
+{
+ for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
+ delete (*i).type;
+}
+
+//
+// Symbol table levels are a map of pointers to symbols that have to be deleted.
+//
+TSymbolTableLevel::~TSymbolTableLevel()
+{
+ for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+ delete (*it).second;
+
+ delete [] defaultPrecision;
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in operation.
+//
+void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
+{
+ tLevel::const_iterator candidate = level.lower_bound(name);
+ while (candidate != level.end()) {
+ const TString& candidateName = (*candidate).first;
+ TString::size_type parenAt = candidateName.find_first_of('(');
+ if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) {
+ TFunction* function = (*candidate).second->getAsFunction();
+ function->relateToOperator(op);
+ } else
+ break;
+ ++candidate;
+ }
+}
+
+// Make all function overloads of the given name require an extension(s).
+// Should only be used for a version/profile that actually needs the extension(s).
+void TSymbolTableLevel::setFunctionExtensions(const char* name, int num, const char* const extensions[])
+{
+ tLevel::const_iterator candidate = level.lower_bound(name);
+ while (candidate != level.end()) {
+ const TString& candidateName = (*candidate).first;
+ TString::size_type parenAt = candidateName.find_first_of('(');
+ if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) {
+ TSymbol* symbol = candidate->second;
+ symbol->setExtensions(num, extensions);
+ } else
+ break;
+ ++candidate;
+ }
+}
+
+//
+// Make all symbols in this table level read only.
+//
+void TSymbolTableLevel::readOnly()
+{
+ for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+ (*it).second->makeReadOnly();
+}
+
+//
+// Copy a symbol, but the copy is writable; call readOnly() afterward if that's not desired.
+//
+TSymbol::TSymbol(const TSymbol& copyOf)
+{
+ name = NewPoolTString(copyOf.name->c_str());
+ uniqueId = copyOf.uniqueId;
+ writable = true;
+}
+
+TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf)
+{
+ type.deepCopy(copyOf.type);
+ userType = copyOf.userType;
+
+ // we don't support specialization-constant subtrees in cloned tables, only extensions
+ constSubtree = nullptr;
+ extensions = nullptr;
+ memberExtensions = nullptr;
+ if (copyOf.getNumExtensions() > 0)
+ setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions());
+ if (copyOf.hasMemberExtensions()) {
+ for (int m = 0; m < (int)copyOf.type.getStruct()->size(); ++m) {
+ if (copyOf.getNumMemberExtensions(m) > 0)
+ setMemberExtensions(m, copyOf.getNumMemberExtensions(m), copyOf.getMemberExtensions(m));
+ }
+ }
+
+ if (! copyOf.constArray.empty()) {
+ assert(! copyOf.type.isStruct());
+ TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size());
+ constArray = newArray;
+ }
+}
+
+TVariable* TVariable::clone() const
+{
+ TVariable *variable = new TVariable(*this);
+
+ return variable;
+}
+
+TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
+{
+ for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
+ TParameter param;
+ parameters.push_back(param);
+ parameters.back().copyParam(copyOf.parameters[i]);
+ }
+
+ extensions = nullptr;
+ if (copyOf.getNumExtensions() > 0)
+ setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions());
+ returnType.deepCopy(copyOf.returnType);
+ mangledName = copyOf.mangledName;
+ op = copyOf.op;
+ defined = copyOf.defined;
+ prototyped = copyOf.prototyped;
+ implicitThis = copyOf.implicitThis;
+ illegalImplicitThis = copyOf.illegalImplicitThis;
+ defaultParamCount = copyOf.defaultParamCount;
+}
+
+TFunction* TFunction::clone() const
+{
+ TFunction *function = new TFunction(*this);
+
+ return function;
+}
+
+TAnonMember* TAnonMember::clone() const
+{
+ // Anonymous members of a given block should be cloned at a higher level,
+ // where they can all be assured to still end up pointing to a single
+ // copy of the original container.
+ assert(0);
+
+ return 0;
+}
+
+TSymbolTableLevel* TSymbolTableLevel::clone() const
+{
+ TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
+ symTableLevel->anonId = anonId;
+ symTableLevel->thisLevel = thisLevel;
+ std::vector<bool> containerCopied(anonId, false);
+ tLevel::const_iterator iter;
+ for (iter = level.begin(); iter != level.end(); ++iter) {
+ const TAnonMember* anon = iter->second->getAsAnonMember();
+ if (anon) {
+ // Insert all the anonymous members of this same container at once,
+ // avoid inserting the remaining members in the future, once this has been done,
+ // allowing them to all be part of the same new container.
+ if (! containerCopied[anon->getAnonId()]) {
+ TVariable* container = anon->getAnonContainer().clone();
+ container->changeName(NewPoolTString(""));
+ // insert the container and all its members
+ symTableLevel->insert(*container, false);
+ containerCopied[anon->getAnonId()] = true;
+ }
+ } else
+ symTableLevel->insert(*iter->second->clone(), false);
+ }
+
+ return symTableLevel;
+}
+
+void TSymbolTable::copyTable(const TSymbolTable& copyOf)
+{
+ assert(adoptedLevels == copyOf.adoptedLevels);
+
+ uniqueId = copyOf.uniqueId;
+ noBuiltInRedeclarations = copyOf.noBuiltInRedeclarations;
+ separateNameSpaces = copyOf.separateNameSpaces;
+ for (unsigned int i = copyOf.adoptedLevels; i < copyOf.table.size(); ++i)
+ table.push_back(copyOf.table[i]->clone());
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.h b/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.h
new file mode 100644
index 0000000000..40ca3da532
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/SymbolTable.h
@@ -0,0 +1,885 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _SYMBOL_TABLE_INCLUDED_
+#define _SYMBOL_TABLE_INCLUDED_
+
+//
+// Symbol table for parsing. Has these design characteristics:
+//
+// * Same symbol table can be used to compile many shaders, to preserve
+// effort of creating and loading with the large numbers of built-in
+// symbols.
+//
+// --> This requires a copy mechanism, so initial pools used to create
+// the shared information can be popped. Done through "clone"
+// methods.
+//
+// * Name mangling will be used to give each function a unique name
+// so that symbol table lookups are never ambiguous. This allows
+// a simpler symbol table structure.
+//
+// * Pushing and popping of scope, so symbol table will really be a stack
+// of symbol tables. Searched from the top, with new inserts going into
+// the top.
+//
+// * Constants: Compile time constant symbols will keep their values
+// in the symbol table. The parser can substitute constants at parse
+// time, including doing constant folding and constant propagation.
+//
+// * No temporaries: Temporaries made from operations (+, --, .xy, etc.)
+// are tracked in the intermediate representation, not the symbol table.
+//
+
+#include "../Include/Common.h"
+#include "../Include/intermediate.h"
+#include "../Include/InfoSink.h"
+
+namespace glslang {
+
+//
+// Symbol base class. (Can build functions or variables out of these...)
+//
+
+class TVariable;
+class TFunction;
+class TAnonMember;
+
+typedef TVector<const char*> TExtensionList;
+
+class TSymbol {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+ explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { }
+ virtual TSymbol* clone() const = 0;
+ virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool
+
+ virtual const TString& getName() const { return *name; }
+ virtual void changeName(const TString* newName) { name = newName; }
+ virtual void addPrefix(const char* prefix)
+ {
+ TString newName(prefix);
+ newName.append(*name);
+ changeName(NewPoolTString(newName.c_str()));
+ }
+ virtual const TString& getMangledName() const { return getName(); }
+ virtual TFunction* getAsFunction() { return 0; }
+ virtual const TFunction* getAsFunction() const { return 0; }
+ virtual TVariable* getAsVariable() { return 0; }
+ virtual const TVariable* getAsVariable() const { return 0; }
+ virtual const TAnonMember* getAsAnonMember() const { return 0; }
+ virtual const TType& getType() const = 0;
+ virtual TType& getWritableType() = 0;
+ virtual void setUniqueId(int id) { uniqueId = id; }
+ virtual int getUniqueId() const { return uniqueId; }
+ virtual void setExtensions(int numExts, const char* const exts[])
+ {
+ assert(extensions == 0);
+ assert(numExts > 0);
+ extensions = NewPoolObject(extensions);
+ for (int e = 0; e < numExts; ++e)
+ extensions->push_back(exts[e]);
+ }
+ virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); }
+ virtual const char** getExtensions() const { return extensions->data(); }
+
+#ifndef GLSLANG_WEB
+ virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0;
+ void dumpExtensions(TInfoSink& infoSink) const;
+#endif
+
+ virtual bool isReadOnly() const { return ! writable; }
+ virtual void makeReadOnly() { writable = false; }
+
+protected:
+ explicit TSymbol(const TSymbol&);
+ TSymbol& operator=(const TSymbol&);
+
+ const TString *name;
+ unsigned int uniqueId; // For cross-scope comparing during code generation
+
+ // For tracking what extensions must be present
+ // (don't use if correct version/profile is present).
+ TExtensionList* extensions; // an array of pointers to existing constant char strings
+
+ //
+ // N.B.: Non-const functions that will be generally used should assert on this,
+ // to avoid overwriting shared symbol-table information.
+ //
+ bool writable;
+};
+
+//
+// Variable class, meaning a symbol that's not a function.
+//
+// There could be a separate class hierarchy for Constant variables;
+// Only one of int, bool, or float, (or none) is correct for
+// any particular use, but it's easy to do this way, and doesn't
+// seem worth having separate classes, and "getConst" can't simply return
+// different values for different types polymorphically, so this is
+// just simple and pragmatic.
+//
+class TVariable : public TSymbol {
+public:
+ TVariable(const TString *name, const TType& t, bool uT = false )
+ : TSymbol(name),
+ userType(uT),
+ constSubtree(nullptr),
+ memberExtensions(nullptr),
+ anonId(-1)
+ { type.shallowCopy(t); }
+ virtual TVariable* clone() const;
+ virtual ~TVariable() { }
+
+ virtual TVariable* getAsVariable() { return this; }
+ virtual const TVariable* getAsVariable() const { return this; }
+ virtual const TType& getType() const { return type; }
+ virtual TType& getWritableType() { assert(writable); return type; }
+ virtual bool isUserType() const { return userType; }
+ virtual const TConstUnionArray& getConstArray() const { return constArray; }
+ virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; }
+ virtual void setConstArray(const TConstUnionArray& array) { constArray = array; }
+ virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
+ virtual TIntermTyped* getConstSubtree() const { return constSubtree; }
+ virtual void setAnonId(int i) { anonId = i; }
+ virtual int getAnonId() const { return anonId; }
+
+ virtual void setMemberExtensions(int member, int numExts, const char* const exts[])
+ {
+ assert(type.isStruct());
+ assert(numExts > 0);
+ if (memberExtensions == nullptr) {
+ memberExtensions = NewPoolObject(memberExtensions);
+ memberExtensions->resize(type.getStruct()->size());
+ }
+ for (int e = 0; e < numExts; ++e)
+ (*memberExtensions)[member].push_back(exts[e]);
+ }
+ virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; }
+ virtual int getNumMemberExtensions(int member) const
+ {
+ return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size();
+ }
+ virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
+
+#ifndef GLSLANG_WEB
+ virtual void dump(TInfoSink& infoSink, bool complete = false) const;
+#endif
+
+protected:
+ explicit TVariable(const TVariable&);
+ TVariable& operator=(const TVariable&);
+
+ TType type;
+ bool userType;
+
+ // we are assuming that Pool Allocator will free the memory allocated to unionArray
+ // when this object is destroyed
+
+ TConstUnionArray constArray; // for compile-time constant value
+ TIntermTyped* constSubtree; // for specialization constant computation
+ TVector<TExtensionList>* memberExtensions; // per-member extension list, allocated only when needed
+ int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose
+};
+
+//
+// The function sub-class of symbols and the parser will need to
+// share this definition of a function parameter.
+//
+struct TParameter {
+ TString *name;
+ TType* type;
+ TIntermTyped* defaultValue;
+ void copyParam(const TParameter& param)
+ {
+ if (param.name)
+ name = NewPoolTString(param.name->c_str());
+ else
+ name = 0;
+ type = param.type->clone();
+ defaultValue = param.defaultValue;
+ }
+ TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; }
+};
+
+//
+// The function sub-class of a symbol.
+//
+class TFunction : public TSymbol {
+public:
+ explicit TFunction(TOperator o) :
+ TSymbol(0),
+ op(o),
+ defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { }
+ TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
+ TSymbol(name),
+ mangledName(*name + '('),
+ op(tOp),
+ defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0)
+ {
+ returnType.shallowCopy(retType);
+ declaredBuiltIn = retType.getQualifier().builtIn;
+ }
+ virtual TFunction* clone() const override;
+ virtual ~TFunction();
+
+ virtual TFunction* getAsFunction() override { return this; }
+ virtual const TFunction* getAsFunction() const override { return this; }
+
+ // Install 'p' as the (non-'this') last parameter.
+ // Non-'this' parameters are reflected in both the list of parameters and the
+ // mangled name.
+ virtual void addParameter(TParameter& p)
+ {
+ assert(writable);
+ parameters.push_back(p);
+ p.type->appendMangledName(mangledName);
+
+ if (p.defaultValue != nullptr)
+ defaultParamCount++;
+ }
+
+ // Install 'this' as the first parameter.
+ // 'this' is reflected in the list of parameters, but not the mangled name.
+ virtual void addThisParameter(TType& type, const char* name)
+ {
+ TParameter p = { NewPoolTString(name), new TType, nullptr };
+ p.type->shallowCopy(type);
+ parameters.insert(parameters.begin(), p);
+ }
+
+ virtual void addPrefix(const char* prefix) override
+ {
+ TSymbol::addPrefix(prefix);
+ mangledName.insert(0, prefix);
+ }
+
+ virtual void removePrefix(const TString& prefix)
+ {
+ assert(mangledName.compare(0, prefix.size(), prefix) == 0);
+ mangledName.erase(0, prefix.size());
+ }
+
+ virtual const TString& getMangledName() const override { return mangledName; }
+ virtual const TType& getType() const override { return returnType; }
+ virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; }
+ virtual TType& getWritableType() override { return returnType; }
+ virtual void relateToOperator(TOperator o) { assert(writable); op = o; }
+ virtual TOperator getBuiltInOp() const { return op; }
+ virtual void setDefined() { assert(writable); defined = true; }
+ virtual bool isDefined() const { return defined; }
+ virtual void setPrototyped() { assert(writable); prototyped = true; }
+ virtual bool isPrototyped() const { return prototyped; }
+ virtual void setImplicitThis() { assert(writable); implicitThis = true; }
+ virtual bool hasImplicitThis() const { return implicitThis; }
+ virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; }
+ virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; }
+
+ // Return total number of parameters
+ virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
+ // Return number of parameters with default values.
+ virtual int getDefaultParamCount() const { return defaultParamCount; }
+ // Return number of fixed parameters (without default values)
+ virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); }
+
+ virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
+ virtual const TParameter& operator[](int i) const { return parameters[i]; }
+
+#ifndef GLSLANG_WEB
+ virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
+#endif
+
+protected:
+ explicit TFunction(const TFunction&);
+ TFunction& operator=(const TFunction&);
+
+ typedef TVector<TParameter> TParamList;
+ TParamList parameters;
+ TType returnType;
+ TBuiltInVariable declaredBuiltIn;
+
+ TString mangledName;
+ TOperator op;
+ bool defined;
+ bool prototyped;
+ bool implicitThis; // True if this function is allowed to see all members of 'this'
+ bool illegalImplicitThis; // True if this function is not supposed to have access to dynamic members of 'this',
+ // even if it finds member variables in the symbol table.
+ // This is important for a static member function that has member variables in scope,
+ // but is not allowed to use them, or see hidden symbols instead.
+ int defaultParamCount;
+};
+
+//
+// Members of anonymous blocks are a kind of TSymbol. They are not hidden in
+// the symbol table behind a container; rather they are visible and point to
+// their anonymous container. (The anonymous container is found through the
+// member, not the other way around.)
+//
+class TAnonMember : public TSymbol {
+public:
+ TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { }
+ virtual TAnonMember* clone() const override;
+ virtual ~TAnonMember() { }
+
+ virtual const TAnonMember* getAsAnonMember() const override { return this; }
+ virtual const TVariable& getAnonContainer() const { return anonContainer; }
+ virtual unsigned int getMemberNumber() const { return memberNumber; }
+
+ virtual const TType& getType() const override
+ {
+ const TTypeList& types = *anonContainer.getType().getStruct();
+ return *types[memberNumber].type;
+ }
+
+ virtual TType& getWritableType() override
+ {
+ assert(writable);
+ const TTypeList& types = *anonContainer.getType().getStruct();
+ return *types[memberNumber].type;
+ }
+
+ virtual void setExtensions(int numExts, const char* const exts[]) override
+ {
+ anonContainer.setMemberExtensions(memberNumber, numExts, exts);
+ }
+ virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); }
+ virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
+
+ virtual int getAnonId() const { return anonId; }
+#ifndef GLSLANG_WEB
+ virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
+#endif
+
+protected:
+ explicit TAnonMember(const TAnonMember&);
+ TAnonMember& operator=(const TAnonMember&);
+
+ TVariable& anonContainer;
+ unsigned int memberNumber;
+ int anonId;
+};
+
+class TSymbolTableLevel {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+ TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { }
+ ~TSymbolTableLevel();
+
+ bool insert(TSymbol& symbol, bool separateNameSpaces)
+ {
+ //
+ // returning true means symbol was added to the table with no semantic errors
+ //
+ const TString& name = symbol.getName();
+ if (name == "") {
+ symbol.getAsVariable()->setAnonId(anonId++);
+ // An empty name means an anonymous container, exposing its members to the external scope.
+ // Give it a name and insert its members in the symbol table, pointing to the container.
+ char buf[20];
+ snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId());
+ symbol.changeName(NewPoolTString(buf));
+
+ return insertAnonymousMembers(symbol, 0);
+ } else {
+ // Check for redefinition errors:
+ // - STL itself will tell us if there is a direct name collision, with name mangling, at this level
+ // - additionally, check for function-redefining-variable name collisions
+ const TString& insertName = symbol.getMangledName();
+ if (symbol.getAsFunction()) {
+ // make sure there isn't a variable of this name
+ if (! separateNameSpaces && level.find(name) != level.end())
+ return false;
+
+ // insert, and whatever happens is okay
+ level.insert(tLevelPair(insertName, &symbol));
+
+ return true;
+ } else
+ return level.insert(tLevelPair(insertName, &symbol)).second;
+ }
+ }
+
+ // Add more members to an already inserted aggregate object
+ bool amend(TSymbol& symbol, int firstNewMember)
+ {
+ // See insert() for comments on basic explanation of insert.
+ // This operates similarly, but more simply.
+ // Only supporting amend of anonymous blocks so far.
+ if (IsAnonymous(symbol.getName()))
+ return insertAnonymousMembers(symbol, firstNewMember);
+ else
+ return false;
+ }
+
+ bool insertAnonymousMembers(TSymbol& symbol, int firstMember)
+ {
+ const TTypeList& types = *symbol.getAsVariable()->getType().getStruct();
+ for (unsigned int m = firstMember; m < types.size(); ++m) {
+ TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId());
+ if (! level.insert(tLevelPair(member->getMangledName(), member)).second)
+ return false;
+ }
+
+ return true;
+ }
+
+ TSymbol* find(const TString& name) const
+ {
+ tLevel::const_iterator it = level.find(name);
+ if (it == level.end())
+ return 0;
+ else
+ return (*it).second;
+ }
+
+ void findFunctionNameList(const TString& name, TVector<const TFunction*>& list)
+ {
+ size_t parenAt = name.find_first_of('(');
+ TString base(name, 0, parenAt + 1);
+
+ tLevel::const_iterator begin = level.lower_bound(base);
+ base[parenAt] = ')'; // assume ')' is lexically after '('
+ tLevel::const_iterator end = level.upper_bound(base);
+ for (tLevel::const_iterator it = begin; it != end; ++it)
+ list.push_back(it->second->getAsFunction());
+ }
+
+ // See if there is already a function in the table having the given non-function-style name.
+ bool hasFunctionName(const TString& name) const
+ {
+ tLevel::const_iterator candidate = level.lower_bound(name);
+ if (candidate != level.end()) {
+ const TString& candidateName = (*candidate).first;
+ TString::size_type parenAt = candidateName.find_first_of('(');
+ if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0)
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // See if there is a variable at this level having the given non-function-style name.
+ // Return true if name is found, and set variable to true if the name was a variable.
+ bool findFunctionVariableName(const TString& name, bool& variable) const
+ {
+ tLevel::const_iterator candidate = level.lower_bound(name);
+ if (candidate != level.end()) {
+ const TString& candidateName = (*candidate).first;
+ TString::size_type parenAt = candidateName.find_first_of('(');
+ if (parenAt == candidateName.npos) {
+ // not a mangled name
+ if (candidateName == name) {
+ // found a variable name match
+ variable = true;
+ return true;
+ }
+ } else {
+ // a mangled name
+ if (candidateName.compare(0, parenAt, name) == 0) {
+ // found a function name match
+ variable = false;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // Use this to do a lazy 'push' of precision defaults the first time
+ // a precision statement is seen in a new scope. Leave it at 0 for
+ // when no push was needed. Thus, it is not the current defaults,
+ // it is what to restore the defaults to when popping a level.
+ void setPreviousDefaultPrecisions(const TPrecisionQualifier *p)
+ {
+ // can call multiple times at one scope, will only latch on first call,
+ // as we're tracking the previous scope's values, not the current values
+ if (defaultPrecision != 0)
+ return;
+
+ defaultPrecision = new TPrecisionQualifier[EbtNumTypes];
+ for (int t = 0; t < EbtNumTypes; ++t)
+ defaultPrecision[t] = p[t];
+ }
+
+ void getPreviousDefaultPrecisions(TPrecisionQualifier *p)
+ {
+ // can be called for table level pops that didn't set the
+ // defaults
+ if (defaultPrecision == 0 || p == 0)
+ return;
+
+ for (int t = 0; t < EbtNumTypes; ++t)
+ p[t] = defaultPrecision[t];
+ }
+
+ void relateToOperator(const char* name, TOperator op);
+ void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
+#ifndef GLSLANG_WEB
+ void dump(TInfoSink& infoSink, bool complete = false) const;
+#endif
+ TSymbolTableLevel* clone() const;
+ void readOnly();
+
+ void setThisLevel() { thisLevel = true; }
+ bool isThisLevel() const { return thisLevel; }
+
+protected:
+ explicit TSymbolTableLevel(TSymbolTableLevel&);
+ TSymbolTableLevel& operator=(TSymbolTableLevel&);
+
+ typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
+ typedef const tLevel::value_type tLevelPair;
+ typedef std::pair<tLevel::iterator, bool> tInsertResult;
+
+ tLevel level; // named mappings
+ TPrecisionQualifier *defaultPrecision;
+ int anonId;
+ bool thisLevel; // True if this level of the symbol table is a structure scope containing member function
+ // that are supposed to see anonymous access to member variables.
+};
+
+class TSymbolTable {
+public:
+ TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0)
+ {
+ //
+ // This symbol table cannot be used until push() is called.
+ //
+ }
+ ~TSymbolTable()
+ {
+ // this can be called explicitly; safest to code it so it can be called multiple times
+
+ // don't deallocate levels passed in from elsewhere
+ while (table.size() > adoptedLevels)
+ pop(0);
+ }
+
+ void adoptLevels(TSymbolTable& symTable)
+ {
+ for (unsigned int level = 0; level < symTable.table.size(); ++level) {
+ table.push_back(symTable.table[level]);
+ ++adoptedLevels;
+ }
+ uniqueId = symTable.uniqueId;
+ noBuiltInRedeclarations = symTable.noBuiltInRedeclarations;
+ separateNameSpaces = symTable.separateNameSpaces;
+ }
+
+ //
+ // While level adopting is generic, the methods below enact a the following
+ // convention for levels:
+ // 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables
+ // 1: per-stage built-ins, shared across all compiles, but a different copy per stage
+ // 2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins
+ // 3: user-shader globals
+ //
+protected:
+ static const int globalLevel = 3;
+ bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
+ bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
+ bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
+public:
+ bool isEmpty() { return table.size() == 0; }
+ bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
+ bool atGlobalLevel() { return isGlobalLevel(currentLevel()); }
+
+ void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
+ void setSeparateNameSpaces() { separateNameSpaces = true; }
+
+ void push()
+ {
+ table.push_back(new TSymbolTableLevel);
+ }
+
+ // Make a new symbol-table level to represent the scope introduced by a structure
+ // containing member functions, such that the member functions can find anonymous
+ // references to member variables.
+ //
+ // 'thisSymbol' should have a name of "" to trigger anonymous structure-member
+ // symbol finds.
+ void pushThis(TSymbol& thisSymbol)
+ {
+ assert(thisSymbol.getName().size() == 0);
+ table.push_back(new TSymbolTableLevel);
+ table.back()->setThisLevel();
+ insert(thisSymbol);
+ }
+
+ void pop(TPrecisionQualifier *p)
+ {
+ table[currentLevel()]->getPreviousDefaultPrecisions(p);
+ delete table.back();
+ table.pop_back();
+ }
+
+ //
+ // Insert a visible symbol into the symbol table so it can
+ // be found later by name.
+ //
+ // Returns false if the was a name collision.
+ //
+ bool insert(TSymbol& symbol)
+ {
+ symbol.setUniqueId(++uniqueId);
+
+ // make sure there isn't a function of this variable name
+ if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName()))
+ return false;
+
+ // check for not overloading or redefining a built-in function
+ if (noBuiltInRedeclarations) {
+ if (atGlobalLevel() && currentLevel() > 0) {
+ if (table[0]->hasFunctionName(symbol.getName()))
+ return false;
+ if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName()))
+ return false;
+ }
+ }
+
+ return table[currentLevel()]->insert(symbol, separateNameSpaces);
+ }
+
+ // Add more members to an already inserted aggregate object
+ bool amend(TSymbol& symbol, int firstNewMember)
+ {
+ // See insert() for comments on basic explanation of insert.
+ // This operates similarly, but more simply.
+ return table[currentLevel()]->amend(symbol, firstNewMember);
+ }
+
+ //
+ // To allocate an internal temporary, which will need to be uniquely
+ // identified by the consumer of the AST, but never need to
+ // found by doing a symbol table search by name, hence allowed an
+ // arbitrary name in the symbol with no worry of collision.
+ //
+ void makeInternalVariable(TSymbol& symbol)
+ {
+ symbol.setUniqueId(++uniqueId);
+ }
+
+ //
+ // Copy a variable or anonymous member's structure from a shared level so that
+ // it can be added (soon after return) to the symbol table where it can be
+ // modified without impacting other users of the shared table.
+ //
+ TSymbol* copyUpDeferredInsert(TSymbol* shared)
+ {
+ if (shared->getAsVariable()) {
+ TSymbol* copy = shared->clone();
+ copy->setUniqueId(shared->getUniqueId());
+ return copy;
+ } else {
+ const TAnonMember* anon = shared->getAsAnonMember();
+ assert(anon);
+ TVariable* container = anon->getAnonContainer().clone();
+ container->changeName(NewPoolTString(""));
+ container->setUniqueId(anon->getAnonContainer().getUniqueId());
+ return container;
+ }
+ }
+
+ TSymbol* copyUp(TSymbol* shared)
+ {
+ TSymbol* copy = copyUpDeferredInsert(shared);
+ table[globalLevel]->insert(*copy, separateNameSpaces);
+ if (shared->getAsVariable())
+ return copy;
+ else {
+ // return the copy of the anonymous member
+ return table[globalLevel]->find(shared->getName());
+ }
+ }
+
+ // Normal find of a symbol, that can optionally say whether the symbol was found
+ // at a built-in level or the current top-scope level.
+ TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0)
+ {
+ int level = currentLevel();
+ TSymbol* symbol;
+ int thisDepth = 0;
+ do {
+ if (table[level]->isThisLevel())
+ ++thisDepth;
+ symbol = table[level]->find(name);
+ --level;
+ } while (symbol == nullptr && level >= 0);
+ level++;
+ if (builtIn)
+ *builtIn = isBuiltInLevel(level);
+ if (currentScope)
+ *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals
+ if (thisDepthP != nullptr) {
+ if (! table[level]->isThisLevel())
+ thisDepth = 0;
+ *thisDepthP = thisDepth;
+ }
+
+ return symbol;
+ }
+
+ // Find of a symbol that returns how many layers deep of nested
+ // structures-with-member-functions ('this' scopes) deep the symbol was
+ // found in.
+ TSymbol* find(const TString& name, int& thisDepth)
+ {
+ int level = currentLevel();
+ TSymbol* symbol;
+ thisDepth = 0;
+ do {
+ if (table[level]->isThisLevel())
+ ++thisDepth;
+ symbol = table[level]->find(name);
+ --level;
+ } while (symbol == 0 && level >= 0);
+
+ if (! table[level + 1]->isThisLevel())
+ thisDepth = 0;
+
+ return symbol;
+ }
+
+ bool isFunctionNameVariable(const TString& name) const
+ {
+ if (separateNameSpaces)
+ return false;
+
+ int level = currentLevel();
+ do {
+ bool variable;
+ bool found = table[level]->findFunctionVariableName(name, variable);
+ if (found)
+ return variable;
+ --level;
+ } while (level >= 0);
+
+ return false;
+ }
+
+ void findFunctionNameList(const TString& name, TVector<const TFunction*>& list, bool& builtIn)
+ {
+ // For user levels, return the set found in the first scope with a match
+ builtIn = false;
+ int level = currentLevel();
+ do {
+ table[level]->findFunctionNameList(name, list);
+ --level;
+ } while (list.empty() && level >= globalLevel);
+
+ if (! list.empty())
+ return;
+
+ // Gather across all built-in levels; they don't hide each other
+ builtIn = true;
+ do {
+ table[level]->findFunctionNameList(name, list);
+ --level;
+ } while (level >= 0);
+ }
+
+ void relateToOperator(const char* name, TOperator op)
+ {
+ for (unsigned int level = 0; level < table.size(); ++level)
+ table[level]->relateToOperator(name, op);
+ }
+
+ void setFunctionExtensions(const char* name, int num, const char* const extensions[])
+ {
+ for (unsigned int level = 0; level < table.size(); ++level)
+ table[level]->setFunctionExtensions(name, num, extensions);
+ }
+
+ void setVariableExtensions(const char* name, int numExts, const char* const extensions[])
+ {
+ TSymbol* symbol = find(TString(name));
+ if (symbol == nullptr)
+ return;
+
+ symbol->setExtensions(numExts, extensions);
+ }
+
+ void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[])
+ {
+ TSymbol* symbol = find(TString(blockName));
+ if (symbol == nullptr)
+ return;
+ TVariable* variable = symbol->getAsVariable();
+ assert(variable != nullptr);
+
+ const TTypeList& structure = *variable->getAsVariable()->getType().getStruct();
+ for (int member = 0; member < (int)structure.size(); ++member) {
+ if (structure[member].type->getFieldName().compare(name) == 0) {
+ variable->setMemberExtensions(member, numExts, extensions);
+ return;
+ }
+ }
+ }
+
+ int getMaxSymbolId() { return uniqueId; }
+#ifndef GLSLANG_WEB
+ void dump(TInfoSink& infoSink, bool complete = false) const;
+#endif
+ void copyTable(const TSymbolTable& copyOf);
+
+ void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); }
+
+ void readOnly()
+ {
+ for (unsigned int level = 0; level < table.size(); ++level)
+ table[level]->readOnly();
+ }
+
+protected:
+ TSymbolTable(TSymbolTable&);
+ TSymbolTable& operator=(TSymbolTableLevel&);
+
+ int currentLevel() const { return static_cast<int>(table.size()) - 1; }
+
+ std::vector<TSymbolTableLevel*> table;
+ int uniqueId; // for unique identification in code generation
+ bool noBuiltInRedeclarations;
+ bool separateNameSpaces;
+ unsigned int adoptedLevels;
+};
+
+} // end namespace glslang
+
+#endif // _SYMBOL_TABLE_INCLUDED_
diff --git a/thirdparty/glslang/glslang/MachineIndependent/Versions.cpp b/thirdparty/glslang/glslang/MachineIndependent/Versions.cpp
new file mode 100644
index 0000000000..e549074df8
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/Versions.cpp
@@ -0,0 +1,1173 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Help manage multiple profiles, versions, extensions etc.
+//
+// These don't return error codes, as the presumption is parsing will
+// always continue as if the tested feature were enabled, and thus there
+// is no error recovery needed.
+//
+
+//
+// HOW TO add a feature enabled by an extension.
+//
+// To add a new hypothetical "Feature F" to the front end, where an extension
+// "XXX_extension_X" can be used to enable the feature, do the following.
+//
+// OVERVIEW: Specific features are what are error-checked for, not
+// extensions: A specific Feature F might be enabled by an extension, or a
+// particular version in a particular profile, or a stage, or combinations, etc.
+//
+// The basic mechanism is to use the following to "declare" all the things that
+// enable/disable Feature F, in a code path that implements Feature F:
+//
+// requireProfile()
+// profileRequires()
+// requireStage()
+// checkDeprecated()
+// requireNotRemoved()
+// requireExtensions()
+//
+// Typically, only the first two calls are needed. They go into a code path that
+// implements Feature F, and will log the proper error/warning messages. Parsing
+// will then always continue as if the tested feature was enabled.
+//
+// There is typically no if-testing or conditional parsing, just insertion of the calls above.
+// However, if symbols specific to the extension are added (step 5), they will
+// only be added under tests that the minimum version and profile are present.
+//
+// 1) Add a symbol name for the extension string at the bottom of Versions.h:
+//
+// const char* const XXX_extension_X = "XXX_extension_X";
+//
+// 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(),
+// the first function below:
+//
+// extensionBehavior[XXX_extension_X] = EBhDisable;
+//
+// 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble():
+//
+// "#define XXX_extension_X 1\n"
+//
+// The new-line is important, as that ends preprocess tokens.
+//
+// 4) Insert a profile check in the feature's path (unless all profiles support the feature,
+// for some version level). That is, call requireProfile() to constrain the profiles, e.g.:
+//
+// // ... in a path specific to Feature F...
+// requireProfile(loc,
+// ECoreProfile | ECompatibilityProfile,
+// "Feature F");
+//
+// 5) For each profile that supports the feature, insert version/extension checks:
+//
+// The mostly likely scenario is that Feature F can only be used with a
+// particular profile if XXX_extension_X is present or the version is
+// high enough that the core specification already incorporated it.
+//
+// // following the requireProfile() call...
+// profileRequires(loc,
+// ECoreProfile | ECompatibilityProfile,
+// 420, // 0 if no version incorporated the feature into the core spec.
+// XXX_extension_X, // can be a list of extensions that all add the feature
+// "Feature F Description");
+//
+// This allows the feature if either A) one of the extensions is enabled or
+// B) the version is high enough. If no version yet incorporates the feature
+// into core, pass in 0.
+//
+// This can be called multiple times, if different profiles support the
+// feature starting at different version numbers or with different
+// extensions.
+//
+// This must be called for each profile allowed by the initial call to requireProfile().
+//
+// Profiles are all masks, which can be "or"-ed together.
+//
+// ENoProfile
+// ECoreProfile
+// ECompatibilityProfile
+// EEsProfile
+//
+// The ENoProfile profile is only for desktop, before profiles showed up in version 150;
+// All other #version with no profile default to either es or core, and so have profiles.
+//
+// You can select all but a particular profile using ~. The following basically means "desktop":
+//
+// ~EEsProfile
+//
+// 6) If built-in symbols are added by the extension, add them in Initialize.cpp: Their use
+// will be automatically error checked against the extensions enabled at that moment.
+// see the comment at the top of Initialize.cpp for where to put them. Establish them at
+// the earliest release that supports the extension. Then, tag them with the
+// set of extensions that both enable them and are necessary, given the version of the symbol
+// table. (There is a different symbol table for each version.)
+//
+
+#include "parseVersions.h"
+#include "localintermediate.h"
+
+namespace glslang {
+
+#ifndef GLSLANG_WEB
+
+//
+// Initialize all extensions, almost always to 'disable', as once their features
+// are incorporated into a core version, their features are supported through allowing that
+// core version, not through a pseudo-enablement of the extension.
+//
+void TParseVersions::initializeExtensionBehavior()
+{
+ extensionBehavior[E_GL_OES_texture_3D] = EBhDisable;
+ extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable;
+ extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable;
+ extensionBehavior[E_GL_OES_EGL_image_external] = EBhDisable;
+ extensionBehavior[E_GL_OES_EGL_image_external_essl3] = EBhDisable;
+ extensionBehavior[E_GL_EXT_YUV_target] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_texture_lod] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shadow_samplers] = EBhDisable;
+ extensionBehavior[E_GL_ARB_texture_rectangle] = EBhDisable;
+ extensionBehavior[E_GL_3DL_array_objects] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shading_language_420pack] = EBhDisable;
+ extensionBehavior[E_GL_ARB_texture_gather] = EBhDisable;
+ extensionBehavior[E_GL_ARB_gpu_shader5] = EBhDisablePartial;
+ extensionBehavior[E_GL_ARB_separate_shader_objects] = EBhDisable;
+ extensionBehavior[E_GL_ARB_compute_shader] = EBhDisable;
+ extensionBehavior[E_GL_ARB_tessellation_shader] = EBhDisable;
+ extensionBehavior[E_GL_ARB_enhanced_layouts] = EBhDisable;
+ extensionBehavior[E_GL_ARB_texture_cube_map_array] = EBhDisable;
+ extensionBehavior[E_GL_ARB_texture_multisample] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_texture_lod] = EBhDisable;
+ extensionBehavior[E_GL_ARB_explicit_attrib_location] = EBhDisable;
+ extensionBehavior[E_GL_ARB_explicit_uniform_location] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_image_load_store] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_atomic_counters] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_draw_parameters] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_group_vote] = EBhDisable;
+ extensionBehavior[E_GL_ARB_derivative_control] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_texture_image_samples] = EBhDisable;
+ extensionBehavior[E_GL_ARB_viewport_array] = EBhDisable;
+ extensionBehavior[E_GL_ARB_gpu_shader_int64] = EBhDisable;
+ extensionBehavior[E_GL_ARB_gpu_shader_fp64] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_ballot] = EBhDisable;
+ extensionBehavior[E_GL_ARB_sparse_texture2] = EBhDisable;
+ extensionBehavior[E_GL_ARB_sparse_texture_clamp] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_stencil_export] = EBhDisable;
+// extensionBehavior[E_GL_ARB_cull_distance] = EBhDisable; // present for 4.5, but need extension control over block members
+ extensionBehavior[E_GL_ARB_post_depth_coverage] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_viewport_layer_array] = EBhDisable;
+ extensionBehavior[E_GL_ARB_fragment_shader_interlock] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_clock] = EBhDisable;
+ extensionBehavior[E_GL_ARB_uniform_buffer_object] = EBhDisable;
+ extensionBehavior[E_GL_ARB_sample_shading] = EBhDisable;
+
+ extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable;
+ extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable;
+ extensionBehavior[E_GL_KHR_shader_subgroup_arithmetic] = EBhDisable;
+ extensionBehavior[E_GL_KHR_shader_subgroup_ballot] = EBhDisable;
+ extensionBehavior[E_GL_KHR_shader_subgroup_shuffle] = EBhDisable;
+ extensionBehavior[E_GL_KHR_shader_subgroup_shuffle_relative] = EBhDisable;
+ extensionBehavior[E_GL_KHR_shader_subgroup_clustered] = EBhDisable;
+ extensionBehavior[E_GL_KHR_shader_subgroup_quad] = EBhDisable;
+ extensionBehavior[E_GL_KHR_memory_scope_semantics] = EBhDisable;
+
+ extensionBehavior[E_GL_EXT_shader_atomic_int64] = EBhDisable;
+
+ extensionBehavior[E_GL_EXT_shader_non_constant_global_initializers] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_image_load_formatted] = EBhDisable;
+ extensionBehavior[E_GL_EXT_post_depth_coverage] = EBhDisable;
+ extensionBehavior[E_GL_EXT_control_flow_attributes] = EBhDisable;
+ extensionBehavior[E_GL_EXT_nonuniform_qualifier] = EBhDisable;
+ extensionBehavior[E_GL_EXT_samplerless_texture_functions] = EBhDisable;
+ extensionBehavior[E_GL_EXT_scalar_block_layout] = EBhDisable;
+ extensionBehavior[E_GL_EXT_fragment_invocation_density] = EBhDisable;
+ extensionBehavior[E_GL_EXT_buffer_reference] = EBhDisable;
+ extensionBehavior[E_GL_EXT_buffer_reference2] = EBhDisable;
+ extensionBehavior[E_GL_EXT_buffer_reference_uvec2] = EBhDisable;
+ extensionBehavior[E_GL_EXT_demote_to_helper_invocation] = EBhDisable;
+
+ extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable;
+
+ // #line and #include
+ extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable;
+ extensionBehavior[E_GL_GOOGLE_include_directive] = EBhDisable;
+
+ extensionBehavior[E_GL_AMD_shader_ballot] = EBhDisable;
+ extensionBehavior[E_GL_AMD_shader_trinary_minmax] = EBhDisable;
+ extensionBehavior[E_GL_AMD_shader_explicit_vertex_parameter] = EBhDisable;
+ extensionBehavior[E_GL_AMD_gcn_shader] = EBhDisable;
+ extensionBehavior[E_GL_AMD_gpu_shader_half_float] = EBhDisable;
+ extensionBehavior[E_GL_AMD_texture_gather_bias_lod] = EBhDisable;
+ extensionBehavior[E_GL_AMD_gpu_shader_int16] = EBhDisable;
+ extensionBehavior[E_GL_AMD_shader_image_load_store_lod] = EBhDisable;
+ extensionBehavior[E_GL_AMD_shader_fragment_mask] = EBhDisable;
+ extensionBehavior[E_GL_AMD_gpu_shader_half_float_fetch] = EBhDisable;
+
+ extensionBehavior[E_GL_INTEL_shader_integer_functions2] = EBhDisable;
+
+ extensionBehavior[E_GL_NV_sample_mask_override_coverage] = EBhDisable;
+ extensionBehavior[E_SPV_NV_geometry_shader_passthrough] = EBhDisable;
+ extensionBehavior[E_GL_NV_viewport_array2] = EBhDisable;
+ extensionBehavior[E_GL_NV_stereo_view_rendering] = EBhDisable;
+ extensionBehavior[E_GL_NVX_multiview_per_view_attributes] = EBhDisable;
+ extensionBehavior[E_GL_NV_shader_atomic_int64] = EBhDisable;
+ extensionBehavior[E_GL_NV_conservative_raster_underestimation] = EBhDisable;
+ extensionBehavior[E_GL_NV_shader_noperspective_interpolation] = EBhDisable;
+ extensionBehavior[E_GL_NV_shader_subgroup_partitioned] = EBhDisable;
+ extensionBehavior[E_GL_NV_shading_rate_image] = EBhDisable;
+ extensionBehavior[E_GL_NV_ray_tracing] = EBhDisable;
+ extensionBehavior[E_GL_NV_fragment_shader_barycentric] = EBhDisable;
+ extensionBehavior[E_GL_NV_compute_shader_derivatives] = EBhDisable;
+ extensionBehavior[E_GL_NV_shader_texture_footprint] = EBhDisable;
+ extensionBehavior[E_GL_NV_mesh_shader] = EBhDisable;
+
+ extensionBehavior[E_GL_NV_cooperative_matrix] = EBhDisable;
+ extensionBehavior[E_GL_NV_shader_sm_builtins] = EBhDisable;
+ extensionBehavior[E_GL_NV_integer_cooperative_matrix] = EBhDisable;
+
+ // AEP
+ extensionBehavior[E_GL_ANDROID_extension_pack_es31a] = EBhDisable;
+ extensionBehavior[E_GL_KHR_blend_equation_advanced] = EBhDisable;
+ extensionBehavior[E_GL_OES_sample_variables] = EBhDisable;
+ extensionBehavior[E_GL_OES_shader_image_atomic] = EBhDisable;
+ extensionBehavior[E_GL_OES_shader_multisample_interpolation] = EBhDisable;
+ extensionBehavior[E_GL_OES_texture_storage_multisample_2d_array] = EBhDisable;
+ extensionBehavior[E_GL_EXT_geometry_shader] = EBhDisable;
+ extensionBehavior[E_GL_EXT_geometry_point_size] = EBhDisable;
+ extensionBehavior[E_GL_EXT_gpu_shader5] = EBhDisable;
+ extensionBehavior[E_GL_EXT_primitive_bounding_box] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_io_blocks] = EBhDisable;
+ extensionBehavior[E_GL_EXT_tessellation_shader] = EBhDisable;
+ extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable;
+ extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable;
+ extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable;
+
+ // OES matching AEP
+ extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable;
+ extensionBehavior[E_GL_OES_geometry_point_size] = EBhDisable;
+ extensionBehavior[E_GL_OES_gpu_shader5] = EBhDisable;
+ extensionBehavior[E_GL_OES_primitive_bounding_box] = EBhDisable;
+ extensionBehavior[E_GL_OES_shader_io_blocks] = EBhDisable;
+ extensionBehavior[E_GL_OES_tessellation_shader] = EBhDisable;
+ extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable;
+ extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable;
+ extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable;
+
+ // EXT extensions
+ extensionBehavior[E_GL_EXT_device_group] = EBhDisable;
+ extensionBehavior[E_GL_EXT_multiview] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_realtime_clock] = EBhDisable;
+
+ // OVR extensions
+ extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
+ extensionBehavior[E_GL_OVR_multiview2] = EBhDisable;
+
+ // explicit types
+ extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int8] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int16] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int32] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int64] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float16] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float32] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float64] = EBhDisable;
+
+ // subgroup extended types
+ extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int8] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int16] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int64] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = EBhDisable;
+}
+#endif // GLSLANG_WEB
+
+// Get code that is not part of a shared symbol table, is specific to this shader,
+// or needed by the preprocessor (which does not use a shared symbol table).
+void TParseVersions::getPreamble(std::string& preamble)
+{
+ if (isEsProfile()) {
+ preamble =
+ "#define GL_ES 1\n"
+ "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
+#ifdef GLSLANG_WEB
+ ;
+#else
+ "#define GL_OES_texture_3D 1\n"
+ "#define GL_OES_standard_derivatives 1\n"
+ "#define GL_EXT_frag_depth 1\n"
+ "#define GL_OES_EGL_image_external 1\n"
+ "#define GL_OES_EGL_image_external_essl3 1\n"
+ "#define GL_EXT_YUV_target 1\n"
+ "#define GL_EXT_shader_texture_lod 1\n"
+ "#define GL_EXT_shadow_samplers 1\n"
+
+ // AEP
+ "#define GL_ANDROID_extension_pack_es31a 1\n"
+ "#define GL_OES_sample_variables 1\n"
+ "#define GL_OES_shader_image_atomic 1\n"
+ "#define GL_OES_shader_multisample_interpolation 1\n"
+ "#define GL_OES_texture_storage_multisample_2d_array 1\n"
+ "#define GL_EXT_geometry_shader 1\n"
+ "#define GL_EXT_geometry_point_size 1\n"
+ "#define GL_EXT_gpu_shader5 1\n"
+ "#define GL_EXT_primitive_bounding_box 1\n"
+ "#define GL_EXT_shader_io_blocks 1\n"
+ "#define GL_EXT_tessellation_shader 1\n"
+ "#define GL_EXT_tessellation_point_size 1\n"
+ "#define GL_EXT_texture_buffer 1\n"
+ "#define GL_EXT_texture_cube_map_array 1\n"
+
+ // OES matching AEP
+ "#define GL_OES_geometry_shader 1\n"
+ "#define GL_OES_geometry_point_size 1\n"
+ "#define GL_OES_gpu_shader5 1\n"
+ "#define GL_OES_primitive_bounding_box 1\n"
+ "#define GL_OES_shader_io_blocks 1\n"
+ "#define GL_OES_tessellation_shader 1\n"
+ "#define GL_OES_tessellation_point_size 1\n"
+ "#define GL_OES_texture_buffer 1\n"
+ "#define GL_OES_texture_cube_map_array 1\n"
+ "#define GL_EXT_shader_non_constant_global_initializers 1\n"
+ ;
+
+ if (isEsProfile() && version >= 300) {
+ preamble += "#define GL_NV_shader_noperspective_interpolation 1\n";
+ }
+
+ } else {
+ preamble =
+ "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
+ "#define GL_ARB_texture_rectangle 1\n"
+ "#define GL_ARB_shading_language_420pack 1\n"
+ "#define GL_ARB_texture_gather 1\n"
+ "#define GL_ARB_gpu_shader5 1\n"
+ "#define GL_ARB_separate_shader_objects 1\n"
+ "#define GL_ARB_compute_shader 1\n"
+ "#define GL_ARB_tessellation_shader 1\n"
+ "#define GL_ARB_enhanced_layouts 1\n"
+ "#define GL_ARB_texture_cube_map_array 1\n"
+ "#define GL_ARB_texture_multisample 1\n"
+ "#define GL_ARB_shader_texture_lod 1\n"
+ "#define GL_ARB_explicit_attrib_location 1\n"
+ "#define GL_ARB_explicit_uniform_location 1\n"
+ "#define GL_ARB_shader_image_load_store 1\n"
+ "#define GL_ARB_shader_atomic_counters 1\n"
+ "#define GL_ARB_shader_draw_parameters 1\n"
+ "#define GL_ARB_shader_group_vote 1\n"
+ "#define GL_ARB_derivative_control 1\n"
+ "#define GL_ARB_shader_texture_image_samples 1\n"
+ "#define GL_ARB_viewport_array 1\n"
+ "#define GL_ARB_gpu_shader_int64 1\n"
+ "#define GL_ARB_gpu_shader_fp64 1\n"
+ "#define GL_ARB_shader_ballot 1\n"
+ "#define GL_ARB_sparse_texture2 1\n"
+ "#define GL_ARB_sparse_texture_clamp 1\n"
+ "#define GL_ARB_shader_stencil_export 1\n"
+ "#define GL_ARB_sample_shading 1\n"
+// "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members
+ "#define GL_ARB_post_depth_coverage 1\n"
+ "#define GL_ARB_fragment_shader_interlock 1\n"
+ "#define GL_ARB_uniform_buffer_object 1\n"
+ "#define GL_EXT_shader_non_constant_global_initializers 1\n"
+ "#define GL_EXT_shader_image_load_formatted 1\n"
+ "#define GL_EXT_post_depth_coverage 1\n"
+ "#define GL_EXT_control_flow_attributes 1\n"
+ "#define GL_EXT_nonuniform_qualifier 1\n"
+ "#define GL_EXT_shader_16bit_storage 1\n"
+ "#define GL_EXT_shader_8bit_storage 1\n"
+ "#define GL_EXT_samplerless_texture_functions 1\n"
+ "#define GL_EXT_scalar_block_layout 1\n"
+ "#define GL_EXT_fragment_invocation_density 1\n"
+ "#define GL_EXT_buffer_reference 1\n"
+ "#define GL_EXT_buffer_reference2 1\n"
+ "#define GL_EXT_buffer_reference_uvec2 1\n"
+ "#define GL_EXT_demote_to_helper_invocation 1\n"
+
+ // GL_KHR_shader_subgroup
+ "#define GL_KHR_shader_subgroup_basic 1\n"
+ "#define GL_KHR_shader_subgroup_vote 1\n"
+ "#define GL_KHR_shader_subgroup_arithmetic 1\n"
+ "#define GL_KHR_shader_subgroup_ballot 1\n"
+ "#define GL_KHR_shader_subgroup_shuffle 1\n"
+ "#define GL_KHR_shader_subgroup_shuffle_relative 1\n"
+ "#define GL_KHR_shader_subgroup_clustered 1\n"
+ "#define GL_KHR_shader_subgroup_quad 1\n"
+
+ "#define E_GL_EXT_shader_atomic_int64 1\n"
+ "#define E_GL_EXT_shader_realtime_clock 1\n"
+
+ "#define GL_AMD_shader_ballot 1\n"
+ "#define GL_AMD_shader_trinary_minmax 1\n"
+ "#define GL_AMD_shader_explicit_vertex_parameter 1\n"
+ "#define GL_AMD_gcn_shader 1\n"
+ "#define GL_AMD_gpu_shader_half_float 1\n"
+ "#define GL_AMD_texture_gather_bias_lod 1\n"
+ "#define GL_AMD_gpu_shader_int16 1\n"
+ "#define GL_AMD_shader_image_load_store_lod 1\n"
+ "#define GL_AMD_shader_fragment_mask 1\n"
+ "#define GL_AMD_gpu_shader_half_float_fetch 1\n"
+
+ "#define GL_INTEL_shader_integer_functions2 1\n"
+
+ "#define GL_NV_sample_mask_override_coverage 1\n"
+ "#define GL_NV_geometry_shader_passthrough 1\n"
+ "#define GL_NV_viewport_array2 1\n"
+ "#define GL_NV_shader_atomic_int64 1\n"
+ "#define GL_NV_conservative_raster_underestimation 1\n"
+ "#define GL_NV_shader_subgroup_partitioned 1\n"
+ "#define GL_NV_shading_rate_image 1\n"
+ "#define GL_NV_ray_tracing 1\n"
+ "#define GL_NV_fragment_shader_barycentric 1\n"
+ "#define GL_NV_compute_shader_derivatives 1\n"
+ "#define GL_NV_shader_texture_footprint 1\n"
+ "#define GL_NV_mesh_shader 1\n"
+ "#define GL_NV_cooperative_matrix 1\n"
+ "#define GL_NV_integer_cooperative_matrix 1\n"
+
+ "#define GL_EXT_shader_explicit_arithmetic_types 1\n"
+ "#define GL_EXT_shader_explicit_arithmetic_types_int8 1\n"
+ "#define GL_EXT_shader_explicit_arithmetic_types_int16 1\n"
+ "#define GL_EXT_shader_explicit_arithmetic_types_int32 1\n"
+ "#define GL_EXT_shader_explicit_arithmetic_types_int64 1\n"
+ "#define GL_EXT_shader_explicit_arithmetic_types_float16 1\n"
+ "#define GL_EXT_shader_explicit_arithmetic_types_float32 1\n"
+ "#define GL_EXT_shader_explicit_arithmetic_types_float64 1\n"
+
+ "#define GL_EXT_shader_subgroup_extended_types_int8 1\n"
+ "#define GL_EXT_shader_subgroup_extended_types_int16 1\n"
+ "#define GL_EXT_shader_subgroup_extended_types_int64 1\n"
+ "#define GL_EXT_shader_subgroup_extended_types_float16 1\n"
+ ;
+
+ if (version >= 150) {
+ // define GL_core_profile and GL_compatibility_profile
+ preamble += "#define GL_core_profile 1\n";
+
+ if (profile == ECompatibilityProfile)
+ preamble += "#define GL_compatibility_profile 1\n";
+ }
+#endif // GLSLANG_WEB
+ }
+
+#ifndef GLSLANG_WEB
+ if ((!isEsProfile() && version >= 140) ||
+ (isEsProfile() && version >= 310)) {
+ preamble +=
+ "#define GL_EXT_device_group 1\n"
+ "#define GL_EXT_multiview 1\n"
+ "#define GL_NV_shader_sm_builtins 1\n"
+ ;
+ }
+
+ if (version >= 300 /* both ES and non-ES */) {
+ preamble +=
+ "#define GL_OVR_multiview 1\n"
+ "#define GL_OVR_multiview2 1\n"
+ ;
+ }
+
+ // #line and #include
+ preamble +=
+ "#define GL_GOOGLE_cpp_style_line_directive 1\n"
+ "#define GL_GOOGLE_include_directive 1\n"
+ "#define GL_KHR_blend_equation_advanced 1\n"
+ ;
+#endif
+
+ // #define VULKAN XXXX
+ const int numberBufSize = 12;
+ char numberBuf[numberBufSize];
+ if (spvVersion.vulkanGlsl > 0) {
+ preamble += "#define VULKAN ";
+ snprintf(numberBuf, numberBufSize, "%d", spvVersion.vulkanGlsl);
+ preamble += numberBuf;
+ preamble += "\n";
+ }
+
+#ifndef GLSLANG_WEB
+ // #define GL_SPIRV XXXX
+ if (spvVersion.openGl > 0) {
+ preamble += "#define GL_SPIRV ";
+ snprintf(numberBuf, numberBufSize, "%d", spvVersion.openGl);
+ preamble += numberBuf;
+ preamble += "\n";
+ }
+#endif
+}
+
+//
+// Map from stage enum to externally readable text name.
+//
+const char* StageName(EShLanguage stage)
+{
+ switch(stage) {
+ case EShLangVertex: return "vertex";
+ case EShLangFragment: return "fragment";
+ case EShLangCompute: return "compute";
+#ifndef GLSLANG_WEB
+ case EShLangTessControl: return "tessellation control";
+ case EShLangTessEvaluation: return "tessellation evaluation";
+ case EShLangGeometry: return "geometry";
+ case EShLangRayGenNV: return "ray-generation";
+ case EShLangIntersectNV: return "intersection";
+ case EShLangAnyHitNV: return "any-hit";
+ case EShLangClosestHitNV: return "closest-hit";
+ case EShLangMissNV: return "miss";
+ case EShLangCallableNV: return "callable";
+ case EShLangMeshNV: return "mesh";
+ case EShLangTaskNV: return "task";
+#endif
+ default: return "unknown stage";
+ }
+}
+
+//
+// When to use requireStage()
+//
+// If only some stages support a feature.
+//
+// Operation: If the current stage is not present, give an error message.
+//
+void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguageMask languageMask, const char* featureDesc)
+{
+ if (((1 << language) & languageMask) == 0)
+ error(loc, "not supported in this stage:", featureDesc, StageName(language));
+}
+
+// If only one stage supports a feature, this can be called. But, all supporting stages
+// must be specified with one call.
+void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguage stage, const char* featureDesc)
+{
+ requireStage(loc, static_cast<EShLanguageMask>(1 << stage), featureDesc);
+}
+
+#ifndef GLSLANG_WEB
+//
+// When to use requireProfile():
+//
+// Use if only some profiles support a feature. However, if within a profile the feature
+// is version or extension specific, follow this call with calls to profileRequires().
+//
+// Operation: If the current profile is not one of the profileMask,
+// give an error message.
+//
+void TParseVersions::requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc)
+{
+ if (! (profile & profileMask))
+ error(loc, "not supported with this profile:", featureDesc, ProfileName(profile));
+}
+
+//
+// When to use profileRequires():
+//
+// If a set of profiles have the same requirements for what version or extensions
+// are needed to support a feature.
+//
+// It must be called for each profile that needs protection. Use requireProfile() first
+// to reduce that set of profiles.
+//
+// Operation: Will issue warnings/errors based on the current profile, version, and extension
+// behaviors. It only checks extensions when the current profile is one of the profileMask.
+//
+// A minVersion of 0 means no version of the profileMask support this in core,
+// the extension must be present.
+//
+
+// entry point that takes multiple extensions
+void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions,
+ const char* const extensions[], const char* featureDesc)
+{
+ if (profile & profileMask) {
+ bool okay = minVersion > 0 && version >= minVersion;
+#ifndef GLSLANG_WEB
+ for (int i = 0; i < numExtensions; ++i) {
+ switch (getExtensionBehavior(extensions[i])) {
+ case EBhWarn:
+ infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
+ // fall through
+ case EBhRequire:
+ case EBhEnable:
+ okay = true;
+ break;
+ default: break; // some compilers want this
+ }
+ }
+#endif
+ if (! okay)
+ error(loc, "not supported for this version or the enabled extensions", featureDesc, "");
+ }
+}
+
+// entry point for the above that takes a single extension
+void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension,
+ const char* featureDesc)
+{
+ profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc);
+}
+
+void TParseVersions::unimplemented(const TSourceLoc& loc, const char* featureDesc)
+{
+ error(loc, "feature not yet implemented", featureDesc, "");
+}
+
+//
+// Within a set of profiles, see if a feature is deprecated and give an error or warning based on whether
+// a future compatibility context is being use.
+//
+void TParseVersions::checkDeprecated(const TSourceLoc& loc, int profileMask, int depVersion, const char* featureDesc)
+{
+ if (profile & profileMask) {
+ if (version >= depVersion) {
+ if (forwardCompatible)
+ error(loc, "deprecated, may be removed in future release", featureDesc, "");
+ else if (! suppressWarnings())
+ infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " +
+ String(depVersion) + "; may be removed in future release").c_str(), loc);
+ }
+ }
+}
+
+//
+// Within a set of profiles, see if a feature has now been removed and if so, give an error.
+// The version argument is the first version no longer having the feature.
+//
+void TParseVersions::requireNotRemoved(const TSourceLoc& loc, int profileMask, int removedVersion, const char* featureDesc)
+{
+ if (profile & profileMask) {
+ if (version >= removedVersion) {
+ const int maxSize = 60;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%s profile; removed in version %d", ProfileName(profile), removedVersion);
+ error(loc, "no longer supported in", featureDesc, buf);
+ }
+ }
+}
+
+// Returns true if at least one of the extensions in the extensions parameter is requested. Otherwise, returns false.
+// Warns appropriately if the requested behavior of an extension is "warn".
+bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
+{
+ // First, see if any of the extensions are enabled
+ for (int i = 0; i < numExtensions; ++i) {
+ TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
+ if (behavior == EBhEnable || behavior == EBhRequire)
+ return true;
+ }
+
+ // See if any extensions want to give a warning on use; give warnings for all such extensions
+ bool warned = false;
+ for (int i = 0; i < numExtensions; ++i) {
+ TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
+ if (behavior == EBhDisable && relaxedErrors()) {
+ infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc);
+ behavior = EBhWarn;
+ }
+ if (behavior == EBhWarn) {
+ infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
+ warned = true;
+ }
+ }
+ if (warned)
+ return true;
+ return false;
+}
+
+//
+// Use when there are no profile/version to check, it's just an error if one of the
+// extensions is not present.
+//
+void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
+{
+ if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
+ return;
+
+ // If we get this far, give errors explaining what extensions are needed
+ if (numExtensions == 1)
+ error(loc, "required extension not requested:", featureDesc, extensions[0]);
+ else {
+ error(loc, "required extension not requested:", featureDesc, "Possible extensions include:");
+ for (int i = 0; i < numExtensions; ++i)
+ infoSink.info.message(EPrefixNone, extensions[i]);
+ }
+}
+
+//
+// Use by preprocessor when there are no profile/version to check, it's just an error if one of the
+// extensions is not present.
+//
+void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
+{
+ if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
+ return;
+
+ // If we get this far, give errors explaining what extensions are needed
+ if (numExtensions == 1)
+ ppError(loc, "required extension not requested:", featureDesc, extensions[0]);
+ else {
+ ppError(loc, "required extension not requested:", featureDesc, "Possible extensions include:");
+ for (int i = 0; i < numExtensions; ++i)
+ infoSink.info.message(EPrefixNone, extensions[i]);
+ }
+}
+
+TExtensionBehavior TParseVersions::getExtensionBehavior(const char* extension)
+{
+ auto iter = extensionBehavior.find(TString(extension));
+ if (iter == extensionBehavior.end())
+ return EBhMissing;
+ else
+ return iter->second;
+}
+
+// Returns true if the given extension is set to enable, require, or warn.
+bool TParseVersions::extensionTurnedOn(const char* const extension)
+{
+ switch (getExtensionBehavior(extension)) {
+ case EBhEnable:
+ case EBhRequire:
+ case EBhWarn:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+// See if any of the extensions are set to enable, require, or warn.
+bool TParseVersions::extensionsTurnedOn(int numExtensions, const char* const extensions[])
+{
+ for (int i = 0; i < numExtensions; ++i) {
+ if (extensionTurnedOn(extensions[i]))
+ return true;
+ }
+ return false;
+}
+
+//
+// Change the current state of an extension's behavior.
+//
+void TParseVersions::updateExtensionBehavior(int line, const char* extension, const char* behaviorString)
+{
+ // Translate from text string of extension's behavior to an enum.
+ TExtensionBehavior behavior = EBhDisable;
+ if (! strcmp("require", behaviorString))
+ behavior = EBhRequire;
+ else if (! strcmp("enable", behaviorString))
+ behavior = EBhEnable;
+ else if (! strcmp("disable", behaviorString))
+ behavior = EBhDisable;
+ else if (! strcmp("warn", behaviorString))
+ behavior = EBhWarn;
+ else {
+ error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString);
+ return;
+ }
+
+ // check if extension is used with correct shader stage
+ checkExtensionStage(getCurrentLoc(), extension);
+
+ // update the requested extension
+ updateExtensionBehavior(extension, behavior);
+
+ // see if need to propagate to implicitly modified things
+ if (strcmp(extension, "GL_ANDROID_extension_pack_es31a") == 0) {
+ // to everything in AEP
+ updateExtensionBehavior(line, "GL_KHR_blend_equation_advanced", behaviorString);
+ updateExtensionBehavior(line, "GL_OES_sample_variables", behaviorString);
+ updateExtensionBehavior(line, "GL_OES_shader_image_atomic", behaviorString);
+ updateExtensionBehavior(line, "GL_OES_shader_multisample_interpolation", behaviorString);
+ updateExtensionBehavior(line, "GL_OES_texture_storage_multisample_2d_array", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_geometry_shader", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_gpu_shader5", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_primitive_bounding_box", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_tessellation_shader", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_texture_buffer", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_texture_cube_map_array", behaviorString);
+ }
+ // geometry to io_blocks
+ else if (strcmp(extension, "GL_EXT_geometry_shader") == 0)
+ updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
+ else if (strcmp(extension, "GL_OES_geometry_shader") == 0)
+ updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString);
+ // tessellation to io_blocks
+ else if (strcmp(extension, "GL_EXT_tessellation_shader") == 0)
+ updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
+ else if (strcmp(extension, "GL_OES_tessellation_shader") == 0)
+ updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString);
+ else if (strcmp(extension, "GL_GOOGLE_include_directive") == 0)
+ updateExtensionBehavior(line, "GL_GOOGLE_cpp_style_line_directive", behaviorString);
+ // subgroup_* to subgroup_basic
+ else if (strcmp(extension, "GL_KHR_shader_subgroup_vote") == 0)
+ updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+ else if (strcmp(extension, "GL_KHR_shader_subgroup_arithmetic") == 0)
+ updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+ else if (strcmp(extension, "GL_KHR_shader_subgroup_ballot") == 0)
+ updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+ else if (strcmp(extension, "GL_KHR_shader_subgroup_shuffle") == 0)
+ updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+ else if (strcmp(extension, "GL_KHR_shader_subgroup_shuffle_relative") == 0)
+ updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+ else if (strcmp(extension, "GL_KHR_shader_subgroup_clustered") == 0)
+ updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+ else if (strcmp(extension, "GL_KHR_shader_subgroup_quad") == 0)
+ updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+ else if (strcmp(extension, "GL_NV_shader_subgroup_partitioned") == 0)
+ updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString);
+ else if (strcmp(extension, "GL_EXT_buffer_reference2") == 0 ||
+ strcmp(extension, "GL_EXT_buffer_reference_uvec2") == 0)
+ updateExtensionBehavior(line, "GL_EXT_buffer_reference", behaviorString);
+ else if (strcmp(extension, "GL_NV_integer_cooperative_matrix") == 0)
+ updateExtensionBehavior(line, "GL_NV_cooperative_matrix", behaviorString);
+ // subgroup extended types to explicit types
+ else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_int8") == 0)
+ updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int8", behaviorString);
+ else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_int16") == 0)
+ updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int16", behaviorString);
+ else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_int64") == 0)
+ updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int64", behaviorString);
+ else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_float16") == 0)
+ updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_float16", behaviorString);
+}
+
+void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
+{
+ // Update the current behavior
+ if (strcmp(extension, "all") == 0) {
+ // special case for the 'all' extension; apply it to every extension present
+ if (behavior == EBhRequire || behavior == EBhEnable) {
+ error(getCurrentLoc(), "extension 'all' cannot have 'require' or 'enable' behavior", "#extension", "");
+ return;
+ } else {
+ for (auto iter = extensionBehavior.begin(); iter != extensionBehavior.end(); ++iter)
+ iter->second = behavior;
+ }
+ } else {
+ // Do the update for this single extension
+ auto iter = extensionBehavior.find(TString(extension));
+ if (iter == extensionBehavior.end()) {
+ switch (behavior) {
+ case EBhRequire:
+ error(getCurrentLoc(), "extension not supported:", "#extension", extension);
+ break;
+ case EBhEnable:
+ case EBhWarn:
+ case EBhDisable:
+ warn(getCurrentLoc(), "extension not supported:", "#extension", extension);
+ break;
+ default:
+ assert(0 && "unexpected behavior");
+ }
+
+ return;
+ } else {
+ if (iter->second == EBhDisablePartial)
+ warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension);
+ if (behavior == EBhEnable || behavior == EBhRequire)
+ intermediate.addRequestedExtension(extension);
+ iter->second = behavior;
+ }
+ }
+}
+
+// Check if extension is used with correct shader stage.
+void TParseVersions::checkExtensionStage(const TSourceLoc& loc, const char * const extension)
+{
+ // GL_NV_mesh_shader extension is only allowed in task/mesh shaders
+ if (strcmp(extension, "GL_NV_mesh_shader") == 0) {
+ requireStage(loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask | EShLangFragmentMask),
+ "#extension GL_NV_mesh_shader");
+ profileRequires(loc, ECoreProfile, 450, 0, "#extension GL_NV_mesh_shader");
+ profileRequires(loc, EEsProfile, 320, 0, "#extension GL_NV_mesh_shader");
+ }
+}
+
+// Call for any operation needing full GLSL integer data-type support.
+void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
+{
+ profileRequires(loc, ENoProfile, 130, nullptr, op);
+ profileRequires(loc, EEsProfile, 300, nullptr, op);
+}
+
+// Call for any operation needing GLSL double data-type support.
+void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
+{
+ //requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader_fp64, op);
+}
+
+// Call for any operation needing GLSL float16 data-type support.
+void TParseVersions::float16Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (!builtIn) {
+ const char* const extensions[] = {
+ E_GL_AMD_gpu_shader_half_float,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_float16};
+ requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+ }
+}
+
+bool TParseVersions::float16Arithmetic()
+{
+ const char* const extensions[] = {
+ E_GL_AMD_gpu_shader_half_float,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_float16};
+ return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions);
+}
+
+bool TParseVersions::int16Arithmetic()
+{
+ const char* const extensions[] = {
+ E_GL_AMD_gpu_shader_int16,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int16};
+ return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions);
+}
+
+bool TParseVersions::int8Arithmetic()
+{
+ const char* const extensions[] = {
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int8};
+ return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions);
+}
+
+void TParseVersions::requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc)
+{
+ TString combined;
+ combined = op;
+ combined += ": ";
+ combined += featureDesc;
+
+ const char* const extensions[] = {
+ E_GL_AMD_gpu_shader_half_float,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_float16};
+ requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str());
+}
+
+void TParseVersions::requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc)
+{
+ TString combined;
+ combined = op;
+ combined += ": ";
+ combined += featureDesc;
+
+ const char* const extensions[] = {
+ E_GL_AMD_gpu_shader_int16,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int16};
+ requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str());
+}
+
+void TParseVersions::requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc)
+{
+ TString combined;
+ combined = op;
+ combined += ": ";
+ combined += featureDesc;
+
+ const char* const extensions[] = {
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int8};
+ requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str());
+}
+
+void TParseVersions::float16ScalarVectorCheck(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (!builtIn) {
+ const char* const extensions[] = {
+ E_GL_AMD_gpu_shader_half_float,
+ E_GL_EXT_shader_16bit_storage,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_float16};
+ requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+ }
+}
+
+// Call for any operation needing GLSL float32 data-type support.
+void TParseVersions::explicitFloat32Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (!builtIn) {
+ const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_float32};
+ requireExtensions(loc, 2, extensions, op);
+ }
+}
+
+// Call for any operation needing GLSL float64 data-type support.
+void TParseVersions::explicitFloat64Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (!builtIn) {
+ const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_float64};
+ requireExtensions(loc, 2, extensions, op);
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op);
+ }
+}
+
+// Call for any operation needing GLSL explicit int8 data-type support.
+void TParseVersions::explicitInt8Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (! builtIn) {
+ const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int8};
+ requireExtensions(loc, 2, extensions, op);
+ }
+}
+
+// Call for any operation needing GLSL float16 opaque-type support
+void TParseVersions::float16OpaqueCheck(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (! builtIn) {
+ requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_half_float_fetch, op);
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op);
+ }
+}
+
+// Call for any operation needing GLSL explicit int16 data-type support.
+void TParseVersions::explicitInt16Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (! builtIn) {
+ const char* const extensions[] = {
+ E_GL_AMD_gpu_shader_int16,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int16};
+ requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+ }
+}
+
+void TParseVersions::int16ScalarVectorCheck(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (! builtIn) {
+ const char* const extensions[] = {
+ E_GL_AMD_gpu_shader_int16,
+ E_GL_EXT_shader_16bit_storage,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int16};
+ requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+ }
+}
+
+void TParseVersions::int8ScalarVectorCheck(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (! builtIn) {
+ const char* const extensions[] = {
+ E_GL_EXT_shader_8bit_storage,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int8};
+ requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+ }
+}
+
+// Call for any operation needing GLSL explicit int32 data-type support.
+void TParseVersions::explicitInt32Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (! builtIn) {
+ const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int32};
+ requireExtensions(loc, 2, extensions, op);
+ }
+}
+
+// Call for any operation needing GLSL 64-bit integer data-type support.
+void TParseVersions::int64Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (! builtIn) {
+ const char* const extensions[3] = {E_GL_ARB_gpu_shader_int64,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int64};
+ requireExtensions(loc, 3, extensions, op);
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op);
+ }
+}
+
+void TParseVersions::fcoopmatCheck(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (!builtIn) {
+ const char* const extensions[] = {E_GL_NV_cooperative_matrix};
+ requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+ }
+}
+
+void TParseVersions::intcoopmatCheck(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (!builtIn) {
+ const char* const extensions[] = {E_GL_NV_integer_cooperative_matrix};
+ requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
+ }
+}
+#endif // GLSLANG_WEB
+// Call for any operation removed because SPIR-V is in use.
+void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
+{
+ if (spvVersion.spv != 0)
+ error(loc, "not allowed when generating SPIR-V", op, "");
+}
+
+// Call for any operation removed because Vulkan SPIR-V is being generated.
+void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
+{
+ if (spvVersion.vulkan > 0)
+ error(loc, "not allowed when using GLSL for Vulkan", op, "");
+}
+
+// Call for any operation that requires Vulkan.
+void TParseVersions::requireVulkan(const TSourceLoc& loc, const char* op)
+{
+#ifndef GLSLANG_WEB
+ if (spvVersion.vulkan == 0)
+ error(loc, "only allowed when using GLSL for Vulkan", op, "");
+#endif
+}
+
+// Call for any operation that requires SPIR-V.
+void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op)
+{
+#ifndef GLSLANG_WEB
+ if (spvVersion.spv == 0)
+ error(loc, "only allowed when generating SPIR-V", op, "");
+#endif
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/Versions.h b/thirdparty/glslang/glslang/MachineIndependent/Versions.h
new file mode 100644
index 0000000000..58558e595a
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/Versions.h
@@ -0,0 +1,314 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+#ifndef _VERSIONS_INCLUDED_
+#define _VERSIONS_INCLUDED_
+
+//
+// Help manage multiple profiles, versions, extensions etc.
+//
+
+//
+// Profiles are set up for masking operations, so queries can be done on multiple
+// profiles at the same time.
+//
+// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible
+// defects from mixing the two different forms.
+//
+typedef enum {
+ EBadProfile = 0,
+ ENoProfile = (1 << 0), // only for desktop, before profiles showed up
+ ECoreProfile = (1 << 1),
+ ECompatibilityProfile = (1 << 2),
+ EEsProfile = (1 << 3)
+} EProfile;
+
+namespace glslang {
+
+//
+// Map from profile enum to externally readable text name.
+//
+inline const char* ProfileName(EProfile profile)
+{
+ switch (profile) {
+ case ENoProfile: return "none";
+ case ECoreProfile: return "core";
+ case ECompatibilityProfile: return "compatibility";
+ case EEsProfile: return "es";
+ default: return "unknown profile";
+ }
+}
+
+//
+// What source rules, validation rules, target language, etc. are needed or
+// desired for SPIR-V?
+//
+// 0 means a target or rule set is not enabled (ignore rules from that entity).
+// Non-0 means to apply semantic rules arising from that version of its rule set.
+// The union of all requested rule sets will be applied.
+//
+struct SpvVersion {
+ SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {}
+ unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
+ int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
+ int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use
+ int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
+};
+
+//
+// The behaviors from the GLSL "#extension extension_name : behavior"
+//
+typedef enum {
+ EBhMissing = 0,
+ EBhRequire,
+ EBhEnable,
+ EBhWarn,
+ EBhDisable,
+ EBhDisablePartial // use as initial state of an extension that is only partially implemented
+} TExtensionBehavior;
+
+//
+// Symbolic names for extensions. Strings may be directly used when calling the
+// functions, but better to have the compiler do spelling checks.
+//
+const char* const E_GL_OES_texture_3D = "GL_OES_texture_3D";
+const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_derivatives";
+const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth";
+const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external";
+const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3";
+const char* const E_GL_EXT_YUV_target = "GL_EXT_YUV_target";
+const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod";
+const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers";
+
+const char* const E_GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle";
+const char* const E_GL_3DL_array_objects = "GL_3DL_array_objects";
+const char* const E_GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack";
+const char* const E_GL_ARB_texture_gather = "GL_ARB_texture_gather";
+const char* const E_GL_ARB_gpu_shader5 = "GL_ARB_gpu_shader5";
+const char* const E_GL_ARB_separate_shader_objects = "GL_ARB_separate_shader_objects";
+const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader";
+const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader";
+const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts";
+const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array";
+const char* const E_GL_ARB_texture_multisample = "GL_ARB_texture_multisample";
+const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod";
+const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location";
+const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location";
+const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store";
+const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters";
+const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters";
+const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote";
+const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control";
+const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples";
+const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array";
+const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64";
+const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64";
+const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot";
+const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2";
+const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp";
+const char* const E_GL_ARB_shader_stencil_export = "GL_ARB_shader_stencil_export";
+// const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members
+const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_coverage";
+const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array";
+const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock";
+const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock";
+const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object";
+const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading";
+
+const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic";
+const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";
+const char* const E_GL_KHR_shader_subgroup_arithmetic = "GL_KHR_shader_subgroup_arithmetic";
+const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot";
+const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle";
+const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative";
+const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered";
+const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad";
+const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics";
+
+const char* const E_GL_EXT_shader_atomic_int64 = "GL_EXT_shader_atomic_int64";
+
+const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers";
+const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted";
+
+const char* const E_GL_EXT_shader_16bit_storage = "GL_EXT_shader_16bit_storage";
+const char* const E_GL_EXT_shader_8bit_storage = "GL_EXT_shader_8bit_storage";
+
+
+// EXT extensions
+const char* const E_GL_EXT_device_group = "GL_EXT_device_group";
+const char* const E_GL_EXT_multiview = "GL_EXT_multiview";
+const char* const E_GL_EXT_post_depth_coverage = "GL_EXT_post_depth_coverage";
+const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes";
+const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier";
+const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions";
+const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout";
+const char* const E_GL_EXT_fragment_invocation_density = "GL_EXT_fragment_invocation_density";
+const char* const E_GL_EXT_buffer_reference = "GL_EXT_buffer_reference";
+const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_reference2";
+const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2";
+const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation";
+const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock";
+
+// Arrays of extensions for the above viewportEXTs duplications
+
+const char* const post_depth_coverageEXTs[] = { E_GL_ARB_post_depth_coverage, E_GL_EXT_post_depth_coverage };
+const int Num_post_depth_coverageEXTs = sizeof(post_depth_coverageEXTs) / sizeof(post_depth_coverageEXTs[0]);
+
+// OVR extensions
+const char* const E_GL_OVR_multiview = "GL_OVR_multiview";
+const char* const E_GL_OVR_multiview2 = "GL_OVR_multiview2";
+
+const char* const OVR_multiview_EXTs[] = { E_GL_OVR_multiview, E_GL_OVR_multiview2 };
+const int Num_OVR_multiview_EXTs = sizeof(OVR_multiview_EXTs) / sizeof(OVR_multiview_EXTs[0]);
+
+// #line and #include
+const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive";
+const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive";
+
+const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot";
+const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax";
+const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter";
+const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader";
+const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_shader_half_float";
+const char* const E_GL_AMD_texture_gather_bias_lod = "GL_AMD_texture_gather_bias_lod";
+const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_shader_int16";
+const char* const E_GL_AMD_shader_image_load_store_lod = "GL_AMD_shader_image_load_store_lod";
+const char* const E_GL_AMD_shader_fragment_mask = "GL_AMD_shader_fragment_mask";
+const char* const E_GL_AMD_gpu_shader_half_float_fetch = "GL_AMD_gpu_shader_half_float_fetch";
+
+const char* const E_GL_INTEL_shader_integer_functions2 = "GL_INTEL_shader_integer_functions2";
+
+const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage";
+const char* const E_SPV_NV_geometry_shader_passthrough = "GL_NV_geometry_shader_passthrough";
+const char* const E_GL_NV_viewport_array2 = "GL_NV_viewport_array2";
+const char* const E_GL_NV_stereo_view_rendering = "GL_NV_stereo_view_rendering";
+const char* const E_GL_NVX_multiview_per_view_attributes = "GL_NVX_multiview_per_view_attributes";
+const char* const E_GL_NV_shader_atomic_int64 = "GL_NV_shader_atomic_int64";
+const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation";
+const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation";
+const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned";
+const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image";
+const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing";
+const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric";
+const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives";
+const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint";
+const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader";
+
+// Arrays of extensions for the above viewportEXTs duplications
+
+const char* const viewportEXTs[] = { E_GL_ARB_shader_viewport_layer_array, E_GL_NV_viewport_array2 };
+const int Num_viewportEXTs = sizeof(viewportEXTs) / sizeof(viewportEXTs[0]);
+
+const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix";
+const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins";
+const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix";
+
+// AEP
+const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a";
+const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced";
+const char* const E_GL_OES_sample_variables = "GL_OES_sample_variables";
+const char* const E_GL_OES_shader_image_atomic = "GL_OES_shader_image_atomic";
+const char* const E_GL_OES_shader_multisample_interpolation = "GL_OES_shader_multisample_interpolation";
+const char* const E_GL_OES_texture_storage_multisample_2d_array = "GL_OES_texture_storage_multisample_2d_array";
+const char* const E_GL_EXT_geometry_shader = "GL_EXT_geometry_shader";
+const char* const E_GL_EXT_geometry_point_size = "GL_EXT_geometry_point_size";
+const char* const E_GL_EXT_gpu_shader5 = "GL_EXT_gpu_shader5";
+const char* const E_GL_EXT_primitive_bounding_box = "GL_EXT_primitive_bounding_box";
+const char* const E_GL_EXT_shader_io_blocks = "GL_EXT_shader_io_blocks";
+const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessellation_shader";
+const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size";
+const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer";
+const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array";
+
+// OES matching AEP
+const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader";
+const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size";
+const char* const E_GL_OES_gpu_shader5 = "GL_OES_gpu_shader5";
+const char* const E_GL_OES_primitive_bounding_box = "GL_OES_primitive_bounding_box";
+const char* const E_GL_OES_shader_io_blocks = "GL_OES_shader_io_blocks";
+const char* const E_GL_OES_tessellation_shader = "GL_OES_tessellation_shader";
+const char* const E_GL_OES_tessellation_point_size = "GL_OES_tessellation_point_size";
+const char* const E_GL_OES_texture_buffer = "GL_OES_texture_buffer";
+const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array";
+
+// EXT
+const char* const E_GL_EXT_shader_explicit_arithmetic_types = "GL_EXT_shader_explicit_arithmetic_types";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8 = "GL_EXT_shader_explicit_arithmetic_types_int8";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16 = "GL_EXT_shader_explicit_arithmetic_types_int16";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32 = "GL_EXT_shader_explicit_arithmetic_types_int32";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64 = "GL_EXT_shader_explicit_arithmetic_types_int64";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16 = "GL_EXT_shader_explicit_arithmetic_types_float16";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32 = "GL_EXT_shader_explicit_arithmetic_types_float32";
+const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64 = "GL_EXT_shader_explicit_arithmetic_types_float64";
+
+const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shader_subgroup_extended_types_int8";
+const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16";
+const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64";
+const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16";
+
+// Arrays of extensions for the above AEP duplications
+
+const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader };
+const int Num_AEP_geometry_shader = sizeof(AEP_geometry_shader)/sizeof(AEP_geometry_shader[0]);
+
+const char* const AEP_geometry_point_size[] = { E_GL_EXT_geometry_point_size, E_GL_OES_geometry_point_size };
+const int Num_AEP_geometry_point_size = sizeof(AEP_geometry_point_size)/sizeof(AEP_geometry_point_size[0]);
+
+const char* const AEP_gpu_shader5[] = { E_GL_EXT_gpu_shader5, E_GL_OES_gpu_shader5 };
+const int Num_AEP_gpu_shader5 = sizeof(AEP_gpu_shader5)/sizeof(AEP_gpu_shader5[0]);
+
+const char* const AEP_primitive_bounding_box[] = { E_GL_EXT_primitive_bounding_box, E_GL_OES_primitive_bounding_box };
+const int Num_AEP_primitive_bounding_box = sizeof(AEP_primitive_bounding_box)/sizeof(AEP_primitive_bounding_box[0]);
+
+const char* const AEP_shader_io_blocks[] = { E_GL_EXT_shader_io_blocks, E_GL_OES_shader_io_blocks };
+const int Num_AEP_shader_io_blocks = sizeof(AEP_shader_io_blocks)/sizeof(AEP_shader_io_blocks[0]);
+
+const char* const AEP_tessellation_shader[] = { E_GL_EXT_tessellation_shader, E_GL_OES_tessellation_shader };
+const int Num_AEP_tessellation_shader = sizeof(AEP_tessellation_shader)/sizeof(AEP_tessellation_shader[0]);
+
+const char* const AEP_tessellation_point_size[] = { E_GL_EXT_tessellation_point_size, E_GL_OES_tessellation_point_size };
+const int Num_AEP_tessellation_point_size = sizeof(AEP_tessellation_point_size)/sizeof(AEP_tessellation_point_size[0]);
+
+const char* const AEP_texture_buffer[] = { E_GL_EXT_texture_buffer, E_GL_OES_texture_buffer };
+const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture_buffer[0]);
+
+const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array };
+const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]);
+
+} // end namespace glslang
+
+#endif // _VERSIONS_INCLUDED_
diff --git a/thirdparty/glslang/glslang/MachineIndependent/attribute.cpp b/thirdparty/glslang/glslang/MachineIndependent/attribute.cpp
new file mode 100644
index 0000000000..9585518349
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/attribute.cpp
@@ -0,0 +1,346 @@
+//
+// Copyright (C) 2017 LunarG, Inc.
+// Copyright (C) 2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of Google, Inc., nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef GLSLANG_WEB
+
+#include "attribute.h"
+#include "../Include/intermediate.h"
+#include "ParseHelper.h"
+
+namespace glslang {
+
+// extract integers out of attribute arguments stored in attribute aggregate
+bool TAttributeArgs::getInt(int& value, int argNum) const
+{
+ const TConstUnion* intConst = getConstUnion(EbtInt, argNum);
+
+ if (intConst == nullptr)
+ return false;
+
+ value = intConst->getIConst();
+ return true;
+}
+
+
+// extract strings out of attribute arguments stored in attribute aggregate.
+// convert to lower case if converToLower is true (for case-insensitive compare convenience)
+bool TAttributeArgs::getString(TString& value, int argNum, bool convertToLower) const
+{
+ const TConstUnion* stringConst = getConstUnion(EbtString, argNum);
+
+ if (stringConst == nullptr)
+ return false;
+
+ value = *stringConst->getSConst();
+
+ // Convenience.
+ if (convertToLower)
+ std::transform(value.begin(), value.end(), value.begin(), ::tolower);
+
+ return true;
+}
+
+// How many arguments were supplied?
+int TAttributeArgs::size() const
+{
+ return args == nullptr ? 0 : (int)args->getSequence().size();
+}
+
+// Helper to get attribute const union. Returns nullptr on failure.
+const TConstUnion* TAttributeArgs::getConstUnion(TBasicType basicType, int argNum) const
+{
+ if (args == nullptr)
+ return nullptr;
+
+ if (argNum >= (int)args->getSequence().size())
+ return nullptr;
+
+ if (args->getSequence()[argNum]->getAsConstantUnion() == nullptr)
+ return nullptr;
+
+ const TConstUnion* constVal = &args->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0];
+ if (constVal == nullptr || constVal->getType() != basicType)
+ return nullptr;
+
+ return constVal;
+}
+
+// Implementation of TParseContext parts of attributes
+TAttributeType TParseContext::attributeFromName(const TString& name) const
+{
+ if (name == "branch" || name == "dont_flatten")
+ return EatBranch;
+ else if (name == "flatten")
+ return EatFlatten;
+ else if (name == "unroll")
+ return EatUnroll;
+ else if (name == "loop" || name == "dont_unroll")
+ return EatLoop;
+ else if (name == "dependency_infinite")
+ return EatDependencyInfinite;
+ else if (name == "dependency_length")
+ return EatDependencyLength;
+ else if (name == "min_iterations")
+ return EatMinIterations;
+ else if (name == "max_iterations")
+ return EatMaxIterations;
+ else if (name == "iteration_multiple")
+ return EatIterationMultiple;
+ else if (name == "peel_count")
+ return EatPeelCount;
+ else if (name == "partial_count")
+ return EatPartialCount;
+ else
+ return EatNone;
+}
+
+// Make an initial leaf for the grammar from a no-argument attribute
+TAttributes* TParseContext::makeAttributes(const TString& identifier) const
+{
+ TAttributes *attributes = nullptr;
+ attributes = NewPoolObject(attributes);
+ TAttributeArgs args = { attributeFromName(identifier), nullptr };
+ attributes->push_back(args);
+ return attributes;
+}
+
+// Make an initial leaf for the grammar from a one-argument attribute
+TAttributes* TParseContext::makeAttributes(const TString& identifier, TIntermNode* node) const
+{
+ TAttributes *attributes = nullptr;
+ attributes = NewPoolObject(attributes);
+
+ // for now, node is always a simple single expression, but other code expects
+ // a list, so make it so
+ TIntermAggregate* agg = intermediate.makeAggregate(node);
+ TAttributeArgs args = { attributeFromName(identifier), agg };
+ attributes->push_back(args);
+ return attributes;
+}
+
+// Merge two sets of attributes into a single set.
+// The second argument is destructively consumed.
+TAttributes* TParseContext::mergeAttributes(TAttributes* attr1, TAttributes* attr2) const
+{
+ attr1->splice(attr1->end(), *attr2);
+ return attr1;
+}
+
+//
+// Selection attributes
+//
+void TParseContext::handleSelectionAttributes(const TAttributes& attributes, TIntermNode* node)
+{
+ TIntermSelection* selection = node->getAsSelectionNode();
+ if (selection == nullptr)
+ return;
+
+ for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+ if (it->size() > 0) {
+ warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", "");
+ continue;
+ }
+
+ switch (it->name) {
+ case EatFlatten:
+ selection->setFlatten();
+ break;
+ case EatBranch:
+ selection->setDontFlatten();
+ break;
+ default:
+ warn(node->getLoc(), "attribute does not apply to a selection", "", "");
+ break;
+ }
+ }
+}
+
+//
+// Switch attributes
+//
+void TParseContext::handleSwitchAttributes(const TAttributes& attributes, TIntermNode* node)
+{
+ TIntermSwitch* selection = node->getAsSwitchNode();
+ if (selection == nullptr)
+ return;
+
+ for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+ if (it->size() > 0) {
+ warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", "");
+ continue;
+ }
+
+ switch (it->name) {
+ case EatFlatten:
+ selection->setFlatten();
+ break;
+ case EatBranch:
+ selection->setDontFlatten();
+ break;
+ default:
+ warn(node->getLoc(), "attribute does not apply to a switch", "", "");
+ break;
+ }
+ }
+}
+
+//
+// Loop attributes
+//
+void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermNode* node)
+{
+ TIntermLoop* loop = node->getAsLoopNode();
+ if (loop == nullptr) {
+ // the actual loop might be part of a sequence
+ TIntermAggregate* agg = node->getAsAggregate();
+ if (agg == nullptr)
+ return;
+ for (auto it = agg->getSequence().begin(); it != agg->getSequence().end(); ++it) {
+ loop = (*it)->getAsLoopNode();
+ if (loop != nullptr)
+ break;
+ }
+ if (loop == nullptr)
+ return;
+ }
+
+ for (auto it = attributes.begin(); it != attributes.end(); ++it) {
+
+ const auto noArgument = [&](const char* feature) {
+ if (it->size() > 0) {
+ warn(node->getLoc(), "expected no arguments", feature, "");
+ return false;
+ }
+ return true;
+ };
+
+ const auto positiveSignedArgument = [&](const char* feature, int& value) {
+ if (it->size() == 1 && it->getInt(value)) {
+ if (value <= 0) {
+ error(node->getLoc(), "must be positive", feature, "");
+ return false;
+ }
+ } else {
+ warn(node->getLoc(), "expected a single integer argument", feature, "");
+ return false;
+ }
+ return true;
+ };
+
+ const auto unsignedArgument = [&](const char* feature, unsigned int& uiValue) {
+ int value;
+ if (!(it->size() == 1 && it->getInt(value))) {
+ warn(node->getLoc(), "expected a single integer argument", feature, "");
+ return false;
+ }
+ uiValue = (unsigned int)value;
+ return true;
+ };
+
+ const auto positiveUnsignedArgument = [&](const char* feature, unsigned int& uiValue) {
+ int value;
+ if (it->size() == 1 && it->getInt(value)) {
+ if (value == 0) {
+ error(node->getLoc(), "must be greater than or equal to 1", feature, "");
+ return false;
+ }
+ } else {
+ warn(node->getLoc(), "expected a single integer argument", feature, "");
+ return false;
+ }
+ uiValue = (unsigned int)value;
+ return true;
+ };
+
+ const auto spirv14 = [&](const char* feature) {
+ if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4)
+ warn(node->getLoc(), "attribute requires a SPIR-V 1.4 target-env", feature, "");
+ };
+
+ int value = 0;
+ unsigned uiValue = 0;
+ switch (it->name) {
+ case EatUnroll:
+ if (noArgument("unroll"))
+ loop->setUnroll();
+ break;
+ case EatLoop:
+ if (noArgument("dont_unroll"))
+ loop->setDontUnroll();
+ break;
+ case EatDependencyInfinite:
+ if (noArgument("dependency_infinite"))
+ loop->setLoopDependency(TIntermLoop::dependencyInfinite);
+ break;
+ case EatDependencyLength:
+ if (positiveSignedArgument("dependency_length", value))
+ loop->setLoopDependency(value);
+ break;
+ case EatMinIterations:
+ spirv14("min_iterations");
+ if (unsignedArgument("min_iterations", uiValue))
+ loop->setMinIterations(uiValue);
+ break;
+ case EatMaxIterations:
+ spirv14("max_iterations");
+ if (unsignedArgument("max_iterations", uiValue))
+ loop->setMaxIterations(uiValue);
+ break;
+ case EatIterationMultiple:
+ spirv14("iteration_multiple");
+ if (positiveUnsignedArgument("iteration_multiple", uiValue))
+ loop->setIterationMultiple(uiValue);
+ break;
+ case EatPeelCount:
+ spirv14("peel_count");
+ if (unsignedArgument("peel_count", uiValue))
+ loop->setPeelCount(uiValue);
+ break;
+ case EatPartialCount:
+ spirv14("partial_count");
+ if (unsignedArgument("partial_count", uiValue))
+ loop->setPartialCount(uiValue);
+ break;
+ default:
+ warn(node->getLoc(), "attribute does not apply to a loop", "", "");
+ break;
+ }
+ }
+}
+
+} // end namespace glslang
+
+#endif // GLSLANG_WEB
diff --git a/thirdparty/glslang/glslang/MachineIndependent/attribute.h b/thirdparty/glslang/glslang/MachineIndependent/attribute.h
new file mode 100644
index 0000000000..38a943d283
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/attribute.h
@@ -0,0 +1,149 @@
+//
+// Copyright (C) 2017 LunarG, Inc.
+// Copyright (C) 2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _ATTRIBUTE_INCLUDED_
+#define _ATTRIBUTE_INCLUDED_
+
+#include "../Include/Common.h"
+#include "../Include/ConstantUnion.h"
+
+namespace glslang {
+
+ enum TAttributeType {
+ EatNone,
+ EatAllow_uav_condition,
+ EatBranch,
+ EatCall,
+ EatDomain,
+ EatEarlyDepthStencil,
+ EatFastOpt,
+ EatFlatten,
+ EatForceCase,
+ EatInstance,
+ EatMaxTessFactor,
+ EatNumThreads,
+ EatMaxVertexCount,
+ EatOutputControlPoints,
+ EatOutputTopology,
+ EatPartitioning,
+ EatPatchConstantFunc,
+ EatPatchSize,
+ EatUnroll,
+ EatLoop,
+ EatBinding,
+ EatGlobalBinding,
+ EatLocation,
+ EatInputAttachment,
+ EatBuiltIn,
+ EatPushConstant,
+ EatConstantId,
+ EatDependencyInfinite,
+ EatDependencyLength,
+ EatMinIterations,
+ EatMaxIterations,
+ EatIterationMultiple,
+ EatPeelCount,
+ EatPartialCount,
+ EatFormatRgba32f,
+ EatFormatRgba16f,
+ EatFormatR32f,
+ EatFormatRgba8,
+ EatFormatRgba8Snorm,
+ EatFormatRg32f,
+ EatFormatRg16f,
+ EatFormatR11fG11fB10f,
+ EatFormatR16f,
+ EatFormatRgba16,
+ EatFormatRgb10A2,
+ EatFormatRg16,
+ EatFormatRg8,
+ EatFormatR16,
+ EatFormatR8,
+ EatFormatRgba16Snorm,
+ EatFormatRg16Snorm,
+ EatFormatRg8Snorm,
+ EatFormatR16Snorm,
+ EatFormatR8Snorm,
+ EatFormatRgba32i,
+ EatFormatRgba16i,
+ EatFormatRgba8i,
+ EatFormatR32i,
+ EatFormatRg32i,
+ EatFormatRg16i,
+ EatFormatRg8i,
+ EatFormatR16i,
+ EatFormatR8i,
+ EatFormatRgba32ui,
+ EatFormatRgba16ui,
+ EatFormatRgba8ui,
+ EatFormatR32ui,
+ EatFormatRgb10a2ui,
+ EatFormatRg32ui,
+ EatFormatRg16ui,
+ EatFormatRg8ui,
+ EatFormatR16ui,
+ EatFormatR8ui,
+ EatFormatUnknown,
+ EatNonWritable,
+ EatNonReadable
+ };
+
+ class TIntermAggregate;
+
+ struct TAttributeArgs {
+ TAttributeType name;
+ const TIntermAggregate* args;
+
+ // Obtain attribute as integer
+ // Return false if it cannot be obtained
+ bool getInt(int& value, int argNum = 0) const;
+
+ // Obtain attribute as string, with optional to-lower transform
+ // Return false if it cannot be obtained
+ bool getString(TString& value, int argNum = 0, bool convertToLower = true) const;
+
+ // How many arguments were provided to the attribute?
+ int size() const;
+
+ protected:
+ const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const;
+ };
+
+ typedef TList<TAttributeArgs> TAttributes;
+
+} // end namespace glslang
+
+#endif // _ATTRIBUTE_INCLUDED_
diff --git a/thirdparty/glslang/glslang/MachineIndependent/gl_types.h b/thirdparty/glslang/glslang/MachineIndependent/gl_types.h
new file mode 100644
index 0000000000..b6f613bced
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/gl_types.h
@@ -0,0 +1,210 @@
+/*
+** Copyright (c) 2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#pragma once
+
+#define GL_FLOAT 0x1406
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+
+#define GL_DOUBLE 0x140A
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+
+#define GL_INT 0x1404
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+
+#define GL_INT64_ARB 0x140E
+#define GL_INT64_VEC2_ARB 0x8FE9
+#define GL_INT64_VEC3_ARB 0x8FEA
+#define GL_INT64_VEC4_ARB 0x8FEB
+
+#define GL_UNSIGNED_INT64_ARB 0x140F
+#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5
+#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6
+#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7
+
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+
+// Those constants are borrowed from extension NV_gpu_shader5
+#define GL_FLOAT16_NV 0x8FF8
+#define GL_FLOAT16_VEC2_NV 0x8FF9
+#define GL_FLOAT16_VEC3_NV 0x8FFA
+#define GL_FLOAT16_VEC4_NV 0x8FFB
+
+#define GL_FLOAT16_MAT2_AMD 0x91C5
+#define GL_FLOAT16_MAT3_AMD 0x91C6
+#define GL_FLOAT16_MAT4_AMD 0x91C7
+#define GL_FLOAT16_MAT2x3_AMD 0x91C8
+#define GL_FLOAT16_MAT2x4_AMD 0x91C9
+#define GL_FLOAT16_MAT3x2_AMD 0x91CA
+#define GL_FLOAT16_MAT3x4_AMD 0x91CB
+#define GL_FLOAT16_MAT4x2_AMD 0x91CC
+#define GL_FLOAT16_MAT4x3_AMD 0x91CD
+
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+
+#define GL_FLOAT16_SAMPLER_1D_AMD 0x91CE
+#define GL_FLOAT16_SAMPLER_2D_AMD 0x91CF
+#define GL_FLOAT16_SAMPLER_3D_AMD 0x91D0
+#define GL_FLOAT16_SAMPLER_CUBE_AMD 0x91D1
+#define GL_FLOAT16_SAMPLER_2D_RECT_AMD 0x91D2
+#define GL_FLOAT16_SAMPLER_1D_ARRAY_AMD 0x91D3
+#define GL_FLOAT16_SAMPLER_2D_ARRAY_AMD 0x91D4
+#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD 0x91D5
+#define GL_FLOAT16_SAMPLER_BUFFER_AMD 0x91D6
+#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD 0x91D7
+#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD 0x91D8
+
+#define GL_FLOAT16_SAMPLER_1D_SHADOW_AMD 0x91D9
+#define GL_FLOAT16_SAMPLER_2D_SHADOW_AMD 0x91DA
+#define GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD 0x91DB
+#define GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD 0x91DC
+#define GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD 0x91DD
+#define GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD 0x91DE
+#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD 0x91DF
+
+#define GL_FLOAT16_IMAGE_1D_AMD 0x91E0
+#define GL_FLOAT16_IMAGE_2D_AMD 0x91E1
+#define GL_FLOAT16_IMAGE_3D_AMD 0x91E2
+#define GL_FLOAT16_IMAGE_2D_RECT_AMD 0x91E3
+#define GL_FLOAT16_IMAGE_CUBE_AMD 0x91E4
+#define GL_FLOAT16_IMAGE_1D_ARRAY_AMD 0x91E5
+#define GL_FLOAT16_IMAGE_2D_ARRAY_AMD 0x91E6
+#define GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD 0x91E7
+#define GL_FLOAT16_IMAGE_BUFFER_AMD 0x91E8
+#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD 0x91E9
+#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD 0x91EA
+
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
diff --git a/thirdparty/glslang/glslang/MachineIndependent/glslang.y b/thirdparty/glslang/glslang/MachineIndependent/glslang.y
new file mode 100644
index 0000000000..9f30fdb2ab
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/glslang.y
@@ -0,0 +1,3827 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Do not edit the .y file, only edit the .m4 file.
+// The .y bison file is not a source file, it is a derivative of the .m4 file.
+// The m4 file needs to be processed by m4 to generate the .y bison file.
+//
+// Code sandwiched between a pair:
+//
+// GLSLANG_WEB_EXCLUDE_ON
+// ...
+// ...
+// ...
+// GLSLANG_WEB_EXCLUDE_OFF
+//
+// Will be excluded from the grammar when m4 is executed as:
+//
+// m4 -P -DGLSLANG_WEB
+//
+// It will be included when m4 is executed as:
+//
+// m4 -P
+//
+
+
+
+
+/**
+ * This is bison grammar and productions for parsing all versions of the
+ * GLSL shading languages.
+ */
+%{
+
+/* Based on:
+ANSI C Yacc grammar
+
+In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a
+matching Lex specification) for the April 30, 1985 draft version of the
+ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that
+original, as mentioned in the answer to question 17.25 of the comp.lang.c
+FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar as
+possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "../Public/ShaderLang.h"
+#include "attribute.h"
+
+using namespace glslang;
+
+%}
+
+%define parse.error verbose
+
+%union {
+ struct {
+ glslang::TSourceLoc loc;
+ union {
+ glslang::TString *string;
+ int i;
+ unsigned int u;
+ long long i64;
+ unsigned long long u64;
+ bool b;
+ double d;
+ };
+ glslang::TSymbol* symbol;
+ } lex;
+ struct {
+ glslang::TSourceLoc loc;
+ glslang::TOperator op;
+ union {
+ TIntermNode* intermNode;
+ glslang::TIntermNodePair nodePair;
+ glslang::TIntermTyped* intermTypedNode;
+ glslang::TAttributes* attributes;
+ };
+ union {
+ glslang::TPublicType type;
+ glslang::TFunction* function;
+ glslang::TParameter param;
+ glslang::TTypeLoc typeLine;
+ glslang::TTypeList* typeList;
+ glslang::TArraySizes* arraySizes;
+ glslang::TIdentifierList* identifierList;
+ };
+ glslang::TArraySizes* typeParameters;
+ } interm;
+}
+
+%{
+
+/* windows only pragma */
+#ifdef _MSC_VER
+ #pragma warning(disable : 4065)
+ #pragma warning(disable : 4127)
+ #pragma warning(disable : 4244)
+#endif
+
+#define parseContext (*pParseContext)
+#define yyerror(context, msg) context->parserError(msg)
+
+extern int yylex(YYSTYPE*, TParseContext&);
+
+%}
+
+%parse-param {glslang::TParseContext* pParseContext}
+%lex-param {parseContext}
+%pure-parser // enable thread safety
+%expect 1 // One shift reduce conflict because of if | else
+
+%token <lex> CONST BOOL INT UINT FLOAT
+%token <lex> BVEC2 BVEC3 BVEC4
+%token <lex> IVEC2 IVEC3 IVEC4
+%token <lex> UVEC2 UVEC3 UVEC4
+%token <lex> VEC2 VEC3 VEC4
+%token <lex> MAT2 MAT3 MAT4
+%token <lex> MAT2X2 MAT2X3 MAT2X4
+%token <lex> MAT3X2 MAT3X3 MAT3X4
+%token <lex> MAT4X2 MAT4X3 MAT4X4
+
+// combined image/sampler
+%token <lex> SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER2DSHADOW
+%token <lex> SAMPLERCUBESHADOW SAMPLER2DARRAY
+%token <lex> SAMPLER2DARRAYSHADOW ISAMPLER2D ISAMPLER3D ISAMPLERCUBE
+%token <lex> ISAMPLER2DARRAY USAMPLER2D USAMPLER3D
+%token <lex> USAMPLERCUBE USAMPLER2DARRAY
+
+// separate image/sampler
+%token <lex> SAMPLER SAMPLERSHADOW
+%token <lex> TEXTURE2D TEXTURE3D TEXTURECUBE TEXTURE2DARRAY
+%token <lex> ITEXTURE2D ITEXTURE3D ITEXTURECUBE ITEXTURE2DARRAY
+%token <lex> UTEXTURE2D UTEXTURE3D UTEXTURECUBE UTEXTURE2DARRAY
+
+
+
+%token <lex> ATTRIBUTE VARYING
+%token <lex> FLOAT16_T FLOAT32_T DOUBLE FLOAT64_T
+%token <lex> INT64_T UINT64_T INT32_T UINT32_T INT16_T UINT16_T INT8_T UINT8_T
+%token <lex> I64VEC2 I64VEC3 I64VEC4
+%token <lex> U64VEC2 U64VEC3 U64VEC4
+%token <lex> I32VEC2 I32VEC3 I32VEC4
+%token <lex> U32VEC2 U32VEC3 U32VEC4
+%token <lex> I16VEC2 I16VEC3 I16VEC4
+%token <lex> U16VEC2 U16VEC3 U16VEC4
+%token <lex> I8VEC2 I8VEC3 I8VEC4
+%token <lex> U8VEC2 U8VEC3 U8VEC4
+%token <lex> DVEC2 DVEC3 DVEC4 DMAT2 DMAT3 DMAT4
+%token <lex> F16VEC2 F16VEC3 F16VEC4 F16MAT2 F16MAT3 F16MAT4
+%token <lex> F32VEC2 F32VEC3 F32VEC4 F32MAT2 F32MAT3 F32MAT4
+%token <lex> F64VEC2 F64VEC3 F64VEC4 F64MAT2 F64MAT3 F64MAT4
+%token <lex> DMAT2X2 DMAT2X3 DMAT2X4
+%token <lex> DMAT3X2 DMAT3X3 DMAT3X4
+%token <lex> DMAT4X2 DMAT4X3 DMAT4X4
+%token <lex> F16MAT2X2 F16MAT2X3 F16MAT2X4
+%token <lex> F16MAT3X2 F16MAT3X3 F16MAT3X4
+%token <lex> F16MAT4X2 F16MAT4X3 F16MAT4X4
+%token <lex> F32MAT2X2 F32MAT2X3 F32MAT2X4
+%token <lex> F32MAT3X2 F32MAT3X3 F32MAT3X4
+%token <lex> F32MAT4X2 F32MAT4X3 F32MAT4X4
+%token <lex> F64MAT2X2 F64MAT2X3 F64MAT2X4
+%token <lex> F64MAT3X2 F64MAT3X3 F64MAT3X4
+%token <lex> F64MAT4X2 F64MAT4X3 F64MAT4X4
+%token <lex> ATOMIC_UINT
+%token <lex> ACCSTRUCTNV
+%token <lex> FCOOPMATNV ICOOPMATNV UCOOPMATNV
+
+// combined image/sampler
+%token <lex> SAMPLERCUBEARRAY SAMPLERCUBEARRAYSHADOW
+%token <lex> ISAMPLERCUBEARRAY USAMPLERCUBEARRAY
+%token <lex> SAMPLER1D SAMPLER1DARRAY SAMPLER1DARRAYSHADOW ISAMPLER1D SAMPLER1DSHADOW
+%token <lex> SAMPLER2DRECT SAMPLER2DRECTSHADOW ISAMPLER2DRECT USAMPLER2DRECT
+%token <lex> SAMPLERBUFFER ISAMPLERBUFFER USAMPLERBUFFER
+%token <lex> SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS
+%token <lex> SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY
+%token <lex> SAMPLEREXTERNALOES
+%token <lex> SAMPLEREXTERNAL2DY2YEXT
+%token <lex> ISAMPLER1DARRAY USAMPLER1D USAMPLER1DARRAY
+%token <lex> F16SAMPLER1D F16SAMPLER2D F16SAMPLER3D F16SAMPLER2DRECT F16SAMPLERCUBE
+%token <lex> F16SAMPLER1DARRAY F16SAMPLER2DARRAY F16SAMPLERCUBEARRAY
+%token <lex> F16SAMPLERBUFFER F16SAMPLER2DMS F16SAMPLER2DMSARRAY
+%token <lex> F16SAMPLER1DSHADOW F16SAMPLER2DSHADOW F16SAMPLER1DARRAYSHADOW F16SAMPLER2DARRAYSHADOW
+%token <lex> F16SAMPLER2DRECTSHADOW F16SAMPLERCUBESHADOW F16SAMPLERCUBEARRAYSHADOW
+
+// images
+%token <lex> IMAGE1D IIMAGE1D UIMAGE1D IMAGE2D IIMAGE2D
+%token <lex> UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D
+%token <lex> IMAGE2DRECT IIMAGE2DRECT UIMAGE2DRECT
+%token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE
+%token <lex> IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER
+%token <lex> IMAGE1DARRAY IIMAGE1DARRAY UIMAGE1DARRAY
+%token <lex> IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY
+%token <lex> IMAGECUBEARRAY IIMAGECUBEARRAY UIMAGECUBEARRAY
+%token <lex> IMAGE2DMS IIMAGE2DMS UIMAGE2DMS
+%token <lex> IMAGE2DMSARRAY IIMAGE2DMSARRAY UIMAGE2DMSARRAY
+
+%token <lex> F16IMAGE1D F16IMAGE2D F16IMAGE3D F16IMAGE2DRECT
+%token <lex> F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY
+%token <lex> F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY
+
+// texture without sampler
+%token <lex> TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY
+%token <lex> TEXTURE1D ITEXTURE1D UTEXTURE1D
+%token <lex> TEXTURE1DARRAY ITEXTURE1DARRAY UTEXTURE1DARRAY
+%token <lex> TEXTURE2DRECT ITEXTURE2DRECT UTEXTURE2DRECT
+%token <lex> TEXTUREBUFFER ITEXTUREBUFFER UTEXTUREBUFFER
+%token <lex> TEXTURE2DMS ITEXTURE2DMS UTEXTURE2DMS
+%token <lex> TEXTURE2DMSARRAY ITEXTURE2DMSARRAY UTEXTURE2DMSARRAY
+
+%token <lex> F16TEXTURE1D F16TEXTURE2D F16TEXTURE3D F16TEXTURE2DRECT F16TEXTURECUBE
+%token <lex> F16TEXTURE1DARRAY F16TEXTURE2DARRAY F16TEXTURECUBEARRAY
+%token <lex> F16TEXTUREBUFFER F16TEXTURE2DMS F16TEXTURE2DMSARRAY
+
+// input attachments
+%token <lex> SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS
+%token <lex> F16SUBPASSINPUT F16SUBPASSINPUTMS
+
+
+
+%token <lex> LEFT_OP RIGHT_OP
+%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token <lex> SUB_ASSIGN
+
+%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
+%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
+%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
+
+%token <lex> INVARIANT
+%token <lex> HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
+%token <lex> PACKED RESOURCE SUPERP
+
+%token <lex> FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT
+%token <lex> IDENTIFIER TYPE_NAME
+%token <lex> CENTROID IN OUT INOUT
+%token <lex> STRUCT VOID WHILE
+%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
+%token <lex> UNIFORM SHARED BUFFER
+%token <lex> FLAT SMOOTH LAYOUT
+
+
+%token <lex> DOUBLECONSTANT INT16CONSTANT UINT16CONSTANT FLOAT16CONSTANT INT32CONSTANT UINT32CONSTANT
+%token <lex> INT64CONSTANT UINT64CONSTANT
+%token <lex> SUBROUTINE DEMOTE
+%token <lex> PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV
+%token <lex> PATCH SAMPLE NONUNIFORM
+%token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT
+%token <lex> SUBGROUPCOHERENT NONPRIVATE
+%token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV
+%token <lex> PRECISE
+
+
+%type <interm> assignment_operator unary_operator
+%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
+%type <interm.intermTypedNode> expression integer_expression assignment_expression
+%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
+%type <interm.intermTypedNode> relational_expression equality_expression
+%type <interm.intermTypedNode> conditional_expression constant_expression
+%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
+%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
+%type <interm.intermTypedNode> function_call initializer condition conditionopt
+
+%type <interm.intermNode> translation_unit function_definition
+%type <interm.intermNode> statement simple_statement
+%type <interm.intermNode> statement_list switch_statement_list compound_statement
+%type <interm.intermNode> declaration_statement selection_statement selection_statement_nonattributed expression_statement
+%type <interm.intermNode> switch_statement switch_statement_nonattributed case_label
+%type <interm.intermNode> declaration external_declaration
+%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
+%type <interm.nodePair> selection_rest_statement for_rest_statement
+%type <interm.intermNode> iteration_statement iteration_statement_nonattributed jump_statement statement_no_new_scope statement_scoped
+%type <interm> single_declaration init_declarator_list
+
+%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
+
+%type <interm> array_specifier
+%type <interm.type> invariant_qualifier interpolation_qualifier storage_qualifier precision_qualifier
+%type <interm.type> layout_qualifier layout_qualifier_id_list layout_qualifier_id
+
+%type <interm.typeParameters> type_parameter_specifier
+%type <interm.typeParameters> type_parameter_specifier_opt
+%type <interm.typeParameters> type_parameter_specifier_list
+
+%type <interm.type> type_qualifier fully_specified_type type_specifier
+%type <interm.type> single_type_qualifier
+%type <interm.type> type_specifier_nonarray
+%type <interm.type> struct_specifier
+%type <interm.typeLine> struct_declarator
+%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
+%type <interm> block_structure
+%type <interm.function> function_header function_declarator
+%type <interm.function> function_header_with_parameters
+%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
+%type <interm> function_call_or_method function_identifier function_call_header
+
+%type <interm.identifierList> identifier_list
+
+
+%type <interm.type> precise_qualifier non_uniform_qualifier
+%type <interm.typeList> type_name_list
+%type <interm.attributes> attribute attribute_list single_attribute
+%type <interm.intermNode> demote_statement
+%type <interm.intermTypedNode> initializer_list
+
+
+%start translation_unit
+%%
+
+variable_identifier
+ : IDENTIFIER {
+ $$ = parseContext.handleVariable($1.loc, $1.symbol, $1.string);
+ }
+ ;
+
+primary_expression
+ : variable_identifier {
+ $$ = $1;
+ }
+ | LEFT_PAREN expression RIGHT_PAREN {
+ $$ = $2;
+ if ($$->getAsConstantUnion())
+ $$->getAsConstantUnion()->setExpression();
+ }
+ | FLOATCONSTANT {
+ $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true);
+ }
+ | INTCONSTANT {
+ $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
+ }
+ | UINTCONSTANT {
+ parseContext.fullIntegerCheck($1.loc, "unsigned literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true);
+ }
+ | BOOLCONSTANT {
+ $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
+ }
+
+ | INT32CONSTANT {
+ parseContext.explicitInt32Check($1.loc, "32-bit signed literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
+ }
+ | UINT32CONSTANT {
+ parseContext.explicitInt32Check($1.loc, "32-bit signed literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true);
+ }
+ | INT64CONSTANT {
+ parseContext.int64Check($1.loc, "64-bit integer literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.i64, $1.loc, true);
+ }
+ | UINT64CONSTANT {
+ parseContext.int64Check($1.loc, "64-bit unsigned integer literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.u64, $1.loc, true);
+ }
+ | INT16CONSTANT {
+ parseContext.explicitInt16Check($1.loc, "16-bit integer literal");
+ $$ = parseContext.intermediate.addConstantUnion((short)$1.i, $1.loc, true);
+ }
+ | UINT16CONSTANT {
+ parseContext.explicitInt16Check($1.loc, "16-bit unsigned integer literal");
+ $$ = parseContext.intermediate.addConstantUnion((unsigned short)$1.u, $1.loc, true);
+ }
+ | DOUBLECONSTANT {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double literal");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.d, EbtDouble, $1.loc, true);
+ }
+ | FLOAT16CONSTANT {
+ parseContext.float16Check($1.loc, "half float literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat16, $1.loc, true);
+ }
+
+ ;
+
+postfix_expression
+ : primary_expression {
+ $$ = $1;
+ }
+ | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
+ $$ = parseContext.handleBracketDereference($2.loc, $1, $3);
+ }
+ | function_call {
+ $$ = $1;
+ }
+ | postfix_expression DOT IDENTIFIER {
+ $$ = parseContext.handleDotDereference($3.loc, $1, *$3.string);
+ }
+ | postfix_expression INC_OP {
+ parseContext.variableCheck($1);
+ parseContext.lValueErrorCheck($2.loc, "++", $1);
+ $$ = parseContext.handleUnaryMath($2.loc, "++", EOpPostIncrement, $1);
+ }
+ | postfix_expression DEC_OP {
+ parseContext.variableCheck($1);
+ parseContext.lValueErrorCheck($2.loc, "--", $1);
+ $$ = parseContext.handleUnaryMath($2.loc, "--", EOpPostDecrement, $1);
+ }
+ ;
+
+integer_expression
+ : expression {
+ parseContext.integerCheck($1, "[]");
+ $$ = $1;
+ }
+ ;
+
+function_call
+ : function_call_or_method {
+ $$ = parseContext.handleFunctionCall($1.loc, $1.function, $1.intermNode);
+ delete $1.function;
+ }
+ ;
+
+function_call_or_method
+ : function_call_generic {
+ $$ = $1;
+ }
+ ;
+
+function_call_generic
+ : function_call_header_with_parameters RIGHT_PAREN {
+ $$ = $1;
+ $$.loc = $2.loc;
+ }
+ | function_call_header_no_parameters RIGHT_PAREN {
+ $$ = $1;
+ $$.loc = $2.loc;
+ }
+ ;
+
+function_call_header_no_parameters
+ : function_call_header VOID {
+ $$ = $1;
+ }
+ | function_call_header {
+ $$ = $1;
+ }
+ ;
+
+function_call_header_with_parameters
+ : function_call_header assignment_expression {
+ TParameter param = { 0, new TType };
+ param.type->shallowCopy($2->getType());
+ $1.function->addParameter(param);
+ $$.function = $1.function;
+ $$.intermNode = $2;
+ }
+ | function_call_header_with_parameters COMMA assignment_expression {
+ TParameter param = { 0, new TType };
+ param.type->shallowCopy($3->getType());
+ $1.function->addParameter(param);
+ $$.function = $1.function;
+ $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, $3, $2.loc);
+ }
+ ;
+
+function_call_header
+ : function_identifier LEFT_PAREN {
+ $$ = $1;
+ }
+ ;
+
+// Grammar Note: Constructors look like functions, but are recognized as types.
+
+function_identifier
+ : type_specifier {
+ // Constructor
+ $$.intermNode = 0;
+ $$.function = parseContext.handleConstructorCall($1.loc, $1);
+ }
+ | postfix_expression {
+ //
+ // Should be a method or subroutine call, but we haven't recognized the arguments yet.
+ //
+ $$.function = 0;
+ $$.intermNode = 0;
+
+ TIntermMethod* method = $1->getAsMethodNode();
+ if (method) {
+ $$.function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength);
+ $$.intermNode = method->getObject();
+ } else {
+ TIntermSymbol* symbol = $1->getAsSymbolNode();
+ if (symbol) {
+ parseContext.reservedErrorCheck(symbol->getLoc(), symbol->getName());
+ TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid));
+ $$.function = function;
+ } else
+ parseContext.error($1->getLoc(), "function call, method, or subroutine call expected", "", "");
+ }
+
+ if ($$.function == 0) {
+ // error recover
+ TString* empty = NewPoolTString("");
+ $$.function = new TFunction(empty, TType(EbtVoid), EOpNull);
+ }
+ }
+
+ | non_uniform_qualifier {
+ // Constructor
+ $$.intermNode = 0;
+ $$.function = parseContext.handleConstructorCall($1.loc, $1);
+ }
+
+ ;
+
+unary_expression
+ : postfix_expression {
+ parseContext.variableCheck($1);
+ $$ = $1;
+ if (TIntermMethod* method = $1->getAsMethodNode())
+ parseContext.error($1->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), "");
+ }
+ | INC_OP unary_expression {
+ parseContext.lValueErrorCheck($1.loc, "++", $2);
+ $$ = parseContext.handleUnaryMath($1.loc, "++", EOpPreIncrement, $2);
+ }
+ | DEC_OP unary_expression {
+ parseContext.lValueErrorCheck($1.loc, "--", $2);
+ $$ = parseContext.handleUnaryMath($1.loc, "--", EOpPreDecrement, $2);
+ }
+ | unary_operator unary_expression {
+ if ($1.op != EOpNull) {
+ char errorOp[2] = {0, 0};
+ switch($1.op) {
+ case EOpNegative: errorOp[0] = '-'; break;
+ case EOpLogicalNot: errorOp[0] = '!'; break;
+ case EOpBitwiseNot: errorOp[0] = '~'; break;
+ default: break; // some compilers want this
+ }
+ $$ = parseContext.handleUnaryMath($1.loc, errorOp, $1.op, $2);
+ } else {
+ $$ = $2;
+ if ($$->getAsConstantUnion())
+ $$->getAsConstantUnion()->setExpression();
+ }
+ }
+ ;
+// Grammar Note: No traditional style type casts.
+
+unary_operator
+ : PLUS { $$.loc = $1.loc; $$.op = EOpNull; }
+ | DASH { $$.loc = $1.loc; $$.op = EOpNegative; }
+ | BANG { $$.loc = $1.loc; $$.op = EOpLogicalNot; }
+ | TILDE { $$.loc = $1.loc; $$.op = EOpBitwiseNot;
+ parseContext.fullIntegerCheck($1.loc, "bitwise not"); }
+ ;
+// Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
+
+multiplicative_expression
+ : unary_expression { $$ = $1; }
+ | multiplicative_expression STAR unary_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "*", EOpMul, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ | multiplicative_expression SLASH unary_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "/", EOpDiv, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ | multiplicative_expression PERCENT unary_expression {
+ parseContext.fullIntegerCheck($2.loc, "%");
+ $$ = parseContext.handleBinaryMath($2.loc, "%", EOpMod, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+additive_expression
+ : multiplicative_expression { $$ = $1; }
+ | additive_expression PLUS multiplicative_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "+", EOpAdd, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ | additive_expression DASH multiplicative_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "-", EOpSub, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+shift_expression
+ : additive_expression { $$ = $1; }
+ | shift_expression LEFT_OP additive_expression {
+ parseContext.fullIntegerCheck($2.loc, "bit shift left");
+ $$ = parseContext.handleBinaryMath($2.loc, "<<", EOpLeftShift, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ | shift_expression RIGHT_OP additive_expression {
+ parseContext.fullIntegerCheck($2.loc, "bit shift right");
+ $$ = parseContext.handleBinaryMath($2.loc, ">>", EOpRightShift, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+relational_expression
+ : shift_expression { $$ = $1; }
+ | relational_expression LEFT_ANGLE shift_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "<", EOpLessThan, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ | relational_expression RIGHT_ANGLE shift_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, ">", EOpGreaterThan, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ | relational_expression LE_OP shift_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "<=", EOpLessThanEqual, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ | relational_expression GE_OP shift_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, ">=", EOpGreaterThanEqual, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ ;
+
+equality_expression
+ : relational_expression { $$ = $1; }
+ | equality_expression EQ_OP relational_expression {
+ parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
+ parseContext.opaqueCheck($2.loc, $1->getType(), "==");
+ parseContext.specializationCheck($2.loc, $1->getType(), "==");
+ parseContext.referenceCheck($2.loc, $1->getType(), "==");
+ $$ = parseContext.handleBinaryMath($2.loc, "==", EOpEqual, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ | equality_expression NE_OP relational_expression {
+ parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
+ parseContext.opaqueCheck($2.loc, $1->getType(), "!=");
+ parseContext.specializationCheck($2.loc, $1->getType(), "!=");
+ parseContext.referenceCheck($2.loc, $1->getType(), "!=");
+ $$ = parseContext.handleBinaryMath($2.loc, "!=", EOpNotEqual, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ ;
+
+and_expression
+ : equality_expression { $$ = $1; }
+ | and_expression AMPERSAND equality_expression {
+ parseContext.fullIntegerCheck($2.loc, "bitwise and");
+ $$ = parseContext.handleBinaryMath($2.loc, "&", EOpAnd, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+exclusive_or_expression
+ : and_expression { $$ = $1; }
+ | exclusive_or_expression CARET and_expression {
+ parseContext.fullIntegerCheck($2.loc, "bitwise exclusive or");
+ $$ = parseContext.handleBinaryMath($2.loc, "^", EOpExclusiveOr, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+inclusive_or_expression
+ : exclusive_or_expression { $$ = $1; }
+ | inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
+ parseContext.fullIntegerCheck($2.loc, "bitwise inclusive or");
+ $$ = parseContext.handleBinaryMath($2.loc, "|", EOpInclusiveOr, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+logical_and_expression
+ : inclusive_or_expression { $$ = $1; }
+ | logical_and_expression AND_OP inclusive_or_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "&&", EOpLogicalAnd, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ ;
+
+logical_xor_expression
+ : logical_and_expression { $$ = $1; }
+ | logical_xor_expression XOR_OP logical_and_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "^^", EOpLogicalXor, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ ;
+
+logical_or_expression
+ : logical_xor_expression { $$ = $1; }
+ | logical_or_expression OR_OP logical_xor_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "||", EOpLogicalOr, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ ;
+
+conditional_expression
+ : logical_or_expression { $$ = $1; }
+ | logical_or_expression QUESTION {
+ ++parseContext.controlFlowNestingLevel;
+ }
+ expression COLON assignment_expression {
+ --parseContext.controlFlowNestingLevel;
+ parseContext.boolCheck($2.loc, $1);
+ parseContext.rValueErrorCheck($2.loc, "?", $1);
+ parseContext.rValueErrorCheck($5.loc, ":", $4);
+ parseContext.rValueErrorCheck($5.loc, ":", $6);
+ $$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(), $6->getCompleteString());
+ $$ = $6;
+ }
+ }
+ ;
+
+assignment_expression
+ : conditional_expression { $$ = $1; }
+ | unary_expression assignment_operator assignment_expression {
+ parseContext.arrayObjectCheck($2.loc, $1->getType(), "array assignment");
+ parseContext.opaqueCheck($2.loc, $1->getType(), "=");
+ parseContext.storage16BitAssignmentCheck($2.loc, $1->getType(), "=");
+ parseContext.specializationCheck($2.loc, $1->getType(), "=");
+ parseContext.lValueErrorCheck($2.loc, "assign", $1);
+ parseContext.rValueErrorCheck($2.loc, "assign", $3);
+ $$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc);
+ if ($$ == 0) {
+ parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString());
+ $$ = $1;
+ }
+ }
+ ;
+
+assignment_operator
+ : EQUAL {
+ $$.loc = $1.loc;
+ $$.op = EOpAssign;
+ }
+ | MUL_ASSIGN {
+ $$.loc = $1.loc;
+ $$.op = EOpMulAssign;
+ }
+ | DIV_ASSIGN {
+ $$.loc = $1.loc;
+ $$.op = EOpDivAssign;
+ }
+ | MOD_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "%=");
+ $$.loc = $1.loc;
+ $$.op = EOpModAssign;
+ }
+ | ADD_ASSIGN {
+ $$.loc = $1.loc;
+ $$.op = EOpAddAssign;
+ }
+ | SUB_ASSIGN {
+ $$.loc = $1.loc;
+ $$.op = EOpSubAssign;
+ }
+ | LEFT_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "bit-shift left assign");
+ $$.loc = $1.loc; $$.op = EOpLeftShiftAssign;
+ }
+ | RIGHT_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "bit-shift right assign");
+ $$.loc = $1.loc; $$.op = EOpRightShiftAssign;
+ }
+ | AND_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "bitwise-and assign");
+ $$.loc = $1.loc; $$.op = EOpAndAssign;
+ }
+ | XOR_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "bitwise-xor assign");
+ $$.loc = $1.loc; $$.op = EOpExclusiveOrAssign;
+ }
+ | OR_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "bitwise-or assign");
+ $$.loc = $1.loc; $$.op = EOpInclusiveOrAssign;
+ }
+ ;
+
+expression
+ : assignment_expression {
+ $$ = $1;
+ }
+ | expression COMMA assignment_expression {
+ parseContext.samplerConstructorLocationCheck($2.loc, ",", $3);
+ $$ = parseContext.intermediate.addComma($1, $3, $2.loc);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(), $3->getCompleteString());
+ $$ = $3;
+ }
+ }
+ ;
+
+constant_expression
+ : conditional_expression {
+ parseContext.constantValueCheck($1, "");
+ $$ = $1;
+ }
+ ;
+
+declaration
+ : function_prototype SEMICOLON {
+ parseContext.handleFunctionDeclarator($1.loc, *$1.function, true /* prototype */);
+ $$ = 0;
+ // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
+ }
+ | init_declarator_list SEMICOLON {
+ if ($1.intermNode && $1.intermNode->getAsAggregate())
+ $1.intermNode->getAsAggregate()->setOperator(EOpSequence);
+ $$ = $1.intermNode;
+ }
+ | PRECISION precision_qualifier type_specifier SEMICOLON {
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "precision statement");
+ // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope
+ parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]);
+ parseContext.setDefaultPrecision($1.loc, $3, $2.qualifier.precision);
+ $$ = 0;
+ }
+ | block_structure SEMICOLON {
+ parseContext.declareBlock($1.loc, *$1.typeList);
+ $$ = 0;
+ }
+ | block_structure IDENTIFIER SEMICOLON {
+ parseContext.declareBlock($1.loc, *$1.typeList, $2.string);
+ $$ = 0;
+ }
+ | block_structure IDENTIFIER array_specifier SEMICOLON {
+ parseContext.declareBlock($1.loc, *$1.typeList, $2.string, $3.arraySizes);
+ $$ = 0;
+ }
+ | type_qualifier SEMICOLON {
+ parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
+ parseContext.updateStandaloneQualifierDefaults($1.loc, $1);
+ $$ = 0;
+ }
+ | type_qualifier IDENTIFIER SEMICOLON {
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$2.string);
+ $$ = 0;
+ }
+ | type_qualifier IDENTIFIER identifier_list SEMICOLON {
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ $3->push_back($2.string);
+ parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$3);
+ $$ = 0;
+ }
+ ;
+
+block_structure
+ : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
+ --parseContext.structNestingLevel;
+ parseContext.blockName = $2.string;
+ parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ parseContext.currentBlockQualifier = $1.qualifier;
+ $$.loc = $1.loc;
+ $$.typeList = $5;
+ }
+
+identifier_list
+ : COMMA IDENTIFIER {
+ $$ = new TIdentifierList;
+ $$->push_back($2.string);
+ }
+ | identifier_list COMMA IDENTIFIER {
+ $$ = $1;
+ $$->push_back($3.string);
+ }
+ ;
+
+function_prototype
+ : function_declarator RIGHT_PAREN {
+ $$.function = $1;
+ $$.loc = $2.loc;
+ }
+ ;
+
+function_declarator
+ : function_header {
+ $$ = $1;
+ }
+ | function_header_with_parameters {
+ $$ = $1;
+ }
+ ;
+
+
+function_header_with_parameters
+ : function_header parameter_declaration {
+ // Add the parameter
+ $$ = $1;
+ if ($2.param.type->getBasicType() != EbtVoid)
+ $1->addParameter($2.param);
+ else
+ delete $2.param.type;
+ }
+ | function_header_with_parameters COMMA parameter_declaration {
+ //
+ // Only first parameter of one-parameter functions can be void
+ // The check for named parameters not being void is done in parameter_declarator
+ //
+ if ($3.param.type->getBasicType() == EbtVoid) {
+ //
+ // This parameter > first is void
+ //
+ parseContext.error($2.loc, "cannot be an argument type except for '(void)'", "void", "");
+ delete $3.param.type;
+ } else {
+ // Add the parameter
+ $$ = $1;
+ $1->addParameter($3.param);
+ }
+ }
+ ;
+
+function_header
+ : fully_specified_type IDENTIFIER LEFT_PAREN {
+ if ($1.qualifier.storage != EvqGlobal && $1.qualifier.storage != EvqTemporary) {
+ parseContext.error($2.loc, "no qualifiers allowed for function return",
+ GetStorageQualifierString($1.qualifier.storage), "");
+ }
+ if ($1.arraySizes)
+ parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes);
+
+ // Add the function as a prototype after parsing it (we do not support recursion)
+ TFunction *function;
+ TType type($1);
+
+ // Potentially rename shader entry point function. No-op most of the time.
+ parseContext.renameShaderFunction($2.string);
+
+ // Make the function
+ function = new TFunction($2.string, type);
+ $$ = function;
+ }
+ ;
+
+parameter_declarator
+ // Type + name
+ : type_specifier IDENTIFIER {
+ if ($1.arraySizes) {
+ parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
+ parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes);
+ }
+ if ($1.basicType == EbtVoid) {
+ parseContext.error($2.loc, "illegal use of type 'void'", $2.string->c_str(), "");
+ }
+ parseContext.reservedErrorCheck($2.loc, *$2.string);
+
+ TParameter param = {$2.string, new TType($1)};
+ $$.loc = $2.loc;
+ $$.param = param;
+ }
+ | type_specifier IDENTIFIER array_specifier {
+ if ($1.arraySizes) {
+ parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
+ parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes);
+ }
+ TType* type = new TType($1);
+ type->transferArraySizes($3.arraySizes);
+ type->copyArrayInnerSizes($1.arraySizes);
+
+ parseContext.arrayOfArrayVersionCheck($2.loc, type->getArraySizes());
+ parseContext.arraySizeRequiredCheck($3.loc, *$3.arraySizes);
+ parseContext.reservedErrorCheck($2.loc, *$2.string);
+
+ TParameter param = { $2.string, type };
+
+ $$.loc = $2.loc;
+ $$.param = param;
+ }
+ ;
+
+parameter_declaration
+ //
+ // With name
+ //
+ : type_qualifier parameter_declarator {
+ $$ = $2;
+ if ($1.qualifier.precision != EpqNone)
+ $$.param.type->getQualifier().precision = $1.qualifier.precision;
+ parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier());
+
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ parseContext.parameterTypeCheck($2.loc, $1.qualifier.storage, *$$.param.type);
+ parseContext.paramCheckFix($1.loc, $1.qualifier, *$$.param.type);
+
+ }
+ | parameter_declarator {
+ $$ = $1;
+
+ parseContext.parameterTypeCheck($1.loc, EvqIn, *$1.param.type);
+ parseContext.paramCheckFixStorage($1.loc, EvqTemporary, *$$.param.type);
+ parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier());
+ }
+ //
+ // Without name
+ //
+ | type_qualifier parameter_type_specifier {
+ $$ = $2;
+ if ($1.qualifier.precision != EpqNone)
+ $$.param.type->getQualifier().precision = $1.qualifier.precision;
+ parseContext.precisionQualifierCheck($1.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier());
+
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ parseContext.parameterTypeCheck($2.loc, $1.qualifier.storage, *$$.param.type);
+ parseContext.paramCheckFix($1.loc, $1.qualifier, *$$.param.type);
+ }
+ | parameter_type_specifier {
+ $$ = $1;
+
+ parseContext.parameterTypeCheck($1.loc, EvqIn, *$1.param.type);
+ parseContext.paramCheckFixStorage($1.loc, EvqTemporary, *$$.param.type);
+ parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier());
+ }
+ ;
+
+parameter_type_specifier
+ : type_specifier {
+ TParameter param = { 0, new TType($1) };
+ $$.param = param;
+ if ($1.arraySizes)
+ parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes);
+ }
+ ;
+
+init_declarator_list
+ : single_declaration {
+ $$ = $1;
+ }
+ | init_declarator_list COMMA IDENTIFIER {
+ $$ = $1;
+ parseContext.declareVariable($3.loc, *$3.string, $1.type);
+ }
+ | init_declarator_list COMMA IDENTIFIER array_specifier {
+ $$ = $1;
+ parseContext.declareVariable($3.loc, *$3.string, $1.type, $4.arraySizes);
+ }
+ | init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer {
+ $$.type = $1.type;
+ TIntermNode* initNode = parseContext.declareVariable($3.loc, *$3.string, $1.type, $4.arraySizes, $6);
+ $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, initNode, $5.loc);
+ }
+ | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
+ $$.type = $1.type;
+ TIntermNode* initNode = parseContext.declareVariable($3.loc, *$3.string, $1.type, 0, $5);
+ $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, initNode, $4.loc);
+ }
+ ;
+
+single_declaration
+ : fully_specified_type {
+ $$.type = $1;
+ $$.intermNode = 0;
+
+ parseContext.declareTypeDefaults($$.loc, $$.type);
+
+ }
+ | fully_specified_type IDENTIFIER {
+ $$.type = $1;
+ $$.intermNode = 0;
+ parseContext.declareVariable($2.loc, *$2.string, $1);
+ }
+ | fully_specified_type IDENTIFIER array_specifier {
+ $$.type = $1;
+ $$.intermNode = 0;
+ parseContext.declareVariable($2.loc, *$2.string, $1, $3.arraySizes);
+ }
+ | fully_specified_type IDENTIFIER array_specifier EQUAL initializer {
+ $$.type = $1;
+ TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, $3.arraySizes, $5);
+ $$.intermNode = parseContext.intermediate.growAggregate(0, initNode, $4.loc);
+ }
+ | fully_specified_type IDENTIFIER EQUAL initializer {
+ $$.type = $1;
+ TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, 0, $4);
+ $$.intermNode = parseContext.intermediate.growAggregate(0, initNode, $3.loc);
+ }
+
+// Grammar Note: No 'enum', or 'typedef'.
+
+fully_specified_type
+ : type_specifier {
+ $$ = $1;
+
+ parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $$);
+ if ($1.arraySizes) {
+ parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
+ }
+ parseContext.precisionQualifierCheck($$.loc, $$.basicType, $$.qualifier);
+ }
+ | type_qualifier type_specifier {
+ parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
+ parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $2);
+
+ if ($2.arraySizes) {
+ parseContext.profileRequires($2.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type");
+ }
+
+ if ($2.arraySizes && parseContext.arrayQualifierError($2.loc, $1.qualifier))
+ $2.arraySizes = nullptr;
+
+ parseContext.checkNoShaderLayouts($2.loc, $1.shaderQualifiers);
+ $2.shaderQualifiers.merge($1.shaderQualifiers);
+ parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true);
+ parseContext.precisionQualifierCheck($2.loc, $2.basicType, $2.qualifier);
+
+ $$ = $2;
+
+ if (! $$.qualifier.isInterpolation() &&
+ ((parseContext.language == EShLangVertex && $$.qualifier.storage == EvqVaryingOut) ||
+ (parseContext.language == EShLangFragment && $$.qualifier.storage == EvqVaryingIn)))
+ $$.qualifier.smooth = true;
+ }
+ ;
+
+invariant_qualifier
+ : INVARIANT {
+ parseContext.globalCheck($1.loc, "invariant");
+ parseContext.profileRequires($$.loc, ENoProfile, 120, 0, "invariant");
+ $$.init($1.loc);
+ $$.qualifier.invariant = true;
+ }
+ ;
+
+interpolation_qualifier
+ : SMOOTH {
+ parseContext.globalCheck($1.loc, "smooth");
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "smooth");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "smooth");
+ $$.init($1.loc);
+ $$.qualifier.smooth = true;
+ }
+ | FLAT {
+ parseContext.globalCheck($1.loc, "flat");
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "flat");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "flat");
+ $$.init($1.loc);
+ $$.qualifier.flat = true;
+ }
+
+ | NOPERSPECTIVE {
+ parseContext.globalCheck($1.loc, "noperspective");
+ parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective");
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "noperspective");
+ $$.init($1.loc);
+ $$.qualifier.nopersp = true;
+ }
+ | EXPLICITINTERPAMD {
+ parseContext.globalCheck($1.loc, "__explicitInterpAMD");
+ parseContext.profileRequires($1.loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation");
+ parseContext.profileRequires($1.loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation");
+ $$.init($1.loc);
+ $$.qualifier.explicitInterp = true;
+ }
+ | PERVERTEXNV {
+ parseContext.globalCheck($1.loc, "pervertexNV");
+ parseContext.profileRequires($1.loc, ECoreProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric");
+ parseContext.profileRequires($1.loc, ECompatibilityProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric");
+ parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric");
+ $$.init($1.loc);
+ $$.qualifier.pervertexNV = true;
+ }
+ | PERPRIMITIVENV {
+ // No need for profile version or extension check. Shader stage already checks both.
+ parseContext.globalCheck($1.loc, "perprimitiveNV");
+ parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshNVMask), "perprimitiveNV");
+ // Fragment shader stage doesn't check for extension. So we explicitly add below extension check.
+ if (parseContext.language == EShLangFragment)
+ parseContext.requireExtensions($1.loc, 1, &E_GL_NV_mesh_shader, "perprimitiveNV");
+ $$.init($1.loc);
+ $$.qualifier.perPrimitiveNV = true;
+ }
+ | PERVIEWNV {
+ // No need for profile version or extension check. Shader stage already checks both.
+ parseContext.globalCheck($1.loc, "perviewNV");
+ parseContext.requireStage($1.loc, EShLangMeshNV, "perviewNV");
+ $$.init($1.loc);
+ $$.qualifier.perViewNV = true;
+ }
+ | PERTASKNV {
+ // No need for profile version or extension check. Shader stage already checks both.
+ parseContext.globalCheck($1.loc, "taskNV");
+ parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask), "taskNV");
+ $$.init($1.loc);
+ $$.qualifier.perTaskNV = true;
+ }
+
+ ;
+
+layout_qualifier
+ : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN {
+ $$ = $3;
+ }
+ ;
+
+layout_qualifier_id_list
+ : layout_qualifier_id {
+ $$ = $1;
+ }
+ | layout_qualifier_id_list COMMA layout_qualifier_id {
+ $$ = $1;
+ $$.shaderQualifiers.merge($3.shaderQualifiers);
+ parseContext.mergeObjectLayoutQualifiers($$.qualifier, $3.qualifier, false);
+ }
+
+layout_qualifier_id
+ : IDENTIFIER {
+ $$.init($1.loc);
+ parseContext.setLayoutQualifier($1.loc, $$, *$1.string);
+ }
+ | IDENTIFIER EQUAL constant_expression {
+ $$.init($1.loc);
+ parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3);
+ }
+ | SHARED { // because "shared" is both an identifier and a keyword
+ $$.init($1.loc);
+ TString strShared("shared");
+ parseContext.setLayoutQualifier($1.loc, $$, strShared);
+ }
+ ;
+
+
+precise_qualifier
+ : PRECISE {
+ parseContext.profileRequires($$.loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise");
+ parseContext.profileRequires($1.loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise");
+ $$.init($1.loc);
+ $$.qualifier.noContraction = true;
+ }
+ ;
+
+
+type_qualifier
+ : single_type_qualifier {
+ $$ = $1;
+ }
+ | type_qualifier single_type_qualifier {
+ $$ = $1;
+ if ($$.basicType == EbtVoid)
+ $$.basicType = $2.basicType;
+
+ $$.shaderQualifiers.merge($2.shaderQualifiers);
+ parseContext.mergeQualifiers($$.loc, $$.qualifier, $2.qualifier, false);
+ }
+ ;
+
+single_type_qualifier
+ : storage_qualifier {
+ $$ = $1;
+ }
+ | layout_qualifier {
+ $$ = $1;
+ }
+ | precision_qualifier {
+ parseContext.checkPrecisionQualifier($1.loc, $1.qualifier.precision);
+ $$ = $1;
+ }
+ | interpolation_qualifier {
+ // allow inheritance of storage qualifier from block declaration
+ $$ = $1;
+ }
+ | invariant_qualifier {
+ // allow inheritance of storage qualifier from block declaration
+ $$ = $1;
+ }
+
+ | precise_qualifier {
+ // allow inheritance of storage qualifier from block declaration
+ $$ = $1;
+ }
+ | non_uniform_qualifier {
+ $$ = $1;
+ }
+
+ ;
+
+storage_qualifier
+ : CONST {
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant
+ }
+ | INOUT {
+ parseContext.globalCheck($1.loc, "inout");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqInOut;
+ }
+ | IN {
+ parseContext.globalCheck($1.loc, "in");
+ $$.init($1.loc);
+ // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later
+ $$.qualifier.storage = EvqIn;
+ }
+ | OUT {
+ parseContext.globalCheck($1.loc, "out");
+ $$.init($1.loc);
+ // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later
+ $$.qualifier.storage = EvqOut;
+ }
+ | CENTROID {
+ parseContext.profileRequires($1.loc, ENoProfile, 120, 0, "centroid");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "centroid");
+ parseContext.globalCheck($1.loc, "centroid");
+ $$.init($1.loc);
+ $$.qualifier.centroid = true;
+ }
+ | UNIFORM {
+ parseContext.globalCheck($1.loc, "uniform");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqUniform;
+ }
+ | SHARED {
+ parseContext.globalCheck($1.loc, "shared");
+ parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared");
+ parseContext.profileRequires($1.loc, EEsProfile, 310, 0, "shared");
+ parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangComputeMask | EShLangMeshNVMask | EShLangTaskNVMask), "shared");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqShared;
+ }
+ | BUFFER {
+ parseContext.globalCheck($1.loc, "buffer");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqBuffer;
+ }
+
+ | ATTRIBUTE {
+ parseContext.requireStage($1.loc, EShLangVertex, "attribute");
+ parseContext.checkDeprecated($1.loc, ECoreProfile, 130, "attribute");
+ parseContext.checkDeprecated($1.loc, ENoProfile, 130, "attribute");
+ parseContext.requireNotRemoved($1.loc, ECoreProfile, 420, "attribute");
+ parseContext.requireNotRemoved($1.loc, EEsProfile, 300, "attribute");
+
+ parseContext.globalCheck($1.loc, "attribute");
+
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqVaryingIn;
+ }
+ | VARYING {
+ parseContext.checkDeprecated($1.loc, ENoProfile, 130, "varying");
+ parseContext.checkDeprecated($1.loc, ECoreProfile, 130, "varying");
+ parseContext.requireNotRemoved($1.loc, ECoreProfile, 420, "varying");
+ parseContext.requireNotRemoved($1.loc, EEsProfile, 300, "varying");
+
+ parseContext.globalCheck($1.loc, "varying");
+
+ $$.init($1.loc);
+ if (parseContext.language == EShLangVertex)
+ $$.qualifier.storage = EvqVaryingOut;
+ else
+ $$.qualifier.storage = EvqVaryingIn;
+ }
+ | PATCH {
+ parseContext.globalCheck($1.loc, "patch");
+ parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch");
+ $$.init($1.loc);
+ $$.qualifier.patch = true;
+ }
+ | SAMPLE {
+ parseContext.globalCheck($1.loc, "sample");
+ $$.init($1.loc);
+ $$.qualifier.sample = true;
+ }
+ | HITATTRNV {
+ parseContext.globalCheck($1.loc, "hitAttributeNV");
+ parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask
+ | EShLangAnyHitNVMask), "hitAttributeNV");
+ parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqHitAttrNV;
+ }
+ | PAYLOADNV {
+ parseContext.globalCheck($1.loc, "rayPayloadNV");
+ parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask |
+ EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV");
+ parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqPayloadNV;
+ }
+ | PAYLOADINNV {
+ parseContext.globalCheck($1.loc, "rayPayloadInNV");
+ parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitNVMask |
+ EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV");
+ parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqPayloadInNV;
+ }
+ | CALLDATANV {
+ parseContext.globalCheck($1.loc, "callableDataNV");
+ parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask |
+ EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV");
+ parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqCallableDataNV;
+ }
+ | CALLDATAINNV {
+ parseContext.globalCheck($1.loc, "callableDataInNV");
+ parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV");
+ parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqCallableDataInNV;
+ }
+ | COHERENT {
+ $$.init($1.loc);
+ $$.qualifier.coherent = true;
+ }
+ | DEVICECOHERENT {
+ $$.init($1.loc);
+ parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "devicecoherent");
+ $$.qualifier.devicecoherent = true;
+ }
+ | QUEUEFAMILYCOHERENT {
+ $$.init($1.loc);
+ parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "queuefamilycoherent");
+ $$.qualifier.queuefamilycoherent = true;
+ }
+ | WORKGROUPCOHERENT {
+ $$.init($1.loc);
+ parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "workgroupcoherent");
+ $$.qualifier.workgroupcoherent = true;
+ }
+ | SUBGROUPCOHERENT {
+ $$.init($1.loc);
+ parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "subgroupcoherent");
+ $$.qualifier.subgroupcoherent = true;
+ }
+ | NONPRIVATE {
+ $$.init($1.loc);
+ parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate");
+ $$.qualifier.nonprivate = true;
+ }
+ | VOLATILE {
+ $$.init($1.loc);
+ $$.qualifier.volatil = true;
+ }
+ | RESTRICT {
+ $$.init($1.loc);
+ $$.qualifier.restrict = true;
+ }
+ | READONLY {
+ $$.init($1.loc);
+ $$.qualifier.readonly = true;
+ }
+ | WRITEONLY {
+ $$.init($1.loc);
+ $$.qualifier.writeonly = true;
+ }
+ | SUBROUTINE {
+ parseContext.spvRemoved($1.loc, "subroutine");
+ parseContext.globalCheck($1.loc, "subroutine");
+ parseContext.unimplemented($1.loc, "subroutine");
+ $$.init($1.loc);
+ }
+ | SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN {
+ parseContext.spvRemoved($1.loc, "subroutine");
+ parseContext.globalCheck($1.loc, "subroutine");
+ parseContext.unimplemented($1.loc, "subroutine");
+ $$.init($1.loc);
+ }
+
+ ;
+
+
+non_uniform_qualifier
+ : NONUNIFORM {
+ $$.init($1.loc);
+ $$.qualifier.nonUniform = true;
+ }
+ ;
+
+type_name_list
+ : IDENTIFIER {
+ // TODO
+ }
+ | type_name_list COMMA IDENTIFIER {
+ // TODO: 4.0 semantics: subroutines
+ // 1) make sure each identifier is a type declared earlier with SUBROUTINE
+ // 2) save all of the identifiers for future comparison with the declared function
+ }
+ ;
+
+
+type_specifier
+ : type_specifier_nonarray type_parameter_specifier_opt {
+ $$ = $1;
+ $$.qualifier.precision = parseContext.getDefaultPrecision($$);
+ $$.typeParameters = $2;
+ }
+ | type_specifier_nonarray type_parameter_specifier_opt array_specifier {
+ parseContext.arrayOfArrayVersionCheck($3.loc, $3.arraySizes);
+ $$ = $1;
+ $$.qualifier.precision = parseContext.getDefaultPrecision($$);
+ $$.typeParameters = $2;
+ $$.arraySizes = $3.arraySizes;
+ }
+ ;
+
+array_specifier
+ : LEFT_BRACKET RIGHT_BRACKET {
+ $$.loc = $1.loc;
+ $$.arraySizes = new TArraySizes;
+ $$.arraySizes->addInnerSize();
+ }
+ | LEFT_BRACKET conditional_expression RIGHT_BRACKET {
+ $$.loc = $1.loc;
+ $$.arraySizes = new TArraySizes;
+
+ TArraySize size;
+ parseContext.arraySizeCheck($2->getLoc(), $2, size, "array size");
+ $$.arraySizes->addInnerSize(size);
+ }
+ | array_specifier LEFT_BRACKET RIGHT_BRACKET {
+ $$ = $1;
+ $$.arraySizes->addInnerSize();
+ }
+ | array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET {
+ $$ = $1;
+
+ TArraySize size;
+ parseContext.arraySizeCheck($3->getLoc(), $3, size, "array size");
+ $$.arraySizes->addInnerSize(size);
+ }
+ ;
+
+type_parameter_specifier_opt
+ : type_parameter_specifier {
+ $$ = $1;
+ }
+ | /* May be null */ {
+ $$ = 0;
+ }
+ ;
+
+type_parameter_specifier
+ : LEFT_ANGLE type_parameter_specifier_list RIGHT_ANGLE {
+ $$ = $2;
+ }
+ ;
+
+type_parameter_specifier_list
+ : unary_expression {
+ $$ = new TArraySizes;
+
+ TArraySize size;
+ parseContext.arraySizeCheck($1->getLoc(), $1, size, "type parameter");
+ $$->addInnerSize(size);
+ }
+ | type_parameter_specifier_list COMMA unary_expression {
+ $$ = $1;
+
+ TArraySize size;
+ parseContext.arraySizeCheck($3->getLoc(), $3, size, "type parameter");
+ $$->addInnerSize(size);
+ }
+ ;
+
+type_specifier_nonarray
+ : VOID {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtVoid;
+ }
+ | FLOAT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ }
+ | INT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ }
+ | UINT {
+ parseContext.fullIntegerCheck($1.loc, "unsigned integer");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ }
+ | BOOL {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtBool;
+ }
+ | VEC2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setVector(2);
+ }
+ | VEC3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setVector(3);
+ }
+ | VEC4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setVector(4);
+ }
+ | BVEC2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtBool;
+ $$.setVector(2);
+ }
+ | BVEC3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtBool;
+ $$.setVector(3);
+ }
+ | BVEC4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtBool;
+ $$.setVector(4);
+ }
+ | IVEC2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ $$.setVector(2);
+ }
+ | IVEC3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ $$.setVector(3);
+ }
+ | IVEC4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ $$.setVector(4);
+ }
+ | UVEC2 {
+ parseContext.fullIntegerCheck($1.loc, "unsigned integer vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ $$.setVector(2);
+ }
+ | UVEC3 {
+ parseContext.fullIntegerCheck($1.loc, "unsigned integer vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ $$.setVector(3);
+ }
+ | UVEC4 {
+ parseContext.fullIntegerCheck($1.loc, "unsigned integer vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ $$.setVector(4);
+ }
+ | MAT2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 2);
+ }
+ | MAT3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 3);
+ }
+ | MAT4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 4);
+ }
+ | MAT2X2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 2);
+ }
+ | MAT2X3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 3);
+ }
+ | MAT2X4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 4);
+ }
+ | MAT3X2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 2);
+ }
+ | MAT3X3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 3);
+ }
+ | MAT3X4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 4);
+ }
+ | MAT4X2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 2);
+ }
+ | MAT4X3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 3);
+ }
+ | MAT4X4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 4);
+ }
+
+ | DOUBLE {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ }
+ | FLOAT16_T {
+ parseContext.float16ScalarVectorCheck($1.loc, "float16_t", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ }
+ | FLOAT32_T {
+ parseContext.explicitFloat32Check($1.loc, "float32_t", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ }
+ | FLOAT64_T {
+ parseContext.explicitFloat64Check($1.loc, "float64_t", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ }
+ | INT8_T {
+ parseContext.int8ScalarVectorCheck($1.loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt8;
+ }
+ | UINT8_T {
+ parseContext.int8ScalarVectorCheck($1.loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint8;
+ }
+ | INT16_T {
+ parseContext.int16ScalarVectorCheck($1.loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt16;
+ }
+ | UINT16_T {
+ parseContext.int16ScalarVectorCheck($1.loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint16;
+ }
+ | INT32_T {
+ parseContext.explicitInt32Check($1.loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ }
+ | UINT32_T {
+ parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ }
+ | INT64_T {
+ parseContext.int64Check($1.loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt64;
+ }
+ | UINT64_T {
+ parseContext.int64Check($1.loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint64;
+ }
+ | DVEC2 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setVector(2);
+ }
+ | DVEC3 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setVector(3);
+ }
+ | DVEC4 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setVector(4);
+ }
+ | F16VEC2 {
+ parseContext.float16ScalarVectorCheck($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setVector(2);
+ }
+ | F16VEC3 {
+ parseContext.float16ScalarVectorCheck($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setVector(3);
+ }
+ | F16VEC4 {
+ parseContext.float16ScalarVectorCheck($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setVector(4);
+ }
+ | F32VEC2 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setVector(2);
+ }
+ | F32VEC3 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setVector(3);
+ }
+ | F32VEC4 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setVector(4);
+ }
+ | F64VEC2 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setVector(2);
+ }
+ | F64VEC3 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setVector(3);
+ }
+ | F64VEC4 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setVector(4);
+ }
+ | I8VEC2 {
+ parseContext.int8ScalarVectorCheck($1.loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt8;
+ $$.setVector(2);
+ }
+ | I8VEC3 {
+ parseContext.int8ScalarVectorCheck($1.loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt8;
+ $$.setVector(3);
+ }
+ | I8VEC4 {
+ parseContext.int8ScalarVectorCheck($1.loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt8;
+ $$.setVector(4);
+ }
+ | I16VEC2 {
+ parseContext.int16ScalarVectorCheck($1.loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt16;
+ $$.setVector(2);
+ }
+ | I16VEC3 {
+ parseContext.int16ScalarVectorCheck($1.loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt16;
+ $$.setVector(3);
+ }
+ | I16VEC4 {
+ parseContext.int16ScalarVectorCheck($1.loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt16;
+ $$.setVector(4);
+ }
+ | I32VEC2 {
+ parseContext.explicitInt32Check($1.loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ $$.setVector(2);
+ }
+ | I32VEC3 {
+ parseContext.explicitInt32Check($1.loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ $$.setVector(3);
+ }
+ | I32VEC4 {
+ parseContext.explicitInt32Check($1.loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ $$.setVector(4);
+ }
+ | I64VEC2 {
+ parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt64;
+ $$.setVector(2);
+ }
+ | I64VEC3 {
+ parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt64;
+ $$.setVector(3);
+ }
+ | I64VEC4 {
+ parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt64;
+ $$.setVector(4);
+ }
+ | U8VEC2 {
+ parseContext.int8ScalarVectorCheck($1.loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint8;
+ $$.setVector(2);
+ }
+ | U8VEC3 {
+ parseContext.int8ScalarVectorCheck($1.loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint8;
+ $$.setVector(3);
+ }
+ | U8VEC4 {
+ parseContext.int8ScalarVectorCheck($1.loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint8;
+ $$.setVector(4);
+ }
+ | U16VEC2 {
+ parseContext.int16ScalarVectorCheck($1.loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint16;
+ $$.setVector(2);
+ }
+ | U16VEC3 {
+ parseContext.int16ScalarVectorCheck($1.loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint16;
+ $$.setVector(3);
+ }
+ | U16VEC4 {
+ parseContext.int16ScalarVectorCheck($1.loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint16;
+ $$.setVector(4);
+ }
+ | U32VEC2 {
+ parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ $$.setVector(2);
+ }
+ | U32VEC3 {
+ parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ $$.setVector(3);
+ }
+ | U32VEC4 {
+ parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ $$.setVector(4);
+ }
+ | U64VEC2 {
+ parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint64;
+ $$.setVector(2);
+ }
+ | U64VEC3 {
+ parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint64;
+ $$.setVector(3);
+ }
+ | U64VEC4 {
+ parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint64;
+ $$.setVector(4);
+ }
+ | DMAT2 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 2);
+ }
+ | DMAT3 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 3);
+ }
+ | DMAT4 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 4);
+ }
+ | DMAT2X2 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 2);
+ }
+ | DMAT2X3 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 3);
+ }
+ | DMAT2X4 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 4);
+ }
+ | DMAT3X2 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 2);
+ }
+ | DMAT3X3 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 3);
+ }
+ | DMAT3X4 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 4);
+ }
+ | DMAT4X2 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 2);
+ }
+ | DMAT4X3 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 3);
+ }
+ | DMAT4X4 {
+ parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 4);
+ }
+ | F16MAT2 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(2, 2);
+ }
+ | F16MAT3 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(3, 3);
+ }
+ | F16MAT4 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(4, 4);
+ }
+ | F16MAT2X2 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(2, 2);
+ }
+ | F16MAT2X3 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(2, 3);
+ }
+ | F16MAT2X4 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(2, 4);
+ }
+ | F16MAT3X2 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(3, 2);
+ }
+ | F16MAT3X3 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(3, 3);
+ }
+ | F16MAT3X4 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(3, 4);
+ }
+ | F16MAT4X2 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(4, 2);
+ }
+ | F16MAT4X3 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(4, 3);
+ }
+ | F16MAT4X4 {
+ parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat16;
+ $$.setMatrix(4, 4);
+ }
+ | F32MAT2 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 2);
+ }
+ | F32MAT3 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 3);
+ }
+ | F32MAT4 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 4);
+ }
+ | F32MAT2X2 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 2);
+ }
+ | F32MAT2X3 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 3);
+ }
+ | F32MAT2X4 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 4);
+ }
+ | F32MAT3X2 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 2);
+ }
+ | F32MAT3X3 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 3);
+ }
+ | F32MAT3X4 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 4);
+ }
+ | F32MAT4X2 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 2);
+ }
+ | F32MAT4X3 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 3);
+ }
+ | F32MAT4X4 {
+ parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 4);
+ }
+ | F64MAT2 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 2);
+ }
+ | F64MAT3 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 3);
+ }
+ | F64MAT4 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 4);
+ }
+ | F64MAT2X2 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 2);
+ }
+ | F64MAT2X3 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 3);
+ }
+ | F64MAT2X4 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 4);
+ }
+ | F64MAT3X2 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 2);
+ }
+ | F64MAT3X3 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 3);
+ }
+ | F64MAT3X4 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 4);
+ }
+ | F64MAT4X2 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 2);
+ }
+ | F64MAT4X3 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 3);
+ }
+ | F64MAT4X4 {
+ parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 4);
+ }
+ | ACCSTRUCTNV {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtAccStructNV;
+ }
+ | ATOMIC_UINT {
+ parseContext.vulkanRemoved($1.loc, "atomic counter types");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtAtomicUint;
+ }
+ | SAMPLER1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd1D);
+ }
+
+ | SAMPLER2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D);
+ }
+ | SAMPLER3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd3D);
+ }
+ | SAMPLERCUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdCube);
+ }
+ | SAMPLER2DSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D, false, true);
+ }
+ | SAMPLERCUBESHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdCube, false, true);
+ }
+ | SAMPLER2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D, true);
+ }
+ | SAMPLER2DARRAYSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D, true, true);
+ }
+
+ | SAMPLER1DSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd1D, false, true);
+ }
+ | SAMPLER1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd1D, true);
+ }
+ | SAMPLER1DARRAYSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd1D, true, true);
+ }
+ | SAMPLERCUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdCube, true);
+ }
+ | SAMPLERCUBEARRAYSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdCube, true, true);
+ }
+ | F16SAMPLER1D {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd1D);
+ }
+ | F16SAMPLER2D {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd2D);
+ }
+ | F16SAMPLER3D {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd3D);
+ }
+ | F16SAMPLERCUBE {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, EsdCube);
+ }
+ | F16SAMPLER1DSHADOW {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd1D, false, true);
+ }
+ | F16SAMPLER2DSHADOW {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd2D, false, true);
+ }
+ | F16SAMPLERCUBESHADOW {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, EsdCube, false, true);
+ }
+ | F16SAMPLER1DARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd1D, true);
+ }
+ | F16SAMPLER2DARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd2D, true);
+ }
+ | F16SAMPLER1DARRAYSHADOW {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd1D, true, true);
+ }
+ | F16SAMPLER2DARRAYSHADOW {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd2D, true, true);
+ }
+ | F16SAMPLERCUBEARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, EsdCube, true);
+ }
+ | F16SAMPLERCUBEARRAYSHADOW {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, EsdCube, true, true);
+ }
+ | ISAMPLER1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd1D);
+ }
+
+ | ISAMPLER2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd2D);
+ }
+ | ISAMPLER3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd3D);
+ }
+ | ISAMPLERCUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, EsdCube);
+ }
+ | ISAMPLER2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd2D, true);
+ }
+ | USAMPLER2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd2D);
+ }
+ | USAMPLER3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd3D);
+ }
+ | USAMPLERCUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, EsdCube);
+ }
+
+ | ISAMPLER1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd1D, true);
+ }
+ | ISAMPLERCUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, EsdCube, true);
+ }
+ | USAMPLER1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd1D);
+ }
+ | USAMPLER1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd1D, true);
+ }
+ | USAMPLERCUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, EsdCube, true);
+ }
+ | TEXTURECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, EsdCube, true);
+ }
+ | ITEXTURECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, EsdCube, true);
+ }
+ | UTEXTURECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, EsdCube, true);
+ }
+
+ | USAMPLER2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd2D, true);
+ }
+ | TEXTURE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd2D);
+ }
+ | TEXTURE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd3D);
+ }
+ | TEXTURE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd2D, true);
+ }
+ | TEXTURECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, EsdCube);
+ }
+ | ITEXTURE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd2D);
+ }
+ | ITEXTURE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd3D);
+ }
+ | ITEXTURECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, EsdCube);
+ }
+ | ITEXTURE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd2D, true);
+ }
+ | UTEXTURE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd2D);
+ }
+ | UTEXTURE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd3D);
+ }
+ | UTEXTURECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, EsdCube);
+ }
+ | UTEXTURE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd2D, true);
+ }
+ | SAMPLER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setPureSampler(false);
+ }
+ | SAMPLERSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setPureSampler(true);
+ }
+
+ | SAMPLER2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdRect);
+ }
+ | SAMPLER2DRECTSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdRect, false, true);
+ }
+ | F16SAMPLER2DRECT {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, EsdRect);
+ }
+ | F16SAMPLER2DRECTSHADOW {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, EsdRect, false, true);
+ }
+ | ISAMPLER2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, EsdRect);
+ }
+ | USAMPLER2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, EsdRect);
+ }
+ | SAMPLERBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdBuffer);
+ }
+ | F16SAMPLERBUFFER {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, EsdBuffer);
+ }
+ | ISAMPLERBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, EsdBuffer);
+ }
+ | USAMPLERBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, EsdBuffer);
+ }
+ | SAMPLER2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D, false, false, true);
+ }
+ | F16SAMPLER2DMS {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd2D, false, false, true);
+ }
+ | ISAMPLER2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd2D, false, false, true);
+ }
+ | USAMPLER2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd2D, false, false, true);
+ }
+ | SAMPLER2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D, true, false, true);
+ }
+ | F16SAMPLER2DMSARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat16, Esd2D, true, false, true);
+ }
+ | ISAMPLER2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd2D, true, false, true);
+ }
+ | USAMPLER2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd2D, true, false, true);
+ }
+ | TEXTURE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd1D);
+ }
+ | F16TEXTURE1D {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, Esd1D);
+ }
+ | F16TEXTURE2D {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, Esd2D);
+ }
+ | F16TEXTURE3D {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, Esd3D);
+ }
+ | F16TEXTURECUBE {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, EsdCube);
+ }
+ | TEXTURE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd1D, true);
+ }
+ | F16TEXTURE1DARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, Esd1D, true);
+ }
+ | F16TEXTURE2DARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, Esd2D, true);
+ }
+ | F16TEXTURECUBEARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, EsdCube, true);
+ }
+ | ITEXTURE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd1D);
+ }
+ | ITEXTURE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd1D, true);
+ }
+ | UTEXTURE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd1D);
+ }
+ | UTEXTURE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd1D, true);
+ }
+ | TEXTURE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, EsdRect);
+ }
+ | F16TEXTURE2DRECT {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, EsdRect);
+ }
+ | ITEXTURE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, EsdRect);
+ }
+ | UTEXTURE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, EsdRect);
+ }
+ | TEXTUREBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, EsdBuffer);
+ }
+ | F16TEXTUREBUFFER {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, EsdBuffer);
+ }
+ | ITEXTUREBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, EsdBuffer);
+ }
+ | UTEXTUREBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, EsdBuffer);
+ }
+ | TEXTURE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd2D, false, false, true);
+ }
+ | F16TEXTURE2DMS {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, Esd2D, false, false, true);
+ }
+ | ITEXTURE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd2D, false, false, true);
+ }
+ | UTEXTURE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd2D, false, false, true);
+ }
+ | TEXTURE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd2D, true, false, true);
+ }
+ | F16TEXTURE2DMSARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat16, Esd2D, true, false, true);
+ }
+ | ITEXTURE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd2D, true, false, true);
+ }
+ | UTEXTURE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd2D, true, false, true);
+ }
+ | IMAGE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd1D);
+ }
+ | F16IMAGE1D {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, Esd1D);
+ }
+ | IIMAGE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd1D);
+ }
+ | UIMAGE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd1D);
+ }
+ | IMAGE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd2D);
+ }
+ | F16IMAGE2D {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, Esd2D);
+ }
+ | IIMAGE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd2D);
+ }
+ | UIMAGE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd2D);
+ }
+ | IMAGE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd3D);
+ }
+ | F16IMAGE3D {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, Esd3D);
+ }
+ | IIMAGE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd3D);
+ }
+ | UIMAGE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd3D);
+ }
+ | IMAGE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, EsdRect);
+ }
+ | F16IMAGE2DRECT {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, EsdRect);
+ }
+ | IIMAGE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, EsdRect);
+ }
+ | UIMAGE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, EsdRect);
+ }
+ | IMAGECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, EsdCube);
+ }
+ | F16IMAGECUBE {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, EsdCube);
+ }
+ | IIMAGECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, EsdCube);
+ }
+ | UIMAGECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, EsdCube);
+ }
+ | IMAGEBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, EsdBuffer);
+ }
+ | F16IMAGEBUFFER {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, EsdBuffer);
+ }
+ | IIMAGEBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, EsdBuffer);
+ }
+ | UIMAGEBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, EsdBuffer);
+ }
+ | IMAGE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd1D, true);
+ }
+ | F16IMAGE1DARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, Esd1D, true);
+ }
+ | IIMAGE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd1D, true);
+ }
+ | UIMAGE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd1D, true);
+ }
+ | IMAGE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd2D, true);
+ }
+ | F16IMAGE2DARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, Esd2D, true);
+ }
+ | IIMAGE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd2D, true);
+ }
+ | UIMAGE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd2D, true);
+ }
+ | IMAGECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, EsdCube, true);
+ }
+ | F16IMAGECUBEARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, EsdCube, true);
+ }
+ | IIMAGECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, EsdCube, true);
+ }
+ | UIMAGECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, EsdCube, true);
+ }
+ | IMAGE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd2D, false, false, true);
+ }
+ | F16IMAGE2DMS {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, Esd2D, false, false, true);
+ }
+ | IIMAGE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd2D, false, false, true);
+ }
+ | UIMAGE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd2D, false, false, true);
+ }
+ | IMAGE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd2D, true, false, true);
+ }
+ | F16IMAGE2DMSARRAY {
+ parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat16, Esd2D, true, false, true);
+ }
+ | IIMAGE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd2D, true, false, true);
+ }
+ | UIMAGE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd2D, true, false, true);
+ }
+ | SAMPLEREXTERNALOES { // GL_OES_EGL_image_external
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D);
+ $$.sampler.external = true;
+ }
+ | SAMPLEREXTERNAL2DY2YEXT { // GL_EXT_YUV_target
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D);
+ $$.sampler.yuv = true;
+ }
+ | SUBPASSINPUT {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtFloat);
+ }
+ | SUBPASSINPUTMS {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtFloat, true);
+ }
+ | F16SUBPASSINPUT {
+ parseContext.float16OpaqueCheck($1.loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel());
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtFloat16);
+ }
+ | F16SUBPASSINPUTMS {
+ parseContext.float16OpaqueCheck($1.loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel());
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtFloat16, true);
+ }
+ | ISUBPASSINPUT {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtInt);
+ }
+ | ISUBPASSINPUTMS {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtInt, true);
+ }
+ | USUBPASSINPUT {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtUint);
+ }
+ | USUBPASSINPUTMS {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtUint, true);
+ }
+ | FCOOPMATNV {
+ parseContext.fcoopmatCheck($1.loc, "fcoopmatNV", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.coopmat = true;
+ }
+ | ICOOPMATNV {
+ parseContext.intcoopmatCheck($1.loc, "icoopmatNV", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ $$.coopmat = true;
+ }
+ | UCOOPMATNV {
+ parseContext.intcoopmatCheck($1.loc, "ucoopmatNV", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ $$.coopmat = true;
+ }
+
+ | struct_specifier {
+ $$ = $1;
+ $$.qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ parseContext.structTypeCheck($$.loc, $$);
+ }
+ | TYPE_NAME {
+ //
+ // This is for user defined type names. The lexical phase looked up the
+ // type.
+ //
+ if (const TVariable* variable = ($1.symbol)->getAsVariable()) {
+ const TType& structure = variable->getType();
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtStruct;
+ $$.userDef = &structure;
+ } else
+ parseContext.error($1.loc, "expected type name", $1.string->c_str(), "");
+ }
+ ;
+
+precision_qualifier
+ : HIGH_PRECISION {
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "highp precision qualifier");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqHigh);
+ }
+ | MEDIUM_PRECISION {
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "mediump precision qualifier");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqMedium);
+ }
+ | LOW_PRECISION {
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "lowp precision qualifier");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqLow);
+ }
+ ;
+
+struct_specifier
+ : STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
+ TType* structure = new TType($5, *$2.string);
+ parseContext.structArrayCheck($2.loc, *structure);
+ TVariable* userTypeDef = new TVariable($2.string, *structure, true);
+ if (! parseContext.symbolTable.insert(*userTypeDef))
+ parseContext.error($2.loc, "redefinition", $2.string->c_str(), "struct");
+ $$.init($1.loc);
+ $$.basicType = EbtStruct;
+ $$.userDef = structure;
+ --parseContext.structNestingLevel;
+ }
+ | STRUCT LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
+ TType* structure = new TType($4, TString(""));
+ $$.init($1.loc);
+ $$.basicType = EbtStruct;
+ $$.userDef = structure;
+ --parseContext.structNestingLevel;
+ }
+ ;
+
+struct_declaration_list
+ : struct_declaration {
+ $$ = $1;
+ }
+ | struct_declaration_list struct_declaration {
+ $$ = $1;
+ for (unsigned int i = 0; i < $2->size(); ++i) {
+ for (unsigned int j = 0; j < $$->size(); ++j) {
+ if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName())
+ parseContext.error((*$2)[i].loc, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str());
+ }
+ $$->push_back((*$2)[i]);
+ }
+ }
+ ;
+
+struct_declaration
+ : type_specifier struct_declarator_list SEMICOLON {
+ if ($1.arraySizes) {
+ parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
+ if (parseContext.isEsProfile())
+ parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes);
+ }
+
+ $$ = $2;
+
+ parseContext.voidErrorCheck($1.loc, (*$2)[0].type->getFieldName(), $1.basicType);
+ parseContext.precisionQualifierCheck($1.loc, $1.basicType, $1.qualifier);
+
+ for (unsigned int i = 0; i < $$->size(); ++i) {
+ TType type($1);
+ type.setFieldName((*$$)[i].type->getFieldName());
+ type.transferArraySizes((*$$)[i].type->getArraySizes());
+ type.copyArrayInnerSizes($1.arraySizes);
+ parseContext.arrayOfArrayVersionCheck((*$$)[i].loc, type.getArraySizes());
+ (*$$)[i].type->shallowCopy(type);
+ }
+ }
+ | type_qualifier type_specifier struct_declarator_list SEMICOLON {
+ if ($2.arraySizes) {
+ parseContext.profileRequires($2.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type");
+ if (parseContext.isEsProfile())
+ parseContext.arraySizeRequiredCheck($2.loc, *$2.arraySizes);
+ }
+
+ $$ = $3;
+
+ parseContext.memberQualifierCheck($1);
+ parseContext.voidErrorCheck($2.loc, (*$3)[0].type->getFieldName(), $2.basicType);
+ parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true);
+ parseContext.precisionQualifierCheck($2.loc, $2.basicType, $2.qualifier);
+
+ for (unsigned int i = 0; i < $$->size(); ++i) {
+ TType type($2);
+ type.setFieldName((*$$)[i].type->getFieldName());
+ type.transferArraySizes((*$$)[i].type->getArraySizes());
+ type.copyArrayInnerSizes($2.arraySizes);
+ parseContext.arrayOfArrayVersionCheck((*$$)[i].loc, type.getArraySizes());
+ (*$$)[i].type->shallowCopy(type);
+ }
+ }
+ ;
+
+struct_declarator_list
+ : struct_declarator {
+ $$ = new TTypeList;
+ $$->push_back($1);
+ }
+ | struct_declarator_list COMMA struct_declarator {
+ $$->push_back($3);
+ }
+ ;
+
+struct_declarator
+ : IDENTIFIER {
+ $$.type = new TType(EbtVoid);
+ $$.loc = $1.loc;
+ $$.type->setFieldName(*$1.string);
+ }
+ | IDENTIFIER array_specifier {
+ parseContext.arrayOfArrayVersionCheck($1.loc, $2.arraySizes);
+
+ $$.type = new TType(EbtVoid);
+ $$.loc = $1.loc;
+ $$.type->setFieldName(*$1.string);
+ $$.type->transferArraySizes($2.arraySizes);
+ }
+ ;
+
+initializer
+ : assignment_expression {
+ $$ = $1;
+ }
+
+ | LEFT_BRACE initializer_list RIGHT_BRACE {
+ const char* initFeature = "{ } style initializers";
+ parseContext.requireProfile($1.loc, ~EEsProfile, initFeature);
+ parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
+ $$ = $2;
+ }
+ | LEFT_BRACE initializer_list COMMA RIGHT_BRACE {
+ const char* initFeature = "{ } style initializers";
+ parseContext.requireProfile($1.loc, ~EEsProfile, initFeature);
+ parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
+ $$ = $2;
+ }
+
+ ;
+
+
+initializer_list
+ : initializer {
+ $$ = parseContext.intermediate.growAggregate(0, $1, $1->getLoc());
+ }
+ | initializer_list COMMA initializer {
+ $$ = parseContext.intermediate.growAggregate($1, $3);
+ }
+ ;
+
+
+declaration_statement
+ : declaration { $$ = $1; }
+ ;
+
+statement
+ : compound_statement { $$ = $1; }
+ | simple_statement { $$ = $1; }
+ ;
+
+// Grammar Note: labeled statements for switch statements only; 'goto' is not supported.
+
+simple_statement
+ : declaration_statement { $$ = $1; }
+ | expression_statement { $$ = $1; }
+ | selection_statement { $$ = $1; }
+ | switch_statement { $$ = $1; }
+ | case_label { $$ = $1; }
+ | iteration_statement { $$ = $1; }
+ | jump_statement { $$ = $1; }
+
+ | demote_statement { $$ = $1; }
+
+ ;
+
+
+demote_statement
+ : DEMOTE SEMICOLON {
+ parseContext.requireStage($1.loc, EShLangFragment, "demote");
+ parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_demote_to_helper_invocation, "demote");
+ $$ = parseContext.intermediate.addBranch(EOpDemote, $1.loc);
+ }
+ ;
+
+
+compound_statement
+ : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
+ | LEFT_BRACE {
+ parseContext.symbolTable.push();
+ ++parseContext.statementNestingLevel;
+ }
+ statement_list {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ }
+ RIGHT_BRACE {
+ if ($3 && $3->getAsAggregate())
+ $3->getAsAggregate()->setOperator(EOpSequence);
+ $$ = $3;
+ }
+ ;
+
+statement_no_new_scope
+ : compound_statement_no_new_scope { $$ = $1; }
+ | simple_statement { $$ = $1; }
+ ;
+
+statement_scoped
+ : {
+ ++parseContext.controlFlowNestingLevel;
+ }
+ compound_statement {
+ --parseContext.controlFlowNestingLevel;
+ $$ = $2;
+ }
+ | {
+ parseContext.symbolTable.push();
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+ simple_statement {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ $$ = $2;
+ }
+
+compound_statement_no_new_scope
+ // Statement that doesn't create a new scope, for selection_statement, iteration_statement
+ : LEFT_BRACE RIGHT_BRACE {
+ $$ = 0;
+ }
+ | LEFT_BRACE statement_list RIGHT_BRACE {
+ if ($2 && $2->getAsAggregate())
+ $2->getAsAggregate()->setOperator(EOpSequence);
+ $$ = $2;
+ }
+ ;
+
+statement_list
+ : statement {
+ $$ = parseContext.intermediate.makeAggregate($1);
+ if ($1 && $1->getAsBranchNode() && ($1->getAsBranchNode()->getFlowOp() == EOpCase ||
+ $1->getAsBranchNode()->getFlowOp() == EOpDefault)) {
+ parseContext.wrapupSwitchSubsequence(0, $1);
+ $$ = 0; // start a fresh subsequence for what's after this case
+ }
+ }
+ | statement_list statement {
+ if ($2 && $2->getAsBranchNode() && ($2->getAsBranchNode()->getFlowOp() == EOpCase ||
+ $2->getAsBranchNode()->getFlowOp() == EOpDefault)) {
+ parseContext.wrapupSwitchSubsequence($1 ? $1->getAsAggregate() : 0, $2);
+ $$ = 0; // start a fresh subsequence for what's after this case
+ } else
+ $$ = parseContext.intermediate.growAggregate($1, $2);
+ }
+ ;
+
+expression_statement
+ : SEMICOLON { $$ = 0; }
+ | expression SEMICOLON { $$ = static_cast<TIntermNode*>($1); }
+ ;
+
+selection_statement
+ : selection_statement_nonattributed {
+ $$ = $1;
+ }
+
+ | attribute selection_statement_nonattributed {
+ parseContext.handleSelectionAttributes(*$1, $2);
+ $$ = $2;
+ }
+
+
+selection_statement_nonattributed
+ : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
+ parseContext.boolCheck($1.loc, $3);
+ $$ = parseContext.intermediate.addSelection($3, $5, $1.loc);
+ }
+ ;
+
+selection_rest_statement
+ : statement_scoped ELSE statement_scoped {
+ $$.node1 = $1;
+ $$.node2 = $3;
+ }
+ | statement_scoped {
+ $$.node1 = $1;
+ $$.node2 = 0;
+ }
+ ;
+
+condition
+ // In 1996 c++ draft, conditions can include single declarations
+ : expression {
+ $$ = $1;
+ parseContext.boolCheck($1->getLoc(), $1);
+ }
+ | fully_specified_type IDENTIFIER EQUAL initializer {
+ parseContext.boolCheck($2.loc, $1);
+
+ TType type($1);
+ TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, 0, $4);
+ if (initNode)
+ $$ = initNode->getAsTyped();
+ else
+ $$ = 0;
+ }
+ ;
+
+switch_statement
+ : switch_statement_nonattributed {
+ $$ = $1;
+ }
+
+ | attribute switch_statement_nonattributed {
+ parseContext.handleSwitchAttributes(*$1, $2);
+ $$ = $2;
+ }
+
+
+switch_statement_nonattributed
+ : SWITCH LEFT_PAREN expression RIGHT_PAREN {
+ // start new switch sequence on the switch stack
+ ++parseContext.controlFlowNestingLevel;
+ ++parseContext.statementNestingLevel;
+ parseContext.switchSequenceStack.push_back(new TIntermSequence);
+ parseContext.switchLevel.push_back(parseContext.statementNestingLevel);
+ parseContext.symbolTable.push();
+ }
+ LEFT_BRACE switch_statement_list RIGHT_BRACE {
+ $$ = parseContext.addSwitch($1.loc, $3, $7 ? $7->getAsAggregate() : 0);
+ delete parseContext.switchSequenceStack.back();
+ parseContext.switchSequenceStack.pop_back();
+ parseContext.switchLevel.pop_back();
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+ ;
+
+switch_statement_list
+ : /* nothing */ {
+ $$ = 0;
+ }
+ | statement_list {
+ $$ = $1;
+ }
+ ;
+
+case_label
+ : CASE expression COLON {
+ $$ = 0;
+ if (parseContext.switchLevel.size() == 0)
+ parseContext.error($1.loc, "cannot appear outside switch statement", "case", "");
+ else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel)
+ parseContext.error($1.loc, "cannot be nested inside control flow", "case", "");
+ else {
+ parseContext.constantValueCheck($2, "case");
+ parseContext.integerCheck($2, "case");
+ $$ = parseContext.intermediate.addBranch(EOpCase, $2, $1.loc);
+ }
+ }
+ | DEFAULT COLON {
+ $$ = 0;
+ if (parseContext.switchLevel.size() == 0)
+ parseContext.error($1.loc, "cannot appear outside switch statement", "default", "");
+ else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel)
+ parseContext.error($1.loc, "cannot be nested inside control flow", "default", "");
+ else
+ $$ = parseContext.intermediate.addBranch(EOpDefault, $1.loc);
+ }
+ ;
+
+iteration_statement
+ : iteration_statement_nonattributed {
+ $$ = $1;
+ }
+
+ | attribute iteration_statement_nonattributed {
+ parseContext.handleLoopAttributes(*$1, $2);
+ $$ = $2;
+ }
+
+
+iteration_statement_nonattributed
+ : WHILE LEFT_PAREN {
+ if (! parseContext.limits.whileLoops)
+ parseContext.error($1.loc, "while loops not available", "limitation", "");
+ parseContext.symbolTable.push();
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+ condition RIGHT_PAREN statement_no_new_scope {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ $$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.loc);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+ | DO {
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+ statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+ if (! parseContext.limits.whileLoops)
+ parseContext.error($1.loc, "do-while loops not available", "limitation", "");
+
+ parseContext.boolCheck($8.loc, $6);
+
+ $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+ | FOR LEFT_PAREN {
+ parseContext.symbolTable.push();
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+ for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ $$ = parseContext.intermediate.makeAggregate($4, $2.loc);
+ TIntermLoop* forLoop = parseContext.intermediate.addLoop($7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.loc);
+ if (! parseContext.limits.nonInductiveForLoops)
+ parseContext.inductiveLoopCheck($1.loc, $4, forLoop);
+ $$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc);
+ $$->getAsAggregate()->setOperator(EOpSequence);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+ ;
+
+for_init_statement
+ : expression_statement {
+ $$ = $1;
+ }
+ | declaration_statement {
+ $$ = $1;
+ }
+ ;
+
+conditionopt
+ : condition {
+ $$ = $1;
+ }
+ | /* May be null */ {
+ $$ = 0;
+ }
+ ;
+
+for_rest_statement
+ : conditionopt SEMICOLON {
+ $$.node1 = $1;
+ $$.node2 = 0;
+ }
+ | conditionopt SEMICOLON expression {
+ $$.node1 = $1;
+ $$.node2 = $3;
+ }
+ ;
+
+jump_statement
+ : CONTINUE SEMICOLON {
+ if (parseContext.loopNestingLevel <= 0)
+ parseContext.error($1.loc, "continue statement only allowed in loops", "", "");
+ $$ = parseContext.intermediate.addBranch(EOpContinue, $1.loc);
+ }
+ | BREAK SEMICOLON {
+ if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0)
+ parseContext.error($1.loc, "break statement only allowed in switch and loops", "", "");
+ $$ = parseContext.intermediate.addBranch(EOpBreak, $1.loc);
+ }
+ | RETURN SEMICOLON {
+ $$ = parseContext.intermediate.addBranch(EOpReturn, $1.loc);
+ if (parseContext.currentFunctionType->getBasicType() != EbtVoid)
+ parseContext.error($1.loc, "non-void function must return a value", "return", "");
+ if (parseContext.inMain)
+ parseContext.postEntryPointReturn = true;
+ }
+ | RETURN expression SEMICOLON {
+ $$ = parseContext.handleReturnValue($1.loc, $2);
+ }
+ | DISCARD SEMICOLON {
+ parseContext.requireStage($1.loc, EShLangFragment, "discard");
+ $$ = parseContext.intermediate.addBranch(EOpKill, $1.loc);
+ }
+ ;
+
+// Grammar Note: No 'goto'. Gotos are not supported.
+
+translation_unit
+ : external_declaration {
+ $$ = $1;
+ parseContext.intermediate.setTreeRoot($$);
+ }
+ | translation_unit external_declaration {
+ if ($2 != nullptr) {
+ $$ = parseContext.intermediate.growAggregate($1, $2);
+ parseContext.intermediate.setTreeRoot($$);
+ }
+ }
+ ;
+
+external_declaration
+ : function_definition {
+ $$ = $1;
+ }
+ | declaration {
+ $$ = $1;
+ }
+
+ | SEMICOLON {
+ parseContext.requireProfile($1.loc, ~EEsProfile, "extraneous semicolon");
+ parseContext.profileRequires($1.loc, ~EEsProfile, 460, nullptr, "extraneous semicolon");
+ $$ = nullptr;
+ }
+
+ ;
+
+function_definition
+ : function_prototype {
+ $1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */);
+ $1.intermNode = parseContext.handleFunctionDefinition($1.loc, *$1.function);
+ }
+ compound_statement_no_new_scope {
+ // May be best done as post process phase on intermediate code
+ if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue)
+ parseContext.error($1.loc, "function does not return a value:", "", $1.function->getName().c_str());
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ $$ = parseContext.intermediate.growAggregate($1.intermNode, $3);
+ parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.function->getType(), $1.loc);
+ $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
+
+ // store the pragma information for debug and optimize and other vendor specific
+ // information. This information can be queried from the parse tree
+ $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize);
+ $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug);
+ $$->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable);
+ }
+ ;
+
+
+attribute
+ : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET {
+ $$ = $3;
+ parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_control_flow_attributes, "attribute");
+ }
+
+attribute_list
+ : single_attribute {
+ $$ = $1;
+ }
+ | attribute_list COMMA single_attribute {
+ $$ = parseContext.mergeAttributes($1, $3);
+ }
+
+single_attribute
+ : IDENTIFIER {
+ $$ = parseContext.makeAttributes(*$1.string);
+ }
+ | IDENTIFIER LEFT_PAREN constant_expression RIGHT_PAREN {
+ $$ = parseContext.makeAttributes(*$1.string, $3);
+ }
+
+
+%%
diff --git a/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp b/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp
new file mode 100644
index 0000000000..2a47faada4
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp
@@ -0,0 +1,10439 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 68 "MachineIndependent/glslang.y" /* yacc.c:339 */
+
+
+/* Based on:
+ANSI C Yacc grammar
+
+In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a
+matching Lex specification) for the April 30, 1985 draft version of the
+ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that
+original, as mentioned in the answer to question 17.25 of the comp.lang.c
+FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar as
+possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "../Public/ShaderLang.h"
+#include "attribute.h"
+
+using namespace glslang;
+
+
+#line 92 "MachineIndependent/glslang_tab.cpp" /* yacc.c:339 */
+
+# ifndef YY_NULLPTR
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+ by #include "glslang_tab.cpp.h". */
+#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ CONST = 258,
+ BOOL = 259,
+ INT = 260,
+ UINT = 261,
+ FLOAT = 262,
+ BVEC2 = 263,
+ BVEC3 = 264,
+ BVEC4 = 265,
+ IVEC2 = 266,
+ IVEC3 = 267,
+ IVEC4 = 268,
+ UVEC2 = 269,
+ UVEC3 = 270,
+ UVEC4 = 271,
+ VEC2 = 272,
+ VEC3 = 273,
+ VEC4 = 274,
+ MAT2 = 275,
+ MAT3 = 276,
+ MAT4 = 277,
+ MAT2X2 = 278,
+ MAT2X3 = 279,
+ MAT2X4 = 280,
+ MAT3X2 = 281,
+ MAT3X3 = 282,
+ MAT3X4 = 283,
+ MAT4X2 = 284,
+ MAT4X3 = 285,
+ MAT4X4 = 286,
+ SAMPLER2D = 287,
+ SAMPLER3D = 288,
+ SAMPLERCUBE = 289,
+ SAMPLER2DSHADOW = 290,
+ SAMPLERCUBESHADOW = 291,
+ SAMPLER2DARRAY = 292,
+ SAMPLER2DARRAYSHADOW = 293,
+ ISAMPLER2D = 294,
+ ISAMPLER3D = 295,
+ ISAMPLERCUBE = 296,
+ ISAMPLER2DARRAY = 297,
+ USAMPLER2D = 298,
+ USAMPLER3D = 299,
+ USAMPLERCUBE = 300,
+ USAMPLER2DARRAY = 301,
+ SAMPLER = 302,
+ SAMPLERSHADOW = 303,
+ TEXTURE2D = 304,
+ TEXTURE3D = 305,
+ TEXTURECUBE = 306,
+ TEXTURE2DARRAY = 307,
+ ITEXTURE2D = 308,
+ ITEXTURE3D = 309,
+ ITEXTURECUBE = 310,
+ ITEXTURE2DARRAY = 311,
+ UTEXTURE2D = 312,
+ UTEXTURE3D = 313,
+ UTEXTURECUBE = 314,
+ UTEXTURE2DARRAY = 315,
+ ATTRIBUTE = 316,
+ VARYING = 317,
+ FLOAT16_T = 318,
+ FLOAT32_T = 319,
+ DOUBLE = 320,
+ FLOAT64_T = 321,
+ INT64_T = 322,
+ UINT64_T = 323,
+ INT32_T = 324,
+ UINT32_T = 325,
+ INT16_T = 326,
+ UINT16_T = 327,
+ INT8_T = 328,
+ UINT8_T = 329,
+ I64VEC2 = 330,
+ I64VEC3 = 331,
+ I64VEC4 = 332,
+ U64VEC2 = 333,
+ U64VEC3 = 334,
+ U64VEC4 = 335,
+ I32VEC2 = 336,
+ I32VEC3 = 337,
+ I32VEC4 = 338,
+ U32VEC2 = 339,
+ U32VEC3 = 340,
+ U32VEC4 = 341,
+ I16VEC2 = 342,
+ I16VEC3 = 343,
+ I16VEC4 = 344,
+ U16VEC2 = 345,
+ U16VEC3 = 346,
+ U16VEC4 = 347,
+ I8VEC2 = 348,
+ I8VEC3 = 349,
+ I8VEC4 = 350,
+ U8VEC2 = 351,
+ U8VEC3 = 352,
+ U8VEC4 = 353,
+ DVEC2 = 354,
+ DVEC3 = 355,
+ DVEC4 = 356,
+ DMAT2 = 357,
+ DMAT3 = 358,
+ DMAT4 = 359,
+ F16VEC2 = 360,
+ F16VEC3 = 361,
+ F16VEC4 = 362,
+ F16MAT2 = 363,
+ F16MAT3 = 364,
+ F16MAT4 = 365,
+ F32VEC2 = 366,
+ F32VEC3 = 367,
+ F32VEC4 = 368,
+ F32MAT2 = 369,
+ F32MAT3 = 370,
+ F32MAT4 = 371,
+ F64VEC2 = 372,
+ F64VEC3 = 373,
+ F64VEC4 = 374,
+ F64MAT2 = 375,
+ F64MAT3 = 376,
+ F64MAT4 = 377,
+ DMAT2X2 = 378,
+ DMAT2X3 = 379,
+ DMAT2X4 = 380,
+ DMAT3X2 = 381,
+ DMAT3X3 = 382,
+ DMAT3X4 = 383,
+ DMAT4X2 = 384,
+ DMAT4X3 = 385,
+ DMAT4X4 = 386,
+ F16MAT2X2 = 387,
+ F16MAT2X3 = 388,
+ F16MAT2X4 = 389,
+ F16MAT3X2 = 390,
+ F16MAT3X3 = 391,
+ F16MAT3X4 = 392,
+ F16MAT4X2 = 393,
+ F16MAT4X3 = 394,
+ F16MAT4X4 = 395,
+ F32MAT2X2 = 396,
+ F32MAT2X3 = 397,
+ F32MAT2X4 = 398,
+ F32MAT3X2 = 399,
+ F32MAT3X3 = 400,
+ F32MAT3X4 = 401,
+ F32MAT4X2 = 402,
+ F32MAT4X3 = 403,
+ F32MAT4X4 = 404,
+ F64MAT2X2 = 405,
+ F64MAT2X3 = 406,
+ F64MAT2X4 = 407,
+ F64MAT3X2 = 408,
+ F64MAT3X3 = 409,
+ F64MAT3X4 = 410,
+ F64MAT4X2 = 411,
+ F64MAT4X3 = 412,
+ F64MAT4X4 = 413,
+ ATOMIC_UINT = 414,
+ ACCSTRUCTNV = 415,
+ FCOOPMATNV = 416,
+ ICOOPMATNV = 417,
+ UCOOPMATNV = 418,
+ SAMPLERCUBEARRAY = 419,
+ SAMPLERCUBEARRAYSHADOW = 420,
+ ISAMPLERCUBEARRAY = 421,
+ USAMPLERCUBEARRAY = 422,
+ SAMPLER1D = 423,
+ SAMPLER1DARRAY = 424,
+ SAMPLER1DARRAYSHADOW = 425,
+ ISAMPLER1D = 426,
+ SAMPLER1DSHADOW = 427,
+ SAMPLER2DRECT = 428,
+ SAMPLER2DRECTSHADOW = 429,
+ ISAMPLER2DRECT = 430,
+ USAMPLER2DRECT = 431,
+ SAMPLERBUFFER = 432,
+ ISAMPLERBUFFER = 433,
+ USAMPLERBUFFER = 434,
+ SAMPLER2DMS = 435,
+ ISAMPLER2DMS = 436,
+ USAMPLER2DMS = 437,
+ SAMPLER2DMSARRAY = 438,
+ ISAMPLER2DMSARRAY = 439,
+ USAMPLER2DMSARRAY = 440,
+ SAMPLEREXTERNALOES = 441,
+ SAMPLEREXTERNAL2DY2YEXT = 442,
+ ISAMPLER1DARRAY = 443,
+ USAMPLER1D = 444,
+ USAMPLER1DARRAY = 445,
+ F16SAMPLER1D = 446,
+ F16SAMPLER2D = 447,
+ F16SAMPLER3D = 448,
+ F16SAMPLER2DRECT = 449,
+ F16SAMPLERCUBE = 450,
+ F16SAMPLER1DARRAY = 451,
+ F16SAMPLER2DARRAY = 452,
+ F16SAMPLERCUBEARRAY = 453,
+ F16SAMPLERBUFFER = 454,
+ F16SAMPLER2DMS = 455,
+ F16SAMPLER2DMSARRAY = 456,
+ F16SAMPLER1DSHADOW = 457,
+ F16SAMPLER2DSHADOW = 458,
+ F16SAMPLER1DARRAYSHADOW = 459,
+ F16SAMPLER2DARRAYSHADOW = 460,
+ F16SAMPLER2DRECTSHADOW = 461,
+ F16SAMPLERCUBESHADOW = 462,
+ F16SAMPLERCUBEARRAYSHADOW = 463,
+ IMAGE1D = 464,
+ IIMAGE1D = 465,
+ UIMAGE1D = 466,
+ IMAGE2D = 467,
+ IIMAGE2D = 468,
+ UIMAGE2D = 469,
+ IMAGE3D = 470,
+ IIMAGE3D = 471,
+ UIMAGE3D = 472,
+ IMAGE2DRECT = 473,
+ IIMAGE2DRECT = 474,
+ UIMAGE2DRECT = 475,
+ IMAGECUBE = 476,
+ IIMAGECUBE = 477,
+ UIMAGECUBE = 478,
+ IMAGEBUFFER = 479,
+ IIMAGEBUFFER = 480,
+ UIMAGEBUFFER = 481,
+ IMAGE1DARRAY = 482,
+ IIMAGE1DARRAY = 483,
+ UIMAGE1DARRAY = 484,
+ IMAGE2DARRAY = 485,
+ IIMAGE2DARRAY = 486,
+ UIMAGE2DARRAY = 487,
+ IMAGECUBEARRAY = 488,
+ IIMAGECUBEARRAY = 489,
+ UIMAGECUBEARRAY = 490,
+ IMAGE2DMS = 491,
+ IIMAGE2DMS = 492,
+ UIMAGE2DMS = 493,
+ IMAGE2DMSARRAY = 494,
+ IIMAGE2DMSARRAY = 495,
+ UIMAGE2DMSARRAY = 496,
+ F16IMAGE1D = 497,
+ F16IMAGE2D = 498,
+ F16IMAGE3D = 499,
+ F16IMAGE2DRECT = 500,
+ F16IMAGECUBE = 501,
+ F16IMAGE1DARRAY = 502,
+ F16IMAGE2DARRAY = 503,
+ F16IMAGECUBEARRAY = 504,
+ F16IMAGEBUFFER = 505,
+ F16IMAGE2DMS = 506,
+ F16IMAGE2DMSARRAY = 507,
+ TEXTURECUBEARRAY = 508,
+ ITEXTURECUBEARRAY = 509,
+ UTEXTURECUBEARRAY = 510,
+ TEXTURE1D = 511,
+ ITEXTURE1D = 512,
+ UTEXTURE1D = 513,
+ TEXTURE1DARRAY = 514,
+ ITEXTURE1DARRAY = 515,
+ UTEXTURE1DARRAY = 516,
+ TEXTURE2DRECT = 517,
+ ITEXTURE2DRECT = 518,
+ UTEXTURE2DRECT = 519,
+ TEXTUREBUFFER = 520,
+ ITEXTUREBUFFER = 521,
+ UTEXTUREBUFFER = 522,
+ TEXTURE2DMS = 523,
+ ITEXTURE2DMS = 524,
+ UTEXTURE2DMS = 525,
+ TEXTURE2DMSARRAY = 526,
+ ITEXTURE2DMSARRAY = 527,
+ UTEXTURE2DMSARRAY = 528,
+ F16TEXTURE1D = 529,
+ F16TEXTURE2D = 530,
+ F16TEXTURE3D = 531,
+ F16TEXTURE2DRECT = 532,
+ F16TEXTURECUBE = 533,
+ F16TEXTURE1DARRAY = 534,
+ F16TEXTURE2DARRAY = 535,
+ F16TEXTURECUBEARRAY = 536,
+ F16TEXTUREBUFFER = 537,
+ F16TEXTURE2DMS = 538,
+ F16TEXTURE2DMSARRAY = 539,
+ SUBPASSINPUT = 540,
+ SUBPASSINPUTMS = 541,
+ ISUBPASSINPUT = 542,
+ ISUBPASSINPUTMS = 543,
+ USUBPASSINPUT = 544,
+ USUBPASSINPUTMS = 545,
+ F16SUBPASSINPUT = 546,
+ F16SUBPASSINPUTMS = 547,
+ LEFT_OP = 548,
+ RIGHT_OP = 549,
+ INC_OP = 550,
+ DEC_OP = 551,
+ LE_OP = 552,
+ GE_OP = 553,
+ EQ_OP = 554,
+ NE_OP = 555,
+ AND_OP = 556,
+ OR_OP = 557,
+ XOR_OP = 558,
+ MUL_ASSIGN = 559,
+ DIV_ASSIGN = 560,
+ ADD_ASSIGN = 561,
+ MOD_ASSIGN = 562,
+ LEFT_ASSIGN = 563,
+ RIGHT_ASSIGN = 564,
+ AND_ASSIGN = 565,
+ XOR_ASSIGN = 566,
+ OR_ASSIGN = 567,
+ SUB_ASSIGN = 568,
+ LEFT_PAREN = 569,
+ RIGHT_PAREN = 570,
+ LEFT_BRACKET = 571,
+ RIGHT_BRACKET = 572,
+ LEFT_BRACE = 573,
+ RIGHT_BRACE = 574,
+ DOT = 575,
+ COMMA = 576,
+ COLON = 577,
+ EQUAL = 578,
+ SEMICOLON = 579,
+ BANG = 580,
+ DASH = 581,
+ TILDE = 582,
+ PLUS = 583,
+ STAR = 584,
+ SLASH = 585,
+ PERCENT = 586,
+ LEFT_ANGLE = 587,
+ RIGHT_ANGLE = 588,
+ VERTICAL_BAR = 589,
+ CARET = 590,
+ AMPERSAND = 591,
+ QUESTION = 592,
+ INVARIANT = 593,
+ HIGH_PRECISION = 594,
+ MEDIUM_PRECISION = 595,
+ LOW_PRECISION = 596,
+ PRECISION = 597,
+ PACKED = 598,
+ RESOURCE = 599,
+ SUPERP = 600,
+ FLOATCONSTANT = 601,
+ INTCONSTANT = 602,
+ UINTCONSTANT = 603,
+ BOOLCONSTANT = 604,
+ IDENTIFIER = 605,
+ TYPE_NAME = 606,
+ CENTROID = 607,
+ IN = 608,
+ OUT = 609,
+ INOUT = 610,
+ STRUCT = 611,
+ VOID = 612,
+ WHILE = 613,
+ BREAK = 614,
+ CONTINUE = 615,
+ DO = 616,
+ ELSE = 617,
+ FOR = 618,
+ IF = 619,
+ DISCARD = 620,
+ RETURN = 621,
+ SWITCH = 622,
+ CASE = 623,
+ DEFAULT = 624,
+ UNIFORM = 625,
+ SHARED = 626,
+ BUFFER = 627,
+ FLAT = 628,
+ SMOOTH = 629,
+ LAYOUT = 630,
+ DOUBLECONSTANT = 631,
+ INT16CONSTANT = 632,
+ UINT16CONSTANT = 633,
+ FLOAT16CONSTANT = 634,
+ INT32CONSTANT = 635,
+ UINT32CONSTANT = 636,
+ INT64CONSTANT = 637,
+ UINT64CONSTANT = 638,
+ SUBROUTINE = 639,
+ DEMOTE = 640,
+ PAYLOADNV = 641,
+ PAYLOADINNV = 642,
+ HITATTRNV = 643,
+ CALLDATANV = 644,
+ CALLDATAINNV = 645,
+ PATCH = 646,
+ SAMPLE = 647,
+ NONUNIFORM = 648,
+ COHERENT = 649,
+ VOLATILE = 650,
+ RESTRICT = 651,
+ READONLY = 652,
+ WRITEONLY = 653,
+ DEVICECOHERENT = 654,
+ QUEUEFAMILYCOHERENT = 655,
+ WORKGROUPCOHERENT = 656,
+ SUBGROUPCOHERENT = 657,
+ NONPRIVATE = 658,
+ NOPERSPECTIVE = 659,
+ EXPLICITINTERPAMD = 660,
+ PERVERTEXNV = 661,
+ PERPRIMITIVENV = 662,
+ PERVIEWNV = 663,
+ PERTASKNV = 664,
+ PRECISE = 665
+ };
+#endif
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 96 "MachineIndependent/glslang.y" /* yacc.c:355 */
+
+ struct {
+ glslang::TSourceLoc loc;
+ union {
+ glslang::TString *string;
+ int i;
+ unsigned int u;
+ long long i64;
+ unsigned long long u64;
+ bool b;
+ double d;
+ };
+ glslang::TSymbol* symbol;
+ } lex;
+ struct {
+ glslang::TSourceLoc loc;
+ glslang::TOperator op;
+ union {
+ TIntermNode* intermNode;
+ glslang::TIntermNodePair nodePair;
+ glslang::TIntermTyped* intermTypedNode;
+ glslang::TAttributes* attributes;
+ };
+ union {
+ glslang::TPublicType type;
+ glslang::TFunction* function;
+ glslang::TParameter param;
+ glslang::TTypeLoc typeLine;
+ glslang::TTypeList* typeList;
+ glslang::TArraySizes* arraySizes;
+ glslang::TIdentifierList* identifierList;
+ };
+ glslang::TArraySizes* typeParameters;
+ } interm;
+
+#line 579 "MachineIndependent/glslang_tab.cpp" /* yacc.c:355 */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int yyparse (glslang::TParseContext* pParseContext);
+
+#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */
+
+/* Copy the second part of user declarations. */
+#line 132 "MachineIndependent/glslang.y" /* yacc.c:358 */
+
+
+/* windows only pragma */
+#ifdef _MSC_VER
+ #pragma warning(disable : 4065)
+ #pragma warning(disable : 4127)
+ #pragma warning(disable : 4244)
+#endif
+
+#define parseContext (*pParseContext)
+#define yyerror(context, msg) context->parserError(msg)
+
+extern int yylex(YYSTYPE*, TParseContext&);
+
+
+#line 610 "MachineIndependent/glslang_tab.cpp" /* yacc.c:358 */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+# define _Noreturn __declspec (noreturn)
+# else
+# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 386
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 9369
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 411
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 111
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 582
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 727
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 665
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
+static const yytype_uint16 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
+ 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+ 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
+ 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232, 233, 234,
+ 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
+ 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+ 255, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
+ 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
+ 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394,
+ 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
+ 405, 406, 407, 408, 409, 410
+};
+
+#if YYDEBUG
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 352, 352, 358, 361, 366, 369, 372, 376, 380,
+ 384, 388, 392, 396, 400, 404, 408, 416, 419, 422,
+ 425, 428, 433, 441, 448, 455, 461, 465, 472, 475,
+ 481, 488, 498, 506, 511, 539, 548, 554, 558, 562,
+ 582, 583, 584, 585, 591, 592, 597, 602, 611, 612,
+ 617, 625, 626, 632, 641, 642, 647, 652, 657, 665,
+ 666, 675, 687, 688, 697, 698, 707, 708, 717, 718,
+ 726, 727, 735, 736, 744, 745, 745, 763, 764, 780,
+ 784, 788, 792, 797, 801, 805, 809, 813, 817, 821,
+ 828, 831, 842, 849, 854, 859, 866, 870, 874, 878,
+ 883, 888, 897, 897, 908, 912, 919, 926, 929, 936,
+ 944, 964, 987, 1002, 1027, 1038, 1048, 1058, 1068, 1077,
+ 1080, 1084, 1088, 1093, 1101, 1108, 1113, 1118, 1123, 1132,
+ 1142, 1169, 1178, 1185, 1193, 1200, 1207, 1215, 1225, 1232,
+ 1243, 1249, 1252, 1259, 1263, 1267, 1276, 1286, 1289, 1300,
+ 1303, 1306, 1310, 1314, 1319, 1323, 1330, 1334, 1339, 1345,
+ 1351, 1358, 1363, 1371, 1377, 1389, 1403, 1409, 1414, 1422,
+ 1430, 1438, 1446, 1453, 1457, 1462, 1467, 1472, 1477, 1482,
+ 1486, 1490, 1494, 1498, 1504, 1515, 1522, 1525, 1534, 1539,
+ 1549, 1554, 1562, 1566, 1576, 1579, 1585, 1591, 1598, 1608,
+ 1612, 1616, 1620, 1625, 1629, 1634, 1639, 1644, 1649, 1654,
+ 1659, 1664, 1669, 1674, 1680, 1686, 1692, 1697, 1702, 1707,
+ 1712, 1717, 1722, 1727, 1732, 1737, 1742, 1747, 1753, 1758,
+ 1763, 1768, 1773, 1778, 1783, 1788, 1793, 1798, 1803, 1808,
+ 1813, 1819, 1825, 1831, 1837, 1843, 1849, 1855, 1861, 1867,
+ 1873, 1879, 1885, 1891, 1897, 1903, 1909, 1915, 1921, 1927,
+ 1933, 1939, 1945, 1951, 1957, 1963, 1969, 1975, 1981, 1987,
+ 1993, 1999, 2005, 2011, 2017, 2023, 2029, 2035, 2041, 2047,
+ 2053, 2059, 2065, 2071, 2077, 2083, 2089, 2095, 2101, 2107,
+ 2113, 2119, 2125, 2131, 2137, 2143, 2149, 2155, 2161, 2167,
+ 2173, 2179, 2185, 2191, 2197, 2203, 2209, 2215, 2221, 2227,
+ 2233, 2239, 2245, 2251, 2257, 2263, 2269, 2275, 2281, 2287,
+ 2293, 2299, 2305, 2311, 2317, 2321, 2326, 2332, 2337, 2342,
+ 2347, 2352, 2357, 2362, 2368, 2373, 2378, 2383, 2388, 2393,
+ 2399, 2405, 2411, 2417, 2423, 2429, 2435, 2441, 2447, 2453,
+ 2459, 2465, 2471, 2477, 2482, 2487, 2492, 2497, 2502, 2507,
+ 2513, 2518, 2523, 2528, 2533, 2538, 2543, 2548, 2554, 2559,
+ 2564, 2569, 2574, 2579, 2584, 2589, 2594, 2599, 2604, 2609,
+ 2614, 2619, 2624, 2630, 2635, 2640, 2646, 2652, 2657, 2662,
+ 2667, 2673, 2678, 2683, 2688, 2694, 2699, 2704, 2709, 2715,
+ 2720, 2725, 2730, 2736, 2742, 2748, 2754, 2759, 2765, 2771,
+ 2777, 2782, 2787, 2792, 2797, 2802, 2808, 2813, 2818, 2823,
+ 2829, 2834, 2839, 2844, 2850, 2855, 2860, 2865, 2871, 2876,
+ 2881, 2886, 2892, 2897, 2902, 2907, 2913, 2918, 2923, 2928,
+ 2934, 2939, 2944, 2949, 2955, 2960, 2965, 2970, 2976, 2981,
+ 2986, 2991, 2997, 3002, 3007, 3012, 3018, 3023, 3028, 3033,
+ 3039, 3044, 3049, 3054, 3060, 3065, 3070, 3075, 3081, 3086,
+ 3091, 3096, 3102, 3107, 3112, 3118, 3124, 3130, 3136, 3143,
+ 3150, 3156, 3162, 3168, 3174, 3180, 3186, 3193, 3198, 3214,
+ 3219, 3224, 3232, 3232, 3243, 3243, 3253, 3256, 3269, 3291,
+ 3318, 3322, 3328, 3333, 3344, 3348, 3354, 3365, 3368, 3375,
+ 3379, 3380, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3394,
+ 3400, 3409, 3410, 3414, 3410, 3426, 3427, 3431, 3431, 3438,
+ 3438, 3452, 3455, 3463, 3471, 3482, 3483, 3487, 3491, 3498,
+ 3505, 3509, 3517, 3521, 3534, 3538, 3545, 3545, 3565, 3568,
+ 3574, 3586, 3598, 3602, 3609, 3609, 3624, 3624, 3640, 3640,
+ 3661, 3664, 3670, 3673, 3679, 3683, 3690, 3695, 3700, 3707,
+ 3710, 3719, 3723, 3732, 3735, 3739, 3748, 3748, 3771, 3777,
+ 3780, 3785, 3788
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "CONST", "BOOL", "INT", "UINT", "FLOAT",
+ "BVEC2", "BVEC3", "BVEC4", "IVEC2", "IVEC3", "IVEC4", "UVEC2", "UVEC3",
+ "UVEC4", "VEC2", "VEC3", "VEC4", "MAT2", "MAT3", "MAT4", "MAT2X2",
+ "MAT2X3", "MAT2X4", "MAT3X2", "MAT3X3", "MAT3X4", "MAT4X2", "MAT4X3",
+ "MAT4X4", "SAMPLER2D", "SAMPLER3D", "SAMPLERCUBE", "SAMPLER2DSHADOW",
+ "SAMPLERCUBESHADOW", "SAMPLER2DARRAY", "SAMPLER2DARRAYSHADOW",
+ "ISAMPLER2D", "ISAMPLER3D", "ISAMPLERCUBE", "ISAMPLER2DARRAY",
+ "USAMPLER2D", "USAMPLER3D", "USAMPLERCUBE", "USAMPLER2DARRAY", "SAMPLER",
+ "SAMPLERSHADOW", "TEXTURE2D", "TEXTURE3D", "TEXTURECUBE",
+ "TEXTURE2DARRAY", "ITEXTURE2D", "ITEXTURE3D", "ITEXTURECUBE",
+ "ITEXTURE2DARRAY", "UTEXTURE2D", "UTEXTURE3D", "UTEXTURECUBE",
+ "UTEXTURE2DARRAY", "ATTRIBUTE", "VARYING", "FLOAT16_T", "FLOAT32_T",
+ "DOUBLE", "FLOAT64_T", "INT64_T", "UINT64_T", "INT32_T", "UINT32_T",
+ "INT16_T", "UINT16_T", "INT8_T", "UINT8_T", "I64VEC2", "I64VEC3",
+ "I64VEC4", "U64VEC2", "U64VEC3", "U64VEC4", "I32VEC2", "I32VEC3",
+ "I32VEC4", "U32VEC2", "U32VEC3", "U32VEC4", "I16VEC2", "I16VEC3",
+ "I16VEC4", "U16VEC2", "U16VEC3", "U16VEC4", "I8VEC2", "I8VEC3", "I8VEC4",
+ "U8VEC2", "U8VEC3", "U8VEC4", "DVEC2", "DVEC3", "DVEC4", "DMAT2",
+ "DMAT3", "DMAT4", "F16VEC2", "F16VEC3", "F16VEC4", "F16MAT2", "F16MAT3",
+ "F16MAT4", "F32VEC2", "F32VEC3", "F32VEC4", "F32MAT2", "F32MAT3",
+ "F32MAT4", "F64VEC2", "F64VEC3", "F64VEC4", "F64MAT2", "F64MAT3",
+ "F64MAT4", "DMAT2X2", "DMAT2X3", "DMAT2X4", "DMAT3X2", "DMAT3X3",
+ "DMAT3X4", "DMAT4X2", "DMAT4X3", "DMAT4X4", "F16MAT2X2", "F16MAT2X3",
+ "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", "F16MAT3X4", "F16MAT4X2",
+ "F16MAT4X3", "F16MAT4X4", "F32MAT2X2", "F32MAT2X3", "F32MAT2X4",
+ "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", "F32MAT4X3",
+ "F32MAT4X4", "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", "F64MAT3X2",
+ "F64MAT3X3", "F64MAT3X4", "F64MAT4X2", "F64MAT4X3", "F64MAT4X4",
+ "ATOMIC_UINT", "ACCSTRUCTNV", "FCOOPMATNV", "ICOOPMATNV", "UCOOPMATNV",
+ "SAMPLERCUBEARRAY", "SAMPLERCUBEARRAYSHADOW", "ISAMPLERCUBEARRAY",
+ "USAMPLERCUBEARRAY", "SAMPLER1D", "SAMPLER1DARRAY",
+ "SAMPLER1DARRAYSHADOW", "ISAMPLER1D", "SAMPLER1DSHADOW", "SAMPLER2DRECT",
+ "SAMPLER2DRECTSHADOW", "ISAMPLER2DRECT", "USAMPLER2DRECT",
+ "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLER2DMS",
+ "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", "ISAMPLER2DMSARRAY",
+ "USAMPLER2DMSARRAY", "SAMPLEREXTERNALOES", "SAMPLEREXTERNAL2DY2YEXT",
+ "ISAMPLER1DARRAY", "USAMPLER1D", "USAMPLER1DARRAY", "F16SAMPLER1D",
+ "F16SAMPLER2D", "F16SAMPLER3D", "F16SAMPLER2DRECT", "F16SAMPLERCUBE",
+ "F16SAMPLER1DARRAY", "F16SAMPLER2DARRAY", "F16SAMPLERCUBEARRAY",
+ "F16SAMPLERBUFFER", "F16SAMPLER2DMS", "F16SAMPLER2DMSARRAY",
+ "F16SAMPLER1DSHADOW", "F16SAMPLER2DSHADOW", "F16SAMPLER1DARRAYSHADOW",
+ "F16SAMPLER2DARRAYSHADOW", "F16SAMPLER2DRECTSHADOW",
+ "F16SAMPLERCUBESHADOW", "F16SAMPLERCUBEARRAYSHADOW", "IMAGE1D",
+ "IIMAGE1D", "UIMAGE1D", "IMAGE2D", "IIMAGE2D", "UIMAGE2D", "IMAGE3D",
+ "IIMAGE3D", "UIMAGE3D", "IMAGE2DRECT", "IIMAGE2DRECT", "UIMAGE2DRECT",
+ "IMAGECUBE", "IIMAGECUBE", "UIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER",
+ "UIMAGEBUFFER", "IMAGE1DARRAY", "IIMAGE1DARRAY", "UIMAGE1DARRAY",
+ "IMAGE2DARRAY", "IIMAGE2DARRAY", "UIMAGE2DARRAY", "IMAGECUBEARRAY",
+ "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", "IMAGE2DMS", "IIMAGE2DMS",
+ "UIMAGE2DMS", "IMAGE2DMSARRAY", "IIMAGE2DMSARRAY", "UIMAGE2DMSARRAY",
+ "F16IMAGE1D", "F16IMAGE2D", "F16IMAGE3D", "F16IMAGE2DRECT",
+ "F16IMAGECUBE", "F16IMAGE1DARRAY", "F16IMAGE2DARRAY",
+ "F16IMAGECUBEARRAY", "F16IMAGEBUFFER", "F16IMAGE2DMS",
+ "F16IMAGE2DMSARRAY", "TEXTURECUBEARRAY", "ITEXTURECUBEARRAY",
+ "UTEXTURECUBEARRAY", "TEXTURE1D", "ITEXTURE1D", "UTEXTURE1D",
+ "TEXTURE1DARRAY", "ITEXTURE1DARRAY", "UTEXTURE1DARRAY", "TEXTURE2DRECT",
+ "ITEXTURE2DRECT", "UTEXTURE2DRECT", "TEXTUREBUFFER", "ITEXTUREBUFFER",
+ "UTEXTUREBUFFER", "TEXTURE2DMS", "ITEXTURE2DMS", "UTEXTURE2DMS",
+ "TEXTURE2DMSARRAY", "ITEXTURE2DMSARRAY", "UTEXTURE2DMSARRAY",
+ "F16TEXTURE1D", "F16TEXTURE2D", "F16TEXTURE3D", "F16TEXTURE2DRECT",
+ "F16TEXTURECUBE", "F16TEXTURE1DARRAY", "F16TEXTURE2DARRAY",
+ "F16TEXTURECUBEARRAY", "F16TEXTUREBUFFER", "F16TEXTURE2DMS",
+ "F16TEXTURE2DMSARRAY", "SUBPASSINPUT", "SUBPASSINPUTMS", "ISUBPASSINPUT",
+ "ISUBPASSINPUTMS", "USUBPASSINPUT", "USUBPASSINPUTMS", "F16SUBPASSINPUT",
+ "F16SUBPASSINPUTMS", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP",
+ "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN",
+ "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN",
+ "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN",
+ "RIGHT_PAREN", "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_BRACE",
+ "RIGHT_BRACE", "DOT", "COMMA", "COLON", "EQUAL", "SEMICOLON", "BANG",
+ "DASH", "TILDE", "PLUS", "STAR", "SLASH", "PERCENT", "LEFT_ANGLE",
+ "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", "AMPERSAND", "QUESTION",
+ "INVARIANT", "HIGH_PRECISION", "MEDIUM_PRECISION", "LOW_PRECISION",
+ "PRECISION", "PACKED", "RESOURCE", "SUPERP", "FLOATCONSTANT",
+ "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT", "IDENTIFIER", "TYPE_NAME",
+ "CENTROID", "IN", "OUT", "INOUT", "STRUCT", "VOID", "WHILE", "BREAK",
+ "CONTINUE", "DO", "ELSE", "FOR", "IF", "DISCARD", "RETURN", "SWITCH",
+ "CASE", "DEFAULT", "UNIFORM", "SHARED", "BUFFER", "FLAT", "SMOOTH",
+ "LAYOUT", "DOUBLECONSTANT", "INT16CONSTANT", "UINT16CONSTANT",
+ "FLOAT16CONSTANT", "INT32CONSTANT", "UINT32CONSTANT", "INT64CONSTANT",
+ "UINT64CONSTANT", "SUBROUTINE", "DEMOTE", "PAYLOADNV", "PAYLOADINNV",
+ "HITATTRNV", "CALLDATANV", "CALLDATAINNV", "PATCH", "SAMPLE",
+ "NONUNIFORM", "COHERENT", "VOLATILE", "RESTRICT", "READONLY",
+ "WRITEONLY", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT",
+ "WORKGROUPCOHERENT", "SUBGROUPCOHERENT", "NONPRIVATE", "NOPERSPECTIVE",
+ "EXPLICITINTERPAMD", "PERVERTEXNV", "PERPRIMITIVENV", "PERVIEWNV",
+ "PERTASKNV", "PRECISE", "$accept", "variable_identifier",
+ "primary_expression", "postfix_expression", "integer_expression",
+ "function_call", "function_call_or_method", "function_call_generic",
+ "function_call_header_no_parameters",
+ "function_call_header_with_parameters", "function_call_header",
+ "function_identifier", "unary_expression", "unary_operator",
+ "multiplicative_expression", "additive_expression", "shift_expression",
+ "relational_expression", "equality_expression", "and_expression",
+ "exclusive_or_expression", "inclusive_or_expression",
+ "logical_and_expression", "logical_xor_expression",
+ "logical_or_expression", "conditional_expression", "$@1",
+ "assignment_expression", "assignment_operator", "expression",
+ "constant_expression", "declaration", "block_structure", "$@2",
+ "identifier_list", "function_prototype", "function_declarator",
+ "function_header_with_parameters", "function_header",
+ "parameter_declarator", "parameter_declaration",
+ "parameter_type_specifier", "init_declarator_list", "single_declaration",
+ "fully_specified_type", "invariant_qualifier", "interpolation_qualifier",
+ "layout_qualifier", "layout_qualifier_id_list", "layout_qualifier_id",
+ "precise_qualifier", "type_qualifier", "single_type_qualifier",
+ "storage_qualifier", "non_uniform_qualifier", "type_name_list",
+ "type_specifier", "array_specifier", "type_parameter_specifier_opt",
+ "type_parameter_specifier", "type_parameter_specifier_list",
+ "type_specifier_nonarray", "precision_qualifier", "struct_specifier",
+ "$@3", "$@4", "struct_declaration_list", "struct_declaration",
+ "struct_declarator_list", "struct_declarator", "initializer",
+ "initializer_list", "declaration_statement", "statement",
+ "simple_statement", "demote_statement", "compound_statement", "$@5",
+ "$@6", "statement_no_new_scope", "statement_scoped", "$@7", "$@8",
+ "compound_statement_no_new_scope", "statement_list",
+ "expression_statement", "selection_statement",
+ "selection_statement_nonattributed", "selection_rest_statement",
+ "condition", "switch_statement", "switch_statement_nonattributed", "$@9",
+ "switch_statement_list", "case_label", "iteration_statement",
+ "iteration_statement_nonattributed", "$@10", "$@11", "$@12",
+ "for_init_statement", "conditionopt", "for_rest_statement",
+ "jump_statement", "translation_unit", "external_declaration",
+ "function_definition", "$@13", "attribute", "attribute_list",
+ "single_attribute", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
+ 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
+ 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394,
+ 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
+ 405, 406, 407, 408, 409, 410, 411, 412, 413, 414,
+ 415, 416, 417, 418, 419, 420, 421, 422, 423, 424,
+ 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
+ 435, 436, 437, 438, 439, 440, 441, 442, 443, 444,
+ 445, 446, 447, 448, 449, 450, 451, 452, 453, 454,
+ 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,
+ 465, 466, 467, 468, 469, 470, 471, 472, 473, 474,
+ 475, 476, 477, 478, 479, 480, 481, 482, 483, 484,
+ 485, 486, 487, 488, 489, 490, 491, 492, 493, 494,
+ 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
+ 505, 506, 507, 508, 509, 510, 511, 512, 513, 514,
+ 515, 516, 517, 518, 519, 520, 521, 522, 523, 524,
+ 525, 526, 527, 528, 529, 530, 531, 532, 533, 534,
+ 535, 536, 537, 538, 539, 540, 541, 542, 543, 544,
+ 545, 546, 547, 548, 549, 550, 551, 552, 553, 554,
+ 555, 556, 557, 558, 559, 560, 561, 562, 563, 564,
+ 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
+ 575, 576, 577, 578, 579, 580, 581, 582, 583, 584,
+ 585, 586, 587, 588, 589, 590, 591, 592, 593, 594,
+ 595, 596, 597, 598, 599, 600, 601, 602, 603, 604,
+ 605, 606, 607, 608, 609, 610, 611, 612, 613, 614,
+ 615, 616, 617, 618, 619, 620, 621, 622, 623, 624,
+ 625, 626, 627, 628, 629, 630, 631, 632, 633, 634,
+ 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,
+ 645, 646, 647, 648, 649, 650, 651, 652, 653, 654,
+ 655, 656, 657, 658, 659, 660, 661, 662, 663, 664,
+ 665
+};
+# endif
+
+#define YYPACT_NINF -453
+
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-453)))
+
+#define YYTABLE_NINF -528
+
+#define yytable_value_is_error(Yytable_value) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int16 yypact[] =
+{
+ 3994, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, 97, -453, -453, -453,
+ -453, -453, 6, -453, -453, -453, -453, -453, -453, -307,
+ -241, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -3, 95, 36,
+ 125, 6034, 82, -453, -22, -453, -453, -453, -453, 4402,
+ -453, -453, -453, -453, 131, -453, -453, 730, -453, -453,
+ 11, -453, 153, -28, 127, -453, 7, -453, 157, -453,
+ 6034, -453, -453, -453, 6034, 129, 134, -453, 13, -453,
+ 73, -453, -453, 8391, 162, -453, -453, -453, 161, 6034,
+ -453, 163, -453, -309, -453, -453, 27, 6831, -453, 16,
+ 1138, -453, -453, -453, -453, 162, 23, -453, 7221, 49,
+ -453, 138, -453, 87, 8391, 8391, 8391, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, 68, -453, -453, -453,
+ 174, 60, 8781, 176, -453, 8391, -453, -453, -320, 175,
+ -453, 6034, 142, 4810, -453, 6034, 8391, -453, -28, -453,
+ 143, -453, -453, 119, 128, 32, 21, 38, 158, 160,
+ 165, 195, 194, 18, 183, 7611, -453, 185, 184, -453,
+ -453, 188, 180, 181, -453, 196, 197, 190, 8001, 198,
+ 8391, 187, 193, 122, -453, -453, 91, -453, 95, 204,
+ 205, -453, -453, -453, -453, -453, 1546, -453, -453, -453,
+ -453, -453, -453, -453, -453, -453, -353, 175, 7221, 69,
+ 7221, -453, -453, 7221, 6034, -453, 170, -453, -453, -453,
+ 78, -453, -453, 8391, 171, -453, -453, 8391, 207, -453,
+ -453, -453, 8391, -453, 142, 162, 93, -453, -453, -453,
+ 5218, -453, -453, -453, -453, 8391, 8391, 8391, 8391, 8391,
+ 8391, 8391, 8391, 8391, 8391, 8391, 8391, 8391, 8391, 8391,
+ 8391, 8391, 8391, 8391, -453, -453, -453, 206, 177, -453,
+ 1954, -453, -453, -453, 1954, -453, 8391, -453, -453, 100,
+ 8391, 144, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, -453, -453, -453, 8391, 8391, -453, -453, -453,
+ -453, -453, -453, -453, 7221, -453, 140, -453, 5626, -453,
+ -453, 209, 208, -453, -453, -453, 123, 175, 142, -453,
+ -453, -453, -453, -453, 119, 119, 128, 128, 32, 32,
+ 32, 32, 21, 21, 38, 158, 160, 165, 195, 194,
+ 8391, -453, 214, 56, -453, 1954, 3586, 172, 3178, 80,
+ -453, 81, -453, -453, -453, -453, -453, 6441, -453, -453,
+ -453, -453, 146, 8391, 215, 177, 212, 208, 186, 6034,
+ 219, 221, -453, -453, 3586, 220, -453, -453, -453, 8391,
+ 222, -453, -453, -453, 216, 2362, 8391, -453, 217, 227,
+ 182, 225, 2770, -453, 229, -453, -453, 7221, -453, -453,
+ -453, 89, 8391, 2362, 220, -453, -453, 1954, -453, 224,
+ 208, -453, -453, 1954, 226, -453, -453
+};
+
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint16 yydefact[] =
+{
+ 0, 156, 203, 201, 202, 200, 207, 208, 209, 210,
+ 211, 212, 213, 214, 215, 204, 205, 206, 216, 217,
+ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+ 327, 328, 329, 330, 331, 332, 333, 353, 354, 355,
+ 356, 357, 358, 359, 368, 381, 382, 369, 370, 372,
+ 371, 373, 374, 375, 376, 377, 378, 379, 380, 164,
+ 165, 229, 230, 228, 231, 238, 239, 236, 237, 234,
+ 235, 232, 233, 261, 262, 263, 273, 274, 275, 258,
+ 259, 260, 270, 271, 272, 255, 256, 257, 267, 268,
+ 269, 252, 253, 254, 264, 265, 266, 240, 241, 242,
+ 276, 277, 278, 243, 244, 245, 288, 289, 290, 246,
+ 247, 248, 300, 301, 302, 249, 250, 251, 312, 313,
+ 314, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+ 291, 292, 293, 294, 295, 296, 297, 298, 299, 303,
+ 304, 305, 306, 307, 308, 309, 310, 311, 315, 316,
+ 317, 318, 319, 320, 321, 322, 323, 325, 324, 484,
+ 485, 486, 337, 338, 361, 364, 326, 335, 336, 352,
+ 334, 383, 384, 387, 388, 389, 391, 392, 393, 395,
+ 396, 397, 399, 400, 474, 475, 360, 362, 363, 339,
+ 340, 341, 385, 342, 346, 347, 350, 390, 394, 398,
+ 343, 344, 348, 349, 386, 345, 351, 430, 432, 433,
+ 434, 436, 437, 438, 440, 441, 442, 444, 445, 446,
+ 448, 449, 450, 452, 453, 454, 456, 457, 458, 460,
+ 461, 462, 464, 465, 466, 468, 469, 470, 472, 473,
+ 431, 435, 439, 443, 447, 455, 459, 463, 451, 467,
+ 471, 365, 366, 367, 401, 410, 412, 406, 411, 413,
+ 414, 416, 417, 418, 420, 421, 422, 424, 425, 426,
+ 428, 429, 402, 403, 404, 415, 405, 407, 408, 409,
+ 419, 423, 427, 476, 477, 480, 481, 482, 483, 478,
+ 479, 575, 131, 489, 490, 491, 0, 488, 160, 158,
+ 159, 157, 0, 199, 161, 162, 163, 133, 132, 0,
+ 183, 169, 170, 168, 171, 172, 166, 167, 185, 173,
+ 179, 180, 181, 182, 174, 175, 176, 177, 178, 134,
+ 135, 136, 137, 138, 139, 146, 574, 0, 576, 0,
+ 108, 107, 0, 119, 124, 153, 152, 150, 154, 0,
+ 147, 149, 155, 129, 195, 151, 487, 0, 571, 573,
+ 0, 494, 0, 0, 0, 96, 0, 93, 0, 106,
+ 0, 115, 109, 117, 0, 118, 0, 94, 125, 99,
+ 0, 148, 130, 0, 188, 194, 1, 572, 0, 0,
+ 492, 143, 145, 0, 141, 186, 0, 0, 97, 0,
+ 0, 577, 110, 114, 116, 112, 120, 111, 0, 126,
+ 102, 0, 100, 0, 0, 0, 0, 42, 41, 43,
+ 40, 5, 6, 7, 8, 2, 15, 13, 14, 16,
+ 9, 10, 11, 12, 3, 17, 36, 19, 24, 25,
+ 0, 0, 29, 0, 197, 0, 35, 33, 0, 189,
+ 95, 0, 0, 0, 496, 0, 0, 140, 0, 184,
+ 0, 190, 44, 48, 51, 54, 59, 62, 64, 66,
+ 68, 70, 72, 74, 0, 0, 98, 0, 522, 531,
+ 535, 0, 0, 0, 556, 0, 0, 0, 0, 0,
+ 0, 0, 0, 44, 77, 90, 0, 509, 0, 155,
+ 129, 512, 533, 511, 519, 510, 0, 513, 514, 537,
+ 515, 544, 516, 517, 552, 518, 0, 113, 0, 121,
+ 0, 504, 128, 0, 0, 104, 0, 101, 37, 38,
+ 0, 21, 22, 0, 0, 27, 26, 0, 199, 30,
+ 32, 39, 0, 196, 0, 502, 0, 500, 495, 497,
+ 0, 92, 144, 142, 187, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 75, 191, 192, 0, 0, 521,
+ 0, 554, 567, 566, 0, 558, 0, 570, 568, 0,
+ 0, 0, 551, 520, 80, 81, 83, 82, 85, 86,
+ 87, 88, 89, 84, 79, 0, 0, 536, 532, 534,
+ 538, 545, 553, 123, 0, 507, 0, 127, 0, 105,
+ 4, 0, 23, 20, 31, 198, 0, 503, 0, 498,
+ 493, 45, 46, 47, 50, 49, 52, 53, 57, 58,
+ 55, 56, 60, 61, 63, 65, 67, 69, 71, 73,
+ 0, 193, 581, 0, 579, 523, 0, 0, 0, 0,
+ 569, 0, 550, 78, 91, 122, 505, 0, 103, 18,
+ 499, 501, 0, 0, 0, 0, 0, 542, 0, 0,
+ 0, 0, 561, 560, 563, 529, 546, 506, 508, 0,
+ 0, 578, 580, 524, 0, 0, 0, 562, 0, 0,
+ 541, 0, 0, 539, 0, 76, 582, 0, 526, 555,
+ 525, 0, 564, 0, 529, 528, 530, 548, 543, 0,
+ 565, 559, 540, 549, 0, 557, 547
+};
+
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -453, -453, -453, -453, -453, -453, -453, -453, -453, -453,
+ -453, -453, 8696, -453, -89, -88, -122, -84, -19, -18,
+ -17, -16, -20, -15, -453, -85, -453, -98, -453, -110,
+ -119, 2, -453, -453, -453, 4, -453, -453, -453, 189,
+ 191, 192, -453, -453, -339, -453, -453, -453, -453, 98,
+ -453, -37, -44, -453, 9, -453, 0, -71, -453, -453,
+ -453, -453, 261, -453, -453, -453, -452, -137, 20, -68,
+ -209, -453, -96, -198, -326, -453, -136, -453, -453, -146,
+ -144, -453, -453, 200, -265, -87, -453, 57, -453, -112,
+ -453, 59, -453, -453, -453, -453, 61, -453, -453, -453,
+ -453, -453, -453, -453, -453, 228, -453, -453, -453, -453,
+ -99
+};
+
+ /* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 434, 435, 436, 621, 437, 438, 439, 440, 441,
+ 442, 443, 493, 445, 463, 464, 465, 466, 467, 468,
+ 469, 470, 471, 472, 473, 494, 650, 495, 605, 496,
+ 552, 497, 337, 524, 413, 498, 339, 340, 341, 371,
+ 372, 373, 342, 343, 344, 345, 346, 347, 393, 394,
+ 348, 349, 350, 351, 446, 396, 447, 399, 384, 385,
+ 448, 354, 355, 356, 455, 389, 453, 454, 546, 547,
+ 522, 616, 501, 502, 503, 504, 505, 580, 676, 709,
+ 700, 701, 702, 710, 506, 507, 508, 509, 703, 680,
+ 510, 511, 704, 724, 512, 513, 514, 656, 584, 658,
+ 684, 698, 699, 515, 357, 358, 359, 368, 516, 653,
+ 654
+};
+
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+static const yytype_int16 yytable[] =
+{
+ 353, 542, 336, 550, 338, 481, 457, 363, 484, 352,
+ 485, 486, 458, 543, 489, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 618, 364, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+ 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
+ 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 374, 381, 530, 409, 609, 613,
+ 521, 615, 474, 449, 617, 655, 549, 678, 562, 563,
+ 573, 365, 391, 397, 361, 560, 561, 407, 378, 397,
+ 381, 398, 475, 374, 517, 519, 408, 566, 567, 397,
+ 476, 375, 459, 392, 539, 678, 518, 366, 460, 382,
+ 352, 369, 451, 564, 565, 574, 362, 353, 352, 336,
+ 388, 338, 297, 531, 532, 475, 352, 302, 303, 708,
+ 375, 551, 523, 674, 375, 536, 716, 675, 589, 352,
+ 591, 537, -34, 352, 533, 475, 657, 708, 534, 452,
+ 577, 410, 614, 620, 411, 685, 686, 412, 352, 606,
+ 500, 606, 606, 376, 719, 665, 377, 381, 526, 499,
+ 606, 527, 606, 549, 628, 607, 451, 629, 451, 367,
+ 521, 606, 521, 622, 660, 521, 594, 595, 596, 597,
+ 598, 599, 600, 601, 602, 603, 293, 294, 295, 624,
+ 638, 639, 640, 641, 628, 604, 370, 670, 555, 556,
+ 557, 544, 723, 452, 558, 452, 559, 609, 688, 666,
+ 352, 667, 352, 383, 352, 606, 662, 606, 689, 634,
+ 635, 390, 636, 637, 627, 400, 659, 395, 397, 405,
+ 661, 549, 642, 643, 406, 450, 456, 451, 525, 535,
+ 540, 475, 545, 554, 568, 569, 571, 572, 718, 570,
+ 575, 578, 581, 579, 582, 583, 500, 663, 664, 592,
+ 585, 586, 590, 451, 587, 499, 521, 593, -35, -33,
+ 619, 623, -28, 651, 452, 609, 669, 652, 673, 606,
+ 681, 693, 691, 352, 695, 696, 694, 706, -527, 707,
+ 672, 712, 713, 478, 714, 726, 677, 717, 725, 644,
+ 452, 645, 648, 646, 690, 647, 553, 360, 649, 352,
+ 671, 402, 682, 403, 626, 715, 404, 721, 401, 521,
+ 722, 683, 697, 610, 677, 611, 692, 612, 0, 0,
+ 500, 451, 0, 0, 500, 387, 711, 0, 551, 499,
+ 0, 705, 0, 499, 0, 0, 0, 0, 0, 0,
+ 0, 0, 720, 0, 0, 0, 0, 0, 0, 521,
+ 0, 0, 0, 0, 0, 0, 0, 0, 452, 679,
+ 0, 0, 0, 0, 0, 0, 0, 352, 0, 0,
+ 0, 0, 0, 0, 0, 381, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 679, 0, 0,
+ 0, 0, 0, 0, 0, 500, 500, 0, 500, 0,
+ 0, 0, 0, 0, 499, 499, 0, 499, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 382,
+ 0, 0, 0, 0, 500, 0, 0, 0, 352, 0,
+ 0, 0, 0, 499, 0, 500, 0, 0, 0, 0,
+ 0, 0, 500, 0, 499, 0, 0, 0, 0, 0,
+ 0, 499, 0, 500, 0, 0, 0, 500, 0, 0,
+ 0, 0, 499, 500, 0, 0, 499, 0, 0, 0,
+ 386, 0, 499, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
+ 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
+ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+ 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
+ 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 291, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 292, 293,
+ 294, 295, 296, 0, 0, 0, 0, 0, 0, 0,
+ 0, 297, 298, 299, 300, 301, 302, 303, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 304, 305, 306, 307, 308, 309, 0, 0, 0, 0,
+ 0, 0, 0, 0, 310, 0, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+ 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
+ 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
+ 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
+ 280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 0, 0, 414, 415, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 416, 0, 477, 0, 478, 479, 0, 0,
+ 0, 0, 480, 417, 418, 419, 420, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 292, 293, 294, 295,
+ 296, 0, 0, 0, 421, 422, 423, 424, 425, 297,
+ 298, 299, 300, 301, 302, 303, 481, 482, 483, 484,
+ 0, 485, 486, 487, 488, 489, 490, 491, 304, 305,
+ 306, 307, 308, 309, 426, 427, 428, 429, 430, 431,
+ 432, 433, 310, 492, 311, 312, 313, 314, 315, 316,
+ 317, 318, 319, 320, 321, 322, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, 334, 335, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+ 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+ 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+ 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 0,
+ 0, 414, 415, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 416, 0, 477, 0, 478, 608, 0, 0, 0, 0,
+ 480, 417, 418, 419, 420, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 292, 293, 294, 295, 296, 0,
+ 0, 0, 421, 422, 423, 424, 425, 297, 298, 299,
+ 300, 301, 302, 303, 481, 482, 483, 484, 0, 485,
+ 486, 487, 488, 489, 490, 491, 304, 305, 306, 307,
+ 308, 309, 426, 427, 428, 429, 430, 431, 432, 433,
+ 310, 492, 311, 312, 313, 314, 315, 316, 317, 318,
+ 319, 320, 321, 322, 323, 324, 325, 326, 327, 328,
+ 329, 330, 331, 332, 333, 334, 335, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+ 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
+ 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+ 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
+ 254, 255, 256, 257, 258, 259, 260, 261, 262, 263,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+ 274, 275, 276, 277, 278, 279, 280, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 0, 0, 414,
+ 415, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 416, 0,
+ 477, 0, 478, 0, 0, 0, 0, 0, 480, 417,
+ 418, 419, 420, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 292, 293, 294, 295, 296, 0, 0, 0,
+ 421, 422, 423, 424, 425, 297, 298, 299, 300, 301,
+ 302, 303, 481, 482, 483, 484, 0, 485, 486, 487,
+ 488, 489, 490, 491, 304, 305, 306, 307, 308, 309,
+ 426, 427, 428, 429, 430, 431, 432, 433, 310, 492,
+ 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
+ 331, 332, 333, 334, 335, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
+ 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
+ 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
+ 226, 227, 228, 229, 230, 231, 232, 233, 234, 235,
+ 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
+ 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
+ 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 0, 0, 414, 415, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 416, 0, 477, 0,
+ 400, 0, 0, 0, 0, 0, 480, 417, 418, 419,
+ 420, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 292, 293, 294, 295, 296, 0, 0, 0, 421, 422,
+ 423, 424, 425, 297, 298, 299, 300, 301, 302, 303,
+ 481, 482, 483, 484, 0, 485, 486, 487, 488, 489,
+ 490, 491, 304, 305, 306, 307, 308, 309, 426, 427,
+ 428, 429, 430, 431, 432, 433, 310, 492, 311, 312,
+ 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
+ 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+ 333, 334, 335, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
+ 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
+ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+ 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
+ 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 0, 0, 414, 415, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 416, 0, 477, 0, 0, 0,
+ 0, 0, 0, 0, 480, 417, 418, 419, 420, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 292, 293,
+ 294, 295, 296, 0, 0, 0, 421, 422, 423, 424,
+ 425, 297, 298, 299, 300, 301, 302, 303, 481, 482,
+ 483, 484, 0, 485, 486, 487, 488, 489, 490, 491,
+ 304, 305, 306, 307, 308, 309, 426, 427, 428, 429,
+ 430, 431, 432, 433, 310, 492, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+ 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
+ 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
+ 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
+ 280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 0, 0, 414, 415, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 416, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 480, 417, 418, 419, 420, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 292, 293, 294, 295,
+ 296, 0, 0, 0, 421, 422, 423, 424, 425, 297,
+ 298, 299, 300, 301, 302, 303, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 304, 305,
+ 306, 307, 308, 309, 426, 427, 428, 429, 430, 431,
+ 432, 433, 310, 0, 311, 312, 313, 314, 315, 316,
+ 317, 318, 319, 320, 321, 322, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, 334, 335, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+ 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+ 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+ 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 0,
+ 0, 414, 415, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 416, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 417, 418, 419, 420, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 292, 293, 294, 295, 0, 0,
+ 0, 0, 421, 422, 423, 424, 425, 297, 298, 299,
+ 300, 301, 302, 303, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 304, 305, 306, 307,
+ 308, 309, 426, 427, 428, 429, 430, 431, 432, 433,
+ 310, 0, 311, 312, 313, 314, 315, 316, 317, 318,
+ 319, 320, 321, 322, 323, 324, 325, 326, 327, 328,
+ 329, 330, 331, 332, 333, 334, 335, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+ 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
+ 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+ 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
+ 254, 255, 256, 257, 258, 259, 260, 261, 262, 263,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+ 274, 275, 276, 277, 278, 279, 280, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 291, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 292, 293, 294, 295, 296, 0, 0, 0,
+ 0, 0, 0, 0, 0, 297, 298, 299, 300, 301,
+ 302, 303, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 304, 305, 306, 307, 308, 309,
+ 0, 0, 0, 0, 0, 0, 0, 0, 310, 0,
+ 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
+ 331, 332, 333, 334, 335, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
+ 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
+ 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
+ 226, 227, 228, 229, 230, 231, 232, 233, 234, 235,
+ 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
+ 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
+ 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 379, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 292, 293, 294, 295, 0, 0, 0, 0, 0, 0,
+ 0, 0, 380, 297, 298, 299, 300, 301, 302, 303,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 304, 305, 306, 307, 308, 309, 0, 0,
+ 0, 0, 0, 0, 0, 0, 310, 0, 311, 312,
+ 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
+ 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+ 333, 334, 335, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
+ 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
+ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+ 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
+ 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 548,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 292, 293,
+ 294, 295, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 297, 298, 299, 300, 301, 302, 303, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 304, 305, 306, 307, 308, 309, 0, 0, 0, 0,
+ 0, 0, 0, 0, 310, 0, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+ 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
+ 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
+ 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
+ 280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 630, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 292, 293, 294, 295,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 297,
+ 298, 299, 300, 301, 302, 303, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 304, 305,
+ 306, 307, 308, 309, 0, 0, 0, 0, 0, 0,
+ 0, 0, 310, 0, 311, 312, 313, 314, 315, 316,
+ 317, 318, 319, 320, 321, 322, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, 334, 335, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+ 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+ 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+ 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 668, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 292, 293, 294, 295, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 297, 298, 299,
+ 300, 301, 302, 303, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 304, 305, 306, 307,
+ 308, 309, 0, 0, 0, 0, 0, 0, 0, 0,
+ 310, 0, 311, 312, 313, 314, 315, 316, 317, 318,
+ 319, 320, 321, 322, 323, 324, 325, 326, 327, 328,
+ 329, 330, 331, 332, 333, 334, 335, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+ 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
+ 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+ 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
+ 254, 255, 256, 257, 258, 259, 260, 261, 262, 263,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+ 274, 275, 276, 277, 278, 279, 280, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 292, 293, 294, 295, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 297, 298, 299, 300, 301,
+ 302, 303, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 304, 305, 306, 307, 308, 309,
+ 0, 0, 0, 0, 0, 0, 0, 0, 310, 0,
+ 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
+ 331, 332, 333, 334, 335, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 0, 0, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+ 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
+ 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 0, 0, 414, 415, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 416, 0, 0, 0, 520,
+ 687, 0, 0, 0, 0, 0, 417, 418, 419, 420,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 421, 422, 423,
+ 424, 425, 297, 0, 0, 0, 0, 302, 303, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 426, 427, 428,
+ 429, 430, 431, 432, 433, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 318, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 0, 0, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+ 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
+ 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 0, 0, 414, 415, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 416, 0, 0, 461, 0,
+ 0, 0, 0, 0, 0, 0, 417, 418, 419, 420,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 421, 422, 423,
+ 424, 425, 297, 0, 0, 0, 0, 302, 303, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 426, 427, 428,
+ 429, 430, 431, 432, 433, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 318, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 0, 0, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+ 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
+ 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 0, 0, 414, 415, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 416, 0, 0, 0, 520,
+ 0, 0, 0, 0, 0, 0, 417, 418, 419, 420,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 421, 422, 423,
+ 424, 425, 297, 0, 0, 0, 0, 302, 303, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 426, 427, 428,
+ 429, 430, 431, 432, 433, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 318, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 0, 0, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+ 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
+ 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 0, 0, 414, 415, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 416, 0, 0, 576, 0,
+ 0, 0, 0, 0, 0, 0, 417, 418, 419, 420,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 421, 422, 423,
+ 424, 425, 297, 0, 0, 0, 0, 302, 303, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 426, 427, 428,
+ 429, 430, 431, 432, 433, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 318, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 0, 0, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+ 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
+ 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 0, 0, 414, 415, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 416, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 588, 417, 418, 419, 420,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 421, 422, 423,
+ 424, 425, 297, 0, 0, 0, 0, 302, 303, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 426, 427, 428,
+ 429, 430, 431, 432, 433, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 318, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 0, 0, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+ 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
+ 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 0, 0, 414, 415, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 416, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 417, 418, 419, 420,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 421, 422, 423,
+ 424, 425, 297, 0, 0, 0, 0, 302, 303, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 426, 427, 428,
+ 429, 430, 431, 432, 433, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 318, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 0, 0, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+ 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
+ 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 0, 0, 414, 415, 0, 444,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 462, 0, 416, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 417, 418, 419, 420,
+ 528, 529, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 421, 422, 423,
+ 424, 425, 297, 0, 0, 0, 0, 302, 538, 0,
+ 0, 541, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 462, 0, 0, 0, 0, 426, 427, 428,
+ 429, 430, 431, 432, 433, 0, 0, 0, 0, 0,
+ 0, 462, 0, 0, 318, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 625, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 631, 632, 633, 462, 462, 462, 462, 462, 462,
+ 462, 462, 462, 462, 462, 462, 462, 462, 462, 462,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 462
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 0, 321, 0, 455, 0, 358, 315, 314, 361, 0,
+ 363, 364, 321, 333, 367, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 524, 314, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, 341, 349, 416, 378, 506, 518,
+ 408, 520, 397, 384, 523, 580, 453, 656, 297, 298,
+ 302, 324, 350, 316, 318, 293, 294, 314, 350, 316,
+ 374, 324, 316, 370, 405, 406, 323, 299, 300, 316,
+ 324, 341, 315, 371, 442, 684, 323, 350, 321, 349,
+ 341, 315, 389, 332, 333, 337, 350, 357, 349, 357,
+ 360, 357, 351, 295, 296, 316, 357, 356, 357, 695,
+ 370, 456, 323, 317, 374, 315, 702, 321, 488, 370,
+ 490, 321, 314, 374, 316, 316, 584, 713, 320, 389,
+ 475, 318, 323, 315, 321, 315, 315, 324, 389, 321,
+ 400, 321, 321, 321, 315, 614, 324, 451, 321, 400,
+ 321, 324, 321, 550, 321, 324, 453, 324, 455, 324,
+ 518, 321, 520, 533, 324, 523, 304, 305, 306, 307,
+ 308, 309, 310, 311, 312, 313, 339, 340, 341, 537,
+ 562, 563, 564, 565, 321, 323, 321, 324, 329, 330,
+ 331, 451, 717, 453, 326, 455, 328, 655, 667, 319,
+ 451, 321, 453, 332, 455, 321, 322, 321, 322, 558,
+ 559, 318, 560, 561, 545, 318, 586, 350, 316, 350,
+ 590, 618, 566, 567, 350, 324, 323, 524, 350, 315,
+ 314, 316, 350, 350, 336, 335, 301, 303, 707, 334,
+ 317, 316, 314, 319, 324, 324, 506, 605, 606, 322,
+ 314, 314, 314, 550, 324, 506, 614, 324, 314, 314,
+ 350, 350, 315, 317, 524, 723, 317, 350, 314, 321,
+ 358, 319, 317, 524, 315, 314, 350, 315, 318, 323,
+ 650, 324, 315, 318, 362, 319, 656, 318, 324, 568,
+ 550, 569, 572, 570, 673, 571, 458, 296, 573, 550,
+ 628, 370, 658, 374, 544, 701, 374, 713, 368, 667,
+ 714, 658, 684, 516, 684, 516, 675, 516, -1, -1,
+ 580, 618, -1, -1, 584, 357, 696, -1, 673, 580,
+ -1, 689, -1, 584, -1, -1, -1, -1, -1, -1,
+ -1, -1, 712, -1, -1, -1, -1, -1, -1, 707,
+ -1, -1, -1, -1, -1, -1, -1, -1, 618, 656,
+ -1, -1, -1, -1, -1, -1, -1, 618, -1, -1,
+ -1, -1, -1, -1, -1, 679, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 684, -1, -1,
+ -1, -1, -1, -1, -1, 655, 656, -1, 658, -1,
+ -1, -1, -1, -1, 655, 656, -1, 658, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 679,
+ -1, -1, -1, -1, 684, -1, -1, -1, 679, -1,
+ -1, -1, -1, 684, -1, 695, -1, -1, -1, -1,
+ -1, -1, 702, -1, 695, -1, -1, -1, -1, -1,
+ -1, 702, -1, 713, -1, -1, -1, 717, -1, -1,
+ -1, -1, 713, 723, -1, -1, 717, -1, -1, -1,
+ 0, -1, 723, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+ 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
+ 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
+ 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
+ 280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 324, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 338, 339,
+ 340, 341, 342, -1, -1, -1, -1, -1, -1, -1,
+ -1, 351, 352, 353, 354, 355, 356, 357, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 370, 371, 372, 373, 374, 375, -1, -1, -1, -1,
+ -1, -1, -1, -1, 384, -1, 386, 387, 388, 389,
+ 390, 391, 392, 393, 394, 395, 396, 397, 398, 399,
+ 400, 401, 402, 403, 404, 405, 406, 407, 408, 409,
+ 410, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+ 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+ 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+ 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, -1, -1, 295, 296, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 314, -1, 316, -1, 318, 319, -1, -1,
+ -1, -1, 324, 325, 326, 327, 328, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 338, 339, 340, 341,
+ 342, -1, -1, -1, 346, 347, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, 358, 359, 360, 361,
+ -1, 363, 364, 365, 366, 367, 368, 369, 370, 371,
+ 372, 373, 374, 375, 376, 377, 378, 379, 380, 381,
+ 382, 383, 384, 385, 386, 387, 388, 389, 390, 391,
+ 392, 393, 394, 395, 396, 397, 398, 399, 400, 401,
+ 402, 403, 404, 405, 406, 407, 408, 409, 410, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+ 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
+ 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+ 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
+ 254, 255, 256, 257, 258, 259, 260, 261, 262, 263,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+ 274, 275, 276, 277, 278, 279, 280, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 291, 292, -1,
+ -1, 295, 296, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 314, -1, 316, -1, 318, 319, -1, -1, -1, -1,
+ 324, 325, 326, 327, 328, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 338, 339, 340, 341, 342, -1,
+ -1, -1, 346, 347, 348, 349, 350, 351, 352, 353,
+ 354, 355, 356, 357, 358, 359, 360, 361, -1, 363,
+ 364, 365, 366, 367, 368, 369, 370, 371, 372, 373,
+ 374, 375, 376, 377, 378, 379, 380, 381, 382, 383,
+ 384, 385, 386, 387, 388, 389, 390, 391, 392, 393,
+ 394, 395, 396, 397, 398, 399, 400, 401, 402, 403,
+ 404, 405, 406, 407, 408, 409, 410, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
+ 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
+ 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
+ 226, 227, 228, 229, 230, 231, 232, 233, 234, 235,
+ 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
+ 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
+ 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, -1, -1, 295,
+ 296, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 314, -1,
+ 316, -1, 318, -1, -1, -1, -1, -1, 324, 325,
+ 326, 327, 328, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 338, 339, 340, 341, 342, -1, -1, -1,
+ 346, 347, 348, 349, 350, 351, 352, 353, 354, 355,
+ 356, 357, 358, 359, 360, 361, -1, 363, 364, 365,
+ 366, 367, 368, 369, 370, 371, 372, 373, 374, 375,
+ 376, 377, 378, 379, 380, 381, 382, 383, 384, 385,
+ 386, 387, 388, 389, 390, 391, 392, 393, 394, 395,
+ 396, 397, 398, 399, 400, 401, 402, 403, 404, 405,
+ 406, 407, 408, 409, 410, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
+ 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
+ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+ 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
+ 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, -1, -1, 295, 296, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 314, -1, 316, -1,
+ 318, -1, -1, -1, -1, -1, 324, 325, 326, 327,
+ 328, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 338, 339, 340, 341, 342, -1, -1, -1, 346, 347,
+ 348, 349, 350, 351, 352, 353, 354, 355, 356, 357,
+ 358, 359, 360, 361, -1, 363, 364, 365, 366, 367,
+ 368, 369, 370, 371, 372, 373, 374, 375, 376, 377,
+ 378, 379, 380, 381, 382, 383, 384, 385, 386, 387,
+ 388, 389, 390, 391, 392, 393, 394, 395, 396, 397,
+ 398, 399, 400, 401, 402, 403, 404, 405, 406, 407,
+ 408, 409, 410, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+ 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
+ 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
+ 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
+ 280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, -1, -1, 295, 296, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 314, -1, 316, -1, -1, -1,
+ -1, -1, -1, -1, 324, 325, 326, 327, 328, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 338, 339,
+ 340, 341, 342, -1, -1, -1, 346, 347, 348, 349,
+ 350, 351, 352, 353, 354, 355, 356, 357, 358, 359,
+ 360, 361, -1, 363, 364, 365, 366, 367, 368, 369,
+ 370, 371, 372, 373, 374, 375, 376, 377, 378, 379,
+ 380, 381, 382, 383, 384, 385, 386, 387, 388, 389,
+ 390, 391, 392, 393, 394, 395, 396, 397, 398, 399,
+ 400, 401, 402, 403, 404, 405, 406, 407, 408, 409,
+ 410, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+ 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+ 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+ 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, -1, -1, 295, 296, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 314, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 324, 325, 326, 327, 328, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 338, 339, 340, 341,
+ 342, -1, -1, -1, 346, 347, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 370, 371,
+ 372, 373, 374, 375, 376, 377, 378, 379, 380, 381,
+ 382, 383, 384, -1, 386, 387, 388, 389, 390, 391,
+ 392, 393, 394, 395, 396, 397, 398, 399, 400, 401,
+ 402, 403, 404, 405, 406, 407, 408, 409, 410, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+ 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
+ 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+ 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
+ 254, 255, 256, 257, 258, 259, 260, 261, 262, 263,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+ 274, 275, 276, 277, 278, 279, 280, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 291, 292, -1,
+ -1, 295, 296, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 314, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 325, 326, 327, 328, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 338, 339, 340, 341, -1, -1,
+ -1, -1, 346, 347, 348, 349, 350, 351, 352, 353,
+ 354, 355, 356, 357, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 370, 371, 372, 373,
+ 374, 375, 376, 377, 378, 379, 380, 381, 382, 383,
+ 384, -1, 386, 387, 388, 389, 390, 391, 392, 393,
+ 394, 395, 396, 397, 398, 399, 400, 401, 402, 403,
+ 404, 405, 406, 407, 408, 409, 410, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
+ 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
+ 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
+ 226, 227, 228, 229, 230, 231, 232, 233, 234, 235,
+ 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
+ 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
+ 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 324, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 338, 339, 340, 341, 342, -1, -1, -1,
+ -1, -1, -1, -1, -1, 351, 352, 353, 354, 355,
+ 356, 357, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 370, 371, 372, 373, 374, 375,
+ -1, -1, -1, -1, -1, -1, -1, -1, 384, -1,
+ 386, 387, 388, 389, 390, 391, 392, 393, 394, 395,
+ 396, 397, 398, 399, 400, 401, 402, 403, 404, 405,
+ 406, 407, 408, 409, 410, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
+ 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
+ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+ 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
+ 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 324, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 338, 339, 340, 341, -1, -1, -1, -1, -1, -1,
+ -1, -1, 350, 351, 352, 353, 354, 355, 356, 357,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 370, 371, 372, 373, 374, 375, -1, -1,
+ -1, -1, -1, -1, -1, -1, 384, -1, 386, 387,
+ 388, 389, 390, 391, 392, 393, 394, 395, 396, 397,
+ 398, 399, 400, 401, 402, 403, 404, 405, 406, 407,
+ 408, 409, 410, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+ 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
+ 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
+ 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
+ 280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 319,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 338, 339,
+ 340, 341, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 351, 352, 353, 354, 355, 356, 357, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 370, 371, 372, 373, 374, 375, -1, -1, -1, -1,
+ -1, -1, -1, -1, 384, -1, 386, 387, 388, 389,
+ 390, 391, 392, 393, 394, 395, 396, 397, 398, 399,
+ 400, 401, 402, 403, 404, 405, 406, 407, 408, 409,
+ 410, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+ 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+ 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+ 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 319, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 338, 339, 340, 341,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 351,
+ 352, 353, 354, 355, 356, 357, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 370, 371,
+ 372, 373, 374, 375, -1, -1, -1, -1, -1, -1,
+ -1, -1, 384, -1, 386, 387, 388, 389, 390, 391,
+ 392, 393, 394, 395, 396, 397, 398, 399, 400, 401,
+ 402, 403, 404, 405, 406, 407, 408, 409, 410, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+ 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
+ 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+ 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
+ 254, 255, 256, 257, 258, 259, 260, 261, 262, 263,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+ 274, 275, 276, 277, 278, 279, 280, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 291, 292, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 319, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 338, 339, 340, 341, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 351, 352, 353,
+ 354, 355, 356, 357, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 370, 371, 372, 373,
+ 374, 375, -1, -1, -1, -1, -1, -1, -1, -1,
+ 384, -1, 386, 387, 388, 389, 390, 391, 392, 393,
+ 394, 395, 396, 397, 398, 399, 400, 401, 402, 403,
+ 404, 405, 406, 407, 408, 409, 410, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
+ 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
+ 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
+ 226, 227, 228, 229, 230, 231, 232, 233, 234, 235,
+ 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
+ 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
+ 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 338, 339, 340, 341, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 351, 352, 353, 354, 355,
+ 356, 357, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 370, 371, 372, 373, 374, 375,
+ -1, -1, -1, -1, -1, -1, -1, -1, 384, -1,
+ 386, 387, 388, 389, 390, 391, 392, 393, 394, 395,
+ 396, 397, 398, 399, 400, 401, 402, 403, 404, 405,
+ 406, 407, 408, 409, 410, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, -1, -1, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, -1, -1, 295, 296, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 314, -1, -1, -1, 318,
+ 319, -1, -1, -1, -1, -1, 325, 326, 327, 328,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 346, 347, 348,
+ 349, 350, 351, -1, -1, -1, -1, 356, 357, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 376, 377, 378,
+ 379, 380, 381, 382, 383, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 393, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, -1, -1, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, -1, -1, 295, 296, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 314, -1, -1, 317, -1,
+ -1, -1, -1, -1, -1, -1, 325, 326, 327, 328,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 346, 347, 348,
+ 349, 350, 351, -1, -1, -1, -1, 356, 357, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 376, 377, 378,
+ 379, 380, 381, 382, 383, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 393, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, -1, -1, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, -1, -1, 295, 296, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 314, -1, -1, -1, 318,
+ -1, -1, -1, -1, -1, -1, 325, 326, 327, 328,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 346, 347, 348,
+ 349, 350, 351, -1, -1, -1, -1, 356, 357, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 376, 377, 378,
+ 379, 380, 381, 382, 383, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 393, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, -1, -1, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, -1, -1, 295, 296, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 314, -1, -1, 317, -1,
+ -1, -1, -1, -1, -1, -1, 325, 326, 327, 328,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 346, 347, 348,
+ 349, 350, 351, -1, -1, -1, -1, 356, 357, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 376, 377, 378,
+ 379, 380, 381, 382, 383, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 393, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, -1, -1, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, -1, -1, 295, 296, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 314, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 324, 325, 326, 327, 328,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 346, 347, 348,
+ 349, 350, 351, -1, -1, -1, -1, 356, 357, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 376, 377, 378,
+ 379, 380, 381, 382, 383, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 393, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, -1, -1, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, -1, -1, 295, 296, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 314, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 325, 326, 327, 328,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 346, 347, 348,
+ 349, 350, 351, -1, -1, -1, -1, 356, 357, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 376, 377, 378,
+ 379, 380, 381, 382, 383, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 393, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, -1, -1, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, -1, -1, 295, 296, -1, 383,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 397, -1, 314, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 325, 326, 327, 328,
+ 414, 415, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 346, 347, 348,
+ 349, 350, 351, -1, -1, -1, -1, 356, 357, -1,
+ -1, 445, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 456, -1, -1, -1, -1, 376, 377, 378,
+ 379, 380, 381, 382, 383, -1, -1, -1, -1, -1,
+ -1, 475, -1, -1, 393, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 542, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 555, 556, 557, 558, 559, 560, 561, 562, 563,
+ 564, 565, 566, 567, 568, 569, 570, 571, 572, 573,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 673
+};
+
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint16 yystos[] =
+{
+ 0, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+ 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+ 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+ 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 324, 338, 339, 340, 341, 342, 351, 352, 353,
+ 354, 355, 356, 357, 370, 371, 372, 373, 374, 375,
+ 384, 386, 387, 388, 389, 390, 391, 392, 393, 394,
+ 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
+ 405, 406, 407, 408, 409, 410, 442, 443, 446, 447,
+ 448, 449, 453, 454, 455, 456, 457, 458, 461, 462,
+ 463, 464, 465, 467, 472, 473, 474, 515, 516, 517,
+ 473, 318, 350, 314, 314, 324, 350, 324, 518, 315,
+ 321, 450, 451, 452, 462, 467, 321, 324, 350, 324,
+ 350, 463, 467, 332, 469, 470, 0, 516, 467, 476,
+ 318, 350, 371, 459, 460, 350, 466, 316, 324, 468,
+ 318, 494, 451, 450, 452, 350, 350, 314, 323, 468,
+ 318, 321, 324, 445, 295, 296, 314, 325, 326, 327,
+ 328, 346, 347, 348, 349, 350, 376, 377, 378, 379,
+ 380, 381, 382, 383, 412, 413, 414, 416, 417, 418,
+ 419, 420, 421, 422, 423, 424, 465, 467, 471, 468,
+ 324, 462, 467, 477, 478, 475, 323, 315, 321, 315,
+ 321, 317, 423, 425, 426, 427, 428, 429, 430, 431,
+ 432, 433, 434, 435, 436, 316, 324, 316, 318, 319,
+ 324, 358, 359, 360, 361, 363, 364, 365, 366, 367,
+ 368, 369, 385, 423, 436, 438, 440, 442, 446, 465,
+ 467, 483, 484, 485, 486, 487, 495, 496, 497, 498,
+ 501, 502, 505, 506, 507, 514, 519, 468, 323, 468,
+ 318, 438, 481, 323, 444, 350, 321, 324, 423, 423,
+ 440, 295, 296, 316, 320, 315, 315, 321, 357, 438,
+ 314, 423, 321, 333, 467, 350, 479, 480, 319, 478,
+ 477, 436, 441, 460, 350, 329, 330, 331, 326, 328,
+ 293, 294, 297, 298, 332, 333, 299, 300, 336, 335,
+ 334, 301, 303, 302, 337, 317, 317, 436, 316, 319,
+ 488, 314, 324, 324, 509, 314, 314, 324, 324, 440,
+ 314, 440, 322, 324, 304, 305, 306, 307, 308, 309,
+ 310, 311, 312, 313, 323, 439, 321, 324, 319, 484,
+ 498, 502, 507, 481, 323, 481, 482, 481, 477, 350,
+ 315, 415, 440, 350, 438, 423, 479, 468, 321, 324,
+ 319, 423, 423, 423, 425, 425, 426, 426, 427, 427,
+ 427, 427, 428, 428, 429, 430, 431, 432, 433, 434,
+ 437, 317, 350, 520, 521, 495, 508, 484, 510, 440,
+ 324, 440, 322, 438, 438, 481, 319, 321, 319, 317,
+ 324, 480, 440, 314, 317, 321, 489, 440, 455, 462,
+ 500, 358, 483, 496, 511, 315, 315, 319, 481, 322,
+ 441, 317, 521, 319, 350, 315, 314, 500, 512, 513,
+ 491, 492, 493, 499, 503, 438, 315, 323, 485, 490,
+ 494, 440, 324, 315, 362, 487, 485, 318, 481, 315,
+ 440, 490, 491, 495, 504, 324, 319
+};
+
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint16 yyr1[] =
+{
+ 0, 411, 412, 413, 413, 413, 413, 413, 413, 413,
+ 413, 413, 413, 413, 413, 413, 413, 414, 414, 414,
+ 414, 414, 414, 415, 416, 417, 418, 418, 419, 419,
+ 420, 420, 421, 422, 422, 422, 423, 423, 423, 423,
+ 424, 424, 424, 424, 425, 425, 425, 425, 426, 426,
+ 426, 427, 427, 427, 428, 428, 428, 428, 428, 429,
+ 429, 429, 430, 430, 431, 431, 432, 432, 433, 433,
+ 434, 434, 435, 435, 436, 437, 436, 438, 438, 439,
+ 439, 439, 439, 439, 439, 439, 439, 439, 439, 439,
+ 440, 440, 441, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 444, 443, 445, 445, 446, 447, 447, 448,
+ 448, 449, 450, 450, 451, 451, 451, 451, 452, 453,
+ 453, 453, 453, 453, 454, 454, 454, 454, 454, 455,
+ 455, 456, 457, 457, 457, 457, 457, 457, 457, 457,
+ 458, 459, 459, 460, 460, 460, 461, 462, 462, 463,
+ 463, 463, 463, 463, 463, 463, 464, 464, 464, 464,
+ 464, 464, 464, 464, 464, 464, 464, 464, 464, 464,
+ 464, 464, 464, 464, 464, 464, 464, 464, 464, 464,
+ 464, 464, 464, 464, 464, 465, 466, 466, 467, 467,
+ 468, 468, 468, 468, 469, 469, 470, 471, 471, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 473,
+ 473, 473, 475, 474, 476, 474, 477, 477, 478, 478,
+ 479, 479, 480, 480, 481, 481, 481, 482, 482, 483,
+ 484, 484, 485, 485, 485, 485, 485, 485, 485, 485,
+ 486, 487, 488, 489, 487, 490, 490, 492, 491, 493,
+ 491, 494, 494, 495, 495, 496, 496, 497, 497, 498,
+ 499, 499, 500, 500, 501, 501, 503, 502, 504, 504,
+ 505, 505, 506, 506, 508, 507, 509, 507, 510, 507,
+ 511, 511, 512, 512, 513, 513, 514, 514, 514, 514,
+ 514, 515, 515, 516, 516, 516, 518, 517, 519, 520,
+ 520, 521, 521
+};
+
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 1, 3, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 4, 1,
+ 3, 2, 2, 1, 1, 1, 2, 2, 2, 1,
+ 2, 3, 2, 1, 1, 1, 1, 2, 2, 2,
+ 1, 1, 1, 1, 1, 3, 3, 3, 1, 3,
+ 3, 1, 3, 3, 1, 3, 3, 3, 3, 1,
+ 3, 3, 1, 3, 1, 3, 1, 3, 1, 3,
+ 1, 3, 1, 3, 1, 0, 6, 1, 3, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 3, 1, 2, 2, 4, 2, 3, 4, 2,
+ 3, 4, 0, 6, 2, 3, 2, 1, 1, 2,
+ 3, 3, 2, 3, 2, 1, 2, 1, 1, 1,
+ 3, 4, 6, 5, 1, 2, 3, 5, 4, 1,
+ 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 4, 1, 3, 1, 3, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 4, 1, 1, 3, 2, 3,
+ 2, 3, 3, 4, 1, 0, 3, 1, 3, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 6, 0, 5, 1, 2, 3, 4,
+ 1, 3, 1, 2, 1, 3, 4, 1, 3, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 0, 0, 5, 1, 1, 0, 2, 0,
+ 2, 2, 3, 1, 2, 1, 2, 1, 2, 5,
+ 3, 1, 1, 4, 1, 2, 0, 8, 0, 1,
+ 3, 2, 1, 2, 0, 6, 0, 8, 0, 7,
+ 1, 1, 1, 0, 2, 3, 2, 2, 2, 3,
+ 2, 1, 2, 1, 1, 1, 0, 3, 5, 1,
+ 3, 1, 4
+};
+
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (pParseContext, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (0)
+
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, pParseContext); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext)
+{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ YYUSE (pParseContext);
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext)
+{
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, pParseContext);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, glslang::TParseContext* pParseContext)
+{
+ unsigned long int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , pParseContext);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, Rule, pParseContext); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
+
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
+ }
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, glslang::TParseContext* pParseContext)
+{
+ YYUSE (yyvaluep);
+ YYUSE (pParseContext);
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YYUSE (yytype);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+int
+yyparse (glslang::TParseContext* pParseContext)
+{
+/* The lookahead symbol. */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol. */
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
+
+ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = yylex (&yylval, parseContext);
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ '$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 352 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleVariable((yyvsp[0].lex).loc, (yyvsp[0].lex).symbol, (yyvsp[0].lex).string);
+ }
+#line 4172 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 3:
+#line 358 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 4180 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 4:
+#line 361 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode);
+ if ((yyval.interm.intermTypedNode)->getAsConstantUnion())
+ (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression();
+ }
+#line 4190 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 5:
+#line 366 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true);
+ }
+#line 4198 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 6:
+#line 369 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true);
+ }
+#line 4206 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 7:
+#line 372 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true);
+ }
+#line 4215 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 8:
+#line 376 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true);
+ }
+#line 4223 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 9:
+#line 380 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true);
+ }
+#line 4232 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 10:
+#line 384 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true);
+ }
+#line 4241 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 11:
+#line 388 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i64, (yyvsp[0].lex).loc, true);
+ }
+#line 4250 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 12:
+#line 392 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u64, (yyvsp[0].lex).loc, true);
+ }
+#line 4259 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 13:
+#line 396 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit integer literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((short)(yyvsp[0].lex).i, (yyvsp[0].lex).loc, true);
+ }
+#line 4268 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 14:
+#line 400 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((unsigned short)(yyvsp[0].lex).u, (yyvsp[0].lex).loc, true);
+ }
+#line 4277 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 15:
+#line 404 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double literal");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtDouble, (yyvsp[0].lex).loc, true);
+ }
+#line 4286 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 16:
+#line 408 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat16, (yyvsp[0].lex).loc, true);
+ }
+#line 4295 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 17:
+#line 416 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 4303 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 18:
+#line 419 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBracketDereference((yyvsp[-2].lex).loc, (yyvsp[-3].interm.intermTypedNode), (yyvsp[-1].interm.intermTypedNode));
+ }
+#line 4311 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 19:
+#line 422 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 4319 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 20:
+#line 425 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleDotDereference((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode), *(yyvsp[0].lex).string);
+ }
+#line 4327 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 21:
+#line 428 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode));
+ parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "++", (yyvsp[-1].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "++", EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode));
+ }
+#line 4337 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 22:
+#line 433 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode));
+ parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "--", (yyvsp[-1].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "--", EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode));
+ }
+#line 4347 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 23:
+#line 441 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.integerCheck((yyvsp[0].interm.intermTypedNode), "[]");
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 4356 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 24:
+#line 448 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleFunctionCall((yyvsp[0].interm).loc, (yyvsp[0].interm).function, (yyvsp[0].interm).intermNode);
+ delete (yyvsp[0].interm).function;
+ }
+#line 4365 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 25:
+#line 455 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+ }
+#line 4373 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 26:
+#line 461 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-1].interm);
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ }
+#line 4382 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 27:
+#line 465 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-1].interm);
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ }
+#line 4391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 28:
+#line 472 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-1].interm);
+ }
+#line 4399 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 29:
+#line 475 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+ }
+#line 4407 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 30:
+#line 481 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ TParameter param = { 0, new TType };
+ param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType());
+ (yyvsp[-1].interm).function->addParameter(param);
+ (yyval.interm).function = (yyvsp[-1].interm).function;
+ (yyval.interm).intermNode = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 4419 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 31:
+#line 488 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ TParameter param = { 0, new TType };
+ param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType());
+ (yyvsp[-2].interm).function->addParameter(param);
+ (yyval.interm).function = (yyvsp[-2].interm).function;
+ (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc);
+ }
+#line 4431 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 32:
+#line 498 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-1].interm);
+ }
+#line 4439 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 33:
+#line 506 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // Constructor
+ (yyval.interm).intermNode = 0;
+ (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type));
+ }
+#line 4449 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 34:
+#line 511 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ //
+ // Should be a method or subroutine call, but we haven't recognized the arguments yet.
+ //
+ (yyval.interm).function = 0;
+ (yyval.interm).intermNode = 0;
+
+ TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode();
+ if (method) {
+ (yyval.interm).function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength);
+ (yyval.interm).intermNode = method->getObject();
+ } else {
+ TIntermSymbol* symbol = (yyvsp[0].interm.intermTypedNode)->getAsSymbolNode();
+ if (symbol) {
+ parseContext.reservedErrorCheck(symbol->getLoc(), symbol->getName());
+ TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid));
+ (yyval.interm).function = function;
+ } else
+ parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "function call, method, or subroutine call expected", "", "");
+ }
+
+ if ((yyval.interm).function == 0) {
+ // error recover
+ TString* empty = NewPoolTString("");
+ (yyval.interm).function = new TFunction(empty, TType(EbtVoid), EOpNull);
+ }
+ }
+#line 4481 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 35:
+#line 539 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // Constructor
+ (yyval.interm).intermNode = 0;
+ (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type));
+ }
+#line 4491 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 36:
+#line 548 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.variableCheck((yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ if (TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode())
+ parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), "");
+ }
+#line 4502 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 37:
+#line 554 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "++", (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "++", EOpPreIncrement, (yyvsp[0].interm.intermTypedNode));
+ }
+#line 4511 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 38:
+#line 558 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "--", (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "--", EOpPreDecrement, (yyvsp[0].interm.intermTypedNode));
+ }
+#line 4520 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 39:
+#line 562 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-1].interm).op != EOpNull) {
+ char errorOp[2] = {0, 0};
+ switch((yyvsp[-1].interm).op) {
+ case EOpNegative: errorOp[0] = '-'; break;
+ case EOpLogicalNot: errorOp[0] = '!'; break;
+ case EOpBitwiseNot: errorOp[0] = '~'; break;
+ default: break; // some compilers want this
+ }
+ (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].interm).loc, errorOp, (yyvsp[-1].interm).op, (yyvsp[0].interm.intermTypedNode));
+ } else {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ if ((yyval.interm.intermTypedNode)->getAsConstantUnion())
+ (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression();
+ }
+ }
+#line 4541 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 40:
+#line 582 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNull; }
+#line 4547 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 41:
+#line 583 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNegative; }
+#line 4553 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 42:
+#line 584 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLogicalNot; }
+#line 4559 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 43:
+#line 585 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpBitwiseNot;
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise not"); }
+#line 4566 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 44:
+#line 591 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4572 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 45:
+#line 592 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "*", EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 4582 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 46:
+#line 597 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "/", EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 4592 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 47:
+#line 602 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "%");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "%", EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 4603 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 48:
+#line 611 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4609 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 49:
+#line 612 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "+", EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 4619 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 50:
+#line 617 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "-", EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 4629 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 51:
+#line 625 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4635 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 52:
+#line 626 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift left");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<<", EOpLeftShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 4646 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 53:
+#line 632 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift right");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">>", EOpRightShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 4657 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 54:
+#line 641 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4663 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 55:
+#line 642 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<", EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 4673 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 56:
+#line 647 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">", EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 4683 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 57:
+#line 652 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<=", EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 4693 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 58:
+#line 657 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">=", EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 4703 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 59:
+#line 665 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4709 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 60:
+#line 666 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison");
+ parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "==");
+ parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "==");
+ parseContext.referenceCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "==");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "==", EOpEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 4723 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 61:
+#line 675 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison");
+ parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!=");
+ parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!=");
+ parseContext.referenceCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!=");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "!=", EOpNotEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 4737 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 62:
+#line 687 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4743 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 63:
+#line 688 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise and");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&", EOpAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 4754 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 64:
+#line 697 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4760 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 65:
+#line 698 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise exclusive or");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^", EOpExclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 4771 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 66:
+#line 707 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4777 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 67:
+#line 708 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise inclusive or");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "|", EOpInclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 4788 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 68:
+#line 717 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4794 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 69:
+#line 718 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&&", EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 4804 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 70:
+#line 726 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4810 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 71:
+#line 727 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^^", EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 4820 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 72:
+#line 735 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4826 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 73:
+#line 736 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "||", EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 4836 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 74:
+#line 744 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4842 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 75:
+#line 745 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 4850 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 76:
+#line 748 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ --parseContext.controlFlowNestingLevel;
+ parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-5].interm.intermTypedNode));
+ parseContext.rValueErrorCheck((yyvsp[-4].lex).loc, "?", (yyvsp[-5].interm.intermTypedNode));
+ parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode));
+ parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addSelection((yyvsp[-5].interm.intermTypedNode), (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-4].lex).loc);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ parseContext.binaryOpError((yyvsp[-4].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+ }
+#line 4867 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 77:
+#line 763 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 4873 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 78:
+#line 764 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.arrayObjectCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array assignment");
+ parseContext.opaqueCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=");
+ parseContext.storage16BitAssignmentCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=");
+ parseContext.specializationCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=");
+ parseContext.lValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode));
+ parseContext.rValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addAssign((yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].interm).loc);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ parseContext.assignError((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+ }
+#line 4891 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 79:
+#line 780 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpAssign;
+ }
+#line 4900 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 80:
+#line 784 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpMulAssign;
+ }
+#line 4909 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 81:
+#line 788 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpDivAssign;
+ }
+#line 4918 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 82:
+#line 792 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "%=");
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpModAssign;
+ }
+#line 4928 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 83:
+#line 797 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpAddAssign;
+ }
+#line 4937 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 84:
+#line 801 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpSubAssign;
+ }
+#line 4946 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 85:
+#line 805 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift left assign");
+ (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLeftShiftAssign;
+ }
+#line 4955 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 86:
+#line 809 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift right assign");
+ (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpRightShiftAssign;
+ }
+#line 4964 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 87:
+#line 813 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-and assign");
+ (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAndAssign;
+ }
+#line 4973 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 88:
+#line 817 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-xor assign");
+ (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpExclusiveOrAssign;
+ }
+#line 4982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 89:
+#line 821 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-or assign");
+ (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpInclusiveOrAssign;
+ }
+#line 4991 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 90:
+#line 828 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 4999 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 91:
+#line 831 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.samplerConstructorLocationCheck((yyvsp[-1].lex).loc, ",", (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ parseContext.binaryOpError((yyvsp[-1].lex).loc, ",", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+ }
+#line 5012 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 92:
+#line 842 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.constantValueCheck((yyvsp[0].interm.intermTypedNode), "");
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 5021 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 93:
+#line 849 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */);
+ (yyval.interm.intermNode) = 0;
+ // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
+ }
+#line 5031 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 94:
+#line 854 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-1].interm).intermNode && (yyvsp[-1].interm).intermNode->getAsAggregate())
+ (yyvsp[-1].interm).intermNode->getAsAggregate()->setOperator(EOpSequence);
+ (yyval.interm.intermNode) = (yyvsp[-1].interm).intermNode;
+ }
+#line 5041 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 95:
+#line 859 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[-3].lex).loc, ENoProfile, 130, 0, "precision statement");
+ // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope
+ parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]);
+ parseContext.setDefaultPrecision((yyvsp[-3].lex).loc, (yyvsp[-1].interm.type), (yyvsp[-2].interm.type).qualifier.precision);
+ (yyval.interm.intermNode) = 0;
+ }
+#line 5053 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 96:
+#line 866 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.declareBlock((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).typeList);
+ (yyval.interm.intermNode) = 0;
+ }
+#line 5062 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 97:
+#line 870 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.declareBlock((yyvsp[-2].interm).loc, *(yyvsp[-2].interm).typeList, (yyvsp[-1].lex).string);
+ (yyval.interm.intermNode) = 0;
+ }
+#line 5071 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 98:
+#line 874 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.declareBlock((yyvsp[-3].interm).loc, *(yyvsp[-3].interm).typeList, (yyvsp[-2].lex).string, (yyvsp[-1].interm).arraySizes);
+ (yyval.interm.intermNode) = 0;
+ }
+#line 5080 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 99:
+#line 878 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier);
+ parseContext.updateStandaloneQualifierDefaults((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type));
+ (yyval.interm.intermNode) = 0;
+ }
+#line 5090 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 100:
+#line 883 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.checkNoShaderLayouts((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).shaderQualifiers);
+ parseContext.addQualifierToExisting((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, *(yyvsp[-1].lex).string);
+ (yyval.interm.intermNode) = 0;
+ }
+#line 5100 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 101:
+#line 888 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.checkNoShaderLayouts((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).shaderQualifiers);
+ (yyvsp[-1].interm.identifierList)->push_back((yyvsp[-2].lex).string);
+ parseContext.addQualifierToExisting((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).qualifier, *(yyvsp[-1].interm.identifierList));
+ (yyval.interm.intermNode) = 0;
+ }
+#line 5111 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 102:
+#line 897 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { parseContext.nestedBlockCheck((yyvsp[-2].interm.type).loc); }
+#line 5117 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 103:
+#line 897 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ --parseContext.structNestingLevel;
+ parseContext.blockName = (yyvsp[-4].lex).string;
+ parseContext.globalQualifierFixCheck((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).qualifier);
+ parseContext.checkNoShaderLayouts((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).shaderQualifiers);
+ parseContext.currentBlockQualifier = (yyvsp[-5].interm.type).qualifier;
+ (yyval.interm).loc = (yyvsp[-5].interm.type).loc;
+ (yyval.interm).typeList = (yyvsp[-1].interm.typeList);
+ }
+#line 5131 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 104:
+#line 908 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.identifierList) = new TIdentifierList;
+ (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string);
+ }
+#line 5140 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 105:
+#line 912 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.identifierList) = (yyvsp[-2].interm.identifierList);
+ (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string);
+ }
+#line 5149 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 106:
+#line 919 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).function = (yyvsp[-1].interm.function);
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ }
+#line 5158 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 107:
+#line 926 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.function) = (yyvsp[0].interm.function);
+ }
+#line 5166 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 108:
+#line 929 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.function) = (yyvsp[0].interm.function);
+ }
+#line 5174 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 109:
+#line 936 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // Add the parameter
+ (yyval.interm.function) = (yyvsp[-1].interm.function);
+ if ((yyvsp[0].interm).param.type->getBasicType() != EbtVoid)
+ (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm).param);
+ else
+ delete (yyvsp[0].interm).param.type;
+ }
+#line 5187 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 110:
+#line 944 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ //
+ // Only first parameter of one-parameter functions can be void
+ // The check for named parameters not being void is done in parameter_declarator
+ //
+ if ((yyvsp[0].interm).param.type->getBasicType() == EbtVoid) {
+ //
+ // This parameter > first is void
+ //
+ parseContext.error((yyvsp[-1].lex).loc, "cannot be an argument type except for '(void)'", "void", "");
+ delete (yyvsp[0].interm).param.type;
+ } else {
+ // Add the parameter
+ (yyval.interm.function) = (yyvsp[-2].interm.function);
+ (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param);
+ }
+ }
+#line 5209 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 111:
+#line 964 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-2].interm.type).qualifier.storage != EvqGlobal && (yyvsp[-2].interm.type).qualifier.storage != EvqTemporary) {
+ parseContext.error((yyvsp[-1].lex).loc, "no qualifiers allowed for function return",
+ GetStorageQualifierString((yyvsp[-2].interm.type).qualifier.storage), "");
+ }
+ if ((yyvsp[-2].interm.type).arraySizes)
+ parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes);
+
+ // Add the function as a prototype after parsing it (we do not support recursion)
+ TFunction *function;
+ TType type((yyvsp[-2].interm.type));
+
+ // Potentially rename shader entry point function. No-op most of the time.
+ parseContext.renameShaderFunction((yyvsp[-1].lex).string);
+
+ // Make the function
+ function = new TFunction((yyvsp[-1].lex).string, type);
+ (yyval.interm.function) = function;
+ }
+#line 5233 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 112:
+#line 987 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-1].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[-1].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[-1].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ parseContext.arraySizeRequiredCheck((yyvsp[-1].interm.type).loc, *(yyvsp[-1].interm.type).arraySizes);
+ }
+ if ((yyvsp[-1].interm.type).basicType == EbtVoid) {
+ parseContext.error((yyvsp[0].lex).loc, "illegal use of type 'void'", (yyvsp[0].lex).string->c_str(), "");
+ }
+ parseContext.reservedErrorCheck((yyvsp[0].lex).loc, *(yyvsp[0].lex).string);
+
+ TParameter param = {(yyvsp[0].lex).string, new TType((yyvsp[-1].interm.type))};
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).param = param;
+ }
+#line 5253 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 113:
+#line 1002 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-2].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes);
+ }
+ TType* type = new TType((yyvsp[-2].interm.type));
+ type->transferArraySizes((yyvsp[0].interm).arraySizes);
+ type->copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes);
+
+ parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, type->getArraySizes());
+ parseContext.arraySizeRequiredCheck((yyvsp[0].interm).loc, *(yyvsp[0].interm).arraySizes);
+ parseContext.reservedErrorCheck((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string);
+
+ TParameter param = { (yyvsp[-1].lex).string, type };
+
+ (yyval.interm).loc = (yyvsp[-1].lex).loc;
+ (yyval.interm).param = param;
+ }
+#line 5277 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 114:
+#line 1027 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+ if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone)
+ (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision;
+ parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier());
+
+ parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers);
+ parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type);
+ parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type);
+
+ }
+#line 5293 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 115:
+#line 1038 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+
+ parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type);
+ parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type);
+ parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier());
+ }
+#line 5305 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 116:
+#line 1048 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+ if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone)
+ (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision;
+ parseContext.precisionQualifierCheck((yyvsp[-1].interm.type).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier());
+
+ parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers);
+ parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type);
+ parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type);
+ }
+#line 5320 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 117:
+#line 1058 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+
+ parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type);
+ parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type);
+ parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier());
+ }
+#line 5332 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 118:
+#line 1068 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ TParameter param = { 0, new TType((yyvsp[0].interm.type)) };
+ (yyval.interm).param = param;
+ if ((yyvsp[0].interm.type).arraySizes)
+ parseContext.arraySizeRequiredCheck((yyvsp[0].interm.type).loc, *(yyvsp[0].interm.type).arraySizes);
+ }
+#line 5343 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 119:
+#line 1077 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+ }
+#line 5351 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 120:
+#line 1080 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-2].interm);
+ parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-2].interm).type);
+ }
+#line 5360 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 121:
+#line 1084 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-3].interm);
+ parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-3].interm).type, (yyvsp[0].interm).arraySizes);
+ }
+#line 5369 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 122:
+#line 1088 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-5].interm).type;
+ TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-5].interm).type, (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-5].interm).intermNode, initNode, (yyvsp[-1].lex).loc);
+ }
+#line 5379 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 123:
+#line 1093 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-4].interm).type;
+ TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-4].interm).type, 0, (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-4].interm).intermNode, initNode, (yyvsp[-1].lex).loc);
+ }
+#line 5389 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 124:
+#line 1101 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[0].interm.type);
+ (yyval.interm).intermNode = 0;
+
+ parseContext.declareTypeDefaults((yyval.interm).loc, (yyval.interm).type);
+
+ }
+#line 5401 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 125:
+#line 1108 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-1].interm.type);
+ (yyval.interm).intermNode = 0;
+ parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-1].interm.type));
+ }
+#line 5411 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 126:
+#line 1113 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-2].interm.type);
+ (yyval.interm).intermNode = 0;
+ parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-2].interm.type), (yyvsp[0].interm).arraySizes);
+ }
+#line 5421 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 127:
+#line 1118 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-4].interm.type);
+ TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-4].interm.type), (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc);
+ }
+#line 5431 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 128:
+#line 1123 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-3].interm.type);
+ TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc);
+ }
+#line 5441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 129:
+#line 1132 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+
+ parseContext.globalQualifierTypeCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyval.interm.type));
+ if ((yyvsp[0].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ }
+ parseContext.precisionQualifierCheck((yyval.interm.type).loc, (yyval.interm.type).basicType, (yyval.interm.type).qualifier);
+ }
+#line 5456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 130:
+#line 1142 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier);
+ parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type));
+
+ if ((yyvsp[0].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ }
+
+ if ((yyvsp[0].interm.type).arraySizes && parseContext.arrayQualifierError((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).qualifier))
+ (yyvsp[0].interm.type).arraySizes = nullptr;
+
+ parseContext.checkNoShaderLayouts((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers);
+ (yyvsp[0].interm.type).shaderQualifiers.merge((yyvsp[-1].interm.type).shaderQualifiers);
+ parseContext.mergeQualifiers((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyvsp[-1].interm.type).qualifier, true);
+ parseContext.precisionQualifierCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).basicType, (yyvsp[0].interm.type).qualifier);
+
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+
+ if (! (yyval.interm.type).qualifier.isInterpolation() &&
+ ((parseContext.language == EShLangVertex && (yyval.interm.type).qualifier.storage == EvqVaryingOut) ||
+ (parseContext.language == EShLangFragment && (yyval.interm.type).qualifier.storage == EvqVaryingIn)))
+ (yyval.interm.type).qualifier.smooth = true;
+ }
+#line 5485 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 131:
+#line 1169 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "invariant");
+ parseContext.profileRequires((yyval.interm.type).loc, ENoProfile, 120, 0, "invariant");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.invariant = true;
+ }
+#line 5496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 132:
+#line 1178 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "smooth");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "smooth");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "smooth");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.smooth = true;
+ }
+#line 5508 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 133:
+#line 1185 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "flat");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "flat");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "flat");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.flat = true;
+ }
+#line 5520 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 134:
+#line 1193 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "noperspective");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "noperspective");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.nopersp = true;
+ }
+#line 5532 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 135:
+#line 1200 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "__explicitInterpAMD");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.explicitInterp = true;
+ }
+#line 5544 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 136:
+#line 1207 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "pervertexNV");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECompatibilityProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.pervertexNV = true;
+ }
+#line 5557 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 137:
+#line 1215 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // No need for profile version or extension check. Shader stage already checks both.
+ parseContext.globalCheck((yyvsp[0].lex).loc, "perprimitiveNV");
+ parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshNVMask), "perprimitiveNV");
+ // Fragment shader stage doesn't check for extension. So we explicitly add below extension check.
+ if (parseContext.language == EShLangFragment)
+ parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_NV_mesh_shader, "perprimitiveNV");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.perPrimitiveNV = true;
+ }
+#line 5572 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 138:
+#line 1225 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // No need for profile version or extension check. Shader stage already checks both.
+ parseContext.globalCheck((yyvsp[0].lex).loc, "perviewNV");
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangMeshNV, "perviewNV");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.perViewNV = true;
+ }
+#line 5584 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 139:
+#line 1232 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // No need for profile version or extension check. Shader stage already checks both.
+ parseContext.globalCheck((yyvsp[0].lex).loc, "taskNV");
+ parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask), "taskNV");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.perTaskNV = true;
+ }
+#line 5596 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 140:
+#line 1243 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[-1].interm.type);
+ }
+#line 5604 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 141:
+#line 1249 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 5612 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 142:
+#line 1252 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[-2].interm.type);
+ (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers);
+ parseContext.mergeObjectLayoutQualifiers((yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false);
+ }
+#line 5622 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 143:
+#line 1259 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), *(yyvsp[0].lex).string);
+ }
+#line 5631 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 144:
+#line 1263 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[-2].lex).loc);
+ parseContext.setLayoutQualifier((yyvsp[-2].lex).loc, (yyval.interm.type), *(yyvsp[-2].lex).string, (yyvsp[0].interm.intermTypedNode));
+ }
+#line 5640 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 145:
+#line 1267 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { // because "shared" is both an identifier and a keyword
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ TString strShared("shared");
+ parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), strShared);
+ }
+#line 5650 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 146:
+#line 1276 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyval.interm.type).loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.noContraction = true;
+ }
+#line 5661 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 147:
+#line 1286 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 5669 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 148:
+#line 1289 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[-1].interm.type);
+ if ((yyval.interm.type).basicType == EbtVoid)
+ (yyval.interm.type).basicType = (yyvsp[0].interm.type).basicType;
+
+ (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers);
+ parseContext.mergeQualifiers((yyval.interm.type).loc, (yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false);
+ }
+#line 5682 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 149:
+#line 1300 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 5690 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 150:
+#line 1303 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 5698 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 151:
+#line 1306 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.checkPrecisionQualifier((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier.precision);
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 5707 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 152:
+#line 1310 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // allow inheritance of storage qualifier from block declaration
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 5716 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 153:
+#line 1314 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // allow inheritance of storage qualifier from block declaration
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 5725 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 154:
+#line 1319 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // allow inheritance of storage qualifier from block declaration
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 5734 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 155:
+#line 1323 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 5742 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 156:
+#line 1330 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant
+ }
+#line 5751 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 157:
+#line 1334 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "inout");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqInOut;
+ }
+#line 5761 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 158:
+#line 1339 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "in");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later
+ (yyval.interm.type).qualifier.storage = EvqIn;
+ }
+#line 5772 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 159:
+#line 1345 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "out");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later
+ (yyval.interm.type).qualifier.storage = EvqOut;
+ }
+#line 5783 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 160:
+#line 1351 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 120, 0, "centroid");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "centroid");
+ parseContext.globalCheck((yyvsp[0].lex).loc, "centroid");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.centroid = true;
+ }
+#line 5795 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 161:
+#line 1358 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "uniform");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqUniform;
+ }
+#line 5805 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 162:
+#line 1363 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "shared");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 310, 0, "shared");
+ parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangComputeMask | EShLangMeshNVMask | EShLangTaskNVMask), "shared");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqShared;
+ }
+#line 5818 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 163:
+#line 1371 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "buffer");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqBuffer;
+ }
+#line 5828 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 164:
+#line 1377 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangVertex, "attribute");
+ parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "attribute");
+ parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "attribute");
+ parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "attribute");
+ parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "attribute");
+
+ parseContext.globalCheck((yyvsp[0].lex).loc, "attribute");
+
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqVaryingIn;
+ }
+#line 5845 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 165:
+#line 1389 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "varying");
+ parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "varying");
+ parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "varying");
+ parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "varying");
+
+ parseContext.globalCheck((yyvsp[0].lex).loc, "varying");
+
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ if (parseContext.language == EShLangVertex)
+ (yyval.interm.type).qualifier.storage = EvqVaryingOut;
+ else
+ (yyval.interm.type).qualifier.storage = EvqVaryingIn;
+ }
+#line 5864 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 166:
+#line 1403 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "patch");
+ parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.patch = true;
+ }
+#line 5875 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 167:
+#line 1409 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "sample");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.sample = true;
+ }
+#line 5885 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 168:
+#line 1414 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeNV");
+ parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask
+ | EShLangAnyHitNVMask), "hitAttributeNV");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqHitAttrNV;
+ }
+#line 5898 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 169:
+#line 1422 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadNV");
+ parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask |
+ EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqPayloadNV;
+ }
+#line 5911 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 170:
+#line 1430 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInNV");
+ parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitNVMask |
+ EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqPayloadInNV;
+ }
+#line 5924 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 171:
+#line 1438 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataNV");
+ parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenNVMask |
+ EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqCallableDataNV;
+ }
+#line 5937 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 172:
+#line 1446 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInNV");
+ parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqCallableDataInNV;
+ }
+#line 5949 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 173:
+#line 1453 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.coherent = true;
+ }
+#line 5958 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 174:
+#line 1457 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "devicecoherent");
+ (yyval.interm.type).qualifier.devicecoherent = true;
+ }
+#line 5968 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 175:
+#line 1462 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "queuefamilycoherent");
+ (yyval.interm.type).qualifier.queuefamilycoherent = true;
+ }
+#line 5978 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 176:
+#line 1467 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "workgroupcoherent");
+ (yyval.interm.type).qualifier.workgroupcoherent = true;
+ }
+#line 5988 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 177:
+#line 1472 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "subgroupcoherent");
+ (yyval.interm.type).qualifier.subgroupcoherent = true;
+ }
+#line 5998 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 178:
+#line 1477 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate");
+ (yyval.interm.type).qualifier.nonprivate = true;
+ }
+#line 6008 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 179:
+#line 1482 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.volatil = true;
+ }
+#line 6017 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 180:
+#line 1486 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.restrict = true;
+ }
+#line 6026 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 181:
+#line 1490 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.readonly = true;
+ }
+#line 6035 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 182:
+#line 1494 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.writeonly = true;
+ }
+#line 6044 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 183:
+#line 1498 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.spvRemoved((yyvsp[0].lex).loc, "subroutine");
+ parseContext.globalCheck((yyvsp[0].lex).loc, "subroutine");
+ parseContext.unimplemented((yyvsp[0].lex).loc, "subroutine");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ }
+#line 6055 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 184:
+#line 1504 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.spvRemoved((yyvsp[-3].lex).loc, "subroutine");
+ parseContext.globalCheck((yyvsp[-3].lex).loc, "subroutine");
+ parseContext.unimplemented((yyvsp[-3].lex).loc, "subroutine");
+ (yyval.interm.type).init((yyvsp[-3].lex).loc);
+ }
+#line 6066 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 185:
+#line 1515 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.nonUniform = true;
+ }
+#line 6075 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 186:
+#line 1522 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // TODO
+ }
+#line 6083 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 187:
+#line 1525 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // TODO: 4.0 semantics: subroutines
+ // 1) make sure each identifier is a type declared earlier with SUBROUTINE
+ // 2) save all of the identifiers for future comparison with the declared function
+ }
+#line 6093 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 188:
+#line 1534 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[-1].interm.type);
+ (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type));
+ (yyval.interm.type).typeParameters = (yyvsp[0].interm.typeParameters);
+ }
+#line 6103 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 189:
+#line 1539 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.arrayOfArrayVersionCheck((yyvsp[0].interm).loc, (yyvsp[0].interm).arraySizes);
+ (yyval.interm.type) = (yyvsp[-2].interm.type);
+ (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type));
+ (yyval.interm.type).typeParameters = (yyvsp[-1].interm.typeParameters);
+ (yyval.interm.type).arraySizes = (yyvsp[0].interm).arraySizes;
+ }
+#line 6115 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 190:
+#line 1549 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[-1].lex).loc;
+ (yyval.interm).arraySizes = new TArraySizes;
+ (yyval.interm).arraySizes->addInnerSize();
+ }
+#line 6125 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 191:
+#line 1554 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[-2].lex).loc;
+ (yyval.interm).arraySizes = new TArraySizes;
+
+ TArraySize size;
+ parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size");
+ (yyval.interm).arraySizes->addInnerSize(size);
+ }
+#line 6138 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 192:
+#line 1562 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-2].interm);
+ (yyval.interm).arraySizes->addInnerSize();
+ }
+#line 6147 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 193:
+#line 1566 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-3].interm);
+
+ TArraySize size;
+ parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size");
+ (yyval.interm).arraySizes->addInnerSize(size);
+ }
+#line 6159 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 194:
+#line 1576 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeParameters) = (yyvsp[0].interm.typeParameters);
+ }
+#line 6167 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 195:
+#line 1579 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeParameters) = 0;
+ }
+#line 6175 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 196:
+#line 1585 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeParameters) = (yyvsp[-1].interm.typeParameters);
+ }
+#line 6183 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 197:
+#line 1591 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeParameters) = new TArraySizes;
+
+ TArraySize size;
+ parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter");
+ (yyval.interm.typeParameters)->addInnerSize(size);
+ }
+#line 6195 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 198:
+#line 1598 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeParameters) = (yyvsp[-2].interm.typeParameters);
+
+ TArraySize size;
+ parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter");
+ (yyval.interm.typeParameters)->addInnerSize(size);
+ }
+#line 6207 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 199:
+#line 1608 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtVoid;
+ }
+#line 6216 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 200:
+#line 1612 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ }
+#line 6225 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 201:
+#line 1616 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ }
+#line 6234 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 202:
+#line 1620 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ }
+#line 6244 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 203:
+#line 1625 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtBool;
+ }
+#line 6253 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 204:
+#line 1629 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6263 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 205:
+#line 1634 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6273 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 206:
+#line 1639 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6283 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 207:
+#line 1644 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtBool;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6293 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 208:
+#line 1649 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtBool;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6303 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 209:
+#line 1654 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtBool;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6313 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 210:
+#line 1659 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6323 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 211:
+#line 1664 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6333 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 212:
+#line 1669 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6343 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 213:
+#line 1674 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6354 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 214:
+#line 1680 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6365 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 215:
+#line 1686 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6376 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 216:
+#line 1692 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 6386 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 217:
+#line 1697 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 6396 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 218:
+#line 1702 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 6406 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 219:
+#line 1707 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 6416 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 220:
+#line 1712 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 3);
+ }
+#line 6426 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 221:
+#line 1717 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 4);
+ }
+#line 6436 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 222:
+#line 1722 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 2);
+ }
+#line 6446 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 223:
+#line 1727 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 6456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 224:
+#line 1732 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 4);
+ }
+#line 6466 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 225:
+#line 1737 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 2);
+ }
+#line 6476 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 226:
+#line 1742 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 3);
+ }
+#line 6486 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 227:
+#line 1747 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 6496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 228:
+#line 1753 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ }
+#line 6506 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 229:
+#line 1758 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "float16_t", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ }
+#line 6516 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 230:
+#line 1763 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ }
+#line 6526 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 231:
+#line 1768 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ }
+#line 6536 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 232:
+#line 1773 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt8;
+ }
+#line 6546 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 233:
+#line 1778 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint8;
+ }
+#line 6556 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 234:
+#line 1783 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt16;
+ }
+#line 6566 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 235:
+#line 1788 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint16;
+ }
+#line 6576 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 236:
+#line 1793 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ }
+#line 6586 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 237:
+#line 1798 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ }
+#line 6596 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 238:
+#line 1803 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt64;
+ }
+#line 6606 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 239:
+#line 1808 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint64;
+ }
+#line 6616 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 240:
+#line 1813 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6627 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 241:
+#line 1819 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6638 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 242:
+#line 1825 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6649 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 243:
+#line 1831 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6660 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 244:
+#line 1837 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6671 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 245:
+#line 1843 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6682 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 246:
+#line 1849 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6693 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 247:
+#line 1855 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6704 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 248:
+#line 1861 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6715 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 249:
+#line 1867 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6726 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 250:
+#line 1873 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6737 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 251:
+#line 1879 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6748 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 252:
+#line 1885 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt8;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6759 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 253:
+#line 1891 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt8;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6770 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 254:
+#line 1897 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt8;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6781 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 255:
+#line 1903 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt16;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6792 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 256:
+#line 1909 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt16;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6803 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 257:
+#line 1915 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt16;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6814 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 258:
+#line 1921 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6825 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 259:
+#line 1927 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6836 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 260:
+#line 1933 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6847 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 261:
+#line 1939 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt64;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6858 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 262:
+#line 1945 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt64;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6869 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 263:
+#line 1951 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt64;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6880 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 264:
+#line 1957 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint8;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6891 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 265:
+#line 1963 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint8;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6902 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 266:
+#line 1969 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint8;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6913 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 267:
+#line 1975 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint16;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6924 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 268:
+#line 1981 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint16;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6935 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 269:
+#line 1987 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint16;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6946 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 270:
+#line 1993 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6957 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 271:
+#line 1999 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ (yyval.interm.type).setVector(3);
+ }
+#line 6968 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 272:
+#line 2005 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ (yyval.interm.type).setVector(4);
+ }
+#line 6979 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 273:
+#line 2011 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint64;
+ (yyval.interm.type).setVector(2);
+ }
+#line 6990 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 274:
+#line 2017 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint64;
+ (yyval.interm.type).setVector(3);
+ }
+#line 7001 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 275:
+#line 2023 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint64;
+ (yyval.interm.type).setVector(4);
+ }
+#line 7012 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 276:
+#line 2029 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 7023 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 277:
+#line 2035 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 7034 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 278:
+#line 2041 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 7045 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 279:
+#line 2047 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 7056 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 280:
+#line 2053 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 3);
+ }
+#line 7067 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 281:
+#line 2059 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 4);
+ }
+#line 7078 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 282:
+#line 2065 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 2);
+ }
+#line 7089 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 283:
+#line 2071 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 7100 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 284:
+#line 2077 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 4);
+ }
+#line 7111 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 285:
+#line 2083 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 2);
+ }
+#line 7122 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 286:
+#line 2089 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 3);
+ }
+#line 7133 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 287:
+#line 2095 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 7144 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 288:
+#line 2101 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 7155 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 289:
+#line 2107 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 7166 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 290:
+#line 2113 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 7177 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 291:
+#line 2119 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 7188 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 292:
+#line 2125 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(2, 3);
+ }
+#line 7199 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 293:
+#line 2131 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(2, 4);
+ }
+#line 7210 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 294:
+#line 2137 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(3, 2);
+ }
+#line 7221 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 295:
+#line 2143 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 7232 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 296:
+#line 2149 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(3, 4);
+ }
+#line 7243 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 297:
+#line 2155 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(4, 2);
+ }
+#line 7254 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 298:
+#line 2161 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(4, 3);
+ }
+#line 7265 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 299:
+#line 2167 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat16;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 7276 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 300:
+#line 2173 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 7287 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 301:
+#line 2179 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 7298 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 302:
+#line 2185 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 7309 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 303:
+#line 2191 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 7320 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 304:
+#line 2197 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 3);
+ }
+#line 7331 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 305:
+#line 2203 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 4);
+ }
+#line 7342 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 306:
+#line 2209 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 2);
+ }
+#line 7353 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 307:
+#line 2215 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 7364 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 308:
+#line 2221 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 4);
+ }
+#line 7375 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 309:
+#line 2227 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 2);
+ }
+#line 7386 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 310:
+#line 2233 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 3);
+ }
+#line 7397 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 311:
+#line 2239 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 7408 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 312:
+#line 2245 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 7419 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 313:
+#line 2251 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 7430 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 314:
+#line 2257 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 7441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 315:
+#line 2263 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 7452 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 316:
+#line 2269 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 3);
+ }
+#line 7463 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 317:
+#line 2275 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 4);
+ }
+#line 7474 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 318:
+#line 2281 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 2);
+ }
+#line 7485 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 319:
+#line 2287 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 7496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 320:
+#line 2293 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 4);
+ }
+#line 7507 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 321:
+#line 2299 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 2);
+ }
+#line 7518 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 322:
+#line 2305 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 3);
+ }
+#line 7529 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 323:
+#line 2311 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 7540 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 324:
+#line 2317 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtAccStructNV;
+ }
+#line 7549 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 325:
+#line 2321 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.vulkanRemoved((yyvsp[0].lex).loc, "atomic counter types");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtAtomicUint;
+ }
+#line 7559 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 326:
+#line 2326 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd1D);
+ }
+#line 7569 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 327:
+#line 2332 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D);
+ }
+#line 7579 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 328:
+#line 2337 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd3D);
+ }
+#line 7589 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 329:
+#line 2342 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdCube);
+ }
+#line 7599 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 330:
+#line 2347 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, true);
+ }
+#line 7609 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 331:
+#line 2352 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdCube, false, true);
+ }
+#line 7619 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 332:
+#line 2357 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true);
+ }
+#line 7629 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 333:
+#line 2362 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, true);
+ }
+#line 7639 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 334:
+#line 2368 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd1D, false, true);
+ }
+#line 7649 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 335:
+#line 2373 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true);
+ }
+#line 7659 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 336:
+#line 2378 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true, true);
+ }
+#line 7669 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 337:
+#line 2383 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true);
+ }
+#line 7679 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 338:
+#line 2388 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true, true);
+ }
+#line 7689 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 339:
+#line 2393 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd1D);
+ }
+#line 7700 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 340:
+#line 2399 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd2D);
+ }
+#line 7711 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 341:
+#line 2405 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd3D);
+ }
+#line 7722 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 342:
+#line 2411 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, EsdCube);
+ }
+#line 7733 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 343:
+#line 2417 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, false, true);
+ }
+#line 7744 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 344:
+#line 2423 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, true);
+ }
+#line 7755 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 345:
+#line 2429 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, false, true);
+ }
+#line 7766 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 346:
+#line 2435 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true);
+ }
+#line 7777 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 347:
+#line 2441 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true);
+ }
+#line 7788 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 348:
+#line 2447 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true, true);
+ }
+#line 7799 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 349:
+#line 2453 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, true);
+ }
+#line 7810 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 350:
+#line 2459 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true);
+ }
+#line 7821 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 351:
+#line 2465 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true, true);
+ }
+#line 7832 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 352:
+#line 2471 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd1D);
+ }
+#line 7842 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 353:
+#line 2477 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd2D);
+ }
+#line 7852 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 354:
+#line 2482 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd3D);
+ }
+#line 7862 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 355:
+#line 2487 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, EsdCube);
+ }
+#line 7872 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 356:
+#line 2492 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd2D, true);
+ }
+#line 7882 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 357:
+#line 2497 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd2D);
+ }
+#line 7892 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 358:
+#line 2502 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd3D);
+ }
+#line 7902 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 359:
+#line 2507 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, EsdCube);
+ }
+#line 7912 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 360:
+#line 2513 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd1D, true);
+ }
+#line 7922 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 361:
+#line 2518 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, EsdCube, true);
+ }
+#line 7932 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 362:
+#line 2523 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd1D);
+ }
+#line 7942 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 363:
+#line 2528 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd1D, true);
+ }
+#line 7952 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 364:
+#line 2533 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, EsdCube, true);
+ }
+#line 7962 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 365:
+#line 2538 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube, true);
+ }
+#line 7972 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 366:
+#line 2543 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube, true);
+ }
+#line 7982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 367:
+#line 2548 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube, true);
+ }
+#line 7992 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 368:
+#line 2554 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd2D, true);
+ }
+#line 8002 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 369:
+#line 2559 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D);
+ }
+#line 8012 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 370:
+#line 2564 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd3D);
+ }
+#line 8022 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 371:
+#line 2569 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true);
+ }
+#line 8032 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 372:
+#line 2574 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube);
+ }
+#line 8042 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 373:
+#line 2579 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D);
+ }
+#line 8052 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 374:
+#line 2584 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd3D);
+ }
+#line 8062 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 375:
+#line 2589 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube);
+ }
+#line 8072 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 376:
+#line 2594 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true);
+ }
+#line 8082 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 377:
+#line 2599 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D);
+ }
+#line 8092 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 378:
+#line 2604 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd3D);
+ }
+#line 8102 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 379:
+#line 2609 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube);
+ }
+#line 8112 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 380:
+#line 2614 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true);
+ }
+#line 8122 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 381:
+#line 2619 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setPureSampler(false);
+ }
+#line 8132 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 382:
+#line 2624 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setPureSampler(true);
+ }
+#line 8142 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 383:
+#line 2630 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdRect);
+ }
+#line 8152 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 384:
+#line 2635 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdRect, false, true);
+ }
+#line 8162 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 385:
+#line 2640 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, EsdRect);
+ }
+#line 8173 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 386:
+#line 2646 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, EsdRect, false, true);
+ }
+#line 8184 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 387:
+#line 2652 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, EsdRect);
+ }
+#line 8194 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 388:
+#line 2657 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, EsdRect);
+ }
+#line 8204 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 389:
+#line 2662 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdBuffer);
+ }
+#line 8214 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 390:
+#line 2667 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, EsdBuffer);
+ }
+#line 8225 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 391:
+#line 2673 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, EsdBuffer);
+ }
+#line 8235 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 392:
+#line 2678 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, EsdBuffer);
+ }
+#line 8245 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 393:
+#line 2683 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, false, true);
+ }
+#line 8255 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 394:
+#line 2688 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, false, true);
+ }
+#line 8266 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 395:
+#line 2694 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd2D, false, false, true);
+ }
+#line 8276 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 396:
+#line 2699 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd2D, false, false, true);
+ }
+#line 8286 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 397:
+#line 2704 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, false, true);
+ }
+#line 8296 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 398:
+#line 2709 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, false, true);
+ }
+#line 8307 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 399:
+#line 2715 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd2D, true, false, true);
+ }
+#line 8317 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 400:
+#line 2720 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd2D, true, false, true);
+ }
+#line 8327 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 401:
+#line 2725 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D);
+ }
+#line 8337 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 402:
+#line 2730 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D);
+ }
+#line 8348 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 403:
+#line 2736 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D);
+ }
+#line 8359 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 404:
+#line 2742 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd3D);
+ }
+#line 8370 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 405:
+#line 2748 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube);
+ }
+#line 8381 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 406:
+#line 2754 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D, true);
+ }
+#line 8391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 407:
+#line 2759 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D, true);
+ }
+#line 8402 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 408:
+#line 2765 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true);
+ }
+#line 8413 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 409:
+#line 2771 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube, true);
+ }
+#line 8424 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 410:
+#line 2777 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D);
+ }
+#line 8434 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 411:
+#line 2782 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D, true);
+ }
+#line 8444 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 412:
+#line 2787 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D);
+ }
+#line 8454 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 413:
+#line 2792 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D, true);
+ }
+#line 8464 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 414:
+#line 2797 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, EsdRect);
+ }
+#line 8474 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 415:
+#line 2802 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdRect);
+ }
+#line 8485 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 416:
+#line 2808 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, EsdRect);
+ }
+#line 8495 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 417:
+#line 2813 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, EsdRect);
+ }
+#line 8505 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 418:
+#line 2818 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, EsdBuffer);
+ }
+#line 8515 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 419:
+#line 2823 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdBuffer);
+ }
+#line 8526 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 420:
+#line 2829 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, EsdBuffer);
+ }
+#line 8536 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 421:
+#line 2834 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, EsdBuffer);
+ }
+#line 8546 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 422:
+#line 2839 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, false, false, true);
+ }
+#line 8556 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 423:
+#line 2844 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, false, false, true);
+ }
+#line 8567 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 424:
+#line 2850 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, false, false, true);
+ }
+#line 8577 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 425:
+#line 2855 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, false, false, true);
+ }
+#line 8587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 426:
+#line 2860 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true, false, true);
+ }
+#line 8597 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 427:
+#line 2865 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true, false, true);
+ }
+#line 8608 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 428:
+#line 2871 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true, false, true);
+ }
+#line 8618 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 429:
+#line 2876 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true, false, true);
+ }
+#line 8628 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 430:
+#line 2881 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D);
+ }
+#line 8638 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 431:
+#line 2886 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D);
+ }
+#line 8649 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 432:
+#line 2892 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd1D);
+ }
+#line 8659 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 433:
+#line 2897 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd1D);
+ }
+#line 8669 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 434:
+#line 2902 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D);
+ }
+#line 8679 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 435:
+#line 2907 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D);
+ }
+#line 8690 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 436:
+#line 2913 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd2D);
+ }
+#line 8700 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 437:
+#line 2918 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd2D);
+ }
+#line 8710 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 438:
+#line 2923 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd3D);
+ }
+#line 8720 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 439:
+#line 2928 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, Esd3D);
+ }
+#line 8731 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 440:
+#line 2934 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd3D);
+ }
+#line 8741 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 441:
+#line 2939 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd3D);
+ }
+#line 8751 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 442:
+#line 2944 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, EsdRect);
+ }
+#line 8761 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 443:
+#line 2949 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, EsdRect);
+ }
+#line 8772 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 444:
+#line 2955 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, EsdRect);
+ }
+#line 8782 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 445:
+#line 2960 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, EsdRect);
+ }
+#line 8792 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 446:
+#line 2965 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube);
+ }
+#line 8802 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 447:
+#line 2970 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube);
+ }
+#line 8813 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 448:
+#line 2976 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, EsdCube);
+ }
+#line 8823 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 449:
+#line 2981 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, EsdCube);
+ }
+#line 8833 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 450:
+#line 2986 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, EsdBuffer);
+ }
+#line 8843 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 451:
+#line 2991 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, EsdBuffer);
+ }
+#line 8854 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 452:
+#line 2997 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, EsdBuffer);
+ }
+#line 8864 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 453:
+#line 3002 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, EsdBuffer);
+ }
+#line 8874 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 454:
+#line 3007 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D, true);
+ }
+#line 8884 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 455:
+#line 3012 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D, true);
+ }
+#line 8895 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 456:
+#line 3018 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd1D, true);
+ }
+#line 8905 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 457:
+#line 3023 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd1D, true);
+ }
+#line 8915 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 458:
+#line 3028 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true);
+ }
+#line 8925 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 459:
+#line 3033 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true);
+ }
+#line 8936 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 460:
+#line 3039 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true);
+ }
+#line 8946 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 461:
+#line 3044 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true);
+ }
+#line 8956 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 462:
+#line 3049 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube, true);
+ }
+#line 8966 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 463:
+#line 3054 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube, true);
+ }
+#line 8977 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 464:
+#line 3060 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, EsdCube, true);
+ }
+#line 8987 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 465:
+#line 3065 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, EsdCube, true);
+ }
+#line 8997 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 466:
+#line 3070 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, false, false, true);
+ }
+#line 9007 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 467:
+#line 3075 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, false, false, true);
+ }
+#line 9018 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 468:
+#line 3081 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, false, false, true);
+ }
+#line 9028 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 469:
+#line 3086 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, false, false, true);
+ }
+#line 9038 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 470:
+#line 3091 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true, false, true);
+ }
+#line 9048 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 471:
+#line 3096 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true, false, true);
+ }
+#line 9059 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 472:
+#line 3102 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true, false, true);
+ }
+#line 9069 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 473:
+#line 3107 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true, false, true);
+ }
+#line 9079 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 474:
+#line 3112 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { // GL_OES_EGL_image_external
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D);
+ (yyval.interm.type).sampler.external = true;
+ }
+#line 9090 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 475:
+#line 3118 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { // GL_EXT_YUV_target
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D);
+ (yyval.interm.type).sampler.yuv = true;
+ }
+#line 9101 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 476:
+#line 3124 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtFloat);
+ }
+#line 9112 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 477:
+#line 3130 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtFloat, true);
+ }
+#line 9123 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 478:
+#line 3136 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel());
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtFloat16);
+ }
+#line 9135 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 479:
+#line 3143 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel());
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtFloat16, true);
+ }
+#line 9147 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 480:
+#line 3150 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtInt);
+ }
+#line 9158 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 481:
+#line 3156 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtInt, true);
+ }
+#line 9169 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 482:
+#line 3162 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtUint);
+ }
+#line 9180 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 483:
+#line 3168 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtUint, true);
+ }
+#line 9191 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 484:
+#line 3174 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fcoopmatCheck((yyvsp[0].lex).loc, "fcoopmatNV", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).coopmat = true;
+ }
+#line 9202 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 485:
+#line 3180 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.intcoopmatCheck((yyvsp[0].lex).loc, "icoopmatNV", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ (yyval.interm.type).coopmat = true;
+ }
+#line 9213 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 486:
+#line 3186 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.intcoopmatCheck((yyvsp[0].lex).loc, "ucoopmatNV", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ (yyval.interm.type).coopmat = true;
+ }
+#line 9224 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 487:
+#line 3193 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ (yyval.interm.type).qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ parseContext.structTypeCheck((yyval.interm.type).loc, (yyval.interm.type));
+ }
+#line 9234 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 488:
+#line 3198 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ //
+ // This is for user defined type names. The lexical phase looked up the
+ // type.
+ //
+ if (const TVariable* variable = ((yyvsp[0].lex).symbol)->getAsVariable()) {
+ const TType& structure = variable->getType();
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtStruct;
+ (yyval.interm.type).userDef = &structure;
+ } else
+ parseContext.error((yyvsp[0].lex).loc, "expected type name", (yyvsp[0].lex).string->c_str(), "");
+ }
+#line 9252 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 489:
+#line 3214 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "highp precision qualifier");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqHigh);
+ }
+#line 9262 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 490:
+#line 3219 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "mediump precision qualifier");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqMedium);
+ }
+#line 9272 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 491:
+#line 3224 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "lowp precision qualifier");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqLow);
+ }
+#line 9282 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 492:
+#line 3232 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { parseContext.nestedStructCheck((yyvsp[-2].lex).loc); }
+#line 9288 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 493:
+#line 3232 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ TType* structure = new TType((yyvsp[-1].interm.typeList), *(yyvsp[-4].lex).string);
+ parseContext.structArrayCheck((yyvsp[-4].lex).loc, *structure);
+ TVariable* userTypeDef = new TVariable((yyvsp[-4].lex).string, *structure, true);
+ if (! parseContext.symbolTable.insert(*userTypeDef))
+ parseContext.error((yyvsp[-4].lex).loc, "redefinition", (yyvsp[-4].lex).string->c_str(), "struct");
+ (yyval.interm.type).init((yyvsp[-5].lex).loc);
+ (yyval.interm.type).basicType = EbtStruct;
+ (yyval.interm.type).userDef = structure;
+ --parseContext.structNestingLevel;
+ }
+#line 9304 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 494:
+#line 3243 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { parseContext.nestedStructCheck((yyvsp[-1].lex).loc); }
+#line 9310 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 495:
+#line 3243 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ TType* structure = new TType((yyvsp[-1].interm.typeList), TString(""));
+ (yyval.interm.type).init((yyvsp[-4].lex).loc);
+ (yyval.interm.type).basicType = EbtStruct;
+ (yyval.interm.type).userDef = structure;
+ --parseContext.structNestingLevel;
+ }
+#line 9322 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 496:
+#line 3253 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeList) = (yyvsp[0].interm.typeList);
+ }
+#line 9330 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 497:
+#line 3256 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeList) = (yyvsp[-1].interm.typeList);
+ for (unsigned int i = 0; i < (yyvsp[0].interm.typeList)->size(); ++i) {
+ for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) {
+ if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[0].interm.typeList))[i].type->getFieldName())
+ parseContext.error((*(yyvsp[0].interm.typeList))[i].loc, "duplicate member name:", "", (*(yyvsp[0].interm.typeList))[i].type->getFieldName().c_str());
+ }
+ (yyval.interm.typeList)->push_back((*(yyvsp[0].interm.typeList))[i]);
+ }
+ }
+#line 9345 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 498:
+#line 3269 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-2].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ if (parseContext.isEsProfile())
+ parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes);
+ }
+
+ (yyval.interm.typeList) = (yyvsp[-1].interm.typeList);
+
+ parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType);
+ parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier);
+
+ for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) {
+ TType type((yyvsp[-2].interm.type));
+ type.setFieldName((*(yyval.interm.typeList))[i].type->getFieldName());
+ type.transferArraySizes((*(yyval.interm.typeList))[i].type->getArraySizes());
+ type.copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes);
+ parseContext.arrayOfArrayVersionCheck((*(yyval.interm.typeList))[i].loc, type.getArraySizes());
+ (*(yyval.interm.typeList))[i].type->shallowCopy(type);
+ }
+ }
+#line 9372 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 499:
+#line 3291 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-2].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ if (parseContext.isEsProfile())
+ parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes);
+ }
+
+ (yyval.interm.typeList) = (yyvsp[-1].interm.typeList);
+
+ parseContext.memberQualifierCheck((yyvsp[-3].interm.type));
+ parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType);
+ parseContext.mergeQualifiers((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, (yyvsp[-3].interm.type).qualifier, true);
+ parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier);
+
+ for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) {
+ TType type((yyvsp[-2].interm.type));
+ type.setFieldName((*(yyval.interm.typeList))[i].type->getFieldName());
+ type.transferArraySizes((*(yyval.interm.typeList))[i].type->getArraySizes());
+ type.copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes);
+ parseContext.arrayOfArrayVersionCheck((*(yyval.interm.typeList))[i].loc, type.getArraySizes());
+ (*(yyval.interm.typeList))[i].type->shallowCopy(type);
+ }
+ }
+#line 9401 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 500:
+#line 3318 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeList) = new TTypeList;
+ (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine));
+ }
+#line 9410 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 501:
+#line 3322 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine));
+ }
+#line 9418 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 502:
+#line 3328 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeLine).type = new TType(EbtVoid);
+ (yyval.interm.typeLine).loc = (yyvsp[0].lex).loc;
+ (yyval.interm.typeLine).type->setFieldName(*(yyvsp[0].lex).string);
+ }
+#line 9428 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 503:
+#line 3333 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, (yyvsp[0].interm).arraySizes);
+
+ (yyval.interm.typeLine).type = new TType(EbtVoid);
+ (yyval.interm.typeLine).loc = (yyvsp[-1].lex).loc;
+ (yyval.interm.typeLine).type->setFieldName(*(yyvsp[-1].lex).string);
+ (yyval.interm.typeLine).type->transferArraySizes((yyvsp[0].interm).arraySizes);
+ }
+#line 9441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 504:
+#line 3344 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 9449 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 505:
+#line 3348 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ const char* initFeature = "{ } style initializers";
+ parseContext.requireProfile((yyvsp[-2].lex).loc, ~EEsProfile, initFeature);
+ parseContext.profileRequires((yyvsp[-2].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
+ (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode);
+ }
+#line 9460 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 506:
+#line 3354 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ const char* initFeature = "{ } style initializers";
+ parseContext.requireProfile((yyvsp[-3].lex).loc, ~EEsProfile, initFeature);
+ parseContext.profileRequires((yyvsp[-3].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 9471 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 507:
+#line 3365 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate(0, (yyvsp[0].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)->getLoc());
+ }
+#line 9479 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 508:
+#line 3368 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ }
+#line 9487 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 509:
+#line 3375 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9493 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 510:
+#line 3379 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9499 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 511:
+#line 3380 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9505 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 512:
+#line 3386 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9511 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 513:
+#line 3387 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9517 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 514:
+#line 3388 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9523 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 515:
+#line 3389 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9529 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 516:
+#line 3390 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9535 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 517:
+#line 3391 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9541 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 518:
+#line 3392 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9547 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 519:
+#line 3394 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9553 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 520:
+#line 3400 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "demote");
+ parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_demote_to_helper_invocation, "demote");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDemote, (yyvsp[-1].lex).loc);
+ }
+#line 9563 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 521:
+#line 3409 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = 0; }
+#line 9569 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 522:
+#line 3410 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.push();
+ ++parseContext.statementNestingLevel;
+ }
+#line 9578 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 523:
+#line 3414 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ }
+#line 9587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 524:
+#line 3418 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-2].interm.intermNode) && (yyvsp[-2].interm.intermNode)->getAsAggregate())
+ (yyvsp[-2].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence);
+ (yyval.interm.intermNode) = (yyvsp[-2].interm.intermNode);
+ }
+#line 9597 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 525:
+#line 3426 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9603 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 526:
+#line 3427 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9609 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 527:
+#line 3431 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 9617 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 528:
+#line 3434 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ --parseContext.controlFlowNestingLevel;
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9626 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 529:
+#line 3438 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.push();
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 9636 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 530:
+#line 3443 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9647 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 531:
+#line 3452 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = 0;
+ }
+#line 9655 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 532:
+#line 3455 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-1].interm.intermNode) && (yyvsp[-1].interm.intermNode)->getAsAggregate())
+ (yyvsp[-1].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence);
+ (yyval.interm.intermNode) = (yyvsp[-1].interm.intermNode);
+ }
+#line 9665 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 533:
+#line 3463 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode));
+ if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase ||
+ (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) {
+ parseContext.wrapupSwitchSubsequence(0, (yyvsp[0].interm.intermNode));
+ (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case
+ }
+ }
+#line 9678 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 534:
+#line 3471 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase ||
+ (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) {
+ parseContext.wrapupSwitchSubsequence((yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0, (yyvsp[0].interm.intermNode));
+ (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case
+ } else
+ (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode));
+ }
+#line 9691 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 535:
+#line 3482 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = 0; }
+#line 9697 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 536:
+#line 3483 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[-1].interm.intermTypedNode)); }
+#line 9703 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 537:
+#line 3487 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9711 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 538:
+#line 3491 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.handleSelectionAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode));
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9720 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 539:
+#line 3498 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-2].interm.intermTypedNode));
+ (yyval.interm.intermNode) = parseContext.intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yyvsp[-4].lex).loc);
+ }
+#line 9729 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 540:
+#line 3505 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode);
+ (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode);
+ }
+#line 9738 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 541:
+#line 3509 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode);
+ (yyval.interm.nodePair).node2 = 0;
+ }
+#line 9747 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 542:
+#line 3517 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ parseContext.boolCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode));
+ }
+#line 9756 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 543:
+#line 3521 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.boolCheck((yyvsp[-2].lex).loc, (yyvsp[-3].interm.type));
+
+ TType type((yyvsp[-3].interm.type));
+ TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode));
+ if (initNode)
+ (yyval.interm.intermTypedNode) = initNode->getAsTyped();
+ else
+ (yyval.interm.intermTypedNode) = 0;
+ }
+#line 9771 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 544:
+#line 3534 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9779 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 545:
+#line 3538 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.handleSwitchAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode));
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9788 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 546:
+#line 3545 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // start new switch sequence on the switch stack
+ ++parseContext.controlFlowNestingLevel;
+ ++parseContext.statementNestingLevel;
+ parseContext.switchSequenceStack.push_back(new TIntermSequence);
+ parseContext.switchLevel.push_back(parseContext.statementNestingLevel);
+ parseContext.symbolTable.push();
+ }
+#line 9801 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 547:
+#line 3553 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = parseContext.addSwitch((yyvsp[-7].lex).loc, (yyvsp[-5].interm.intermTypedNode), (yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0);
+ delete parseContext.switchSequenceStack.back();
+ parseContext.switchSequenceStack.pop_back();
+ parseContext.switchLevel.pop_back();
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+#line 9815 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 548:
+#line 3565 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = 0;
+ }
+#line 9823 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 549:
+#line 3568 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9831 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 550:
+#line 3574 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = 0;
+ if (parseContext.switchLevel.size() == 0)
+ parseContext.error((yyvsp[-2].lex).loc, "cannot appear outside switch statement", "case", "");
+ else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel)
+ parseContext.error((yyvsp[-2].lex).loc, "cannot be nested inside control flow", "case", "");
+ else {
+ parseContext.constantValueCheck((yyvsp[-1].interm.intermTypedNode), "case");
+ parseContext.integerCheck((yyvsp[-1].interm.intermTypedNode), "case");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpCase, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc);
+ }
+ }
+#line 9848 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 551:
+#line 3586 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = 0;
+ if (parseContext.switchLevel.size() == 0)
+ parseContext.error((yyvsp[-1].lex).loc, "cannot appear outside switch statement", "default", "");
+ else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel)
+ parseContext.error((yyvsp[-1].lex).loc, "cannot be nested inside control flow", "default", "");
+ else
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDefault, (yyvsp[-1].lex).loc);
+ }
+#line 9862 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 552:
+#line 3598 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9870 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 553:
+#line 3602 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.handleLoopAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode));
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9879 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 554:
+#line 3609 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if (! parseContext.limits.whileLoops)
+ parseContext.error((yyvsp[-1].lex).loc, "while loops not available", "limitation", "");
+ parseContext.symbolTable.push();
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 9892 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 555:
+#line 3617 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, true, (yyvsp[-5].lex).loc);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+#line 9904 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 556:
+#line 3624 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 9914 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 557:
+#line 3629 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if (! parseContext.limits.whileLoops)
+ parseContext.error((yyvsp[-7].lex).loc, "do-while loops not available", "limitation", "");
+
+ parseContext.boolCheck((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode));
+
+ (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[-5].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, false, (yyvsp[-4].lex).loc);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+#line 9930 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 558:
+#line 3640 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.push();
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 9941 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 559:
+#line 3646 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[-3].interm.intermNode), (yyvsp[-5].lex).loc);
+ TIntermLoop* forLoop = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), reinterpret_cast<TIntermTyped*>((yyvsp[-2].interm.nodePair).node1), reinterpret_cast<TIntermTyped*>((yyvsp[-2].interm.nodePair).node2), true, (yyvsp[-6].lex).loc);
+ if (! parseContext.limits.nonInductiveForLoops)
+ parseContext.inductiveLoopCheck((yyvsp[-6].lex).loc, (yyvsp[-3].interm.intermNode), forLoop);
+ (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyval.interm.intermNode), forLoop, (yyvsp[-6].lex).loc);
+ (yyval.interm.intermNode)->getAsAggregate()->setOperator(EOpSequence);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+#line 9958 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 560:
+#line 3661 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9966 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 561:
+#line 3664 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 9974 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 562:
+#line 3670 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 9982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 563:
+#line 3673 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = 0;
+ }
+#line 9990 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 564:
+#line 3679 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode);
+ (yyval.interm.nodePair).node2 = 0;
+ }
+#line 9999 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 565:
+#line 3683 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode);
+ (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 10008 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 566:
+#line 3690 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if (parseContext.loopNestingLevel <= 0)
+ parseContext.error((yyvsp[-1].lex).loc, "continue statement only allowed in loops", "", "");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpContinue, (yyvsp[-1].lex).loc);
+ }
+#line 10018 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 567:
+#line 3695 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0)
+ parseContext.error((yyvsp[-1].lex).loc, "break statement only allowed in switch and loops", "", "");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpBreak, (yyvsp[-1].lex).loc);
+ }
+#line 10028 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 568:
+#line 3700 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].lex).loc);
+ if (parseContext.currentFunctionType->getBasicType() != EbtVoid)
+ parseContext.error((yyvsp[-1].lex).loc, "non-void function must return a value", "return", "");
+ if (parseContext.inMain)
+ parseContext.postEntryPointReturn = true;
+ }
+#line 10040 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 569:
+#line 3707 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = parseContext.handleReturnValue((yyvsp[-2].lex).loc, (yyvsp[-1].interm.intermTypedNode));
+ }
+#line 10048 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 570:
+#line 3710 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "discard");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpKill, (yyvsp[-1].lex).loc);
+ }
+#line 10057 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 571:
+#line 3719 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ parseContext.intermediate.setTreeRoot((yyval.interm.intermNode));
+ }
+#line 10066 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 572:
+#line 3723 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[0].interm.intermNode) != nullptr) {
+ (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode));
+ parseContext.intermediate.setTreeRoot((yyval.interm.intermNode));
+ }
+ }
+#line 10077 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 573:
+#line 3732 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 10085 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 574:
+#line 3735 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 10093 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 575:
+#line 3739 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireProfile((yyvsp[0].lex).loc, ~EEsProfile, "extraneous semicolon");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ~EEsProfile, 460, nullptr, "extraneous semicolon");
+ (yyval.interm.intermNode) = nullptr;
+ }
+#line 10103 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 576:
+#line 3748 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].interm).function = parseContext.handleFunctionDeclarator((yyvsp[0].interm).loc, *(yyvsp[0].interm).function, false /* not prototype */);
+ (yyvsp[0].interm).intermNode = parseContext.handleFunctionDefinition((yyvsp[0].interm).loc, *(yyvsp[0].interm).function);
+ }
+#line 10112 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 577:
+#line 3752 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // May be best done as post process phase on intermediate code
+ if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue)
+ parseContext.error((yyvsp[-2].interm).loc, "function does not return a value:", "", (yyvsp[-2].interm).function->getName().c_str());
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermNode));
+ parseContext.intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[-2].interm).function->getType(), (yyvsp[-2].interm).loc);
+ (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[-2].interm).function->getMangledName().c_str());
+
+ // store the pragma information for debug and optimize and other vendor specific
+ // information. This information can be queried from the parse tree
+ (yyval.interm.intermNode)->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize);
+ (yyval.interm.intermNode)->getAsAggregate()->setDebug(parseContext.contextPragma.debug);
+ (yyval.interm.intermNode)->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable);
+ }
+#line 10132 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 578:
+#line 3771 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.attributes) = (yyvsp[-2].interm.attributes);
+ parseContext.requireExtensions((yyvsp[-4].lex).loc, 1, &E_GL_EXT_control_flow_attributes, "attribute");
+ }
+#line 10141 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 579:
+#line 3777 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.attributes) = (yyvsp[0].interm.attributes);
+ }
+#line 10149 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 580:
+#line 3780 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.attributes) = parseContext.mergeAttributes((yyvsp[-2].interm.attributes), (yyvsp[0].interm.attributes));
+ }
+#line 10157 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 581:
+#line 3785 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[0].lex).string);
+ }
+#line 10165 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 582:
+#line 3788 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[-3].lex).string, (yyvsp[-1].interm.intermTypedNode));
+ }
+#line 10173 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+
+#line 10177 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now 'shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (pParseContext, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
+ {
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
+ {
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
+ }
+ yyerror (pParseContext, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
+ }
+# undef YYSYNTAX_ERROR
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, pParseContext);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, pParseContext);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (pParseContext, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, pParseContext);
+ }
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, pParseContext);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ return yyresult;
+}
+#line 3793 "MachineIndependent/glslang.y" /* yacc.c:1906 */
+
diff --git a/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h b/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
new file mode 100644
index 0000000000..f4f4114730
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
@@ -0,0 +1,512 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ CONST = 258,
+ BOOL = 259,
+ INT = 260,
+ UINT = 261,
+ FLOAT = 262,
+ BVEC2 = 263,
+ BVEC3 = 264,
+ BVEC4 = 265,
+ IVEC2 = 266,
+ IVEC3 = 267,
+ IVEC4 = 268,
+ UVEC2 = 269,
+ UVEC3 = 270,
+ UVEC4 = 271,
+ VEC2 = 272,
+ VEC3 = 273,
+ VEC4 = 274,
+ MAT2 = 275,
+ MAT3 = 276,
+ MAT4 = 277,
+ MAT2X2 = 278,
+ MAT2X3 = 279,
+ MAT2X4 = 280,
+ MAT3X2 = 281,
+ MAT3X3 = 282,
+ MAT3X4 = 283,
+ MAT4X2 = 284,
+ MAT4X3 = 285,
+ MAT4X4 = 286,
+ SAMPLER2D = 287,
+ SAMPLER3D = 288,
+ SAMPLERCUBE = 289,
+ SAMPLER2DSHADOW = 290,
+ SAMPLERCUBESHADOW = 291,
+ SAMPLER2DARRAY = 292,
+ SAMPLER2DARRAYSHADOW = 293,
+ ISAMPLER2D = 294,
+ ISAMPLER3D = 295,
+ ISAMPLERCUBE = 296,
+ ISAMPLER2DARRAY = 297,
+ USAMPLER2D = 298,
+ USAMPLER3D = 299,
+ USAMPLERCUBE = 300,
+ USAMPLER2DARRAY = 301,
+ SAMPLER = 302,
+ SAMPLERSHADOW = 303,
+ TEXTURE2D = 304,
+ TEXTURE3D = 305,
+ TEXTURECUBE = 306,
+ TEXTURE2DARRAY = 307,
+ ITEXTURE2D = 308,
+ ITEXTURE3D = 309,
+ ITEXTURECUBE = 310,
+ ITEXTURE2DARRAY = 311,
+ UTEXTURE2D = 312,
+ UTEXTURE3D = 313,
+ UTEXTURECUBE = 314,
+ UTEXTURE2DARRAY = 315,
+ ATTRIBUTE = 316,
+ VARYING = 317,
+ FLOAT16_T = 318,
+ FLOAT32_T = 319,
+ DOUBLE = 320,
+ FLOAT64_T = 321,
+ INT64_T = 322,
+ UINT64_T = 323,
+ INT32_T = 324,
+ UINT32_T = 325,
+ INT16_T = 326,
+ UINT16_T = 327,
+ INT8_T = 328,
+ UINT8_T = 329,
+ I64VEC2 = 330,
+ I64VEC3 = 331,
+ I64VEC4 = 332,
+ U64VEC2 = 333,
+ U64VEC3 = 334,
+ U64VEC4 = 335,
+ I32VEC2 = 336,
+ I32VEC3 = 337,
+ I32VEC4 = 338,
+ U32VEC2 = 339,
+ U32VEC3 = 340,
+ U32VEC4 = 341,
+ I16VEC2 = 342,
+ I16VEC3 = 343,
+ I16VEC4 = 344,
+ U16VEC2 = 345,
+ U16VEC3 = 346,
+ U16VEC4 = 347,
+ I8VEC2 = 348,
+ I8VEC3 = 349,
+ I8VEC4 = 350,
+ U8VEC2 = 351,
+ U8VEC3 = 352,
+ U8VEC4 = 353,
+ DVEC2 = 354,
+ DVEC3 = 355,
+ DVEC4 = 356,
+ DMAT2 = 357,
+ DMAT3 = 358,
+ DMAT4 = 359,
+ F16VEC2 = 360,
+ F16VEC3 = 361,
+ F16VEC4 = 362,
+ F16MAT2 = 363,
+ F16MAT3 = 364,
+ F16MAT4 = 365,
+ F32VEC2 = 366,
+ F32VEC3 = 367,
+ F32VEC4 = 368,
+ F32MAT2 = 369,
+ F32MAT3 = 370,
+ F32MAT4 = 371,
+ F64VEC2 = 372,
+ F64VEC3 = 373,
+ F64VEC4 = 374,
+ F64MAT2 = 375,
+ F64MAT3 = 376,
+ F64MAT4 = 377,
+ DMAT2X2 = 378,
+ DMAT2X3 = 379,
+ DMAT2X4 = 380,
+ DMAT3X2 = 381,
+ DMAT3X3 = 382,
+ DMAT3X4 = 383,
+ DMAT4X2 = 384,
+ DMAT4X3 = 385,
+ DMAT4X4 = 386,
+ F16MAT2X2 = 387,
+ F16MAT2X3 = 388,
+ F16MAT2X4 = 389,
+ F16MAT3X2 = 390,
+ F16MAT3X3 = 391,
+ F16MAT3X4 = 392,
+ F16MAT4X2 = 393,
+ F16MAT4X3 = 394,
+ F16MAT4X4 = 395,
+ F32MAT2X2 = 396,
+ F32MAT2X3 = 397,
+ F32MAT2X4 = 398,
+ F32MAT3X2 = 399,
+ F32MAT3X3 = 400,
+ F32MAT3X4 = 401,
+ F32MAT4X2 = 402,
+ F32MAT4X3 = 403,
+ F32MAT4X4 = 404,
+ F64MAT2X2 = 405,
+ F64MAT2X3 = 406,
+ F64MAT2X4 = 407,
+ F64MAT3X2 = 408,
+ F64MAT3X3 = 409,
+ F64MAT3X4 = 410,
+ F64MAT4X2 = 411,
+ F64MAT4X3 = 412,
+ F64MAT4X4 = 413,
+ ATOMIC_UINT = 414,
+ ACCSTRUCTNV = 415,
+ FCOOPMATNV = 416,
+ ICOOPMATNV = 417,
+ UCOOPMATNV = 418,
+ SAMPLERCUBEARRAY = 419,
+ SAMPLERCUBEARRAYSHADOW = 420,
+ ISAMPLERCUBEARRAY = 421,
+ USAMPLERCUBEARRAY = 422,
+ SAMPLER1D = 423,
+ SAMPLER1DARRAY = 424,
+ SAMPLER1DARRAYSHADOW = 425,
+ ISAMPLER1D = 426,
+ SAMPLER1DSHADOW = 427,
+ SAMPLER2DRECT = 428,
+ SAMPLER2DRECTSHADOW = 429,
+ ISAMPLER2DRECT = 430,
+ USAMPLER2DRECT = 431,
+ SAMPLERBUFFER = 432,
+ ISAMPLERBUFFER = 433,
+ USAMPLERBUFFER = 434,
+ SAMPLER2DMS = 435,
+ ISAMPLER2DMS = 436,
+ USAMPLER2DMS = 437,
+ SAMPLER2DMSARRAY = 438,
+ ISAMPLER2DMSARRAY = 439,
+ USAMPLER2DMSARRAY = 440,
+ SAMPLEREXTERNALOES = 441,
+ SAMPLEREXTERNAL2DY2YEXT = 442,
+ ISAMPLER1DARRAY = 443,
+ USAMPLER1D = 444,
+ USAMPLER1DARRAY = 445,
+ F16SAMPLER1D = 446,
+ F16SAMPLER2D = 447,
+ F16SAMPLER3D = 448,
+ F16SAMPLER2DRECT = 449,
+ F16SAMPLERCUBE = 450,
+ F16SAMPLER1DARRAY = 451,
+ F16SAMPLER2DARRAY = 452,
+ F16SAMPLERCUBEARRAY = 453,
+ F16SAMPLERBUFFER = 454,
+ F16SAMPLER2DMS = 455,
+ F16SAMPLER2DMSARRAY = 456,
+ F16SAMPLER1DSHADOW = 457,
+ F16SAMPLER2DSHADOW = 458,
+ F16SAMPLER1DARRAYSHADOW = 459,
+ F16SAMPLER2DARRAYSHADOW = 460,
+ F16SAMPLER2DRECTSHADOW = 461,
+ F16SAMPLERCUBESHADOW = 462,
+ F16SAMPLERCUBEARRAYSHADOW = 463,
+ IMAGE1D = 464,
+ IIMAGE1D = 465,
+ UIMAGE1D = 466,
+ IMAGE2D = 467,
+ IIMAGE2D = 468,
+ UIMAGE2D = 469,
+ IMAGE3D = 470,
+ IIMAGE3D = 471,
+ UIMAGE3D = 472,
+ IMAGE2DRECT = 473,
+ IIMAGE2DRECT = 474,
+ UIMAGE2DRECT = 475,
+ IMAGECUBE = 476,
+ IIMAGECUBE = 477,
+ UIMAGECUBE = 478,
+ IMAGEBUFFER = 479,
+ IIMAGEBUFFER = 480,
+ UIMAGEBUFFER = 481,
+ IMAGE1DARRAY = 482,
+ IIMAGE1DARRAY = 483,
+ UIMAGE1DARRAY = 484,
+ IMAGE2DARRAY = 485,
+ IIMAGE2DARRAY = 486,
+ UIMAGE2DARRAY = 487,
+ IMAGECUBEARRAY = 488,
+ IIMAGECUBEARRAY = 489,
+ UIMAGECUBEARRAY = 490,
+ IMAGE2DMS = 491,
+ IIMAGE2DMS = 492,
+ UIMAGE2DMS = 493,
+ IMAGE2DMSARRAY = 494,
+ IIMAGE2DMSARRAY = 495,
+ UIMAGE2DMSARRAY = 496,
+ F16IMAGE1D = 497,
+ F16IMAGE2D = 498,
+ F16IMAGE3D = 499,
+ F16IMAGE2DRECT = 500,
+ F16IMAGECUBE = 501,
+ F16IMAGE1DARRAY = 502,
+ F16IMAGE2DARRAY = 503,
+ F16IMAGECUBEARRAY = 504,
+ F16IMAGEBUFFER = 505,
+ F16IMAGE2DMS = 506,
+ F16IMAGE2DMSARRAY = 507,
+ TEXTURECUBEARRAY = 508,
+ ITEXTURECUBEARRAY = 509,
+ UTEXTURECUBEARRAY = 510,
+ TEXTURE1D = 511,
+ ITEXTURE1D = 512,
+ UTEXTURE1D = 513,
+ TEXTURE1DARRAY = 514,
+ ITEXTURE1DARRAY = 515,
+ UTEXTURE1DARRAY = 516,
+ TEXTURE2DRECT = 517,
+ ITEXTURE2DRECT = 518,
+ UTEXTURE2DRECT = 519,
+ TEXTUREBUFFER = 520,
+ ITEXTUREBUFFER = 521,
+ UTEXTUREBUFFER = 522,
+ TEXTURE2DMS = 523,
+ ITEXTURE2DMS = 524,
+ UTEXTURE2DMS = 525,
+ TEXTURE2DMSARRAY = 526,
+ ITEXTURE2DMSARRAY = 527,
+ UTEXTURE2DMSARRAY = 528,
+ F16TEXTURE1D = 529,
+ F16TEXTURE2D = 530,
+ F16TEXTURE3D = 531,
+ F16TEXTURE2DRECT = 532,
+ F16TEXTURECUBE = 533,
+ F16TEXTURE1DARRAY = 534,
+ F16TEXTURE2DARRAY = 535,
+ F16TEXTURECUBEARRAY = 536,
+ F16TEXTUREBUFFER = 537,
+ F16TEXTURE2DMS = 538,
+ F16TEXTURE2DMSARRAY = 539,
+ SUBPASSINPUT = 540,
+ SUBPASSINPUTMS = 541,
+ ISUBPASSINPUT = 542,
+ ISUBPASSINPUTMS = 543,
+ USUBPASSINPUT = 544,
+ USUBPASSINPUTMS = 545,
+ F16SUBPASSINPUT = 546,
+ F16SUBPASSINPUTMS = 547,
+ LEFT_OP = 548,
+ RIGHT_OP = 549,
+ INC_OP = 550,
+ DEC_OP = 551,
+ LE_OP = 552,
+ GE_OP = 553,
+ EQ_OP = 554,
+ NE_OP = 555,
+ AND_OP = 556,
+ OR_OP = 557,
+ XOR_OP = 558,
+ MUL_ASSIGN = 559,
+ DIV_ASSIGN = 560,
+ ADD_ASSIGN = 561,
+ MOD_ASSIGN = 562,
+ LEFT_ASSIGN = 563,
+ RIGHT_ASSIGN = 564,
+ AND_ASSIGN = 565,
+ XOR_ASSIGN = 566,
+ OR_ASSIGN = 567,
+ SUB_ASSIGN = 568,
+ LEFT_PAREN = 569,
+ RIGHT_PAREN = 570,
+ LEFT_BRACKET = 571,
+ RIGHT_BRACKET = 572,
+ LEFT_BRACE = 573,
+ RIGHT_BRACE = 574,
+ DOT = 575,
+ COMMA = 576,
+ COLON = 577,
+ EQUAL = 578,
+ SEMICOLON = 579,
+ BANG = 580,
+ DASH = 581,
+ TILDE = 582,
+ PLUS = 583,
+ STAR = 584,
+ SLASH = 585,
+ PERCENT = 586,
+ LEFT_ANGLE = 587,
+ RIGHT_ANGLE = 588,
+ VERTICAL_BAR = 589,
+ CARET = 590,
+ AMPERSAND = 591,
+ QUESTION = 592,
+ INVARIANT = 593,
+ HIGH_PRECISION = 594,
+ MEDIUM_PRECISION = 595,
+ LOW_PRECISION = 596,
+ PRECISION = 597,
+ PACKED = 598,
+ RESOURCE = 599,
+ SUPERP = 600,
+ FLOATCONSTANT = 601,
+ INTCONSTANT = 602,
+ UINTCONSTANT = 603,
+ BOOLCONSTANT = 604,
+ IDENTIFIER = 605,
+ TYPE_NAME = 606,
+ CENTROID = 607,
+ IN = 608,
+ OUT = 609,
+ INOUT = 610,
+ STRUCT = 611,
+ VOID = 612,
+ WHILE = 613,
+ BREAK = 614,
+ CONTINUE = 615,
+ DO = 616,
+ ELSE = 617,
+ FOR = 618,
+ IF = 619,
+ DISCARD = 620,
+ RETURN = 621,
+ SWITCH = 622,
+ CASE = 623,
+ DEFAULT = 624,
+ UNIFORM = 625,
+ SHARED = 626,
+ BUFFER = 627,
+ FLAT = 628,
+ SMOOTH = 629,
+ LAYOUT = 630,
+ DOUBLECONSTANT = 631,
+ INT16CONSTANT = 632,
+ UINT16CONSTANT = 633,
+ FLOAT16CONSTANT = 634,
+ INT32CONSTANT = 635,
+ UINT32CONSTANT = 636,
+ INT64CONSTANT = 637,
+ UINT64CONSTANT = 638,
+ SUBROUTINE = 639,
+ DEMOTE = 640,
+ PAYLOADNV = 641,
+ PAYLOADINNV = 642,
+ HITATTRNV = 643,
+ CALLDATANV = 644,
+ CALLDATAINNV = 645,
+ PATCH = 646,
+ SAMPLE = 647,
+ NONUNIFORM = 648,
+ COHERENT = 649,
+ VOLATILE = 650,
+ RESTRICT = 651,
+ READONLY = 652,
+ WRITEONLY = 653,
+ DEVICECOHERENT = 654,
+ QUEUEFAMILYCOHERENT = 655,
+ WORKGROUPCOHERENT = 656,
+ SUBGROUPCOHERENT = 657,
+ NONPRIVATE = 658,
+ NOPERSPECTIVE = 659,
+ EXPLICITINTERPAMD = 660,
+ PERVERTEXNV = 661,
+ PERPRIMITIVENV = 662,
+ PERVIEWNV = 663,
+ PERTASKNV = 664,
+ PRECISE = 665
+ };
+#endif
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 96 "MachineIndependent/glslang.y" /* yacc.c:1909 */
+
+ struct {
+ glslang::TSourceLoc loc;
+ union {
+ glslang::TString *string;
+ int i;
+ unsigned int u;
+ long long i64;
+ unsigned long long u64;
+ bool b;
+ double d;
+ };
+ glslang::TSymbol* symbol;
+ } lex;
+ struct {
+ glslang::TSourceLoc loc;
+ glslang::TOperator op;
+ union {
+ TIntermNode* intermNode;
+ glslang::TIntermNodePair nodePair;
+ glslang::TIntermTyped* intermTypedNode;
+ glslang::TAttributes* attributes;
+ };
+ union {
+ glslang::TPublicType type;
+ glslang::TFunction* function;
+ glslang::TParameter param;
+ glslang::TTypeLoc typeLine;
+ glslang::TTypeList* typeList;
+ glslang::TArraySizes* arraySizes;
+ glslang::TIdentifierList* identifierList;
+ };
+ glslang::TArraySizes* typeParameters;
+ } interm;
+
+#line 501 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int yyparse (glslang::TParseContext* pParseContext);
+
+#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */
diff --git a/thirdparty/glslang/glslang/MachineIndependent/intermOut.cpp b/thirdparty/glslang/glslang/MachineIndependent/intermOut.cpp
new file mode 100644
index 0000000000..3a93aedafb
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/intermOut.cpp
@@ -0,0 +1,1539 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2012-2016 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef GLSLANG_WEB
+
+#include "localintermediate.h"
+#include "../Include/InfoSink.h"
+
+#ifdef _MSC_VER
+#include <cfloat>
+#else
+#include <cmath>
+#endif
+#include <cstdint>
+
+namespace {
+
+bool IsInfinity(double x) {
+#ifdef _MSC_VER
+ switch (_fpclass(x)) {
+ case _FPCLASS_NINF:
+ case _FPCLASS_PINF:
+ return true;
+ default:
+ return false;
+ }
+#else
+ return std::isinf(x);
+#endif
+}
+
+bool IsNan(double x) {
+#ifdef _MSC_VER
+ switch (_fpclass(x)) {
+ case _FPCLASS_SNAN:
+ case _FPCLASS_QNAN:
+ return true;
+ default:
+ return false;
+ }
+#else
+ return std::isnan(x);
+#endif
+}
+
+}
+
+namespace glslang {
+
+//
+// Two purposes:
+// 1. Show an example of how to iterate tree. Functions can
+// also directly call Traverse() on children themselves to
+// have finer grained control over the process than shown here.
+// See the last function for how to get started.
+// 2. Print out a text based description of the tree.
+//
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TOutputTraverser : public TIntermTraverser {
+public:
+ TOutputTraverser(TInfoSink& i) : infoSink(i), extraOutput(NoExtraOutput) { }
+
+ enum EExtraOutput {
+ NoExtraOutput,
+ BinaryDoubleOutput
+ };
+ void setDoubleOutput(EExtraOutput extra) { extraOutput = extra; }
+
+ virtual bool visitBinary(TVisit, TIntermBinary* node);
+ virtual bool visitUnary(TVisit, TIntermUnary* node);
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node);
+ virtual bool visitSelection(TVisit, TIntermSelection* node);
+ virtual void visitConstantUnion(TIntermConstantUnion* node);
+ virtual void visitSymbol(TIntermSymbol* node);
+ virtual bool visitLoop(TVisit, TIntermLoop* node);
+ virtual bool visitBranch(TVisit, TIntermBranch* node);
+ virtual bool visitSwitch(TVisit, TIntermSwitch* node);
+
+ TInfoSink& infoSink;
+protected:
+ TOutputTraverser(TOutputTraverser&);
+ TOutputTraverser& operator=(TOutputTraverser&);
+
+ EExtraOutput extraOutput;
+};
+
+//
+// Helper functions for printing, not part of traversing.
+//
+
+static void OutputTreeText(TInfoSink& infoSink, const TIntermNode* node, const int depth)
+{
+ int i;
+
+ infoSink.debug << node->getLoc().string << ":";
+ if (node->getLoc().line)
+ infoSink.debug << node->getLoc().line;
+ else
+ infoSink.debug << "? ";
+
+ for (i = 0; i < depth; ++i)
+ infoSink.debug << " ";
+}
+
+//
+// The rest of the file are the traversal functions. The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children. If you process children yourself,
+// return false.
+//
+
+bool TOutputTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpAssign: out.debug << "move second child to first child"; break;
+ case EOpAddAssign: out.debug << "add second child into first child"; break;
+ case EOpSubAssign: out.debug << "subtract second child into first child"; break;
+ case EOpMulAssign: out.debug << "multiply second child into first child"; break;
+ case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
+ case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break;
+ case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break;
+ case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
+ case EOpDivAssign: out.debug << "divide second child into first child"; break;
+ case EOpModAssign: out.debug << "mod second child into first child"; break;
+ case EOpAndAssign: out.debug << "and second child into first child"; break;
+ case EOpInclusiveOrAssign: out.debug << "or second child into first child"; break;
+ case EOpExclusiveOrAssign: out.debug << "exclusive or second child into first child"; break;
+ case EOpLeftShiftAssign: out.debug << "left shift second child into first child"; break;
+ case EOpRightShiftAssign: out.debug << "right shift second child into first child"; break;
+
+ case EOpIndexDirect: out.debug << "direct index"; break;
+ case EOpIndexIndirect: out.debug << "indirect index"; break;
+ case EOpIndexDirectStruct:
+ {
+ bool reference = node->getLeft()->getType().isReference();
+ const TTypeList *members = reference ? node->getLeft()->getType().getReferentType()->getStruct() : node->getLeft()->getType().getStruct();
+ out.debug << (*members)[node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()].type->getFieldName();
+ out.debug << ": direct index for structure"; break;
+ }
+ case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
+ case EOpMatrixSwizzle: out.debug << "matrix swizzle"; break;
+
+ case EOpAdd: out.debug << "add"; break;
+ case EOpSub: out.debug << "subtract"; break;
+ case EOpMul: out.debug << "component-wise multiply"; break;
+ case EOpDiv: out.debug << "divide"; break;
+ case EOpMod: out.debug << "mod"; break;
+ case EOpRightShift: out.debug << "right-shift"; break;
+ case EOpLeftShift: out.debug << "left-shift"; break;
+ case EOpAnd: out.debug << "bitwise and"; break;
+ case EOpInclusiveOr: out.debug << "inclusive-or"; break;
+ case EOpExclusiveOr: out.debug << "exclusive-or"; break;
+ case EOpEqual: out.debug << "Compare Equal"; break;
+ case EOpNotEqual: out.debug << "Compare Not Equal"; break;
+ case EOpLessThan: out.debug << "Compare Less Than"; break;
+ case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
+ case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
+ case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+ case EOpVectorEqual: out.debug << "Equal"; break;
+ case EOpVectorNotEqual: out.debug << "NotEqual"; break;
+
+ case EOpVectorTimesScalar: out.debug << "vector-scale"; break;
+ case EOpVectorTimesMatrix: out.debug << "vector-times-matrix"; break;
+ case EOpMatrixTimesVector: out.debug << "matrix-times-vector"; break;
+ case EOpMatrixTimesScalar: out.debug << "matrix-scale"; break;
+ case EOpMatrixTimesMatrix: out.debug << "matrix-multiply"; break;
+
+ case EOpLogicalOr: out.debug << "logical-or"; break;
+ case EOpLogicalXor: out.debug << "logical-xor"; break;
+ case EOpLogicalAnd: out.debug << "logical-and"; break;
+
+ case EOpAbsDifference: out.debug << "absoluteDifference"; break;
+ case EOpAddSaturate: out.debug << "addSaturate"; break;
+ case EOpSubSaturate: out.debug << "subtractSaturate"; break;
+ case EOpAverage: out.debug << "average"; break;
+ case EOpAverageRounded: out.debug << "averageRounded"; break;
+ case EOpMul32x16: out.debug << "multiply32x16"; break;
+
+ default: out.debug << "<unknown op>";
+ }
+
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpNegative: out.debug << "Negate value"; break;
+ case EOpVectorLogicalNot:
+ case EOpLogicalNot: out.debug << "Negate conditional"; break;
+ case EOpBitwiseNot: out.debug << "Bitwise not"; break;
+
+ case EOpPostIncrement: out.debug << "Post-Increment"; break;
+ case EOpPostDecrement: out.debug << "Post-Decrement"; break;
+ case EOpPreIncrement: out.debug << "Pre-Increment"; break;
+ case EOpPreDecrement: out.debug << "Pre-Decrement"; break;
+ case EOpCopyObject: out.debug << "copy object"; break;
+
+ // * -> bool
+ case EOpConvInt8ToBool: out.debug << "Convert int8_t to bool"; break;
+ case EOpConvUint8ToBool: out.debug << "Convert uint8_t to bool"; break;
+ case EOpConvInt16ToBool: out.debug << "Convert int16_t to bool"; break;
+ case EOpConvUint16ToBool: out.debug << "Convert uint16_t to bool";break;
+ case EOpConvIntToBool: out.debug << "Convert int to bool"; break;
+ case EOpConvUintToBool: out.debug << "Convert uint to bool"; break;
+ case EOpConvInt64ToBool: out.debug << "Convert int64 to bool"; break;
+ case EOpConvUint64ToBool: out.debug << "Convert uint64 to bool"; break;
+ case EOpConvFloat16ToBool: out.debug << "Convert float16_t to bool"; break;
+ case EOpConvFloatToBool: out.debug << "Convert float to bool"; break;
+ case EOpConvDoubleToBool: out.debug << "Convert double to bool"; break;
+
+ // bool -> *
+ case EOpConvBoolToInt8: out.debug << "Convert bool to int8_t"; break;
+ case EOpConvBoolToUint8: out.debug << "Convert bool to uint8_t"; break;
+ case EOpConvBoolToInt16: out.debug << "Convert bool to in16t_t"; break;
+ case EOpConvBoolToUint16: out.debug << "Convert bool to uint16_t";break;
+ case EOpConvBoolToInt: out.debug << "Convert bool to int" ; break;
+ case EOpConvBoolToUint: out.debug << "Convert bool to uint"; break;
+ case EOpConvBoolToInt64: out.debug << "Convert bool to int64"; break;
+ case EOpConvBoolToUint64: out.debug << "Convert bool to uint64";break;
+ case EOpConvBoolToFloat16: out.debug << "Convert bool to float16_t"; break;
+ case EOpConvBoolToFloat: out.debug << "Convert bool to float"; break;
+ case EOpConvBoolToDouble: out.debug << "Convert bool to double"; break;
+
+ // int8_t -> (u)int*
+ case EOpConvInt8ToInt16: out.debug << "Convert int8_t to int16_t";break;
+ case EOpConvInt8ToInt: out.debug << "Convert int8_t to int"; break;
+ case EOpConvInt8ToInt64: out.debug << "Convert int8_t to int64"; break;
+ case EOpConvInt8ToUint8: out.debug << "Convert int8_t to uint8_t";break;
+ case EOpConvInt8ToUint16: out.debug << "Convert int8_t to uint16_t";break;
+ case EOpConvInt8ToUint: out.debug << "Convert int8_t to uint"; break;
+ case EOpConvInt8ToUint64: out.debug << "Convert int8_t to uint64"; break;
+
+ // uint8_t -> (u)int*
+ case EOpConvUint8ToInt8: out.debug << "Convert uint8_t to int8_t";break;
+ case EOpConvUint8ToInt16: out.debug << "Convert uint8_t to int16_t";break;
+ case EOpConvUint8ToInt: out.debug << "Convert uint8_t to int"; break;
+ case EOpConvUint8ToInt64: out.debug << "Convert uint8_t to int64"; break;
+ case EOpConvUint8ToUint16: out.debug << "Convert uint8_t to uint16_t";break;
+ case EOpConvUint8ToUint: out.debug << "Convert uint8_t to uint"; break;
+ case EOpConvUint8ToUint64: out.debug << "Convert uint8_t to uint64"; break;
+
+ // int8_t -> float*
+ case EOpConvInt8ToFloat16: out.debug << "Convert int8_t to float16_t";break;
+ case EOpConvInt8ToFloat: out.debug << "Convert int8_t to float"; break;
+ case EOpConvInt8ToDouble: out.debug << "Convert int8_t to double"; break;
+
+ // uint8_t -> float*
+ case EOpConvUint8ToFloat16: out.debug << "Convert uint8_t to float16_t";break;
+ case EOpConvUint8ToFloat: out.debug << "Convert uint8_t to float"; break;
+ case EOpConvUint8ToDouble: out.debug << "Convert uint8_t to double"; break;
+
+ // int16_t -> (u)int*
+ case EOpConvInt16ToInt8: out.debug << "Convert int16_t to int8_t";break;
+ case EOpConvInt16ToInt: out.debug << "Convert int16_t to int"; break;
+ case EOpConvInt16ToInt64: out.debug << "Convert int16_t to int64"; break;
+ case EOpConvInt16ToUint8: out.debug << "Convert int16_t to uint8_t";break;
+ case EOpConvInt16ToUint16: out.debug << "Convert int16_t to uint16_t";break;
+ case EOpConvInt16ToUint: out.debug << "Convert int16_t to uint"; break;
+ case EOpConvInt16ToUint64: out.debug << "Convert int16_t to uint64"; break;
+
+ // int16_t -> float*
+ case EOpConvInt16ToFloat16: out.debug << "Convert int16_t to float16_t";break;
+ case EOpConvInt16ToFloat: out.debug << "Convert int16_t to float"; break;
+ case EOpConvInt16ToDouble: out.debug << "Convert int16_t to double"; break;
+
+ // uint16_t -> (u)int*
+ case EOpConvUint16ToInt8: out.debug << "Convert uint16_t to int8_t";break;
+ case EOpConvUint16ToInt16: out.debug << "Convert uint16_t to int16_t";break;
+ case EOpConvUint16ToInt: out.debug << "Convert uint16_t to int"; break;
+ case EOpConvUint16ToInt64: out.debug << "Convert uint16_t to int64"; break;
+ case EOpConvUint16ToUint8: out.debug << "Convert uint16_t to uint8_t";break;
+ case EOpConvUint16ToUint: out.debug << "Convert uint16_t to uint"; break;
+ case EOpConvUint16ToUint64: out.debug << "Convert uint16_t to uint64"; break;
+
+ // uint16_t -> float*
+ case EOpConvUint16ToFloat16: out.debug << "Convert uint16_t to float16_t";break;
+ case EOpConvUint16ToFloat: out.debug << "Convert uint16_t to float"; break;
+ case EOpConvUint16ToDouble: out.debug << "Convert uint16_t to double"; break;
+
+ // int32_t -> (u)int*
+ case EOpConvIntToInt8: out.debug << "Convert int to int8_t";break;
+ case EOpConvIntToInt16: out.debug << "Convert int to int16_t";break;
+ case EOpConvIntToInt64: out.debug << "Convert int to int64"; break;
+ case EOpConvIntToUint8: out.debug << "Convert int to uint8_t";break;
+ case EOpConvIntToUint16: out.debug << "Convert int to uint16_t";break;
+ case EOpConvIntToUint: out.debug << "Convert int to uint"; break;
+ case EOpConvIntToUint64: out.debug << "Convert int to uint64"; break;
+
+ // int32_t -> float*
+ case EOpConvIntToFloat16: out.debug << "Convert int to float16_t";break;
+ case EOpConvIntToFloat: out.debug << "Convert int to float"; break;
+ case EOpConvIntToDouble: out.debug << "Convert int to double"; break;
+
+ // uint32_t -> (u)int*
+ case EOpConvUintToInt8: out.debug << "Convert uint to int8_t";break;
+ case EOpConvUintToInt16: out.debug << "Convert uint to int16_t";break;
+ case EOpConvUintToInt: out.debug << "Convert uint to int";break;
+ case EOpConvUintToInt64: out.debug << "Convert uint to int64"; break;
+ case EOpConvUintToUint8: out.debug << "Convert uint to uint8_t";break;
+ case EOpConvUintToUint16: out.debug << "Convert uint to uint16_t";break;
+ case EOpConvUintToUint64: out.debug << "Convert uint to uint64"; break;
+
+ // uint32_t -> float*
+ case EOpConvUintToFloat16: out.debug << "Convert uint to float16_t";break;
+ case EOpConvUintToFloat: out.debug << "Convert uint to float"; break;
+ case EOpConvUintToDouble: out.debug << "Convert uint to double"; break;
+
+ // int64 -> (u)int*
+ case EOpConvInt64ToInt8: out.debug << "Convert int64 to int8_t"; break;
+ case EOpConvInt64ToInt16: out.debug << "Convert int64 to int16_t"; break;
+ case EOpConvInt64ToInt: out.debug << "Convert int64 to int"; break;
+ case EOpConvInt64ToUint8: out.debug << "Convert int64 to uint8_t";break;
+ case EOpConvInt64ToUint16: out.debug << "Convert int64 to uint16_t";break;
+ case EOpConvInt64ToUint: out.debug << "Convert int64 to uint"; break;
+ case EOpConvInt64ToUint64: out.debug << "Convert int64 to uint64"; break;
+
+ // int64 -> float*
+ case EOpConvInt64ToFloat16: out.debug << "Convert int64 to float16_t";break;
+ case EOpConvInt64ToFloat: out.debug << "Convert int64 to float"; break;
+ case EOpConvInt64ToDouble: out.debug << "Convert int64 to double"; break;
+
+ // uint64 -> (u)int*
+ case EOpConvUint64ToInt8: out.debug << "Convert uint64 to int8_t";break;
+ case EOpConvUint64ToInt16: out.debug << "Convert uint64 to int16_t";break;
+ case EOpConvUint64ToInt: out.debug << "Convert uint64 to int"; break;
+ case EOpConvUint64ToInt64: out.debug << "Convert uint64 to int64"; break;
+ case EOpConvUint64ToUint8: out.debug << "Convert uint64 to uint8_t";break;
+ case EOpConvUint64ToUint16: out.debug << "Convert uint64 to uint16"; break;
+ case EOpConvUint64ToUint: out.debug << "Convert uint64 to uint"; break;
+
+ // uint64 -> float*
+ case EOpConvUint64ToFloat16: out.debug << "Convert uint64 to float16_t";break;
+ case EOpConvUint64ToFloat: out.debug << "Convert uint64 to float"; break;
+ case EOpConvUint64ToDouble: out.debug << "Convert uint64 to double"; break;
+
+ // float16_t -> int*
+ case EOpConvFloat16ToInt8: out.debug << "Convert float16_t to int8_t"; break;
+ case EOpConvFloat16ToInt16: out.debug << "Convert float16_t to int16_t"; break;
+ case EOpConvFloat16ToInt: out.debug << "Convert float16_t to int"; break;
+ case EOpConvFloat16ToInt64: out.debug << "Convert float16_t to int64"; break;
+
+ // float16_t -> uint*
+ case EOpConvFloat16ToUint8: out.debug << "Convert float16_t to uint8_t"; break;
+ case EOpConvFloat16ToUint16: out.debug << "Convert float16_t to uint16_t"; break;
+ case EOpConvFloat16ToUint: out.debug << "Convert float16_t to uint"; break;
+ case EOpConvFloat16ToUint64: out.debug << "Convert float16_t to uint64"; break;
+
+ // float16_t -> float*
+ case EOpConvFloat16ToFloat: out.debug << "Convert float16_t to float"; break;
+ case EOpConvFloat16ToDouble: out.debug << "Convert float16_t to double"; break;
+
+ // float32 -> float*
+ case EOpConvFloatToFloat16: out.debug << "Convert float to float16_t"; break;
+ case EOpConvFloatToDouble: out.debug << "Convert float to double"; break;
+
+ // float32_t -> int*
+ case EOpConvFloatToInt8: out.debug << "Convert float to int8_t"; break;
+ case EOpConvFloatToInt16: out.debug << "Convert float to int16_t"; break;
+ case EOpConvFloatToInt: out.debug << "Convert float to int"; break;
+ case EOpConvFloatToInt64: out.debug << "Convert float to int64"; break;
+
+ // float32_t -> uint*
+ case EOpConvFloatToUint8: out.debug << "Convert float to uint8_t"; break;
+ case EOpConvFloatToUint16: out.debug << "Convert float to uint16_t"; break;
+ case EOpConvFloatToUint: out.debug << "Convert float to uint"; break;
+ case EOpConvFloatToUint64: out.debug << "Convert float to uint64"; break;
+
+ // double -> float*
+ case EOpConvDoubleToFloat16: out.debug << "Convert double to float16_t"; break;
+ case EOpConvDoubleToFloat: out.debug << "Convert double to float"; break;
+
+ // double -> int*
+ case EOpConvDoubleToInt8: out.debug << "Convert double to int8_t"; break;
+ case EOpConvDoubleToInt16: out.debug << "Convert double to int16_t"; break;
+ case EOpConvDoubleToInt: out.debug << "Convert double to int"; break;
+ case EOpConvDoubleToInt64: out.debug << "Convert double to int64"; break;
+
+ // float32_t -> uint*
+ case EOpConvDoubleToUint8: out.debug << "Convert double to uint8_t"; break;
+ case EOpConvDoubleToUint16: out.debug << "Convert double to uint16_t"; break;
+ case EOpConvDoubleToUint: out.debug << "Convert double to uint"; break;
+ case EOpConvDoubleToUint64: out.debug << "Convert double to uint64"; break;
+
+ case EOpConvUint64ToPtr: out.debug << "Convert uint64_t to pointer"; break;
+ case EOpConvPtrToUint64: out.debug << "Convert pointer to uint64_t"; break;
+
+ case EOpRadians: out.debug << "radians"; break;
+ case EOpDegrees: out.debug << "degrees"; break;
+ case EOpSin: out.debug << "sine"; break;
+ case EOpCos: out.debug << "cosine"; break;
+ case EOpTan: out.debug << "tangent"; break;
+ case EOpAsin: out.debug << "arc sine"; break;
+ case EOpAcos: out.debug << "arc cosine"; break;
+ case EOpAtan: out.debug << "arc tangent"; break;
+ case EOpSinh: out.debug << "hyp. sine"; break;
+ case EOpCosh: out.debug << "hyp. cosine"; break;
+ case EOpTanh: out.debug << "hyp. tangent"; break;
+ case EOpAsinh: out.debug << "arc hyp. sine"; break;
+ case EOpAcosh: out.debug << "arc hyp. cosine"; break;
+ case EOpAtanh: out.debug << "arc hyp. tangent"; break;
+
+ case EOpExp: out.debug << "exp"; break;
+ case EOpLog: out.debug << "log"; break;
+ case EOpExp2: out.debug << "exp2"; break;
+ case EOpLog2: out.debug << "log2"; break;
+ case EOpSqrt: out.debug << "sqrt"; break;
+ case EOpInverseSqrt: out.debug << "inverse sqrt"; break;
+
+ case EOpAbs: out.debug << "Absolute value"; break;
+ case EOpSign: out.debug << "Sign"; break;
+ case EOpFloor: out.debug << "Floor"; break;
+ case EOpTrunc: out.debug << "trunc"; break;
+ case EOpRound: out.debug << "round"; break;
+ case EOpRoundEven: out.debug << "roundEven"; break;
+ case EOpCeil: out.debug << "Ceiling"; break;
+ case EOpFract: out.debug << "Fraction"; break;
+
+ case EOpIsNan: out.debug << "isnan"; break;
+ case EOpIsInf: out.debug << "isinf"; break;
+
+ case EOpFloatBitsToInt: out.debug << "floatBitsToInt"; break;
+ case EOpFloatBitsToUint:out.debug << "floatBitsToUint"; break;
+ case EOpIntBitsToFloat: out.debug << "intBitsToFloat"; break;
+ case EOpUintBitsToFloat:out.debug << "uintBitsToFloat"; break;
+ case EOpDoubleBitsToInt64: out.debug << "doubleBitsToInt64"; break;
+ case EOpDoubleBitsToUint64: out.debug << "doubleBitsToUint64"; break;
+ case EOpInt64BitsToDouble: out.debug << "int64BitsToDouble"; break;
+ case EOpUint64BitsToDouble: out.debug << "uint64BitsToDouble"; break;
+ case EOpFloat16BitsToInt16: out.debug << "float16BitsToInt16"; break;
+ case EOpFloat16BitsToUint16: out.debug << "float16BitsToUint16"; break;
+ case EOpInt16BitsToFloat16: out.debug << "int16BitsToFloat16"; break;
+ case EOpUint16BitsToFloat16: out.debug << "uint16BitsToFloat16"; break;
+
+ case EOpPackSnorm2x16: out.debug << "packSnorm2x16"; break;
+ case EOpUnpackSnorm2x16:out.debug << "unpackSnorm2x16"; break;
+ case EOpPackUnorm2x16: out.debug << "packUnorm2x16"; break;
+ case EOpUnpackUnorm2x16:out.debug << "unpackUnorm2x16"; break;
+ case EOpPackHalf2x16: out.debug << "packHalf2x16"; break;
+ case EOpUnpackHalf2x16: out.debug << "unpackHalf2x16"; break;
+ case EOpPack16: out.debug << "pack16"; break;
+ case EOpPack32: out.debug << "pack32"; break;
+ case EOpPack64: out.debug << "pack64"; break;
+ case EOpUnpack32: out.debug << "unpack32"; break;
+ case EOpUnpack16: out.debug << "unpack16"; break;
+ case EOpUnpack8: out.debug << "unpack8"; break;
+
+ case EOpPackSnorm4x8: out.debug << "PackSnorm4x8"; break;
+ case EOpUnpackSnorm4x8: out.debug << "UnpackSnorm4x8"; break;
+ case EOpPackUnorm4x8: out.debug << "PackUnorm4x8"; break;
+ case EOpUnpackUnorm4x8: out.debug << "UnpackUnorm4x8"; break;
+ case EOpPackDouble2x32: out.debug << "PackDouble2x32"; break;
+ case EOpUnpackDouble2x32: out.debug << "UnpackDouble2x32"; break;
+
+ case EOpPackInt2x32: out.debug << "packInt2x32"; break;
+ case EOpUnpackInt2x32: out.debug << "unpackInt2x32"; break;
+ case EOpPackUint2x32: out.debug << "packUint2x32"; break;
+ case EOpUnpackUint2x32: out.debug << "unpackUint2x32"; break;
+
+ case EOpPackInt2x16: out.debug << "packInt2x16"; break;
+ case EOpUnpackInt2x16: out.debug << "unpackInt2x16"; break;
+ case EOpPackUint2x16: out.debug << "packUint2x16"; break;
+ case EOpUnpackUint2x16: out.debug << "unpackUint2x16"; break;
+
+ case EOpPackInt4x16: out.debug << "packInt4x16"; break;
+ case EOpUnpackInt4x16: out.debug << "unpackInt4x16"; break;
+ case EOpPackUint4x16: out.debug << "packUint4x16"; break;
+ case EOpUnpackUint4x16: out.debug << "unpackUint4x16"; break;
+ case EOpPackFloat2x16: out.debug << "packFloat2x16"; break;
+ case EOpUnpackFloat2x16: out.debug << "unpackFloat2x16"; break;
+
+ case EOpLength: out.debug << "length"; break;
+ case EOpNormalize: out.debug << "normalize"; break;
+ case EOpDPdx: out.debug << "dPdx"; break;
+ case EOpDPdy: out.debug << "dPdy"; break;
+ case EOpFwidth: out.debug << "fwidth"; break;
+ case EOpDPdxFine: out.debug << "dPdxFine"; break;
+ case EOpDPdyFine: out.debug << "dPdyFine"; break;
+ case EOpFwidthFine: out.debug << "fwidthFine"; break;
+ case EOpDPdxCoarse: out.debug << "dPdxCoarse"; break;
+ case EOpDPdyCoarse: out.debug << "dPdyCoarse"; break;
+ case EOpFwidthCoarse: out.debug << "fwidthCoarse"; break;
+
+ case EOpInterpolateAtCentroid: out.debug << "interpolateAtCentroid"; break;
+
+ case EOpDeterminant: out.debug << "determinant"; break;
+ case EOpMatrixInverse: out.debug << "inverse"; break;
+ case EOpTranspose: out.debug << "transpose"; break;
+
+ case EOpAny: out.debug << "any"; break;
+ case EOpAll: out.debug << "all"; break;
+
+ case EOpArrayLength: out.debug << "array length"; break;
+
+ case EOpEmitStreamVertex: out.debug << "EmitStreamVertex"; break;
+ case EOpEndStreamPrimitive: out.debug << "EndStreamPrimitive"; break;
+
+ case EOpAtomicCounterIncrement: out.debug << "AtomicCounterIncrement";break;
+ case EOpAtomicCounterDecrement: out.debug << "AtomicCounterDecrement";break;
+ case EOpAtomicCounter: out.debug << "AtomicCounter"; break;
+
+ case EOpTextureQuerySize: out.debug << "textureSize"; break;
+ case EOpTextureQueryLod: out.debug << "textureQueryLod"; break;
+ case EOpTextureQueryLevels: out.debug << "textureQueryLevels"; break;
+ case EOpTextureQuerySamples: out.debug << "textureSamples"; break;
+ case EOpImageQuerySize: out.debug << "imageQuerySize"; break;
+ case EOpImageQuerySamples: out.debug << "imageQuerySamples"; break;
+ case EOpImageLoad: out.debug << "imageLoad"; break;
+
+ case EOpBitFieldReverse: out.debug << "bitFieldReverse"; break;
+ case EOpBitCount: out.debug << "bitCount"; break;
+ case EOpFindLSB: out.debug << "findLSB"; break;
+ case EOpFindMSB: out.debug << "findMSB"; break;
+
+ case EOpCountLeadingZeros: out.debug << "countLeadingZeros"; break;
+ case EOpCountTrailingZeros: out.debug << "countTrailingZeros"; break;
+
+ case EOpNoise: out.debug << "noise"; break;
+
+ case EOpBallot: out.debug << "ballot"; break;
+ case EOpReadFirstInvocation: out.debug << "readFirstInvocation"; break;
+
+ case EOpAnyInvocation: out.debug << "anyInvocation"; break;
+ case EOpAllInvocations: out.debug << "allInvocations"; break;
+ case EOpAllInvocationsEqual: out.debug << "allInvocationsEqual"; break;
+
+ case EOpSubgroupElect: out.debug << "subgroupElect"; break;
+ case EOpSubgroupAll: out.debug << "subgroupAll"; break;
+ case EOpSubgroupAny: out.debug << "subgroupAny"; break;
+ case EOpSubgroupAllEqual: out.debug << "subgroupAllEqual"; break;
+ case EOpSubgroupBroadcast: out.debug << "subgroupBroadcast"; break;
+ case EOpSubgroupBroadcastFirst: out.debug << "subgroupBroadcastFirst"; break;
+ case EOpSubgroupBallot: out.debug << "subgroupBallot"; break;
+ case EOpSubgroupInverseBallot: out.debug << "subgroupInverseBallot"; break;
+ case EOpSubgroupBallotBitExtract: out.debug << "subgroupBallotBitExtract"; break;
+ case EOpSubgroupBallotBitCount: out.debug << "subgroupBallotBitCount"; break;
+ case EOpSubgroupBallotInclusiveBitCount: out.debug << "subgroupBallotInclusiveBitCount"; break;
+ case EOpSubgroupBallotExclusiveBitCount: out.debug << "subgroupBallotExclusiveBitCount"; break;
+ case EOpSubgroupBallotFindLSB: out.debug << "subgroupBallotFindLSB"; break;
+ case EOpSubgroupBallotFindMSB: out.debug << "subgroupBallotFindMSB"; break;
+ case EOpSubgroupShuffle: out.debug << "subgroupShuffle"; break;
+ case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break;
+ case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break;
+ case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break;
+ case EOpSubgroupAdd: out.debug << "subgroupAdd"; break;
+ case EOpSubgroupMul: out.debug << "subgroupMul"; break;
+ case EOpSubgroupMin: out.debug << "subgroupMin"; break;
+ case EOpSubgroupMax: out.debug << "subgroupMax"; break;
+ case EOpSubgroupAnd: out.debug << "subgroupAnd"; break;
+ case EOpSubgroupOr: out.debug << "subgroupOr"; break;
+ case EOpSubgroupXor: out.debug << "subgroupXor"; break;
+ case EOpSubgroupInclusiveAdd: out.debug << "subgroupInclusiveAdd"; break;
+ case EOpSubgroupInclusiveMul: out.debug << "subgroupInclusiveMul"; break;
+ case EOpSubgroupInclusiveMin: out.debug << "subgroupInclusiveMin"; break;
+ case EOpSubgroupInclusiveMax: out.debug << "subgroupInclusiveMax"; break;
+ case EOpSubgroupInclusiveAnd: out.debug << "subgroupInclusiveAnd"; break;
+ case EOpSubgroupInclusiveOr: out.debug << "subgroupInclusiveOr"; break;
+ case EOpSubgroupInclusiveXor: out.debug << "subgroupInclusiveXor"; break;
+ case EOpSubgroupExclusiveAdd: out.debug << "subgroupExclusiveAdd"; break;
+ case EOpSubgroupExclusiveMul: out.debug << "subgroupExclusiveMul"; break;
+ case EOpSubgroupExclusiveMin: out.debug << "subgroupExclusiveMin"; break;
+ case EOpSubgroupExclusiveMax: out.debug << "subgroupExclusiveMax"; break;
+ case EOpSubgroupExclusiveAnd: out.debug << "subgroupExclusiveAnd"; break;
+ case EOpSubgroupExclusiveOr: out.debug << "subgroupExclusiveOr"; break;
+ case EOpSubgroupExclusiveXor: out.debug << "subgroupExclusiveXor"; break;
+ case EOpSubgroupClusteredAdd: out.debug << "subgroupClusteredAdd"; break;
+ case EOpSubgroupClusteredMul: out.debug << "subgroupClusteredMul"; break;
+ case EOpSubgroupClusteredMin: out.debug << "subgroupClusteredMin"; break;
+ case EOpSubgroupClusteredMax: out.debug << "subgroupClusteredMax"; break;
+ case EOpSubgroupClusteredAnd: out.debug << "subgroupClusteredAnd"; break;
+ case EOpSubgroupClusteredOr: out.debug << "subgroupClusteredOr"; break;
+ case EOpSubgroupClusteredXor: out.debug << "subgroupClusteredXor"; break;
+ case EOpSubgroupQuadBroadcast: out.debug << "subgroupQuadBroadcast"; break;
+ case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break;
+ case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break;
+ case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break;
+
+ case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break;
+ case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break;
+ case EOpSubgroupPartitionedMul: out.debug << "subgroupPartitionedMulNV"; break;
+ case EOpSubgroupPartitionedMin: out.debug << "subgroupPartitionedMinNV"; break;
+ case EOpSubgroupPartitionedMax: out.debug << "subgroupPartitionedMaxNV"; break;
+ case EOpSubgroupPartitionedAnd: out.debug << "subgroupPartitionedAndNV"; break;
+ case EOpSubgroupPartitionedOr: out.debug << "subgroupPartitionedOrNV"; break;
+ case EOpSubgroupPartitionedXor: out.debug << "subgroupPartitionedXorNV"; break;
+ case EOpSubgroupPartitionedInclusiveAdd: out.debug << "subgroupPartitionedInclusiveAddNV"; break;
+ case EOpSubgroupPartitionedInclusiveMul: out.debug << "subgroupPartitionedInclusiveMulNV"; break;
+ case EOpSubgroupPartitionedInclusiveMin: out.debug << "subgroupPartitionedInclusiveMinNV"; break;
+ case EOpSubgroupPartitionedInclusiveMax: out.debug << "subgroupPartitionedInclusiveMaxNV"; break;
+ case EOpSubgroupPartitionedInclusiveAnd: out.debug << "subgroupPartitionedInclusiveAndNV"; break;
+ case EOpSubgroupPartitionedInclusiveOr: out.debug << "subgroupPartitionedInclusiveOrNV"; break;
+ case EOpSubgroupPartitionedInclusiveXor: out.debug << "subgroupPartitionedInclusiveXorNV"; break;
+ case EOpSubgroupPartitionedExclusiveAdd: out.debug << "subgroupPartitionedExclusiveAddNV"; break;
+ case EOpSubgroupPartitionedExclusiveMul: out.debug << "subgroupPartitionedExclusiveMulNV"; break;
+ case EOpSubgroupPartitionedExclusiveMin: out.debug << "subgroupPartitionedExclusiveMinNV"; break;
+ case EOpSubgroupPartitionedExclusiveMax: out.debug << "subgroupPartitionedExclusiveMaxNV"; break;
+ case EOpSubgroupPartitionedExclusiveAnd: out.debug << "subgroupPartitionedExclusiveAndNV"; break;
+ case EOpSubgroupPartitionedExclusiveOr: out.debug << "subgroupPartitionedExclusiveOrNV"; break;
+ case EOpSubgroupPartitionedExclusiveXor: out.debug << "subgroupPartitionedExclusiveXorNV"; break;
+
+ case EOpClip: out.debug << "clip"; break;
+ case EOpIsFinite: out.debug << "isfinite"; break;
+ case EOpLog10: out.debug << "log10"; break;
+ case EOpRcp: out.debug << "rcp"; break;
+ case EOpSaturate: out.debug << "saturate"; break;
+
+ case EOpSparseTexelsResident: out.debug << "sparseTexelsResident"; break;
+
+ case EOpMinInvocations: out.debug << "minInvocations"; break;
+ case EOpMaxInvocations: out.debug << "maxInvocations"; break;
+ case EOpAddInvocations: out.debug << "addInvocations"; break;
+ case EOpMinInvocationsNonUniform: out.debug << "minInvocationsNonUniform"; break;
+ case EOpMaxInvocationsNonUniform: out.debug << "maxInvocationsNonUniform"; break;
+ case EOpAddInvocationsNonUniform: out.debug << "addInvocationsNonUniform"; break;
+
+ case EOpMinInvocationsInclusiveScan: out.debug << "minInvocationsInclusiveScan"; break;
+ case EOpMaxInvocationsInclusiveScan: out.debug << "maxInvocationsInclusiveScan"; break;
+ case EOpAddInvocationsInclusiveScan: out.debug << "addInvocationsInclusiveScan"; break;
+ case EOpMinInvocationsInclusiveScanNonUniform: out.debug << "minInvocationsInclusiveScanNonUniform"; break;
+ case EOpMaxInvocationsInclusiveScanNonUniform: out.debug << "maxInvocationsInclusiveScanNonUniform"; break;
+ case EOpAddInvocationsInclusiveScanNonUniform: out.debug << "addInvocationsInclusiveScanNonUniform"; break;
+
+ case EOpMinInvocationsExclusiveScan: out.debug << "minInvocationsExclusiveScan"; break;
+ case EOpMaxInvocationsExclusiveScan: out.debug << "maxInvocationsExclusiveScan"; break;
+ case EOpAddInvocationsExclusiveScan: out.debug << "addInvocationsExclusiveScan"; break;
+ case EOpMinInvocationsExclusiveScanNonUniform: out.debug << "minInvocationsExclusiveScanNonUniform"; break;
+ case EOpMaxInvocationsExclusiveScanNonUniform: out.debug << "maxInvocationsExclusiveScanNonUniform"; break;
+ case EOpAddInvocationsExclusiveScanNonUniform: out.debug << "addInvocationsExclusiveScanNonUniform"; break;
+
+ case EOpMbcnt: out.debug << "mbcnt"; break;
+
+ case EOpFragmentMaskFetch: out.debug << "fragmentMaskFetchAMD"; break;
+ case EOpFragmentFetch: out.debug << "fragmentFetchAMD"; break;
+
+ case EOpCubeFaceIndex: out.debug << "cubeFaceIndex"; break;
+ case EOpCubeFaceCoord: out.debug << "cubeFaceCoord"; break;
+
+ case EOpSubpassLoad: out.debug << "subpassLoad"; break;
+ case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
+
+ case EOpConstructReference: out.debug << "Construct reference type"; break;
+
+ default: out.debug.message(EPrefixError, "Bad unary op");
+ }
+
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
+{
+ TInfoSink& out = infoSink;
+
+ if (node->getOp() == EOpNull) {
+ out.debug.message(EPrefixError, "node is still EOpNull!");
+ return true;
+ }
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpSequence: out.debug << "Sequence\n"; return true;
+ case EOpLinkerObjects: out.debug << "Linker Objects\n"; return true;
+ case EOpComma: out.debug << "Comma"; break;
+ case EOpFunction: out.debug << "Function Definition: " << node->getName(); break;
+ case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break;
+ case EOpParameters: out.debug << "Function Parameters: "; break;
+
+ case EOpConstructFloat: out.debug << "Construct float"; break;
+ case EOpConstructDouble:out.debug << "Construct double"; break;
+
+ case EOpConstructVec2: out.debug << "Construct vec2"; break;
+ case EOpConstructVec3: out.debug << "Construct vec3"; break;
+ case EOpConstructVec4: out.debug << "Construct vec4"; break;
+ case EOpConstructDVec2: out.debug << "Construct dvec2"; break;
+ case EOpConstructDVec3: out.debug << "Construct dvec3"; break;
+ case EOpConstructDVec4: out.debug << "Construct dvec4"; break;
+ case EOpConstructBool: out.debug << "Construct bool"; break;
+ case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
+ case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
+ case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
+ case EOpConstructInt8: out.debug << "Construct int8_t"; break;
+ case EOpConstructI8Vec2: out.debug << "Construct i8vec2"; break;
+ case EOpConstructI8Vec3: out.debug << "Construct i8vec3"; break;
+ case EOpConstructI8Vec4: out.debug << "Construct i8vec4"; break;
+ case EOpConstructInt: out.debug << "Construct int"; break;
+ case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
+ case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
+ case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
+ case EOpConstructUint8: out.debug << "Construct uint8_t"; break;
+ case EOpConstructU8Vec2: out.debug << "Construct u8vec2"; break;
+ case EOpConstructU8Vec3: out.debug << "Construct u8vec3"; break;
+ case EOpConstructU8Vec4: out.debug << "Construct u8vec4"; break;
+ case EOpConstructUint: out.debug << "Construct uint"; break;
+ case EOpConstructUVec2: out.debug << "Construct uvec2"; break;
+ case EOpConstructUVec3: out.debug << "Construct uvec3"; break;
+ case EOpConstructUVec4: out.debug << "Construct uvec4"; break;
+ case EOpConstructInt64: out.debug << "Construct int64"; break;
+ case EOpConstructI64Vec2: out.debug << "Construct i64vec2"; break;
+ case EOpConstructI64Vec3: out.debug << "Construct i64vec3"; break;
+ case EOpConstructI64Vec4: out.debug << "Construct i64vec4"; break;
+ case EOpConstructUint64: out.debug << "Construct uint64"; break;
+ case EOpConstructU64Vec2: out.debug << "Construct u64vec2"; break;
+ case EOpConstructU64Vec3: out.debug << "Construct u64vec3"; break;
+ case EOpConstructU64Vec4: out.debug << "Construct u64vec4"; break;
+ case EOpConstructInt16: out.debug << "Construct int16_t"; break;
+ case EOpConstructI16Vec2: out.debug << "Construct i16vec2"; break;
+ case EOpConstructI16Vec3: out.debug << "Construct i16vec3"; break;
+ case EOpConstructI16Vec4: out.debug << "Construct i16vec4"; break;
+ case EOpConstructUint16: out.debug << "Construct uint16_t"; break;
+ case EOpConstructU16Vec2: out.debug << "Construct u16vec2"; break;
+ case EOpConstructU16Vec3: out.debug << "Construct u16vec3"; break;
+ case EOpConstructU16Vec4: out.debug << "Construct u16vec4"; break;
+ case EOpConstructMat2x2: out.debug << "Construct mat2"; break;
+ case EOpConstructMat2x3: out.debug << "Construct mat2x3"; break;
+ case EOpConstructMat2x4: out.debug << "Construct mat2x4"; break;
+ case EOpConstructMat3x2: out.debug << "Construct mat3x2"; break;
+ case EOpConstructMat3x3: out.debug << "Construct mat3"; break;
+ case EOpConstructMat3x4: out.debug << "Construct mat3x4"; break;
+ case EOpConstructMat4x2: out.debug << "Construct mat4x2"; break;
+ case EOpConstructMat4x3: out.debug << "Construct mat4x3"; break;
+ case EOpConstructMat4x4: out.debug << "Construct mat4"; break;
+ case EOpConstructDMat2x2: out.debug << "Construct dmat2"; break;
+ case EOpConstructDMat2x3: out.debug << "Construct dmat2x3"; break;
+ case EOpConstructDMat2x4: out.debug << "Construct dmat2x4"; break;
+ case EOpConstructDMat3x2: out.debug << "Construct dmat3x2"; break;
+ case EOpConstructDMat3x3: out.debug << "Construct dmat3"; break;
+ case EOpConstructDMat3x4: out.debug << "Construct dmat3x4"; break;
+ case EOpConstructDMat4x2: out.debug << "Construct dmat4x2"; break;
+ case EOpConstructDMat4x3: out.debug << "Construct dmat4x3"; break;
+ case EOpConstructDMat4x4: out.debug << "Construct dmat4"; break;
+ case EOpConstructIMat2x2: out.debug << "Construct imat2"; break;
+ case EOpConstructIMat2x3: out.debug << "Construct imat2x3"; break;
+ case EOpConstructIMat2x4: out.debug << "Construct imat2x4"; break;
+ case EOpConstructIMat3x2: out.debug << "Construct imat3x2"; break;
+ case EOpConstructIMat3x3: out.debug << "Construct imat3"; break;
+ case EOpConstructIMat3x4: out.debug << "Construct imat3x4"; break;
+ case EOpConstructIMat4x2: out.debug << "Construct imat4x2"; break;
+ case EOpConstructIMat4x3: out.debug << "Construct imat4x3"; break;
+ case EOpConstructIMat4x4: out.debug << "Construct imat4"; break;
+ case EOpConstructUMat2x2: out.debug << "Construct umat2"; break;
+ case EOpConstructUMat2x3: out.debug << "Construct umat2x3"; break;
+ case EOpConstructUMat2x4: out.debug << "Construct umat2x4"; break;
+ case EOpConstructUMat3x2: out.debug << "Construct umat3x2"; break;
+ case EOpConstructUMat3x3: out.debug << "Construct umat3"; break;
+ case EOpConstructUMat3x4: out.debug << "Construct umat3x4"; break;
+ case EOpConstructUMat4x2: out.debug << "Construct umat4x2"; break;
+ case EOpConstructUMat4x3: out.debug << "Construct umat4x3"; break;
+ case EOpConstructUMat4x4: out.debug << "Construct umat4"; break;
+ case EOpConstructBMat2x2: out.debug << "Construct bmat2"; break;
+ case EOpConstructBMat2x3: out.debug << "Construct bmat2x3"; break;
+ case EOpConstructBMat2x4: out.debug << "Construct bmat2x4"; break;
+ case EOpConstructBMat3x2: out.debug << "Construct bmat3x2"; break;
+ case EOpConstructBMat3x3: out.debug << "Construct bmat3"; break;
+ case EOpConstructBMat3x4: out.debug << "Construct bmat3x4"; break;
+ case EOpConstructBMat4x2: out.debug << "Construct bmat4x2"; break;
+ case EOpConstructBMat4x3: out.debug << "Construct bmat4x3"; break;
+ case EOpConstructBMat4x4: out.debug << "Construct bmat4"; break;
+ case EOpConstructFloat16: out.debug << "Construct float16_t"; break;
+ case EOpConstructF16Vec2: out.debug << "Construct f16vec2"; break;
+ case EOpConstructF16Vec3: out.debug << "Construct f16vec3"; break;
+ case EOpConstructF16Vec4: out.debug << "Construct f16vec4"; break;
+ case EOpConstructF16Mat2x2: out.debug << "Construct f16mat2"; break;
+ case EOpConstructF16Mat2x3: out.debug << "Construct f16mat2x3"; break;
+ case EOpConstructF16Mat2x4: out.debug << "Construct f16mat2x4"; break;
+ case EOpConstructF16Mat3x2: out.debug << "Construct f16mat3x2"; break;
+ case EOpConstructF16Mat3x3: out.debug << "Construct f16mat3"; break;
+ case EOpConstructF16Mat3x4: out.debug << "Construct f16mat3x4"; break;
+ case EOpConstructF16Mat4x2: out.debug << "Construct f16mat4x2"; break;
+ case EOpConstructF16Mat4x3: out.debug << "Construct f16mat4x3"; break;
+ case EOpConstructF16Mat4x4: out.debug << "Construct f16mat4"; break;
+ case EOpConstructStruct: out.debug << "Construct structure"; break;
+ case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
+ case EOpConstructReference: out.debug << "Construct reference"; break;
+ case EOpConstructCooperativeMatrix: out.debug << "Construct cooperative matrix"; break;
+
+ case EOpLessThan: out.debug << "Compare Less Than"; break;
+ case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
+ case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
+ case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+ case EOpVectorEqual: out.debug << "Equal"; break;
+ case EOpVectorNotEqual: out.debug << "NotEqual"; break;
+
+ case EOpMod: out.debug << "mod"; break;
+ case EOpModf: out.debug << "modf"; break;
+ case EOpPow: out.debug << "pow"; break;
+
+ case EOpAtan: out.debug << "arc tangent"; break;
+
+ case EOpMin: out.debug << "min"; break;
+ case EOpMax: out.debug << "max"; break;
+ case EOpClamp: out.debug << "clamp"; break;
+ case EOpMix: out.debug << "mix"; break;
+ case EOpStep: out.debug << "step"; break;
+ case EOpSmoothStep: out.debug << "smoothstep"; break;
+
+ case EOpDistance: out.debug << "distance"; break;
+ case EOpDot: out.debug << "dot-product"; break;
+ case EOpCross: out.debug << "cross-product"; break;
+ case EOpFaceForward: out.debug << "face-forward"; break;
+ case EOpReflect: out.debug << "reflect"; break;
+ case EOpRefract: out.debug << "refract"; break;
+ case EOpMul: out.debug << "component-wise multiply"; break;
+ case EOpOuterProduct: out.debug << "outer product"; break;
+
+ case EOpEmitVertex: out.debug << "EmitVertex"; break;
+ case EOpEndPrimitive: out.debug << "EndPrimitive"; break;
+
+ case EOpBarrier: out.debug << "Barrier"; break;
+ case EOpMemoryBarrier: out.debug << "MemoryBarrier"; break;
+ case EOpMemoryBarrierAtomicCounter: out.debug << "MemoryBarrierAtomicCounter"; break;
+ case EOpMemoryBarrierBuffer: out.debug << "MemoryBarrierBuffer"; break;
+ case EOpMemoryBarrierImage: out.debug << "MemoryBarrierImage"; break;
+ case EOpMemoryBarrierShared: out.debug << "MemoryBarrierShared"; break;
+ case EOpGroupMemoryBarrier: out.debug << "GroupMemoryBarrier"; break;
+
+ case EOpReadInvocation: out.debug << "readInvocation"; break;
+
+ case EOpSwizzleInvocations: out.debug << "swizzleInvocations"; break;
+ case EOpSwizzleInvocationsMasked: out.debug << "swizzleInvocationsMasked"; break;
+ case EOpWriteInvocation: out.debug << "writeInvocation"; break;
+
+ case EOpMin3: out.debug << "min3"; break;
+ case EOpMax3: out.debug << "max3"; break;
+ case EOpMid3: out.debug << "mid3"; break;
+ case EOpTime: out.debug << "time"; break;
+
+ case EOpAtomicAdd: out.debug << "AtomicAdd"; break;
+ case EOpAtomicMin: out.debug << "AtomicMin"; break;
+ case EOpAtomicMax: out.debug << "AtomicMax"; break;
+ case EOpAtomicAnd: out.debug << "AtomicAnd"; break;
+ case EOpAtomicOr: out.debug << "AtomicOr"; break;
+ case EOpAtomicXor: out.debug << "AtomicXor"; break;
+ case EOpAtomicExchange: out.debug << "AtomicExchange"; break;
+ case EOpAtomicCompSwap: out.debug << "AtomicCompSwap"; break;
+ case EOpAtomicLoad: out.debug << "AtomicLoad"; break;
+ case EOpAtomicStore: out.debug << "AtomicStore"; break;
+
+ case EOpAtomicCounterAdd: out.debug << "AtomicCounterAdd"; break;
+ case EOpAtomicCounterSubtract: out.debug << "AtomicCounterSubtract"; break;
+ case EOpAtomicCounterMin: out.debug << "AtomicCounterMin"; break;
+ case EOpAtomicCounterMax: out.debug << "AtomicCounterMax"; break;
+ case EOpAtomicCounterAnd: out.debug << "AtomicCounterAnd"; break;
+ case EOpAtomicCounterOr: out.debug << "AtomicCounterOr"; break;
+ case EOpAtomicCounterXor: out.debug << "AtomicCounterXor"; break;
+ case EOpAtomicCounterExchange: out.debug << "AtomicCounterExchange"; break;
+ case EOpAtomicCounterCompSwap: out.debug << "AtomicCounterCompSwap"; break;
+
+ case EOpImageQuerySize: out.debug << "imageQuerySize"; break;
+ case EOpImageQuerySamples: out.debug << "imageQuerySamples"; break;
+ case EOpImageLoad: out.debug << "imageLoad"; break;
+ case EOpImageStore: out.debug << "imageStore"; break;
+ case EOpImageAtomicAdd: out.debug << "imageAtomicAdd"; break;
+ case EOpImageAtomicMin: out.debug << "imageAtomicMin"; break;
+ case EOpImageAtomicMax: out.debug << "imageAtomicMax"; break;
+ case EOpImageAtomicAnd: out.debug << "imageAtomicAnd"; break;
+ case EOpImageAtomicOr: out.debug << "imageAtomicOr"; break;
+ case EOpImageAtomicXor: out.debug << "imageAtomicXor"; break;
+ case EOpImageAtomicExchange: out.debug << "imageAtomicExchange"; break;
+ case EOpImageAtomicCompSwap: out.debug << "imageAtomicCompSwap"; break;
+ case EOpImageAtomicLoad: out.debug << "imageAtomicLoad"; break;
+ case EOpImageAtomicStore: out.debug << "imageAtomicStore"; break;
+ case EOpImageLoadLod: out.debug << "imageLoadLod"; break;
+ case EOpImageStoreLod: out.debug << "imageStoreLod"; break;
+
+ case EOpTextureQuerySize: out.debug << "textureSize"; break;
+ case EOpTextureQueryLod: out.debug << "textureQueryLod"; break;
+ case EOpTextureQueryLevels: out.debug << "textureQueryLevels"; break;
+ case EOpTextureQuerySamples: out.debug << "textureSamples"; break;
+ case EOpTexture: out.debug << "texture"; break;
+ case EOpTextureProj: out.debug << "textureProj"; break;
+ case EOpTextureLod: out.debug << "textureLod"; break;
+ case EOpTextureOffset: out.debug << "textureOffset"; break;
+ case EOpTextureFetch: out.debug << "textureFetch"; break;
+ case EOpTextureFetchOffset: out.debug << "textureFetchOffset"; break;
+ case EOpTextureProjOffset: out.debug << "textureProjOffset"; break;
+ case EOpTextureLodOffset: out.debug << "textureLodOffset"; break;
+ case EOpTextureProjLod: out.debug << "textureProjLod"; break;
+ case EOpTextureProjLodOffset: out.debug << "textureProjLodOffset"; break;
+ case EOpTextureGrad: out.debug << "textureGrad"; break;
+ case EOpTextureGradOffset: out.debug << "textureGradOffset"; break;
+ case EOpTextureProjGrad: out.debug << "textureProjGrad"; break;
+ case EOpTextureProjGradOffset: out.debug << "textureProjGradOffset"; break;
+ case EOpTextureGather: out.debug << "textureGather"; break;
+ case EOpTextureGatherOffset: out.debug << "textureGatherOffset"; break;
+ case EOpTextureGatherOffsets: out.debug << "textureGatherOffsets"; break;
+ case EOpTextureClamp: out.debug << "textureClamp"; break;
+ case EOpTextureOffsetClamp: out.debug << "textureOffsetClamp"; break;
+ case EOpTextureGradClamp: out.debug << "textureGradClamp"; break;
+ case EOpTextureGradOffsetClamp: out.debug << "textureGradOffsetClamp"; break;
+ case EOpTextureGatherLod: out.debug << "textureGatherLod"; break;
+ case EOpTextureGatherLodOffset: out.debug << "textureGatherLodOffset"; break;
+ case EOpTextureGatherLodOffsets: out.debug << "textureGatherLodOffsets"; break;
+
+ case EOpSparseTexture: out.debug << "sparseTexture"; break;
+ case EOpSparseTextureOffset: out.debug << "sparseTextureOffset"; break;
+ case EOpSparseTextureLod: out.debug << "sparseTextureLod"; break;
+ case EOpSparseTextureLodOffset: out.debug << "sparseTextureLodOffset"; break;
+ case EOpSparseTextureFetch: out.debug << "sparseTexelFetch"; break;
+ case EOpSparseTextureFetchOffset: out.debug << "sparseTexelFetchOffset"; break;
+ case EOpSparseTextureGrad: out.debug << "sparseTextureGrad"; break;
+ case EOpSparseTextureGradOffset: out.debug << "sparseTextureGradOffset"; break;
+ case EOpSparseTextureGather: out.debug << "sparseTextureGather"; break;
+ case EOpSparseTextureGatherOffset: out.debug << "sparseTextureGatherOffset"; break;
+ case EOpSparseTextureGatherOffsets: out.debug << "sparseTextureGatherOffsets"; break;
+ case EOpSparseImageLoad: out.debug << "sparseImageLoad"; break;
+ case EOpSparseTextureClamp: out.debug << "sparseTextureClamp"; break;
+ case EOpSparseTextureOffsetClamp: out.debug << "sparseTextureOffsetClamp"; break;
+ case EOpSparseTextureGradClamp: out.debug << "sparseTextureGradClamp"; break;
+ case EOpSparseTextureGradOffsetClamp: out.debug << "sparseTextureGradOffsetClam"; break;
+ case EOpSparseTextureGatherLod: out.debug << "sparseTextureGatherLod"; break;
+ case EOpSparseTextureGatherLodOffset: out.debug << "sparseTextureGatherLodOffset"; break;
+ case EOpSparseTextureGatherLodOffsets: out.debug << "sparseTextureGatherLodOffsets"; break;
+ case EOpSparseImageLoadLod: out.debug << "sparseImageLoadLod"; break;
+ case EOpImageSampleFootprintNV: out.debug << "imageSampleFootprintNV"; break;
+ case EOpImageSampleFootprintClampNV: out.debug << "imageSampleFootprintClampNV"; break;
+ case EOpImageSampleFootprintLodNV: out.debug << "imageSampleFootprintLodNV"; break;
+ case EOpImageSampleFootprintGradNV: out.debug << "imageSampleFootprintGradNV"; break;
+ case EOpImageSampleFootprintGradClampNV: out.debug << "mageSampleFootprintGradClampNV"; break;
+ case EOpAddCarry: out.debug << "addCarry"; break;
+ case EOpSubBorrow: out.debug << "subBorrow"; break;
+ case EOpUMulExtended: out.debug << "uMulExtended"; break;
+ case EOpIMulExtended: out.debug << "iMulExtended"; break;
+ case EOpBitfieldExtract: out.debug << "bitfieldExtract"; break;
+ case EOpBitfieldInsert: out.debug << "bitfieldInsert"; break;
+
+ case EOpFma: out.debug << "fma"; break;
+ case EOpFrexp: out.debug << "frexp"; break;
+ case EOpLdexp: out.debug << "ldexp"; break;
+
+ case EOpInterpolateAtSample: out.debug << "interpolateAtSample"; break;
+ case EOpInterpolateAtOffset: out.debug << "interpolateAtOffset"; break;
+ case EOpInterpolateAtVertex: out.debug << "interpolateAtVertex"; break;
+
+ case EOpSinCos: out.debug << "sincos"; break;
+ case EOpGenMul: out.debug << "mul"; break;
+
+ case EOpAllMemoryBarrierWithGroupSync: out.debug << "AllMemoryBarrierWithGroupSync"; break;
+ case EOpDeviceMemoryBarrier: out.debug << "DeviceMemoryBarrier"; break;
+ case EOpDeviceMemoryBarrierWithGroupSync: out.debug << "DeviceMemoryBarrierWithGroupSync"; break;
+ case EOpWorkgroupMemoryBarrier: out.debug << "WorkgroupMemoryBarrier"; break;
+ case EOpWorkgroupMemoryBarrierWithGroupSync: out.debug << "WorkgroupMemoryBarrierWithGroupSync"; break;
+
+ case EOpSubgroupBarrier: out.debug << "subgroupBarrier"; break;
+ case EOpSubgroupMemoryBarrier: out.debug << "subgroupMemoryBarrier"; break;
+ case EOpSubgroupMemoryBarrierBuffer: out.debug << "subgroupMemoryBarrierBuffer"; break;
+ case EOpSubgroupMemoryBarrierImage: out.debug << "subgroupMemoryBarrierImage"; break;
+ case EOpSubgroupMemoryBarrierShared: out.debug << "subgroupMemoryBarrierShared"; break;
+ case EOpSubgroupElect: out.debug << "subgroupElect"; break;
+ case EOpSubgroupAll: out.debug << "subgroupAll"; break;
+ case EOpSubgroupAny: out.debug << "subgroupAny"; break;
+ case EOpSubgroupAllEqual: out.debug << "subgroupAllEqual"; break;
+ case EOpSubgroupBroadcast: out.debug << "subgroupBroadcast"; break;
+ case EOpSubgroupBroadcastFirst: out.debug << "subgroupBroadcastFirst"; break;
+ case EOpSubgroupBallot: out.debug << "subgroupBallot"; break;
+ case EOpSubgroupInverseBallot: out.debug << "subgroupInverseBallot"; break;
+ case EOpSubgroupBallotBitExtract: out.debug << "subgroupBallotBitExtract"; break;
+ case EOpSubgroupBallotBitCount: out.debug << "subgroupBallotBitCount"; break;
+ case EOpSubgroupBallotInclusiveBitCount: out.debug << "subgroupBallotInclusiveBitCount"; break;
+ case EOpSubgroupBallotExclusiveBitCount: out.debug << "subgroupBallotExclusiveBitCount"; break;
+ case EOpSubgroupBallotFindLSB: out.debug << "subgroupBallotFindLSB"; break;
+ case EOpSubgroupBallotFindMSB: out.debug << "subgroupBallotFindMSB"; break;
+ case EOpSubgroupShuffle: out.debug << "subgroupShuffle"; break;
+ case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break;
+ case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break;
+ case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break;
+ case EOpSubgroupAdd: out.debug << "subgroupAdd"; break;
+ case EOpSubgroupMul: out.debug << "subgroupMul"; break;
+ case EOpSubgroupMin: out.debug << "subgroupMin"; break;
+ case EOpSubgroupMax: out.debug << "subgroupMax"; break;
+ case EOpSubgroupAnd: out.debug << "subgroupAnd"; break;
+ case EOpSubgroupOr: out.debug << "subgroupOr"; break;
+ case EOpSubgroupXor: out.debug << "subgroupXor"; break;
+ case EOpSubgroupInclusiveAdd: out.debug << "subgroupInclusiveAdd"; break;
+ case EOpSubgroupInclusiveMul: out.debug << "subgroupInclusiveMul"; break;
+ case EOpSubgroupInclusiveMin: out.debug << "subgroupInclusiveMin"; break;
+ case EOpSubgroupInclusiveMax: out.debug << "subgroupInclusiveMax"; break;
+ case EOpSubgroupInclusiveAnd: out.debug << "subgroupInclusiveAnd"; break;
+ case EOpSubgroupInclusiveOr: out.debug << "subgroupInclusiveOr"; break;
+ case EOpSubgroupInclusiveXor: out.debug << "subgroupInclusiveXor"; break;
+ case EOpSubgroupExclusiveAdd: out.debug << "subgroupExclusiveAdd"; break;
+ case EOpSubgroupExclusiveMul: out.debug << "subgroupExclusiveMul"; break;
+ case EOpSubgroupExclusiveMin: out.debug << "subgroupExclusiveMin"; break;
+ case EOpSubgroupExclusiveMax: out.debug << "subgroupExclusiveMax"; break;
+ case EOpSubgroupExclusiveAnd: out.debug << "subgroupExclusiveAnd"; break;
+ case EOpSubgroupExclusiveOr: out.debug << "subgroupExclusiveOr"; break;
+ case EOpSubgroupExclusiveXor: out.debug << "subgroupExclusiveXor"; break;
+ case EOpSubgroupClusteredAdd: out.debug << "subgroupClusteredAdd"; break;
+ case EOpSubgroupClusteredMul: out.debug << "subgroupClusteredMul"; break;
+ case EOpSubgroupClusteredMin: out.debug << "subgroupClusteredMin"; break;
+ case EOpSubgroupClusteredMax: out.debug << "subgroupClusteredMax"; break;
+ case EOpSubgroupClusteredAnd: out.debug << "subgroupClusteredAnd"; break;
+ case EOpSubgroupClusteredOr: out.debug << "subgroupClusteredOr"; break;
+ case EOpSubgroupClusteredXor: out.debug << "subgroupClusteredXor"; break;
+ case EOpSubgroupQuadBroadcast: out.debug << "subgroupQuadBroadcast"; break;
+ case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break;
+ case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break;
+ case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break;
+
+ case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break;
+ case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break;
+ case EOpSubgroupPartitionedMul: out.debug << "subgroupPartitionedMulNV"; break;
+ case EOpSubgroupPartitionedMin: out.debug << "subgroupPartitionedMinNV"; break;
+ case EOpSubgroupPartitionedMax: out.debug << "subgroupPartitionedMaxNV"; break;
+ case EOpSubgroupPartitionedAnd: out.debug << "subgroupPartitionedAndNV"; break;
+ case EOpSubgroupPartitionedOr: out.debug << "subgroupPartitionedOrNV"; break;
+ case EOpSubgroupPartitionedXor: out.debug << "subgroupPartitionedXorNV"; break;
+ case EOpSubgroupPartitionedInclusiveAdd: out.debug << "subgroupPartitionedInclusiveAddNV"; break;
+ case EOpSubgroupPartitionedInclusiveMul: out.debug << "subgroupPartitionedInclusiveMulNV"; break;
+ case EOpSubgroupPartitionedInclusiveMin: out.debug << "subgroupPartitionedInclusiveMinNV"; break;
+ case EOpSubgroupPartitionedInclusiveMax: out.debug << "subgroupPartitionedInclusiveMaxNV"; break;
+ case EOpSubgroupPartitionedInclusiveAnd: out.debug << "subgroupPartitionedInclusiveAndNV"; break;
+ case EOpSubgroupPartitionedInclusiveOr: out.debug << "subgroupPartitionedInclusiveOrNV"; break;
+ case EOpSubgroupPartitionedInclusiveXor: out.debug << "subgroupPartitionedInclusiveXorNV"; break;
+ case EOpSubgroupPartitionedExclusiveAdd: out.debug << "subgroupPartitionedExclusiveAddNV"; break;
+ case EOpSubgroupPartitionedExclusiveMul: out.debug << "subgroupPartitionedExclusiveMulNV"; break;
+ case EOpSubgroupPartitionedExclusiveMin: out.debug << "subgroupPartitionedExclusiveMinNV"; break;
+ case EOpSubgroupPartitionedExclusiveMax: out.debug << "subgroupPartitionedExclusiveMaxNV"; break;
+ case EOpSubgroupPartitionedExclusiveAnd: out.debug << "subgroupPartitionedExclusiveAndNV"; break;
+ case EOpSubgroupPartitionedExclusiveOr: out.debug << "subgroupPartitionedExclusiveOrNV"; break;
+ case EOpSubgroupPartitionedExclusiveXor: out.debug << "subgroupPartitionedExclusiveXorNV"; break;
+
+ case EOpSubpassLoad: out.debug << "subpassLoad"; break;
+ case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
+
+ case EOpTraceNV: out.debug << "traceNV"; break;
+ case EOpReportIntersectionNV: out.debug << "reportIntersectionNV"; break;
+ case EOpIgnoreIntersectionNV: out.debug << "ignoreIntersectionNV"; break;
+ case EOpTerminateRayNV: out.debug << "terminateRayNV"; break;
+ case EOpExecuteCallableNV: out.debug << "executeCallableNV"; break;
+ case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
+
+ case EOpCooperativeMatrixLoad: out.debug << "Load cooperative matrix"; break;
+ case EOpCooperativeMatrixStore: out.debug << "Store cooperative matrix"; break;
+ case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break;
+
+ case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break;
+
+ default: out.debug.message(EPrefixError, "Bad aggregation op");
+ }
+
+ if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ out.debug << "Test condition and select";
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ if (node->getShortCircuit() == false)
+ out.debug << ": no shortcircuit";
+ if (node->getFlatten())
+ out.debug << ": Flatten";
+ if (node->getDontFlatten())
+ out.debug << ": DontFlatten";
+ out.debug << "\n";
+
+ ++depth;
+
+ OutputTreeText(out, node, depth);
+ out.debug << "Condition\n";
+ node->getCondition()->traverse(this);
+
+ OutputTreeText(out, node, depth);
+ if (node->getTrueBlock()) {
+ out.debug << "true case\n";
+ node->getTrueBlock()->traverse(this);
+ } else
+ out.debug << "true case is null\n";
+
+ if (node->getFalseBlock()) {
+ OutputTreeText(out, node, depth);
+ out.debug << "false case\n";
+ node->getFalseBlock()->traverse(this);
+ }
+
+ --depth;
+
+ return false;
+}
+
+// Print infinities and NaNs, and numbers in a portable way.
+// Goals:
+// - portable (across IEEE 754 platforms)
+// - shows all possible IEEE values
+// - shows simple numbers in a simple way, e.g., no leading/trailing 0s
+// - shows all digits, no premature rounding
+static void OutputDouble(TInfoSink& out, double value, TOutputTraverser::EExtraOutput extra)
+{
+ if (IsInfinity(value)) {
+ if (value < 0)
+ out.debug << "-1.#INF";
+ else
+ out.debug << "+1.#INF";
+ } else if (IsNan(value))
+ out.debug << "1.#IND";
+ else {
+ const int maxSize = 340;
+ char buf[maxSize];
+ const char* format = "%f";
+ if (fabs(value) > 0.0 && (fabs(value) < 1e-5 || fabs(value) > 1e12))
+ format = "%-.13e";
+ int len = snprintf(buf, maxSize, format, value);
+ assert(len < maxSize);
+
+ // remove a leading zero in the 100s slot in exponent; it is not portable
+ // pattern: XX...XXXe+0XX or XX...XXXe-0XX
+ if (len > 5) {
+ if (buf[len-5] == 'e' && (buf[len-4] == '+' || buf[len-4] == '-') && buf[len-3] == '0') {
+ buf[len-3] = buf[len-2];
+ buf[len-2] = buf[len-1];
+ buf[len-1] = '\0';
+ }
+ }
+
+ out.debug << buf;
+
+ switch (extra) {
+ case TOutputTraverser::BinaryDoubleOutput:
+ {
+ uint64_t b;
+ static_assert(sizeof(b) == sizeof(value), "sizeof(uint64_t) != sizeof(double)");
+ memcpy(&b, &value, sizeof(b));
+
+ out.debug << " : ";
+ for (size_t i = 0; i < 8 * sizeof(value); ++i, ++b) {
+ out.debug << ((b & 0x8000000000000000) != 0 ? "1" : "0");
+ b <<= 1;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const TConstUnionArray& constUnion,
+ TOutputTraverser::EExtraOutput extra, int depth)
+{
+ int size = node->getType().computeNumComponents();
+
+ for (int i = 0; i < size; i++) {
+ OutputTreeText(out, node, depth);
+ switch (constUnion[i].getType()) {
+ case EbtBool:
+ if (constUnion[i].getBConst())
+ out.debug << "true";
+ else
+ out.debug << "false";
+
+ out.debug << " (" << "const bool" << ")";
+
+ out.debug << "\n";
+ break;
+ case EbtFloat:
+ case EbtDouble:
+ case EbtFloat16:
+ OutputDouble(out, constUnion[i].getDConst(), extra);
+ out.debug << "\n";
+ break;
+ case EbtInt8:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%d (%s)", constUnion[i].getI8Const(), "const int8_t");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtUint8:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%u (%s)", constUnion[i].getU8Const(), "const uint8_t");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtInt16:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%d (%s)", constUnion[i].getI16Const(), "const int16_t");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtUint16:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%u (%s)", constUnion[i].getU16Const(), "const uint16_t");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtInt:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtUint:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtInt64:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%lld (%s)", constUnion[i].getI64Const(), "const int64_t");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtUint64:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%llu (%s)", constUnion[i].getU64Const(), "const uint64_t");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ default:
+ out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
+ break;
+ }
+ }
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+ OutputTreeText(infoSink, node, depth);
+ infoSink.debug << "Constant:\n";
+
+ OutputConstantUnion(infoSink, node, node->getConstArray(), extraOutput, depth + 1);
+}
+
+void TOutputTraverser::visitSymbol(TIntermSymbol* node)
+{
+ OutputTreeText(infoSink, node, depth);
+
+ infoSink.debug << "'" << node->getName() << "' (" << node->getCompleteString() << ")\n";
+
+ if (! node->getConstArray().empty())
+ OutputConstantUnion(infoSink, node, node->getConstArray(), extraOutput, depth + 1);
+ else if (node->getConstSubtree()) {
+ incrementDepth(node);
+ node->getConstSubtree()->traverse(this);
+ decrementDepth();
+ }
+}
+
+bool TOutputTraverser::visitLoop(TVisit /* visit */, TIntermLoop* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ out.debug << "Loop with condition ";
+ if (! node->testFirst())
+ out.debug << "not ";
+ out.debug << "tested first";
+
+ if (node->getUnroll())
+ out.debug << ": Unroll";
+ if (node->getDontUnroll())
+ out.debug << ": DontUnroll";
+ if (node->getLoopDependency()) {
+ out.debug << ": Dependency ";
+ out.debug << node->getLoopDependency();
+ }
+ out.debug << "\n";
+
+ ++depth;
+
+ OutputTreeText(infoSink, node, depth);
+ if (node->getTest()) {
+ out.debug << "Loop Condition\n";
+ node->getTest()->traverse(this);
+ } else
+ out.debug << "No loop condition\n";
+
+ OutputTreeText(infoSink, node, depth);
+ if (node->getBody()) {
+ out.debug << "Loop Body\n";
+ node->getBody()->traverse(this);
+ } else
+ out.debug << "No loop body\n";
+
+ if (node->getTerminal()) {
+ OutputTreeText(infoSink, node, depth);
+ out.debug << "Loop Terminal Expression\n";
+ node->getTerminal()->traverse(this);
+ }
+
+ --depth;
+
+ return false;
+}
+
+bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getFlowOp()) {
+ case EOpKill: out.debug << "Branch: Kill"; break;
+ case EOpBreak: out.debug << "Branch: Break"; break;
+ case EOpContinue: out.debug << "Branch: Continue"; break;
+ case EOpReturn: out.debug << "Branch: Return"; break;
+ case EOpCase: out.debug << "case: "; break;
+ case EOpDemote: out.debug << "Demote"; break;
+ case EOpDefault: out.debug << "default: "; break;
+ default: out.debug << "Branch: Unknown Branch"; break;
+ }
+
+ if (node->getExpression()) {
+ out.debug << " with expression\n";
+ ++depth;
+ node->getExpression()->traverse(this);
+ --depth;
+ } else
+ out.debug << "\n";
+
+ return false;
+}
+
+bool TOutputTraverser::visitSwitch(TVisit /* visit */, TIntermSwitch* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+ out.debug << "switch";
+
+ if (node->getFlatten())
+ out.debug << ": Flatten";
+ if (node->getDontFlatten())
+ out.debug << ": DontFlatten";
+ out.debug << "\n";
+
+ OutputTreeText(out, node, depth);
+ out.debug << "condition\n";
+ ++depth;
+ node->getCondition()->traverse(this);
+
+ --depth;
+ OutputTreeText(out, node, depth);
+ out.debug << "body\n";
+ ++depth;
+ node->getBody()->traverse(this);
+
+ --depth;
+
+ return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node. It's children will still be processed.
+//
+void TIntermediate::output(TInfoSink& infoSink, bool tree)
+{
+ infoSink.debug << "Shader version: " << version << "\n";
+ if (requestedExtensions.size() > 0) {
+ for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt)
+ infoSink.debug << "Requested " << *extIt << "\n";
+ }
+
+ if (xfbMode)
+ infoSink.debug << "in xfb mode\n";
+
+ switch (language) {
+ case EShLangVertex:
+ break;
+
+ case EShLangTessControl:
+ infoSink.debug << "vertices = " << vertices << "\n";
+
+ if (inputPrimitive != ElgNone)
+ infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
+ if (vertexSpacing != EvsNone)
+ infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n";
+ if (vertexOrder != EvoNone)
+ infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n";
+ break;
+
+ case EShLangTessEvaluation:
+ infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
+ infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n";
+ infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n";
+ if (pointMode)
+ infoSink.debug << "using point mode\n";
+ break;
+
+ case EShLangGeometry:
+ infoSink.debug << "invocations = " << invocations << "\n";
+ infoSink.debug << "max_vertices = " << vertices << "\n";
+ infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
+ infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n";
+ break;
+
+ case EShLangFragment:
+ if (pixelCenterInteger)
+ infoSink.debug << "gl_FragCoord pixel center is integer\n";
+ if (originUpperLeft)
+ infoSink.debug << "gl_FragCoord origin is upper left\n";
+ if (earlyFragmentTests)
+ infoSink.debug << "using early_fragment_tests\n";
+ if (postDepthCoverage)
+ infoSink.debug << "using post_depth_coverage\n";
+ if (depthLayout != EldNone)
+ infoSink.debug << "using " << TQualifier::getLayoutDepthString(depthLayout) << "\n";
+ if (blendEquations != 0) {
+ infoSink.debug << "using";
+ // blendEquations is a mask, decode it
+ for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
+ if (blendEquations & (1 << be))
+ infoSink.debug << " " << TQualifier::getBlendEquationString(be);
+ }
+ infoSink.debug << "\n";
+ }
+ if (interlockOrdering != EioNone)
+ infoSink.debug << "interlock ordering = " << TQualifier::getInterlockOrderingString(interlockOrdering) << "\n";
+ break;
+
+ case EShLangMeshNV:
+ infoSink.debug << "max_vertices = " << vertices << "\n";
+ infoSink.debug << "max_primitives = " << primitives << "\n";
+ infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n";
+ // Fall through
+ case EShLangTaskNV:
+ // Fall through
+ case EShLangCompute:
+ infoSink.debug << "local_size = (" << localSize[0] << ", " << localSize[1] << ", " << localSize[2] << ")\n";
+ {
+ if (localSizeSpecId[0] != TQualifier::layoutNotSet ||
+ localSizeSpecId[1] != TQualifier::layoutNotSet ||
+ localSizeSpecId[2] != TQualifier::layoutNotSet) {
+ infoSink.debug << "local_size ids = (" <<
+ localSizeSpecId[0] << ", " <<
+ localSizeSpecId[1] << ", " <<
+ localSizeSpecId[2] << ")\n";
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (treeRoot == 0 || ! tree)
+ return;
+
+ TOutputTraverser it(infoSink);
+ if (getBinaryDoubleOutput())
+ it.setDoubleOutput(TOutputTraverser::BinaryDoubleOutput);
+ treeRoot->traverse(&it);
+}
+
+} // end namespace glslang
+
+#endif // not GLSLANG_WEB \ No newline at end of file
diff --git a/thirdparty/glslang/glslang/MachineIndependent/iomapper.cpp b/thirdparty/glslang/glslang/MachineIndependent/iomapper.cpp
new file mode 100644
index 0000000000..3262c0a203
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/iomapper.cpp
@@ -0,0 +1,1249 @@
+//
+// Copyright (C) 2016-2017 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef GLSLANG_WEB
+
+#include "../Include/Common.h"
+#include "../Include/InfoSink.h"
+
+#include "gl_types.h"
+#include "iomapper.h"
+
+//
+// Map IO bindings.
+//
+// High-level algorithm for one stage:
+//
+// 1. Traverse all code (live+dead) to find the explicitly provided bindings.
+//
+// 2. Traverse (just) the live code to determine which non-provided bindings
+// require auto-numbering. We do not auto-number dead ones.
+//
+// 3. Traverse all the code to apply the bindings:
+// a. explicitly given bindings are offset according to their type
+// b. implicit live bindings are auto-numbered into the holes, using
+// any open binding slot.
+// c. implicit dead bindings are left un-bound.
+//
+
+namespace glslang {
+
+class TVarGatherTraverser : public TLiveTraverser {
+public:
+ TVarGatherTraverser(const TIntermediate& i, bool traverseDeadCode, TVarLiveMap& inList, TVarLiveMap& outList, TVarLiveMap& uniformList)
+ : TLiveTraverser(i, traverseDeadCode, true, true, false)
+ , inputList(inList)
+ , outputList(outList)
+ , uniformList(uniformList)
+ {
+ }
+
+ virtual void visitSymbol(TIntermSymbol* base)
+ {
+ TVarLiveMap* target = nullptr;
+ if (base->getQualifier().storage == EvqVaryingIn)
+ target = &inputList;
+ else if (base->getQualifier().storage == EvqVaryingOut)
+ target = &outputList;
+ else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant())
+ target = &uniformList;
+ if (target) {
+ TVarEntryInfo ent = {base->getId(), base, ! traverseAll};
+ ent.stage = intermediate.getStage();
+ TVarLiveMap::iterator at = target->find(
+ ent.symbol->getName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
+ if (at != target->end() && at->second.id == ent.id)
+ at->second.live = at->second.live || ! traverseAll; // update live state
+ else
+ (*target)[ent.symbol->getName()] = ent;
+ }
+ }
+
+private:
+ TVarLiveMap& inputList;
+ TVarLiveMap& outputList;
+ TVarLiveMap& uniformList;
+};
+
+class TVarSetTraverser : public TLiveTraverser
+{
+public:
+ TVarSetTraverser(const TIntermediate& i, const TVarLiveMap& inList, const TVarLiveMap& outList, const TVarLiveMap& uniformList)
+ : TLiveTraverser(i, true, true, true, false)
+ , inputList(inList)
+ , outputList(outList)
+ , uniformList(uniformList)
+ {
+ }
+
+ virtual void visitSymbol(TIntermSymbol* base) {
+ const TVarLiveMap* source;
+ if (base->getQualifier().storage == EvqVaryingIn)
+ source = &inputList;
+ else if (base->getQualifier().storage == EvqVaryingOut)
+ source = &outputList;
+ else if (base->getQualifier().isUniformOrBuffer())
+ source = &uniformList;
+ else
+ return;
+
+ TVarEntryInfo ent = { base->getId() };
+ TVarLiveMap::const_iterator at = source->find(base->getName());
+ if (at == source->end())
+ return;
+
+ if (at->second.id != ent.id)
+ return;
+
+ if (at->second.newBinding != -1)
+ base->getWritableType().getQualifier().layoutBinding = at->second.newBinding;
+ if (at->second.newSet != -1)
+ base->getWritableType().getQualifier().layoutSet = at->second.newSet;
+ if (at->second.newLocation != -1)
+ base->getWritableType().getQualifier().layoutLocation = at->second.newLocation;
+ if (at->second.newComponent != -1)
+ base->getWritableType().getQualifier().layoutComponent = at->second.newComponent;
+ if (at->second.newIndex != -1)
+ base->getWritableType().getQualifier().layoutIndex = at->second.newIndex;
+ }
+
+ private:
+ const TVarLiveMap& inputList;
+ const TVarLiveMap& outputList;
+ const TVarLiveMap& uniformList;
+};
+
+struct TNotifyUniformAdaptor
+{
+ EShLanguage stage;
+ TIoMapResolver& resolver;
+ inline TNotifyUniformAdaptor(EShLanguage s, TIoMapResolver& r)
+ : stage(s)
+ , resolver(r)
+ {
+ }
+
+ inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
+ {
+ resolver.notifyBinding(stage, entKey.second);
+ }
+
+private:
+ TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&);
+};
+
+struct TNotifyInOutAdaptor
+{
+ EShLanguage stage;
+ TIoMapResolver& resolver;
+ inline TNotifyInOutAdaptor(EShLanguage s, TIoMapResolver& r)
+ : stage(s)
+ , resolver(r)
+ {
+ }
+
+ inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
+ {
+ resolver.notifyInOut(stage, entKey.second);
+ }
+
+private:
+ TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&);
+};
+
+struct TResolverUniformAdaptor {
+ TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e)
+ : stage(s)
+ , resolver(r)
+ , infoSink(i)
+ , error(e)
+ {
+ }
+
+ inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
+ TVarEntryInfo& ent = entKey.second;
+ ent.newLocation = -1;
+ ent.newComponent = -1;
+ ent.newBinding = -1;
+ ent.newSet = -1;
+ ent.newIndex = -1;
+ const bool isValid = resolver.validateBinding(stage, ent);
+ if (isValid) {
+ resolver.resolveBinding(stage, ent);
+ resolver.resolveSet(stage, ent);
+ resolver.resolveUniformLocation(stage, ent);
+
+ if (ent.newBinding != -1) {
+ if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
+ TString err = "mapped binding out of range: " + entKey.first;
+
+ infoSink.info.message(EPrefixInternalError, err.c_str());
+ error = true;
+ }
+ }
+ if (ent.newSet != -1) {
+ if (ent.newSet >= int(TQualifier::layoutSetEnd)) {
+ TString err = "mapped set out of range: " + entKey.first;
+
+ infoSink.info.message(EPrefixInternalError, err.c_str());
+ error = true;
+ }
+ }
+ } else {
+ TString errorMsg = "Invalid binding: " + entKey.first;
+ infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
+ error = true;
+ }
+ }
+
+ inline void setStage(EShLanguage s) { stage = s; }
+
+ EShLanguage stage;
+ TIoMapResolver& resolver;
+ TInfoSink& infoSink;
+ bool& error;
+
+private:
+ TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&);
+};
+
+struct TResolverInOutAdaptor {
+ TResolverInOutAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e)
+ : stage(s)
+ , resolver(r)
+ , infoSink(i)
+ , error(e)
+ {
+ }
+
+ inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
+ {
+ TVarEntryInfo& ent = entKey.second;
+ ent.newLocation = -1;
+ ent.newComponent = -1;
+ ent.newBinding = -1;
+ ent.newSet = -1;
+ ent.newIndex = -1;
+ const bool isValid = resolver.validateInOut(stage, ent);
+ if (isValid) {
+ resolver.resolveInOutLocation(stage, ent);
+ resolver.resolveInOutComponent(stage, ent);
+ resolver.resolveInOutIndex(stage, ent);
+ } else {
+ TString errorMsg;
+ if (ent.symbol->getType().getQualifier().semanticName != nullptr) {
+ errorMsg = "Invalid shader In/Out variable semantic: ";
+ errorMsg += ent.symbol->getType().getQualifier().semanticName;
+ } else {
+ errorMsg = "Invalid shader In/Out variable: ";
+ errorMsg += ent.symbol->getName();
+ }
+ infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
+ error = true;
+ }
+ }
+
+ inline void setStage(EShLanguage s) { stage = s; }
+
+ EShLanguage stage;
+ TIoMapResolver& resolver;
+ TInfoSink& infoSink;
+ bool& error;
+
+private:
+ TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&);
+};
+
+// The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings
+
+struct TSymbolValidater
+{
+ TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount],
+ TVarLiveMap* uniform[EShLangCount], bool& hadError)
+ : preStage(EShLangCount)
+ , currentStage(EShLangCount)
+ , nextStage(EShLangCount)
+ , resolver(r)
+ , infoSink(i)
+ , hadError(hadError)
+ {
+ memcpy(inVarMaps, in, EShLangCount * (sizeof(TVarLiveMap*)));
+ memcpy(outVarMaps, out, EShLangCount * (sizeof(TVarLiveMap*)));
+ memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));
+ }
+
+ inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
+ TVarEntryInfo& ent1 = entKey.second;
+ TIntermSymbol* base = ent1.symbol;
+ const TType& type = ent1.symbol->getType();
+ const TString& name = entKey.first;
+ TString mangleName1, mangleName2;
+ type.appendMangledName(mangleName1);
+ EShLanguage stage = ent1.stage;
+ if (currentStage != stage) {
+ preStage = currentStage;
+ currentStage = stage;
+ nextStage = EShLangCount;
+ for (int i = currentStage + 1; i < EShLangCount; i++) {
+ if (inVarMaps[i] != nullptr)
+ nextStage = static_cast<EShLanguage>(i);
+ }
+ }
+ if (base->getQualifier().storage == EvqVaryingIn) {
+ // validate stage in;
+ if (preStage == EShLangCount)
+ return;
+ if (outVarMaps[preStage] != nullptr) {
+ auto ent2 = outVarMaps[preStage]->find(name);
+ if (ent2 != outVarMaps[preStage]->end()) {
+ ent2->second.symbol->getType().appendMangledName(mangleName2);
+ if (mangleName1 == mangleName2)
+ return;
+ else {
+ TString err = "Invalid In/Out variable type : " + entKey.first;
+ infoSink.info.message(EPrefixInternalError, err.c_str());
+ hadError = true;
+ }
+ }
+ return;
+ }
+ } else if (base->getQualifier().storage == EvqVaryingOut) {
+ // validate stage out;
+ if (nextStage == EShLangCount)
+ return;
+ if (outVarMaps[nextStage] != nullptr) {
+ auto ent2 = inVarMaps[nextStage]->find(name);
+ if (ent2 != inVarMaps[nextStage]->end()) {
+ ent2->second.symbol->getType().appendMangledName(mangleName2);
+ if (mangleName1 == mangleName2)
+ return;
+ else {
+ TString err = "Invalid In/Out variable type : " + entKey.first;
+ infoSink.info.message(EPrefixInternalError, err.c_str());
+ hadError = true;
+ }
+ }
+ return;
+ }
+ } else if (base->getQualifier().isUniformOrBuffer() && ! base->getQualifier().isPushConstant()) {
+ // validate uniform type;
+ for (int i = 0; i < EShLangCount; i++) {
+ if (i != currentStage && outVarMaps[i] != nullptr) {
+ auto ent2 = uniformVarMap[i]->find(name);
+ if (ent2 != uniformVarMap[i]->end()) {
+ ent2->second.symbol->getType().appendMangledName(mangleName2);
+ if (mangleName1 != mangleName2) {
+ TString err = "Invalid Uniform variable type : " + entKey.first;
+ infoSink.info.message(EPrefixInternalError, err.c_str());
+ hadError = true;
+ }
+ mangleName2.clear();
+ }
+ }
+ }
+ }
+ }
+ TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount];
+ // Use for mark pre stage, to get more interface symbol information.
+ EShLanguage preStage, currentStage, nextStage;
+ // Use for mark current shader stage for resolver
+ TIoMapResolver& resolver;
+ TInfoSink& infoSink;
+ bool& hadError;
+
+private:
+ TSymbolValidater& operator=(TSymbolValidater&);
+};
+
+struct TSlotCollector {
+ TSlotCollector(TIoMapResolver& r, TInfoSink& i) : resolver(r), infoSink(i) { }
+
+ inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
+ resolver.reserverStorageSlot(entKey.second, infoSink);
+ resolver.reserverResourceSlot(entKey.second, infoSink);
+ }
+ TIoMapResolver& resolver;
+ TInfoSink& infoSink;
+
+private:
+ TSlotCollector& operator=(TSlotCollector&);
+};
+
+TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate)
+ : intermediate(intermediate)
+ , nextUniformLocation(intermediate.getUniformLocationBase())
+ , nextInputLocation(0)
+ , nextOutputLocation(0)
+{
+ memset(stageMask, false, sizeof(bool) * (EShLangCount + 1));
+}
+
+int TDefaultIoResolverBase::getBaseBinding(TResourceType res, unsigned int set) const {
+ return selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set));
+}
+
+const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding() const {
+ return intermediate.getResourceSetBinding();
+}
+
+bool TDefaultIoResolverBase::doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); }
+
+bool TDefaultIoResolverBase::doAutoLocationMapping() const { return intermediate.getAutoMapLocations(); }
+
+TDefaultIoResolverBase::TSlotSet::iterator TDefaultIoResolverBase::findSlot(int set, int slot) {
+ return std::lower_bound(slots[set].begin(), slots[set].end(), slot);
+}
+
+bool TDefaultIoResolverBase::checkEmpty(int set, int slot) {
+ TSlotSet::iterator at = findSlot(set, slot);
+ return ! (at != slots[set].end() && *at == slot);
+}
+
+int TDefaultIoResolverBase::reserveSlot(int set, int slot, int size) {
+ TSlotSet::iterator at = findSlot(set, slot);
+ // tolerate aliasing, by not double-recording aliases
+ // (policy about appropriateness of the alias is higher up)
+ for (int i = 0; i < size; i++) {
+ if (at == slots[set].end() || *at != slot + i)
+ at = slots[set].insert(at, slot + i);
+ ++at;
+ }
+ return slot;
+}
+
+int TDefaultIoResolverBase::getFreeSlot(int set, int base, int size) {
+ TSlotSet::iterator at = findSlot(set, base);
+ if (at == slots[set].end())
+ return reserveSlot(set, base, size);
+ // look for a big enough gap
+ for (; at != slots[set].end(); ++at) {
+ if (*at - base >= size)
+ break;
+ base = *at + 1;
+ }
+ return reserveSlot(set, base, size);
+}
+
+int TDefaultIoResolverBase::resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) {
+ const TType& type = ent.symbol->getType();
+ if (type.getQualifier().hasSet()) {
+ return ent.newSet = type.getQualifier().layoutSet;
+ }
+ // If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
+ if (getResourceSetBinding().size() == 1) {
+ return ent.newSet = atoi(getResourceSetBinding()[0].c_str());
+ }
+ return ent.newSet = 0;
+}
+
+int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
+ const TType& type = ent.symbol->getType();
+ const char* name = ent.symbol->getName().c_str();
+ // kick out of not doing this
+ if (! doAutoLocationMapping()) {
+ return ent.newLocation = -1;
+ }
+ // no locations added if already present, a built-in variable, a block, or an opaque
+ if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock ||
+ type.isAtomic() || (type.containsOpaque() && intermediate.getSpv().openGl == 0)) {
+ return ent.newLocation = -1;
+ }
+ // no locations on blocks of built-in variables
+ if (type.isStruct()) {
+ if (type.getStruct()->size() < 1) {
+ return ent.newLocation = -1;
+ }
+ if ((*type.getStruct())[0].type->isBuiltIn()) {
+ return ent.newLocation = -1;
+ }
+ }
+ int location = intermediate.getUniformLocationOverride(name);
+ if (location != -1) {
+ return ent.newLocation = location;
+ }
+ location = nextUniformLocation;
+ nextUniformLocation += TIntermediate::computeTypeUniformLocationSize(type);
+ return ent.newLocation = location;
+}
+
+int TDefaultIoResolverBase::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
+ const TType& type = ent.symbol->getType();
+ // kick out of not doing this
+ if (! doAutoLocationMapping()) {
+ return ent.newLocation = -1;
+ }
+
+ // no locations added if already present, or a built-in variable
+ if (type.getQualifier().hasLocation() || type.isBuiltIn()) {
+ return ent.newLocation = -1;
+ }
+
+ // no locations on blocks of built-in variables
+ if (type.isStruct()) {
+ if (type.getStruct()->size() < 1) {
+ return ent.newLocation = -1;
+ }
+ if ((*type.getStruct())[0].type->isBuiltIn()) {
+ return ent.newLocation = -1;
+ }
+ }
+ // point to the right input or output location counter
+ int& nextLocation = type.getQualifier().isPipeInput() ? nextInputLocation : nextOutputLocation;
+ // Placeholder. This does not do proper cross-stage lining up, nor
+ // work with mixed location/no-location declarations.
+ int location = nextLocation;
+ int typeLocationSize;
+ // Don’t take into account the outer-most array if the stage’s
+ // interface is automatically an array.
+ typeLocationSize = computeTypeLocationSize(type, stage);
+ nextLocation += typeLocationSize;
+ return ent.newLocation = location;
+}
+
+int TDefaultIoResolverBase::resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) {
+ return ent.newComponent = -1;
+}
+
+int TDefaultIoResolverBase::resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) { return ent.newIndex = -1; }
+
+uint32_t TDefaultIoResolverBase::computeTypeLocationSize(const TType& type, EShLanguage stage) {
+ int typeLocationSize;
+ // Don’t take into account the outer-most array if the stage’s
+ // interface is automatically an array.
+ if (type.getQualifier().isArrayedIo(stage)) {
+ TType elementType(type, 0);
+ typeLocationSize = TIntermediate::computeTypeLocationSize(elementType, stage);
+ } else {
+ typeLocationSize = TIntermediate::computeTypeLocationSize(type, stage);
+ }
+ return typeLocationSize;
+}
+
+//TDefaultGlslIoResolver
+TResourceType TDefaultGlslIoResolver::getResourceType(const glslang::TType& type) {
+ if (isImageType(type)) {
+ return EResImage;
+ }
+ if (isTextureType(type)) {
+ return EResTexture;
+ }
+ if (isSsboType(type)) {
+ return EResSsbo;
+ }
+ if (isSamplerType(type)) {
+ return EResSampler;
+ }
+ if (isUboType(type)) {
+ return EResUbo;
+ }
+ return EResCount;
+}
+
+TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate)
+ : TDefaultIoResolverBase(intermediate)
+ , preStage(EShLangCount)
+ , currentStage(EShLangCount)
+{ }
+
+int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
+ const TType& type = ent.symbol->getType();
+ const TString& name = ent.symbol->getName();
+ if (currentStage != stage) {
+ preStage = currentStage;
+ currentStage = stage;
+ }
+ // kick out of not doing this
+ if (! doAutoLocationMapping()) {
+ return ent.newLocation = -1;
+ }
+ // expand the location to each element if the symbol is a struct or array
+ if (type.getQualifier().hasLocation()) {
+ return ent.newLocation = type.getQualifier().layoutLocation;
+ }
+ // no locations added if already present, or a built-in variable
+ if (type.isBuiltIn()) {
+ return ent.newLocation = -1;
+ }
+ // no locations on blocks of built-in variables
+ if (type.isStruct()) {
+ if (type.getStruct()->size() < 1) {
+ return ent.newLocation = -1;
+ }
+ if ((*type.getStruct())[0].type->isBuiltIn()) {
+ return ent.newLocation = -1;
+ }
+ }
+ int typeLocationSize = computeTypeLocationSize(type, stage);
+ int location = type.getQualifier().layoutLocation;
+ bool hasLocation = false;
+ EShLanguage keyStage(EShLangCount);
+ TStorageQualifier storage;
+ storage = EvqInOut;
+ if (type.getQualifier().isPipeInput()) {
+ // If this symbol is a input, search pre stage's out
+ keyStage = preStage;
+ }
+ if (type.getQualifier().isPipeOutput()) {
+ // If this symbol is a output, search next stage's in
+ keyStage = currentStage;
+ }
+ // The in/out in current stage is not declared with location, but it is possible declared
+ // with explicit location in other stages, find the storageSlotMap firstly to check whether
+ // the in/out has location
+ int resourceKey = buildStorageKey(keyStage, storage);
+ if (! storageSlotMap[resourceKey].empty()) {
+ TVarSlotMap::iterator iter = storageSlotMap[resourceKey].find(name);
+ if (iter != storageSlotMap[resourceKey].end()) {
+ // If interface resource be found, set it has location and this symbol's new location
+ // equal the symbol's explicit location declarated in pre or next stage.
+ //
+ // vs: out vec4 a;
+ // fs: layout(..., location = 3,...) in vec4 a;
+ hasLocation = true;
+ location = iter->second;
+ // if we want deal like that:
+ // vs: layout(location=4) out vec4 a;
+ // out vec4 b;
+ //
+ // fs: in vec4 a;
+ // layout(location = 4) in vec4 b;
+ // we need retraverse the map.
+ }
+ if (! hasLocation) {
+ // If interface resource note found, It's mean the location in two stage are both implicit declarat.
+ // So we should find a new slot for this interface.
+ //
+ // vs: out vec4 a;
+ // fs: in vec4 a;
+ location = getFreeSlot(resourceKey, 0, typeLocationSize);
+ storageSlotMap[resourceKey][name] = location;
+ }
+ } else {
+ // the first interface declarated in a program.
+ TVarSlotMap varSlotMap;
+ location = getFreeSlot(resourceKey, 0, typeLocationSize);
+ varSlotMap[name] = location;
+ storageSlotMap[resourceKey] = varSlotMap;
+ }
+ //Update location
+ return ent.newLocation = location;
+}
+
+int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
+ const TType& type = ent.symbol->getType();
+ const TString& name = ent.symbol->getName();
+ // kick out of not doing this
+ if (! doAutoLocationMapping()) {
+ return ent.newLocation = -1;
+ }
+ // expand the location to each element if the symbol is a struct or array
+ if (type.getQualifier().hasLocation() && (type.isStruct() || type.isArray())) {
+ return ent.newLocation = type.getQualifier().layoutLocation;
+ } else {
+ // no locations added if already present, a built-in variable, a block, or an opaque
+ if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock ||
+ type.isAtomic() || (type.containsOpaque() && intermediate.getSpv().openGl == 0)) {
+ return ent.newLocation = -1;
+ }
+ // no locations on blocks of built-in variables
+ if (type.isStruct()) {
+ if (type.getStruct()->size() < 1) {
+ return ent.newLocation = -1;
+ }
+ if ((*type.getStruct())[0].type->isBuiltIn()) {
+ return ent.newLocation = -1;
+ }
+ }
+ }
+ int location = intermediate.getUniformLocationOverride(name.c_str());
+ if (location != -1) {
+ return ent.newLocation = location;
+ }
+
+ int size = TIntermediate::computeTypeUniformLocationSize(type);
+
+ // The uniform in current stage is not declared with location, but it is possible declared
+ // with explicit location in other stages, find the storageSlotMap firstly to check whether
+ // the uniform has location
+ bool hasLocation = false;
+ int resourceKey = buildStorageKey(EShLangCount, EvqUniform);
+ TVarSlotMap& slotMap = storageSlotMap[resourceKey];
+ // Check dose shader program has uniform resource
+ if (! slotMap.empty()) {
+ // If uniform resource not empty, try find a same name uniform
+ TVarSlotMap::iterator iter = slotMap.find(name);
+ if (iter != slotMap.end()) {
+ // If uniform resource be found, set it has location and this symbol's new location
+ // equal the uniform's explicit location declarated in other stage.
+ //
+ // vs: uniform vec4 a;
+ // fs: layout(..., location = 3,...) uniform vec4 a;
+ hasLocation = true;
+ location = iter->second;
+ }
+ if (! hasLocation) {
+ // No explicit location declaraten in other stage.
+ // So we should find a new slot for this uniform.
+ //
+ // vs: uniform vec4 a;
+ // fs: uniform vec4 a;
+ location = getFreeSlot(resourceKey, 0, computeTypeLocationSize(type, currentStage));
+ storageSlotMap[resourceKey][name] = location;
+ }
+ } else {
+ // the first uniform declarated in a program.
+ TVarSlotMap varSlotMap;
+ location = getFreeSlot(resourceKey, 0, size);
+ varSlotMap[name] = location;
+ storageSlotMap[resourceKey] = varSlotMap;
+ }
+ return ent.newLocation = location;
+}
+
+int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
+ const TType& type = ent.symbol->getType();
+ const TString& name = ent.symbol->getName();
+ // On OpenGL arrays of opaque types take a seperate binding for each element
+ int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
+ TResourceType resource = getResourceType(type);
+ // don't need to handle uniform symbol, it will be handled in resolveUniformLocation
+ if (resource == EResUbo && type.getBasicType() != EbtBlock) {
+ return ent.newBinding = -1;
+ }
+ // There is no 'set' qualifier in OpenGL shading language, each resource has its own
+ // binding name space, so remap the 'set' to resource type which make each resource
+ // binding is valid from 0 to MAX_XXRESOURCE_BINDINGS
+ int set = resource;
+ if (resource < EResCount) {
+ if (type.getQualifier().hasBinding()) {
+ ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings);
+ return ent.newBinding;
+ } else if (ent.live && doAutoBindingMapping()) {
+ // The resource in current stage is not declared with binding, but it is possible declared
+ // with explicit binding in other stages, find the resourceSlotMap firstly to check whether
+ // the resource has binding, don't need to allocate if it already has a binding
+ bool hasBinding = false;
+ if (! resourceSlotMap[resource].empty()) {
+ TVarSlotMap::iterator iter = resourceSlotMap[resource].find(name);
+ if (iter != resourceSlotMap[resource].end()) {
+ hasBinding = true;
+ ent.newBinding = iter->second;
+ }
+ }
+ if (! hasBinding) {
+ TVarSlotMap varSlotMap;
+ // find free slot, the caller did make sure it passes all vars with binding
+ // first and now all are passed that do not have a binding and needs one
+ int binding = getFreeSlot(resource, getBaseBinding(resource, set), numBindings);
+ varSlotMap[name] = binding;
+ resourceSlotMap[resource] = varSlotMap;
+ ent.newBinding = binding;
+ }
+ return ent.newBinding;
+ }
+ }
+ return ent.newBinding = -1;
+}
+
+void TDefaultGlslIoResolver::beginResolve(EShLanguage stage) {
+ // reset stage state
+ if (stage == EShLangCount)
+ preStage = currentStage = stage;
+ // update stage state
+ else if (currentStage != stage) {
+ preStage = currentStage;
+ currentStage = stage;
+ }
+}
+
+void TDefaultGlslIoResolver::endResolve(EShLanguage /*stage*/) {
+ // TODO nothing
+}
+
+void TDefaultGlslIoResolver::beginCollect(EShLanguage stage) {
+ // reset stage state
+ if (stage == EShLangCount)
+ preStage = currentStage = stage;
+ // update stage state
+ else if (currentStage != stage) {
+ preStage = currentStage;
+ currentStage = stage;
+ }
+}
+
+void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) {
+ // TODO nothing
+}
+
+void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
+ const TType& type = ent.symbol->getType();
+ const TString& name = ent.symbol->getName();
+ TStorageQualifier storage = type.getQualifier().storage;
+ EShLanguage stage(EShLangCount);
+ switch (storage) {
+ case EvqUniform:
+ if (type.getBasicType() != EbtBlock && type.getQualifier().hasLocation()) {
+ //
+ // Reserve the slots for the uniforms who has explicit location
+ int storageKey = buildStorageKey(EShLangCount, EvqUniform);
+ int location = type.getQualifier().layoutLocation;
+ TVarSlotMap& varSlotMap = storageSlotMap[storageKey];
+ TVarSlotMap::iterator iter = varSlotMap.find(name);
+ if (iter == varSlotMap.end()) {
+ int numLocations = TIntermediate::computeTypeUniformLocationSize(type);
+ reserveSlot(storageKey, location, numLocations);
+ varSlotMap[name] = location;
+ } else {
+ // Allocate location by name for OpenGL driver, so the uniform in different
+ // stages should be declared with the same location
+ if (iter->second != location) {
+ TString errorMsg = "Invalid location: " + name;
+ infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
+ }
+ }
+ }
+ break;
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ //
+ // Reserve the slots for the inout who has explicit location
+ if (type.getQualifier().hasLocation()) {
+ stage = storage == EvqVaryingIn ? preStage : stage;
+ stage = storage == EvqVaryingOut ? currentStage : stage;
+ int storageKey = buildStorageKey(stage, EvqInOut);
+ int location = type.getQualifier().layoutLocation;
+ TVarSlotMap& varSlotMap = storageSlotMap[storageKey];
+ TVarSlotMap::iterator iter = varSlotMap.find(name);
+ if (iter == varSlotMap.end()) {
+ int numLocations = TIntermediate::computeTypeUniformLocationSize(type);
+ reserveSlot(storageKey, location, numLocations);
+ varSlotMap[name] = location;
+ } else {
+ // Allocate location by name for OpenGL driver, so the uniform in different
+ // stages should be declared with the same location
+ if (iter->second != location) {
+ TString errorMsg = "Invalid location: " + name;
+ infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
+ const TType& type = ent.symbol->getType();
+ const TString& name = ent.symbol->getName();
+ int resource = getResourceType(type);
+ if (type.getQualifier().hasBinding()) {
+ TVarSlotMap& varSlotMap = resourceSlotMap[resource];
+ TVarSlotMap::iterator iter = varSlotMap.find(name);
+ int binding = type.getQualifier().layoutBinding;
+ if (iter == varSlotMap.end()) {
+ // Reserve the slots for the ubo, ssbo and opaques who has explicit binding
+ int numBindings = type.isSizedArray() ? type.getCumulativeArraySize() : 1;
+ varSlotMap[name] = binding;
+ reserveSlot(resource, binding, numBindings);
+ } else {
+ // Allocate binding by name for OpenGL driver, so the resource in different
+ // stages should be declared with the same binding
+ if (iter->second != binding) {
+ TString errorMsg = "Invalid binding: " + name;
+ infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
+ }
+ }
+ }
+}
+
+//TDefaultGlslIoResolver end
+
+/*
+ * Basic implementation of glslang::TIoMapResolver that replaces the
+ * previous offset behavior.
+ * It does the same, uses the offsets for the corresponding uniform
+ * types. Also respects the EOptionAutoMapBindings flag and binds
+ * them if needed.
+ */
+/*
+ * Default resolver
+ */
+struct TDefaultIoResolver : public TDefaultIoResolverBase {
+ TDefaultIoResolver(const TIntermediate& intermediate) : TDefaultIoResolverBase(intermediate) { }
+
+ bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
+
+ TResourceType getResourceType(const glslang::TType& type) override {
+ if (isImageType(type)) {
+ return EResImage;
+ }
+ if (isTextureType(type)) {
+ return EResTexture;
+ }
+ if (isSsboType(type)) {
+ return EResSsbo;
+ }
+ if (isSamplerType(type)) {
+ return EResSampler;
+ }
+ if (isUboType(type)) {
+ return EResUbo;
+ }
+ return EResCount;
+ }
+
+ int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override {
+ const TType& type = ent.symbol->getType();
+ const int set = getLayoutSet(type);
+ // On OpenGL arrays of opaque types take a seperate binding for each element
+ int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
+ TResourceType resource = getResourceType(type);
+ if (resource < EResCount) {
+ if (type.getQualifier().hasBinding()) {
+ return ent.newBinding = reserveSlot(
+ set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings);
+ } else if (ent.live && doAutoBindingMapping()) {
+ // find free slot, the caller did make sure it passes all vars with binding
+ // first and now all are passed that do not have a binding and needs one
+ return ent.newBinding = getFreeSlot(set, getBaseBinding(resource, set), numBindings);
+ }
+ }
+ return ent.newBinding = -1;
+ }
+};
+
+#ifdef ENABLE_HLSL
+/********************************************************************************
+The following IO resolver maps types in HLSL register space, as follows:
+
+t - for shader resource views (SRV)
+ TEXTURE1D
+ TEXTURE1DARRAY
+ TEXTURE2D
+ TEXTURE2DARRAY
+ TEXTURE3D
+ TEXTURECUBE
+ TEXTURECUBEARRAY
+ TEXTURE2DMS
+ TEXTURE2DMSARRAY
+ STRUCTUREDBUFFER
+ BYTEADDRESSBUFFER
+ BUFFER
+ TBUFFER
+
+s - for samplers
+ SAMPLER
+ SAMPLER1D
+ SAMPLER2D
+ SAMPLER3D
+ SAMPLERCUBE
+ SAMPLERSTATE
+ SAMPLERCOMPARISONSTATE
+
+u - for unordered access views (UAV)
+ RWBYTEADDRESSBUFFER
+ RWSTRUCTUREDBUFFER
+ APPENDSTRUCTUREDBUFFER
+ CONSUMESTRUCTUREDBUFFER
+ RWBUFFER
+ RWTEXTURE1D
+ RWTEXTURE1DARRAY
+ RWTEXTURE2D
+ RWTEXTURE2DARRAY
+ RWTEXTURE3D
+
+b - for constant buffer views (CBV)
+ CBUFFER
+ CONSTANTBUFFER
+ ********************************************************************************/
+struct TDefaultHlslIoResolver : public TDefaultIoResolverBase {
+ TDefaultHlslIoResolver(const TIntermediate& intermediate) : TDefaultIoResolverBase(intermediate) { }
+
+ bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
+
+ TResourceType getResourceType(const glslang::TType& type) override {
+ if (isUavType(type)) {
+ return EResUav;
+ }
+ if (isSrvType(type)) {
+ return EResTexture;
+ }
+ if (isSamplerType(type)) {
+ return EResSampler;
+ }
+ if (isUboType(type)) {
+ return EResUbo;
+ }
+ return EResCount;
+ }
+
+ int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override {
+ const TType& type = ent.symbol->getType();
+ const int set = getLayoutSet(type);
+ TResourceType resource = getResourceType(type);
+ if (resource < EResCount) {
+ if (type.getQualifier().hasBinding()) {
+ return ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding);
+ } else if (ent.live && doAutoBindingMapping()) {
+ // find free slot, the caller did make sure it passes all vars with binding
+ // first and now all are passed that do not have a binding and needs one
+ return ent.newBinding = getFreeSlot(set, getBaseBinding(resource, set));
+ }
+ }
+ return ent.newBinding = -1;
+ }
+};
+#endif
+
+// Map I/O variables to provided offsets, and make bindings for
+// unbound but live variables.
+//
+// Returns false if the input is too malformed to do this.
+bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) {
+ bool somethingToDo = ! intermediate.getResourceSetBinding().empty() || intermediate.getAutoMapBindings() ||
+ intermediate.getAutoMapLocations();
+ // Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce
+ // unnecessary or insignificant for-loop operation after 'somethingToDo' have been true.
+ for (int res = 0; (res < EResCount && !somethingToDo); ++res) {
+ somethingToDo = somethingToDo || (intermediate.getShiftBinding(TResourceType(res)) != 0) ||
+ intermediate.hasShiftBindingForSet(TResourceType(res));
+ }
+ if (! somethingToDo && resolver == nullptr)
+ return true;
+ if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
+ return false;
+ TIntermNode* root = intermediate.getTreeRoot();
+ if (root == nullptr)
+ return false;
+ // if no resolver is provided, use the default resolver with the given shifts and auto map settings
+ TDefaultIoResolver defaultResolver(intermediate);
+#ifdef ENABLE_HLSL
+ TDefaultHlslIoResolver defaultHlslResolver(intermediate);
+ if (resolver == nullptr) {
+ // TODO: use a passed in IO mapper for this
+ if (intermediate.usingHlslIoMapping())
+ resolver = &defaultHlslResolver;
+ else
+ resolver = &defaultResolver;
+ }
+ resolver->addStage(stage);
+#else
+ resolver = &defaultResolver;
+#endif
+
+ TVarLiveMap inVarMap, outVarMap, uniformVarMap;
+ TVarLiveVector inVector, outVector, uniformVector;
+ TVarGatherTraverser iter_binding_all(intermediate, true, inVarMap, outVarMap, uniformVarMap);
+ TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap);
+ root->traverse(&iter_binding_all);
+ iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
+ while (! iter_binding_live.functions.empty()) {
+ TIntermNode* function = iter_binding_live.functions.back();
+ iter_binding_live.functions.pop_back();
+ function->traverse(&iter_binding_live);
+ }
+ // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
+ std::for_each(inVarMap.begin(), inVarMap.end(),
+ [&inVector](TVarLivePair p) { inVector.push_back(p); });
+ std::sort(inVector.begin(), inVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
+ return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+ });
+ std::for_each(outVarMap.begin(), outVarMap.end(),
+ [&outVector](TVarLivePair p) { outVector.push_back(p); });
+ std::sort(outVector.begin(), outVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
+ return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+ });
+ std::for_each(uniformVarMap.begin(), uniformVarMap.end(),
+ [&uniformVector](TVarLivePair p) { uniformVector.push_back(p); });
+ std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
+ return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+ });
+ bool hadError = false;
+ TNotifyInOutAdaptor inOutNotify(stage, *resolver);
+ TNotifyUniformAdaptor uniformNotify(stage, *resolver);
+ TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError);
+ TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError);
+ resolver->beginNotifications(stage);
+ std::for_each(inVector.begin(), inVector.end(), inOutNotify);
+ std::for_each(outVector.begin(), outVector.end(), inOutNotify);
+ std::for_each(uniformVector.begin(), uniformVector.end(), uniformNotify);
+ resolver->endNotifications(stage);
+ resolver->beginResolve(stage);
+ std::for_each(inVector.begin(), inVector.end(), inOutResolve);
+ std::for_each(inVector.begin(), inVector.end(), [&inVarMap](TVarLivePair p) {
+ auto at = inVarMap.find(p.second.symbol->getName());
+ if (at != inVarMap.end())
+ at->second = p.second;
+ });
+ std::for_each(outVector.begin(), outVector.end(), inOutResolve);
+ std::for_each(outVector.begin(), outVector.end(), [&outVarMap](TVarLivePair p) {
+ auto at = outVarMap.find(p.second.symbol->getName());
+ if (at != outVarMap.end())
+ at->second = p.second;
+ });
+ std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
+ std::for_each(uniformVector.begin(), uniformVector.end(), [&uniformVarMap](TVarLivePair p) {
+ auto at = uniformVarMap.find(p.second.symbol->getName());
+ if (at != uniformVarMap.end())
+ at->second = p.second;
+ });
+ resolver->endResolve(stage);
+ if (!hadError) {
+ TVarSetTraverser iter_iomap(intermediate, inVarMap, outVarMap, uniformVarMap);
+ root->traverse(&iter_iomap);
+ }
+ return !hadError;
+}
+
+// Map I/O variables to provided offsets, and make bindings for
+// unbound but live variables.
+//
+// Returns false if the input is too malformed to do this.
+bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) {
+
+ bool somethingToDo = ! intermediate.getResourceSetBinding().empty() || intermediate.getAutoMapBindings() ||
+ intermediate.getAutoMapLocations();
+ // Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce
+ // unnecessary or insignificant for-loop operation after 'somethingToDo' have been true.
+ for (int res = 0; (res < EResCount && !somethingToDo); ++res) {
+ somethingToDo = somethingToDo || (intermediate.getShiftBinding(TResourceType(res)) != 0) ||
+ intermediate.hasShiftBindingForSet(TResourceType(res));
+ }
+ if (! somethingToDo && resolver == nullptr) {
+ return true;
+ }
+ if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive()) {
+ return false;
+ }
+ TIntermNode* root = intermediate.getTreeRoot();
+ if (root == nullptr) {
+ return false;
+ }
+ // if no resolver is provided, use the default resolver with the given shifts and auto map settings
+ TDefaultGlslIoResolver defaultResolver(intermediate);
+ if (resolver == nullptr) {
+ resolver = &defaultResolver;
+ }
+ resolver->addStage(stage);
+ inVarMaps[stage] = new TVarLiveMap, outVarMaps[stage] = new TVarLiveMap(), uniformVarMap[stage] = new TVarLiveMap();
+ TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage],
+ *uniformVarMap[stage]);
+ TVarGatherTraverser iter_binding_live(intermediate, false, *inVarMaps[stage], *outVarMaps[stage],
+ *uniformVarMap[stage]);
+ root->traverse(&iter_binding_all);
+ iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
+ while (! iter_binding_live.functions.empty()) {
+ TIntermNode* function = iter_binding_live.functions.back();
+ iter_binding_live.functions.pop_back();
+ function->traverse(&iter_binding_live);
+ }
+ TNotifyInOutAdaptor inOutNotify(stage, *resolver);
+ TNotifyUniformAdaptor uniformNotify(stage, *resolver);
+ // Resolve current stage input symbol location with previous stage output here,
+ // uniform symbol, ubo, ssbo and opaque symbols are per-program resource,
+ // will resolve uniform symbol location and ubo/ssbo/opaque binding in doMap()
+ resolver->beginNotifications(stage);
+ std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), inOutNotify);
+ std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), inOutNotify);
+ std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(), uniformNotify);
+ resolver->endNotifications(stage);
+ TSlotCollector slotCollector(*resolver, infoSink);
+ resolver->beginCollect(stage);
+ std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), slotCollector);
+ std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), slotCollector);
+ std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(), slotCollector);
+ resolver->endCollect(stage);
+ intermediates[stage] = &intermediate;
+ return !hadError;
+}
+
+bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
+ resolver->endResolve(EShLangCount);
+ if (!hadError) {
+ //Resolve uniform location, ubo/ssbo/opaque bindings across stages
+ TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, infoSink, hadError);
+ TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError);
+ TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps, outVarMaps, uniformVarMap, hadError);
+ TVarLiveVector uniformVector;
+ resolver->beginResolve(EShLangCount);
+ for (int stage = EShLangVertex; stage < EShLangCount; stage++) {
+ if (inVarMaps[stage] != nullptr) {
+ inOutResolve.setStage(EShLanguage(stage));
+ std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), symbolValidater);
+ std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), inOutResolve);
+ std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), symbolValidater);
+ std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), inOutResolve);
+ }
+ if (uniformVarMap[stage] != nullptr) {
+ uniformResolve.setStage(EShLanguage(stage));
+ // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
+ std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(),
+ [&uniformVector](TVarLivePair p) { uniformVector.push_back(p); });
+ }
+ }
+ std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
+ return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+ });
+ std::for_each(uniformVector.begin(), uniformVector.end(), symbolValidater);
+ std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
+ std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
+ return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
+ });
+ resolver->endResolve(EShLangCount);
+ for (size_t stage = 0; stage < EShLangCount; stage++) {
+ if (intermediates[stage] != nullptr) {
+ // traverse each stage, set new location to each input/output and unifom symbol, set new binding to
+ // ubo, ssbo and opaque symbols
+ TVarLiveMap** pUniformVarMap = uniformVarMap;
+ std::for_each(uniformVector.begin(), uniformVector.end(), [pUniformVarMap, stage](TVarLivePair p) {
+ auto at = pUniformVarMap[stage]->find(p.second.symbol->getName());
+ if (at != pUniformVarMap[stage]->end())
+ at->second = p.second;
+ });
+ TVarSetTraverser iter_iomap(*intermediates[stage], *inVarMaps[stage], *outVarMaps[stage],
+ *uniformVarMap[stage]);
+ intermediates[stage]->getTreeRoot()->traverse(&iter_iomap);
+ }
+ }
+ return !hadError;
+ } else {
+ return false;
+ }
+}
+
+} // end namespace glslang
+
+#endif // GLSLANG_WEB
diff --git a/thirdparty/glslang/glslang/MachineIndependent/iomapper.h b/thirdparty/glslang/glslang/MachineIndependent/iomapper.h
new file mode 100644
index 0000000000..684e88d571
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/iomapper.h
@@ -0,0 +1,299 @@
+//
+// Copyright (C) 2016 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef GLSLANG_WEB
+
+#ifndef _IOMAPPER_INCLUDED
+#define _IOMAPPER_INCLUDED
+
+#include <cstdint>
+#include "LiveTraverser.h"
+#include <unordered_map>
+#include <unordered_set>
+//
+// A reflection database and its interface, consistent with the OpenGL API reflection queries.
+//
+
+class TInfoSink;
+
+namespace glslang {
+
+class TIntermediate;
+struct TVarEntryInfo {
+ int id;
+ TIntermSymbol* symbol;
+ bool live;
+ int newBinding;
+ int newSet;
+ int newLocation;
+ int newComponent;
+ int newIndex;
+ EShLanguage stage;
+ struct TOrderById {
+ inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; }
+ };
+
+ struct TOrderByPriority {
+ // ordering:
+ // 1) has both binding and set
+ // 2) has binding but no set
+ // 3) has no binding but set
+ // 4) has no binding and no set
+ inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
+ const TQualifier& lq = l.symbol->getQualifier();
+ const TQualifier& rq = r.symbol->getQualifier();
+
+ // simple rules:
+ // has binding gives 2 points
+ // has set gives 1 point
+ // who has the most points is more important.
+ int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
+ int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
+
+ if (lPoints == rPoints)
+ return l.id < r.id;
+ return lPoints > rPoints;
+ }
+ };
+};
+
+// Base class for shared TIoMapResolver services, used by several derivations.
+struct TDefaultIoResolverBase : public glslang::TIoMapResolver {
+public:
+ TDefaultIoResolverBase(const TIntermediate& intermediate);
+ typedef std::vector<int> TSlotSet;
+ typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
+
+ // grow the reflection stage by stage
+ void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {}
+ void notifyInOut(EShLanguage, TVarEntryInfo& /*ent*/) override {}
+ void beginNotifications(EShLanguage) override {}
+ void endNotifications(EShLanguage) override {}
+ void beginResolve(EShLanguage) override {}
+ void endResolve(EShLanguage) override {}
+ void beginCollect(EShLanguage) override {}
+ void endCollect(EShLanguage) override {}
+ void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
+ void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
+ int getBaseBinding(TResourceType res, unsigned int set) const;
+ const std::vector<std::string>& getResourceSetBinding() const;
+ virtual TResourceType getResourceType(const glslang::TType& type) = 0;
+ bool doAutoBindingMapping() const;
+ bool doAutoLocationMapping() const;
+ TSlotSet::iterator findSlot(int set, int slot);
+ bool checkEmpty(int set, int slot);
+ bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
+ int reserveSlot(int set, int slot, int size = 1);
+ int getFreeSlot(int set, int base, int size = 1);
+ int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
+ int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
+ int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
+ int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
+ int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
+ void addStage(EShLanguage stage) override {
+ if (stage < EShLangCount)
+ stageMask[stage] = true;
+ }
+ uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
+
+ TSlotSetMap slots;
+
+protected:
+ TDefaultIoResolverBase(TDefaultIoResolverBase&);
+ TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&);
+ const TIntermediate& intermediate;
+ int nextUniformLocation;
+ int nextInputLocation;
+ int nextOutputLocation;
+ bool stageMask[EShLangCount + 1];
+ // Return descriptor set specific base if there is one, and the generic base otherwise.
+ int selectBaseBinding(int base, int descriptorSetBase) const {
+ return descriptorSetBase != -1 ? descriptorSetBase : base;
+ }
+
+ static int getLayoutSet(const glslang::TType& type) {
+ if (type.getQualifier().hasSet())
+ return type.getQualifier().layoutSet;
+ else
+ return 0;
+ }
+
+ static bool isSamplerType(const glslang::TType& type) {
+ return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler();
+ }
+
+ static bool isTextureType(const glslang::TType& type) {
+ return (type.getBasicType() == glslang::EbtSampler &&
+ (type.getSampler().isTexture() || type.getSampler().isSubpass()));
+ }
+
+ static bool isUboType(const glslang::TType& type) {
+ return type.getQualifier().storage == EvqUniform;
+ }
+
+ static bool isImageType(const glslang::TType& type) {
+ return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage();
+ }
+
+ static bool isSsboType(const glslang::TType& type) {
+ return type.getQualifier().storage == EvqBuffer;
+ }
+
+ // Return true if this is a SRV (shader resource view) type:
+ static bool isSrvType(const glslang::TType& type) {
+ return isTextureType(type) || type.getQualifier().storage == EvqBuffer;
+ }
+
+ // Return true if this is a UAV (unordered access view) type:
+ static bool isUavType(const glslang::TType& type) {
+ if (type.getQualifier().isReadOnly())
+ return false;
+ return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) ||
+ (type.getQualifier().storage == EvqBuffer);
+ }
+};
+
+// Defaulf I/O resolver for OpenGL
+struct TDefaultGlslIoResolver : public TDefaultIoResolverBase {
+public:
+ typedef std::map<TString, int> TVarSlotMap; // <resourceName, location/binding>
+ typedef std::map<int, TVarSlotMap> TSlotMap; // <resourceKey, TVarSlotMap>
+ TDefaultGlslIoResolver(const TIntermediate& intermediate);
+ bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
+ TResourceType getResourceType(const glslang::TType& type) override;
+ int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
+ int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
+ int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
+ void beginResolve(EShLanguage /*stage*/) override;
+ void endResolve(EShLanguage stage) override;
+ void beginCollect(EShLanguage) override;
+ void endCollect(EShLanguage) override;
+ void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
+ void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
+ // in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol.
+ // We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage.
+ // if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key.
+ // Note: both stage and type must less then 0xffff.
+ int buildStorageKey(EShLanguage stage, TStorageQualifier type) {
+ assert(static_cast<uint32_t>(stage) <= 0x0000ffff && static_cast<uint32_t>(type) <= 0x0000ffff);
+ return (stage << 16) | type;
+ }
+
+protected:
+ // Use for mark pre stage, to get more interface symbol information.
+ EShLanguage preStage;
+ // Use for mark current shader stage for resolver
+ EShLanguage currentStage;
+ // Slot map for storage resource(location of uniform and interface symbol) It's a program share slot
+ TSlotMap resourceSlotMap;
+ // Slot map for other resource(image, ubo, ssbo), It's a program share slot.
+ TSlotMap storageSlotMap;
+};
+
+typedef std::map<TString, TVarEntryInfo> TVarLiveMap;
+
+// override function "operator=", if a vector<const _Kty, _Ty> being sort,
+// when use vc++, the sort function will call :
+// pair& operator=(const pair<_Other1, _Other2>& _Right)
+// {
+// first = _Right.first;
+// second = _Right.second;
+// return (*this);
+// }
+// that will make a const type handing on left.
+// override this function can avoid a compiler error.
+// In the future, if the vc++ compiler can handle such a situation,
+// this part of the code will be removed.
+struct TVarLivePair : std::pair<const TString, TVarEntryInfo> {
+ TVarLivePair(std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
+ TVarLivePair& operator=(const TVarLivePair& _Right) {
+ const_cast<TString&>(first) = _Right.first;
+ second = _Right.second;
+ return (*this);
+ }
+};
+typedef std::vector<TVarLivePair> TVarLiveVector;
+
+// I/O mapper
+class TIoMapper {
+public:
+ TIoMapper() {}
+ virtual ~TIoMapper() {}
+ // grow the reflection stage by stage
+ bool virtual addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*);
+ bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; }
+};
+
+// I/O mapper for OpenGL
+class TGlslIoMapper : public TIoMapper {
+public:
+ TGlslIoMapper() {
+ memset(inVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
+ memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
+ memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
+ memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1));
+ }
+ virtual ~TGlslIoMapper() {
+ for (size_t stage = 0; stage < EShLangCount; stage++) {
+ if (inVarMaps[stage] != nullptr) {
+ delete inVarMaps[stage];
+ inVarMaps[stage] = nullptr;
+ }
+ if (outVarMaps[stage] != nullptr) {
+ delete outVarMaps[stage];
+ outVarMaps[stage] = nullptr;
+ }
+ if (uniformVarMap[stage] != nullptr) {
+ delete uniformVarMap[stage];
+ uniformVarMap[stage] = nullptr;
+ }
+ if (intermediates[stage] != nullptr)
+ intermediates[stage] = nullptr;
+ }
+ }
+ // grow the reflection stage by stage
+ bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override;
+ bool doMap(TIoMapResolver*, TInfoSink&) override;
+ TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount],
+ *uniformVarMap[EShLangCount];
+ TIntermediate* intermediates[EShLangCount];
+ bool hadError = false;
+};
+
+} // end namespace glslang
+
+#endif // _IOMAPPER_INCLUDED
+
+#endif // GLSLANG_WEB
diff --git a/thirdparty/glslang/glslang/MachineIndependent/limits.cpp b/thirdparty/glslang/glslang/MachineIndependent/limits.cpp
new file mode 100644
index 0000000000..51d9300341
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/limits.cpp
@@ -0,0 +1,200 @@
+//
+// Copyright (C) 2013 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Do sub tree walks for
+// 1) inductive loop bodies to see if the inductive variable is modified
+// 2) array-index expressions to see if they are "constant-index-expression"
+//
+// These are per Appendix A of ES 2.0:
+//
+// "Within the body of the loop, the loop index is not statically assigned to nor is it used as the
+// argument to a function out or inout parameter."
+//
+// "The following are constant-index-expressions:
+// - Constant expressions
+// - Loop indices as defined in section 4
+// - Expressions composed of both of the above"
+//
+// N.B.: assuming the last rule excludes function calls
+//
+
+#include "ParseHelper.h"
+
+namespace glslang {
+
+//
+// The inductive loop-body traverser.
+//
+// Just look at things that might modify the loop index.
+//
+
+class TInductiveTraverser : public TIntermTraverser {
+public:
+ TInductiveTraverser(int id, TSymbolTable& st)
+ : loopId(id), symbolTable(st), bad(false) { }
+
+ virtual bool visitBinary(TVisit, TIntermBinary* node);
+ virtual bool visitUnary(TVisit, TIntermUnary* node);
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node);
+
+ int loopId; // unique ID of the symbol that's the loop inductive variable
+ TSymbolTable& symbolTable;
+ bool bad;
+ TSourceLoc badLoc;
+
+protected:
+ TInductiveTraverser(TInductiveTraverser&);
+ TInductiveTraverser& operator=(TInductiveTraverser&);
+};
+
+// check binary operations for those modifying the loop index
+bool TInductiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
+{
+ if (node->modifiesState() && node->getLeft()->getAsSymbolNode() &&
+ node->getLeft()->getAsSymbolNode()->getId() == loopId) {
+ bad = true;
+ badLoc = node->getLoc();
+ }
+
+ return true;
+}
+
+// check unary operations for those modifying the loop index
+bool TInductiveTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
+{
+ if (node->modifiesState() && node->getOperand()->getAsSymbolNode() &&
+ node->getOperand()->getAsSymbolNode()->getId() == loopId) {
+ bad = true;
+ badLoc = node->getLoc();
+ }
+
+ return true;
+}
+
+// check function calls for arguments modifying the loop index
+bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
+{
+ if (node->getOp() == EOpFunctionCall) {
+ // see if an out or inout argument is the loop index
+ const TIntermSequence& args = node->getSequence();
+ for (int i = 0; i < (int)args.size(); ++i) {
+ if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == loopId) {
+ TSymbol* function = symbolTable.find(node->getName());
+ const TType* type = (*function->getAsFunction())[i].type;
+ if (type->getQualifier().storage == EvqOut ||
+ type->getQualifier().storage == EvqInOut) {
+ bad = true;
+ badLoc = node->getLoc();
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+//
+// External function to call for loop check.
+//
+void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable)
+{
+ TInductiveTraverser it(loopId, symbolTable);
+
+ if (body == nullptr)
+ return;
+
+ body->traverse(&it);
+
+ if (it.bad)
+ error(it.badLoc, "inductive loop index modified", "limitations", "");
+}
+
+//
+// The "constant-index-expression" tranverser.
+//
+// Just look at things that can form an index.
+//
+
+class TIndexTraverser : public TIntermTraverser {
+public:
+ TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { }
+ virtual void visitSymbol(TIntermSymbol* symbol);
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node);
+ const TIdSetType& inductiveLoopIds;
+ bool bad;
+ TSourceLoc badLoc;
+
+protected:
+ TIndexTraverser(TIndexTraverser&);
+ TIndexTraverser& operator=(TIndexTraverser&);
+};
+
+// make sure symbols are inductive-loop indexes
+void TIndexTraverser::visitSymbol(TIntermSymbol* symbol)
+{
+ if (inductiveLoopIds.find(symbol->getId()) == inductiveLoopIds.end()) {
+ bad = true;
+ badLoc = symbol->getLoc();
+ }
+}
+
+// check for function calls, assuming they are bad; spec. doesn't really say
+bool TIndexTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
+{
+ if (node->getOp() == EOpFunctionCall) {
+ bad = true;
+ badLoc = node->getLoc();
+ }
+
+ return true;
+}
+
+//
+// External function to call for loop check.
+//
+void TParseContext::constantIndexExpressionCheck(TIntermNode* index)
+{
+#ifndef GLSLANG_WEB
+ TIndexTraverser it(inductiveLoopIds);
+
+ index->traverse(&it);
+
+ if (it.bad)
+ error(it.badLoc, "Non-constant-index-expression", "limitations", "");
+#endif
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/linkValidate.cpp b/thirdparty/glslang/glslang/MachineIndependent/linkValidate.cpp
new file mode 100644
index 0000000000..fe51ec93ff
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/linkValidate.cpp
@@ -0,0 +1,1723 @@
+//
+// Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Do link-time merging and validation of intermediate representations.
+//
+// Basic model is that during compilation, each compilation unit (shader) is
+// compiled into one TIntermediate instance. Then, at link time, multiple
+// units for the same stage can be merged together, which can generate errors.
+// Then, after all merging, a single instance of TIntermediate represents
+// the whole stage. A final error check can be done on the resulting stage,
+// even if no merging was done (i.e., the stage was only one compilation unit).
+//
+
+#include "localintermediate.h"
+#include "../Include/InfoSink.h"
+
+namespace glslang {
+
+//
+// Link-time error emitter.
+//
+void TIntermediate::error(TInfoSink& infoSink, const char* message)
+{
+#ifndef GLSLANG_WEB
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n";
+#endif
+
+ ++numErrors;
+}
+
+// Link-time warning.
+void TIntermediate::warn(TInfoSink& infoSink, const char* message)
+{
+#ifndef GLSLANG_WEB
+ infoSink.info.prefix(EPrefixWarning);
+ infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n";
+#endif
+}
+
+// TODO: 4.4 offset/align: "Two blocks linked together in the same program with the same block
+// name must have the exact same set of members qualified with offset and their integral-constant
+// expression values must be the same, or a link-time error results."
+
+//
+// Merge the information from 'unit' into 'this'
+//
+void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
+{
+#ifndef GLSLANG_WEB
+ mergeCallGraphs(infoSink, unit);
+ mergeModes(infoSink, unit);
+ mergeTrees(infoSink, unit);
+#endif
+}
+
+void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
+{
+ if (unit.getNumEntryPoints() > 0) {
+ if (getNumEntryPoints() > 0)
+ error(infoSink, "can't handle multiple entry points per stage");
+ else {
+ entryPointName = unit.getEntryPointName();
+ entryPointMangledName = unit.getEntryPointMangledName();
+ }
+ }
+ numEntryPoints += unit.getNumEntryPoints();
+
+ callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
+}
+
+#ifndef GLSLANG_WEB
+
+#define MERGE_MAX(member) member = std::max(member, unit.member)
+#define MERGE_TRUE(member) if (unit.member) member = unit.member;
+
+void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
+{
+ if (language != unit.language)
+ error(infoSink, "stages must match when linking into a single stage");
+
+ if (getSource() == EShSourceNone)
+ setSource(unit.getSource());
+ if (getSource() != unit.getSource())
+ error(infoSink, "can't link compilation units from different source languages");
+
+ if (treeRoot == nullptr) {
+ profile = unit.profile;
+ version = unit.version;
+ requestedExtensions = unit.requestedExtensions;
+ } else {
+ if ((isEsProfile()) != (unit.isEsProfile()))
+ error(infoSink, "Cannot cross link ES and desktop profiles");
+ else if (unit.profile == ECompatibilityProfile)
+ profile = ECompatibilityProfile;
+ version = std::max(version, unit.version);
+ requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
+ }
+
+ MERGE_MAX(spvVersion.spv);
+ MERGE_MAX(spvVersion.vulkanGlsl);
+ MERGE_MAX(spvVersion.vulkan);
+ MERGE_MAX(spvVersion.openGl);
+
+ numErrors += unit.getNumErrors();
+ numPushConstants += unit.numPushConstants;
+
+ if (unit.invocations != TQualifier::layoutNotSet) {
+ if (invocations == TQualifier::layoutNotSet)
+ invocations = unit.invocations;
+ else if (invocations != unit.invocations)
+ error(infoSink, "number of invocations must match between compilation units");
+ }
+
+ if (vertices == TQualifier::layoutNotSet)
+ vertices = unit.vertices;
+ else if (vertices != unit.vertices) {
+ if (language == EShLangGeometry || language == EShLangMeshNV)
+ error(infoSink, "Contradictory layout max_vertices values");
+ else if (language == EShLangTessControl)
+ error(infoSink, "Contradictory layout vertices values");
+ else
+ assert(0);
+ }
+ if (primitives == TQualifier::layoutNotSet)
+ primitives = unit.primitives;
+ else if (primitives != unit.primitives) {
+ if (language == EShLangMeshNV)
+ error(infoSink, "Contradictory layout max_primitives values");
+ else
+ assert(0);
+ }
+
+ if (inputPrimitive == ElgNone)
+ inputPrimitive = unit.inputPrimitive;
+ else if (inputPrimitive != unit.inputPrimitive)
+ error(infoSink, "Contradictory input layout primitives");
+
+ if (outputPrimitive == ElgNone)
+ outputPrimitive = unit.outputPrimitive;
+ else if (outputPrimitive != unit.outputPrimitive)
+ error(infoSink, "Contradictory output layout primitives");
+
+ if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
+ error(infoSink, "gl_FragCoord redeclarations must match across shaders");
+
+ if (vertexSpacing == EvsNone)
+ vertexSpacing = unit.vertexSpacing;
+ else if (vertexSpacing != unit.vertexSpacing)
+ error(infoSink, "Contradictory input vertex spacing");
+
+ if (vertexOrder == EvoNone)
+ vertexOrder = unit.vertexOrder;
+ else if (vertexOrder != unit.vertexOrder)
+ error(infoSink, "Contradictory triangle ordering");
+
+ MERGE_TRUE(pointMode);
+
+ for (int i = 0; i < 3; ++i) {
+ if (!localSizeNotDefault[i] && unit.localSizeNotDefault[i]) {
+ localSize[i] = unit.localSize[i];
+ localSizeNotDefault[i] = true;
+ }
+ else if (localSize[i] != unit.localSize[i])
+ error(infoSink, "Contradictory local size");
+
+ if (localSizeSpecId[i] == TQualifier::layoutNotSet)
+ localSizeSpecId[i] = unit.localSizeSpecId[i];
+ else if (localSizeSpecId[i] != unit.localSizeSpecId[i])
+ error(infoSink, "Contradictory local size specialization ids");
+ }
+
+ MERGE_TRUE(earlyFragmentTests);
+ MERGE_TRUE(postDepthCoverage);
+
+ if (depthLayout == EldNone)
+ depthLayout = unit.depthLayout;
+ else if (depthLayout != unit.depthLayout)
+ error(infoSink, "Contradictory depth layouts");
+
+ MERGE_TRUE(depthReplacing);
+ MERGE_TRUE(hlslFunctionality1);
+
+ blendEquations |= unit.blendEquations;
+
+ MERGE_TRUE(xfbMode);
+
+ for (size_t b = 0; b < xfbBuffers.size(); ++b) {
+ if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd)
+ xfbBuffers[b].stride = unit.xfbBuffers[b].stride;
+ else if (xfbBuffers[b].stride != unit.xfbBuffers[b].stride)
+ error(infoSink, "Contradictory xfb_stride");
+ xfbBuffers[b].implicitStride = std::max(xfbBuffers[b].implicitStride, unit.xfbBuffers[b].implicitStride);
+ if (unit.xfbBuffers[b].contains64BitType)
+ xfbBuffers[b].contains64BitType = true;
+ if (unit.xfbBuffers[b].contains32BitType)
+ xfbBuffers[b].contains32BitType = true;
+ if (unit.xfbBuffers[b].contains16BitType)
+ xfbBuffers[b].contains16BitType = true;
+ // TODO: 4.4 link: enhanced layouts: compare ranges
+ }
+
+ MERGE_TRUE(multiStream);
+ MERGE_TRUE(layoutOverrideCoverage);
+ MERGE_TRUE(geoPassthroughEXT);
+
+ for (unsigned int i = 0; i < unit.shiftBinding.size(); ++i) {
+ if (unit.shiftBinding[i] > 0)
+ setShiftBinding((TResourceType)i, unit.shiftBinding[i]);
+ }
+
+ for (unsigned int i = 0; i < unit.shiftBindingForSet.size(); ++i) {
+ for (auto it = unit.shiftBindingForSet[i].begin(); it != unit.shiftBindingForSet[i].end(); ++it)
+ setShiftBindingForSet((TResourceType)i, it->second, it->first);
+ }
+
+ resourceSetBinding.insert(resourceSetBinding.end(), unit.resourceSetBinding.begin(), unit.resourceSetBinding.end());
+
+ MERGE_TRUE(autoMapBindings);
+ MERGE_TRUE(autoMapLocations);
+ MERGE_TRUE(invertY);
+ MERGE_TRUE(flattenUniformArrays);
+ MERGE_TRUE(useUnknownFormat);
+ MERGE_TRUE(hlslOffsets);
+ MERGE_TRUE(useStorageBuffer);
+ MERGE_TRUE(hlslIoMapping);
+
+ // TODO: sourceFile
+ // TODO: sourceText
+ // TODO: processes
+
+ MERGE_TRUE(needToLegalize);
+ MERGE_TRUE(binaryDoubleOutput);
+ MERGE_TRUE(usePhysicalStorageBuffer);
+}
+
+//
+// Merge the 'unit' AST into 'this' AST.
+// That includes rationalizing the unique IDs, which were set up independently,
+// and might have overlaps that are not the same symbol, or might have different
+// IDs for what should be the same shared symbol.
+//
+void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
+{
+ if (unit.treeRoot == nullptr)
+ return;
+
+ if (treeRoot == nullptr) {
+ treeRoot = unit.treeRoot;
+ return;
+ }
+
+ // Getting this far means we have two existing trees to merge...
+ numShaderRecordNVBlocks += unit.numShaderRecordNVBlocks;
+ numTaskNVBlocks += unit.numTaskNVBlocks;
+
+ // Get the top-level globals of each unit
+ TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
+ TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence();
+
+ // Get the linker-object lists
+ TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
+ const TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence();
+
+ // Map by global name to unique ID to rationalize the same object having
+ // differing IDs in different trees.
+ TMap<TString, int> idMap;
+ int maxId;
+ seedIdMap(idMap, maxId);
+ remapIds(idMap, maxId + 1, unit);
+
+ mergeBodies(infoSink, globals, unitGlobals);
+ mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
+ ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
+}
+
+#endif
+
+// Traverser that seeds an ID map with all built-ins, and tracks the
+// maximum ID used.
+// (It would be nice to put this in a function, but that causes warnings
+// on having no bodies for the copy-constructor/operator=.)
+class TBuiltInIdTraverser : public TIntermTraverser {
+public:
+ TBuiltInIdTraverser(TMap<TString, int>& idMap) : idMap(idMap), maxId(0) { }
+ // If it's a built in, add it to the map.
+ // Track the max ID.
+ virtual void visitSymbol(TIntermSymbol* symbol)
+ {
+ const TQualifier& qualifier = symbol->getType().getQualifier();
+ if (qualifier.builtIn != EbvNone)
+ idMap[symbol->getName()] = symbol->getId();
+ maxId = std::max(maxId, symbol->getId());
+ }
+ int getMaxId() const { return maxId; }
+protected:
+ TBuiltInIdTraverser(TBuiltInIdTraverser&);
+ TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
+ TMap<TString, int>& idMap;
+ int maxId;
+};
+
+// Traverser that seeds an ID map with non-builtins.
+// (It would be nice to put this in a function, but that causes warnings
+// on having no bodies for the copy-constructor/operator=.)
+class TUserIdTraverser : public TIntermTraverser {
+public:
+ TUserIdTraverser(TMap<TString, int>& idMap) : idMap(idMap) { }
+ // If its a non-built-in global, add it to the map.
+ virtual void visitSymbol(TIntermSymbol* symbol)
+ {
+ const TQualifier& qualifier = symbol->getType().getQualifier();
+ if (qualifier.builtIn == EbvNone)
+ idMap[symbol->getName()] = symbol->getId();
+ }
+
+protected:
+ TUserIdTraverser(TUserIdTraverser&);
+ TUserIdTraverser& operator=(TUserIdTraverser&);
+ TMap<TString, int>& idMap; // over biggest id
+};
+
+// Initialize the the ID map with what we know of 'this' AST.
+void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId)
+{
+ // all built-ins everywhere need to align on IDs and contribute to the max ID
+ TBuiltInIdTraverser builtInIdTraverser(idMap);
+ treeRoot->traverse(&builtInIdTraverser);
+ maxId = builtInIdTraverser.getMaxId();
+
+ // user variables in the linker object list need to align on ids
+ TUserIdTraverser userIdTraverser(idMap);
+ findLinkerObjects()->traverse(&userIdTraverser);
+}
+
+// Traverser to map an AST ID to what was known from the seeding AST.
+// (It would be nice to put this in a function, but that causes warnings
+// on having no bodies for the copy-constructor/operator=.)
+class TRemapIdTraverser : public TIntermTraverser {
+public:
+ TRemapIdTraverser(const TMap<TString, int>& idMap, int idShift) : idMap(idMap), idShift(idShift) { }
+ // Do the mapping:
+ // - if the same symbol, adopt the 'this' ID
+ // - otherwise, ensure a unique ID by shifting to a new space
+ virtual void visitSymbol(TIntermSymbol* symbol)
+ {
+ const TQualifier& qualifier = symbol->getType().getQualifier();
+ bool remapped = false;
+ if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) {
+ auto it = idMap.find(symbol->getName());
+ if (it != idMap.end()) {
+ symbol->changeId(it->second);
+ remapped = true;
+ }
+ }
+ if (!remapped)
+ symbol->changeId(symbol->getId() + idShift);
+ }
+protected:
+ TRemapIdTraverser(TRemapIdTraverser&);
+ TRemapIdTraverser& operator=(TRemapIdTraverser&);
+ const TMap<TString, int>& idMap;
+ int idShift;
+};
+
+void TIntermediate::remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate& unit)
+{
+ // Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
+ TRemapIdTraverser idTraverser(idMap, idShift);
+ unit.getTreeRoot()->traverse(&idTraverser);
+}
+
+//
+// Merge the function bodies and global-level initializers from unitGlobals into globals.
+// Will error check duplication of function bodies for the same signature.
+//
+void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, const TIntermSequence& unitGlobals)
+{
+ // TODO: link-time performance: Processing in alphabetical order will be faster
+
+ // Error check the global objects, not including the linker objects
+ for (unsigned int child = 0; child < globals.size() - 1; ++child) {
+ for (unsigned int unitChild = 0; unitChild < unitGlobals.size() - 1; ++unitChild) {
+ TIntermAggregate* body = globals[child]->getAsAggregate();
+ TIntermAggregate* unitBody = unitGlobals[unitChild]->getAsAggregate();
+ if (body && unitBody && body->getOp() == EOpFunction && unitBody->getOp() == EOpFunction && body->getName() == unitBody->getName()) {
+ error(infoSink, "Multiple function bodies in multiple compilation units for the same signature in the same stage:");
+ infoSink.info << " " << globals[child]->getAsAggregate()->getName() << "\n";
+ }
+ }
+ }
+
+ // Merge the global objects, just in front of the linker objects
+ globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1);
+}
+
+//
+// Merge the linker objects from unitLinkerObjects into linkerObjects.
+// Duplication is expected and filtered out, but contradictions are an error.
+//
+void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects)
+{
+ // Error check and merge the linker objects (duplicates should not be created)
+ std::size_t initialNumLinkerObjects = linkerObjects.size();
+ for (unsigned int unitLinkObj = 0; unitLinkObj < unitLinkerObjects.size(); ++unitLinkObj) {
+ bool merge = true;
+ for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) {
+ TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
+ TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
+ assert(symbol && unitSymbol);
+ if (symbol->getName() == unitSymbol->getName()) {
+ // filter out copy
+ merge = false;
+
+ // but if one has an initializer and the other does not, update
+ // the initializer
+ if (symbol->getConstArray().empty() && ! unitSymbol->getConstArray().empty())
+ symbol->setConstArray(unitSymbol->getConstArray());
+
+ // Similarly for binding
+ if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding())
+ symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding;
+
+ // Update implicit array sizes
+ mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType());
+
+ // Check for consistent types/qualification/initializers etc.
+ mergeErrorCheck(infoSink, *symbol, *unitSymbol, false);
+ }
+ }
+ if (merge)
+ linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
+ }
+}
+
+// TODO 4.5 link functionality: cull distance array size checking
+
+// Recursively merge the implicit array sizes through the objects' respective type trees.
+void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType)
+{
+ if (type.isUnsizedArray()) {
+ if (unitType.isUnsizedArray()) {
+ type.updateImplicitArraySize(unitType.getImplicitArraySize());
+ if (unitType.isArrayVariablyIndexed())
+ type.setArrayVariablyIndexed();
+ } else if (unitType.isSizedArray())
+ type.changeOuterArraySize(unitType.getOuterArraySize());
+ }
+
+ // Type mismatches are caught and reported after this, just be careful for now.
+ if (! type.isStruct() || ! unitType.isStruct() || type.getStruct()->size() != unitType.getStruct()->size())
+ return;
+
+ for (int i = 0; i < (int)type.getStruct()->size(); ++i)
+ mergeImplicitArraySizes(*(*type.getStruct())[i].type, *(*unitType.getStruct())[i].type);
+}
+
+//
+// Compare two global objects from two compilation units and see if they match
+// well enough. Rules can be different for intra- vs. cross-stage matching.
+//
+// This function only does one of intra- or cross-stage matching per call.
+//
+void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage)
+{
+#ifndef GLSLANG_WEB
+ bool writeTypeComparison = false;
+
+ // Types have to match
+ if (symbol.getType() != unitSymbol.getType()) {
+ // but, we make an exception if one is an implicit array and the other is sized
+ if (! (symbol.getType().isArray() && unitSymbol.getType().isArray() &&
+ symbol.getType().sameElementType(unitSymbol.getType()) &&
+ (symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()))) {
+ error(infoSink, "Types must match:");
+ writeTypeComparison = true;
+ }
+ }
+
+ // Qualifiers have to (almost) match
+
+ // Storage...
+ if (symbol.getQualifier().storage != unitSymbol.getQualifier().storage) {
+ error(infoSink, "Storage qualifiers must match:");
+ writeTypeComparison = true;
+ }
+
+ // Precision...
+ if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
+ error(infoSink, "Precision qualifiers must match:");
+ writeTypeComparison = true;
+ }
+
+ // Invariance...
+ if (! crossStage && symbol.getQualifier().invariant != unitSymbol.getQualifier().invariant) {
+ error(infoSink, "Presence of invariant qualifier must match:");
+ writeTypeComparison = true;
+ }
+
+ // Precise...
+ if (! crossStage && symbol.getQualifier().isNoContraction() != unitSymbol.getQualifier().isNoContraction()) {
+ error(infoSink, "Presence of precise qualifier must match:");
+ writeTypeComparison = true;
+ }
+
+ // Auxiliary and interpolation...
+ if (symbol.getQualifier().centroid != unitSymbol.getQualifier().centroid ||
+ symbol.getQualifier().smooth != unitSymbol.getQualifier().smooth ||
+ symbol.getQualifier().flat != unitSymbol.getQualifier().flat ||
+ symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() ||
+ symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() ||
+ symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective()) {
+ error(infoSink, "Interpolation and auxiliary storage qualifiers must match:");
+ writeTypeComparison = true;
+ }
+
+ // Memory...
+ if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent ||
+ symbol.getQualifier().devicecoherent != unitSymbol.getQualifier().devicecoherent ||
+ symbol.getQualifier().queuefamilycoherent != unitSymbol.getQualifier().queuefamilycoherent ||
+ symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent ||
+ symbol.getQualifier().subgroupcoherent != unitSymbol.getQualifier().subgroupcoherent ||
+ symbol.getQualifier().nonprivate != unitSymbol.getQualifier().nonprivate ||
+ symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil ||
+ symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict ||
+ symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly ||
+ symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) {
+ error(infoSink, "Memory qualifiers must match:");
+ writeTypeComparison = true;
+ }
+
+ // Layouts...
+ // TODO: 4.4 enhanced layouts: Generalize to include offset/align: current spec
+ // requires separate user-supplied offset from actual computed offset, but
+ // current implementation only has one offset.
+ if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix ||
+ symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking ||
+ symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation ||
+ symbol.getQualifier().layoutComponent != unitSymbol.getQualifier().layoutComponent ||
+ symbol.getQualifier().layoutIndex != unitSymbol.getQualifier().layoutIndex ||
+ symbol.getQualifier().layoutBinding != unitSymbol.getQualifier().layoutBinding ||
+ (symbol.getQualifier().hasBinding() && (symbol.getQualifier().layoutOffset != unitSymbol.getQualifier().layoutOffset))) {
+ error(infoSink, "Layout qualification must match:");
+ writeTypeComparison = true;
+ }
+
+ // Initializers have to match, if both are present, and if we don't already know the types don't match
+ if (! writeTypeComparison) {
+ if (! symbol.getConstArray().empty() && ! unitSymbol.getConstArray().empty()) {
+ if (symbol.getConstArray() != unitSymbol.getConstArray()) {
+ error(infoSink, "Initializers must match:");
+ infoSink.info << " " << symbol.getName() << "\n";
+ }
+ }
+ }
+
+ if (writeTypeComparison)
+ infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus \"" <<
+ unitSymbol.getType().getCompleteString() << "\"\n";
+#endif
+}
+
+//
+// Do final link-time error checking of a complete (merged) intermediate representation.
+// (Much error checking was done during merging).
+//
+// Also, lock in defaults of things not set, including array sizes.
+//
+void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
+{
+ if (getTreeRoot() == nullptr)
+ return;
+
+ if (numEntryPoints < 1) {
+ if (getSource() == EShSourceGlsl)
+ error(infoSink, "Missing entry point: Each stage requires one entry point");
+ else
+ warn(infoSink, "Entry point not found");
+ }
+
+ // recursion and missing body checking
+ checkCallGraphCycles(infoSink);
+ checkCallGraphBodies(infoSink, keepUncalled);
+
+ // overlap/alias/missing I/O, etc.
+ inOutLocationCheck(infoSink);
+
+#ifndef GLSLANG_WEB
+ if (getNumPushConstants() > 1)
+ error(infoSink, "Only one push_constant block is allowed per stage");
+
+ // invocations
+ if (invocations == TQualifier::layoutNotSet)
+ invocations = 1;
+
+ if (inIoAccessed("gl_ClipDistance") && inIoAccessed("gl_ClipVertex"))
+ error(infoSink, "Can only use one of gl_ClipDistance or gl_ClipVertex (gl_ClipDistance is preferred)");
+ if (inIoAccessed("gl_CullDistance") && inIoAccessed("gl_ClipVertex"))
+ error(infoSink, "Can only use one of gl_CullDistance or gl_ClipVertex (gl_ClipDistance is preferred)");
+
+ if (userOutputUsed() && (inIoAccessed("gl_FragColor") || inIoAccessed("gl_FragData")))
+ error(infoSink, "Cannot use gl_FragColor or gl_FragData when using user-defined outputs");
+ if (inIoAccessed("gl_FragColor") && inIoAccessed("gl_FragData"))
+ error(infoSink, "Cannot use both gl_FragColor and gl_FragData");
+
+ for (size_t b = 0; b < xfbBuffers.size(); ++b) {
+ if (xfbBuffers[b].contains64BitType)
+ RoundToPow2(xfbBuffers[b].implicitStride, 8);
+ else if (xfbBuffers[b].contains32BitType)
+ RoundToPow2(xfbBuffers[b].implicitStride, 4);
+ else if (xfbBuffers[b].contains16BitType)
+ RoundToPow2(xfbBuffers[b].implicitStride, 2);
+
+ // "It is a compile-time or link-time error to have
+ // any xfb_offset that overflows xfb_stride, whether stated on declarations before or after the xfb_stride, or
+ // in different compilation units. While xfb_stride can be declared multiple times for the same buffer, it is a
+ // compile-time or link-time error to have different values specified for the stride for the same buffer."
+ if (xfbBuffers[b].stride != TQualifier::layoutXfbStrideEnd && xfbBuffers[b].implicitStride > xfbBuffers[b].stride) {
+ error(infoSink, "xfb_stride is too small to hold all buffer entries:");
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << ", minimum stride needed: " << xfbBuffers[b].implicitStride << "\n";
+ }
+ if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd)
+ xfbBuffers[b].stride = xfbBuffers[b].implicitStride;
+
+ // "If the buffer is capturing any
+ // outputs with double-precision or 64-bit integer components, the stride must be a multiple of 8, otherwise it must be a
+ // multiple of 4, or a compile-time or link-time error results."
+ if (xfbBuffers[b].contains64BitType && ! IsMultipleOfPow2(xfbBuffers[b].stride, 8)) {
+ error(infoSink, "xfb_stride must be multiple of 8 for buffer holding a double or 64-bit integer:");
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n";
+ } else if (xfbBuffers[b].contains32BitType && ! IsMultipleOfPow2(xfbBuffers[b].stride, 4)) {
+ error(infoSink, "xfb_stride must be multiple of 4:");
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n";
+ }
+ // "If the buffer is capturing any
+ // outputs with half-precision or 16-bit integer components, the stride must be a multiple of 2"
+ else if (xfbBuffers[b].contains16BitType && ! IsMultipleOfPow2(xfbBuffers[b].stride, 2)) {
+ error(infoSink, "xfb_stride must be multiple of 2 for buffer holding a half float or 16-bit integer:");
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n";
+ }
+
+ // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the
+ // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents."
+ if (xfbBuffers[b].stride > (unsigned int)(4 * resources.maxTransformFeedbackInterleavedComponents)) {
+ error(infoSink, "xfb_stride is too large:");
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << " xfb_buffer " << (unsigned int)b << ", components (1/4 stride) needed are " << xfbBuffers[b].stride/4 << ", gl_MaxTransformFeedbackInterleavedComponents is " << resources.maxTransformFeedbackInterleavedComponents << "\n";
+ }
+ }
+
+ switch (language) {
+ case EShLangVertex:
+ break;
+ case EShLangTessControl:
+ if (vertices == TQualifier::layoutNotSet)
+ error(infoSink, "At least one shader must specify an output layout(vertices=...)");
+ break;
+ case EShLangTessEvaluation:
+ if (getSource() == EShSourceGlsl) {
+ if (inputPrimitive == ElgNone)
+ error(infoSink, "At least one shader must specify an input layout primitive");
+ if (vertexSpacing == EvsNone)
+ vertexSpacing = EvsEqual;
+ if (vertexOrder == EvoNone)
+ vertexOrder = EvoCcw;
+ }
+ break;
+ case EShLangGeometry:
+ if (inputPrimitive == ElgNone)
+ error(infoSink, "At least one shader must specify an input layout primitive");
+ if (outputPrimitive == ElgNone)
+ error(infoSink, "At least one shader must specify an output layout primitive");
+ if (vertices == TQualifier::layoutNotSet)
+ error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
+ break;
+ case EShLangFragment:
+ // for GL_ARB_post_depth_coverage, EarlyFragmentTest is set automatically in
+ // ParseHelper.cpp. So if we reach here, this must be GL_EXT_post_depth_coverage
+ // requiring explicit early_fragment_tests
+ if (getPostDepthCoverage() && !getEarlyFragmentTests())
+ error(infoSink, "post_depth_coverage requires early_fragment_tests");
+ break;
+ case EShLangCompute:
+ break;
+ case EShLangRayGenNV:
+ case EShLangIntersectNV:
+ case EShLangAnyHitNV:
+ case EShLangClosestHitNV:
+ case EShLangMissNV:
+ case EShLangCallableNV:
+ if (numShaderRecordNVBlocks > 1)
+ error(infoSink, "Only one shaderRecordNV buffer block is allowed per stage");
+ break;
+ case EShLangMeshNV:
+ // NV_mesh_shader doesn't allow use of both single-view and per-view builtins.
+ if (inIoAccessed("gl_Position") && inIoAccessed("gl_PositionPerViewNV"))
+ error(infoSink, "Can only use one of gl_Position or gl_PositionPerViewNV");
+ if (inIoAccessed("gl_ClipDistance") && inIoAccessed("gl_ClipDistancePerViewNV"))
+ error(infoSink, "Can only use one of gl_ClipDistance or gl_ClipDistancePerViewNV");
+ if (inIoAccessed("gl_CullDistance") && inIoAccessed("gl_CullDistancePerViewNV"))
+ error(infoSink, "Can only use one of gl_CullDistance or gl_CullDistancePerViewNV");
+ if (inIoAccessed("gl_Layer") && inIoAccessed("gl_LayerPerViewNV"))
+ error(infoSink, "Can only use one of gl_Layer or gl_LayerPerViewNV");
+ if (inIoAccessed("gl_ViewportMask") && inIoAccessed("gl_ViewportMaskPerViewNV"))
+ error(infoSink, "Can only use one of gl_ViewportMask or gl_ViewportMaskPerViewNV");
+ if (outputPrimitive == ElgNone)
+ error(infoSink, "At least one shader must specify an output layout primitive");
+ if (vertices == TQualifier::layoutNotSet)
+ error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
+ if (primitives == TQualifier::layoutNotSet)
+ error(infoSink, "At least one shader must specify a layout(max_primitives = value)");
+ // fall through
+ case EShLangTaskNV:
+ if (numTaskNVBlocks > 1)
+ error(infoSink, "Only one taskNV interface block is allowed per shader");
+ break;
+ default:
+ error(infoSink, "Unknown Stage.");
+ break;
+ }
+
+ // Process the tree for any node-specific work.
+ class TFinalLinkTraverser : public TIntermTraverser {
+ public:
+ TFinalLinkTraverser() { }
+ virtual ~TFinalLinkTraverser() { }
+
+ virtual void visitSymbol(TIntermSymbol* symbol)
+ {
+ // Implicitly size arrays.
+ // If an unsized array is left as unsized, it effectively
+ // becomes run-time sized.
+ symbol->getWritableType().adoptImplicitArraySizes(false);
+ }
+ } finalLinkTraverser;
+
+ treeRoot->traverse(&finalLinkTraverser);
+#endif
+}
+
+//
+// See if the call graph contains any static recursion, which is disallowed
+// by the specification.
+//
+void TIntermediate::checkCallGraphCycles(TInfoSink& infoSink)
+{
+ // Clear fields we'll use for this.
+ for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
+ call->visited = false;
+ call->currentPath = false;
+ call->errorGiven = false;
+ }
+
+ //
+ // Loop, looking for a new connected subgraph. One subgraph is handled per loop iteration.
+ //
+
+ TCall* newRoot;
+ do {
+ // See if we have unvisited parts of the graph.
+ newRoot = 0;
+ for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
+ if (! call->visited) {
+ newRoot = &(*call);
+ break;
+ }
+ }
+
+ // If not, we are done.
+ if (! newRoot)
+ break;
+
+ // Otherwise, we found a new subgraph, process it:
+ // See what all can be reached by this new root, and if any of
+ // that is recursive. This is done by depth-first traversals, seeing
+ // if a new call is found that was already in the currentPath (a back edge),
+ // thereby detecting recursion.
+ std::list<TCall*> stack;
+ newRoot->currentPath = true; // currentPath will be true iff it is on the stack
+ stack.push_back(newRoot);
+ while (! stack.empty()) {
+ // get a caller
+ TCall* call = stack.back();
+
+ // Add to the stack just one callee.
+ // This algorithm always terminates, because only !visited and !currentPath causes a push
+ // and all pushes change currentPath to true, and all pops change visited to true.
+ TGraph::iterator child = callGraph.begin();
+ for (; child != callGraph.end(); ++child) {
+
+ // If we already visited this node, its whole subgraph has already been processed, so skip it.
+ if (child->visited)
+ continue;
+
+ if (call->callee == child->caller) {
+ if (child->currentPath) {
+ // Then, we found a back edge
+ if (! child->errorGiven) {
+ error(infoSink, "Recursion detected:");
+ infoSink.info << " " << call->callee << " calling " << child->callee << "\n";
+ child->errorGiven = true;
+ recursive = true;
+ }
+ } else {
+ child->currentPath = true;
+ stack.push_back(&(*child));
+ break;
+ }
+ }
+ }
+ if (child == callGraph.end()) {
+ // no more callees, we bottomed out, never look at this node again
+ stack.back()->currentPath = false;
+ stack.back()->visited = true;
+ stack.pop_back();
+ }
+ } // end while, meaning nothing left to process in this subtree
+
+ } while (newRoot); // redundant loop check; should always exit via the 'break' above
+}
+
+//
+// See which functions are reachable from the entry point and which have bodies.
+// Reachable ones with missing bodies are errors.
+// Unreachable bodies are dead code.
+//
+void TIntermediate::checkCallGraphBodies(TInfoSink& infoSink, bool keepUncalled)
+{
+ // Clear fields we'll use for this.
+ for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
+ call->visited = false;
+ call->calleeBodyPosition = -1;
+ }
+
+ // The top level of the AST includes function definitions (bodies).
+ // Compare these to function calls in the call graph.
+ // We'll end up knowing which have bodies, and if so,
+ // how to map the call-graph node to the location in the AST.
+ TIntermSequence &functionSequence = getTreeRoot()->getAsAggregate()->getSequence();
+ std::vector<bool> reachable(functionSequence.size(), true); // so that non-functions are reachable
+ for (int f = 0; f < (int)functionSequence.size(); ++f) {
+ glslang::TIntermAggregate* node = functionSequence[f]->getAsAggregate();
+ if (node && (node->getOp() == glslang::EOpFunction)) {
+ if (node->getName().compare(getEntryPointMangledName().c_str()) != 0)
+ reachable[f] = false; // so that function bodies are unreachable, until proven otherwise
+ for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
+ if (call->callee == node->getName())
+ call->calleeBodyPosition = f;
+ }
+ }
+ }
+
+ // Start call-graph traversal by visiting the entry point nodes.
+ for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
+ if (call->caller.compare(getEntryPointMangledName().c_str()) == 0)
+ call->visited = true;
+ }
+
+ // Propagate 'visited' through the call-graph to every part of the graph it
+ // can reach (seeded with the entry-point setting above).
+ bool changed;
+ do {
+ changed = false;
+ for (auto call1 = callGraph.begin(); call1 != callGraph.end(); ++call1) {
+ if (call1->visited) {
+ for (TGraph::iterator call2 = callGraph.begin(); call2 != callGraph.end(); ++call2) {
+ if (! call2->visited) {
+ if (call1->callee == call2->caller) {
+ changed = true;
+ call2->visited = true;
+ }
+ }
+ }
+ }
+ }
+ } while (changed);
+
+ // Any call-graph node set to visited but without a callee body is an error.
+ for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
+ if (call->visited) {
+ if (call->calleeBodyPosition == -1) {
+ error(infoSink, "No function definition (body) found: ");
+ infoSink.info << " " << call->callee << "\n";
+ } else
+ reachable[call->calleeBodyPosition] = true;
+ }
+ }
+
+ // Bodies in the AST not reached by the call graph are dead;
+ // clear them out, since they can't be reached and also can't
+ // be translated further due to possibility of being ill defined.
+ if (! keepUncalled) {
+ for (int f = 0; f < (int)functionSequence.size(); ++f) {
+ if (! reachable[f])
+ functionSequence[f] = nullptr;
+ }
+ functionSequence.erase(std::remove(functionSequence.begin(), functionSequence.end(), nullptr), functionSequence.end());
+ }
+}
+
+//
+// Satisfy rules for location qualifiers on inputs and outputs
+//
+void TIntermediate::inOutLocationCheck(TInfoSink& infoSink)
+{
+ // ES 3.0 requires all outputs to have location qualifiers if there is more than one output
+ bool fragOutWithNoLocation = false;
+ int numFragOut = 0;
+
+ // TODO: linker functionality: location collision checking
+
+ TIntermSequence& linkObjects = findLinkerObjects()->getSequence();
+ for (size_t i = 0; i < linkObjects.size(); ++i) {
+ const TType& type = linkObjects[i]->getAsTyped()->getType();
+ const TQualifier& qualifier = type.getQualifier();
+ if (language == EShLangFragment) {
+ if (qualifier.storage == EvqVaryingOut && qualifier.builtIn == EbvNone) {
+ ++numFragOut;
+ if (!qualifier.hasAnyLocation())
+ fragOutWithNoLocation = true;
+ }
+ }
+ }
+
+ if (isEsProfile()) {
+ if (numFragOut > 1 && fragOutWithNoLocation)
+ error(infoSink, "when more than one fragment shader output, all must have location qualifiers");
+ }
+}
+
+TIntermAggregate* TIntermediate::findLinkerObjects() const
+{
+ // Get the top-level globals
+ TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
+
+ // Get the last member of the sequences, expected to be the linker-object lists
+ assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects);
+
+ return globals.back()->getAsAggregate();
+}
+
+// See if a variable was both a user-declared output and used.
+// Note: the spec discusses writing to one, but this looks at read or write, which
+// is more useful, and perhaps the spec should be changed to reflect that.
+bool TIntermediate::userOutputUsed() const
+{
+ const TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
+
+ bool found = false;
+ for (size_t i = 0; i < linkerObjects.size(); ++i) {
+ const TIntermSymbol& symbolNode = *linkerObjects[i]->getAsSymbolNode();
+ if (symbolNode.getQualifier().storage == EvqVaryingOut &&
+ symbolNode.getName().compare(0, 3, "gl_") != 0 &&
+ inIoAccessed(symbolNode.getName())) {
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+}
+
+// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions
+// as the accumulation is done.
+//
+// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
+//
+// typeCollision is set to true if there is no direct collision, but the types in the same location
+// are different.
+//
+int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& type, bool& typeCollision)
+{
+ typeCollision = false;
+
+ int set;
+ if (qualifier.isPipeInput())
+ set = 0;
+ else if (qualifier.isPipeOutput())
+ set = 1;
+ else if (qualifier.storage == EvqUniform)
+ set = 2;
+ else if (qualifier.storage == EvqBuffer)
+ set = 3;
+ else
+ return -1;
+
+ int size;
+ if (qualifier.isUniformOrBuffer() || qualifier.isTaskMemory()) {
+ if (type.isSizedArray())
+ size = type.getCumulativeArraySize();
+ else
+ size = 1;
+ } else {
+ // Strip off the outer array dimension for those having an extra one.
+ if (type.isArray() && qualifier.isArrayedIo(language)) {
+ TType elementType(type, 0);
+ size = computeTypeLocationSize(elementType, language);
+ } else
+ size = computeTypeLocationSize(type, language);
+ }
+
+ // Locations, and components within locations.
+ //
+ // Almost always, dealing with components means a single location is involved.
+ // The exception is a dvec3. From the spec:
+ //
+ // "A dvec3 will consume all four components of the first location and components 0 and 1 of
+ // the second location. This leaves components 2 and 3 available for other component-qualified
+ // declarations."
+ //
+ // That means, without ever mentioning a component, a component range
+ // for a different location gets specified, if it's not a vertex shader input. (!)
+ // (A vertex shader input will show using only one location, even for a dvec3/4.)
+ //
+ // So, for the case of dvec3, we need two independent ioRanges.
+
+ int collision = -1; // no collision
+#ifndef GLSLANG_WEB
+ if (size == 2 && type.getBasicType() == EbtDouble && type.getVectorSize() == 3 &&
+ (qualifier.isPipeInput() || qualifier.isPipeOutput())) {
+ // Dealing with dvec3 in/out split across two locations.
+ // Need two io-ranges.
+ // The case where the dvec3 doesn't start at component 0 was previously caught as overflow.
+
+ // First range:
+ TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation);
+ TRange componentRange(0, 3);
+ TIoRange range(locationRange, componentRange, type.getBasicType(), 0);
+
+ // check for collisions
+ collision = checkLocationRange(set, range, type, typeCollision);
+ if (collision < 0) {
+ usedIo[set].push_back(range);
+
+ // Second range:
+ TRange locationRange2(qualifier.layoutLocation + 1, qualifier.layoutLocation + 1);
+ TRange componentRange2(0, 1);
+ TIoRange range2(locationRange2, componentRange2, type.getBasicType(), 0);
+
+ // check for collisions
+ collision = checkLocationRange(set, range2, type, typeCollision);
+ if (collision < 0)
+ usedIo[set].push_back(range2);
+ }
+ } else
+#endif
+ {
+ // Not a dvec3 in/out split across two locations, generic path.
+ // Need a single IO-range block.
+
+ TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation + size - 1);
+ TRange componentRange(0, 3);
+ if (qualifier.hasComponent() || type.getVectorSize() > 0) {
+ int consumedComponents = type.getVectorSize() * (type.getBasicType() == EbtDouble ? 2 : 1);
+ if (qualifier.hasComponent())
+ componentRange.start = qualifier.layoutComponent;
+ componentRange.last = componentRange.start + consumedComponents - 1;
+ }
+
+ // combine location and component ranges
+ TIoRange range(locationRange, componentRange, type.getBasicType(), qualifier.hasIndex() ? qualifier.getIndex() : 0);
+
+ // check for collisions, except for vertex inputs on desktop targeting OpenGL
+ if (! (!isEsProfile() && language == EShLangVertex && qualifier.isPipeInput()) || spvVersion.vulkan > 0)
+ collision = checkLocationRange(set, range, type, typeCollision);
+
+ if (collision < 0)
+ usedIo[set].push_back(range);
+ }
+
+ return collision;
+}
+
+// Compare a new (the passed in) 'range' against the existing set, and see
+// if there are any collisions.
+//
+// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
+//
+int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TType& type, bool& typeCollision)
+{
+ for (size_t r = 0; r < usedIo[set].size(); ++r) {
+ if (range.overlap(usedIo[set][r])) {
+ // there is a collision; pick one
+ return std::max(range.location.start, usedIo[set][r].location.start);
+ } else if (range.location.overlap(usedIo[set][r].location) && type.getBasicType() != usedIo[set][r].basicType) {
+ // aliased-type mismatch
+ typeCollision = true;
+ return std::max(range.location.start, usedIo[set][r].location.start);
+ }
+ }
+
+ return -1; // no collision
+}
+
+// Accumulate bindings and offsets, and check for collisions
+// as the accumulation is done.
+//
+// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
+//
+int TIntermediate::addUsedOffsets(int binding, int offset, int numOffsets)
+{
+ TRange bindingRange(binding, binding);
+ TRange offsetRange(offset, offset + numOffsets - 1);
+ TOffsetRange range(bindingRange, offsetRange);
+
+ // check for collisions, except for vertex inputs on desktop
+ for (size_t r = 0; r < usedAtomics.size(); ++r) {
+ if (range.overlap(usedAtomics[r])) {
+ // there is a collision; pick one
+ return std::max(offset, usedAtomics[r].offset.start);
+ }
+ }
+
+ usedAtomics.push_back(range);
+
+ return -1; // no collision
+}
+
+// Accumulate used constant_id values.
+//
+// Return false is one was already used.
+bool TIntermediate::addUsedConstantId(int id)
+{
+ if (usedConstantId.find(id) != usedConstantId.end())
+ return false;
+
+ usedConstantId.insert(id);
+
+ return true;
+}
+
+// Recursively figure out how many locations are used up by an input or output type.
+// Return the size of type, as measured by "locations".
+int TIntermediate::computeTypeLocationSize(const TType& type, EShLanguage stage)
+{
+ // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n
+ // consecutive locations..."
+ if (type.isArray()) {
+ // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
+ // TODO: are there valid cases of having an unsized array with a location? If so, running this code too early.
+ TType elementType(type, 0);
+ if (type.isSizedArray() && !type.getQualifier().isPerView())
+ return type.getOuterArraySize() * computeTypeLocationSize(elementType, stage);
+ else {
+#ifndef GLSLANG_WEB
+ // unset perViewNV attributes for arrayed per-view outputs: "perviewNV vec4 v[MAX_VIEWS][3];"
+ elementType.getQualifier().perViewNV = false;
+#endif
+ return computeTypeLocationSize(elementType, stage);
+ }
+ }
+
+ // "The locations consumed by block and structure members are determined by applying the rules above
+ // recursively..."
+ if (type.isStruct()) {
+ int size = 0;
+ for (int member = 0; member < (int)type.getStruct()->size(); ++member) {
+ TType memberType(type, member);
+ size += computeTypeLocationSize(memberType, stage);
+ }
+ return size;
+ }
+
+ // ES: "If a shader input is any scalar or vector type, it will consume a single location."
+
+ // Desktop: "If a vertex shader input is any scalar or vector type, it will consume a single location. If a non-vertex
+ // shader input is a scalar or vector type other than dvec3 or dvec4, it will consume a single location, while
+ // types dvec3 or dvec4 will consume two consecutive locations. Inputs of type double and dvec2 will
+ // consume only a single location, in all stages."
+ if (type.isScalar())
+ return 1;
+ if (type.isVector()) {
+ if (stage == EShLangVertex && type.getQualifier().isPipeInput())
+ return 1;
+ if (type.getBasicType() == EbtDouble && type.getVectorSize() > 2)
+ return 2;
+ else
+ return 1;
+ }
+
+ // "If the declared input is an n x m single- or double-precision matrix, ...
+ // The number of locations assigned for each matrix will be the same as
+ // for an n-element array of m-component vectors..."
+ if (type.isMatrix()) {
+ TType columnType(type, 0);
+ return type.getMatrixCols() * computeTypeLocationSize(columnType, stage);
+ }
+
+ assert(0);
+ return 1;
+}
+
+// Same as computeTypeLocationSize but for uniforms
+int TIntermediate::computeTypeUniformLocationSize(const TType& type)
+{
+ // "Individual elements of a uniform array are assigned
+ // consecutive locations with the first element taking location
+ // location."
+ if (type.isArray()) {
+ // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
+ TType elementType(type, 0);
+ if (type.isSizedArray()) {
+ return type.getOuterArraySize() * computeTypeUniformLocationSize(elementType);
+ } else {
+ // TODO: are there valid cases of having an implicitly-sized array with a location? If so, running this code too early.
+ return computeTypeUniformLocationSize(elementType);
+ }
+ }
+
+ // "Each subsequent inner-most member or element gets incremental
+ // locations for the entire structure or array."
+ if (type.isStruct()) {
+ int size = 0;
+ for (int member = 0; member < (int)type.getStruct()->size(); ++member) {
+ TType memberType(type, member);
+ size += computeTypeUniformLocationSize(memberType);
+ }
+ return size;
+ }
+
+ return 1;
+}
+
+#ifndef GLSLANG_WEB
+
+// Accumulate xfb buffer ranges and check for collisions as the accumulation is done.
+//
+// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
+//
+int TIntermediate::addXfbBufferOffset(const TType& type)
+{
+ const TQualifier& qualifier = type.getQualifier();
+
+ assert(qualifier.hasXfbOffset() && qualifier.hasXfbBuffer());
+ TXfbBuffer& buffer = xfbBuffers[qualifier.layoutXfbBuffer];
+
+ // compute the range
+ unsigned int size = computeTypeXfbSize(type, buffer.contains64BitType, buffer.contains32BitType, buffer.contains16BitType);
+ buffer.implicitStride = std::max(buffer.implicitStride, qualifier.layoutXfbOffset + size);
+ TRange range(qualifier.layoutXfbOffset, qualifier.layoutXfbOffset + size - 1);
+
+ // check for collisions
+ for (size_t r = 0; r < buffer.ranges.size(); ++r) {
+ if (range.overlap(buffer.ranges[r])) {
+ // there is a collision; pick an example to return
+ return std::max(range.start, buffer.ranges[r].start);
+ }
+ }
+
+ buffer.ranges.push_back(range);
+
+ return -1; // no collision
+}
+
+// Recursively figure out how many bytes of xfb buffer are used by the given type.
+// Return the size of type, in bytes.
+// Sets contains64BitType to true if the type contains a 64-bit data type.
+// Sets contains32BitType to true if the type contains a 32-bit data type.
+// Sets contains16BitType to true if the type contains a 16-bit data type.
+// N.B. Caller must set contains64BitType, contains32BitType, and contains16BitType to false before calling.
+unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const
+{
+ // "...if applied to an aggregate containing a double or 64-bit integer, the offset must also be a multiple of 8,
+ // and the space taken in the buffer will be a multiple of 8.
+ // ...within the qualified entity, subsequent components are each
+ // assigned, in order, to the next available offset aligned to a multiple of
+ // that component's size. Aggregate types are flattened down to the component
+ // level to get this sequence of components."
+
+ if (type.isArray()) {
+ // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
+ assert(type.isSizedArray());
+ TType elementType(type, 0);
+ return type.getOuterArraySize() * computeTypeXfbSize(elementType, contains64BitType, contains16BitType, contains16BitType);
+ }
+
+ if (type.isStruct()) {
+ unsigned int size = 0;
+ bool structContains64BitType = false;
+ bool structContains32BitType = false;
+ bool structContains16BitType = false;
+ for (int member = 0; member < (int)type.getStruct()->size(); ++member) {
+ TType memberType(type, member);
+ // "... if applied to
+ // an aggregate containing a double or 64-bit integer, the offset must also be a multiple of 8,
+ // and the space taken in the buffer will be a multiple of 8."
+ bool memberContains64BitType = false;
+ bool memberContains32BitType = false;
+ bool memberContains16BitType = false;
+ int memberSize = computeTypeXfbSize(memberType, memberContains64BitType, memberContains32BitType, memberContains16BitType);
+ if (memberContains64BitType) {
+ structContains64BitType = true;
+ RoundToPow2(size, 8);
+ } else if (memberContains32BitType) {
+ structContains32BitType = true;
+ RoundToPow2(size, 4);
+ } else if (memberContains16BitType) {
+ structContains16BitType = true;
+ RoundToPow2(size, 2);
+ }
+ size += memberSize;
+ }
+
+ if (structContains64BitType) {
+ contains64BitType = true;
+ RoundToPow2(size, 8);
+ } else if (structContains32BitType) {
+ contains32BitType = true;
+ RoundToPow2(size, 4);
+ } else if (structContains16BitType) {
+ contains16BitType = true;
+ RoundToPow2(size, 2);
+ }
+ return size;
+ }
+
+ int numComponents;
+ if (type.isScalar())
+ numComponents = 1;
+ else if (type.isVector())
+ numComponents = type.getVectorSize();
+ else if (type.isMatrix())
+ numComponents = type.getMatrixCols() * type.getMatrixRows();
+ else {
+ assert(0);
+ numComponents = 1;
+ }
+
+ if (type.getBasicType() == EbtDouble || type.getBasicType() == EbtInt64 || type.getBasicType() == EbtUint64) {
+ contains64BitType = true;
+ return 8 * numComponents;
+ } else if (type.getBasicType() == EbtFloat16 || type.getBasicType() == EbtInt16 || type.getBasicType() == EbtUint16) {
+ contains16BitType = true;
+ return 2 * numComponents;
+ } else if (type.getBasicType() == EbtInt8 || type.getBasicType() == EbtUint8)
+ return numComponents;
+ else {
+ contains32BitType = true;
+ return 4 * numComponents;
+ }
+}
+
+#endif
+
+const int baseAlignmentVec4Std140 = 16;
+
+// Return the size and alignment of a component of the given type.
+// The size is returned in the 'size' parameter
+// Return value is the alignment..
+int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
+{
+#ifdef GLSLANG_WEB
+ size = 4; return 4;
+#endif
+
+ switch (type.getBasicType()) {
+ case EbtInt64:
+ case EbtUint64:
+ case EbtDouble: size = 8; return 8;
+ case EbtFloat16: size = 2; return 2;
+ case EbtInt8:
+ case EbtUint8: size = 1; return 1;
+ case EbtInt16:
+ case EbtUint16: size = 2; return 2;
+ case EbtReference: size = 8; return 8;
+ default: size = 4; return 4;
+ }
+}
+
+// Implement base-alignment and size rules from section 7.6.2.2 Standard Uniform Block Layout
+// Operates recursively.
+//
+// If std140 is true, it does the rounding up to vec4 size required by std140,
+// otherwise it does not, yielding std430 rules.
+//
+// The size is returned in the 'size' parameter
+//
+// The stride is only non-0 for arrays or matrices, and is the stride of the
+// top-level object nested within the type. E.g., for an array of matrices,
+// it is the distances needed between matrices, despite the rules saying the
+// stride comes from the flattening down to vectors.
+//
+// Return value is the alignment of the type.
+int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor)
+{
+ int alignment;
+
+ bool std140 = layoutPacking == glslang::ElpStd140;
+ // When using the std140 storage layout, structures will be laid out in buffer
+ // storage with its members stored in monotonically increasing order based on their
+ // location in the declaration. A structure and each structure member have a base
+ // offset and a base alignment, from which an aligned offset is computed by rounding
+ // the base offset up to a multiple of the base alignment. The base offset of the first
+ // member of a structure is taken from the aligned offset of the structure itself. The
+ // base offset of all other structure members is derived by taking the offset of the
+ // last basic machine unit consumed by the previous member and adding one. Each
+ // structure member is stored in memory at its aligned offset. The members of a top-
+ // level uniform block are laid out in buffer storage by treating the uniform block as
+ // a structure with a base offset of zero.
+ //
+ // 1. If the member is a scalar consuming N basic machine units, the base alignment is N.
+ //
+ // 2. If the member is a two- or four-component vector with components consuming N basic
+ // machine units, the base alignment is 2N or 4N, respectively.
+ //
+ // 3. If the member is a three-component vector with components consuming N
+ // basic machine units, the base alignment is 4N.
+ //
+ // 4. If the member is an array of scalars or vectors, the base alignment and array
+ // stride are set to match the base alignment of a single array element, according
+ // to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The
+ // array may have padding at the end; the base offset of the member following
+ // the array is rounded up to the next multiple of the base alignment.
+ //
+ // 5. If the member is a column-major matrix with C columns and R rows, the
+ // matrix is stored identically to an array of C column vectors with R
+ // components each, according to rule (4).
+ //
+ // 6. If the member is an array of S column-major matrices with C columns and
+ // R rows, the matrix is stored identically to a row of S X C column vectors
+ // with R components each, according to rule (4).
+ //
+ // 7. If the member is a row-major matrix with C columns and R rows, the matrix
+ // is stored identically to an array of R row vectors with C components each,
+ // according to rule (4).
+ //
+ // 8. If the member is an array of S row-major matrices with C columns and R
+ // rows, the matrix is stored identically to a row of S X R row vectors with C
+ // components each, according to rule (4).
+ //
+ // 9. If the member is a structure, the base alignment of the structure is N , where
+ // N is the largest base alignment value of any of its members, and rounded
+ // up to the base alignment of a vec4. The individual members of this substructure
+ // are then assigned offsets by applying this set of rules recursively,
+ // where the base offset of the first member of the sub-structure is equal to the
+ // aligned offset of the structure. The structure may have padding at the end;
+ // the base offset of the member following the sub-structure is rounded up to
+ // the next multiple of the base alignment of the structure.
+ //
+ // 10. If the member is an array of S structures, the S elements of the array are laid
+ // out in order, according to rule (9).
+ //
+ // Assuming, for rule 10: The stride is the same as the size of an element.
+
+ stride = 0;
+ int dummyStride;
+
+ // rules 4, 6, 8, and 10
+ if (type.isArray()) {
+ // TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
+ TType derefType(type, 0);
+ alignment = getBaseAlignment(derefType, size, dummyStride, layoutPacking, rowMajor);
+ if (std140)
+ alignment = std::max(baseAlignmentVec4Std140, alignment);
+ RoundToPow2(size, alignment);
+ stride = size; // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected)
+ // uses the assumption for rule 10 in the comment above
+ size = stride * type.getOuterArraySize();
+ return alignment;
+ }
+
+ // rule 9
+ if (type.getBasicType() == EbtStruct) {
+ const TTypeList& memberList = *type.getStruct();
+
+ size = 0;
+ int maxAlignment = std140 ? baseAlignmentVec4Std140 : 0;
+ for (size_t m = 0; m < memberList.size(); ++m) {
+ int memberSize;
+ // modify just the children's view of matrix layout, if there is one for this member
+ TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
+ int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, layoutPacking,
+ (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
+ maxAlignment = std::max(maxAlignment, memberAlignment);
+ RoundToPow2(size, memberAlignment);
+ size += memberSize;
+ }
+
+ // The structure may have padding at the end; the base offset of
+ // the member following the sub-structure is rounded up to the next
+ // multiple of the base alignment of the structure.
+ RoundToPow2(size, maxAlignment);
+
+ return maxAlignment;
+ }
+
+ // rule 1
+ if (type.isScalar())
+ return getBaseAlignmentScalar(type, size);
+
+ // rules 2 and 3
+ if (type.isVector()) {
+ int scalarAlign = getBaseAlignmentScalar(type, size);
+ switch (type.getVectorSize()) {
+ case 1: // HLSL has this, GLSL does not
+ return scalarAlign;
+ case 2:
+ size *= 2;
+ return 2 * scalarAlign;
+ default:
+ size *= type.getVectorSize();
+ return 4 * scalarAlign;
+ }
+ }
+
+ // rules 5 and 7
+ if (type.isMatrix()) {
+ // rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows
+ TType derefType(type, 0, rowMajor);
+
+ alignment = getBaseAlignment(derefType, size, dummyStride, layoutPacking, rowMajor);
+ if (std140)
+ alignment = std::max(baseAlignmentVec4Std140, alignment);
+ RoundToPow2(size, alignment);
+ stride = size; // use intra-matrix stride for stride of a just a matrix
+ if (rowMajor)
+ size = stride * type.getMatrixRows();
+ else
+ size = stride * type.getMatrixCols();
+
+ return alignment;
+ }
+
+ assert(0); // all cases should be covered above
+ size = baseAlignmentVec4Std140;
+ return baseAlignmentVec4Std140;
+}
+
+// To aid the basic HLSL rule about crossing vec4 boundaries.
+bool TIntermediate::improperStraddle(const TType& type, int size, int offset)
+{
+ if (! type.isVector() || type.isArray())
+ return false;
+
+ return size <= 16 ? offset / 16 != (offset + size - 1) / 16
+ : offset % 16 != 0;
+}
+
+int TIntermediate::getScalarAlignment(const TType& type, int& size, int& stride, bool rowMajor)
+{
+ int alignment;
+
+ stride = 0;
+ int dummyStride;
+
+ if (type.isArray()) {
+ TType derefType(type, 0);
+ alignment = getScalarAlignment(derefType, size, dummyStride, rowMajor);
+
+ stride = size;
+ RoundToPow2(stride, alignment);
+
+ size = stride * (type.getOuterArraySize() - 1) + size;
+ return alignment;
+ }
+
+ if (type.getBasicType() == EbtStruct) {
+ const TTypeList& memberList = *type.getStruct();
+
+ size = 0;
+ int maxAlignment = 0;
+ for (size_t m = 0; m < memberList.size(); ++m) {
+ int memberSize;
+ // modify just the children's view of matrix layout, if there is one for this member
+ TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
+ int memberAlignment = getScalarAlignment(*memberList[m].type, memberSize, dummyStride,
+ (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
+ maxAlignment = std::max(maxAlignment, memberAlignment);
+ RoundToPow2(size, memberAlignment);
+ size += memberSize;
+ }
+
+ return maxAlignment;
+ }
+
+ if (type.isScalar())
+ return getBaseAlignmentScalar(type, size);
+
+ if (type.isVector()) {
+ int scalarAlign = getBaseAlignmentScalar(type, size);
+
+ size *= type.getVectorSize();
+ return scalarAlign;
+ }
+
+ if (type.isMatrix()) {
+ TType derefType(type, 0, rowMajor);
+
+ alignment = getScalarAlignment(derefType, size, dummyStride, rowMajor);
+
+ stride = size; // use intra-matrix stride for stride of a just a matrix
+ if (rowMajor)
+ size = stride * type.getMatrixRows();
+ else
+ size = stride * type.getMatrixCols();
+
+ return alignment;
+ }
+
+ assert(0); // all cases should be covered above
+ size = 1;
+ return 1;
+}
+
+int TIntermediate::getMemberAlignment(const TType& type, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor)
+{
+ if (layoutPacking == glslang::ElpScalar) {
+ return getScalarAlignment(type, size, stride, rowMajor);
+ } else {
+ return getBaseAlignment(type, size, stride, layoutPacking, rowMajor);
+ }
+}
+
+// shared calculation by getOffset and getOffsets
+void TIntermediate::updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize)
+{
+ int dummyStride;
+
+ // modify just the children's view of matrix layout, if there is one for this member
+ TLayoutMatrix subMatrixLayout = memberType.getQualifier().layoutMatrix;
+ int memberAlignment = getMemberAlignment(memberType, memberSize, dummyStride,
+ parentType.getQualifier().layoutPacking,
+ subMatrixLayout != ElmNone
+ ? subMatrixLayout == ElmRowMajor
+ : parentType.getQualifier().layoutMatrix == ElmRowMajor);
+ RoundToPow2(offset, memberAlignment);
+}
+
+// Lookup or calculate the offset of a block member, using the recursively
+// defined block offset rules.
+int TIntermediate::getOffset(const TType& type, int index)
+{
+ const TTypeList& memberList = *type.getStruct();
+
+ // Don't calculate offset if one is present, it could be user supplied
+ // and different than what would be calculated. That is, this is faster,
+ // but not just an optimization.
+ if (memberList[index].type->getQualifier().hasOffset())
+ return memberList[index].type->getQualifier().layoutOffset;
+
+ int memberSize = 0;
+ int offset = 0;
+ for (int m = 0; m <= index; ++m) {
+ updateOffset(type, *memberList[m].type, offset, memberSize);
+
+ if (m < index)
+ offset += memberSize;
+ }
+
+ return offset;
+}
+
+// Calculate the block data size.
+// Block arrayness is not taken into account, each element is backed by a separate buffer.
+int TIntermediate::getBlockSize(const TType& blockType)
+{
+ const TTypeList& memberList = *blockType.getStruct();
+ int lastIndex = (int)memberList.size() - 1;
+ int lastOffset = getOffset(blockType, lastIndex);
+
+ int lastMemberSize;
+ int dummyStride;
+ getMemberAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride,
+ blockType.getQualifier().layoutPacking,
+ blockType.getQualifier().layoutMatrix == ElmRowMajor);
+
+ return lastOffset + lastMemberSize;
+}
+
+int TIntermediate::computeBufferReferenceTypeSize(const TType& type)
+{
+ assert(type.isReference());
+ int size = getBlockSize(*type.getReferentType());
+
+ int align = type.getBufferReferenceAlignment();
+
+ if (align) {
+ size = (size + align - 1) & ~(align-1);
+ }
+
+ return size;
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/localintermediate.h b/thirdparty/glslang/glslang/MachineIndependent/localintermediate.h
new file mode 100644
index 0000000000..683290af74
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/localintermediate.h
@@ -0,0 +1,1001 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2016 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _LOCAL_INTERMEDIATE_INCLUDED_
+#define _LOCAL_INTERMEDIATE_INCLUDED_
+
+#include "../Include/intermediate.h"
+#include "../Public/ShaderLang.h"
+#include "Versions.h"
+
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <set>
+#include <array>
+
+class TInfoSink;
+
+namespace glslang {
+
+struct TMatrixSelector {
+ int coord1; // stay agnostic about column/row; this is parse order
+ int coord2;
+};
+
+typedef int TVectorSelector;
+
+const int MaxSwizzleSelectors = 4;
+
+template<typename selectorType>
+class TSwizzleSelectors {
+public:
+ TSwizzleSelectors() : size_(0) { }
+
+ void push_back(selectorType comp)
+ {
+ if (size_ < MaxSwizzleSelectors)
+ components[size_++] = comp;
+ }
+ void resize(int s)
+ {
+ assert(s <= size_);
+ size_ = s;
+ }
+ int size() const { return size_; }
+ selectorType operator[](int i) const
+ {
+ assert(i < MaxSwizzleSelectors);
+ return components[i];
+ }
+
+private:
+ int size_;
+ selectorType components[MaxSwizzleSelectors];
+};
+
+//
+// Some helper structures for TIntermediate. Their contents are encapsulated
+// by TIntermediate.
+//
+
+// Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies.
+// A "call" is a pair: <caller, callee>.
+// There can be duplicates. General assumption is the list is small.
+struct TCall {
+ TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { }
+ TString caller;
+ TString callee;
+ bool visited;
+ bool currentPath;
+ bool errorGiven;
+ int calleeBodyPosition;
+};
+
+// A generic 1-D range.
+struct TRange {
+ TRange(int start, int last) : start(start), last(last) { }
+ bool overlap(const TRange& rhs) const
+ {
+ return last >= rhs.start && start <= rhs.last;
+ }
+ int start;
+ int last;
+};
+
+// An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying
+// within the same location range, component range, and index value. Locations don't alias unless
+// all other dimensions of their range overlap.
+struct TIoRange {
+ TIoRange(TRange location, TRange component, TBasicType basicType, int index)
+ : location(location), component(component), basicType(basicType), index(index) { }
+ bool overlap(const TIoRange& rhs) const
+ {
+ return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
+ }
+ TRange location;
+ TRange component;
+ TBasicType basicType;
+ int index;
+};
+
+// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying
+// within the same binding and offset range.
+struct TOffsetRange {
+ TOffsetRange(TRange binding, TRange offset)
+ : binding(binding), offset(offset) { }
+ bool overlap(const TOffsetRange& rhs) const
+ {
+ return binding.overlap(rhs.binding) && offset.overlap(rhs.offset);
+ }
+ TRange binding;
+ TRange offset;
+};
+
+#ifndef GLSLANG_WEB
+// Things that need to be tracked per xfb buffer.
+struct TXfbBuffer {
+ TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false),
+ contains32BitType(false), contains16BitType(false) { }
+ std::vector<TRange> ranges; // byte offsets that have already been assigned
+ unsigned int stride;
+ unsigned int implicitStride;
+ bool contains64BitType;
+ bool contains32BitType;
+ bool contains16BitType;
+};
+#endif
+
+// Track a set of strings describing how the module was processed.
+// Using the form:
+// process arg0 arg1 arg2 ...
+// process arg0 arg1 arg2 ...
+// where everything is textual, and there can be zero or more arguments
+class TProcesses {
+public:
+ TProcesses() {}
+ ~TProcesses() {}
+
+ void addProcess(const char* process)
+ {
+ processes.push_back(process);
+ }
+ void addProcess(const std::string& process)
+ {
+ processes.push_back(process);
+ }
+ void addArgument(int arg)
+ {
+ processes.back().append(" ");
+ std::string argString = std::to_string(arg);
+ processes.back().append(argString);
+ }
+ void addArgument(const char* arg)
+ {
+ processes.back().append(" ");
+ processes.back().append(arg);
+ }
+ void addArgument(const std::string& arg)
+ {
+ processes.back().append(" ");
+ processes.back().append(arg);
+ }
+ void addIfNonZero(const char* process, int value)
+ {
+ if (value != 0) {
+ addProcess(process);
+ addArgument(value);
+ }
+ }
+
+ const std::vector<std::string>& getProcesses() const { return processes; }
+
+private:
+ std::vector<std::string> processes;
+};
+
+class TSymbolTable;
+class TSymbol;
+class TVariable;
+
+//
+// Texture and Sampler transformation mode.
+//
+enum ComputeDerivativeMode {
+ LayoutDerivativeNone, // default layout as SPV_NV_compute_shader_derivatives not enabled
+ LayoutDerivativeGroupQuads, // derivative_group_quadsNV
+ LayoutDerivativeGroupLinear, // derivative_group_linearNV
+};
+
+//
+// Set of helper functions to help parse and build the tree.
+//
+class TIntermediate {
+public:
+ explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
+ language(l),
+ profile(p), version(v), treeRoot(0),
+ numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
+ invertY(false),
+ useStorageBuffer(false),
+ nanMinMaxClamp(false),
+ depthReplacing(false)
+#ifndef GLSLANG_WEB
+ ,
+ implicitThisName("@this"), implicitCounterName("@count"),
+ source(EShSourceNone),
+ useVulkanMemoryModel(false),
+ invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
+ inputPrimitive(ElgNone), outputPrimitive(ElgNone),
+ pixelCenterInteger(false), originUpperLeft(false),
+ vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
+ postDepthCoverage(false), depthLayout(EldNone),
+ hlslFunctionality1(false),
+ blendEquations(0), xfbMode(false), multiStream(false),
+ layoutOverrideCoverage(false),
+ geoPassthroughEXT(false),
+ numShaderRecordNVBlocks(0),
+ computeDerivativeMode(LayoutDerivativeNone),
+ primitives(TQualifier::layoutNotSet),
+ numTaskNVBlocks(0),
+ autoMapBindings(false),
+ autoMapLocations(false),
+ flattenUniformArrays(false),
+ useUnknownFormat(false),
+ hlslOffsets(false),
+ hlslIoMapping(false),
+ useVariablePointers(false),
+ textureSamplerTransformMode(EShTexSampTransKeep),
+ needToLegalize(false),
+ binaryDoubleOutput(false),
+ usePhysicalStorageBuffer(false),
+ uniformLocationBase(0)
+#endif
+ {
+ localSize[0] = 1;
+ localSize[1] = 1;
+ localSize[2] = 1;
+ localSizeNotDefault[0] = false;
+ localSizeNotDefault[1] = false;
+ localSizeNotDefault[2] = false;
+ localSizeSpecId[0] = TQualifier::layoutNotSet;
+ localSizeSpecId[1] = TQualifier::layoutNotSet;
+ localSizeSpecId[2] = TQualifier::layoutNotSet;
+#ifndef GLSLANG_WEB
+ xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
+ shiftBinding.fill(0);
+#endif
+ }
+
+ void setVersion(int v) { version = v; }
+ int getVersion() const { return version; }
+ void setProfile(EProfile p) { profile = p; }
+ EProfile getProfile() const { return profile; }
+ void setSpv(const SpvVersion& s)
+ {
+ spvVersion = s;
+
+ // client processes
+ if (spvVersion.vulkan > 0)
+ processes.addProcess("client vulkan100");
+ if (spvVersion.openGl > 0)
+ processes.addProcess("client opengl100");
+
+ // target SPV
+ switch (spvVersion.spv) {
+ case 0:
+ break;
+ case EShTargetSpv_1_0:
+ break;
+ case EShTargetSpv_1_1:
+ processes.addProcess("target-env spirv1.1");
+ break;
+ case EShTargetSpv_1_2:
+ processes.addProcess("target-env spirv1.2");
+ break;
+ case EShTargetSpv_1_3:
+ processes.addProcess("target-env spirv1.3");
+ break;
+ case EShTargetSpv_1_4:
+ processes.addProcess("target-env spirv1.4");
+ break;
+ case EShTargetSpv_1_5:
+ processes.addProcess("target-env spirv1.5");
+ break;
+ default:
+ processes.addProcess("target-env spirvUnknown");
+ break;
+ }
+
+ // target-environment processes
+ switch (spvVersion.vulkan) {
+ case 0:
+ break;
+ case EShTargetVulkan_1_0:
+ processes.addProcess("target-env vulkan1.0");
+ break;
+ case EShTargetVulkan_1_1:
+ processes.addProcess("target-env vulkan1.1");
+ break;
+ case EShTargetVulkan_1_2:
+ processes.addProcess("target-env vulkan1.2");
+ break;
+ default:
+ processes.addProcess("target-env vulkanUnknown");
+ break;
+ }
+ if (spvVersion.openGl > 0)
+ processes.addProcess("target-env opengl");
+ }
+ const SpvVersion& getSpv() const { return spvVersion; }
+ EShLanguage getStage() const { return language; }
+ void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
+ const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
+
+ void setTreeRoot(TIntermNode* r) { treeRoot = r; }
+ TIntermNode* getTreeRoot() const { return treeRoot; }
+ void incrementEntryPointCount() { ++numEntryPoints; }
+ int getNumEntryPoints() const { return numEntryPoints; }
+ int getNumErrors() const { return numErrors; }
+ void addPushConstantCount() { ++numPushConstants; }
+ void setLimits(const TBuiltInResource& r) { resources = r; }
+
+ bool postProcess(TIntermNode*, EShLanguage);
+ void removeTree();
+
+ void setEntryPointName(const char* ep)
+ {
+ entryPointName = ep;
+ processes.addProcess("entry-point");
+ processes.addArgument(entryPointName);
+ }
+ void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; }
+ const std::string& getEntryPointName() const { return entryPointName; }
+ const std::string& getEntryPointMangledName() const { return entryPointMangledName; }
+
+ void setInvertY(bool invert)
+ {
+ invertY = invert;
+ if (invertY)
+ processes.addProcess("invert-y");
+ }
+ bool getInvertY() const { return invertY; }
+
+#ifdef ENABLE_HLSL
+ void setSource(EShSource s) { source = s; }
+ EShSource getSource() const { return source; }
+#else
+ void setSource(EShSource s) { assert(s == EShSourceGlsl); }
+ EShSource getSource() const { return EShSourceGlsl; }
+#endif
+
+ bool isRecursive() const { return recursive; }
+
+ TIntermSymbol* addSymbol(const TVariable&);
+ TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
+ TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
+ TIntermSymbol* addSymbol(const TIntermSymbol&);
+ TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
+ std::tuple<TIntermTyped*, TIntermTyped*> addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
+ TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
+ TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
+ void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
+ TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
+ TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+ TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+ TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
+ TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
+ TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
+ bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
+ bool isIntegralPromotion(TBasicType from, TBasicType to) const;
+ bool isFPPromotion(TBasicType from, TBasicType to) const;
+ bool isIntegralConversion(TBasicType from, TBasicType to) const;
+ bool isFPConversion(TBasicType from, TBasicType to) const;
+ bool isFPIntegralConversion(TBasicType from, TBasicType to) const;
+ TOperator mapTypeToConstructorOp(const TType&) const;
+ TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
+ TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
+ TIntermAggregate* makeAggregate(TIntermNode* node);
+ TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
+ TIntermAggregate* makeAggregate(const TSourceLoc&);
+ TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
+ bool areAllChildConst(TIntermAggregate* aggrNode);
+ TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
+ TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
+ TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
+ TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
+ TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
+ TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
+ bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
+ TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
+ TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst,
+ const TSourceLoc&, TIntermLoop*&);
+ TIntermBranch* addBranch(TOperator, const TSourceLoc&);
+ TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
+ template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
+
+ // Low level functions to add nodes (no conversions or other higher level transformations)
+ // If a type is provided, the node's type will be set to it.
+ TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const;
+ TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const;
+ TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const;
+ TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const;
+
+ // Constant folding (in Constant.cpp)
+ TIntermTyped* fold(TIntermAggregate* aggrNode);
+ TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
+ TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&);
+ TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& fields, const TSourceLoc&);
+
+ // Tree ops
+ static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay);
+
+ // Linkage related
+ void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
+ void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
+
+ void setUseStorageBuffer()
+ {
+ useStorageBuffer = true;
+ processes.addProcess("use-storage-buffer");
+ }
+ bool usingStorageBuffer() const { return useStorageBuffer; }
+ void setDepthReplacing() { depthReplacing = true; }
+ bool isDepthReplacing() const { return depthReplacing; }
+ bool setLocalSize(int dim, int size)
+ {
+ if (localSizeNotDefault[dim])
+ return size == localSize[dim];
+ localSizeNotDefault[dim] = true;
+ localSize[dim] = size;
+ return true;
+ }
+ unsigned int getLocalSize(int dim) const { return localSize[dim]; }
+ bool setLocalSizeSpecId(int dim, int id)
+ {
+ if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
+ return id == localSizeSpecId[dim];
+ localSizeSpecId[dim] = id;
+ return true;
+ }
+ int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
+#ifdef GLSLANG_WEB
+ void output(TInfoSink&, bool tree) { }
+
+ bool isEsProfile() const { return false; }
+ bool getXfbMode() const { return false; }
+ bool isMultiStream() const { return false; }
+ TLayoutGeometry getOutputPrimitive() const { return ElgNone; }
+ bool getPostDepthCoverage() const { return false; }
+ bool getEarlyFragmentTests() const { return false; }
+ TLayoutDepth getDepth() const { return EldNone; }
+ bool getPixelCenterInteger() const { return false; }
+ void setOriginUpperLeft() { }
+ bool getOriginUpperLeft() const { return true; }
+ TInterlockOrdering getInterlockOrdering() const { return EioNone; }
+
+ bool getAutoMapBindings() const { return false; }
+ bool getAutoMapLocations() const { return false; }
+ int getNumPushConstants() const { return 0; }
+ void addShaderRecordNVCount() { }
+ void addTaskNVCount() { }
+ void setUseVulkanMemoryModel() { }
+ bool usingVulkanMemoryModel() const { return false; }
+ bool usingPhysicalStorageBuffer() const { return false; }
+ bool usingVariablePointers() const { return false; }
+ unsigned getXfbStride(int buffer) const { return 0; }
+ bool hasLayoutDerivativeModeNone() const { return false; }
+ ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; }
+#else
+ void output(TInfoSink&, bool tree);
+
+ bool isEsProfile() const { return profile == EEsProfile; }
+
+ void setShiftBinding(TResourceType res, unsigned int shift)
+ {
+ shiftBinding[res] = shift;
+
+ const char* name = getResourceName(res);
+ if (name != nullptr)
+ processes.addIfNonZero(name, shift);
+ }
+
+ unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; }
+
+ void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set)
+ {
+ if (shift == 0) // ignore if there's no shift: it's a no-op.
+ return;
+
+ shiftBindingForSet[res][set] = shift;
+
+ const char* name = getResourceName(res);
+ if (name != nullptr) {
+ processes.addProcess(name);
+ processes.addArgument(shift);
+ processes.addArgument(set);
+ }
+ }
+
+ int getShiftBindingForSet(TResourceType res, unsigned int set) const
+ {
+ const auto shift = shiftBindingForSet[res].find(set);
+ return shift == shiftBindingForSet[res].end() ? -1 : shift->second;
+ }
+ bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); }
+
+ void setResourceSetBinding(const std::vector<std::string>& shift)
+ {
+ resourceSetBinding = shift;
+ if (shift.size() > 0) {
+ processes.addProcess("resource-set-binding");
+ for (int s = 0; s < (int)shift.size(); ++s)
+ processes.addArgument(shift[s]);
+ }
+ }
+ const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
+ void setAutoMapBindings(bool map)
+ {
+ autoMapBindings = map;
+ if (autoMapBindings)
+ processes.addProcess("auto-map-bindings");
+ }
+ bool getAutoMapBindings() const { return autoMapBindings; }
+ void setAutoMapLocations(bool map)
+ {
+ autoMapLocations = map;
+ if (autoMapLocations)
+ processes.addProcess("auto-map-locations");
+ }
+ bool getAutoMapLocations() const { return autoMapLocations; }
+
+#ifdef ENABLE_HLSL
+ void setFlattenUniformArrays(bool flatten)
+ {
+ flattenUniformArrays = flatten;
+ if (flattenUniformArrays)
+ processes.addProcess("flatten-uniform-arrays");
+ }
+ bool getFlattenUniformArrays() const { return flattenUniformArrays; }
+#endif
+ void setNoStorageFormat(bool b)
+ {
+ useUnknownFormat = b;
+ if (useUnknownFormat)
+ processes.addProcess("no-storage-format");
+ }
+ bool getNoStorageFormat() const { return useUnknownFormat; }
+ void setUseVulkanMemoryModel()
+ {
+ useVulkanMemoryModel = true;
+ processes.addProcess("use-vulkan-memory-model");
+ }
+ bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; }
+ void setUsePhysicalStorageBuffer()
+ {
+ usePhysicalStorageBuffer = true;
+ }
+ bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; }
+ void setUseVariablePointers()
+ {
+ useVariablePointers = true;
+ processes.addProcess("use-variable-pointers");
+ }
+ bool usingVariablePointers() const { return useVariablePointers; }
+
+#ifdef ENABLE_HLSL
+ template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; }
+ bool hasCounterBufferName(const TString& name) const {
+ size_t len = strlen(implicitCounterName);
+ return name.size() > len &&
+ name.compare(name.size() - len, len, implicitCounterName) == 0;
+ }
+#endif
+
+ void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
+ int getNumPushConstants() const { return numPushConstants; }
+ void addShaderRecordNVCount() { ++numShaderRecordNVBlocks; }
+ void addTaskNVCount() { ++numTaskNVBlocks; }
+
+ bool setInvocations(int i)
+ {
+ if (invocations != TQualifier::layoutNotSet)
+ return invocations == i;
+ invocations = i;
+ return true;
+ }
+ int getInvocations() const { return invocations; }
+ bool setVertices(int m)
+ {
+ if (vertices != TQualifier::layoutNotSet)
+ return vertices == m;
+ vertices = m;
+ return true;
+ }
+ int getVertices() const { return vertices; }
+ bool setInputPrimitive(TLayoutGeometry p)
+ {
+ if (inputPrimitive != ElgNone)
+ return inputPrimitive == p;
+ inputPrimitive = p;
+ return true;
+ }
+ TLayoutGeometry getInputPrimitive() const { return inputPrimitive; }
+ bool setVertexSpacing(TVertexSpacing s)
+ {
+ if (vertexSpacing != EvsNone)
+ return vertexSpacing == s;
+ vertexSpacing = s;
+ return true;
+ }
+ TVertexSpacing getVertexSpacing() const { return vertexSpacing; }
+ bool setVertexOrder(TVertexOrder o)
+ {
+ if (vertexOrder != EvoNone)
+ return vertexOrder == o;
+ vertexOrder = o;
+ return true;
+ }
+ TVertexOrder getVertexOrder() const { return vertexOrder; }
+ void setPointMode() { pointMode = true; }
+ bool getPointMode() const { return pointMode; }
+
+ bool setInterlockOrdering(TInterlockOrdering o)
+ {
+ if (interlockOrdering != EioNone)
+ return interlockOrdering == o;
+ interlockOrdering = o;
+ return true;
+ }
+ TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; }
+
+ void setXfbMode() { xfbMode = true; }
+ bool getXfbMode() const { return xfbMode; }
+ void setMultiStream() { multiStream = true; }
+ bool isMultiStream() const { return multiStream; }
+ bool setOutputPrimitive(TLayoutGeometry p)
+ {
+ if (outputPrimitive != ElgNone)
+ return outputPrimitive == p;
+ outputPrimitive = p;
+ return true;
+ }
+ TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; }
+ void setPostDepthCoverage() { postDepthCoverage = true; }
+ bool getPostDepthCoverage() const { return postDepthCoverage; }
+ void setEarlyFragmentTests() { earlyFragmentTests = true; }
+ bool getEarlyFragmentTests() const { return earlyFragmentTests; }
+ bool setDepth(TLayoutDepth d)
+ {
+ if (depthLayout != EldNone)
+ return depthLayout == d;
+ depthLayout = d;
+ return true;
+ }
+ TLayoutDepth getDepth() const { return depthLayout; }
+ void setOriginUpperLeft() { originUpperLeft = true; }
+ bool getOriginUpperLeft() const { return originUpperLeft; }
+ void setPixelCenterInteger() { pixelCenterInteger = true; }
+ bool getPixelCenterInteger() const { return pixelCenterInteger; }
+ void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
+ unsigned int getBlendEquations() const { return blendEquations; }
+ bool setXfbBufferStride(int buffer, unsigned stride)
+ {
+ if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd)
+ return xfbBuffers[buffer].stride == stride;
+ xfbBuffers[buffer].stride = stride;
+ return true;
+ }
+ unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; }
+ int addXfbBufferOffset(const TType&);
+ unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const;
+ unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const;
+ void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; }
+ bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; }
+ void setGeoPassthroughEXT() { geoPassthroughEXT = true; }
+ bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
+ void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
+ bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; }
+ ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
+ bool setPrimitives(int m)
+ {
+ if (primitives != TQualifier::layoutNotSet)
+ return primitives == m;
+ primitives = m;
+ return true;
+ }
+ int getPrimitives() const { return primitives; }
+ const char* addSemanticName(const TString& name)
+ {
+ return semanticNameSet.insert(name).first->c_str();
+ }
+ void addUniformLocationOverride(const char* nameStr, int location)
+ {
+ std::string name = nameStr;
+ uniformLocationOverrides[name] = location;
+ }
+
+ int getUniformLocationOverride(const char* nameStr) const
+ {
+ std::string name = nameStr;
+ auto pos = uniformLocationOverrides.find(name);
+ if (pos == uniformLocationOverrides.end())
+ return -1;
+ else
+ return pos->second;
+ }
+
+ void setUniformLocationBase(int base) { uniformLocationBase = base; }
+ int getUniformLocationBase() const { return uniformLocationBase; }
+
+ void setNeedsLegalization() { needToLegalize = true; }
+ bool needsLegalization() const { return needToLegalize; }
+
+ void setBinaryDoubleOutput() { binaryDoubleOutput = true; }
+ bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
+#endif // GLSLANG_WEB
+
+#ifdef ENABLE_HLSL
+ void setHlslFunctionality1() { hlslFunctionality1 = true; }
+ bool getHlslFunctionality1() const { return hlslFunctionality1; }
+ void setHlslOffsets()
+ {
+ hlslOffsets = true;
+ if (hlslOffsets)
+ processes.addProcess("hlsl-offsets");
+ }
+ bool usingHlslOffsets() const { return hlslOffsets; }
+ void setHlslIoMapping(bool b)
+ {
+ hlslIoMapping = b;
+ if (hlslIoMapping)
+ processes.addProcess("hlsl-iomap");
+ }
+ bool usingHlslIoMapping() { return hlslIoMapping; }
+#else
+ bool getHlslFunctionality1() const { return false; }
+ bool usingHlslOffsets() const { return false; }
+ bool usingHlslIoMapping() { return false; }
+#endif
+
+ void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
+ void merge(TInfoSink&, TIntermediate&);
+ void finalCheck(TInfoSink&, bool keepUncalled);
+
+ bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
+ TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
+
+ void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
+ bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
+
+ int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
+ int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
+ int addUsedOffsets(int binding, int offset, int numOffsets);
+ bool addUsedConstantId(int id);
+ static int computeTypeLocationSize(const TType&, EShLanguage);
+ static int computeTypeUniformLocationSize(const TType&);
+
+ static int getBaseAlignmentScalar(const TType&, int& size);
+ static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
+ static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor);
+ static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
+ static bool improperStraddle(const TType& type, int size, int offset);
+ static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize);
+ static int getOffset(const TType& type, int index);
+ static int getBlockSize(const TType& blockType);
+ static int computeBufferReferenceTypeSize(const TType&);
+ bool promote(TIntermOperator*);
+ void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
+ bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
+
+ void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; }
+ const std::string& getSourceFile() const { return sourceFile; }
+ void addSourceText(const char* text, size_t len) { sourceText.append(text, len); }
+ const std::string& getSourceText() const { return sourceText; }
+ const std::map<std::string, std::string>& getIncludeText() const { return includeText; }
+ void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); }
+ void addProcesses(const std::vector<std::string>& p)
+ {
+ for (int i = 0; i < (int)p.size(); ++i)
+ processes.addProcess(p[i]);
+ }
+ void addProcess(const std::string& process) { processes.addProcess(process); }
+ void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
+ const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
+
+ // Certain explicit conversions are allowed conditionally
+#ifdef GLSLANG_WEB
+ bool getArithemeticInt8Enabled() const { return false; }
+ bool getArithemeticInt16Enabled() const { return false; }
+ bool getArithemeticFloat16Enabled() const { return false; }
+#else
+ bool getArithemeticInt8Enabled() const {
+ return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
+ }
+ bool getArithemeticInt16Enabled() const {
+ return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ extensionRequested(E_GL_AMD_gpu_shader_int16) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
+ }
+
+ bool getArithemeticFloat16Enabled() const {
+ return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
+ extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
+ extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
+ }
+#endif
+
+protected:
+ TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
+ void error(TInfoSink& infoSink, const char*);
+ void warn(TInfoSink& infoSink, const char*);
+ void mergeCallGraphs(TInfoSink&, TIntermediate&);
+ void mergeModes(TInfoSink&, TIntermediate&);
+ void mergeTrees(TInfoSink&, TIntermediate&);
+ void seedIdMap(TMap<TString, int>& idMap, int& maxId);
+ void remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate&);
+ void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
+ void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
+ void mergeImplicitArraySizes(TType&, const TType&);
+ void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage);
+ void checkCallGraphCycles(TInfoSink&);
+ void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
+ void inOutLocationCheck(TInfoSink&);
+ TIntermAggregate* findLinkerObjects() const;
+ bool userOutputUsed() const;
+ bool isSpecializationOperation(const TIntermOperator&) const;
+ bool isNonuniformPropagating(TOperator) const;
+ bool promoteUnary(TIntermUnary&);
+ bool promoteBinary(TIntermBinary&);
+ void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
+ bool promoteAggregate(TIntermAggregate&);
+ void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&);
+ void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
+ bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
+ void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
+ bool isConversionAllowed(TOperator op, TIntermTyped* node) const;
+ std::tuple<TBasicType, TBasicType> getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const;
+
+ // JohnK: I think this function should go away.
+ // This data structure is just a log to pass on to back ends.
+ // Versioning and extensions are handled in Version.cpp, with a rich
+ // set of functions for querying stages, versions, extension enable/disabled, etc.
+#ifdef GLSLANG_WEB
+ bool extensionRequested(const char *extension) const { return false; }
+#else
+ bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();}
+#endif
+
+ static const char* getResourceName(TResourceType);
+
+ const EShLanguage language; // stage, known at construction time
+ std::string entryPointName;
+ std::string entryPointMangledName;
+ typedef std::list<TCall> TGraph;
+ TGraph callGraph;
+
+ EProfile profile; // source profile
+ int version; // source version
+ SpvVersion spvVersion;
+ TIntermNode* treeRoot;
+ std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
+ TBuiltInResource resources;
+ int numEntryPoints;
+ int numErrors;
+ int numPushConstants;
+ bool recursive;
+ bool invertY;
+ bool useStorageBuffer;
+ bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN
+ bool depthReplacing;
+ int localSize[3];
+ bool localSizeNotDefault[3];
+ int localSizeSpecId[3];
+#ifndef GLSLANG_WEB
+public:
+ const char* const implicitThisName;
+ const char* const implicitCounterName;
+protected:
+ EShSource source; // source language, known a bit later
+ bool useVulkanMemoryModel;
+ int invocations;
+ int vertices;
+ TLayoutGeometry inputPrimitive;
+ TLayoutGeometry outputPrimitive;
+ bool pixelCenterInteger;
+ bool originUpperLeft;
+ TVertexSpacing vertexSpacing;
+ TVertexOrder vertexOrder;
+ TInterlockOrdering interlockOrdering;
+ bool pointMode;
+ bool earlyFragmentTests;
+ bool postDepthCoverage;
+ TLayoutDepth depthLayout;
+ bool hlslFunctionality1;
+ int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift
+ bool xfbMode;
+ std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
+ bool multiStream;
+ bool layoutOverrideCoverage;
+ bool geoPassthroughEXT;
+ int numShaderRecordNVBlocks;
+ ComputeDerivativeMode computeDerivativeMode;
+ int primitives;
+ int numTaskNVBlocks;
+
+ // Base shift values
+ std::array<unsigned int, EResCount> shiftBinding;
+
+ // Per-descriptor-set shift values
+ std::array<std::map<int, int>, EResCount> shiftBindingForSet;
+
+ std::vector<std::string> resourceSetBinding;
+ bool autoMapBindings;
+ bool autoMapLocations;
+ bool flattenUniformArrays;
+ bool useUnknownFormat;
+ bool hlslOffsets;
+ bool hlslIoMapping;
+ bool useVariablePointers;
+
+ std::set<TString> semanticNameSet;
+
+ EShTextureSamplerTransformMode textureSamplerTransformMode;
+
+ bool needToLegalize;
+ bool binaryDoubleOutput;
+ bool usePhysicalStorageBuffer;
+
+ std::unordered_map<std::string, int> uniformLocationOverrides;
+ int uniformLocationBase;
+#endif
+
+ std::unordered_set<int> usedConstantId; // specialization constant ids used
+ std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
+ std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
+ // set of names of statically read/written I/O that might need extra checking
+ std::set<TString> ioAccessed;
+ // source code of shader, useful as part of debug information
+ std::string sourceFile;
+ std::string sourceText;
+
+ // Included text. First string is a name, second is the included text
+ std::map<std::string, std::string> includeText;
+
+ // for OpModuleProcessed, or equivalent
+ TProcesses processes;
+
+private:
+ void operator=(TIntermediate&); // prevent assignments
+};
+
+} // end namespace glslang
+
+#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/thirdparty/glslang/glslang/MachineIndependent/parseConst.cpp b/thirdparty/glslang/glslang/MachineIndependent/parseConst.cpp
new file mode 100644
index 0000000000..1a8e6d9987
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/parseConst.cpp
@@ -0,0 +1,204 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Traverse a tree of constants to create a single folded constant.
+// It should only be used when the whole tree is known to be constant.
+//
+
+#include "ParseHelper.h"
+
+namespace glslang {
+
+class TConstTraverser : public TIntermTraverser {
+public:
+ TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t)
+ : unionArray(cUnion), type(t),
+ constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
+ matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull; }
+
+ virtual void visitConstantUnion(TIntermConstantUnion* node);
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node);
+
+ int index;
+ TConstUnionArray unionArray;
+ TOperator tOp;
+ const TType& type;
+ TOperator constructorType;
+ bool singleConstantParam;
+ bool error;
+ int size; // size of the constructor ( 4 for vec4)
+ bool isMatrix;
+ int matrixCols;
+ int matrixRows;
+
+protected:
+ TConstTraverser(TConstTraverser&);
+ TConstTraverser& operator=(TConstTraverser&);
+};
+
+bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
+{
+ if (! node->isConstructor() && node->getOp() != EOpComma) {
+ error = true;
+
+ return false;
+ }
+
+ bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
+ if (flag) {
+ singleConstantParam = true;
+ constructorType = node->getOp();
+ size = node->getType().computeNumComponents();
+
+ if (node->getType().isMatrix()) {
+ isMatrix = true;
+ matrixCols = node->getType().getMatrixCols();
+ matrixRows = node->getType().getMatrixRows();
+ }
+ }
+
+ for (TIntermSequence::iterator p = node->getSequence().begin();
+ p != node->getSequence().end(); p++) {
+
+ if (node->getOp() == EOpComma)
+ index = 0;
+
+ (*p)->traverse(this);
+ }
+ if (flag)
+ {
+ singleConstantParam = false;
+ constructorType = EOpNull;
+ size = 0;
+ isMatrix = false;
+ matrixCols = 0;
+ matrixRows = 0;
+ }
+
+ return false;
+}
+
+void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+ TConstUnionArray leftUnionArray(unionArray);
+ int instanceSize = type.computeNumComponents();
+
+ if (index >= instanceSize)
+ return;
+
+ if (! singleConstantParam) {
+ int rightUnionSize = node->getType().computeNumComponents();
+
+ const TConstUnionArray& rightUnionArray = node->getConstArray();
+ for (int i = 0; i < rightUnionSize; i++) {
+ if (index >= instanceSize)
+ return;
+ leftUnionArray[index] = rightUnionArray[i];
+
+ index++;
+ }
+ } else {
+ int endIndex = index + size;
+ const TConstUnionArray& rightUnionArray = node->getConstArray();
+ if (! isMatrix) {
+ int count = 0;
+ int nodeComps = node->getType().computeNumComponents();
+ for (int i = index; i < endIndex; i++) {
+ if (i >= instanceSize)
+ return;
+
+ leftUnionArray[i] = rightUnionArray[count];
+
+ (index)++;
+
+ if (nodeComps > 1)
+ count++;
+ }
+ } else {
+ // constructing a matrix, but from what?
+ if (node->isMatrix()) {
+ // Matrix from a matrix; this has the outer matrix, node is the argument matrix.
+ // Traverse the outer, potentially bigger matrix, fill in missing pieces with the
+ // identity matrix.
+ for (int c = 0; c < matrixCols; ++c) {
+ for (int r = 0; r < matrixRows; ++r) {
+ int targetOffset = index + c * matrixRows + r;
+ if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
+ int srcOffset = c * node->getType().getMatrixRows() + r;
+ leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
+ } else if (r == c)
+ leftUnionArray[targetOffset].setDConst(1.0);
+ else
+ leftUnionArray[targetOffset].setDConst(0.0);
+ }
+ }
+ } else {
+ // matrix from vector
+ int count = 0;
+ const int startIndex = index;
+ int nodeComps = node->getType().computeNumComponents();
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i >= instanceSize)
+ return;
+ if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
+ leftUnionArray[i] = rightUnionArray[count];
+ else
+ leftUnionArray[i].setDConst(0.0);
+
+ index++;
+
+ if (nodeComps > 1)
+ count++;
+ }
+ }
+ }
+ }
+}
+
+bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
+{
+ if (root == 0)
+ return false;
+
+ TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
+
+ root->traverse(&it);
+ if (it.error)
+ return true;
+ else
+ return false;
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/parseVersions.h b/thirdparty/glslang/glslang/MachineIndependent/parseVersions.h
new file mode 100644
index 0000000000..aa1964fc2e
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/parseVersions.h
@@ -0,0 +1,236 @@
+//
+// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2017 ARM Limited.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+// This is implemented in Versions.cpp
+
+#ifndef _PARSE_VERSIONS_INCLUDED_
+#define _PARSE_VERSIONS_INCLUDED_
+
+#include "../Public/ShaderLang.h"
+#include "../Include/InfoSink.h"
+#include "Scan.h"
+
+#include <map>
+
+namespace glslang {
+
+//
+// Base class for parse helpers.
+// This just has version-related information and checking.
+// This class should be sufficient for preprocessing.
+//
+class TParseVersions {
+public:
+ TParseVersions(TIntermediate& interm, int version, EProfile profile,
+ const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink,
+ bool forwardCompatible, EShMessages messages)
+ :
+#ifndef GLSLANG_WEB
+ forwardCompatible(forwardCompatible),
+ profile(profile),
+#endif
+ infoSink(infoSink), version(version),
+ language(language),
+ spvVersion(spvVersion),
+ intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { }
+ virtual ~TParseVersions() { }
+ void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc);
+ void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc);
+#ifdef GLSLANG_WEB
+ const EProfile profile = EEsProfile;
+ bool isEsProfile() const { return true; }
+ void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc)
+ {
+ if (! (EEsProfile & profileMask))
+ error(loc, "not supported with this profile:", featureDesc, ProfileName(profile));
+ }
+ void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions,
+ const char* const extensions[], const char* featureDesc)
+ {
+ if ((EEsProfile & profileMask) && (minVersion == 0 || version < minVersion))
+ error(loc, "not supported for this version or the enabled extensions", featureDesc, "");
+ }
+ void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension,
+ const char* featureDesc)
+ {
+ profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc);
+ }
+ void initializeExtensionBehavior() { }
+ void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc) { }
+ void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc) { }
+ void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
+ const char* featureDesc) { }
+ void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
+ const char* featureDesc) { }
+ TExtensionBehavior getExtensionBehavior(const char*) { return EBhMissing; }
+ bool extensionTurnedOn(const char* const extension) { return false; }
+ bool extensionsTurnedOn(int numExtensions, const char* const extensions[]) { return false; }
+ void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { }
+ void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { }
+ void checkExtensionStage(const TSourceLoc&, const char* const extension) { }
+ void fullIntegerCheck(const TSourceLoc&, const char* op) { }
+ void doubleCheck(const TSourceLoc&, const char* op) { }
+ bool float16Arithmetic() { return false; }
+ void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { }
+ bool int16Arithmetic() { return false; }
+ void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { }
+ bool int8Arithmetic() { return false; }
+ void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { }
+ void int64Check(const TSourceLoc&, const char* op, bool builtIn = false) { }
+ void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false) { }
+ void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false) { }
+ bool relaxedErrors() const { return false; }
+ bool suppressWarnings() const { return true; }
+ bool isForwardCompatible() const { return false; }
+#else
+ bool forwardCompatible; // true if errors are to be given for use of deprecated features
+ EProfile profile; // the declared profile in the shader (core by default)
+ bool isEsProfile() const { return profile == EEsProfile; }
+ void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc);
+ void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions,
+ const char* const extensions[], const char* featureDesc);
+ void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension,
+ const char* featureDesc);
+ virtual void initializeExtensionBehavior();
+ virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc);
+ virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc);
+ virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
+ const char* featureDesc);
+ virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
+ const char* featureDesc);
+ virtual TExtensionBehavior getExtensionBehavior(const char*);
+ virtual bool extensionTurnedOn(const char* const extension);
+ virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]);
+ virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior);
+ virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
+ virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[],
+ const char* featureDesc);
+ virtual void checkExtensionStage(const TSourceLoc&, const char* const extension);
+ virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
+
+ virtual void unimplemented(const TSourceLoc&, const char* featureDesc);
+ virtual void doubleCheck(const TSourceLoc&, const char* op);
+ virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual void float16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual bool float16Arithmetic();
+ virtual void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
+ virtual void int16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual bool int16Arithmetic();
+ virtual void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
+ virtual void int8ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual bool int8Arithmetic();
+ virtual void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
+ virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual void explicitInt8Check(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual void explicitInt16Check(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual void explicitInt32Check(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual void fcoopmatCheck(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual void intcoopmatCheck(const TSourceLoc&, const char *op, bool builtIn = false);
+ bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; }
+ bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; }
+ bool isForwardCompatible() const { return forwardCompatible; }
+#endif // GLSLANG_WEB
+ virtual void spvRemoved(const TSourceLoc&, const char* op);
+ virtual void vulkanRemoved(const TSourceLoc&, const char* op);
+ virtual void requireVulkan(const TSourceLoc&, const char* op);
+ virtual void requireSpv(const TSourceLoc&, const char* op);
+
+
+#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL)
+ void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) { addError(); }
+ void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) { }
+ void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) { addError(); }
+ void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) { }
+#else
+ virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) = 0;
+ virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) = 0;
+ virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) = 0;
+ virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) = 0;
+#endif
+
+ void addError() { ++numErrors; }
+ int getNumErrors() const { return numErrors; }
+
+ void setScanner(TInputScanner* scanner) { currentScanner = scanner; }
+ TInputScanner* getScanner() const { return currentScanner; }
+ const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); }
+ void setCurrentLine(int line) { currentScanner->setLine(line); }
+ void setCurrentColumn(int col) { currentScanner->setColumn(col); }
+ void setCurrentSourceName(const char* name) { currentScanner->setFile(name); }
+ void setCurrentString(int string) { currentScanner->setString(string); }
+
+ void getPreamble(std::string&);
+#ifdef ENABLE_HLSL
+ bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; }
+ bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; }
+ bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; }
+#else
+ bool isReadingHLSL() const { return false; }
+#endif
+
+ TInfoSink& infoSink;
+
+ // compilation mode
+ int version; // version, updated by #version in the shader
+ EShLanguage language; // really the stage
+ SpvVersion spvVersion;
+ TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
+
+protected:
+ TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is set to
+ EShMessages messages; // errors/warnings/rule-sets
+ int numErrors; // number of compile-time errors encountered
+ TInputScanner* currentScanner;
+
+private:
+ explicit TParseVersions(const TParseVersions&);
+ TParseVersions& operator=(const TParseVersions&);
+};
+
+} // end namespace glslang
+
+#endif // _PARSE_VERSIONS_INCLUDED_
diff --git a/thirdparty/glslang/glslang/MachineIndependent/pch.cpp b/thirdparty/glslang/glslang/MachineIndependent/pch.cpp
new file mode 100644
index 0000000000..b7a08654a5
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/pch.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2018 The Khronos Group Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "pch.h"
diff --git a/thirdparty/glslang/glslang/MachineIndependent/pch.h b/thirdparty/glslang/glslang/MachineIndependent/pch.h
new file mode 100644
index 0000000000..6ea3761ea1
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/pch.h
@@ -0,0 +1,49 @@
+#ifndef _PCH_H
+#define _PCH_H
+//
+// Copyright (C) 2018 The Khronos Group Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+#include <sstream>
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+#include <climits>
+#include <iostream>
+#include <sstream>
+#include <memory>
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "Scan.h"
+#include "ScanContext.h"
+
+#endif /* _PCH_H */
diff --git a/thirdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp
new file mode 100755
index 0000000000..d7ff485c0a
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp
@@ -0,0 +1,1323 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include <sstream>
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+#include <climits>
+
+#include "PpContext.h"
+#include "PpTokens.h"
+
+namespace glslang {
+
+// Handle #define
+int TPpContext::CPPdefine(TPpToken* ppToken)
+{
+ MacroSymbol mac;
+
+ // get the macro name
+ int token = scanToken(ppToken);
+ if (token != PpAtomIdentifier) {
+ parseContext.ppError(ppToken->loc, "must be followed by macro name", "#define", "");
+ return token;
+ }
+ if (ppToken->loc.string >= 0) {
+ // We are in user code; check for reserved name use:
+ parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#define");
+ }
+
+ // save the macro name
+ const int defAtom = atomStrings.getAddAtom(ppToken->name);
+ TSourceLoc defineLoc = ppToken->loc; // because ppToken might go to the next line before we report errors
+
+ // gather parameters to the macro, between (...)
+ token = scanToken(ppToken);
+ if (token == '(' && !ppToken->space) {
+ mac.functionLike = 1;
+ do {
+ token = scanToken(ppToken);
+ if (mac.args.size() == 0 && token == ')')
+ break;
+ if (token != PpAtomIdentifier) {
+ parseContext.ppError(ppToken->loc, "bad argument", "#define", "");
+
+ return token;
+ }
+ const int argAtom = atomStrings.getAddAtom(ppToken->name);
+
+ // check for duplication of parameter name
+ bool duplicate = false;
+ for (size_t a = 0; a < mac.args.size(); ++a) {
+ if (mac.args[a] == argAtom) {
+ parseContext.ppError(ppToken->loc, "duplicate macro parameter", "#define", "");
+ duplicate = true;
+ break;
+ }
+ }
+ if (! duplicate)
+ mac.args.push_back(argAtom);
+ token = scanToken(ppToken);
+ } while (token == ',');
+ if (token != ')') {
+ parseContext.ppError(ppToken->loc, "missing parenthesis", "#define", "");
+
+ return token;
+ }
+
+ token = scanToken(ppToken);
+ } else if (token != '\n' && token != EndOfInput && !ppToken->space) {
+ parseContext.ppWarn(ppToken->loc, "missing space after macro name", "#define", "");
+
+ return token;
+ }
+
+ // record the definition of the macro
+ while (token != '\n' && token != EndOfInput) {
+ mac.body.putToken(token, ppToken);
+ token = scanToken(ppToken);
+ if (token != '\n' && ppToken->space)
+ mac.body.putToken(' ', ppToken);
+ }
+
+ // check for duplicate definition
+ MacroSymbol* existing = lookupMacroDef(defAtom);
+ if (existing != nullptr) {
+ if (! existing->undef) {
+ // Already defined -- need to make sure they are identical:
+ // "Two replacement lists are identical if and only if the
+ // preprocessing tokens in both have the same number,
+ // ordering, spelling, and white-space separation, where all
+ // white-space separations are considered identical."
+ if (existing->functionLike != mac.functionLike) {
+ parseContext.ppError(defineLoc, "Macro redefined; function-like versus object-like:", "#define",
+ atomStrings.getString(defAtom));
+ } else if (existing->args.size() != mac.args.size()) {
+ parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define",
+ atomStrings.getString(defAtom));
+ } else {
+ if (existing->args != mac.args) {
+ parseContext.ppError(defineLoc, "Macro redefined; different argument names:", "#define",
+ atomStrings.getString(defAtom));
+ }
+ // set up to compare the two
+ existing->body.reset();
+ mac.body.reset();
+ int newToken;
+ bool firstToken = true;
+ do {
+ int oldToken;
+ TPpToken oldPpToken;
+ TPpToken newPpToken;
+ oldToken = existing->body.getToken(parseContext, &oldPpToken);
+ newToken = mac.body.getToken(parseContext, &newPpToken);
+ // for the first token, preceding spaces don't matter
+ if (firstToken) {
+ newPpToken.space = oldPpToken.space;
+ firstToken = false;
+ }
+ if (oldToken != newToken || oldPpToken != newPpToken) {
+ parseContext.ppError(defineLoc, "Macro redefined; different substitutions:", "#define",
+ atomStrings.getString(defAtom));
+ break;
+ }
+ } while (newToken != EndOfInput);
+ }
+ }
+ *existing = mac;
+ } else
+ addMacroDef(defAtom, mac);
+
+ return '\n';
+}
+
+// Handle #undef
+int TPpContext::CPPundef(TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+ if (token != PpAtomIdentifier) {
+ parseContext.ppError(ppToken->loc, "must be followed by macro name", "#undef", "");
+
+ return token;
+ }
+
+ parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#undef");
+
+ MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name));
+ if (macro != nullptr)
+ macro->undef = 1;
+ token = scanToken(ppToken);
+ if (token != '\n')
+ parseContext.ppError(ppToken->loc, "can only be followed by a single macro name", "#undef", "");
+
+ return token;
+}
+
+// Handle #else
+/* Skip forward to appropriate spot. This is used both
+** to skip to a #endif after seeing an #else, AND to skip to a #else,
+** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false.
+*/
+int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
+{
+ int depth = 0;
+ int token = scanToken(ppToken);
+
+ while (token != EndOfInput) {
+ if (token != '#') {
+ while (token != '\n' && token != EndOfInput)
+ token = scanToken(ppToken);
+
+ if (token == EndOfInput)
+ return token;
+
+ token = scanToken(ppToken);
+ continue;
+ }
+
+ if ((token = scanToken(ppToken)) != PpAtomIdentifier)
+ continue;
+
+ int nextAtom = atomStrings.getAtom(ppToken->name);
+ if (nextAtom == PpAtomIf || nextAtom == PpAtomIfdef || nextAtom == PpAtomIfndef) {
+ depth++;
+ if (ifdepth >= maxIfNesting || elsetracker >= maxIfNesting) {
+ parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if/#ifdef/#ifndef", "");
+ return EndOfInput;
+ } else {
+ ifdepth++;
+ elsetracker++;
+ }
+ } else if (nextAtom == PpAtomEndif) {
+ token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken));
+ elseSeen[elsetracker] = false;
+ --elsetracker;
+ if (depth == 0) {
+ // found the #endif we are looking for
+ if (ifdepth > 0)
+ --ifdepth;
+ break;
+ }
+ --depth;
+ --ifdepth;
+ } else if (matchelse && depth == 0) {
+ if (nextAtom == PpAtomElse) {
+ elseSeen[elsetracker] = true;
+ token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken));
+ // found the #else we are looking for
+ break;
+ } else if (nextAtom == PpAtomElif) {
+ if (elseSeen[elsetracker])
+ parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
+ /* we decrement ifdepth here, because CPPif will increment
+ * it and we really want to leave it alone */
+ if (ifdepth > 0) {
+ --ifdepth;
+ elseSeen[elsetracker] = false;
+ --elsetracker;
+ }
+
+ return CPPif(ppToken);
+ }
+ } else if (nextAtom == PpAtomElse) {
+ if (elseSeen[elsetracker])
+ parseContext.ppError(ppToken->loc, "#else after #else", "#else", "");
+ else
+ elseSeen[elsetracker] = true;
+ token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken));
+ } else if (nextAtom == PpAtomElif) {
+ if (elseSeen[elsetracker])
+ parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
+ }
+ }
+
+ return token;
+}
+
+// Call when there should be no more tokens left on a line.
+int TPpContext::extraTokenCheck(int contextAtom, TPpToken* ppToken, int token)
+{
+ if (token != '\n' && token != EndOfInput) {
+ static const char* message = "unexpected tokens following directive";
+
+ const char* label;
+ if (contextAtom == PpAtomElse)
+ label = "#else";
+ else if (contextAtom == PpAtomElif)
+ label = "#elif";
+ else if (contextAtom == PpAtomEndif)
+ label = "#endif";
+ else if (contextAtom == PpAtomIf)
+ label = "#if";
+ else if (contextAtom == PpAtomLine)
+ label = "#line";
+ else
+ label = "";
+
+ if (parseContext.relaxedErrors())
+ parseContext.ppWarn(ppToken->loc, message, label, "");
+ else
+ parseContext.ppError(ppToken->loc, message, label, "");
+
+ while (token != '\n' && token != EndOfInput)
+ token = scanToken(ppToken);
+ }
+
+ return token;
+}
+
+enum eval_prec {
+ MIN_PRECEDENCE,
+ COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
+ MAX_PRECEDENCE
+};
+
+namespace {
+
+ int op_logor(int a, int b) { return a || b; }
+ int op_logand(int a, int b) { return a && b; }
+ int op_or(int a, int b) { return a | b; }
+ int op_xor(int a, int b) { return a ^ b; }
+ int op_and(int a, int b) { return a & b; }
+ int op_eq(int a, int b) { return a == b; }
+ int op_ne(int a, int b) { return a != b; }
+ int op_ge(int a, int b) { return a >= b; }
+ int op_le(int a, int b) { return a <= b; }
+ int op_gt(int a, int b) { return a > b; }
+ int op_lt(int a, int b) { return a < b; }
+ int op_shl(int a, int b) { return a << b; }
+ int op_shr(int a, int b) { return a >> b; }
+ int op_add(int a, int b) { return a + b; }
+ int op_sub(int a, int b) { return a - b; }
+ int op_mul(int a, int b) { return a * b; }
+ int op_div(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a / b; }
+ int op_mod(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a % b; }
+ int op_pos(int a) { return a; }
+ int op_neg(int a) { return -a; }
+ int op_cmpl(int a) { return ~a; }
+ int op_not(int a) { return !a; }
+
+};
+
+struct TBinop {
+ int token, precedence, (*op)(int, int);
+} binop[] = {
+ { PpAtomOr, LOGOR, op_logor },
+ { PpAtomAnd, LOGAND, op_logand },
+ { '|', OR, op_or },
+ { '^', XOR, op_xor },
+ { '&', AND, op_and },
+ { PpAtomEQ, EQUAL, op_eq },
+ { PpAtomNE, EQUAL, op_ne },
+ { '>', RELATION, op_gt },
+ { PpAtomGE, RELATION, op_ge },
+ { '<', RELATION, op_lt },
+ { PpAtomLE, RELATION, op_le },
+ { PpAtomLeft, SHIFT, op_shl },
+ { PpAtomRight, SHIFT, op_shr },
+ { '+', ADD, op_add },
+ { '-', ADD, op_sub },
+ { '*', MUL, op_mul },
+ { '/', MUL, op_div },
+ { '%', MUL, op_mod },
+};
+
+struct TUnop {
+ int token, (*op)(int);
+} unop[] = {
+ { '+', op_pos },
+ { '-', op_neg },
+ { '~', op_cmpl },
+ { '!', op_not },
+};
+
+#define NUM_ELEMENTS(A) (sizeof(A) / sizeof(A[0]))
+
+int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
+{
+ TSourceLoc loc = ppToken->loc; // because we sometimes read the newline before reporting the error
+ if (token == PpAtomIdentifier) {
+ if (strcmp("defined", ppToken->name) == 0) {
+ if (! parseContext.isReadingHLSL() && isMacroInput()) {
+ if (parseContext.relaxedErrors())
+ parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression",
+ "defined", "");
+ else
+ parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros",
+ "defined", "");
+ }
+ bool needclose = 0;
+ token = scanToken(ppToken);
+ if (token == '(') {
+ needclose = true;
+ token = scanToken(ppToken);
+ }
+ if (token != PpAtomIdentifier) {
+ parseContext.ppError(loc, "incorrect directive, expected identifier", "preprocessor evaluation", "");
+ err = true;
+ res = 0;
+
+ return token;
+ }
+
+ MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name));
+ res = macro != nullptr ? !macro->undef : 0;
+ token = scanToken(ppToken);
+ if (needclose) {
+ if (token != ')') {
+ parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", "");
+ err = true;
+ res = 0;
+
+ return token;
+ }
+ token = scanToken(ppToken);
+ }
+ } else {
+ token = evalToToken(token, shortCircuit, res, err, ppToken);
+ return eval(token, precedence, shortCircuit, res, err, ppToken);
+ }
+ } else if (token == PpAtomConstInt) {
+ res = ppToken->ival;
+ token = scanToken(ppToken);
+ } else if (token == '(') {
+ token = scanToken(ppToken);
+ token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken);
+ if (! err) {
+ if (token != ')') {
+ parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", "");
+ err = true;
+ res = 0;
+
+ return token;
+ }
+ token = scanToken(ppToken);
+ }
+ } else {
+ int op = NUM_ELEMENTS(unop) - 1;
+ for (; op >= 0; op--) {
+ if (unop[op].token == token)
+ break;
+ }
+ if (op >= 0) {
+ token = scanToken(ppToken);
+ token = eval(token, UNARY, shortCircuit, res, err, ppToken);
+ res = unop[op].op(res);
+ } else {
+ parseContext.ppError(loc, "bad expression", "preprocessor evaluation", "");
+ err = true;
+ res = 0;
+
+ return token;
+ }
+ }
+
+ token = evalToToken(token, shortCircuit, res, err, ppToken);
+
+ // Perform evaluation of binary operation, if there is one, otherwise we are done.
+ while (! err) {
+ if (token == ')' || token == '\n')
+ break;
+ int op;
+ for (op = NUM_ELEMENTS(binop) - 1; op >= 0; op--) {
+ if (binop[op].token == token)
+ break;
+ }
+ if (op < 0 || binop[op].precedence <= precedence)
+ break;
+ int leftSide = res;
+
+ // Setup short-circuiting, needed for ES, unless already in a short circuit.
+ // (Once in a short-circuit, can't turn off again, until that whole subexpression is done.
+ if (! shortCircuit) {
+ if ((token == PpAtomOr && leftSide == 1) ||
+ (token == PpAtomAnd && leftSide == 0))
+ shortCircuit = true;
+ }
+
+ token = scanToken(ppToken);
+ token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken);
+
+ if (binop[op].op == op_div || binop[op].op == op_mod) {
+ if (res == 0) {
+ parseContext.ppError(loc, "division by 0", "preprocessor evaluation", "");
+ res = 1;
+ }
+ }
+ res = binop[op].op(leftSide, res);
+ }
+
+ return token;
+}
+
+// Expand macros, skipping empty expansions, to get to the first real token in those expansions.
+int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
+{
+ while (token == PpAtomIdentifier && strcmp("defined", ppToken->name) != 0) {
+ switch (MacroExpand(ppToken, true, false)) {
+ case MacroExpandNotStarted:
+ case MacroExpandError:
+ parseContext.ppError(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", "");
+ err = true;
+ res = 0;
+ break;
+ case MacroExpandStarted:
+ break;
+ case MacroExpandUndef:
+ if (! shortCircuit && parseContext.isEsProfile()) {
+ const char* message = "undefined macro in expression not allowed in es profile";
+ if (parseContext.relaxedErrors())
+ parseContext.ppWarn(ppToken->loc, message, "preprocessor evaluation", ppToken->name);
+ else
+ parseContext.ppError(ppToken->loc, message, "preprocessor evaluation", ppToken->name);
+ }
+ break;
+ }
+ token = scanToken(ppToken);
+ if (err)
+ break;
+ }
+
+ return token;
+}
+
+// Handle #if
+int TPpContext::CPPif(TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+ if (ifdepth >= maxIfNesting || elsetracker >= maxIfNesting) {
+ parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if", "");
+ return EndOfInput;
+ } else {
+ elsetracker++;
+ ifdepth++;
+ }
+ int res = 0;
+ bool err = false;
+ token = eval(token, MIN_PRECEDENCE, false, res, err, ppToken);
+ token = extraTokenCheck(PpAtomIf, ppToken, token);
+ if (!res && !err)
+ token = CPPelse(1, ppToken);
+
+ return token;
+}
+
+// Handle #ifdef
+int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+ if (ifdepth > maxIfNesting || elsetracker > maxIfNesting) {
+ parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#ifdef", "");
+ return EndOfInput;
+ } else {
+ elsetracker++;
+ ifdepth++;
+ }
+
+ if (token != PpAtomIdentifier) {
+ if (defined)
+ parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifdef", "");
+ else
+ parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifndef", "");
+ } else {
+ MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name));
+ token = scanToken(ppToken);
+ if (token != '\n') {
+ parseContext.ppError(ppToken->loc, "unexpected tokens following #ifdef directive - expected a newline", "#ifdef", "");
+ while (token != '\n' && token != EndOfInput)
+ token = scanToken(ppToken);
+ }
+ if (((macro != nullptr && !macro->undef) ? 1 : 0) != defined)
+ token = CPPelse(1, ppToken);
+ }
+
+ return token;
+}
+
+// Handle #include ...
+// TODO: Handle macro expansions for the header name
+int TPpContext::CPPinclude(TPpToken* ppToken)
+{
+ const TSourceLoc directiveLoc = ppToken->loc;
+ bool startWithLocalSearch = true; // to additionally include the extra "" paths
+ int token = scanToken(ppToken);
+
+ // handle <header-name>-style #include
+ if (token == '<') {
+ startWithLocalSearch = false;
+ token = scanHeaderName(ppToken, '>');
+ }
+ // otherwise ppToken already has the header name and it was "header-name" style
+
+ if (token != PpAtomConstString) {
+ parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", "");
+ return token;
+ }
+
+ // Make a copy of the name because it will be overwritten by the next token scan.
+ const std::string filename = ppToken->name;
+
+ // See if the directive was well formed
+ token = scanToken(ppToken);
+ if (token != '\n') {
+ if (token == EndOfInput)
+ parseContext.ppError(ppToken->loc, "expected newline after header name:", "#include", "%s", filename.c_str());
+ else
+ parseContext.ppError(ppToken->loc, "extra content after header name:", "#include", "%s", filename.c_str());
+ return token;
+ }
+
+ // Process well-formed directive
+
+ // Find the inclusion, first look in "Local" ("") paths, if requested,
+ // otherwise, only search the "System" (<>) paths.
+ TShader::Includer::IncludeResult* res = nullptr;
+ if (startWithLocalSearch)
+ res = includer.includeLocal(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1);
+ if (res == nullptr || res->headerName.empty()) {
+ includer.releaseInclude(res);
+ res = includer.includeSystem(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1);
+ }
+
+ // Process the results
+ if (res != nullptr && !res->headerName.empty()) {
+ if (res->headerData != nullptr && res->headerLength > 0) {
+ // path for processing one or more tokens from an included header, hand off 'res'
+ const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine();
+ std::ostringstream prologue;
+ std::ostringstream epilogue;
+ prologue << "#line " << forNextLine << " " << "\"" << res->headerName << "\"\n";
+ epilogue << (res->headerData[res->headerLength - 1] == '\n'? "" : "\n") <<
+ "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n";
+ pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), this));
+ parseContext.intermediate.addIncludeText(res->headerName.c_str(), res->headerData, res->headerLength);
+ // There's no "current" location anymore.
+ parseContext.setCurrentColumn(0);
+ } else {
+ // things are okay, but there is nothing to process
+ includer.releaseInclude(res);
+ }
+ } else {
+ // error path, clean up
+ std::string message =
+ res != nullptr ? std::string(res->headerData, res->headerLength)
+ : std::string("Could not process include directive");
+ parseContext.ppError(directiveLoc, message.c_str(), "#include", "for header name: %s", filename.c_str());
+ includer.releaseInclude(res);
+ }
+
+ return token;
+}
+
+// Handle #line
+int TPpContext::CPPline(TPpToken* ppToken)
+{
+ // "#line must have, after macro substitution, one of the following forms:
+ // "#line line
+ // "#line line source-string-number"
+
+ int token = scanToken(ppToken);
+ const TSourceLoc directiveLoc = ppToken->loc;
+ if (token == '\n') {
+ parseContext.ppError(ppToken->loc, "must by followed by an integral literal", "#line", "");
+ return token;
+ }
+
+ int lineRes = 0; // Line number after macro expansion.
+ int lineToken = 0;
+ bool hasFile = false;
+ int fileRes = 0; // Source file number after macro expansion.
+ const char* sourceName = nullptr; // Optional source file name.
+ bool lineErr = false;
+ bool fileErr = false;
+ token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken);
+ if (! lineErr) {
+ lineToken = lineRes;
+ if (token == '\n')
+ ++lineRes;
+
+ if (parseContext.lineDirectiveShouldSetNextLine())
+ --lineRes;
+ parseContext.setCurrentLine(lineRes);
+
+ if (token != '\n') {
+#ifndef GLSLANG_WEB
+ if (token == PpAtomConstString) {
+ parseContext.ppRequireExtensions(directiveLoc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based #line");
+ // We need to save a copy of the string instead of pointing
+ // to the name field of the token since the name field
+ // will likely be overwritten by the next token scan.
+ sourceName = atomStrings.getString(atomStrings.getAddAtom(ppToken->name));
+ parseContext.setCurrentSourceName(sourceName);
+ hasFile = true;
+ token = scanToken(ppToken);
+ } else
+#endif
+ {
+ token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken);
+ if (! fileErr) {
+ parseContext.setCurrentString(fileRes);
+ hasFile = true;
+ }
+ }
+ }
+ }
+ if (!fileErr && !lineErr) {
+ parseContext.notifyLineDirective(directiveLoc.line, lineToken, hasFile, fileRes, sourceName);
+ }
+ token = extraTokenCheck(PpAtomLine, ppToken, token);
+
+ return token;
+}
+
+// Handle #error
+int TPpContext::CPPerror(TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+ std::string message;
+ TSourceLoc loc = ppToken->loc;
+
+ while (token != '\n' && token != EndOfInput) {
+ if (token == PpAtomConstInt16 || token == PpAtomConstUint16 ||
+ token == PpAtomConstInt || token == PpAtomConstUint ||
+ token == PpAtomConstInt64 || token == PpAtomConstUint64 ||
+ token == PpAtomConstFloat16 ||
+ token == PpAtomConstFloat || token == PpAtomConstDouble) {
+ message.append(ppToken->name);
+ } else if (token == PpAtomIdentifier || token == PpAtomConstString) {
+ message.append(ppToken->name);
+ } else {
+ message.append(atomStrings.getString(token));
+ }
+ message.append(" ");
+ token = scanToken(ppToken);
+ }
+ parseContext.notifyErrorDirective(loc.line, message.c_str());
+ // store this msg into the shader's information log..set the Compile Error flag!!!!
+ parseContext.ppError(loc, message.c_str(), "#error", "");
+
+ return '\n';
+}
+
+// Handle #pragma
+int TPpContext::CPPpragma(TPpToken* ppToken)
+{
+ char SrcStrName[2];
+ TVector<TString> tokens;
+
+ TSourceLoc loc = ppToken->loc; // because we go to the next line before processing
+ int token = scanToken(ppToken);
+ while (token != '\n' && token != EndOfInput) {
+ switch (token) {
+ case PpAtomIdentifier:
+ case PpAtomConstInt:
+ case PpAtomConstUint:
+ case PpAtomConstInt64:
+ case PpAtomConstUint64:
+ case PpAtomConstInt16:
+ case PpAtomConstUint16:
+ case PpAtomConstFloat:
+ case PpAtomConstDouble:
+ case PpAtomConstFloat16:
+ tokens.push_back(ppToken->name);
+ break;
+ default:
+ SrcStrName[0] = (char)token;
+ SrcStrName[1] = '\0';
+ tokens.push_back(SrcStrName);
+ }
+ token = scanToken(ppToken);
+ }
+
+ if (token == EndOfInput)
+ parseContext.ppError(loc, "directive must end with a newline", "#pragma", "");
+ else
+ parseContext.handlePragma(loc, tokens);
+
+ return token;
+}
+
+// #version: This is just for error checking: the version and profile are decided before preprocessing starts
+int TPpContext::CPPversion(TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+
+ if (errorOnVersion || versionSeen) {
+ if (parseContext.isReadingHLSL())
+ parseContext.ppError(ppToken->loc, "invalid preprocessor command", "#version", "");
+ else
+ parseContext.ppError(ppToken->loc, "must occur first in shader", "#version", "");
+ }
+ versionSeen = true;
+
+ if (token == '\n') {
+ parseContext.ppError(ppToken->loc, "must be followed by version number", "#version", "");
+
+ return token;
+ }
+
+ if (token != PpAtomConstInt)
+ parseContext.ppError(ppToken->loc, "must be followed by version number", "#version", "");
+
+ ppToken->ival = atoi(ppToken->name);
+ int versionNumber = ppToken->ival;
+ int line = ppToken->loc.line;
+ token = scanToken(ppToken);
+
+ if (token == '\n') {
+ parseContext.notifyVersion(line, versionNumber, nullptr);
+ return token;
+ } else {
+ int profileAtom = atomStrings.getAtom(ppToken->name);
+ if (profileAtom != PpAtomCore &&
+ profileAtom != PpAtomCompatibility &&
+ profileAtom != PpAtomEs)
+ parseContext.ppError(ppToken->loc, "bad profile name; use es, core, or compatibility", "#version", "");
+ parseContext.notifyVersion(line, versionNumber, ppToken->name);
+ token = scanToken(ppToken);
+
+ if (token == '\n')
+ return token;
+ else
+ parseContext.ppError(ppToken->loc, "bad tokens following profile -- expected newline", "#version", "");
+ }
+
+ return token;
+}
+
+// Handle #extension
+int TPpContext::CPPextension(TPpToken* ppToken)
+{
+ int line = ppToken->loc.line;
+ int token = scanToken(ppToken);
+ char extensionName[MaxTokenLength + 1];
+
+ if (token=='\n') {
+ parseContext.ppError(ppToken->loc, "extension name not specified", "#extension", "");
+ return token;
+ }
+
+ if (token != PpAtomIdentifier)
+ parseContext.ppError(ppToken->loc, "extension name expected", "#extension", "");
+
+ snprintf(extensionName, sizeof(extensionName), "%s", ppToken->name);
+
+ token = scanToken(ppToken);
+ if (token != ':') {
+ parseContext.ppError(ppToken->loc, "':' missing after extension name", "#extension", "");
+ return token;
+ }
+
+ token = scanToken(ppToken);
+ if (token != PpAtomIdentifier) {
+ parseContext.ppError(ppToken->loc, "behavior for extension not specified", "#extension", "");
+ return token;
+ }
+
+ parseContext.updateExtensionBehavior(line, extensionName, ppToken->name);
+ parseContext.notifyExtensionDirective(line, extensionName, ppToken->name);
+
+ token = scanToken(ppToken);
+ if (token == '\n')
+ return token;
+ else
+ parseContext.ppError(ppToken->loc, "extra tokens -- expected newline", "#extension","");
+
+ return token;
+}
+
+int TPpContext::readCPPline(TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+
+ if (token == PpAtomIdentifier) {
+ switch (atomStrings.getAtom(ppToken->name)) {
+ case PpAtomDefine:
+ token = CPPdefine(ppToken);
+ break;
+ case PpAtomElse:
+ if (elseSeen[elsetracker])
+ parseContext.ppError(ppToken->loc, "#else after #else", "#else", "");
+ elseSeen[elsetracker] = true;
+ if (ifdepth == 0)
+ parseContext.ppError(ppToken->loc, "mismatched statements", "#else", "");
+ token = extraTokenCheck(PpAtomElse, ppToken, scanToken(ppToken));
+ token = CPPelse(0, ppToken);
+ break;
+ case PpAtomElif:
+ if (ifdepth == 0)
+ parseContext.ppError(ppToken->loc, "mismatched statements", "#elif", "");
+ if (elseSeen[elsetracker])
+ parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
+ // this token is really a dont care, but we still need to eat the tokens
+ token = scanToken(ppToken);
+ while (token != '\n' && token != EndOfInput)
+ token = scanToken(ppToken);
+ token = CPPelse(0, ppToken);
+ break;
+ case PpAtomEndif:
+ if (ifdepth == 0)
+ parseContext.ppError(ppToken->loc, "mismatched statements", "#endif", "");
+ else {
+ elseSeen[elsetracker] = false;
+ --elsetracker;
+ --ifdepth;
+ }
+ token = extraTokenCheck(PpAtomEndif, ppToken, scanToken(ppToken));
+ break;
+ case PpAtomIf:
+ token = CPPif(ppToken);
+ break;
+ case PpAtomIfdef:
+ token = CPPifdef(1, ppToken);
+ break;
+ case PpAtomIfndef:
+ token = CPPifdef(0, ppToken);
+ break;
+ case PpAtomLine:
+ token = CPPline(ppToken);
+ break;
+#ifndef GLSLANG_WEB
+ case PpAtomInclude:
+ if(!parseContext.isReadingHLSL()) {
+ parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_include_directive, "#include");
+ }
+ token = CPPinclude(ppToken);
+ break;
+ case PpAtomPragma:
+ token = CPPpragma(ppToken);
+ break;
+#endif
+ case PpAtomUndef:
+ token = CPPundef(ppToken);
+ break;
+ case PpAtomError:
+ token = CPPerror(ppToken);
+ break;
+ case PpAtomVersion:
+ token = CPPversion(ppToken);
+ break;
+ case PpAtomExtension:
+ token = CPPextension(ppToken);
+ break;
+ default:
+ parseContext.ppError(ppToken->loc, "invalid directive:", "#", ppToken->name);
+ break;
+ }
+ } else if (token != '\n' && token != EndOfInput)
+ parseContext.ppError(ppToken->loc, "invalid directive", "#", "");
+
+ while (token != '\n' && token != EndOfInput)
+ token = scanToken(ppToken);
+
+ return token;
+}
+
+// Context-dependent parsing of a #include <header-name>.
+// Assumes no macro expansions etc. are being done; the name is just on the current input.
+// Always creates a name and returns PpAtomicConstString, unless we run out of input.
+int TPpContext::scanHeaderName(TPpToken* ppToken, char delimit)
+{
+ bool tooLong = false;
+
+ if (inputStack.empty())
+ return EndOfInput;
+
+ int len = 0;
+ ppToken->name[0] = '\0';
+ do {
+ int ch = inputStack.back()->getch();
+
+ // done yet?
+ if (ch == delimit) {
+ ppToken->name[len] = '\0';
+ if (tooLong)
+ parseContext.ppError(ppToken->loc, "header name too long", "", "");
+ return PpAtomConstString;
+ } else if (ch == EndOfInput)
+ return EndOfInput;
+
+ // found a character to expand the name with
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ else
+ tooLong = true;
+ } while (true);
+}
+
+// Macro-expand a macro argument 'arg' to create 'expandedArg'.
+// Does not replace 'arg'.
+// Returns nullptr if no expanded argument is created.
+TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream& arg, TPpToken* ppToken, bool newLineOkay)
+{
+ // expand the argument
+ TokenStream* expandedArg = new TokenStream;
+ pushInput(new tMarkerInput(this));
+ pushTokenStreamInput(arg);
+ int token;
+ while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) {
+ token = tokenPaste(token, *ppToken);
+ if (token == PpAtomIdentifier) {
+ switch (MacroExpand(ppToken, false, newLineOkay)) {
+ case MacroExpandNotStarted:
+ break;
+ case MacroExpandError:
+ // toss the rest of the pushed-input argument by scanning until tMarkerInput
+ while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput)
+ ;
+ break;
+ case MacroExpandStarted:
+ case MacroExpandUndef:
+ continue;
+ }
+ }
+ if (token == tMarkerInput::marker || token == EndOfInput)
+ break;
+ expandedArg->putToken(token, ppToken);
+ }
+
+ if (token != tMarkerInput::marker) {
+ // Error, or MacroExpand ate the marker, so had bad input, recover
+ delete expandedArg;
+ expandedArg = nullptr;
+ }
+
+ return expandedArg;
+}
+
+//
+// Return the next token for a macro expansion, handling macro arguments,
+// whose semantics are dependent on being adjacent to ##.
+//
+int TPpContext::tMacroInput::scan(TPpToken* ppToken)
+{
+ int token;
+ do {
+ token = mac->body.getToken(pp->parseContext, ppToken);
+ } while (token == ' '); // handle white space in macro
+
+ // Hash operators basically turn off a round of macro substitution
+ // (the round done on the argument before the round done on the RHS of the
+ // macro definition):
+ //
+ // "A parameter in the replacement list, unless preceded by a # or ##
+ // preprocessing token or followed by a ## preprocessing token (see below),
+ // is replaced by the corresponding argument after all macros contained
+ // therein have been expanded."
+ //
+ // "If, in the replacement list, a parameter is immediately preceded or
+ // followed by a ## preprocessing token, the parameter is replaced by the
+ // corresponding argument's preprocessing token sequence."
+
+ bool pasting = false;
+ if (postpaste) {
+ // don't expand next token
+ pasting = true;
+ postpaste = false;
+ }
+
+ if (prepaste) {
+ // already know we should be on a ##, verify
+ assert(token == PpAtomPaste);
+ prepaste = false;
+ postpaste = true;
+ }
+
+ // see if are preceding a ##
+ if (mac->body.peekUntokenizedPasting()) {
+ prepaste = true;
+ pasting = true;
+ }
+
+ // HLSL does expand macros before concatenation
+ if (pasting && pp->parseContext.isReadingHLSL())
+ pasting = false;
+
+ // TODO: preprocessor: properly handle whitespace (or lack of it) between tokens when expanding
+ if (token == PpAtomIdentifier) {
+ int i;
+ for (i = (int)mac->args.size() - 1; i >= 0; i--)
+ if (strcmp(pp->atomStrings.getString(mac->args[i]), ppToken->name) == 0)
+ break;
+ if (i >= 0) {
+ TokenStream* arg = expandedArgs[i];
+ if (arg == nullptr || pasting)
+ arg = args[i];
+ pp->pushTokenStreamInput(*arg, prepaste);
+
+ return pp->scanToken(ppToken);
+ }
+ }
+
+ if (token == EndOfInput)
+ mac->busy = 0;
+
+ return token;
+}
+
+// return a textual zero, for scanning a macro that was never defined
+int TPpContext::tZeroInput::scan(TPpToken* ppToken)
+{
+ if (done)
+ return EndOfInput;
+
+ ppToken->name[0] = '0';
+ ppToken->name[1] = 0;
+ ppToken->ival = 0;
+ ppToken->space = false;
+ done = true;
+
+ return PpAtomConstInt;
+}
+
+//
+// Check a token to see if it is a macro that should be expanded:
+// - If it is, and defined, push a tInput that will produce the appropriate
+// expansion and return MacroExpandStarted.
+// - If it is, but undefined, and expandUndef is requested, push a tInput
+// that will expand to 0 and return MacroExpandUndef.
+// - Otherwise, there is no expansion, and there are two cases:
+// * It might be okay there is no expansion, and no specific error was
+// detected. Returns MacroExpandNotStarted.
+// * The expansion was started, but could not be completed, due to an error
+// that cannot be recovered from. Returns MacroExpandError.
+//
+MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay)
+{
+ ppToken->space = false;
+ int macroAtom = atomStrings.getAtom(ppToken->name);
+ switch (macroAtom) {
+ case PpAtomLineMacro:
+ ppToken->ival = parseContext.getCurrentLoc().line;
+ snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
+ UngetToken(PpAtomConstInt, ppToken);
+ return MacroExpandStarted;
+
+ case PpAtomFileMacro: {
+ if (parseContext.getCurrentLoc().name)
+ parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based __FILE__");
+ ppToken->ival = parseContext.getCurrentLoc().string;
+ snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str());
+ UngetToken(PpAtomConstInt, ppToken);
+ return MacroExpandStarted;
+ }
+
+ case PpAtomVersionMacro:
+ ppToken->ival = parseContext.version;
+ snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
+ UngetToken(PpAtomConstInt, ppToken);
+ return MacroExpandStarted;
+
+ default:
+ break;
+ }
+
+ MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom);
+
+ // no recursive expansions
+ if (macro != nullptr && macro->busy)
+ return MacroExpandNotStarted;
+
+ // not expanding undefined macros
+ if ((macro == nullptr || macro->undef) && ! expandUndef)
+ return MacroExpandNotStarted;
+
+ // 0 is the value of an undefined macro
+ if ((macro == nullptr || macro->undef) && expandUndef) {
+ pushInput(new tZeroInput(this));
+ return MacroExpandUndef;
+ }
+
+ tMacroInput *in = new tMacroInput(this);
+
+ TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error
+ in->mac = macro;
+ if (macro->functionLike) {
+ // We don't know yet if this will be a successful call of a
+ // function-like macro; need to look for a '(', but without trashing
+ // the passed in ppToken, until we know we are no longer speculative.
+ TPpToken parenToken;
+ int token = scanToken(&parenToken);
+ if (newLineOkay) {
+ while (token == '\n')
+ token = scanToken(&parenToken);
+ }
+ if (token != '(') {
+ // Function-like macro called with object-like syntax: okay, don't expand.
+ // (We ate exactly one token that might not be white space; put it back.
+ UngetToken(token, &parenToken);
+ delete in;
+ return MacroExpandNotStarted;
+ }
+ in->args.resize(in->mac->args.size());
+ for (size_t i = 0; i < in->mac->args.size(); i++)
+ in->args[i] = new TokenStream;
+ in->expandedArgs.resize(in->mac->args.size());
+ for (size_t i = 0; i < in->mac->args.size(); i++)
+ in->expandedArgs[i] = nullptr;
+ size_t arg = 0;
+ bool tokenRecorded = false;
+ do {
+ TVector<char> nestStack;
+ while (true) {
+ token = scanToken(ppToken);
+ if (token == EndOfInput || token == tMarkerInput::marker) {
+ parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom));
+ delete in;
+ return MacroExpandError;
+ }
+ if (token == '\n') {
+ if (! newLineOkay) {
+ parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", atomStrings.getString(macroAtom));
+ delete in;
+ return MacroExpandError;
+ }
+ continue;
+ }
+ if (token == '#') {
+ parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", atomStrings.getString(macroAtom));
+ delete in;
+ return MacroExpandError;
+ }
+ if (in->mac->args.size() == 0 && token != ')')
+ break;
+ if (nestStack.size() == 0 && (token == ',' || token == ')'))
+ break;
+ if (token == '(')
+ nestStack.push_back(')');
+ else if (token == '{' && parseContext.isReadingHLSL())
+ nestStack.push_back('}');
+ else if (nestStack.size() > 0 && token == nestStack.back())
+ nestStack.pop_back();
+ in->args[arg]->putToken(token, ppToken);
+ tokenRecorded = true;
+ }
+ // end of single argument scan
+
+ if (token == ')') {
+ // closing paren of call
+ if (in->mac->args.size() == 1 && !tokenRecorded)
+ break;
+ arg++;
+ break;
+ }
+ arg++;
+ } while (arg < in->mac->args.size());
+ // end of all arguments scan
+
+ if (arg < in->mac->args.size())
+ parseContext.ppError(loc, "Too few args in Macro", "macro expansion", atomStrings.getString(macroAtom));
+ else if (token != ')') {
+ // Error recover code; find end of call, if possible
+ int depth = 0;
+ while (token != EndOfInput && (depth > 0 || token != ')')) {
+ if (token == ')' || token == '}')
+ depth--;
+ token = scanToken(ppToken);
+ if (token == '(' || token == '{')
+ depth++;
+ }
+
+ if (token == EndOfInput) {
+ parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom));
+ delete in;
+ return MacroExpandError;
+ }
+ parseContext.ppError(loc, "Too many args in macro", "macro expansion", atomStrings.getString(macroAtom));
+ }
+
+ // We need both expanded and non-expanded forms of the argument, for whether or
+ // not token pasting will be applied later when the argument is consumed next to ##.
+ for (size_t i = 0; i < in->mac->args.size(); i++)
+ in->expandedArgs[i] = PrescanMacroArg(*in->args[i], ppToken, newLineOkay);
+ }
+
+ pushInput(in);
+ macro->busy = 1;
+ macro->body.reset();
+
+ return MacroExpandStarted;
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp
new file mode 100644
index 0000000000..06c2333ef1
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp
@@ -0,0 +1,181 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+
+#include "PpContext.h"
+#include "PpTokens.h"
+
+namespace {
+
+using namespace glslang;
+
+const struct {
+ int val;
+ const char* str;
+} tokens[] = {
+
+ { PPAtomAddAssign, "+=" },
+ { PPAtomSubAssign, "-=" },
+ { PPAtomMulAssign, "*=" },
+ { PPAtomDivAssign, "/=" },
+ { PPAtomModAssign, "%=" },
+
+ { PpAtomRight, ">>" },
+ { PpAtomLeft, "<<" },
+ { PpAtomAnd, "&&" },
+ { PpAtomOr, "||" },
+ { PpAtomXor, "^^" },
+
+ { PpAtomRightAssign, ">>=" },
+ { PpAtomLeftAssign, "<<=" },
+ { PpAtomAndAssign, "&=" },
+ { PpAtomOrAssign, "|=" },
+ { PpAtomXorAssign, "^=" },
+
+ { PpAtomEQ, "==" },
+ { PpAtomNE, "!=" },
+ { PpAtomGE, ">=" },
+ { PpAtomLE, "<=" },
+
+ { PpAtomDecrement, "--" },
+ { PpAtomIncrement, "++" },
+
+ { PpAtomColonColon, "::" },
+
+ { PpAtomDefine, "define" },
+ { PpAtomUndef, "undef" },
+ { PpAtomIf, "if" },
+ { PpAtomElif, "elif" },
+ { PpAtomElse, "else" },
+ { PpAtomEndif, "endif" },
+ { PpAtomIfdef, "ifdef" },
+ { PpAtomIfndef, "ifndef" },
+ { PpAtomLine, "line" },
+ { PpAtomPragma, "pragma" },
+ { PpAtomError, "error" },
+
+ { PpAtomVersion, "version" },
+ { PpAtomCore, "core" },
+ { PpAtomCompatibility, "compatibility" },
+ { PpAtomEs, "es" },
+ { PpAtomExtension, "extension" },
+
+ { PpAtomLineMacro, "__LINE__" },
+ { PpAtomFileMacro, "__FILE__" },
+ { PpAtomVersionMacro, "__VERSION__" },
+
+ { PpAtomInclude, "include" },
+};
+
+} // end anonymous namespace
+
+namespace glslang {
+
+//
+// Initialize the atom table.
+//
+TStringAtomMap::TStringAtomMap()
+{
+ badToken.assign("<bad token>");
+
+ // Add single character tokens to the atom table:
+ const char* s = "~!%^&*()-+=|,.<>/?;:[]{}#\\";
+ char t[2];
+
+ t[1] = '\0';
+ while (*s) {
+ t[0] = *s;
+ addAtomFixed(t, s[0]);
+ s++;
+ }
+
+ // Add multiple character scanner tokens :
+ for (size_t ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
+ addAtomFixed(tokens[ii].str, tokens[ii].val);
+
+ nextAtom = PpAtomLast;
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp
new file mode 100755
index 0000000000..cc003a8d12
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp
@@ -0,0 +1,119 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#include <cstdlib>
+#include <locale>
+
+#include "PpContext.h"
+
+namespace glslang {
+
+TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) :
+ preamble(0), strings(0), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false),
+ rootFileName(rootFileName),
+ currentSourceFile(rootFileName)
+{
+ ifdepth = 0;
+ for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++)
+ elseSeen[elsetracker] = false;
+ elsetracker = 0;
+
+ strtodStream.imbue(std::locale::classic());
+}
+
+TPpContext::~TPpContext()
+{
+ delete [] preamble;
+
+ // free up the inputStack
+ while (! inputStack.empty())
+ popInput();
+}
+
+void TPpContext::setInput(TInputScanner& input, bool versionWillBeError)
+{
+ assert(inputStack.size() == 0);
+
+ pushInput(new tStringInput(this, input));
+
+ errorOnVersion = versionWillBeError;
+ versionSeen = false;
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h
new file mode 100644
index 0000000000..8470e172a2
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h
@@ -0,0 +1,702 @@
+//
+// Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef PPCONTEXT_H
+#define PPCONTEXT_H
+
+#include <stack>
+#include <unordered_map>
+#include <sstream>
+
+#include "../ParseHelper.h"
+#include "PpTokens.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+ #pragma warning(disable : 4127)
+#endif
+
+namespace glslang {
+
+class TPpToken {
+public:
+ TPpToken() { clear(); }
+ void clear()
+ {
+ space = false;
+ i64val = 0;
+ loc.init();
+ name[0] = 0;
+ }
+
+ // Used for comparing macro definitions, so checks what is relevant for that.
+ bool operator==(const TPpToken& right)
+ {
+ return space == right.space &&
+ ival == right.ival && dval == right.dval && i64val == right.i64val &&
+ strncmp(name, right.name, MaxTokenLength) == 0;
+ }
+ bool operator!=(const TPpToken& right) { return ! operator==(right); }
+
+ TSourceLoc loc;
+ // True if a space (for white space or a removed comment) should also be
+ // recognized, in front of the token returned:
+ bool space;
+ // Numeric value of the token:
+ union {
+ int ival;
+ double dval;
+ long long i64val;
+ };
+ // Text string of the token:
+ char name[MaxTokenLength + 1];
+};
+
+class TStringAtomMap {
+//
+// Implementation is in PpAtom.cpp
+//
+// Maintain a bi-directional mapping between relevant preprocessor strings and
+// "atoms" which a unique integers (small, contiguous, not hash-like) per string.
+//
+public:
+ TStringAtomMap();
+
+ // Map string -> atom.
+ // Return 0 if no existing string.
+ int getAtom(const char* s) const
+ {
+ auto it = atomMap.find(s);
+ return it == atomMap.end() ? 0 : it->second;
+ }
+
+ // Map a new or existing string -> atom, inventing a new atom if necessary.
+ int getAddAtom(const char* s)
+ {
+ int atom = getAtom(s);
+ if (atom == 0) {
+ atom = nextAtom++;
+ addAtomFixed(s, atom);
+ }
+ return atom;
+ }
+
+ // Map atom -> string.
+ const char* getString(int atom) const { return stringMap[atom]->c_str(); }
+
+protected:
+ TStringAtomMap(TStringAtomMap&);
+ TStringAtomMap& operator=(TStringAtomMap&);
+
+ TUnorderedMap<TString, int> atomMap;
+ TVector<const TString*> stringMap; // these point into the TString in atomMap
+ int nextAtom;
+
+ // Bad source characters can lead to bad atoms, so gracefully handle those by
+ // pre-filling the table with them (to avoid if tests later).
+ TString badToken;
+
+ // Add bi-directional mappings:
+ // - string -> atom
+ // - atom -> string
+ void addAtomFixed(const char* s, int atom)
+ {
+ auto it = atomMap.insert(std::pair<TString, int>(s, atom)).first;
+ if (stringMap.size() < (size_t)atom + 1)
+ stringMap.resize(atom + 100, &badToken);
+ stringMap[atom] = &it->first;
+ }
+};
+
+class TInputScanner;
+
+enum MacroExpandResult {
+ MacroExpandNotStarted, // macro not expanded, which might not be an error
+ MacroExpandError, // a clear error occurred while expanding, no expansion
+ MacroExpandStarted, // macro expansion process has started
+ MacroExpandUndef // macro is undefined and will be expanded
+};
+
+// This class is the result of turning a huge pile of C code communicating through globals
+// into a class. This was done to allowing instancing to attain thread safety.
+// Don't expect too much in terms of OO design.
+class TPpContext {
+public:
+ TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&);
+ virtual ~TPpContext();
+
+ void setPreamble(const char* preamble, size_t length);
+
+ int tokenize(TPpToken& ppToken);
+ int tokenPaste(int token, TPpToken&);
+
+ class tInput {
+ public:
+ tInput(TPpContext* p) : done(false), pp(p) { }
+ virtual ~tInput() { }
+
+ virtual int scan(TPpToken*) = 0;
+ virtual int getch() = 0;
+ virtual void ungetch() = 0;
+ virtual bool peekPasting() { return false; } // true when about to see ##
+ virtual bool peekContinuedPasting(int) { return false; } // true when non-spaced tokens can paste
+ virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define)
+ virtual bool isMacroInput() { return false; }
+
+ // Will be called when we start reading tokens from this instance
+ virtual void notifyActivated() {}
+ // Will be called when we do not read tokens from this instance anymore
+ virtual void notifyDeleted() {}
+ protected:
+ bool done;
+ TPpContext* pp;
+ };
+
+ void setInput(TInputScanner& input, bool versionWillBeError);
+
+ void pushInput(tInput* in)
+ {
+ inputStack.push_back(in);
+ in->notifyActivated();
+ }
+ void popInput()
+ {
+ inputStack.back()->notifyDeleted();
+ delete inputStack.back();
+ inputStack.pop_back();
+ }
+
+ //
+ // From PpTokens.cpp
+ //
+
+ // Capture the needed parts of a token stream for macro recording/playback.
+ class TokenStream {
+ public:
+ // Manage a stream of these 'Token', which capture the relevant parts
+ // of a TPpToken, plus its atom.
+ class Token {
+ public:
+ Token(int atom, const TPpToken& ppToken) :
+ atom(atom),
+ space(ppToken.space),
+ i64val(ppToken.i64val),
+ name(ppToken.name) { }
+ int get(TPpToken& ppToken)
+ {
+ ppToken.clear();
+ ppToken.space = space;
+ ppToken.i64val = i64val;
+ snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str());
+ return atom;
+ }
+ bool isAtom(int a) const { return atom == a; }
+ int getAtom() const { return atom; }
+ bool nonSpaced() const { return !space; }
+ protected:
+ Token() {}
+ int atom;
+ bool space; // did a space precede the token?
+ long long i64val;
+ TString name;
+ };
+
+ TokenStream() : currentPos(0) { }
+
+ void putToken(int token, TPpToken* ppToken);
+ bool peekToken(int atom) { return !atEnd() && stream[currentPos].isAtom(atom); }
+ bool peekContinuedPasting(int atom)
+ {
+ // This is basically necessary because, for example, the PP
+ // tokenizer only accepts valid numeric-literals plus suffixes, so
+ // separates numeric-literals plus bad suffix into two tokens, which
+ // should get both pasted together as one token when token pasting.
+ //
+ // The following code is a bit more generalized than the above example.
+ if (!atEnd() && atom == PpAtomIdentifier && stream[currentPos].nonSpaced()) {
+ switch(stream[currentPos].getAtom()) {
+ case PpAtomConstInt:
+ case PpAtomConstUint:
+ case PpAtomConstInt64:
+ case PpAtomConstUint64:
+ case PpAtomConstInt16:
+ case PpAtomConstUint16:
+ case PpAtomConstFloat:
+ case PpAtomConstDouble:
+ case PpAtomConstFloat16:
+ case PpAtomConstString:
+ case PpAtomIdentifier:
+ return true;
+ default:
+ break;
+ }
+ }
+
+ return false;
+ }
+ int getToken(TParseContextBase&, TPpToken*);
+ bool atEnd() { return currentPos >= stream.size(); }
+ bool peekTokenizedPasting(bool lastTokenPastes);
+ bool peekUntokenizedPasting();
+ void reset() { currentPos = 0; }
+
+ protected:
+ TVector<Token> stream;
+ size_t currentPos;
+ };
+
+ //
+ // From Pp.cpp
+ //
+
+ struct MacroSymbol {
+ MacroSymbol() : functionLike(0), busy(0), undef(0) { }
+ TVector<int> args;
+ TokenStream body;
+ unsigned functionLike : 1; // 0 means object-like, 1 means function-like
+ unsigned busy : 1;
+ unsigned undef : 1;
+ };
+
+ typedef TMap<int, MacroSymbol> TSymbolMap;
+ TSymbolMap macroDefs; // map atoms to macro definitions
+ MacroSymbol* lookupMacroDef(int atom)
+ {
+ auto existingMacroIt = macroDefs.find(atom);
+ return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second);
+ }
+ void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; }
+
+protected:
+ TPpContext(TPpContext&);
+ TPpContext& operator=(TPpContext&);
+
+ TStringAtomMap atomStrings;
+ char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble
+ int preambleLength;
+ char** strings; // official strings of shader, starting a string 0 line 1
+ size_t* lengths;
+ int numStrings; // how many official strings there are
+ int currentString; // which string we're currently parsing (-1 for preamble)
+
+ // Scanner data:
+ int previous_token;
+ TParseContextBase& parseContext;
+
+ // Get the next token from *stack* of input sources, popping input sources
+ // that are out of tokens, down until an input source is found that has a token.
+ // Return EndOfInput when there are no more tokens to be found by doing this.
+ int scanToken(TPpToken* ppToken)
+ {
+ int token = EndOfInput;
+
+ while (! inputStack.empty()) {
+ token = inputStack.back()->scan(ppToken);
+ if (token != EndOfInput || inputStack.empty())
+ break;
+ popInput();
+ }
+
+ return token;
+ }
+ int getChar() { return inputStack.back()->getch(); }
+ void ungetChar() { inputStack.back()->ungetch(); }
+ bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); }
+ bool peekContinuedPasting(int a)
+ {
+ return !inputStack.empty() && inputStack.back()->peekContinuedPasting(a);
+ }
+ bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
+ bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }
+
+ static const int maxIfNesting = 65;
+
+ int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor)
+ bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth
+ int elsetracker; // #if-#else and #endif constructs...Counter.
+
+ class tMacroInput : public tInput {
+ public:
+ tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { }
+ virtual ~tMacroInput()
+ {
+ for (size_t i = 0; i < args.size(); ++i)
+ delete args[i];
+ for (size_t i = 0; i < expandedArgs.size(); ++i)
+ delete expandedArgs[i];
+ }
+
+ virtual int scan(TPpToken*) override;
+ virtual int getch() override { assert(0); return EndOfInput; }
+ virtual void ungetch() override { assert(0); }
+ bool peekPasting() override { return prepaste; }
+ bool peekContinuedPasting(int a) override { return mac->body.peekContinuedPasting(a); }
+ bool endOfReplacementList() override { return mac->body.atEnd(); }
+ bool isMacroInput() override { return true; }
+
+ MacroSymbol *mac;
+ TVector<TokenStream*> args;
+ TVector<TokenStream*> expandedArgs;
+
+ protected:
+ bool prepaste; // true if we are just before ##
+ bool postpaste; // true if we are right after ##
+ };
+
+ class tMarkerInput : public tInput {
+ public:
+ tMarkerInput(TPpContext* pp) : tInput(pp) { }
+ virtual int scan(TPpToken*) override
+ {
+ if (done)
+ return EndOfInput;
+ done = true;
+
+ return marker;
+ }
+ virtual int getch() override { assert(0); return EndOfInput; }
+ virtual void ungetch() override { assert(0); }
+ static const int marker = -3;
+ };
+
+ class tZeroInput : public tInput {
+ public:
+ tZeroInput(TPpContext* pp) : tInput(pp) { }
+ virtual int scan(TPpToken*) override;
+ virtual int getch() override { assert(0); return EndOfInput; }
+ virtual void ungetch() override { assert(0); }
+ };
+
+ std::vector<tInput*> inputStack;
+ bool errorOnVersion;
+ bool versionSeen;
+
+ //
+ // from Pp.cpp
+ //
+
+ // Used to obtain #include content.
+ TShader::Includer& includer;
+
+ int CPPdefine(TPpToken * ppToken);
+ int CPPundef(TPpToken * ppToken);
+ int CPPelse(int matchelse, TPpToken * ppToken);
+ int extraTokenCheck(int atom, TPpToken* ppToken, int token);
+ int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
+ int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
+ int CPPif (TPpToken * ppToken);
+ int CPPifdef(int defined, TPpToken * ppToken);
+ int CPPinclude(TPpToken * ppToken);
+ int CPPline(TPpToken * ppToken);
+ int CPPerror(TPpToken * ppToken);
+ int CPPpragma(TPpToken * ppToken);
+ int CPPversion(TPpToken * ppToken);
+ int CPPextension(TPpToken * ppToken);
+ int readCPPline(TPpToken * ppToken);
+ int scanHeaderName(TPpToken* ppToken, char delimit);
+ TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
+ MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
+
+ //
+ // From PpTokens.cpp
+ //
+ void pushTokenStreamInput(TokenStream&, bool pasting = false);
+ void UngetToken(int token, TPpToken*);
+
+ class tTokenInput : public tInput {
+ public:
+ tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) :
+ tInput(pp),
+ tokens(t),
+ lastTokenPastes(prepasting) { }
+ virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); }
+ virtual int getch() override { assert(0); return EndOfInput; }
+ virtual void ungetch() override { assert(0); }
+ virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); }
+ bool peekContinuedPasting(int a) override { return tokens->peekContinuedPasting(a); }
+ protected:
+ TokenStream* tokens;
+ bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token
+ };
+
+ class tUngotTokenInput : public tInput {
+ public:
+ tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { }
+ virtual int scan(TPpToken *) override;
+ virtual int getch() override { assert(0); return EndOfInput; }
+ virtual void ungetch() override { assert(0); }
+ protected:
+ int token;
+ TPpToken lval;
+ };
+
+ //
+ // From PpScanner.cpp
+ //
+ class tStringInput : public tInput {
+ public:
+ tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { }
+ virtual int scan(TPpToken*) override;
+
+ // Scanner used to get source stream characters.
+ // - Escaped newlines are handled here, invisibly to the caller.
+ // - All forms of newline are handled, and turned into just a '\n'.
+ int getch() override
+ {
+ int ch = input->get();
+
+ if (ch == '\\') {
+ // Move past escaped newlines, as many as sequentially exist
+ do {
+ if (input->peek() == '\r' || input->peek() == '\n') {
+ bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment);
+ if (! allowed && pp->inComment)
+ return '\\';
+
+ // escape one newline now
+ ch = input->get();
+ int nextch = input->get();
+ if (ch == '\r' && nextch == '\n')
+ ch = input->get();
+ else
+ ch = nextch;
+ } else
+ return '\\';
+ } while (ch == '\\');
+ }
+
+ // handle any non-escaped newline
+ if (ch == '\r' || ch == '\n') {
+ if (ch == '\r' && input->peek() == '\n')
+ input->get();
+ return '\n';
+ }
+
+ return ch;
+ }
+
+ // Scanner used to backup the source stream characters. Newlines are
+ // handled here, invisibly to the caller, meaning have to undo exactly
+ // what getch() above does (e.g., don't leave things in the middle of a
+ // sequence of escaped newlines).
+ void ungetch() override
+ {
+ input->unget();
+
+ do {
+ int ch = input->peek();
+ if (ch == '\r' || ch == '\n') {
+ if (ch == '\n') {
+ // correct for two-character newline
+ input->unget();
+ if (input->peek() != '\r')
+ input->get();
+ }
+ // now in front of a complete newline, move past an escape character
+ input->unget();
+ if (input->peek() == '\\')
+ input->unget();
+ else {
+ input->get();
+ break;
+ }
+ } else
+ break;
+ } while (true);
+ }
+
+ protected:
+ TInputScanner* input;
+ };
+
+ // Holds a reference to included file data, as well as a
+ // prologue and an epilogue string. This can be scanned using the tInput
+ // interface and acts as a single source string.
+ class TokenizableIncludeFile : public tInput {
+ public:
+ // Copies prologue and epilogue. The includedFile must remain valid
+ // until this TokenizableIncludeFile is no longer used.
+ TokenizableIncludeFile(const TSourceLoc& startLoc,
+ const std::string& prologue,
+ TShader::Includer::IncludeResult* includedFile,
+ const std::string& epilogue,
+ TPpContext* pp)
+ : tInput(pp),
+ prologue_(prologue),
+ epilogue_(epilogue),
+ includedFile_(includedFile),
+ scanner(3, strings, lengths, nullptr, 0, 0, true),
+ prevScanner(nullptr),
+ stringInput(pp, scanner)
+ {
+ strings[0] = prologue_.data();
+ strings[1] = includedFile_->headerData;
+ strings[2] = epilogue_.data();
+
+ lengths[0] = prologue_.size();
+ lengths[1] = includedFile_->headerLength;
+ lengths[2] = epilogue_.size();
+
+ scanner.setLine(startLoc.line);
+ scanner.setString(startLoc.string);
+
+ scanner.setFile(startLoc.getFilenameStr(), 0);
+ scanner.setFile(startLoc.getFilenameStr(), 1);
+ scanner.setFile(startLoc.getFilenameStr(), 2);
+ }
+
+ // tInput methods:
+ int scan(TPpToken* t) override { return stringInput.scan(t); }
+ int getch() override { return stringInput.getch(); }
+ void ungetch() override { stringInput.ungetch(); }
+
+ void notifyActivated() override
+ {
+ prevScanner = pp->parseContext.getScanner();
+ pp->parseContext.setScanner(&scanner);
+ pp->push_include(includedFile_);
+ }
+
+ void notifyDeleted() override
+ {
+ pp->parseContext.setScanner(prevScanner);
+ pp->pop_include();
+ }
+
+ private:
+ TokenizableIncludeFile& operator=(const TokenizableIncludeFile&);
+
+ // Stores the prologue for this string.
+ const std::string prologue_;
+
+ // Stores the epilogue for this string.
+ const std::string epilogue_;
+
+ // Points to the IncludeResult that this TokenizableIncludeFile represents.
+ TShader::Includer::IncludeResult* includedFile_;
+
+ // Will point to prologue_, includedFile_->headerData and epilogue_
+ // This is passed to scanner constructor.
+ // These do not own the storage and it must remain valid until this
+ // object has been destroyed.
+ const char* strings[3];
+ // Length of str_, passed to scanner constructor.
+ size_t lengths[3];
+ // Scans over str_.
+ TInputScanner scanner;
+ // The previous effective scanner before the scanner in this instance
+ // has been activated.
+ TInputScanner* prevScanner;
+ // Delegate object implementing the tInput interface.
+ tStringInput stringInput;
+ };
+
+ int ScanFromString(char* s);
+ void missingEndifCheck();
+ int lFloatConst(int len, int ch, TPpToken* ppToken);
+ int characterLiteral(TPpToken* ppToken);
+
+ void push_include(TShader::Includer::IncludeResult* result)
+ {
+ currentSourceFile = result->headerName;
+ includeStack.push(result);
+ }
+
+ void pop_include()
+ {
+ TShader::Includer::IncludeResult* include = includeStack.top();
+ includeStack.pop();
+ includer.releaseInclude(include);
+ if (includeStack.empty()) {
+ currentSourceFile = rootFileName;
+ } else {
+ currentSourceFile = includeStack.top()->headerName;
+ }
+ }
+
+ bool inComment;
+ std::string rootFileName;
+ std::stack<TShader::Includer::IncludeResult*> includeStack;
+ std::string currentSourceFile;
+
+ std::istringstream strtodStream;
+};
+
+} // end namespace glslang
+
+#endif // PPCONTEXT_H
diff --git a/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp
new file mode 100755
index 0000000000..c293af3c1e
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp
@@ -0,0 +1,1245 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2017 ARM Limited.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include <cstdlib>
+#include <cstring>
+
+#include "PpContext.h"
+#include "PpTokens.h"
+#include "../Scan.h"
+
+namespace glslang {
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Floating point constants: /////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+//
+// Scan a single- or double-precision floating point constant.
+// Assumes that the scanner has seen at least one digit,
+// followed by either a decimal '.' or the letter 'e', or a
+// precision ending (e.g., F or LF).
+//
+// This is technically not correct, as the preprocessor should just
+// accept the numeric literal along with whatever suffix it has, but
+// currently, it stops on seeing a bad suffix, treating that as the
+// next token. This effects things like token pasting, where it is
+// relevant how many tokens something was broken into.
+//
+// See peekContinuedPasting().
+int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
+{
+ const auto saveName = [&](int ch) {
+ if (len <= MaxTokenLength)
+ ppToken->name[len++] = static_cast<char>(ch);
+ };
+
+ // find the range of non-zero digits before the decimal point
+ int startNonZero = 0;
+ while (startNonZero < len && ppToken->name[startNonZero] == '0')
+ ++startNonZero;
+ int endNonZero = len;
+ while (endNonZero > startNonZero && ppToken->name[endNonZero-1] == '0')
+ --endNonZero;
+ int numWholeNumberDigits = endNonZero - startNonZero;
+
+ // accumulate the range's value
+ bool fastPath = numWholeNumberDigits <= 15; // when the number gets too complex, set to false
+ unsigned long long wholeNumber = 0;
+ if (fastPath) {
+ for (int i = startNonZero; i < endNonZero; ++i)
+ wholeNumber = wholeNumber * 10 + (ppToken->name[i] - '0');
+ }
+ int decimalShift = len - endNonZero;
+
+ // Decimal point:
+ bool hasDecimalOrExponent = false;
+ if (ch == '.') {
+ hasDecimalOrExponent = true;
+ saveName(ch);
+ ch = getChar();
+ int firstDecimal = len;
+
+#ifdef ENABLE_HLSL
+ // 1.#INF or -1.#INF
+ if (ch == '#' && (ifdepth > 0 || parseContext.intermediate.getSource() == EShSourceHlsl)) {
+ if ((len < 2) ||
+ (len == 2 && ppToken->name[0] != '1') ||
+ (len == 3 && ppToken->name[1] != '1' && !(ppToken->name[0] == '-' || ppToken->name[0] == '+')) ||
+ (len > 3))
+ parseContext.ppError(ppToken->loc, "unexpected use of", "#", "");
+ else {
+ // we have 1.# or -1.# or +1.#, check for 'INF'
+ if ((ch = getChar()) != 'I' ||
+ (ch = getChar()) != 'N' ||
+ (ch = getChar()) != 'F')
+ parseContext.ppError(ppToken->loc, "expected 'INF'", "#", "");
+ else {
+ // we have [+-].#INF, and we are targeting IEEE 754, so wrap it up:
+ saveName('I');
+ saveName('N');
+ saveName('F');
+ ppToken->name[len] = '\0';
+ if (ppToken->name[0] == '-')
+ ppToken->i64val = 0xfff0000000000000; // -Infinity
+ else
+ ppToken->i64val = 0x7ff0000000000000; // +Infinity
+ return PpAtomConstFloat;
+ }
+ }
+ }
+#endif
+
+ // Consume leading-zero digits after the decimal point
+ while (ch == '0') {
+ saveName(ch);
+ ch = getChar();
+ }
+ int startNonZeroDecimal = len;
+ int endNonZeroDecimal = len;
+
+ // Consume remaining digits, up to the exponent
+ while (ch >= '0' && ch <= '9') {
+ saveName(ch);
+ if (ch != '0')
+ endNonZeroDecimal = len;
+ ch = getChar();
+ }
+
+ // Compute accumulation up to the last non-zero digit
+ if (endNonZeroDecimal > startNonZeroDecimal) {
+ numWholeNumberDigits += endNonZeroDecimal - endNonZero - 1; // don't include the "."
+ if (numWholeNumberDigits > 15)
+ fastPath = false;
+ if (fastPath) {
+ for (int i = endNonZero; i < endNonZeroDecimal; ++i) {
+ if (ppToken->name[i] != '.')
+ wholeNumber = wholeNumber * 10 + (ppToken->name[i] - '0');
+ }
+ }
+ decimalShift = firstDecimal - endNonZeroDecimal;
+ }
+ }
+
+ // Exponent:
+ bool negativeExponent = false;
+ double exponentValue = 0.0;
+ int exponent = 0;
+ {
+ if (ch == 'e' || ch == 'E') {
+ hasDecimalOrExponent = true;
+ saveName(ch);
+ ch = getChar();
+ if (ch == '+' || ch == '-') {
+ negativeExponent = ch == '-';
+ saveName(ch);
+ ch = getChar();
+ }
+ if (ch >= '0' && ch <= '9') {
+ while (ch >= '0' && ch <= '9') {
+ exponent = exponent * 10 + (ch - '0');
+ saveName(ch);
+ ch = getChar();
+ }
+ } else {
+ parseContext.ppError(ppToken->loc, "bad character in float exponent", "", "");
+ }
+ }
+
+ // Compensate for location of decimal
+ if (negativeExponent)
+ exponent -= decimalShift;
+ else {
+ exponent += decimalShift;
+ if (exponent < 0) {
+ negativeExponent = true;
+ exponent = -exponent;
+ }
+ }
+ if (exponent > 22)
+ fastPath = false;
+
+ if (fastPath) {
+ // Compute the floating-point value of the exponent
+ exponentValue = 1.0;
+ if (exponent > 0) {
+ double expFactor = 10;
+ while (exponent > 0) {
+ if (exponent & 0x1)
+ exponentValue *= expFactor;
+ expFactor *= expFactor;
+ exponent >>= 1;
+ }
+ }
+ }
+ }
+
+ // Suffix:
+ bool isDouble = false;
+ bool isFloat16 = false;
+#ifndef GLSLANG_WEB
+ if (ch == 'l' || ch == 'L') {
+ if (ifdepth == 0 && parseContext.intermediate.getSource() == EShSourceGlsl)
+ parseContext.doubleCheck(ppToken->loc, "double floating-point suffix");
+ if (ifdepth == 0 && !hasDecimalOrExponent)
+ parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
+ if (parseContext.intermediate.getSource() == EShSourceGlsl) {
+ int ch2 = getChar();
+ if (ch2 != 'f' && ch2 != 'F') {
+ ungetChar();
+ ungetChar();
+ } else {
+ saveName(ch);
+ saveName(ch2);
+ isDouble = true;
+ }
+ } else if (parseContext.intermediate.getSource() == EShSourceHlsl) {
+ saveName(ch);
+ isDouble = true;
+ }
+ } else if (ch == 'h' || ch == 'H') {
+ if (ifdepth == 0 && parseContext.intermediate.getSource() == EShSourceGlsl)
+ parseContext.float16Check(ppToken->loc, "half floating-point suffix");
+ if (ifdepth == 0 && !hasDecimalOrExponent)
+ parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
+ if (parseContext.intermediate.getSource() == EShSourceGlsl) {
+ int ch2 = getChar();
+ if (ch2 != 'f' && ch2 != 'F') {
+ ungetChar();
+ ungetChar();
+ } else {
+ saveName(ch);
+ saveName(ch2);
+ isFloat16 = true;
+ }
+ } else if (parseContext.intermediate.getSource() == EShSourceHlsl) {
+ saveName(ch);
+ isFloat16 = true;
+ }
+ } else
+#endif
+ if (ch == 'f' || ch == 'F') {
+#ifndef GLSLANG_WEB
+ if (ifdepth == 0)
+ parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix");
+ if (ifdepth == 0 && !parseContext.relaxedErrors())
+ parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix");
+#endif
+ if (ifdepth == 0 && !hasDecimalOrExponent)
+ parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
+ saveName(ch);
+ } else
+ ungetChar();
+
+ // Patch up the name and length for overflow
+
+ if (len > MaxTokenLength) {
+ len = MaxTokenLength;
+ parseContext.ppError(ppToken->loc, "float literal too long", "", "");
+ }
+ ppToken->name[len] = '\0';
+
+ // Compute the numerical value
+ if (fastPath) {
+ // compute the floating-point value of the exponent
+ if (exponentValue == 0.0)
+ ppToken->dval = (double)wholeNumber;
+ else if (negativeExponent)
+ ppToken->dval = (double)wholeNumber / exponentValue;
+ else
+ ppToken->dval = (double)wholeNumber * exponentValue;
+ } else {
+ // slow path
+ ppToken->dval = 0.0;
+
+ // remove suffix
+ TString numstr(ppToken->name);
+ if (numstr.back() == 'f' || numstr.back() == 'F')
+ numstr.pop_back();
+ if (numstr.back() == 'h' || numstr.back() == 'H')
+ numstr.pop_back();
+ if (numstr.back() == 'l' || numstr.back() == 'L')
+ numstr.pop_back();
+
+ // use platform library
+ strtodStream.clear();
+ strtodStream.str(numstr.c_str());
+ strtodStream >> ppToken->dval;
+ if (strtodStream.fail()) {
+ // Assume failure combined with a large exponent was overflow, in
+ // an attempt to set INF.
+ if (!negativeExponent && exponent + numWholeNumberDigits > 300)
+ ppToken->i64val = 0x7ff0000000000000; // +Infinity
+ // Assume failure combined with a small exponent was overflow.
+ if (negativeExponent && exponent + numWholeNumberDigits > 300)
+ ppToken->dval = 0.0;
+ // Unknown reason for failure. Theory is that either
+ // - the 0.0 is still there, or
+ // - something reasonable was written that is better than 0.0
+ }
+ }
+
+ // Return the right token type
+ if (isDouble)
+ return PpAtomConstDouble;
+ else if (isFloat16)
+ return PpAtomConstFloat16;
+ else
+ return PpAtomConstFloat;
+}
+
+// Recognize a character literal.
+//
+// The first ' has already been accepted, read the rest, through the closing '.
+//
+// Always returns PpAtomConstInt.
+//
+int TPpContext::characterLiteral(TPpToken* ppToken)
+{
+ ppToken->name[0] = 0;
+ ppToken->ival = 0;
+
+ if (parseContext.intermediate.getSource() != EShSourceHlsl) {
+ // illegal, except in macro definition, for which case we report the character
+ return '\'';
+ }
+
+ int ch = getChar();
+ switch (ch) {
+ case '\'':
+ // As empty sequence: ''
+ parseContext.ppError(ppToken->loc, "unexpected", "\'", "");
+ return PpAtomConstInt;
+ case '\\':
+ // As escape sequence: '\XXX'
+ switch (ch = getChar()) {
+ case 'a':
+ ppToken->ival = 7;
+ break;
+ case 'b':
+ ppToken->ival = 8;
+ break;
+ case 't':
+ ppToken->ival = 9;
+ break;
+ case 'n':
+ ppToken->ival = 10;
+ break;
+ case 'v':
+ ppToken->ival = 11;
+ break;
+ case 'f':
+ ppToken->ival = 12;
+ break;
+ case 'r':
+ ppToken->ival = 13;
+ break;
+ case 'x':
+ case '0':
+ parseContext.ppError(ppToken->loc, "octal and hex sequences not supported", "\\", "");
+ break;
+ default:
+ // This catches '\'', '\"', '\?', etc.
+ // Also, things like '\C' mean the same thing as 'C'
+ // (after the above cases are filtered out).
+ ppToken->ival = ch;
+ break;
+ }
+ break;
+ default:
+ ppToken->ival = ch;
+ break;
+ }
+ ppToken->name[0] = (char)ppToken->ival;
+ ppToken->name[1] = '\0';
+ ch = getChar();
+ if (ch != '\'') {
+ parseContext.ppError(ppToken->loc, "expected", "\'", "");
+ // Look ahead for a closing '
+ do {
+ ch = getChar();
+ } while (ch != '\'' && ch != EndOfInput && ch != '\n');
+ }
+
+ return PpAtomConstInt;
+}
+
+//
+// Scanner used to tokenize source stream.
+//
+// N.B. Invalid numeric suffixes are not consumed.//
+// This is technically not correct, as the preprocessor should just
+// accept the numeric literal along with whatever suffix it has, but
+// currently, it stops on seeing a bad suffix, treating that as the
+// next token. This effects things like token pasting, where it is
+// relevant how many tokens something was broken into.
+// See peekContinuedPasting().
+//
+int TPpContext::tStringInput::scan(TPpToken* ppToken)
+{
+ int AlreadyComplained = 0;
+ int len = 0;
+ int ch = 0;
+ int ii = 0;
+ unsigned long long ival = 0;
+ const auto floatingPointChar = [&](int ch) { return ch == '.' || ch == 'e' || ch == 'E' ||
+ ch == 'f' || ch == 'F' ||
+ ch == 'h' || ch == 'H'; };
+
+ static const char* const Int64_Extensions[] = {
+ E_GL_ARB_gpu_shader_int64,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int64 };
+ static const int Num_Int64_Extensions = sizeof(Int64_Extensions) / sizeof(Int64_Extensions[0]);
+
+ static const char* const Int16_Extensions[] = {
+ E_GL_AMD_gpu_shader_int16,
+ E_GL_EXT_shader_explicit_arithmetic_types,
+ E_GL_EXT_shader_explicit_arithmetic_types_int16 };
+ static const int Num_Int16_Extensions = sizeof(Int16_Extensions) / sizeof(Int16_Extensions[0]);
+
+ ppToken->ival = 0;
+ ppToken->i64val = 0;
+ ppToken->space = false;
+ ch = getch();
+ for (;;) {
+ while (ch == ' ' || ch == '\t') {
+ ppToken->space = true;
+ ch = getch();
+ }
+
+ ppToken->loc = pp->parseContext.getCurrentLoc();
+ len = 0;
+ switch (ch) {
+ default:
+ // Single character token, including EndOfInput, '#' and '\' (escaped newlines are handled at a lower level, so this is just a '\' token)
+ if (ch > PpAtomMaxSingle)
+ ch = PpAtomBadToken;
+ return ch;
+
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y':
+ case 'Z': case '_':
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y':
+ case 'z':
+ do {
+ if (len < MaxTokenLength) {
+ ppToken->name[len++] = (char)ch;
+ ch = getch();
+ } else {
+ if (! AlreadyComplained) {
+ pp->parseContext.ppError(ppToken->loc, "name too long", "", "");
+ AlreadyComplained = 1;
+ }
+ ch = getch();
+ }
+ } while ((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ ch == '_');
+
+ // line continuation with no token before or after makes len == 0, and need to start over skipping white space, etc.
+ if (len == 0)
+ continue;
+
+ ppToken->name[len] = '\0';
+ ungetch();
+ return PpAtomIdentifier;
+ case '0':
+ ppToken->name[len++] = (char)ch;
+ ch = getch();
+ if (ch == 'x' || ch == 'X') {
+ // must be hexadecimal
+
+ bool isUnsigned = false;
+ bool isInt64 = false;
+ bool isInt16 = false;
+ ppToken->name[len++] = (char)ch;
+ ch = getch();
+ if ((ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'F') ||
+ (ch >= 'a' && ch <= 'f')) {
+
+ ival = 0;
+ do {
+ if (len < MaxTokenLength && ival <= 0x0fffffffffffffffull) {
+ ppToken->name[len++] = (char)ch;
+ if (ch >= '0' && ch <= '9') {
+ ii = ch - '0';
+ } else if (ch >= 'A' && ch <= 'F') {
+ ii = ch - 'A' + 10;
+ } else if (ch >= 'a' && ch <= 'f') {
+ ii = ch - 'a' + 10;
+ } else
+ pp->parseContext.ppError(ppToken->loc, "bad digit in hexadecimal literal", "", "");
+ ival = (ival << 4) | ii;
+ } else {
+ if (! AlreadyComplained) {
+ if(len < MaxTokenLength)
+ pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too big", "", "");
+ else
+ pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too long", "", "");
+ AlreadyComplained = 1;
+ }
+ ival = 0xffffffffffffffffull;
+ }
+ ch = getch();
+ } while ((ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'F') ||
+ (ch >= 'a' && ch <= 'f'));
+ } else {
+ pp->parseContext.ppError(ppToken->loc, "bad digit in hexadecimal literal", "", "");
+ }
+ if (ch == 'u' || ch == 'U') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isUnsigned = true;
+
+#ifndef GLSLANG_WEB
+ int nextCh = getch();
+ if (nextCh == 'l' || nextCh == 'L') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)nextCh;
+ isInt64 = true;
+ } else
+ ungetch();
+
+ nextCh = getch();
+ if ((nextCh == 's' || nextCh == 'S') &&
+ pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)nextCh;
+ isInt16 = true;
+ } else
+ ungetch();
+ } else if (ch == 'l' || ch == 'L') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isInt64 = true;
+ } else if ((ch == 's' || ch == 'S') &&
+ pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isInt16 = true;
+#endif
+ } else
+ ungetch();
+ ppToken->name[len] = '\0';
+
+ if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ if (pp->ifdepth == 0) {
+ pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+ "64-bit hexadecimal literal");
+ pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+ Num_Int64_Extensions, Int64_Extensions, "64-bit hexadecimal literal");
+ }
+ ppToken->i64val = ival;
+ return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
+ } else if (isInt16) {
+ if (pp->ifdepth == 0) {
+ if (pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+ "16-bit hexadecimal literal");
+ pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+ Num_Int16_Extensions, Int16_Extensions, "16-bit hexadecimal literal");
+ }
+ }
+ ppToken->ival = (int)ival;
+ return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
+ } else {
+ if (ival > 0xffffffffu && !AlreadyComplained)
+ pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too big", "", "");
+ ppToken->ival = (int)ival;
+ return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
+ }
+ } else {
+ // could be octal integer or floating point, speculative pursue octal until it must be floating point
+
+ bool isUnsigned = false;
+ bool isInt64 = false;
+ bool isInt16 = false;
+ bool octalOverflow = false;
+ bool nonOctal = false;
+ ival = 0;
+
+ // see how much octal-like stuff we can read
+ while (ch >= '0' && ch <= '7') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ else if (! AlreadyComplained) {
+ pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", "");
+ AlreadyComplained = 1;
+ }
+ if (ival <= 0x1fffffffffffffffull) {
+ ii = ch - '0';
+ ival = (ival << 3) | ii;
+ } else
+ octalOverflow = true;
+ ch = getch();
+ }
+
+ // could be part of a float...
+ if (ch == '8' || ch == '9') {
+ nonOctal = true;
+ do {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ else if (! AlreadyComplained) {
+ pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", "");
+ AlreadyComplained = 1;
+ }
+ ch = getch();
+ } while (ch >= '0' && ch <= '9');
+ }
+ if (floatingPointChar(ch))
+ return pp->lFloatConst(len, ch, ppToken);
+
+ // wasn't a float, so must be octal...
+ if (nonOctal)
+ pp->parseContext.ppError(ppToken->loc, "octal literal digit too large", "", "");
+
+ if (ch == 'u' || ch == 'U') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isUnsigned = true;
+
+#ifndef GLSLANG_WEB
+ int nextCh = getch();
+ if (nextCh == 'l' || nextCh == 'L') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)nextCh;
+ isInt64 = true;
+ } else
+ ungetch();
+
+ nextCh = getch();
+ if ((nextCh == 's' || nextCh == 'S') &&
+ pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)nextCh;
+ isInt16 = true;
+ } else
+ ungetch();
+ } else if (ch == 'l' || ch == 'L') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isInt64 = true;
+ } else if ((ch == 's' || ch == 'S') &&
+ pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isInt16 = true;
+#endif
+ } else
+ ungetch();
+ ppToken->name[len] = '\0';
+
+ if (!isInt64 && ival > 0xffffffffu)
+ octalOverflow = true;
+
+ if (octalOverflow)
+ pp->parseContext.ppError(ppToken->loc, "octal literal too big", "", "");
+
+ if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ if (pp->ifdepth == 0) {
+ pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+ "64-bit octal literal");
+ pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+ Num_Int64_Extensions, Int64_Extensions, "64-bit octal literal");
+ }
+ ppToken->i64val = ival;
+ return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
+ } else if (isInt16) {
+ if (pp->ifdepth == 0) {
+ if (pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+ "16-bit octal literal");
+ pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+ Num_Int16_Extensions, Int16_Extensions, "16-bit octal literal");
+ }
+ }
+ ppToken->ival = (int)ival;
+ return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
+ } else {
+ ppToken->ival = (int)ival;
+ return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
+ }
+ }
+ break;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ // can't be hexadecimal or octal, is either decimal or floating point
+
+ do {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ else if (! AlreadyComplained) {
+ pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", "");
+ AlreadyComplained = 1;
+ }
+ ch = getch();
+ } while (ch >= '0' && ch <= '9');
+ if (floatingPointChar(ch))
+ return pp->lFloatConst(len, ch, ppToken);
+ else {
+ // Finish handling signed and unsigned integers
+ int numericLen = len;
+ bool isUnsigned = false;
+ bool isInt64 = false;
+ bool isInt16 = false;
+ if (ch == 'u' || ch == 'U') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isUnsigned = true;
+
+#ifndef GLSLANG_WEB
+ int nextCh = getch();
+ if (nextCh == 'l' || nextCh == 'L') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)nextCh;
+ isInt64 = true;
+ } else
+ ungetch();
+
+ nextCh = getch();
+ if ((nextCh == 's' || nextCh == 'S') &&
+ pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)nextCh;
+ isInt16 = true;
+ } else
+ ungetch();
+ } else if (ch == 'l' || ch == 'L') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isInt64 = true;
+ } else if ((ch == 's' || ch == 'S') &&
+ pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isInt16 = true;
+#endif
+ } else
+ ungetch();
+
+ ppToken->name[len] = '\0';
+ ival = 0;
+ const unsigned oneTenthMaxInt = 0xFFFFFFFFu / 10;
+ const unsigned remainderMaxInt = 0xFFFFFFFFu - 10 * oneTenthMaxInt;
+ const unsigned long long oneTenthMaxInt64 = 0xFFFFFFFFFFFFFFFFull / 10;
+ const unsigned long long remainderMaxInt64 = 0xFFFFFFFFFFFFFFFFull - 10 * oneTenthMaxInt64;
+ const unsigned short oneTenthMaxInt16 = 0xFFFFu / 10;
+ const unsigned short remainderMaxInt16 = 0xFFFFu - 10 * oneTenthMaxInt16;
+ for (int i = 0; i < numericLen; i++) {
+ ch = ppToken->name[i] - '0';
+ bool overflow = false;
+ if (isInt64)
+ overflow = (ival > oneTenthMaxInt64 || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64));
+ else if (isInt16)
+ overflow = (ival > oneTenthMaxInt16 || (ival == oneTenthMaxInt16 && (unsigned short)ch > remainderMaxInt16));
+ else
+ overflow = (ival > oneTenthMaxInt || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt));
+ if (overflow) {
+ pp->parseContext.ppError(ppToken->loc, "numeric literal too big", "", "");
+ ival = 0xFFFFFFFFFFFFFFFFull;
+ break;
+ } else
+ ival = ival * 10 + ch;
+ }
+
+ if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ if (pp->ifdepth == 0) {
+ pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+ "64-bit literal");
+ pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+ Num_Int64_Extensions, Int64_Extensions, "64-bit literal");
+ }
+ ppToken->i64val = ival;
+ return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
+ } else if (isInt16) {
+ if (pp->ifdepth == 0 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) {
+ pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile,
+ "16-bit literal");
+ pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0,
+ Num_Int16_Extensions, Int16_Extensions, "16-bit literal");
+ }
+ ppToken->ival = (int)ival;
+ return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
+ } else {
+ ppToken->ival = (int)ival;
+ return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
+ }
+ }
+ break;
+ case '-':
+ ch = getch();
+ if (ch == '-') {
+ return PpAtomDecrement;
+ } else if (ch == '=') {
+ return PPAtomSubAssign;
+ } else {
+ ungetch();
+ return '-';
+ }
+ case '+':
+ ch = getch();
+ if (ch == '+') {
+ return PpAtomIncrement;
+ } else if (ch == '=') {
+ return PPAtomAddAssign;
+ } else {
+ ungetch();
+ return '+';
+ }
+ case '*':
+ ch = getch();
+ if (ch == '=') {
+ return PPAtomMulAssign;
+ } else {
+ ungetch();
+ return '*';
+ }
+ case '%':
+ ch = getch();
+ if (ch == '=') {
+ return PPAtomModAssign;
+ } else {
+ ungetch();
+ return '%';
+ }
+ case '^':
+ ch = getch();
+ if (ch == '^') {
+ return PpAtomXor;
+ } else {
+ if (ch == '=')
+ return PpAtomXorAssign;
+ else{
+ ungetch();
+ return '^';
+ }
+ }
+
+ case '=':
+ ch = getch();
+ if (ch == '=') {
+ return PpAtomEQ;
+ } else {
+ ungetch();
+ return '=';
+ }
+ case '!':
+ ch = getch();
+ if (ch == '=') {
+ return PpAtomNE;
+ } else {
+ ungetch();
+ return '!';
+ }
+ case '|':
+ ch = getch();
+ if (ch == '|') {
+ return PpAtomOr;
+ } else if (ch == '=') {
+ return PpAtomOrAssign;
+ } else {
+ ungetch();
+ return '|';
+ }
+ case '&':
+ ch = getch();
+ if (ch == '&') {
+ return PpAtomAnd;
+ } else if (ch == '=') {
+ return PpAtomAndAssign;
+ } else {
+ ungetch();
+ return '&';
+ }
+ case '<':
+ ch = getch();
+ if (ch == '<') {
+ ch = getch();
+ if (ch == '=')
+ return PpAtomLeftAssign;
+ else {
+ ungetch();
+ return PpAtomLeft;
+ }
+ } else if (ch == '=') {
+ return PpAtomLE;
+ } else {
+ ungetch();
+ return '<';
+ }
+ case '>':
+ ch = getch();
+ if (ch == '>') {
+ ch = getch();
+ if (ch == '=')
+ return PpAtomRightAssign;
+ else {
+ ungetch();
+ return PpAtomRight;
+ }
+ } else if (ch == '=') {
+ return PpAtomGE;
+ } else {
+ ungetch();
+ return '>';
+ }
+ case '.':
+ ch = getch();
+ if (ch >= '0' && ch <= '9') {
+ ungetch();
+ return pp->lFloatConst(0, '.', ppToken);
+ } else {
+ ungetch();
+ return '.';
+ }
+ case '/':
+ ch = getch();
+ if (ch == '/') {
+ pp->inComment = true;
+ do {
+ ch = getch();
+ } while (ch != '\n' && ch != EndOfInput);
+ ppToken->space = true;
+ pp->inComment = false;
+
+ return ch;
+ } else if (ch == '*') {
+ ch = getch();
+ do {
+ while (ch != '*') {
+ if (ch == EndOfInput) {
+ pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", "");
+ return ch;
+ }
+ ch = getch();
+ }
+ ch = getch();
+ if (ch == EndOfInput) {
+ pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", "");
+ return ch;
+ }
+ } while (ch != '/');
+ ppToken->space = true;
+ // loop again to get the next token...
+ break;
+ } else if (ch == '=') {
+ return PPAtomDivAssign;
+ } else {
+ ungetch();
+ return '/';
+ }
+ break;
+ case '\'':
+ return pp->characterLiteral(ppToken);
+ case '"':
+ // TODO: If this gets enhanced to handle escape sequences, or
+ // anything that is different than what #include needs, then
+ // #include needs to use scanHeaderName() for this.
+ ch = getch();
+ while (ch != '"' && ch != '\n' && ch != EndOfInput) {
+ if (len < MaxTokenLength) {
+ ppToken->name[len] = (char)ch;
+ len++;
+ ch = getch();
+ } else
+ break;
+ };
+ ppToken->name[len] = '\0';
+ if (ch != '"') {
+ ungetch();
+ pp->parseContext.ppError(ppToken->loc, "End of line in string", "string", "");
+ }
+ return PpAtomConstString;
+ case ':':
+ ch = getch();
+ if (ch == ':')
+ return PpAtomColonColon;
+ ungetch();
+ return ':';
+ }
+
+ ch = getch();
+ }
+}
+
+//
+// The main functional entry point into the preprocessor, which will
+// scan the source strings to figure out and return the next processing token.
+//
+// Return the token, or EndOfInput when no more tokens.
+//
+int TPpContext::tokenize(TPpToken& ppToken)
+{
+ for(;;) {
+ int token = scanToken(&ppToken);
+
+ // Handle token-pasting logic
+ token = tokenPaste(token, ppToken);
+
+ if (token == EndOfInput) {
+ missingEndifCheck();
+ return EndOfInput;
+ }
+ if (token == '#') {
+ if (previous_token == '\n') {
+ token = readCPPline(&ppToken);
+ if (token == EndOfInput) {
+ missingEndifCheck();
+ return EndOfInput;
+ }
+ continue;
+ } else {
+ parseContext.ppError(ppToken.loc, "preprocessor directive cannot be preceded by another token", "#", "");
+ return EndOfInput;
+ }
+ }
+ previous_token = token;
+
+ if (token == '\n')
+ continue;
+
+ // expand macros
+ if (token == PpAtomIdentifier) {
+ switch (MacroExpand(&ppToken, false, true)) {
+ case MacroExpandNotStarted:
+ break;
+ case MacroExpandError:
+ return EndOfInput;
+ case MacroExpandStarted:
+ case MacroExpandUndef:
+ continue;
+ }
+ }
+
+ switch (token) {
+ case PpAtomIdentifier:
+ case PpAtomConstInt:
+ case PpAtomConstUint:
+ case PpAtomConstFloat:
+ case PpAtomConstInt64:
+ case PpAtomConstUint64:
+ case PpAtomConstInt16:
+ case PpAtomConstUint16:
+ case PpAtomConstDouble:
+ case PpAtomConstFloat16:
+ if (ppToken.name[0] == '\0')
+ continue;
+ break;
+ case PpAtomConstString:
+ if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) {
+ // HLSL allows string literals.
+ parseContext.ppError(ppToken.loc, "string literals not supported", "\"\"", "");
+ continue;
+ }
+ break;
+ case '\'':
+ parseContext.ppError(ppToken.loc, "character literals not supported", "\'", "");
+ continue;
+ default:
+ snprintf(ppToken.name, sizeof(ppToken.name), "%s", atomStrings.getString(token));
+ break;
+ }
+
+ return token;
+ }
+}
+
+//
+// Do all token-pasting related combining of two pasted tokens when getting a
+// stream of tokens from a replacement list. Degenerates to no processing if a
+// replacement list is not the source of the token stream.
+//
+int TPpContext::tokenPaste(int token, TPpToken& ppToken)
+{
+ // starting with ## is illegal, skip to next token
+ if (token == PpAtomPaste) {
+ parseContext.ppError(ppToken.loc, "unexpected location", "##", "");
+ return scanToken(&ppToken);
+ }
+
+ int resultToken = token; // "foo" pasted with "35" is an identifier, not a number
+
+ // ## can be chained, process all in the chain at once
+ while (peekPasting()) {
+ TPpToken pastedPpToken;
+
+ // next token has to be ##
+ token = scanToken(&pastedPpToken);
+ assert(token == PpAtomPaste);
+
+ // This covers end of macro expansion
+ if (endOfReplacementList()) {
+ parseContext.ppError(ppToken.loc, "unexpected location; end of replacement list", "##", "");
+ break;
+ }
+
+ // Get the token(s) after the ##.
+ // Because of "space" semantics, and prior tokenization, what
+ // appeared a single token, e.g. "3A", might have been tokenized
+ // into two tokens "3" and "A", but the "A" will have 'space' set to
+ // false. Accumulate all of these to recreate the original lexical
+ // appearing token.
+ do {
+ token = scanToken(&pastedPpToken);
+
+ // This covers end of argument expansion
+ if (token == tMarkerInput::marker) {
+ parseContext.ppError(ppToken.loc, "unexpected location; end of argument", "##", "");
+ return resultToken;
+ }
+
+ // get the token text
+ switch (resultToken) {
+ case PpAtomIdentifier:
+ // already have the correct text in token.names
+ break;
+ case '=':
+ case '!':
+ case '-':
+ case '~':
+ case '+':
+ case '*':
+ case '/':
+ case '%':
+ case '<':
+ case '>':
+ case '|':
+ case '^':
+ case '&':
+ case PpAtomRight:
+ case PpAtomLeft:
+ case PpAtomAnd:
+ case PpAtomOr:
+ case PpAtomXor:
+ snprintf(ppToken.name, sizeof(ppToken.name), "%s", atomStrings.getString(resultToken));
+ snprintf(pastedPpToken.name, sizeof(pastedPpToken.name), "%s", atomStrings.getString(token));
+ break;
+ default:
+ parseContext.ppError(ppToken.loc, "not supported for these tokens", "##", "");
+ return resultToken;
+ }
+
+ // combine the tokens
+ if (strlen(ppToken.name) + strlen(pastedPpToken.name) > MaxTokenLength) {
+ parseContext.ppError(ppToken.loc, "combined tokens are too long", "##", "");
+ return resultToken;
+ }
+ snprintf(&ppToken.name[0] + strlen(ppToken.name), sizeof(ppToken.name) - strlen(ppToken.name),
+ "%s", pastedPpToken.name);
+
+ // correct the kind of token we are making, if needed (identifiers stay identifiers)
+ if (resultToken != PpAtomIdentifier) {
+ int newToken = atomStrings.getAtom(ppToken.name);
+ if (newToken > 0)
+ resultToken = newToken;
+ else
+ parseContext.ppError(ppToken.loc, "combined token is invalid", "##", "");
+ }
+ } while (peekContinuedPasting(resultToken));
+ }
+
+ return resultToken;
+}
+
+// Checks if we've seen balanced #if...#endif
+void TPpContext::missingEndifCheck()
+{
+ if (ifdepth > 0)
+ parseContext.ppError(parseContext.getCurrentLoc(), "missing #endif", "", "");
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp
new file mode 100755
index 0000000000..7ed58703f2
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp
@@ -0,0 +1,221 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+//
+// For recording and playing back the stream of tokens in a macro definition.
+//
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
+#define snprintf sprintf_s
+#endif
+
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+
+#include "PpContext.h"
+#include "PpTokens.h"
+
+namespace glslang {
+
+// Add a token (including backing string) to the end of a macro
+// token stream, for later playback.
+void TPpContext::TokenStream::putToken(int atom, TPpToken* ppToken)
+{
+ TokenStream::Token streamToken(atom, *ppToken);
+ stream.push_back(streamToken);
+}
+
+// Read the next token from a macro token stream.
+int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken *ppToken)
+{
+ if (atEnd())
+ return EndOfInput;
+
+ int atom = stream[currentPos++].get(*ppToken);
+ ppToken->loc = parseContext.getCurrentLoc();
+
+#ifndef GLSLANG_WEB
+ // Check for ##, unless the current # is the last character
+ if (atom == '#') {
+ if (peekToken('#')) {
+ parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)");
+ parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)");
+ currentPos++;
+ atom = PpAtomPaste;
+ }
+ }
+#endif
+
+ return atom;
+}
+
+// We are pasting if
+// 1. we are preceding a pasting operator within this stream
+// or
+// 2. the entire macro is preceding a pasting operator (lastTokenPastes)
+// and we are also on the last token
+bool TPpContext::TokenStream::peekTokenizedPasting(bool lastTokenPastes)
+{
+ // 1. preceding ##?
+
+ size_t savePos = currentPos;
+ // skip white space
+ while (peekToken(' '))
+ ++currentPos;
+ if (peekToken(PpAtomPaste)) {
+ currentPos = savePos;
+ return true;
+ }
+
+ // 2. last token and we've been told after this there will be a ##
+
+ if (! lastTokenPastes)
+ return false;
+ // Getting here means the last token will be pasted, after this
+
+ // Are we at the last non-whitespace token?
+ savePos = currentPos;
+ bool moreTokens = false;
+ do {
+ if (atEnd())
+ break;
+ if (!peekToken(' ')) {
+ moreTokens = true;
+ break;
+ }
+ ++currentPos;
+ } while (true);
+ currentPos = savePos;
+
+ return !moreTokens;
+}
+
+// See if the next non-white-space tokens are two consecutive #
+bool TPpContext::TokenStream::peekUntokenizedPasting()
+{
+ // don't return early, have to restore this
+ size_t savePos = currentPos;
+
+ // skip white-space
+ while (peekToken(' '))
+ ++currentPos;
+
+ // check for ##
+ bool pasting = false;
+ if (peekToken('#')) {
+ ++currentPos;
+ if (peekToken('#'))
+ pasting = true;
+ }
+
+ currentPos = savePos;
+
+ return pasting;
+}
+
+void TPpContext::pushTokenStreamInput(TokenStream& ts, bool prepasting)
+{
+ pushInput(new tTokenInput(this, &ts, prepasting));
+ ts.reset();
+}
+
+int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken)
+{
+ if (done)
+ return EndOfInput;
+
+ int ret = token;
+ *ppToken = lval;
+ done = true;
+
+ return ret;
+}
+
+void TPpContext::UngetToken(int token, TPpToken* ppToken)
+{
+ pushInput(new tUngotTokenInput(this, token, ppToken));
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h
new file mode 100644
index 0000000000..7b0f815500
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h
@@ -0,0 +1,179 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef PARSER_H
+#define PARSER_H
+
+namespace glslang {
+
+// Multi-character tokens
+enum EFixedAtoms {
+ // single character tokens get their own char value as their token; start here for multi-character tokens
+ PpAtomMaxSingle = 127,
+
+ // replace bad character tokens with this, to avoid accidental aliasing with the below
+ PpAtomBadToken,
+
+ // Operators
+
+ PPAtomAddAssign,
+ PPAtomSubAssign,
+ PPAtomMulAssign,
+ PPAtomDivAssign,
+ PPAtomModAssign,
+
+ PpAtomRight,
+ PpAtomLeft,
+
+ PpAtomRightAssign,
+ PpAtomLeftAssign,
+ PpAtomAndAssign,
+ PpAtomOrAssign,
+ PpAtomXorAssign,
+
+ PpAtomAnd,
+ PpAtomOr,
+ PpAtomXor,
+
+ PpAtomEQ,
+ PpAtomNE,
+ PpAtomGE,
+ PpAtomLE,
+
+ PpAtomDecrement,
+ PpAtomIncrement,
+
+ PpAtomColonColon,
+
+ PpAtomPaste,
+
+ // Constants
+
+ PpAtomConstInt,
+ PpAtomConstUint,
+ PpAtomConstInt64,
+ PpAtomConstUint64,
+ PpAtomConstInt16,
+ PpAtomConstUint16,
+ PpAtomConstFloat,
+ PpAtomConstDouble,
+ PpAtomConstFloat16,
+ PpAtomConstString,
+
+ // Identifiers
+ PpAtomIdentifier,
+
+ // preprocessor "keywords"
+
+ PpAtomDefine,
+ PpAtomUndef,
+
+ PpAtomIf,
+ PpAtomIfdef,
+ PpAtomIfndef,
+ PpAtomElse,
+ PpAtomElif,
+ PpAtomEndif,
+
+ PpAtomLine,
+ PpAtomPragma,
+ PpAtomError,
+
+ // #version ...
+ PpAtomVersion,
+ PpAtomCore,
+ PpAtomCompatibility,
+ PpAtomEs,
+
+ // #extension
+ PpAtomExtension,
+
+ // __LINE__, __FILE__, __VERSION__
+
+ PpAtomLineMacro,
+ PpAtomFileMacro,
+ PpAtomVersionMacro,
+
+ // #include
+ PpAtomInclude,
+
+ PpAtomLast,
+};
+
+} // end namespace glslang
+
+#endif /* not PARSER_H */
diff --git a/thirdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp b/thirdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp
new file mode 100644
index 0000000000..83a3230f51
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp
@@ -0,0 +1,870 @@
+//
+// Copyright (C) 2015-2016 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Visit the nodes in the glslang intermediate tree representation to
+// propagate the 'noContraction' qualifier.
+//
+
+#ifndef GLSLANG_WEB
+
+#include "propagateNoContraction.h"
+
+#include <cstdlib>
+#include <string>
+#include <tuple>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "localintermediate.h"
+namespace {
+
+// Use a string to hold the access chain information, as in most cases the
+// access chain is short and may contain only one element, which is the symbol
+// ID.
+// Example: struct {float a; float b;} s;
+// Object s.a will be represented with: <symbol ID of s>/0
+// Object s.b will be represented with: <symbol ID of s>/1
+// Object s will be represented with: <symbol ID of s>
+// For members of vector, matrix and arrays, they will be represented with the
+// same symbol ID of their container symbol objects. This is because their
+// preciseness is always the same as their container symbol objects.
+typedef std::string ObjectAccessChain;
+
+// The delimiter used in the ObjectAccessChain string to separate symbol ID and
+// different level of struct indices.
+const char ObjectAccesschainDelimiter = '/';
+
+// Mapping from Symbol IDs of symbol nodes, to their defining operation
+// nodes.
+typedef std::unordered_multimap<ObjectAccessChain, glslang::TIntermOperator*> NodeMapping;
+// Mapping from object nodes to their access chain info string.
+typedef std::unordered_map<glslang::TIntermTyped*, ObjectAccessChain> AccessChainMapping;
+
+// Set of object IDs.
+typedef std::unordered_set<ObjectAccessChain> ObjectAccesschainSet;
+// Set of return branch nodes.
+typedef std::unordered_set<glslang::TIntermBranch*> ReturnBranchNodeSet;
+
+// A helper function to tell whether a node is 'noContraction'. Returns true if
+// the node has 'noContraction' qualifier, otherwise false.
+bool isPreciseObjectNode(glslang::TIntermTyped* node)
+{
+ return node->getType().getQualifier().isNoContraction();
+}
+
+// Returns true if the opcode is a dereferencing one.
+bool isDereferenceOperation(glslang::TOperator op)
+{
+ switch (op) {
+ case glslang::EOpIndexDirect:
+ case glslang::EOpIndexDirectStruct:
+ case glslang::EOpIndexIndirect:
+ case glslang::EOpVectorSwizzle:
+ case glslang::EOpMatrixSwizzle:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Returns true if the opcode leads to an assignment operation.
+bool isAssignOperation(glslang::TOperator op)
+{
+ switch (op) {
+ case glslang::EOpAssign:
+ case glslang::EOpAddAssign:
+ case glslang::EOpSubAssign:
+ case glslang::EOpMulAssign:
+ case glslang::EOpVectorTimesMatrixAssign:
+ case glslang::EOpVectorTimesScalarAssign:
+ case glslang::EOpMatrixTimesScalarAssign:
+ case glslang::EOpMatrixTimesMatrixAssign:
+ case glslang::EOpDivAssign:
+ case glslang::EOpModAssign:
+ case glslang::EOpAndAssign:
+ case glslang::EOpLeftShiftAssign:
+ case glslang::EOpRightShiftAssign:
+ case glslang::EOpInclusiveOrAssign:
+ case glslang::EOpExclusiveOrAssign:
+
+ case glslang::EOpPostIncrement:
+ case glslang::EOpPostDecrement:
+ case glslang::EOpPreIncrement:
+ case glslang::EOpPreDecrement:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// A helper function to get the unsigned int from a given constant union node.
+// Note the node should only hold a uint scalar.
+unsigned getStructIndexFromConstantUnion(glslang::TIntermTyped* node)
+{
+ assert(node->getAsConstantUnion() && node->getAsConstantUnion()->isScalar());
+ unsigned struct_dereference_index = node->getAsConstantUnion()->getConstArray()[0].getUConst();
+ return struct_dereference_index;
+}
+
+// A helper function to generate symbol_label.
+ObjectAccessChain generateSymbolLabel(glslang::TIntermSymbol* node)
+{
+ ObjectAccessChain symbol_id =
+ std::to_string(node->getId()) + "(" + node->getName().c_str() + ")";
+ return symbol_id;
+}
+
+// Returns true if the operation is an arithmetic operation and valid for
+// the 'NoContraction' decoration.
+bool isArithmeticOperation(glslang::TOperator op)
+{
+ switch (op) {
+ case glslang::EOpAddAssign:
+ case glslang::EOpSubAssign:
+ case glslang::EOpMulAssign:
+ case glslang::EOpVectorTimesMatrixAssign:
+ case glslang::EOpVectorTimesScalarAssign:
+ case glslang::EOpMatrixTimesScalarAssign:
+ case glslang::EOpMatrixTimesMatrixAssign:
+ case glslang::EOpDivAssign:
+ case glslang::EOpModAssign:
+
+ case glslang::EOpNegative:
+
+ case glslang::EOpAdd:
+ case glslang::EOpSub:
+ case glslang::EOpMul:
+ case glslang::EOpDiv:
+ case glslang::EOpMod:
+
+ case glslang::EOpVectorTimesScalar:
+ case glslang::EOpVectorTimesMatrix:
+ case glslang::EOpMatrixTimesVector:
+ case glslang::EOpMatrixTimesScalar:
+ case glslang::EOpMatrixTimesMatrix:
+
+ case glslang::EOpDot:
+
+ case glslang::EOpPostIncrement:
+ case glslang::EOpPostDecrement:
+ case glslang::EOpPreIncrement:
+ case glslang::EOpPreDecrement:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// A helper class to help manage the populating_initial_no_contraction_ flag.
+template <typename T> class StateSettingGuard {
+public:
+ StateSettingGuard(T* state_ptr, T new_state_value)
+ : state_ptr_(state_ptr), previous_state_(*state_ptr)
+ {
+ *state_ptr = new_state_value;
+ }
+ StateSettingGuard(T* state_ptr) : state_ptr_(state_ptr), previous_state_(*state_ptr) {}
+ void setState(T new_state_value) { *state_ptr_ = new_state_value; }
+ ~StateSettingGuard() { *state_ptr_ = previous_state_; }
+
+private:
+ T* state_ptr_;
+ T previous_state_;
+};
+
+// A helper function to get the front element from a given ObjectAccessChain
+ObjectAccessChain getFrontElement(const ObjectAccessChain& chain)
+{
+ size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter);
+ return pos_delimiter == std::string::npos ? chain : chain.substr(0, pos_delimiter);
+}
+
+// A helper function to get the access chain starting from the second element.
+ObjectAccessChain subAccessChainFromSecondElement(const ObjectAccessChain& chain)
+{
+ size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter);
+ return pos_delimiter == std::string::npos ? "" : chain.substr(pos_delimiter + 1);
+}
+
+// A helper function to get the access chain after removing a given prefix.
+ObjectAccessChain getSubAccessChainAfterPrefix(const ObjectAccessChain& chain,
+ const ObjectAccessChain& prefix)
+{
+ size_t pos = chain.find(prefix);
+ if (pos != 0)
+ return chain;
+ return chain.substr(prefix.length() + sizeof(ObjectAccesschainDelimiter));
+}
+
+//
+// A traverser which traverses the whole AST and populates:
+// 1) A mapping from symbol nodes' IDs to their defining operation nodes.
+// 2) A set of access chains of the initial precise object nodes.
+//
+class TSymbolDefinitionCollectingTraverser : public glslang::TIntermTraverser {
+public:
+ TSymbolDefinitionCollectingTraverser(NodeMapping* symbol_definition_mapping,
+ AccessChainMapping* accesschain_mapping,
+ ObjectAccesschainSet* precise_objects,
+ ReturnBranchNodeSet* precise_return_nodes);
+
+ bool visitUnary(glslang::TVisit, glslang::TIntermUnary*) override;
+ bool visitBinary(glslang::TVisit, glslang::TIntermBinary*) override;
+ void visitSymbol(glslang::TIntermSymbol*) override;
+ bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*) override;
+ bool visitBranch(glslang::TVisit, glslang::TIntermBranch*) override;
+
+protected:
+ TSymbolDefinitionCollectingTraverser& operator=(const TSymbolDefinitionCollectingTraverser&);
+
+ // The mapping from symbol node IDs to their defining nodes. This should be
+ // populated along traversing the AST.
+ NodeMapping& symbol_definition_mapping_;
+ // The set of symbol node IDs for precise symbol nodes, the ones marked as
+ // 'noContraction'.
+ ObjectAccesschainSet& precise_objects_;
+ // The set of precise return nodes.
+ ReturnBranchNodeSet& precise_return_nodes_;
+ // A temporary cache of the symbol node whose defining node is to be found
+ // currently along traversing the AST.
+ ObjectAccessChain current_object_;
+ // A map from object node to its access chain. This traverser stores
+ // the built access chains into this map for each object node it has
+ // visited.
+ AccessChainMapping& accesschain_mapping_;
+ // The pointer to the Function Definition node, so we can get the
+ // preciseness of the return expression from it when we traverse the
+ // return branch node.
+ glslang::TIntermAggregate* current_function_definition_node_;
+};
+
+TSymbolDefinitionCollectingTraverser::TSymbolDefinitionCollectingTraverser(
+ NodeMapping* symbol_definition_mapping, AccessChainMapping* accesschain_mapping,
+ ObjectAccesschainSet* precise_objects,
+ std::unordered_set<glslang::TIntermBranch*>* precise_return_nodes)
+ : TIntermTraverser(true, false, false), symbol_definition_mapping_(*symbol_definition_mapping),
+ precise_objects_(*precise_objects), precise_return_nodes_(*precise_return_nodes),
+ current_object_(), accesschain_mapping_(*accesschain_mapping),
+ current_function_definition_node_(nullptr) {}
+
+// Visits a symbol node, set the current_object_ to the
+// current node symbol ID, and record a mapping from this node to the current
+// current_object_, which is the just obtained symbol
+// ID.
+void TSymbolDefinitionCollectingTraverser::visitSymbol(glslang::TIntermSymbol* node)
+{
+ current_object_ = generateSymbolLabel(node);
+ accesschain_mapping_[node] = current_object_;
+}
+
+// Visits an aggregate node, traverses all of its children.
+bool TSymbolDefinitionCollectingTraverser::visitAggregate(glslang::TVisit,
+ glslang::TIntermAggregate* node)
+{
+ // This aggregate node might be a function definition node, in which case we need to
+ // cache this node, so we can get the preciseness information of the return value
+ // of this function later.
+ StateSettingGuard<glslang::TIntermAggregate*> current_function_definition_node_setting_guard(
+ &current_function_definition_node_);
+ if (node->getOp() == glslang::EOpFunction) {
+ // This is function definition node, we need to cache this node so that we can
+ // get the preciseness of the return value later.
+ current_function_definition_node_setting_guard.setState(node);
+ }
+ // Traverse the items in the sequence.
+ glslang::TIntermSequence& seq = node->getSequence();
+ for (int i = 0; i < (int)seq.size(); ++i) {
+ current_object_.clear();
+ seq[i]->traverse(this);
+ }
+ return false;
+}
+
+bool TSymbolDefinitionCollectingTraverser::visitBranch(glslang::TVisit,
+ glslang::TIntermBranch* node)
+{
+ if (node->getFlowOp() == glslang::EOpReturn && node->getExpression() &&
+ current_function_definition_node_ &&
+ current_function_definition_node_->getType().getQualifier().noContraction) {
+ // This node is a return node with an expression, and its function has a
+ // precise return value. We need to find the involved objects in its
+ // expression and add them to the set of initial precise objects.
+ precise_return_nodes_.insert(node);
+ node->getExpression()->traverse(this);
+ }
+ return false;
+}
+
+// Visits a unary node. This might be an implicit assignment like i++, i--. etc.
+bool TSymbolDefinitionCollectingTraverser::visitUnary(glslang::TVisit /* visit */,
+ glslang::TIntermUnary* node)
+{
+ current_object_.clear();
+ node->getOperand()->traverse(this);
+ if (isAssignOperation(node->getOp())) {
+ // We should always be able to get an access chain of the operand node.
+ assert(!current_object_.empty());
+
+ // If the operand node object is 'precise', we collect its access chain
+ // for the initial set of 'precise' objects.
+ if (isPreciseObjectNode(node->getOperand())) {
+ // The operand node is an 'precise' object node, add its
+ // access chain to the set of 'precise' objects. This is to collect
+ // the initial set of 'precise' objects.
+ precise_objects_.insert(current_object_);
+ }
+ // Gets the symbol ID from the object's access chain.
+ ObjectAccessChain id_symbol = getFrontElement(current_object_);
+ // Add a mapping from the symbol ID to this assignment operation node.
+ symbol_definition_mapping_.insert(std::make_pair(id_symbol, node));
+ }
+ // A unary node is not a dereference node, so we clear the access chain which
+ // is under construction.
+ current_object_.clear();
+ return false;
+}
+
+// Visits a binary node and updates the mapping from symbol IDs to the definition
+// nodes. Also collects the access chains for the initial precise objects.
+bool TSymbolDefinitionCollectingTraverser::visitBinary(glslang::TVisit /* visit */,
+ glslang::TIntermBinary* node)
+{
+ // Traverses the left node to build the access chain info for the object.
+ current_object_.clear();
+ node->getLeft()->traverse(this);
+
+ if (isAssignOperation(node->getOp())) {
+ // We should always be able to get an access chain for the left node.
+ assert(!current_object_.empty());
+
+ // If the left node object is 'precise', it is an initial precise object
+ // specified in the shader source. Adds it to the initial work list to
+ // process later.
+ if (isPreciseObjectNode(node->getLeft())) {
+ // The left node is an 'precise' object node, add its access chain to
+ // the set of 'precise' objects. This is to collect the initial set
+ // of 'precise' objects.
+ precise_objects_.insert(current_object_);
+ }
+ // Gets the symbol ID from the object access chain, which should be the
+ // first element recorded in the access chain.
+ ObjectAccessChain id_symbol = getFrontElement(current_object_);
+ // Adds a mapping from the symbol ID to this assignment operation node.
+ symbol_definition_mapping_.insert(std::make_pair(id_symbol, node));
+
+ // Traverses the right node, there may be other 'assignment'
+ // operations in the right.
+ current_object_.clear();
+ node->getRight()->traverse(this);
+
+ } else if (isDereferenceOperation(node->getOp())) {
+ // The left node (parent node) is a struct type object. We need to
+ // record the access chain information of the current node into its
+ // object id.
+ if (node->getOp() == glslang::EOpIndexDirectStruct) {
+ unsigned struct_dereference_index = getStructIndexFromConstantUnion(node->getRight());
+ current_object_.push_back(ObjectAccesschainDelimiter);
+ current_object_.append(std::to_string(struct_dereference_index));
+ }
+ accesschain_mapping_[node] = current_object_;
+
+ // For a dereference node, there is no need to traverse the right child
+ // node as the right node should always be an integer type object.
+
+ } else {
+ // For other binary nodes, still traverse the right node.
+ current_object_.clear();
+ node->getRight()->traverse(this);
+ }
+ return false;
+}
+
+// Traverses the AST and returns a tuple of four members:
+// 1) a mapping from symbol IDs to the definition nodes (aka. assignment nodes) of these symbols.
+// 2) a mapping from object nodes in the AST to the access chains of these objects.
+// 3) a set of access chains of precise objects.
+// 4) a set of return nodes with precise expressions.
+std::tuple<NodeMapping, AccessChainMapping, ObjectAccesschainSet, ReturnBranchNodeSet>
+getSymbolToDefinitionMappingAndPreciseSymbolIDs(const glslang::TIntermediate& intermediate)
+{
+ auto result_tuple = std::make_tuple(NodeMapping(), AccessChainMapping(), ObjectAccesschainSet(),
+ ReturnBranchNodeSet());
+
+ TIntermNode* root = intermediate.getTreeRoot();
+ if (root == 0)
+ return result_tuple;
+
+ NodeMapping& symbol_definition_mapping = std::get<0>(result_tuple);
+ AccessChainMapping& accesschain_mapping = std::get<1>(result_tuple);
+ ObjectAccesschainSet& precise_objects = std::get<2>(result_tuple);
+ ReturnBranchNodeSet& precise_return_nodes = std::get<3>(result_tuple);
+
+ // Traverses the AST and populate the results.
+ TSymbolDefinitionCollectingTraverser collector(&symbol_definition_mapping, &accesschain_mapping,
+ &precise_objects, &precise_return_nodes);
+ root->traverse(&collector);
+
+ return result_tuple;
+}
+
+//
+// A traverser that determine whether the left node (or operand node for unary
+// node) of an assignment node is 'precise', containing 'precise' or not,
+// according to the access chain a given precise object which share the same
+// symbol as the left node.
+//
+// Post-orderly traverses the left node subtree of an binary assignment node and:
+//
+// 1) Propagates the 'precise' from the left object nodes to this object node.
+//
+// 2) Builds object access chain along the traversal, and also compares with
+// the access chain of the given 'precise' object along with the traversal to
+// tell if the node to be defined is 'precise' or not.
+//
+class TNoContractionAssigneeCheckingTraverser : public glslang::TIntermTraverser {
+
+ enum DecisionStatus {
+ // The object node to be assigned to may contain 'precise' objects and also not 'precise' objects.
+ Mixed = 0,
+ // The object node to be assigned to is either a 'precise' object or a struct objects whose members are all 'precise'.
+ Precise = 1,
+ // The object node to be assigned to is not a 'precise' object.
+ NotPreicse = 2,
+ };
+
+public:
+ TNoContractionAssigneeCheckingTraverser(const AccessChainMapping& accesschain_mapping)
+ : TIntermTraverser(true, false, false), accesschain_mapping_(accesschain_mapping),
+ precise_object_(nullptr) {}
+
+ // Checks the preciseness of a given assignment node with a precise object
+ // represented as access chain. The precise object shares the same symbol
+ // with the assignee of the given assignment node. Return a tuple of two:
+ //
+ // 1) The preciseness of the assignee node of this assignment node. True
+ // if the assignee contains 'precise' objects or is 'precise', false if
+ // the assignee is not 'precise' according to the access chain of the given
+ // precise object.
+ //
+ // 2) The incremental access chain from the assignee node to its nested
+ // 'precise' object, according to the access chain of the given precise
+ // object. This incremental access chain can be empty, which means the
+ // assignee is 'precise'. Otherwise it shows the path to the nested
+ // precise object.
+ std::tuple<bool, ObjectAccessChain>
+ getPrecisenessAndRemainedAccessChain(glslang::TIntermOperator* node,
+ const ObjectAccessChain& precise_object)
+ {
+ assert(isAssignOperation(node->getOp()));
+ precise_object_ = &precise_object;
+ ObjectAccessChain assignee_object;
+ if (glslang::TIntermBinary* BN = node->getAsBinaryNode()) {
+ // This is a binary assignment node, we need to check the
+ // preciseness of the left node.
+ assert(accesschain_mapping_.count(BN->getLeft()));
+ // The left node (assignee node) is an object node, traverse the
+ // node to let the 'precise' of nesting objects being transfered to
+ // nested objects.
+ BN->getLeft()->traverse(this);
+ // After traversing the left node, if the left node is 'precise',
+ // we can conclude this assignment should propagate 'precise'.
+ if (isPreciseObjectNode(BN->getLeft())) {
+ return make_tuple(true, ObjectAccessChain());
+ }
+ // If the preciseness of the left node (assignee node) can not
+ // be determined by now, we need to compare the access chain string
+ // of the assignee object with the given precise object.
+ assignee_object = accesschain_mapping_.at(BN->getLeft());
+
+ } else if (glslang::TIntermUnary* UN = node->getAsUnaryNode()) {
+ // This is a unary assignment node, we need to check the
+ // preciseness of the operand node. For unary assignment node, the
+ // operand node should always be an object node.
+ assert(accesschain_mapping_.count(UN->getOperand()));
+ // Traverse the operand node to let the 'precise' being propagated
+ // from lower nodes to upper nodes.
+ UN->getOperand()->traverse(this);
+ // After traversing the operand node, if the operand node is
+ // 'precise', this assignment should propagate 'precise'.
+ if (isPreciseObjectNode(UN->getOperand())) {
+ return make_tuple(true, ObjectAccessChain());
+ }
+ // If the preciseness of the operand node (assignee node) can not
+ // be determined by now, we need to compare the access chain string
+ // of the assignee object with the given precise object.
+ assignee_object = accesschain_mapping_.at(UN->getOperand());
+ } else {
+ // Not a binary or unary node, should not happen.
+ assert(false);
+ }
+
+ // Compare the access chain string of the assignee node with the given
+ // precise object to determine if this assignment should propagate
+ // 'precise'.
+ if (assignee_object.find(precise_object) == 0) {
+ // The access chain string of the given precise object is a prefix
+ // of assignee's access chain string. The assignee should be
+ // 'precise'.
+ return make_tuple(true, ObjectAccessChain());
+ } else if (precise_object.find(assignee_object) == 0) {
+ // The assignee's access chain string is a prefix of the given
+ // precise object, the assignee object contains 'precise' object,
+ // and we need to pass the remained access chain to the object nodes
+ // in the right.
+ return make_tuple(true, getSubAccessChainAfterPrefix(precise_object, assignee_object));
+ } else {
+ // The access chain strings do not match, the assignee object can
+ // not be labeled as 'precise' according to the given precise
+ // object.
+ return make_tuple(false, ObjectAccessChain());
+ }
+ }
+
+protected:
+ TNoContractionAssigneeCheckingTraverser& operator=(const TNoContractionAssigneeCheckingTraverser&);
+
+ bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override;
+ void visitSymbol(glslang::TIntermSymbol* node) override;
+
+ // A map from object nodes to their access chain string (used as object ID).
+ const AccessChainMapping& accesschain_mapping_;
+ // A given precise object, represented in it access chain string. This
+ // precise object is used to be compared with the assignee node to tell if
+ // the assignee node is 'precise', contains 'precise' object or not
+ // 'precise'.
+ const ObjectAccessChain* precise_object_;
+};
+
+// Visits a binary node. If the node is an object node, it must be a dereference
+// node. In such cases, if the left node is 'precise', this node should also be
+// 'precise'.
+bool TNoContractionAssigneeCheckingTraverser::visitBinary(glslang::TVisit,
+ glslang::TIntermBinary* node)
+{
+ // Traverses the left so that we transfer the 'precise' from nesting object
+ // to its nested object.
+ node->getLeft()->traverse(this);
+ // If this binary node is an object node, we should have it in the
+ // accesschain_mapping_.
+ if (accesschain_mapping_.count(node)) {
+ // A binary object node must be a dereference node.
+ assert(isDereferenceOperation(node->getOp()));
+ // If the left node is 'precise', this node should also be precise,
+ // otherwise, compare with the given precise_object_. If the
+ // access chain of this node matches with the given precise_object_,
+ // this node should be marked as 'precise'.
+ if (isPreciseObjectNode(node->getLeft())) {
+ node->getWritableType().getQualifier().noContraction = true;
+ } else if (accesschain_mapping_.at(node) == *precise_object_) {
+ node->getWritableType().getQualifier().noContraction = true;
+ }
+ }
+ return false;
+}
+
+// Visits a symbol node, if the symbol node ID (its access chain string) matches
+// with the given precise object, this node should be 'precise'.
+void TNoContractionAssigneeCheckingTraverser::visitSymbol(glslang::TIntermSymbol* node)
+{
+ // A symbol node should always be an object node, and should have been added
+ // to the map from object nodes to their access chain strings.
+ assert(accesschain_mapping_.count(node));
+ if (accesschain_mapping_.at(node) == *precise_object_) {
+ node->getWritableType().getQualifier().noContraction = true;
+ }
+}
+
+//
+// A traverser that only traverses the right side of binary assignment nodes
+// and the operand node of unary assignment nodes.
+//
+// 1) Marks arithmetic operations as 'NoContraction'.
+//
+// 2) Find the object which should be marked as 'precise' in the right and
+// update the 'precise' object work list.
+//
+class TNoContractionPropagator : public glslang::TIntermTraverser {
+public:
+ TNoContractionPropagator(ObjectAccesschainSet* precise_objects,
+ const AccessChainMapping& accesschain_mapping)
+ : TIntermTraverser(true, false, false),
+ precise_objects_(*precise_objects), added_precise_object_ids_(),
+ remained_accesschain_(), accesschain_mapping_(accesschain_mapping) {}
+
+ // Propagates 'precise' in the right nodes of a given assignment node with
+ // access chain record from the assignee node to a 'precise' object it
+ // contains.
+ void
+ propagateNoContractionInOneExpression(glslang::TIntermTyped* defining_node,
+ const ObjectAccessChain& assignee_remained_accesschain)
+ {
+ remained_accesschain_ = assignee_remained_accesschain;
+ if (glslang::TIntermBinary* BN = defining_node->getAsBinaryNode()) {
+ assert(isAssignOperation(BN->getOp()));
+ BN->getRight()->traverse(this);
+ if (isArithmeticOperation(BN->getOp())) {
+ BN->getWritableType().getQualifier().noContraction = true;
+ }
+ } else if (glslang::TIntermUnary* UN = defining_node->getAsUnaryNode()) {
+ assert(isAssignOperation(UN->getOp()));
+ UN->getOperand()->traverse(this);
+ if (isArithmeticOperation(UN->getOp())) {
+ UN->getWritableType().getQualifier().noContraction = true;
+ }
+ }
+ }
+
+ // Propagates 'precise' in a given precise return node.
+ void propagateNoContractionInReturnNode(glslang::TIntermBranch* return_node)
+ {
+ remained_accesschain_ = "";
+ assert(return_node->getFlowOp() == glslang::EOpReturn && return_node->getExpression());
+ return_node->getExpression()->traverse(this);
+ }
+
+protected:
+ TNoContractionPropagator& operator=(const TNoContractionPropagator&);
+
+ // Visits an aggregate node. The node can be a initializer list, in which
+ // case we need to find the 'precise' or 'precise' containing object node
+ // with the access chain record. In other cases, just need to traverse all
+ // the children nodes.
+ bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate* node) override
+ {
+ if (!remained_accesschain_.empty() && node->getOp() == glslang::EOpConstructStruct) {
+ // This is a struct initializer node, and the remained
+ // access chain is not empty, we need to refer to the
+ // assignee_remained_access_chain_ to find the nested
+ // 'precise' object. And we don't need to visit other nodes in this
+ // aggregate node.
+
+ // Gets the struct dereference index that leads to 'precise' object.
+ ObjectAccessChain precise_accesschain_index_str =
+ getFrontElement(remained_accesschain_);
+ unsigned precise_accesschain_index = (unsigned)strtoul(precise_accesschain_index_str.c_str(), nullptr, 10);
+ // Gets the node pointed by the access chain index extracted before.
+ glslang::TIntermTyped* potential_precise_node =
+ node->getSequence()[precise_accesschain_index]->getAsTyped();
+ assert(potential_precise_node);
+ // Pop the front access chain index from the path, and visit the nested node.
+ {
+ ObjectAccessChain next_level_accesschain =
+ subAccessChainFromSecondElement(remained_accesschain_);
+ StateSettingGuard<ObjectAccessChain> setup_remained_accesschain_for_next_level(
+ &remained_accesschain_, next_level_accesschain);
+ potential_precise_node->traverse(this);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ // Visits a binary node. A binary node can be an object node, e.g. a dereference node.
+ // As only the top object nodes in the right side of an assignment needs to be visited
+ // and added to 'precise' work list, this traverser won't visit the children nodes of
+ // an object node. If the binary node does not represent an object node, it should
+ // go on to traverse its children nodes and if it is an arithmetic operation node, this
+ // operation should be marked as 'noContraction'.
+ bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override
+ {
+ if (isDereferenceOperation(node->getOp())) {
+ // This binary node is an object node. Need to update the precise
+ // object set with the access chain of this node + remained
+ // access chain .
+ ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
+ if (remained_accesschain_.empty()) {
+ node->getWritableType().getQualifier().noContraction = true;
+ } else {
+ new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
+ }
+ // Cache the access chain as added precise object, so we won't add the
+ // same object to the work list again.
+ if (!added_precise_object_ids_.count(new_precise_accesschain)) {
+ precise_objects_.insert(new_precise_accesschain);
+ added_precise_object_ids_.insert(new_precise_accesschain);
+ }
+ // Only the upper-most object nodes should be visited, so do not
+ // visit children of this object node.
+ return false;
+ }
+ // If this is an arithmetic operation, marks this node as 'noContraction'.
+ if (isArithmeticOperation(node->getOp()) && node->getBasicType() != glslang::EbtInt) {
+ node->getWritableType().getQualifier().noContraction = true;
+ }
+ // As this node is not an object node, need to traverse the children nodes.
+ return true;
+ }
+
+ // Visits a unary node. A unary node can not be an object node. If the operation
+ // is an arithmetic operation, need to mark this node as 'noContraction'.
+ bool visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) override
+ {
+ // If this is an arithmetic operation, marks this with 'noContraction'
+ if (isArithmeticOperation(node->getOp())) {
+ node->getWritableType().getQualifier().noContraction = true;
+ }
+ return true;
+ }
+
+ // Visits a symbol node. A symbol node is always an object node. So we
+ // should always be able to find its in our collected mapping from object
+ // nodes to access chains. As an object node, a symbol node can be either
+ // 'precise' or containing 'precise' objects according to unused
+ // access chain information we have when we visit this node.
+ void visitSymbol(glslang::TIntermSymbol* node) override
+ {
+ // Symbol nodes are object nodes and should always have an
+ // access chain collected before matches with it.
+ assert(accesschain_mapping_.count(node));
+ ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
+ // If the unused access chain is empty, this symbol node should be
+ // marked as 'precise'. Otherwise, the unused access chain should be
+ // appended to the symbol ID to build a new access chain which points to
+ // the nested 'precise' object in this symbol object.
+ if (remained_accesschain_.empty()) {
+ node->getWritableType().getQualifier().noContraction = true;
+ } else {
+ new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
+ }
+ // Add the new 'precise' access chain to the work list and make sure we
+ // don't visit it again.
+ if (!added_precise_object_ids_.count(new_precise_accesschain)) {
+ precise_objects_.insert(new_precise_accesschain);
+ added_precise_object_ids_.insert(new_precise_accesschain);
+ }
+ }
+
+ // A set of precise objects, represented as access chains.
+ ObjectAccesschainSet& precise_objects_;
+ // Visited symbol nodes, should not revisit these nodes.
+ ObjectAccesschainSet added_precise_object_ids_;
+ // The left node of an assignment operation might be an parent of 'precise' objects.
+ // This means the left node might not be an 'precise' object node, but it may contains
+ // 'precise' qualifier which should be propagated to the corresponding child node in
+ // the right. So we need the path from the left node to its nested 'precise' node to
+ // tell us how to find the corresponding 'precise' node in the right.
+ ObjectAccessChain remained_accesschain_;
+ // A map from node pointers to their access chains.
+ const AccessChainMapping& accesschain_mapping_;
+};
+}
+
+namespace glslang {
+
+void PropagateNoContraction(const glslang::TIntermediate& intermediate)
+{
+ // First, traverses the AST, records symbols with their defining operations
+ // and collects the initial set of precise symbols (symbol nodes that marked
+ // as 'noContraction') and precise return nodes.
+ auto mappings_and_precise_objects =
+ getSymbolToDefinitionMappingAndPreciseSymbolIDs(intermediate);
+
+ // The mapping of symbol node IDs to their defining nodes. This enables us
+ // to get the defining node directly from a given symbol ID without
+ // traversing the tree again.
+ NodeMapping& symbol_definition_mapping = std::get<0>(mappings_and_precise_objects);
+
+ // The mapping of object nodes to their access chains recorded.
+ AccessChainMapping& accesschain_mapping = std::get<1>(mappings_and_precise_objects);
+
+ // The initial set of 'precise' objects which are represented as the
+ // access chain toward them.
+ ObjectAccesschainSet& precise_object_accesschains = std::get<2>(mappings_and_precise_objects);
+
+ // The set of 'precise' return nodes.
+ ReturnBranchNodeSet& precise_return_nodes = std::get<3>(mappings_and_precise_objects);
+
+ // Second, uses the initial set of precise objects as a work list, pops an
+ // access chain, extract the symbol ID from it. Then:
+ // 1) Check the assignee object, see if it is 'precise' object node or
+ // contains 'precise' object. Obtain the incremental access chain from the
+ // assignee node to its nested 'precise' node (if any).
+ // 2) If the assignee object node is 'precise' or it contains 'precise'
+ // objects, traverses the right side of the assignment operation
+ // expression to mark arithmetic operations as 'noContration' and update
+ // 'precise' access chain work list with new found object nodes.
+ // Repeat above steps until the work list is empty.
+ TNoContractionAssigneeCheckingTraverser checker(accesschain_mapping);
+ TNoContractionPropagator propagator(&precise_object_accesschains, accesschain_mapping);
+
+ // We have two initial precise work lists to handle:
+ // 1) precise return nodes
+ // 2) precise object access chains
+ // We should process the precise return nodes first and the involved
+ // objects in the return expression should be added to the precise object
+ // access chain set.
+ while (!precise_return_nodes.empty()) {
+ glslang::TIntermBranch* precise_return_node = *precise_return_nodes.begin();
+ propagator.propagateNoContractionInReturnNode(precise_return_node);
+ precise_return_nodes.erase(precise_return_node);
+ }
+
+ while (!precise_object_accesschains.empty()) {
+ // Get the access chain of a precise object from the work list.
+ ObjectAccessChain precise_object_accesschain = *precise_object_accesschains.begin();
+ // Get the symbol id from the access chain.
+ ObjectAccessChain symbol_id = getFrontElement(precise_object_accesschain);
+ // Get all the defining nodes of that symbol ID.
+ std::pair<NodeMapping::iterator, NodeMapping::iterator> range =
+ symbol_definition_mapping.equal_range(symbol_id);
+ // Visits all the assignment nodes of that symbol ID and
+ // 1) Check if the assignee node is 'precise' or contains 'precise'
+ // objects.
+ // 2) Propagate the 'precise' to the top layer object nodes
+ // in the right side of the assignment operation, update the 'precise'
+ // work list with new access chains representing the new 'precise'
+ // objects, and mark arithmetic operations as 'noContraction'.
+ for (NodeMapping::iterator defining_node_iter = range.first;
+ defining_node_iter != range.second; defining_node_iter++) {
+ TIntermOperator* defining_node = defining_node_iter->second;
+ // Check the assignee node.
+ auto checker_result = checker.getPrecisenessAndRemainedAccessChain(
+ defining_node, precise_object_accesschain);
+ bool& contain_precise = std::get<0>(checker_result);
+ ObjectAccessChain& remained_accesschain = std::get<1>(checker_result);
+ // If the assignee node is 'precise' or contains 'precise', propagate the
+ // 'precise' to the right. Otherwise just skip this assignment node.
+ if (contain_precise) {
+ propagator.propagateNoContractionInOneExpression(defining_node,
+ remained_accesschain);
+ }
+ }
+ // Remove the last processed 'precise' object from the work list.
+ precise_object_accesschains.erase(precise_object_accesschain);
+ }
+}
+};
+
+#endif // GLSLANG_WEB \ No newline at end of file
diff --git a/thirdparty/glslang/glslang/MachineIndependent/propagateNoContraction.h b/thirdparty/glslang/glslang/MachineIndependent/propagateNoContraction.h
new file mode 100644
index 0000000000..8521ad7d6a
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/propagateNoContraction.h
@@ -0,0 +1,55 @@
+//
+// Copyright (C) 2015-2016 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Visit the nodes in the glslang intermediate tree representation to
+// propagate 'noContraction' qualifier.
+//
+
+#pragma once
+
+#include "../Include/intermediate.h"
+
+namespace glslang {
+
+// Propagates the 'precise' qualifier for objects (objects marked with
+// 'noContraction' qualifier) from the shader source specified 'precise'
+// variables to all the involved objects, and add 'noContraction' qualifier for
+// the involved arithmetic operations.
+// Note that the same qualifier: 'noContraction' is used in both object nodes
+// and arithmetic operation nodes, but has different meaning. For object nodes,
+// 'noContraction' means the object is 'precise'; and for arithmetic operation
+// nodes, it means the operation should not be contracted.
+void PropagateNoContraction(const glslang::TIntermediate& intermediate);
+};
diff --git a/thirdparty/glslang/glslang/MachineIndependent/reflection.cpp b/thirdparty/glslang/glslang/MachineIndependent/reflection.cpp
new file mode 100644
index 0000000000..b09367113c
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/reflection.cpp
@@ -0,0 +1,1204 @@
+//
+// Copyright (C) 2013-2016 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef GLSLANG_WEB
+
+#include "../Include/Common.h"
+#include "reflection.h"
+#include "LiveTraverser.h"
+#include "localintermediate.h"
+
+#include "gl_types.h"
+
+//
+// Grow the reflection database through a friend traverser class of TReflection and a
+// collection of functions to do a liveness traversal that note what uniforms are used
+// in semantically non-dead code.
+//
+// Can be used multiple times, once per stage, to grow a program reflection.
+//
+// High-level algorithm for one stage:
+//
+// 1. Put the entry point on the list of live functions.
+//
+// 2. Traverse any live function, while skipping if-tests with a compile-time constant
+// condition of false, and while adding any encountered function calls to the live
+// function list.
+//
+// Repeat until the live function list is empty.
+//
+// 3. Add any encountered uniform variables and blocks to the reflection database.
+//
+// Can be attempted with a failed link, but will return false if recursion had been detected, or
+// there wasn't exactly one entry point.
+//
+
+namespace glslang {
+
+//
+// The traverser: mostly pass through, except
+// - processing binary nodes to see if they are dereferences of an aggregates to track
+// - processing symbol nodes to see if they are non-aggregate objects to track
+//
+// This ignores semantically dead code by using TLiveTraverser.
+//
+// This is in the glslang namespace directly so it can be a friend of TReflection.
+//
+
+class TReflectionTraverser : public TLiveTraverser {
+public:
+ TReflectionTraverser(const TIntermediate& i, TReflection& r) :
+ TLiveTraverser(i), reflection(r) { }
+
+ virtual bool visitBinary(TVisit, TIntermBinary* node);
+ virtual void visitSymbol(TIntermSymbol* base);
+
+ // Add a simple reference to a uniform variable to the uniform database, no dereference involved.
+ // However, no dereference doesn't mean simple... it could be a complex aggregate.
+ void addUniform(const TIntermSymbol& base)
+ {
+ if (processedDerefs.find(&base) == processedDerefs.end()) {
+ processedDerefs.insert(&base);
+
+ // Use a degenerate (empty) set of dereferences to immediately put as at the end of
+ // the dereference change expected by blowUpActiveAggregate.
+ TList<TIntermBinary*> derefs;
+ blowUpActiveAggregate(base.getType(), base.getName(), derefs, derefs.end(), -1, -1, 0, 0,
+ base.getQualifier().storage, true);
+ }
+ }
+
+ void addPipeIOVariable(const TIntermSymbol& base)
+ {
+ if (processedDerefs.find(&base) == processedDerefs.end()) {
+ processedDerefs.insert(&base);
+
+ const TString &name = base.getName();
+ const TType &type = base.getType();
+ const bool input = base.getQualifier().isPipeInput();
+
+ TReflection::TMapIndexToReflection &ioItems =
+ input ? reflection.indexToPipeInput : reflection.indexToPipeOutput;
+
+
+ TReflection::TNameToIndex &ioMapper =
+ input ? reflection.pipeInNameToIndex : reflection.pipeOutNameToIndex;
+
+ if (reflection.options & EShReflectionUnwrapIOBlocks) {
+ bool anonymous = IsAnonymous(name);
+
+ TString baseName;
+ if (type.getBasicType() == EbtBlock) {
+ baseName = anonymous ? TString() : type.getTypeName();
+ } else {
+ baseName = anonymous ? TString() : name;
+ }
+
+ // by convention if this is an arrayed block we ignore the array in the reflection
+ if (type.isArray() && type.getBasicType() == EbtBlock) {
+ blowUpIOAggregate(input, baseName, TType(type, 0));
+ } else {
+ blowUpIOAggregate(input, baseName, type);
+ }
+ } else {
+ TReflection::TNameToIndex::const_iterator it = ioMapper.find(name.c_str());
+ if (it == ioMapper.end()) {
+ // seperate pipe i/o params from uniforms and blocks
+ // in is only for input in first stage as out is only for last stage. check traverse in call stack.
+ ioMapper[name.c_str()] = static_cast<int>(ioItems.size());
+ ioItems.push_back(
+ TObjectReflection(name.c_str(), type, 0, mapToGlType(type), mapToGlArraySize(type), 0));
+ EShLanguageMask& stages = ioItems.back().stages;
+ stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+ } else {
+ EShLanguageMask& stages = ioItems[it->second].stages;
+ stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+ }
+ }
+ }
+ }
+
+ // Lookup or calculate the offset of all block members at once, using the recursively
+ // defined block offset rules.
+ void getOffsets(const TType& type, TVector<int>& offsets)
+ {
+ const TTypeList& memberList = *type.getStruct();
+
+ int memberSize = 0;
+ int offset = 0;
+ for (size_t m = 0; m < offsets.size(); ++m) {
+ // if the user supplied an offset, snap to it now
+ if (memberList[m].type->getQualifier().hasOffset())
+ offset = memberList[m].type->getQualifier().layoutOffset;
+
+ // calculate the offset of the next member and align the current offset to this member
+ intermediate.updateOffset(type, *memberList[m].type, offset, memberSize);
+
+ // save the offset of this member
+ offsets[m] = offset;
+
+ // update for the next member
+ offset += memberSize;
+ }
+ }
+
+ // Calculate the stride of an array type
+ int getArrayStride(const TType& baseType, const TType& type)
+ {
+ int dummySize;
+ int stride;
+
+ // consider blocks to have 0 stride, so that all offsets are relative to the start of their block
+ if (type.getBasicType() == EbtBlock)
+ return 0;
+
+ TLayoutMatrix subMatrixLayout = type.getQualifier().layoutMatrix;
+ intermediate.getMemberAlignment(type, dummySize, stride,
+ baseType.getQualifier().layoutPacking,
+ subMatrixLayout != ElmNone
+ ? subMatrixLayout == ElmRowMajor
+ : baseType.getQualifier().layoutMatrix == ElmRowMajor);
+
+ return stride;
+ }
+
+ // count the total number of leaf members from iterating out of a block type
+ int countAggregateMembers(const TType& parentType)
+ {
+ if (! parentType.isStruct())
+ return 1;
+
+ const bool strictArraySuffix = (reflection.options & EShReflectionStrictArraySuffix);
+
+ bool blockParent = (parentType.getBasicType() == EbtBlock && parentType.getQualifier().storage == EvqBuffer);
+
+ const TTypeList &memberList = *parentType.getStruct();
+
+ int ret = 0;
+
+ for (size_t i = 0; i < memberList.size(); i++)
+ {
+ const TType &memberType = *memberList[i].type;
+ int numMembers = countAggregateMembers(memberType);
+ // for sized arrays of structs, apply logic to expand out the same as we would below in
+ // blowUpActiveAggregate
+ if (memberType.isArray() && ! memberType.getArraySizes()->hasUnsized() && memberType.isStruct()) {
+ if (! strictArraySuffix || ! blockParent)
+ numMembers *= memberType.getArraySizes()->getCumulativeSize();
+ }
+ ret += numMembers;
+ }
+
+ return ret;
+ }
+
+ // Traverse the provided deref chain, including the base, and
+ // - build a full reflection-granularity name, array size, etc. entry out of it, if it goes down to that granularity
+ // - recursively expand any variable array index in the middle of that traversal
+ // - recursively expand what's left at the end if the deref chain did not reach down to reflection granularity
+ //
+ // arraySize tracks, just for the final dereference in the chain, if there was a specific known size.
+ // A value of 0 for arraySize will mean to use the full array's size.
+ void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList<TIntermBinary*>& derefs,
+ TList<TIntermBinary*>::const_iterator deref, int offset, int blockIndex, int arraySize,
+ int topLevelArrayStride, TStorageQualifier baseStorage, bool active)
+ {
+ // when strictArraySuffix is enabled, we closely follow the rules from ARB_program_interface_query.
+ // Broadly:
+ // * arrays-of-structs always have a [x] suffix.
+ // * with array-of-struct variables in the root of a buffer block, only ever return [0].
+ // * otherwise, array suffixes are added whenever we iterate, even if that means expanding out an array.
+ const bool strictArraySuffix = (reflection.options & EShReflectionStrictArraySuffix);
+
+ // is this variable inside a buffer block. This flag is set back to false after we iterate inside the first array element.
+ bool blockParent = (baseType.getBasicType() == EbtBlock && baseType.getQualifier().storage == EvqBuffer);
+
+ // process the part of the dereference chain that was explicit in the shader
+ TString name = baseName;
+ const TType* terminalType = &baseType;
+ for (; deref != derefs.end(); ++deref) {
+ TIntermBinary* visitNode = *deref;
+ terminalType = &visitNode->getType();
+ int index;
+ switch (visitNode->getOp()) {
+ case EOpIndexIndirect: {
+ int stride = getArrayStride(baseType, visitNode->getLeft()->getType());
+
+ if (topLevelArrayStride == 0)
+ topLevelArrayStride = stride;
+
+ // Visit all the indices of this array, and for each one add on the remaining dereferencing
+ for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) {
+ TString newBaseName = name;
+ if (strictArraySuffix && blockParent)
+ newBaseName.append(TString("[0]"));
+ else if (strictArraySuffix || baseType.getBasicType() != EbtBlock)
+ newBaseName.append(TString("[") + String(i) + "]");
+ TList<TIntermBinary*>::const_iterator nextDeref = deref;
+ ++nextDeref;
+ blowUpActiveAggregate(*terminalType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize,
+ topLevelArrayStride, baseStorage, active);
+
+ if (offset >= 0)
+ offset += stride;
+ }
+
+ // it was all completed in the recursive calls above
+ return;
+ }
+ case EOpIndexDirect: {
+ int stride = getArrayStride(baseType, visitNode->getLeft()->getType());
+
+ index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
+ if (strictArraySuffix && blockParent) {
+ name.append(TString("[0]"));
+ } else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
+ name.append(TString("[") + String(index) + "]");
+
+ if (offset >= 0)
+ offset += stride * index;
+ }
+
+ if (topLevelArrayStride == 0)
+ topLevelArrayStride = stride;
+
+ blockParent = false;
+ break;
+ }
+ case EOpIndexDirectStruct:
+ index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
+ if (offset >= 0)
+ offset += intermediate.getOffset(visitNode->getLeft()->getType(), index);
+ if (name.size() > 0)
+ name.append(".");
+ name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName());
+ break;
+ default:
+ break;
+ }
+ }
+
+ // if the terminalType is still too coarse a granularity, this is still an aggregate to expand, expand it...
+ if (! isReflectionGranularity(*terminalType)) {
+ // the base offset of this node, that children are relative to
+ int baseOffset = offset;
+
+ if (terminalType->isArray()) {
+ // Visit all the indices of this array, and for each one,
+ // fully explode the remaining aggregate to dereference
+
+ int stride = 0;
+ if (offset >= 0)
+ stride = getArrayStride(baseType, *terminalType);
+
+ if (topLevelArrayStride == 0)
+ topLevelArrayStride = stride;
+
+ int arrayIterateSize = std::max(terminalType->getOuterArraySize(), 1);
+
+ // for top-level arrays in blocks, only expand [0] to avoid explosion of items
+ if (strictArraySuffix && blockParent)
+ arrayIterateSize = 1;
+
+ for (int i = 0; i < arrayIterateSize; ++i) {
+ TString newBaseName = name;
+ newBaseName.append(TString("[") + String(i) + "]");
+ TType derefType(*terminalType, 0);
+ if (offset >= 0)
+ offset = baseOffset + stride * i;
+
+ blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
+ topLevelArrayStride, baseStorage, active);
+ }
+ } else {
+ // Visit all members of this aggregate, and for each one,
+ // fully explode the remaining aggregate to dereference
+ const TTypeList& typeList = *terminalType->getStruct();
+
+ TVector<int> memberOffsets;
+
+ if (baseOffset >= 0) {
+ memberOffsets.resize(typeList.size());
+ getOffsets(*terminalType, memberOffsets);
+ }
+
+ for (int i = 0; i < (int)typeList.size(); ++i) {
+ TString newBaseName = name;
+ if (newBaseName.size() > 0)
+ newBaseName.append(".");
+ newBaseName.append(typeList[i].type->getFieldName());
+ TType derefType(*terminalType, i);
+ if (offset >= 0)
+ offset = baseOffset + memberOffsets[i];
+
+ int arrayStride = topLevelArrayStride;
+ if (terminalType->getBasicType() == EbtBlock && terminalType->getQualifier().storage == EvqBuffer &&
+ derefType.isArray()) {
+ arrayStride = getArrayStride(baseType, derefType);
+ }
+
+ blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
+ arrayStride, baseStorage, active);
+ }
+ }
+
+ // it was all completed in the recursive calls above
+ return;
+ }
+
+ if ((reflection.options & EShReflectionBasicArraySuffix) && terminalType->isArray()) {
+ name.append(TString("[0]"));
+ }
+
+ // Finally, add a full string to the reflection database, and update the array size if necessary.
+ // If the dereferenced entity to record is an array, compute the size and update the maximum size.
+
+ // there might not be a final array dereference, it could have been copied as an array object
+ if (arraySize == 0)
+ arraySize = mapToGlArraySize(*terminalType);
+
+ TReflection::TMapIndexToReflection& variables = reflection.GetVariableMapForStorage(baseStorage);
+
+ TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
+ if (it == reflection.nameToIndex.end()) {
+ int uniformIndex = (int)variables.size();
+ reflection.nameToIndex[name.c_str()] = uniformIndex;
+ variables.push_back(TObjectReflection(name.c_str(), *terminalType, offset, mapToGlType(*terminalType),
+ arraySize, blockIndex));
+ if (terminalType->isArray()) {
+ variables.back().arrayStride = getArrayStride(baseType, *terminalType);
+ if (topLevelArrayStride == 0)
+ topLevelArrayStride = variables.back().arrayStride;
+ }
+
+ if ((reflection.options & EShReflectionSeparateBuffers) && terminalType->isAtomic())
+ reflection.atomicCounterUniformIndices.push_back(uniformIndex);
+
+ variables.back().topLevelArrayStride = topLevelArrayStride;
+
+ if ((reflection.options & EShReflectionAllBlockVariables) && active) {
+ EShLanguageMask& stages = variables.back().stages;
+ stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+ }
+ } else {
+ if (arraySize > 1) {
+ int& reflectedArraySize = variables[it->second].size;
+ reflectedArraySize = std::max(arraySize, reflectedArraySize);
+ }
+
+ if ((reflection.options & EShReflectionAllBlockVariables) && active) {
+ EShLanguageMask& stages = variables[it->second].stages;
+ stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+ }
+ }
+ }
+
+ // similar to blowUpActiveAggregate, but with simpler rules and no dereferences to follow.
+ void blowUpIOAggregate(bool input, const TString &baseName, const TType &type)
+ {
+ TString name = baseName;
+
+ // if the type is still too coarse a granularity, this is still an aggregate to expand, expand it...
+ if (! isReflectionGranularity(type)) {
+ if (type.isArray()) {
+ // Visit all the indices of this array, and for each one,
+ // fully explode the remaining aggregate to dereference
+ for (int i = 0; i < std::max(type.getOuterArraySize(), 1); ++i) {
+ TString newBaseName = name;
+ newBaseName.append(TString("[") + String(i) + "]");
+ TType derefType(type, 0);
+
+ blowUpIOAggregate(input, newBaseName, derefType);
+ }
+ } else {
+ // Visit all members of this aggregate, and for each one,
+ // fully explode the remaining aggregate to dereference
+ const TTypeList& typeList = *type.getStruct();
+
+ for (int i = 0; i < (int)typeList.size(); ++i) {
+ TString newBaseName = name;
+ if (newBaseName.size() > 0)
+ newBaseName.append(".");
+ newBaseName.append(typeList[i].type->getFieldName());
+ TType derefType(type, i);
+
+ blowUpIOAggregate(input, newBaseName, derefType);
+ }
+ }
+
+ // it was all completed in the recursive calls above
+ return;
+ }
+
+ if ((reflection.options & EShReflectionBasicArraySuffix) && type.isArray()) {
+ name.append(TString("[0]"));
+ }
+
+ TReflection::TMapIndexToReflection &ioItems =
+ input ? reflection.indexToPipeInput : reflection.indexToPipeOutput;
+
+ std::string namespacedName = input ? "in " : "out ";
+ namespacedName += name.c_str();
+
+ TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(namespacedName);
+ if (it == reflection.nameToIndex.end()) {
+ reflection.nameToIndex[namespacedName] = (int)ioItems.size();
+ ioItems.push_back(
+ TObjectReflection(name.c_str(), type, 0, mapToGlType(type), mapToGlArraySize(type), 0));
+
+ EShLanguageMask& stages = ioItems.back().stages;
+ stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+ } else {
+ EShLanguageMask& stages = ioItems[it->second].stages;
+ stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+ }
+ }
+
+ // Add a uniform dereference where blocks/struct/arrays are involved in the access.
+ // Handles the situation where the left node is at the correct or too coarse a
+ // granularity for reflection. (That is, further dereferences up the tree will be
+ // skipped.) Earlier dereferences, down the tree, will be handled
+ // at the same time, and logged to prevent reprocessing as the tree is traversed.
+ //
+ // Note: Other things like the following must be caught elsewhere:
+ // - a simple non-array, non-struct variable (no dereference even conceivable)
+ // - an aggregrate consumed en masse, without a dereference
+ //
+ // So, this code is for cases like
+ // - a struct/block dereferencing a member (whether the member is array or not)
+ // - an array of struct
+ // - structs/arrays containing the above
+ //
+ void addDereferencedUniform(TIntermBinary* topNode)
+ {
+ // See if too fine-grained to process (wait to get further down the tree)
+ const TType& leftType = topNode->getLeft()->getType();
+ if ((leftType.isVector() || leftType.isMatrix()) && ! leftType.isArray())
+ return;
+
+ // We have an array or structure or block dereference, see if it's a uniform
+ // based dereference (if not, skip it).
+ TIntermSymbol* base = findBase(topNode);
+ if (! base || ! base->getQualifier().isUniformOrBuffer())
+ return;
+
+ // See if we've already processed this (e.g., in the middle of something
+ // we did earlier), and if so skip it
+ if (processedDerefs.find(topNode) != processedDerefs.end())
+ return;
+
+ // Process this uniform dereference
+
+ int offset = -1;
+ int blockIndex = -1;
+ bool anonymous = false;
+
+ // See if we need to record the block itself
+ bool block = base->getBasicType() == EbtBlock;
+ if (block) {
+ offset = 0;
+ anonymous = IsAnonymous(base->getName());
+
+ const TString& blockName = base->getType().getTypeName();
+ TString baseName;
+
+ if (! anonymous)
+ baseName = blockName;
+
+ if (base->getType().isArray()) {
+ TType derefType(base->getType(), 0);
+
+ assert(! anonymous);
+ for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e)
+ blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType,
+ intermediate.getBlockSize(base->getType()));
+ baseName.append(TString("[0]"));
+ } else
+ blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
+
+ if (reflection.options & EShReflectionAllBlockVariables) {
+ // Use a degenerate (empty) set of dereferences to immediately put as at the end of
+ // the dereference change expected by blowUpActiveAggregate.
+ TList<TIntermBinary*> derefs;
+
+ // because we don't have any derefs, the first thing blowUpActiveAggregate will do is iterate over each
+ // member in the struct definition. This will lose any information about whether the parent was a buffer
+ // block. So if we're using strict array rules which don't expand the first child of a buffer block we
+ // instead iterate over the children here.
+ const bool strictArraySuffix = (reflection.options & EShReflectionStrictArraySuffix);
+ bool blockParent = (base->getType().getBasicType() == EbtBlock && base->getQualifier().storage == EvqBuffer);
+
+ if (strictArraySuffix && blockParent) {
+ TType structDerefType(base->getType(), 0);
+
+ const TType &structType = base->getType().isArray() ? structDerefType : base->getType();
+ const TTypeList& typeList = *structType.getStruct();
+
+ TVector<int> memberOffsets;
+
+ memberOffsets.resize(typeList.size());
+ getOffsets(structType, memberOffsets);
+
+ for (int i = 0; i < (int)typeList.size(); ++i) {
+ TType derefType(structType, i);
+ TString name = baseName;
+ if (name.size() > 0)
+ name.append(".");
+ name.append(typeList[i].type->getFieldName());
+
+ // if this member is an array, store the top-level array stride but start the explosion from
+ // the inner struct type.
+ if (derefType.isArray() && derefType.isStruct()) {
+ name.append("[0]");
+ blowUpActiveAggregate(TType(derefType, 0), name, derefs, derefs.end(), memberOffsets[i],
+ blockIndex, 0, getArrayStride(structType, derefType),
+ base->getQualifier().storage, false);
+ } else {
+ blowUpActiveAggregate(derefType, name, derefs, derefs.end(), memberOffsets[i], blockIndex,
+ 0, 0, base->getQualifier().storage, false);
+ }
+ }
+ } else {
+ // otherwise - if we're not using strict array suffix rules, or this isn't a block so we are
+ // expanding root arrays anyway, just start the iteration from the base block type.
+ blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, 0,
+ base->getQualifier().storage, false);
+ }
+ }
+ }
+
+ // Process the dereference chain, backward, accumulating the pieces for later forward traversal.
+ // If the topNode is a reflection-granularity-array dereference, don't include that last dereference.
+ TList<TIntermBinary*> derefs;
+ for (TIntermBinary* visitNode = topNode; visitNode; visitNode = visitNode->getLeft()->getAsBinaryNode()) {
+ if (isReflectionGranularity(visitNode->getLeft()->getType()))
+ continue;
+
+ derefs.push_front(visitNode);
+ processedDerefs.insert(visitNode);
+ }
+ processedDerefs.insert(base);
+
+ // See if we have a specific array size to stick to while enumerating the explosion of the aggregate
+ int arraySize = 0;
+ if (isReflectionGranularity(topNode->getLeft()->getType()) && topNode->getLeft()->isArray()) {
+ if (topNode->getOp() == EOpIndexDirect)
+ arraySize = topNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst() + 1;
+ }
+
+ // Put the dereference chain together, forward
+ TString baseName;
+ if (! anonymous) {
+ if (block)
+ baseName = base->getType().getTypeName();
+ else
+ baseName = base->getName();
+ }
+ blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, 0,
+ base->getQualifier().storage, true);
+ }
+
+ int addBlockName(const TString& name, const TType& type, int size)
+ {
+ TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
+
+ int blockIndex;
+ TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
+ if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
+ blockIndex = (int)blocks.size();
+ reflection.nameToIndex[name.c_str()] = blockIndex;
+ blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, -1));
+
+ blocks.back().numMembers = countAggregateMembers(type);
+
+ EShLanguageMask& stages = blocks.back().stages;
+ stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+ } else {
+ blockIndex = it->second;
+
+ EShLanguageMask& stages = blocks[blockIndex].stages;
+ stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
+ }
+
+ return blockIndex;
+ }
+
+ // Are we at a level in a dereference chain at which individual active uniform queries are made?
+ bool isReflectionGranularity(const TType& type)
+ {
+ return type.getBasicType() != EbtBlock && type.getBasicType() != EbtStruct && !type.isArrayOfArrays();
+ }
+
+ // For a binary operation indexing into an aggregate, chase down the base of the aggregate.
+ // Return 0 if the topology does not fit this situation.
+ TIntermSymbol* findBase(const TIntermBinary* node)
+ {
+ TIntermSymbol *base = node->getLeft()->getAsSymbolNode();
+ if (base)
+ return base;
+ TIntermBinary* left = node->getLeft()->getAsBinaryNode();
+ if (! left)
+ return nullptr;
+
+ return findBase(left);
+ }
+
+ //
+ // Translate a glslang sampler type into the GL API #define number.
+ //
+ int mapSamplerToGlType(TSampler sampler)
+ {
+ if (! sampler.image) {
+ // a sampler...
+ switch (sampler.type) {
+ case EbtFloat:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ switch ((int)sampler.shadow) {
+ case false: return sampler.arrayed ? GL_SAMPLER_1D_ARRAY : GL_SAMPLER_1D;
+ case true: return sampler.arrayed ? GL_SAMPLER_1D_ARRAY_SHADOW : GL_SAMPLER_1D_SHADOW;
+ }
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false:
+ switch ((int)sampler.shadow) {
+ case false: return sampler.arrayed ? GL_SAMPLER_2D_ARRAY : GL_SAMPLER_2D;
+ case true: return sampler.arrayed ? GL_SAMPLER_2D_ARRAY_SHADOW : GL_SAMPLER_2D_SHADOW;
+ }
+ case true: return sampler.arrayed ? GL_SAMPLER_2D_MULTISAMPLE_ARRAY : GL_SAMPLER_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_SAMPLER_3D;
+ case EsdCube:
+ switch ((int)sampler.shadow) {
+ case false: return sampler.arrayed ? GL_SAMPLER_CUBE_MAP_ARRAY : GL_SAMPLER_CUBE;
+ case true: return sampler.arrayed ? GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW : GL_SAMPLER_CUBE_SHADOW;
+ }
+ case EsdRect:
+ return sampler.shadow ? GL_SAMPLER_2D_RECT_SHADOW : GL_SAMPLER_2D_RECT;
+ case EsdBuffer:
+ return GL_SAMPLER_BUFFER;
+ }
+ case EbtFloat16:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ switch ((int)sampler.shadow) {
+ case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_1D_ARRAY_AMD : GL_FLOAT16_SAMPLER_1D_AMD;
+ case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_1D_SHADOW_AMD;
+ }
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false:
+ switch ((int)sampler.shadow) {
+ case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_ARRAY_AMD : GL_FLOAT16_SAMPLER_2D_AMD;
+ case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_2D_SHADOW_AMD;
+ }
+ case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD : GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD;
+ }
+ case Esd3D:
+ return GL_FLOAT16_SAMPLER_3D_AMD;
+ case EsdCube:
+ switch ((int)sampler.shadow) {
+ case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD : GL_FLOAT16_SAMPLER_CUBE_AMD;
+ case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD;
+ }
+ case EsdRect:
+ return sampler.shadow ? GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD : GL_FLOAT16_SAMPLER_2D_RECT_AMD;
+ case EsdBuffer:
+ return GL_FLOAT16_SAMPLER_BUFFER_AMD;
+ }
+ case EbtInt:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_INT_SAMPLER_1D_ARRAY : GL_INT_SAMPLER_1D;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_INT_SAMPLER_2D_ARRAY : GL_INT_SAMPLER_2D;
+ case true: return sampler.arrayed ? GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
+ : GL_INT_SAMPLER_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_INT_SAMPLER_3D;
+ case EsdCube:
+ return sampler.arrayed ? GL_INT_SAMPLER_CUBE_MAP_ARRAY : GL_INT_SAMPLER_CUBE;
+ case EsdRect:
+ return GL_INT_SAMPLER_2D_RECT;
+ case EsdBuffer:
+ return GL_INT_SAMPLER_BUFFER;
+ }
+ case EbtUint:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_1D_ARRAY : GL_UNSIGNED_INT_SAMPLER_1D;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_ARRAY : GL_UNSIGNED_INT_SAMPLER_2D;
+ case true: return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
+ : GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_UNSIGNED_INT_SAMPLER_3D;
+ case EsdCube:
+ return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY : GL_UNSIGNED_INT_SAMPLER_CUBE;
+ case EsdRect:
+ return GL_UNSIGNED_INT_SAMPLER_2D_RECT;
+ case EsdBuffer:
+ return GL_UNSIGNED_INT_SAMPLER_BUFFER;
+ }
+ default:
+ return 0;
+ }
+ } else {
+ // an image...
+ switch (sampler.type) {
+ case EbtFloat:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_IMAGE_1D_ARRAY : GL_IMAGE_1D;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_IMAGE_2D_ARRAY : GL_IMAGE_2D;
+ case true: return sampler.arrayed ? GL_IMAGE_2D_MULTISAMPLE_ARRAY : GL_IMAGE_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_IMAGE_3D;
+ case EsdCube:
+ return sampler.arrayed ? GL_IMAGE_CUBE_MAP_ARRAY : GL_IMAGE_CUBE;
+ case EsdRect:
+ return GL_IMAGE_2D_RECT;
+ case EsdBuffer:
+ return GL_IMAGE_BUFFER;
+ }
+ case EbtFloat16:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_FLOAT16_IMAGE_1D_ARRAY_AMD : GL_FLOAT16_IMAGE_1D_AMD;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_FLOAT16_IMAGE_2D_ARRAY_AMD : GL_FLOAT16_IMAGE_2D_AMD;
+ case true: return sampler.arrayed ? GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD : GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD;
+ }
+ case Esd3D:
+ return GL_FLOAT16_IMAGE_3D_AMD;
+ case EsdCube:
+ return sampler.arrayed ? GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD : GL_FLOAT16_IMAGE_CUBE_AMD;
+ case EsdRect:
+ return GL_FLOAT16_IMAGE_2D_RECT_AMD;
+ case EsdBuffer:
+ return GL_FLOAT16_IMAGE_BUFFER_AMD;
+ }
+ case EbtInt:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_INT_IMAGE_1D_ARRAY : GL_INT_IMAGE_1D;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_INT_IMAGE_2D_ARRAY : GL_INT_IMAGE_2D;
+ case true: return sampler.arrayed ? GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY : GL_INT_IMAGE_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_INT_IMAGE_3D;
+ case EsdCube:
+ return sampler.arrayed ? GL_INT_IMAGE_CUBE_MAP_ARRAY : GL_INT_IMAGE_CUBE;
+ case EsdRect:
+ return GL_INT_IMAGE_2D_RECT;
+ case EsdBuffer:
+ return GL_INT_IMAGE_BUFFER;
+ }
+ case EbtUint:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_1D_ARRAY : GL_UNSIGNED_INT_IMAGE_1D;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_ARRAY : GL_UNSIGNED_INT_IMAGE_2D;
+ case true: return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY
+ : GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_UNSIGNED_INT_IMAGE_3D;
+ case EsdCube:
+ return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY : GL_UNSIGNED_INT_IMAGE_CUBE;
+ case EsdRect:
+ return GL_UNSIGNED_INT_IMAGE_2D_RECT;
+ case EsdBuffer:
+ return GL_UNSIGNED_INT_IMAGE_BUFFER;
+ }
+ default:
+ return 0;
+ }
+ }
+ }
+
+ //
+ // Translate a glslang type into the GL API #define number.
+ // Ignores arrayness.
+ //
+ int mapToGlType(const TType& type)
+ {
+ switch (type.getBasicType()) {
+ case EbtSampler:
+ return mapSamplerToGlType(type.getSampler());
+ case EbtStruct:
+ case EbtBlock:
+ case EbtVoid:
+ return 0;
+ default:
+ break;
+ }
+
+ if (type.isVector()) {
+ int offset = type.getVectorSize() - 2;
+ switch (type.getBasicType()) {
+ case EbtFloat: return GL_FLOAT_VEC2 + offset;
+ case EbtDouble: return GL_DOUBLE_VEC2 + offset;
+ case EbtFloat16: return GL_FLOAT16_VEC2_NV + offset;
+ case EbtInt: return GL_INT_VEC2 + offset;
+ case EbtUint: return GL_UNSIGNED_INT_VEC2 + offset;
+ case EbtInt64: return GL_INT64_ARB + offset;
+ case EbtUint64: return GL_UNSIGNED_INT64_ARB + offset;
+ case EbtBool: return GL_BOOL_VEC2 + offset;
+ case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER + offset;
+ default: return 0;
+ }
+ }
+ if (type.isMatrix()) {
+ switch (type.getBasicType()) {
+ case EbtFloat:
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_FLOAT_MAT2;
+ case 3: return GL_FLOAT_MAT2x3;
+ case 4: return GL_FLOAT_MAT2x4;
+ default: return 0;
+ }
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_FLOAT_MAT3x2;
+ case 3: return GL_FLOAT_MAT3;
+ case 4: return GL_FLOAT_MAT3x4;
+ default: return 0;
+ }
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_FLOAT_MAT4x2;
+ case 3: return GL_FLOAT_MAT4x3;
+ case 4: return GL_FLOAT_MAT4;
+ default: return 0;
+ }
+ }
+ case EbtDouble:
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_DOUBLE_MAT2;
+ case 3: return GL_DOUBLE_MAT2x3;
+ case 4: return GL_DOUBLE_MAT2x4;
+ default: return 0;
+ }
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_DOUBLE_MAT3x2;
+ case 3: return GL_DOUBLE_MAT3;
+ case 4: return GL_DOUBLE_MAT3x4;
+ default: return 0;
+ }
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_DOUBLE_MAT4x2;
+ case 3: return GL_DOUBLE_MAT4x3;
+ case 4: return GL_DOUBLE_MAT4;
+ default: return 0;
+ }
+ }
+ case EbtFloat16:
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_FLOAT16_MAT2_AMD;
+ case 3: return GL_FLOAT16_MAT2x3_AMD;
+ case 4: return GL_FLOAT16_MAT2x4_AMD;
+ default: return 0;
+ }
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_FLOAT16_MAT3x2_AMD;
+ case 3: return GL_FLOAT16_MAT3_AMD;
+ case 4: return GL_FLOAT16_MAT3x4_AMD;
+ default: return 0;
+ }
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_FLOAT16_MAT4x2_AMD;
+ case 3: return GL_FLOAT16_MAT4x3_AMD;
+ case 4: return GL_FLOAT16_MAT4_AMD;
+ default: return 0;
+ }
+ }
+ default:
+ return 0;
+ }
+ }
+ if (type.getVectorSize() == 1) {
+ switch (type.getBasicType()) {
+ case EbtFloat: return GL_FLOAT;
+ case EbtDouble: return GL_DOUBLE;
+ case EbtFloat16: return GL_FLOAT16_NV;
+ case EbtInt: return GL_INT;
+ case EbtUint: return GL_UNSIGNED_INT;
+ case EbtInt64: return GL_INT64_ARB;
+ case EbtUint64: return GL_UNSIGNED_INT64_ARB;
+ case EbtBool: return GL_BOOL;
+ case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER;
+ default: return 0;
+ }
+ }
+
+ return 0;
+ }
+
+ int mapToGlArraySize(const TType& type)
+ {
+ return type.isArray() ? type.getOuterArraySize() : 1;
+ }
+
+ TReflection& reflection;
+ std::set<const TIntermNode*> processedDerefs;
+
+protected:
+ TReflectionTraverser(TReflectionTraverser&);
+ TReflectionTraverser& operator=(TReflectionTraverser&);
+};
+
+//
+// Implement the traversal functions of interest.
+//
+
+// To catch dereferenced aggregates that must be reflected.
+// This catches them at the highest level possible in the tree.
+bool TReflectionTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
+{
+ switch (node->getOp()) {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ addDereferencedUniform(node);
+ break;
+ default:
+ break;
+ }
+
+ // still need to visit everything below, which could contain sub-expressions
+ // containing different uniforms
+ return true;
+}
+
+// To reflect non-dereferenced objects.
+void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
+{
+ if (base->getQualifier().storage == EvqUniform)
+ addUniform(*base);
+
+ if ((intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput()) ||
+ (intermediate.getStage() == reflection.lastStage && base->getQualifier().isPipeOutput()))
+ addPipeIOVariable(*base);
+}
+
+//
+// Implement TObjectReflection methods.
+//
+
+TObjectReflection::TObjectReflection(const std::string &pName, const TType &pType, int pOffset, int pGLDefineType,
+ int pSize, int pIndex)
+ : name(pName), offset(pOffset), glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1),
+ numMembers(-1), arrayStride(0), topLevelArrayStride(0), stages(EShLanguageMask(0)), type(pType.clone())
+{
+}
+
+int TObjectReflection::getBinding() const
+{
+ if (type == nullptr || !type->getQualifier().hasBinding())
+ return -1;
+ return type->getQualifier().layoutBinding;
+}
+
+void TObjectReflection::dump() const
+{
+ printf("%s: offset %d, type %x, size %d, index %d, binding %d, stages %d", name.c_str(), offset, glDefineType, size,
+ index, getBinding(), stages);
+
+ if (counterIndex != -1)
+ printf(", counter %d", counterIndex);
+
+ if (numMembers != -1)
+ printf(", numMembers %d", numMembers);
+
+ if (arrayStride != 0)
+ printf(", arrayStride %d", arrayStride);
+
+ if (topLevelArrayStride != 0)
+ printf(", topLevelArrayStride %d", topLevelArrayStride);
+
+ printf("\n");
+}
+
+//
+// Implement TReflection methods.
+//
+
+// Track any required attribute reflection, such as compute shader numthreads.
+//
+void TReflection::buildAttributeReflection(EShLanguage stage, const TIntermediate& intermediate)
+{
+ if (stage == EShLangCompute) {
+ // Remember thread dimensions
+ for (int dim=0; dim<3; ++dim)
+ localSize[dim] = intermediate.getLocalSize(dim);
+ }
+}
+
+// build counter block index associations for buffers
+void TReflection::buildCounterIndices(const TIntermediate& intermediate)
+{
+#ifdef ENABLE_HLSL
+ // search for ones that have counters
+ for (int i = 0; i < int(indexToUniformBlock.size()); ++i) {
+ const TString counterName(intermediate.addCounterBufferName(indexToUniformBlock[i].name).c_str());
+ const int index = getIndex(counterName);
+
+ if (index >= 0)
+ indexToUniformBlock[i].counterIndex = index;
+ }
+#endif
+}
+
+// build Shader Stages mask for all uniforms
+void TReflection::buildUniformStageMask(const TIntermediate& intermediate)
+{
+ if (options & EShReflectionAllBlockVariables)
+ return;
+
+ for (int i = 0; i < int(indexToUniform.size()); ++i) {
+ indexToUniform[i].stages = static_cast<EShLanguageMask>(indexToUniform[i].stages | 1 << intermediate.getStage());
+ }
+
+ for (int i = 0; i < int(indexToBufferVariable.size()); ++i) {
+ indexToBufferVariable[i].stages =
+ static_cast<EShLanguageMask>(indexToBufferVariable[i].stages | 1 << intermediate.getStage());
+ }
+}
+
+// Merge live symbols from 'intermediate' into the existing reflection database.
+//
+// Returns false if the input is too malformed to do this.
+bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
+{
+ if (intermediate.getTreeRoot() == nullptr ||
+ intermediate.getNumEntryPoints() != 1 ||
+ intermediate.isRecursive())
+ return false;
+
+ buildAttributeReflection(stage, intermediate);
+
+ TReflectionTraverser it(intermediate, *this);
+
+ // put the entry point on the list of functions to process
+ it.pushFunction(intermediate.getEntryPointMangledName().c_str());
+
+ // process all the functions
+ while (! it.functions.empty()) {
+ TIntermNode* function = it.functions.back();
+ it.functions.pop_back();
+ function->traverse(&it);
+ }
+
+ buildCounterIndices(intermediate);
+ buildUniformStageMask(intermediate);
+
+ return true;
+}
+
+void TReflection::dump()
+{
+ printf("Uniform reflection:\n");
+ for (size_t i = 0; i < indexToUniform.size(); ++i)
+ indexToUniform[i].dump();
+ printf("\n");
+
+ printf("Uniform block reflection:\n");
+ for (size_t i = 0; i < indexToUniformBlock.size(); ++i)
+ indexToUniformBlock[i].dump();
+ printf("\n");
+
+ printf("Buffer variable reflection:\n");
+ for (size_t i = 0; i < indexToBufferVariable.size(); ++i)
+ indexToBufferVariable[i].dump();
+ printf("\n");
+
+ printf("Buffer block reflection:\n");
+ for (size_t i = 0; i < indexToBufferBlock.size(); ++i)
+ indexToBufferBlock[i].dump();
+ printf("\n");
+
+ printf("Pipeline input reflection:\n");
+ for (size_t i = 0; i < indexToPipeInput.size(); ++i)
+ indexToPipeInput[i].dump();
+ printf("\n");
+
+ printf("Pipeline output reflection:\n");
+ for (size_t i = 0; i < indexToPipeOutput.size(); ++i)
+ indexToPipeOutput[i].dump();
+ printf("\n");
+
+ if (getLocalSize(0) > 1) {
+ static const char* axis[] = { "X", "Y", "Z" };
+
+ for (int dim=0; dim<3; ++dim)
+ if (getLocalSize(dim) > 1)
+ printf("Local size %s: %d\n", axis[dim], getLocalSize(dim));
+
+ printf("\n");
+ }
+
+ // printf("Live names\n");
+ // for (TNameToIndex::const_iterator it = nameToIndex.begin(); it != nameToIndex.end(); ++it)
+ // printf("%s: %d\n", it->first.c_str(), it->second);
+ // printf("\n");
+}
+
+} // end namespace glslang
+
+#endif // GLSLANG_WEB
diff --git a/thirdparty/glslang/glslang/MachineIndependent/reflection.h b/thirdparty/glslang/glslang/MachineIndependent/reflection.h
new file mode 100644
index 0000000000..efdc8934fb
--- /dev/null
+++ b/thirdparty/glslang/glslang/MachineIndependent/reflection.h
@@ -0,0 +1,223 @@
+//
+// Copyright (C) 2013-2016 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef GLSLANG_WEB
+
+#ifndef _REFLECTION_INCLUDED
+#define _REFLECTION_INCLUDED
+
+#include "../Public/ShaderLang.h"
+#include "../Include/Types.h"
+
+#include <list>
+#include <set>
+
+//
+// A reflection database and its interface, consistent with the OpenGL API reflection queries.
+//
+
+namespace glslang {
+
+class TIntermediate;
+class TIntermAggregate;
+class TReflectionTraverser;
+
+// The full reflection database
+class TReflection {
+public:
+ TReflection(EShReflectionOptions opts, EShLanguage first, EShLanguage last)
+ : options(opts), firstStage(first), lastStage(last), badReflection(TObjectReflection::badReflection())
+ {
+ for (int dim=0; dim<3; ++dim)
+ localSize[dim] = 0;
+ }
+
+ virtual ~TReflection() {}
+
+ // grow the reflection stage by stage
+ bool addStage(EShLanguage, const TIntermediate&);
+
+ // for mapping a uniform index to a uniform object's description
+ int getNumUniforms() { return (int)indexToUniform.size(); }
+ const TObjectReflection& getUniform(int i) const
+ {
+ if (i >= 0 && i < (int)indexToUniform.size())
+ return indexToUniform[i];
+ else
+ return badReflection;
+ }
+
+ // for mapping a block index to the block's description
+ int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); }
+ const TObjectReflection& getUniformBlock(int i) const
+ {
+ if (i >= 0 && i < (int)indexToUniformBlock.size())
+ return indexToUniformBlock[i];
+ else
+ return badReflection;
+ }
+
+ // for mapping an pipeline input index to the input's description
+ int getNumPipeInputs() { return (int)indexToPipeInput.size(); }
+ const TObjectReflection& getPipeInput(int i) const
+ {
+ if (i >= 0 && i < (int)indexToPipeInput.size())
+ return indexToPipeInput[i];
+ else
+ return badReflection;
+ }
+
+ // for mapping an pipeline output index to the output's description
+ int getNumPipeOutputs() { return (int)indexToPipeOutput.size(); }
+ const TObjectReflection& getPipeOutput(int i) const
+ {
+ if (i >= 0 && i < (int)indexToPipeOutput.size())
+ return indexToPipeOutput[i];
+ else
+ return badReflection;
+ }
+
+ // for mapping from an atomic counter to the uniform index
+ int getNumAtomicCounters() const { return (int)atomicCounterUniformIndices.size(); }
+ const TObjectReflection& getAtomicCounter(int i) const
+ {
+ if (i >= 0 && i < (int)atomicCounterUniformIndices.size())
+ return getUniform(atomicCounterUniformIndices[i]);
+ else
+ return badReflection;
+ }
+
+ // for mapping a buffer variable index to a buffer variable object's description
+ int getNumBufferVariables() { return (int)indexToBufferVariable.size(); }
+ const TObjectReflection& getBufferVariable(int i) const
+ {
+ if (i >= 0 && i < (int)indexToBufferVariable.size())
+ return indexToBufferVariable[i];
+ else
+ return badReflection;
+ }
+
+ // for mapping a storage block index to the storage block's description
+ int getNumStorageBuffers() const { return (int)indexToBufferBlock.size(); }
+ const TObjectReflection& getStorageBufferBlock(int i) const
+ {
+ if (i >= 0 && i < (int)indexToBufferBlock.size())
+ return indexToBufferBlock[i];
+ else
+ return badReflection;
+ }
+
+ // for mapping any name to its index (block names, uniform names and input/output names)
+ int getIndex(const char* name) const
+ {
+ TNameToIndex::const_iterator it = nameToIndex.find(name);
+ if (it == nameToIndex.end())
+ return -1;
+ else
+ return it->second;
+ }
+
+ // see getIndex(const char*)
+ int getIndex(const TString& name) const { return getIndex(name.c_str()); }
+
+
+ // for mapping any name to its index (only pipe input/output names)
+ int getPipeIOIndex(const char* name, const bool inOrOut) const
+ {
+ TNameToIndex::const_iterator it = inOrOut ? pipeInNameToIndex.find(name) : pipeOutNameToIndex.find(name);
+ if (it == (inOrOut ? pipeInNameToIndex.end() : pipeOutNameToIndex.end()))
+ return -1;
+ else
+ return it->second;
+ }
+
+ // see gePipeIOIndex(const char*, const bool)
+ int getPipeIOIndex(const TString& name, const bool inOrOut) const { return getPipeIOIndex(name.c_str(), inOrOut); }
+
+ // Thread local size
+ unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; }
+
+ void dump();
+
+protected:
+ friend class glslang::TReflectionTraverser;
+
+ void buildCounterIndices(const TIntermediate&);
+ void buildUniformStageMask(const TIntermediate& intermediate);
+ void buildAttributeReflection(EShLanguage, const TIntermediate&);
+
+ // Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;
+ typedef std::map<std::string, int> TNameToIndex;
+ typedef std::vector<TObjectReflection> TMapIndexToReflection;
+ typedef std::vector<int> TIndices;
+
+ TMapIndexToReflection& GetBlockMapForStorage(TStorageQualifier storage)
+ {
+ if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer)
+ return indexToBufferBlock;
+ return indexToUniformBlock;
+ }
+ TMapIndexToReflection& GetVariableMapForStorage(TStorageQualifier storage)
+ {
+ if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer)
+ return indexToBufferVariable;
+ return indexToUniform;
+ }
+
+ EShReflectionOptions options;
+
+ EShLanguage firstStage;
+ EShLanguage lastStage;
+
+ TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this
+ TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed
+ TNameToIndex pipeInNameToIndex; // maps pipe in names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers.
+ TNameToIndex pipeOutNameToIndex; // maps pipe out names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers.
+ TMapIndexToReflection indexToUniform;
+ TMapIndexToReflection indexToUniformBlock;
+ TMapIndexToReflection indexToBufferVariable;
+ TMapIndexToReflection indexToBufferBlock;
+ TMapIndexToReflection indexToPipeInput;
+ TMapIndexToReflection indexToPipeOutput;
+ TIndices atomicCounterUniformIndices;
+
+ unsigned int localSize[3];
+};
+
+} // end namespace glslang
+
+#endif // _REFLECTION_INCLUDED
+
+#endif // GLSLANG_WEB \ No newline at end of file
diff --git a/thirdparty/glslang/glslang/OSDependent/Unix/ossource.cpp b/thirdparty/glslang/glslang/OSDependent/Unix/ossource.cpp
new file mode 100644
index 0000000000..3f029f0239
--- /dev/null
+++ b/thirdparty/glslang/glslang/OSDependent/Unix/ossource.cpp
@@ -0,0 +1,207 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// This file contains the Linux-specific functions
+//
+#include "../osinclude.h"
+#include "../../../OGLCompilersDLL/InitializeDll.h"
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <cstdio>
+#include <sys/time.h>
+
+#if !defined(__Fuchsia__)
+#include <sys/resource.h>
+#endif
+
+namespace glslang {
+
+//
+// Thread cleanup
+//
+
+//
+// Wrapper for Linux call to DetachThread. This is required as pthread_cleanup_push() expects
+// the cleanup routine to return void.
+//
+static void DetachThreadLinux(void *)
+{
+ DetachThread();
+}
+
+//
+// Registers cleanup handler, sets cancel type and state, and executes the thread specific
+// cleanup handler. This function will be called in the Standalone.cpp for regression
+// testing. When OpenGL applications are run with the driver code, Linux OS does the
+// thread cleanup.
+//
+void OS_CleanupThreadData(void)
+{
+#if defined(__ANDROID__) || defined(__Fuchsia__)
+ DetachThreadLinux(NULL);
+#else
+ int old_cancel_state, old_cancel_type;
+ void *cleanupArg = NULL;
+
+ //
+ // Set thread cancel state and push cleanup handler.
+ //
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancel_state);
+ pthread_cleanup_push(DetachThreadLinux, (void *) cleanupArg);
+
+ //
+ // Put the thread in deferred cancellation mode.
+ //
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &old_cancel_type);
+
+ //
+ // Pop cleanup handler and execute it prior to unregistering the cleanup handler.
+ //
+ pthread_cleanup_pop(1);
+
+ //
+ // Restore the thread's previous cancellation mode.
+ //
+ pthread_setcanceltype(old_cancel_state, NULL);
+#endif
+}
+
+//
+// Thread Local Storage Operations
+//
+inline OS_TLSIndex PthreadKeyToTLSIndex(pthread_key_t key)
+{
+ return (OS_TLSIndex)((uintptr_t)key + 1);
+}
+
+inline pthread_key_t TLSIndexToPthreadKey(OS_TLSIndex nIndex)
+{
+ return (pthread_key_t)((uintptr_t)nIndex - 1);
+}
+
+OS_TLSIndex OS_AllocTLSIndex()
+{
+ pthread_key_t pPoolIndex;
+
+ //
+ // Create global pool key.
+ //
+ if ((pthread_key_create(&pPoolIndex, NULL)) != 0) {
+ assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+ return OS_INVALID_TLS_INDEX;
+ }
+ else
+ return PthreadKeyToTLSIndex(pPoolIndex);
+}
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (pthread_setspecific(TLSIndexToPthreadKey(nIndex), lpvValue) == 0)
+ return true;
+ else
+ return false;
+}
+
+void* OS_GetTLSValue(OS_TLSIndex nIndex)
+{
+ //
+ // This function should return 0 if nIndex is invalid.
+ //
+ assert(nIndex != OS_INVALID_TLS_INDEX);
+ return pthread_getspecific(TLSIndexToPthreadKey(nIndex));
+}
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ //
+ // Delete the global pool key.
+ //
+ if (pthread_key_delete(TLSIndexToPthreadKey(nIndex)) == 0)
+ return true;
+ else
+ return false;
+}
+
+namespace {
+ pthread_mutex_t gMutex;
+}
+
+void InitGlobalLock()
+{
+ pthread_mutexattr_t mutexattr;
+ pthread_mutexattr_init(&mutexattr);
+ pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&gMutex, &mutexattr);
+}
+
+void GetGlobalLock()
+{
+ pthread_mutex_lock(&gMutex);
+}
+
+void ReleaseGlobalLock()
+{
+ pthread_mutex_unlock(&gMutex);
+}
+
+// #define DUMP_COUNTERS
+
+void OS_DumpMemoryCounters()
+{
+#ifdef DUMP_COUNTERS
+ struct rusage usage;
+
+ if (getrusage(RUSAGE_SELF, &usage) == 0)
+ printf("Working set size: %ld\n", usage.ru_maxrss * 1024);
+#else
+ printf("Recompile with DUMP_COUNTERS defined to see counters.\n");
+#endif
+}
+
+} // end namespace glslang
diff --git a/thirdparty/glslang/glslang/OSDependent/Web/glslang.after.js b/thirdparty/glslang/glslang/OSDependent/Web/glslang.after.js
new file mode 100644
index 0000000000..c2cfc35a48
--- /dev/null
+++ b/thirdparty/glslang/glslang/OSDependent/Web/glslang.after.js
@@ -0,0 +1,26 @@
+export default (() => {
+ const initialize = () => {
+ return new Promise(resolve => {
+ Module({
+ locateFile() {
+ const i = import.meta.url.lastIndexOf('/')
+ return import.meta.url.substring(0, i) + '/glslang.wasm';
+ },
+ onRuntimeInitialized() {
+ resolve({
+ compileGLSLZeroCopy: this.compileGLSLZeroCopy,
+ compileGLSL: this.compileGLSL,
+ });
+ },
+ });
+ });
+ };
+
+ let instance;
+ return () => {
+ if (!instance) {
+ instance = initialize();
+ }
+ return instance;
+ };
+})();
diff --git a/thirdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp b/thirdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp
new file mode 100644
index 0000000000..6cb93fe27e
--- /dev/null
+++ b/thirdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp
@@ -0,0 +1,269 @@
+//
+// Copyright (C) 2019 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include <cstdio>
+#include <cstdint>
+#include <memory>
+
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
+#include "../../../SPIRV/GlslangToSpv.h"
+#include "../../../glslang/Public/ShaderLang.h"
+
+#ifndef __EMSCRIPTEN__
+#define EMSCRIPTEN_KEEPALIVE
+#endif
+
+const TBuiltInResource DefaultTBuiltInResource = {
+ /* .MaxLights = */ 32,
+ /* .MaxClipPlanes = */ 6,
+ /* .MaxTextureUnits = */ 32,
+ /* .MaxTextureCoords = */ 32,
+ /* .MaxVertexAttribs = */ 64,
+ /* .MaxVertexUniformComponents = */ 4096,
+ /* .MaxVaryingFloats = */ 64,
+ /* .MaxVertexTextureImageUnits = */ 32,
+ /* .MaxCombinedTextureImageUnits = */ 80,
+ /* .MaxTextureImageUnits = */ 32,
+ /* .MaxFragmentUniformComponents = */ 4096,
+ /* .MaxDrawBuffers = */ 32,
+ /* .MaxVertexUniformVectors = */ 128,
+ /* .MaxVaryingVectors = */ 8,
+ /* .MaxFragmentUniformVectors = */ 16,
+ /* .MaxVertexOutputVectors = */ 16,
+ /* .MaxFragmentInputVectors = */ 15,
+ /* .MinProgramTexelOffset = */ -8,
+ /* .MaxProgramTexelOffset = */ 7,
+ /* .MaxClipDistances = */ 8,
+ /* .MaxComputeWorkGroupCountX = */ 65535,
+ /* .MaxComputeWorkGroupCountY = */ 65535,
+ /* .MaxComputeWorkGroupCountZ = */ 65535,
+ /* .MaxComputeWorkGroupSizeX = */ 1024,
+ /* .MaxComputeWorkGroupSizeY = */ 1024,
+ /* .MaxComputeWorkGroupSizeZ = */ 64,
+ /* .MaxComputeUniformComponents = */ 1024,
+ /* .MaxComputeTextureImageUnits = */ 16,
+ /* .MaxComputeImageUniforms = */ 8,
+ /* .MaxComputeAtomicCounters = */ 8,
+ /* .MaxComputeAtomicCounterBuffers = */ 1,
+ /* .MaxVaryingComponents = */ 60,
+ /* .MaxVertexOutputComponents = */ 64,
+ /* .MaxGeometryInputComponents = */ 64,
+ /* .MaxGeometryOutputComponents = */ 128,
+ /* .MaxFragmentInputComponents = */ 128,
+ /* .MaxImageUnits = */ 8,
+ /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
+ /* .MaxCombinedShaderOutputResources = */ 8,
+ /* .MaxImageSamples = */ 0,
+ /* .MaxVertexImageUniforms = */ 0,
+ /* .MaxTessControlImageUniforms = */ 0,
+ /* .MaxTessEvaluationImageUniforms = */ 0,
+ /* .MaxGeometryImageUniforms = */ 0,
+ /* .MaxFragmentImageUniforms = */ 8,
+ /* .MaxCombinedImageUniforms = */ 8,
+ /* .MaxGeometryTextureImageUnits = */ 16,
+ /* .MaxGeometryOutputVertices = */ 256,
+ /* .MaxGeometryTotalOutputComponents = */ 1024,
+ /* .MaxGeometryUniformComponents = */ 1024,
+ /* .MaxGeometryVaryingComponents = */ 64,
+ /* .MaxTessControlInputComponents = */ 128,
+ /* .MaxTessControlOutputComponents = */ 128,
+ /* .MaxTessControlTextureImageUnits = */ 16,
+ /* .MaxTessControlUniformComponents = */ 1024,
+ /* .MaxTessControlTotalOutputComponents = */ 4096,
+ /* .MaxTessEvaluationInputComponents = */ 128,
+ /* .MaxTessEvaluationOutputComponents = */ 128,
+ /* .MaxTessEvaluationTextureImageUnits = */ 16,
+ /* .MaxTessEvaluationUniformComponents = */ 1024,
+ /* .MaxTessPatchComponents = */ 120,
+ /* .MaxPatchVertices = */ 32,
+ /* .MaxTessGenLevel = */ 64,
+ /* .MaxViewports = */ 16,
+ /* .MaxVertexAtomicCounters = */ 0,
+ /* .MaxTessControlAtomicCounters = */ 0,
+ /* .MaxTessEvaluationAtomicCounters = */ 0,
+ /* .MaxGeometryAtomicCounters = */ 0,
+ /* .MaxFragmentAtomicCounters = */ 8,
+ /* .MaxCombinedAtomicCounters = */ 8,
+ /* .MaxAtomicCounterBindings = */ 1,
+ /* .MaxVertexAtomicCounterBuffers = */ 0,
+ /* .MaxTessControlAtomicCounterBuffers = */ 0,
+ /* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
+ /* .MaxGeometryAtomicCounterBuffers = */ 0,
+ /* .MaxFragmentAtomicCounterBuffers = */ 1,
+ /* .MaxCombinedAtomicCounterBuffers = */ 1,
+ /* .MaxAtomicCounterBufferSize = */ 16384,
+ /* .MaxTransformFeedbackBuffers = */ 4,
+ /* .MaxTransformFeedbackInterleavedComponents = */ 64,
+ /* .MaxCullDistances = */ 8,
+ /* .MaxCombinedClipAndCullDistances = */ 8,
+ /* .MaxSamples = */ 4,
+ /* .maxMeshOutputVerticesNV = */ 256,
+ /* .maxMeshOutputPrimitivesNV = */ 512,
+ /* .maxMeshWorkGroupSizeX_NV = */ 32,
+ /* .maxMeshWorkGroupSizeY_NV = */ 1,
+ /* .maxMeshWorkGroupSizeZ_NV = */ 1,
+ /* .maxTaskWorkGroupSizeX_NV = */ 32,
+ /* .maxTaskWorkGroupSizeY_NV = */ 1,
+ /* .maxTaskWorkGroupSizeZ_NV = */ 1,
+ /* .maxMeshViewCountNV = */ 4,
+
+ /* .limits = */ {
+ /* .nonInductiveForLoops = */ 1,
+ /* .whileLoops = */ 1,
+ /* .doWhileLoops = */ 1,
+ /* .generalUniformIndexing = */ 1,
+ /* .generalAttributeMatrixVectorIndexing = */ 1,
+ /* .generalVaryingIndexing = */ 1,
+ /* .generalSamplerIndexing = */ 1,
+ /* .generalVariableIndexing = */ 1,
+ /* .generalConstantMatrixVectorIndexing = */ 1,
+ }};
+
+static bool initialized = false;
+
+extern "C" {
+
+/*
+ * Takes in a GLSL shader as a string and converts it to SPIR-V in binary form.
+ *
+ * |glsl| Null-terminated string containing the shader to be converted.
+ * |stage_int| Magic number indicating the type of shader being processed.
+* Legal values are as follows:
+ * Vertex = 0
+ * Fragment = 4
+ * Compute = 5
+ * |gen_debug| Flag to indicate if debug information should be generated.
+ * |spirv| Output parameter for a pointer to the resulting SPIR-V data.
+ * |spirv_len| Output parameter for the length of the output binary buffer.
+ *
+ * Returns a void* pointer which, if not null, must be destroyed by
+ * destroy_output_buffer.o. (This is not the same pointer returned in |spirv|.)
+ * If null, the compilation failed.
+ */
+EMSCRIPTEN_KEEPALIVE
+void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uint32_t** spirv, size_t* spirv_len)
+{
+ if (glsl == nullptr) {
+ fprintf(stderr, "Input pointer null\n");
+ return nullptr;
+ }
+ if (spirv == nullptr || spirv_len == nullptr) {
+ fprintf(stderr, "Output pointer null\n");
+ return nullptr;
+ }
+ *spirv = nullptr;
+ *spirv_len = 0;
+
+ if (stage_int != 0 && stage_int != 4 && stage_int != 5) {
+ fprintf(stderr, "Invalid shader stage\n");
+ return nullptr;
+ }
+ EShLanguage stage = static_cast<EShLanguage>(stage_int);
+
+ if (!initialized) {
+ glslang::InitializeProcess();
+ initialized = true;
+ }
+
+ glslang::TShader shader(stage);
+ shader.setStrings(&glsl, 1);
+ shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100);
+ shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
+ shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
+ if (!shader.parse(&DefaultTBuiltInResource, 100, true, EShMsgDefault)) {
+ fprintf(stderr, "Parse failed\n");
+ fprintf(stderr, "%s\n", shader.getInfoLog());
+ return nullptr;
+ }
+
+ glslang::TProgram program;
+ program.addShader(&shader);
+ if (!program.link(EShMsgDefault)) {
+ fprintf(stderr, "Link failed\n");
+ fprintf(stderr, "%s\n", program.getInfoLog());
+ return nullptr;
+ }
+
+ glslang::SpvOptions spvOptions;
+ spvOptions.generateDebugInfo = gen_debug;
+ spvOptions.optimizeSize = false;
+ spvOptions.disassemble = false;
+ spvOptions.validate = false;
+
+ std::vector<uint32_t>* output = new std::vector<uint32_t>;
+ glslang::GlslangToSpv(*program.getIntermediate(stage), *output, nullptr, &spvOptions);
+
+ *spirv_len = output->size();
+ *spirv = output->data();
+ return output;
+}
+
+/*
+ * Destroys a buffer created by convert_glsl_to_spirv
+ */
+EMSCRIPTEN_KEEPALIVE
+void destroy_output_buffer(void* p)
+{
+ delete static_cast<std::vector<uint32_t>*>(p);
+}
+
+} // extern "C"
+
+/*
+ * For non-Emscripten builds we supply a generic main, so that the glslang.js
+ * build target can generate an executable with a trivial use case instead of
+ * generating a WASM binary. This is done so that there is a target that can be
+ * built and output analyzed using desktop tools, since WASM binaries are
+ * specific to the Emscripten toolchain.
+ */
+#ifndef __EMSCRIPTEN__
+int main() {
+ const char* input = R"(#version 310 es
+
+void main() { })";
+
+ uint32_t* output;
+ size_t output_len;
+
+ void* id = convert_glsl_to_spirv(input, 4, false, &output, &output_len);
+ assert(output != nullptr);
+ assert(output_len != 0);
+ destroy_output_buffer(id);
+ return 0;
+}
+#endif // ifndef __EMSCRIPTEN__
diff --git a/thirdparty/glslang/glslang/OSDependent/Web/glslang.pre.js b/thirdparty/glslang/glslang/OSDependent/Web/glslang.pre.js
new file mode 100644
index 0000000000..7d3fd0234c
--- /dev/null
+++ b/thirdparty/glslang/glslang/OSDependent/Web/glslang.pre.js
@@ -0,0 +1,45 @@
+Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug) {
+ gen_debug = !!gen_debug;
+
+ var shader_stage_int;
+ if (shader_stage === 'vertex') {
+ shader_stage_int = 0;
+ } else if (shader_stage === 'fragment') {
+ shader_stage_int = 4;
+ } else if (shader_stage === 'compute') {
+ shader_stage_int = 5;
+ } else {
+ throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'");
+ }
+
+ var p_output = Module['_malloc'](4);
+ var p_output_len = Module['_malloc'](4);
+ var id = ccall('convert_glsl_to_spirv',
+ 'number',
+ ['string', 'number', 'boolean', 'number', 'number'],
+ [glsl, shader_stage_int, gen_debug, p_output, p_output_len]);
+ var output = getValue(p_output, 'i32');
+ var output_len = getValue(p_output_len, 'i32');
+ Module['_free'](p_output);
+ Module['_free'](p_output_len);
+
+ if (id === 0) {
+ throw new Error('GLSL compilation failed');
+ }
+
+ var ret = {};
+ var outputIndexU32 = output / 4;
+ ret['data'] = Module['HEAPU32'].subarray(outputIndexU32, outputIndexU32 + output_len);
+ ret['free'] = function() {
+ Module['_destroy_output_buffer'](id);
+ };
+
+ return ret;
+};
+
+Module['compileGLSL'] = function(glsl, shader_stage, gen_debug) {
+ var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug);
+ var ret = compiled['data'].slice()
+ compiled['free']();
+ return ret;
+};
diff --git a/thirdparty/glslang/glslang/OSDependent/Windows/main.cpp b/thirdparty/glslang/glslang/OSDependent/Windows/main.cpp
new file mode 100644
index 0000000000..0bcde7b660
--- /dev/null
+++ b/thirdparty/glslang/glslang/OSDependent/Windows/main.cpp
@@ -0,0 +1,74 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "InitializeDll.h"
+
+#define STRICT
+#define VC_EXTRALEAN 1
+#include <windows.h>
+#include <assert.h>
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+
+ if (! glslang::InitProcess())
+ return FALSE;
+ break;
+ case DLL_THREAD_ATTACH:
+
+ if (! glslang::InitThread())
+ return FALSE;
+ break;
+
+ case DLL_THREAD_DETACH:
+
+ if (! glslang::DetachThread())
+ return FALSE;
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ glslang::DetachProcess();
+ break;
+
+ default:
+ assert(0 && "DllMain(): Reason for calling DLL Main is unknown");
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/thirdparty/glslang/glslang/OSDependent/Windows/ossource.cpp b/thirdparty/glslang/glslang/OSDependent/Windows/ossource.cpp
new file mode 100644
index 0000000000..870840c56e
--- /dev/null
+++ b/thirdparty/glslang/glslang/OSDependent/Windows/ossource.cpp
@@ -0,0 +1,147 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../osinclude.h"
+
+#define STRICT
+#define VC_EXTRALEAN 1
+#include <windows.h>
+#include <cassert>
+#include <process.h>
+#include <psapi.h>
+#include <cstdio>
+#include <cstdint>
+
+//
+// This file contains the Window-OS-specific functions
+//
+
+#if !(defined(_WIN32) || defined(_WIN64))
+#error Trying to build a windows specific file in a non windows build.
+#endif
+
+namespace glslang {
+
+inline OS_TLSIndex ToGenericTLSIndex (DWORD handle)
+{
+ return (OS_TLSIndex)((uintptr_t)handle + 1);
+}
+
+inline DWORD ToNativeTLSIndex (OS_TLSIndex nIndex)
+{
+ return (DWORD)((uintptr_t)nIndex - 1);
+}
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+ DWORD dwIndex = TlsAlloc();
+ if (dwIndex == TLS_OUT_OF_INDEXES) {
+ assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+ return OS_INVALID_TLS_INDEX;
+ }
+
+ return ToGenericTLSIndex(dwIndex);
+}
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (TlsSetValue(ToNativeTLSIndex(nIndex), lpvValue))
+ return true;
+ else
+ return false;
+}
+
+void* OS_GetTLSValue(OS_TLSIndex nIndex)
+{
+ assert(nIndex != OS_INVALID_TLS_INDEX);
+ return TlsGetValue(ToNativeTLSIndex(nIndex));
+}
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (TlsFree(ToNativeTLSIndex(nIndex)))
+ return true;
+ else
+ return false;
+}
+
+HANDLE GlobalLock;
+
+void InitGlobalLock()
+{
+ GlobalLock = CreateMutex(0, false, 0);
+}
+
+void GetGlobalLock()
+{
+ WaitForSingleObject(GlobalLock, INFINITE);
+}
+
+void ReleaseGlobalLock()
+{
+ ReleaseMutex(GlobalLock);
+}
+
+unsigned int __stdcall EnterGenericThread (void* entry)
+{
+ return ((TThreadEntrypoint)entry)(0);
+}
+
+//#define DUMP_COUNTERS
+
+void OS_DumpMemoryCounters()
+{
+#ifdef DUMP_COUNTERS
+ PROCESS_MEMORY_COUNTERS counters;
+ GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters));
+ printf("Working set size: %d\n", counters.WorkingSetSize);
+#else
+ printf("Recompile with DUMP_COUNTERS defined to see counters.\n");
+#endif
+}
+
+} // namespace glslang
diff --git a/thirdparty/glslang/glslang/OSDependent/osinclude.h b/thirdparty/glslang/glslang/OSDependent/osinclude.h
new file mode 100644
index 0000000000..218abe4f23
--- /dev/null
+++ b/thirdparty/glslang/glslang/OSDependent/osinclude.h
@@ -0,0 +1,63 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef __OSINCLUDE_H
+#define __OSINCLUDE_H
+
+namespace glslang {
+
+//
+// Thread Local Storage Operations
+//
+typedef void* OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX ((void*)0)
+
+OS_TLSIndex OS_AllocTLSIndex();
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue);
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex);
+void* OS_GetTLSValue(OS_TLSIndex nIndex);
+
+void InitGlobalLock();
+void GetGlobalLock();
+void ReleaseGlobalLock();
+
+typedef unsigned int (*TThreadEntrypoint)(void*);
+
+void OS_CleanupThreadData(void);
+
+void OS_DumpMemoryCounters();
+
+} // end namespace glslang
+
+#endif // __OSINCLUDE_H
diff --git a/thirdparty/glslang/glslang/Public/ShaderLang.h b/thirdparty/glslang/glslang/Public/ShaderLang.h
new file mode 100755
index 0000000000..4fe5c7df19
--- /dev/null
+++ b/thirdparty/glslang/glslang/Public/ShaderLang.h
@@ -0,0 +1,903 @@
+//
+// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+// Copyright (C) 2013-2016 LunarG, Inc.
+// Copyright (C) 2015-2018 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+#ifndef _COMPILER_INTERFACE_INCLUDED_
+#define _COMPILER_INTERFACE_INCLUDED_
+
+#include "../Include/ResourceLimits.h"
+#include "../MachineIndependent/Versions.h"
+
+#include <cstring>
+#include <vector>
+
+#ifdef _WIN32
+#define C_DECL __cdecl
+//#ifdef SH_EXPORTING
+// #define SH_IMPORT_EXPORT __declspec(dllexport)
+//#else
+// #define SH_IMPORT_EXPORT __declspec(dllimport)
+//#endif
+#define SH_IMPORT_EXPORT
+#else
+#define SH_IMPORT_EXPORT
+#define C_DECL
+#endif
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler/linker.
+//
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// This should always increase, as some paths to do not consume
+// a more major number.
+// It should increment by one when new functionality is added.
+#define GLSLANG_MINOR_VERSION 13
+
+//
+// Call before doing any other compiler/linker operations.
+//
+// (Call once per process, not once per thread.)
+//
+SH_IMPORT_EXPORT int ShInitialize();
+
+//
+// Call this at process shutdown to clean up memory.
+//
+SH_IMPORT_EXPORT int ShFinalize();
+
+//
+// Types of languages the compiler can consume.
+//
+typedef enum {
+ EShLangVertex,
+ EShLangTessControl,
+ EShLangTessEvaluation,
+ EShLangGeometry,
+ EShLangFragment,
+ EShLangCompute,
+ EShLangRayGenNV,
+ EShLangIntersectNV,
+ EShLangAnyHitNV,
+ EShLangClosestHitNV,
+ EShLangMissNV,
+ EShLangCallableNV,
+ EShLangTaskNV,
+ EShLangMeshNV,
+ EShLangCount,
+} EShLanguage; // would be better as stage, but this is ancient now
+
+typedef enum {
+ EShLangVertexMask = (1 << EShLangVertex),
+ EShLangTessControlMask = (1 << EShLangTessControl),
+ EShLangTessEvaluationMask = (1 << EShLangTessEvaluation),
+ EShLangGeometryMask = (1 << EShLangGeometry),
+ EShLangFragmentMask = (1 << EShLangFragment),
+ EShLangComputeMask = (1 << EShLangCompute),
+ EShLangRayGenNVMask = (1 << EShLangRayGenNV),
+ EShLangIntersectNVMask = (1 << EShLangIntersectNV),
+ EShLangAnyHitNVMask = (1 << EShLangAnyHitNV),
+ EShLangClosestHitNVMask = (1 << EShLangClosestHitNV),
+ EShLangMissNVMask = (1 << EShLangMissNV),
+ EShLangCallableNVMask = (1 << EShLangCallableNV),
+ EShLangTaskNVMask = (1 << EShLangTaskNV),
+ EShLangMeshNVMask = (1 << EShLangMeshNV),
+} EShLanguageMask;
+
+namespace glslang {
+
+class TType;
+
+typedef enum {
+ EShSourceNone,
+ EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL)
+ EShSourceHlsl, // HLSL
+} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead
+
+typedef enum {
+ EShClientNone, // use when there is no client, e.g. for validation
+ EShClientVulkan,
+ EShClientOpenGL,
+} EShClient;
+
+typedef enum {
+ EShTargetNone,
+ EShTargetSpv, // SPIR-V (preferred spelling)
+ EshTargetSpv = EShTargetSpv, // legacy spelling
+} EShTargetLanguage;
+
+typedef enum {
+ EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0
+ EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1
+ EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2
+ EShTargetOpenGL_450 = 450, // OpenGL
+} EShTargetClientVersion;
+
+typedef EShTargetClientVersion EshTargetClientVersion;
+
+typedef enum {
+ EShTargetSpv_1_0 = (1 << 16), // SPIR-V 1.0
+ EShTargetSpv_1_1 = (1 << 16) | (1 << 8), // SPIR-V 1.1
+ EShTargetSpv_1_2 = (1 << 16) | (2 << 8), // SPIR-V 1.2
+ EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3
+ EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4
+ EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5
+} EShTargetLanguageVersion;
+
+struct TInputLanguage {
+ EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone
+ EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone
+ EShClient dialect;
+ int dialectVersion; // version of client's language definition, not the client (when not EShClientNone)
+};
+
+struct TClient {
+ EShClient client;
+ EShTargetClientVersion version; // version of client itself (not the client's input dialect)
+};
+
+struct TTarget {
+ EShTargetLanguage language;
+ EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header
+ bool hlslFunctionality1; // can target hlsl_functionality1 extension(s)
+};
+
+// All source/client/target versions and settings.
+// Can override previous methods of setting, when items are set here.
+// Expected to grow, as more are added, rather than growing parameter lists.
+struct TEnvironment {
+ TInputLanguage input; // definition of the input language
+ TClient client; // what client is the overall compilation being done for?
+ TTarget target; // what to generate
+};
+
+const char* StageName(EShLanguage);
+
+} // end namespace glslang
+
+//
+// Types of output the linker will create.
+//
+typedef enum {
+ EShExVertexFragment,
+ EShExFragment
+} EShExecutable;
+
+//
+// Optimization level for the compiler.
+//
+typedef enum {
+ EShOptNoGeneration,
+ EShOptNone,
+ EShOptSimple, // Optimizations that can be done quickly
+ EShOptFull, // Optimizations that will take more time
+} EShOptimizationLevel;
+
+//
+// Texture and Sampler transformation mode.
+//
+typedef enum {
+ EShTexSampTransKeep, // keep textures and samplers as is (default)
+ EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers
+} EShTextureSamplerTransformMode;
+
+//
+// Message choices for what errors and warnings are given.
+//
+enum EShMessages {
+ EShMsgDefault = 0, // default is to give all required errors and extra warnings
+ EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input
+ EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification
+ EShMsgAST = (1 << 2), // print the AST intermediate representation
+ EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation
+ EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V
+ EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor
+ EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics
+ EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit
+ EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions
+ EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules
+ EShMsgDebugInfo = (1 << 10), // save debug information
+ EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL
+ EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages
+ EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers)
+ EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table
+};
+
+//
+// Options for building reflection
+//
+typedef enum {
+ EShReflectionDefault = 0, // default is original behaviour before options were added
+ EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes
+ EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection
+ EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader
+ EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately
+ EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive
+ EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks
+} EShReflectionOptions;
+
+//
+// Build a table for bindings. This can be used for locating
+// attributes, uniforms, globals, etc., as needed.
+//
+typedef struct {
+ const char* name;
+ int binding;
+} ShBinding;
+
+typedef struct {
+ int numBindings;
+ ShBinding* bindings; // array of bindings
+} ShBindingTable;
+
+//
+// ShHandle held by but opaque to the driver. It is allocated,
+// managed, and de-allocated by the compiler/linker. It's contents
+// are defined by and used by the compiler and linker. For example,
+// symbol table information and object code passed from the compiler
+// to the linker can be stored where ShHandle points.
+//
+// If handle creation fails, 0 will be returned.
+//
+typedef void* ShHandle;
+
+//
+// Driver calls these to create and destroy compiler/linker
+// objects.
+//
+SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader
+SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair
+SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object)
+SH_IMPORT_EXPORT void ShDestruct(ShHandle);
+
+//
+// The return value of ShCompile is boolean, non-zero indicating
+// success.
+//
+// The info-log should be written by ShCompile into
+// ShHandle, so it can answer future queries.
+//
+SH_IMPORT_EXPORT int ShCompile(
+ const ShHandle,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const int* lengths,
+ const EShOptimizationLevel,
+ const TBuiltInResource *resources,
+ int debugOptions,
+ int defaultVersion = 110, // use 100 for ES environment, overridden by #version in shader
+ bool forwardCompatible = false, // give errors for use of deprecated features
+ EShMessages messages = EShMsgDefault // warnings and errors
+ );
+
+SH_IMPORT_EXPORT int ShLinkExt(
+ const ShHandle, // linker object
+ const ShHandle h[], // compiler objects to link together
+ const int numHandles);
+
+//
+// ShSetEncrpytionMethod is a place-holder for specifying
+// how source code is encrypted.
+//
+SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle);
+
+//
+// All the following return 0 if the information is not
+// available in the object passed down, or the object is bad.
+//
+SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle);
+SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle);
+SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing
+SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings
+//
+// Tell the linker to never assign a vertex attribute to this list of physical attributes
+//
+SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count);
+
+//
+// Returns the location ID of the named uniform.
+// Returns -1 if error.
+//
+SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
+
+#ifdef __cplusplus
+ } // end extern "C"
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Deferred-Lowering C++ Interface
+// -----------------------------------
+//
+// Below is a new alternate C++ interface, which deprecates the above
+// opaque handle-based interface.
+//
+// The below is further designed to handle multiple compilation units per stage, where
+// the intermediate results, including the parse tree, are preserved until link time,
+// rather than the above interface which is designed to have each compilation unit
+// lowered at compile time. In the above model, linking occurs on the lowered results,
+// whereas in this model intra-stage linking can occur at the parse tree
+// (treeRoot in TIntermediate) level, and then a full stage can be lowered.
+//
+
+#include <list>
+#include <string>
+#include <utility>
+
+class TCompiler;
+class TInfoSink;
+
+namespace glslang {
+
+const char* GetEsslVersionString();
+const char* GetGlslVersionString();
+int GetKhronosToolId();
+
+class TIntermediate;
+class TProgram;
+class TPoolAllocator;
+
+// Call this exactly once per process before using anything else
+bool InitializeProcess();
+
+// Call once per process to tear down everything
+void FinalizeProcess();
+
+// Resource type for IO resolver
+enum TResourceType {
+ EResSampler,
+ EResTexture,
+ EResImage,
+ EResUbo,
+ EResSsbo,
+ EResUav,
+ EResCount
+};
+
+// Make one TShader per shader that you will link into a program. Then
+// - provide the shader through setStrings() or setStringsWithLengths()
+// - optionally call setEnv*(), see below for more detail
+// - optionally use setPreamble() to set a special shader string that will be
+// processed before all others but won't affect the validity of #version
+// - call parse(): source language and target environment must be selected
+// either by correct setting of EShMessages sent to parse(), or by
+// explicitly calling setEnv*()
+// - query the info logs
+//
+// N.B.: Does not yet support having the same TShader instance being linked into
+// multiple programs.
+//
+// N.B.: Destruct a linked program *before* destructing the shaders linked into it.
+//
+class TShader {
+public:
+ explicit TShader(EShLanguage);
+ virtual ~TShader();
+ void setStrings(const char* const* s, int n);
+ void setStringsWithLengths(const char* const* s, const int* l, int n);
+ void setStringsWithLengthsAndNames(
+ const char* const* s, const int* l, const char* const* names, int n);
+ void setPreamble(const char* s) { preamble = s; }
+ void setEntryPoint(const char* entryPoint);
+ void setSourceEntryPoint(const char* sourceEntryPointName);
+ void addProcesses(const std::vector<std::string>&);
+
+ // IO resolver binding data: see comments in ShaderLang.cpp
+ void setShiftBinding(TResourceType res, unsigned int base);
+ void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
+ void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
+ void setResourceSetBinding(const std::vector<std::string>& base);
+ void setAutoMapBindings(bool map);
+ void setAutoMapLocations(bool map);
+ void addUniformLocationOverride(const char* name, int loc);
+ void setUniformLocationBase(int base);
+ void setInvertY(bool invert);
+#ifdef ENABLE_HLSL
+ void setHlslIoMapping(bool hlslIoMap);
+ void setFlattenUniformArrays(bool flatten);
+#endif
+ void setNoStorageFormat(bool useUnknownFormat);
+ void setNanMinMaxClamp(bool nanMinMaxClamp);
+ void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
+
+ // For setting up the environment (cleared to nothingness in the constructor).
+ // These must be called so that parsing is done for the right source language and
+ // target environment, either indirectly through TranslateEnvironment() based on
+ // EShMessages et. al., or directly by the user.
+ //
+ // setEnvInput: The input source language and stage. If generating code for a
+ // specific client, the input client semantics to use and the
+ // version of the that client's input semantics to use, otherwise
+ // use EShClientNone and version of 0, e.g. for validation mode.
+ // Note 'version' does not describe the target environment,
+ // just the version of the source dialect to compile under.
+ //
+ // See the definitions of TEnvironment, EShSource, EShLanguage,
+ // and EShClient for choices and more detail.
+ //
+ // setEnvClient: The client that will be hosting the execution, and it's version.
+ // Note 'version' is not the version of the languages involved, but
+ // the version of the client environment.
+ // Use EShClientNone and version of 0 if there is no client, e.g.
+ // for validation mode.
+ //
+ // See EShTargetClientVersion for choices.
+ //
+ // setEnvTarget: The language to translate to when generating code, and that
+ // language's version.
+ // Use EShTargetNone and version of 0 if there is no client, e.g.
+ // for validation mode.
+ //
+ void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version)
+ {
+ environment.input.languageFamily = lang;
+ environment.input.stage = envStage;
+ environment.input.dialect = client;
+ environment.input.dialectVersion = version;
+ }
+ void setEnvClient(EShClient client, EShTargetClientVersion version)
+ {
+ environment.client.client = client;
+ environment.client.version = version;
+ }
+ void setEnvTarget(EShTargetLanguage lang, EShTargetLanguageVersion version)
+ {
+ environment.target.language = lang;
+ environment.target.version = version;
+ }
+
+ void getStrings(const char* const* &s, int& n) { s = strings; n = numStrings; }
+
+#ifdef ENABLE_HLSL
+ void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; }
+ bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; }
+#else
+ bool getEnvTargetHlslFunctionality1() const { return false; }
+#endif
+
+ // Interface to #include handlers.
+ //
+ // To support #include, a client of Glslang does the following:
+ // 1. Call setStringsWithNames to set the source strings and associated
+ // names. For example, the names could be the names of the files
+ // containing the shader sources.
+ // 2. Call parse with an Includer.
+ //
+ // When the Glslang parser encounters an #include directive, it calls
+ // the Includer's include method with the requested include name
+ // together with the current string name. The returned IncludeResult
+ // contains the fully resolved name of the included source, together
+ // with the source text that should replace the #include directive
+ // in the source stream. After parsing that source, Glslang will
+ // release the IncludeResult object.
+ class Includer {
+ public:
+ // An IncludeResult contains the resolved name and content of a source
+ // inclusion.
+ struct IncludeResult {
+ IncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, void* userData) :
+ headerName(headerName), headerData(headerData), headerLength(headerLength), userData(userData) { }
+ // For a successful inclusion, the fully resolved name of the requested
+ // include. For example, in a file system-based includer, full resolution
+ // should convert a relative path name into an absolute path name.
+ // For a failed inclusion, this is an empty string.
+ const std::string headerName;
+ // The content and byte length of the requested inclusion. The
+ // Includer producing this IncludeResult retains ownership of the
+ // storage.
+ // For a failed inclusion, the header
+ // field points to a string containing error details.
+ const char* const headerData;
+ const size_t headerLength;
+ // Include resolver's context.
+ void* userData;
+ protected:
+ IncludeResult& operator=(const IncludeResult&);
+ IncludeResult();
+ };
+
+ // For both include methods below:
+ //
+ // Resolves an inclusion request by name, current source name,
+ // and include depth.
+ // On success, returns an IncludeResult containing the resolved name
+ // and content of the include.
+ // On failure, returns a nullptr, or an IncludeResult
+ // with an empty string for the headerName and error details in the
+ // header field.
+ // The Includer retains ownership of the contents
+ // of the returned IncludeResult value, and those contents must
+ // remain valid until the releaseInclude method is called on that
+ // IncludeResult object.
+ //
+ // Note "local" vs. "system" is not an "either/or": "local" is an
+ // extra thing to do over "system". Both might get called, as per
+ // the C++ specification.
+
+ // For the "system" or <>-style includes; search the "system" paths.
+ virtual IncludeResult* includeSystem(const char* /*headerName*/,
+ const char* /*includerName*/,
+ size_t /*inclusionDepth*/) { return nullptr; }
+
+ // For the "local"-only aspect of a "" include. Should not search in the
+ // "system" paths, because on returning a failure, the parser will
+ // call includeSystem() to look in the "system" locations.
+ virtual IncludeResult* includeLocal(const char* /*headerName*/,
+ const char* /*includerName*/,
+ size_t /*inclusionDepth*/) { return nullptr; }
+
+ // Signals that the parser will no longer use the contents of the
+ // specified IncludeResult.
+ virtual void releaseInclude(IncludeResult*) = 0;
+ virtual ~Includer() {}
+ };
+
+ // Fail all Includer searches
+ class ForbidIncluder : public Includer {
+ public:
+ virtual void releaseInclude(IncludeResult*) override { }
+ };
+
+ bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, EShMessages, Includer&);
+
+ bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, EShMessages messages)
+ {
+ TShader::ForbidIncluder includer;
+ return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer);
+ }
+
+ // Equivalent to parse() without a default profile and without forcing defaults.
+ bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
+ {
+ return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
+ }
+
+ bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages,
+ Includer& includer)
+ {
+ return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer);
+ }
+
+ // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
+ // is not an officially supported or fully working path.
+ bool preprocess(const TBuiltInResource* builtInResources,
+ int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, EShMessages message, std::string* outputString,
+ Includer& includer);
+
+ const char* getInfoLog();
+ const char* getInfoDebugLog();
+ EShLanguage getStage() const { return stage; }
+ TIntermediate* getIntermediate() const { return intermediate; }
+
+protected:
+ TPoolAllocator* pool;
+ EShLanguage stage;
+ TCompiler* compiler;
+ TIntermediate* intermediate;
+ TInfoSink* infoSink;
+ // strings and lengths follow the standard for glShaderSource:
+ // strings is an array of numStrings pointers to string data.
+ // lengths can be null, but if not it is an array of numStrings
+ // integers containing the length of the associated strings.
+ // if lengths is null or lengths[n] < 0 the associated strings[n] is
+ // assumed to be null-terminated.
+ // stringNames is the optional names for all the strings. If stringNames
+ // is null, then none of the strings has name. If a certain element in
+ // stringNames is null, then the corresponding string does not have name.
+ const char* const* strings;
+ const int* lengths;
+ const char* const* stringNames;
+ const char* preamble;
+ int numStrings;
+
+ // a function in the source string can be renamed FROM this TO the name given in setEntryPoint.
+ std::string sourceEntryPointName;
+
+ TEnvironment environment;
+
+ friend class TProgram;
+
+private:
+ TShader& operator=(TShader&);
+};
+
+#ifndef GLSLANG_WEB
+
+//
+// A reflection database and its interface, consistent with the OpenGL API reflection queries.
+//
+
+// Data needed for just a single object at the granularity exchanged by the reflection API
+class TObjectReflection {
+public:
+ TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex);
+
+ const TType* getType() const { return type; }
+ int getBinding() const;
+ void dump() const;
+ static TObjectReflection badReflection() { return TObjectReflection(); }
+
+ std::string name;
+ int offset;
+ int glDefineType;
+ int size; // data size in bytes for a block, array size for a (non-block) object that's an array
+ int index;
+ int counterIndex;
+ int numMembers;
+ int arrayStride; // stride of an array variable
+ int topLevelArrayStride; // stride of the top-level variable in a storage buffer member
+ EShLanguageMask stages;
+
+protected:
+ TObjectReflection()
+ : offset(-1), glDefineType(-1), size(-1), index(-1), counterIndex(-1), numMembers(-1), arrayStride(0),
+ topLevelArrayStride(0), stages(EShLanguageMask(0)), type(nullptr)
+ {
+ }
+
+ const TType* type;
+};
+
+class TReflection;
+class TIoMapper;
+struct TVarEntryInfo;
+
+// Allows to customize the binding layout after linking.
+// All used uniform variables will invoke at least validateBinding.
+// If validateBinding returned true then the other resolveBinding,
+// resolveSet, and resolveLocation are invoked to resolve the binding
+// and descriptor set index respectively.
+//
+// Invocations happen in a particular order:
+// 1) all shader inputs
+// 2) all shader outputs
+// 3) all uniforms with binding and set already defined
+// 4) all uniforms with binding but no set defined
+// 5) all uniforms with set but no binding defined
+// 6) all uniforms with no binding and no set defined
+//
+// mapIO will use this resolver in two phases. The first
+// phase is a notification phase, calling the corresponging
+// notifiy callbacks, this phase ends with a call to endNotifications.
+// Phase two starts directly after the call to endNotifications
+// and calls all other callbacks to validate and to get the
+// bindings, sets, locations, component and color indices.
+//
+// NOTE: that still limit checks are applied to bindings and sets
+// and may result in an error.
+class TIoMapResolver
+{
+public:
+ virtual ~TIoMapResolver() {}
+
+ // Should return true if the resulting/current binding would be okay.
+ // Basic idea is to do aliasing binding checks with this.
+ virtual bool validateBinding(EShLanguage stage, TVarEntryInfo& ent) = 0;
+ // Should return a value >= 0 if the current binding should be overridden.
+ // Return -1 if the current binding (including no binding) should be kept.
+ virtual int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) = 0;
+ // Should return a value >= 0 if the current set should be overridden.
+ // Return -1 if the current set (including no set) should be kept.
+ virtual int resolveSet(EShLanguage stage, TVarEntryInfo& ent) = 0;
+ // Should return a value >= 0 if the current location should be overridden.
+ // Return -1 if the current location (including no location) should be kept.
+ virtual int resolveUniformLocation(EShLanguage stage, TVarEntryInfo& ent) = 0;
+ // Should return true if the resulting/current setup would be okay.
+ // Basic idea is to do aliasing checks and reject invalid semantic names.
+ virtual bool validateInOut(EShLanguage stage, TVarEntryInfo& ent) = 0;
+ // Should return a value >= 0 if the current location should be overridden.
+ // Return -1 if the current location (including no location) should be kept.
+ virtual int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) = 0;
+ // Should return a value >= 0 if the current component index should be overridden.
+ // Return -1 if the current component index (including no index) should be kept.
+ virtual int resolveInOutComponent(EShLanguage stage, TVarEntryInfo& ent) = 0;
+ // Should return a value >= 0 if the current color index should be overridden.
+ // Return -1 if the current color index (including no index) should be kept.
+ virtual int resolveInOutIndex(EShLanguage stage, TVarEntryInfo& ent) = 0;
+ // Notification of a uniform variable
+ virtual void notifyBinding(EShLanguage stage, TVarEntryInfo& ent) = 0;
+ // Notification of a in or out variable
+ virtual void notifyInOut(EShLanguage stage, TVarEntryInfo& ent) = 0;
+ // Called by mapIO when it starts its notify pass for the given stage
+ virtual void beginNotifications(EShLanguage stage) = 0;
+ // Called by mapIO when it has finished the notify pass
+ virtual void endNotifications(EShLanguage stage) = 0;
+ // Called by mipIO when it starts its resolve pass for the given stage
+ virtual void beginResolve(EShLanguage stage) = 0;
+ // Called by mapIO when it has finished the resolve pass
+ virtual void endResolve(EShLanguage stage) = 0;
+ // Called by mapIO when it starts its symbol collect for teh given stage
+ virtual void beginCollect(EShLanguage stage) = 0;
+ // Called by mapIO when it has finished the symbol collect
+ virtual void endCollect(EShLanguage stage) = 0;
+ // Called by TSlotCollector to resolve storage locations or bindings
+ virtual void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0;
+ // Called by TSlotCollector to resolve resource locations or bindings
+ virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0;
+ // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline
+ virtual void addStage(EShLanguage stage) = 0;
+};
+
+#endif // GLSLANG_WEB
+
+// Make one TProgram per set of shaders that will get linked together. Add all
+// the shaders that are to be linked together. After calling shader.parse()
+// for all shaders, call link().
+//
+// N.B.: Destruct a linked program *before* destructing the shaders linked into it.
+//
+class TProgram {
+public:
+ TProgram();
+ virtual ~TProgram();
+ void addShader(TShader* shader) { stages[shader->stage].push_back(shader); }
+ std::list<TShader*>& getShaders(EShLanguage stage) { return stages[stage]; }
+ // Link Validation interface
+ bool link(EShMessages);
+ const char* getInfoLog();
+ const char* getInfoDebugLog();
+
+ TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; }
+
+#ifndef GLSLANG_WEB
+
+ // Reflection Interface
+
+ // call first, to do liveness analysis, index mapping, etc.; returns false on failure
+ bool buildReflection(int opts = EShReflectionDefault);
+ unsigned getLocalSize(int dim) const; // return dim'th local size
+ int getReflectionIndex(const char *name) const;
+ int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const;
+ int getNumUniformVariables() const;
+ const TObjectReflection& getUniform(int index) const;
+ int getNumUniformBlocks() const;
+ const TObjectReflection& getUniformBlock(int index) const;
+ int getNumPipeInputs() const;
+ const TObjectReflection& getPipeInput(int index) const;
+ int getNumPipeOutputs() const;
+ const TObjectReflection& getPipeOutput(int index) const;
+ int getNumBufferVariables() const;
+ const TObjectReflection& getBufferVariable(int index) const;
+ int getNumBufferBlocks() const;
+ const TObjectReflection& getBufferBlock(int index) const;
+ int getNumAtomicCounters() const;
+ const TObjectReflection& getAtomicCounter(int index) const;
+
+ // Legacy Reflection Interface - expressed in terms of above interface
+
+ // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS)
+ int getNumLiveUniformVariables() const { return getNumUniformVariables(); }
+
+ // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS)
+ int getNumLiveUniformBlocks() const { return getNumUniformBlocks(); }
+
+ // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES)
+ int getNumLiveAttributes() const { return getNumPipeInputs(); }
+
+ // can be used for glGetUniformIndices()
+ int getUniformIndex(const char *name) const { return getReflectionIndex(name); }
+
+ int getPipeIOIndex(const char *name, const bool inOrOut) const
+ { return getReflectionPipeIOIndex(name, inOrOut); }
+
+ // can be used for "name" part of glGetActiveUniform()
+ const char *getUniformName(int index) const { return getUniform(index).name.c_str(); }
+
+ // returns the binding number
+ int getUniformBinding(int index) const { return getUniform(index).getBinding(); }
+
+ // returns Shaders Stages where a Uniform is present
+ EShLanguageMask getUniformStages(int index) const { return getUniform(index).stages; }
+
+ // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX)
+ int getUniformBlockIndex(int index) const { return getUniform(index).index; }
+
+ // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE)
+ int getUniformType(int index) const { return getUniform(index).glDefineType; }
+
+ // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET)
+ int getUniformBufferOffset(int index) const { return getUniform(index).offset; }
+
+ // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE)
+ int getUniformArraySize(int index) const { return getUniform(index).size; }
+
+ // returns a TType*
+ const TType *getUniformTType(int index) const { return getUniform(index).getType(); }
+
+ // can be used for glGetActiveUniformBlockName()
+ const char *getUniformBlockName(int index) const { return getUniformBlock(index).name.c_str(); }
+
+ // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE)
+ int getUniformBlockSize(int index) const { return getUniformBlock(index).size; }
+
+ // returns the block binding number
+ int getUniformBlockBinding(int index) const { return getUniformBlock(index).getBinding(); }
+
+ // returns block index of associated counter.
+ int getUniformBlockCounterIndex(int index) const { return getUniformBlock(index).counterIndex; }
+
+ // returns a TType*
+ const TType *getUniformBlockTType(int index) const { return getUniformBlock(index).getType(); }
+
+ // can be used for glGetActiveAttrib()
+ const char *getAttributeName(int index) const { return getPipeInput(index).name.c_str(); }
+
+ // can be used for glGetActiveAttrib()
+ int getAttributeType(int index) const { return getPipeInput(index).glDefineType; }
+
+ // returns a TType*
+ const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); }
+
+ void dumpReflection();
+ // I/O mapping: apply base offsets and map live unbound variables
+ // If resolver is not provided it uses the previous approach
+ // and respects auto assignment and offsets.
+ bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr);
+#endif
+
+protected:
+ bool linkStage(EShLanguage, EShMessages);
+
+ TPoolAllocator* pool;
+ std::list<TShader*> stages[EShLangCount];
+ TIntermediate* intermediate[EShLangCount];
+ bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage
+ TInfoSink* infoSink;
+#ifndef GLSLANG_WEB
+ TReflection* reflection;
+#endif
+ bool linked;
+
+private:
+ TProgram(TProgram&);
+ TProgram& operator=(TProgram&);
+};
+
+} // end namespace glslang
+
+#endif // _COMPILER_INTERFACE_INCLUDED_
diff --git a/thirdparty/glslang/patches/fix-mingw-snprintf.patch b/thirdparty/glslang/patches/fix-mingw-snprintf.patch
new file mode 100644
index 0000000000..2a51bc1f22
--- /dev/null
+++ b/thirdparty/glslang/patches/fix-mingw-snprintf.patch
@@ -0,0 +1,15 @@
+diff --git a/thirdparty/glslang/glslang/Include/Common.h b/thirdparty/glslang/glslang/Include/Common.h
+index 733a790cfd..2c511bc1c5 100644
+--- a/thirdparty/glslang/glslang/Include/Common.h
++++ b/thirdparty/glslang/glslang/Include/Common.h
+@@ -50,7 +50,9 @@ std::string to_string(const T& val) {
+ }
+ #endif
+
+-#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API
++// -- GODOT start --
++#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) /* || defined MINGW_HAS_SECURE_API */
++// -- GODOT end --
+ #include <basetsd.h>
+ #ifndef snprintf
+ #define snprintf sprintf_s
diff --git a/thirdparty/jpeg-compressor/jpgd.cpp b/thirdparty/jpeg-compressor/jpgd.cpp
index 62fbd1b72d..baf6ea0484 100644
--- a/thirdparty/jpeg-compressor/jpgd.cpp
+++ b/thirdparty/jpeg-compressor/jpgd.cpp
@@ -1,27 +1,53 @@
-// jpgd.cpp - C++ class for JPEG decompression.
-// Public domain, Rich Geldreich <richgel99@gmail.com>
+// jpgd.cpp - C++ class for JPEG decompression. Written by Richard Geldreich <richgel99@gmail.com> between 1994-2020.
+// Supports progressive and baseline sequential JPEG image files, and the most common chroma subsampling factors: Y, H1V1, H2V1, H1V2, and H2V2.
+// Supports box and linear chroma upsampling.
+//
+// Released under two licenses. You are free to choose which license you want:
+// License 1:
+// Public Domain
+//
+// License 2:
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
// Alex Evans: Linear memory allocator (taken from jpge.h).
-// v1.04, May. 19, 2012: Code tweaks to fix VS2008 static code analysis warnings (all looked harmless)
+// v1.04, May. 19, 2012: Code tweaks to fix VS2008 static code analysis warnings
+// v2.00, March 20, 2020: Fuzzed with zzuf and afl. Fixed several issues, converted most assert()'s to run-time checks. Added chroma upsampling. Removed freq. domain upsampling. gcc/clang warnings.
//
-// Supports progressive and baseline sequential JPEG image files, and the most common chroma subsampling factors: Y, H1V1, H2V1, H1V2, and H2V2.
+// Important:
+// #define JPGD_USE_SSE2 to 0 to completely disable SSE2 usage.
//
-// Chroma upsampling quality: H2V2 is upsampled in the frequency domain, H2V1 and H1V2 are upsampled using point sampling.
-// Chroma upsampling reference: "Fast Scheme for Image Size Change in the Compressed Domain"
-// http://vision.ai.uiuc.edu/~dugad/research/dct/index.html
-
#include "jpgd.h"
#include <string.h>
-
+#include <algorithm>
#include <assert.h>
-#define JPGD_ASSERT(x) assert(x)
#ifdef _MSC_VER
#pragma warning (disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
#endif
-// Set to 1 to enable freq. domain chroma upsampling on images using H2V2 subsampling (0=faster nearest neighbor sampling).
-// This is slower, but results in higher quality on images with highly saturated colors.
-#define JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING 1
+#ifndef JPGD_USE_SSE2
+
+ #if defined(__GNUC__)
+ #if defined(__SSE2__)
+ #define JPGD_USE_SSE2 (1)
+ #endif
+ #elif defined(_MSC_VER)
+ #if defined(_M_X64)
+ #define JPGD_USE_SSE2 (1)
+ #endif
+ #endif
+
+#endif
#define JPGD_TRUE (1)
#define JPGD_FALSE (0)
@@ -29,28 +55,28 @@
#define JPGD_MAX(a,b) (((a)>(b)) ? (a) : (b))
#define JPGD_MIN(a,b) (((a)<(b)) ? (a) : (b))
-// TODO: Move to header and use these constants when declaring the arrays.
-#define JPGD_HUFF_TREE_MAX_LENGTH 512
-#define JPGD_HUFF_CODE_SIZE_MAX_LENGTH 256
-
namespace jpgd {
-static inline void *jpgd_malloc(size_t nSize) { return malloc(nSize); }
-static inline void jpgd_free(void *p) { free(p); }
+ static inline void* jpgd_malloc(size_t nSize) { return malloc(nSize); }
+ static inline void jpgd_free(void* p) { free(p); }
+
+ // DCT coefficients are stored in this sequence.
+ static int g_ZAG[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 };
-// DCT coefficients are stored in this sequence.
-static int g_ZAG[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 };
+ enum JPEG_MARKER
+ {
+ M_SOF0 = 0xC0, M_SOF1 = 0xC1, M_SOF2 = 0xC2, M_SOF3 = 0xC3, M_SOF5 = 0xC5, M_SOF6 = 0xC6, M_SOF7 = 0xC7, M_JPG = 0xC8,
+ M_SOF9 = 0xC9, M_SOF10 = 0xCA, M_SOF11 = 0xCB, M_SOF13 = 0xCD, M_SOF14 = 0xCE, M_SOF15 = 0xCF, M_DHT = 0xC4, M_DAC = 0xCC,
+ M_RST0 = 0xD0, M_RST1 = 0xD1, M_RST2 = 0xD2, M_RST3 = 0xD3, M_RST4 = 0xD4, M_RST5 = 0xD5, M_RST6 = 0xD6, M_RST7 = 0xD7,
+ M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_DNL = 0xDC, M_DRI = 0xDD, M_DHP = 0xDE, M_EXP = 0xDF,
+ M_APP0 = 0xE0, M_APP15 = 0xEF, M_JPG0 = 0xF0, M_JPG13 = 0xFD, M_COM = 0xFE, M_TEM = 0x01, M_ERROR = 0x100, RST0 = 0xD0
+ };
-enum JPEG_MARKER
-{
- M_SOF0 = 0xC0, M_SOF1 = 0xC1, M_SOF2 = 0xC2, M_SOF3 = 0xC3, M_SOF5 = 0xC5, M_SOF6 = 0xC6, M_SOF7 = 0xC7, M_JPG = 0xC8,
- M_SOF9 = 0xC9, M_SOF10 = 0xCA, M_SOF11 = 0xCB, M_SOF13 = 0xCD, M_SOF14 = 0xCE, M_SOF15 = 0xCF, M_DHT = 0xC4, M_DAC = 0xCC,
- M_RST0 = 0xD0, M_RST1 = 0xD1, M_RST2 = 0xD2, M_RST3 = 0xD3, M_RST4 = 0xD4, M_RST5 = 0xD5, M_RST6 = 0xD6, M_RST7 = 0xD7,
- M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_DNL = 0xDC, M_DRI = 0xDD, M_DHP = 0xDE, M_EXP = 0xDF,
- M_APP0 = 0xE0, M_APP15 = 0xEF, M_JPG0 = 0xF0, M_JPG13 = 0xFD, M_COM = 0xFE, M_TEM = 0x01, M_ERROR = 0x100, RST0 = 0xD0
-};
+ enum JPEG_SUBSAMPLING { JPGD_GRAYSCALE = 0, JPGD_YH1V1, JPGD_YH2V1, JPGD_YH1V2, JPGD_YH2V2 };
-enum JPEG_SUBSAMPLING { JPGD_GRAYSCALE = 0, JPGD_YH1V1, JPGD_YH2V1, JPGD_YH1V2, JPGD_YH2V2 };
+#if JPGD_USE_SSE2
+#include "jpgd_idct.h"
+#endif
#define CONST_BITS 13
#define PASS1_BITS 2
@@ -76,3130 +102,3182 @@ enum JPEG_SUBSAMPLING { JPGD_GRAYSCALE = 0, JPGD_YH1V1, JPGD_YH2V1, JPGD_YH1V2,
#define CLAMP(i) ((static_cast<uint>(i) > 255) ? (((~i) >> 31) & 0xFF) : (i))
-// Compiler creates a fast path 1D IDCT for X non-zero columns
-template <int NONZERO_COLS>
-struct Row
-{
- static void idct(int* pTemp, const jpgd_block_t* pSrc)
- {
- // ACCESS_COL() will be optimized at compile time to either an array access, or 0.
- #define ACCESS_COL(x) (((x) < NONZERO_COLS) ? (int)pSrc[x] : 0)
-
- const int z2 = ACCESS_COL(2), z3 = ACCESS_COL(6);
-
- const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
- const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
- const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
-
- const int tmp0 = (ACCESS_COL(0) + ACCESS_COL(4)) << CONST_BITS;
- const int tmp1 = (ACCESS_COL(0) - ACCESS_COL(4)) << CONST_BITS;
-
- const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
-
- const int atmp0 = ACCESS_COL(7), atmp1 = ACCESS_COL(5), atmp2 = ACCESS_COL(3), atmp3 = ACCESS_COL(1);
-
- const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3;
- const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602);
-
- const int az1 = MULTIPLY(bz1, - FIX_0_899976223);
- const int az2 = MULTIPLY(bz2, - FIX_2_562915447);
- const int az3 = MULTIPLY(bz3, - FIX_1_961570560) + bz5;
- const int az4 = MULTIPLY(bz4, - FIX_0_390180644) + bz5;
-
- const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3;
- const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4;
- const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3;
- const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4;
-
- pTemp[0] = DESCALE(tmp10 + btmp3, CONST_BITS-PASS1_BITS);
- pTemp[7] = DESCALE(tmp10 - btmp3, CONST_BITS-PASS1_BITS);
- pTemp[1] = DESCALE(tmp11 + btmp2, CONST_BITS-PASS1_BITS);
- pTemp[6] = DESCALE(tmp11 - btmp2, CONST_BITS-PASS1_BITS);
- pTemp[2] = DESCALE(tmp12 + btmp1, CONST_BITS-PASS1_BITS);
- pTemp[5] = DESCALE(tmp12 - btmp1, CONST_BITS-PASS1_BITS);
- pTemp[3] = DESCALE(tmp13 + btmp0, CONST_BITS-PASS1_BITS);
- pTemp[4] = DESCALE(tmp13 - btmp0, CONST_BITS-PASS1_BITS);
- }
-};
-
-template <>
-struct Row<0>
-{
- static void idct(int* pTemp, const jpgd_block_t* pSrc)
- {
-#ifdef _MSC_VER
- pTemp; pSrc;
+ static inline int left_shifti(int val, uint32_t bits)
+ {
+ return static_cast<int>(static_cast<uint32_t>(val) << bits);
+ }
+
+ // Compiler creates a fast path 1D IDCT for X non-zero columns
+ template <int NONZERO_COLS>
+ struct Row
+ {
+ static void idct(int* pTemp, const jpgd_block_coeff_t* pSrc)
+ {
+ // ACCESS_COL() will be optimized at compile time to either an array access, or 0. Good compilers will then optimize out muls against 0.
+#define ACCESS_COL(x) (((x) < NONZERO_COLS) ? (int)pSrc[x] : 0)
+
+ const int z2 = ACCESS_COL(2), z3 = ACCESS_COL(6);
+
+ const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ const int tmp2 = z1 + MULTIPLY(z3, -FIX_1_847759065);
+ const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
+
+ const int tmp0 = left_shifti(ACCESS_COL(0) + ACCESS_COL(4), CONST_BITS);
+ const int tmp1 = left_shifti(ACCESS_COL(0) - ACCESS_COL(4), CONST_BITS);
+
+ const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
+
+ const int atmp0 = ACCESS_COL(7), atmp1 = ACCESS_COL(5), atmp2 = ACCESS_COL(3), atmp3 = ACCESS_COL(1);
+
+ const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3;
+ const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602);
+
+ const int az1 = MULTIPLY(bz1, -FIX_0_899976223);
+ const int az2 = MULTIPLY(bz2, -FIX_2_562915447);
+ const int az3 = MULTIPLY(bz3, -FIX_1_961570560) + bz5;
+ const int az4 = MULTIPLY(bz4, -FIX_0_390180644) + bz5;
+
+ const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3;
+ const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4;
+ const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3;
+ const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4;
+
+ pTemp[0] = DESCALE(tmp10 + btmp3, CONST_BITS - PASS1_BITS);
+ pTemp[7] = DESCALE(tmp10 - btmp3, CONST_BITS - PASS1_BITS);
+ pTemp[1] = DESCALE(tmp11 + btmp2, CONST_BITS - PASS1_BITS);
+ pTemp[6] = DESCALE(tmp11 - btmp2, CONST_BITS - PASS1_BITS);
+ pTemp[2] = DESCALE(tmp12 + btmp1, CONST_BITS - PASS1_BITS);
+ pTemp[5] = DESCALE(tmp12 - btmp1, CONST_BITS - PASS1_BITS);
+ pTemp[3] = DESCALE(tmp13 + btmp0, CONST_BITS - PASS1_BITS);
+ pTemp[4] = DESCALE(tmp13 - btmp0, CONST_BITS - PASS1_BITS);
+ }
+ };
+
+ template <>
+ struct Row<0>
+ {
+ static void idct(int* pTemp, const jpgd_block_coeff_t* pSrc)
+ {
+ (void)pTemp;
+ (void)pSrc;
+ }
+ };
+
+ template <>
+ struct Row<1>
+ {
+ static void idct(int* pTemp, const jpgd_block_coeff_t* pSrc)
+ {
+ const int dcval = left_shifti(pSrc[0], PASS1_BITS);
+
+ pTemp[0] = dcval;
+ pTemp[1] = dcval;
+ pTemp[2] = dcval;
+ pTemp[3] = dcval;
+ pTemp[4] = dcval;
+ pTemp[5] = dcval;
+ pTemp[6] = dcval;
+ pTemp[7] = dcval;
+ }
+ };
+
+ // Compiler creates a fast path 1D IDCT for X non-zero rows
+ template <int NONZERO_ROWS>
+ struct Col
+ {
+ static void idct(uint8* pDst_ptr, const int* pTemp)
+ {
+ // ACCESS_ROW() will be optimized at compile time to either an array access, or 0.
+#define ACCESS_ROW(x) (((x) < NONZERO_ROWS) ? pTemp[x * 8] : 0)
+
+ const int z2 = ACCESS_ROW(2);
+ const int z3 = ACCESS_ROW(6);
+
+ const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ const int tmp2 = z1 + MULTIPLY(z3, -FIX_1_847759065);
+ const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
+
+ const int tmp0 = left_shifti(ACCESS_ROW(0) + ACCESS_ROW(4), CONST_BITS);
+ const int tmp1 = left_shifti(ACCESS_ROW(0) - ACCESS_ROW(4), CONST_BITS);
+
+ const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
+
+ const int atmp0 = ACCESS_ROW(7), atmp1 = ACCESS_ROW(5), atmp2 = ACCESS_ROW(3), atmp3 = ACCESS_ROW(1);
+
+ const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3;
+ const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602);
+
+ const int az1 = MULTIPLY(bz1, -FIX_0_899976223);
+ const int az2 = MULTIPLY(bz2, -FIX_2_562915447);
+ const int az3 = MULTIPLY(bz3, -FIX_1_961570560) + bz5;
+ const int az4 = MULTIPLY(bz4, -FIX_0_390180644) + bz5;
+
+ const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3;
+ const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4;
+ const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3;
+ const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4;
+
+ int i = DESCALE_ZEROSHIFT(tmp10 + btmp3, CONST_BITS + PASS1_BITS + 3);
+ pDst_ptr[8 * 0] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp10 - btmp3, CONST_BITS + PASS1_BITS + 3);
+ pDst_ptr[8 * 7] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp11 + btmp2, CONST_BITS + PASS1_BITS + 3);
+ pDst_ptr[8 * 1] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp11 - btmp2, CONST_BITS + PASS1_BITS + 3);
+ pDst_ptr[8 * 6] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp12 + btmp1, CONST_BITS + PASS1_BITS + 3);
+ pDst_ptr[8 * 2] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp12 - btmp1, CONST_BITS + PASS1_BITS + 3);
+ pDst_ptr[8 * 5] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp13 + btmp0, CONST_BITS + PASS1_BITS + 3);
+ pDst_ptr[8 * 3] = (uint8)CLAMP(i);
+
+ i = DESCALE_ZEROSHIFT(tmp13 - btmp0, CONST_BITS + PASS1_BITS + 3);
+ pDst_ptr[8 * 4] = (uint8)CLAMP(i);
+ }
+ };
+
+ template <>
+ struct Col<1>
+ {
+ static void idct(uint8* pDst_ptr, const int* pTemp)
+ {
+ int dcval = DESCALE_ZEROSHIFT(pTemp[0], PASS1_BITS + 3);
+ const uint8 dcval_clamped = (uint8)CLAMP(dcval);
+ pDst_ptr[0 * 8] = dcval_clamped;
+ pDst_ptr[1 * 8] = dcval_clamped;
+ pDst_ptr[2 * 8] = dcval_clamped;
+ pDst_ptr[3 * 8] = dcval_clamped;
+ pDst_ptr[4 * 8] = dcval_clamped;
+ pDst_ptr[5 * 8] = dcval_clamped;
+ pDst_ptr[6 * 8] = dcval_clamped;
+ pDst_ptr[7 * 8] = dcval_clamped;
+ }
+ };
+
+ static const uint8 s_idct_row_table[] =
+ {
+ 1,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0, 2,1,0,0,0,0,0,0, 2,1,1,0,0,0,0,0, 2,2,1,0,0,0,0,0, 3,2,1,0,0,0,0,0, 4,2,1,0,0,0,0,0, 4,3,1,0,0,0,0,0,
+ 4,3,2,0,0,0,0,0, 4,3,2,1,0,0,0,0, 4,3,2,1,1,0,0,0, 4,3,2,2,1,0,0,0, 4,3,3,2,1,0,0,0, 4,4,3,2,1,0,0,0, 5,4,3,2,1,0,0,0, 6,4,3,2,1,0,0,0,
+ 6,5,3,2,1,0,0,0, 6,5,4,2,1,0,0,0, 6,5,4,3,1,0,0,0, 6,5,4,3,2,0,0,0, 6,5,4,3,2,1,0,0, 6,5,4,3,2,1,1,0, 6,5,4,3,2,2,1,0, 6,5,4,3,3,2,1,0,
+ 6,5,4,4,3,2,1,0, 6,5,5,4,3,2,1,0, 6,6,5,4,3,2,1,0, 7,6,5,4,3,2,1,0, 8,6,5,4,3,2,1,0, 8,7,5,4,3,2,1,0, 8,7,6,4,3,2,1,0, 8,7,6,5,3,2,1,0,
+ 8,7,6,5,4,2,1,0, 8,7,6,5,4,3,1,0, 8,7,6,5,4,3,2,0, 8,7,6,5,4,3,2,1, 8,7,6,5,4,3,2,2, 8,7,6,5,4,3,3,2, 8,7,6,5,4,4,3,2, 8,7,6,5,5,4,3,2,
+ 8,7,6,6,5,4,3,2, 8,7,7,6,5,4,3,2, 8,8,7,6,5,4,3,2, 8,8,8,6,5,4,3,2, 8,8,8,7,5,4,3,2, 8,8,8,7,6,4,3,2, 8,8,8,7,6,5,3,2, 8,8,8,7,6,5,4,2,
+ 8,8,8,7,6,5,4,3, 8,8,8,7,6,5,4,4, 8,8,8,7,6,5,5,4, 8,8,8,7,6,6,5,4, 8,8,8,7,7,6,5,4, 8,8,8,8,7,6,5,4, 8,8,8,8,8,6,5,4, 8,8,8,8,8,7,5,4,
+ 8,8,8,8,8,7,6,4, 8,8,8,8,8,7,6,5, 8,8,8,8,8,7,6,6, 8,8,8,8,8,7,7,6, 8,8,8,8,8,8,7,6, 8,8,8,8,8,8,8,6, 8,8,8,8,8,8,8,7, 8,8,8,8,8,8,8,8,
+ };
+
+ static const uint8 s_idct_col_table[] =
+ {
+ 1, 1, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
+ };
+
+ // Scalar "fast pathing" IDCT.
+ static void idct(const jpgd_block_coeff_t* pSrc_ptr, uint8* pDst_ptr, int block_max_zag, bool use_simd)
+ {
+ (void)use_simd;
+
+ assert(block_max_zag >= 1);
+ assert(block_max_zag <= 64);
+
+ if (block_max_zag <= 1)
+ {
+ int k = ((pSrc_ptr[0] + 4) >> 3) + 128;
+ k = CLAMP(k);
+ k = k | (k << 8);
+ k = k | (k << 16);
+
+ for (int i = 8; i > 0; i--)
+ {
+ *(int*)&pDst_ptr[0] = k;
+ *(int*)&pDst_ptr[4] = k;
+ pDst_ptr += 8;
+ }
+ return;
+ }
+
+#if JPGD_USE_SSE2
+ if (use_simd)
+ {
+ assert((((uintptr_t)pSrc_ptr) & 15) == 0);
+ assert((((uintptr_t)pDst_ptr) & 15) == 0);
+ idctSSEShortU8(pSrc_ptr, pDst_ptr);
+ return;
+ }
#endif
- }
-};
-
-template <>
-struct Row<1>
-{
- static void idct(int* pTemp, const jpgd_block_t* pSrc)
- {
- const int dcval = (pSrc[0] << PASS1_BITS);
-
- pTemp[0] = dcval;
- pTemp[1] = dcval;
- pTemp[2] = dcval;
- pTemp[3] = dcval;
- pTemp[4] = dcval;
- pTemp[5] = dcval;
- pTemp[6] = dcval;
- pTemp[7] = dcval;
- }
-};
-
-// Compiler creates a fast path 1D IDCT for X non-zero rows
-template <int NONZERO_ROWS>
-struct Col
-{
- static void idct(uint8* pDst_ptr, const int* pTemp)
- {
- // ACCESS_ROW() will be optimized at compile time to either an array access, or 0.
- #define ACCESS_ROW(x) (((x) < NONZERO_ROWS) ? pTemp[x * 8] : 0)
-
- const int z2 = ACCESS_ROW(2);
- const int z3 = ACCESS_ROW(6);
-
- const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
- const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
- const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
-
- const int tmp0 = (ACCESS_ROW(0) + ACCESS_ROW(4)) << CONST_BITS;
- const int tmp1 = (ACCESS_ROW(0) - ACCESS_ROW(4)) << CONST_BITS;
-
- const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
-
- const int atmp0 = ACCESS_ROW(7), atmp1 = ACCESS_ROW(5), atmp2 = ACCESS_ROW(3), atmp3 = ACCESS_ROW(1);
-
- const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3;
- const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602);
-
- const int az1 = MULTIPLY(bz1, - FIX_0_899976223);
- const int az2 = MULTIPLY(bz2, - FIX_2_562915447);
- const int az3 = MULTIPLY(bz3, - FIX_1_961570560) + bz5;
- const int az4 = MULTIPLY(bz4, - FIX_0_390180644) + bz5;
-
- const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3;
- const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4;
- const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3;
- const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4;
-
- int i = DESCALE_ZEROSHIFT(tmp10 + btmp3, CONST_BITS+PASS1_BITS+3);
- pDst_ptr[8*0] = (uint8)CLAMP(i);
-
- i = DESCALE_ZEROSHIFT(tmp10 - btmp3, CONST_BITS+PASS1_BITS+3);
- pDst_ptr[8*7] = (uint8)CLAMP(i);
-
- i = DESCALE_ZEROSHIFT(tmp11 + btmp2, CONST_BITS+PASS1_BITS+3);
- pDst_ptr[8*1] = (uint8)CLAMP(i);
-
- i = DESCALE_ZEROSHIFT(tmp11 - btmp2, CONST_BITS+PASS1_BITS+3);
- pDst_ptr[8*6] = (uint8)CLAMP(i);
-
- i = DESCALE_ZEROSHIFT(tmp12 + btmp1, CONST_BITS+PASS1_BITS+3);
- pDst_ptr[8*2] = (uint8)CLAMP(i);
-
- i = DESCALE_ZEROSHIFT(tmp12 - btmp1, CONST_BITS+PASS1_BITS+3);
- pDst_ptr[8*5] = (uint8)CLAMP(i);
-
- i = DESCALE_ZEROSHIFT(tmp13 + btmp0, CONST_BITS+PASS1_BITS+3);
- pDst_ptr[8*3] = (uint8)CLAMP(i);
-
- i = DESCALE_ZEROSHIFT(tmp13 - btmp0, CONST_BITS+PASS1_BITS+3);
- pDst_ptr[8*4] = (uint8)CLAMP(i);
- }
-};
-
-template <>
-struct Col<1>
-{
- static void idct(uint8* pDst_ptr, const int* pTemp)
- {
- int dcval = DESCALE_ZEROSHIFT(pTemp[0], PASS1_BITS+3);
- const uint8 dcval_clamped = (uint8)CLAMP(dcval);
- pDst_ptr[0*8] = dcval_clamped;
- pDst_ptr[1*8] = dcval_clamped;
- pDst_ptr[2*8] = dcval_clamped;
- pDst_ptr[3*8] = dcval_clamped;
- pDst_ptr[4*8] = dcval_clamped;
- pDst_ptr[5*8] = dcval_clamped;
- pDst_ptr[6*8] = dcval_clamped;
- pDst_ptr[7*8] = dcval_clamped;
- }
-};
-
-static const uint8 s_idct_row_table[] =
-{
- 1,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0, 2,1,0,0,0,0,0,0, 2,1,1,0,0,0,0,0, 2,2,1,0,0,0,0,0, 3,2,1,0,0,0,0,0, 4,2,1,0,0,0,0,0, 4,3,1,0,0,0,0,0,
- 4,3,2,0,0,0,0,0, 4,3,2,1,0,0,0,0, 4,3,2,1,1,0,0,0, 4,3,2,2,1,0,0,0, 4,3,3,2,1,0,0,0, 4,4,3,2,1,0,0,0, 5,4,3,2,1,0,0,0, 6,4,3,2,1,0,0,0,
- 6,5,3,2,1,0,0,0, 6,5,4,2,1,0,0,0, 6,5,4,3,1,0,0,0, 6,5,4,3,2,0,0,0, 6,5,4,3,2,1,0,0, 6,5,4,3,2,1,1,0, 6,5,4,3,2,2,1,0, 6,5,4,3,3,2,1,0,
- 6,5,4,4,3,2,1,0, 6,5,5,4,3,2,1,0, 6,6,5,4,3,2,1,0, 7,6,5,4,3,2,1,0, 8,6,5,4,3,2,1,0, 8,7,5,4,3,2,1,0, 8,7,6,4,3,2,1,0, 8,7,6,5,3,2,1,0,
- 8,7,6,5,4,2,1,0, 8,7,6,5,4,3,1,0, 8,7,6,5,4,3,2,0, 8,7,6,5,4,3,2,1, 8,7,6,5,4,3,2,2, 8,7,6,5,4,3,3,2, 8,7,6,5,4,4,3,2, 8,7,6,5,5,4,3,2,
- 8,7,6,6,5,4,3,2, 8,7,7,6,5,4,3,2, 8,8,7,6,5,4,3,2, 8,8,8,6,5,4,3,2, 8,8,8,7,5,4,3,2, 8,8,8,7,6,4,3,2, 8,8,8,7,6,5,3,2, 8,8,8,7,6,5,4,2,
- 8,8,8,7,6,5,4,3, 8,8,8,7,6,5,4,4, 8,8,8,7,6,5,5,4, 8,8,8,7,6,6,5,4, 8,8,8,7,7,6,5,4, 8,8,8,8,7,6,5,4, 8,8,8,8,8,6,5,4, 8,8,8,8,8,7,5,4,
- 8,8,8,8,8,7,6,4, 8,8,8,8,8,7,6,5, 8,8,8,8,8,7,6,6, 8,8,8,8,8,7,7,6, 8,8,8,8,8,8,7,6, 8,8,8,8,8,8,8,6, 8,8,8,8,8,8,8,7, 8,8,8,8,8,8,8,8,
-};
-
-static const uint8 s_idct_col_table[] = { 1, 1, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 };
-
-void idct(const jpgd_block_t* pSrc_ptr, uint8* pDst_ptr, int block_max_zag)
-{
- JPGD_ASSERT(block_max_zag >= 1);
- JPGD_ASSERT(block_max_zag <= 64);
-
- if (block_max_zag <= 1)
- {
- int k = ((pSrc_ptr[0] + 4) >> 3) + 128;
- k = CLAMP(k);
- k = k | (k<<8);
- k = k | (k<<16);
-
- for (int i = 8; i > 0; i--)
- {
- *(int*)&pDst_ptr[0] = k;
- *(int*)&pDst_ptr[4] = k;
- pDst_ptr += 8;
- }
- return;
- }
-
- int temp[64];
-
- const jpgd_block_t* pSrc = pSrc_ptr;
- int* pTemp = temp;
-
- const uint8* pRow_tab = &s_idct_row_table[(block_max_zag - 1) * 8];
- int i;
- for (i = 8; i > 0; i--, pRow_tab++)
- {
- switch (*pRow_tab)
- {
- case 0: Row<0>::idct(pTemp, pSrc); break;
- case 1: Row<1>::idct(pTemp, pSrc); break;
- case 2: Row<2>::idct(pTemp, pSrc); break;
- case 3: Row<3>::idct(pTemp, pSrc); break;
- case 4: Row<4>::idct(pTemp, pSrc); break;
- case 5: Row<5>::idct(pTemp, pSrc); break;
- case 6: Row<6>::idct(pTemp, pSrc); break;
- case 7: Row<7>::idct(pTemp, pSrc); break;
- case 8: Row<8>::idct(pTemp, pSrc); break;
- }
-
- pSrc += 8;
- pTemp += 8;
- }
-
- pTemp = temp;
-
- const int nonzero_rows = s_idct_col_table[block_max_zag - 1];
- for (i = 8; i > 0; i--)
- {
- switch (nonzero_rows)
- {
- case 1: Col<1>::idct(pDst_ptr, pTemp); break;
- case 2: Col<2>::idct(pDst_ptr, pTemp); break;
- case 3: Col<3>::idct(pDst_ptr, pTemp); break;
- case 4: Col<4>::idct(pDst_ptr, pTemp); break;
- case 5: Col<5>::idct(pDst_ptr, pTemp); break;
- case 6: Col<6>::idct(pDst_ptr, pTemp); break;
- case 7: Col<7>::idct(pDst_ptr, pTemp); break;
- case 8: Col<8>::idct(pDst_ptr, pTemp); break;
- }
-
- pTemp++;
- pDst_ptr++;
- }
-}
-
-void idct_4x4(const jpgd_block_t* pSrc_ptr, uint8* pDst_ptr)
-{
- int temp[64];
- int* pTemp = temp;
- const jpgd_block_t* pSrc = pSrc_ptr;
-
- for (int i = 4; i > 0; i--)
- {
- Row<4>::idct(pTemp, pSrc);
- pSrc += 8;
- pTemp += 8;
- }
-
- pTemp = temp;
- for (int i = 8; i > 0; i--)
- {
- Col<4>::idct(pDst_ptr, pTemp);
- pTemp++;
- pDst_ptr++;
- }
-}
-
-// Retrieve one character from the input stream.
-inline uint jpeg_decoder::get_char()
-{
- // Any bytes remaining in buffer?
- if (!m_in_buf_left)
- {
- // Try to get more bytes.
- prep_in_buffer();
- // Still nothing to get?
- if (!m_in_buf_left)
- {
- // Pad the end of the stream with 0xFF 0xD9 (EOI marker)
- int t = m_tem_flag;
- m_tem_flag ^= 1;
- if (t)
- return 0xD9;
- else
- return 0xFF;
- }
- }
-
- uint c = *m_pIn_buf_ofs++;
- m_in_buf_left--;
-
- return c;
-}
-
-// Same as previous method, except can indicate if the character is a pad character or not.
-inline uint jpeg_decoder::get_char(bool *pPadding_flag)
-{
- if (!m_in_buf_left)
- {
- prep_in_buffer();
- if (!m_in_buf_left)
- {
- *pPadding_flag = true;
- int t = m_tem_flag;
- m_tem_flag ^= 1;
- if (t)
- return 0xD9;
- else
- return 0xFF;
- }
- }
-
- *pPadding_flag = false;
-
- uint c = *m_pIn_buf_ofs++;
- m_in_buf_left--;
-
- return c;
-}
-
-// Inserts a previously retrieved character back into the input buffer.
-inline void jpeg_decoder::stuff_char(uint8 q)
-{
- *(--m_pIn_buf_ofs) = q;
- m_in_buf_left++;
-}
-
-// Retrieves one character from the input stream, but does not read past markers. Will continue to return 0xFF when a marker is encountered.
-inline uint8 jpeg_decoder::get_octet()
-{
- bool padding_flag;
- int c = get_char(&padding_flag);
-
- if (c == 0xFF)
- {
- if (padding_flag)
- return 0xFF;
-
- c = get_char(&padding_flag);
- if (padding_flag)
- {
- stuff_char(0xFF);
- return 0xFF;
- }
-
- if (c == 0x00)
- return 0xFF;
- else
- {
- stuff_char(static_cast<uint8>(c));
- stuff_char(0xFF);
- return 0xFF;
- }
- }
-
- return static_cast<uint8>(c);
-}
-
-// Retrieves a variable number of bits from the input stream. Does not recognize markers.
-inline uint jpeg_decoder::get_bits(int num_bits)
-{
- if (!num_bits)
- return 0;
-
- uint i = m_bit_buf >> (32 - num_bits);
-
- if ((m_bits_left -= num_bits) <= 0)
- {
- m_bit_buf <<= (num_bits += m_bits_left);
-
- uint c1 = get_char();
- uint c2 = get_char();
- m_bit_buf = (m_bit_buf & 0xFFFF0000) | (c1 << 8) | c2;
-
- m_bit_buf <<= -m_bits_left;
-
- m_bits_left += 16;
-
- JPGD_ASSERT(m_bits_left >= 0);
- }
- else
- m_bit_buf <<= num_bits;
-
- return i;
-}
-
-// Retrieves a variable number of bits from the input stream. Markers will not be read into the input bit buffer. Instead, an infinite number of all 1's will be returned when a marker is encountered.
-inline uint jpeg_decoder::get_bits_no_markers(int num_bits)
-{
- if (!num_bits)
- return 0;
-
- uint i = m_bit_buf >> (32 - num_bits);
-
- if ((m_bits_left -= num_bits) <= 0)
- {
- m_bit_buf <<= (num_bits += m_bits_left);
-
- if ((m_in_buf_left < 2) || (m_pIn_buf_ofs[0] == 0xFF) || (m_pIn_buf_ofs[1] == 0xFF))
- {
- uint c1 = get_octet();
- uint c2 = get_octet();
- m_bit_buf |= (c1 << 8) | c2;
- }
- else
- {
- m_bit_buf |= ((uint)m_pIn_buf_ofs[0] << 8) | m_pIn_buf_ofs[1];
- m_in_buf_left -= 2;
- m_pIn_buf_ofs += 2;
- }
-
- m_bit_buf <<= -m_bits_left;
-
- m_bits_left += 16;
-
- JPGD_ASSERT(m_bits_left >= 0);
- }
- else
- m_bit_buf <<= num_bits;
-
- return i;
-}
-
-// Decodes a Huffman encoded symbol.
-inline int jpeg_decoder::huff_decode(huff_tables *pH)
-{
- JPGD_ASSERT(pH);
-
- int symbol;
- // Check first 8-bits: do we have a complete symbol?
- if ((symbol = pH->look_up[m_bit_buf >> 24]) < 0)
- {
- // Decode more bits, use a tree traversal to find symbol.
- int ofs = 23;
- do
- {
- unsigned int idx = -(int)(symbol + ((m_bit_buf >> ofs) & 1));
- JPGD_ASSERT(idx < JPGD_HUFF_TREE_MAX_LENGTH);
- symbol = pH->tree[idx];
- ofs--;
- } while (symbol < 0);
-
- get_bits_no_markers(8 + (23 - ofs));
- }
- else
- {
- JPGD_ASSERT(symbol < JPGD_HUFF_CODE_SIZE_MAX_LENGTH);
- get_bits_no_markers(pH->code_size[symbol]);
- }
-
- return symbol;
-}
-
-// Decodes a Huffman encoded symbol.
-inline int jpeg_decoder::huff_decode(huff_tables *pH, int& extra_bits)
-{
- int symbol;
-
- JPGD_ASSERT(pH);
-
- // Check first 8-bits: do we have a complete symbol?
- if ((symbol = pH->look_up2[m_bit_buf >> 24]) < 0)
- {
- // Use a tree traversal to find symbol.
- int ofs = 23;
- do
- {
- unsigned int idx = -(int)(symbol + ((m_bit_buf >> ofs) & 1));
- JPGD_ASSERT(idx < JPGD_HUFF_TREE_MAX_LENGTH);
- symbol = pH->tree[idx];
- ofs--;
- } while (symbol < 0);
-
- get_bits_no_markers(8 + (23 - ofs));
-
- extra_bits = get_bits_no_markers(symbol & 0xF);
- }
- else
- {
- JPGD_ASSERT(((symbol >> 8) & 31) == pH->code_size[symbol & 255] + ((symbol & 0x8000) ? (symbol & 15) : 0));
-
- if (symbol & 0x8000)
- {
- get_bits_no_markers((symbol >> 8) & 31);
- extra_bits = symbol >> 16;
- }
- else
- {
- int code_size = (symbol >> 8) & 31;
- int num_extra_bits = symbol & 0xF;
- int bits = code_size + num_extra_bits;
- if (bits <= (m_bits_left + 16))
- extra_bits = get_bits_no_markers(bits) & ((1 << num_extra_bits) - 1);
- else
- {
- get_bits_no_markers(code_size);
- extra_bits = get_bits_no_markers(num_extra_bits);
- }
- }
-
- symbol &= 0xFF;
- }
-
- return symbol;
-}
-
-// Tables and macro used to fully decode the DPCM differences.
-static const int s_extend_test[16] = { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
-static const int s_extend_offset[16] = { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
-static const int s_extend_mask[] = { 0, (1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7), (1<<8), (1<<9), (1<<10), (1<<11), (1<<12), (1<<13), (1<<14), (1<<15), (1<<16) };
-// The logical AND's in this macro are to shut up static code analysis (aren't really necessary - couldn't find another way to do this)
+
+ int temp[64];
+
+ const jpgd_block_coeff_t* pSrc = pSrc_ptr;
+ int* pTemp = temp;
+
+ const uint8* pRow_tab = &s_idct_row_table[(block_max_zag - 1) * 8];
+ int i;
+ for (i = 8; i > 0; i--, pRow_tab++)
+ {
+ switch (*pRow_tab)
+ {
+ case 0: Row<0>::idct(pTemp, pSrc); break;
+ case 1: Row<1>::idct(pTemp, pSrc); break;
+ case 2: Row<2>::idct(pTemp, pSrc); break;
+ case 3: Row<3>::idct(pTemp, pSrc); break;
+ case 4: Row<4>::idct(pTemp, pSrc); break;
+ case 5: Row<5>::idct(pTemp, pSrc); break;
+ case 6: Row<6>::idct(pTemp, pSrc); break;
+ case 7: Row<7>::idct(pTemp, pSrc); break;
+ case 8: Row<8>::idct(pTemp, pSrc); break;
+ }
+
+ pSrc += 8;
+ pTemp += 8;
+ }
+
+ pTemp = temp;
+
+ const int nonzero_rows = s_idct_col_table[block_max_zag - 1];
+ for (i = 8; i > 0; i--)
+ {
+ switch (nonzero_rows)
+ {
+ case 1: Col<1>::idct(pDst_ptr, pTemp); break;
+ case 2: Col<2>::idct(pDst_ptr, pTemp); break;
+ case 3: Col<3>::idct(pDst_ptr, pTemp); break;
+ case 4: Col<4>::idct(pDst_ptr, pTemp); break;
+ case 5: Col<5>::idct(pDst_ptr, pTemp); break;
+ case 6: Col<6>::idct(pDst_ptr, pTemp); break;
+ case 7: Col<7>::idct(pDst_ptr, pTemp); break;
+ case 8: Col<8>::idct(pDst_ptr, pTemp); break;
+ }
+
+ pTemp++;
+ pDst_ptr++;
+ }
+ }
+
+ // Retrieve one character from the input stream.
+ inline uint jpeg_decoder::get_char()
+ {
+ // Any bytes remaining in buffer?
+ if (!m_in_buf_left)
+ {
+ // Try to get more bytes.
+ prep_in_buffer();
+ // Still nothing to get?
+ if (!m_in_buf_left)
+ {
+ // Pad the end of the stream with 0xFF 0xD9 (EOI marker)
+ int t = m_tem_flag;
+ m_tem_flag ^= 1;
+ if (t)
+ return 0xD9;
+ else
+ return 0xFF;
+ }
+ }
+
+ uint c = *m_pIn_buf_ofs++;
+ m_in_buf_left--;
+
+ return c;
+ }
+
+ // Same as previous method, except can indicate if the character is a pad character or not.
+ inline uint jpeg_decoder::get_char(bool* pPadding_flag)
+ {
+ if (!m_in_buf_left)
+ {
+ prep_in_buffer();
+ if (!m_in_buf_left)
+ {
+ *pPadding_flag = true;
+ int t = m_tem_flag;
+ m_tem_flag ^= 1;
+ if (t)
+ return 0xD9;
+ else
+ return 0xFF;
+ }
+ }
+
+ *pPadding_flag = false;
+
+ uint c = *m_pIn_buf_ofs++;
+ m_in_buf_left--;
+
+ return c;
+ }
+
+ // Inserts a previously retrieved character back into the input buffer.
+ inline void jpeg_decoder::stuff_char(uint8 q)
+ {
+ // This could write before the input buffer, but we've placed another array there.
+ *(--m_pIn_buf_ofs) = q;
+ m_in_buf_left++;
+ }
+
+ // Retrieves one character from the input stream, but does not read past markers. Will continue to return 0xFF when a marker is encountered.
+ inline uint8 jpeg_decoder::get_octet()
+ {
+ bool padding_flag;
+ int c = get_char(&padding_flag);
+
+ if (c == 0xFF)
+ {
+ if (padding_flag)
+ return 0xFF;
+
+ c = get_char(&padding_flag);
+ if (padding_flag)
+ {
+ stuff_char(0xFF);
+ return 0xFF;
+ }
+
+ if (c == 0x00)
+ return 0xFF;
+ else
+ {
+ stuff_char(static_cast<uint8>(c));
+ stuff_char(0xFF);
+ return 0xFF;
+ }
+ }
+
+ return static_cast<uint8>(c);
+ }
+
+ // Retrieves a variable number of bits from the input stream. Does not recognize markers.
+ inline uint jpeg_decoder::get_bits(int num_bits)
+ {
+ if (!num_bits)
+ return 0;
+
+ uint i = m_bit_buf >> (32 - num_bits);
+
+ if ((m_bits_left -= num_bits) <= 0)
+ {
+ m_bit_buf <<= (num_bits += m_bits_left);
+
+ uint c1 = get_char();
+ uint c2 = get_char();
+ m_bit_buf = (m_bit_buf & 0xFFFF0000) | (c1 << 8) | c2;
+
+ m_bit_buf <<= -m_bits_left;
+
+ m_bits_left += 16;
+
+ assert(m_bits_left >= 0);
+ }
+ else
+ m_bit_buf <<= num_bits;
+
+ return i;
+ }
+
+ // Retrieves a variable number of bits from the input stream. Markers will not be read into the input bit buffer. Instead, an infinite number of all 1's will be returned when a marker is encountered.
+ inline uint jpeg_decoder::get_bits_no_markers(int num_bits)
+ {
+ if (!num_bits)
+ return 0;
+
+ assert(num_bits <= 16);
+
+ uint i = m_bit_buf >> (32 - num_bits);
+
+ if ((m_bits_left -= num_bits) <= 0)
+ {
+ m_bit_buf <<= (num_bits += m_bits_left);
+
+ if ((m_in_buf_left < 2) || (m_pIn_buf_ofs[0] == 0xFF) || (m_pIn_buf_ofs[1] == 0xFF))
+ {
+ uint c1 = get_octet();
+ uint c2 = get_octet();
+ m_bit_buf |= (c1 << 8) | c2;
+ }
+ else
+ {
+ m_bit_buf |= ((uint)m_pIn_buf_ofs[0] << 8) | m_pIn_buf_ofs[1];
+ m_in_buf_left -= 2;
+ m_pIn_buf_ofs += 2;
+ }
+
+ m_bit_buf <<= -m_bits_left;
+
+ m_bits_left += 16;
+
+ assert(m_bits_left >= 0);
+ }
+ else
+ m_bit_buf <<= num_bits;
+
+ return i;
+ }
+
+ // Decodes a Huffman encoded symbol.
+ inline int jpeg_decoder::huff_decode(huff_tables* pH)
+ {
+ if (!pH)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ int symbol;
+ // Check first 8-bits: do we have a complete symbol?
+ if ((symbol = pH->look_up[m_bit_buf >> 24]) < 0)
+ {
+ // Decode more bits, use a tree traversal to find symbol.
+ int ofs = 23;
+ do
+ {
+ unsigned int idx = -(int)(symbol + ((m_bit_buf >> ofs) & 1));
+
+ // This should never happen, but to be safe I'm turning these asserts into a run-time check.
+ if ((idx >= JPGD_HUFF_TREE_MAX_LENGTH) || (ofs < 0))
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ symbol = pH->tree[idx];
+ ofs--;
+ } while (symbol < 0);
+
+ get_bits_no_markers(8 + (23 - ofs));
+ }
+ else
+ {
+ assert(symbol < JPGD_HUFF_CODE_SIZE_MAX_LENGTH);
+ get_bits_no_markers(pH->code_size[symbol]);
+ }
+
+ return symbol;
+ }
+
+ // Decodes a Huffman encoded symbol.
+ inline int jpeg_decoder::huff_decode(huff_tables* pH, int& extra_bits)
+ {
+ int symbol;
+
+ if (!pH)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ // Check first 8-bits: do we have a complete symbol?
+ if ((symbol = pH->look_up2[m_bit_buf >> 24]) < 0)
+ {
+ // Use a tree traversal to find symbol.
+ int ofs = 23;
+ do
+ {
+ unsigned int idx = -(int)(symbol + ((m_bit_buf >> ofs) & 1));
+
+ // This should never happen, but to be safe I'm turning these asserts into a run-time check.
+ if ((idx >= JPGD_HUFF_TREE_MAX_LENGTH) || (ofs < 0))
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ symbol = pH->tree[idx];
+ ofs--;
+ } while (symbol < 0);
+
+ get_bits_no_markers(8 + (23 - ofs));
+
+ extra_bits = get_bits_no_markers(symbol & 0xF);
+ }
+ else
+ {
+ if (symbol & 0x8000)
+ {
+ //get_bits_no_markers((symbol >> 8) & 31);
+ assert(((symbol >> 8) & 31) <= 15);
+ get_bits_no_markers((symbol >> 8) & 15);
+ extra_bits = symbol >> 16;
+ }
+ else
+ {
+ int code_size = (symbol >> 8) & 31;
+ int num_extra_bits = symbol & 0xF;
+ int bits = code_size + num_extra_bits;
+
+ if (bits <= 16)
+ extra_bits = get_bits_no_markers(bits) & ((1 << num_extra_bits) - 1);
+ else
+ {
+ get_bits_no_markers(code_size);
+ extra_bits = get_bits_no_markers(num_extra_bits);
+ }
+ }
+
+ symbol &= 0xFF;
+ }
+
+ return symbol;
+ }
+
+ // Tables and macro used to fully decode the DPCM differences.
+ static const int s_extend_test[16] = { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+ static const int s_extend_offset[16] = { 0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047, -4095, -8191, -16383, -32767 };
+ //static const int s_extend_mask[] = { 0, (1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4), (1 << 5), (1 << 6), (1 << 7), (1 << 8), (1 << 9), (1 << 10), (1 << 11), (1 << 12), (1 << 13), (1 << 14), (1 << 15), (1 << 16) };
+
#define JPGD_HUFF_EXTEND(x, s) (((x) < s_extend_test[s & 15]) ? ((x) + s_extend_offset[s & 15]) : (x))
-// Clamps a value between 0-255.
-inline uint8 jpeg_decoder::clamp(int i)
-{
- if (static_cast<uint>(i) > 255)
- i = (((~i) >> 31) & 0xFF);
-
- return static_cast<uint8>(i);
-}
-
-namespace DCT_Upsample
-{
- struct Matrix44
- {
- typedef int Element_Type;
- enum { NUM_ROWS = 4, NUM_COLS = 4 };
-
- Element_Type v[NUM_ROWS][NUM_COLS];
-
- inline int rows() const { return NUM_ROWS; }
- inline int cols() const { return NUM_COLS; }
-
- inline const Element_Type & at(int r, int c) const { return v[r][c]; }
- inline Element_Type & at(int r, int c) { return v[r][c]; }
-
- inline Matrix44() { }
-
- inline Matrix44& operator += (const Matrix44& a)
- {
- for (int r = 0; r < NUM_ROWS; r++)
- {
- at(r, 0) += a.at(r, 0);
- at(r, 1) += a.at(r, 1);
- at(r, 2) += a.at(r, 2);
- at(r, 3) += a.at(r, 3);
- }
- return *this;
- }
-
- inline Matrix44& operator -= (const Matrix44& a)
- {
- for (int r = 0; r < NUM_ROWS; r++)
- {
- at(r, 0) -= a.at(r, 0);
- at(r, 1) -= a.at(r, 1);
- at(r, 2) -= a.at(r, 2);
- at(r, 3) -= a.at(r, 3);
- }
- return *this;
- }
-
- friend inline Matrix44 operator + (const Matrix44& a, const Matrix44& b)
- {
- Matrix44 ret;
- for (int r = 0; r < NUM_ROWS; r++)
- {
- ret.at(r, 0) = a.at(r, 0) + b.at(r, 0);
- ret.at(r, 1) = a.at(r, 1) + b.at(r, 1);
- ret.at(r, 2) = a.at(r, 2) + b.at(r, 2);
- ret.at(r, 3) = a.at(r, 3) + b.at(r, 3);
- }
- return ret;
- }
-
- friend inline Matrix44 operator - (const Matrix44& a, const Matrix44& b)
- {
- Matrix44 ret;
- for (int r = 0; r < NUM_ROWS; r++)
- {
- ret.at(r, 0) = a.at(r, 0) - b.at(r, 0);
- ret.at(r, 1) = a.at(r, 1) - b.at(r, 1);
- ret.at(r, 2) = a.at(r, 2) - b.at(r, 2);
- ret.at(r, 3) = a.at(r, 3) - b.at(r, 3);
- }
- return ret;
- }
-
- static inline void add_and_store(jpgd_block_t* pDst, const Matrix44& a, const Matrix44& b)
- {
- for (int r = 0; r < 4; r++)
- {
- pDst[0*8 + r] = static_cast<jpgd_block_t>(a.at(r, 0) + b.at(r, 0));
- pDst[1*8 + r] = static_cast<jpgd_block_t>(a.at(r, 1) + b.at(r, 1));
- pDst[2*8 + r] = static_cast<jpgd_block_t>(a.at(r, 2) + b.at(r, 2));
- pDst[3*8 + r] = static_cast<jpgd_block_t>(a.at(r, 3) + b.at(r, 3));
- }
- }
-
- static inline void sub_and_store(jpgd_block_t* pDst, const Matrix44& a, const Matrix44& b)
- {
- for (int r = 0; r < 4; r++)
- {
- pDst[0*8 + r] = static_cast<jpgd_block_t>(a.at(r, 0) - b.at(r, 0));
- pDst[1*8 + r] = static_cast<jpgd_block_t>(a.at(r, 1) - b.at(r, 1));
- pDst[2*8 + r] = static_cast<jpgd_block_t>(a.at(r, 2) - b.at(r, 2));
- pDst[3*8 + r] = static_cast<jpgd_block_t>(a.at(r, 3) - b.at(r, 3));
- }
- }
- };
-
- const int FRACT_BITS = 10;
- const int SCALE = 1 << FRACT_BITS;
-
- typedef int Temp_Type;
- #define D(i) (((i) + (SCALE >> 1)) >> FRACT_BITS)
- #define F(i) ((int)((i) * SCALE + .5f))
-
- // Any decent C++ compiler will optimize this at compile time to a 0, or an array access.
- #define AT(c, r) ((((c)>=NUM_COLS)||((r)>=NUM_ROWS)) ? 0 : pSrc[(c)+(r)*8])
-
- // NUM_ROWS/NUM_COLS = # of non-zero rows/cols in input matrix
- template<int NUM_ROWS, int NUM_COLS>
- struct P_Q
- {
- static void calc(Matrix44& P, Matrix44& Q, const jpgd_block_t* pSrc)
- {
- // 4x8 = 4x8 times 8x8, matrix 0 is constant
- const Temp_Type X000 = AT(0, 0);
- const Temp_Type X001 = AT(0, 1);
- const Temp_Type X002 = AT(0, 2);
- const Temp_Type X003 = AT(0, 3);
- const Temp_Type X004 = AT(0, 4);
- const Temp_Type X005 = AT(0, 5);
- const Temp_Type X006 = AT(0, 6);
- const Temp_Type X007 = AT(0, 7);
- const Temp_Type X010 = D(F(0.415735f) * AT(1, 0) + F(0.791065f) * AT(3, 0) + F(-0.352443f) * AT(5, 0) + F(0.277785f) * AT(7, 0));
- const Temp_Type X011 = D(F(0.415735f) * AT(1, 1) + F(0.791065f) * AT(3, 1) + F(-0.352443f) * AT(5, 1) + F(0.277785f) * AT(7, 1));
- const Temp_Type X012 = D(F(0.415735f) * AT(1, 2) + F(0.791065f) * AT(3, 2) + F(-0.352443f) * AT(5, 2) + F(0.277785f) * AT(7, 2));
- const Temp_Type X013 = D(F(0.415735f) * AT(1, 3) + F(0.791065f) * AT(3, 3) + F(-0.352443f) * AT(5, 3) + F(0.277785f) * AT(7, 3));
- const Temp_Type X014 = D(F(0.415735f) * AT(1, 4) + F(0.791065f) * AT(3, 4) + F(-0.352443f) * AT(5, 4) + F(0.277785f) * AT(7, 4));
- const Temp_Type X015 = D(F(0.415735f) * AT(1, 5) + F(0.791065f) * AT(3, 5) + F(-0.352443f) * AT(5, 5) + F(0.277785f) * AT(7, 5));
- const Temp_Type X016 = D(F(0.415735f) * AT(1, 6) + F(0.791065f) * AT(3, 6) + F(-0.352443f) * AT(5, 6) + F(0.277785f) * AT(7, 6));
- const Temp_Type X017 = D(F(0.415735f) * AT(1, 7) + F(0.791065f) * AT(3, 7) + F(-0.352443f) * AT(5, 7) + F(0.277785f) * AT(7, 7));
- const Temp_Type X020 = AT(4, 0);
- const Temp_Type X021 = AT(4, 1);
- const Temp_Type X022 = AT(4, 2);
- const Temp_Type X023 = AT(4, 3);
- const Temp_Type X024 = AT(4, 4);
- const Temp_Type X025 = AT(4, 5);
- const Temp_Type X026 = AT(4, 6);
- const Temp_Type X027 = AT(4, 7);
- const Temp_Type X030 = D(F(0.022887f) * AT(1, 0) + F(-0.097545f) * AT(3, 0) + F(0.490393f) * AT(5, 0) + F(0.865723f) * AT(7, 0));
- const Temp_Type X031 = D(F(0.022887f) * AT(1, 1) + F(-0.097545f) * AT(3, 1) + F(0.490393f) * AT(5, 1) + F(0.865723f) * AT(7, 1));
- const Temp_Type X032 = D(F(0.022887f) * AT(1, 2) + F(-0.097545f) * AT(3, 2) + F(0.490393f) * AT(5, 2) + F(0.865723f) * AT(7, 2));
- const Temp_Type X033 = D(F(0.022887f) * AT(1, 3) + F(-0.097545f) * AT(3, 3) + F(0.490393f) * AT(5, 3) + F(0.865723f) * AT(7, 3));
- const Temp_Type X034 = D(F(0.022887f) * AT(1, 4) + F(-0.097545f) * AT(3, 4) + F(0.490393f) * AT(5, 4) + F(0.865723f) * AT(7, 4));
- const Temp_Type X035 = D(F(0.022887f) * AT(1, 5) + F(-0.097545f) * AT(3, 5) + F(0.490393f) * AT(5, 5) + F(0.865723f) * AT(7, 5));
- const Temp_Type X036 = D(F(0.022887f) * AT(1, 6) + F(-0.097545f) * AT(3, 6) + F(0.490393f) * AT(5, 6) + F(0.865723f) * AT(7, 6));
- const Temp_Type X037 = D(F(0.022887f) * AT(1, 7) + F(-0.097545f) * AT(3, 7) + F(0.490393f) * AT(5, 7) + F(0.865723f) * AT(7, 7));
-
- // 4x4 = 4x8 times 8x4, matrix 1 is constant
- P.at(0, 0) = X000;
- P.at(0, 1) = D(X001 * F(0.415735f) + X003 * F(0.791065f) + X005 * F(-0.352443f) + X007 * F(0.277785f));
- P.at(0, 2) = X004;
- P.at(0, 3) = D(X001 * F(0.022887f) + X003 * F(-0.097545f) + X005 * F(0.490393f) + X007 * F(0.865723f));
- P.at(1, 0) = X010;
- P.at(1, 1) = D(X011 * F(0.415735f) + X013 * F(0.791065f) + X015 * F(-0.352443f) + X017 * F(0.277785f));
- P.at(1, 2) = X014;
- P.at(1, 3) = D(X011 * F(0.022887f) + X013 * F(-0.097545f) + X015 * F(0.490393f) + X017 * F(0.865723f));
- P.at(2, 0) = X020;
- P.at(2, 1) = D(X021 * F(0.415735f) + X023 * F(0.791065f) + X025 * F(-0.352443f) + X027 * F(0.277785f));
- P.at(2, 2) = X024;
- P.at(2, 3) = D(X021 * F(0.022887f) + X023 * F(-0.097545f) + X025 * F(0.490393f) + X027 * F(0.865723f));
- P.at(3, 0) = X030;
- P.at(3, 1) = D(X031 * F(0.415735f) + X033 * F(0.791065f) + X035 * F(-0.352443f) + X037 * F(0.277785f));
- P.at(3, 2) = X034;
- P.at(3, 3) = D(X031 * F(0.022887f) + X033 * F(-0.097545f) + X035 * F(0.490393f) + X037 * F(0.865723f));
- // 40 muls 24 adds
-
- // 4x4 = 4x8 times 8x4, matrix 1 is constant
- Q.at(0, 0) = D(X001 * F(0.906127f) + X003 * F(-0.318190f) + X005 * F(0.212608f) + X007 * F(-0.180240f));
- Q.at(0, 1) = X002;
- Q.at(0, 2) = D(X001 * F(-0.074658f) + X003 * F(0.513280f) + X005 * F(0.768178f) + X007 * F(-0.375330f));
- Q.at(0, 3) = X006;
- Q.at(1, 0) = D(X011 * F(0.906127f) + X013 * F(-0.318190f) + X015 * F(0.212608f) + X017 * F(-0.180240f));
- Q.at(1, 1) = X012;
- Q.at(1, 2) = D(X011 * F(-0.074658f) + X013 * F(0.513280f) + X015 * F(0.768178f) + X017 * F(-0.375330f));
- Q.at(1, 3) = X016;
- Q.at(2, 0) = D(X021 * F(0.906127f) + X023 * F(-0.318190f) + X025 * F(0.212608f) + X027 * F(-0.180240f));
- Q.at(2, 1) = X022;
- Q.at(2, 2) = D(X021 * F(-0.074658f) + X023 * F(0.513280f) + X025 * F(0.768178f) + X027 * F(-0.375330f));
- Q.at(2, 3) = X026;
- Q.at(3, 0) = D(X031 * F(0.906127f) + X033 * F(-0.318190f) + X035 * F(0.212608f) + X037 * F(-0.180240f));
- Q.at(3, 1) = X032;
- Q.at(3, 2) = D(X031 * F(-0.074658f) + X033 * F(0.513280f) + X035 * F(0.768178f) + X037 * F(-0.375330f));
- Q.at(3, 3) = X036;
- // 40 muls 24 adds
- }
- };
-
- template<int NUM_ROWS, int NUM_COLS>
- struct R_S
- {
- static void calc(Matrix44& R, Matrix44& S, const jpgd_block_t* pSrc)
- {
- // 4x8 = 4x8 times 8x8, matrix 0 is constant
- const Temp_Type X100 = D(F(0.906127f) * AT(1, 0) + F(-0.318190f) * AT(3, 0) + F(0.212608f) * AT(5, 0) + F(-0.180240f) * AT(7, 0));
- const Temp_Type X101 = D(F(0.906127f) * AT(1, 1) + F(-0.318190f) * AT(3, 1) + F(0.212608f) * AT(5, 1) + F(-0.180240f) * AT(7, 1));
- const Temp_Type X102 = D(F(0.906127f) * AT(1, 2) + F(-0.318190f) * AT(3, 2) + F(0.212608f) * AT(5, 2) + F(-0.180240f) * AT(7, 2));
- const Temp_Type X103 = D(F(0.906127f) * AT(1, 3) + F(-0.318190f) * AT(3, 3) + F(0.212608f) * AT(5, 3) + F(-0.180240f) * AT(7, 3));
- const Temp_Type X104 = D(F(0.906127f) * AT(1, 4) + F(-0.318190f) * AT(3, 4) + F(0.212608f) * AT(5, 4) + F(-0.180240f) * AT(7, 4));
- const Temp_Type X105 = D(F(0.906127f) * AT(1, 5) + F(-0.318190f) * AT(3, 5) + F(0.212608f) * AT(5, 5) + F(-0.180240f) * AT(7, 5));
- const Temp_Type X106 = D(F(0.906127f) * AT(1, 6) + F(-0.318190f) * AT(3, 6) + F(0.212608f) * AT(5, 6) + F(-0.180240f) * AT(7, 6));
- const Temp_Type X107 = D(F(0.906127f) * AT(1, 7) + F(-0.318190f) * AT(3, 7) + F(0.212608f) * AT(5, 7) + F(-0.180240f) * AT(7, 7));
- const Temp_Type X110 = AT(2, 0);
- const Temp_Type X111 = AT(2, 1);
- const Temp_Type X112 = AT(2, 2);
- const Temp_Type X113 = AT(2, 3);
- const Temp_Type X114 = AT(2, 4);
- const Temp_Type X115 = AT(2, 5);
- const Temp_Type X116 = AT(2, 6);
- const Temp_Type X117 = AT(2, 7);
- const Temp_Type X120 = D(F(-0.074658f) * AT(1, 0) + F(0.513280f) * AT(3, 0) + F(0.768178f) * AT(5, 0) + F(-0.375330f) * AT(7, 0));
- const Temp_Type X121 = D(F(-0.074658f) * AT(1, 1) + F(0.513280f) * AT(3, 1) + F(0.768178f) * AT(5, 1) + F(-0.375330f) * AT(7, 1));
- const Temp_Type X122 = D(F(-0.074658f) * AT(1, 2) + F(0.513280f) * AT(3, 2) + F(0.768178f) * AT(5, 2) + F(-0.375330f) * AT(7, 2));
- const Temp_Type X123 = D(F(-0.074658f) * AT(1, 3) + F(0.513280f) * AT(3, 3) + F(0.768178f) * AT(5, 3) + F(-0.375330f) * AT(7, 3));
- const Temp_Type X124 = D(F(-0.074658f) * AT(1, 4) + F(0.513280f) * AT(3, 4) + F(0.768178f) * AT(5, 4) + F(-0.375330f) * AT(7, 4));
- const Temp_Type X125 = D(F(-0.074658f) * AT(1, 5) + F(0.513280f) * AT(3, 5) + F(0.768178f) * AT(5, 5) + F(-0.375330f) * AT(7, 5));
- const Temp_Type X126 = D(F(-0.074658f) * AT(1, 6) + F(0.513280f) * AT(3, 6) + F(0.768178f) * AT(5, 6) + F(-0.375330f) * AT(7, 6));
- const Temp_Type X127 = D(F(-0.074658f) * AT(1, 7) + F(0.513280f) * AT(3, 7) + F(0.768178f) * AT(5, 7) + F(-0.375330f) * AT(7, 7));
- const Temp_Type X130 = AT(6, 0);
- const Temp_Type X131 = AT(6, 1);
- const Temp_Type X132 = AT(6, 2);
- const Temp_Type X133 = AT(6, 3);
- const Temp_Type X134 = AT(6, 4);
- const Temp_Type X135 = AT(6, 5);
- const Temp_Type X136 = AT(6, 6);
- const Temp_Type X137 = AT(6, 7);
- // 80 muls 48 adds
-
- // 4x4 = 4x8 times 8x4, matrix 1 is constant
- R.at(0, 0) = X100;
- R.at(0, 1) = D(X101 * F(0.415735f) + X103 * F(0.791065f) + X105 * F(-0.352443f) + X107 * F(0.277785f));
- R.at(0, 2) = X104;
- R.at(0, 3) = D(X101 * F(0.022887f) + X103 * F(-0.097545f) + X105 * F(0.490393f) + X107 * F(0.865723f));
- R.at(1, 0) = X110;
- R.at(1, 1) = D(X111 * F(0.415735f) + X113 * F(0.791065f) + X115 * F(-0.352443f) + X117 * F(0.277785f));
- R.at(1, 2) = X114;
- R.at(1, 3) = D(X111 * F(0.022887f) + X113 * F(-0.097545f) + X115 * F(0.490393f) + X117 * F(0.865723f));
- R.at(2, 0) = X120;
- R.at(2, 1) = D(X121 * F(0.415735f) + X123 * F(0.791065f) + X125 * F(-0.352443f) + X127 * F(0.277785f));
- R.at(2, 2) = X124;
- R.at(2, 3) = D(X121 * F(0.022887f) + X123 * F(-0.097545f) + X125 * F(0.490393f) + X127 * F(0.865723f));
- R.at(3, 0) = X130;
- R.at(3, 1) = D(X131 * F(0.415735f) + X133 * F(0.791065f) + X135 * F(-0.352443f) + X137 * F(0.277785f));
- R.at(3, 2) = X134;
- R.at(3, 3) = D(X131 * F(0.022887f) + X133 * F(-0.097545f) + X135 * F(0.490393f) + X137 * F(0.865723f));
- // 40 muls 24 adds
- // 4x4 = 4x8 times 8x4, matrix 1 is constant
- S.at(0, 0) = D(X101 * F(0.906127f) + X103 * F(-0.318190f) + X105 * F(0.212608f) + X107 * F(-0.180240f));
- S.at(0, 1) = X102;
- S.at(0, 2) = D(X101 * F(-0.074658f) + X103 * F(0.513280f) + X105 * F(0.768178f) + X107 * F(-0.375330f));
- S.at(0, 3) = X106;
- S.at(1, 0) = D(X111 * F(0.906127f) + X113 * F(-0.318190f) + X115 * F(0.212608f) + X117 * F(-0.180240f));
- S.at(1, 1) = X112;
- S.at(1, 2) = D(X111 * F(-0.074658f) + X113 * F(0.513280f) + X115 * F(0.768178f) + X117 * F(-0.375330f));
- S.at(1, 3) = X116;
- S.at(2, 0) = D(X121 * F(0.906127f) + X123 * F(-0.318190f) + X125 * F(0.212608f) + X127 * F(-0.180240f));
- S.at(2, 1) = X122;
- S.at(2, 2) = D(X121 * F(-0.074658f) + X123 * F(0.513280f) + X125 * F(0.768178f) + X127 * F(-0.375330f));
- S.at(2, 3) = X126;
- S.at(3, 0) = D(X131 * F(0.906127f) + X133 * F(-0.318190f) + X135 * F(0.212608f) + X137 * F(-0.180240f));
- S.at(3, 1) = X132;
- S.at(3, 2) = D(X131 * F(-0.074658f) + X133 * F(0.513280f) + X135 * F(0.768178f) + X137 * F(-0.375330f));
- S.at(3, 3) = X136;
- // 40 muls 24 adds
- }
- };
-} // end namespace DCT_Upsample
-
-// Unconditionally frees all allocated m_blocks.
-void jpeg_decoder::free_all_blocks()
-{
- m_pStream = NULL;
- for (mem_block *b = m_pMem_blocks; b; )
- {
- mem_block *n = b->m_pNext;
- jpgd_free(b);
- b = n;
- }
- m_pMem_blocks = NULL;
-}
-
-// This method handles all errors. It will never return.
-// It could easily be changed to use C++ exceptions.
-JPGD_NORETURN void jpeg_decoder::stop_decoding(jpgd_status status)
-{
- m_error_code = status;
- free_all_blocks();
- longjmp(m_jmp_state, status);
-}
-
-void *jpeg_decoder::alloc(size_t nSize, bool zero)
-{
- nSize = (JPGD_MAX(nSize, 1) + 3) & ~3;
- char *rv = NULL;
- for (mem_block *b = m_pMem_blocks; b; b = b->m_pNext)
- {
- if ((b->m_used_count + nSize) <= b->m_size)
- {
- rv = b->m_data + b->m_used_count;
- b->m_used_count += nSize;
- break;
- }
- }
- if (!rv)
- {
- int capacity = JPGD_MAX(32768 - 256, (nSize + 2047) & ~2047);
- mem_block *b = (mem_block*)jpgd_malloc(sizeof(mem_block) + capacity);
- if (!b) { stop_decoding(JPGD_NOTENOUGHMEM); }
- b->m_pNext = m_pMem_blocks; m_pMem_blocks = b;
- b->m_used_count = nSize;
- b->m_size = capacity;
- rv = b->m_data;
- }
- if (zero) memset(rv, 0, nSize);
- return rv;
-}
-
-void jpeg_decoder::word_clear(void *p, uint16 c, uint n)
-{
- uint8 *pD = (uint8*)p;
- const uint8 l = c & 0xFF, h = (c >> 8) & 0xFF;
- while (n)
- {
- pD[0] = l; pD[1] = h; pD += 2;
- n--;
- }
-}
-
-// Refill the input buffer.
-// This method will sit in a loop until (A) the buffer is full or (B)
-// the stream's read() method reports and end of file condition.
-void jpeg_decoder::prep_in_buffer()
-{
- m_in_buf_left = 0;
- m_pIn_buf_ofs = m_in_buf;
-
- if (m_eof_flag)
- return;
-
- do
- {
- int bytes_read = m_pStream->read(m_in_buf + m_in_buf_left, JPGD_IN_BUF_SIZE - m_in_buf_left, &m_eof_flag);
- if (bytes_read == -1)
- stop_decoding(JPGD_STREAM_READ);
-
- m_in_buf_left += bytes_read;
- } while ((m_in_buf_left < JPGD_IN_BUF_SIZE) && (!m_eof_flag));
-
- m_total_bytes_read += m_in_buf_left;
-
- // Pad the end of the block with M_EOI (prevents the decompressor from going off the rails if the stream is invalid).
- // (This dates way back to when this decompressor was written in C/asm, and the all-asm Huffman decoder did some fancy things to increase perf.)
- word_clear(m_pIn_buf_ofs + m_in_buf_left, 0xD9FF, 64);
-}
-
-// Read a Huffman code table.
-void jpeg_decoder::read_dht_marker()
-{
- int i, index, count;
- uint8 huff_num[17];
- uint8 huff_val[256];
-
- uint num_left = get_bits(16);
-
- if (num_left < 2)
- stop_decoding(JPGD_BAD_DHT_MARKER);
-
- num_left -= 2;
-
- while (num_left)
- {
- index = get_bits(8);
-
- huff_num[0] = 0;
-
- count = 0;
-
- for (i = 1; i <= 16; i++)
- {
- huff_num[i] = static_cast<uint8>(get_bits(8));
- count += huff_num[i];
- }
-
- if (count > 255)
- stop_decoding(JPGD_BAD_DHT_COUNTS);
-
- for (i = 0; i < count; i++)
- huff_val[i] = static_cast<uint8>(get_bits(8));
+ // Unconditionally frees all allocated m_blocks.
+ void jpeg_decoder::free_all_blocks()
+ {
+ m_pStream = nullptr;
+ for (mem_block* b = m_pMem_blocks; b; )
+ {
+ mem_block* n = b->m_pNext;
+ jpgd_free(b);
+ b = n;
+ }
+ m_pMem_blocks = nullptr;
+ }
+
+ // This method handles all errors. It will never return.
+ // It could easily be changed to use C++ exceptions.
+ JPGD_NORETURN void jpeg_decoder::stop_decoding(jpgd_status status)
+ {
+ m_error_code = status;
+ free_all_blocks();
+ longjmp(m_jmp_state, status);
+ }
+
+ void* jpeg_decoder::alloc(size_t nSize, bool zero)
+ {
+ nSize = (JPGD_MAX(nSize, 1) + 3) & ~3;
+ char* rv = nullptr;
+ for (mem_block* b = m_pMem_blocks; b; b = b->m_pNext)
+ {
+ if ((b->m_used_count + nSize) <= b->m_size)
+ {
+ rv = b->m_data + b->m_used_count;
+ b->m_used_count += nSize;
+ break;
+ }
+ }
+ if (!rv)
+ {
+ int capacity = JPGD_MAX(32768 - 256, (nSize + 2047) & ~2047);
+ mem_block* b = (mem_block*)jpgd_malloc(sizeof(mem_block) + capacity);
+ if (!b)
+ {
+ stop_decoding(JPGD_NOTENOUGHMEM);
+ }
+
+ b->m_pNext = m_pMem_blocks;
+ m_pMem_blocks = b;
+ b->m_used_count = nSize;
+ b->m_size = capacity;
+ rv = b->m_data;
+ }
+ if (zero) memset(rv, 0, nSize);
+ return rv;
+ }
+
+ void* jpeg_decoder::alloc_aligned(size_t nSize, uint32_t align, bool zero)
+ {
+ assert((align >= 1U) && ((align & (align - 1U)) == 0U));
+ void *p = alloc(nSize + align - 1U, zero);
+ p = (void *)( ((uintptr_t)p + (align - 1U)) & ~((uintptr_t)(align - 1U)) );
+ return p;
+ }
+
+ void jpeg_decoder::word_clear(void* p, uint16 c, uint n)
+ {
+ uint8* pD = (uint8*)p;
+ const uint8 l = c & 0xFF, h = (c >> 8) & 0xFF;
+ while (n)
+ {
+ pD[0] = l;
+ pD[1] = h;
+ pD += 2;
+ n--;
+ }
+ }
+
+ // Refill the input buffer.
+ // This method will sit in a loop until (A) the buffer is full or (B)
+ // the stream's read() method reports and end of file condition.
+ void jpeg_decoder::prep_in_buffer()
+ {
+ m_in_buf_left = 0;
+ m_pIn_buf_ofs = m_in_buf;
+
+ if (m_eof_flag)
+ return;
+
+ do
+ {
+ int bytes_read = m_pStream->read(m_in_buf + m_in_buf_left, JPGD_IN_BUF_SIZE - m_in_buf_left, &m_eof_flag);
+ if (bytes_read == -1)
+ stop_decoding(JPGD_STREAM_READ);
+
+ m_in_buf_left += bytes_read;
+ } while ((m_in_buf_left < JPGD_IN_BUF_SIZE) && (!m_eof_flag));
+
+ m_total_bytes_read += m_in_buf_left;
+
+ // Pad the end of the block with M_EOI (prevents the decompressor from going off the rails if the stream is invalid).
+ // (This dates way back to when this decompressor was written in C/asm, and the all-asm Huffman decoder did some fancy things to increase perf.)
+ word_clear(m_pIn_buf_ofs + m_in_buf_left, 0xD9FF, 64);
+ }
+
+ // Read a Huffman code table.
+ void jpeg_decoder::read_dht_marker()
+ {
+ int i, index, count;
+ uint8 huff_num[17];
+ uint8 huff_val[256];
- i = 1 + 16 + count;
+ uint num_left = get_bits(16);
- if (num_left < (uint)i)
- stop_decoding(JPGD_BAD_DHT_MARKER);
+ if (num_left < 2)
+ stop_decoding(JPGD_BAD_DHT_MARKER);
- num_left -= i;
+ num_left -= 2;
- if ((index & 0x10) > 0x10)
- stop_decoding(JPGD_BAD_DHT_INDEX);
+ while (num_left)
+ {
+ index = get_bits(8);
- index = (index & 0x0F) + ((index & 0x10) >> 4) * (JPGD_MAX_HUFF_TABLES >> 1);
+ huff_num[0] = 0;
- if (index >= JPGD_MAX_HUFF_TABLES)
- stop_decoding(JPGD_BAD_DHT_INDEX);
+ count = 0;
- if (!m_huff_num[index])
- m_huff_num[index] = (uint8 *)alloc(17);
+ for (i = 1; i <= 16; i++)
+ {
+ huff_num[i] = static_cast<uint8>(get_bits(8));
+ count += huff_num[i];
+ }
- if (!m_huff_val[index])
- m_huff_val[index] = (uint8 *)alloc(256);
+ if (count > 255)
+ stop_decoding(JPGD_BAD_DHT_COUNTS);
- m_huff_ac[index] = (index & 0x10) != 0;
- memcpy(m_huff_num[index], huff_num, 17);
- memcpy(m_huff_val[index], huff_val, 256);
- }
-}
+ bool symbol_present[256];
+ memset(symbol_present, 0, sizeof(symbol_present));
-// Read a quantization table.
-void jpeg_decoder::read_dqt_marker()
-{
- int n, i, prec;
- uint num_left;
- uint temp;
+ for (i = 0; i < count; i++)
+ {
+ const int s = get_bits(8);
- num_left = get_bits(16);
+ // Check for obviously bogus tables.
+ if (symbol_present[s])
+ stop_decoding(JPGD_BAD_DHT_COUNTS);
- if (num_left < 2)
- stop_decoding(JPGD_BAD_DQT_MARKER);
+ huff_val[i] = static_cast<uint8_t>(s);
+ symbol_present[s] = true;
+ }
- num_left -= 2;
+ i = 1 + 16 + count;
- while (num_left)
- {
- n = get_bits(8);
- prec = n >> 4;
- n &= 0x0F;
+ if (num_left < (uint)i)
+ stop_decoding(JPGD_BAD_DHT_MARKER);
- if (n >= JPGD_MAX_QUANT_TABLES)
- stop_decoding(JPGD_BAD_DQT_TABLE);
+ num_left -= i;
- if (!m_quant[n])
- m_quant[n] = (jpgd_quant_t *)alloc(64 * sizeof(jpgd_quant_t));
+ if ((index & 0x10) > 0x10)
+ stop_decoding(JPGD_BAD_DHT_INDEX);
- // read quantization entries, in zag order
- for (i = 0; i < 64; i++)
- {
- temp = get_bits(8);
+ index = (index & 0x0F) + ((index & 0x10) >> 4) * (JPGD_MAX_HUFF_TABLES >> 1);
- if (prec)
- temp = (temp << 8) + get_bits(8);
+ if (index >= JPGD_MAX_HUFF_TABLES)
+ stop_decoding(JPGD_BAD_DHT_INDEX);
- m_quant[n][i] = static_cast<jpgd_quant_t>(temp);
- }
+ if (!m_huff_num[index])
+ m_huff_num[index] = (uint8*)alloc(17);
- i = 64 + 1;
+ if (!m_huff_val[index])
+ m_huff_val[index] = (uint8*)alloc(256);
- if (prec)
- i += 64;
+ m_huff_ac[index] = (index & 0x10) != 0;
+ memcpy(m_huff_num[index], huff_num, 17);
+ memcpy(m_huff_val[index], huff_val, 256);
+ }
+ }
- if (num_left < (uint)i)
- stop_decoding(JPGD_BAD_DQT_LENGTH);
+ // Read a quantization table.
+ void jpeg_decoder::read_dqt_marker()
+ {
+ int n, i, prec;
+ uint num_left;
+ uint temp;
- num_left -= i;
- }
-}
+ num_left = get_bits(16);
-// Read the start of frame (SOF) marker.
-void jpeg_decoder::read_sof_marker()
-{
- int i;
- uint num_left;
+ if (num_left < 2)
+ stop_decoding(JPGD_BAD_DQT_MARKER);
- num_left = get_bits(16);
+ num_left -= 2;
- if (get_bits(8) != 8) /* precision: sorry, only 8-bit precision is supported right now */
- stop_decoding(JPGD_BAD_PRECISION);
+ while (num_left)
+ {
+ n = get_bits(8);
+ prec = n >> 4;
+ n &= 0x0F;
- m_image_y_size = get_bits(16);
+ if (n >= JPGD_MAX_QUANT_TABLES)
+ stop_decoding(JPGD_BAD_DQT_TABLE);
- if ((m_image_y_size < 1) || (m_image_y_size > JPGD_MAX_HEIGHT))
- stop_decoding(JPGD_BAD_HEIGHT);
+ if (!m_quant[n])
+ m_quant[n] = (jpgd_quant_t*)alloc(64 * sizeof(jpgd_quant_t));
- m_image_x_size = get_bits(16);
+ // read quantization entries, in zag order
+ for (i = 0; i < 64; i++)
+ {
+ temp = get_bits(8);
- if ((m_image_x_size < 1) || (m_image_x_size > JPGD_MAX_WIDTH))
- stop_decoding(JPGD_BAD_WIDTH);
+ if (prec)
+ temp = (temp << 8) + get_bits(8);
- m_comps_in_frame = get_bits(8);
+ m_quant[n][i] = static_cast<jpgd_quant_t>(temp);
+ }
- if (m_comps_in_frame > JPGD_MAX_COMPONENTS)
- stop_decoding(JPGD_TOO_MANY_COMPONENTS);
+ i = 64 + 1;
- if (num_left != (uint)(m_comps_in_frame * 3 + 8))
- stop_decoding(JPGD_BAD_SOF_LENGTH);
+ if (prec)
+ i += 64;
- for (i = 0; i < m_comps_in_frame; i++)
- {
- m_comp_ident[i] = get_bits(8);
- m_comp_h_samp[i] = get_bits(4);
- m_comp_v_samp[i] = get_bits(4);
- m_comp_quant[i] = get_bits(8);
- }
-}
+ if (num_left < (uint)i)
+ stop_decoding(JPGD_BAD_DQT_LENGTH);
-// Used to skip unrecognized markers.
-void jpeg_decoder::skip_variable_marker()
-{
- uint num_left;
+ num_left -= i;
+ }
+ }
- num_left = get_bits(16);
+ // Read the start of frame (SOF) marker.
+ void jpeg_decoder::read_sof_marker()
+ {
+ int i;
+ uint num_left;
- if (num_left < 2)
- stop_decoding(JPGD_BAD_VARIABLE_MARKER);
+ num_left = get_bits(16);
- num_left -= 2;
+ /* precision: sorry, only 8-bit precision is supported */
+ if (get_bits(8) != 8)
+ stop_decoding(JPGD_BAD_PRECISION);
- while (num_left)
- {
- get_bits(8);
- num_left--;
- }
-}
+ m_image_y_size = get_bits(16);
-// Read a define restart interval (DRI) marker.
-void jpeg_decoder::read_dri_marker()
-{
- if (get_bits(16) != 4)
- stop_decoding(JPGD_BAD_DRI_LENGTH);
+ if ((m_image_y_size < 1) || (m_image_y_size > JPGD_MAX_HEIGHT))
+ stop_decoding(JPGD_BAD_HEIGHT);
- m_restart_interval = get_bits(16);
-}
+ m_image_x_size = get_bits(16);
-// Read a start of scan (SOS) marker.
-void jpeg_decoder::read_sos_marker()
-{
- uint num_left;
- int i, ci, n, c, cc;
+ if ((m_image_x_size < 1) || (m_image_x_size > JPGD_MAX_WIDTH))
+ stop_decoding(JPGD_BAD_WIDTH);
- num_left = get_bits(16);
+ m_comps_in_frame = get_bits(8);
- n = get_bits(8);
-
- m_comps_in_scan = n;
-
- num_left -= 3;
-
- if ( (num_left != (uint)(n * 2 + 3)) || (n < 1) || (n > JPGD_MAX_COMPS_IN_SCAN) )
- stop_decoding(JPGD_BAD_SOS_LENGTH);
-
- for (i = 0; i < n; i++)
- {
- cc = get_bits(8);
- c = get_bits(8);
- num_left -= 2;
-
- for (ci = 0; ci < m_comps_in_frame; ci++)
- if (cc == m_comp_ident[ci])
- break;
-
- if (ci >= m_comps_in_frame)
- stop_decoding(JPGD_BAD_SOS_COMP_ID);
-
- m_comp_list[i] = ci;
- m_comp_dc_tab[ci] = (c >> 4) & 15;
- m_comp_ac_tab[ci] = (c & 15) + (JPGD_MAX_HUFF_TABLES >> 1);
- }
-
- m_spectral_start = get_bits(8);
- m_spectral_end = get_bits(8);
- m_successive_high = get_bits(4);
- m_successive_low = get_bits(4);
-
- if (!m_progressive_flag)
- {
- m_spectral_start = 0;
- m_spectral_end = 63;
- }
-
- num_left -= 3;
-
- while (num_left) /* read past whatever is num_left */
- {
- get_bits(8);
- num_left--;
- }
-}
-
-// Finds the next marker.
-int jpeg_decoder::next_marker()
-{
- uint c, bytes;
-
- bytes = 0;
-
- do
- {
- do
- {
- bytes++;
- c = get_bits(8);
- } while (c != 0xFF);
-
- do
- {
- c = get_bits(8);
- } while (c == 0xFF);
-
- } while (c == 0);
-
- // If bytes > 0 here, there where extra bytes before the marker (not good).
-
- return c;
-}
-
-// Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is
-// encountered.
-int jpeg_decoder::process_markers()
-{
- int c;
-
- for ( ; ; )
- {
- c = next_marker();
-
- switch (c)
- {
- case M_SOF0:
- case M_SOF1:
- case M_SOF2:
- case M_SOF3:
- case M_SOF5:
- case M_SOF6:
- case M_SOF7:
-// case M_JPG:
- case M_SOF9:
- case M_SOF10:
- case M_SOF11:
- case M_SOF13:
- case M_SOF14:
- case M_SOF15:
- case M_SOI:
- case M_EOI:
- case M_SOS:
- {
- return c;
- }
- case M_DHT:
- {
- read_dht_marker();
- break;
- }
- // No arithmitic support - dumb patents!
- case M_DAC:
- {
- stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT);
- break;
- }
- case M_DQT:
- {
- read_dqt_marker();
- break;
- }
- case M_DRI:
- {
- read_dri_marker();
- break;
- }
- //case M_APP0: /* no need to read the JFIF marker */
-
- case M_JPG:
- case M_RST0: /* no parameters */
- case M_RST1:
- case M_RST2:
- case M_RST3:
- case M_RST4:
- case M_RST5:
- case M_RST6:
- case M_RST7:
- case M_TEM:
- {
- stop_decoding(JPGD_UNEXPECTED_MARKER);
- break;
- }
- default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
- {
- skip_variable_marker();
- break;
- }
- }
- }
-}
-
-// Finds the start of image (SOI) marker.
-// This code is rather defensive: it only checks the first 512 bytes to avoid
-// false positives.
-void jpeg_decoder::locate_soi_marker()
-{
- uint lastchar, thischar;
- uint bytesleft;
-
- lastchar = get_bits(8);
-
- thischar = get_bits(8);
-
- /* ok if it's a normal JPEG file without a special header */
-
- if ((lastchar == 0xFF) && (thischar == M_SOI))
- return;
-
- bytesleft = 4096; //512;
-
- for ( ; ; )
- {
- if (--bytesleft == 0)
- stop_decoding(JPGD_NOT_JPEG);
-
- lastchar = thischar;
-
- thischar = get_bits(8);
-
- if (lastchar == 0xFF)
- {
- if (thischar == M_SOI)
- break;
- else if (thischar == M_EOI) // get_bits will keep returning M_EOI if we read past the end
- stop_decoding(JPGD_NOT_JPEG);
- }
- }
-
- // Check the next character after marker: if it's not 0xFF, it can't be the start of the next marker, so the file is bad.
- thischar = (m_bit_buf >> 24) & 0xFF;
-
- if (thischar != 0xFF)
- stop_decoding(JPGD_NOT_JPEG);
-}
-
-// Find a start of frame (SOF) marker.
-void jpeg_decoder::locate_sof_marker()
-{
- locate_soi_marker();
-
- int c = process_markers();
-
- switch (c)
- {
- case M_SOF2:
- m_progressive_flag = JPGD_TRUE;
- case M_SOF0: /* baseline DCT */
- case M_SOF1: /* extended sequential DCT */
- {
- read_sof_marker();
- break;
- }
- case M_SOF9: /* Arithmitic coding */
- {
- stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT);
- break;
- }
- default:
- {
- stop_decoding(JPGD_UNSUPPORTED_MARKER);
- break;
- }
- }
-}
-
-// Find a start of scan (SOS) marker.
-int jpeg_decoder::locate_sos_marker()
-{
- int c;
-
- c = process_markers();
-
- if (c == M_EOI)
- return JPGD_FALSE;
- else if (c != M_SOS)
- stop_decoding(JPGD_UNEXPECTED_MARKER);
-
- read_sos_marker();
-
- return JPGD_TRUE;
-}
-
-// Reset everything to default/uninitialized state.
-void jpeg_decoder::init(jpeg_decoder_stream *pStream)
-{
- m_pMem_blocks = NULL;
- m_error_code = JPGD_SUCCESS;
- m_ready_flag = false;
- m_image_x_size = m_image_y_size = 0;
- m_pStream = pStream;
- m_progressive_flag = JPGD_FALSE;
-
- memset(m_huff_ac, 0, sizeof(m_huff_ac));
- memset(m_huff_num, 0, sizeof(m_huff_num));
- memset(m_huff_val, 0, sizeof(m_huff_val));
- memset(m_quant, 0, sizeof(m_quant));
-
- m_scan_type = 0;
- m_comps_in_frame = 0;
-
- memset(m_comp_h_samp, 0, sizeof(m_comp_h_samp));
- memset(m_comp_v_samp, 0, sizeof(m_comp_v_samp));
- memset(m_comp_quant, 0, sizeof(m_comp_quant));
- memset(m_comp_ident, 0, sizeof(m_comp_ident));
- memset(m_comp_h_blocks, 0, sizeof(m_comp_h_blocks));
- memset(m_comp_v_blocks, 0, sizeof(m_comp_v_blocks));
-
- m_comps_in_scan = 0;
- memset(m_comp_list, 0, sizeof(m_comp_list));
- memset(m_comp_dc_tab, 0, sizeof(m_comp_dc_tab));
- memset(m_comp_ac_tab, 0, sizeof(m_comp_ac_tab));
-
- m_spectral_start = 0;
- m_spectral_end = 0;
- m_successive_low = 0;
- m_successive_high = 0;
- m_max_mcu_x_size = 0;
- m_max_mcu_y_size = 0;
- m_blocks_per_mcu = 0;
- m_max_blocks_per_row = 0;
- m_mcus_per_row = 0;
- m_mcus_per_col = 0;
- m_expanded_blocks_per_component = 0;
- m_expanded_blocks_per_mcu = 0;
- m_expanded_blocks_per_row = 0;
- m_freq_domain_chroma_upsample = false;
-
- memset(m_mcu_org, 0, sizeof(m_mcu_org));
-
- m_total_lines_left = 0;
- m_mcu_lines_left = 0;
- m_real_dest_bytes_per_scan_line = 0;
- m_dest_bytes_per_scan_line = 0;
- m_dest_bytes_per_pixel = 0;
-
- memset(m_pHuff_tabs, 0, sizeof(m_pHuff_tabs));
-
- memset(m_dc_coeffs, 0, sizeof(m_dc_coeffs));
- memset(m_ac_coeffs, 0, sizeof(m_ac_coeffs));
- memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
-
- m_eob_run = 0;
-
- memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
-
- m_pIn_buf_ofs = m_in_buf;
- m_in_buf_left = 0;
- m_eof_flag = false;
- m_tem_flag = 0;
-
- memset(m_in_buf_pad_start, 0, sizeof(m_in_buf_pad_start));
- memset(m_in_buf, 0, sizeof(m_in_buf));
- memset(m_in_buf_pad_end, 0, sizeof(m_in_buf_pad_end));
-
- m_restart_interval = 0;
- m_restarts_left = 0;
- m_next_restart_num = 0;
-
- m_max_mcus_per_row = 0;
- m_max_blocks_per_mcu = 0;
- m_max_mcus_per_col = 0;
-
- memset(m_last_dc_val, 0, sizeof(m_last_dc_val));
- m_pMCU_coefficients = NULL;
- m_pSample_buf = NULL;
-
- m_total_bytes_read = 0;
-
- m_pScan_line_0 = NULL;
- m_pScan_line_1 = NULL;
-
- // Ready the input buffer.
- prep_in_buffer();
-
- // Prime the bit buffer.
- m_bits_left = 16;
- m_bit_buf = 0;
-
- get_bits(16);
- get_bits(16);
-
- for (int i = 0; i < JPGD_MAX_BLOCKS_PER_MCU; i++)
- m_mcu_block_max_zag[i] = 64;
-}
+ if (m_comps_in_frame > JPGD_MAX_COMPONENTS)
+ stop_decoding(JPGD_TOO_MANY_COMPONENTS);
+
+ if (num_left != (uint)(m_comps_in_frame * 3 + 8))
+ stop_decoding(JPGD_BAD_SOF_LENGTH);
+
+ for (i = 0; i < m_comps_in_frame; i++)
+ {
+ m_comp_ident[i] = get_bits(8);
+ m_comp_h_samp[i] = get_bits(4);
+ m_comp_v_samp[i] = get_bits(4);
+
+ if (!m_comp_h_samp[i] || !m_comp_v_samp[i] || (m_comp_h_samp[i] > 2) || (m_comp_v_samp[i] > 2))
+ stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
+
+ m_comp_quant[i] = get_bits(8);
+ if (m_comp_quant[i] >= JPGD_MAX_QUANT_TABLES)
+ stop_decoding(JPGD_DECODE_ERROR);
+ }
+ }
+
+ // Used to skip unrecognized markers.
+ void jpeg_decoder::skip_variable_marker()
+ {
+ uint num_left;
+
+ num_left = get_bits(16);
+
+ if (num_left < 2)
+ stop_decoding(JPGD_BAD_VARIABLE_MARKER);
+
+ num_left -= 2;
+
+ while (num_left)
+ {
+ get_bits(8);
+ num_left--;
+ }
+ }
+
+ // Read a define restart interval (DRI) marker.
+ void jpeg_decoder::read_dri_marker()
+ {
+ if (get_bits(16) != 4)
+ stop_decoding(JPGD_BAD_DRI_LENGTH);
+
+ m_restart_interval = get_bits(16);
+ }
+
+ // Read a start of scan (SOS) marker.
+ void jpeg_decoder::read_sos_marker()
+ {
+ uint num_left;
+ int i, ci, n, c, cc;
+
+ num_left = get_bits(16);
+
+ n = get_bits(8);
+
+ m_comps_in_scan = n;
+
+ num_left -= 3;
+
+ if ((num_left != (uint)(n * 2 + 3)) || (n < 1) || (n > JPGD_MAX_COMPS_IN_SCAN))
+ stop_decoding(JPGD_BAD_SOS_LENGTH);
+
+ for (i = 0; i < n; i++)
+ {
+ cc = get_bits(8);
+ c = get_bits(8);
+ num_left -= 2;
+
+ for (ci = 0; ci < m_comps_in_frame; ci++)
+ if (cc == m_comp_ident[ci])
+ break;
+
+ if (ci >= m_comps_in_frame)
+ stop_decoding(JPGD_BAD_SOS_COMP_ID);
+
+ if (ci >= JPGD_MAX_COMPONENTS)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ m_comp_list[i] = ci;
+
+ m_comp_dc_tab[ci] = (c >> 4) & 15;
+ m_comp_ac_tab[ci] = (c & 15) + (JPGD_MAX_HUFF_TABLES >> 1);
+
+ if (m_comp_dc_tab[ci] >= JPGD_MAX_HUFF_TABLES)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ if (m_comp_ac_tab[ci] >= JPGD_MAX_HUFF_TABLES)
+ stop_decoding(JPGD_DECODE_ERROR);
+ }
+
+ m_spectral_start = get_bits(8);
+ m_spectral_end = get_bits(8);
+ m_successive_high = get_bits(4);
+ m_successive_low = get_bits(4);
+
+ if (!m_progressive_flag)
+ {
+ m_spectral_start = 0;
+ m_spectral_end = 63;
+ }
+
+ num_left -= 3;
+
+ /* read past whatever is num_left */
+ while (num_left)
+ {
+ get_bits(8);
+ num_left--;
+ }
+ }
+
+ // Finds the next marker.
+ int jpeg_decoder::next_marker()
+ {
+ uint c, bytes;
+
+ bytes = 0;
+
+ do
+ {
+ do
+ {
+ bytes++;
+ c = get_bits(8);
+ } while (c != 0xFF);
+
+ do
+ {
+ c = get_bits(8);
+ } while (c == 0xFF);
+
+ } while (c == 0);
+
+ // If bytes > 0 here, there where extra bytes before the marker (not good).
+
+ return c;
+ }
+
+ // Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is
+ // encountered.
+ int jpeg_decoder::process_markers()
+ {
+ int c;
+
+ for (; ; )
+ {
+ c = next_marker();
+
+ switch (c)
+ {
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ // case M_JPG:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ case M_SOI:
+ case M_EOI:
+ case M_SOS:
+ {
+ return c;
+ }
+ case M_DHT:
+ {
+ read_dht_marker();
+ break;
+ }
+ // No arithmitic support - dumb patents!
+ case M_DAC:
+ {
+ stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT);
+ break;
+ }
+ case M_DQT:
+ {
+ read_dqt_marker();
+ break;
+ }
+ case M_DRI:
+ {
+ read_dri_marker();
+ break;
+ }
+ //case M_APP0: /* no need to read the JFIF marker */
+ case M_JPG:
+ case M_RST0: /* no parameters */
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ case M_TEM:
+ {
+ stop_decoding(JPGD_UNEXPECTED_MARKER);
+ break;
+ }
+ default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
+ {
+ skip_variable_marker();
+ break;
+ }
+ }
+ }
+ }
+
+ // Finds the start of image (SOI) marker.
+ void jpeg_decoder::locate_soi_marker()
+ {
+ uint lastchar, thischar;
+ uint bytesleft;
+
+ lastchar = get_bits(8);
+
+ thischar = get_bits(8);
+
+ /* ok if it's a normal JPEG file without a special header */
+
+ if ((lastchar == 0xFF) && (thischar == M_SOI))
+ return;
+
+ bytesleft = 4096;
+
+ for (; ; )
+ {
+ if (--bytesleft == 0)
+ stop_decoding(JPGD_NOT_JPEG);
+
+ lastchar = thischar;
+
+ thischar = get_bits(8);
+
+ if (lastchar == 0xFF)
+ {
+ if (thischar == M_SOI)
+ break;
+ else if (thischar == M_EOI) // get_bits will keep returning M_EOI if we read past the end
+ stop_decoding(JPGD_NOT_JPEG);
+ }
+ }
+
+ // Check the next character after marker: if it's not 0xFF, it can't be the start of the next marker, so the file is bad.
+ thischar = (m_bit_buf >> 24) & 0xFF;
+
+ if (thischar != 0xFF)
+ stop_decoding(JPGD_NOT_JPEG);
+ }
+
+ // Find a start of frame (SOF) marker.
+ void jpeg_decoder::locate_sof_marker()
+ {
+ locate_soi_marker();
+
+ int c = process_markers();
+
+ switch (c)
+ {
+ case M_SOF2:
+ {
+ m_progressive_flag = JPGD_TRUE;
+ read_sof_marker();
+ break;
+ }
+ case M_SOF0: /* baseline DCT */
+ case M_SOF1: /* extended sequential DCT */
+ {
+ read_sof_marker();
+ break;
+ }
+ case M_SOF9: /* Arithmitic coding */
+ {
+ stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT);
+ break;
+ }
+ default:
+ {
+ stop_decoding(JPGD_UNSUPPORTED_MARKER);
+ break;
+ }
+ }
+ }
+
+ // Find a start of scan (SOS) marker.
+ int jpeg_decoder::locate_sos_marker()
+ {
+ int c;
+
+ c = process_markers();
+
+ if (c == M_EOI)
+ return JPGD_FALSE;
+ else if (c != M_SOS)
+ stop_decoding(JPGD_UNEXPECTED_MARKER);
+
+ read_sos_marker();
+
+ return JPGD_TRUE;
+ }
+
+ // Reset everything to default/uninitialized state.
+ void jpeg_decoder::init(jpeg_decoder_stream* pStream, uint32_t flags)
+ {
+ m_flags = flags;
+ m_pMem_blocks = nullptr;
+ m_error_code = JPGD_SUCCESS;
+ m_ready_flag = false;
+ m_image_x_size = m_image_y_size = 0;
+ m_pStream = pStream;
+ m_progressive_flag = JPGD_FALSE;
+
+ memset(m_huff_ac, 0, sizeof(m_huff_ac));
+ memset(m_huff_num, 0, sizeof(m_huff_num));
+ memset(m_huff_val, 0, sizeof(m_huff_val));
+ memset(m_quant, 0, sizeof(m_quant));
+
+ m_scan_type = 0;
+ m_comps_in_frame = 0;
+
+ memset(m_comp_h_samp, 0, sizeof(m_comp_h_samp));
+ memset(m_comp_v_samp, 0, sizeof(m_comp_v_samp));
+ memset(m_comp_quant, 0, sizeof(m_comp_quant));
+ memset(m_comp_ident, 0, sizeof(m_comp_ident));
+ memset(m_comp_h_blocks, 0, sizeof(m_comp_h_blocks));
+ memset(m_comp_v_blocks, 0, sizeof(m_comp_v_blocks));
+
+ m_comps_in_scan = 0;
+ memset(m_comp_list, 0, sizeof(m_comp_list));
+ memset(m_comp_dc_tab, 0, sizeof(m_comp_dc_tab));
+ memset(m_comp_ac_tab, 0, sizeof(m_comp_ac_tab));
+
+ m_spectral_start = 0;
+ m_spectral_end = 0;
+ m_successive_low = 0;
+ m_successive_high = 0;
+ m_max_mcu_x_size = 0;
+ m_max_mcu_y_size = 0;
+ m_blocks_per_mcu = 0;
+ m_max_blocks_per_row = 0;
+ m_mcus_per_row = 0;
+ m_mcus_per_col = 0;
+
+ memset(m_mcu_org, 0, sizeof(m_mcu_org));
+
+ m_total_lines_left = 0;
+ m_mcu_lines_left = 0;
+ m_num_buffered_scanlines = 0;
+ m_real_dest_bytes_per_scan_line = 0;
+ m_dest_bytes_per_scan_line = 0;
+ m_dest_bytes_per_pixel = 0;
+
+ memset(m_pHuff_tabs, 0, sizeof(m_pHuff_tabs));
+
+ memset(m_dc_coeffs, 0, sizeof(m_dc_coeffs));
+ memset(m_ac_coeffs, 0, sizeof(m_ac_coeffs));
+ memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
+
+ m_eob_run = 0;
+
+ m_pIn_buf_ofs = m_in_buf;
+ m_in_buf_left = 0;
+ m_eof_flag = false;
+ m_tem_flag = 0;
+
+ memset(m_in_buf_pad_start, 0, sizeof(m_in_buf_pad_start));
+ memset(m_in_buf, 0, sizeof(m_in_buf));
+ memset(m_in_buf_pad_end, 0, sizeof(m_in_buf_pad_end));
+
+ m_restart_interval = 0;
+ m_restarts_left = 0;
+ m_next_restart_num = 0;
+
+ m_max_mcus_per_row = 0;
+ m_max_blocks_per_mcu = 0;
+ m_max_mcus_per_col = 0;
+
+ memset(m_last_dc_val, 0, sizeof(m_last_dc_val));
+ m_pMCU_coefficients = nullptr;
+ m_pSample_buf = nullptr;
+ m_pSample_buf_prev = nullptr;
+ m_sample_buf_prev_valid = false;
+
+ m_total_bytes_read = 0;
+
+ m_pScan_line_0 = nullptr;
+ m_pScan_line_1 = nullptr;
+
+ // Ready the input buffer.
+ prep_in_buffer();
+
+ // Prime the bit buffer.
+ m_bits_left = 16;
+ m_bit_buf = 0;
+
+ get_bits(16);
+ get_bits(16);
+
+ for (int i = 0; i < JPGD_MAX_BLOCKS_PER_MCU; i++)
+ m_mcu_block_max_zag[i] = 64;
+
+ m_has_sse2 = false;
+
+#if JPGD_USE_SSE2
+#ifdef _MSC_VER
+ int cpu_info[4];
+ __cpuid(cpu_info, 1);
+ const int cpu_info3 = cpu_info[3];
+ m_has_sse2 = ((cpu_info3 >> 26U) & 1U) != 0U;
+#else
+ m_has_sse2 = true;
+#endif
+#endif
+ }
#define SCALEBITS 16
#define ONE_HALF ((int) 1 << (SCALEBITS-1))
#define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5f))
-// Create a few tables that allow us to quickly convert YCbCr to RGB.
-void jpeg_decoder::create_look_ups()
-{
- for (int i = 0; i <= 255; i++)
- {
- int k = i - 128;
- m_crr[i] = ( FIX(1.40200f) * k + ONE_HALF) >> SCALEBITS;
- m_cbb[i] = ( FIX(1.77200f) * k + ONE_HALF) >> SCALEBITS;
- m_crg[i] = (-FIX(0.71414f)) * k;
- m_cbg[i] = (-FIX(0.34414f)) * k + ONE_HALF;
- }
-}
-
-// This method throws back into the stream any bytes that where read
-// into the bit buffer during initial marker scanning.
-void jpeg_decoder::fix_in_buffer()
-{
- // In case any 0xFF's where pulled into the buffer during marker scanning.
- JPGD_ASSERT((m_bits_left & 7) == 0);
-
- if (m_bits_left == 16)
- stuff_char( (uint8)(m_bit_buf & 0xFF));
-
- if (m_bits_left >= 8)
- stuff_char( (uint8)((m_bit_buf >> 8) & 0xFF));
-
- stuff_char((uint8)((m_bit_buf >> 16) & 0xFF));
- stuff_char((uint8)((m_bit_buf >> 24) & 0xFF));
-
- m_bits_left = 16;
- get_bits_no_markers(16);
- get_bits_no_markers(16);
-}
-
-void jpeg_decoder::transform_mcu(int mcu_row)
-{
- jpgd_block_t* pSrc_ptr = m_pMCU_coefficients;
- if (m_freq_domain_chroma_upsample) {
- JPGD_ASSERT(mcu_row * m_blocks_per_mcu < m_expanded_blocks_per_row);
- }
- else {
- JPGD_ASSERT(mcu_row * m_blocks_per_mcu < m_max_blocks_per_row);
- }
- uint8* pDst_ptr = m_pSample_buf + mcu_row * m_blocks_per_mcu * 64;
-
- for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
- {
- idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]);
- pSrc_ptr += 64;
- pDst_ptr += 64;
- }
-}
-
-static const uint8 s_max_rc[64] =
-{
- 17, 18, 34, 50, 50, 51, 52, 52, 52, 68, 84, 84, 84, 84, 85, 86, 86, 86, 86, 86,
- 102, 118, 118, 118, 118, 118, 118, 119, 120, 120, 120, 120, 120, 120, 120, 136,
- 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
- 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136
-};
-
-void jpeg_decoder::transform_mcu_expand(int mcu_row)
-{
- jpgd_block_t* pSrc_ptr = m_pMCU_coefficients;
- uint8* pDst_ptr = m_pSample_buf + mcu_row * m_expanded_blocks_per_mcu * 64;
-
- // Y IDCT
- int mcu_block;
- for (mcu_block = 0; mcu_block < m_expanded_blocks_per_component; mcu_block++)
- {
- idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]);
- pSrc_ptr += 64;
- pDst_ptr += 64;
- }
-
- // Chroma IDCT, with upsampling
- jpgd_block_t temp_block[64];
-
- for (int i = 0; i < 2; i++)
- {
- DCT_Upsample::Matrix44 P, Q, R, S;
-
- JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] >= 1);
- JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] <= 64);
-
- int max_zag = m_mcu_block_max_zag[mcu_block++] - 1;
- if (max_zag <= 0) max_zag = 0; // should never happen, only here to shut up static analysis
- switch (s_max_rc[max_zag])
- {
- case 1*16+1:
- DCT_Upsample::P_Q<1, 1>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<1, 1>::calc(R, S, pSrc_ptr);
- break;
- case 1*16+2:
- DCT_Upsample::P_Q<1, 2>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<1, 2>::calc(R, S, pSrc_ptr);
- break;
- case 2*16+2:
- DCT_Upsample::P_Q<2, 2>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<2, 2>::calc(R, S, pSrc_ptr);
- break;
- case 3*16+2:
- DCT_Upsample::P_Q<3, 2>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<3, 2>::calc(R, S, pSrc_ptr);
- break;
- case 3*16+3:
- DCT_Upsample::P_Q<3, 3>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<3, 3>::calc(R, S, pSrc_ptr);
- break;
- case 3*16+4:
- DCT_Upsample::P_Q<3, 4>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<3, 4>::calc(R, S, pSrc_ptr);
- break;
- case 4*16+4:
- DCT_Upsample::P_Q<4, 4>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<4, 4>::calc(R, S, pSrc_ptr);
- break;
- case 5*16+4:
- DCT_Upsample::P_Q<5, 4>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<5, 4>::calc(R, S, pSrc_ptr);
- break;
- case 5*16+5:
- DCT_Upsample::P_Q<5, 5>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<5, 5>::calc(R, S, pSrc_ptr);
- break;
- case 5*16+6:
- DCT_Upsample::P_Q<5, 6>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<5, 6>::calc(R, S, pSrc_ptr);
- break;
- case 6*16+6:
- DCT_Upsample::P_Q<6, 6>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<6, 6>::calc(R, S, pSrc_ptr);
- break;
- case 7*16+6:
- DCT_Upsample::P_Q<7, 6>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<7, 6>::calc(R, S, pSrc_ptr);
- break;
- case 7*16+7:
- DCT_Upsample::P_Q<7, 7>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<7, 7>::calc(R, S, pSrc_ptr);
- break;
- case 7*16+8:
- DCT_Upsample::P_Q<7, 8>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<7, 8>::calc(R, S, pSrc_ptr);
- break;
- case 8*16+8:
- DCT_Upsample::P_Q<8, 8>::calc(P, Q, pSrc_ptr);
- DCT_Upsample::R_S<8, 8>::calc(R, S, pSrc_ptr);
- break;
- default:
- JPGD_ASSERT(false);
- }
-
- DCT_Upsample::Matrix44 a(P + Q); P -= Q;
- DCT_Upsample::Matrix44& b = P;
- DCT_Upsample::Matrix44 c(R + S); R -= S;
- DCT_Upsample::Matrix44& d = R;
-
- DCT_Upsample::Matrix44::add_and_store(temp_block, a, c);
- idct_4x4(temp_block, pDst_ptr);
- pDst_ptr += 64;
-
- DCT_Upsample::Matrix44::sub_and_store(temp_block, a, c);
- idct_4x4(temp_block, pDst_ptr);
- pDst_ptr += 64;
-
- DCT_Upsample::Matrix44::add_and_store(temp_block, b, d);
- idct_4x4(temp_block, pDst_ptr);
- pDst_ptr += 64;
-
- DCT_Upsample::Matrix44::sub_and_store(temp_block, b, d);
- idct_4x4(temp_block, pDst_ptr);
- pDst_ptr += 64;
-
- pSrc_ptr += 64;
- }
-}
-
-// Loads and dequantizes the next row of (already decoded) coefficients.
-// Progressive images only.
-void jpeg_decoder::load_next_row()
-{
- int i;
- jpgd_block_t *p;
- jpgd_quant_t *q;
- int mcu_row, mcu_block, row_block = 0;
- int component_num, component_id;
- int block_x_mcu[JPGD_MAX_COMPONENTS];
-
- memset(block_x_mcu, 0, JPGD_MAX_COMPONENTS * sizeof(int));
-
- for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
- {
- int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0;
-
- for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
- {
- component_id = m_mcu_org[mcu_block];
- JPGD_ASSERT(m_comp_quant[component_id] < JPGD_MAX_QUANT_TABLES);
- q = m_quant[m_comp_quant[component_id]];
-
- p = m_pMCU_coefficients + 64 * mcu_block;
-
- jpgd_block_t* pAC = coeff_buf_getp(m_ac_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
- jpgd_block_t* pDC = coeff_buf_getp(m_dc_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
- p[0] = pDC[0];
- memcpy(&p[1], &pAC[1], 63 * sizeof(jpgd_block_t));
-
- for (i = 63; i > 0; i--)
- if (p[g_ZAG[i]])
- break;
-
- m_mcu_block_max_zag[mcu_block] = i + 1;
-
- for ( ; i >= 0; i--)
- if (p[g_ZAG[i]])
- p[g_ZAG[i]] = static_cast<jpgd_block_t>(p[g_ZAG[i]] * q[i]);
-
- row_block++;
-
- if (m_comps_in_scan == 1)
- block_x_mcu[component_id]++;
- else
- {
- if (++block_x_mcu_ofs == m_comp_h_samp[component_id])
- {
- block_x_mcu_ofs = 0;
-
- if (++block_y_mcu_ofs == m_comp_v_samp[component_id])
- {
- block_y_mcu_ofs = 0;
-
- block_x_mcu[component_id] += m_comp_h_samp[component_id];
- }
- }
- }
- }
-
- if (m_freq_domain_chroma_upsample)
- transform_mcu_expand(mcu_row);
- else
- transform_mcu(mcu_row);
- }
-
- if (m_comps_in_scan == 1)
- m_block_y_mcu[m_comp_list[0]]++;
- else
- {
- for (component_num = 0; component_num < m_comps_in_scan; component_num++)
- {
- component_id = m_comp_list[component_num];
-
- m_block_y_mcu[component_id] += m_comp_v_samp[component_id];
- }
- }
-}
-
-// Restart interval processing.
-void jpeg_decoder::process_restart()
-{
- int i;
- int c = 0;
-
- // Align to a byte boundry
- // FIXME: Is this really necessary? get_bits_no_markers() never reads in markers!
- //get_bits_no_markers(m_bits_left & 7);
-
- // Let's scan a little bit to find the marker, but not _too_ far.
- // 1536 is a "fudge factor" that determines how much to scan.
- for (i = 1536; i > 0; i--)
- if (get_char() == 0xFF)
- break;
-
- if (i == 0)
- stop_decoding(JPGD_BAD_RESTART_MARKER);
-
- for ( ; i > 0; i--)
- if ((c = get_char()) != 0xFF)
- break;
-
- if (i == 0)
- stop_decoding(JPGD_BAD_RESTART_MARKER);
-
- // Is it the expected marker? If not, something bad happened.
- if (c != (m_next_restart_num + M_RST0))
- stop_decoding(JPGD_BAD_RESTART_MARKER);
-
- // Reset each component's DC prediction values.
- memset(&m_last_dc_val, 0, m_comps_in_frame * sizeof(uint));
-
- m_eob_run = 0;
-
- m_restarts_left = m_restart_interval;
-
- m_next_restart_num = (m_next_restart_num + 1) & 7;
-
- // Get the bit buffer going again...
-
- m_bits_left = 16;
- get_bits_no_markers(16);
- get_bits_no_markers(16);
-}
-
-static inline int dequantize_ac(int c, int q) { c *= q; return c; }
-
-// Decodes and dequantizes the next row of coefficients.
-void jpeg_decoder::decode_next_row()
-{
- int row_block = 0;
-
- for (int mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
- {
- if ((m_restart_interval) && (m_restarts_left == 0))
- process_restart();
-
- jpgd_block_t* p = m_pMCU_coefficients;
- for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++, p += 64)
- {
- int component_id = m_mcu_org[mcu_block];
- JPGD_ASSERT(m_comp_quant[component_id] < JPGD_MAX_QUANT_TABLES);
- jpgd_quant_t* q = m_quant[m_comp_quant[component_id]];
-
- int r, s;
- s = huff_decode(m_pHuff_tabs[m_comp_dc_tab[component_id]], r);
- s = JPGD_HUFF_EXTEND(r, s);
-
- m_last_dc_val[component_id] = (s += m_last_dc_val[component_id]);
-
- p[0] = static_cast<jpgd_block_t>(s * q[0]);
-
- int prev_num_set = m_mcu_block_max_zag[mcu_block];
-
- huff_tables *pH = m_pHuff_tabs[m_comp_ac_tab[component_id]];
-
- int k;
- for (k = 1; k < 64; k++)
- {
- int extra_bits;
- s = huff_decode(pH, extra_bits);
-
- r = s >> 4;
- s &= 15;
-
- if (s)
- {
- if (r)
- {
- if ((k + r) > 63)
- stop_decoding(JPGD_DECODE_ERROR);
-
- if (k < prev_num_set)
- {
- int n = JPGD_MIN(r, prev_num_set - k);
- int kt = k;
- while (n--)
- p[g_ZAG[kt++]] = 0;
- }
-
- k += r;
- }
-
- s = JPGD_HUFF_EXTEND(extra_bits, s);
-
- JPGD_ASSERT(k < 64);
-
- p[g_ZAG[k]] = static_cast<jpgd_block_t>(dequantize_ac(s, q[k])); //s * q[k];
- }
- else
- {
- if (r == 15)
- {
- if ((k + 16) > 64)
- stop_decoding(JPGD_DECODE_ERROR);
-
- if (k < prev_num_set)
- {
- int n = JPGD_MIN(16, prev_num_set - k);
- int kt = k;
- while (n--)
- {
- JPGD_ASSERT(kt <= 63);
- p[g_ZAG[kt++]] = 0;
- }
- }
-
- k += 16 - 1; // - 1 because the loop counter is k
- JPGD_ASSERT(p[g_ZAG[k]] == 0);
- }
- else
- break;
- }
- }
-
- if (k < prev_num_set)
- {
- int kt = k;
- while (kt < prev_num_set)
- p[g_ZAG[kt++]] = 0;
- }
-
- m_mcu_block_max_zag[mcu_block] = k;
-
- row_block++;
- }
-
- if (m_freq_domain_chroma_upsample)
- transform_mcu_expand(mcu_row);
- else
- transform_mcu(mcu_row);
-
- m_restarts_left--;
- }
-}
-
-// YCbCr H1V1 (1x1:1:1, 3 m_blocks per MCU) to RGB
-void jpeg_decoder::H1V1Convert()
-{
- int row = m_max_mcu_y_size - m_mcu_lines_left;
- uint8 *d = m_pScan_line_0;
- uint8 *s = m_pSample_buf + row * 8;
-
- for (int i = m_max_mcus_per_row; i > 0; i--)
- {
- for (int j = 0; j < 8; j++)
- {
- int y = s[j];
- int cb = s[64+j];
- int cr = s[128+j];
-
- d[0] = clamp(y + m_crr[cr]);
- d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
- d[2] = clamp(y + m_cbb[cb]);
- d[3] = 255;
-
- d += 4;
- }
-
- s += 64*3;
- }
-}
-
-// YCbCr H2V1 (2x1:1:1, 4 m_blocks per MCU) to RGB
-void jpeg_decoder::H2V1Convert()
-{
- int row = m_max_mcu_y_size - m_mcu_lines_left;
- uint8 *d0 = m_pScan_line_0;
- uint8 *y = m_pSample_buf + row * 8;
- uint8 *c = m_pSample_buf + 2*64 + row * 8;
-
- for (int i = m_max_mcus_per_row; i > 0; i--)
- {
- for (int l = 0; l < 2; l++)
- {
- for (int j = 0; j < 4; j++)
- {
- int cb = c[0];
- int cr = c[64];
-
- int rc = m_crr[cr];
- int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
- int bc = m_cbb[cb];
-
- int yy = y[j<<1];
- d0[0] = clamp(yy+rc);
- d0[1] = clamp(yy+gc);
- d0[2] = clamp(yy+bc);
- d0[3] = 255;
-
- yy = y[(j<<1)+1];
- d0[4] = clamp(yy+rc);
- d0[5] = clamp(yy+gc);
- d0[6] = clamp(yy+bc);
- d0[7] = 255;
-
- d0 += 8;
-
- c++;
- }
- y += 64;
- }
-
- y += 64*4 - 64*2;
- c += 64*4 - 8;
- }
-}
-
-// YCbCr H2V1 (1x2:1:1, 4 m_blocks per MCU) to RGB
-void jpeg_decoder::H1V2Convert()
-{
- int row = m_max_mcu_y_size - m_mcu_lines_left;
- uint8 *d0 = m_pScan_line_0;
- uint8 *d1 = m_pScan_line_1;
- uint8 *y;
- uint8 *c;
-
- if (row < 8)
- y = m_pSample_buf + row * 8;
- else
- y = m_pSample_buf + 64*1 + (row & 7) * 8;
-
- c = m_pSample_buf + 64*2 + (row >> 1) * 8;
-
- for (int i = m_max_mcus_per_row; i > 0; i--)
- {
- for (int j = 0; j < 8; j++)
- {
- int cb = c[0+j];
- int cr = c[64+j];
-
- int rc = m_crr[cr];
- int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
- int bc = m_cbb[cb];
-
- int yy = y[j];
- d0[0] = clamp(yy+rc);
- d0[1] = clamp(yy+gc);
- d0[2] = clamp(yy+bc);
- d0[3] = 255;
-
- yy = y[8+j];
- d1[0] = clamp(yy+rc);
- d1[1] = clamp(yy+gc);
- d1[2] = clamp(yy+bc);
- d1[3] = 255;
-
- d0 += 4;
- d1 += 4;
- }
-
- y += 64*4;
- c += 64*4;
- }
-}
-
-// YCbCr H2V2 (2x2:1:1, 6 m_blocks per MCU) to RGB
-void jpeg_decoder::H2V2Convert()
-{
- int row = m_max_mcu_y_size - m_mcu_lines_left;
- uint8 *d0 = m_pScan_line_0;
- uint8 *d1 = m_pScan_line_1;
- uint8 *y;
- uint8 *c;
-
- if (row < 8)
- y = m_pSample_buf + row * 8;
- else
- y = m_pSample_buf + 64*2 + (row & 7) * 8;
-
- c = m_pSample_buf + 64*4 + (row >> 1) * 8;
-
- for (int i = m_max_mcus_per_row; i > 0; i--)
- {
- for (int l = 0; l < 2; l++)
- {
- for (int j = 0; j < 8; j += 2)
- {
- int cb = c[0];
- int cr = c[64];
+ // Create a few tables that allow us to quickly convert YCbCr to RGB.
+ void jpeg_decoder::create_look_ups()
+ {
+ for (int i = 0; i <= 255; i++)
+ {
+ int k = i - 128;
+ m_crr[i] = (FIX(1.40200f) * k + ONE_HALF) >> SCALEBITS;
+ m_cbb[i] = (FIX(1.77200f) * k + ONE_HALF) >> SCALEBITS;
+ m_crg[i] = (-FIX(0.71414f)) * k;
+ m_cbg[i] = (-FIX(0.34414f)) * k + ONE_HALF;
+ }
+ }
+
+ // This method throws back into the stream any bytes that where read
+ // into the bit buffer during initial marker scanning.
+ void jpeg_decoder::fix_in_buffer()
+ {
+ // In case any 0xFF's where pulled into the buffer during marker scanning.
+ assert((m_bits_left & 7) == 0);
+
+ if (m_bits_left == 16)
+ stuff_char((uint8)(m_bit_buf & 0xFF));
+
+ if (m_bits_left >= 8)
+ stuff_char((uint8)((m_bit_buf >> 8) & 0xFF));
+
+ stuff_char((uint8)((m_bit_buf >> 16) & 0xFF));
+ stuff_char((uint8)((m_bit_buf >> 24) & 0xFF));
+
+ m_bits_left = 16;
+ get_bits_no_markers(16);
+ get_bits_no_markers(16);
+ }
+
+ void jpeg_decoder::transform_mcu(int mcu_row)
+ {
+ jpgd_block_coeff_t* pSrc_ptr = m_pMCU_coefficients;
+ if (mcu_row * m_blocks_per_mcu >= m_max_blocks_per_row)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ uint8* pDst_ptr = m_pSample_buf + mcu_row * m_blocks_per_mcu * 64;
+
+ for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
+ {
+ idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block], ((m_flags & cFlagDisableSIMD) == 0) && m_has_sse2);
+ pSrc_ptr += 64;
+ pDst_ptr += 64;
+ }
+ }
+
+ // Loads and dequantizes the next row of (already decoded) coefficients.
+ // Progressive images only.
+ void jpeg_decoder::load_next_row()
+ {
+ int i;
+ jpgd_block_coeff_t* p;
+ jpgd_quant_t* q;
+ int mcu_row, mcu_block, row_block = 0;
+ int component_num, component_id;
+ int block_x_mcu[JPGD_MAX_COMPONENTS];
+
+ memset(block_x_mcu, 0, JPGD_MAX_COMPONENTS * sizeof(int));
+
+ for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
+ {
+ int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0;
+
+ for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
+ {
+ component_id = m_mcu_org[mcu_block];
+ if (m_comp_quant[component_id] >= JPGD_MAX_QUANT_TABLES)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ q = m_quant[m_comp_quant[component_id]];
+
+ p = m_pMCU_coefficients + 64 * mcu_block;
+
+ jpgd_block_coeff_t* pAC = coeff_buf_getp(m_ac_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
+ jpgd_block_coeff_t* pDC = coeff_buf_getp(m_dc_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
+ p[0] = pDC[0];
+ memcpy(&p[1], &pAC[1], 63 * sizeof(jpgd_block_coeff_t));
+
+ for (i = 63; i > 0; i--)
+ if (p[g_ZAG[i]])
+ break;
+
+ m_mcu_block_max_zag[mcu_block] = i + 1;
+
+ for (; i >= 0; i--)
+ if (p[g_ZAG[i]])
+ p[g_ZAG[i]] = static_cast<jpgd_block_coeff_t>(p[g_ZAG[i]] * q[i]);
+
+ row_block++;
+
+ if (m_comps_in_scan == 1)
+ block_x_mcu[component_id]++;
+ else
+ {
+ if (++block_x_mcu_ofs == m_comp_h_samp[component_id])
+ {
+ block_x_mcu_ofs = 0;
+
+ if (++block_y_mcu_ofs == m_comp_v_samp[component_id])
+ {
+ block_y_mcu_ofs = 0;
+
+ block_x_mcu[component_id] += m_comp_h_samp[component_id];
+ }
+ }
+ }
+ }
+
+ transform_mcu(mcu_row);
+ }
+
+ if (m_comps_in_scan == 1)
+ m_block_y_mcu[m_comp_list[0]]++;
+ else
+ {
+ for (component_num = 0; component_num < m_comps_in_scan; component_num++)
+ {
+ component_id = m_comp_list[component_num];
+
+ m_block_y_mcu[component_id] += m_comp_v_samp[component_id];
+ }
+ }
+ }
+
+ // Restart interval processing.
+ void jpeg_decoder::process_restart()
+ {
+ int i;
+ int c = 0;
+
+ // Align to a byte boundry
+ // FIXME: Is this really necessary? get_bits_no_markers() never reads in markers!
+ //get_bits_no_markers(m_bits_left & 7);
+
+ // Let's scan a little bit to find the marker, but not _too_ far.
+ // 1536 is a "fudge factor" that determines how much to scan.
+ for (i = 1536; i > 0; i--)
+ if (get_char() == 0xFF)
+ break;
+
+ if (i == 0)
+ stop_decoding(JPGD_BAD_RESTART_MARKER);
+
+ for (; i > 0; i--)
+ if ((c = get_char()) != 0xFF)
+ break;
+
+ if (i == 0)
+ stop_decoding(JPGD_BAD_RESTART_MARKER);
+
+ // Is it the expected marker? If not, something bad happened.
+ if (c != (m_next_restart_num + M_RST0))
+ stop_decoding(JPGD_BAD_RESTART_MARKER);
+
+ // Reset each component's DC prediction values.
+ memset(&m_last_dc_val, 0, m_comps_in_frame * sizeof(uint));
+
+ m_eob_run = 0;
+
+ m_restarts_left = m_restart_interval;
+
+ m_next_restart_num = (m_next_restart_num + 1) & 7;
+
+ // Get the bit buffer going again...
+
+ m_bits_left = 16;
+ get_bits_no_markers(16);
+ get_bits_no_markers(16);
+ }
+
+ static inline int dequantize_ac(int c, int q) { c *= q; return c; }
+
+ // Decodes and dequantizes the next row of coefficients.
+ void jpeg_decoder::decode_next_row()
+ {
+ int row_block = 0;
+
+ for (int mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
+ {
+ if ((m_restart_interval) && (m_restarts_left == 0))
+ process_restart();
+
+ jpgd_block_coeff_t* p = m_pMCU_coefficients;
+ for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++, p += 64)
+ {
+ int component_id = m_mcu_org[mcu_block];
+ if (m_comp_quant[component_id] >= JPGD_MAX_QUANT_TABLES)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ jpgd_quant_t* q = m_quant[m_comp_quant[component_id]];
+
+ int r, s;
+ s = huff_decode(m_pHuff_tabs[m_comp_dc_tab[component_id]], r);
+ if (s >= 16)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ s = JPGD_HUFF_EXTEND(r, s);
+
+ m_last_dc_val[component_id] = (s += m_last_dc_val[component_id]);
+
+ p[0] = static_cast<jpgd_block_coeff_t>(s * q[0]);
+
+ int prev_num_set = m_mcu_block_max_zag[mcu_block];
+
+ huff_tables* pH = m_pHuff_tabs[m_comp_ac_tab[component_id]];
+
+ int k;
+ for (k = 1; k < 64; k++)
+ {
+ int extra_bits;
+ s = huff_decode(pH, extra_bits);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s)
+ {
+ if (r)
+ {
+ if ((k + r) > 63)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ if (k < prev_num_set)
+ {
+ int n = JPGD_MIN(r, prev_num_set - k);
+ int kt = k;
+ while (n--)
+ p[g_ZAG[kt++]] = 0;
+ }
+
+ k += r;
+ }
+
+ s = JPGD_HUFF_EXTEND(extra_bits, s);
+
+ if (k >= 64)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ p[g_ZAG[k]] = static_cast<jpgd_block_coeff_t>(dequantize_ac(s, q[k])); //s * q[k];
+ }
+ else
+ {
+ if (r == 15)
+ {
+ if ((k + 16) > 64)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ if (k < prev_num_set)
+ {
+ int n = JPGD_MIN(16, prev_num_set - k);
+ int kt = k;
+ while (n--)
+ {
+ if (kt > 63)
+ stop_decoding(JPGD_DECODE_ERROR);
+ p[g_ZAG[kt++]] = 0;
+ }
+ }
+
+ k += 16 - 1; // - 1 because the loop counter is k
+
+ if (p[g_ZAG[k & 63]] != 0)
+ stop_decoding(JPGD_DECODE_ERROR);
+ }
+ else
+ break;
+ }
+ }
+
+ if (k < prev_num_set)
+ {
+ int kt = k;
+ while (kt < prev_num_set)
+ p[g_ZAG[kt++]] = 0;
+ }
+
+ m_mcu_block_max_zag[mcu_block] = k;
+
+ row_block++;
+ }
+
+ transform_mcu(mcu_row);
+
+ m_restarts_left--;
+ }
+ }
+
+ // YCbCr H1V1 (1x1:1:1, 3 m_blocks per MCU) to RGB
+ void jpeg_decoder::H1V1Convert()
+ {
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8* d = m_pScan_line_0;
+ uint8* s = m_pSample_buf + row * 8;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ for (int j = 0; j < 8; j++)
+ {
+ int y = s[j];
+ int cb = s[64 + j];
+ int cr = s[128 + j];
+
+ d[0] = clamp(y + m_crr[cr]);
+ d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
+ d[2] = clamp(y + m_cbb[cb]);
+ d[3] = 255;
+
+ d += 4;
+ }
+
+ s += 64 * 3;
+ }
+ }
+
+ // YCbCr H2V1 (2x1:1:1, 4 m_blocks per MCU) to RGB
+ void jpeg_decoder::H2V1Convert()
+ {
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8* d0 = m_pScan_line_0;
+ uint8* y = m_pSample_buf + row * 8;
+ uint8* c = m_pSample_buf + 2 * 64 + row * 8;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ for (int l = 0; l < 2; l++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ int cb = c[0];
+ int cr = c[64];
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ int yy = y[j << 1];
+ d0[0] = clamp(yy + rc);
+ d0[1] = clamp(yy + gc);
+ d0[2] = clamp(yy + bc);
+ d0[3] = 255;
+
+ yy = y[(j << 1) + 1];
+ d0[4] = clamp(yy + rc);
+ d0[5] = clamp(yy + gc);
+ d0[6] = clamp(yy + bc);
+ d0[7] = 255;
+
+ d0 += 8;
+
+ c++;
+ }
+ y += 64;
+ }
+
+ y += 64 * 4 - 64 * 2;
+ c += 64 * 4 - 8;
+ }
+ }
+
+ // YCbCr H2V1 (2x1:1:1, 4 m_blocks per MCU) to RGB
+ void jpeg_decoder::H2V1ConvertFiltered()
+ {
+ const uint BLOCKS_PER_MCU = 4;
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8* d0 = m_pScan_line_0;
+
+ const int half_image_x_size = (m_image_x_size >> 1) - 1;
+ const int row_x8 = row * 8;
+
+ for (int x = 0; x < m_image_x_size; x++)
+ {
+ int y = m_pSample_buf[check_sample_buf_ofs((x >> 4) * BLOCKS_PER_MCU * 64 + ((x & 8) ? 64 : 0) + (x & 7) + row_x8)];
+
+ int c_x0 = (x - 1) >> 1;
+ int c_x1 = JPGD_MIN(c_x0 + 1, half_image_x_size);
+ c_x0 = JPGD_MAX(c_x0, 0);
+
+ int a = (c_x0 >> 3) * BLOCKS_PER_MCU * 64 + (c_x0 & 7) + row_x8 + 128;
+ int cb0 = m_pSample_buf[check_sample_buf_ofs(a)];
+ int cr0 = m_pSample_buf[check_sample_buf_ofs(a + 64)];
+
+ int b = (c_x1 >> 3) * BLOCKS_PER_MCU * 64 + (c_x1 & 7) + row_x8 + 128;
+ int cb1 = m_pSample_buf[check_sample_buf_ofs(b)];
+ int cr1 = m_pSample_buf[check_sample_buf_ofs(b + 64)];
+
+ int w0 = (x & 1) ? 3 : 1;
+ int w1 = (x & 1) ? 1 : 3;
+
+ int cb = (cb0 * w0 + cb1 * w1 + 2) >> 2;
+ int cr = (cr0 * w0 + cr1 * w1 + 2) >> 2;
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ d0[0] = clamp(y + rc);
+ d0[1] = clamp(y + gc);
+ d0[2] = clamp(y + bc);
+ d0[3] = 255;
+
+ d0 += 4;
+ }
+ }
+
+ // YCbCr H2V1 (1x2:1:1, 4 m_blocks per MCU) to RGB
+ void jpeg_decoder::H1V2Convert()
+ {
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8* d0 = m_pScan_line_0;
+ uint8* d1 = m_pScan_line_1;
+ uint8* y;
+ uint8* c;
+
+ if (row < 8)
+ y = m_pSample_buf + row * 8;
+ else
+ y = m_pSample_buf + 64 * 1 + (row & 7) * 8;
+
+ c = m_pSample_buf + 64 * 2 + (row >> 1) * 8;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ for (int j = 0; j < 8; j++)
+ {
+ int cb = c[0 + j];
+ int cr = c[64 + j];
int rc = m_crr[cr];
int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
int bc = m_cbb[cb];
int yy = y[j];
- d0[0] = clamp(yy+rc);
- d0[1] = clamp(yy+gc);
- d0[2] = clamp(yy+bc);
+ d0[0] = clamp(yy + rc);
+ d0[1] = clamp(yy + gc);
+ d0[2] = clamp(yy + bc);
d0[3] = 255;
- yy = y[j+1];
- d0[4] = clamp(yy+rc);
- d0[5] = clamp(yy+gc);
- d0[6] = clamp(yy+bc);
- d0[7] = 255;
-
- yy = y[j+8];
- d1[0] = clamp(yy+rc);
- d1[1] = clamp(yy+gc);
- d1[2] = clamp(yy+bc);
+ yy = y[8 + j];
+ d1[0] = clamp(yy + rc);
+ d1[1] = clamp(yy + gc);
+ d1[2] = clamp(yy + bc);
d1[3] = 255;
- yy = y[j+8+1];
- d1[4] = clamp(yy+rc);
- d1[5] = clamp(yy+gc);
- d1[6] = clamp(yy+bc);
- d1[7] = 255;
+ d0 += 4;
+ d1 += 4;
+ }
+
+ y += 64 * 4;
+ c += 64 * 4;
+ }
+ }
+
+ // YCbCr H2V1 (1x2:1:1, 4 m_blocks per MCU) to RGB
+ void jpeg_decoder::H1V2ConvertFiltered()
+ {
+ const uint BLOCKS_PER_MCU = 4;
+ int y = m_image_y_size - m_total_lines_left;
+ int row = y & 15;
+
+ const int half_image_y_size = (m_image_y_size >> 1) - 1;
+
+ uint8* d0 = m_pScan_line_0;
+
+ const int w0 = (row & 1) ? 3 : 1;
+ const int w1 = (row & 1) ? 1 : 3;
+
+ int c_y0 = (y - 1) >> 1;
+ int c_y1 = JPGD_MIN(c_y0 + 1, half_image_y_size);
+
+ const uint8_t* p_YSamples = m_pSample_buf;
+ const uint8_t* p_C0Samples = m_pSample_buf;
+ if ((c_y0 >= 0) && (((row & 15) == 0) || ((row & 15) == 15)) && (m_total_lines_left > 1))
+ {
+ assert(y > 0);
+ assert(m_sample_buf_prev_valid);
+
+ if ((row & 15) == 15)
+ p_YSamples = m_pSample_buf_prev;
+
+ p_C0Samples = m_pSample_buf_prev;
+ }
+
+ const int y_sample_base_ofs = ((row & 8) ? 64 : 0) + (row & 7) * 8;
+ const int y0_base = (c_y0 & 7) * 8 + 128;
+ const int y1_base = (c_y1 & 7) * 8 + 128;
+
+ for (int x = 0; x < m_image_x_size; x++)
+ {
+ const int base_ofs = (x >> 3) * BLOCKS_PER_MCU * 64 + (x & 7);
+
+ int y_sample = p_YSamples[check_sample_buf_ofs(base_ofs + y_sample_base_ofs)];
+
+ int a = base_ofs + y0_base;
+ int cb0_sample = p_C0Samples[check_sample_buf_ofs(a)];
+ int cr0_sample = p_C0Samples[check_sample_buf_ofs(a + 64)];
+
+ int b = base_ofs + y1_base;
+ int cb1_sample = m_pSample_buf[check_sample_buf_ofs(b)];
+ int cr1_sample = m_pSample_buf[check_sample_buf_ofs(b + 64)];
+
+ int cb = (cb0_sample * w0 + cb1_sample * w1 + 2) >> 2;
+ int cr = (cr0_sample * w0 + cr1_sample * w1 + 2) >> 2;
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ d0[0] = clamp(y_sample + rc);
+ d0[1] = clamp(y_sample + gc);
+ d0[2] = clamp(y_sample + bc);
+ d0[3] = 255;
+
+ d0 += 4;
+ }
+ }
+
+ // YCbCr H2V2 (2x2:1:1, 6 m_blocks per MCU) to RGB
+ void jpeg_decoder::H2V2Convert()
+ {
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8* d0 = m_pScan_line_0;
+ uint8* d1 = m_pScan_line_1;
+ uint8* y;
+ uint8* c;
- d0 += 8;
- d1 += 8;
+ if (row < 8)
+ y = m_pSample_buf + row * 8;
+ else
+ y = m_pSample_buf + 64 * 2 + (row & 7) * 8;
- c++;
+ c = m_pSample_buf + 64 * 4 + (row >> 1) * 8;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ for (int l = 0; l < 2; l++)
+ {
+ for (int j = 0; j < 8; j += 2)
+ {
+ int cb = c[0];
+ int cr = c[64];
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ int yy = y[j];
+ d0[0] = clamp(yy + rc);
+ d0[1] = clamp(yy + gc);
+ d0[2] = clamp(yy + bc);
+ d0[3] = 255;
+
+ yy = y[j + 1];
+ d0[4] = clamp(yy + rc);
+ d0[5] = clamp(yy + gc);
+ d0[6] = clamp(yy + bc);
+ d0[7] = 255;
+
+ yy = y[j + 8];
+ d1[0] = clamp(yy + rc);
+ d1[1] = clamp(yy + gc);
+ d1[2] = clamp(yy + bc);
+ d1[3] = 255;
+
+ yy = y[j + 8 + 1];
+ d1[4] = clamp(yy + rc);
+ d1[5] = clamp(yy + gc);
+ d1[6] = clamp(yy + bc);
+ d1[7] = 255;
+
+ d0 += 8;
+ d1 += 8;
+
+ c++;
+ }
+ y += 64;
}
- y += 64;
- }
-
- y += 64*6 - 64*2;
- c += 64*6 - 8;
- }
-}
-
-// Y (1 block per MCU) to 8-bit grayscale
-void jpeg_decoder::gray_convert()
-{
- int row = m_max_mcu_y_size - m_mcu_lines_left;
- uint8 *d = m_pScan_line_0;
- uint8 *s = m_pSample_buf + row * 8;
-
- for (int i = m_max_mcus_per_row; i > 0; i--)
- {
- *(uint *)d = *(uint *)s;
- *(uint *)(&d[4]) = *(uint *)(&s[4]);
-
- s += 64;
- d += 8;
- }
-}
-
-void jpeg_decoder::expanded_convert()
-{
- int row = m_max_mcu_y_size - m_mcu_lines_left;
-
- uint8* Py = m_pSample_buf + (row / 8) * 64 * m_comp_h_samp[0] + (row & 7) * 8;
-
- uint8* d = m_pScan_line_0;
-
- for (int i = m_max_mcus_per_row; i > 0; i--)
- {
- for (int k = 0; k < m_max_mcu_x_size; k += 8)
- {
- const int Y_ofs = k * 8;
- const int Cb_ofs = Y_ofs + 64 * m_expanded_blocks_per_component;
- const int Cr_ofs = Y_ofs + 64 * m_expanded_blocks_per_component * 2;
- for (int j = 0; j < 8; j++)
- {
- int y = Py[Y_ofs + j];
- int cb = Py[Cb_ofs + j];
- int cr = Py[Cr_ofs + j];
-
- d[0] = clamp(y + m_crr[cr]);
- d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
- d[2] = clamp(y + m_cbb[cb]);
- d[3] = 255;
-
- d += 4;
- }
- }
-
- Py += 64 * m_expanded_blocks_per_mcu;
- }
-}
-
-// Find end of image (EOI) marker, so we can return to the user the exact size of the input stream.
-void jpeg_decoder::find_eoi()
-{
- if (!m_progressive_flag)
- {
- // Attempt to read the EOI marker.
- //get_bits_no_markers(m_bits_left & 7);
-
- // Prime the bit buffer
- m_bits_left = 16;
- get_bits(16);
- get_bits(16);
-
- // The next marker _should_ be EOI
- process_markers();
- }
-
- m_total_bytes_read -= m_in_buf_left;
-}
-
-int jpeg_decoder::decode(const void** pScan_line, uint* pScan_line_len)
-{
- if ((m_error_code) || (!m_ready_flag))
- return JPGD_FAILED;
-
- if (m_total_lines_left == 0)
- return JPGD_DONE;
-
- if (m_mcu_lines_left == 0)
- {
- if (setjmp(m_jmp_state))
- return JPGD_FAILED;
-
- if (m_progressive_flag)
- load_next_row();
- else
- decode_next_row();
-
- // Find the EOI marker if that was the last row.
- if (m_total_lines_left <= m_max_mcu_y_size)
- find_eoi();
-
- m_mcu_lines_left = m_max_mcu_y_size;
- }
-
- if (m_freq_domain_chroma_upsample)
- {
- expanded_convert();
- *pScan_line = m_pScan_line_0;
- }
- else
- {
- switch (m_scan_type)
- {
- case JPGD_YH2V2:
- {
- if ((m_mcu_lines_left & 1) == 0)
- {
- H2V2Convert();
- *pScan_line = m_pScan_line_0;
- }
- else
- *pScan_line = m_pScan_line_1;
-
- break;
- }
- case JPGD_YH2V1:
- {
- H2V1Convert();
- *pScan_line = m_pScan_line_0;
- break;
- }
- case JPGD_YH1V2:
- {
- if ((m_mcu_lines_left & 1) == 0)
- {
- H1V2Convert();
- *pScan_line = m_pScan_line_0;
- }
- else
- *pScan_line = m_pScan_line_1;
-
- break;
- }
- case JPGD_YH1V1:
- {
- H1V1Convert();
- *pScan_line = m_pScan_line_0;
- break;
- }
- case JPGD_GRAYSCALE:
- {
- gray_convert();
- *pScan_line = m_pScan_line_0;
-
- break;
- }
- }
- }
-
- *pScan_line_len = m_real_dest_bytes_per_scan_line;
-
- m_mcu_lines_left--;
- m_total_lines_left--;
-
- return JPGD_SUCCESS;
-}
-
-// Creates the tables needed for efficient Huffman decoding.
-void jpeg_decoder::make_huff_table(int index, huff_tables *pH)
-{
- int p, i, l, si;
- uint8 huffsize[257];
- uint huffcode[257];
- uint code;
- uint subtree;
- int code_size;
- int lastp;
- int nextfreeentry;
- int currententry;
-
- pH->ac_table = m_huff_ac[index] != 0;
-
- p = 0;
-
- for (l = 1; l <= 16; l++)
- {
- for (i = 1; i <= m_huff_num[index][l]; i++)
- {
- JPGD_ASSERT(p < 257);
- huffsize[p++] = static_cast<uint8>(l);
- }
- }
-
- huffsize[p] = 0;
-
- lastp = p;
-
- code = 0;
- si = huffsize[0];
- p = 0;
-
- while (huffsize[p])
- {
- while (huffsize[p] == si)
- {
- JPGD_ASSERT(p < 257);
- huffcode[p++] = code;
- code++;
- }
-
- code <<= 1;
- si++;
- }
-
- memset(pH->look_up, 0, sizeof(pH->look_up));
- memset(pH->look_up2, 0, sizeof(pH->look_up2));
- memset(pH->tree, 0, sizeof(pH->tree));
- memset(pH->code_size, 0, sizeof(pH->code_size));
-
- nextfreeentry = -1;
-
- p = 0;
-
- while (p < lastp)
- {
- i = m_huff_val[index][p];
- code = huffcode[p];
- code_size = huffsize[p];
-
- pH->code_size[i] = static_cast<uint8>(code_size);
-
- if (code_size <= 8)
- {
- code <<= (8 - code_size);
-
- for (l = 1 << (8 - code_size); l > 0; l--)
- {
- JPGD_ASSERT(i < JPGD_HUFF_CODE_SIZE_MAX_LENGTH);
- JPGD_ASSERT(code < JPGD_HUFF_CODE_SIZE_MAX_LENGTH);
-
- pH->look_up[code] = i;
-
- bool has_extrabits = false;
- int extra_bits = 0;
- int num_extra_bits = i & 15;
-
- int bits_to_fetch = code_size;
- if (num_extra_bits)
- {
- int total_codesize = code_size + num_extra_bits;
- if (total_codesize <= 8)
- {
- has_extrabits = true;
- extra_bits = ((1 << num_extra_bits) - 1) & (code >> (8 - total_codesize));
- JPGD_ASSERT(extra_bits <= 0x7FFF);
- bits_to_fetch += num_extra_bits;
- }
- }
-
- if (!has_extrabits)
- pH->look_up2[code] = i | (bits_to_fetch << 8);
- else
- pH->look_up2[code] = i | 0x8000 | (extra_bits << 16) | (bits_to_fetch << 8);
-
- code++;
- }
- }
- else
- {
- subtree = (code >> (code_size - 8)) & 0xFF;
-
- currententry = pH->look_up[subtree];
-
- if (currententry == 0)
- {
- pH->look_up[subtree] = currententry = nextfreeentry;
- pH->look_up2[subtree] = currententry = nextfreeentry;
-
- nextfreeentry -= 2;
- }
-
- code <<= (16 - (code_size - 8));
-
- for (l = code_size; l > 9; l--)
- {
- if ((code & 0x8000) == 0)
- currententry--;
-
- unsigned int idx = -currententry - 1;
- JPGD_ASSERT(idx < JPGD_HUFF_TREE_MAX_LENGTH);
- if (pH->tree[idx] == 0)
- {
- pH->tree[idx] = nextfreeentry;
-
- currententry = nextfreeentry;
-
- nextfreeentry -= 2;
- }
- else {
- currententry = pH->tree[idx];
- }
-
- code <<= 1;
- }
-
- if ((code & 0x8000) == 0)
- currententry--;
-
- pH->tree[-currententry - 1] = i;
- }
-
- p++;
- }
-}
-
-// Verifies the quantization tables needed for this scan are available.
-void jpeg_decoder::check_quant_tables()
-{
- for (int i = 0; i < m_comps_in_scan; i++)
- if (m_quant[m_comp_quant[m_comp_list[i]]] == NULL)
- stop_decoding(JPGD_UNDEFINED_QUANT_TABLE);
-}
-
-// Verifies that all the Huffman tables needed for this scan are available.
-void jpeg_decoder::check_huff_tables()
-{
- for (int i = 0; i < m_comps_in_scan; i++)
- {
- if ((m_spectral_start == 0) && (m_huff_num[m_comp_dc_tab[m_comp_list[i]]] == NULL))
- stop_decoding(JPGD_UNDEFINED_HUFF_TABLE);
-
- if ((m_spectral_end > 0) && (m_huff_num[m_comp_ac_tab[m_comp_list[i]]] == NULL))
- stop_decoding(JPGD_UNDEFINED_HUFF_TABLE);
- }
-
- for (int i = 0; i < JPGD_MAX_HUFF_TABLES; i++)
- if (m_huff_num[i])
- {
- if (!m_pHuff_tabs[i])
- m_pHuff_tabs[i] = (huff_tables *)alloc(sizeof(huff_tables));
-
- make_huff_table(i, m_pHuff_tabs[i]);
- }
-}
-
-// Determines the component order inside each MCU.
-// Also calcs how many MCU's are on each row, etc.
-void jpeg_decoder::calc_mcu_block_order()
-{
- int component_num, component_id;
- int max_h_samp = 0, max_v_samp = 0;
-
- for (component_id = 0; component_id < m_comps_in_frame; component_id++)
- {
- if (m_comp_h_samp[component_id] > max_h_samp)
- max_h_samp = m_comp_h_samp[component_id];
-
- if (m_comp_v_samp[component_id] > max_v_samp)
- max_v_samp = m_comp_v_samp[component_id];
- }
-
- for (component_id = 0; component_id < m_comps_in_frame; component_id++)
- {
- m_comp_h_blocks[component_id] = ((((m_image_x_size * m_comp_h_samp[component_id]) + (max_h_samp - 1)) / max_h_samp) + 7) / 8;
- m_comp_v_blocks[component_id] = ((((m_image_y_size * m_comp_v_samp[component_id]) + (max_v_samp - 1)) / max_v_samp) + 7) / 8;
- }
-
- if (m_comps_in_scan == 1)
- {
- m_mcus_per_row = m_comp_h_blocks[m_comp_list[0]];
- m_mcus_per_col = m_comp_v_blocks[m_comp_list[0]];
- }
- else
- {
- m_mcus_per_row = (((m_image_x_size + 7) / 8) + (max_h_samp - 1)) / max_h_samp;
- m_mcus_per_col = (((m_image_y_size + 7) / 8) + (max_v_samp - 1)) / max_v_samp;
- }
-
- if (m_comps_in_scan == 1)
- {
- m_mcu_org[0] = m_comp_list[0];
-
- m_blocks_per_mcu = 1;
- }
- else
- {
- m_blocks_per_mcu = 0;
-
- for (component_num = 0; component_num < m_comps_in_scan; component_num++)
- {
- int num_blocks;
-
- component_id = m_comp_list[component_num];
-
- num_blocks = m_comp_h_samp[component_id] * m_comp_v_samp[component_id];
-
- while (num_blocks--)
- m_mcu_org[m_blocks_per_mcu++] = component_id;
- }
- }
-}
-
-// Starts a new scan.
-int jpeg_decoder::init_scan()
-{
- if (!locate_sos_marker())
- return JPGD_FALSE;
-
- calc_mcu_block_order();
-
- check_huff_tables();
-
- check_quant_tables();
-
- memset(m_last_dc_val, 0, m_comps_in_frame * sizeof(uint));
-
- m_eob_run = 0;
-
- if (m_restart_interval)
- {
- m_restarts_left = m_restart_interval;
- m_next_restart_num = 0;
- }
-
- fix_in_buffer();
-
- return JPGD_TRUE;
-}
-
-// Starts a frame. Determines if the number of components or sampling factors
-// are supported.
-void jpeg_decoder::init_frame()
-{
- int i;
-
- if (m_comps_in_frame == 1)
- {
- if ((m_comp_h_samp[0] != 1) || (m_comp_v_samp[0] != 1))
- stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
-
- m_scan_type = JPGD_GRAYSCALE;
- m_max_blocks_per_mcu = 1;
- m_max_mcu_x_size = 8;
- m_max_mcu_y_size = 8;
- }
- else if (m_comps_in_frame == 3)
- {
- if ( ((m_comp_h_samp[1] != 1) || (m_comp_v_samp[1] != 1)) ||
- ((m_comp_h_samp[2] != 1) || (m_comp_v_samp[2] != 1)) )
- stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
-
- if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1))
- {
- m_scan_type = JPGD_YH1V1;
-
- m_max_blocks_per_mcu = 3;
- m_max_mcu_x_size = 8;
- m_max_mcu_y_size = 8;
- }
- else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1))
- {
- m_scan_type = JPGD_YH2V1;
- m_max_blocks_per_mcu = 4;
- m_max_mcu_x_size = 16;
- m_max_mcu_y_size = 8;
- }
- else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 2))
- {
- m_scan_type = JPGD_YH1V2;
- m_max_blocks_per_mcu = 4;
- m_max_mcu_x_size = 8;
- m_max_mcu_y_size = 16;
- }
- else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2))
- {
- m_scan_type = JPGD_YH2V2;
- m_max_blocks_per_mcu = 6;
- m_max_mcu_x_size = 16;
- m_max_mcu_y_size = 16;
- }
- else
- stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
- }
- else
- stop_decoding(JPGD_UNSUPPORTED_COLORSPACE);
-
- m_max_mcus_per_row = (m_image_x_size + (m_max_mcu_x_size - 1)) / m_max_mcu_x_size;
- m_max_mcus_per_col = (m_image_y_size + (m_max_mcu_y_size - 1)) / m_max_mcu_y_size;
-
- // These values are for the *destination* pixels: after conversion.
- if (m_scan_type == JPGD_GRAYSCALE)
- m_dest_bytes_per_pixel = 1;
- else
- m_dest_bytes_per_pixel = 4;
-
- m_dest_bytes_per_scan_line = ((m_image_x_size + 15) & 0xFFF0) * m_dest_bytes_per_pixel;
-
- m_real_dest_bytes_per_scan_line = (m_image_x_size * m_dest_bytes_per_pixel);
-
- // Initialize two scan line buffers.
- m_pScan_line_0 = (uint8 *)alloc(m_dest_bytes_per_scan_line, true);
- if ((m_scan_type == JPGD_YH1V2) || (m_scan_type == JPGD_YH2V2))
- m_pScan_line_1 = (uint8 *)alloc(m_dest_bytes_per_scan_line, true);
-
- m_max_blocks_per_row = m_max_mcus_per_row * m_max_blocks_per_mcu;
-
- // Should never happen
- if (m_max_blocks_per_row > JPGD_MAX_BLOCKS_PER_ROW)
- stop_decoding(JPGD_ASSERTION_ERROR);
-
- // Allocate the coefficient buffer, enough for one MCU
- m_pMCU_coefficients = (jpgd_block_t*)alloc(m_max_blocks_per_mcu * 64 * sizeof(jpgd_block_t));
-
- for (i = 0; i < m_max_blocks_per_mcu; i++)
- m_mcu_block_max_zag[i] = 64;
-
- m_expanded_blocks_per_component = m_comp_h_samp[0] * m_comp_v_samp[0];
- m_expanded_blocks_per_mcu = m_expanded_blocks_per_component * m_comps_in_frame;
- m_expanded_blocks_per_row = m_max_mcus_per_row * m_expanded_blocks_per_mcu;
- // Freq. domain chroma upsampling is only supported for H2V2 subsampling factor (the most common one I've seen).
- m_freq_domain_chroma_upsample = false;
-#if JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING
- m_freq_domain_chroma_upsample = (m_expanded_blocks_per_mcu == 4*3);
-#endif
- if (m_freq_domain_chroma_upsample)
- m_pSample_buf = (uint8 *)alloc(m_expanded_blocks_per_row * 64);
- else
- m_pSample_buf = (uint8 *)alloc(m_max_blocks_per_row * 64);
-
- m_total_lines_left = m_image_y_size;
-
- m_mcu_lines_left = 0;
-
- create_look_ups();
-}
-
-// The coeff_buf series of methods originally stored the coefficients
-// into a "virtual" file which was located in EMS, XMS, or a disk file. A cache
-// was used to make this process more efficient. Now, we can store the entire
-// thing in RAM.
-jpeg_decoder::coeff_buf* jpeg_decoder::coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y)
-{
- coeff_buf* cb = (coeff_buf*)alloc(sizeof(coeff_buf));
-
- cb->block_num_x = block_num_x;
- cb->block_num_y = block_num_y;
- cb->block_len_x = block_len_x;
- cb->block_len_y = block_len_y;
- cb->block_size = (block_len_x * block_len_y) * sizeof(jpgd_block_t);
- cb->pData = (uint8 *)alloc(cb->block_size * block_num_x * block_num_y, true);
- return cb;
-}
-
-inline jpgd_block_t *jpeg_decoder::coeff_buf_getp(coeff_buf *cb, int block_x, int block_y)
-{
- JPGD_ASSERT((block_x < cb->block_num_x) && (block_y < cb->block_num_y));
- return (jpgd_block_t *)(cb->pData + block_x * cb->block_size + block_y * (cb->block_size * cb->block_num_x));
-}
-
-// The following methods decode the various types of m_blocks encountered
-// in progressively encoded images.
-void jpeg_decoder::decode_block_dc_first(jpeg_decoder *pD, int component_id, int block_x, int block_y)
-{
- int s, r;
- jpgd_block_t *p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y);
-
- if ((s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_dc_tab[component_id]])) != 0)
- {
- r = pD->get_bits_no_markers(s);
- s = JPGD_HUFF_EXTEND(r, s);
- }
-
- pD->m_last_dc_val[component_id] = (s += pD->m_last_dc_val[component_id]);
-
- p[0] = static_cast<jpgd_block_t>(s << pD->m_successive_low);
-}
-
-void jpeg_decoder::decode_block_dc_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y)
-{
- if (pD->get_bits_no_markers(1))
- {
- jpgd_block_t *p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y);
-
- p[0] |= (1 << pD->m_successive_low);
- }
-}
-
-void jpeg_decoder::decode_block_ac_first(jpeg_decoder *pD, int component_id, int block_x, int block_y)
-{
- int k, s, r;
-
- if (pD->m_eob_run)
- {
- pD->m_eob_run--;
- return;
- }
-
- jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
-
- for (k = pD->m_spectral_start; k <= pD->m_spectral_end; k++)
- {
- unsigned int idx = pD->m_comp_ac_tab[component_id];
- JPGD_ASSERT(idx < JPGD_MAX_HUFF_TABLES);
- s = pD->huff_decode(pD->m_pHuff_tabs[idx]);
-
- r = s >> 4;
- s &= 15;
-
- if (s)
- {
- if ((k += r) > 63)
- pD->stop_decoding(JPGD_DECODE_ERROR);
-
- r = pD->get_bits_no_markers(s);
- s = JPGD_HUFF_EXTEND(r, s);
-
- p[g_ZAG[k]] = static_cast<jpgd_block_t>(s << pD->m_successive_low);
- }
- else
- {
- if (r == 15)
- {
- if ((k += 15) > 63)
- pD->stop_decoding(JPGD_DECODE_ERROR);
- }
- else
- {
- pD->m_eob_run = 1 << r;
-
- if (r)
- pD->m_eob_run += pD->get_bits_no_markers(r);
-
- pD->m_eob_run--;
-
- break;
- }
- }
- }
-}
-
-void jpeg_decoder::decode_block_ac_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y)
-{
- int s, k, r;
- int p1 = 1 << pD->m_successive_low;
- int m1 = (-1) << pD->m_successive_low;
- jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
- JPGD_ASSERT(pD->m_spectral_end <= 63);
-
- k = pD->m_spectral_start;
-
- if (pD->m_eob_run == 0)
- {
- for ( ; k <= pD->m_spectral_end; k++)
- {
- unsigned int idx = pD->m_comp_ac_tab[component_id];
- JPGD_ASSERT(idx < JPGD_MAX_HUFF_TABLES);
- s = pD->huff_decode(pD->m_pHuff_tabs[idx]);
-
- r = s >> 4;
- s &= 15;
-
- if (s)
- {
- if (s != 1)
- pD->stop_decoding(JPGD_DECODE_ERROR);
-
- if (pD->get_bits_no_markers(1))
- s = p1;
- else
- s = m1;
- }
- else
- {
- if (r != 15)
- {
- pD->m_eob_run = 1 << r;
-
- if (r)
- pD->m_eob_run += pD->get_bits_no_markers(r);
-
- break;
- }
- }
-
- do
- {
- jpgd_block_t *this_coef = p + g_ZAG[k & 63];
-
- if (*this_coef != 0)
- {
- if (pD->get_bits_no_markers(1))
- {
- if ((*this_coef & p1) == 0)
- {
- if (*this_coef >= 0)
- *this_coef = static_cast<jpgd_block_t>(*this_coef + p1);
- else
- *this_coef = static_cast<jpgd_block_t>(*this_coef + m1);
- }
- }
- }
- else
- {
- if (--r < 0)
- break;
- }
-
- k++;
-
- } while (k <= pD->m_spectral_end);
-
- if ((s) && (k < 64))
- {
- p[g_ZAG[k]] = static_cast<jpgd_block_t>(s);
- }
- }
- }
-
- if (pD->m_eob_run > 0)
- {
- for ( ; k <= pD->m_spectral_end; k++)
- {
- jpgd_block_t *this_coef = p + g_ZAG[k & 63]; // logical AND to shut up static code analysis
-
- if (*this_coef != 0)
- {
- if (pD->get_bits_no_markers(1))
- {
- if ((*this_coef & p1) == 0)
- {
- if (*this_coef >= 0)
- *this_coef = static_cast<jpgd_block_t>(*this_coef + p1);
- else
- *this_coef = static_cast<jpgd_block_t>(*this_coef + m1);
- }
- }
- }
- }
-
- pD->m_eob_run--;
- }
-}
-
-// Decode a scan in a progressively encoded image.
-void jpeg_decoder::decode_scan(pDecode_block_func decode_block_func)
-{
- int mcu_row, mcu_col, mcu_block;
- int block_x_mcu[JPGD_MAX_COMPONENTS], m_block_y_mcu[JPGD_MAX_COMPONENTS];
-
- memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
-
- for (mcu_col = 0; mcu_col < m_mcus_per_col; mcu_col++)
- {
- int component_num, component_id;
-
- memset(block_x_mcu, 0, sizeof(block_x_mcu));
-
- for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
- {
- int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0;
-
- if ((m_restart_interval) && (m_restarts_left == 0))
- process_restart();
-
- for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
- {
- component_id = m_mcu_org[mcu_block];
-
- decode_block_func(this, component_id, block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
-
- if (m_comps_in_scan == 1)
- block_x_mcu[component_id]++;
- else
- {
- if (++block_x_mcu_ofs == m_comp_h_samp[component_id])
- {
- block_x_mcu_ofs = 0;
-
- if (++block_y_mcu_ofs == m_comp_v_samp[component_id])
- {
- block_y_mcu_ofs = 0;
- block_x_mcu[component_id] += m_comp_h_samp[component_id];
- }
- }
- }
- }
-
- m_restarts_left--;
- }
-
- if (m_comps_in_scan == 1)
- m_block_y_mcu[m_comp_list[0]]++;
- else
- {
- for (component_num = 0; component_num < m_comps_in_scan; component_num++)
- {
- component_id = m_comp_list[component_num];
- m_block_y_mcu[component_id] += m_comp_v_samp[component_id];
- }
- }
- }
-}
-
-// Decode a progressively encoded image.
-void jpeg_decoder::init_progressive()
-{
- int i;
-
- if (m_comps_in_frame == 4)
- stop_decoding(JPGD_UNSUPPORTED_COLORSPACE);
-
- // Allocate the coefficient buffers.
- for (i = 0; i < m_comps_in_frame; i++)
- {
- m_dc_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 1, 1);
- m_ac_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 8, 8);
- }
-
- for ( ; ; )
- {
- int dc_only_scan, refinement_scan;
- pDecode_block_func decode_block_func;
-
- if (!init_scan())
- break;
-
- dc_only_scan = (m_spectral_start == 0);
- refinement_scan = (m_successive_high != 0);
-
- if ((m_spectral_start > m_spectral_end) || (m_spectral_end > 63))
- stop_decoding(JPGD_BAD_SOS_SPECTRAL);
-
- if (dc_only_scan)
- {
- if (m_spectral_end)
- stop_decoding(JPGD_BAD_SOS_SPECTRAL);
- }
- else if (m_comps_in_scan != 1) /* AC scans can only contain one component */
- stop_decoding(JPGD_BAD_SOS_SPECTRAL);
-
- if ((refinement_scan) && (m_successive_low != m_successive_high - 1))
- stop_decoding(JPGD_BAD_SOS_SUCCESSIVE);
-
- if (dc_only_scan)
- {
- if (refinement_scan)
- decode_block_func = decode_block_dc_refine;
- else
- decode_block_func = decode_block_dc_first;
- }
- else
- {
- if (refinement_scan)
- decode_block_func = decode_block_ac_refine;
- else
- decode_block_func = decode_block_ac_first;
- }
-
- decode_scan(decode_block_func);
-
- m_bits_left = 16;
- get_bits(16);
- get_bits(16);
- }
-
- m_comps_in_scan = m_comps_in_frame;
-
- for (i = 0; i < m_comps_in_frame; i++)
- m_comp_list[i] = i;
-
- calc_mcu_block_order();
-}
-
-void jpeg_decoder::init_sequential()
-{
- if (!init_scan())
- stop_decoding(JPGD_UNEXPECTED_MARKER);
-}
-
-void jpeg_decoder::decode_start()
-{
- init_frame();
-
- if (m_progressive_flag)
- init_progressive();
- else
- init_sequential();
-}
-
-void jpeg_decoder::decode_init(jpeg_decoder_stream *pStream)
-{
- init(pStream);
- locate_sof_marker();
-}
-
-jpeg_decoder::jpeg_decoder(jpeg_decoder_stream *pStream)
-{
- if (setjmp(m_jmp_state))
- return;
- decode_init(pStream);
-}
-
-int jpeg_decoder::begin_decoding()
-{
- if (m_ready_flag)
- return JPGD_SUCCESS;
-
- if (m_error_code)
- return JPGD_FAILED;
-
- if (setjmp(m_jmp_state))
- return JPGD_FAILED;
-
- decode_start();
-
- m_ready_flag = true;
-
- return JPGD_SUCCESS;
-}
-
-jpeg_decoder::~jpeg_decoder()
-{
- free_all_blocks();
-}
-
-jpeg_decoder_file_stream::jpeg_decoder_file_stream()
-{
- m_pFile = NULL;
- m_eof_flag = false;
- m_error_flag = false;
-}
-
-void jpeg_decoder_file_stream::close()
-{
- if (m_pFile)
- {
- fclose(m_pFile);
- m_pFile = NULL;
- }
-
- m_eof_flag = false;
- m_error_flag = false;
-}
-
-jpeg_decoder_file_stream::~jpeg_decoder_file_stream()
-{
- close();
-}
-
-bool jpeg_decoder_file_stream::open(const char *Pfilename)
-{
- close();
-
- m_eof_flag = false;
- m_error_flag = false;
+ y += 64 * 6 - 64 * 2;
+ c += 64 * 6 - 8;
+ }
+ }
+
+ uint32_t jpeg_decoder::H2V2ConvertFiltered()
+ {
+ const uint BLOCKS_PER_MCU = 6;
+ int y = m_image_y_size - m_total_lines_left;
+ int row = y & 15;
+
+ const int half_image_y_size = (m_image_y_size >> 1) - 1;
+
+ uint8* d0 = m_pScan_line_0;
+
+ int c_y0 = (y - 1) >> 1;
+ int c_y1 = JPGD_MIN(c_y0 + 1, half_image_y_size);
+
+ const uint8_t* p_YSamples = m_pSample_buf;
+ const uint8_t* p_C0Samples = m_pSample_buf;
+ if ((c_y0 >= 0) && (((row & 15) == 0) || ((row & 15) == 15)) && (m_total_lines_left > 1))
+ {
+ assert(y > 0);
+ assert(m_sample_buf_prev_valid);
+
+ if ((row & 15) == 15)
+ p_YSamples = m_pSample_buf_prev;
+
+ p_C0Samples = m_pSample_buf_prev;
+ }
+
+ const int y_sample_base_ofs = ((row & 8) ? 128 : 0) + (row & 7) * 8;
+ const int y0_base = (c_y0 & 7) * 8 + 256;
+ const int y1_base = (c_y1 & 7) * 8 + 256;
+
+ const int half_image_x_size = (m_image_x_size >> 1) - 1;
+
+ static const uint8_t s_muls[2][2][4] =
+ {
+ { { 1, 3, 3, 9 }, { 3, 9, 1, 3 }, },
+ { { 3, 1, 9, 3 }, { 9, 3, 3, 1 } }
+ };
+
+ if (((row & 15) >= 1) && ((row & 15) <= 14))
+ {
+ assert((row & 1) == 1);
+ assert(((y + 1 - 1) >> 1) == c_y0);
+
+ assert(p_YSamples == m_pSample_buf);
+ assert(p_C0Samples == m_pSample_buf);
+
+ uint8* d1 = m_pScan_line_1;
+ const int y_sample_base_ofs1 = (((row + 1) & 8) ? 128 : 0) + ((row + 1) & 7) * 8;
+
+ for (int x = 0; x < m_image_x_size; x++)
+ {
+ int k = (x >> 4) * BLOCKS_PER_MCU * 64 + ((x & 8) ? 64 : 0) + (x & 7);
+ int y_sample0 = p_YSamples[check_sample_buf_ofs(k + y_sample_base_ofs)];
+ int y_sample1 = p_YSamples[check_sample_buf_ofs(k + y_sample_base_ofs1)];
+
+ int c_x0 = (x - 1) >> 1;
+ int c_x1 = JPGD_MIN(c_x0 + 1, half_image_x_size);
+ c_x0 = JPGD_MAX(c_x0, 0);
+
+ int a = (c_x0 >> 3) * BLOCKS_PER_MCU * 64 + (c_x0 & 7);
+ int cb00_sample = p_C0Samples[check_sample_buf_ofs(a + y0_base)];
+ int cr00_sample = p_C0Samples[check_sample_buf_ofs(a + y0_base + 64)];
+
+ int cb01_sample = m_pSample_buf[check_sample_buf_ofs(a + y1_base)];
+ int cr01_sample = m_pSample_buf[check_sample_buf_ofs(a + y1_base + 64)];
+
+ int b = (c_x1 >> 3) * BLOCKS_PER_MCU * 64 + (c_x1 & 7);
+ int cb10_sample = p_C0Samples[check_sample_buf_ofs(b + y0_base)];
+ int cr10_sample = p_C0Samples[check_sample_buf_ofs(b + y0_base + 64)];
+
+ int cb11_sample = m_pSample_buf[check_sample_buf_ofs(b + y1_base)];
+ int cr11_sample = m_pSample_buf[check_sample_buf_ofs(b + y1_base + 64)];
+
+ {
+ const uint8_t* pMuls = &s_muls[row & 1][x & 1][0];
+ int cb = (cb00_sample * pMuls[0] + cb01_sample * pMuls[1] + cb10_sample * pMuls[2] + cb11_sample * pMuls[3] + 8) >> 4;
+ int cr = (cr00_sample * pMuls[0] + cr01_sample * pMuls[1] + cr10_sample * pMuls[2] + cr11_sample * pMuls[3] + 8) >> 4;
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ d0[0] = clamp(y_sample0 + rc);
+ d0[1] = clamp(y_sample0 + gc);
+ d0[2] = clamp(y_sample0 + bc);
+ d0[3] = 255;
+
+ d0 += 4;
+ }
+
+ {
+ const uint8_t* pMuls = &s_muls[(row + 1) & 1][x & 1][0];
+ int cb = (cb00_sample * pMuls[0] + cb01_sample * pMuls[1] + cb10_sample * pMuls[2] + cb11_sample * pMuls[3] + 8) >> 4;
+ int cr = (cr00_sample * pMuls[0] + cr01_sample * pMuls[1] + cr10_sample * pMuls[2] + cr11_sample * pMuls[3] + 8) >> 4;
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ d1[0] = clamp(y_sample1 + rc);
+ d1[1] = clamp(y_sample1 + gc);
+ d1[2] = clamp(y_sample1 + bc);
+ d1[3] = 255;
+
+ d1 += 4;
+ }
+
+ if (((x & 1) == 1) && (x < m_image_x_size - 1))
+ {
+ const int nx = x + 1;
+ assert(c_x0 == (nx - 1) >> 1);
+
+ k = (nx >> 4) * BLOCKS_PER_MCU * 64 + ((nx & 8) ? 64 : 0) + (nx & 7);
+ y_sample0 = p_YSamples[check_sample_buf_ofs(k + y_sample_base_ofs)];
+ y_sample1 = p_YSamples[check_sample_buf_ofs(k + y_sample_base_ofs1)];
+
+ {
+ const uint8_t* pMuls = &s_muls[row & 1][nx & 1][0];
+ int cb = (cb00_sample * pMuls[0] + cb01_sample * pMuls[1] + cb10_sample * pMuls[2] + cb11_sample * pMuls[3] + 8) >> 4;
+ int cr = (cr00_sample * pMuls[0] + cr01_sample * pMuls[1] + cr10_sample * pMuls[2] + cr11_sample * pMuls[3] + 8) >> 4;
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ d0[0] = clamp(y_sample0 + rc);
+ d0[1] = clamp(y_sample0 + gc);
+ d0[2] = clamp(y_sample0 + bc);
+ d0[3] = 255;
+
+ d0 += 4;
+ }
+
+ {
+ const uint8_t* pMuls = &s_muls[(row + 1) & 1][nx & 1][0];
+ int cb = (cb00_sample * pMuls[0] + cb01_sample * pMuls[1] + cb10_sample * pMuls[2] + cb11_sample * pMuls[3] + 8) >> 4;
+ int cr = (cr00_sample * pMuls[0] + cr01_sample * pMuls[1] + cr10_sample * pMuls[2] + cr11_sample * pMuls[3] + 8) >> 4;
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ d1[0] = clamp(y_sample1 + rc);
+ d1[1] = clamp(y_sample1 + gc);
+ d1[2] = clamp(y_sample1 + bc);
+ d1[3] = 255;
+
+ d1 += 4;
+ }
+
+ ++x;
+ }
+ }
+
+ return 2;
+ }
+ else
+ {
+ for (int x = 0; x < m_image_x_size; x++)
+ {
+ int y_sample = p_YSamples[check_sample_buf_ofs((x >> 4) * BLOCKS_PER_MCU * 64 + ((x & 8) ? 64 : 0) + (x & 7) + y_sample_base_ofs)];
+
+ int c_x0 = (x - 1) >> 1;
+ int c_x1 = JPGD_MIN(c_x0 + 1, half_image_x_size);
+ c_x0 = JPGD_MAX(c_x0, 0);
+
+ int a = (c_x0 >> 3) * BLOCKS_PER_MCU * 64 + (c_x0 & 7);
+ int cb00_sample = p_C0Samples[check_sample_buf_ofs(a + y0_base)];
+ int cr00_sample = p_C0Samples[check_sample_buf_ofs(a + y0_base + 64)];
+
+ int cb01_sample = m_pSample_buf[check_sample_buf_ofs(a + y1_base)];
+ int cr01_sample = m_pSample_buf[check_sample_buf_ofs(a + y1_base + 64)];
+
+ int b = (c_x1 >> 3) * BLOCKS_PER_MCU * 64 + (c_x1 & 7);
+ int cb10_sample = p_C0Samples[check_sample_buf_ofs(b + y0_base)];
+ int cr10_sample = p_C0Samples[check_sample_buf_ofs(b + y0_base + 64)];
+
+ int cb11_sample = m_pSample_buf[check_sample_buf_ofs(b + y1_base)];
+ int cr11_sample = m_pSample_buf[check_sample_buf_ofs(b + y1_base + 64)];
+
+ const uint8_t* pMuls = &s_muls[row & 1][x & 1][0];
+ int cb = (cb00_sample * pMuls[0] + cb01_sample * pMuls[1] + cb10_sample * pMuls[2] + cb11_sample * pMuls[3] + 8) >> 4;
+ int cr = (cr00_sample * pMuls[0] + cr01_sample * pMuls[1] + cr10_sample * pMuls[2] + cr11_sample * pMuls[3] + 8) >> 4;
+
+ int rc = m_crr[cr];
+ int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
+ int bc = m_cbb[cb];
+
+ d0[0] = clamp(y_sample + rc);
+ d0[1] = clamp(y_sample + gc);
+ d0[2] = clamp(y_sample + bc);
+ d0[3] = 255;
+
+ d0 += 4;
+ }
+
+ return 1;
+ }
+ }
+
+ // Y (1 block per MCU) to 8-bit grayscale
+ void jpeg_decoder::gray_convert()
+ {
+ int row = m_max_mcu_y_size - m_mcu_lines_left;
+ uint8* d = m_pScan_line_0;
+ uint8* s = m_pSample_buf + row * 8;
+
+ for (int i = m_max_mcus_per_row; i > 0; i--)
+ {
+ *(uint*)d = *(uint*)s;
+ *(uint*)(&d[4]) = *(uint*)(&s[4]);
+
+ s += 64;
+ d += 8;
+ }
+ }
+
+ // Find end of image (EOI) marker, so we can return to the user the exact size of the input stream.
+ void jpeg_decoder::find_eoi()
+ {
+ if (!m_progressive_flag)
+ {
+ // Attempt to read the EOI marker.
+ //get_bits_no_markers(m_bits_left & 7);
+
+ // Prime the bit buffer
+ m_bits_left = 16;
+ get_bits(16);
+ get_bits(16);
+
+ // The next marker _should_ be EOI
+ process_markers();
+ }
+
+ m_total_bytes_read -= m_in_buf_left;
+ }
+
+ int jpeg_decoder::decode_next_mcu_row()
+ {
+ if (::setjmp(m_jmp_state))
+ return JPGD_FAILED;
+
+ const bool chroma_y_filtering = ((m_flags & cFlagBoxChromaFiltering) == 0) && ((m_scan_type == JPGD_YH2V2) || (m_scan_type == JPGD_YH1V2));
+ if (chroma_y_filtering)
+ {
+ std::swap(m_pSample_buf, m_pSample_buf_prev);
+
+ m_sample_buf_prev_valid = true;
+ }
+
+ if (m_progressive_flag)
+ load_next_row();
+ else
+ decode_next_row();
+
+ // Find the EOI marker if that was the last row.
+ if (m_total_lines_left <= m_max_mcu_y_size)
+ find_eoi();
+
+ m_mcu_lines_left = m_max_mcu_y_size;
+ return 0;
+ }
+
+ int jpeg_decoder::decode(const void** pScan_line, uint* pScan_line_len)
+ {
+ if ((m_error_code) || (!m_ready_flag))
+ return JPGD_FAILED;
+
+ if (m_total_lines_left == 0)
+ return JPGD_DONE;
+
+ const bool chroma_y_filtering = ((m_flags & cFlagBoxChromaFiltering) == 0) && ((m_scan_type == JPGD_YH2V2) || (m_scan_type == JPGD_YH1V2));
+
+ bool get_another_mcu_row = false;
+ bool got_mcu_early = false;
+ if (chroma_y_filtering)
+ {
+ if (m_total_lines_left == m_image_y_size)
+ get_another_mcu_row = true;
+ else if ((m_mcu_lines_left == 1) && (m_total_lines_left > 1))
+ {
+ get_another_mcu_row = true;
+ got_mcu_early = true;
+ }
+ }
+ else
+ {
+ get_another_mcu_row = (m_mcu_lines_left == 0);
+ }
+
+ if (get_another_mcu_row)
+ {
+ int status = decode_next_mcu_row();
+ if (status != 0)
+ return status;
+ }
+
+ switch (m_scan_type)
+ {
+ case JPGD_YH2V2:
+ {
+ if ((m_flags & cFlagBoxChromaFiltering) == 0)
+ {
+ if (m_num_buffered_scanlines == 1)
+ {
+ *pScan_line = m_pScan_line_1;
+ }
+ else if (m_num_buffered_scanlines == 0)
+ {
+ m_num_buffered_scanlines = H2V2ConvertFiltered();
+ *pScan_line = m_pScan_line_0;
+ }
+
+ m_num_buffered_scanlines--;
+ }
+ else
+ {
+ if ((m_mcu_lines_left & 1) == 0)
+ {
+ H2V2Convert();
+ *pScan_line = m_pScan_line_0;
+ }
+ else
+ *pScan_line = m_pScan_line_1;
+ }
+
+ break;
+ }
+ case JPGD_YH2V1:
+ {
+ if ((m_flags & cFlagBoxChromaFiltering) == 0)
+ H2V1ConvertFiltered();
+ else
+ H2V1Convert();
+ *pScan_line = m_pScan_line_0;
+ break;
+ }
+ case JPGD_YH1V2:
+ {
+ if (chroma_y_filtering)
+ {
+ H1V2ConvertFiltered();
+ *pScan_line = m_pScan_line_0;
+ }
+ else
+ {
+ if ((m_mcu_lines_left & 1) == 0)
+ {
+ H1V2Convert();
+ *pScan_line = m_pScan_line_0;
+ }
+ else
+ *pScan_line = m_pScan_line_1;
+ }
+
+ break;
+ }
+ case JPGD_YH1V1:
+ {
+ H1V1Convert();
+ *pScan_line = m_pScan_line_0;
+ break;
+ }
+ case JPGD_GRAYSCALE:
+ {
+ gray_convert();
+ *pScan_line = m_pScan_line_0;
+
+ break;
+ }
+ }
+
+ *pScan_line_len = m_real_dest_bytes_per_scan_line;
+
+ if (!got_mcu_early)
+ {
+ m_mcu_lines_left--;
+ }
+
+ m_total_lines_left--;
+
+ return JPGD_SUCCESS;
+ }
+
+ // Creates the tables needed for efficient Huffman decoding.
+ void jpeg_decoder::make_huff_table(int index, huff_tables* pH)
+ {
+ int p, i, l, si;
+ uint8 huffsize[258];
+ uint huffcode[258];
+ uint code;
+ uint subtree;
+ int code_size;
+ int lastp;
+ int nextfreeentry;
+ int currententry;
+
+ pH->ac_table = m_huff_ac[index] != 0;
+
+ p = 0;
+
+ for (l = 1; l <= 16; l++)
+ {
+ for (i = 1; i <= m_huff_num[index][l]; i++)
+ {
+ if (p >= 257)
+ stop_decoding(JPGD_DECODE_ERROR);
+ huffsize[p++] = static_cast<uint8>(l);
+ }
+ }
+
+ assert(p < 258);
+ huffsize[p] = 0;
+
+ lastp = p;
+
+ code = 0;
+ si = huffsize[0];
+ p = 0;
+
+ while (huffsize[p])
+ {
+ while (huffsize[p] == si)
+ {
+ if (p >= 257)
+ stop_decoding(JPGD_DECODE_ERROR);
+ huffcode[p++] = code;
+ code++;
+ }
+
+ code <<= 1;
+ si++;
+ }
+
+ memset(pH->look_up, 0, sizeof(pH->look_up));
+ memset(pH->look_up2, 0, sizeof(pH->look_up2));
+ memset(pH->tree, 0, sizeof(pH->tree));
+ memset(pH->code_size, 0, sizeof(pH->code_size));
+
+ nextfreeentry = -1;
+
+ p = 0;
+
+ while (p < lastp)
+ {
+ i = m_huff_val[index][p];
+
+ code = huffcode[p];
+ code_size = huffsize[p];
+
+ assert(i < JPGD_HUFF_CODE_SIZE_MAX_LENGTH);
+ pH->code_size[i] = static_cast<uint8>(code_size);
+
+ if (code_size <= 8)
+ {
+ code <<= (8 - code_size);
+
+ for (l = 1 << (8 - code_size); l > 0; l--)
+ {
+ if (code >= 256)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ pH->look_up[code] = i;
+
+ bool has_extrabits = false;
+ int extra_bits = 0;
+ int num_extra_bits = i & 15;
+
+ int bits_to_fetch = code_size;
+ if (num_extra_bits)
+ {
+ int total_codesize = code_size + num_extra_bits;
+ if (total_codesize <= 8)
+ {
+ has_extrabits = true;
+ extra_bits = ((1 << num_extra_bits) - 1) & (code >> (8 - total_codesize));
+
+ if (extra_bits > 0x7FFF)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ bits_to_fetch += num_extra_bits;
+ }
+ }
+
+ if (!has_extrabits)
+ pH->look_up2[code] = i | (bits_to_fetch << 8);
+ else
+ pH->look_up2[code] = i | 0x8000 | (extra_bits << 16) | (bits_to_fetch << 8);
+
+ code++;
+ }
+ }
+ else
+ {
+ subtree = (code >> (code_size - 8)) & 0xFF;
+
+ currententry = pH->look_up[subtree];
+
+ if (currententry == 0)
+ {
+ pH->look_up[subtree] = currententry = nextfreeentry;
+ pH->look_up2[subtree] = currententry = nextfreeentry;
+
+ nextfreeentry -= 2;
+ }
+
+ code <<= (16 - (code_size - 8));
+
+ for (l = code_size; l > 9; l--)
+ {
+ if ((code & 0x8000) == 0)
+ currententry--;
+
+ unsigned int idx = -currententry - 1;
+
+ if (idx >= JPGD_HUFF_TREE_MAX_LENGTH)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ if (pH->tree[idx] == 0)
+ {
+ pH->tree[idx] = nextfreeentry;
+
+ currententry = nextfreeentry;
+
+ nextfreeentry -= 2;
+ }
+ else
+ {
+ currententry = pH->tree[idx];
+ }
+
+ code <<= 1;
+ }
+
+ if ((code & 0x8000) == 0)
+ currententry--;
+
+ if ((-currententry - 1) >= JPGD_HUFF_TREE_MAX_LENGTH)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ pH->tree[-currententry - 1] = i;
+ }
+
+ p++;
+ }
+ }
+
+ // Verifies the quantization tables needed for this scan are available.
+ void jpeg_decoder::check_quant_tables()
+ {
+ for (int i = 0; i < m_comps_in_scan; i++)
+ if (m_quant[m_comp_quant[m_comp_list[i]]] == nullptr)
+ stop_decoding(JPGD_UNDEFINED_QUANT_TABLE);
+ }
+
+ // Verifies that all the Huffman tables needed for this scan are available.
+ void jpeg_decoder::check_huff_tables()
+ {
+ for (int i = 0; i < m_comps_in_scan; i++)
+ {
+ if ((m_spectral_start == 0) && (m_huff_num[m_comp_dc_tab[m_comp_list[i]]] == nullptr))
+ stop_decoding(JPGD_UNDEFINED_HUFF_TABLE);
+
+ if ((m_spectral_end > 0) && (m_huff_num[m_comp_ac_tab[m_comp_list[i]]] == nullptr))
+ stop_decoding(JPGD_UNDEFINED_HUFF_TABLE);
+ }
+
+ for (int i = 0; i < JPGD_MAX_HUFF_TABLES; i++)
+ if (m_huff_num[i])
+ {
+ if (!m_pHuff_tabs[i])
+ m_pHuff_tabs[i] = (huff_tables*)alloc(sizeof(huff_tables));
+
+ make_huff_table(i, m_pHuff_tabs[i]);
+ }
+ }
+
+ // Determines the component order inside each MCU.
+ // Also calcs how many MCU's are on each row, etc.
+ bool jpeg_decoder::calc_mcu_block_order()
+ {
+ int component_num, component_id;
+ int max_h_samp = 0, max_v_samp = 0;
+
+ for (component_id = 0; component_id < m_comps_in_frame; component_id++)
+ {
+ if (m_comp_h_samp[component_id] > max_h_samp)
+ max_h_samp = m_comp_h_samp[component_id];
+
+ if (m_comp_v_samp[component_id] > max_v_samp)
+ max_v_samp = m_comp_v_samp[component_id];
+ }
+
+ for (component_id = 0; component_id < m_comps_in_frame; component_id++)
+ {
+ m_comp_h_blocks[component_id] = ((((m_image_x_size * m_comp_h_samp[component_id]) + (max_h_samp - 1)) / max_h_samp) + 7) / 8;
+ m_comp_v_blocks[component_id] = ((((m_image_y_size * m_comp_v_samp[component_id]) + (max_v_samp - 1)) / max_v_samp) + 7) / 8;
+ }
+
+ if (m_comps_in_scan == 1)
+ {
+ m_mcus_per_row = m_comp_h_blocks[m_comp_list[0]];
+ m_mcus_per_col = m_comp_v_blocks[m_comp_list[0]];
+ }
+ else
+ {
+ m_mcus_per_row = (((m_image_x_size + 7) / 8) + (max_h_samp - 1)) / max_h_samp;
+ m_mcus_per_col = (((m_image_y_size + 7) / 8) + (max_v_samp - 1)) / max_v_samp;
+ }
+
+ if (m_comps_in_scan == 1)
+ {
+ m_mcu_org[0] = m_comp_list[0];
+
+ m_blocks_per_mcu = 1;
+ }
+ else
+ {
+ m_blocks_per_mcu = 0;
+
+ for (component_num = 0; component_num < m_comps_in_scan; component_num++)
+ {
+ int num_blocks;
+
+ component_id = m_comp_list[component_num];
+
+ num_blocks = m_comp_h_samp[component_id] * m_comp_v_samp[component_id];
+
+ while (num_blocks--)
+ m_mcu_org[m_blocks_per_mcu++] = component_id;
+ }
+ }
+
+ if (m_blocks_per_mcu > m_max_blocks_per_mcu)
+ return false;
+
+ for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
+ {
+ int comp_id = m_mcu_org[mcu_block];
+ if (comp_id >= JPGD_MAX_QUANT_TABLES)
+ return false;
+ }
+
+ return true;
+ }
+
+ // Starts a new scan.
+ int jpeg_decoder::init_scan()
+ {
+ if (!locate_sos_marker())
+ return JPGD_FALSE;
+
+ if (!calc_mcu_block_order())
+ return JPGD_FALSE;
+
+ check_huff_tables();
+
+ check_quant_tables();
+
+ memset(m_last_dc_val, 0, m_comps_in_frame * sizeof(uint));
+
+ m_eob_run = 0;
+
+ if (m_restart_interval)
+ {
+ m_restarts_left = m_restart_interval;
+ m_next_restart_num = 0;
+ }
+
+ fix_in_buffer();
+
+ return JPGD_TRUE;
+ }
+
+ // Starts a frame. Determines if the number of components or sampling factors
+ // are supported.
+ void jpeg_decoder::init_frame()
+ {
+ int i;
+
+ if (m_comps_in_frame == 1)
+ {
+ if ((m_comp_h_samp[0] != 1) || (m_comp_v_samp[0] != 1))
+ stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
+
+ m_scan_type = JPGD_GRAYSCALE;
+ m_max_blocks_per_mcu = 1;
+ m_max_mcu_x_size = 8;
+ m_max_mcu_y_size = 8;
+ }
+ else if (m_comps_in_frame == 3)
+ {
+ if (((m_comp_h_samp[1] != 1) || (m_comp_v_samp[1] != 1)) ||
+ ((m_comp_h_samp[2] != 1) || (m_comp_v_samp[2] != 1)))
+ stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
+
+ if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1))
+ {
+ m_scan_type = JPGD_YH1V1;
+
+ m_max_blocks_per_mcu = 3;
+ m_max_mcu_x_size = 8;
+ m_max_mcu_y_size = 8;
+ }
+ else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1))
+ {
+ m_scan_type = JPGD_YH2V1;
+ m_max_blocks_per_mcu = 4;
+ m_max_mcu_x_size = 16;
+ m_max_mcu_y_size = 8;
+ }
+ else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 2))
+ {
+ m_scan_type = JPGD_YH1V2;
+ m_max_blocks_per_mcu = 4;
+ m_max_mcu_x_size = 8;
+ m_max_mcu_y_size = 16;
+ }
+ else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2))
+ {
+ m_scan_type = JPGD_YH2V2;
+ m_max_blocks_per_mcu = 6;
+ m_max_mcu_x_size = 16;
+ m_max_mcu_y_size = 16;
+ }
+ else
+ stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
+ }
+ else
+ stop_decoding(JPGD_UNSUPPORTED_COLORSPACE);
+
+ m_max_mcus_per_row = (m_image_x_size + (m_max_mcu_x_size - 1)) / m_max_mcu_x_size;
+ m_max_mcus_per_col = (m_image_y_size + (m_max_mcu_y_size - 1)) / m_max_mcu_y_size;
+
+ // These values are for the *destination* pixels: after conversion.
+ if (m_scan_type == JPGD_GRAYSCALE)
+ m_dest_bytes_per_pixel = 1;
+ else
+ m_dest_bytes_per_pixel = 4;
+
+ m_dest_bytes_per_scan_line = ((m_image_x_size + 15) & 0xFFF0) * m_dest_bytes_per_pixel;
+
+ m_real_dest_bytes_per_scan_line = (m_image_x_size * m_dest_bytes_per_pixel);
+
+ // Initialize two scan line buffers.
+ m_pScan_line_0 = (uint8*)alloc_aligned(m_dest_bytes_per_scan_line, true);
+ if ((m_scan_type == JPGD_YH1V2) || (m_scan_type == JPGD_YH2V2))
+ m_pScan_line_1 = (uint8*)alloc_aligned(m_dest_bytes_per_scan_line, true);
+
+ m_max_blocks_per_row = m_max_mcus_per_row * m_max_blocks_per_mcu;
+
+ // Should never happen
+ if (m_max_blocks_per_row > JPGD_MAX_BLOCKS_PER_ROW)
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ // Allocate the coefficient buffer, enough for one MCU
+ m_pMCU_coefficients = (jpgd_block_coeff_t *)alloc_aligned(m_max_blocks_per_mcu * 64 * sizeof(jpgd_block_coeff_t));
+
+ for (i = 0; i < m_max_blocks_per_mcu; i++)
+ m_mcu_block_max_zag[i] = 64;
+
+ m_pSample_buf = (uint8*)alloc_aligned(m_max_blocks_per_row * 64);
+ m_pSample_buf_prev = (uint8*)alloc_aligned(m_max_blocks_per_row * 64);
+
+ m_total_lines_left = m_image_y_size;
+
+ m_mcu_lines_left = 0;
+
+ create_look_ups();
+ }
+
+ // The coeff_buf series of methods originally stored the coefficients
+ // into a "virtual" file which was located in EMS, XMS, or a disk file. A cache
+ // was used to make this process more efficient. Now, we can store the entire
+ // thing in RAM.
+ jpeg_decoder::coeff_buf* jpeg_decoder::coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y)
+ {
+ coeff_buf* cb = (coeff_buf*)alloc(sizeof(coeff_buf));
+
+ cb->block_num_x = block_num_x;
+ cb->block_num_y = block_num_y;
+ cb->block_len_x = block_len_x;
+ cb->block_len_y = block_len_y;
+ cb->block_size = (block_len_x * block_len_y) * sizeof(jpgd_block_coeff_t);
+ cb->pData = (uint8*)alloc(cb->block_size * block_num_x * block_num_y, true);
+ return cb;
+ }
+
+ inline jpgd_block_coeff_t* jpeg_decoder::coeff_buf_getp(coeff_buf* cb, int block_x, int block_y)
+ {
+ if ((block_x >= cb->block_num_x) || (block_y >= cb->block_num_y))
+ stop_decoding(JPGD_DECODE_ERROR);
+
+ return (jpgd_block_coeff_t*)(cb->pData + block_x * cb->block_size + block_y * (cb->block_size * cb->block_num_x));
+ }
+
+ // The following methods decode the various types of m_blocks encountered
+ // in progressively encoded images.
+ void jpeg_decoder::decode_block_dc_first(jpeg_decoder* pD, int component_id, int block_x, int block_y)
+ {
+ int s, r;
+ jpgd_block_coeff_t* p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y);
+
+ if ((s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_dc_tab[component_id]])) != 0)
+ {
+ if (s >= 16)
+ pD->stop_decoding(JPGD_DECODE_ERROR);
+
+ r = pD->get_bits_no_markers(s);
+ s = JPGD_HUFF_EXTEND(r, s);
+ }
+
+ pD->m_last_dc_val[component_id] = (s += pD->m_last_dc_val[component_id]);
+
+ p[0] = static_cast<jpgd_block_coeff_t>(s << pD->m_successive_low);
+ }
+
+ void jpeg_decoder::decode_block_dc_refine(jpeg_decoder* pD, int component_id, int block_x, int block_y)
+ {
+ if (pD->get_bits_no_markers(1))
+ {
+ jpgd_block_coeff_t* p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y);
+
+ p[0] |= (1 << pD->m_successive_low);
+ }
+ }
+
+ void jpeg_decoder::decode_block_ac_first(jpeg_decoder* pD, int component_id, int block_x, int block_y)
+ {
+ int k, s, r;
+
+ if (pD->m_eob_run)
+ {
+ pD->m_eob_run--;
+ return;
+ }
+
+ jpgd_block_coeff_t* p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
+
+ for (k = pD->m_spectral_start; k <= pD->m_spectral_end; k++)
+ {
+ unsigned int idx = pD->m_comp_ac_tab[component_id];
+ if (idx >= JPGD_MAX_HUFF_TABLES)
+ pD->stop_decoding(JPGD_DECODE_ERROR);
+
+ s = pD->huff_decode(pD->m_pHuff_tabs[idx]);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s)
+ {
+ if ((k += r) > 63)
+ pD->stop_decoding(JPGD_DECODE_ERROR);
+
+ r = pD->get_bits_no_markers(s);
+ s = JPGD_HUFF_EXTEND(r, s);
+
+ p[g_ZAG[k]] = static_cast<jpgd_block_coeff_t>(s << pD->m_successive_low);
+ }
+ else
+ {
+ if (r == 15)
+ {
+ if ((k += 15) > 63)
+ pD->stop_decoding(JPGD_DECODE_ERROR);
+ }
+ else
+ {
+ pD->m_eob_run = 1 << r;
+
+ if (r)
+ pD->m_eob_run += pD->get_bits_no_markers(r);
+
+ pD->m_eob_run--;
+
+ break;
+ }
+ }
+ }
+ }
+
+ void jpeg_decoder::decode_block_ac_refine(jpeg_decoder* pD, int component_id, int block_x, int block_y)
+ {
+ int s, k, r;
+
+ int p1 = 1 << pD->m_successive_low;
+
+ //int m1 = (-1) << pD->m_successive_low;
+ int m1 = static_cast<int>((UINT32_MAX << pD->m_successive_low));
+
+ jpgd_block_coeff_t* p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
+ if (pD->m_spectral_end > 63)
+ pD->stop_decoding(JPGD_DECODE_ERROR);
+
+ k = pD->m_spectral_start;
+
+ if (pD->m_eob_run == 0)
+ {
+ for (; k <= pD->m_spectral_end; k++)
+ {
+ unsigned int idx = pD->m_comp_ac_tab[component_id];
+ if (idx >= JPGD_MAX_HUFF_TABLES)
+ pD->stop_decoding(JPGD_DECODE_ERROR);
+
+ s = pD->huff_decode(pD->m_pHuff_tabs[idx]);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s)
+ {
+ if (s != 1)
+ pD->stop_decoding(JPGD_DECODE_ERROR);
+
+ if (pD->get_bits_no_markers(1))
+ s = p1;
+ else
+ s = m1;
+ }
+ else
+ {
+ if (r != 15)
+ {
+ pD->m_eob_run = 1 << r;
+
+ if (r)
+ pD->m_eob_run += pD->get_bits_no_markers(r);
+
+ break;
+ }
+ }
+
+ do
+ {
+ jpgd_block_coeff_t* this_coef = p + g_ZAG[k & 63];
+
+ if (*this_coef != 0)
+ {
+ if (pD->get_bits_no_markers(1))
+ {
+ if ((*this_coef & p1) == 0)
+ {
+ if (*this_coef >= 0)
+ *this_coef = static_cast<jpgd_block_coeff_t>(*this_coef + p1);
+ else
+ *this_coef = static_cast<jpgd_block_coeff_t>(*this_coef + m1);
+ }
+ }
+ }
+ else
+ {
+ if (--r < 0)
+ break;
+ }
+
+ k++;
+
+ } while (k <= pD->m_spectral_end);
+
+ if ((s) && (k < 64))
+ {
+ p[g_ZAG[k]] = static_cast<jpgd_block_coeff_t>(s);
+ }
+ }
+ }
+
+ if (pD->m_eob_run > 0)
+ {
+ for (; k <= pD->m_spectral_end; k++)
+ {
+ jpgd_block_coeff_t* this_coef = p + g_ZAG[k & 63]; // logical AND to shut up static code analysis
+
+ if (*this_coef != 0)
+ {
+ if (pD->get_bits_no_markers(1))
+ {
+ if ((*this_coef & p1) == 0)
+ {
+ if (*this_coef >= 0)
+ *this_coef = static_cast<jpgd_block_coeff_t>(*this_coef + p1);
+ else
+ *this_coef = static_cast<jpgd_block_coeff_t>(*this_coef + m1);
+ }
+ }
+ }
+ }
+
+ pD->m_eob_run--;
+ }
+ }
+
+ // Decode a scan in a progressively encoded image.
+ void jpeg_decoder::decode_scan(pDecode_block_func decode_block_func)
+ {
+ int mcu_row, mcu_col, mcu_block;
+ int block_x_mcu[JPGD_MAX_COMPONENTS], block_y_mcu[JPGD_MAX_COMPONENTS];
+
+ memset(block_y_mcu, 0, sizeof(block_y_mcu));
+
+ for (mcu_col = 0; mcu_col < m_mcus_per_col; mcu_col++)
+ {
+ int component_num, component_id;
+
+ memset(block_x_mcu, 0, sizeof(block_x_mcu));
+
+ for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
+ {
+ int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0;
+
+ if ((m_restart_interval) && (m_restarts_left == 0))
+ process_restart();
+
+ for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
+ {
+ component_id = m_mcu_org[mcu_block];
+
+ decode_block_func(this, component_id, block_x_mcu[component_id] + block_x_mcu_ofs, block_y_mcu[component_id] + block_y_mcu_ofs);
+
+ if (m_comps_in_scan == 1)
+ block_x_mcu[component_id]++;
+ else
+ {
+ if (++block_x_mcu_ofs == m_comp_h_samp[component_id])
+ {
+ block_x_mcu_ofs = 0;
+
+ if (++block_y_mcu_ofs == m_comp_v_samp[component_id])
+ {
+ block_y_mcu_ofs = 0;
+ block_x_mcu[component_id] += m_comp_h_samp[component_id];
+ }
+ }
+ }
+ }
+
+ m_restarts_left--;
+ }
+
+ if (m_comps_in_scan == 1)
+ block_y_mcu[m_comp_list[0]]++;
+ else
+ {
+ for (component_num = 0; component_num < m_comps_in_scan; component_num++)
+ {
+ component_id = m_comp_list[component_num];
+ block_y_mcu[component_id] += m_comp_v_samp[component_id];
+ }
+ }
+ }
+ }
+
+ // Decode a progressively encoded image.
+ void jpeg_decoder::init_progressive()
+ {
+ int i;
+
+ if (m_comps_in_frame == 4)
+ stop_decoding(JPGD_UNSUPPORTED_COLORSPACE);
+
+ // Allocate the coefficient buffers.
+ for (i = 0; i < m_comps_in_frame; i++)
+ {
+ m_dc_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 1, 1);
+ m_ac_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 8, 8);
+ }
+
+ // See https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf
+ uint32_t total_scans = 0;
+ const uint32_t MAX_SCANS_TO_PROCESS = 1000;
+
+ for (; ; )
+ {
+ int dc_only_scan, refinement_scan;
+ pDecode_block_func decode_block_func;
+
+ if (!init_scan())
+ break;
+
+ dc_only_scan = (m_spectral_start == 0);
+ refinement_scan = (m_successive_high != 0);
+
+ if ((m_spectral_start > m_spectral_end) || (m_spectral_end > 63))
+ stop_decoding(JPGD_BAD_SOS_SPECTRAL);
+
+ if (dc_only_scan)
+ {
+ if (m_spectral_end)
+ stop_decoding(JPGD_BAD_SOS_SPECTRAL);
+ }
+ else if (m_comps_in_scan != 1) /* AC scans can only contain one component */
+ stop_decoding(JPGD_BAD_SOS_SPECTRAL);
+
+ if ((refinement_scan) && (m_successive_low != m_successive_high - 1))
+ stop_decoding(JPGD_BAD_SOS_SUCCESSIVE);
+
+ if (dc_only_scan)
+ {
+ if (refinement_scan)
+ decode_block_func = decode_block_dc_refine;
+ else
+ decode_block_func = decode_block_dc_first;
+ }
+ else
+ {
+ if (refinement_scan)
+ decode_block_func = decode_block_ac_refine;
+ else
+ decode_block_func = decode_block_ac_first;
+ }
+
+ decode_scan(decode_block_func);
+
+ m_bits_left = 16;
+ get_bits(16);
+ get_bits(16);
+
+ total_scans++;
+ if (total_scans > MAX_SCANS_TO_PROCESS)
+ stop_decoding(JPGD_TOO_MANY_SCANS);
+ }
+
+ m_comps_in_scan = m_comps_in_frame;
+
+ for (i = 0; i < m_comps_in_frame; i++)
+ m_comp_list[i] = i;
+
+ if (!calc_mcu_block_order())
+ stop_decoding(JPGD_DECODE_ERROR);
+ }
+
+ void jpeg_decoder::init_sequential()
+ {
+ if (!init_scan())
+ stop_decoding(JPGD_UNEXPECTED_MARKER);
+ }
+
+ void jpeg_decoder::decode_start()
+ {
+ init_frame();
+
+ if (m_progressive_flag)
+ init_progressive();
+ else
+ init_sequential();
+ }
+
+ void jpeg_decoder::decode_init(jpeg_decoder_stream* pStream, uint32_t flags)
+ {
+ init(pStream, flags);
+ locate_sof_marker();
+ }
+
+ jpeg_decoder::jpeg_decoder(jpeg_decoder_stream* pStream, uint32_t flags)
+ {
+ if (::setjmp(m_jmp_state))
+ return;
+ decode_init(pStream, flags);
+ }
+
+ int jpeg_decoder::begin_decoding()
+ {
+ if (m_ready_flag)
+ return JPGD_SUCCESS;
+
+ if (m_error_code)
+ return JPGD_FAILED;
+
+ if (::setjmp(m_jmp_state))
+ return JPGD_FAILED;
+
+ decode_start();
+
+ m_ready_flag = true;
+
+ return JPGD_SUCCESS;
+ }
+
+ jpeg_decoder::~jpeg_decoder()
+ {
+ free_all_blocks();
+ }
+
+ jpeg_decoder_file_stream::jpeg_decoder_file_stream()
+ {
+ m_pFile = nullptr;
+ m_eof_flag = false;
+ m_error_flag = false;
+ }
+
+ void jpeg_decoder_file_stream::close()
+ {
+ if (m_pFile)
+ {
+ fclose(m_pFile);
+ m_pFile = nullptr;
+ }
+
+ m_eof_flag = false;
+ m_error_flag = false;
+ }
+
+ jpeg_decoder_file_stream::~jpeg_decoder_file_stream()
+ {
+ close();
+ }
+
+ bool jpeg_decoder_file_stream::open(const char* Pfilename)
+ {
+ close();
+
+ m_eof_flag = false;
+ m_error_flag = false;
#if defined(_MSC_VER)
- m_pFile = NULL;
- fopen_s(&m_pFile, Pfilename, "rb");
+ m_pFile = nullptr;
+ fopen_s(&m_pFile, Pfilename, "rb");
#else
- m_pFile = fopen(Pfilename, "rb");
+ m_pFile = fopen(Pfilename, "rb");
#endif
- return m_pFile != NULL;
-}
-
-int jpeg_decoder_file_stream::read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag)
-{
- if (!m_pFile)
- return -1;
-
- if (m_eof_flag)
- {
- *pEOF_flag = true;
- return 0;
- }
-
- if (m_error_flag)
- return -1;
-
- int bytes_read = static_cast<int>(fread(pBuf, 1, max_bytes_to_read, m_pFile));
- if (bytes_read < max_bytes_to_read)
- {
- if (ferror(m_pFile))
- {
- m_error_flag = true;
- return -1;
- }
-
- m_eof_flag = true;
- *pEOF_flag = true;
- }
-
- return bytes_read;
-}
-
-bool jpeg_decoder_mem_stream::open(const uint8 *pSrc_data, uint size)
-{
- close();
- m_pSrc_data = pSrc_data;
- m_ofs = 0;
- m_size = size;
- return true;
-}
-
-int jpeg_decoder_mem_stream::read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag)
-{
- *pEOF_flag = false;
-
- if (!m_pSrc_data)
- return -1;
-
- uint bytes_remaining = m_size - m_ofs;
- if ((uint)max_bytes_to_read > bytes_remaining)
- {
- max_bytes_to_read = bytes_remaining;
- *pEOF_flag = true;
- }
-
- memcpy(pBuf, m_pSrc_data + m_ofs, max_bytes_to_read);
- m_ofs += max_bytes_to_read;
-
- return max_bytes_to_read;
-}
-
-unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps)
-{
- if (!actual_comps)
- return NULL;
- *actual_comps = 0;
-
- if ((!pStream) || (!width) || (!height) || (!req_comps))
- return NULL;
-
- if ((req_comps != 1) && (req_comps != 3) && (req_comps != 4))
- return NULL;
-
- jpeg_decoder decoder(pStream);
- if (decoder.get_error_code() != JPGD_SUCCESS)
- return NULL;
-
- const int image_width = decoder.get_width(), image_height = decoder.get_height();
- *width = image_width;
- *height = image_height;
- *actual_comps = decoder.get_num_components();
-
- if (decoder.begin_decoding() != JPGD_SUCCESS)
- return NULL;
-
- const int dst_bpl = image_width * req_comps;
-
- uint8 *pImage_data = (uint8*)jpgd_malloc(dst_bpl * image_height);
- if (!pImage_data)
- return NULL;
-
- for (int y = 0; y < image_height; y++)
- {
- const uint8* pScan_line;
- uint scan_line_len;
- if (decoder.decode((const void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS)
- {
- jpgd_free(pImage_data);
- return NULL;
- }
-
- uint8 *pDst = pImage_data + y * dst_bpl;
-
- if (((req_comps == 1) && (decoder.get_num_components() == 1)) || ((req_comps == 4) && (decoder.get_num_components() == 3)))
- memcpy(pDst, pScan_line, dst_bpl);
- else if (decoder.get_num_components() == 1)
- {
- if (req_comps == 3)
- {
- for (int x = 0; x < image_width; x++)
- {
- uint8 luma = pScan_line[x];
- pDst[0] = luma;
- pDst[1] = luma;
- pDst[2] = luma;
- pDst += 3;
- }
- }
- else
- {
- for (int x = 0; x < image_width; x++)
- {
- uint8 luma = pScan_line[x];
- pDst[0] = luma;
- pDst[1] = luma;
- pDst[2] = luma;
- pDst[3] = 255;
- pDst += 4;
- }
- }
- }
- else if (decoder.get_num_components() == 3)
- {
- if (req_comps == 1)
- {
- const int YR = 19595, YG = 38470, YB = 7471;
- for (int x = 0; x < image_width; x++)
- {
- int r = pScan_line[x*4+0];
- int g = pScan_line[x*4+1];
- int b = pScan_line[x*4+2];
- *pDst++ = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
- }
- }
- else
- {
- for (int x = 0; x < image_width; x++)
- {
- pDst[0] = pScan_line[x*4+0];
- pDst[1] = pScan_line[x*4+1];
- pDst[2] = pScan_line[x*4+2];
- pDst += 3;
- }
- }
- }
- }
-
- return pImage_data;
-}
-
-unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps)
-{
- jpgd::jpeg_decoder_mem_stream mem_stream(pSrc_data, src_data_size);
- return decompress_jpeg_image_from_stream(&mem_stream, width, height, actual_comps, req_comps);
-}
-
-unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps)
-{
- jpgd::jpeg_decoder_file_stream file_stream;
- if (!file_stream.open(pSrc_filename))
- return NULL;
- return decompress_jpeg_image_from_stream(&file_stream, width, height, actual_comps, req_comps);
-}
-
-} // namespace jpgd \ No newline at end of file
+ return m_pFile != nullptr;
+ }
+
+ int jpeg_decoder_file_stream::read(uint8* pBuf, int max_bytes_to_read, bool* pEOF_flag)
+ {
+ if (!m_pFile)
+ return -1;
+
+ if (m_eof_flag)
+ {
+ *pEOF_flag = true;
+ return 0;
+ }
+
+ if (m_error_flag)
+ return -1;
+
+ int bytes_read = static_cast<int>(fread(pBuf, 1, max_bytes_to_read, m_pFile));
+ if (bytes_read < max_bytes_to_read)
+ {
+ if (ferror(m_pFile))
+ {
+ m_error_flag = true;
+ return -1;
+ }
+
+ m_eof_flag = true;
+ *pEOF_flag = true;
+ }
+
+ return bytes_read;
+ }
+
+ bool jpeg_decoder_mem_stream::open(const uint8* pSrc_data, uint size)
+ {
+ close();
+ m_pSrc_data = pSrc_data;
+ m_ofs = 0;
+ m_size = size;
+ return true;
+ }
+
+ int jpeg_decoder_mem_stream::read(uint8* pBuf, int max_bytes_to_read, bool* pEOF_flag)
+ {
+ *pEOF_flag = false;
+
+ if (!m_pSrc_data)
+ return -1;
+
+ uint bytes_remaining = m_size - m_ofs;
+ if ((uint)max_bytes_to_read > bytes_remaining)
+ {
+ max_bytes_to_read = bytes_remaining;
+ *pEOF_flag = true;
+ }
+
+ memcpy(pBuf, m_pSrc_data + m_ofs, max_bytes_to_read);
+ m_ofs += max_bytes_to_read;
+
+ return max_bytes_to_read;
+ }
+
+ unsigned char* decompress_jpeg_image_from_stream(jpeg_decoder_stream* pStream, int* width, int* height, int* actual_comps, int req_comps, uint32_t flags)
+ {
+ if (!actual_comps)
+ return nullptr;
+ *actual_comps = 0;
+
+ if ((!pStream) || (!width) || (!height) || (!req_comps))
+ return nullptr;
+
+ if ((req_comps != 1) && (req_comps != 3) && (req_comps != 4))
+ return nullptr;
+
+ jpeg_decoder decoder(pStream, flags);
+ if (decoder.get_error_code() != JPGD_SUCCESS)
+ return nullptr;
+
+ const int image_width = decoder.get_width(), image_height = decoder.get_height();
+ *width = image_width;
+ *height = image_height;
+ *actual_comps = decoder.get_num_components();
+
+ if (decoder.begin_decoding() != JPGD_SUCCESS)
+ return nullptr;
+
+ const int dst_bpl = image_width * req_comps;
+
+ uint8* pImage_data = (uint8*)jpgd_malloc(dst_bpl * image_height);
+ if (!pImage_data)
+ return nullptr;
+
+ for (int y = 0; y < image_height; y++)
+ {
+ const uint8* pScan_line;
+ uint scan_line_len;
+ if (decoder.decode((const void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS)
+ {
+ jpgd_free(pImage_data);
+ return nullptr;
+ }
+
+ uint8* pDst = pImage_data + y * dst_bpl;
+
+ if (((req_comps == 1) && (decoder.get_num_components() == 1)) || ((req_comps == 4) && (decoder.get_num_components() == 3)))
+ memcpy(pDst, pScan_line, dst_bpl);
+ else if (decoder.get_num_components() == 1)
+ {
+ if (req_comps == 3)
+ {
+ for (int x = 0; x < image_width; x++)
+ {
+ uint8 luma = pScan_line[x];
+ pDst[0] = luma;
+ pDst[1] = luma;
+ pDst[2] = luma;
+ pDst += 3;
+ }
+ }
+ else
+ {
+ for (int x = 0; x < image_width; x++)
+ {
+ uint8 luma = pScan_line[x];
+ pDst[0] = luma;
+ pDst[1] = luma;
+ pDst[2] = luma;
+ pDst[3] = 255;
+ pDst += 4;
+ }
+ }
+ }
+ else if (decoder.get_num_components() == 3)
+ {
+ if (req_comps == 1)
+ {
+ const int YR = 19595, YG = 38470, YB = 7471;
+ for (int x = 0; x < image_width; x++)
+ {
+ int r = pScan_line[x * 4 + 0];
+ int g = pScan_line[x * 4 + 1];
+ int b = pScan_line[x * 4 + 2];
+ *pDst++ = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
+ }
+ }
+ else
+ {
+ for (int x = 0; x < image_width; x++)
+ {
+ pDst[0] = pScan_line[x * 4 + 0];
+ pDst[1] = pScan_line[x * 4 + 1];
+ pDst[2] = pScan_line[x * 4 + 2];
+ pDst += 3;
+ }
+ }
+ }
+ }
+
+ return pImage_data;
+ }
+
+ unsigned char* decompress_jpeg_image_from_memory(const unsigned char* pSrc_data, int src_data_size, int* width, int* height, int* actual_comps, int req_comps, uint32_t flags)
+ {
+ jpgd::jpeg_decoder_mem_stream mem_stream(pSrc_data, src_data_size);
+ return decompress_jpeg_image_from_stream(&mem_stream, width, height, actual_comps, req_comps, flags);
+ }
+
+ unsigned char* decompress_jpeg_image_from_file(const char* pSrc_filename, int* width, int* height, int* actual_comps, int req_comps, uint32_t flags)
+ {
+ jpgd::jpeg_decoder_file_stream file_stream;
+ if (!file_stream.open(pSrc_filename))
+ return nullptr;
+ return decompress_jpeg_image_from_stream(&file_stream, width, height, actual_comps, req_comps, flags);
+ }
+
+} // namespace jpgd
diff --git a/thirdparty/jpeg-compressor/jpgd.h b/thirdparty/jpeg-compressor/jpgd.h
index 150b9a0b26..39136696ba 100644
--- a/thirdparty/jpeg-compressor/jpgd.h
+++ b/thirdparty/jpeg-compressor/jpgd.h
@@ -1,319 +1,351 @@
// jpgd.h - C++ class for JPEG decompression.
-// Public domain, Rich Geldreich <richgel99@gmail.com>
+// Richard Geldreich <richgel99@gmail.com>
+// See jpgd.cpp for license (Public Domain or Apache 2.0).
#ifndef JPEG_DECODER_H
#define JPEG_DECODER_H
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
+#include <assert.h>
+#include <stdint.h>
#ifdef _MSC_VER
- #define JPGD_NORETURN __declspec(noreturn)
+#define JPGD_NORETURN __declspec(noreturn)
#elif defined(__GNUC__)
- #define JPGD_NORETURN __attribute__ ((noreturn))
+#define JPGD_NORETURN __attribute__ ((noreturn))
#else
- #define JPGD_NORETURN
+#define JPGD_NORETURN
#endif
+#define JPGD_HUFF_TREE_MAX_LENGTH 512
+#define JPGD_HUFF_CODE_SIZE_MAX_LENGTH 256
+
namespace jpgd
{
- typedef unsigned char uint8;
- typedef signed short int16;
- typedef unsigned short uint16;
- typedef unsigned int uint;
- typedef signed int int32;
-
- // Loads a JPEG image from a memory buffer or a file.
- // req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA).
- // On return, width/height will be set to the image's dimensions, and actual_comps will be set to the either 1 (grayscale) or 3 (RGB).
- // Notes: For more control over where and how the source data is read, see the decompress_jpeg_image_from_stream() function below, or call the jpeg_decoder class directly.
- // Requesting a 8 or 32bpp image is currently a little faster than 24bpp because the jpeg_decoder class itself currently always unpacks to either 8 or 32bpp.
- unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps);
- unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps);
-
- // Success/failure error codes.
- enum jpgd_status
- {
- JPGD_SUCCESS = 0, JPGD_FAILED = -1, JPGD_DONE = 1,
- JPGD_BAD_DHT_COUNTS = -256, JPGD_BAD_DHT_INDEX, JPGD_BAD_DHT_MARKER, JPGD_BAD_DQT_MARKER, JPGD_BAD_DQT_TABLE,
- JPGD_BAD_PRECISION, JPGD_BAD_HEIGHT, JPGD_BAD_WIDTH, JPGD_TOO_MANY_COMPONENTS,
- JPGD_BAD_SOF_LENGTH, JPGD_BAD_VARIABLE_MARKER, JPGD_BAD_DRI_LENGTH, JPGD_BAD_SOS_LENGTH,
- JPGD_BAD_SOS_COMP_ID, JPGD_W_EXTRA_BYTES_BEFORE_MARKER, JPGD_NO_ARITHMITIC_SUPPORT, JPGD_UNEXPECTED_MARKER,
- JPGD_NOT_JPEG, JPGD_UNSUPPORTED_MARKER, JPGD_BAD_DQT_LENGTH, JPGD_TOO_MANY_BLOCKS,
- JPGD_UNDEFINED_QUANT_TABLE, JPGD_UNDEFINED_HUFF_TABLE, JPGD_NOT_SINGLE_SCAN, JPGD_UNSUPPORTED_COLORSPACE,
- JPGD_UNSUPPORTED_SAMP_FACTORS, JPGD_DECODE_ERROR, JPGD_BAD_RESTART_MARKER, JPGD_ASSERTION_ERROR,
- JPGD_BAD_SOS_SPECTRAL, JPGD_BAD_SOS_SUCCESSIVE, JPGD_STREAM_READ, JPGD_NOTENOUGHMEM
- };
-
- // Input stream interface.
- // Derive from this class to read input data from sources other than files or memory. Set m_eof_flag to true when no more data is available.
- // The decoder is rather greedy: it will keep on calling this method until its internal input buffer is full, or until the EOF flag is set.
- // It the input stream contains data after the JPEG stream's EOI (end of image) marker it will probably be pulled into the internal buffer.
- // Call the get_total_bytes_read() method to determine the actual size of the JPEG stream after successful decoding.
- class jpeg_decoder_stream
- {
- public:
- jpeg_decoder_stream() { }
- virtual ~jpeg_decoder_stream() { }
-
- // The read() method is called when the internal input buffer is empty.
- // Parameters:
- // pBuf - input buffer
- // max_bytes_to_read - maximum bytes that can be written to pBuf
- // pEOF_flag - set this to true if at end of stream (no more bytes remaining)
- // Returns -1 on error, otherwise return the number of bytes actually written to the buffer (which may be 0).
- // Notes: This method will be called in a loop until you set *pEOF_flag to true or the internal buffer is full.
- virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag) = 0;
- };
-
- // stdio FILE stream class.
- class jpeg_decoder_file_stream : public jpeg_decoder_stream
- {
- jpeg_decoder_file_stream(const jpeg_decoder_file_stream &);
- jpeg_decoder_file_stream &operator =(const jpeg_decoder_file_stream &);
-
- FILE *m_pFile;
- bool m_eof_flag, m_error_flag;
-
- public:
- jpeg_decoder_file_stream();
- virtual ~jpeg_decoder_file_stream();
-
- bool open(const char *Pfilename);
- void close();
-
- virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag);
- };
-
- // Memory stream class.
- class jpeg_decoder_mem_stream : public jpeg_decoder_stream
- {
- const uint8 *m_pSrc_data;
- uint m_ofs, m_size;
-
- public:
- jpeg_decoder_mem_stream() : m_pSrc_data(NULL), m_ofs(0), m_size(0) { }
- jpeg_decoder_mem_stream(const uint8 *pSrc_data, uint size) : m_pSrc_data(pSrc_data), m_ofs(0), m_size(size) { }
-
- virtual ~jpeg_decoder_mem_stream() { }
-
- bool open(const uint8 *pSrc_data, uint size);
- void close() { m_pSrc_data = NULL; m_ofs = 0; m_size = 0; }
-
- virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag);
- };
-
- // Loads JPEG file from a jpeg_decoder_stream.
- unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps);
-
- enum
- {
- JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4,
- JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384
- };
-
- typedef int16 jpgd_quant_t;
- typedef int16 jpgd_block_t;
-
- class jpeg_decoder
- {
- public:
- // Call get_error_code() after constructing to determine if the stream is valid or not. You may call the get_width(), get_height(), etc.
- // methods after the constructor is called. You may then either destruct the object, or begin decoding the image by calling begin_decoding(), then decode() on each scanline.
- jpeg_decoder(jpeg_decoder_stream *pStream);
-
- ~jpeg_decoder();
-
- // Call this method after constructing the object to begin decompression.
- // If JPGD_SUCCESS is returned you may then call decode() on each scanline.
- int begin_decoding();
-
- // Returns the next scan line.
- // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1).
- // Otherwise, it will always point to a buffer containing 32-bit RGBA pixels (A will always be 255, and get_bytes_per_pixel() will return 4).
- // Returns JPGD_SUCCESS if a scan line has been returned.
- // Returns JPGD_DONE if all scan lines have been returned.
- // Returns JPGD_FAILED if an error occurred. Call get_error_code() for a more info.
- int decode(const void** pScan_line, uint* pScan_line_len);
-
- inline jpgd_status get_error_code() const { return m_error_code; }
-
- inline int get_width() const { return m_image_x_size; }
- inline int get_height() const { return m_image_y_size; }
-
- inline int get_num_components() const { return m_comps_in_frame; }
-
- inline int get_bytes_per_pixel() const { return m_dest_bytes_per_pixel; }
- inline int get_bytes_per_scan_line() const { return m_image_x_size * get_bytes_per_pixel(); }
-
- // Returns the total number of bytes actually consumed by the decoder (which should equal the actual size of the JPEG file).
- inline int get_total_bytes_read() const { return m_total_bytes_read; }
-
- private:
- jpeg_decoder(const jpeg_decoder &);
- jpeg_decoder &operator =(const jpeg_decoder &);
-
- typedef void (*pDecode_block_func)(jpeg_decoder *, int, int, int);
-
- struct huff_tables
- {
- bool ac_table;
- uint look_up[256];
- uint look_up2[256];
- uint8 code_size[256];
- uint tree[512];
- };
-
- struct coeff_buf
- {
- uint8 *pData;
- int block_num_x, block_num_y;
- int block_len_x, block_len_y;
- int block_size;
- };
-
- struct mem_block
- {
- mem_block *m_pNext;
- size_t m_used_count;
- size_t m_size;
- char m_data[1];
- };
-
- jmp_buf m_jmp_state;
- mem_block *m_pMem_blocks;
- int m_image_x_size;
- int m_image_y_size;
- jpeg_decoder_stream *m_pStream;
- int m_progressive_flag;
- uint8 m_huff_ac[JPGD_MAX_HUFF_TABLES];
- uint8* m_huff_num[JPGD_MAX_HUFF_TABLES]; // pointer to number of Huffman codes per bit size
- uint8* m_huff_val[JPGD_MAX_HUFF_TABLES]; // pointer to Huffman codes per bit size
- jpgd_quant_t* m_quant[JPGD_MAX_QUANT_TABLES]; // pointer to quantization tables
- int m_scan_type; // Gray, Yh1v1, Yh1v2, Yh2v1, Yh2v2 (CMYK111, CMYK4114 no longer supported)
- int m_comps_in_frame; // # of components in frame
- int m_comp_h_samp[JPGD_MAX_COMPONENTS]; // component's horizontal sampling factor
- int m_comp_v_samp[JPGD_MAX_COMPONENTS]; // component's vertical sampling factor
- int m_comp_quant[JPGD_MAX_COMPONENTS]; // component's quantization table selector
- int m_comp_ident[JPGD_MAX_COMPONENTS]; // component's ID
- int m_comp_h_blocks[JPGD_MAX_COMPONENTS];
- int m_comp_v_blocks[JPGD_MAX_COMPONENTS];
- int m_comps_in_scan; // # of components in scan
- int m_comp_list[JPGD_MAX_COMPS_IN_SCAN]; // components in this scan
- int m_comp_dc_tab[JPGD_MAX_COMPONENTS]; // component's DC Huffman coding table selector
- int m_comp_ac_tab[JPGD_MAX_COMPONENTS]; // component's AC Huffman coding table selector
- int m_spectral_start; // spectral selection start
- int m_spectral_end; // spectral selection end
- int m_successive_low; // successive approximation low
- int m_successive_high; // successive approximation high
- int m_max_mcu_x_size; // MCU's max. X size in pixels
- int m_max_mcu_y_size; // MCU's max. Y size in pixels
- int m_blocks_per_mcu;
- int m_max_blocks_per_row;
- int m_mcus_per_row, m_mcus_per_col;
- int m_mcu_org[JPGD_MAX_BLOCKS_PER_MCU];
- int m_total_lines_left; // total # lines left in image
- int m_mcu_lines_left; // total # lines left in this MCU
- int m_real_dest_bytes_per_scan_line;
- int m_dest_bytes_per_scan_line; // rounded up
- int m_dest_bytes_per_pixel; // 4 (RGB) or 1 (Y)
- huff_tables* m_pHuff_tabs[JPGD_MAX_HUFF_TABLES];
- coeff_buf* m_dc_coeffs[JPGD_MAX_COMPONENTS];
- coeff_buf* m_ac_coeffs[JPGD_MAX_COMPONENTS];
- int m_eob_run;
- int m_block_y_mcu[JPGD_MAX_COMPONENTS];
- uint8* m_pIn_buf_ofs;
- int m_in_buf_left;
- int m_tem_flag;
- bool m_eof_flag;
- uint8 m_in_buf_pad_start[128];
- uint8 m_in_buf[JPGD_IN_BUF_SIZE + 128];
- uint8 m_in_buf_pad_end[128];
- int m_bits_left;
- uint m_bit_buf;
- int m_restart_interval;
- int m_restarts_left;
- int m_next_restart_num;
- int m_max_mcus_per_row;
- int m_max_blocks_per_mcu;
- int m_expanded_blocks_per_mcu;
- int m_expanded_blocks_per_row;
- int m_expanded_blocks_per_component;
- bool m_freq_domain_chroma_upsample;
- int m_max_mcus_per_col;
- uint m_last_dc_val[JPGD_MAX_COMPONENTS];
- jpgd_block_t* m_pMCU_coefficients;
- int m_mcu_block_max_zag[JPGD_MAX_BLOCKS_PER_MCU];
- uint8* m_pSample_buf;
- int m_crr[256];
- int m_cbb[256];
- int m_crg[256];
- int m_cbg[256];
- uint8* m_pScan_line_0;
- uint8* m_pScan_line_1;
- jpgd_status m_error_code;
- bool m_ready_flag;
- int m_total_bytes_read;
-
- void free_all_blocks();
- JPGD_NORETURN void stop_decoding(jpgd_status status);
- void *alloc(size_t n, bool zero = false);
- void word_clear(void *p, uint16 c, uint n);
- void prep_in_buffer();
- void read_dht_marker();
- void read_dqt_marker();
- void read_sof_marker();
- void skip_variable_marker();
- void read_dri_marker();
- void read_sos_marker();
- int next_marker();
- int process_markers();
- void locate_soi_marker();
- void locate_sof_marker();
- int locate_sos_marker();
- void init(jpeg_decoder_stream * pStream);
- void create_look_ups();
- void fix_in_buffer();
- void transform_mcu(int mcu_row);
- void transform_mcu_expand(int mcu_row);
- coeff_buf* coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y);
- inline jpgd_block_t *coeff_buf_getp(coeff_buf *cb, int block_x, int block_y);
- void load_next_row();
- void decode_next_row();
- void make_huff_table(int index, huff_tables *pH);
- void check_quant_tables();
- void check_huff_tables();
- void calc_mcu_block_order();
- int init_scan();
- void init_frame();
- void process_restart();
- void decode_scan(pDecode_block_func decode_block_func);
- void init_progressive();
- void init_sequential();
- void decode_start();
- void decode_init(jpeg_decoder_stream * pStream);
- void H2V2Convert();
- void H2V1Convert();
- void H1V2Convert();
- void H1V1Convert();
- void gray_convert();
- void expanded_convert();
- void find_eoi();
- inline uint get_char();
- inline uint get_char(bool *pPadding_flag);
- inline void stuff_char(uint8 q);
- inline uint8 get_octet();
- inline uint get_bits(int num_bits);
- inline uint get_bits_no_markers(int numbits);
- inline int huff_decode(huff_tables *pH);
- inline int huff_decode(huff_tables *pH, int& extrabits);
- static inline uint8 clamp(int i);
- static void decode_block_dc_first(jpeg_decoder *pD, int component_id, int block_x, int block_y);
- static void decode_block_dc_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y);
- static void decode_block_ac_first(jpeg_decoder *pD, int component_id, int block_x, int block_y);
- static void decode_block_ac_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y);
- };
-
+ typedef unsigned char uint8;
+ typedef signed short int16;
+ typedef unsigned short uint16;
+ typedef unsigned int uint;
+ typedef signed int int32;
+
+ // Loads a JPEG image from a memory buffer or a file.
+ // req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA).
+ // On return, width/height will be set to the image's dimensions, and actual_comps will be set to the either 1 (grayscale) or 3 (RGB).
+ // Notes: For more control over where and how the source data is read, see the decompress_jpeg_image_from_stream() function below, or call the jpeg_decoder class directly.
+ // Requesting a 8 or 32bpp image is currently a little faster than 24bpp because the jpeg_decoder class itself currently always unpacks to either 8 or 32bpp.
+ unsigned char* decompress_jpeg_image_from_memory(const unsigned char* pSrc_data, int src_data_size, int* width, int* height, int* actual_comps, int req_comps, uint32_t flags = 0);
+ unsigned char* decompress_jpeg_image_from_file(const char* pSrc_filename, int* width, int* height, int* actual_comps, int req_comps, uint32_t flags = 0);
+
+ // Success/failure error codes.
+ enum jpgd_status
+ {
+ JPGD_SUCCESS = 0, JPGD_FAILED = -1, JPGD_DONE = 1,
+ JPGD_BAD_DHT_COUNTS = -256, JPGD_BAD_DHT_INDEX, JPGD_BAD_DHT_MARKER, JPGD_BAD_DQT_MARKER, JPGD_BAD_DQT_TABLE,
+ JPGD_BAD_PRECISION, JPGD_BAD_HEIGHT, JPGD_BAD_WIDTH, JPGD_TOO_MANY_COMPONENTS,
+ JPGD_BAD_SOF_LENGTH, JPGD_BAD_VARIABLE_MARKER, JPGD_BAD_DRI_LENGTH, JPGD_BAD_SOS_LENGTH,
+ JPGD_BAD_SOS_COMP_ID, JPGD_W_EXTRA_BYTES_BEFORE_MARKER, JPGD_NO_ARITHMITIC_SUPPORT, JPGD_UNEXPECTED_MARKER,
+ JPGD_NOT_JPEG, JPGD_UNSUPPORTED_MARKER, JPGD_BAD_DQT_LENGTH, JPGD_TOO_MANY_BLOCKS,
+ JPGD_UNDEFINED_QUANT_TABLE, JPGD_UNDEFINED_HUFF_TABLE, JPGD_NOT_SINGLE_SCAN, JPGD_UNSUPPORTED_COLORSPACE,
+ JPGD_UNSUPPORTED_SAMP_FACTORS, JPGD_DECODE_ERROR, JPGD_BAD_RESTART_MARKER,
+ JPGD_BAD_SOS_SPECTRAL, JPGD_BAD_SOS_SUCCESSIVE, JPGD_STREAM_READ, JPGD_NOTENOUGHMEM, JPGD_TOO_MANY_SCANS
+ };
+
+ // Input stream interface.
+ // Derive from this class to read input data from sources other than files or memory. Set m_eof_flag to true when no more data is available.
+ // The decoder is rather greedy: it will keep on calling this method until its internal input buffer is full, or until the EOF flag is set.
+ // It the input stream contains data after the JPEG stream's EOI (end of image) marker it will probably be pulled into the internal buffer.
+ // Call the get_total_bytes_read() method to determine the actual size of the JPEG stream after successful decoding.
+ class jpeg_decoder_stream
+ {
+ public:
+ jpeg_decoder_stream() { }
+ virtual ~jpeg_decoder_stream() { }
+
+ // The read() method is called when the internal input buffer is empty.
+ // Parameters:
+ // pBuf - input buffer
+ // max_bytes_to_read - maximum bytes that can be written to pBuf
+ // pEOF_flag - set this to true if at end of stream (no more bytes remaining)
+ // Returns -1 on error, otherwise return the number of bytes actually written to the buffer (which may be 0).
+ // Notes: This method will be called in a loop until you set *pEOF_flag to true or the internal buffer is full.
+ virtual int read(uint8* pBuf, int max_bytes_to_read, bool* pEOF_flag) = 0;
+ };
+
+ // stdio FILE stream class.
+ class jpeg_decoder_file_stream : public jpeg_decoder_stream
+ {
+ jpeg_decoder_file_stream(const jpeg_decoder_file_stream&);
+ jpeg_decoder_file_stream& operator =(const jpeg_decoder_file_stream&);
+
+ FILE* m_pFile;
+ bool m_eof_flag, m_error_flag;
+
+ public:
+ jpeg_decoder_file_stream();
+ virtual ~jpeg_decoder_file_stream();
+
+ bool open(const char* Pfilename);
+ void close();
+
+ virtual int read(uint8* pBuf, int max_bytes_to_read, bool* pEOF_flag);
+ };
+
+ // Memory stream class.
+ class jpeg_decoder_mem_stream : public jpeg_decoder_stream
+ {
+ const uint8* m_pSrc_data;
+ uint m_ofs, m_size;
+
+ public:
+ jpeg_decoder_mem_stream() : m_pSrc_data(NULL), m_ofs(0), m_size(0) { }
+ jpeg_decoder_mem_stream(const uint8* pSrc_data, uint size) : m_pSrc_data(pSrc_data), m_ofs(0), m_size(size) { }
+
+ virtual ~jpeg_decoder_mem_stream() { }
+
+ bool open(const uint8* pSrc_data, uint size);
+ void close() { m_pSrc_data = NULL; m_ofs = 0; m_size = 0; }
+
+ virtual int read(uint8* pBuf, int max_bytes_to_read, bool* pEOF_flag);
+ };
+
+ // Loads JPEG file from a jpeg_decoder_stream.
+ unsigned char* decompress_jpeg_image_from_stream(jpeg_decoder_stream* pStream, int* width, int* height, int* actual_comps, int req_comps, uint32_t flags = 0);
+
+ enum
+ {
+ JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4,
+ JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 16384, JPGD_MAX_HEIGHT = 32768, JPGD_MAX_WIDTH = 32768
+ };
+
+ typedef int16 jpgd_quant_t;
+ typedef int16 jpgd_block_coeff_t;
+
+ class jpeg_decoder
+ {
+ public:
+ enum
+ {
+ cFlagBoxChromaFiltering = 1,
+ cFlagDisableSIMD = 2
+ };
+
+ // Call get_error_code() after constructing to determine if the stream is valid or not. You may call the get_width(), get_height(), etc.
+ // methods after the constructor is called. You may then either destruct the object, or begin decoding the image by calling begin_decoding(), then decode() on each scanline.
+ jpeg_decoder(jpeg_decoder_stream* pStream, uint32_t flags = 0);
+
+ ~jpeg_decoder();
+
+ // Call this method after constructing the object to begin decompression.
+ // If JPGD_SUCCESS is returned you may then call decode() on each scanline.
+
+ int begin_decoding();
+
+ // Returns the next scan line.
+ // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1).
+ // Otherwise, it will always point to a buffer containing 32-bit RGBA pixels (A will always be 255, and get_bytes_per_pixel() will return 4).
+ // Returns JPGD_SUCCESS if a scan line has been returned.
+ // Returns JPGD_DONE if all scan lines have been returned.
+ // Returns JPGD_FAILED if an error occurred. Call get_error_code() for a more info.
+ int decode(const void** pScan_line, uint* pScan_line_len);
+
+ inline jpgd_status get_error_code() const { return m_error_code; }
+
+ inline int get_width() const { return m_image_x_size; }
+ inline int get_height() const { return m_image_y_size; }
+
+ inline int get_num_components() const { return m_comps_in_frame; }
+
+ inline int get_bytes_per_pixel() const { return m_dest_bytes_per_pixel; }
+ inline int get_bytes_per_scan_line() const { return m_image_x_size * get_bytes_per_pixel(); }
+
+ // Returns the total number of bytes actually consumed by the decoder (which should equal the actual size of the JPEG file).
+ inline int get_total_bytes_read() const { return m_total_bytes_read; }
+
+ private:
+ jpeg_decoder(const jpeg_decoder&);
+ jpeg_decoder& operator =(const jpeg_decoder&);
+
+ typedef void (*pDecode_block_func)(jpeg_decoder*, int, int, int);
+
+ struct huff_tables
+ {
+ bool ac_table;
+ uint look_up[256];
+ uint look_up2[256];
+ uint8 code_size[JPGD_HUFF_CODE_SIZE_MAX_LENGTH];
+ uint tree[JPGD_HUFF_TREE_MAX_LENGTH];
+ };
+
+ struct coeff_buf
+ {
+ uint8* pData;
+ int block_num_x, block_num_y;
+ int block_len_x, block_len_y;
+ int block_size;
+ };
+
+ struct mem_block
+ {
+ mem_block* m_pNext;
+ size_t m_used_count;
+ size_t m_size;
+ char m_data[1];
+ };
+
+ jmp_buf m_jmp_state;
+ uint32_t m_flags;
+ mem_block* m_pMem_blocks;
+ int m_image_x_size;
+ int m_image_y_size;
+ jpeg_decoder_stream* m_pStream;
+
+ int m_progressive_flag;
+
+ uint8 m_huff_ac[JPGD_MAX_HUFF_TABLES];
+ uint8* m_huff_num[JPGD_MAX_HUFF_TABLES]; // pointer to number of Huffman codes per bit size
+ uint8* m_huff_val[JPGD_MAX_HUFF_TABLES]; // pointer to Huffman codes per bit size
+ jpgd_quant_t* m_quant[JPGD_MAX_QUANT_TABLES]; // pointer to quantization tables
+ int m_scan_type; // Gray, Yh1v1, Yh1v2, Yh2v1, Yh2v2 (CMYK111, CMYK4114 no longer supported)
+ int m_comps_in_frame; // # of components in frame
+ int m_comp_h_samp[JPGD_MAX_COMPONENTS]; // component's horizontal sampling factor
+ int m_comp_v_samp[JPGD_MAX_COMPONENTS]; // component's vertical sampling factor
+ int m_comp_quant[JPGD_MAX_COMPONENTS]; // component's quantization table selector
+ int m_comp_ident[JPGD_MAX_COMPONENTS]; // component's ID
+ int m_comp_h_blocks[JPGD_MAX_COMPONENTS];
+ int m_comp_v_blocks[JPGD_MAX_COMPONENTS];
+ int m_comps_in_scan; // # of components in scan
+ int m_comp_list[JPGD_MAX_COMPS_IN_SCAN]; // components in this scan
+ int m_comp_dc_tab[JPGD_MAX_COMPONENTS]; // component's DC Huffman coding table selector
+ int m_comp_ac_tab[JPGD_MAX_COMPONENTS]; // component's AC Huffman coding table selector
+ int m_spectral_start; // spectral selection start
+ int m_spectral_end; // spectral selection end
+ int m_successive_low; // successive approximation low
+ int m_successive_high; // successive approximation high
+ int m_max_mcu_x_size; // MCU's max. X size in pixels
+ int m_max_mcu_y_size; // MCU's max. Y size in pixels
+ int m_blocks_per_mcu;
+ int m_max_blocks_per_row;
+ int m_mcus_per_row, m_mcus_per_col;
+ int m_mcu_org[JPGD_MAX_BLOCKS_PER_MCU];
+ int m_total_lines_left; // total # lines left in image
+ int m_mcu_lines_left; // total # lines left in this MCU
+ int m_num_buffered_scanlines;
+ int m_real_dest_bytes_per_scan_line;
+ int m_dest_bytes_per_scan_line; // rounded up
+ int m_dest_bytes_per_pixel; // 4 (RGB) or 1 (Y)
+ huff_tables* m_pHuff_tabs[JPGD_MAX_HUFF_TABLES];
+ coeff_buf* m_dc_coeffs[JPGD_MAX_COMPONENTS];
+ coeff_buf* m_ac_coeffs[JPGD_MAX_COMPONENTS];
+ int m_eob_run;
+ int m_block_y_mcu[JPGD_MAX_COMPONENTS];
+ uint8* m_pIn_buf_ofs;
+ int m_in_buf_left;
+ int m_tem_flag;
+
+ uint8 m_in_buf_pad_start[64];
+ uint8 m_in_buf[JPGD_IN_BUF_SIZE + 128];
+ uint8 m_in_buf_pad_end[64];
+
+ int m_bits_left;
+ uint m_bit_buf;
+ int m_restart_interval;
+ int m_restarts_left;
+ int m_next_restart_num;
+ int m_max_mcus_per_row;
+ int m_max_blocks_per_mcu;
+
+ int m_max_mcus_per_col;
+ uint m_last_dc_val[JPGD_MAX_COMPONENTS];
+ jpgd_block_coeff_t* m_pMCU_coefficients;
+ int m_mcu_block_max_zag[JPGD_MAX_BLOCKS_PER_MCU];
+ uint8* m_pSample_buf;
+ uint8* m_pSample_buf_prev;
+ int m_crr[256];
+ int m_cbb[256];
+ int m_crg[256];
+ int m_cbg[256];
+ uint8* m_pScan_line_0;
+ uint8* m_pScan_line_1;
+ jpgd_status m_error_code;
+ int m_total_bytes_read;
+
+ bool m_ready_flag;
+ bool m_eof_flag;
+ bool m_sample_buf_prev_valid;
+ bool m_has_sse2;
+
+ inline int check_sample_buf_ofs(int ofs) const { assert(ofs >= 0); assert(ofs < m_max_blocks_per_row * 64); return ofs; }
+ void free_all_blocks();
+ JPGD_NORETURN void stop_decoding(jpgd_status status);
+ void* alloc(size_t n, bool zero = false);
+ void* alloc_aligned(size_t nSize, uint32_t align = 16, bool zero = false);
+ void word_clear(void* p, uint16 c, uint n);
+ void prep_in_buffer();
+ void read_dht_marker();
+ void read_dqt_marker();
+ void read_sof_marker();
+ void skip_variable_marker();
+ void read_dri_marker();
+ void read_sos_marker();
+ int next_marker();
+ int process_markers();
+ void locate_soi_marker();
+ void locate_sof_marker();
+ int locate_sos_marker();
+ void init(jpeg_decoder_stream* pStream, uint32_t flags);
+ void create_look_ups();
+ void fix_in_buffer();
+ void transform_mcu(int mcu_row);
+ coeff_buf* coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y);
+ inline jpgd_block_coeff_t* coeff_buf_getp(coeff_buf* cb, int block_x, int block_y);
+ void load_next_row();
+ void decode_next_row();
+ void make_huff_table(int index, huff_tables* pH);
+ void check_quant_tables();
+ void check_huff_tables();
+ bool calc_mcu_block_order();
+ int init_scan();
+ void init_frame();
+ void process_restart();
+ void decode_scan(pDecode_block_func decode_block_func);
+ void init_progressive();
+ void init_sequential();
+ void decode_start();
+ void decode_init(jpeg_decoder_stream* pStream, uint32_t flags);
+ void H2V2Convert();
+ uint32_t H2V2ConvertFiltered();
+ void H2V1Convert();
+ void H2V1ConvertFiltered();
+ void H1V2Convert();
+ void H1V2ConvertFiltered();
+ void H1V1Convert();
+ void gray_convert();
+ void find_eoi();
+ inline uint get_char();
+ inline uint get_char(bool* pPadding_flag);
+ inline void stuff_char(uint8 q);
+ inline uint8 get_octet();
+ inline uint get_bits(int num_bits);
+ inline uint get_bits_no_markers(int numbits);
+ inline int huff_decode(huff_tables* pH);
+ inline int huff_decode(huff_tables* pH, int& extrabits);
+
+ // Clamps a value between 0-255.
+ static inline uint8 clamp(int i)
+ {
+ if (static_cast<uint>(i) > 255)
+ i = (((~i) >> 31) & 0xFF);
+ return static_cast<uint8>(i);
+ }
+ int decode_next_mcu_row();
+
+ static void decode_block_dc_first(jpeg_decoder* pD, int component_id, int block_x, int block_y);
+ static void decode_block_dc_refine(jpeg_decoder* pD, int component_id, int block_x, int block_y);
+ static void decode_block_ac_first(jpeg_decoder* pD, int component_id, int block_x, int block_y);
+ static void decode_block_ac_refine(jpeg_decoder* pD, int component_id, int block_x, int block_y);
+ };
+
} // namespace jpgd
#endif // JPEG_DECODER_H
diff --git a/thirdparty/jpeg-compressor/jpgd_idct.h b/thirdparty/jpeg-compressor/jpgd_idct.h
new file mode 100644
index 0000000000..876425a959
--- /dev/null
+++ b/thirdparty/jpeg-compressor/jpgd_idct.h
@@ -0,0 +1,462 @@
+// Copyright 2009 Intel Corporation
+// All Rights Reserved
+//
+// Permission is granted to use, copy, distribute and prepare derivative works of this
+// software for any purpose and without fee, provided, that the above copyright notice
+// and this statement appear in all copies. Intel makes no representations about the
+// suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS."
+// INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,
+// INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,
+// INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not
+// assume any responsibility for any errors which may appear in this software nor any
+// responsibility to update it.
+//
+// From:
+// https://software.intel.com/sites/default/files/m/d/4/1/d/8/UsingIntelAVXToImplementIDCT-r1_5.pdf
+// https://software.intel.com/file/29048
+//
+// Requires SSE
+//
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+#include <immintrin.h>
+
+#ifdef _MSC_VER
+ #define JPGD_SIMD_ALIGN(type, name) __declspec(align(16)) type name
+#else
+ #define JPGD_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
+#endif
+
+#define BITS_INV_ACC 4
+#define SHIFT_INV_ROW 16 - BITS_INV_ACC
+#define SHIFT_INV_COL 1 + BITS_INV_ACC
+const short IRND_INV_ROW = 1024 * (6 - BITS_INV_ACC); //1 << (SHIFT_INV_ROW-1)
+const short IRND_INV_COL = 16 * (BITS_INV_ACC - 3); // 1 << (SHIFT_INV_COL-1)
+const short IRND_INV_CORR = IRND_INV_COL - 1; // correction -1.0 and round
+
+JPGD_SIMD_ALIGN(short, shortM128_one_corr[8]) = {1, 1, 1, 1, 1, 1, 1, 1};
+JPGD_SIMD_ALIGN(short, shortM128_round_inv_row[8]) = {IRND_INV_ROW, 0, IRND_INV_ROW, 0, IRND_INV_ROW, 0, IRND_INV_ROW, 0};
+JPGD_SIMD_ALIGN(short, shortM128_round_inv_col[8]) = {IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL};
+JPGD_SIMD_ALIGN(short, shortM128_round_inv_corr[8])= {IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR};
+JPGD_SIMD_ALIGN(short, shortM128_tg_1_16[8]) = {13036, 13036, 13036, 13036, 13036, 13036, 13036, 13036}; // tg * (2<<16) + 0.5
+JPGD_SIMD_ALIGN(short, shortM128_tg_2_16[8]) = {27146, 27146, 27146, 27146, 27146, 27146, 27146, 27146}; // tg * (2<<16) + 0.5
+JPGD_SIMD_ALIGN(short, shortM128_tg_3_16[8]) = {-21746, -21746, -21746, -21746, -21746, -21746, -21746, -21746}; // tg * (2<<16) + 0.5
+JPGD_SIMD_ALIGN(short, shortM128_cos_4_16[8]) = {-19195, -19195, -19195, -19195, -19195, -19195, -19195, -19195};// cos * (2<<16) + 0.5
+
+//-----------------------------------------------------------------------------
+// Table for rows 0,4 - constants are multiplied on cos_4_16
+// w15 w14 w11 w10 w07 w06 w03 w02
+// w29 w28 w25 w24 w21 w20 w17 w16
+// w31 w30 w27 w26 w23 w22 w19 w18
+//movq -> w05 w04 w01 w00
+JPGD_SIMD_ALIGN(short, shortM128_tab_i_04[]) = {
+ 16384, 21407, 16384, 8867,
+ 16384, -8867, 16384, -21407, // w13 w12 w09 w08
+ 16384, 8867, -16384, -21407, // w07 w06 w03 w02
+ -16384, 21407, 16384, -8867, // w15 w14 w11 w10
+ 22725, 19266, 19266, -4520, // w21 w20 w17 w16
+ 12873, -22725, 4520, -12873, // w29 w28 w25 w24
+ 12873, 4520, -22725, -12873, // w23 w22 w19 w18
+ 4520, 19266, 19266, -22725}; // w31 w30 w27 w26
+
+ // Table for rows 1,7 - constants are multiplied on cos_1_16
+//movq -> w05 w04 w01 w00
+JPGD_SIMD_ALIGN(short, shortM128_tab_i_17[]) = {
+ 22725, 29692, 22725, 12299,
+ 22725, -12299, 22725, -29692, // w13 w12 w09 w08
+ 22725, 12299, -22725, -29692, // w07 w06 w03 w02
+ -22725, 29692, 22725, -12299, // w15 w14 w11 w10
+ 31521, 26722, 26722, -6270, // w21 w20 w17 w16
+ 17855, -31521, 6270, -17855, // w29 w28 w25 w24
+ 17855, 6270, -31521, -17855, // w23 w22 w19 w18
+ 6270, 26722, 26722, -31521}; // w31 w30 w27 w26
+
+// Table for rows 2,6 - constants are multiplied on cos_2_16
+//movq -> w05 w04 w01 w00
+JPGD_SIMD_ALIGN(short, shortM128_tab_i_26[]) = {
+ 21407, 27969, 21407, 11585,
+ 21407, -11585, 21407, -27969, // w13 w12 w09 w08
+ 21407, 11585, -21407, -27969, // w07 w06 w03 w02
+ -21407, 27969, 21407, -11585, // w15 w14 w11 w10
+ 29692, 25172, 25172, -5906, // w21 w20 w17 w16
+ 16819, -29692, 5906, -16819, // w29 w28 w25 w24
+ 16819, 5906, -29692, -16819, // w23 w22 w19 w18
+ 5906, 25172, 25172, -29692}; // w31 w30 w27 w26
+// Table for rows 3,5 - constants are multiplied on cos_3_16
+//movq -> w05 w04 w01 w00
+JPGD_SIMD_ALIGN(short, shortM128_tab_i_35[]) = {
+ 19266, 25172, 19266, 10426,
+ 19266, -10426, 19266, -25172, // w13 w12 w09 w08
+ 19266, 10426, -19266, -25172, // w07 w06 w03 w02
+ -19266, 25172, 19266, -10426, // w15 w14 w11 w10
+ 26722, 22654, 22654, -5315, // w21 w20 w17 w16
+ 15137, -26722, 5315, -15137, // w29 w28 w25 w24
+ 15137, 5315, -26722, -15137, // w23 w22 w19 w18
+ 5315, 22654, 22654, -26722}; // w31 w30 w27 w26
+
+JPGD_SIMD_ALIGN(short, shortM128_128[8]) = { 128, 128, 128, 128, 128, 128, 128, 128 };
+
+void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
+{
+ __m128i r_xmm0, r_xmm4;
+ __m128i r_xmm1, r_xmm2, r_xmm3, r_xmm5, r_xmm6, r_xmm7;
+ __m128i row0, row1, row2, row3, row4, row5, row6, row7;
+ short * pTab_i_04 = shortM128_tab_i_04;
+ short * pTab_i_26 = shortM128_tab_i_26;
+
+ //Get pointers for this input and output
+ pTab_i_04 = shortM128_tab_i_04;
+ pTab_i_26 = shortM128_tab_i_26;
+
+ //Row 1 and Row 3
+ r_xmm0 = _mm_load_si128((__m128i *) pInput);
+ r_xmm4 = _mm_load_si128((__m128i *) (&pInput[2*8]));
+
+ // *** Work on the data in xmm0
+ //low shuffle mask = 0xd8 = 11 01 10 00
+ //get short 2 and short 0 into ls 32-bits
+ r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
+
+ // copy short 2 and short 0 to all locations
+ r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
+
+ // add to those copies
+ r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *) pTab_i_04));
+
+ // shuffle mask = 0x55 = 01 01 01 01
+ // copy short 3 and short 1 to all locations
+ r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
+
+ // high shuffle mask = 0xd8 = 11 01 10 00
+ // get short 6 and short 4 into bit positions 64-95
+ // get short 7 and short 5 into bit positions 96-127
+ r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
+
+ // add to short 3 and short 1
+ r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *) &pTab_i_04[16]));
+
+ // shuffle mask = 0xaa = 10 10 10 10
+ // copy short 6 and short 4 to all locations
+ r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
+
+ // shuffle mask = 0xaa = 11 11 11 11
+ // copy short 7 and short 5 to all locations
+ r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
+
+ // add to short 6 and short 4
+ r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *) &pTab_i_04[8]));
+
+ // *** Work on the data in xmm4
+ // high shuffle mask = 0xd8 11 01 10 00
+ // get short 6 and short 4 into bit positions 64-95
+ // get short 7 and short 5 into bit positions 96-127
+ r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
+
+ // (xmm0 short 2 and short 0 plus pSi) + some constants
+ r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *) shortM128_round_inv_row));
+ r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
+ r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *) &pTab_i_04[24]));
+ r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
+ r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
+ r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *) &shortM128_tab_i_26[0]));
+ r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
+ r_xmm2 = r_xmm1;
+ r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
+ r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *) &shortM128_tab_i_26[8]));
+ r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
+ r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
+ r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
+ r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *) &shortM128_tab_i_26[16]));
+ r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
+ r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
+ r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *) shortM128_round_inv_row));
+ r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *) &shortM128_tab_i_26[24]));
+ r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
+ r_xmm6 = r_xmm5;
+ r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
+ r_xmm2 = _mm_shuffle_epi32(r_xmm2, 0x1b);
+ row0 = _mm_packs_epi32(r_xmm0, r_xmm2);
+ r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm7);
+ r_xmm6 = _mm_sub_epi32(r_xmm6, r_xmm4);
+ r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm5);
+ r_xmm6 = _mm_srai_epi32(r_xmm6, 12);
+ r_xmm4 = _mm_srai_epi32(r_xmm4, 12);
+ r_xmm6 = _mm_shuffle_epi32(r_xmm6, 0x1b);
+ row2 = _mm_packs_epi32(r_xmm4, r_xmm6);
+
+ //Row 5 and row 7
+ r_xmm0 = _mm_load_si128((__m128i *) (&pInput[4*8]));
+ r_xmm4 = _mm_load_si128((__m128i *) (&pInput[6*8]));
+
+ r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
+ r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
+ r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *) pTab_i_04));
+ r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
+ r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
+ r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *) &pTab_i_04[16]));
+ r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
+ r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
+ r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *) &pTab_i_04[8]));
+ r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
+ r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *) shortM128_round_inv_row));
+ r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
+ r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *) &pTab_i_04[24]));
+ r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
+ r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
+ r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *) &shortM128_tab_i_26[0]));
+ r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
+ r_xmm2 = r_xmm1;
+ r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
+ r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *) &shortM128_tab_i_26[8]));
+ r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
+ r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
+ r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
+ r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *) &shortM128_tab_i_26[16]));
+ r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
+ r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
+ r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *) shortM128_round_inv_row));
+ r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *) &shortM128_tab_i_26[24]));
+ r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
+ r_xmm6 = r_xmm5;
+ r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
+ r_xmm2 = _mm_shuffle_epi32(r_xmm2, 0x1b);
+ row4 = _mm_packs_epi32(r_xmm0, r_xmm2);
+ r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm7);
+ r_xmm6 = _mm_sub_epi32(r_xmm6, r_xmm4);
+ r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm5);
+ r_xmm6 = _mm_srai_epi32(r_xmm6, 12);
+ r_xmm4 = _mm_srai_epi32(r_xmm4, 12);
+ r_xmm6 = _mm_shuffle_epi32(r_xmm6, 0x1b);
+ row6 = _mm_packs_epi32(r_xmm4, r_xmm6);
+
+ //Row 4 and row 2
+ pTab_i_04 = shortM128_tab_i_35;
+ pTab_i_26 = shortM128_tab_i_17;
+ r_xmm0 = _mm_load_si128((__m128i *) (&pInput[3*8]));
+ r_xmm4 = _mm_load_si128((__m128i *) (&pInput[1*8]));
+
+ r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
+ r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
+ r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *) pTab_i_04));
+ r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
+ r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
+ r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *) &pTab_i_04[16]));
+ r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
+ r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
+ r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *) &pTab_i_04[8]));
+ r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
+ r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *) shortM128_round_inv_row));
+ r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
+ r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *) &pTab_i_04[24]));
+ r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
+ r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
+ r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *) &pTab_i_26[0]));
+ r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
+ r_xmm2 = r_xmm1;
+ r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
+ r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *) &pTab_i_26[8]));
+ r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
+ r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
+ r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
+ r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *) &pTab_i_26[16]));
+ r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
+ r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
+ r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *) shortM128_round_inv_row));
+ r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *) &pTab_i_26[24]));
+ r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
+ r_xmm6 = r_xmm5;
+ r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
+ r_xmm2 = _mm_shuffle_epi32(r_xmm2, 0x1b);
+ row3 = _mm_packs_epi32(r_xmm0, r_xmm2);
+ r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm7);
+ r_xmm6 = _mm_sub_epi32(r_xmm6, r_xmm4);
+ r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm5);
+ r_xmm6 = _mm_srai_epi32(r_xmm6, 12);
+ r_xmm4 = _mm_srai_epi32(r_xmm4, 12);
+ r_xmm6 = _mm_shuffle_epi32(r_xmm6, 0x1b);
+ row1 = _mm_packs_epi32(r_xmm4, r_xmm6);
+
+ //Row 6 and row 8
+ r_xmm0 = _mm_load_si128((__m128i *) (&pInput[5*8]));
+ r_xmm4 = _mm_load_si128((__m128i *) (&pInput[7*8]));
+
+ r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
+ r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
+ r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *) pTab_i_04));
+ r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
+ r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
+ r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *) &pTab_i_04[16]));
+ r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
+ r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
+ r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *) &pTab_i_04[8]));
+ r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
+ r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *) shortM128_round_inv_row));
+ r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
+ r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *) &pTab_i_04[24]));
+ r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
+ r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
+ r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *) &pTab_i_26[0]));
+ r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
+ r_xmm2 = r_xmm1;
+ r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
+ r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *) &pTab_i_26[8]));
+ r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
+ r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
+ r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
+ r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *) &pTab_i_26[16]));
+ r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
+ r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
+ r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *) shortM128_round_inv_row));
+ r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *) &pTab_i_26[24]));
+ r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
+ r_xmm6 = r_xmm5;
+ r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
+ r_xmm2 = _mm_shuffle_epi32(r_xmm2, 0x1b);
+ row5 = _mm_packs_epi32(r_xmm0, r_xmm2);
+ r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm7);
+ r_xmm6 = _mm_sub_epi32(r_xmm6, r_xmm4);
+ r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm5);
+ r_xmm6 = _mm_srai_epi32(r_xmm6, 12);
+ r_xmm4 = _mm_srai_epi32(r_xmm4, 12);
+ r_xmm6 = _mm_shuffle_epi32(r_xmm6, 0x1b);
+ row7 = _mm_packs_epi32(r_xmm4, r_xmm6);
+
+ r_xmm1 = _mm_load_si128((__m128i *) shortM128_tg_3_16);
+ r_xmm2 = row5;
+ r_xmm3 = row3;
+ r_xmm0 = _mm_mulhi_epi16(row5, r_xmm1);
+
+ r_xmm1 = _mm_mulhi_epi16(r_xmm1, r_xmm3);
+ r_xmm5 = _mm_load_si128((__m128i *) shortM128_tg_1_16);
+ r_xmm6 = row7;
+ r_xmm4 = _mm_mulhi_epi16(row7, r_xmm5);
+
+ r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm2);
+ r_xmm5 = _mm_mulhi_epi16(r_xmm5, row1);
+ r_xmm1 = _mm_adds_epi16(r_xmm1, r_xmm3);
+ r_xmm7 = row6;
+
+ r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm3);
+ r_xmm3 = _mm_load_si128((__m128i *) shortM128_tg_2_16);
+ r_xmm2 = _mm_subs_epi16(r_xmm2, r_xmm1);
+ r_xmm7 = _mm_mulhi_epi16(r_xmm7, r_xmm3);
+ r_xmm1 = r_xmm0;
+ r_xmm3 = _mm_mulhi_epi16(r_xmm3, row2);
+ r_xmm5 = _mm_subs_epi16(r_xmm5, r_xmm6);
+ r_xmm4 = _mm_adds_epi16(r_xmm4, row1);
+ r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm4);
+ r_xmm0 = _mm_adds_epi16(r_xmm0, *((__m128i *) shortM128_one_corr));
+ r_xmm4 = _mm_subs_epi16(r_xmm4, r_xmm1);
+ r_xmm6 = r_xmm5;
+ r_xmm5 = _mm_subs_epi16(r_xmm5, r_xmm2);
+ r_xmm5 = _mm_adds_epi16(r_xmm5, *((__m128i *) shortM128_one_corr));
+ r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm2);
+
+ //Intermediate results, needed later
+ __m128i temp3, temp7;
+ temp7 = r_xmm0;
+
+ r_xmm1 = r_xmm4;
+ r_xmm0 = _mm_load_si128((__m128i *) shortM128_cos_4_16);
+ r_xmm4 = _mm_adds_epi16(r_xmm4, r_xmm5);
+ r_xmm2 = _mm_load_si128((__m128i *) shortM128_cos_4_16);
+ r_xmm2 = _mm_mulhi_epi16(r_xmm2, r_xmm4);
+
+ //Intermediate results, needed later
+ temp3 = r_xmm6;
+
+ r_xmm1 = _mm_subs_epi16(r_xmm1, r_xmm5);
+ r_xmm7 = _mm_adds_epi16(r_xmm7, row2);
+ r_xmm3 = _mm_subs_epi16(r_xmm3, row6);
+ r_xmm6 = row0;
+ r_xmm0 = _mm_mulhi_epi16(r_xmm0, r_xmm1);
+ r_xmm5 = row4;
+ r_xmm5 = _mm_adds_epi16(r_xmm5, r_xmm6);
+ r_xmm6 = _mm_subs_epi16(r_xmm6, row4);
+ r_xmm4 = _mm_adds_epi16(r_xmm4, r_xmm2);
+
+ r_xmm4 = _mm_or_si128(r_xmm4, *((__m128i *) shortM128_one_corr));
+ r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm1);
+ r_xmm0 = _mm_or_si128(r_xmm0, *((__m128i *) shortM128_one_corr));
+
+ r_xmm2 = r_xmm5;
+ r_xmm5 = _mm_adds_epi16(r_xmm5, r_xmm7);
+ r_xmm1 = r_xmm6;
+ r_xmm5 = _mm_adds_epi16(r_xmm5, *((__m128i *) shortM128_round_inv_col));
+ r_xmm2 = _mm_subs_epi16(r_xmm2, r_xmm7);
+ r_xmm7 = temp7;
+ r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm3);
+ r_xmm6 = _mm_adds_epi16(r_xmm6, *((__m128i *) shortM128_round_inv_col));
+ r_xmm7 = _mm_adds_epi16(r_xmm7, r_xmm5);
+ r_xmm7 = _mm_srai_epi16(r_xmm7, SHIFT_INV_COL);
+ r_xmm1 = _mm_subs_epi16(r_xmm1, r_xmm3);
+ r_xmm1 = _mm_adds_epi16(r_xmm1, *((__m128i *) shortM128_round_inv_corr));
+ r_xmm3 = r_xmm6;
+ r_xmm2 = _mm_adds_epi16(r_xmm2, *((__m128i *) shortM128_round_inv_corr));
+ r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm4);
+
+ //Store results for row 0
+ //_mm_store_si128((__m128i *) pOutput, r_xmm7);
+ __m128i r0 = r_xmm7;
+
+ r_xmm6 = _mm_srai_epi16(r_xmm6, SHIFT_INV_COL);
+ r_xmm7 = r_xmm1;
+ r_xmm1 = _mm_adds_epi16(r_xmm1, r_xmm0);
+
+ //Store results for row 1
+ //_mm_store_si128((__m128i *) (&pOutput[1*8]), r_xmm6);
+ __m128i r1 = r_xmm6;
+
+ r_xmm1 = _mm_srai_epi16(r_xmm1, SHIFT_INV_COL);
+ r_xmm6 = temp3;
+ r_xmm7 = _mm_subs_epi16(r_xmm7, r_xmm0);
+ r_xmm7 = _mm_srai_epi16(r_xmm7, SHIFT_INV_COL);
+
+ //Store results for row 2
+ //_mm_store_si128((__m128i *) (&pOutput[2*8]), r_xmm1);
+ __m128i r2 = r_xmm1;
+
+ r_xmm5 = _mm_subs_epi16(r_xmm5, temp7);
+ r_xmm5 = _mm_srai_epi16(r_xmm5, SHIFT_INV_COL);
+
+ //Store results for row 7
+ //_mm_store_si128((__m128i *) (&pOutput[7*8]), r_xmm5);
+ __m128i r7 = r_xmm5;
+
+ r_xmm3 = _mm_subs_epi16(r_xmm3, r_xmm4);
+ r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm2);
+ r_xmm2 = _mm_subs_epi16(r_xmm2, temp3);
+ r_xmm6 = _mm_srai_epi16(r_xmm6, SHIFT_INV_COL);
+ r_xmm2 = _mm_srai_epi16(r_xmm2, SHIFT_INV_COL);
+
+ //Store results for row 3
+ //_mm_store_si128((__m128i *) (&pOutput[3*8]), r_xmm6);
+ __m128i r3 = r_xmm6;
+
+ r_xmm3 = _mm_srai_epi16(r_xmm3, SHIFT_INV_COL);
+
+ //Store results for rows 4, 5, and 6
+ //_mm_store_si128((__m128i *) (&pOutput[4*8]), r_xmm2);
+ //_mm_store_si128((__m128i *) (&pOutput[5*8]), r_xmm7);
+ //_mm_store_si128((__m128i *) (&pOutput[6*8]), r_xmm3);
+
+ __m128i r4 = r_xmm2;
+ __m128i r5 = r_xmm7;
+ __m128i r6 = r_xmm3;
+
+ r0 = _mm_add_epi16(*(const __m128i *)shortM128_128, r0);
+ r1 = _mm_add_epi16(*(const __m128i *)shortM128_128, r1);
+ r2 = _mm_add_epi16(*(const __m128i *)shortM128_128, r2);
+ r3 = _mm_add_epi16(*(const __m128i *)shortM128_128, r3);
+ r4 = _mm_add_epi16(*(const __m128i *)shortM128_128, r4);
+ r5 = _mm_add_epi16(*(const __m128i *)shortM128_128, r5);
+ r6 = _mm_add_epi16(*(const __m128i *)shortM128_128, r6);
+ r7 = _mm_add_epi16(*(const __m128i *)shortM128_128, r7);
+
+ ((__m128i *)pOutputUB)[0] = _mm_packus_epi16(r0, r1);
+ ((__m128i *)pOutputUB)[1] = _mm_packus_epi16(r2, r3);
+ ((__m128i *)pOutputUB)[2] = _mm_packus_epi16(r4, r5);
+ ((__m128i *)pOutputUB)[3] = _mm_packus_epi16(r6, r7);
+}
diff --git a/thirdparty/libwebp/src/dec/frame_dec.c b/thirdparty/libwebp/src/dec/frame_dec.c
index bda9e1a6f6..04609a8e56 100644
--- a/thirdparty/libwebp/src/dec/frame_dec.c
+++ b/thirdparty/libwebp/src/dec/frame_dec.c
@@ -732,7 +732,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
mem += f_info_size;
dec->thread_ctx_.id_ = 0;
dec->thread_ctx_.f_info_ = dec->f_info_;
- if (dec->mt_method_ > 0) {
+ if (dec->filter_type_ > 0 && dec->mt_method_ > 0) {
// secondary cache line. The deblocking process need to make use of the
// filtering strength from previous macroblock row, while the new ones
// are being decoded in parallel. We'll just swap the pointers.
diff --git a/thirdparty/libwebp/src/dec/idec_dec.c b/thirdparty/libwebp/src/dec/idec_dec.c
index 9bc9166808..9035df5659 100644
--- a/thirdparty/libwebp/src/dec/idec_dec.c
+++ b/thirdparty/libwebp/src/dec/idec_dec.c
@@ -166,9 +166,11 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
MemBuffer* const mem = &idec->mem_;
const int need_compressed_alpha = NeedCompressedAlpha(idec);
- const uint8_t* const old_start = mem->buf_ + mem->start_;
+ const uint8_t* const old_start =
+ (mem->buf_ == NULL) ? NULL : mem->buf_ + mem->start_;
const uint8_t* const old_base =
need_compressed_alpha ? dec->alpha_data_ : old_start;
+ assert(mem->buf_ != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_APPEND);
if (data_size > MAX_CHUNK_PAYLOAD) {
// security safeguard: trying to allocate more than what the format
@@ -184,7 +186,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
uint8_t* const new_buf =
(uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
if (new_buf == NULL) return 0;
- memcpy(new_buf, old_base, current_size);
+ if (old_base != NULL) memcpy(new_buf, old_base, current_size);
WebPSafeFree(mem->buf_);
mem->buf_ = new_buf;
mem->buf_size_ = (size_t)extra_size;
@@ -192,6 +194,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
mem->end_ = current_size;
}
+ assert(mem->buf_ != NULL);
memcpy(mem->buf_ + mem->end_, data, data_size);
mem->end_ += data_size;
assert(mem->end_ <= mem->buf_size_);
@@ -204,7 +207,9 @@ static int RemapMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data, size_t data_size) {
MemBuffer* const mem = &idec->mem_;
const uint8_t* const old_buf = mem->buf_;
- const uint8_t* const old_start = old_buf + mem->start_;
+ const uint8_t* const old_start =
+ (old_buf == NULL) ? NULL : old_buf + mem->start_;
+ assert(old_buf != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_MAP);
if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
diff --git a/thirdparty/libwebp/src/dec/vp8i_dec.h b/thirdparty/libwebp/src/dec/vp8i_dec.h
index 3de8d86f90..600a684410 100644
--- a/thirdparty/libwebp/src/dec/vp8i_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8i_dec.h
@@ -31,8 +31,8 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
-#define DEC_MIN_VERSION 0
-#define DEC_REV_VERSION 3
+#define DEC_MIN_VERSION 1
+#define DEC_REV_VERSION 0
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),
diff --git a/thirdparty/libwebp/src/dec/vp8l_dec.c b/thirdparty/libwebp/src/dec/vp8l_dec.c
index d3e27119ea..93615d4ed2 100644
--- a/thirdparty/libwebp/src/dec/vp8l_dec.c
+++ b/thirdparty/libwebp/src/dec/vp8l_dec.c
@@ -754,11 +754,11 @@ static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
-static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
+static void ApplyInverseTransforms(VP8LDecoder* const dec,
+ int start_row, int num_rows,
const uint32_t* const rows) {
int n = dec->next_transform_;
const int cache_pixs = dec->width_ * num_rows;
- const int start_row = dec->last_row_;
const int end_row = start_row + num_rows;
const uint32_t* rows_in = rows;
uint32_t* const rows_out = dec->argb_cache_;
@@ -789,8 +789,7 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
VP8Io* const io = dec->io_;
uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
-
- ApplyInverseTransforms(dec, num_rows, rows);
+ ApplyInverseTransforms(dec, dec->last_row_, num_rows, rows);
if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
// Nothing to output (this time).
} else {
@@ -1193,6 +1192,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
VP8LFillBitWindow(br);
dist_code = GetCopyDistance(dist_symbol, br);
dist = PlaneCodeToDistance(width, dist_code);
+
if (VP8LIsEndOfStream(br)) break;
if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
goto Error;
@@ -1553,7 +1553,7 @@ static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
const int cache_pixs = width * num_rows_to_process;
uint8_t* const dst = output + width * cur_row;
const uint32_t* const src = dec->argb_cache_;
- ApplyInverseTransforms(dec, num_rows_to_process, in);
+ ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in);
WebPExtractGreen(src, dst, cache_pixs);
AlphaApplyFilter(alph_dec,
cur_row, cur_row + num_rows_to_process, dst, width);
diff --git a/thirdparty/libwebp/src/dec/vp8li_dec.h b/thirdparty/libwebp/src/dec/vp8li_dec.h
index 0a4d613f99..72b2e86120 100644
--- a/thirdparty/libwebp/src/dec/vp8li_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8li_dec.h
@@ -37,7 +37,7 @@ struct VP8LTransform {
int bits_; // subsampling bits defining transform window.
int xsize_; // transform window X index.
int ysize_; // transform window Y index.
- uint32_t *data_; // transform data.
+ uint32_t* data_; // transform data.
};
typedef struct {
@@ -48,23 +48,23 @@ typedef struct {
int huffman_mask_;
int huffman_subsample_bits_;
int huffman_xsize_;
- uint32_t *huffman_image_;
+ uint32_t* huffman_image_;
int num_htree_groups_;
- HTreeGroup *htree_groups_;
- HuffmanCode *huffman_tables_;
+ HTreeGroup* htree_groups_;
+ HuffmanCode* huffman_tables_;
} VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder;
struct VP8LDecoder {
VP8StatusCode status_;
VP8LDecodeState state_;
- VP8Io *io_;
+ VP8Io* io_;
- const WebPDecBuffer *output_; // shortcut to io->opaque->output
+ const WebPDecBuffer* output_; // shortcut to io->opaque->output
- uint32_t *pixels_; // Internal data: either uint8_t* for alpha
+ uint32_t* pixels_; // Internal data: either uint8_t* for alpha
// or uint32_t* for BGRA.
- uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
+ uint32_t* argb_cache_; // Scratch buffer for temporary BGRA storage.
VP8LBitReader br_;
int incremental_; // if true, incremental decoding is expected
@@ -86,8 +86,8 @@ struct VP8LDecoder {
// or'd bitset storing the transforms types.
uint32_t transforms_seen_;
- uint8_t *rescaler_memory; // Working memory for rescaling work.
- WebPRescaler *rescaler; // Common rescaler for all channels.
+ uint8_t* rescaler_memory; // Working memory for rescaling work.
+ WebPRescaler* rescaler; // Common rescaler for all channels.
};
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/demux/demux.c b/thirdparty/libwebp/src/demux/demux.c
index ab6433e54b..1b3cc2e0a8 100644
--- a/thirdparty/libwebp/src/demux/demux.c
+++ b/thirdparty/libwebp/src/demux/demux.c
@@ -24,8 +24,8 @@
#include "src/webp/format_constants.h"
#define DMUX_MAJ_VERSION 1
-#define DMUX_MIN_VERSION 0
-#define DMUX_REV_VERSION 3
+#define DMUX_MIN_VERSION 1
+#define DMUX_REV_VERSION 0
typedef struct {
size_t start_; // start location of the data
diff --git a/thirdparty/libwebp/src/dsp/dec_neon.c b/thirdparty/libwebp/src/dsp/dec_neon.c
index ffa697fcf9..239ec4167e 100644
--- a/thirdparty/libwebp/src/dsp/dec_neon.c
+++ b/thirdparty/libwebp/src/dsp/dec_neon.c
@@ -1361,7 +1361,8 @@ static void RD4_NEON(uint8_t* dst) { // Down-right
const uint32_t J = dst[-1 + 1 * BPS];
const uint32_t K = dst[-1 + 2 * BPS];
const uint32_t L = dst[-1 + 3 * BPS];
- const uint64x1_t LKJI____ = vcreate_u64(L | (K << 8) | (J << 16) | (I << 24));
+ const uint64x1_t LKJI____ =
+ vcreate_u64((uint64_t)L | (K << 8) | (J << 16) | (I << 24));
const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC);
const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8));
const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16));
@@ -1427,10 +1428,16 @@ static WEBP_INLINE void DC8_NEON(uint8_t* dst, int do_top, int do_left) {
if (do_top) {
const uint8x8_t A = vld1_u8(dst - BPS); // top row
+#if defined(__aarch64__)
+ const uint16x8_t B = vmovl_u8(A);
+ const uint16_t p2 = vaddvq_u16(B);
+ sum_top = vdupq_n_u16(p2);
+#else
const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
const uint16x4_t p1 = vpadd_u16(p0, p0);
const uint16x4_t p2 = vpadd_u16(p1, p1);
sum_top = vcombine_u16(p2, p2);
+#endif
}
if (do_left) {
diff --git a/thirdparty/libwebp/src/dsp/dsp.h b/thirdparty/libwebp/src/dsp/dsp.h
index fafc2d05d3..a784de334a 100644
--- a/thirdparty/libwebp/src/dsp/dsp.h
+++ b/thirdparty/libwebp/src/dsp/dsp.h
@@ -246,9 +246,9 @@ extern VP8Fdct VP8FTransform2; // performs two transforms at a time
extern VP8WHT VP8FTransformWHT;
// Predictions
// *dst is the destination block. *top and *left can be NULL.
-typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left,
+typedef void (*VP8IntraPreds)(uint8_t* dst, const uint8_t* left,
const uint8_t* top);
-typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top);
+typedef void (*VP8Intra4Preds)(uint8_t* dst, const uint8_t* top);
extern VP8Intra4Preds VP8EncPredLuma4;
extern VP8IntraPreds VP8EncPredLuma16;
extern VP8IntraPreds VP8EncPredChroma8;
diff --git a/thirdparty/libwebp/src/dsp/lossless.c b/thirdparty/libwebp/src/dsp/lossless.c
index d05af84e7b..aad5f43ec9 100644
--- a/thirdparty/libwebp/src/dsp/lossless.c
+++ b/thirdparty/libwebp/src/dsp/lossless.c
@@ -81,7 +81,7 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is
// inlined.
-#if defined(__arm__) && LOCAL_GCC_VERSION <= 0x409
+#if defined(__arm__) && defined(__GNUC__) && LOCAL_GCC_VERSION <= 0x409
# define LOCAL_INLINE __attribute__ ((noinline))
#else
# define LOCAL_INLINE WEBP_INLINE
@@ -167,15 +167,20 @@ static uint32_t Predictor13_C(uint32_t left, const uint32_t* const top) {
return pred;
}
-GENERATE_PREDICTOR_ADD(Predictor0_C, PredictorAdd0_C)
+static void PredictorAdd0_C(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int x;
+ (void)upper;
+ for (x = 0; x < num_pixels; ++x) out[x] = VP8LAddPixels(in[x], ARGB_BLACK);
+}
static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) {
int i;
uint32_t left = out[-1];
+ (void)upper;
for (i = 0; i < num_pixels; ++i) {
out[i] = left = VP8LAddPixels(in[i], left);
}
- (void)upper;
}
GENERATE_PREDICTOR_ADD(Predictor2_C, PredictorAdd2_C)
GENERATE_PREDICTOR_ADD(Predictor3_C, PredictorAdd3_C)
diff --git a/thirdparty/libwebp/src/dsp/lossless_common.h b/thirdparty/libwebp/src/dsp/lossless_common.h
index a2648d1737..9c2ebe6809 100644
--- a/thirdparty/libwebp/src/dsp/lossless_common.h
+++ b/thirdparty/libwebp/src/dsp/lossless_common.h
@@ -177,6 +177,7 @@ uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int x; \
+ assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(out[x - 1], upper + x); \
out[x] = VP8LAddPixels(in[x], pred); \
@@ -189,6 +190,7 @@ static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
static void PREDICTOR_SUB(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int x; \
+ assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(in[x - 1], upper + x); \
out[x] = VP8LSubPixels(in[x], pred); \
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
index 8adc52139b..e676f6fdc9 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
@@ -455,8 +455,9 @@ static void PredictorSub0_SSE2(const uint32_t* in, const uint32_t* upper,
_mm_storeu_si128((__m128i*)&out[i], res);
}
if (i != num_pixels) {
- VP8LPredictorsSub_C[0](in + i, upper + i, num_pixels - i, out + i);
+ VP8LPredictorsSub_C[0](in + i, NULL, num_pixels - i, out + i);
}
+ (void)upper;
}
#define GENERATE_PREDICTOR_1(X, IN) \
diff --git a/thirdparty/libwebp/src/dsp/lossless_sse2.c b/thirdparty/libwebp/src/dsp/lossless_sse2.c
index 17d7576419..aef0cee1b3 100644
--- a/thirdparty/libwebp/src/dsp/lossless_sse2.c
+++ b/thirdparty/libwebp/src/dsp/lossless_sse2.c
@@ -191,8 +191,9 @@ static void PredictorAdd0_SSE2(const uint32_t* in, const uint32_t* upper,
_mm_storeu_si128((__m128i*)&out[i], res);
}
if (i != num_pixels) {
- VP8LPredictorsAdd_C[0](in + i, upper + i, num_pixels - i, out + i);
+ VP8LPredictorsAdd_C[0](in + i, NULL, num_pixels - i, out + i);
}
+ (void)upper;
}
// Predictor1: left.
diff --git a/thirdparty/libwebp/src/dsp/upsampling_msa.c b/thirdparty/libwebp/src/dsp/upsampling_msa.c
index 99eea70e7d..f2e03e85e9 100644
--- a/thirdparty/libwebp/src/dsp/upsampling_msa.c
+++ b/thirdparty/libwebp/src/dsp/upsampling_msa.c
@@ -576,9 +576,9 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \
const uint32_t l_uv = ((cur_u[0]) | ((cur_v[0]) << 16)); \
const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
const uint8_t* ptop_y = &top_y[1]; \
- uint8_t *ptop_dst = top_dst + XSTEP; \
+ uint8_t* ptop_dst = top_dst + XSTEP; \
const uint8_t* pbot_y = &bot_y[1]; \
- uint8_t *pbot_dst = bot_dst + XSTEP; \
+ uint8_t* pbot_dst = bot_dst + XSTEP; \
\
FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
if (bot_y != NULL) { \
diff --git a/thirdparty/libwebp/src/dsp/upsampling_neon.c b/thirdparty/libwebp/src/dsp/upsampling_neon.c
index 17cbc9f911..6ba71a7de5 100644
--- a/thirdparty/libwebp/src/dsp/upsampling_neon.c
+++ b/thirdparty/libwebp/src/dsp/upsampling_neon.c
@@ -58,8 +58,8 @@
} while (0)
// Turn the macro into a function for reducing code-size when non-critical
-static void Upsample16Pixels_NEON(const uint8_t *r1, const uint8_t *r2,
- uint8_t *out) {
+static void Upsample16Pixels_NEON(const uint8_t* r1, const uint8_t* r2,
+ uint8_t* out) {
UPSAMPLE_16PIXELS(r1, r2, out);
}
@@ -190,14 +190,14 @@ static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 };
}
#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \
-static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \
- const uint8_t *top_u, const uint8_t *top_v, \
- const uint8_t *cur_u, const uint8_t *cur_v, \
- uint8_t *top_dst, uint8_t *bottom_dst, int len) { \
+static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
+ const uint8_t* top_u, const uint8_t* top_v, \
+ const uint8_t* cur_u, const uint8_t* cur_v, \
+ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
int block; \
/* 16 byte aligned array to cache reconstructed u and v */ \
uint8_t uv_buf[2 * 32 + 15]; \
- uint8_t *const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
+ uint8_t* const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
const int uv_len = (len + 1) >> 1; \
/* 9 pixels must be read-able for each block */ \
const int num_blocks = (uv_len - 1) >> 3; \
diff --git a/thirdparty/libwebp/src/enc/histogram_enc.c b/thirdparty/libwebp/src/enc/histogram_enc.c
index d89b98524a..a4e6bf3a98 100644
--- a/thirdparty/libwebp/src/enc/histogram_enc.c
+++ b/thirdparty/libwebp/src/enc/histogram_enc.c
@@ -641,7 +641,7 @@ static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo,
// Merges some histograms with same bin_id together if it's advantageous.
// Sets the remaining histograms to NULL.
static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo,
- int *num_used,
+ int* num_used,
const uint16_t* const clusters,
uint16_t* const cluster_mappings,
VP8LHistogram* cur_combo,
diff --git a/thirdparty/libwebp/src/enc/picture_csp_enc.c b/thirdparty/libwebp/src/enc/picture_csp_enc.c
index 02d9df76d5..718e014ed2 100644
--- a/thirdparty/libwebp/src/enc/picture_csp_enc.c
+++ b/thirdparty/libwebp/src/enc/picture_csp_enc.c
@@ -29,11 +29,15 @@
#define USE_INVERSE_ALPHA_TABLE
#ifdef WORDS_BIGENDIAN
-#define ALPHA_OFFSET 0 // uint32_t 0xff000000 is 0xff,00,00,00 in memory
+// uint32_t 0xff000000 is 0xff,00,00,00 in memory
+#define CHANNEL_OFFSET(i) (i)
#else
-#define ALPHA_OFFSET 3 // uint32_t 0xff000000 is 0x00,00,00,ff in memory
+// uint32_t 0xff000000 is 0x00,00,00,ff in memory
+#define CHANNEL_OFFSET(i) (3-(i))
#endif
+#define ALPHA_OFFSET CHANNEL_OFFSET(0)
+
//------------------------------------------------------------------------------
// Detection of non-trivial transparency
@@ -997,10 +1001,10 @@ static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace,
return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
} else {
const uint8_t* const argb = (const uint8_t*)picture->argb;
- const uint8_t* const a = argb + (0 ^ ALPHA_OFFSET);
- const uint8_t* const r = argb + (1 ^ ALPHA_OFFSET);
- const uint8_t* const g = argb + (2 ^ ALPHA_OFFSET);
- const uint8_t* const b = argb + (3 ^ ALPHA_OFFSET);
+ const uint8_t* const a = argb + CHANNEL_OFFSET(0);
+ const uint8_t* const r = argb + CHANNEL_OFFSET(1);
+ const uint8_t* const g = argb + CHANNEL_OFFSET(2);
+ const uint8_t* const b = argb + CHANNEL_OFFSET(3);
picture->colorspace = WEBP_YUV420;
return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride,
@@ -1050,7 +1054,7 @@ int WebPPictureYUVAToARGB(WebPPicture* picture) {
const int height = picture->height;
const int argb_stride = 4 * picture->argb_stride;
uint8_t* dst = (uint8_t*)picture->argb;
- const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
+ const uint8_t* cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
WebPUpsampleLinePairFunc upsample =
WebPGetLinePairConverter(ALPHA_OFFSET > 0);
diff --git a/thirdparty/libwebp/src/enc/vp8i_enc.h b/thirdparty/libwebp/src/enc/vp8i_enc.h
index 24e1944610..fedcaeea27 100644
--- a/thirdparty/libwebp/src/enc/vp8i_enc.h
+++ b/thirdparty/libwebp/src/enc/vp8i_enc.h
@@ -31,8 +31,8 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 1
-#define ENC_MIN_VERSION 0
-#define ENC_REV_VERSION 3
+#define ENC_MIN_VERSION 1
+#define ENC_REV_VERSION 0
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
@@ -249,7 +249,7 @@ typedef struct {
int percent0_; // saved initial progress percent
DError left_derr_; // left error diffusion (u/v)
- DError *top_derr_; // top diffusion error - NULL if disabled
+ DError* top_derr_; // top diffusion error - NULL if disabled
uint8_t* y_left_; // left luma samples (addressable from index -1 to 15).
uint8_t* u_left_; // left u samples (addressable from index -1 to 7)
diff --git a/thirdparty/libwebp/src/mux/muxi.h b/thirdparty/libwebp/src/mux/muxi.h
index 7bc0b07e9b..ad3e1bdb97 100644
--- a/thirdparty/libwebp/src/mux/muxi.h
+++ b/thirdparty/libwebp/src/mux/muxi.h
@@ -28,8 +28,8 @@ extern "C" {
// Defines and constants.
#define MUX_MAJ_VERSION 1
-#define MUX_MIN_VERSION 0
-#define MUX_REV_VERSION 3
+#define MUX_MIN_VERSION 1
+#define MUX_REV_VERSION 0
// Chunk object.
typedef struct WebPChunk WebPChunk;
diff --git a/thirdparty/libwebp/src/mux/muxread.c b/thirdparty/libwebp/src/mux/muxread.c
index 268f6acb53..ae3b876bc5 100644
--- a/thirdparty/libwebp/src/mux/muxread.c
+++ b/thirdparty/libwebp/src/mux/muxread.c
@@ -100,7 +100,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
WebPMuxImage* const wpi) {
const uint8_t* bytes = chunk->data_.bytes;
size_t size = chunk->data_.size;
- const uint8_t* const last = bytes + size;
+ const uint8_t* const last = (bytes == NULL) ? NULL : bytes + size;
WebPChunk subchunk;
size_t subchunk_size;
WebPChunk** unknown_chunk_list = &wpi->unknown_;
diff --git a/thirdparty/libwebp/src/utils/color_cache_utils.h b/thirdparty/libwebp/src/utils/color_cache_utils.h
index ec21d5199b..b45d47c2d5 100644
--- a/thirdparty/libwebp/src/utils/color_cache_utils.h
+++ b/thirdparty/libwebp/src/utils/color_cache_utils.h
@@ -26,7 +26,7 @@ extern "C" {
// Main color cache struct.
typedef struct {
- uint32_t *colors_; // color entries
+ uint32_t* colors_; // color entries
int hash_shift_; // Hash shift: 32 - hash_bits_.
int hash_bits_;
} VP8LColorCache;
diff --git a/thirdparty/libwebp/src/utils/thread_utils.c b/thirdparty/libwebp/src/utils/thread_utils.c
index 438296b45f..4e470e17ac 100644
--- a/thirdparty/libwebp/src/utils/thread_utils.c
+++ b/thirdparty/libwebp/src/utils/thread_utils.c
@@ -73,7 +73,7 @@ typedef struct {
#endif
static int pthread_create(pthread_t* const thread, const void* attr,
- unsigned int (__stdcall *start)(void*), void* arg) {
+ unsigned int (__stdcall* start)(void*), void* arg) {
(void)attr;
#ifdef USE_CREATE_THREAD
*thread = CreateThread(NULL, /* lpThreadAttributes */
diff --git a/thirdparty/libwebp/src/utils/utils.c b/thirdparty/libwebp/src/utils/utils.c
index 44d5c14f01..764f752b82 100644
--- a/thirdparty/libwebp/src/utils/utils.c
+++ b/thirdparty/libwebp/src/utils/utils.c
@@ -216,9 +216,14 @@ void WebPSafeFree(void* const ptr) {
free(ptr);
}
-// Public API function.
+// Public API functions.
+
+void* WebPMalloc(size_t size) {
+ return WebPSafeMalloc(1, size);
+}
+
void WebPFree(void* ptr) {
- free(ptr);
+ WebPSafeFree(ptr);
}
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/webp/decode.h b/thirdparty/libwebp/src/webp/decode.h
index ae8bfe840e..80dd0ef0cc 100644
--- a/thirdparty/libwebp/src/webp/decode.h
+++ b/thirdparty/libwebp/src/webp/decode.h
@@ -20,7 +20,7 @@
extern "C" {
#endif
-#define WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b)
+#define WEBP_DECODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b)
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
// the types are left here for reference.
@@ -91,9 +91,6 @@ WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
uint8_t** u, uint8_t** v,
int* stride, int* uv_stride);
-// Releases memory returned by the WebPDecode*() functions above.
-WEBP_EXTERN void WebPFree(void* ptr);
-
// These five functions are variants of the above ones, that decode the image
// directly into a pre-allocated buffer 'output_buffer'. The maximum storage
// available in this buffer is indicated by 'output_buffer_size'. If this
diff --git a/thirdparty/libwebp/src/webp/encode.h b/thirdparty/libwebp/src/webp/encode.h
index 339f8810aa..655166e7d4 100644
--- a/thirdparty/libwebp/src/webp/encode.h
+++ b/thirdparty/libwebp/src/webp/encode.h
@@ -20,7 +20,7 @@
extern "C" {
#endif
-#define WEBP_ENCODER_ABI_VERSION 0x020e // MAJOR(8b) + MINOR(8b)
+#define WEBP_ENCODER_ABI_VERSION 0x020f // MAJOR(8b) + MINOR(8b)
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
// the types are left here for reference.
@@ -79,9 +79,6 @@ WEBP_EXTERN size_t WebPEncodeLosslessBGRA(const uint8_t* bgra,
int width, int height, int stride,
uint8_t** output);
-// Releases memory returned by the WebPEncode*() functions above.
-WEBP_EXTERN void WebPFree(void* ptr);
-
//------------------------------------------------------------------------------
// Coding parameters
@@ -306,7 +303,7 @@ struct WebPPicture {
// YUV input (mostly used for input to lossy compression)
WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr).
int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION)
- uint8_t *y, *u, *v; // pointers to luma/chroma planes.
+ uint8_t* y, *u, *v; // pointers to luma/chroma planes.
int y_stride, uv_stride; // luma/chroma strides.
uint8_t* a; // pointer to the alpha plane
int a_stride; // stride of the alpha plane
@@ -350,7 +347,7 @@ struct WebPPicture {
uint32_t pad3[3]; // padding for later use
// Unused for now
- uint8_t *pad4, *pad5;
+ uint8_t* pad4, *pad5;
uint32_t pad6[8]; // padding for later use
// PRIVATE FIELDS
diff --git a/thirdparty/libwebp/src/webp/mux.h b/thirdparty/libwebp/src/webp/mux.h
index 66096a92e0..7d27489a40 100644
--- a/thirdparty/libwebp/src/webp/mux.h
+++ b/thirdparty/libwebp/src/webp/mux.h
@@ -57,7 +57,7 @@ extern "C" {
WebPMuxGetChunk(mux, "ICCP", &icc_profile);
// ... (Consume icc_data).
WebPMuxDelete(mux);
- free(data);
+ WebPFree(data);
*/
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
@@ -245,7 +245,7 @@ WEBP_EXTERN WebPMuxError WebPMuxPushFrame(
WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data);
// Gets the nth frame from the mux object.
-// The content of 'frame->bitstream' is allocated using malloc(), and NOT
+// The content of 'frame->bitstream' is allocated using WebPMalloc(), and NOT
// owned by the 'mux' object. It MUST be deallocated by the caller by calling
// WebPDataClear().
// nth=0 has a special meaning - last position.
@@ -376,10 +376,10 @@ WEBP_EXTERN WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'.
// This function also validates the mux object.
// Note: The content of 'assembled_data' will be ignored and overwritten.
-// Also, the content of 'assembled_data' is allocated using malloc(), and NOT
-// owned by the 'mux' object. It MUST be deallocated by the caller by calling
-// WebPDataClear(). It's always safe to call WebPDataClear() upon return,
-// even in case of error.
+// Also, the content of 'assembled_data' is allocated using WebPMalloc(), and
+// NOT owned by the 'mux' object. It MUST be deallocated by the caller by
+// calling WebPDataClear(). It's always safe to call WebPDataClear() upon
+// return, even in case of error.
// Parameters:
// mux - (in/out) object whose chunks are to be assembled
// assembled_data - (out) assembled WebP data
diff --git a/thirdparty/libwebp/src/webp/mux_types.h b/thirdparty/libwebp/src/webp/mux_types.h
index ceea77dfc6..2fe8195839 100644
--- a/thirdparty/libwebp/src/webp/mux_types.h
+++ b/thirdparty/libwebp/src/webp/mux_types.h
@@ -14,7 +14,6 @@
#ifndef WEBP_WEBP_MUX_TYPES_H_
#define WEBP_WEBP_MUX_TYPES_H_
-#include <stdlib.h> // free()
#include <string.h> // memset()
#include "./types.h"
@@ -56,6 +55,7 @@ typedef enum WebPMuxAnimBlend {
// Data type used to describe 'raw' data, e.g., chunk data
// (ICC profile, metadata) and WebP compressed image data.
+// 'bytes' memory must be allocated using WebPMalloc() and such.
struct WebPData {
const uint8_t* bytes;
size_t size;
@@ -68,11 +68,11 @@ static WEBP_INLINE void WebPDataInit(WebPData* webp_data) {
}
}
-// Clears the contents of the 'webp_data' object by calling free(). Does not
-// deallocate the object itself.
+// Clears the contents of the 'webp_data' object by calling WebPFree().
+// Does not deallocate the object itself.
static WEBP_INLINE void WebPDataClear(WebPData* webp_data) {
if (webp_data != NULL) {
- free((void*)webp_data->bytes);
+ WebPFree((void*)webp_data->bytes);
WebPDataInit(webp_data);
}
}
@@ -83,7 +83,7 @@ static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
if (src == NULL || dst == NULL) return 0;
WebPDataInit(dst);
if (src->bytes != NULL && src->size != 0) {
- dst->bytes = (uint8_t*)malloc(src->size);
+ dst->bytes = (uint8_t*)WebPMalloc(src->size);
if (dst->bytes == NULL) return 0;
memcpy((void*)dst->bytes, src->bytes, src->size);
dst->size = src->size;
diff --git a/thirdparty/libwebp/src/webp/types.h b/thirdparty/libwebp/src/webp/types.h
index 0ce2622e41..47f7f2b007 100644
--- a/thirdparty/libwebp/src/webp/types.h
+++ b/thirdparty/libwebp/src/webp/types.h
@@ -7,7 +7,7 @@
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
-// Common types
+// Common types + memory wrappers
//
// Author: Skal (pascal.massimino@gmail.com)
@@ -49,4 +49,20 @@ typedef long long int int64_t;
// Macro to check ABI compatibility (same major revision number)
#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Allocates 'size' bytes of memory. Returns NULL upon error. Memory
+// must be deallocated by calling WebPFree(). This function is made available
+// by the core 'libwebp' library.
+WEBP_EXTERN void* WebPMalloc(size_t size);
+
+// Releases memory returned by the WebPDecode*() functions (from decode.h).
+WEBP_EXTERN void WebPFree(void* ptr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // WEBP_WEBP_TYPES_H_
diff --git a/thirdparty/mbedtls/include/mbedtls/bignum.h b/thirdparty/mbedtls/include/mbedtls/bignum.h
index 1c8607264f..22b373113e 100644
--- a/thirdparty/mbedtls/include/mbedtls/bignum.h
+++ b/thirdparty/mbedtls/include/mbedtls/bignum.h
@@ -184,7 +184,7 @@ extern "C" {
*/
typedef struct mbedtls_mpi
{
- int s; /*!< integer sign */
+ int s; /*!< Sign: -1 if the mpi is negative, 1 otherwise */
size_t n; /*!< total # of limbs */
mbedtls_mpi_uint *p; /*!< pointer to limbs */
}
@@ -560,6 +560,24 @@ int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y );
int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y );
/**
+ * \brief Check if an MPI is less than the other in constant time.
+ *
+ * \param X The left-hand MPI. This must point to an initialized MPI
+ * with the same allocated length as Y.
+ * \param Y The right-hand MPI. This must point to an initialized MPI
+ * with the same allocated length as X.
+ * \param ret The result of the comparison:
+ * \c 1 if \p X is less than \p Y.
+ * \c 0 if \p X is greater than or equal to \p Y.
+ *
+ * \return 0 on success.
+ * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of
+ * the two input MPIs is not the same.
+ */
+int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
+ unsigned *ret );
+
+/**
* \brief Compare an MPI with an integer.
*
* \param X The left-hand MPI. This must point to an initialized MPI.
diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h
index 6eabcc8748..93de091c4d 100644
--- a/thirdparty/mbedtls/include/mbedtls/check_config.h
+++ b/thirdparty/mbedtls/include/mbedtls/check_config.h
@@ -281,6 +281,14 @@
#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
+#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites"
+#endif
+
+#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
+#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites"
+#endif
+
#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
#endif
@@ -538,6 +546,23 @@
#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
#endif
+#if (defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \
+ !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) )
+#error "One or more versions of the TLS protocol are enabled " \
+ "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx"
+#endif
+
#if defined(MBEDTLS_SSL_PROTO_DTLS) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
@@ -661,6 +686,10 @@
#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_CERTS_C) && !defined(MBEDTLS_X509_USE_C)
+#error "MBEDTLS_CERTS_C defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )
#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites"
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h
index 0cc502cd79..8d9c31a504 100644
--- a/thirdparty/mbedtls/include/mbedtls/config.h
+++ b/thirdparty/mbedtls/include/mbedtls/config.h
@@ -689,6 +689,13 @@
#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
#define MBEDTLS_CIPHER_PADDING_ZEROS
+/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
+ *
+ * Uncomment this macro to use a 128-bit key in the CTR_DRBG module.
+ * By default, CTR_DRBG uses a 256-bit key.
+ */
+//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
+
/**
* \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES
*
@@ -2149,7 +2156,11 @@
*
* Enable the CTR_DRBG AES-based random generator.
* The CTR_DRBG generator uses AES-256 by default.
- * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below.
+ * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above.
+ *
+ * \note To achieve a 256-bit security strength with CTR_DRBG,
+ * you must use AES-256 *and* use sufficient entropy.
+ * See ctr_drbg.h for more details.
*
* Module: library/ctr_drbg.c
* Caller:
@@ -3043,7 +3054,6 @@
//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
-//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */
/* HMAC_DRBG options */
//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
index cc3df7b113..e0b5ed9c93 100644
--- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
+++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
@@ -1,7 +1,8 @@
/**
* \file ctr_drbg.h
*
- * \brief This file contains CTR_DRBG definitions and functions.
+ * \brief This file contains definitions and functions for the
+ * CTR_DRBG pseudorandom generator.
*
* CTR_DRBG is a standardized way of building a PRNG from a block-cipher
* in counter mode operation, as defined in <em>NIST SP 800-90A:
@@ -9,13 +10,35 @@
* Bit Generators</em>.
*
* The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128
- * as the underlying block cipher.
- *
- * \warning Using 128-bit keys for CTR_DRBG limits the security of generated
- * keys and operations that use random values generated to 128-bit security.
+ * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time)
+ * as the underlying block cipher, with a derivation function.
+ * The initial seeding grabs #MBEDTLS_CTR_DRBG_ENTROPY_LEN bytes of entropy.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more details.
+ *
+ * Based on NIST SP 800-90A §10.2.1 table 3 and NIST SP 800-57 part 1 table 2,
+ * here are the security strengths achieved in typical configuration:
+ * - 256 bits under the default configuration of the library, with AES-256
+ * and with #MBEDTLS_CTR_DRBG_ENTROPY_LEN set to 48 or more.
+ * - 256 bits if AES-256 is used, #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set
+ * to 32 or more, and the DRBG is initialized with an explicit
+ * nonce in the \c custom parameter to mbedtls_ctr_drbg_seed().
+ * - 128 bits if AES-256 is used but #MBEDTLS_CTR_DRBG_ENTROPY_LEN is
+ * between 24 and 47 and the DRBG is not initialized with an explicit
+ * nonce (see mbedtls_ctr_drbg_seed()).
+ * - 128 bits if AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
+ * and #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set to 24 or more (which is
+ * always the case unless it is explicitly set to a different value
+ * in config.h).
+ *
+ * Note that the value of #MBEDTLS_CTR_DRBG_ENTROPY_LEN defaults to:
+ * - \c 48 if the module \c MBEDTLS_SHA512_C is enabled and the symbol
+ * \c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled at compile time.
+ * This is the default configuration of the library.
+ * - \c 32 if the module \c MBEDTLS_SHA512_C is disabled at compile time.
+ * - \c 32 if \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled at compile time.
*/
/*
- * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -56,9 +79,19 @@
#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */
#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
-#define MBEDTLS_CTR_DRBG_KEYSIZE 16 /**< The key size used by the cipher (compile-time choice: 128 bits). */
+#define MBEDTLS_CTR_DRBG_KEYSIZE 16
+/**< The key size in bytes used by the cipher.
+ *
+ * Compile-time choice: 16 bytes (128 bits)
+ * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled.
+ */
#else
-#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher (compile-time choice: 256 bits). */
+#define MBEDTLS_CTR_DRBG_KEYSIZE 32
+/**< The key size in bytes used by the cipher.
+ *
+ * Compile-time choice: 32 bytes (256 bits)
+ * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled.
+ */
#endif
#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */
@@ -73,21 +106,31 @@
* \{
*/
+/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN
+ *
+ * \brief The amount of entropy used per seed by default, in bytes.
+ */
#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN)
#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256)
+/** This is 48 bytes because the entropy module uses SHA-512
+ * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled).
+ */
#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48
-/**< The amount of entropy used per seed by default:
- * <ul><li>48 with SHA-512.</li>
- * <li>32 with SHA-256.</li></ul>
+
+#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */
+
+/** This is 32 bytes because the entropy module uses SHA-256
+ * (the SHA512 module is disabled or
+ * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled).
*/
-#else
-#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32
-/**< Amount of entropy used per seed by default:
- * <ul><li>48 with SHA-512.</li>
- * <li>32 with SHA-256.</li></ul>
+#if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+/** \warning To achieve a 256-bit security strength, you must pass a nonce
+ * to mbedtls_ctr_drbg_seed().
*/
-#endif
-#endif
+#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */
+#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32
+#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */
+#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */
#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL)
#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000
@@ -106,7 +149,7 @@
#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT)
#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384
-/**< The maximum size of seed or reseed buffer. */
+/**< The maximum size of seed or reseed buffer in bytes. */
#endif
/* \} name SECTION: Module settings */
@@ -164,17 +207,68 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
* \brief This function seeds and sets up the CTR_DRBG
* entropy source for future reseeds.
*
- * \note Personalization data can be provided in addition to the more generic
- * entropy source, to make this instantiation as unique as possible.
- *
+ * A typical choice for the \p f_entropy and \p p_entropy parameters is
+ * to use the entropy module:
+ * - \p f_entropy is mbedtls_entropy_func();
+ * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized
+ * with mbedtls_entropy_init() (which registers the platform's default
+ * entropy sources).
+ *
+ * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default.
+ * You can override it by calling mbedtls_ctr_drbg_set_entropy_len().
+ *
+ * You can provide a personalization string in addition to the
+ * entropy source, to make this instantiation as unique as possible.
+ *
+ * \note The _seed_material_ value passed to the derivation
+ * function in the CTR_DRBG Instantiate Process
+ * described in NIST SP 800-90A §10.2.1.3.2
+ * is the concatenation of the string obtained from
+ * calling \p f_entropy and the \p custom string.
+ * The origin of the nonce depends on the value of
+ * the entropy length relative to the security strength.
+ * - If the entropy length is at least 1.5 times the
+ * security strength then the nonce is taken from the
+ * string obtained with \p f_entropy.
+ * - If the entropy length is less than the security
+ * strength, then the nonce is taken from \p custom.
+ * In this case, for compliance with SP 800-90A,
+ * you must pass a unique value of \p custom at
+ * each invocation. See SP 800-90A §8.6.7 for more
+ * details.
+ */
+#if MBEDTLS_CTR_DRBG_ENTROPY_LEN < MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
+/** \warning When #MBEDTLS_CTR_DRBG_ENTROPY_LEN is less than
+ * #MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2, to achieve the
+ * maximum security strength permitted by CTR_DRBG,
+ * you must pass a value of \p custom that is a nonce:
+ * this value must never be repeated in subsequent
+ * runs of the same application or on a different
+ * device.
+ */
+#endif
+/**
* \param ctx The CTR_DRBG context to seed.
+ * It must have been initialized with
+ * mbedtls_ctr_drbg_init().
+ * After a successful call to mbedtls_ctr_drbg_seed(),
+ * you may not call mbedtls_ctr_drbg_seed() again on
+ * the same context unless you call
+ * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
+ * again first.
* \param f_entropy The entropy callback, taking as arguments the
* \p p_entropy context, the buffer to fill, and the
- length of the buffer.
- * \param p_entropy The entropy context.
- * \param custom Personalization data, that is device-specific
- identifiers. Can be NULL.
- * \param len The length of the personalization data.
+ * length of the buffer.
+ * \p f_entropy is always called with a buffer size
+ * equal to the entropy length.
+ * \param p_entropy The entropy context to pass to \p f_entropy.
+ * \param custom The personalization string.
+ * This can be \c NULL, in which case the personalization
+ * string is empty regardless of the value of \p len.
+ * \param len The length of the personalization string.
+ * This must be at most
+ * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ * - #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
@@ -197,7 +291,8 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx );
* The default value is off.
*
* \note If enabled, entropy is gathered at the beginning of
- * every call to mbedtls_ctr_drbg_random_with_add().
+ * every call to mbedtls_ctr_drbg_random_with_add()
+ * or mbedtls_ctr_drbg_random().
* Only use this if your entropy source has sufficient
* throughput.
*
@@ -209,18 +304,37 @@ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
/**
* \brief This function sets the amount of entropy grabbed on each
- * seed or reseed. The default value is
- * #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
+ * seed or reseed.
+ *
+ * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
+ *
+ * \note The security strength of CTR_DRBG is bounded by the
+ * entropy length. Thus:
+ * - When using AES-256
+ * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled,
+ * which is the default),
+ * \p len must be at least 32 (in bytes)
+ * to achieve a 256-bit strength.
+ * - When using AES-128
+ * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled)
+ * \p len must be at least 16 (in bytes)
+ * to achieve a 128-bit strength.
*
* \param ctx The CTR_DRBG context.
- * \param len The amount of entropy to grab.
+ * \param len The amount of entropy to grab, in bytes.
+ * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
*/
void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
size_t len );
/**
* \brief This function sets the reseed interval.
- * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL.
+ *
+ * The reseed interval is the number of calls to mbedtls_ctr_drbg_random()
+ * or mbedtls_ctr_drbg_random_with_add() after which the entropy function
+ * is called again.
+ *
+ * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL.
*
* \param ctx The CTR_DRBG context.
* \param interval The reseed interval.
@@ -233,8 +347,12 @@ void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
* extracts data from the entropy source.
*
* \param ctx The CTR_DRBG context.
- * \param additional Additional data to add to the state. Can be NULL.
+ * \param additional Additional data to add to the state. Can be \c NULL.
* \param len The length of the additional data.
+ * This must be less than
+ * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len
+ * where \c entropy_len is the entropy length
+ * configured for the context.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
@@ -246,7 +364,8 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
* \brief This function updates the state of the CTR_DRBG context.
*
* \param ctx The CTR_DRBG context.
- * \param additional The data to update the state with.
+ * \param additional The data to update the state with. This must not be
+ * \c NULL unless \p add_len is \c 0.
* \param add_len Length of \p additional in bytes. This must be at
* most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
*
@@ -264,14 +383,23 @@ int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
* \brief This function updates a CTR_DRBG instance with additional
* data and uses it to generate random data.
*
- * \note The function automatically reseeds if the reseed counter is exceeded.
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
*
* \param p_rng The CTR_DRBG context. This must be a pointer to a
* #mbedtls_ctr_drbg_context structure.
* \param output The buffer to fill.
- * \param output_len The length of the buffer.
- * \param additional Additional data to update. Can be NULL.
- * \param add_len The length of the additional data.
+ * \param output_len The length of the buffer in bytes.
+ * \param additional Additional data to update. Can be \c NULL, in which
+ * case the additional data is empty regardless of
+ * the value of \p add_len.
+ * \param add_len The length of the additional data
+ * if \p additional is not \c NULL.
+ * This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT
+ * and less than
+ * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len
+ * where \c entropy_len is the entropy length
+ * configured for the context.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
@@ -284,12 +412,14 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
/**
* \brief This function uses CTR_DRBG to generate random data.
*
- * \note The function automatically reseeds if the reseed counter is exceeded.
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
+ *
*
* \param p_rng The CTR_DRBG context. This must be a pointer to a
* #mbedtls_ctr_drbg_context structure.
* \param output The buffer to fill.
- * \param output_len The length of the buffer.
+ * \param output_len The length of the buffer in bytes.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
@@ -336,7 +466,7 @@ MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update(
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
- * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on
+ * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed
* failure.
*/
int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path );
@@ -350,8 +480,10 @@ int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
- * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
- * #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG on failure.
+ * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on
+ * reseed failure.
+ * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing
+ * seed file is too large.
*/
int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path );
#endif /* MBEDTLS_FS_IO */
diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
index f1289cb306..7931c2281c 100644
--- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
+++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
@@ -1,10 +1,14 @@
/**
* \file hmac_drbg.h
*
- * \brief HMAC_DRBG (NIST SP 800-90A)
+ * \brief The HMAC_DRBG pseudorandom generator.
+ *
+ * This module implements the HMAC_DRBG pseudorandom generator described
+ * in <em>NIST SP 800-90A: Recommendation for Random Number Generation Using
+ * Deterministic Random Bit Generators</em>.
*/
/*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2019, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -104,38 +108,72 @@ typedef struct mbedtls_hmac_drbg_context
} mbedtls_hmac_drbg_context;
/**
- * \brief HMAC_DRBG context initialization
- * Makes the context ready for mbedtls_hmac_drbg_seed(),
- * mbedtls_hmac_drbg_seed_buf() or
- * mbedtls_hmac_drbg_free().
+ * \brief HMAC_DRBG context initialization.
+ *
+ * This function makes the context ready for mbedtls_hmac_drbg_seed(),
+ * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free().
*
- * \param ctx HMAC_DRBG context to be initialized
+ * \param ctx HMAC_DRBG context to be initialized.
*/
void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
/**
- * \brief HMAC_DRBG initial seeding
- * Seed and setup entropy source for future reseeds.
- *
- * \param ctx HMAC_DRBG context to be seeded
- * \param md_info MD algorithm to use for HMAC_DRBG
- * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer
- * length)
- * \param p_entropy Entropy context
- * \param custom Personalization data (Device specific identifiers)
- * (Can be NULL)
- * \param len Length of personalization data
- *
- * \note The "security strength" as defined by NIST is set to:
- * 128 bits if md_alg is SHA-1,
- * 192 bits if md_alg is SHA-224,
- * 256 bits if md_alg is SHA-256 or higher.
- * Note that SHA-256 is just as efficient as SHA-224.
+ * \brief HMAC_DRBG initial seeding.
+ *
+ * Set the initial seed and set up the entropy source for future reseeds.
+ *
+ * A typical choice for the \p f_entropy and \p p_entropy parameters is
+ * to use the entropy module:
+ * - \p f_entropy is mbedtls_entropy_func();
+ * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized
+ * with mbedtls_entropy_init() (which registers the platform's default
+ * entropy sources).
+ *
+ * You can provide a personalization string in addition to the
+ * entropy source, to make this instantiation as unique as possible.
*
- * \return 0 if successful, or
- * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or
- * MBEDTLS_ERR_MD_ALLOC_FAILED, or
- * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED.
+ * \note By default, the security strength as defined by NIST is:
+ * - 128 bits if \p md_info is SHA-1;
+ * - 192 bits if \p md_info is SHA-224;
+ * - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512.
+ * Note that SHA-256 is just as efficient as SHA-224.
+ * The security strength can be reduced if a smaller
+ * entropy length is set with
+ * mbedtls_hmac_drbg_set_entropy_len().
+ *
+ * \note The default entropy length is the security strength
+ * (converted from bits to bytes). You can override
+ * it by calling mbedtls_hmac_drbg_set_entropy_len().
+ *
+ * \note During the initial seeding, this function calls
+ * the entropy source to obtain a nonce
+ * whose length is half the entropy length.
+ *
+ * \param ctx HMAC_DRBG context to be seeded.
+ * \param md_info MD algorithm to use for HMAC_DRBG.
+ * \param f_entropy The entropy callback, taking as arguments the
+ * \p p_entropy context, the buffer to fill, and the
+ * length of the buffer.
+ * \p f_entropy is always called with a length that is
+ * less than or equal to the entropy length.
+ * \param p_entropy The entropy context to pass to \p f_entropy.
+ * \param custom The personalization string.
+ * This can be \c NULL, in which case the personalization
+ * string is empty regardless of the value of \p len.
+ * \param len The length of the personalization string.
+ * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
+ * and also at most
+ * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2
+ * where \p entropy_len is the entropy length
+ * described above.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is
+ * invalid.
+ * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough
+ * memory to allocate context data.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ * if the call to \p f_entropy failed.
*/
int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
const mbedtls_md_info_t * md_info,
@@ -146,98 +184,131 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
/**
* \brief Initilisation of simpified HMAC_DRBG (never reseeds).
- * (For use with deterministic ECDSA.)
*
- * \param ctx HMAC_DRBG context to be initialised
- * \param md_info MD algorithm to use for HMAC_DRBG
- * \param data Concatenation of entropy string and additional data
- * \param data_len Length of data in bytes
+ * This function is meant for use in algorithms that need a pseudorandom
+ * input such as deterministic ECDSA.
+ *
+ * \param ctx HMAC_DRBG context to be initialised.
+ * \param md_info MD algorithm to use for HMAC_DRBG.
+ * \param data Concatenation of the initial entropy string and
+ * the additional data.
+ * \param data_len Length of \p data in bytes.
*
- * \return 0 if successful, or
- * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or
- * MBEDTLS_ERR_MD_ALLOC_FAILED.
+ * \return \c 0 if successful. or
+ * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is
+ * invalid.
+ * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough
+ * memory to allocate context data.
*/
int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
const mbedtls_md_info_t * md_info,
const unsigned char *data, size_t data_len );
/**
- * \brief Enable / disable prediction resistance (Default: Off)
+ * \brief This function turns prediction resistance on or off.
+ * The default value is off.
*
- * Note: If enabled, entropy is used for ctx->entropy_len before each call!
- * Only use this if you have ample supply of good entropy!
+ * \note If enabled, entropy is gathered at the beginning of
+ * every call to mbedtls_hmac_drbg_random_with_add()
+ * or mbedtls_hmac_drbg_random().
+ * Only use this if your entropy source has sufficient
+ * throughput.
*
- * \param ctx HMAC_DRBG context
- * \param resistance MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF
+ * \param ctx The HMAC_DRBG context.
+ * \param resistance #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF.
*/
void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
int resistance );
/**
- * \brief Set the amount of entropy grabbed on each reseed
- * (Default: given by the security strength, which
- * depends on the hash used, see \c mbedtls_hmac_drbg_init() )
+ * \brief This function sets the amount of entropy grabbed on each
+ * seed or reseed.
+ *
+ * See the documentation of mbedtls_hmac_drbg_seed() for the default value.
*
- * \param ctx HMAC_DRBG context
- * \param len Amount of entropy to grab, in bytes
+ * \param ctx The HMAC_DRBG context.
+ * \param len The amount of entropy to grab, in bytes.
*/
void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx,
size_t len );
/**
- * \brief Set the reseed interval
- * (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)
+ * \brief Set the reseed interval.
*
- * \param ctx HMAC_DRBG context
- * \param interval Reseed interval
+ * The reseed interval is the number of calls to mbedtls_hmac_drbg_random()
+ * or mbedtls_hmac_drbg_random_with_add() after which the entropy function
+ * is called again.
+ *
+ * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL.
+ *
+ * \param ctx The HMAC_DRBG context.
+ * \param interval The reseed interval.
*/
void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
int interval );
/**
- * \brief HMAC_DRBG update state
+ * \brief This function updates the state of the HMAC_DRBG context.
*
- * \param ctx HMAC_DRBG context
- * \param additional Additional data to update state with, or NULL
- * \param add_len Length of additional data, or 0
+ * \param ctx The HMAC_DRBG context.
+ * \param additional The data to update the state with.
+ * If this is \c NULL, there is no additional data.
+ * \param add_len Length of \p additional in bytes.
+ * Unused if \p additional is \c NULL.
*
* \return \c 0 on success, or an error from the underlying
* hash calculation.
- *
- * \note Additional data is optional, pass NULL and 0 as second
- * third argument if no additional data is being used.
*/
int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len );
/**
- * \brief HMAC_DRBG reseeding (extracts data from entropy source)
- *
- * \param ctx HMAC_DRBG context
- * \param additional Additional data to add to state (Can be NULL)
- * \param len Length of additional data
- *
- * \return 0 if successful, or
- * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ * \brief This function reseeds the HMAC_DRBG context, that is
+ * extracts data from the entropy source.
+ *
+ * \param ctx The HMAC_DRBG context.
+ * \param additional Additional data to add to the state.
+ * If this is \c NULL, there is no additional data
+ * and \p len should be \c 0.
+ * \param len The length of the additional data.
+ * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
+ * and also at most
+ * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len
+ * where \p entropy_len is the entropy length
+ * (see mbedtls_hmac_drbg_set_entropy_len()).
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ * if a call to the entropy function failed.
*/
int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t len );
/**
- * \brief HMAC_DRBG generate random with additional update input
- *
- * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
- *
- * \param p_rng HMAC_DRBG context
- * \param output Buffer to fill
- * \param output_len Length of the buffer
- * \param additional Additional data to update with (can be NULL)
- * \param add_len Length of additional data (can be 0)
- *
- * \return 0 if successful, or
- * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
- * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or
- * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG.
+ * \brief This function updates an HMAC_DRBG instance with additional
+ * data and uses it to generate random data.
+ *
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
+ *
+ * \param p_rng The HMAC_DRBG context. This must be a pointer to a
+ * #mbedtls_hmac_drbg_context structure.
+ * \param output The buffer to fill.
+ * \param output_len The length of the buffer in bytes.
+ * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
+ * \param additional Additional data to update with.
+ * If this is \c NULL, there is no additional data
+ * and \p add_len should be \c 0.
+ * \param add_len The length of the additional data.
+ * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ * if a call to the entropy source failed.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if
+ * \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if
+ * \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT.
*/
int mbedtls_hmac_drbg_random_with_add( void *p_rng,
unsigned char *output, size_t output_len,
@@ -245,24 +316,29 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
size_t add_len );
/**
- * \brief HMAC_DRBG generate random
- *
- * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
- *
- * \param p_rng HMAC_DRBG context
- * \param output Buffer to fill
- * \param out_len Length of the buffer
- *
- * \return 0 if successful, or
- * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
- * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG
+ * \brief This function uses HMAC_DRBG to generate random data.
+ *
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
+ *
+ * \param p_rng The HMAC_DRBG context. This must be a pointer to a
+ * #mbedtls_hmac_drbg_context structure.
+ * \param output The buffer to fill.
+ * \param out_len The length of the buffer in bytes.
+ * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ * if a call to the entropy source failed.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if
+ * \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
*/
int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len );
/**
* \brief Free an HMAC_DRBG context
*
- * \param ctx HMAC_DRBG context to free.
+ * \param ctx The HMAC_DRBG context to free.
*/
void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx );
@@ -273,17 +349,16 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx );
#define MBEDTLS_DEPRECATED
#endif
/**
- * \brief HMAC_DRBG update state
+ * \brief This function updates the state of the HMAC_DRBG context.
*
* \deprecated Superseded by mbedtls_hmac_drbg_update_ret()
* in 2.16.0.
*
- * \param ctx HMAC_DRBG context
- * \param additional Additional data to update state with, or NULL
- * \param add_len Length of additional data, or 0
- *
- * \note Additional data is optional, pass NULL and 0 as second
- * third argument if no additional data is being used.
+ * \param ctx The HMAC_DRBG context.
+ * \param additional The data to update the state with.
+ * If this is \c NULL, there is no additional data.
+ * \param add_len Length of \p additional in bytes.
+ * Unused if \p additional is \c NULL.
*/
MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update(
mbedtls_hmac_drbg_context *ctx,
@@ -293,26 +368,31 @@ MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update(
#if defined(MBEDTLS_FS_IO)
/**
- * \brief Write a seed file
+ * \brief This function writes a seed file.
*
- * \param ctx HMAC_DRBG context
- * \param path Name of the file
+ * \param ctx The HMAC_DRBG context.
+ * \param path The name of the file.
*
- * \return 0 if successful, 1 on file error, or
- * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed
+ * failure.
*/
int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
/**
- * \brief Read and update a seed file. Seed is added to this
- * instance
- *
- * \param ctx HMAC_DRBG context
- * \param path Name of the file
- *
- * \return 0 if successful, 1 on file error,
- * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or
- * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG
+ * \brief This function reads and updates a seed file. The seed
+ * is added to this instance.
+ *
+ * \param ctx The HMAC_DRBG context.
+ * \param path The name of the file.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on
+ * reseed failure.
+ * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing
+ * seed file is too large.
*/
int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
#endif /* MBEDTLS_FS_IO */
@@ -320,9 +400,10 @@ int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const ch
#if defined(MBEDTLS_SELF_TEST)
/**
- * \brief Checkup routine
+ * \brief The HMAC_DRBG Checkup routine.
*
- * \return 0 if successful, or 1 if the test failed
+ * \return \c 0 if successful.
+ * \return \c 1 if the test failed.
*/
int mbedtls_hmac_drbg_self_test( int verbose );
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h
index b4eef71e50..e0a2e7f6d6 100644
--- a/thirdparty/mbedtls/include/mbedtls/version.h
+++ b/thirdparty/mbedtls/include/mbedtls/version.h
@@ -40,16 +40,16 @@
*/
#define MBEDTLS_VERSION_MAJOR 2
#define MBEDTLS_VERSION_MINOR 16
-#define MBEDTLS_VERSION_PATCH 3
+#define MBEDTLS_VERSION_PATCH 6
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x02100300
-#define MBEDTLS_VERSION_STRING "2.16.3"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.3"
+#define MBEDTLS_VERSION_NUMBER 0x02100600
+#define MBEDTLS_VERSION_STRING "2.16.6"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.6"
#if defined(MBEDTLS_VERSION_C)
diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c
index aff0a9939a..02a7986b59 100644
--- a/thirdparty/mbedtls/library/aes.c
+++ b/thirdparty/mbedtls/library/aes.c
@@ -918,6 +918,18 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
PUT_UINT32_LE( X2, output, 8 );
PUT_UINT32_LE( X3, output, 12 );
+ mbedtls_platform_zeroize( &X0, sizeof( X0 ) );
+ mbedtls_platform_zeroize( &X1, sizeof( X1 ) );
+ mbedtls_platform_zeroize( &X2, sizeof( X2 ) );
+ mbedtls_platform_zeroize( &X3, sizeof( X3 ) );
+
+ mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) );
+ mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) );
+ mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) );
+ mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) );
+
+ mbedtls_platform_zeroize( &RK, sizeof( RK ) );
+
return( 0 );
}
#endif /* !MBEDTLS_AES_ENCRYPT_ALT */
@@ -986,6 +998,18 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
PUT_UINT32_LE( X2, output, 8 );
PUT_UINT32_LE( X3, output, 12 );
+ mbedtls_platform_zeroize( &X0, sizeof( X0 ) );
+ mbedtls_platform_zeroize( &X1, sizeof( X1 ) );
+ mbedtls_platform_zeroize( &X2, sizeof( X2 ) );
+ mbedtls_platform_zeroize( &X3, sizeof( X3 ) );
+
+ mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) );
+ mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) );
+ mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) );
+ mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) );
+
+ mbedtls_platform_zeroize( &RK, sizeof( RK ) );
+
return( 0 );
}
#endif /* !MBEDTLS_AES_DECRYPT_ALT */
diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c
index d1717e9435..87ccf42fad 100644
--- a/thirdparty/mbedtls/library/bignum.c
+++ b/thirdparty/mbedtls/library/bignum.c
@@ -157,9 +157,10 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
- /* Actually resize up in this case */
+ /* Actually resize up if there are currently fewer than nblimbs limbs. */
if( X->n <= nblimbs )
return( mbedtls_mpi_grow( X, nblimbs ) );
+ /* After this point, then X->n > nblimbs and in particular X->n > 0. */
for( i = X->n - 1; i > 0; i-- )
if( X->p[i] != 0 )
@@ -198,7 +199,7 @@ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
if( X == Y )
return( 0 );
- if( Y->p == NULL )
+ if( Y->n == 0 )
{
mbedtls_mpi_free( X );
return( 0 );
@@ -1071,6 +1072,107 @@ int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
return( 0 );
}
+/** Decide if an integer is less than the other, without branches.
+ *
+ * \param x First integer.
+ * \param y Second integer.
+ *
+ * \return 1 if \p x is less than \p y, 0 otherwise
+ */
+static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
+ const mbedtls_mpi_uint y )
+{
+ mbedtls_mpi_uint ret;
+ mbedtls_mpi_uint cond;
+
+ /*
+ * Check if the most significant bits (MSB) of the operands are different.
+ */
+ cond = ( x ^ y );
+ /*
+ * If the MSB are the same then the difference x-y will be negative (and
+ * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
+ */
+ ret = ( x - y ) & ~cond;
+ /*
+ * If the MSB are different, then the operand with the MSB of 1 is the
+ * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
+ * the MSB of y is 0.)
+ */
+ ret |= y & cond;
+
+
+ ret = ret >> ( biL - 1 );
+
+ return (unsigned) ret;
+}
+
+/*
+ * Compare signed values in constant time
+ */
+int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
+ unsigned *ret )
+{
+ size_t i;
+ /* The value of any of these variables is either 0 or 1 at all times. */
+ unsigned cond, done, X_is_negative, Y_is_negative;
+
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( Y != NULL );
+ MPI_VALIDATE_RET( ret != NULL );
+
+ if( X->n != Y->n )
+ return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+ /*
+ * Set sign_N to 1 if N >= 0, 0 if N < 0.
+ * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
+ */
+ X_is_negative = ( X->s & 2 ) >> 1;
+ Y_is_negative = ( Y->s & 2 ) >> 1;
+
+ /*
+ * If the signs are different, then the positive operand is the bigger.
+ * That is if X is negative (X_is_negative == 1), then X < Y is true and it
+ * is false if X is positive (X_is_negative == 0).
+ */
+ cond = ( X_is_negative ^ Y_is_negative );
+ *ret = cond & X_is_negative;
+
+ /*
+ * This is a constant-time function. We might have the result, but we still
+ * need to go through the loop. Record if we have the result already.
+ */
+ done = cond;
+
+ for( i = X->n; i > 0; i-- )
+ {
+ /*
+ * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
+ * X and Y are negative.
+ *
+ * Again even if we can make a decision, we just mark the result and
+ * the fact that we are done and continue looping.
+ */
+ cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
+ *ret |= cond & ( 1 - done ) & X_is_negative;
+ done |= cond;
+
+ /*
+ * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
+ * X and Y are positive.
+ *
+ * Again even if we can make a decision, we just mark the result and
+ * the fact that we are done and continue looping.
+ */
+ cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
+ *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
+ done |= cond;
+ }
+
+ return( 0 );
+}
+
/*
* Compare signed values
*/
@@ -2338,8 +2440,6 @@ static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
- i = mbedtls_mpi_bitlen( X );
-
for( i = 0; i < rounds; i++ )
{
/*
diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c
index 273997577b..8d010b59ac 100644
--- a/thirdparty/mbedtls/library/cipher.c
+++ b/thirdparty/mbedtls/library/cipher.c
@@ -361,6 +361,10 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
*olen = 0;
block_size = mbedtls_cipher_get_block_size( ctx );
+ if ( 0 == block_size )
+ {
+ return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
+ }
if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
{
@@ -396,11 +400,6 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
}
#endif
- if ( 0 == block_size )
- {
- return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
- }
-
if( input == output &&
( ctx->unprocessed_len != 0 || ilen % block_size ) )
{
@@ -459,11 +458,6 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
*/
if( 0 != ilen )
{
- if( 0 == block_size )
- {
- return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
- }
-
/* Encryption: only cache partial blocks
* Decryption w/ padding: always keep at least one whole block
* Decryption w/o padding: only cache partial blocks
diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c
index fb121575bb..ad0a1936d1 100644
--- a/thirdparty/mbedtls/library/ctr_drbg.c
+++ b/thirdparty/mbedtls/library/ctr_drbg.c
@@ -62,68 +62,6 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
#endif
}
-/*
- * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
- * NIST tests to succeed (which require known length fixed entropy)
- */
-/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
- * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
- * custom, len, entropy_len)
- * implements
- * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
- * security_strength) -> initial_working_state
- * with inputs
- * custom[:len] = nonce || personalization_string
- * where entropy_input comes from f_entropy for entropy_len bytes
- * and with outputs
- * ctx = initial_working_state
- */
-int mbedtls_ctr_drbg_seed_entropy_len(
- mbedtls_ctr_drbg_context *ctx,
- int (*f_entropy)(void *, unsigned char *, size_t),
- void *p_entropy,
- const unsigned char *custom,
- size_t len,
- size_t entropy_len )
-{
- int ret;
- unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
-
- memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
-
- mbedtls_aes_init( &ctx->aes_ctx );
-
- ctx->f_entropy = f_entropy;
- ctx->p_entropy = p_entropy;
-
- ctx->entropy_len = entropy_len;
- ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
-
- /*
- * Initialize with an empty key
- */
- if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
- {
- return( ret );
- }
-
- if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
- {
- return( ret );
- }
- return( 0 );
-}
-
-int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
- int (*f_entropy)(void *, unsigned char *, size_t),
- void *p_entropy,
- const unsigned char *custom,
- size_t len )
-{
- return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
- MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
-}
-
void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
{
if( ctx == NULL )
@@ -427,6 +365,63 @@ exit:
return( ret );
}
+/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
+ * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
+ * implements
+ * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
+ * security_strength) -> initial_working_state
+ * with inputs
+ * custom[:len] = nonce || personalization_string
+ * where entropy_input comes from f_entropy for ctx->entropy_len bytes
+ * and with outputs
+ * ctx = initial_working_state
+ */
+int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len )
+{
+ int ret;
+ unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
+
+ memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
+
+ mbedtls_aes_init( &ctx->aes_ctx );
+
+ ctx->f_entropy = f_entropy;
+ ctx->p_entropy = p_entropy;
+
+ if( ctx->entropy_len == 0 )
+ ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
+ ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
+
+ /*
+ * Initialize with an empty key
+ */
+ if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
+ {
+ return( ret );
+ }
+ return( 0 );
+}
+
+/* Backward compatibility wrapper */
+int mbedtls_ctr_drbg_seed_entropy_len(
+ mbedtls_ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
+ const unsigned char *custom, size_t len,
+ size_t entropy_len )
+{
+ mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
+ return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
+}
+
/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
* mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
* implements
@@ -517,7 +512,7 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
exit:
mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
- return( 0 );
+ return( ret );
}
int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
@@ -678,8 +673,11 @@ int mbedtls_ctr_drbg_self_test( int verbose )
mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
test_offset = 0;
- CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
- (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
+ mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
+ CHK( mbedtls_ctr_drbg_seed( &ctx,
+ ctr_drbg_self_test_entropy,
+ (void *) entropy_source_pr,
+ nonce_pers_pr, 16 ) );
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
@@ -699,8 +697,11 @@ int mbedtls_ctr_drbg_self_test( int verbose )
mbedtls_ctr_drbg_init( &ctx );
test_offset = 0;
- CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
- (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
+ mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
+ CHK( mbedtls_ctr_drbg_seed( &ctx,
+ ctr_drbg_self_test_entropy,
+ (void *) entropy_source_nopr,
+ nonce_pers_nopr, 16 ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
diff --git a/thirdparty/mbedtls/library/ecdsa.c b/thirdparty/mbedtls/library/ecdsa.c
index 2b4800642d..6b72e0d927 100644
--- a/thirdparty/mbedtls/library/ecdsa.c
+++ b/thirdparty/mbedtls/library/ecdsa.c
@@ -297,7 +297,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
*p_sign_tries = 0;
do
{
- if( *p_sign_tries++ > 10 )
+ if( (*p_sign_tries)++ > 10 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
@@ -310,7 +310,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
*p_key_tries = 0;
do
{
- if( *p_key_tries++ > 10 )
+ if( (*p_key_tries)++ > 10 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
@@ -363,6 +363,7 @@ modn:
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c
index db36191b9b..725e176df2 100644
--- a/thirdparty/mbedtls/library/ecp.c
+++ b/thirdparty/mbedtls/library/ecp.c
@@ -1938,6 +1938,20 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
final_norm:
#endif
+ /*
+ * Knowledge of the jacobian coordinates may leak the last few bits of the
+ * scalar [1], and since our MPI implementation isn't constant-flow,
+ * inversion (used for coordinate normalization) may leak the full value
+ * of its input via side-channels [2].
+ *
+ * [1] https://eprint.iacr.org/2003/191
+ * [2] https://eprint.iacr.org/2020/055
+ *
+ * Avoid the leak by randomizing coordinates before we normalize them.
+ */
+ if( f_rng != 0 )
+ MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
+
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
@@ -2308,6 +2322,20 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
}
+ /*
+ * Knowledge of the projective coordinates may leak the last few bits of the
+ * scalar [1], and since our MPI implementation isn't constant-flow,
+ * inversion (used for coordinate normalization) may leak the full value
+ * of its input via side-channels [2].
+ *
+ * [1] https://eprint.iacr.org/2003/191
+ * [2] https://eprint.iacr.org/2020/055
+ *
+ * Avoid the leak by randomizing coordinates before we normalize them.
+ */
+ if( f_rng != NULL )
+ MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
+
MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
cleanup:
@@ -2724,6 +2752,7 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
{
/* SEC1 3.2.1: Generate d such that 1 <= n < N */
int count = 0;
+ unsigned cmp = 0;
/*
* Match the procedure given in RFC 6979 (deterministic ECDSA):
@@ -2748,9 +2777,14 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
*/
if( ++count > 30 )
return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
+
+ ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
+ if( ret != 0 )
+ {
+ goto cleanup;
+ }
}
- while( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
- mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 );
+ while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
}
#endif /* ECP_SHORTWEIERSTRASS */
diff --git a/thirdparty/mbedtls/library/hmac_drbg.c b/thirdparty/mbedtls/library/hmac_drbg.c
index 50d88bd54b..284c9b4e96 100644
--- a/thirdparty/mbedtls/library/hmac_drbg.c
+++ b/thirdparty/mbedtls/library/hmac_drbg.c
@@ -273,16 +273,19 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
- /*
- * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
- * each hash function, then according to SP800-90A rev1 10.1 table 2,
- * min_entropy_len (in bits) is security_strength.
- *
- * (This also matches the sizes used in the NIST test vectors.)
- */
- ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
- md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
- 32; /* better (256+) -> 256 bits */
+ if( ctx->entropy_len == 0 )
+ {
+ /*
+ * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
+ * each hash function, then according to SP800-90A rev1 10.1 table 2,
+ * min_entropy_len (in bits) is security_strength.
+ *
+ * (This also matches the sizes used in the NIST test vectors.)
+ */
+ ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
+ md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
+ 32; /* better (256+) -> 256 bits */
+ }
if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
1 /* add nonce */ ) ) != 0 )
@@ -303,7 +306,7 @@ void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx
}
/*
- * Set entropy length grabbed for reseeds
+ * Set entropy length grabbed for seeding
*/
void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
{
diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c
index ae210bca6a..d5004577a1 100644
--- a/thirdparty/mbedtls/library/pkparse.c
+++ b/thirdparty/mbedtls/library/pkparse.c
@@ -678,6 +678,32 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
#if defined(MBEDTLS_RSA_C)
/*
+ * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
+ *
+ * The value zero is:
+ * - never a valid value for an RSA parameter
+ * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
+ *
+ * Since values can't be omitted in PKCS#1, passing a zero value to
+ * rsa_complete() would be incorrect, so reject zero values early.
+ */
+static int asn1_get_nonzero_mpi( unsigned char **p,
+ const unsigned char *end,
+ mbedtls_mpi *X )
+{
+ int ret;
+
+ ret = mbedtls_asn1_get_mpi( p, end, X );
+ if( ret != 0 )
+ return( ret );
+
+ if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
+ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+
+ return( 0 );
+}
+
+/*
* Parse a PKCS#1 encoded private RSA key
*/
static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
@@ -729,54 +755,84 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
}
/* Import N */
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_INTEGER ) ) != 0 ||
- ( ret = mbedtls_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0,
- NULL, 0, NULL, 0 ) ) != 0 )
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL,
+ NULL, NULL ) ) != 0 )
goto cleanup;
- p += len;
/* Import E */
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_INTEGER ) ) != 0 ||
- ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
- NULL, 0, p, len ) ) != 0 )
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL,
+ NULL, &T ) ) != 0 )
goto cleanup;
- p += len;
/* Import D */
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_INTEGER ) ) != 0 ||
- ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
- p, len, NULL, 0 ) ) != 0 )
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL,
+ &T, NULL ) ) != 0 )
goto cleanup;
- p += len;
/* Import P */
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_INTEGER ) ) != 0 ||
- ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0,
- NULL, 0, NULL, 0 ) ) != 0 )
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL,
+ NULL, NULL ) ) != 0 )
goto cleanup;
- p += len;
/* Import Q */
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_INTEGER ) ) != 0 ||
- ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len,
- NULL, 0, NULL, 0 ) ) != 0 )
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T,
+ NULL, NULL ) ) != 0 )
goto cleanup;
- p += len;
- /* Complete the RSA private key */
- if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
- goto cleanup;
+#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
+ /*
+ * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
+ * that they can be easily recomputed from D, P and Q. However by
+ * parsing them from the PKCS1 structure it is possible to avoid
+ * recalculating them which both reduces the overhead of loading
+ * RSA private keys into memory and also avoids side channels which
+ * can arise when computing those values, since all of D, P, and Q
+ * are secret. See https://eprint.iacr.org/2020/055 for a
+ * description of one such attack.
+ */
+
+ /* Import DP */
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 )
+ goto cleanup;
+
+ /* Import DQ */
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 )
+ goto cleanup;
+
+ /* Import QP */
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 )
+ goto cleanup;
+
+#else
+ /* Verify existance of the CRT params */
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 )
+ goto cleanup;
+#endif
- /* Check optional parameters */
- if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
- ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
- ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 )
+ /* rsa_complete() doesn't complete anything with the default
+ * implementation but is still called:
+ * - for the benefit of alternative implementation that may want to
+ * pre-compute stuff beyond what's provided (eg Montgomery factors)
+ * - as is also sanity-checks the key
+ *
+ * Furthermore, we also check the public part for consistency with
+ * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
+ */
+ if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ||
+ ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 )
+ {
goto cleanup;
+ }
if( p != end )
{
diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c
index af1a878599..09fd379fdb 100644
--- a/thirdparty/mbedtls/library/rsa.c
+++ b/thirdparty/mbedtls/library/rsa.c
@@ -249,6 +249,9 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
{
int ret = 0;
int have_N, have_P, have_Q, have_D, have_E;
+#if !defined(MBEDTLS_RSA_NO_CRT)
+ int have_DP, have_DQ, have_QP;
+#endif
int n_missing, pq_missing, d_missing, is_pub, is_priv;
RSA_VALIDATE_RET( ctx != NULL );
@@ -259,6 +262,12 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
+#if !defined(MBEDTLS_RSA_NO_CRT)
+ have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 );
+ have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 );
+ have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 );
+#endif
+
/*
* Check whether provided parameters are enough
* to deduce all others. The following incomplete
@@ -324,7 +333,7 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
*/
#if !defined(MBEDTLS_RSA_NO_CRT)
- if( is_priv )
+ if( is_priv && ! ( have_DP && have_DQ && have_QP ) )
{
ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
&ctx->DP, &ctx->DQ, &ctx->QP );
diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c
index afced7a99c..c5c3af69df 100644
--- a/thirdparty/mbedtls/library/ssl_cli.c
+++ b/thirdparty/mbedtls/library/ssl_cli.c
@@ -1417,6 +1417,19 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) );
+ /* Check that there is enough room for:
+ * - 2 bytes of version
+ * - 1 byte of cookie_len
+ */
+ if( mbedtls_ssl_hs_hdr_len( ssl ) + 3 > ssl->in_msglen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1,
+ ( "incoming HelloVerifyRequest message is too short" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
/*
* struct {
* ProtocolVersion server_version;
@@ -1445,8 +1458,6 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
}
cookie_len = *p++;
- MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len );
-
if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len )
{
MBEDTLS_SSL_DEBUG_MSG( 1,
@@ -1455,6 +1466,7 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
+ MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len );
mbedtls_free( ssl->handshake->verify_cookie );
diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c
index b8f35fec5d..cbec74fe8c 100644
--- a/thirdparty/mbedtls/library/ssl_tls.c
+++ b/thirdparty/mbedtls/library/ssl_tls.c
@@ -1004,8 +1004,6 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
if( mbedtls_ssl_hw_record_init != NULL )
{
- int ret = 0;
-
MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) );
if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, transform->keylen,
@@ -2885,15 +2883,18 @@ static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl );
/*
* Swap transform_out and out_ctr with the alternative ones
*/
-static void ssl_swap_epochs( mbedtls_ssl_context *ssl )
+static int ssl_swap_epochs( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_transform *tmp_transform;
unsigned char tmp_out_ctr[8];
+#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
+ int ret;
+#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
if( ssl->transform_out == ssl->handshake->alt_transform_out )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) );
- return;
+ return( 0 );
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) );
@@ -2920,7 +2921,9 @@ static void ssl_swap_epochs( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
}
}
-#endif
+#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
+
+ return( 0 );
}
/*
@@ -2957,7 +2960,8 @@ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
ssl->handshake->cur_msg = ssl->handshake->flight;
ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;
- ssl_swap_epochs( ssl );
+ if( ( ret = ssl_swap_epochs( ssl ) ) != 0 )
+ return( ret );
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;
}
@@ -2980,7 +2984,8 @@ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) );
- ssl_swap_epochs( ssl );
+ if( ( ret = ssl_swap_epochs( ssl ) ) != 0 )
+ return( ret );
}
ret = ssl_get_remaining_payload_in_datagram( ssl );
@@ -3017,7 +3022,10 @@ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) )
{
if( is_finished )
- ssl_swap_epochs( ssl );
+ {
+ if( ( ret = ssl_swap_epochs( ssl ) ) != 0 )
+ return( ret );
+ }
if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
return( ret );
@@ -3997,17 +4005,23 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
{
+ int send_ret;
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
+ ssl->out_buf, len );
/* Don't check write errors as we can't do anything here.
* If the error is permanent we'll catch it later,
* if it's not, then hopefully it'll work next time. */
- (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len );
+ send_ret = ssl->f_send( ssl->p_bio, ssl->out_buf, len );
+ MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret );
+ (void) send_ret;
return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
}
if( ret == 0 )
{
- /* Got a valid cookie, partially reset context */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting context" ) );
if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret );
diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c
index a99ee808d6..3b67b2be85 100644
--- a/thirdparty/mbedtls/library/version_features.c
+++ b/thirdparty/mbedtls/library/version_features.c
@@ -297,6 +297,9 @@ static const char *features[] = {
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
"MBEDTLS_CIPHER_PADDING_ZEROS",
#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
+#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+ "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY",
+#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES)
"MBEDTLS_ENABLE_WEAK_CIPHERSUITES",
#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */
diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c
index 2e0b0e8f6c..4d25303206 100644
--- a/thirdparty/mbedtls/library/x509.c
+++ b/thirdparty/mbedtls/library/x509.c
@@ -1063,7 +1063,7 @@ cleanup:
mbedtls_x509_crt_free( &clicert );
#else
((void) verbose);
-#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */
+#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA256_C */
return( ret );
}
diff --git a/thirdparty/mbedtls/library/x509write_csr.c b/thirdparty/mbedtls/library/x509write_csr.c
index b65a11c6aa..7406a97542 100644
--- a/thirdparty/mbedtls/library/x509write_csr.c
+++ b/thirdparty/mbedtls/library/x509write_csr.c
@@ -226,7 +226,9 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s
/*
* Prepare signature
*/
- mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
+ ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
+ if( ret != 0 )
+ return( ret );
if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
f_rng, p_rng ) ) != 0 )
diff --git a/thirdparty/miniupnpc/miniupnpc/minissdpc.c b/thirdparty/miniupnpc/miniupnpc/minissdpc.c
index 29f8110155..36244dedec 100644
--- a/thirdparty/miniupnpc/miniupnpc/minissdpc.c
+++ b/thirdparty/miniupnpc/miniupnpc/minissdpc.c
@@ -62,13 +62,13 @@ struct sockaddr_un {
#include "miniupnpc_socketdef.h"
-#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) && !defined(__GNU__) && !defined(__FreeBSD_kernel__)
+#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) && !defined(__GNU__) && !defined(__FreeBSD_kernel__) && !defined(__HAIKU__)
#define HAS_IP_MREQN
#endif
#if !defined(HAS_IP_MREQN) && !defined(_WIN32)
#include <sys/ioctl.h>
-#if defined(__sun)
+#if defined(__sun) || defined(__HAIKU__)
#include <sys/sockio.h>
#endif
#endif
@@ -683,11 +683,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
#endif
} else {
struct in_addr mc_if;
-#if defined(_WIN32) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
- InetPtonA(AF_INET, multicastif, &mc_if);
-#else
mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
-#endif
if(mc_if.s_addr != INADDR_NONE)
{
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
diff --git a/thirdparty/miniupnpc/miniupnpc/portlistingparse.c b/thirdparty/miniupnpc/miniupnpc/portlistingparse.c
index 55859f2714..18d967b877 100644
--- a/thirdparty/miniupnpc/miniupnpc/portlistingparse.c
+++ b/thirdparty/miniupnpc/miniupnpc/portlistingparse.c
@@ -1,7 +1,7 @@
/* $Id: portlistingparse.c,v 1.9 2015/07/15 12:41:13 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * (c) 2011-2016 Thomas Bernard
+ * (c) 2011-2020 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <string.h>
@@ -12,6 +12,11 @@
#include "portlistingparse.h"
#include "minixml.h"
+#if defined(__HAIKU__)
+/* rename our private function because Haiku already defines a atoui() function */
+#define atoui atoui2
+#endif
+
/* list of the elements */
static const struct {
const portMappingElt code;
diff --git a/thirdparty/miniupnpc/miniupnpc/upnpc.c b/thirdparty/miniupnpc/miniupnpc/upnpc.c
index 4325658bee..cb7f18b5f6 100644
--- a/thirdparty/miniupnpc/miniupnpc/upnpc.c
+++ b/thirdparty/miniupnpc/miniupnpc/upnpc.c
@@ -1,7 +1,7 @@
/* $Id: upnpc.c,v 1.119 2018/03/13 23:34:46 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
- * Copyright (c) 2005-2019 Thomas Bernard
+ * Copyright (c) 2005-2020 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@@ -580,7 +580,7 @@ int main(int argc, char ** argv)
}
#endif
printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
- printf(" (c) 2005-2019 Thomas Bernard.\n");
+ printf(" (c) 2005-2020 Thomas Bernard.\n");
printf("Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/\n"
"for more information.\n");
/* command line processing */
diff --git a/thirdparty/miniupnpc/windows_fix.diff b/thirdparty/miniupnpc/windows_fix.diff
new file mode 100644
index 0000000000..460b596888
--- /dev/null
+++ b/thirdparty/miniupnpc/windows_fix.diff
@@ -0,0 +1,16 @@
+diff --git a/thirdparty/miniupnpc/miniupnpc/minissdpc.c b/thirdparty/miniupnpc/miniupnpc/minissdpc.c
+index 29f8110155..ea9af02e1f 100644
+--- a/thirdparty/miniupnpc/miniupnpc/minissdpc.c
++++ b/thirdparty/miniupnpc/miniupnpc/minissdpc.c
+@@ -683,11 +683,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
+ #endif
+ } else {
+ struct in_addr mc_if;
+-#if defined(_WIN32) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
+- InetPtonA(AF_INET, multicastif, &mc_if);
+-#else
+ mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
+-#endif
+ if(mc_if.s_addr != INADDR_NONE)
+ {
+ ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
diff --git a/thirdparty/misc/cubemap_coeffs.h b/thirdparty/misc/cubemap_coeffs.h
new file mode 100644
index 0000000000..15e4e1664b
--- /dev/null
+++ b/thirdparty/misc/cubemap_coeffs.h
@@ -0,0 +1,28 @@
+// Copyright 2016 Activision Publishing, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the Software
+// is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef CUBEMAP_COEFFS_H
+#define CUBEMAP_COEFFS_H
+
+const float low_quality_coeffs[7][5][6][4] = { { { { 0.0002037563f, 0.0045063655f, -0.0016408688f, 0.00012037493f }, { -9.1834951e-05f, -0.008947532f, -8.1524405e-05f, -3.9080094e-05f }, { -2.6038267e-05f, -6.8409667e-05f, 7.2175702e-05f, 0.25492775f }, { -9.9426044e-05f, 0.0025427756f, -0.00074437925f, 1.1773191e-05f }, { -3.2668211e-05f, 0.0026930659f, -4.824934e-05f, -0.0006835048f }, { -0.0002864144f, -0.0032220854f, 0.0021558286f, -0.00014573736f } }, { { 0.00030683201f, 0.0026819548f, -0.00060011756f, -0.0067169226f }, { -0.0030993251f, 0.0098575575f, 0.0022416671f, -8.9075401e-05f }, { 0.00052405626f, 0.00057860515f, 0.00011654518f, -0.048018609f }, { 0.00010850967f, -0.0088443512f, -0.0018168095f, 8.6633128e-05f }, { 0.003333989f, -0.0050956447f, -8.0414612e-05f, 0.0049721239f }, { -4.0961436e-05f, -8.5486984e-05f, 0.0058683066f, 2.2978359e-05f } }, { { 0.99999993f, 0.99998625f, 0.99999847f, 0.99997743f }, { 0.99999519f, 0.99991138f, 0.99999748f, 1.0f }, { 0.99999986f, 0.99999983f, 0.99999999f, 0.96576708f }, { 0.99999999f, 0.99995765f, 0.99999807f, 1.0f }, { 0.99999444f, 0.99998339f, 1.0f, 0.99998741f }, { 0.99999996f, 0.99999481f, 0.99998046f, 0.99999999f } }, { { -0.32267524f, -0.65409377f, -1.4666488f, 0.87153305f }, { -1.264365f, 0.89880861f, -1.2245906f, -0.88501403f }, { -0.31118682f, -0.086150323f, -0.58811532f, 1.1317711f }, { -1.2193493f, 1.250379f, -1.0871569f, -0.12694096f }, { -0.4012249f, -0.47436307f, -0.59661001f, 2.7313005f }, { -1.3109856f, 0.60929855f, 0.55672643f, -0.39880018f } }, { { 0.93273157f, 0.59530745f, 1.1994788f, 0.19102276f }, { 1.2272239f, 0.23245736f, 1.2577607f, 2.5491008f }, { 1.1210098f, 0.83074953f, 1.3049282f, -0.001940633f }, { 1.5839111f, 0.10520816f, 1.150458f, 2.3251789f }, { 0.688692f, 0.59807498f, 1.3374877f, 0.095746692f }, { 1.3054173f, 0.36604721f, 0.065870226f, 1.6496907f } } }, { { { 0.10348445f, -4.6771514e-07f, -0.011513131f, 8.8921052e-05f }, { -0.042152043f, 0.013143535f, 0.00029120107f, 0.036661611f }, { -0.04516036f, 0.011438473f, -0.0099289792f, -0.011707897f }, { -0.034779497f, 0.0090981166f, -5.4202726e-05f, 0.038592793f }, { -0.0071967376f, -0.0056614418f, -0.012278945f, 0.0056867462f }, { -0.037678514f, 0.011570177f, 0.00029044557f, 0.038583909f } }, { { 0.048320869f, 1.4603673e-05f, 0.0092672368f, 0.00033289199f }, { 0.0071001761f, -0.0090106091f, -0.0027305905f, -0.00221479f }, { -0.0027204116f, 0.00017921587f, 0.015296357f, -0.00010306185f }, { 0.0079350203f, -0.014772431f, -1.2410913e-05f, -0.0062296897f }, { 0.025087691f, 0.00086046427f, 0.015034685f, -0.00078224706f }, { 0.00074587265f, -0.014602074f, 0.00027338224f, -0.012848552f } }, { { 0.99345662f, 1.0f, 0.99989078f, 0.99999994f }, { 0.99908598f, 0.99987302f, 0.99999623f, 0.99932528f }, { 0.99897605f, 0.99993456f, 0.9998337f, 0.99993145f }, { 0.99936351f, 0.99984949f, 1.0f, 0.9992356f }, { 0.99965935f, 0.9999836f, 0.99981158f, 0.99998352f }, { 0.99928963f, 0.99982644f, 0.99999992f, 0.99917276f } }, { { 3.6882765f, 0.15963861f, 0.55983965f, 0.4075649f }, { 2.1169304f, 0.56463157f, 0.52957047f, 2.0117964f }, { 3.1080461f, 0.09682931f, 0.42125986f, 0.089254784f }, { 1.4247315f, 0.48411378f, -0.17039102f, 1.7431674f }, { 4.0339531f, 0.14046159f, 0.89848909f, 0.011661811f }, { 1.9787852f, 0.61750145f, 0.63514194f, 1.9359003f } }, { { 0.030848793f, 1.4472743f, 1.4356825f, 1.4078009f }, { 0.37639678f, 1.0793106f, 1.1945413f, 0.43983395f }, { 0.27451605f, 1.5256415f, 1.016769f, 1.4850575f }, { 0.54580883f, 1.1332879f, 3.1331784f, 0.60772955f }, { 0.11785158f, 1.3928946f, 0.94998805f, 1.0377182f }, { 0.2842108f, 1.0026911f, 1.9064553f, 0.27147854f } } }, { { { -0.096789259f, 0.10326967f, 0.0011799959f, -0.03077328f }, { 0.08342021f, 0.033260738f, -0.00045864451f, -0.021450568f }, { -0.093369441f, -0.05807574f, -0.033745214f, 0.023817208f }, { 0.056747754f, 0.031140512f, 0.00019362509f, -0.023727797f }, { -0.084538386f, -0.040545412f, -0.0076838784f, 0.03424599f }, { 0.074312056f, 0.027619787f, 0.0015509082f, -0.031043528f } }, { { -0.0085160473f, -0.012179292f, 0.0049910118f, 0.020224799f }, { 0.022559343f, -0.016273333f, -0.0069382139f, 0.00058083224f }, { -0.001115062f, 0.035002846f, -0.0038974773f, -0.039378629f }, { 0.0014921617f, -0.00058523872f, -0.0011606685f, 0.02807528f }, { -0.021454809f, 0.052957852f, -0.0022083677f, -0.027956663f }, { -0.016486487f, -0.0040233682f, 0.00029949558f, 0.021924605f } }, { { 0.99526846f, 0.99457883f, 0.99998685f, 0.99932175f }, { 0.99625908f, 0.99931422f, 0.99997583f, 0.99976974f }, { 0.99563091f, 0.99769836f, 0.99942287f, 0.99894047f }, { 0.99838743f, 0.99951485f, 0.99999931f, 0.99932416f }, { 0.99618922f, 0.99777329f, 0.99996804f, 0.99902234f }, { 0.99709875f, 0.9996104f, 0.99999875f, 0.99927754f } }, { { 3.0342011f, 4.8022834f, 1.3814123f, 1.5280754f }, { 2.9043837f, 1.7325954f, 1.422223f, 2.0569263f }, { 3.0358722f, 5.3331504f, 1.5680146f, 1.6079289f }, { 3.2062833f, 1.5368069f, 1.0484709f, 1.5399477f }, { 2.4471653f, 4.0916696f, 1.5060688f, 1.5807009f }, { 2.6932695f, 1.5161537f, 1.3991175f, 1.6301918f } }, { { 0.50787578f, 0.17735471f, 1.4006765f, 1.0878482f }, { 0.69514518f, 1.6765187f, 1.2224869f, 1.3461327f }, { 0.71381288f, 0.17509216f, 1.2712934f, 0.94575821f }, { 1.1817337f, 1.796984f, 1.8671538f, 1.5708691f }, { 0.55621228f, 0.38291359f, 1.4128781f, 0.82625349f }, { 0.72441647f, 1.005794f, 1.5522327f, 1.6032524f } } }, { { { -0.00041301094f, -0.095882618f, 0.26932618f, -0.25137214f }, { 0.13737415f, -0.12694293f, -0.0090389663f, 0.07227623f }, { -0.005236407f, -0.0072961249f, 0.27776083f, -0.19536433f }, { 0.12781899f, -0.042881667f, -0.095979169f, 0.088937396f }, { 0.037496084f, -0.090547583f, 0.22112334f, -0.21930294f }, { 0.13353408f, -0.084346121f, -0.011365728f, 0.043459312f } }, { { -0.05799135f, -0.048612281f, 0.02422989f, 0.015536268f }, { -0.083144241f, 0.039381032f, 0.018705957f, 0.029297922f }, { 0.026364989f, -0.041927591f, 0.036718516f, 0.0050376168f }, { -0.11562256f, 0.043521976f, -0.014481644f, 0.01529188f }, { -0.047859898f, -0.057779647f, -0.053171395f, -0.0063193506f }, { -0.028781196f, 0.041145059f, -0.00018523142f, 0.053524246f } }, { { 0.998317f, 0.99420489f, 0.96274416f, 0.96776581f }, { 0.98702349f, 0.99112796f, 0.99978417f, 0.99695425f }, { 0.99963867f, 0.99909401f, 0.95994827f, 0.9807178f }, { 0.98503489f, 0.99813175f, 0.99527799f, 0.99591983f }, { 0.99815003f, 0.99421459f, 0.97379529f, 0.97563635f }, { 0.99062621f, 0.99558667f, 0.99993539f, 0.99762039f } }, { { 2.3221943f, 2.5383575f, 4.3177232f, 4.2016467f }, { 3.1936529f, 3.0443024f, 2.548962f, 2.7636456f }, { 2.5923827f, 2.3497949f, 4.2471014f, 4.1975975f }, { 3.3748785f, 3.2836577f, 2.9220414f, 2.7175317f }, { 2.3290083f, 2.5560991f, 4.3572168f, 4.4372585f }, { 3.1512055f, 3.2863613f, 2.4475378f, 2.3620003f } }, { { 0.62833231f, 0.52378061f, 0.55845033f, 0.64883444f }, { 0.76905594f, 1.1017801f, 1.8714048f, 1.5664383f }, { 1.5283278f, 1.2423369f, 0.62247385f, 1.0341956f }, { 0.77484548f, 1.6866409f, 1.0307399f, 1.4224643f }, { 0.85627405f, 0.72516079f, 0.70094339f, 0.7547877f }, { 1.202842f, 1.7650605f, 1.5938526f, 0.97031337f } } }, { { { -0.078108035f, -0.049518839f, 0.26950139f, -0.51522828f }, { 0.43015518f, -0.045354216f, 0.094550359f, -0.2395012f }, { -0.079900522f, -0.082582235f, 0.24464909f, -0.5234896f }, { 0.38422945f, -0.023833644f, 0.07334288f, -0.22827313f }, { -0.075370379f, -0.05156594f, 0.19883182f, -0.45064193f }, { 0.46285395f, 0.021899343f, 0.10155287f, -0.25974773f } }, { { 0.068681419f, -0.32175988f, 0.15143274f, -0.0066205388f }, { -0.17060226f, 0.31051319f, -0.080511981f, -0.1593209f }, { 0.08167251f, -0.32517768f, 0.10937023f, -0.06941926f }, { -0.14580685f, 0.32474959f, -0.081718057f, -0.11068378f }, { 0.053961394f, -0.29322836f, 0.10408839f, -0.02243046f }, { -0.030598471f, 0.34332821f, -0.091528353f, -0.16299796f } }, { { 0.99457629f, 0.9455255f, 0.95101899f, 0.85702741f }, { 0.88648824f, 0.94948647f, 0.99225906f, 0.95773484f }, { 0.99345131f, 0.94204015f, 0.96342357f, 0.84919939f }, { 0.9116513f, 0.94549969f, 0.99395321f, 0.96728511f }, { 0.99569447f, 0.95465076f, 0.97449039f, 0.89242295f }, { 0.88590629f, 0.93896015f, 0.99061071f, 0.95182077f } }, { { 3.6380949f, 4.1749529f, 4.1351439f, 4.8389883f }, { 5.256362f, 4.2027959f, 3.6096892f, 3.9848645f }, { 3.5689427f, 3.8620869f, 4.0023981f, 4.8268584f }, { 5.1128497f, 4.468934f, 3.5851596f, 4.047485f }, { 3.7014988f, 4.1310058f, 4.2446872f, 5.3049323f }, { 4.8659881f, 4.3133002f, 3.4582876f, 3.8863853f } }, { { 1.6276316f, 0.7747672f, 1.0485958f, 0.73900224f }, { 0.72010795f, 0.65403093f, 1.3179681f, 0.65610074f }, { 1.5881174f, 0.55108527f, 1.0509725f, 0.72153362f }, { 1.1389053f, 1.0905142f, 1.6661598f, 0.9987548f }, { 1.977914f, 0.83001686f, 1.0571479f, 0.80249183f }, { 0.94107069f, 0.80840873f, 0.95379751f, 0.50386367f } } }, { { { 0.015525428f, -0.48038019f, -0.021799698f, 0.43629156f }, { 0.045681247f, -0.55039024f, -0.54573329f, 0.57817853f }, { -0.045869129f, -0.42209953f, -0.14040829f, 0.37787106f }, { 0.66327604f, -0.70070311f, -0.55261635f, 0.63446196f }, { 0.015397585f, -0.43515767f, -0.021927897f, 0.4203714f }, { 0.85681772f, -0.65394729f, -0.67557236f, 0.60104142f } }, { { -0.31503888f, -0.26745648f, 0.26817896f, 0.26548747f }, { -0.93282124f, -0.033621213f, 0.68374802f, -0.10858524f }, { -0.21723689f, -0.17935495f, 0.38521982f, 0.2578335f }, { -0.39913153f, 0.23555359f, 0.59589456f, -0.19075103f }, { -0.28851798f, -0.24142459f, 0.28279261f, 0.24766617f }, { -0.29435977f, -0.25850549f, 0.57790878f, -0.200546f } }, { { 0.94895177f, 0.83528552f, 0.96312243f, 0.85974768f }, { 0.35743218f, 0.8342303f, 0.48442112f, 0.80865248f }, { 0.97504059f, 0.88863029f, 0.9120807f, 0.88923301f }, { 0.63305523f, 0.67344611f, 0.58268761f, 0.74904744f }, { 0.95735066f, 0.86738225f, 0.9589304f, 0.87289711f }, { 0.42333878f, 0.71100482f, 0.45784651f, 0.77364753f } }, { { 5.3641275f, 5.2550422f, 5.3103777f, 5.2851215f }, { 5.2657045f, 6.2095784f, 6.9549598f, 4.9205516f }, { 5.163385f, 5.3141038f, 4.9907618f, 5.3583852f }, { 6.1257061f, 6.1102338f, 6.9549598f, 5.3129951f }, { 5.3138838f, 5.3257842f, 5.3133783f, 5.2687156f }, { 5.8915091f, 6.153324f, 6.9549598f, 4.9568971f } }, { { 3.1221918f, 1.1882615f, 2.6991784f, 1.1185048f }, { -0.2322432f, -0.16590163f, 0.088416958f, 0.057399579f }, { 3.4395383f, 1.5836276f, 2.6242352f, 1.2873336f }, { -0.23767634f, -0.79425452f, 0.20477899f, 0.40461516f }, { 2.2521751f, 1.1933374f, 2.3309484f, 1.0185309f }, { -0.099258385f, -0.2173726f, 0.0736866f, 0.15470436f } } }, { { { 0.066050217f, -0.33053278f, -0.13771479f, 0.33278465f }, { 0.00084467977f, -0.50077778f, -0.30083482f, 0.6494273f }, { 0.24880159f, -0.30354993f, -0.15417892f, 0.38203296f }, { -0.073325098f, -0.4778777f, 0.10779844f, 0.66683723f }, { 0.15703809f, -0.36335455f, -0.15657631f, 0.35926503f }, { 0.26127617f, -0.29524368f, -0.14490804f, 0.65461301f } }, { { -0.57970022f, -0.33939622f, 0.72169742f, 0.320959f }, { -0.38698206f, -0.12730306f, 0.65810895f, 0.026509232f }, { -0.6199708f, -0.34745658f, 0.68683659f, 0.34547285f }, { -0.3613378f, -0.14006845f, 0.65917895f, 0.038446867f }, { -0.57778101f, -0.35057776f, 0.57837882f, 0.36488991f }, { -0.50051482f, -0.019174387f, 0.50816239f, 0.02682636f } }, { { 0.8121484f, 0.88065787f, 0.67837119f, 0.88670158f }, { 0.92208686f, 0.85616327f, 0.69021085f, -0.75996148f }, { 0.74413303f, 0.88720424f, 0.71027063f, 0.85714604f }, { 0.92954743f, 0.86718726f, 0.74421946f, -0.74421095f }, { 0.80094204f, 0.86317363f, 0.8006009f, 0.85894353f }, { 0.82536033f, 0.95522956f, 0.8489833f, -0.75548802f } }, { { 5.7725061f, 5.1565901f, 5.6224483f, 5.0847054f }, { 5.7717118f, 6.4180057f, 6.9797014f, -0.03290957f }, { 5.7847117f, 5.2015529f, 5.614561f, 5.2019388f }, { 6.2613999f, 6.5807982f, 6.9797014f, -0.032764603f }, { 5.823775f, 5.2332343f, 5.826694f, 5.197143f }, { 6.3463188f, 5.8174311f, 6.9797014f, -0.032766769f } }, { { 2.96787f, 1.3557735f, 2.0749129f, 1.3066609f }, { -0.92782801f, 0.0079162579f, -0.33479446f, 2.699659e-05f }, { 2.1997063f, 3.1083252f, 2.6810949f, 1.8276262f }, { -0.48654719f, -0.10954189f, -0.32175132f, 5.490092e-05f }, { 3.1970446f, 1.787085f, 3.062849f, 1.6274811f }, { -0.78882801f, -0.34050184f, -0.59962127f, 3.6554198e-05f } } } };
+
+const float high_quality_coeffs[7][5][3][24][4] = { { { { { -4.8355339e-06f, -4.4902569e-05f, -9.2632249e-05f, -0.00053773136f }, { 0.0040143823f, -0.00060900339f, -0.0095301923f, -0.0053956011f }, { -0.0005923892f, -3.6901978e-05f, -5.6694857e-06f, -0.00017018564f }, { 0.0012441402f, 0.02236187f, 0.022751769f, 0.0062788948f }, { 0.00013810055f, -2.2709815e-05f, 0.0054849671f, -1.6599195e-05f }, { -0.020320408f, -0.017066319f, -0.017457746f, 0.022910628f }, { 0.00024171724f, 9.7419073e-05f, -0.00047804272f, -0.00010093683f }, { 7.6988167e-05f, 1.8551597e-05f, -5.7692813e-05f, -3.332362e-05f }, { -0.00062766208f, 2.713742e-05f, 0.00026511682f, 2.3841873e-05f }, { -0.00043656844f, 0.0028645469f, 0.0049817085f, 0.0080221478f }, { -3.3210444e-05f, -8.0852386e-05f, -2.2111492e-06f, -8.4430827e-05f }, { 0.010967284f, 0.018811225f, 0.017569463f, -0.0046944996f }, { -0.00018391248f, -0.00010462174f, -0.00017726f, -0.00018490133f }, { 0.00012591989f, 0.015965386f, 0.015964059f, -0.0078018431f }, { -0.006125333f, -8.2224165e-05f, -0.00020500151f, -0.00025207244f }, { -0.00016320041f, -0.0001279242f, 0.00014038799f, 8.1359421e-05f }, { -0.00064341098f, -0.0011265496f, -0.0011634792f, -0.00081607159f }, { 0.00089294825f, 0.0061923653f, 0.0052662392f, -0.00058227469f }, { -2.4001308e-05f, -1.3534224e-05f, -1.4720478e-05f, -2.5120827e-05f }, { 0.00029964918f, -0.0045658543f, -0.0045581938f, 0.0017106208f }, { 7.5790173e-05f, -1.8265415e-05f, 1.5918205e-05f, 5.8524021e-05f }, { 0.0011669872f, -0.00017571882f, -0.00017190275f, -0.0023833977f }, { 0.0033487264f, -0.0066535821f, -0.0066413786f, -0.0032332601f }, { -3.6468807e-05f, -0.00068145131f, -9.8190714e-05f, -8.7169435e-05f } }, { { -0.0010440653f, -8.9750644e-05f, 4.971182e-05f, 0.0044618878f }, { 0.0078333883f, -0.00090884312f, -0.00046920549f, -0.002465051f }, { -0.0058778609f, 0.0026554895f, -0.00031880506f, -0.00010649091f }, { -0.0015095448f, 0.0094026506f, 0.009492703f, 0.0024572848f }, { 0.0047331786f, 0.00070722401f, 0.0028798817f, -0.00039779892f }, { -0.0089878107f, -0.0095474878f, -0.0097187652f, 0.008765907f }, { -4.0435321e-05f, -0.00061813281f, -0.0060490143f, 0.0016259965f }, { -0.00014720558f, -1.0601876e-05f, 0.00014757138f, 0.00016227641f }, { -0.010428289f, -0.00031812813f, -0.0016172213f, -0.00012022134f }, { 0.0040517131f, 0.0072972763f, 0.0060433905f, 0.0025041645f }, { 0.00014090924f, 0.00027612853f, 0.00015961665f, 0.0002605418f }, { -0.00020653783f, -0.00048482867f, -0.00058472338f, 0.00026413759f }, { 0.00056712638f, 0.00026385353f, 0.00035484947f, 0.00033212447f }, { -0.00094663094f, 0.0029891757f, 0.0029887838f, -0.0026583585f }, { -0.0017400246f, 0.00042350567f, 0.00086128207f, 0.00039863587f }, { 0.00059604848f, 0.00027495434f, -0.00059956434f, -4.4981673e-05f }, { -0.010211343f, -0.0080580409f, -0.0085333216f, 0.0023258717f }, { 0.00042832593f, 0.0056750222f, 0.0048059635f, -0.0092168281f }, { 3.0214612e-05f, 4.540924e-06f, 1.7239937e-05f, 2.783598e-05f }, { 0.00029393335f, -4.5128636e-05f, -4.3089017e-05f, 0.00030682556f }, { -4.7077735e-05f, -1.3596835e-05f, -0.0015338149f, -7.4957991e-05f }, { -0.00097136844f, 0.00018564298f, 0.00021815754f, 0.0015095577f }, { 0.00043929849f, -0.0014691094f, -0.0014671742f, -0.00029365954f }, { 8.8554045e-05f, 0.0062500772f, 0.0001495049f, 0.00021007601f } }, { { 0.0020307077f, 0.0020947445f, 0.0017438295f, 0.0084822342f }, { -0.0069727503f, -0.0010131005f, 0.0055261321f, -0.0020442588f }, { 0.00031035611f, 0.00010839441f, 3.7359209e-06f, 4.3112837e-05f }, { 9.1207794e-05f, 0.0050148169f, 0.0051071455f, 0.0033679057f }, { -0.00090101737f, -0.00053793176f, -0.0025829621f, 0.0003241927f }, { -0.0019244714f, -0.0033690472f, -0.0035193497f, 0.0027653636f }, { -0.00065476293f, -0.00017787403f, 0.00040383136f, -0.00018123957f }, { -0.00030640434f, -0.00018961553f, -0.00011036218f, -0.00015793049f }, { 0.001110592f, -0.00021252645f, 0.00015849587f, -3.7758317e-05f }, { 0.00077967828f, -0.0051765235f, -0.0078505592f, -0.010796339f }, { -1.2024951e-05f, 6.48806e-05f, -3.9409005e-05f, 7.4639306e-05f }, { -0.00017352424f, -0.00037802595f, -0.00045639468f, 0.00016843169f }, { -4.2866244e-05f, -4.3730932e-06f, 7.3574276e-05f, 5.6076779e-05f }, { 0.00024802387f, 0.0018053101f, 0.0018042994f, -0.0016700716f }, { 0.0082698262f, -0.00014605077f, 0.0004377682f, 8.1585074e-05f }, { -4.494343e-06f, 0.00019781519f, -0.00058910268f, -0.00027360572f }, { 0.0013016934f, 0.0021020456f, 0.0022718598f, -0.0059377824f }, { 0.002185371f, -0.0080788056f, -0.0071952836f, 0.0039688918f }, { 0.00013048617f, 0.0001738124f, 0.00012978924f, 0.00013813358f }, { 0.00032386518f, 0.00023046021f, 0.00023064714f, 0.00033762343f }, { 0.00023643771f, 0.00019652953f, 0.0013083597f, 0.00024739959f }, { -0.0063957036f, -0.0055319023f, -0.0054742301f, -0.0037204932f }, { -0.0005510683f, -0.0007715413f, -0.00077385934f, -0.001009415f }, { 0.00017904616f, -0.00096137522f, 0.00030252599f, -2.2478138e-05f } } }, { { { -0.00038948583f, -0.00040817153f, -0.00041280315f, -0.0010985631f }, { 0.0025695337f, 0.00042904308f, 0.0054649973f, -0.0055079106f }, { 0.00052050672f, 2.2618679e-05f, 0.00024058975f, -0.00012632201f }, { -0.013468886f, 0.0079396715f, 0.0079402246f, 0.026283756f }, { -7.922122e-05f, -3.4761763e-06f, -0.0041716347f, 0.0001478739f }, { 0.023716381f, -0.016415262f, -0.015296927f, -0.021050827f }, { 3.7654391e-05f, 0.00012765816f, -0.0001337099f, 0.00051483398f }, { 0.00015671907f, 0.00010686796f, 2.1421097e-05f, -2.2281569e-05f }, { 3.1779413e-06f, 0.00010449913f, -0.00018303614f, 7.5382489e-05f }, { -0.00020526765f, -0.0011333575f, -0.0050720108f, 0.0051482782f }, { 4.0450357e-05f, 1.0808158e-05f, -2.3316095e-05f, 9.7767333e-06f }, { -0.019107229f, 0.010907324f, 0.0048969594f, 0.017851514f }, { 7.4048796e-05f, -7.041835e-06f, 8.0226174e-05f, 5.1714105e-05f }, { -0.016564627f, 0.0023486944f, 0.0023601429f, 0.016005248f }, { -0.004528284f, 3.6291049e-05f, 2.4229636e-05f, 0.0024853948f }, { 5.6882054e-05f, 6.8805135e-05f, 0.00013119897f, 0.00010339801f }, { 0.00021183341f, 0.0008203137f, -7.204401e-05f, 0.00062599728f }, { -0.00099314707f, 0.0030198762f, -0.0038989955f, 0.00055571214f }, { -7.4247984e-05f, -8.3993373e-05f, -5.9133252e-05f, -7.7411989e-05f }, { 0.0054296732f, -0.00057858871f, -0.00058417754f, -0.005072911f }, { -0.00019259782f, -0.00018772532f, -4.2959783e-05f, -0.0001827295f }, { -0.00029351865f, 0.00013736372f, 0.00016666048f, 0.00020873447f }, { 0.0069341659f, 0.0027612928f, 0.0027538377f, -0.0061770317f }, { 4.2584714e-05f, -0.00037063589f, -9.0693123e-06f, 0.00011845784f } }, { { 0.0028834168f, 0.0031807308f, 0.0031352582f, 0.01064051f }, { 0.0049297987f, -4.2149356e-05f, -0.0014926841f, -0.0002300371f }, { 0.0020396303f, -0.00066042794f, -6.4359283e-05f, 0.00017835163f }, { -0.0025767816f, 0.0025148152f, 0.0025224779f, 0.0043006543f }, { -0.00042084416f, -0.00013534305f, 0.002453623f, -4.0707749e-05f }, { -0.0001803055f, -0.0010450606f, -0.00084380806f, 0.00014843677f }, { -0.0064067107f, 0.00011012652f, -0.0022552747f, -0.00080508294f }, { -0.00017778763f, -4.296789e-05f, 0.00015343883f, 0.00025036711f }, { 0.002825978f, -0.00031945362f, -0.00031987612f, -0.00021117763f }, { 0.00032791249f, -0.00049524542f, 0.0049368722f, -0.0017186408f }, { -0.0001685943f, -0.00016766033f, -0.0001755097f, -0.00017067307f }, { 0.00023939157f, -0.00011793706f, -6.0620575e-05f, -0.0002706595f }, { -2.9718673e-05f, 3.5950879e-05f, 1.839844e-05f, -2.8718148e-05f }, { -0.0017260981f, 0.00012145435f, 0.0001236679f, 0.0018292155f }, { 0.0036086706f, 0.0001026898f, -2.5518889e-05f, -0.00019830236f }, { -0.00031546808f, -0.00042107458f, -0.00059963868f, -0.00061472497f }, { -0.0074719522f, 0.0015719596f, -0.0033624165f, -0.0092664101f }, { -0.0011285776f, 0.0018601435f, 0.00052060704f, -1.5554679e-05f }, { 4.9853171e-05f, 7.3650922e-05f, 3.4080107e-05f, 5.4255445e-05f }, { 0.00015102779f, -2.58105e-05f, -2.5851018e-05f, -4.5185316e-05f }, { 0.0002057452f, 0.00019037765f, 0.0040052198f, 0.00020046579f }, { 0.0027727314f, 0.0040749211f, 0.0036050794f, 0.0034635222f }, { 0.00042503689f, 0.00056027382f, 0.00056052971f, -8.2485044e-05f }, { -5.6309634e-05f, 0.0019722025f, 6.4267434e-05f, -0.00020376412f } }, { { 0.0051607661f, 0.0047835358f, 0.0047658352f, 0.0054281814f }, { -0.0040939561f, 0.0012119183f, -0.0023408179f, -0.00055891234f }, { -0.0031939804f, -0.0015954053f, -0.00018570689f, 0.00028849431f }, { -0.0075625096f, 0.0033878734f, 0.0033797415f, 0.010242674f }, { -0.002293562f, 0.00024245282f, 0.0019455622f, 0.0039550747f }, { 0.0090386754f, -0.0086947671f, -0.0082684939f, -0.0075613346f }, { -0.00085735117f, 3.4822634e-05f, -0.0024653972f, -0.00090964985f }, { -0.00013750587f, -0.00010089501f, 6.3555498e-05f, 0.0002758494f }, { 0.0060496328f, -0.00032664426f, 0.0005979723f, -0.00018819024f }, { 0.00072724184f, 0.00082242885f, 0.0045668772f, -0.0054557456f }, { -9.6167811e-05f, 7.9856612e-05f, 0.00015672473f, 8.0901183e-05f }, { 0.00038859448f, -0.00025360755f, -0.00017624981f, -0.00049125519f }, { -8.8277361e-05f, 2.4159527e-05f, -0.00016014627f, -2.7854246e-05f }, { -0.0037308647f, 0.00041434141f, 0.0004167221f, 0.0037190244f }, { 0.00050696744f, -4.6752715e-05f, 0.00033183668f, -0.0025882828f }, { -0.00015915702f, -0.0002325901f, -0.00036157415f, -0.00016391937f }, { 0.00012320153f, 0.0026711886f, 0.0018414591f, -0.0058215223f }, { -0.0029409983f, -0.00015460743f, 0.0031951665f, 0.0074654329f }, { 9.9084813e-05f, 9.1785865e-05f, 5.9300007e-05f, 0.00010463304f }, { 0.00024773341f, -2.5723276e-05f, -2.5709769e-05f, -0.00015357475f }, { 0.000416633f, 0.00028749584f, -0.0038632071f, 0.00039869488f }, { 0.00018344152f, 3.0811778e-05f, -0.00010240082f, 0.00059301197f }, { 0.0019217461f, 0.00034404024f, 0.00034318823f, -0.0015867375f }, { -0.00011928879f, 0.001178769f, -5.8655983e-05f, -0.00028461439f } } }, { { { 0.99999992f, 0.99999992f, 0.99999991f, 0.99999925f }, { 0.99998864f, 0.99999972f, 0.99993965f, 0.99997027f }, { 0.99999969f, 1.0f, 0.99999997f, 0.99999998f }, { 0.99990852f, 0.99971841f, 0.99970961f, 0.9996348f }, { 0.99999999f, 1.0f, 0.99997626f, 0.99999999f }, { 0.99951219f, 0.9997196f, 0.99973058f, 0.99951587f }, { 0.99999997f, 0.99999999f, 0.99999988f, 0.99999986f }, { 0.99999998f, 0.99999999f, 1.0f, 1.0f }, { 0.9999998f, 0.99999999f, 0.99999995f, 1.0f }, { 0.99999988f, 0.99999525f, 0.99997473f, 0.99995457f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 0.99975729f, 0.99976356f, 0.99983365f, 0.99982963f }, { 0.99999998f, 0.99999999f, 0.99999998f, 0.99999998f }, { 0.99986279f, 0.99986979f, 0.99986978f, 0.99984147f }, { 0.99997099f, 1.0f, 0.99999998f, 0.99999688f }, { 0.99999999f, 0.99999999f, 0.99999998f, 0.99999999f }, { 0.99999977f, 0.99999903f, 0.99999932f, 0.99999947f }, { 0.99999911f, 0.99997627f, 0.99997853f, 0.99999968f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 0.99998521f, 0.99998941f, 0.99998944f, 0.99998567f }, { 0.99999998f, 0.99999998f, 1.0f, 0.99999998f }, { 0.99999928f, 0.99999998f, 0.99999997f, 0.99999714f }, { 0.99997035f, 0.99997405f, 0.99997415f, 0.99997569f }, { 1.0f, 0.9999997f, 1.0f, 0.99999999f } }, { { 0.00015966941f, 0.00014262676f, 0.00020165066f, 0.00021618914f }, { 2.8140907e-06f, -0.00020325872f, 0.00017736728f, 6.0386679e-05f }, { -0.0003187876f, 5.8862288e-05f, 6.2281085e-05f, 1.7339908e-05f }, { -2.6587911e-05f, -0.00011609007f, -0.00011725093f, -7.6114852e-05f }, { 0.00013665042f, 5.2703844e-06f, -0.00031293536f, 3.8693931e-05f }, { -9.8143069e-05f, -0.00012816332f, -0.00012926252f, -0.00010623032f }, { 0.00032342312f, -1.9200091e-06f, -0.00010691485f, 6.3541059e-05f }, { -8.0643542e-06f, 9.7622933e-06f, 2.9924822e-05f, -1.988333e-05f }, { 0.00025318464f, 1.2588649e-05f, 1.4665927e-05f, 9.3294806e-06f }, { 2.6875391e-06f, -2.4928123e-05f, 2.251878e-05f, 0.00011026808f }, { 1.767638e-05f, 1.0309044e-05f, 2.4765648e-05f, 1.4397941e-05f }, { 6.9000935e-06f, 1.0637078e-05f, 1.087637e-05f, 6.3065784e-06f }, { 5.532953e-05f, 1.6231463e-05f, 4.9564371e-05f, 3.6623041e-05f }, { -1.6958729e-05f, -3.1627491e-05f, -3.1524511e-05f, -2.9954116e-05f }, { 8.9045086e-05f, 2.1005026e-05f, 1.3016463e-05f, 8.7863053e-05f }, { -2.75035e-05f, -3.0440427e-05f, -3.5356286e-05f, 5.9609261e-06f }, { 0.0001586274f, 4.0711165e-05f, 3.1563135e-05f, 0.0001385483f }, { 8.5548316e-06f, 7.4531928e-05f, -3.7017413e-05f, 2.6874037e-05f }, { -1.3750655e-05f, -8.2756032e-06f, -2.7214983e-07f, -1.4830115e-05f }, { -7.0798362e-07f, -3.3187173e-07f, -3.3266762e-07f, -5.7113855e-07f }, { 4.3615512e-05f, -4.4076433e-06f, 8.9239586e-06f, 3.7278531e-05f }, { -7.7366773e-06f, 4.610399e-06f, 4.3762687e-06f, -5.64067e-06f }, { -3.2666125e-06f, -1.0773146e-05f, -1.0861965e-05f, -1.3327232e-06f }, { -9.1178305e-06f, 0.00030171207f, -1.5395234e-05f, -2.0695425e-07f } }, { { 0.00017159464f, 0.00014699558f, 0.00018752678f, 0.0002227926f }, { -4.6524822e-05f, -0.00010460271f, 0.00034735325f, 0.00010082238f }, { -6.8269006e-05f, 1.4343751e-05f, 7.7283393e-06f, 2.5347136e-05f }, { -6.6149546e-05f, -7.1168993e-05f, -7.0621016e-05f, -0.00015246746f }, { 7.12022e-05f, 3.8790461e-05f, -0.00023994449f, 6.6792921e-05f }, { -0.00014735813f, -0.00012658353f, -0.00012162488f, -0.00012106777f }, { 0.00015161388f, -1.4439153e-05f, -3.7629923e-06f, 8.3140788e-06f }, { 4.0175416e-05f, 2.5380268e-05f, -2.2894421e-06f, 4.6374378e-06f }, { 0.00028906023f, 1.7695243e-05f, 5.3790587e-06f, 1.631859e-05f }, { 1.8890685e-05f, -1.6898275e-05f, 2.1007663e-05f, 6.5179363e-05f }, { -3.9142595e-06f, 2.5745488e-05f, 1.0803197e-05f, 2.7099749e-05f }, { 9.4245546e-06f, 1.0010075e-05f, 9.058324e-06f, 9.8703427e-06f }, { -2.3441863e-06f, 2.5490323e-05f, -1.0097654e-05f, 4.0554798e-05f }, { -4.1443921e-05f, -1.996316e-05f, -2.0000841e-05f, -4.7495655e-05f }, { 0.00012591695f, 5.6179903e-05f, -1.8415869e-05f, -3.8697972e-05f }, { 2.6719505e-05f, 2.4195362e-06f, 2.4287424e-05f, 3.4703059e-05f }, { 7.3804931e-05f, 4.9784871e-05f, 3.1159931e-06f, 0.00015857197f }, { -0.00010634331f, -1.6427658e-05f, -7.4874306e-05f, -6.2620255e-05f }, { -4.2561214e-06f, -1.6123179e-05f, -1.5507273e-05f, -1.2909924e-05f }, { -1.2210463e-06f, 1.1546399e-06f, 1.1413892e-06f, -1.3465856e-06f }, { 3.4909884e-05f, -1.2677793e-05f, 0.00011543701f, 2.413091e-05f }, { -2.1953323e-05f, -4.6244252e-06f, -3.5624435e-06f, 4.2293671e-06f }, { -1.1392936e-05f, -4.3970369e-06f, -4.4264864e-06f, -1.208518e-05f }, { -4.4002617e-05f, 0.00020912348f, -3.9617824e-05f, -4.1725112e-05f } } }, { { { -0.32504349f, -0.32502096f, -0.32501094f, -0.32423576f }, { -0.65602876f, -0.65622598f, -0.65567173f, -0.65525128f }, { -1.4666488f, -1.4666488f, -1.4666488f, -1.4666488f }, { 0.87168363f, 0.87181364f, 0.87181792f, 0.8718169f }, { -1.264365f, -1.264365f, -1.264365f, -1.264365f }, { 0.89917968f, 0.89916889f, 0.89916525f, 0.89927374f }, { -1.2245906f, -1.2245906f, -1.2245906f, -1.2245906f }, { -0.8885678f, -0.88856217f, -0.88856327f, -0.88855044f }, { -0.31799095f, -0.31916566f, -0.31907669f, -0.31918911f }, { -0.08987958f, -0.090342401f, -0.090004674f, -0.090222398f }, { -0.59425693f, -0.59433999f, -0.59429118f, -0.59433553f }, { 1.1317575f, 1.1317475f, 1.1317412f, 1.1317494f }, { -1.2193493f, -1.2193493f, -1.2193493f, -1.2193493f }, { 1.2506981f, 1.250675f, 1.250675f, 1.2506569f }, { -1.08782f, -1.0877793f, -1.0878022f, -1.0878025f }, { -0.13925598f, -0.13932948f, -0.13919658f, -0.13913403f }, { -0.40394684f, -0.4042314f, -0.40436178f, -0.40402218f }, { -0.47762966f, -0.47745572f, -0.47767784f, -0.47713093f }, { -0.60177181f, -0.60176862f, -0.60177347f, -0.60177079f }, { 2.7311956f, 2.7311911f, 2.7311911f, 2.731191f }, { -1.3109856f, -1.3109856f, -1.3109856f, -1.3109856f }, { 0.60942644f, 0.60941369f, 0.6094123f, 0.60944198f }, { 0.55675448f, 0.55672275f, 0.55672303f, 0.5567542f }, { -0.40637059f, -0.4057945f, -0.40635768f, -0.40636681f } }, { { -0.0016154222f, -0.0015930079f, -0.0015828998f, -0.00087447165f }, { -0.0011262472f, -0.001324462f, -0.00094895016f, -0.00062188189f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 9.7616744e-05f, 0.00010718899f, 0.00010718606f, 0.00012665246f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00013476236f, 6.982272e-05f, 6.8208505e-05f, 0.00014604742f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.0031089951f, -0.0031071196f, -0.0031207245f, -0.0031097054f }, { -0.0027808116f, -0.0035049857f, -0.0034100135f, -0.0035192661f }, { -0.0018291474f, -0.0019603285f, -0.0018919656f, -0.0019656229f }, { -0.0034301741f, -0.0034912573f, -0.0034474395f, -0.0034893985f }, { -6.156701e-06f, -9.8568527e-06f, -1.2383692e-05f, -9.9984205e-06f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00011838153f, 0.00011008679f, 0.00011008878f, 0.00010536608f }, { -0.0006246638f, -0.00058479459f, -0.00061327452f, -0.00061085433f }, { -0.0059197749f, -0.0059778169f, -0.0059586015f, -0.0058798299f }, { -0.0013246996f, -0.0016061786f, -0.0016081246f, -0.0014374546f }, { -0.001593227f, -0.0014706843f, -0.0015974008f, -0.001341579f }, { -0.0027930604f, -0.0027920013f, -0.0027939865f, -0.0027928528f }, { -1.8908723e-06f, -4.266382e-06f, -4.2210172e-06f, -5.0155215e-06f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00018508026f, 0.00019774537f, 0.00019744661f, 0.00019538593f }, { 2.3243747e-05f, 1.7291398e-05f, 1.7309712e-05f, 2.9261396e-05f }, { -0.0041402471f, -0.0037085946f, -0.0041294876f, -0.0041316136f } }, { { -0.0018899732f, -0.0018719182f, -0.0018661076f, -0.0012234594f }, { -0.0012968123f, -0.0012971446f, -0.00093522854f, -0.00066475268f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 9.1054464e-05f, 0.00014124217f, 0.00014156806f, 0.00012014953f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00017026995f, 0.00010528413f, 0.00010537941f, 0.00015698848f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.0025812972f, -0.0025835894f, -0.0025789321f, -0.002554949f }, { -0.0035568863f, -0.0042988014f, -0.0042155548f, -0.004312546f }, { -0.0024184575f, -0.0025111277f, -0.0024654994f, -0.0023980076f }, { -0.0036993386f, -0.0037113013f, -0.0036987284f, -0.0037094875f }, { -5.074861e-06f, -1.1367399e-05f, -1.4819989e-05f, -9.2705899e-06f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00012570403f, 0.00012150272f, 0.00012149179f, 0.00010579599f }, { -0.00062162762f, -0.00058131015f, -0.00060837583f, -0.00060795256f }, { -0.00775735f, -0.0077198081f, -0.0078365948f, -0.0077749317f }, { -0.0015325554f, -0.0017125784f, -0.001703195f, -0.0015662859f }, { -0.0018130784f, -0.00177106f, -0.001858095f, -0.0015845058f }, { -0.003668417f, -0.0036659688f, -0.0036693421f, -0.0036680526f }, { -9.5804016e-06f, -9.6276607e-06f, -9.630607e-06f, -1.2159056e-05f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00017930618f, 0.00020084683f, 0.00020150104f, 0.00020810787f }, { 2.3869269e-05f, 1.1024793e-05f, 1.1041937e-05f, 1.6467357e-05f }, { -0.004690782f, -0.0044656761f, -0.0046782065f, -0.0046921455f } } }, { { { 0.23047932f, 0.23043226f, 0.23041471f, 0.22922185f }, { 0.14990977f, 0.15703656f, 0.15110771f, 0.15149153f }, { 0.30629171f, 0.30426701f, 0.30400037f, 0.30403889f }, { 0.03476576f, 0.036188528f, 0.036216719f, 0.037322097f }, { 0.31066251f, 0.31090363f, 0.31041565f, 0.31057779f }, { 0.04875259f, 0.046468595f, 0.046486323f, 0.046584523f }, { 0.31745458f, 0.31874472f, 0.32086369f, 0.31880207f }, { 0.64054942f, 0.64062862f, 0.64051973f, 0.64059059f }, { 0.27309038f, 0.27480819f, 0.27477284f, 0.27486762f }, { 0.196647f, 0.19687982f, 0.19607604f, 0.1957915f }, { 0.32867362f, 0.32858008f, 0.32856702f, 0.328555f }, { -0.0026873031f, -0.0042393446f, -0.0057894907f, -0.0041858859f }, { 0.40254624f, 0.4024247f, 0.4025598f, 0.40243731f }, { 0.019362807f, 0.018146218f, 0.018146051f, 0.019656613f }, { 0.29328089f, 0.29403937f, 0.29435036f, 0.29403094f }, { 0.57111506f, 0.57118505f, 0.57099608f, 0.57099266f }, { 0.16966612f, 0.16993739f, 0.17069399f, 0.16991136f }, { 0.14989055f, 0.1489484f, 0.14995985f, 0.15015916f }, { 0.33606014f, 0.33606294f, 0.33606393f, 0.33605429f }, { 0.015421206f, 0.015180692f, 0.01518037f, 0.015431139f }, { 0.33165237f, 0.33185282f, 0.33162592f, 0.33166981f }, { 0.078137018f, 0.078153855f, 0.078165152f, 0.078332343f }, { 0.002896946f, 0.0026038621f, 0.0026029604f, 0.0022081151f }, { 0.41064398f, 0.40987685f, 0.41065341f, 0.41059166f } }, { { -0.0024316111f, -0.0024732789f, -0.0024922144f, -0.0035874346f }, { 0.0013306961f, 0.004171802f, 0.0027660627f, 0.0023671465f }, { 0.0034411091f, 0.0020878413f, 0.0020874456f, 0.0022028237f }, { -0.0032873976f, -0.0021351911f, -0.0021071363f, -0.0028424534f }, { 0.0017995208f, 0.0022319618f, 0.0039270256f, 0.0021249365f }, { -0.0019590835f, -0.0012526895f, -0.0012347747f, -0.0021069943f }, { 0.0012319531f, 0.002255621f, 0.0030193583f, 0.0020970822f }, { 0.0015144077f, 0.0015110104f, 0.0014803089f, 0.0015340007f }, { -0.0036679996f, -0.0028160114f, -0.0028586497f, -0.0027953731f }, { -0.005445786f, -0.0052624873f, -0.0054843188f, -0.0053271749f }, { 0.00067154572f, 0.0007530775f, 0.00067974516f, 0.00074462315f }, { -0.0035626119f, -0.0034186877f, -0.0038720517f, -0.0040088745f }, { 0.003455851f, 0.0035040061f, 0.0034671486f, 0.0035069881f }, { -0.0047789747f, -0.0047994804f, -0.0047996451f, -0.0044008337f }, { 0.0032403482f, 0.0033627856f, 0.003429619f, 0.0031153117f }, { -0.005027022f, -0.0049812f, -0.0049604573f, -0.0050556194f }, { -0.0020728991f, -0.0014784158f, -0.001216894f, -0.0019213729f }, { -0.00013808007f, -0.00067270623f, -0.00024001574f, -0.00030691077f }, { 0.0004367104f, 0.00043390709f, 0.00043548166f, 0.00043425516f }, { -0.00082746467f, -0.00088151411f, -0.00088152334f, -0.0008043643f }, { 0.0030277712f, 0.003133577f, 0.0028529862f, 0.0030362271f }, { -0.0058721937f, -0.0059816331f, -0.0059799345f, -0.0058882832f }, { -0.0057032562f, -0.0057401855f, -0.0057416619f, -0.0062417688f }, { -0.0014357888f, -0.0020782049f, -0.0014346823f, -0.0014513767f } }, { { -0.0027051235f, -0.0027087245f, -0.0027052303f, -0.0033594951f }, { 0.0028036195f, 0.0030416572f, 0.0014306948f, 0.0017897371f }, { 0.0031113166f, 0.0026432303f, 0.0025937824f, 0.0025394463f }, { -0.0036032904f, -0.003447065f, -0.0034344406f, -0.0024163572f }, { 0.0023912799f, 0.0025281229f, 0.0038665087f, 0.0024214034f }, { -0.0023543827f, -0.0024294943f, -0.0024539784f, -0.0027742617f }, { 0.0020903896f, 0.0026617586f, 0.003395249f, 0.0026261065f }, { 0.0019031008f, 0.0019405475f, 0.0019426085f, 0.0019404325f }, { -0.0040413326f, -0.0030964835f, -0.0031020735f, -0.0030826754f }, { -0.0064568993f, -0.0062342438f, -0.0064704698f, -0.0065636744f }, { 0.0010788406f, 0.0010092051f, 0.0010264121f, 0.00099891228f }, { -0.0040759201f, -0.0059224283f, -0.0066809927f, -0.0049099348f }, { 0.0042962009f, 0.0041909175f, 0.0043195236f, 0.0041900138f }, { -0.0062728983f, -0.0070256154f, -0.007025641f, -0.0061758746f }, { 0.0036210401f, 0.0039723998f, 0.0042232048f, 0.0042757707f }, { -0.0058693852f, -0.0058583303f, -0.0058544016f, -0.005887725f }, { -0.0023099876f, -0.0021136245f, -0.0017298078f, -0.0022483337f }, { -0.00017851962f, -0.00014956209f, 8.5676316e-05f, -0.00024971669f }, { 0.0003734781f, 0.00037078986f, 0.00037364181f, 0.00037070594f }, { -0.00030648905f, -0.00038230535f, -0.00038223043f, -0.00028623253f }, { 0.0032871423f, 0.0034163052f, 0.0028276655f, 0.0032991918f }, { -0.0061331695f, -0.0063319797f, -0.0063340119f, -0.0064390374f }, { -0.0062172888f, -0.0059787106f, -0.0059793294f, -0.0060406701f }, { -0.0018276142f, -0.0022170788f, -0.0018293949f, -0.0018222824f } } } }, { { { { 0.13218089f, -0.11654637f, -0.11622196f, -0.044208736f }, { 0.0074579257f, 0.0038503609f, 0.0013201096f, 4.0415784e-05f }, { -0.025474487f, -0.01209255f, -0.016535858f, 0.012704547f }, { -0.0016894103f, -0.0081312144f, -0.0033264609f, 0.0011923269f }, { -0.068044876f, 0.018276873f, -0.074833897f, 0.01308348f }, { 0.02665691f, 0.013515118f, 0.026440814f, -0.0077037816f }, { 0.0023286096f, -0.0025782652f, 0.0021644694f, -0.0042955294f }, { 0.051356261f, -0.031058382f, -0.085382962f, -0.033103269f }, { -0.081609229f, 0.0035270199f, -0.015722417f, 0.048773789f }, { 0.0023928418f, -0.001243811f, 0.011910492f, -0.011621478f }, { -0.028953904f, -0.029335777f, -0.0057891432f, 0.013874136f }, { -0.012473582f, 0.001772629f, -0.013983442f, 0.014846792f }, { -0.016111661f, 0.0018902323f, 0.025910586f, 0.042848276f }, { 0.026200626f, 0.024007879f, 0.0017667146f, -0.016394032f }, { -0.0067006429f, -0.0017968936f, 0.009028659f, 0.0044060413f }, { 0.019280611f, 0.0449581f, -0.042852227f, -0.066012332f }, { -0.014451123f, -0.047772741f, -0.047475406f, 0.098434178f }, { -0.0028954635f, 0.010521833f, -0.015741597f, -0.00091666191f }, { 0.0020291956f, -0.057966746f, -0.04525094f, 0.032711614f }, { 0.020563445f, -0.0078684621f, -0.015282237f, -0.0019830466f }, { -0.019504171f, 0.071338511f, 0.0033729474f, -0.0095772339f }, { 0.013056103f, 0.018719519f, 0.0096002937f, -0.028774366f }, { -0.00038728577f, -0.0010662982f, -0.0014333502f, 0.00059135695f }, { 0.073844752f, -0.05666013f, -0.1007151f, -0.030440738f } }, { { 0.00017766639f, -9.2398532e-05f, -3.9442682e-05f, -3.9559848e-05f }, { -0.0043956477f, 0.00044042277f, -0.00047491077f, 9.4171117e-05f }, { -0.0042095545f, -0.00910753f, -0.0014295282f, 0.0042595844f }, { 0.00070989004f, -0.0009623012f, 0.00084162653f, -0.00015925965f }, { -0.0017587638f, 0.0033199811f, -0.00025544613f, 0.00083644978f }, { 0.0051797987f, 0.0015691893f, -0.002324397f, 0.0050776381f }, { 0.003911779f, 0.00072639703f, 2.102924e-05f, -0.0029529332f }, { 0.0050240476f, -0.00041452319f, 3.1730448e-06f, -0.0072697591f }, { -1.5023048e-05f, 0.00032491246f, -9.2151952e-05f, 0.0035851726f }, { 0.0030984373f, 0.0016428856f, 0.0032974124f, -0.0036034289f }, { -0.00044578206f, -0.0035916409f, 0.0028146658f, 0.0068013321f }, { 0.00025716711f, -0.0024772152f, 0.0029660992f, -0.0008783244f }, { -0.005543602f, -0.00046453249f, 0.006815884f, 0.0069207512f }, { -0.0033541738f, -0.0015140333f, -0.004071746f, -0.0020908789f }, { 0.0027932918f, -0.0012517158f, -0.0033509184f, -0.001271572f }, { 0.0043481525f, -0.00088858735f, -0.0081538059f, 0.00027985077f }, { 7.4017523e-05f, -7.0080388e-05f, -7.1766386e-05f, 0.00020468758f }, { 0.00044507396f, 0.010179106f, -0.0048087449f, 0.0013487105f }, { 0.00082148695f, -0.00042640153f, -0.0024255173f, 0.0044486011f }, { -0.00026383509f, -0.0031871528f, -0.008203704f, -0.00053957093f }, { -0.0002996462f, 0.00070789605f, 7.9300612e-05f, -0.00024002209f }, { 0.0013722116f, 0.0049176054f, 0.0029283062f, -0.000849108f }, { 0.00026545039f, 0.0011783443f, 0.00072103548f, -0.0007355776f }, { 0.002192273f, -0.00294318f, 1.5452606e-05f, -0.0020953993f } }, { { 2.4074136e-05f, -2.4931598e-05f, -1.0893587e-05f, 1.080951e-05f }, { -0.0061635883f, -0.0042963493f, -0.00177783f, -0.00080292808f }, { 0.0047868795f, -0.0050472436f, 0.0082439123f, -0.0090979713f }, { 0.0017221077f, 0.0067285193f, 0.0031011872f, -0.0019932567f }, { 0.0010926271f, -0.0012170693f, 0.00012875612f, 0.00016441623f }, { -0.0048786273f, -0.0041225634f, -0.005591426f, 0.0043469593f }, { -0.0070664098f, -0.0012625813f, -0.00022220241f, -0.0026120468f }, { -0.0026689917f, 0.00030860545f, 1.9297947e-05f, 0.001274799f }, { 0.0026769559f, 0.00016106032f, 0.00013829246f, -0.0017239107f }, { -0.0042495789f, 0.0010270326f, -0.00078224804f, -0.0019210019f }, { 0.0072385804f, 0.0086418476f, 0.0061428272f, -0.0027142827f }, { 0.0019768127f, -0.00057957046f, 0.0047464783f, -0.004599565f }, { 0.0093618867f, -0.0010476542f, -0.0038681572f, -0.0065219521f }, { -0.0076406673f, -0.0036729355f, -0.0068804827f, 0.0077571478f }, { 0.0012706397f, -0.00042567505f, -0.002521821f, 6.0288127e-05f }, { -0.002041411f, 0.000430125f, 0.0073620925f, 0.0021579456f }, { 0.00012145466f, 4.1276616e-05f, 4.2449608e-05f, 9.8351262e-05f }, { 0.0014376278f, -0.007439719f, 0.0039006971f, 0.00051135138f }, { -7.1665367e-05f, 0.00023856335f, 0.00015274881f, -0.0096946274f }, { -0.00076804256f, 0.0040182915f, 0.012603411f, -0.00059669891f }, { -0.00010641981f, -0.00052355992f, 0.00057481361f, 0.00016456343f }, { -0.0027623375f, -0.0036761364f, -0.010480297f, 0.0066006902f }, { 0.00049081404f, 0.00077264749f, 0.0021355718f, -0.00029188425f }, { 0.00028566818f, 0.00097678458f, 0.00089022281f, -0.00013760767f } } }, { { { -0.0098123577f, 0.11017117f, 0.11245143f, -0.01173447f }, { 0.0036188505f, -0.0025878518f, -0.00043343726f, -0.0038813197f }, { 0.013109746f, -0.016775181f, -0.0011093308f, 0.00083465721f }, { -0.0042515898f, -0.0028159364f, 0.00027829209f, -0.002907578f }, { -0.0081027554f, -0.0019330574f, 0.061872524f, -0.037539524f }, { -0.012923735f, 0.021011524f, 0.002680406f, 0.0034369108f }, { 0.0027819214f, 0.0028657905f, -0.0034177203f, -0.0037322329f }, { -0.0036178174f, 0.065792163f, 0.13263475f, 0.0055427994f }, { 0.027832309f, -0.083372016f, -0.058757582f, 0.016164879f }, { -0.0082343898f, 0.011782416f, 0.011496052f, -0.0027847616f }, { 0.0012516658f, -0.014686832f, -0.025073035f, -0.020700577f }, { 0.0055718234f, -0.011543219f, -0.012867689f, -0.0049474286f }, { 0.028869265f, -0.035431559f, 0.024976635f, -0.01063055f }, { -0.0010657662f, 0.014977146f, 0.027109f, 0.01612865f }, { -0.0021697493f, 0.0044220507f, 0.0055654161f, -0.0032373397f }, { -0.018500666f, -0.01979267f, -0.0068480612f, 0.03908391f }, { 0.063306878f, 0.01934691f, 0.019254616f, -0.099824471f }, { 7.0580666e-05f, -0.0015082457f, -0.0056893693f, 0.00022726294f }, { 0.0077067654f, -0.014018834f, -0.021406454f, -0.0076589993f }, { -0.0013072394f, 2.6765854e-05f, 0.0028400803f, 0.0037431063f }, { -0.025369581f, -0.064039908f, -0.020594137f, -0.086807367f }, { -0.033639351f, 0.010434758f, 0.00082983507f, 0.013145885f }, { 0.00029373395f, 7.8193614e-05f, 0.00048496415f, 0.00062972215f }, { -0.0041597628f, 0.024283117f, -0.030148407f, 0.011456515f } }, { { -1.3484857e-05f, -3.7204145e-05f, -1.5660577e-05f, -2.4497955e-05f }, { -0.0068070249f, 0.0041035892f, 0.0034647689f, 0.0035918321f }, { -0.0053613309f, 0.0080593503f, 0.0028507084f, -0.0023104987f }, { 0.0048581064f, 0.0039720065f, -0.0019058129f, 0.0047295789f }, { -0.00030675956f, -0.0007787587f, -0.00025201217f, 0.00020777843f }, { -0.00026433336f, -0.0093672701f, -0.0053201627f, -0.0059632173f }, { -0.0063062815f, 0.0011995204f, 0.0001870407f, 0.0028197877f }, { -0.00053247524f, -0.00066138217f, -1.4959372e-05f, -0.00036023628f }, { 0.00027591427f, 0.00011309835f, 2.2453632e-05f, -0.00075736359f }, { 0.0015654886f, 0.0018114616f, -0.0004503446f, -8.5866048e-05f }, { 0.003501393f, 0.0037179893f, 0.008328543f, 0.013411108f }, { -0.0035136609f, -0.0015054003f, 0.0011903964f, 0.0022551358f }, { -0.0083723767f, 0.0061303554f, -0.008056962f, 0.0035035183f }, { -0.0023715655f, -0.0070468331f, -0.010219655f, -0.0057856465f }, { -0.0011406634f, -0.00021204595f, -0.001693195f, 0.0011051597f }, { 0.0011643412f, 0.00037557194f, 0.0048567739f, -0.00063996433f }, { -3.1728174e-05f, -2.9073903e-06f, -3.0243209e-06f, 2.579239e-05f }, { 0.00053152589f, 0.0029635352f, 0.0040743289f, -0.00051381046f }, { -0.0017253584f, 0.00012081524f, 0.00012243664f, -0.00063598215f }, { 0.0026711847f, -0.0020733972f, -0.0027860744f, 0.0017065643f }, { 5.7762902e-05f, 0.00092043577f, -0.0035278882f, 0.0007846087f }, { 0.0056127705f, -0.0051893669f, -0.0027072408f, -0.0025630045f }, { -0.00059289151f, -0.0004168408f, -8.8118696e-05f, -0.00073538101f }, { 0.0003388606f, -0.00094234652f, 3.013109e-05f, -0.0010532484f } }, { { -2.9013996e-05f, 6.1983083e-05f, 2.8401438e-05f, -3.4901557e-05f }, { 0.0045230474f, -0.0021369843f, -0.00422706f, -0.0018918027f }, { 0.00017586142f, 0.005389053f, 0.0071352982f, -0.0018278685f }, { -0.0012135723f, -0.0035970727f, 0.00078957165f, -0.0017065397f }, { -0.00067051937f, -1.9501585e-05f, 4.1968766e-05f, -0.0010958091f }, { -0.0015277626f, -0.0039952533f, -0.00049631478f, 0.0018042745f }, { 0.0039376754f, -0.00097834328f, 6.5894634e-06f, -0.0044189106f }, { -0.00067623039f, 0.0004690807f, 1.4532105e-07f, 0.0032984829f }, { 0.0020787449f, -0.0016586579f, -0.00062367064f, 0.0021545362f }, { 0.0016427801f, 2.6710288e-05f, 0.0016011535f, -0.00077649869f }, { 0.0039999622f, -0.0014968097f, -0.0025647576f, 0.0022783424f }, { 0.001558454f, -0.00083803058f, 0.0018955692f, 0.0010432376f }, { 0.010555722f, -0.010395022f, 0.0050354965f, -0.0016177699f }, { 0.00011370745f, -0.009328355f, -0.0063009522f, 0.0024377458f }, { -0.00024433189f, 0.00052920244f, -0.0013213352f, -0.0013503982f }, { -0.0057620093f, 0.00095391746f, -0.0034768563f, 0.00093990705f }, { 0.00012108024f, 4.1007202e-05f, 4.2193381e-05f, -0.00011043617f }, { 0.0038593696f, -0.00074282979f, -0.0093457897f, 0.00027311164f }, { 0.0021514797f, -7.8742315e-05f, -0.0018813077f, -0.0017625098f }, { 0.0038491118f, 0.00022570776f, -0.0061331041f, 0.00014956617f }, { -0.00014676603f, -0.00025053931f, 0.003376287f, -0.00014730695f }, { 0.0016439646f, 0.0060569792f, 0.00063058918f, -0.0034810156f }, { 0.00011722835f, 0.00032237223f, -0.0012556553f, -0.0006887808f }, { 0.00060814722f, 0.0003708376f, -0.00056515636f, -0.00016801817f } } }, { { { 0.99117704f, 0.98705585f, 0.98683693f, 0.9989534f }, { 0.99996564f, 0.99998924f, 0.99999903f, 0.99999247f }, { 0.99958951f, 0.99978616f, 0.99986266f, 0.99991895f }, { 0.99998953f, 0.99996298f, 0.99999443f, 0.99999506f }, { 0.99764936f, 0.9998311f, 0.99527468f, 0.99920949f }, { 0.9995611f, 0.99968788f, 0.99964679f, 0.99996442f }, { 0.99999342f, 0.99999257f, 0.99999182f, 0.99998381f }, { 0.99867384f, 0.99734987f, 0.98748052f, 0.99943657f }, { 0.99627571f, 0.99651225f, 0.99814846f, 0.99867903f }, { 0.99996323f, 0.99992981f, 0.99986298f, 0.99992859f }, { 0.99957996f, 0.99946171f, 0.99966886f, 0.99968945f }, { 0.99990668f, 0.9999318f, 0.99981943f, 0.99987754f }, { 0.99945334f, 0.99937032f, 0.99935219f, 0.99902503f }, { 0.99965614f, 0.99959957f, 0.99963092f, 0.99973552f }, { 0.9999752f, 0.99998861f, 0.99994375f, 0.99998505f }, { 0.99964293f, 0.99879278f, 0.99905795f, 0.99705307f }, { 0.99788947f, 0.99867085f, 0.99868681f, 0.99012413f }, { 0.99999581f, 0.99994351f, 0.99985991f, 0.99999955f }, { 0.99996824f, 0.99822008f, 0.99874627f, 0.99943549f }, { 0.9997877f, 0.99996904f, 0.99987919f, 0.99999103f }, { 0.99948785f, 0.99539425f, 0.99978223f, 0.99617908f }, { 0.99934875f, 0.99977032f, 0.99995357f, 0.99949949f }, { 0.99999988f, 0.99999943f, 0.99999886f, 0.99999963f }, { 0.99726107f, 0.99809817f, 0.99445842f, 0.99947091f } }, { { -2.3481737e-05f, -6.7307406e-06f, -2.8605869e-06f, -2.0372001e-06f }, { 6.6885689e-05f, 4.5630281e-06f, 3.5788218e-05f, 1.0842484e-05f }, { -4.9278613e-05f, -2.4660601e-05f, 3.1625301e-06f, 0.00019708279f }, { 1.2439158e-05f, 3.0347865e-05f, 8.6153947e-06f, 1.0887256e-05f }, { -0.00012454598f, -6.513709e-05f, -3.5853483e-06f, -3.4708286e-06f }, { -0.00013746339f, 0.00013516333f, 8.4535039e-05f, 5.693766e-05f }, { -2.3674091e-05f, -3.4690053e-06f, 5.3812265e-07f, -1.7613197e-05f }, { -0.00025790043f, 3.0475251e-05f, 2.1174795e-06f, -0.00023630753f }, { -8.8624748e-06f, 7.9175589e-06f, -2.4258477e-07f, -0.00017288313f }, { 4.0061469e-05f, 0.00069846663f, -0.00060299476f, -0.00015396968f }, { 5.0667108e-06f, 2.306363e-05f, 0.00028636884f, 3.6246633e-05f }, { 0.00032740524f, -0.00037985037f, -0.00014841039f, -0.00012676016f }, { 8.7000758e-05f, 0.00018530207f, 1.7669124e-05f, -0.00023199594f }, { 9.2332094e-05f, 0.00013487652f, 0.00034587506f, -3.8853378e-05f }, { 6.9809868e-05f, -0.00015411544f, 0.0013505166f, 1.4531796e-06f }, { -6.3782301e-05f, 4.8545135e-05f, -0.00027083794f, 4.5129465e-05f }, { 3.0912438e-06f, -3.2982361e-06f, -3.3551612e-06f, -1.7781589e-05f }, { 9.872609e-06f, -2.9944213e-05f, -4.5592652e-05f, 1.5950681e-05f }, { 1.4767773e-05f, -2.2486726e-05f, -0.00010613341f, -0.00015794394f }, { 2.4386215e-05f, -1.1610334e-05f, -4.4456294e-05f, -5.0215596e-06f }, { -4.2741558e-06f, 8.7714242e-06f, -6.6343322e-05f, 6.7010735e-05f }, { 0.00016489767f, -3.3636771e-05f, 5.1610504e-05f, 5.2803593e-06f }, { 1.1649256e-05f, 2.1169993e-05f, 1.9755999e-05f, 1.3389438e-05f }, { -0.00015815197f, -0.00014316145f, 2.6536218e-06f, -4.6846396e-05f } }, { { -3.5109783e-06f, -9.8530632e-06f, -4.5020804e-06f, 6.9233235e-08f }, { 9.9938991e-06f, -2.0914089e-06f, 3.5717699e-05f, 3.2813664e-06f }, { 0.00012938219f, 1.111062e-05f, 8.0858608e-05f, 0.00018147439f }, { 4.8657525e-06f, 8.6580257e-06f, 3.6742927e-06f, 3.5828406e-06f }, { 6.9905696e-05f, 2.0985073e-05f, 6.8866215e-06f, -4.2552499e-05f }, { 0.00012100208f, 9.7821801e-05f, 0.00013576456f, 6.3686234e-05f }, { 1.954525e-06f, -1.0727343e-06f, 5.2332444e-07f, -5.4034988e-06f }, { 0.00013699813f, -2.226833e-05f, 1.4994043e-06f, 1.7110377e-05f }, { 0.0001678261f, -0.00013844113f, -3.4281745e-05f, 5.3854072e-05f }, { -1.3018868e-05f, 0.00022176303f, 0.00016983401f, 0.00038109805f }, { 0.00019016068f, 0.00023448876f, 2.643329e-05f, 4.6842203e-05f }, { -1.2492528e-05f, -0.00059486605f, 0.00012427061f, 8.1876965e-05f }, { 8.400564e-05f, -0.00029859163f, -4.884214e-05f, 0.0002631806f }, { 0.00019907281f, 0.00014046808f, 0.00015482448f, 4.0461099e-05f }, { -0.00024349239f, 0.00081298441f, 0.00084294728f, 7.9617963e-05f }, { -6.0040835e-05f, 3.2352918e-07f, 0.00024295599f, 0.00011067283f }, { -6.0027092e-06f, 1.1975092e-06f, 1.2248893e-06f, -2.1293392e-05f }, { 1.4478736e-05f, 6.8326918e-05f, -7.8693614e-06f, 9.2888155e-06f }, { -1.6982828e-05f, 1.2094341e-05f, -3.1693808e-05f, 0.00028574477f }, { 3.4480942e-05f, 2.6556008e-05f, 0.00016193956f, -1.8966503e-06f }, { -5.7726961e-06f, 2.1091148e-05f, 5.8963955e-05f, -1.0834372e-05f }, { 0.0001214393f, 1.4174882e-05f, 0.0001371836f, 0.00021757165f }, { 1.0140226e-05f, 6.1641031e-06f, 1.0590727e-05f, 1.0893212e-05f }, { -1.7442656e-05f, 4.2353331e-05f, 7.4324714e-05f, -1.9484775e-06f } } }, { { { 3.7217719f, 3.6900797f, 3.6899881f, 3.6670816f }, { 0.067826319f, 0.16468028f, 0.083129199f, 0.1336756f }, { 0.66338737f, 0.23883566f, 0.093361469f, 0.10095622f }, { 0.27185537f, 0.20781392f, 0.32216624f, 0.29876595f }, { 2.0776462f, 2.0006156f, 2.0243138f, 2.080345f }, { 0.57695783f, 0.18015147f, -0.11440889f, 0.14229144f }, { 0.63833683f, 0.41431062f, 0.44752994f, 0.47594414f }, { 1.7890608f, 1.962584f, 1.9322155f, 1.6588331f }, { 3.0538128f, 3.108267f, 3.1001573f, 2.9593433f }, { -0.28383051f, -0.27708376f, -0.042513902f, -0.085181891f }, { 0.3873435f, 0.41697884f, 0.39625427f, 0.33250735f }, { -0.33498881f, -0.40206929f, -0.028905862f, -0.48179632f }, { 1.1875033f, 1.3535177f, 1.2526197f, 1.3337495f }, { 0.42579488f, 0.24951727f, 0.18976118f, 0.20605317f }, { -0.53212666f, -0.3861028f, -0.75685995f, -0.23411882f }, { 1.6910165f, 1.686815f, 1.5906473f, 1.6528217f }, { 4.0570657f, 4.0349492f, 4.0350332f, 4.0498099f }, { -0.017225465f, -0.032503897f, 0.46003211f, 0.21602109f }, { 1.1196901f, 1.00885f, 0.91675568f, 0.99635794f }, { -0.093891275f, 0.0809352f, -0.13783332f, 0.27130678f }, { 1.9925136f, 1.9829394f, 1.8820721f, 1.9542026f }, { 0.84563763f, 0.48476746f, 0.37907152f, 0.70267878f }, { 0.37054708f, 0.4228574f, 0.6329822f, 0.26197064f }, { 1.9618393f, 1.8405969f, 1.9440918f, 1.901629f } }, { { -5.6047186e-06f, 6.0454847e-06f, 2.8365975e-06f, 6.0894367e-06f }, { -0.00069876506f, -0.00029642785f, -0.00059516082f, -0.00025400441f }, { -0.00020850504f, -0.00012959593f, -0.00032902532f, -0.00058117893f }, { -0.00037901964f, -0.00038062016f, -0.00023777964f, -0.00033714679f }, { -5.9894351e-05f, -9.820791e-05f, -5.9867157e-06f, -6.258549e-06f }, { -0.00035424038f, -8.7146215e-05f, 3.0398362e-05f, -0.00061406521f }, { 0.00014971442f, 4.5936211e-05f, -5.6259869e-06f, 0.00013567035f }, { -0.00016180211f, 3.1840487e-06f, 3.8979157e-07f, -0.00017131994f }, { -1.9877193e-05f, 2.5768261e-05f, 9.0577543e-06f, -0.00013927462f }, { -0.0012323564f, -0.00042892846f, 7.2082106e-05f, 0.00010999853f }, { -0.00034618449f, -0.00017058897f, -0.00016535057f, -0.00096982024f }, { -0.00028039653f, -7.155747e-05f, -0.00075796707f, 0.00062756458f }, { 6.6596276e-05f, -7.9730809e-05f, -8.0686754e-05f, -2.9532397e-05f }, { -0.00084106867f, -0.00036762453f, 0.00012523548f, -0.00052789663f }, { 7.6718268e-05f, -0.0010042005f, -0.00042802983f, -0.0011951304f }, { -3.6972258e-05f, 2.1447505e-06f, -0.00035448623f, -1.0620008e-05f }, { 2.8326169e-05f, 2.2049468e-05f, 2.2640575e-05f, 1.7574827e-05f }, { -0.00014318496f, -0.0004811524f, -0.00049293303f, -0.00067646484f }, { -2.7469144e-05f, -5.9653763e-06f, -1.3998899e-05f, -0.00018475323f }, { -0.00017314302f, -0.00010954727f, -0.00040004932f, 3.31106e-05f }, { -3.6093435e-06f, -1.6125243e-05f, -4.9195648e-05f, 1.5586886e-05f }, { 0.0002059631f, -0.0004024722f, -0.00047984678f, -9.8485329e-05f }, { -0.00094100913f, -0.00073046048f, -0.00052500163f, -0.00068196784f }, { -2.2820197e-05f, -5.9454557e-05f, -6.2505468e-06f, -2.6569804e-05f } }, { { 2.6015883e-05f, 8.5398335e-06f, 3.8473185e-06f, 9.1409625e-06f }, { -0.00041459247f, -0.0001855224f, -0.00030529542f, -0.00016322166f }, { -8.8427847e-05f, -0.0002302048f, -0.00038072959f, -0.00076801295f }, { -0.00027717792f, -0.00028594346f, -0.00017910208f, -0.00027291164f }, { 2.8409311e-05f, -3.8005817e-05f, -4.2266878e-06f, -1.4520383e-05f }, { -0.0001088827f, -0.00021924377f, 3.9307406e-05f, -0.00032488556f }, { 0.00027997916f, 3.5103699e-05f, -5.7448764e-06f, 0.00010259251f }, { -4.7807894e-06f, -2.9470863e-05f, 2.6656233e-07f, -0.00014346393f }, { 0.00015527098f, -6.8528726e-05f, -1.1206714e-05f, 2.3422595e-05f }, { -0.0012763247f, -0.00051503472f, 0.00058055106f, -0.00068688488f }, { -6.1232076e-06f, -1.7073841e-05f, -0.00033533389f, -0.00078769935f }, { -0.00044113485f, -0.00027577451f, -0.0012008622f, 0.00013071136f }, { 1.834948e-05f, -0.00015615102f, -0.00016449385f, 3.6685217e-05f }, { -0.00063618257f, -0.00032641968f, -5.0281118e-05f, -0.00041378992f }, { -0.0010181884f, -0.0003871932f, -0.00050061147f, -0.0018967455f }, { -5.7650067e-05f, -5.1145774e-06f, -0.00017409773f, 1.9512036e-05f }, { 1.5838743e-05f, 2.503655e-05f, 2.5679098e-05f, 2.0053218e-05f }, { -0.00018055811f, -0.00044345237f, -7.9049557e-05f, -0.00095669161f }, { -4.98611e-05f, -1.1320605e-06f, 3.7756645e-06f, -8.7299215e-05f }, { -0.00011794063f, -0.00015778552f, -0.00036514881f, 4.7288704e-05f }, { -5.1753817e-06f, -1.5040527e-06f, -2.836739e-05f, -9.4945229e-06f }, { 0.00016873335f, -0.00031983601f, -0.00052281245f, 0.00019034815f }, { -0.0011988594f, -0.0010684975f, -0.00057577023f, -0.0009143845f }, { 5.0336006e-05f, -1.356148e-05f, 1.5582694e-05f, -2.0666272e-05f } } }, { { { 0.012207721f, 0.0044164612f, 0.0022704542f, 0.0042008503f }, { 0.29516302f, 0.139976f, 0.35038027f, 0.13748343f }, { 0.1462123f, 0.12114907f, 0.28473665f, 0.45762717f }, { 0.17976664f, 0.19141553f, 0.1209483f, 0.16393769f }, { 0.044254492f, 0.11383095f, 0.0062726904f, 0.023550537f }, { 0.14785458f, 0.10151341f, 0.045717467f, 0.42243971f }, { -0.24205201f, -0.033590842f, 0.0032064617f, -0.093924041f }, { 0.10866955f, 0.016299431f, 0.00081631108f, 0.15856447f }, { 0.10108337f, 0.057931152f, 0.024463589f, 0.21514346f }, { 0.47967783f, 0.75472932f, 0.5653649f, 0.64752457f }, { 0.30082544f, 0.15124922f, 0.23567284f, 0.47161499f }, { 0.54286166f, 0.61049777f, 0.61641378f, 0.51181399f }, { 0.39328762f, 0.25557559f, 0.25875912f, 0.22436901f }, { 0.45699569f, 0.16989563f, 0.2429263f, 0.3924359f }, { 0.92996797f, 1.1024806f, 0.78045387f, 1.2298879f }, { 0.19029829f, -0.022675055f, 0.28113642f, 0.034941166f }, { 0.013203939f, 0.013034069f, 0.013414649f, 0.011688038f }, { 0.076026927f, 0.13838472f, 0.29961655f, 0.31531564f }, { 0.089182386f, 0.010401684f, 0.029374547f, 0.22995838f }, { 0.052198894f, 0.039866726f, 0.11570972f, -0.013818992f }, { 0.0062380932f, 0.01788119f, -0.20765047f, 0.013339281f }, { 0.12436441f, 0.17318651f, 0.21554136f, 0.18600144f }, { 0.38005287f, 0.32135548f, 0.28632777f, 0.29211902f }, { 0.03798742f, 0.0450845f, 0.010912505f, 0.039060104f } }, { { 0.00077914246f, 0.00011130803f, 8.1110229e-05f, -0.00035312557f }, { 0.00051711901f, 0.00029701387f, 0.00040733345f, 0.00034149723f }, { 0.00063893978f, -0.00013702086f, 0.00030866699f, -0.00020070677f }, { 7.5899443e-05f, 9.7456273e-05f, -4.5352178e-05f, 7.6172703e-06f }, { 0.00066250814f, -0.00073033349f, 0.00015225542f, -0.0010197351f }, { 0.00040931533f, -0.00043022747f, 0.00093333285f, 0.0002579685f }, { -0.00067488578f, -0.0003706974f, -0.00044487256f, -0.00056555959f }, { 0.00075838366f, -0.0021903789f, -0.0026744174f, -0.00047135202f }, { -0.00081050821f, -0.0010297809f, -0.00099480849f, -0.00074914246f }, { 0.00063637392f, 5.248783e-05f, 0.00044645091f, 0.00018028446f }, { 0.00067430392f, 0.0004762628f, -0.00032736685f, 0.00041933609f }, { 6.2324555e-05f, -1.6709531e-06f, 0.00057418116f, -0.0010360999f }, { -0.00038256183f, -0.0010104012f, -0.00045533693f, -1.3888404e-05f }, { 0.00068274628f, 0.00068411875f, -0.00091273333f, 0.00016211145f }, { -0.00039440715f, 0.00027665323f, -0.00035895503f, 0.00013423207f }, { -0.00061939017f, 0.00012140102f, 0.00024178233f, 0.00064755788f }, { -0.00052441128f, -0.00050994483f, -0.00051126044f, 0.00066320373f }, { 0.00085915332f, 0.0013567332f, -0.00014328466f, 0.00056098523f }, { -0.0012682676f, 0.0029139719f, 0.0019812291f, -0.00053863027f }, { 0.0021895869f, 0.00062956835f, 0.0018161156f, 0.00011699452f }, { -0.0010337306f, 0.00016880497f, -0.0014942346f, -0.0034402453f }, { -0.0025336946f, -0.00019468865f, -0.00018045349f, -5.4312149e-05f }, { 0.00021491979f, 4.7651714e-05f, -0.00044921151f, 0.00046742044f }, { 0.0019408125f, 0.00044842687f, 0.0026003265f, -0.00090116109f } }, { { -0.0006591255f, 0.00022873584f, 0.00026313866f, -0.00060151354f }, { 0.00027198127f, 0.00034252944f, 0.00033246896f, 0.00035232159f }, { -0.00034460639f, -5.9085725e-05f, 7.836454e-05f, -0.00018946388f }, { 0.00018790551f, 0.0001918358f, 9.7031467e-05f, 0.00015259869f }, { -0.0023033429f, -0.0012945186f, -0.00080964072f, -0.00030432514f }, { -0.001359781f, 0.00055828912f, -0.00041912301f, 0.00019263336f }, { -0.00042789448f, -0.00018313775f, -0.00030217124f, -0.00028437496f }, { -0.0018340159f, 0.00030654336f, -0.00010781402f, -0.0011985455f }, { -0.002103478f, 0.00029492518f, -0.00042283946f, -0.001472689f }, { 0.00064558079f, 0.00049703204f, -0.00018932594f, -0.00038268301f }, { -0.00097813334f, -0.00057838807f, 0.00079268109f, 0.00039650774f }, { -0.00017335252f, 0.00074363734f, 0.0008194423f, -0.00065923207f }, { -0.00075344545f, -0.00026114262f, -0.00054658657f, -0.0013814943f }, { -0.00028279346f, 0.00055730283f, 0.00048990213f, -0.00022186466f }, { 0.00013438509f, -0.0001962818f, -0.00036195953f, 0.00042669461f }, { -0.00089003585f, -0.0011600794f, -0.0012554286f, -0.0012892408f }, { -0.00067007058f, -0.0010597247f, -0.0010590421f, 0.00044132516f }, { 0.0011626727f, 0.001261033f, -0.00072912018f, 0.00076332442f }, { -0.001204702f, -0.00011230019f, 0.00036178615f, -0.0017559004f }, { 0.00096282849f, 0.001025959f, 0.0011696947f, 0.00046633555f }, { -0.00082328571f, -0.00075771669f, -0.0011629302f, 0.00073458863f }, { -0.0016869269f, -0.00035239862f, -0.0004024204f, -0.0016276971f }, { 0.00029053123f, 0.00013409355f, -0.00049087974f, 0.00061969429f }, { -0.0013198997f, -0.0018615784f, -0.0025724061f, -0.0015563017f } } } }, { { { { -0.072246889f, -0.043157285f, 0.043289306f, 0.095998047f }, { 0.12597079f, 0.24289541f, -0.10930005f, -0.24150539f }, { 0.031889347f, -0.036238337f, -0.014521983f, -0.018963885f }, { -0.044155351f, -0.0077170425f, -0.043781059f, 0.047982339f }, { 0.093995001f, -0.0079510758f, -0.04688882f, -0.11125523f }, { 0.01700754f, -0.0034361033f, 0.055252382f, -0.053119426f }, { -0.0014957087f, -0.00063057103f, 0.037930463f, 0.017656646f }, { -0.017388477f, -0.084085888f, -0.067726647f, 0.061397079f }, { -0.070625168f, -0.061293011f, -0.077366932f, 0.11518646f }, { -0.14771316f, -0.12543895f, 0.052150789f, 0.10530462f }, { -0.03609139f, 0.001131616f, -0.039549928f, 0.03805765f }, { 0.064364205f, 0.066758929f, 0.045537002f, -0.05510954f }, { 0.049051369f, 0.098312455f, -0.01079726f, -0.11202623f }, { 0.033012208f, -0.0013996988f, -0.0049458824f, -0.028981527f }, { 0.008617177f, -0.00017670863f, -0.0052380282f, -0.0023438457f }, { -0.05901498f, -0.050754807f, -0.00011829844f, 0.037297411f }, { -0.056264446f, -0.03645315f, -0.066412698f, 0.019549244f }, { -0.11401603f, -0.11856524f, 0.12275022f, 0.11635143f }, { -0.0011999881f, -0.0016334327f, -0.0056868938f, 0.013393766f }, { 0.054526972f, 0.033632235f, 0.062591094f, -0.0025531074f }, { 0.073041316f, 0.073735243f, -0.06935254f, -0.11214186f }, { 0.034872822f, -0.015473423f, 0.037359975f, -0.026829465f }, { -0.015137592f, -0.0064462553f, 0.011771178f, 0.0025042048f }, { -0.038708904f, -0.033968131f, -0.044070885f, 0.024422773f } }, { { -0.047895007f, -0.016535938f, 0.04855533f, 0.018341613f }, { 0.004310087f, 0.01519838f, -0.0033290683f, -0.013597406f }, { 0.0015859181f, 0.016869623f, -0.019279963f, -0.01426933f }, { -0.0061048976f, 0.031131561f, 0.018085381f, -0.017927117f }, { 0.052590378f, 0.0066156852f, -0.0025756141f, -0.037241705f }, { 0.0083512619f, 0.0046235666f, 0.024122126f, -0.013443654f }, { 0.0010672274f, 0.00053123301f, -0.0016276029f, -0.04221993f }, { -0.0048754166f, -0.021474788f, -0.0039993317f, 0.011831691f }, { -0.054685347f, -0.050242732f, -0.007606251f, 0.043061893f }, { -7.5644942e-05f, 0.00086632318f, 0.0001960729f, 0.0013264286f }, { 0.0042413724f, -0.0057181522f, 0.0065940983f, -0.0078263328f }, { 0.0031260881f, -0.0013520907f, 0.025073658f, -0.010841673f }, { 0.038353769f, 0.06620308f, -0.0072105562f, -0.079188681f }, { 0.003099559f, -0.0022927921f, 0.021982683f, -0.018991144f }, { 0.012285675f, 0.0091834074f, -0.0041874571f, -0.032253924f }, { -0.014563556f, 0.009843969f, -0.010490279f, 0.012979866f }, { -0.005492286f, 0.064109426f, -0.034795617f, -0.020395732f }, { -0.023364141f, -0.059336321f, 0.080710391f, 0.038948527f }, { 0.0028384819f, 0.001822471f, 0.0012903958f, 0.012781079f }, { -0.004510518f, -0.0020008272f, 0.0017752876f, 0.0077607089f }, { 0.032279653f, 0.0041906079f, -0.034682371f, 0.0061335907f }, { -0.0082992317f, -0.025250117f, -0.017026845f, -0.028345042f }, { -0.013132125f, -0.026688493f, -0.0014827793f, -0.003236826f }, { 0.01650781f, 0.002313574f, -0.012897922f, 0.026077933f } }, { { 0.062668058f, 0.0081578851f, 0.018952049f, -0.012267283f }, { 0.0008567722f, 0.0033246009f, -0.0037620102f, -0.0096317368f }, { -0.0083012273f, 0.01184624f, -0.01209373f, 0.020208536f }, { 0.013862003f, 0.019166381f, 0.013235471f, -0.026788736f }, { -0.021904217f, -0.051018749f, 0.0020330268f, 0.006626371f }, { -0.015856131f, 0.0028024655f, -0.032825412f, -0.018920906f }, { 0.0020870233f, 0.0011616727f, -0.0032704368f, -0.027327141f }, { 0.01934969f, 0.002427195f, 0.049925128f, -0.0061414889f }, { 0.013158375f, 0.022248445f, 0.040266734f, -0.017583455f }, { 1.9024812e-05f, 0.00071602053f, 0.0012622199f, 0.0018791611f }, { -0.0011857767f, 0.0023417924f, 0.026237548f, -0.014687892f }, { -0.041419782f, 0.024942194f, -0.029143101f, 0.036590943f }, { -0.015470651f, -0.035208671f, -0.038530514f, 0.037434376f }, { -0.0029356279f, 0.0023358079f, 0.017641055f, 0.0038203652f }, { -0.0030449623f, -0.010187444f, 0.0066142145f, 0.0037433206f }, { 0.0080034603f, 0.011463159f, -0.0058129532f, 0.011831147f }, { -0.0091743137f, 0.045949289f, 0.022412137f, -0.0067531419f }, { 0.00069946656f, -0.0068974782f, 0.0091806954f, 0.0022160793f }, { -0.0027530077f, 0.00089797627f, 0.0066153093f, -0.010355635f }, { -0.019399018f, -0.0085762573f, 0.0208003f, -0.027739023f }, { -0.014354809f, -0.011971089f, -0.0031124986f, 0.044710091f }, { -0.011411144f, 0.0073253411f, -0.0087561348f, -0.014838738f }, { 0.018837992f, 0.00231775f, -0.013982978f, -0.0020044658f }, { 0.0012069362f, 0.0012202952f, 0.029106153f, 0.00062793994f } } }, { { { 0.054154158f, -0.11603661f, -0.025631275f, 0.054671866f }, { -0.2359715f, 0.093194255f, 0.21874866f, -0.08378526f }, { 0.0089903397f, 0.0087113885f, -0.015445726f, 0.011142042f }, { -0.0055372249f, -0.0041494086f, -0.033355186f, -0.010136823f }, { -0.015010227f, -0.0077144008f, 0.13058394f, -0.016779666f }, { -0.015855009f, 0.014090685f, 0.026549575f, 0.025677527f }, { -0.00065423811f, -0.0011506403f, 0.028628751f, 0.0086359197f }, { -0.010571292f, 0.035861454f, -0.025871285f, -0.024827688f }, { 0.00010603924f, 0.011433504f, -0.052819957f, -0.020208661f }, { 0.12243361f, -0.14574398f, -0.10091072f, 0.054524772f }, { -0.014659734f, -0.02291001f, 0.010102434f, -0.0099333349f }, { -0.0079939087f, 0.023468399f, 0.044548395f, 0.04568814f }, { -0.048188816f, 0.016469102f, 0.084818672f, -0.040634065f }, { 0.015089138f, 0.025396216f, 0.017000121f, 0.010820807f }, { -0.0098155552f, -0.00080001495f, 0.0020122754f, -0.00046896909f }, { -0.0018906417f, -0.03909342f, -0.020339049f, -0.024007559f }, { -0.0012744487f, -0.027829333f, -0.05202457f, -0.024366779f }, { 0.10406956f, -0.092281421f, -0.050420166f, 0.10716663f }, { -0.0049603976f, -0.0055370076f, -0.0016910106f, 0.012172389f }, { -0.0026486448f, 0.038673757f, -0.0016176887f, 0.052692494f }, { -0.03722357f, 0.055455783f, 0.067738953f, -0.0087990582f }, { -0.0026491637f, 0.017275247f, 0.010687117f, 0.020312052f }, { -0.0016032469f, 0.0090272843f, -0.0079027514f, -0.0050039898f }, { -0.0073653412f, -0.033150577f, 0.0082912493f, -0.021457881f } }, { { -0.0059001999f, 0.033600833f, 0.066374213f, -0.018058548f }, { -0.0037864945f, -0.0064946131f, 0.0018627774f, 0.0044899139f }, { 0.0048961861f, -0.0034770968f, -0.0002311598f, -0.0053935761f }, { 0.0090090757f, 0.012149811f, 0.0029969663f, 0.0049403543f }, { -0.042874682f, -0.0083455851f, -0.0064437344f, 0.0010579362f }, { 0.011866873f, -0.017157526f, -0.014724976f, 0.0054373752f }, { -0.0006329516f, -0.00024834697f, 0.0015416168f, -0.014246989f }, { 0.031530357f, -0.052715858f, -0.0063186617f, -0.0070200141f }, { -0.0082273844f, 0.053856605f, 0.0096812384f, 0.01684635f }, { -0.00017150577f, 0.00097354737f, 0.0013944706f, 0.00085166684f }, { -0.013604545f, 0.0089329355f, -0.013809086f, 0.0025044469f }, { -0.020284731f, 0.0004724419f, -0.045697697f, -0.01844702f }, { 0.017874081f, -0.0040537465f, -0.023316716f, -0.026344708f }, { 0.0092557469f, -0.014456327f, -0.0092919835f, 0.0091758924f }, { 0.016058873f, 0.0019220807f, 0.0031692823f, 0.0024577167f }, { -0.021184352f, 0.021287579f, -0.0048442696f, 0.0095799112f }, { 0.035229915f, -0.054291919f, -0.013871324f, 0.035585241f }, { 0.001275203f, 0.011513119f, 0.020184769f, -0.0061701639f }, { 0.011353237f, 0.0052697685f, 0.0047637419f, -0.020278005f }, { 0.0068266296f, -0.01173749f, 0.037482577f, -0.0083236299f }, { 0.025699221f, -0.03651135f, -0.032342446f, -0.0059784486f }, { 0.0029540635f, -0.0021598269f, 0.0028168477f, 0.0044577193f }, { 0.0038274002f, -0.0050806333f, 0.007628551f, 0.0027461742f }, { 0.0056567464f, 0.006846664f, -0.031161558f, -0.0040832656f } }, { { 0.025668431f, 0.0093723617f, 7.4324163e-05f, -0.023051436f }, { -0.010148124f, 0.0018159908f, 0.0072269566f, 0.00082671261f }, { 0.0069741056f, 0.023493533f, 0.028507618f, -0.026874125f }, { 0.0083316277f, -0.024891629f, 0.013623217f, 0.0038373532f }, { -0.020992516f, 0.070912136f, -0.0014634877f, -0.015680371f }, { 0.02178962f, -0.003772636f, -0.024578501f, -0.047467019f }, { 0.0028586275f, 0.0033445767f, 0.0049576063f, -0.017365739f }, { 0.0075721122f, 0.010652219f, -0.024031886f, -0.0001146548f }, { 0.016381176f, -0.044765924f, -0.038036229f, -0.014041395f }, { -0.00082564842f, 0.00033107944f, 0.00073792054f, 0.0005712734f }, { 0.0080934887f, 0.014534447f, -0.0071347609f, 0.0085413493f }, { -0.018211778f, 0.0064443848f, 0.017393403f, 0.011490985f }, { -0.071531366f, 0.030059694f, 0.049103287f, 0.0074609412f }, { 0.00770209f, -0.017999995f, -0.040048679f, -0.0029073853f }, { 0.020442166f, 0.0019454488f, -0.019644905f, 0.021793285f }, { 0.035171271f, 0.0080192155f, -0.023151504f, 0.014168348f }, { -0.048901887f, -0.0039613606f, 0.0021703807f, 0.030275152f }, { 0.044666116f, -0.029756153f, -0.015570779f, 0.034470632f }, { -0.0078700362f, 0.0037551741f, 0.0003070052f, -0.0031237403f }, { 0.015288427f, -0.01284757f, -0.0075319169f, 0.026981487f }, { -0.0093872483f, 0.013517073f, -0.030221944f, 0.058356065f }, { 0.0042326205f, -0.016381154f, 0.021475001f, 0.01008732f }, { 0.0034929117f, 0.020531314f, -0.0085114063f, 0.004821913f }, { 0.014314413f, 0.01127037f, -0.017197896f, 0.0046932185f } } }, { { { 0.99591552f, 0.99230689f, 0.99873374f, 0.99387895f }, { 0.96356049f, 0.96556546f, 0.96964041f, 0.96677566f }, { 0.99945097f, 0.99930521f, 0.99977525f, 0.99975808f }, { 0.99900933f, 0.99996161f, 0.99848418f, 0.99879675f }, { 0.99545951f, 0.99993863f, 0.99032786f, 0.9936502f }, { 0.99972964f, 0.99989482f, 0.99811938f, 0.99825798f }, { 0.99999867f, 0.99999914f, 0.9988702f, 0.99980681f }, { 0.99979292f, 0.99581299f, 0.99736843f, 0.99780458f }, { 0.99750292f, 0.99805433f, 0.99560254f, 0.9931383f }, { 0.98142286f, 0.98133774f, 0.99352772f, 0.9929441f }, { 0.99924096f, 0.99973689f, 0.99916652f, 0.99922617f }, { 0.99789446f, 0.9974931f, 0.99796885f, 0.99743448f }, { 0.9976331f, 0.99501931f, 0.9963379f, 0.99287411f }, { 0.99934104f, 0.99967648f, 0.99984325f, 0.99952138f }, { 0.9999147f, 0.99999966f, 0.99998426f, 0.99999714f }, { 0.99825531f, 0.99794572f, 0.99979313f, 0.99901579f }, { 0.99841509f, 0.99894779f, 0.99643504f, 0.99951192f }, { 0.98801309f, 0.98864879f, 0.99115599f, 0.98740957f }, { 0.99998698f, 0.99998334f, 0.9999824f, 0.99983621f }, { 0.99850879f, 0.99868574f, 0.99803794f, 0.99860752f }, { 0.99663402f, 0.99573479f, 0.99528974f, 0.99365325f }, { 0.99938825f, 0.99973103f, 0.99924472f, 0.99943364f }, { 0.99988413f, 0.99993848f, 0.99989949f, 0.99998434f }, { 0.99922338f, 0.99887297f, 0.998994f, 0.9994714f } }, { { -0.0050599833f, 0.003362263f, 0.0035202243f, -0.00056864904f }, { -0.0014675187f, -0.0029154981f, -0.00077796172f, -0.0027392627f }, { -0.0010916411f, 0.00078232803f, 0.0014339533f, -0.0020166729f }, { 0.011183745f, 0.008298699f, 0.011631254f, 0.00030693508f }, { -0.0012964861f, -0.00028098882f, 0.00098513135f, -0.0052243577f }, { 0.0091119501f, 0.002780703f, 0.011045274f, 0.00334383f }, { 4.1103001e-05f, 5.5767744e-05f, 0.0030605577f, 0.0022152241f }, { 0.00085375099f, 0.0026952672f, 0.0071937971f, 0.0056504112f }, { -0.003773118f, 0.0047936307f, -4.5743022e-05f, -0.0038357994f }, { 2.3815581e-05f, 0.0002468657f, 0.00013492048f, -0.00018410816f }, { 0.0070959632f, -0.00205589f, 0.0056417297f, 0.0030702073f }, { 0.010671769f, 0.0074346008f, 0.0012867659f, 0.0075437523f }, { -0.0013037272f, -0.0058374269f, 0.0025899757f, -0.0071565118f }, { 0.0030041304f, 0.0018011397f, 0.0093160386f, 0.0082062863f }, { 0.0053156934f, 0.0036543193f, 0.0048724246f, 0.0035118324f }, { -0.0053866158f, 0.0024053442f, 0.00052459148f, 0.0090970513f }, { 0.011239324f, -0.0010327051f, -0.00097551594f, 0.0044180668f }, { -0.0024379533f, -0.0088232426f, -0.012355568f, -0.0031875953f }, { 0.0026244123f, 0.0011858999f, 0.0028110843f, -0.001005442f }, { 0.0059514328f, 0.0018892606f, 0.0050231625f, 0.0046700575f }, { 0.00050741664f, 0.0096547476f, -0.00079618251f, 0.0024532112f }, { 0.0058717468f, -0.0017457656f, 0.0080261577f, -0.00048009588f }, { 0.0025457914f, 0.0016788968f, 0.0013982313f, 0.00073909928f }, { 0.0075035778f, 0.011234409f, 0.0079271096f, 0.006672353f } }, { { 0.0095152396f, 0.0011785006f, -0.00081996856f, 0.0018904938f }, { -0.0025430397f, -0.0010236291f, -0.0020168276f, -0.0021827861f }, { 0.0036295778f, 0.005406882f, 0.0040788276f, -0.0057729163f }, { -0.00029952998f, 0.0024548208f, 0.0088548836f, 0.0019084209f }, { 0.0034184324f, -0.0088925589f, 0.00023040452f, 0.00017437939f }, { 0.0037804595f, 0.012156355f, 0.0041276361f, 0.012721488f }, { 7.4846461e-05f, 0.00010580108f, 0.013483417f, 0.0024239851f }, { 0.00026411032f, -0.00059353627f, 0.0093564271f, 0.0061507538f }, { 0.0016065383f, -0.0027764641f, 0.0013620195f, 0.0010062065f }, { 9.7127925e-05f, 0.00017275393f, 1.0814607e-05f, -0.00022627793f }, { 0.0048710612f, -0.00014794569f, 0.0082832436f, -0.00072595412f }, { -0.0027392579f, 0.0066783951f, 0.00087397132f, 0.001567366f }, { -0.003378151f, 0.0025916338f, -0.0025553201f, 0.0030152022f }, { 0.0096818399f, 0.0012695523f, 0.0072489949f, 0.016881099f }, { 0.0022796191f, 0.0051693266f, 0.0023373397f, -0.0041448561f }, { -0.0002074582f, 0.0035962454f, -0.0007460719f, 0.0025086317f }, { 0.0035784996f, 0.003162753f, 0.0022592918f, 0.00024595998f }, { -0.0051294944f, -0.0041428868f, -0.0027597f, -0.0039539398f }, { 0.0022410392f, 0.00031263884f, 0.0016376751f, -0.0022787113f }, { 0.0025647038f, 0.0074733037f, 0.0051722028f, 0.0024463612f }, { 0.0011787227f, 0.0071159753f, 0.0017217143f, 0.0062717989f }, { 0.0046836737f, 0.0038976423f, 0.00062832002f, 0.0027638154f }, { 0.0014142926f, 0.0024903802f, 0.0015757227f, 0.0011628587f }, { 0.0016928585f, 0.0043828548f, 0.001653268f, 0.011450696f } } }, { { { 2.8886078f, 2.8900127f, 2.7925705f, 2.7895874f }, { 4.5455217f, 4.5284714f, 4.7042338f, 4.6915273f }, { 0.96672505f, 0.99303664f, 0.98927606f, 1.0351588f }, { 1.2743756f, 1.2525364f, 0.99649566f, 0.94572778f }, { 2.6910679f, 2.6922168f, 2.8503404f, 2.8246076f }, { 1.256075f, 1.2325025f, 1.5911826f, 1.6091223f }, { 1.3601759f, 1.3606869f, 1.2793533f, 1.240925f }, { 2.0291828f, 2.0506809f, 1.7341658f, 1.6555689f }, { 2.6663531f, 2.6921882f, 3.1290975f, 3.11849f }, { 5.3676887f, 5.3663279f, 5.3848664f, 5.3852162f }, { 1.0586431f, 1.0865889f, 0.8196623f, 0.8076665f }, { 1.6967251f, 1.7305944f, 1.5450413f, 1.6347879f }, { 3.0908857f, 3.0706775f, 3.2974343f, 3.3053965f }, { 1.2172073f, 1.3839086f, 1.5086796f, 1.4295506f }, { 0.97676668f, 1.0856738f, 0.98747912f, 1.0385491f }, { 1.5662275f, 1.4603538f, 1.784278f, 1.6575438f }, { 2.1085757f, 2.2092885f, 2.1410448f, 2.1518347f }, { 4.0214776f, 4.006424f, 3.7686967f, 3.7771354f }, { 1.2089239f, 1.2116036f, 1.1244311f, 1.0901017f }, { 1.1827246f, 1.1472796f, 1.7516784f, 1.7833976f }, { 2.2113439f, 2.197512f, 2.2692963f, 2.2787751f }, { 0.98819531f, 1.057833f, 1.3587301f, 1.3890421f }, { 1.208957f, 1.2247867f, 1.2301205f, 1.2325178f }, { 1.0499613f, 1.1319197f, 1.4067885f, 1.3209087f } }, { { -0.002860931f, -0.0033581281f, -0.0047612075f, -0.0030481839f }, { -0.0017370907f, -0.0065700936f, -0.0011051926f, -0.0046915938f }, { -0.0006126207f, 0.0010791181f, -0.022876686f, -0.015937275f }, { -0.010040922f, -0.016433531f, -0.0044976975f, -0.029838315f }, { 0.00056888968f, -0.0093450028f, -0.00041549218f, -0.0069079656f }, { -0.029781683f, -0.019722587f, 0.019472312f, 0.0016798037f }, { -0.0015128736f, -0.0012250172f, -0.0091568262f, -0.0091368119f }, { 0.0010846814f, 0.0017189068f, 0.012975603f, -0.0051530971f }, { -0.026042808f, -0.0090684857f, -0.0021498742f, -0.0032938309f }, { -0.0012792901f, -0.0010431731f, -0.0021366737f, -0.0025526365f }, { -0.03218779f, -0.013848893f, -0.021872476f, -0.029443623f }, { 0.008300061f, 0.011951182f, -0.011139414f, 0.0098292843f }, { -0.0065854884f, -0.020955083f, -9.3843515e-05f, -0.0078425688f }, { -0.054726229f, -0.0073673428f, -0.019267231f, -0.03383648f }, { -0.049769726f, 0.0065482059f, -0.010189395f, -0.0050480393f }, { 0.022565943f, -0.020311569f, 0.0091512717f, -0.015600752f }, { -0.014418429f, 0.0060070592f, -0.0055296743f, -0.003361885f }, { 8.8146509e-05f, -0.0082609252f, 0.0036746024f, 0.0040108321f }, { 0.0010230427f, 4.8153189e-06f, 0.0052893378f, -0.0096303521f }, { 0.0032909351f, -0.010982824f, 0.003880027f, 0.0097699095f }, { -0.006528317f, -0.012608887f, -0.0057088008f, -0.003867806f }, { -0.046599771f, -0.024701737f, -0.001078321f, -0.0041018649f }, { -0.021680777f, -0.021120711f, 0.0055144734f, -0.0031337995f }, { -0.030559213f, 0.0089872726f, -0.011166202f, -0.0077587071f } }, { { -0.0059548858f, -0.0040070313f, -0.0062572119f, -0.0047711065f }, { -0.0031938803f, -0.005431389f, -0.0026376521f, -0.0046119366f }, { 0.0064917253f, 0.013030824f, -0.027850471f, -0.011824849f }, { -0.032644485f, -0.025045016f, -0.0034396539f, -0.039827623f }, { -0.007691681f, -0.014095643f, -0.0008171964f, -0.0051336386f }, { -0.035626586f, -0.021424668f, 0.00035790929f, 0.0099705685f }, { -0.0019006762f, -0.0014887089f, -0.0050782898f, -0.0096835564f }, { -0.00087496879f, 0.0052586834f, 0.017041675f, -0.00046753956f }, { -0.022489507f, -0.0084834888f, 0.0017184219f, -0.0023910992f }, { -0.0010618265f, -0.00085888729f, -0.0020035777f, -0.0024245283f }, { -0.029245834f, -0.038977066f, -0.013385246f, -0.030312138f }, { -0.0028497869f, 0.014205986f, -0.0125692f, 0.0037959624f }, { -0.0086377959f, -0.019175965f, -0.007684309f, -0.005037677f }, { -0.063945685f, -0.0060751259f, -0.0057457302f, -0.019079575f }, { -0.043745147f, 0.013651906f, -0.034067394f, 0.0012111497f }, { 0.0086647574f, -0.019171418f, 0.020745219f, -0.0055629951f }, { -0.024541273f, 0.0072112135f, -0.0078821942f, -0.0085072621f }, { -0.0018227939f, -0.0021153099f, 0.008577002f, 0.0043865151f }, { -0.013984752f, -0.012209334f, 0.00023638151f, -0.0085025952f }, { -0.0099800075f, -0.0095390578f, 0.0081328135f, 0.012673433f }, { -0.0099975551f, -0.0028467616f, -0.010712056f, -0.0045012212f }, { -0.011329139f, -0.0084709831f, -0.0070232966f, 0.0015504012f }, { -0.015334801f, -0.0075637633f, -0.01107439f, -0.0094188163f }, { -0.017505269f, -0.00013701888f, -0.033955823f, -0.034192649f } } }, { { { 0.16413327f, 0.084074422f, 0.10646123f, 0.18806073f }, { 0.039511019f, 0.058967072f, 0.035166958f, 0.052296507f }, { 0.26970995f, 0.21576211f, 0.2954278f, 0.29870678f }, { 0.40442043f, 0.38744132f, 0.14502571f, 0.24076804f }, { 0.22655046f, 0.20912486f, 0.015295019f, 0.16442957f }, { 0.69235319f, 0.6080183f, 0.36756076f, 0.23314717f }, { 0.085565328f, 0.075535626f, 0.22162979f, 0.33140596f }, { 0.16109547f, 0.11961895f, 0.26619212f, 0.25941009f }, { 0.27077686f, 0.23481238f, 0.063446408f, 0.11614487f }, { 0.026116057f, 0.027491327f, 0.030421883f, 0.039965345f }, { 0.33922592f, 0.38039792f, 0.27167385f, 0.31510976f }, { 0.32744968f, 0.22567102f, 0.23116584f, 0.18867836f }, { 0.29783431f, 0.28054079f, 0.26752139f, 0.23889932f }, { 0.61721263f, 0.60602797f, 0.51283622f, 0.47601102f }, { 0.51383952f, 0.53111455f, 0.44519064f, 0.42875877f }, { 0.3485879f, 0.35374178f, 0.53292055f, 0.53995494f }, { 0.4366997f, 0.35554257f, 0.14878367f, 0.22083288f }, { 0.12855375f, 0.16718264f, 0.17583661f, 0.11125895f }, { 0.35898096f, 0.37222307f, 0.35439108f, 0.35956111f }, { 0.16773044f, 0.25668894f, 0.23246756f, 0.1506316f }, { 0.36172813f, 0.26938211f, 0.20069185f, 0.1714591f }, { 0.3998571f, 0.23607244f, 0.34121623f, 0.29126696f }, { 0.31471307f, 0.29500525f, 0.39451396f, 0.40013999f }, { 0.29554399f, 0.28083636f, 0.47190649f, 0.47892938f } }, { { 0.01419653f, -0.061214452f, -0.032506906f, 0.0078227125f }, { -0.015799432f, 0.0136148f, -0.0090824684f, 0.013638505f }, { 0.023848919f, 0.022034707f, 0.022812846f, 0.022790329f }, { -0.0026324255f, -0.0053566952f, 0.00027470228f, 0.050203583f }, { 0.0035659857f, -0.02015272f, -0.039043616f, 0.054511651f }, { 0.0052075445f, 0.0051043119f, -0.011801097f, -0.0074336577f }, { 0.020735195f, 0.01811747f, 0.00808952f, 0.01140964f }, { -0.0073139049f, 0.011075347f, 0.0057685988f, 0.010251582f }, { 0.024813488f, -0.01629986f, -0.012536791f, -0.01110061f }, { -0.014508648f, -0.021444084f, -0.023836972f, -0.014258253f }, { 0.0079687141f, -0.00092011446f, 0.060249601f, 0.033199468f }, { -0.020822483f, -0.013924875f, -0.005068391f, -0.016928794f }, { -0.030059f, -0.013887475f, -0.045329289f, -0.04449219f }, { 0.007264541f, 0.0015213919f, -0.0066322618f, -0.0036449174f }, { 0.0057175046f, 0.0012159867f, -0.00054271896f, 0.0020625484f }, { 0.0027083179f, -0.0012554897f, -0.0044854592f, -0.0045242423f }, { -0.017906563f, -0.028301884f, -0.010139427f, 0.0035851304f }, { -0.020245794f, 0.01149232f, 0.011320484f, -0.013561794f }, { 0.0068048997f, 0.011957759f, 0.0046962412f, -0.0015476541f }, { -0.0022514613f, 0.019996868f, 0.0051520398f, -0.023405604f }, { 0.0055213198f, 0.0070384134f, 0.024405643f, -0.02050399f }, { 0.039987541f, 0.021127504f, -0.012323503f, -0.0041538161f }, { 0.0072321478f, 0.0053097351f, 0.0039966161f, 0.013617175f }, { 0.030470642f, 0.0044694115f, -0.0024591651f, -0.0027274707f } }, { { -0.040500402f, -0.039657034f, -0.017497359f, -0.017857145f }, { -0.0015646885f, -0.020957371f, -0.0057356498f, -0.0060587007f }, { 0.0070388709f, -0.013205178f, -0.00033412934f, 0.02192306f }, { -0.0042317723f, 0.020620857f, -0.012309167f, 0.065948811f }, { -0.016686589f, 0.013616667f, 0.030139062f, -0.019023551f }, { 0.015181564f, 0.008673659f, -0.0014559576f, -0.025916054f }, { 0.031630671f, 0.027030197f, -0.026982415f, 0.025214731f }, { -0.003845127f, -0.00062884599f, -0.029488655f, -0.0051457939f }, { -0.0032476351f, 0.0021153707f, -0.033110808f, -0.033629213f }, { -0.0064637077f, -0.010805748f, -0.014982403f, -0.0084641529f }, { 0.0087766042f, 0.017780238f, 0.026838871f, 0.032580257f }, { 0.0010700985f, -0.037414784f, -0.0053773565f, 0.0040969752f }, { -0.02637392f, -0.050236074f, -0.048422986f, -0.069357813f }, { -0.0089483588f, 0.0026259727f, 0.0040142797f, -0.010752754f }, { -0.0025658872f, 0.0071106029f, 0.015467367f, 0.0012536589f }, { -0.0037247444f, -0.0036991733f, -0.015429566f, -0.016148852f }, { -0.024788221f, -0.045938054f, -0.028679471f, 0.011593494f }, { -0.032699114f, -0.036800967f, -0.033870575f, -0.031842203f }, { 0.018156047f, 0.02457546f, 0.0209432f, 0.015057433f }, { 0.0043152638f, 0.025831372f, -0.019608349f, -0.026614397f }, { -0.0057047815f, -0.013831909f, 0.027613211f, -0.043616864f }, { 0.014124478f, -0.010786326f, 0.010775415f, -0.023241344f }, { 0.018337827f, 0.0048735321f, 0.018371717f, 0.022106807f }, { 0.013619207f, 0.022051384f, 0.0082720974f, -0.0030262071f } } } }, { { { { 0.083322661f, 0.079807165f, 0.03660117f, -0.051657142f }, { -0.099216074f, -0.0080141573f, 0.10637241f, 0.0367403f }, { 0.20813681f, -0.0001361621f, -0.20762563f, -0.085913357f }, { -0.22091149f, 0.10003156f, -0.16122219f, 0.31542901f }, { 0.16226908f, 0.02665194f, -0.012123307f, -0.16559939f }, { -0.14025496f, 0.025804505f, 0.076174345f, 0.20548591f }, { 0.0035713609f, -0.0092551928f, -0.099937652f, 0.0038879391f }, { 0.12405732f, -0.0053373497f, -0.030865175f, -0.060934551f }, { -0.0060175826f, -0.026583926f, -0.075326797f, -0.0063155886f }, { 0.036389362f, 0.054175433f, 0.06490927f, -0.038784258f }, { 0.30604876f, -0.030813476f, 0.011402956f, -0.21074796f }, { -0.31769497f, 0.046793931f, -0.038212559f, 0.21137297f }, { 0.12952945f, 0.20720126f, 0.08525845f, -0.14568109f }, { -0.09735197f, -0.17799099f, -0.12256082f, 0.038889119f }, { 0.002114572f, 0.026037779f, -0.0036772795f, 0.13478173f }, { 0.094577863f, 0.0057382415f, -0.087017736f, -0.059444148f }, { 0.054953104f, 0.071323301f, 0.097417831f, 8.3254475e-05f }, { -0.11005534f, 0.027214076f, 0.0059378205f, 0.02443999f }, { 0.27096654f, 0.1864966f, 0.034810947f, -0.25886676f }, { -0.35626794f, 0.037256657f, -0.17795321f, 0.52988269f }, { 0.14913899f, -0.0086988732f, -0.028760192f, -0.21779266f }, { -0.16010301f, -0.17699785f, 0.017269826f, 0.17878541f }, { -0.0049504093f, -0.02387924f, -0.04034852f, -0.060461173f }, { 0.10405347f, 0.0072745723f, -0.10244372f, -0.072981984f } }, { { 0.019363393f, 5.327311e-05f, 0.0075925373f, 0.0019542034f }, { -0.051707557f, 0.06554253f, 0.0050626046f, -0.0061857803f }, { 0.022891698f, 0.014872273f, -0.020436928f, 0.0069081531f }, { -0.044566611f, 0.019854557f, 0.023600607f, -0.0055387351f }, { 0.02283957f, -0.067086756f, 0.088865856f, -0.033915007f }, { 0.0020254431f, -0.16422426f, 0.032495902f, 0.012460808f }, { -0.017316175f, 0.023440087f, 0.011459595f, 0.0043887872f }, { 0.027714908f, -0.06907548f, 0.013578806f, -0.009848884f }, { 0.0044782488f, 0.0079432606f, 0.010143137f, 0.023589488f }, { 0.014325082f, 0.0075465848f, -0.0079373813f, -0.0056032635f }, { 0.025123579f, 0.01904807f, -0.0092328848f, -0.019002052f }, { -0.02633985f, -0.019560519f, -0.065544737f, 0.0073352606f }, { 0.044308433f, -0.0032233834f, 0.01324206f, -0.00047128106f }, { -0.076577611f, -0.021853603f, -0.020190543f, 0.0026420865f }, { -0.0029799448f, -0.0083566545f, 0.14896601f, 0.0078617095f }, { 0.021033237f, -0.08234711f, -0.020642328f, -0.0089829962f }, { 0.043793881f, 0.0096494147f, 0.035831274f, -0.01294602f }, { -0.014064874f, 0.066144489f, 0.0143429f, 0.015113964f }, { 0.043111732f, 0.0029232804f, -0.016912145f, 0.012142059f }, { 0.0014186333f, -0.0078590166f, 0.065781153f, -0.038375123f }, { 0.02255714f, -0.030191796f, -0.078373164f, -0.0017593196f }, { -0.033878798f, 0.016266579f, 0.013539653f, 0.043519216f }, { 0.019046482f, 0.0080403173f, -0.0010755939f, 0.03305222f }, { 0.023206448f, -0.054323067f, -0.035173093f, -0.010873592f } }, { { 0.014068291f, -0.026418786f, 0.016375695f, 0.0048801469f }, { 0.024404214f, 0.0073572002f, -0.027247654f, 0.00093849398f }, { 0.012741523f, -0.012913063f, 0.0054881373f, -0.021780769f }, { -0.020497215f, 0.057437717f, 0.0031122704f, 0.014713732f }, { 0.012765254f, -0.052846334f, 0.048042201f, 0.0016578534f }, { 0.031245254f, -0.0469321f, -0.057199738f, 0.012436479f }, { -0.0022837759f, 0.0068501747f, 0.010541107f, -0.0005227683f }, { -0.0187059f, 0.0025631581f, -0.0082184266f, 0.0026294483f }, { 0.0053899388f, -0.0199458f, 0.0023448066f, 0.016215236f }, { 0.021117204f, 0.010868775f, -0.016412681f, -0.016399297f }, { -0.0026199223f, -0.011436548f, 0.0031355049f, 0.011933919f }, { 0.017940023f, 0.090292392f, -0.061029038f, 0.016388845f }, { 0.0074493061f, -0.045849358f, -0.082612855f, 0.025851315f }, { 0.061276666f, -0.024654813f, 0.035447334f, -0.025952766f }, { -0.0068267167f, -0.02207426f, 0.003724368f, 0.0070458116f }, { 0.021714649f, -0.017552721f, -0.037105408f, 0.024398534f }, { 0.0092901891f, -0.021559075f, 0.009034776f, -0.016574279f }, { -0.017218595f, -0.041930302f, 0.003369899f, 0.017959363f }, { -0.0022510875f, 0.028106616f, -0.042936548f, -0.041948028f }, { -0.017145551f, -0.032331654f, 0.021486923f, -0.020295391f }, { -0.023196465f, -0.088353584f, 0.010086154f, 0.018689553f }, { -0.024508386f, -0.00058959302f, -0.02867958f, 0.019018994f }, { 0.0088748911f, 0.012528454f, -0.016636351f, 0.0078166115f }, { 0.00066772723f, 0.001693912f, 0.032066885f, 0.016951148f } } }, { { { 0.015200105f, 0.071414961f, -0.020616434f, 0.0063982643f }, { -0.084578144f, -0.12318522f, -0.035470756f, 0.057833574f }, { 0.19487946f, 0.44043059f, 0.10981527f, -0.31907303f }, { -0.17774238f, -0.30460726f, -0.53133003f, 0.31186606f }, { -0.1172677f, 0.3183613f, 0.10375266f, -0.066515168f }, { 0.054176263f, -0.12382077f, -0.033807438f, 0.039809238f }, { -5.3634009e-05f, 0.004084452f, 0.005103199f, -0.060697866f }, { 0.06093199f, 0.060355274f, 0.049176467f, -0.060579228f }, { 0.054611799f, 9.0520863e-05f, -0.048891261f, -0.047609349f }, { -0.036428706f, 0.06336736f, 0.0020843807f, 0.033254378f }, { 0.26975732f, 0.51328693f, 0.29976157f, 0.049031141f }, { -0.28383516f, -0.48219276f, -0.27898799f, -0.033028759f }, { -0.078976834f, 0.14077934f, 0.098587186f, 0.051336328f }, { 0.076281206f, -0.074223398f, -0.053178835f, -0.099578331f }, { -0.056377095f, -0.00066113896f, -0.11597726f, 0.058805777f }, { -0.0027130032f, 0.12007881f, 0.0081935835f, -0.10415807f }, { -0.019349408f, 0.06206561f, -0.0079099126f, 0.079363093f }, { -0.059959607f, -0.0591041f, -0.047505451f, -0.0031496967f }, { -0.11419194f, 0.20904287f, 0.53960104f, 0.10467592f }, { -0.21312862f, -0.34770872f, -0.54593093f, 0.23230512f }, { -0.073229448f, 0.12913f, 0.27728133f, -0.050627706f }, { 0.082312471f, -0.24529296f, -0.12381516f, 0.05577292f }, { 0.03015389f, -0.0015805638f, 0.024306632f, -0.080697961f }, { 0.061367564f, 0.056058289f, 0.041197211f, -0.015551356f } }, { { -0.029269776f, -0.030251548f, 0.01352869f, 0.0084860712f }, { 0.053983187f, 0.047657625f, -0.026379004f, 0.022474039f }, { 0.011898439f, 0.045120742f, -0.024430477f, -0.081318878f }, { -0.0012641508f, -0.018495044f, -0.030127865f, -0.0088483264f }, { 0.040728292f, 0.010691761f, -0.023566342f, 0.028045232f }, { 0.014593998f, 0.0047006468f, -0.049032498f, -0.011446808f }, { 0.00045433705f, -0.0030610749f, -0.010359449f, -0.0026455857f }, { -0.0026794352f, -0.032142744f, 0.010153936f, -0.0034586152f }, { 0.0097198782f, 0.0051005644f, 0.03482872f, -0.0043676475f }, { -0.0012381415f, -0.025746274f, -0.0081178021f, 0.0041481596f }, { -0.01598781f, 0.0048815642f, 0.06313106f, -0.0062291669f }, { 0.072970618f, -0.041153529f, -0.007457013f, 0.059776924f }, { 0.0024768493f, 0.0093018711f, 0.024827984f, 0.043842172f }, { -0.012927661f, -0.023256709f, -0.0035951539f, -0.069710027f }, { 0.0064149713f, 0.0019783425f, 0.010135188f, 0.019449636f }, { -0.0071551675f, 0.015761815f, 0.0086309278f, 0.038854386f }, { 0.020978109f, -0.0056696814f, 0.0025526797f, -0.017352926f }, { -0.010711116f, -0.0097050903f, 0.0022304504f, -0.0039308489f }, { 0.036904234f, 0.025927127f, 0.028330671f, 0.051193417f }, { -0.00076391153f, -0.077528792f, -0.029763477f, 0.0033945843f }, { -0.01775202f, 0.034507636f, 0.065392848f, -0.017840909f }, { -0.019567742f, -0.019880035f, 0.055214211f, -0.02206159f }, { 0.01110111f, 0.0022938832f, -0.011417507f, 0.017692635f }, { 0.050208493f, -0.028178909f, 0.0065276591f, -0.0056267473f } }, { { 0.0065622702f, -0.0012303136f, -0.0081183663f, 0.00079383048f }, { 0.030775912f, 0.052260356f, -0.019758331f, -0.020044147f }, { 0.019016537f, -0.043070451f, 0.035298744f, -0.040592775f }, { 0.010468089f, 0.00057085185f, 0.0081761984f, 0.0033382478f }, { 0.047189462f, -0.052695409f, 0.021849623f, 0.033585939f }, { 0.0012065616f, -0.050287476f, -0.065085924f, -0.039012886f }, { -0.012294892f, 0.006839242f, 0.0051165438f, -2.0711078e-05f }, { -0.03292822f, 0.015299577f, 0.0029119931f, 0.0073040242f }, { -0.0086784873f, 0.0085910164f, -0.0059378411f, -0.010259049f }, { -0.014191355f, -0.011172486f, -0.01299927f, 0.015386671f }, { 0.040453224f, -0.041489173f, 0.015047889f, 0.064340197f }, { -0.020000046f, 0.058477092f, -0.0018150465f, 0.048536972f }, { -0.006105982f, 0.03437044f, 0.0087640339f, 0.032868283f }, { -0.027120362f, 0.016579996f, -0.01708524f, 0.011178424f }, { 0.030535528f, 0.0058718219f, -0.031240404f, 0.024241052f }, { 0.003729958f, -0.055735848f, -0.0055392842f, 0.03447519f }, { -0.04084502f, -0.01227488f, 0.0062970198f, -0.021996031f }, { 0.053671675f, -0.067787009f, 0.0053426012f, -0.0080796738f }, { -0.021911856f, 0.038395527f, -0.07713235f, 0.024805484f }, { -0.0034319194f, 0.0052741327f, 0.026402991f, 0.0012916612f }, { -0.033119652f, -0.0046506889f, 0.045613946f, -0.050230593f }, { -0.0054612035f, -0.033482221f, 0.084267507f, -0.0224334f }, { -0.0063348693f, -0.0074524817f, -0.0029629355f, 0.035493958f }, { -0.0073519185f, 0.045139911f, 0.0022901735f, -0.041385515f } } }, { { { 0.99640669f, 0.99424882f, 0.99911727f, 0.99864438f }, { 0.99146493f, 0.99235134f, 0.99369348f, 0.99764995f }, { 0.95848895f, 0.89778665f, 0.9720248f, 0.943828f }, { 0.95896077f, 0.9472107f, 0.83168251f, 0.89623886f }, { 0.97975356f, 0.94759472f, 0.99452924f, 0.98394744f }, { 0.98863213f, 0.99196902f, 0.99652121f, 0.97785007f }, { 0.99999362f, 0.99994883f, 0.99498061f, 0.99814861f }, { 0.99040248f, 0.99816269f, 0.99831309f, 0.99630173f }, { 0.99848953f, 0.99964658f, 0.9959596f, 0.99884607f }, { 0.9986735f, 0.99651874f, 0.99788899f, 0.99869411f }, { 0.91299789f, 0.85766372f, 0.953946f, 0.97631002f }, { 0.90471405f, 0.87481454f, 0.959534f, 0.97684726f }, { 0.9884254f, 0.96811612f, 0.9914694f, 0.98799879f }, { 0.99232241f, 0.98122887f, 0.99103524f, 0.99426948f }, { 0.99840731f, 0.99966074f, 0.99324506f, 0.98912879f }, { 0.99551377f, 0.99274778f, 0.99617307f, 0.9927827f }, { 0.99830144f, 0.99552039f, 0.99521214f, 0.99684577f }, { 0.99211525f, 0.9978808f, 0.99885333f, 0.99969634f }, { 0.95579147f, 0.95995838f, 0.84120087f, 0.96022443f }, { 0.90975235f, 0.9368621f, 0.81871367f, 0.8156339f }, { 0.98610091f, 0.99158952f, 0.96035822f, 0.97468107f }, { 0.98366238f, 0.9531543f, 0.99215501f, 0.98230604f }, { 0.99953301f, 0.9997136f, 0.99888998f, 0.99490315f }, { 0.99267663f, 0.998401f, 0.99388534f, 0.99721201f } }, { { -0.0021537732f, 0.010607958f, -0.0066166595f, -0.0027390442f }, { -0.0069401807f, 0.0053215201f, 0.0062121114f, 0.013403291f }, { -0.0035740125f, -0.021839368f, 0.00042431197f, -0.029478899f }, { -0.007886159f, -0.0087705321f, -0.010570968f, 0.0040635318f }, { -0.0021772698f, 0.00025306776f, -0.0092725896f, -0.0075657706f }, { -0.010438319f, -0.0072866821f, 0.009272756f, 0.0043932916f }, { -0.00058203184f, 0.0081284104f, 0.027749999f, 0.0035426599f }, { -0.003604276f, -0.012244348f, 0.0072177908f, 0.0026686264f }, { 0.011192179f, 0.0069527119f, 0.017278396f, -0.0053058312f }, { -0.020276487f, -0.0063228657f, 0.013968347f, -0.0021534789f }, { -0.0037534313f, 0.00061399133f, -0.02126817f, 0.0085256452f }, { 0.015620795f, -0.022637876f, 0.00069280338f, 0.0054369037f }, { 0.0095244184f, -0.0026896982f, -0.0057963534f, 0.0067237437f }, { -0.0085689961f, -0.004816024f, -0.00088793436f, -0.0034021999f }, { 0.015428153f, 0.019777562f, -0.011217833f, 0.0095744159f }, { -0.003802304f, 0.0022643577f, 0.0054254827f, 0.025560756f }, { -0.0053298651f, 0.021621993f, -0.01864184f, 0.019120967f }, { 0.015380344f, -0.0027384467f, 0.0010235928f, 0.0062792725f }, { -0.001166873f, -0.0049586656f, -0.014850883f, 0.00057841904f }, { 0.0032865456f, -0.033386196f, 0.0032068954f, 0.02854738f }, { 0.010308266f, -0.000233004f, -0.020287643f, 0.0044441043f }, { -0.0040523345f, 0.0050367711f, 0.01627907f, -0.010032412f }, { 0.0073463987f, 0.00073274858f, 0.002814661f, 0.030221018f }, { 0.0057509063f, -0.011441338f, 0.01894259f, 0.0077856453f } }, { { -0.0053054924f, 0.0037677068f, 0.0066263851f, 0.0011220287f }, { -0.02212139f, 0.013769097f, -0.0013834097f, 0.014152363f }, { -0.0008493126f, 0.021473024f, -0.0039313241f, -0.017764981f }, { -0.00081897848f, -0.0074161164f, 0.0038179092f, -0.0035760615f }, { 0.014045643f, 0.015317904f, 0.0045966739f, 0.0075917156f }, { 0.0035574126f, -0.00017773424f, -0.0010937491f, -0.0017762282f }, { 0.0072018344f, 0.012586227f, 0.0138702f, -0.0085424173f }, { -0.0055783456f, -0.019909385f, 0.01190919f, -0.0065821489f }, { 1.7402026e-05f, 0.0094513341f, 0.015333305f, -0.0072158969f }, { -0.0063049905f, 0.0021776758f, 0.014376378f, 0.0072426401f }, { -0.0078049673f, 0.028764242f, -0.0024169449f, 0.0077604105f }, { 0.00047536469f, 0.029806623f, 0.0017798261f, 0.00087410198f }, { -0.0030498401f, 0.0044874501f, 0.0020382571f, -0.0011101062f }, { -0.0057084397f, -0.0013428994f, -0.001024136f, 0.0066188614f }, { 0.039201052f, 0.015120258f, -0.0082642793f, 0.0051985023f }, { -0.0091203243f, 0.020790215f, 0.0025270937f, 0.020092044f }, { -0.0029830063f, 0.006602841f, -0.00833601f, 0.044852353f }, { 0.025206353f, -0.0038915173f, 0.00045914851f, 0.0037840538f }, { 0.0014814254f, -0.011573911f, 0.046232337f, -0.015228958f }, { -0.0071984443f, 0.0090004063f, 0.022942838f, 0.016019787f }, { 0.0050929336f, 0.0060892107f, -0.0061771339f, 0.0047850766f }, { -0.011634853f, 0.0010276548f, 0.022396644f, -0.0021248711f }, { -0.012943002f, 0.0016430074f, 0.02034928f, 0.024289705f }, { 0.0051047037f, 0.010052556f, 0.0020923265f, -0.019043181f } } }, { { { 2.1627647f, 2.1788232f, 1.9290264f, 1.8457806f }, { 2.526488f, 2.3020441f, 2.538915f, 2.03484f }, { 3.9987521f, 4.3952121f, 3.906821f, 4.1693278f }, { 4.0400466f, 4.1069844f, 5.2512999f, 5.4283264f }, { 3.0141968f, 3.3306035f, 3.2224806f, 3.2473051f }, { 2.9840674f, 3.1294685f, 3.2964833f, 3.2929246f }, { 1.8346741f, 1.8637353f, 2.3037966f, 2.0860888f }, { 2.691236f, 2.6068079f, 1.9349032f, 2.1632935f }, { 1.9231956f, 1.7251627f, 2.1609654f, 2.1155629f }, { 2.165771f, 2.1908952f, 1.777038f, 2.0223741f }, { 4.5166991f, 4.8674508f, 3.918546f, 3.378087f }, { 4.4502295f, 4.5429338f, 3.9552598f, 3.3580272f }, { 3.0973598f, 3.3953852f, 2.2704362f, 2.6488177f }, { 3.2110537f, 3.3104376f, 2.515002f, 2.3267785f }, { 1.8303675f, 1.7094345f, 3.1787979f, 2.5960104f }, { 2.4391795f, 2.8730077f, 2.3730261f, 2.1545299f }, { 2.2130903f, 2.1899209f, 2.4997355f, 1.9058674f }, { 2.6472893f, 2.5455636f, 2.1164596f, 1.8341163f }, { 3.9428283f, 4.0433678f, 4.5430063f, 4.2482776f }, { 4.1941673f, 4.28852f, 4.64044f, 4.6644567f }, { 3.0873642f, 2.649364f, 3.6026133f, 3.2426354f }, { 3.2415154f, 3.5406745f, 3.2976852f, 3.3100246f }, { 1.8400289f, 1.8404692f, 1.889289f, 2.0125184f }, { 2.7063995f, 2.7229173f, 2.6289878f, 2.4313709f } }, { { -0.015335928f, -0.043382119f, -0.0054163805f, -0.028249934f }, { -0.017200109f, 0.0027582413f, -0.079612821f, -0.0013966663f }, { -0.027233584f, -0.018783395f, -0.01183278f, -0.020918937f }, { -0.0036358348f, -0.015712206f, -0.0089146421f, -0.0057117233f }, { 0.020392865f, 0.017743746f, -0.068597326f, -0.030425581f }, { -0.041123673f, -0.020767538f, -0.0087941887f, -0.0065248183f }, { -0.0055478408f, -0.00082196865f, 0.0088521402f, -0.045916836f }, { -0.010506485f, 0.0078523247f, -0.030002306f, -0.0015085765f }, { 0.01894068f, -0.012424968f, -0.034837214f, -0.045009941f }, { -0.045299587f, 0.02630478f, -0.017175711f, -0.043601235f }, { -0.046003661f, -0.020588165f, 0.034398873f, -0.054653787f }, { -0.0042534368f, 0.01325834f, -0.0036369576f, -0.079162988f }, { -0.028728556f, 0.0051289128f, 0.012104313f, 0.010686997f }, { -0.066337767f, 0.00059928728f, -0.080303668f, 0.011318772f }, { -0.031879871f, 0.0011317962f, -0.050259029f, 0.0031596552f }, { -0.090121238f, -0.011196084f, -0.072456123f, -0.00079731072f }, { -0.024243475f, 0.021401076f, -0.018209385f, -0.0083196072f }, { -0.079888701f, 0.0032806631f, -0.12762259f, -0.04652308f }, { 0.031806075f, -0.034165157f, -0.015255921f, -0.049164663f }, { -0.0012051123f, 0.030788487f, 0.022291919f, 0.0025694519f }, { 0.035836509f, 0.0055365388f, 0.026704836f, 0.0001547235f }, { -0.012129747f, -0.0094322145f, -0.040637935f, -0.12125388f }, { -0.027044986f, 0.04531553f, -0.033484589f, -0.0059927923f }, { 0.0067188802f, -0.051166351f, -0.048822794f, -0.025926988f } }, { { 0.022049053f, 0.021265778f, -0.040370641f, -0.036232952f }, { -0.0058098424f, -0.0042264198f, -0.077428509f, -0.04241654f }, { -0.0026825379f, -0.029453318f, -0.016181275f, -0.028320229f }, { -0.012541692f, -0.01345735f, 0.00037814888f, -0.0046052489f }, { -0.026527394f, 0.020033638f, -0.025683861f, -0.084207169f }, { -0.0010459945f, -0.036745215f, -0.039772051f, 0.024810839f }, { 0.012134618f, 0.0068515798f, -0.035286972f, 0.043129595f }, { -0.077093357f, -0.026872688f, 0.032800133f, -0.090326706f }, { 0.13930909f, 0.0081274014f, -0.08349188f, -0.012200005f }, { -0.091693797f, -0.012567011f, -0.069736822f, -0.0061444184f }, { -0.053061301f, 0.003642159f, 0.0052515175f, -0.036957472f }, { 0.0043493933f, -0.013069332f, -0.014708126f, -0.032765039f }, { -0.016116105f, -0.022907609f, -0.043503106f, -0.013266465f }, { -0.072759977f, -0.077354585f, 0.0043827591f, -0.013821612f }, { -0.032399073f, -0.045305037f, -0.021840791f, 0.073996542f }, { -0.057239255f, -0.056581235f, -0.038880927f, 0.044102943f }, { -0.026951489f, -0.088667645f, -0.013659704f, 0.033527579f }, { 0.034815442f, -0.028634059f, -0.036666529f, 0.011546036f }, { 0.026688447f, -0.0081892129f, -0.031138092f, -0.041739155f }, { 0.0015665701f, -0.012701682f, 0.0013533943f, -0.002849785f }, { 0.032994636f, 0.008802974f, 0.019032649f, 0.0039042621f }, { -0.044544917f, 0.0093201326f, -0.017968915f, 0.01936344f }, { -0.034794535f, 0.043032983f, -0.051072531f, -0.040148303f }, { -0.0030398597f, -0.027112065f, -0.064007483f, -0.01798277f } } }, { { { 0.22040906f, 0.24911942f, 0.41660708f, 0.23632869f }, { 0.25894466f, 0.1416669f, 0.41902981f, 0.35717608f }, { 0.26918091f, 0.14566759f, 0.2147652f, 0.15769391f }, { 0.22500921f, 0.12113361f, 0.11151768f, 0.12348609f }, { 0.25699055f, 0.056819107f, 0.3859882f, 0.4585378f }, { 0.7304995f, 0.20719358f, 0.44455636f, 0.42226989f }, { 0.43602897f, 0.51049581f, 0.41978824f, 0.62521039f }, { 0.42004119f, 0.52912054f, 0.33314238f, 0.38257921f }, { 0.55092562f, 0.43085653f, 0.31149977f, 0.34391138f }, { 0.40391149f, 0.48820255f, 0.13569806f, 0.36060266f }, { 0.13647907f, 0.12061002f, 0.20668806f, 0.30221394f }, { 0.15583476f, 0.13133696f, 0.22775202f, 0.35653823f }, { 0.56336195f, 0.25684627f, 0.11118383f, 0.23109245f }, { 0.45430401f, 0.42843367f, 0.25496534f, 0.097473509f }, { 0.3420223f, 0.39418925f, 0.26458947f, 0.30588082f }, { 0.51345558f, 0.3612731f, 0.41151773f, 0.25269512f }, { 0.29195176f, 0.42659964f, 0.47971993f, 0.32714756f }, { 0.49222777f, 0.28477645f, 0.74993827f, 0.43781271f }, { 0.098434481f, 0.31164923f, 0.14486345f, 0.11466693f }, { 0.070833248f, 0.20569754f, 0.10233576f, 0.047352701f }, { 0.51050902f, 0.15597643f, 0.1417112f, 0.35581415f }, { 0.48261165f, 0.14592221f, 0.62554576f, 0.5209765f }, { 0.33562628f, 0.39920067f, 0.28183433f, 0.297464f }, { 0.366851f, 0.59278666f, 0.59095922f, 0.48385165f } }, { { 0.13792051f, 0.072076744f, 0.094800532f, 0.026318377f }, { 0.13607414f, -0.061382542f, 0.061800151f, -0.020060553f }, { 0.028096406f, 0.069282616f, 0.010195109f, -0.010461141f }, { 0.018651237f, 0.02642439f, 0.0077552848f, -0.051151646f }, { 0.098299803f, -0.0085081153f, -0.011764584f, 0.087405711f }, { 0.064082346f, -0.04626424f, -0.071480607f, 0.064447268f }, { 0.022766233f, 0.0167542f, -0.021285286f, -0.071637286f }, { -0.0202445f, 0.011692601f, 0.048325551f, 0.0097755172f }, { -0.027775183f, 0.016463115f, 0.060050391f, -0.034226107f }, { 0.019412547f, 0.059977501f, -0.0041737169f, 0.031539317f }, { 0.013192979f, 0.036015595f, -0.049943198f, 0.014112312f }, { -0.013272349f, 0.035821037f, -0.060503687f, 0.095316821f }, { 0.038338785f, -0.059038809f, -0.044954172f, -0.00051347307f }, { -0.039594082f, 0.018205882f, 0.13413799f, 0.012292954f }, { 0.015177594f, -0.0082493854f, 0.00029420179f, 0.010356248f }, { 0.100271f, -0.13623174f, 0.1121235f, 0.068902399f }, { 0.025189636f, 0.0014918434f, 0.0088847718f, -0.053714493f }, { 0.06487698f, -0.097217547f, -0.069537353f, 0.032490984f }, { -0.030729608f, 0.048956315f, 0.016036034f, 0.022485239f }, { 0.049839618f, 0.01148525f, -0.021032427f, -0.019665817f }, { -0.0037762817f, -0.030422275f, -0.062343207f, 0.057994884f }, { 0.014035184f, -0.021387762f, -0.080846143f, -0.020681511f }, { -0.03594567f, 0.026862531f, 0.078975557f, -0.034056659f }, { -0.014490672f, 0.026128902f, 0.045617611f, 0.090192953f } }, { { 0.011904288f, -0.014624471f, 0.042023114f, 0.019592867f }, { 0.032705848f, 0.00038558691f, 0.031901745f, 0.027208951f }, { -0.044369719f, -0.039761364f, -0.013366816f, -0.019308126f }, { -0.019051023f, -0.00015767269f, -0.082968285f, -0.035266053f }, { -0.004775162f, 0.010889271f, 0.0089521094f, 0.027037104f }, { 0.005616143f, -0.00099668486f, 0.0068716426f, -0.12649184f }, { 0.018531199f, 0.023881776f, -0.053798787f, -0.041912909f }, { -0.0036187094f, 0.11590788f, 0.025140733f, 0.022280209f }, { -0.02994342f, -0.026293799f, -0.017204658f, 0.044901944f }, { 0.079892089f, 0.10816526f, 0.14667807f, 0.027301352f }, { -0.045296738f, -0.066748968f, -0.0099354431f, -0.070369692f }, { -0.08357374f, -0.043311901f, 0.013163375f, -0.0881777f }, { -0.065923811f, -0.10382274f, 0.090440302f, -0.013617198f }, { -0.092578587f, -0.010178017f, -0.01416593f, 0.0432333f }, { 0.055172515f, 0.10021805f, -0.0062782668f, -0.11791805f }, { -0.039684132f, -0.08934283f, 0.020686084f, -0.0013788117f }, { 0.064624676f, 0.051773746f, 0.0045383964f, -0.037696971f }, { -0.066296373f, 0.020570689f, -0.017742721f, -0.022651449f }, { -0.0061572447f, -0.094510525f, -0.094775804f, -0.038022514f }, { 0.0055683313f, 0.039513342f, -0.096815654f, -0.0065483011f }, { -0.03311602f, -0.018395457f, 0.0028464434f, -0.088048272f }, { -0.073106109f, -0.055187863f, -0.093209932f, -0.10155137f }, { 0.042841842f, -0.005778703f, 0.074069607f, -0.025841052f }, { -0.018569637f, 0.063144303f, 0.02291584f, 0.005525742f } } } }, { { { { -0.20809663f, -0.18346453f, -0.072140694f, -0.0078104407f }, { -0.19490097f, 0.25712922f, 0.37640771f, 0.11563399f }, { 0.26894915f, -0.33477877f, -0.093739129f, -0.55078405f }, { -0.65794103f, 0.09211629f, -0.19166986f, 0.5574327f }, { 0.45579532f, 0.23202083f, 0.19626303f, -0.64130523f }, { -0.018763975f, -0.24981569f, -0.32514026f, -0.11121342f }, { 0.22376238f, 0.09515938f, 0.071728264f, -0.02790747f }, { -0.3053338f, 0.34023365f, 0.099862481f, 0.26163964f }, { -0.21722968f, -0.094881958f, -0.086364431f, -0.0081863581f }, { -0.16090709f, 0.23527698f, 0.28947119f, 0.11309742f }, { 0.26447184f, -0.33536416f, -0.096418234f, -0.26201294f }, { -0.56343769f, -0.041662822f, -0.24873841f, 0.67122901f }, { 0.35362642f, 0.2577592f, 0.2009013f, -0.74233681f }, { -0.047956299f, -0.54973418f, -0.4958485f, -0.12453303f }, { 0.06917425f, 0.080509853f, 0.0090863722f, -0.023518805f }, { -0.27000602f, 0.083167162f, 0.12715558f, 0.12397839f }, { -0.11376964f, -0.079199259f, 0.019676685f, -0.0094352472f }, { -0.19185851f, 0.22193112f, 0.28110877f, -0.06422845f }, { 0.084091992f, -0.16151548f, 0.091400556f, -0.28257376f }, { -0.53821376f, 0.21718328f, -0.2234907f, 0.52302804f }, { 0.71322306f, 0.042728493f, 0.13229522f, -0.61892094f }, { 0.15270046f, -0.26304886f, -0.33110633f, -0.052728951f }, { 0.072398971f, 0.25829764f, 0.25881687f, -0.020942042f }, { -0.26788161f, 0.055822039f, 0.33817103f, 0.42061402f } }, { { 0.088248648f, 0.091306255f, 0.020476927f, 0.0030144802f }, { 0.0087376707f, 0.043816157f, 0.0022807168f, 0.016745414f }, { -0.13412414f, 0.12686539f, 0.060531476f, 0.044582027f }, { 0.019204757f, -0.0070891897f, 0.091194602f, 0.065258927f }, { -0.10429513f, -0.027665602f, -0.064350626f, 0.0053147478f }, { 0.069218141f, -0.035018324f, -0.088257571f, 0.019279642f }, { -0.073137338f, 0.040764456f, -0.022352804f, 0.031743288f }, { 0.040325697f, -0.12840825f, -0.009582113f, 0.034509657f }, { 0.081971224f, -0.0035223125f, -0.051728499f, 0.0038899717f }, { 0.050968435f, 0.022254651f, 0.18781134f, -0.032392139f }, { 0.024342518f, 0.13929014f, -0.019175435f, -0.0011608234f }, { -0.0021942487f, -0.01251222f, 0.024263454f, -0.063179344f }, { -0.13071776f, -0.059221747f, -0.034153238f, 0.036561209f }, { 0.054124093f, 0.070495803f, 0.081441614f, 0.051900357f }, { 0.027480327f, 0.028940343f, -0.01469313f, 0.032388411f }, { -0.039696828f, -0.0069393798f, -0.011361641f, 0.035031025f }, { -0.039730763f, 0.0085971581f, -0.0077461932f, -0.040735188f }, { 0.10893368f, 0.00014757217f, 0.025489178f, -0.11388774f }, { -0.0013816669f, 0.0031148929f, 0.10281666f, -0.019860642f }, { -0.065093128f, -0.11495815f, 0.041783056f, -0.091373461f }, { -0.044985581f, 0.0012713031f, -0.16078032f, 0.17303747f }, { -0.038132358f, -0.02995975f, -0.037612782f, 0.012575173f }, { 0.0042976619f, 0.027014275f, 0.017518808f, 0.030405184f }, { -0.0015298607f, 0.029297664f, -0.1034349f, 0.023450502f } }, { { 0.028785558f, -0.028708377f, -0.010459636f, 2.8360915e-05f }, { 0.091634877f, 0.021214811f, 0.12282079f, 0.080617943f }, { -0.29287977f, 0.045481846f, 0.014712563f, 0.057317576f }, { -0.10728772f, 0.03268482f, 0.015167285f, -0.011256231f }, { 0.09337321f, 0.037150859f, 0.052549202f, -0.042671474f }, { -0.0041288689f, -0.024299997f, -0.11357403f, -0.022045772f }, { -0.041469935f, -0.0071353646f, -0.0086607538f, 0.008536762f }, { 0.033629272f, -0.0070042955f, -0.037864853f, -0.0055907778f }, { 0.016404597f, -0.0055321059f, -0.020989839f, -0.013771265f }, { 0.042552435f, 0.04428518f, 0.0030587466f, 0.044894182f }, { -0.027600219f, 0.026831779f, 0.051120849f, -0.032184808f }, { 0.13870554f, 0.15273282f, 0.049260112f, 0.043371121f }, { -0.018453269f, -0.18061413f, 0.24805649f, -0.031741165f }, { -0.085137374f, 0.025935867f, 0.015978067f, 0.067726486f }, { 0.072393868f, 0.0050430488f, 0.0016664585f, 0.0072097064f }, { 0.033840162f, 0.082225764f, -0.079387016f, 0.033165625f }, { 0.033170766f, 0.0012231618f, -0.066984982f, 0.051671704f }, { 0.017894231f, -0.012267532f, 0.045536123f, -0.07327109f }, { 0.0073109731f, -0.063797898f, -0.13446413f, 0.1408986f }, { -0.045702456f, -0.1647051f, -0.14336468f, 0.054543693f }, { 0.0042448876f, -0.13234456f, 0.092181719f, -0.10440841f }, { -0.060020212f, -0.011098469f, -0.030257182f, -0.030922037f }, { -0.018118661f, 0.00067983745f, -0.0061776598f, -0.031721273f }, { -0.019885189f, 0.094157888f, 0.014017961f, -0.051373389f } } }, { { { 0.12415319f, -0.13611564f, -0.029441661f, -0.14143497f }, { -0.26074418f, 0.011913326f, -0.033328425f, 0.43248793f }, { 0.19336432f, 0.37269586f, 0.36803538f, -0.51720719f }, { -0.15185913f, -0.47431781f, -0.6593667f, 0.23163184f }, { 0.18276216f, 0.19248743f, 0.65453332f, 0.54748087f }, { 0.17751443f, -0.0020337696f, 0.08506463f, -0.40147769f }, { -0.11370932f, 0.11523476f, -0.010573025f, 0.082295392f }, { -0.13666335f, -0.32747478f, -0.16897386f, 0.15359006f }, { 0.11716326f, -0.12259922f, 0.0033396256f, -0.13240653f }, { -0.27776876f, -0.10222241f, -0.039920479f, 0.35499708f }, { 0.090003723f, 0.3313923f, 0.1871549f, 0.003163675f }, { -0.51626118f, -0.76341562f, -0.56326874f, 0.20153559f }, { -0.34172723f, 0.26975563f, 0.67520079f, -0.1252004f }, { 0.45758078f, -0.19142179f, 0.064180031f, -0.48748431f }, { -0.12800789f, 0.1399912f, 0.0077954775f, 0.14379741f }, { -0.13042104f, -0.45670817f, -0.18831095f, 0.0032738639f }, { 0.12446807f, -0.11504524f, -0.027331682f, 0.03861758f }, { -0.31337986f, -0.11842668f, 0.033415325f, 0.45344231f }, { 0.11463107f, 0.077427841f, 0.060880794f, -0.069619455f }, { -0.37772106f, -0.59628905f, -0.65426572f, 0.065297039f }, { 0.29532991f, 0.75920243f, 0.53294265f, -0.15002562f }, { 0.3618333f, 0.10488387f, 0.36007528f, -0.30963565f }, { -0.13738196f, 0.20795596f, 0.029274703f, 0.18017599f }, { -0.10290023f, -0.48517535f, -0.33278584f, 0.56477854f } }, { { -0.0047891472f, 0.024629901f, 0.015256654f, -0.0084462001f }, { 0.056227746f, -0.048057782f, -0.15671312f, 0.06418471f }, { -0.070093217f, -0.018057199f, 0.062026545f, -0.051053726f }, { -0.0091221476f, 0.0020547295f, -0.087729813f, -0.10164738f }, { 0.098917091f, -0.066835916f, 0.083151519f, 0.006342544f }, { 0.0013540606f, 0.038719082f, 0.036333261f, -0.053178668f }, { 0.0083787438f, 0.0028359378f, 0.0089872852f, 0.031308249f }, { 0.014379686f, -0.079563474f, -0.079160006f, -0.016352226f }, { 0.0091376645f, -0.016678006f, -0.044636785f, -0.0011035265f }, { 0.0099146109f, 0.027589302f, -0.09494437f, 0.07451767f }, { 0.017453983f, 0.080674871f, 0.06341808f, 0.048820473f }, { 0.02794057f, 0.058230195f, -0.010793601f, 0.091813872f }, { -0.049633232f, -0.1142016f, 0.036984283f, 0.0034294865f }, { 0.047712957f, 0.10161366f, 0.13774722f, 0.039503136f }, { 0.014194782f, -0.014555183f, -0.00053182909f, 0.0019143477f }, { 0.0014900262f, 0.0056176356f, -0.034517871f, -0.0010707988f }, { 0.013287784f, -0.0073967933f, -0.019271341f, 0.016354896f }, { -0.10345626f, 0.023536634f, 0.027943639f, -0.015686972f }, { -0.025193395f, -0.10224801f, 0.078686884f, -0.048574399f }, { 0.15797878f, -0.0012322757f, -0.036096649f, -0.23983963f }, { -0.10455507f, -0.056368102f, -0.06570944f, 0.29104616f }, { 0.05155239f, -0.040940824f, -0.038367594f, 0.058174485f }, { 0.010471732f, -0.066952904f, -0.047763843f, -0.021124742f }, { -0.033555686f, 0.0049111983f, -0.026592789f, 0.014438586f } }, { { -0.0048440946f, 0.025915095f, -0.018325403f, 0.022133613f }, { 0.059240081f, -0.031272176f, -0.12967647f, -0.17957913f }, { 0.0574837f, 0.067005152f, 0.024644254f, 0.10786296f }, { 0.067084865f, 0.008513386f, 0.04077659f, 0.10587924f }, { 0.026332643f, 0.1072618f, -0.098375042f, -0.001724609f }, { -0.021386362f, -0.0020174921f, 0.16800158f, 0.081359882f }, { -0.018204146f, -0.026432136f, -0.0068153455f, -0.029997667f }, { -0.043221501f, -0.016869967f, -0.067406967f, -0.024965804f }, { -0.0033879999f, 0.031310818f, -0.010853802f, 0.00088944004f }, { -0.068991006f, 0.087874253f, -0.15737392f, -0.088870044f }, { 0.061763806f, -0.00072874343f, -0.009915009f, -0.0178225f }, { -0.07340717f, 0.080339271f, -0.0027124572f, -0.13078641f }, { -0.023682834f, 0.16512313f, -0.15784472f, 0.047978827f }, { 0.0063250439f, -0.09953777f, 0.094180888f, 0.010565041f }, { 0.010047311f, -0.042999009f, -0.012483998f, -0.016966759f }, { -0.048612679f, 0.051708319f, 0.015059148f, 0.0036776472f }, { -0.011737015f, -0.0027276603f, 0.026535075f, -0.065453876f }, { 0.056388137f, 0.061461073f, -0.12726984f, -0.025578248f }, { 0.0016833003f, 0.10878558f, 0.13254828f, -0.017098914f }, { -0.031606282f, -0.072245098f, 0.12724789f, -0.21852899f }, { -0.062502612f, -0.073402771f, -0.049624729f, 0.069066032f }, { -0.075837195f, -0.10297347f, -0.07249237f, -0.11538062f }, { -0.015644005f, 0.039474396f, 0.074415075f, -0.038881161f }, { -0.040175911f, 0.034030267f, 0.03947059f, 0.014167463f } } }, { { { 0.97019677f, 0.97355703f, 0.99695983f, 0.98991674f }, { 0.94552952f, 0.96630359f, 0.92585444f, 0.89419404f }, { 0.9435447f, 0.86545998f, 0.92507456f, 0.65508294f }, { 0.73759908f, 0.87552111f, 0.72697883f, 0.79725496f }, { 0.87111918f, 0.95347518f, 0.73011435f, 0.53758004f }, { 0.9839393f, 0.96829127f, 0.94183216f, 0.90909143f }, { 0.96798791f, 0.98876976f, 0.99736817f, 0.99621717f }, { 0.9423876f, 0.88147679f, 0.98054848f, 0.95286662f }, { 0.96906348f, 0.98791034f, 0.99625801f, 0.99116169f }, { 0.94707625f, 0.9665378f, 0.9563539f, 0.9280011f }, { 0.96018435f, 0.88187869f, 0.97758711f, 0.96505917f }, { 0.64499021f, 0.64456248f, 0.78794513f, 0.71332673f }, { 0.87073007f, 0.92778882f, 0.70974824f, 0.65822558f }, { 0.88787388f, 0.81311133f, 0.86603417f, 0.86420517f }, { 0.98935782f, 0.98687417f, 0.99992833f, 0.98932764f }, { 0.95398485f, 0.88572054f, 0.97384313f, 0.99227952f }, { 0.98567955f, 0.99019799f, 0.99943274f, 0.99920952f }, { 0.93004482f, 0.96784384f, 0.95909399f, 0.88896838f }, { 0.98984254f, 0.98382807f, 0.99395144f, 0.95671584f }, { 0.75342733f, 0.77283296f, 0.72248756f, 0.84981055f }, { 0.63568318f, 0.6494505f, 0.83574524f, 0.77099234f }, { 0.91965169f, 0.95906448f, 0.87218942f, 0.94939213f }, { 0.98786871f, 0.94341754f, 0.96548269f, 0.98341143f }, { 0.95794101f, 0.87263324f, 0.8802806f, 0.71000638f } }, { { -0.0064390277f, 0.051629953f, -0.011423447f, 0.032337826f }, { 0.055030538f, 0.061305324f, -0.016012659f, 0.083766345f }, { 0.052467122f, 0.018425134f, -0.00054737782f, 0.048038459f }, { 0.076436505f, 0.016815709f, -0.024174832f, -0.00829119f }, { 0.057903371f, 0.068822104f, -0.0064003131f, 0.00010695928f }, { 0.067104151f, 0.067284611f, 0.0074295447f, 0.024215238f }, { 0.073380541f, 0.01486405f, 0.01523157f, 0.012966612f }, { -0.0002536971f, 0.010628632f, 0.00045031869f, 0.041891438f }, { 0.055922922f, 0.0090823157f, 0.011101162f, 0.033807592f }, { -0.040264953f, 0.022318628f, -0.013682045f, -0.016112502f }, { -0.034286564f, 4.7089727e-05f, -0.013030079f, -0.012231424f }, { 0.027756308f, 0.084041595f, 0.018308393f, 0.11564334f }, { 0.0026690817f, 0.058149333f, -0.013682964f, 0.052975934f }, { -0.03852481f, 0.063493354f, 0.059460027f, 0.047740976f }, { 0.026410264f, -0.0073902435f, 0.022353771f, 0.012987341f }, { 0.035217135f, -0.0023455309f, -0.0055505614f, 0.010102857f }, { 0.00075590283f, 0.038624793f, -0.0040614962f, 0.070039437f }, { -0.02318411f, 0.04527054f, 0.013119286f, 0.025335215f }, { 0.021268391f, 0.044855911f, 0.012622905f, 0.04827088f }, { -0.0046678346f, -0.01934799f, 0.018393432f, 0.09750434f }, { 0.12480373f, 0.059151139f, 0.055196092f, 0.26701338f }, { -0.0096669036f, 0.065624767f, 0.016918517f, 0.028425135f }, { 0.026488514f, -0.0037618693f, 0.0077028717f, 0.041713399f }, { 0.018628451f, 0.033145064f, 0.029067918f, -0.000924258f } }, { { -0.043525781f, 0.028119778f, -0.011653105f, -0.020930158f }, { -0.028099186f, 0.017594088f, -0.099226445f, 0.10408808f }, { 0.11750066f, -0.0010629746f, 0.018381448f, 0.096538552f }, { 0.0010069446f, 0.013799541f, 0.1325137f, 0.020820734f }, { -0.053571928f, -0.0066793785f, 0.14596488f, -0.03272949f }, { 0.028507895f, 0.015474376f, -0.025411653f, 0.037264272f }, { 0.033698911f, 0.018088387f, 0.0038898537f, 0.03163178f }, { 0.0057766828f, 0.015879322f, 0.012557033f, 0.071771631f }, { -0.0044521866f, 0.0083963511f, -0.0020426175f, 0.023784146f }, { -0.011508765f, 0.0075020051f, 0.0018808294f, 0.040843424f }, { 0.0085150894f, 0.0056891711f, 0.010134672f, 0.046224768f }, { 0.040825446f, 0.10099754f, 0.021853299f, 0.024507528f }, { -0.0055958303f, -0.0060958f, 0.1115321f, -0.021701014f }, { 0.010487817f, -0.010033143f, -0.031203025f, 0.054265436f }, { 0.0040500672f, 0.0053935875f, 0.018233022f, 0.018797311f }, { 0.064057639f, 0.014318185f, 0.0199119f, 0.014366235f }, { 0.02411682f, 0.045454692f, 0.0030084434f, 0.019464939f }, { 0.012500289f, 0.027734846f, 0.0025097372f, 0.047343669f }, { 0.037625829f, -0.00064472688f, 0.0557556f, 0.04785655f }, { 0.0020433437f, 0.019929208f, 0.087936103f, -0.036738471f }, { 0.020811556f, 0.0915387f, 0.055445303f, -0.065132763f }, { 0.03911814f, 0.043721622f, 0.0074336204f, -0.031370424f }, { 0.014072509f, -0.014795458f, 0.010517063f, 0.022409628f }, { -0.0054107234f, 0.055313602f, 0.053556404f, 0.048574319f } } }, { { { 3.4224197f, 3.3162336f, 3.1136621f, 3.3189801f }, { 4.0715355f, 3.5614196f, 4.1797877f, 4.0959601f }, { 4.3979407f, 4.1858272f, 4.3116447f, 4.5467451f }, { 4.4920032f, 4.0716439f, 4.6107962f, 4.5268016f }, { 5.6570832f, 4.9036495f, 4.7373547f, 4.7259419f }, { 3.3277827f, 3.6015237f, 4.226646f, 3.7939772f }, { 3.4893058f, 3.3260638f, 3.0626103f, 3.1798705f }, { 3.6423735f, 4.1092281f, 3.3264203f, 3.7325301f }, { 3.4756581f, 3.2550256f, 3.224671f, 3.4093307f }, { 3.8511362f, 3.4821381f, 4.3232597f, 3.7357164f }, { 3.6688024f, 4.0797971f, 3.4140927f, 3.6881261f }, { 4.5298469f, 4.7472506f, 4.4046473f, 4.7279944f }, { 4.1614448f, 4.1242955f, 4.6741969f, 5.0037875f }, { 4.3148703f, 4.3815566f, 4.1976536f, 3.9032858f }, { 3.2640506f, 3.3214728f, 2.9463564f, 3.3562068f }, { 3.6729325f, 3.9218642f, 3.4550701f, 3.4833871f }, { 3.435975f, 3.3079446f, 3.3432341f, 3.3632985f }, { 3.8404619f, 3.4716915f, 3.858149f, 3.8677391f }, { 3.3181827f, 3.8403872f, 4.0363918f, 3.9604287f }, { 5.0916792f, 5.2773748f, 4.5404255f, 4.377031f }, { 4.6514614f, 4.7569957f, 4.1233238f, 4.4022582f }, { 3.6884833f, 3.6283543f, 4.1874612f, 4.2963913f }, { 3.456705f, 3.6250566f, 3.5292789f, 3.1420033f }, { 3.5986317f, 4.0596074f, 4.0696874f, 4.5327067f } }, { { -0.12592901f, -0.14780788f, -0.11051274f, -0.18767653f }, { -0.020435093f, 0.0055221209f, -0.021183195f, -0.15159792f }, { 0.022498629f, -0.025100789f, -0.30939177f, 0.016420202f }, { 0.21296442f, -0.042976575f, 0.082118132f, 0.14574735f }, { -0.13608022f, 0.16141834f, -0.015091164f, 0.044951541f }, { -0.08235774f, -0.10333151f, 0.089785432f, -0.036620639f }, { -0.17664465f, -0.015842477f, -0.083075331f, -0.15660828f }, { -0.11292423f, -0.072894494f, -0.068901923f, -0.2283674f }, { -0.19063437f, -0.071954393f, 0.091375283f, -0.26993547f }, { 0.042798331f, -0.06495575f, 0.050221766f, 0.024602586f }, { -0.026228614f, 0.0049810367f, 0.046584088f, -0.13067577f }, { 0.072779737f, -0.023369437f, -0.030275791f, 0.19591126f }, { -0.018649072f, 0.029208952f, 0.012033439f, 0.00094798196f }, { -0.094599446f, 0.0070746366f, -0.0007115864f, -0.040175552f }, { -0.027599009f, -0.068747365f, 0.19480498f, -0.19423733f }, { -0.076671551f, 0.0075475135f, 0.019853903f, -0.012984601f }, { 0.064371855f, -0.24044027f, -0.043765356f, 0.0016424127f }, { -0.076744435f, 0.035881398f, 0.12967612f, 0.081825243f }, { -0.15224256f, 0.032665115f, -0.027927205f, 0.076091133f }, { -0.0057973613f, -0.14914213f, -0.047678749f, -0.037214457f }, { 0.10060085f, -0.099197666f, -0.22704457f, -0.0020812401f }, { -0.070664558f, -0.13179176f, -0.014217065f, -0.030410253f }, { -0.12286487f, -0.046623366f, -0.10695394f, -0.0081383175f }, { -0.14561788f, 0.02765909f, 0.10439783f, 0.033139041f } }, { { 0.0063171031f, -0.0047223477f, -0.056312039f, -0.065065766f }, { -0.0059575982f, -0.062348475f, 0.069540315f, -0.090331962f }, { 0.10218203f, 0.050383376f, -0.0089914697f, -0.037837343f }, { -0.0037657879f, 0.18278082f, 0.079014627f, -0.052587294f }, { -0.33929282f, 0.018522098f, 0.0078923893f, 0.042545349f }, { 0.027294929f, -0.086490439f, -0.0057363347f, -0.035932082f }, { -0.061716003f, -0.14470599f, 0.033117786f, -0.08112808f }, { 0.16414856f, 0.082471596f, -0.058497326f, 0.050552718f }, { -0.07627083f, -0.0064181717f, -0.031179581f, -0.075705068f }, { -0.057808009f, -0.00074561624f, -0.23990956f, 0.018671772f }, { 0.1677602f, 0.10757253f, 0.028015134f, -0.23923178f }, { 0.078827365f, 0.068682485f, 0.056277532f, -0.069749241f }, { 0.079502977f, 0.05526585f, 0.0089767144f, -0.15319341f }, { -0.038594242f, -0.055488998f, -0.043132461f, 0.054313031f }, { 0.12890592f, -0.082639555f, 0.22520491f, -0.026781096f }, { -0.071292391f, 0.064592881f, -0.050368563f, -0.072488866f }, { 0.092998671f, 0.12152394f, 0.033318795f, -0.039691417f }, { -0.0049706273f, -0.0014175115f, -0.11634604f, 0.15219284f }, { -0.012414906f, 0.035583927f, -0.072463074f, -0.058394705f }, { -0.071558898f, -0.00093653835f, 0.013149622f, 0.01495775f }, { -0.057103279f, 0.013702583f, -0.020242751f, 0.04649072f }, { -0.083398977f, -0.20123674f, 0.062758815f, -0.043671819f }, { 0.084479675f, 0.17868517f, -0.021185269f, 0.15711776f }, { 0.11862504f, 0.079985297f, 0.063556911f, 0.14639069f } } }, { { { 0.48018566f, 0.17712962f, 0.45065949f, 0.76214707f }, { 0.37788335f, 0.385421f, 0.24766167f, 0.3647243f }, { 0.45095873f, 0.2634498f, 0.37824131f, 0.10713483f }, { 0.18808611f, 0.27852978f, 0.23671202f, 0.23174978f }, { 0.39404781f, -0.7399413f, 0.28511918f, 0.026007027f }, { 0.46587668f, 0.46802177f, 0.36697974f, 0.23706778f }, { 0.48925391f, 0.42086488f, 0.49570155f, 0.45137287f }, { 0.30655255f, 0.35196398f, 0.23019387f, 0.50586011f }, { 0.45798975f, 0.34137244f, 0.33289763f, 0.54218519f }, { 0.42271216f, 0.38700914f, 0.48791862f, 0.15025833f }, { 0.7282781f, 0.37956244f, 0.25156645f, 0.51632504f }, { 0.084933462f, 0.15576738f, 0.16469359f, 0.29684651f }, { 0.34570877f, 0.34912791f, 0.26663435f, 0.11188061f }, { 0.48552914f, 0.19012867f, 0.12677402f, 0.1234341f }, { 0.2190939f, 0.41431469f, 0.64823269f, 0.51846746f }, { 0.49289149f, 0.29829354f, 0.29090992f, 0.36465152f }, { 0.50568056f, 0.64150077f, 0.40217634f, 0.53523743f }, { 0.24945735f, 0.47058801f, 0.29099852f, 0.25452114f }, { 0.49039753f, 0.26327736f, 0.39431507f, 0.50632023f }, { 0.19678915f, 0.031547614f, 0.22295107f, 0.26300048f }, { 0.12409997f, 0.11506147f, 0.19327618f, 0.2174585f }, { 0.15319333f, 0.39177705f, 0.38498586f, 0.25972804f }, { 0.69027161f, 0.37279682f, 0.31143504f, 0.23440833f }, { 0.39682066f, 0.3156927f, 0.36369313f, 0.14308402f } }, { { 0.15030994f, 0.15410005f, 0.0072554408f, -0.22242826f }, { -0.032421729f, 0.22531436f, 0.22185899f, -0.022703209f }, { 0.070341052f, 0.30237173f, 0.047916387f, 0.03629681f }, { -0.024283222f, 0.075614195f, 0.013940033f, -0.016841468f }, { 0.077729482f, 0.19455394f, -0.02162282f, -0.018761003f }, { -0.22986895f, 0.18914992f, 0.14483608f, 0.11173921f }, { 0.14132894f, -0.0081864768f, -0.11405791f, 0.031777789f }, { 0.38775389f, 0.0085565642f, -0.057167843f, 0.09784167f }, { 0.079102739f, 0.030530894f, 0.041954967f, 0.02957611f }, { 0.076915126f, 0.18656729f, 0.044218872f, 0.22478833f }, { 0.017173879f, 0.11961351f, -0.085099523f, 0.22720323f }, { 0.030466202f, 0.095221887f, -0.042982583f, -0.069264747f }, { 0.041170442f, -0.090598444f, -0.021082598f, -0.028016784f }, { -0.082581617f, -0.023712106f, 0.32427665f, 0.1010696f }, { 0.19197752f, 0.10900527f, -0.0053794951f, 0.068553764f }, { 0.18674269f, 0.028895321f, -0.053421028f, 0.063918058f }, { 0.044090722f, -0.054247791f, 0.05585954f, -0.13406746f }, { 0.08358642f, -0.032301886f, 0.010371619f, 0.099505528f }, { 0.16467816f, 0.044994571f, -0.0045949279f, 0.0626774f }, { 0.12942209f, 0.092097891f, 0.019866495f, 0.10340014f }, { 0.037094903f, 0.13829877f, 0.15116473f, -0.048632499f }, { 0.10749044f, 0.14329542f, -0.061272024f, -0.1536028f }, { 0.097716907f, 0.044246181f, 0.056664419f, 0.15804873f }, { 0.031819999f, 0.10132976f, 0.079198524f, 0.017871462f } }, { { 0.056219172f, 0.08683492f, -0.061488015f, 0.065746152f }, { 0.088983664f, 0.19773741f, -0.096766599f, 0.16352101f }, { -0.0097043787f, -0.040925999f, 0.097458334f, 0.032319634f }, { -0.024873518f, 0.057873123f, -0.0059256291f, -0.057498398f }, { -0.13355098f, 0.39190863f, 0.017449142f, -0.0076009344f }, { 0.10319658f, 0.22069551f, -0.098795717f, 0.10603434f }, { 0.090765308f, 0.13803326f, -0.070647945f, 0.14557561f }, { -0.068457348f, 0.058955208f, -0.050501105f, 0.02914144f }, { 0.10363866f, 0.060231993f, 0.027681685f, 0.079659088f }, { 0.01269983f, 0.11977996f, -0.049648315f, 0.089882363f }, { -0.072877286f, 0.019348792f, 0.13977764f, 0.055396044f }, { 0.028834456f, -0.1084196f, -0.0043985215f, -0.072640844f }, { -0.040232522f, 0.051835989f, -0.02198193f, 0.016421295f }, { -0.087848469f, -0.04621504f, 0.099259188f, -0.0025909067f }, { 0.3000131f, 0.10526775f, 0.016890366f, 0.12892588f }, { -0.021028821f, -0.024429075f, 0.088067677f, -0.084594075f }, { 0.086861805f, -0.045902006f, 0.0058222123f, -0.0075466204f }, { 0.14411905f, 0.036488937f, 0.05091815f, 0.16385101f }, { 0.1576814f, 0.043890956f, -0.064244298f, -0.087234754f }, { -0.071100004f, 0.16782304f, -0.10860149f, -0.1601076f }, { 0.032634641f, -0.0025068263f, -0.093802703f, -0.076176546f }, { 0.1121451f, 0.15584236f, 0.070074778f, 0.083736091f }, { 0.16981897f, -0.078106227f, 0.12480295f, -0.0056807652f }, { -0.20300117f, -0.017467249f, 0.035504155f, 0.056546123f } } } }, { { { { 0.014994926f, 0.3118252f, 0.12179235f, -0.2013765f }, { -0.2622824f, 0.28086607f, 0.018805882f, 0.72058929f }, { -0.0081002049f, -0.28176506f, -0.592214f, -0.15032918f }, { 0.18913426f, -0.24000825f, 0.0020279072f, -0.54749128f }, { 0.010237954f, 0.76905205f, 0.80173664f, -0.016024595f }, { -0.53448318f, 0.31204229f, -0.16183732f, 0.76857439f }, { -0.57639279f, -0.63719194f, -0.71354849f, 0.56346054f }, { 0.49443258f, 0.15067585f, 0.31864726f, -0.30570933f }, { -0.20756322f, 0.2544828f, -0.005298245f, 0.0073796841f }, { -0.61822672f, 0.21508574f, 0.6362534f, 0.30433278f }, { -0.0050327191f, -0.278054f, -0.3460806f, 0.29967778f }, { 0.33983098f, -0.11715664f, -0.21761592f, -0.068273894f }, { 0.5550354f, 0.44369709f, 0.64019993f, -0.026032291f }, { -0.72587268f, -0.33528197f, -0.33592445f, 0.53027141f }, { -0.47623191f, -0.61767624f, -0.61525655f, 0.37823554f }, { 0.82869964f, 0.219401f, -0.018181789f, -0.56937955f }, { -0.051792934f, 0.3461701f, 0.20915925f, 0.078166496f }, { -0.26705611f, 0.14439061f, 0.0055054648f, 0.463243f }, { -0.0019649711f, -0.34119962f, -0.29306531f, -0.040223173f }, { 0.29285811f, -0.32824753f, -0.24768208f, -0.29676955f }, { 0.87604898f, 0.25374435f, 0.2341931f, -0.77851996f }, { -0.80404697f, 0.011122158f, 0.18899178f, 0.55592668f }, { -0.78397618f, -0.53690406f, -0.59931185f, 0.62348293f }, { 0.54613799f, 0.080819658f, 0.12590931f, -0.60614071f } }, { { -0.12307869f, -0.20242175f, 0.21530167f, -0.15608553f }, { 0.00052208688f, 0.09998365f, -0.067550225f, -0.14009319f }, { 0.12621699f, -0.089024022f, 0.022656689f, 0.18947331f }, { 0.34838897f, -0.04936051f, 0.25527451f, -0.18942819f }, { 0.013210249f, -0.043957685f, -0.19088103f, -0.034189573f }, { -0.0027790938f, -0.026595097f, 0.087083287f, -0.12513839f }, { -0.038231564f, 0.013328425f, -0.0091503894f, -0.005743873f }, { 0.17205702f, -0.14956835f, -0.0088915291f, 0.18720588f }, { -0.049670195f, 0.39532325f, 0.080260299f, 0.01811245f }, { 0.043555003f, -0.30289197f, -0.50878196f, 0.27306166f }, { 0.02555972f, -0.0068359476f, 0.061097702f, -0.43822038f }, { -0.10926471f, 0.1870906f, 0.12419548f, 0.1245213f }, { -0.012443149f, 0.040036941f, 0.18601483f, 0.02310445f }, { -0.10442982f, 0.057455632f, 0.13475314f, -0.0019859122f }, { -0.068181593f, -0.0033655904f, 0.01922998f, -0.020393828f }, { -0.10660626f, 0.0020812455f, 0.081209707f, 0.077131932f }, { 0.088733212f, -0.10430986f, 0.45554817f, -0.17113078f }, { 0.0046831409f, 0.13247549f, -0.1077727f, 0.15382275f }, { 0.022346595f, 0.022924261f, -0.35016323f, 0.2437608f }, { 0.029795657f, 0.23046877f, -0.020493651f, -0.33214749f }, { -0.016101582f, 0.042296203f, 0.046779444f, 0.037412394f }, { -0.02214903f, -0.025218605f, 0.14797485f, -0.051723623f }, { 0.021321783f, 0.010405115f, 0.0075476201f, 0.0082410917f }, { 0.040559796f, 0.027927916f, -0.012812736f, -0.0096642379f } }, { { -0.055647079f, 0.017595207f, 0.34495838f, -0.03055759f }, { -0.058415094f, 0.027416036f, 0.18568916f, 0.13044498f }, { 0.01482217f, -0.17300703f, 0.027540135f, -0.2744944f }, { 0.25558424f, -0.15324455f, -0.29751197f, -0.11422984f }, { -0.068936732f, -0.11425403f, 0.094767025f, -0.0020892558f }, { 0.040887892f, 0.031622148f, -0.095292456f, -0.02460001f }, { -0.0026237665f, 0.017734103f, 0.01213911f, 0.0056586962f }, { -0.052138375f, 0.052245567f, 0.04608449f, -0.043004468f }, { -0.17693366f, 0.0021023738f, 0.13167397f, -0.14062006f }, { -0.20900333f, 0.0057695127f, 0.13057243f, 0.046715668f }, { -0.020569928f, -0.08439655f, -0.09683347f, 0.038139385f }, { 0.18196242f, 0.44461908f, -0.11388512f, -0.12413082f }, { 0.072801844f, -0.0017236427f, -0.0026756083f, 0.049805114f }, { -0.092195952f, -0.0076195172f, -0.22763849f, -0.11320887f }, { 0.016234922f, 0.007258942f, 0.078535592f, -0.084829275f }, { -0.15320003f, 0.057490618f, -0.16065455f, -0.17063675f }, { -0.012856124f, 0.024818957f, 0.097529739f, 0.11569844f }, { -0.11141243f, 0.26677735f, 0.1319403f, -0.15699502f }, { -0.021128161f, -0.12370585f, 0.056198856f, -0.1836225f }, { -0.01871806f, 0.025525037f, 0.063822152f, 0.066517944f }, { -0.013759301f, 0.11401068f, -0.04701374f, -0.021321516f }, { 0.032714649f, -3.161284e-06f, 0.026930697f, 0.00019593482f }, { 0.10575127f, 0.016956425f, 0.016873291f, 0.0049304377f }, { -0.11938883f, 0.31242334f, 0.29347156f, -0.19514533f } } }, { { { -0.17374661f, -0.028781395f, -0.25993234f, 0.27242277f }, { -0.13675759f, -0.62291002f, -0.80742781f, 0.54260546f }, { 0.16876581f, -0.052588487f, 0.22415557f, -0.59669887f }, { 0.1769234f, 0.64210979f, 0.81157479f, -0.2718564f }, { -0.99873125f, -0.013258174f, 0.58939675f, 0.99930085f }, { -0.30883355f, -0.71116337f, -0.76218623f, 0.096388818f }, { 0.65749012f, -0.54533843f, -0.57508599f, -0.70359398f }, { -0.27406769f, 0.61006308f, 0.1873512f, 0.2563151f }, { -0.78453523f, -0.13585943f, -0.048534939f, 0.02085237f }, { 0.40938527f, -0.76981396f, -0.42506866f, 0.22362984f }, { 0.29003079f, -0.20624421f, 0.1151133f, -0.50558933f }, { 0.0070051806f, 0.20763719f, 0.59485798f, -0.61562639f }, { -0.4371111f, 0.48314196f, 0.72981069f, 0.99889301f }, { 0.58257878f, -0.8603979f, -0.94188892f, -0.83140889f }, { 0.71858167f, -0.49534538f, -0.63421799f, -0.84488463f }, { 0.016158248f, 0.65330502f, 0.82883727f, -0.127372f }, { -0.50292264f, -0.14848746f, -0.20836533f, 0.2471481f }, { -0.15815031f, -0.63472031f, -0.79826416f, 0.15325573f }, { -0.010424343f, -0.022843894f, 0.099730136f, -0.26040744f }, { 0.15069433f, 0.31188588f, 0.63836617f, -0.25234477f }, { -0.36946506f, 0.92093529f, 0.96548808f, 0.62354203f }, { -0.57070465f, -0.99847512f, -0.47855156f, -0.079970605f }, { 0.077467525f, -0.71134336f, -0.67172579f, -0.66364974f }, { -0.27299386f, 0.89512951f, 0.61598356f, 0.49577277f } }, { { 0.070458859f, -0.28774455f, 0.21287043f, -0.094689772f }, { 0.0029548085f, -0.31404605f, -0.039280892f, -0.3652277f }, { -0.033729607f, 0.041215792f, 0.065844258f, -0.21509418f }, { 0.39270582f, 0.067526811f, 0.15655351f, 0.053346856f }, { 0.052704394f, -0.087801294f, 0.18655104f, 0.056114808f }, { -0.074582751f, -0.055177669f, -0.22165519f, 0.13272162f }, { -0.027850171f, 0.0029849066f, -0.0062314784f, -0.010484316f }, { 0.20753796f, -0.0087111988f, -0.13875075f, -0.06137521f }, { 0.089744421f, 0.07271039f, 0.099417029f, -0.22157272f }, { -0.013209094f, 0.048633419f, -0.26528065f, -0.15253703f }, { 0.052922007f, 0.24859103f, 0.14406684f, 0.13857649f }, { 0.00096142813f, 0.32643367f, 0.17939549f, -0.39761314f }, { 0.013505803f, -0.036986517f, -0.12729111f, 0.15459921f }, { -0.00049722057f, -0.047063275f, -0.0018666598f, 0.1067114f }, { -0.074221027f, -0.00927958f, -0.029535811f, -0.024240068f }, { -0.12387933f, 0.06626829f, 0.16422781f, 0.077740779f }, { 0.14560404f, -0.082132455f, 0.027268021f, 0.18857832f }, { 0.10470732f, -0.29519533f, -0.23666419f, 0.10917064f }, { 0.042550279f, 0.02436036f, -0.31865644f, -0.024987356f }, { -0.030434576f, 0.082115299f, 0.17770796f, 0.020944092f }, { -0.17365377f, 0.13807361f, 0.12476029f, 0.072738061f }, { -0.11503962f, -0.04022554f, 0.028018434f, -0.070211356f }, { -0.043677907f, 0.0053361863f, 0.0039019898f, 0.0027489647f }, { 0.27060899f, -0.0016552279f, 0.14166067f, -0.25461265f } }, { { 0.014703402f, 0.094752279f, -0.32162049f, 0.082335322f }, { -0.31539882f, 0.44394592f, 0.44316202f, -0.031456167f }, { -0.024148679f, 0.082370612f, -0.0031744796f, 0.098610537f }, { 0.46130367f, -0.19989896f, -0.56118891f, 0.11979937f }, { 0.11784636f, 0.079971516f, -0.16977121f, 0.014922099f }, { 0.018367216f, -0.076519762f, 0.13801492f, 0.039682415f }, { -0.0027614728f, 0.0010389006f, -0.023126227f, 0.0027068473f }, { 0.22249856f, -0.071302328f, 0.23721977f, 0.10734273f }, { 0.41478408f, -0.36611101f, 0.18031261f, -0.11176768f }, { 0.15800457f, 0.23829725f, -0.0016193556f, 0.2112867f }, { -0.14793833f, -0.15378785f, 0.0082778301f, 0.27105519f }, { -0.064743588f, 0.44794816f, -0.12599819f, 0.4310022f }, { 0.092725214f, 0.033947737f, 0.19969884f, 0.0072363359f }, { -0.074190657f, 0.005985921f, 0.300818f, -0.090919095f }, { 0.024238118f, -0.010955859f, -0.068086841f, -0.021137349f }, { 0.12196721f, -0.19977338f, -0.64428422f, -0.30808722f }, { 0.46567096f, -0.042072501f, -0.1778338f, 0.34294059f }, { -0.32528695f, 0.25699981f, 0.49346557f, -0.20743316f }, { 0.10422458f, 0.049488574f, 0.49098274f, -0.34871439f }, { 0.16431875f, -0.050748897f, -0.18464312f, -0.61695364f }, { -0.1753479f, 0.033238479f, -0.046267845f, -0.012339883f }, { -0.16098841f, 0.080519992f, -0.11793031f, 0.036790025f }, { 0.017193144f, -0.0029212372f, -0.0044153187f, -0.0057094316f }, { 0.23481771f, -0.1556448f, -0.18775429f, -0.013697353f } } }, { { { 0.98467622f, 0.94970347f, 0.95791534f, 0.9408684f }, { 0.95525144f, 0.73013516f, 0.58966657f, 0.43166004f }, { 0.98562289f, 0.95804118f, 0.77397471f, 0.78825859f }, { 0.96588112f, 0.72807352f, 0.58424502f, 0.79142113f }, { -0.049305848f, 0.63904864f, 0.099145551f, -0.03377918f }, { 0.78673348f, 0.62998117f, 0.62680207f, 0.63245759f }, { 0.48526085f, 0.544603f, 0.40015579f, 0.43297544f }, { 0.82487776f, 0.77789448f, 0.92917353f, 0.91697567f }, { 0.58431326f, 0.95748667f, 0.99880743f, 0.99975533f }, { 0.67096902f, 0.60093643f, 0.64381538f, 0.92594344f }, { 0.95700408f, 0.93816272f, 0.93111608f, 0.80905665f }, { 0.94046044f, 0.97116483f, 0.77381347f, 0.78507504f }, { 0.7077214f, 0.7547892f, 0.23983411f, -0.039180128f }, { 0.3656649f, 0.38379871f, -0.00015338393f, 0.16604667f }, { 0.50679735f, 0.6108265f, 0.46821675f, 0.37829596f }, { 0.55946029f, 0.72460731f, 0.55919425f, 0.81214734f }, { 0.86277825f, 0.92634645f, 0.95542467f, 0.96581976f }, { 0.95061533f, 0.75913205f, 0.60228234f, 0.87287949f }, { 0.99994373f, 0.93971324f, 0.95087677f, 0.96466059f }, { 0.9442062f, 0.89161694f, 0.72879505f, 0.92100486f }, { 0.30989313f, 0.29579046f, 0.11395771f, 0.071428407f }, { 0.16674735f, -0.054071458f, 0.85747916f, 0.82737551f }, { 0.61593841f, 0.45356879f, 0.43544204f, 0.41332561f }, { 0.79196443f, 0.43841915f, 0.77763172f, 0.62193473f } }, { { 0.028699614f, 0.071974788f, -0.028868668f, 0.030119772f }, { -0.16988515f, -0.35713152f, 0.36877151f, 0.37172103f }, { 0.024472009f, 0.10373643f, 0.052160621f, -0.12998364f }, { 0.051999909f, -0.1688679f, 0.05813266f, -0.11063347f }, { 0.026373007f, 0.067310776f, 0.34433164f, 0.0017481699f }, { -0.017659611f, -0.10215276f, -0.23736187f, 0.12678732f }, { -0.0019097928f, 0.02067204f, -0.030447136f, -0.0093192388f }, { 0.10615435f, 0.11124023f, 0.04473958f, 0.14369936f }, { 0.14791062f, -0.034502091f, 0.041456555f, 0.06737059f }, { 0.22389399f, 0.2668048f, 0.25742349f, 0.03724758f }, { 0.0046009946f, 0.066632032f, 0.097957775f, 0.22969631f }, { 0.043253167f, -0.013638494f, 0.071328387f, -0.19249903f }, { -0.023561087f, 0.011490741f, 0.19824644f, -0.04133258f }, { -0.057507532f, -0.039265903f, 0.060469313f, 0.37300659f }, { 0.027051207f, -0.0086784396f, -0.0055877341f, -0.0315352f }, { 0.15724931f, 0.0099485187f, 0.22462997f, 0.14112999f }, { 0.13909905f, 0.026199511f, -0.12430815f, -0.076900423f }, { -0.022327596f, -0.1975812f, 0.49862652f, -0.096026553f }, { 0.076782007f, 0.041598482f, 0.0033451155f, 0.039947963f }, { 0.005353589f, 0.070993946f, 0.0068174778f, -0.17805261f }, { -0.059912765f, -0.17027417f, -0.060069718f, 0.1561139f }, { 0.017122435f, 0.048532637f, -0.05315926f, 0.066962855f }, { 0.058014377f, 0.021874362f, 0.017248667f, -0.0069413843f }, { 0.099274028f, 0.040622241f, 0.040435904f, 0.14191123f } }, { { -0.13453832f, 0.071519908f, -0.1597656f, -0.030758273f }, { -0.13511715f, 0.32373425f, 0.35851035f, -0.18685481f }, { 0.021440457f, 0.034442875f, 0.14324368f, 0.15754565f }, { -0.061440371f, 0.16837735f, 0.47887644f, -0.036265812f }, { 0.55060811f, 0.14095672f, 0.13077418f, 0.25515565f }, { -0.084599968f, -0.084002143f, 0.1542308f, 0.044223437f }, { 0.0017727822f, 0.025149715f, -0.025479364f, -0.0023658361f }, { 0.1619123f, 0.069159159f, -0.016343512f, 0.026108175f }, { 0.3296525f, 0.029456656f, 0.039715069f, 0.015958704f }, { -0.093419591f, 0.37051381f, -0.063182977f, -0.017764112f }, { 0.11962535f, 0.062511772f, -0.070445145f, 0.27768911f }, { 0.07458833f, -0.16218828f, 0.064111239f, 0.43889373f }, { -0.0326486f, -0.03666828f, -0.17597139f, 0.34213144f }, { 0.061334301f, -0.0099525239f, 0.21497301f, 0.0074569296f }, { -0.016749445f, 0.00054557189f, 0.040331287f, 0.066200794f }, { 0.20620866f, 0.25268529f, 0.46594276f, 0.059651923f }, { 0.15170896f, 0.041438057f, 0.021708506f, -0.15049245f }, { -0.14317538f, 0.13548996f, 0.37297491f, 0.13718874f }, { 0.053339004f, 0.015014013f, -0.10418356f, -0.13598877f }, { -0.02227412f, 0.045548464f, 0.21534467f, -0.23828118f }, { -0.055326885f, 0.11851609f, 0.28938409f, 0.041373996f }, { -0.1219532f, 0.57338554f, -0.094571555f, 0.025008596f }, { 0.070380772f, 0.016993506f, 0.018073937f, -0.015404818f }, { 0.17033841f, 0.12449473f, 0.10847869f, -0.11141982f } } }, { { { 4.409738f, 4.5071479f, 5.4761817f, 5.3214091f }, { 5.3741435f, 4.6270256f, 5.4786338f, 5.323679f }, { 4.305776f, 4.4890731f, 4.6894257f, 4.6068436f }, { 5.4930574f, 4.9116386f, 5.4097636f, 4.9225404f }, { 5.1861828f, 5.5144226f, 5.1307797f, 5.0804212f }, { 6.1194597f, 6.0655136f, 5.7369562f, 6.1076578f }, { 6.9549598f, 6.9281578f, 6.9549598f, 6.9549598f }, { 4.5030565f, 4.5849566f, 4.4830953f, 4.4904323f }, { 5.3629211f, 5.5524848f, 4.5719135f, 4.9103175f }, { 4.8906163f, 5.3972226f, 4.8806206f, 5.1834202f }, { 4.5047396f, 4.5984947f, 4.7039612f, 4.3422371f }, { 4.5956963f, 5.6294962f, 4.46025f, 4.4827131f }, { 5.8454206f, 6.000743f, 5.4594428f, 4.9952614f }, { 6.09642f, 6.3979283f, 4.9784963f, 5.6878449f }, { 6.9549598f, 6.9752898f, 6.9549598f, 6.9549598f }, { 6.2053562f, 4.9984547f, 5.3887395f, 4.6221036f }, { 4.5265196f, 4.3684629f, 5.5819288f, 5.4957366f }, { 5.2220057f, 4.6118907f, 5.5046208f, 4.9190037f }, { 4.3408178f, 4.4980303f, 5.4937404f, 5.6154153f }, { 4.4802186f, 4.4666194f, 4.8546878f, 5.1764252f }, { 5.7384024f, 5.9048089f, 5.4636107f, 5.0807017f }, { 5.1013817f, 5.2237041f, 6.0338955f, 5.8869417f }, { 6.9414339f, 6.9549598f, 6.9549598f, 6.9549598f }, { 4.3368412f, 4.9692663f, 4.7090567f, 4.9023075f } }, { { 0.0093525884f, -0.33796029f, -0.4366682f, -0.18161326f }, { -0.34446047f, 0.10854359f, -0.61563912f, -0.16514117f }, { 0.055849315f, 0.093045585f, 0.36722184f, 0.085665647f }, { -0.21881508f, -0.036846235f, -0.25226403f, -0.012790033f }, { -0.14697546f, -0.026656628f, 0.2559775f, 0.026279081f }, { 0.073189287f, -0.074472165f, -0.15439557f, 0.020907645f }, { 0.0f, -0.015078298f, 0.0f, 0.0f }, { 0.027540893f, -0.30876053f, -0.15680794f, -0.18470107f }, { -0.072547269f, -0.019227086f, -0.26735769f, -0.1362069f }, { 0.36907279f, -0.28005156f, 0.01966203f, -0.10277819f }, { -0.26755862f, 0.066747173f, 0.60834173f, -0.23356165f }, { -0.12357338f, -0.41742338f, 0.081840746f, -0.14596222f }, { -0.068599762f, -0.004402392f, -0.17192993f, -0.15797464f }, { -0.072923207f, -0.02555551f, -0.21075071f, 0.047272919f }, { 0.0f, 0.0115085f, 0.0f, 0.0f }, { 0.32527558f, 0.066048741f, -0.28639187f, 0.45171914f }, { -0.158086f, -0.049098981f, -0.17226122f, -0.50289857f }, { -0.39456648f, 0.031970902f, -0.74883626f, 0.20536003f }, { 0.22864705f, -0.0095988927f, -0.1155595f, -0.06240073f }, { 0.12336497f, -0.34128076f, 0.34341316f, 0.083678547f }, { -0.032718317f, 0.076359349f, -0.30099369f, -0.016865529f }, { -0.23491753f, -0.17228011f, -0.044893186f, -0.057411459f }, { -0.0077848677f, 0.0f, 0.0f, 0.0f }, { -0.18713605f, -0.11612415f, 0.30907006f, 0.064707406f } }, { { -0.20768494f, -0.15642062f, -0.079474216f, -0.020948121f }, { -0.18767308f, -0.013722599f, 0.15827086f, -0.27421942f }, { -0.11484158f, -0.29325715f, 0.24426149f, 0.34598577f }, { -0.095599056f, 0.16784413f, 0.23369965f, 0.15036114f }, { 0.058496274f, -0.064565923f, -0.076598803f, -0.11988702f }, { -0.03406356f, -0.010863931f, -0.036116475f, 0.0077051595f }, { 0.0f, -0.015078298f, 0.0f, 0.0f }, { -0.21271534f, 0.31678528f, 0.084310434f, -0.039787477f }, { 0.057420352f, -0.60894321f, -0.14275706f, -0.29178151f }, { -0.21477227f, 0.091254596f, -0.053659362f, -0.13299553f }, { -0.24972574f, 0.22261101f, -0.59415755f, -0.13299464f }, { -0.406027f, 0.15018847f, 0.33281927f, 0.28006105f }, { -0.033198856f, 0.013081228f, 0.0098634494f, -0.18858267f }, { -0.16914457f, -0.014917022f, -0.15618156f, 0.038961385f }, { 0.0f, 0.0115085f, 0.0f, 0.0f }, { 0.047340338f, -0.052961301f, 0.30193278f, 0.38564757f }, { -0.2009302f, -0.15247105f, -0.32333852f, 0.22878398f }, { -0.22934017f, 0.022888443f, 0.30911154f, -0.12420416f }, { 0.21191356f, -0.33281926f, -0.13523708f, -0.038546557f }, { 0.28507859f, -0.012777666f, 0.16285544f, -0.12612215f }, { -0.057034227f, 0.01719448f, -0.037892291f, -0.13064036f }, { -0.075888865f, 0.041589292f, 0.0089100653f, -0.10775402f }, { 0.0075560462f, 0.0f, 0.0f, 0.0f }, { -0.18120766f, 0.16485298f, 0.58949587f, 0.072313493f } } }, { { { 0.60381773f, 0.64633179f, 0.92301353f, 0.23720177f }, { 1.1128727f, 0.42172315f, 1.6605811f, 0.22066721f }, { 0.55829912f, 0.7107351f, 0.47437673f, 0.53646626f }, { 0.75684406f, 0.65607146f, 1.5264507f, 0.12817954f }, { -0.25070514f, 0.30263175f, -0.21070678f, -0.2264813f }, { -0.24745858f, -0.26801252f, 0.2750925f, 0.055035565f }, { -0.018769156f, -0.066023008f, 0.10111114f, 0.0089232736f }, { 0.41152465f, 0.52508091f, 0.4161358f, 0.39058287f }, { 0.90919582f, 1.2448772f, 0.61547497f, 0.51303689f }, { 0.2973136f, 1.2348603f, 0.24154398f, 0.76087607f }, { 0.23369317f, 0.68368068f, 0.81024353f, 0.35451079f }, { 0.69272073f, 0.47014545f, 0.61401877f, 0.43768641f }, { -0.44449894f, -0.10123077f, -0.19173956f, -0.15811184f }, { -0.089717f, -0.068601549f, -0.16704813f, -0.29761406f }, { 0.0055968308f, -0.089855929f, -0.087150641f, 0.2244144f }, { 0.38902787f, 0.62620686f, 1.3314901f, 0.26038797f }, { 0.16776511f, 0.32722251f, 0.71914611f, 0.53556119f }, { 0.63106992f, 0.46256454f, 1.785895f, 0.17339911f }, { 0.72516261f, 0.44941094f, 0.81174974f, 0.61247129f }, { 0.56877815f, 0.20989179f, 0.7607991f, 0.017998645f }, { 0.016372087f, 0.26062407f, -0.32771461f, -0.075930098f }, { -0.11957223f, -0.22579003f, -0.42587945f, -0.0015549589f }, { 0.0049992009f, 0.053511694f, 0.00053268274f, 0.022778575f }, { 0.19356675f, 0.5564623f, 0.74981777f, 0.28733119f } }, { { 0.017029304f, 0.22690356f, 0.25927682f, -0.048136042f }, { 0.52936856f, -0.26082526f, 0.12568074f, -0.046727529f }, { 0.08949554f, -0.019090555f, 0.31477592f, -0.067513409f }, { 0.056302335f, -0.011819435f, -0.063621104f, 0.27092306f }, { 0.053971592f, -0.17913246f, -0.14991651f, -0.044263405f }, { 0.29037749f, -0.040498369f, -0.33600753f, 0.16250066f }, { -0.067102844f, -0.17843768f, 0.033172168f, 0.13638573f }, { 0.057127881f, -0.044468822f, 0.33005778f, 0.34775491f }, { -0.14300931f, 0.022121077f, -0.045281831f, -0.065216583f }, { 0.084931489f, 0.06688461f, 0.15758114f, -0.091330485f }, { -0.014274888f, 0.29139103f, 0.089163749f, -0.18005467f }, { -0.2191522f, -0.1333803f, -0.31948964f, -0.28536602f }, { 0.20298891f, -0.0031882515f, -0.15749696f, -0.014977715f }, { -0.14016857f, -0.17278064f, 0.01369474f, 0.10971499f }, { 0.018219806f, 0.080447764f, 0.0056022696f, -0.043028475f }, { -0.076556403f, -0.13038184f, -0.23788273f, 0.5849635f }, { 0.1038427f, 0.18199702f, 0.35294355f, -0.0023601311f }, { 0.22294845f, -0.37427713f, 0.2907529f, 0.26234219f }, { 0.40809306f, 0.12982813f, 0.42857338f, 0.14064303f }, { 0.4265028f, 0.18710053f, 0.15310514f, 0.067551813f }, { -0.18986488f, -0.029676062f, -0.087045959f, -0.14788626f }, { -0.07865478f, 0.011558295f, -0.018262356f, 0.38992629f }, { 0.22297641f, 0.072192947f, 0.064119712f, 0.12862555f }, { -0.069262467f, -0.14990585f, 0.31342655f, -0.15002022f } }, { { 0.25288162f, -0.096551539f, 0.051695506f, 0.20925392f }, { 0.23093904f, 0.096712594f, 0.19826434f, 0.32530694f }, { 0.14114785f, 0.071010138f, -0.17642029f, 0.092260082f }, { 0.39001648f, -0.17666595f, 0.088397252f, 0.1462816f }, { 0.12484597f, 0.066920676f, -0.16116194f, 0.21758387f }, { 0.15625272f, -0.00043631439f, -0.07868976f, -0.19261141f }, { -0.0142415f, 0.06356153f, 0.026276923f, -0.024546668f }, { 0.097089221f, 0.085426402f, 0.11936115f, 0.012042542f }, { 0.52509109f, -0.22465399f, -0.11490612f, 0.023562122f }, { -0.12418278f, 0.11985465f, 0.087804943f, 0.25283464f }, { 0.10716753f, -0.036426901f, 0.2469409f, -0.095816257f }, { -0.095364501f, 0.14001518f, -0.068636804f, -0.082487255f }, { 0.074490355f, 0.25323233f, 0.17863748f, 0.12482145f }, { -0.019616587f, -0.0053326518f, 0.047558858f, 0.066104462f }, { 0.12647102f, 0.25712368f, 0.12306783f, -0.050252261f }, { -0.13375041f, 0.17825067f, 0.026649645f, -0.33338076f }, { 0.16384463f, -0.022241979f, 0.17817325f, 0.6808721f }, { 0.42075944f, -0.024292721f, -0.11323318f, 0.45027063f }, { -0.023953485f, 0.25719992f, 0.28680108f, 0.33600529f }, { 0.013445546f, 0.22504275f, 0.17408162f, 0.52860686f }, { -0.098839039f, -0.27017244f, 0.10293505f, -0.012472685f }, { 0.074267375f, -0.0056418849f, 0.17632358f, 0.21754089f }, { 0.1491061f, 0.017927571f, -0.0217757f, -0.0039381966f }, { 0.067239102f, -0.74624136f, 0.12992555f, -0.058866581f } } } }, { { { { 0.1270204f, 0.7650174f, 0.55252173f, 0.05956498f }, { -0.36870832f, 0.31227245f, 0.52167466f, 0.4282174f }, { -0.036761861f, -0.5477415f, -0.76091563f, -0.37583127f }, { 0.17129434f, -0.14281209f, -0.40463148f, -0.56367877f }, { 0.07429238f, 0.45420144f, 0.41919765f, 0.019225986f }, { -0.44125436f, -0.05567539f, 0.080551064f, 0.54444995f }, { -0.36600455f, -0.55359309f, -0.3290331f, 0.33946169f }, { 0.65253747f, 0.015186649f, 0.0665303f, -0.64649501f }, { 0.05392469f, 0.54355001f, 0.7539307f, -0.41089455f }, { -0.29264863f, 0.49684721f, 0.39184208f, 0.47737193f }, { 0.10885354f, -0.80803227f, -0.7443769f, -0.3736688f }, { 0.1939378f, -0.079590275f, -0.42241709f, -0.75536039f }, { 0.44776697f, 0.44884546f, 0.427965f, 0.3297221f }, { -0.34595785f, 0.27723463f, 0.12245317f, 0.43884357f }, { 0.18467758f, -0.55582608f, -0.99421464f, -0.0096027817f }, { 0.6672057f, -0.038103784f, -0.048616141f, -0.68508055f }, { -0.016615937f, 0.62001729f, 0.50530563f, -0.22211425f }, { -0.16823123f, 0.31934529f, 0.47092187f, 0.4884373f }, { 0.03194189f, -0.5624624f, -0.44688229f, 0.223814f }, { 0.17828041f, -0.080017082f, -0.44239439f, -0.46726625f }, { 0.19895649f, 0.82568772f, 0.47859751f, 0.064443297f }, { -0.47464217f, 0.011895223f, 0.01123465f, -0.010697203f }, { -0.17670677f, -0.66931423f, -0.5814681f, -0.01325001f }, { 0.65193874f, -0.010713062f, -0.007915928f, -0.65520853f } }, { { -0.01027431f, -0.0019056004f, 0.0020213958f, 0.0064495753f }, { 0.0058416688f, 0.0051314639f, 0.021497114f, 0.005870592f }, { -0.00035518612f, -0.00087553938f, -0.0029318969f, 0.0087577986f }, { -0.0048770476f, -0.015949665f, -0.034816051f, -0.006104917f }, { 0.0015371362f, -0.0012591621f, 0.01241148f, 0.00096621463f }, { 0.0032416133f, 0.021025709f, 0.0036344622f, 0.0015436078f }, { -0.0093946276f, 0.0046564763f, 0.028177476f, -0.01022744f }, { 0.00014675555f, 0.030031482f, -0.0092302407f, -0.001999398f }, { -0.049980321f, 0.024752279f, 0.016684689f, -0.0045230976f }, { 0.0067493834f, 0.014071508f, 0.0079316435f, 0.034593704f }, { 0.01971715f, -0.0037227013f, -0.013430278f, -0.024257585f }, { -0.004342319f, 0.024001878f, -0.013356442f, -0.022792018f }, { -0.0051709665f, -0.017029547f, 0.040567567f, 0.0052520812f }, { 0.0090399102f, 0.0079604733f, 0.00018765016f, -0.0092868977f }, { -0.020304032f, 0.0056590257f, -0.0045373063f, -0.018653318f }, { -9.9636934e-05f, 0.002001886f, 0.0046843544f, 0.0055608043f }, { 0.0018025744f, -0.0025962216f, 0.0068285574f, -0.014851062f }, { 0.00041645221f, 0.0054738242f, 0.0076769026f, -0.013419208f }, { 0.0038347099f, -0.0042555066f, -0.0066470075f, 0.0039146778f }, { -0.009084153f, 0.024461537f, 0.0034578066f, -0.0054827001f }, { 0.0033463477f, 0.0045594748f, 0.00037604935f, -0.01571513f }, { -0.012589588f, 0.029678359f, -0.019924871f, -0.004708459f }, { -0.0002642682f, -0.0051057336f, -0.0042867302f, -0.00041141781f }, { -0.00086487068f, -0.0025170841f, 0.0030062196f, -0.0030385417f } }, { { -0.01027431f, -0.0019056004f, 0.0020213958f, 0.0064495753f }, { 0.0058416688f, 0.0051314639f, 0.021497114f, 0.005870592f }, { -0.00035518612f, -0.00087553938f, -0.0029318969f, 0.0087577986f }, { -0.0048770476f, -0.015949665f, -0.034816051f, -0.006104917f }, { 0.0015371362f, -0.0012591621f, 0.01241148f, 0.00096621463f }, { 0.0032416133f, 0.021025709f, 0.0036344622f, 0.0015436078f }, { -0.0093946276f, 0.0046564763f, 0.028177476f, -0.01022744f }, { 0.00014675555f, 0.030031482f, -0.0092302407f, -0.001999398f }, { -0.049980321f, 0.024752279f, 0.016684689f, -0.0045230976f }, { 0.0067493834f, 0.014071508f, 0.0079316435f, 0.034593704f }, { 0.01971715f, -0.0037227013f, -0.013430278f, -0.024257585f }, { -0.004342319f, 0.024001878f, -0.013356442f, -0.022792018f }, { -0.0051709665f, -0.017029547f, 0.040567567f, 0.0052520812f }, { 0.0090399102f, 0.0079604733f, 0.00018765016f, -0.0092868977f }, { -0.020304032f, 0.0056590257f, -0.0045373063f, -0.018653318f }, { -9.9636934e-05f, 0.002001886f, 0.0046843544f, 0.0055608043f }, { 0.0018025744f, -0.0025962216f, 0.0068285574f, -0.014851062f }, { 0.00041645221f, 0.0054738242f, 0.0076769026f, -0.013419208f }, { 0.0038347099f, -0.0042555066f, -0.0066470075f, 0.0039146778f }, { -0.009084153f, 0.024461537f, 0.0034578066f, -0.0054827001f }, { 0.0033463477f, 0.0045594748f, 0.00037604935f, -0.01571513f }, { -0.012589588f, 0.029678359f, -0.019924871f, -0.004708459f }, { -0.0002642682f, -0.0051057336f, -0.0042867302f, -0.00041141781f }, { -0.00086487068f, -0.0025170841f, 0.0030062196f, -0.0030385417f } } }, { { { -0.68772793f, 0.19029367f, -0.17427646f, 0.60300616f }, { -0.29980532f, -0.22397537f, -0.4071009f, 0.36277983f }, { 0.75628069f, -0.13426242f, 0.13645381f, -0.74653491f }, { 0.14891408f, -0.13497977f, 0.36807879f, -0.39814386f }, { -0.20608987f, -0.076497863f, -0.19510375f, 0.34604256f }, { -0.02421123f, -0.4588774f, -0.64965351f, 0.083039161f }, { 0.51918764f, -0.30614677f, -0.25791921f, -0.40837612f }, { 0.028860181f, 0.63152733f, 0.5876224f, -0.033139773f }, { -0.63418144f, 0.046874151f, 0.24431924f, 0.71662556f }, { -0.29088451f, -0.21455586f, -0.73980807f, 0.65038559f }, { 0.78663226f, 0.00020858525f, 0.40361403f, -0.75720144f }, { 0.1998276f, 0.54590973f, 0.1773378f, -0.35464319f }, { -0.40236144f, 0.31362578f, -0.34406026f, 0.38120073f }, { -0.27845549f, -0.46862161f, -0.47141499f, 0.095899189f }, { 0.6004921f, 0.28051621f, -0.011378178f, -0.98141078f }, { 0.032724674f, 0.66798127f, 0.66430425f, -0.05209965f }, { -0.59603974f, -0.083198329f, 0.34616224f, 0.42082916f }, { -0.14262632f, -0.21418442f, -0.37504914f, 0.32676687f }, { 0.58204273f, 0.0067537174f, -0.35923481f, -0.40792038f }, { 0.15607366f, 0.17215007f, 0.34414936f, -0.33566945f }, { -0.44862333f, 0.004919013f, 0.0076768115f, 0.41897935f }, { -0.022062848f, -0.39695079f, -0.0062786656f, 0.042925103f }, { 0.65953535f, -0.15521993f, 0.011867978f, -0.57721165f }, { 0.031305912f, 0.65627006f, 0.66779002f, -0.029815636f } }, { { 0.011457792f, -0.011774949f, -0.012205337f, 0.0048139052f }, { -0.024024566f, 0.018313023f, -0.023210623f, -0.0046351547f }, { 0.0039133571f, 0.0046801024f, -0.020590099f, -0.0018568631f }, { -0.015369931f, -0.0092621276f, -0.026149742f, 0.0010335971f }, { 0.032555144f, -0.01336897f, -0.022733265f, -0.027997469f }, { -0.028161537f, -0.00073877629f, -0.023989631f, 0.0055660453f }, { -0.012966193f, 0.003944376f, 0.025685982f, -0.0017458044f }, { 0.00015626641f, -0.009524206f, 0.0083025026f, -0.00049753811f }, { -0.02358661f, 0.006370149f, 0.00087066462f, -0.00054248544f }, { -0.0024571244f, -0.023218369f, -0.010895303f, -0.0095647684f }, { 0.0069970393f, -0.00093403301f, -0.0081922371f, -0.00026359768f }, { 0.0065921354f, 0.028846533f, -0.045676337f, 0.006070217f }, { 0.0045248423f, -0.0084676847f, 0.028756195f, 0.020612871f }, { 0.0037691244f, -0.0069385161f, -0.00029501448f, -0.0017839033f }, { -0.0048675353f, -0.011930456f, 0.0044251285f, -0.00016323616f }, { -0.0012291164f, -0.0019575288f, 0.0078250029f, -0.0011151155f }, { 0.00503333f, -0.0094538968f, 0.0092375183f, 0.018207648f }, { 0.0080615812f, -0.0073583459f, -0.0166794f, 0.016416158f }, { 0.002192959f, -0.01153759f, -0.0048668362f, -0.0071123281f }, { -0.010116143f, -0.010224552f, 0.010897731f, 0.00093792816f }, { 0.017199359f, -0.0087516179f, 0.0021169251f, -0.020946959f }, { -0.01570063f, 0.020087246f, 0.014492818f, -0.016014018f }, { 0.0023484072f, 0.0015070243f, -0.00045616273f, -0.001211882f }, { 0.0018090492f, -0.0012261901f, 0.0012809284f, 0.00096488905f } }, { { 0.011457792f, -0.011774949f, -0.012205337f, 0.0048139052f }, { -0.024024566f, 0.018313023f, -0.023210623f, -0.0046351547f }, { 0.0039133571f, 0.0046801024f, -0.020590099f, -0.0018568631f }, { -0.015369931f, -0.0092621276f, -0.026149742f, 0.0010335971f }, { 0.032555144f, -0.01336897f, -0.022733265f, -0.027997469f }, { -0.028161537f, -0.00073877629f, -0.023989631f, 0.0055660453f }, { -0.012966193f, 0.003944376f, 0.025685982f, -0.0017458044f }, { 0.00015626641f, -0.009524206f, 0.0083025026f, -0.00049753811f }, { -0.02358661f, 0.006370149f, 0.00087066462f, -0.00054248544f }, { -0.0024571244f, -0.023218369f, -0.010895303f, -0.0095647684f }, { 0.0069970393f, -0.00093403301f, -0.0081922371f, -0.00026359768f }, { 0.0065921354f, 0.028846533f, -0.045676337f, 0.006070217f }, { 0.0045248423f, -0.0084676847f, 0.028756195f, 0.020612871f }, { 0.0037691244f, -0.0069385161f, -0.00029501448f, -0.0017839033f }, { -0.0048675353f, -0.011930456f, 0.0044251285f, -0.00016323616f }, { -0.0012291164f, -0.0019575288f, 0.0078250029f, -0.0011151155f }, { 0.00503333f, -0.0094538968f, 0.0092375183f, 0.018207648f }, { 0.0080615812f, -0.0073583459f, -0.0166794f, 0.016416158f }, { 0.002192959f, -0.01153759f, -0.0048668362f, -0.0071123281f }, { -0.010116143f, -0.010224552f, 0.010897731f, 0.00093792816f }, { 0.017199359f, -0.0087516179f, 0.0021169251f, -0.020946959f }, { -0.01570063f, 0.020087246f, 0.014492818f, -0.016014018f }, { 0.0023484072f, 0.0015070243f, -0.00045616273f, -0.001211882f }, { 0.0018090492f, -0.0012261901f, 0.0012809284f, 0.00096488905f } } }, { { { 0.71476997f, 0.61525336f, 0.81507512f, 0.79550964f }, { 0.87986984f, 0.9232123f, 0.74974956f, 0.82765975f }, { 0.65321366f, 0.82580437f, 0.63434042f, 0.54903231f }, { 0.97390084f, 0.98050251f, 0.83713283f, 0.72370416f }, { 0.97570877f, 0.88760866f, 0.88668363f, 0.9380218f }, { 0.89705541f, 0.88675351f, 0.75595095f, 0.83467284f }, { 0.77232433f, 0.77447327f, 0.9084134f, 0.84734569f }, { -0.75720667f, -0.77520488f, -0.80639546f, -0.76219811f }, { 0.77130152f, 0.83806694f, 0.60983327f, 0.56357207f }, { 0.91090229f, 0.84089752f, 0.54694041f, 0.59085922f }, { 0.60775044f, 0.58913818f, 0.53197627f, 0.53574024f }, { 0.96044628f, 0.83405513f, 0.88888419f, 0.55105253f }, { 0.79850486f, 0.83676557f, 0.83574428f, 0.86369517f }, { 0.89597751f, 0.83876978f, 0.87336884f, 0.8934314f }, { 0.77801249f, 0.78253947f, 0.10680725f, 0.19167855f }, { -0.74415432f, -0.74320194f, -0.74587957f, -0.72660186f }, { 0.802783f, 0.78016447f, 0.79046691f, 0.87952719f }, { 0.97537479f, 0.92311625f, 0.79848027f, 0.80910594f }, { 0.8125306f, 0.82679528f, 0.81929639f, 0.88516002f }, { 0.97152309f, 0.98181547f, 0.82815966f, 0.81791703f }, { 0.87129411f, 0.56410602f, 0.87800085f, 0.905706f }, { 0.87990229f, 0.91776281f, 0.99991718f, 0.99902102f }, { 0.73060786f, 0.72658464f, 0.81348263f, 0.81648708f }, { -0.75762512f, -0.75445002f, -0.74430762f, -0.75485946f } }, { { 0.018332644f, 0.0084005452f, -0.0018937689f, -0.0035491975f }, { 0.0016556654f, 0.0049261013f, -0.021796869f, 0.0025973591f }, { -0.0019671758f, 0.00051947074f, 0.0071261223f, 0.0056689139f }, { 0.00041901024f, -0.0023903288f, -0.0035639711f, -0.0036673013f }, { 0.009963464f, 0.00099195429f, -0.0042516892f, 0.0092605531f }, { 0.0034813664f, 0.0028575465f, -0.016343415f, -0.0014475905f }, { 0.0053571039f, 0.0051116063f, 0.016171091f, -0.00052744238f }, { 0.00013272575f, -0.0095491849f, 0.0070156475f, 0.0017057538f }, { 0.028067438f, -0.0086835729f, -0.0087852674f, 0.0035321054f }, { 0.0025007808f, -0.0075654884f, -0.012551417f, -0.0068823899f }, { -0.00017607308f, 0.002636122f, -0.011272055f, -0.010314896f }, { 0.010646599f, 0.00042804331f, 0.013900837f, -0.01279076f }, { 0.0059898286f, 0.012331371f, -0.0073125296f, 0.016248603f }, { 0.031579315f, -0.0057840222f, -0.00018304192f, 0.005171422f }, { 0.010928513f, 0.0092660887f, 0.030404621f, 0.0053167707f }, { -0.00014899672f, -0.0035246494f, 0.0075862845f, -0.005861723f }, { 0.0067791918f, 0.0021224495f, -0.0071755505f, -0.010370936f }, { 0.0015352958f, -0.0025785166f, -0.0092688001f, 0.003966373f }, { 0.0036915074f, -0.002306452f, -0.005736452f, -0.0033594125f }, { 0.0065128512f, 0.006188005f, 0.00088322638f, -0.0016227066f }, { 0.0092720771f, -0.0046684631f, -7.3769604e-05f, 0.013807013f }, { -0.0031421984f, 0.010622679f, 0.00041591214f, 0.0032786075f }, { -0.0021421613f, -0.0041675589f, -0.0029529994f, -0.00085350449f }, { -0.00069204344f, -0.0010785124f, 0.00097549628f, 0.0025280456f } }, { { 0.018332644f, 0.0084005452f, -0.0018937689f, -0.0035491975f }, { 0.0016556654f, 0.0049261013f, -0.021796869f, 0.0025973591f }, { -0.0019671758f, 0.00051947074f, 0.0071261223f, 0.0056689139f }, { 0.00041901024f, -0.0023903288f, -0.0035639711f, -0.0036673013f }, { 0.009963464f, 0.00099195429f, -0.0042516892f, 0.0092605531f }, { 0.0034813664f, 0.0028575465f, -0.016343415f, -0.0014475905f }, { 0.0053571039f, 0.0051116063f, 0.016171091f, -0.00052744238f }, { 0.00013272575f, -0.0095491849f, 0.0070156475f, 0.0017057538f }, { 0.028067438f, -0.0086835729f, -0.0087852674f, 0.0035321054f }, { 0.0025007808f, -0.0075654884f, -0.012551417f, -0.0068823899f }, { -0.00017607308f, 0.002636122f, -0.011272055f, -0.010314896f }, { 0.010646599f, 0.00042804331f, 0.013900837f, -0.01279076f }, { 0.0059898286f, 0.012331371f, -0.0073125296f, 0.016248603f }, { 0.031579315f, -0.0057840222f, -0.00018304192f, 0.005171422f }, { 0.010928513f, 0.0092660887f, 0.030404621f, 0.0053167707f }, { -0.00014899672f, -0.0035246494f, 0.0075862845f, -0.005861723f }, { 0.0067791918f, 0.0021224495f, -0.0071755505f, -0.010370936f }, { 0.0015352958f, -0.0025785166f, -0.0092688001f, 0.003966373f }, { 0.0036915074f, -0.002306452f, -0.005736452f, -0.0033594125f }, { 0.0065128512f, 0.006188005f, 0.00088322638f, -0.0016227066f }, { 0.0092720771f, -0.0046684631f, -7.3769604e-05f, 0.013807013f }, { -0.0031421984f, 0.010622679f, 0.00041591214f, 0.0032786075f }, { -0.0021421613f, -0.0041675589f, -0.0029529994f, -0.00085350449f }, { -0.00069204344f, -0.0010785124f, 0.00097549628f, 0.0025280456f } } }, { { { 5.3792285f, 5.1960477f, 5.5112916f, 5.6615254f }, { 5.0489877f, 5.2428834f, 5.1752035f, 5.1109826f }, { 5.5205204f, 5.7511938f, 5.0202917f, 4.9168865f }, { 4.9522523f, 4.8880256f, 5.1015936f, 5.2858816f }, { 5.7256502f, 5.7919759f, 5.645241f, 5.6035708f }, { 6.4076931f, 6.4822111f, 6.2642633f, 6.3925959f }, { 6.9797014f, 6.981436f, 7.0028674f, 6.9976464f }, { -0.03290957f, -0.03290957f, -0.03290957f, -0.03290957f }, { 5.4977854f, 5.7684965f, 5.3463095f, 4.8810492f }, { 4.9869047f, 5.4896416f, 4.9647805f, 4.884877f }, { 5.3141219f, 5.3357788f, 4.7695434f, 4.8709631f }, { 5.2056063f, 5.407802f, 5.2123857f, 4.9428208f }, { 6.2188218f, 6.17756f, 6.2751008f, 6.3672109f }, { 6.9105856f, 6.7986798f, 6.5712335f, 6.5907061f }, { 6.9797014f, 6.9797014f, 5.6859993f, 5.5642483f }, { -0.032764603f, -0.032764603f, -0.032764603f, -0.032764603f }, { 5.7724142f, 6.0929556f, 5.99581f, 5.9265164f }, { 4.9363192f, 4.9823732f, 5.1732995f, 5.2475265f }, { 5.8365191f, 5.9972902f, 5.9778441f, 5.9270668f }, { 4.8706768f, 5.0194503f, 5.155585f, 5.2188041f }, { 6.1569904f, 6.0563989f, 6.0989699f, 6.2139837f }, { 5.8727399f, 5.8948086f, 5.5734095f, 5.5536103f }, { 6.9797014f, 6.9797014f, 6.9797014f, 6.9797014f }, { -0.032766769f, -0.032766769f, -0.032766769f, -0.032766769f } }, { { 0.0011802354f, -0.006546101f, -0.02103972f, 0.0008654047f }, { -0.015460534f, 0.017874544f, 0.0029121134f, 0.023511773f }, { -0.040909245f, 0.011927691f, 0.011991588f, 0.01677931f }, { -0.015633544f, -0.0042321141f, 0.026623034f, 0.0080414514f }, { 0.012614382f, 0.0065080145f, 0.035716738f, -0.0080665814f }, { -0.0057849744f, -0.017478461f, -0.031219642f, 0.00016446523f }, { 0.0f, 0.00032235028f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.068586697f, -0.024228236f, -0.012857221f, -0.039493706f }, { -0.018078201f, -0.015140979f, 0.00072119173f, -0.051249859f }, { -0.054228277f, 0.0097895101f, 0.0019832646f, -0.011715411f }, { -0.042326208f, -0.010160072f, 0.037088052f, -0.031848667f }, { 0.00067130897f, -0.013966717f, -0.017268559f, -0.0074614576f }, { 0.070515961f, 0.012848107f, -0.0008396517f, 0.0049006506f }, { 0.0f, 0.0f, -0.063014256f, -0.0085124986f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.040302299f, 0.0048936307f, 0.0064406394f, 0.0034044871f }, { -0.010453589f, 0.0035820836f, -0.017384391f, -0.038199947f }, { -0.044968611f, -0.0088322127f, 0.020303819f, 0.0058131005f }, { -0.0056838535f, 0.010211409f, -0.010999927f, -0.027621859f }, { 0.0064753811f, -0.0059341242f, -0.014902755f, 0.0082868118f }, { -0.0013222735f, 0.0028492181f, -0.023523273f, -0.02576271f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f } }, { { 0.0011802354f, -0.006546101f, -0.02103972f, 0.00086540469f }, { -0.015460534f, 0.017874544f, 0.0029121134f, 0.023511773f }, { -0.040909245f, 0.011927691f, 0.011991588f, 0.01677931f }, { -0.015633544f, -0.0042321141f, 0.026623034f, 0.0080414514f }, { 0.012614382f, 0.0065080145f, 0.035716738f, -0.0080665814f }, { -0.0057849744f, -0.017478461f, -0.031219642f, 0.00016446523f }, { 0.0f, 0.00032235028f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.068586697f, -0.024228236f, -0.012857221f, -0.039493706f }, { -0.018078201f, -0.015140979f, 0.00072119173f, -0.051249859f }, { -0.054228277f, 0.0097895101f, 0.0019832646f, -0.011715411f }, { -0.042326208f, -0.010160072f, 0.037088052f, -0.031848667f }, { 0.00067130897f, -0.013966717f, -0.017268559f, -0.0074614576f }, { 0.070515961f, 0.012848107f, -0.0008396517f, 0.0049006506f }, { 0.0f, 0.0f, -0.063014256f, -0.0085124986f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.040302299f, 0.0048936307f, 0.0064406394f, 0.0034044871f }, { -0.010453589f, 0.0035820836f, -0.017384391f, -0.038199947f }, { -0.044968611f, -0.0088322127f, 0.020303819f, 0.0058131005f }, { -0.0056838535f, 0.010211409f, -0.010999927f, -0.027621859f }, { 0.0064753811f, -0.0059341242f, -0.014902755f, 0.0082868118f }, { -0.0013222735f, 0.0028492181f, -0.023523273f, -0.02576271f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f } } }, { { { 0.72189984f, 0.22069996f, 0.71952927f, 0.77725949f }, { 0.4054405f, 0.20582059f, 0.2747016f, 0.37612563f }, { 0.58887422f, 0.27441131f, 0.19468101f, 0.21480554f }, { 0.46814145f, 0.34317f, 0.46068212f, 0.13962064f }, { -0.18134132f, -0.26668789f, -0.60984999f, -0.67879259f }, { -0.47870351f, -0.34453227f, 0.32494779f, 0.10292971f }, { 0.087252967f, 0.066950358f, 0.31813819f, 0.071094818f }, { -0.0031436256f, 0.038245091f, -0.0076651913f, -0.015389479f }, { 1.2668531f, 1.2894974f, 0.40584018f, 0.51755806f }, { 1.3207257f, 1.3403747f, 0.54924634f, 0.40282713f }, { 0.78581828f, 0.56379328f, 0.27901993f, 0.56429306f }, { 0.8748226f, 1.0271253f, 1.0085726f, 0.3888545f }, { -0.22577636f, -0.32895071f, -0.2846317f, -0.11679531f }, { 0.26477285f, 0.3179447f, -0.063393238f, 0.024059773f }, { -0.15463395f, -0.22721468f, -0.20680404f, -0.15700788f }, { 0.012107106f, -0.0061245949f, -0.024224367f, 0.005040693f }, { 0.97943693f, 0.64840429f, 0.45106998f, 0.40771935f }, { 0.49907853f, 0.1562184f, 0.34338458f, 0.39710628f }, { 0.95047709f, 0.53336107f, 0.38318275f, 0.44919148f }, { 0.41892697f, 0.069965886f, 0.45831656f, 0.38821529f }, { -0.20216736f, -0.43209441f, -0.57684857f, -0.40189427f }, { -0.63992377f, -0.40683032f, -0.59207903f, -0.57251716f }, { -0.047117438f, -0.1880015f, -0.12265155f, 0.00059988607f }, { -0.011836442f, -0.010049497f, -0.0026152072f, 0.016137736f } }, { { 0.092068993f, 0.0045466749f, 0.0054574031f, 0.02582156f }, { 0.022115456f, -0.015664041f, -0.022004653f, 0.041431654f }, { 0.029951298f, -0.0004408542f, 0.0087496069f, 0.017850027f }, { 0.029086373f, 0.022116039f, 0.044010315f, 0.001644876f }, { 0.016256387f, 0.0083249367f, 0.019570849f, -0.0021276222f }, { 0.0079070076f, -0.024696939f, 0.044311101f, 0.023671132f }, { -0.0081796119f, -0.0024995551f, 0.033501743f, -0.031958988f }, { 0.0065005403f, -0.076642001f, 0.015736477f, 0.030966939f }, { 0.029110717f, 0.039154477f, -0.074376619f, 0.025532063f }, { -0.10980761f, 0.0038346834f, 0.014449171f, -0.030702653f }, { -0.00068350423f, -0.037251569f, -0.008409224f, -0.026322878f }, { 0.035406012f, 0.064176275f, 0.031437854f, -0.0344642f }, { 0.037145809f, -0.024909212f, 0.041030386f, 0.035216105f }, { -0.093276646f, -0.013904083f, -0.019536023f, -0.023834405f }, { 0.042751846f, -0.03620164f, 0.081115921f, 0.018379967f }, { -0.023909625f, 0.012833691f, 0.048086442f, -0.0097340268f }, { 0.039552712f, -0.00026806514f, 0.011646753f, 0.0065939486f }, { 0.058985248f, 0.020165701f, 0.0076721521f, 0.033274221f }, { 0.052889871f, 0.0042520093f, 0.016490396f, 0.009287973f }, { 0.044305975f, -0.0016263469f, 0.041390177f, 0.033541355f }, { 0.014595133f, -0.004801042f, -0.0049517302f, 0.015714264f }, { 0.00075086205f, 0.0080838736f, -0.037611057f, -0.030488441f }, { 0.0019178075f, -0.0082517768f, -0.002525773f, 0.0043993022f }, { 0.023774971f, 0.020335611f, 0.0056643868f, -0.032100338f } }, { { 0.092068993f, 0.0045466749f, 0.0054574031f, 0.02582156f }, { 0.022115456f, -0.015664041f, -0.022004653f, 0.041431654f }, { 0.029951298f, -0.0004408542f, 0.0087496069f, 0.017850027f }, { 0.029086373f, 0.022116039f, 0.044010315f, 0.001644876f }, { 0.016256387f, 0.0083249367f, 0.019570849f, -0.0021276222f }, { 0.0079070076f, -0.024696939f, 0.044311101f, 0.023671132f }, { -0.0081796119f, -0.0024995551f, 0.033501743f, -0.031958988f }, { 0.0065005403f, -0.076642001f, 0.015736477f, 0.030966939f }, { 0.029110717f, 0.039154477f, -0.074376619f, 0.025532063f }, { -0.10980761f, 0.0038346834f, 0.014449171f, -0.030702653f }, { -0.00068350423f, -0.037251569f, -0.008409224f, -0.026322878f }, { 0.035406012f, 0.064176275f, 0.031437854f, -0.0344642f }, { 0.037145809f, -0.024909212f, 0.041030386f, 0.035216105f }, { -0.093276646f, -0.013904083f, -0.019536023f, -0.023834405f }, { 0.042751846f, -0.03620164f, 0.081115921f, 0.018379967f }, { -0.023909625f, 0.012833691f, 0.048086442f, -0.0097340268f }, { 0.039552712f, -0.00026806514f, 0.011646753f, 0.0065939486f }, { 0.058985248f, 0.020165701f, 0.0076721521f, 0.033274221f }, { 0.052889871f, 0.0042520093f, 0.016490396f, 0.009287973f }, { 0.044305975f, -0.0016263469f, 0.041390177f, 0.033541355f }, { 0.014595133f, -0.004801042f, -0.0049517303f, 0.015714264f }, { 0.00075086205f, 0.0080838736f, -0.037611057f, -0.030488441f }, { 0.0019178075f, -0.0082517768f, -0.002525773f, 0.0043993022f }, { 0.023774971f, 0.020335611f, 0.0056643868f, -0.032100338f } } } } };
+
+#endif
diff --git a/thirdparty/misc/curl_hostcheck.c b/thirdparty/misc/curl_hostcheck.c
deleted file mode 100644
index feef232619..0000000000
--- a/thirdparty/misc/curl_hostcheck.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-/* This file is an amalgamation of hostcheck.c and most of rawstr.c
- from cURL. The contents of the COPYING file mentioned above are:
-
-COPYRIGHT AND PERMISSION NOTICE
-
-Copyright (c) 1996 - 2013, Daniel Stenberg, <daniel@haxx.se>.
-
-All rights reserved.
-
-Permission to use, copy, modify, and distribute this software for any purpose
-with or without fee is hereby granted, provided that the above copyright
-notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
-NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
-OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of a copyright holder shall not
-be used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization of the copyright holder.
-*/
-
-#include "curl_hostcheck.h"
-#include <string.h>
-
-/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
- its behavior is altered by the current locale. */
-static char Curl_raw_toupper(char in)
-{
- switch (in) {
- case 'a':
- return 'A';
- case 'b':
- return 'B';
- case 'c':
- return 'C';
- case 'd':
- return 'D';
- case 'e':
- return 'E';
- case 'f':
- return 'F';
- case 'g':
- return 'G';
- case 'h':
- return 'H';
- case 'i':
- return 'I';
- case 'j':
- return 'J';
- case 'k':
- return 'K';
- case 'l':
- return 'L';
- case 'm':
- return 'M';
- case 'n':
- return 'N';
- case 'o':
- return 'O';
- case 'p':
- return 'P';
- case 'q':
- return 'Q';
- case 'r':
- return 'R';
- case 's':
- return 'S';
- case 't':
- return 'T';
- case 'u':
- return 'U';
- case 'v':
- return 'V';
- case 'w':
- return 'W';
- case 'x':
- return 'X';
- case 'y':
- return 'Y';
- case 'z':
- return 'Z';
- }
- return in;
-}
-
-/*
- * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant
- * to be locale independent and only compare strings we know are safe for
- * this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
- * some further explanation to why this function is necessary.
- *
- * The function is capable of comparing a-z case insensitively even for
- * non-ascii.
- */
-
-static int Curl_raw_equal(const char *first, const char *second)
-{
- while(*first && *second) {
- if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
- /* get out of the loop as soon as they don't match */
- break;
- first++;
- second++;
- }
- /* we do the comparison here (possibly again), just to make sure that if the
- loop above is skipped because one of the strings reached zero, we must not
- return this as a successful match */
- return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
-}
-
-static int Curl_raw_nequal(const char *first, const char *second, size_t max)
-{
- while(*first && *second && max) {
- if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
- break;
- }
- max--;
- first++;
- second++;
- }
- if(0 == max)
- return 1; /* they are equal this far */
-
- return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
-}
-
-/*
- * Match a hostname against a wildcard pattern.
- * E.g.
- * "foo.host.com" matches "*.host.com".
- *
- * We use the matching rule described in RFC6125, section 6.4.3.
- * http://tools.ietf.org/html/rfc6125#section-6.4.3
- */
-
-static int hostmatch(const char *hostname, const char *pattern)
-{
- const char *pattern_label_end, *pattern_wildcard, *hostname_label_end;
- int wildcard_enabled;
- size_t prefixlen, suffixlen;
- pattern_wildcard = strchr(pattern, '*');
- if(pattern_wildcard == NULL)
- return Curl_raw_equal(pattern, hostname) ?
- CURL_HOST_MATCH : CURL_HOST_NOMATCH;
-
- /* We require at least 2 dots in pattern to avoid too wide wildcard
- match. */
- wildcard_enabled = 1;
- pattern_label_end = strchr(pattern, '.');
- if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL ||
- pattern_wildcard > pattern_label_end ||
- Curl_raw_nequal(pattern, "xn--", 4)) {
- wildcard_enabled = 0;
- }
- if(!wildcard_enabled)
- return Curl_raw_equal(pattern, hostname) ?
- CURL_HOST_MATCH : CURL_HOST_NOMATCH;
-
- hostname_label_end = strchr(hostname, '.');
- if(hostname_label_end == NULL ||
- !Curl_raw_equal(pattern_label_end, hostname_label_end))
- return CURL_HOST_NOMATCH;
-
- /* The wildcard must match at least one character, so the left-most
- label of the hostname is at least as large as the left-most label
- of the pattern. */
- if(hostname_label_end - hostname < pattern_label_end - pattern)
- return CURL_HOST_NOMATCH;
-
- prefixlen = pattern_wildcard - pattern;
- suffixlen = pattern_label_end - (pattern_wildcard+1);
- return Curl_raw_nequal(pattern, hostname, prefixlen) &&
- Curl_raw_nequal(pattern_wildcard+1, hostname_label_end - suffixlen,
- suffixlen) ?
- CURL_HOST_MATCH : CURL_HOST_NOMATCH;
-}
-
-int Tool_Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
-{
- if(!match_pattern || !*match_pattern ||
- !hostname || !*hostname) /* sanity check */
- return 0;
-
- if(Curl_raw_equal(hostname, match_pattern)) /* trivial case */
- return 1;
-
- if(hostmatch(hostname,match_pattern) == CURL_HOST_MATCH)
- return 1;
- return 0;
-}
diff --git a/thirdparty/misc/curl_hostcheck.h b/thirdparty/misc/curl_hostcheck.h
deleted file mode 100644
index 1b7fbe81e3..0000000000
--- a/thirdparty/misc/curl_hostcheck.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef HEADER_TOOL_CURL_HOSTCHECK_H
-#define HEADER_TOOL_CURL_HOSTCHECK_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#define CURL_HOST_NOMATCH 0
-#define CURL_HOST_MATCH 1
-int Tool_Curl_cert_hostcheck(const char *match_pattern, const char *hostname);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HEADER_CURL_HOSTCHECK_H */
-
diff --git a/thirdparty/misc/fastlz.c b/thirdparty/misc/fastlz.c
index 508f6ea2ae..b4d2dd3c29 100644
--- a/thirdparty/misc/fastlz.c
+++ b/thirdparty/misc/fastlz.c
@@ -1,9 +1,6 @@
- /*
- FastLZ - lightning-fast lossless compression library
-
- Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
- Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
- Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+/*
+ FastLZ - Byte-aligned LZ77 compression library
+ Copyright (C) 2005-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -24,239 +21,375 @@
THE SOFTWARE.
*/
-#if !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
+#include "fastlz.h"
+
+#include <stdint.h>
/*
* Always check for bound when decompressing.
* Generally it is best to leave it defined.
*/
#define FASTLZ_SAFE
+#if defined(FASTLZ_USE_SAFE_DECOMPRESSOR) && (FASTLZ_USE_SAFE_DECOMPRESSOR == 0)
+#undef FASTLZ_SAFE
+#endif
/*
* Give hints to the compiler for branch prediction optimization.
*/
-#if defined(__GNUC__) && (__GNUC__ > 2)
-#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
-#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
+#define FASTLZ_LIKELY(c) (__builtin_expect(!!(c), 1))
+#define FASTLZ_UNLIKELY(c) (__builtin_expect(!!(c), 0))
#else
-#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
-#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
+#define FASTLZ_LIKELY(c) (c)
+#define FASTLZ_UNLIKELY(c) (c)
#endif
-/*
- * Use inlined functions for supported systems.
- */
-#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
-#define FASTLZ_INLINE inline
-#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
-#define FASTLZ_INLINE __inline
-#else
-#define FASTLZ_INLINE
+#if defined(FASTLZ_SAFE)
+#define FASTLZ_BOUND_CHECK(cond) \
+ if (FASTLZ_UNLIKELY(!(cond))) return 0;
+#else
+#define FASTLZ_BOUND_CHECK(cond) \
+ do { \
+ } while (0)
#endif
-/*
- * Prevent accessing more than 8-bit at once, except on x86 architectures.
- */
-#if !defined(FASTLZ_STRICT_ALIGN)
-#define FASTLZ_STRICT_ALIGN
-#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
-#undef FASTLZ_STRICT_ALIGN
-#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */
-#undef FASTLZ_STRICT_ALIGN
-#elif defined(_M_IX86) /* Intel, MSVC */
-#undef FASTLZ_STRICT_ALIGN
-#elif defined(__386)
-#undef FASTLZ_STRICT_ALIGN
-#elif defined(_X86_) /* MinGW */
-#undef FASTLZ_STRICT_ALIGN
-#elif defined(__I86__) /* Digital Mars */
-#undef FASTLZ_STRICT_ALIGN
-#endif
-#endif
+#define MAX_COPY 32
+#define MAX_LEN 264 /* 256 + 8 */
+#define MAX_L1_DISTANCE 8192
+#define MAX_L2_DISTANCE 8191
+#define MAX_FARDISTANCE (65535 + MAX_L2_DISTANCE - 1)
+
+#define FASTLZ_READU16(p) ((p)[0] | (p)[1] << 8)
+
+#define HASH_LOG 13
+#define HASH_SIZE (1 << HASH_LOG)
+#define HASH_MASK (HASH_SIZE - 1)
+#define HASH_FUNCTION(v, p) \
+ { \
+ v = FASTLZ_READU16(p); \
+ v ^= FASTLZ_READU16(p + 1) ^ (v >> (16 - HASH_LOG)); \
+ v &= HASH_MASK; \
+ }
-/*
- * FIXME: use preprocessor magic to set this on different platforms!
- */
-typedef unsigned char flzuint8;
-typedef unsigned short flzuint16;
-typedef unsigned int flzuint32;
+int fastlz1_compress(const void* input, int length, void* output) {
+ const uint8_t* ip = (const uint8_t*)input;
+ const uint8_t* ip_bound = ip + length - 2;
+ const uint8_t* ip_limit = ip + length - 12 - 1;
+ uint8_t* op = (uint8_t*)output;
-/* prototypes */
-int fastlz_compress(const void* input, int length, void* output);
-int fastlz_compress_level(int level, const void* input, int length, void* output);
-int fastlz_decompress(const void* input, int length, void* output, int maxout);
+ const uint8_t* htab[HASH_SIZE];
+ uint32_t hval;
-#define MAX_COPY 32
-#define MAX_LEN 264 /* 256 + 8 */
-#define MAX_DISTANCE 8192
+ uint32_t copy;
-#if !defined(FASTLZ_STRICT_ALIGN)
-#define FASTLZ_READU16(p) *((const flzuint16*)(p))
-#else
-#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
-#endif
+ /* sanity check */
+ if (FASTLZ_UNLIKELY(length < 4)) {
+ if (length) {
+ /* create literal copy only */
+ *op++ = length - 1;
+ ip_bound++;
+ while (ip <= ip_bound) *op++ = *ip++;
+ return length + 1;
+ } else
+ return 0;
+ }
-#define HASH_LOG 13
-#define HASH_SIZE (1<< HASH_LOG)
-#define HASH_MASK (HASH_SIZE-1)
-#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
-
-#undef FASTLZ_LEVEL
-#define FASTLZ_LEVEL 1
-
-#undef FASTLZ_COMPRESSOR
-#undef FASTLZ_DECOMPRESSOR
-#define FASTLZ_COMPRESSOR fastlz1_compress
-#define FASTLZ_DECOMPRESSOR fastlz1_decompress
-static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
-static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
-#include "fastlz.c"
-
-#undef FASTLZ_LEVEL
-#define FASTLZ_LEVEL 2
-
-#undef MAX_DISTANCE
-#define MAX_DISTANCE 8191
-#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
-
-#undef FASTLZ_COMPRESSOR
-#undef FASTLZ_DECOMPRESSOR
-#define FASTLZ_COMPRESSOR fastlz2_compress
-#define FASTLZ_DECOMPRESSOR fastlz2_decompress
-static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
-static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
-#include "fastlz.c"
-
-int fastlz_compress(const void* input, int length, void* output)
-{
- /* for short block, choose fastlz1 */
- if(length < 65536)
- return fastlz1_compress(input, length, output);
+ /* initializes hash table */
+ for (hval = 0; hval < HASH_SIZE; ++hval) htab[hval] = ip;
- /* else... */
- return fastlz2_compress(input, length, output);
+ /* we start with literal copy */
+ copy = 2;
+ *op++ = MAX_COPY - 1;
+ *op++ = *ip++;
+ *op++ = *ip++;
+
+ /* main loop */
+ while (FASTLZ_LIKELY(ip < ip_limit)) {
+ const uint8_t* ref;
+ uint32_t distance;
+
+ /* minimum match length */
+ uint32_t len = 3;
+
+ /* comparison starting-point */
+ const uint8_t* anchor = ip;
+
+ /* find potential match */
+ HASH_FUNCTION(hval, ip);
+ ref = htab[hval];
+
+ /* update hash table */
+ htab[hval] = anchor;
+
+ /* calculate distance to the match */
+ distance = anchor - ref;
+
+ /* is this a match? check the first 3 bytes */
+ if (distance == 0 || (distance >= MAX_L1_DISTANCE) || *ref++ != *ip++ ||
+ *ref++ != *ip++ || *ref++ != *ip++)
+ goto literal;
+
+ /* last matched byte */
+ ip = anchor + len;
+
+ /* distance is biased */
+ distance--;
+
+ if (!distance) {
+ /* zero distance means a run */
+ uint8_t x = ip[-1];
+ while (ip < ip_bound)
+ if (*ref++ != x)
+ break;
+ else
+ ip++;
+ } else
+ for (;;) {
+ /* safe because the outer check against ip limit */
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ while (ip < ip_bound)
+ if (*ref++ != *ip++) break;
+ break;
+ }
+
+ /* if we have copied something, adjust the copy count */
+ if (copy) /* copy is biased, '0' means 1 byte copy */
+ *(op - copy - 1) = copy - 1;
+ else
+ /* back, to overwrite the copy count */
+ op--;
+
+ /* reset literal counter */
+ copy = 0;
+
+ /* length is biased, '1' means a match of 3 bytes */
+ ip -= 3;
+ len = ip - anchor;
+
+ /* encode the match */
+ if (FASTLZ_UNLIKELY(len > MAX_LEN - 2))
+ while (len > MAX_LEN - 2) {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = MAX_LEN - 2 - 7 - 2;
+ *op++ = (distance & 255);
+ len -= MAX_LEN - 2;
+ }
+
+ if (len < 7) {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ } else {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = len - 7;
+ *op++ = (distance & 255);
+ }
+
+ /* update the hash at match boundary */
+ HASH_FUNCTION(hval, ip);
+ htab[hval] = ip++;
+ HASH_FUNCTION(hval, ip);
+ htab[hval] = ip++;
+
+ /* assuming literal copy */
+ *op++ = MAX_COPY - 1;
+
+ continue;
+
+ literal:
+ *op++ = *anchor++;
+ ip = anchor;
+ copy++;
+ if (FASTLZ_UNLIKELY(copy == MAX_COPY)) {
+ copy = 0;
+ *op++ = MAX_COPY - 1;
+ }
+ }
+
+ /* left-over as literal copy */
+ ip_bound++;
+ while (ip <= ip_bound) {
+ *op++ = *ip++;
+ copy++;
+ if (copy == MAX_COPY) {
+ copy = 0;
+ *op++ = MAX_COPY - 1;
+ }
+ }
+
+ /* if we have copied something, adjust the copy length */
+ if (copy)
+ *(op - copy - 1) = copy - 1;
+ else
+ op--;
+
+ return op - (uint8_t*)output;
}
-int fastlz_decompress(const void* input, int length, void* output, int maxout)
-{
- /* magic identifier for compression level */
- int level = ((*(const flzuint8*)input) >> 5) + 1;
+#if defined(FASTLZ_USE_MEMMOVE) && (FASTLZ_USE_MEMMOVE == 0)
- if(level == 1)
- return fastlz1_decompress(input, length, output, maxout);
- if(level == 2)
- return fastlz2_decompress(input, length, output, maxout);
+static void fastlz_memmove(uint8_t* dest, const uint8_t* src, uint32_t count) {
+ do {
+ *dest++ = *src++;
+ } while (--count);
+}
- /* unknown level, trigger error */
- return 0;
+static void fastlz_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count) {
+ return fastlz_memmove(dest, src, count);
}
-int fastlz_compress_level(int level, const void* input, int length, void* output)
-{
- if(level == 1)
- return fastlz1_compress(input, length, output);
- if(level == 2)
- return fastlz2_compress(input, length, output);
+#else
- return 0;
+#include <string.h>
+
+static void fastlz_memmove(uint8_t* dest, const uint8_t* src, uint32_t count) {
+ if ((count > 4) && (dest >= src + count)) {
+ memmove(dest, src, count);
+ } else {
+ switch (count) {
+ default:
+ do {
+ *dest++ = *src++;
+ } while (--count);
+ break;
+ case 3:
+ *dest++ = *src++;
+ case 2:
+ *dest++ = *src++;
+ case 1:
+ *dest++ = *src++;
+ case 0:
+ break;
+ }
+ }
+}
+
+static void fastlz_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count) {
+ memcpy(dest, src, count);
}
-#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
+#endif
-static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
-{
- const flzuint8* ip = (const flzuint8*) input;
- const flzuint8* ip_bound = ip + length - 2;
- const flzuint8* ip_limit = ip + length - 12;
- flzuint8* op = (flzuint8*) output;
+int fastlz1_decompress(const void* input, int length, void* output,
+ int maxout) {
+ const uint8_t* ip = (const uint8_t*)input;
+ const uint8_t* ip_limit = ip + length;
+ const uint8_t* ip_bound = ip_limit - 2;
+ uint8_t* op = (uint8_t*)output;
+ uint8_t* op_limit = op + maxout;
+ uint32_t ctrl = (*ip++) & 31;
+
+ while (1) {
+ if (ctrl >= 32) {
+ uint32_t len = (ctrl >> 5) - 1;
+ uint32_t ofs = (ctrl & 31) << 8;
+ const uint8_t* ref = op - ofs - 1;
+ if (len == 7 - 1) {
+ FASTLZ_BOUND_CHECK(ip <= ip_bound);
+ len += *ip++;
+ }
+ ref -= *ip++;
+ len += 3;
+ FASTLZ_BOUND_CHECK(op + len <= op_limit);
+ FASTLZ_BOUND_CHECK(ref >= (uint8_t*)output);
+ fastlz_memmove(op, ref, len);
+ op += len;
+ } else {
+ ctrl++;
+ FASTLZ_BOUND_CHECK(op + ctrl <= op_limit);
+ FASTLZ_BOUND_CHECK(ip + ctrl <= ip_limit);
+ fastlz_memcpy(op, ip, ctrl);
+ ip += ctrl;
+ op += ctrl;
+ }
- const flzuint8* htab[HASH_SIZE];
- const flzuint8** hslot;
- flzuint32 hval;
+ if (FASTLZ_UNLIKELY(ip > ip_bound)) break;
+ ctrl = *ip++;
+ }
+
+ return op - (uint8_t*)output;
+}
- flzuint32 copy;
+int fastlz2_compress(const void* input, int length, void* output) {
+ const uint8_t* ip = (const uint8_t*)input;
+ const uint8_t* ip_bound = ip + length - 2;
+ const uint8_t* ip_limit = ip + length - 12 - 1;
+ uint8_t* op = (uint8_t*)output;
+
+ const uint8_t* htab[HASH_SIZE];
+ uint32_t hval;
+
+ uint32_t copy;
/* sanity check */
- if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
- {
- if(length)
- {
+ if (FASTLZ_UNLIKELY(length < 4)) {
+ if (length) {
/* create literal copy only */
- *op++ = length-1;
+ *op++ = length - 1;
ip_bound++;
- while(ip <= ip_bound)
- *op++ = *ip++;
- return length+1;
- }
- else
+ while (ip <= ip_bound) *op++ = *ip++;
+ return length + 1;
+ } else
return 0;
}
/* initializes hash table */
- for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
- *hslot = ip;
+ for (hval = 0; hval < HASH_SIZE; ++hval) htab[hval] = ip;
/* we start with literal copy */
copy = 2;
- *op++ = MAX_COPY-1;
+ *op++ = MAX_COPY - 1;
*op++ = *ip++;
*op++ = *ip++;
/* main loop */
- while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
- {
- const flzuint8* ref;
- flzuint32 distance;
+ while (FASTLZ_LIKELY(ip < ip_limit)) {
+ const uint8_t* ref;
+ uint32_t distance;
/* minimum match length */
- flzuint32 len = 3;
+ uint32_t len = 3;
/* comparison starting-point */
- const flzuint8* anchor = ip;
+ const uint8_t* anchor = ip;
/* check for a run */
-#if FASTLZ_LEVEL==2
- if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
- {
+ if (ip[0] == ip[-1] && ip[0] == ip[1] && ip[1] == ip[2]) {
distance = 1;
ip += 3;
ref = anchor - 1 + 3;
goto match;
}
-#endif
/* find potential match */
- HASH_FUNCTION(hval,ip);
- hslot = htab + hval;
+ HASH_FUNCTION(hval, ip);
ref = htab[hval];
+ /* update hash table */
+ htab[hval] = anchor;
+
/* calculate distance to the match */
distance = anchor - ref;
- /* update hash table */
- *hslot = anchor;
-
/* is this a match? check the first 3 bytes */
- if(distance==0 ||
-#if FASTLZ_LEVEL==1
- (distance >= MAX_DISTANCE) ||
-#else
- (distance >= MAX_FARDISTANCE) ||
-#endif
- *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
+ if (distance == 0 || (distance >= MAX_FARDISTANCE) || *ref++ != *ip++ ||
+ *ref++ != *ip++ || *ref++ != *ip++)
goto literal;
-#if FASTLZ_LEVEL==2
/* far, needs at least 5-byte match */
- if(distance >= MAX_DISTANCE)
- {
- if(*ip++ != *ref++ || *ip++!= *ref++)
- goto literal;
+ if (distance >= MAX_L2_DISTANCE) {
+ if (*ip++ != *ref++ || *ip++ != *ref++) goto literal;
len += 2;
}
-
- match:
-#endif
+
+ match:
/* last matched byte */
ip = anchor + len;
@@ -264,34 +397,33 @@ static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void*
/* distance is biased */
distance--;
- if(!distance)
- {
+ if (!distance) {
/* zero distance means a run */
- flzuint8 x = ip[-1];
- while(ip < ip_bound)
- if(*ref++ != x) break; else ip++;
- }
- else
- for(;;)
- {
- /* safe because the outer check against ip limit */
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- if(*ref++ != *ip++) break;
- while(ip < ip_bound)
- if(*ref++ != *ip++) break;
- break;
- }
+ uint8_t x = ip[-1];
+ while (ip < ip_bound)
+ if (*ref++ != x)
+ break;
+ else
+ ip++;
+ } else
+ for (;;) {
+ /* safe because the outer check against ip limit */
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ if (*ref++ != *ip++) break;
+ while (ip < ip_bound)
+ if (*ref++ != *ip++) break;
+ break;
+ }
/* if we have copied something, adjust the copy count */
- if(copy)
- /* copy is biased, '0' means 1 byte copy */
- *(op-copy-1) = copy-1;
+ if (copy) /* copy is biased, '0' means 1 byte copy */
+ *(op - copy - 1) = copy - 1;
else
/* back, to overwrite the copy count */
op--;
@@ -304,248 +436,156 @@ static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void*
len = ip - anchor;
/* encode the match */
-#if FASTLZ_LEVEL==2
- if(distance < MAX_DISTANCE)
- {
- if(len < 7)
- {
+ if (distance < MAX_L2_DISTANCE) {
+ if (len < 7) {
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
- }
- else
- {
+ } else {
*op++ = (7 << 5) + (distance >> 8);
- for(len-=7; len >= 255; len-= 255)
- *op++ = 255;
+ for (len -= 7; len >= 255; len -= 255) *op++ = 255;
*op++ = len;
*op++ = (distance & 255);
}
- }
- else
- {
+ } else {
/* far away, but not yet in the another galaxy... */
- if(len < 7)
- {
- distance -= MAX_DISTANCE;
+ if (len < 7) {
+ distance -= MAX_L2_DISTANCE;
*op++ = (len << 5) + 31;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
- }
- else
- {
- distance -= MAX_DISTANCE;
+ } else {
+ distance -= MAX_L2_DISTANCE;
*op++ = (7 << 5) + 31;
- for(len-=7; len >= 255; len-= 255)
- *op++ = 255;
+ for (len -= 7; len >= 255; len -= 255) *op++ = 255;
*op++ = len;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
}
-#else
-
- if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
- while(len > MAX_LEN-2)
- {
- *op++ = (7 << 5) + (distance >> 8);
- *op++ = MAX_LEN - 2 - 7 -2;
- *op++ = (distance & 255);
- len -= MAX_LEN-2;
- }
-
- if(len < 7)
- {
- *op++ = (len << 5) + (distance >> 8);
- *op++ = (distance & 255);
- }
- else
- {
- *op++ = (7 << 5) + (distance >> 8);
- *op++ = len - 7;
- *op++ = (distance & 255);
- }
-#endif
/* update the hash at match boundary */
- HASH_FUNCTION(hval,ip);
+ HASH_FUNCTION(hval, ip);
htab[hval] = ip++;
- HASH_FUNCTION(hval,ip);
+ HASH_FUNCTION(hval, ip);
htab[hval] = ip++;
/* assuming literal copy */
- *op++ = MAX_COPY-1;
+ *op++ = MAX_COPY - 1;
continue;
- literal:
- *op++ = *anchor++;
- ip = anchor;
- copy++;
- if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
- {
- copy = 0;
- *op++ = MAX_COPY-1;
- }
+ literal:
+ *op++ = *anchor++;
+ ip = anchor;
+ copy++;
+ if (FASTLZ_UNLIKELY(copy == MAX_COPY)) {
+ copy = 0;
+ *op++ = MAX_COPY - 1;
+ }
}
/* left-over as literal copy */
ip_bound++;
- while(ip <= ip_bound)
- {
+ while (ip <= ip_bound) {
*op++ = *ip++;
copy++;
- if(copy == MAX_COPY)
- {
+ if (copy == MAX_COPY) {
copy = 0;
- *op++ = MAX_COPY-1;
+ *op++ = MAX_COPY - 1;
}
}
/* if we have copied something, adjust the copy length */
- if(copy)
- *(op-copy-1) = copy-1;
+ if (copy)
+ *(op - copy - 1) = copy - 1;
else
op--;
-#if FASTLZ_LEVEL==2
/* marker for fastlz2 */
- *(flzuint8*)output |= (1 << 5);
-#endif
+ *(uint8_t*)output |= (1 << 5);
- return op - (flzuint8*)output;
+ return op - (uint8_t*)output;
}
-static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
-{
- const flzuint8* ip = (const flzuint8*) input;
- const flzuint8* ip_limit = ip + length;
- flzuint8* op = (flzuint8*) output;
- flzuint8* op_limit = op + maxout;
- flzuint32 ctrl = (*ip++) & 31;
- int loop = 1;
-
- do
- {
- const flzuint8* ref = op;
- flzuint32 len = ctrl >> 5;
- flzuint32 ofs = (ctrl & 31) << 8;
-
- if(ctrl >= 32)
- {
-#if FASTLZ_LEVEL==2
- flzuint8 code;
-#endif
- len--;
- ref -= ofs;
- if (len == 7-1)
-#if FASTLZ_LEVEL==1
- len += *ip++;
- ref -= *ip++;
-#else
- do
- {
+int fastlz2_decompress(const void* input, int length, void* output,
+ int maxout) {
+ const uint8_t* ip = (const uint8_t*)input;
+ const uint8_t* ip_limit = ip + length;
+ const uint8_t* ip_bound = ip_limit - 2;
+ uint8_t* op = (uint8_t*)output;
+ uint8_t* op_limit = op + maxout;
+ uint32_t ctrl = (*ip++) & 31;
+
+ while (1) {
+ if (ctrl >= 32) {
+ uint32_t len = (ctrl >> 5) - 1;
+ uint32_t ofs = (ctrl & 31) << 8;
+ const uint8_t* ref = op - ofs - 1;
+
+ uint8_t code;
+ if (len == 7 - 1) do {
+ FASTLZ_BOUND_CHECK(ip <= ip_bound);
code = *ip++;
len += code;
- } while (code==255);
+ } while (code == 255);
code = *ip++;
ref -= code;
+ len += 3;
/* match from 16-bit distance */
- if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
- if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
- {
- ofs = (*ip++) << 8;
- ofs += *ip++;
- ref = op - ofs - MAX_DISTANCE;
- }
-#endif
-
-#ifdef FASTLZ_SAFE
- if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
- return 0;
-
- if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
- return 0;
-#endif
-
- if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
- ctrl = *ip++;
- else
- loop = 0;
-
- if(ref == op)
- {
- /* optimize copy for a run */
- flzuint8 b = ref[-1];
- *op++ = b;
- *op++ = b;
- *op++ = b;
- for(; len; --len)
- *op++ = b;
- }
- else
- {
-#if !defined(FASTLZ_STRICT_ALIGN)
- const flzuint16* p;
- flzuint16* q;
-#endif
- /* copy from reference */
- ref--;
- *op++ = *ref++;
- *op++ = *ref++;
- *op++ = *ref++;
-
-#if !defined(FASTLZ_STRICT_ALIGN)
- /* copy a byte, so that now it's word aligned */
- if(len & 1)
- {
- *op++ = *ref++;
- len--;
+ if (FASTLZ_UNLIKELY(code == 255))
+ if (FASTLZ_LIKELY(ofs == (31 << 8))) {
+ FASTLZ_BOUND_CHECK(ip < ip_bound);
+ ofs = (*ip++) << 8;
+ ofs += *ip++;
+ ref = op - ofs - MAX_L2_DISTANCE - 1;
}
- /* copy 16-bit at once */
- q = (flzuint16*) op;
- op += len;
- p = (const flzuint16*) ref;
- for(len>>=1; len > 4; len-=4)
- {
- *q++ = *p++;
- *q++ = *p++;
- *q++ = *p++;
- *q++ = *p++;
- }
- for(; len; --len)
- *q++ = *p++;
-#else
- for(; len; --len)
- *op++ = *ref++;
-#endif
- }
- }
- else
- {
+ FASTLZ_BOUND_CHECK(op + len <= op_limit);
+ FASTLZ_BOUND_CHECK(ref >= (uint8_t*)output);
+ fastlz_memmove(op, ref, len);
+ op += len;
+ } else {
ctrl++;
-#ifdef FASTLZ_SAFE
- if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
- return 0;
- if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
- return 0;
-#endif
-
- *op++ = *ip++;
- for(--ctrl; ctrl; ctrl--)
- *op++ = *ip++;
-
- loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
- if(loop)
- ctrl = *ip++;
+ FASTLZ_BOUND_CHECK(op + ctrl <= op_limit);
+ FASTLZ_BOUND_CHECK(ip + ctrl <= ip_limit);
+ fastlz_memcpy(op, ip, ctrl);
+ ip += ctrl;
+ op += ctrl;
}
+
+ if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
+ ctrl = *ip++;
}
- while(FASTLZ_EXPECT_CONDITIONAL(loop));
- return op - (flzuint8*)output;
+ return op - (uint8_t*)output;
}
-#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
+int fastlz_compress(const void* input, int length, void* output) {
+ /* for short block, choose fastlz1 */
+ if (length < 65536) return fastlz1_compress(input, length, output);
+
+ /* else... */
+ return fastlz2_compress(input, length, output);
+}
+
+int fastlz_decompress(const void* input, int length, void* output, int maxout) {
+ /* magic identifier for compression level */
+ int level = ((*(const uint8_t*)input) >> 5) + 1;
+
+ if (level == 1) return fastlz1_decompress(input, length, output, maxout);
+ if (level == 2) return fastlz2_decompress(input, length, output, maxout);
+
+ /* unknown level, trigger error */
+ return 0;
+}
+
+int fastlz_compress_level(int level, const void* input, int length,
+ void* output) {
+ if (level == 1) return fastlz1_compress(input, length, output);
+ if (level == 2) return fastlz2_compress(input, length, output);
+
+ return 0;
+}
diff --git a/thirdparty/misc/fastlz.h b/thirdparty/misc/fastlz.h
index e5ca8dfc02..e53dbfbb56 100644
--- a/thirdparty/misc/fastlz.h
+++ b/thirdparty/misc/fastlz.h
@@ -1,9 +1,6 @@
/*
- FastLZ - lightning-fast lossless compression library
-
- Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
- Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
- Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+ FastLZ - Byte-aligned LZ77 compression library
+ Copyright (C) 2005-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -27,15 +24,15 @@
#ifndef FASTLZ_H
#define FASTLZ_H
-#define FASTLZ_VERSION 0x000100
+#define FASTLZ_VERSION 0x000500
-#define FASTLZ_VERSION_MAJOR 0
-#define FASTLZ_VERSION_MINOR 0
-#define FASTLZ_VERSION_REVISION 0
+#define FASTLZ_VERSION_MAJOR 0
+#define FASTLZ_VERSION_MINOR 5
+#define FASTLZ_VERSION_REVISION 0
-#define FASTLZ_VERSION_STRING "0.1.0"
+#define FASTLZ_VERSION_STRING "0.5.0"
-#if defined (__cplusplus)
+#if defined(__cplusplus)
extern "C" {
#endif
@@ -51,9 +48,18 @@ extern "C" {
length (input buffer size).
The input buffer and the output buffer can not overlap.
+
+ Compression level can be specified in parameter level. At the moment,
+ only level 1 and level 2 are supported.
+ Level 1 is the fastest compression and generally useful for short data.
+ Level 2 is slightly slower but it gives better compression ratio.
+
+ Note that the compressed data, regardless of the level, can always be
+ decompressed using the function fastlz_decompress below.
*/
-int fastlz_compress(const void* input, int length, void* output);
+int fastlz_compress_level(int level, const void* input, int length,
+ void* output);
/**
Decompress a block of compressed data and returns the size of the
@@ -65,35 +71,27 @@ int fastlz_compress(const void* input, int length, void* output);
Decompression is memory safe and guaranteed not to write the output buffer
more than what is specified in maxout.
+
+ Note that the decompression will always work, regardless of the
+ compression level specified in fastlz_compress_level above (when
+ producing the compressed block).
*/
int fastlz_decompress(const void* input, int length, void* output, int maxout);
/**
- Compress a block of data in the input buffer and returns the size of
- compressed block. The size of input buffer is specified by length. The
- minimum input buffer size is 16.
+ DEPRECATED.
- The output buffer must be at least 5% larger than the input buffer
- and can not be smaller than 66 bytes.
-
- If the input is not compressible, the return value might be larger than
- length (input buffer size).
+ This is similar to fastlz_compress_level above, but with the level
+ automatically chosen.
- The input buffer and the output buffer can not overlap.
-
- Compression level can be specified in parameter level. At the moment,
- only level 1 and level 2 are supported.
- Level 1 is the fastest compression and generally useful for short data.
- Level 2 is slightly slower but it gives better compression ratio.
-
- Note that the compressed data, regardless of the level, can always be
- decompressed using the function fastlz_decompress above.
+ This function is deprecated and it will be completely removed in some future
+ version.
*/
-int fastlz_compress_level(int level, const void* input, int length, void* output);
+int fastlz_compress(const void* input, int length, void* output);
-#if defined (__cplusplus)
+#if defined(__cplusplus)
}
#endif
diff --git a/thirdparty/misc/hq2x.cpp b/thirdparty/misc/hq2x.cpp
deleted file mode 100644
index 9c089ba85c..0000000000
--- a/thirdparty/misc/hq2x.cpp
+++ /dev/null
@@ -1,2636 +0,0 @@
-/*
- * Copyright 2016 Bruno Ribeiro
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "hq2x.h"
-
-#include "core/math/math_funcs.h"
-
-static const uint32_t AMASK = 0xFF000000;
-static const uint32_t YMASK = 0x00FF0000;
-static const uint32_t UMASK = 0x0000FF00;
-static const uint32_t VMASK = 0x000000FF;
-
-_FORCE_INLINE_ static uint32_t ARGBtoAYUV(
- uint32_t value )
-{
- uint32_t A, R, G, B, Y, U, V;
-//todo big endian check
- A = value >> 24;
- R = (value >> 16) & 0xFF;
- G = (value >> 8) & 0xFF;
- B = value & 0xFF;
-
- Y = Math::fast_ftoi( 0.299 * R + 0.587 * G + 0.114 * B);
- U = Math::fast_ftoi(-0.169 * R - 0.331 * G + 0.5 * B) + 128;
- V = Math::fast_ftoi( 0.5 * R - 0.419 * G - 0.081 * B) + 128;
- return (A << 24) + (Y << 16) + (U << 8) + V;
-}
-
-
-/*
- * Use this function for sharper images (good for cartoon style, used by DOSBOX)
- */
-
-_FORCE_INLINE_ static bool isDifferent(
- uint32_t color1,
- uint32_t color2,
- uint32_t trY,
- uint32_t trU,
- uint32_t trV,
- uint32_t trA )
-{
- color1 = ARGBtoAYUV(color1);
- color2 = ARGBtoAYUV(color2);
-
- uint32_t value;
-
- value = ((color1 & YMASK) - (color2 & YMASK));
- value = (value ^ (value >> 31)) - (value >> 31);
- if (value > trY) return true;
-
- value = ((color1 & UMASK) - (color2 & UMASK));
- value = (value ^ (value >> 31)) - (value >> 31);
- if (value > trU) return true;
-
- value = ((color1 & VMASK) - (color2 & VMASK));
- value = (value ^ (value >> 31)) - (value >> 31);
- if (value > trV) return true;
-
- value = ((color1 & AMASK) - (color2 & AMASK));
- value = (value ^ (value >> 31)) - (value >> 31);
- if (value > trA) return true;
-
- return false;
-
-}
-
-
-
-#define MASK_RB 0x00FF00FF
-#define MASK_G 0x0000FF00
-#define MASK_A 0xFF000000
-
-
-/**
- * @brief Mixes two colors using the given weights.
- */
-#define HQX_MIX_2(C0,C1,W0,W1) \
- ((((C0 & MASK_RB) * W0 + (C1 & MASK_RB) * W1) / (W0 + W1)) & MASK_RB) | \
- ((((C0 & MASK_G) * W0 + (C1 & MASK_G) * W1) / (W0 + W1)) & MASK_G) | \
- ((((((C0 & MASK_A) >> 8) * W0 + ((C1 & MASK_A) >> 8) * W1) / (W0 + W1)) << 8) & MASK_A)
-
-/**
- * @brief Mixes three colors using the given weights.
- */
-#define HQX_MIX_3(C0,C1,C2,W0,W1,W2) \
- ((((C0 & MASK_RB) * W0 + (C1 & MASK_RB) * W1 + (C2 & MASK_RB) * W2) / (W0 + W1 + W2)) & MASK_RB) | \
- ((((C0 & MASK_G) * W0 + (C1 & MASK_G) * W1 + (C2 & MASK_G) * W2) / (W0 + W1 + W2)) & MASK_G) | \
- ((((((C0 & MASK_A) >> 8) * W0 + ((C1 & MASK_A) >> 8) * W1 + ((C2 & MASK_A) >> 8) * W2) / (W0 + W1 + W2)) << 8) & MASK_A)
-
-
-#define MIX_00_4 *output = w[4];
-#define MIX_00_MIX_00_4_0_3_1 *output = HQX_MIX_2(w[4],w[0],3U,1U);
-#define MIX_00_4_3_3_1 *output = HQX_MIX_2(w[4],w[3],3U,1U);
-#define MIX_00_4_1_3_1 *output = HQX_MIX_2(w[4],w[1],3U,1U);
-#define MIX_00_3_1_1_1 *output = HQX_MIX_2(w[3],w[1],1U,1U);
-#define MIX_00_4_3_1_2_1_1 *output = HQX_MIX_3(w[4],w[3],w[1],2U,1U,1U);
-#define MIX_00_4_3_1_2_7_7 *output = HQX_MIX_3(w[4],w[3],w[1],2U,7U,7U);
-#define MIX_00_4_0_1_2_1_1 *output = HQX_MIX_3(w[4],w[0],w[1],2U,1U,1U);
-#define MIX_00_4_0_3_2_1_1 *output = HQX_MIX_3(w[4],w[0],w[3],2U,1U,1U);
-#define MIX_00_4_1_3_5_2_1 *output = HQX_MIX_3(w[4],w[1],w[3],5U,2U,1U);
-#define MIX_00_4_3_1_5_2_1 *output = HQX_MIX_3(w[4],w[3],w[1],5U,2U,1U);
-#define MIX_00_4_3_1_6_1_1 *output = HQX_MIX_3(w[4],w[3],w[1],6U,1U,1U);
-#define MIX_00_4_3_1_2_3_3 *output = HQX_MIX_3(w[4],w[3],w[1],2U,3U,3U);
-#define MIX_00_MIX_00_4_0_3_10 *output = HQX_MIX_3(w[4],w[3],w[1],14U,1U,1U);
-
-#define MIX_01_4 *(output + 1) = w[4];
-#define MIX_01_4_2_3_1 *(output + 1) = HQX_MIX_2(w[4],w[2],3U,1U);
-#define MIX_01_4_1_3_1 *(output + 1) = HQX_MIX_2(w[4],w[1],3U,1U);
-#define MIX_01_1_4_3_1 *(output + 1) = HQX_MIX_2(w[1],w[4],3U,1U);
-#define MIX_01_4_5_3_1 *(output + 1) = HQX_MIX_2(w[4],w[5],3U,1U);
-#define MIX_01_4_1_7_1 *(output + 1) = HQX_MIX_2(w[4],w[1],7U,1U);
-#define MIX_01_4_1_5_2_1_1 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],2U,1U,1U);
-#define MIX_01_4_2_5_2_1_1 *(output + 1) = HQX_MIX_3(w[4],w[2],w[5],2U,1U,1U);
-#define MIX_01_4_2_1_2_1_1 *(output + 1) = HQX_MIX_3(w[4],w[2],w[1],2U,1U,1U);
-#define MIX_01_4_5_1_5_2_1 *(output + 1) = HQX_MIX_3(w[4],w[5],w[1],5U,2U,1U);
-#define MIX_01_4_1_5_5_2_1 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],5U,2U,1U);
-#define MIX_01_4_1_5_6_1_1 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],6U,1U,1U);
-#define MIX_01_4_1_5_2_3_3 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],2U,3U,3U);
-#define MIX_01_4_2_3_10 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],14U,1U,1U);
-
-#define MIX_02_4 *(output + 2) = w[4];
-#define MIX_02_4_2_3_1 *(output + 2) = HQX_MIX_2(w[4],w[2],3U,1U);
-#define MIX_02_4_1_3_1 *(output + 2) = HQX_MIX_2(w[4],w[1],3U,1U);
-#define MIX_02_4_5_3_1 *(output + 2) = HQX_MIX_2(w[4],w[5],3U,1U);
-#define MIX_02_4_1_5_2_1_1 *(output + 2) = HQX_MIX_3(w[4],w[1],w[5],2U,1U,1U);
-#define MIX_02_4_1_5_2_7_7 *(output + 2) = HQX_MIX_3(w[4],w[1],w[5],2U,7U,7U);
-#define MIX_02_1_5_1_1 *(output + 2) = HQX_MIX_2(w[1],w[5],1U,1U);
-
-#define MIX_10_4 *(output + lineSize) = w[4];
-#define MIX_10_4_6_3_1 *(output + lineSize) = HQX_MIX_2(w[4],w[6],3U,1U);
-#define MIX_10_4_7_3_1 *(output + lineSize) = HQX_MIX_2(w[4],w[7],3U,1U);
-#define MIX_10_4_3_3_1 *(output + lineSize) = HQX_MIX_2(w[4],w[3],3U,1U);
-#define MIX_10_4_7_3_2_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,1U,1U);
-#define MIX_10_4_6_3_2_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[6],w[3],2U,1U,1U);
-#define MIX_10_4_6_7_2_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[6],w[7],2U,1U,1U);
-#define MIX_10_4_3_7_5_2_1 *(output + lineSize) = HQX_MIX_3(w[4],w[3],w[7],5U,2U,1U);
-#define MIX_10_4_7_3_5_2_1 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],5U,2U,1U);
-#define MIX_10_4_7_3_6_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],6U,1U,1U);
-#define MIX_10_4_7_3_2_3_3 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,3U,3U);
-#define MIX_10_4_6_3_10 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],14U,1U,1U);
-#define MIX_10_4_3_7_1 *(output + lineSize) = HQX_MIX_2(w[4],w[3],7U,1U);
-#define MIX_10_3_4_3_1 *(output + lineSize) = HQX_MIX_2(w[3],w[4],3U,1U);
-
-#define MIX_11_4 *(output + lineSize + 1) = w[4];
-#define MIX_11_4_8_3_1 *(output + lineSize + 1) = HQX_MIX_2(w[4],w[8],3U,1U);
-#define MIX_11_4_5_3_1 *(output + lineSize + 1) = HQX_MIX_2(w[4],w[5],3U,1U);
-#define MIX_11_4_7_3_1 *(output + lineSize + 1) = HQX_MIX_2(w[4],w[7],3U,1U);
-#define MIX_11_4_5_7_2_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],2U,1U,1U);
-#define MIX_11_4_8_7_2_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[8],w[7],2U,1U,1U);
-#define MIX_11_4_8_5_2_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[8],w[5],2U,1U,1U);
-#define MIX_11_4_7_5_5_2_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[7],w[5],5U,2U,1U);
-#define MIX_11_4_5_7_5_2_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],5U,2U,1U);
-#define MIX_11_4_5_7_6_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],6U,1U,1U);
-#define MIX_11_4_5_7_2_3_3 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],2U,3U,3U);
-#define MIX_11_4_8_3_10 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],14U,1U,1U);
-
-#define MIX_12_4 *(output + lineSize + 2) = w[4];
-#define MIX_12_4_5_3_1 *(output + lineSize + 2) = HQX_MIX_2(w[4],w[5],3U,1U);
-#define MIX_12_4_5_7_1 *(output + lineSize + 2) = HQX_MIX_2(w[4],w[5],7U,1U);
-#define MIX_12_5_4_3_1 *(output + lineSize + 2) = HQX_MIX_2(w[5],w[4],3U,1U);
-
-#define MIX_20_4 *(output + lineSize + lineSize) = w[4];
-#define MIX_20_4_6_3_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[4],w[6],3U,1U);
-#define MIX_20_4_7_3_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[4],w[7],3U,1U);
-#define MIX_20_4_3_3_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[4],w[3],3U,1U);
-#define MIX_20_4_7_3_2_1_1 *(output + lineSize + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,1U,1U);
-#define MIX_20_4_7_3_2_7_7 *(output + lineSize + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,7U,7U);
-#define MIX_20_7_3_1_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[7],w[3],1U,1U);
-
-#define MIX_21_4 *(output + lineSize + lineSize + 1) = w[4];
-#define MIX_21_4_7_3_1 *(output + lineSize + lineSize + 1) = HQX_MIX_2(w[4],w[7],3U,1U);
-#define MIX_21_4_7_7_1 *(output + lineSize + lineSize + 1) = HQX_MIX_2(w[4],w[7],7U,1U);
-#define MIX_21_7_4_3_1 *(output + lineSize + lineSize + 1) = HQX_MIX_2(w[7],w[4],3U,1U);
-
-#define MIX_22_4 *(output + lineSize + lineSize + 2) = w[4];
-#define MIX_22_4_8_3_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[4],w[8],3U,1U);
-#define MIX_22_4_7_3_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[4],w[7],3U,1U);
-#define MIX_22_4_5_3_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[4],w[5],3U,1U);
-#define MIX_22_4_5_7_2_1_1 *(output + lineSize + lineSize + 2) = HQX_MIX_3(w[4],w[5],w[7],2U,1U,1U);
-#define MIX_22_4_5_7_2_7_7 *(output + lineSize + lineSize + 2) = HQX_MIX_3(w[4],w[5],w[7],2U,7U,7U);
-#define MIX_22_5_7_1_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[5],w[7],1U,1U);
-
-
-
-uint32_t *hq2x_resize(
- const uint32_t *image,
- uint32_t width,
- uint32_t height,
- uint32_t *output,
- uint32_t trY,
- uint32_t trU,
- uint32_t trV,
- uint32_t trA,
- bool wrapX,
- bool wrapY )
-{
- int lineSize = width * 2;
-
- int previous, next;
- uint32_t w[9];
-
- trY <<= 16;
- trU <<= 8;
- trA <<= 24;
-
- // iterates between the lines
- for (uint32_t row = 0; row < height; row++)
- {
- /*
- * Note: this function uses a 3x3 sliding window over the original image.
- *
- * +----+----+----+
- * | | | |
- * | w0 | w1 | w2 |
- * +----+----+----+
- * | | | |
- * | w3 | w4 | w5 |
- * +----+----+----+
- * | | | |
- * | w6 | w7 | w8 |
- * +----+----+----+
- */
-
- // adjusts the previous and next line pointers
- if (row > 0)
- previous = -width;
- else
- {
- if (wrapY)
- previous = width * (height - 1);
- else
- previous = 0;
- }
- if (row < height - 1)
- next = width;
- else
- {
- if (wrapY)
- next = -(width * (height - 1));
- else
- next = 0;
- }
-
- // iterates between the columns
- for (uint32_t col = 0; col < width; col++)
- {
- w[1] = *(image + previous);
- w[4] = *image;
- w[7] = *(image + next);
-
- if (col > 0)
- {
- w[0] = *(image + previous - 1);
- w[3] = *(image - 1);
- w[6] = *(image + next - 1);
- }
- else
- {
- if (wrapX)
- {
- w[0] = *(image + previous + width - 1);
- w[3] = *(image + width - 1);
- w[6] = *(image + next + width - 1);
- }
- else
- {
- w[0] = w[1];
- w[3] = w[4];
- w[6] = w[7];
- }
- }
-
- if (col < width - 1)
- {
- w[2] = *(image + previous + 1);
- w[5] = *(image + 1);
- w[8] = *(image + next + 1);
- }
- else
- {
- if (wrapX)
- {
- w[2] = *(image + previous - width + 1);
- w[5] = *(image - width + 1);
- w[8] = *(image + next - width + 1);
- }
- else
- {
- w[2] = w[1];
- w[5] = w[4];
- w[8] = w[7];
- }
- }
-
- int pattern = 0;
-
- // computes the pattern to be used considering the neighbor pixels
- for (int k = 0, flag = 1; k < 9; k++)
- {
- // ignores the central pixel
- if (k == 4) continue;
-
- if (w[k] != w[4])
- if (isDifferent(w[4], w[k], trY, trU, trV, trA)) pattern |= flag;
- flag <<= 1;
- }
-
- switch (pattern)
- {
- case 0:
- case 1:
- case 4:
- case 32:
- case 128:
- case 5:
- case 132:
- case 160:
- case 33:
- case 129:
- case 36:
- case 133:
- case 164:
- case 161:
- case 37:
- case 165:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 2:
- case 34:
- case 130:
- case 162:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 16:
- case 17:
- case 48:
- case 49:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 64:
- case 65:
- case 68:
- case 69:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 8:
- case 12:
- case 136:
- case 140:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 3:
- case 35:
- case 131:
- case 163:
- MIX_00_4_3_3_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 6:
- case 38:
- case 134:
- case 166:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_5_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 20:
- case 21:
- case 52:
- case 53:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 144:
- case 145:
- case 176:
- case 177:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_7_3_1
- break;
- case 192:
- case 193:
- case 196:
- case 197:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_5_3_1
- break;
- case 96:
- case 97:
- case 100:
- case 101:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 40:
- case 44:
- case 168:
- case 172:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_5_7_2_1_1
- break;
- case 9:
- case 13:
- case 137:
- case 141:
- MIX_00_4_1_3_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 18:
- case 50:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 80:
- case 81:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 72:
- case 76:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 10:
- case 138:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 66:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 24:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 7:
- case 39:
- case 135:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 148:
- case 149:
- case 180:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_7_3_1
- break;
- case 224:
- case 228:
- case 225:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 41:
- case 169:
- case 45:
- MIX_00_4_1_3_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_5_7_2_1_1
- break;
- case 22:
- case 54:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 208:
- case 209:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 104:
- case 108:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 11:
- case 139:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 19:
- case 51:
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_00_4_3_3_1
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_00_4_1_3_5_2_1
- MIX_01_4_1_5_2_3_3
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 146:
- case 178:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- MIX_11_4_7_3_1
- }
- else
- {
- MIX_01_4_1_5_2_3_3
- MIX_11_4_5_7_5_2_1
- }
- MIX_10_4_7_3_2_1_1
- break;
- case 84:
- case 85:
- MIX_00_4_3_1_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_01_4_1_3_1
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_01_4_5_1_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- MIX_10_4_6_3_2_1_1
- break;
- case 112:
- case 113:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_10_4_3_3_1
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_10_4_7_3_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- break;
- case 200:
- case 204:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- MIX_11_4_5_3_1
- }
- else
- {
- MIX_10_4_7_3_2_3_3
- MIX_11_4_7_5_5_2_1
- }
- break;
- case 73:
- case 77:
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_00_4_1_3_1
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_00_4_3_1_5_2_1
- MIX_10_4_7_3_2_3_3
- }
- MIX_01_4_1_5_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 42:
- case 170:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- MIX_10_4_7_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_10_4_3_7_5_2_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 14:
- case 142:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- MIX_01_4_5_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_01_4_1_5_5_2_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 67:
- MIX_00_4_3_3_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 70:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_5_3_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 28:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 152:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 194:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_5_3_1
- break;
- case 98:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 56:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 25:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 26:
- case 31:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 82:
- case 214:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 88:
- case 248:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 74:
- case 107:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 27:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 86:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_3_1
- break;
- case 216:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 106:
- MIX_00_MIX_00_4_0_3_1
- MIX_01_4_2_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 30:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 210:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_3_1
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 120:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_3_1
- break;
- case 75:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 29:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 198:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_5_3_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_5_3_1
- break;
- case 184:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 99:
- MIX_00_4_3_3_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 57:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 71:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 156:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 226:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 60:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 195:
- MIX_00_4_3_3_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_5_3_1
- break;
- case 102:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_5_3_1
- MIX_10_4_3_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 153:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 58:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 83:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 92:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 202:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- MIX_01_4_2_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- MIX_11_4_5_3_1
- break;
- case 78:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 154:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 114:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 89:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 90:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 55:
- case 23:
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_00_4_3_3_1
- MIX_01_4
- }
- else
- {
- MIX_00_4_1_3_5_2_1
- MIX_01_4_1_5_2_3_3
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 182:
- case 150:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- MIX_11_4_7_3_1
- }
- else
- {
- MIX_01_4_1_5_2_3_3
- MIX_11_4_5_7_5_2_1
- }
- MIX_10_4_7_3_2_1_1
- break;
- case 213:
- case 212:
- MIX_00_4_3_1_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_01_4_1_3_1
- MIX_11_4
- }
- else
- {
- MIX_01_4_5_1_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- MIX_10_4_6_3_2_1_1
- break;
- case 241:
- case 240:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_10_4_3_3_1
- MIX_11_4
- }
- else
- {
- MIX_10_4_7_3_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- break;
- case 236:
- case 232:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- MIX_11_4_5_3_1
- }
- else
- {
- MIX_10_4_7_3_2_3_3
- MIX_11_4_7_5_5_2_1
- }
- break;
- case 109:
- case 105:
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_00_4_1_3_1
- MIX_10_4
- }
- else
- {
- MIX_00_4_3_1_5_2_1
- MIX_10_4_7_3_2_3_3
- }
- MIX_01_4_1_5_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 171:
- case 43:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- MIX_10_4_7_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_10_4_3_7_5_2_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 143:
- case 15:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- MIX_01_4_5_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_01_4_1_5_5_2_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 124:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_3_1
- break;
- case 203:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_1
- MIX_11_4_5_3_1
- break;
- case 62:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 211:
- MIX_00_4_3_3_1
- MIX_01_4_2_3_1
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 118:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_3_3_1
- MIX_11_4_8_3_1
- break;
- case 217:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 110:
- MIX_00_MIX_00_4_0_3_1
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 155:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 188:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 185:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 61:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 157:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 103:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_3_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 227:
- MIX_00_4_3_3_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 230:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_5_3_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 199:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_5_3_1
- break;
- case 220:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 158:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 234:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- MIX_01_4_2_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_5_3_1
- break;
- case 242:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 59:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 121:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 87:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 79:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 122:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 94:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 218:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 91:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 229:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 167:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 173:
- MIX_00_4_1_3_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_5_7_2_1_1
- break;
- case 181:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_7_3_1
- break;
- case 186:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 115:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 93:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 206:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- MIX_11_4_5_3_1
- break;
- case 205:
- case 201:
- MIX_00_4_1_3_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- MIX_11_4_5_3_1
- break;
- case 174:
- case 46:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- MIX_01_4_5_3_1
- MIX_10_4_7_3_1
- MIX_11_4_5_7_2_1_1
- break;
- case 179:
- case 147:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_7_3_1
- break;
- case 117:
- case 116:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 189:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 231:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 126:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_3_1
- break;
- case 219:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_3_1
- MIX_10_4_6_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 125:
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_00_4_1_3_1
- MIX_10_4
- }
- else
- {
- MIX_00_4_3_1_5_2_1
- MIX_10_4_7_3_2_3_3
- }
- MIX_01_4_1_3_1
- MIX_11_4_8_3_1
- break;
- case 221:
- MIX_00_4_1_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_01_4_1_3_1
- MIX_11_4
- }
- else
- {
- MIX_01_4_5_1_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- MIX_10_4_6_3_1
- break;
- case 207:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- MIX_01_4_5_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_01_4_1_5_5_2_1
- }
- MIX_10_4_6_3_1
- MIX_11_4_5_3_1
- break;
- case 238:
- MIX_00_MIX_00_4_0_3_1
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- MIX_11_4_5_3_1
- }
- else
- {
- MIX_10_4_7_3_2_3_3
- MIX_11_4_7_5_5_2_1
- }
- break;
- case 190:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- MIX_11_4_7_3_1
- }
- else
- {
- MIX_01_4_1_5_2_3_3
- MIX_11_4_5_7_5_2_1
- }
- MIX_10_4_7_3_1
- break;
- case 187:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- MIX_10_4_7_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_10_4_3_7_5_2_1
- }
- MIX_01_4_2_3_1
- MIX_11_4_7_3_1
- break;
- case 243:
- MIX_00_4_3_3_1
- MIX_01_4_2_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_10_4_3_3_1
- MIX_11_4
- }
- else
- {
- MIX_10_4_7_3_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- break;
- case 119:
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_00_4_3_3_1
- MIX_01_4
- }
- else
- {
- MIX_00_4_1_3_5_2_1
- MIX_01_4_1_5_2_3_3
- }
- MIX_10_4_3_3_1
- MIX_11_4_8_3_1
- break;
- case 237:
- case 233:
- MIX_00_4_1_3_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- MIX_11_4_5_3_1
- break;
- case 175:
- case 47:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- MIX_01_4_5_3_1
- MIX_10_4_7_3_1
- MIX_11_4_5_7_2_1_1
- break;
- case 183:
- case 151:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_7_3_1
- break;
- case 245:
- case 244:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 250:
- MIX_00_MIX_00_4_0_3_1
- MIX_01_4_2_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 123:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_3_1
- break;
- case 95:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_3_1
- MIX_11_4_8_3_1
- break;
- case 222:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 252:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 249:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 235:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- MIX_11_4_5_3_1
- break;
- case 111:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 63:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 159:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 215:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 246:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 254:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 253:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 251:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 239:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- MIX_11_4_5_3_1
- break;
- case 127:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_3_1
- break;
- case 191:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 223:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_6_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 247:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 255:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- MIX_00_4
- else
- MIX_00_MIX_00_4_0_3_10
-
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- MIX_01_4
- else
- MIX_01_4_2_3_10
-
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- MIX_10_4
- else
- MIX_10_4_6_3_10
-
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- MIX_11_4
- else
- MIX_11_4_8_3_10
- break;
- }
- image++;
- output += 2;
- }
- output += lineSize;
- }
-
- return output;
-}
diff --git a/thirdparty/misc/hq2x.h b/thirdparty/misc/hq2x.h
deleted file mode 100644
index bebd917950..0000000000
--- a/thirdparty/misc/hq2x.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef HQ2X_H
-#define HQ2X_H
-
-#include "core/typedefs.h"
-
-
-uint32_t *hq2x_resize(
- const uint32_t *image,
- uint32_t width,
- uint32_t height,
- uint32_t *output,
- uint32_t trY = 0x30,
- uint32_t trU = 0x07,
- uint32_t trV = 0x06,
- uint32_t trA = 0x50,
- bool wrapX = false,
- bool wrapY = false );
-
-#endif // HQ2X_H
diff --git a/thirdparty/misc/ifaddrs-android.h b/thirdparty/misc/ifaddrs-android.h
index 6e204af26f..8de94324b8 100644
--- a/thirdparty/misc/ifaddrs-android.h
+++ b/thirdparty/misc/ifaddrs-android.h
@@ -32,6 +32,11 @@
// Fills out a list of ifaddr structs (see below) which contain information
// about every network interface available on the host.
// See 'man getifaddrs' on Linux or OS X (nb: it is not a POSIX function).
+// -- GODOT start --
+#ifdef __cplusplus
+extern "C" {
+#endif
+// -- GODOT end --
struct ifaddrs {
struct ifaddrs* ifa_next;
char* ifa_name;
@@ -40,7 +45,21 @@ struct ifaddrs {
struct sockaddr* ifa_netmask;
// Real ifaddrs has broadcast, point to point and data members.
// We don't need them (yet?).
+ // -- GODOT start --
+ // We never initialize the following members. We only define them to match the ifaddrs struct.
+ union
+ {
+ struct sockaddr *ifu_broadaddr;
+ struct sockaddr *ifu_dstaddr;
+ } ifa_ifu;
+ void *ifa_data;
+ // -- GODOT end --
};
+// -- GODOT start --
+#ifdef __cplusplus
+}
+#endif
+// -- GODOT end --
int getifaddrs(struct ifaddrs** result);
void freeifaddrs(struct ifaddrs* addrs);
#endif // TALK_BASE_IFADDRS_ANDROID_H_
diff --git a/thirdparty/misc/r128.c b/thirdparty/misc/r128.c
new file mode 100644
index 0000000000..6b981aa693
--- /dev/null
+++ b/thirdparty/misc/r128.c
@@ -0,0 +1,2 @@
+#define R128_IMPLEMENTATION
+#include "r128.h"
diff --git a/thirdparty/misc/r128.h b/thirdparty/misc/r128.h
new file mode 100644
index 0000000000..1f7aab78fb
--- /dev/null
+++ b/thirdparty/misc/r128.h
@@ -0,0 +1,2123 @@
+/*
+r128.h: 128-bit (64.64) signed fixed-point arithmetic. Version 1.4.3
+
+COMPILATION
+-----------
+Drop this header file somewhere in your project and include it wherever it is
+needed. There is no separate .c file for this library. To get the code, in ONE
+file in your project, put:
+
+#define R128_IMPLEMENTATION
+
+before you include this file. You may also provide a definition for R128_ASSERT
+to force the library to use a custom assert macro.
+
+COMPILER/LIBRARY SUPPORT
+------------------------
+This library requires a C89 compiler with support for 64-bit integers. If your
+compiler does not support the long long data type, the R128_U64, etc. macros
+must be set appropriately. On x86 and x64 targets, Intel intrinsics are used
+for speed. If your compiler does not support these intrinsics, you can add
+#define R128_STDC_ONLY
+in your implementation file before including r128.h.
+
+The only C runtime library functionality used by this library is <assert.h>.
+This can be avoided by defining an R128_ASSERT macro in your implementation
+file. Since this library uses 64-bit arithmetic, this may implicitly add a
+runtime library dependency on 32-bit platforms.
+
+C++ SUPPORT
+-----------
+Operator overloads are supplied for C++ files that include this file. Since all
+C++ functions are declared inline (or static inline), the R128_IMPLEMENTATION
+file can be either C++ or C.
+
+LICENSE
+-------
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef H_R128_H
+#define H_R128_H
+
+#include <stddef.h>
+
+// 64-bit integer support
+// If your compiler does not have stdint.h, add appropriate defines for these macros.
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+# define R128_S32 __int32
+# define R128_U32 unsigned __int32
+# define R128_S64 __int64
+# define R128_U64 unsigned __int64
+# define R128_LIT_S64(x) x##i64
+# define R128_LIT_U64(x) x##ui64
+#else
+# include <stdint.h>
+# define R128_S32 int32_t
+# define R128_U32 uint32_t
+# define R128_S64 int64_t
+# define R128_U64 uint64_t
+# define R128_LIT_S64(x) x##ll
+# define R128_LIT_U64(x) x##ull
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct R128 {
+ R128_U64 lo;
+ R128_U64 hi;
+
+#ifdef __cplusplus
+ R128();
+ R128(double);
+ R128(int);
+ R128(R128_S64);
+ R128(R128_U64 low, R128_U64 high);
+
+ operator double() const;
+ operator R128_S64() const;
+ operator int() const;
+ operator bool() const;
+
+ bool operator!() const;
+ R128 operator~() const;
+ R128 operator-() const;
+ R128 &operator|=(const R128 &rhs);
+ R128 &operator&=(const R128 &rhs);
+ R128 &operator^=(const R128 &rhs);
+ R128 &operator+=(const R128 &rhs);
+ R128 &operator-=(const R128 &rhs);
+ R128 &operator*=(const R128 &rhs);
+ R128 &operator/=(const R128 &rhs);
+ R128 &operator%=(const R128 &rhs);
+ R128 &operator<<=(int amount);
+ R128 &operator>>=(int amount);
+#endif //__cplusplus
+} R128;
+
+// Type conversion
+extern void r128FromInt(R128 *dst, R128_S64 v);
+extern void r128FromFloat(R128 *dst, double v);
+extern R128_S64 r128ToInt(const R128 *v);
+extern double r128ToFloat(const R128 *v);
+
+// Copy
+extern void r128Copy(R128 *dst, const R128 *src);
+
+// Negate
+extern void r128Neg(R128 *dst, const R128 *src);
+
+// Bitwise operations
+extern void r128Not(R128 *dst, const R128 *src); // ~a
+extern void r128Or(R128 *dst, const R128 *a, const R128 *b); // a | b
+extern void r128And(R128 *dst, const R128 *a, const R128 *b); // a & b
+extern void r128Xor(R128 *dst, const R128 *a, const R128 *b); // a ^ b
+extern void r128Shl(R128 *dst, const R128 *src, int amount); // shift left by amount mod 128
+extern void r128Shr(R128 *dst, const R128 *src, int amount); // shift right logical by amount mod 128
+extern void r128Sar(R128 *dst, const R128 *src, int amount); // shift right arithmetic by amount mod 128
+
+// Arithmetic
+extern void r128Add(R128 *dst, const R128 *a, const R128 *b); // a + b
+extern void r128Sub(R128 *dst, const R128 *a, const R128 *b); // a - b
+extern void r128Mul(R128 *dst, const R128 *a, const R128 *b); // a * b
+extern void r128Div(R128 *dst, const R128 *a, const R128 *b); // a / b
+extern void r128Mod(R128 *dst, const R128 *a, const R128 *b); // a - toInt(a / b) * b
+
+extern void r128Sqrt(R128 *dst, const R128 *v); // sqrt(v)
+extern void r128Rsqrt(R128 *dst, const R128 *v); // 1 / sqrt(v)
+
+// Comparison
+extern int r128Cmp(const R128 *a, const R128 *b); // sign of a-b
+extern void r128Min(R128 *dst, const R128 *a, const R128 *b);
+extern void r128Max(R128 *dst, const R128 *a, const R128 *b);
+extern void r128Floor(R128 *dst, const R128 *v);
+extern void r128Ceil(R128 *dst, const R128 *v);
+extern int r128IsNeg(const R128 *v); // quick check for < 0
+
+// String conversion
+//
+typedef enum R128ToStringSign {
+ R128ToStringSign_Default, // no sign character for positive values
+ R128ToStringSign_Space, // leading space for positive values
+ R128ToStringSign_Plus, // leading '+' for positive values
+} R128ToStringSign;
+
+// Formatting options for use with r128ToStringOpt. The "defaults" correspond
+// to a format string of "%f".
+//
+typedef struct R128ToStringFormat {
+ // sign character for positive values. Default is R128ToStringSign_Default.
+ R128ToStringSign sign;
+
+ // minimum number of characters to write. Default is 0.
+ int width;
+
+ // place to the right of the decimal at which rounding is performed. If negative,
+ // a maximum of 20 decimal places will be written, with no trailing zeroes.
+ // (20 places is sufficient to ensure that r128FromString will convert back to the
+ // original value.) Default is -1. NOTE: This is not the same default that the C
+ // standard library uses for %f.
+ int precision;
+
+ // If non-zero, pads the output string with leading zeroes if the final result is
+ // fewer than width characters. Otherwise, leading spaces are used. Default is 0.
+ int zeroPad;
+
+ // Always print a decimal point, even if the value is an integer. Default is 0.
+ int decimal;
+
+ // Left-align output if width specifier requires padding.
+ // Default is 0 (right align).
+ int leftAlign;
+} R128ToStringFormat;
+
+// r128ToStringOpt: convert R128 to a decimal string, with formatting.
+//
+// dst and dstSize: specify the buffer to write into. At most dstSize bytes will be written
+// (including null terminator). No additional rounding is performed if dstSize is not large
+// enough to hold the entire string.
+//
+// opt: an R128ToStringFormat struct (q.v.) with formatting options.
+//
+// Uses the R128_decimal global as the decimal point character.
+// Always writes a null terminator, even if the destination buffer is not large enough.
+//
+// Number of bytes that will be written (i.e. how big does dst need to be?):
+// If width is specified: width + 1 bytes.
+// If precision is specified: at most precision + 22 bytes.
+// If neither is specified: at most 42 bytes.
+//
+// Returns the number of bytes that would have been written if dst was sufficiently large,
+// not including the final null terminator.
+//
+extern int r128ToStringOpt(char *dst, size_t dstSize, const R128 *v, const R128ToStringFormat *opt);
+
+// r128ToStringf: convert R128 to a decimal string, with formatting.
+//
+// dst and dstSize: specify the buffer to write into. At most dstSize bytes will be written
+// (including null terminator).
+//
+// format: a printf-style format specifier, as one would use with floating point types.
+// e.g. "%+5.2f". (The leading % and trailing f are optional.)
+// NOTE: This is NOT a full replacement for sprintf. Any characters in the format string
+// that do not correspond to a format placeholder are ignored.
+//
+// Uses the R128_decimal global as the decimal point character.
+// Always writes a null terminator, even if the destination buffer is not large enough.
+//
+// Number of bytes that will be written (i.e. how big does dst need to be?):
+// If the precision field is specified: at most max(width, precision + 21) + 1 bytes
+// Otherwise: at most max(width, 41) + 1 bytes.
+//
+// Returns the number of bytes that would have been written if dst was sufficiently large,
+// not including the final null terminator.
+//
+extern int r128ToStringf(char *dst, size_t dstSize, const char *format, const R128 *v);
+
+// r128ToString: convert R128 to a decimal string, with default formatting.
+// Equivalent to r128ToStringf(dst, dstSize, "%f", v).
+//
+// Uses the R128_decimal global as the decimal point character.
+// Always writes a null terminator, even if the destination buffer is not large enough.
+//
+// Will write at most 42 bytes (including NUL) to dst.
+//
+// Returns the number of bytes that would have been written if dst was sufficiently large,
+// not including the final null terminator.
+//
+extern int r128ToString(char *dst, size_t dstSize, const R128 *v);
+
+// r128FromString: Convert string to R128.
+//
+// The string can be formatted either as a decimal number with optional sign
+// or as hexadecimal with a prefix of 0x or 0X.
+//
+// endptr, if not NULL, is set to the character following the last character
+// used in the conversion.
+//
+extern void r128FromString(R128 *dst, const char *s, char **endptr);
+
+// Constants
+extern const R128 R128_min; // minimum (most negative) value
+extern const R128 R128_max; // maximum (most positive) value
+extern const R128 R128_smallest; // smallest positive value
+extern const R128 R128_zero; // zero
+extern const R128 R128_one; // 1.0
+
+extern char R128_decimal; // decimal point character used by r128From/ToString. defaults to '.'
+
+#ifdef __cplusplus
+}
+
+#include <limits>
+namespace std {
+template<>
+struct numeric_limits<R128>
+{
+ static const bool is_specialized = true;
+
+ static R128 min() throw() { return R128_min; }
+ static R128 max() throw() { return R128_max; }
+
+ static const int digits = 127;
+ static const int digits10 = 38;
+ static const bool is_signed = true;
+ static const bool is_integer = false;
+ static const bool is_exact = false;
+ static const int radix = 2;
+ static R128 epsilon() throw() { return R128_smallest; }
+ static R128 round_error() throw() { return R128_one; }
+
+ static const int min_exponent = 0;
+ static const int min_exponent10 = 0;
+ static const int max_exponent = 0;
+ static const int max_exponent10 = 0;
+
+ static const bool has_infinity = false;
+ static const bool has_quiet_NaN = false;
+ static const bool has_signaling_NaN = false;
+ static const float_denorm_style has_denorm = denorm_absent;
+ static const bool has_denorm_loss = false;
+
+ static R128 infinity() throw() { return R128_zero; }
+ static R128 quiet_NaN() throw() { return R128_zero; }
+ static R128 signaling_NaN() throw() { return R128_zero; }
+ static R128 denorm_min() throw() { return R128_zero; }
+
+ static const bool is_iec559 = false;
+ static const bool is_bounded = true;
+ static const bool is_modulo = true;
+
+ static const bool traps = numeric_limits<R128_U64>::traps;
+ static const bool tinyness_before = false;
+ static const float_round_style round_style = round_toward_zero;
+};
+} //namespace std
+
+inline R128::R128() {}
+
+inline R128::R128(double v)
+{
+ r128FromFloat(this, v);
+}
+
+inline R128::R128(int v)
+{
+ r128FromInt(this, v);
+}
+
+inline R128::R128(R128_S64 v)
+{
+ r128FromInt(this, v);
+}
+
+inline R128::R128(R128_U64 low, R128_U64 high)
+{
+ lo = low;
+ hi = high;
+}
+
+inline R128::operator double() const
+{
+ return r128ToFloat(this);
+}
+
+inline R128::operator R128_S64() const
+{
+ return r128ToInt(this);
+}
+
+inline R128::operator int() const
+{
+ return (int) r128ToInt(this);
+}
+
+inline R128::operator bool() const
+{
+ return lo || hi;
+}
+
+inline bool R128::operator!() const
+{
+ return !lo && !hi;
+}
+
+inline R128 R128::operator~() const
+{
+ R128 r;
+ r128Not(&r, this);
+ return r;
+}
+
+inline R128 R128::operator-() const
+{
+ R128 r;
+ r128Neg(&r, this);
+ return r;
+}
+
+inline R128 &R128::operator|=(const R128 &rhs)
+{
+ r128Or(this, this, &rhs);
+ return *this;
+}
+
+inline R128 &R128::operator&=(const R128 &rhs)
+{
+ r128And(this, this, &rhs);
+ return *this;
+}
+
+inline R128 &R128::operator^=(const R128 &rhs)
+{
+ r128Xor(this, this, &rhs);
+ return *this;
+}
+
+inline R128 &R128::operator+=(const R128 &rhs)
+{
+ r128Add(this, this, &rhs);
+ return *this;
+}
+
+inline R128 &R128::operator-=(const R128 &rhs)
+{
+ r128Sub(this, this, &rhs);
+ return *this;
+}
+
+inline R128 &R128::operator*=(const R128 &rhs)
+{
+ r128Mul(this, this, &rhs);
+ return *this;
+}
+
+inline R128 &R128::operator/=(const R128 &rhs)
+{
+ r128Div(this, this, &rhs);
+ return *this;
+}
+
+inline R128 &R128::operator%=(const R128 &rhs)
+{
+ r128Mod(this, this, &rhs);
+ return *this;
+}
+
+inline R128 &R128::operator<<=(int amount)
+{
+ r128Shl(this, this, amount);
+ return *this;
+}
+
+inline R128 &R128::operator>>=(int amount)
+{
+ r128Sar(this, this, amount);
+ return *this;
+}
+
+static inline R128 operator|(const R128 &lhs, const R128 &rhs)
+{
+ R128 r(lhs);
+ return r |= rhs;
+}
+
+static inline R128 operator&(const R128 &lhs, const R128 &rhs)
+{
+ R128 r(lhs);
+ return r &= rhs;
+}
+
+static inline R128 operator^(const R128 &lhs, const R128 &rhs)
+{
+ R128 r(lhs);
+ return r ^= rhs;
+}
+
+static inline R128 operator+(const R128 &lhs, const R128 &rhs)
+{
+ R128 r(lhs);
+ return r += rhs;
+}
+
+static inline R128 operator-(const R128 &lhs, const R128 &rhs)
+{
+ R128 r(lhs);
+ return r -= rhs;
+}
+
+static inline R128 operator*(const R128 &lhs, const R128 &rhs)
+{
+ R128 r(lhs);
+ return r *= rhs;
+}
+
+static inline R128 operator/(const R128 &lhs, const R128 &rhs)
+{
+ R128 r(lhs);
+ return r /= rhs;
+}
+
+static inline R128 operator%(const R128 &lhs, const R128 &rhs)
+{
+ R128 r(lhs);
+ return r %= rhs;
+}
+
+static inline R128 operator<<(const R128 &lhs, int amount)
+{
+ R128 r(lhs);
+ return r <<= amount;
+}
+
+static inline R128 operator>>(const R128 &lhs, int amount)
+{
+ R128 r(lhs);
+ return r >>= amount;
+}
+
+static inline bool operator<(const R128 &lhs, const R128 &rhs)
+{
+ return r128Cmp(&lhs, &rhs) < 0;
+}
+
+static inline bool operator>(const R128 &lhs, const R128 &rhs)
+{
+ return r128Cmp(&lhs, &rhs) > 0;
+}
+
+static inline bool operator<=(const R128 &lhs, const R128 &rhs)
+{
+ return r128Cmp(&lhs, &rhs) <= 0;
+}
+
+static inline bool operator>=(const R128 &lhs, const R128 &rhs)
+{
+ return r128Cmp(&lhs, &rhs) >= 0;
+}
+
+static inline bool operator==(const R128 &lhs, const R128 &rhs)
+{
+ return lhs.lo == rhs.lo && lhs.hi == rhs.hi;
+}
+
+static inline bool operator!=(const R128 &lhs, const R128 &rhs)
+{
+ return lhs.lo != rhs.lo || lhs.hi != rhs.hi;
+}
+
+#endif //__cplusplus
+#endif //H_R128_H
+
+#ifdef R128_IMPLEMENTATION
+
+#ifdef R128_DEBUG_VIS
+# define R128_DEBUG_SET(x) r128ToString(R128_last, sizeof(R128_last), x)
+#else
+# define R128_DEBUG_SET(x)
+#endif
+
+#define R128_SET2(x, l, h) do { (x)->lo = (R128_U64)(l); (x)->hi = (R128_U64)(h); } while(0)
+#define R128_R0(x) ((R128_U32)(x)->lo)
+#define R128_R2(x) ((R128_U32)(x)->hi)
+#if defined(_M_IX86)
+// workaround: MSVC x86's handling of 64-bit values is not great
+# define R128_SET4(x, r0, r1, r2, r3) do { \
+ ((R128_U32*)&(x)->lo)[0] = (R128_U32)(r0); \
+ ((R128_U32*)&(x)->lo)[1] = (R128_U32)(r1); \
+ ((R128_U32*)&(x)->hi)[0] = (R128_U32)(r2); \
+ ((R128_U32*)&(x)->hi)[1] = (R128_U32)(r3); \
+ } while(0)
+# define R128_R1(x) (((R128_U32*)&(x)->lo)[1])
+# define R128_R3(x) (((R128_U32*)&(x)->hi)[1])
+#else
+# define R128_SET4(x, r0, r1, r2, r3) do { (x)->lo = (R128_U64)(r0) | ((R128_U64)(r1) << 32); \
+ (x)->hi = (R128_U64)(r2) | ((R128_U64)(r3) << 32); } while(0)
+# define R128_R1(x) ((R128_U32)((x)->lo >> 32))
+# define R128_R3(x) ((R128_U32)((x)->hi >> 32))
+#endif
+
+#if defined(_M_X64)
+# define R128_INTEL 1
+# define R128_64BIT 1
+# ifndef R128_STDC_ONLY
+# include <intrin.h>
+# endif
+#elif defined(__x86_64__)
+# define R128_INTEL 1
+# define R128_64BIT 1
+# ifndef R128_STDC_ONLY
+# include <x86intrin.h>
+# endif
+#elif defined(_M_IX86)
+# define R128_INTEL 1
+# ifndef R128_STDC_ONLY
+# include <intrin.h>
+# endif
+#elif defined(__i386__)
+# define R128_INTEL 1
+# ifndef R128_STDC_ONLY
+# include <x86intrin.h>
+# endif
+#elif defined(_M_ARM)
+# ifndef R128_STDC_ONLY
+# include <intrin.h>
+# endif
+#elif defined(_M_ARM64)
+# define R128_64BIT 1
+# ifndef R128_STDC_ONLY
+# include <intrin.h>
+# endif
+#elif defined(__aarch64__)
+# define R128_64BIT 1
+#endif
+
+#ifndef R128_INTEL
+# define R128_INTEL 0
+#endif
+
+#ifndef R128_64BIT
+# define R128_64BIT 0
+#endif
+
+#ifndef R128_ASSERT
+# include <assert.h>
+# define R128_ASSERT(x) assert(x)
+#endif
+
+#include <stdlib.h> // for NULL
+
+static const R128ToStringFormat R128__defaultFormat = {
+ R128ToStringSign_Default,
+ 0,
+ -1,
+ 0,
+ 0,
+ 0
+};
+
+const R128 R128_min = { 0, R128_LIT_U64(0x8000000000000000) };
+const R128 R128_max = { R128_LIT_U64(0xffffffffffffffff), R128_LIT_U64(0x7fffffffffffffff) };
+const R128 R128_smallest = { 1, 0 };
+const R128 R128_zero = { 0, 0 };
+const R128 R128_one = { 0, 1 };
+char R128_decimal = '.';
+#ifdef R128_DEBUG_VIS
+char R128_last[42];
+#endif
+
+static int r128__clz64(R128_U64 x)
+{
+#if defined(R128_STDC_ONLY)
+ R128_U64 n = 64, y;
+ y = x >> 32; if (y) { n -= 32; x = y; }
+ y = x >> 16; if (y) { n -= 16; x = y; }
+ y = x >> 8; if (y) { n -= 8; x = y; }
+ y = x >> 4; if (y) { n -= 4; x = y; }
+ y = x >> 2; if (y) { n -= 2; x = y; }
+ y = x >> 1; if (y) { n -= 1; x = y; }
+ return (int)(n - x);
+#elif defined(_M_X64) || defined(_M_ARM64)
+ unsigned long idx;
+ if (_BitScanReverse64(&idx, x)) {
+ return 63 - (int)idx;
+ } else {
+ return 64;
+ }
+#elif defined(_MSC_VER)
+ unsigned long idx;
+ if (_BitScanReverse(&idx, (R128_U32)(x >> 32))) {
+ return 31 - (int)idx;
+ } else if (_BitScanReverse(&idx, (R128_U32)x)) {
+ return 63 - (int)idx;
+ } else {
+ return 64;
+ }
+#else
+ return x ? __builtin_clzll(x) : 64;
+#endif
+}
+
+#if !R128_64BIT
+// 32*32->64
+static R128_U64 r128__umul64(R128_U32 a, R128_U32 b)
+{
+# if defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
+ return __emulu(a, b);
+# elif defined(_M_ARM) && !defined(R128_STDC_ONLY)
+ return _arm_umull(a, b);
+# else
+ return a * (R128_U64)b;
+# endif
+}
+
+// 64/32->32
+static R128_U32 r128__udiv64(R128_U32 nlo, R128_U32 nhi, R128_U32 d, R128_U32 *rem)
+{
+# if defined(_M_IX86) && (_MSC_VER >= 1920) && !defined(R128_STDC_ONLY)
+ unsigned __int64 n = ((unsigned __int64)nhi << 32) | nlo;
+ return _udiv64(n, d, rem);
+# elif defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
+ __asm {
+ mov eax, nlo
+ mov edx, nhi
+ div d
+ mov ecx, rem
+ mov dword ptr [ecx], edx
+ }
+# elif defined(__i386__) && !defined(R128_STDC_ONLY)
+ R128_U32 q, r;
+ __asm("divl %4"
+ : "=a"(q), "=d"(r)
+ : "a"(nlo), "d"(nhi), "X"(d));
+ *rem = r;
+ return q;
+# else
+ R128_U64 n64 = ((R128_U64)nhi << 32) | nlo;
+ *rem = (R128_U32)(n64 % d);
+ return (R128_U32)(n64 / d);
+# endif
+}
+#elif !defined(_M_X64) || defined(R128_STDC_ONLY)
+#define r128__umul64(a, b) ((a) * (R128_U64)(b))
+static R128_U32 r128__udiv64(R128_U32 nlo, R128_U32 nhi, R128_U32 d, R128_U32 *rem)
+{
+ R128_U64 n64 = ((R128_U64)nhi << 32) | nlo;
+ *rem = (R128_U32)(n64 % d);
+ return (R128_U32)(n64 / d);
+}
+#endif //!R128_64BIT
+
+static void r128__neg(R128 *dst, const R128 *src)
+{
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(src != NULL);
+
+#if R128_INTEL && !defined(R128_STDC_ONLY)
+ {
+ unsigned char carry = 0;
+# if R128_64BIT
+ carry = _addcarry_u64(carry, ~src->lo, 1, &dst->lo);
+ carry = _addcarry_u64(carry, ~src->hi, 0, &dst->hi);
+# else
+ R128_U32 r0, r1, r2, r3;
+ carry = _addcarry_u32(carry, ~R128_R0(src), 1, &r0);
+ carry = _addcarry_u32(carry, ~R128_R1(src), 0, &r1);
+ carry = _addcarry_u32(carry, ~R128_R2(src), 0, &r2);
+ carry = _addcarry_u32(carry, ~R128_R3(src), 0, &r3);
+ R128_SET4(dst, r0, r1, r2, r3);
+# endif //R128_64BIT
+ }
+#else
+ if (src->lo) {
+ dst->lo = ~src->lo + 1;
+ dst->hi = ~src->hi;
+ } else {
+ dst->lo = 0;
+ dst->hi = ~src->hi + 1;
+ }
+#endif //R128_INTEL
+}
+
+// 64*64->128
+static void r128__umul128(R128 *dst, R128_U64 a, R128_U64 b)
+{
+#if defined(_M_X64) && !defined(R128_STDC_ONLY)
+ dst->lo = _umul128(a, b, &dst->hi);
+#elif R128_64BIT && !defined(_MSC_VER) && !defined(R128_STDC_ONLY)
+ unsigned __int128 p0 = a * (unsigned __int128)b;
+ dst->hi = (R128_U64)(p0 >> 64);
+ dst->lo = (R128_U64)p0;
+#else
+ R128_U32 alo = (R128_U32)a;
+ R128_U32 ahi = (R128_U32)(a >> 32);
+ R128_U32 blo = (R128_U32)b;
+ R128_U32 bhi = (R128_U32)(b >> 32);
+ R128_U64 p0, p1, p2, p3;
+
+ p0 = r128__umul64(alo, blo);
+ p1 = r128__umul64(alo, bhi);
+ p2 = r128__umul64(ahi, blo);
+ p3 = r128__umul64(ahi, bhi);
+
+ {
+#if R128_INTEL && !defined(R128_STDC_ONLY)
+ R128_U32 r0, r1, r2, r3;
+ unsigned char carry;
+
+ r0 = (R128_U32)(p0);
+ r1 = (R128_U32)(p0 >> 32);
+ r2 = (R128_U32)(p1 >> 32);
+ r3 = (R128_U32)(p3 >> 32);
+
+ carry = _addcarry_u32(0, r1, (R128_U32)p1, &r1);
+ carry = _addcarry_u32(carry, r2, (R128_U32)(p2 >> 32), &r2);
+ _addcarry_u32(carry, r3, 0, &r3);
+ carry = _addcarry_u32(0, r1, (R128_U32)p2, &r1);
+ carry = _addcarry_u32(carry, r2, (R128_U32)p3, &r2);
+ _addcarry_u32(carry, r3, 0, &r3);
+
+ R128_SET4(dst, r0, r1, r2, r3);
+#else
+ R128_U64 carry, lo, hi;
+ carry = ((R128_U64)(R128_U32)p1 + (R128_U64)(R128_U32)p2 + (p0 >> 32)) >> 32;
+
+ lo = p0 + ((p1 + p2) << 32);
+ hi = p3 + ((R128_U32)(p1 >> 32) + (R128_U32)(p2 >> 32)) + carry;
+
+ R128_SET2(dst, lo, hi);
+#endif
+ }
+#endif
+}
+
+// 128/64->64
+#if defined(_M_X64) && (_MSC_VER < 1920) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
+// MSVC x64 provides neither inline assembly nor (pre-2019) a div intrinsic, so we do fake
+// "inline assembly" to avoid long division or outline assembly.
+#pragma code_seg(".text")
+__declspec(allocate(".text")) static const unsigned char r128__udiv128Code[] = {
+ 0x48, 0x8B, 0xC1, //mov rax, rcx
+ 0x49, 0xF7, 0xF0, //div rax, r8
+ 0x49, 0x89, 0x11, //mov qword ptr [r9], rdx
+ 0xC3 //ret
+};
+typedef R128_U64 (*r128__udiv128Proc)(R128_U64 nlo, R128_U64 nhi, R128_U64 d, R128_U64 *rem);
+static const r128__udiv128Proc r128__udiv128 = (r128__udiv128Proc)(void*)r128__udiv128Code;
+#else
+static R128_U64 r128__udiv128(R128_U64 nlo, R128_U64 nhi, R128_U64 d, R128_U64 *rem)
+{
+#if defined(_M_X64) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
+ return _udiv128(nhi, nlo, d, rem);
+#elif defined(__x86_64__) && !defined(R128_STDC_ONLY)
+ R128_U64 q, r;
+ __asm("divq %4"
+ : "=a"(q), "=d"(r)
+ : "a"(nlo), "d"(nhi), "X"(d));
+ *rem = r;
+ return q;
+#else
+ R128_U64 tmp;
+ R128_U32 d0, d1;
+ R128_U32 n3, n2, n1, n0;
+ R128_U32 q0, q1;
+ R128_U32 r;
+ int shift;
+
+ R128_ASSERT(d != 0); //division by zero
+ R128_ASSERT(nhi < d); //overflow
+
+ // normalize
+ shift = r128__clz64(d);
+
+ if (shift) {
+ R128 tmp128;
+ R128_SET2(&tmp128, nlo, nhi);
+ r128Shl(&tmp128, &tmp128, shift);
+ n3 = R128_R3(&tmp128);
+ n2 = R128_R2(&tmp128);
+ n1 = R128_R1(&tmp128);
+ n0 = R128_R0(&tmp128);
+ d <<= shift;
+ } else {
+ n3 = (R128_U32)(nhi >> 32);
+ n2 = (R128_U32)nhi;
+ n1 = (R128_U32)(nlo >> 32);
+ n0 = (R128_U32)nlo;
+ }
+
+ d1 = (R128_U32)(d >> 32);
+ d0 = (R128_U32)d;
+
+ // first digit
+ R128_ASSERT(n3 <= d1);
+ if (n3 < d1) {
+ q1 = r128__udiv64(n2, n3, d1, &r);
+ } else {
+ q1 = 0xffffffffu;
+ r = n2 + d1;
+ }
+refine1:
+ if (r128__umul64(q1, d0) > ((R128_U64)r << 32) + n1) {
+ --q1;
+ if (r < ~d1 + 1) {
+ r += d1;
+ goto refine1;
+ }
+ }
+
+ tmp = ((R128_U64)n2 << 32) + n1 - (r128__umul64(q1, d0) + (r128__umul64(q1, d1) << 32));
+ n2 = (R128_U32)(tmp >> 32);
+ n1 = (R128_U32)tmp;
+
+ // second digit
+ R128_ASSERT(n2 <= d1);
+ if (n2 < d1) {
+ q0 = r128__udiv64(n1, n2, d1, &r);
+ } else {
+ q0 = 0xffffffffu;
+ r = n1 + d1;
+ }
+refine0:
+ if (r128__umul64(q0, d0) > ((R128_U64)r << 32) + n0) {
+ --q0;
+ if (r < ~d1 + 1) {
+ r += d1;
+ goto refine0;
+ }
+ }
+
+ tmp = ((R128_U64)n1 << 32) + n0 - (r128__umul64(q0, d0) + (r128__umul64(q0, d1) << 32));
+ n1 = (R128_U32)(tmp >> 32);
+ n0 = (R128_U32)tmp;
+
+ *rem = (((R128_U64)n1 << 32) + n0) >> shift;
+ return ((R128_U64)q1 << 32) + q0;
+#endif
+}
+#endif
+
+static int r128__ucmp(const R128 *a, const R128 *b)
+{
+ if (a->hi != b->hi) {
+ if (a->hi > b->hi) {
+ return 1;
+ } else {
+ return -1;
+ }
+ } else {
+ if (a->lo == b->lo) {
+ return 0;
+ } else if (a->lo > b->lo) {
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+}
+
+static void r128__umul(R128 *dst, const R128 *a, const R128 *b)
+{
+#if defined(_M_X64) && !defined(R128_STDC_ONLY)
+ R128_U64 t0, t1;
+ R128_U64 lo, hi = 0;
+ unsigned char carry;
+
+ t0 = _umul128(a->lo, b->lo, &t1);
+ carry = _addcarry_u64(0, t1, t0 >> 63, &lo);
+ _addcarry_u64(carry, hi, hi, &hi);
+
+ t0 = _umul128(a->lo, b->hi, &t1);
+ carry = _addcarry_u64(0, lo, t0, &lo);
+ _addcarry_u64(carry, hi, t1, &hi);
+
+ t0 = _umul128(a->hi, b->lo, &t1);
+ carry = _addcarry_u64(0, lo, t0, &lo);
+ _addcarry_u64(carry, hi, t1, &hi);
+
+ t0 = _umul128(a->hi, b->hi, &t1);
+ hi += t0;
+
+ R128_SET2(dst, lo, hi);
+#elif defined(__x86_64__) && !defined(R128_STDC_ONLY)
+ unsigned __int128 p0, p1, p2, p3;
+ p0 = a->lo * (unsigned __int128)b->lo;
+ p1 = a->lo * (unsigned __int128)b->hi;
+ p2 = a->hi * (unsigned __int128)b->lo;
+ p3 = a->hi * (unsigned __int128)b->hi;
+
+ p0 = (p3 << 64) + p2 + p1 + (p0 >> 64) + ((R128_U64)p0 >> 63);
+ dst->lo = (R128_U64)p0;
+ dst->hi = (R128_U64)(p0 >> 64);
+#else
+ R128 p0, p1, p2, p3, round;
+
+ r128__umul128(&p0, a->lo, b->lo);
+ round.hi = 0; round.lo = p0.lo >> 63;
+ p0.lo = p0.hi; p0.hi = 0; //r128Shr(&p0, &p0, 64);
+ r128Add(&p0, &p0, &round);
+
+ r128__umul128(&p1, a->hi, b->lo);
+ r128Add(&p0, &p0, &p1);
+
+ r128__umul128(&p2, a->lo, b->hi);
+ r128Add(&p0, &p0, &p2);
+
+ r128__umul128(&p3, a->hi, b->hi);
+ p3.hi = p3.lo; p3.lo = 0; //r128Shl(&p3, &p3, 64);
+ r128Add(&p0, &p0, &p3);
+
+ R128_SET2(dst, p0.lo, p0.hi);
+#endif
+}
+
+// Shift d left until the high bit is set, and shift n left by the same amount.
+// returns non-zero on overflow.
+static int r128__norm(R128 *n, R128 *d, R128_U64 *n2)
+{
+ R128_U64 d0, d1;
+ R128_U64 n0, n1;
+ int shift;
+
+ d1 = d->hi;
+ d0 = d->lo;
+ n1 = n->hi;
+ n0 = n->lo;
+
+ if (d1) {
+ shift = r128__clz64(d1);
+ if (shift) {
+ d1 = (d1 << shift) | (d0 >> (64 - shift));
+ d0 = d0 << shift;
+ *n2 = n1 >> (64 - shift);
+ n1 = (n1 << shift) | (n0 >> (64 - shift));
+ n0 = n0 << shift;
+ } else {
+ *n2 = 0;
+ }
+ } else {
+ shift = r128__clz64(d0);
+ if (r128__clz64(n1) <= shift) {
+ return 1; // overflow
+ }
+
+ if (shift) {
+ d1 = d0 << shift;
+ d0 = 0;
+ *n2 = (n1 << shift) | (n0 >> (64 - shift));
+ n1 = n0 << shift;
+ n0 = 0;
+ } else {
+ d1 = d0;
+ d0 = 0;
+ *n2 = n1;
+ n1 = n0;
+ n0 = 0;
+ }
+ }
+
+ R128_SET2(n, n0, n1);
+ R128_SET2(d, d0, d1);
+ return 0;
+}
+
+static void r128__udiv(R128 *quotient, const R128 *dividend, const R128 *divisor)
+{
+ R128 tmp;
+ R128_U64 d0, d1;
+ R128_U64 n1, n2, n3;
+ R128 q;
+
+ R128_ASSERT(dividend != NULL);
+ R128_ASSERT(divisor != NULL);
+ R128_ASSERT(quotient != NULL);
+ R128_ASSERT(divisor->hi != 0 || divisor->lo != 0); // divide by zero
+
+ // scale dividend and normalize
+ {
+ R128 n, d;
+ R128_SET2(&n, dividend->lo, dividend->hi);
+ R128_SET2(&d, divisor->lo, divisor->hi);
+ if (r128__norm(&n, &d, &n3)) {
+ R128_SET2(quotient, R128_max.lo, R128_max.hi);
+ return;
+ }
+
+ d1 = d.hi;
+ d0 = d.lo;
+ n2 = n.hi;
+ n1 = n.lo;
+ }
+
+ // first digit
+ R128_ASSERT(n3 <= d1);
+ {
+ R128 t0, t1;
+ t0.lo = n1;
+ if (n3 < d1) {
+ q.hi = r128__udiv128(n2, n3, d1, &t0.hi);
+ } else {
+ q.hi = R128_LIT_U64(0xffffffffffffffff);
+ t0.hi = n2 + d1;
+ }
+
+refine1:
+ r128__umul128(&t1, q.hi, d0);
+ if (r128__ucmp(&t1, &t0) > 0) {
+ --q.hi;
+ if (t0.hi < ~d1 + 1) {
+ t0.hi += d1;
+ goto refine1;
+ }
+ }
+ }
+
+ {
+ R128 t0, t1, t2;
+ t0.hi = n2;
+ t0.lo = n1;
+
+ r128__umul128(&t1, q.hi, d0);
+ r128__umul128(&t2, q.hi, d1);
+
+ t2.hi = t2.lo; t2.lo = 0; //r128Shl(&t2, &t2, 64);
+ r128Add(&tmp, &t1, &t2);
+ r128Sub(&tmp, &t0, &tmp);
+ }
+ n2 = tmp.hi;
+ n1 = tmp.lo;
+
+ // second digit
+ R128_ASSERT(n2 <= d1);
+ {
+ R128 t0, t1;
+ t0.lo = 0;
+ if (n2 < d1) {
+ q.lo = r128__udiv128(n1, n2, d1, &t0.hi);
+ } else {
+ q.lo = R128_LIT_U64(0xffffffffffffffff);
+ t0.hi = n1 + d1;
+ }
+
+ refine0:
+ r128__umul128(&t1, q.lo, d0);
+ if (r128__ucmp(&t1, &t0) > 0) {
+ --q.lo;
+ if (t0.hi < ~d1 + 1) {
+ t0.hi += d1;
+ goto refine0;
+ }
+ }
+ }
+
+ R128_SET2(quotient, q.lo, q.hi);
+}
+
+static R128_U64 r128__umod(R128 *n, R128 *d)
+{
+ R128_U64 d0, d1;
+ R128_U64 n3, n2, n1;
+ R128_U64 q;
+
+ R128_ASSERT(d != NULL);
+ R128_ASSERT(n != NULL);
+ R128_ASSERT(d->hi != 0 || d->lo != 0); // divide by zero
+
+ if (r128__norm(n, d, &n3)) {
+ return R128_LIT_U64(0xffffffffffffffff);
+ }
+
+ d1 = d->hi;
+ d0 = d->lo;
+ n2 = n->hi;
+ n1 = n->lo;
+
+ R128_ASSERT(n3 < d1);
+ {
+ R128 t0, t1;
+ t0.lo = n1;
+ q = r128__udiv128(n2, n3, d1, &t0.hi);
+
+ refine1:
+ r128__umul128(&t1, q, d0);
+ if (r128__ucmp(&t1, &t0) > 0) {
+ --q;
+ if (t0.hi < ~d1 + 1) {
+ t0.hi += d1;
+ goto refine1;
+ }
+ }
+ }
+
+ return q;
+}
+
+static int r128__format(char *dst, size_t dstSize, const R128 *v, const R128ToStringFormat *format)
+{
+ char buf[128];
+ R128 tmp;
+ R128_U64 whole;
+ char *cursor, *decimal, *dstp = dst;
+ int sign = 0;
+ int fullPrecision = 1;
+ int width, precision;
+ int padCnt, trail = 0;
+
+ R128_ASSERT(dst != NULL && dstSize > 0);
+ R128_ASSERT(v != NULL);
+ R128_ASSERT(format != NULL);
+
+ --dstSize;
+
+ R128_SET2(&tmp, v->lo, v->hi);
+ if (r128IsNeg(&tmp)) {
+ r128__neg(&tmp, &tmp);
+ sign = 1;
+ }
+
+ width = format->width;
+ if (width < 0) {
+ width = 0;
+ }
+
+ precision = format->precision;
+ if (precision < 0) {
+ // print a maximum of 20 digits
+ fullPrecision = 0;
+ precision = 20;
+ } else if (precision > sizeof(buf) - 21) {
+ trail = precision - (sizeof(buf) - 21);
+ precision -= trail;
+ }
+
+ whole = tmp.hi;
+ decimal = cursor = buf;
+
+ // fractional part first in case a carry into the whole part is required
+ if (tmp.lo || format->decimal) {
+ while (tmp.lo || (fullPrecision && precision)) {
+ if ((int)(cursor - buf) == precision) {
+ if ((R128_S64)tmp.lo < 0) {
+ // round up, propagate carry backwards
+ char *c;
+ for (c = cursor - 1; c >= buf; --c) {
+ char d = ++*c;
+ if (d <= '9') {
+ goto endfrac;
+ } else {
+ *c = '0';
+ }
+ }
+
+ // carry out into the whole part
+ whole++;
+ }
+
+ break;
+ }
+
+ r128__umul128(&tmp, tmp.lo, 10);
+ *cursor++ = (char)tmp.hi + '0';
+ }
+
+ endfrac:
+ if (format->decimal || precision) {
+ decimal = cursor;
+ *cursor++ = R128_decimal;
+ }
+ }
+
+ // whole part
+ do {
+ char digit = (char)(whole % 10);
+ whole /= 10;
+ *cursor++ = digit + '0';
+ } while (whole);
+
+#define R128__WRITE(c) do { if (dstp < dst + dstSize) *dstp = c; ++dstp; } while(0)
+
+ padCnt = width - (int)(cursor - buf) - 1;
+
+ // left padding
+ if (!format->leftAlign) {
+ char padChar = format->zeroPad ? '0' : ' ';
+ if (format->zeroPad) {
+ if (sign) {
+ R128__WRITE('-');
+ } else if (format->sign == R128ToStringSign_Plus) {
+ R128__WRITE('+');
+ } else if (format->sign == R128ToStringSign_Space) {
+ R128__WRITE(' ');
+ } else {
+ ++padCnt;
+ }
+ }
+
+ for (; padCnt > 0; --padCnt) {
+ R128__WRITE(padChar);
+ }
+ }
+
+ if (format->leftAlign || !format->zeroPad) {
+ if (sign) {
+ R128__WRITE('-');
+ } else if (format->sign == R128ToStringSign_Plus) {
+ R128__WRITE('+');
+ } else if (format->sign == R128ToStringSign_Space) {
+ R128__WRITE(' ');
+ } else {
+ ++padCnt;
+ }
+ }
+
+ {
+ char *i;
+
+ // reverse the whole part
+ for (i = cursor - 1; i >= decimal; --i) {
+ R128__WRITE(*i);
+ }
+
+ // copy the fractional part
+ for (i = buf; i < decimal; ++i) {
+ R128__WRITE(*i);
+ }
+ }
+
+ // right padding
+ if (format->leftAlign) {
+ char padChar = format->zeroPad ? '0' : ' ';
+ for (; padCnt > 0; --padCnt) {
+ R128__WRITE(padChar);
+ }
+ }
+
+ // trailing zeroes for very large precision
+ while (trail--) {
+ R128__WRITE('0');
+ }
+
+#undef R128__WRITE
+
+ if (dstp <= dst + dstSize) {
+ *dstp = '\0';
+ } else {
+ dst[dstSize] = '\0';
+ }
+ return (int)(dstp - dst);
+}
+
+void r128FromInt(R128 *dst, R128_S64 v)
+{
+ R128_ASSERT(dst != NULL);
+ dst->lo = 0;
+ dst->hi = (R128_U64)v;
+ R128_DEBUG_SET(dst);
+}
+
+void r128FromFloat(R128 *dst, double v)
+{
+ R128_ASSERT(dst != NULL);
+
+ if (v < -9223372036854775808.0) {
+ r128Copy(dst, &R128_min);
+ } else if (v >= 9223372036854775808.0) {
+ r128Copy(dst, &R128_max);
+ } else {
+ R128 r;
+ int sign = 0;
+
+ if (v < 0) {
+ v = -v;
+ sign = 1;
+ }
+
+ r.hi = (R128_U64)(R128_S64)v;
+ v -= (R128_S64)v;
+ r.lo = (R128_U64)(v * 18446744073709551616.0);
+
+ if (sign) {
+ r128__neg(&r, &r);
+ }
+
+ r128Copy(dst, &r);
+ }
+}
+
+void r128FromString(R128 *dst, const char *s, char **endptr)
+{
+ R128_U64 lo = 0, hi = 0;
+ R128_U64 base = 10;
+
+ int sign = 0;
+
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(s != NULL);
+
+ R128_SET2(dst, 0, 0);
+
+ // consume whitespace
+ for (;;) {
+ if (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n' || *s == '\v') {
+ ++s;
+ } else {
+ break;
+ }
+ }
+
+ // sign
+ if (*s == '-') {
+ sign = 1;
+ ++s;
+ } else if (*s == '+') {
+ ++s;
+ }
+
+ // parse base prefix
+ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
+ base = 16;
+ s += 2;
+ }
+
+ // whole part
+ for (;; ++s) {
+ R128_U64 digit;
+
+ if ('0' <= *s && *s <= '9') {
+ digit = *s - '0';
+ } else if (base == 16 && 'a' <= *s && *s <= 'f') {
+ digit = *s - 'a' + 10;
+ } else if (base == 16 && 'A' <= *s && *s <= 'F') {
+ digit = *s - 'A' + 10;
+ } else {
+ break;
+ }
+
+ hi = hi * base + digit;
+ }
+
+ // fractional part
+ if (*s == R128_decimal) {
+ const char *exp = ++s;
+
+ // find the last digit and work backwards
+ for (;; ++s) {
+ if ('0' <= *s && *s <= '9') {
+ } else if (base == 16 && ('a' <= *s && *s <= 'f')) {
+ } else if (base == 16 && ('A' <= *s && *s <= 'F')) {
+ } else {
+ break;
+ }
+ }
+
+ for (--s; s >= exp; --s) {
+ R128_U64 digit, unused;
+
+ if ('0' <= *s && *s <= '9') {
+ digit = *s - '0';
+ } else if ('a' <= *s && *s <= 'f') {
+ digit = *s - 'a' + 10;
+ } else {
+ digit = *s - 'A' + 10;
+ }
+
+ lo = r128__udiv128(lo, digit, base, &unused);
+ }
+ }
+
+ R128_SET2(dst, lo, hi);
+ if (sign) {
+ r128__neg(dst, dst);
+ }
+
+ if (endptr) {
+ *endptr = (char *) s;
+ }
+}
+
+R128_S64 r128ToInt(const R128 *v)
+{
+ R128_ASSERT(v != NULL);
+ return (R128_S64)v->hi;
+}
+
+double r128ToFloat(const R128 *v)
+{
+ R128 tmp;
+ int sign = 0;
+ double d;
+
+ R128_ASSERT(v != NULL);
+
+ R128_SET2(&tmp, v->lo, v->hi);
+ if (r128IsNeg(&tmp)) {
+ r128__neg(&tmp, &tmp);
+ sign = 1;
+ }
+
+ d = tmp.hi + tmp.lo * (1 / 18446744073709551616.0);
+ if (sign) {
+ d = -d;
+ }
+
+ return d;
+}
+
+int r128ToStringOpt(char *dst, size_t dstSize, const R128 *v, const R128ToStringFormat *opt)
+{
+ return r128__format(dst, dstSize, v, opt);
+}
+
+int r128ToStringf(char *dst, size_t dstSize, const char *format, const R128 *v)
+{
+ R128ToStringFormat opts;
+
+ R128_ASSERT(dst != NULL && dstSize);
+ R128_ASSERT(format != NULL);
+ R128_ASSERT(v != NULL);
+
+ opts.sign = R128__defaultFormat.sign;
+ opts.precision = R128__defaultFormat.precision;
+ opts.zeroPad = R128__defaultFormat.zeroPad;
+ opts.decimal = R128__defaultFormat.decimal;
+ opts.leftAlign = R128__defaultFormat.leftAlign;
+
+ if (*format == '%') {
+ ++format;
+ }
+
+ // flags field
+ for (;; ++format) {
+ if (*format == ' ' && opts.sign != R128ToStringSign_Plus) {
+ opts.sign = R128ToStringSign_Space;
+ } else if (*format == '+') {
+ opts.sign = R128ToStringSign_Plus;
+ } else if (*format == '0') {
+ opts.zeroPad = 1;
+ } else if (*format == '-') {
+ opts.leftAlign = 1;
+ } else if (*format == '#') {
+ opts.decimal = 1;
+ } else {
+ break;
+ }
+ }
+
+ // width field
+ opts.width = 0;
+ for (;;) {
+ if ('0' <= *format && *format <= '9') {
+ opts.width = opts.width * 10 + *format++ - '0';
+ } else {
+ break;
+ }
+ }
+
+ // precision field
+ if (*format == '.') {
+ opts.precision = 0;
+ ++format;
+ for (;;) {
+ if ('0' <= *format && *format <= '9') {
+ opts.precision = opts.precision * 10 + *format++ - '0';
+ } else {
+ break;
+ }
+ }
+ }
+
+ return r128__format(dst, dstSize, v, &opts);
+}
+
+int r128ToString(char *dst, size_t dstSize, const R128 *v)
+{
+ return r128__format(dst, dstSize, v, &R128__defaultFormat);
+}
+
+void r128Copy(R128 *dst, const R128 *src)
+{
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(src != NULL);
+ dst->lo = src->lo;
+ dst->hi = src->hi;
+ R128_DEBUG_SET(dst);
+}
+
+void r128Neg(R128 *dst, const R128 *src)
+{
+ r128__neg(dst, src);
+ R128_DEBUG_SET(dst);
+}
+
+void r128Not(R128 *dst, const R128 *src)
+{
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(src != NULL);
+
+ dst->lo = ~src->lo;
+ dst->hi = ~src->hi;
+ R128_DEBUG_SET(dst);
+}
+
+void r128Or(R128 *dst, const R128 *a, const R128 *b)
+{
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+ dst->lo = a->lo | b->lo;
+ dst->hi = a->hi | b->hi;
+ R128_DEBUG_SET(dst);
+}
+
+void r128And(R128 *dst, const R128 *a, const R128 *b)
+{
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+ dst->lo = a->lo & b->lo;
+ dst->hi = a->hi & b->hi;
+ R128_DEBUG_SET(dst);
+}
+
+void r128Xor(R128 *dst, const R128 *a, const R128 *b)
+{
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+ dst->lo = a->lo ^ b->lo;
+ dst->hi = a->hi ^ b->hi;
+ R128_DEBUG_SET(dst);
+}
+
+void r128Shl(R128 *dst, const R128 *src, int amount)
+{
+ R128_U64 r[4];
+
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(src != NULL);
+
+#if defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
+ __asm {
+ // load src
+ mov edx, dword ptr[src]
+ mov ecx, amount
+
+ mov edi, dword ptr[edx]
+ mov esi, dword ptr[edx + 4]
+ mov ebx, dword ptr[edx + 8]
+ mov eax, dword ptr[edx + 12]
+
+ // shift mod 32
+ shld eax, ebx, cl
+ shld ebx, esi, cl
+ shld esi, edi, cl
+ shl edi, cl
+
+ // clear out low 12 bytes of stack
+ xor edx, edx
+ mov dword ptr[r], edx
+ mov dword ptr[r + 4], edx
+ mov dword ptr[r + 8], edx
+
+ // store shifted amount offset by count/32 bits
+ shr ecx, 5
+ and ecx, 3
+ mov dword ptr[r + ecx * 4 + 0], edi
+ mov dword ptr[r + ecx * 4 + 4], esi
+ mov dword ptr[r + ecx * 4 + 8], ebx
+ mov dword ptr[r + ecx * 4 + 12], eax
+ }
+#else
+
+ r[0] = src->lo;
+ r[1] = src->hi;
+
+ amount &= 127;
+ if (amount >= 64) {
+ r[1] = r[0] << (amount - 64);
+ r[0] = 0;
+ } else if (amount) {
+# ifdef _M_X64
+ r[1] = __shiftleft128(r[0], r[1], (char) amount);
+# else
+ r[1] = (r[1] << amount) | (r[0] >> (64 - amount));
+# endif
+ r[0] = r[0] << amount;
+ }
+#endif //_M_IX86
+
+ dst->lo = r[0];
+ dst->hi = r[1];
+ R128_DEBUG_SET(dst);
+}
+
+void r128Shr(R128 *dst, const R128 *src, int amount)
+{
+ R128_U64 r[4];
+
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(src != NULL);
+
+#if defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
+ __asm {
+ // load src
+ mov edx, dword ptr[src]
+ mov ecx, amount
+
+ mov edi, dword ptr[edx]
+ mov esi, dword ptr[edx + 4]
+ mov ebx, dword ptr[edx + 8]
+ mov eax, dword ptr[edx + 12]
+
+ // shift mod 32
+ shrd edi, esi, cl
+ shrd esi, ebx, cl
+ shrd ebx, eax, cl
+ shr eax, cl
+
+ // clear out high 12 bytes of stack
+ xor edx, edx
+ mov dword ptr[r + 20], edx
+ mov dword ptr[r + 24], edx
+ mov dword ptr[r + 28], edx
+
+ // store shifted amount offset by -count/32 bits
+ shr ecx, 5
+ and ecx, 3
+ neg ecx
+ mov dword ptr[r + ecx * 4 + 16], edi
+ mov dword ptr[r + ecx * 4 + 20], esi
+ mov dword ptr[r + ecx * 4 + 24], ebx
+ mov dword ptr[r + ecx * 4 + 28], eax
+ }
+#else
+ r[2] = src->lo;
+ r[3] = src->hi;
+
+ amount &= 127;
+ if (amount >= 64) {
+ r[2] = r[3] >> (amount - 64);
+ r[3] = 0;
+ } else if (amount) {
+#ifdef _M_X64
+ r[2] = __shiftright128(r[2], r[3], (char) amount);
+#else
+ r[2] = (r[2] >> amount) | (r[3] << (64 - amount));
+#endif
+ r[3] = r[3] >> amount;
+ }
+#endif
+
+ dst->lo = r[2];
+ dst->hi = r[3];
+ R128_DEBUG_SET(dst);
+}
+
+void r128Sar(R128 *dst, const R128 *src, int amount)
+{
+ R128_U64 r[4];
+
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(src != NULL);
+
+#if defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
+ __asm {
+ // load src
+ mov edx, dword ptr[src]
+ mov ecx, amount
+
+ mov edi, dword ptr[edx]
+ mov esi, dword ptr[edx + 4]
+ mov ebx, dword ptr[edx + 8]
+ mov eax, dword ptr[edx + 12]
+
+ // shift mod 32
+ shrd edi, esi, cl
+ shrd esi, ebx, cl
+ shrd ebx, eax, cl
+ sar eax, cl
+
+ // copy sign to high 12 bytes of stack
+ cdq
+ mov dword ptr[r + 20], edx
+ mov dword ptr[r + 24], edx
+ mov dword ptr[r + 28], edx
+
+ // store shifted amount offset by -count/32 bits
+ shr ecx, 5
+ and ecx, 3
+ neg ecx
+ mov dword ptr[r + ecx * 4 + 16], edi
+ mov dword ptr[r + ecx * 4 + 20], esi
+ mov dword ptr[r + ecx * 4 + 24], ebx
+ mov dword ptr[r + ecx * 4 + 28], eax
+ }
+#else
+ r[2] = src->lo;
+ r[3] = src->hi;
+
+ amount &= 127;
+ if (amount >= 64) {
+ r[2] = (R128_U64)((R128_S64)r[3] >> (amount - 64));
+ r[3] = (R128_U64)((R128_S64)r[3] >> 63);
+ } else if (amount) {
+ r[2] = (r[2] >> amount) | (R128_U64)((R128_S64)r[3] << (64 - amount));
+ r[3] = (R128_U64)((R128_S64)r[3] >> amount);
+ }
+#endif
+
+ dst->lo = r[2];
+ dst->hi = r[3];
+ R128_DEBUG_SET(dst);
+}
+
+void r128Add(R128 *dst, const R128 *a, const R128 *b)
+{
+ unsigned char carry = 0;
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+#if R128_INTEL && !defined(R128_STDC_ONLY)
+# if R128_64BIT
+ carry = _addcarry_u64(carry, a->lo, b->lo, &dst->lo);
+ carry = _addcarry_u64(carry, a->hi, b->hi, &dst->hi);
+# else
+ R128_U32 r0, r1, r2, r3;
+ carry = _addcarry_u32(carry, R128_R0(a), R128_R0(b), &r0);
+ carry = _addcarry_u32(carry, R128_R1(a), R128_R1(b), &r1);
+ carry = _addcarry_u32(carry, R128_R2(a), R128_R2(b), &r2);
+ carry = _addcarry_u32(carry, R128_R3(a), R128_R3(b), &r3);
+ R128_SET4(dst, r0, r1, r2, r3);
+# endif //R128_64BIT
+#else
+ {
+ R128_U64 r = a->lo + b->lo;
+ carry = r < a->lo;
+ dst->lo = r;
+ dst->hi = a->hi + b->hi + carry;
+ }
+#endif //R128_INTEL
+
+ R128_DEBUG_SET(dst);
+}
+
+void r128Sub(R128 *dst, const R128 *a, const R128 *b)
+{
+ unsigned char borrow = 0;
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+#if R128_INTEL && !defined(R128_STDC_ONLY)
+# if R128_64BIT
+ borrow = _subborrow_u64(borrow, a->lo, b->lo, &dst->lo);
+ borrow = _subborrow_u64(borrow, a->hi, b->hi, &dst->hi);
+# else
+ R128_U32 r0, r1, r2, r3;
+ borrow = _subborrow_u32(borrow, R128_R0(a), R128_R0(b), &r0);
+ borrow = _subborrow_u32(borrow, R128_R1(a), R128_R1(b), &r1);
+ borrow = _subborrow_u32(borrow, R128_R2(a), R128_R2(b), &r2);
+ borrow = _subborrow_u32(borrow, R128_R3(a), R128_R3(b), &r3);
+ R128_SET4(dst, r0, r1, r2, r3);
+# endif //R128_64BIT
+#else
+ {
+ R128_U64 r = a->lo - b->lo;
+ borrow = r > a->lo;
+ dst->lo = r;
+ dst->hi = a->hi - b->hi - borrow;
+ }
+#endif //R128_INTEL
+
+ R128_DEBUG_SET(dst);
+}
+
+void r128Mul(R128 *dst, const R128 *a, const R128 *b)
+{
+ int sign = 0;
+ R128 ta, tb, tc;
+
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+ R128_SET2(&ta, a->lo, a->hi);
+ R128_SET2(&tb, b->lo, b->hi);
+
+ if (r128IsNeg(&ta)) {
+ r128__neg(&ta, &ta);
+ sign = !sign;
+ }
+ if (r128IsNeg(&tb)) {
+ r128__neg(&tb, &tb);
+ sign = !sign;
+ }
+
+ r128__umul(&tc, &ta, &tb);
+ if (sign) {
+ r128__neg(&tc, &tc);
+ }
+
+ r128Copy(dst, &tc);
+}
+
+void r128Div(R128 *dst, const R128 *a, const R128 *b)
+{
+ int sign = 0;
+ R128 tn, td, tq;
+
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+ R128_SET2(&tn, a->lo, a->hi);
+ R128_SET2(&td, b->lo, b->hi);
+
+ if (r128IsNeg(&tn)) {
+ r128__neg(&tn, &tn);
+ sign = !sign;
+ }
+
+ if (td.lo == 0 && td.hi == 0) {
+ // divide by zero
+ if (sign) {
+ r128Copy(dst, &R128_min);
+ } else {
+ r128Copy(dst, &R128_max);
+ }
+ return;
+ } else if (r128IsNeg(&td)) {
+ r128__neg(&td, &td);
+ sign = !sign;
+ }
+
+ r128__udiv(&tq, &tn, &td);
+
+ if (sign) {
+ r128__neg(&tq, &tq);
+ }
+
+ r128Copy(dst, &tq);
+}
+
+void r128Mod(R128 *dst, const R128 *a, const R128 *b)
+{
+ int sign = 0;
+ R128 tn, td, tq;
+
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+ R128_SET2(&tn, a->lo, a->hi);
+ R128_SET2(&td, b->lo, b->hi);
+
+ if (r128IsNeg(&tn)) {
+ r128__neg(&tn, &tn);
+ sign = !sign;
+ }
+
+ if (td.lo == 0 && td.hi == 0) {
+ // divide by zero
+ if (sign) {
+ r128Copy(dst, &R128_min);
+ } else {
+ r128Copy(dst, &R128_max);
+ }
+ return;
+ } else if (r128IsNeg(&td)) {
+ r128__neg(&td, &td);
+ sign = !sign;
+ }
+
+ tq.hi = r128__umod(&tn, &td);
+ tq.lo = 0;
+
+ if (sign) {
+ tq.hi = ~tq.hi + 1;
+ }
+
+ r128Mul(&tq, &tq, b);
+ r128Sub(dst, a, &tq);
+}
+
+void r128Rsqrt(R128 *dst, const R128 *v)
+{
+ static const R128 threeHalves = { R128_LIT_U64(0x8000000000000000), 1 };
+ R128 x, est;
+ int i;
+
+ if ((R128_S64)v->hi < 0) {
+ r128Copy(dst, &R128_min);
+ return;
+ }
+
+ R128_SET2(&x, v->lo, v->hi);
+
+ // get initial estimate
+ if (x.hi) {
+ int shift = (64 + r128__clz64(x.hi)) >> 1;
+ est.lo = R128_LIT_U64(1) << shift;
+ est.hi = 0;
+ } else if (x.lo) {
+ int shift = r128__clz64(x.lo) >> 1;
+ est.hi = R128_LIT_U64(1) << shift;
+ est.lo = 0;
+ } else {
+ R128_SET2(dst, 0, 0);
+ return;
+ }
+
+ // x /= 2
+ r128Shr(&x, &x, 1);
+
+ // Newton-Raphson iterate
+ for (i = 0; i < 7; ++i) {
+ R128 newEst;
+
+ // newEst = est * (threeHalves - (x / 2) * est * est);
+ r128__umul(&newEst, &est, &est);
+ r128__umul(&newEst, &newEst, &x);
+ r128Sub(&newEst, &threeHalves, &newEst);
+ r128__umul(&newEst, &est, &newEst);
+
+ if (newEst.lo == est.lo && newEst.hi == est.hi) {
+ break;
+ }
+ R128_SET2(&est, newEst.lo, newEst.hi);
+ }
+
+ r128Copy(dst, &est);
+}
+
+void r128Sqrt(R128 *dst, const R128 *v)
+{
+ R128 x, est;
+ int i;
+
+ if ((R128_S64)v->hi < 0) {
+ r128Copy(dst, &R128_min);
+ return;
+ }
+
+ R128_SET2(&x, v->lo, v->hi);
+
+ // get initial estimate
+ if (x.hi) {
+ int shift = (63 - r128__clz64(x.hi)) >> 1;
+ r128Shr(&est, &x, shift);
+ } else if (x.lo) {
+ int shift = (1 + r128__clz64(x.lo)) >> 1;
+ r128Shl(&est, &x, shift);
+ } else {
+ R128_SET2(dst, 0, 0);
+ return;
+ }
+
+ // Newton-Raphson iterate
+ for (i = 0; i < 7; ++i) {
+ R128 newEst;
+
+ // newEst = (est + x / est) / 2
+ r128__udiv(&newEst, &x, &est);
+ r128Add(&newEst, &newEst, &est);
+ r128Shr(&newEst, &newEst, 1);
+
+ if (newEst.lo == est.lo && newEst.hi == est.hi) {
+ break;
+ }
+ R128_SET2(&est, newEst.lo, newEst.hi);
+ }
+
+ r128Copy(dst, &est);
+}
+
+int r128Cmp(const R128 *a, const R128 *b)
+{
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+ if (a->hi == b->hi) {
+ if (a->lo == b->lo) {
+ return 0;
+ } else if (a->lo > b->lo) {
+ return 1;
+ } else {
+ return -1;
+ }
+ } else if ((R128_S64)a->hi > (R128_S64)b->hi) {
+ return 1;
+ } else {
+ return -1;
+ }
+}
+
+int r128IsNeg(const R128 *v)
+{
+ R128_ASSERT(v != NULL);
+
+ return (R128_S64)v->hi < 0;
+}
+
+void r128Min(R128 *dst, const R128 *a, const R128 *b)
+{
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+ if (r128Cmp(a, b) < 0) {
+ r128Copy(dst, a);
+ } else {
+ r128Copy(dst, b);
+ }
+}
+
+void r128Max(R128 *dst, const R128 *a, const R128 *b)
+{
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(a != NULL);
+ R128_ASSERT(b != NULL);
+
+ if (r128Cmp(a, b) > 0) {
+ r128Copy(dst, a);
+ } else {
+ r128Copy(dst, b);
+ }
+}
+
+void r128Floor(R128 *dst, const R128 *v)
+{
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(v != NULL);
+
+ if ((R128_S64)v->hi < 0) {
+ dst->hi = v->hi - (v->lo != 0);
+ } else {
+ dst->hi = v->hi;
+ }
+ dst->lo = 0;
+ R128_DEBUG_SET(dst);
+}
+
+void r128Ceil(R128 *dst, const R128 *v)
+{
+ R128_ASSERT(dst != NULL);
+ R128_ASSERT(v != NULL);
+
+ if ((R128_S64)v->hi > 0) {
+ dst->hi = v->hi + (v->lo != 0);
+ } else {
+ dst->hi = v->hi;
+ }
+ dst->lo = 0;
+ R128_DEBUG_SET(dst);
+}
+
+#endif //R128_IMPLEMENTATION
diff --git a/thirdparty/misc/stb_rect_pack.h b/thirdparty/misc/stb_rect_pack.h
new file mode 100644
index 0000000000..5c848de0e7
--- /dev/null
+++ b/thirdparty/misc/stb_rect_pack.h
@@ -0,0 +1,628 @@
+// stb_rect_pack.h - v1.00 - public domain - rectangle packing
+// Sean Barrett 2014
+//
+// Useful for e.g. packing rectangular textures into an atlas.
+// Does not do rotation.
+//
+// Not necessarily the awesomest packing method, but better than
+// the totally naive one in stb_truetype (which is primarily what
+// this is meant to replace).
+//
+// Has only had a few tests run, may have issues.
+//
+// More docs to come.
+//
+// No memory allocations; uses qsort() and assert() from stdlib.
+// Can override those by defining STBRP_SORT and STBRP_ASSERT.
+//
+// This library currently uses the Skyline Bottom-Left algorithm.
+//
+// Please note: better rectangle packers are welcome! Please
+// implement them to the same API, but with a different init
+// function.
+//
+// Credits
+//
+// Library
+// Sean Barrett
+// Minor features
+// Martins Mozeiko
+// github:IntellectualKitty
+//
+// Bugfixes / warning fixes
+// Jeremy Jaussaud
+// Fabian Giesen
+//
+// Version history:
+//
+// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
+// 0.99 (2019-02-07) warning fixes
+// 0.11 (2017-03-03) return packing success/fail result
+// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
+// 0.09 (2016-08-27) fix compiler warnings
+// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
+// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
+// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
+// 0.05: added STBRP_ASSERT to allow replacing assert
+// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
+// 0.01: initial release
+//
+// LICENSE
+//
+// See end of file for license information.
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// INCLUDE SECTION
+//
+
+#ifndef STB_INCLUDE_STB_RECT_PACK_H
+#define STB_INCLUDE_STB_RECT_PACK_H
+
+#define STB_RECT_PACK_VERSION 1
+
+#ifdef STBRP_STATIC
+#define STBRP_DEF static
+#else
+#define STBRP_DEF extern
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct stbrp_context stbrp_context;
+typedef struct stbrp_node stbrp_node;
+typedef struct stbrp_rect stbrp_rect;
+
+#ifdef STBRP_LARGE_RECTS
+typedef int stbrp_coord;
+#else
+typedef unsigned short stbrp_coord;
+#endif
+
+STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
+// Assign packed locations to rectangles. The rectangles are of type
+// 'stbrp_rect' defined below, stored in the array 'rects', and there
+// are 'num_rects' many of them.
+//
+// Rectangles which are successfully packed have the 'was_packed' flag
+// set to a non-zero value and 'x' and 'y' store the minimum location
+// on each axis (i.e. bottom-left in cartesian coordinates, top-left
+// if you imagine y increasing downwards). Rectangles which do not fit
+// have the 'was_packed' flag set to 0.
+//
+// You should not try to access the 'rects' array from another thread
+// while this function is running, as the function temporarily reorders
+// the array while it executes.
+//
+// To pack into another rectangle, you need to call stbrp_init_target
+// again. To continue packing into the same rectangle, you can call
+// this function again. Calling this multiple times with multiple rect
+// arrays will probably produce worse packing results than calling it
+// a single time with the full rectangle array, but the option is
+// available.
+//
+// The function returns 1 if all of the rectangles were successfully
+// packed and 0 otherwise.
+
+struct stbrp_rect
+{
+ // reserved for your use:
+ int id;
+
+ // input:
+ stbrp_coord w, h;
+
+ // output:
+ stbrp_coord x, y;
+ int was_packed; // non-zero if valid packing
+
+}; // 16 bytes, nominally
+
+
+STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
+// Initialize a rectangle packer to:
+// pack a rectangle that is 'width' by 'height' in dimensions
+// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
+//
+// You must call this function every time you start packing into a new target.
+//
+// There is no "shutdown" function. The 'nodes' memory must stay valid for
+// the following stbrp_pack_rects() call (or calls), but can be freed after
+// the call (or calls) finish.
+//
+// Note: to guarantee best results, either:
+// 1. make sure 'num_nodes' >= 'width'
+// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
+//
+// If you don't do either of the above things, widths will be quantized to multiples
+// of small integers to guarantee the algorithm doesn't run out of temporary storage.
+//
+// If you do #2, then the non-quantized algorithm will be used, but the algorithm
+// may run out of temporary storage and be unable to pack some rectangles.
+
+STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
+// Optionally call this function after init but before doing any packing to
+// change the handling of the out-of-temp-memory scenario, described above.
+// If you call init again, this will be reset to the default (false).
+
+
+STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
+// Optionally select which packing heuristic the library should use. Different
+// heuristics will produce better/worse results for different data sets.
+// If you call init again, this will be reset to the default.
+
+enum
+{
+ STBRP_HEURISTIC_Skyline_default=0,
+ STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
+ STBRP_HEURISTIC_Skyline_BF_sortHeight
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// the details of the following structures don't matter to you, but they must
+// be visible so you can handle the memory allocations for them
+
+struct stbrp_node
+{
+ stbrp_coord x,y;
+ stbrp_node *next;
+};
+
+struct stbrp_context
+{
+ int width;
+ int height;
+ int align;
+ int init_mode;
+ int heuristic;
+ int num_nodes;
+ stbrp_node *active_head;
+ stbrp_node *free_head;
+ stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// IMPLEMENTATION SECTION
+//
+
+#ifdef STB_RECT_PACK_IMPLEMENTATION
+#ifndef STBRP_SORT
+#include <stdlib.h>
+#define STBRP_SORT qsort
+#endif
+
+#ifndef STBRP_ASSERT
+#include <assert.h>
+#define STBRP_ASSERT assert
+#endif
+
+#ifdef _MSC_VER
+#define STBRP__NOTUSED(v) (void)(v)
+#else
+#define STBRP__NOTUSED(v) (void)sizeof(v)
+#endif
+
+enum
+{
+ STBRP__INIT_skyline = 1
+};
+
+STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
+{
+ switch (context->init_mode) {
+ case STBRP__INIT_skyline:
+ STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
+ context->heuristic = heuristic;
+ break;
+ default:
+ STBRP_ASSERT(0);
+ }
+}
+
+STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
+{
+ if (allow_out_of_mem)
+ // if it's ok to run out of memory, then don't bother aligning them;
+ // this gives better packing, but may fail due to OOM (even though
+ // the rectangles easily fit). @TODO a smarter approach would be to only
+ // quantize once we've hit OOM, then we could get rid of this parameter.
+ context->align = 1;
+ else {
+ // if it's not ok to run out of memory, then quantize the widths
+ // so that num_nodes is always enough nodes.
+ //
+ // I.e. num_nodes * align >= width
+ // align >= width / num_nodes
+ // align = ceil(width/num_nodes)
+
+ context->align = (context->width + context->num_nodes-1) / context->num_nodes;
+ }
+}
+
+STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
+{
+ int i;
+#ifndef STBRP_LARGE_RECTS
+ STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
+#endif
+
+ for (i=0; i < num_nodes-1; ++i)
+ nodes[i].next = &nodes[i+1];
+ nodes[i].next = NULL;
+ context->init_mode = STBRP__INIT_skyline;
+ context->heuristic = STBRP_HEURISTIC_Skyline_default;
+ context->free_head = &nodes[0];
+ context->active_head = &context->extra[0];
+ context->width = width;
+ context->height = height;
+ context->num_nodes = num_nodes;
+ stbrp_setup_allow_out_of_mem(context, 0);
+
+ // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
+ context->extra[0].x = 0;
+ context->extra[0].y = 0;
+ context->extra[0].next = &context->extra[1];
+ context->extra[1].x = (stbrp_coord) width;
+#ifdef STBRP_LARGE_RECTS
+ context->extra[1].y = (1<<30);
+#else
+ context->extra[1].y = 65535;
+#endif
+ context->extra[1].next = NULL;
+}
+
+// find minimum y position if it starts at x1
+static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
+{
+ stbrp_node *node = first;
+ int x1 = x0 + width;
+ int min_y, visited_width, waste_area;
+
+ STBRP__NOTUSED(c);
+
+ STBRP_ASSERT(first->x <= x0);
+
+ #if 0
+ // skip in case we're past the node
+ while (node->next->x <= x0)
+ ++node;
+ #else
+ STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
+ #endif
+
+ STBRP_ASSERT(node->x <= x0);
+
+ min_y = 0;
+ waste_area = 0;
+ visited_width = 0;
+ while (node->x < x1) {
+ if (node->y > min_y) {
+ // raise min_y higher.
+ // we've accounted for all waste up to min_y,
+ // but we'll now add more waste for everything we've visted
+ waste_area += visited_width * (node->y - min_y);
+ min_y = node->y;
+ // the first time through, visited_width might be reduced
+ if (node->x < x0)
+ visited_width += node->next->x - x0;
+ else
+ visited_width += node->next->x - node->x;
+ } else {
+ // add waste area
+ int under_width = node->next->x - node->x;
+ if (under_width + visited_width > width)
+ under_width = width - visited_width;
+ waste_area += under_width * (min_y - node->y);
+ visited_width += under_width;
+ }
+ node = node->next;
+ }
+
+ *pwaste = waste_area;
+ return min_y;
+}
+
+typedef struct
+{
+ int x,y;
+ stbrp_node **prev_link;
+} stbrp__findresult;
+
+static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
+{
+ int best_waste = (1<<30), best_x, best_y = (1 << 30);
+ stbrp__findresult fr;
+ stbrp_node **prev, *node, *tail, **best = NULL;
+
+ // align to multiple of c->align
+ width = (width + c->align - 1);
+ width -= width % c->align;
+ STBRP_ASSERT(width % c->align == 0);
+
+ // if it can't possibly fit, bail immediately
+ if (width > c->width || height > c->height) {
+ fr.prev_link = NULL;
+ fr.x = fr.y = 0;
+ return fr;
+ }
+
+ node = c->active_head;
+ prev = &c->active_head;
+ while (node->x + width <= c->width) {
+ int y,waste;
+ y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
+ if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
+ // bottom left
+ if (y < best_y) {
+ best_y = y;
+ best = prev;
+ }
+ } else {
+ // best-fit
+ if (y + height <= c->height) {
+ // can only use it if it first vertically
+ if (y < best_y || (y == best_y && waste < best_waste)) {
+ best_y = y;
+ best_waste = waste;
+ best = prev;
+ }
+ }
+ }
+ prev = &node->next;
+ node = node->next;
+ }
+
+ best_x = (best == NULL) ? 0 : (*best)->x;
+
+ // if doing best-fit (BF), we also have to try aligning right edge to each node position
+ //
+ // e.g, if fitting
+ //
+ // ____________________
+ // |____________________|
+ //
+ // into
+ //
+ // | |
+ // | ____________|
+ // |____________|
+ //
+ // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
+ //
+ // This makes BF take about 2x the time
+
+ if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
+ tail = c->active_head;
+ node = c->active_head;
+ prev = &c->active_head;
+ // find first node that's admissible
+ while (tail->x < width)
+ tail = tail->next;
+ while (tail) {
+ int xpos = tail->x - width;
+ int y,waste;
+ STBRP_ASSERT(xpos >= 0);
+ // find the left position that matches this
+ while (node->next->x <= xpos) {
+ prev = &node->next;
+ node = node->next;
+ }
+ STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
+ y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
+ if (y + height <= c->height) {
+ if (y <= best_y) {
+ if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
+ best_x = xpos;
+ STBRP_ASSERT(y <= best_y);
+ best_y = y;
+ best_waste = waste;
+ best = prev;
+ }
+ }
+ }
+ tail = tail->next;
+ }
+ }
+
+ fr.prev_link = best;
+ fr.x = best_x;
+ fr.y = best_y;
+ return fr;
+}
+
+static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
+{
+ // find best position according to heuristic
+ stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
+ stbrp_node *node, *cur;
+
+ // bail if:
+ // 1. it failed
+ // 2. the best node doesn't fit (we don't always check this)
+ // 3. we're out of memory
+ if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
+ res.prev_link = NULL;
+ return res;
+ }
+
+ // on success, create new node
+ node = context->free_head;
+ node->x = (stbrp_coord) res.x;
+ node->y = (stbrp_coord) (res.y + height);
+
+ context->free_head = node->next;
+
+ // insert the new node into the right starting point, and
+ // let 'cur' point to the remaining nodes needing to be
+ // stiched back in
+
+ cur = *res.prev_link;
+ if (cur->x < res.x) {
+ // preserve the existing one, so start testing with the next one
+ stbrp_node *next = cur->next;
+ cur->next = node;
+ cur = next;
+ } else {
+ *res.prev_link = node;
+ }
+
+ // from here, traverse cur and free the nodes, until we get to one
+ // that shouldn't be freed
+ while (cur->next && cur->next->x <= res.x + width) {
+ stbrp_node *next = cur->next;
+ // move the current node to the free list
+ cur->next = context->free_head;
+ context->free_head = cur;
+ cur = next;
+ }
+
+ // stitch the list back in
+ node->next = cur;
+
+ if (cur->x < res.x + width)
+ cur->x = (stbrp_coord) (res.x + width);
+
+#ifdef _DEBUG
+ cur = context->active_head;
+ while (cur->x < context->width) {
+ STBRP_ASSERT(cur->x < cur->next->x);
+ cur = cur->next;
+ }
+ STBRP_ASSERT(cur->next == NULL);
+
+ {
+ int count=0;
+ cur = context->active_head;
+ while (cur) {
+ cur = cur->next;
+ ++count;
+ }
+ cur = context->free_head;
+ while (cur) {
+ cur = cur->next;
+ ++count;
+ }
+ STBRP_ASSERT(count == context->num_nodes+2);
+ }
+#endif
+
+ return res;
+}
+
+static int rect_height_compare(const void *a, const void *b)
+{
+ const stbrp_rect *p = (const stbrp_rect *) a;
+ const stbrp_rect *q = (const stbrp_rect *) b;
+ if (p->h > q->h)
+ return -1;
+ if (p->h < q->h)
+ return 1;
+ return (p->w > q->w) ? -1 : (p->w < q->w);
+}
+
+static int rect_original_order(const void *a, const void *b)
+{
+ const stbrp_rect *p = (const stbrp_rect *) a;
+ const stbrp_rect *q = (const stbrp_rect *) b;
+ return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
+}
+
+#ifdef STBRP_LARGE_RECTS
+#define STBRP__MAXVAL 0xffffffff
+#else
+#define STBRP__MAXVAL 0xffff
+#endif
+
+STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
+{
+ int i, all_rects_packed = 1;
+
+ // we use the 'was_packed' field internally to allow sorting/unsorting
+ for (i=0; i < num_rects; ++i) {
+ rects[i].was_packed = i;
+ }
+
+ // sort according to heuristic
+ STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
+
+ for (i=0; i < num_rects; ++i) {
+ if (rects[i].w == 0 || rects[i].h == 0) {
+ rects[i].x = rects[i].y = 0; // empty rect needs no space
+ } else {
+ stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
+ if (fr.prev_link) {
+ rects[i].x = (stbrp_coord) fr.x;
+ rects[i].y = (stbrp_coord) fr.y;
+ } else {
+ rects[i].x = rects[i].y = STBRP__MAXVAL;
+ }
+ }
+ }
+
+ // unsort
+ STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
+
+ // set was_packed flags and all_rects_packed status
+ for (i=0; i < num_rects; ++i) {
+ rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
+ if (!rects[i].was_packed)
+ all_rects_packed = 0;
+ }
+
+ // return the all_rects_packed status
+ return all_rects_packed;
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/thirdparty/misc/stb_vorbis.c b/thirdparty/misc/stb_vorbis.c
index 4ab8880d5d..b0d79b1724 100644
--- a/thirdparty/misc/stb_vorbis.c
+++ b/thirdparty/misc/stb_vorbis.c
@@ -1,4 +1,4 @@
-// Ogg Vorbis audio decoder - v1.17 - public domain
+// Ogg Vorbis audio decoder - v1.19 - public domain
// http://nothings.org/stb_vorbis/
//
// Original version written by Sean Barrett in 2007.
@@ -26,13 +26,16 @@
// Terje Mathisen Niklas Frykholm Andy Hill
// Casey Muratori John Bolton Gargaj
// Laurent Gomila Marc LeBlanc Ronny Chevalier
-// Bernhard Wodo Evan Balster alxprd@github
+// Bernhard Wodo Evan Balster github:alxprd
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart
-// manxorist@github saga musix github:infatum
-// Timur Gagiev Maxwell Koo
+// github:manxorist saga musix github:infatum
+// Timur Gagiev Maxwell Koo Peter Waller
+// github:audinowho Dougall Johnson
//
// Partial history:
+// 1.19 - 2020-02-05 - warnings
+// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc.
// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure)
// 1.16 - 2019-03-04 - fix warnings
// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found
@@ -130,9 +133,20 @@ typedef struct
int max_frame_size;
} stb_vorbis_info;
+typedef struct
+{
+ char *vendor;
+
+ int comment_list_length;
+ char **comment_list;
+} stb_vorbis_comment;
+
// get general information about the file
extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f);
+// get ogg comments
+extern stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f);
+
// get the last error detected (clears it, too)
extern int stb_vorbis_get_error(stb_vorbis *f);
@@ -759,6 +773,10 @@ struct stb_vorbis
unsigned int temp_memory_required;
unsigned int setup_temp_memory_required;
+ char *vendor;
+ int comment_list_length;
+ char **comment_list;
+
// input config
#ifndef STB_VORBIS_NO_STDIO
FILE *f;
@@ -774,8 +792,11 @@ struct stb_vorbis
uint8 push_mode;
+ // the page to seek to when seeking to start, may be zero
uint32 first_audio_page_offset;
+ // p_first is the page on which the first audio packet ends
+ // (but not necessarily the page on which it starts)
ProbedPage p_first, p_last;
// memory management
@@ -888,7 +909,7 @@ static int error(vorb *f, enum STBVorbisError e)
#define array_size_required(count,size) (count*(sizeof(void *)+(size)))
#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size))
-#define temp_free(f,p) 0
+#define temp_free(f,p) (void)0
#define temp_alloc_save(f) ((f)->temp_offset)
#define temp_alloc_restore(f,p) ((f)->temp_offset = (p))
@@ -909,7 +930,7 @@ static void *make_block_array(void *mem, int count, int size)
static void *setup_malloc(vorb *f, int sz)
{
- sz = (sz+3) & ~3;
+ sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs.
f->setup_memory_required += sz;
if (f->alloc.alloc_buffer) {
void *p = (char *) f->alloc.alloc_buffer + f->setup_offset;
@@ -928,7 +949,7 @@ static void setup_free(vorb *f, void *p)
static void *setup_temp_malloc(vorb *f, int sz)
{
- sz = (sz+3) & ~3;
+ sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs.
if (f->alloc.alloc_buffer) {
if (f->temp_offset - sz < f->setup_offset) return NULL;
f->temp_offset -= sz;
@@ -940,7 +961,7 @@ static void *setup_temp_malloc(vorb *f, int sz)
static void setup_temp_free(vorb *f, void *p, int sz)
{
if (f->alloc.alloc_buffer) {
- f->temp_offset += (sz+3)&~3;
+ f->temp_offset += (sz+7)&~7;
return;
}
free(p);
@@ -1404,6 +1425,9 @@ static int capture_pattern(vorb *f)
static int start_page_no_capturepattern(vorb *f)
{
uint32 loc0,loc1,n;
+ if (f->first_decode && !IS_PUSH_MODE(f)) {
+ f->p_first.page_start = stb_vorbis_get_file_offset(f) - 4;
+ }
// stream structure version
if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version);
// header flag
@@ -1440,15 +1464,12 @@ static int start_page_no_capturepattern(vorb *f)
}
if (f->first_decode) {
int i,len;
- ProbedPage p;
len = 0;
for (i=0; i < f->segment_count; ++i)
len += f->segments[i];
len += 27 + f->segment_count;
- p.page_start = f->first_audio_page_offset;
- p.page_end = p.page_start + len;
- p.last_decoded_sample = loc0;
- f->p_first = p;
+ f->p_first.page_end = f->p_first.page_start + len;
+ f->p_first.last_decoded_sample = loc0;
}
f->next_seg = 0;
return TRUE;
@@ -1539,6 +1560,16 @@ static int get8_packet(vorb *f)
return x;
}
+static int get32_packet(vorb *f)
+{
+ uint32 x;
+ x = get8_packet(f);
+ x += get8_packet(f) << 8;
+ x += get8_packet(f) << 16;
+ x += (uint32) get8_packet(f) << 24;
+ return x;
+}
+
static void flush_packet(vorb *f)
{
while (get8_packet_raw(f) != EOP);
@@ -2130,47 +2161,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
++class_set;
#endif
}
- } else if (ch == 1) {
- while (pcount < part_read) {
- int z = r->begin + pcount*r->part_size;
- int c_inter = 0, p_inter = z;
- if (pass == 0) {
- Codebook *c = f->codebooks+r->classbook;
- int q;
- DECODE(q,f,c);
- if (q == EOP) goto done;
- #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
- part_classdata[0][class_set] = r->classdata[q];
- #else
- for (i=classwords-1; i >= 0; --i) {
- classifications[0][i+pcount] = q % r->classifications;
- q /= r->classifications;
- }
- #endif
- }
- for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
- int z = r->begin + pcount*r->part_size;
- #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
- int c = part_classdata[0][class_set][i];
- #else
- int c = classifications[0][pcount];
- #endif
- int b = r->residue_books[c][pass];
- if (b >= 0) {
- Codebook *book = f->codebooks + b;
- if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
- goto done;
- } else {
- z += r->part_size;
- c_inter = 0;
- p_inter = z;
- }
- }
- #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
- ++class_set;
- #endif
- }
- } else {
+ } else if (ch > 2) {
while (pcount < part_read) {
int z = r->begin + pcount*r->part_size;
int c_inter = z % ch, p_inter = z/ch;
@@ -3504,7 +3495,7 @@ static int vorbis_pump_first_frame(stb_vorbis *f)
}
#ifndef STB_VORBIS_NO_PUSHDATA_API
-static int is_whole_packet_present(stb_vorbis *f, int end_page)
+static int is_whole_packet_present(stb_vorbis *f)
{
// make sure that we have the packet available before continuing...
// this requires a full ogg parse, but we know we can fetch from f->stream
@@ -3524,8 +3515,6 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page)
break;
}
// either this continues, or it ends it...
- if (end_page)
- if (s < f->segment_count-1) return error(f, VORBIS_invalid_stream);
if (s == f->segment_count)
s = -1; // set 'crosses page' flag
if (p > f->stream_end) return error(f, VORBIS_need_more_data);
@@ -3558,8 +3547,6 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page)
if (q[s] < 255)
break;
}
- if (end_page)
- if (s < n-1) return error(f, VORBIS_invalid_stream);
if (s == n)
s = -1; // set 'crosses page' flag
if (p > f->stream_end) return error(f, VORBIS_need_more_data);
@@ -3576,6 +3563,7 @@ static int start_decoder(vorb *f)
int longest_floorlist=0;
// first page, first packet
+ f->first_decode = TRUE;
if (!start_page(f)) return FALSE;
// validate page flag
@@ -3633,6 +3621,41 @@ static int start_decoder(vorb *f)
if (!start_page(f)) return FALSE;
if (!start_packet(f)) return FALSE;
+
+ if (!next_segment(f)) return FALSE;
+
+ if (get8_packet(f) != VORBIS_packet_comment) return error(f, VORBIS_invalid_setup);
+ for (i=0; i < 6; ++i) header[i] = get8_packet(f);
+ if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup);
+ //file vendor
+ len = get32_packet(f);
+ f->vendor = (char*)setup_malloc(f, sizeof(char) * (len+1));
+ for(i=0; i < len; ++i) {
+ f->vendor[i] = get8_packet(f);
+ }
+ f->vendor[len] = (char)'\0';
+ //user comments
+ f->comment_list_length = get32_packet(f);
+ f->comment_list = (char**)setup_malloc(f, sizeof(char*) * (f->comment_list_length));
+
+ for(i=0; i < f->comment_list_length; ++i) {
+ len = get32_packet(f);
+ f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1));
+
+ for(j=0; j < len; ++j) {
+ f->comment_list[i][j] = get8_packet(f);
+ }
+ f->comment_list[i][len] = (char)'\0';
+ }
+
+ // framing_flag
+ x = get8_packet(f);
+ if (!(x & 1)) return error(f, VORBIS_invalid_setup);
+
+
+ skip(f, f->bytes_in_seg);
+ f->bytes_in_seg = 0;
+
do {
len = next_segment(f);
skip(f, len);
@@ -3644,7 +3667,7 @@ static int start_decoder(vorb *f)
#ifndef STB_VORBIS_NO_PUSHDATA_API
if (IS_PUSH_MODE(f)) {
- if (!is_whole_packet_present(f, TRUE)) {
+ if (!is_whole_packet_present(f)) {
// convert error in ogg header to write type
if (f->error == VORBIS_invalid_stream)
f->error = VORBIS_invalid_setup;
@@ -3947,7 +3970,7 @@ static int start_decoder(vorb *f)
g->sorted_order[j] = (uint8) p[j].id;
// precompute the neighbors
for (j=2; j < g->values; ++j) {
- int low,hi;
+ int low = 0,hi = 0;
neighbors(g->Xlist, j, &low,&hi);
g->neighbors[j][0] = low;
g->neighbors[j][1] = hi;
@@ -4132,7 +4155,6 @@ static int start_decoder(vorb *f)
f->temp_memory_required = imdct_mem;
}
- f->first_decode = TRUE;
if (f->alloc.alloc_buffer) {
assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes);
@@ -4141,7 +4163,17 @@ static int start_decoder(vorb *f)
return error(f, VORBIS_outofmem);
}
- f->first_audio_page_offset = stb_vorbis_get_file_offset(f);
+ // @TODO: stb_vorbis_seek_start expects first_audio_page_offset to point to a page
+ // without PAGEFLAG_continued_packet, so this either points to the first page, or
+ // the page after the end of the headers. It might be cleaner to point to a page
+ // in the middle of the headers, when that's the page where the first audio packet
+ // starts, but we'd have to also correctly skip the end of any continued packet in
+ // stb_vorbis_seek_start.
+ if (f->next_seg == -1) {
+ f->first_audio_page_offset = stb_vorbis_get_file_offset(f);
+ } else {
+ f->first_audio_page_offset = 0;
+ }
return TRUE;
}
@@ -4149,6 +4181,13 @@ static int start_decoder(vorb *f)
static void vorbis_deinit(stb_vorbis *p)
{
int i,j;
+
+ setup_free(p, p->vendor);
+ for (i=0; i < p->comment_list_length; ++i) {
+ setup_free(p, p->comment_list[i]);
+ }
+ setup_free(p, p->comment_list);
+
if (p->residue_config) {
for (i=0; i < p->residue_count; ++i) {
Residue *r = p->residue_config+i;
@@ -4248,6 +4287,15 @@ stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f)
return d;
}
+stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f)
+{
+ stb_vorbis_comment d;
+ d.vendor = f->vendor;
+ d.comment_list_length = f->comment_list_length;
+ d.comment_list = f->comment_list;
+ return d;
+}
+
int stb_vorbis_get_error(stb_vorbis *f)
{
int e = f->error;
@@ -4389,7 +4437,7 @@ int stb_vorbis_decode_frame_pushdata(
f->error = VORBIS__no_error;
// check that we have the entire packet in memory
- if (!is_whole_packet_present(f, FALSE)) {
+ if (!is_whole_packet_present(f)) {
*samples = 0;
return 0;
}
@@ -4625,8 +4673,8 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
{
ProbedPage left, right, mid;
int i, start_seg_with_known_loc, end_pos, page_start;
- uint32 delta, stream_length, padding;
- double offset, bytes_per_sample;
+ uint32 delta, stream_length, padding, last_sample_limit;
+ double offset = 0.0, bytes_per_sample = 0.0;
int probe = 0;
// find the last page and validate the target sample
@@ -4639,9 +4687,9 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
// indicates should be the granule position (give or take one)).
padding = ((f->blocksize_1 - f->blocksize_0) >> 2);
if (sample_number < padding)
- sample_number = 0;
+ last_sample_limit = 0;
else
- sample_number -= padding;
+ last_sample_limit = sample_number - padding;
left = f->p_first;
while (left.last_decoded_sample == ~0U) {
@@ -4654,9 +4702,12 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
assert(right.last_decoded_sample != ~0U);
// starting from the start is handled differently
- if (sample_number <= left.last_decoded_sample) {
- if (stb_vorbis_seek_start(f))
+ if (last_sample_limit <= left.last_decoded_sample) {
+ if (stb_vorbis_seek_start(f)) {
+ if (f->current_loc > sample_number)
+ return error(f, VORBIS_seek_failed);
return 1;
+ }
return 0;
}
@@ -4673,10 +4724,10 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
// first probe (interpolate)
double data_bytes = right.page_end - left.page_start;
bytes_per_sample = data_bytes / right.last_decoded_sample;
- offset = left.page_start + bytes_per_sample * (sample_number - left.last_decoded_sample);
+ offset = left.page_start + bytes_per_sample * (last_sample_limit - left.last_decoded_sample);
} else {
// second probe (try to bound the other side)
- double error = ((double) sample_number - mid.last_decoded_sample) * bytes_per_sample;
+ double error = ((double) last_sample_limit - mid.last_decoded_sample) * bytes_per_sample;
if (error >= 0 && error < 8000) error = 8000;
if (error < 0 && error > -8000) error = -8000;
offset += error * 2;
@@ -4707,14 +4758,16 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
}
// if we've just found the last page again then we're in a tricky file,
- // and we're close enough.
- if (mid.page_start == right.page_start)
- break;
-
- if (sample_number < mid.last_decoded_sample)
- right = mid;
- else
- left = mid;
+ // and we're close enough (if it wasn't an interpolation probe).
+ if (mid.page_start == right.page_start) {
+ if (probe >= 2 || delta <= 65536)
+ break;
+ } else {
+ if (last_sample_limit < mid.last_decoded_sample)
+ right = mid;
+ else
+ left = mid;
+ }
++probe;
}
@@ -4830,8 +4883,8 @@ int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number)
flush_packet(f);
}
}
- // the next frame will start with the sample
- assert(f->current_loc == sample_number);
+ // the next frame should start with the sample
+ if (f->current_loc != sample_number) return error(f, VORBIS_seek_failed);
return 1;
}
@@ -5173,7 +5226,7 @@ static void convert_samples_short(int buf_c, short **buffer, int b_offset, int d
int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples)
{
- float **output;
+ float **output = NULL;
int len = stb_vorbis_get_frame_float(f, NULL, &output);
if (len > num_samples) len = num_samples;
if (len)
diff --git a/thirdparty/oidn/0001-window.h-case-sensitive.patch b/thirdparty/oidn/0001-window.h-case-sensitive.patch
new file mode 100644
index 0000000000..7b9c8e96c1
--- /dev/null
+++ b/thirdparty/oidn/0001-window.h-case-sensitive.patch
@@ -0,0 +1,13 @@
+diff --git a/thirdparty/oidn/common/platform.h b/thirdparty/oidn/common/platform.h
+index 205ac8981d..9373b617b5 100644
+--- a/thirdparty/oidn/common/platform.h
++++ b/thirdparty/oidn/common/platform.h
+@@ -19,7 +19,7 @@
+ #if defined(_WIN32)
+ #define WIN32_LEAN_AND_MEAN
+ #define NOMINMAX
+- #include <Windows.h>
++ #include <windows.h>
+ #elif defined(__APPLE__)
+ #include <sys/sysctl.h>
+ #endif
diff --git a/thirdparty/oidn/LICENSE.txt b/thirdparty/oidn/LICENSE.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/thirdparty/oidn/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/thirdparty/oidn/common/barrier.h b/thirdparty/oidn/common/barrier.h
new file mode 100644
index 0000000000..b20f670053
--- /dev/null
+++ b/thirdparty/oidn/common/barrier.h
@@ -0,0 +1,52 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "platform.h"
+#include <mutex>
+#include <condition_variable>
+
+namespace oidn {
+
+ class Barrier
+ {
+ private:
+ std::mutex m;
+ std::condition_variable cv;
+ volatile int count;
+
+ public:
+ Barrier(int count) : count(count) {}
+
+ void wait()
+ {
+ std::unique_lock<std::mutex> lk(m);
+ count--;
+
+ if (count == 0)
+ {
+ lk.unlock();
+ cv.notify_all();
+ }
+ else
+ {
+ cv.wait(lk, [&]{ return count == 0; });
+ }
+ }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/common/exception.h b/thirdparty/oidn/common/exception.h
new file mode 100644
index 0000000000..18069c6a7d
--- /dev/null
+++ b/thirdparty/oidn/common/exception.h
@@ -0,0 +1,45 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include <exception>
+#include "platform.h"
+
+namespace oidn {
+
+ class Exception : public std::exception
+ {
+ private:
+ Error error;
+ const char* message;
+
+ public:
+ Exception(Error error, const char* message)
+ : error(error), message(message) {}
+
+ Error code() const noexcept
+ {
+ return error;
+ }
+
+ const char* what() const noexcept override
+ {
+ return message;
+ }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/common/platform.cpp b/thirdparty/oidn/common/platform.cpp
new file mode 100644
index 0000000000..59a14ff47c
--- /dev/null
+++ b/thirdparty/oidn/common/platform.cpp
@@ -0,0 +1,114 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "platform.h"
+
+namespace oidn {
+
+ // ----------------------------------------------------------------------------
+ // Common functions
+ // ----------------------------------------------------------------------------
+
+ void* alignedMalloc(size_t size, size_t alignment)
+ {
+ if (size == 0)
+ return nullptr;
+
+ assert((alignment & (alignment-1)) == 0);
+ void* ptr = _mm_malloc(size, alignment);
+
+ if (ptr == nullptr)
+ throw std::bad_alloc();
+
+ return ptr;
+ }
+
+ void alignedFree(void* ptr)
+ {
+ if (ptr)
+ _mm_free(ptr);
+ }
+
+ // ----------------------------------------------------------------------------
+ // System information
+ // ----------------------------------------------------------------------------
+
+ std::string getPlatformName()
+ {
+ std::string name;
+
+ #if defined(__linux__)
+ name = "Linux";
+ #elif defined(__FreeBSD__)
+ name = "FreeBSD";
+ #elif defined(__CYGWIN__)
+ name = "Cygwin";
+ #elif defined(_WIN32)
+ name = "Windows";
+ #elif defined(__APPLE__)
+ name = "macOS";
+ #elif defined(__unix__)
+ name = "Unix";
+ #else
+ return "Unknown";
+ #endif
+
+ #if defined(__x86_64__) || defined(_M_X64) || defined(__ia64__) || defined(__aarch64__)
+ name += " (64-bit)";
+ #else
+ name += " (32-bit)";
+ #endif
+
+ return name;
+ }
+
+ std::string getCompilerName()
+ {
+ #if defined(__INTEL_COMPILER)
+ int mayor = __INTEL_COMPILER / 100 % 100;
+ int minor = __INTEL_COMPILER % 100;
+ std::string version = "Intel Compiler ";
+ version += toString(mayor);
+ version += "." + toString(minor);
+ #if defined(__INTEL_COMPILER_UPDATE)
+ version += "." + toString(__INTEL_COMPILER_UPDATE);
+ #endif
+ return version;
+ #elif defined(__clang__)
+ return "Clang " __clang_version__;
+ #elif defined(__GNUC__)
+ return "GCC " __VERSION__;
+ #elif defined(_MSC_VER)
+ std::string version = toString(_MSC_FULL_VER);
+ version.insert(4, ".");
+ version.insert(9, ".");
+ version.insert(2, ".");
+ return "Visual C++ Compiler " + version;
+ #else
+ return "Unknown";
+ #endif
+ }
+
+ std::string getBuildName()
+ {
+ #if defined(NDEBUG)
+ return "Release";
+ #else
+ return "Debug";
+ #endif
+ }
+
+} // namespace oidn
diff --git a/thirdparty/oidn/common/platform.h b/thirdparty/oidn/common/platform.h
new file mode 100644
index 0000000000..9373b617b5
--- /dev/null
+++ b/thirdparty/oidn/common/platform.h
@@ -0,0 +1,131 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#if defined(_WIN32)
+ #define WIN32_LEAN_AND_MEAN
+ #define NOMINMAX
+ #include <windows.h>
+#elif defined(__APPLE__)
+ #include <sys/sysctl.h>
+#endif
+
+#include <xmmintrin.h>
+#include <cstdint>
+#include <climits>
+#include <limits>
+#include <atomic>
+#include <algorithm>
+#include <memory>
+#include <cmath>
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <cassert>
+#include "include/OpenImageDenoise/oidn.hpp"
+
+namespace oidn {
+
+ // ----------------------------------------------------------------------------
+ // Macros
+ // ----------------------------------------------------------------------------
+
+ #if defined(_WIN32)
+ // Windows
+ #if !defined(__noinline)
+ #define __noinline __declspec(noinline)
+ #endif
+ #else
+ // Unix
+ #if !defined(__forceinline)
+ #define __forceinline inline __attribute__((always_inline))
+ #endif
+ #if !defined(__noinline)
+ #define __noinline __attribute__((noinline))
+ #endif
+ #endif
+
+ #ifndef UNUSED
+ #define UNUSED(x) ((void)x)
+ #endif
+ #ifndef MAYBE_UNUSED
+ #define MAYBE_UNUSED(x) UNUSED(x)
+ #endif
+
+ // ----------------------------------------------------------------------------
+ // Error handling and debugging
+ // ----------------------------------------------------------------------------
+
+ struct Verbose
+ {
+ int verbose;
+
+ Verbose(int v = 0) : verbose(v) {}
+ __forceinline bool isVerbose(int v = 1) const { return v <= verbose; }
+ };
+
+ #define OIDN_WARNING(message) { if (isVerbose()) std::cerr << "Warning: " << message << std::endl; }
+ #define OIDN_FATAL(message) throw std::runtime_error(message);
+
+ // ----------------------------------------------------------------------------
+ // Common functions
+ // ----------------------------------------------------------------------------
+
+ using std::min;
+ using std::max;
+
+ template<typename T>
+ __forceinline T clamp(const T& value, const T& minValue, const T& maxValue)
+ {
+ return min(max(value, minValue), maxValue);
+ }
+
+ void* alignedMalloc(size_t size, size_t alignment);
+ void alignedFree(void* ptr);
+
+ template<typename T>
+ inline std::string toString(const T& a)
+ {
+ std::stringstream sm;
+ sm << a;
+ return sm.str();
+ }
+
+#if defined(__APPLE__)
+ template<typename T>
+ bool getSysctl(const char* name, T& value)
+ {
+ int64_t result = 0;
+ size_t size = sizeof(result);
+
+ if (sysctlbyname(name, &result, &size, nullptr, 0) != 0)
+ return false;
+
+ value = T(result);
+ return true;
+ }
+#endif
+
+ // ----------------------------------------------------------------------------
+ // System information
+ // ----------------------------------------------------------------------------
+
+ std::string getPlatformName();
+ std::string getCompilerName();
+ std::string getBuildName();
+
+} // namespace oidn
diff --git a/thirdparty/oidn/common/ref.h b/thirdparty/oidn/common/ref.h
new file mode 100644
index 0000000000..de44603af2
--- /dev/null
+++ b/thirdparty/oidn/common/ref.h
@@ -0,0 +1,163 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "platform.h"
+
+namespace oidn {
+
+ class RefCount
+ {
+ private:
+ std::atomic<size_t> count;
+
+ public:
+ __forceinline RefCount(int count = 0) noexcept : count(count) {}
+
+ __forceinline size_t incRef() noexcept
+ {
+ return count.fetch_add(1) + 1;
+ }
+
+ __forceinline size_t decRef()
+ {
+ const size_t newCount = decRefKeep();
+ if (newCount == 0)
+ destroy();
+ return newCount;
+ }
+
+ __forceinline size_t decRefKeep() noexcept
+ {
+ return count.fetch_add(-1) - 1;
+ }
+
+ __forceinline void destroy()
+ {
+ delete this;
+ }
+
+ protected:
+ // Disable copying
+ RefCount(const RefCount&) = delete;
+ RefCount& operator =(const RefCount&) = delete;
+
+ virtual ~RefCount() noexcept = default;
+ };
+
+ template<typename T>
+ class Ref
+ {
+ private:
+ T* ptr;
+
+ public:
+ __forceinline Ref() noexcept : ptr(nullptr) {}
+ __forceinline Ref(std::nullptr_t) noexcept : ptr(nullptr) {}
+ __forceinline Ref(const Ref& other) noexcept : ptr(other.ptr) { if (ptr) ptr->incRef(); }
+ __forceinline Ref(Ref&& other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
+ __forceinline Ref(T* ptr) noexcept : ptr(ptr) { if (ptr) ptr->incRef(); }
+
+ template<typename Y>
+ __forceinline Ref(const Ref<Y>& other) noexcept : ptr(other.get()) { if (ptr) ptr->incRef(); }
+
+ template<typename Y>
+ __forceinline explicit Ref(Y* ptr) noexcept : ptr(ptr) { if (ptr) ptr->incRef(); }
+
+ __forceinline ~Ref() { if (ptr) ptr->decRef(); }
+
+ __forceinline Ref& operator =(const Ref& other)
+ {
+ if (other.ptr)
+ other.ptr->incRef();
+ if (ptr)
+ ptr->decRef();
+ ptr = other.ptr;
+ return *this;
+ }
+
+ __forceinline Ref& operator =(Ref&& other)
+ {
+ if (ptr)
+ ptr->decRef();
+ ptr = other.ptr;
+ other.ptr = nullptr;
+ return *this;
+ }
+
+ __forceinline Ref& operator =(T* other)
+ {
+ if (other)
+ other->incRef();
+ if (ptr)
+ ptr->decRef();
+ ptr = other;
+ return *this;
+ }
+
+ __forceinline Ref& operator =(std::nullptr_t)
+ {
+ if (ptr)
+ ptr->decRef();
+ ptr = nullptr;
+ return *this;
+ }
+
+ __forceinline operator bool() const noexcept { return ptr != nullptr; }
+
+ __forceinline T& operator *() const noexcept { return *ptr; }
+ __forceinline T* operator ->() const noexcept { return ptr; }
+
+ __forceinline T* get() const noexcept { return ptr; }
+
+ __forceinline T* detach() noexcept
+ {
+ T* res = ptr;
+ ptr = nullptr;
+ return res;
+ }
+ };
+
+ template<typename T> __forceinline bool operator < (const Ref<T>& a, const Ref<T>& b) noexcept { return a.ptr < b.ptr; }
+
+ template<typename T> __forceinline bool operator ==(const Ref<T>& a, std::nullptr_t) noexcept { return a.ptr == nullptr; }
+ template<typename T> __forceinline bool operator ==(std::nullptr_t, const Ref<T>& b) noexcept { return nullptr == b.ptr; }
+ template<typename T> __forceinline bool operator ==(const Ref<T>& a, const Ref<T>& b) noexcept { return a.ptr == b.ptr; }
+
+ template<typename T> __forceinline bool operator !=(const Ref<T>& a, std::nullptr_t) noexcept { return a.ptr != nullptr; }
+ template<typename T> __forceinline bool operator !=(std::nullptr_t, const Ref<T>& b) noexcept { return nullptr != b.ptr; }
+ template<typename T> __forceinline bool operator !=(const Ref<T>& a, const Ref<T>& b) noexcept { return a.ptr != b.ptr; }
+
+ template<typename T, typename... Args>
+ __forceinline Ref<T> makeRef(Args&&... args)
+ {
+ return Ref<T>(new T(std::forward<Args>(args)...));
+ }
+
+ template<typename T, typename Y>
+ __forceinline Ref<Y> staticRefCast(const Ref<T>& a)
+ {
+ return Ref<Y>(static_cast<Y*>(a.get()));
+ }
+
+ template<typename T, typename Y>
+ __forceinline Ref<Y> dynamicRefCast(const Ref<T>& a)
+ {
+ return Ref<Y>(dynamic_cast<Y*>(a.get()));
+ }
+
+} // namespace oidn
diff --git a/thirdparty/oidn/common/tensor.cpp b/thirdparty/oidn/common/tensor.cpp
new file mode 100644
index 0000000000..0249f2e141
--- /dev/null
+++ b/thirdparty/oidn/common/tensor.cpp
@@ -0,0 +1,83 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "exception.h"
+#include "tensor.h"
+
+namespace oidn {
+
+ std::map<std::string, Tensor> parseTensors(void* buffer)
+ {
+ char* input = (char*)buffer;
+
+ // Parse the magic value
+ const int magic = *(unsigned short*)input;
+ if (magic != 0x41D7)
+ throw Exception(Error::InvalidOperation, "invalid tensor archive");
+ input += sizeof(unsigned short);
+
+ // Parse the version
+ const int majorVersion = *(unsigned char*)input++;
+ const int minorVersion = *(unsigned char*)input++;
+ UNUSED(minorVersion);
+ if (majorVersion > 1)
+ throw Exception(Error::InvalidOperation, "unsupported tensor archive version");
+
+ // Parse the number of tensors
+ const int numTensors = *(int*)input;
+ input += sizeof(int);
+
+ // Parse the tensors
+ std::map<std::string, Tensor> tensorMap;
+ for (int i = 0; i < numTensors; ++i)
+ {
+ Tensor tensor;
+
+ // Parse the name
+ const int nameLen = *(unsigned char*)input++;
+ std::string name(input, nameLen);
+ input += nameLen;
+
+ // Parse the number of dimensions
+ const int ndims = *(unsigned char*)input++;
+
+ // Parse the shape of the tensor
+ tensor.dims.resize(ndims);
+ for (int i = 0; i < ndims; ++i)
+ tensor.dims[i] = ((int*)input)[i];
+ input += ndims * sizeof(int);
+
+ // Parse the format of the tensor
+ tensor.format = std::string(input, input + ndims);
+ input += ndims;
+
+ // Parse the data type of the tensor
+ const char type = *(unsigned char*)input++;
+ if (type != 'f') // only float32 is supported
+ throw Exception(Error::InvalidOperation, "unsupported tensor data type");
+
+ // Skip the data
+ tensor.data = (float*)input;
+ input += tensor.size() * sizeof(float);
+
+ // Add the tensor to the map
+ tensorMap.emplace(name, std::move(tensor));
+ }
+
+ return tensorMap;
+ }
+
+} // namespace oidn
diff --git a/thirdparty/oidn/common/tensor.h b/thirdparty/oidn/common/tensor.h
new file mode 100644
index 0000000000..48e7d1123d
--- /dev/null
+++ b/thirdparty/oidn/common/tensor.h
@@ -0,0 +1,66 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "platform.h"
+#include <vector>
+#include <map>
+
+namespace oidn {
+
+ template<typename T>
+ using shared_vector = std::shared_ptr<std::vector<T>>;
+
+ // Generic tensor
+ struct Tensor
+ {
+ float* data;
+ std::vector<int64_t> dims;
+ std::string format;
+ shared_vector<char> buffer; // optional, only for reference counting
+
+ __forceinline Tensor() : data(nullptr) {}
+
+ __forceinline Tensor(const std::vector<int64_t>& dims, const std::string& format)
+ : dims(dims),
+ format(format)
+ {
+ buffer = std::make_shared<std::vector<char>>(size() * sizeof(float));
+ data = (float*)buffer->data();
+ }
+
+ __forceinline operator bool() const { return data != nullptr; }
+
+ __forceinline int ndims() const { return (int)dims.size(); }
+
+ // Returns the number of values
+ __forceinline size_t size() const
+ {
+ size_t size = 1;
+ for (int i = 0; i < ndims(); ++i)
+ size *= dims[i];
+ return size;
+ }
+
+ __forceinline float& operator [](size_t i) { return data[i]; }
+ __forceinline const float& operator [](size_t i) const { return data[i]; }
+ };
+
+ // Parses tensors from a buffer
+ std::map<std::string, Tensor> parseTensors(void* buffer);
+
+} // namespace oidn
diff --git a/thirdparty/oidn/common/thread.cpp b/thirdparty/oidn/common/thread.cpp
new file mode 100644
index 0000000000..48c489c57b
--- /dev/null
+++ b/thirdparty/oidn/common/thread.cpp
@@ -0,0 +1,297 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#if defined(_MSC_VER)
+ #pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
+#endif
+
+#if defined(__APPLE__)
+ #include <mach/thread_act.h>
+ #include <mach/mach_init.h>
+#endif
+
+#include "thread.h"
+#include <fstream>
+
+namespace oidn {
+
+#if defined(_WIN32)
+
+ // --------------------------------------------------------------------------
+ // ThreadAffinity - Windows
+ // --------------------------------------------------------------------------
+
+ ThreadAffinity::ThreadAffinity(int numThreadsPerCore, int verbose)
+ : Verbose(verbose)
+ {
+ HMODULE hLib = GetModuleHandle(TEXT("kernel32"));
+ pGetLogicalProcessorInformationEx = (GetLogicalProcessorInformationExFunc)GetProcAddress(hLib, "GetLogicalProcessorInformationEx");
+ pSetThreadGroupAffinity = (SetThreadGroupAffinityFunc)GetProcAddress(hLib, "SetThreadGroupAffinity");
+
+ if (pGetLogicalProcessorInformationEx && pSetThreadGroupAffinity)
+ {
+ // Get logical processor information
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX buffer = nullptr;
+ DWORD bufferSize = 0;
+
+ // First call the function with an empty buffer to get the required buffer size
+ BOOL result = pGetLogicalProcessorInformationEx(RelationProcessorCore, buffer, &bufferSize);
+ if (result || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ OIDN_WARNING("GetLogicalProcessorInformationEx failed");
+ return;
+ }
+
+ // Allocate the buffer
+ buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)malloc(bufferSize);
+ if (!buffer)
+ {
+ OIDN_WARNING("SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX allocation failed");
+ return;
+ }
+
+ // Call again the function but now with the properly sized buffer
+ result = pGetLogicalProcessorInformationEx(RelationProcessorCore, buffer, &bufferSize);
+ if (!result)
+ {
+ OIDN_WARNING("GetLogicalProcessorInformationEx failed");
+ free(buffer);
+ return;
+ }
+
+ // Iterate over the logical processor information structures
+ // There should be one structure for each physical core
+ char* ptr = (char*)buffer;
+ while (ptr < (char*)buffer + bufferSize)
+ {
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX item = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)ptr;
+ if (item->Relationship == RelationProcessorCore && item->Processor.GroupCount > 0)
+ {
+ // Iterate over the groups
+ int numThreads = 0;
+ for (int group = 0; (group < item->Processor.GroupCount) && (numThreads < numThreadsPerCore); ++group)
+ {
+ GROUP_AFFINITY coreAffinity = item->Processor.GroupMask[group];
+ while ((coreAffinity.Mask != 0) && (numThreads < numThreadsPerCore))
+ {
+ // Extract the next set bit/thread from the mask
+ GROUP_AFFINITY threadAffinity = coreAffinity;
+ threadAffinity.Mask = threadAffinity.Mask & -threadAffinity.Mask;
+
+ // Push the affinity for this thread
+ affinities.push_back(threadAffinity);
+ oldAffinities.push_back(threadAffinity);
+ numThreads++;
+
+ // Remove this bit/thread from the mask
+ coreAffinity.Mask ^= threadAffinity.Mask;
+ }
+ }
+ }
+
+ // Next structure
+ ptr += item->Size;
+ }
+
+ // Free the buffer
+ free(buffer);
+ }
+ }
+
+ void ThreadAffinity::set(int threadIndex)
+ {
+ if (threadIndex >= (int)affinities.size())
+ return;
+
+ // Save the current affinity and set the new one
+ const HANDLE thread = GetCurrentThread();
+ if (!pSetThreadGroupAffinity(thread, &affinities[threadIndex], &oldAffinities[threadIndex]))
+ OIDN_WARNING("SetThreadGroupAffinity failed");
+ }
+
+ void ThreadAffinity::restore(int threadIndex)
+ {
+ if (threadIndex >= (int)affinities.size())
+ return;
+
+ // Restore the original affinity
+ const HANDLE thread = GetCurrentThread();
+ if (!pSetThreadGroupAffinity(thread, &oldAffinities[threadIndex], nullptr))
+ OIDN_WARNING("SetThreadGroupAffinity failed");
+ }
+
+#elif defined(__linux__)
+
+ // --------------------------------------------------------------------------
+ // ThreadAffinity - Linux
+ // --------------------------------------------------------------------------
+
+ ThreadAffinity::ThreadAffinity(int numThreadsPerCore, int verbose)
+ : Verbose(verbose)
+ {
+ std::vector<int> threadIds;
+
+ // Parse the thread/CPU topology
+ for (int cpuId = 0; ; cpuId++)
+ {
+ std::fstream fs;
+ std::string cpu = std::string("/sys/devices/system/cpu/cpu") + std::to_string(cpuId) + std::string("/topology/thread_siblings_list");
+ fs.open(cpu.c_str(), std::fstream::in);
+ if (fs.fail()) break;
+
+ int i;
+ int j = 0;
+ while ((j < numThreadsPerCore) && (fs >> i))
+ {
+ if (std::none_of(threadIds.begin(), threadIds.end(), [&](int id) { return id == i; }))
+ threadIds.push_back(i);
+
+ if (fs.peek() == ',')
+ fs.ignore();
+ j++;
+ }
+
+ fs.close();
+ }
+
+ #if 0
+ for (size_t i = 0; i < thread_ids.size(); ++i)
+ std::cout << "thread " << i << " -> " << thread_ids[i] << std::endl;
+ #endif
+
+ // Create the affinity structures
+ affinities.resize(threadIds.size());
+ oldAffinities.resize(threadIds.size());
+
+ for (size_t i = 0; i < threadIds.size(); ++i)
+ {
+ cpu_set_t affinity;
+ CPU_ZERO(&affinity);
+ CPU_SET(threadIds[i], &affinity);
+
+ affinities[i] = affinity;
+ oldAffinities[i] = affinity;
+ }
+ }
+
+ void ThreadAffinity::set(int threadIndex)
+ {
+ if (threadIndex >= (int)affinities.size())
+ return;
+
+ const pthread_t thread = pthread_self();
+
+ // Save the current affinity
+ if (pthread_getaffinity_np(thread, sizeof(cpu_set_t), &oldAffinities[threadIndex]) != 0)
+ {
+ OIDN_WARNING("pthread_getaffinity_np failed");
+ oldAffinities[threadIndex] = affinities[threadIndex];
+ return;
+ }
+
+ // Set the new affinity
+ if (pthread_setaffinity_np(thread, sizeof(cpu_set_t), &affinities[threadIndex]) != 0)
+ OIDN_WARNING("pthread_setaffinity_np failed");
+ }
+
+ void ThreadAffinity::restore(int threadIndex)
+ {
+ if (threadIndex >= (int)affinities.size())
+ return;
+
+ const pthread_t thread = pthread_self();
+
+ // Restore the original affinity
+ if (pthread_setaffinity_np(thread, sizeof(cpu_set_t), &oldAffinities[threadIndex]) != 0)
+ OIDN_WARNING("pthread_setaffinity_np failed");
+ }
+
+#elif defined(__APPLE__)
+
+ // --------------------------------------------------------------------------
+ // ThreadAffinity - macOS
+ // --------------------------------------------------------------------------
+
+ ThreadAffinity::ThreadAffinity(int numThreadsPerCore, int verbose)
+ : Verbose(verbose)
+ {
+ // Query the thread/CPU topology
+ int numPhysicalCpus;
+ int numLogicalCpus;
+
+ if (!getSysctl("hw.physicalcpu", numPhysicalCpus) || !getSysctl("hw.logicalcpu", numLogicalCpus))
+ {
+ OIDN_WARNING("sysctlbyname failed");
+ return;
+ }
+
+ if ((numLogicalCpus % numPhysicalCpus != 0) && (numThreadsPerCore > 1))
+ return; // this shouldn't happen
+ const int maxThreadsPerCore = numLogicalCpus / numPhysicalCpus;
+
+ // Create the affinity structures
+ // macOS doesn't support binding a thread to a specific core, but we can at least group threads which
+ // should be on the same core together
+ for (int core = 1; core <= numPhysicalCpus; ++core) // tags start from 1!
+ {
+ thread_affinity_policy affinity;
+ affinity.affinity_tag = core;
+
+ for (int thread = 0; thread < min(numThreadsPerCore, maxThreadsPerCore); ++thread)
+ {
+ affinities.push_back(affinity);
+ oldAffinities.push_back(affinity);
+ }
+ }
+ }
+
+ void ThreadAffinity::set(int threadIndex)
+ {
+ if (threadIndex >= (int)affinities.size())
+ return;
+
+ const auto thread = mach_thread_self();
+
+ // Save the current affinity
+ mach_msg_type_number_t policyCount = THREAD_AFFINITY_POLICY_COUNT;
+ boolean_t getDefault = FALSE;
+ if (thread_policy_get(thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&oldAffinities[threadIndex], &policyCount, &getDefault) != KERN_SUCCESS)
+ {
+ OIDN_WARNING("thread_policy_get failed");
+ oldAffinities[threadIndex] = affinities[threadIndex];
+ return;
+ }
+
+ // Set the new affinity
+ if (thread_policy_set(thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&affinities[threadIndex], THREAD_AFFINITY_POLICY_COUNT) != KERN_SUCCESS)
+ OIDN_WARNING("thread_policy_set failed");
+ }
+
+ void ThreadAffinity::restore(int threadIndex)
+ {
+ if (threadIndex >= (int)affinities.size())
+ return;
+
+ const auto thread = mach_thread_self();
+
+ // Restore the original affinity
+ if (thread_policy_set(thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&oldAffinities[threadIndex], THREAD_AFFINITY_POLICY_COUNT) != KERN_SUCCESS)
+ OIDN_WARNING("thread_policy_set failed");
+ }
+
+#endif
+
+} // namespace oidn
diff --git a/thirdparty/oidn/common/thread.h b/thirdparty/oidn/common/thread.h
new file mode 100644
index 0000000000..2c731367da
--- /dev/null
+++ b/thirdparty/oidn/common/thread.h
@@ -0,0 +1,202 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "platform.h"
+
+#if !defined(_WIN32)
+ #include <pthread.h>
+ #include <sched.h>
+ #if defined(__APPLE__)
+ #include <mach/thread_policy.h>
+ #endif
+#endif
+
+#include <vector>
+#include <mutex>
+
+namespace oidn {
+
+ // --------------------------------------------------------------------------
+ // ThreadLocal
+ // --------------------------------------------------------------------------
+
+ // Wrapper which makes any variable thread-local
+ template<typename T>
+ class ThreadLocal : public Verbose
+ {
+ private:
+ #if defined(_WIN32)
+ DWORD key;
+ #else
+ pthread_key_t key;
+ #endif
+
+ std::vector<T*> instances;
+ std::mutex mutex;
+
+ public:
+ ThreadLocal(int verbose = 0)
+ : Verbose(verbose)
+ {
+ #if defined(_WIN32)
+ key = TlsAlloc();
+ if (key == TLS_OUT_OF_INDEXES)
+ OIDN_FATAL("TlsAlloc failed");
+ #else
+ if (pthread_key_create(&key, nullptr) != 0)
+ OIDN_FATAL("pthread_key_create failed");
+ #endif
+ }
+
+ ~ThreadLocal()
+ {
+ std::lock_guard<std::mutex> lock(mutex);
+ for (T* ptr : instances)
+ delete ptr;
+
+ #if defined(_WIN32)
+ if (!TlsFree(key))
+ OIDN_WARNING("TlsFree failed");
+ #else
+ if (pthread_key_delete(key) != 0)
+ OIDN_WARNING("pthread_key_delete failed");
+ #endif
+ }
+
+ T& get()
+ {
+ #if defined(_WIN32)
+ T* ptr = (T*)TlsGetValue(key);
+ #else
+ T* ptr = (T*)pthread_getspecific(key);
+ #endif
+
+ if (ptr)
+ return *ptr;
+
+ ptr = new T;
+ std::lock_guard<std::mutex> lock(mutex);
+ instances.push_back(ptr);
+
+ #if defined(_WIN32)
+ if (!TlsSetValue(key, ptr))
+ OIDN_FATAL("TlsSetValue failed");
+ #else
+ if (pthread_setspecific(key, ptr) != 0)
+ OIDN_FATAL("pthread_setspecific failed");
+ #endif
+
+ return *ptr;
+ }
+ };
+
+#if defined(_WIN32)
+
+ // --------------------------------------------------------------------------
+ // ThreadAffinity - Windows
+ // --------------------------------------------------------------------------
+
+ class ThreadAffinity : public Verbose
+ {
+ private:
+ typedef BOOL (WINAPI *GetLogicalProcessorInformationExFunc)(LOGICAL_PROCESSOR_RELATIONSHIP,
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX,
+ PDWORD);
+
+ typedef BOOL (WINAPI *SetThreadGroupAffinityFunc)(HANDLE,
+ CONST GROUP_AFFINITY*,
+ PGROUP_AFFINITY);
+
+ GetLogicalProcessorInformationExFunc pGetLogicalProcessorInformationEx = nullptr;
+ SetThreadGroupAffinityFunc pSetThreadGroupAffinity = nullptr;
+
+ std::vector<GROUP_AFFINITY> affinities; // thread affinities
+ std::vector<GROUP_AFFINITY> oldAffinities; // original thread affinities
+
+ public:
+ ThreadAffinity(int numThreadsPerCore = INT_MAX, int verbose = 0);
+
+ int getNumThreads() const
+ {
+ return (int)affinities.size();
+ }
+
+ // Sets the affinity (0..numThreads-1) of the thread after saving the current affinity
+ void set(int threadIndex);
+
+ // Restores the affinity of the thread
+ void restore(int threadIndex);
+ };
+
+#elif defined(__linux__)
+
+ // --------------------------------------------------------------------------
+ // ThreadAffinity - Linux
+ // --------------------------------------------------------------------------
+
+ class ThreadAffinity : public Verbose
+ {
+ private:
+ std::vector<cpu_set_t> affinities; // thread affinities
+ std::vector<cpu_set_t> oldAffinities; // original thread affinities
+
+ public:
+ ThreadAffinity(int numThreadsPerCore = INT_MAX, int verbose = 0);
+
+ int getNumThreads() const
+ {
+ return (int)affinities.size();
+ }
+
+ // Sets the affinity (0..numThreads-1) of the thread after saving the current affinity
+ void set(int threadIndex);
+
+ // Restores the affinity of the thread
+ void restore(int threadIndex);
+ };
+
+#elif defined(__APPLE__)
+
+ // --------------------------------------------------------------------------
+ // ThreadAffinity - macOS
+ // --------------------------------------------------------------------------
+
+ class ThreadAffinity : public Verbose
+ {
+ private:
+ std::vector<thread_affinity_policy> affinities; // thread affinities
+ std::vector<thread_affinity_policy> oldAffinities; // original thread affinities
+
+ public:
+ ThreadAffinity(int numThreadsPerCore = INT_MAX, int verbose = 0);
+
+ int getNumThreads() const
+ {
+ return (int)affinities.size();
+ }
+
+ // Sets the affinity (0..numThreads-1) of the thread after saving the current affinity
+ void set(int threadIndex);
+
+ // Restores the affinity of the thread
+ void restore(int threadIndex);
+ };
+
+#endif
+
+} // namespace oidn
diff --git a/thirdparty/oidn/common/timer.h b/thirdparty/oidn/common/timer.h
new file mode 100644
index 0000000000..62aaaa1c33
--- /dev/null
+++ b/thirdparty/oidn/common/timer.h
@@ -0,0 +1,49 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "platform.h"
+#include <chrono>
+
+namespace oidn {
+
+ class Timer
+ {
+ private:
+ using clock = std::chrono::high_resolution_clock;
+
+ std::chrono::time_point<clock> start;
+
+ public:
+ Timer()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ start = clock::now();
+ }
+
+ double query() const
+ {
+ auto end = clock::now();
+ return std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count();
+ }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/api.cpp b/thirdparty/oidn/core/api.cpp
new file mode 100644
index 0000000000..7353fe4e25
--- /dev/null
+++ b/thirdparty/oidn/core/api.cpp
@@ -0,0 +1,408 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#ifdef _WIN32
+# define OIDN_API extern "C" __declspec(dllexport)
+#else
+# define OIDN_API extern "C" __attribute__ ((visibility ("default")))
+#endif
+
+// Locks the device that owns the specified object
+// Use *only* inside OIDN_TRY/CATCH!
+#define OIDN_LOCK(obj) \
+ std::lock_guard<std::mutex> lock(obj->getDevice()->getMutex());
+
+// Try/catch for converting exceptions to errors
+#define OIDN_TRY \
+ try {
+
+#define OIDN_CATCH(obj) \
+ } catch (Exception& e) { \
+ Device::setError(obj ? obj->getDevice() : nullptr, e.code(), e.what()); \
+ } catch (std::bad_alloc&) { \
+ Device::setError(obj ? obj->getDevice() : nullptr, Error::OutOfMemory, "out of memory"); \
+ } catch (mkldnn::error& e) { \
+ if (e.status == mkldnn_out_of_memory) \
+ Device::setError(obj ? obj->getDevice() : nullptr, Error::OutOfMemory, "out of memory"); \
+ else \
+ Device::setError(obj ? obj->getDevice() : nullptr, Error::Unknown, e.message); \
+ } catch (std::exception& e) { \
+ Device::setError(obj ? obj->getDevice() : nullptr, Error::Unknown, e.what()); \
+ } catch (...) { \
+ Device::setError(obj ? obj->getDevice() : nullptr, Error::Unknown, "unknown exception caught"); \
+ }
+
+#include "device.h"
+#include "filter.h"
+#include <mutex>
+
+namespace oidn {
+
+ namespace
+ {
+ __forceinline void checkHandle(void* handle)
+ {
+ if (handle == nullptr)
+ throw Exception(Error::InvalidArgument, "invalid handle");
+ }
+
+ template<typename T>
+ __forceinline void retainObject(T* obj)
+ {
+ if (obj)
+ {
+ obj->incRef();
+ }
+ else
+ {
+ OIDN_TRY
+ checkHandle(obj);
+ OIDN_CATCH(obj)
+ }
+ }
+
+ template<typename T>
+ __forceinline void releaseObject(T* obj)
+ {
+ if (obj == nullptr || obj->decRefKeep() == 0)
+ {
+ OIDN_TRY
+ checkHandle(obj);
+ OIDN_LOCK(obj);
+ obj->destroy();
+ OIDN_CATCH(obj)
+ }
+ }
+
+ template<>
+ __forceinline void releaseObject(Device* obj)
+ {
+ if (obj == nullptr || obj->decRefKeep() == 0)
+ {
+ OIDN_TRY
+ checkHandle(obj);
+ // Do NOT lock the device because it owns the mutex
+ obj->destroy();
+ OIDN_CATCH(obj)
+ }
+ }
+ }
+
+ OIDN_API OIDNDevice oidnNewDevice(OIDNDeviceType type)
+ {
+ Ref<Device> device = nullptr;
+ OIDN_TRY
+ if (type == OIDN_DEVICE_TYPE_CPU || type == OIDN_DEVICE_TYPE_DEFAULT)
+ device = makeRef<Device>();
+ else
+ throw Exception(Error::InvalidArgument, "invalid device type");
+ OIDN_CATCH(device)
+ return (OIDNDevice)device.detach();
+ }
+
+ OIDN_API void oidnRetainDevice(OIDNDevice hDevice)
+ {
+ Device* device = (Device*)hDevice;
+ retainObject(device);
+ }
+
+ OIDN_API void oidnReleaseDevice(OIDNDevice hDevice)
+ {
+ Device* device = (Device*)hDevice;
+ releaseObject(device);
+ }
+
+ OIDN_API void oidnSetDevice1b(OIDNDevice hDevice, const char* name, bool value)
+ {
+ Device* device = (Device*)hDevice;
+ OIDN_TRY
+ checkHandle(hDevice);
+ OIDN_LOCK(device);
+ device->set1i(name, value);
+ OIDN_CATCH(device)
+ }
+
+ OIDN_API void oidnSetDevice1i(OIDNDevice hDevice, const char* name, int value)
+ {
+ Device* device = (Device*)hDevice;
+ OIDN_TRY
+ checkHandle(hDevice);
+ OIDN_LOCK(device);
+ device->set1i(name, value);
+ OIDN_CATCH(device)
+ }
+
+ OIDN_API bool oidnGetDevice1b(OIDNDevice hDevice, const char* name)
+ {
+ Device* device = (Device*)hDevice;
+ OIDN_TRY
+ checkHandle(hDevice);
+ OIDN_LOCK(device);
+ return device->get1i(name);
+ OIDN_CATCH(device)
+ return false;
+ }
+
+ OIDN_API int oidnGetDevice1i(OIDNDevice hDevice, const char* name)
+ {
+ Device* device = (Device*)hDevice;
+ OIDN_TRY
+ checkHandle(hDevice);
+ OIDN_LOCK(device);
+ return device->get1i(name);
+ OIDN_CATCH(device)
+ return 0;
+ }
+
+ OIDN_API void oidnSetDeviceErrorFunction(OIDNDevice hDevice, OIDNErrorFunction func, void* userPtr)
+ {
+ Device* device = (Device*)hDevice;
+ OIDN_TRY
+ checkHandle(hDevice);
+ OIDN_LOCK(device);
+ device->setErrorFunction((ErrorFunction)func, userPtr);
+ OIDN_CATCH(device)
+ }
+
+ OIDN_API OIDNError oidnGetDeviceError(OIDNDevice hDevice, const char** outMessage)
+ {
+ Device* device = (Device*)hDevice;
+ OIDN_TRY
+ return (OIDNError)Device::getError(device, outMessage);
+ OIDN_CATCH(device)
+ if (outMessage) *outMessage = "";
+ return OIDN_ERROR_UNKNOWN;
+ }
+
+ OIDN_API void oidnCommitDevice(OIDNDevice hDevice)
+ {
+ Device* device = (Device*)hDevice;
+ OIDN_TRY
+ checkHandle(hDevice);
+ OIDN_LOCK(device);
+ device->commit();
+ OIDN_CATCH(device)
+ }
+
+ OIDN_API OIDNBuffer oidnNewBuffer(OIDNDevice hDevice, size_t byteSize)
+ {
+ Device* device = (Device*)hDevice;
+ OIDN_TRY
+ checkHandle(hDevice);
+ OIDN_LOCK(device);
+ Ref<Buffer> buffer = device->newBuffer(byteSize);
+ return (OIDNBuffer)buffer.detach();
+ OIDN_CATCH(device)
+ return nullptr;
+ }
+
+ OIDN_API OIDNBuffer oidnNewSharedBuffer(OIDNDevice hDevice, void* ptr, size_t byteSize)
+ {
+ Device* device = (Device*)hDevice;
+ OIDN_TRY
+ checkHandle(hDevice);
+ OIDN_LOCK(device);
+ Ref<Buffer> buffer = device->newBuffer(ptr, byteSize);
+ return (OIDNBuffer)buffer.detach();
+ OIDN_CATCH(device)
+ return nullptr;
+ }
+
+ OIDN_API void oidnRetainBuffer(OIDNBuffer hBuffer)
+ {
+ Buffer* buffer = (Buffer*)hBuffer;
+ retainObject(buffer);
+ }
+
+ OIDN_API void oidnReleaseBuffer(OIDNBuffer hBuffer)
+ {
+ Buffer* buffer = (Buffer*)hBuffer;
+ releaseObject(buffer);
+ }
+
+ OIDN_API void* oidnMapBuffer(OIDNBuffer hBuffer, OIDNAccess access, size_t byteOffset, size_t byteSize)
+ {
+ Buffer* buffer = (Buffer*)hBuffer;
+ OIDN_TRY
+ checkHandle(hBuffer);
+ OIDN_LOCK(buffer);
+ return buffer->map(byteOffset, byteSize);
+ OIDN_CATCH(buffer)
+ return nullptr;
+ }
+
+ OIDN_API void oidnUnmapBuffer(OIDNBuffer hBuffer, void* mappedPtr)
+ {
+ Buffer* buffer = (Buffer*)hBuffer;
+ OIDN_TRY
+ checkHandle(hBuffer);
+ OIDN_LOCK(buffer);
+ return buffer->unmap(mappedPtr);
+ OIDN_CATCH(buffer)
+ }
+
+ OIDN_API OIDNFilter oidnNewFilter(OIDNDevice hDevice, const char* type)
+ {
+ Device* device = (Device*)hDevice;
+ OIDN_TRY
+ checkHandle(hDevice);
+ OIDN_LOCK(device);
+ Ref<Filter> filter = device->newFilter(type);
+ return (OIDNFilter)filter.detach();
+ OIDN_CATCH(device)
+ return nullptr;
+ }
+
+ OIDN_API void oidnRetainFilter(OIDNFilter hFilter)
+ {
+ Filter* filter = (Filter*)hFilter;
+ retainObject(filter);
+ }
+
+ OIDN_API void oidnReleaseFilter(OIDNFilter hFilter)
+ {
+ Filter* filter = (Filter*)hFilter;
+ releaseObject(filter);
+ }
+
+ OIDN_API void oidnSetFilterImage(OIDNFilter hFilter, const char* name,
+ OIDNBuffer hBuffer, OIDNFormat format,
+ size_t width, size_t height,
+ size_t byteOffset,
+ size_t bytePixelStride, size_t byteRowStride)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ checkHandle(hBuffer);
+ OIDN_LOCK(filter);
+ Ref<Buffer> buffer = (Buffer*)hBuffer;
+ if (buffer->getDevice() != filter->getDevice())
+ throw Exception(Error::InvalidArgument, "the specified objects are bound to different devices");
+ Image data(buffer, (Format)format, (int)width, (int)height, byteOffset, bytePixelStride, byteRowStride);
+ filter->setImage(name, data);
+ OIDN_CATCH(filter)
+ }
+
+ OIDN_API void oidnSetSharedFilterImage(OIDNFilter hFilter, const char* name,
+ void* ptr, OIDNFormat format,
+ size_t width, size_t height,
+ size_t byteOffset,
+ size_t bytePixelStride, size_t byteRowStride)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ OIDN_LOCK(filter);
+ Image data(ptr, (Format)format, (int)width, (int)height, byteOffset, bytePixelStride, byteRowStride);
+ filter->setImage(name, data);
+ OIDN_CATCH(filter)
+ }
+
+ OIDN_API void oidnSetFilter1b(OIDNFilter hFilter, const char* name, bool value)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ OIDN_LOCK(filter);
+ filter->set1i(name, int(value));
+ OIDN_CATCH(filter)
+ }
+
+ OIDN_API bool oidnGetFilter1b(OIDNFilter hFilter, const char* name)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ OIDN_LOCK(filter);
+ return filter->get1i(name);
+ OIDN_CATCH(filter)
+ return false;
+ }
+
+ OIDN_API void oidnSetFilter1i(OIDNFilter hFilter, const char* name, int value)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ OIDN_LOCK(filter);
+ filter->set1i(name, value);
+ OIDN_CATCH(filter)
+ }
+
+ OIDN_API int oidnGetFilter1i(OIDNFilter hFilter, const char* name)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ OIDN_LOCK(filter);
+ return filter->get1i(name);
+ OIDN_CATCH(filter)
+ return 0;
+ }
+
+ OIDN_API void oidnSetFilter1f(OIDNFilter hFilter, const char* name, float value)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ OIDN_LOCK(filter);
+ filter->set1f(name, value);
+ OIDN_CATCH(filter)
+ }
+
+ OIDN_API float oidnGetFilter1f(OIDNFilter hFilter, const char* name)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ OIDN_LOCK(filter);
+ return filter->get1f(name);
+ OIDN_CATCH(filter)
+ return 0;
+ }
+
+ OIDN_API void oidnSetFilterProgressMonitorFunction(OIDNFilter hFilter, OIDNProgressMonitorFunction func, void* userPtr)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ OIDN_LOCK(filter);
+ filter->setProgressMonitorFunction(func, userPtr);
+ OIDN_CATCH(filter)
+ }
+
+ OIDN_API void oidnCommitFilter(OIDNFilter hFilter)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ OIDN_LOCK(filter);
+ filter->commit();
+ OIDN_CATCH(filter)
+ }
+
+ OIDN_API void oidnExecuteFilter(OIDNFilter hFilter)
+ {
+ Filter* filter = (Filter*)hFilter;
+ OIDN_TRY
+ checkHandle(hFilter);
+ OIDN_LOCK(filter);
+ filter->execute();
+ OIDN_CATCH(filter)
+ }
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/autoencoder.cpp b/thirdparty/oidn/core/autoencoder.cpp
new file mode 100644
index 0000000000..8ae2421fa6
--- /dev/null
+++ b/thirdparty/oidn/core/autoencoder.cpp
@@ -0,0 +1,519 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "autoencoder.h"
+
+namespace oidn {
+
+ // --------------------------------------------------------------------------
+ // AutoencoderFilter
+ // --------------------------------------------------------------------------
+
+ AutoencoderFilter::AutoencoderFilter(const Ref<Device>& device)
+ : Filter(device)
+ {
+ }
+
+ void AutoencoderFilter::setImage(const std::string& name, const Image& data)
+ {
+ if (name == "color")
+ color = data;
+ else if (name == "albedo")
+ albedo = data;
+ else if (name == "normal")
+ normal = data;
+ else if (name == "output")
+ output = data;
+
+ dirty = true;
+ }
+
+ void AutoencoderFilter::set1i(const std::string& name, int value)
+ {
+ if (name == "hdr")
+ hdr = value;
+ else if (name == "srgb")
+ srgb = value;
+ else if (name == "maxMemoryMB")
+ maxMemoryMB = value;
+
+ dirty = true;
+ }
+
+ int AutoencoderFilter::get1i(const std::string& name)
+ {
+ if (name == "hdr")
+ return hdr;
+ else if (name == "srgb")
+ return srgb;
+ else if (name == "maxMemoryMB")
+ return maxMemoryMB;
+ else if (name == "alignment")
+ return alignment;
+ else if (name == "overlap")
+ return overlap;
+ else
+ throw Exception(Error::InvalidArgument, "invalid parameter");
+ }
+
+ void AutoencoderFilter::set1f(const std::string& name, float value)
+ {
+ if (name == "hdrScale")
+ hdrScale = value;
+
+ dirty = true;
+ }
+
+ float AutoencoderFilter::get1f(const std::string& name)
+ {
+ if (name == "hdrScale")
+ return hdrScale;
+ else
+ throw Exception(Error::InvalidArgument, "invalid parameter");
+ }
+
+ void AutoencoderFilter::commit()
+ {
+ if (!dirty)
+ return;
+
+ {
+ if (mayiuse(avx512_common))
+ net = buildNet<16>();
+ else
+ net = buildNet<8>();
+ }
+
+ dirty = false;
+ }
+
+ void AutoencoderFilter::execute()
+ {
+ if (dirty)
+ throw Exception(Error::InvalidOperation, "changes to the filter are not committed");
+
+ if (!net)
+ return;
+
+ {
+ Progress progress;
+ progress.func = progressFunc;
+ progress.userPtr = progressUserPtr;
+ progress.taskCount = tileCountH * tileCountW;
+
+ // Iterate over the tiles
+ int tileIndex = 0;
+
+ for (int i = 0; i < tileCountH; ++i)
+ {
+ const int h = i * (tileH - 2*overlap); // input tile position (including overlap)
+ const int overlapBeginH = i > 0 ? overlap : 0; // overlap on the top
+ const int overlapEndH = i < tileCountH-1 ? overlap : 0; // overlap on the bottom
+ const int tileH1 = min(H - h, tileH); // input tile size (including overlap)
+ const int tileH2 = tileH1 - overlapBeginH - overlapEndH; // output tile size
+ const int alignOffsetH = tileH - roundUp(tileH1, alignment); // align to the bottom in the tile buffer
+
+ for (int j = 0; j < tileCountW; ++j)
+ {
+ const int w = j * (tileW - 2*overlap); // input tile position (including overlap)
+ const int overlapBeginW = j > 0 ? overlap : 0; // overlap on the left
+ const int overlapEndW = j < tileCountW-1 ? overlap : 0; // overlap on the right
+ const int tileW1 = min(W - w, tileW); // input tile size (including overlap)
+ const int tileW2 = tileW1 - overlapBeginW - overlapEndW; // output tile size
+ const int alignOffsetW = tileW - roundUp(tileW1, alignment); // align to the right in the tile buffer
+
+ // Set the input tile
+ inputReorder->setTile(h, w,
+ alignOffsetH, alignOffsetW,
+ tileH1, tileW1);
+
+ // Set the output tile
+ outputReorder->setTile(alignOffsetH + overlapBeginH, alignOffsetW + overlapBeginW,
+ h + overlapBeginH, w + overlapBeginW,
+ tileH2, tileW2);
+
+ //printf("Tile: %d %d -> %d %d\n", w+overlapBeginW, h+overlapBeginH, w+overlapBeginW+tileW2, h+overlapBeginH+tileH2);
+
+ // Denoise the tile
+ net->execute(progress, tileIndex);
+
+ // Next tile
+ tileIndex++;
+ }
+ }
+ }
+ }
+
+ void AutoencoderFilter::computeTileSize()
+ {
+ const int minTileSize = 3*overlap;
+ const int estimatedBytesPerPixel = mayiuse(avx512_common) ? estimatedBytesPerPixel16 : estimatedBytesPerPixel8;
+ const int64_t maxTilePixels = (int64_t(maxMemoryMB)*1024*1024 - estimatedBytesBase) / estimatedBytesPerPixel;
+
+ tileCountH = 1;
+ tileCountW = 1;
+ tileH = roundUp(H, alignment);
+ tileW = roundUp(W, alignment);
+
+ // Divide the image into tiles until the tile size gets below the threshold
+ while (int64_t(tileH) * tileW > maxTilePixels)
+ {
+ if (tileH > minTileSize && tileH > tileW)
+ {
+ tileCountH++;
+ tileH = max(roundUp(ceilDiv(H - 2*overlap, tileCountH), alignment) + 2*overlap, minTileSize);
+ }
+ else if (tileW > minTileSize)
+ {
+ tileCountW++;
+ tileW = max(roundUp(ceilDiv(W - 2*overlap, tileCountW), alignment) + 2*overlap, minTileSize);
+ }
+ else
+ break;
+ }
+
+ // Compute the final number of tiles
+ tileCountH = (H > tileH) ? ceilDiv(H - 2*overlap, tileH - 2*overlap) : 1;
+ tileCountW = (W > tileW) ? ceilDiv(W - 2*overlap, tileW - 2*overlap) : 1;
+
+ if (device->isVerbose(2))
+ {
+ std::cout << "Tile size : " << tileW << "x" << tileH << std::endl;
+ std::cout << "Tile count: " << tileCountW << "x" << tileCountH << std::endl;
+ }
+ }
+
+ template<int K>
+ std::shared_ptr<Executable> AutoencoderFilter::buildNet()
+ {
+ H = color.height;
+ W = color.width;
+
+ // Configure the network
+ int inputC;
+ void* weightPtr;
+
+ if (srgb && hdr)
+ throw Exception(Error::InvalidOperation, "srgb and hdr modes cannot be enabled at the same time");
+
+ if (color && !albedo && !normal && weightData.hdr)
+ {
+ inputC = 3;
+ weightPtr = hdr ? weightData.hdr : weightData.ldr;
+ }
+ else if (color && albedo && !normal && weightData.hdr_alb)
+ {
+ inputC = 6;
+ weightPtr = hdr ? weightData.hdr_alb : weightData.ldr_alb;
+ }
+ else if (color && albedo && normal && weightData.hdr_alb_nrm)
+ {
+ inputC = 9;
+ weightPtr = hdr ? weightData.hdr_alb_nrm : weightData.ldr_alb_nrm;
+ }
+ else
+ {
+ throw Exception(Error::InvalidOperation, "unsupported combination of input features");
+ }
+
+ if (!output)
+ throw Exception(Error::InvalidOperation, "output image not specified");
+
+ if ((color.format != Format::Float3)
+ || (albedo && albedo.format != Format::Float3)
+ || (normal && normal.format != Format::Float3)
+ || (output.format != Format::Float3))
+ throw Exception(Error::InvalidOperation, "unsupported image format");
+
+ if ((albedo && (albedo.width != W || albedo.height != H))
+ || (normal && (normal.width != W || normal.height != H))
+ || (output.width != W || output.height != H))
+ throw Exception(Error::InvalidOperation, "image size mismatch");
+
+ // Compute the tile size
+ computeTileSize();
+
+ // If the image size is zero, there is nothing else to do
+ if (H <= 0 || W <= 0)
+ return nullptr;
+
+ // Parse the weights
+ const auto weightMap = parseTensors(weightPtr);
+
+ // Create the network
+ std::shared_ptr<Network<K>> net = std::make_shared<Network<K>>(device, weightMap);
+
+ // Compute the tensor sizes
+ const auto inputDims = memory::dims({1, inputC, tileH, tileW});
+ const auto inputReorderDims = net->getInputReorderDims(inputDims, alignment); //-> concat0
+
+ const auto conv1Dims = net->getConvDims("conv1", inputReorderDims); //-> temp0
+ const auto conv1bDims = net->getConvDims("conv1b", conv1Dims); //-> temp1
+ const auto pool1Dims = net->getPoolDims(conv1bDims); //-> concat1
+ const auto conv2Dims = net->getConvDims("conv2", pool1Dims); //-> temp0
+ const auto pool2Dims = net->getPoolDims(conv2Dims); //-> concat2
+ const auto conv3Dims = net->getConvDims("conv3", pool2Dims); //-> temp0
+ const auto pool3Dims = net->getPoolDims(conv3Dims); //-> concat3
+ const auto conv4Dims = net->getConvDims("conv4", pool3Dims); //-> temp0
+ const auto pool4Dims = net->getPoolDims(conv4Dims); //-> concat4
+ const auto conv5Dims = net->getConvDims("conv5", pool4Dims); //-> temp0
+ const auto pool5Dims = net->getPoolDims(conv5Dims); //-> temp1
+ const auto upsample4Dims = net->getUpsampleDims(pool5Dims); //-> concat4
+ const auto concat4Dims = net->getConcatDims(upsample4Dims, pool4Dims);
+ const auto conv6Dims = net->getConvDims("conv6", concat4Dims); //-> temp0
+ const auto conv6bDims = net->getConvDims("conv6b", conv6Dims); //-> temp1
+ const auto upsample3Dims = net->getUpsampleDims(conv6bDims); //-> concat3
+ const auto concat3Dims = net->getConcatDims(upsample3Dims, pool3Dims);
+ const auto conv7Dims = net->getConvDims("conv7", concat3Dims); //-> temp0
+ const auto conv7bDims = net->getConvDims("conv7b", conv7Dims); //-> temp1
+ const auto upsample2Dims = net->getUpsampleDims(conv7bDims); //-> concat2
+ const auto concat2Dims = net->getConcatDims(upsample2Dims, pool2Dims);
+ const auto conv8Dims = net->getConvDims("conv8", concat2Dims); //-> temp0
+ const auto conv8bDims = net->getConvDims("conv8b", conv8Dims); //-> temp1
+ const auto upsample1Dims = net->getUpsampleDims(conv8bDims); //-> concat1
+ const auto concat1Dims = net->getConcatDims(upsample1Dims, pool1Dims);
+ const auto conv9Dims = net->getConvDims("conv9", concat1Dims); //-> temp0
+ const auto conv9bDims = net->getConvDims("conv9b", conv9Dims); //-> temp1
+ const auto upsample0Dims = net->getUpsampleDims(conv9bDims); //-> concat0
+ const auto concat0Dims = net->getConcatDims(upsample0Dims, inputReorderDims);
+ const auto conv10Dims = net->getConvDims("conv10", concat0Dims); //-> temp0
+ const auto conv10bDims = net->getConvDims("conv10b", conv10Dims); //-> temp1
+ const auto conv11Dims = net->getConvDims("conv11", conv10bDims); //-> temp0
+
+ const auto outputDims = memory::dims({1, 3, tileH, tileW});
+
+ // Allocate two temporary ping-pong buffers to decrease memory usage
+ const auto temp0Dims = getMaxTensorDims({
+ conv1Dims,
+ conv2Dims,
+ conv3Dims,
+ conv4Dims,
+ conv5Dims,
+ conv6Dims,
+ conv7Dims,
+ conv8Dims,
+ conv9Dims,
+ conv10Dims,
+ conv11Dims
+ });
+
+ const auto temp1Dims = getMaxTensorDims({
+ conv1bDims,
+ pool5Dims,
+ conv6bDims,
+ conv7bDims,
+ conv8bDims,
+ conv9bDims,
+ conv10bDims,
+ });
+
+ auto temp0 = net->allocTensor(temp0Dims);
+ auto temp1 = net->allocTensor(temp1Dims);
+
+ // Allocate enough memory to hold the concat outputs. Then use the first
+ // half to hold the previous conv output and the second half to hold the
+ // pool/orig image output. This works because everything is C dimension
+ // outermost, padded to K floats, and all the concats are on the C dimension.
+ auto concat0Dst = net->allocTensor(concat0Dims);
+ auto concat1Dst = net->allocTensor(concat1Dims);
+ auto concat2Dst = net->allocTensor(concat2Dims);
+ auto concat3Dst = net->allocTensor(concat3Dims);
+ auto concat4Dst = net->allocTensor(concat4Dims);
+
+ // Transfer function
+ std::shared_ptr<TransferFunction> transferFunc = makeTransferFunc();
+
+ // Autoexposure
+ if (auto tf = std::dynamic_pointer_cast<HDRTransferFunction>(transferFunc))
+ {
+ if (isnan(hdrScale))
+ net->addAutoexposure(color, tf);
+ else
+ tf->setExposure(hdrScale);
+ }
+
+ // Input reorder
+ auto inputReorderDst = net->castTensor(inputReorderDims, concat0Dst, upsample0Dims);
+ inputReorder = net->addInputReorder(color, albedo, normal,
+ transferFunc,
+ alignment, inputReorderDst);
+
+ // conv1
+ auto conv1 = net->addConv("conv1", inputReorder->getDst(), temp0);
+
+ // conv1b
+ auto conv1b = net->addConv("conv1b", conv1->getDst(), temp1);
+
+ // pool1
+ // Adjust pointer for pool1 to eliminate concat1
+ auto pool1Dst = net->castTensor(pool1Dims, concat1Dst, upsample1Dims);
+ auto pool1 = net->addPool(conv1b->getDst(), pool1Dst);
+
+ // conv2
+ auto conv2 = net->addConv("conv2", pool1->getDst(), temp0);
+
+ // pool2
+ // Adjust pointer for pool2 to eliminate concat2
+ auto pool2Dst = net->castTensor(pool2Dims, concat2Dst, upsample2Dims);
+ auto pool2 = net->addPool(conv2->getDst(), pool2Dst);
+
+ // conv3
+ auto conv3 = net->addConv("conv3", pool2->getDst(), temp0);
+
+ // pool3
+ // Adjust pointer for pool3 to eliminate concat3
+ auto pool3Dst = net->castTensor(pool3Dims, concat3Dst, upsample3Dims);
+ auto pool3 = net->addPool(conv3->getDst(), pool3Dst);
+
+ // conv4
+ auto conv4 = net->addConv("conv4", pool3->getDst(), temp0);
+
+ // pool4
+ // Adjust pointer for pool4 to eliminate concat4
+ auto pool4Dst = net->castTensor(pool4Dims, concat4Dst, upsample4Dims);
+ auto pool4 = net->addPool(conv4->getDst(), pool4Dst);
+
+ // conv5
+ auto conv5 = net->addConv("conv5", pool4->getDst(), temp0);
+
+ // pool5
+ auto pool5 = net->addPool(conv5->getDst(), temp1);
+
+ // upsample4
+ auto upsample4Dst = net->castTensor(upsample4Dims, concat4Dst);
+ auto upsample4 = net->addUpsample(pool5->getDst(), upsample4Dst);
+
+ // conv6
+ auto conv6 = net->addConv("conv6", concat4Dst, temp0);
+
+ // conv6b
+ auto conv6b = net->addConv("conv6b", conv6->getDst(), temp1);
+
+ // upsample3
+ auto upsample3Dst = net->castTensor(upsample3Dims, concat3Dst);
+ auto upsample3 = net->addUpsample(conv6b->getDst(), upsample3Dst);
+
+ // conv7
+ auto conv7 = net->addConv("conv7", concat3Dst, temp0);
+
+ // conv7b
+ auto conv7b = net->addConv("conv7b", conv7->getDst(), temp1);
+
+ // upsample2
+ auto upsample2Dst = net->castTensor(upsample2Dims, concat2Dst);
+ auto upsample2 = net->addUpsample(conv7b->getDst(), upsample2Dst);
+
+ // conv8
+ auto conv8 = net->addConv("conv8", concat2Dst, temp0);
+
+ // conv8b
+ auto conv8b = net->addConv("conv8b", conv8->getDst(), temp1);
+
+ // upsample1
+ auto upsample1Dst = net->castTensor(upsample1Dims, concat1Dst);
+ auto upsample1 = net->addUpsample(conv8b->getDst(), upsample1Dst);
+
+ // conv9
+ auto conv9 = net->addConv("conv9", concat1Dst, temp0);
+
+ // conv9b
+ auto conv9b = net->addConv("conv9b", conv9->getDst(), temp1);
+
+ // upsample0
+ auto upsample0Dst = net->castTensor(upsample0Dims, concat0Dst);
+ auto upsample0 = net->addUpsample(conv9b->getDst(), upsample0Dst);
+
+ // conv10
+ auto conv10 = net->addConv("conv10", concat0Dst, temp0);
+
+ // conv10b
+ auto conv10b = net->addConv("conv10b", conv10->getDst(), temp1);
+
+ // conv11
+ auto conv11 = net->addConv("conv11", conv10b->getDst(), temp0, false /* no relu */);
+
+ // Output reorder
+ outputReorder = net->addOutputReorder(conv11->getDst(), transferFunc, output);
+
+ net->finalize();
+ return net;
+ }
+
+ std::shared_ptr<TransferFunction> AutoencoderFilter::makeTransferFunc()
+ {
+ if (hdr)
+ return std::make_shared<PQXTransferFunction>();
+ else if (srgb)
+ return std::make_shared<LinearTransferFunction>();
+ else
+ return std::make_shared<GammaTransferFunction>();
+ }
+
+// Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
+#if 0
+ // --------------------------------------------------------------------------
+ // RTFilter
+ // --------------------------------------------------------------------------
+
+ namespace weights
+ {
+ // LDR
+ extern unsigned char rt_ldr[]; // color
+ extern unsigned char rt_ldr_alb[]; // color, albedo
+ extern unsigned char rt_ldr_alb_nrm[]; // color, albedo, normal
+
+ // HDR
+ extern unsigned char rt_hdr[]; // color
+ extern unsigned char rt_hdr_alb[]; // color, albedo
+ extern unsigned char rt_hdr_alb_nrm[]; // color, albedo, normal
+ }
+
+ RTFilter::RTFilter(const Ref<Device>& device)
+ : AutoencoderFilter(device)
+ {
+ weightData.ldr = weights::rt_ldr;
+ weightData.ldr_alb = weights::rt_ldr_alb;
+ weightData.ldr_alb_nrm = weights::rt_ldr_alb_nrm;
+ weightData.hdr = weights::rt_hdr;
+ weightData.hdr_alb = weights::rt_hdr_alb;
+ weightData.hdr_alb_nrm = weights::rt_hdr_alb_nrm;
+ }
+#endif
+
+ // --------------------------------------------------------------------------
+ // RTLightmapFilter
+ // --------------------------------------------------------------------------
+
+ namespace weights
+ {
+ // HDR
+ extern unsigned char rtlightmap_hdr[]; // color
+ }
+
+ RTLightmapFilter::RTLightmapFilter(const Ref<Device>& device)
+ : AutoencoderFilter(device)
+ {
+ weightData.hdr = weights::rtlightmap_hdr;
+
+ hdr = true;
+ }
+
+ std::shared_ptr<TransferFunction> RTLightmapFilter::makeTransferFunc()
+ {
+ return std::make_shared<LogTransferFunction>();
+ }
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/autoencoder.h b/thirdparty/oidn/core/autoencoder.h
new file mode 100644
index 0000000000..97432f2bbd
--- /dev/null
+++ b/thirdparty/oidn/core/autoencoder.h
@@ -0,0 +1,116 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "filter.h"
+#include "network.h"
+#include "transfer_function.h"
+
+namespace oidn {
+
+ // --------------------------------------------------------------------------
+ // AutoencoderFilter - Direct-predicting autoencoder
+ // --------------------------------------------------------------------------
+
+ class AutoencoderFilter : public Filter
+ {
+ protected:
+ static constexpr int alignment = 32; // required spatial alignment in pixels (padding may be necessary)
+ static constexpr int receptiveField = 222; // receptive field in pixels
+ static constexpr int overlap = roundUp(receptiveField / 2, alignment); // required spatial overlap between tiles in pixels
+
+ static constexpr int estimatedBytesBase = 16*1024*1024; // estimated base memory usage
+ static constexpr int estimatedBytesPerPixel8 = 889; // estimated memory usage per pixel for K=8
+ static constexpr int estimatedBytesPerPixel16 = 2185; // estimated memory usage per pixel for K=16
+
+ Image color;
+ Image albedo;
+ Image normal;
+ Image output;
+ bool hdr = false;
+ float hdrScale = std::numeric_limits<float>::quiet_NaN();
+ bool srgb = false;
+ int maxMemoryMB = 6000; // approximate maximum memory usage in MBs
+
+ int H = 0; // image height
+ int W = 0; // image width
+ int tileH = 0; // tile height
+ int tileW = 0; // tile width
+ int tileCountH = 1; // number of tiles in H dimension
+ int tileCountW = 1; // number of tiles in W dimension
+
+ std::shared_ptr<Executable> net;
+ std::shared_ptr<Node> inputReorder;
+ std::shared_ptr<Node> outputReorder;
+
+ struct
+ {
+ void* ldr = nullptr;
+ void* ldr_alb = nullptr;
+ void* ldr_alb_nrm = nullptr;
+ void* hdr = nullptr;
+ void* hdr_alb = nullptr;
+ void* hdr_alb_nrm = nullptr;
+ } weightData;
+
+ explicit AutoencoderFilter(const Ref<Device>& device);
+ virtual std::shared_ptr<TransferFunction> makeTransferFunc();
+
+ public:
+ void setImage(const std::string& name, const Image& data) override;
+ void set1i(const std::string& name, int value) override;
+ int get1i(const std::string& name) override;
+ void set1f(const std::string& name, float value) override;
+ float get1f(const std::string& name) override;
+
+ void commit() override;
+ void execute() override;
+
+ private:
+ void computeTileSize();
+
+ template<int K>
+ std::shared_ptr<Executable> buildNet();
+
+ bool isCommitted() const { return bool(net); }
+ };
+
+ // --------------------------------------------------------------------------
+ // RTFilter - Generic ray tracing denoiser
+ // --------------------------------------------------------------------------
+
+// Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
+#if 0
+ class RTFilter : public AutoencoderFilter
+ {
+ public:
+ explicit RTFilter(const Ref<Device>& device);
+ };
+#endif
+
+ // --------------------------------------------------------------------------
+ // RTLightmapFilter - Ray traced lightmap denoiser
+ // --------------------------------------------------------------------------
+
+ class RTLightmapFilter : public AutoencoderFilter
+ {
+ public:
+ explicit RTLightmapFilter(const Ref<Device>& device);
+ std::shared_ptr<TransferFunction> makeTransferFunc() override;
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/buffer.h b/thirdparty/oidn/core/buffer.h
new file mode 100644
index 0000000000..b95109152e
--- /dev/null
+++ b/thirdparty/oidn/core/buffer.h
@@ -0,0 +1,75 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "common.h"
+#include "device.h"
+
+namespace oidn {
+
+ class Device;
+
+ // Buffer which may or may not own its data
+ class Buffer : public RefCount
+ {
+ private:
+ char* ptr;
+ size_t byteSize;
+ bool shared;
+ Ref<Device> device;
+
+ public:
+ __forceinline Buffer(const Ref<Device>& device, size_t size)
+ : ptr((char*)alignedMalloc(size, 64)),
+ byteSize(size),
+ shared(false),
+ device(device) {}
+
+ __forceinline Buffer(const Ref<Device>& device, void* data, size_t size)
+ : ptr((char*)data),
+ byteSize(size),
+ shared(true),
+ device(device)
+ {
+ if (data == nullptr)
+ throw Exception(Error::InvalidArgument, "buffer pointer null");
+ }
+
+ __forceinline ~Buffer()
+ {
+ if (!shared)
+ alignedFree(ptr);
+ }
+
+ __forceinline char* data() { return ptr; }
+ __forceinline const char* data() const { return ptr; }
+ __forceinline size_t size() const { return byteSize; }
+
+ void* map(size_t offset, size_t size)
+ {
+ if (offset + size > byteSize)
+ throw Exception(Error::InvalidArgument, "buffer region out of range");
+
+ return ptr + offset;
+ }
+
+ void unmap(void* mappedPtr) {}
+
+ Device* getDevice() { return device.get(); }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/common.h b/thirdparty/oidn/core/common.h
new file mode 100644
index 0000000000..6c87f377bc
--- /dev/null
+++ b/thirdparty/oidn/core/common.h
@@ -0,0 +1,133 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "common/platform.h"
+
+#include "mkl-dnn/include/mkldnn.hpp"
+#include "mkl-dnn/include/mkldnn_debug.h"
+#include "mkl-dnn/src/common/mkldnn_thread.hpp"
+#include "mkl-dnn/src/common/type_helpers.hpp"
+#include "mkl-dnn/src/cpu/jit_generator.hpp"
+
+#include "common/ref.h"
+#include "common/exception.h"
+#include "common/thread.h"
+#include "math.h"
+
+namespace oidn {
+
+ using namespace mkldnn;
+ using namespace mkldnn::impl::cpu;
+ using mkldnn::impl::parallel_nd;
+ using mkldnn::impl::memory_desc_matches_tag;
+
+
+ inline size_t getFormatBytes(Format format)
+ {
+ switch (format)
+ {
+ case Format::Undefined: return 1;
+ case Format::Float: return sizeof(float);
+ case Format::Float2: return sizeof(float)*2;
+ case Format::Float3: return sizeof(float)*3;
+ case Format::Float4: return sizeof(float)*4;
+ }
+ assert(0);
+ return 0;
+ }
+
+
+ inline memory::dims getTensorDims(const std::shared_ptr<memory>& mem)
+ {
+ const mkldnn_memory_desc_t& desc = mem->get_desc().data;
+ return memory::dims(&desc.dims[0], &desc.dims[desc.ndims]);
+ }
+
+ inline memory::data_type getTensorType(const std::shared_ptr<memory>& mem)
+ {
+ const mkldnn_memory_desc_t& desc = mem->get_desc().data;
+ return memory::data_type(desc.data_type);
+ }
+
+ // Returns the number of values in a tensor
+ inline size_t getTensorSize(const memory::dims& dims)
+ {
+ size_t res = 1;
+ for (int i = 0; i < (int)dims.size(); ++i)
+ res *= dims[i];
+ return res;
+ }
+
+ inline memory::dims getMaxTensorDims(const std::vector<memory::dims>& dims)
+ {
+ memory::dims result;
+ size_t maxSize = 0;
+
+ for (const auto& d : dims)
+ {
+ const size_t size = getTensorSize(d);
+ if (size > maxSize)
+ {
+ result = d;
+ maxSize = size;
+ }
+ }
+
+ return result;
+ }
+
+ inline size_t getTensorSize(const std::shared_ptr<memory>& mem)
+ {
+ return getTensorSize(getTensorDims(mem));
+ }
+
+
+ template<int K>
+ inline int getPadded(int dim)
+ {
+ return (dim + (K-1)) & ~(K-1);
+ }
+
+ template<int K>
+ inline memory::dims getPadded_nchw(const memory::dims& dims)
+ {
+ assert(dims.size() == 4);
+ memory::dims padDims = dims;
+ padDims[1] = getPadded<K>(dims[1]); // pad C
+ return padDims;
+ }
+
+
+ template<int K>
+ struct BlockedFormat;
+
+ template<>
+ struct BlockedFormat<8>
+ {
+ static constexpr memory::format_tag nChwKc = memory::format_tag::nChw8c;
+ static constexpr memory::format_tag OIhwKiKo = memory::format_tag::OIhw8i8o;
+ };
+
+ template<>
+ struct BlockedFormat<16>
+ {
+ static constexpr memory::format_tag nChwKc = memory::format_tag::nChw16c;
+ static constexpr memory::format_tag OIhwKiKo = memory::format_tag::OIhw16i16o;
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/device.cpp b/thirdparty/oidn/core/device.cpp
new file mode 100644
index 0000000000..0812624bb5
--- /dev/null
+++ b/thirdparty/oidn/core/device.cpp
@@ -0,0 +1,205 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "device.h"
+#include "autoencoder.h"
+
+namespace oidn {
+
+ thread_local Device::ErrorState Device::globalError;
+
+ Device::Device()
+ {
+ if (!mayiuse(sse41))
+ throw Exception(Error::UnsupportedHardware, "SSE4.1 support is required at minimum");
+ }
+
+ Device::~Device()
+ {
+ }
+
+ void Device::setError(Device* device, Error code, const std::string& message)
+ {
+ // Update the stored error only if the previous error was queried
+ if (device)
+ {
+ ErrorState& curError = device->error.get();
+
+ if (curError.code == Error::None)
+ {
+ curError.code = code;
+ curError.message = message;
+ }
+
+ // Print the error message in verbose mode
+ if (device->isVerbose())
+ std::cerr << "Error: " << message << std::endl;
+
+ // Call the error callback function
+ ErrorFunction errorFunc;
+ void* errorUserPtr;
+
+ {
+ std::lock_guard<std::mutex> lock(device->mutex);
+ errorFunc = device->errorFunc;
+ errorUserPtr = device->errorUserPtr;
+ }
+
+ if (errorFunc)
+ errorFunc(errorUserPtr, code, (code == Error::None) ? nullptr : message.c_str());
+ }
+ else
+ {
+ if (globalError.code == Error::None)
+ {
+ globalError.code = code;
+ globalError.message = message;
+ }
+ }
+ }
+
+ Error Device::getError(Device* device, const char** outMessage)
+ {
+ // Return and clear the stored error code, but keep the error message so pointers to it will
+ // remain valid until the next getError call
+ if (device)
+ {
+ ErrorState& curError = device->error.get();
+ const Error code = curError.code;
+ if (outMessage)
+ *outMessage = (code == Error::None) ? nullptr : curError.message.c_str();
+ curError.code = Error::None;
+ return code;
+ }
+ else
+ {
+ const Error code = globalError.code;
+ if (outMessage)
+ *outMessage = (code == Error::None) ? nullptr : globalError.message.c_str();
+ globalError.code = Error::None;
+ return code;
+ }
+ }
+
+ void Device::setErrorFunction(ErrorFunction func, void* userPtr)
+ {
+ errorFunc = func;
+ errorUserPtr = userPtr;
+ }
+
+ int Device::get1i(const std::string& name)
+ {
+ if (name == "numThreads")
+ return numThreads;
+ else if (name == "setAffinity")
+ return setAffinity;
+ else if (name == "verbose")
+ return verbose;
+ else if (name == "version")
+ return OIDN_VERSION;
+ else if (name == "versionMajor")
+ return OIDN_VERSION_MAJOR;
+ else if (name == "versionMinor")
+ return OIDN_VERSION_MINOR;
+ else if (name == "versionPatch")
+ return OIDN_VERSION_PATCH;
+ else
+ throw Exception(Error::InvalidArgument, "invalid parameter");
+ }
+
+ void Device::set1i(const std::string& name, int value)
+ {
+ if (name == "numThreads")
+ numThreads = value;
+ else if (name == "setAffinity")
+ setAffinity = value;
+ else if (name == "verbose")
+ {
+ verbose = value;
+ error.verbose = value;
+ }
+
+ dirty = true;
+ }
+
+ void Device::commit()
+ {
+ if (isCommitted())
+ throw Exception(Error::InvalidOperation, "device can be committed only once");
+
+ // Create the task arena
+ const int maxNumThreads = 1; //affinity ? affinity->getNumThreads() : tbb::this_task_arena::max_concurrency();
+ numThreads = (numThreads > 0) ? min(numThreads, maxNumThreads) : maxNumThreads;
+
+ dirty = false;
+
+ if (isVerbose())
+ print();
+ }
+
+ void Device::checkCommitted()
+ {
+ if (dirty)
+ throw Exception(Error::InvalidOperation, "changes to the device are not committed");
+ }
+
+ Ref<Buffer> Device::newBuffer(size_t byteSize)
+ {
+ checkCommitted();
+ return makeRef<Buffer>(Ref<Device>(this), byteSize);
+ }
+
+ Ref<Buffer> Device::newBuffer(void* ptr, size_t byteSize)
+ {
+ checkCommitted();
+ return makeRef<Buffer>(Ref<Device>(this), ptr, byteSize);
+ }
+
+ Ref<Filter> Device::newFilter(const std::string& type)
+ {
+ checkCommitted();
+
+ if (isVerbose())
+ std::cout << "Filter: " << type << std::endl;
+
+ Ref<Filter> filter;
+
+// Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
+#if 0
+ if (type == "RT")
+ filter = makeRef<RTFilter>(Ref<Device>(this));
+#endif
+ if (type == "RTLightmap")
+ filter = makeRef<RTLightmapFilter>(Ref<Device>(this));
+ else
+ throw Exception(Error::InvalidArgument, "unknown filter type");
+
+ return filter;
+ }
+
+ void Device::print()
+ {
+ std::cout << std::endl;
+
+ std::cout << "Intel(R) Open Image Denoise " << OIDN_VERSION_STRING << std::endl;
+ std::cout << " Compiler: " << getCompilerName() << std::endl;
+ std::cout << " Build : " << getBuildName() << std::endl;
+ std::cout << " Platform: " << getPlatformName() << std::endl;
+
+ std::cout << std::endl;
+ }
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/device.h b/thirdparty/oidn/core/device.h
new file mode 100644
index 0000000000..93a83eb731
--- /dev/null
+++ b/thirdparty/oidn/core/device.h
@@ -0,0 +1,78 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "common.h"
+
+namespace oidn {
+
+ class Buffer;
+ class Filter;
+
+ class Device : public RefCount, public Verbose
+ {
+ private:
+ // Thread-safety
+ std::mutex mutex;
+
+ // Error handling
+ struct ErrorState
+ {
+ Error code = Error::None;
+ std::string message;
+ };
+
+ static thread_local ErrorState globalError;
+ ThreadLocal<ErrorState> error;
+ ErrorFunction errorFunc = nullptr;
+ void* errorUserPtr = nullptr;
+
+ // Parameters
+ int numThreads = 0; // autodetect by default
+ bool setAffinity = true;
+
+ bool dirty = true;
+
+ public:
+ Device();
+ ~Device();
+
+ static void setError(Device* device, Error code, const std::string& message);
+ static Error getError(Device* device, const char** outMessage);
+
+ void setErrorFunction(ErrorFunction func, void* userPtr);
+
+ int get1i(const std::string& name);
+ void set1i(const std::string& name, int value);
+
+ void commit();
+
+ Ref<Buffer> newBuffer(size_t byteSize);
+ Ref<Buffer> newBuffer(void* ptr, size_t byteSize);
+ Ref<Filter> newFilter(const std::string& type);
+
+ __forceinline Device* getDevice() { return this; }
+ __forceinline std::mutex& getMutex() { return mutex; }
+
+ private:
+ bool isCommitted() const { return false; }
+ void checkCommitted();
+
+ void print();
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/filter.cpp b/thirdparty/oidn/core/filter.cpp
new file mode 100644
index 0000000000..ec1f10af87
--- /dev/null
+++ b/thirdparty/oidn/core/filter.cpp
@@ -0,0 +1,27 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "filter.h"
+
+namespace oidn {
+
+ void Filter::setProgressMonitorFunction(ProgressMonitorFunction func, void* userPtr)
+ {
+ progressFunc = func;
+ progressUserPtr = userPtr;
+ }
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/filter.h b/thirdparty/oidn/core/filter.h
new file mode 100644
index 0000000000..935fa202f4
--- /dev/null
+++ b/thirdparty/oidn/core/filter.h
@@ -0,0 +1,52 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "common.h"
+#include "device.h"
+#include "image.h"
+
+namespace oidn {
+
+ class Filter : public RefCount
+ {
+ protected:
+ Ref<Device> device;
+
+ ProgressMonitorFunction progressFunc = nullptr;
+ void* progressUserPtr = nullptr;
+
+ bool dirty = true;
+
+ public:
+ explicit Filter(const Ref<Device>& device) : device(device) {}
+
+ virtual void setImage(const std::string& name, const Image& data) = 0;
+ virtual void set1i(const std::string& name, int value) = 0;
+ virtual int get1i(const std::string& name) = 0;
+ virtual void set1f(const std::string& name, float value) = 0;
+ virtual float get1f(const std::string& name) = 0;
+
+ void setProgressMonitorFunction(ProgressMonitorFunction func, void* userPtr);
+
+ virtual void commit() = 0;
+ virtual void execute() = 0;
+
+ Device* getDevice() { return device.get(); }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/image.h b/thirdparty/oidn/core/image.h
new file mode 100644
index 0000000000..748f49c4e5
--- /dev/null
+++ b/thirdparty/oidn/core/image.h
@@ -0,0 +1,111 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "common.h"
+#include "buffer.h"
+
+namespace oidn {
+
+ struct Image
+ {
+ static constexpr int maxSize = 65536;
+
+ char* ptr; // pointer to the first pixel
+ int width; // width in number of pixels
+ int height; // height in number of pixels
+ size_t bytePixelStride; // pixel stride in number of *bytes*
+ size_t rowStride; // row stride in number of *pixel strides*
+ Format format; // pixel format
+ Ref<Buffer> buffer; // buffer containing the image data
+
+ Image() : ptr(nullptr), width(0), height(0), bytePixelStride(0), rowStride(0), format(Format::Undefined) {}
+
+ Image(void* ptr, Format format, int width, int height, size_t byteOffset, size_t inBytePixelStride, size_t inByteRowStride)
+ {
+ if (ptr == nullptr)
+ throw Exception(Error::InvalidArgument, "buffer pointer null");
+
+ init((char*)ptr + byteOffset, format, width, height, inBytePixelStride, inByteRowStride);
+ }
+
+ Image(const Ref<Buffer>& buffer, Format format, int width, int height, size_t byteOffset, size_t inBytePixelStride, size_t inByteRowStride)
+ {
+ init(buffer->data() + byteOffset, format, width, height, inBytePixelStride, inByteRowStride);
+
+ if (byteOffset + height * rowStride * bytePixelStride > buffer->size())
+ throw Exception(Error::InvalidArgument, "buffer region out of range");
+ }
+
+ void init(char* ptr, Format format, int width, int height, size_t inBytePixelStride, size_t inByteRowStride)
+ {
+ assert(width >= 0);
+ assert(height >= 0);
+ if (width > maxSize || height > maxSize)
+ throw Exception(Error::InvalidArgument, "image size too large");
+
+ this->ptr = ptr;
+ this->width = width;
+ this->height = height;
+
+ const size_t pixelSize = getFormatBytes(format);
+ if (inBytePixelStride != 0)
+ {
+ if (inBytePixelStride < pixelSize)
+ throw Exception(Error::InvalidArgument, "pixel stride smaller than pixel size");
+
+ this->bytePixelStride = inBytePixelStride;
+ }
+ else
+ {
+ this->bytePixelStride = pixelSize;
+ }
+
+ if (inByteRowStride != 0)
+ {
+ if (inByteRowStride < width * this->bytePixelStride)
+ throw Exception(Error::InvalidArgument, "row stride smaller than width * pixel stride");
+ if (inByteRowStride % this->bytePixelStride != 0)
+ throw Exception(Error::InvalidArgument, "row stride not integer multiple of pixel stride");
+
+ this->rowStride = inByteRowStride / this->bytePixelStride;
+ }
+ else
+ {
+ this->rowStride = width;
+ }
+
+ this->format = format;
+ }
+
+ __forceinline char* get(int y, int x)
+ {
+ return ptr + ((size_t(y) * rowStride + size_t(x)) * bytePixelStride);
+ }
+
+ __forceinline const char* get(int y, int x) const
+ {
+ return ptr + ((size_t(y) * rowStride + size_t(x)) * bytePixelStride);
+ }
+
+ operator bool() const
+ {
+ return ptr != nullptr;
+ }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/input_reorder.h b/thirdparty/oidn/core/input_reorder.h
new file mode 100644
index 0000000000..966856afe9
--- /dev/null
+++ b/thirdparty/oidn/core/input_reorder.h
@@ -0,0 +1,232 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "node.h"
+#include "image.h"
+
+namespace oidn {
+
+ // Input reorder node
+ template<int K, class TransferFunction>
+ class InputReorderNode : public Node
+ {
+ private:
+ // Source
+ Image color;
+ Image albedo;
+ Image normal;
+
+ // Destination
+ std::shared_ptr<memory> dst;
+ float* dstPtr;
+ int C2;
+ int H2;
+ int W2;
+
+ // Tile
+ int h1Begin;
+ int w1Begin;
+ int h2Begin;
+ int w2Begin;
+ int H;
+ int W;
+
+ std::shared_ptr<TransferFunction> transferFunc;
+
+ public:
+ InputReorderNode(const Image& color,
+ const Image& albedo,
+ const Image& normal,
+ const std::shared_ptr<memory>& dst,
+ const std::shared_ptr<TransferFunction>& transferFunc)
+ : color(color), albedo(albedo), normal(normal),
+ dst(dst),
+ h1Begin(0), w1Begin(0),
+ H(color.height), W(color.width),
+ transferFunc(transferFunc)
+ {
+ const mkldnn_memory_desc_t& dstDesc = dst->get_desc().data;
+ assert(memory_desc_matches_tag(dstDesc, mkldnn_format_tag_t(BlockedFormat<K>::nChwKc)));
+ assert(dstDesc.ndims == 4);
+ assert(dstDesc.data_type == memory::data_type::f32);
+ assert(dstDesc.dims[0] == 1);
+ //assert(dstDesc.dims[1] >= getPadded<K>(C1));
+
+ dstPtr = (float*)dst->get_data_handle();
+ C2 = dstDesc.dims[1];
+ H2 = dstDesc.dims[2];
+ W2 = dstDesc.dims[3];
+ }
+
+ void setTile(int h1, int w1, int h2, int w2, int H, int W) override
+ {
+ h1Begin = h1;
+ w1Begin = w1;
+ h2Begin = h2;
+ w2Begin = w2;
+ this->H = H;
+ this->W = W;
+ }
+
+ void execute(stream& sm) override
+ {
+ assert(H + h1Begin <= color.height);
+ assert(W + w1Begin <= color.width);
+ assert(H + h2Begin <= H2);
+ assert(W + w2Begin <= W2);
+
+ parallel_nd(H2, [&](int h2)
+ {
+ const int h = h2 - h2Begin;
+
+ if (h >= 0 && h < H)
+ {
+ const int h1 = h + h1Begin;
+
+ // Zero pad
+ for (int w2 = 0; w2 < w2Begin; ++w2)
+ {
+ int c = 0;
+ while (c < C2)
+ store(h2, w2, c, 0.f);
+ }
+
+ // Reorder
+ for (int w = 0; w < W; ++w)
+ {
+ const int w1 = w + w1Begin;
+ const int w2 = w + w2Begin;
+
+ int c = 0;
+ storeColor(h2, w2, c, (float*)color.get(h1, w1));
+ if (albedo)
+ storeAlbedo(h2, w2, c, (float*)albedo.get(h1, w1));
+ if (normal)
+ storeNormal(h2, w2, c, (float*)normal.get(h1, w1));
+ while (c < C2)
+ store(h2, w2, c, 0.f);
+ }
+
+ // Zero pad
+ for (int w2 = W + w2Begin; w2 < W2; ++w2)
+ {
+ int c = 0;
+ while (c < C2)
+ store(h2, w2, c, 0.f);
+ }
+ }
+ else
+ {
+ // Zero pad
+ for (int w2 = 0; w2 < W2; ++w2)
+ {
+ int c = 0;
+ while (c < C2)
+ store(h2, w2, c, 0.f);
+ }
+ }
+ });
+ }
+
+ std::shared_ptr<memory> getDst() const override { return dst; }
+
+ private:
+ // Stores a single value
+ __forceinline void store(int h, int w, int& c, float value)
+ {
+ // Destination is in nChwKc format
+ float* dst_c = dstPtr + (H2*W2*K*(c/K)) + h*W2*K + w*K + (c%K);
+ *dst_c = value;
+ c++;
+ }
+
+ // Stores a color
+ __forceinline void storeColor(int h, int w, int& c, const float* values)
+ {
+ #pragma unroll
+ for (int i = 0; i < 3; ++i)
+ {
+ // Load the value
+ float x = values[i];
+
+ // Sanitize the value
+ x = maxSafe(x, 0.f);
+
+ // Apply the transfer function
+ x = transferFunc->forward(x);
+
+ // Store the value
+ store(h, w, c, x);
+ }
+ }
+
+ // Stores an albedo
+ __forceinline void storeAlbedo(int h, int w, int& c, const float* values)
+ {
+ #pragma unroll
+ for (int i = 0; i < 3; ++i)
+ {
+ // Load the value
+ float x = values[i];
+
+ // Sanitize the value
+ x = clampSafe(x, 0.f, 1.f);
+
+ // Store the value
+ store(h, w, c, x);
+ }
+ }
+
+ // Stores a normal
+ __forceinline void storeNormal(int h, int w, int& c, const float* values)
+ {
+ // Load the normal
+ float x = values[0];
+ float y = values[1];
+ float z = values[2];
+
+ // Compute the length of the normal
+ const float lengthSqr = sqr(x) + sqr(y) + sqr(z);
+
+ // Normalize the normal and transform it to [0..1]
+ if (isfinite(lengthSqr))
+ {
+ const float invLength = (lengthSqr > minVectorLengthSqr) ? rsqrt(lengthSqr) : 1.f;
+
+ const float scale = invLength * 0.5f;
+ const float offset = 0.5f;
+
+ x = x * scale + offset;
+ y = y * scale + offset;
+ z = z * scale + offset;
+ }
+ else
+ {
+ x = 0.f;
+ y = 0.f;
+ z = 0.f;
+ }
+
+ // Store the normal
+ store(h, w, c, x);
+ store(h, w, c, y);
+ store(h, w, c, z);
+ }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/math.h b/thirdparty/oidn/core/math.h
new file mode 100644
index 0000000000..a844ef0d1d
--- /dev/null
+++ b/thirdparty/oidn/core/math.h
@@ -0,0 +1,78 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "common/platform.h"
+
+namespace oidn {
+
+ constexpr float minVectorLength = 1e-10f;
+ constexpr float minVectorLengthSqr = minVectorLength * minVectorLength;
+
+ using std::log;
+ using std::log2;
+ using std::exp;
+ using std::exp2;
+ using std::pow;
+ using std::isfinite;
+ using std::isnan;
+
+ __forceinline float sqr(float x)
+ {
+ return x * x;
+ }
+
+ __forceinline float rcp(float x)
+ {
+ __m128 r = _mm_rcp_ss(_mm_set_ss(x));
+ return _mm_cvtss_f32(_mm_sub_ss(_mm_add_ss(r, r), _mm_mul_ss(_mm_mul_ss(r, r), _mm_set_ss(x))));
+ }
+
+ __forceinline float rsqrt(float x)
+ {
+ __m128 r = _mm_rsqrt_ss(_mm_set_ss(x));
+ return _mm_cvtss_f32(_mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r),
+ _mm_mul_ss(_mm_mul_ss(_mm_mul_ss(_mm_set_ss(x), _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r))));
+ }
+
+ __forceinline float maxSafe(float value, float minValue)
+ {
+ return isfinite(value) ? max(value, minValue) : minValue;
+ }
+
+ __forceinline float clampSafe(float value, float minValue, float maxValue)
+ {
+ return isfinite(value) ? clamp(value, minValue, maxValue) : minValue;
+ }
+
+ // Returns ceil(a / b) for non-negative integers
+ template<class Int>
+ __forceinline constexpr Int ceilDiv(Int a, Int b)
+ {
+ //assert(a >= 0);
+ //assert(b > 0);
+ return (a + b - 1) / b;
+ }
+
+ // Returns a rounded up to multiple of b
+ template<class Int>
+ __forceinline constexpr Int roundUp(Int a, Int b)
+ {
+ return ceilDiv(a, b) * b;
+ }
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/network.cpp b/thirdparty/oidn/core/network.cpp
new file mode 100644
index 0000000000..4da32073cd
--- /dev/null
+++ b/thirdparty/oidn/core/network.cpp
@@ -0,0 +1,434 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "network.h"
+#include "upsample.h"
+#include "weights_reorder.h"
+#include <cstring>
+
+namespace oidn {
+
+ template<int K>
+ Network<K>::Network(const Ref<Device>& device, const std::map<std::string, Tensor>& weightMap)
+ : device(device),
+ eng(engine::cpu, 0),
+ sm(eng),
+ weightMap(weightMap)
+ {
+ }
+
+ template<int K>
+ void Network<K>::execute(const Progress& progress, int taskIndex)
+ {
+ if (progress.func)
+ {
+ const double value = double(taskIndex) / double(progress.taskCount);
+ if (!progress.func(progress.userPtr, value))
+ throw Exception(Error::Cancelled, "execution was cancelled");
+ }
+
+ for (size_t i = 0; i < nodes.size(); ++i)
+ {
+ nodes[i]->execute(sm);
+
+ if (progress.func)
+ {
+ const double value = (double(taskIndex) + double(i+1) / double(nodes.size())) / double(progress.taskCount);
+ if (!progress.func(progress.userPtr, value))
+ throw Exception(Error::Cancelled, "execution was cancelled");
+ }
+ }
+ }
+
+ template<int K>
+ std::shared_ptr<memory> Network<K>::allocTensor(const memory::dims& dims,
+ memory::format_tag format,
+ void* data)
+ {
+ if (format == memory::format_tag::any)
+ {
+ if (dims.size() == 4)
+ format = BlockedFormat<K>::nChwKc;
+ else if (dims.size() == 1)
+ format = memory::format_tag::x;
+ else
+ assert(0);
+ }
+ memory::desc desc(dims, memory::data_type::f32, format);
+ if (data == nullptr)
+ {
+ const size_t bytes = getTensorSize(dims) * sizeof(float);
+ if (format == BlockedFormat<K>::nChwKc)
+ activationAllocBytes += bytes;
+ totalAllocBytes += bytes;
+
+ return std::make_shared<memory>(desc, eng);
+ }
+ else
+ {
+ return std::make_shared<memory>(desc, eng, data);
+ }
+ }
+
+ template<int K>
+ std::shared_ptr<memory> Network<K>::castTensor(const memory::dims& dims,
+ const std::shared_ptr<memory>& src,
+ size_t srcOffset,
+ memory::format_tag format)
+ {
+ const mkldnn_memory_desc_t& srcDesc = src->get_desc().data;
+ MAYBE_UNUSED(srcDesc);
+ assert(srcDesc.data_type == memory::data_type::f32);
+ assert(getTensorSize(src) >= srcOffset + getTensorSize(dims));
+
+ if (format == memory::format_tag::any)
+ {
+ if (dims.size() == 4)
+ format = BlockedFormat<K>::nChwKc;
+ else if (dims.size() == 1)
+ format = memory::format_tag::x;
+ else
+ assert(0);
+ }
+ memory::desc desc(dims, memory::data_type::f32, format);
+ float* srcPtr = (float*)src->get_data_handle() + srcOffset;
+ return std::make_shared<memory>(desc, eng, srcPtr);
+ }
+
+ template<int K>
+ std::shared_ptr<memory> Network<K>::castTensor(const memory::dims& dims,
+ const std::shared_ptr<memory>& src,
+ const memory::dims& srcOffset)
+ {
+ return castTensor(dims, src, getTensorSize(srcOffset));
+ }
+
+ template<int K>
+ void Network<K>::zeroTensor(const std::shared_ptr<memory>& dst)
+ {
+ assert(getTensorType(dst) == memory::data_type::f32);
+ memset(dst->get_data_handle(), 0, getTensorSize(dst)*sizeof(float));
+ }
+
+ template<int K>
+ memory::dims Network<K>::getInputReorderDims(const memory::dims& srcDims, int alignment)
+ {
+ memory::dims dstDims = srcDims;
+ dstDims[1] = getPadded<K>(srcDims[1]); // round up C
+ dstDims[2] = roundUp(srcDims[2], memory::dim(alignment)); // round up H
+ dstDims[3] = roundUp(srcDims[3], memory::dim(alignment)); // round up W
+ return dstDims;
+ }
+
+ template<int K>
+ std::shared_ptr<Node> Network<K>::addInputReorder(const Image& color,
+ const Image& albedo,
+ const Image& normal,
+ const std::shared_ptr<TransferFunction>& transferFunc,
+ int alignment,
+ const std::shared_ptr<memory>& userDst)
+ {
+ assert(color);
+ int inputC = 3;
+ if (albedo) inputC += 3;
+ if (normal) inputC += 3;
+
+ memory::dims srcDims = {1, inputC, color.height, color.width};
+ memory::dims dstDims = getInputReorderDims(srcDims, alignment);
+
+ // Allocate padded memory
+ auto dst = userDst;
+ if (!dst)
+ dst = allocTensor(dstDims);
+
+ // Push node
+ std::shared_ptr<Node> node;
+
+ if (auto tf = std::dynamic_pointer_cast<LinearTransferFunction>(transferFunc))
+ node = std::make_shared<InputReorderNode<K, LinearTransferFunction>>(color, albedo, normal, dst, tf);
+ else if (auto tf = std::dynamic_pointer_cast<GammaTransferFunction>(transferFunc))
+ node = std::make_shared<InputReorderNode<K, GammaTransferFunction>>(color, albedo, normal, dst, tf);
+ else if (auto tf = std::dynamic_pointer_cast<LogTransferFunction>(transferFunc))
+ node = std::make_shared<InputReorderNode<K, LogTransferFunction>>(color, albedo, normal, dst, tf);
+ else if (auto tf = std::dynamic_pointer_cast<PQXTransferFunction>(transferFunc))
+ node = std::make_shared<InputReorderNode<K, PQXTransferFunction>>(color, albedo, normal, dst, tf);
+ else
+ assert(0);
+
+ nodes.push_back(node);
+ return node;
+ }
+
+ template<int K>
+ std::shared_ptr<Node> Network<K>::addOutputReorder(const std::shared_ptr<memory>& src,
+ const std::shared_ptr<TransferFunction>& transferFunc,
+ const Image& output)
+ {
+ memory::dims srcDims = getTensorDims(src);
+ assert(srcDims[1] == K);
+
+ // Push node
+ std::shared_ptr<Node> node;
+
+ if (auto tf = std::dynamic_pointer_cast<LinearTransferFunction>(transferFunc))
+ node = std::make_shared<OutputReorderNode<K, LinearTransferFunction>>(src, output, tf);
+ else if (auto tf = std::dynamic_pointer_cast<GammaTransferFunction>(transferFunc))
+ node = std::make_shared<OutputReorderNode<K, GammaTransferFunction>>(src, output, tf);
+ else if (auto tf = std::dynamic_pointer_cast<LogTransferFunction>(transferFunc))
+ node = std::make_shared<OutputReorderNode<K, LogTransferFunction>>(src, output, tf);
+ else if (auto tf = std::dynamic_pointer_cast<PQXTransferFunction>(transferFunc))
+ node = std::make_shared<OutputReorderNode<K, PQXTransferFunction>>(src, output, tf);
+ else
+ assert(0);
+
+ nodes.push_back(node);
+ return node;
+ }
+
+ template<int K>
+ memory::dims Network<K>::getConvDims(const std::string& name, const memory::dims& srcDims)
+ {
+ auto b = weightMap[name + "/b"];
+ memory::dims dstDims = srcDims;
+ dstDims[1] = getPadded<K>(b.dims[0]); // dstDims[C] = getPadded(OC)
+ return dstDims;
+ }
+
+ template<int K>
+ std::shared_ptr<Node> Network<K>::addConv(const std::string& name,
+ const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& userDst,
+ bool relu)
+ {
+ const memory::dims strides = {1, 1};
+ const memory::dims padding = {1, 1};
+
+ memory::dims srcDims = getTensorDims(src);
+
+ // Get the weights
+ const auto& W = weightMap[name + "/W"];
+ if (W.ndims() != 4 || W.format != "oihw")
+ throw Exception(Error::InvalidOperation, "invalid convolution weights");
+ memory::dims weightsDims = W.dims;
+ auto userWeights = allocTensor(weightsDims, memory::format_tag::oihw, W.data);
+
+ // Pad the weights
+ memory::dims weightsPadDims = weightsDims;
+ weightsPadDims[1] = getPadded<K>(weightsDims[1]); // IC
+ weightsPadDims[0] = getPadded<K>(weightsDims[0]); // OC
+ assert(srcDims[1] == weightsPadDims[1]); // srcDims[C] == weightsPadDims[IC]
+ auto weightsPad = allocTensor(weightsPadDims, memory::format_tag::oihw);
+ WeightsReorderNode<K>(userWeights, weightsPad).execute(sm);
+
+ // Get the biases
+ const auto& b = weightMap[name + "/b"];
+ if (b.ndims() != 1)
+ throw Exception(Error::InvalidOperation, "invalid convolution biases");
+ memory::dims biasDims = b.dims;
+
+ // Copy/pad the biases
+ memory::dims biasPadDims = {getPadded<K>(biasDims[0])};
+ auto bias = allocTensor(biasPadDims);
+ if (biasDims[0] != biasPadDims[0])
+ memset(bias->get_data_handle(), 0, biasPadDims[0]*sizeof(float));
+ memcpy(bias->get_data_handle(), b.data, biasDims[0]*sizeof(float));
+
+ // Allocate memory for destination
+ memory::dims dstDims = srcDims;
+ dstDims[1] = weightsPadDims[0]; // dstDims[C] = weightsPadDims[OC]
+
+ std::shared_ptr<memory> dst;
+ if (!userDst)
+ dst = allocTensor(dstDims);
+ else if (getTensorDims(userDst) == dstDims)
+ dst = userDst;
+ else
+ dst = castTensor(dstDims, userDst);
+
+ // Create a convolution
+ // Let the convolution primitive choose the weights format
+ auto weightsDesc = memory::desc({ weightsPadDims }, memory::data_type::f32, memory::format_tag::any);
+
+ auto convAlgo = (K == 16) ? convolution_winograd : convolution_direct;
+ auto convDesc = convolution_forward::desc(
+ prop_kind::forward_inference, convAlgo,
+ src->get_desc(),
+ weightsDesc,
+ bias->get_desc(),
+ dst->get_desc(),
+ strides, padding, padding, padding_kind::zero);
+
+ // Incorporate relu
+ mkldnn::primitive_attr convAttr;
+ if (relu)
+ {
+ mkldnn::post_ops ops;
+ ops.append_eltwise(
+ 1.f, // scale factor, not used
+ algorithm::eltwise_relu,
+ 0.f, // max with
+ 0.f // unused
+ );
+ convAttr.set_post_ops(ops);
+ }
+ convAttr.set_scratchpad_mode(scratchpad_mode_user);
+
+ auto convPrimDesc = convolution_forward::primitive_desc(convDesc, convAttr, eng);
+
+ // Reorder the weights to the final format, if necessary
+ auto weights = weightsPad;
+ if (convPrimDesc.weights_desc() != weightsPad->get_desc())
+ {
+ weights = std::make_shared<memory>(convPrimDesc.weights_desc(), eng);
+ ReorderNode(weightsPad, weights).execute(sm);
+ }
+
+ // Create convolution node and add it to the net
+ auto node = std::make_shared<ConvNode>(convPrimDesc, src, weights, bias, dst);
+ nodes.push_back(node);
+ return node;
+ }
+
+ template<int K>
+ memory::dims Network<K>::getPoolDims(const memory::dims& srcDims)
+ {
+ memory::dims dstDims = srcDims;
+ dstDims[2] /= 2; // H/2
+ dstDims[3] /= 2; // W/2
+ return dstDims;
+ }
+
+ template<int K>
+ std::shared_ptr<Node> Network<K>::addPool(const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& userDst)
+ {
+ const memory::dims kernel = {2, 2};
+ const memory::dims strides = {2, 2};
+ const memory::dims padding = {0, 0};
+
+ memory::dims srcDims = getTensorDims(src);
+ memory::dims dstDims = getPoolDims(srcDims);
+
+ std::shared_ptr<memory> dst;
+ if (!userDst)
+ dst = allocTensor(dstDims);
+ else if (getTensorDims(userDst) == dstDims)
+ dst = userDst;
+ else
+ dst = castTensor(dstDims, userDst);
+
+ auto poolDesc = pooling_forward::desc(
+ prop_kind::forward_inference, pooling_max,
+ src->get_desc(),
+ dst->get_desc(),
+ strides, kernel, padding, padding, padding_kind::zero);
+
+ mkldnn::primitive_attr poolAttr;
+ poolAttr.set_scratchpad_mode(scratchpad_mode_user);
+
+ auto poolPrimDesc = pooling_forward::primitive_desc(poolDesc, poolAttr, eng);
+
+ auto node = std::make_shared<PoolNode>(poolPrimDesc, src, dst);
+ nodes.push_back(node);
+ return node;
+ }
+
+ template<int K>
+ memory::dims Network<K>::getUpsampleDims(const memory::dims& srcDims)
+ {
+ memory::dims dstDims = srcDims;
+ dstDims[2] *= 2; // H*2
+ dstDims[3] *= 2; // W*2
+ return dstDims;
+ }
+
+ template<int K>
+ std::shared_ptr<Node> Network<K>::addUpsample(const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& userDst)
+ {
+ memory::dims srcDims = getTensorDims(src);
+ memory::dims dstDims = getUpsampleDims(srcDims);
+
+ std::shared_ptr<memory> dst;
+ if (!userDst)
+ dst = allocTensor(dstDims);
+ else if (getTensorDims(userDst) == dstDims)
+ dst = userDst;
+ else
+ dst = castTensor(dstDims, userDst);
+
+ // Create upsampling node and add it to net
+ auto node = std::make_shared<UpsampleNode<K>>(src, dst);
+ nodes.push_back(node);
+ return node;
+ }
+
+ template<int K>
+ memory::dims Network<K>::getConcatDims(const memory::dims& src1Dims, const memory::dims& src2Dims)
+ {
+ assert(src1Dims[0] == src2Dims[0]); // N
+ assert(src1Dims[2] == src2Dims[2]); // H
+ assert(src1Dims[3] == src2Dims[3]); // W
+
+ memory::dims dstDims = src1Dims;
+ dstDims[1] += src2Dims[1]; // C
+ return dstDims;
+ }
+
+ template<int K>
+ std::shared_ptr<Node> Network<K>::addAutoexposure(const Image& color,
+ const std::shared_ptr<HDRTransferFunction>& transferFunc)
+ {
+ auto node = std::make_shared<AutoexposureNode>(color, transferFunc);
+ nodes.push_back(node);
+ return node;
+ }
+
+ template <int K>
+ void Network<K>::finalize()
+ {
+ // Compute the size of the scratchpad
+ size_t scratchpadSize = 0;
+ for (const auto& node : nodes)
+ scratchpadSize = max(scratchpadSize, node->getScratchpadSize());
+
+ // Allocate the scratchpad
+ memory::dims scratchpadDims = { memory::dim(scratchpadSize) };
+ memory::desc scratchpadDesc(scratchpadDims, memory::data_type::u8, memory::format_tag::x);
+ auto scratchpad = std::make_shared<memory>(scratchpadDesc, eng);
+ activationAllocBytes += scratchpadSize;
+ totalAllocBytes += scratchpadSize;
+
+ // Set the scratchpad for the nodes
+ for (auto& node : nodes)
+ node->setScratchpad(scratchpad);
+
+ // Free the weights
+ weightMap.clear();
+
+ // Print statistics
+ if (device->isVerbose(2))
+ {
+ std::cout << "Activation bytes: " << activationAllocBytes << std::endl;
+ std::cout << "Scratchpad bytes: " << scratchpadSize << std::endl;
+ std::cout << "Total bytes : " << totalAllocBytes << std::endl;
+ }
+ }
+
+ template class Network<8>;
+ template class Network<16>;
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/network.h b/thirdparty/oidn/core/network.h
new file mode 100644
index 0000000000..7a696fd355
--- /dev/null
+++ b/thirdparty/oidn/core/network.h
@@ -0,0 +1,112 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "common/tensor.h"
+#include "image.h"
+#include "node.h"
+#include "input_reorder.h"
+#include "output_reorder.h"
+#include "transfer_function.h"
+
+#pragma once
+
+namespace oidn {
+
+ // Progress state
+ struct Progress
+ {
+ ProgressMonitorFunction func;
+ void* userPtr;
+ int taskCount;
+ };
+
+ class Executable
+ {
+ public:
+ virtual ~Executable() {}
+ virtual void execute(const Progress& progress, int taskIndex) = 0;
+ };
+
+ template<int K>
+ class Network : public Executable
+ {
+ public:
+ Network(const Ref<Device>& device, const std::map<std::string, Tensor>& weightMap);
+
+ void execute(const Progress& progress, int taskIndex) override;
+
+ std::shared_ptr<memory> allocTensor(const memory::dims& dims,
+ memory::format_tag format = memory::format_tag::any,
+ void* data = nullptr);
+
+ std::shared_ptr<memory> castTensor(const memory::dims& dims,
+ const std::shared_ptr<memory>& src,
+ size_t srcOffset = 0,
+ memory::format_tag format = memory::format_tag::any);
+
+ std::shared_ptr<memory> castTensor(const memory::dims& dims,
+ const std::shared_ptr<memory>& src,
+ const memory::dims& srcOffset);
+
+ void zeroTensor(const std::shared_ptr<memory>& dst);
+
+ memory::dims getInputReorderDims(const memory::dims& srcDims, int alignment);
+
+ std::shared_ptr<Node> addInputReorder(const Image& color,
+ const Image& albedo,
+ const Image& normal,
+ const std::shared_ptr<TransferFunction>& transferFunc,
+ int alignment,
+ const std::shared_ptr<memory>& userDst = nullptr);
+
+ std::shared_ptr<Node> addOutputReorder(const std::shared_ptr<memory>& src,
+ const std::shared_ptr<TransferFunction>& transferFunc,
+ const Image& output);
+
+ memory::dims getConvDims(const std::string& name, const memory::dims& srcDims);
+ std::shared_ptr<Node> addConv(const std::string& name,
+ const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& userDst = nullptr,
+ bool relu = true);
+
+ memory::dims getPoolDims(const memory::dims& srcDims);
+ std::shared_ptr<Node> addPool(const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& userDst = nullptr);
+
+ memory::dims getUpsampleDims(const memory::dims& srcDims);
+ std::shared_ptr<Node> addUpsample(const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& userDst = nullptr);
+
+ memory::dims getConcatDims(const memory::dims& src1Dims, const memory::dims& src2Dims);
+
+ std::shared_ptr<Node> addAutoexposure(const Image& color,
+ const std::shared_ptr<HDRTransferFunction>& transferFunc);
+
+ void finalize();
+
+ private:
+ Ref<Device> device;
+ engine eng;
+ stream sm;
+ std::vector<std::shared_ptr<Node>> nodes;
+ std::map<std::string, Tensor> weightMap;
+
+ // Memory allocation statistics
+ size_t activationAllocBytes = 0; // number of allocated activation bytes
+ size_t totalAllocBytes = 0; // total number of allocated bytes
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/node.h b/thirdparty/oidn/core/node.h
new file mode 100644
index 0000000000..b9ffe906df
--- /dev/null
+++ b/thirdparty/oidn/core/node.h
@@ -0,0 +1,142 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "common.h"
+#include <vector>
+
+namespace oidn {
+
+ class Node
+ {
+ public:
+ virtual ~Node() = default;
+
+ virtual void execute(stream& sm) = 0;
+
+ virtual std::shared_ptr<memory> getDst() const { return nullptr; }
+
+ virtual size_t getScratchpadSize() const { return 0; }
+ virtual void setScratchpad(const std::shared_ptr<memory>& mem) {}
+
+ virtual void setTile(int h1, int w1, int h2, int w2, int H, int W)
+ {
+ assert(0); // not supported
+ }
+ };
+
+ // Node wrapping an MKL-DNN primitive
+ class MklNode : public Node
+ {
+ private:
+ primitive prim;
+ std::unordered_map<int, memory> args;
+ std::shared_ptr<memory> scratchpad;
+
+ public:
+ MklNode(const primitive& prim, const std::unordered_map<int, memory>& args)
+ : prim(prim),
+ args(args)
+ {}
+
+ size_t getScratchpadSize() const override
+ {
+ const auto primDesc = prim.get_primitive_desc();
+ const mkldnn_memory_desc_t* scratchpadDesc = mkldnn_primitive_desc_query_md(primDesc, mkldnn_query_scratchpad_md, 0);
+ if (scratchpadDesc == nullptr)
+ return 0;
+ return mkldnn_memory_desc_get_size(scratchpadDesc);
+ }
+
+ void setScratchpad(const std::shared_ptr<memory>& mem) override
+ {
+ scratchpad = mem;
+ args.insert(std::make_pair(MKLDNN_ARG_SCRATCHPAD, *scratchpad));
+ }
+
+ void execute(stream& sm) override
+ {
+ prim.execute(sm, args);
+ }
+ };
+
+ // Convolution node
+ class ConvNode : public MklNode
+ {
+ private:
+ std::shared_ptr<memory> src;
+ std::shared_ptr<memory> weights;
+ std::shared_ptr<memory> bias;
+ std::shared_ptr<memory> dst;
+
+ public:
+ ConvNode(const convolution_forward::primitive_desc& desc,
+ const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& weights,
+ const std::shared_ptr<memory>& bias,
+ const std::shared_ptr<memory>& dst)
+ : MklNode(convolution_forward(desc),
+ { { MKLDNN_ARG_SRC, *src },
+ { MKLDNN_ARG_WEIGHTS, *weights },
+ { MKLDNN_ARG_BIAS, *bias },
+ { MKLDNN_ARG_DST, *dst } }),
+ src(src), weights(weights), bias(bias), dst(dst)
+ {}
+
+ std::shared_ptr<memory> getDst() const override { return dst; }
+ };
+
+ // Pooling node
+ class PoolNode : public MklNode
+ {
+ private:
+ std::shared_ptr<memory> src;
+ std::shared_ptr<memory> dst;
+
+ public:
+ PoolNode(const pooling_forward::primitive_desc& desc,
+ const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& dst)
+ : MklNode(pooling_forward(desc),
+ { { MKLDNN_ARG_SRC, *src },
+ { MKLDNN_ARG_DST, *dst } }),
+ src(src), dst(dst)
+ {}
+
+ std::shared_ptr<memory> getDst() const override { return dst; }
+ };
+
+ // Reorder node
+ class ReorderNode : public MklNode
+ {
+ private:
+ std::shared_ptr<memory> src;
+ std::shared_ptr<memory> dst;
+
+ public:
+ ReorderNode(const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& dst)
+ : MklNode(reorder(reorder::primitive_desc(*src, *dst)),
+ { { MKLDNN_ARG_SRC, *src },
+ { MKLDNN_ARG_DST, *dst } }),
+ src(src), dst(dst)
+ {}
+
+ std::shared_ptr<memory> getDst() const override { return dst; }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/output_reorder.h b/thirdparty/oidn/core/output_reorder.h
new file mode 100644
index 0000000000..7918d48e15
--- /dev/null
+++ b/thirdparty/oidn/core/output_reorder.h
@@ -0,0 +1,126 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "node.h"
+#include "image.h"
+
+namespace oidn {
+
+ // Output reorder node
+ template<int K, class TransferFunction>
+ class OutputReorderNode : public Node
+ {
+ private:
+ // Source
+ std::shared_ptr<memory> src;
+ const float* srcPtr;
+ int H1;
+ int W1;
+
+ // Destination
+ Image output;
+
+ // Tile
+ int h1Begin;
+ int w1Begin;
+ int h2Begin;
+ int w2Begin;
+ int H;
+ int W;
+
+ std::shared_ptr<TransferFunction> transferFunc;
+
+ public:
+ OutputReorderNode(const std::shared_ptr<memory>& src,
+ const Image& output,
+ const std::shared_ptr<TransferFunction>& transferFunc)
+ : src(src),
+ output(output),
+ h1Begin(0), w1Begin(0),
+ h2Begin(0), w2Begin(0),
+ H(output.height), W(output.width),
+ transferFunc(transferFunc)
+ {
+ const mkldnn_memory_desc_t& srcDesc = src->get_desc().data;
+ MAYBE_UNUSED(srcDesc);
+ assert(memory_desc_matches_tag(srcDesc, mkldnn_format_tag_t(BlockedFormat<K>::nChwKc)));
+ assert(srcDesc.ndims == 4);
+ assert(srcDesc.data_type == memory::data_type::f32);
+ assert(srcDesc.dims[0] == 1);
+ // We assume output data is <= K OC
+ assert(srcDesc.dims[1] == K);
+
+ srcPtr = (float*)src->get_data_handle();
+ H1 = srcDesc.dims[2];
+ W1 = srcDesc.dims[3];
+ }
+
+ void setTile(int h1, int w1, int h2, int w2, int H, int W) override
+ {
+ h1Begin = h1;
+ w1Begin = w1;
+ h2Begin = h2;
+ w2Begin = w2;
+ this->H = H;
+ this->W = W;
+ }
+
+ void execute(stream& sm) override
+ {
+ assert(h1Begin + H <= H1);
+ assert(w1Begin + W <= W1);
+ assert(h2Begin + H <= output.height);
+ assert(w2Begin + W <= output.width);
+
+ const int C1 = K;
+
+ parallel_nd(H, [&](int h)
+ {
+ const int h1 = h + h1Begin;
+ const int h2 = h + h2Begin;
+
+ for (int w = 0; w < W; ++w)
+ {
+ const int w1 = w + w1Begin;
+ const int w2 = w + w2Begin;
+ float* dstPtr_C = (float*)output.get(h2, w2);
+
+ // Source is in nChwKc format. In this case C is 1 so this is really nhwc
+ const float* srcPtr_C = srcPtr + h1*W1*C1 + w1*C1;
+
+ #pragma unroll
+ for (int i = 0; i < 3; ++i)
+ {
+ // Load the value
+ float x = srcPtr_C[i];
+
+ // The CNN output may contain negative values or even NaNs, so it must be sanitized
+ x = maxSafe(x, 0.f);
+
+ // Apply the inverse transfer function
+ x = transferFunc->inverse(x);
+
+ // Sanitize and store the final value
+ dstPtr_C[i] = max(x, 0.f);
+ }
+ }
+ });
+ }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/transfer_function.cpp b/thirdparty/oidn/core/transfer_function.cpp
new file mode 100644
index 0000000000..a33e3c84bc
--- /dev/null
+++ b/thirdparty/oidn/core/transfer_function.cpp
@@ -0,0 +1,95 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#include "transfer_function.h"
+
+namespace oidn {
+
+ const float LogTransferFunction::xScale = 1.f / log(LogTransferFunction::yMax + 1.f);
+ const float PQXTransferFunction::xScale = 1.f / PQXTransferFunction::pqxForward(PQXTransferFunction::yMax * PQXTransferFunction::yScale);
+
+ float AutoexposureNode::autoexposure(const Image& color)
+ {
+ assert(color.format == Format::Float3);
+ return 1.0f;
+
+ /*constexpr float key = 0.18f;
+ constexpr float eps = 1e-8f;
+ constexpr int K = 16; // downsampling amount
+
+ // Downsample the image to minimize sensitivity to noise
+ const int H = color.height; // original height
+ const int W = color.width; // original width
+ const int HK = (H + K/2) / K; // downsampled height
+ const int WK = (W + K/2) / K; // downsampled width
+
+ // Compute the average log luminance of the downsampled image
+ using Sum = std::pair<float, int>;
+
+ Sum sum =
+ tbb::parallel_reduce(
+ tbb::blocked_range2d<int>(0, HK, 0, WK),
+ Sum(0.f, 0),
+ [&](const tbb::blocked_range2d<int>& r, Sum sum) -> Sum
+ {
+ // Iterate over blocks
+ for (int i = r.rows().begin(); i != r.rows().end(); ++i)
+ {
+ for (int j = r.cols().begin(); j != r.cols().end(); ++j)
+ {
+ // Compute the average luminance in the current block
+ const int beginH = int(ptrdiff_t(i) * H / HK);
+ const int beginW = int(ptrdiff_t(j) * W / WK);
+ const int endH = int(ptrdiff_t(i+1) * H / HK);
+ const int endW = int(ptrdiff_t(j+1) * W / WK);
+
+ float L = 0.f;
+
+ for (int h = beginH; h < endH; ++h)
+ {
+ for (int w = beginW; w < endW; ++w)
+ {
+ const float* rgb = (const float*)color.get(h, w);
+
+ const float r = maxSafe(rgb[0], 0.f);
+ const float g = maxSafe(rgb[1], 0.f);
+ const float b = maxSafe(rgb[2], 0.f);
+
+ L += luminance(r, g, b);
+ }
+ }
+
+ L /= (endH - beginH) * (endW - beginW);
+
+ // Accumulate the log luminance
+ if (L > eps)
+ {
+ sum.first += log2(L);
+ sum.second++;
+ }
+ }
+ }
+
+ return sum;
+ },
+ [](Sum a, Sum b) -> Sum { return Sum(a.first+b.first, a.second+b.second); },
+ tbb::static_partitioner()
+ );
+
+ return (sum.second > 0) ? (key / exp2(sum.first / float(sum.second))) : 1.f;*/
+ }
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/transfer_function.h b/thirdparty/oidn/core/transfer_function.h
new file mode 100644
index 0000000000..35f2833092
--- /dev/null
+++ b/thirdparty/oidn/core/transfer_function.h
@@ -0,0 +1,201 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "image.h"
+#include "node.h"
+
+namespace oidn {
+
+ __forceinline float luminance(float r, float g, float b)
+ {
+ return 0.212671f * r + 0.715160f * g + 0.072169f * b;
+ }
+
+ // Color transfer function base class
+ class TransferFunction
+ {
+ public:
+ virtual ~TransferFunction() = default;
+
+ virtual float forward(float y) const = 0;
+ virtual float inverse(float x) const = 0;
+ };
+
+ // HDR transfer function base class
+ class HDRTransferFunction : public TransferFunction
+ {
+ protected:
+ static constexpr float yMax = 65504.f;
+
+ float exposure;
+ float rcpExposure;
+
+ public:
+ HDRTransferFunction(float exposure = 1.f)
+ {
+ setExposure(exposure);
+ }
+
+ void setExposure(float exposure)
+ {
+ this->exposure = exposure;
+ this->rcpExposure = (exposure != 0.f) ? (1.f / exposure) : 0.f;
+ }
+ };
+
+ // Linear transfer function (LDR)
+ class LinearTransferFunction : public TransferFunction
+ {
+ public:
+ __forceinline float forward(float y) const override
+ {
+ return min(y, 1.f);
+ }
+
+ __forceinline float inverse(float x) const override
+ {
+ return min(x, 1.f);
+ }
+ };
+
+ // 2.2 gamma transfer function (LDR)
+ class GammaTransferFunction : public TransferFunction
+ {
+ public:
+ __forceinline float forward(float y) const override
+ {
+ return min(pow(y, 1.f/2.2f), 1.f);
+ }
+
+ __forceinline float inverse(float x) const override
+ {
+ return min(pow(x, 2.2f), 1.f);
+ }
+ };
+
+ // Logarithmic transfer function (HDR)
+ // Compresses [0..65504] to [0..1]
+ class LogTransferFunction : public HDRTransferFunction
+ {
+ private:
+ static const float xScale;
+
+ public:
+ LogTransferFunction(float exposure = 1.f)
+ : HDRTransferFunction(exposure)
+ {
+ }
+
+ __forceinline float forward(float y) const override
+ {
+ return log(y * exposure + 1.f) * xScale;
+ }
+
+ __forceinline float inverse(float x) const override
+ {
+ return (exp(x * (1.f/xScale)) - 1.f) * rcpExposure;
+ }
+ };
+
+ // PQX transfer function (HDR)
+ // Compresses [0..65504] to [0..1]
+ class PQXTransferFunction : public HDRTransferFunction
+ {
+ private:
+ static constexpr float m1 = 2610.f / 4096.f / 4.f;
+ static constexpr float m2 = 2523.f / 4096.f * 128.f;
+ static constexpr float c1 = 3424.f / 4096.f;
+ static constexpr float c2 = 2413.f / 4096.f * 32.f;
+ static constexpr float c3 = 2392.f / 4096.f * 32.f;
+ static constexpr float a = 3711.f / 4096.f / 8.f;
+
+ static constexpr float yScale = 100.f / 10000.f;
+ static const float xScale;
+
+ public:
+ PQXTransferFunction(float exposure = 1.f)
+ : HDRTransferFunction(exposure)
+ {
+ }
+
+ __forceinline float forward(float y) const override
+ {
+ return pqxForward(y * exposure * yScale) * xScale;
+ }
+
+ __forceinline float inverse(float x) const override
+ {
+ return pqxInverse(x * (1.f/xScale)) * (1.f/yScale) * rcpExposure;
+ }
+
+ private:
+ static __forceinline float pqForward(float y)
+ {
+ const float yp = pow(y, m1);
+ return pow((c1 + c2 * yp) * rcp(1.f + c3 * yp), m2);
+ }
+
+ static __forceinline float pqxForward(float y)
+ {
+ if (y <= 1.f)
+ return pqForward(y);
+ else
+ return a * log(y) + 1.f;
+ }
+
+ static __forceinline float pqInverse(float x)
+ {
+ const float xp = pow(x, 1.f/m2);
+ return pow(max((xp - c1) * rcp(c2 - c3 * xp), 0.f), 1.f/m1);
+ }
+
+ static __forceinline float pqxInverse(float x)
+ {
+ if (x <= 1.f)
+ return pqInverse(x);
+ else
+ return exp((x - 1.f) * (1.f/a));
+ }
+ };
+
+ // Autoexposure node
+ class AutoexposureNode : public Node
+ {
+ private:
+ Image color;
+ std::shared_ptr<HDRTransferFunction> transferFunc;
+
+ public:
+ AutoexposureNode(const Image& color,
+ const std::shared_ptr<HDRTransferFunction>& transferFunc)
+ : color(color),
+ transferFunc(transferFunc)
+ {}
+
+ void execute(stream& sm) override
+ {
+ const float exposure = autoexposure(color);
+ //printf("exposure = %f\n", exposure);
+ transferFunc->setExposure(exposure);
+ }
+
+ private:
+ static float autoexposure(const Image& color);
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/upsample.h b/thirdparty/oidn/core/upsample.h
new file mode 100644
index 0000000000..f6cace44cd
--- /dev/null
+++ b/thirdparty/oidn/core/upsample.h
@@ -0,0 +1,92 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "node.h"
+
+namespace oidn {
+
+ // 2x2 nearest-neighbor upsampling node
+ template<int K>
+ class UpsampleNode : public Node
+ {
+ private:
+ std::shared_ptr<memory> src;
+ std::shared_ptr<memory> dst;
+
+ public:
+ UpsampleNode(const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& dst)
+ : src(src),
+ dst(dst)
+ {
+ const mkldnn_memory_desc_t& srcDesc = src->get_desc().data;
+ const mkldnn_memory_desc_t& dstDesc = dst->get_desc().data;
+ MAYBE_UNUSED(srcDesc);
+ MAYBE_UNUSED(dstDesc);
+ assert(memory_desc_matches_tag(srcDesc, mkldnn_format_tag_t(BlockedFormat<K>::nChwKc)));
+ assert(memory_desc_matches_tag(dstDesc, mkldnn_format_tag_t(BlockedFormat<K>::nChwKc)));
+ assert(srcDesc.ndims == 4);
+ assert(dstDesc.ndims == 4);
+ assert(srcDesc.data_type == memory::data_type::f32);
+ assert(dstDesc.data_type == memory::data_type::f32);
+ assert(srcDesc.dims[0] == 1);
+ assert(dstDesc.dims[0] == 1);
+ // 2x2 upsampling
+ assert(dstDesc.dims[2] == srcDesc.dims[2] * 2);
+ assert(dstDesc.dims[3] == srcDesc.dims[3] * 2);
+ }
+
+ void execute(stream& sm) override
+ {
+ const mkldnn_memory_desc_t& srcDesc = src->get_desc().data;
+
+ const float* srcPtr = (float*)src->get_data_handle();
+ float* dstPtr = (float*)dst->get_data_handle();
+
+ const int C = srcDesc.dims[1];
+ const int H = srcDesc.dims[2];
+ const int W = srcDesc.dims[3];
+ const int CK = C / K;
+
+ parallel_nd(CK, H, [&](int ck, int h)
+ {
+ const size_t offset = ck*H*W*K + h*W*K;
+ const float* srcPtr_line = srcPtr + offset;
+ float* dstPtr_line0 = dstPtr + offset * 4;
+ float* dstPtr_line1 = dstPtr_line0 + W*2*K; // next line
+
+ for (int w = 0; w < W; ++w)
+ {
+ #pragma unroll
+ for (int k = 0; k < K; k += 4)
+ {
+ const __m128 m = _mm_load_ps(&srcPtr_line[w*K + k]);
+
+ _mm_stream_ps(&dstPtr_line0[w*2*K + k], m);
+ _mm_stream_ps(&dstPtr_line0[w*2*K+K + k], m);
+ _mm_stream_ps(&dstPtr_line1[w*2*K + k], m);
+ _mm_stream_ps(&dstPtr_line1[w*2*K+K + k], m);
+ }
+ }
+ });
+ }
+
+ std::shared_ptr<memory> getDst() const override { return dst; }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/core/weights_reorder.h b/thirdparty/oidn/core/weights_reorder.h
new file mode 100644
index 0000000000..6c5dacb8aa
--- /dev/null
+++ b/thirdparty/oidn/core/weights_reorder.h
@@ -0,0 +1,99 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include "node.h"
+
+namespace oidn {
+
+ // Reorders weights from oihw to padded oihw format
+ template<int K>
+ class WeightsReorderNode : public Node
+ {
+ private:
+ std::shared_ptr<memory> src;
+ std::shared_ptr<memory> dst;
+
+ public:
+ WeightsReorderNode(const std::shared_ptr<memory>& src,
+ const std::shared_ptr<memory>& dst)
+ : src(src),
+ dst(dst)
+ {
+ const mkldnn_memory_desc_t& srcDesc = src->get_desc().data;
+ const mkldnn_memory_desc_t& dstDesc = dst->get_desc().data;
+ MAYBE_UNUSED(srcDesc);
+ MAYBE_UNUSED(dstDesc);
+ assert(memory_desc_matches_tag(srcDesc, mkldnn_format_tag_t(memory::format_tag::oihw)));
+ assert(memory_desc_matches_tag(dstDesc, mkldnn_format_tag_t(memory::format_tag::oihw)));
+ assert(srcDesc.ndims == 4);
+ assert(dstDesc.ndims == 4);
+ assert(srcDesc.data_type == memory::data_type::f32);
+ assert(dstDesc.data_type == memory::data_type::f32);
+ assert(getPadded<K>(srcDesc.dims[0]) == dstDesc.dims[0]); // OC
+ assert(getPadded<K>(srcDesc.dims[1]) == dstDesc.dims[1]); // IC
+ assert(srcDesc.dims[2] == dstDesc.dims[2]);
+ assert(srcDesc.dims[3] == dstDesc.dims[3]);
+ }
+
+ void execute(stream& sm) override
+ {
+ const mkldnn_memory_desc_t& srcDesc = src->get_desc().data;
+ const mkldnn_memory_desc_t& dstDesc = dst->get_desc().data;
+
+ const float* srcPtr = (float*)src->get_data_handle();
+ float* dstPtr = (float*)dst->get_data_handle();
+
+ const int OC1 = srcDesc.dims[0];
+ const int OC2 = dstDesc.dims[0];
+ const int IC1 = srcDesc.dims[1];
+ const int IC2 = dstDesc.dims[1];
+ const int H = dstDesc.dims[2];
+ const int W = dstDesc.dims[3];
+
+ for (int oc = 0; oc < OC2; ++oc)
+ {
+ for (int ic = 0; ic < IC2; ++ic)
+ {
+ for (int h = 0; h < H; ++h)
+ {
+ for (int w = 0; w < W; ++w)
+ {
+ // Output is in oihw format
+ float* dstPtr_c = dstPtr + oc*IC2*H*W + ic*H*W + h*W + w;
+
+ if (oc < OC1 && ic < IC1)
+ {
+ // Input is in oihw format
+ const float* srcPtr_c = srcPtr + oc*IC1*H*W + ic*H*W + h*W + w;
+ *dstPtr_c = *srcPtr_c;
+ }
+ else
+ {
+ // padding
+ *dstPtr_c = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ std::shared_ptr<memory> getDst() const override { return dst; }
+ };
+
+} // namespace oidn
diff --git a/thirdparty/oidn/include/OpenImageDenoise/oidn.h b/thirdparty/oidn/include/OpenImageDenoise/oidn.h
new file mode 100644
index 0000000000..57ba6baa21
--- /dev/null
+++ b/thirdparty/oidn/include/OpenImageDenoise/oidn.h
@@ -0,0 +1,214 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "version.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef OIDN_API
+#if defined(_WIN32) && !defined(OIDN_STATIC_LIB)
+# define OIDN_API __declspec(dllimport)
+#else
+# define OIDN_API
+#endif
+#endif
+
+// ----------------------------------------------------------------------------
+// Device
+// ----------------------------------------------------------------------------
+
+// Device types
+typedef enum
+{
+ OIDN_DEVICE_TYPE_DEFAULT = 0, // select device automatically
+
+ OIDN_DEVICE_TYPE_CPU = 1, // CPU device
+} OIDNDeviceType;
+
+// Error codes
+typedef enum
+{
+ OIDN_ERROR_NONE = 0, // no error occurred
+ OIDN_ERROR_UNKNOWN = 1, // an unknown error occurred
+ OIDN_ERROR_INVALID_ARGUMENT = 2, // an invalid argument was specified
+ OIDN_ERROR_INVALID_OPERATION = 3, // the operation is not allowed
+ OIDN_ERROR_OUT_OF_MEMORY = 4, // not enough memory to execute the operation
+ OIDN_ERROR_UNSUPPORTED_HARDWARE = 5, // the hardware (e.g. CPU) is not supported
+ OIDN_ERROR_CANCELLED = 6, // the operation was cancelled by the user
+} OIDNError;
+
+// Error callback function
+typedef void (*OIDNErrorFunction)(void* userPtr, OIDNError code, const char* message);
+
+// Device handle
+typedef struct OIDNDeviceImpl* OIDNDevice;
+
+// Creates a new device.
+OIDN_API OIDNDevice oidnNewDevice(OIDNDeviceType type);
+
+// Retains the device (increments the reference count).
+OIDN_API void oidnRetainDevice(OIDNDevice device);
+
+// Releases the device (decrements the reference count).
+OIDN_API void oidnReleaseDevice(OIDNDevice device);
+
+// Sets a boolean parameter of the device.
+OIDN_API void oidnSetDevice1b(OIDNDevice device, const char* name, bool value);
+
+// Sets an integer parameter of the device.
+OIDN_API void oidnSetDevice1i(OIDNDevice device, const char* name, int value);
+
+// Gets a boolean parameter of the device.
+OIDN_API bool oidnGetDevice1b(OIDNDevice device, const char* name);
+
+// Gets an integer parameter of the device (e.g. "version").
+OIDN_API int oidnGetDevice1i(OIDNDevice device, const char* name);
+
+// Sets the error callback function of the device.
+OIDN_API void oidnSetDeviceErrorFunction(OIDNDevice device, OIDNErrorFunction func, void* userPtr);
+
+// Returns the first unqueried error code stored in the device for the current
+// thread, optionally also returning a string message (if not NULL), and clears
+// the stored error. Can be called with a NULL device as well to check why a
+// device creation failed.
+OIDN_API OIDNError oidnGetDeviceError(OIDNDevice device, const char** outMessage);
+
+// Commits all previous changes to the device.
+// Must be called before first using the device (e.g. creating filters).
+OIDN_API void oidnCommitDevice(OIDNDevice device);
+
+// ----------------------------------------------------------------------------
+// Buffer
+// ----------------------------------------------------------------------------
+
+// Formats for images and other data stored in buffers
+typedef enum
+{
+ OIDN_FORMAT_UNDEFINED = 0,
+
+ // 32-bit single-precision floating point scalar and vector formats
+ OIDN_FORMAT_FLOAT = 1,
+ OIDN_FORMAT_FLOAT2 = 2,
+ OIDN_FORMAT_FLOAT3 = 3,
+ OIDN_FORMAT_FLOAT4 = 4,
+} OIDNFormat;
+
+// Access modes for mapping buffers
+typedef enum
+{
+ OIDN_ACCESS_READ = 0, // read-only access
+ OIDN_ACCESS_WRITE = 1, // write-only access
+ OIDN_ACCESS_READ_WRITE = 2, // read and write access
+ OIDN_ACCESS_WRITE_DISCARD = 3, // write-only access, previous contents discarded
+} OIDNAccess;
+
+// Buffer handle
+typedef struct OIDNBufferImpl* OIDNBuffer;
+
+// Creates a new buffer (data allocated and owned by the device).
+OIDN_API OIDNBuffer oidnNewBuffer(OIDNDevice device, size_t byteSize);
+
+// Creates a new shared buffer (data allocated and owned by the user).
+OIDN_API OIDNBuffer oidnNewSharedBuffer(OIDNDevice device, void* ptr, size_t byteSize);
+
+// Maps a region of the buffer to host memory.
+// If byteSize is 0, the maximum available amount of memory will be mapped.
+OIDN_API void* oidnMapBuffer(OIDNBuffer buffer, OIDNAccess access, size_t byteOffset, size_t byteSize);
+
+// Unmaps a region of the buffer.
+// mappedPtr must be a pointer returned by a previous call to oidnMapBuffer.
+OIDN_API void oidnUnmapBuffer(OIDNBuffer buffer, void* mappedPtr);
+
+// Retains the buffer (increments the reference count).
+OIDN_API void oidnRetainBuffer(OIDNBuffer buffer);
+
+// Releases the buffer (decrements the reference count).
+OIDN_API void oidnReleaseBuffer(OIDNBuffer buffer);
+
+// ----------------------------------------------------------------------------
+// Filter
+// ----------------------------------------------------------------------------
+
+// Progress monitor callback function
+typedef bool (*OIDNProgressMonitorFunction)(void* userPtr, double n);
+
+// Filter handle
+typedef struct OIDNFilterImpl* OIDNFilter;
+
+// Creates a new filter of the specified type (e.g. "RT").
+OIDN_API OIDNFilter oidnNewFilter(OIDNDevice device, const char* type);
+
+// Retains the filter (increments the reference count).
+OIDN_API void oidnRetainFilter(OIDNFilter filter);
+
+// Releases the filter (decrements the reference count).
+OIDN_API void oidnReleaseFilter(OIDNFilter filter);
+
+// Sets an image parameter of the filter (stored in a buffer).
+// If bytePixelStride and/or byteRowStride are zero, these will be computed automatically.
+OIDN_API void oidnSetFilterImage(OIDNFilter filter, const char* name,
+ OIDNBuffer buffer, OIDNFormat format,
+ size_t width, size_t height,
+ size_t byteOffset,
+ size_t bytePixelStride, size_t byteRowStride);
+
+// Sets an image parameter of the filter (owned by the user).
+// If bytePixelStride and/or byteRowStride are zero, these will be computed automatically.
+OIDN_API void oidnSetSharedFilterImage(OIDNFilter filter, const char* name,
+ void* ptr, OIDNFormat format,
+ size_t width, size_t height,
+ size_t byteOffset,
+ size_t bytePixelStride, size_t byteRowStride);
+
+// Sets a boolean parameter of the filter.
+OIDN_API void oidnSetFilter1b(OIDNFilter filter, const char* name, bool value);
+
+// Gets a boolean parameter of the filter.
+OIDN_API bool oidnGetFilter1b(OIDNFilter filter, const char* name);
+
+// Sets an integer parameter of the filter.
+OIDN_API void oidnSetFilter1i(OIDNFilter filter, const char* name, int value);
+
+// Gets an integer parameter of the filter.
+OIDN_API int oidnGetFilter1i(OIDNFilter filter, const char* name);
+
+// Sets a float parameter of the filter.
+OIDN_API void oidnSetFilter1f(OIDNFilter filter, const char* name, float value);
+
+// Gets a float parameter of the filter.
+OIDN_API float oidnGetFilter1f(OIDNFilter filter, const char* name);
+
+// Sets the progress monitor callback function of the filter.
+OIDN_API void oidnSetFilterProgressMonitorFunction(OIDNFilter filter, OIDNProgressMonitorFunction func, void* userPtr);
+
+// Commits all previous changes to the filter.
+// Must be called before first executing the filter.
+OIDN_API void oidnCommitFilter(OIDNFilter filter);
+
+// Executes the filter.
+OIDN_API void oidnExecuteFilter(OIDNFilter filter);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/thirdparty/oidn/include/OpenImageDenoise/oidn.hpp b/thirdparty/oidn/include/OpenImageDenoise/oidn.hpp
new file mode 100644
index 0000000000..9f95a56fe1
--- /dev/null
+++ b/thirdparty/oidn/include/OpenImageDenoise/oidn.hpp
@@ -0,0 +1,468 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#include <algorithm>
+#include "oidn.h"
+
+namespace oidn {
+
+ // --------------------------------------------------------------------------
+ // Buffer
+ // --------------------------------------------------------------------------
+
+ // Formats for images and other data stored in buffers
+ enum class Format
+ {
+ Undefined = OIDN_FORMAT_UNDEFINED,
+
+ // 32-bit single-precision floating point scalar and vector formats
+ Float = OIDN_FORMAT_FLOAT,
+ Float2 = OIDN_FORMAT_FLOAT2,
+ Float3 = OIDN_FORMAT_FLOAT3,
+ Float4 = OIDN_FORMAT_FLOAT4,
+ };
+
+ // Access modes for mapping buffers
+ enum class Access
+ {
+ Read = OIDN_ACCESS_READ, // read-only access
+ Write = OIDN_ACCESS_WRITE, // write-only access
+ ReadWrite = OIDN_ACCESS_READ_WRITE, // read and write access
+ WriteDiscard = OIDN_ACCESS_WRITE_DISCARD, // write-only access, previous contents discarded
+ };
+
+ // Buffer object with automatic reference counting
+ class BufferRef
+ {
+ private:
+ OIDNBuffer handle;
+
+ public:
+ BufferRef() : handle(nullptr) {}
+ BufferRef(OIDNBuffer handle) : handle(handle) {}
+
+ BufferRef(const BufferRef& other) : handle(other.handle)
+ {
+ if (handle)
+ oidnRetainBuffer(handle);
+ }
+
+ BufferRef(BufferRef&& other) : handle(other.handle)
+ {
+ other.handle = nullptr;
+ }
+
+ BufferRef& operator =(const BufferRef& other)
+ {
+ if (&other != this)
+ {
+ if (other.handle)
+ oidnRetainBuffer(other.handle);
+ if (handle)
+ oidnReleaseBuffer(handle);
+ handle = other.handle;
+ }
+ return *this;
+ }
+
+ BufferRef& operator =(BufferRef&& other)
+ {
+ std::swap(handle, other.handle);
+ return *this;
+ }
+
+ BufferRef& operator =(OIDNBuffer other)
+ {
+ if (other)
+ oidnRetainBuffer(other);
+ if (handle)
+ oidnReleaseBuffer(handle);
+ handle = other;
+ return *this;
+ }
+
+ ~BufferRef()
+ {
+ if (handle)
+ oidnReleaseBuffer(handle);
+ }
+
+ OIDNBuffer getHandle() const
+ {
+ return handle;
+ }
+
+ operator bool() const
+ {
+ return handle != nullptr;
+ }
+
+ // Maps a region of the buffer to host memory.
+ // If byteSize is 0, the maximum available amount of memory will be mapped.
+ void* map(Access access = Access::ReadWrite, size_t byteOffset = 0, size_t byteSize = 0)
+ {
+ return oidnMapBuffer(handle, (OIDNAccess)access, byteOffset, byteSize);
+ }
+
+ // Unmaps a region of the buffer.
+ // mappedPtr must be a pointer returned by a previous call to map.
+ void unmap(void* mappedPtr)
+ {
+ oidnUnmapBuffer(handle, mappedPtr);
+ }
+ };
+
+ // --------------------------------------------------------------------------
+ // Filter
+ // --------------------------------------------------------------------------
+
+ // Progress monitor callback function
+ typedef bool (*ProgressMonitorFunction)(void* userPtr, double n);
+
+ // Filter object with automatic reference counting
+ class FilterRef
+ {
+ private:
+ OIDNFilter handle;
+
+ public:
+ FilterRef() : handle(nullptr) {}
+ FilterRef(OIDNFilter handle) : handle(handle) {}
+
+ FilterRef(const FilterRef& other) : handle(other.handle)
+ {
+ if (handle)
+ oidnRetainFilter(handle);
+ }
+
+ FilterRef(FilterRef&& other) : handle(other.handle)
+ {
+ other.handle = nullptr;
+ }
+
+ FilterRef& operator =(const FilterRef& other)
+ {
+ if (&other != this)
+ {
+ if (other.handle)
+ oidnRetainFilter(other.handle);
+ if (handle)
+ oidnReleaseFilter(handle);
+ handle = other.handle;
+ }
+ return *this;
+ }
+
+ FilterRef& operator =(FilterRef&& other)
+ {
+ std::swap(handle, other.handle);
+ return *this;
+ }
+
+ FilterRef& operator =(OIDNFilter other)
+ {
+ if (other)
+ oidnRetainFilter(other);
+ if (handle)
+ oidnReleaseFilter(handle);
+ handle = other;
+ return *this;
+ }
+
+ ~FilterRef()
+ {
+ if (handle)
+ oidnReleaseFilter(handle);
+ }
+
+ OIDNFilter getHandle() const
+ {
+ return handle;
+ }
+
+ operator bool() const
+ {
+ return handle != nullptr;
+ }
+
+ // Sets an image parameter of the filter (stored in a buffer).
+ void setImage(const char* name,
+ const BufferRef& buffer, Format format,
+ size_t width, size_t height,
+ size_t byteOffset = 0,
+ size_t bytePixelStride = 0, size_t byteRowStride = 0)
+ {
+ oidnSetFilterImage(handle, name,
+ buffer.getHandle(), (OIDNFormat)format,
+ width, height,
+ byteOffset,
+ bytePixelStride, byteRowStride);
+ }
+
+ // Sets an image parameter of the filter (owned by the user).
+ void setImage(const char* name,
+ void* ptr, Format format,
+ size_t width, size_t height,
+ size_t byteOffset = 0,
+ size_t bytePixelStride = 0, size_t byteRowStride = 0)
+ {
+ oidnSetSharedFilterImage(handle, name,
+ ptr, (OIDNFormat)format,
+ width, height,
+ byteOffset,
+ bytePixelStride, byteRowStride);
+ }
+
+ // Sets a boolean parameter of the filter.
+ void set(const char* name, bool value)
+ {
+ oidnSetFilter1b(handle, name, value);
+ }
+
+ // Sets an integer parameter of the filter.
+ void set(const char* name, int value)
+ {
+ oidnSetFilter1i(handle, name, value);
+ }
+
+ // Sets a float parameter of the filter.
+ void set(const char* name, float value)
+ {
+ oidnSetFilter1f(handle, name, value);
+ }
+
+ // Gets a parameter of the filter.
+ template<typename T>
+ T get(const char* name);
+
+ // Sets the progress monitor callback function of the filter.
+ void setProgressMonitorFunction(ProgressMonitorFunction func, void* userPtr = nullptr)
+ {
+ oidnSetFilterProgressMonitorFunction(handle, (OIDNProgressMonitorFunction)func, userPtr);
+ }
+
+ // Commits all previous changes to the filter.
+ void commit()
+ {
+ oidnCommitFilter(handle);
+ }
+
+ // Executes the filter.
+ void execute()
+ {
+ oidnExecuteFilter(handle);
+ }
+ };
+
+ // Gets a boolean parameter of the filter.
+ template<>
+ inline bool FilterRef::get(const char* name)
+ {
+ return oidnGetFilter1b(handle, name);
+ }
+
+ // Gets an integer parameter of the filter.
+ template<>
+ inline int FilterRef::get(const char* name)
+ {
+ return oidnGetFilter1i(handle, name);
+ }
+
+ // Gets a float parameter of the filter.
+ template<>
+ inline float FilterRef::get(const char* name)
+ {
+ return oidnGetFilter1f(handle, name);
+ }
+
+ // --------------------------------------------------------------------------
+ // Device
+ // --------------------------------------------------------------------------
+
+ // Device types
+ enum class DeviceType
+ {
+ Default = OIDN_DEVICE_TYPE_DEFAULT, // select device automatically
+
+ CPU = OIDN_DEVICE_TYPE_CPU, // CPU device
+ };
+
+ // Error codes
+ enum class Error
+ {
+ None = OIDN_ERROR_NONE, // no error occurred
+ Unknown = OIDN_ERROR_UNKNOWN, // an unknown error occurred
+ InvalidArgument = OIDN_ERROR_INVALID_ARGUMENT, // an invalid argument was specified
+ InvalidOperation = OIDN_ERROR_INVALID_OPERATION, // the operation is not allowed
+ OutOfMemory = OIDN_ERROR_OUT_OF_MEMORY, // not enough memory to execute the operation
+ UnsupportedHardware = OIDN_ERROR_UNSUPPORTED_HARDWARE, // the hardware (e.g. CPU) is not supported
+ Cancelled = OIDN_ERROR_CANCELLED, // the operation was cancelled by the user
+ };
+
+ // Error callback function
+ typedef void (*ErrorFunction)(void* userPtr, Error code, const char* message);
+
+ // Device object with automatic reference counting
+ class DeviceRef
+ {
+ private:
+ OIDNDevice handle;
+
+ public:
+ DeviceRef() : handle(nullptr) {}
+ DeviceRef(OIDNDevice handle) : handle(handle) {}
+
+ DeviceRef(const DeviceRef& other) : handle(other.handle)
+ {
+ if (handle)
+ oidnRetainDevice(handle);
+ }
+
+ DeviceRef(DeviceRef&& other) : handle(other.handle)
+ {
+ other.handle = nullptr;
+ }
+
+ DeviceRef& operator =(const DeviceRef& other)
+ {
+ if (&other != this)
+ {
+ if (other.handle)
+ oidnRetainDevice(other.handle);
+ if (handle)
+ oidnReleaseDevice(handle);
+ handle = other.handle;
+ }
+ return *this;
+ }
+
+ DeviceRef& operator =(DeviceRef&& other)
+ {
+ std::swap(handle, other.handle);
+ return *this;
+ }
+
+ DeviceRef& operator =(OIDNDevice other)
+ {
+ if (other)
+ oidnRetainDevice(other);
+ if (handle)
+ oidnReleaseDevice(handle);
+ handle = other;
+ return *this;
+ }
+
+ ~DeviceRef()
+ {
+ if (handle)
+ oidnReleaseDevice(handle);
+ }
+
+ OIDNDevice getHandle() const
+ {
+ return handle;
+ }
+
+ operator bool() const
+ {
+ return handle != nullptr;
+ }
+
+ // Sets a boolean parameter of the device.
+ void set(const char* name, bool value)
+ {
+ oidnSetDevice1b(handle, name, value);
+ }
+
+ // Sets an integer parameter of the device.
+ void set(const char* name, int value)
+ {
+ oidnSetDevice1i(handle, name, value);
+ }
+
+ // Gets a parameter of the device.
+ template<typename T>
+ T get(const char* name);
+
+ // Sets the error callback function of the device.
+ void setErrorFunction(ErrorFunction func, void* userPtr = nullptr)
+ {
+ oidnSetDeviceErrorFunction(handle, (OIDNErrorFunction)func, userPtr);
+ }
+
+ // Returns the first unqueried error code and clears the stored error.
+ // Can be called for a null device as well to check why a device creation failed.
+ Error getError()
+ {
+ return (Error)oidnGetDeviceError(handle, nullptr);
+ }
+
+ // Returns the first unqueried error code and string message, and clears the stored error.
+ // Can be called for a null device as well to check why a device creation failed.
+ Error getError(const char*& outMessage)
+ {
+ return (Error)oidnGetDeviceError(handle, &outMessage);
+ }
+
+ // Commits all previous changes to the device.
+ // Must be called before first using the device (e.g. creating filters).
+ void commit()
+ {
+ oidnCommitDevice(handle);
+ }
+
+ // Creates a new buffer (data allocated and owned by the device).
+ BufferRef newBuffer(size_t byteSize)
+ {
+ return oidnNewBuffer(handle, byteSize);
+ }
+
+ // Creates a new shared buffer (data allocated and owned by the user).
+ BufferRef newBuffer(void* ptr, size_t byteSize)
+ {
+ return oidnNewSharedBuffer(handle, ptr, byteSize);
+ }
+
+ // Creates a new filter of the specified type (e.g. "RT").
+ FilterRef newFilter(const char* type)
+ {
+ return oidnNewFilter(handle, type);
+ }
+ };
+
+ // Gets a boolean parameter of the device.
+ template<>
+ inline bool DeviceRef::get(const char* name)
+ {
+ return oidnGetDevice1b(handle, name);
+ }
+
+ // Gets an integer parameter of the device (e.g. "version").
+ template<>
+ inline int DeviceRef::get(const char* name)
+ {
+ return oidnGetDevice1i(handle, name);
+ }
+
+ // Creates a new device.
+ inline DeviceRef newDevice(DeviceType type = DeviceType::Default)
+ {
+ return DeviceRef(oidnNewDevice((OIDNDeviceType)type));
+ }
+
+} // namespace oidn
diff --git a/thirdparty/oidn/include/OpenImageDenoise/version.h b/thirdparty/oidn/include/OpenImageDenoise/version.h
new file mode 100644
index 0000000000..66b347c992
--- /dev/null
+++ b/thirdparty/oidn/include/OpenImageDenoise/version.h
@@ -0,0 +1,23 @@
+// ======================================================================== //
+// Copyright 2009-2019 Intel Corporation //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+#pragma once
+
+#define OIDN_VERSION_MAJOR 1
+#define OIDN_VERSION_MINOR 1
+#define OIDN_VERSION_PATCH 0
+#define OIDN_VERSION 10100
+#define OIDN_VERSION_STRING "1.1.0"
diff --git a/thirdparty/oidn/mkl-dnn/LICENSE b/thirdparty/oidn/mkl-dnn/LICENSE
new file mode 100644
index 0000000000..d13f7b7ca0
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/LICENSE
@@ -0,0 +1,214 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ ============================================================================
+
+ Intel MKL-DNN includes components with separate copyright
+ notices and license terms.
+
+ XByak, 3-clause BSD license
+ Copyright (c) 2007 MITSUNARI Shigeo
+ See full copyright notice and license text in src/cpu/xbyak/COPYRIGHT
+
+ gtest, 3-clause BSD license
+ Copyright 2008, Google Inc.
+ See full copyright notice and license text in tests/gtests/gtest/LICENSE
diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn.h b/thirdparty/oidn/mkl-dnn/include/mkldnn.h
new file mode 100644
index 0000000000..9b64994922
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/include/mkldnn.h
@@ -0,0 +1,1771 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MKLDNN_H
+#define MKLDNN_H
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/* All symbols shall be internal unless marked as MKLDNN_API */
+#if defined _WIN32 || defined __CYGWIN__
+# define MKLDNN_HELPER_DLL_IMPORT __declspec(dllimport)
+# define MKLDNN_HELPER_DLL_EXPORT __declspec(dllexport)
+#else
+# if __GNUC__ >= 4
+# define MKLDNN_HELPER_DLL_IMPORT __attribute__ ((visibility ("default")))
+# define MKLDNN_HELPER_DLL_EXPORT __attribute__ ((visibility ("default")))
+# else
+# define MKLDNN_HELPER_DLL_IMPORT
+# define MKLDNN_HELPER_DLL_EXPORT
+# endif
+#endif
+
+#ifdef MKLDNN_DLL
+# ifdef MKLDNN_DLL_EXPORTS
+# define MKLDNN_API MKLDNN_HELPER_DLL_EXPORT
+# else
+# define MKLDNN_API MKLDNN_HELPER_DLL_IMPORT
+# endif
+#else
+# define MKLDNN_API
+#endif
+
+#if defined (__GNUC__)
+# define MKLDNN_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER)
+# define MKLDNN_DEPRECATED __declspec(deprecated)
+#else
+# define MKLDNN_DEPRECATED
+#endif
+
+#include "mkldnn_types.h"
+#include "mkldnn_version.h"
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup c_api C API
+ * @{ */
+
+/** @addtogroup c_api_primitive Primitive operations
+ * @{ */
+
+/** @addtogroup c_api_primitive_common Common primitive operations
+ * @{ */
+
+/** Creates a primitive descriptor @p iterator for given @p op_desc, @p attr,
+ * @p engine, and optionally a hint primitive descriptor from forward
+ * propagation (required for backward propagation). Pass @c NULL for forward
+ * propagation.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_iterator_create(
+ mkldnn_primitive_desc_iterator_t *iterator,
+ const_mkldnn_op_desc_t op_desc, const_mkldnn_primitive_attr_t attr,
+ mkldnn_engine_t engine,
+ const_mkldnn_primitive_desc_t hint_forward_primitive_desc);
+
+/** Iterates over primitive descriptors. Returns #mkldnn_iterator_ends if no
+ * more primitive descriptors are available. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_iterator_next(
+ mkldnn_primitive_desc_iterator_t iterator);
+
+/** Fetches the current primitive descriptor.
+ *
+ * @note
+ * The user should delete the fetched primitive descriptor using
+ * mkldnn_primitive_desc_destroy() once it is no longer needed. */
+mkldnn_primitive_desc_t MKLDNN_API mkldnn_primitive_desc_iterator_fetch(
+ const_mkldnn_primitive_desc_iterator_t iterator);
+
+/** Deletes a primitive descriptor @p iterator */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_iterator_destroy(
+ mkldnn_primitive_desc_iterator_t iterator);
+
+/** Creates a @p primitive_desc using @p op_desc, @p attr, @p engine, and
+ * optionally a hint primitive descriptor from forward propagation. The call is
+ * equivalent to creating a primitive descriptor iterator, immediately fetching
+ * a primitive descriptor, and then destroying the iterator. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_create(
+ mkldnn_primitive_desc_t *primitive_desc,
+ const_mkldnn_op_desc_t op_desc, const_mkldnn_primitive_attr_t attr,
+ mkldnn_engine_t engine,
+ const_mkldnn_primitive_desc_t hint_forward_primitive_desc);
+
+/** Makes a copy of a @p primitive_desc. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_clone(
+ mkldnn_primitive_desc_t *primitive_desc,
+ const_mkldnn_primitive_desc_t existing_primitive_desc);
+
+/** Returns a constant reference to the attribute of a @p primitive_desc.
+ *
+ * @warning
+ * The user should not destroy the obtained @p attr.
+ *
+ * @warning
+ * The lifetime of an @p attr is the same as that of a @p primitive_desc,
+ * so it is illegal to use the @p attr once @p primitive_desc has been
+ * destroyed. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_get_attr(
+ const_mkldnn_primitive_desc_t primitive_desc,
+ const_mkldnn_primitive_attr_t *attr);
+
+/** Deletes a @p primitive_desc. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_destroy(
+ mkldnn_primitive_desc_t primitive_desc);
+
+/** Queries primitive descriptor
+ *
+ * One of the most typical use cases is to query a convolution primitive
+ * descriptor created with source, weights, and destination formats equal
+ * to #mkldnn_format_tag_any about the corresponding memory descriptors
+ * (@p what equals #mkldnn_query_src_md, #mkldnn_query_weights_md, and
+ * #mkldnn_query_dst_md respectively) to be able to prepare memory and
+ * create reorders if required.
+ *
+ * Another quite typical use case is to query an operation primitive
+ * descriptor for a workspace (@p what equals #mkldnn_query_workspace_md).
+ * The returned status #mkldnn_not_required indicates that a workspace is
+ * not required.
+ *
+ * A few other possibilities:
+ * - query an operation primitive descriptor for the underlying operation
+ * descriptor (#mkldnn_query_convolution_d, #mkldnn_query_eltwise_d,
+ * #mkldnn_query_rnn_d, etc.)
+ * - query an operation primitive descriptor for the implementation
+ * information string (#mkldnn_query_impl_info_str)
+ * - query an operation primitive descriptor for the number of inputs and
+ * outputs (#mkldnn_query_num_of_inputs_s32 and
+ * #mkldnn_query_num_of_outputs_s32 respectively)
+ *
+ * @sa mkldnn_query_t for more options
+ */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_desc_query(
+ const_mkldnn_primitive_desc_t primitive_desc, mkldnn_query_t what,
+ int index, void *result);
+
+/** Queries primitive descriptor for memory descriptor
+ *
+ * @returns NULL in case of any error.
+ *
+ * This is just a specialized version of mkldnn_primitive_desc_query
+ * used for convenience.
+ */
+const mkldnn_memory_desc_t MKLDNN_API *mkldnn_primitive_desc_query_md(
+ const_mkldnn_primitive_desc_t primitive_desc, mkldnn_query_t what,
+ int index);
+
+/** Queries primitive descriptor for signed 32bit int
+ *
+ * @returns 0 in case of any error (in particular if the queried entity is
+ * not of type int32_t). Note that 0 might also be the actual returned
+ * value.
+ *
+ * This is just a specialized version of mkldnn_primitive_desc_query
+ * used for convenience.
+ */
+int MKLDNN_API mkldnn_primitive_desc_query_s32(
+ const_mkldnn_primitive_desc_t primitive_desc, mkldnn_query_t what,
+ int index);
+
+/** Creates a @p primitive using a @p primitive_desc descriptor. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_create(
+ mkldnn_primitive_t *primitive,
+ const_mkldnn_primitive_desc_t primitive_desc);
+
+/** Executes a @p primitive using a @p stream, and @p nargs arguments
+ * @p args. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_execute(
+ const_mkldnn_primitive_t primitive, mkldnn_stream_t stream,
+ int nargs, const mkldnn_exec_arg_t *args);
+
+/** Retrieves a reference to the @p primitive_desc descriptor of given @p
+ * primitive.
+ *
+ * @warning
+ * The returned object must not be destroyed by the user. The @c const
+ * qualifier of the returned object prevents such attempts. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_get_primitive_desc(
+ const_mkldnn_primitive_t primitive,
+ const_mkldnn_primitive_desc_t *primitive_desc);
+
+/** Deletes a @p primitive. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_destroy(
+ mkldnn_primitive_t primitive);
+
+/** @} */
+
+/** @addtogroup c_api_attributes Attributes
+ * An extension for controlling primitive behavior.
+ * @{ */
+
+/** Creates an empty (default) @p attr attribute. All the parameters are set to
+ * default values.
+ *
+ * An empty attribute is used in primitive descriptor creation whenever it
+ * is not passed explicitly, e.g. in mkldnn_primitive_desc_create.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_create(
+ mkldnn_primitive_attr_t *attr);
+
+/** Makes a copy of an @p existing_attr. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_clone(
+ mkldnn_primitive_attr_t *attr,
+ const_mkldnn_primitive_attr_t existing_attr);
+
+/** Deletes an @p attr. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_destroy(
+ mkldnn_primitive_attr_t attr);
+
+/** Returns the scratchpad @p mode set in the attribute @p attr */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_get_scratchpad_mode(
+ const_mkldnn_primitive_attr_t attr, mkldnn_scratchpad_mode_t *mode);
+
+/** Sets scratchpad @p mode.
+ *
+ * The possible values are: #mkldnn_scratchpad_mode_library (default) and
+ * #mkldnn_scratchpad_mode_user. */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_set_scratchpad_mode(
+ mkldnn_primitive_attr_t attr, mkldnn_scratchpad_mode_t mode);
+
+/** Returns @p count, correspondence scale @p mask, and a pointer to a constant
+ * floating point array of output @p scales for given @p attr, previously set
+ * by mkldnn_primitive_attr_set_output_scales.
+ *
+ * @warning
+ * The @p scales array points to the internal @p attr field, so the user
+ * should not modify or destroy @p scales.
+ *
+ * @warning
+ * The lifetime of @p scales is the same as that of the @p attr to which it
+ * belongs, so it is illegal to use @p scales after @p attr is destroyed.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_get_output_scales(
+ const_mkldnn_primitive_attr_t attr, mkldnn_dim_t *count, int *mask,
+ const float **scales);
+
+/** Sets output @p scales for primitive operations. The number of elements @p
+ * count and correspondence scale @p mask are stored for future use.
+ *
+ * The @p mask argument defines the correspondence between the output tensor
+ * dimensions and the @p scales array. Set the i-th bit of @p mask to 1 to use a
+ * dedicated scaling factor for each slice of the output tensor over the i-th
+ * dimension. Set @p mask to 0 to use a common scaling factor for the whole
+ * output tensor.
+ *
+ * @note
+ * The dimension order is always native and does not depend on the actual
+ * layout used. Examples:
+ * - 2D dimensional data the order of dimensions is always: (n, c)
+ * - 4D dimensional data the order is always: (n, c, h, w)
+ * - 5D dimensional weights the order is always: (g, oc, ic, kh, kw)
+ *
+ * Example usage:
+ * @code
+ * int mb = 32, oc = 32, oh = 14, ow = 14; // convolution output params
+ * float scales[oc] = { ... }; // unique output scales per output channel
+ * int oc_dim = 1; // mb_dim = 0, channel_dim = 1, height_dim = 2, ...
+ *
+ * mkldnn_convolution_desc_t cd; // create & configure convolution op_desc
+ *
+ * mkldnn_primitive_attr_t attr;
+ * mkldnn_primitive_attr_create(&attr); // create default attributes
+ * mkldnn_primitive_attr_set_output_scales(attr, oc, 1 << oc_dim, scales);
+ *
+ * mkldnn_primitive_desc_t cpd;
+ * mkldnn_primitive_desc_create(&cpd, &cd, attr, NULL);
+ * @endcode
+ *
+ * @note
+ * There is no way to check that @p count corresponds to @p mask until an
+ * actual primitive descriptor is created, so it is the user's
+ * responsibility to set proper values. The following formula must hold:
+ *
+ * \f[count = \prod\limits_{d \in mask} output.dims[d]\f]
+ */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_set_output_scales(
+ mkldnn_primitive_attr_t attr, mkldnn_dim_t count, int mask,
+ const float *scales);
+
+/** Returns @p post_ops for given @p attr.
+ *
+ * @warning
+ * @p post_ops points to the internal @p attr field, so the user should not
+ * modify or destroy @p post_ops. Also, the lifetime of @p post_ops is the
+ * same as that of the @p attr it belongs to, so it is illegal to use @p
+ * post_ops after @p attr has been destroyed.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_get_post_ops(
+ const_mkldnn_primitive_attr_t attr, const_mkldnn_post_ops_t *post_ops);
+
+/** Sets configured @p post_ops to an attribute @p attr for future use (when
+ * primitive descriptor is being created).
+ *
+ * @note
+ * At this point in time, there is no way to check whether the primitive
+ * descriptor does or does not support a given sequence of post operations.
+ * Therefore the user should handle an error that might occur at the
+ * mkldnn_primitive_desc_create call.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_set_post_ops(
+ mkldnn_primitive_attr_t attr, const_mkldnn_post_ops_t post_ops);
+
+/** @addtogroup c_api_attributes_post_ops Sequence of post operations
+ * An extension for performing extra operations after a base operation.
+ * @{ */
+
+/** Creates an empty sequence of post operations @p post_ops. */
+mkldnn_status_t MKLDNN_API mkldnn_post_ops_create(mkldnn_post_ops_t *post_ops);
+
+/** Deletes a @p post_ops sequence. */
+mkldnn_status_t MKLDNN_API mkldnn_post_ops_destroy(mkldnn_post_ops_t post_ops);
+
+/** Returns the @p length of post operations for given @p post_ops. */
+int MKLDNN_API mkldnn_post_ops_len(const_mkldnn_post_ops_t post_ops);
+
+/** Returns the type of post operation with index @p index in given
+ * @p post_ops. In case of error, returns #mkldnn_undefined_primitive. */
+mkldnn_primitive_kind_t MKLDNN_API mkldnn_post_ops_get_kind(
+ const_mkldnn_post_ops_t post_ops, int index);
+
+/** Appends accumulation (sum) post operation to the @p post_ops. Prior to
+ * accumulating the result, the previous value would be multiplied by @p scale.
+ *
+ * The kind of this post operation is #mkldnn_sum.
+ *
+ * This feature might improve performance for cases like residual learning
+ * blocks, where the result of convolution is accumulated to the previously
+ * computed activations. The parameter @p scale might be extreme for the
+ * integer-based computations when the result and previous activations have
+ * different logical scaling factors.
+ *
+ * In the simplest case when the accumulation is the only post operation, the
+ * computations would be:
+ * dst[] <- scale * dst[] + op(...) // instead of dst[] <- op(...)
+ *
+ * @note
+ * This post operation (as well as all the others) disregards the original
+ * layout of the destination; that is, the layout of the original
+ * destination is expected to be the same as the layout of the stored
+ * destination.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_post_ops_append_sum(
+ mkldnn_post_ops_t post_ops, float scale);
+
+/** Gets the parameters of the accumulation (sum) post operation with index
+ * @p index in the sequence of @p post_ops.
+ *
+ * @note
+ * If index @p index would not correspond to the accumulation post
+ * operation, the function returns #mkldnn_invalid_arguments.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_post_ops_get_params_sum(
+ const_mkldnn_post_ops_t post_ops, int index, float *scale);
+
+/** Appends eltwise post operation to the @p post_ops with given parameters
+ * @p kind, @p alpha, and @p beta (@sa mkldnn_eltwise_forward_desc_init and
+ * mkldnn_eltwise_desc_t).
+ *
+ * The kind of this post operation is #mkldnn_eltwise.
+ *
+ * In the simplest case when the eltwise is the only post operation, the
+ * computations would be:
+ * dst[] <- scale * eltwise_op ( op(...) ) // instead of dst[] <- op(...)
+ * where eltwise_op is configured with the given parameters.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_post_ops_append_eltwise(
+ mkldnn_post_ops_t post_ops, float scale, mkldnn_alg_kind_t alg,
+ float alpha, float beta);
+
+/** Gets the eltwise parameters of the post operation with index @p index in
+ * the sequence of @p post_ops.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_post_ops_get_params_eltwise(
+ const_mkldnn_post_ops_t post_ops, int index, float *scale,
+ mkldnn_alg_kind_t *alg, float *alpha, float *beta);
+
+/** @} */
+
+/** @} */
+
+/** @addtogroup c_api_memory Memory
+ * A primitive to describe and store data.
+ *
+ * The library supports various data types and formats. Memory hierarchy
+ * consists of three levels of abstraction:
+ * 1. **Memory descriptor** -- engine agnostic logical description of data
+ * (number of dimensions, dimensions themselves, and data type), and
+ * optionally the format/layout that describes the physical representation
+ * of data in memory. If the format is not known yet, one can pass
+ * #mkldnn_format_tag_any. This approach is used to allow compute-intensive
+ * primitives to specify the most appropriate format on their own with
+ * users required to reorder the data if the incoming format doesn't match
+ * the primitive's selection. Memory descriptor can be initialized with
+ * mkldnn_memory_desc_init_by_tag() or mkldnn_memory_desc_init_by_strides()
+ * functions, or by directly filling the mkldnn_memory_desc_t structure.
+ * The latter requires deep knowledge of how the physical data
+ * representation is mapped to the structure.
+ * The @ref understanding_memory_formats topic should shed some light on
+ * that.
+ * For the fully defined memory descriptors (i.e. where the format kind is
+ * not equal to #mkldnn_format_kind_any) a user can the size, using the
+ * mkldnn_memory_desc_get_size() function. As described in
+ * @ref understanding_memory_formats, the size of data sometimes cannot
+ * be computed as the product of dimensions times the size of the data
+ * type. So users are encouraged to use this function for better code
+ * portability.
+ * Two memory descriptors can be compared with mkldnn_memory_desc_equal().
+ * The comparison is especially useful when checking whether a primitive
+ * requires reorder from the user's data format to the primitive's format.
+ * 2. **Memory** -- an engine-specific object that handles the data and its
+ * description (a memory descriptor). For CPU enigne, the data handle is
+ * simply a pointer to @c void. The data handle can be queried using
+ * mkldnn_memory_get_data_handle() and set using
+ * mkldnn_memory_set_data_handle(). The latter function always sets the
+ * memory in the padding region to zero, which is the invariant maintained
+ * by all the primitives in Intel MKL-DNN.
+ * See @ref understanding_memory_formats for more details.
+ * A memory can be created using mkldnn_memory_create() function.
+ * A memory can also be queried for the underlying memory descriptor and
+ * engine using mkldnn_memory_get_memory_desc() and
+ * mkldnn_memory_get_engine() functions.
+ *
+ * Along with ordinary memory with all dimensions being positive, Intel
+ * MKL-DNN supports *zero-volume* memory with one or more dimensions set to
+ * zero. This is to support the NumPy\* convention.
+ * If a *zero-volume* memory is passed to a primitive, the primitive does
+ * not perform any computations on this memory. For example:
+ * - Convolution with `(0 batch, 3 input channels, 13 height, 13 width)`
+ * source and `(16 output channels, 3 inputs, channel, 3 height, 3 width)`
+ * weights would produce `(0 batch, 16 output channels, 11 height, 11 width)`
+ * destination (assuming strides are `1` and paddings are zero) and perform
+ * zero multiply-add operations.
+ * - Concatenation of three memories of shapes `(3, 4, 13, 13)`,
+ * `(3, 0, 13, 13)`, and `(3, 1, 13, 13)` along the second axis would produce
+ * the output of the shape `(3, 5, 13, 13)`, effectively ignoring the second
+ * input (however, if the user created a concatenation primitive descriptor
+ * with three inputs they should also provide all three memories to the
+ * concatenation primitive, including the one with zero second dimension).
+ * - However, Intel MKL-DNN would return an error when attempting to create a
+ * convolution with *zero-volume* memory passed for weights because such a
+ * convolution is not well-defined:
+ * ~~~
+ * dst(1, 16, 11, 11) <-- src(1, 0, 13, 13) (*) wei(16, 0, 3, 3)
+ * ~~~
+ * Should the values in the destination be zeroes or just not accessed at
+ * all? Moreover, backward pass w.r.t. weights in such cases is also not
+ * well-defined.
+ *
+ * Data handle of *zero-volume* memory is never accessed and hence can be
+ * unset (NULL in case of CPU engine).
+ *
+ * @sa @ref understanding_memory_formats
+ * @{ */
+
+/** Initializes a @p memory_desc memory descriptor using @p ndims, @p dims, @p
+ * data_type, and @p strides.
+ *
+ * The @p strides might be NULL, which means the order of physical dimensions
+ * is the same as the order of logical ones.
+ *
+ * @note The logical order of dimensions is defined by a primitive that
+ * consumes the memory.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_memory_desc_init_by_strides(
+ mkldnn_memory_desc_t *memory_desc, int ndims, const mkldnn_dims_t dims,
+ mkldnn_data_type_t data_type, const mkldnn_dims_t strides);
+
+/** Initializes a @p memory_desc memory descriptor using @p ndims, @p dims, @p
+ * data_type, and format @p tag.
+ *
+ * @p tag can be #mkldnn_format_tag_any, which allows a primitive to define
+ * the appropriate memory format. In this case, the @p format_kind would be set
+ * to #mkldnn_format_kind_any */
+mkldnn_status_t MKLDNN_API mkldnn_memory_desc_init_by_tag(
+ mkldnn_memory_desc_t *memory_desc, int ndims, const mkldnn_dims_t dims,
+ mkldnn_data_type_t data_type, mkldnn_format_tag_t tag);
+
+/** Initializes a @p memory_desc for a given @p parent_memory_desc, with
+ * @p dims sizes and @p offsets. May fail if layout used does not allow
+ * obtain desired submemory. In this case consider using `extract` or `insert`
+ * primitive */
+mkldnn_status_t MKLDNN_API mkldnn_memory_desc_init_submemory(
+ mkldnn_memory_desc_t *memory_desc,
+ const mkldnn_memory_desc_t *parent_memory_desc,
+ const mkldnn_dims_t dims, const mkldnn_dims_t offsets);
+
+/** Compares two memory descriptors.
+ * @return 1 if the descriptors are the same.
+ * @return 0 if the descriptors are different.
+ *
+ * Use this function to identify whether a reorder is required between the
+ * two memories */
+int MKLDNN_API mkldnn_memory_desc_equal(
+ const mkldnn_memory_desc_t *lhs,
+ const mkldnn_memory_desc_t *rhs);
+
+/** Returns the size (in bytes) that is required for given @p memory_desc */
+size_t MKLDNN_API mkldnn_memory_desc_get_size(
+ const mkldnn_memory_desc_t *memory_desc);
+
+/** Creates a memory for given @p memory_desc and @p engine. Also sets handle
+ * to @p native_handle.
+ * The @p native_handle can:
+ * - point to the user allocated memory, i.e. valid handle. In this case the
+ * library doesn't own allocated memory.
+ * - be MKLDNN_NATIVE_HANDLE_ALLOCATE to ask the library to allocate and
+ * attach memory. In this case the library owns allocated memory.
+ * - be MKLDNN_NATIVE_HANDLE_NONE to create mkldnn_memory w/o attached memory.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_memory_create(mkldnn_memory_t *memory,
+ const mkldnn_memory_desc_t *memory_desc, mkldnn_engine_t engine,
+ void *native_handle);
+
+/** Returns a @p memory_desc associated with @p memory. */
+mkldnn_status_t MKLDNN_API mkldnn_memory_get_memory_desc(
+ const_mkldnn_memory_t memory,
+ const mkldnn_memory_desc_t **memory_desc);
+
+/** Returns an @p engine associated with @p memory. */
+mkldnn_status_t MKLDNN_API mkldnn_memory_get_engine(
+ const_mkldnn_memory_t memory, mkldnn_engine_t *engine);
+
+/** For a @p memory, returns the data @p handle.
+ *
+ * For the CPU engine, the data handle is a pointer to the actual data. */
+mkldnn_status_t MKLDNN_API mkldnn_memory_get_data_handle(
+ const_mkldnn_memory_t memory, void **handle);
+
+/** For a @p memory, sets the data @p handle. */
+mkldnn_status_t MKLDNN_API mkldnn_memory_set_data_handle(
+ mkldnn_memory_t memory, void *handle);
+
+/** Deletes a @p memory. */
+mkldnn_status_t MKLDNN_API mkldnn_memory_destroy(mkldnn_memory_t memory);
+
+/** @} */
+
+/** @addtogroup c_api_reorder Reorder
+ * A primitive to copy data between memory formats.
+ * @{ */
+
+/** Initializes a @p reorder_primitive_desc using the description of the source
+ * (@p src_engine and @p src_md) and destination (@p dst_engine and @p dst_md)
+ * memory, and an @p attr attribute.
+ *
+ * Inputs:
+ * - input (#mkldnn_query_src_md, 0)
+ *
+ * Outputs:
+ * - output (#mkldnn_query_dst_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_reorder_primitive_desc_create(
+ mkldnn_primitive_desc_t *reorder_primitive_desc,
+ mkldnn_engine_t src_engine, const mkldnn_memory_desc_t *src_md,
+ mkldnn_engine_t dst_engine, const mkldnn_memory_desc_t *dst_md,
+ const_mkldnn_primitive_attr_t attr);
+
+/** @} */
+
+/** @addtogroup c_api_concat Concat
+ * A primitive to concatenate data by arbitrary dimension.
+ * @{ */
+
+/** Creates out-of-place @p concat_primitive_desc for concatenation of @p n
+ * inputs by @p concat_dimension with resulting @p output_desc memory
+ * descriptor. @p output_desc can be NULL or specified with the
+ * #mkldnn_format_kind_any format kind -- in this case, the appropriate memory
+ * format would be chosen automatically.
+ *
+ * Inputs:
+ * - input 0 (#mkldnn_query_src_md, 0)
+ * - input 1 (#mkldnn_query_src_md, 1)
+ * - ...
+ * - input @p n - 1 (#mkldnn_query_src_md, @p n - 1)
+ *
+ * Outputs:
+ * - output (#mkldnn_query_dst_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_concat_primitive_desc_create(
+ mkldnn_primitive_desc_t *concat_primitive_desc,
+ const mkldnn_memory_desc_t *dst_md,
+ int n, int concat_dimension,
+ const mkldnn_memory_desc_t *src_mds,
+ const_mkldnn_primitive_attr_t attr,
+ mkldnn_engine_t engine);
+
+/** @} */
+
+/** @addtogroup c_api_sum Sum
+ * A primitive to sum data.
+ * @{ */
+
+/** Creates out-of-place @p sum_primitive_desc for sum of @p n
+ * inputs multiplied by scale with resulting @p output_desc memory
+ * descriptor. @p output_desc can be NULL or specified with the
+ * #mkldnn_format_kind_any format kind -- in this case, the appropriate memory
+ * format would be chosen automatically.
+ *
+ * Inputs:
+ * - src 0 (#mkldnn_query_src_md, 0)
+ * - src 1 (#mkldnn_query_src_md, 1)
+ * - ...
+ * - src @p n - 1 (#mkldnn_query_src_md, @p n - 1)
+ *
+ * Outputs:
+ * - output (#mkldnn_query_dst_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_sum_primitive_desc_create(
+ mkldnn_primitive_desc_t *sum_primitive_desc,
+ const mkldnn_memory_desc_t *dst_mds,
+ int n, const float *scales,
+ const mkldnn_memory_desc_t *src_mds,
+ const_mkldnn_primitive_attr_t attr,
+ mkldnn_engine_t engine);
+
+/** @} */
+
+/** @addtogroup c_api_convolution Convolution
+ * A primitive to compute convolution using different algorithms.
+ *
+ * \f[dst[n][oc][oh][ow] =
+ * \sum_{kw=0}^{KW}\sum_{kh=0}^{KH}\sum_{ic=0}^{IC}
+ * src[n][ic][oh \cdot s_h - p_l[0] + kh][ow \cdot s_w - p_r[1] + kw]
+ * \cdot weights[g][oc][ic][kh][kw]
+ * + bias[g][oc],\f]
+ *
+ * where size of output spatial domain is given by
+ * \f$ OH = \left\lfloor{\frac{IH - KH + p_l[0] + p_r[0]}{s_h}}
+ * \right\rfloor + 1\f$,
+ * \f$ OW = \left\lfloor{\frac{IW - KW + p_l[1] + p_r[1]}{s_w}}
+ * \right\rfloor + 1\f$,
+ *
+ * and summation is carried over input channels \f$ic\f$ in
+ * group \f$g\f$, and \f$s_h, s_w\f$ are @p strides and
+ * \f$p_l, p_r\f$ are @p padding_l and @p padding_r.
+ * @{ */
+
+/** Initializes a convolution descriptor @p conv_desc for forward propagation
+ * using @p prop_kind (possible values are #mkldnn_forward_training and
+ * #mkldnn_forward_inference), @p alg_kind, memory descriptors, @p strides, @p
+ * padding_l, @p padding_r, and @p padding_kind. In order to create a
+ * convolution without bias, @p bias_desc should either be @c NULL or point to
+ * a descriptor with memory format kind equal to #mkldnn_format_kind_undef.
+ *
+ * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - weights (#mkldnn_query_weights_md, 0)
+ * - bias (#mkldnn_query_weights_md, 1), if created with bias
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_convolution_forward_desc_init(
+ mkldnn_convolution_desc_t *conv_desc, mkldnn_prop_kind_t prop_kind,
+ mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *weights_desc,
+ const mkldnn_memory_desc_t *bias_desc,
+ const mkldnn_memory_desc_t *dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r,
+ mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a dilated convolution descriptor @p conv_desc for forward
+ * propagation using @p prop_kind (possible values are #mkldnn_forward_training
+ * and #mkldnn_forward_inference), @p alg_kind, memory descriptors, @p strides,
+ * @p dilates, @p padding_l, @p padding_r, and @p padding_kind.
+ * In order to create a dilated convolution without bias, @p bias_desc
+ * should either be @c NULL or point to a descriptor with memory format kind
+ * equals #mkldnn_format_kind_undef.
+ *
+ * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - weights (#mkldnn_query_weights_md, 0)
+ * - bias (#mkldnn_query_weights_md, 1), if created with bias
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_dilated_convolution_forward_desc_init(
+ mkldnn_convolution_desc_t *conv_desc, mkldnn_prop_kind_t prop_kind,
+ mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *weights_desc,
+ const mkldnn_memory_desc_t *bias_desc,
+ const mkldnn_memory_desc_t *dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l,
+ const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a convolution descriptor @p conv_desc for backward propagation
+ * with respect to data using @p alg_kind, memory descriptors, @p strides, @p
+ * padding_l, @p padding_r, and @p padding_kind.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ * - weights (#mkldnn_query_weights_md, 0)
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_convolution_backward_data_desc_init(
+ mkldnn_convolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *diff_src_desc,
+ const mkldnn_memory_desc_t *weights_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r,
+ mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a dilated convolution descriptor @p conv_desc for backward
+ * propagation with respect to data using @p alg_kind, memory descriptors, @p
+ * strides, @p dilates @p padding_l, @p padding_r, and @p padding_kind.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ * - weights (#mkldnn_query_weights_md, 0)
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_dilated_convolution_backward_data_desc_init(
+ mkldnn_convolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *diff_src_desc,
+ const mkldnn_memory_desc_t *weights_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l,
+ const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a convolution descriptor @p conv_desc for backward propagation
+ * with respect to weights using @p alg_kind, memory descriptors, @p strides,
+ * @p padding_l, @p padding_r, and @p padding_kind.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ *
+ * Outputs:
+ * - diff_weights (#mkldnn_query_diff_weights_md, 0)
+ * - diff_bias (#mkldnn_query_diff_weights_md, 1), if created with bias
+ */
+mkldnn_status_t MKLDNN_API mkldnn_convolution_backward_weights_desc_init(
+ mkldnn_convolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *diff_weights_desc,
+ const mkldnn_memory_desc_t *diff_bias_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r,
+ mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a convolution descriptor @p conv_desc for backward propagation
+ * with respect to weights using @p alg_kind, memory descriptors, @p strides,
+ * @p dilates @p padding_l, @p padding_r, and @p padding_kind.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ *
+ * Outputs:
+ * - diff_weights (#mkldnn_query_diff_weights_md, 0)
+ * - diff_bias (#mkldnn_query_diff_weights_md, 1), if created with bias
+ */
+mkldnn_status_t MKLDNN_API
+mkldnn_dilated_convolution_backward_weights_desc_init(
+ mkldnn_convolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *diff_weights_desc,
+ const mkldnn_memory_desc_t *diff_bias_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l,
+ const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind);
+
+/** @} */
+
+/** @addtogroup c_api_deconvolution Deconvolution
+ * A primitive to compute deconvolution using different algorithms.
+ *
+ * @{ */
+
+
+/** Initializes a deconvolution descriptor @p deconv_desc for forward
+ * propagation using @p prop_kind (possible values are #mkldnn_forward_training
+ * and #mkldnn_forward_inference), @p alg_kind, memory descriptors, @p strides,
+ * @p padding_l, @p padding_r, and @p padding_kind. In order to create a
+ * deconvolution without bias, @p bias_desc should either be @c NULL or point to
+ * a descriptor with memory format kind equals #mkldnn_format_kind_undef.
+ *
+ * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - weights (#mkldnn_query_weights_md, 0)
+ * - bias (#mkldnn_query_weights_md, 1), if created with bias
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_deconvolution_forward_desc_init(
+ mkldnn_deconvolution_desc_t *conv_desc, mkldnn_prop_kind_t prop_kind,
+ mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *weights_desc,
+ const mkldnn_memory_desc_t *bias_desc,
+ const mkldnn_memory_desc_t *dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r,
+ mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a dilated deconvolution descriptor @p deconv_desc for forward
+ * propagation using @p prop_kind (possible values are #mkldnn_forward_training
+ * and #mkldnn_forward_inference), @p alg_kind, memory descriptors, @p strides,
+ * @p dilates, @p padding_l, @p padding_r, and @p padding_kind. In order to
+ * create a dilated deconvolution without bias, @p bias_desc should either be
+ * @c NULL or point to a descriptor with memory format kind equal
+ * #mkldnn_format_kind_undef.
+ *
+ * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - weights (#mkldnn_query_weights_md, 0)
+ * - bias (#mkldnn_query_weights_md, 1), if created with bias
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_dilated_deconvolution_forward_desc_init(
+ mkldnn_deconvolution_desc_t *conv_desc, mkldnn_prop_kind_t prop_kind,
+ mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *weights_desc,
+ const mkldnn_memory_desc_t *bias_desc,
+ const mkldnn_memory_desc_t *dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l,
+ const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a deconvolution descriptor @p conv_desc for backward propagation
+ * with respect to data using @p alg_kind, memory descriptors, @p strides, @p
+ * padding_l, @p padding_r, and @p padding_kind.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ * - weights (#mkldnn_query_weights_md, 0)
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_deconvolution_backward_data_desc_init(
+ mkldnn_deconvolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *diff_src_desc,
+ const mkldnn_memory_desc_t *weights_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r,
+ mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a dilated deconvolution descriptor @p conv_desc for backward
+ * propagation with respect to data using @p alg_kind, memory descriptors, @p
+ * strides, @p dilates, @p padding_l, @p padding_r, and @p padding_kind.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ * - weights (#mkldnn_query_weights_md, 0)
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_dilated_deconvolution_backward_data_desc_init(
+ mkldnn_deconvolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *diff_src_desc,
+ const mkldnn_memory_desc_t *weights_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l,
+ const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a deconvolution descriptor @p conv_desc for backward propagation
+ * with respect to weights using @p alg_kind, memory descriptors, @p strides,
+ * @p padding_l, @p padding_r, and @p padding_kind.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ *
+ * Outputs:
+ * - diff_weights (#mkldnn_query_diff_weights_md, 0)
+ * - diff_bias (#mkldnn_query_diff_weights_md, 1), if created with bias
+ */
+mkldnn_status_t MKLDNN_API mkldnn_deconvolution_backward_weights_desc_init(
+ mkldnn_deconvolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *diff_weights_desc,
+ const mkldnn_memory_desc_t *diff_bias_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t padding_l, const mkldnn_dims_t padding_r,
+ mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a dilated deconvolution descriptor @p conv_desc for backward
+ * propagation with respect to weights using @p alg_kind, memory descriptors,
+ * @p strides, @p dilates, @p padding_l, @p padding_r, and @p padding_kind.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ *
+ * Outputs:
+ * - diff_weights (#mkldnn_query_diff_weights_md, 0)
+ * - diff_bias (#mkldnn_query_diff_weights_md, 1), if created with bias
+ */
+mkldnn_status_t MKLDNN_API mkldnn_dilated_deconvolution_backward_weights_desc_init(
+ mkldnn_deconvolution_desc_t *conv_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *diff_weights_desc,
+ const mkldnn_memory_desc_t *diff_bias_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t dilates, const mkldnn_dims_t padding_l,
+ const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind);
+
+/** @} */
+
+/** @addtogroup c_api_shuffle Shuffle
+ * A primitive to shuffle data along the axis.
+ * @{ */
+
+/** Initializes a @p shuffle_desc for forward propagation using @p prop_kind,
+ * memory descriptor @p data_desc, @p axis, and @p group_size.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ *
+ */
+mkldnn_status_t MKLDNN_API mkldnn_shuffle_forward_desc_init(
+ mkldnn_shuffle_desc_t *shuffle_desc, mkldnn_prop_kind_t prop_kind,
+ const mkldnn_memory_desc_t *data_desc, int axis,
+ mkldnn_dim_t group_size);
+
+/** Initializes a @p shuffle_desc for backward propagation using memory
+ * descriptor @p diff_data_desc, @p axis, and @p group_size.
+ *
+ *
+ * Inputs:
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ *
+ */
+mkldnn_status_t MKLDNN_API mkldnn_shuffle_backward_desc_init(
+ mkldnn_shuffle_desc_t *shuffle_desc,
+ const mkldnn_memory_desc_t *diff_data_desc, int axis,
+ mkldnn_dim_t group_size);
+
+/** @} */
+
+/** @addtogroup c_api_eltwise Eltwise
+ * A primitive to compute element-wise operations like parametric rectifier
+ * linear unit (ReLU).
+ *
+ * Both forward and backward passes support in-place operation; that is, src
+ * and dst point to the same memory for forward pass, and diff_dst and diff_src
+ * point to the same memory for backward pass.
+ *
+ * @warning Because the original src is required for backward pass, in-place
+ * forward pass in general cannot be applied during training. However, for some
+ * kinds of element-wise operations (namely ReLU with alpha parameter equals 0),
+ * dst and src can be interchangeable for the backward pass, which enables
+ * performing in-place forward even for training.
+ *
+ * @{ */
+
+/** Initializes an @p eltwise_desc for forward propagation using @p prop_kind
+ * (possible values are #mkldnn_forward_training and #mkldnn_forward_inference),
+ * @p alg_kind algorithm, memory descriptor @p data_desc, @p alpha, and
+ * @p beta parameters.
+ *
+ * @sa mkldnn_eltwise_desc_t for details.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_eltwise_forward_desc_init(
+ mkldnn_eltwise_desc_t *eltwise_desc, mkldnn_prop_kind_t prop_kind,
+ mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *data_desc,
+ float alpha, float beta);
+
+/** Initializes an @p eltwise_desc for backward propagation using @p alg_kind
+ * algorithm memory descriptors @p diff_data_desc and @p data_desc, and the
+ * @p alpha and @p beta parameters.
+ *
+ * @sa mkldnn_eltwise_desc_t for details.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_eltwise_backward_desc_init(
+ mkldnn_eltwise_desc_t *eltwise_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *diff_data_desc,
+ const mkldnn_memory_desc_t *data_desc, float alpha, float beta);
+
+/** @} */
+
+/** @addtogroup c_api_softmax Softmax
+ * A primitive to perform softmax.
+ *
+ * \f[dst[u][c][in] =
+ * \frac{\exp(src[ou][c][in]) - \max\limits_{c}(src[ou][c][in])}
+ * {\sum\limits_{c}\{\exp(src[ou][c][in])
+ * - \max\limits_{c}(src[ou][c][in])\}},\f]
+ *
+ * where \f$ou, iu\f$ are outer and inner sizes repectively, defined
+ * by @p data_desc.dims and @p softmax_axis.
+ * @{ */
+
+/** Initializes a @p softmax_desc for forward propagation using @p prop_kind
+ * (possible values are #mkldnn_forward_training and #mkldnn_forward_inference)
+ * and memory descriptor @p data_desc.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_softmax_forward_desc_init(
+ mkldnn_softmax_desc_t *softmax_desc, mkldnn_prop_kind_t prop_kind,
+ const mkldnn_memory_desc_t *data_desc, int softmax_axis);
+
+/** Initializes a @p softmax_desc for backward propagation using memory
+ * descriptors @p diff_desc and @p data_desc.
+ *
+ * Inputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_softmax_backward_desc_init(
+ mkldnn_softmax_desc_t *softmax_desc,
+ const mkldnn_memory_desc_t *diff_desc,
+ const mkldnn_memory_desc_t *data_desc, int softmax_axis);
+
+/** @} */
+
+/** @addtogroup c_api_pooling Pooling
+ * A primitive to perform max or average pooling.
+ *
+ * Max pooling:
+ * \f[dst[n][oc][oh][ow] =
+ * \max\limits_{kw,kh}
+ * (src[n][ic][oh \cdot s_h - p_l[0] + kh][ow \cdot s_w - p_r[1] + kw]),\f]
+ *
+ * Average pooling:
+ * \f[dst[n][oc][oh][ow] =
+ * \frac{1}{KW \cdot KH}\sum\limits_{kw,kh}
+ * src[n][ic][oh \cdot s_h - p_l[0] + kh][ow \cdot s_w - p_r[1] + kw],\f]
+ *
+ * where \f$p_l, p_r\f$ are @p padding_l and @p padding_r respectively, and
+ * output spatial dimensions are calculated similarly to how they are done in
+ * convolution.
+ *
+ * During training, max pooling requires a workspace on forward
+ * (#mkldnn_forward_training) and backward (#mkldnn_backward) passes to
+ * save indices where maximum was found. The workspace layout is opaque, and
+ * the indices cannot be restored from it. However, one can use backward
+ * pooling to perform up-sampling (used in some detection topologies).
+ *
+ * @{ */
+
+/** Initializes a pooling descriptor @p pool_desc for forward propagation using
+ * @p prop_kind (possible values are #mkldnn_forward_training and
+ * #mkldnn_forward_inference), @p alg_kind, memory descriptors, and pooling
+ * parameters in the spatial domain: @p strides, @p kernel sizes, @p padding_l,
+ * @p padding_r, and @p padding_kind.
+ *
+ * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ * - workspace (#mkldnn_query_workspace_md, 0),
+ * if @p alg_kind = #mkldnn_pooling_max and
+ * @p prop_kind = #mkldnn_forward_training
+ */
+mkldnn_status_t MKLDNN_API mkldnn_pooling_forward_desc_init(
+ mkldnn_pooling_desc_t *pool_desc, mkldnn_prop_kind_t prop_kind,
+ mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t kernel, const mkldnn_dims_t padding_l,
+ const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind);
+
+/** Initializes a pooling descriptor @p pool_desc for backward propagation
+ * using @p alg_kind, memory descriptors, and pooling parameters in the spatial
+ * domain: @p strides, @p kernel sizes, @p padding_l, @p padding_r, and @p
+ * padding_kind.
+ *
+ * @note If @p padding_r is @c NULL, the padding is supposed to be symmetric.
+ *
+ * Inputs:
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ * - workspace (#mkldnn_query_workspace_md, 0),
+ * if @p alg_kind = #mkldnn_pooling_max
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_pooling_backward_desc_init(
+ mkldnn_pooling_desc_t *pool_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *diff_src_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc, const mkldnn_dims_t strides,
+ const mkldnn_dims_t kernel, const mkldnn_dims_t padding_l,
+ const mkldnn_dims_t padding_r, mkldnn_padding_kind_t padding_kind);
+
+/** @} */
+
+/** @addtogroup c_api_lrn LRN
+ * A primitive to perform local response normalization (LRN) across or within
+ * channels.
+ *
+ * LRN accross channels:
+ * \f[dst[n][c][h][w] = \left\{k + \frac{\alpha}{n_{l}}
+ * \sum\limits_{i=-(n_{l}-1)/2}^{(n_{l}+1)/2}
+ * (src[n][c+i][h][w])^2\right\}^{-\beta}
+ * src[n][c][h][w],\f]
+ *
+ * LRN within channels:
+ * \f[dst[n][c][h][w] = \left\{k + \frac{\alpha}{n_{l}}
+ * \sum\limits_{i=-(n_{l}-1)/2}^{(n_{l}+1)/2}
+ * (src[n][c][h+i][w+i])^2\right\}^{-\beta}
+ * src[n][c][h][w],\f]
+ *
+ * where \f$n_{l}\f$ is the @p local_size.
+ *
+ * During training, LRN might or might not require a workspace on forward
+ * (#mkldnn_forward_training) and backward (#mkldnn_backward) passes. The
+ * behavior is implementation specific. Optimized implementations typically
+ * require a workspace and use it to save some intermediate results from the
+ * forward pass that accelerate computations on the backward pass.
+ *
+ * To check whether a workspace is required, query the LRN primitive descriptor
+ * for the workspace (#mkldnn_query_workspace_md). Success indicates that the
+ * workspace is required and its description will be returned.
+ * @sa mkldnn_primitive_desc_query and mkldnn_primitive_desc_query_pd
+ *
+ * @{ */
+
+/** Initializes an @p lrn_desc for forward propagation using @p prop_kind
+ * (possible values are #mkldnn_forward_training and #mkldnn_forward_inference),
+ * @p alg_kind, memory descriptor @p data_desc, and regularization
+ * parameters @p local_size, @p alpha, @p beta, and @p k.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ * - workspace (#mkldnn_query_workspace_md, 0),
+ * if the underlying implementation requires
+ */
+mkldnn_status_t MKLDNN_API mkldnn_lrn_forward_desc_init(
+ mkldnn_lrn_desc_t *lrn_desc, mkldnn_prop_kind_t prop_kind,
+ mkldnn_alg_kind_t alg_kind, const mkldnn_memory_desc_t *data_desc,
+ mkldnn_dim_t local_size, float alpha, float beta, float k);
+
+/** Initializes an @p lrn_desc for backward propagation using @p alg_kind,
+ * memory descriptors @p data_desc and @p diff_data_desc, and regularization
+ * parameters @p local_size, @p alpha, @p beta, and @p k.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ * - workspace (#mkldnn_query_workspace_md, 0),
+ * if the underlying implementation requires
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_lrn_backward_desc_init(
+ mkldnn_lrn_desc_t *lrn_desc, mkldnn_alg_kind_t alg_kind,
+ const mkldnn_memory_desc_t *diff_data_desc,
+ const mkldnn_memory_desc_t *data_desc, mkldnn_dim_t local_size,
+ float alpha, float beta, float k);
+
+/** @} */
+
+/** @addtogroup c_api_batch_normalization Batch Normalization
+ * A primitive to perform batch normalization.
+ *
+ * \f[dst[n][c][h][w] = \gamma[c] \frac{src[n][c][h][w] - \mu[c]}
+ * {\sqrt{\sigma[c] + eps}} + \beta[c],\f]
+ *
+ * where \f$\gamma[c], \beta[c]\f$ are weights and bias for a channel and,
+ *
+ * \f$\mu[c] = \frac{1}{NHW} \sum\limits_{whn} src[n][c][h][w]\f$,
+ * \f$\sigma[c] = \frac{1}{NHW} \sum\limits_{whn}
+ * (src[n][c][h][w] - \mu[c])^2\f$,
+ *
+ * and @c eps is a constant to improve numerical stability.
+ *
+ * Both forward and backward passes support in-place operation; that is, src
+ * and dst point to the same memory for forward pass, and diff_dst and diff_src
+ * point to the same memory for backward pass.
+ *
+ * Batch normalization supports different flavors controlled by
+ * mkldnn_batch_normalization_desc_t. For example, batch normalization can
+ * compute the mean and variance on its own or take them as inputs. It can
+ * either perform scaling and shifting using gamma and beta parameters or not.
+ * Optionally it can also perform a fused ReLU, which in case of training would
+ * also require a workspace.
+ *
+ * @sa mkldnn_batch_normalization_desc_t
+ * @{ */
+
+/** Initializes a batch normalization descriptor @p bnrm_desc for forward
+ * propagation using @p prop_kind (possible values are
+ * #mkldnn_forward_training and #mkldnn_forward_inference), memory descriptor
+ * @p data_desc, normalization parameter @p epsilon, and @p flags set using bit
+ * flags of type mkldnn_batch_normalization_desc_t.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - mean (#mkldnn_query_src_md, 1),
+ * if #mkldnn_use_global_stats bit-flags is set in @p flags
+ * - variance (#mkldnn_query_src_md, 2),
+ * if #mkldnn_use_global_stats bit-flags is set in @p flags
+ * - scale_and_shift (#mkldnn_query_weights_md, 0),
+ * if #mkldnn_use_scaleshift bit-flags is set in @p flags
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ * - mean (#mkldnn_query_dst_md, 1),
+ * if #mkldnn_use_global_stats bit-flags is not set in @p flags
+ * @p prop_kind = #mkldnn_forward_training
+ * - variance (#mkldnn_query_dst_md, 2),
+ * if #mkldnn_use_global_stats bit-flags is not set in @p flags
+ * and @p prop_kind = #mkldnn_forward_training
+ * - workspace (#mkldnn_query_workspace_md, 0),
+ * if #mkldnn_fuse_bn_relu bit-flags is set in @p flags
+ * and @p prop_kind = #mkldnn_forward_training
+ *
+ * @note In-place operation is supported; that is, dst points to the same memory
+ * as src.
+ *
+ * @sa mkldnn_batch_normalization_desc_t
+ */
+mkldnn_status_t MKLDNN_API mkldnn_batch_normalization_forward_desc_init(
+ mkldnn_batch_normalization_desc_t *bnrm_desc,
+ mkldnn_prop_kind_t prop_kind, const mkldnn_memory_desc_t *data_desc,
+ float epsilon, unsigned flags);
+
+/** Initializes a batch normalization descriptor @p bnrm_desc for backward
+ * propagation with respect to data and scale-shift parameters using memory
+ * descriptors @p data_desc and @p diff_data_desc, normalization parameter
+ * @p epsilon, and @p flags set using bit flags of type
+ * mkldnn_batch_normalization_desc_t.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - mean (#mkldnn_query_src_md, 1)
+ * - variance (#mkldnn_query_src_md, 2)
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ * - scale_and_shift (#mkldnn_query_weights_md, 0),
+ * if #mkldnn_use_scaleshift bit-flags is set in @p flags
+ * - workspace (#mkldnn_query_workspace_md, 0),
+ * if #mkldnn_fuse_bn_relu bit-flags is set in @p flags
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ * - diff_scale_and_shift (#mkldnn_query_diff_weights_md, 0),
+ * if #mkldnn_use_scaleshift bit-flags is set in @p flags
+ * and @p prop_kind = #mkldnn_backward
+ *
+ * @note in-place operation is supported,
+ * i.e. diff_src points to the same memory as diff_dst.
+ *
+ * @sa mkldnn_batch_normalization_desc_t
+ */
+mkldnn_status_t MKLDNN_API mkldnn_batch_normalization_backward_desc_init(
+ mkldnn_batch_normalization_desc_t *bnrm_desc,
+ mkldnn_prop_kind_t prop_kind,
+ const mkldnn_memory_desc_t *diff_data_desc,
+ const mkldnn_memory_desc_t *data_desc,
+ float epsilon, unsigned flags);
+
+/** @} */
+
+/** @addtogroup c_api_inner_product Inner product
+ * A primitive to compute an inner product.
+ *
+ * Inner product layer is also known as fully connected layer.
+ * With spatial dimension:
+ *
+ * \f[dst[n][oc] = \sum\limits_{ic, kh, kw}
+ * src[n][ic][kh][kw] \cdot weights[oc][ic][kh][kw]
+ * + bias[oc]\f]
+ * @{ */
+
+/** Initializes an inner product descriptor @p ip_desc for forward propagation
+ * using @p prop_kind (possible values are #mkldnn_forward_training and
+ * #mkldnn_forward_inference) and memory descriptors. In order to create an
+ * inner product without bias, @p bias_desc should be either @c NULL or a
+ * pointer to a descriptor with memory format kind equals
+ * #mkldnn_format_kind_undef.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - weights (#mkldnn_query_weights_md, 0)
+ * - bias (#mkldnn_query_weights_md, 1), if created with bias
+ *
+ * Outputs:
+ * - dst (#mkldnn_query_dst_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_inner_product_forward_desc_init(
+ mkldnn_inner_product_desc_t *ip_desc, mkldnn_prop_kind_t prop_kind,
+ const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *weights_desc,
+ const mkldnn_memory_desc_t *bias_desc,
+ const mkldnn_memory_desc_t *dst_desc);
+
+/** Initializes an inner product descriptor @p ip_desc for backward propagation
+ * with respect to data using memory descriptors.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ * - weights (#mkldnn_query_weights_md, 0)
+ *
+ * Outputs:
+ * - diff_src (#mkldnn_query_diff_src_md, 0)
+ */
+mkldnn_status_t MKLDNN_API mkldnn_inner_product_backward_data_desc_init(
+ mkldnn_inner_product_desc_t *ip_desc,
+ const mkldnn_memory_desc_t *diff_src_desc,
+ const mkldnn_memory_desc_t *weights_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc);
+
+/** Initializes an inner product descriptor @p ip_desc for backward propagation
+ * with respect to weights using memory descriptors.
+ *
+ * @note Memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src (#mkldnn_query_src_md, 0)
+ * - diff_dst (#mkldnn_query_diff_dst_md, 0)
+ *
+ * Outputs:
+ * - diff_weights (#mkldnn_query_diff_weights_md, 0)
+ * - diff_bias (#mkldnn_query_diff_weights_md, 1), if created with bias
+ */
+mkldnn_status_t MKLDNN_API mkldnn_inner_product_backward_weights_desc_init(
+ mkldnn_inner_product_desc_t *ip_desc,
+ const mkldnn_memory_desc_t *src_desc,
+ const mkldnn_memory_desc_t *diff_weights_desc,
+ const mkldnn_memory_desc_t *diff_bias_desc,
+ const mkldnn_memory_desc_t *diff_dst_desc);
+
+/** @} */
+
+/** @addtogroup c_api_rnn RNN
+ * A primitive to compute the common recurrent layer.
+ * @todo add additional description for the group
+ * @{ */
+
+/**
+ * Initializes a recurrent cell descriptor @p rnn_cell_desc
+ * using @p rnn_cell_desc, @p kind (possible values are
+ * #mkldnn_vanilla_rnn, #mkldnn_vanilla_lstm, #mkldnn_vanilla_gru, and
+ * #mkldnn_gru_linear_before_reset),
+ * @p f (possible values are #mkldnn_eltwise_relu and
+ * #mkldnn_eltwise_tanh), @p flags, @p alpha, and @p clipping.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_rnn_cell_desc_init(
+ mkldnn_rnn_cell_desc_t *rnn_cell_desc,
+ mkldnn_alg_kind_t kind, mkldnn_alg_kind_t f,
+ unsigned int flags, float alpha, float clipping);
+
+/** Returns the number of gates of a particular @p rnn_cell_desc. */
+int MKLDNN_API mkldnn_rnn_cell_get_gates_count(
+ const mkldnn_rnn_cell_desc_t *rnn_cell_desc);
+
+/** Returns the number of states of a particular @p rnn_cell_desc. */
+int MKLDNN_API mkldnn_rnn_cell_get_states_count(
+ const mkldnn_rnn_cell_desc_t *rnn_cell_desc);
+
+/** Sets quantization @p scale and @p shift for RNN data tensors.
+ * For performance reasons, low precision configuration of RNN primitive
+ * expects input activations to have unsigned int8 data type. Scale and shift
+ * used to quantize floating point data to unsigned integer must be passed to
+ * RNN primitive using attributes.
+ * Example usage:
+ * @code
+ * // rnn parameters
+ * int l = 2, t = 2, mb = 32, sic = 32, slc = 32, dic = 32, dlc = 32;
+ * // activations quantization parameters
+ * float scale = ..., shift = ..;
+ *
+ * mkldnn_primitive_attr_t rnn_attr;
+ * // create default attributes
+ * mkldnn_primitive_attr_create(&rnn_attr);
+ *
+ * // set scale and shift for int8 quantization of activation
+ * mkldnn_primitive_attr_set_rnn_data_qparams(rnn_attr, scale, shift);
+ *
+ * // create & configure rnn op_desc
+ * mkldnn_rnn_desc_t rnn_d;
+ * mkldnn_primitive_desc_t rnn_pd;
+ * mkldnn_primitive_desc_create(&rnn_pd, &rnn_d, attr, engine, NULL);
+ * @endcode
+ * @note
+ * Quantization scale and shift are common for src_layer, src_iter,
+ * dst_iter and dst_layer.
+ */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_set_rnn_data_qparams(
+ mkldnn_primitive_attr_t attr, const float scale, const float shift);
+
+/** Sets quantization scales @p weights_scales for RNN weights tensors.
+ * Low precision configuration of RNN primitive expects input weights to have
+ * signed int8 data type. Scales used to quantize floating point data
+ * to signed integer must be passed to RNN primitive using attributes.
+ * The @p mask argument defines correspondence between output tensor dimensions
+ * and the @p weights_scales array. Set i-th bit of @p mask to 1 to use
+ * dedicated scaling factor for each slice of the output tensor over i-th
+ * dimension. Set @p mask to 0 to use common scaling factor for the whole output
+ * tensor. Example usage:
+ * @code
+ * // rnn parameters
+ * int l = 2, t = 2, mb = 32, sic = 32, slc = 32, dic = 32, dlc = 32;
+ * // unique output scales per output channel
+ * float weights_scales[dic * n_gates] = { ... };
+ * // mask that specifies last two dimensions of ldigo format
+ * int mask = 0x3;
+ *
+ * mkldnn_primitive_attr_t attr;
+ * // create default attributes
+ * mkldnn_primitive_attr_create(&attr);
+ *
+ * // set output channel-wise weights scales
+ * mkldnn_primitive_attr_set_rnn_weights_qparams(attr, dic * n_gates, mask,
+ * weights_scales);
+ *
+ * // create & configure rnn op_desc
+ * mkldnn_rnn_desc_t rnn_d;
+ * mkldnn_primitive_desc_t rnn_pd;
+ * mkldnn_primitive_desc_create(&rnn_pd, &rnn_d, attr, engine, NULL);
+ * @endcode
+ * @note
+ * The dimension order is always native and does not depend on the actual
+ * layout used. For example, 5 dimensional weights always have
+ * (l, d, i, g, o) logical dimension ordering.
+ * @note
+ * Quantization sales are common for weights_layer and weights_iteration
+ * @note
+ * There is no way to check that @p count corresponds to @p mask until an
+ * actual primitive descriptor is created, so it is user's responsibility
+ * to set proper values. The following formula must be held:
+ *
+ * \f[count = \prod\limits_{d \in mask} output.dims[d]\f]
+ */
+mkldnn_status_t MKLDNN_API mkldnn_primitive_attr_set_rnn_weights_qparams (
+ mkldnn_primitive_attr_t attr, mkldnn_dim_t count, int mask,
+ const float *weights_scales);
+
+/** Initializes a rnn descriptor @p rnn_desc for forward propagation
+ * using @p prop_kind, @p rnn_cell_desc, @p direction, and memory descriptors.
+ * @note If @p prop_kind equals #mkldnn_forward_training, you must query a
+ * workspace memory descriptor before creating the primitive.
+ *
+ * @p src_iter_desc, @p bias_desc, and @p dst_iter_desc are allowed to either be
+ * @c NULL or point to a zero memory descriptor, which would indicate that the
+ * RNN primitive should not use them.
+ *
+ * @note All memory descriptors except @p src_iter_desc are allowed to be
+ * initialized with #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * Inputs:
+ * - src_layer (#mkldnn_query_src_md, 0)
+ * - src_iter (#mkldnn_query_src_md, 1), if used
+ * - weights_layer (#mkldnn_query_weights_md, 0)
+ * - weights_iter (#mkldnn_query_weights_md, 1)
+ * - bias (#mkldnn_query_weights_md, 2), if used
+ *
+ * Outputs:
+ * - dst_layer (#mkldnn_query_dst_md, 0)
+ * - dst_iter (#mkldnn_query_dst_md, 1), if used
+ * - workspace (#mkldnn_query_workspace_md, 0),
+ * if @p prop_kind equals #mkldnn_forward_training
+ */
+mkldnn_status_t MKLDNN_API mkldnn_rnn_forward_desc_init(
+ mkldnn_rnn_desc_t *rnn_desc, mkldnn_prop_kind_t prop_kind,
+ const mkldnn_rnn_cell_desc_t *rnn_cell_desc,
+ const mkldnn_rnn_direction_t direction,
+ const mkldnn_memory_desc_t *src_layer_desc,
+ const mkldnn_memory_desc_t *src_iter_desc,
+ const mkldnn_memory_desc_t *weights_layer_desc,
+ const mkldnn_memory_desc_t *weights_iter_desc,
+ const mkldnn_memory_desc_t *bias_desc,
+ const mkldnn_memory_desc_t *dst_layer_desc,
+ const mkldnn_memory_desc_t *dst_iter_desc);
+
+/** Initializes a rnn descriptor @p rnn_desc for backward propagation
+ * using @p prop_kind, @p rnn_cell_desc, @p direction, and memory descriptors.
+ *
+ * @note All memory descriptors are allowed to be initialized with
+ * #mkldnn_format_kind_any value of @p format_kind.
+ *
+ * @p src_iter_desc (simultaneously with @p diff_src_iter_desc),
+ * @p bias_desc (simultaneously with @p diff_bias_desc), and
+ * @p dst_iter_desc (simultaneously with @p diff_src_iter_desc) are allowed to
+ * either be @c NULL or point to a zero memory descriptor, which would indicate
+ * that the RNN primitive should not use them.
+ *
+ * Inputs:
+ * - src_layer (#mkldnn_query_src_md, 0)
+ * - src_iter (#mkldnn_query_src_md, 1), if used
+ * - weights_layer (#mkldnn_query_weights_md, 0)
+ * - weights_iter (#mkldnn_query_weights_md, 1)
+ * - bias (#mkldnn_query_weights_md, 2), if used
+ * - dst_layer (#mkldnn_query_dst_md, 0)
+ * - dst_iter (#mkldnn_query_dst_md, 1), if used
+ * - diff_dst_layer (#mkldnn_query_diff_dst_md, 0)
+ * - diff_dst_iter (#mkldnn_query_diff_dst_md, 1), if used
+ * - workspace (#mkldnn_query_workspace_md, 0)
+ *
+ * Outputs:
+ * - diff_src_layer (#mkldnn_query_diff_src_md, 0)
+ * - diff_src_iter (#mkldnn_query_diff_src_md, 1), if used
+ * - diff_weights_layer (#mkldnn_query_diff_weights_md, 0)
+ * - diff_weights_iter (#mkldnn_query_diff_weights_md, 1)
+ * - diff_bias (#mkldnn_query_diff_weights_md, 2), if used
+ */
+mkldnn_status_t MKLDNN_API mkldnn_rnn_backward_desc_init(
+ mkldnn_rnn_desc_t *rnn_desc, mkldnn_prop_kind_t prop_kind,
+ const mkldnn_rnn_cell_desc_t *rnn_cell_desc,
+ const mkldnn_rnn_direction_t direction,
+ const mkldnn_memory_desc_t *src_layer_desc,
+ const mkldnn_memory_desc_t *src_iter_desc,
+ const mkldnn_memory_desc_t *weights_layer_desc,
+ const mkldnn_memory_desc_t *weights_iter_desc,
+ const mkldnn_memory_desc_t *bias_desc,
+ const mkldnn_memory_desc_t *dst_layer_desc,
+ const mkldnn_memory_desc_t *dst_iter_desc,
+ const mkldnn_memory_desc_t *diff_src_layer_desc,
+ const mkldnn_memory_desc_t *diff_src_iter_desc,
+ const mkldnn_memory_desc_t *diff_weights_layer_desc,
+ const mkldnn_memory_desc_t *diff_weights_iter_desc,
+ const mkldnn_memory_desc_t *diff_bias_desc,
+ const mkldnn_memory_desc_t *diff_dst_layer,
+ const mkldnn_memory_desc_t *diff_dst_iter_desc);
+
+/** @} */
+
+/** @} */
+
+/** @addtogroup c_api_engine Engine operations
+ * @{ */
+
+/** Returns the number of engines of a particular @p kind. */
+size_t MKLDNN_API mkldnn_engine_get_count(mkldnn_engine_kind_t kind);
+
+/** Creates an @p engine of particular @p kind and @p index. */
+mkldnn_status_t MKLDNN_API mkldnn_engine_create(mkldnn_engine_t *engine,
+ mkldnn_engine_kind_t kind, size_t index);
+
+/** Returns the kind of an @p engine. */
+mkldnn_status_t MKLDNN_API mkldnn_engine_get_kind(mkldnn_engine_t engine,
+ mkldnn_engine_kind_t *kind);
+
+/** Destroys an @p engine. */
+mkldnn_status_t MKLDNN_API mkldnn_engine_destroy(mkldnn_engine_t engine);
+
+/** @} */
+
+/** @addtogroup c_api_stream Execution stream operations
+ * @{ */
+
+/** Creates an execution @p stream for @p engine and with @p flags. */
+mkldnn_status_t MKLDNN_API mkldnn_stream_create(mkldnn_stream_t *stream,
+ mkldnn_engine_t engine, unsigned flags);
+
+/** Destroys an execution @p stream. */
+mkldnn_status_t MKLDNN_API mkldnn_stream_destroy(mkldnn_stream_t stream);
+
+/** @} */
+
+/** @addtogroup c_api_service Service functions
+ * @{ */
+
+/** Sets verbosity level (print information to stdout).
+ * Possible levels are:
+ * - 0 -- no verbose output (default)
+ * - 1 -- primitive information at execution
+ * - 2 -- primitive information at creation and execution
+ *
+ * @note
+ * Dumping information might affect performance.
+ * This setting overrides the MKLDNN_VERBOSE environment variable. */
+mkldnn_status_t MKLDNN_API mkldnn_set_verbose(int level);
+
+/** Enables or disables dumping of JIT-generated code.
+ * The enable parameter can be:
+ * - 0 -- disable
+ * - any other value -- enable
+ *
+ * @note
+ * This setting overrides the MKLDNN_JIT_DUMP environment variable. */
+mkldnn_status_t MKLDNN_API mkldnn_set_jit_dump(int enable);
+
+/** Gets library version information.
+ * Version information includes:
+ * - major -- major version number
+ * - minor -- minor version number
+ * - patch -- patch release number
+ * - hash -- git commit hash */
+const mkldnn_version_t MKLDNN_API *mkldnn_version();
+
+/** @} */
+
+/** @addtogroup c_api_blas BLAS functions
+ * A subset of Basic Linear ALgebra (BLAS) functions to perform
+ * matrix-matrix multiplication.
+ * @{ */
+
+/** SGEMM performs a matrix-matrix multiplication operation defined as
+ *
+ * C := alpha*op( A )*op( B ) + beta*C
+ *
+ * where
+ * - op( X ) is one of op( X ) = X or op( X ) = X**T,
+ * - alpha and beta are scalars,
+ * - A, B and C are matrices, with op( A ) an m by k matrix, op( B ) a k by n matrix
+ * and C an m by n matrix.
+ *
+ * The matrices are assumed to be stored in column-major order (the elements
+ * in a matrix columns are contiguous in memory).
+ *
+ * @note
+ * The API is different from the standard BLAS routine
+ * because it returns mkldnn_status_t for error handling.
+ * XERBLA is not supported: no error message will be printed
+ * in case of incorrect parameters. */
+mkldnn_status_t MKLDNN_API mkldnn_sgemm(
+ const char *transa, const char *transb,
+ const mkldnn_dim_t *M, const mkldnn_dim_t *N, const mkldnn_dim_t *K,
+ const float *alpha, const float *A, const mkldnn_dim_t *lda,
+ const float *B, const mkldnn_dim_t *ldb,
+ const float *beta, float *C, const mkldnn_dim_t *ldc);
+
+/** gemm_s8u8s32 and gemm_s8s8s32 perform a matrix-matrix multiplication
+ * operation and add the result to a scalar-matrix product. For the final
+ * result, a vector is added to each row or column of the output matrix.
+ * The operation is defined as:
+ *
+ * C := alpha*(op(A) + A_offset) * (op(B) + B_offset) + beta*C + C_offset
+ *
+ * where
+ * - op( X ) = X or op( X ) = X**T,
+ * - A_offset is an m-by-k matrix with every element equal to the value oa,
+ * - B_offset is an k-by-n matrix with every element equal to the value ob,
+ * - C_offset is an m-by-n matrix defined by the oc array, size len:
+ * - if offsetc = F: len must be at least 1
+ * - if offsetc = C: len must be at least max(1, m)
+ * - if offsetc = R: len must be at least max(1, n)
+ * - alpha and beta are scalars, and A, B and C are matrices, with op( A )
+ * an m-by-k matrix, op( B ) a k-by-n matrix and C an m-by-n matrix.
+ *
+ * The matrices are assumed to be stored in column-major order (the elements
+ * in a matrix columns are contiguous in memory).
+ *
+ * @note
+ * The API is different compared with the standard BLAS routine
+ * because it returns mkldnn_status_t for error handling.
+ * XERBLA is not supported: no error message will be printed
+ * in case of incorrect parameters. */
+mkldnn_status_t MKLDNN_API mkldnn_gemm_s8u8s32(
+ const char *transa, const char *transb, const char *offsetc,
+ const mkldnn_dim_t *M, const mkldnn_dim_t *N, const mkldnn_dim_t *K,
+ const float *alpha,
+ const int8_t *A, const mkldnn_dim_t *lda, const int8_t *ao,
+ const uint8_t *B, const mkldnn_dim_t *ldb, const int8_t *bo,
+ const float *beta,
+ int32_t *c, const mkldnn_dim_t *ldc, const int32_t *co);
+
+mkldnn_status_t MKLDNN_API mkldnn_gemm_s8s8s32(
+ const char *transa, const char *transb, const char *offsetc,
+ const mkldnn_dim_t *M, const mkldnn_dim_t *N, const mkldnn_dim_t *K,
+ const float *alpha,
+ const int8_t *A, const mkldnn_dim_t *lda, const int8_t *ao,
+ const int8_t *B, const mkldnn_dim_t *ldb, const int8_t *bo,
+ const float *beta,
+ int32_t *c, const mkldnn_dim_t *ldc, const int32_t *co);
+/** @} */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn.hpp b/thirdparty/oidn/mkl-dnn/include/mkldnn.hpp
new file mode 100644
index 0000000000..581400a013
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/include/mkldnn.hpp
@@ -0,0 +1,2615 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MKLDNN_HPP
+#define MKLDNN_HPP
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+#include <stdlib.h>
+#include <memory>
+#include <vector>
+#include <unordered_map>
+#include <algorithm>
+#include <iterator>
+
+#include "mkldnn.h"
+#endif
+
+namespace mkldnn {
+
+/// @addtogroup cpp_api C++ API
+/// @{
+
+/// @addtogroup cpp_api_utils Utils
+/// @{
+
+/// A class that provides the destructor for an Intel(R) MKL-DNN C handle
+template <typename T> class handle_traits {};
+
+/// A class for wrapping an Intel(R) MKL-DNN handle. It is used as the base
+/// class for primitive (#mkldnn_primitive_t), engine (#mkldnn_engine_t), and
+/// stream (#mkldnn_stream_t) handles. An object of the #mkldnn::handle class
+/// can be passed by value. This class enables wrapping:
+/// - Newly constructed handles.
+/// @n In this case, the constructed handle uses reference counting provided
+/// by @p std::shared_ptr with a proper deleter function specified through
+/// the @p handle_traits class.
+/// - Pre-existing handles returned by the Intel(R) MKL-DNN C API (for
+/// example, through mkldnn_primitive_get_primitive_desc()).
+/// @n In this case, an Intel(R) MKL-DNN C API handle is wrapped without a
+/// deleter because it is assumed that the handle wrapper for the original
+/// object deletes the handle (this model is similar to @p std::weak_ptr).
+template <typename T, typename traits=handle_traits<T>> class handle {
+private:
+ std::shared_ptr<typename std::remove_pointer<T>::type> _data;
+ handle(const handle &&) = delete;
+ handle &operator=(const handle &&other) = delete;
+protected:
+ bool operator==(const T other) const { return other == _data.get(); }
+ bool operator!=(const T other) const { return !(*this == other); }
+public:
+ /// Constructs a C handle wrapper.
+ /// @param t The C handle to wrap.
+ /// @param weak A flag to specify whether to construct a weak wrapper.
+ handle(T t = 0, bool weak = false): _data(0) {
+ reset(t, weak);
+ }
+
+ handle(const handle &other): _data(other._data) {}
+ handle &operator=(const handle &other) {
+ _data = other._data;
+ return *this;
+ }
+ /// Resets the value of a C handle.
+ /// @param t The new value of the C handle.
+ /// @param weak A flag to specify whether the wrapper should be weak.
+ void reset(T t, bool weak = false) {
+ auto dummy_destructor = [](T) { return decltype(traits::destructor(0))(0); };
+ _data.reset(t, weak ? dummy_destructor : traits::destructor);
+ }
+
+ /// Returns the value of the underlying C handle.
+ T get() const { return _data.get(); }
+
+ bool operator==(const handle &other) const { return other._data.get() == _data.get(); }
+ bool operator!=(const handle &other) const { return !(*this == other); }
+};
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template <> struct handle_traits<mkldnn_memory_t> {
+ static constexpr auto destructor = &mkldnn_memory_destroy;
+};
+
+template <> struct handle_traits<mkldnn_primitive_desc_t> {
+ static constexpr auto destructor = &mkldnn_primitive_desc_destroy;
+};
+
+template <> struct handle_traits<mkldnn_primitive_t> {
+ static constexpr auto destructor = &mkldnn_primitive_destroy;
+};
+
+template <> struct handle_traits<mkldnn_primitive_desc_iterator_t> {
+ static constexpr auto destructor = &mkldnn_primitive_desc_iterator_destroy;
+};
+#endif
+
+struct memory;
+struct primitive_desc;
+
+/// Base class for all computational primitives.
+class primitive: public handle<mkldnn_primitive_t> {
+ friend struct error;
+ friend struct stream;
+ using handle::handle;
+public:
+ /// A proxy to C primitive kind enum
+ enum class kind {
+ undefined_primitive = mkldnn_undefined_primitive,
+ reorder = mkldnn_reorder,
+ concat = mkldnn_concat,
+ sum = mkldnn_sum,
+ convolution = mkldnn_convolution,
+ deconvolution = mkldnn_deconvolution,
+ shuffle = mkldnn_shuffle,
+ eltwise = mkldnn_eltwise,
+ softmax = mkldnn_softmax,
+ pooling = mkldnn_pooling,
+ lrn = mkldnn_lrn,
+ batch_normalization = mkldnn_batch_normalization,
+ inner_product = mkldnn_inner_product,
+ rnn = mkldnn_rnn,
+ };
+
+ primitive(const_mkldnn_primitive_desc_t c_pd);
+ primitive(const primitive_desc &pd);
+
+ /// Returns the descriptor of the underlying C API primitive.
+ inline const_mkldnn_primitive_desc_t get_primitive_desc() const;
+ // TODO: use the C++ API wrapper structure.
+
+ void execute(struct stream &astream,
+ const std::unordered_map<int, memory> &args) const;
+};
+
+inline mkldnn_primitive_kind_t convert_to_c(primitive::kind akind) {
+ return static_cast<mkldnn_primitive_kind_t>(akind);
+}
+/// Intel(R) MKL-DNN exception class.
+///
+/// This class captures the status returned by the failed C API function, error
+/// message, and, optionally, handle of the primitive that caused the error.
+struct error: public std::exception {
+ mkldnn_status_t status;
+ const char *message;
+
+ /// Constructs an error instance.
+ ///
+ /// @param astatus The error status returned by the C API.
+ /// @param amessage The error message.
+ error(mkldnn_status_t astatus, const char *amessage)
+ : status(astatus), message(amessage) {}
+
+ /// A convenience function for wrapping calls to the C API. Checks the
+ /// return status and throws an #error in case of failure.
+ ///
+ /// @param status The error status returned by the C API.
+ /// @param message The error message.
+ static void wrap_c_api(mkldnn_status_t status, const char *message) {
+ if (status != mkldnn_success)
+ throw error(status, message);
+ }
+};
+
+const_mkldnn_primitive_desc_t primitive::get_primitive_desc() const {
+ const_mkldnn_primitive_desc_t pd;
+ error::wrap_c_api(mkldnn_primitive_get_primitive_desc(get(), &pd),
+ "could not get primitive descriptor by primitive");
+ return pd;
+}
+/// @}
+
+/// @addtogroup cpp_api_enums Common data types and enumerations
+/// A proxy to @ref c_api_types in @ref c_api.
+///
+/// @{
+
+enum scratchpad_mode {
+ scratchpad_mode_library = mkldnn_scratchpad_mode_library,
+ scratchpad_mode_user = mkldnn_scratchpad_mode_user,
+};
+
+inline mkldnn_scratchpad_mode_t convert_to_c(scratchpad_mode mode) {
+ return static_cast<mkldnn_scratchpad_mode_t>(mode);
+}
+
+enum padding_kind {
+ zero = mkldnn_padding_zero
+};
+
+inline mkldnn_padding_kind_t convert_to_c(padding_kind kind) {
+ return static_cast<mkldnn_padding_kind_t>(kind);
+}
+
+enum prop_kind {
+ forward_training = mkldnn_forward_training,
+ forward_scoring = mkldnn_forward_scoring,
+ forward_inference = mkldnn_forward_inference,
+ forward = mkldnn_forward,
+ backward = mkldnn_backward,
+ backward_data = mkldnn_backward_data,
+ backward_weights = mkldnn_backward_weights,
+ backward_bias = mkldnn_backward_bias
+};
+
+inline mkldnn_prop_kind_t convert_to_c(prop_kind kind) {
+ return static_cast<mkldnn_prop_kind_t>(kind);
+}
+
+enum algorithm {
+ algorithm_undef = mkldnn_alg_kind_undef,
+ convolution_auto = mkldnn_convolution_auto,
+ convolution_direct = mkldnn_convolution_direct,
+ convolution_winograd = mkldnn_convolution_winograd,
+ deconvolution_direct = mkldnn_deconvolution_direct,
+ deconvolution_winograd = mkldnn_deconvolution_winograd,
+ eltwise_relu = mkldnn_eltwise_relu,
+ eltwise_tanh = mkldnn_eltwise_tanh,
+ eltwise_elu = mkldnn_eltwise_elu,
+ eltwise_square = mkldnn_eltwise_square,
+ eltwise_abs = mkldnn_eltwise_abs,
+ eltwise_sqrt = mkldnn_eltwise_sqrt,
+ eltwise_linear = mkldnn_eltwise_linear,
+ eltwise_bounded_relu = mkldnn_eltwise_bounded_relu,
+ eltwise_soft_relu = mkldnn_eltwise_soft_relu,
+ eltwise_logistic = mkldnn_eltwise_logistic,
+ lrn_across_channels = mkldnn_lrn_across_channels,
+ lrn_within_channel = mkldnn_lrn_within_channel,
+ pooling_max = mkldnn_pooling_max,
+ pooling_avg = mkldnn_pooling_avg,
+ pooling_avg_include_padding = mkldnn_pooling_avg_include_padding,
+ pooling_avg_exclude_padding = mkldnn_pooling_avg_exclude_padding,
+ vanilla_rnn = mkldnn_vanilla_rnn,
+ vanilla_lstm = mkldnn_vanilla_lstm,
+ vanilla_gru = mkldnn_vanilla_gru,
+ gru_linear_before_reset = mkldnn_gru_linear_before_reset
+};
+
+inline mkldnn_alg_kind_t convert_to_c(algorithm aalgorithm) {
+ return static_cast<mkldnn_alg_kind_t>(aalgorithm);
+}
+
+enum batch_normalization_flag {
+ use_global_stats = mkldnn_use_global_stats,
+ use_scale_shift = mkldnn_use_scaleshift,
+ fuse_bn_relu = mkldnn_fuse_bn_relu
+};
+
+inline mkldnn_batch_normalization_flag_t convert_to_c(
+ batch_normalization_flag aflag) {
+ return static_cast<mkldnn_batch_normalization_flag_t>(aflag);
+}
+
+enum rnn_direction {
+ unidirectional_left2right = mkldnn_unidirectional_left2right,
+ unidirectional_right2left = mkldnn_unidirectional_right2left,
+ unidirectional = mkldnn_unidirectional,
+ bidirectional_concat = mkldnn_bidirectional_concat,
+ bidirectional_sum = mkldnn_bidirectional_sum,
+};
+
+inline mkldnn_rnn_direction_t convert_to_c(rnn_direction adir) {
+ return static_cast<mkldnn_rnn_direction_t>(adir);
+}
+
+enum query {
+ undef = mkldnn_query_undef,
+
+ query_engine = mkldnn_query_engine,
+ primitive_kind = mkldnn_query_primitive_kind,
+
+ num_of_inputs_s32 = mkldnn_query_num_of_inputs_s32,
+ num_of_outputs_s32 = mkldnn_query_num_of_outputs_s32,
+
+ time_estimate_f64 = mkldnn_query_time_estimate_f64,
+ memory_consumption_s64 = mkldnn_query_memory_consumption_s64,
+
+ query_scratchpad_engine = mkldnn_query_scratchpad_engine,
+
+ impl_info_str = mkldnn_query_impl_info_str,
+
+ op_d = mkldnn_query_op_d,
+ convolution_d = mkldnn_query_convolution_d,
+ deconvolution_d = mkldnn_query_deconvolution_d,
+ shuffle_d = mkldnn_query_shuffle_d,
+ eltwise_d = mkldnn_query_eltwise_d,
+ softmax_d = mkldnn_query_softmax_d,
+ pooling_d = mkldnn_query_pooling_d,
+ lrn_d = mkldnn_query_lrn_d,
+ batch_normalization_d = mkldnn_query_batch_normalization_d,
+ inner_product_d = mkldnn_query_inner_product_d,
+ rnn_d = mkldnn_query_rnn_d,
+
+ src_md = mkldnn_query_src_md,
+ diff_src_md = mkldnn_query_diff_src_md,
+ weights_md = mkldnn_query_weights_md,
+ diff_weights_md = mkldnn_query_diff_weights_md,
+ dst_md = mkldnn_query_dst_md,
+ diff_dst_md = mkldnn_query_diff_dst_md,
+ workspace_md = mkldnn_query_workspace_md,
+ scratchpad_md = mkldnn_query_scratchpad_md,
+};
+
+inline mkldnn_query_t convert_to_c(query aquery) {
+ return static_cast<mkldnn_query_t>(aquery);
+}
+
+/// @}
+
+/// @addtogroup cpp_api_attr Attributes
+/// An extension for controlling primitive behavior.
+///
+/// @sa @ref c_api_attributes in @ref c_api
+/// @{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template <> struct handle_traits<mkldnn_post_ops_t> {
+ static constexpr auto destructor = &mkldnn_post_ops_destroy;
+};
+#endif
+
+struct post_ops: public handle<mkldnn_post_ops_t> {
+ post_ops() {
+ mkldnn_post_ops_t result;
+ error::wrap_c_api(mkldnn_post_ops_create(&result),
+ "could not create post operation sequence");
+ reset(result);
+ }
+
+ int len() const { return mkldnn_post_ops_len(get()); }
+
+ primitive::kind kind(int index) const {
+ error::wrap_c_api(
+ index < len() ? mkldnn_success : mkldnn_invalid_arguments,
+ "post_ops index is out of range");
+ return static_cast<primitive::kind>(mkldnn_post_ops_get_kind(get(),
+ index));
+ }
+
+ void append_sum(float scale = 1.) {
+ error::wrap_c_api(mkldnn_post_ops_append_sum(get(), scale),
+ "could not append sum");
+ }
+
+ void get_params_sum(int index, float &scale) const {
+ error::wrap_c_api(mkldnn_post_ops_get_params_sum(get(), index, &scale),
+ "could not get sum params");
+ }
+
+ void append_eltwise(float scale, algorithm alg, float alpha,
+ float beta) {
+ error::wrap_c_api(mkldnn_post_ops_append_eltwise(get(), scale,
+ convert_to_c(alg), alpha, beta),
+ "could not append eltwise");
+ }
+
+ void get_params_eltwise(int index, float &scale, algorithm &alg,
+ float &alpha, float &beta) const {
+ mkldnn_alg_kind_t c_alg;
+ error::wrap_c_api(mkldnn_post_ops_get_params_eltwise(get(), index,
+ &scale, &c_alg, &alpha, &beta),
+ "could not get eltwise params");
+ alg = static_cast<algorithm>(c_alg);
+ }
+};
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template <> struct handle_traits<mkldnn_primitive_attr_t> {
+ static constexpr auto destructor = &mkldnn_primitive_attr_destroy;
+};
+#endif
+
+struct primitive_attr: public handle<mkldnn_primitive_attr_t> {
+ primitive_attr() {
+ mkldnn_primitive_attr_t result;
+ error::wrap_c_api(mkldnn_primitive_attr_create(&result),
+ "could not create a primitive attr");
+ reset(result);
+ }
+
+ scratchpad_mode get_scratchpad_mode() const {
+ mkldnn_scratchpad_mode_t result;
+ error::wrap_c_api(mkldnn_primitive_attr_get_scratchpad_mode(
+ get(), &result), "could not get scratchpad mode");
+ return scratchpad_mode(result);
+ }
+
+ void set_scratchpad_mode(scratchpad_mode mode) {
+ error::wrap_c_api(mkldnn_primitive_attr_set_scratchpad_mode(
+ get(), mkldnn::convert_to_c(mode)),
+ "could not set scratchpad mode");
+ }
+
+ void get_output_scales(int &mask, std::vector<float> &scales) const
+ {
+ mkldnn_dim_t count;
+ int c_mask;
+ const float *c_scales;
+ error::wrap_c_api(mkldnn_primitive_attr_get_output_scales(get(),
+ &count, &c_mask, &c_scales),
+ "could not get int output scales");
+ scales.resize(count);
+
+ mask = c_mask;
+ for (mkldnn_dim_t c = 0; c < count; ++c)
+ scales[c] = c_scales[c];
+ }
+
+ void set_output_scales(int mask, const std::vector<float> &scales)
+ {
+ error::wrap_c_api(mkldnn_primitive_attr_set_output_scales(get(),
+ (mkldnn_dim_t)scales.size(), mask, &scales[0]),
+ "could not set int output scales");
+ }
+
+ const post_ops get_post_ops() const {
+ post_ops result;
+ const_mkldnn_post_ops_t c_result;
+ error::wrap_c_api(mkldnn_primitive_attr_get_post_ops(get(), &c_result),
+ "could not get post operation sequence");
+ result.reset(const_cast<mkldnn_post_ops_t>(c_result), true);
+ return result;
+ }
+
+ void set_post_ops(post_ops ops) {
+ error::wrap_c_api(mkldnn_primitive_attr_set_post_ops(get(), ops.get()),
+ "could not set post operation sequence");
+ }
+
+ void set_rnn_data_qparams(const float scale, const float shift)
+ {
+ error::wrap_c_api(mkldnn_primitive_attr_set_rnn_data_qparams(get(),
+ scale, shift), "could not set rnn data int scale/shift");
+ }
+
+ void set_rnn_weights_qparams(int mask, const std::vector<float> &scales)
+ {
+ error::wrap_c_api(mkldnn_primitive_attr_set_rnn_weights_qparams(get(),
+ (int)scales.size(), mask, &scales[0]),
+ "could not set rnn weights int scales");
+ }
+};
+
+/// @}
+
+/// @addtogroup cpp_api_engine Engine
+/// Engine operations.
+///
+/// @sa @ref c_api_engine in @ref c_api
+/// @{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template <> struct handle_traits<mkldnn_engine_t> {
+ static constexpr auto destructor = &mkldnn_engine_destroy;
+};
+#endif
+
+/// An execution engine.
+struct engine: public handle<mkldnn_engine_t> {
+ friend class primitive;
+ // gcc bug??? using handle::handle;
+
+ /// Kinds of engines.
+ enum kind {
+ /// An unspecified engine
+ any = mkldnn_any_engine,
+ /// CPU engine
+ cpu = mkldnn_cpu,
+ };
+
+ /// Returns the number of engines of a certain kind.
+ ///
+ /// @param akind The kind of engines to count.
+
+ static size_t get_count(kind akind) {
+ return mkldnn_engine_get_count(convert_to_c(akind));
+ }
+
+ /// Constructs an engine.
+ ///
+ /// @param akind The kind of engine to construct.
+ /// @param index The index of the engine. Must be less than the value
+ /// returned by #get_count() for this particular kind of engine.
+
+ engine(kind akind, size_t index) {
+ mkldnn_engine_t aengine;
+ error::wrap_c_api(
+ mkldnn_engine_create(&aengine,
+ convert_to_c(akind), index),
+ "could not create an engine");
+ reset(aengine);
+ }
+
+ explicit engine(const mkldnn_engine_t& aengine)
+ : handle(aengine, true) {}
+
+ engine(const handle<mkldnn_primitive_desc_t> &pd) {
+ mkldnn_engine_t engine_q;
+ error::wrap_c_api(
+ mkldnn_primitive_desc_query(pd.get(),
+ mkldnn::convert_to_c(query_engine), 0, &engine_q),
+ "could not get engine from primitive_desc");
+ reset(engine_q, true);
+ }
+
+ template <class primitive_desc>
+ static engine query(const primitive_desc &pd) {
+ mkldnn_engine_t engine_q;
+ error::wrap_c_api(
+ mkldnn_primitive_desc_query(pd.get(),
+ mkldnn::convert_to_c(query_engine), 0, &engine_q),
+ "could not get engine from primitive_desc");
+
+ return engine(engine_q);
+ }
+
+private:
+ static mkldnn_engine_kind_t convert_to_c(kind akind) {
+ return static_cast<mkldnn_engine_kind_t>(akind);
+ }
+};
+
+/// @}
+
+/// @addtogroup cpp_api_stream Stream
+/// Execution stream operations
+///
+/// @sa @ref c_api_stream in @ref c_api
+/// @{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template <> struct handle_traits<mkldnn_stream_t> {
+ static constexpr auto destructor = &mkldnn_stream_destroy;
+};
+#endif
+
+struct stream: public handle<mkldnn_stream_t> {
+ using handle::handle;
+
+ enum: unsigned {
+ default_flags = mkldnn_stream_default_flags,
+ };
+
+ /// Constructs a stream.
+ stream(const engine &aengine,
+ unsigned flags = static_cast<unsigned>(default_flags)) {
+ mkldnn_stream_t astream;
+ error::wrap_c_api(mkldnn_stream_create(&astream, aengine.get(), flags),
+ "could not create a stream");
+ reset(astream);
+ }
+};
+
+/// @}
+
+/// @addtogroup cpp_api_memory_related Memory and memory related operations
+/// @{
+
+/// @addtogroup cpp_api_memory Memory
+/// A primitive to describe and store data.
+///
+/// For more information, refer to @ref c_api_memory in @ref c_api.
+/// @{
+
+/// Memory that describes the data.
+struct memory: public handle<mkldnn_memory_t> {
+ public:
+ typedef mkldnn_dim_t dim;
+ typedef std::vector<dim> dims;
+
+ template <typename T> static void validate_dims(const std::vector<T> &v) {
+ if (v.size() > MKLDNN_MAX_NDIMS)
+ throw error(mkldnn_invalid_arguments, "invalid dimensions");
+ }
+
+ /// Data type specification. See #mkldnn_data_type_t for a detailed
+ /// description.
+ enum data_type {
+ data_undef = mkldnn_data_type_undef,
+ f32 = mkldnn_f32,
+ s32 = mkldnn_s32,
+ s8 = mkldnn_s8,
+ u8 = mkldnn_u8,
+ };
+
+ /// Memory format tag specification. See #mkldnn_format_tag_t
+ /// for a detailed description.
+ enum format_tag {
+ format_tag_undef = mkldnn_format_tag_undef,
+ any = mkldnn_format_tag_any,
+ a = mkldnn_a,
+ ab = mkldnn_ab,
+ abc = mkldnn_abc,
+ abcd = mkldnn_abcd,
+ abcde = mkldnn_abcde,
+ abcdef = mkldnn_abcdef,
+ abdec = mkldnn_abdec,
+ acb = mkldnn_acb,
+ acbde = mkldnn_acbde,
+ acdb = mkldnn_acdb,
+ acdeb = mkldnn_acdeb,
+ ba = mkldnn_ba,
+ bac = mkldnn_bac,
+ bacd = mkldnn_bacd,
+ bcda = mkldnn_bcda,
+ cba = mkldnn_cba,
+ cdba = mkldnn_cdba,
+ cdeba = mkldnn_cdeba,
+ decab = mkldnn_decab,
+ Abc16a = mkldnn_Abc16a,
+ ABc16a16b = mkldnn_ABc16a16b,
+ aBc16b = mkldnn_aBc16b,
+ ABc16b16a = mkldnn_ABc16b16a,
+ Abc4a = mkldnn_Abc4a,
+ aBc4b = mkldnn_aBc4b,
+ ABc4b16a4b = mkldnn_ABc4b16a4b,
+ ABc4b4a = mkldnn_ABc4b4a,
+ ABc8a16b2a = mkldnn_ABc8a16b2a,
+ ABc8a8b = mkldnn_ABc8a8b,
+ aBc8b = mkldnn_aBc8b,
+ ABc8b16a2b = mkldnn_ABc8b16a2b,
+ ABc8b8a = mkldnn_ABc8b8a,
+ Abcd16a = mkldnn_Abcd16a,
+ ABcd16a16b = mkldnn_ABcd16a16b,
+ aBcd16b = mkldnn_aBcd16b,
+ ABcd16b16a = mkldnn_ABcd16b16a,
+ aBCd16b16c = mkldnn_aBCd16b16c,
+ aBCd16c16b = mkldnn_aBCd16c16b,
+ Abcd4a = mkldnn_Abcd4a,
+ aBcd4b = mkldnn_aBcd4b,
+ ABcd4b16a4b = mkldnn_ABcd4b16a4b,
+ ABcd4b4a = mkldnn_ABcd4b4a,
+ aBCd4c16b4c = mkldnn_aBCd4c16b4c,
+ aBCd4c4b = mkldnn_aBCd4c4b,
+ ABcd8a16b2a = mkldnn_ABcd8a16b2a,
+ ABcd8a8b = mkldnn_ABcd8a8b,
+ aBcd8b = mkldnn_aBcd8b,
+ ABcd8b16a2b = mkldnn_ABcd8b16a2b,
+ aBCd8b16c2b = mkldnn_aBCd8b16c2b,
+ ABcd8b8a = mkldnn_ABcd8b8a,
+ aBCd8b8c = mkldnn_aBCd8b8c,
+ aBCd8c16b2c = mkldnn_aBCd8c16b2c,
+ aBCd8c8b = mkldnn_aBCd8c8b,
+ Abcde16a = mkldnn_Abcde16a,
+ ABcde16a16b = mkldnn_ABcde16a16b,
+ aBcde16b = mkldnn_aBcde16b,
+ ABcde16b16a = mkldnn_ABcde16b16a,
+ aBCde16b16c = mkldnn_aBCde16b16c,
+ aBCde16c16b = mkldnn_aBCde16c16b,
+ aBCde2c8b4c = mkldnn_aBCde2c8b4c,
+ Abcde4a = mkldnn_Abcde4a,
+ aBcde4b = mkldnn_aBcde4b,
+ ABcde4b4a = mkldnn_ABcde4b4a,
+ aBCde4b4c = mkldnn_aBCde4b4c,
+ aBCde4c16b4c = mkldnn_aBCde4c16b4c,
+ aBCde4c4b = mkldnn_aBCde4c4b,
+ Abcde8a = mkldnn_Abcde8a,
+ ABcde8a8b = mkldnn_ABcde8a8b,
+ aBcde8b = mkldnn_aBcde8b,
+ ABcde8b16a2b = mkldnn_ABcde8b16a2b,
+ aBCde8b16c2b = mkldnn_aBCde8b16c2b,
+ ABcde8b8a = mkldnn_ABcde8b8a,
+ aBCde8b8c = mkldnn_aBCde8b8c,
+ aBCde8c16b2c = mkldnn_aBCde8c16b2c,
+ aBCde8c8b = mkldnn_aBCde8c8b,
+ aBcdef16b = mkldnn_aBcdef16b,
+ aBCdef16b16c = mkldnn_aBCdef16b16c,
+ aBCdef16c16b = mkldnn_aBCdef16c16b,
+ aBcdef4b = mkldnn_aBcdef4b,
+ aBCdef4c4b = mkldnn_aBCdef4c4b,
+ aBCdef8b8c = mkldnn_aBCdef8b8c,
+ aBCdef8c16b2c = mkldnn_aBCdef8c16b2c,
+ aBCdef8c8b = mkldnn_aBCdef8c8b,
+ aBdc16b = mkldnn_aBdc16b,
+ aBdc4b = mkldnn_aBdc4b,
+ aBdc8b = mkldnn_aBdc8b,
+ aBdec16b = mkldnn_aBdec16b,
+ aBdec4b = mkldnn_aBdec4b,
+ aBdec8b = mkldnn_aBdec8b,
+ aBdefc16b = mkldnn_aBdefc16b,
+ aBdefc4b = mkldnn_aBdefc4b,
+ aBdefc8b = mkldnn_aBdefc8b,
+ Acb16a = mkldnn_Acb16a,
+ Acb4a = mkldnn_Acb4a,
+ Acb8a = mkldnn_Acb8a,
+ aCBd16b16c = mkldnn_aCBd16b16c,
+ aCBde16b16c = mkldnn_aCBde16b16c,
+ Acdb16a = mkldnn_Acdb16a,
+ Acdb4a = mkldnn_Acdb4a,
+ Acdb8a = mkldnn_Acdb8a,
+ Acdeb16a = mkldnn_Acdeb16a,
+ Acdeb4a = mkldnn_Acdeb4a,
+ Acdeb8a = mkldnn_Acdeb8a,
+ BAc16a16b = mkldnn_BAc16a16b,
+ BAcd16a16b = mkldnn_BAcd16a16b,
+ format_tag_last = mkldnn_format_tag_last,
+
+ x = mkldnn_x,
+ nc = mkldnn_nc,
+ cn = mkldnn_cn,
+ ncw = mkldnn_ncw,
+ nwc = mkldnn_nwc,
+ nchw = mkldnn_nchw,
+ nhwc = mkldnn_nhwc,
+ chwn = mkldnn_chwn,
+ ncdhw = mkldnn_ncdhw,
+ ndhwc = mkldnn_ndhwc,
+ oi = mkldnn_oi,
+ io = mkldnn_io,
+ oiw = mkldnn_oiw,
+ wio = mkldnn_wio,
+ oihw = mkldnn_oihw,
+ hwio = mkldnn_hwio,
+ ihwo = mkldnn_ihwo,
+ iohw = mkldnn_iohw,
+ oidhw = mkldnn_oidhw,
+ dhwio = mkldnn_dhwio,
+ goiw = mkldnn_goiw,
+ goihw = mkldnn_goihw,
+ hwigo = mkldnn_hwigo,
+ giohw = mkldnn_giohw,
+ goidhw = mkldnn_goidhw,
+ tnc = mkldnn_tnc,
+ ntc = mkldnn_ntc,
+ ldsnc = mkldnn_ldsnc,
+ ldigo = mkldnn_ldigo,
+ ldgoi = mkldnn_ldgoi,
+ ldgo = mkldnn_ldgo,
+ nCdhw16c = mkldnn_nCdhw16c,
+ nCdhw4c = mkldnn_nCdhw4c,
+ nCdhw8c = mkldnn_nCdhw8c,
+ nChw16c = mkldnn_nChw16c,
+ nChw4c = mkldnn_nChw4c,
+ nChw8c = mkldnn_nChw8c,
+ nCw16c = mkldnn_nCw16c,
+ nCw4c = mkldnn_nCw4c,
+ nCw8c = mkldnn_nCw8c,
+ IOw16o16i = mkldnn_IOw16o16i,
+ OIw16i16o = mkldnn_OIw16i16o,
+ OIw16o16i = mkldnn_OIw16o16i,
+ Oiw16o = mkldnn_Oiw16o,
+ OIw4i16o4i = mkldnn_OIw4i16o4i,
+ OIw4i4o = mkldnn_OIw4i4o,
+ Oiw4o = mkldnn_Oiw4o,
+ OIw8i16o2i = mkldnn_OIw8i16o2i,
+ OIw8i8o = mkldnn_OIw8i8o,
+ OIw8o16i2o = mkldnn_OIw8o16i2o,
+ OIw8o8i = mkldnn_OIw8o8i,
+ Owi16o = mkldnn_Owi16o,
+ Owi4o = mkldnn_Owi4o,
+ Owi8o = mkldnn_Owi8o,
+ IOhw16o16i = mkldnn_IOhw16o16i,
+ Ohwi16o = mkldnn_Ohwi16o,
+ Ohwi4o = mkldnn_Ohwi4o,
+ Ohwi8o = mkldnn_Ohwi8o,
+ OIhw16i16o = mkldnn_OIhw16i16o,
+ OIhw16o16i = mkldnn_OIhw16o16i,
+ Oihw16o = mkldnn_Oihw16o,
+ OIhw4i16o4i = mkldnn_OIhw4i16o4i,
+ OIhw4i4o = mkldnn_OIhw4i4o,
+ Oihw4o = mkldnn_Oihw4o,
+ OIhw8i16o2i = mkldnn_OIhw8i16o2i,
+ OIhw8i8o = mkldnn_OIhw8i8o,
+ OIhw8o16i2o = mkldnn_OIhw8o16i2o,
+ OIhw8o8i = mkldnn_OIhw8o8i,
+ Odhwi16o = mkldnn_Odhwi16o,
+ Odhwi4o = mkldnn_Odhwi4o,
+ Odhwi8o = mkldnn_Odhwi8o,
+ OIdhw16i16o = mkldnn_OIdhw16i16o,
+ OIdhw16o16i = mkldnn_OIdhw16o16i,
+ Oidhw16o = mkldnn_Oidhw16o,
+ OIdhw4i4o = mkldnn_OIdhw4i4o,
+ Oidhw4o = mkldnn_Oidhw4o,
+ OIdhw8i16o2i = mkldnn_OIdhw8i16o2i,
+ OIdhw8i8o = mkldnn_OIdhw8i8o,
+ OIdhw8o8i = mkldnn_OIdhw8o8i,
+ gIOw16o16i = mkldnn_gIOw16o16i,
+ gOIw16i16o = mkldnn_gOIw16i16o,
+ gOIw16o16i = mkldnn_gOIw16o16i,
+ gOiw16o = mkldnn_gOiw16o,
+ gOIw4i16o4i = mkldnn_gOIw4i16o4i,
+ gOIw4i4o = mkldnn_gOIw4i4o,
+ gOiw4o = mkldnn_gOiw4o,
+ gOIw8i16o2i = mkldnn_gOIw8i16o2i,
+ gOIw8i8o = mkldnn_gOIw8i8o,
+ gOIw8o16i2o = mkldnn_gOIw8o16i2o,
+ gOIw8o8i = mkldnn_gOIw8o8i,
+ gOwi16o = mkldnn_gOwi16o,
+ gOwi4o = mkldnn_gOwi4o,
+ gOwi8o = mkldnn_gOwi8o,
+ gIOhw16o16i = mkldnn_gIOhw16o16i,
+ gOhwi16o = mkldnn_gOhwi16o,
+ gOhwi4o = mkldnn_gOhwi4o,
+ gOhwi8o = mkldnn_gOhwi8o,
+ Goihw16g = mkldnn_Goihw16g,
+ gOIhw16i16o = mkldnn_gOIhw16i16o,
+ gOIhw16o16i = mkldnn_gOIhw16o16i,
+ gOihw16o = mkldnn_gOihw16o,
+ gOIhw2i8o4i = mkldnn_gOIhw2i8o4i,
+ gOIhw4i16o4i = mkldnn_gOIhw4i16o4i,
+ gOIhw4i4o = mkldnn_gOIhw4i4o,
+ gOIhw4o4i = mkldnn_gOIhw4o4i,
+ gOihw4o = mkldnn_gOihw4o,
+ Goihw8g = mkldnn_Goihw8g,
+ gOIhw8i16o2i = mkldnn_gOIhw8i16o2i,
+ gOIhw8i8o = mkldnn_gOIhw8i8o,
+ gOIhw8o16i2o = mkldnn_gOIhw8o16i2o,
+ gOIhw8o8i = mkldnn_gOIhw8o8i,
+ gOdhwi16o = mkldnn_gOdhwi16o,
+ gOdhwi4o = mkldnn_gOdhwi4o,
+ gOdhwi8o = mkldnn_gOdhwi8o,
+ gOIdhw16i16o = mkldnn_gOIdhw16i16o,
+ gOIdhw16o16i = mkldnn_gOIdhw16o16i,
+ gOidhw16o = mkldnn_gOidhw16o,
+ gOIdhw4i4o = mkldnn_gOIdhw4i4o,
+ gOidhw4o = mkldnn_gOidhw4o,
+ gOIdhw8i16o2i = mkldnn_gOIdhw8i16o2i,
+ gOIdhw8i8o = mkldnn_gOIdhw8i8o,
+ gOIdhw8o8i = mkldnn_gOIdhw8o8i,
+ };
+
+ /// A memory descriptor.
+ struct desc {
+ friend struct memory;
+ /// The underlying C API data structure.
+ mkldnn_memory_desc_t data;
+
+ /// Constructs a zero memory descriptor
+ desc(): data() {}
+
+ /// Constructs a memory descriptor.
+ ///
+ /// @param adims Data dimensions
+ /// @param adata_type Data precision/type.
+ /// @param aformat Data layout format tag.
+ desc(const dims &adims, data_type adata_type,
+ format_tag aformat) {
+ validate_dims(adims);
+ error::wrap_c_api(mkldnn_memory_desc_init_by_tag(&data, (int)adims.size(),
+ adims.size() == 0 ? nullptr : &adims[0],
+ convert_to_c(adata_type), convert_to_c(aformat)),
+ "could not initialize a memory descriptor");
+ }
+
+ /// Constructs a memory descriptor from a C API data structure.
+ ///
+ /// @param adata A C API #mkldnn_memory_desc_t structure.
+ desc(const mkldnn_memory_desc_t &adata): data(adata) {}
+
+ /// Constructs a sub-memory descriptor
+ //
+ /// @param adims Sizes of a sub-memory
+ /// @param offsets Offsets of a sub-memory
+ desc submemory_desc(const dims &adims, const dims &offsets) {
+ mkldnn_memory_desc_t sub_md;
+ error::wrap_c_api(mkldnn_memory_desc_init_submemory(&sub_md,
+ &data, &adims[0], &offsets[0]),
+ "could not initialize a sub-memory");
+ return desc(sub_md);
+ }
+
+ /// Returns the number of bytes required to allocate the memory described
+ /// including the padding area.
+ size_t get_size() const { return mkldnn_memory_desc_get_size(&data); }
+
+ bool operator==(const desc &other) const {
+ return mkldnn_memory_desc_equal(&data, &other.data) != 0;
+ }
+
+ bool operator!=(const desc &other) const { return !operator==(other); }
+ };
+
+ /// Constructs a memory.
+ ///
+ /// @param md Memory descriptor.
+ /// @param aengine Engine.
+ /// @param ahandle Native handle.
+ memory(const desc &md, const engine &aengine, void *ahandle) {
+ mkldnn_memory_t result;
+ error::wrap_c_api(mkldnn_memory_create(&result, &md.data,
+ aengine.get(), ahandle), "could not create a memory");
+ reset(result);
+ }
+
+ /// Constructs a memory.
+ ///
+ /// @param md Memory descriptor.
+ /// @param aengine Engine.
+ memory(const desc &md, const engine &aengine)
+ : memory(md, aengine, MKLDNN_NATIVE_HANDLE_ALLOCATE) {}
+
+ /// Returns the descriptor of the memory.
+ desc get_desc() const {
+ const mkldnn_memory_desc_t *cdesc;
+ error::wrap_c_api(mkldnn_memory_get_memory_desc(get(), &cdesc),
+ "could not get memory descriptor from a memory");
+ return desc(*cdesc);
+ }
+
+ /// Returns the engine of the memory.
+ engine get_engine() const {
+ mkldnn_engine_t engine_q;
+ error::wrap_c_api(mkldnn_memory_get_engine(get(), &engine_q),
+ "could not get engine from a memory");
+ return engine(engine_q);
+ }
+
+ /// Returns a handle of the data contained in the memory.
+ ///
+ /// On the CPU engine, this is a pointer to the allocated memory.
+ void *get_data_handle() const {
+ void *handle;
+ error::wrap_c_api(mkldnn_memory_get_data_handle(get(), &handle),
+ "could not get native handle");
+ return handle;
+ }
+
+ void set_data_handle(void *handle) const {
+ error::wrap_c_api(mkldnn_memory_set_data_handle(get(), handle),
+ "could not set native handle");
+ }
+
+ // Must go away or be private:
+ static mkldnn_data_type_t convert_to_c(data_type adata_type) {
+ return static_cast<mkldnn_data_type_t>(adata_type);
+ }
+ static mkldnn_format_tag_t convert_to_c(format_tag aformat) {
+ return static_cast<mkldnn_format_tag_t>(aformat);
+ }
+};
+
+inline bool operator==(mkldnn_data_type_t a, memory::data_type b) {
+ return a == memory::convert_to_c(b);
+}
+inline bool operator!=(mkldnn_data_type_t a, memory::data_type b) {
+ return !(a == b);
+}
+inline bool operator==(memory::data_type a, mkldnn_data_type_t b) {
+ return b == a;
+}
+inline bool operator!=(memory::data_type a, mkldnn_data_type_t b) {
+ return !(a == b);
+}
+
+inline bool operator==(mkldnn_format_tag_t a, memory::format_tag b) {
+ return a == memory::convert_to_c(b);
+}
+inline bool operator!=(mkldnn_format_tag_t a, memory::format_tag b) {
+ return !(a == b);
+}
+inline bool operator==(memory::format_tag a, mkldnn_format_tag_t b) {
+ return b == a;
+}
+inline bool operator!=(memory::format_tag a, mkldnn_format_tag_t b) {
+ return !(a == b);
+}
+
+/// @}
+
+/// @addtogroup cpp_api_reorder Reorder
+/// A primitive to copy data between memory formats.
+///
+/// @sa @ref c_api_reorder in @ref c_api
+/// @{
+
+struct reorder : public primitive {
+ struct primitive_desc : public handle<mkldnn_primitive_desc_t> {
+ primitive_desc(const engine &src_engine, const memory::desc &src_md,
+ const engine &dst_engine, const memory::desc &dst_md,
+ const primitive_attr &aattr) {
+ mkldnn_primitive_desc_t result;
+ error::wrap_c_api(mkldnn_reorder_primitive_desc_create(&result,
+ src_engine.get(), &src_md.data,
+ dst_engine.get(), &dst_md.data, aattr.get()),
+ "could not create a reorder primitive descriptor");
+ reset(result);
+ }
+
+ primitive_desc(const engine &src_engine, const memory::desc &src_md,
+ const engine &dst_engine, const memory::desc &dst_md) {
+ mkldnn_primitive_desc_t result;
+ error::wrap_c_api(mkldnn_reorder_primitive_desc_create(&result,
+ src_engine.get(), &src_md.data,
+ dst_engine.get(), &dst_md.data, nullptr),
+ "could not create a reorder primitive descriptor");
+ reset(result);
+ }
+
+ primitive_desc(const memory &src, const memory &dst,
+ const primitive_attr &aattr) {
+ mkldnn_primitive_desc_t result;
+ auto src_md = src.get_desc();
+ auto dst_md = dst.get_desc();
+ error::wrap_c_api(mkldnn_reorder_primitive_desc_create(&result,
+ src.get_engine().get(), &src_md.data,
+ dst.get_engine().get(), &dst_md.data, aattr.get()),
+ "could not create a reorder primitive descriptor");
+ reset(result);
+ }
+
+ primitive_desc(const memory &src, const memory &dst) {
+ mkldnn_primitive_desc_t result;
+ auto src_md = src.get_desc();
+ auto dst_md = dst.get_desc();
+ error::wrap_c_api(mkldnn_reorder_primitive_desc_create(&result,
+ src.get_engine().get(), &src_md.data,
+ dst.get_engine().get(), &dst_md.data, nullptr),
+ "could not create a reorder primitive descriptor");
+ reset(result);
+ }
+
+ memory::desc scratchpad_desc() const {
+ const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md(
+ get(), mkldnn::convert_to_c(scratchpad_md), 0);
+ if (cdesc == nullptr)
+ return memory::desc();
+ return memory::desc(*cdesc);
+ }
+
+ engine scratchpad_engine() {
+ mkldnn_engine_t engine_q;
+ error::wrap_c_api(
+ mkldnn_primitive_desc_query(get(),
+ mkldnn::convert_to_c(query_scratchpad_engine), 0, &engine_q),
+ "could not get scratchpad engine from reorder primitive_desc");
+
+ return engine(engine_q);
+ }
+
+ engine get_engine() { return engine::query(*this); }
+ };
+
+ reorder(const primitive_desc &pd): primitive(pd.get()) {}
+
+ reorder(const memory &src, const memory &dst):
+ primitive(primitive_desc(src, dst).get()) {}
+
+ void execute(stream astream, memory &src, memory &dst) {
+ primitive::execute(astream,
+ {{MKLDNN_ARG_FROM, src}, {MKLDNN_ARG_TO, dst}});
+ }
+};
+
+/// @}
+
+/// @addtogroup cpp_api_concat Concat
+/// A primitive to concatenate data by arbitrary dimension.
+///
+/// @sa @ref c_api_concat in @ref c_api
+/// @{
+
+struct concat : public primitive {
+ struct primitive_desc : public handle<mkldnn_primitive_desc_t> {
+ std::vector<mkldnn_memory_desc_t> cpp_to_c(
+ const std::vector<memory::desc> &srcs) {
+ std::vector<mkldnn_memory_desc_t> c_api_srcs;
+ c_api_srcs.reserve(srcs.size());
+ for (const auto &s : srcs) c_api_srcs.push_back(s.data);
+ return c_api_srcs;
+ }
+
+ primitive_desc(const memory::desc &dst, int concat_dimension,
+ const std::vector<memory::desc> &srcs, const engine &aengine) {
+ auto c_api_srcs = cpp_to_c(srcs);
+
+ mkldnn_primitive_desc_t result;
+ error::wrap_c_api(mkldnn_concat_primitive_desc_create(
+ &result, &dst.data, (int)c_api_srcs.size(),
+ concat_dimension, &c_api_srcs[0], nullptr, aengine.get()),
+ "could not create a concat primitive descriptor");
+ reset(result);
+ }
+
+ primitive_desc(int concat_dimension,
+ const std::vector<memory::desc> &srcs, const engine &aengine) {
+ auto c_api_srcs = cpp_to_c(srcs);
+
+ mkldnn_primitive_desc_t result;
+ error::wrap_c_api(mkldnn_concat_primitive_desc_create(
+ &result, nullptr, (int)c_api_srcs.size(),
+ concat_dimension, &c_api_srcs[0], nullptr, aengine.get()),
+ "could not create a concat primitive descriptor");
+ reset(result);
+ }
+
+ memory::desc dst_desc() const {
+ const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md(
+ get(), mkldnn::convert_to_c(dst_md), 0);
+ error::wrap_c_api(
+ cdesc == nullptr ? mkldnn_runtime_error : mkldnn_success,
+ "could not get a dst memory descriptor");
+ return memory::desc(*cdesc);
+ }
+
+ memory::desc scratchpad_desc() const {
+ const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md(
+ get(), mkldnn::convert_to_c(scratchpad_md), 0);
+ if (cdesc == nullptr)
+ return memory::desc();
+ return memory::desc(*cdesc);
+ }
+
+ engine get_engine() { return engine::query(*this); }
+ };
+
+ concat(const primitive_desc &pd): primitive(pd.get()) {}
+};
+
+/// @}
+
+/// @addtogroup cpp_api_sum Sum
+/// A primitive to sum data.
+///
+/// @sa @ref c_api_sum in @ref c_api
+/// @{
+
+struct sum : public primitive {
+ struct primitive_desc : public handle<mkldnn_primitive_desc_t> {
+ std::vector<mkldnn_memory_desc_t> cpp_to_c(
+ const std::vector<memory::desc> &srcs) {
+ std::vector<mkldnn_memory_desc_t> c_api_srcs;
+ c_api_srcs.reserve(srcs.size());
+ for (const auto &s : srcs) c_api_srcs.push_back(s.data);
+ return c_api_srcs;
+ }
+
+ primitive_desc(const memory::desc &dst,
+ const std::vector<float> &scales,
+ const std::vector<memory::desc> &srcs, const engine &aengine) {
+ error::wrap_c_api(scales.size() == srcs.size()
+ ? mkldnn_success : mkldnn_invalid_arguments,
+ "number of scales not equal to number of srcs");
+
+ auto c_api_srcs = cpp_to_c(srcs);
+
+ mkldnn_primitive_desc_t result;
+ error::wrap_c_api(mkldnn_sum_primitive_desc_create(
+ &result, &dst.data, (int)c_api_srcs.size(),
+ &scales[0], &c_api_srcs[0], nullptr, aengine.get()),
+ "could not create a sum primitive descriptor");
+ reset(result);
+ }
+
+ primitive_desc(const std::vector<float> &scales,
+ const std::vector<memory::desc> &srcs, const engine &aengine) {
+ error::wrap_c_api(scales.size() == srcs.size()
+ ? mkldnn_success : mkldnn_invalid_arguments,
+ "number of scales not equal to number of srcs");
+
+ auto c_api_srcs = cpp_to_c(srcs);
+ mkldnn_primitive_desc_t result;
+ error::wrap_c_api(mkldnn_sum_primitive_desc_create(&result,
+ nullptr, (int)c_api_srcs.size(), &scales[0],
+ &c_api_srcs[0], nullptr, aengine.get()),
+ "could not create a sum primitive descriptor");
+ reset(result);
+ }
+
+ memory::desc dst_desc() const {
+ const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md(
+ get(), mkldnn::convert_to_c(dst_md), 0);
+ error::wrap_c_api(
+ cdesc == nullptr ? mkldnn_runtime_error : mkldnn_success,
+ "could not get a dst memory descriptor");
+ return memory::desc(*cdesc);
+ }
+
+ memory::desc scratchpad_desc() const {
+ const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md(
+ get(), mkldnn::convert_to_c(scratchpad_md), 0);
+ if (cdesc == nullptr)
+ return memory::desc();
+ return memory::desc(*cdesc);
+ }
+
+ engine get_engine() { return engine::query(*this); }
+ };
+
+ sum(const primitive_desc &pd): primitive(pd.get()) {}
+};
+
+/// @}
+
+/// @}
+
+/// @addtogroup cpp_api_primitives Primitives
+/// @{
+
+/// @addtogroup cpp_api_primitive_descriptors Primitive descriptors
+/// @{
+
+/// A base class for all primitive descriptors.
+struct primitive_desc : public handle<mkldnn_primitive_desc_t> {
+ primitive_desc(const_mkldnn_op_desc_t desc, const primitive_attr *attr,
+ const engine &e, const_mkldnn_primitive_desc_t hint_fwd_pd) {
+ mkldnn_primitive_desc_iterator_t iterator = nullptr;
+ mkldnn_status_t status = mkldnn_primitive_desc_iterator_create(
+ &iterator, desc, attr ? attr->get() : nullptr, e.get(),
+ hint_fwd_pd);
+ error::wrap_c_api(status,
+ "could not create a primitive descriptor iterator");
+ pd_iterator.reset(iterator);
+ fetch_impl();
+ }
+
+ engine get_engine() { return engine::query(*this); }
+
+ primitive_attr get_primitive_attr() const {
+ const_mkldnn_primitive_attr_t const_cattr;
+ error::wrap_c_api(mkldnn_primitive_desc_get_attr(get(), &const_cattr),
+ "could not get attributes");
+ mkldnn_primitive_attr_t cattr;
+ error::wrap_c_api(mkldnn_primitive_attr_clone(&cattr, const_cattr),
+ "could not clone attributes");
+
+ primitive_attr attr;
+ attr.reset(cattr);
+ return attr;
+ }
+
+ /// Returns implementation name
+ const char *impl_info_str() const {
+ const char *res;
+ error::wrap_c_api(mkldnn_primitive_desc_query(get(),
+ mkldnn_query_impl_info_str, 0, &res),
+ "could not query implementation info string");
+ return res;
+ }
+
+ /// Queries the memory::dim value (same as int64_t)
+ memory::dim query_s64(query q) const {
+ memory::dim res;
+ mkldnn_status_t status = mkldnn_primitive_desc_query(get(),
+ mkldnn::convert_to_c(q), 0, &res);
+ return status == mkldnn_success ? res : 0;
+ }
+
+ /// Advances the next implementation for the given op descriptor.
+ ///
+ /// Returns:
+ /// - @c true on success
+ /// - @c false if the last implementation reached, and
+ /// the primitive descriptor itself is kept unchanged
+ bool next_impl() {
+ mkldnn_status_t status = mkldnn_primitive_desc_iterator_next(
+ pd_iterator.get());
+ if (status == mkldnn_iterator_ends) return false;
+ error::wrap_c_api(status, "primitive descriptor iterator next failed");
+
+ fetch_impl();
+ return true;
+ }
+
+ /// Queries and returns requested memory descriptor.
+ memory::desc query_md(query what, int idx = 0) const {
+ std::vector<query> valid_q{src_md, diff_src_md, weights_md,
+ diff_weights_md, dst_md, diff_dst_md, workspace_md, scratchpad_md};
+ if (!std::any_of(valid_q.cbegin(), valid_q.cend(),
+ [=](query q) { return what == q; }))
+ throw error(mkldnn_invalid_arguments, "invalid memory query");
+
+ const mkldnn_memory_desc_t *cdesc = mkldnn_primitive_desc_query_md(
+ get(), mkldnn::convert_to_c(what), idx);
+ if (cdesc == nullptr) return memory::desc();
+
+ return memory::desc(*cdesc);
+ }
+
+ // register specialized queries, e.g. src_desc()
+# define REG_QUERY_MD(name, what, idx) \
+ memory::desc name ## _desc() const { return query_md(what ## _md, idx); }
+
+ private:
+ handle<mkldnn_primitive_desc_iterator_t> pd_iterator;
+ void fetch_impl() {
+ mkldnn_primitive_desc_t pd = mkldnn_primitive_desc_iterator_fetch(
+ pd_iterator.get());
+ error::wrap_c_api(pd != nullptr ? mkldnn_success : mkldnn_runtime_error,
+ "could not fetch a primitive descriptor from the iterator");
+ reset(pd);
+ }
+};
+
+/// @}
+
+/// @addtogroup cpp_api_convolution Convolution
+/// A primitive to compute convolution using different algorithms.
+///
+/// @sa @ref c_api_convolution in @ref c_api
+/// @{
+
+struct convolution_forward: public primitive {
+ struct desc {
+ mkldnn_convolution_desc_t data;
+ desc(prop_kind aprop_kind, algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &bias_desc,
+ const memory::desc &dst_desc,
+ const memory::dims strides,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_convolution_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm),
+ &src_desc.data, &weights_desc.data, &bias_desc.data,
+ &dst_desc.data, &strides[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a convolution forward descriptor");
+ }
+ desc(prop_kind aprop_kind, algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &dst_desc,
+ const memory::dims strides,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_convolution_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm),
+ &src_desc.data, &weights_desc.data, nullptr,
+ &dst_desc.data, &strides[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a convolution forward descriptor");
+ }
+ desc(prop_kind aprop_kind, algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &bias_desc,
+ const memory::desc &dst_desc,
+ const memory::dims strides,
+ const memory::dims dilates,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(dilates);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(
+ mkldnn_dilated_convolution_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm),
+ &src_desc.data, &weights_desc.data, &bias_desc.data,
+ &dst_desc.data, &strides[0], &dilates[0],
+ &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a dilated convolution forward descriptor");
+ }
+ desc(prop_kind aprop_kind, algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &dst_desc,
+ const memory::dims strides,
+ const memory::dims dilates,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(dilates);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(
+ mkldnn_dilated_convolution_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm),
+ &src_desc.data, &weights_desc.data, nullptr,
+ &dst_desc.data, &strides[0], &dilates[0],
+ &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a dilated convolution forward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(weights, weights, 0);
+ REG_QUERY_MD(bias, weights, 1);
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ convolution_forward(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct convolution_backward_data : public primitive {
+ struct desc {
+ mkldnn_convolution_desc_t data;
+ desc(algorithm aalgorithm,
+ const memory::desc &diff_src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_convolution_backward_data_desc_init(
+ &data, convert_to_c(aalgorithm), &diff_src_desc.data,
+ &weights_desc.data, &diff_dst_desc.data,
+ &strides[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a convolution backward data descriptor");
+ }
+ desc(algorithm aalgorithm,
+ const memory::desc &diff_src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims dilates,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(dilates);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(
+ mkldnn_dilated_convolution_backward_data_desc_init(
+ &data, convert_to_c(aalgorithm), &diff_src_desc.data,
+ &weights_desc.data, &diff_dst_desc.data,
+ &strides[0], &dilates[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a convolution backward data descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const convolution_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const convolution_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(diff_src, diff_src, 0);
+ REG_QUERY_MD(weights, weights, 0);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ convolution_backward_data(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct convolution_backward_weights : public primitive {
+ struct desc {
+ mkldnn_convolution_desc_t data;
+ desc(algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &diff_weights_desc,
+ const memory::desc &diff_bias_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_convolution_backward_weights_desc_init(
+ &data, convert_to_c(aalgorithm), &src_desc.data,
+ &diff_weights_desc.data, &diff_bias_desc.data,
+ &diff_dst_desc.data,
+ &strides[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a convolution backward weights descriptor");
+ }
+ desc(algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &diff_weights_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_convolution_backward_weights_desc_init(
+ &data, convert_to_c(aalgorithm), &src_desc.data,
+ &diff_weights_desc.data, nullptr, &diff_dst_desc.data,
+ &strides[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a convolution backward weights descriptor");
+ }
+ desc(algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &diff_weights_desc,
+ const memory::desc &diff_bias_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims dilates,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(dilates);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_dilated_convolution_backward_weights_desc_init(
+ &data, convert_to_c(aalgorithm), &src_desc.data,
+ &diff_weights_desc.data, &diff_bias_desc.data,
+ &diff_dst_desc.data,
+ &strides[0], &dilates[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a convolution backward weights descriptor");
+ }
+ desc(algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &diff_weights_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims dilates,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(dilates);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_dilated_convolution_backward_weights_desc_init(
+ &data, convert_to_c(aalgorithm), &src_desc.data,
+ &diff_weights_desc.data, nullptr, &diff_dst_desc.data,
+ &strides[0], &dilates[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a convolution backward weights descriptor");
+ }
+
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const convolution_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const convolution_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(diff_weights, diff_weights, 0);
+ REG_QUERY_MD(diff_bias, diff_weights, 1);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ convolution_backward_weights(const primitive_desc &pd): primitive(pd) {}
+};
+
+/// @}
+//
+/// @addtogroup cpp_api_deconvolution Deconvolution
+/// A primitive to compute deconvolution using different algorithms.
+///
+/// @sa @ref c_api_deconvolution in @ref c_api
+/// @{
+
+struct deconvolution_forward: public primitive {
+ struct desc {
+ mkldnn_deconvolution_desc_t data;
+ desc(prop_kind aprop_kind, algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &bias_desc,
+ const memory::desc &dst_desc,
+ const memory::dims strides,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_deconvolution_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm),
+ &src_desc.data, &weights_desc.data, &bias_desc.data,
+ &dst_desc.data, &strides[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a deconvolution forward descriptor");
+ }
+ desc(prop_kind aprop_kind, algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &dst_desc,
+ const memory::dims strides,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_deconvolution_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm),
+ &src_desc.data, &weights_desc.data, nullptr,
+ &dst_desc.data, &strides[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a deconvolution forward descriptor");
+ }
+ desc(prop_kind aprop_kind, algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &bias_desc,
+ const memory::desc &dst_desc,
+ const memory::dims strides,
+ const memory::dims dilates,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(dilates);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_dilated_deconvolution_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm),
+ &src_desc.data, &weights_desc.data, &bias_desc.data,
+ &dst_desc.data, &strides[0], &dilates[0], &padding_l[0],
+ &padding_r[0], mkldnn::convert_to_c(apadding_kind)),
+ "could not create a dilated deconvolution forward descriptor");
+ }
+ desc(prop_kind aprop_kind, algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &dst_desc,
+ const memory::dims strides,
+ const memory::dims dilates,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(dilates);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_dilated_deconvolution_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm),
+ &src_desc.data, &weights_desc.data, nullptr,
+ &dst_desc.data, &strides[0], &dilates[0], &padding_l[0],
+ &padding_r[0], mkldnn::convert_to_c(apadding_kind)),
+ "could not create a dilated deconvolution forward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(weights, weights, 0);
+ REG_QUERY_MD(bias, weights, 1);
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ deconvolution_forward(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct deconvolution_backward_data : public primitive {
+ struct desc {
+ mkldnn_deconvolution_desc_t data;
+ desc(algorithm aalgorithm,
+ const memory::desc &diff_src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_deconvolution_backward_data_desc_init(
+ &data, convert_to_c(aalgorithm), &diff_src_desc.data,
+ &weights_desc.data, &diff_dst_desc.data,
+ &strides[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a deconvolution backward data descriptor");
+ }
+ desc(algorithm aalgorithm,
+ const memory::desc &diff_src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims dilates,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(dilates);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_dilated_deconvolution_backward_data_desc_init(
+ &data, convert_to_c(aalgorithm), &diff_src_desc.data,
+ &weights_desc.data, &diff_dst_desc.data,
+ &strides[0], &dilates[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a dilated deconvolution backward data descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const deconvolution_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const deconvolution_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(diff_src, diff_src, 0);
+ REG_QUERY_MD(weights, weights, 0);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ deconvolution_backward_data(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct deconvolution_backward_weights : public primitive {
+ struct desc {
+ mkldnn_deconvolution_desc_t data;
+ desc(algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &diff_weights_desc,
+ const memory::desc &diff_bias_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_deconvolution_backward_weights_desc_init(
+ &data, convert_to_c(aalgorithm), &src_desc.data,
+ &diff_weights_desc.data, &diff_bias_desc.data,
+ &diff_dst_desc.data,
+ &strides[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a deconvolution backward weights descriptor");
+ }
+ desc(algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &diff_weights_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_deconvolution_backward_weights_desc_init(
+ &data, convert_to_c(aalgorithm), &src_desc.data,
+ &diff_weights_desc.data, nullptr, &diff_dst_desc.data,
+ &strides[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a deconvolution backward weights descriptor");
+ }
+ desc(algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &diff_weights_desc,
+ const memory::desc &diff_bias_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims dilates,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(dilates);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_dilated_deconvolution_backward_weights_desc_init(
+ &data, convert_to_c(aalgorithm), &src_desc.data,
+ &diff_weights_desc.data, &diff_bias_desc.data,
+ &diff_dst_desc.data,
+ &strides[0], &dilates[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a dilated deconvolution backward weights descriptor");
+ }
+ desc(algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &diff_weights_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims strides,
+ const memory::dims dilates,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(dilates);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_dilated_deconvolution_backward_weights_desc_init(
+ &data, convert_to_c(aalgorithm), &src_desc.data,
+ &diff_weights_desc.data, nullptr, &diff_dst_desc.data,
+ &strides[0], &dilates[0], &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not create a dilated deconvolution backward weights descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const deconvolution_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const deconvolution_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(diff_weights, diff_weights, 0);
+ REG_QUERY_MD(diff_bias, diff_weights, 1);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ deconvolution_backward_weights(const primitive_desc &pd): primitive(pd) {}
+};
+
+/// @}
+
+/// @addtogroup cpp_api_lrn LRN
+/// A primitive to perform local response normalization (LRN) across or within
+/// channels.
+///
+/// @sa @ref c_api_lrn in @ref c_api
+/// @{
+
+struct lrn_forward : public primitive {
+ struct desc {
+ mkldnn_lrn_desc_t data;
+
+ desc(prop_kind aprop_kind, algorithm aalgorithm,
+ const memory::desc &src_desc, memory::dim local_size,
+ float alpha, float beta, float k = 1.f) {
+ error::wrap_c_api(mkldnn_lrn_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), convert_to_c(aalgorithm),
+ &src_desc.data, local_size, alpha, beta, k),
+ "could not create a lrn forward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(workspace, workspace, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ lrn_forward(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct lrn_backward : public primitive {
+ struct desc {
+ mkldnn_lrn_desc_t data;
+
+ desc(algorithm aalgorithm, const memory::desc &data_desc,
+ const memory::desc &diff_data_desc, memory::dim local_size,
+ float alpha, float beta, float k = 1.f) {
+ error::wrap_c_api(mkldnn_lrn_backward_desc_init(&data,
+ convert_to_c(aalgorithm), &diff_data_desc.data,
+ &data_desc.data, local_size, alpha, beta, k),
+ "could not create a lrn backward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const lrn_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const lrn_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(diff_src, diff_src, 0);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(workspace, workspace, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ lrn_backward(const primitive_desc &pd): primitive(pd) {}
+};
+
+/// @}
+
+/// @addtogroup cpp_api_pooling Pooling
+/// A primitive to perform max or average pooling.
+///
+/// @sa @ref c_api_pooling in @ref c_api
+/// @{
+
+struct pooling_forward : public primitive {
+ struct desc {
+ mkldnn_pooling_desc_t data;
+ desc(prop_kind aprop_kind, algorithm aalgorithm,
+ const memory::desc &src_desc,
+ const memory::desc &dst_desc,
+ const memory::dims strides,
+ const memory::dims kernel,
+ const memory::dims padding_l,
+ const memory::dims padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(kernel);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_pooling_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind),
+ convert_to_c(aalgorithm),
+ &src_desc.data, &dst_desc.data,
+ &strides[0], &kernel[0],
+ &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not init a forward pooling descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(workspace, workspace, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ pooling_forward(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct pooling_backward : public primitive {
+ struct desc {
+ mkldnn_pooling_desc_t data;
+ desc(algorithm aalgorithm,
+ const memory::desc &diff_src_desc,
+ const memory::desc &diff_dst_desc,
+ const memory::dims &strides,
+ const memory::dims &kernel,
+ const memory::dims &padding_l,
+ const memory::dims &padding_r,
+ const padding_kind apadding_kind) {
+ memory::validate_dims(strides);
+ memory::validate_dims(kernel);
+ memory::validate_dims(padding_l);
+ memory::validate_dims(padding_r);
+ error::wrap_c_api(mkldnn_pooling_backward_desc_init(&data,
+ convert_to_c(aalgorithm),
+ &diff_src_desc.data, &diff_dst_desc.data,
+ &strides[0], &kernel[0],
+ &padding_l[0], &padding_r[0],
+ mkldnn::convert_to_c(apadding_kind)),
+ "could not init a backward pooling descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const pooling_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const pooling_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(diff_src, diff_src, 0);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(workspace, workspace, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ pooling_backward(const primitive_desc &pd): primitive(pd) {}
+};
+
+/// @}
+
+/// @addtogroup cpp_api_eltwise Eltwise
+/// A primitive to compute element-wise operations like parametric rectifier
+/// linear unit (ReLU).
+///
+/// @sa @ref c_api_eltwise in @ref c_api
+/// @{
+
+struct eltwise_forward : public primitive {
+ struct desc {
+ mkldnn_eltwise_desc_t data;
+ template <typename T>
+ desc(prop_kind aprop_kind, algorithm alg_kind,
+ const memory::desc &src_desc, T alpha = 0, T beta = 0) {
+ error::wrap_c_api(mkldnn_eltwise_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind),
+ mkldnn::convert_to_c(alg_kind), &src_desc.data,
+ static_cast<float>(alpha), static_cast<float>(beta)),
+ "could not create a eltwise forward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ eltwise_forward(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct eltwise_backward : public primitive {
+ struct desc {
+ mkldnn_eltwise_desc_t data;
+
+ template <typename T>
+ desc(algorithm alg_kind, const memory::desc &diff_data_desc,
+ const memory::desc &data_desc, T alpha = 0, T beta = 0) {
+ error::wrap_c_api(mkldnn_eltwise_backward_desc_init(&data,
+ mkldnn::convert_to_c(alg_kind), &diff_data_desc.data,
+ &data_desc.data, static_cast<float>(alpha),
+ static_cast<float>(beta)),
+ "could not create a eltwise backward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const eltwise_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const eltwise_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(diff_src, diff_src, 0);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ eltwise_backward(const primitive_desc &pd): primitive(pd) {}
+};
+
+/// @}
+
+/// @addtogroup cpp_api_softmax Softmax
+/// A primitive to perform softmax.
+///
+/// @sa @ref c_api_softmax in @ref c_api
+/// @{
+
+struct softmax_forward : public primitive {
+ struct desc {
+ mkldnn_softmax_desc_t data;
+ desc(prop_kind aprop_kind, const memory::desc &data_desc,
+ int softmax_axis) {
+ error::wrap_c_api(mkldnn_softmax_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), &data_desc.data,
+ softmax_axis),
+ "could not create a softmax forward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ softmax_forward(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct softmax_backward : public primitive {
+ struct desc {
+ mkldnn_softmax_desc_t data;
+ desc(const memory::desc &diff_desc, const memory::desc &data_desc,
+ int softmax_axis) {
+ error::wrap_c_api(mkldnn_softmax_backward_desc_init(&data,
+ &diff_desc.data, &data_desc.data, softmax_axis),
+ "could not init a backward softmax descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const softmax_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const softmax_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(diff_src, diff_src, 0);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(workspace, workspace, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ softmax_backward(const primitive_desc &pd): primitive(pd) {}
+};
+
+/// @}
+
+/// @addtogroup cpp_api_batch_norm Batch normalization
+/// A primitive to perform batch normalization.
+///
+/// @sa @ref c_api_batch_normalization in @ref c_api
+/// @{
+
+struct batch_normalization_forward : public primitive {
+ struct desc {
+ mkldnn_batch_normalization_desc_t data;
+ template <typename T>
+ desc(prop_kind aprop_kind, const memory::desc &src_desc, T epsilon,
+ unsigned flags) {
+ error::wrap_c_api(
+ mkldnn_batch_normalization_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), &src_desc.data,
+ static_cast<float>(epsilon), flags),
+ "could not create a batch normalization forward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(weights, weights, 0);
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(workspace, workspace, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+
+ memory::desc mean_desc() const { return stat_desc(mean); }
+ memory::desc variance_desc() const { return stat_desc(var); }
+
+ private:
+ enum { mean = 1, var = 2, };
+ memory::desc stat_desc(int kind) const {
+ mkldnn_batch_normalization_desc_t *p;
+ error::wrap_c_api(mkldnn_primitive_desc_query(
+ get(), mkldnn::convert_to_c(batch_normalization_d), 0, &p),
+ "could not get a batch-normalization descriptor");
+ return query_md(p->flags & use_global_stats ? src_md : dst_md, kind);
+ }
+ };
+
+ batch_normalization_forward(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct batch_normalization_backward : public primitive {
+ struct desc {
+ mkldnn_batch_normalization_desc_t data;
+ template <typename T>
+ desc(prop_kind aprop_kind, const memory::desc &diff_data_desc,
+ const memory::desc &data_desc, T epsilon, unsigned flags) {
+ error::wrap_c_api(
+ mkldnn_batch_normalization_backward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind),
+ &diff_data_desc.data, &data_desc.data,
+ static_cast<float>(epsilon), flags),
+ "could not create a batch normalization backward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const batch_normalization_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const batch_normalization_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(mean, src, 1);
+ REG_QUERY_MD(variance, src, 2);
+ REG_QUERY_MD(weights, weights, 0);
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(workspace, workspace, 0);
+
+ REG_QUERY_MD(diff_src, diff_src, 0);
+ REG_QUERY_MD(diff_weights, diff_weights, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ batch_normalization_backward(const primitive_desc &pd): primitive(pd) {}
+};
+
+/// @}
+
+/// @addtogroup cpp_api_inner_product Inner Product
+/// A primitive to compute an inner product.
+///
+/// @sa @ref c_api_inner_product in @ref c_api
+/// @{
+
+struct inner_product_forward: public primitive {
+ struct desc {
+ mkldnn_inner_product_desc_t data;
+ desc(prop_kind aprop_kind, const memory::desc &src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &bias_desc,
+ const memory::desc &dst_desc) {
+ error::wrap_c_api(
+ mkldnn_inner_product_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), &src_desc.data,
+ &weights_desc.data, &bias_desc.data, &dst_desc.data),
+ "could not create a inner product forward descriptor");
+ }
+
+ desc(prop_kind aprop_kind, const memory::desc &src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &dst_desc) {
+ error::wrap_c_api(
+ mkldnn_inner_product_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), &src_desc.data,
+ &weights_desc.data, nullptr, &dst_desc.data),
+ "could not create a inner product forward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(weights, weights, 0);
+ REG_QUERY_MD(bias, weights, 1);
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ inner_product_forward(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct inner_product_backward_data: public primitive {
+ struct desc {
+ mkldnn_inner_product_desc_t data;
+ desc(const memory::desc &diff_src_desc,
+ const memory::desc &weights_desc,
+ const memory::desc &diff_dst_desc) {
+ error::wrap_c_api(
+ mkldnn_inner_product_backward_data_desc_init(&data,
+ &diff_src_desc.data, &weights_desc.data,
+ &diff_dst_desc.data),
+ "could not create a inner product backward data descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const inner_product_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const inner_product_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(diff_src, diff_src, 0);
+ REG_QUERY_MD(weights, weights, 0);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ inner_product_backward_data(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct inner_product_backward_weights: public primitive {
+ struct desc {
+ mkldnn_inner_product_desc_t data;
+ desc(const memory::desc &src_desc,
+ const memory::desc &diff_weights_desc,
+ const memory::desc &diff_bias_desc,
+ const memory::desc &diff_dst_desc) {
+ error::wrap_c_api(
+ mkldnn_inner_product_backward_weights_desc_init(
+ &data, &src_desc.data, &diff_weights_desc.data,
+ &diff_bias_desc.data, &diff_dst_desc.data),
+ "could not create a inner product backward weights descriptor");
+ }
+ desc(const memory::desc &src_desc,
+ const memory::desc &diff_weights_desc,
+ const memory::desc &diff_dst_desc) {
+ error::wrap_c_api(
+ mkldnn_inner_product_backward_weights_desc_init(
+ &data, &src_desc.data, &diff_weights_desc.data,
+ nullptr, &diff_dst_desc.data),
+ "could not create a inner product backward weights descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const inner_product_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const inner_product_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(diff_weights, diff_weights, 0);
+ REG_QUERY_MD(diff_bias, diff_weights, 1);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ inner_product_backward_weights(const primitive_desc &pd): primitive(pd) {}
+};
+
+/// @}
+
+/// @addtogroup cpp_api_rnn RNN
+/// A primitive to compute common recurrent layer.
+///
+/// @sa @ref c_api_rnn in @ref c_api
+/// @{
+
+struct rnn_cell {
+ struct desc {
+ mkldnn_rnn_cell_desc_t c_rnn_cell_;
+
+ desc(algorithm kind, algorithm activation_f) {
+ error::wrap_c_api(mkldnn_rnn_cell_desc_init(&c_rnn_cell_,
+ mkldnn::convert_to_c(kind),
+ mkldnn::convert_to_c(activation_f), 0U, 0, 0),
+ "could not init an rnn cell descriptor");
+ }
+ desc(algorithm kind): desc(kind, algorithm::algorithm_undef) {}
+
+ operator const mkldnn_rnn_cell_desc_t*() const { return &c_rnn_cell_; }
+
+ algorithm get_cell_kind() const
+ { return algorithm(c_rnn_cell_.cell_kind); }
+ algorithm get_activation() const
+ { return algorithm(c_rnn_cell_.activation_kind); }
+
+ float get_alpha() const { return c_rnn_cell_.alpha; }
+ void set_alpha(float alpha) {
+ c_rnn_cell_.flags |= mkldnn_rnn_cell_with_relu;
+ c_rnn_cell_.alpha = alpha;
+ }
+
+ float get_clipping() const { return c_rnn_cell_.clipping; }
+ void set_clipping(float clipping) {
+ c_rnn_cell_.flags |= mkldnn_rnn_cell_with_clipping;
+ c_rnn_cell_.clipping = clipping;
+ }
+
+ int get_gates_count() const {
+ return mkldnn_rnn_cell_get_gates_count(&c_rnn_cell_);
+ }
+ int get_state_count() const {
+ return mkldnn_rnn_cell_get_states_count(&c_rnn_cell_);
+ }
+ };
+};
+
+struct rnn_forward : public primitive {
+ struct desc {
+ mkldnn_rnn_desc_t data;
+ desc(prop_kind aprop_kind, rnn_cell::desc cell,
+ const rnn_direction direction,
+ const memory::desc &src_layer_desc,
+ const memory::desc &src_iter_desc,
+ const memory::desc &weights_layer_desc,
+ const memory::desc &weights_iter_desc,
+ const memory::desc &bias_desc,
+ const memory::desc &dst_layer_desc,
+ const memory::desc &dst_iter_desc
+ ) {
+ error::wrap_c_api(mkldnn_rnn_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), cell,
+ mkldnn::convert_to_c(direction),
+ &src_layer_desc.data, &src_iter_desc.data,
+ &weights_layer_desc.data, &weights_iter_desc.data,
+ &bias_desc.data,
+ &dst_layer_desc.data, &dst_iter_desc.data),
+ "could not create an RNN forward descriptor");
+ }
+
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, nullptr) {}
+
+ REG_QUERY_MD(src_layer, src, 0);
+ REG_QUERY_MD(src_iter, src, 1);
+ REG_QUERY_MD(weights_layer, weights, 0);
+ REG_QUERY_MD(weights_iter, weights, 1);
+ REG_QUERY_MD(bias, weights, 2);
+ REG_QUERY_MD(dst_layer, dst, 0);
+ REG_QUERY_MD(dst_iter, dst, 1);
+ REG_QUERY_MD(workspace, workspace, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ rnn_forward(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct rnn_backward : public primitive {
+ struct desc {
+ mkldnn_rnn_desc_t data;
+ desc(prop_kind aprop_kind, rnn_cell::desc cell,
+ const rnn_direction direction,
+ const memory::desc &src_layer_desc,
+ const memory::desc &src_iter_desc,
+ const memory::desc &weights_layer_desc,
+ const memory::desc &weights_iter_desc,
+ const memory::desc &bias_desc,
+ const memory::desc &dst_layer_desc,
+ const memory::desc &dst_iter_desc,
+ const memory::desc &diff_src_layer_desc,
+ const memory::desc &diff_src_iter_desc,
+ const memory::desc &diff_weights_layer_desc,
+ const memory::desc &diff_weights_iter_desc,
+ const memory::desc &diff_bias_desc,
+ const memory::desc &diff_dst_layer_desc,
+ const memory::desc &diff_dst_iter_desc) {
+ error::wrap_c_api(mkldnn_rnn_backward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), cell,
+ mkldnn::convert_to_c(direction),
+ &src_layer_desc.data, &src_iter_desc.data,
+ &weights_layer_desc.data, &weights_iter_desc.data,
+ &bias_desc.data,
+ &dst_layer_desc.data, &dst_iter_desc.data,
+ &diff_src_layer_desc.data, &diff_src_iter_desc.data,
+ &diff_weights_layer_desc.data,
+ &diff_weights_iter_desc.data, &diff_bias_desc.data,
+ &diff_dst_layer_desc.data, &diff_dst_iter_desc.data),
+ "could not create an RNN backward descriptor");
+ }
+
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const rnn_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ primitive_desc(const desc &desc, const primitive_attr &attr, const engine &e,
+ const rnn_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, &attr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(src_layer, src, 0);
+ REG_QUERY_MD(src_iter, src, 1);
+ REG_QUERY_MD(weights_layer, weights, 0);
+ REG_QUERY_MD(weights_iter, weights, 1);
+ REG_QUERY_MD(bias, weights, 2);
+ REG_QUERY_MD(dst_layer, dst, 0);
+ REG_QUERY_MD(dst_iter, dst, 1);
+ REG_QUERY_MD(workspace, workspace, 0);
+
+ REG_QUERY_MD(diff_src_layer, diff_src, 0);
+ REG_QUERY_MD(diff_src_iter, diff_src, 1);
+ REG_QUERY_MD(diff_weights_layer, diff_weights, 0);
+ REG_QUERY_MD(diff_weights_iter, diff_weights, 1);
+ REG_QUERY_MD(diff_bias, diff_weights, 2);
+ REG_QUERY_MD(diff_dst_layer, diff_dst, 0);
+ REG_QUERY_MD(diff_dst_iter, diff_dst, 1);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ // With last iteration (with and without input src_iter)
+ rnn_backward(const primitive_desc &pd): primitive(pd) {}
+};
+
+/// @}
+
+/// @addtogroup cpp_api_shuffle Shuffle
+/// A primitive to shuffle data along the axis.
+///
+/// @sa @ref c_api_shuffle in @ref c_api
+/// @{
+
+struct shuffle_forward : public primitive {
+ struct desc {
+ mkldnn_shuffle_desc_t data;
+ desc(prop_kind aprop_kind, const memory::desc &data_desc,
+ int axis, int group_size) {
+ error::wrap_c_api(mkldnn_shuffle_forward_desc_init(&data,
+ mkldnn::convert_to_c(aprop_kind), &data_desc.data,
+ axis, group_size),
+ "could not create a shuffle forward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, nullptr) {}
+
+ REG_QUERY_MD(src, src, 0);
+ REG_QUERY_MD(dst, dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ shuffle_forward(const primitive_desc &pd): primitive(pd) {}
+};
+
+struct shuffle_backward : public primitive {
+ struct desc {
+ mkldnn_shuffle_desc_t data;
+ desc(const memory::desc &diff_data_desc, int axis, int group_size) {
+ error::wrap_c_api(mkldnn_shuffle_backward_desc_init(&data,
+ &diff_data_desc.data, axis, group_size),
+ "could not create a shuffle backward descriptor");
+ }
+ };
+
+ struct primitive_desc : public mkldnn::primitive_desc {
+ primitive_desc(const desc &desc, const engine &e,
+ const shuffle_forward::primitive_desc &hint_fwd_pd)
+ : mkldnn::primitive_desc(&desc.data, nullptr, e, hint_fwd_pd.get()) {}
+
+ REG_QUERY_MD(diff_src, diff_src, 0);
+ REG_QUERY_MD(diff_dst, diff_dst, 0);
+ REG_QUERY_MD(scratchpad, scratchpad, 0);
+ };
+
+ shuffle_backward(const primitive_desc &pd): primitive(pd) {}
+};
+
+/// @}
+
+/// @} Primitives
+
+/// @} C++ API
+
+#undef REG_QUERY_MD
+
+// implementation section
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+inline primitive::primitive(const_mkldnn_primitive_desc_t c_pd) {
+ mkldnn_primitive_t result;
+ error::wrap_c_api(mkldnn_primitive_create(&result, c_pd),
+ "could not create a primitive");
+ reset(result);
+}
+
+inline primitive::primitive(const primitive_desc &pd): primitive(pd.get()) {}
+
+inline void primitive::execute(stream &astream,
+ const std::unordered_map<int, memory> &args) const {
+ std::vector<mkldnn_exec_arg_t> c_args;
+ c_args.reserve(args.size());
+ for (const auto &a: args)
+ c_args.push_back({a.first, a.second.get()});
+
+ error::wrap_c_api(mkldnn_primitive_execute(get(), astream.get(),
+ (int)c_args.size(), c_args.data()),
+ "primitive execution fail");
+}
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+} // namespace mkldnn
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn_debug.h b/thirdparty/oidn/mkl-dnn/include/mkldnn_debug.h
new file mode 100644
index 0000000000..f4dc2fdfa6
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/include/mkldnn_debug.h
@@ -0,0 +1,98 @@
+/*******************************************************************************
+* Copyright 2018-2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/* DO NOT EDIT, AUTO-GENERATED */
+
+#ifndef MKLDNN_DEBUG_H
+#define MKLDNN_DEBUG_H
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/* All symbols shall be internal unless marked as MKLDNN_API */
+#if defined _WIN32 || defined __CYGWIN__
+# define MKLDNN_HELPER_DLL_IMPORT __declspec(dllimport)
+# define MKLDNN_HELPER_DLL_EXPORT __declspec(dllexport)
+#else
+# if __GNUC__ >= 4
+# define MKLDNN_HELPER_DLL_IMPORT __attribute__ ((visibility ("default")))
+# define MKLDNN_HELPER_DLL_EXPORT __attribute__ ((visibility ("default")))
+# else
+# define MKLDNN_HELPER_DLL_IMPORT
+# define MKLDNN_HELPER_DLL_EXPORT
+# endif
+#endif
+
+#ifdef MKLDNN_DLL
+# ifdef MKLDNN_DLL_EXPORTS
+# define MKLDNN_API MKLDNN_HELPER_DLL_EXPORT
+# else
+# define MKLDNN_API MKLDNN_HELPER_DLL_IMPORT
+# endif
+#else
+# define MKLDNN_API
+#endif
+
+#if defined (__GNUC__)
+# define MKLDNN_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER)
+# define MKLDNN_DEPRECATED __declspec(deprecated)
+#else
+# define MKLDNN_DEPRECATED
+#endif
+
+#include "mkldnn_types.h"
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const char MKLDNN_API *mkldnn_status2str(mkldnn_status_t v);
+const char MKLDNN_API *mkldnn_dt2str(mkldnn_data_type_t v);
+const char MKLDNN_API *mkldnn_fmt_kind2str(mkldnn_format_kind_t v);
+const char MKLDNN_API *mkldnn_fmt_tag2str(mkldnn_format_tag_t v);
+const char MKLDNN_API *mkldnn_prop_kind2str(mkldnn_prop_kind_t v);
+const char MKLDNN_API *mkldnn_prim_kind2str(mkldnn_primitive_kind_t v);
+const char MKLDNN_API *mkldnn_alg_kind2str(mkldnn_alg_kind_t v);
+const char MKLDNN_API *mkldnn_rnn_direction2str(mkldnn_rnn_direction_t v);
+
+/** Forms a format string for a given memory descriptor.
+ *
+ * The format is defined as: 'dt:[p|o|0]:fmt_kind:fmt:extra'.
+ * Here:
+ * - dt -- data type
+ * - p -- indicates there is non-trivial padding
+ * - o -- indicates there is non-trivial padding offset
+ * - 0 -- indicates there is non-trivial offset0
+ * - fmt_kind -- format kind (blocked, wino, etc...)
+ * - fmt -- extended format string (format_kind specific)
+ * - extra -- shows extra fields (underspecified)
+ */
+int MKLDNN_API mkldnn_md2fmt_str(char *fmt_str, size_t fmt_str_len,
+ const mkldnn_memory_desc_t *md);
+
+/** Forms a dimension string for a given memory descriptor.
+ *
+ * The format is defined as: 'dim0xdim1x...xdimN
+ */
+int MKLDNN_API mkldnn_md2dim_str(char *dim_str, size_t dim_str_len,
+ const mkldnn_memory_desc_t *md);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn_types.h b/thirdparty/oidn/mkl-dnn/include/mkldnn_types.h
new file mode 100644
index 0000000000..1b6c356982
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/include/mkldnn_types.h
@@ -0,0 +1,1415 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MKLDNN_TYPES_H
+#define MKLDNN_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+#include <stddef.h>
+#include <stdint.h>
+#endif
+
+/** @addtogroup c_api C API
+ * @{
+ *
+ * @addtogroup c_api_types Types
+ * @{
+ *
+ * @addtogroup c_api_types_generic Generic
+ * @{ */
+
+/** Intel(R) MKL-DNN Version type */
+typedef struct {
+ int major;
+ int minor;
+ int patch;
+ const char *hash;
+} mkldnn_version_t;
+
+/** Status values returned by Intel(R) MKL-DNN functions. */
+typedef enum {
+ /** The operation was successful */
+ mkldnn_success = 0,
+ /** The operation failed due to an out-of-memory condition */
+ mkldnn_out_of_memory = 1,
+ /** The operation failed and should be retried */
+ mkldnn_try_again = 2,
+ /** The operation failed because of incorrect function arguments */
+ mkldnn_invalid_arguments = 3,
+ /** The operation failed because a primitive was not ready for execution */
+ mkldnn_not_ready = 4,
+ /** The operation failed because requested functionality is not implemented
+ */
+ mkldnn_unimplemented = 5,
+ /** Primitive iterator passed over last primitive descriptor */
+ mkldnn_iterator_ends = 6,
+ /** Primitive or engine failed on execution */
+ mkldnn_runtime_error = 7,
+ /** Queried element is not required for given primitive */
+ mkldnn_not_required = 8,
+} mkldnn_status_t;
+
+/** Data type specification */
+typedef enum {
+ /** Undefined data type, used for empty memory descriptors. */
+ mkldnn_data_type_undef = 0,
+ /** 32-bit/single-precision floating point. */
+ mkldnn_f32 = 1,
+ /** 32-bit signed integer. */
+ mkldnn_s32 = 2,
+ /** 8-bit signed integer. */
+ mkldnn_s8 = 3,
+ /** 8-bit unsigned integer. */
+ mkldnn_u8 = 4,
+} mkldnn_data_type_t;
+
+/** Memory format kind */
+typedef enum {
+ /** Undefined memory format, used for empty memory descriptors. */
+ mkldnn_format_kind_undef = 0,
+ /** Unspecified format. The primitive selects a format automatically. */
+ mkldnn_format_kind_any,
+ /** A tensor in a generic format described by the stride and blocking
+ * values in each dimension. See #mkldnn_blocking_desc_t for more
+ * information. */
+ mkldnn_blocked,
+ /** Weights format used in 8bit Winograd convolution */
+ mkldnn_format_kind_wino,
+ /** Packed weights format used in RNN */
+ mkldnn_format_kind_rnn_packed,
+} mkldnn_format_kind_t;
+
+/** Memory format tag specification.
+ *
+ * Intel MKL-DNN formats describe physical data layout. The physical layout
+ * is described as a sequence of the dimensions as they are laid out in the
+ * memory (from the outer-most to the inner-most). Note that this order
+ * doesn't affect the logical order of the dimensions that is kept in the
+ * `dims` field of the mkldnn_memory_desc_t structure. The logical order of the
+ * dimensions is specified by the type of tensor.
+ *
+ * For example, CNN 5D tensor always has its logical dimensions in the order
+ * `(batch, channels, depth, height, width)`, while the physical layout might be
+ * #mkldnn_ncdhw or #mkldnn_ndhwc:
+ *
+ * ~~~cpp
+ * int batch = 2, channels = 16, depth = 13, height = 13, width = 13;
+ *
+ * int ndims = 5; // 5D tensor
+ * mkldnn_dims_t dims = {batch, channels, depth, height, width};
+ * mkldnn_memory_desc_t data_in_ncdhw;
+ * mkldnn_memory_desc_init_by_tag(
+ * &data_in_ncdhw, 5, dims, mkldnn_f32, mkldnn_ncdhw);
+ *
+ * // note that in both cases dims passed are the same
+ * mkldnn_memory_desc_t data_in_ndhwc;
+ * mkldnn_memory_desc_init_by_tag(
+ * &data_in_ndhwc, 5, dims, mkldnn_f32, mkldnn_ndhwc);
+ * ~~~
+ *
+ * The following notation applies to memory format names:
+ * - @c 'n' denotes the mini-batch dimension
+ * - @c 'c' denotes a channels dimension
+ * - When there are multiple channel dimensions (for example, in convolution
+ * weights tensor), @c 'i' and @c 'o' denote dimensions of input and output
+ * channels
+ * - @c 'd', @c 'h', and @c 'w' denote spatial depth, height, and width
+ * respectively
+ * - Upper-case letters indicate that the data is laid out in blocks
+ * for a particular dimension. In such cases, the format name contains both
+ * upper- and lower-case letters for that dimension with a lower-case letter
+ * preceded by the block size. For example: @c 'mkldnn_nChw8c' describes a
+ * format where the outermost dimension is mini-batch, followed by the
+ * channel block number, followed by the spatial height and width, and
+ * finally followed by 8-element channel blocks.
+ *
+ * @note
+ * Channel designations can be different. For example, both the @c
+ * 'mkldnn_nc' and @c 'mkldnn_io' formats can be used to describe a 2D
+ * tensor.
+ *
+ * @sa @ref understanding_memory_formats
+ */
+typedef enum {
+ /** Undefined memory format tag */
+ mkldnn_format_tag_undef = 0,
+ /** Undefined memory format tag.
+ * The primitive selects a format automatically. */
+ mkldnn_format_tag_any,
+
+ /* Semantic agnostic section */
+ /* The physical order of dimensions is defined by the permutation of the
+ * characters, assuming that ab..z defines the natural order.
+ */
+
+ /* Plain formats */
+
+ mkldnn_a,
+ mkldnn_ab,
+ mkldnn_abc,
+ mkldnn_abcd,
+ mkldnn_abcde,
+ mkldnn_abcdef,
+ mkldnn_abdec,
+ mkldnn_acb,
+ mkldnn_acbde,
+ mkldnn_acdb,
+ mkldnn_acdeb,
+ mkldnn_ba,
+ mkldnn_bac,
+ mkldnn_bacd,
+ mkldnn_bcda,
+ mkldnn_cba,
+ mkldnn_cdba,
+ mkldnn_cdeba,
+ mkldnn_decab,
+
+ /* Opaque blocked formats */
+
+ mkldnn_Abc16a,
+ mkldnn_ABc16a16b,
+ mkldnn_aBc16b,
+ mkldnn_ABc16b16a,
+ mkldnn_Abc4a,
+ mkldnn_aBc4b,
+ mkldnn_ABc4b16a4b,
+ mkldnn_ABc4b4a,
+ mkldnn_ABc8a16b2a,
+ mkldnn_ABc8a8b,
+ mkldnn_aBc8b,
+ mkldnn_ABc8b16a2b,
+ mkldnn_ABc8b8a,
+ mkldnn_Abcd16a,
+ mkldnn_ABcd16a16b,
+ mkldnn_aBcd16b,
+ mkldnn_ABcd16b16a,
+ mkldnn_aBCd16b16c,
+ mkldnn_aBCd16c16b,
+ mkldnn_Abcd4a,
+ mkldnn_aBcd4b,
+ mkldnn_ABcd4b16a4b,
+ mkldnn_ABcd4b4a,
+ mkldnn_aBCd4c16b4c,
+ mkldnn_aBCd4c4b,
+ mkldnn_ABcd8a16b2a,
+ mkldnn_ABcd8a8b,
+ mkldnn_aBcd8b,
+ mkldnn_ABcd8b16a2b,
+ mkldnn_aBCd8b16c2b,
+ mkldnn_ABcd8b8a,
+ mkldnn_aBCd8b8c,
+ mkldnn_aBCd8c16b2c,
+ mkldnn_aBCd8c8b,
+ mkldnn_Abcde16a,
+ mkldnn_ABcde16a16b,
+ mkldnn_aBcde16b,
+ mkldnn_ABcde16b16a,
+ mkldnn_aBCde16b16c,
+ mkldnn_aBCde16c16b,
+ mkldnn_aBCde2c8b4c,
+ mkldnn_Abcde4a,
+ mkldnn_aBcde4b,
+ mkldnn_ABcde4b4a,
+ mkldnn_aBCde4b4c,
+ mkldnn_aBCde4c16b4c,
+ mkldnn_aBCde4c4b,
+ mkldnn_Abcde8a,
+ mkldnn_ABcde8a8b,
+ mkldnn_aBcde8b,
+ mkldnn_ABcde8b16a2b,
+ mkldnn_aBCde8b16c2b,
+ mkldnn_ABcde8b8a,
+ mkldnn_aBCde8b8c,
+ mkldnn_aBCde8c16b2c,
+ mkldnn_aBCde8c8b,
+ mkldnn_aBcdef16b,
+ mkldnn_aBCdef16b16c,
+ mkldnn_aBCdef16c16b,
+ mkldnn_aBcdef4b,
+ mkldnn_aBCdef4c4b,
+ mkldnn_aBCdef8b8c,
+ mkldnn_aBCdef8c16b2c,
+ mkldnn_aBCdef8c8b,
+ mkldnn_aBdc16b,
+ mkldnn_aBdc4b,
+ mkldnn_aBdc8b,
+ mkldnn_aBdec16b,
+ mkldnn_aBdec4b,
+ mkldnn_aBdec8b,
+ mkldnn_aBdefc16b,
+ mkldnn_aBdefc4b,
+ mkldnn_aBdefc8b,
+ mkldnn_Acb16a,
+ mkldnn_Acb4a,
+ mkldnn_Acb8a,
+ mkldnn_aCBd16b16c,
+ mkldnn_aCBde16b16c,
+ mkldnn_Acdb16a,
+ mkldnn_Acdb4a,
+ mkldnn_Acdb8a,
+ mkldnn_Acdeb16a,
+ mkldnn_Acdeb4a,
+ mkldnn_Acdeb8a,
+ mkldnn_BAc16a16b,
+ mkldnn_BAcd16a16b,
+
+ /** Just a sentinel, not real memory format tag. Must be changed after new
+ * format tag is added. */
+ mkldnn_format_tag_last,
+
+ /* Aliases */
+
+ mkldnn_x = mkldnn_a,
+ mkldnn_nc = mkldnn_ab,
+ mkldnn_cn = mkldnn_ba,
+ mkldnn_ncw = mkldnn_abc,
+ mkldnn_nwc = mkldnn_acb,
+ mkldnn_nchw = mkldnn_abcd,
+ mkldnn_nhwc = mkldnn_acdb,
+ mkldnn_chwn = mkldnn_bcda,
+ mkldnn_ncdhw = mkldnn_abcde,
+ mkldnn_ndhwc = mkldnn_acdeb,
+
+ mkldnn_oi = mkldnn_ab,
+ mkldnn_io = mkldnn_ba,
+ mkldnn_oiw = mkldnn_abc,
+ mkldnn_wio = mkldnn_cba,
+ mkldnn_oihw = mkldnn_abcd,
+ mkldnn_hwio = mkldnn_cdba,
+ mkldnn_ihwo = mkldnn_bcda,
+ mkldnn_iohw = mkldnn_bacd,
+ mkldnn_oidhw = mkldnn_abcde,
+ mkldnn_dhwio = mkldnn_cdeba,
+ mkldnn_goiw = mkldnn_abcd,
+ mkldnn_goihw = mkldnn_abcde,
+ mkldnn_hwigo = mkldnn_decab,
+ mkldnn_giohw = mkldnn_acbde,
+ mkldnn_goidhw = mkldnn_abcdef,
+
+ /** 3D RNN data tensor in the format (seq_length, batch, input channels). */
+ mkldnn_tnc = mkldnn_abc,
+ /** 3D RNN data tensor in the format (batch, seq_length, input channels). */
+ mkldnn_ntc = mkldnn_bac,
+ /** 5D RNN states tensor in the format (num_layers, num_directions,
+ * num_states, batch, state channels). */
+ mkldnn_ldsnc = mkldnn_abcde,
+ /** 5D RNN weights tensor in the format (num_layers, num_directions,
+ * input_channels, num_gates, output_channels).
+ *
+ * - For LSTM cells, the gates order is input, forget, candidate
+ * and output gate.
+ * - For GRU cells, the gates order is update, reset and output gate. */
+ mkldnn_ldigo = mkldnn_abcde,
+ /** 5D RNN weights tensor in the format (num_layers, num_directions,
+ * num_gates, output_channels, input_channels).
+ *
+ * - For LSTM cells, the gates order is input, forget, candidate
+ * and output gate.
+ * - For GRU cells, the gates order is update, reset and output gate. */
+ mkldnn_ldgoi = mkldnn_abdec,
+ /** 4D RNN bias tensor in the format (num_layers, num_directions,
+ * num_gates, output_channels).
+ *
+ * - For LSTM cells, the gates order is input, forget, candidate
+ * and output gate.
+ * - For GRU cells, the gates order is update, reset and output gate. */
+ mkldnn_ldgo = mkldnn_abcd,
+
+ /* Opaque data types, are not to be used explicitly */
+
+ /* data */
+ mkldnn_nCdhw16c = mkldnn_aBcde16b,
+ mkldnn_nCdhw4c = mkldnn_aBcde4b,
+ mkldnn_nCdhw8c = mkldnn_aBcde8b,
+ mkldnn_nChw16c = mkldnn_aBcd16b,
+ mkldnn_nChw4c = mkldnn_aBcd4b,
+ mkldnn_nChw8c = mkldnn_aBcd8b,
+ mkldnn_nCw16c = mkldnn_aBc16b,
+ mkldnn_nCw4c = mkldnn_aBc4b,
+ mkldnn_nCw8c = mkldnn_aBc8b,
+
+ /* weights, 3D */
+ mkldnn_IOw16o16i = mkldnn_BAc16a16b,
+ mkldnn_OIw16i16o = mkldnn_ABc16b16a,
+ mkldnn_OIw16o16i = mkldnn_ABc16a16b,
+ mkldnn_Oiw16o = mkldnn_Abc16a,
+ mkldnn_OIw4i16o4i = mkldnn_ABc4b16a4b,
+ mkldnn_OIw4i4o = mkldnn_ABc4b4a,
+ mkldnn_Oiw4o = mkldnn_Abc4a,
+ mkldnn_OIw8i16o2i = mkldnn_ABc8b16a2b,
+ mkldnn_OIw8i8o = mkldnn_ABc8b8a,
+ mkldnn_OIw8o16i2o = mkldnn_ABc8a16b2a,
+ mkldnn_OIw8o8i = mkldnn_ABc8a8b,
+ mkldnn_Owi16o = mkldnn_Acb16a,
+ mkldnn_Owi4o = mkldnn_Acb4a,
+ mkldnn_Owi8o = mkldnn_Acb8a,
+
+ /* weights, 4D */
+ mkldnn_IOhw16o16i = mkldnn_BAcd16a16b,
+ mkldnn_Ohwi16o = mkldnn_Acdb16a,
+ mkldnn_Ohwi4o = mkldnn_Acdb4a,
+ mkldnn_Ohwi8o = mkldnn_Acdb8a,
+ mkldnn_OIhw16i16o = mkldnn_ABcd16b16a,
+ mkldnn_OIhw16o16i = mkldnn_ABcd16a16b,
+ mkldnn_Oihw16o = mkldnn_Abcd16a,
+ mkldnn_OIhw4i16o4i = mkldnn_ABcd4b16a4b,
+ mkldnn_OIhw4i4o = mkldnn_ABcd4b4a,
+ mkldnn_Oihw4o = mkldnn_Abcd4a,
+ mkldnn_OIhw8i16o2i = mkldnn_ABcd8b16a2b,
+ mkldnn_OIhw8i8o = mkldnn_ABcd8b8a,
+ mkldnn_OIhw8o16i2o = mkldnn_ABcd8a16b2a,
+ mkldnn_OIhw8o8i = mkldnn_ABcd8a8b,
+
+ /* weights, 5D */
+ mkldnn_Odhwi16o = mkldnn_Acdeb16a,
+ mkldnn_Odhwi4o = mkldnn_Acdeb4a,
+ mkldnn_Odhwi8o = mkldnn_Acdeb8a,
+ mkldnn_OIdhw16i16o = mkldnn_ABcde16b16a,
+ mkldnn_OIdhw16o16i = mkldnn_ABcde16a16b,
+ mkldnn_Oidhw16o = mkldnn_Abcde16a,
+ mkldnn_OIdhw4i4o = mkldnn_ABcde4b4a,
+ mkldnn_Oidhw4o = mkldnn_Abcde4a,
+ mkldnn_OIdhw8i16o2i = mkldnn_ABcde8b16a2b,
+ mkldnn_OIdhw8i8o = mkldnn_ABcde8b8a,
+ mkldnn_OIdhw8o8i = mkldnn_ABcde8a8b,
+
+ /* weights w/ groups, 3D */
+ mkldnn_Goiw16g = mkldnn_Abcd16a,
+ mkldnn_gIOw16o16i = mkldnn_aCBd16b16c,
+ mkldnn_gOIw16i16o = mkldnn_aBCd16c16b,
+ mkldnn_gOIw16o16i = mkldnn_aBCd16b16c,
+ mkldnn_gOiw16o = mkldnn_aBcd16b,
+ mkldnn_gOIw4i16o4i = mkldnn_aBCd4c16b4c,
+ mkldnn_gOIw4i4o = mkldnn_aBCd4c4b,
+ mkldnn_gOiw4o = mkldnn_aBcd4b,
+ mkldnn_gOIw8i16o2i = mkldnn_aBCd8c16b2c,
+ mkldnn_gOIw8i8o = mkldnn_aBCd8c8b,
+ mkldnn_gOIw8o16i2o = mkldnn_aBCd8b16c2b,
+ mkldnn_gOIw8o8i = mkldnn_aBCd8b8c,
+ mkldnn_gOwi16o = mkldnn_aBdc16b,
+ mkldnn_gOwi4o = mkldnn_aBdc4b,
+ mkldnn_gOwi8o = mkldnn_aBdc8b,
+
+ /* weights w/ groups, 4D */
+ mkldnn_gIOhw16o16i = mkldnn_aCBde16b16c,
+ mkldnn_gOhwi16o = mkldnn_aBdec16b,
+ mkldnn_gOhwi4o = mkldnn_aBdec4b,
+ mkldnn_gOhwi8o = mkldnn_aBdec8b,
+ mkldnn_Goihw16g = mkldnn_Abcde16a,
+ mkldnn_gOIhw16i16o = mkldnn_aBCde16c16b,
+ mkldnn_gOIhw16o16i = mkldnn_aBCde16b16c,
+ mkldnn_gOihw16o = mkldnn_aBcde16b,
+ mkldnn_gOIhw2i8o4i = mkldnn_aBCde2c8b4c,
+ mkldnn_gOIhw4i16o4i = mkldnn_aBCde4c16b4c,
+ mkldnn_gOIhw4i4o = mkldnn_aBCde4c4b,
+ mkldnn_gOIhw4o4i = mkldnn_aBCde4b4c,
+ mkldnn_gOihw4o = mkldnn_aBcde4b,
+ mkldnn_Goihw8g = mkldnn_Abcde8a,
+ mkldnn_gOIhw8i16o2i = mkldnn_aBCde8c16b2c,
+ mkldnn_gOIhw8i8o = mkldnn_aBCde8c8b,
+ mkldnn_gOIhw8o16i2o = mkldnn_aBCde8b16c2b,
+ mkldnn_gOIhw8o8i = mkldnn_aBCde8b8c,
+
+ /* weights w/ groups, 6D */
+ mkldnn_gOdhwi16o = mkldnn_aBdefc16b,
+ mkldnn_gOdhwi4o = mkldnn_aBdefc4b,
+ mkldnn_gOdhwi8o = mkldnn_aBdefc8b,
+ mkldnn_gOIdhw16i16o = mkldnn_aBCdef16c16b,
+ mkldnn_gOIdhw16o16i = mkldnn_aBCdef16b16c,
+ mkldnn_gOidhw16o = mkldnn_aBcdef16b,
+ mkldnn_gOIdhw4i4o = mkldnn_aBCdef4c4b,
+ mkldnn_gOidhw4o = mkldnn_aBcdef4b,
+ mkldnn_gOIdhw8i16o2i = mkldnn_aBCdef8c16b2c,
+ mkldnn_gOIdhw8i8o = mkldnn_aBCdef8c8b,
+ mkldnn_gOIdhw8o8i = mkldnn_aBCdef8b8c,
+} mkldnn_format_tag_t;
+
+/** Kinds of padding. Define how to interpret the data in padding regions. */
+typedef enum {
+ /** The data in padding regions is zero. */
+ mkldnn_padding_zero,
+} mkldnn_padding_kind_t;
+
+/** Kinds of propagation. */
+typedef enum {
+ /* TODO: suggest renames */
+ /** Undefined propagation type. */
+ mkldnn_prop_kind_undef = 0,
+ /** Forward data propagation (training mode). In this mode primitives
+ * perform computations necessary for subsequent backward propagation. */
+ mkldnn_forward_training = 64,
+ /** Forward data propagation (inference mode). In this mode primitives
+ * perform only computations that are necessary for inference and omit
+ * computations that are necessary only for backward propagation. */
+ mkldnn_forward_inference = 96,
+ /** Forward data propagation (alias for @c mkldnn_forward_inference) */
+ mkldnn_forward_scoring = mkldnn_forward_inference,
+ /** Forward data propagation (alias for @c mkldnn_forward_training) */
+ mkldnn_forward = mkldnn_forward_training,
+ /** Backward propagation (with respect to all parameters */
+ mkldnn_backward = 128,
+ /** Backward data propagation */
+ mkldnn_backward_data = 160,
+ /** Backward weights propagation */
+ mkldnn_backward_weights = 192,
+ /** Backward bias propagation */
+ mkldnn_backward_bias = 193,
+} mkldnn_prop_kind_t;
+
+/** Kinds of primitives. Used to implement a way to extend the library with new
+ * primitives without changing the ABI. */
+typedef enum {
+ /** Undefined primitive (XXX: why do we have it?). */
+ mkldnn_undefined_primitive,
+ /** A reorder primitive.*/
+ mkldnn_reorder,
+ /** A shuffle primitive.*/
+ mkldnn_shuffle,
+ /** A (out-of-place) concat primitive. */
+ mkldnn_concat,
+ /** A sum primitive. */
+ mkldnn_sum,
+ /** A convolution primitive. */
+ mkldnn_convolution,
+ /** A deconvolution primitive. */
+ mkldnn_deconvolution,
+ /** An element-wise primitive. */
+ mkldnn_eltwise,
+ /** A Softmax primitive. */
+ mkldnn_softmax,
+ /** A pooling primitive. */
+ mkldnn_pooling,
+ /** An LRN primitive. */
+ mkldnn_lrn,
+ /** An batch normalization primitive. */
+ mkldnn_batch_normalization,
+ /** An inner product primitive. */
+ mkldnn_inner_product,
+ /** A rnn primitive. */
+ mkldnn_rnn,
+} mkldnn_primitive_kind_t;
+
+/** Kinds of algorithms. */
+typedef enum {
+ mkldnn_alg_kind_undef,
+ /** Direct convolution */
+ mkldnn_convolution_direct = 0x1,
+ /** Winograd convolution */
+ mkldnn_convolution_winograd = 0x2,
+ /** Convolution algorithm(either direct or Winograd) is chosen just in time **/
+ mkldnn_convolution_auto = 0x3,
+ /** Direct deconvolution */
+ mkldnn_deconvolution_direct = 0xa,
+ /** Winograd deconvolution */
+ mkldnn_deconvolution_winograd = 0xb,
+ /** Eltwise: ReLU */
+ mkldnn_eltwise_relu = 0x1f,
+ /** Eltwise: hyperbolic tangent non-linearity (tanh) */
+ mkldnn_eltwise_tanh = 0x2f,
+ /** Eltwise: parametric exponential linear unit (elu) */
+ mkldnn_eltwise_elu = 0x3f,
+ /** Eltwise: square */
+ mkldnn_eltwise_square = 0x4f,
+ /** Eltwise: abs */
+ mkldnn_eltwise_abs = 0x5f,
+ /** Eltwise: square root */
+ mkldnn_eltwise_sqrt = 0x6f,
+ /** Eltwise: linear */
+ mkldnn_eltwise_linear = 0x7f,
+ /** Eltwise: bounded_relu */
+ mkldnn_eltwise_bounded_relu = 0x8f,
+ /** Eltwise: soft_relu */
+ mkldnn_eltwise_soft_relu = 0x9f,
+ /** Eltwise: logistic */
+ mkldnn_eltwise_logistic = 0xaf,
+ /** Max pooling */
+ mkldnn_pooling_max = 0x1ff,
+ /** Average pooling include padding */
+ mkldnn_pooling_avg_include_padding = 0x2ff,
+ /** Average pooling exclude padding */
+ mkldnn_pooling_avg_exclude_padding = 0x3ff,
+ mkldnn_pooling_avg = mkldnn_pooling_avg_exclude_padding,
+ /** Local response normalization (LRN) across multiple channels */
+ mkldnn_lrn_across_channels = 0xaff,
+ /** LRN within a single channel */
+ mkldnn_lrn_within_channel = 0xbff,
+ /** RNN cell */
+ mkldnn_vanilla_rnn = 0x1fff,
+ /** LSTM cell */
+ mkldnn_vanilla_lstm = 0x2fff,
+ /** GRU cell */
+ mkldnn_vanilla_gru = 0x3fff,
+ /** GRU cell with linear before reset
+ *
+ * Modification of original GRU cell. Differs from #mkldnn_vanilla_gru
+ * in how the new memory gate is calculated:
+ * \f[ c_t = tanh(W_c*x_t + b_{c_x} + r_t*(U_c*h_{t-1}+b_{c_h})) \f]
+ * Primitive expects 4 biases on input:
+ * \f$[b_{u}, b_{r}, b_{c_x}, b_{c_h}]\f$
+ * */
+ mkldnn_gru_linear_before_reset = 0x4fff,
+} mkldnn_alg_kind_t;
+
+/** Flags for batch-normalization primititve. */
+typedef enum {
+ /** Use global statistics
+ *
+ * If specified
+ * - on forward propagation use mean and variance provided by user (input)
+ * - on backward propagation reduces the amount of computations, since
+ * mean and variance are considered as constants
+ *
+ * If not specified:
+ * - on forward propagation mean and variance are computed and stored in
+ * output
+ * - on backward propagation compute full derivative wrt to data
+ */
+ mkldnn_use_global_stats = 0x1U,
+ /** Use scale and shift parameters
+ *
+ * If specified:
+ * - on forward propagation use scale and shift (aka scale and bias) for
+ * the batch normalization results
+ * - on backward propagation (for prop_kind == #mkldnn_backward) compute
+ * diff wrt to scale and shift (hence one extra output used)
+ *
+ * If no specified:
+ * - on backward propagation prop_kind == #mkldnn_backward_data has the
+ * same behavior as prop_kind == #mkldnn_backward
+ */
+ mkldnn_use_scaleshift = 0x2U,
+ /** Fuse with ReLU
+ *
+ * If specified:
+ * - on inference this option behaves the same as if the primitive were
+ * fused with ReLU via post ops API
+ * - on training primitive requires workspace (required to be able to
+ * perform backward pass)
+ */
+ mkldnn_fuse_bn_relu = 0x4U,
+} mkldnn_batch_normalization_flag_t;
+
+/** @} */
+
+/** @addtogroup c_api_types_memory Memory
+ * @{ */
+
+/** Maximum number of dimensions a tensor can have. Only restricts the amount
+ * of space used for the tensor description. Individual computational
+ * primitives may support only tensors of certain dimensions. */
+#define MKLDNN_MAX_NDIMS 12
+
+/** A type to describe tensor dimension. */
+typedef int64_t mkldnn_dim_t;
+
+/** A type to describe tensor dimensions. */
+typedef mkldnn_dim_t mkldnn_dims_t[MKLDNN_MAX_NDIMS];
+
+/** A type to describe strides within a tensor. */
+typedef mkldnn_dim_t mkldnn_strides_t[MKLDNN_MAX_NDIMS];
+
+/** Generic description of blocked data layout for most memory formats.
+ *
+ * @sa @ref understanding_memory_formats */
+typedef struct {
+ /** The strides between the outermost blocks.
+ * In case of plain (non-blocked) formats the strides between dimensions. */
+ mkldnn_dims_t strides;
+ /* Innermost section
+ * ASSUMPTION: the innermost blocks are always dense */
+ /** The number of innermost blocks, e.g. 3 in case of `OIhw_4i16o4i_` */
+ int inner_nblks;
+ /** The size of the blocks, e.g. `{4, 16, 4}` in case of `OIhw_4i16o4i` */
+ mkldnn_dims_t inner_blks;
+ /** The logical indices of the blocks, e.g. `{1, 0, 1}` in case of
+ * `4i16o4i`, because `i` is the 1st dim and `o` is the 0st dim */
+ mkldnn_dims_t inner_idxs;
+} mkldnn_blocking_desc_t;
+
+typedef enum {
+ /** Undefined memory format, used for empty memory descriptors. */
+ mkldnn_wino_undef = 0,
+ /** Tensors of weights for 2x3 winograd convolutions. */
+ mkldnn_wino_wei_aaOIoi,
+ mkldnn_wino_wei_aaOio,
+ mkldnn_wino_wei_aaOBiOo,
+ /** Tensor of weights for 4x3 convolution. */
+ mkldnn_wino_wei_OBaaIBOIio
+} mkldnn_wino_memory_format_t;
+
+/** Description of tensor of weights for winograd 2x3 convolution. */
+typedef struct {
+ mkldnn_wino_memory_format_t wino_format;
+ int r;
+ int alpha;
+ int ic;
+ int oc;
+ int ic_block;
+ int oc_block;
+ int ic2_block;
+ int oc2_block;
+ float adj_scale;
+ size_t size;
+} mkldnn_wino_desc_t;
+
+typedef enum {
+ mkldnn_packed_format_undef = 0,
+ mkldnn_ldigo_p,
+ mkldnn_ldgoi_p
+} mkldnn_rnn_packed_memory_format_t;
+
+/* Maximum number of parts of RNN weights tensor that require separate
+ * computation. */
+#define MKLDNN_RNN_MAX_N_PARTS 4
+
+/** Description of tensor of packed weights for rnn. */
+typedef struct {
+ mkldnn_rnn_packed_memory_format_t format;
+ int n_parts;
+ int n;
+ int parts[MKLDNN_RNN_MAX_N_PARTS];
+ size_t part_pack_size[MKLDNN_RNN_MAX_N_PARTS];
+ size_t offset_compensation;
+ size_t size;
+} mkldnn_rnn_packed_desc_t;
+
+typedef enum {
+ mkldnn_memory_extra_flag_none = 0x0U,
+ /** Indicates the weights have an additional buffer, that depends on the
+ * @p compensation_mask.
+ *
+ * For instance, in 4D case with the compensation mask equals (1 << 0)
+ * the additional buffer would consist of OC values:
+ * O[oc : 0,OC] =
+ * -128 * SUM(ic : 0,IC; kh : 0,KH; kw : 0,KW){ weights(oc, ic, kh, kw) }
+ */
+ mkldnn_memory_extra_flag_compensation_conv_s8s8 = 0x1U,
+ mkldnn_memory_extra_flag_scale_adjust = 0x2U,
+} mkldnn_memory_extra_flags_t;
+
+/** Description of extra information stored in memory */
+typedef struct {
+ /** The flags contain arbitrary extra information, such as compensation.
+ * @sa mkldnn_memory_extra_flags_t */
+ uint64_t flags;
+ /** Compensation mask */
+ int compensation_mask;
+ /** Scale applied to the data */
+ float scale_adjust;
+ /** For future backwards compatibility */
+ char reserved[64];
+} mkldnn_memory_extra_desc_t;
+
+/** Memory descriptor. The description is based on a number of dimensions,
+ * dimensions themselves, plus information about elements type and memory
+ * format. Additionally, contains format-specific descriptions of the data
+ * layout. */
+typedef struct {
+ /** Number of dimensions */
+ int ndims;
+ /** Dimensions in the following order:
+ * - CNN data tensors: mini-batch, channel, spatial
+ * (<code>{N, C, [[D,] H,] W}</code>)
+ * - CNN weight tensors: group (optional), output channel, input channel,
+ * spatial (<code>{[G,] O, I, [[D,] H,] W}</code>)
+ * - RNN data tensors: time, mini-batch, channels (<code>{T, N, C}</code>)
+ * or layers, directions, states, mini-batch, channels (<code>{L, D, S, N, C}</code>)
+ * - RNN weight tensor: layers, directions, input channel, gates, output channels
+ * (<code>{L, D, I, G, O}</code>).
+ *
+ * @note
+ * The order of dimensions does not depend on the memory format, so
+ * whether the data is laid out in #mkldnn_nchw or #mkldnn_nhwc
+ * the dims for 4D CN data tensor would be <code>{N, C, H, W}</code>.
+ */
+ mkldnn_dims_t dims;
+ /** Data type of the tensor elements. */
+ mkldnn_data_type_t data_type;
+
+ /** Size of the data including padding in each dimension. */
+ mkldnn_dims_t padded_dims;
+ /** Per-dimension offset from the padding to actual data, the top-level
+ * tensor with offsets applied must lie within the padding area. */
+ mkldnn_dims_t padded_offsets;
+
+ /** Offset from memory origin to the current block, non-zero only in
+ * a description of a memory sub-block. */
+ mkldnn_dim_t offset0;
+
+ /** Memory format kind. */
+ mkldnn_format_kind_t format_kind;
+ union {
+ /** Description of the data layout for memory formats that use
+ * blocking. */
+ mkldnn_blocking_desc_t blocking;
+ /** Tensor of weights for integer 8bit winograd convolution. */
+ mkldnn_wino_desc_t wino_desc;
+ /** Tensor of packed weights for RNN. */
+ mkldnn_rnn_packed_desc_t rnn_packed_desc;
+ /* ... other descriptions possible */
+ } format_desc;
+
+ mkldnn_memory_extra_desc_t extra;
+} mkldnn_memory_desc_t;
+
+/** @struct mkldnn_memory
+ * An opaque structure to describe a memory. */
+struct mkldnn_memory;
+
+/** A memory handle. */
+typedef struct mkldnn_memory *mkldnn_memory_t;
+
+/** A constant memory handle. */
+typedef const struct mkldnn_memory *const_mkldnn_memory_t;
+
+#define MKLDNN_NATIVE_HANDLE_NONE (NULL)
+#define MKLDNN_NATIVE_HANDLE_ALLOCATE ((void *)(size_t)-1)
+
+/** @} */
+
+/** @addtogroup c_api_types_op_descs Operation descriptors
+ * @{*/
+
+/** A pointer to any of the operation descriptors. */
+typedef void *mkldnn_op_desc_t;
+/** A pointer to any of the operation descriptors (constant variant). */
+typedef const void *const_mkldnn_op_desc_t;
+
+/** A descriptor of a convolution operation. */
+typedef struct {
+ /** The kind of primitive. Used for self-identifying the primitive
+ * descriptor. Must be #mkldnn_convolution. */
+ mkldnn_primitive_kind_t primitive_kind;
+ /** The kind of propagation. Possible values: #mkldnn_forward_training,
+ * #mkldnn_forward_inference, #mkldnn_backward_data,
+ * #mkldnn_backward_weights, and #mkldnn_backward_bias. */
+ mkldnn_prop_kind_t prop_kind;
+ /** The kind of the convolution algorithm. Possible values:
+ * #mkldnn_convolution_direct. */
+ mkldnn_alg_kind_t alg_kind;
+ /** Source memory descriptor. */
+ mkldnn_memory_desc_t src_desc;
+ /** Source gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_src_desc;
+ /** Weights memory descriptor. */
+ mkldnn_memory_desc_t weights_desc;
+ /** Weights gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_weights_desc;
+ /** Bias memory descriptor. */
+ mkldnn_memory_desc_t bias_desc;
+ /** Bias gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_bias_desc;
+ /** Destination memory descriptor. */
+ mkldnn_memory_desc_t dst_desc;
+ /** Destination gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_dst_desc;
+ /** Convolution strides in each spatial dimension. */
+ mkldnn_dims_t strides;
+ /** Convolution dilates in each spatial dimension. */
+ mkldnn_dims_t dilates;
+ /** Padding in each spatial dimension. padding[0] is a padding in the
+ * beginning (@p padding_l), padding[1] is a padding in the end (@p
+ * padding_r). */
+ mkldnn_dims_t padding[2];
+ /** The kind of padding to use. */
+ mkldnn_padding_kind_t padding_kind;
+ /** The accumulator data type. Initialized automatically. */
+ mkldnn_data_type_t accum_data_type;
+} mkldnn_convolution_desc_t;
+
+/** A descriptor of a deconvolution operation. */
+typedef mkldnn_convolution_desc_t mkldnn_deconvolution_desc_t;
+
+/** A descriptor of a shuffle operation. */
+typedef struct {
+ /** The kind of primitive. Used for self-identifying the primitive
+ * descriptor. Must be #mkldnn_convolution. */
+ mkldnn_primitive_kind_t primitive_kind;
+ /** The kind of propagation. Possible values: #mkldnn_forward_training,
+ * #mkldnn_forward_inference, and #mkldnn_backward_data. */
+ mkldnn_prop_kind_t prop_kind;
+ /** Source and destination memory descriptor,
+ * and source and destination gradient memory descriptor. */
+ mkldnn_memory_desc_t data_desc;
+ /** axis for shuffling. */
+ int axis;
+ /** number of groups in group convolution */
+ mkldnn_dim_t group_size;
+} mkldnn_shuffle_desc_t;
+
+/** A descriptor of a element-wise operation. */
+typedef struct {
+ /** The kind of primitive. Used for self-identifying the primitive
+ * descriptor. Must be #mkldnn_eltwise. */
+ mkldnn_primitive_kind_t primitive_kind;
+ /** The kind of propagation. Possible values: #mkldnn_forward_training,
+ * #mkldnn_forward_inference, #mkldnn_backward, and #mkldnn_backward_data.
+ */
+ mkldnn_prop_kind_t prop_kind;
+ /** The kind of eltwise algorithm. Possible values: #mkldnn_eltwise_relu,
+ * #mkldnn_eltwise_tanh, #mkldnn_eltwise_elu, #mkldnn_eltwise_square,
+ * #mkldnn_eltwise_abs, #mkldnn_eltwise_sqrt, #mkldnn_eltwise_linear,
+ * #mkldnn_eltwise_bounded_relu, #mkldnn_eltwise_soft_relu, and
+ * #mkldnn_eltwise_logistic. */
+ mkldnn_alg_kind_t alg_kind;
+ /** Source and destination memory descriptor. */
+ mkldnn_memory_desc_t data_desc;
+ /** Source and destination gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_data_desc;
+ /** Algorithm specific parameter.
+ * Accordance table:
+ * - #mkldnn_eltwise_relu: @p alpha -- negative slope, @p beta ignored
+ * - #mkldnn_eltwise_tanh: @p alpha and @p beta ignored
+ * - #mkldnn_eltwise_elu: @p alpha -- negative slope, @p beta ignored
+ * - #mkldnn_eltwise_square: @p alpha and @p beta ignored
+ * - #mkldnn_eltwise_abs: @p alpha and @p beta ignored
+ * - #mkldnn_eltwise_sqrt: @p alpha and @p beta ignored
+ * - #mkldnn_eltwise_linear: @p alpha -- scale, @p beta -- shift
+ * - #mkldnn_eltwise_bounded_relu: @p alpha -- upper bound, @p beta ignored
+ * - #mkldnn_eltwise_soft_relu: @p alpha and @p beta ignored
+ * - #mkldnn_eltwise_logistic: @p alpha and @p beta ignored
+ */
+ float alpha, beta;
+} mkldnn_eltwise_desc_t;
+
+/** A descriptor of a Softmax operation. */
+typedef struct {
+ /** The kind of primitive. Used for self-identifying the primitive
+ * descriptor. Must be #mkldnn_softmax. */
+ mkldnn_primitive_kind_t primitive_kind;
+ /** The kind of propagation. Possible values: #mkldnn_forward_training and
+ * #mkldnn_forward_inference. */
+ mkldnn_prop_kind_t prop_kind;
+ /** Source and destination memory descriptor. */
+ mkldnn_memory_desc_t data_desc;
+ /** Source and Destination of gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_desc;
+ /** The axis along which to perform the softmax. */
+ int softmax_axis;
+} mkldnn_softmax_desc_t;
+
+/** A descriptor of a pooling operation. */
+typedef struct {
+ /** The kind of primitive. Used for self-identifying the primitive
+ * descriptor. Must be #mkldnn_pooling. */
+ mkldnn_primitive_kind_t primitive_kind;
+ /** The kind of propagation. Possible values: #mkldnn_forward_training,
+ * #mkldnn_forward_inference, #mkldnn_backward, and #mkldnn_backward_data.
+ */
+ mkldnn_prop_kind_t prop_kind;
+ /** The kind of pooling algorithm. Possible values: #mkldnn_pooling_max and
+ * #mkldnn_pooling_avg. */
+ mkldnn_alg_kind_t alg_kind;
+ /** Source memory descriptor. */
+ mkldnn_memory_desc_t src_desc;
+ /** Source gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_src_desc;
+ /** Destination memory descriptor. */
+ mkldnn_memory_desc_t dst_desc;
+ /** Destination gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_dst_desc;
+ /** Pooling kernel strides for spatial dimensions. */
+ mkldnn_dims_t strides;
+ /** Pooling kernel spatial dimensions. */
+ mkldnn_dims_t kernel;
+ /** Padding in each spatial dimension. padding[0] is a padding in the
+ * beginning (@p padding_l), padding[1] is a padding in the end (@p
+ * padding_r). */
+ mkldnn_dims_t padding[2];
+ /** The kind of padding to use. */
+ mkldnn_padding_kind_t padding_kind;
+ /** The accumulator data type. Initialized automatically. */
+ mkldnn_data_type_t accum_data_type;
+} mkldnn_pooling_desc_t;
+
+/** A descriptor of a Local Response Normalization (LRN) operation. */
+typedef struct {
+ /** The kind of primitive. Used for self-identifying the primitive
+ * descriptor. Must be #mkldnn_lrn. */
+ mkldnn_primitive_kind_t primitive_kind;
+ /** The kind of propagation. Possible values: #mkldnn_forward_training,
+ * #mkldnn_forward_inference, #mkldnn_backward, and #mkldnn_backward_data.
+ */
+ mkldnn_prop_kind_t prop_kind;
+ /** LRN algorithm. Possible values: #mkldnn_lrn_within_channel and
+ * #mkldnn_lrn_across_channels. */
+ mkldnn_alg_kind_t alg_kind;
+ /** Source and destination memory descriptor. */
+ mkldnn_memory_desc_t data_desc;
+ /** Source and destination gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_data_desc;
+ /** The number of channels to sum over (for cross-channel LRN) or the side
+ * length of the square region to sum over (for within-channel LRN). */
+ mkldnn_dim_t local_size;
+ /** LRN alpha parameter. */
+ float lrn_alpha;
+ /** LRN beta parameter. */
+ float lrn_beta;
+ /** LRN k parameter. */
+ float lrn_k;
+} mkldnn_lrn_desc_t;
+
+/** A descriptor of a Batch Normalization operation. */
+typedef struct {
+ /** The kind of primitive. Used for self-identifying the primitive
+ * descriptor. Must be #mkldnn_batch_normalization. */
+ mkldnn_primitive_kind_t primitive_kind;
+ /** The kind of propagation. Possible values: #mkldnn_forward_training,
+ * #mkldnn_forward_inference, #mkldnn_backward, and #mkldnn_backward_data.
+ */
+ mkldnn_prop_kind_t prop_kind;
+ /** Source and destination memory descriptor. */
+ mkldnn_memory_desc_t data_desc;
+ /** Source and destination gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_data_desc;
+ /** Scale and shift data and gradient memory descriptors.
+ *
+ * Scaleshift memory descriptor uses 2D #mkldnn_nc format[2,Channels]. 1-st
+ * dimension contains gamma parameter, 2-nd dimension contains beta
+ * parameter. */
+ mkldnn_memory_desc_t data_scaleshift_desc;
+ mkldnn_memory_desc_t diff_data_scaleshift_desc;
+ /** Mean and variance data memory descriptors.
+ *
+ * Mean and variance memory descriptors use 1D #mkldnn_x format[Channels].
+ */
+ mkldnn_memory_desc_t mean_desc;
+ mkldnn_memory_desc_t variance_desc;
+ /** Batch normalization epsilon parameter. */
+ float batch_norm_epsilon;
+ unsigned flags;
+} mkldnn_batch_normalization_desc_t;
+
+/** A descriptor of an inner product operation. */
+typedef struct {
+ /** The kind of primitive. Used for self-identifying the primitive
+ * descriptor. Must be #mkldnn_inner_product. */
+ mkldnn_primitive_kind_t primitive_kind;
+ /** The kind of propagation. Possible values: #mkldnn_forward_training,
+ * #mkldnn_forward_inference, #mkldnn_backward_data,
+ * #mkldnn_backward_weights, and #mkldnn_backward_bias. */
+ mkldnn_prop_kind_t prop_kind;
+ /** Source memory descriptor. */
+ mkldnn_memory_desc_t src_desc;
+ /** Source gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_src_desc;
+ /** Weights memory descriptor. */
+ mkldnn_memory_desc_t weights_desc;
+ /** Weights gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_weights_desc;
+ /** Bias memory descriptor. */
+ mkldnn_memory_desc_t bias_desc;
+ /** Bias gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_bias_desc;
+ /** Destination memory descriptor. */
+ mkldnn_memory_desc_t dst_desc;
+ /** Destination gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_dst_desc;
+ /** The accumulator data type. Initialized automatically. */
+ mkldnn_data_type_t accum_data_type;
+} mkldnn_inner_product_desc_t;
+
+/** Flags for RNN cell. */
+typedef enum {
+ mkldnn_rnn_cell_with_relu = 0x1U,
+ mkldnn_rnn_cell_with_clipping = 0x2U,
+} mkldnn_rnn_cell_flags_t;
+
+typedef struct {
+ /** RNN cell kind. Must be one of #mkldnn_vanilla_rnn,
+ * #mkldnn_vanilla_lstm, #mkldnn_vanilla_gru,
+ * or #mkldnn_gru_linear_before_reset. */
+ mkldnn_alg_kind_t cell_kind;
+ /** Activation function used. Must be either #mkldnn_eltwise_relu or
+ * #mkldnn_eltwise_tanh. */
+ mkldnn_alg_kind_t activation_kind;
+ /** RNN cell flags */
+ unsigned int flags;
+ /** @c alpha is a negative slope parameter (used only if
+ * `(flags & #mkldnn_rnn_cell_with_relu) != 0`) */
+ float alpha;
+ /** clipping parameter (used only if
+ * `(flags & #mkldnn_rnn_cell_with_clipping) != 0`) */
+ float clipping;
+} mkldnn_rnn_cell_desc_t;
+
+/** A direction of RNN primitive execution. */
+typedef enum {
+ /* Unidirectional execution of RNN primitive from left to right. */
+ mkldnn_unidirectional_left2right,
+ /* Unidirectional execution of RNN primitive from right to left. */
+ mkldnn_unidirectional_right2left,
+ /* Bidirectional execution of RNN primitive with concatenation of the
+ * results. */
+ mkldnn_bidirectional_concat,
+ /* Bidirectional execution of RNN primitive with summation of the
+ * results. */
+ mkldnn_bidirectional_sum,
+ mkldnn_unidirectional = mkldnn_unidirectional_left2right,
+} mkldnn_rnn_direction_t;
+
+/** A descriptor for an RNN operation. */
+typedef struct {
+ /** The kind of primitive. Used for self-identifying the primitive
+ * descriptor. Must be #mkldnn_rnn. */
+ mkldnn_primitive_kind_t primitive_kind;
+ /** The kind of propagation. Possible values: #mkldnn_forward_training,
+ * #mkldnn_forward_inference, and #mkldnn_backward. */
+ mkldnn_prop_kind_t prop_kind;
+ /** The RNN cell desc. */
+ mkldnn_rnn_cell_desc_t cell_desc;
+ /** The direction of RNN primitive execution. */
+ mkldnn_rnn_direction_t direction;
+ /** Source layer memory descriptor. */
+ mkldnn_memory_desc_t src_layer_desc;
+ /** Source iteration memory descriptor. */
+ mkldnn_memory_desc_t src_iter_desc;
+ /** Weights layer memory descriptor. */
+ mkldnn_memory_desc_t weights_layer_desc;
+ /** Weights iteration memory descriptor. */
+ mkldnn_memory_desc_t weights_iter_desc;
+ /** Bias memory descriptor. */
+ mkldnn_memory_desc_t bias_desc;
+ /** Destination layer memory descriptor. */
+ mkldnn_memory_desc_t dst_layer_desc;
+ /** Destination iter memory descriptor. */
+ mkldnn_memory_desc_t dst_iter_desc;
+ /** Source gradient layer memory descriptor. */
+ mkldnn_memory_desc_t diff_src_layer_desc;
+ /** Source gradient iter memory descriptor. */
+ mkldnn_memory_desc_t diff_src_iter_desc;
+ /** Weights gradient layer memory descriptor. */
+ mkldnn_memory_desc_t diff_weights_layer_desc;
+ /** Weights gradient iter memory descriptor. */
+ mkldnn_memory_desc_t diff_weights_iter_desc;
+ /** Bias gradient memory descriptor. */
+ mkldnn_memory_desc_t diff_bias_desc;
+ /** Destination gradient layer memory descriptor. */
+ mkldnn_memory_desc_t diff_dst_layer_desc;
+ /** Destination gradient iteration memory descriptor. */
+ mkldnn_memory_desc_t diff_dst_iter_desc;
+} mkldnn_rnn_desc_t;
+
+/** @} */
+
+/** @addtogroup c_api_engine_types Engine
+ * @{ */
+
+/** @brief Kinds of engines. */
+typedef enum {
+ /** An unspecified engine. */
+ mkldnn_any_engine,
+ /** CPU engine. */
+ mkldnn_cpu,
+} mkldnn_engine_kind_t;
+
+/** @struct mkldnn_engine
+ * @brief An opaque structure to describe an engine. */
+struct mkldnn_engine;
+/** @brief An engine handle. */
+typedef struct mkldnn_engine *mkldnn_engine_t;
+#if 0
+/* FIXME: looks like this never happens */
+/** @brief A constant engine handle. */
+typedef const struct mkldnn_engine *const_mkldnn_engine_t;
+#endif
+
+/** @} */
+
+/** @addtogroup c_api_primitive_desc_iterators Primitive descriptor iterators
+ * @{ */
+
+/** @struct mkldnn_primitive_desc_iterator
+ * @brief An opaque structure to describe a primitive descriptor iterator. */
+struct mkldnn_primitive_desc_iterator;
+
+/** @brief A primitive descriptor iterator handle. */
+typedef struct mkldnn_primitive_desc_iterator
+ *mkldnn_primitive_desc_iterator_t;
+
+/** @brief A constant primitive descriptor iterator handle. */
+typedef const struct mkldnn_primitive_desc_iterator
+ *const_mkldnn_primitive_desc_iterator_t;
+
+/** @} */
+
+/** @addtogroup c_api_primitive_descs Primitive descriptors
+ * @{ */
+
+/** @struct mkldnn_primitive_desc
+ * @brief An opaque structure to describe a primitive descriptor. */
+struct mkldnn_primitive_desc;
+
+/** @brief A primitive descriptor handle. */
+typedef struct mkldnn_primitive_desc *mkldnn_primitive_desc_t;
+
+/** @brief A constant primitive descriptor handle. */
+typedef const struct mkldnn_primitive_desc *const_mkldnn_primitive_desc_t;
+
+/** @} */
+
+/** @addtogroup c_api_primitive_attr Primitive descriptor attributes
+ * @{ */
+
+/** Scratchpad mode */
+typedef enum {
+ /** The library manages scratchpad (default) */
+ mkldnn_scratchpad_mode_library,
+ /** A user shall query and provide the scratchpad memory to primitives */
+ mkldnn_scratchpad_mode_user,
+} mkldnn_scratchpad_mode_t;
+
+/** @struct mkldnn_primitive_attr
+ * @brief An opaque structure for primitive descriptor attributes.
+ *
+ * Attributes may contain:
+ * - output scales (to scale the result prior to storing it to the memory)
+ */
+struct mkldnn_primitive_attr;
+
+/** @brief A primitive descriptor attributes handle that controls primitive
+ * behavior. */
+typedef struct mkldnn_primitive_attr *mkldnn_primitive_attr_t;
+
+/** @brief A constant primitive descriptor attributes handle. */
+typedef const struct mkldnn_primitive_attr *const_mkldnn_primitive_attr_t;
+
+/** @struct mkldnn_post_ops
+ * @brief An opaque structure for a chain of post operations.
+ *
+ * mkldnn_post_ops can be used to perform some (trivial) operations like
+ * accumulation or eltwise after certain primitives like convolution.
+ *
+ * Post operations might be combined together, making a chain of post
+ * operations. For instance one can configure convolution followed by
+ * accumulation followed by eltwise. This might be especially beneficial
+ * for residual learning blocks.
+ *
+ * @warning
+ * Of course not all combinations are supported, so the user should handle
+ * errors accordingly.
+ *
+ * Supported post operations:
+ * - accumulation (base primitive: convolution)
+ * - eltwise (base primitive: convolution)
+ */
+struct mkldnn_post_ops;
+
+/** @brief A post operation chain handle. */
+typedef struct mkldnn_post_ops *mkldnn_post_ops_t;
+
+/** @brief A constant post operation chain handle. */
+typedef const struct mkldnn_post_ops *const_mkldnn_post_ops_t;
+
+/** @} */
+
+/** @addtogroup c_api_types_primitive Primitive
+ * @{ */
+
+/** @struct mkldnn_primitive
+ * An opaque structure to describe a primitive. */
+struct mkldnn_primitive;
+/** A primitive handle. */
+typedef struct mkldnn_primitive *mkldnn_primitive_t;
+/** A constant primitive handle. */
+typedef const struct mkldnn_primitive *const_mkldnn_primitive_t;
+
+/** @addtogroup c_api_types_arguments Argument indices
+ * @{ */
+
+#define MKLDNN_ARG_SRC_0 1
+#define MKLDNN_ARG_SRC MKLDNN_ARG_SRC_0
+#define MKLDNN_ARG_SRC_LAYER MKLDNN_ARG_SRC_0
+#define MKLDNN_ARG_FROM MKLDNN_ARG_SRC_0
+
+#define MKLDNN_ARG_SRC_1 2
+#define MKLDNN_ARG_SRC_ITER MKLDNN_ARG_SRC_1
+
+#define MKLDNN_ARG_DST_0 17
+#define MKLDNN_ARG_DST MKLDNN_ARG_DST_0
+#define MKLDNN_ARG_TO MKLDNN_ARG_DST_0
+#define MKLDNN_ARG_DST_LAYER MKLDNN_ARG_DST_0
+
+#define MKLDNN_ARG_DST_1 18
+#define MKLDNN_ARG_DST_ITER MKLDNN_ARG_DST_1
+
+#define MKLDNN_ARG_WEIGHTS_0 33
+#define MKLDNN_ARG_WEIGHTS MKLDNN_ARG_WEIGHTS_0
+#define MKLDNN_ARG_SCALE_SHIFT MKLDNN_ARG_WEIGHTS_0
+#define MKLDNN_ARG_WEIGHTS_LAYER MKLDNN_ARG_WEIGHTS_0
+
+#define MKLDNN_ARG_WEIGHTS_1 34
+#define MKLDNN_ARG_WEIGHTS_ITER MKLDNN_ARG_WEIGHTS_1
+
+#define MKLDNN_ARG_BIAS 41
+
+#define MKLDNN_ARG_MEAN 49
+#define MKLDNN_ARG_VARIANCE 50
+
+#define MKLDNN_ARG_WORKSPACE 64
+#define MKLDNN_ARG_SCRATCHPAD 80
+
+#define MKLDNN_ARG_DIFF_SRC_0 129
+#define MKLDNN_ARG_DIFF_SRC MKLDNN_ARG_DIFF_SRC_0
+#define MKLDNN_ARG_DIFF_SRC_LAYER MKLDNN_ARG_DIFF_SRC_0
+
+#define MKLDNN_ARG_DIFF_SRC_1 130
+#define MKLDNN_ARG_DIFF_SRC_ITER MKLDNN_ARG_DIFF_SRC_1
+
+#define MKLDNN_ARG_DIFF_DST_0 145
+#define MKLDNN_ARG_DIFF_DST MKLDNN_ARG_DIFF_DST_0
+#define MKLDNN_ARG_DIFF_DST_LAYER MKLDNN_ARG_DIFF_DST_0
+
+#define MKLDNN_ARG_DIFF_DST_1 146
+#define MKLDNN_ARG_DIFF_DST_ITER MKLDNN_ARG_DIFF_DST_1
+
+#define MKLDNN_ARG_DIFF_WEIGHTS_0 161
+#define MKLDNN_ARG_DIFF_WEIGHTS MKLDNN_ARG_DIFF_WEIGHTS_0
+#define MKLDNN_ARG_DIFF_SCALE_SHIFT MKLDNN_ARG_DIFF_WEIGHTS_0
+#define MKLDNN_ARG_DIFF_WEIGHTS_LAYER MKLDNN_ARG_DIFF_WEIGHTS_0
+
+#define MKLDNN_ARG_DIFF_WEIGHTS_1 162
+#define MKLDNN_ARG_DIFF_WEIGHTS_ITER MKLDNN_ARG_DIFF_WEIGHTS_1
+
+#define MKLDNN_ARG_DIFF_BIAS 169
+
+#define MKLDNN_ARG_MULTIPLE_SRC 1024
+#define MKLDNN_ARG_MULTIPLE_DST 2048
+
+/** @} */
+
+/** An auxiliary structure to specify primitive's inputs/outputs at execution
+ *
+ * @warning
+ * With this API it's impossible to preserve constness of memory, so all
+ * memories are passed w/o const qualifier. However only memories with
+ * output semantics might be changed during the execution */
+typedef struct {
+ int arg; /**< An argument index, e.g. MKLDNN_ARG_SRC */
+ mkldnn_memory_t memory; /**< Input/output memory */
+} mkldnn_exec_arg_t;
+
+/** @} */
+
+/** @addtogroup c_api_types_query Queries
+ * @{ */
+
+/** Primitive descriptor query specification
+ *
+ * For generic function mkldnn_primitive_desc_query(), the type of result must
+ * agree with the queried argument. The correspondence table:
+ * Query | type of result
+ * --------------------------------------------------------------
+ * #mkldnn_query_engine | mkldnn_engine_t *
+ * #mkldnn_query_scratchpad_engine | mkldnn_engine_t *
+ * #mkldnn_query_primitive_kind | mkldnn_primitive_kind_t *
+ * *_s32 | int *
+ * *_s64 | mkldnn_dim_t * (same as int64_t *)
+ * *_f64 | double *
+ * *_str | const char **
+ * #mkldnn_query_op_d | const_mkldnn_op_desc_t *
+ * *_md | const mkldnn_memory_desc_t **
+ * *_${op}_d | const mkldnn_${op}_desc_t **
+ * *_pd | const_mkldnn_primitive_desc_t *
+ *
+ * @note
+ * Rule of thumb: all opaque types and structures are returned by
+ * reference. All numbers are returned by value.
+ *
+ * @warning
+ * All returned references point to constant objects and are valid only
+ * during the lifetime of the queried primitive descriptor. Returned objects
+ * must not be destroyed by the user. If you need to keep the object longer
+ * than the lifetime of the queried primitive descriptor, use
+ * mkldnn_primitive_desc_clone() to make a copy. */
+typedef enum {
+ mkldnn_query_undef = 0, /**< no query */
+
+ mkldnn_query_engine, /**< execution engine */
+ mkldnn_query_primitive_kind, /**< primitive kind */
+
+ mkldnn_query_num_of_inputs_s32, /**< number of inputs expected */
+ mkldnn_query_num_of_outputs_s32, /**< number of outputs expected */
+
+ mkldnn_query_time_estimate_f64, /**< runtime estimation (seconds) */
+ mkldnn_query_memory_consumption_s64, /**< memory consumption -- extra
+ (scratch) memory, additional to all
+ inputs and outputs memory (bytes) */
+
+ mkldnn_query_scratchpad_engine, /**< scratchpad engine -- engine to be used
+ for creating scratchpad memory */
+
+ mkldnn_query_impl_info_str, /**< implementation name */
+
+ /* memory and op descriptor section */
+ mkldnn_query_some_d = 64, /**< stub */
+ mkldnn_query_op_d, /**< op descriptor */
+ mkldnn_query_convolution_d, /**< convolution descriptor */
+ mkldnn_query_deconvolution_d, /**< deconvolution descriptor */
+ mkldnn_query_shuffle_d, /**< shuffle descriptor */
+ mkldnn_query_eltwise_d, /**< eltwise descriptor */
+ mkldnn_query_softmax_d, /**< softmax descriptor */
+ mkldnn_query_pooling_d, /**< pooling descriptor */
+ mkldnn_query_lrn_d, /**< lrn descriptor */
+ mkldnn_query_batch_normalization_d, /**< batch normalization descriptor */
+ mkldnn_query_inner_product_d, /**< inner product descriptor */
+ mkldnn_query_rnn_d, /**< rnn descriptor */
+
+ /* memory descriptor section */
+ mkldnn_query_some_md = 128, /**< stub */
+ mkldnn_query_src_md, /**< source memory desc */
+ mkldnn_query_diff_src_md, /**< source gradient memory desc */
+ mkldnn_query_weights_md, /**< weights memory descriptor desc */
+ mkldnn_query_diff_weights_md, /**< weights grad. memory desc */
+ mkldnn_query_dst_md, /**< destination memory desc */
+ mkldnn_query_diff_dst_md, /**< destination grad. memory desc */
+ mkldnn_query_workspace_md, /**< workspace memory desc */
+ mkldnn_query_scratchpad_md, /**< scratchpad memory desc */
+} mkldnn_query_t;
+
+/** @} */
+
+/** @addtogroup c_api_types_stream Execution stream
+ * @{ */
+
+/** @brief Stream flags. */
+typedef enum {
+ /** A default stream configuration. */
+ mkldnn_stream_default_flags = 0x0U,
+} mkldnn_stream_flags_t;
+
+/** @struct mkldnn_stream
+ * An opaque structure to describe an execution stream. */
+struct mkldnn_stream;
+/** An execution stream handle. */
+typedef struct mkldnn_stream *mkldnn_stream_t;
+/** A constant execution stream handle. */
+typedef const struct mkldnn_stream *const_mkldnn_stream_t;
+
+/** @} */
+/** @} */
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h b/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h
new file mode 100644
index 0000000000..a2713deccb
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h
@@ -0,0 +1,32 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MKLDNN_VERSION_H
+#define MKLDNN_VERSION_H
+
+/* Major version of MKL-DNN */
+#define MKLDNN_VERSION_MAJOR 0
+
+/* Minor version of MKL-DNN */
+#define MKLDNN_VERSION_MINOR 90
+
+/* Patch version of MKL-DNN */
+#define MKLDNN_VERSION_PATCH 0
+
+/* Git Commit Hash of MKL-DNN */
+#define MKLDNN_VERSION_HASH "096bda1ca23324879f2df5a129e610e4405f775c"
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h.in b/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h.in
new file mode 100644
index 0000000000..5ee0126188
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/include/mkldnn_version.h.in
@@ -0,0 +1,32 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MKLDNN_VERSION_H
+#define MKLDNN_VERSION_H
+
+/* Major version of MKL-DNN */
+#define MKLDNN_VERSION_MAJOR @MKLDNN_VERSION_MAJOR@
+
+/* Minor version of MKL-DNN */
+#define MKLDNN_VERSION_MINOR @MKLDNN_VERSION_MINOR@
+
+/* Patch version of MKL-DNN */
+#define MKLDNN_VERSION_PATCH @MKLDNN_VERSION_PATCH@
+
+/* Git Commit Hash of MKL-DNN */
+#define MKLDNN_VERSION_HASH "@MKLDNN_VERSION_HASH@"
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/batch_normalization.cpp b/thirdparty/oidn/mkl-dnn/src/common/batch_normalization.cpp
new file mode 100644
index 0000000000..1a51d8562b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/batch_normalization.cpp
@@ -0,0 +1,104 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::alg_kind;
+using namespace mkldnn::impl::types;
+
+namespace {
+status_t bnrm_desc_init(batch_normalization_desc_t *bnrm_desc,
+ prop_kind_t prop_kind, const memory_desc_t *data_desc,
+ const memory_desc_t *diff_data_desc, float epsilon, unsigned flags) {
+ bool args_ok = true
+ && !any_null(bnrm_desc, data_desc)
+ && one_of(prop_kind, forward_training, forward_inference,
+ backward_data, backward)
+ && IMPLICATION(prop_kind & backward, diff_data_desc != nullptr);
+ if (!args_ok) return invalid_arguments;
+
+ auto bd = batch_normalization_desc_t();
+ bd.primitive_kind = primitive_kind::batch_normalization;
+ bd.prop_kind = prop_kind;
+
+ bd.data_desc = *data_desc;
+ bd.diff_data_desc = zero_md();
+ if ( one_of(bd.prop_kind,backward_data, backward) )
+ bd.diff_data_desc = *diff_data_desc;
+
+ dims_t scaleshift_dims = { 2, data_desc->dims[1] };
+ mkldnn_memory_desc_init_by_tag(&bd.data_scaleshift_desc, 2,
+ scaleshift_dims, data_type::f32, mkldnn_nc);
+ bd.diff_data_scaleshift_desc = zero_md();
+ if (bd.prop_kind == backward) {
+ bd.diff_data_scaleshift_desc = bd.data_scaleshift_desc;
+ }
+
+ dims_t stats_dims = { data_desc->dims[1] };
+ mkldnn_memory_desc_init_by_tag(&bd.mean_desc, 1, stats_dims,
+ data_type::f32, mkldnn_x);
+ bd.variance_desc = bd.mean_desc;
+ bd.batch_norm_epsilon = epsilon;
+
+ unsigned bnorm_flags =
+ mkldnn_use_global_stats | mkldnn_use_scaleshift | mkldnn_fuse_bn_relu;
+ if ((~bnorm_flags & flags) != 0) return invalid_arguments;
+
+ bd.flags = flags;
+
+ bool consistency = true
+ && utils::one_of(bd.data_desc.ndims, 2, 4, 5);
+ if (bd.prop_kind == backward_data)
+ consistency = consistency
+ && utils::one_of(bd.diff_data_desc.ndims, 2, 4, 5)
+ && array_cmp(bd.diff_data_desc.dims, bd.data_desc.dims,
+ bd.diff_data_desc.ndims);
+ if (!consistency) return invalid_arguments;
+
+ *bnrm_desc = bd;
+ return success;
+}
+}
+
+status_t mkldnn_batch_normalization_forward_desc_init(
+ batch_normalization_desc_t *bnrm_desc, prop_kind_t prop_kind,
+ const memory_desc_t *data_desc, float epsilon, unsigned flags) {
+ if (!one_of(prop_kind, forward_training, forward_inference))
+ return invalid_arguments;
+ return bnrm_desc_init(bnrm_desc, prop_kind, data_desc, nullptr,
+ epsilon, flags);
+}
+
+status_t mkldnn_batch_normalization_backward_desc_init(
+ batch_normalization_desc_t *bnrm_desc, prop_kind_t prop_kind,
+ const memory_desc_t *diff_data_desc, const memory_desc_t *data_desc,
+ float epsilon, unsigned flags) {
+ if (!one_of(prop_kind, backward, backward_data))
+ return invalid_arguments;
+ return bnrm_desc_init(bnrm_desc, prop_kind, data_desc, diff_data_desc,
+ epsilon, flags);
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/batch_normalization_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/batch_normalization_pd.hpp
new file mode 100644
index 0000000000..f61410b33c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/batch_normalization_pd.hpp
@@ -0,0 +1,240 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef BATCH_NORMALIZATION_PD_HPP
+#define BATCH_NORMALIZATION_PD_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive_desc.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct batch_normalization_fwd_pd_t;
+
+struct batch_normalization_pd_t: public primitive_desc_t {
+ static constexpr auto base_pkind = primitive_kind::batch_normalization;
+
+ batch_normalization_pd_t(engine_t *engine,
+ const batch_normalization_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const batch_normalization_fwd_pd_t *hint_fwd_pd)
+ : primitive_desc_t(engine, attr, base_pkind)
+ , desc_(*adesc)
+ , hint_fwd_pd_(hint_fwd_pd)
+ , data_md_(desc_.data_desc)
+ , stat_md_(desc_.mean_desc)
+ , scaleshift_md_(desc_.data_scaleshift_desc)
+ , ws_md_()
+ {}
+
+ const batch_normalization_desc_t *desc() const { return &desc_; }
+ virtual const op_desc_t *op_desc() const override
+ { return reinterpret_cast<const op_desc_t *>(this->desc()); }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual status_t query(query_t what, int idx, void *result) const override {
+ switch (what) {
+ case query::batch_normalization_d:
+ *(const batch_normalization_desc_t**)result = desc(); break;
+ default: return primitive_desc_t::query(what, idx, result);
+ }
+ return status::success;
+ }
+
+ /* common batch_normalization aux functions */
+
+ dim_t MB() const { return data_desc().dims[0]; }
+ dim_t C() const { return data_desc().dims[1]; }
+ dim_t D() const { return ndims() >= 5 ? data_desc().dims[ndims() - 3] : 1; }
+ dim_t H() const { return ndims() >= 4 ? data_desc().dims[ndims() - 2] : 1; }
+ dim_t W() const { return ndims() >= 3 ? data_desc().dims[ndims() - 1] : 1; }
+
+ int ndims() const { return desc_.data_desc.ndims; }
+
+ bool stats_is_src() const { return desc_.flags & mkldnn_use_global_stats; }
+ bool use_scaleshift() const { return desc_.flags & mkldnn_use_scaleshift; }
+ bool use_global_stats() const
+ { return desc_.flags & mkldnn_use_global_stats; }
+ bool fuse_bn_relu() const { return desc_.flags & mkldnn_fuse_bn_relu; }
+ bool with_relu_post_op() const {
+ const auto &p = this->attr()->post_ops_;
+ return p.len_ == 1 && p.entry_[0].is_relu(true, true);
+ }
+
+ bool is_fwd() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ }
+ bool is_bwd() const { return !this->is_fwd(); }
+ bool is_training() const
+ { return desc_.prop_kind == prop_kind::forward_training; }
+
+ bool has_zero_dim_memory() const
+ { return memory_desc_wrapper(desc_.data_desc).has_zero_dim(); }
+
+protected:
+ batch_normalization_desc_t desc_;
+ const batch_normalization_fwd_pd_t *hint_fwd_pd_;
+
+ memory_desc_t data_md_;
+ memory_desc_t stat_md_;
+ memory_desc_t scaleshift_md_;
+
+ memory_desc_t ws_md_;
+
+ void init_default_ws(size_t bits_per_element) {
+ const auto data_mdw = memory_desc_wrapper(data_md_);
+
+ const dim_t data_nelems = data_mdw.nelems(true);
+ const dim_t bits_per_byte = 8;
+ const dims_t ws_sz = { (dim_t)utils::div_up(
+ data_nelems * bits_per_element, bits_per_byte) };
+ mkldnn_memory_desc_init_by_tag(&ws_md_, 1, ws_sz, impl::data_type::u8,
+ format_tag::x);
+ }
+
+private:
+ const memory_desc_t &data_desc() const { return desc_.data_desc; }
+};
+
+struct batch_normalization_fwd_pd_t: public batch_normalization_pd_t {
+ typedef batch_normalization_fwd_pd_t base_class;
+ typedef batch_normalization_fwd_pd_t hint_class;
+
+ batch_normalization_fwd_pd_t(engine_t *engine,
+ const batch_normalization_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const batch_normalization_fwd_pd_t *hint_fwd_pd)
+ : batch_normalization_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (arg == MKLDNN_ARG_SRC) return arg_usage_t::input;
+ if (arg == MKLDNN_ARG_DST) return arg_usage_t::output;
+
+ if (utils::one_of(arg, MKLDNN_ARG_MEAN, MKLDNN_ARG_VARIANCE)) {
+ if (stats_is_src()) return arg_usage_t::input;
+ if (!stats_is_src() && is_training()) return arg_usage_t::output;
+ return arg_usage_t::unused;
+ }
+
+ if (arg == MKLDNN_ARG_SCALE_SHIFT && use_scaleshift())
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_WORKSPACE && is_training() && fuse_bn_relu())
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override {
+ if (index == 0) return &data_md_;
+ if (stats_is_src() && (index == 1 || index == 2)) return &stat_md_;
+ return nullptr;
+ }
+
+ virtual const memory_desc_t *dst_md(int index = 0) const override {
+ if (index == 0) return &data_md_;
+ if (!stats_is_src() && is_training() && (index == 1 || index == 2))
+ return &stat_md_;
+ return nullptr;
+ }
+
+ virtual const memory_desc_t *weights_md(int index = 0) const override
+ { return index == 0 ? &scaleshift_md_ : nullptr; }
+
+ virtual const memory_desc_t *workspace_md(int index = 0) const override
+ { return index == 0 && is_training() && fuse_bn_relu() ? &ws_md_ : nullptr; }
+
+ const memory_desc_t *stat_md() const
+ { return stats_is_src() ? src_md(1) : dst_md(1); }
+
+ virtual int n_inputs() const override
+ { return 1 + 2 * stats_is_src() + use_scaleshift(); }
+ virtual int n_outputs() const override
+ { return 1 + (fuse_bn_relu() + 2 * (!stats_is_src())) * is_training(); }
+};
+
+struct batch_normalization_bwd_pd_t: public batch_normalization_pd_t {
+ typedef batch_normalization_bwd_pd_t base_class;
+ typedef batch_normalization_fwd_pd_t hint_class;
+
+ batch_normalization_bwd_pd_t(engine_t *engine,
+ const batch_normalization_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const batch_normalization_fwd_pd_t *hint_fwd_pd)
+ : batch_normalization_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , diff_data_md_(desc_.diff_data_desc)
+ , diff_scaleshift_md_(desc_.diff_data_scaleshift_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_MEAN,
+ MKLDNN_ARG_VARIANCE, MKLDNN_ARG_DIFF_DST))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_SCALE_SHIFT && use_scaleshift())
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_WORKSPACE && fuse_bn_relu())
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_SRC)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_DIFF_SCALE_SHIFT && use_scaleshift())
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &data_md_ : index <= 2 ? &stat_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_data_md_ : nullptr; }
+ virtual const memory_desc_t *diff_src_md(int index = 0) const override
+ { return index == 0 ? &diff_data_md_ : nullptr; }
+
+ virtual const memory_desc_t *weights_md(int index = 0) const override
+ { return index == 0 ? &scaleshift_md_ : nullptr; }
+ virtual const memory_desc_t *diff_weights_md(int index = 0) const override
+ { return index == 0 ? &diff_scaleshift_md_ : nullptr; }
+
+ virtual const memory_desc_t *workspace_md(int index = 0) const override
+ { return index == 0 && fuse_bn_relu() ? &ws_md_ : nullptr; }
+
+ const memory_desc_t *stat_md() const { return src_md(1); }
+
+ virtual int n_inputs() const override
+ { return 4 + use_scaleshift() + fuse_bn_relu(); }
+ virtual int n_outputs() const override
+ { return 1 + (desc_.prop_kind == prop_kind::backward); }
+
+protected:
+ memory_desc_t diff_data_md_;
+ memory_desc_t diff_scaleshift_md_;
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/c_types_map.hpp b/thirdparty/oidn/mkl-dnn/src/common/c_types_map.hpp
new file mode 100644
index 0000000000..3d43a0fbee
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/c_types_map.hpp
@@ -0,0 +1,550 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef TYPE_MAPPING_HPP
+#define TYPE_MAPPING_HPP
+
+#include "mkldnn_types.h"
+
+namespace mkldnn {
+namespace impl {
+
+// TODO: autogenerate this
+
+using dim_t = mkldnn_dim_t;
+using dims_t = mkldnn_dims_t;
+using stride_t = mkldnn_dim_t;
+using strides_t = mkldnn_strides_t;
+
+using status_t = mkldnn_status_t;
+namespace status {
+ const status_t success = mkldnn_success;
+ const status_t out_of_memory = mkldnn_out_of_memory;
+ const status_t try_again = mkldnn_try_again;
+ const status_t invalid_arguments = mkldnn_invalid_arguments;
+ const status_t not_ready = mkldnn_not_ready;
+ const status_t unimplemented = mkldnn_unimplemented;
+ const status_t iterator_ends = mkldnn_iterator_ends;
+ const status_t runtime_error = mkldnn_runtime_error;
+ const status_t not_required = mkldnn_not_required;
+}
+
+using prop_kind_t = mkldnn_prop_kind_t;
+namespace prop_kind {
+ const prop_kind_t undef = mkldnn_prop_kind_undef;
+ const prop_kind_t forward_training = mkldnn_forward_training;
+ const prop_kind_t forward_inference = mkldnn_forward_inference;
+ const prop_kind_t forward_scoring = mkldnn_forward_scoring;
+ const prop_kind_t forward = mkldnn_forward;
+ const prop_kind_t backward = mkldnn_backward;
+ const prop_kind_t backward_data = mkldnn_backward_data;
+ const prop_kind_t backward_weights = mkldnn_backward_weights;
+ const prop_kind_t backward_bias = mkldnn_backward_bias;
+}
+
+using alg_kind_t = mkldnn_alg_kind_t;
+namespace alg_kind {
+ const alg_kind_t undef = mkldnn_alg_kind_undef;
+ const alg_kind_t convolution_auto = mkldnn_convolution_auto;
+ const alg_kind_t convolution_direct = mkldnn_convolution_direct;
+ const alg_kind_t convolution_winograd = mkldnn_convolution_winograd;
+ const alg_kind_t deconvolution_direct = mkldnn_deconvolution_direct;
+ const alg_kind_t deconvolution_winograd = mkldnn_deconvolution_winograd;
+ const alg_kind_t eltwise_relu = mkldnn_eltwise_relu;
+ const alg_kind_t eltwise_tanh = mkldnn_eltwise_tanh;
+ const alg_kind_t eltwise_elu = mkldnn_eltwise_elu;
+ const alg_kind_t eltwise_square = mkldnn_eltwise_square;
+ const alg_kind_t eltwise_abs = mkldnn_eltwise_abs;
+ const alg_kind_t eltwise_sqrt = mkldnn_eltwise_sqrt;
+ const alg_kind_t eltwise_linear = mkldnn_eltwise_linear;
+ const alg_kind_t eltwise_bounded_relu = mkldnn_eltwise_bounded_relu;
+ const alg_kind_t eltwise_soft_relu = mkldnn_eltwise_soft_relu;
+ const alg_kind_t eltwise_logistic = mkldnn_eltwise_logistic;
+ const alg_kind_t pooling_max = mkldnn_pooling_max;
+ const alg_kind_t pooling_avg = mkldnn_pooling_avg;
+ const alg_kind_t pooling_avg_include_padding = mkldnn_pooling_avg_include_padding;
+ const alg_kind_t pooling_avg_exclude_padding = mkldnn_pooling_avg_exclude_padding;
+ const alg_kind_t lrn_across_channels = mkldnn_lrn_across_channels;
+ const alg_kind_t lrn_within_channel = mkldnn_lrn_within_channel;
+ const alg_kind_t vanilla_rnn = mkldnn_vanilla_rnn;
+ const alg_kind_t vanilla_lstm = mkldnn_vanilla_lstm;
+ const alg_kind_t vanilla_gru = mkldnn_vanilla_gru;
+ const alg_kind_t gru_linear_before_reset = mkldnn_gru_linear_before_reset;
+}
+
+using data_type_t = mkldnn_data_type_t;
+namespace data_type {
+ const data_type_t undef = mkldnn_data_type_undef;
+ const data_type_t f32 = mkldnn_f32;
+ const data_type_t s32 = mkldnn_s32;
+ const data_type_t s8 = mkldnn_s8;
+ const data_type_t u8 = mkldnn_u8;
+}
+
+using scratchpad_mode_t = mkldnn_scratchpad_mode_t;
+namespace scratchpad_mode {
+ const scratchpad_mode_t library = mkldnn_scratchpad_mode_library;
+ const scratchpad_mode_t user = mkldnn_scratchpad_mode_user;
+}
+
+using rnn_packed_format_t = mkldnn_rnn_packed_memory_format_t;
+namespace rnn_packed_format {
+ const rnn_packed_format_t undef = mkldnn_packed_format_undef;
+ const rnn_packed_format_t ldigo_p = mkldnn_ldigo_p;
+ const rnn_packed_format_t ldgoi_p = mkldnn_ldgoi_p;
+}
+
+using format_kind_t = mkldnn_format_kind_t;
+namespace format_kind {
+ const format_kind_t undef = mkldnn_format_kind_undef;
+ const format_kind_t any = mkldnn_format_kind_any;
+ const format_kind_t blocked = mkldnn_blocked;
+ const format_kind_t wino = mkldnn_format_kind_wino;
+ const format_kind_t rnn_packed = mkldnn_format_kind_rnn_packed;
+}
+
+using format_tag_t = mkldnn_format_tag_t;
+namespace format_tag {
+ const format_tag_t undef = mkldnn_format_tag_undef;
+ const format_tag_t any = mkldnn_format_tag_any;
+ const format_tag_t a = mkldnn_a;
+ const format_tag_t ab = mkldnn_ab;
+ const format_tag_t abc = mkldnn_abc;
+ const format_tag_t abcd = mkldnn_abcd;
+ const format_tag_t abcde = mkldnn_abcde;
+ const format_tag_t abcdef = mkldnn_abcdef;
+ const format_tag_t abdec = mkldnn_abdec;
+ const format_tag_t acb = mkldnn_acb;
+ const format_tag_t acbde = mkldnn_acbde;
+ const format_tag_t acdb = mkldnn_acdb;
+ const format_tag_t acdeb = mkldnn_acdeb;
+ const format_tag_t ba = mkldnn_ba;
+ const format_tag_t bac = mkldnn_bac;
+ const format_tag_t bacd = mkldnn_bacd;
+ const format_tag_t bcda = mkldnn_bcda;
+ const format_tag_t cba = mkldnn_cba;
+ const format_tag_t cdba = mkldnn_cdba;
+ const format_tag_t cdeba = mkldnn_cdeba;
+ const format_tag_t decab = mkldnn_decab;
+ const format_tag_t Abc16a = mkldnn_Abc16a;
+ const format_tag_t ABc16a16b = mkldnn_ABc16a16b;
+ const format_tag_t aBc16b = mkldnn_aBc16b;
+ const format_tag_t ABc16b16a = mkldnn_ABc16b16a;
+ const format_tag_t Abc4a = mkldnn_Abc4a;
+ const format_tag_t aBc4b = mkldnn_aBc4b;
+ const format_tag_t ABc4b16a4b = mkldnn_ABc4b16a4b;
+ const format_tag_t ABc4b4a = mkldnn_ABc4b4a;
+ const format_tag_t ABc8a16b2a = mkldnn_ABc8a16b2a;
+ const format_tag_t ABc8a8b = mkldnn_ABc8a8b;
+ const format_tag_t aBc8b = mkldnn_aBc8b;
+ const format_tag_t ABc8b16a2b = mkldnn_ABc8b16a2b;
+ const format_tag_t ABc8b8a = mkldnn_ABc8b8a;
+ const format_tag_t Abcd16a = mkldnn_Abcd16a;
+ const format_tag_t ABcd16a16b = mkldnn_ABcd16a16b;
+ const format_tag_t aBcd16b = mkldnn_aBcd16b;
+ const format_tag_t ABcd16b16a = mkldnn_ABcd16b16a;
+ const format_tag_t aBCd16b16c = mkldnn_aBCd16b16c;
+ const format_tag_t aBCd16c16b = mkldnn_aBCd16c16b;
+ const format_tag_t Abcd4a = mkldnn_Abcd4a;
+ const format_tag_t aBcd4b = mkldnn_aBcd4b;
+ const format_tag_t ABcd4b16a4b = mkldnn_ABcd4b16a4b;
+ const format_tag_t ABcd4b4a = mkldnn_ABcd4b4a;
+ const format_tag_t aBCd4c16b4c = mkldnn_aBCd4c16b4c;
+ const format_tag_t aBCd4c4b = mkldnn_aBCd4c4b;
+ const format_tag_t ABcd8a16b2a = mkldnn_ABcd8a16b2a;
+ const format_tag_t ABcd8a8b = mkldnn_ABcd8a8b;
+ const format_tag_t aBcd8b = mkldnn_aBcd8b;
+ const format_tag_t ABcd8b16a2b = mkldnn_ABcd8b16a2b;
+ const format_tag_t aBCd8b16c2b = mkldnn_aBCd8b16c2b;
+ const format_tag_t ABcd8b8a = mkldnn_ABcd8b8a;
+ const format_tag_t aBCd8b8c = mkldnn_aBCd8b8c;
+ const format_tag_t aBCd8c16b2c = mkldnn_aBCd8c16b2c;
+ const format_tag_t aBCd8c8b = mkldnn_aBCd8c8b;
+ const format_tag_t Abcde16a = mkldnn_Abcde16a;
+ const format_tag_t ABcde16a16b = mkldnn_ABcde16a16b;
+ const format_tag_t aBcde16b = mkldnn_aBcde16b;
+ const format_tag_t ABcde16b16a = mkldnn_ABcde16b16a;
+ const format_tag_t aBCde16b16c = mkldnn_aBCde16b16c;
+ const format_tag_t aBCde16c16b = mkldnn_aBCde16c16b;
+ const format_tag_t aBCde2c8b4c = mkldnn_aBCde2c8b4c;
+ const format_tag_t Abcde4a = mkldnn_Abcde4a;
+ const format_tag_t aBcde4b = mkldnn_aBcde4b;
+ const format_tag_t ABcde4b4a = mkldnn_ABcde4b4a;
+ const format_tag_t aBCde4b4c = mkldnn_aBCde4b4c;
+ const format_tag_t aBCde4c16b4c = mkldnn_aBCde4c16b4c;
+ const format_tag_t aBCde4c4b = mkldnn_aBCde4c4b;
+ const format_tag_t Abcde8a = mkldnn_Abcde8a;
+ const format_tag_t ABcde8a8b = mkldnn_ABcde8a8b;
+ const format_tag_t aBcde8b = mkldnn_aBcde8b;
+ const format_tag_t ABcde8b16a2b = mkldnn_ABcde8b16a2b;
+ const format_tag_t aBCde8b16c2b = mkldnn_aBCde8b16c2b;
+ const format_tag_t ABcde8b8a = mkldnn_ABcde8b8a;
+ const format_tag_t aBCde8b8c = mkldnn_aBCde8b8c;
+ const format_tag_t aBCde8c16b2c = mkldnn_aBCde8c16b2c;
+ const format_tag_t aBCde8c8b = mkldnn_aBCde8c8b;
+ const format_tag_t aBcdef16b = mkldnn_aBcdef16b;
+ const format_tag_t aBCdef16b16c = mkldnn_aBCdef16b16c;
+ const format_tag_t aBCdef16c16b = mkldnn_aBCdef16c16b;
+ const format_tag_t aBcdef4b = mkldnn_aBcdef4b;
+ const format_tag_t aBCdef4c4b = mkldnn_aBCdef4c4b;
+ const format_tag_t aBCdef8b8c = mkldnn_aBCdef8b8c;
+ const format_tag_t aBCdef8c16b2c = mkldnn_aBCdef8c16b2c;
+ const format_tag_t aBCdef8c8b = mkldnn_aBCdef8c8b;
+ const format_tag_t aBdc16b = mkldnn_aBdc16b;
+ const format_tag_t aBdc4b = mkldnn_aBdc4b;
+ const format_tag_t aBdc8b = mkldnn_aBdc8b;
+ const format_tag_t aBdec16b = mkldnn_aBdec16b;
+ const format_tag_t aBdec4b = mkldnn_aBdec4b;
+ const format_tag_t aBdec8b = mkldnn_aBdec8b;
+ const format_tag_t aBdefc16b = mkldnn_aBdefc16b;
+ const format_tag_t aBdefc4b = mkldnn_aBdefc4b;
+ const format_tag_t aBdefc8b = mkldnn_aBdefc8b;
+ const format_tag_t Acb16a = mkldnn_Acb16a;
+ const format_tag_t Acb4a = mkldnn_Acb4a;
+ const format_tag_t Acb8a = mkldnn_Acb8a;
+ const format_tag_t aCBd16b16c = mkldnn_aCBd16b16c;
+ const format_tag_t aCBde16b16c = mkldnn_aCBde16b16c;
+ const format_tag_t Acdb16a = mkldnn_Acdb16a;
+ const format_tag_t Acdb4a = mkldnn_Acdb4a;
+ const format_tag_t Acdb8a = mkldnn_Acdb8a;
+ const format_tag_t Acdeb16a = mkldnn_Acdeb16a;
+ const format_tag_t Acdeb4a = mkldnn_Acdeb4a;
+ const format_tag_t Acdeb8a = mkldnn_Acdeb8a;
+ const format_tag_t BAc16a16b = mkldnn_BAc16a16b;
+ const format_tag_t BAcd16a16b = mkldnn_BAcd16a16b;
+ const format_tag_t last = mkldnn_format_tag_last;
+
+ const format_tag_t x = mkldnn_x;
+ const format_tag_t nc = mkldnn_nc;
+ const format_tag_t cn = mkldnn_cn;
+ const format_tag_t ncw = mkldnn_ncw;
+ const format_tag_t nwc = mkldnn_nwc;
+ const format_tag_t nchw = mkldnn_nchw;
+ const format_tag_t nhwc = mkldnn_nhwc;
+ const format_tag_t chwn = mkldnn_chwn;
+ const format_tag_t ncdhw = mkldnn_ncdhw;
+ const format_tag_t ndhwc = mkldnn_ndhwc;
+ const format_tag_t oi = mkldnn_oi;
+ const format_tag_t io = mkldnn_io;
+ const format_tag_t oiw = mkldnn_oiw;
+ const format_tag_t wio = mkldnn_wio;
+ const format_tag_t oihw = mkldnn_oihw;
+ const format_tag_t hwio = mkldnn_hwio;
+ const format_tag_t ihwo = mkldnn_ihwo;
+ const format_tag_t iohw = mkldnn_iohw;
+ const format_tag_t oidhw = mkldnn_oidhw;
+ const format_tag_t dhwio = mkldnn_dhwio;
+ const format_tag_t goiw = mkldnn_goiw;
+ const format_tag_t goihw = mkldnn_goihw;
+ const format_tag_t hwigo = mkldnn_hwigo;
+ const format_tag_t giohw = mkldnn_giohw;
+ const format_tag_t goidhw = mkldnn_goidhw;
+ const format_tag_t tnc = mkldnn_tnc;
+ const format_tag_t ntc = mkldnn_ntc;
+ const format_tag_t ldsnc = mkldnn_ldsnc;
+ const format_tag_t ldigo = mkldnn_ldigo;
+ const format_tag_t ldgoi = mkldnn_ldgoi;
+ const format_tag_t ldgo = mkldnn_ldgo;
+ const format_tag_t nCdhw16c = mkldnn_nCdhw16c;
+ const format_tag_t nCdhw4c = mkldnn_nCdhw4c;
+ const format_tag_t nCdhw8c = mkldnn_nCdhw8c;
+ const format_tag_t nChw16c = mkldnn_nChw16c;
+ const format_tag_t nChw4c = mkldnn_nChw4c;
+ const format_tag_t nChw8c = mkldnn_nChw8c;
+ const format_tag_t nCw16c = mkldnn_nCw16c;
+ const format_tag_t nCw4c = mkldnn_nCw4c;
+ const format_tag_t nCw8c = mkldnn_nCw8c;
+ const format_tag_t IOw16o16i = mkldnn_IOw16o16i;
+ const format_tag_t OIw16i16o = mkldnn_OIw16i16o;
+ const format_tag_t OIw16o16i = mkldnn_OIw16o16i;
+ const format_tag_t Oiw16o = mkldnn_Oiw16o;
+ const format_tag_t OIw4i16o4i = mkldnn_OIw4i16o4i;
+ const format_tag_t OIw4i4o = mkldnn_OIw4i4o;
+ const format_tag_t Oiw4o = mkldnn_Oiw4o;
+ const format_tag_t OIw8i16o2i = mkldnn_OIw8i16o2i;
+ const format_tag_t OIw8i8o = mkldnn_OIw8i8o;
+ const format_tag_t OIw8o16i2o = mkldnn_OIw8o16i2o;
+ const format_tag_t OIw8o8i = mkldnn_OIw8o8i;
+ const format_tag_t Owi16o = mkldnn_Owi16o;
+ const format_tag_t Owi4o = mkldnn_Owi4o;
+ const format_tag_t Owi8o = mkldnn_Owi8o;
+ const format_tag_t IOhw16o16i = mkldnn_IOhw16o16i;
+ const format_tag_t Ohwi16o = mkldnn_Ohwi16o;
+ const format_tag_t Ohwi4o = mkldnn_Ohwi4o;
+ const format_tag_t Ohwi8o = mkldnn_Ohwi8o;
+ const format_tag_t OIhw16i16o = mkldnn_OIhw16i16o;
+ const format_tag_t OIhw16o16i = mkldnn_OIhw16o16i;
+ const format_tag_t Oihw16o = mkldnn_Oihw16o;
+ const format_tag_t OIhw4i16o4i = mkldnn_OIhw4i16o4i;
+ const format_tag_t OIhw4i4o = mkldnn_OIhw4i4o;
+ const format_tag_t Oihw4o = mkldnn_Oihw4o;
+ const format_tag_t OIhw8i16o2i = mkldnn_OIhw8i16o2i;
+ const format_tag_t OIhw8i8o = mkldnn_OIhw8i8o;
+ const format_tag_t OIhw8o16i2o = mkldnn_OIhw8o16i2o;
+ const format_tag_t OIhw8o8i = mkldnn_OIhw8o8i;
+ const format_tag_t Odhwi16o = mkldnn_Odhwi16o;
+ const format_tag_t Odhwi4o = mkldnn_Odhwi4o;
+ const format_tag_t Odhwi8o = mkldnn_Odhwi8o;
+ const format_tag_t OIdhw16i16o = mkldnn_OIdhw16i16o;
+ const format_tag_t OIdhw16o16i = mkldnn_OIdhw16o16i;
+ const format_tag_t Oidhw16o = mkldnn_Oidhw16o;
+ const format_tag_t OIdhw4i4o = mkldnn_OIdhw4i4o;
+ const format_tag_t Oidhw4o = mkldnn_Oidhw4o;
+ const format_tag_t OIdhw8i16o2i = mkldnn_OIdhw8i16o2i;
+ const format_tag_t OIdhw8i8o = mkldnn_OIdhw8i8o;
+ const format_tag_t OIdhw8o8i = mkldnn_OIdhw8o8i;
+ const format_tag_t gIOw16o16i = mkldnn_gIOw16o16i;
+ const format_tag_t Goiw16g = mkldnn_Goiw16g;
+ const format_tag_t gOIw16i16o = mkldnn_gOIw16i16o;
+ const format_tag_t gOIw16o16i = mkldnn_gOIw16o16i;
+ const format_tag_t gOiw16o = mkldnn_gOiw16o;
+ const format_tag_t gOIw4i16o4i = mkldnn_gOIw4i16o4i;
+ const format_tag_t gOIw4i4o = mkldnn_gOIw4i4o;
+ const format_tag_t gOiw4o = mkldnn_gOiw4o;
+ const format_tag_t gOIw8i16o2i = mkldnn_gOIw8i16o2i;
+ const format_tag_t gOIw8i8o = mkldnn_gOIw8i8o;
+ const format_tag_t gOIw8o16i2o = mkldnn_gOIw8o16i2o;
+ const format_tag_t gOIw8o8i = mkldnn_gOIw8o8i;
+ const format_tag_t gOwi16o = mkldnn_gOwi16o;
+ const format_tag_t gOwi4o = mkldnn_gOwi4o;
+ const format_tag_t gOwi8o = mkldnn_gOwi8o;
+ const format_tag_t gIOhw16o16i = mkldnn_gIOhw16o16i;
+ const format_tag_t gOhwi16o = mkldnn_gOhwi16o;
+ const format_tag_t gOhwi4o = mkldnn_gOhwi4o;
+ const format_tag_t gOhwi8o = mkldnn_gOhwi8o;
+ const format_tag_t Goihw16g = mkldnn_Goihw16g;
+ const format_tag_t gOIhw16i16o = mkldnn_gOIhw16i16o;
+ const format_tag_t gOIhw16o16i = mkldnn_gOIhw16o16i;
+ const format_tag_t gOihw16o = mkldnn_gOihw16o;
+ const format_tag_t gOIhw2i8o4i = mkldnn_gOIhw2i8o4i;
+ const format_tag_t gOIhw4i16o4i = mkldnn_gOIhw4i16o4i;
+ const format_tag_t gOIhw4i4o = mkldnn_gOIhw4i4o;
+ const format_tag_t gOIhw4o4i = mkldnn_gOIhw4o4i;
+ const format_tag_t gOihw4o = mkldnn_gOihw4o;
+ const format_tag_t Goihw8g = mkldnn_Goihw8g;
+ const format_tag_t gOIhw8i16o2i = mkldnn_gOIhw8i16o2i;
+ const format_tag_t gOIhw8i8o = mkldnn_gOIhw8i8o;
+ const format_tag_t gOIhw8o16i2o = mkldnn_gOIhw8o16i2o;
+ const format_tag_t gOIhw8o8i = mkldnn_gOIhw8o8i;
+ const format_tag_t gOdhwi16o = mkldnn_gOdhwi16o;
+ const format_tag_t gOdhwi4o = mkldnn_gOdhwi4o;
+ const format_tag_t gOdhwi8o = mkldnn_gOdhwi8o;
+ const format_tag_t gOIdhw16i16o = mkldnn_gOIdhw16i16o;
+ const format_tag_t gOIdhw16o16i = mkldnn_gOIdhw16o16i;
+ const format_tag_t gOidhw16o = mkldnn_gOidhw16o;
+ const format_tag_t gOIdhw4i4o = mkldnn_gOIdhw4i4o;
+ const format_tag_t gOidhw4o = mkldnn_gOidhw4o;
+ const format_tag_t gOIdhw8i16o2i = mkldnn_gOIdhw8i16o2i;
+ const format_tag_t gOIdhw8i8o = mkldnn_gOIdhw8i8o;
+ const format_tag_t gOIdhw8o8i = mkldnn_gOIdhw8o8i;
+}
+
+using memory_extra_flags_t = mkldnn_memory_extra_flags_t;
+namespace memory_extra_flags {
+ const memory_extra_flags_t none = mkldnn_memory_extra_flag_none;
+ const memory_extra_flags_t compensation_conv_s8s8 = mkldnn_memory_extra_flag_compensation_conv_s8s8;
+ const memory_extra_flags_t scale_adjust = mkldnn_memory_extra_flag_scale_adjust;
+}
+
+using padding_kind_t = mkldnn_padding_kind_t;
+namespace padding_kind {
+ const padding_kind_t padding_zero = mkldnn_padding_zero;
+}
+
+using engine_kind_t = mkldnn_engine_kind_t;
+namespace engine_kind {
+ const engine_kind_t any_engine = mkldnn_any_engine;
+ const engine_kind_t cpu = mkldnn_cpu;
+}
+
+using primitive_kind_t = mkldnn_primitive_kind_t;
+namespace primitive_kind {
+ const primitive_kind_t undefined = mkldnn_undefined_primitive;
+ const primitive_kind_t reorder = mkldnn_reorder;
+ const primitive_kind_t concat = mkldnn_concat;
+ const primitive_kind_t sum = mkldnn_sum;
+ const primitive_kind_t convolution = mkldnn_convolution;
+ const primitive_kind_t deconvolution = mkldnn_deconvolution;
+ const primitive_kind_t shuffle = mkldnn_shuffle;
+ const primitive_kind_t eltwise = mkldnn_eltwise;
+ const primitive_kind_t softmax = mkldnn_softmax;
+ const primitive_kind_t pooling = mkldnn_pooling;
+ const primitive_kind_t lrn = mkldnn_lrn;
+ const primitive_kind_t batch_normalization = mkldnn_batch_normalization;
+ const primitive_kind_t inner_product = mkldnn_inner_product;
+ const primitive_kind_t rnn = mkldnn_rnn;
+}
+
+using query_t = mkldnn_query_t;
+namespace query {
+ const query_t undef = mkldnn_query_undef;
+
+ const query_t engine = mkldnn_query_engine;
+ const query_t primitive_kind = mkldnn_query_primitive_kind;
+
+ const query_t num_of_inputs_s32 = mkldnn_query_num_of_inputs_s32;
+ const query_t num_of_outputs_s32 = mkldnn_query_num_of_outputs_s32;
+
+ const query_t time_estimate_f64 = mkldnn_query_time_estimate_f64;
+ const query_t memory_consumption_s64 = mkldnn_query_memory_consumption_s64;
+
+ const query_t scratchpad_engine = mkldnn_query_scratchpad_engine;
+
+ const query_t impl_info_str = mkldnn_query_impl_info_str;
+
+ const query_t some_d = mkldnn_query_some_d;
+ const query_t op_d = mkldnn_query_op_d;
+ const query_t convolution_d = mkldnn_query_convolution_d;
+ const query_t deconvolution_d = mkldnn_query_deconvolution_d;
+ const query_t shuffle_d = mkldnn_query_shuffle_d;
+ const query_t eltwise_d = mkldnn_query_eltwise_d;
+ const query_t softmax_d = mkldnn_query_softmax_d;
+ const query_t pooling_d = mkldnn_query_pooling_d;
+ const query_t lrn_d = mkldnn_query_lrn_d;
+ const query_t batch_normalization_d = mkldnn_query_batch_normalization_d;
+ const query_t inner_product_d = mkldnn_query_inner_product_d;
+ const query_t rnn_d = mkldnn_query_rnn_d;
+
+ const query_t some_md = mkldnn_query_some_md;
+ const query_t src_md = mkldnn_query_src_md;
+ const query_t diff_src_md = mkldnn_query_diff_src_md;
+ const query_t weights_md = mkldnn_query_weights_md;
+ const query_t diff_weights_md = mkldnn_query_diff_weights_md;
+ const query_t dst_md = mkldnn_query_dst_md;
+ const query_t diff_dst_md = mkldnn_query_diff_dst_md;
+
+ const query_t workspace_md = mkldnn_query_workspace_md;
+ const query_t scratchpad_md = mkldnn_query_scratchpad_md;
+}
+
+using blocking_desc_t = mkldnn_blocking_desc_t;
+using rnn_packed_desc_t = mkldnn_rnn_packed_desc_t;
+using wino_desc_t = mkldnn_wino_desc_t;
+using memory_extra_desc_t = mkldnn_memory_extra_desc_t;
+using memory_desc_t = mkldnn_memory_desc_t;
+using convolution_desc_t = mkldnn_convolution_desc_t;
+using deconvolution_desc_t = mkldnn_deconvolution_desc_t;
+using shuffle_desc_t = mkldnn_shuffle_desc_t;
+using pooling_desc_t = mkldnn_pooling_desc_t;
+using eltwise_desc_t = mkldnn_eltwise_desc_t;
+using softmax_desc_t = mkldnn_softmax_desc_t;
+using lrn_desc_t = mkldnn_lrn_desc_t;
+using batch_normalization_desc_t = mkldnn_batch_normalization_desc_t;
+using inner_product_desc_t = mkldnn_inner_product_desc_t;
+
+using rnn_direction_t = mkldnn_rnn_direction_t;
+using rnn_cell_desc_t = mkldnn_rnn_cell_desc_t;
+using rnn_desc_t = mkldnn_rnn_desc_t;
+
+/* C op_desc_t, which eventually are just (void*) */
+using c_op_desc_t = mkldnn_op_desc_t;
+using const_c_op_desc_t = const_mkldnn_op_desc_t;
+
+struct op_desc_t {
+ union {
+ primitive_kind_t kind;
+ convolution_desc_t convolution;
+ deconvolution_desc_t deconvolution;
+ shuffle_desc_t shuffle;
+ pooling_desc_t pooling;
+ eltwise_desc_t eltwise;
+ softmax_desc_t softmax;
+ lrn_desc_t lrn;
+ batch_normalization_desc_t batch_normalization;
+ inner_product_desc_t inner_product;
+ rnn_desc_t rnn;
+ };
+
+ op_desc_t(const primitive_kind_t &_): kind(_) {}
+
+# define DECL_CTOR_AND_CONVERTERS(c_type, name) \
+ op_desc_t(const c_type &_): name(_) {} \
+ static op_desc_t *convert_from_c(c_type *_) \
+ { return reinterpret_cast<op_desc_t*>(_); } \
+ static const op_desc_t *convert_from_c(const c_type *_) \
+ { return reinterpret_cast<const op_desc_t*>(_); }
+
+ DECL_CTOR_AND_CONVERTERS(convolution_desc_t, convolution);
+ DECL_CTOR_AND_CONVERTERS(shuffle_desc_t, shuffle);
+ DECL_CTOR_AND_CONVERTERS(pooling_desc_t, pooling);
+ DECL_CTOR_AND_CONVERTERS(eltwise_desc_t, eltwise);
+ DECL_CTOR_AND_CONVERTERS(softmax_desc_t, softmax);
+ DECL_CTOR_AND_CONVERTERS(lrn_desc_t, lrn);
+ DECL_CTOR_AND_CONVERTERS(batch_normalization_desc_t, batch_normalization);
+ DECL_CTOR_AND_CONVERTERS(inner_product_desc_t, inner_product);
+ DECL_CTOR_AND_CONVERTERS(rnn_desc_t, rnn);
+
+# undef DECL_CTOR_AND_CONVERTERS
+};
+
+using engine_t = mkldnn_engine;
+using primitive_desc_iterator_t = mkldnn_primitive_desc_iterator;
+using primitive_desc_t = mkldnn_primitive_desc;
+using primitive_attr_t = mkldnn_primitive_attr;
+using post_ops_t = mkldnn_post_ops;
+using memory_t = mkldnn_memory;
+using primitive_t = mkldnn_primitive;
+
+using primitive_arg_index_t = int;
+
+using stream_flags_t = mkldnn_stream_flags_t;
+namespace stream_flags {
+ const stream_flags_t default_flags = mkldnn_stream_default_flags;
+}
+using stream_t = mkldnn_stream;
+
+/* forward declaration of the internal primitive_desc types */
+struct batch_normalization_bwd_pd_t;
+struct batch_normalization_fwd_pd_t;
+struct batch_normalization_pd_t;
+struct concat_pd_t;
+struct convolution_bwd_data_pd_t;
+struct convolution_bwd_weights_pd_t;
+struct convolution_fwd_pd_t;
+struct convolution_pd_t;
+struct deconvolution_bwd_data_pd_t;
+struct deconvolution_bwd_weights_pd_t;
+struct deconvolution_fwd_pd_t;
+struct deconvolution_pd_t;
+struct eltwise_bwd_pd_t;
+struct eltwise_fwd_pd_t;
+struct eltwise_pd_t;
+struct inner_product_bwd_data_pd_t;
+struct inner_product_bwd_weights_pd_t;
+struct inner_product_fwd_pd_t;
+struct inner_product_pd_t;
+struct lrn_bwd_pd_t;
+struct lrn_fwd_pd_t;
+struct lrn_pd_t;
+struct pooling_bwd_pd_t;
+struct pooling_fwd_pd_t;
+struct pooling_pd_t;
+struct reorder_pd_t;
+struct rnn_bwd_pd_t;
+struct rnn_fwd_pd_t;
+struct rnn_pd_t;
+struct shuffle_pd_t;
+struct softmax_bwd_pd_t;
+struct softmax_fwd_pd_t;
+struct softmax_pd_t;
+struct sum_pd_t;
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/concat.cpp b/thirdparty/oidn/mkl-dnn/src/common/concat.cpp
new file mode 100644
index 0000000000..ed4c35c6e9
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/concat.cpp
@@ -0,0 +1,86 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "engine.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "concat_pd.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+
+status_t mkldnn_concat_primitive_desc_create(primitive_desc_t **concat_pd,
+ const memory_desc_t *dst_md, int n, int concat_dim,
+ const memory_desc_t *src_mds,
+ const primitive_attr_t *attr,
+ engine_t *engine) {
+ bool args_ok = !any_null(concat_pd, src_mds) && n > 0;
+ if (!args_ok) return invalid_arguments;
+
+ const primitive_attr_t dummy_attr;
+ if (attr == NULL)
+ attr = &dummy_attr;
+
+ const int ndims = src_mds[0].ndims;
+ const dims_t &dims = src_mds[0].dims;
+ const data_type_t dt = src_mds[0].data_type;
+
+ int concat_dim_sz = dims[concat_dim];
+ for (int i = 1; i < n; ++i) {
+ if (src_mds[i].ndims != ndims) return invalid_arguments;
+ for (int d = 0; d < ndims; ++d) {
+ if (d == concat_dim) continue;
+ if (src_mds[i].dims[d] != dims[d])
+ return invalid_arguments;
+ }
+ if (src_mds[i].data_type != dt) return invalid_arguments;
+ concat_dim_sz += src_mds[i].dims[concat_dim];
+ }
+
+ memory_desc_t dummy_dst_md;
+ if (dst_md) {
+ if (dst_md->ndims != ndims) return invalid_arguments;
+ for (int d = 0; d < ndims; ++d) {
+ if (dst_md->dims[d] !=
+ (d == concat_dim ? concat_dim_sz : dims[d]))
+ return invalid_arguments;
+ }
+ } else {
+ dummy_dst_md = src_mds[0];
+ dummy_dst_md.dims[concat_dim] = concat_dim_sz;
+ dummy_dst_md.format_kind = format_kind::any;
+ dst_md = &dummy_dst_md;
+ }
+
+ auto c_pd = reinterpret_cast<concat_pd_t **>(concat_pd);
+
+ for (auto c = engine->get_concat_implementation_list(); *c; ++c) {
+ if ((*c)(c_pd, engine, attr, dst_md, n, concat_dim, src_mds)
+ == success) {
+ (*c_pd)->init_info();
+ (*c_pd)->init_scratchpad_md();
+ return success;
+ }
+ }
+ return unimplemented;
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/concat_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/concat_pd.hpp
new file mode 100644
index 0000000000..29311927e2
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/concat_pd.hpp
@@ -0,0 +1,211 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CONCAT_PD_HPP
+#define CONCAT_PD_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "primitive_desc.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct concat_pd_t: public primitive_desc_t {
+ concat_pd_t(engine_t *engine, const primitive_attr_t *attr,
+ const memory_desc_t *dst_md, int n, int concat_dim,
+ const memory_desc_t *src_mds)
+ : primitive_desc_t(engine, attr, primitive_kind::concat)
+ , n_(n), concat_dim_(concat_dim), dst_md_(*dst_md)
+ {
+ src_mds_.reserve(n_);
+ for (int i = 0; i < n_; ++i) src_mds_.push_back(src_mds[i]);
+ }
+
+ concat_pd_t(const concat_pd_t &rhs) = default;
+
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (arg >= MKLDNN_ARG_MULTIPLE_SRC
+ && arg < MKLDNN_ARG_MULTIPLE_SRC + n_inputs())
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index < n_inputs() ? &src_mds_[index] : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &dst_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return n_; }
+ virtual int n_outputs() const override { return 1; }
+
+ int concat_dim() const { return concat_dim_; }
+
+ const memory_desc_t *src_image_md(int index = 0) const
+ { return index < n_inputs() ? &src_image_mds_[index] : nullptr; }
+
+protected:
+ int n_, concat_dim_;
+ memory_desc_t dst_md_;
+ nstl::vector<memory_desc_t> src_mds_;
+
+ /* contains images of srcs in the dst memory (if possible)
+ * Lives here to simplify some implementations. An implementation might
+ * use this auxiliary array iff init() returned success */
+ nstl::vector<memory_desc_t> src_image_mds_;
+
+protected:
+ /* inits src_image_mds_ and dst_md_ in simple cases. The call may fail */
+ status_t init() {
+ bool ok = true
+ && set_default_params() == status::success
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ for (int i = 0; i < n_; ++i) {
+ const memory_desc_wrapper i_d(&src_mds_[i]);
+ if (!i_d.is_blocking_desc() || i_d.is_additional_buffer())
+ return status::unimplemented;
+ }
+
+ const int ndims = dst_md_.ndims;
+ int current_concat_dim_offset = 0;
+ for (int i = 0; i < n_; ++i) {
+ const int dim = src_mds_[i].dims[concat_dim_];
+ dims_t dims, offsets = {};
+ utils::array_copy(dims, dst_md_.dims, ndims);
+ dims[concat_dim_] = dim;
+ offsets[concat_dim_] = current_concat_dim_offset;
+
+ memory_desc_t src_img_d;
+ status_t status = mkldnn_memory_desc_init_submemory(&src_img_d,
+ &dst_md_, dims, offsets);
+ if (status != status::success) return status;
+ src_image_mds_.push_back(src_img_d);
+ current_concat_dim_offset += dim;
+ }
+
+ return status::success;
+ }
+
+ status_t set_default_params() {
+ if (dst_md_.format_kind != format_kind::any)
+ return status::success;
+
+ const int ndims = dst_md_.ndims;
+
+ /* The stupidest ever heuristics (but not the same as we had before):
+ * - Pick the first non-plain format;
+ * - If all formats are plain or it is not possible to create a
+ * blocked format for the output, pick the format of the plain input
+ * - If this fails as well, use plain layout (abcd...)
+ */
+ status_t status = status::unimplemented;
+ for (int i = 0; i < n_; ++i) {
+ const memory_desc_wrapper src_d(src_mds_[i]);
+ if (src_d.is_blocking_desc() && !src_d.is_plain()) {
+ status = memory_desc_init_by_blocking_desc(dst_md_,
+ src_d.blocking_desc());
+ if (status == status::success) break;
+ }
+ }
+
+ if (status == status::success) {
+ /* check if we can create a sub-memory for the dst */
+ bool desired_format_ok = true;
+ int current_concat_dim_offset = 0;
+ for (int i = 0; i < n_; ++i) {
+ const int dim = src_mds_[i].dims[concat_dim_];
+ dims_t dims, offsets = {};
+ utils::array_copy(dims, dst_md_.dims, ndims);
+ dims[concat_dim_] = dim;
+ offsets[concat_dim_] = current_concat_dim_offset;
+
+ memory_desc_t src_img_d;
+ status_t status = mkldnn_memory_desc_init_submemory(&src_img_d,
+ &dst_md_, dims, offsets);
+ if (status != status::success) {
+ desired_format_ok = false;
+ break;
+ }
+ current_concat_dim_offset += dim;
+ }
+
+ if (!desired_format_ok)
+ status = status::unimplemented;
+ }
+
+ /* if no success so far, try using the format of the first plain input */
+ if (status != status::success) {
+ for (int i = 0; i < n_; ++i) {
+ const memory_desc_wrapper src_d(src_mds_[i]);
+ if (src_d.is_blocking_desc() && src_d.is_plain()) {
+ status = memory_desc_init_by_blocking_desc(dst_md_,
+ memory_desc_wrapper(src_mds_[0]).blocking_desc());
+ if (status == status::success) return status;
+ }
+ }
+ }
+
+ /* the last line of defense: use plain abcd... format */
+ if (status != status::success)
+ status = memory_desc_init_by_strides(dst_md_, nullptr);
+
+ return status;
+ }
+};
+
+#define DECLARE_CONCAT_PD_t(impl_name, ...) \
+ static status_t create(concat_pd_t **concat_pd, \
+ engine_t *engine, const primitive_attr_t *attr, \
+ const memory_desc_t *dst_md, int n, int concat_dim, \
+ const memory_desc_t *src_mds) { \
+ using namespace status; \
+ auto _pd = new pd_t(engine, attr, dst_md, n, concat_dim, src_mds); \
+ if (_pd == nullptr) return out_of_memory; \
+ if (_pd->init() != success) { delete _pd; return unimplemented; } \
+ return safe_ptr_assign<concat_pd_t>(*concat_pd, _pd); \
+ } \
+ virtual status_t create_primitive(primitive_t **p) const override { \
+ double ms = get_msec(); \
+ auto ret = safe_ptr_assign<primitive_t>(*p, new (__VA_ARGS__)(this)); \
+ ms = get_msec() - ms; \
+ if (mkldnn_verbose()->level >= 2) { \
+ printf("mkldnn_verbose,create,%s,%g\n", this->info(), ms); \
+ fflush(0); \
+ } \
+ return ret; \
+ } \
+ virtual pd_t *clone() const override { return new pd_t(*this); } \
+ virtual const char *name() const override { return impl_name; } \
+
+#define DECLARE_CONCAT_PD_T(impl_name, ...) \
+ DECLARE_CONCAT_PD_t(impl_name, __VA_ARGS__)
+
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/convolution.cpp b/thirdparty/oidn/mkl-dnn/src/common/convolution.cpp
new file mode 100644
index 0000000000..0c5c02bcd1
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/convolution.cpp
@@ -0,0 +1,200 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::alg_kind;
+using namespace mkldnn::impl::types;
+
+namespace mkldnn {
+namespace impl {
+status_t conv_desc_init(convolution_desc_t *conv_desc,
+ prop_kind_t prop_kind, alg_kind_t alg_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *weights_desc,
+ const memory_desc_t *bias_desc, const memory_desc_t *dst_desc,
+ const dims_t strides, const dims_t dilates,
+ const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ bool args_ok = true
+ && !any_null(conv_desc, src_desc, weights_desc, dst_desc, strides,
+ padding_l)
+ && one_of(alg_kind, convolution_auto, convolution_direct, convolution_winograd)
+ && one_of(padding_kind, padding_kind::padding_zero);
+ if (!args_ok) return invalid_arguments;
+
+ if (padding_r == nullptr) padding_r = padding_l;
+
+ auto cd = convolution_desc_t();
+ cd.primitive_kind = primitive_kind::convolution;
+ cd.prop_kind = prop_kind;
+ cd.alg_kind = alg_kind;
+
+ cd.diff_src_desc = cd.src_desc = zero_md();
+ cd.diff_dst_desc = cd.dst_desc = zero_md();
+ cd.diff_weights_desc = cd.weights_desc = zero_md();
+ cd.diff_bias_desc = cd.bias_desc = zero_md();
+
+ const bool is_fwd = one_of(prop_kind, forward_training, forward_inference);
+ const bool with_bias =
+ bias_desc && bias_desc->format_kind != format_kind::undef;
+ const bool with_groups = weights_desc->ndims == src_desc->ndims + 1;
+
+ (prop_kind == backward_data ? cd.diff_src_desc : cd.src_desc) = *src_desc;
+ (is_fwd ? cd.dst_desc : cd.diff_dst_desc) = *dst_desc;
+ (prop_kind == backward_weights ? cd.diff_weights_desc : cd.weights_desc) =
+ *weights_desc;
+ if (with_bias)
+ (prop_kind == backward_weights ? cd.diff_bias_desc : cd.bias_desc) =
+ *bias_desc;
+
+ int sp_dims = src_desc->ndims - 2;
+ utils::array_copy(cd.strides, strides, sp_dims);
+ utils::array_copy(cd.padding[0], padding_l, sp_dims);
+ utils::array_copy(cd.padding[1], padding_r, sp_dims);
+ if (dilates)
+ utils::array_copy(cd.dilates, dilates, sp_dims);
+ else
+ utils::array_set(cd.dilates, 0, sp_dims);
+
+ cd.padding_kind = padding_kind;
+ cd.accum_data_type = types::default_accum_data_type(src_desc->data_type,
+ weights_desc->data_type, dst_desc->data_type, prop_kind);
+
+ const int g = with_groups ? weights_desc->dims[0] : 1;
+ const int bias_dim = prop_kind == backward_data
+ ? src_desc->dims[1]
+ : dst_desc->dims[1];
+
+ bool consistency = true
+ && memory_desc_wrapper(weights_desc).nelems()
+ && src_desc->ndims == dst_desc->ndims
+ && utils::one_of(src_desc->ndims, 3, 4, 5)
+ && utils::one_of(weights_desc->ndims, src_desc->ndims,
+ src_desc->ndims + 1)
+ && (with_bias ? bias_desc->ndims == 1 : true)
+ && (with_bias ? bias_desc->dims[0] == bias_dim : true)
+ && src_desc->dims[0] == dst_desc->dims[0]
+ && src_desc->dims[1] == g * weights_desc->dims[with_groups + 1]
+ && dst_desc->dims[1] == g * weights_desc->dims[with_groups + 0];
+ for (int i = 2; i < src_desc->ndims; ++i)
+ {
+ int src = src_desc->dims[i];
+ int ker = weights_desc->dims[with_groups + i];
+ int dil = cd.dilates[i - 2];
+ int pad_l = padding_l[i - 2];
+ int pad_r = padding_r[i - 2];
+ int str = strides[i - 2];
+ int dst = dst_desc->dims[i];
+ int ker_range = 1 + (ker - 1) * (dil + 1);
+
+ if (str < 1) return invalid_arguments;
+ consistency = consistency
+ && dil >= 0
+ && pad_l >= 0
+ && pad_r + str > 0
+ && (src - ker_range + pad_l + pad_r) / str + 1 == dst;
+ }
+ if (!consistency) return invalid_arguments;
+
+ *conv_desc = cd;
+ return success;
+}
+}
+}
+
+status_t mkldnn_convolution_forward_desc_init(convolution_desc_t *conv_desc,
+ prop_kind_t prop_kind, alg_kind_t alg_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *weights_desc,
+ const memory_desc_t *bias_desc, const memory_desc_t *dst_desc,
+ const dims_t strides, const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ if (!one_of(prop_kind, forward_training, forward_inference))
+ return invalid_arguments;
+ return mkldnn::impl::conv_desc_init(conv_desc, prop_kind, alg_kind, src_desc,
+ weights_desc, bias_desc, dst_desc, strides, nullptr,
+ padding_l, padding_r, padding_kind);
+}
+
+status_t mkldnn_dilated_convolution_forward_desc_init(
+ convolution_desc_t *conv_desc, prop_kind_t prop_kind,
+ alg_kind_t alg_kind, const memory_desc_t *src_desc,
+ const memory_desc_t *weights_desc, const memory_desc_t *bias_desc,
+ const memory_desc_t *dst_desc, const dims_t strides,
+ const dims_t dilates, const dims_t padding_l,
+ const dims_t padding_r, padding_kind_t padding_kind) {
+ if (!one_of(prop_kind, forward_training, forward_inference))
+ return invalid_arguments;
+ return mkldnn::impl::conv_desc_init(conv_desc, prop_kind, alg_kind, src_desc,
+ weights_desc, bias_desc, dst_desc, strides, dilates,
+ padding_l, padding_r, padding_kind);
+}
+
+status_t mkldnn_convolution_backward_data_desc_init(
+ convolution_desc_t *conv_desc, alg_kind_t alg_kind,
+ const memory_desc_t *diff_src_desc, const memory_desc_t *weights_desc,
+ const memory_desc_t *diff_dst_desc, const dims_t strides,
+ const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ return mkldnn::impl::conv_desc_init(conv_desc, backward_data, alg_kind, diff_src_desc,
+ weights_desc, nullptr, diff_dst_desc, strides, nullptr,
+ padding_l, padding_r, padding_kind);
+}
+
+status_t mkldnn_dilated_convolution_backward_data_desc_init(
+ convolution_desc_t *conv_desc, alg_kind_t alg_kind,
+ const memory_desc_t *diff_src_desc, const memory_desc_t *weights_desc,
+ const memory_desc_t *diff_dst_desc, const dims_t strides,
+ const dims_t dilates, const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ return mkldnn::impl::conv_desc_init(conv_desc, backward_data, alg_kind, diff_src_desc,
+ weights_desc, nullptr, diff_dst_desc, strides, dilates,
+ padding_l, padding_r, padding_kind);
+}
+
+status_t mkldnn_convolution_backward_weights_desc_init(
+ convolution_desc_t *conv_desc, alg_kind_t alg_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *diff_weights_desc,
+ const memory_desc_t *diff_bias_desc,
+ const memory_desc_t *diff_dst_desc, const dims_t strides,
+ const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ return mkldnn::impl::conv_desc_init(conv_desc, backward_weights, alg_kind, src_desc,
+ diff_weights_desc, diff_bias_desc, diff_dst_desc, strides,
+ nullptr, padding_l, padding_r, padding_kind);
+}
+
+status_t mkldnn_dilated_convolution_backward_weights_desc_init(
+ convolution_desc_t *conv_desc, alg_kind_t alg_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *diff_weights_desc,
+ const memory_desc_t *diff_bias_desc,
+ const memory_desc_t *diff_dst_desc, const dims_t strides,
+ const dims_t dilates, const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ return mkldnn::impl::conv_desc_init(conv_desc, backward_weights, alg_kind, src_desc,
+ diff_weights_desc, diff_bias_desc, diff_dst_desc, strides,
+ dilates, padding_l, padding_r, padding_kind);
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.cpp b/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.cpp
new file mode 100644
index 0000000000..9604e0acf5
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.cpp
@@ -0,0 +1,56 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "utils.hpp"
+
+#include "convolution_pd.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+using namespace prop_kind;
+
+memory_desc_t *conv_prop_invariant_src_d(convolution_desc_t *desc) {
+ return desc->prop_kind == backward_data
+ ? &desc->diff_src_desc : &desc->src_desc;
+}
+
+memory_desc_t *conv_prop_invariant_wei_d(convolution_desc_t *desc) {
+ return desc->prop_kind == backward_weights
+ ? &desc->diff_weights_desc : &desc->weights_desc;
+}
+
+memory_desc_t *conv_prop_invariant_bia_d(convolution_desc_t *desc) {
+ return desc->prop_kind == backward_weights
+ ? &desc->diff_bias_desc : &desc->bias_desc;
+}
+
+memory_desc_t *conv_prop_invariant_dst_d(convolution_desc_t *desc) {
+ return utils::one_of(desc->prop_kind, forward_inference, forward_training)
+ ? &desc->dst_desc : &desc->diff_dst_desc;
+}
+
+const memory_desc_t *conv_prop_invariant_src_d(const convolution_desc_t *desc)
+{ return conv_prop_invariant_src_d(const_cast<convolution_desc_t *>(desc)); }
+const memory_desc_t *conv_prop_invariant_wei_d(const convolution_desc_t *desc)
+{ return conv_prop_invariant_wei_d(const_cast<convolution_desc_t *>(desc)); }
+const memory_desc_t *conv_prop_invariant_bia_d(const convolution_desc_t *desc)
+{ return conv_prop_invariant_bia_d(const_cast<convolution_desc_t *>(desc)); }
+const memory_desc_t *conv_prop_invariant_dst_d(const convolution_desc_t *desc)
+{ return conv_prop_invariant_dst_d(const_cast<convolution_desc_t *>(desc)); }
+
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.hpp
new file mode 100644
index 0000000000..b10c36db49
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/convolution_pd.hpp
@@ -0,0 +1,348 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CONVOLUTION_PD_HPP
+#define CONVOLUTION_PD_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive_desc.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+status_t conv_desc_init(convolution_desc_t *conv_desc,
+ prop_kind_t prop_kind, alg_kind_t alg_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *weights_desc,
+ const memory_desc_t *bias_desc, const memory_desc_t *dst_desc,
+ const dims_t strides, const dims_t dilates,
+ const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind);
+
+memory_desc_t *conv_prop_invariant_src_d(convolution_desc_t *desc);
+memory_desc_t *conv_prop_invariant_wei_d(convolution_desc_t *desc);
+memory_desc_t *conv_prop_invariant_bia_d(convolution_desc_t *desc);
+memory_desc_t *conv_prop_invariant_dst_d(convolution_desc_t *desc);
+const memory_desc_t *conv_prop_invariant_src_d(const convolution_desc_t *desc);
+const memory_desc_t *conv_prop_invariant_wei_d(const convolution_desc_t *desc);
+const memory_desc_t *conv_prop_invariant_bia_d(const convolution_desc_t *desc);
+const memory_desc_t *conv_prop_invariant_dst_d(const convolution_desc_t *desc);
+
+struct convolution_fwd_pd_t;
+
+struct convolution_pd_t: public primitive_desc_t {
+ static constexpr auto base_pkind = primitive_kind::convolution;
+
+ convolution_pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : primitive_desc_t(engine, attr, base_pkind)
+ , desc_(*adesc)
+ , hint_fwd_pd_(hint_fwd_pd)
+ {}
+
+ const convolution_desc_t *desc() const { return &desc_; }
+ virtual const op_desc_t *op_desc() const override
+ { return reinterpret_cast<const op_desc_t *>(this->desc()); }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual status_t query(query_t what, int idx, void *result) const override {
+ switch (what) {
+ case pkind_traits<base_pkind>::query_d:
+ *(const convolution_desc_t**)result = desc(); break;
+ default: return primitive_desc_t::query(what, idx, result);
+ }
+ return status::success;
+ }
+
+ /* common conv aux functions */
+
+ dim_t MB() const { return _src_md()->dims[0]; }
+
+ dim_t IC() const { return _src_md()->dims[1]; }
+ dim_t OC() const { return _dst_md()->dims[1]; }
+ dim_t G() const { return with_groups() ? _wei_md()->dims[0] : 1; }
+
+ dim_t ID() const { return ndims() >= 5 ? _src_md()->dims[ndims() - 3] : 1; }
+ dim_t IH() const { return ndims() >= 4 ? _src_md()->dims[ndims() - 2] : 1; }
+ dim_t IW() const { return _src_md()->dims[ndims() - 1]; }
+
+ dim_t OD() const { return ndims() >= 5 ? _dst_md()->dims[ndims() - 3] : 1; }
+ dim_t OH() const { return ndims() >= 4 ? _dst_md()->dims[ndims() - 2] : 1; }
+ dim_t OW() const { return _dst_md()->dims[ndims() - 1]; }
+
+ dim_t KD() const { return ndims() >= 5 ? _wei_md()->dims[ndims() + with_groups() - 3] : 1; }
+ dim_t KH() const { return ndims() >= 4 ? _wei_md()->dims[ndims() + with_groups() - 2] : 1; }
+ dim_t KW() const { return _wei_md()->dims[ndims() + with_groups() - 1]; }
+
+ dim_t KSD() const { return ndims() >= 5 ? desc_.strides[ndims() - 5] : 1; }
+ dim_t KSH() const { return ndims() >= 4 ? desc_.strides[ndims() - 4] : 1; }
+ dim_t KSW() const { return desc_.strides[ndims() - 3]; }
+
+ dim_t KDD() const { return ndims() >= 5 ? desc_.dilates[ndims() - 5] : 0; }
+ dim_t KDH() const { return ndims() >= 4 ? desc_.dilates[ndims() - 4] : 1; }
+ dim_t KDW() const { return desc_.dilates[ndims() - 3]; }
+
+ dim_t padFront() const { return ndims() >= 5 ? desc_.padding[0][ndims() - 5] : 0; }
+ dim_t padBack() const { return ndims() >= 5 ? desc_.padding[1][ndims() - 5] : 0; }
+ dim_t padT() const { return ndims() >= 4 ? desc_.padding[0][ndims() - 4] : 0; }
+ dim_t padB() const { return ndims() >= 4 ? desc_.padding[1][ndims() - 4] : 0; }
+ dim_t padL() const { return desc_.padding[0][ndims() - 3]; }
+ dim_t padR() const { return desc_.padding[1][ndims() - 3]; }
+
+ int ndims() const { return _src_md()->ndims; }
+
+ bool with_bias() const { return !memory_desc_wrapper(*_bia_md()).is_zero(); }
+ bool with_groups() const { return _wei_md()->ndims == ndims() + 1; }
+
+ bool is_fwd() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ }
+
+ bool has_zero_dim_memory() const {
+ const auto s_d = memory_desc_wrapper(*_src_md());
+ const auto d_d = memory_desc_wrapper(*_dst_md());
+ return s_d.has_zero_dim() || d_d.has_zero_dim();
+ }
+
+protected:
+ convolution_desc_t desc_;
+ const convolution_fwd_pd_t *hint_fwd_pd_;
+
+ bool set_default_formats_common_template(
+ memory_desc_t &src_md, format_tag_t src_tag,
+ memory_desc_t &wei_md, format_tag_t wei_tag,
+ memory_desc_t &dst_md, format_tag_t dst_tag,
+ memory_desc_t &bia_md) {
+ using namespace format_tag;
+
+# define IS_OK(f) \
+ do { if ((f) != status::success) return false; } while(0)
+ if (src_md.format_kind == format_kind::any
+ && !utils::one_of(src_tag, any, undef))
+ IS_OK(memory_desc_init_by_tag(src_md, src_tag));
+ if (dst_md.format_kind == format_kind::any
+ && !utils::one_of(dst_tag, any, undef))
+ IS_OK(memory_desc_init_by_tag(dst_md, dst_tag));
+ if (wei_md.format_kind == format_kind::any
+ && !utils::one_of(wei_tag, any, undef))
+ IS_OK(memory_desc_init_by_tag(wei_md, wei_tag));
+ if (with_bias() && bia_md.format_kind == format_kind::any)
+ IS_OK(memory_desc_init_by_tag(bia_md, x));
+# undef IS_OK
+
+ return true;
+ }
+
+ bool set_default_alg_kind(alg_kind_t alg_kind) {
+ assert(utils::one_of(alg_kind, alg_kind::convolution_direct,
+ alg_kind::convolution_winograd));
+ if (desc_.alg_kind == alg_kind::convolution_auto)
+ desc_.alg_kind = alg_kind;
+ return desc_.alg_kind == alg_kind;
+ }
+
+ bool expect_data_types(data_type_t src_dt, data_type_t wei_dt,
+ data_type_t bia_dt, data_type_t dst_dt, data_type_t acc_dt) const {
+ bool ok = true
+ && (src_dt == data_type::undef || _src_md()->data_type == src_dt)
+ && (wei_dt == data_type::undef || _wei_md()->data_type == wei_dt)
+ && (dst_dt == data_type::undef || _dst_md()->data_type == dst_dt)
+ && (acc_dt == data_type::undef || desc_.accum_data_type == acc_dt);
+ if (with_bias() && bia_dt != data_type::undef)
+ ok = ok && _bia_md()->data_type == bia_dt;
+ return ok;
+ }
+
+private:
+ const memory_desc_t *_src_md() const { return conv_prop_invariant_src_d(&desc_); }
+ const memory_desc_t *_wei_md() const { return conv_prop_invariant_wei_d(&desc_); }
+ const memory_desc_t *_bia_md() const { return conv_prop_invariant_bia_d(&desc_); }
+ const memory_desc_t *_dst_md() const { return conv_prop_invariant_dst_d(&desc_); }
+};
+
+struct convolution_fwd_pd_t: public convolution_pd_t {
+ typedef convolution_fwd_pd_t base_class;
+ typedef convolution_fwd_pd_t hint_class;
+
+ convolution_fwd_pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : convolution_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , src_md_(desc_.src_desc)
+ , weights_md_(desc_.weights_desc)
+ , bias_md_(desc_.bias_desc)
+ , dst_md_(desc_.dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_WEIGHTS))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_BIAS && with_bias())
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &src_md_ : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &dst_md_ : nullptr; }
+ virtual const memory_desc_t *weights_md(int index = 0) const override {
+ if (index == 0) return &weights_md_;
+ if (index == 1 && with_bias()) return &bias_md_;
+ return nullptr;
+ }
+
+ virtual int n_inputs() const override { return 2 + with_bias(); }
+ virtual int n_outputs() const override { return 1; }
+
+protected:
+ memory_desc_t src_md_;
+ memory_desc_t weights_md_;
+ memory_desc_t bias_md_;
+ memory_desc_t dst_md_;
+
+ bool set_default_formats_common(format_tag_t src_tag,
+ format_tag_t wei_tag, format_tag_t dst_tag) {
+ return set_default_formats_common_template(src_md_, src_tag,
+ weights_md_, wei_tag, dst_md_, dst_tag, bias_md_);
+ }
+};
+
+struct convolution_bwd_data_pd_t: public convolution_pd_t {
+ typedef convolution_bwd_data_pd_t base_class;
+ typedef convolution_fwd_pd_t hint_class;
+
+ convolution_bwd_data_pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : convolution_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , diff_src_md_(desc_.diff_src_desc)
+ , weights_md_(desc_.weights_desc)
+ , bias_md_(desc_.bias_desc)
+ , diff_dst_md_(desc_.diff_dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_WEIGHTS, MKLDNN_ARG_DIFF_DST))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_SRC)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *diff_src_md(int index = 0) const override
+ { return index == 0 ? &diff_src_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_dst_md_ : nullptr; }
+ virtual const memory_desc_t *weights_md(int index = 0) const override {
+ if (index == 0) return &weights_md_;
+ if (index == 1 && with_bias()) return &bias_md_;
+ return nullptr;
+ }
+
+ virtual int n_inputs() const override { return 2 + with_bias(); }
+ virtual int n_outputs() const override { return 1; }
+
+ virtual bool support_bias() const { return false; }
+
+protected:
+ memory_desc_t diff_src_md_;
+ memory_desc_t weights_md_;
+ memory_desc_t bias_md_;
+ memory_desc_t diff_dst_md_;
+
+ bool set_default_formats_common(format_tag_t diff_src_tag,
+ format_tag_t wei_tag, format_tag_t diff_dst_tag) {
+ return set_default_formats_common_template(diff_src_md_, diff_src_tag,
+ weights_md_, wei_tag, diff_dst_md_, diff_dst_tag, bias_md_);
+ }
+};
+
+struct convolution_bwd_weights_pd_t: public convolution_pd_t {
+ typedef convolution_bwd_weights_pd_t base_class;
+ typedef convolution_fwd_pd_t hint_class;
+
+ convolution_bwd_weights_pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : convolution_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , src_md_(desc_.src_desc)
+ , diff_weights_md_(desc_.diff_weights_desc)
+ , diff_bias_md_(desc_.diff_bias_desc)
+ , diff_dst_md_(desc_.diff_dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_DIFF_DST))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_WEIGHTS)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_DIFF_BIAS && with_bias())
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &src_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_dst_md_ : nullptr; }
+ virtual const memory_desc_t *diff_weights_md(int index = 0) const override {
+ if (index == 0) return &diff_weights_md_;
+ if (index == 1 && with_bias()) return &diff_bias_md_;
+ return nullptr;
+ }
+
+ virtual int n_inputs() const override { return 2; }
+ virtual int n_outputs() const override { return 1 + with_bias(); }
+
+protected:
+ memory_desc_t src_md_;
+ memory_desc_t diff_weights_md_;
+ memory_desc_t diff_bias_md_;
+ memory_desc_t diff_dst_md_;
+
+ bool set_default_formats_common(format_tag_t src_tag,
+ format_tag_t diff_wei_tag, format_tag_t diff_dst_tag) {
+ return set_default_formats_common_template(src_md_, src_tag,
+ diff_weights_md_, diff_wei_tag, diff_dst_md_, diff_dst_tag,
+ diff_bias_md_);
+ }
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/deconvolution.cpp b/thirdparty/oidn/mkl-dnn/src/common/deconvolution.cpp
new file mode 100644
index 0000000000..98063c1c37
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/deconvolution.cpp
@@ -0,0 +1,188 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn.h"
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::alg_kind;
+using namespace mkldnn::impl::types;
+
+namespace {
+status_t deconv_desc_init(deconvolution_desc_t *deconv_desc,
+ prop_kind_t prop_kind, alg_kind_t alg_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *weights_desc,
+ const memory_desc_t *bias_desc, const memory_desc_t *dst_desc,
+ const dims_t strides, const dims_t dilates, const dims_t padding_l,
+ const dims_t padding_r, padding_kind_t padding_kind) {
+ bool args_ok = true
+ && !any_null(deconv_desc, src_desc, weights_desc, dst_desc, strides,
+ padding_l)
+ && one_of(alg_kind, deconvolution_direct, deconvolution_winograd)
+ && one_of(padding_kind, padding_kind::padding_zero);
+ if (!args_ok)
+ return invalid_arguments;
+
+ if (padding_r == nullptr)
+ padding_r = padding_l;
+
+ auto dd = deconvolution_desc_t();
+ dd.primitive_kind = primitive_kind::deconvolution;
+ dd.prop_kind = prop_kind;
+ dd.alg_kind = alg_kind;
+
+ dd.diff_src_desc = dd.src_desc = zero_md();
+ dd.diff_dst_desc = dd.dst_desc = zero_md();
+ dd.diff_weights_desc = dd.weights_desc = zero_md();
+ dd.diff_bias_desc = dd.bias_desc = zero_md();
+
+ const bool is_fwd = one_of(prop_kind, forward_training, forward_inference);
+ const bool with_bias
+ = bias_desc && bias_desc->format_kind != format_kind::undef;
+ const bool with_groups = weights_desc->ndims == src_desc->ndims + 1;
+
+ (prop_kind == backward_data ? dd.diff_src_desc : dd.src_desc) = *src_desc;
+ (is_fwd ? dd.dst_desc : dd.diff_dst_desc) = *dst_desc;
+ (prop_kind == backward_weights ? dd.diff_weights_desc : dd.weights_desc)
+ = *weights_desc;
+ if (with_bias)
+ (prop_kind == backward_weights ? dd.diff_bias_desc : dd.bias_desc)
+ = *bias_desc;
+
+ int sp_dims = src_desc->ndims - 2;
+ utils::array_copy(dd.strides, strides, sp_dims);
+ utils::array_copy(dd.padding[0], padding_l, sp_dims);
+ utils::array_copy(dd.padding[1], padding_r, sp_dims);
+ if (dilates)
+ utils::array_copy(dd.dilates, dilates, sp_dims);
+ else
+ utils::array_set(dd.dilates, 0, sp_dims);
+
+ dd.padding_kind = padding_kind;
+ dd.accum_data_type = types::default_accum_data_type(src_desc->data_type,
+ weights_desc->data_type, dst_desc->data_type, prop_kind);
+
+ const int g = with_groups ? weights_desc->dims[0] : 1;
+ bool consistency = true
+ && src_desc->ndims == dst_desc->ndims
+ && utils::one_of(src_desc->ndims, 3, 4, 5)
+ && utils::one_of(weights_desc->ndims, src_desc->ndims,
+ src_desc->ndims + 1)
+ && (with_bias ? bias_desc->ndims == 1 : true)
+ && (with_bias ? bias_desc->dims[0] == dst_desc->dims[1] : true)
+ && src_desc->dims[0] == dst_desc->dims[0]
+ && src_desc->dims[1] == g * weights_desc->dims[with_groups + 1]
+ && dst_desc->dims[1] == g * weights_desc->dims[with_groups + 0];
+ for (int i = 2; i < src_desc->ndims; ++i) {
+ int src = src_desc->dims[i];
+ int ker = weights_desc->dims[with_groups + i];
+ int dil = dd.dilates[i - 2];
+ int pad = padding_l[i - 2] + padding_r[i - 2];
+ int str = strides[i - 2];
+ int dst = dst_desc->dims[i];
+ int ker_range = 1 + (ker - 1) * (dil + 1);
+
+ consistency
+ = consistency && (dst - ker_range + pad) / str + 1 == src;
+ }
+ if (!consistency)
+ return invalid_arguments;
+
+ *deconv_desc = dd;
+ return success;
+}
+}
+
+status_t mkldnn_deconvolution_forward_desc_init(
+ deconvolution_desc_t *deconv_desc, prop_kind_t prop_kind,
+ alg_kind_t alg_kind, const memory_desc_t *src_desc,
+ const memory_desc_t *weights_desc, const memory_desc_t *bias_desc,
+ const memory_desc_t *dst_desc, const dims_t strides,
+ const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ if (!one_of(prop_kind, forward_training, forward_inference))
+ return invalid_arguments;
+ return deconv_desc_init(deconv_desc, prop_kind, alg_kind, src_desc,
+ weights_desc, bias_desc, dst_desc, strides, nullptr, padding_l,
+ padding_r, padding_kind);
+}
+
+status_t mkldnn_dilated_deconvolution_forward_desc_init(
+ deconvolution_desc_t *deconv_desc, prop_kind_t prop_kind,
+ alg_kind_t alg_kind, const memory_desc_t *src_desc,
+ const memory_desc_t *weights_desc, const memory_desc_t *bias_desc,
+ const memory_desc_t *dst_desc, const dims_t strides,
+ const dims_t dilates, const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ if (!one_of(prop_kind, forward_training, forward_inference))
+ return invalid_arguments;
+ return deconv_desc_init(deconv_desc, prop_kind, alg_kind, src_desc,
+ weights_desc, bias_desc, dst_desc, strides, dilates, padding_l,
+ padding_r, padding_kind);
+}
+
+status_t mkldnn_deconvolution_backward_data_desc_init(
+ deconvolution_desc_t *deconv_desc, alg_kind_t alg_kind,
+ const memory_desc_t *diff_src_desc, const memory_desc_t *weights_desc,
+ const memory_desc_t *diff_dst_desc, const dims_t strides,
+ const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ return deconv_desc_init(deconv_desc, backward_data, alg_kind, diff_src_desc,
+ weights_desc, nullptr, diff_dst_desc, strides, nullptr, padding_l,
+ padding_r, padding_kind);
+}
+
+status_t mkldnn_dilated_deconvolution_backward_data_desc_init(
+ deconvolution_desc_t *deconv_desc, alg_kind_t alg_kind,
+ const memory_desc_t *diff_src_desc, const memory_desc_t *weights_desc,
+ const memory_desc_t *diff_dst_desc, const dims_t strides,
+ const dims_t dilates, const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ return deconv_desc_init(deconv_desc, backward_data, alg_kind, diff_src_desc,
+ weights_desc, nullptr, diff_dst_desc, strides,dilates, padding_l,
+ padding_r, padding_kind);
+}
+
+status_t mkldnn_deconvolution_backward_weights_desc_init(
+ deconvolution_desc_t *deconv_desc, alg_kind_t alg_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *diff_weights_desc,
+ const memory_desc_t *diff_bias_desc, const memory_desc_t *diff_dst_desc,
+ const dims_t strides, const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ return deconv_desc_init(deconv_desc, backward_weights, alg_kind, src_desc,
+ diff_weights_desc, diff_bias_desc, diff_dst_desc, strides, nullptr,
+ padding_l, padding_r, padding_kind);
+}
+
+status_t mkldnn_dilated_deconvolution_backward_weights_desc_init(
+ deconvolution_desc_t *deconv_desc, alg_kind_t alg_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *diff_weights_desc,
+ const memory_desc_t *diff_bias_desc, const memory_desc_t *diff_dst_desc,
+ const dims_t strides, const dims_t dilates, const dims_t padding_l,
+ const dims_t padding_r, padding_kind_t padding_kind) {
+ return deconv_desc_init(deconv_desc, backward_weights, alg_kind, src_desc,
+ diff_weights_desc, diff_bias_desc, diff_dst_desc, strides, dilates,
+ padding_l, padding_r, padding_kind);
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/deconvolution_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/deconvolution_pd.hpp
new file mode 100644
index 0000000000..539e44bd9b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/deconvolution_pd.hpp
@@ -0,0 +1,293 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef DECONVOLUTION_PD_HPP
+#define DECONVOLUTION_PD_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "convolution_pd.hpp"
+#include "primitive_desc.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct deconvolution_fwd_pd_t;
+
+struct deconvolution_pd_t: public primitive_desc_t {
+ static constexpr auto base_pkind = primitive_kind::deconvolution;
+
+ deconvolution_pd_t(engine_t *engine,
+ const deconvolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const deconvolution_fwd_pd_t *hint_fwd_pd)
+ : primitive_desc_t(engine, attr, base_pkind)
+ , desc_(*adesc)
+ , hint_fwd_pd_(hint_fwd_pd)
+ {}
+
+ const deconvolution_desc_t *desc() const { return &desc_; }
+ virtual const op_desc_t *op_desc() const override
+ { return reinterpret_cast<const op_desc_t *>(this->desc()); }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual status_t query(query_t what, int idx, void *result) const override {
+ switch (what) {
+ case pkind_traits<base_pkind>::query_d:
+ *(const deconvolution_desc_t **)result = desc();
+ break;
+ default: return primitive_desc_t::query(what, idx, result);
+ }
+ return status::success;
+ }
+
+ /* common deconv aux functions (note that conv_desc_t == deconv_desc_t) */
+
+ dim_t MB() const { return conv_prop_invariant_src_d(&desc_)->dims[0]; }
+
+ dim_t IC() const { return conv_prop_invariant_src_d(&desc_)->dims[1]; }
+ dim_t OC() const { return conv_prop_invariant_dst_d(&desc_)->dims[1]; }
+ dim_t G() const
+ { return with_groups() ? conv_prop_invariant_wei_d(&desc_)->dims[0] : 1; }
+
+ dim_t ID() const {
+ return ndims() >= 5
+ ? conv_prop_invariant_src_d(&desc_)->dims[ndims() - 3] : 1;
+ }
+ dim_t IH() const {
+ return ndims() >= 4
+ ? conv_prop_invariant_src_d(&desc_)->dims[ndims() - 2] : 1;
+ }
+ dim_t IW() const {
+ return conv_prop_invariant_src_d(&desc_)->dims[ndims() - 1];
+ }
+
+ dim_t OD() const {
+ return ndims() >= 5
+ ? conv_prop_invariant_dst_d(&desc_)->dims[ndims() - 3] : 1;
+ }
+ dim_t OH() const {
+ return ndims() >= 4
+ ? conv_prop_invariant_dst_d(&desc_)->dims[ndims() - 2] : 1;
+ }
+ dim_t OW() const {
+ return conv_prop_invariant_dst_d(&desc_)->dims[ndims() - 1];
+ }
+
+ dim_t KD() const {
+ const int w_ndims = ndims() + with_groups();
+ return ndims() >= 5
+ ? conv_prop_invariant_wei_d(&desc_)->dims[w_ndims - 3] : 1;
+ }
+ dim_t KH() const {
+ const int w_ndims = ndims() + with_groups();
+ return ndims() >= 4
+ ? conv_prop_invariant_wei_d(&desc_)->dims[w_ndims - 2] : 1;
+ }
+ dim_t KW() const {
+ const int w_ndims = ndims() + with_groups();
+ return conv_prop_invariant_wei_d(&desc_)->dims[w_ndims - 1];
+ }
+
+ dim_t KSD() const { return ndims() >= 5 ? desc_.strides[ndims() - 5] : 1; }
+ dim_t KSH() const { return ndims() >= 4 ? desc_.strides[ndims() - 4] : 1; }
+ dim_t KSW() const { return desc_.strides[ndims() - 3]; }
+
+ dim_t KDD() const { return ndims() >= 5 ? desc_.dilates[ndims() - 5] : 0; }
+ dim_t KDH() const { return ndims() >= 4 ? desc_.dilates[ndims() - 4] : 1; }
+ dim_t KDW() const { return desc_.dilates[ndims() - 3]; }
+
+ dim_t padFront() const
+ { return ndims() >= 5 ? desc_.padding[0][ndims() - 5] : 0; }
+ dim_t padBack() const
+ { return ndims() >= 5 ? desc_.padding[1][ndims() - 5] : 0; }
+ dim_t padT() const
+ { return ndims() >= 4 ? desc_.padding[0][ndims() - 4] : 0; }
+ dim_t padB() const
+ { return ndims() >= 4 ? desc_.padding[1][ndims() - 4] : 0; }
+ dim_t padL() const { return desc_.padding[0][ndims() - 3]; }
+ dim_t padR() const { return desc_.padding[1][ndims() - 3]; }
+
+ bool with_bias() const {
+ return
+ !memory_desc_wrapper(*conv_prop_invariant_bia_d(&desc_)).is_zero();
+ }
+
+ bool with_groups() const
+ { return conv_prop_invariant_wei_d(&desc_)->ndims == ndims() + 1; }
+
+ int ndims() const { return conv_prop_invariant_src_d(&desc_)->ndims; }
+
+ bool is_fwd() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ }
+
+ bool has_zero_dim_memory() const {
+ const auto s_d = memory_desc_wrapper(*conv_prop_invariant_src_d(&desc_));
+ const auto d_d = memory_desc_wrapper(*conv_prop_invariant_dst_d(&desc_));
+ return s_d.has_zero_dim() || d_d.has_zero_dim();
+ }
+
+protected:
+ deconvolution_desc_t desc_;
+ const deconvolution_fwd_pd_t *hint_fwd_pd_;
+};
+
+struct deconvolution_fwd_pd_t: public deconvolution_pd_t {
+ typedef deconvolution_fwd_pd_t base_class;
+ typedef deconvolution_fwd_pd_t hint_class;
+
+ deconvolution_fwd_pd_t(engine_t *engine,
+ const deconvolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const deconvolution_fwd_pd_t *hint_fwd_pd)
+ : deconvolution_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , src_md_(desc_.src_desc)
+ , weights_md_(desc_.weights_desc)
+ , bias_md_(desc_.bias_desc)
+ , dst_md_(desc_.dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_WEIGHTS))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_BIAS && with_bias())
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &src_md_ : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &dst_md_ : nullptr; }
+ virtual const memory_desc_t *weights_md(int index = 0) const override {
+ if (index == 0) return &weights_md_;
+ if (index == 1 && with_bias()) return &bias_md_;
+ return nullptr;
+ }
+
+ virtual int n_inputs() const override { return 2 + with_bias(); }
+ virtual int n_outputs() const override { return 1; }
+
+protected:
+ memory_desc_t src_md_;
+ memory_desc_t weights_md_;
+ memory_desc_t bias_md_;
+ memory_desc_t dst_md_;
+};
+
+struct deconvolution_bwd_data_pd_t: public deconvolution_pd_t {
+ typedef deconvolution_bwd_data_pd_t base_class;
+ typedef deconvolution_fwd_pd_t hint_class;
+
+ deconvolution_bwd_data_pd_t(engine_t *engine,
+ const deconvolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const deconvolution_fwd_pd_t *hint_fwd_pd)
+ : deconvolution_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , diff_src_md_(desc_.diff_src_desc)
+ , weights_md_(desc_.weights_desc)
+ , diff_dst_md_(desc_.diff_dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_WEIGHTS, MKLDNN_ARG_DIFF_DST))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_SRC)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *diff_src_md(int index = 0) const override
+ { return index == 0 ? &diff_src_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_dst_md_ : nullptr; }
+ virtual const memory_desc_t *weights_md(int index = 0) const override
+ { return index == 0 ? &weights_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return 2; }
+ virtual int n_outputs() const override { return 1; }
+
+protected:
+ memory_desc_t diff_src_md_;
+ memory_desc_t weights_md_;
+ memory_desc_t diff_dst_md_;
+};
+
+struct deconvolution_bwd_weights_pd_t: public deconvolution_pd_t {
+ typedef deconvolution_bwd_weights_pd_t base_class;
+ typedef deconvolution_fwd_pd_t hint_class;
+
+ deconvolution_bwd_weights_pd_t(engine_t *engine,
+ const deconvolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const deconvolution_fwd_pd_t *hint_fwd_pd)
+ : deconvolution_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , src_md_(desc_.src_desc)
+ , diff_weights_md_(desc_.diff_weights_desc)
+ , diff_bias_md_(desc_.diff_bias_desc)
+ , diff_dst_md_(desc_.diff_dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_DIFF_DST))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_WEIGHTS)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_DIFF_BIAS && with_bias())
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &src_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_dst_md_ : nullptr; }
+ virtual const memory_desc_t *diff_weights_md(int index = 0) const override {
+ if (index == 0) return &diff_weights_md_;
+ if (index == 1 && with_bias()) return &diff_bias_md_;
+ return nullptr;
+ }
+
+ virtual int n_inputs() const override { return 2; }
+ virtual int n_outputs() const override { return 1 + with_bias(); }
+
+protected:
+ memory_desc_t src_md_;
+ memory_desc_t diff_weights_md_;
+ memory_desc_t diff_bias_md_;
+ memory_desc_t diff_dst_md_;
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/eltwise.cpp b/thirdparty/oidn/mkl-dnn/src/common/eltwise.cpp
new file mode 100644
index 0000000000..f1708fca52
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/eltwise.cpp
@@ -0,0 +1,84 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::alg_kind;
+using namespace mkldnn::impl::types;
+
+namespace {
+status_t eltwise_desc_init(eltwise_desc_t *eltwise_desc, prop_kind_t prop_kind,
+ alg_kind_t alg_kind, const memory_desc_t *data_desc,
+ const memory_desc_t *diff_data_desc, float alpha, float beta) {
+ bool args_ok = true
+ && !any_null(eltwise_desc, data_desc)
+ && one_of(prop_kind, forward_training, forward_inference,
+ backward_data)
+ && one_of(alg_kind, eltwise_relu, eltwise_tanh, eltwise_elu,
+ eltwise_square, eltwise_abs, eltwise_sqrt, eltwise_linear,
+ eltwise_bounded_relu, eltwise_soft_relu, eltwise_logistic)
+ && IMPLICATION(prop_kind == backward_data, diff_data_desc != nullptr);
+ if (!args_ok) return invalid_arguments;
+
+ auto ed = eltwise_desc_t();
+ ed.primitive_kind = primitive_kind::eltwise;
+ ed.prop_kind = prop_kind;
+ ed.alg_kind = alg_kind;
+
+ ed.data_desc = *data_desc;
+ ed.diff_data_desc =
+ (ed.prop_kind == backward_data) ? *diff_data_desc : zero_md();
+
+ ed.alpha = alpha;
+ ed.beta = beta;
+
+ bool consistency = true
+ && IMPLICATION(ed.prop_kind == backward_data,
+ array_cmp(ed.diff_data_desc.dims, ed.data_desc.dims,
+ ed.diff_data_desc.ndims));
+ if (!consistency) return invalid_arguments;
+
+ *eltwise_desc = ed;
+ return success;
+}
+}
+
+status_t mkldnn_eltwise_forward_desc_init(eltwise_desc_t *eltwise_desc,
+ prop_kind_t prop_kind, alg_kind_t alg_kind,
+ const memory_desc_t *data_desc, float alpha, float beta) {
+ if (!one_of(prop_kind, forward_training, forward_inference))
+ return invalid_arguments;
+ return eltwise_desc_init(eltwise_desc, prop_kind, alg_kind, data_desc,
+ nullptr, alpha, beta);
+}
+
+status_t mkldnn_eltwise_backward_desc_init(eltwise_desc_t *eltwise_desc,
+ alg_kind_t alg_kind, const memory_desc_t *diff_data_desc,
+ const memory_desc_t *data_desc, float alpha, float beta) {
+ return eltwise_desc_init(eltwise_desc, backward_data, alg_kind, data_desc,
+ diff_data_desc, alpha, beta);
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/eltwise_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/eltwise_pd.hpp
new file mode 100644
index 0000000000..9fd260fcee
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/eltwise_pd.hpp
@@ -0,0 +1,161 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef ELTWISE_PD_HPP
+#define ELTWISE_PD_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive_desc.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct eltwise_fwd_pd_t;
+
+struct eltwise_pd_t: public primitive_desc_t {
+ static constexpr auto base_pkind = primitive_kind::eltwise;
+
+ eltwise_pd_t(mkldnn::impl::engine_t *engine,
+ const eltwise_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const eltwise_fwd_pd_t *hint_fwd_pd)
+ : primitive_desc_t(engine, attr, base_pkind)
+ , desc_(*adesc)
+ , hint_fwd_pd_(hint_fwd_pd)
+ , data_md_(desc_.data_desc)
+ {}
+
+ const eltwise_desc_t *desc() const { return &desc_; }
+ virtual const op_desc_t *op_desc() const override
+ { return reinterpret_cast<const op_desc_t *>(this->desc()); }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual status_t query(query_t what, int idx, void *result) const override {
+ switch (what) {
+ case query::eltwise_d:
+ *(const eltwise_desc_t**)result = desc(); break;
+ default: return primitive_desc_t::query(what, idx, result);
+ }
+ return status::success;
+ }
+
+ /* common eltwise aux functions */
+
+ dim_t MB() const { return data_desc().dims[0]; }
+ dim_t C() const { return data_desc().dims[1]; }
+ dim_t D() const { return ndims() >= 5 ? data_desc().dims[ndims() - 3] : 1; }
+ dim_t H() const { return ndims() >= 4 ? data_desc().dims[ndims() - 2] : 1; }
+ dim_t W() const { return ndims() >= 3 ? data_desc().dims[ndims() - 1] : 1; }
+
+ int ndims() const { return data_desc().ndims; }
+
+ bool is_fwd() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ }
+
+ bool has_zero_dim_memory() const
+ { return memory_desc_wrapper(desc_.data_desc).has_zero_dim(); }
+
+protected:
+ eltwise_desc_t desc_;
+ const eltwise_fwd_pd_t *hint_fwd_pd_;
+
+ memory_desc_t data_md_;
+
+private:
+ const memory_desc_t &data_desc() const { return desc_.data_desc; }
+};
+
+struct eltwise_fwd_pd_t: public eltwise_pd_t {
+ typedef eltwise_fwd_pd_t base_class;
+ typedef eltwise_fwd_pd_t hint_class;
+
+ eltwise_fwd_pd_t(mkldnn::impl::engine_t *engine,
+ const eltwise_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const eltwise_fwd_pd_t *hint_fwd_pd)
+ : eltwise_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (arg == MKLDNN_ARG_SRC)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &data_md_ : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &data_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return 1; }
+ virtual int n_outputs() const override { return 1; }
+
+ bool is_zero_preserved() const
+ { return math::eltwise_fwd_preserves_zero(desc_.alg_kind); }
+};
+
+struct eltwise_bwd_pd_t: public eltwise_pd_t {
+ typedef eltwise_bwd_pd_t base_class;
+ typedef eltwise_fwd_pd_t hint_class;
+
+ eltwise_bwd_pd_t(engine_t *engine,
+ const eltwise_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const eltwise_fwd_pd_t *hint_fwd_pd)
+ : eltwise_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , diff_data_md_(desc_.diff_data_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_DIFF_DST))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_SRC)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &data_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_data_md_ : nullptr; }
+ virtual const memory_desc_t *diff_src_md(int index = 0) const override
+ { return index == 0 ? &diff_data_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return 2; }
+ virtual int n_outputs() const override { return 1; }
+
+ bool is_zero_preserved() const { return true; }
+
+protected:
+ memory_desc_t diff_data_md_;
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/engine.cpp b/thirdparty/oidn/mkl-dnn/src/common/engine.cpp
new file mode 100644
index 0000000000..3b3e25456d
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/engine.cpp
@@ -0,0 +1,75 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn.h"
+#include "engine.hpp"
+#include "nstl.hpp"
+
+#include "c_types_map.hpp"
+#include "../cpu/cpu_engine.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+engine_factory_t *engine_factories[] = {
+ &cpu::engine_factory,
+ nullptr,
+};
+
+static inline engine_factory_t *get_engine_factory(engine_kind_t kind) {
+ for (engine_factory_t **ef = engine_factories; *ef; ef++)
+ if ((*ef)->kind() == kind)
+ return *ef;
+ return nullptr;
+}
+
+}
+}
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::status;
+
+size_t mkldnn_engine_get_count(engine_kind_t kind) {
+ engine_factory_t *ef = get_engine_factory(kind);
+ return ef != nullptr ? ef->count() : 0;
+}
+
+status_t mkldnn_engine_create(engine_t **engine,
+ engine_kind_t kind, size_t index) {
+ if (engine == nullptr)
+ return invalid_arguments;
+
+ engine_factory_t *ef = get_engine_factory(kind);
+ if (ef == nullptr || index >= ef->count())
+ return invalid_arguments;
+
+ return ef->engine_create(engine, index);
+}
+
+status_t mkldnn_engine_get_kind(engine_t *engine, engine_kind_t *kind) {
+ if (engine == nullptr)
+ return invalid_arguments;
+ *kind = engine->kind();
+ return success;
+}
+
+status_t mkldnn_engine_destroy(engine_t *engine) {
+ /* TODO: engine->dec_ref_count(); */
+ delete engine;
+ return success;
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/engine.hpp b/thirdparty/oidn/mkl-dnn/src/common/engine.hpp
new file mode 100644
index 0000000000..8ac8a29de5
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/engine.hpp
@@ -0,0 +1,119 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef ENGINE_HPP
+#define ENGINE_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive.hpp"
+#include "utils.hpp"
+
+/** \brief An abstraction of an execution unit with shared resources
+ *
+ * Responsibilities:
+ * - Provide engine specific memory allocation
+ * - Provide engine specific primitive_desc_t creators
+ */
+struct mkldnn_engine: public mkldnn::impl::c_compatible {
+ mkldnn_engine(mkldnn::impl::engine_kind_t kind)
+ : kind_(kind)
+ {}
+ virtual ~mkldnn_engine() {}
+
+ /** get kind of the current engine */
+ virtual mkldnn::impl::engine_kind_t kind() const { return kind_; }
+
+ /** allocate memory */
+ virtual mkldnn::impl::status_t memory_create(
+ mkldnn::impl::memory_t **memory,
+ const mkldnn::impl::memory_desc_t *md,
+ void *handle) = 0;
+
+ /** implementation section (typedefs) */
+
+ // TODO: remove engine?
+ typedef mkldnn::impl::status_t (*reorder_primitive_desc_create_f)(
+ mkldnn::impl::reorder_pd_t **reorder_pd,
+ mkldnn::impl::engine_t *engine,
+ const mkldnn::impl::primitive_attr_t *attr,
+ mkldnn::impl::engine_t *src_engine,
+ const mkldnn::impl::memory_desc_t *src_md,
+ mkldnn::impl::engine_t *dst_engine,
+ const mkldnn::impl::memory_desc_t *dst_md);
+
+ typedef mkldnn::impl::status_t (*concat_primitive_desc_create_f)(
+ mkldnn::impl::concat_pd_t **concat_pd,
+ mkldnn::impl::engine_t *engine,
+ const mkldnn::impl::primitive_attr_t *attr,
+ const mkldnn::impl::memory_desc_t *dst_md,
+ int n, int concat_dim,
+ const mkldnn::impl::memory_desc_t *src_mds);
+
+ typedef mkldnn::impl::status_t (*sum_primitive_desc_create_f)(
+ mkldnn::impl::sum_pd_t **sum_pd,
+ mkldnn::impl::engine_t *engine,
+ const mkldnn::impl::primitive_attr_t *attr,
+ const mkldnn::impl::memory_desc_t *dst_md,
+ int n, const float *scales,
+ const mkldnn::impl::memory_desc_t *src_mds);
+
+ typedef mkldnn::impl::status_t (*primitive_desc_create_f)(
+ mkldnn::impl::primitive_desc_t **, const mkldnn::impl::op_desc_t *,
+ const mkldnn::impl::primitive_attr_t *attr,
+ mkldnn::impl::engine_t *, const mkldnn::impl::primitive_desc_t *);
+
+ /* implementation section */
+
+ /** return the list of reorder implementations. engine guarantees to return
+ * a NULL-terminated list */
+ virtual const reorder_primitive_desc_create_f*
+ get_reorder_implementation_list() const = 0;
+
+ /** return the list of concat implementations. engine guarantees to return
+ * a NULL-terminated list */
+ virtual const concat_primitive_desc_create_f*
+ get_concat_implementation_list() const = 0;
+
+ /** return the list of sum implementations. engine guarantees to return
+ * a NULL-terminated list */
+ virtual const sum_primitive_desc_create_f*
+ get_sum_implementation_list() const = 0;
+
+ /** return the list of implementations. engine guarantees to return a
+ * NULL-terminated list */
+ virtual const primitive_desc_create_f* get_implementation_list() const = 0;
+
+protected:
+ mkldnn::impl::engine_kind_t kind_;
+};
+
+namespace mkldnn {
+namespace impl {
+
+struct engine_factory_t: public c_compatible {
+ virtual size_t count() const = 0;
+ virtual engine_kind_t kind() const = 0;
+ virtual status_t engine_create(engine_t **engine, size_t index) const = 0;
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/inner_product.cpp b/thirdparty/oidn/mkl-dnn/src/common/inner_product.cpp
new file mode 100644
index 0000000000..5a9f58cb1e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/inner_product.cpp
@@ -0,0 +1,106 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::types;
+
+namespace {
+status_t ip_desc_init(inner_product_desc_t *ip_desc, prop_kind_t prop_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *weights_desc,
+ const memory_desc_t *bias_desc, const memory_desc_t *dst_desc) {
+ bool args_ok = !any_null(ip_desc, src_desc, weights_desc, dst_desc);
+ if (!args_ok) return invalid_arguments;
+
+ auto id = inner_product_desc_t();
+ id.primitive_kind = primitive_kind::inner_product;
+ id.prop_kind = prop_kind;
+
+ id.diff_src_desc = id.src_desc = zero_md();
+ id.diff_dst_desc = id.dst_desc = zero_md();
+ id.diff_weights_desc = id.weights_desc = zero_md();
+ id.diff_bias_desc = id.bias_desc = zero_md();
+
+ const bool is_fwd = one_of(prop_kind, forward_training, forward_inference);
+ const bool with_bias =
+ bias_desc && bias_desc->format_kind != format_kind::undef;
+
+ (prop_kind == backward_data ? id.diff_src_desc : id.src_desc) = *src_desc;
+ (is_fwd ? id.dst_desc : id.diff_dst_desc) = *dst_desc;
+ (prop_kind == backward_weights ? id.diff_weights_desc : id.weights_desc) =
+ *weights_desc;
+ if (with_bias)
+ (prop_kind == backward_weights ? id.diff_bias_desc : id.bias_desc) =
+ *bias_desc;
+
+ id.accum_data_type = types::default_accum_data_type(src_desc->data_type,
+ weights_desc->data_type, dst_desc->data_type, prop_kind);
+
+ bool consistency = true
+ && memory_desc_wrapper(weights_desc).nelems()
+ && one_of(src_desc->ndims, 2, 3, 4, 5)
+ && dst_desc->ndims == 2
+ && weights_desc->ndims == src_desc->ndims
+ && (with_bias ? bias_desc->ndims == 1 : true)
+ && (with_bias ? bias_desc->dims[0] == dst_desc->dims[1] : true)
+ && src_desc->dims[0] == dst_desc->dims[0]
+ && array_cmp(&src_desc->dims[1], &weights_desc->dims[1],
+ src_desc->ndims - 1)
+ && dst_desc->dims[1] == weights_desc->dims[0];
+ if (!consistency) return invalid_arguments;
+
+ *ip_desc = id;
+ return success;
+}
+}
+
+status_t mkldnn_inner_product_forward_desc_init(inner_product_desc_t *ip_desc,
+ prop_kind_t prop_kind, const memory_desc_t *src_desc,
+ const memory_desc_t *weights_desc, const memory_desc_t *bias_desc,
+ const memory_desc_t *dst_desc) {
+ if (!one_of(prop_kind, forward_training, forward_inference))
+ return invalid_arguments;
+ return ip_desc_init(ip_desc, prop_kind, src_desc, weights_desc, bias_desc,
+ dst_desc);
+}
+
+status_t mkldnn_inner_product_backward_data_desc_init(
+ inner_product_desc_t *ip_desc, const memory_desc_t *diff_src_desc,
+ const memory_desc_t *weights_desc, const memory_desc_t *diff_dst_desc)
+{
+ return ip_desc_init(ip_desc, backward_data, diff_src_desc, weights_desc,
+ nullptr, diff_dst_desc);
+}
+
+status_t mkldnn_inner_product_backward_weights_desc_init(
+ inner_product_desc_t *ip_desc, const memory_desc_t *src_desc,
+ const memory_desc_t *diff_weights_desc,
+ const memory_desc_t *diff_bias_desc,
+ const memory_desc_t *diff_dst_desc) {
+ return ip_desc_init(ip_desc, backward_weights, src_desc, diff_weights_desc,
+ diff_bias_desc, diff_dst_desc);
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.cpp b/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.cpp
new file mode 100644
index 0000000000..091cf0f5d6
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.cpp
@@ -0,0 +1,56 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "utils.hpp"
+
+#include "inner_product_pd.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+using namespace prop_kind;
+
+memory_desc_t *ip_prop_invariant_src_d(inner_product_desc_t *desc) {
+ return desc->prop_kind == backward_data
+ ? &desc->diff_src_desc : &desc->src_desc;
+}
+
+memory_desc_t *ip_prop_invariant_wei_d(inner_product_desc_t *desc) {
+ return desc->prop_kind == backward_weights
+ ? &desc->diff_weights_desc : &desc->weights_desc;
+}
+
+memory_desc_t *ip_prop_invariant_bia_d(inner_product_desc_t *desc) {
+ return desc->prop_kind == backward_weights
+ ? &desc->diff_bias_desc : &desc->bias_desc;
+}
+
+memory_desc_t *ip_prop_invariant_dst_d(inner_product_desc_t *desc) {
+ return utils::one_of(desc->prop_kind, forward_inference, forward_training)
+ ? &desc->dst_desc : &desc->diff_dst_desc;
+}
+
+const memory_desc_t *ip_prop_invariant_src_d(const inner_product_desc_t *desc)
+{ return ip_prop_invariant_src_d(const_cast<inner_product_desc_t *>(desc)); }
+const memory_desc_t *ip_prop_invariant_wei_d(const inner_product_desc_t *desc)
+{ return ip_prop_invariant_wei_d(const_cast<inner_product_desc_t *>(desc)); }
+const memory_desc_t *ip_prop_invariant_bia_d(const inner_product_desc_t *desc)
+{ return ip_prop_invariant_bia_d(const_cast<inner_product_desc_t *>(desc)); }
+const memory_desc_t *ip_prop_invariant_dst_d(const inner_product_desc_t *desc)
+{ return ip_prop_invariant_dst_d(const_cast<inner_product_desc_t *>(desc)); }
+
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.hpp
new file mode 100644
index 0000000000..c426de632c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/inner_product_pd.hpp
@@ -0,0 +1,321 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef INNER_PRODUCT_PD_HPP
+#define INNER_PRODUCT_PD_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive_desc.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+memory_desc_t *ip_prop_invariant_src_d(inner_product_desc_t *desc);
+memory_desc_t *ip_prop_invariant_wei_d(inner_product_desc_t *desc);
+memory_desc_t *ip_prop_invariant_bia_d(inner_product_desc_t *desc);
+memory_desc_t *ip_prop_invariant_dst_d(inner_product_desc_t *desc);
+const memory_desc_t *ip_prop_invariant_src_d(const inner_product_desc_t *desc);
+const memory_desc_t *ip_prop_invariant_wei_d(const inner_product_desc_t *desc);
+const memory_desc_t *ip_prop_invariant_bia_d(const inner_product_desc_t *desc);
+const memory_desc_t *ip_prop_invariant_dst_d(const inner_product_desc_t *desc);
+
+struct inner_product_fwd_pd_t;
+
+struct inner_product_pd_t: public primitive_desc_t {
+ static constexpr auto base_pkind = primitive_kind::inner_product;
+
+ inner_product_pd_t(engine_t *engine,
+ const inner_product_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const inner_product_fwd_pd_t *hint_fwd_pd)
+ : primitive_desc_t(engine, attr, base_pkind)
+ , desc_(*adesc)
+ , hint_fwd_pd_(hint_fwd_pd)
+ {}
+
+ const inner_product_desc_t *desc() const { return &desc_; }
+ virtual const op_desc_t *op_desc() const override
+ { return reinterpret_cast<const op_desc_t *>(this->desc()); }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual status_t query(query_t what, int idx, void *result) const override {
+ switch (what) {
+ case query::inner_product_d:
+ *(const inner_product_desc_t**)result = desc(); break;
+ default: return primitive_desc_t::query(what, idx, result);
+ }
+ return status::success;
+ }
+
+ /* common inner_product aux functions */
+
+ dim_t MB() const { return ip_prop_invariant_src_d(&desc_)->dims[0]; }
+ dim_t IC() const { return ip_prop_invariant_src_d(&desc_)->dims[1]; }
+ dim_t OC() const { return ip_prop_invariant_dst_d(&desc_)->dims[1]; }
+
+ dim_t ID() const {
+ return ndims() >= 5
+ ? ip_prop_invariant_src_d(&desc_)->dims[ndims() - 3] : 1;
+ }
+ dim_t IH() const {
+ return ndims() >= 4
+ ? ip_prop_invariant_src_d(&desc_)->dims[ndims() - 2] : 1;
+ }
+ dim_t IW() const {
+ return ndims() >= 3
+ ? ip_prop_invariant_src_d(&desc_)->dims[ndims() - 1] : 1;
+ }
+
+ dim_t OD() const {
+ return ndims() >= 5
+ ? ip_prop_invariant_dst_d(&desc_)->dims[ndims() - 3] : 1;
+ }
+ dim_t OH() const {
+ return ndims() >= 4
+ ? ip_prop_invariant_dst_d(&desc_)->dims[ndims() - 2] : 1;
+ }
+ dim_t OW() const {
+ return ndims() >= 3
+ ? ip_prop_invariant_dst_d(&desc_)->dims[ndims() - 1] : 1;
+ }
+
+ dim_t KD() const {
+ return ndims() >= 5
+ ? ip_prop_invariant_wei_d(&desc_)->dims[ndims() - 3] : 1;
+ }
+ dim_t KH() const {
+ return ndims() >= 4
+ ? ip_prop_invariant_wei_d(&desc_)->dims[ndims() - 2] : 1;
+ }
+ dim_t KW() const {
+ return ndims() >= 3
+ ? ip_prop_invariant_wei_d(&desc_)->dims[ndims() - 1] : 1;
+ }
+
+ dim_t IC_total() const {
+ return utils::array_product(&ip_prop_invariant_src_d(&desc_)->dims[1],
+ ndims() - 1);
+ }
+
+ dim_t IC_total_padded() const {
+ auto src_d = desc()->prop_kind == prop_kind::backward_data
+ ? memory_desc_wrapper(diff_src_md())
+ : memory_desc_wrapper(src_md());
+ assert(src_d.is_blocking_desc());
+ if (!src_d.is_blocking_desc()) return -1;
+ return utils::array_product(src_d.padded_dims() + 1, ndims() - 1);
+ }
+
+ int ndims() const { return ip_prop_invariant_src_d(&desc_)->ndims; }
+
+ bool with_bias() const
+ { return !memory_desc_wrapper(*ip_prop_invariant_bia_d(&desc_)).is_zero(); }
+
+ bool has_zero_dim_memory() const {
+ const auto s_d = memory_desc_wrapper(*ip_prop_invariant_src_d(&desc_));
+ const auto d_d = memory_desc_wrapper(*ip_prop_invariant_dst_d(&desc_));
+ return s_d.has_zero_dim() || d_d.has_zero_dim();
+ }
+
+ bool is_fwd() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ }
+
+protected:
+ inner_product_desc_t desc_;
+ const inner_product_fwd_pd_t *hint_fwd_pd_;
+
+ status_t template_set_default_params(memory_desc_t &src_md,
+ memory_desc_t &weights_md, memory_desc_t &dst_md,
+ memory_desc_t *bias_md) {
+ using namespace format_tag;
+ if (src_md.format_kind == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(src_md,
+ utils::pick(ndims() - 2, nc, ncw, nchw, ncdhw)));
+ }
+ if (dst_md.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(dst_md, nc));
+ if (weights_md.format_kind == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(weights_md,
+ utils::pick(ndims() - 2, oi, oiw, oihw, oidhw)));
+ }
+ if (bias_md && bias_md->format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(*bias_md, x));
+ return status::success;
+ }
+};
+
+struct inner_product_fwd_pd_t: public inner_product_pd_t {
+ typedef inner_product_fwd_pd_t base_class;
+ typedef inner_product_fwd_pd_t hint_class;
+
+ inner_product_fwd_pd_t(engine_t *engine,
+ const inner_product_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const inner_product_fwd_pd_t *hint_fwd_pd)
+ : inner_product_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , src_md_(desc_.src_desc)
+ , weights_md_(desc_.weights_desc)
+ , bias_md_(desc_.bias_desc)
+ , dst_md_(desc_.dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_WEIGHTS))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_BIAS && with_bias())
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &src_md_ : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &dst_md_ : nullptr; }
+ virtual const memory_desc_t *weights_md(int index = 0) const override {
+ if (index == 0) return &weights_md_;
+ if (index == 1 && with_bias()) return &bias_md_;
+ return nullptr;
+ }
+
+ virtual int n_inputs() const override { return 2 + with_bias(); }
+ virtual int n_outputs() const override { return 1; }
+
+protected:
+ memory_desc_t src_md_;
+ memory_desc_t weights_md_;
+ memory_desc_t bias_md_;
+ memory_desc_t dst_md_;
+
+ status_t set_default_params() {
+ return template_set_default_params(src_md_, weights_md_, dst_md_,
+ &bias_md_);
+ }
+};
+
+struct inner_product_bwd_data_pd_t: public inner_product_pd_t {
+ typedef inner_product_bwd_data_pd_t base_class;
+ typedef inner_product_fwd_pd_t hint_class;
+
+ inner_product_bwd_data_pd_t(engine_t *engine,
+ const inner_product_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const inner_product_fwd_pd_t *hint_fwd_pd)
+ : inner_product_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , diff_src_md_(desc_.diff_src_desc)
+ , weights_md_(desc_.weights_desc)
+ , diff_dst_md_(desc_.diff_dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_WEIGHTS, MKLDNN_ARG_DIFF_DST))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_SRC)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *diff_src_md(int index = 0) const override
+ { return index == 0 ? &diff_src_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_dst_md_ : nullptr; }
+ virtual const memory_desc_t *weights_md(int index = 0) const override
+ { return index == 0 ? &weights_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return 2; }
+ virtual int n_outputs() const override { return 1; }
+
+protected:
+ memory_desc_t diff_src_md_;
+ memory_desc_t weights_md_;
+ memory_desc_t diff_dst_md_;
+
+ status_t set_default_params() {
+ return template_set_default_params(diff_src_md_, weights_md_,
+ diff_dst_md_, nullptr);
+ }
+};
+
+struct inner_product_bwd_weights_pd_t: public inner_product_pd_t {
+ typedef inner_product_bwd_weights_pd_t base_class;
+ typedef inner_product_fwd_pd_t hint_class;
+
+ inner_product_bwd_weights_pd_t(engine_t *engine,
+ const inner_product_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const inner_product_fwd_pd_t *hint_fwd_pd)
+ : inner_product_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , src_md_(desc_.src_desc)
+ , diff_weights_md_(desc_.diff_weights_desc)
+ , diff_bias_md_(desc_.diff_bias_desc)
+ , diff_dst_md_(desc_.diff_dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_DIFF_DST))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_WEIGHTS)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_DIFF_BIAS && with_bias())
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &src_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_dst_md_ : nullptr; }
+ virtual const memory_desc_t *diff_weights_md(int index = 0) const override {
+ if (index == 0) return &diff_weights_md_;
+ if (index == 1 && with_bias()) return &diff_bias_md_;
+ return nullptr;
+ }
+
+ virtual int n_inputs() const override { return 2; }
+ virtual int n_outputs() const override { return 1 + with_bias(); }
+
+protected:
+ memory_desc_t src_md_;
+ memory_desc_t diff_weights_md_;
+ memory_desc_t diff_bias_md_;
+ memory_desc_t diff_dst_md_;
+
+ status_t set_default_params() {
+ return template_set_default_params(src_md_, diff_weights_md_,
+ diff_dst_md_, &diff_bias_md_);
+ }
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/lrn.cpp b/thirdparty/oidn/mkl-dnn/src/common/lrn.cpp
new file mode 100644
index 0000000000..fcf18b556f
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/lrn.cpp
@@ -0,0 +1,91 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::alg_kind;
+using namespace mkldnn::impl::types;
+
+namespace {
+status_t lrn_desc_init(lrn_desc_t *lrn_desc,
+ prop_kind_t prop_kind, alg_kind_t alg_kind,
+ const memory_desc_t *data_desc, const memory_desc_t *diff_data_desc,
+ dim_t local_size, float alpha, float beta, float k) {
+ bool args_ok = true
+ && !any_null(lrn_desc, data_desc)
+ && one_of(alg_kind, lrn_within_channel, lrn_across_channels)
+ && one_of(prop_kind, forward_training, forward_inference, backward_data)
+ && IMPLICATION(prop_kind == backward_data, diff_data_desc != nullptr);
+ if (!args_ok) return invalid_arguments;
+
+ auto ld = lrn_desc_t();
+ ld.primitive_kind = primitive_kind::lrn;
+ ld.prop_kind = prop_kind;
+ ld.alg_kind = alg_kind;
+
+ const bool is_fwd = one_of(prop_kind, forward_training, forward_inference);
+
+ ld.data_desc = *data_desc;
+ if (!is_fwd)
+ ld.diff_data_desc = *diff_data_desc;
+ else
+ ld.diff_data_desc = zero_md();
+ ld.local_size = local_size;
+ ld.lrn_alpha = alpha;
+ ld.lrn_beta = beta;
+ ld.lrn_k = k;
+
+ bool consistency = true
+ && ld.data_desc.ndims == 4;
+ if (ld.prop_kind == backward_data)
+ consistency = consistency
+ && ld.diff_data_desc.ndims == 4
+ && array_cmp(ld.diff_data_desc.dims, ld.data_desc.dims, 4);
+ if (!consistency) return invalid_arguments;
+
+ *lrn_desc = ld;
+ return success;
+}
+}
+
+status_t mkldnn_lrn_forward_desc_init(lrn_desc_t *lrn_desc,
+ prop_kind_t prop_kind, alg_kind_t alg_kind,
+ const memory_desc_t *data_desc, dim_t local_size, float alpha,
+ float beta, float k) {
+ if (!one_of(prop_kind, forward_training, forward_inference))
+ return invalid_arguments;
+ return lrn_desc_init(lrn_desc, prop_kind, alg_kind, data_desc, nullptr,
+ local_size, alpha, beta, k);
+}
+
+status_t mkldnn_lrn_backward_desc_init(lrn_desc_t *lrn_desc,
+ alg_kind_t alg_kind, const memory_desc_t *data_desc,
+ const memory_desc_t *diff_data_desc, dim_t local_size, float alpha,
+ float beta, float k) {
+ return lrn_desc_init(lrn_desc, backward_data, alg_kind, data_desc,
+ diff_data_desc, local_size, alpha, beta, k);
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/lrn_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/lrn_pd.hpp
new file mode 100644
index 0000000000..90886e9656
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/lrn_pd.hpp
@@ -0,0 +1,170 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef LRN_PD_HPP
+#define LRN_PD_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive_desc.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct lrn_fwd_pd_t;
+
+struct lrn_pd_t: public primitive_desc_t {
+ static constexpr auto base_pkind = primitive_kind::lrn;
+
+ lrn_pd_t(engine_t *engine,
+ const lrn_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const lrn_fwd_pd_t *hint_fwd_pd)
+ : primitive_desc_t(engine, attr, base_pkind)
+ , desc_(*adesc)
+ , hint_fwd_pd_(hint_fwd_pd)
+ , data_md_(desc_.data_desc)
+ , ws_md_()
+ {}
+
+ const lrn_desc_t *desc() const { return &desc_; }
+ virtual const op_desc_t *op_desc() const override
+ { return reinterpret_cast<const op_desc_t *>(this->desc()); }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual status_t query(query_t what, int idx, void *result) const override {
+ switch (what) {
+ case query::lrn_d:
+ *(const lrn_desc_t**)result = desc(); break;
+ default: return primitive_desc_t::query(what, idx, result);
+ }
+ return status::success;
+ }
+
+ /* common lrn aux functions */
+
+ dim_t MB() const { return data_desc().dims[0]; }
+ dim_t C() const { return data_desc().dims[1]; }
+ dim_t D() const { return ndims() >= 5 ? data_desc().dims[ndims() - 3] : 1; }
+ dim_t H() const { return ndims() >= 4 ? data_desc().dims[ndims() - 2] : 1; }
+ dim_t W() const { return ndims() >= 3 ? data_desc().dims[ndims() - 1] : 1; }
+
+ int ndims() const { return data_desc().ndims; }
+
+ bool has_zero_dim_memory() const
+ { return memory_desc_wrapper(desc_.data_desc).has_zero_dim(); }
+
+ bool is_fwd() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ }
+
+protected:
+ lrn_desc_t desc_;
+ const lrn_fwd_pd_t *hint_fwd_pd_;
+
+ memory_desc_t data_md_;
+ memory_desc_t ws_md_;
+
+private:
+ const memory_desc_t &data_desc() const { return desc_.data_desc; }
+};
+
+struct lrn_fwd_pd_t: public lrn_pd_t {
+ typedef lrn_fwd_pd_t base_class;
+ typedef lrn_fwd_pd_t hint_class;
+
+ lrn_fwd_pd_t(engine_t *engine,
+ const lrn_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const lrn_fwd_pd_t *hint_fwd_pd)
+ : lrn_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (arg == MKLDNN_ARG_SRC)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr))
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &data_md_ : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &data_md_ : nullptr; }
+ virtual const memory_desc_t *workspace_md(int index = 0) const override
+ { return index == 0 && !types::is_zero_md(&ws_md_) ? &ws_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return 1; }
+ virtual int n_outputs() const override
+ { return 1 + (workspace_md() != nullptr); }
+};
+
+struct lrn_bwd_pd_t: public lrn_pd_t {
+ typedef lrn_bwd_pd_t base_class;
+ typedef lrn_fwd_pd_t hint_class;
+
+ lrn_bwd_pd_t(engine_t *engine,
+ const lrn_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const lrn_fwd_pd_t *hint_fwd_pd)
+ : lrn_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , diff_data_md_(desc_.diff_data_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_SRC, MKLDNN_ARG_DIFF_DST))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_SRC)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr))
+ return arg_usage_t::input;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &data_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_data_md_ : nullptr; }
+ virtual const memory_desc_t *diff_src_md(int index = 0) const override
+ { return index == 0 ? &diff_data_md_ : nullptr; }
+ virtual const memory_desc_t *workspace_md(int index = 0) const override
+ { return index == 0 && !types::is_zero_md(&ws_md_) ? &ws_md_ : nullptr; }
+
+ virtual int n_inputs() const override
+ { return 2 + (workspace_md() != nullptr); }
+ virtual int n_outputs() const override { return 1; }
+
+protected:
+ memory_desc_t diff_data_md_;
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/math_utils.hpp b/thirdparty/oidn/mkl-dnn/src/common/math_utils.hpp
new file mode 100644
index 0000000000..3fddc0bd45
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/math_utils.hpp
@@ -0,0 +1,280 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MATH_UTILS_HPP
+#define MATH_UTILS_HPP
+
+#include <stdint.h>
+#include <math.h>
+
+#include "utils.hpp"
+#include "nstl.hpp"
+#include "mkldnn_traits.hpp"
+
+#if defined(MKLDNN_X86_64)
+#include "immintrin.h"
+#endif
+
+namespace mkldnn {
+namespace impl {
+namespace math {
+
+/** rounds @p f to an integer according to the mxcsr register */
+inline int mxcsr_round(float f) {
+#if defined(MKLDNN_X86_64)
+ return _mm_cvtss_si32(_mm_load_ss(&f));
+#else
+ return (int)nearbyintf(f); // optimism
+#endif
+}
+
+template <typename data_t, typename acc_t>
+inline typename utils::enable_if<!nstl::is_integral<data_t>::value,
+ typename utils::remove_reference<data_t>::type>::type
+saturate(const acc_t &x) {
+ return (typename utils::remove_reference<data_t>::type)x;
+}
+
+template <typename data_t, typename acc_t>
+inline typename utils::enable_if<nstl::is_integral<data_t>::value,
+ typename utils::remove_reference<data_t>::type>::type
+saturate(const acc_t &x) {
+ acc_t v = x;
+ if (v < (acc_t)nstl::numeric_limits<data_t>::lowest())
+ v = (acc_t)nstl::numeric_limits<data_t>::lowest();
+ if (v > (acc_t)nstl::numeric_limits<data_t>::max())
+ v = (acc_t)nstl::numeric_limits<data_t>::max();
+ return (typename utils::remove_reference<data_t>::type)v;
+}
+
+template <typename data_t>
+double saturate(const double &x) {
+ double v = x;
+ if (v < (double)nstl::numeric_limits<data_t>::lowest())
+ v = (double)nstl::numeric_limits<data_t>::lowest();
+ if (v > (double)nstl::numeric_limits<data_t>::max())
+ v = (double)nstl::numeric_limits<data_t>::max();
+ return v;
+}
+
+template <> inline int8_t saturate<int8_t, uint8_t>(const uint8_t &x) {
+ return x <= 127u ? x : 127;
+}
+
+template <> inline uint8_t saturate<uint8_t, int8_t>(const int8_t &x) {
+ return x >= 0 ? x : 0;
+}
+
+template <typename out_t>
+typename utils::enable_if<nstl::is_integral<out_t>::value, out_t>::type
+out_round(float v) { return (out_t)mxcsr_round(v); }
+
+template <typename out_t>
+typename utils::enable_if<nstl::is_integral<out_t>::value, out_t>::type
+out_round(double v) { return (out_t)mxcsr_round((float)v); }
+
+template <typename out_t>
+typename utils::enable_if<!nstl::is_integral<out_t>::value, out_t>::type
+out_round(float v) { return v; }
+
+inline int gcd(int a, int b) {
+ a = impl::nstl::abs(a);
+ b = impl::nstl::abs(b);
+ if (a < b) { int x = a; a = b; b = x; }
+
+ if (b == 0) return a;
+
+ int r;
+ while ((r = a % b) != 0) { a = b; b = r; }
+
+ return b;
+}
+
+template <typename T>
+inline bool is_pow2(const T& v) { return (v & (v - 1)) == 0; }
+
+/** returns floor(log2(v)), aka the position of the leftmost non-0 bit */
+inline int ilog2q(size_t v) {
+ if (v == 0)
+ return -1;
+
+ int p = 0;
+# define CP(pw) do { if (v >= (1ull << pw)) { v >>= pw; p += pw; } } while(0)
+ CP(32); CP(16); CP(8); CP(4); CP(2); CP(1);
+# undef CP
+ return p;
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U one_m_square(T x) {
+ return (U)(1 - x) * (1 + x);
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U x_m_square(T x) {
+ return (U)(1 - x) * x;
+}
+
+/* activation */
+template <typename T, typename A,
+ typename U = typename utils::remove_reference<T>::type>
+inline U relu_fwd(T s, A alpha) {
+ return s > 0 ? s : (U)(s * alpha);
+}
+template <typename T, typename A,
+ typename U = typename utils::remove_reference<T>::type>
+inline U relu_bwd(T dd, T s, A alpha) {
+ return s > 0 ? dd : (U)(dd * alpha);
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U tanh_fwd(T s) {
+ const float e = tanhf((float) s);
+ return (U)e;
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U tanh_bwd(T dd, T s) {
+ const float e = tanh_fwd<float>((float) s);
+ return (U)(dd * (1 - e) * (1 + e));
+}
+
+template <typename T, typename A,
+ typename U = typename utils::remove_reference<T>::type>
+inline U elu_fwd(T s, A alpha) {
+ return s > 0 ? s : (U)(alpha * (::expm1f((float)s)));
+}
+template <typename T, typename A,
+ typename U = typename utils::remove_reference<T>::type>
+ inline U elu_bwd(T dd, T s, A alpha) {
+ return (U)(dd * (s > 0 ? 1 : alpha * ::expf((float)s)));
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U square_fwd(T s) {
+ return s * s;
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U square_bwd(T dd, T s) {
+ return dd * 2 * s;
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U abs_fwd(T s) {
+ return s > 0 ? s : -s;
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U abs_bwd(T dd, T s) {
+ return s > 0 ? dd : s < 0 ? -dd : 0;
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U sqrt_fwd(T s) {
+ return s > 0 ? (U)(::sqrtf((float)(s))) : 0;
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U sqrt_bwd(T dd, T s) {
+ return s > 0
+ ? (U)(dd / (2 * ::sqrtf((float)(s))))
+ : 0;
+}
+
+template <typename T, typename A,
+ typename U = typename utils::remove_reference<T>::type>
+inline U linear_fwd(T s, A alpha, A beta) {
+ return (U)(alpha * s + beta);
+}
+
+template <typename T, typename A,
+ typename U = typename utils::remove_reference<T>::type>
+inline U linear_bwd(T dd, T s, A alpha, A beta) {
+ (void) s;
+ (void) beta;
+ return (U)(dd * alpha);
+}
+
+template <typename T, typename A,
+ typename U = typename utils::remove_reference<T>::type>
+inline U bounded_relu_fwd(T s, A alpha) {
+ s = s > 0 ? s : 0;
+ return s > alpha ? (U)(alpha) : s;
+}
+
+template <typename T, typename A,
+ typename U = typename utils::remove_reference<T>::type>
+inline U bounded_relu_bwd(T dd, T s, A alpha) {
+ return dd * (0 < s && s < alpha ? 1 : 0);
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U soft_relu_fwd(T s) {
+ float max_logf = 8.872284e+01; //::logf(FLT_MAX)
+ return s < max_logf ? (U)(::log1pf(::expf((float)s))) : s;
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U soft_relu_bwd(T dd, T s) {
+ return (U)(dd / (1 + ::expf((float)(-s))));
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U logistic_fwd(T s) {
+ U v = (U)(::expf((float) -s));
+ return 1 / (1 + v);
+}
+
+template <typename T, typename U = typename utils::remove_reference<T>::type>
+inline U logistic_bwd(T dd, T s) {
+ U v = logistic_fwd<T, U>(s);
+ return dd * v * (1 - v);
+}
+
+inline bool eltwise_fwd_preserves_zero(alg_kind_t alg, bool jit_impl = false) {
+ using namespace alg_kind;
+ using namespace utils;
+ const bool preserves_zero = true
+ && !one_of(alg, eltwise_linear, eltwise_soft_relu, eltwise_logistic)
+ && IMPLICATION(jit_impl, !one_of(alg, eltwise_elu, eltwise_tanh));
+ return preserves_zero;
+}
+
+inline float get_bias(const char *bias, size_t offset, data_type_t data_type)
+{
+ if (!bias)
+ return 0.0f;
+
+#define CASE(dt) \
+ case dt: return (float)((const prec_traits<dt>::type *)bias)[offset]
+
+ switch (data_type) {
+ CASE(data_type::s8);
+ CASE(data_type::u8);
+ CASE(data_type::s32);
+ CASE(data_type::f32);
+ default: assert(!"unimplemented");
+ }
+ return 0; // never happens (should probably be a NaN)
+#undef CASE
+}
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/memory.cpp b/thirdparty/oidn/mkl-dnn/src/common/memory.cpp
new file mode 100644
index 0000000000..cea849c96e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/memory.cpp
@@ -0,0 +1,238 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "engine.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::data_type;
+
+namespace {
+bool memory_desc_sanity_check(int ndims,const dims_t dims,
+ data_type_t data_type, format_kind_t format_kind) {
+ if (ndims == 0) return true;
+
+ bool ok = true
+ && dims != nullptr
+ && 0 < ndims && ndims <= MKLDNN_MAX_NDIMS
+ && one_of(data_type, f32, s32, s8, u8)
+ && format_kind != format_kind::undef;
+ if (!ok) return false;
+ for (int d = 0; d < ndims; ++d)
+ if (dims[d] < 0) return false;
+
+ return true;
+}
+
+bool memory_desc_sanity_check(const memory_desc_t *md) {
+ if (md == nullptr) return false;
+ return memory_desc_sanity_check(md->ndims, md->dims, md->data_type,
+ format_kind::any);
+}
+}
+
+status_t mkldnn_memory_desc_init_by_tag(memory_desc_t *memory_desc, int ndims,
+ const dims_t dims, data_type_t data_type, format_tag_t tag) {
+ if (any_null(memory_desc)) return invalid_arguments;
+ if (ndims == 0 || tag == format_tag::undef) {
+ *memory_desc = types::zero_md();
+ return success;
+ }
+
+ format_kind_t format_kind = types::format_tag_to_kind(tag);
+
+ /* memory_desc != 0 */
+ bool args_ok = !any_null(memory_desc)
+ && memory_desc_sanity_check(ndims, dims, data_type, format_kind);
+ if (!args_ok) return invalid_arguments;
+
+ auto md = memory_desc_t();
+ md.ndims = ndims;
+ array_copy(md.dims, dims, ndims);
+ md.data_type = data_type;
+ array_copy(md.padded_dims, dims, ndims);
+ md.format_kind = format_kind;
+
+ status_t status = success;
+ if (tag == format_tag::undef) {
+ status = invalid_arguments;
+ } else if (tag == format_tag::any) {
+ // nop
+ } else if (format_kind == format_kind::blocked) {
+ status = memory_desc_wrapper::compute_blocking(md, tag);
+ } else {
+ assert(!"unreachable");
+ status = invalid_arguments;
+ }
+
+ if (status == success)
+ *memory_desc = md;
+
+ return status;
+}
+
+status_t mkldnn_memory_desc_init_by_strides(memory_desc_t *memory_desc,
+ int ndims, const dims_t dims, data_type_t data_type,
+ const dims_t strides) {
+ if (any_null(memory_desc)) return invalid_arguments;
+ if (ndims == 0) {
+ *memory_desc = types::zero_md();
+ return success;
+ }
+
+ /* memory_desc != 0 */
+ bool args_ok = !any_null(memory_desc)
+ && memory_desc_sanity_check(ndims, dims, data_type, format_kind::any);
+ if (!args_ok) return invalid_arguments;
+
+ auto md = memory_desc_t();
+ md.ndims = ndims;
+ array_copy(md.dims, dims, ndims);
+ md.data_type = data_type;
+ array_copy(md.padded_dims, dims, ndims);
+ md.format_kind = format_kind::blocked;
+
+ dims_t default_strides = {0};
+ if (strides == nullptr) {
+ default_strides[md.ndims - 1] = 1;
+ for (int d = md.ndims - 2; d >= 0; --d)
+ default_strides[d] = default_strides[d + 1] * md.padded_dims[d + 1];
+ strides = default_strides;
+ } else {
+ /* TODO: add sanity check for the provided strides */
+ }
+
+ array_copy(md.format_desc.blocking.strides, strides, md.ndims);
+
+ *memory_desc = md;
+
+ return status::success;
+}
+
+status_t mkldnn_memory_desc_init_submemory(memory_desc_t *md,
+ const memory_desc_t *parent_md, const dims_t dims,
+ const dims_t offsets) {
+ if (any_null(md, parent_md) || !memory_desc_sanity_check(parent_md))
+ return invalid_arguments;
+
+ const memory_desc_wrapper src_d(parent_md);
+
+ for (int d = 0; d < src_d.ndims(); ++d) {
+ if (dims[d] < 0 || offsets[d] < 0
+ || (offsets[d] + dims[d] > src_d.dims()[d]))
+ return invalid_arguments;
+ }
+
+ if (src_d.format_kind() != format_kind::blocked)
+ return unimplemented;
+
+ dims_t blocks;
+ src_d.compute_blocks(blocks);
+
+ memory_desc_t dst_d = *parent_md;
+ auto &dst_d_blk = dst_d.format_desc.blocking;
+
+ /* TODO: put this into memory_desc_wrapper */
+ for (int d = 0; d < src_d.ndims(); ++d) {
+ /* very limited functionality for now */
+ const bool ok = true
+ && offsets[d] % blocks[d] == 0 /* [r1] */
+ && src_d.padded_offsets()[d] == 0
+ && (false
+ || dims[d] % blocks[d] == 0
+ || dims[d] < blocks[d]);
+ if (!ok)
+ return unimplemented;
+
+ const bool is_right_border = offsets[d] + dims[d] == src_d.dims()[d];
+
+ dst_d.dims[d] = dims[d];
+ dst_d.padded_dims[d] = is_right_border
+ ? src_d.padded_dims()[d] - offsets[d] : dst_d.dims[d];
+ dst_d.padded_offsets[d] = src_d.padded_offsets()[d];
+ dst_d.offset0 += /* [r1] */
+ offsets[d] / blocks[d] * dst_d_blk.strides[d];
+ }
+
+ *md = dst_d;
+
+ return success;
+}
+
+int mkldnn_memory_desc_equal(const memory_desc_t *lhs,
+ const memory_desc_t *rhs) {
+ if (lhs == rhs) return 1;
+ if (any_null(lhs, rhs)) return 0;
+ return memory_desc_wrapper(*lhs) == memory_desc_wrapper(*rhs);
+}
+
+size_t mkldnn_memory_desc_get_size(const memory_desc_t *md) {
+ if (md == nullptr) return 0;
+ return memory_desc_wrapper(*md).size();
+}
+
+status_t mkldnn_memory_create(memory_t **memory, const memory_desc_t *md,
+ engine_t *engine, void *handle) {
+ if (any_null(memory, engine)) return invalid_arguments;
+ memory_desc_t z_md = types::zero_md();
+ return engine->memory_create(memory, md ? md : &z_md, handle);
+}
+
+status_t mkldnn_memory_get_memory_desc(const memory_t *memory,
+ const memory_desc_t **md) {
+ if (any_null(memory, md)) return invalid_arguments;
+ *md = memory->md();
+ return success;
+}
+
+status_t mkldnn_memory_get_engine(const memory_t *memory, engine_t **engine) {
+ if (any_null(memory, engine)) return invalid_arguments;
+ *engine = memory->engine();
+ return success;
+}
+
+status_t mkldnn_memory_get_data_handle(const memory_t *memory,
+ void **handle) {
+ if (any_null(handle))
+ return invalid_arguments;
+ if (memory == nullptr) {
+ *handle = nullptr;
+ return success;
+ }
+ return memory->get_data_handle(handle);
+}
+
+status_t mkldnn_memory_set_data_handle(memory_t *memory, void *handle) {
+ if (any_null(memory)) return invalid_arguments;
+ return memory->set_data_handle(handle);
+}
+
+status_t mkldnn_memory_destroy(memory_t *memory) {
+ delete memory;
+ return success;
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/memory.hpp b/thirdparty/oidn/mkl-dnn/src/common/memory.hpp
new file mode 100644
index 0000000000..03dfee01ff
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/memory.hpp
@@ -0,0 +1,63 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MEMORY_HPP
+#define MEMORY_HPP
+
+#include <assert.h>
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+
+struct mkldnn_memory: public mkldnn::impl::c_compatible {
+ mkldnn_memory(mkldnn::impl::engine_t *engine,
+ const mkldnn::impl::memory_desc_t *md)
+ : engine_(engine), md_(*md) {}
+ virtual ~mkldnn_memory() {}
+
+ /** allocates/initializes memory */
+ virtual mkldnn::impl::status_t init() = 0;
+
+ /** returns memory's engine */
+ mkldnn::impl::engine_t *engine() const { return engine_; }
+ /** returns memory's description */
+ const mkldnn::impl::memory_desc_t *md() const { return &md_; }
+
+ /** returns data handle */
+ virtual mkldnn::impl::status_t get_data_handle(void **handle) const = 0;
+
+ /** sets data handle */
+ virtual mkldnn::impl::status_t set_data_handle(void *handle) = 0;
+
+ /** zeros padding */
+ virtual mkldnn::impl::status_t zero_pad() const
+ { return mkldnn::impl::status::success; }
+
+protected:
+ mkldnn::impl::engine_t *engine_;
+ const mkldnn::impl::memory_desc_t md_;
+
+private:
+ mkldnn_memory() = delete;
+ mkldnn_memory(const mkldnn_memory &) = delete;
+ mkldnn_memory(mkldnn_memory &&) = delete;
+ mkldnn_memory &operator=(const mkldnn_memory &) = delete;
+ mkldnn_memory &operator=(mkldnn_memory &&) = delete;
+};
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.cpp b/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.cpp
new file mode 100644
index 0000000000..8a99be33f3
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.cpp
@@ -0,0 +1,212 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include <initializer_list>
+
+#include "c_types_map.hpp"
+#include "memory_desc_wrapper.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+status_t fill_blocked(memory_desc_t &md,
+ std::initializer_list<int> perm,
+ std::initializer_list<int> inner_blks,
+ std::initializer_list<int> inner_idxs) {
+ const bool ok = true
+ && perm.size() == (size_t)md.ndims
+ && inner_blks.size() == inner_idxs.size();
+ if (!ok) return status::invalid_arguments;
+
+ md.offset0 = 0;
+
+ blocking_desc_t &blk = md.format_desc.blocking;
+
+ dim_t block_size = 1;
+ dims_t blocks = {0};
+ utils::array_set(blocks, 1, md.ndims);
+
+ blk.inner_nblks = (int)inner_blks.size();
+
+ int iblk = 0;
+ for (const auto &b: inner_idxs)
+ blk.inner_idxs[iblk++] = b;
+
+ iblk = 0;
+ for (const auto &b: inner_blks) {
+ int dim = blk.inner_idxs[iblk];
+ block_size *= b;
+ blocks[dim] *= b;
+ blk.inner_blks[iblk++] = b;
+ }
+
+ utils::array_set(md.padded_offsets, 0, md.ndims);
+ for (int d = 0; d < md.ndims; ++d)
+ md.padded_dims[d] = utils::rnd_up(md.dims[d], blocks[d]);
+
+ dim_t stride = block_size;
+ // if only we use C++14, the initializer_list would have rbegin()/rend()...
+ for (int d = 0; d < md.ndims; ++d)
+ stride *= md.padded_dims[d] == 0 ? 1 : md.padded_dims[d] / blocks[d];
+
+ for (const auto &d: perm) {
+ if (md.padded_dims[d] == 0) {
+ blk.strides[d] = 1;
+ continue;
+ }
+ stride /= md.padded_dims[d] / blocks[d];
+ blk.strides[d] = stride;
+ }
+
+ assert(stride == block_size);
+
+ return status::success;
+}
+
+status_t memory_desc_wrapper::compute_blocking(memory_desc_t &memory_desc,
+ format_tag_t tag)
+{
+ using namespace format_tag;
+
+ if (memory_desc.ndims == 0) return status::invalid_arguments;
+
+# define C(tag, ... /* perm, inner_blks, inner_idxs */) \
+ case tag: return fill_blocked(memory_desc, __VA_ARGS__)
+
+ switch (tag) {
+ C(a, {0}, {}, {});
+ C(ab, {0, 1}, {}, {});
+ C(abc, {0, 1, 2}, {}, {});
+ C(abcd, {0, 1, 2, 3}, {}, {});
+ C(abcde, {0, 1, 2, 3, 4}, {}, {});
+ C(abcdef, {0, 1, 2, 3, 4, 5}, {}, {});
+ C(abdec, {0, 1, 3, 4, 2}, {}, {});
+ C(acb, {0, 2, 1}, {}, {});
+ C(acbde, {0, 2, 1, 3, 4}, {}, {});
+ C(acdb, {0, 2, 3, 1}, {}, {});
+ C(acdeb, {0, 2, 3, 4, 1}, {}, {});
+ C(ba, {1, 0}, {}, {});
+ C(bac, {1, 0, 2}, {}, {});
+ C(bacd, {1, 0, 2, 3}, {}, {});
+ C(bcda, {1, 2, 3, 0}, {}, {});
+ C(cba, {2, 1, 0}, {}, {});
+ C(cdba, {2, 3, 1, 0}, {}, {});
+ C(cdeba, {2, 3, 4, 1, 0}, {}, {});
+ C(decab, {3, 4, 2, 0, 1}, {}, {});
+
+ C(Abc4a, {0, 1, 2}, {4}, {0});
+ C(aBc4b, {0, 1, 2}, {4}, {1});
+ C(ABc4b16a4b, {0, 1, 2}, {4, 16, 4}, {1, 0, 1});
+ C(ABc4b4a, {0, 1, 2}, {4, 4}, {1, 0});
+ C(Abcd4a, {0, 1, 2, 3}, {4}, {0});
+ C(aBcd4b, {0, 1, 2, 3}, {4}, {1});
+ C(ABcd4b4a, {0, 1, 2, 3}, {4, 4}, {1, 0});
+ C(aBCd4c16b4c, {0, 1, 2, 3}, {4, 16, 4}, {2, 1, 2});
+ C(aBCd4c4b, {0, 1, 2, 3, 4}, {4, 4}, {2, 1});
+ C(Abcde4a, {0, 1, 2, 3, 4}, {4}, {0});
+ C(aBcde4b, {0, 1, 2, 3, 4}, {4}, {1});
+ C(ABcde4b4a, {0, 1, 2, 3, 4}, {4, 4}, {1, 0});
+ C(aBCde4c4b, {0, 1, 2, 3, 4}, {4, 4}, {2, 1});
+ C(aBcdef4b, {0, 1, 2, 3, 4, 5}, {4}, {1});
+ C(aBCdef4c4b, {0, 1, 2, 3, 4, 5}, {4, 4}, {2, 1});
+ C(aBdc4b, {0, 1, 3, 2}, {4}, {1});
+ C(aBdec4b, {0, 1, 3, 4, 2}, {4}, {1});
+ C(aBdefc4b, {0, 1, 3, 4, 5, 2}, {4}, {1});
+ C(Acb4a, {0, 2, 1}, {4}, {0});
+ C(Acdb4a, {0, 2, 3, 1}, {4}, {0});
+ C(Acdeb4a, {0, 2, 3, 4, 1}, {4}, {0});
+
+ C(Abc16a, {0, 1, 2}, {16}, {0});
+ C(ABc16a16b, {0, 1, 2}, {16, 16}, {0, 1});
+ C(aBc16b, {0, 1, 2}, {16}, {1});
+ C(ABc16b16a, {0, 1, 2}, {16, 16}, {1, 0});
+ C(ABc8a16b2a, {0, 1, 2}, {8, 16, 2}, {0, 1, 0});
+ C(ABc8a8b, {0, 1, 2}, {8, 8}, {0, 1});
+ C(aBc8b, {0, 1, 2}, {8}, {1});
+ C(ABc8b16a2b, {0, 1, 2}, {8, 16, 2}, {1, 0, 1});
+ C(ABc8b8a, {0, 1, 2}, {8, 8}, {1, 0});
+ C(Abcd16a, {0, 1, 2, 3}, {16}, {0});
+ C(ABcd16a16b, {0, 1, 2, 3}, {16, 16}, {0, 1});
+ C(aBcd16b, {0, 1, 2, 3}, {16}, {1});
+ C(ABcd16b16a, {0, 1, 2, 3}, {16, 16}, {1, 0});
+ C(aBCd16b16c, {0, 1, 2, 3}, {16, 16}, {1, 2});
+ C(aBCd16c16b, {0, 1, 2, 3}, {16, 16}, {2, 1});
+ C(ABcd4b16a4b, {0, 1, 2, 3}, {4, 16, 4}, {1, 0, 1});
+ C(ABcd8a16b2a, {0, 1, 2, 3}, {8, 16, 2}, {0, 1, 0});
+ C(ABcd8a8b, {0, 1, 2, 3}, {8, 8}, {0, 1});
+ C(aBcd8b, {0, 1, 2, 3}, {8}, {1});
+ C(ABcd8b16a2b, {0, 1, 2, 3}, {8, 16, 2}, {1, 0, 1});
+ C(aBCd8b16c2b, {0, 1, 2, 3}, {8, 16, 2}, {1, 2, 1});
+ C(ABcd8b8a, {0, 1, 2, 3}, {8, 8}, {1, 0});
+ C(aBCd8b8c, {0, 1, 2, 3}, {8, 8}, {1, 2});
+ C(aBCd8c16b2c, {0, 1, 2, 3}, {8, 16, 2}, {2, 1, 2});
+ C(aBCd8c8b, {0, 1, 2, 3}, {8, 8}, {2, 1});
+ C(Abcde16a, {0, 1, 2, 3, 4}, {16}, {0});
+ C(ABcde16a16b, {0, 1, 2, 3, 4}, {16, 16}, {0, 1});
+ C(aBcde16b, {0, 1, 2, 3, 4}, {16}, {1});
+ C(ABcde16b16a, {0, 1, 2, 3, 4}, {16, 16}, {1, 0});
+ C(aBCde16b16c, {0, 1, 2, 3, 4}, {16, 16}, {1, 2});
+ C(aBCde16c16b, {0, 1, 2, 3, 4}, {16, 16}, {2, 1});
+ C(aBCde2c8b4c, {0, 1, 2, 3, 4}, {2, 8, 4}, {2, 1, 2});
+ C(aBCde4b4c, {0, 1, 2, 3, 4}, {4, 4}, {1, 2});
+ C(aBCde4c16b4c, {0, 1, 2, 3, 4}, {4, 16, 4}, {2, 1, 2});
+ C(Abcde8a, {0, 1, 2, 3, 4}, {8}, {0});
+ C(ABcde8a8b, {0, 1, 2, 3, 4}, {8, 8}, {0, 1});
+ C(aBcde8b, {0, 1, 2, 3, 4}, {8}, {1});
+ C(ABcde8b16a2b, {0, 1, 2, 3, 4}, {8, 16, 2}, {1, 0, 1});
+ C(aBCde8b16c2b, {0, 1, 2, 3, 4}, {8, 16, 2}, {1, 2, 1});
+ C(ABcde8b8a, {0, 1, 2, 3, 4}, {8, 8}, {1, 0});
+ C(aBCde8b8c, {0, 1, 2, 3, 4}, {8, 8}, {1, 2});
+ C(aBCde8c16b2c, {0, 1, 2, 3, 4}, {8, 16, 2}, {2, 1, 2});
+ C(aBCde8c8b, {0, 1, 2, 3, 4}, {8, 8}, {2, 1});
+ C(aBcdef16b, {0, 1, 2, 3, 4, 5}, {16}, {1});
+ C(aBCdef16b16c, {0, 1, 2, 3, 4, 5}, {16, 16}, {1, 2});
+ C(aBCdef16c16b, {0, 1, 2, 3, 4, 5}, {16, 16}, {2, 1});
+ C(aBCdef8b8c, {0, 1, 2, 3, 4, 5}, {8, 8}, {1, 2});
+ C(aBCdef8c16b2c, {0, 1, 2, 3, 4, 5}, {8, 16, 2}, {2, 1, 2});
+ C(aBCdef8c8b, {0, 1, 2, 3, 4, 5}, {8, 8}, {2, 1});
+ C(aBdc16b, {0, 1, 3, 2}, {16}, {1});
+ C(aBdc8b, {0, 1, 3, 2}, {8}, {1});
+ C(aBdec16b, {0, 1, 3, 4, 2}, {16}, {1});
+ C(aBdec8b, {0, 1, 3, 4, 2}, {8}, {1});
+ C(aBdefc16b, {0, 1, 3, 4, 5, 2}, {16}, {1});
+ C(aBdefc8b, {0, 1, 3, 4, 5, 2}, {8}, {1});
+ C(Acb16a, {0, 2, 1}, {16}, {0});
+ C(Acb8a, {0, 2, 1}, {8}, {0});
+ C(aCBd16b16c, {0, 2, 1, 3}, {16, 16}, {1, 2});
+ C(aCBde16b16c, {0, 2, 1, 3, 4}, {16, 16}, {1, 2});
+ C(Acdb16a, {0, 2, 3, 1}, {16}, {0});
+ C(Acdb8a, {0, 2, 3, 1}, {8}, {0});
+ C(Acdeb16a, {0, 2, 3, 4, 1}, {16}, {0});
+ C(Acdeb8a, {0, 2, 3, 4, 1}, {8}, {0});
+ C(BAc16a16b, {1, 0, 2}, {16, 16}, {0, 1});
+ C(BAcd16a16b, {1, 0, 2, 3}, {16, 16}, {0, 1});
+ default: break;
+ }
+
+#undef C
+
+ return status::invalid_arguments;
+}
+
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.hpp b/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.hpp
new file mode 100644
index 0000000000..1758f9078a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/memory_desc_wrapper.hpp
@@ -0,0 +1,400 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MEMORY_DESC_WRAPPER_HPP
+#define MEMORY_DESC_WRAPPER_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "utils.hpp"
+
+#include "type_helpers.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+/** thin wrapper class over \struct memory_desc_t which allows easy
+ * manipulations with underlying C structure, which is taken by reference */
+struct memory_desc_wrapper: public c_compatible {
+ const memory_desc_t *md_;
+
+ /** constructor which takes a reference to a constant underlying C memory
+ * descriptor \param md */
+ memory_desc_wrapper(const memory_desc_t *md): md_(md) {}
+ memory_desc_wrapper(const memory_desc_t &md): memory_desc_wrapper(&md) {}
+
+ /* implementing attributes */
+ int ndims() const { return md_->ndims; }
+ const dims_t &dims() const { return md_->dims; }
+ data_type_t data_type() const { return md_->data_type; }
+
+ const dims_t &padded_dims() const { return md_->padded_dims; }
+ const dims_t &padded_offsets() const { return md_->padded_offsets; }
+ dim_t offset0() const { return md_->offset0; }
+
+ format_kind_t format_kind() const { return md_->format_kind; }
+
+ bool is_blocking_desc() const
+ { return format_kind() == format_kind::blocked; }
+ bool is_wino_desc() const
+ { return format_kind() == format_kind::wino; }
+ bool is_rnn_packed_desc() const
+ { return format_kind() == format_kind::rnn_packed; }
+
+ const blocking_desc_t &blocking_desc() const {
+ assert(is_blocking_desc());
+ return md_->format_desc.blocking;
+ }
+ const wino_desc_t &wino_desc() const {
+ assert(is_wino_desc());
+ return md_->format_desc.wino_desc;
+ }
+ const rnn_packed_desc_t &rnn_packed_desc() const {
+ assert(is_rnn_packed_desc());
+ return md_->format_desc.rnn_packed_desc;
+ }
+
+ const memory_extra_desc_t &extra() const { return md_->extra; }
+
+ /* some useful function */
+
+ /** returns the number of elements including padding if \param with_padding
+ * is true, and the number of data elements otherwise */
+ dim_t nelems(bool with_padding = false) const {
+ if (is_zero()) return 0;
+ return utils::array_product(
+ with_padding ? padded_dims() : dims(), ndims());
+ }
+
+ /** returns true if memory descriptor is zero */
+ bool is_zero() const { return ndims() == 0; }
+
+ /** returns true if memory descriptor contains zero as one of its dim */
+ bool has_zero_dim() const { return nelems() == 0; }
+
+ /** return the size of data type (a shortcut) */
+ size_t data_type_size() const
+ { return types::data_type_size(data_type()); }
+
+ /** return the size of data type of additional buffer */
+ size_t additional_buffer_data_size() const {
+ if (extra().flags & memory_extra_flags::compensation_conv_s8s8)
+ return sizeof(int32_t);
+ return 0;
+ }
+
+ /** return true if memory format has additional buffer */
+ bool is_additional_buffer() const {
+ return (extra().flags & memory_extra_flags::compensation_conv_s8s8);
+ }
+
+ /** returns the size of additional buffer */
+ size_t additional_buffer_size() const {
+ if (extra().flags & memory_extra_flags::compensation_conv_s8s8) {
+ int cmask = extra().compensation_mask;
+ assert(cmask == 1 || cmask == 3);
+ dim_t prod = 1;
+ for (int d = 0; d < ndims(); ++d)
+ if (cmask & (1<<d)) prod *= padded_dims()[d];
+ return prod * additional_buffer_data_size();
+ }
+
+ return 0;
+ }
+
+ /** returns the size required to store described memory
+ * note: if offset0 != 0 returns 0 (need to specify the behavior) */
+ size_t size() const {
+ if (is_zero() || has_zero_dim() || format_kind() == format_kind::any)
+ return 0;
+
+ if (format_kind() == format_kind::wino) {
+ return wino_desc().size;
+ } else if (format_kind() == format_kind::rnn_packed) {
+ return rnn_packed_desc().size;
+ } else {
+ if (offset0() != 0) return 0;
+
+ dims_t blocks = {0};
+ compute_blocks(blocks);
+
+ const auto &bd = blocking_desc();
+
+ size_t max_size = 0;
+ for (int d = 0; d < ndims(); ++d)
+ max_size = nstl::max<size_t>(max_size,
+ padded_dims()[d] / blocks[d] * bd.strides[d]);
+
+ if (max_size == 1 && bd.inner_nblks != 0) {
+ max_size = utils::array_product(bd.inner_blks, bd.inner_nblks);
+ }
+
+ return max_size * data_type_size() + additional_buffer_size();
+ }
+ }
+
+ /** returns true if data is dense in memory */
+ bool is_dense(bool with_padding = false) const {
+ if (utils::one_of(format_kind(), format_kind::undef, format_kind::any))
+ return false;
+ return nelems(with_padding) * data_type_size() == size();
+ }
+
+ /** returns true if memory desc is fully defined */
+ bool is_defined() const { return format_kind() != format_kind::any; }
+
+ /** returns true if the only (potentially) padded dim is \param dim */
+ bool only_padded_dim(int dim) const {
+ for (int d = 0; d < ndims(); ++d)
+ if (d != dim && dims()[d] != padded_dims()[d])
+ return false;
+ return true;
+ }
+
+ /** returns true if memory desc has blocked layout and block dims are 1s */
+ bool is_plain() const {
+ if (!is_blocking_desc()) return false;
+ return blocking_desc().inner_nblks == 0;
+ }
+
+ /** returns overall block sizes */
+ void compute_blocks(dims_t blocks) const {
+ if (!is_blocking_desc()) {
+ utils::array_set(blocks, 0, ndims());
+ return;
+ }
+
+ utils::array_set(blocks, 1, ndims());
+
+ const auto &bd = blocking_desc();
+ for (int iblk = 0; iblk < bd.inner_nblks; ++iblk)
+ blocks[bd.inner_idxs[iblk]] *= bd.inner_blks[iblk];
+ }
+
+ /* comparison section */
+
+ bool operator==(const memory_desc_wrapper &rhs) const
+ { return *this->md_ == *rhs.md_; }
+ bool operator!=(const memory_desc_wrapper &rhs) const
+ { return !operator==(rhs); }
+ bool operator==(const memory_desc_t &rhs) const
+ { return operator==(memory_desc_wrapper(rhs)); }
+ bool operator!=(const memory_desc_t &rhs) const
+ { return !operator==(rhs); }
+
+ /** returns true if data (w/o padding if with_padding == false and w/
+ * padding otherwise) have the same physical structure, i.e. dimensions,
+ * strides, and blocked structure. Depending on with_data_type flag
+ * data_type is taken or not taken into account. dim_start allows to check
+ * similarity for the logical part of data [dim_start .. ndims()].
+ * CAUTION: format kind any and undef are not similar to whatever, hence the
+ * following statement might be true: lhs == rhs && !lhs.similar_to(rhs) */
+ /* TODO: revise */
+ bool similar_to(const memory_desc_wrapper &rhs,
+ bool with_padding = true, bool with_data_type = true,
+ int dim_start = 0) const;
+
+ /** returns true if one memory can be reordered to another */
+ bool consistent_with(const memory_desc_wrapper &rhs) const;
+
+ /** returns true if the memory desc corresponds to the given format tag and
+ * strides.
+ * @sa memory_desc_matches_tag */
+ bool matches_tag(format_tag_t tag, const dims_t strides = nullptr) const {
+ return memory_desc_matches_tag(*md_, tag, strides);
+ }
+
+ /** returns matching tag (or undef if match is not found)
+ * XXX: This is a workaround that eventually should go away! */
+ template <typename... Tags>
+ format_tag_t matches_one_of_tag(Tags ...tags) const {
+ for (const auto tag: {tags...}) {
+ if (memory_desc_matches_tag(*md_, tag))
+ return tag;
+ }
+ return format_tag::undef;
+ }
+
+ /* offset section */
+
+ /** returns physical offset by logical one. logical offset is represented by
+ * an array \param pos. if \param is_pos_padded is true \param pos
+ * represents the position in already padded area */
+ dim_t off_v(const dims_t pos, bool is_pos_padded = false) const {
+ assert(is_blocking_desc());
+ const blocking_desc_t &blk = blocking_desc();
+
+ dims_t pos_copy = {0};
+ for (int d = 0; d < ndims(); ++d)
+ pos_copy[d] = pos[d] + (is_pos_padded ? 0 : padded_offsets()[d]);
+
+ dim_t phys_offset = offset0();
+
+ if (blk.inner_nblks > 0) {
+ dim_t blk_stride = 1;
+ for (int iblk = blk.inner_nblks - 1; iblk >= 0; --iblk) {
+ const int d = blk.inner_idxs[iblk];
+ const dim_t p = pos_copy[d] % blk.inner_blks[iblk];
+
+ phys_offset += p * blk_stride;
+
+ pos_copy[d] /= blk.inner_blks[iblk];
+
+ blk_stride *= blk.inner_blks[iblk];
+ }
+ }
+
+ for (int d = 0; d < ndims(); ++d) {
+ const dim_t p = pos_copy[d];
+ phys_offset += p * blk.strides[d];
+ }
+
+ return phys_offset;
+ }
+
+ /** returns physical offset by logical one. logical offset is represented by
+ * a scalar \param l_offset. if \param is_pos_padded is true, \param
+ * l_offset represents logical offset in already padded area */
+ dim_t off_l(dim_t l_offset, bool is_pos_padded = false) const {
+ assert(is_blocking_desc());
+ dims_t pos;
+ for (int rd = 0; rd < ndims(); ++rd) {
+ const int d = ndims() - 1 - rd;
+ const dim_t cur_dim = is_pos_padded ? padded_dims()[d] : dims()[d];
+ pos[d] = l_offset % cur_dim;
+ l_offset /= cur_dim;
+ }
+ return off_v(pos, is_pos_padded);
+ }
+
+ /** returns physical offset by logical one. logical offset is represented by
+ * a tuple of indices (\param xn, ..., \param x1, \param x0) */
+ template<typename... Args>
+ dim_t off(Args... args) const {
+ assert(sizeof...(args) == ndims());
+ dims_t pos = { args... };
+ return off_v(pos, false);
+ }
+
+ /** returns physical offset by logical one. logical offset is represented by
+ * a tuple of indices (\param xn, ..., \param x1, \param x0) in already
+ * padded area */
+ template<typename... Args>
+ dim_t off_padding(Args... args) const {
+ assert(sizeof...(args) == ndims());
+ dims_t pos = { args... };
+ return off_v(pos, true);
+ }
+
+ /** returns physical offset by logical one. Logical offset is represented by
+ * a tuple of block indices (\param bn, ..., \param b1, \param b0). It is a
+ * user responsibility to adjust the result to get offset within blocks */
+ template<typename ...Args>
+ dim_t blk_off(Args... args) const {
+ return _blk_off<sizeof...(args), Args...>(args...);
+ }
+
+ template<bool skip_first, typename T, typename ...Args>
+ dim_t blk_off(T xn, Args... args) const {
+ return skip_first
+ ? blk_off<Args...>(args...)
+ : blk_off<T, Args...>(xn, args...);
+ }
+
+ /* static functions section */
+ /* TODO: replace with non-static, once md_ becomes non-const ref */
+
+ static status_t compute_blocking(memory_desc_t &memory_desc,
+ format_tag_t tag);
+
+private:
+ /* TODO: put logical_offset in utils */
+ template<typename T>
+ dim_t logical_offset(T x0) const { return x0; }
+
+ template<typename T, typename... Args>
+ dim_t logical_offset(T xn, Args... args) const {
+ const size_t n_args = sizeof...(args);
+ return xn * utils::array_product<n_args>(
+ &dims()[ndims() - n_args]) + logical_offset(args...);
+ }
+
+ template<int ORIG_LEN, typename ...Void>
+ dim_t _blk_off() const { return offset0(); }
+
+ template<int ORIG_LEN, typename T, typename ...Args>
+ dim_t _blk_off(T xc, Args ...args) const {
+ assert(is_blocking_desc());
+ constexpr int dc = ORIG_LEN - sizeof...(args) - 1;
+ return xc * blocking_desc().strides[dc]
+ + _blk_off<ORIG_LEN, Args...>(args...);
+ }
+};
+
+inline bool memory_desc_wrapper::similar_to(const memory_desc_wrapper &rhs,
+ bool with_padding, bool with_data_type, int dim_start) const {
+ using namespace utils;
+
+ if (one_of(format_kind(), format_kind::undef, format_kind::any))
+ return false;
+ if (is_wino_desc() || is_rnn_packed_desc())
+ return false;
+
+ const int ds = dim_start;
+ const auto &blk = blocking_desc();
+ const auto &r_blk = rhs.blocking_desc();
+
+ return ndims() == rhs.ndims()
+ && dim_start <= ndims() /* guard */
+ && format_kind() == rhs.format_kind()
+ && IMPLICATION(with_data_type, data_type() == rhs.data_type())
+ && array_cmp(dims() + ds, rhs.dims() + ds, ndims() - ds)
+ && array_cmp(blk.strides + ds, r_blk.strides + ds, ndims() - ds)
+ && blk.inner_nblks == r_blk.inner_nblks
+ && array_cmp(blk.inner_blks, r_blk.inner_blks, blk.inner_nblks)
+ && array_cmp(blk.inner_idxs, r_blk.inner_idxs, blk.inner_nblks)
+ && IMPLICATION(with_padding, true
+ && array_cmp(padded_dims() + ds, rhs.padded_dims() + ds,
+ ndims() - ds)
+ && array_cmp(padded_offsets() + ds, rhs.padded_offsets() + ds,
+ ndims() - ds));
+}
+
+inline bool memory_desc_wrapper::consistent_with(
+ const memory_desc_wrapper &rhs) const {
+ if (ndims() == rhs.ndims()) {
+ for (int d = 0; d < ndims(); ++d) {
+ if (dims()[d] != rhs.dims()[d]) return false;
+ }
+ return true;
+ } else {
+ /* TODO: revise.
+ * is the following possible?
+ * [1, a, b] <--reorder--> [a, b]
+ * [a, 1, b] <--reorder--> [a, b]
+ * not, at least for now */
+ return false;
+ }
+}
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/memory_tracking.hpp b/thirdparty/oidn/mkl-dnn/src/common/memory_tracking.hpp
new file mode 100644
index 0000000000..ec077b308c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/memory_tracking.hpp
@@ -0,0 +1,295 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MEMORY_TRACKING_HPP
+#define MEMORY_TRACKING_HPP
+
+#include <assert.h>
+#include <unordered_map>
+
+#include "nstl.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace memory_tracking {
+
+/* Memory tracking capabilities
+ *
+ * The main purpose of this header file is to provide uniform way to register
+ * required memory for a scratchpad at a primitive descriptor creation time
+ * and then easily access it having only the base address of the scratchpad.
+ *
+ * Primitives might contain multiple disjoint parts that require temporary
+ * buffers (known as scratchpad) during their execution. A primitive descriptor
+ * should summarize all the needs into one single number -- the buffer size
+ * that would be requested from a user. At execution time, the corresponding
+ * primitive will receive a base pointer to a scratchpad. It then needs to
+ * provide each part of algorithm the corresponding piece of memory. Three main
+ * challenges here are:
+ * 1. Track correct offset (from the base scratchpad address) for each piece
+ * 2. Algorithm might require that different memory pieces to be aligned, so
+ * the scratchpad size is no more just a sum of size of the corresponding
+ * subparts.
+ * 3. While a primitive is responsible for its scratchpad, the implementation
+ * might use some other basic blocks (e.g. cpu_reducer) that also require
+ * scratchpad memory. So there should be a simple way of passing the
+ * information back and force between the main algorithm (a primitive) and
+ * auxiliary stuff that lives completely separately from it (e.g. reducer).
+ *
+ * To address these challenges this header file provides 3 structures:
+ * 1. registry_t -- the class the stores the information about requested
+ * memory. The information includes required size and desired
+ * alignment for each piece. This class is also responsible
+ * for computing the right offset to a given piece using the
+ * base pointer.
+ * This class is basically a ledger with all entries.
+ * Lives in primitive descriptors.
+ *
+ * 2. registrar_t -- the interface to a registry_t to book memory. Used at
+ * primitive descriptor creation time only. Contains a
+ * reference to the corresponding *mutable* registry.
+ * Always modifiable.
+ * Allows chaining (using prefixes).
+ *
+ * 3. grantor_t -- the interface to a registry_t to access memory. Used at
+ * primitive execution time only. Contains a reference to
+ * the corresponding *constant* registry and base pointer.
+ * Always constant.
+ * Allows chaining (using prefixes).
+ *
+ * Both registrar_t and grantor_t allow chaining with extra prefix provided.
+ * The feature is useful when a primitive offload a part of computations to
+ * some other primitives which require their own scratchpad space
+ * (e.g. reducer). Prefixes are used to avoid key collision in cases when
+ * multiple sub-primitive (e.g. multiple reducers) are used.
+ *
+ * A short example below demonstrates how to use aforementioned classes. In it
+ * the main primitive is convolution that uses scratchpad for keeping padded
+ * bias. It also needs a reducer, that needs its own space as well.
+ *
+ * ``` c++
+ * struct reducer_t {
+ * static void init(registrar_t &scratchpad) {
+ * // preserve space for the reduction (one page aligned)
+ * scratchpad.book(key_space, sizeof(float) * 980 * 1024, 4096);
+ * }
+ *
+ * void exec(const grantor_t &scratchpad) {
+ * // get the pointer to preserved space. scratchpad came from
+ * // upper primitive (convolution in this example)
+ * auto space = scratchpad.get<float>(key_reducer_space);
+ *
+ * space[:] += ...;
+ * }
+ * };
+ *
+ * struct conv_t {
+ * struct pd_t {
+ * void init() {
+ * registrar_t scratchpad(scratchpad_registry_);
+ *
+ * // preserve a space for padded bias (using default alignment)
+ * scratchpad.book(key_conv_padded_bias, 128);
+ *
+ * // create a proxy registrar for the reducer All entries made
+ * // by reducer would live in convolution's registry, but would
+ * // have their own `prefix`, so no interference with conv's
+ * // buffers.
+ * registrar_t reducer_scratchpad(scratchpad, prefix_reducer);
+ *
+ * reducer_t::init(reducer_scratchpad);
+ * }
+ *
+ * registry_t scratchpad_registry_;
+ * }
+ *
+ * void exec() {
+ * // get the base pointer to a scratchpad memory from a user
+ * void *scratchpad_ptr = this->input(MKLDNN_MEM_SCRATCHPAD);
+ *
+ * // create a grantor to the scratchpad (and provide the base
+ * // pointer).
+ * grantor_t scratchpad(pd()->scratchpad_registry_, scratchpad_ptr);
+ *
+ * // access the padded_bias (need only key name and the grantor)
+ * auto padded_bias = scratchpad.get<float>(key_conv_padded_bias);
+ *
+ * // to give the `right` grantor to reducer we need to add the
+ * // corresponding prefix, so that reducer would be able to access
+ * // its keys. The call is very similar to the one in pd_t::init
+ * // with only difference in types: grantor_t vs registrar_t.
+ * grantor_t reducer_scratchpad(scratchpad, prefix_reducer);
+ * reducer->exec(reducer_scratchpad);
+ * }
+ * };
+ * ```
+ */
+
+
+/* namespace with common keys and prefixes */
+namespace names {
+enum {
+ key_none = 0,
+ key_bnorm_tmp_mean,
+ key_bnorm_tmp_var,
+ key_bnorm_tmp_diff_ss,
+ key_bnorm_tmp_stats,
+ key_bnorm_reduction,
+ key_concat_iptrs,
+ key_concat_istrides,
+ key_concat_nelems,
+ key_concat_optrs,
+ key_conv_adjusted_scales,
+ key_conv_bia_reduction,
+ key_conv_gemm_col,
+ key_conv_gemm_imtr,
+ key_conv_int_dat_in_acc_dt,
+ key_conv_padded_bias,
+ key_conv_rtus_space,
+ key_conv_tr_diff_dst,
+ key_conv_tr_diff_dst_bctx,
+ key_conv_tr_src,
+ key_conv_tr_src_bctx,
+ key_conv_wei_reduction,
+ key_conv_wei_bia_reduction,
+ key_conv_wei_bia_reduction_bctx,
+ key_iprod_int_dat_in_acc_dt,
+ key_reducer_space,
+ key_reducer_space_bctx,
+ key_reorder_wino_plain,
+ key_reorder_wino_transform_space,
+ key_reorder_rnn_weights_quantization,
+ key_reorder_rnn_weights_reduction,
+ key_rnn_space,
+ key_rnn_ptrs_bia,
+ key_rnn_ptrs_wei_layer,
+ key_rnn_ptrs_wei_iter,
+ key_softmax_reduction,
+ key_wino_U,
+ key_wino_V,
+ key_wino_M,
+ key_barrier,
+};
+
+enum {
+ prefix_none = 0,
+ prefix_reducer_bia,
+ prefix_reducer_wei,
+};
+}
+
+// level 0: 00 00 00 xxx
+// level 1: 00 00 aa xxx
+// level 2: 00 aa bb xxx
+// level 3: aa bb cc xxx
+// max # of levels: 3 + 1 (base_level)
+// here:
+// xxx : [1 .. MAX_KEY) : key
+// aa, bb, cc : [1 .. MAX_PREFIX) : prefixes for levels 1, 2, and 3
+
+using key_t = uint32_t;
+enum { MAX_KEY = (1u << 10), MAX_PREFIX = (1u << 7), };
+
+/// generates global key based on a prefix and a local key
+inline key_t make_key(key_t prefix, key_t key) { return prefix + key; }
+
+/// generates global prefix based on the global parent and the local ones
+inline key_t make_prefix(key_t parent_prefix, key_t prefix)
+{ return MAX_PREFIX * parent_prefix + MAX_KEY * prefix; }
+
+struct registrar_t;
+struct grantor_t;
+
+struct registry_t {
+ void book(const key_t &key, size_t size, size_t alignment) {
+ if (size == 0) return;
+ assert(offset_map_.count(key) == 0);
+
+ size = utils::rnd_up(size, minimal_alignment);
+ alignment = nstl::max<size_t>(alignment, minimal_alignment);
+ offset_map_[key] = entry_t{size_, size, alignment};
+
+ size_ += size + alignment - minimal_alignment;
+ }
+
+ void *get(const key_t &key, void *base_ptr) const {
+ if (base_ptr == nullptr) { assert(size() == 0); return nullptr; }
+ if (offset_map_.count(key) != 1) return nullptr;
+
+ const auto &e = offset_map_.at(key);
+ base_ptr = utils::align_ptr<void>(base_ptr, minimal_alignment);
+ char *ptr = (char *)base_ptr + e.offset;
+ return utils::align_ptr<void>(ptr, e.alignment);
+ }
+
+ size_t size() const
+ { return size_ > 0 ? size_ + minimal_alignment - 1 : 0; }
+
+ registrar_t registrar();
+ grantor_t grantor(void *base_ptr) const;
+
+protected:
+ enum { minimal_alignment = 64 };
+ struct entry_t { size_t offset, size, alignment; };
+
+ std::unordered_map<key_t, entry_t> offset_map_;
+ size_t size_ = 0;
+};
+
+struct registrar_t {
+ enum { default_alignment = 64 };
+
+ registrar_t(registry_t &registry): registry_(registry), prefix_(0) {}
+ registrar_t(registrar_t &parent, const key_t &prefix)
+ : registry_(parent.registry_)
+ , prefix_(make_prefix(parent.prefix_, prefix)) {}
+
+ void book(const key_t &key, size_t size,
+ size_t alignment = default_alignment)
+ { registry_.book(make_key(prefix_, key), size, alignment); }
+
+protected:
+ registry_t &registry_;
+ const key_t prefix_;
+};
+
+struct grantor_t {
+ grantor_t(const registry_t &registry, void *base_ptr)
+ : registry_(registry), prefix_(0), base_ptr_(base_ptr) {}
+ grantor_t(const grantor_t &parent, const key_t &prefix)
+ : registry_(parent.registry_)
+ , prefix_(make_prefix(parent.prefix_, prefix))
+ , base_ptr_(parent.base_ptr_) {}
+
+ template <typename T = void> T *get(const key_t &key) const
+ { return (T *)registry_.get(make_key(prefix_, key), base_ptr_); }
+
+protected:
+ const registry_t &registry_;
+ const key_t prefix_;
+ void *base_ptr_;
+};
+
+inline registrar_t registry_t::registrar() { return registrar_t(*this); }
+inline grantor_t registry_t::grantor(void *base_ptr) const
+{ return grantor_t(*this, base_ptr); }
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug.cpp b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug.cpp
new file mode 100644
index 0000000000..2ef4a8fddc
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug.cpp
@@ -0,0 +1,131 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <stdio.h>
+#include <cinttypes>
+
+#include "mkldnn_debug.h"
+#include "mkldnn_types.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#define DPRINT(...) do { \
+ int l = snprintf(str + written_len, str_len, __VA_ARGS__); \
+ if (l < 0) return l; \
+ if ((size_t)l >= str_len) return -1; \
+ written_len += l; str_len -= l; \
+} while(0)
+
+int mkldnn_md2fmt_str(char *str, size_t str_len,
+ const mkldnn_memory_desc_t *mdesc) {
+ using namespace mkldnn::impl;
+
+ if (str == nullptr || str_len <= 1u)
+ return -1;
+
+ int written_len = 0;
+
+ if (mdesc == nullptr) {
+ DPRINT("%s::%s::",
+ mkldnn_dt2str(data_type::undef),
+ mkldnn_fmt_kind2str(format_kind::undef));
+ return written_len;
+ }
+
+ memory_desc_wrapper md(mdesc);
+
+ DPRINT("%s:", mkldnn_dt2str(md.data_type()));
+
+ bool padded_dims = false, padded_offsets = false;
+ for (int d = 0; d < md.ndims(); ++d) {
+ if (md.dims()[d] != md.padded_dims()[d]) padded_dims = true;
+ if (md.padded_offsets()[d] != 0) padded_offsets = true;
+ }
+ bool offset0 = md.offset0();
+ DPRINT("%s%s%s:",
+ padded_dims ? "p" : "",
+ padded_offsets ? "o" : "",
+ offset0 ? "0" : "");
+
+ DPRINT("%s:", mkldnn_fmt_kind2str(md.format_kind()));
+
+ if (!md.is_blocking_desc()) {
+ /* TODO: extend */
+ DPRINT("%s:", "");
+ } else {
+ const auto &blk = md.blocking_desc();
+
+ dims_t blocks;
+ md.compute_blocks(blocks);
+
+ char dim_chars[MKLDNN_MAX_NDIMS + 1];
+
+ bool plain = true;
+ for (int d = 0; d < md.ndims(); ++d) {
+ dim_chars[d] = (blocks[d] == 1 ? 'a' : 'A') + (char)d;
+ if (blocks[d] != 1) plain = false;
+ }
+
+ dims_t strides;
+ utils::array_copy(strides, blk.strides, md.ndims());
+ utils::simultaneous_sort(strides, dim_chars, md.ndims(),
+ [](dim_t a, dim_t b) { return b - a; });
+
+ dim_chars[md.ndims()] = '\0';
+ DPRINT("%s", dim_chars);
+
+ if (!plain) {
+ for (int iblk = 0; iblk < blk.inner_nblks; ++iblk) {
+ DPRINT("%d%c", (int)blk.inner_blks[iblk],
+ 'a' + (char)blk.inner_idxs[iblk]);
+ }
+ }
+
+ DPRINT("%s", ":");
+ }
+
+ DPRINT("f%lx", (long)md.extra().flags);
+
+ return written_len;
+}
+
+int mkldnn_md2dim_str(char *str, size_t str_len,
+ const mkldnn_memory_desc_t *mdesc) {
+ using namespace mkldnn::impl;
+
+ if (str == nullptr || str_len <= 1)
+ return -1;
+
+ int written_len = 0;
+
+ if (mdesc == nullptr || mdesc->ndims == 0) {
+ DPRINT("%s", "");
+ return written_len;
+ }
+
+ memory_desc_wrapper md(mdesc);
+
+ for (int d = 0; d < md.ndims() - 1; ++d)
+ DPRINT("%" PRId64 "x", md.dims()[d]);
+ DPRINT("%" PRId64, md.dims()[md.ndims() - 1]);
+
+ return written_len;
+}
+
+#undef DPRINT
diff --git a/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug_autogenerated.cpp b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug_autogenerated.cpp
new file mode 100644
index 0000000000..16a8f7ea5e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_debug_autogenerated.cpp
@@ -0,0 +1,365 @@
+/*******************************************************************************
+* Copyright 2018-2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/* DO NOT EDIT, AUTO-GENERATED */
+
+#include <assert.h>
+
+#include "mkldnn_debug.h"
+#include "mkldnn_types.h"
+
+const char *mkldnn_status2str(mkldnn_status_t v) {
+ if (v == mkldnn_success) return "success";
+ if (v == mkldnn_out_of_memory) return "out_of_memory";
+ if (v == mkldnn_try_again) return "try_again";
+ if (v == mkldnn_invalid_arguments) return "invalid_arguments";
+ if (v == mkldnn_not_ready) return "not_ready";
+ if (v == mkldnn_unimplemented) return "unimplemented";
+ if (v == mkldnn_iterator_ends) return "iterator_ends";
+ if (v == mkldnn_runtime_error) return "runtime_error";
+ if (v == mkldnn_not_required) return "not_required";
+ assert(!"unknown status");
+ return "unknown status";
+}
+
+const char *mkldnn_dt2str(mkldnn_data_type_t v) {
+ if (v == mkldnn_data_type_undef) return "undef";
+ if (v == mkldnn_f32) return "f32";
+ if (v == mkldnn_s32) return "s32";
+ if (v == mkldnn_s8) return "s8";
+ if (v == mkldnn_u8) return "u8";
+ assert(!"unknown dt");
+ return "unknown dt";
+}
+
+const char *mkldnn_fmt_kind2str(mkldnn_format_kind_t v) {
+ if (v == mkldnn_format_kind_undef) return "undef";
+ if (v == mkldnn_format_kind_any) return "any";
+ if (v == mkldnn_blocked) return "blocked";
+ if (v == mkldnn_format_kind_wino) return "wino";
+ if (v == mkldnn_format_kind_rnn_packed) return "rnn_packed";
+ assert(!"unknown fmt_kind");
+ return "unknown fmt_kind";
+}
+
+const char *mkldnn_fmt_tag2str(mkldnn_format_tag_t v) {
+ if (v == mkldnn_format_tag_undef) return "undef";
+ if (v == mkldnn_format_tag_any) return "format_tag_any";
+ if (v == mkldnn_a) return "a";
+ if (v == mkldnn_ab) return "ab";
+ if (v == mkldnn_abc) return "abc";
+ if (v == mkldnn_abcd) return "abcd";
+ if (v == mkldnn_abcde) return "abcde";
+ if (v == mkldnn_abcdef) return "abcdef";
+ if (v == mkldnn_abdec) return "abdec";
+ if (v == mkldnn_acb) return "acb";
+ if (v == mkldnn_acbde) return "acbde";
+ if (v == mkldnn_acdb) return "acdb";
+ if (v == mkldnn_acdeb) return "acdeb";
+ if (v == mkldnn_ba) return "ba";
+ if (v == mkldnn_bac) return "bac";
+ if (v == mkldnn_bacd) return "bacd";
+ if (v == mkldnn_bcda) return "bcda";
+ if (v == mkldnn_cba) return "cba";
+ if (v == mkldnn_cdba) return "cdba";
+ if (v == mkldnn_cdeba) return "cdeba";
+ if (v == mkldnn_decab) return "decab";
+ if (v == mkldnn_Abc16a) return "Abc16a";
+ if (v == mkldnn_ABc16a16b) return "ABc16a16b";
+ if (v == mkldnn_aBc16b) return "aBc16b";
+ if (v == mkldnn_ABc16b16a) return "ABc16b16a";
+ if (v == mkldnn_Abc4a) return "Abc4a";
+ if (v == mkldnn_aBc4b) return "aBc4b";
+ if (v == mkldnn_ABc4b16a4b) return "ABc4b16a4b";
+ if (v == mkldnn_ABc4b4a) return "ABc4b4a";
+ if (v == mkldnn_ABc8a16b2a) return "ABc8a16b2a";
+ if (v == mkldnn_ABc8a8b) return "ABc8a8b";
+ if (v == mkldnn_aBc8b) return "aBc8b";
+ if (v == mkldnn_ABc8b16a2b) return "ABc8b16a2b";
+ if (v == mkldnn_ABc8b8a) return "ABc8b8a";
+ if (v == mkldnn_Abcd16a) return "Abcd16a";
+ if (v == mkldnn_ABcd16a16b) return "ABcd16a16b";
+ if (v == mkldnn_aBcd16b) return "aBcd16b";
+ if (v == mkldnn_ABcd16b16a) return "ABcd16b16a";
+ if (v == mkldnn_aBCd16b16c) return "aBCd16b16c";
+ if (v == mkldnn_aBCd16c16b) return "aBCd16c16b";
+ if (v == mkldnn_Abcd4a) return "Abcd4a";
+ if (v == mkldnn_aBcd4b) return "aBcd4b";
+ if (v == mkldnn_ABcd4b16a4b) return "ABcd4b16a4b";
+ if (v == mkldnn_ABcd4b4a) return "ABcd4b4a";
+ if (v == mkldnn_aBCd4c16b4c) return "aBCd4c16b4c";
+ if (v == mkldnn_aBCd4c4b) return "aBCd4c4b";
+ if (v == mkldnn_ABcd8a16b2a) return "ABcd8a16b2a";
+ if (v == mkldnn_ABcd8a8b) return "ABcd8a8b";
+ if (v == mkldnn_aBcd8b) return "aBcd8b";
+ if (v == mkldnn_ABcd8b16a2b) return "ABcd8b16a2b";
+ if (v == mkldnn_aBCd8b16c2b) return "aBCd8b16c2b";
+ if (v == mkldnn_ABcd8b8a) return "ABcd8b8a";
+ if (v == mkldnn_aBCd8b8c) return "aBCd8b8c";
+ if (v == mkldnn_aBCd8c16b2c) return "aBCd8c16b2c";
+ if (v == mkldnn_aBCd8c8b) return "aBCd8c8b";
+ if (v == mkldnn_Abcde16a) return "Abcde16a";
+ if (v == mkldnn_ABcde16a16b) return "ABcde16a16b";
+ if (v == mkldnn_aBcde16b) return "aBcde16b";
+ if (v == mkldnn_ABcde16b16a) return "ABcde16b16a";
+ if (v == mkldnn_aBCde16b16c) return "aBCde16b16c";
+ if (v == mkldnn_aBCde16c16b) return "aBCde16c16b";
+ if (v == mkldnn_aBCde2c8b4c) return "aBCde2c8b4c";
+ if (v == mkldnn_Abcde4a) return "Abcde4a";
+ if (v == mkldnn_aBcde4b) return "aBcde4b";
+ if (v == mkldnn_ABcde4b4a) return "ABcde4b4a";
+ if (v == mkldnn_aBCde4b4c) return "aBCde4b4c";
+ if (v == mkldnn_aBCde4c16b4c) return "aBCde4c16b4c";
+ if (v == mkldnn_aBCde4c4b) return "aBCde4c4b";
+ if (v == mkldnn_Abcde8a) return "Abcde8a";
+ if (v == mkldnn_ABcde8a8b) return "ABcde8a8b";
+ if (v == mkldnn_ABcde8b16a2b) return "ABcde8b16a2b";
+ if (v == mkldnn_aBCde8b16c2b) return "aBCde8b16c2b";
+ if (v == mkldnn_ABcde8b8a) return "ABcde8b8a";
+ if (v == mkldnn_aBCde8b8c) return "aBCde8b8c";
+ if (v == mkldnn_aBCde8c16b2c) return "aBCde8c16b2c";
+ if (v == mkldnn_aBCde8c8b) return "aBCde8c8b";
+ if (v == mkldnn_aBcdef16b) return "aBcdef16b";
+ if (v == mkldnn_aBCdef16b16c) return "aBCdef16b16c";
+ if (v == mkldnn_aBCdef16c16b) return "aBCdef16c16b";
+ if (v == mkldnn_aBcdef4b) return "aBcdef4b";
+ if (v == mkldnn_aBCdef4c4b) return "aBCdef4c4b";
+ if (v == mkldnn_aBCdef8b8c) return "aBCdef8b8c";
+ if (v == mkldnn_aBCdef8c16b2c) return "aBCdef8c16b2c";
+ if (v == mkldnn_aBCdef8c8b) return "aBCdef8c8b";
+ if (v == mkldnn_aBdc16b) return "aBdc16b";
+ if (v == mkldnn_aBdc4b) return "aBdc4b";
+ if (v == mkldnn_aBdc8b) return "aBdc8b";
+ if (v == mkldnn_aBdec16b) return "aBdec16b";
+ if (v == mkldnn_aBdec4b) return "aBdec4b";
+ if (v == mkldnn_aBdec8b) return "aBdec8b";
+ if (v == mkldnn_aBdefc16b) return "aBdefc16b";
+ if (v == mkldnn_aBdefc4b) return "aBdefc4b";
+ if (v == mkldnn_aBdefc8b) return "aBdefc8b";
+ if (v == mkldnn_Acb16a) return "Acb16a";
+ if (v == mkldnn_Acb4a) return "Acb4a";
+ if (v == mkldnn_Acb8a) return "Acb8a";
+ if (v == mkldnn_aCBd16b16c) return "aCBd16b16c";
+ if (v == mkldnn_aCBde16b16c) return "aCBde16b16c";
+ if (v == mkldnn_Acdb16a) return "Acdb16a";
+ if (v == mkldnn_Acdb4a) return "Acdb4a";
+ if (v == mkldnn_Acdb8a) return "Acdb8a";
+ if (v == mkldnn_Acdeb16a) return "Acdeb16a";
+ if (v == mkldnn_Acdeb4a) return "Acdeb4a";
+ if (v == mkldnn_Acdeb8a) return "Acdeb8a";
+ if (v == mkldnn_BAc16a16b) return "BAc16a16b";
+ if (v == mkldnn_BAcd16a16b) return "BAcd16a16b";
+ if (v == mkldnn_format_tag_last) return "format_tag_last";
+ if (v == mkldnn_x) return "x";
+ if (v == mkldnn_nc) return "nc";
+ if (v == mkldnn_cn) return "cn";
+ if (v == mkldnn_ncw) return "ncw";
+ if (v == mkldnn_nwc) return "nwc";
+ if (v == mkldnn_nchw) return "nchw";
+ if (v == mkldnn_nhwc) return "nhwc";
+ if (v == mkldnn_chwn) return "chwn";
+ if (v == mkldnn_ncdhw) return "ncdhw";
+ if (v == mkldnn_ndhwc) return "ndhwc";
+ if (v == mkldnn_oi) return "oi";
+ if (v == mkldnn_io) return "io";
+ if (v == mkldnn_oiw) return "oiw";
+ if (v == mkldnn_wio) return "wio";
+ if (v == mkldnn_oihw) return "oihw";
+ if (v == mkldnn_hwio) return "hwio";
+ if (v == mkldnn_ihwo) return "ihwo";
+ if (v == mkldnn_iohw) return "iohw";
+ if (v == mkldnn_oidhw) return "oidhw";
+ if (v == mkldnn_dhwio) return "dhwio";
+ if (v == mkldnn_goiw) return "goiw";
+ if (v == mkldnn_goihw) return "goihw";
+ if (v == mkldnn_hwigo) return "hwigo";
+ if (v == mkldnn_giohw) return "giohw";
+ if (v == mkldnn_goidhw) return "goidhw";
+ if (v == mkldnn_tnc) return "tnc";
+ if (v == mkldnn_ntc) return "ntc";
+ if (v == mkldnn_ldsnc) return "ldsnc";
+ if (v == mkldnn_ldigo) return "ldigo";
+ if (v == mkldnn_ldgoi) return "ldgoi";
+ if (v == mkldnn_ldgo) return "ldgo";
+ if (v == mkldnn_nCdhw16c) return "nCdhw16c";
+ if (v == mkldnn_nCdhw4c) return "nCdhw4c";
+ if (v == mkldnn_nCdhw8c) return "nCdhw8c";
+ if (v == mkldnn_nChw16c) return "nChw16c";
+ if (v == mkldnn_nChw4c) return "nChw4c";
+ if (v == mkldnn_nChw8c) return "nChw8c";
+ if (v == mkldnn_nCw16c) return "nCw16c";
+ if (v == mkldnn_nCw4c) return "nCw4c";
+ if (v == mkldnn_nCw8c) return "nCw8c";
+ if (v == mkldnn_IOw16o16i) return "IOw16o16i";
+ if (v == mkldnn_OIw16i16o) return "OIw16i16o";
+ if (v == mkldnn_OIw16o16i) return "OIw16o16i";
+ if (v == mkldnn_Oiw16o) return "Oiw16o";
+ if (v == mkldnn_OIw4i16o4i) return "OIw4i16o4i";
+ if (v == mkldnn_OIw4i4o) return "OIw4i4o";
+ if (v == mkldnn_Oiw4o) return "Oiw4o";
+ if (v == mkldnn_OIw8i16o2i) return "OIw8i16o2i";
+ if (v == mkldnn_OIw8i8o) return "OIw8i8o";
+ if (v == mkldnn_OIw8o16i2o) return "OIw8o16i2o";
+ if (v == mkldnn_OIw8o8i) return "OIw8o8i";
+ if (v == mkldnn_Owi16o) return "Owi16o";
+ if (v == mkldnn_Owi4o) return "Owi4o";
+ if (v == mkldnn_Owi8o) return "Owi8o";
+ if (v == mkldnn_IOhw16o16i) return "IOhw16o16i";
+ if (v == mkldnn_Ohwi16o) return "Ohwi16o";
+ if (v == mkldnn_Ohwi4o) return "Ohwi4o";
+ if (v == mkldnn_Ohwi8o) return "Ohwi8o";
+ if (v == mkldnn_OIhw16i16o) return "OIhw16i16o";
+ if (v == mkldnn_OIhw16o16i) return "OIhw16o16i";
+ if (v == mkldnn_Oihw16o) return "Oihw16o";
+ if (v == mkldnn_OIhw4i16o4i) return "OIhw4i16o4i";
+ if (v == mkldnn_OIhw4i4o) return "OIhw4i4o";
+ if (v == mkldnn_Oihw4o) return "Oihw4o";
+ if (v == mkldnn_OIhw8i16o2i) return "OIhw8i16o2i";
+ if (v == mkldnn_OIhw8i8o) return "OIhw8i8o";
+ if (v == mkldnn_OIhw8o16i2o) return "OIhw8o16i2o";
+ if (v == mkldnn_OIhw8o8i) return "OIhw8o8i";
+ if (v == mkldnn_Odhwi16o) return "Odhwi16o";
+ if (v == mkldnn_Odhwi4o) return "Odhwi4o";
+ if (v == mkldnn_Odhwi8o) return "Odhwi8o";
+ if (v == mkldnn_OIdhw16i16o) return "OIdhw16i16o";
+ if (v == mkldnn_OIdhw16o16i) return "OIdhw16o16i";
+ if (v == mkldnn_Oidhw16o) return "Oidhw16o";
+ if (v == mkldnn_OIdhw4i4o) return "OIdhw4i4o";
+ if (v == mkldnn_Oidhw4o) return "Oidhw4o";
+ if (v == mkldnn_OIdhw8i16o2i) return "OIdhw8i16o2i";
+ if (v == mkldnn_OIdhw8i8o) return "OIdhw8i8o";
+ if (v == mkldnn_OIdhw8o8i) return "OIdhw8o8i";
+ if (v == mkldnn_Goiw16g) return "Goiw16g";
+ if (v == mkldnn_gIOw16o16i) return "gIOw16o16i";
+ if (v == mkldnn_gOIw16i16o) return "gOIw16i16o";
+ if (v == mkldnn_gOIw16o16i) return "gOIw16o16i";
+ if (v == mkldnn_gOiw16o) return "gOiw16o";
+ if (v == mkldnn_gOIw4i16o4i) return "gOIw4i16o4i";
+ if (v == mkldnn_gOIw4i4o) return "gOIw4i4o";
+ if (v == mkldnn_gOiw4o) return "gOiw4o";
+ if (v == mkldnn_gOIw8i16o2i) return "gOIw8i16o2i";
+ if (v == mkldnn_gOIw8i8o) return "gOIw8i8o";
+ if (v == mkldnn_gOIw8o16i2o) return "gOIw8o16i2o";
+ if (v == mkldnn_gOIw8o8i) return "gOIw8o8i";
+ if (v == mkldnn_gOwi16o) return "gOwi16o";
+ if (v == mkldnn_gOwi4o) return "gOwi4o";
+ if (v == mkldnn_gOwi8o) return "gOwi8o";
+ if (v == mkldnn_gIOhw16o16i) return "gIOhw16o16i";
+ if (v == mkldnn_gOhwi16o) return "gOhwi16o";
+ if (v == mkldnn_gOhwi4o) return "gOhwi4o";
+ if (v == mkldnn_gOhwi8o) return "gOhwi8o";
+ if (v == mkldnn_Goihw16g) return "Goihw16g";
+ if (v == mkldnn_gOIhw16i16o) return "gOIhw16i16o";
+ if (v == mkldnn_gOIhw16o16i) return "gOIhw16o16i";
+ if (v == mkldnn_gOihw16o) return "gOihw16o";
+ if (v == mkldnn_gOIhw2i8o4i) return "gOIhw2i8o4i";
+ if (v == mkldnn_gOIhw4i16o4i) return "gOIhw4i16o4i";
+ if (v == mkldnn_gOIhw4i4o) return "gOIhw4i4o";
+ if (v == mkldnn_gOIhw4o4i) return "gOIhw4o4i";
+ if (v == mkldnn_gOihw4o) return "gOihw4o";
+ if (v == mkldnn_Goihw8g) return "Goihw8g";
+ if (v == mkldnn_gOIhw8i16o2i) return "gOIhw8i16o2i";
+ if (v == mkldnn_gOIhw8i8o) return "gOIhw8i8o";
+ if (v == mkldnn_gOIhw8o16i2o) return "gOIhw8o16i2o";
+ if (v == mkldnn_gOIhw8o8i) return "gOIhw8o8i";
+ if (v == mkldnn_gOdhwi16o) return "gOdhwi16o";
+ if (v == mkldnn_gOdhwi4o) return "gOdhwi4o";
+ if (v == mkldnn_gOdhwi8o) return "gOdhwi8o";
+ if (v == mkldnn_gOIdhw16i16o) return "gOIdhw16i16o";
+ if (v == mkldnn_gOIdhw16o16i) return "gOIdhw16o16i";
+ if (v == mkldnn_gOidhw16o) return "gOidhw16o";
+ if (v == mkldnn_gOIdhw4i4o) return "gOIdhw4i4o";
+ if (v == mkldnn_gOidhw4o) return "gOidhw4o";
+ if (v == mkldnn_gOIdhw8i16o2i) return "gOIdhw8i16o2i";
+ if (v == mkldnn_gOIdhw8i8o) return "gOIdhw8i8o";
+ if (v == mkldnn_gOIdhw8o8i) return "gOIdhw8o8i";
+ assert(!"unknown fmt_tag");
+ return "unknown fmt_tag";
+}
+
+const char *mkldnn_prop_kind2str(mkldnn_prop_kind_t v) {
+ if (v == mkldnn_prop_kind_undef) return "undef";
+ if (v == mkldnn_forward_training) return "forward_training";
+ if (v == mkldnn_forward_inference) return "forward_inference";
+ if (v == mkldnn_forward_scoring) return "forward_scoring";
+ if (v == mkldnn_forward) return "forward";
+ if (v == mkldnn_backward) return "backward";
+ if (v == mkldnn_backward_data) return "backward_data";
+ if (v == mkldnn_backward_weights) return "backward_weights";
+ if (v == mkldnn_backward_bias) return "backward_bias";
+ assert(!"unknown prop_kind");
+ return "unknown prop_kind";
+}
+
+const char *mkldnn_prim_kind2str(mkldnn_primitive_kind_t v) {
+ if (v == mkldnn_undefined_primitive) return "undef";
+ if (v == mkldnn_reorder) return "reorder";
+ if (v == mkldnn_shuffle) return "shuffle";
+ if (v == mkldnn_concat) return "concat";
+ if (v == mkldnn_sum) return "sum";
+ if (v == mkldnn_convolution) return "convolution";
+ if (v == mkldnn_deconvolution) return "deconvolution";
+ if (v == mkldnn_eltwise) return "eltwise";
+ if (v == mkldnn_softmax) return "softmax";
+ if (v == mkldnn_pooling) return "pooling";
+ if (v == mkldnn_lrn) return "lrn";
+ if (v == mkldnn_batch_normalization) return "batch_normalization";
+ if (v == mkldnn_inner_product) return "inner_product";
+ if (v == mkldnn_rnn) return "rnn";
+ assert(!"unknown prim_kind");
+ return "unknown prim_kind";
+}
+
+const char *mkldnn_alg_kind2str(mkldnn_alg_kind_t v) {
+ if (v == mkldnn_alg_kind_undef) return "undef";
+ if (v == mkldnn_convolution_direct) return "convolution_direct";
+ if (v == mkldnn_convolution_winograd) return "convolution_winograd";
+ if (v == mkldnn_convolution_auto) return "convolution_auto";
+ if (v == mkldnn_deconvolution_direct) return "deconvolution_direct";
+ if (v == mkldnn_deconvolution_winograd) return "deconvolution_winograd";
+ if (v == mkldnn_eltwise_relu) return "eltwise_relu";
+ if (v == mkldnn_eltwise_tanh) return "eltwise_tanh";
+ if (v == mkldnn_eltwise_elu) return "eltwise_elu";
+ if (v == mkldnn_eltwise_square) return "eltwise_square";
+ if (v == mkldnn_eltwise_abs) return "eltwise_abs";
+ if (v == mkldnn_eltwise_sqrt) return "eltwise_sqrt";
+ if (v == mkldnn_eltwise_linear) return "eltwise_linear";
+ if (v == mkldnn_eltwise_bounded_relu) return "eltwise_bounded_relu";
+ if (v == mkldnn_eltwise_soft_relu) return "eltwise_soft_relu";
+ if (v == mkldnn_eltwise_logistic) return "eltwise_logistic";
+ if (v == mkldnn_pooling_max) return "pooling_max";
+ if (v == mkldnn_pooling_avg_include_padding) return "pooling_avg_include_padding";
+ if (v == mkldnn_pooling_avg_exclude_padding) return "pooling_avg_exclude_padding";
+ if (v == mkldnn_pooling_avg) return "pooling_avg";
+ if (v == mkldnn_lrn_across_channels) return "lrn_across_channels";
+ if (v == mkldnn_lrn_within_channel) return "lrn_within_channel";
+ if (v == mkldnn_vanilla_rnn) return "vanilla_rnn";
+ if (v == mkldnn_vanilla_lstm) return "vanilla_lstm";
+ if (v == mkldnn_vanilla_gru) return "vanilla_gru";
+ if (v == mkldnn_gru_linear_before_reset) return "gru_linear_before_reset";
+ assert(!"unknown alg_kind");
+ return "unknown alg_kind";
+}
+
+const char *mkldnn_rnn_direction2str(mkldnn_rnn_direction_t v) {
+ if (v == mkldnn_unidirectional_left2right) return "unidirectional_left2right";
+ if (v == mkldnn_unidirectional_right2left) return "unidirectional_right2left";
+ if (v == mkldnn_bidirectional_concat) return "bidirectional_concat";
+ if (v == mkldnn_bidirectional_sum) return "bidirectional_sum";
+ if (v == mkldnn_unidirectional) return "unidirectional";
+ assert(!"unknown rnn_direction");
+ return "unknown rnn_direction";
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread.hpp b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread.hpp
new file mode 100644
index 0000000000..7e5789e2c3
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread.hpp
@@ -0,0 +1,115 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MKLDNN_THREAD_HPP
+#define MKLDNN_THREAD_HPP
+
+#include "utils.hpp"
+#include "z_magic.hpp"
+
+#define MKLDNN_THR_SEQ 0
+#define MKLDNN_THR_OMP 1
+#define MKLDNN_THR_TBB 2
+
+/* Ideally this condition below should never happen (if the library is built
+ * using regular cmake). For the 3rd-party projects that build the library
+ * from the sources on their own try to guess the right threading... */
+#if !defined(MKLDNN_THR)
+# define MKLDNN_THR MKLDNN_THR_TBB
+#endif
+
+#if MKLDNN_THR == MKLDNN_THR_SEQ
+#define MKLDNN_THR_SYNC 1
+inline int mkldnn_get_max_threads() { return 1; }
+inline int mkldnn_get_num_threads() { return 1; }
+inline int mkldnn_get_thread_num() { return 0; }
+inline int mkldnn_in_parallel() { return 0; }
+inline void mkldnn_thr_barrier() {}
+
+#define PRAGMA_OMP(...)
+
+#elif MKLDNN_THR == MKLDNN_THR_OMP
+#include <omp.h>
+#define MKLDNN_THR_SYNC 1
+
+inline int mkldnn_get_max_threads() { return omp_get_max_threads(); }
+inline int mkldnn_get_num_threads() { return omp_get_num_threads(); }
+inline int mkldnn_get_thread_num() { return omp_get_thread_num(); }
+inline int mkldnn_in_parallel() { return omp_in_parallel(); }
+inline void mkldnn_thr_barrier() {
+# pragma omp barrier
+}
+
+#define PRAGMA_OMP(...) PRAGMA_MACRO(CHAIN2(omp, __VA_ARGS__))
+
+#elif MKLDNN_THR == MKLDNN_THR_TBB
+#include "tbb/task_arena.h"
+#include "tbb/parallel_for.h"
+#define MKLDNN_THR_SYNC 0
+
+inline int mkldnn_get_max_threads()
+{ return tbb::this_task_arena::max_concurrency(); }
+inline int mkldnn_get_num_threads() { return mkldnn_get_max_threads(); }
+inline int mkldnn_get_thread_num()
+{ return tbb::this_task_arena::current_thread_index(); }
+inline int mkldnn_in_parallel() { return 0; }
+inline void mkldnn_thr_barrier() { assert(!"no barrier in TBB"); }
+
+#define PRAGMA_OMP(...)
+
+#endif
+
+/* MSVC still supports omp 2.0 only */
+#if defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER)
+# define collapse(x)
+# define PRAGMA_OMP_SIMD(...)
+#else
+# define PRAGMA_OMP_SIMD(...) PRAGMA_MACRO(CHAIN2(omp, simd __VA_ARGS__))
+#endif // defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+
+namespace mkldnn {
+namespace impl {
+
+inline bool mkldnn_thr_syncable() { return MKLDNN_THR_SYNC == 1; }
+
+template <typename T, typename U>
+inline void balance211(T n, U team, U tid, T &n_start, T &n_end) {
+ T n_min = 1;
+ T &n_my = n_end;
+ if (team <= 1 || n == 0) {
+ n_start = 0;
+ n_my = n;
+ } else if (n_min == 1) {
+ // team = T1 + T2
+ // n = T1*n1 + T2*n2 (n1 - n2 = 1)
+ T n1 = utils::div_up(n, (T)team);
+ T n2 = n1 - 1;
+ T T1 = n - n2 * (T)team;
+ n_my = (T)tid < T1 ? n1 : n2;
+ n_start = (T)tid <= T1 ? tid * n1 : T1 * n1 + ((T)tid - T1) * n2;
+ }
+
+ n_end += n_start;
+}
+
+} // namespace impl
+} // namespace mkldnn
+
+#include "mkldnn_thread_parallel_nd.hpp"
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread_parallel_nd.hpp b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread_parallel_nd.hpp
new file mode 100644
index 0000000000..50f9b29622
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_thread_parallel_nd.hpp
@@ -0,0 +1,277 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MKLDNN_THREAD_PARALLEL_ND_HPP
+#define MKLDNN_THREAD_PARALLEL_ND_HPP
+
+/* This header must be included by mkldnn_thread.hpp only */
+
+/* Functions:
+ * - parallel(nthr, f) - executes f in parallel using at most
+ * nthr threads. If nthr equals 0
+ * mkldnn_get_max_threads() threads is
+ * used
+ * - for_nd(ithr, nthr, dims..., f) - multidimensional for loop for already
+ * created threads
+ * - parallel_nd(dims..., f) - creates a parallel section and then
+ * calls for_nd
+ * - parallel_nd_in_omp(dims..., f) - queries current nthr and ithr and then
+ * calls for_nd (mostly for convenience)
+ */
+
+namespace mkldnn {
+namespace impl {
+
+/* general parallelization */
+template <typename F>
+void parallel(int nthr, F f) {
+ if (nthr == 0) nthr = mkldnn_get_max_threads();
+#if MKLDNN_THR == MKLDNN_THR_SEQ
+ assert(nthr == 1);
+ f(0, 1);
+#elif MKLDNN_THR == MKLDNN_THR_OMP
+ if (nthr == 1) { f(0, 1); return; }
+# pragma omp parallel num_threads(nthr)
+ f(mkldnn_get_thread_num(), mkldnn_get_num_threads());
+#elif MKLDNN_THR == MKLDNN_THR_TBB
+ if (nthr == 1) { f(0, 1); return; }
+ tbb::parallel_for(0, nthr, [&](int ithr) { f(ithr, nthr); }, tbb::static_partitioner());
+#endif
+}
+
+/* for_nd section */
+
+template <typename T0, typename F>
+void for_nd(const int ithr, const int nthr, const T0 &D0, F f) {
+ T0 start{0}, end{0};
+ balance211(D0, nthr, ithr, start, end);
+ for (T0 d0 = start; d0 < end; ++d0) f(d0);
+}
+
+template <typename T0, typename T1, typename F>
+void for_nd(const int ithr, const int nthr, const T0 &D0, const T1 &D1, F f) {
+ const size_t work_amount = (size_t)D0 * D1;
+ if (work_amount == 0) return;
+ size_t start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ T0 d0{0}; T1 d1{0};
+ utils::nd_iterator_init(start, d0, D0, d1, D1);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ f(d0, d1);
+ utils::nd_iterator_step(d0, D0, d1, D1);
+ }
+}
+
+template <typename T0, typename T1, typename T2, typename F>
+void for_nd(const int ithr, const int nthr, const T0 &D0, const T1 &D1,
+ const T2 &D2, F f) {
+ const size_t work_amount = (size_t)D0 * D1 * D2;
+ if (work_amount == 0) return;
+ size_t start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ T0 d0{0}; T1 d1{0}; T2 d2{0};
+ utils::nd_iterator_init(start, d0, D0, d1, D1, d2, D2);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ f(d0, d1, d2);
+ utils::nd_iterator_step(d0, D0, d1, D1, d2, D2);
+ }
+}
+
+template <typename T0, typename T1, typename T2, typename T3, typename F>
+void for_nd(const int ithr, const int nthr, const T0 &D0, const T1 &D1,
+ const T2 &D2, const T3 &D3, F f) {
+ const size_t work_amount = (size_t)D0 * D1 * D2 * D3;
+ if (work_amount == 0) return;
+ size_t start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0};
+ utils::nd_iterator_init(start, d0, D0, d1, D1, d2, D2, d3, D3);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ f(d0, d1, d2, d3);
+ utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3);
+ }
+}
+
+template <typename T0, typename T1, typename T2, typename T3, typename T4,
+ typename F>
+void for_nd(const int ithr, const int nthr, const T0 &D0, const T1 &D1,
+ const T2 &D2, const T3 &D3, const T4 &D4, F f) {
+ const size_t work_amount = (size_t)D0 * D1 * D2 * D3 * D4;
+ if (work_amount == 0) return;
+ size_t start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0}; T4 d4{0};
+ utils::nd_iterator_init(start, d0, D0, d1, D1, d2, D2, d3, D3, d4, D4);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ f(d0, d1, d2, d3, d4);
+ utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3, d4, D4);
+ }
+}
+
+template <typename T0, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename F>
+void for_nd(const int ithr, const int nthr, const T0 &D0, const T1 &D1,
+ const T2 &D2, const T3 &D3, const T4 &D4, const T5 &D5, F f) {
+ const size_t work_amount = (size_t)D0 * D1 * D2 * D3 * D4 * D5;
+ if (work_amount == 0) return;
+ size_t start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0}; T4 d4{0}; T5 d5{0};
+ utils::nd_iterator_init(start, d0, D0, d1, D1, d2, D2, d3, D3, d4, D4,
+ d5, D5);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ f(d0, d1, d2, d3, d4, d5);
+ utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3, d4, D4, d5, D5);
+ }
+}
+
+// Skip a lambda function in the parameter pack.
+template <typename T>
+constexpr size_t get_work_amount(const T &v) { return 1; }
+template <typename T, typename ...Args>
+constexpr size_t get_work_amount(const T &v, Args &&...args)
+{ return (size_t)v * get_work_amount(utils::forward<Args>(args)...); }
+
+/* parallel_nd and parallel_nd_in_omp section */
+
+#if MKLDNN_THR != MKLDNN_THR_TBB
+template <typename ...Args>
+void parallel_nd(Args &&...args) {
+#if MKLDNN_THR == MKLDNN_THR_SEQ
+ for_nd(0, 1, utils::forward<Args>(args)...);
+#elif MKLDNN_THR == MKLDNN_THR_OMP
+ const bool do_parallel = get_work_amount(utils::forward<Args>(args)...) > 1;
+# pragma omp parallel if (do_parallel)
+ {
+ const int nthr = !do_parallel ? 1 : mkldnn_get_num_threads();
+ const int ithr = !do_parallel ? 0 : mkldnn_get_thread_num();
+ for_nd(ithr, nthr, utils::forward<Args>(args)...);
+ }
+#endif
+}
+#else // MKLDNN_THR != MKLDNN_THR_TBB
+
+// gcc 4.8 has a bug with passing parameter pack to lambdas.
+// So have to explicitly instantiate all the cases.
+
+template <typename T0, typename F>
+void parallel_nd(const T0 &D0, F f) {
+ const size_t work_amount = (size_t)D0;
+ if (work_amount == 0) return;
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, work_amount), [&](const tbb::blocked_range<size_t>& r) {
+ for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) {
+ f(T0(iwork));
+ }
+ }, tbb::static_partitioner());
+}
+
+template <typename T0, typename T1, typename F>
+void parallel_nd(const T0 &D0, const T1 &D1, F f) {
+ const size_t work_amount = (size_t)D0 * D1;
+ if (work_amount == 0) return;
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, work_amount), [&](const tbb::blocked_range<size_t>& r) {
+ T0 d0{0}; T1 d1{0};
+ utils::nd_iterator_init(r.begin(), d0, D0, d1, D1);
+ for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) {
+ f(d0, d1);
+ utils::nd_iterator_step(d0, D0, d1, D1);
+ }
+ }, tbb::static_partitioner());
+}
+
+template <typename T0, typename T1, typename T2, typename F>
+void parallel_nd(const T0 &D0, const T1 &D1, const T2 &D2, F f) {
+ const size_t work_amount = (size_t)D0 * D1 * D2;
+ if (work_amount == 0) return;
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, work_amount), [&](const tbb::blocked_range<size_t>& r) {
+ T0 d0{0}; T1 d1{0}; T2 d2{0};
+ utils::nd_iterator_init(r.begin(), d0, D0, d1, D1, d2, D2);
+ for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) {
+ f(d0, d1, d2);
+ utils::nd_iterator_step(d0, D0, d1, D1, d2, D2);
+ }
+ }, tbb::static_partitioner());
+}
+
+template <typename T0, typename T1, typename T2, typename T3, typename F>
+void parallel_nd(const T0 &D0, const T1 &D1, const T2 &D2, const T3 &D3, F f) {
+ const size_t work_amount = (size_t)D0 * D1 * D2 * D3;
+ if (work_amount == 0) return;
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, work_amount), [&](const tbb::blocked_range<size_t>& r) {
+ T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0};
+ utils::nd_iterator_init(r.begin(), d0, D0, d1, D1, d2, D2, d3, D3);
+ for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) {
+ f(d0, d1, d2, d3);
+ utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3);
+ }
+ }, tbb::static_partitioner());
+}
+
+template <typename T0, typename T1, typename T2, typename T3, typename T4,
+ typename F>
+void parallel_nd(const T0 &D0, const T1 &D1, const T2 &D2, const T3 &D3,
+ const T4 &D4, F f) {
+ const size_t work_amount = (size_t)D0 * D1 * D2 * D3 * D4;
+ if (work_amount == 0) return;
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, work_amount), [&](const tbb::blocked_range<size_t>& r) {
+ T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0}; T4 d4{0};
+ utils::nd_iterator_init(r.begin(), d0, D0, d1, D1, d2, D2, d3, D3, d4, D4);
+ for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) {
+ f(d0, d1, d2, d3, d4);
+ utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3, d4, D4);
+ }
+ }, tbb::static_partitioner());
+}
+
+template <typename T0, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename F>
+void parallel_nd(const T0 &D0, const T1 &D1, const T2 &D2, const T3 &D3,
+ const T4 &D4, const T5 &D5, F f) {
+ const size_t work_amount = (size_t)D0 * D1 * D2 * D3 * D4 * D5;
+ if (work_amount == 0) return;
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, work_amount), [&](const tbb::blocked_range<size_t>& r) {
+ T0 d0{0}; T1 d1{0}; T2 d2{0}; T3 d3{0}; T4 d4{0}; T5 d5{0};
+ utils::nd_iterator_init(r.begin(), d0, D0, d1, D1, d2, D2, d3, D3, d4, D4,
+ d5, D5);
+ for (size_t iwork = r.begin(); iwork != r.end(); ++iwork) {
+ f(d0, d1, d2, d3, d4, d5);
+ utils::nd_iterator_step(d0, D0, d1, D1, d2, D2, d3, D3, d4, D4, d5, D5);
+ }
+ }, tbb::static_partitioner());
+}
+#endif
+
+template <typename ...Args>
+void parallel_nd_in_omp(Args &&...args) {
+#if MKLDNN_THR == MKLDNN_THR_SEQ
+ for_nd(0, 1, utils::forward<Args>(args)...);
+#elif MKLDNN_THR == MKLDNN_THR_OMP
+ for_nd(mkldnn_get_thread_num(), mkldnn_get_num_threads(),
+ utils::forward<Args>(args)...);
+#elif MKLDNN_THR == MKLDNN_THR_TBB
+ assert(!"unsupported parallel_nd_in_omp()");
+#endif
+}
+
+} // namespace impl
+} // namespace mkldnn
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/mkldnn_traits.hpp b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_traits.hpp
new file mode 100644
index 0000000000..aa671a0b6e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/mkldnn_traits.hpp
@@ -0,0 +1,77 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef MKLDNN_TRAITS_HPP
+#define MKLDNN_TRAITS_HPP
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "mkldnn.h"
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "utils.hpp"
+#include "z_magic.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+template <data_type_t> struct prec_traits {}; /* ::type -> float */
+template <typename> struct data_traits {}; /* ::data_type -> f32 */
+template <int> struct typesize_traits {}; /* ::data_type_size -> f32 */
+template <primitive_kind_t> struct pkind_traits {}; /* ::desc_type, ::query_d */
+
+template <> struct prec_traits<data_type::f32> { typedef float type; };
+template <> struct prec_traits<data_type::s32> { typedef int32_t type; };
+template <> struct prec_traits<data_type::s8> { typedef int8_t type; };
+template <> struct prec_traits<data_type::u8> { typedef uint8_t type; };
+
+template <> struct data_traits<float>
+{ static constexpr data_type_t data_type = data_type::f32; };
+template <> struct data_traits<int32_t>
+{ static constexpr data_type_t data_type = data_type::s32; };
+template <> struct data_traits<int8_t>
+{ static constexpr data_type_t data_type = data_type::s8; };
+template <> struct data_traits<uint8_t>
+{ static constexpr data_type_t data_type = data_type::u8; };
+
+template <> struct typesize_traits<4> { typedef float type; };
+template <> struct typesize_traits<2> { typedef int16_t type; };
+template <> struct typesize_traits<1> { typedef uint8_t type; };
+
+#define PKIND_TRAITS_INST(op) \
+template <> struct pkind_traits<primitive_kind::op> { \
+ typedef CONCAT2(op, _desc_t) desc_type; \
+ static constexpr query_t query_d = query::CONCAT2(op, _d); \
+}
+PKIND_TRAITS_INST(convolution);
+PKIND_TRAITS_INST(deconvolution);
+PKIND_TRAITS_INST(shuffle);
+PKIND_TRAITS_INST(eltwise);
+PKIND_TRAITS_INST(softmax);
+PKIND_TRAITS_INST(pooling);
+PKIND_TRAITS_INST(lrn);
+PKIND_TRAITS_INST(batch_normalization);
+PKIND_TRAITS_INST(inner_product);
+PKIND_TRAITS_INST(rnn);
+#undef PKIND_TRAITS_INST
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/nstl.hpp b/thirdparty/oidn/mkl-dnn/src/common/nstl.hpp
new file mode 100644
index 0000000000..f89ea999e2
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/nstl.hpp
@@ -0,0 +1,193 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef NSTL_HPP
+#define NSTL_HPP
+
+#include <stdint.h>
+#include <limits.h>
+#include <float.h>
+
+#include <vector>
+#include <map>
+
+#include "z_magic.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+void *malloc(size_t size, int alignment);
+void free(void *p);
+
+struct c_compatible {
+ enum { default_alignment = 64 };
+ static void *operator new(size_t sz) {
+ return malloc(sz, default_alignment);
+ }
+ static void *operator new(size_t sz, void *p) { UNUSED(sz); return p; }
+ static void *operator new[](size_t sz) {
+ return malloc(sz, default_alignment);
+ }
+ static void operator delete(void *p) { free(p); }
+ static void operator delete[](void *p) { free(p); }
+};
+
+namespace nstl {
+
+template<typename T>
+inline const T abs(const T& a) {
+ return a >= 0 ? a : -a;
+}
+
+template<typename T>
+inline const T& max(const T& a, const T& b) {
+ return a > b ? a : b;
+}
+
+template<typename T>
+inline const T& min(const T& a, const T& b) {
+ return a < b ? a : b;
+}
+
+template<typename T> void swap(T& t1, T& t2) {
+ T tmp(t1);
+ t1 = t2;
+ t2 = tmp;
+}
+
+// Rationale: MKL-DNN needs numeric limits implementation that does not
+// generate dependencies on C++ run-time libraries.
+
+template<typename T> struct numeric_limits;
+
+template<> struct numeric_limits<float> {
+ static constexpr float lowest() { return -FLT_MAX; }
+ static constexpr float max() { return FLT_MAX; }
+};
+
+template<> struct numeric_limits<int32_t> {
+ static constexpr int lowest() { return INT32_MIN; }
+ static constexpr int max() { return INT32_MAX; }
+};
+
+template<> struct numeric_limits<int16_t> {
+ static constexpr int16_t lowest() { return INT16_MIN; }
+ static constexpr int16_t max() { return INT16_MAX; }
+};
+
+template<> struct numeric_limits<int8_t> {
+ static constexpr int8_t lowest() { return INT8_MIN; }
+ static constexpr int8_t max() { return INT8_MAX; }
+};
+
+template<> struct numeric_limits<uint8_t> {
+ static constexpr uint8_t lowest() { return 0; }
+ static constexpr uint8_t max() { return UINT8_MAX; }
+};
+
+template<typename T> struct is_integral
+{ static constexpr bool value = false; };
+template<> struct is_integral<int32_t> { static constexpr bool value = true; };
+template<> struct is_integral<int16_t> { static constexpr bool value = true; };
+template<> struct is_integral<int8_t> { static constexpr bool value = true; };
+template<> struct is_integral<uint8_t> { static constexpr bool value = true; };
+
+template <typename T, typename U> struct is_same
+{ static constexpr bool value = false; };
+template <typename T> struct is_same<T, T>
+{ static constexpr bool value = true; };
+
+// Rationale: MKL-DNN needs container implementations that do not generate
+// dependencies on C++ run-time libraries.
+//
+// Implementation philosophy: caller is responsible to check if the operation
+// is valid. The only functions that have to return status are those that
+// depend on memory allocation or similar operations.
+//
+// This means that e.g. an operator [] does not have to check for boundaries.
+// The caller should have checked the boundaries. If it did not we crash and
+// burn: this is a bug in MKL-DNN and throwing an exception would not have been
+// recoverable.
+//
+// On the other hand, insert() or resize() or a similar operation needs to
+// return a status because the outcome depends on factors external to the
+// caller. The situation is probably also not recoverable also, but MKL-DNN
+// needs to be nice and report "out of memory" to the users.
+
+enum nstl_status_t {
+ success = 0,
+ out_of_memory
+};
+
+template <typename T> class vector: public c_compatible {
+private:
+ std::vector<T> _impl;
+public:
+ typedef typename std::vector<T>::iterator iterator;
+ typedef typename std::vector<T>::const_iterator const_iterator;
+ typedef typename std::vector<T>::size_type size_type;
+ vector() {}
+ vector(size_type n): _impl(n) {}
+ vector(size_type n, const T &value): _impl(n, value) {}
+ template <typename input_iterator>
+ vector(input_iterator first, input_iterator last): _impl(first, last) {}
+ ~vector() {}
+ size_type size() const { return _impl.size(); }
+ T& operator[] (size_type i) { return _impl[i]; }
+ const T& operator[] (size_type i) const { return _impl[i]; }
+ iterator begin() { return _impl.begin(); }
+ const_iterator begin() const { return _impl.begin(); }
+ iterator end() { return _impl.end(); }
+ const_iterator end() const { return _impl.end(); }
+ template <typename input_iterator>
+ nstl_status_t insert(iterator pos, input_iterator begin, input_iterator end)
+ {
+ _impl.insert(pos, begin, end);
+ return success;
+ }
+ void clear() { _impl.clear(); }
+ void push_back(const T& t) { _impl.push_back(t); }
+ void resize(size_type count) { _impl.resize(count); }
+ void reserve(size_type count) { _impl.reserve(count); }
+};
+
+template <typename Key, typename T> class map: public c_compatible {
+private:
+ std::map<Key, T> _impl;
+public:
+ typedef typename std::map<Key, T>::iterator iterator;
+ typedef typename std::map<Key, T>::const_iterator const_iterator;
+ typedef typename std::map<Key, T>::size_type size_type;
+ map() {}
+ ~map() {}
+ size_type size() const { return _impl.size(); }
+ T& operator[](const Key &k) { return _impl[k]; }
+ const T& operator[](const Key &k) const { return _impl[k]; }
+ iterator begin() { return _impl.begin(); }
+ const_iterator begin() const { return _impl.begin(); }
+ iterator end() { return _impl.end(); }
+ const_iterator end() const { return _impl.end(); }
+ template <typename input_iterator>
+ void clear() { _impl.clear(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/pooling.cpp b/thirdparty/oidn/mkl-dnn/src/common/pooling.cpp
new file mode 100644
index 0000000000..be96e654ff
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/pooling.cpp
@@ -0,0 +1,114 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::alg_kind;
+using namespace mkldnn::impl::types;
+
+namespace {
+status_t pooling_desc_init(pooling_desc_t *pool_desc,
+ prop_kind_t prop_kind, alg_kind_t alg_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *dst_desc,
+ const dims_t strides, const dims_t kernel, const dims_t padding_l,
+ const dims_t padding_r, padding_kind_t padding_kind) {
+ bool args_ok = true
+ && !any_null(pool_desc, src_desc, dst_desc, strides, kernel, padding_l)
+ && one_of(alg_kind, pooling_max,
+ pooling_avg_include_padding,
+ pooling_avg_exclude_padding)
+ && one_of(padding_kind, padding_kind::padding_zero);
+ if (!args_ok) return invalid_arguments;
+
+ if (padding_r == nullptr) padding_r = padding_l;
+
+ auto pd = pooling_desc_t();
+ pd.primitive_kind = primitive_kind::pooling;
+ pd.prop_kind = prop_kind;
+ pd.alg_kind = alg_kind;
+ pd.src_desc.ndims = src_desc->ndims;
+
+ const bool is_fwd = one_of(prop_kind, forward_training, forward_inference);
+
+ pd.diff_src_desc = pd.src_desc = zero_md();
+ pd.diff_dst_desc = pd.dst_desc = zero_md();
+
+ (is_fwd ? pd.src_desc : pd.diff_src_desc) = *src_desc;
+ (is_fwd ? pd.dst_desc : pd.diff_dst_desc) = *dst_desc;
+
+ int sp_dims = src_desc->ndims - 2;
+ utils::array_copy(pd.strides, strides, sp_dims);
+ utils::array_copy(pd.kernel, kernel, sp_dims);
+ utils::array_copy(pd.padding[0], padding_l, sp_dims);
+ utils::array_copy(pd.padding[1], padding_r, sp_dims);
+
+ pd.padding_kind = padding_kind;
+ if (one_of(alg_kind, pooling_max, pooling_avg_include_padding,
+ pooling_avg_exclude_padding)) {
+ pd.accum_data_type = types::default_accum_data_type(
+ src_desc->data_type, dst_desc->data_type);
+ } else {
+ pd.accum_data_type = dst_desc->data_type;
+ }
+
+ bool consistency = true
+ && utils::one_of(src_desc->ndims, 4, 5)
+ && utils::one_of(dst_desc->ndims, 4, 5)
+ && src_desc->dims[0] == dst_desc->dims[0]
+ && src_desc->dims[1] == dst_desc->dims[1];
+ for (int i = 2; i < src_desc->ndims; ++i)
+ consistency = consistency && (
+ (src_desc->dims[i] - kernel[i - 2] + padding_l[i - 2]
+ + padding_r[i - 2]) / strides[i - 2] + 1
+ == dst_desc->dims[i]);
+ if (!consistency) return invalid_arguments;
+
+ *pool_desc = pd;
+ return success;
+}
+}
+
+status_t mkldnn_pooling_forward_desc_init(pooling_desc_t *pool_desc,
+ prop_kind_t prop_kind, alg_kind_t alg_kind,
+ const memory_desc_t *src_desc, const memory_desc_t *dst_desc,
+ const dims_t strides, const dims_t kernel, const dims_t padding_l,
+ const dims_t padding_r, padding_kind_t padding_kind) {
+ if (!one_of(prop_kind, forward_training, forward_inference))
+ return invalid_arguments;
+ return pooling_desc_init(pool_desc, prop_kind, alg_kind, src_desc,
+ dst_desc, strides, kernel, padding_l, padding_r, padding_kind);
+}
+
+status_t mkldnn_pooling_backward_desc_init(pooling_desc_t *pool_desc,
+ alg_kind_t alg_kind, const memory_desc_t *diff_src_desc,
+ const memory_desc_t *diff_dst_desc, const dims_t strides,
+ const dims_t kernel, const dims_t padding_l, const dims_t padding_r,
+ padding_kind_t padding_kind) {
+ return pooling_desc_init(pool_desc, prop_kind::backward_data, alg_kind,
+ diff_src_desc, diff_dst_desc, strides, kernel, padding_l,
+ padding_r, padding_kind);
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/pooling_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/pooling_pd.hpp
new file mode 100644
index 0000000000..4c9c009412
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/pooling_pd.hpp
@@ -0,0 +1,238 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef POOLING_PD_HPP
+#define POOLING_PD_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive_desc.hpp"
+#include "type_helpers.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct pooling_fwd_pd_t;
+
+struct pooling_pd_t: public primitive_desc_t {
+ static constexpr auto base_pkind = primitive_kind::pooling;
+
+ pooling_pd_t(engine_t *engine,
+ const pooling_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const pooling_fwd_pd_t *hint_fwd_pd)
+ : primitive_desc_t(engine, attr, base_pkind)
+ , desc_(*adesc)
+ , hint_fwd_pd_(hint_fwd_pd)
+ , ws_md_()
+ {}
+
+ const pooling_desc_t *desc() const { return &desc_; }
+ virtual const op_desc_t *op_desc() const override
+ { return reinterpret_cast<const op_desc_t *>(this->desc()); }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual status_t query(query_t what, int idx, void *result) const override {
+ switch (what) {
+ case query::pooling_d:
+ *(const pooling_desc_t**)result = desc(); break;
+ default: return primitive_desc_t::query(what, idx, result);
+ }
+ return status::success;
+ }
+
+ /* common pooling aux functions */
+
+ dim_t MB() const { return src_desc().dims[0]; }
+ dim_t C() const { return src_desc().dims[1]; }
+
+ dim_t ID() const { return ndims() >= 5 ? src_desc().dims[ndims() - 3] : 1; }
+ dim_t IH() const { return ndims() >= 4 ? src_desc().dims[ndims() - 2] : 1; }
+ dim_t IW() const { return src_desc().dims[ndims() - 1]; }
+
+ dim_t OD() const { return ndims() >= 5 ? dst_desc().dims[ndims() - 3] : 1; }
+ dim_t OH() const { return ndims() >= 4 ? dst_desc().dims[ndims() - 2] : 1; }
+ dim_t OW() const { return dst_desc().dims[ndims() - 1]; }
+
+ dim_t KD() const { return ndims() >= 5 ? desc_.kernel[ndims() - 5] : 1; }
+ dim_t KH() const { return ndims() >= 4 ? desc_.kernel[ndims() - 4] : 1; }
+ dim_t KW() const { return desc_.kernel[ndims() - 3]; }
+
+ dim_t KSD() const { return ndims() >= 5 ? desc_.strides[ndims() - 5] : 1; }
+ dim_t KSH() const { return ndims() >= 4 ? desc_.strides[ndims() - 4] : 1; }
+ dim_t KSW() const { return desc_.strides[ndims() - 3]; }
+
+ dim_t padFront() const
+ { return ndims() >= 5 ? desc_.padding[0][ndims() - 5] : 0; }
+ dim_t padBack() const
+ { return ndims() >= 5 ? desc_.padding[1][ndims() - 5] : 0; }
+ dim_t padT() const
+ { return ndims() >= 4 ? desc_.padding[0][ndims() - 4] : 0; }
+ dim_t padB() const
+ { return ndims() >= 4 ? desc_.padding[1][ndims() - 4] : 0; }
+ dim_t padL() const { return desc_.padding[0][ndims() - 3]; }
+ dim_t padR() const { return desc_.padding[1][ndims() - 3]; }
+
+ int ndims() const { return src_desc().ndims; }
+ bool is_3d() const { return ndims() == 5; }
+
+ bool has_zero_dim_memory() const
+ { return memory_desc_wrapper(src_desc()).has_zero_dim(); }
+
+ bool is_fwd() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ }
+
+protected:
+ pooling_desc_t desc_;
+ const pooling_fwd_pd_t *hint_fwd_pd_;
+
+ memory_desc_t ws_md_;
+
+ void init_default_ws() {
+ ws_md_ = is_fwd() ? *dst_md() : *diff_dst_md();
+ ws_md_.data_type = indices_data_type();
+ }
+
+ data_type_t indices_data_type() const {
+ /* the simplest way to express 256... */
+ const int u8_max = nstl::numeric_limits<
+ typename prec_traits<data_type::u8>::type>::max();
+ return utils::array_product(desc()->kernel, ndims()) <= u8_max
+ ? data_type::u8 : data_type::s32;
+ }
+
+private:
+ const memory_desc_t &src_desc() const
+ { return is_fwd() ? desc_.src_desc : desc_.diff_src_desc; }
+ const memory_desc_t &dst_desc() const
+ { return is_fwd() ? desc_.dst_desc : desc_.diff_dst_desc; }
+};
+
+struct pooling_fwd_pd_t: public pooling_pd_t {
+ typedef pooling_fwd_pd_t base_class;
+ typedef pooling_fwd_pd_t hint_class;
+
+ pooling_fwd_pd_t(engine_t *engine,
+ const pooling_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const pooling_fwd_pd_t *hint_fwd_pd)
+ : pooling_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , src_md_(desc_.src_desc)
+ , dst_md_(desc_.dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (arg == MKLDNN_ARG_SRC)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr))
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &src_md_ : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &dst_md_ : nullptr; }
+ virtual const memory_desc_t *workspace_md(int index = 0) const override
+ { return index == 0 && !types::is_zero_md(&ws_md_) ? &ws_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return 1; }
+ virtual int n_outputs() const override
+ { return 1 + (workspace_md() != nullptr); }
+
+protected:
+ memory_desc_t src_md_;
+ memory_desc_t dst_md_;
+
+ virtual status_t set_default_params() {
+ if (dst_md()->format_kind != format_kind::any)
+ return status::success;
+
+ if (src_md()->format_kind != format_kind::blocked)
+ return status::unimplemented;
+
+ return memory_desc_init_by_blocking_desc(dst_md_,
+ src_md_.format_desc.blocking);
+ }
+};
+
+struct pooling_bwd_pd_t: public pooling_pd_t {
+ typedef pooling_bwd_pd_t base_class;
+ typedef pooling_fwd_pd_t hint_class;
+
+ pooling_bwd_pd_t(engine_t *engine,
+ const pooling_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const pooling_fwd_pd_t *hint_fwd_pd)
+ : pooling_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , diff_src_md_(desc_.diff_src_desc)
+ , diff_dst_md_(desc_.diff_dst_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (arg == MKLDNN_ARG_DIFF_DST)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_SRC)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr))
+ return arg_usage_t::input;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *diff_src_md(int index = 0) const override
+ { return index == 0 ? &diff_src_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_dst_md_ : nullptr; }
+ virtual const memory_desc_t *workspace_md(int index = 0) const override
+ { return index == 0 && !types::is_zero_md(&ws_md_) ? &ws_md_ : nullptr; }
+
+ virtual int n_inputs() const override
+ { return 1 + (workspace_md() != nullptr); }
+ virtual int n_outputs() const override { return 1; }
+
+protected:
+ memory_desc_t diff_src_md_;
+ memory_desc_t diff_dst_md_;
+
+ virtual status_t set_default_params() {
+ if (diff_src_md()->format_kind != format_kind::any)
+ return status::success;
+
+ if (diff_dst_md()->format_kind != format_kind::blocked)
+ return status::unimplemented;
+
+ return memory_desc_init_by_blocking_desc(diff_src_md_,
+ diff_dst_md_.format_desc.blocking);
+ }
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive.cpp b/thirdparty/oidn/mkl-dnn/src/common/primitive.cpp
new file mode 100644
index 0000000000..fdf6522f62
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/primitive.cpp
@@ -0,0 +1,103 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "engine.hpp"
+#include "primitive_desc.hpp"
+#include "primitive.hpp"
+#include "type_helpers.hpp"
+#include "stream.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::primitive_kind;
+
+namespace {
+// XXX: this is a huge hammer. This disables all and any msan checks on
+// primitives outputs.
+//
+// A proper approach would be an implementation-specific unpoisoning.
+void unpoison_outputs(const exec_args_t &args) {
+ for(const auto &arg: args) {
+ if (arg.second.is_const) continue;
+ auto *mem = arg.second.mem;
+ void *p;
+ mem->get_data_handle(&p);
+ size_t s = memory_desc_wrapper(*mem->md()).size();
+ msan_unpoison(p, s);
+ }
+}
+}
+
+status_t mkldnn_primitive_desc_destroy(primitive_desc_t *primitive_desc) {
+ if (primitive_desc) delete primitive_desc;
+ return success;
+}
+
+status_t mkldnn_primitive_create(primitive_t **primitive,
+ const primitive_desc_t *primitive_desc) {
+ if (utils::any_null(primitive, primitive_desc))
+ return invalid_arguments;
+ return primitive_desc->create_primitive(primitive);
+}
+
+status_t mkldnn_primitive_execute(const primitive_t *primitive,
+ stream_t *stream, int nargs, const mkldnn_exec_arg_t *c_args) {
+ bool ok = true
+ && !utils::any_null(primitive, stream)
+ && primitive->engine() == stream->engine()
+ && IMPLICATION(nargs > 0, c_args != nullptr);
+ if (!ok) return invalid_arguments;
+
+ exec_args_t args;
+ status_t status = cvt_primtive_args(primitive->pd(), nargs, c_args, args);
+ if (status != status::success) return status;
+
+ exec_ctx_t ctx(stream, std::move(args));
+
+ if (mkldnn_verbose()->level) {
+ double ms = get_msec();
+ status = primitive->execute(ctx);
+ ms = get_msec() - ms;
+ printf("mkldnn_verbose,exec,%s,%g\n", primitive->pd()->info(), ms);
+ fflush(0);
+ } else {
+ status = primitive->execute(ctx);
+ }
+
+ if (msan_enabled) unpoison_outputs(ctx.args());
+
+ return status;
+}
+
+status_t mkldnn_primitive_get_primitive_desc(const primitive_t *primitive,
+ const primitive_desc_t **primitive_desc) {
+ if (utils::any_null(primitive, primitive_desc))
+ return invalid_arguments;
+ return safe_ptr_assign<const primitive_desc_t>(*primitive_desc,
+ primitive->pd());
+}
+
+status_t mkldnn_primitive_destroy(primitive_t *primitive) {
+ if (primitive != nullptr)
+ delete primitive;
+ return success;
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive.hpp b/thirdparty/oidn/mkl-dnn/src/common/primitive.hpp
new file mode 100644
index 0000000000..3b506d6d1f
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/primitive.hpp
@@ -0,0 +1,76 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef PRIMITIVE_HPP
+#define PRIMITIVE_HPP
+
+#include <assert.h>
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "primitive_desc.hpp"
+#include "primitive_exec_types.hpp"
+
+/** \brief A pure virtual primitive class
+ *
+ * Primitive contains links to its inputs & outputs, though it does not track
+ * their readiness on execution step.
+ *
+ * @remark @b Rational.
+ * Dependencies are essential through-out the whole MKL-DNN library, so it
+ * makes sense to include them on the very low level. On the other hand,
+ * tracking them should be a task for corresponding essence, like scheduler,
+ * stream or whatever. Primitive itself should know nothing about the
+ * environment it is running in.
+ *
+ * @note
+ * To make user experience better we should provide API which allows
+ * achieving the best (or good enough) performance when creating primitives
+ * in natural order: i.e. from bottom to top for forward pass and from top to
+ * bottom for backward pass. Please consider restriction [1] in Level 0.
+ */
+struct mkldnn_primitive: public mkldnn::impl::c_compatible {
+ mkldnn_primitive(const mkldnn::impl::primitive_desc_t *pd)
+ : pd_(pd->clone()) {}
+ virtual ~mkldnn_primitive() { delete pd_; }
+
+ /** returns primitive's engine */
+ mkldnn::impl::engine_t *engine() const { return pd_->engine(); }
+ /** returns primitive's inputs */
+ const mkldnn::impl::primitive_desc_t *pd() const { return pd_; }
+ /** returns primitive's kind */
+ mkldnn::impl::primitive_kind_t kind() const { return pd_->kind(); }
+
+ /** executes primitive with execution context @p ctx */
+ virtual mkldnn::impl::status_t execute(const mkldnn::impl::exec_ctx_t &ctx)
+ const = 0;
+
+protected:
+ const mkldnn::impl::primitive_desc_t *pd_;
+
+private:
+ mkldnn_primitive() = delete;
+ mkldnn_primitive(const mkldnn_primitive &) = delete;
+ mkldnn_primitive(mkldnn_primitive &&) = delete;
+ mkldnn_primitive &operator=(const mkldnn_primitive &) = delete;
+ mkldnn_primitive &operator=(mkldnn_primitive &&) = delete;
+};
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.cpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.cpp
new file mode 100644
index 0000000000..9fd638842c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.cpp
@@ -0,0 +1,290 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive_attr.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::utils;
+
+namespace mkldnn {
+namespace impl {
+
+status_t scales_t::set(dim_t count, int mask, const float *scales) {
+ cleanup();
+
+ count_ = count;
+ mask_ = mask;
+
+ if (count_ == 1) {
+ scales_ = scales_buf_;
+ utils::array_set(scales_, scales[0], scales_buf_size);
+ } else {
+ scales_ = (float *)impl::malloc(count_ * sizeof(*scales_), 64);
+ if (scales_ == nullptr)
+ return status::out_of_memory;
+
+ for (dim_t c = 0; c < count_; ++c)
+ scales_[c] = scales[c];
+ }
+
+ return status::success;
+}
+
+}
+}
+
+status_t post_ops_t::append_sum(float scale) {
+ if (len_ == capacity)
+ return out_of_memory;
+
+ entry_[len_].kind = primitive_kind::sum;
+ entry_[len_].sum.scale = scale;
+
+ len_++;
+
+ return success;
+}
+
+status_t post_ops_t::append_eltwise(float scale, alg_kind_t alg, float alpha,
+ float beta) {
+ using namespace mkldnn::impl::alg_kind;
+ bool known_alg = one_of(alg, eltwise_relu, eltwise_tanh, eltwise_elu,
+ eltwise_square, eltwise_abs, eltwise_sqrt, eltwise_linear,
+ eltwise_bounded_relu, eltwise_soft_relu, eltwise_logistic);
+ if (!known_alg)
+ return invalid_arguments;
+
+ if (len_ == capacity)
+ return out_of_memory;
+
+ entry_[len_].kind = primitive_kind::eltwise;
+ entry_[len_].eltwise.scale = scale;
+ entry_[len_].eltwise.alg = alg;
+ entry_[len_].eltwise.alpha = alpha;
+ entry_[len_].eltwise.beta = beta;
+
+ len_++;
+
+ return success;
+}
+
+status_t primitive_attr_t::set_scratchpad_mode(
+ scratchpad_mode_t scratchpad_mode) {
+ using namespace mkldnn::impl::scratchpad_mode;
+
+ const bool ok = one_of(scratchpad_mode, library, user);
+ if (!ok)
+ return invalid_arguments;
+
+ scratchpad_mode_ = scratchpad_mode;
+ return success;
+}
+
+status_t primitive_attr_t::set_post_ops(const post_ops_t &post_ops) {
+ this->post_ops_ = post_ops;
+ return success;
+}
+
+/* Public C API */
+
+status_t mkldnn_primitive_attr_create(primitive_attr_t **attr) {
+ if (attr == nullptr)
+ return invalid_arguments;
+
+ return safe_ptr_assign<mkldnn_primitive_attr>(*attr,
+ new mkldnn_primitive_attr);
+}
+
+status_t mkldnn_primitive_attr_clone(primitive_attr_t **attr,
+ const primitive_attr_t *existing_attr) {
+ if (any_null(attr, existing_attr))
+ return invalid_arguments;
+
+ return safe_ptr_assign<mkldnn_primitive_attr>(*attr,
+ existing_attr->clone());
+}
+
+status_t mkldnn_primitive_attr_destroy(primitive_attr_t *attr) {
+ if (attr)
+ delete attr;
+
+ return success;
+}
+
+status_t mkldnn_primitive_attr_get_scratchpad_mode(
+ const primitive_attr_t *attr, scratchpad_mode_t *scratchpad_mode) {
+ if (any_null(attr, scratchpad_mode))
+ return invalid_arguments;
+
+ *scratchpad_mode = attr->scratchpad_mode_;
+
+ return success;
+}
+
+status_t mkldnn_primitive_attr_set_scratchpad_mode(
+ primitive_attr_t *attr, scratchpad_mode_t scratchpad_mode) {
+ if (any_null(attr))
+ return invalid_arguments;
+
+ return attr->set_scratchpad_mode(scratchpad_mode);
+}
+
+status_t mkldnn_primitive_attr_get_output_scales(const primitive_attr_t *attr,
+ dim_t *count, int *mask, const float **scales) {
+ if (any_null(attr, count, mask, scales))
+ return invalid_arguments;
+
+ *count = attr->output_scales_.count_;
+ *mask = attr->output_scales_.mask_;
+ *scales = attr->output_scales_.scales_;
+
+ return success;
+}
+
+status_t mkldnn_primitive_attr_set_output_scales(primitive_attr_t *attr,
+ dim_t count, int mask, const float *scales) {
+ bool ok = !any_null(attr, scales) && count > 0 && mask >= 0;
+ if (!ok)
+ return invalid_arguments;
+
+ return attr->output_scales_.set(count, mask, scales);
+}
+
+status_t mkldnn_primitive_attr_get_post_ops(const primitive_attr_t *attr,
+ const post_ops_t **post_ops) {
+ if (any_null(attr, post_ops))
+ return invalid_arguments;
+
+ *post_ops = &attr->post_ops_;
+ return success;
+}
+
+status_t mkldnn_primitive_attr_set_post_ops(primitive_attr_t *attr,
+ const post_ops_t *post_ops) {
+ if (any_null(attr, post_ops))
+ return invalid_arguments;
+
+ return attr->set_post_ops(*post_ops);
+}
+
+status_t mkldnn_post_ops_create(post_ops_t **post_ops) {
+ if (post_ops == nullptr)
+ return invalid_arguments;
+
+ return safe_ptr_assign<mkldnn_post_ops>(*post_ops, new mkldnn_post_ops);
+}
+
+status_t mkldnn_post_ops_destroy(post_ops_t *post_ops) {
+ if (post_ops)
+ delete post_ops;
+
+ return success;
+}
+
+int mkldnn_post_ops_len(const post_ops_t *post_ops) {
+ if (post_ops)
+ return post_ops->len_;
+
+ return 0;
+}
+
+primitive_kind_t mkldnn_post_ops_get_kind(const post_ops_t *post_ops,
+ int index) {
+ bool ok = post_ops && 0 <= index && index < post_ops->len_;
+ if (!ok)
+ return primitive_kind::undefined;
+
+ return post_ops->entry_[index].kind;
+}
+
+status_t mkldnn_post_ops_append_sum(post_ops_t *post_ops, float scale) {
+ if (post_ops == nullptr)
+ return invalid_arguments;
+
+ return post_ops->append_sum(scale);
+}
+
+namespace {
+bool simple_get_params_check(const post_ops_t *post_ops, int index,
+ primitive_kind_t kind) {
+ bool ok = true
+ && post_ops != nullptr
+ && 0 <= index
+ && index < post_ops->len_
+ && post_ops->entry_[index].kind == kind;
+ return ok;
+}
+}
+
+status_t mkldnn_post_ops_get_params_sum(const post_ops_t *post_ops, int index,
+ float *scale) {
+ bool ok = true
+ && simple_get_params_check(post_ops, index, primitive_kind::sum)
+ && !any_null(scale);
+ if (!ok)
+ return invalid_arguments;
+
+ *scale = post_ops->entry_[index].sum.scale;
+ return success;
+}
+
+status_t mkldnn_post_ops_append_eltwise(post_ops_t *post_ops, float scale,
+ alg_kind_t kind, float alpha, float beta) {
+ if (post_ops == nullptr)
+ return invalid_arguments;
+
+ return post_ops->append_eltwise(scale, kind, alpha, beta);
+}
+
+status_t mkldnn_post_ops_get_params_eltwise(const post_ops_t *post_ops,
+ int index, float *scale, alg_kind_t *alg, float *alpha, float *beta) {
+ bool ok = true
+ && simple_get_params_check(post_ops, index, primitive_kind::eltwise)
+ && !any_null(scale, alpha, beta);
+ if (!ok)
+ return invalid_arguments;
+
+ const auto &e = post_ops->entry_[index].eltwise;
+ *scale = e.scale;
+ *alg = e.alg;
+ *alpha = e.alpha;
+ *beta = e.beta;
+
+ return success;
+}
+
+status_t mkldnn_primitive_attr_set_rnn_data_qparams(
+ primitive_attr_t *attr, const float scale, const float shift) {
+ if (attr == nullptr)
+ return invalid_arguments;
+
+ return attr->rnn_data_qparams_.set(scale, shift);
+}
+
+status_t mkldnn_primitive_attr_set_rnn_weights_qparams(
+ primitive_attr_t *attr, dim_t count, int mask, const float *scales) {
+ bool ok = !any_null(attr, scales) && count > 0 && mask >= 0;
+ if (!ok)
+ return invalid_arguments;
+
+ return attr->rnn_weights_qparams_.set(count, mask, scales);
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.hpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.hpp
new file mode 100644
index 0000000000..e2130c7ab1
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_attr.hpp
@@ -0,0 +1,183 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef PRIMITIVE_ATTR_HPP
+#define PRIMITIVE_ATTR_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct rnn_data_qparams_t : public c_compatible {
+ rnn_data_qparams_t() : scale_(1.), shift_(0.) {}
+ bool has_default_values() const { return (scale_ == 1. && shift_ == 0.); }
+
+ status_t set(float scale, float shift) {
+ scale_ = scale;
+ shift_ = shift;
+ return status::success;
+ }
+
+ float scale_;
+ float shift_;
+};
+
+struct scales_t: public c_compatible {
+ scales_t(): count_(1), mask_(0), scales_(scales_buf_)
+ { set(1.); }
+
+ scales_t(const scales_t &rhs): scales_t()
+ { set(rhs.count_, rhs.mask_, rhs.scales_); }
+
+ ~scales_t() { cleanup(); }
+
+ scales_t &operator=(const scales_t &rhs) {
+ if (&rhs == this)
+ return *this;
+ status_t status = set(rhs.count_, rhs.mask_, rhs.scales_);
+ assert(status == status::success);
+ (void)status;
+ return *this;
+ }
+
+ bool has_default_values() const {
+ for (dim_t c = 0; c < count_; ++c) {
+ if(scales_[c] != 1.) return false;
+ }
+ return true;
+ }
+
+ status_t set(dim_t count, int mask, const float *scales);
+ status_t set(float single_scale) { return this->set(1, 0, &single_scale); }
+
+ dim_t count_;
+ int mask_;
+ float *scales_;
+
+private:
+ enum { scales_buf_size = 16 };
+ float scales_buf_[scales_buf_size];
+
+ void cleanup() {
+ if (scales_ != scales_buf_ && scales_ != nullptr)
+ impl::free(scales_);
+
+ count_ = 1;
+ mask_ = 0;
+ scales_ = scales_buf_;
+ }
+};
+
+}
+}
+
+struct mkldnn_post_ops: public mkldnn::impl::c_compatible {
+ struct entry_t {
+ struct eltwise_t {
+ mkldnn::impl::alg_kind_t alg;
+ float scale, alpha, beta;
+ };
+
+ mkldnn::impl::primitive_kind_t kind;
+ union {
+ struct { float scale; } sum;
+ eltwise_t eltwise;
+ };
+
+ bool is_eltwise(bool require_scale_one = true) const {
+ using namespace mkldnn::impl;
+ return kind == primitive_kind::eltwise
+ && IMPLICATION(require_scale_one, eltwise.scale == 1.f);
+ }
+
+ bool is_relu(bool require_scale_one = true,
+ bool require_nslope_zero = true) const {
+ using namespace mkldnn::impl;
+ return is_eltwise(require_scale_one)
+ && eltwise.alg == alg_kind::eltwise_relu
+ && IMPLICATION(require_nslope_zero, eltwise.alpha == 0.f);
+ }
+
+ bool is_sum(bool require_scale_one = true) const {
+ using namespace mkldnn::impl;
+ return kind == primitive_kind::sum
+ && IMPLICATION(require_scale_one, sum.scale == 1.f);
+ }
+ };
+
+ mkldnn_post_ops(): len_(0) {}
+
+ mkldnn::impl::status_t append_sum(float scale);
+ mkldnn::impl::status_t append_eltwise(float scale,
+ mkldnn::impl::alg_kind_t alg, float alpha, float beta);
+
+ int find(mkldnn::impl::primitive_kind_t kind, int start = 0,
+ int stop = -1) const {
+ if (stop == -1) stop = len_;
+ stop = mkldnn::impl::nstl::min(stop, len_);
+ for (int idx = start; idx < stop; ++idx)
+ if (entry_[idx].kind == kind) return idx;
+ return -1;
+ }
+
+ bool has_default_values() const { return len_ == 0; }
+
+ bool contain(mkldnn::impl::primitive_kind_t kind, int index) const
+ { return find(kind, index, index + 1) == index; }
+
+ enum { capacity = 4 };
+
+ int len_;
+ entry_t entry_[capacity];
+};
+
+struct mkldnn_primitive_attr: public mkldnn::impl::c_compatible {
+ mkldnn_primitive_attr()
+ : scratchpad_mode_(mkldnn::impl::scratchpad_mode::library)
+ {}
+
+ mkldnn_primitive_attr *clone() const
+ { return new mkldnn_primitive_attr(*this); }
+
+ /** Returns true if the attributes have default values.
+ *
+ * @note The scratchpad_mode_ is not take into account */
+ bool has_default_values() const {
+ return true
+ && output_scales_.has_default_values()
+ && post_ops_.has_default_values()
+ && rnn_data_qparams_.has_default_values()
+ && rnn_weights_qparams_.has_default_values();
+ }
+
+ mkldnn::impl::status_t set_scratchpad_mode(
+ mkldnn::impl::scratchpad_mode_t scratchpad_mode);
+ mkldnn::impl::status_t set_post_ops(
+ const mkldnn::impl::post_ops_t &post_ops);
+
+ mkldnn::impl::scratchpad_mode_t scratchpad_mode_;
+ mkldnn::impl::scales_t output_scales_;
+ mkldnn::impl::post_ops_t post_ops_;
+ mkldnn::impl::rnn_data_qparams_t rnn_data_qparams_;
+ mkldnn::impl::scales_t rnn_weights_qparams_;
+};
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.cpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.cpp
new file mode 100644
index 0000000000..723c41e05a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.cpp
@@ -0,0 +1,78 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "primitive_desc.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::status;
+
+status_t primitive_desc_t::query(query_t what, int idx, void *result) const {
+ auto safe_ret_md = [&](const memory_desc_t *_) {
+ if (_ == nullptr) return not_required;
+ *(const memory_desc_t **)result = _;
+ return success;
+ };
+
+ switch (what) {
+ case query::engine: *(engine_t**)result = engine(); break;
+ case query::primitive_kind: *(primitive_kind_t*)result = kind(); break;
+
+ case query::scratchpad_engine:
+ *(engine_t**)result = scratchpad_engine(); break;
+
+ case query::memory_consumption_s64:
+ *(dim_t *)result = scratchpad_size(scratchpad_mode::library); break;
+
+ case query::op_d:
+ if (idx != 0 || op_desc() == nullptr) return invalid_arguments;
+ *(const_c_op_desc_t *)result
+ = static_cast<const_c_op_desc_t>(op_desc()); break;
+
+ case query::src_md: return safe_ret_md(src_md(idx));
+ case query::diff_src_md: return safe_ret_md(diff_src_md(idx));
+ case query::dst_md: return safe_ret_md(dst_md(idx));
+ case query::diff_dst_md: return safe_ret_md(diff_dst_md(idx));
+ case query::weights_md: return safe_ret_md(weights_md(idx));
+ case query::diff_weights_md: return safe_ret_md(diff_weights_md(idx));
+ case query::workspace_md:
+ if (idx != 0) return status::invalid_arguments;
+ return safe_ret_md(workspace_md(idx));
+ case query::scratchpad_md:
+ if (idx != 0) return status::invalid_arguments;
+ return safe_ret_md(scratchpad_md(idx));
+
+ case query::num_of_inputs_s32: *(int*)result = n_inputs(); break;
+ case query::num_of_outputs_s32: *(int*)result = n_outputs(); break;
+
+ case query::impl_info_str: *(const char **)result = name(); break;
+
+ default: return unimplemented;
+ }
+ return success;
+}
+
+status_t mkldnn_primitive_desc_get_attr(const primitive_desc_t *primitive_desc,
+ const primitive_attr_t **attr) {
+ if (utils::any_null(primitive_desc, attr))
+ return invalid_arguments;
+
+ *attr = primitive_desc->attr();
+ return success;
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.hpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.hpp
new file mode 100644
index 0000000000..536dcfa1d0
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_desc.hpp
@@ -0,0 +1,174 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef PRIMITIVE_DESC_HPP
+#define PRIMITIVE_DESC_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "primitive_attr.hpp"
+#include "verbose.hpp"
+
+struct mkldnn_primitive_desc: public mkldnn::impl::c_compatible {
+ using md_t = mkldnn::impl::memory_desc_t;
+
+ mkldnn_primitive_desc(mkldnn::impl::engine_t *engine,
+ const mkldnn::impl::primitive_attr_t *attr,
+ mkldnn::impl::primitive_kind_t kind)
+ : engine_(engine), attr_(*attr), kind_(kind) { info_[0] = '\0'; }
+
+ mkldnn_primitive_desc(mkldnn::impl::engine_t *engine,
+ mkldnn::impl::primitive_kind_t kind)
+ : engine_(engine), kind_(kind) { info_[0] = '\0'; }
+
+ virtual mkldnn_primitive_desc *clone() const = 0;
+ virtual ~mkldnn_primitive_desc() {}
+
+ const mkldnn::impl::primitive_attr_t *attr() const { return &attr_; }
+ mkldnn::impl::engine_t *engine() const { return engine_; }
+ mkldnn::impl::primitive_kind_t kind() const { return kind_; }
+
+ virtual void init_info() {}
+ const char *info() const { return info_; }
+
+ mkldnn::impl::memory_tracking::registry_t &scratchpad_registry()
+ { return scratchpad_registry_; }
+ const mkldnn::impl::memory_tracking::registry_t &scratchpad_registry() const
+ { return scratchpad_registry_; }
+ virtual mkldnn::impl::engine_t *scratchpad_engine() const
+ { return engine_; }
+
+ virtual const mkldnn::impl::op_desc_t *op_desc() const { return nullptr; }
+
+ enum class arg_usage_t { unused, input, output };
+ virtual arg_usage_t arg_usage(
+ mkldnn::impl::primitive_arg_index_t arg) const {
+ using mkldnn::impl::types::is_zero_md;
+ if (arg == MKLDNN_ARG_SCRATCHPAD && !is_zero_md(scratchpad_md()))
+ return arg_usage_t::output;
+ return arg_usage_t::unused;
+ }
+
+# define DECLARE_MD_STUB(stub) \
+ virtual const mkldnn::impl::memory_desc_t *stub(int idx = 0) const \
+ { return nullptr; }
+
+ DECLARE_MD_STUB(input_md); DECLARE_MD_STUB(output_md);
+ DECLARE_MD_STUB(src_md); DECLARE_MD_STUB(diff_src_md);
+ DECLARE_MD_STUB(dst_md); DECLARE_MD_STUB(diff_dst_md);
+ DECLARE_MD_STUB(weights_md); DECLARE_MD_STUB(diff_weights_md);
+ DECLARE_MD_STUB(workspace_md);
+# undef DECLARE_MD_STUB
+
+ const mkldnn::impl::memory_desc_t *scratchpad_md(int idx = 0) const {
+ return idx == 0 ? &scratchpad_md_ : nullptr;
+ }
+
+ virtual void init_scratchpad_md() {
+ auto size = scratchpad_size(mkldnn::impl::scratchpad_mode::user);
+ mkldnn::impl::dims_t dims = { size };
+ mkldnn_memory_desc_init_by_tag(&scratchpad_md_, size ? 1 : 0, dims,
+ mkldnn::impl::data_type::u8, mkldnn_x);
+ }
+
+ /** returns the scratchpad size for the given scratchpad mode. */
+ mkldnn::impl::dim_t scratchpad_size(
+ mkldnn::impl::scratchpad_mode_t mode) const {
+ if (mode != attr_.scratchpad_mode_) return 0;
+ return scratchpad_registry().size();
+ }
+
+ virtual int n_inputs() const { return 0; }
+ virtual int n_outputs() const { return 0; }
+
+ virtual mkldnn::impl::status_t query(mkldnn::impl::query_t what, int idx,
+ void *result) const;
+
+ virtual mkldnn::impl::status_t create_primitive(
+ mkldnn::impl::primitive_t **primitive) const = 0;
+
+ virtual const char *name() const { return "mkldnn_primitive_desc"; }
+
+ /* static magic */
+
+ template<typename pd_t>
+ static mkldnn::impl::status_t create(mkldnn::impl::primitive_desc_t **pd,
+ const mkldnn::impl::op_desc_t *adesc,
+ const mkldnn::impl::primitive_attr_t *attr,
+ mkldnn::impl::engine_t *engine,
+ const mkldnn::impl::primitive_desc_t *hint_fwd) {
+ using namespace mkldnn::impl;
+ using namespace mkldnn::impl::status;
+ using pd_op_desc_t = typename pkind_traits<pd_t::base_pkind>::desc_type;
+ if (adesc->kind != pd_t::base_pkind) return invalid_arguments;
+ assert(hint_fwd ? hint_fwd->kind() == pd_t::base_pkind : true);
+ auto hint =
+ reinterpret_cast<const typename pd_t::hint_class *>(hint_fwd);
+ auto _pd = new pd_t(engine, (const pd_op_desc_t *)adesc, attr, hint);
+ if (_pd == nullptr) return out_of_memory;
+ if (_pd->init() != success) { delete _pd; return unimplemented; }
+ _pd->init_info();
+ _pd->init_scratchpad_md();
+ *pd = _pd;
+ return success;
+ }
+
+protected:
+ mkldnn::impl::engine_t *engine_;
+ mkldnn::impl::primitive_attr_t attr_;
+ mkldnn::impl::primitive_kind_t kind_;
+
+ mkldnn::impl::memory_desc_t scratchpad_md_;
+
+ char info_[MKLDNN_VERBOSE_BUF_LEN];
+
+ mkldnn::impl::memory_tracking::registry_t scratchpad_registry_;
+
+protected:
+ /** compares ws between fwd_pd and this (make sense to use for bwd_pd)
+ * Expectation: this already set workspace, and this workspace should
+ * exactly match the one from fwd_pd */
+ bool compare_ws(const mkldnn_primitive_desc *fwd_pd) const {
+ using namespace mkldnn::impl;
+ if (!workspace_md()) return true; // the impl lives fine w/o workspace
+ return fwd_pd && fwd_pd->workspace_md()
+ && *fwd_pd->workspace_md() == *workspace_md();
+ }
+};
+
+#define DECLARE_COMMON_PD_t(impl_name, ...) \
+ virtual pd_t *clone() const override { return new pd_t(*this); } \
+ virtual status_t create_primitive(primitive_t **p) const override { \
+ double ms = get_msec(); \
+ auto ret = safe_ptr_assign<primitive_t>(*p, new (__VA_ARGS__)(this)); \
+ ms = get_msec() - ms; \
+ if (mkldnn_verbose()->level >= 2) { \
+ printf("mkldnn_verbose,create,%s,%g\n", this->info(), ms); \
+ fflush(0); \
+ } \
+ return ret; \
+ } \
+ virtual const char *name() const override { return impl_name; }
+#define DECLARE_COMMON_PD_T(impl_name, ...) \
+ DECLARE_COMMON_PD_t(impl_name, __VA_ARGS__)
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.cpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.cpp
new file mode 100644
index 0000000000..43e5a31ef3
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.cpp
@@ -0,0 +1,90 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "memory.hpp"
+#include "primitive.hpp"
+#include "primitive_exec_types.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+status_t cvt_primtive_args(const primitive_desc_t *pd, int nargs,
+ const mkldnn_exec_arg_t *c_args, exec_args_t &args) {
+ using namespace status;
+
+ if (!IMPLICATION(nargs > 0, c_args != nullptr)) return invalid_arguments;
+
+ int n_inputs = 0;
+ int n_outputs = 0;
+
+ for (int i = 0; i < nargs; ++i) {
+ primitive_arg_index_t arg = c_args[i].arg;
+ auto *mem = c_args[i].memory;
+
+ switch (pd->arg_usage(arg)) {
+ case primitive_desc_t::arg_usage_t::input:
+ if (args.count(arg) != 0) return invalid_arguments;
+ args[arg] = {mem, true};
+ n_inputs++;
+ break;
+ case primitive_desc_t::arg_usage_t::output:
+ if (args.count(arg) != 0) return invalid_arguments;
+ args[arg] = {mem, false};
+ n_outputs++;
+ break;
+ case primitive_desc_t::arg_usage_t::unused:
+ break;
+ }
+ }
+
+ bool scratchpad_required = !types::is_zero_md(pd->scratchpad_md());
+
+ if (n_inputs != pd->n_inputs()) return invalid_arguments;
+ if (n_outputs != pd->n_outputs() + (scratchpad_required ? 1 : 0))
+ return invalid_arguments;
+
+ return success;
+}
+
+const void *exec_ctx_t::input(primitive_arg_index_t arg) const {
+ if (args_.count(arg) != 1) return nullptr;
+ const auto ma = args_.at(arg);
+ assert(ma.is_const);
+ void *ptr;
+ status_t status = ma.mem->get_data_handle(&ptr);
+ assert(status == status::success); MAYBE_UNUSED(status);
+ return ptr;
+}
+
+void *exec_ctx_t::output(primitive_arg_index_t arg) const {
+ if (args_.count(arg) != 1) return nullptr;
+ const auto ma = args_.at(arg);
+ assert(!ma.is_const);
+ void *ptr;
+ status_t status = ma.mem->get_data_handle(&ptr);
+ assert(status == status::success); MAYBE_UNUSED(status);
+ return ptr;
+}
+
+const memory_t *exec_ctx_t::memory(primitive_arg_index_t arg) const {
+ assert(args_.count(arg) == 1);
+ const auto ma = args_.at(arg);
+ assert(!ma.is_const);
+ return ma.mem;
+}
+
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.hpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.hpp
new file mode 100644
index 0000000000..0645891da7
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_exec_types.hpp
@@ -0,0 +1,68 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef PRIMITIVE_EXEC_TYPES_HPP
+#define PRIMITIVE_EXEC_TYPES_HPP
+
+#include <unordered_map>
+
+#include "mkldnn_types.h"
+
+#include "c_types_map.hpp"
+#include "memory.hpp"
+#include "primitive_desc.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct memory_arg_t {
+ memory_t *mem;
+ bool is_const;
+};
+
+using exec_args_t = std::unordered_map<primitive_arg_index_t, memory_arg_t>;
+
+status_t cvt_primtive_args(const primitive_desc_t *pd, int nargs,
+ const mkldnn_exec_arg_t *c_args, exec_args_t &args);
+
+/** Primitive execution context (helps passing stream, memories, and events. */
+struct exec_ctx_t {
+ exec_ctx_t(const exec_ctx_t &) = default;
+ exec_ctx_t(exec_ctx_t &&) = default;
+
+ exec_ctx_t(stream_t *stream): stream_(stream) {}
+ exec_ctx_t(stream_t *stream, exec_args_t &&args)
+ : stream_(stream)
+ , args_(std::move(args)) {}
+
+ stream_t *stream() const { return stream_; }
+ const exec_args_t &args() const { return args_; }
+
+ /* tentative solution... TODO: replace with functions return memory_t */
+ const void *input(primitive_arg_index_t arg) const;
+ void *output(primitive_arg_index_t arg) const;
+
+ const memory_t *memory(primitive_arg_index_t arg) const;
+
+private:
+ stream_t *stream_;
+ exec_args_t args_;
+};
+
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.cpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.cpp
new file mode 100644
index 0000000000..5a1cd7d379
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.cpp
@@ -0,0 +1,89 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "engine.hpp"
+#include "primitive_desc.hpp"
+#include "type_helpers.hpp"
+#include "primitive_iterator.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::status;
+
+status_t mkldnn_primitive_desc_iterator_create(
+ primitive_desc_iterator_t **iterator, const_c_op_desc_t c_op_desc,
+ const primitive_attr_t *attr, engine_t *engine,
+ const primitive_desc_t *hint_fwd_pd) {
+ const op_desc_t *op_desc = (const op_desc_t *)c_op_desc;
+
+ auto it = new primitive_desc_iterator_t(engine, op_desc, attr, hint_fwd_pd);
+ if (it == nullptr) return out_of_memory;
+
+ ++(*it);
+ if (*it == it->end()) {
+ delete it;
+ return unimplemented;
+ }
+
+ *iterator = it;
+ return success;
+}
+
+status_t mkldnn_primitive_desc_iterator_next(
+ primitive_desc_iterator_t *iterator) {
+ if (iterator == nullptr) return invalid_arguments;
+ ++(*iterator);
+ return *iterator == iterator->end() ? iterator_ends : success;
+}
+
+primitive_desc_t *mkldnn_primitive_desc_iterator_fetch(
+ const primitive_desc_iterator_t *iterator) {
+ if (iterator == nullptr) return nullptr;
+ return *(*iterator);
+}
+
+status_t mkldnn_primitive_desc_clone(primitive_desc_t **primitive_desc,
+ const primitive_desc_t *existing_primitive_desc) {
+ if (utils::any_null(primitive_desc, existing_primitive_desc))
+ return invalid_arguments;
+ return safe_ptr_assign<primitive_desc_t>(*primitive_desc,
+ existing_primitive_desc->clone());
+}
+
+status_t mkldnn_primitive_desc_iterator_destroy(
+ primitive_desc_iterator_t *iterator) {
+ if (iterator != nullptr)
+ delete iterator;
+ return success;
+}
+
+status_t mkldnn_primitive_desc_create(primitive_desc_t **primitive_desc,
+ const_c_op_desc_t c_op_desc, const primitive_attr_t *attr,
+ engine_t *engine, const primitive_desc_t *hint_fwd_pd) {
+ const op_desc_t *op_desc = (const op_desc_t *)c_op_desc;
+
+ mkldnn_primitive_desc_iterator it(engine, op_desc, attr, hint_fwd_pd);
+ ++it;
+ if (it == it.end()) return unimplemented;
+
+ return safe_ptr_assign<primitive_desc_t>(*primitive_desc, *it);
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.hpp b/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.hpp
new file mode 100644
index 0000000000..4e88ab3aa5
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/primitive_iterator.hpp
@@ -0,0 +1,79 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+#ifndef PRIMITIVE_ITERATOR_HPP
+#define PRIMITIVE_ITERATOR_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "engine.hpp"
+#include "primitive_desc.hpp"
+#include "type_helpers.hpp"
+
+struct mkldnn_primitive_desc_iterator: public mkldnn::impl::c_compatible {
+ using pd_create_f = mkldnn::impl::engine_t::primitive_desc_create_f;
+
+ mkldnn_primitive_desc_iterator(mkldnn::impl::engine_t *engine, const mkldnn::impl::op_desc_t *op_desc,
+ const mkldnn::impl::primitive_attr_t *attr, const mkldnn::impl::primitive_desc_t *hint_fwd_pd)
+ : idx_(-1), engine_(engine), pd_(nullptr), op_desc_(op_desc)
+ , attr_(attr ? *attr : mkldnn::impl::primitive_attr_t()), hint_fwd_pd_(hint_fwd_pd)
+ , impl_list_(engine_->get_implementation_list()), last_idx_(0)
+ {
+ while (impl_list_[last_idx_] != nullptr) ++last_idx_;
+ }
+ ~mkldnn_primitive_desc_iterator() { if (pd_) delete pd_; }
+
+ bool operator==(const mkldnn::impl::primitive_desc_iterator_t& rhs) const
+ { return idx_ == rhs.idx_ && engine_ == rhs.engine_; }
+ bool operator!=(const mkldnn::impl::primitive_desc_iterator_t& rhs) const
+ { return !operator==(rhs); }
+
+ mkldnn::impl::primitive_desc_iterator_t end() const
+ { return mkldnn_primitive_desc_iterator(engine_, last_idx_); }
+
+ mkldnn::impl::primitive_desc_iterator_t &operator++() {
+ if (pd_) { delete pd_; pd_ = nullptr; }
+ while (++idx_ != last_idx_) {
+ auto s = impl_list_[idx_](&pd_, op_desc_, &attr_, engine_,
+ hint_fwd_pd_);
+ if (s == mkldnn::impl::status::success) break;
+ }
+ return *this;
+ }
+
+ mkldnn::impl::primitive_desc_t *operator*() const {
+ if (*this == end() || pd_ == nullptr) return nullptr;
+ return pd_->clone();
+ }
+
+protected:
+ int idx_;
+ mkldnn::impl::engine_t *engine_;
+ mkldnn::impl::primitive_desc_t *pd_;
+ const mkldnn::impl::op_desc_t *op_desc_;
+ const mkldnn::impl::primitive_attr_t attr_;
+ const mkldnn::impl::primitive_desc_t *hint_fwd_pd_;
+ const pd_create_f *impl_list_;
+ int last_idx_;
+
+private:
+ mkldnn_primitive_desc_iterator(mkldnn::impl::engine_t *engine, int last_idx)
+ : idx_(last_idx), engine_(engine), pd_(nullptr)
+ , op_desc_(nullptr), hint_fwd_pd_(nullptr)
+ , impl_list_(nullptr), last_idx_(last_idx) {}
+};
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/query.cpp b/thirdparty/oidn/mkl-dnn/src/common/query.cpp
new file mode 100644
index 0000000000..835cd73581
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/query.cpp
@@ -0,0 +1,59 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "engine.hpp"
+#include "primitive_desc.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+
+status_t mkldnn_primitive_desc_query(const primitive_desc_t *primitive_desc,
+ query_t what, int index, void *result) {
+ if (any_null(primitive_desc, result))
+ return invalid_arguments;
+
+ return primitive_desc->query(what, index, result);
+}
+
+const memory_desc_t *mkldnn_primitive_desc_query_md(
+ const primitive_desc_t *primitive_desc, query_t what, int index) {
+ const memory_desc_t *res_md = nullptr;
+ bool args_ok = true
+ && primitive_desc != nullptr
+ && (what & query::some_md) == query::some_md
+ && what != query::some_md
+ && mkldnn_primitive_desc_query(primitive_desc,
+ what, index, &res_md) == success;
+ return args_ok ? res_md : nullptr;
+}
+
+int mkldnn_primitive_desc_query_s32(const primitive_desc_t *primitive_desc,
+ query_t what, int index) {
+ int res_s32;
+ bool args_ok = primitive_desc != nullptr
+ && one_of(what, query::num_of_inputs_s32, query::num_of_outputs_s32)
+ && mkldnn_primitive_desc_query(primitive_desc, what, index, &res_s32)
+ == success;
+ return args_ok ? res_s32 : 0;
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/reorder.cpp b/thirdparty/oidn/mkl-dnn/src/common/reorder.cpp
new file mode 100644
index 0000000000..d11f1a0361
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/reorder.cpp
@@ -0,0 +1,68 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "engine.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "reorder_pd.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+
+status_t mkldnn_reorder_primitive_desc_create(
+ primitive_desc_t **reorder_pd,
+ engine_t *src_engine, const memory_desc_t *src_md,
+ engine_t *dst_engine, const memory_desc_t *dst_md,
+ const primitive_attr_t *attr) {
+ if (any_null(reorder_pd, src_engine, src_md, dst_engine, dst_md))
+ return invalid_arguments;
+
+ auto s_ek = src_engine->kind();
+ auto d_ek = dst_engine->kind();
+ if (!IMPLICATION(s_ek != d_ek, one_of(engine_kind::cpu, s_ek, d_ek)))
+ return invalid_arguments;
+
+ auto r_pd = reinterpret_cast<reorder_pd_t **>(reorder_pd);
+ auto s_mdw = memory_desc_wrapper(*src_md);
+ auto d_mdw = memory_desc_wrapper(*dst_md);
+
+ if (!s_mdw.consistent_with(d_mdw))
+ return invalid_arguments;
+
+ auto e = (s_ek != engine_kind::cpu) ? src_engine : dst_engine;
+
+ const primitive_attr_t dummy_attr;
+ if (attr == NULL)
+ attr = &dummy_attr;
+
+ for (auto r = e->get_reorder_implementation_list(); *r; ++r) {
+ if ((*r)(r_pd, e, attr, src_engine, src_md, dst_engine, dst_md)
+ == success) {
+ (*r_pd)->init_info();
+ (*r_pd)->init_scratchpad_md();
+ return success;
+ }
+ }
+ return unimplemented;
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/reorder_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/reorder_pd.hpp
new file mode 100644
index 0000000000..963cb0f58a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/reorder_pd.hpp
@@ -0,0 +1,85 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef REORDER_PD_HPP
+#define REORDER_PD_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "primitive_attr.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct reorder_pd_t: public primitive_desc_t {
+ reorder_pd_t(engine_t *engine, const primitive_attr_t *attr,
+ engine_t *src_engine, const memory_desc_t *src_md,
+ engine_t *dst_engine, const memory_desc_t *dst_md)
+ : primitive_desc_t(engine, attr, primitive_kind::reorder)
+ , src_engine_(src_engine)
+ , dst_engine_(dst_engine)
+ , scratchpad_engine_(nullptr)
+ , src_md_(*src_md)
+ , dst_md_(*dst_md)
+ {}
+
+ virtual const op_desc_t *op_desc() const override { return nullptr; }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (arg == MKLDNN_ARG_FROM)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_TO)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &src_md_ : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &dst_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return 1; }
+ virtual int n_outputs() const override { return 1; }
+
+ float alpha() const { return attr()->output_scales_.scales_[0]; }
+ float beta() const {
+ const int sum_idx = attr()->post_ops_.find(primitive_kind::sum);
+ return sum_idx == -1 ? 0 : attr()->post_ops_.entry_[sum_idx].sum.scale;
+ }
+ virtual mkldnn::impl::engine_t *scratchpad_engine() const override
+ { return scratchpad_engine_; }
+
+protected:
+ engine_t *src_engine_;
+ engine_t *dst_engine_;
+ engine_t *scratchpad_engine_;
+
+ memory_desc_t src_md_;
+ memory_desc_t dst_md_;
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/rnn.cpp b/thirdparty/oidn/mkl-dnn/src/common/rnn.cpp
new file mode 100644
index 0000000000..36967431a6
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/rnn.cpp
@@ -0,0 +1,400 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+#include "cpu/gemm/os_blas.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::types;
+using namespace mkldnn::impl::utils;
+
+namespace {
+memory_desc_t copy_maybe_null(const memory_desc_t *md) {
+ return md ? *md : zero_md();
+}
+
+rnn_desc_t zero_rnn_desc() {
+ auto rd = rnn_desc_t();
+ rd.src_layer_desc = zero_md();
+ rd.src_iter_desc = zero_md();
+ rd.weights_layer_desc = zero_md();
+ rd.weights_iter_desc = zero_md();
+ rd.bias_desc = zero_md();
+ rd.dst_layer_desc = zero_md();
+ rd.dst_iter_desc = zero_md();
+ rd.diff_src_layer_desc = zero_md();
+ rd.diff_src_iter_desc = zero_md();
+ rd.diff_weights_layer_desc = zero_md();
+ rd.diff_weights_iter_desc = zero_md();
+ rd.diff_bias_desc = zero_md();
+ rd.diff_dst_layer_desc = zero_md();
+ rd.diff_dst_iter_desc = zero_md();
+ return rd;
+}
+}
+
+/* Public C Api */
+
+status_t mkldnn_rnn_cell_desc_init(rnn_cell_desc_t *rnn_cell_desc,
+ mkldnn_alg_kind_t cell_kind, mkldnn_alg_kind_t act_f,
+ unsigned int flags, float alpha, float clipping) {
+ using namespace mkldnn::impl::alg_kind;
+
+ bool args_ok = true
+ && one_of(cell_kind, vanilla_rnn, vanilla_lstm, vanilla_gru,
+ gru_linear_before_reset)
+ && IMPLICATION(cell_kind == vanilla_rnn,
+ one_of(act_f, eltwise_relu, eltwise_tanh, eltwise_logistic));
+ if (!args_ok)
+ return invalid_arguments;
+
+ auto rcd = mkldnn_rnn_cell_desc_t();
+
+ rcd.cell_kind = cell_kind;
+ rcd.activation_kind = act_f;
+ rcd.flags = flags;
+ rcd.alpha = rcd.flags & mkldnn_rnn_cell_with_relu ? alpha : 0;
+ rcd.clipping = rcd.flags & mkldnn_rnn_cell_with_clipping ? clipping : 0;
+
+ *rnn_cell_desc = rcd;
+
+ return success;
+}
+
+int mkldnn_rnn_cell_get_gates_count(const rnn_cell_desc_t *rnn_cell_desc) {
+ switch (rnn_cell_desc->cell_kind) {
+ case mkldnn::impl::alg_kind::vanilla_rnn: return 1;
+ case mkldnn::impl::alg_kind::vanilla_gru: return 3;
+ case mkldnn::impl::alg_kind::gru_linear_before_reset: return 3;
+ case mkldnn::impl::alg_kind::vanilla_lstm: return 4;
+ default: assert(!"unknown cell kind"); return 0;
+ }
+ return 0;
+}
+
+int mkldnn_rnn_cell_get_states_count(const rnn_cell_desc_t *rnn_cell_desc) {
+ switch (rnn_cell_desc->cell_kind) {
+ case mkldnn::impl::alg_kind::vanilla_rnn: return 1;
+ case mkldnn::impl::alg_kind::vanilla_gru: return 1;
+ case mkldnn::impl::alg_kind::gru_linear_before_reset: return 1;
+ case mkldnn::impl::alg_kind::vanilla_lstm: return 2;
+ default: assert(!"unknown cell kind"); return 0;
+ }
+ return 0;
+}
+
+status_t check_data_type_consistency_fwd(const rnn_cell_desc_t *rnn_cell_desc,
+ prop_kind_t prop_kind, const memory_desc_t *src_layer_desc,
+ const memory_desc_t *src_iter_desc,
+ const memory_desc_t *weights_layer_desc,
+ const memory_desc_t *weights_iter_desc, const memory_desc_t *bias_desc,
+ const memory_desc_t *dst_layer_desc,
+ const memory_desc_t *dst_iter_desc) {
+ using namespace data_type;
+ data_type_t src_layer_dt = src_layer_desc->data_type;
+ data_type_t dst_layer_dt = dst_layer_desc->data_type;
+ data_type_t weights_iter_dt = weights_iter_desc->data_type;
+ data_type_t weights_layer_dt = weights_layer_desc->data_type;
+
+ bool is_f32 = everyone_is(f32, src_layer_dt, dst_layer_dt, weights_iter_dt,
+ weights_layer_dt)
+ && IMPLICATION(!is_zero_md(src_iter_desc),
+ src_iter_desc->data_type == f32)
+ && IMPLICATION(!is_zero_md(dst_iter_desc),
+ dst_iter_desc->data_type == f32)
+ && IMPLICATION(!is_zero_md(bias_desc), bias_desc->data_type == f32);
+
+#if USE_MKL_PACKED_GEMM
+ bool is_u8u8u8 = src_layer_dt == u8
+ && IMPLICATION(!is_zero_md(src_iter_desc),
+ src_iter_desc->data_type == u8)
+ && IMPLICATION(!is_zero_md(dst_iter_desc),
+ dst_iter_desc->data_type == u8)
+ && one_of(dst_layer_dt, u8, f32)
+ && everyone_is(s8, weights_iter_dt, weights_layer_dt)
+ && IMPLICATION(!is_zero_md(bias_desc), bias_desc->data_type == f32);
+
+ bool is_f32u8f32 = src_layer_dt == u8
+ && IMPLICATION(!is_zero_md(src_iter_desc),
+ src_iter_desc->data_type == f32)
+ && IMPLICATION(!is_zero_md(dst_iter_desc),
+ dst_iter_desc->data_type == f32)
+ && one_of(dst_layer_dt, u8, f32)
+ && everyone_is(s8, weights_iter_dt, weights_layer_dt)
+ && IMPLICATION(!is_zero_md(bias_desc), bias_desc->data_type == f32);
+
+ bool is_inference = prop_kind == prop_kind::forward_inference;
+ bool is_lstm = rnn_cell_desc->cell_kind == mkldnn_vanilla_lstm;
+
+ return (is_f32 || ((is_u8u8u8 || is_f32u8f32) && is_lstm && is_inference))
+ ? success
+ : unimplemented;
+#else
+ return is_f32 ? success : unimplemented;
+#endif
+}
+
+status_t check_dim_consistency(const rnn_cell_desc_t *rnn_cell_desc,
+ rnn_direction_t direction, int L, int D, int T, int N, int S, int G,
+ int SLC, int SIC, int DLC, int DIC, const memory_desc_t *src_layer_desc,
+ const memory_desc_t *src_iter_desc,
+ const memory_desc_t *weights_layer_desc,
+ const memory_desc_t *weights_iter_desc, const memory_desc_t *bias_desc,
+ const memory_desc_t *dst_layer_desc,
+ const memory_desc_t *dst_iter_desc) {
+ bool args_ok;
+
+ // * algorithm specific
+ args_ok = true
+ && IMPLICATION(rnn_cell_desc->cell_kind == alg_kind::vanilla_gru,
+ DIC == SIC);
+ if (!args_ok) return invalid_arguments;
+ int extra_bias =
+ rnn_cell_desc->cell_kind == alg_kind::gru_linear_before_reset;
+
+ // * on num layers
+ args_ok = true
+ && L == weights_layer_desc->dims[0]
+ && L == weights_iter_desc->dims[0]
+ && IMPLICATION(!is_zero_md(bias_desc), L == bias_desc->dims[0])
+ && IMPLICATION(!is_zero_md(src_iter_desc), L == src_iter_desc->dims[0])
+ && IMPLICATION(!is_zero_md(dst_iter_desc), L == dst_iter_desc->dims[0]);
+ if (!args_ok) return invalid_arguments;
+
+ // * on num directions
+ args_ok = true
+ && D == weights_layer_desc->dims[1]
+ && D == weights_iter_desc->dims[1]
+ && IMPLICATION(!is_zero_md(bias_desc), D == bias_desc->dims[1])
+ && IMPLICATION(!is_zero_md(src_iter_desc), D == src_iter_desc->dims[1])
+ && IMPLICATION(!is_zero_md(dst_iter_desc), D == dst_iter_desc->dims[1]);
+ if (!args_ok) return invalid_arguments;
+
+ // * on num iterations
+ args_ok = true
+ && T == src_layer_desc->dims[0]
+ && T == dst_layer_desc->dims[0];
+ if (!args_ok) return invalid_arguments;
+
+ // * on mb
+ args_ok = true
+ && N == src_layer_desc->dims[1]
+ && N == dst_layer_desc->dims[1]
+ && IMPLICATION(!is_zero_md(src_iter_desc), N == src_iter_desc->dims[3])
+ && IMPLICATION(!is_zero_md(dst_iter_desc), N == dst_iter_desc->dims[3]);
+ if (!args_ok) return invalid_arguments;
+
+ // * on num gates
+ args_ok = true
+ && G == mkldnn_rnn_cell_get_gates_count(rnn_cell_desc)
+ && G == weights_layer_desc->dims[3]
+ && G == weights_iter_desc->dims[3]
+ && IMPLICATION(!is_zero_md(bias_desc),
+ G + extra_bias == bias_desc->dims[2]);
+ if (!args_ok) return invalid_arguments;
+
+ // * on num states
+ args_ok = true
+ && S == mkldnn_rnn_cell_get_states_count(rnn_cell_desc)
+ && IMPLICATION(!is_zero_md(src_iter_desc), S == src_iter_desc->dims[2])
+ && IMPLICATION(!is_zero_md(dst_iter_desc), S == dst_iter_desc->dims[2]);
+ if (!args_ok) return invalid_arguments;
+
+ // * on slc
+ args_ok = true
+ && SLC == weights_layer_desc->dims[2]
+ && SLC == src_layer_desc->dims[2];
+ if (!args_ok) return invalid_arguments;
+
+ // * on sic
+ args_ok = true
+ && SIC == weights_iter_desc->dims[2]
+ && IMPLICATION(!is_zero_md(src_iter_desc),
+ SIC == src_iter_desc->dims[4]);
+ if (!args_ok) return invalid_arguments;
+
+ // * on dlc
+ int dlc_multiplier = (direction == mkldnn_bidirectional_concat) ? 2 : 1;
+ args_ok = true
+ && DLC == dlc_multiplier * DIC
+ && DLC == dst_layer_desc->dims[2];
+ if (!args_ok) return invalid_arguments;
+
+ // * on dic
+ args_ok = true
+ && DIC == weights_layer_desc->dims[4]
+ && DIC == weights_iter_desc->dims[4]
+ && IMPLICATION(!is_zero_md(bias_desc), DIC == bias_desc->dims[3])
+ && IMPLICATION(!is_zero_md(dst_iter_desc),
+ DIC == dst_iter_desc->dims[4]);
+ if (!args_ok) return invalid_arguments;
+
+ // * unrolling/fusion conditions
+ args_ok = true
+ && IMPLICATION(L > 1, (dlc_multiplier * SLC) == DLC)
+ && IMPLICATION(T > 1, SIC == DIC);
+ if (!args_ok) return invalid_arguments;
+
+ return success;
+}
+
+status_t MKLDNN_API mkldnn_rnn_forward_desc_init(mkldnn_rnn_desc_t *rnn_desc,
+ prop_kind_t prop_kind, const rnn_cell_desc_t *rnn_cell_desc,
+ const rnn_direction_t direction, const memory_desc_t *src_layer_desc,
+ const memory_desc_t *src_iter_desc,
+ const memory_desc_t *weights_layer_desc,
+ const memory_desc_t *weights_iter_desc, const memory_desc_t *bias_desc,
+ const memory_desc_t *dst_layer_desc,
+ const memory_desc_t *dst_iter_desc) {
+ bool args_ok = true && rnn_cell_desc != nullptr
+ && !any_null(src_layer_desc, weights_layer_desc, weights_iter_desc,
+ dst_layer_desc);
+ if (!args_ok) return invalid_arguments;
+
+ //check dimensions consistency
+ int L = weights_layer_desc->dims[0];
+ int T = src_layer_desc->dims[0];
+ int N = src_layer_desc->dims[1];
+ const int D = one_of(direction, mkldnn_unidirectional_left2right,
+ mkldnn_unidirectional_right2left) ?
+ 1 :
+ 2;
+ int G = mkldnn_rnn_cell_get_gates_count(rnn_cell_desc);
+ int S = mkldnn_rnn_cell_get_states_count(rnn_cell_desc);
+ int SLC = src_layer_desc->dims[2];
+ int SIC = weights_iter_desc->dims[2];
+ int DLC = dst_layer_desc->dims[2];
+ int DIC = weights_layer_desc->dims[4];
+
+ CHECK(check_dim_consistency(rnn_cell_desc, direction, L, D, T, N, S,
+ G, SLC, SIC, DLC, DIC, src_layer_desc, src_iter_desc,
+ weights_layer_desc, weights_iter_desc, bias_desc, dst_layer_desc,
+ dst_iter_desc));
+
+ CHECK(check_data_type_consistency_fwd(rnn_cell_desc, prop_kind,
+ src_layer_desc, src_iter_desc, weights_layer_desc,
+ weights_iter_desc, bias_desc, dst_layer_desc, dst_iter_desc));
+
+ // Create the descriptor
+ mkldnn_rnn_desc_t rd = zero_rnn_desc();
+
+ rd.primitive_kind = primitive_kind::rnn;
+ rd.prop_kind = prop_kind;
+ rd.cell_desc = *rnn_cell_desc;
+ rd.direction = direction;
+ rd.src_layer_desc = copy_maybe_null(src_layer_desc);
+ rd.src_iter_desc = copy_maybe_null(src_iter_desc);
+ rd.weights_layer_desc = copy_maybe_null(weights_layer_desc);
+ rd.weights_iter_desc = copy_maybe_null(weights_iter_desc);
+ rd.bias_desc = copy_maybe_null(bias_desc);
+ rd.dst_layer_desc = copy_maybe_null(dst_layer_desc);
+ rd.dst_iter_desc = copy_maybe_null(dst_iter_desc);
+
+ *rnn_desc = rd;
+
+ return success;
+}
+
+status_t MKLDNN_API mkldnn_rnn_backward_desc_init(mkldnn_rnn_desc_t *rnn_desc,
+ prop_kind_t prop_kind, const rnn_cell_desc_t *rnn_cell_desc,
+ const rnn_direction_t direction, const memory_desc_t *src_layer_desc,
+ const memory_desc_t *src_iter_desc,
+ const memory_desc_t *weights_layer_desc,
+ const memory_desc_t *weights_iter_desc, const memory_desc_t *bias_desc,
+ const memory_desc_t *dst_layer_desc, const memory_desc_t *dst_iter_desc,
+ const memory_desc_t *diff_src_layer_desc,
+ const memory_desc_t *diff_src_iter_desc,
+ const memory_desc_t *diff_weights_layer_desc,
+ const memory_desc_t *diff_weights_iter_desc,
+ const memory_desc_t *diff_bias_desc,
+ const memory_desc_t *diff_dst_layer_desc,
+ const memory_desc_t *diff_dst_iter_desc) {
+ bool args_ok = true
+ && !any_null(src_layer_desc, weights_layer_desc, weights_iter_desc,
+ dst_layer_desc, diff_src_layer_desc,
+ diff_weights_layer_desc, diff_weights_iter_desc,
+ diff_dst_layer_desc);
+ if (!args_ok)
+ return invalid_arguments;
+
+ auto xnor_md = [=](const memory_desc_t *a_md, const memory_desc_t *b_md) {
+ return is_zero_md(a_md) == is_zero_md(b_md);
+ };
+
+ args_ok = args_ok && xnor_md(bias_desc, diff_bias_desc)
+ && xnor_md(dst_iter_desc, diff_dst_iter_desc)
+ && xnor_md(src_iter_desc, diff_src_iter_desc);
+ if (!args_ok)
+ return invalid_arguments;
+
+ //check dimensions consistency
+ int L = weights_layer_desc->dims[0];
+ int T = src_layer_desc->dims[0];
+ int N = src_layer_desc->dims[1];
+ const int D = one_of(direction, mkldnn_unidirectional_left2right,
+ mkldnn_unidirectional_right2left) ?
+ 1 :
+ 2;
+ int G = mkldnn_rnn_cell_get_gates_count(rnn_cell_desc);
+ int S = mkldnn_rnn_cell_get_states_count(rnn_cell_desc);
+ int SLC = src_layer_desc->dims[2];
+ int SIC = weights_iter_desc->dims[2];
+ int DLC = dst_layer_desc->dims[2];
+ int DIC = weights_layer_desc->dims[4];
+
+ status_t st = check_dim_consistency(rnn_cell_desc, direction, L, D, T, N, S,
+ G, SLC, SIC, DLC, DIC, src_layer_desc, src_iter_desc,
+ weights_layer_desc, weights_iter_desc, bias_desc, dst_layer_desc,
+ dst_iter_desc);
+ if (st != success) return st;
+
+ st = check_dim_consistency(rnn_cell_desc, direction, L, D, T, N, S,
+ G, SLC, SIC, DLC, DIC, diff_src_layer_desc, diff_src_iter_desc,
+ diff_weights_layer_desc, diff_weights_iter_desc, diff_bias_desc,
+ diff_dst_layer_desc, diff_dst_iter_desc);
+ if (st != success) return st;
+
+ mkldnn_rnn_desc_t rd = zero_rnn_desc();
+
+ rd.primitive_kind = primitive_kind::rnn;
+ rd.prop_kind = prop_kind;
+ rd.cell_desc = *rnn_cell_desc;
+ rd.direction = direction;
+
+ rd.src_layer_desc = copy_maybe_null(src_layer_desc);
+ rd.src_iter_desc = copy_maybe_null(src_iter_desc);
+ rd.weights_layer_desc = copy_maybe_null(weights_layer_desc);
+ rd.weights_iter_desc = copy_maybe_null(weights_iter_desc);
+ rd.bias_desc = copy_maybe_null(bias_desc);
+ rd.dst_layer_desc = copy_maybe_null(dst_layer_desc);
+ rd.dst_iter_desc = copy_maybe_null(dst_iter_desc);
+ rd.diff_src_layer_desc = copy_maybe_null(diff_src_layer_desc);
+ rd.diff_src_iter_desc = copy_maybe_null(diff_src_iter_desc);
+ rd.diff_weights_layer_desc = copy_maybe_null(diff_weights_layer_desc);
+ rd.diff_weights_iter_desc = copy_maybe_null(diff_weights_iter_desc);
+ rd.diff_bias_desc = copy_maybe_null(diff_bias_desc);
+ rd.diff_dst_layer_desc = copy_maybe_null(diff_dst_layer_desc);
+ rd.diff_dst_iter_desc = copy_maybe_null(diff_dst_iter_desc);
+
+ *rnn_desc = rd;
+
+ return success;
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/rnn_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/rnn_pd.hpp
new file mode 100644
index 0000000000..1ee2ba1114
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/rnn_pd.hpp
@@ -0,0 +1,280 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef RNN_PD_HPP
+#define RNN_PD_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive_desc.hpp"
+#include "type_helpers.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct rnn_fwd_pd_t;
+
+struct rnn_pd_t : public primitive_desc_t {
+ static constexpr auto base_pkind = primitive_kind::rnn;
+
+ rnn_pd_t(engine_t *engine,
+ const rnn_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const rnn_fwd_pd_t *hint_fwd_pd)
+ : primitive_desc_t(engine, attr, base_pkind)
+ , desc_(*adesc)
+ , hint_fwd_pd_(hint_fwd_pd)
+ , src_layer_md_(desc_.src_layer_desc)
+ , src_iter_md_(desc_.src_iter_desc)
+ , weights_layer_md_(desc_.weights_layer_desc)
+ , weights_iter_md_(desc_.weights_iter_desc)
+ , bias_md_(desc_.bias_desc)
+ , dst_layer_md_(desc_.dst_layer_desc)
+ , dst_iter_md_(desc_.dst_iter_desc)
+ , ws_md_()
+ {}
+
+ const rnn_desc_t *desc() const { return &desc_; }
+ virtual const op_desc_t *op_desc() const override
+ { return reinterpret_cast<const op_desc_t *>(this->desc()); }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual status_t query(query_t what, int idx, void *result) const override {
+ switch (what) {
+ case query::rnn_d: *(const rnn_desc_t **)result = desc(); break;
+ default: return primitive_desc_t::query(what, idx, result);
+ }
+ return status::success;
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override {
+ if (index == 0) return &src_layer_md_;
+ if (index == 1 && with_src_iter()) return &src_iter_md_;
+ return nullptr;
+ }
+ virtual const memory_desc_t *weights_md(int index = 0) const override {
+ if (index == 0) return &weights_layer_md_;
+ if (index == 1) return &weights_iter_md_;
+ if (index == 2 && with_bias()) return &bias_md_;
+ return nullptr;
+ }
+ virtual const memory_desc_t *dst_md(int index = 0) const override {
+ if (index == 0) return &dst_layer_md_;
+ if (index == 1 && with_dst_iter()) return &dst_iter_md_;
+ return nullptr;
+ }
+ virtual const memory_desc_t *workspace_md(int index = 0) const override
+ { return index == 0 && !types::is_zero_md(&ws_md_) ? &ws_md_ : nullptr; }
+
+ /* common pooling aux functions */
+
+ bool is_training() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::backward);
+ }
+
+ bool is_fwd() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ }
+
+ dim_t T() const { return desc_.src_layer_desc.dims[0]; }
+ dim_t MB() const { return desc_.src_layer_desc.dims[1]; }
+
+ dim_t L() const { return desc_.weights_layer_desc.dims[0]; }
+ dim_t D() const { return desc_.weights_layer_desc.dims[1]; }
+
+ dim_t SIC() const { return desc_.weights_iter_desc.dims[2]; }
+
+ dim_t SLC() const { return desc_.weights_layer_desc.dims[2]; }
+ dim_t G() const { return desc_.weights_layer_desc.dims[3]; }
+ dim_t DIC() const { return desc_.weights_layer_desc.dims[4]; }
+
+ dim_t DLC() const { return desc_.dst_layer_desc.dims[2]; }
+
+ bool with_bias() const
+ { return !memory_desc_wrapper(desc_.bias_desc).is_zero(); }
+
+ bool with_src_iter() const
+ { return !(memory_desc_wrapper(desc_.src_iter_desc).is_zero()); }
+
+ bool with_dst_iter() const
+ { return !memory_desc_wrapper(desc_.dst_iter_desc).is_zero(); }
+
+ mkldnn::impl::alg_kind_t cell_kind() const
+ { return desc_.cell_desc.cell_kind; }
+ mkldnn::impl::alg_kind_t activation_kind() const
+ { return desc_.cell_desc.activation_kind; }
+
+ bool is_lbr() const
+ { return cell_kind() == mkldnn_gru_linear_before_reset; }
+
+ mkldnn_rnn_direction_t direction() const { return desc_.direction; }
+
+protected:
+ rnn_desc_t desc_;
+ const rnn_fwd_pd_t *hint_fwd_pd_;
+
+ memory_desc_t src_layer_md_;
+ memory_desc_t src_iter_md_;
+ memory_desc_t weights_layer_md_;
+ memory_desc_t weights_iter_md_;
+ memory_desc_t bias_md_;
+ memory_desc_t dst_layer_md_;
+ memory_desc_t dst_iter_md_;
+
+ memory_desc_t ws_md_;
+};
+
+struct rnn_fwd_pd_t: public rnn_pd_t {
+ typedef rnn_fwd_pd_t base_class;
+ typedef rnn_fwd_pd_t hint_class;
+
+ rnn_fwd_pd_t(engine_t *engine,
+ const rnn_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const rnn_fwd_pd_t *hint_fwd_pd)
+ : rnn_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (arg == MKLDNN_ARG_SRC_LAYER)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_SRC_ITER && with_src_iter())
+ return arg_usage_t::input;
+
+ if (utils::one_of(arg, MKLDNN_ARG_WEIGHTS_LAYER,
+ MKLDNN_ARG_WEIGHTS_ITER))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_BIAS && with_bias())
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST_LAYER)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_DST_ITER && with_dst_iter())
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_WORKSPACE && is_training())
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual int n_inputs() const override
+ { return 3 + with_bias() + with_src_iter(); }
+ virtual int n_outputs() const override
+ { return 1 + with_dst_iter() + is_training(); }
+};
+
+struct rnn_bwd_pd_t : public rnn_pd_t {
+ typedef rnn_bwd_pd_t base_class;
+ typedef rnn_fwd_pd_t hint_class;
+
+ rnn_bwd_pd_t(engine_t *engine,
+ const rnn_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const rnn_fwd_pd_t *hint_fwd_pd)
+ : rnn_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , diff_src_layer_md_(desc_.diff_src_layer_desc)
+ , diff_src_iter_md_(desc_.diff_src_iter_desc)
+ , diff_weights_layer_md_(desc_.diff_weights_layer_desc)
+ , diff_weights_iter_md_(desc_.diff_weights_iter_desc)
+ , diff_bias_md_(desc_.diff_bias_desc)
+ , diff_dst_layer_md_(desc_.diff_dst_layer_desc)
+ , diff_dst_iter_md_(desc_.diff_dst_iter_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_SRC_LAYER, MKLDNN_ARG_DST_LAYER,
+ MKLDNN_ARG_DIFF_DST_LAYER))
+ return arg_usage_t::input;
+
+ if (with_src_iter()) {
+ if (arg == MKLDNN_ARG_SRC_ITER)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_SRC_ITER)
+ return arg_usage_t::output;
+ }
+
+ if (utils::one_of(arg, MKLDNN_ARG_WEIGHTS_LAYER,
+ MKLDNN_ARG_WEIGHTS_ITER))
+ return arg_usage_t::input;
+
+ if (with_bias()) {
+ if (arg == MKLDNN_ARG_BIAS)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_BIAS)
+ return arg_usage_t::output;
+ }
+
+ if (utils::one_of(arg, MKLDNN_ARG_DST_ITER, MKLDNN_ARG_DIFF_DST_ITER)
+ && with_dst_iter())
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_WORKSPACE)
+ return arg_usage_t::input;
+
+ if (utils::one_of(arg, MKLDNN_ARG_DIFF_SRC_LAYER,
+ MKLDNN_ARG_DIFF_WEIGHTS_LAYER,
+ MKLDNN_ARG_DIFF_WEIGHTS_ITER))
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *diff_src_md(int index = 0) const override {
+ if (index == 0) return &diff_src_layer_md_;
+ if (index == 1 && with_src_iter()) return &diff_src_iter_md_;
+ return nullptr;
+ }
+ virtual const memory_desc_t *diff_weights_md(
+ int index = 0) const override {
+ if (index == 0) return &diff_weights_layer_md_;
+ if (index == 1) return &diff_weights_iter_md_;
+ if (index == 2 && with_bias()) return &diff_bias_md_;
+ return nullptr;
+ }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override {
+ if (index == 0) return &diff_dst_layer_md_;
+ if (index == 1 && with_dst_iter()) return &diff_dst_iter_md_;
+ return nullptr;
+ }
+
+ virtual int n_inputs() const override
+ { return 6 + with_src_iter() + with_bias() + 2 * with_dst_iter(); }
+ virtual int n_outputs() const override
+ { return 3 + with_src_iter() + with_bias(); }
+
+protected:
+ memory_desc_t diff_src_layer_md_;
+ memory_desc_t diff_src_iter_md_;
+ memory_desc_t diff_weights_layer_md_;
+ memory_desc_t diff_weights_iter_md_;
+ memory_desc_t diff_bias_md_;
+ memory_desc_t diff_dst_layer_md_;
+ memory_desc_t diff_dst_iter_md_;
+};
+
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/scratchpad.cpp b/thirdparty/oidn/mkl-dnn/src/common/scratchpad.cpp
new file mode 100644
index 0000000000..6bc14fc72a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/scratchpad.cpp
@@ -0,0 +1,112 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "scratchpad.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+/* Allocating memory buffers on a page boundary to reduce TLB/page misses */
+const size_t page_size = 2097152;
+
+/*
+ Implementation of the scratchpad_t interface that is compatible with
+ a concurrent execution
+*/
+struct concurent_scratchpad_t : public scratchpad_t {
+ concurent_scratchpad_t(size_t size) {
+ size_ = size;
+ scratchpad_ = (char *) malloc(size, page_size);
+ assert(scratchpad_ != nullptr);
+ }
+
+ ~concurent_scratchpad_t() {
+ free(scratchpad_);
+ }
+
+ virtual char *get() const {
+ return scratchpad_;
+ }
+
+private:
+ char *scratchpad_;
+ size_t size_;
+};
+
+/*
+ Implementation of the scratchpad_t interface that uses a global
+ scratchpad
+*/
+
+struct global_scratchpad_t : public scratchpad_t {
+ global_scratchpad_t(size_t size) {
+ if (size > size_) {
+ if (scratchpad_ != nullptr) free(scratchpad_);
+ size_ = size;
+ scratchpad_ = (char *) malloc(size, page_size);
+ assert(scratchpad_ != nullptr);
+ }
+ reference_count_++;
+ }
+
+ ~global_scratchpad_t() {
+ reference_count_--;
+ if (reference_count_ == 0) {
+ free(scratchpad_);
+ scratchpad_ = nullptr;
+ size_ = 0;
+ }
+ }
+
+ virtual char *get() const {
+ return scratchpad_;
+ }
+
+private:
+ /*
+ Using thread-local here is unnecessary and even buggy! All threads
+ actually share the same scratchpad, which is created and queried only
+ on the main thread. If the scratchpad is queried on some thread other
+ than the one it was created on (e.g. the application calls the API from
+ multiple threads), thread-local causes a segfault because the scratchpad
+ is uninitialized on the current thread.
+ */
+ /*thread_local*/ static char *scratchpad_;
+ /*thread_local*/ static size_t size_;
+ /*thread_local*/ static unsigned int reference_count_;
+};
+
+/*thread_local*/ char *global_scratchpad_t::scratchpad_ = nullptr;
+/*thread_local*/ size_t global_scratchpad_t::size_ = 0;
+/*thread_local*/ unsigned int global_scratchpad_t::reference_count_ = 0;
+
+
+/*
+ Scratchpad creation routine
+*/
+scratchpad_t *create_scratchpad(size_t size) {
+#ifndef MKLDNN_ENABLE_CONCURRENT_EXEC
+ return new global_scratchpad_t(size);
+#else
+ return new concurent_scratchpad_t(size);
+#endif
+}
+
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/scratchpad.hpp b/thirdparty/oidn/mkl-dnn/src/common/scratchpad.hpp
new file mode 100644
index 0000000000..f7a246bc99
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/scratchpad.hpp
@@ -0,0 +1,36 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef COMMON_SCRATCHPAD_HPP
+#define COMMON_SCRATCHPAD_HPP
+
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct scratchpad_t {
+ virtual ~scratchpad_t() {}
+ virtual char *get() const = 0;
+};
+
+scratchpad_t *create_scratchpad(size_t size);
+
+}
+}
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/shuffle.cpp b/thirdparty/oidn/mkl-dnn/src/common/shuffle.cpp
new file mode 100644
index 0000000000..e32e735224
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/shuffle.cpp
@@ -0,0 +1,72 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::types;
+
+namespace {
+status_t shuffle_desc_init(shuffle_desc_t *shuffle_desc, prop_kind_t prop_kind,
+ const memory_desc_t *data_desc, int axis, dim_t group_size) {
+ bool args_ok = true
+ && !any_null(shuffle_desc, data_desc)
+ && one_of(prop_kind, forward_training, forward_inference,
+ backward, backward_data)
+ && axis >= 0 && axis < data_desc->ndims
+ && group_size > 0 && group_size <= data_desc->dims[axis];
+ if (!args_ok) return invalid_arguments;
+
+ auto sd = shuffle_desc_t();
+ sd.primitive_kind = primitive_kind::shuffle;
+ sd.prop_kind = prop_kind;
+ sd.data_desc = *data_desc;
+ sd.axis = axis;
+ sd.group_size = group_size;
+
+ bool consistency = true
+ && sd.data_desc.dims[axis] % sd.group_size == 0;
+ if (!consistency) return invalid_arguments;
+
+ *shuffle_desc = sd;
+ return success;
+}
+}
+
+status_t mkldnn_shuffle_forward_desc_init(shuffle_desc_t *shuffle_desc,
+ prop_kind_t prop_kind, const memory_desc_t *data_desc, int axis,
+ dim_t group_size) {
+ if (!one_of(prop_kind, forward_training, forward_inference))
+ return invalid_arguments;
+ return shuffle_desc_init(shuffle_desc, prop_kind, data_desc, axis,
+ group_size);
+}
+
+status_t mkldnn_shuffle_backward_desc_init(shuffle_desc_t *shuffle_desc,
+ const memory_desc_t *diff_data_desc, int axis, dim_t group_size) {
+ return shuffle_desc_init(shuffle_desc, backward_data, diff_data_desc, axis,
+ group_size);
+}
+
+// vim: et ts=5 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/shuffle_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/shuffle_pd.hpp
new file mode 100644
index 0000000000..cc5553fe7f
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/shuffle_pd.hpp
@@ -0,0 +1,121 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef SHUFFLE_PD_HPP
+#define SHUFFLE_PD_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive_desc.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct shuffle_pd_t: public primitive_desc_t {
+ static constexpr auto base_pkind = primitive_kind::shuffle;
+
+ typedef shuffle_pd_t base_class;
+ typedef shuffle_pd_t hint_class;
+
+ shuffle_pd_t(engine_t *engine,
+ const shuffle_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const shuffle_pd_t *hint_fwd_pd)
+ : primitive_desc_t(engine, attr, base_pkind)
+ , desc_(*adesc)
+ , hint_fwd_pd_(hint_fwd_pd)
+ , data_md_(desc_.data_desc)
+ {}
+
+ const shuffle_desc_t *desc() const { return &desc_; }
+ virtual const op_desc_t *op_desc() const override
+ { return reinterpret_cast<const op_desc_t *>(this->desc()); }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual status_t query(query_t what, int idx, void *result) const override {
+ switch (what) {
+ case query::shuffle_d:
+ *(const shuffle_desc_t**)result = desc(); break;
+ default: return primitive_desc_t::query(what, idx, result);
+ }
+ return status::success;
+ }
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (is_fwd()) {
+ if (arg == MKLDNN_ARG_SRC)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST)
+ return arg_usage_t::output;
+ } else {
+ if (arg == MKLDNN_ARG_DIFF_DST)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_SRC)
+ return arg_usage_t::output;
+ }
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 && is_fwd() ? &data_md_ : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 && is_fwd() ? &data_md_ : nullptr; }
+
+ virtual const memory_desc_t *diff_src_md(int index = 0) const override
+ { return index == 0 && !is_fwd() ? &data_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 && !is_fwd() ? &data_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return 1; }
+ virtual int n_outputs() const override { return 1; }
+
+ /* shuffle aux functions */
+
+ dim_t MB() const { return data_md()->dims[0]; }
+ dim_t C() const { return ndims() >= 2 ? data_md()->dims[1] : 1; }
+ dim_t D() const { return ndims() >= 5 ? data_md()->dims[ndims() - 3] : 1; }
+ dim_t H() const { return ndims() >= 4 ? data_md()->dims[ndims() - 2] : 1; }
+ dim_t W() const { return ndims() >= 3 ? data_md()->dims[ndims() - 1] : 1; }
+
+ int ndims() const { return data_md()->ndims; }
+
+ int axis() const { return desc_.axis; }
+ dim_t group_size() const { return desc_.group_size; }
+ dim_t axis_size() const { return data_md()->dims[axis()]; }
+
+ bool is_fwd() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ }
+
+ const memory_desc_t *data_md() const { return &data_md_; }
+
+protected:
+ shuffle_desc_t desc_;
+ const shuffle_pd_t *hint_fwd_pd_;
+ memory_desc_t data_md_;
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/softmax.cpp b/thirdparty/oidn/mkl-dnn/src/common/softmax.cpp
new file mode 100644
index 0000000000..82848e3d1f
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/softmax.cpp
@@ -0,0 +1,68 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "memory_desc_wrapper.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::alg_kind;
+using namespace mkldnn::impl::types;
+
+namespace {
+status_t softmax_desc_init(softmax_desc_t *softmax_desc, prop_kind_t prop_kind,
+ const memory_desc_t *data_desc, const memory_desc_t *diff_desc, int softmax_axis) {
+ bool args_ok = true
+ && !any_null(softmax_desc, data_desc)
+ && 0 <= softmax_axis
+ && softmax_axis < data_desc->ndims;
+ if (!args_ok) return invalid_arguments;
+
+ auto sd = softmax_desc_t();
+ sd.primitive_kind = primitive_kind::softmax;
+ sd.prop_kind = prop_kind;
+
+ bool is_bwd = (sd.prop_kind == backward_data);
+ sd.data_desc = *data_desc;
+ sd.diff_desc = is_bwd ? *diff_desc : zero_md();
+ sd.softmax_axis = softmax_axis;
+
+ *softmax_desc = sd;
+ return success;
+}
+}
+
+status_t mkldnn_softmax_forward_desc_init(softmax_desc_t *softmax_desc,
+ prop_kind_t prop_kind, const memory_desc_t *data_desc,
+ int softmax_axis) {
+ if (!one_of(prop_kind, forward_inference, forward_training))
+ return invalid_arguments;
+ return softmax_desc_init(softmax_desc, prop_kind, data_desc, nullptr, softmax_axis);
+}
+
+status_t mkldnn_softmax_backward_desc_init(softmax_desc_t *softmax_desc,
+ const memory_desc_t *diff_desc, const mkldnn_memory_desc_t *data_desc,
+ int softmax_axis) {
+ return softmax_desc_init(softmax_desc, prop_kind::backward_data,
+ data_desc, diff_desc, softmax_axis);
+}
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/softmax_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/softmax_pd.hpp
new file mode 100644
index 0000000000..8a16ce901c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/softmax_pd.hpp
@@ -0,0 +1,161 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef SOFTMAX_PD_HPP
+#define SOFTMAX_PD_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "primitive_desc.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct softmax_fwd_pd_t;
+
+struct softmax_pd_t: public primitive_desc_t {
+ static constexpr auto base_pkind = primitive_kind::softmax;
+
+ softmax_pd_t(engine_t *engine,
+ const softmax_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const softmax_fwd_pd_t *hint_fwd_pd)
+ : primitive_desc_t(engine, attr, base_pkind)
+ , desc_(*adesc)
+ , hint_fwd_pd_(hint_fwd_pd)
+ , data_md_(desc_.data_desc)
+ {}
+
+ const softmax_desc_t *desc() const { return &desc_; }
+ virtual const op_desc_t *op_desc() const override
+ { return reinterpret_cast<const op_desc_t *>(this->desc()); }
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual status_t query(query_t what, int idx, void *result) const override {
+ switch (what) {
+ case query::softmax_d:
+ *(const softmax_desc_t**)result = desc(); break;
+ default: return primitive_desc_t::query(what, idx, result);
+ }
+ return status::success;
+ }
+
+ /* common softmax aux functions */
+
+ dim_t MB() const { return data_desc().dims[0]; }
+ dim_t C() const { return data_desc().dims[1]; }
+ dim_t D() const { return ndims() >= 5 ? data_desc().dims[ndims() - 3] : 1; }
+ dim_t H() const { return ndims() >= 4 ? data_desc().dims[ndims() - 2] : 1; }
+ dim_t W() const { return ndims() >= 3 ? data_desc().dims[ndims() - 1] : 1; }
+
+ int ndims() const { return data_desc().ndims; }
+
+ bool is_fwd() const {
+ return utils::one_of(desc_.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ }
+
+protected:
+ softmax_desc_t desc_;
+ const softmax_fwd_pd_t *hint_fwd_pd_;
+
+ memory_desc_t data_md_;
+
+private:
+ const memory_desc_t &data_desc() const { return desc_.data_desc; }
+};
+
+struct softmax_fwd_pd_t: public softmax_pd_t {
+ typedef softmax_fwd_pd_t base_class;
+ typedef softmax_fwd_pd_t hint_class;
+
+ softmax_fwd_pd_t(engine_t *engine,
+ const softmax_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const softmax_fwd_pd_t *hint_fwd_pd)
+ : softmax_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (arg == MKLDNN_ARG_SRC)
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr))
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index == 0 ? &data_md_ : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &data_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return 1; }
+ virtual int n_outputs() const override
+ { return 1 + (workspace_md() != nullptr); }
+};
+
+struct softmax_bwd_pd_t: public softmax_pd_t {
+ typedef softmax_bwd_pd_t base_class;
+ typedef softmax_fwd_pd_t hint_class;
+
+ softmax_bwd_pd_t(engine_t *engine,
+ const softmax_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const softmax_fwd_pd_t *hint_fwd_pd)
+ : softmax_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , diff_data_md_(desc_.diff_desc)
+ {}
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (utils::one_of(arg, MKLDNN_ARG_DST, MKLDNN_ARG_DIFF_DST))
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DIFF_SRC)
+ return arg_usage_t::output;
+
+ if (arg == MKLDNN_ARG_WORKSPACE && (workspace_md() != nullptr))
+ return arg_usage_t::input;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &data_md_ : nullptr; }
+ virtual const memory_desc_t *diff_dst_md(int index = 0) const override
+ { return index == 0 ? &diff_data_md_ : nullptr; }
+ virtual const memory_desc_t *diff_src_md(int index = 0) const override
+ { return index == 0 ? &diff_data_md_ : nullptr; }
+
+ virtual int n_inputs() const override
+ { return 2 + (workspace_md() != nullptr); }
+ virtual int n_outputs() const override { return 1; }
+
+protected:
+ memory_desc_t diff_data_md_;
+};
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/stream.cpp b/thirdparty/oidn/mkl-dnn/src/common/stream.cpp
new file mode 100644
index 0000000000..00af8935c0
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/stream.cpp
@@ -0,0 +1,46 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "engine.hpp"
+#include "stream.hpp"
+#include "utils.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::status;
+
+/* API */
+
+status_t mkldnn_stream_create(stream_t **stream, engine_t *engine,
+ unsigned flags) {
+ bool args_ok = true
+ && !utils::any_null(stream, engine)
+ && flags == stream_flags::default_flags;
+ if (!args_ok)
+ return invalid_arguments;
+
+ return safe_ptr_assign<stream_t>(*stream, new stream_t(engine, flags));
+}
+
+status_t mkldnn_stream_destroy(stream_t *stream) {
+ delete stream;
+ return success;
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/stream.hpp b/thirdparty/oidn/mkl-dnn/src/common/stream.hpp
new file mode 100644
index 0000000000..f010e5f6ed
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/stream.hpp
@@ -0,0 +1,44 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef STREAM_HPP
+#define STREAM_HPP
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "engine.hpp"
+
+struct mkldnn_stream: public mkldnn::impl::c_compatible {
+ mkldnn_stream(mkldnn::impl::engine_t *engine, unsigned flags)
+ : engine_(engine), flags_(flags) {}
+ virtual ~mkldnn_stream() {}
+
+ /** returns stream's engine */
+ mkldnn::impl::engine_t *engine() const { return engine_; }
+
+ /** returns stream's kind */
+ unsigned flags() const { return flags_; }
+
+protected:
+ mkldnn::impl::engine_t *engine_;
+ unsigned flags_;
+};
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/sum.cpp b/thirdparty/oidn/mkl-dnn/src/common/sum.cpp
new file mode 100644
index 0000000000..365663c0f8
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/sum.cpp
@@ -0,0 +1,79 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "engine.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "sum_pd.hpp"
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::status;
+
+status_t mkldnn_sum_primitive_desc_create(primitive_desc_t **sum_pd,
+ const memory_desc_t *dst_md, int n, const float *scales,
+ const memory_desc_t *src_mds, const primitive_attr_t *attr,
+ engine_t *engine) {
+ bool args_ok = !any_null(sum_pd, src_mds, scales) && n > 0;
+ if (!args_ok) return invalid_arguments;
+
+ const primitive_attr_t dummy_attr;
+ if (attr == NULL)
+ attr = &dummy_attr;
+
+ const int ndims = src_mds[0].ndims;
+ const dims_t &dims = src_mds[0].dims;
+ const data_type_t dt = src_mds[0].data_type;
+
+ for (int i = 1; i < n; ++i) {
+ if (src_mds[i].ndims != ndims) return invalid_arguments;
+ for (int d = 0; d < ndims; ++d) {
+ if (src_mds[i].dims[d] != dims[d])
+ return invalid_arguments;
+ }
+ if (src_mds[i].data_type != dt) return invalid_arguments;
+ }
+
+ memory_desc_t dummy_dst_md;
+ if (dst_md) {
+ if (dst_md->ndims != ndims) return invalid_arguments;
+ for (int d = 0; d < ndims; ++d) {
+ if (dst_md->dims[d] != dims[d])
+ return invalid_arguments;
+ }
+ } else {
+ dummy_dst_md = src_mds[0];
+ dummy_dst_md.format_kind = format_kind::any;
+ dst_md = &dummy_dst_md;
+ }
+
+ auto s_pd = reinterpret_cast<sum_pd_t **>(sum_pd);
+
+ for (auto s = engine->get_sum_implementation_list(); *s; ++s) {
+ if ((*s)(s_pd, engine, attr, dst_md, n, scales, src_mds) == success) {
+ (*s_pd)->init_info();
+ (*s_pd)->init_scratchpad_md();
+ return success;
+ }
+ }
+ return unimplemented;
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/sum_pd.hpp b/thirdparty/oidn/mkl-dnn/src/common/sum_pd.hpp
new file mode 100644
index 0000000000..80254667df
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/sum_pd.hpp
@@ -0,0 +1,143 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef SUM_PD_HPP
+#define SUM_PD_HPP
+
+#include <assert.h>
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "primitive_desc.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct sum_pd_t: public primitive_desc_t {
+ sum_pd_t(engine_t *engine, const primitive_attr_t *attr,
+ const memory_desc_t *dst_md, int n, const float *scales,
+ const memory_desc_t *src_mds)
+ : primitive_desc_t(engine, attr, primitive_kind::sum)
+ , n_(n), dst_md_(*dst_md)
+ {
+ scales_.reserve(n_);
+ for (int i = 0; i < n_; ++i) scales_.push_back(scales[i]);
+ src_mds_.reserve(n_);
+ for (int i = 0; i < n_; ++i) src_mds_.push_back(src_mds[i]);
+ }
+
+ virtual void init_info() override { impl::init_info(this, this->info_); }
+
+ virtual arg_usage_t arg_usage(primitive_arg_index_t arg) const override {
+ if (arg >= MKLDNN_ARG_MULTIPLE_SRC
+ && arg < MKLDNN_ARG_MULTIPLE_SRC + n_inputs())
+ return arg_usage_t::input;
+
+ if (arg == MKLDNN_ARG_DST)
+ return arg_usage_t::output;
+
+ return primitive_desc_t::arg_usage(arg);
+ }
+
+ virtual const memory_desc_t *src_md(int index = 0) const override
+ { return index < n_inputs() ? &src_mds_[index] : nullptr; }
+ virtual const memory_desc_t *dst_md(int index = 0) const override
+ { return index == 0 ? &dst_md_ : nullptr; }
+
+ virtual int n_inputs() const override { return n_; }
+ virtual int n_outputs() const override { return 1; }
+
+ const float *scales() const { return &scales_[0]; }
+
+protected:
+ int n_;
+ nstl::vector<float> scales_;
+ memory_desc_t dst_md_;
+ nstl::vector<memory_desc_t> src_mds_;
+
+protected:
+ /* inits dst_md_ in simple cases. The call may fail. */
+ status_t init() {
+ for (int i = 0; i < n_; ++i) {
+ const memory_desc_wrapper src_d(&src_mds_[i]);
+ if (!src_d.is_blocking_desc() || src_d.is_additional_buffer())
+ return status::unimplemented;
+ }
+ bool ok = true
+ && set_default_params() == status::success
+ && attr()->has_default_values();
+ return ok ? status::success : status::unimplemented;
+ }
+
+ status_t set_default_params() {
+ if (dst_md_.format_kind != format_kind::any)
+ return status::success;
+
+ /* The stupidest ever heuristics (but not the same as we had before):
+ * - Pick the first non-plain format;
+ * - If all formats are plain, pick the format of the first input
+ */
+ for (int i = 0; i < n_; ++i) {
+ const memory_desc_wrapper src_d(src_mds_[i]);
+ if (!src_d.is_plain() && src_d.is_blocking_desc()) {
+ return memory_desc_init_by_blocking_desc(dst_md_,
+ src_d.blocking_desc());
+ }
+ }
+
+ if (src_mds_[0].format_kind != format_kind::blocked)
+ return status::unimplemented;
+
+ dst_md_ = src_mds_[0];
+
+ return status::success;
+ }
+};
+
+#define DECLARE_SUM_PD_t(impl_name, ...) \
+ static status_t create(sum_pd_t **sum_pd, \
+ engine_t *engine, const primitive_attr_t *attr, \
+ const memory_desc_t *dst_md, int n, const float *scales, \
+ const memory_desc_t *src_mds) { \
+ using namespace status; \
+ auto _pd = new pd_t(engine, attr, dst_md, n, scales, src_mds); \
+ if (_pd == nullptr) return out_of_memory; \
+ if (_pd->init() != success) { delete _pd; return unimplemented; } \
+ return safe_ptr_assign<sum_pd_t>(*sum_pd, _pd); \
+ } \
+ virtual status_t create_primitive(primitive_t **p) const override { \
+ double ms = get_msec(); \
+ auto ret = safe_ptr_assign<primitive_t>(*p, new (__VA_ARGS__)(this)); \
+ ms = get_msec() - ms; \
+ if (mkldnn_verbose()->level >= 2) { \
+ printf("mkldnn_verbose,create,%s,%g\n", this->info(), ms); \
+ fflush(0); \
+ } \
+ return ret; \
+ } \
+ virtual pd_t *clone() const override { return new pd_t(*this); } \
+ virtual const char *name() const override { return impl_name; } \
+
+#define DECLARE_SUM_PD_T(impl_name, ...) \
+ DECLARE_SUM_PD_t(impl_name, __VA_ARGS__)
+
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/tag_traits.hpp b/thirdparty/oidn/mkl-dnn/src/common/tag_traits.hpp
new file mode 100644
index 0000000000..a408f45980
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/tag_traits.hpp
@@ -0,0 +1,200 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef TAG_TRAITS_HPP
+#define TAG_TRAITS_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+enum class block_dim_t {
+ _,
+ _A, _B,
+ _AB, _BC,
+};
+
+enum class inner_blk_t {
+ _,
+ _4a, _4b,
+ _8a, _8b,
+ _16a, _16b,
+
+ _4b4a, _4b4c, _4c4b,
+ _8a8b, _8b8a, _8b8c, _8c8b,
+ _16a16b, _16a4b, _16b16a, _16b4c, _16b16c, _16c16b,
+
+ _2c8b4c, _8a16b2a, _4b16a4b, _8b16a2b, _8b16c2b, _4c16b4c, _8c16b2c,
+};
+
+/** returns the offset within the block for weights blocked over oc and ic */
+template <inner_blk_t f>
+constexpr int AB_or_BC_blk_off(int x0, int x1) {
+ using ib = inner_blk_t;
+ static_assert(utils::one_of(f, ib::_4b4a, ib::_4b4c, ib::_4c4b, ib::_8a8b,
+ ib::_8b8a, ib::_8b8c, ib::_8c8b, ib::_16a16b, ib::_16a4b,
+ ib::_16b16a, ib::_16b4c, ib::_16b16c, ib::_16c16b, ib::_2c8b4c,
+ ib::_8a16b2a, ib::_4b16a4b, ib::_8b16a2b, ib::_8b16c2b,
+ ib::_4c16b4c, ib::_8c16b2c),
+ "unexpected inner_blk format");
+ return false ? 0
+ : (f == ib::_4b4c) ? 4 * x0 + x1
+ : (f == ib::_4b4a || f == ib::_4c4b) ? 4 * x1 + x0
+ : (f == ib::_8a8b || f == ib::_8b8c) ? 8 * x0 + x1
+ : (f == ib::_8b8a || f == ib::_8c8b) ? 8 * x1 + x0
+ : (f == ib::_16a16b || f == ib::_16b16c) ? 16 * x0 + x1
+ : (f == ib::_16b16a || f == ib::_16c16b) ? 16 * x1 + x0
+ : (f == ib::_16a4b || f == ib::_16b4c) ? 4 * x0 + x1
+ : (f == ib::_8a16b2a || f == ib::_8b16c2b) ? (x0 / 2) * 32 + x1 * 2 + x0 % 2
+ : (f == ib::_4b16a4b || f == ib::_4c16b4c) ? (x1 / 4) * 64 + x0 * 4 + x1 % 4
+ : (f == ib::_8b16a2b || f == ib::_8c16b2c) ? (x1 / 2) * 32 + x0 * 2 + x1 % 2
+ : (f == ib::_2c8b4c) ? (x1 / 4) * 32 + x0 * 4 + x1 % 4
+ : INT_MIN;
+}
+
+template <inner_blk_t b> struct inner_blk_traits {
+ using ib = inner_blk_t;
+};
+
+template <format_tag_t> struct tag_traits {
+ // block_dim_t block_dims;
+ // inner_blk_t inner_blks;
+ // int ndims;
+};
+
+#define DECL_TRAITS(_tag, _blk_fmt, _inner_blk, _ndims) \
+template <> struct tag_traits<format_tag::_tag> { \
+ static constexpr block_dim_t block_dims = block_dim_t::_blk_fmt; \
+ static constexpr inner_blk_t inner_blks = inner_blk_t::_inner_blk; \
+ static constexpr int ndims = _ndims; \
+}
+
+DECL_TRAITS(a, _, _, 1);
+DECL_TRAITS(ab, _, _, 2);
+DECL_TRAITS(abc, _, _, 3);
+DECL_TRAITS(abcd, _, _, 4);
+DECL_TRAITS(abcde, _, _, 5);
+DECL_TRAITS(abcdef, _, _, 6);
+DECL_TRAITS(abdec, _, _, 5);
+DECL_TRAITS(acb, _, _, 3);
+DECL_TRAITS(acbde, _, _, 5);
+DECL_TRAITS(acdb, _, _, 4);
+DECL_TRAITS(acdeb, _, _, 5);
+DECL_TRAITS(ba, _, _, 2);
+DECL_TRAITS(bac, _, _, 3);
+DECL_TRAITS(bacd, _, _, 4);
+DECL_TRAITS(bcda, _, _, 4);
+DECL_TRAITS(cba, _, _, 3);
+DECL_TRAITS(cdba, _, _, 4);
+DECL_TRAITS(cdeba, _, _, 5);
+DECL_TRAITS(decab, _, _, 5);
+
+DECL_TRAITS(Abc4a, _A, _4a, 3);
+DECL_TRAITS(aBc4b, _B, _4b, 3);
+DECL_TRAITS(ABc4b16a4b, _AB, _4b16a4b, 3);
+DECL_TRAITS(ABc4b4a, _AB, _4b4a, 3);
+DECL_TRAITS(Abcd4a, _A, _4a, 4);
+DECL_TRAITS(aBcd4b, _B, _4b, 4);
+DECL_TRAITS(ABcd4b4a, _AB, _4b4a, 4);
+DECL_TRAITS(aBCd4c16b4c, _BC, _4c16b4c, 4);
+DECL_TRAITS(aBCd4c4b, _BC, _4c4b, 4);
+DECL_TRAITS(Abcde4a, _A, _4a, 5);
+DECL_TRAITS(aBcde4b, _B, _4b, 5);
+DECL_TRAITS(ABcde4b4a, _AB, _4b4a, 5);
+DECL_TRAITS(aBCde4c4b, _BC, _4c4b, 5);
+DECL_TRAITS(aBcdef4b, _B, _4b, 6);
+DECL_TRAITS(aBCdef4c4b, _BC, _4c4b, 6);
+DECL_TRAITS(aBdc4b, _B, _4b, 4);
+DECL_TRAITS(aBdec4b, _B, _4b, 5);
+DECL_TRAITS(aBdefc4b, _B, _4b, 6);
+DECL_TRAITS(Acb4a, _A, _4a, 3);
+DECL_TRAITS(Acdb4a, _A, _4a, 4);
+DECL_TRAITS(Acdeb4a, _A, _4a, 5);
+
+DECL_TRAITS(Abc16a, _A, _16a, 3);
+DECL_TRAITS(ABc16a16b, _AB, _16a16b, 3);
+DECL_TRAITS(aBc16b, _B, _16b, 3);
+DECL_TRAITS(ABc16b16a, _AB, _16b16a, 3);
+DECL_TRAITS(ABc8a16b2a, _AB, _8a16b2a, 3);
+DECL_TRAITS(ABc8a8b, _AB, _8a8b, 3);
+DECL_TRAITS(aBc8b, _B, _8b, 3);
+DECL_TRAITS(ABc8b16a2b, _AB, _8b16a2b, 3);
+DECL_TRAITS(ABc8b8a, _AB, _8b8a, 3);
+DECL_TRAITS(Abcd16a, _A, _16a, 4);
+DECL_TRAITS(ABcd16a16b, _AB, _16a16b, 4);
+DECL_TRAITS(aBcd16b, _B, _16b, 4);
+DECL_TRAITS(ABcd16b16a, _AB, _16b16a, 4);
+DECL_TRAITS(aBCd16b16c, _BC, _16b16c, 4);
+DECL_TRAITS(aBCd16c16b, _BC, _16c16b, 4);
+DECL_TRAITS(ABcd4b16a4b, _AB, _4b16a4b, 4);
+DECL_TRAITS(ABcd8a16b2a, _AB, _8a16b2a, 4);
+DECL_TRAITS(ABcd8a8b, _AB, _8a8b, 4);
+DECL_TRAITS(aBcd8b, _B, _8b, 4);
+DECL_TRAITS(ABcd8b16a2b, _AB, _8b16a2b, 4);
+DECL_TRAITS(aBCd8b16c2b, _BC, _8b16c2b, 4);
+DECL_TRAITS(ABcd8b8a, _AB, _8b8a, 4);
+DECL_TRAITS(aBCd8b8c, _BC, _8b8c, 4);
+DECL_TRAITS(aBCd8c16b2c, _BC, _8c16b2c, 4);
+DECL_TRAITS(aBCd8c8b, _BC, _8c8b, 4);
+DECL_TRAITS(Abcde16a, _A, _16a, 5);
+DECL_TRAITS(ABcde16a16b, _AB, _16a16b, 5);
+DECL_TRAITS(aBcde16b, _B, _16b, 5);
+DECL_TRAITS(ABcde16b16a, _AB, _16b16a, 5);
+DECL_TRAITS(aBCde16b16c, _BC, _16b16c, 5);
+DECL_TRAITS(aBCde16c16b, _BC, _16c16b, 5);
+DECL_TRAITS(aBCde4c16b4c, _BC, _4c16b4c, 5);
+DECL_TRAITS(Abcde8a, _A, _8a, 5);
+DECL_TRAITS(ABcde8a8b, _AB, _8a8b, 5);
+DECL_TRAITS(aBcde8b, _B, _8b, 5);
+DECL_TRAITS(ABcde8b16a2b, _AB, _8b16a2b, 5);
+DECL_TRAITS(aBCde8b16c2b, _BC, _8b16c2b, 5);
+DECL_TRAITS(ABcde8b8a, _AB, _8b8a, 5);
+DECL_TRAITS(aBCde8b8c, _BC, _8b8c, 5);
+DECL_TRAITS(aBCde2c8b4c, _BC, _2c8b4c, 5);
+DECL_TRAITS(aBCde8c16b2c, _BC, _8c16b2c, 5);
+DECL_TRAITS(aBCde4b4c, _BC, _4b4c, 5);
+DECL_TRAITS(aBCde8c8b, _BC, _8c8b, 5);
+DECL_TRAITS(aBcdef16b, _B, _16b, 6);
+DECL_TRAITS(aBCdef16b16c, _BC, _16b16c, 6);
+DECL_TRAITS(aBCdef16c16b, _BC, _16c16b, 6);
+DECL_TRAITS(aBCdef8b8c, _BC, _8b8c, 6);
+DECL_TRAITS(aBCdef8c16b2c, _BC, _8c16b2c, 6);
+DECL_TRAITS(aBCdef8c8b, _BC, _8c8b, 6);
+DECL_TRAITS(aBdc16b, _B, _16b, 4);
+DECL_TRAITS(aBdc8b, _B, _8b, 4);
+DECL_TRAITS(aBdec16b, _B, _16b, 5);
+DECL_TRAITS(aBdec8b, _B, _8b, 5);
+DECL_TRAITS(aBdefc16b, _B, _16b, 6);
+DECL_TRAITS(aBdefc8b, _B, _8b, 6);
+DECL_TRAITS(Acb16a, _A, _16a, 3);
+DECL_TRAITS(Acb8a, _A, _8a, 3);
+DECL_TRAITS(aCBd16b16c, _BC, _16b16c, 4);
+DECL_TRAITS(aCBde16b16c, _BC, _16b16c, 5);
+DECL_TRAITS(Acdb16a, _A, _16a, 4);
+DECL_TRAITS(Acdb8a, _A, _8a, 4);
+DECL_TRAITS(Acdeb16a, _A, _16a, 5);
+DECL_TRAITS(Acdeb8a, _A, _8a, 5);
+DECL_TRAITS(BAc16a16b, _AB, _16a16b, 3);
+DECL_TRAITS(BAcd16a16b, _AB, _16a16b, 4);
+
+} // namespace impl
+} // namespace mkldnn
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/type_helpers.hpp b/thirdparty/oidn/mkl-dnn/src/common/type_helpers.hpp
new file mode 100644
index 0000000000..4f06368738
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/type_helpers.hpp
@@ -0,0 +1,348 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef TYPE_HELPERS_HPP
+#define TYPE_HELPERS_HPP
+
+#include <assert.h>
+#include <math.h>
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "mkldnn_traits.hpp"
+#include "nstl.hpp"
+#include "utils.hpp"
+#include "math_utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+template <typename T>
+status_t safe_ptr_assign(T * &lhs, T* rhs) {
+ if (rhs == nullptr) return status::out_of_memory;
+ lhs = rhs;
+ return status::success;
+}
+
+template <typename T, typename U> struct is_subset
+{ static constexpr bool value = false; };
+template <typename T> struct is_subset<T, T>
+{ static constexpr bool value = true; };
+template <typename T> struct is_subset<T,
+ typename utils::enable_if<nstl::is_integral<T>::value, float>::type>
+{ static constexpr bool value = true; };
+#define ISSPEC(t1, t2) template <> \
+ struct is_subset<t1, t2> { static constexpr bool value = true; }
+ISSPEC(int16_t, int32_t);
+ISSPEC(int8_t, int32_t);
+ISSPEC(uint8_t, int32_t);
+ISSPEC(int8_t, int16_t);
+ISSPEC(uint8_t, int16_t);
+#undef ISSPEC
+
+inline bool operator==(const memory_desc_t &lhs, const memory_desc_t &rhs);
+
+namespace types {
+
+inline size_t data_type_size(data_type_t data_type) {
+ using namespace data_type;
+ switch (data_type) {
+ case f32: return sizeof(prec_traits<f32>::type);
+ case s32: return sizeof(prec_traits<s32>::type);
+ case s8: return sizeof(prec_traits<s8>::type);
+ case u8: return sizeof(prec_traits<u8>::type);
+ case data_type::undef:
+ default: assert(!"unknown data_type");
+ }
+ return 0; /* not supposed to be reachable */
+}
+
+inline format_kind_t format_tag_to_kind(format_tag_t tag) {
+ switch (tag) {
+ case format_tag::undef: return format_kind::undef;
+ case format_tag::any: return format_kind::any;
+ case format_tag::last: return format_kind::undef;
+ default: return format_kind::blocked;
+ }
+
+ assert(!"unreachable");
+ return format_kind::undef;
+}
+
+inline bool memory_extra_desc_is_equal(const memory_extra_desc_t &lhs,
+ const memory_extra_desc_t &rhs) {
+ return true
+ && lhs.flags == rhs.flags
+ && IMPLICATION(lhs.flags & memory_extra_flags::compensation_conv_s8s8,
+ lhs.compensation_mask == rhs.compensation_mask)
+ && IMPLICATION(lhs.flags & memory_extra_flags::scale_adjust,
+ lhs.scale_adjust == rhs.scale_adjust);
+}
+
+inline bool blocking_desc_is_equal(const blocking_desc_t &lhs,
+ const blocking_desc_t &rhs, int ndims = MKLDNN_MAX_NDIMS) {
+ using mkldnn::impl::utils::array_cmp;
+ return true
+ && lhs.inner_nblks == rhs.inner_nblks
+ && array_cmp(lhs.strides, rhs.strides, ndims)
+ && array_cmp(lhs.inner_blks, rhs.inner_blks, lhs.inner_nblks)
+ && array_cmp(lhs.inner_idxs, rhs.inner_idxs, lhs.inner_nblks);
+}
+
+inline bool wino_desc_is_equal(const wino_desc_t &lhs,
+ const wino_desc_t &rhs) {
+ return lhs.wino_format == rhs.wino_format
+ && lhs.alpha == rhs.alpha
+ && lhs.ic == rhs.ic
+ && lhs.oc == rhs.oc
+ && lhs.ic_block == rhs.ic_block
+ && lhs.oc_block == rhs.oc_block
+ && lhs.ic2_block == rhs.ic2_block
+ && lhs.oc2_block == rhs.oc2_block
+ && lhs.r == rhs.r;
+}
+
+inline bool rnn_packed_desc_is_equal(
+ const rnn_packed_desc_t &lhs, const rnn_packed_desc_t &rhs) {
+ bool ok = true
+ && lhs.format == rhs.format
+ && lhs.n_parts == rhs.n_parts
+ && lhs.offset_compensation == rhs.offset_compensation
+ && lhs.size == rhs.size
+ && lhs.n == rhs.n;
+ if (!ok)
+ return false;
+
+ for (int i = 0; i < rhs.n_parts; i++)
+ ok = ok && lhs.parts[i] == rhs.parts[i];
+ for (int i = 0; i < rhs.n_parts; i++)
+ ok = ok && lhs.part_pack_size[i] == rhs.part_pack_size[i];
+ return ok;
+}
+
+inline memory_desc_t zero_md() {
+ auto zero = memory_desc_t();
+ return zero;
+}
+
+inline bool is_zero_md(const memory_desc_t *md) {
+ return md == nullptr || *md == zero_md();
+}
+
+inline data_type_t default_accum_data_type(data_type_t src_dt,
+ data_type_t dst_dt) {
+ using namespace utils;
+ using namespace data_type;
+
+ if (one_of(f32, src_dt, dst_dt)) return f32;
+ if (one_of(s32, src_dt, dst_dt)) return s32;
+
+ if (one_of(s8, src_dt, dst_dt) || one_of(u8, src_dt, dst_dt)) return s32;
+
+ assert(!"unimplemented use-case: no default parameters available");
+ return dst_dt;
+}
+
+inline data_type_t default_accum_data_type(data_type_t src_dt,
+ data_type_t wei_dt, data_type_t dst_dt, prop_kind_t prop_kind) {
+ using namespace utils;
+ using namespace data_type;
+ using namespace prop_kind;
+
+ /* prop_kind doesn't matter */
+ if (everyone_is(f32, src_dt, wei_dt, dst_dt)) return f32;
+
+ if (one_of(prop_kind, forward_training, forward_inference)) {
+ if ((src_dt == u8 || src_dt == s8)
+ && wei_dt == s8 && one_of(dst_dt, f32, s32, s8, u8))
+ return s32;
+ } else if (prop_kind == backward_data) {
+ if (one_of(src_dt, f32, s32, s8, u8) && wei_dt == s8 &&
+ one_of(dst_dt, s8, u8))
+ return s32;
+ }
+
+ assert(!"unimplemented use-case: no default parameters available");
+ return dst_dt;
+}
+
+}
+
+inline bool operator==(const memory_desc_t &lhs, const memory_desc_t &rhs) {
+ using namespace mkldnn::impl::utils;
+ bool base_equal = true
+ && lhs.ndims == rhs.ndims
+ && array_cmp(lhs.dims, rhs.dims, lhs.ndims)
+ && lhs.data_type == rhs.data_type
+ && array_cmp(lhs.padded_dims, rhs.padded_dims, lhs.ndims)
+ && array_cmp(lhs.padded_offsets, rhs.padded_offsets, lhs.ndims)
+ && lhs.offset0 == rhs.offset0
+ && lhs.format_kind == rhs.format_kind;
+ if (!base_equal) return false;
+ if (!types::memory_extra_desc_is_equal(lhs.extra, rhs.extra)) return false;
+ if (lhs.format_kind == format_kind::blocked)
+ return types::blocking_desc_is_equal(lhs.format_desc.blocking,
+ rhs.format_desc.blocking, lhs.ndims);
+ else if (lhs.format_kind == format_kind::wino)
+ return types::wino_desc_is_equal(lhs.format_desc.wino_desc,
+ rhs.format_desc.wino_desc);
+ else if (lhs.format_kind == format_kind::rnn_packed)
+ return types::rnn_packed_desc_is_equal(lhs.format_desc.rnn_packed_desc,
+ rhs.format_desc.rnn_packed_desc);
+ return true;
+}
+
+inline bool operator!=(const memory_desc_t &lhs, const memory_desc_t &rhs) {
+ return !operator==(lhs, rhs);
+}
+
+inline status_t memory_desc_init_by_strides(memory_desc_t &md,
+ const dims_t strides) {
+ return mkldnn_memory_desc_init_by_strides(
+ &md, md.ndims, md.dims, md.data_type, strides);
+}
+
+inline status_t memory_desc_init_by_tag(memory_desc_t &md, format_tag_t tag,
+ const dims_t strides = nullptr) {
+ status_t status = mkldnn_memory_desc_init_by_tag(
+ &md, md.ndims, md.dims, md.data_type, tag);
+ if (status != status::success || strides == nullptr)
+ return status;
+
+ /* TODO: add consistency check */
+
+ for (int d = 0; d < md.ndims; ++d)
+ md.format_desc.blocking.strides[d] = strides[d];
+
+ return status::success;
+}
+
+/** inits memory descriptor based on logical dimensions kept in @p md, and the
+ * blocking structure @p blk.
+ *
+ * @note blk.strides represent the order only (from smaller to bigger)
+ *
+ * TODO: move md related functions to one single place
+ */
+inline status_t memory_desc_init_by_blocking_desc(memory_desc_t &md,
+ const blocking_desc_t &blk) {
+ dims_t blocks = {0};
+ utils::array_set(blocks, 1, md.ndims);
+ dim_t block_size = 1;
+ for (int iblk = 0; iblk < blk.inner_nblks; ++iblk) {
+ blocks[blk.inner_idxs[iblk]] *= blk.inner_blks[iblk];
+ block_size *= blk.inner_blks[iblk];
+ }
+
+ for (int d = 0; d < md.ndims; ++d) {
+ md.padded_dims[d] = utils::rnd_up(md.dims[d], blocks[d]);
+ md.padded_offsets[d] = 0;
+ }
+ md.offset0 = 0;
+
+ md.format_kind = format_kind::blocked;
+ auto &mblk = md.format_desc.blocking;
+ mblk = blk;
+
+ const int ndims = nstl::min(MKLDNN_MAX_NDIMS, md.ndims); // make GCC 5 happy
+ utils::array_copy(mblk.strides, blk.strides, ndims);
+
+ int perm[MKLDNN_MAX_NDIMS];
+ for (int d = 0; d < ndims; ++d) perm[d] = d;
+
+ utils::simultaneous_sort(mblk.strides, perm, ndims,
+ [](stride_t a, stride_t b) { return b - a; });
+
+ dim_t stride = block_size;
+ for (int _d = ndims - 1; _d >= 0; --_d) {
+ const int d = perm[_d];
+ md.format_desc.blocking.strides[d] = stride;
+ stride *= md.padded_dims[d] / blocks[d];
+ }
+
+ md.extra = utils::zero<memory_extra_desc_t>();
+
+ return status::success;
+}
+
+/** returns true if memory desc @p md corresponds to the given format tag and
+ * strides.
+ * If strides are not passed (or passed as nullptr) the dense structure is
+ * assumed (i.e. the one that mkldnn_memory_desc_init_by_tag() returns).
+ * Strides might contain `0` value, indicating the stride must match the one
+ * that mkldnn_memory_desc_init_by_tag() returns.
+ * Strides might contain `-1` values, that would be ignored during the
+ * comparison. For instance, this can be used if a stride along minibatch
+ * doesn't matter. */
+inline bool memory_desc_matches_tag(const memory_desc_t &md, format_tag_t tag,
+ const dims_t strides = nullptr) {
+ if (md.format_kind != types::format_tag_to_kind(tag))
+ return false;
+
+ memory_desc_t md_gold;
+ status_t status = mkldnn_memory_desc_init_by_tag(
+ &md_gold, md.ndims, md.dims, md.data_type, tag);
+ if (status != status::success) return false;
+
+ if (md.format_kind != format_kind::blocked)
+ return false; // unimplemented yet
+
+ const auto &blk = md.format_desc.blocking;
+ const auto &blk_gold = md_gold.format_desc.blocking;
+
+ using utils::array_cmp;
+ bool same_blocks = true
+ && blk.inner_nblks == blk_gold.inner_nblks
+ && array_cmp(blk.inner_blks, blk_gold.inner_blks, blk.inner_nblks)
+ && array_cmp(blk.inner_idxs, blk_gold.inner_idxs, blk.inner_nblks);
+
+ if (!same_blocks)
+ return false;
+
+ if (strides == nullptr)
+ return array_cmp(blk.strides, blk_gold.strides, md.ndims);
+
+ for (int d = 0; d < md.ndims; ++d) {
+ dim_t stride = strides[d];
+ if (stride == -1) continue;
+ if (stride == 0) stride = blk_gold.strides[d];
+ if (blk.strides[d] != stride) return false;
+ }
+
+ return true;
+}
+
+/** returns matching tag (or undef if match is not found)
+ * XXX: This is a workaround that eventually should go away! */
+template <typename... Tags>
+format_tag_t memory_desc_matches_one_of_tag(const memory_desc_t &md,
+ Tags ...tags) {
+ for (const auto tag: {tags...}) {
+ if (memory_desc_matches_tag(md, tag))
+ return tag;
+ }
+ return format_tag::undef;
+}
+
+}
+}
+
+#include "memory_desc_wrapper.hpp"
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/utils.cpp b/thirdparty/oidn/mkl-dnn/src/common/utils.cpp
new file mode 100644
index 0000000000..d23f4682dc
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/utils.cpp
@@ -0,0 +1,135 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <string.h>
+#ifdef _WIN32
+#include <malloc.h>
+#include <windows.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "mkldnn.h"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+int getenv(const char *name, char *buffer, int buffer_size) {
+ if (name == NULL || buffer_size < 0 || (buffer == NULL && buffer_size > 0))
+ return INT_MIN;
+
+ int result = 0;
+ int term_zero_idx = 0;
+ size_t value_length = 0;
+
+#ifdef _WIN32
+ value_length = GetEnvironmentVariable(name, buffer, buffer_size);
+#else
+ const char *value = ::getenv(name);
+ value_length = value == NULL ? 0 : strlen(value);
+#endif
+
+ if (value_length > INT_MAX)
+ result = INT_MIN;
+ else {
+ int int_value_length = (int)value_length;
+ if (int_value_length >= buffer_size) {
+ result = -int_value_length;
+ } else {
+ term_zero_idx = int_value_length;
+ result = int_value_length;
+#ifndef _WIN32
+ strncpy(buffer, value, value_length);
+#endif
+ }
+ }
+
+ if (buffer != NULL)
+ buffer[term_zero_idx] = '\0';
+ return result;
+}
+
+int getenv_int(const char *name, int default_value)
+{
+ int value = default_value;
+ // # of digits in the longest 32-bit signed int + sign + terminating null
+ const int len = 12;
+ char value_str[len];
+ if (getenv(name, value_str, len) > 0)
+ value = atoi(value_str);
+ return value;
+}
+
+FILE *fopen(const char *filename, const char *mode) {
+#ifdef _WIN32
+ FILE *fp = NULL;
+ return ::fopen_s(&fp, filename, mode) ? NULL : fp;
+#else
+ return ::fopen(filename, mode);
+#endif
+}
+
+void *malloc(size_t size, int alignment) {
+ void *ptr;
+
+#ifdef _WIN32
+ ptr = _aligned_malloc(size, alignment);
+ int rc = ptr ? 0 : -1;
+#else
+ int rc = ::posix_memalign(&ptr, alignment, size);
+#endif
+
+ return (rc == 0) ? ptr : 0;
+}
+
+void free(void *p) {
+#ifdef _WIN32
+ _aligned_free(p);
+#else
+ ::free(p);
+#endif
+}
+
+// Atomic operations
+int32_t fetch_and_add(int32_t *dst, int32_t val) {
+#ifdef _WIN32
+ return InterlockedExchangeAdd(reinterpret_cast<long*>(dst), val);
+#else
+ return __sync_fetch_and_add(dst, val);
+#endif
+}
+
+static int jit_dump_flag = 0;
+static bool jit_dump_flag_initialized = false;
+bool jit_dump_enabled() {
+ if (!jit_dump_flag_initialized) {
+ jit_dump_flag = getenv_int("MKLDNN_JIT_DUMP");
+ jit_dump_flag_initialized = true;
+ }
+ return jit_dump_flag != 0;
+}
+
+}
+}
+
+mkldnn_status_t mkldnn_set_jit_dump(int enabled) {
+ using namespace mkldnn::impl::status;
+ mkldnn::impl::jit_dump_flag = enabled;
+ mkldnn::impl::jit_dump_flag_initialized = true;
+ return success;
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/utils.hpp b/thirdparty/oidn/mkl-dnn/src/common/utils.hpp
new file mode 100644
index 0000000000..d5a8ec5139
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/utils.hpp
@@ -0,0 +1,370 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef UTILS_HPP
+#define UTILS_HPP
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdint.h>
+
+#if defined(__x86_64__) || defined(_M_X64)
+#define MKLDNN_X86_64
+#endif
+
+#define MSAN_ENABLED 0
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+#undef MSAN_ENABLED
+#define MSAN_ENABLED 1
+#include <sanitizer/msan_interface.h>
+#endif
+#endif
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "z_magic.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+// Sanity check for 64 bits
+static_assert(sizeof(void*) == 8, "Intel(R) MKL-DNN supports 64 bit only");
+
+#define CHECK(f) do { \
+ status_t status = f; \
+ if (status != status::success) \
+ return status; \
+} while (0)
+
+#define IMPLICATION(cause, effect) (!(cause) || !!(effect))
+
+namespace utils {
+
+/* a bunch of std:: analogues to be compliant with any msvs version
+ *
+ * Rationale: msvs c++ (and even some c) headers contain special pragma that
+ * injects msvs-version check into object files in order to abi-mismatches
+ * during the static linking. This makes sense if e.g. std:: objects are passed
+ * through between application and library, which is not the case for mkl-dnn
+ * (since there is no any c++-rt dependent stuff, ideally...). */
+
+/* SFINAE helper -- analogue to std::enable_if */
+template<bool expr, class T = void> struct enable_if {};
+template<class T> struct enable_if<true, T> { typedef T type; };
+
+/* analogue std::conditional */
+template <bool, typename, typename> struct conditional {};
+template <typename T, typename F> struct conditional<true, T, F>
+{ typedef T type; };
+template <typename T, typename F> struct conditional<false, T, F>
+{ typedef F type; };
+
+template <bool, typename, bool, typename, typename> struct conditional3 {};
+template <typename T, typename FT, typename FF>
+struct conditional3<true, T, false, FT, FF> { typedef T type; };
+template <typename T, typename FT, typename FF>
+struct conditional3<false, T, true, FT, FF> { typedef FT type; };
+template <typename T, typename FT, typename FF>
+struct conditional3<false, T, false, FT, FF> { typedef FF type; };
+
+template <bool, typename U, U, U> struct conditional_v {};
+template <typename U, U t, U f> struct conditional_v<true, U, t, f>
+{ static constexpr U value = t; };
+template <typename U, U t, U f> struct conditional_v<false, U, t, f>
+{ static constexpr U value = f; };
+
+template <typename T> struct remove_reference { typedef T type; };
+template <typename T> struct remove_reference<T&> { typedef T type; };
+template <typename T> struct remove_reference<T&&> { typedef T type; };
+
+template <typename T>
+inline T&& forward(typename utils::remove_reference<T>::type &t)
+{ return static_cast<T&&>(t); }
+template <typename T>
+inline T&& forward(typename utils::remove_reference<T>::type &&t)
+{ return static_cast<T&&>(t); }
+
+template <typename T>
+inline typename remove_reference<T>::type zero()
+{ auto zero = typename remove_reference<T>::type(); return zero; }
+
+template <typename T, typename P>
+inline bool everyone_is(T val, P item) { return val == item; }
+template <typename T, typename P, typename... Args>
+inline bool everyone_is(T val, P item, Args... item_others) {
+ return val == item && everyone_is(val, item_others...);
+}
+
+template <typename T, typename P>
+constexpr bool one_of(T val, P item) { return val == item; }
+template <typename T, typename P, typename... Args>
+constexpr bool one_of(T val, P item, Args... item_others) {
+ return val == item || one_of(val, item_others...);
+}
+
+template <typename... Args>
+inline bool any_null(Args... ptrs) { return one_of(nullptr, ptrs...); }
+
+template<typename T>
+inline void array_copy(T *dst, const T *src, size_t size) {
+ for (size_t i = 0; i < size; ++i) dst[i] = src[i];
+}
+template<typename T>
+inline bool array_cmp(const T *a1, const T *a2, size_t size) {
+ for (size_t i = 0; i < size; ++i) if (a1[i] != a2[i]) return false;
+ return true;
+}
+template<typename T, typename U>
+inline void array_set(T *arr, const U& val, size_t size) {
+ for (size_t i = 0; i < size; ++i) arr[i] = static_cast<T>(val);
+}
+
+namespace product_impl {
+template<size_t> struct int2type{};
+
+template <typename T>
+constexpr int product_impl(const T *arr, int2type<0>) { return arr[0]; }
+
+template <typename T, size_t num>
+inline T product_impl(const T *arr, int2type<num>) {
+ return arr[0]*product_impl(arr+1, int2type<num-1>()); }
+}
+
+template <size_t num, typename T>
+inline T array_product(const T *arr) {
+ return product_impl::product_impl(arr, product_impl::int2type<num-1>());
+}
+
+template<typename T, typename R = T>
+inline R array_product(const T *arr, size_t size) {
+ R prod = 1;
+ for (size_t i = 0; i < size; ++i) prod *= arr[i];
+ return prod;
+}
+
+/** sorts an array of values using @p comparator. While sorting the array
+ * of value, the function permutes an array of @p keys accordingly.
+ *
+ * @note The arrays of @p keys can be omitted. In this case the function
+ * sorts the array of @vals only.
+ */
+template <typename T, typename U, typename F>
+inline void simultaneous_sort(T *vals, U *keys, size_t size, F comparator) {
+ if (size == 0) return;
+
+ for (size_t i = 0; i < size - 1; ++i) {
+ bool swapped = false;
+
+ for (size_t j = 0; j < size - i - 1; j++) {
+ if (comparator(vals[j], vals[j + 1]) > 0) {
+ nstl::swap(vals[j], vals[j + 1]);
+ if (keys) nstl::swap(keys[j], keys[j + 1]);
+ swapped = true;
+ }
+ }
+
+ if (swapped == false) break;
+ }
+}
+
+template <typename T, typename U>
+inline typename remove_reference<T>::type div_up(const T a, const U b) {
+ assert(b);
+ return (a + b - 1) / b;
+}
+
+template <typename T, typename U>
+inline typename remove_reference<T>::type rnd_up(const T a, const U b) {
+ return div_up(a, b) * b;
+}
+
+template <typename T, typename U>
+inline typename remove_reference<T>::type rnd_dn(const T a, const U b) {
+ return (a / b) * b;
+}
+
+template <typename T> T *align_ptr(T *ptr, uintptr_t alignment)
+{ return (T *)(((uintptr_t)ptr + alignment - 1) & ~(alignment - 1)); }
+
+template <typename T, typename U, typename V>
+inline U this_block_size(const T offset, const U max, const V block_size) {
+ assert(offset < max);
+ // TODO (Roma): can't use nstl::max() due to circular dependency... we
+ // need to fix this
+ const T block_boundary = offset + block_size;
+ if (block_boundary > max)
+ return max - offset;
+ else
+ return block_size;
+}
+
+template<typename T>
+inline T nd_iterator_init(T start) { return start; }
+template<typename T, typename U, typename W, typename... Args>
+inline T nd_iterator_init(T start, U &x, const W &X, Args &&... tuple) {
+ start = nd_iterator_init(start, utils::forward<Args>(tuple)...);
+ x = start % X;
+ return start / X;
+}
+
+inline bool nd_iterator_step() { return true; }
+template<typename U, typename W, typename... Args>
+inline bool nd_iterator_step(U &x, const W &X, Args &&... tuple) {
+ if (nd_iterator_step(utils::forward<Args>(tuple)...) ) {
+ x = (x + 1) % X;
+ return x == 0;
+ }
+ return false;
+}
+
+template<typename U, typename W, typename Y>
+inline bool nd_iterator_jump(U &cur, const U end, W &x, const Y &X)
+{
+ U max_jump = end - cur;
+ U dim_jump = X - x;
+ if (dim_jump <= max_jump) {
+ x = 0;
+ cur += dim_jump;
+ return true;
+ } else {
+ cur += max_jump;
+ x += max_jump;
+ return false;
+ }
+}
+template<typename U, typename W, typename Y, typename... Args>
+inline bool nd_iterator_jump(U &cur, const U end, W &x, const Y &X,
+ Args &&... tuple)
+{
+ if (nd_iterator_jump(cur, end, utils::forward<Args>(tuple)...)) {
+ x = (x + 1) % X;
+ return x == 0;
+ }
+ return false;
+}
+
+template <typename T>
+inline T pick(size_t i, const T &x0) { return x0; }
+template <typename T, typename ...Args>
+inline T pick(size_t i, const T &x0, Args &&... args) {
+ return i == 0 ? x0 : pick(i - 1, utils::forward<Args>(args)...);
+}
+
+template <typename T>
+T pick_by_prop_kind(prop_kind_t prop_kind, const T &val_fwd_inference,
+ const T &val_fwd_training, const T &val_bwd_d, const T &val_bwd_w) {
+ switch (prop_kind) {
+ case prop_kind::forward_inference: return val_fwd_inference;
+ case prop_kind::forward_training: return val_fwd_training;
+ case prop_kind::backward_data: return val_bwd_d;
+ case prop_kind::backward_weights: return val_bwd_w;
+ default: assert(!"unsupported prop_kind");
+ }
+ return T();
+}
+
+template <typename T>
+T pick_by_prop_kind(prop_kind_t prop_kind,
+ const T &val_fwd, const T &val_bwd_d, const T &val_bwd_w)
+{ return pick_by_prop_kind(prop_kind, val_fwd, val_fwd, val_bwd_d, val_bwd_w); }
+
+template <typename Telem, size_t Tdims>
+struct array_offset_calculator {
+ template <typename... Targs>
+ array_offset_calculator(Telem *base, Targs... Fargs) : _dims{ Fargs... }
+ {
+ _base_ptr = base;
+ }
+ template <typename... Targs>
+ inline Telem &operator()(Targs... Fargs)
+ {
+ return *(_base_ptr + _offset(1, Fargs...));
+ }
+
+private:
+ template <typename... Targs>
+ inline size_t _offset(size_t const dimension, size_t element)
+ {
+ return element;
+ }
+
+ template <typename... Targs>
+ inline size_t _offset(size_t const dimension, size_t theta, size_t element)
+ {
+ return element + (_dims[dimension] * theta);
+ }
+
+ template <typename... Targs>
+ inline size_t _offset(size_t const dimension, size_t theta, size_t element,
+ Targs... Fargs)
+ {
+ size_t t_prime = element + (_dims[dimension] * theta);
+ return _offset(dimension + 1, t_prime, Fargs...);
+ }
+
+ Telem *_base_ptr;
+ const int _dims[Tdims];
+};
+
+}
+
+int32_t fetch_and_add(int32_t *dst, int32_t val);
+inline void yield_thread() {}
+
+// Reads an environment variable 'name' and stores its string value in the
+// 'buffer' of 'buffer_size' bytes on success.
+//
+// - Returns the length of the environment variable string value (excluding
+// the terminating 0) if it is set and its contents (including the terminating
+// 0) can be stored in the 'buffer' without truncation.
+//
+// - Returns negated length of environment variable string value and writes
+// "\0" to the buffer (if it is not NULL) if the 'buffer_size' is to small to
+// store the value (including the terminating 0) without truncation.
+//
+// - Returns 0 and writes "\0" to the buffer (if not NULL) if the environment
+// variable is not set.
+//
+// - Returns INT_MIN if the 'name' is NULL.
+//
+// - Returns INT_MIN if the 'buffer_size' is negative.
+//
+// - Returns INT_MIN if the 'buffer' is NULL and 'buffer_size' is greater than
+// zero. Passing NULL 'buffer' with 'buffer_size' set to 0 can be used to
+// retrieve the length of the environment variable value string.
+//
+int getenv(const char *name, char *buffer, int buffer_size);
+// Reads an integer from the environment
+int getenv_int(const char *name, int default_value = 0);
+bool jit_dump_enabled();
+FILE *fopen(const char *filename, const char *mode);
+
+constexpr int msan_enabled = MSAN_ENABLED;
+inline void msan_unpoison(void *ptr, size_t size) {
+#if MSAN_ENABLED
+ __msan_unpoison(ptr, size);
+#endif
+}
+
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/common/verbose.cpp b/thirdparty/oidn/mkl-dnn/src/common/verbose.cpp
new file mode 100644
index 0000000000..89a57772cf
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/verbose.cpp
@@ -0,0 +1,665 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <stdlib.h>
+#ifndef _WIN32
+#include <sys/time.h>
+#endif
+
+#include "mkldnn.h"
+#include "mkldnn_version.h"
+#include "c_types_map.hpp"
+#include "verbose.hpp"
+#include "cpu/cpu_isa_traits.hpp"
+
+#include "batch_normalization_pd.hpp"
+#include "pooling_pd.hpp"
+#include "concat_pd.hpp"
+#include "reorder_pd.hpp"
+#include "convolution_pd.hpp"
+#include "rnn_pd.hpp"
+#include "deconvolution_pd.hpp"
+#include "shuffle_pd.hpp"
+#include "eltwise_pd.hpp"
+#include "softmax_pd.hpp"
+#include "inner_product_pd.hpp"
+#include "sum_pd.hpp"
+#include "lrn_pd.hpp"
+
+/* MKL-DNN CPU ISA info */
+#define ISA_ANY "No instruction set specific optimizations"
+#define SSE42 "Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2)"
+#define AVX "Intel(R) Advanced Vector Extensions (Intel(R) AVX)"
+#define AVX2 "Intel(R) Advanced Vector Extensions 2 (Intel(R) AVX2)"
+#define AVX512_COMMON "Intel(R) Advanced Vector Extensions 512 (Intel(R) " \
+ "AVX-512)"
+#define AVX512_CORE "Intel(R) Advanced Vector Extensions 512 (Intel(R) " \
+ "AVX-512) with AVX512BW, AVX512VL, and AVX512DQ extensions"
+#define AVX512_CORE_VNNI "Intel(R) AVX512-Deep Learning Boost (Intel(R) " \
+ "AVX512-DL Boost)"
+#define AVX512_MIC "Intel(R) Advanced Vector Extensions 512 (Intel(R) " \
+ "AVX-512) with AVX512CD, AVX512ER, and AVX512PF extensions"
+#define AVX512_MIC_4OPS "Intel(R) Advanced Vector Extensions 512 (Intel(R) " \
+ "AVX-512) with AVX512_4FMAPS and AVX512_4VNNIW extensions"
+
+namespace mkldnn {
+namespace impl {
+
+static verbose_t verbose;
+static bool initialized;
+static bool version_printed = false;
+
+const verbose_t *mkldnn_verbose() {
+#if !defined(DISABLE_VERBOSE)
+ if (!initialized) {
+ const int len = 2;
+ char val[len] = {0};
+ if (getenv("MKLDNN_VERBOSE", val, len) == 1)
+ verbose.level = atoi(val);
+ initialized = true;
+ }
+ if (!version_printed && verbose.level > 0) {
+ printf("mkldnn_verbose,info,"
+ "Intel(R) MKL-DNN v%d.%d.%d (Git Hash %s),%s\n",
+ mkldnn_version()->major, mkldnn_version()->minor,
+ mkldnn_version()->patch, mkldnn_version()->hash,
+ get_isa_info());
+ version_printed = true;
+ }
+#else
+ verbose.level = 0;
+#endif
+ return &verbose;
+}
+
+double get_msec() {
+#ifdef _WIN32
+ static LARGE_INTEGER frequency;
+ if (frequency.QuadPart == 0)
+ QueryPerformanceFrequency(&frequency);
+ LARGE_INTEGER now;
+ QueryPerformanceCounter(&now);
+ return 1e+3 * now.QuadPart / frequency.QuadPart;
+#else
+ struct timeval time;
+ gettimeofday(&time, NULL);
+ return 1e+3 * time.tv_sec + 1e-3 * time.tv_usec;
+#endif
+}
+
+const char *get_isa_info() {
+ using namespace mkldnn::impl::cpu;
+ if (mayiuse(avx512_mic_4ops)) return AVX512_MIC_4OPS;
+ if (mayiuse(avx512_mic)) return AVX512_MIC;
+ if (mayiuse(avx512_core_vnni)) return AVX512_CORE_VNNI;
+ if (mayiuse(avx512_core)) return AVX512_CORE;
+ if (mayiuse(avx512_common)) return AVX512_COMMON;
+ if (mayiuse(avx2)) return AVX2;
+ if (mayiuse(avx)) return AVX;
+ if (mayiuse(sse42)) return SSE42;
+ return ISA_ANY;
+}
+
+/* init_info section */
+namespace {
+#if !defined(DISABLE_VERBOSE)
+#define MKLDNN_VERBOSE_DAT_LEN 256
+#define MKLDNN_VERBOSE_AUX_LEN 384
+#define MKLDNN_VERBOSE_PRB_LEN 384
+
+#define DECL_DAT_AUX_PRB_STRS() \
+ int dat_written = 0, aux_written = 0, prb_written = 0; \
+ MAYBE_UNUSED((dat_written * aux_written * prb_written)); \
+ char dat_str[MKLDNN_VERBOSE_DAT_LEN] = {'\0'}; MAYBE_UNUSED(dat_str); \
+ char aux_str[MKLDNN_VERBOSE_AUX_LEN] = {'\0'}; MAYBE_UNUSED(aux_str); \
+ char prb_str[MKLDNN_VERBOSE_PRB_LEN] = {'\0'}; MAYBE_UNUSED(prb_str)
+
+#define DFMT "%" PRId64
+
+void clear_buf(char *buf, int &written) {
+ /* TODO: do it better */
+ buf[0] = '#';
+ buf[1] = '\0';
+ written = 1;
+}
+
+#define DPRINT(buf, buf_len, written, ...) do { \
+ int l = snprintf(buf + written, buf_len - written, __VA_ARGS__); \
+ if (l < 0 || written + l > buf_len) { \
+ clear_buf(buf, written); \
+ } else { \
+ written += l; \
+ } \
+} while(0)
+
+// XXX: Outputs strings corresponding to memory formats used for data tensors.
+void format_prb_desc_str(char *str, int len, const memory_desc_t *md) {
+ const auto dims = md->dims;
+ int written = 0;
+ if (md->ndims == 1)
+ DPRINT(str, len, written,
+ "x" DFMT, dims[0]);
+ else if (md->ndims == 2)
+ DPRINT(str, len, written,
+ "mb" DFMT "ic" DFMT, dims[0], dims[1]);
+ else if (md->ndims == 3)
+ DPRINT(str, len, written,
+ "mb" DFMT "ic" DFMT "iw" DFMT,
+ dims[0], dims[1], dims[2]);
+ else if (md->ndims == 4)
+ DPRINT(str, len, written,
+ "mb" DFMT "ic" DFMT "ih" DFMT "iw" DFMT,
+ dims[0], dims[1], dims[2], dims[3]);
+ else if (md->ndims == 5)
+ DPRINT(str, len, written,
+ "mb" DFMT "ic" DFMT "id" DFMT "ih" DFMT "iw" DFMT,
+ dims[0], dims[1], dims[2], dims[3], dims[4]);
+ else
+ mkldnn_md2dim_str(str, len, md);
+}
+
+void verbose_templ(char *buffer, mkldnn_primitive_kind_t prim_kind,
+ const char *impl_str, mkldnn_prop_kind_t prop_kind,
+ const char *data_str, const char *aux_str, const char *prb_str) {
+ MAYBE_UNUSED(verbose_templ);
+ int written = 0;
+ DPRINT(buffer, MKLDNN_VERBOSE_BUF_LEN, written, "%s,%s,%s,%s,%s,%s",
+ mkldnn_prim_kind2str(prim_kind), impl_str,
+ mkldnn_prop_kind2str(prop_kind), data_str, aux_str, prb_str);
+}
+
+template <typename pd_t> static void init_info_bnorm(pd_t *s, char *buffer) {
+ DECL_DAT_AUX_PRB_STRS();
+
+ if (1) { // data
+ auto md = s->src_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "data_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // diff data
+ auto md = s->diff_src_md();
+ if (md) {
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " diff_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ }
+
+ DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written,
+ "flags:%u", s->desc()->flags);
+
+ format_prb_desc_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, s->src_md());
+
+ verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str,
+ aux_str, prb_str);
+}
+
+template <typename pd_t> static void init_info_conv(pd_t *s, char *buffer) {
+ DECL_DAT_AUX_PRB_STRS();
+
+ if (1) { // src
+ auto md = s->desc()->prop_kind == prop_kind::backward_data
+ ? s->diff_src_md() : s->src_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // wei
+ auto md = s->desc()->prop_kind == prop_kind::backward_weights
+ ? s->diff_weights_md() : s->weights_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " wei_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // bia
+ auto md = s->desc()->prop_kind == prop_kind::backward_weights
+ ? s->diff_weights_md(1) : s->weights_md(1);
+ if (md) {
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " bia_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ }
+ if (1) { // dst
+ auto md = !s->is_fwd() ? s->diff_dst_md() : s->dst_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " dst_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+
+ DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written,
+ "alg:%s", mkldnn_alg_kind2str(s->desc()->alg_kind));
+
+ if (s->ndims() == 5) {
+ if (s->with_groups())
+ DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written,
+ "mb" DFMT "_g" DFMT "ic" DFMT "oc" DFMT
+ "_id" DFMT "od" DFMT "kd" DFMT "sd" DFMT "dd" DFMT "pd" DFMT
+ "_ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "dh" DFMT "ph" DFMT
+ "_iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "dw" DFMT "pw" DFMT,
+ s->MB(), s->G(), s->IC(), s->OC(),
+ s->ID(), s->OD(), s->KD(), s->KSD(), s->KDD(), s->padFront(),
+ s->IH(), s->OH(), s->KH(), s->KSH(), s->KDH(), s->padT(),
+ s->IW(), s->OW(), s->KW(), s->KSW(), s->KDW(), s->padL());
+ else
+ DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written,
+ "mb" DFMT "_ic" DFMT "oc" DFMT
+ "_id" DFMT "od" DFMT "kd" DFMT "sd" DFMT "dd" DFMT "pd" DFMT
+ "_ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "dh" DFMT "ph" DFMT
+ "_iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "dw" DFMT "pw" DFMT,
+ s->MB(), s->IC(), s->OC(),
+ s->ID(), s->OD(), s->KD(), s->KSD(), s->KDD(), s->padFront(),
+ s->IH(), s->OH(), s->KH(), s->KSH(), s->KDH(), s->padT(),
+ s->IW(), s->OW(), s->KW(), s->KSW(), s->KDW(), s->padL());
+ } else {
+ if (s->with_groups())
+ DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written,
+ "mb" DFMT "_g" DFMT "ic" DFMT "oc" DFMT
+ "_ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "dh" DFMT "ph" DFMT
+ "_iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "dw" DFMT "pw" DFMT,
+ s->MB(), s->G(), s->IC(), s->OC(),
+ s->IH(), s->OH(), s->KH(), s->KSH(), s->KDH(), s->padT(),
+ s->IW(), s->OW(), s->KW(), s->KSW(), s->KDW(), s->padL());
+ else
+ DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written,
+ "mb" DFMT "_ic" DFMT "oc" DFMT
+ "_ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "dh" DFMT "ph" DFMT
+ "_iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "dw" DFMT "pw" DFMT,
+ s->MB(), s->IC(), s->OC(),
+ s->IH(), s->OH(), s->KH(), s->KSH(), s->KDH(), s->padT(),
+ s->IW(), s->OW(), s->KW(), s->KSW(), s->KDW(), s->padL());
+ }
+
+ verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str,
+ aux_str, prb_str);
+}
+
+template <typename pd_t> static void init_info_shuffle(pd_t *s, char *buffer) {
+ DECL_DAT_AUX_PRB_STRS();
+
+ auto md = s->is_fwd() ? s->src_md() : s->diff_dst_md();
+
+ if (1) { // data
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "data_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+
+ DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written,
+ "axis:%d group_size:" DFMT, s->axis(), s->group_size());
+
+ mkldnn_md2dim_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, md);
+
+ verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str,
+ aux_str, prb_str);
+}
+
+template <typename pd_t> static void init_info_eltwise(pd_t *s, char *buffer) {
+ DECL_DAT_AUX_PRB_STRS();
+
+ if (1) { // data
+ auto md = s->src_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "data_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // diff data
+ auto md = s->diff_src_md();
+ if (md) {
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " diff_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ }
+
+ DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written,
+ "alg:%s", mkldnn_alg_kind2str(s->desc()->alg_kind));
+
+ mkldnn_md2dim_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, s->src_md());
+
+ verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str,
+ aux_str, prb_str);
+}
+
+template <typename pd_t> static void init_info_iprod(pd_t *s, char *buffer) {
+ DECL_DAT_AUX_PRB_STRS();
+
+ if (1) { // src
+ auto md = s->desc()->prop_kind == prop_kind::backward_data
+ ? s->diff_src_md() : s->src_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // wei
+ auto md = s->desc()->prop_kind == prop_kind::backward_weights
+ ? s->diff_weights_md() : s->weights_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " wei_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // bia
+ auto md = s->desc()->prop_kind == prop_kind::backward_weights
+ ? s->diff_weights_md(1) : s->weights_md(1);
+ if (md) {
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " bia_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ }
+ if (1) { // dst
+ auto md = !s->is_fwd() ? s->diff_dst_md() : s->dst_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " dst_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+
+ DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written,
+ "mb" DFMT "ic" DFMT "oc" DFMT, s->MB(), s->IC_total(), s->OC());
+
+ verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str,
+ aux_str, prb_str);
+}
+
+template <typename pd_t> static void init_info_lrn(pd_t *s, char *buffer) {
+ DECL_DAT_AUX_PRB_STRS();
+
+ if (1) { // data
+ auto md = s->src_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "data_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // diff data
+ auto md = s->diff_src_md();
+ if (md) {
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " diff_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ }
+
+ DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written,
+ "alg:%s", mkldnn_alg_kind2str(s->desc()->alg_kind));
+
+ format_prb_desc_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, s->src_md());
+
+ verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str,
+ aux_str, prb_str);
+}
+
+template <typename pd_t> static void init_info_mem(pd_t *s, char *buffer) {
+ DECL_DAT_AUX_PRB_STRS();
+
+ if (1) { // src
+ auto md = s->src_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // dst
+ auto md = s->dst_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " dst_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+
+ DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written,
+ "num:%d", s->n_inputs());
+
+ mkldnn_md2dim_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, s->dst_md());
+
+ verbose_templ(buffer, s->kind(), s->name(), prop_kind::undef, dat_str,
+ aux_str, prb_str);
+}
+
+template <typename pd_t> static void init_info_pool(pd_t *s, char *buffer) {
+ DECL_DAT_AUX_PRB_STRS();
+
+ if (1) { // src
+ auto md = s->is_fwd() ? s->src_md() : s->diff_src_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // dst
+ auto md = s->is_fwd() ? s->dst_md() : s->diff_dst_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " dst_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // ws
+ auto md = s->workspace_md();
+ if (md) {
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " ws_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ }
+
+ DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written,
+ "alg:%s", mkldnn_alg_kind2str(s->desc()->alg_kind));
+
+ if (s->is_3d()) {
+ DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written,
+ "mb" DFMT "ic" DFMT "_"
+ "id" DFMT "od" DFMT "kd" DFMT "sd" DFMT "pd" DFMT "_"
+ "ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "ph" DFMT "_"
+ "iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "pw" DFMT "",
+ s->MB(), s->C(),
+ s->ID(), s->OD(), s->KD(), s->KSD(), s->padFront(),
+ s->IH(), s->OH(), s->KH(), s->KSH(), s->padT(),
+ s->IW(), s->OW(), s->KW(), s->KSW(), s->padL());
+ } else {
+ DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written,
+ "mb" DFMT "ic" DFMT "_"
+ "ih" DFMT "oh" DFMT "kh" DFMT "sh" DFMT "ph" DFMT "_"
+ "iw" DFMT "ow" DFMT "kw" DFMT "sw" DFMT "pw" DFMT,
+ s->MB(), s->C(),
+ s->IH(), s->OH(), s->KH(), s->KSH(), s->padT(),
+ s->IW(), s->OW(), s->KW(), s->KSW(), s->padL());
+ }
+
+ verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str,
+ aux_str, prb_str);
+}
+
+template <typename pd_t> static void init_info_softmax(pd_t *s, char *buffer) {
+ DECL_DAT_AUX_PRB_STRS();
+
+ if (1) { // data
+ auto md = s->dst_md();
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "data_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // diff data
+ auto md = s->diff_src_md();
+ if (md) {
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " diff_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ }
+
+ mkldnn_md2dim_str(prb_str, MKLDNN_VERBOSE_PRB_LEN, s->dst_md());
+
+ verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str,
+ aux_str, prb_str);
+}
+
+template <typename pd_t> static void init_info_rnn(pd_t *s, char *buffer) {
+ DECL_DAT_AUX_PRB_STRS();
+
+ if (1) { // src layer
+ auto md = s->is_fwd() ? s->src_md(0) : s->diff_src_md(0);
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_layer_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // src iter
+ auto md = s->is_fwd() ? s->src_md(1) : s->diff_src_md(1);
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "src_iter_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // wei_layer
+ auto md = s->is_fwd() ? s->weights_md(0) : s->diff_weights_md(0);
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " wei_layer_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // wei_iter
+ auto md = s->is_fwd() ? s->weights_md(1) : s->diff_weights_md(1);
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " wei_layer_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // bias
+ auto md = s->is_fwd() ? s->weights_md(2) : s->diff_weights_md(2);
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, " bias_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // dst layer
+ auto md = s->is_fwd() ? s->dst_md(0) : s->diff_dst_md(0);
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "dst_layer_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+ if (1) { // dst iter
+ auto md = s->is_fwd() ? s->dst_md(1) : s->diff_dst_md(1);
+ DPRINT(dat_str, MKLDNN_VERBOSE_DAT_LEN, dat_written, "dst_iter_");
+ int l = mkldnn_md2fmt_str(dat_str + dat_written,
+ MKLDNN_VERBOSE_DAT_LEN - dat_written, md);
+ if (l >= 0) dat_written += l; else clear_buf(dat_str, dat_written);
+ }
+
+ alg_kind_t alg_kind = s->cell_kind();
+ rnn_direction_t rnn_dir = s->direction();
+ DPRINT(aux_str, MKLDNN_VERBOSE_AUX_LEN, aux_written,
+ "alg:%s_%s", mkldnn_alg_kind2str(alg_kind),
+ mkldnn_rnn_direction2str(rnn_dir));
+
+ DPRINT(prb_str, MKLDNN_VERBOSE_PRB_LEN, prb_written,
+ "l" DFMT "t" DFMT "mb" DFMT
+ "sic" DFMT "slc" DFMT "dic" DFMT "dlc" DFMT,
+ s->L(), s->T(), s->MB(),
+ s->SIC(), s->SLC(), s->DIC(), s->DLC());
+
+ verbose_templ(buffer, s->kind(), s->name(), s->desc()->prop_kind, dat_str,
+ aux_str, prb_str);
+}
+
+#undef DPRINT
+
+#else // !defined(DISABLE_VERBOSE)
+
+#define DEFINE_STUB(name) \
+ template <typename pd_t> \
+ static void CONCAT2(init_info_, name)(pd_t *s, char *buffer) \
+ { UNUSED(s); UNUSED(buffer); }
+
+DEFINE_STUB(bnorm);
+DEFINE_STUB(conv);
+DEFINE_STUB(eltwise);
+DEFINE_STUB(iprod);
+DEFINE_STUB(lrn);
+DEFINE_STUB(mem);
+DEFINE_STUB(pool);
+DEFINE_STUB(softmax);
+DEFINE_STUB(rnn);
+DEFINE_STUB(shuffle);
+#undef DEFINE_STUB
+
+#endif // !defined(DISABLE_VERBOSE)
+}
+
+void init_info(batch_normalization_pd_t *s, char *b)
+{ init_info_bnorm(s, b); }
+void init_info(concat_pd_t *s, char *b)
+{ init_info_mem(s, b); }
+void init_info(convolution_pd_t *s, char *b)
+{ init_info_conv(s, b); }
+void init_info(deconvolution_pd_t *s, char *b)
+{ init_info_conv(s, b); }
+void init_info(eltwise_pd_t *s, char *b)
+{ init_info_eltwise(s, b); }
+void init_info(inner_product_pd_t *s, char *b)
+{ init_info_iprod(s, b); }
+void init_info(lrn_pd_t *s, char *b)
+{ init_info_lrn(s, b); }
+void init_info(pooling_pd_t *s, char *b)
+{ init_info_pool(s, b); }
+void init_info(reorder_pd_t *s, char *b)
+{ init_info_mem(s, b); }
+void init_info(rnn_pd_t *s, char *b)
+{ init_info_rnn(s, b); }
+void init_info(shuffle_pd_t *s, char *b)
+{ init_info_shuffle(s, b); }
+void init_info(softmax_pd_t *s, char *b)
+{ init_info_softmax(s, b); }
+void init_info(sum_pd_t *s, char *b)
+{ init_info_mem(s, b); }
+
+}
+}
+
+mkldnn_status_t mkldnn_set_verbose(int level) {
+ using namespace mkldnn::impl::status;
+ if (level < 0 || level > 2) return invalid_arguments;
+ mkldnn::impl::verbose.level = level;
+ mkldnn::impl::initialized = true;
+ return success;
+}
+
+const mkldnn_version_t *mkldnn_version() {
+ static mkldnn_version_t ver = {
+ MKLDNN_VERSION_MAJOR,
+ MKLDNN_VERSION_MINOR,
+ MKLDNN_VERSION_PATCH,
+ MKLDNN_VERSION_HASH};
+ return &ver;
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/common/verbose.hpp b/thirdparty/oidn/mkl-dnn/src/common/verbose.hpp
new file mode 100644
index 0000000000..e3049750cb
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/verbose.hpp
@@ -0,0 +1,62 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef VERBOSE_HPP
+#define VERBOSE_HPP
+
+#include <stdio.h>
+#include <cinttypes>
+
+#include "mkldnn_debug.h"
+#include "c_types_map.hpp"
+#include "utils.hpp"
+#include "z_magic.hpp"
+
+namespace mkldnn {
+namespace impl {
+
+struct verbose_t {
+ int level;
+};
+
+const verbose_t *mkldnn_verbose();
+double get_msec();
+const char *get_isa_info();
+
+#if !defined(DISABLE_VERBOSE)
+#define MKLDNN_VERBOSE_BUF_LEN 1024
+#else
+#define MKLDNN_VERBOSE_BUF_LEN 1
+#endif
+
+void init_info(batch_normalization_pd_t *s, char *buffer);
+void init_info(concat_pd_t *s, char *buffer);
+void init_info(convolution_pd_t *s, char *buffer);
+void init_info(deconvolution_pd_t *s, char *buffer);
+void init_info(eltwise_pd_t *s, char *buffer);
+void init_info(inner_product_pd_t *s, char *buffer);
+void init_info(lrn_pd_t *s, char *buffer);
+void init_info(pooling_pd_t *s, char *buffer);
+void init_info(reorder_pd_t *s, char *buffer);
+void init_info(rnn_pd_t *s, char *buffer);
+void init_info(shuffle_pd_t *s, char *buffer);
+void init_info(softmax_pd_t *s, char *buffer);
+void init_info(sum_pd_t *s, char *buffer);
+
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/common/z_magic.hpp b/thirdparty/oidn/mkl-dnn/src/common/z_magic.hpp
new file mode 100644
index 0000000000..520bd4710b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/common/z_magic.hpp
@@ -0,0 +1,46 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef Z_MAGIC_HPP
+#define Z_MAGIC_HPP
+
+#define CHAIn2(a,b) a b
+#define CHAIN2(a,b) CHAIn2(a,b)
+
+#define CONCAt2(a,b) a ## b
+#define CONCAT2(a,b) CONCAt2(a,b)
+
+#define STRINGIFy(s) #s
+#define STRINGIFY(s) STRINGIFy(s)
+
+#ifdef _MSC_VER
+# define PRAGMA_MACRo(x) __pragma(x)
+# define PRAGMA_MACRO(x) PRAGMA_MACRo(x)
+#else
+# define PRAGMA_MACRo(x) _Pragma(#x)
+# define PRAGMA_MACRO(x) PRAGMA_MACRo(x)
+#endif
+
+#define UNUSED(x) ((void)x)
+#define MAYBE_UNUSED(x) UNUSED(x)
+
+#if defined(_WIN32) && !defined(__GNUC__)
+#define __PRETTY_FUNCTION__ __FUNCSIG__
+#endif
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.cpp
new file mode 100644
index 0000000000..7cf7822d90
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.cpp
@@ -0,0 +1,112 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "cpu_barrier.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace simple_barrier {
+
+void generate(jit_generator &code, Xbyak::Reg64 reg_ctx,
+ Xbyak::Reg64 reg_nthr) {
+# define BAR_CTR_OFF offsetof(ctx_t, ctr)
+# define BAR_SENSE_OFF offsetof(ctx_t, sense)
+ using namespace Xbyak;
+
+ Xbyak::Reg64 reg_tmp = [&]() {
+ /* returns register which is neither reg_ctx nor reg_nthr */
+ Xbyak::Reg64 regs[] = { util::rax, util::rbx, util::rcx };
+ for (size_t i = 0; i < sizeof(regs) / sizeof(regs[0]); ++i)
+ if (!utils::one_of(regs[i], reg_ctx, reg_nthr))
+ return regs[i];
+ return regs[0]; /* should not happen */
+ }();
+
+ Label barrier_exit_label, barrier_exit_restore_label, spin_label;
+
+ code.cmp(reg_nthr, 1);
+ code.jbe(barrier_exit_label);
+
+ code.push(reg_tmp);
+
+ /* take and save current sense */
+ code.mov(reg_tmp, code.ptr[reg_ctx + BAR_SENSE_OFF]);
+ code.push(reg_tmp);
+ code.mov(reg_tmp, 1);
+
+ if (mayiuse(avx512_mic)) {
+ code.prefetchwt1(code.ptr[reg_ctx + BAR_CTR_OFF]);
+ code.prefetchwt1(code.ptr[reg_ctx + BAR_CTR_OFF]);
+ }
+
+ code.lock(); code.xadd(code.ptr[reg_ctx + BAR_CTR_OFF], reg_tmp);
+ code.add(reg_tmp, 1);
+ code.cmp(reg_tmp, reg_nthr);
+ code.pop(reg_tmp); /* restore previous sense */
+ code.jne(spin_label);
+
+ /* the last thread {{{ */
+ code.mov(code.qword[reg_ctx + BAR_CTR_OFF], 0); // reset ctx
+
+ // notify waiting threads
+ code.not_(reg_tmp);
+ code.mov(code.ptr[reg_ctx + BAR_SENSE_OFF], reg_tmp);
+ code.jmp(barrier_exit_restore_label);
+ /* }}} the last thread */
+
+ code.CodeGenerator::L(spin_label);
+ code.pause();
+ code.cmp(reg_tmp, code.ptr[reg_ctx + BAR_SENSE_OFF]);
+ code.je(spin_label);
+
+ code.CodeGenerator::L(barrier_exit_restore_label);
+ code.pop(reg_tmp);
+
+ code.CodeGenerator::L(barrier_exit_label);
+# undef BAR_CTR_OFF
+# undef BAR_SENSE_OFF
+}
+
+/** jit barrier generator */
+struct jit_t: public jit_generator {
+ void (*barrier)(ctx_t *ctx, size_t nthr);
+
+ jit_t() {
+ generate(*this, abi_param1, abi_param2);
+ ret();
+ barrier = reinterpret_cast<decltype(barrier)>(const_cast<uint8_t*>(
+ this->getCode()));
+ }
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_t)
+};
+
+void barrier(ctx_t *ctx, int nthr) {
+ static jit_t j; /* XXX: constructed on load ... */
+ j.barrier(ctx, nthr);
+}
+
+}
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.hpp
new file mode 100644
index 0000000000..0f55e33aa8
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_barrier.hpp
@@ -0,0 +1,60 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_BARRIER_HPP
+#define CPU_BARRIER_HPP
+
+#include <assert.h>
+
+#include "jit_generator.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace simple_barrier {
+
+STRUCT_ALIGN(64,
+struct ctx_t {
+ enum { CACHE_LINE_SIZE = 64 };
+ volatile size_t ctr;
+ char pad1[CACHE_LINE_SIZE - 1 * sizeof(size_t)];
+ volatile size_t sense;
+ char pad2[CACHE_LINE_SIZE - 1 * sizeof(size_t)];
+});
+
+inline void ctx_init(ctx_t *ctx) { *ctx = utils::zero<ctx_t>(); }
+void barrier(ctx_t *ctx, int nthr);
+
+/** injects actual barrier implementation into another jitted code
+ * @params:
+ * code -- jit_generator object where the barrier is to be injected
+ * reg_ctx -- read-only register with pointer to the barrier context
+ * reg_nnthr -- read-only register with the # of synchronizing threads
+ */
+void generate(jit_generator &code, Xbyak::Reg64 reg_ctx,
+ Xbyak::Reg64 reg_nthr);
+
+}
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_pd.hpp
new file mode 100644
index 0000000000..1ed5ad57b9
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_pd.hpp
@@ -0,0 +1,40 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_BATCH_NORMALIZATION_PD_HPP
+#define CPU_BATCH_NORMALIZATION_PD_HPP
+
+#include "batch_normalization_pd.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_batch_normalization_fwd_pd_t: public batch_normalization_fwd_pd_t {
+ using batch_normalization_fwd_pd_t::batch_normalization_fwd_pd_t;
+};
+
+struct cpu_batch_normalization_bwd_pd_t: public batch_normalization_bwd_pd_t {
+ using batch_normalization_bwd_pd_t::batch_normalization_bwd_pd_t;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.cpp
new file mode 100644
index 0000000000..b8d5c4fcaf
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.cpp
@@ -0,0 +1,140 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "utils.hpp"
+
+#include "jit_generator.hpp"
+
+#include "cpu_batch_normalization_utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+namespace bnorm_utils {
+
+void cache_balance(size_t working_set_size, dim_t C_blks,
+ dim_t &C_blks_per_iter, int64_t &iters) {
+ int nthrs = mkldnn_get_max_threads();
+ int l3_size = get_cache_size(3, true) * nthrs / 2;
+
+ C_blks_per_iter = l3_size / working_set_size;
+
+ if (C_blks_per_iter == 0)
+ C_blks_per_iter = 1;
+ if (C_blks_per_iter > C_blks)
+ C_blks_per_iter = C_blks;
+
+ iters = (C_blks + C_blks_per_iter - 1) / C_blks_per_iter;
+}
+
+bool thread_balance(bool do_blocking, bool spatial_thr_allowed, int ithr,
+ int nthr, dim_t N, dim_t C_blks, dim_t SP, int &C_ithr, int &C_nthr,
+ dim_t &C_blk_s, dim_t &C_blk_e, int &N_ithr, int &N_nthr, dim_t &N_s,
+ dim_t &N_e, int &S_ithr, int &S_nthr, dim_t &S_s, dim_t &S_e) {
+ if (nthr <= C_blks || !mkldnn_thr_syncable()) {
+ C_ithr = ithr; C_nthr = nthr;
+ N_ithr = 0; N_nthr = 1;
+ S_ithr = 0; S_nthr = 1;
+ N_s = 0; N_e = N; S_s = 0; S_e = SP;
+ balance211(C_blks, C_nthr, C_ithr, C_blk_s, C_blk_e);
+ } else {
+ if (do_blocking) {
+ N_nthr = (int)nstl::min<dim_t>(N, nthr);
+ C_nthr = (int)nstl::min<dim_t>(C_blks, nthr / N_nthr);
+ S_nthr = (int)nstl::min<dim_t>(SP, nthr / (C_nthr * N_nthr));
+ } else {
+ C_nthr = (int)math::gcd((dim_t)nthr, C_blks);
+ N_nthr = (int)nstl::min<dim_t>(N, nthr / C_nthr);
+ S_nthr = (int)nstl::min<dim_t>(SP, nthr / (C_nthr * N_nthr));
+ }
+
+ if (!spatial_thr_allowed)
+ S_nthr = 1;
+
+ if (S_nthr < 1) S_nthr = 1;
+ if (ithr < C_nthr * N_nthr * S_nthr) {
+ N_ithr = (ithr / S_nthr) % N_nthr ;
+ C_ithr = ithr / (N_nthr * S_nthr);
+ S_ithr = ithr % S_nthr;
+ balance211(C_blks, C_nthr, C_ithr, C_blk_s, C_blk_e);
+ balance211(N, N_nthr, N_ithr, N_s, N_e);
+ balance211(SP, S_nthr, S_ithr, S_s, S_e);
+ } else {
+ S_ithr = N_ithr = C_ithr = -ithr;
+ S_s = S_e = N_s = N_e = C_blk_s = C_blk_e = -1;
+ }
+ }
+
+ // spatial_thr_allowed is meant to help maintain
+ // consistent decisions about spatial threading
+ // between mutiple invocations of this routine.
+ // It is caller's responsibility to check the
+ // return value and pass it as a flag to the
+ // next call if needed.
+ if (S_nthr == 1)
+ spatial_thr_allowed = false;
+
+ return spatial_thr_allowed;
+}
+
+bool is_spatial_thr(const batch_normalization_pd_t *bdesc, int simd_w,
+ int data_size) {
+ if (!mkldnn_thr_syncable()) return false;
+
+ dim_t nthr = mkldnn_get_max_threads();
+ dim_t SP = bdesc->W() * bdesc->D() * bdesc->H();
+ dim_t C_PADDED = memory_desc_wrapper(bdesc->src_md())
+ .padded_dims()[1];
+ assert(C_PADDED % simd_w == 0);
+
+ size_t data = bdesc->MB() * C_PADDED * SP * data_size;
+ size_t l3_size_ = get_cache_size(3, true) * nthr / 2;
+ bool do_blocking = (data >= l3_size_ / 2 && l3_size_ > 0);
+ dim_t C_blks_per_iter{ 1 }, iters{ 1 };
+ dim_t C_blks = C_PADDED / simd_w;
+
+ if (do_blocking) {
+ int num_tensors = bdesc->is_fwd() ? 1 : 2;
+ size_t working_set_size
+ = (bdesc->MB() * SP * simd_w * data_size) * num_tensors;
+ cache_balance(working_set_size, C_blks, C_blks_per_iter, iters);
+ }
+
+ // Spatial threading decision made in this function shall be consistent
+ // with thread_balance() behavior.
+ C_blks = do_blocking ? C_blks_per_iter : C_blks;
+
+ if (nthr <= C_blks) return false;
+
+ dim_t S_nthr = 1;
+ if (do_blocking) {
+ dim_t N_nthr = nstl::min(bdesc->MB(), nthr);
+ dim_t C_nthr = nstl::min(C_blks, nthr / N_nthr);
+ S_nthr = nstl::min(SP, nthr / (C_nthr * N_nthr));
+ } else {
+ dim_t C_nthr = math::gcd(nthr, C_blks);
+ dim_t N_nthr = nstl::min(bdesc->MB(), nthr / C_nthr);
+ S_nthr = nstl::min(SP, nthr / (C_nthr * N_nthr));
+ }
+
+ return S_nthr > 1;
+}
+
+}
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.hpp
new file mode 100644
index 0000000000..0daef0716c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_batch_normalization_utils.hpp
@@ -0,0 +1,43 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_BATCH_NORMALIZATION_UTILS_HPP
+#define CPU_BATCH_NORMALIZATION_UTILS_HPP
+
+#include "batch_normalization_pd.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+namespace bnorm_utils {
+
+void cache_balance(size_t working_set_size, dim_t C_blks,
+ dim_t &C_blks_per_iter, int64_t &iters);
+
+bool thread_balance(bool do_blocking, bool spatial_thr_allowed, int ithr,
+ int nthr, dim_t N, dim_t C_blks, dim_t SP, int &C_ithr, int &C_nthr,
+ dim_t &C_blk_s, dim_t &C_blk_e, int &N_ithr, int &N_nthr, dim_t &N_s,
+ dim_t &N_e, int &S_ithr, int &S_nthr, dim_t &S_s, dim_t &S_e);
+
+bool is_spatial_thr(const batch_normalization_pd_t *bdesc, int simd_w,
+ int data_size);
+
+}
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat.cpp
new file mode 100644
index 0000000000..b926491202
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat.cpp
@@ -0,0 +1,51 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "cpu_engine.hpp"
+
+/*
+#include "cpu/ref_concat.hpp"
+#include "cpu/simple_concat.hpp"
+*/
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using cpd_create_f = mkldnn::impl::engine_t::concat_primitive_desc_create_f;
+
+namespace {
+#define INSTANCE(...) __VA_ARGS__::pd_t::create
+static const cpd_create_f cpu_concat_impl_list[] = {
+ /*
+ INSTANCE(simple_concat_t<data_type::f32>),
+ INSTANCE(simple_concat_t<data_type::u8>),
+ INSTANCE(simple_concat_t<data_type::s8>),
+ INSTANCE(simple_concat_t<data_type::s32>),
+ INSTANCE(ref_concat_t),
+ */
+ nullptr,
+};
+#undef INSTANCE
+}
+
+const cpd_create_f *cpu_engine_t::get_concat_implementation_list() const {
+ return cpu_concat_impl_list;
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat_pd.hpp
new file mode 100644
index 0000000000..0b01bcf163
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_concat_pd.hpp
@@ -0,0 +1,41 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_CONCAT_PD_HPP
+#define CPU_CONCAT_PD_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "concat_pd.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_concat_pd_t: public concat_pd_t {
+ using concat_pd_t::concat_pd_t;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_convolution_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_convolution_pd.hpp
new file mode 100644
index 0000000000..52a38a2294
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_convolution_pd.hpp
@@ -0,0 +1,74 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_CONVOLUTION_PD_HPP
+#define CPU_CONVOLUTION_PD_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "convolution_pd.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_convolution_fwd_pd_t: public convolution_fwd_pd_t {
+ using convolution_fwd_pd_t::convolution_fwd_pd_t;
+
+ bool has_padded_dst() const {
+ memory_desc_wrapper dst_d(&dst_md_);
+ return OC() != dst_d.padded_dims()[1];
+ }
+
+ bool wants_padded_bias() const {
+ if (!with_bias()) return false;
+ return has_padded_dst();
+ }
+
+ bool wants_zero_pad_dst(bool jit_impl = true) const {
+ if (!has_padded_dst()) return false;
+ const auto &po = attr()->post_ops_;
+ int idx;
+ if ((idx = po.find(primitive_kind::eltwise)) == -1) return false;
+ return !math::eltwise_fwd_preserves_zero(po.entry_[idx].eltwise.alg,
+ jit_impl);
+ }
+};
+
+struct cpu_convolution_bwd_data_pd_t: public convolution_bwd_data_pd_t {
+ using convolution_bwd_data_pd_t::convolution_bwd_data_pd_t;
+};
+
+struct cpu_convolution_bwd_weights_pd_t: public convolution_bwd_weights_pd_t {
+ using convolution_bwd_weights_pd_t::convolution_bwd_weights_pd_t;
+
+ bool wants_padded_bias() const {
+ if (!with_bias()) return false;
+ memory_desc_wrapper diff_dst_d(&diff_dst_md_);
+ return OC() != diff_dst_d.padded_dims()[1];
+ }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_deconvolution_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_deconvolution_pd.hpp
new file mode 100644
index 0000000000..164c8601d7
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_deconvolution_pd.hpp
@@ -0,0 +1,46 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_DECONVOLUTION_PD_HPP
+#define CPU_DECONVOLUTION_PD_HPP
+
+#include <assert.h>
+
+#include "deconvolution_pd.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_deconvolution_fwd_pd_t: public deconvolution_fwd_pd_t {
+ using deconvolution_fwd_pd_t::deconvolution_fwd_pd_t;
+};
+
+struct cpu_deconvolution_bwd_data_pd_t: public deconvolution_bwd_data_pd_t {
+ using deconvolution_bwd_data_pd_t::deconvolution_bwd_data_pd_t;
+};
+
+struct cpu_deconvolution_bwd_weights_pd_t: public deconvolution_bwd_weights_pd_t {
+ using deconvolution_bwd_weights_pd_t::deconvolution_bwd_weights_pd_t;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_eltwise_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_eltwise_pd.hpp
new file mode 100644
index 0000000000..c52f00026e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_eltwise_pd.hpp
@@ -0,0 +1,45 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_ELTWISE_PD_HPP
+#define CPU_ELTWISE_PD_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "eltwise_pd.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_eltwise_fwd_pd_t: public eltwise_fwd_pd_t {
+ using eltwise_fwd_pd_t::eltwise_fwd_pd_t;
+};
+
+struct cpu_eltwise_bwd_pd_t: public eltwise_bwd_pd_t {
+ using eltwise_bwd_pd_t::eltwise_bwd_pd_t;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.cpp
new file mode 100644
index 0000000000..ce0a3667ad
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.cpp
@@ -0,0 +1,324 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "type_helpers.hpp"
+#include "verbose.hpp"
+
+#include "cpu_engine.hpp"
+#include "cpu_memory.hpp"
+
+//#include "cpu/rnn/ref_rnn.hpp"
+
+//#include "cpu/jit_avx512_core_x8s8s32x_1x1_convolution.hpp"
+//#include "cpu/jit_avx512_common_1x1_convolution.hpp"
+#include "cpu/jit_avx512_core_fp32_wino_conv_4x3.hpp"
+#include "cpu/jit_avx512_common_convolution_winograd.hpp"
+//#include "cpu/jit_avx512_core_x8s8s32x_convolution.hpp"
+#include "cpu/jit_avx512_common_convolution.hpp"
+//#include "cpu/jit_avx2_1x1_convolution.hpp"
+//#include "cpu/jit_sse42_1x1_convolution.hpp"
+#include "cpu/jit_avx2_convolution.hpp"
+#include "cpu/jit_sse42_convolution.hpp"
+//#include "cpu/gemm_convolution.hpp"
+//#include "cpu/gemm_x8s8s32x_convolution.hpp"
+//#include "cpu/ref_convolution.hpp"
+//#include "cpu/jit_avx512_core_x8s8s32x_deconvolution.hpp"
+//#include "cpu/jit_avx512_core_x8s8s32x_1x1_deconvolution.hpp"
+//#include "cpu/ref_deconvolution.hpp"
+//#include "cpu/ref_shuffle.hpp"
+//#include "cpu/jit_uni_eltwise.hpp"
+//#include "cpu/ref_eltwise.hpp"
+//#include "cpu/ref_softmax.hpp"
+#include "cpu/jit_uni_pooling.hpp"
+//#include "cpu/jit_uni_i8i8_pooling.hpp"
+//#include "cpu/ref_pooling.hpp"
+//#include "cpu/nchw_pooling.hpp"
+//#include "cpu/nhwc_pooling.hpp"
+//#include "cpu/jit_avx512_common_lrn.hpp"
+//#include "cpu/jit_uni_lrn.hpp"
+//#include "cpu/ref_lrn.hpp"
+//#include "cpu/jit_uni_batch_normalization.hpp"
+//#include "cpu/ref_batch_normalization.hpp"
+//#include "cpu/ncsp_batch_normalization.hpp"
+//#include "cpu/nspc_batch_normalization.hpp"
+//#include "cpu/ref_inner_product.hpp"
+//#include "cpu/gemm_inner_product.hpp"
+//#include "cpu/gemm_x8s8s32x_inner_product.hpp"
+//#include "cpu/jit_uni_dw_convolution.hpp"
+//#include "cpu/jit_avx512_core_u8s8s32x_wino_convolution.hpp"
+#include "cpu/jit_avx512_core_fp32_wino_conv_2x3.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+status_t cpu_engine_t::memory_create(memory_t **memory,
+ const memory_desc_t *md, void *handle) {
+ auto _memory = new cpu_memory_t(this, md, handle);
+ if (_memory == nullptr)
+ return status::out_of_memory;
+
+ status_t status = _memory->init();
+ if (status != status::success) {
+ delete _memory;
+ return status;
+ }
+
+ return safe_ptr_assign<memory_t>(*memory, _memory);
+}
+
+using pd_create_f = mkldnn::impl::engine_t::primitive_desc_create_f;
+
+namespace {
+using namespace mkldnn::impl::data_type;
+
+#define INSTANCE(...) &primitive_desc_t::create<__VA_ARGS__::pd_t>
+static const pd_create_f cpu_impl_list[] = {
+ /* RNN */
+ /*
+ INSTANCE(ref_rnn_fwd_f32_t),
+ INSTANCE(ref_rnn_fwd_u8s8_t),
+ INSTANCE(ref_rnn_bwd_f32_t),
+ */
+ /* conv */
+ /*
+ INSTANCE(jit_avx512_common_dw_convolution_fwd_t),
+ INSTANCE(jit_avx512_common_dw_convolution_bwd_data_t),
+ INSTANCE(jit_avx512_common_dw_convolution_bwd_weights_t),
+ INSTANCE(jit_avx512_common_1x1_convolution_fwd_f32_t),
+ INSTANCE(jit_avx512_common_1x1_convolution_bwd_data_f32_t),
+ INSTANCE(jit_avx512_common_1x1_convolution_bwd_weights_t),
+ */
+ INSTANCE(jit_avx512_core_fp32_wino_conv_2x3_fwd_t),
+ INSTANCE(jit_avx512_core_fp32_wino_conv_4x3_fwd_t),
+ //INSTANCE(jit_avx512_core_fp32_wino_conv_4x3_bwd_data_t),
+ //INSTANCE(jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t),
+ INSTANCE(jit_avx512_common_convolution_winograd_fwd_t),
+ //INSTANCE(jit_avx512_common_convolution_winograd_bwd_data_t),
+ //INSTANCE(jit_avx512_common_convolution_winograd_bwd_weights_t),
+ INSTANCE(jit_avx512_common_convolution_fwd_t<f32>),
+ //INSTANCE(jit_avx512_common_convolution_bwd_data_t<f32>),
+ //INSTANCE(jit_avx512_common_convolution_bwd_weights_t<f32>),
+ /*
+ INSTANCE(jit_avx2_dw_convolution_fwd_t),
+ INSTANCE(jit_avx2_dw_convolution_bwd_data_t),
+ INSTANCE(jit_avx2_dw_convolution_bwd_weights_t),
+ INSTANCE(jit_avx2_1x1_convolution_fwd_t),
+ INSTANCE(jit_avx2_1x1_convolution_bwd_data_t),
+ INSTANCE(jit_avx2_1x1_convolution_bwd_weights_t),
+ INSTANCE(jit_sse42_dw_convolution_fwd_t),
+ INSTANCE(jit_sse42_dw_convolution_bwd_data_t),
+ INSTANCE(jit_sse42_dw_convolution_bwd_weights_t),
+ INSTANCE(jit_sse42_1x1_convolution_fwd_t),
+ */
+ INSTANCE(jit_avx2_convolution_fwd_t),
+ //INSTANCE(jit_avx2_convolution_bwd_data_t),
+ //INSTANCE(jit_avx2_convolution_bwd_weights_t),
+ INSTANCE(jit_sse42_convolution_fwd_t),
+ /*
+ INSTANCE(gemm_convolution_fwd_t),
+ INSTANCE(gemm_convolution_bwd_data_t),
+ INSTANCE(gemm_convolution_bwd_weights_t),
+ INSTANCE(ref_convolution_fwd_t<f32>),
+ INSTANCE(ref_convolution_bwd_data_t<f32, f32, f32, f32>),
+ INSTANCE(ref_convolution_bwd_weights_t<f32, f32, f32, f32>),
+ */
+ /* conv (int) */
+ /*
+ INSTANCE(jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<f32>),
+ INSTANCE(jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<s32>),
+ INSTANCE(jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<s8>),
+ INSTANCE(jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<u8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<u8,f32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<u8,s32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<u8,u8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<u8,s8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<s8,f32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<s8,s32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<s8,u8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<s8,s8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t<u8,f32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t<u8,s32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t<u8,u8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t<u8,s8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t<s8,f32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t<s8,s32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t<s8,u8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_convolution_fwd_t<s8,s8>),
+ INSTANCE(_gemm_x8s8s32x_convolution_fwd_t<u8, s32>),
+ INSTANCE(_gemm_x8s8s32x_convolution_fwd_t<u8, u8>),
+ INSTANCE(_gemm_x8s8s32x_convolution_fwd_t<u8, s8>),
+ INSTANCE(_gemm_x8s8s32x_convolution_fwd_t<u8, f32>),
+ INSTANCE(_gemm_x8s8s32x_convolution_fwd_t<s8, s32>),
+ INSTANCE(_gemm_x8s8s32x_convolution_fwd_t<s8, u8>),
+ INSTANCE(_gemm_x8s8s32x_convolution_fwd_t<s8, s8>),
+ INSTANCE(_gemm_x8s8s32x_convolution_fwd_t<s8, f32>),
+ INSTANCE(_gemm_u8s8s32x_convolution_bwd_data_t<s32>),
+ INSTANCE(_gemm_u8s8s32x_convolution_bwd_data_t<u8>),
+ INSTANCE(_gemm_u8s8s32x_convolution_bwd_data_t<s8>),
+ INSTANCE(_gemm_u8s8s32x_convolution_bwd_data_t<f32>),
+ INSTANCE(ref_convolution_fwd_t<u8, s8, f32, s32>),
+ INSTANCE(ref_convolution_fwd_t<u8, s8, s32, s32>),
+ INSTANCE(ref_convolution_fwd_t<u8, s8, s8, s32>),
+ INSTANCE(ref_convolution_fwd_t<u8, s8, u8, s32>),
+ INSTANCE(ref_convolution_bwd_data_t<f32, s8, u8, s32>),
+ INSTANCE(ref_convolution_bwd_data_t<s32, s8, u8, s32>),
+ INSTANCE(ref_convolution_bwd_data_t<s8, s8, u8, s32>),
+ INSTANCE(ref_convolution_bwd_data_t<u8, s8, u8, s32>),
+ */
+ /* deconv */
+ /*
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t<u8,f32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t<u8,s32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t<u8,u8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t<u8,s8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t<s8,f32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t<s8,s32>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t<s8,u8>),
+ INSTANCE(jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t<s8,s8>),
+ INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t<u8,s32>),
+ INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t<u8,u8>),
+ INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t<u8,s8>),
+ INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t<u8,f32>),
+ INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t<s8,s32>),
+ INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t<s8,u8>),
+ INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t<s8,s8>),
+ INSTANCE(_jit_avx512_core_x8s8s32x_deconvolution_fwd_t<s8,f32>),
+ INSTANCE(ref_deconvolution_bwd_weights_t),
+ INSTANCE(ref_deconvolution_bwd_data_t),
+ INSTANCE(ref_deconvolution_fwd_t),
+ */
+ /* shuffle */
+ /*
+ INSTANCE(ref_shuffle_t<4>), // f32 or s32
+ INSTANCE(ref_shuffle_t<1>), // s8 or u8
+ */
+ /* eltwise */
+ /*
+ INSTANCE(jit_uni_eltwise_fwd_t<avx512_common>),
+ INSTANCE(jit_uni_eltwise_bwd_t<avx512_common>),
+ INSTANCE(jit_uni_eltwise_fwd_t<avx2>),
+ INSTANCE(jit_uni_eltwise_bwd_t<avx2>),
+ INSTANCE(jit_uni_eltwise_fwd_t<sse42>),
+ INSTANCE(jit_uni_eltwise_bwd_t<sse42>),
+ INSTANCE(ref_eltwise_fwd_t<f32>),
+ INSTANCE(ref_eltwise_bwd_t<f32>),
+ */
+ /* eltwise (int) */
+ /*
+ INSTANCE(ref_eltwise_fwd_t<s32>),
+ INSTANCE(ref_eltwise_fwd_t<s8>),
+ INSTANCE(ref_eltwise_fwd_t<u8>),
+ INSTANCE(ref_eltwise_bwd_t<s32>),
+ */
+ /* softmax */
+ /*
+ INSTANCE(ref_softmax_fwd_t<f32>),
+ INSTANCE(ref_softmax_bwd_t<f32>),
+ */
+ /* pool */
+ INSTANCE(jit_uni_pooling_fwd_t<avx512_common>),
+ //INSTANCE(jit_uni_pooling_bwd_t<avx512_common>),
+ INSTANCE(jit_uni_pooling_fwd_t<avx>),
+ //INSTANCE(jit_uni_pooling_bwd_t<avx>),
+ INSTANCE(jit_uni_pooling_fwd_t<sse42>),
+ //INSTANCE(jit_uni_pooling_bwd_t<sse42>),
+ /*
+ INSTANCE(nchw_pooling_fwd_t<f32>),
+ INSTANCE(nchw_pooling_bwd_t<f32>),
+ INSTANCE(nhwc_pooling_fwd_t<f32>),
+ INSTANCE(nhwc_pooling_bwd_t<f32>),
+ INSTANCE(ref_pooling_fwd_t<f32>),
+ INSTANCE(ref_pooling_bwd_t<f32>),
+ */
+ /* pool (int) */
+ /*
+ INSTANCE(jit_uni_i8i8_pooling_fwd_t<avx512_core>),
+ INSTANCE(jit_uni_i8i8_pooling_fwd_t<avx2>),
+ INSTANCE(ref_pooling_fwd_t<s32>),
+ INSTANCE(ref_pooling_fwd_t<s8, s32>),
+ INSTANCE(ref_pooling_fwd_t<u8, s32>),
+ INSTANCE(ref_pooling_bwd_t<s32>),
+ */
+ /* lrn */
+ /*
+ INSTANCE(jit_avx512_common_lrn_fwd_t),
+ INSTANCE(jit_avx512_common_lrn_bwd_t),
+ INSTANCE(jit_uni_lrn_fwd_t<avx2>),
+ INSTANCE(jit_uni_lrn_bwd_t<avx2>),
+ INSTANCE(jit_uni_lrn_fwd_t<sse42>),
+ INSTANCE(ref_lrn_fwd_t<f32>),
+ INSTANCE(ref_lrn_bwd_t<f32>),
+ */
+ /* batch normalization */
+ /*
+ INSTANCE(jit_uni_batch_normalization_fwd_t<avx512_common>),
+ INSTANCE(jit_uni_batch_normalization_bwd_t<avx512_common>),
+ INSTANCE(jit_uni_batch_normalization_fwd_t<avx2>),
+ INSTANCE(jit_uni_batch_normalization_bwd_t<avx2>),
+ INSTANCE(jit_uni_batch_normalization_fwd_t<sse42>),
+ INSTANCE(jit_uni_batch_normalization_bwd_t<sse42>),
+ INSTANCE(ncsp_batch_normalization_fwd_t),
+ INSTANCE(ncsp_batch_normalization_bwd_t),
+ INSTANCE(nspc_batch_normalization_fwd_t),
+ INSTANCE(nspc_batch_normalization_bwd_t),
+ INSTANCE(ref_batch_normalization_fwd_t<f32>),
+ INSTANCE(ref_batch_normalization_bwd_t<f32>),
+ INSTANCE(ref_batch_normalization_fwd_t<s8>),
+ */
+ /* inner product */
+ /*
+ INSTANCE(gemm_inner_product_fwd_t<f32>),
+ INSTANCE(gemm_inner_product_bwd_data_t<f32>),
+ INSTANCE(gemm_inner_product_bwd_weights_t<f32>),
+ INSTANCE(ref_inner_product_fwd_t<f32>),
+ INSTANCE(ref_inner_product_bwd_data_t<f32, f32, f32, f32>),
+ INSTANCE(ref_inner_product_bwd_weights_t<f32>),
+ */
+ /* inner product (int) */
+ /*
+ INSTANCE(gemm_x8s8s32x_inner_product_fwd_t<u8, u8>),
+ INSTANCE(gemm_x8s8s32x_inner_product_fwd_t<u8, s8>),
+ INSTANCE(gemm_x8s8s32x_inner_product_fwd_t<u8, s32>),
+ INSTANCE(gemm_x8s8s32x_inner_product_fwd_t<u8, f32>),
+ INSTANCE(gemm_x8s8s32x_inner_product_fwd_t<s8, u8>),
+ INSTANCE(gemm_x8s8s32x_inner_product_fwd_t<s8, s8>),
+ INSTANCE(gemm_x8s8s32x_inner_product_fwd_t<s8, s32>),
+ INSTANCE(gemm_x8s8s32x_inner_product_fwd_t<s8, f32>),
+ INSTANCE(ref_inner_product_fwd_t<u8, s8, u8, s32>),
+ INSTANCE(ref_inner_product_fwd_t<u8, s8, s8, s32>),
+ INSTANCE(ref_inner_product_fwd_t<u8, s8, s32, s32>),
+ INSTANCE(ref_inner_product_fwd_t<u8, s8, f32, s32>),
+ */
+ /* eol */
+ nullptr,
+};
+#undef INSTANCE
+}
+
+const pd_create_f* cpu_engine_t::get_implementation_list() const {
+ return cpu_impl_list;
+}
+
+cpu_engine_factory_t engine_factory;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.hpp
new file mode 100644
index 0000000000..e4c877ee05
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_engine.hpp
@@ -0,0 +1,70 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_ENGINE_HPP
+#define CPU_ENGINE_HPP
+
+#include <assert.h>
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "../common/engine.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+class cpu_engine_t: public engine_t {
+public:
+ cpu_engine_t(): engine_t(engine_kind::cpu) {}
+
+ /* implementation part */
+
+ virtual status_t memory_create(memory_t **memory,
+ const memory_desc_t *md, void *handle) override;
+
+ virtual const concat_primitive_desc_create_f*
+ get_concat_implementation_list() const override;
+ virtual const reorder_primitive_desc_create_f*
+ get_reorder_implementation_list() const override;
+ virtual const sum_primitive_desc_create_f*
+ get_sum_implementation_list() const override;
+ virtual const primitive_desc_create_f*
+ get_implementation_list() const override;
+};
+
+class cpu_engine_factory_t: public engine_factory_t {
+public:
+ virtual size_t count() const override { return 1; }
+ virtual engine_kind_t kind() const override { return engine_kind::cpu; }
+ virtual status_t engine_create(engine_t **engine,
+ size_t index) const override {
+ assert(index == 0);
+ *engine = new cpu_engine_t();
+ return status::success;
+ };
+};
+
+extern cpu_engine_factory_t engine_factory;
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_inner_product_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_inner_product_pd.hpp
new file mode 100644
index 0000000000..5880d3450c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_inner_product_pd.hpp
@@ -0,0 +1,84 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_INNER_PRODUCT_PD_HPP
+#define CPU_INNER_PRODUCT_PD_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "inner_product_pd.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace {
+inline bool dense_gemm_consitency_check(const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &wei_d, const memory_desc_wrapper &dst_d) {
+ using namespace utils;
+
+ auto strides_compatible = [&]() {
+ bool ok = true;
+ auto w_str = wei_d.blocking_desc().strides;
+ auto d_str = src_d.blocking_desc().strides;
+ for (int i = 1; i < src_d.ndims() - 1; i++) {
+ ok = ok && w_str[i] / d_str[i] == w_str[i + 1] / d_str[i + 1];
+ }
+ return ok && one_of(w_str[1] / d_str[1], 1, wei_d.padded_dims()[0]);
+ };
+ return true && src_d.is_blocking_desc() && wei_d.is_blocking_desc()
+ && src_d.ndims() == wei_d.ndims()
+ && src_d.blocking_desc().inner_nblks
+ == wei_d.blocking_desc().inner_nblks
+ && utils::one_of(src_d.blocking_desc().inner_nblks, 0, 1)
+ && array_cmp(src_d.blocking_desc().inner_blks,
+ wei_d.blocking_desc().inner_blks,
+ wei_d.blocking_desc().inner_nblks)
+ && array_cmp(src_d.blocking_desc().inner_idxs,
+ wei_d.blocking_desc().inner_idxs,
+ wei_d.blocking_desc().inner_nblks)
+ && strides_compatible()
+ && dst_d.matches_tag(format_tag::nc)
+ && src_d.only_padded_dim(1)
+ && wei_d.only_padded_dim(1)
+ && src_d.padded_dims()[1] == wei_d.padded_dims()[1]
+ && src_d.is_dense(true)
+ && dst_d.is_dense()
+ && wei_d.is_dense(true);
+}
+}
+
+struct cpu_inner_product_fwd_pd_t: public inner_product_fwd_pd_t {
+ using inner_product_fwd_pd_t::inner_product_fwd_pd_t;
+};
+
+struct cpu_inner_product_bwd_data_pd_t: public inner_product_bwd_data_pd_t {
+ using inner_product_bwd_data_pd_t::inner_product_bwd_data_pd_t;
+};
+
+struct cpu_inner_product_bwd_weights_pd_t: public inner_product_bwd_weights_pd_t {
+ using inner_product_bwd_weights_pd_t::inner_product_bwd_weights_pd_t;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_isa_traits.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_isa_traits.hpp
new file mode 100644
index 0000000000..da6e9dac8e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_isa_traits.hpp
@@ -0,0 +1,151 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_ISA_TRAITS_HPP
+#define CPU_ISA_TRAITS_HPP
+
+#include <type_traits>
+
+#define XBYAK64
+#define XBYAK_NO_OP_NAMES
+/* in order to make selinux happy memory that would be marked with X-bit should
+ * be obtained with mmap */
+#define XBYAK_USE_MMAP_ALLOCATOR
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+/* turn off `size_t to other-type implicit casting` warning
+ * currently we have a lot of jit-generated instructions that
+ * take uint32_t, but we pass size_t (e.g. due to using sizeof).
+ * FIXME: replace size_t parameters with the appropriate ones */
+#pragma warning (disable: 4267)
+#endif
+#include "xbyak/xbyak.h"
+#include "xbyak/xbyak_util.h"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+typedef enum {
+ isa_any,
+ sse41,
+ sse42,
+ avx,
+ avx2,
+ avx512_common,
+ avx512_core,
+ avx512_core_vnni,
+ avx512_mic,
+ avx512_mic_4ops,
+} cpu_isa_t;
+
+template <cpu_isa_t> struct cpu_isa_traits {}; /* ::vlen -> 32 (for avx2) */
+
+template <> struct cpu_isa_traits<sse42> {
+ typedef Xbyak::Xmm Vmm;
+ static constexpr int vlen_shift = 4;
+ static constexpr int vlen = 16;
+ static constexpr int n_vregs = 16;
+};
+template <> struct cpu_isa_traits<avx> {
+ typedef Xbyak::Ymm Vmm;
+ static constexpr int vlen_shift = 5;
+ static constexpr int vlen = 32;
+ static constexpr int n_vregs = 16;
+};
+template <> struct cpu_isa_traits<avx2>:
+ public cpu_isa_traits<avx> {};
+
+template <> struct cpu_isa_traits<avx512_common> {
+ typedef Xbyak::Zmm Vmm;
+ static constexpr int vlen_shift = 6;
+ static constexpr int vlen = 64;
+ static constexpr int n_vregs = 32;
+};
+template <> struct cpu_isa_traits<avx512_core>:
+ public cpu_isa_traits<avx512_common> {};
+
+template <> struct cpu_isa_traits<avx512_mic>:
+ public cpu_isa_traits<avx512_common> {};
+
+template <> struct cpu_isa_traits<avx512_mic_4ops>:
+ public cpu_isa_traits<avx512_common> {};
+
+namespace {
+
+static Xbyak::util::Cpu cpu;
+static inline bool mayiuse(const cpu_isa_t cpu_isa) {
+ using namespace Xbyak::util;
+
+ switch (cpu_isa) {
+ case sse41:
+ case sse42:
+ // FIXME: SSE4.2 is actually NOT required
+ //return cpu.has(Cpu::tSSE42);
+ return cpu.has(Cpu::tSSE41);
+ case avx:
+ return cpu.has(Cpu::tAVX);
+ case avx2:
+ return cpu.has(Cpu::tAVX2);
+ case avx512_common:
+ return cpu.has(Cpu::tAVX512F);
+ case avx512_core:
+ return true
+ && cpu.has(Cpu::tAVX512F)
+ && cpu.has(Cpu::tAVX512BW)
+ && cpu.has(Cpu::tAVX512VL)
+ && cpu.has(Cpu::tAVX512DQ);
+ case avx512_core_vnni:
+ return true
+ && cpu.has(Cpu::tAVX512F)
+ && cpu.has(Cpu::tAVX512BW)
+ && cpu.has(Cpu::tAVX512VL)
+ && cpu.has(Cpu::tAVX512DQ)
+ && cpu.has(Cpu::tAVX512_VNNI);
+ case avx512_mic:
+ return true
+ && cpu.has(Cpu::tAVX512F)
+ && cpu.has(Cpu::tAVX512CD)
+ && cpu.has(Cpu::tAVX512ER)
+ && cpu.has(Cpu::tAVX512PF);
+ case avx512_mic_4ops:
+ return true
+ && mayiuse(avx512_mic)
+ && cpu.has(Cpu::tAVX512_4FMAPS)
+ && cpu.has(Cpu::tAVX512_4VNNIW);
+ case isa_any:
+ return true;
+ }
+ return false;
+}
+}
+
+/* whatever is required to generate string literals... */
+#include "z_magic.hpp"
+#define JIT_IMPL_NAME_HELPER(prefix, isa, suffix_if_any) \
+ (isa == sse42 ? prefix STRINGIFY(sse42) : \
+ (isa == avx ? prefix STRINGIFY(avx) : \
+ (isa == avx2 ? prefix STRINGIFY(avx2) : \
+ (isa == avx512_common ? prefix STRINGIFY(avx512_common) : \
+ (isa == avx512_core ? prefix STRINGIFY(avx512_core) : \
+ (isa == avx512_mic ? prefix STRINGIFY(avx512_mic) : \
+ (isa == avx512_mic_4ops ? prefix STRINGIFY(avx512_mic_4ops) : \
+ prefix suffix_if_any)))))))
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_lrn_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_lrn_pd.hpp
new file mode 100644
index 0000000000..49988f4c2d
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_lrn_pd.hpp
@@ -0,0 +1,42 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_LRN_PD_HPP
+#define CPU_LRN_PD_HPP
+
+#include <assert.h>
+
+#include "lrn_pd.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_lrn_fwd_pd_t: public lrn_fwd_pd_t {
+ using lrn_fwd_pd_t::lrn_fwd_pd_t;
+};
+
+struct cpu_lrn_bwd_pd_t: public lrn_bwd_pd_t {
+ using lrn_bwd_pd_t::lrn_bwd_pd_t;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.cpp
new file mode 100644
index 0000000000..3c0624cf46
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.cpp
@@ -0,0 +1,277 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "mkldnn_traits.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_memory.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::data_type;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::format_tag;
+
+enum blk_kind_t { a, b, c, ab, ba, bc, cb };
+
+template <data_type_t dt, blk_kind_t blk_kind, int blksize>
+void typed_zero_pad_blk(
+ const memory_desc_wrapper &m_d, typename prec_traits<dt>::type *data) {
+ using data_t = typename prec_traits<dt>::type;
+ const auto &dims = m_d.dims();
+ const auto &pdims = m_d.padded_dims();
+ const auto &blk = m_d.blocking_desc();
+ auto dim_is_blocked = [&](int dim) {
+ for (int i = 0; i < blk.inner_nblks; i++)
+ if (blk.inner_idxs[i] == dim)
+ return true;
+ return false;
+ };
+ bool A_blocked = dim_is_blocked(0), B_blocked = dim_is_blocked(1),
+ C_blocked = dim_is_blocked(2);
+
+ assert(blk.inner_nblks < 4);
+ assert((A_blocked || B_blocked || C_blocked) || (A_blocked && B_blocked)
+ || (C_blocked && B_blocked));
+
+ const int a_tail_s = A_blocked ? dims[0] % blksize : 0;
+ const int b_tail_s = B_blocked ? dims[1] % blksize : 0;
+ const int c_tail_s = C_blocked ? dims[2] % blksize : 0;
+ assert(a_tail_s || b_tail_s || c_tail_s);
+
+ const int A = A_blocked ? pdims[0] / blksize : dims[0];
+ const int B = B_blocked ? pdims[1] / blksize : dims[1];
+ const int C = C_blocked ? pdims[2] / blksize : dims[2];
+ const int D = m_d.ndims() > 3 ? dims[3] : 1;
+ const int E = m_d.ndims() > 4 ? dims[4] : 1;
+ const int F = m_d.ndims() > 5 ? dims[5] : 1;
+ const int inner_blk = blk.inner_nblks == 3 ? blk.inner_blks[2] : 1;
+
+ auto zeroize_tail = [&](data_t *d, const int tail_s) {
+ for (int b = tail_s; b < blksize; ++b)
+ d[b] = 0;
+ };
+ auto zeroize_tail_inner = [&](data_t *d, const int tail_s) {
+ for (int b1 = 0; b1 < blksize; ++b1)
+ for (int b2 = tail_s; b2 < blksize; ++b2)
+ d[(b1 / inner_blk) * blksize * inner_blk + inner_blk * b2
+ + b1 % inner_blk]
+ = 0;
+ };
+ auto zeroize_tail_outer = [&](data_t *d, const int tail_s) {
+ for (int b1 = tail_s; b1 < blksize; ++b1)
+ for (int b2 = 0; b2 < blksize; ++b2)
+ d[(b1 / inner_blk) * blksize * inner_blk + inner_blk * b2
+ + b1 % inner_blk]
+ = 0;
+ };
+
+ if (c_tail_s) {
+ parallel_nd(A, B, D, E, F, [&](int a, int b, int d, int e, int f) {
+ auto x = &data[m_d.blk_off(a, b, C - 1, d, e, f)];
+ if (blk_kind == c)
+ zeroize_tail(x, c_tail_s);
+ else if (blk_kind == bc)
+ zeroize_tail_inner(x, c_tail_s);
+ else if (blk_kind == cb)
+ zeroize_tail_outer(x, c_tail_s);
+ });
+ }
+
+ if (b_tail_s) {
+ parallel_nd(A, C, D, E, F, [&](int a, int c, int d, int e, int f) {
+ auto x = &data[m_d.blk_off(a, B - 1, c, d, e, f)];
+ if (blk_kind == b)
+ zeroize_tail(x, b_tail_s);
+ else if (blk_kind == ab || blk_kind == cb)
+ zeroize_tail_inner(x, b_tail_s);
+ else if (blk_kind == ba || blk_kind == bc)
+ zeroize_tail_outer(x, b_tail_s);
+ });
+ }
+
+ if (a_tail_s) {
+ parallel_nd(B, C, D, E, F, [&](int b, int c, int d, int e, int f) {
+ auto x = &data[m_d.blk_off(A - 1, b, c, d, e, f)];
+ if (blk_kind == a)
+ zeroize_tail(x, a_tail_s);
+ else if (blk_kind == ba)
+ zeroize_tail_inner(x, a_tail_s);
+ else if (blk_kind == ab)
+ zeroize_tail_outer(x, a_tail_s);
+ });
+ }
+}
+
+/*
+ * all
+ */
+template <data_type_t dt>
+void typed_zero_pad_generic_blocked(
+ const memory_desc_wrapper &m_d, typename prec_traits<dt>::type *data) {
+ const int ndims = m_d.ndims();
+ const auto &dims = m_d.dims();
+ const auto &pdims = m_d.padded_dims();
+
+ const ptrdiff_t nelems = (ptrdiff_t)m_d.nelems(true);
+
+ /* [D_0] .. [D_k][D_k+1] .. [D_ndim - 1]
+ * | \ /
+ * | ---------------------
+ * has contiguous
+ * padding
+ *
+ * step <-- D_k+1 * ... * D_ndims-1
+ * step_dim <-- k
+ */
+
+ ptrdiff_t step = 1;
+ int step_dim = ndims - 1;
+ for (; step_dim >= 0; --step_dim) {
+ if (dims[step_dim] != pdims[step_dim])
+ break;
+ step *= dims[step_dim];
+ }
+
+ assert(step_dim >= 0 && "no zero padding is required");
+ if (step_dim < 0)
+ return;
+
+ parallel_nd(nelems / step, [&](ptrdiff_t e1) {
+ bool need_zero = false;
+
+ ptrdiff_t idx = e1;
+ for (int d = step_dim; d >= 0; --d) {
+ if (idx % pdims[d] >= dims[d]) {
+ need_zero = true;
+ break;
+ }
+ idx /= pdims[d];
+ }
+
+ if (need_zero) {
+ for (ptrdiff_t e0 = 0; e0 < step; ++e0)
+ data[m_d.off_l(e1 * step + e0, true)] = 0;
+ }
+ });
+}
+
+template <data_type_t dt>
+status_t cpu_memory_t::typed_zero_pad() const {
+ const memory_desc_wrapper mdw(md());
+
+ if (mdw.format_kind() != format_kind::blocked)
+ return unimplemented;
+
+ if (mdw.nelems(false) == mdw.nelems(true))
+ return success;
+
+ auto *data = (typename prec_traits<dt>::type *)data_;
+ auto blk = mdw.blocking_desc();
+
+ auto get_blksize = [&](int ind) {
+ int blksize = 1;
+ for (int i = 0; i < blk.inner_nblks; i++) {
+ if (blk.inner_idxs[i] == ind)
+ blksize *= blk.inner_blks[i];
+ }
+ return blksize;
+ };
+ const int blksize = get_blksize(blk.inner_idxs[0]);
+
+# define CASE(blksize_, blk_kind) \
+ do { \
+ if (blksize == blksize_) { \
+ typed_zero_pad_blk<dt, blk_kind, blksize_>(mdw, data); \
+ return success; \
+ } \
+ } while(0)
+
+ switch (blk.inner_nblks) {
+ case 1:
+ if (blk.inner_idxs[0] == 0) {
+ CASE(4, a);
+ CASE(8, a);
+ CASE(16, a);
+ } else if (blk.inner_idxs[0] == 1) {
+ CASE(4, b);
+ CASE(8, b);
+ CASE(16, b);
+ }
+ break;
+ case 2:
+ case 3:
+ if (!IMPLICATION(blk.inner_nblks == 3,
+ blk.inner_idxs[0] == blk.inner_idxs[2]))
+ break;
+
+ if (blk.inner_idxs[0] == 0 && blk.inner_idxs[1] == 1) {
+ CASE(4, ab);
+ CASE(8, ab);
+ CASE(16, ab);
+ } else if (blk.inner_idxs[0] == 1 && blk.inner_idxs[1] == 0) {
+ CASE(4, ba);
+ CASE(8, ba);
+ CASE(16, ba);
+ }
+ if (blk.inner_idxs[0] == 1 && blk.inner_idxs[1] == 2) {
+ CASE(4, bc);
+ CASE(8, bc);
+ CASE(16, bc);
+ } else if (blk.inner_idxs[0] == 2 && blk.inner_idxs[1] == 1) {
+ CASE(4, cb);
+ CASE(8, cb);
+ CASE(16, cb);
+ }
+ break;
+ default: break;
+ }
+
+# undef CASE
+
+ // the last line of defence
+ typed_zero_pad_generic_blocked<dt>(mdw, data);
+ return success;
+}
+
+status_t cpu_memory_t::zero_pad() const {
+ memory_desc_wrapper mdw(md());
+ const bool skip_zeroing = false
+ || data_ == nullptr
+ || mdw.is_zero()
+ || !mdw.is_blocking_desc();
+ if (skip_zeroing) return success;
+
+ switch (mdw.data_type()) {
+ case f32: return typed_zero_pad<f32>();
+ case s32: return typed_zero_pad<s32>();
+ case s8: return typed_zero_pad<s8>();
+ case u8: return typed_zero_pad<u8>();
+ default: assert(!"memory is undefined"); return unimplemented;
+ }
+ return unimplemented;
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.hpp
new file mode 100644
index 0000000000..2c01bcc6af
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_memory.hpp
@@ -0,0 +1,89 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_MEMORY_HPP
+#define CPU_MEMORY_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory.hpp"
+#include "memory_desc_wrapper.hpp"
+
+#include "cpu_engine.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_memory_t: public memory_t {
+ cpu_memory_t(cpu_engine_t *engine, const memory_desc_t *md, void *handle)
+ : memory_t(engine, md)
+ , own_data_(handle == MKLDNN_NATIVE_HANDLE_ALLOCATE)
+ , data_((char *)handle) {}
+
+ cpu_memory_t(cpu_engine_t *engine, const memory_desc_t *md)
+ : cpu_memory_t(engine, md, nullptr) {}
+
+ ~cpu_memory_t() { if (own_data_) free(data_); }
+
+ virtual status_t init() override {
+ if (own_data_) {
+ data_ = nullptr;
+ const size_t size = memory_desc_wrapper(this->md()).size();
+ if (size) {
+ data_ = (char *)malloc(size, 64);
+ if (data_ == nullptr)
+ return status::out_of_memory;
+ }
+ }
+ return zero_pad();
+ }
+
+ cpu_engine_t *engine() const { return (cpu_engine_t *)memory_t::engine(); }
+
+ virtual status_t get_data_handle(void **handle) const override {
+ *handle = static_cast<void *>(data_);
+ return status::success;
+ }
+
+ virtual mkldnn::impl::status_t set_data_handle(void *handle) override {
+ if (own_data_) { free(data_); own_data_ = false; }
+ data_ = static_cast<char *>(handle);
+ return zero_pad();
+ }
+
+ virtual mkldnn::impl::status_t zero_pad() const override;
+
+private:
+ bool own_data_;
+ char *data_;
+
+ template <mkldnn::impl::data_type_t>
+ mkldnn::impl::status_t typed_zero_pad() const;
+
+ cpu_memory_t(const cpu_memory_t &) = delete;
+ cpu_memory_t &operator=(const cpu_memory_t &) = delete;
+ cpu_memory_t &operator=(cpu_memory_t &&) = delete;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_pooling_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_pooling_pd.hpp
new file mode 100644
index 0000000000..ac2daa415e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_pooling_pd.hpp
@@ -0,0 +1,40 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_POOLING_PD_HPP
+#define CPU_POOLING_PD_HPP
+
+#include "pooling_pd.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_pooling_fwd_pd_t: public pooling_fwd_pd_t {
+ using pooling_fwd_pd_t::pooling_fwd_pd_t;
+};
+
+struct cpu_pooling_bwd_pd_t: public pooling_bwd_pd_t {
+ using pooling_bwd_pd_t::pooling_bwd_pd_t;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_primitive.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_primitive.hpp
new file mode 100644
index 0000000000..56127f36c2
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_primitive.hpp
@@ -0,0 +1,83 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_PRIMITIVE_HPP
+#define CPU_PRIMITIVE_HPP
+
+#include "mkldnn.h"
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "primitive.hpp"
+#include "scratchpad.hpp"
+
+#define CTX_IN_MEM(type, arg) static_cast<type>(ctx.input(arg))
+#define CTX_OUT_MEM(type, arg) static_cast<type>(ctx.output(arg))
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_memory_t;
+
+struct cpu_primitive_t: public primitive_t {
+ cpu_primitive_t(const primitive_desc_t *pd,
+ bool use_global_scratchpad = false)
+ : primitive_t(pd)
+ , scratchpad_buffer_(nullptr)
+ , global_scratchpad_(nullptr)
+ {
+ const size_t scratchpad_size =
+ this->pd()->scratchpad_size(scratchpad_mode::library);
+
+ if (scratchpad_size) {
+ if (use_global_scratchpad)
+ global_scratchpad_ = create_scratchpad(scratchpad_size);
+ else
+ scratchpad_buffer_ = malloc(scratchpad_size, 64);
+ }
+ }
+
+ virtual ~cpu_primitive_t() {
+ delete global_scratchpad_;
+ free(scratchpad_buffer_);
+ }
+
+protected:
+ memory_tracking::grantor_t scratchpad(const exec_ctx_t &ctx) const {
+ void *ptr = nullptr;
+ if (pd()->attr()->scratchpad_mode_ == scratchpad_mode::user) {
+ ptr = CTX_OUT_MEM(void *, MKLDNN_ARG_SCRATCHPAD);
+ } else {
+ ptr = global_scratchpad_
+ ? global_scratchpad_->get() : scratchpad_buffer_;
+ }
+
+ return pd()->scratchpad_registry().grantor(ptr);
+ }
+
+private:
+ void *scratchpad_buffer_;
+ scratchpad_t *global_scratchpad_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.cpp
new file mode 100644
index 0000000000..1d41ac5cea
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.cpp
@@ -0,0 +1,544 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "mkldnn_thread.hpp"
+#include "mkldnn_types.h"
+#include "nstl.hpp"
+#include "utils.hpp"
+
+#include "cpu_reducer.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace memory_tracking::names;
+
+void reduce_balancer_t::balance() {
+ using namespace nstl;
+ using namespace utils;
+
+ assert(nthr_ > 0 && job_size_ > 0 && njobs_ > 0 && reduction_size_ > 0);
+
+ const int job_complexity = 1;
+
+ const int min_njobs_per_group = max(1, njobs_ / nthr_);
+ const int max_njobs_per_group = max(1,
+ static_cast<int>(max_buffer_size_ / (nthr_ * job_size_)));
+
+ /* initial guess */
+ int ngroups = min(njobs_ / min_njobs_per_group, nthr_);
+ int nthr_per_group = syncable_ ? min(nthr_ / ngroups, reduction_size_) : 1;
+ int njobs_per_group_ub = div_up(njobs_, ngroups);
+
+ /* rough upper-bound estimation, will be fixed during brute force */
+ size_t thread_complexity_ub = njobs_ * job_size_ * reduction_size_;
+
+ /* brute force parameters for the best balance... */
+ for (int c_njobs_per_group = min_njobs_per_group;
+ c_njobs_per_group < njobs_; ++c_njobs_per_group) {
+ /* current assumption */
+ int c_ngroups = min(njobs_ / c_njobs_per_group, nthr_);
+ int c_nthr_per_group = syncable_
+ ? min(nthr_ / c_ngroups, reduction_size_) : 1;
+ int c_njobs_per_group_ub = div_up(njobs_, c_ngroups);
+
+ if (c_nthr_per_group > 1 && c_njobs_per_group_ub > max_njobs_per_group)
+ continue;
+
+ int c_thread_reduction_ub = div_up(reduction_size_, c_nthr_per_group);
+ size_t c_group_size_ub = job_size_ * c_njobs_per_group_ub;
+ size_t c_thread_complexity_ub = c_group_size_ub * (
+ job_complexity * c_thread_reduction_ub
+ + (c_nthr_per_group != 1));
+
+ if (c_thread_complexity_ub < thread_complexity_ub) {
+ ngroups = c_ngroups;
+ nthr_per_group = c_nthr_per_group;
+ njobs_per_group_ub = c_njobs_per_group_ub;
+ thread_complexity_ub = c_thread_complexity_ub;
+ }
+ }
+
+ assert(njobs_per_group_ub <= max_njobs_per_group || nthr_per_group == 1);
+ assert(ngroups * nthr_per_group <= nthr_);
+ assert((size_t)njobs_per_group_ub * job_size_ * nthr_ <= max_buffer_size_
+ || nthr_per_group == 1); /* no reduction buffer overflow */
+ assert(IMPLICATION(!syncable_, nthr_per_group == 1));
+
+ ngroups_ = ngroups;
+ nthr_per_group_ = nthr_per_group;
+ njobs_per_group_ub_ = njobs_per_group_ub;
+}
+
+/* reducer jit-ted driver */
+
+using namespace Xbyak;
+
+template <impl::data_type_t data_type>
+struct reducer_2d_driver_t: public c_compatible {
+ typedef typename prec_traits<data_type>::type data_t;
+
+ reducer_2d_driver_t(int n_src, size_t src_ld,
+ size_t src_step, size_t dst_step, bool nullify_dst)
+ : n_src_(n_src), src_ld_(src_ld), src_step_(src_step)
+ , dst_step_(dst_step), nullify_dst_(nullify_dst), ker_(nullptr) {}
+ virtual ~reducer_2d_driver_t() {}
+ void operator()(data_t *dst, const data_t *srcs, size_t ny, size_t nx)
+ { assert(ker_); ker_(dst, srcs, ny, nx); }
+
+protected:
+ int n_src_;
+ size_t src_ld_, src_step_, dst_step_;
+ bool nullify_dst_;
+ void (*ker_)(data_t *dst, const data_t *srcs, size_t ny, size_t nx);
+};
+
+template <impl::data_type_t data_type, cpu_isa_t isa>
+struct reducer_2d_driver_f_s_32_t: public reducer_2d_driver_t<data_type>,
+ public jit_generator
+{
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(reducer_2d_driver_f_s_32_t)
+
+ /* cpu specific part */
+ using Vmm = typename utils::conditional<isa == avx2, Ymm, Zmm>::type;
+ const AddressFrame &vmmword = (isa == avx2) ? yword : zword;
+ void uni_vadd(const Xmm& x1, const Xmm& x2, const Operand& op)
+ { if (data_type == data_type::f32) vaddps(x1, x2, op);
+ else vpaddd(x1, x2, op); }
+ void uni_add(const Xmm& x1, const Operand& op)
+ { if (data_type == data_type::f32) addss(x1, op); else paddd(x1, op); }
+
+ const int vlen = cpu_isa_traits<isa>::vlen;
+ const int typesize
+ = sizeof(typename mkldnn::impl::prec_traits<data_type>::type);
+ Xbyak::Reg64 reg_dst = abi_param1;
+ Xbyak::Reg64 reg_src = abi_param2;
+ Xbyak::Reg64 reg_ny = abi_param3;
+ Xbyak::Reg64 reg_nx = abi_param4;
+
+ Xbyak::Reg64 reg_x = rax;
+ Xbyak::Reg64 reg_src_id = r10;
+
+ reducer_2d_driver_f_s_32_t(int n_src, size_t src_ld, size_t src_step,
+ size_t dst_step, bool nullify_dst)
+ : reducer_2d_driver_t<data_type>(n_src, src_ld, src_step,
+ dst_step, nullify_dst)
+ { generate(); }
+
+ void nullify_dst(int nloads, int load_len) {
+ UNUSED(load_len);
+ for (int i = 0; i < nloads; ++i)
+ uni_vpxor(Vmm(i), Vmm(i), Vmm(i));
+ /* prefetches[dst] ? */
+ }
+
+ void load_dst(int nloads, int load_len) {
+ for (int i = 0; i < nloads; ++i) {
+ if (load_len == typesize)
+ movd(Xmm(i), ptr[reg_dst + i * load_len]);
+ else if (load_len == vlen)
+ vmovups(Vmm(i), ptr[reg_dst + i * load_len]);
+ else
+ assert(!"unsupported");
+ }
+ }
+
+ void store_dst(int nloads, int load_len) {
+ for (int i = 0; i < nloads; ++i) {
+ if (load_len == typesize)
+ movd(ptr[reg_dst + i * load_len], Xmm(i));
+ else if (load_len == vlen)
+ vmovups(ptr[reg_dst + i * load_len], Vmm(i));
+ else
+ assert(!"unsupported");
+ }
+ }
+
+ void accumulate(int nloads, int load_len, size_t base_off) {
+ for (int i = 0; i < nloads; ++i) {
+ size_t off = base_off + i * load_len;
+
+ if (load_len == typesize)
+ uni_add(Xmm(i), ptr[reg_src + off]);
+ else if (load_len == vlen)
+ uni_vadd(Vmm(i), Vmm(i), vmmword[reg_src + off]);
+ else
+ assert(!"unsupported");
+ }
+ }
+
+ void loop_x() {
+ const int nloads[] = {cpu_isa_traits<isa>::n_vregs, 1, 1};
+ const int nbranches = sizeof(nloads) / sizeof(nloads[0]);
+
+ const int load_len[nbranches] = {vlen, vlen, typesize};
+ Label loop_x_label[nbranches + 1];
+
+ mov(reg_x, reg_nx);
+
+ for (int id = 0; id < nbranches; ++id) {
+ L(loop_x_label[id]);
+
+ cmp(reg_x, nloads[id] * load_len[id]);
+ jl(loop_x_label[id + 1], T_NEAR);
+
+ if (this->nullify_dst_)
+ nullify_dst(nloads[id], load_len[id]);
+ else
+ load_dst(nloads[id], load_len[id]);
+
+ if (nloads[id] > 1) {
+ Label loop_srcs;
+ mov(reg_src_id, this->n_src_);
+ L(loop_srcs);
+
+ accumulate(nloads[id], load_len[id], 0);
+ add(reg_src, this->src_ld_ * typesize);
+
+ dec(reg_src_id);
+ jnz(loop_srcs, T_NEAR);
+
+ sub(reg_src, this->n_src_ * this->src_ld_ * typesize);
+ } else {
+ for (int src_id = 0; src_id < this->n_src_; ++src_id) {
+ const size_t base_off = src_id * this->src_ld_ * typesize;
+ accumulate(nloads[id], load_len[id], base_off);
+ }
+ }
+
+ store_dst(nloads[id], load_len[id]);
+
+ add(reg_src, nloads[id] * load_len[id]);
+ add(reg_dst, nloads[id] * load_len[id]);
+
+ sub(reg_x, nloads[id] * load_len[id]);
+
+ jmp(loop_x_label[id], T_NEAR);
+ }
+
+ L(loop_x_label[nbranches]);
+
+ /* restore address registers */
+ sub(reg_src, reg_nx);
+ sub(reg_dst, reg_nx);
+ }
+
+ void generate() {
+ assert(isa == avx2 || isa == avx512_common || isa == avx512_mic);
+
+ preamble();
+
+ shl(reg_nx, 2);
+
+ Label ny_loop;
+ L(ny_loop);
+
+ loop_x();
+
+ add(reg_dst, this->dst_step_ * typesize);
+ add(reg_src, this->src_step_ * typesize);
+
+ dec(reg_ny);
+ jnz(ny_loop, T_NEAR);
+
+ postamble();
+ this->ker_ = reinterpret_cast<decltype(this->ker_)>(
+ const_cast<uint8_t*>(this->getCode()));
+ }
+};
+
+template <impl::data_type_t data_type>
+inline reducer_2d_driver_t<data_type> *create_reduce_2d_drv(int n_src,
+ size_t src_ld, size_t src_step, size_t dst_step, bool nullify_dst) {
+ if (mayiuse(avx512_common))
+ return new reducer_2d_driver_f_s_32_t<data_type, avx512_common>(n_src,
+ src_ld, src_step, dst_step, nullify_dst);
+ else if (mayiuse(avx2))
+ return new reducer_2d_driver_f_s_32_t<data_type, avx2>(n_src, src_ld,
+ src_step, dst_step, nullify_dst);
+ assert(!"unimplemented");
+ return nullptr;
+}
+
+/* cpu_reducer_t */
+
+template <impl::data_type_t data_type>
+void cpu_reducer_t<data_type>::conf_t::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad) const {
+ if (balancer_.nthr_per_group_ == 1) return;
+
+ const size_t space_size = balancer_.ngroups_
+ * (balancer_.nthr_per_group_ - 1)
+ * cpu_reducer_t<data_type>::space_per_thread(balancer_);
+ scratchpad.book(key_reducer_space, sizeof(data_t) * space_size, PAGE_4K);
+ scratchpad.book(key_reducer_space_bctx,
+ sizeof(simple_barrier::ctx_t) * balancer_.ngroups_);
+}
+
+template <impl::data_type_t data_type>
+cpu_reducer_t<data_type>::cpu_reducer_t(const conf_t &conf)
+ : conf_(conf), drv_(nullptr)
+{
+ if (balancer().nthr_per_group_ == 1) return;
+
+ drv_ = create_reduce_2d_drv<data_type>(balancer().nthr_per_group_ - 1,
+ space_per_thread(balancer()), 0, 0, false);
+}
+
+template <impl::data_type_t data_type>
+cpu_reducer_t<data_type>::~cpu_reducer_t() { delete drv_; }
+
+template <impl::data_type_t data_type>
+typename cpu_reducer_t<data_type>::data_t *
+cpu_reducer_t<data_type>::get_local_ptr(int ithr, data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const int id_in_grp = balancer().id_in_group(ithr);
+
+ /* threads 0 from each group writes directly to the destination */
+ if (id_in_grp == 0)
+ return dst + balancer().ithr_job_off(ithr) * balancer().job_size_;
+
+ const int grp_id = balancer().group_id(ithr);
+ const int offset_factor = grp_id * (balancer().nthr_per_group_ - 1)
+ + (id_in_grp - 1);
+
+ auto space = scratchpad.template get<data_t>(key_reducer_space);
+ return space + offset_factor * space_per_thread(balancer());
+}
+
+template <impl::data_type_t data_type>
+void cpu_reducer_t<data_type>::reduce_nolock(int ithr, data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const {
+ bool redundant_reduction = balancer().nthr_per_group_ == 1
+ || balancer().idle(ithr);
+ if (redundant_reduction) return;
+
+#ifdef SIMPLE_IMPL
+ if (balancer().id_in_group(ithr) != 0)
+ return; /* only threads 0 do the reduction */
+
+ const int njobs_in_grp = balancer().ithr_njobs(ithr);
+ data_t *d = get_local_ptr(ithr, dst, scratchpad);
+ for (int id_in_grp = 1; id_in_grp < balancer_.nthr_per_group_; ++id_in_grp)
+ {
+ const data_t *space = get_local_ptr(ithr + id_in_grp, dst, scratchpad);
+ for (size_t i = 0; i < (size_t)njobs_in_grp * balancer().job_size_; ++i)
+ d[i] += space[i];
+ }
+#else
+ using namespace utils;
+
+ const int id_in_grp = balancer().id_in_group(ithr);
+ const int njobs_in_grp = balancer().ithr_njobs(ithr);
+ const size_t cl = 64 / sizeof(data_t);
+
+ const size_t reduction_size = njobs_in_grp * balancer().job_size_;
+ size_t start{0}, end{0};
+ balance211(div_up(reduction_size, cl), balancer().nthr_per_group_,
+ id_in_grp, start, end);
+
+ if (start == end) return;
+
+ data_t *d = get_local_ptr(ithr - id_in_grp, dst, scratchpad) + start * cl;
+ const data_t *space = get_local_ptr(ithr - id_in_grp + 1, dst, scratchpad)
+ + start * cl;
+ const size_t len = nstl::min(end * cl, reduction_size) - start * cl;
+
+ (*drv_)(d, space, 1, len);
+#endif
+}
+
+template struct cpu_reducer_t<data_type::f32>;
+template struct cpu_reducer_t<data_type::s32>;
+
+/* cpu_reducer_2d_t */
+
+template <impl::data_type_t data_type>
+void cpu_reducer_2d_t<data_type>::conf_t::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad) const {
+ if (balancer_.nthr_per_group_ == 1) return;
+
+ const size_t space_size = balancer_.ngroups_ * balancer_.nthr_per_group_
+ * cpu_reducer_2d_t<data_type>::space_per_thread(balancer_);
+ scratchpad.book(key_reducer_space, sizeof(data_t) * space_size);
+ scratchpad.book(key_reducer_space_bctx,
+ sizeof(simple_barrier::ctx_t) * balancer_.ngroups_);
+}
+
+template <impl::data_type_t data_type>
+cpu_reducer_2d_t<data_type>::cpu_reducer_2d_t(const conf_t &conf)
+ : conf_(conf), drv_(nullptr)
+{
+ if (balancer().nthr_per_group_ == 1) return;
+
+ drv_ = create_reduce_2d_drv<data_type>(balancer().nthr_per_group_,
+ space_per_thread(balancer()), conf_.job_size_x_, conf_.dst_x_,
+ true);
+}
+
+template <impl::data_type_t data_type>
+cpu_reducer_2d_t<data_type>::~cpu_reducer_2d_t() { delete drv_; }
+
+template <impl::data_type_t data_type>
+typename cpu_reducer_2d_t<data_type>::data_t *cpu_reducer_2d_t<data_type>::
+get_local_ptr(int ithr, const memory_tracking::grantor_t &scratchpad) const {
+ const int id_in_grp = balancer().id_in_group(ithr);
+ const int grp_id = balancer().group_id(ithr);
+ const int offset_factor = grp_id * balancer().nthr_per_group_ + id_in_grp;
+ auto space = scratchpad.template get<data_t>(key_reducer_space);
+ return space + offset_factor * space_per_thread(balancer());
+}
+
+template <impl::data_type_t data_type>
+int cpu_reducer_2d_t<data_type>::choose_x_blocking(int nx, int ny,
+ int nthr_per_grp) const {
+ // find x_blocking for better balance reducing work between threads
+ assert(conf_.x_block_ > 0 && nx > conf_.x_block_
+ && nx % conf_.x_block_ == 0);
+ int x_blocking = nx / conf_.x_block_;
+ int min_x_blocking =
+ utils::div_up(x_blocking, nstl::max(1, nthr_per_grp / ny));
+ while (true) {
+ if (x_blocking % 2 == 0 && x_blocking >= min_x_blocking * 2)
+ x_blocking /= 2;
+ else if (x_blocking % 3 == 0 && x_blocking >= min_x_blocking * 3)
+ x_blocking /= 3;
+ else
+ break;
+ }
+ if (x_blocking >= min_x_blocking * 4) x_blocking = 1;
+ x_blocking *= conf_.x_block_;
+ return x_blocking;
+}
+
+template <impl::data_type_t data_type>
+void cpu_reducer_2d_t<data_type>::reduce_block(const data_t* space_base,
+ data_t *dst, int job, int start_y, int start_x,
+ int ny_start, int nx_start, int ny_step, int nx_step) const {
+ data_t *d = dst + (start_y + ny_start) * conf_.dst_x_
+ + start_x + nx_start;
+ const data_t *space = space_base + job * balancer().job_size_
+ + ny_start * conf_.job_size_x_ + nx_start;
+#ifdef SIMPLE_IMPL
+ for (int idg = 0; idg < balancer().nthr_per_group_; ++idg) {
+ const data_t *w = &space[idg * space_per_thread(balancer())];
+ for (int y = 0; y < ny_step; ++y)
+ for (int x = 0; x < nx_step; ++x) {
+ d[y * conf_.dst_x_ + x]
+ = (idg == 0 ? 0 : d[y * conf_.dst_x_ + x])
+ + w[y * conf_.job_size_x_ + x];
+ }
+ }
+#else
+ (*drv_)(d, space, ny_step, nx_step);
+#endif
+}
+
+template <impl::data_type_t data_type>
+void cpu_reducer_2d_t<data_type>::reduce_nolock(int ithr, data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const {
+ bool redundant_reduction = balancer().nthr_per_group_ == 1
+ || balancer().idle(ithr);
+ if (redundant_reduction) return;
+
+ const int id_in_grp = balancer().id_in_group(ithr);
+ const int njobs_in_grp = balancer().ithr_njobs(ithr);
+ const int njobs_x = utils::div_up(conf_.dst_x_, conf_.job_size_x_);
+ const int global_job_start = balancer().ithr_job_off(ithr);
+
+ const data_t *space_base = get_local_ptr(ithr - id_in_grp, scratchpad);
+
+ const int pr_grps = nstl::min(njobs_in_grp, balancer().nthr_per_group_);
+ const int pr_nthr_per_grp = balancer().nthr_per_group_ / pr_grps;
+
+ if (id_in_grp >= pr_grps * pr_nthr_per_grp)
+ return; /* idle */
+
+ const int pr_my_grp = id_in_grp / pr_nthr_per_grp;
+ const int pr_my_id = id_in_grp % pr_nthr_per_grp;
+
+ int pr_job_start{0}, pr_job_end{0};
+ balance211(njobs_in_grp, pr_grps, pr_my_grp, pr_job_start, pr_job_end);
+
+ for (int j = pr_job_start; j < pr_job_end; ++j) {
+ const int global_job = global_job_start + j;
+ const int j_y = global_job / njobs_x;
+ const int j_x = global_job % njobs_x;
+ const int start_y = j_y * conf_.job_size_y_;
+ const int start_x = j_x * conf_.job_size_x_;
+ const int ny = nstl::min(conf_.dst_y_ - start_y, conf_.job_size_y_);
+ const int nx = nstl::min(conf_.dst_x_ - start_x, conf_.job_size_x_);
+ int x_blocking = choose_x_blocking(nx, ny, pr_nthr_per_grp);
+
+ int nxy_start{0}, nxy_end{0};
+ balance211(ny * nx / x_blocking, pr_nthr_per_grp, pr_my_id,
+ nxy_start, nxy_end);
+ if (nxy_start == nxy_end) continue;
+ nxy_start *= x_blocking;
+ nxy_end *= x_blocking;
+
+ int nxy = nxy_start;
+ if (nxy % nx != 0) {
+ int nx_step = nstl::min(nx - nxy % nx, nxy_end - nxy);
+ reduce_block(space_base, dst, j, start_y, start_x,
+ nxy / nx, nxy % nx, 1, nx_step);
+ nxy += nx_step;
+ }
+ if ((nxy_end - nxy) > nx) {
+ int ny_step = (nxy_end - nxy) / nx;
+ reduce_block(space_base, dst, j, start_y, start_x,
+ nxy / nx, nxy % nx, ny_step, nx);
+ nxy += nx * ny_step;
+ }
+ if ((nxy_end - nxy) > 0) {
+ reduce_block(space_base, dst, j, start_y, start_x,
+ nxy / nx, nxy % nx, 1, nxy_end - nxy);
+ }
+ }
+}
+
+template struct cpu_reducer_2d_t<data_type::f32>;
+template struct cpu_reducer_2d_t<data_type::s32>;
+
+/* accumulator section */
+
+template <impl::data_type_t data_type>
+cpu_accumulator_1d_t<data_type>::cpu_accumulator_1d_t(): drv_(nullptr) {
+ drv_ = create_reduce_2d_drv<data_type>(1, 0, 0, 0, false);
+}
+
+template <impl::data_type_t data_type>
+cpu_accumulator_1d_t<data_type>::~cpu_accumulator_1d_t() {
+ delete drv_;
+}
+
+template <impl::data_type_t data_type>
+void cpu_accumulator_1d_t<data_type>::accumulate(data_t *dst,
+ const data_t *src, size_t size) {
+ (*drv_)(dst, src, 1, size);
+}
+
+template struct cpu_accumulator_1d_t<data_type::f32>;
+template struct cpu_accumulator_1d_t<data_type::s32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.hpp
new file mode 100644
index 0000000000..27f5939cd2
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reducer.hpp
@@ -0,0 +1,334 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REDUCER_HPP
+#define CPU_REDUCER_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "mkldnn_types.h"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+
+#include "cpu_barrier.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+/** class to perform balancing over 3D array
+ *
+ * Conceptually the reduction happens according to the picture below:
+ *
+ * <--job_size->
+ * +-----------+ +-----------+ +-----------+ ^
+ * | | | | | | |
+ * | | | | | | |
+ * | 1 | | 2 | . . . | njobs | | reduction_size
+ * | | | | | | |
+ * | | | | | | |
+ * +-----------+ +-----------+ +-----------+ v
+ *
+ * | | | | | | | | |
+ * v v v v v v v v v
+ * ===================================================== vertical reduction
+ *
+ * +-----------+ +-----------+ . . . +-----------+ result
+ *
+ * In a simple case the result must be contiguous in memory.
+ * @class cpu_reducer_t is an implementation.
+ *
+ * Threads are divided into groups. The groups are independent of each other.
+ * Each group may work on several jobs (the distribution is not uniform, since
+ * njobs might be not a multiple of groups). Threads within a group work on
+ * different parts of the reduction dimension. Thread 0 in each group is called
+ * master (@sa reduce_balancer_t::master()).
+ *
+ * If threading driver does not allow sync between sub-group of threads (e.g.
+ * Intel(R) TBB) the # of thread per group is enforced to be 1.
+ */
+struct reduce_balancer_t {
+ reduce_balancer_t() { init(1, 1, 1, 1, 0); } /* trivial balance */
+ reduce_balancer_t(int nthr, int job_size, int njobs, int reduction_size,
+ size_t max_buffer_size)
+ { init(nthr, job_size, njobs, reduction_size, max_buffer_size); }
+
+ reduce_balancer_t &init(int nthr, int job_size, int njobs,
+ int reduction_size, size_t max_buffer_size)
+ {
+ syncable_ = mkldnn_thr_syncable();
+ nthr_ = nthr;
+ job_size_ = job_size;
+ njobs_ = njobs;
+ reduction_size_ = reduction_size;
+ max_buffer_size_ = max_buffer_size;
+ balance();
+ return *this;
+ }
+
+ bool syncable_;
+ int nthr_;
+ int job_size_, njobs_, reduction_size_;
+
+ int ngroups_; /** number of independent work (thread) groups */
+ int nthr_per_group_; /** number of threads within a single work group */
+ int njobs_per_group_ub_; /** the max # of jobs within a work group */
+
+ bool master(int ithr) const { return id_in_group(ithr) == 0; }
+ bool idle(int ithr) const { return ithr >= nthr_per_group_ * ngroups_; }
+
+ int group_id(int ithr) const { return ithr / nthr_per_group_; }
+ int id_in_group(int ithr) const { return ithr % nthr_per_group_; }
+
+ int grp_njobs(int grp) const {
+ if (grp >= ngroups_) return 0;
+ return njobs_ / ngroups_ + (grp < njobs_ % ngroups_);
+ }
+ int grp_job_off(int grp) const {
+ if (grp >= ngroups_) return njobs_;
+ return njobs_ / ngroups_ * grp + nstl::min(grp, njobs_ % ngroups_);
+ }
+
+ int ithr_njobs(int ithr) const { return grp_njobs(group_id(ithr)); }
+ int ithr_job_off(int ithr) const { return grp_job_off(group_id(ithr)); }
+
+private:
+ size_t max_buffer_size_;
+ void balance();
+};
+
+/** forward declaration of reduce driver */
+template <impl::data_type_t data_type> struct reducer_2d_driver_t;
+
+/** class to perform a reduction over 3D array
+ *
+ * Balancing is based on @class reduce_balancer_t.
+ * Restrictions: the result of the reduction must be contiguous in memory. *
+ * The reduction happens according to the picture below (once more):
+ *
+ * <--job_size->
+ * +-----------+ +-----------+ +-----------+ ^
+ * | | | | | | |
+ * | | | | | | |
+ * | 1 | | 2 | . . . | njobs | | reduction_size
+ * | | | | | | |
+ * | | | | | | |
+ * +-----------+ +-----------+ +-----------+ v
+ *
+ * | | | | | | | | |
+ * v v v v v v v v v
+ * ===================================================== vertical reduction
+ *
+ * +-----------+ +-----------+ . . . +-----------+ (contiguous) result
+ *
+ * An example how work might be shared is shown below.
+ *
+ * In this example group 0 owns 2 (independent) jobs -- 2 big squares.
+ * The number of threads per group is also 2 (thread 0 of group 0 and thread 1
+ * of group 0). Master threads (i.e. threads with id 0 in corresponding group)
+ * from each group put the partial result directly into destination memory,
+ * while all the other threads with-in the group use workspace (on the picture
+ * the only thread 1). Once intermediate results obtained each group reduces
+ * corresponding part (own jobs) to the destination memory.
+ *
+ * <------- group 0 ------->
+ *
+ * +-----------+ +-----------+ ^
+ * | | | | | thread 0 of reduces to the dest-memory
+ * | | | | | group 0 +-----------+ +-----------+
+ * |- - - - - -| |- - - - - -| X
+ * | | | | | thread 1 of reduces to workspace[tid=1]:
+ * | | | | | group 0 +-----------+ +-----------+
+ * +-----------+ +-----------+ v
+ * | | | | | |
+ * v v v v v v
+ * ((barrier)) =============================
+ *
+ * dest-memory: +-----------+ +-----------+
+ */
+template <impl::data_type_t data_type>
+struct cpu_reducer_t {
+ typedef typename prec_traits<data_type>::type data_t;
+
+ struct conf_t {
+ conf_t() = default;
+ conf_t &init(const reduce_balancer_t &balancer)
+ { balancer_ = balancer; return *this; }
+
+ void init_scratchpad(memory_tracking::registrar_t &scratchpad) const;
+
+ reduce_balancer_t balancer_;
+ };
+
+ cpu_reducer_t(const conf_t &conf);
+ ~cpu_reducer_t();
+
+ /** initializes reducer.
+ * Must be called from a single thread prior to actual usage */
+ void init(const memory_tracking::grantor_t &scratchpad) const {
+ if (balancer().nthr_per_group_ == 1) return;
+
+ auto bctx = scratchpad.template get<simple_barrier::ctx_t>(
+ memory_tracking::names::key_reducer_space_bctx);
+ for (int i = 0; i < balancer().ngroups_; ++i)
+ simple_barrier::ctx_init(&bctx[i]);
+ }
+
+ /** for given thread returns the pointer where to put partial results.
+ * Reduction destination @p dst must be provided as well (master threads
+ * from each group will use it for partial result to reduce memory
+ * pressure).
+ *
+ * @note: job offset is already applied by get_local_ptr(), which means all
+ * threads should start writing from the very beginning of returned
+ * address.
+ */
+ data_t *get_local_ptr(int ithr, data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const;
+
+ /** performs the reduction with built-in synchronization. */
+ void reduce(int ithr, data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const {
+ bool redundant_reduction = balancer().nthr_per_group_ == 1
+ || balancer().idle(ithr);
+ if (redundant_reduction) return;
+
+ auto bctx = scratchpad.template get<simple_barrier::ctx_t>(
+ memory_tracking::names::key_reducer_space_bctx);
+ simple_barrier::barrier(&bctx[balancer().group_id(ithr)],
+ balancer().nthr_per_group_);
+
+ reduce_nolock(ithr, dst, scratchpad);
+ }
+
+ const reduce_balancer_t &balancer() const { return conf_.balancer_; }
+
+private:
+ static size_t space_per_thread(const reduce_balancer_t &balancer)
+ { return balancer.njobs_per_group_ub_ * balancer.job_size_; }
+
+ /* The scratchpad is organized as follows:
+ *
+ * data_t space[nthr_][njobs_per_group_ub_][jobs_size_];
+ * simple_barrier::ctx_t barriers[groups_]; */
+
+ const conf_t conf_;
+ reducer_2d_driver_t<data_type> *drv_;
+
+ void reduce_nolock(int ithr, data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const;
+};
+
+template <impl::data_type_t data_type>
+struct cpu_reducer_2d_t {
+ typedef typename prec_traits<data_type>::type data_t;
+
+ struct conf_t {
+ conf_t() = default;
+ conf_t &init(const reduce_balancer_t &balancer, int job_size_x,
+ int job_size_y, int x_block, int dst_x, int dst_y) {
+ balancer_ = balancer;
+ job_size_x_ = job_size_x;
+ job_size_y_ = job_size_y;
+ x_block_ = x_block;
+ dst_x_ = dst_x;
+ dst_y_ = dst_y;
+ return *this;
+ }
+
+ void init_scratchpad(memory_tracking::registrar_t &scratchpad) const;
+
+ reduce_balancer_t balancer_;
+ int job_size_x_, job_size_y_, x_block_, dst_x_, dst_y_;
+ };
+
+ cpu_reducer_2d_t(const conf_t &conf);
+ ~cpu_reducer_2d_t();
+
+ /** initializes reducer.
+ * Must be called from a single thread prior to actual usage */
+ void init(const memory_tracking::grantor_t &scratchpad) const {
+ if (balancer().nthr_per_group_ == 1) return;
+
+ auto bctx = scratchpad.template get<simple_barrier::ctx_t>(
+ memory_tracking::names::key_reducer_space_bctx);
+ for (int i = 0; i < balancer().ngroups_; ++i)
+ simple_barrier::ctx_init(&bctx[i]);
+ }
+
+ /** for given thread returns the pointer where to put partial results */
+ data_t *get_local_ptr(int ithr,
+ const memory_tracking::grantor_t &scratchpad) const;
+
+ /** performs the reduction with built-in synchronization. */
+ void reduce(int ithr, data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const {
+ bool redundant_reduction = balancer().nthr_per_group_ == 1
+ || balancer().idle(ithr);
+ if (redundant_reduction) return;
+
+ auto bctx = scratchpad.template get<simple_barrier::ctx_t>(
+ memory_tracking::names::key_reducer_space_bctx);
+ simple_barrier::barrier(&bctx[balancer().group_id(ithr)],
+ balancer().nthr_per_group_);
+
+ reduce_nolock(ithr, dst, scratchpad);
+ }
+
+ const reduce_balancer_t &balancer() const { return conf_.balancer_; }
+
+private:
+ static size_t space_per_thread(const reduce_balancer_t &balancer)
+ { return balancer.njobs_per_group_ub_ * balancer.job_size_; }
+
+ /* The scratchpad is organized as follows:
+ *
+ * data_t space[nthr_][njobs_per_group_ub_][jobs_size_];
+ * simple_barrier::ctx_t barriers[groups_]; */
+
+ const conf_t conf_;
+ reducer_2d_driver_t<data_type> *drv_;
+
+ int choose_x_blocking(int nx, int ny, int nthr_per_grp) const;
+ void reduce_block(const data_t* space_base, data_t *dst,
+ int job, int start_y, int start_x,
+ int ny_start, int nx_start, int ny_step, int nx_step) const;
+ void reduce_nolock(int ithr, data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const;
+};
+
+/** simple 1d accumulator: y[:] += x[:] */
+template <impl::data_type_t data_type>
+struct cpu_accumulator_1d_t {
+ typedef typename prec_traits<data_type>::type data_t;
+
+ cpu_accumulator_1d_t();
+ ~cpu_accumulator_1d_t();
+ void accumulate(data_t *dst, const data_t *src, size_t size);
+
+ reducer_2d_driver_t<data_type> *drv_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder.cpp
new file mode 100644
index 0000000000..82be70353d
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder.cpp
@@ -0,0 +1,262 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "cpu_engine.hpp"
+#include "cpu_primitive.hpp"
+#include "cpu_reorder_pd.hpp"
+#include "cpu_memory.hpp"
+#include "type_helpers.hpp"
+
+#include "cpu/jit_uni_reorder.hpp"
+#include "cpu/simple_reorder.hpp"
+#include "cpu/wino_reorder.hpp"
+#include "cpu/rnn/rnn_reorders.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using rpd_create_f = mkldnn::impl::engine_t::reorder_primitive_desc_create_f;
+
+namespace {
+using namespace mkldnn::impl::data_type;
+using namespace mkldnn::impl::format_tag;
+
+#define REG_SR(idt, ifmt, odt, ofmt, ...) \
+ simple_reorder_t<idt, ifmt, odt, ofmt, __VA_ARGS__>::pd_t::create
+
+#define REG_SR_BIDIR(idt, ifmt, odt, ofmt) \
+ REG_SR(idt, ifmt, odt, ofmt, fmt_order::keep), \
+ REG_SR(idt, ifmt, odt, ofmt, fmt_order::reverse)
+
+#define REG_SR_DIRECT_COPY(idt, odt) \
+ REG_SR(idt, any, odt, any, fmt_order::any, spec::direct_copy), \
+ REG_SR(idt, any, odt, any, fmt_order::any, spec::direct_copy_except_dim_0)
+
+static const rpd_create_f cpu_reorder_impl_list[] = {
+ /* winograd */
+ wino_reorder_t<f32, f32>::pd_t::create,
+ //wino_reorder_t<f32, s8>::pd_t::create,
+
+ /* rnn reorders */
+ rnn_data_reorder_t<f32, u8>::pd_t::create,
+ rnn_weights_reorder_t<f32, f32>::pd_t::create,
+ rnn_weights_reorder_t<f32, s8>::pd_t::create,
+
+ /* conv reorders w/ compensation */
+ REG_SR(f32, any, s8, hwio, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(f32, any, s8, hwigo, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(s8, any, s8, hwio, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(s8, any, s8, hwigo, fmt_order::keep, spec::conv_s8s8),
+
+ REG_SR(f32, oiw, s8, OIw4i16o4i, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(f32, goiw, s8, gOIw4i16o4i, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(s8, oiw, s8, OIw4i16o4i, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(s8, goiw, s8, gOIw4i16o4i, fmt_order::keep, spec::conv_s8s8),
+
+ REG_SR(f32, oihw, s8, OIhw4i16o4i, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(f32, goihw, s8, gOIhw4i16o4i, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(s8, oihw, s8, OIhw4i16o4i, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(s8, goihw, s8, gOIhw4i16o4i, fmt_order::keep, spec::conv_s8s8),
+
+ REG_SR(f32, goihw, s8, gOIhw2i8o4i, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(s8, goihw, s8, gOIhw2i8o4i, fmt_order::keep, spec::conv_s8s8),
+
+ REG_SR(f32, goihw, s8, gOIhw4o4i, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(s8, goihw, s8, gOIhw4o4i, fmt_order::keep, spec::conv_s8s8),
+
+ REG_SR(f32, goiw, s8, Goiw16g, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(s8, goiw, s8, Goiw16g, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(f32, goihw, s8, Goihw16g, fmt_order::keep, spec::conv_s8s8),
+ REG_SR(s8, goihw, s8, Goihw16g, fmt_order::keep, spec::conv_s8s8),
+
+ /* regular reorders */
+
+#if defined(__INTEL_COMPILER) || (defined(__GNUC__) && !defined(__clang__))
+ /* Direct copy for icc which is faster than jitted code;
+ * Direct copy for gcc which might or might not be faster than jitted
+ * code, but still worth it because doesn't require jitting, i.e. much
+ * faster creation time. This is tentative solution and should be removed
+ * later (when we will cache jitted code?...). */
+ REG_SR_DIRECT_COPY(f32, f32),
+#endif
+
+#ifdef __INTEL_COMPILER
+ /* direct copy for icc, which is faster than jitted code */
+ /*
+ REG_SR_DIRECT_COPY(f32, s32),
+ REG_SR_DIRECT_COPY(f32, s8),
+ REG_SR_DIRECT_COPY(f32, u8),
+ REG_SR_DIRECT_COPY(s32, f32),
+ REG_SR_DIRECT_COPY(s32, s32),
+ REG_SR_DIRECT_COPY(s32, s8),
+ REG_SR_DIRECT_COPY(s32, u8),
+ REG_SR_DIRECT_COPY(s8, f32),
+ REG_SR_DIRECT_COPY(s8, s32),
+ REG_SR_DIRECT_COPY(s8, s8),
+ REG_SR_DIRECT_COPY(s8, u8),
+ REG_SR_DIRECT_COPY(u8, f32),
+ REG_SR_DIRECT_COPY(u8, s32),
+ REG_SR_DIRECT_COPY(u8, s8),
+ REG_SR_DIRECT_COPY(u8, u8),
+ */
+#endif
+
+ /* jit */
+ jit_uni_reorder_create,
+
+ /* fp32: flat <-> blocked with tail */
+ /*
+ REG_SR_BIDIR(f32, any, f32, nCw4c),
+ REG_SR_BIDIR(f32, any, f32, nCw8c),
+ REG_SR_BIDIR(f32, any, f32, OIw4i4o),
+ REG_SR_BIDIR(f32, any, f32, OIw8i8o),
+ REG_SR_BIDIR(f32, any, f32, OIw8o8i),
+ REG_SR_BIDIR(f32, any, f32, gOIw4i4o),
+ REG_SR_BIDIR(f32, any, f32, gOIw8i8o),
+ REG_SR_BIDIR(f32, any, f32, gOIw8o8i),
+
+ REG_SR_BIDIR(f32, any, f32, nCw16c),
+ REG_SR_BIDIR(f32, any, f32, OIw16o16i),
+ REG_SR_BIDIR(f32, any, f32, OIw16i16o),
+ REG_SR_BIDIR(f32, any, f32, IOw16o16i),
+ REG_SR_BIDIR(f32, any, f32, gOIw16o16i),
+ REG_SR_BIDIR(f32, any, f32, gOIw16i16o),
+ REG_SR_BIDIR(f32, any, f32, gIOw16o16i),
+
+ REG_SR_BIDIR(f32, any, f32, nChw4c),
+ REG_SR_BIDIR(f32, any, f32, nChw8c),
+ REG_SR_BIDIR(f32, any, f32, OIhw4i4o),
+ REG_SR_BIDIR(f32, any, f32, Ohwi8o),
+
+ REG_SR_BIDIR(f32, any, f32, OIhw8i8o),
+ REG_SR_BIDIR(f32, any, f32, OIhw8o8i),
+ REG_SR_BIDIR(f32, any, f32, gOIhw4i4o),
+ REG_SR_BIDIR(f32, any, f32, gOIhw4o4i),
+ REG_SR_BIDIR(f32, any, f32, gOhwi8o),
+ REG_SR_BIDIR(f32, any, f32, gOIhw8i8o),
+ REG_SR_BIDIR(f32, any, f32, gOIhw8o8i),
+
+ REG_SR_BIDIR(f32, any, f32, nChw16c),
+ REG_SR_BIDIR(f32, any, f32, Oihw4o),
+ REG_SR_BIDIR(f32, any, f32, Oihw16o),
+ REG_SR_BIDIR(f32, any, f32, Ohwi4o),
+ REG_SR_BIDIR(f32, any, f32, Ohwi16o),
+ REG_SR_BIDIR(f32, any, f32, OIhw16o16i),
+ REG_SR_BIDIR(f32, any, f32, OIhw16i16o),
+ REG_SR_BIDIR(f32, any, f32, IOhw16o16i),
+ REG_SR_BIDIR(f32, any, f32, gOihw4o),
+ REG_SR_BIDIR(f32, any, f32, gOihw16o),
+ REG_SR_BIDIR(f32, any, f32, gOhwi4o),
+ REG_SR_BIDIR(f32, any, f32, gOhwi16o),
+ REG_SR_BIDIR(f32, any, f32, gOIhw16o16i),
+ REG_SR_BIDIR(f32, any, f32, gOIhw16i16o),
+ REG_SR_BIDIR(f32, any, f32, gIOhw16o16i),
+
+ REG_SR_BIDIR(f32, any, f32, nCdhw4c),
+ REG_SR_BIDIR(f32, any, f32, nCdhw8c),
+ REG_SR_BIDIR(f32, any, f32, OIdhw4i4o),
+ REG_SR_BIDIR(f32, any, f32, Odhwi8o),
+ REG_SR_BIDIR(f32, any, f32, OIdhw8i8o),
+ REG_SR_BIDIR(f32, any, f32, OIdhw8o8i),
+ REG_SR_BIDIR(f32, any, f32, gOIdhw4i4o),
+ REG_SR_BIDIR(f32, any, f32, gOdhwi8o),
+ REG_SR_BIDIR(f32, any, f32, gOIdhw8i8o),
+ REG_SR_BIDIR(f32, any, f32, gOIdhw8o8i),
+
+ REG_SR_BIDIR(f32, any, f32, nCdhw16c),
+ REG_SR_BIDIR(f32, any, f32, Oidhw4o),
+ REG_SR_BIDIR(f32, any, f32, Oidhw16o),
+ REG_SR_BIDIR(f32, any, f32, Odhwi16o),
+ REG_SR_BIDIR(f32, any, f32, OIdhw16o16i),
+ REG_SR_BIDIR(f32, any, f32, OIdhw16i16o),
+ REG_SR_BIDIR(f32, any, f32, gOidhw4o),
+ REG_SR_BIDIR(f32, any, f32, gOidhw16o),
+ REG_SR_BIDIR(f32, any, f32, gOdhwi16o),
+ REG_SR_BIDIR(f32, any, f32, gOIdhw16o16i),
+ REG_SR_BIDIR(f32, any, f32, gOIdhw16i16o),
+ */
+
+ /* fp32: blocked <-> blocked with tail */
+ REG_SR_BIDIR(f32, nCw8c, f32, nCw16c),
+ REG_SR_BIDIR(f32, nChw8c, f32, nChw16c),
+ REG_SR_BIDIR(f32, nCdhw8c, f32, nCdhw16c),
+
+ /* int: flat <-> blocked with tail */
+ /*
+ REG_SR_BIDIR(f32, any, s32, nChw16c),
+ REG_SR_BIDIR(f32, any, s8, nChw16c),
+ REG_SR_BIDIR(f32, any, u8, nChw16c),
+ REG_SR_BIDIR(s32, any, f32, nChw16c),
+ REG_SR_BIDIR(s32, any, s32, nChw16c),
+ REG_SR_BIDIR(s32, any, s8, nChw16c),
+ REG_SR_BIDIR(s32, any, u8, nChw16c),
+ REG_SR_BIDIR(s8, any, f32, nChw16c),
+ REG_SR_BIDIR(s8, any, s32, nChw16c),
+ REG_SR_BIDIR(s8, any, s8, nChw16c),
+ REG_SR_BIDIR(s8, any, u8, nChw16c),
+ REG_SR_BIDIR(u8, any, f32, nChw16c),
+ REG_SR_BIDIR(u8, any, s32, nChw16c),
+ REG_SR_BIDIR(u8, any, s8, nChw16c),
+ REG_SR_BIDIR(u8, any, u8, nChw16c),
+
+ REG_SR_BIDIR(f32, any, f32, OIhw4i16o4i),
+ REG_SR_BIDIR(f32, any, s8, OIhw4i16o4i),
+ REG_SR_BIDIR(s8, any, f32, OIhw4i16o4i),
+ REG_SR_BIDIR(s8, any, s8, OIhw4i16o4i),
+ REG_SR_BIDIR(f32, any, s8, gOIhw4i16o4i),
+ REG_SR_BIDIR(s8, any, f32, gOIhw4i16o4i),
+ REG_SR_BIDIR(f32, any, f32, gOIhw4i16o4i),
+ REG_SR_BIDIR(s8, any, s8, gOIhw4i16o4i),
+ */
+
+ /* reference: the last line of defence */
+ /*
+ REG_SR(f32, any, f32, any, fmt_order::any, spec::reference),
+ REG_SR(f32, any, s32, any, fmt_order::any, spec::reference),
+ REG_SR(f32, any, s8, any, fmt_order::any, spec::reference),
+ REG_SR(f32, any, u8, any, fmt_order::any, spec::reference),
+
+ REG_SR(s32, any, f32, any, fmt_order::any, spec::reference),
+ REG_SR(s32, any, s32, any, fmt_order::any, spec::reference),
+ REG_SR(s32, any, s8, any, fmt_order::any, spec::reference),
+ REG_SR(s32, any, u8, any, fmt_order::any, spec::reference),
+
+ REG_SR(s8, any, f32, any, fmt_order::any, spec::reference),
+ REG_SR(s8, any, s32, any, fmt_order::any, spec::reference),
+ REG_SR(s8, any, s8, any, fmt_order::any, spec::reference),
+ REG_SR(s8, any, u8, any, fmt_order::any, spec::reference),
+
+ REG_SR(u8, any, f32, any, fmt_order::any, spec::reference),
+ REG_SR(u8, any, s32, any, fmt_order::any, spec::reference),
+ REG_SR(u8, any, u8, any, fmt_order::any, spec::reference),
+ REG_SR(u8, any, s8, any, fmt_order::any, spec::reference),
+ */
+
+ /* eol */
+ nullptr,
+};
+}
+
+const rpd_create_f *cpu_engine_t::get_reorder_implementation_list() const {
+ return cpu_reorder_impl_list;
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder_pd.hpp
new file mode 100644
index 0000000000..1622eb6849
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_reorder_pd.hpp
@@ -0,0 +1,48 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REORDER_PD_HPP
+#define CPU_REORDER_PD_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "reorder_pd.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_reorder_pd_t: public reorder_pd_t {
+ using reorder_pd_t::reorder_pd_t;
+
+ status_t init() {
+ const auto &post_ops = attr()->post_ops_;
+ bool args_ok = IMPLICATION(post_ops.len_ != 0, post_ops.len_ == 1
+ && post_ops.entry_[0].kind == primitive_kind::sum);
+ scratchpad_engine_ = src_engine_;
+ return args_ok ? status::success : status::unimplemented;
+ }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_shuffle_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_shuffle_pd.hpp
new file mode 100644
index 0000000000..f16587b99f
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_shuffle_pd.hpp
@@ -0,0 +1,41 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_SHUFFLE_PD_HPP
+#define CPU_SHUFFLE_PD_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "shuffle_pd.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_shuffle_pd_t: public shuffle_pd_t {
+ using shuffle_pd_t::shuffle_pd_t;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_softmax_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_softmax_pd.hpp
new file mode 100644
index 0000000000..3a39eab974
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_softmax_pd.hpp
@@ -0,0 +1,45 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_SOFTMAX_PD_HPP
+#define CPU_SOFTMAX_PD_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "softmax_pd.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_softmax_fwd_pd_t: public softmax_fwd_pd_t {
+ using softmax_fwd_pd_t::softmax_fwd_pd_t;
+};
+
+struct cpu_softmax_bwd_pd_t: public softmax_bwd_pd_t {
+ using softmax_bwd_pd_t::softmax_bwd_pd_t;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum.cpp
new file mode 100644
index 0000000000..1ab5d9f174
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum.cpp
@@ -0,0 +1,48 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "cpu_engine.hpp"
+
+/*
+#include "cpu/ref_sum.hpp"
+#include "cpu/simple_sum.hpp"
+*/
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using spd_create_f = mkldnn::impl::engine_t::sum_primitive_desc_create_f;
+
+namespace {
+#define INSTANCE(...) __VA_ARGS__::pd_t::create
+static const spd_create_f cpu_sum_impl_list[] = {
+ /*
+ INSTANCE(simple_sum_t<data_type::f32>),
+ INSTANCE(ref_sum_t),
+ */
+ nullptr,
+};
+#undef INSTANCE
+}
+
+const spd_create_f *cpu_engine_t::get_sum_implementation_list() const {
+ return cpu_sum_impl_list;
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum_pd.hpp
new file mode 100644
index 0000000000..0965129f9b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/cpu_sum_pd.hpp
@@ -0,0 +1,39 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_SUM_PD_HPP
+#define CPU_SUM_PD_HPP
+
+#include "c_types_map.hpp"
+#include "sum_pd.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_sum_pd_t: public sum_pd_t {
+ using sum_pd_t::sum_pd_t;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.cpp
new file mode 100644
index 0000000000..a9810dec28
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.cpp
@@ -0,0 +1,372 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+#include <cmath>
+
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+#include "gemm_utils_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+namespace gemm_utils {
+#define BM_NOCOPY_AVX 64
+#define BN_NOCOPY_AVX 48
+#define BK_NOCOPY_AVX 384
+#define BN_LARGE_NOCOPY_AVX 192
+#define BM_SMALL_NOCOPY_AVX 16
+#define BN_SMALL_NOCOPY_AVX 1
+#define BK_SMALL_NOCOPY_AVX 4
+// Determine number of threads for each dimension of a 3-D partitioning
+// algorithm based on input parameters
+// m/n/k - First/second/third parameter for GEMM
+// nthrs - total available number of threads
+// nthrs_m/nthrs_n/nthrs_k - number of threads to use in each dimension
+// BM/BN/BK - blocking values
+void calc_nthr_nocopy_avx(int m, int n, int k,
+ int nthrs, int *nthrs_m, int *nthrs_n, int *nthrs_k, int *BM, int *BN,
+ int *BK)
+{
+ int nthr, nthr_m, nthr_n, nthr_k;
+ int MB, NB, KB;
+
+ nthr = nthrs;
+ nthr_m = (m + BM_NOCOPY_AVX - 1) / BM_NOCOPY_AVX;
+ nthr_n = (n + BN_NOCOPY_AVX - 1) / BN_NOCOPY_AVX;
+ nthr_k = 1;
+
+ // Partition along K dimension
+ // - if threading allows having barriers (e.g. OMP)
+ // - if there is not enough parallelism along M or N
+ if (mkldnn_thr_syncable()) {
+ int nthr_other = nthr_k = 1;
+ while ((nthr_m * nthr_n * nthr_other < nthr)
+ && (k / (nthr_other + 1) > BK_NOCOPY_AVX)) {
+ nthr_other++;
+ if ((nthr / nthr_other) * nthr_other > 0.9 * nthr)
+ nthr_k = nthr_other;
+ }
+ }
+ nthr /= nthr_k;
+
+ if (nthr_m == 1)
+ nthr_n = nthr;
+ if (nthr_n == 1)
+ nthr_m = nthr;
+
+ // Simple partition reduction
+ while (nthr_m * nthr_n > nthr)
+ if (nthr_m > nthr_n)
+ nthr_m--;
+ else
+ nthr_n--;
+ while (nthr_m * nthr_n < nthr)
+ if (nthr_m < nthr_n)
+ nthr_m++;
+ else
+ nthr_n++;
+
+ if ((nthr_m * nthr_n > nthr) && (nthr_m > 1) && (nthr_n > 1)) {
+
+ if (nthr_m <= nthr_n) {
+ nthr_m = (int)sqrt((double)nthr);
+ if (nthr_m > (m + BM_SMALL_NOCOPY_AVX - 1) / BM_SMALL_NOCOPY_AVX)
+ nthr_m = (m + BM_SMALL_NOCOPY_AVX - 1) / BM_SMALL_NOCOPY_AVX;
+ nthr_n = nthr / nthr_m;
+
+ while ((nthr_m > 1) && (nthr_m * nthr_n != nthr)) {
+ nthr_m--;
+ nthr_n = nthr / nthr_m;
+ }
+ } else {
+ nthr_n = (int)sqrt((double)nthr);
+ if (nthr_n > (n + BN_SMALL_NOCOPY_AVX - 1) / BN_SMALL_NOCOPY_AVX)
+ nthr_n = (n + BN_SMALL_NOCOPY_AVX - 1) / BN_SMALL_NOCOPY_AVX;
+ nthr_m = nthr / nthr_n;
+
+ while ((nthr_n > 1) && (nthr_m * nthr_n != nthr)) {
+ nthr_n--;
+ nthr_m = nthr / nthr_n;
+ }
+ }
+ }
+
+ MB = (m + nthr_m - 1) / nthr_m + BM_SMALL_NOCOPY_AVX - 1;
+ MB -= MB % BM_SMALL_NOCOPY_AVX;
+ NB = (n + nthr_n - 1) / nthr_n + BN_SMALL_NOCOPY_AVX - 1;
+ NB -= NB % BN_SMALL_NOCOPY_AVX;
+ KB = (k + nthr_k - 1) / nthr_k + BK_SMALL_NOCOPY_AVX - 1;
+ KB -= KB % BK_SMALL_NOCOPY_AVX;
+
+ if (MB * nthr_m > m)
+ nthr_m = (m + MB - 1) / MB;
+ if (NB * nthr_n > n)
+ nthr_n = (n + NB - 1) / NB;
+ if (KB * nthr_k > k)
+ nthr_k = (k + KB - 1) / KB;
+
+ *nthrs_m = nthr_m;
+ *nthrs_n = nthr_n;
+ *nthrs_k = nthr_k;
+
+ *BM = MB;
+ *BN = NB;
+ *BK = KB;
+}
+#undef BM_NOCOPY_AVX
+#undef BN_NOCOPY_AVX
+#undef BK_NOCOPY_AVX
+#undef BN_LARGE_NOCOPY_AVX
+#undef BM_SMALL_NOCOPY_AVX
+#undef BN_SMALL_NOCOPY_AVX
+#undef BK_SMALL_NOCOPY_AVX
+
+#define BM_NOCOPY_AVX512_COMMON 32
+#define BN_NOCOPY_AVX512_COMMON 64
+#define BK_NOCOPY_AVX512_COMMON 192
+#define BN_LARGE_NOCOPY_AVX512_COMMON 192
+#define BM_SMALL_NOCOPY_AVX512_COMMON 16
+#define BN_SMALL_NOCOPY_AVX512_COMMON 1
+#define BK_SMALL_NOCOPY_AVX512_COMMON 4
+// Determine number of threads for each dimension of a 3-D partitioning
+// algorithm based on input parameters
+// m/n/k - First/second/third parameter for GEMM
+// nthrs - total available number of threads
+// nthrs_m/nthrs_n/nthrs_k - number of threads to use in each dimension
+// BM/BN/BK - blocking values
+void calc_nthr_nocopy_avx512_common(int m,
+ int n, int k, int nthrs, int *nthrs_m, int *nthrs_n, int *nthrs_k,
+ int *BM, int *BN, int *BK)
+{
+ int nthr, nthr_m, nthr_n, nthr_k = 1;
+ int MB, NB, KB;
+ nthr = nthrs;
+
+ int counter = 0;
+ float ratio_float = 1.;
+ int ratio = 1;
+ nthr = nthrs;
+ int nthr_m_gt_n;
+
+ // Partition along K dimension
+ // - if threading allows having barriers (e.g. OMP)
+ // - if there is not enough parallelism along M or N
+ if (mkldnn_thr_syncable()) {
+ if (n <= 2 * BN_NOCOPY_AVX512_COMMON &&
+ m <= 2 * BM_NOCOPY_AVX512_COMMON * nthr) {
+ nthr_k = k / BK_NOCOPY_AVX512_COMMON;
+ if (nthr_k > nthr / 4)
+ nthr_k = nthr / 4;
+ if (nthr_k < 1)
+ nthr_k = 1;
+
+ while ((nthr_k > 1) && (nthr % nthr_k)) {
+ nthr_k--;
+ }
+ nthr /= nthr_k;
+ } else {
+ nthr_k = 1;
+ }
+ }
+ nthr_m = (m + BM_NOCOPY_AVX512_COMMON - 1) / BM_NOCOPY_AVX512_COMMON;
+ nthr_n = (n + BN_NOCOPY_AVX512_COMMON - 1) / BN_NOCOPY_AVX512_COMMON;
+
+ if (nthr_m < 1)
+ nthr_m = 1;
+ if (nthr_n < 1)
+ nthr_n = 1;
+
+ nthr_m_gt_n = nthr_m > nthr_n ? 1 : 0;
+ ratio_float = (float)nthr_m / nthr_n;
+
+ if (nthr_m_gt_n)
+ ratio = (int)ratio_float;
+ else
+ ratio = (int)(1. / ratio_float);
+
+ // scale down nthr_m and nthr_n if they are too large
+ while (nthr_m * nthr_n > 4 * nthr) {
+ nthr_m /= 2;
+ nthr_n /= 2;
+ }
+
+ if (nthr_m < 1)
+ nthr_m = 1;
+ if (nthr_n < 1)
+ nthr_n = 1;
+
+ // Simple partition reduction
+ counter = 0;
+ while (nthr_m * nthr_n > nthr) {
+ if (nthr_m > nthr_n) {
+ if (counter < ratio)
+ nthr_m--;
+ else {
+ nthr_n--;
+ counter = -1;
+ }
+ } else {
+ if (counter < ratio)
+ nthr_n--;
+ else {
+ nthr_m--;
+ counter = -1;
+ }
+ }
+ counter++;
+ }
+
+ // Simple partition increment
+ counter = 0;
+ while (nthr_m * nthr_n < 0.95 * nthr) {
+ if (nthr_m > nthr_n) {
+ if (counter < ratio)
+ nthr_m++;
+ else {
+ nthr_n++;
+ counter = -1;
+ }
+ } else {
+ if (counter < ratio)
+ nthr_n++;
+ else {
+ nthr_m++;
+ counter = -1;
+ }
+ }
+ counter++;
+ }
+
+ // if nothing works out, then this should work
+ if ((nthr_m * nthr_n > nthr)) {
+
+ if (nthr_m <= nthr_n) {
+ nthr_m = (int)sqrt((double)nthr);
+ if (nthr_m > (m + BM_SMALL_NOCOPY_AVX512_COMMON - 1)
+ / BM_SMALL_NOCOPY_AVX512_COMMON)
+ nthr_m = (m + BM_SMALL_NOCOPY_AVX512_COMMON - 1)
+ / BM_SMALL_NOCOPY_AVX512_COMMON;
+ nthr_n = nthr / nthr_m;
+
+ while ((nthr_m > 1) && (nthr_m * nthr_n != nthr)) {
+ nthr_m--;
+ nthr_n = nthr / nthr_m;
+ }
+ } else {
+ nthr_n = (int)sqrt((double)nthr);
+ if (nthr_n > (n + BN_SMALL_NOCOPY_AVX512_COMMON - 1)
+ / BN_SMALL_NOCOPY_AVX512_COMMON)
+ nthr_n = (n + BN_SMALL_NOCOPY_AVX512_COMMON - 1)
+ / BN_SMALL_NOCOPY_AVX512_COMMON;
+ nthr_m = nthr / nthr_n;
+
+ while ((nthr_n > 1) && (nthr_m * nthr_n != nthr)) {
+ nthr_n--;
+ nthr_m = nthr / nthr_n;
+ }
+ }
+ }
+
+ MB = (m + nthr_m - 1) / nthr_m + BM_SMALL_NOCOPY_AVX512_COMMON - 1;
+ MB -= MB % BM_SMALL_NOCOPY_AVX512_COMMON;
+ NB = (n + nthr_n - 1) / nthr_n + BN_SMALL_NOCOPY_AVX512_COMMON - 1;
+ NB -= NB % BN_SMALL_NOCOPY_AVX512_COMMON;
+ KB = (k + nthr_k - 1) / nthr_k + BK_SMALL_NOCOPY_AVX512_COMMON - 1;
+ KB -= KB % BK_SMALL_NOCOPY_AVX512_COMMON;
+
+ if (MB * nthr_m > m)
+ nthr_m = (m + MB - 1) / MB;
+ if (NB * nthr_n > n)
+ nthr_n = (n + NB - 1) / NB;
+ if (KB * nthr_k > k)
+ nthr_k = (k + KB - 1) / KB;
+
+ *nthrs_m = nthr_m;
+ *nthrs_n = nthr_n;
+ *nthrs_k = nthr_k;
+
+ *BM = MB;
+ *BN = NB;
+ *BK = KB;
+}
+#undef BM_NOCOPY_AVX512_COMMON
+#undef BN_NOCOPY_AVX512_COMMON
+#undef BK_NOCOPY_AVX512_COMMON
+#undef BN_LARGE_NOCOPY_AVX512_COMMON
+#undef BM_SMALL_NOCOPY_AVX512_COMMON
+#undef BN_SMALL_NOCOPY_AVX512_COMMON
+#undef BK_SMALL_NOCOPY_AVX512_COMMON
+
+// Partition n values as equally as possible among nthr threads
+// and set the offset (t_offset) and number of values (t_block) for ithr
+// Assumption: 0 <= ithr < nthr
+void partition_unit_diff(
+ int ithr, int nthr, int n, int *t_offset, int *t_block)
+{
+ int band = n / nthr;
+ if (band == 0)
+ band = 1;
+ int tail = n - band * nthr;
+ if (tail < 0)
+ tail = 0;
+
+ if (ithr < tail) {
+ band++;
+ *t_offset = band * ithr;
+ *t_block = band;
+ } else {
+ *t_offset = band * ithr + tail;
+ *t_block = band;
+ }
+
+ if (*t_offset >= n) {
+ *t_offset = 0;
+ *t_block = 0;
+ }
+
+ if (*t_offset + *t_block > n) {
+ *t_block = n - *t_offset;
+ }
+}
+
+// Sum the m*n values from p_src into p_dst, assuming the two-dimensional
+// arrays have leading dimensions ld_src and ld_dst, respectively
+template<typename data_t>
+void sum_two_matrices(int m, int n,
+ data_t * __restrict p_src, dim_t ld_src,
+ data_t * __restrict p_dst, dim_t ld_dst)
+{
+ int i, j;
+ for (j = 0; j < n; j++) {
+ for (i = 0; i < m; i++) {
+ p_dst[i + j * ld_dst] += p_src[i + j * ld_src];
+ }
+ }
+}
+
+template
+void sum_two_matrices<float>(int m, int n,
+ float * __restrict p_src, dim_t ld_src,
+ float * __restrict p_dst, dim_t ld_dst);
+
+template
+void sum_two_matrices<double>(int m, int n,
+ double * __restrict p_src, dim_t ld_src,
+ double * __restrict p_dst, dim_t ld_dst);
+}
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.hpp
new file mode 100644
index 0000000000..3352298b4a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/gemm_utils_f32.hpp
@@ -0,0 +1,72 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef GEMM_UTILS_HPP
+#define GEMM_UTILS_HPP
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace gemm_utils {
+// Alias for any dimension related variable.
+typedef ptrdiff_t dim_t;
+
+template <typename T, bool isTransA, bool isTransB>
+struct gemm_traits {};
+
+template <bool isTransA, bool isTransB>
+struct gemm_traits<double, isTransA, isTransB> {
+ static constexpr int m = 8;
+ static constexpr int n = 6;
+ static constexpr int BM = 4032;
+ static constexpr int BN = isTransA ? 96 : 192;
+ static constexpr int BK = isTransB ? 96 : 512;
+};
+
+template <bool isTransA, bool isTransB>
+struct gemm_traits<float, isTransA, isTransB> {
+ static constexpr int m = 16;
+ static constexpr int n = 6;
+ static constexpr int BM = 4032;
+ static constexpr int BN = isTransA ? 96 : 48;
+ static constexpr int BK = isTransB ? 96 : 256;
+};
+
+template <typename T>
+using unroll_factor = gemm_traits<T, false, false>;
+
+template <typename data_t>
+void sum_two_matrices(int m, int n,
+ data_t * __restrict p_src, dim_t ld_src,
+ data_t * __restrict p_dst, dim_t ld_dst);
+
+void calc_nthr_nocopy_avx512_common(int m,
+ int n, int k, int nthrs, int *nthrs_m, int *nthrs_n, int *nthrs_k,
+ int *BM, int *BN, int *BK);
+
+void calc_nthr_nocopy_avx(int m, int n, int k,
+ int nthrs, int *nthrs_m, int *nthrs_n, int *nthrs_k, int *BM, int *BN,
+ int *BK);
+
+void partition_unit_diff(
+ int ithr, int nthr, int n, int *t_offset, int *t_block);
+};
+
+}
+}
+}
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.cpp
new file mode 100644
index 0000000000..d7be43e392
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.cpp
@@ -0,0 +1,2131 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <cmath>
+#include <mutex>
+
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "ref_gemm_f32.hpp"
+#include "gemm_utils_f32.hpp"
+#include "jit_avx512_common_gemm_f32.hpp"
+
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+#define CACHE_LINE_SIZE 64
+
+#define STACKSIZE get_size_of_abi_save_regs()
+#ifdef _WIN32
+#define STACK_K_CAPACITY 32
+#else
+#define STACK_K_CAPACITY 2048
+#endif
+#define SIZE 4
+#define OFFSET 128
+#define BASE_SHIFT 2
+#define SECOND_FETCH unroll_n
+#define UNROLL_M 48
+#define UNROLL_N 8
+
+namespace avx512_common_gemm_f32 {
+using namespace gemm_utils;
+
+struct xbyak_gemm : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_gemm_f32_xbyak_gemm)
+
+ xbyak_gemm(char isTransA, char isTransB, float beta, bool hasBias = false,
+ void *code_ptr = nullptr,
+ size_t code_size = 80 * Xbyak::DEFAULT_MAX_CODE_SIZE)
+ : jit_generator(code_ptr, code_size)
+ {
+ using namespace Xbyak;
+
+ enum { ver_avx512_core, ver_avx512_mic } ver =
+ mayiuse(avx512_core) ? ver_avx512_core : ver_avx512_mic;
+
+ bool isBeta0 = (beta == 0.0);
+ bool isBetaN = (!isBeta0 && beta != 1.0);
+
+ // various definitions for convenience
+ auto ARG_M = abi_param1;
+ auto ARG_N = abi_param2;
+ auto K = abi_param3;
+ auto ARG_ALPHA = abi_param4;
+#ifdef _WIN32
+ auto ARG_A = ptr[rsp + OFFSET_SHADOWSPACE + STACKSIZE];
+ auto ARG_LDA = qword[rsp + OFFSET_SHADOWSPACE +
+ sizeof(float *) + STACKSIZE];
+ const auto stackOffset = OFFSET_SHADOWSPACE +
+ sizeof(float *) + STACKSIZE;
+ auto A = rsi;
+ auto LDA = rdi;
+#else
+ auto ARG_A = r8;
+ auto ARG_LDA = r9;
+ const auto stackOffset = STACKSIZE;
+ auto A = ARG_A;
+ auto LDA = ARG_LDA;
+#endif
+ auto ARG_B = ptr[rsp + 8 + stackOffset];
+ auto ARG_LDB = ptr[rsp + 16 + stackOffset];
+ auto ARG_BETA = ptr[rsp + 24 + stackOffset];
+ auto ARG_C = ptr[rsp + 32 + stackOffset];
+ auto ARG_LDC = ptr[rsp + 40 + stackOffset];
+ auto ARG_BIAS = ptr[rsp + 48 + stackOffset];
+ auto ARG_WS = ptr[rsp + 56 + stackOffset];
+
+ auto B = r11;
+ auto LDB = rbx;
+ auto LDC = r13;
+ auto LL = rax;
+ auto AO1 = abi_param2;
+ auto BO1 = abi_param4;
+ auto BO2 = rbp;
+ auto CO1 = r14;
+ auto CO2 = r15;
+ auto LDB3 = r10;
+ auto LDA4 = abi_param1;
+ auto AA = r12;
+ auto BIAS1 = abi_param1;
+
+ auto M = qword[rsp + 0];
+ auto N = qword[rsp + 8];
+ auto FLAG = qword[rsp + 16];
+ auto I = qword[rsp + 24];
+ auto C = qword[rsp + 32];
+ auto BIAS = qword[rsp + 40];
+ auto ALPHA = qword[rsp + 48];
+ auto BETA = qword[rsp + 64];
+ auto ORIG_A = qword[rsp + 80];
+ auto ORIG_SP = qword[rsp + 120];
+
+ auto ZSTRIDE = zmm4;
+ auto VALPHA = zmm6;
+ auto VBETA = zmm7;
+ auto VBIAS1 = zmm1;
+ auto VBIAS2 = zmm2;
+ auto VBIAS3 = zmm3;
+
+ auto PREFETCHSIZEA = ver == ver_avx512_core ? 48 : 80;
+ auto PREFETCHSIZEB = 16;
+
+ Zmm regs[] = { zmm8, zmm9, zmm10, zmm11, zmm12, zmm13, zmm14, zmm15,
+ zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23, zmm24,
+ zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31 };
+
+ // Function for packing if needed
+ auto do_pack = [&](int unroll_m) {
+ Label pack2, pack3, pack4, pack10;
+
+ mov(BO1, A);
+ lea(AO1, ptr[rsp + 128 + OFFSET * SIZE]);
+ mov(LL, K);
+ sar(LL, 2);
+ jle(pack3, T_NEAR);
+ align(16);
+
+ L(pack2);
+ if (!isTransA) {
+ for (int i = 0; i < 4; i++) {
+ vmovups(zmm0 | k1, ptr[BO1 + (0 * 16 - OFFSET) * SIZE]);
+ if (unroll_m > 16)
+ vmovups(zmm1 | k2, ptr[BO1 + (1 * 16 - OFFSET) * SIZE]);
+ if (unroll_m > 32)
+ vmovups(zmm2 | k3, ptr[BO1 + (2 * 16 - OFFSET) * SIZE]);
+ add(BO1, LDA);
+
+ vmovups(ptr[AO1 + (unroll_m * i + 0 * 16 - OFFSET) * SIZE]
+ | k1,
+ zmm0);
+ if (unroll_m > 16)
+ vmovups(ptr[AO1
+ + (unroll_m * i + 1 * 16 - OFFSET)
+ * SIZE]
+ | k2,
+ zmm1);
+ if (unroll_m > 32)
+ vmovups(ptr[AO1
+ + (unroll_m * i + 2 * 16 - OFFSET)
+ * SIZE]
+ | k3,
+ zmm2);
+ }
+ } else {
+ for (int i = 0; i < 4; i++) {
+ kmovw(k4, k1);
+ vgatherqps(ymm5 | k4,
+ ptr[BO1 + ZSTRIDE + (i - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO1 + LDA * 8]);
+ kshiftrw(k4, k1, 8);
+ vgatherqps(ymm6 | k4,
+ ptr[BO2 + ZSTRIDE + (i - OFFSET) * SIZE]);
+ vshuff64x2(zmm0, zmm5, zmm6, 0x44);
+
+ if (unroll_m > 16) {
+ lea(BO2, ptr[BO2 + LDA * 8]);
+ kmovw(k4, k2);
+ vgatherqps(ymm5 | k4,
+ ptr[BO2 + ZSTRIDE + (i - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 8]);
+ kshiftrw(k4, k2, 8);
+ vgatherqps(ymm6 | k4,
+ ptr[BO2 + ZSTRIDE + (i - OFFSET) * SIZE]);
+ vshuff64x2(zmm1, zmm5, zmm6, 0x44);
+ }
+
+ if (unroll_m > 32) {
+ lea(BO2, ptr[BO2 + LDA * 8]);
+ kmovw(k4, k3);
+ vgatherqps(ymm5 | k4,
+ ptr[BO2 + ZSTRIDE + (i - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 8]);
+ kshiftrw(k4, k3, 8);
+ vgatherqps(ymm6 | k4,
+ ptr[BO2 + ZSTRIDE + (i - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 8]);
+ vshuff64x2(zmm2, zmm5, zmm6, 0x44);
+ }
+
+ vmovups(ptr[AO1 + (unroll_m * i + 0 * 16 - OFFSET) * SIZE],
+ zmm0 | k1);
+ if (unroll_m > 16)
+ vmovups(ptr[AO1
+ + (unroll_m * i + 1 * 16 - OFFSET)
+ * SIZE],
+ zmm1 | k2);
+ if (unroll_m > 32)
+ vmovups(ptr[AO1
+ + (unroll_m * i + 2 * 16 - OFFSET)
+ * SIZE],
+ zmm2 | k3);
+ }
+ add(BO1, 4 * SIZE);
+ }
+ add(AO1, unroll_m * 4 * SIZE);
+
+ sub(LL, 1);
+ jg(pack2, T_NEAR);
+ align(16);
+
+ L(pack3);
+ mov(LL, K);
+ and_(LL, 3);
+ jle(pack10, T_NEAR);
+ align(16);
+
+ L(pack4);
+ if (!isTransA) {
+ vmovups(zmm0 | k1, ptr[BO1 + (0 * 16 - OFFSET) * SIZE]);
+ if (unroll_m > 16)
+ vmovups(zmm1 | k2, ptr[BO1 + (1 * 16 - OFFSET) * SIZE]);
+ if (unroll_m > 32)
+ vmovups(zmm2 | k3, ptr[BO1 + (2 * 16 - OFFSET) * SIZE]);
+ add(BO1, LDA);
+ } else {
+ kmovw(k4, k1);
+ vgatherqps(ymm5 | k4, ptr[BO1 + ZSTRIDE + (0 - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO1 + LDA * 8]);
+ kshiftrw(k4, k1, 8);
+ vgatherqps(ymm6 | k4, ptr[BO2 + ZSTRIDE + (0 - OFFSET) * SIZE]);
+ vshuff64x2(zmm0, zmm5, zmm6, 0x44);
+
+ if (unroll_m > 16) {
+ lea(BO2, ptr[BO2 + LDA * 8]);
+ kmovw(k4, k2);
+ vgatherqps(ymm5 | k4,
+ ptr[BO2 + ZSTRIDE + (0 - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 8]);
+ kshiftrw(k4, k2, 8);
+ vgatherqps(ymm6 | k4,
+ ptr[BO2 + ZSTRIDE + (0 - OFFSET) * SIZE]);
+ vshuff64x2(zmm1, zmm5, zmm6, 0x44);
+ }
+
+ if (unroll_m > 32) {
+ lea(BO2, ptr[BO2 + LDA * 8]);
+ kmovw(k4, k3);
+ vgatherqps(ymm5 | k4,
+ ptr[BO2 + ZSTRIDE + (0 - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 8]);
+ kshiftrw(k4, k3, 8);
+ vgatherqps(ymm6 | k4,
+ ptr[BO2 + ZSTRIDE + (0 - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 8]);
+ vshuff64x2(zmm2, zmm5, zmm6, 0x44);
+ }
+ add(BO1, SIZE);
+ }
+
+ vmovups(ptr[AO1 + (unroll_m * 0 + 0 * 16 - OFFSET) * SIZE],
+ zmm0 | k1);
+ if (unroll_m > 16)
+ vmovups(ptr[AO1 + (unroll_m * 0 + 1 * 16 - OFFSET) * SIZE],
+ zmm1 | k2);
+ if (unroll_m > 32)
+ vmovups(ptr[AO1 + (unroll_m * 0 + 2 * 16 - OFFSET) * SIZE],
+ zmm2 | k3);
+
+ add(AO1, unroll_m * SIZE);
+ sub(LL, 1);
+ jg(pack4, T_NEAR);
+ align(16);
+
+ L(pack10);
+ };
+
+ // Function to update C, covering masking and other considerations
+ auto update = [&](Zmm reg, bool useCO1, int offset, int mask,
+ bool useScale = false) {
+ vmulps(reg, reg, VALPHA);
+ if (!isBeta0) {
+ if (!useScale) {
+ switch (mask) {
+ case 0:
+ if (useCO1)
+ vmovups(zmm0, ptr[CO1 + offset * SIZE]);
+ else
+ vmovups(zmm0, ptr[CO2 + offset * SIZE]);
+ break;
+ case 1:
+ if (useCO1)
+ vmovups(zmm0 | k1 | T_z, ptr[CO1 + offset * SIZE]);
+ else
+ vmovups(zmm0 | k1 | T_z, ptr[CO2 + offset * SIZE]);
+ break;
+ case 2:
+ if (useCO1)
+ vmovups(zmm0 | k2 | T_z, ptr[CO1 + offset * SIZE]);
+ else
+ vmovups(zmm0 | k2 | T_z, ptr[CO2 + offset * SIZE]);
+ break;
+ case 3:
+ if (useCO1)
+ vmovups(zmm0 | k3 | T_z, ptr[CO1 + offset * SIZE]);
+ else
+ vmovups(zmm0 | k3 | T_z, ptr[CO2 + offset * SIZE]);
+ break;
+ }
+ } else {
+ switch (mask) {
+ case 0:
+ if (useCO1)
+ vmovups(zmm0, ptr[CO1 + LDC + offset * SIZE]);
+ else
+ vmovups(zmm0, ptr[CO2 + LDC + offset * SIZE]);
+ break;
+ case 1:
+ if (useCO1)
+ vmovups(zmm0 | k1 | T_z,
+ ptr[CO1 + LDC + offset * SIZE]);
+ else
+ vmovups(zmm0 | k1 | T_z,
+ ptr[CO2 + LDC + offset * SIZE]);
+ break;
+ case 2:
+ if (useCO1)
+ vmovups(zmm0 | k2 | T_z,
+ ptr[CO1 + LDC + offset * SIZE]);
+ else
+ vmovups(zmm0 | k2 | T_z,
+ ptr[CO2 + LDC + offset * SIZE]);
+ break;
+ case 3:
+ if (useCO1)
+ vmovups(zmm0 | k3 | T_z,
+ ptr[CO1 + LDC + offset * SIZE]);
+ else
+ vmovups(zmm0 | k3 | T_z,
+ ptr[CO2 + LDC + offset * SIZE]);
+ break;
+ }
+ }
+ if (!isBetaN) {
+ vaddps(zmm0, reg, zmm0);
+ } else {
+ vfmadd132ps(zmm0, reg, VBETA);
+ }
+ if (!useScale) {
+ switch (mask) {
+ case 0:
+ if (useCO1)
+ vmovups(ptr[CO1 + offset * SIZE], zmm0);
+ else
+ vmovups(ptr[CO2 + offset * SIZE], zmm0);
+ break;
+ case 1:
+ if (useCO1)
+ vmovups(ptr[CO1 + offset * SIZE], zmm0 | k1);
+ else
+ vmovups(ptr[CO2 + offset * SIZE], zmm0 | k1);
+ break;
+ case 2:
+ if (useCO1)
+ vmovups(ptr[CO1 + offset * SIZE], zmm0 | k2);
+ else
+ vmovups(ptr[CO2 + offset * SIZE], zmm0 | k2);
+ break;
+ case 3:
+ if (useCO1)
+ vmovups(ptr[CO1 + offset * SIZE], zmm0 | k3);
+ else
+ vmovups(ptr[CO2 + offset * SIZE], zmm0 | k3);
+ break;
+ }
+ } else {
+ switch (mask) {
+ case 0:
+ if (useCO1)
+ vmovups(ptr[CO1 + LDC + offset * SIZE], zmm0);
+ else
+ vmovups(ptr[CO2 + LDC + offset * SIZE], zmm0);
+ break;
+ case 1:
+ if (useCO1)
+ vmovups(ptr[CO1 + LDC + offset * SIZE], zmm0 | k1);
+ else
+ vmovups(ptr[CO2 + LDC + offset * SIZE], zmm0 | k1);
+ break;
+ case 2:
+ if (useCO1)
+ vmovups(ptr[CO1 + LDC + offset * SIZE], zmm0 | k2);
+ else
+ vmovups(ptr[CO2 + LDC + offset * SIZE], zmm0 | k2);
+ break;
+ case 3:
+ if (useCO1)
+ vmovups(ptr[CO1 + LDC + offset * SIZE], zmm0 | k3);
+ else
+ vmovups(ptr[CO2 + LDC + offset * SIZE], zmm0 | k3);
+ break;
+ }
+ }
+ } else {
+ if (!useScale) {
+ switch (mask) {
+ case 0:
+ if (useCO1)
+ vmovups(ptr[CO1 + offset * SIZE], reg);
+ else
+ vmovups(ptr[CO2 + offset * SIZE], reg);
+ break;
+ case 1:
+ if (useCO1)
+ vmovups(ptr[CO1 + offset * SIZE], reg | k1);
+ else
+ vmovups(ptr[CO2 + offset * SIZE], reg | k1);
+ break;
+ case 2:
+ if (useCO1)
+ vmovups(ptr[CO1 + offset * SIZE], reg | k2);
+ else
+ vmovups(ptr[CO2 + offset * SIZE], reg | k2);
+ break;
+ case 3:
+ if (useCO1)
+ vmovups(ptr[CO1 + offset * SIZE], reg | k3);
+ else
+ vmovups(ptr[CO2 + offset * SIZE], reg | k3);
+ break;
+ }
+ } else {
+ switch (mask) {
+ case 0:
+ if (useCO1)
+ vmovups(ptr[CO1 + LDC + offset * SIZE], reg);
+ else
+ vmovups(ptr[CO2 + LDC + offset * SIZE], reg);
+ break;
+ case 1:
+ if (useCO1)
+ vmovups(ptr[CO1 + LDC + offset * SIZE], reg | k1);
+ else
+ vmovups(ptr[CO2 + LDC + offset * SIZE], reg | k1);
+ break;
+ case 2:
+ if (useCO1)
+ vmovups(ptr[CO1 + LDC + offset * SIZE], reg | k2);
+ else
+ vmovups(ptr[CO2 + LDC + offset * SIZE], reg | k2);
+ break;
+ case 3:
+ if (useCO1)
+ vmovups(ptr[CO1 + LDC + offset * SIZE], reg | k3);
+ else
+ vmovups(ptr[CO2 + LDC + offset * SIZE], reg | k3);
+ break;
+ }
+ }
+ }
+ vpxorq(reg, reg, reg);
+ };
+
+ // Loop with unroll_n - 2 FMAs; called by innerkernel
+ auto fmaloop = [&](int unroll_m, int unroll_n, int iteration) {
+ for (int i = 2; i < unroll_n; i++) {
+ if (ver == ver_avx512_core) {
+ if (!isTransB) {
+ switch (i) {
+ case 2:
+ vbroadcastss(
+ zmm3,
+ ptr[BO1 + LDB * 2
+ + (iteration - OFFSET) * SIZE]);
+ break;
+ case 3:
+ vbroadcastss(
+ zmm3,
+ ptr[BO1 + LDB3
+ + (iteration - OFFSET) * SIZE]);
+ break;
+ case 4:
+ vbroadcastss(zmm3,
+ ptr[BO2 + (iteration - OFFSET) * SIZE]);
+ break;
+ case 5:
+ vbroadcastss(
+ zmm3,
+ ptr[BO2 + LDB * 1
+ + (iteration - OFFSET) * SIZE]);
+ break;
+ case 6:
+ vbroadcastss(
+ zmm3,
+ ptr[BO2 + LDB * 2
+ + (iteration - OFFSET) * SIZE]);
+ break;
+ case 7:
+ vbroadcastss(
+ zmm3,
+ ptr[BO2 + LDB3
+ + (iteration - OFFSET) * SIZE]);
+ break;
+ }
+ } else {
+ vbroadcastss(zmm3, ptr[BO1 + (i - OFFSET) * SIZE]);
+ }
+ vfmadd231ps(regs[i], zmm3, zmm0);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[i + 8], zmm3, zmm1);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[i + 16], zmm3, zmm2);
+ } else {
+ if (!isTransB) {
+ switch (i) {
+ case 2:
+ vfmadd231ps(regs[i], zmm0,
+ zword_b[BO1 + LDB * 2
+ + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[i + 8], zmm1,
+ zword_b[BO1 + LDB * 2
+ + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[i + 16], zmm2,
+ zword_b[BO1 + LDB * 2
+ + (iteration - OFFSET) * SIZE]);
+ break;
+ case 3:
+ vfmadd231ps(regs[i], zmm0,
+ zword_b[BO1 + LDB3
+ + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[i + 8], zmm1,
+ zword_b[BO1 + LDB3
+ + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[i + 16], zmm2,
+ zword_b[BO1 + LDB3
+ + (iteration - OFFSET) * SIZE]);
+ break;
+ case 4:
+ vfmadd231ps(regs[i], zmm0,
+ zword_b[BO2 + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[i + 8], zmm1,
+ zword_b[BO2 + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[i + 16], zmm2,
+ zword_b[BO2 + (iteration - OFFSET) * SIZE]);
+ break;
+ case 5:
+ vfmadd231ps(regs[i], zmm0,
+ zword_b[BO2 + LDB * 1
+ + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[i + 8], zmm1,
+ zword_b[BO2 + LDB * 1
+ + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[i + 16], zmm2,
+ zword_b[BO2 + LDB * 1
+ + (iteration - OFFSET) * SIZE]);
+ break;
+ case 6:
+ vfmadd231ps(regs[i], zmm0,
+ zword_b[BO2 + LDB * 2
+ + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[i + 8], zmm1,
+ zword_b[BO2 + LDB * 2
+ + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[i + 16], zmm2,
+ zword_b[BO2 + LDB * 2
+ + (iteration - OFFSET) * SIZE]);
+ break;
+ case 7:
+ vfmadd231ps(regs[i], zmm0,
+ zword_b[BO2 + LDB3
+ + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[i + 8], zmm1,
+ zword_b[BO2 + LDB3
+ + (iteration - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[i + 16], zmm2,
+ zword_b[BO2 + LDB3
+ + (iteration - OFFSET) * SIZE]);
+ break;
+ }
+ } else {
+ vfmadd231ps(
+ regs[i], zmm0, zword_b[BO1 + (i - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[i + 8], zmm1,
+ zword_b[BO1 + (i - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[i + 16], zmm2,
+ zword_b[BO1 + (i - OFFSET) * SIZE]);
+ }
+ }
+ }
+ };
+
+ // Innerkernel; called by kernel
+ auto innerkernel = [&](int unroll_m, int unroll_n, bool isDirect,
+ bool isCopy, bool doCPrefetch, bool isUnmasked = true) {
+ for (int i = 0; i < 8; i++) {
+ if (!isDirect) {
+ prefetcht0(ptr[AO1
+ + (PREFETCHSIZEA + i * unroll_m + 0 * 16 - OFFSET)
+ * SIZE]);
+ if (unroll_m >= 32)
+ prefetcht0(ptr[AO1
+ + (PREFETCHSIZEA + i * unroll_m + 1 * 16 - OFFSET)
+ * SIZE]);
+ if (unroll_m >= 48)
+ prefetcht0(ptr[AO1
+ + (PREFETCHSIZEA + i * unroll_m + 2 * 16 - OFFSET)
+ * SIZE]);
+ } else {
+ prefetcht0(ptr[AO1 + LDA4 + (16 * 0 * SIZE)]);
+ if (unroll_m >= 32)
+ prefetcht0(ptr[AO1 + LDA4 + (16 * 1 * SIZE)]);
+ if (unroll_m >= 48)
+ prefetcht0(ptr[AO1 + LDA4 + (16 * 2 * SIZE)]);
+ }
+
+ if (!isDirect) {
+ if (i != 0) {
+ if (isUnmasked || unroll_m > 16) {
+ vmovups(zmm0,
+ ptr[AO1
+ + (unroll_m * i + 0 * 16 - OFFSET)
+ * SIZE]);
+ } else {
+ vmovups(zmm0 | k1 | T_z,
+ ptr[AO1
+ + (unroll_m * i + 0 * 16 - OFFSET)
+ * SIZE]);
+ }
+ if (unroll_m >= 32) {
+ if (isUnmasked || unroll_m > 32) {
+ vmovups(zmm1, ptr[AO1
+ + (unroll_m * i + 1 * 16
+ - OFFSET)
+ * SIZE]);
+ } else {
+ vmovups(zmm1 | k2 | T_z,
+ ptr[AO1
+ + (unroll_m * i + 1 * 16
+ - OFFSET)
+ * SIZE]);
+ }
+ }
+ if (unroll_m >= 48) {
+ if (isUnmasked) {
+ vmovups(zmm2, ptr[AO1
+ + (unroll_m * i + 2 * 16
+ - OFFSET)
+ * SIZE]);
+ } else {
+ vmovups(zmm2 | k3 | T_z,
+ ptr[AO1
+ + (unroll_m * i + 2 * 16
+ - OFFSET)
+ * SIZE]);
+ }
+ }
+ }
+ } else {
+ if (isUnmasked || unroll_m > 16) {
+ vmovups(zmm0, ptr[AO1 + (0 * 16 - OFFSET) * SIZE]);
+ } else {
+ vmovups(zmm0 | k1 | T_z,
+ ptr[AO1 + (0 * 16 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 32) {
+ if (isUnmasked || unroll_m > 32) {
+ vmovups(zmm1, ptr[AO1 + (1 * 16 - OFFSET) * SIZE]);
+ } else {
+ vmovups(zmm1 | k2 | T_z,
+ ptr[AO1 + (1 * 16 - OFFSET) * SIZE]);
+ }
+ }
+ if (unroll_m >= 48) {
+ if (isUnmasked) {
+ vmovups(zmm2, ptr[AO1 + (2 * 16 - OFFSET) * SIZE]);
+ } else {
+ vmovups(zmm2 | k3 | T_z,
+ ptr[AO1 + (2 * 16 - OFFSET) * SIZE]);
+ }
+ }
+ add(AO1, LDA);
+ }
+
+ if (ver == ver_avx512_core) {
+ if (!isTransB) {
+ vbroadcastss(zmm3, ptr[BO1 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(zmm3, ptr[BO1 + (0 - OFFSET) * SIZE]);
+ }
+ vfmadd231ps(regs[0], zmm3, zmm0);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[0 + 8], zmm3, zmm1);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[0 + 16], zmm3, zmm2);
+ } else {
+ if (!isTransB) {
+ vfmadd231ps(regs[0], zmm0,
+ zword_b[BO1 + (i - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[0 + 8], zmm1,
+ zword_b[BO1 + (i - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[0 + 16], zmm2,
+ zword_b[BO1 + (i - OFFSET) * SIZE]);
+ } else {
+ vfmadd231ps(regs[0], zmm0,
+ zword_b[BO1 + (0 - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[0 + 8], zmm1,
+ zword_b[BO1 + (0 - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[0 + 16], zmm2,
+ zword_b[BO1 + (0 - OFFSET) * SIZE]);
+ }
+ }
+
+ if (unroll_n >= i + 1) {
+ if (!isTransB) {
+ switch (i) {
+ case 0:
+ prefetcht0(
+ ptr[BO1 + (PREFETCHSIZEB - OFFSET) * SIZE]);
+ break;
+ case 1:
+ prefetcht0(ptr[BO1 + LDB
+ + (PREFETCHSIZEB - OFFSET) * SIZE]);
+ break;
+ case 2:
+ prefetcht0(ptr[BO1 + LDB * 2
+ + (PREFETCHSIZEB - OFFSET) * SIZE]);
+ break;
+ case 3:
+ prefetcht0(ptr[BO1 + LDB3
+ + (PREFETCHSIZEB - OFFSET) * SIZE]);
+ break;
+ case 4:
+ prefetcht0(
+ ptr[BO2 + (PREFETCHSIZEB - OFFSET) * SIZE]);
+ break;
+ case 5:
+ prefetcht0(ptr[BO2 + LDB
+ + (PREFETCHSIZEB - OFFSET) * SIZE]);
+ break;
+ case 6:
+ prefetcht0(ptr[BO2 + LDB * 2
+ + (PREFETCHSIZEB - OFFSET) * SIZE]);
+ break;
+ case 7:
+ prefetcht0(ptr[BO2 + LDB3
+ + (PREFETCHSIZEB - OFFSET) * SIZE]);
+ break;
+ }
+ }
+ }
+
+ if (unroll_n >= 2) {
+ if (ver == ver_avx512_core) {
+ if (!isTransB) {
+ vbroadcastss(zmm3,
+ ptr[BO1 + LDB * 1 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(zmm3, ptr[BO1 + (1 - OFFSET) * SIZE]);
+ }
+ vfmadd231ps(regs[1], zmm3, zmm0);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[1 + 8], zmm3, zmm1);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[1 + 16], zmm3, zmm2);
+ } else {
+ if (!isTransB) {
+ vfmadd231ps(regs[1], zmm0,
+ zword_b[BO1 + LDB * 1 + (i - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[1 + 8], zmm1,
+ zword_b[BO1 + LDB * 1
+ + (i - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[1 + 16], zmm2,
+ zword_b[BO1 + LDB * 1
+ + (i - OFFSET) * SIZE]);
+ } else {
+ vfmadd231ps(regs[1], zmm0,
+ zword_b[BO1 + (1 - OFFSET) * SIZE]);
+ if (unroll_m >= 32)
+ vfmadd231ps(regs[1 + 8], zmm1,
+ zword_b[BO1 + (1 - OFFSET) * SIZE]);
+ if (unroll_m >= 48)
+ vfmadd231ps(regs[1 + 16], zmm2,
+ zword_b[BO1 + (1 - OFFSET) * SIZE]);
+ }
+ }
+ }
+
+ if (isCopy) {
+ if (isUnmasked || unroll_m > 16) {
+ vmovups(ptr[LDA4
+ + (unroll_m * i + 0 * 16 - OFFSET)
+ * SIZE],
+ zmm0);
+ } else {
+ vmovups(ptr[LDA4
+ + (unroll_m * i + 0 * 16 - OFFSET)
+ * SIZE],
+ zmm0 | k1);
+ }
+ if (unroll_m >= 32) {
+ if (isUnmasked || unroll_m > 32) {
+ vmovups(ptr[LDA4
+ + (unroll_m * i + 1 * 16 - OFFSET)
+ * SIZE],
+ zmm1);
+ } else {
+ vmovups(ptr[LDA4
+ + (unroll_m * i + 1 * 16 - OFFSET)
+ * SIZE],
+ zmm1 | k2);
+ }
+ }
+ if (unroll_m >= 48) {
+ if (isUnmasked) {
+ vmovups(ptr[LDA4
+ + (unroll_m * i + 2 * 16 - OFFSET)
+ * SIZE],
+ zmm2);
+ } else {
+ vmovups(ptr[LDA4
+ + (unroll_m * i + 2 * 16 - OFFSET)
+ * SIZE],
+ zmm2 | k3);
+ }
+ }
+ if (i == 7)
+ sub(LDA4, -unroll_m * 8 * SIZE);
+ }
+ fmaloop(unroll_m, unroll_n, i);
+
+ if (i == 1) {
+ if (doCPrefetch) {
+ if (ver == ver_avx512_core)
+ prefetchw(ptr[CO2 + 0 * 16 * SIZE]);
+ else
+ prefetcht0(ptr[CO2 + 0 * 16 * SIZE]);
+ }
+ }
+ if (i == 3) {
+ if (doCPrefetch && unroll_m >= 32) {
+ if (ver == ver_avx512_core)
+ prefetchw(ptr[CO2 + 1 * 16 * SIZE]);
+ else
+ prefetcht0(ptr[CO2 + 1 * 16 * SIZE]);
+ }
+ if (!isTransA) {
+ if (ver == ver_avx512_core)
+ prefetcht0(ptr[AA + 16 * 0 * SIZE]);
+ else
+ prefetcht2(ptr[AA + 16 * 0 * SIZE]);
+ }
+ }
+ if (i == 5) {
+ if (doCPrefetch) {
+ if (unroll_m >= 48) {
+ if (ver == ver_avx512_core)
+ prefetchw(ptr[CO2 + 2 * 16 * SIZE]);
+ else
+ prefetcht0(ptr[CO2 + 2 * 16 * SIZE]);
+ }
+ add(CO2, LDC);
+ }
+ if (!isTransA) {
+ if (unroll_m >= 32) {
+ if (ver == ver_avx512_core)
+ prefetcht0(ptr[AA + 16 * 1 * SIZE]);
+ else
+ prefetcht2(ptr[AA + 16 * 1 * SIZE]);
+ }
+ }
+ }
+
+ if (isTransB) {
+ prefetcht0(ptr[BO1 + BO2]);
+ add(BO1, LDB);
+ }
+ } // end of for loop
+
+ if (!isTransB) {
+ sub(BO1, -8 * SIZE);
+ if (unroll_n >= 4)
+ sub(BO2, -8 * SIZE);
+ }
+ if (!isTransA) {
+ if (unroll_m >= 48) {
+ if (ver == ver_avx512_core)
+ prefetcht0(ptr[AA + 16 * 2 * SIZE]);
+ else
+ prefetcht2(ptr[AA + 16 * 2 * SIZE]);
+ }
+ lea(AA, ptr[AA + LDA]);
+ }
+
+ if (!isDirect) {
+ if (isUnmasked || unroll_m > 16) {
+ vmovups(zmm0,
+ ptr[AO1 + (unroll_m * 8 + 0 * 16 - OFFSET) * SIZE]);
+ } else {
+ vmovups(zmm0 | k1 | T_z,
+ ptr[AO1 + (unroll_m * 8 + 0 * 16 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 32) {
+ if (isUnmasked || unroll_m > 32) {
+ vmovups(zmm1, ptr[AO1
+ + (unroll_m * 8 + 1 * 16 - OFFSET)
+ * SIZE]);
+ } else {
+ vmovups(zmm1 | k2 | T_z,
+ ptr[AO1
+ + (unroll_m * 8 + 1 * 16 - OFFSET)
+ * SIZE]);
+ }
+ }
+ if (unroll_m >= 48) {
+ if (isUnmasked) {
+ vmovups(zmm2, ptr[AO1
+ + (unroll_m * 8 + 2 * 16 - OFFSET)
+ * SIZE]);
+ } else {
+ vmovups(zmm2 | k3 | T_z,
+ ptr[AO1
+ + (unroll_m * 8 + 2 * 16 - OFFSET)
+ * SIZE]);
+ }
+ }
+ sub(AO1, -unroll_m * 8 * SIZE);
+ }
+
+ sub(LL, 1);
+ };
+
+ // Main kernel; does prefetching and calls innerkernel
+ // After calculating results in registers, writes back to C matrix by
+ // calling update
+ auto kernel = [&](int unroll_m, int unroll_n, bool isDirect,
+ bool isCopy, bool isUnmasked = true) {
+ if (!isDirect) {
+ lea(AO1, ptr[rsp + 128 + OFFSET * SIZE]);
+ } else {
+ mov(AO1, A);
+ }
+
+ if (isCopy) {
+ lea(LDA4, ptr[rsp + 128 + OFFSET * SIZE]);
+ } else {
+ auto step = ver == ver_avx512_core ? 2 : 4;
+ lea(LDA4, ptr[LDA * step + (16 - 1 - OFFSET) * SIZE]);
+ }
+
+ if (isTransB) {
+ lea(BO2, ptr[LDB * 4 + (16 / 2 - 1 - OFFSET) * SIZE]);
+ }
+
+ if (!isDirect) {
+ if (isUnmasked || unroll_m > 16) {
+ vmovups(zmm0,
+ ptr[AO1 + (unroll_m * 0 + 0 * 16 - OFFSET) * SIZE]);
+ } else {
+ vmovups(zmm0 | k1 | T_z,
+ ptr[AO1 + (unroll_m * 0 + 0 * 16 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 32) {
+ if (isUnmasked || unroll_m > 32) {
+ vmovups(zmm1, ptr[AO1
+ + (unroll_m * 0 + 1 * 16 - OFFSET)
+ * SIZE]);
+ } else {
+ vmovups(zmm1 | k2 | T_z,
+ ptr[AO1
+ + (unroll_m * 0 + 1 * 16 - OFFSET)
+ * SIZE]);
+ }
+ }
+ if (unroll_m >= 48) {
+ if (isUnmasked) {
+ vmovups(zmm2, ptr[AO1
+ + (unroll_m * 0 + 2 * 16 - OFFSET)
+ * SIZE]);
+ } else {
+ vmovups(zmm2 | k3 | T_z,
+ ptr[AO1
+ + (unroll_m * 0 + 2 * 16 - OFFSET)
+ * SIZE]);
+ }
+ }
+ }
+
+ Label kernel12, kernel13, kernel14, kernel15, kernel16, kernel18;
+
+ mov(LL, K);
+ sar(LL, 3);
+ sub(LL, SECOND_FETCH);
+ jle(kernel13, T_NEAR);
+ align(16);
+
+ L(kernel12);
+ innerkernel(
+ unroll_m, unroll_n, isDirect, isCopy, false, isUnmasked);
+ jg(kernel12, T_NEAR);
+ align(16);
+
+ L(kernel13);
+ lea(CO2, ptr[CO1 + (16 - 1) * SIZE]);
+ add(LL, unroll_n);
+ jle(kernel15, T_NEAR);
+ align(16);
+
+ L(kernel14);
+ innerkernel(unroll_m, unroll_n, isDirect, isCopy, true, isUnmasked);
+ jg(kernel14, T_NEAR);
+ align(16);
+
+ L(kernel15);
+ mov(LL, K);
+ and_(LL, 7);
+ jle(kernel18, T_NEAR);
+ align(16);
+
+ L(kernel16);
+ if (isDirect) {
+ if (isUnmasked || unroll_m > 16) {
+ vmovups(zmm0, ptr[AO1 + (0 * 16 - OFFSET) * SIZE]);
+ } else {
+ vmovups(zmm0 | k1 | T_z,
+ ptr[AO1 + (0 * 16 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 32) {
+ if (isUnmasked || unroll_m > 32) {
+ vmovups(zmm1, ptr[AO1 + (1 * 16 - OFFSET) * SIZE]);
+ } else {
+ vmovups(zmm1 | k2 | T_z,
+ ptr[AO1 + (1 * 16 - OFFSET) * SIZE]);
+ }
+ }
+ if (unroll_m >= 48) {
+ if (isUnmasked) {
+ vmovups(zmm2, ptr[AO1 + (2 * 16 - OFFSET) * SIZE]);
+ } else {
+ vmovups(zmm2 | k3 | T_z,
+ ptr[AO1 + (2 * 16 - OFFSET) * SIZE]);
+ }
+ }
+ add(AO1, LDA);
+ }
+
+ for (int i = 0; i < unroll_n; i++) {
+ if (!isTransB) {
+ switch (i) {
+ case 0:
+ vbroadcastss(zmm3, ptr[BO1 + (0 - OFFSET) * SIZE]);
+ break;
+ case 1:
+ vbroadcastss(
+ zmm3, ptr[BO1 + LDB * 1 + (0 - OFFSET) * SIZE]);
+ break;
+ case 2:
+ vbroadcastss(
+ zmm3, ptr[BO1 + LDB * 2 + (0 - OFFSET) * SIZE]);
+ break;
+ case 3:
+ vbroadcastss(
+ zmm3, ptr[BO1 + LDB3 + (0 - OFFSET) * SIZE]);
+ break;
+ case 4:
+ vbroadcastss(zmm3, ptr[BO2 + (0 - OFFSET) * SIZE]);
+ break;
+ case 5:
+ vbroadcastss(
+ zmm3, ptr[BO2 + LDB * 1 + (0 - OFFSET) * SIZE]);
+ break;
+ case 6:
+ vbroadcastss(
+ zmm3, ptr[BO2 + LDB * 2 + (0 - OFFSET) * SIZE]);
+ break;
+ case 7:
+ vbroadcastss(
+ zmm3, ptr[BO2 + LDB3 + (0 - OFFSET) * SIZE]);
+ break;
+ }
+ } else {
+ vbroadcastss(zmm3, ptr[BO1 + (i - OFFSET) * SIZE]);
+ }
+ vfmadd231ps(regs[i], zmm3, zmm0);
+ if (unroll_m >= 32) {
+ vfmadd231ps(regs[i + 8], zmm3, zmm1);
+ }
+ if (unroll_m >= 48) {
+ vfmadd231ps(regs[i + 16], zmm3, zmm2);
+ }
+ }
+
+ if (isCopy) {
+ if (isUnmasked || unroll_m > 16) {
+ vmovups(ptr[LDA4 + (unroll_m * 0 + 0 * 16 - OFFSET) * SIZE],
+ zmm0);
+ } else {
+ vmovups(ptr[LDA4 + (unroll_m * 0 + 0 * 16 - OFFSET) * SIZE],
+ zmm0 | k1);
+ }
+ if (unroll_m >= 32) {
+ if (isUnmasked || unroll_m > 32) {
+ vmovups(ptr[LDA4
+ + (unroll_m * 0 + 1 * 16 - OFFSET)
+ * SIZE],
+ zmm1);
+ } else {
+ vmovups(ptr[LDA4
+ + (unroll_m * 0 + 1 * 16 - OFFSET)
+ * SIZE],
+ zmm1 | k2);
+ }
+ }
+ if (unroll_m >= 48) {
+ if (isUnmasked) {
+ vmovups(ptr[LDA4
+ + (unroll_m * 0 + 2 * 16 - OFFSET)
+ * SIZE],
+ zmm2);
+ } else {
+ vmovups(ptr[LDA4
+ + (unroll_m * 0 + 2 * 16 - OFFSET)
+ * SIZE],
+ zmm2 | k3);
+ }
+ }
+ sub(LDA4, -unroll_m * SIZE);
+ }
+
+ if (!isDirect) {
+ if (isUnmasked || unroll_m > 16) {
+ vmovups(zmm0,
+ ptr[AO1 + (unroll_m * 1 + 0 * 16 - OFFSET) * SIZE]);
+ } else {
+ vmovups(zmm0 | k1 | T_z,
+ ptr[AO1 + (unroll_m * 1 + 0 * 16 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 32) {
+ if (isUnmasked || unroll_m > 32) {
+ vmovups(zmm1, ptr[AO1
+ + (unroll_m * 1 + 1 * 16 - OFFSET)
+ * SIZE]);
+ } else {
+ vmovups(zmm1 | k2 | T_z,
+ ptr[AO1
+ + (unroll_m * 1 + 1 * 16 - OFFSET)
+ * SIZE]);
+ }
+ }
+ if (unroll_m >= 48) {
+ if (isUnmasked) {
+ vmovups(zmm2, ptr[AO1
+ + (unroll_m * 1 + 2 * 16 - OFFSET)
+ * SIZE]);
+ } else {
+ vmovups(zmm2 | k3 | T_z,
+ ptr[AO1
+ + (unroll_m * 1 + 2 * 16 - OFFSET)
+ * SIZE]);
+ }
+ }
+ sub(AO1, -unroll_m * SIZE);
+ }
+
+ if (!isTransB) {
+ sub(BO1, -SIZE);
+ if (unroll_n >= 4) {
+ sub(BO2, -SIZE);
+ }
+ } else {
+ add(BO1, LDB);
+ }
+
+ sub(LL, 1);
+ jg(kernel16, T_NEAR);
+ align(16);
+
+ L(kernel18);
+ vbroadcastss(VALPHA, ALPHA);
+
+ if (isBetaN) {
+ vbroadcastss(VBETA, BETA);
+ }
+
+ // Write back the results; all beta cases need to be handled
+ if (hasBias) {
+ mov(BIAS1, BIAS);
+ if (isUnmasked || unroll_m > 16)
+ vmovups(VBIAS1, ptr[BIAS1 + 0 * SIZE]);
+ else
+ vmovups(VBIAS1 | k1 | T_z, ptr[BIAS1 + 0 * SIZE]);
+ if (unroll_m >= 32) {
+ if (isUnmasked || unroll_m > 32)
+ vmovups(VBIAS2, ptr[BIAS1 + 16 * SIZE]);
+ else
+ vmovups(VBIAS2 | k2 | T_z, ptr[BIAS1 + 16 * SIZE]);
+ }
+ if (unroll_m >= 48) {
+ if (isUnmasked)
+ vmovups(VBIAS3, ptr[BIAS1 + 32 * SIZE]);
+ else
+ vmovups(VBIAS3 | k3 | T_z, ptr[BIAS1 + 32 * SIZE]);
+ }
+ }
+
+ for (int i = 0; i < unroll_n; i++) {
+ bool useScale = i % 2 != 0;
+ bool useCO1 = i < 2;
+ if (i == 2)
+ lea(CO2, ptr[CO1 + LDC * 2]);
+ if (i == 4 || i == 6)
+ lea(CO2, ptr[CO2 + LDC * 2]);
+ if (hasBias)
+ vaddps(regs[i], VBIAS1, regs[i]);
+ if (isUnmasked || unroll_m > 16) {
+ update(regs[i], useCO1, 0, 0, useScale);
+ } else {
+ update(regs[i], useCO1, 0, 1, useScale);
+ }
+ if (unroll_m >= 32) {
+ if (hasBias)
+ vaddps(regs[i + 8], VBIAS2, regs[i + 8]);
+ if (isUnmasked || unroll_m > 32) {
+ update(regs[i + 8], useCO1, 16, 0, useScale);
+ } else {
+ update(regs[i + 8], useCO1, 16, 2, useScale);
+ }
+ }
+ if (unroll_m >= 48) {
+ if (hasBias)
+ vaddps(regs[i + 16], VBIAS3, regs[i + 16]);
+ if (isUnmasked) {
+ update(regs[i + 16], useCO1, 32, 0, useScale);
+ } else {
+ update(regs[i + 16], useCO1, 32, 3, useScale);
+ }
+ }
+ }
+
+ switch (unroll_n) {
+ case 1: add(CO1, LDC); break;
+ case 2: lea(CO1, ptr[CO1 + LDC * 2]); break;
+ case 3: lea(CO1, ptr[CO2 + LDC * 1]); break;
+ case 4: lea(CO1, ptr[CO2 + LDC * 2]); break;
+ case 5: lea(CO1, ptr[CO2 + LDC * 1]); break;
+ case 6: lea(CO1, ptr[CO2 + LDC * 2]); break;
+ case 7: lea(CO1, ptr[CO2 + LDC * 1]); break;
+ case 8: lea(CO1, ptr[CO2 + LDC * 2]); break;
+ }
+
+ // Compute next address of B
+ if (!isTransB) {
+ lea(rax, ptr[K * SIZE]);
+ switch (unroll_n) {
+ case 1:
+ add(BO1, LDB);
+ add(BO2, LDB);
+ break;
+ case 2:
+ lea(BO1, ptr[BO1 + LDB * 2]);
+ lea(BO2, ptr[BO2 + LDB * 2]);
+ break;
+ case 3:
+ lea(BO1, ptr[BO1 + LDB3]);
+ lea(BO2, ptr[BO2 + LDB3]);
+ break;
+ case 4:
+ lea(BO1, ptr[BO1 + LDB * 4]);
+ lea(BO2, ptr[BO2 + LDB * 4]);
+ break;
+ case 5:
+ lea(BO1, ptr[BO1 + LDB * 4]);
+ add(BO1, LDB);
+ lea(BO2, ptr[BO2 + LDB * 4]);
+ add(BO2, LDB);
+ break;
+ case 6:
+ lea(BO1, ptr[BO1 + LDB3 * 2]);
+ lea(BO2, ptr[BO2 + LDB3 * 2]);
+ break;
+ case 7:
+ lea(BO1, ptr[BO1 + LDB * 8]);
+ sub(BO1, LDB);
+ lea(BO2, ptr[BO2 + LDB * 8]);
+ sub(BO2, LDB);
+ break;
+ case 8:
+ lea(BO1, ptr[BO1 + LDB * 8]);
+ lea(BO2, ptr[BO2 + LDB * 8]);
+ break;
+ }
+ sub(BO1, rax);
+ sub(BO2, rax);
+ } else {
+ mov(rax, LDB);
+ imul(rax, K);
+ sub(BO1, rax);
+ add(BO1, unroll_n * SIZE);
+ }
+ };
+
+ // High-level subroutine; does packing if needed, then splits C matrix.
+ // Operates on chunks of 48 rows, 8 columns at a time (handling tail
+ // cases appropriately by doing 32 or 16 rows, and/or with masking,
+ // and/or fewer columns).
+ auto subloop = [&](int unroll_m) {
+ Label l_subloop_20x[8], l_subloop_mask_20x[8];
+ Label l_subloop_30x[8], l_subloop_mask_30x[8];
+
+ Label subloop11, subloop11mask;
+ Label subloop30, subloop30mask;
+ Label subloop31, subloop31mask;
+ Label subloop96;
+ Label subloop98, subloop98mask;
+ Label subloop99;
+
+ // Create mask
+ mov(BO1, rcx);
+ mov(rcx, M);
+ sub(rcx, unroll_m - 16);
+ mov(CO1, 16);
+ cmp(rcx, 16);
+
+ cmovg(rcx, CO1);
+ mov(rax, 1);
+ sal(rax, cl);
+ sub(rax, 1);
+ mov(rcx, 0xffff);
+
+ if (unroll_m == 16) {
+ kmovw(k1, eax);
+ } else if (unroll_m == 32) {
+ kmovw(k1, ecx);
+ kmovw(k2, eax);
+ } else {
+ kmovw(k1, ecx);
+ kmovw(k2, ecx);
+ kmovw(k3, eax);
+ }
+ mov(rcx, BO1);
+
+ and_(rax, 0xffff);
+ cmp(rax, 0xffff);
+ jne(subloop96, T_NEAR);
+
+ if (isTransA) {
+ do_pack(unroll_m);
+ }
+
+ mov(CO1, C);
+ add(C, unroll_m * SIZE);
+
+ mov(BO1, B);
+ if (!isTransB) {
+ lea(BO2, ptr[B + LDB * 4]);
+ }
+
+ if (!isTransA) {
+ lea(AA, ptr[A + (unroll_m + 16 - 1 - OFFSET) * SIZE]);
+ cmp(M, UNROLL_M);
+ jg(subloop98, T_NEAR);
+
+ mov(AA, ORIG_A);
+ lea(AA, ptr[AA + (16 - 1 - OFFSET) * SIZE]);
+ L(subloop98);
+ }
+
+ mov(LL, N);
+ mov(I, LL);
+ if (!isTransA) {
+ // If N is too small, skip copy operation
+ cmp(LL, UNROLL_N * 3);
+ jle(subloop30, T_NEAR);
+
+ // If A is not aligned to cache line
+ cmp(FLAG, 0);
+ je(subloop30, T_NEAR);
+ } else {
+ cmp(LL, UNROLL_N);
+ jl(l_subloop_20x[1], T_NEAR);
+ }
+ align(16);
+
+ if (!isTransA) {
+ kernel(unroll_m, UNROLL_N, true, true);
+ } else {
+ kernel(unroll_m, UNROLL_N, false, false);
+ }
+
+ sub(I, UNROLL_N);
+ cmp(I, UNROLL_N);
+ jl(l_subloop_20x[1], T_NEAR);
+ align(16);
+
+ L(subloop11);
+ kernel(unroll_m, UNROLL_N, false, false);
+ sub(I, UNROLL_N);
+ cmp(I, UNROLL_N);
+ jge(subloop11, T_NEAR);
+ align(16);
+
+ for (int i = 1; i <= 7; i++) {
+ L(l_subloop_20x[i]);
+ cmp(I, i);
+ if (i < 7) {
+ jne(l_subloop_20x[i + 1], T_NEAR);
+ } else {
+ jne(subloop99, T_NEAR);
+ }
+ kernel(unroll_m, i, false, false);
+ jmp(subloop99, T_NEAR);
+ align(16);
+ }
+
+ if (!isTransA) {
+ L(subloop30);
+ cmp(I, UNROLL_N);
+ jl(l_subloop_30x[1], T_NEAR);
+ align(16);
+
+ L(subloop31);
+ kernel(unroll_m, UNROLL_N, true, false);
+ sub(I, UNROLL_N);
+ cmp(I, UNROLL_N);
+ jge(subloop31, T_NEAR);
+ align(16);
+
+ for (int i = 1; i <= 7; i++) {
+ L(l_subloop_30x[i]);
+ cmp(I, i);
+ if (i < 7) {
+ jne(l_subloop_30x[i + 1], T_NEAR);
+ } else {
+ jne(subloop99, T_NEAR);
+ }
+ kernel(unroll_m, i, true, false);
+ if (i < 7)
+ jmp(subloop99, T_NEAR);
+ align(16);
+ }
+ }
+ jmp(subloop99, T_NEAR);
+ align(16);
+
+ L(subloop96);
+ if (isTransA) {
+ do_pack(unroll_m);
+ }
+
+ mov(CO1, C);
+ add(C, unroll_m * SIZE);
+ mov(BO1, B);
+ if (!isTransB) {
+ lea(BO2, ptr[B + LDB * 4]);
+ }
+
+ if (!isTransA) {
+ lea(AA, ptr[A + (unroll_m + 16 - 1 - OFFSET) * SIZE]);
+ cmp(M, UNROLL_M);
+ jg(subloop98mask, T_NEAR);
+ mov(AA, ORIG_A);
+ lea(AA, ptr[AA + (16 - 1 - OFFSET) * SIZE]);
+ L(subloop98mask);
+ }
+
+ mov(LL, N);
+ mov(I, LL);
+ if (!isTransA) {
+ // If N is too small, skip copy operation
+ cmp(LL, UNROLL_N * 3);
+ jle(subloop30mask, T_NEAR);
+
+ // If A is not aligned to cache line
+ cmp(FLAG, 0);
+ je(subloop30mask, T_NEAR);
+ } else {
+ cmp(LL, UNROLL_N);
+ jl(l_subloop_mask_20x[1], T_NEAR);
+ }
+ align(16);
+
+ if (!isTransA) {
+ kernel(unroll_m, UNROLL_N, true, true, false);
+ } else {
+ kernel(unroll_m, UNROLL_N, false, false, false);
+ }
+
+ sub(I, UNROLL_N);
+ cmp(I, UNROLL_N);
+ jl(l_subloop_mask_20x[1], T_NEAR);
+ align(16);
+
+ L(subloop11mask);
+ kernel(unroll_m, UNROLL_N, false, false, false);
+ sub(I, UNROLL_N);
+ cmp(I, UNROLL_N);
+ jge(subloop11mask, T_NEAR);
+ align(16);
+
+ for (int i = 1; i <= 7; i++) {
+ L(l_subloop_mask_20x[i]);
+ cmp(I, i);
+ if (i < 7) {
+ jne(l_subloop_mask_20x[i + 1], T_NEAR);
+ } else {
+ jne(subloop99, T_NEAR);
+ }
+ kernel(unroll_m, i, false, false, false);
+ jmp(subloop99, T_NEAR);
+ align(16);
+ }
+
+ if (!isTransA) {
+ L(subloop30mask);
+ cmp(I, UNROLL_N);
+ jl(l_subloop_mask_30x[1], T_NEAR);
+ align(16);
+
+ L(subloop31mask);
+ kernel(unroll_m, UNROLL_N, true, false, false);
+ sub(I, UNROLL_N);
+ cmp(I, UNROLL_N);
+ jge(subloop31mask, T_NEAR);
+ align(16);
+
+ for (int i = 1; i <= 7; i++) {
+ L(l_subloop_mask_30x[i]);
+ cmp(I, i);
+ if (i < 7) {
+ jne(l_subloop_mask_30x[i + 1], T_NEAR);
+ } else {
+ jne(subloop99, T_NEAR);
+ }
+ kernel(unroll_m, i, true, false, false);
+ if (i < 7)
+ jmp(subloop99, T_NEAR);
+ align(16);
+ }
+ }
+
+ L(subloop99);
+ // Compute address for A
+ if (!isTransA) {
+ add(A, unroll_m * SIZE);
+ } else {
+ mov(rax, LDA);
+ imul(rax, rax, unroll_m);
+ add(A, rax);
+ }
+
+ // Compute next address of BIAS
+ if (hasBias) {
+ add(BIAS, unroll_m * SIZE);
+ }
+ };
+
+ preamble();
+
+ Label buffer_in_ws, buffer_allocated;
+
+ // Get the registers
+ mov(B, ARG_B);
+ mov(LDB, ARG_LDB);
+ mov(r15, ARG_BETA);
+ mov(r12, ARG_C);
+ if (hasBias)
+ mov(r10, ARG_BIAS);
+ mov(LDC, ARG_LDC);
+ mov(rbp, rsp);
+
+ vmovss(xmm0, ptr[ARG_ALPHA]);
+ vmovss(xmm1, ptr[r15]);
+
+#if _WIN32
+ mov(A, ARG_A);
+ mov(LDA, ARG_LDA);
+#endif
+
+ cmp(K, STACK_K_CAPACITY);
+ jg(buffer_in_ws, T_NEAR);
+
+ // Create buffer and align to 4kB page
+ lea(rax, ptr[K * SIZE]);
+ imul(rax, rax, 0x30);
+ add(rax, 256);
+ sub(rsp, rax);
+ and_(rsp, -PAGE_4K);
+ jmp(buffer_allocated, T_NEAR);
+
+ L(buffer_in_ws);
+ mov(rsp, ARG_WS);
+
+ L(buffer_allocated);
+
+ mov(ORIG_SP, rbp);
+ mov(M, ARG_M);
+ mov(N, ARG_N);
+ mov(C, r12);
+ if (hasBias)
+ mov(BIAS, r10);
+ vmovss(ALPHA, xmm0);
+ vmovss(BETA, xmm1);
+ sub(A, -OFFSET * SIZE);
+ sub(B, -OFFSET * SIZE);
+ mov(ORIG_A, A);
+ sal(LDA, BASE_SHIFT);
+ sal(LDB, BASE_SHIFT);
+ sal(LDC, BASE_SHIFT);
+ lea(LDB3, ptr[LDB + LDB * 2]);
+
+ if (isTransA) {
+ vpbroadcastq(zmm2, LDA);
+ vpxorq(ZSTRIDE, ZSTRIDE, ZSTRIDE);
+ mov(rax, -2);
+ kmovw(k4, eax);
+
+ for (int i = 0; i < 6; i++) {
+ vpaddq(ZSTRIDE | k4, ZSTRIDE, zmm2);
+ kshiftlw(k4, k4, 1);
+ }
+ vpaddq(ZSTRIDE | k4, ZSTRIDE, zmm2);
+ }
+
+ // Check A alignment and leading dimension; take copy-based path as
+ // needed
+ mov(rax, LDA);
+ or_(rax, A);
+ and_(rax, ver == ver_avx512_core ? 0x07 : 0x3f);
+ mov(FLAG, rax);
+
+ for (int i = 8; i < 16; i++) {
+ for (int j = 0; j < 3; j++) {
+ vpxorq(Zmm(i + 8 * j), Zmm(i + 8 * j), Zmm(i + 8 * j));
+ }
+ }
+
+ Label main0, main1, main2, main999;
+
+ cmp(M, 32);
+ jle(main0, T_NEAR);
+ align(16);
+
+ L(main1);
+ subloop(48);
+ sub(M, UNROLL_M);
+ cmp(M, 32);
+ jg(main1, T_NEAR);
+ align(16);
+
+ L(main0);
+ cmp(M, 16);
+ jle(main2, T_NEAR);
+
+ subloop(32);
+ jmp(main999, T_NEAR);
+ align(16);
+
+ L(main2);
+ cmp(M, 0);
+ jle(main999, T_NEAR);
+ subloop(16);
+ align(16);
+
+ L(main999);
+ // Restore original stack
+ mov(rsp, ORIG_SP);
+
+ vzeroupper();
+ postamble();
+
+ ker_ = this->getCode<ker_t>();
+ }
+
+ typedef void (*ker_t)(dim_t m, dim_t n, dim_t k,
+ const float *alpha, const float *a, dim_t lda,
+ const float *b, dim_t ldb, const float *beta, float *c,
+ dim_t ldc, const float *bias, float *ws);
+
+ void operator()(dim_t m, dim_t n, dim_t k,
+ const float *alpha, const float *a, dim_t lda,
+ const float *b, dim_t ldb, const float *beta, float *c,
+ dim_t ldc, const float *bias, float *ws) const
+ {
+ ker_(m, n, k, alpha, a, lda, b, ldb, beta, c, ldc, bias, ws);
+ }
+
+private:
+ ker_t ker_;
+};
+
+const xbyak_gemm *get_xbyak_gemm(
+ bool isTransA, bool isTransB, float beta, bool hasBias) {
+ auto beta_idx = [](float beta) {
+ return (beta == 0.0) ? 0 : (beta == 1.0 ? 1 : 2);
+ };
+
+ // Kernel table [isTransA][isTransB][hasBias][beta (0, 1, other)]
+ static xbyak_gemm *kernel_table[2][2][2][3];
+ static std::once_flag initialized;
+ std::call_once(initialized, [=]{
+ for (bool isTransA: {false, true})
+ for (bool isTransB: {false, true})
+ for (bool hasBias: {false, true})
+ for (float beta: {0.0f, 1.0f, 2.0f}) {
+ // nocopy sgemm with bias for beta != 0.0 is not supported
+ if (hasBias && beta != 0.0)
+ continue;
+ kernel_table[isTransA][isTransB][hasBias][beta_idx(beta)] =
+ new xbyak_gemm(isTransA, isTransB, beta, hasBias);
+ }
+ });
+
+ return kernel_table[isTransA][isTransB][hasBias][beta_idx(beta)];
+}
+
+void sgemm_nocopy_driver(const char *transa,
+ const char *transb, int m, int n, int k, const float *alpha,
+ const float *a, dim_t lda, const float *b, dim_t ldb, const float *beta,
+ float *c, dim_t ldc, const float *bias, float *ws)
+{
+ bool isTransA = (*transa == 'T' || *transa == 't');
+ bool isTransB = (*transb == 'T' || *transb == 't');
+
+ int Bm, sizeM, Bn, sizeN, Bk, sizeK;
+
+ int i, j;
+
+ if ((m <= 0) || (n <= 0))
+ return;
+
+ if ((k <= 0) || (alpha[0] == 0.)) {
+
+ if (beta[0] == 0.) {
+ for (j = 0; j < n; j++)
+ for (i = 0; i < m; i++)
+ c[i + j * ldc] = 0.0;
+ } else if (beta[0] != 1.) {
+ for (j = 0; j < n; j++)
+ for (i = 0; i < m; i++)
+ c[i + j * ldc] *= beta[0];
+ }
+
+ return;
+ }
+
+ assert(IMPLICATION(bias != nullptr, *beta == 0.0));
+
+ // XXX: this happens on every thread...
+ bool hasBias = (bias != nullptr);
+ auto ker_bn = get_xbyak_gemm(isTransA, isTransB, *beta, hasBias);
+ auto ker_b1 = get_xbyak_gemm(isTransA, isTransB, 1.0, false);
+ auto ker_b0 = get_xbyak_gemm(isTransA, isTransB, 0.0, false);
+ assert(ker_bn && ker_b1 && ker_b0);
+
+ int BM = 4032, BN, BK;
+ if (mayiuse(avx512_core)) {
+ BN = isTransA ? 384 : 64;
+ BK = 384;
+ } else {
+ BN = isTransA ? 96 : 64;
+ BK = isTransB ? 96 : 192;
+ if (!isTransA && !isTransB)
+ BK = 128;
+ }
+ const float *curA, *curB, *curBias = nullptr;
+ float *curC;
+
+ for (Bk = 0; Bk < k; Bk += sizeK) {
+ sizeK = k - Bk;
+ if (sizeK >= BK * 2)
+ sizeK = BK;
+ else {
+ if (sizeK > BK)
+ sizeK = (sizeK + 1) / 2;
+ }
+
+ for (Bm = 0; Bm < m; Bm += sizeM) {
+ sizeM = m - Bm;
+ if (sizeM >= BM * 2)
+ sizeM = BM;
+ else {
+ if (sizeM > BM + BM / 2)
+ sizeM = (sizeM + 1) / 2;
+ }
+
+ for (Bn = 0; Bn < n; Bn += sizeN) {
+ sizeN = n - Bn;
+ if (sizeN >= BN * 2)
+ sizeN = BN;
+ else {
+ if (sizeN > BN + BN / 2)
+ sizeN = (sizeN + 1) / 2;
+ }
+
+ if (!isTransA) {
+ curA = a + Bm + Bk * lda;
+ } else {
+ curA = a + Bk + Bm * lda;
+ }
+ if (!isTransB) {
+ curB = b + Bk + Bn * ldb;
+ } else {
+ curB = b + Bn + Bk * ldb;
+ }
+ curC = c + Bm + (size_t)Bn * ldc;
+ if (bias != nullptr) {
+ if (Bk == 0) {
+ curBias = bias + Bm;
+ } else {
+ curBias = nullptr;
+ }
+ }
+ if (Bk == 0) {
+ if (*beta == 0.0 && bias == nullptr)
+ (*ker_b0)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK,
+ alpha, curA, lda, curB, ldb, beta, curC, ldc,
+ curBias, ws);
+ else
+ (*ker_bn)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK,
+ alpha, curA, lda, curB, ldb, beta, curC, ldc,
+ curBias, ws);
+ } else {
+ (*ker_b1)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK,
+ alpha, curA, lda, curB, ldb, beta, curC, ldc,
+ curBias, ws);
+ }
+ }
+ }
+ }
+}
+
+}
+
+mkldnn_status_t jit_avx512_common_gemm_f32(
+ const char *transa, const char *transb,
+ const int *p_m, const int *p_n, const int *p_k, const float *p_alpha,
+ const float *A, const int *p_lda, const float *B, const int *p_ldb,
+ const float *p_beta, float *C, const int *p_ldc, const float *bias)
+{
+ using namespace mkldnn::impl::utils;
+ using namespace avx512_common_gemm_f32;
+ using namespace gemm_utils;
+
+ if (*p_beta != 0 && bias)
+ return ref_gemm(transa, transb, p_m, p_n, p_k,
+ p_alpha, A, p_lda, B, p_lda, p_beta, C, p_ldc, bias);
+
+ int nthr = (mkldnn_in_parallel()) ? 1 : mkldnn_get_max_threads();
+
+ int m = *p_m;
+ int n = *p_n;
+ int k = *p_k;
+ dim_t lda = *p_lda;
+ dim_t ldb = *p_ldb;
+ dim_t ldc = *p_ldc;
+ float beta = *p_beta;
+ int MB, NB, KB;
+
+ int nthr_m, nthr_n, nthr_k, nthr_mn;
+
+ // Determine threading partitioning
+ calc_nthr_nocopy_avx512_common(
+ m, n, k, nthr, &nthr_m, &nthr_n, &nthr_k, &MB, &NB, &KB);
+ assert(IMPLICATION(!mkldnn_thr_syncable(), nthr_k == 1));
+
+ // May not happen, but just in case
+ if (nthr < nthr_m * nthr_n * nthr_k)
+ nthr = nthr_m * nthr_n * nthr_k;
+
+ nthr_mn = nthr_m * nthr_n;
+
+ unsigned char * ompstatus_ = nullptr;
+ unsigned char volatile *ompstatus = nullptr;
+
+ float *c_buffers = nullptr;
+ float *ws_buffers = nullptr;
+
+ if (nthr_k > 1) {
+ ompstatus_ = (unsigned char *) malloc(
+ nthr * CACHE_LINE_SIZE,
+ CACHE_LINE_SIZE);
+ ompstatus = (unsigned char volatile *) ompstatus_;
+ assert(ompstatus);
+
+ for (int i = 0; i < nthr; i++)
+ ompstatus[i * CACHE_LINE_SIZE] = 0;
+
+ c_buffers = (float *)malloc(nthr_m * nthr_n * (nthr_k - 1) * MB * NB
+ * sizeof(float), PAGE_4K);
+ }
+
+ const size_t ws_elems_per_thr = (size_t)k * 48 + 64;
+ const size_t ws_size_per_thr
+ = rnd_up(ws_elems_per_thr * sizeof(float), PAGE_4K);
+ if (k > STACK_K_CAPACITY) {
+ ws_buffers = (float *)malloc(nthr * ws_size_per_thr, PAGE_4K);
+ }
+
+ parallel_nd(nthr, [&](const int ithr) {
+ int ithr_m, ithr_n, ithr_k, ithr_mn;
+ int m_from, m_to, myM;
+ int n_from, n_to, myN;
+ int k_from, k_to, myK;
+ int cbase, ibase;
+ const float *myA, *myB, *myBias = nullptr;
+ float *myC = C, myBeta;
+ float *ws = ws_buffers ?
+ ws_buffers + ithr * ws_size_per_thr / sizeof(float) : 0;
+ dim_t ld = ldc;
+
+ int sum_later = (mkldnn_get_num_threads() < nthr_m * nthr_n * nthr_k);
+
+ if (ithr < nthr_m * nthr_n * nthr_k) {
+
+ ithr_mn = ithr % nthr_mn;
+ ithr_m = ithr_mn % nthr_m;
+ ithr_n = ithr_mn / nthr_m;
+ ithr_k = ithr / nthr_mn;
+
+ /* swap ithr_k for performance improvement */
+ if (ithr_k == 0)
+ ithr_k = nthr_k - 1;
+ else if (ithr_k == nthr_k - 1)
+ ithr_k = 0;
+
+ m_from = MB * (ithr_m);
+ m_to = MB * (ithr_m + 1);
+ if (m_to > m)
+ m_to = m;
+ myM = m_to - m_from;
+
+ n_from = NB * (ithr_n);
+ n_to = NB * (ithr_n + 1);
+ if (n_to > n)
+ n_to = n;
+ myN = n_to - n_from;
+
+ k_from = KB * (ithr_k);
+ k_to = KB * (ithr_k + 1);
+ if (k_to > k)
+ k_to = k;
+ myK = k_to - k_from;
+
+ cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1);
+ ibase = (ithr_m + nthr_m * ithr_n) * nthr_k;
+
+ if ((myM > 0) && (myN > 0)) {
+
+ if (*transa == 'N' || *transa == 'n') {
+ myA = &(A[m_from + k_from * lda]);
+ } else {
+ myA = &(A[k_from + m_from * lda]);
+ }
+ if (*transb == 'N' || *transb == 'n') {
+ myB = &(B[k_from + n_from * ldb]);
+ } else {
+ myB = &(B[n_from + k_from * ldb]);
+ }
+ if (ithr_k == 0) {
+ myC = &(C[m_from + n_from * ldc]);
+ myBeta = beta;
+ ld = ldc;
+ if (bias)
+ myBias = &(bias[m_from]);
+ } else {
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1);
+ myBeta = 0.0;
+ ld = MB;
+ myBias = nullptr;
+ }
+
+ sgemm_nocopy_driver(transa, transb, myM, myN, myK, p_alpha, myA,
+ lda, myB, ldb, &myBeta, myC, ld, myBias, ws);
+
+ if (nthr_k > 1 && !sum_later)
+ ompstatus[(ibase + ithr_k) * CACHE_LINE_SIZE] = 1;
+ }
+
+ if (nthr_k > 1 && !sum_later) {
+
+ // sum matrices partitioned along K dimension
+ int n1, n2;
+
+ partition_unit_diff(ithr_k, nthr_k, myN, &n1, &n2);
+
+ if (ithr_k > 0) {
+
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1)
+ + (dim_t)n1 * MB;
+ /* need to wait until main thread finishes */
+ while (ompstatus[ibase * CACHE_LINE_SIZE] != 1) {
+ };
+
+ /* my cache is hot */
+ sum_two_matrices(myM, n2, myC, MB,
+ &C[m_from + (n_from + n1) * ldc], ldc);
+ }
+
+ for (int ik = 1; ik < nthr_k; ++ik) {
+ if (ik != ithr_k) {
+
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ik - 1)
+ + (dim_t)n1 * MB;
+
+ while (ompstatus[(ibase + ik) * CACHE_LINE_SIZE] != 1) {
+ };
+
+ sum_two_matrices(myM, n2, myC, MB,
+ &C[m_from + (n_from + n1) * ldc], ldc);
+ }
+ }
+ }
+ }
+ });
+
+
+ // handle C summation later
+ if (nthr_k > 1 && ompstatus[0] == 0) {
+
+ parallel_nd(nthr, [&](const int ithr) {
+ int ithr_m, ithr_n, ithr_k, ithr_mn;
+ int m_from, m_to, myM;
+ int n_from, n_to, myN;
+ int cbase;
+ float *myC = C;
+
+ if (ithr < nthr_m * nthr_n * nthr_k) {
+
+ ithr_mn = ithr % nthr_mn;
+ ithr_m = ithr_mn % nthr_m;
+ ithr_n = ithr_mn / nthr_m;
+ ithr_k = ithr / nthr_mn;
+
+ /* swap ithr_k for performance improvement */
+ if (ithr_k == 0)
+ ithr_k = nthr_k - 1;
+ else if (ithr_k == nthr_k - 1)
+ ithr_k = 0;
+
+ m_from = MB * (ithr_m);
+ m_to = MB * (ithr_m + 1);
+ if (m_to > m)
+ m_to = m;
+ myM = m_to - m_from;
+
+ n_from = NB * (ithr_n);
+ n_to = NB * (ithr_n + 1);
+ if (n_to > n)
+ n_to = n;
+ myN = n_to - n_from;
+
+ cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1);
+
+ if (nthr_k > 1) {
+ // sum matrices partitioned along K dimension
+ int n1, n2;
+
+ partition_unit_diff(ithr_k, nthr_k, myN, &n1, &n2);
+
+ if (ithr_k > 0) {
+
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1)
+ + (dim_t)n1 * MB;
+
+ /* my cache is hot */
+ sum_two_matrices(myM, n2, myC, MB,
+ &C[m_from + (n_from + n1) * ldc], ldc);
+ }
+
+ for (int ik = 1; ik < nthr_k; ++ik) {
+ if (ik != ithr_k) {
+
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ik - 1)
+ + (dim_t)n1 * MB;
+
+ sum_two_matrices(myM, n2, myC, MB,
+ &C[m_from + (n_from + n1) * ldc], ldc);
+ }
+ }
+ }
+ }
+ });
+ }
+
+ free(c_buffers);
+ free(ompstatus_);
+ free(ws_buffers);
+
+ return mkldnn_success;
+}
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.hpp
new file mode 100644
index 0000000000..d581b7fd71
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx512_common_gemm_f32.hpp
@@ -0,0 +1,36 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_AVX512_COMMON_GEMM_F32_HPP
+#define JIT_AVX512_COMMON_GEMM_F32_HPP
+
+#include "mkldnn_types.h"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+mkldnn_status_t jit_avx512_common_gemm_f32(
+ const char *transa, const char *transb, const int *M,
+ const int *N, const int *K, const float *alpha, const float *A,
+ const int *lda, const float *B, const int *ldb, const float *beta,
+ float *C, const int *ldc, const float *bias = nullptr);
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.cpp
new file mode 100644
index 0000000000..60d4220837
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.cpp
@@ -0,0 +1,2705 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <cmath>
+#include <mutex>
+
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "ref_gemm_f32.hpp"
+#include "gemm_utils_f32.hpp"
+#include "jit_avx_gemm_f32.hpp"
+
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+#define CACHE_LINE_SIZE 64
+
+#define STACKSIZE get_size_of_abi_save_regs()
+#if _WIN32
+#define STACK_K_CAPACITY 128
+#else
+#define STACK_K_CAPACITY 8192
+#endif
+#define SIZE 4
+#define OFFSET 32
+#define BASE_SHIFT 2
+#define SECOND_FETCH 14
+
+namespace avx_gemm_f32 {
+using namespace gemm_utils;
+
+struct xbyak_gemm : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx_gemm_f32_xbyak_gemm)
+
+ xbyak_gemm(char isTransA, char isTransB, float beta, bool hasBias = false,
+ void *code_ptr = nullptr,
+ size_t code_size = 80 * Xbyak::DEFAULT_MAX_CODE_SIZE)
+ : jit_generator(code_ptr, code_size)
+ {
+ using namespace Xbyak;
+
+ const bool is_avx2 = mayiuse(avx2);
+ assert(IMPLICATION(!is_avx2, mayiuse(avx)));
+
+ const int UNROLL_M = is_avx2 ? 16 : 8;
+ const int UNROLL_N = 6;
+
+ bool isBeta0 = (beta == 0.0);
+ bool isBetaN = (!isBeta0 && beta != 1.0);
+
+ // various definitions for convenience
+ auto ARG_M = abi_param1;
+ auto ARG_N = abi_param2;
+ auto K = abi_param3;
+ auto ARG_ALPHA = abi_param4;
+#ifdef _WIN32
+ auto ARG_A = ptr[rsp + OFFSET_SHADOWSPACE + STACKSIZE];
+ auto ARG_LDA = qword[rsp + OFFSET_SHADOWSPACE +
+ sizeof(float *) + STACKSIZE];
+ const auto stackOffset = OFFSET_SHADOWSPACE +
+ sizeof(float *) + STACKSIZE;
+ auto A = rsi;
+ auto LDA = rdi;
+#else
+ auto ARG_A = r8;
+ auto ARG_LDA = r9;
+ const auto stackOffset = STACKSIZE;
+ auto A = ARG_A;
+ auto LDA = ARG_LDA;
+#endif
+ auto ARG_B = ptr[rsp + 8 + stackOffset];
+ auto ARG_LDB = ptr[rsp + 16 + stackOffset];
+ auto ARG_BETA = ptr[rsp + 24 + stackOffset];
+ auto ARG_C = ptr[rsp + 32 + stackOffset];
+ auto ARG_LDC = ptr[rsp + 40 + stackOffset];
+ auto ARG_BIAS = ptr[rsp + 48 + stackOffset];
+ auto ARG_WS = ptr[rsp + 56 + stackOffset];
+
+ auto B = r11;
+ auto LDB = rbx;
+ auto LDC = r13;
+ auto LL = rax;
+ auto AO1 = abi_param2;
+ auto BO1 = abi_param4;
+ auto BO2 = rbp;
+ auto CO1 = r14;
+ auto CO2 = r15;
+ auto LDB3 = r10;
+ auto LDA4 = abi_param1;
+ auto AA = r12;
+ auto BIAS1 = abi_param1;
+
+ auto M = qword[rsp + 0];
+ auto N = qword[rsp + 8];
+ auto FLAG = qword[rsp + 16];
+ auto I = qword[rsp + 24];
+ auto C = qword[rsp + 32];
+ auto BIAS = qword[rsp + 40];
+ auto ALPHA = qword[rsp + 48];
+ auto BETA = qword[rsp + 64];
+ auto ORIG_A = qword[rsp + 80];
+ auto MASK = dword[rsp + 88];
+ auto STRIDE = qword[rsp + 120];
+ auto ORIG_SP = qword[rsp + 152];
+
+ auto VALPHA = ymm1;
+ auto VBETA = ymm2;
+ auto VMASK = ymm3;
+ auto VBIAS1 = ymm2;
+ auto VBIAS2 = ymm4;
+
+ auto PREFETCHSIZEA = 128;
+ auto PREFETCHSIZEB = (!isTransB) ? -16 : 0;
+
+ // Function for packing if needed
+ auto do_pack = [&](
+ int unroll_m, bool isLoad1Unmasked, bool isLoad2Unmasked) {
+ Label pack2, pack3, pack4, pack10;
+
+ int regIdx;
+ Reg64 reg;
+
+ mov(BO1, A);
+ lea(AO1, ptr[rsp + 256 + OFFSET * SIZE]);
+
+ if (isTransA) {
+ lea(BO2, ptr[BO1 + LDA * 4]);
+ lea(CO1, ptr[LDA + LDA * 2]);
+ vmovupd(ymm7, STRIDE);
+ }
+
+ mov(LL, K);
+ sar(LL, 2);
+ jle(pack3, T_NEAR);
+ align(16);
+
+ L(pack2);
+ if (!isTransA) {
+ for (int i = 0; i < 4; i++) {
+ regIdx = (i % 2 == 0) ? 4 : 6;
+ if (isLoad1Unmasked) {
+ vmovups(Ymm(regIdx),
+ ptr[BO1 + (0 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(Ymm(regIdx), VMASK,
+ ptr[BO1 + (0 * 8 - OFFSET) * SIZE]);
+ }
+ if (unroll_m > 8) {
+ if (isLoad2Unmasked) {
+ vmovups(Ymm(regIdx + 1),
+ ptr[BO1 + (1 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(Ymm(regIdx + 1), VMASK,
+ ptr[BO1 + (1 * 8 - OFFSET) * SIZE]);
+ }
+ }
+ add(BO1, LDA);
+
+ vmovups(ptr[AO1 + (unroll_m * i + 0 * 8 - OFFSET) * SIZE],
+ Ymm(regIdx));
+ if (unroll_m > 8) {
+ vmovups(ptr[AO1
+ + (unroll_m * i + 1 * 8 - OFFSET)
+ * SIZE],
+ Ymm(regIdx + 1));
+ }
+ }
+
+ } else {
+ if (isLoad1Unmasked) {
+ for (int i = 0; i < 2; i++) {
+ reg = (i % 2 == 0) ? BO1 : BO2;
+ vmovups(xmm0, ptr[reg + (0 * 8 - OFFSET) * SIZE]);
+ vmovups(xmm1,
+ ptr[reg + LDA * 1 + (0 * 8 - OFFSET) * SIZE]);
+ lea(BO2, ptr[reg + LDA * 2]);
+ vunpcklps(xmm4, xmm0, xmm1);
+ vunpckhps(xmm5, xmm0, xmm1);
+ vmovups(xmm0, ptr[BO2 + (0 * 8 - OFFSET) * SIZE]);
+ vmovups(xmm1,
+ ptr[BO2 + LDA * 1 + (0 * 8 - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 2]);
+ vunpcklps(xmm6, xmm0, xmm1);
+ vunpckhps(xmm2, xmm0, xmm1);
+
+ vunpcklpd(xmm0, xmm4, xmm6);
+ vunpckhpd(xmm1, xmm4, xmm6);
+ vmovups(ptr[AO1
+ + (unroll_m * 0 + i * 4 - OFFSET)
+ * SIZE],
+ xmm0);
+ vmovups(ptr[AO1
+ + (unroll_m * 1 + i * 4 - OFFSET)
+ * SIZE],
+ xmm1);
+ vunpcklpd(xmm0, xmm5, xmm2);
+ vunpckhpd(xmm1, xmm5, xmm2);
+ vmovups(ptr[AO1
+ + (unroll_m * 2 + i * 4 - OFFSET)
+ * SIZE],
+ xmm0);
+ vmovups(ptr[AO1
+ + (unroll_m * 3 + i * 4 - OFFSET)
+ * SIZE],
+ xmm1);
+ }
+ } else if (is_avx2) {
+ for (int i = 0; i < 2; i++) {
+ vmovaps(xmm4, xmm3);
+ vgatherqps(xmm0,
+ ptr[BO1 + ymm7 + ((2 * i) - OFFSET) * SIZE],
+ xmm4);
+ vmovaps(xmm4, xmm3);
+ vgatherqps(xmm1,
+ ptr[BO1 + ymm7 + ((2 * i + 1) - OFFSET) * SIZE],
+ xmm4);
+
+ vmovups(ptr[AO1
+ + (unroll_m * (2 * i) + 0 * 4 - OFFSET)
+ * SIZE],
+ xmm0);
+ vmovups(ptr[AO1
+ + (unroll_m * (2 * i + 1) + 0 * 4
+ - OFFSET)
+ * SIZE],
+ xmm1);
+ }
+
+ lea(BO2, ptr[BO1 + LDA * 4]);
+
+ for (int i = 0; i < 2; i++) {
+ vextractf128(xmm4, ymm3, 1);
+ vgatherqps(xmm0,
+ ptr[BO2 + ymm7 + ((2 * i) - OFFSET) * SIZE],
+ xmm4);
+ vextractf128(xmm4, ymm3, 1);
+ vgatherqps(xmm1,
+ ptr[BO2 + ymm7 + ((2 * i + 1) - OFFSET) * SIZE],
+ xmm4);
+
+ vmovups(ptr[AO1
+ + (unroll_m * (2 * i) + 1 * 4 - OFFSET)
+ * SIZE],
+ xmm0);
+ vmovups(ptr[AO1
+ + (unroll_m * (2 * i + 1) + 1 * 4
+ - OFFSET)
+ * SIZE],
+ xmm1);
+ }
+
+ lea(BO2, ptr[BO2 + LDA * 4]);
+ } else {
+ vxorps(xmm4, xmm4, xmm4);
+ lea(BO2, ptr[BO1 + LDA * 4]);
+
+ auto el_cp = [&](int section, int ld_step) {
+ RegExp src_addr = section == 0 ? BO1 : BO2;
+ if (ld_step == 1 || ld_step == 2)
+ src_addr = src_addr + LDA * ld_step;
+ else if (ld_step == 3)
+ src_addr = src_addr + CO1;
+ src_addr = src_addr - OFFSET * SIZE;
+
+ vmovups(Xmm(ld_step % 2), ptr[src_addr]);
+ RegExp dst_addr = AO1
+ + (ld_step + section * 4 - OFFSET) * SIZE;
+ for (int off = 0; off < 4; ++off)
+ pextrd(ptr[dst_addr + unroll_m * off * SIZE],
+ Xmm(ld_step % 2), off);
+ };
+
+ Label l_end;
+ el_cp(0, 0); cmp(M, 4 * 0 + 0 + 1); je(l_end, T_NEAR);
+ el_cp(0, 1); cmp(M, 4 * 0 + 1 + 1); je(l_end, T_NEAR);
+ el_cp(0, 2); cmp(M, 4 * 0 + 2 + 1); je(l_end, T_NEAR);
+ el_cp(0, 3); cmp(M, 4 * 0 + 3 + 1); je(l_end, T_NEAR);
+ el_cp(1, 0); cmp(M, 4 * 1 + 0 + 1); je(l_end, T_NEAR);
+ el_cp(1, 1); cmp(M, 4 * 1 + 1 + 1); je(l_end, T_NEAR);
+ el_cp(1, 2);
+ L(l_end);
+
+ lea(BO2, ptr[BO2 + LDA * 4]);
+ }
+
+ if (unroll_m >= 16) {
+ assert(is_avx2);
+ if (isLoad2Unmasked) {
+ for (int i = 0; i < 2; i++) {
+ vmovups(xmm0, ptr[BO2 + (0 * 8 - OFFSET) * SIZE]);
+ vmovups(xmm1, ptr[BO2 + LDA * 1
+ + (0 * 8 - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 2]);
+ vunpcklps(xmm4, xmm0, xmm1);
+ vunpckhps(xmm5, xmm0, xmm1);
+ vmovups(xmm0, ptr[BO2 + (0 * 8 - OFFSET) * SIZE]);
+ vmovups(xmm1, ptr[BO2 + LDA * 1
+ + (0 * 8 - OFFSET) * SIZE]);
+ if (i == 0)
+ lea(BO2, ptr[BO2 + LDA * 2]);
+ vunpcklps(xmm6, xmm0, xmm1);
+ vunpckhps(xmm2, xmm0, xmm1);
+
+ vunpcklpd(xmm0, xmm4, xmm6);
+ vunpckhpd(xmm1, xmm4, xmm6);
+ vmovups(ptr[AO1
+ + (unroll_m * 0 + (i + 2) * 4
+ - OFFSET)
+ * SIZE],
+ xmm0);
+ vmovups(ptr[AO1
+ + (unroll_m * 1 + (i + 2) * 4
+ - OFFSET)
+ * SIZE],
+ xmm1);
+ vunpcklpd(xmm0, xmm5, xmm2);
+ vunpckhpd(xmm1, xmm5, xmm2);
+ vmovups(ptr[AO1
+ + (unroll_m * 2 + (i + 2) * 4
+ - OFFSET)
+ * SIZE],
+ xmm0);
+ vmovups(ptr[AO1
+ + (unroll_m * 3 + (i + 2) * 4
+ - OFFSET)
+ * SIZE],
+ xmm1);
+ }
+ } else {
+ for (int i = 0; i < 2; i++) {
+ vmovaps(xmm4, xmm3);
+ vgatherqps(xmm0,
+ ptr[BO2 + ymm7 + ((2 * i) - OFFSET) * SIZE],
+ xmm4);
+ vmovaps(xmm4, xmm3);
+ vgatherqps(xmm1,
+ ptr[BO2 + ymm7
+ + ((2 * i + 1) - OFFSET) * SIZE],
+ xmm4);
+
+ vmovups(ptr[AO1
+ + (unroll_m * (2 * i) + 2 * 4
+ - OFFSET)
+ * SIZE],
+ xmm0);
+ vmovups(ptr[AO1
+ + (unroll_m * (2 * i + 1) + 2 * 4
+ - OFFSET)
+ * SIZE],
+ xmm1);
+ }
+
+ lea(BO2, ptr[BO2 + LDA * 4]);
+
+ for (int i = 0; i < 2; i++) {
+ vextractf128(xmm4, ymm3, 1);
+ vgatherqps(xmm0,
+ ptr[BO2 + ymm7 + ((2 * i) - OFFSET) * SIZE],
+ xmm4);
+ vextractf128(xmm4, ymm3, 1);
+ vgatherqps(xmm1,
+ ptr[BO2 + ymm7
+ + ((2 * i + 1) - OFFSET) * SIZE],
+ xmm4);
+
+ vmovups(ptr[AO1
+ + (unroll_m * (2 * i) + 3 * 4
+ - OFFSET)
+ * SIZE],
+ xmm0);
+ vmovups(ptr[AO1
+ + (unroll_m * (2 * i + 1) + 3 * 4
+ - OFFSET)
+ * SIZE],
+ xmm1);
+ }
+
+ lea(BO2, ptr[BO2 + LDA * 4]);
+ }
+ }
+ add(BO1, (4 * SIZE));
+ }
+
+ add(AO1, unroll_m * 4 * SIZE);
+ sub(LL, 1);
+ jg(pack2, T_NEAR);
+ align(16);
+
+ L(pack3);
+ mov(LL, K);
+ and_(LL, 3);
+ jle(pack10, T_NEAR);
+ align(16);
+
+ L(pack4);
+ if (!isTransA) {
+ if (isLoad1Unmasked) {
+ vmovups(ymm4, ptr[BO1 + (0 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm4, VMASK, ptr[BO1 + (0 * 8 - OFFSET) * SIZE]);
+ }
+ if (unroll_m > 8) {
+ if (isLoad2Unmasked) {
+ vmovups(ymm5, ptr[BO1 + (1 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm5, VMASK,
+ ptr[BO1 + (1 + 8 - OFFSET) * SIZE]);
+ }
+ }
+ add(BO1, LDA);
+ vmovups(ptr[AO1 + (unroll_m * 0 + 0 * 8 - OFFSET) * SIZE],
+ ymm4);
+ if (unroll_m > 8) {
+ vmovups(ptr[AO1 + (unroll_m * 0 + 1 * 8 - OFFSET) * SIZE],
+ ymm5);
+ }
+ } else {
+ if (isLoad1Unmasked) {
+ for (int i = 0; i < 2; i++) {
+ reg = (i % 2 == 0) ? BO1 : BO2;
+ vmovss(Xmm(i + 1), ptr[reg + (0 * 8 - OFFSET) * SIZE]);
+ vmovss(xmm0,
+ ptr[reg + LDA * 1 + (0 * 8 - OFFSET) * SIZE]);
+ lea(BO2, ptr[reg + LDA * 2]);
+ vunpcklps(Xmm(i + 1), Xmm(i + 1), Xmm(0));
+ }
+ vunpcklpd(xmm1, xmm1, xmm2);
+ vmovups(ptr[AO1 + (unroll_m * 0 + 0 * 4 - OFFSET) * SIZE],
+ xmm1);
+
+ for (int i = 0; i < 2; i++) {
+ vmovss(Xmm(i + 1), ptr[BO2 + (0 * 8 - OFFSET) * SIZE]);
+ vmovss(xmm0,
+ ptr[BO2 + LDA * 1 + (0 * 8 - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 2]);
+ vunpcklps(Xmm(i + 1), Xmm(i + 1), Xmm(0));
+ }
+ vunpcklpd(xmm1, xmm1, xmm2);
+ vmovups(ptr[AO1 + (unroll_m * 0 + 1 * 4 - OFFSET) * SIZE],
+ xmm1);
+ } else if (is_avx2) {
+ vmovaps(xmm4, xmm3);
+ vgatherqps(xmm1, ptr[BO1 + ymm7 + (0 * 8 - OFFSET) * SIZE],
+ xmm4);
+ lea(BO2, ptr[BO1 + LDA * 4]);
+ vmovups(ptr[AO1 + (unroll_m * 0 + 0 * 4 - OFFSET) * SIZE],
+ xmm1);
+
+ vextractf128(xmm4, ymm3, 1);
+ vgatherqps(xmm1, ptr[BO2 + ymm7 + (0 * 8 - OFFSET) * SIZE],
+ xmm4);
+ lea(BO2, ptr[BO2 + LDA * 4]);
+ vmovups(ptr[AO1 + (unroll_m * 0 + 1 * 4 - OFFSET) * SIZE],
+ xmm1);
+ } else {
+ vxorps(xmm4, xmm4, xmm4);
+ lea(BO2, ptr[BO1 + LDA * 4]);
+
+ auto el_cp = [&](int section, int ld_step) {
+ RegExp src_addr = section == 0 ? BO1 : BO2;
+ if (ld_step == 1 || ld_step == 2)
+ src_addr = src_addr + LDA * ld_step;
+ else if (ld_step == 3)
+ src_addr = src_addr + CO1;
+ src_addr = src_addr - OFFSET * SIZE;
+
+ vmovss(xmm1, ptr[src_addr]);
+ RegExp dst_addr = AO1
+ + (ld_step + section * 4 - OFFSET) * SIZE;
+ movss(ptr[dst_addr], xmm1);
+ };
+
+ Label l_end;
+ el_cp(0, 0); cmp(M, 4 * 0 + 0 + 1); je(l_end, T_NEAR);
+ el_cp(0, 1); cmp(M, 4 * 0 + 1 + 1); je(l_end, T_NEAR);
+ el_cp(0, 2); cmp(M, 4 * 0 + 2 + 1); je(l_end, T_NEAR);
+ el_cp(0, 3); cmp(M, 4 * 0 + 3 + 1); je(l_end, T_NEAR);
+ el_cp(1, 0); cmp(M, 4 * 1 + 0 + 1); je(l_end, T_NEAR);
+ el_cp(1, 1); cmp(M, 4 * 1 + 1 + 1); je(l_end, T_NEAR);
+ el_cp(1, 2);
+ L(l_end);
+
+ lea(BO2, ptr[BO2 + LDA * 4]);
+ }
+
+ if (unroll_m >= 16) {
+ assert(is_avx2);
+ if (isLoad2Unmasked) {
+ for (int i = 0; i < 2; i++) {
+ vmovss(Xmm(i + 1),
+ ptr[BO2 + (0 * 8 - OFFSET) * SIZE]);
+ vmovss(xmm0, ptr[BO2 + LDA * 1
+ + (0 * 8 - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 2]);
+ vunpcklps(Xmm(i + 1), Xmm(i + 1), Xmm(0));
+ }
+ vunpcklpd(xmm1, xmm1, xmm2);
+ } else {
+ vmovaps(xmm4, xmm3);
+ vgatherqps(xmm1,
+ ptr[BO2 + ymm7 + (0 * 8 - OFFSET) * SIZE],
+ xmm4);
+ lea(BO2, ptr[BO2 + LDA * 4]);
+ }
+ vmovups(ptr[AO1 + (unroll_m * 0 + 2 * 4 - OFFSET) * SIZE],
+ xmm1);
+
+ if (isLoad2Unmasked) {
+ for (int i = 0; i < 2; i++) {
+ vmovss(Xmm(i + 1),
+ ptr[BO2 + (0 * 8 - OFFSET) * SIZE]);
+ vmovss(xmm0, ptr[BO2 + LDA * 1
+ + (0 * 8 - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDA * 2]);
+ vunpcklps(Xmm(i + 1), Xmm(i + 1), Xmm(0));
+ }
+ vunpcklpd(xmm1, xmm1, xmm2);
+ } else {
+ vextractf128(xmm4, ymm3, 1);
+ vgatherqps(xmm1,
+ ptr[BO2 + ymm7 + (0 * 8 - OFFSET) * SIZE],
+ xmm4);
+ }
+ vmovups(ptr[AO1 + (unroll_m * 0 + 3 * 4 - OFFSET) * SIZE],
+ xmm1);
+ }
+ add(BO1, SIZE);
+ }
+
+ add(AO1, unroll_m * SIZE);
+ sub(LL, 1);
+ jg(pack4, T_NEAR);
+ align(16);
+
+ L(pack10);
+ };
+
+ // Fused multiply add; may become one or two instructions
+ auto fma = [&](bool useFma, Ymm reg0, Ymm reg1, Ymm reg2,
+ bool overWrite = false) {
+ if (useFma) {
+ if (is_avx2) {
+ vfmadd231ps(reg2, reg1, reg0);
+ } else {
+ assert(UNROLL_M == 8);
+ auto tent_vreg = overWrite ? reg1 : ymm1;
+ vmulps(tent_vreg, reg1, reg0);
+ vaddps(reg2, reg2, tent_vreg);
+ }
+ } else {
+ if (!overWrite) {
+ vmulps(ymm15, reg1, reg0);
+ vaddps(reg2, reg2, ymm15);
+ } else {
+ vmulps(reg1, reg1, reg0);
+ vaddps(reg2, reg2, reg1);
+ }
+ }
+ };
+
+ // Inner kernel with k=8
+ auto innerkernel8 = [&](int unroll_m, int unroll_n,
+ bool isLoad1Unmasked, bool isLoad2Unmasked, bool isDirect,
+ bool isCopy, bool useFma, Ymm reg00, Ymm reg01, Ymm reg02,
+ Ymm reg03, Ymm reg04, Ymm reg05, Ymm reg06, Ymm reg07,
+ Ymm reg08, Ymm reg09, Ymm reg10, Ymm reg11, Ymm reg12,
+ Ymm reg13, Ymm reg14, Ymm reg15, Ymm reg16, Ymm reg17,
+ Ymm reg18, Ymm reg19, Ymm reg20, Ymm reg21, Ymm reg22,
+ Ymm reg23) {
+
+ Ymm fmareg;
+
+ if (!isDirect) {
+ prefetcht0(ptr[AO1 + (PREFETCHSIZEA + 0) * SIZE]);
+ } else {
+ prefetcht0(ptr[AO1 + LDA4]);
+ }
+
+ for (int i = 0; i < 8; i++) {
+ if (isDirect) {
+ if (isLoad1Unmasked) {
+ vmovups(ymm0, ptr[AO1 + (0 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm0, VMASK,
+ ptr[AO1 + (0 * 8 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 16) {
+ if (isLoad2Unmasked) {
+ vmovups(ymm1, ptr[AO1 + (1 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm1, VMASK,
+ ptr[AO1 + (1 * 8 - OFFSET) * SIZE]);
+ }
+ }
+ add(AO1, LDA);
+ }
+
+ if (!isTransB) {
+ vbroadcastss(ymm2, ptr[BO1 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg00 : reg12;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg06 : reg18;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ if (i == 0) {
+ if (!isTransB) {
+ prefetcht0(ptr[BO1 + PREFETCHSIZEB * SIZE]);
+ }
+ }
+ if (unroll_n >= 2) {
+ if (!isTransB) {
+ if (i == 1) {
+ prefetcht0(ptr[BO1 + LDB + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(
+ ymm2, ptr[BO1 + LDB * 1 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (1 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg01 : reg13;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg07 : reg19;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (isCopy) {
+ vmovups(ptr[LDA4 + (unroll_m * i + 0 * 8 - OFFSET) * SIZE],
+ ymm0);
+ if (unroll_m >= 16) {
+ vmovups(ptr[LDA4
+ + (unroll_m * i + 1 * 8 - OFFSET)
+ * SIZE],
+ ymm1);
+ }
+ if (i == 7) {
+ sub(LDA4, -unroll_m * 8 * SIZE);
+ }
+ }
+
+ if (unroll_n >= 3) {
+ if (!isTransB) {
+ if (i == 2) {
+ prefetcht0(
+ ptr[BO1 + LDB * 2 + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(
+ ymm2, ptr[BO1 + LDB * 2 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (2 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg02 : reg14;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg08 : reg20;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (i == 7) {
+ if (!isTransB) {
+ sub(BO1, -8 * SIZE);
+ }
+ }
+
+ if (unroll_n >= 4) {
+ if (!isTransB) {
+ if (i == 3) {
+ prefetcht0(ptr[BO2 + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(ymm2, ptr[BO2 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (3 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg03 : reg15;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg09 : reg21;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (unroll_n >= 5) {
+ if (!isTransB) {
+ if (i == 4) {
+ prefetcht0(ptr[BO2 + LDB + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(
+ ymm2, ptr[BO2 + LDB * 1 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (4 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg04 : reg16;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg10 : reg22;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (unroll_n >= 6) {
+ if (!isTransB) {
+ if (i == 5) {
+ prefetcht0(
+ ptr[BO2 + LDB * 2 + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(
+ ymm2, ptr[BO2 + LDB * 2 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (5 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg05 : reg17;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg11 : reg23;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+ if (isTransB) {
+ prefetcht0(ptr[BO1 + BO2]);
+ add(BO1, LDB);
+ }
+
+ if (i == 0) {
+ if (unroll_m >= 4) {
+ if (!isDirect) {
+ prefetcht0(
+ ptr[AO1 + (PREFETCHSIZEA + 2 * 8) * SIZE]);
+ } else {
+ prefetcht0(ptr[AO1 + LDA4]);
+ }
+ }
+ }
+ if (i == 1 || i == 2) {
+ if (unroll_m >= 8) {
+ if (!isDirect) {
+ prefetcht0(ptr[AO1
+ + (PREFETCHSIZEA + (2 + 2 * i) * 8)
+ * SIZE]);
+ } else {
+ prefetcht0(ptr[AO1 + LDA4]);
+ }
+ }
+ }
+ if (i == 3 || i == 4 || i == 5 || i == 6) {
+ if (unroll_m >= 16) {
+ if (!isDirect) {
+ prefetcht0(ptr[AO1
+ + (PREFETCHSIZEA + (2 + 2 * i) * 8)
+ * SIZE]);
+ } else {
+ prefetcht0(ptr[AO1 + LDA4]);
+ }
+ }
+ }
+ if (i == 7) {
+ if (!isTransB) {
+ if (unroll_n >= 4) {
+ sub(BO2, -8 * SIZE);
+ }
+ }
+ if (!isTransA) {
+ prefetcht2(ptr[AA]);
+ lea(AA, ptr[AA + LDA]);
+ }
+ }
+
+ if (!isDirect) {
+ if (isLoad1Unmasked) {
+ vmovups(ymm0,
+ ptr[AO1
+ + (unroll_m * (i + 1) + 0 * 8 - OFFSET)
+ * SIZE]);
+ } else {
+ vmaskmovps(
+ ymm0, VMASK,
+ ptr[AO1
+ + (unroll_m * (i + 1) + 0 * 8 - OFFSET)
+ * SIZE]);
+ }
+ if (unroll_m >= 16) {
+ if (isLoad2Unmasked) {
+ vmovups(ymm1, ptr[AO1
+ + (unroll_m * (i + 1) + 1 * 8
+ - OFFSET)
+ * SIZE]);
+ } else {
+ vmaskmovps(ymm1, VMASK,
+ ptr[AO1
+ + (unroll_m * (i + 1) + 1 * 8
+ - OFFSET)
+ * SIZE]);
+ }
+ }
+ }
+ }
+
+ if (!isDirect) {
+ sub(AO1, -unroll_m * 8 * SIZE);
+ }
+ sub(LL, 1);
+
+ };
+
+ // Inner kernel with k=4
+ auto innerkernel4 = [&](int unroll_m, int unroll_n,
+ bool isLoad1Unmasked, bool isLoad2Unmasked, bool isDirect,
+ bool isCopy, bool useFma, Ymm reg00, Ymm reg01, Ymm reg02,
+ Ymm reg03, Ymm reg04, Ymm reg05, Ymm reg06, Ymm reg07,
+ Ymm reg08, Ymm reg09, Ymm reg10, Ymm reg11, Ymm reg12,
+ Ymm reg13, Ymm reg14, Ymm reg15, Ymm reg16, Ymm reg17,
+ Ymm reg18, Ymm reg19, Ymm reg20, Ymm reg21, Ymm reg22,
+ Ymm reg23) {
+
+ Ymm fmareg;
+
+ if (!isDirect) {
+ prefetcht0(ptr[AO1 + (PREFETCHSIZEA + 0) * SIZE]);
+ } else {
+ prefetcht0(ptr[AO1 + LDA4]);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if (isDirect) {
+ if (isLoad1Unmasked) {
+ vmovups(ymm0, ptr[AO1 + (0 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm0, VMASK,
+ ptr[AO1 + (0 * 8 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 16) {
+ if (isLoad2Unmasked) {
+ vmovups(ymm1, ptr[AO1 + (1 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm1, VMASK,
+ ptr[AO1 + (1 * 8 - OFFSET) * SIZE]);
+ }
+ }
+ add(AO1, LDA);
+ }
+
+ if (!isTransB) {
+ vbroadcastss(ymm2, ptr[BO1 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg00 : reg12;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg06 : reg18;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ if (i == 0) {
+ if (!isTransB) {
+ prefetcht0(ptr[BO1 + PREFETCHSIZEB * SIZE]);
+ }
+ }
+ if (unroll_n >= 2) {
+ if (!isTransB) {
+ if (i == 1) {
+ prefetcht0(ptr[BO1 + LDB + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(
+ ymm2, ptr[BO1 + LDB * 1 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (1 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg01 : reg13;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg07 : reg19;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (isCopy) {
+ vmovups(ptr[LDA4 + (unroll_m * i + 0 * 8 - OFFSET) * SIZE],
+ ymm0);
+ if (unroll_m >= 16) {
+ vmovups(ptr[LDA4
+ + (unroll_m * i + 1 * 8 - OFFSET)
+ * SIZE],
+ ymm1);
+ }
+ if (i == 3) {
+ sub(LDA4, -unroll_m * 4 * SIZE);
+ }
+ }
+
+ if (unroll_n >= 3) {
+ if (!isTransB) {
+ if (i == 2) {
+ prefetcht0(
+ ptr[BO1 + LDB * 2 + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(
+ ymm2, ptr[BO1 + LDB * 2 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (2 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg02 : reg14;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg08 : reg20;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (i == 7) {
+ if (!isTransB) {
+ sub(BO1, -8 * SIZE);
+ }
+ }
+
+ if (unroll_n >= 4) {
+ if (!isTransB) {
+ if (i == 3) {
+ prefetcht0(ptr[BO2 + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(ymm2, ptr[BO2 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (3 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg03 : reg15;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg09 : reg21;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (unroll_n >= 5) {
+ if (!isTransB) {
+ if (i == 4) {
+ prefetcht0(ptr[BO2 + LDB + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(
+ ymm2, ptr[BO2 + LDB * 1 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (4 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg04 : reg16;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg10 : reg22;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (unroll_n >= 6) {
+ if (!isTransB) {
+ if (i == 5) {
+ prefetcht0(
+ ptr[BO2 + LDB * 2 + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(
+ ymm2, ptr[BO2 + LDB * 2 + (i - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (5 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg05 : reg17;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg11 : reg23;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+ if (isTransB) {
+ prefetcht0(ptr[BO1 + BO2]);
+ add(BO1, LDB);
+ }
+
+ if (i == 0) {
+ if (unroll_m >= 4) {
+ if (!isDirect) {
+ prefetcht0(
+ ptr[AO1 + (PREFETCHSIZEA + 2 * 8) * SIZE]);
+ } else {
+ prefetcht0(ptr[AO1 + LDA4]);
+ }
+ }
+ }
+ if (i == 1 || i == 2) {
+ if (unroll_m >= 8) {
+ if (!isDirect) {
+ prefetcht0(ptr[AO1
+ + (PREFETCHSIZEA + (2 + 2 * i) * 8)
+ * SIZE]);
+ } else {
+ prefetcht0(ptr[AO1 + LDA4]);
+ }
+ }
+ }
+ if (i == 3) {
+ if (!isTransB) {
+ sub(BO1, -4 * SIZE);
+ if (unroll_n >= 4) {
+ sub(BO2, -4 * SIZE);
+ }
+ }
+ }
+
+ if (!isDirect) {
+ if (isLoad1Unmasked) {
+ vmovups(ymm0,
+ ptr[AO1
+ + (unroll_m * (i + 1) + 0 * 8 - OFFSET)
+ * SIZE]);
+ } else {
+ vmaskmovps(
+ ymm0, VMASK,
+ ptr[AO1
+ + (unroll_m * (i + 1) + 0 * 8 - OFFSET)
+ * SIZE]);
+ }
+ if (unroll_m >= 16) {
+ if (isLoad2Unmasked) {
+ vmovups(ymm1, ptr[AO1
+ + (unroll_m * (i + 1) + 1 * 8
+ - OFFSET)
+ * SIZE]);
+ } else {
+ vmaskmovps(ymm1, VMASK,
+ ptr[AO1
+ + (unroll_m * (i + 1) + 1 * 8
+ - OFFSET)
+ * SIZE]);
+ }
+ }
+ }
+ }
+
+ if (!isDirect) {
+ sub(AO1, -unroll_m * 4 * SIZE);
+ }
+
+ };
+
+ // Inner kernel with k=2
+ auto innerkernel2 = [&](int unroll_m, int unroll_n,
+ bool isLoad1Unmasked, bool isLoad2Unmasked, bool isDirect,
+ bool isCopy, bool useFma, Ymm reg00, Ymm reg01, Ymm reg02,
+ Ymm reg03, Ymm reg04, Ymm reg05, Ymm reg06, Ymm reg07,
+ Ymm reg08, Ymm reg09, Ymm reg10, Ymm reg11, Ymm reg12,
+ Ymm reg13, Ymm reg14, Ymm reg15, Ymm reg16, Ymm reg17,
+ Ymm reg18, Ymm reg19, Ymm reg20, Ymm reg21, Ymm reg22,
+ Ymm reg23) {
+
+ Ymm fmareg;
+
+ for (int i = 0; i < 2; i++) {
+ if (isDirect) {
+ if (isLoad1Unmasked) {
+ vmovups(ymm0, ptr[AO1 + (0 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm0, VMASK,
+ ptr[AO1 + (0 * 8 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 16) {
+ if (isLoad2Unmasked) {
+ vmovups(ymm1, ptr[AO1 + (1 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm1, VMASK,
+ ptr[AO1 + (1 * 8 - OFFSET) * SIZE]);
+ }
+ }
+ add(AO1, LDA);
+ }
+
+ if (!isTransB) {
+ vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg00 : reg12;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg06 : reg18;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ if (unroll_n >= 2) {
+ if (!isTransB) {
+ vbroadcastss(
+ ymm2, ptr[BO1 + LDB * 1 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (1 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg01 : reg13;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg07 : reg19;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (unroll_n >= 3) {
+ if (!isTransB) {
+ if (i == 2) {
+ prefetcht0(
+ ptr[BO1 + LDB * 2 + PREFETCHSIZEB * SIZE]);
+ }
+ vbroadcastss(
+ ymm2, ptr[BO1 + LDB * 2 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (2 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg02 : reg14;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg08 : reg20;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (unroll_n >= 4) {
+ if (!isTransB) {
+ vbroadcastss(ymm2, ptr[BO2 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (3 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg03 : reg15;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg09 : reg21;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (unroll_n >= 5) {
+ if (!isTransB) {
+ vbroadcastss(
+ ymm2, ptr[BO2 + LDB * 1 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (4 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg04 : reg16;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg10 : reg22;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (unroll_n >= 6) {
+ if (!isTransB) {
+ vbroadcastss(
+ ymm2, ptr[BO2 + LDB * 2 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (5 - OFFSET) * SIZE]);
+ }
+ fmareg = (i % 2 == 0) ? reg05 : reg17;
+ fma(useFma, ymm0, ymm2, fmareg);
+ if (unroll_m >= 16) {
+ fmareg = (i % 2 == 0) ? reg11 : reg23;
+ fma(useFma, ymm1, ymm2, fmareg);
+ }
+ }
+
+ if (isCopy) {
+ vmovups(ptr[LDA4 + (unroll_m * 0 + 0 * 8 - OFFSET) * SIZE],
+ ymm0);
+ if (unroll_m >= 16) {
+ vmovups(ptr[LDA4
+ + (unroll_m * 0 + 1 * 8 - OFFSET)
+ * SIZE],
+ ymm1);
+ }
+ sub(LDA4, -unroll_m * SIZE);
+ }
+
+ if (!isDirect) {
+ if (isLoad1Unmasked) {
+ vmovups(ymm0, ptr[AO1
+ + (unroll_m * 1 + 0 * 8 - OFFSET)
+ * SIZE]);
+ } else {
+ vmaskmovps(ymm0, VMASK,
+ ptr[AO1
+ + (unroll_m * 1 + 0 * 8 - OFFSET)
+ * SIZE]);
+ }
+ if (unroll_m >= 16) {
+ if (isLoad2Unmasked) {
+ vmovups(ymm1,
+ ptr[AO1
+ + (unroll_m * 1 + 1 * 8 - OFFSET)
+ * SIZE]);
+ } else {
+ vmaskmovps(ymm1, VMASK,
+ ptr[AO1
+ + (unroll_m * 1 + 1 * 8 - OFFSET)
+ * SIZE]);
+ }
+ }
+ sub(AO1, -unroll_m * SIZE);
+ }
+
+ if (!isTransB) {
+ sub(BO1, -SIZE);
+ if (unroll_n >= 4) {
+ sub(BO2, -SIZE);
+ }
+ } else {
+ add(BO1, LDB);
+ }
+ }
+
+ };
+
+ // Inner kernel with k=1
+ auto innerkernel1 = [&](int unroll_m, int unroll_n,
+ bool isLoad1Unmasked, bool isLoad2Unmasked, bool isDirect,
+ bool isCopy, bool useFma, Ymm reg00, Ymm reg01, Ymm reg02,
+ Ymm reg03, Ymm reg04, Ymm reg05, Ymm reg06, Ymm reg07,
+ Ymm reg08, Ymm reg09, Ymm reg10, Ymm reg11) {
+
+ if (isDirect) {
+ if (isLoad1Unmasked) {
+ vmovups(ymm0, ptr[AO1 + (0 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm0, VMASK, ptr[AO1 + (0 * 8 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 16) {
+ if (isLoad2Unmasked) {
+ vmovups(ymm1, ptr[AO1 + (1 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm1, VMASK,
+ ptr[AO1 + (1 * 8 - OFFSET) * SIZE]);
+ }
+ }
+ add(AO1, LDA);
+ }
+
+ if (!isTransB) {
+ vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (0 - OFFSET) * SIZE]);
+ }
+ fma(useFma, ymm0, ymm2, reg00);
+ if (unroll_m >= 16) {
+ fma(useFma, ymm1, ymm2, reg06);
+ }
+
+ if (unroll_n >= 2) {
+ if (!isTransB) {
+ vbroadcastss(
+ ymm2, ptr[BO1 + LDB * 1 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (1 - OFFSET) * SIZE]);
+ }
+ fma(useFma, ymm0, ymm2, reg01);
+ if (unroll_m >= 16) {
+ fma(useFma, ymm1, ymm2, reg07);
+ }
+ }
+
+ if (unroll_n >= 3) {
+ if (!isTransB) {
+ vbroadcastss(
+ ymm2, ptr[BO1 + LDB * 2 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (2 - OFFSET) * SIZE]);
+ }
+ fma(useFma, ymm0, ymm2, reg02);
+ if (unroll_m >= 16) {
+ fma(useFma, ymm1, ymm2, reg08);
+ }
+ }
+
+ if (unroll_n >= 4) {
+ if (!isTransB) {
+ vbroadcastss(ymm2, ptr[BO2 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (3 - OFFSET) * SIZE]);
+ }
+ fma(useFma, ymm0, ymm2, reg03);
+ if (unroll_m >= 16) {
+ fma(useFma, ymm1, ymm2, reg09);
+ }
+ }
+
+ if (unroll_n >= 5) {
+ if (!isTransB) {
+ vbroadcastss(
+ ymm2, ptr[BO2 + LDB * 1 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (4 - OFFSET) * SIZE]);
+ }
+ fma(useFma, ymm0, ymm2, reg04);
+ if (unroll_m >= 16) {
+ fma(useFma, ymm1, ymm2, reg10);
+ }
+ }
+
+ if (unroll_n >= 6) {
+ if (!isTransB) {
+ vbroadcastss(
+ ymm2, ptr[BO2 + LDB * 2 + (0 - OFFSET) * SIZE]);
+ } else {
+ vbroadcastss(ymm2, ptr[BO1 + (5 - OFFSET) * SIZE]);
+ }
+ fma(useFma, ymm0, ymm2, reg05);
+ if (unroll_m >= 16) {
+ fma(useFma, ymm1, ymm2, reg11);
+ }
+ }
+
+ if (isCopy) {
+ vmovups(ptr[LDA4 + (unroll_m * 0 + 0 * 8 - OFFSET) * SIZE],
+ ymm0);
+ if (unroll_m >= 16) {
+ vmovups(ptr[LDA4 + (unroll_m * 0 + 1 * 8 - OFFSET) * SIZE],
+ ymm1);
+ }
+ sub(LDA4, -unroll_m * SIZE);
+ }
+
+ if (!isDirect) {
+ if (isLoad1Unmasked) {
+ vmovups(ymm0,
+ ptr[AO1 + (unroll_m * 1 + 0 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm0, VMASK,
+ ptr[AO1 + (unroll_m * 1 + 0 * 8 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 16) {
+ if (isLoad2Unmasked) {
+ vmovups(ymm1, ptr[AO1
+ + (unroll_m * 1 + 1 * 8 - OFFSET)
+ * SIZE]);
+ } else {
+ vmaskmovps(ymm1, VMASK,
+ ptr[AO1
+ + (unroll_m * 1 + 1 * 8 - OFFSET)
+ * SIZE]);
+ }
+ }
+ sub(AO1, -unroll_m * SIZE);
+ }
+
+ if (!isTransB) {
+ sub(BO1, -SIZE);
+ if (unroll_n >= 4) {
+ sub(BO2, -SIZE);
+ }
+ } else {
+ add(BO1, LDB);
+ }
+
+ };
+
+ // Main kernel; does prefetching and calls innerkernel{1,2,4,8} as
+ // appropriate
+ // After calculating results in registers, writes back to C matrix
+ auto kernel = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy, bool useFma,
+ Ymm reg00 = Ymm(4), Ymm reg01 = Ymm(5), Ymm reg02 = Ymm(6),
+ Ymm reg03 = Ymm(7), Ymm reg04 = Ymm(8), Ymm reg05 = Ymm(9),
+ Ymm reg06 = Ymm(10), Ymm reg07 = Ymm(11), Ymm reg08 = Ymm(12),
+ Ymm reg09 = Ymm(13), Ymm reg10 = Ymm(14), Ymm reg11 = Ymm(15),
+ Ymm reg12 = Ymm(4), Ymm reg13 = Ymm(5), Ymm reg14 = Ymm(6),
+ Ymm reg15 = Ymm(7), Ymm reg16 = Ymm(8), Ymm reg17 = Ymm(9),
+ Ymm reg18 = Ymm(10), Ymm reg19 = Ymm(11), Ymm reg20 = Ymm(12),
+ Ymm reg21 = Ymm(13), Ymm reg22 = Ymm(14), Ymm reg23 = Ymm(15)) {
+ if (!isDirect) {
+ lea(AO1, ptr[rsp + 256 + OFFSET * SIZE]);
+ } else {
+ mov(AO1, A);
+ }
+
+ if (isCopy) {
+ lea(LDA4, ptr[rsp + 256 + OFFSET * SIZE]);
+ } else {
+ lea(LDA4, ptr[LDA * 8 + (8 - 1 - OFFSET) * SIZE]);
+ }
+
+ if (isTransB) {
+ lea(BO2, ptr[LDB * 4 + (8 - 1 - OFFSET) * SIZE]);
+ lea(BO2, ptr[BO2 + LDB * 2]);
+ }
+
+ if (!isDirect) {
+ if (isLoad1Unmasked) {
+ vmovups(ymm0,
+ ptr[AO1 + (unroll_m * 0 + 0 * 8 - OFFSET) * SIZE]);
+ } else {
+ vmaskmovps(ymm0, VMASK,
+ ptr[AO1 + (unroll_m * 0 + 0 * 8 - OFFSET) * SIZE]);
+ }
+ if (unroll_m >= 16) {
+ if (isLoad2Unmasked) {
+ vmovups(ymm1, ptr[AO1
+ + (unroll_m * 0 + 1 * 8 - OFFSET)
+ * SIZE]);
+ } else {
+ vmaskmovps(ymm1, VMASK,
+ ptr[AO1
+ + (unroll_m * 0 + 1 * 8 - OFFSET)
+ * SIZE]);
+ }
+ }
+ }
+
+ for (int i = 4; i < 10; i++) {
+ vxorps(Ymm(i), Ymm(i), Ymm(i));
+ vxorps(Ymm(i + 6), Ymm(i + 6), Ymm(i + 6));
+ }
+
+ mov(LL, K);
+ sar(LL, 3);
+
+ Label kernel12, kernel13, kernel14, kernel15;
+ Label kernel16, kernel17, kernel18;
+
+ sub(LL, SECOND_FETCH);
+ jle(kernel13, T_NEAR);
+ align(16);
+
+ L(kernel12);
+ innerkernel8(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, useFma, reg00, reg01, reg02, reg03, reg04,
+ reg05, reg06, reg07, reg08, reg09, reg10, reg11, reg12,
+ reg13, reg14, reg15, reg16, reg17, reg18, reg19, reg20,
+ reg21, reg22, reg23);
+ jg(kernel12, T_NEAR);
+ align(16);
+
+ L(kernel13);
+ prefetcht0(ptr[CO1 + (unroll_m - 1) * SIZE]);
+ if (unroll_n >= 2)
+ prefetcht0(ptr[CO1 + LDC + (unroll_m - 1) * SIZE]);
+ if (unroll_n >= 3)
+ prefetcht0(ptr[CO1 + LDC * 2 + (unroll_m - 1) * SIZE]);
+ if (unroll_n >= 4)
+ prefetcht0(ptr[CO2 + (unroll_m - 1) * SIZE]);
+ if (unroll_n >= 5)
+ prefetcht0(ptr[CO2 + LDC + (unroll_m - 1) * SIZE]);
+ if (unroll_n >= 6)
+ prefetcht0(ptr[CO2 + LDC * 2 + (unroll_m - 1) * SIZE]);
+
+ add(LL, SECOND_FETCH);
+ jle(kernel15, T_NEAR);
+ align(16);
+
+ L(kernel14);
+ innerkernel8(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, useFma, reg00, reg01, reg02, reg03, reg04,
+ reg05, reg06, reg07, reg08, reg09, reg10, reg11, reg12,
+ reg13, reg14, reg15, reg16, reg17, reg18, reg19, reg20,
+ reg21, reg22, reg23);
+ jg(kernel14, T_NEAR);
+ align(16);
+
+ L(kernel15);
+ test(K, 4);
+ jle(kernel16, T_NEAR);
+ innerkernel4(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, useFma, reg00, reg01, reg02, reg03, reg04,
+ reg05, reg06, reg07, reg08, reg09, reg10, reg11, reg12,
+ reg13, reg14, reg15, reg16, reg17, reg18, reg19, reg20,
+ reg21, reg22, reg23);
+
+ L(kernel16);
+ test(K, 2);
+ jle(kernel17, T_NEAR);
+ innerkernel2(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, useFma, reg00, reg01, reg02, reg03, reg04,
+ reg05, reg06, reg07, reg08, reg09, reg10, reg11, reg12,
+ reg13, reg14, reg15, reg16, reg17, reg18, reg19, reg20,
+ reg21, reg22, reg23);
+ align(16);
+
+ L(kernel17);
+ if (unroll_m == 16) {
+ if (unroll_n <= 3) {
+ vaddps(reg00, reg00, reg12);
+ vaddps(reg01, reg01, reg13);
+ vaddps(reg02, reg02, reg14);
+ vaddps(reg06, reg06, reg18);
+ vaddps(reg07, reg07, reg19);
+ vaddps(reg08, reg08, reg20);
+ }
+ }
+
+ if (unroll_m <= 8) {
+ vaddps(reg00, reg00, reg12);
+ vaddps(reg01, reg01, reg13);
+ vaddps(reg02, reg02, reg14);
+ vaddps(reg03, reg03, reg15);
+ vaddps(reg04, reg04, reg16);
+ vaddps(reg05, reg05, reg17);
+ }
+
+ test(K, 1);
+ jle(kernel18, T_NEAR);
+ innerkernel1(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, useFma, reg00, reg01, reg02, reg03, reg04,
+ reg05, reg06, reg07, reg08, reg09, reg10, reg11);
+ align(16);
+
+ L(kernel18);
+ vbroadcastss(VALPHA, ALPHA);
+
+ if (isBetaN) {
+ vbroadcastss(VBETA, BETA);
+ }
+
+ // Write back the results; all beta and bias cases need to be
+ // handled
+ switch (unroll_n) {
+ case 1: mov(rax, LDC); break;
+ case 2: lea(rax, ptr[LDC * 2]); break;
+ case 3: lea(rax, ptr[LDC + LDC * 2]); break;
+ case 4: lea(rax, ptr[LDC + LDC * 4]); break;
+ case 5:
+ lea(rax, ptr[LDC * 4]);
+ add(rax, LDC);
+ break;
+ case 6:
+ lea(rax, ptr[LDC + LDC * 2]);
+ add(rax, rax);
+ break;
+ }
+
+ if (hasBias) {
+ mov(BIAS1, BIAS);
+ if (isLoad1Unmasked) {
+ vmovups(VBIAS1, ptr[BIAS1 + 0 * SIZE]);
+ } else {
+ vmaskmovps(VBIAS1, VMASK, ptr[BIAS1 + 0 * SIZE]);
+ }
+ }
+
+ for (int i = 0; i < unroll_n; i++) {
+ vmulps(Ymm(i + 4), Ymm(i + 4), VALPHA);
+ if (!isBeta0) {
+ if (isLoad1Unmasked) {
+ switch (i) {
+ case 0: vmovups(ymm0, ptr[CO1 + 0 * SIZE]); break;
+ case 1: vmovups(ymm0, ptr[CO1 + LDC + 0 * SIZE]); break;
+ case 2:
+ vmovups(ymm0, ptr[CO1 + LDC * 2 + 0 * SIZE]);
+ break;
+ case 3: vmovups(ymm0, ptr[CO2 + 0 * SIZE]); break;
+ case 4: vmovups(ymm0, ptr[CO2 + LDC + 0 * SIZE]); break;
+ case 5:
+ vmovups(ymm0, ptr[CO2 + LDC * 2 + 0 * SIZE]);
+ break;
+ }
+ } else {
+ switch (i) {
+ case 0:
+ vmaskmovps(ymm0, VMASK, ptr[CO1 + 0 * SIZE]);
+ break;
+ case 1:
+ vmaskmovps(ymm0, VMASK, ptr[CO1 + LDC + 0 * SIZE]);
+ break;
+ case 2:
+ vmaskmovps(
+ ymm0, VMASK, ptr[CO1 + LDC * 2 + 0 * SIZE]);
+ break;
+ case 3:
+ vmaskmovps(ymm0, VMASK, ptr[CO2 + 0 * SIZE]);
+ break;
+ case 4:
+ vmaskmovps(ymm0, VMASK, ptr[CO2 + LDC + 0 * SIZE]);
+ break;
+ case 5:
+ vmaskmovps(
+ ymm0, VMASK, ptr[CO2 + LDC * 2 + 0 * SIZE]);
+ break;
+ }
+ }
+
+ if (!isBetaN) {
+ vaddps(Ymm(i + 4), ymm0, Ymm(i + 4));
+ } else {
+ fma(useFma, VBETA, ymm0, Ymm(i + 4), true);
+ }
+ }
+ if (hasBias) {
+ vaddps(Ymm(i + 4), VBIAS1, Ymm(i + 4));
+ }
+ if (isLoad1Unmasked) {
+ switch (i) {
+ case 0: vmovups(ptr[CO1 + 0 * SIZE], Ymm(i + 4)); break;
+ case 1:
+ vmovups(ptr[CO1 + LDC + 0 * SIZE], Ymm(i + 4));
+ break;
+ case 2:
+ vmovups(ptr[CO1 + LDC * 2 + 0 * SIZE], Ymm(i + 4));
+ break;
+ case 3: vmovups(ptr[CO2 + 0 * SIZE], Ymm(i + 4)); break;
+ case 4:
+ vmovups(ptr[CO2 + LDC + 0 * SIZE], Ymm(i + 4));
+ break;
+ case 5:
+ vmovups(ptr[CO2 + LDC * 2 + 0 * SIZE], Ymm(i + 4));
+ break;
+ }
+ } else {
+ switch (i) {
+ case 0:
+ vmaskmovps(ptr[CO1 + 0 * SIZE], VMASK, Ymm(i + 4));
+ break;
+ case 1:
+ vmaskmovps(
+ ptr[CO1 + LDC + 0 * SIZE], VMASK, Ymm(i + 4));
+ break;
+ case 2:
+ vmaskmovps(ptr[CO1 + LDC * 2 + 0 * SIZE], VMASK,
+ Ymm(i + 4));
+ break;
+ case 3:
+ vmaskmovps(ptr[CO2 + 0 * SIZE], VMASK, Ymm(i + 4));
+ break;
+ case 4:
+ vmaskmovps(
+ ptr[CO2 + LDC + 0 * SIZE], VMASK, Ymm(i + 4));
+ break;
+ case 5:
+ vmaskmovps(ptr[CO2 + LDC * 2 + 0 * SIZE], VMASK,
+ Ymm(i + 4));
+ break;
+ }
+ }
+
+ if (unroll_m >= 16) {
+ // Re-use ymm4 (VBIAS2)
+ if (i == 0) {
+ if (hasBias) {
+ if (isLoad1Unmasked) {
+ vmovups(VBIAS2, ptr[BIAS1 + 8 * SIZE]);
+ } else {
+ vmaskmovps(
+ VBIAS2, VMASK, ptr[BIAS1 + 8 * SIZE]);
+ }
+ }
+ }
+ vmulps(Ymm(i + 10), Ymm(i + 10), VALPHA);
+ if (!isBeta0) {
+ if (isLoad2Unmasked) {
+ switch (i) {
+ case 0: vmovups(ymm0, ptr[CO1 + 8 * SIZE]); break;
+ case 1:
+ vmovups(ymm0, ptr[CO1 + LDC + 8 * SIZE]);
+ break;
+ case 2:
+ vmovups(ymm0, ptr[CO1 + LDC * 2 + 8 * SIZE]);
+ break;
+ case 3: vmovups(ymm0, ptr[CO2 + 8 * SIZE]); break;
+ case 4:
+ vmovups(ymm0, ptr[CO2 + LDC + 8 * SIZE]);
+ break;
+ case 5:
+ vmovups(ymm0, ptr[CO2 + LDC * 2 + 8 * SIZE]);
+ break;
+ }
+ } else {
+ switch (i) {
+ case 0:
+ vmaskmovps(ymm0, VMASK, ptr[CO1 + 8 * SIZE]);
+ break;
+ case 1:
+ vmaskmovps(
+ ymm0, VMASK, ptr[CO1 + LDC + 8 * SIZE]);
+ break;
+ case 2:
+ vmaskmovps(ymm0, VMASK,
+ ptr[CO1 + LDC * 2 + 8 * SIZE]);
+ break;
+ case 3:
+ vmaskmovps(ymm0, VMASK, ptr[CO2 + 8 * SIZE]);
+ break;
+ case 4:
+ vmaskmovps(
+ ymm0, VMASK, ptr[CO2 + LDC + 8 * SIZE]);
+ break;
+ case 5:
+ vmaskmovps(ymm0, VMASK,
+ ptr[CO2 + LDC * 2 + 8 * SIZE]);
+ break;
+ }
+ }
+ if (!isBetaN) {
+ vaddps(Ymm(i + 10), ymm0, Ymm(i + 10));
+ } else {
+ fma(useFma, VBETA, ymm0, Ymm(i + 10), true);
+ }
+ }
+ if (hasBias) {
+ vaddps(Ymm(i + 10), VBIAS2, Ymm(i + 10));
+ }
+ if (isLoad2Unmasked) {
+ switch (i) {
+ case 0:
+ vmovups(ptr[CO1 + 8 * SIZE], Ymm(i + 10));
+ break;
+ case 1:
+ vmovups(ptr[CO1 + LDC + 8 * SIZE], Ymm(i + 10));
+ break;
+ case 2:
+ vmovups(ptr[CO1 + LDC * 2 + 8 * SIZE], Ymm(i + 10));
+ break;
+ case 3:
+ vmovups(ptr[CO2 + 8 * SIZE], Ymm(i + 10));
+ break;
+ case 4:
+ vmovups(ptr[CO2 + LDC + 8 * SIZE], Ymm(i + 10));
+ break;
+ case 5:
+ vmovups(ptr[CO2 + LDC * 2 + 8 * SIZE], Ymm(i + 10));
+ break;
+ }
+ } else {
+ switch (i) {
+ case 0:
+ vmaskmovps(ptr[CO1 + 8 * SIZE], VMASK, Ymm(i + 10));
+ break;
+ case 1:
+ vmaskmovps(ptr[CO1 + LDC + 8 * SIZE], VMASK,
+ Ymm(i + 10));
+ break;
+ case 2:
+ vmaskmovps(ptr[CO1 + LDC * 2 + 8 * SIZE], VMASK,
+ Ymm(i + 10));
+ break;
+ case 3:
+ vmaskmovps(ptr[CO2 + 8 * SIZE], VMASK, Ymm(i + 10));
+ break;
+ case 4:
+ vmaskmovps(ptr[CO2 + LDC + 8 * SIZE], VMASK,
+ Ymm(i + 10));
+ break;
+ case 5:
+ vmaskmovps(ptr[CO2 + LDC * 2 + 8 * SIZE], VMASK,
+ Ymm(i + 10));
+ break;
+ }
+ }
+ }
+ if (i == 2)
+ add(CO1, rax);
+ }
+ if (unroll_n >= 4) {
+ add(CO2, rax);
+ }
+
+ // Compute next address of B
+ if (!isTransB) {
+ lea(rax, ptr[K * SIZE]);
+ switch (unroll_n) {
+ case 1:
+ add(BO1, LDB);
+ add(BO2, LDB);
+ break;
+ case 2:
+ lea(BO1, ptr[BO1 + LDB * 2]);
+ lea(BO2, ptr[BO2 + LDB * 2]);
+ break;
+ case 3:
+ lea(BO1, ptr[BO1 + LDB3]);
+ lea(BO2, ptr[BO2 + LDB3]);
+ break;
+ case 4:
+ lea(BO1, ptr[BO1 + LDB * 4]);
+ lea(BO2, ptr[BO2 + LDB * 4]);
+ break;
+ case 5:
+ lea(BO1, ptr[BO1 + LDB * 4]);
+ add(BO1, LDB);
+ lea(BO2, ptr[BO2 + LDB * 4]);
+ add(BO2, LDB);
+ break;
+ case 6:
+ lea(BO1, ptr[BO1 + LDB3 * 2]);
+ lea(BO2, ptr[BO2 + LDB3 * 2]);
+ break;
+ }
+ sub(BO1, rax);
+ sub(BO2, rax);
+ } else {
+ mov(rax, LDB);
+ imul(rax, K);
+ sub(BO1, rax);
+ add(BO1, unroll_n * SIZE);
+ }
+ };
+
+ auto kernel_16x6 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy) {
+ kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, true);
+ };
+
+ auto kernel_16x5 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy) {
+ kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, true);
+ };
+
+ auto kernel_16x4 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy) {
+ kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, true);
+ };
+
+ auto kernel_16x3 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy,
+ bool useFma = true) {
+ kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, useFma, Ymm(4), Ymm(5), Ymm(6), Ymm(7),
+ Ymm(8), Ymm(9), Ymm(10), Ymm(11), Ymm(12), Ymm(13), Ymm(14),
+ Ymm(15), Ymm(7), Ymm(8), Ymm(9), Ymm(7), Ymm(8), Ymm(9),
+ Ymm(13), Ymm(14), Ymm(15));
+ };
+
+ auto kernel_16x2 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy) {
+ kernel_16x3(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, false);
+ };
+
+ auto kernel_16x1 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy) {
+ kernel_16x3(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, false);
+ };
+
+ auto kernel_8x6 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy,
+ bool useFma = true) {
+ kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, useFma, Ymm(4), Ymm(5), Ymm(6), Ymm(7),
+ Ymm(8), Ymm(9), Ymm(10), Ymm(11), Ymm(12), Ymm(13), Ymm(14),
+ Ymm(15), Ymm(10), Ymm(11), Ymm(12), Ymm(13), Ymm(14),
+ Ymm(15));
+ };
+
+ auto kernel_8x5 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy) {
+ kernel_8x6(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy);
+ };
+
+ auto kernel_8x4 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy) {
+ kernel_8x6(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy);
+ };
+
+ auto kernel_8x3 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy,
+ bool useFma = true) {
+ kernel(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, useFma, Ymm(4), Ymm(5), Ymm(6), Ymm(7),
+ Ymm(8), Ymm(9), Ymm(10), Ymm(11), Ymm(12), Ymm(13), Ymm(14),
+ Ymm(15), Ymm(7), Ymm(8), Ymm(9), Ymm(7), Ymm(8), Ymm(9),
+ Ymm(13), Ymm(14), Ymm(15));
+ };
+
+ auto kernel_8x2 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy) {
+ kernel_8x3(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, false);
+ };
+
+ auto kernel_8x1 = [&](int unroll_m, int unroll_n, bool isLoad1Unmasked,
+ bool isLoad2Unmasked, bool isDirect, bool isCopy) {
+ kernel_8x3(unroll_m, unroll_n, isLoad1Unmasked, isLoad2Unmasked,
+ isDirect, isCopy, false);
+ };
+
+ // High-level subroutine; does packing if needed, then splits C matrix.
+ // Operates on chunks of 16 rows, 6 columns at a time (handling tail
+ // cases appropriately).
+ // Masking is used for tail cases where M is not divisible by 8.
+ auto subloop = [&](
+ int unroll_m, bool isLoad1Unmasked, bool isLoad2Unmasked) {
+ if (isTransA) {
+ do_pack(unroll_m, isLoad1Unmasked, isLoad2Unmasked);
+ }
+
+ Label subloop11, subloop11mask;
+ Label subloop20, subloop21, subloop22, subloop23;
+ Label subloop24, subloop25;
+ Label subloop30, subloop31, subloop32, subloop33;
+ Label subloop34, subloop35;
+ Label subloop98, subloop98mask;
+ Label subloop99, subloop99mask;
+
+ mov(CO1, C);
+ lea(CO2, ptr[CO1 + LDC * 2]);
+ add(CO2, LDC);
+ add(C, unroll_m * SIZE);
+ mov(BO1, B);
+ if (!isTransB) {
+ lea(BO2, qword[B + LDB3]);
+ }
+
+ if (!isTransA) {
+ lea(AA, ptr[A + (unroll_m * 2 - 1 - OFFSET) * SIZE]);
+ cmp(M, UNROLL_M);
+ jg(subloop98, T_NEAR);
+
+ mov(AA, ORIG_A);
+ lea(AA, ptr[AA + (unroll_m - 1 - OFFSET) * SIZE]);
+ L(subloop98);
+ }
+
+ mov(LL, N);
+ mov(I, LL);
+ if (!isTransA) {
+ // If N is too small, skip copy operation
+ cmp(LL, UNROLL_N * 3);
+ jle(subloop30, T_NEAR);
+
+ // If A is not aligned to cache line
+ cmp(FLAG, 0);
+ je(subloop30, T_NEAR);
+ } else {
+ cmp(LL, UNROLL_N);
+ jl(subloop20, T_NEAR);
+ }
+ align(16);
+
+ if (!isTransA) {
+ if (unroll_m == 16) {
+ kernel_16x6(unroll_m, UNROLL_N, isLoad1Unmasked,
+ isLoad2Unmasked, true, true);
+ } else {
+ kernel_8x6(unroll_m, UNROLL_N, isLoad1Unmasked,
+ isLoad2Unmasked, true, true);
+ }
+ } else {
+ if (unroll_m == 16) {
+ kernel_16x6(unroll_m, UNROLL_N, isLoad1Unmasked,
+ isLoad2Unmasked, false, false);
+ } else {
+ kernel_8x6(unroll_m, UNROLL_N, isLoad1Unmasked,
+ isLoad2Unmasked, false, false);
+ }
+ }
+
+ sub(I, UNROLL_N);
+ cmp(I, UNROLL_N);
+ jl(subloop20, T_NEAR);
+ align(16);
+
+ L(subloop11);
+ if (unroll_m == 16) {
+ kernel_16x6(unroll_m, UNROLL_N, isLoad1Unmasked,
+ isLoad2Unmasked, false, false);
+ } else {
+ kernel_8x6(unroll_m, UNROLL_N, isLoad1Unmasked, isLoad2Unmasked,
+ false, false);
+ }
+ sub(I, UNROLL_N);
+ cmp(I, UNROLL_N);
+ jge(subloop11, T_NEAR);
+ align(16);
+
+ L(subloop20);
+ cmp(I, 1);
+ jne(subloop21, T_NEAR);
+ if (unroll_m == 16) {
+ kernel_16x1(unroll_m, 1, isLoad1Unmasked, isLoad2Unmasked,
+ false, false);
+ } else {
+ kernel_8x1(unroll_m, 1, isLoad1Unmasked, isLoad2Unmasked, false,
+ false);
+ }
+ jmp(subloop99, T_NEAR);
+ align(16);
+
+ L(subloop21);
+ cmp(I, 2);
+ jne(subloop22, T_NEAR);
+ if (unroll_m == 16) {
+ kernel_16x2(unroll_m, 2, isLoad1Unmasked, isLoad2Unmasked,
+ false, false);
+ } else {
+ kernel_8x2(unroll_m, 2, isLoad1Unmasked, isLoad2Unmasked, false,
+ false);
+ }
+ jmp(subloop99, T_NEAR);
+ align(16);
+
+ L(subloop22);
+ cmp(I, 3);
+ jne(subloop23, T_NEAR);
+ if (unroll_m == 16) {
+ kernel_16x3(unroll_m, 3, isLoad1Unmasked, isLoad2Unmasked,
+ false, false);
+ } else {
+ kernel_8x3(unroll_m, 3, isLoad1Unmasked, isLoad2Unmasked, false,
+ false);
+ }
+ jmp(subloop99, T_NEAR);
+ align(16);
+
+ L(subloop23);
+ cmp(I, 4);
+ jne(subloop24, T_NEAR);
+ if (unroll_m == 16) {
+ kernel_16x4(unroll_m, 4, isLoad1Unmasked, isLoad2Unmasked,
+ false, false);
+ } else {
+ kernel_8x4(unroll_m, 4, isLoad1Unmasked, isLoad2Unmasked, false,
+ false);
+ }
+ jmp(subloop99, T_NEAR);
+ align(16);
+
+ L(subloop24);
+ cmp(I, 5);
+ jne(subloop99, T_NEAR);
+ if (unroll_m == 16) {
+ kernel_16x5(unroll_m, 5, isLoad1Unmasked, isLoad2Unmasked,
+ false, false);
+ } else {
+ kernel_8x5(unroll_m, 5, isLoad1Unmasked, isLoad2Unmasked, false,
+ false);
+ }
+ jmp(subloop99, T_NEAR);
+ align(16);
+
+ if (!isTransA) {
+ L(subloop30);
+ cmp(I, UNROLL_N);
+ jl(subloop25, T_NEAR);
+ align(16);
+
+ L(subloop31);
+ if (unroll_m == 16) {
+ kernel_16x6(unroll_m, UNROLL_N, isLoad1Unmasked,
+ isLoad2Unmasked, true, false);
+ } else {
+ kernel_8x6(unroll_m, UNROLL_N, isLoad1Unmasked,
+ isLoad2Unmasked, true, false);
+ }
+ sub(I, UNROLL_N);
+ cmp(I, UNROLL_N);
+ jge(subloop31, T_NEAR);
+ align(16);
+
+ L(subloop25);
+ cmp(I, 1);
+ jne(subloop32, T_NEAR);
+ if (unroll_m == 16) {
+ kernel_16x1(unroll_m, 1, isLoad1Unmasked, isLoad2Unmasked,
+ true, false);
+ } else {
+ kernel_8x1(unroll_m, 1, isLoad1Unmasked, isLoad2Unmasked,
+ true, false);
+ }
+ jmp(subloop99, T_NEAR);
+ align(16);
+
+ L(subloop32);
+ cmp(I, 2);
+ jne(subloop33, T_NEAR);
+ if (unroll_m == 16) {
+ kernel_16x2(unroll_m, 2, isLoad1Unmasked, isLoad2Unmasked,
+ true, false);
+ } else {
+ kernel_8x2(unroll_m, 2, isLoad1Unmasked, isLoad2Unmasked,
+ true, false);
+ }
+ jmp(subloop99, T_NEAR);
+ align(16);
+
+ L(subloop33);
+ cmp(I, 3);
+ jne(subloop34, T_NEAR);
+ if (unroll_m == 16) {
+ kernel_16x3(unroll_m, 3, isLoad1Unmasked, isLoad2Unmasked,
+ true, false);
+ } else {
+ kernel_8x3(unroll_m, 3, isLoad1Unmasked, isLoad2Unmasked,
+ true, false);
+ }
+ jmp(subloop99, T_NEAR);
+ align(16);
+
+ L(subloop34);
+ cmp(I, 4);
+ jne(subloop35, T_NEAR);
+ if (unroll_m == 16) {
+ kernel_16x4(unroll_m, 4, isLoad1Unmasked, isLoad2Unmasked,
+ true, false);
+ } else {
+ kernel_8x4(unroll_m, 4, isLoad1Unmasked, isLoad2Unmasked,
+ true, false);
+ }
+ jmp(subloop99, T_NEAR);
+ align(16);
+
+ L(subloop35);
+ cmp(I, 5);
+ jne(subloop99, T_NEAR);
+ if (unroll_m == 16) {
+ kernel_16x5(unroll_m, 5, isLoad1Unmasked, isLoad2Unmasked,
+ true, false);
+ } else {
+ kernel_8x5(unroll_m, 5, isLoad1Unmasked, isLoad2Unmasked,
+ true, false);
+ }
+ align(16);
+ }
+
+ L(subloop99);
+ // Compute address for A
+ if (!isTransA) {
+ add(A, unroll_m * SIZE);
+ } else {
+ mov(rax, LDA);
+ imul(rax, rax, unroll_m);
+ add(A, rax);
+ }
+
+ // Compute next address of BIAS
+ if (hasBias) {
+ add(BIAS, unroll_m * SIZE);
+ }
+ };
+
+ preamble();
+
+ Label buffer_in_ws, buffer_allocated;
+
+ // Get the registers
+ mov(B, ARG_B);
+ mov(LDB, ARG_LDB);
+ mov(r15, ARG_BETA);
+ mov(r12, ARG_C);
+ if (hasBias)
+ mov(r10, ARG_BIAS);
+ mov(LDC, ARG_LDC);
+ mov(rbp, rsp);
+
+ vmovss(xmm0, ptr[ARG_ALPHA]);
+ vmovss(xmm1, ptr[r15]);
+
+#if _WIN32
+ mov(A, ARG_A);
+ mov(LDA, ARG_LDA);
+#endif
+
+ cmp(K, STACK_K_CAPACITY);
+ jg(buffer_in_ws, T_NEAR);
+
+ // Create buffer and align to 4kB page
+ lea(rax, ptr[K * SIZE]);
+ sal(rax, 4);
+ add(rax, 256);
+ sub(rsp, rax);
+ and_(rsp, -PAGE_4K);
+ jmp(buffer_allocated, T_NEAR);
+
+ L(buffer_in_ws);
+ mov(rsp, ARG_WS);
+
+ L(buffer_allocated);
+
+ mov(ORIG_SP, rbp);
+ mov(M, ARG_M);
+ mov(N, ARG_N);
+ mov(C, r12);
+ if (hasBias)
+ mov(BIAS, r10);
+ vmovss(ALPHA, xmm0);
+ vmovss(BETA, xmm1);
+ sub(A, -OFFSET * SIZE);
+ sub(B, -OFFSET * SIZE);
+ mov(ORIG_A, A);
+ sal(LDA, BASE_SHIFT);
+ sal(LDB, BASE_SHIFT);
+ sal(LDC, BASE_SHIFT);
+ lea(LDB3, ptr[LDB + LDB * 2]);
+
+ for (int i = 0; i < 8; i++) {
+ mov(dword[rsp + 88 + i * 4], i);
+ }
+
+ if (isTransA && is_avx2) {
+ movq(xmm0, LDA);
+ vpbroadcastq(ymm1, xmm0);
+ vinsertf128(ymm0, ymm0, xmm0, 1);
+ vpermilpd(ymm0, ymm0, 5);
+ vpaddq(ymm1, ymm1, ymm1);
+ vperm2f128(ymm1, ymm1, ymm1, 8);
+ vpaddq(ymm0, ymm0, ymm1);
+ vmovups(STRIDE, ymm0);
+ }
+
+ // Check A alignment and leading dimension; take copy-based path as
+ // needed
+ mov(rax, LDA);
+ or_(rax, A);
+ and_(rax, 0x1f);
+ mov(FLAG, rax);
+
+ Label main0, main1, main2, main3, main999;
+
+ cmp(M, UNROLL_M);
+ jl(main0, T_NEAR);
+ align(16);
+
+ L(main1);
+ subloop(UNROLL_M, true, true);
+ sub(M, UNROLL_M);
+ cmp(M, UNROLL_M);
+ jge(main1, T_NEAR);
+ align(16);
+
+ L(main0);
+ cmp(M, 0);
+ jle(main999, T_NEAR);
+
+ if (UNROLL_M > 8) {
+ cmp(M, 8);
+ jle(main2, T_NEAR);
+
+ sub(M, 8);
+ vbroadcastss(VMASK, M);
+ vpcmpgtd(VMASK, VMASK, MASK);
+
+ subloop(16, true, false);
+ jmp(main999, T_NEAR);
+ align(16);
+
+ L(main2);
+ cmp(M, 8);
+ jne(main3, T_NEAR);
+ subloop(8, true, true);
+ jmp(main999, T_NEAR);
+ }
+
+ align(16);
+
+ L(main3);
+ vbroadcastss(VMASK, M);
+ if (is_avx2) {
+ vpcmpgtd(VMASK, VMASK, MASK);
+ } else {
+ auto xmask = Xmm(VMASK.getIdx());
+ auto xmm_tmp = xmm4;
+
+ vextractf128(xmm_tmp, VMASK, 1);
+ vpcmpgtd(xmask, xmask, MASK);
+ vpcmpgtd(xmm_tmp, xmm_tmp, dword[rsp + 88 + 4 * 4]); // MASK + 4
+ vinsertf128(VMASK, VMASK, xmm_tmp, 1);
+ }
+ subloop(8, false, false);
+ align(16);
+
+ L(main999);
+ // Restore original stack
+ mov(rsp, ORIG_SP);
+
+ vzeroupper();
+ postamble();
+
+ ker_ = this->getCode<ker_t>();
+ }
+
+ typedef void (*ker_t)(dim_t m, dim_t n, dim_t k,
+ const float *alpha, const float *a, dim_t lda,
+ const float *b, dim_t ldb, const float *beta, float *c,
+ dim_t ldc, const float *bias, float *ws);
+
+ void operator()(dim_t m, dim_t n, dim_t k,
+ const float *alpha, const float *a, dim_t lda,
+ const float *b, dim_t ldb, const float *beta, float *c,
+ dim_t ldc, const float *bias, float *ws) const
+ {
+ ker_(m, n, k, alpha, a, lda, b, ldb, beta, c, ldc, bias, ws);
+ }
+
+private:
+ ker_t ker_;
+};
+
+const xbyak_gemm *get_xbyak_gemm(
+ bool isTransA, bool isTransB, float beta, bool hasBias) {
+ auto beta_idx = [](float beta) {
+ return (beta == 0.0) ? 0 : (beta == 1.0 ? 1 : 2);
+ };
+
+ // Kernel table [isTransA][isTransB][hasBias][beta (0, 1, other)]
+ static xbyak_gemm *kernel_table[2][2][2][3];
+ static std::once_flag initialized;
+ std::call_once(initialized, [=]{
+ for (bool isTransA: {false, true})
+ for (bool isTransB: {false, true})
+ for (bool hasBias: {false, true})
+ for (float beta: {0.0f, 1.0f, 2.0f}) {
+ // nocopy sgemm with bias for beta != 0.0 is not supported
+ if (hasBias && beta != 0.0)
+ continue;
+ kernel_table[isTransA][isTransB][hasBias][beta_idx(beta)] =
+ new xbyak_gemm(isTransA, isTransB, beta, hasBias);
+ }
+ });
+
+ return kernel_table[isTransA][isTransB][hasBias][beta_idx(beta)];
+}
+
+void sgemm_nocopy_driver(const char *transa,
+ const char *transb, int m, int n, int k, const float *alpha,
+ const float *a, dim_t lda, const float *b, dim_t ldb, const float *beta,
+ float *c, dim_t ldc, const float *bias, float *ws)
+{
+ bool isTransA = (*transa == 'T' || *transa == 't');
+ bool isTransB = (*transb == 'T' || *transb == 't');
+
+ int Bm, sizeM, Bn, sizeN, Bk, sizeK;
+
+ int i, j;
+
+ if ((m <= 0) || (n <= 0))
+ return;
+
+ if ((k <= 0) || (alpha[0] == 0.)) {
+
+ if (beta[0] == 0.) {
+ for (j = 0; j < n; j++)
+ for (i = 0; i < m; i++)
+ c[i + j * ldc] = 0.0;
+ } else if (beta[0] != 1.) {
+ for (j = 0; j < n; j++)
+ for (i = 0; i < m; i++)
+ c[i + j * ldc] *= beta[0];
+ }
+
+ return;
+ }
+
+ assert(IMPLICATION(bias != nullptr, *beta == 0.0));
+
+ // XXX: this happens on every thread...
+ bool hasBias = (bias != nullptr);
+ auto ker_bn = get_xbyak_gemm(isTransA, isTransB, *beta, hasBias);
+ auto ker_b1 = get_xbyak_gemm(isTransA, isTransB, 1.0, false);
+ auto ker_b0 = get_xbyak_gemm(isTransA, isTransB, 0.0, false);
+ assert(ker_bn && ker_b1 && ker_b0);
+
+ int BM = 4032;
+ int BN = isTransA ? 96 : 48;
+ int BK = isTransB ? 96 : 256;
+ const float *curA, *curB, *curBias = nullptr;
+ float *curC;
+
+ for (Bk = 0; Bk < k; Bk += sizeK) {
+ sizeK = k - Bk;
+ if (sizeK >= BK * 2)
+ sizeK = BK;
+ else {
+ if (sizeK > BK)
+ sizeK = (sizeK + 1) / 2;
+ }
+
+ for (Bm = 0; Bm < m; Bm += sizeM) {
+ sizeM = m - Bm;
+ if (sizeM >= BM * 2)
+ sizeM = BM;
+ else {
+ if (sizeM > BM + BM / 2)
+ sizeM = (sizeM + 1) / 2;
+ }
+
+ for (Bn = 0; Bn < n; Bn += sizeN) {
+ sizeN = n - Bn;
+ if (sizeN >= BN * 2)
+ sizeN = BN;
+ else {
+ if (sizeN > BN + BN / 2)
+ sizeN = (sizeN + 1) / 2;
+ }
+
+ if (!isTransA) {
+ curA = a + Bm + Bk * lda;
+ } else {
+ curA = a + Bk + Bm * lda;
+ }
+ if (!isTransB) {
+ curB = b + Bk + Bn * ldb;
+ } else {
+ curB = b + Bn + Bk * ldb;
+ }
+ curC = c + Bm + (size_t)Bn * ldc;
+ if (bias != nullptr) {
+ if (Bk == 0) {
+ curBias = bias + Bm;
+ } else {
+ curBias = nullptr;
+ }
+ }
+ if (Bk == 0) {
+ if (*beta == 0.0 && bias == nullptr)
+ (*ker_b0)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK,
+ alpha, curA, lda, curB, ldb, beta, curC, ldc,
+ curBias, ws);
+ else
+ (*ker_bn)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK,
+ alpha, curA, lda, curB, ldb, beta, curC, ldc,
+ curBias, ws);
+ } else {
+ (*ker_b1)((dim_t)sizeM, (dim_t)sizeN, (dim_t)sizeK,
+ alpha, curA, lda, curB, ldb, beta, curC, ldc,
+ curBias, ws);
+ }
+ }
+ }
+ }
+}
+
+}
+
+mkldnn_status_t jit_avx_gemm_f32(
+ const char *transa, const char *transb,
+ const int *p_m, const int *p_n, const int *p_k, const float *p_alpha,
+ const float *A, const int *p_lda, const float *B, const int *p_ldb,
+ const float *p_beta, float *C, const int *p_ldc, const float *bias)
+{
+ using namespace mkldnn::impl::utils;
+ using namespace avx_gemm_f32;
+ using namespace gemm_utils;
+
+ if (*p_beta != 0 && bias)
+ return ref_gemm(transa, transb, p_m, p_n, p_k,
+ p_alpha, A, p_lda, B, p_lda, p_beta, C, p_ldc, bias);
+
+ int nthr = (mkldnn_in_parallel()) ? 1 : mkldnn_get_max_threads();
+
+ int m = *p_m;
+ int n = *p_n;
+ int k = *p_k;
+ dim_t lda = *p_lda;
+ dim_t ldb = *p_ldb;
+ dim_t ldc = *p_ldc;
+ float beta = *p_beta;
+ int MB, NB, KB;
+
+ int nthr_m, nthr_n, nthr_k, nthr_mn;
+
+ // Determine threading partitioning
+ calc_nthr_nocopy_avx(
+ m, n, k, nthr, &nthr_m, &nthr_n, &nthr_k, &MB, &NB, &KB);
+ assert(IMPLICATION(!mkldnn_thr_syncable(), nthr_k == 1));
+
+ // May not happen, but just in case
+ if (nthr < nthr_m * nthr_n * nthr_k)
+ nthr = nthr_m * nthr_n * nthr_k;
+
+ nthr_mn = nthr_m * nthr_n;
+
+ unsigned char * ompstatus_ = nullptr;
+ unsigned char volatile *ompstatus = nullptr;
+
+ float *c_buffers = nullptr;
+ float *ws_buffers = nullptr;
+
+ if (nthr_k > 1) {
+ ompstatus_ = (unsigned char *) malloc(
+ nthr * CACHE_LINE_SIZE,
+ CACHE_LINE_SIZE);
+ ompstatus = (unsigned char volatile *) ompstatus_;
+ assert(ompstatus);
+
+ for (int i = 0; i < nthr; i++)
+ ompstatus[i * CACHE_LINE_SIZE] = 0;
+
+ c_buffers = (float *)malloc(nthr_m * nthr_n * (nthr_k - 1) * MB * NB
+ * sizeof(float), PAGE_4K);
+ }
+
+ const size_t ws_elems_per_thr = (size_t)k * 16 + 64;
+ const size_t ws_size_per_thr
+ = rnd_up(ws_elems_per_thr * sizeof(float), PAGE_4K);
+ if (k > STACK_K_CAPACITY) {
+ ws_buffers = (float *)malloc(nthr * ws_size_per_thr, PAGE_4K);
+ }
+
+ parallel_nd(nthr, [&](const int ithr) {
+ int ithr_m, ithr_n, ithr_k, ithr_mn;
+ int m_from, m_to, myM;
+ int n_from, n_to, myN;
+ int k_from, k_to, myK;
+ int cbase, ibase;
+ const float *myA, *myB, *myBias = nullptr;
+ float *myC = C, myBeta;
+ float *ws = ws_buffers ?
+ ws_buffers + ithr * ws_size_per_thr / sizeof(float) : 0;
+ dim_t ld = ldc;
+
+ int sum_later = (mkldnn_get_num_threads() < nthr_m * nthr_n * nthr_k);
+
+ if (ithr < nthr_m * nthr_n * nthr_k) {
+
+ ithr_mn = ithr % nthr_mn;
+ ithr_m = ithr_mn % nthr_m;
+ ithr_n = ithr_mn / nthr_m;
+ ithr_k = ithr / nthr_mn;
+
+ /* swap ithr_k for performance improvement */
+ if (ithr_k == 0)
+ ithr_k = nthr_k - 1;
+ else if (ithr_k == nthr_k - 1)
+ ithr_k = 0;
+
+ m_from = MB * (ithr_m);
+ m_to = MB * (ithr_m + 1);
+ if (m_to > m)
+ m_to = m;
+ myM = m_to - m_from;
+
+ n_from = NB * (ithr_n);
+ n_to = NB * (ithr_n + 1);
+ if (n_to > n)
+ n_to = n;
+ myN = n_to - n_from;
+
+ k_from = KB * (ithr_k);
+ k_to = KB * (ithr_k + 1);
+ if (k_to > k)
+ k_to = k;
+ myK = k_to - k_from;
+
+ cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1);
+ ibase = (ithr_m + nthr_m * ithr_n) * nthr_k;
+
+ if ((myM > 0) && (myN > 0)) {
+
+ if (*transa == 'N' || *transa == 'n') {
+ myA = &(A[m_from + k_from * lda]);
+ } else {
+ myA = &(A[k_from + m_from * lda]);
+ }
+ if (*transb == 'N' || *transb == 'n') {
+ myB = &(B[k_from + n_from * ldb]);
+ } else {
+ myB = &(B[n_from + k_from * ldb]);
+ }
+ if (ithr_k == 0) {
+ myC = &(C[m_from + n_from * ldc]);
+ myBeta = beta;
+ ld = ldc;
+ if (bias)
+ myBias = &(bias[m_from]);
+ } else {
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1);
+ myBeta = 0.0;
+ ld = MB;
+ myBias = nullptr;
+ }
+
+ sgemm_nocopy_driver(transa, transb, myM, myN, myK, p_alpha, myA,
+ lda, myB, ldb, &myBeta, myC, ld, myBias, ws);
+
+ if (nthr_k > 1 && !sum_later)
+ ompstatus[(ibase + ithr_k) * CACHE_LINE_SIZE] = 1;
+ }
+
+ if (nthr_k > 1 && !sum_later) {
+
+ // sum matrices partitioned along K dimension
+ int n1, n2;
+
+ partition_unit_diff(ithr_k, nthr_k, myN, &n1, &n2);
+
+ if (ithr_k > 0) {
+
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1)
+ + (dim_t)n1 * MB;
+ /* need to wait until main thread finishes */
+ while (ompstatus[ibase * CACHE_LINE_SIZE] != 1) {
+ };
+
+ /* my cache is hot */
+ sum_two_matrices(myM, n2, myC, MB,
+ &C[m_from + (n_from + n1) * ldc], ldc);
+ }
+
+ for (int ik = 1; ik < nthr_k; ++ik) {
+ if (ik != ithr_k) {
+
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ik - 1)
+ + (dim_t)n1 * MB;
+
+ while (ompstatus[(ibase + ik) * CACHE_LINE_SIZE] != 1) {
+ };
+
+ sum_two_matrices(myM, n2, myC, MB,
+ &C[m_from + (n_from + n1) * ldc], ldc);
+ }
+ }
+ }
+ }
+ });
+
+ // handle C summation later
+ if (nthr_k > 1 && ompstatus[0] == 0) {
+
+ parallel_nd(nthr, [&](const int ithr) {
+ int ithr_m, ithr_n, ithr_k, ithr_mn;
+ int m_from, m_to, myM;
+ int n_from, n_to, myN;
+ int cbase;
+ float *myC = C;
+
+ if (ithr < nthr_m * nthr_n * nthr_k) {
+
+ ithr_mn = ithr % nthr_mn;
+ ithr_m = ithr_mn % nthr_m;
+ ithr_n = ithr_mn / nthr_m;
+ ithr_k = ithr / nthr_mn;
+
+ /* swap ithr_k for performance improvement */
+ if (ithr_k == 0)
+ ithr_k = nthr_k - 1;
+ else if (ithr_k == nthr_k - 1)
+ ithr_k = 0;
+
+ m_from = MB * (ithr_m);
+ m_to = MB * (ithr_m + 1);
+ if (m_to > m)
+ m_to = m;
+ myM = m_to - m_from;
+
+ n_from = NB * (ithr_n);
+ n_to = NB * (ithr_n + 1);
+ if (n_to > n)
+ n_to = n;
+ myN = n_to - n_from;
+
+ cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1);
+
+ if (nthr_k > 1) {
+ // sum matrices partitioned along K dimension
+ int n1, n2;
+
+ partition_unit_diff(ithr_k, nthr_k, myN, &n1, &n2);
+
+ if (ithr_k > 0) {
+
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1)
+ + (dim_t)n1 * MB;
+
+ /* my cache is hot */
+ sum_two_matrices(myM, n2, myC, MB,
+ &C[m_from + (n_from + n1) * ldc], ldc);
+ }
+
+ for (int ik = 1; ik < nthr_k; ++ik) {
+ if (ik != ithr_k) {
+
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ik - 1)
+ + (dim_t)n1 * MB;
+
+ sum_two_matrices(myM, n2, myC, MB,
+ &C[m_from + (n_from + n1) * ldc], ldc);
+ }
+ }
+ }
+ }
+ });
+ }
+
+
+ free(c_buffers);
+ free(ompstatus_);
+ free(ws_buffers);
+
+ return mkldnn_success;
+}
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.hpp
new file mode 100644
index 0000000000..aabf520a3c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/jit_avx_gemm_f32.hpp
@@ -0,0 +1,37 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_AVX_GEMM_F32_HPP
+#define JIT_AVX_GEMM_F32_HPP
+
+#include "mkldnn_types.h"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+mkldnn_status_t jit_avx_gemm_f32(
+ const char *transa, const char *transb, const int *M,
+ const int *N, const int *K, const float *alpha, const float *A,
+ const int *lda, const float *B, const int *ldb, const float *beta,
+ float *C, const int *ldc, const float *bias = nullptr);
+
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.cpp
new file mode 100644
index 0000000000..5147885a89
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.cpp
@@ -0,0 +1,346 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn_types.h"
+
+#include "mkldnn_thread.hpp"
+#include "nstl.hpp"
+#include "utils.hpp"
+
+#include "jit_generator.hpp"
+
+#include "gemm_utils_f32.hpp"
+#include "ref_gemm_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::utils;
+using namespace gemm_utils;
+
+namespace {
+
+template <typename data_t>
+void copy_A(
+ bool isTransA, int K, const data_t *A, const dim_t lda, data_t *ws) {
+ for (int k = 0; k < K; k++) {
+ PRAGMA_OMP_SIMD()
+ for (int i = 0; i < unroll_factor<data_t>::m; i++) {
+ ws[i] = isTransA ? A[i * lda + k] : A[i + k * lda];
+ }
+ ws += unroll_factor<data_t>::m;
+ }
+}
+
+template <typename data_t, bool isTransA, bool isTransB>
+void kernel_mxn(int K, const data_t *A, const dim_t lda,
+ const data_t *B, const dim_t ldb, data_t *C, const dim_t ldc,
+ const data_t alpha, const data_t beta) {
+ data_t c[unroll_factor<data_t>::m * unroll_factor<data_t>::n] =
+ { static_cast<data_t>(0.) };
+ for (int k = 0; k < K; k++) {
+ for (int j = 0; j < unroll_factor<data_t>::n; j++) {
+ data_t b = isTransB ? B[j + k * ldb] : B[k + j * ldb];
+ PRAGMA_OMP_SIMD()
+ for (int i = 0; i < unroll_factor<data_t>::m; i++) {
+ data_t a = isTransA ? A[i * lda + k] : A[i + lda * k];
+ c[i + unroll_factor<data_t>::m * j] += a * b;
+ }
+ }
+ }
+ for (int j = 0; j < unroll_factor<data_t>::n; j++) {
+ PRAGMA_OMP_SIMD()
+ for (int i = 0; i < unroll_factor<data_t>::m; i++) {
+ C[i + j * ldc] = (beta == static_cast<data_t>(0.))
+ ? alpha * c[i + unroll_factor<data_t>::m * j]
+ : alpha * c[i + unroll_factor<data_t>::m * j]
+ + beta * C[i + j * ldc];
+ }
+ }
+}
+
+template <typename data_t, bool isTransA, bool isTransB>
+void block_ker(const int M, const int N, const int K,
+ const data_t *A, const dim_t lda, const data_t *B, const dim_t ldb,
+ data_t *C, const dim_t ldc, const data_t alpha, const data_t beta,
+ data_t *ws, bool do_copy) {
+ int Nu = rnd_dn(N, unroll_factor<data_t>::n);
+ int Mu = rnd_dn(M, unroll_factor<data_t>::m);
+ for (int i = 0; i < Mu; i += unroll_factor<data_t>::m) {
+ for (int j = 0; j < Nu; j += unroll_factor<data_t>::n) {
+ const data_t *b = isTransB ? &B[j] : &B[j * ldb];
+ const data_t *a = isTransA ? &A[i * lda] : &A[i];
+ if (do_copy) {
+ if (j == 0) {
+ copy_A<data_t>(isTransA, K, a, lda, ws);
+ }
+ kernel_mxn<data_t, false, isTransB>(
+ K, ws, unroll_factor<data_t>::m, b, ldb,
+ &C[i + j * ldc], ldc, alpha, beta);
+ } else {
+ kernel_mxn<data_t, isTransA, isTransB>(
+ K, a, lda, b, ldb, &C[i + j * ldc], ldc, alpha, beta);
+ }
+ }
+ }
+ // tail processing
+ for (int i = 0; i < M; i++) {
+ for (int j = Nu; j < N; j++) {
+ data_t c = beta == static_cast<data_t>(0.)
+ ? static_cast<data_t>(0.)
+ : beta * C[i + j * ldc];
+ for (int p = 0; p < K; p++) {
+ data_t b = isTransB ? B[j + p * ldb] : B[p + j * ldb];
+ data_t a = isTransA ? A[p + i * lda] : A[i + p * lda];
+ c += alpha * a * b;
+ }
+ C[i + j * ldc] = c;
+ }
+ }
+ for (int i = Mu; i < M; i++) {
+ for (int j = 0; j < Nu; j++) {
+ data_t c = beta == static_cast<data_t>(0.)
+ ? static_cast<data_t>(0.)
+ : beta * C[i + j * ldc];
+ for (int p = 0; p < K; p++) {
+ data_t b = isTransB ? B[j + p * ldb] : B[p + j * ldb];
+ data_t a = isTransA ? A[p + i * lda] : A[i + p * lda];
+ c += alpha * a * b;
+ }
+ C[i + j * ldc] = c;
+ }
+ }
+}
+
+template <typename data_t, bool isTransA, bool isTransB>
+void gemm_ithr(const int M, const int N, const int K, const data_t alpha,
+ const data_t *A, const dim_t lda, const data_t *B, const dim_t ldb,
+ const data_t beta, data_t *C, const dim_t ldc, bool do_copy,
+ data_t *ws) {
+ constexpr int BM = gemm_traits<data_t, isTransA, isTransB>::BM;
+ constexpr int BN = gemm_traits<data_t, isTransA, isTransB>::BN;
+ constexpr int BK = gemm_traits<data_t, isTransA, isTransB>::BK;
+
+ const data_t *curA;
+ const data_t *curB;
+ data_t *curC;
+
+ if ((M <= 0) || (N <= 0))
+ return;
+
+ if ((K <= 0) || (alpha == static_cast<data_t>(0))) {
+ dim_t MN = N * M;
+ if (beta == static_cast<data_t>(0.)) {
+ for (dim_t j = 0; j < MN; j++)
+ C[j] = static_cast<data_t>(0.);
+ } else if (beta != static_cast<data_t>(1.)) {
+ for (dim_t j = 0; j < MN; j++)
+ C[j] *= beta;
+ }
+ return;
+ }
+
+ for (int Bk = 0; Bk < K; Bk += BK) {
+ int kb = nstl::min(K - Bk, BK);
+ for (int Bm = 0; Bm < M; Bm += BM) {
+ int mb = nstl::min(M - Bm, BM);
+ for (int Bn = 0; Bn < N; Bn += BN) {
+ int nb = nstl::min(N - Bn, BN);
+ curA = isTransA ? A + Bk + Bm * lda : A + Bm + Bk * lda;
+ curB = isTransB ? B + Bn + Bk * ldb : B + Bk + Bn * ldb;
+ curC = C + Bm + Bn * ldc;
+ if (Bk == 0) {
+ block_ker<data_t, isTransA, isTransB>(mb, nb, kb, curA, lda,
+ curB, ldb, curC, ldc, alpha, beta, ws, do_copy);
+ } else {
+ block_ker<data_t, isTransA, isTransB>(mb, nb, kb, curA, lda,
+ curB, ldb, curC, ldc, alpha, static_cast<data_t>(1.0),
+ ws, do_copy);
+ }
+ }
+ }
+ }
+}
+
+}
+
+template <typename data_t>
+mkldnn_status_t ref_gemm(
+ const char *transa_, const char *transb_, const int *M_,
+ const int *N_, const int *K_, const data_t *alpha_, const data_t *A,
+ const int *lda_, const data_t *B, const int *ldb_, const data_t *beta_,
+ data_t *C, const int *ldc_, const data_t *bias) {
+
+ bool isTransA = (*transa_ == 'T' || *transa_ == 't');
+ bool isTransB = (*transb_ == 'T' || *transb_ == 't');
+ const int M = *M_, N = *N_, K = *K_;
+ const dim_t lda = *lda_, ldb = *ldb_, ldc = *ldc_;
+ const data_t alpha = *alpha_, beta = *beta_;
+
+ int max_nthr = mkldnn_in_parallel() ? 1 : mkldnn_get_max_threads();
+ int nthr_m, nthr_n, nthr_k;
+ int MB, NB, KB;
+ // thread balancing over M, N, K & size of blocking dimensions
+ calc_nthr_nocopy_avx(
+ M, N, K, max_nthr, &nthr_m, &nthr_n, &nthr_k, &MB, &NB, &KB);
+ assert(IMPLICATION(!mkldnn_thr_syncable(), nthr_k == 1));
+
+ data_t *c_buffers = nullptr;
+ data_t *ws_buffers = nullptr;
+ if (nthr_k > 1) {
+ c_buffers = (data_t *)malloc(nthr_m * nthr_n * (nthr_k - 1) * MB * NB
+ * sizeof(data_t), PAGE_4K);
+ if (!c_buffers) {
+ nthr_k = 1;
+ KB = K;
+ }
+ }
+
+ bool do_copy = (NB / unroll_factor<data_t>::n > 3);
+ const int nthr_mn = nthr_m * nthr_n;
+ const int nthr = nthr_mn * nthr_k;
+ const size_t ws_elems_per_thr = K * unroll_factor<data_t>::m;
+ const size_t ws_size_per_thr
+ = rnd_up(ws_elems_per_thr * sizeof(data_t), PAGE_4K);
+ if (do_copy) {
+ ws_buffers = (data_t*)malloc(nthr * ws_size_per_thr, PAGE_4K);
+ if (!ws_buffers)
+ do_copy = false;
+ }
+
+ auto get_thr_block = [&](int &from, int &to, int &myN, int NB, int N,
+ int ithr) {
+ from = NB * (ithr);
+ to = NB * (ithr + 1);
+ if (to > N)
+ to = N;
+ myN = to - from;
+ };
+
+ parallel_nd(nthr, [&](const int ithr) {
+ int ithr_mn = ithr % nthr_mn;
+ int ithr_m = ithr_mn % nthr_m;
+ int ithr_n = ithr_mn / nthr_m;
+ int ithr_k = ithr / nthr_mn;
+
+ int cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1);
+
+ data_t *ws = do_copy
+ ? ws_buffers + ithr * ws_size_per_thr / sizeof(data_t)
+ : nullptr;
+
+ int m_from = 0, m_to = 0, myM = 0, n_from = 0, n_to = 0, myN = 0,
+ k_from = 0, k_to = 0, myK = 0;
+
+ get_thr_block(m_from, m_to, myM, MB, M, ithr_m);
+ get_thr_block(n_from, n_to, myN, NB, N, ithr_n);
+ get_thr_block(k_from, k_to, myK, KB, K, ithr_k);
+
+ if (myM > 0 && myN > 0) {
+ data_t myBeta, *myC;
+ dim_t ld;
+ if (ithr_k == 0) {
+ myC = &(C[m_from + n_from * ldc]);
+ myBeta = beta;
+ ld = ldc;
+ } else {
+ myC = c_buffers + (dim_t)MB * NB * (cbase + ithr_k - 1);
+ myBeta = 0.0f;
+ ld = MB;
+ }
+ const data_t *myA = isTransA
+ ? &(A[k_from + m_from * lda])
+ : &(A[m_from + k_from * lda]);
+ const data_t *myB = isTransB
+ ? &(B[n_from + k_from * ldb])
+ : &(B[k_from + n_from * ldb]);
+
+ if (!isTransA) {
+ if (!isTransB) {
+ gemm_ithr<data_t, false, false>(myM, myN, myK, alpha, myA,
+ lda, myB, ldb, myBeta, myC, ld, do_copy, ws);
+ } else {
+ gemm_ithr<data_t, false, true>(myM, myN, myK, alpha, myA,
+ lda, myB, ldb, myBeta, myC, ld, do_copy, ws);
+ }
+ } else {
+ if (!isTransB) {
+ gemm_ithr<data_t, true, false>(myM, myN, myK, alpha, myA,
+ lda, myB, ldb, myBeta, myC, ld, do_copy, ws);
+ } else {
+ gemm_ithr<data_t, true, true>(myM, myN, myK, alpha, myA,
+ lda, myB, ldb, myBeta, myC, ld, do_copy, ws);
+ }
+ }
+ }
+ });
+
+ if (nthr_k > 1) {
+ parallel_nd(nthr, [&](const int ithr) {
+ int ithr_mn = ithr % nthr_mn;
+ int ithr_m = ithr_mn % nthr_m;
+ int ithr_k = ithr / nthr_mn;
+ int ithr_n = ithr_mn / nthr_m;
+
+ int n_from = 0, n_to = 0, myN = 0;
+ int m_from = 0, m_to = 0, myM = 0;
+
+ int cbase = (ithr_m + nthr_m * ithr_n) * (nthr_k - 1);
+
+ get_thr_block(n_from, n_to, myN, NB, N, ithr_n);
+ get_thr_block(m_from, m_to, myM, MB, M, ithr_m);
+
+ // sum matrices partitioned along K dimension
+ int offset = 0, block = 0;
+ gemm_utils::partition_unit_diff(ithr_k, nthr_k, myN, &offset,
+ &block);
+ for (int ik = 1; ik < nthr_k; ++ik) {
+ data_t *myC = c_buffers
+ + MB * ((dim_t)NB * (cbase + ik - 1) + offset);
+
+ gemm_utils::sum_two_matrices(myM, block, myC, MB,
+ &C[m_from + (n_from + offset) * ldc], ldc);
+ }
+ });
+ }
+
+ if (bias) {
+ parallel_nd(N, M, [&](int i, int j) {
+ C[i*ldc + j] += bias[j];
+ });
+ }
+
+ free(ws_buffers);
+ free(c_buffers);
+
+ return mkldnn_success;
+}
+
+template mkldnn_status_t ref_gemm<float>(
+ const char *transa_, const char *transb_,
+ const int *M_, const int *N_, const int *K_, const float *alpha_,
+ const float *A, const int *lda_, const float *B, const int *ldb_,
+ const float *beta_, float *C, const int *ldc_, const float *bias);
+
+template mkldnn_status_t ref_gemm<double>(
+ const char *transa_, const char *transb_,
+ const int *M_, const int *N_, const int *K_, const double *alpha_,
+ const double *A, const int *lda_, const double *B, const int *ldb_,
+ const double *beta_, double *C, const int *ldc_, const double *bias);
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.hpp
new file mode 100644
index 0000000000..7c90ba6277
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/f32/ref_gemm_f32.hpp
@@ -0,0 +1,36 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef REF_GEMM_F32_HPP
+#define REF_GEMM_F32_HPP
+
+#include "mkldnn_types.h"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <typename data_t>
+mkldnn_status_t ref_gemm(const char *transa, const char *transb, const int *M,
+ const int *N, const int *K, const data_t *alpha, const data_t *A,
+ const int *lda, const data_t *B, const int *ldb, const data_t *beta,
+ data_t *C, const int *ldc, const data_t *bias);
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.cpp
new file mode 100644
index 0000000000..3dbe07d743
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.cpp
@@ -0,0 +1,280 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn.h"
+
+#include "mkldnn_traits.hpp"
+#include "nstl.hpp"
+
+#include "jit_generator.hpp"
+
+#include "gemm.hpp"
+
+#include "f32/jit_avx512_common_gemm_f32.hpp"
+#include "f32/jit_avx_gemm_f32.hpp"
+#include "f32/ref_gemm_f32.hpp"
+
+#include "s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp"
+#include "s8x8s32/simple_gemm_s8s8s32.hpp"
+#include "s8x8s32/ref_gemm_s8x8s32.hpp"
+
+#include "os_blas.hpp"
+
+/* USE_MKL USE_CBLAS effect
+ * ------- --------- ------
+ * yes yes use Intel(R) MKL CBLAS
+ * yes no use jit
+ * no yes system-dependent CBLAS
+ * no no use jit
+ */
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+mkldnn_status_t check_gemm_input(const char *transa, const char *transb,
+ const int *M, const int *N, const int *K, const int *lda,
+ const int *ldb, const int *ldc, const float *alpha, const float *beta,
+ const bool with_bias) {
+ if (utils::any_null(transa, transb, M, N, K, lda, ldb, ldc, alpha, beta))
+ return mkldnn_invalid_arguments;
+ if (with_bias && *beta != 0)
+ return mkldnn_unimplemented;
+ bool consistency = true
+ && utils::one_of(*transa, 'T', 't', 'N', 'n')
+ && utils::one_of(*transb, 'T', 't', 'N', 'n')
+ && *M >= 0
+ && *N >= 0
+ && *K >= 0;
+
+ if (!consistency)
+ return mkldnn_invalid_arguments;
+ bool isTransA = utils::one_of(*transa, 'T', 't');
+ bool isTransB = utils::one_of(*transb, 'T', 't');
+ int nrowA = isTransA ? *K : *M;
+ int nrowB = isTransB ? *N : *K;
+ consistency = true
+ && *lda >= nstl::max(1, nrowA)
+ && *ldb >= nstl::max(1, nrowB)
+ && *ldc >= nstl::max(1, *M);
+ if (!consistency)
+ return mkldnn_invalid_arguments;
+
+ return mkldnn_success;
+}
+
+mkldnn_status_t check_gemm_x8x8x32_input(const char *offsetc,
+ const char *transa, const char *transb, const int *M, const int *N,
+ const int *K, const int *lda, const int *ldb, const int *ldc,
+ const float *alpha, const float *beta, const bool with_bias) {
+ if (offsetc == nullptr)
+ return mkldnn_invalid_arguments;
+ if (!utils::one_of(*offsetc, 'F', 'f', 'C', 'c', 'R', 'r'))
+ return mkldnn_invalid_arguments;
+
+ return check_gemm_input(transa, transb, M, N, K, lda, ldb, ldc, alpha,
+ beta, with_bias);
+}
+
+mkldnn_status_t extended_sgemm(const char *transa, const char *transb,
+ const int *M, const int *N, const int *K, const float *alpha,
+ const float *A, const int *lda, const float *B, const int *ldb,
+ const float *beta, float *C, const int *ldc,
+ const float *bias, const bool force_jit_gemm) {
+ mkldnn_status_t status = check_gemm_input(transa, transb, M, N, K,
+ lda, ldb, ldc, alpha, beta, bias != nullptr);
+ if (status != mkldnn_success)
+ return status;
+
+#ifdef USE_CBLAS
+ if (!force_jit_gemm) {
+ bool trA = *transa == 't' || *transa == 'T';
+ bool trB = *transb == 't' || *transb == 'T';
+ CBLAS_TRANSPOSE Cblas_trA = trA ? CblasTrans : CblasNoTrans;
+ CBLAS_TRANSPOSE Cblas_trB = trB ? CblasTrans : CblasNoTrans;
+ cblas_sgemm(CblasColMajor, Cblas_trA, Cblas_trB,
+ *M, *N, *K, *alpha, A, *lda, B, *ldb, *beta, C, *ldc);
+
+ if (bias) {
+ // Add bias if necessary (bias is applied to columns of C)
+ cblas_int incx = 1, incy = 1;
+ parallel_nd(*N, [&](int n) {
+ ptrdiff_t offset = (ptrdiff_t)n * (*ldc);
+ cblas_saxpy(*M, 1.0, bias, incx, C + offset, incy);
+ });
+ }
+ return mkldnn_success;
+ }
+#endif
+
+ if (mayiuse(avx512_common))
+ return jit_avx512_common_gemm_f32(transa, transb,
+ M, N, K, alpha, A, lda, B, ldb, beta, C, ldc, bias);
+ else if (mayiuse(avx))
+ return jit_avx_gemm_f32(transa, transb,
+ M, N, K, alpha, A, lda, B, ldb, beta, C, ldc, bias);
+ else
+ return ref_gemm<float>(transa, transb,
+ M, N, K, alpha, A, lda, B, ldb, beta, C, ldc, bias);
+}
+
+template <typename b_dt>
+mkldnn_status_t gemm_s8x8s32(const char *transa, const char *transb,
+ const char *offsetc, const int *M, const int *N, const int *K,
+ const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao,
+ const b_dt *B, const int *LDB, const int8_t *bo, const float *beta,
+ int32_t *C, const int *LDC, const int32_t *co) {
+ mkldnn_status_t status = check_gemm_x8x8x32_input(offsetc, transa, transb,
+ M, N, K, LDA, LDB, LDC, alpha, beta, false);
+ if (status != mkldnn_success)
+ return status;
+
+ if (*M == 0 || *N == 0 || *K == 0)
+ return mkldnn_success;
+
+#if USE_MKL_IGEMM
+ bool OCisR = (*offsetc == 'R' || *offsetc == 'r');
+ bool OCisC = (*offsetc == 'C' || *offsetc == 'c');
+ bool AisN = (*transa == 'N' || *transa == 'n');
+ bool BisN = (*transb == 'N' || *transb == 'n');
+
+ if (data_traits<b_dt>::data_type == data_type::u8) {
+ CBLAS_TRANSPOSE Cblas_trA = AisN ? CblasNoTrans : CblasTrans;
+ CBLAS_TRANSPOSE Cblas_trB = BisN ? CblasNoTrans : CblasTrans;
+ CBLAS_OFFSET Cblas_offsetc =
+ OCisR
+ ? CblasRowOffset
+ : OCisC
+ ? CblasColOffset
+ : CblasFixOffset;
+ cblas_gemm_s8u8s32(CblasColMajor, Cblas_trA, Cblas_trB, Cblas_offsetc,
+ *M, *N, *K, *alpha, A, *LDA, *ao, (uint8_t *)B, *LDB, *bo,
+ *beta, C, *LDC, co);
+ return mkldnn_success;
+ } else {
+ assert(data_traits<b_dt>::data_type == data_type::s8);
+ // TODO CBLAS implementation of gemm_s8s8s32 goes here.
+ // mkldnn_gemm_s8s8s32 doesn't support non-zero ao and bo
+ if (utils::everyone_is(0, *ao, *bo)) {
+ return simple_gemm_s8s8s32(transa, transb, offsetc, M,
+ N, K, alpha, A, LDA, ao, (int8_t *)B, LDB, bo, beta,
+ C, LDC, co);
+ } else {
+ return ref_gemm_s8x8s32(transa, transb, offsetc, M, N, K,
+ alpha, A, LDA, ao, B, LDB, bo, beta, C, LDC, co);
+ }
+ }
+#else
+ cpu_isa_t isa = isa_any;
+ if (mayiuse(avx512_core_vnni)) {
+ isa = avx512_core_vnni;
+ } else if (mayiuse(avx512_core)) {
+ isa = avx512_core;
+ }
+
+ if (data_traits<b_dt>::data_type == data_type::u8) {
+ switch (isa) {
+ case avx512_core:
+ case avx512_core_vnni:
+ return jit_avx512_core_gemm_s8u8s32(transa, transb, offsetc, M,
+ N, K, alpha, A, LDA, ao, (uint8_t *)B, LDB, bo, beta,
+ C, LDC, co);
+ default:
+ return ref_gemm_s8x8s32(transa, transb, offsetc, M, N, K,
+ alpha, A, LDA, ao, B, LDB, bo, beta, C, LDC, co);
+ }
+ } else {
+ assert(data_traits<b_dt>::data_type == data_type::s8);
+ // mkldnn_gemm_s8s8s32 doesn't support non-zero ao and bo
+ if ((mayiuse(avx512_core) || mayiuse(avx512_core_vnni))
+ && *ao == 0 && *bo == 0) {
+ return simple_gemm_s8s8s32(transa, transb, offsetc, M,
+ N, K, alpha, A, LDA, ao, (int8_t *)B, LDB, bo, beta,
+ C, LDC, co);
+ } else {
+ return ref_gemm_s8x8s32(transa, transb, offsetc, M, N, K,
+ alpha, A, LDA, ao, B, LDB, bo, beta, C, LDC, co);
+ }
+ }
+#endif
+}
+
+template
+mkldnn_status_t gemm_s8x8s32(const char *transa, const char *transb,
+ const char *offsetc, const int *M, const int *N, const int *K,
+ const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao,
+ const int8_t *B, const int *LDB, const int8_t *bo, const float *beta,
+ int32_t *C, const int *LDC, const int32_t *co);
+
+template
+mkldnn_status_t gemm_s8x8s32(const char *transa, const char *transb,
+ const char *offsetc, const int *M, const int *N, const int *K,
+ const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao,
+ const uint8_t *B, const int *LDB, const int8_t *bo, const float *beta,
+ int32_t *C, const int *LDC, const int32_t *co);
+
+}
+}
+}
+
+using namespace mkldnn::impl;
+using namespace mkldnn::impl::cpu;
+
+mkldnn_status_t mkldnn_sgemm(const char *transa, const char *transb,
+ const int64_t *M, const int64_t *N, const int64_t *K, const float *alpha,
+ const float *A, const int64_t *lda, const float *B, const int64_t *ldb,
+ const float *beta, float *C, const int64_t *ldc) {
+ int M_s32 = (int)*M;
+ int N_s32 = (int)*N;
+ int K_s32 = (int)*K;
+ int lda_s32 = (int)*lda;
+ int ldb_s32 = (int)*ldb;
+ int ldc_s32 = (int)*ldc;
+
+ return extended_sgemm(transa, transb, &M_s32, &N_s32, &K_s32,
+ alpha, A, &lda_s32, B, &ldb_s32, beta, C, &ldc_s32);
+}
+
+mkldnn_status_t mkldnn_gemm_s8u8s32(const char *transa, const char *transb,
+ const char *offsetc, const int64_t *M, const int64_t *N, const int64_t *K,
+ const float *alpha, const int8_t *A, const int64_t *lda, const int8_t *ao,
+ const uint8_t *B, const int64_t *ldb, const int8_t *bo, const float *beta,
+ int32_t *C, const int64_t *ldc, const int32_t *co) {
+ int M_s32 = (int)*M;
+ int N_s32 = (int)*N;
+ int K_s32 = (int)*K;
+ int lda_s32 = (int)*lda;
+ int ldb_s32 = (int)*ldb;
+ int ldc_s32 = (int)*ldc;
+ return gemm_s8x8s32(transa, transb, offsetc, &M_s32, &N_s32, &K_s32,
+ alpha, A, &lda_s32, ao, B, &ldb_s32, bo, beta, C, &ldc_s32, co);
+}
+
+mkldnn_status_t mkldnn_gemm_s8s8s32(const char *transa, const char *transb,
+ const char *offsetc, const int64_t *M, const int64_t *N, const int64_t *K,
+ const float *alpha, const int8_t *A, const int64_t *lda, const int8_t *ao,
+ const int8_t *B, const int64_t *ldb, const int8_t *bo, const float *beta,
+ int32_t *C, const int64_t *ldc, const int32_t *co) {
+ int M_s32 = (int)*M;
+ int N_s32 = (int)*N;
+ int K_s32 = (int)*K;
+ int lda_s32 = (int)*lda;
+ int ldb_s32 = (int)*ldb;
+ int ldc_s32 = (int)*ldc;
+
+ return gemm_s8x8s32<int8_t>(transa, transb, offsetc, &M_s32, &N_s32, &K_s32,
+ alpha, A, &lda_s32, ao, B, &ldb_s32, bo, beta, C, &ldc_s32, co);
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.hpp
new file mode 100644
index 0000000000..dc15ff7130
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/gemm.hpp
@@ -0,0 +1,58 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef GEMM_HPP
+#define GEMM_HPP
+
+#include "mkldnn_types.h"
+#include "os_blas.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+mkldnn_status_t extended_sgemm(const char *transa, const char *transb,
+ const int *M, const int *N, const int *K, const float *alpha,
+ const float *A, const int *lda, const float *B, const int *ldb,
+ const float *beta, float *C, const int *ldc,
+ const float *bias = nullptr, bool force_jit_gemm = false);
+
+template <typename b_dt>
+mkldnn_status_t gemm_s8x8s32(const char *transa, const char *transb,
+ const char *offsetc, const int *M, const int *N, const int *K,
+ const float *alpha, const int8_t *A, const int *lda, const int8_t *ao,
+ const b_dt *B, const int *ldb, const int8_t *bo, const float *beta,
+ int32_t *c, const int *ldc, const int32_t *co);
+
+#ifdef USE_CBLAS
+#define GEMM_IMPL_STR "gemm:blas"
+#else
+#define GEMM_IMPL_STR "gemm:jit"
+#endif
+
+#if USE_MKL_IGEMM
+#define IGEMM_S8U8S32_IMPL_STR "igemm_s8u8s32:blas"
+#define IGEMM_S8S8S32_IMPL_STR "igemm_s8s8s32:blas"
+#else
+#define IGEMM_S8U8S32_IMPL_STR "igemm_s8u8s32:jit"
+#define IGEMM_S8S8S32_IMPL_STR "igemm_s8s8s32:jit"
+#endif
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/os_blas.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/os_blas.hpp
new file mode 100644
index 0000000000..4d34ede0bd
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/os_blas.hpp
@@ -0,0 +1,86 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef OS_BLAS_HPP
+#define OS_BLAS_HPP
+
+/** \file
+ * Common stuff respecting USE_MKL and USE_CBLAS compile flags
+ *
+ * USE_MKL USE_CBLAS effect
+ * ------- --------- ------
+ * yes yes normal compile: jit *may* be preferred over Intel(R) MKL CBLAS
+ * yes no jit calls OK; assert if cblas is ever called
+ * no yes system-dependent CBLAS
+ * no no gemm convolution (or other blas) N/A; create stubs
+ */
+
+#if defined(USE_MKL)
+
+#include "mkl_version.h"
+
+#define USE_MKL_PACKED_GEMM (INTEL_MKL_VERSION >= 20190001)
+#define USE_MKL_IGEMM \
+ (INTEL_MKL_VERSION >= 20180000 && __INTEL_MKL_BUILD_DATE >= 20170628)
+
+#include "mkl_cblas.h"
+#if !defined(USE_CBLAS)
+#define cblas_sgemm(...) assert(!"CBLAS is unavailable")
+#endif
+
+#else /* defined(USE_MKL) */
+
+#define USE_MKL_PACKED_GEMM 0
+#define USE_MKL_IGEMM 0
+
+#if defined(_SX)
+/* TODO: _SX should also define USE_CBLAS in case the later is available */
+extern "C" {
+#include "cblas.h" // CHECK: does SX also have a fortran API sgemm?
+}
+
+#elif defined(USE_CBLAS)
+#include "cblas.h" // Maybe a system/cmake cblas works for you?
+#else
+/* put the stubs to make a code compilable but not workable */
+#define cblas_sgemm(...) assert(!"CBLAS is unavailable")
+#endif /* defined(_SX) */
+
+#endif /* defined(USE_MKL) */
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+#if defined(USE_MKL) && defined(USE_CBLAS)
+typedef MKL_INT cblas_int;
+
+#elif defined(USE_CBLAS)
+typedef int cblas_int;
+
+#if defined(_SX)
+/* this cblas.h is peculiar... */
+typedef CBLAS_ORDER CBLAS_LAYOUT;
+#endif
+#endif
+
+}
+}
+}
+
+#endif /* OS_BLAS_HPP */
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/common.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/common.hpp
new file mode 100644
index 0000000000..dde72f4a17
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/common.hpp
@@ -0,0 +1,206 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#define GEMM_CODE_SIZE (4096L * 32)
+
+#define AVX512_UNROLL_M 48
+#define AVX512_UNROLL_N 8
+#define AVX512_UNROLL_K 1
+#define AVX512_BM 9984
+#define AVX512_BN 384
+#define AVX512_BK 768
+#define AVX512_BK_VNNI 1536
+#define AVX512_BK_TRADITIONAL 384
+#define AVX512_BLOCKING_SMALL_K 48
+#define AVX512_BN_SMALL_K 24
+
+
+#define PAGESIZE 4096
+
+#define PADD_BYTESIZE_ONPAGE(x, size) (((x) * (size) + PAGESIZE - 1) / PAGESIZE) * PAGESIZE
+#define NEXT_THR_STRIDE(x, size) (PADD_BYTESIZE_ONPAGE(x, size)) / size
+
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+enum {
+ PARTITION_1D_ROW,
+ PARTITION_1D_COL,
+ PARTITION_2D_COL_MAJOR,
+ PARTITION_2D = PARTITION_2D_COL_MAJOR,
+};
+
+enum {
+ COPY_NONE,
+ COPY_A,
+};
+
+enum {
+ NO_OFFSET,
+ FIX_OFFSET,
+ COL_OFFSET,
+ ROW_OFFSET,
+};
+
+// Alias for any dimension related variable.
+typedef long long int dim_t;
+
+typedef struct {
+ // Interface arguments.
+ int transa, transb, offsetc;
+ dim_t m, n, k;
+ dim_t lda, ldb, ldc;
+ const int8_t *a;
+ const uint8_t *b;
+ int32_t *c;
+ const float *alpha, *beta;
+
+ int8_t ao, bo;
+ const int32_t *co;
+
+ // Kernel parameters.
+ dim_t um, un, uk, bm, bn, bk;
+ dim_t bn_small_k, bk_traditional, blocking_small_k;
+
+ int (*copyA)(const dim_t *m, const dim_t *n, const int8_t *a,
+ const dim_t *lda, const int8_t *alpha, int8_t *b,
+ const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum);
+
+ int (*copyB)(const dim_t *m, const dim_t *n, const uint8_t *a,
+ const dim_t *lda, const uint8_t *alpha, uint8_t *b,
+ const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum);
+
+ int (*kernel)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ int (*kernel_b)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ int (*kernel_r)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ int (*kernel_c)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ int (*kernel_b0)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ int (*kernel_b0_b)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ int (*kernel_b0_r)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ int (*kernel_b0_c)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ // Gemv kernels
+ void (*gemv_s8u8s32_kernel)(const dim_t, const dim_t, const float,
+ const int8_t*, const dim_t, const uint8_t*,
+ const float, int32_t*);
+
+ void (*gemv_u8s8s32_kernel)(const dim_t, const dim_t, const float,
+ const uint8_t*, const dim_t, const int8_t*,
+ const float, int32_t*);
+
+ // Gemv parameters
+ int swap;
+
+} blas_t;
+
+
+class jit_avx512_core_u8_copy_an_kern : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_an_kern);
+
+ public:
+ jit_avx512_core_u8_copy_an_kern();
+};
+
+class jit_avx512_core_u8_copy_at_kern : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_at_kern);
+
+ public:
+ jit_avx512_core_u8_copy_at_kern();
+};
+
+class jit_avx512_core_u8_copy_bn_kern : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_bn_kern);
+
+ public:
+ jit_avx512_core_u8_copy_bn_kern();
+};
+
+class jit_avx512_core_u8_copy_bt_kern : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_bt_kern);
+
+ public:
+ jit_avx512_core_u8_copy_bt_kern();
+};
+
+class jit_avx512_core_u8_copy_sum_an_kern : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_sum_an_kern);
+
+ public:
+ jit_avx512_core_u8_copy_sum_an_kern();
+};
+
+class jit_avx512_core_u8_copy_sum_at_kern : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_sum_at_kern);
+
+ public:
+ jit_avx512_core_u8_copy_sum_at_kern();
+};
+
+class jit_avx512_core_u8_copy_sum_bn_kern : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_sum_bn_kern);
+
+ public:
+ jit_avx512_core_u8_copy_sum_bn_kern();
+};
+
+class jit_avx512_core_u8_copy_sum_bt_kern : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8_copy_sum_bt_kern);
+
+ public:
+ jit_avx512_core_u8_copy_sum_bt_kern();
+};
+
+}
+}
+}
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/gemv.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/gemv.hpp
new file mode 100644
index 0000000000..db9dd9ef97
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/gemv.hpp
@@ -0,0 +1,28 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "common.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+int gemm_s8u8s32_jump_to_gemv_s8u8s32(blas_t *arg);
+int gemv_threading_driver(blas_t *arg);
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.cpp
new file mode 100644
index 0000000000..e4b8e1cde2
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.cpp
@@ -0,0 +1,1409 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <cstdint>
+#include <mutex>
+
+#include "common.hpp"
+#include "mkldnn_types.h"
+#include "nstl.hpp"
+#include "utils.hpp"
+
+#include "jit_avx512_core_gemm_s8u8s32.hpp"
+#include "jit_avx512_core_gemm_s8u8s32_kern.hpp"
+#include "jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp"
+#include "gemv.hpp"
+
+#if defined(_MSC_VER)
+#include <malloc.h>
+#endif
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+typedef struct {
+ int nthrs_m, nthrs_n;
+ int partition;
+ int copy_type;
+} blas_thread_t;
+
+static inline void round_to_nearest(int32_t *rounded_val, double fp_val) {
+ if (fp_val >= 0.) {
+ fp_val += 0.5;
+ if (fp_val > INT32_MAX) {
+ fp_val = INT32_MAX;
+ }
+ } else {
+ fp_val -= 0.5;
+ if (fp_val < INT32_MIN) {
+ fp_val = INT32_MIN;
+ }
+ }
+ *rounded_val = (int32_t) fp_val;
+}
+
+static inline void add_results(const dim_t m, const dim_t n, const dim_t k,
+ const float alpha, const float beta, const int32_t *c_partial_sum,
+ const dim_t ldcp, int32_t *c_data, const dim_t ldc,
+ const int32_t *a_row_sum, const int32_t *b_col_sum, const int8_t ao,
+ const int8_t bo, const int32_t *co, const int offsetc)
+{
+ for (dim_t j = 0; j < n; ++j) {
+ for (dim_t i = 0; i < m; ++i) {
+ int32_t ctemp = c_partial_sum[i + j * ldcp];
+
+ if (alpha == 1.0f) {
+ if (beta == 0.0f) {
+ c_data[i + j * ldc] = ctemp;
+ } else {
+ double c_float = (double) beta
+ * (double) c_data[i + j * ldc];
+ c_float += (double) ctemp;
+ round_to_nearest(&c_data[i + j * ldc], c_float);
+ }
+ } else if (alpha == -1.0f) {
+ if (beta == 0.0f) {
+ c_data[i + j * ldc] = -ctemp;
+ } else {
+ double c_float = (double) beta
+ * (double) c_data[i + j * ldc];
+ c_float -= (double) ctemp;
+ round_to_nearest(&c_data[i + j * ldc], c_float);
+ }
+ } else {
+ if (beta == 0.0f) {
+ double c_float = alpha * (double) ctemp;
+ round_to_nearest(&c_data[i + j * ldc], c_float);
+ } else {
+ double c_float = alpha * (double) ctemp +
+ beta * (double) c_data[i + j * ldc];
+ round_to_nearest(&c_data[i + j * ldc], c_float);
+ }
+ }
+
+ if (offsetc == FIX_OFFSET) {
+ c_data[i + j * ldc] += co[0];
+ } else if (offsetc == ROW_OFFSET) {
+ c_data[i + j * ldc] += co[j];
+ } else if (offsetc == COL_OFFSET) {
+ c_data[i + j * ldc] += co[i];
+ }
+ }
+ }
+}
+
+// TODO Find a better place for those functions.
+static inline dim_t ld_padd(const dim_t x)
+{
+ return ((x + ((2048 / sizeof(int32_t)) - 1)) / (2048 / sizeof(int32_t)))
+ * (2048 / sizeof(int32_t)) + (64 / sizeof(int32_t));
+}
+
+void igemm_inner_kernel(const dim_t m, const dim_t n, const dim_t k,
+ const int8_t *a, const uint8_t *b, float beta, int32_t *c,
+ const dim_t ldc, const int32_t *a_row_sum, const int32_t *b_col_sum,
+ const int32_t *co, const int offsetc, const blas_t *arg)
+{
+ int8_t ao = arg->ao;
+ int8_t bo = arg->bo;
+ int32_t co_0 = (offsetc == NO_OFFSET)? 0 : co[0];
+
+ // Since m and n are limited by blocking, stack overflow may not happen;
+ // it's up to 32kB
+#if !defined(_MSC_VER)
+ int32_t col_offset[m];
+ int32_t row_offset[n];
+#else
+ int32_t *col_offset = (int32_t *) _alloca(sizeof(*col_offset) * m);
+ int32_t *row_offset = (int32_t *) _alloca(sizeof(*row_offset) * n);
+#endif
+
+ int col_req = 0;
+ int row_req = 0;
+
+ if ((bo != 0) || (offsetc == COL_OFFSET))
+ col_req = 1;
+ if ((ao != 0) || (offsetc == ROW_OFFSET))
+ row_req = 1;
+
+ // It needs one of colum or row offsets, but it doesn't need both
+ if (((ao != 0) && (bo != 0)) || ((offsetc == FIX_OFFSET) && (co_0 != 0))) {
+ if ((col_req == 0) && (row_req == 0)) {
+ if (m <= n) {
+ col_req = 1;
+ } else {
+ row_req = 1;
+ }
+ }
+ }
+
+ if (col_req) {
+ for (dim_t i = 0; i < m; i++)
+ col_offset[i] = 0;
+
+ if (offsetc == COL_OFFSET) {
+ for (dim_t i = 0; i < m; i++)
+ col_offset[i] += co[i];
+ }
+
+ if (bo != 0) {
+ for (dim_t i = 0; i < m; i++)
+ col_offset[i] += bo * a_row_sum[i];
+ }
+ }
+
+ if (row_req) {
+ for (dim_t i = 0; i < n; i++)
+ row_offset[i] = 0;
+
+ if (offsetc == ROW_OFFSET) {
+ for (dim_t i = 0; i < n; i++)
+ row_offset[i] += co[i];
+ }
+
+ if (ao != 0) {
+ for (dim_t i = 0; i < n; i++)
+ row_offset[i] += ao * b_col_sum[i];
+ }
+ }
+
+ if ((offsetc == FIX_OFFSET) && (co_0 != 0)) {
+ if (col_req) {
+ for (dim_t i = 0; i < m; i++)
+ col_offset[i] += co_0;
+ } else {
+ for (dim_t i = 0; i < n; i++)
+ row_offset[i] += co_0;
+ }
+ }
+
+ if ((ao != 0) && (bo != 0)) {
+ if (col_req) {
+ for (dim_t i = 0; i < m; i++)
+ col_offset[i] += (int32_t) k * ao * bo;
+ } else {
+ for (dim_t i = 0; i < n; i++)
+ row_offset[i] += (int32_t) k * ao * bo;
+ }
+ }
+
+ if (col_req == 0) {
+ if (row_req == 0) {
+ if (beta == 0.0) {
+ arg->kernel_b0(&m, &n, &k, NULL, a, b, c, ldc, col_offset,
+ row_offset);
+ } else {
+ arg->kernel(&m, &n, &k, NULL, a, b, c, ldc, col_offset,
+ row_offset);
+ }
+ } else {
+ if (beta == 0.0) {
+ arg->kernel_b0_r(&m, &n, &k, NULL, a, b, c, ldc, col_offset,
+ row_offset);
+ } else {
+ arg->kernel_r(&m, &n, &k, NULL, a, b, c, ldc, col_offset,
+ row_offset);
+ }
+ }
+ } else {
+ if (row_req == 0) {
+ if (beta == 0.0) {
+ arg->kernel_b0_c(&m, &n, &k, NULL, a, b, c, ldc, col_offset,
+ row_offset);
+ } else {
+ arg->kernel_c(&m, &n, &k, NULL, a, b, c, ldc, col_offset,
+ row_offset);
+ }
+ } else {
+ if (beta == 0.0) {
+ arg->kernel_b0_b(&m, &n, &k, NULL, a, b, c, ldc, col_offset,
+ row_offset);
+ } else {
+ arg->kernel_b(&m, &n, &k, NULL, a, b, c, ldc, col_offset,
+ row_offset);
+ }
+ }
+ }
+}
+
+static inline void *align(void *ptr, size_t alignment)
+{
+ return (void *) utils::rnd_up((uintptr_t) ptr, alignment);
+}
+
+static int gemm_kernel_driver(const dim_t m, const dim_t n, const dim_t k,
+ const int8_t *a, const uint8_t *b, int32_t *c, const int32_t *co,
+ const blas_t *arg)
+{
+ dim_t lda = arg->lda;
+ dim_t ldb = arg->ldb;
+ dim_t ldc = arg->ldc;
+ int8_t ao = arg->ao;
+ int8_t bo = arg->bo;
+ float alpha = *arg->alpha;
+ float beta = *arg->beta;
+
+ if (m <= 0 || n <= 0) {
+ return 0;
+ }
+
+ // Padding along K dimension.
+ dim_t k_padd = 0;
+ if (k <= arg->bk_traditional) {
+ k_padd = utils::rnd_up(k, arg->uk);
+ k_padd = nstl::max(128LL, k_padd);
+ } else if (k < 2 * arg->bk) {
+ k_padd = utils::rnd_up(k / 2, arg->uk);
+ } else {
+ k_padd = arg->bk;
+ }
+
+ // Padding along M dimension.
+ dim_t m_padd = utils::rnd_up(nstl::min(nstl::max(m, arg->um), arg->bm),
+ arg->um);
+
+ // Padding along N dimension.
+ dim_t n_padd = 0;
+ if (k < arg->blocking_small_k) {
+ n_padd = utils::rnd_up(nstl::min(nstl::max(n, arg->un),
+ arg->bn_small_k), arg->un);
+ } else {
+ n_padd = utils::rnd_up(nstl::min(nstl::max(n, arg->un), arg->bn),
+ arg->un);
+ }
+
+ // Padding for temporary buffer for C
+ dim_t ldc_buf = ld_padd(m_padd);
+
+ dim_t strideAm = (arg->transa == 0)? 1 : lda;
+ dim_t strideAn = (arg->transa != 0)? 1 : lda;
+ dim_t strideBm = (arg->transb == 0)? 1 : ldb;
+ dim_t strideBn = (arg->transb != 0)? 1 : ldb;
+
+ size_t a_buf_nelems = m_padd * k_padd;
+ size_t b_buf_nelems = k_padd * n_padd;
+ size_t a_row_sum_nelems = m_padd;
+ size_t b_col_sum_nelems = n_padd;
+
+ size_t mem_size = a_buf_nelems * sizeof(*a) + PAGE_4K
+ + b_buf_nelems * sizeof(*b) + PAGE_4K
+ + a_row_sum_nelems * sizeof(*c) + PAGE_4K
+ + b_col_sum_nelems * sizeof(*c) + PAGE_4K;
+
+ bool need_c_buffer = alpha != 1.0f || (beta != 1 && beta != 0);
+ if (need_c_buffer) {
+ size_t c_buf_nelems = ldc_buf * n_padd;
+ mem_size += c_buf_nelems * sizeof(*c) + PAGE_4K;
+ }
+
+ char *mem = (char *) malloc(mem_size, 128);
+
+ if (!mem) {
+ return -1;
+ }
+
+ int8_t *bufferA = (int8_t *) align(mem, PAGE_4K);
+ uint8_t *bufferB = (uint8_t *) align(bufferA + a_buf_nelems, PAGE_4K);
+ int32_t *a_row_sum = (int32_t *) align(bufferB + b_buf_nelems, PAGE_4K);
+ int32_t *b_col_sum = (int32_t *) align(a_row_sum + a_row_sum_nelems,
+ PAGE_4K);
+
+ int32_t *bufferC = NULL;
+ if (need_c_buffer) {
+ bufferC = (int32_t *) align(b_col_sum + b_col_sum_nelems, PAGE_4K);
+ }
+
+ float beta_saved = beta;
+
+ int a_block_copied = 0;
+ dim_t sizeM = 0;
+ for (dim_t Bm = 0; Bm < m; Bm += sizeM) {
+ sizeM = m - Bm;
+ if (sizeM > m_padd)
+ sizeM = m_padd;
+
+ dim_t sizeK = 0;
+ for (dim_t Bk = 0; Bk < k; Bk += sizeK) {
+ sizeK = k - Bk;
+ if (sizeK > k_padd)
+ sizeK = k_padd;
+
+ // Scale C blocks by beta only for the first time
+ if (Bk == 0)
+ beta = beta_saved;
+ else
+ beta = 1.0f;
+
+ // Apply C offset when to the last k-block of the partial sum.
+ int offsetc = NO_OFFSET;
+ if (Bk + sizeK == k)
+ offsetc = arg->offsetc;
+
+ dim_t sizeN = 0;
+ for (dim_t Bn = 0; Bn < n; Bn += sizeN) {
+ sizeN = n - Bn;
+ if (sizeN > n_padd)
+ sizeN = n_padd;
+
+ const uint8_t *b_block = b + Bk * strideBm + Bn * strideBn;
+ arg->copyB(&sizeK, &sizeN, b_block, &ldb, NULL, bufferB, NULL,
+ NULL, b_col_sum);
+
+ dim_t sizeUM = 0;
+ for (dim_t Um = 0; Um < sizeM; Um += sizeUM) {
+ sizeUM = sizeM - Um;
+ if (sizeUM > arg->um)
+ sizeUM = arg->um;
+
+ /*
+ * Use the whole A buffer only if we have multiple B blocks
+ * for k-dimension, otherwise we are wasting cache to store
+ * B and C blocks.
+ */
+ dim_t Um_forA = 0;
+ if (sizeN < n)
+ Um_forA = Um;
+
+ const int8_t *a_block = a + (Bm + Um) * strideAm
+ + Bk * strideAn;
+ if (!a_block_copied) {
+ arg->copyA(&sizeK, &sizeUM, a_block, &lda, NULL,
+ bufferA + Um_forA * sizeK, NULL, NULL,
+ a_row_sum + Um_forA);
+ }
+
+ int32_t *c_block = c + (Bm + Um) + Bn * ldc;
+ dim_t co_stride = 0;
+ if (offsetc == FIX_OFFSET) {
+ co_stride = 0;
+ } else if (offsetc == ROW_OFFSET) {
+ co_stride = Bn;
+ } else if (offsetc == COL_OFFSET) {
+ co_stride = Bm + Um;
+ }
+ if (need_c_buffer) {
+ igemm_inner_kernel(sizeUM, sizeN, sizeK,
+ bufferA + Um_forA * sizeK, bufferB, 0.0f,
+ bufferC + Um, ldc_buf, a_row_sum + Um_forA,
+ b_col_sum, NULL, NO_OFFSET, arg);
+
+ // Finish the block adding the necessary alpha, beta
+ // and offsets.
+ add_results(sizeUM, sizeN, sizeK, alpha, beta,
+ bufferC + Um, ldc_buf, c_block, ldc,
+ a_row_sum + Um_forA, b_col_sum, ao, bo,
+ co + co_stride, offsetc);
+ } else {
+ igemm_inner_kernel(sizeUM, sizeN, sizeK,
+ bufferA + Um_forA * sizeK, bufferB, beta,
+ c_block, ldc, a_row_sum + Um_forA, b_col_sum,
+ co + co_stride, offsetc, arg);
+ }
+ }
+ a_block_copied = 1;
+ }
+ a_block_copied = 0;
+ }
+ }
+
+ free(mem);
+
+ return 0;
+}
+
+static int kernel_driver_parallel_acopiedbcopy(const dim_t m, const dim_t n,
+ const dim_t k, const int8_t *bufferA, const uint8_t *b,
+ const float beta, int32_t *c, const int offsetc, const int32_t *co,
+ const int32_t *a_row_sum, const blas_t *arg)
+{
+ dim_t ldb = arg->ldb;
+ dim_t ldc = arg->ldc;
+ int8_t ao = arg->ao;
+ int8_t bo = arg->bo;
+ float alpha = *arg->alpha;
+
+ if (m <= 0 || n <= 0) {
+ return 0;
+ }
+
+ // Padding along N dimension.
+ dim_t n_padd = 0;
+ if (k < arg->blocking_small_k) {
+ n_padd = utils::rnd_up(nstl::min(nstl::max(n, arg->un),
+ arg->bn_small_k), arg->un);
+ } else {
+ n_padd = utils::rnd_up(nstl::min(nstl::max(n, arg->un), arg->bn),
+ arg->un);
+ }
+
+ // Padding for temporary buffer for C
+ dim_t ldc_buf = ld_padd(m);
+
+ dim_t strideBn = (arg->transb != 0)? 1 : ldb;
+
+ size_t b_buf_nelems = k * n_padd;
+ size_t b_col_sum_nelems = n_padd;
+
+ size_t mem_size = b_buf_nelems * sizeof(*b) + PAGE_4K
+ + b_col_sum_nelems * sizeof(*c) + PAGE_4K;
+
+ bool need_c_buffer = alpha != 1.0f || (beta != 1 && beta != 0);
+ if (need_c_buffer) {
+ size_t c_buf_nelems = ldc_buf * n_padd;
+ mem_size += c_buf_nelems * sizeof(*c) + PAGE_4K;
+ }
+
+ char *mem = (char *) malloc(mem_size, 128);
+
+ if (!mem) {
+ return -1;
+ }
+
+ uint8_t *bufferB = (uint8_t *) align(mem, PAGE_4K);
+ int32_t *b_col_sum = (int32_t *) align(bufferB + b_buf_nelems, PAGE_4K);
+
+ int32_t *bufferC = NULL;
+ if (need_c_buffer) {
+ bufferC = (int32_t *) align(b_col_sum + b_col_sum_nelems, PAGE_4K);
+ }
+
+ dim_t sizeN = 0;
+ for (dim_t Bn = 0; Bn < n; Bn += sizeN) {
+ sizeN = n - Bn;
+ if (sizeN > n_padd)
+ sizeN = n_padd;
+
+ // Implement the kernel here.
+ const uint8_t *b_block = b + Bn * strideBn;
+ arg->copyB(&k, &sizeN, b_block, &ldb, NULL, bufferB, NULL, NULL,
+ b_col_sum);
+
+ dim_t co_stride = 0;
+ if (offsetc == FIX_OFFSET) {
+ co_stride = 0;
+ } else if (offsetc == ROW_OFFSET) {
+ co_stride = Bn;
+ } else if (offsetc == COL_OFFSET) {
+ co_stride = 0;
+ }
+ int32_t *c_block = c + Bn * ldc;
+ if (need_c_buffer) {
+ igemm_inner_kernel(m, sizeN, k, bufferA, bufferB, 0.0f, bufferC,
+ ldc_buf, a_row_sum, b_col_sum, NULL, NO_OFFSET, arg);
+
+ // Finish the block adding the necessary alpha, beta and offsets.
+ add_results(m, sizeN, k, alpha, beta, bufferC, ldc_buf, c_block,
+ ldc, a_row_sum, b_col_sum, ao, bo, co + co_stride,
+ offsetc);
+ } else {
+ igemm_inner_kernel(m, sizeN, k, bufferA, bufferB, beta, c_block,
+ ldc, a_row_sum, b_col_sum, co + co_stride, offsetc, arg);
+ }
+ }
+
+ free(mem);
+
+ return 0;
+
+}
+
+#define N2D_MAX_AVX512 384
+#define M2D_MIN_AVX512 384
+#define VECLEN 16
+#define NCONS 1
+static inline void set_thread_opts_avx512(int *p_nthrs,
+ blas_thread_t *thread_info, const blas_t *arg)
+{
+ int nthrs = *p_nthrs;
+ dim_t m = arg->m;
+ dim_t n = arg->n;
+
+ thread_info->nthrs_m = 0;
+ thread_info->nthrs_n = 0;
+ thread_info->copy_type = COPY_NONE; // By default don't do parallel copy.
+
+ int condition_2D_bsrc = -1;
+ if ((256 * m > nthrs * n) && (nthrs * m < 256 * n)) {
+ condition_2D_bsrc = 1;
+ } else {
+ condition_2D_bsrc = 0;
+ }
+
+ int condition_1D_copya = 0;
+ if ((m >= 1000) && (n >= nthrs * N2D_MAX_AVX512 / 4)) {
+ condition_2D_bsrc = 0;
+ condition_1D_copya = 1;
+ }
+
+ // If offset is non-zero, we need to keep 1D_copya to reduce update overhead
+ if (arg->ao != 0 || arg->bo != 0 || arg->co[0] != 0
+ || arg->offsetc != FIX_OFFSET) {
+ condition_2D_bsrc = 0;
+ condition_1D_copya = 1;
+ }
+
+ if (condition_2D_bsrc == 1) {
+ int nthrs_m = 1;
+ int nthrs_n = nthrs;
+
+ while ((nthrs_n % 2 == 0) &&
+ (n / nthrs > N2D_MAX_AVX512 ||
+ n / nthrs_n <= N2D_MAX_AVX512 / 2) &&
+ (m / nthrs_m >= 2 * M2D_MIN_AVX512) &&
+ (nthrs_m < 4)) {
+ nthrs_m *= 2;
+ nthrs_n /= 2;
+ }
+
+ thread_info->nthrs_m = nthrs_m;
+ thread_info->nthrs_n = nthrs_n;
+ thread_info->partition = PARTITION_2D;
+
+ // Reset the total number of threads that will be used.
+ *p_nthrs = nthrs_m * nthrs_n;
+
+ } else if (condition_1D_copya && mkldnn_thr_syncable()) {
+ // Use parallel copy A algorithm
+ thread_info->copy_type = COPY_A;
+ thread_info->partition = PARTITION_1D_COL;
+ } else {
+ if ((m > n) && (m / nthrs >= VECLEN || n < NCONS * nthrs)) {
+ thread_info->partition = PARTITION_1D_ROW;
+ } else {
+ thread_info->partition = PARTITION_1D_COL;
+ }
+ }
+}
+#undef N2D_MAX_AVX512
+#undef M2D_MIN_AVX512
+#undef VECLEN
+#undef NCONS
+
+static inline void partition_1d(const int ithr, const int nthrs, const dim_t n,
+ dim_t *t_offset, dim_t *t_block)
+{
+ dim_t band = n / nthrs;
+
+ dim_t tail = n - (nthrs - 1) * band;
+ if (tail > (band + 1))
+ band++;
+ tail = n - (nthrs - 1) * band;
+
+ if (ithr < (nthrs - 1))
+ *t_block = band;
+ else
+ *t_block = tail;
+
+ *t_offset = ithr * band;
+
+ if (*t_offset >= n) {
+ *t_block = 0;
+ *t_offset = 0;
+ } else if ((*t_offset + *t_block) > n) {
+ *t_block = n - *t_offset;
+ }
+}
+
+static inline void partition_2d(const int ithr, int *nthrs, const int ithr_i,
+ const int ithr_j, const int nthrs_m, const int nthrs_n, const dim_t m,
+ const dim_t n, dim_t *p_m_disp, dim_t *p_m_band, dim_t *p_n_disp,
+ dim_t *p_n_band)
+{
+ dim_t m_disp = 0, n_disp = 0;
+ dim_t m_band = 0, n_band = 0;
+
+ int mdiv = nthrs_m;
+ int ndiv = nthrs_n;
+
+ dim_t m_bandt = m / mdiv; /* size per thread */
+ dim_t n_bandt = n / ndiv; /* size per thread */
+ int firstmgroup = mdiv - 1;
+ int firstngroup = ndiv - 1;
+ dim_t firstmval = m_bandt;
+ dim_t firstnval = n_bandt;
+
+ int mthr_used = mdiv;
+ if (m - (mdiv - 1) * m_bandt > m_bandt + 1) {
+ if (m - (mdiv - 1) * m_bandt > mdiv)
+ ++m_bandt;
+
+ firstmval = m_bandt + 1;
+ mthr_used = (int) (m / firstmval);
+
+ if (mthr_used * firstmval < m)
+ ++mthr_used;
+
+ firstmgroup = mthr_used - 1;
+ }
+
+ int nthr_used = ndiv;
+ if (n - (ndiv - 1) * n_bandt > n_bandt + 1) {
+ firstnval = n_bandt + 1;
+ nthr_used = (int) (n / firstnval);
+
+ if (nthr_used * firstnval < n)
+ ++nthr_used;
+
+ firstngroup = nthr_used - 1;
+ }
+
+ *nthrs = mthr_used * nthr_used;
+
+ if (ithr < *nthrs) {
+ if (ithr_i < firstmgroup) {
+ m_band = firstmval;
+ m_disp = ithr_i * firstmval;
+ } else if (ithr_i <= mthr_used - 2) {
+ m_band = m_bandt;
+ m_disp = firstmgroup * firstmval + (ithr_i - firstmgroup) * m_bandt;
+ } else {
+ m_disp = firstmgroup * firstmval
+ + (mthr_used - 1 - firstmgroup) * m_bandt;
+ m_band = nstl::max(0LL, m - m_disp);
+ }
+
+ if (ithr_j < firstngroup) {
+ n_band = firstnval;
+ n_disp = ithr_j * firstnval;
+ } else if (ithr_j <= nthr_used - 2) {
+ n_band = n_bandt;
+ n_disp = firstngroup * firstnval + (ithr_j - firstngroup) * n_bandt;
+ } else {
+ n_disp = firstngroup * firstnval
+ + (nthr_used - 1 - firstngroup) * n_bandt;
+ n_band = nstl::max(0LL, n - n_disp);
+ }
+ m_disp = nstl::max(nstl::min(m_disp, m - 1), 0LL);
+ n_disp = nstl::max(nstl::min(n_disp, n - 1), 0LL);
+ }
+
+ if (ithr < *nthrs) {
+ *p_m_disp = m_disp;
+ *p_n_disp = n_disp;
+ *p_m_band = m_band;
+ *p_n_band = n_band;
+ } else {
+ *p_m_disp = 0;
+ *p_n_disp = 0;
+ *p_m_band = 0;
+ *p_n_band = 0;
+ }
+
+ return;
+}
+
+static inline void decompose_matrices(const int ithr, int *nthrs, dim_t *m,
+ dim_t *n, dim_t *k, const int8_t **a, const uint8_t **b, int32_t **c,
+ const int32_t **co, const blas_thread_t *thread_info, const blas_t *arg)
+{
+ dim_t strideAm = (arg->transa == 0)? 1 : arg->lda;
+ dim_t strideBn = (arg->transb != 0)? 1 : arg->ldb;
+ int offsetc = arg->offsetc;
+
+ switch (thread_info->partition) {
+ case PARTITION_1D_ROW:
+ {
+ dim_t offset = 0;
+ dim_t block = 0;
+ partition_1d(ithr, *nthrs, arg->m, &offset, &block);
+
+ *m = block;
+ *n = arg->n;
+ *k = arg->k;
+
+ // Set matrix A.
+ *a = arg->a + offset * strideAm;
+
+ // Set matrix B.
+ *b = arg->b;
+
+ // Set matrix C.
+ *c = arg->c + offset;
+
+ // Set offset vector for C matrix
+ dim_t co_stride = 0;
+ if (offsetc == FIX_OFFSET) {
+ co_stride = 0;
+ } else if (offsetc == ROW_OFFSET) {
+ co_stride = 0;
+ } else if (offsetc == COL_OFFSET) {
+ co_stride = offset;
+ }
+ *co = arg->co + co_stride;
+ break;
+ }
+
+ case PARTITION_1D_COL:
+ {
+ dim_t offset = 0;
+ dim_t block = 0;
+ partition_1d(ithr, *nthrs, arg->n, &offset, &block);
+
+ *m = arg->m;
+ *n = block;
+ *k = arg->k;
+
+ // Set matrix A.
+ *a = arg->a;
+
+ // Set matrix B.
+ *b = arg->b + offset * strideBn;
+
+ // Set matrix C.
+ *c = arg->c + offset * arg->ldc;
+
+ // Set offset vector for C matrix
+ dim_t co_stride = 0;
+ if (offsetc == FIX_OFFSET) {
+ co_stride = 0;
+ } else if (offsetc == ROW_OFFSET) {
+ co_stride = offset;
+ } else if (offsetc == COL_OFFSET) {
+ co_stride = 0;
+ }
+ *co = arg->co + co_stride;
+ break;
+ }
+
+ case PARTITION_2D_COL_MAJOR:
+ {
+ int nthrs_m = thread_info->nthrs_m;
+ int nthrs_n = thread_info->nthrs_n;
+ int ithr_i = ithr % nthrs_m;
+ int ithr_j = ithr / nthrs_m;
+
+ dim_t m_disp = 0;
+ dim_t m_band = 0;
+ dim_t n_disp = 0;
+ dim_t n_band = 0;
+
+ partition_2d(ithr, nthrs, ithr_i, ithr_j, nthrs_m, nthrs_n,
+ arg->m, arg->n, &m_disp, &m_band, &n_disp, &n_band);
+
+ *m = m_band;
+ *n = n_band;
+ *k = arg->k;
+
+ // Set matrix A.
+ *a = arg->a + m_disp * strideAm;
+
+ // Set matrix B.
+ *b = arg->b + n_disp * strideBn;
+
+ // Set matrix C.
+ *c = arg->c + m_disp + n_disp * arg->ldc;
+
+ // Set offset vector for C matrix
+ dim_t co_stride = 0;
+ if (offsetc == FIX_OFFSET) {
+ co_stride = 0;
+ } else if (offsetc == ROW_OFFSET) {
+ co_stride = n_disp;
+ } else if (offsetc == COL_OFFSET) {
+ co_stride = m_disp;
+ }
+ *co = arg->co + co_stride;
+ break;
+ }
+ }
+}
+
+#define MULTIPLIER 10
+static int parallel_a_copy(const int ithr, const int nthrs, const dim_t m,
+ const dim_t n, const dim_t k, const int8_t *a, const uint8_t *b,
+ int32_t *c, const int32_t *co, const blas_t *arg,
+ char **p_shared_mem)
+{
+ const dim_t lda = arg->lda;
+ const dim_t ldb = arg->ldb;
+ const dim_t strideAm = (arg->transa == 0)? 1 : lda;
+ const dim_t strideAn = (arg->transa != 0)? 1 : lda;
+ const dim_t strideBm = (arg->transb == 0)? 1 : ldb;
+
+ // Padding along M dimension.
+ dim_t m_padd = utils::rnd_up(nstl::min(nstl::max(m, arg->um), arg->bm),
+ arg->um);
+
+ // Padding along K dimension.
+ dim_t k_padd = 0;
+ if (k <= arg->bk_traditional) {
+ k_padd = utils::rnd_up(k, arg->uk);
+ k_padd = nstl::max(128LL, k_padd);
+ } else if (k < 2 * arg->bk) {
+ k_padd = utils::rnd_up(k / 2, arg->uk);
+ } else {
+ k_padd = arg->bk;
+ }
+
+ m_padd *= nthrs > MULTIPLIER ? MULTIPLIER : nthrs;
+ if (m_padd > m) {
+ m_padd = utils::rnd_up(m, arg->um);
+ }
+
+ size_t a_buf_nelems = m_padd * k_padd;
+
+ // Allocate shared memory for A and its row sum buffers in master thread.
+ if (ithr == 0) { // If thread master
+ size_t a_row_sum_nelems = m_padd;
+
+ size_t mem_size = (a_buf_nelems * sizeof(*a) + PAGE_4K)
+ + a_row_sum_nelems * sizeof(*c) + PAGE_4K;
+
+ *p_shared_mem = (char *) malloc(mem_size, 128);
+
+ }
+ mkldnn_thr_barrier();
+
+ char *mem = *p_shared_mem;
+ int8_t *bufferA = (int8_t *) align(mem, PAGE_4K);
+ int32_t *a_row_sum = (int32_t *) align(bufferA + a_buf_nelems, PAGE_4K);
+
+ if (!mem) {
+ return -1;
+ }
+
+ int result = 0; // Return status
+
+ dim_t sizeK = 0;
+ for (dim_t Bk = 0; Bk < k; Bk += sizeK) {
+ sizeK = k - Bk;
+ if (sizeK > k_padd)
+ sizeK = k_padd;
+
+ // Scale C blocks by beta only for the first term of partial sum.
+ float beta = 1.0f;
+ if (Bk == 0)
+ beta = *(arg->beta);
+
+ // Apply C offset for the last k-block of the partial sum.
+ int offsetc = NO_OFFSET;
+ if (Bk + sizeK == k)
+ offsetc = arg->offsetc;
+
+ dim_t sizeM = 0;
+ for (dim_t Bm = 0; Bm < m; Bm += sizeM) {
+ sizeM = m - Bm;
+ if (sizeM > m_padd)
+ sizeM = m_padd;
+
+ if (ithr < nthrs) {
+ dim_t band = (sizeM + nthrs - 1) / nthrs;
+ band = utils::rnd_up(band, arg->um);
+
+ dim_t offset = band * ithr;
+
+ // If offset is too large don't use that thread for copying.
+ if (offset >= sizeM) {
+ offset = 0;
+ band = 0;
+ }
+
+ // Handle the tail of the copy.
+ if (offset + band > sizeM) {
+ band = sizeM - offset;
+ }
+
+ if (band > 0) {
+ const int8_t *a_block = a + (Bm + offset) * strideAm
+ + Bk * strideAn;
+ arg->copyA(&sizeK, &band, a_block, &lda, NULL,
+ bufferA + offset * sizeK, NULL, NULL,
+ a_row_sum + offset);
+ }
+ }
+ mkldnn_thr_barrier(); // Wait for finishing parallel copy.
+
+ const uint8_t *b_block = b + Bk * strideBm;
+ int32_t *c_block = c + Bm;
+ dim_t co_stride = 0;
+ if (offsetc == FIX_OFFSET) {
+ co_stride = 0;
+ } else if (offsetc == ROW_OFFSET) {
+ co_stride = 0;
+ } else if (offsetc == COL_OFFSET) {
+ co_stride = Bm;
+ }
+
+ result = kernel_driver_parallel_acopiedbcopy(sizeM, n, sizeK,
+ bufferA, b_block, beta, c_block, offsetc, co + co_stride,
+ a_row_sum, arg);
+
+ mkldnn_thr_barrier(); // Wait for kernel computations to finish.
+ }
+ }
+
+ // Free memory allocated in master thread
+ if (ithr == 0) {
+ free(mem);
+ }
+
+ return result;
+}
+#undef MULTIPLIER
+
+static inline void get_omp_thread_count(dim_t m, dim_t n, dim_t k,
+ double fp_per_cycle, int *nthrs)
+{
+ double omp_overhead_small_core = 3.0e+3;
+ double omp_intercept_big_core = 4.0e+3;
+ double omp_slope_big_core = 5.0e+2;
+
+ double gemm_cycles = 8.0 * m * n * k / fp_per_cycle;
+
+ int i = *nthrs;
+
+ // Use a different model for omp overheads if nthrs is <= 4
+ if (*nthrs <= 4 && omp_overhead_small_core > 0) {
+ double omp_cycles = omp_overhead_small_core;
+ if (gemm_cycles < omp_cycles) {
+ *nthrs = 1;
+ return;
+ } else {
+ while (i > 1) {
+ if (omp_cycles * i < gemm_cycles * (i - 1)) break;
+ --i;
+ }
+ }
+ } else {
+ if (gemm_cycles < (omp_intercept_big_core + 2 * omp_slope_big_core)) {
+ *nthrs = 1;
+ return;
+ }
+
+ // adaptive decrement to march faster·
+ while (i > 1) {
+ double omp_cycles = omp_intercept_big_core + i * omp_slope_big_core;
+ if (omp_cycles * i < gemm_cycles * (i - 1))
+ break;
+
+ if (i < 10)
+ i -= 2;
+ else if (i < 30)
+ i -= 4;
+ else
+ i -= 8;
+ }
+ }
+
+ if (i < 1)
+ i = 1;
+
+ *nthrs = i;
+}
+
+#define CACHE_LINE_SIZE 64
+static int gemm_threading_driver(blas_t *arg)
+{
+ if ((arg->m <= 0) || (arg->n <= 0))
+ return mkldnn_success;
+
+ if (gemm_s8u8s32_jump_to_gemv_s8u8s32(arg)) {
+ return mkldnn_success;
+ }
+
+ int nthr = (mkldnn_in_parallel()) ? 1 : mkldnn_get_max_threads();
+ get_omp_thread_count(arg->m, arg->n, arg->k, 64.0, &nthr);
+
+ if (nthr == 1) {
+ return gemm_kernel_driver(arg->m, arg->n, arg->k, arg->a, arg->b,
+ arg->c, arg->co, arg);
+ }
+
+ int *results = (int *) malloc(sizeof(*results) * nthr * CACHE_LINE_SIZE,
+ PAGE_4K);
+
+ if (!results) {
+ return -1;
+ }
+
+ for (int i = 0; i < nthr; i++) {
+ results[i * CACHE_LINE_SIZE] = 0; // Initialize to success
+ }
+
+ char *shared_mem = NULL;
+
+ parallel(nthr, [&](const int ithr, const int nthr) {
+ int nthrs = nthr;
+ if (nthrs == 1) {
+ results[0] = gemm_kernel_driver(arg->m, arg->n, arg->k, arg->a,
+ arg->b, arg->c, arg->co, arg);
+ } else {
+ blas_thread_t thread_info;
+ set_thread_opts_avx512(&nthrs, &thread_info, arg);
+
+ const int8_t *a = NULL;
+ const uint8_t *b = NULL;
+ int32_t *c = NULL;
+ const int32_t *co = NULL;
+ dim_t m = -1;
+ dim_t n = -1;
+ dim_t k = -1;
+ decompose_matrices(ithr, &nthrs, &m, &n, &k, &a, &b, &c, &co,
+ &thread_info, arg);
+
+ if (ithr < nthrs) {
+ switch (thread_info.copy_type) {
+ case COPY_A:
+ results[ithr * CACHE_LINE_SIZE] =
+ parallel_a_copy(ithr, nthrs, m, n, k, a, b, c, co, arg,
+ &shared_mem);
+ break;
+
+ default:
+ case COPY_NONE:
+ results[ithr * CACHE_LINE_SIZE] =
+ gemm_kernel_driver(m, n, k, a, b, c, co, arg);
+ break;
+ }
+ }
+ }
+ });
+
+ int result = 0; // Initialize to success
+ for (int i = 0; i < nthr; i++) {
+ if (results[i] != 0) {
+ result = results[i * CACHE_LINE_SIZE];
+ break;
+ }
+ }
+
+ free(results);
+
+ return result;
+}
+#undef CACHE_LINE_SIZE
+
+static jit_avx512_core_u8_copy_an_kern *copy_an;
+static jit_avx512_core_u8_copy_at_kern *copy_at;
+static jit_avx512_core_u8_copy_bn_kern *copy_bn;
+static jit_avx512_core_u8_copy_bt_kern *copy_bt;
+static jit_avx512_core_u8_copy_sum_an_kern *copy_sum_an;
+static jit_avx512_core_u8_copy_sum_at_kern *copy_sum_at;
+static jit_avx512_core_u8_copy_sum_bn_kern *copy_sum_bn;
+static jit_avx512_core_u8_copy_sum_bt_kern *copy_sum_bt;
+static jit_avx512_core_gemm_s8u8s32_kern *kernel;
+static jit_avx512_core_gemm_s8u8s32_kern *kernel_b;
+static jit_avx512_core_gemm_s8u8s32_kern *kernel_r;
+static jit_avx512_core_gemm_s8u8s32_kern *kernel_c;
+static jit_avx512_core_gemm_s8u8s32_kern *kernel_b0;
+static jit_avx512_core_gemm_s8u8s32_kern *kernel_b0_b;
+static jit_avx512_core_gemm_s8u8s32_kern *kernel_b0_r;
+static jit_avx512_core_gemm_s8u8s32_kern *kernel_b0_c;
+static jit_avx512_core_gemv_s8u8s32_kern *gemv_s8u8s32_kernel;
+static jit_avx512_core_gemv_s8u8s32_kern *gemv_u8s8s32_kernel;
+
+static void jit_init(blas_t *arg)
+{
+ static int (*copyAn)(const dim_t *m, const dim_t *n, const int8_t *a,
+ const dim_t *lda, const int8_t *alpha, int8_t *b,
+ const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum);
+
+ static int (*copyAt)(const dim_t *m, const dim_t *n, const int8_t *a,
+ const dim_t *lda, const int8_t *alpha, int8_t *b,
+ const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum);
+
+ static int (*copyBn)(const dim_t *m, const dim_t *n, const uint8_t *a,
+ const dim_t *lda, const uint8_t *alpha, uint8_t *b,
+ const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum);
+
+ static int (*copyBt)(const dim_t *m, const dim_t *n, const uint8_t *a,
+ const dim_t *lda, const uint8_t *alpha, uint8_t *b,
+ const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum);
+
+ static int (*copySumAn)(const dim_t *m, const dim_t *n, const int8_t *a,
+ const dim_t *lda, const int8_t *alpha, int8_t *b,
+ const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum);
+
+ static int (*copySumAt)(const dim_t *m, const dim_t *n, const int8_t *a,
+ const dim_t *lda, const int8_t *alpha, int8_t *b,
+ const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum);
+
+ static int (*copySumBn)(const dim_t *m, const dim_t *n, const uint8_t *a,
+ const dim_t *lda, const uint8_t *alpha, uint8_t *b,
+ const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum);
+
+ static int (*copySumBt)(const dim_t *m, const dim_t *n, const uint8_t *a,
+ const dim_t *lda, const uint8_t *alpha, uint8_t *b,
+ const dim_t *dummy1, const dim_t *dummy2, int32_t *row_col_sum);
+
+ static int (*kern)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ static int (*kern_b)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ static int (*kern_r)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ static int (*kern_c)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ static int (*kern_b0)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ static int (*kern_b0_b)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ static int (*kern_b0_r)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ static int (*kern_b0_c)(const dim_t *m, const dim_t *n, const dim_t *k,
+ const float *alpha, const int8_t *a, const uint8_t *b, int32_t *c,
+ const dim_t ldc, const int32_t *col_offset,
+ const int32_t *row_offset);
+
+ static void (*gemv_s8u8s32_kern)(const dim_t, const dim_t, const float,
+ const int8_t*, const dim_t, const uint8_t*,
+ const float, int32_t*);
+
+ static void (*gemv_u8s8s32_kern)(const dim_t, const dim_t, const float,
+ const uint8_t*, const dim_t, const int8_t*,
+ const float, int32_t*);
+
+ if (mayiuse(avx512_core_vnni)) {
+ arg->um = AVX512_UNROLL_M;
+ arg->un = AVX512_UNROLL_N;
+ arg->uk = AVX512_UNROLL_K;
+ arg->bm = AVX512_BM;
+ arg->bn = AVX512_BN;
+ arg->bk = AVX512_BK_VNNI;
+
+ arg->bk_traditional = AVX512_BK_TRADITIONAL;
+ arg->bn_small_k = AVX512_BN_SMALL_K;
+ arg->blocking_small_k = AVX512_BLOCKING_SMALL_K;
+ } else {
+ arg->um = AVX512_UNROLL_M;
+ arg->un = AVX512_UNROLL_N;
+ arg->uk = AVX512_UNROLL_K;
+ arg->bm = AVX512_BM;
+ arg->bn = AVX512_BN;
+ arg->bk = AVX512_BK;
+
+ arg->bk_traditional = AVX512_BK_TRADITIONAL;
+ arg->bn_small_k = AVX512_BN_SMALL_K;
+ arg->blocking_small_k = AVX512_BLOCKING_SMALL_K;
+ }
+
+ static std::once_flag initialized;
+ std::call_once(initialized, []{
+
+ copy_an = new jit_avx512_core_u8_copy_an_kern();
+ copy_at = new jit_avx512_core_u8_copy_at_kern();
+ copy_bn = new jit_avx512_core_u8_copy_bn_kern();
+ copy_bt = new jit_avx512_core_u8_copy_bt_kern();
+
+ copy_sum_an = new jit_avx512_core_u8_copy_sum_an_kern();
+ copy_sum_at = new jit_avx512_core_u8_copy_sum_at_kern();
+ copy_sum_bn = new jit_avx512_core_u8_copy_sum_bn_kern();
+ copy_sum_bt = new jit_avx512_core_u8_copy_sum_bt_kern();
+
+ kernel = new jit_avx512_core_gemm_s8u8s32_kern(false, false, false);
+ kernel_b = new jit_avx512_core_gemm_s8u8s32_kern(false, true, true);
+ kernel_r = new jit_avx512_core_gemm_s8u8s32_kern(false, false, true);
+ kernel_c = new jit_avx512_core_gemm_s8u8s32_kern(false, true, false);
+ kernel_b0 = new jit_avx512_core_gemm_s8u8s32_kern(true, false, false);
+ kernel_b0_b = new jit_avx512_core_gemm_s8u8s32_kern(true, true, true);
+ kernel_b0_r = new jit_avx512_core_gemm_s8u8s32_kern(true, false, true);
+ kernel_b0_c = new jit_avx512_core_gemm_s8u8s32_kern(true, true, false);
+
+ gemv_s8u8s32_kernel = new jit_avx512_core_gemv_s8u8s32_kern();
+ gemv_u8s8s32_kernel = new jit_avx512_core_gemv_s8u8s32_kern();
+
+
+ copyAn = copy_an->getCode<int (*)(const dim_t *, const dim_t *,
+ const int8_t *, const dim_t *, const int8_t *, int8_t *,
+ const dim_t *, const dim_t *, int32_t *)>();
+
+ copyAt = copy_at->getCode<int (*)(const dim_t *, const dim_t *,
+ const int8_t *, const dim_t *, const int8_t *, int8_t *,
+ const dim_t *, const dim_t *, int32_t *)>();
+
+ copyBn = copy_bn->getCode<int (*)(const dim_t *, const dim_t *,
+ const uint8_t *, const dim_t *, const uint8_t *, uint8_t *,
+ const dim_t *, const dim_t *, int32_t *)>();
+
+ copyBt = copy_bt->getCode<int (*)(const dim_t *, const dim_t *,
+ const uint8_t *, const dim_t *, const uint8_t *, uint8_t *,
+ const dim_t *, const dim_t *, int32_t *)>();
+
+ copySumAn = copy_sum_an->getCode<int (*)(const dim_t *, const dim_t *,
+ const int8_t *, const dim_t *, const int8_t *, int8_t *,
+ const dim_t *, const dim_t *, int32_t *)>();
+
+ copySumAt = copy_sum_at->getCode<int (*)(const dim_t *, const dim_t *,
+ const int8_t *, const dim_t *, const int8_t *, int8_t *,
+ const dim_t *, const dim_t *, int32_t *)>();
+
+ copySumBn = copy_sum_bn->getCode<int (*)(const dim_t *, const dim_t *,
+ const uint8_t *, const dim_t *, const uint8_t *, uint8_t *,
+ const dim_t *, const dim_t *, int32_t *)>();
+
+ copySumBt = copy_sum_bt->getCode<int (*)(const dim_t *, const dim_t *,
+ const uint8_t *, const dim_t *, const uint8_t *, uint8_t *,
+ const dim_t *, const dim_t *, int32_t *)>();
+
+ kern = kernel->getCode<int (*)(const dim_t *, const dim_t *,
+ const dim_t *, const float *, const int8_t *, const uint8_t *,
+ int32_t *, const dim_t, const int32_t *, const int32_t *)>();
+
+ kern_b = kernel_b->getCode<int (*)(const dim_t *, const dim_t *,
+ const dim_t *, const float *, const int8_t *, const uint8_t *,
+ int32_t *, const dim_t, const int32_t *, const int32_t *)>();
+
+ kern_r = kernel_r->getCode<int (*)(const dim_t *, const dim_t *,
+ const dim_t *, const float *, const int8_t *, const uint8_t *,
+ int32_t *, const dim_t, const int32_t *, const int32_t *)>();
+
+ kern_c = kernel_c->getCode<int (*)(const dim_t *, const dim_t *,
+ const dim_t *, const float *, const int8_t *, const uint8_t *,
+ int32_t *, const dim_t, const int32_t *, const int32_t *)>();
+
+ kern_b0 = kernel_b0->getCode<int (*)(const dim_t *, const dim_t *,
+ const dim_t *, const float *, const int8_t *, const uint8_t *,
+ int32_t *, const dim_t, const int32_t *, const int32_t *)>();
+
+ kern_b0_b = kernel_b0_b->getCode<int (*)(const dim_t *, const dim_t *,
+ const dim_t *, const float *, const int8_t *, const uint8_t *,
+ int32_t *, const dim_t, const int32_t *, const int32_t *)>();
+
+ kern_b0_r = kernel_b0_r->getCode<int (*)(const dim_t *, const dim_t *,
+ const dim_t *, const float *, const int8_t *, const uint8_t *,
+ int32_t *, const dim_t, const int32_t *, const int32_t *)>();
+
+ kern_b0_c = kernel_b0_c->getCode<int (*)(const dim_t *, const dim_t *,
+ const dim_t *, const float *, const int8_t *, const uint8_t *,
+ int32_t *, const dim_t, const int32_t *, const int32_t *)>();
+
+ gemv_s8u8s32_kern =
+ gemv_s8u8s32_kernel -> generate<jit_avx512_core_gemv_s8u8s32_kern::gemv_s8u8s32_kernel_t>
+ (mayiuse(avx512_core_vnni));
+ gemv_u8s8s32_kern =
+ gemv_u8s8s32_kernel -> generate<jit_avx512_core_gemv_s8u8s32_kern::gemv_u8s8s32_kernel_t>
+ (mayiuse(avx512_core_vnni));
+ });
+
+ if (arg->bo == 0) { // No need to compute A row sum if bo is zero
+ if (arg->transa == 0) {
+ arg->copyA = copyAn;
+ } else {
+ arg->copyA = copyAt;
+ }
+ } else {
+ if (arg->transa == 0) {
+ arg->copyA = copySumAn;
+ } else {
+ arg->copyA = copySumAt;
+ }
+ }
+
+ if (arg->ao == 0) { // No need to compute B column sum if ao is zero
+ if (arg->transb == 0) {
+ arg->copyB = copyBn;
+ } else {
+ arg->copyB = copyBt;
+ }
+ } else {
+ if (arg->transb == 0) {
+ arg->copyB = copySumBn;
+ } else {
+ arg->copyB = copySumBt;
+ }
+ }
+
+ arg->kernel = kern;
+ arg->kernel_b = kern_b;
+ arg->kernel_r = kern_r;
+ arg->kernel_c = kern_c;
+ arg->kernel_b0 = kern_b0;
+ arg->kernel_b0_b = kern_b0_b;
+ arg->kernel_b0_r = kern_b0_r;
+ arg->kernel_b0_c = kern_b0_c;
+ arg -> gemv_s8u8s32_kernel = gemv_s8u8s32_kern;
+ arg -> gemv_u8s8s32_kernel = gemv_u8s8s32_kern;
+}
+
+mkldnn_status_t jit_avx512_core_gemm_s8u8s32(
+ const char *transA, const char *transB, const char *offsetC,
+ const int *m, const int *n, const int *k,
+ const float *alpha, const int8_t *a, const int *lda, const int8_t *oa,
+ const uint8_t *b, const int *ldb, const int8_t *ob,
+ const float *beta, int32_t *c, const int *ldc, const int32_t *oc)
+{
+ char transa = *transA;
+ char transb = *transB;
+ char offsetc = *offsetC;
+
+ blas_t args;
+
+ // Initialize blas structure
+ args.m = *m;
+ args.n = *n;
+ args.k = *k;
+ args.alpha = alpha;
+ args.a = a;
+ args.lda = *lda;
+ args.b = b;
+ args.ldb = *ldb;
+ args.beta = beta;
+ args.c = c;
+ args.ldc = *ldc;
+ args.transa = (transa == 'N' || transa == 'n') ? 0 : 1;
+ args.transb = (transb == 'N' || transb == 'n') ? 0 : 1;
+ args.um = 0;
+ args.un = 0;
+ args.bm = 0;
+ args.bn = 0;
+ args.bk = 0;
+ args.copyA = NULL;
+ args.copyB = NULL;
+ args.kernel = NULL;
+ args.kernel_b0 = NULL;
+ args.ao = *oa;
+ args.bo = *ob;
+ args.co = oc;
+
+ if (offsetc == 'F' || offsetc == 'f') {
+ args.offsetc = FIX_OFFSET;
+ } else if (offsetc == 'R' || offsetc == 'r') {
+ args.offsetc = ROW_OFFSET;
+ } else { // offsetc == 'C' || offsetc == 'c'
+ args.offsetc = COL_OFFSET;
+ }
+
+ jit_init(&args);
+ int result = gemm_threading_driver(&args);
+
+ return (result < 0) ? mkldnn_out_of_memory : mkldnn_success;
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp
new file mode 100644
index 0000000000..b2e2902a12
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32.hpp
@@ -0,0 +1,38 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_AVX512_CORE_GEMM_S8U8S32_HPP
+#define JIT_AVX512_CORE_GEMM_S8U8S32_HPP
+
+#include <cstdint>
+#include "mkldnn_types.h"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+mkldnn_status_t jit_avx512_core_gemm_s8u8s32(
+ const char *transA, const char *transB, const char *offsetC,
+ const int *m, const int *n, const int *k,
+ const float *alpha, const int8_t *a, const int *lda, const int8_t *oa,
+ const uint8_t *b, const int *ldb, const int8_t *ob,
+ const float *beta, int32_t *c, const int *ldc, const int32_t *oc);
+
+}
+}
+}
+
+#endif // JIT_AVX512_CORE_GEMM_S8U8S32_HPP
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.cpp
new file mode 100644
index 0000000000..57554a1852
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.cpp
@@ -0,0 +1,539 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_avx512_core_gemm_s8u8s32_kern.hpp"
+
+
+#ifdef _WIN32
+static const bool is_windows = 1;
+#else
+static const bool is_windows = 0;
+#endif
+
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace Xbyak;
+
+
+
+
+// Convert between vector register lengths.
+static inline Xmm make_xmm(const Xmm &v) { return Xmm(v.getIdx()); }
+static inline Ymm make_ymm(const Xmm &v) { return Ymm(v.getIdx()); }
+
+// Load from or store to C.
+void jit_avx512_core_gemm_s8u8s32_kern::c_load(const Xbyak::Xmm &dst,
+ const Xbyak::Address &src, int nelems)
+{
+ switch (nelems) {
+ default: vmovups(dst, src); break;
+ case 8: vmovups(make_ymm(dst), src); break;
+ case 4: vmovups(make_xmm(dst), src); break;
+ case 2: vmovlps(make_xmm(dst), src); break;
+ case 1: vmovss(make_xmm(dst), src); break;
+ }
+}
+void jit_avx512_core_gemm_s8u8s32_kern::c_store(const Xbyak::Address &dst,
+ const Xbyak::Xmm &src, int nelems)
+{
+ switch (nelems) {
+ default: vmovups(dst, src); break;
+ case 8: vmovups(dst, make_ymm(src)); break;
+ case 4: vmovups(dst, make_xmm(src)); break;
+ case 2: vmovsd(dst, make_xmm(src)); break;
+ case 1: vmovss(dst, make_xmm(src)); break;
+ }
+}
+
+// Perform length-4 dot product accumulations of unsigned and signed bytes
+// in parallel.
+// Use vpdpbusd if VNNI available, otherwise emulate.
+void jit_avx512_core_gemm_s8u8s32_kern::dot_product(const Xmm &dst,
+ const Xmm &src1, const Xmm &src2)
+{
+ if (vnni)
+ vpdpbusd(dst, src1, src2);
+ else {
+ vpmaddubsw(dp_scratch, src1, src2);
+ vpmaddwd(dp_scratch, ones, dp_scratch);
+ vpaddd(dst, dst, dp_scratch);
+ }
+}
+
+// Inner kernel.
+void jit_avx512_core_gemm_s8u8s32_kern::kernel_loop(int unroll_m, int unroll_n,
+ bool cfetch)
+{
+ int um_vecs = (unroll_m + 15) >> 4;
+ Label label_kernel_loop;
+
+ L_aligned(label_kernel_loop); {
+ for (int h = 0; h < 4; h++) {
+ for (int j = 0; j < unroll_n; j++) {
+ const Zmm b = b_regs[j & 1];
+
+ vpbroadcastd(b, ptr[BO + isize *
+ (2 * j + 2 * h * unroll_n - offset_b)]);
+ dot_product(c_regs[0][j], b, a_regs[0]);
+
+ if (j == 1 && !(h & 1))
+ prefetch_b(ptr[BO + isize * (prefetch_size_b
+ + 2 * h * unroll_n - offset_b)]);
+ else if (j % 3 == 0)
+ prefetch_a(ptr[AO + isize * (prefetch_size_a
+ + 32 * (j / 3) + 2 * h * unroll_m - offset_a)]);
+
+ for (int i = 1; i < um_vecs; i++)
+ dot_product(c_regs[i][j], b, a_regs[i]);
+
+ if (cfetch && (j == std::min(1, unroll_n - 1))) {
+ if (h == 3)
+ lea(CO2, ptr[CO2 + LDC]);
+ else if (h < um_vecs)
+ prefetch_c(ptr[CO2 + (16 * h * size)]);
+ }
+
+ if (h == 3 && j == std::min(3, unroll_n - 1))
+ lea(AA, ptr[AA + (32 * isize)]);
+ }
+
+ for (int i = 0; i < um_vecs; i++)
+ vmovups(a_regs[i], ptr[AO + isize *
+ (32 * i + 2 * (h + 1) * unroll_m - offset_a)]);
+
+ if (h == 2)
+ prefetch_x(ptr[AA - (offset_a * isize)]);
+ }
+
+ add(AO, 8 * isize * unroll_m);
+ add(BO, 8 * isize * unroll_n);
+ sub(LoopCount, 1);
+ jg(label_kernel_loop, T_NEAR);
+ }
+}
+
+// k remainder loop for kernel.
+void jit_avx512_core_gemm_s8u8s32_kern::remainder_kernel(int unroll_m,
+ int unroll_n, int unroll_k, int bwidth)
+{
+ if ((unroll_m > IGEMM_UNROLL_M) || (unroll_n > IGEMM_UNROLL_N)
+ || (unroll_m < 0) || (unroll_n < 0))
+ return;
+
+ int um_vecs = (unroll_m + 15) >> 4;
+
+ for (int h = 0; h < unroll_k; h++) {
+ for (int j = 0; j < unroll_n; j++) {
+ Zmm b = b_regs[j & 1];
+ auto b_src = ptr[BO + (-isize * offset_b
+ + bwidth * (j + h * unroll_n))];
+
+ switch (bwidth) {
+ case 4:
+ vpbroadcastd(b, b_src);
+ break;
+ case 2:
+ vpbroadcastw(b, b_src);
+ break;
+ case 1:
+ vpbroadcastb(b, b_src);
+ break;
+ }
+ for (int i = 0; i < um_vecs; i++)
+ dot_product(c_regs[i][j], b, a_regs[i]);
+ }
+
+ if (unroll_k > 1) {
+ for (int i = 0; i < um_vecs; i++)
+ vmovups(a_regs[i], ptr[AO + isize * (32 * i
+ + (h + 1) * 2 * unroll_m - offset_a)]);
+ }
+ }
+
+ add(AO, unroll_k * unroll_m * bwidth);
+ add(BO, unroll_k * unroll_n * bwidth);
+}
+
+// Inner loop.
+void jit_avx512_core_gemm_s8u8s32_kern::innerloop(int unroll_m, int unroll_n)
+{
+ if ((unroll_m > IGEMM_UNROLL_M) || (unroll_n > IGEMM_UNROLL_N)
+ || (unroll_m < 0) || (unroll_n < 0))
+ return;
+
+ int um_vecs = (unroll_m + 15) >> 4;
+ int stage1 = unroll_n, stage2 = unroll_n;
+
+ Label label_kernel_loop_1, label_k_main_loop_2, label_kernel_loop_2;
+ Label label_k_main_loop_3, label_kernel_loop_3;
+ Label label_k_remainder_loop_begin, label_k_rem_4, label_k_rem_2;
+ Label label_k_rem_1, label_update_begin;
+
+ mov(AO, A);
+ for (int i = 0; i < um_vecs; i++)
+ vmovups(a_regs[i], ptr[AO + isize * (32 * i - offset_a)]);
+
+ mov(LoopCount, K);
+ sar(LoopCount, 4);
+ jle(label_k_remainder_loop_begin, T_NEAR);
+
+ // Main k loops, broken into three parts to time C prefetching.
+ sub(LoopCount, stage1 + stage2);
+ jle(label_k_main_loop_2, T_NEAR);
+
+ kernel_loop(unroll_m, unroll_n, false);
+
+ L_aligned(label_k_main_loop_2);
+ lea(CO2, ptr[CO1 + size * (std::min(unroll_m, 16) - 1)]);
+ add(LoopCount, stage1);
+ jle(label_k_main_loop_3, T_NEAR);
+
+ kernel_loop(unroll_m, unroll_n, true);
+
+ L_aligned(label_k_main_loop_3);
+ lea(CO2, ptr[CO1 + size * (std::min(unroll_m, 16) - 1)]);
+ add(LoopCount, stage2);
+ jle(label_k_remainder_loop_begin, T_NEAR);
+
+ kernel_loop(unroll_m, unroll_n, true);
+
+ // k remainder handling
+ L_aligned(label_k_remainder_loop_begin);
+ mov(LoopCount, K);
+ test(LoopCount, 8);
+ je(label_k_rem_4, T_NEAR);
+
+ remainder_kernel(unroll_m, unroll_n, 2, 4);
+
+ L_aligned(label_k_rem_4);
+ mov(LoopCount, K);
+ test(LoopCount, 4);
+ je(label_k_rem_2, T_NEAR);
+
+ remainder_kernel(unroll_m, unroll_n, 1, 4);
+
+ L_aligned(label_k_rem_2);
+ mov(LoopCount, K);
+ test(LoopCount, 2);
+ je(label_k_rem_1, T_NEAR);
+
+ Zmm zero = zmm6;
+ Zmm tmp = zmm5;
+
+ vpxorq(zero, zero, zero);
+ for (int i = 0; i < um_vecs; i++) {
+ Zmm a = a_regs[i];
+ vbroadcasti64x4(a, ptr[AO + isize * (16 * i - offset_a)]);
+ vpunpcklwd(tmp, a, zero);
+ vpunpckhwd(a, a, zero);
+ vshufi32x4(a, tmp, a, 0x44);
+ vshufi32x4(a, a, a, 0xD8);
+ }
+
+ remainder_kernel(unroll_m, unroll_n, 1, 2);
+
+ L_aligned(label_k_rem_1);
+ mov(LoopCount, K);
+ test(LoopCount, 1);
+ je(label_update_begin, T_NEAR);
+
+ vpxorq(zero, zero, zero);
+ for (int i = 0; i < um_vecs; i++) {
+ Zmm a = a_regs[i];
+ vbroadcasti32x4(a, ptr[AO + isize * (8 * i - offset_a)]);
+ vpunpcklbw(tmp, a, zero);
+ vpunpckhbw(a, a, zero);
+ vinsertf128(make_ymm(a), make_ymm(tmp), make_xmm(a), 1);
+ vpunpcklwd(tmp, a, zero);
+ vpunpckhwd(a, a, zero);
+ vshufi32x4(a, tmp, a, 0x44);
+ vshufi32x4(a, a, a, 0xD8);
+ }
+
+ remainder_kernel(unroll_m, unroll_n, 1, 1);
+
+ // Add offsets and update C.
+ L_aligned(label_update_begin);
+
+ if (enable_offset_r) {
+ // Add row offsets.
+ mov(rax, coffset_ry);
+ for (int j = 0; j < unroll_n; j++) {
+ Zmm row_offset = zmm0;
+
+ vbroadcastss(row_offset, ptr[rax + size * j]);
+
+ for (int i = 0; i < um_vecs; i++)
+ vpaddd(c_regs[i][j], c_regs[i][j], row_offset);
+ }
+ add(coffset_ry, size * unroll_n);
+ }
+
+ if (enable_offset_c) {
+ // Add column offsets.
+ mov(rax, coffset_cy);
+ for (int i = 0; i < um_vecs; i++) {
+ Zmm col_offset = zmm0;
+
+ c_load(col_offset, ptr[rax + size * 16 * i], unroll_m);
+
+ for (int j = 0; j < unroll_n; j++)
+ vpaddd(c_regs[i][j], c_regs[i][j], col_offset);
+ }
+ }
+
+ Reg64 LDC3 = rax;
+ lea(LDC3, ptr[LDC + LDC * 2]);
+
+ // C updates.
+ int c_off_j = 0;
+ for (int j = 0; j < unroll_n; j++) {
+ if (j > 0 && (j & 3) == 0) {
+ lea(CO1, ptr[CO1 + LDC * 4]);
+ c_off_j += 4;
+ }
+
+ int jj = j - c_off_j;
+
+ for (int i = 0; i < um_vecs; i++) {
+ Zmm c = c_regs[i][j];
+ Zmm c_old = zmm0;
+ decltype(LDC * jj) ldc_mult = (jj == 3) ? LDC3 : LDC * jj;
+
+ auto c_mem = ptr[CO1 + ldc_mult + size * 16 * i];
+
+ if (beta_zero)
+ c_store(c_mem, c, unroll_m);
+ else {
+ c_load(c_old, c_mem, unroll_m);
+ vpaddd(c_old, c, c_old);
+ c_store(c_mem, c_old, unroll_m);
+ }
+
+ vpxorq(c, c, c);
+ }
+ }
+
+ lea(CO1, ptr[CO1 + LDC * (unroll_n - c_off_j)]);
+}
+
+// Outer loop.
+void jit_avx512_core_gemm_s8u8s32_kern::outerloop(int unroll_x, int unroll_y,
+ Label *&cur_outerloop_label)
+{
+ Label label_m_loop, label_n_loop, label_n_remainder_loops[6];
+
+ L(*cur_outerloop_label);
+ cur_outerloop_label++;
+ if (unroll_x >= IGEMM_UNROLL_M) {
+ mov(J, M);
+ cmp(J, unroll_x);
+ jl(*cur_outerloop_label, T_NEAR); // Jump to next outerloop label.
+ } else {
+ test(J, unroll_x);
+ jle(*cur_outerloop_label, T_NEAR);
+ }
+
+ L_aligned(label_m_loop); {
+ mov(CO1, C);
+ add(C, unroll_x * size);
+
+ mov(BO, B);
+
+ mov(AA, K);
+ imul(AA, AA, unroll_x * isize);
+ lea(AA, ptr[A + AA + isize * prefetch_size_a]);
+
+ if (enable_offset_c) {
+ mov(rax, coffset_cx);
+ mov(coffset_cy, rax);
+ add(rax, unroll_x * size);
+ mov(coffset_cx, rax);
+ }
+
+ if (enable_offset_r) {
+ mov(rax, coffset_rx);
+ mov(coffset_ry, rax);
+ }
+
+ mov(I, N);
+ cmp(I, unroll_y);
+ jl(label_n_remainder_loops[0], T_NEAR);
+
+ L_aligned(label_n_loop); {
+ innerloop(unroll_x, unroll_y);
+ sub(I, unroll_y);
+ cmp(I, unroll_y);
+ jge(label_n_loop, T_NEAR);
+ }
+
+ align(16);
+
+ int label_idx = 0;
+ for (int uy = 16; uy > 0; uy >>= 1) {
+ L(label_n_remainder_loops[label_idx++]);
+ if (unroll_y > uy) {
+ test(I, uy);
+ jle(label_n_remainder_loops[label_idx], T_NEAR);
+
+ innerloop(unroll_x, uy);
+ align(16);
+ }
+ }
+ L(label_n_remainder_loops[label_idx]);
+
+ mov(A, AO);
+ if (unroll_x >= IGEMM_UNROLL_M) {
+ sub(J, unroll_x);
+ cmp(J, unroll_x);
+ jge(label_m_loop);
+ }
+ }
+
+ align(16);
+}
+
+void jit_avx512_core_gemm_s8u8s32_kern::generate()
+{
+ // Prologue
+ preamble();
+ sub(rsp, stack_alloc_size);
+
+ if (is_windows) {
+ mov(A, arg_a);
+ mov(B, arg_b);
+ }
+
+ mov(C, arg_c);
+ mov(LDC, arg_ldc);
+
+ sub(A, -offset_a * isize);
+ sub(B, -offset_b * isize);
+
+ mov(M, qword[M]);
+ mov(N, qword[N]);
+ mov(K, qword[K]);
+
+ lea(LDC, ptr[LDC * size]);
+
+ if (enable_offset_c) {
+ mov(rax, arg_coffset_c);
+ mov(coffset_cx, rax);
+ }
+ if (enable_offset_r) {
+ mov(rax, arg_coffset_r);
+ mov(coffset_rx, rax);
+ }
+
+ for (int i = 0; i < (max_unroll_m >> 4); i++) {
+ for (int j = 0; j < max_unroll_n; j++) {
+ auto &c = c_regs[i][j];
+ vpxorq(c, c, c);
+ }
+ }
+
+ if (!vnni) {
+ mov(rax, 1);
+ movq(make_xmm(ones), rax);
+ vpbroadcastw(ones, make_xmm(ones));
+ }
+
+ Label outerloop_labels[8];
+ Label *cur_outerloop_label = &outerloop_labels[0];
+
+ // Main m loop.
+ outerloop(IGEMM_UNROLL_M, IGEMM_UNROLL_N, cur_outerloop_label);
+
+ // m remainder loops.
+ for (int um = 32; um > 0; um >>= 1)
+ if (IGEMM_UNROLL_M > um)
+ outerloop(um, IGEMM_UNROLL_N, cur_outerloop_label);
+
+ L(*cur_outerloop_label);
+
+ // Epilogue.
+ add(rsp, stack_alloc_size);
+ postamble();
+}
+
+
+jit_avx512_core_gemm_s8u8s32_kern::jit_avx512_core_gemm_s8u8s32_kern(bool
+ beta_zero_, bool enable_offset_c_, bool enable_offset_r_) :
+ jit_generator(nullptr, 100000), arg_a(0), arg_b(0), arg_c(0), arg_ldc(0),
+ arg_coffset_c(0), arg_coffset_r(0), coffset_cx(0), coffset_cy(0),
+ coffset_rx(0), coffset_ry(0)
+{
+ beta_zero = beta_zero_;
+ enable_offset_c = enable_offset_c_;
+ enable_offset_r = enable_offset_r_;
+ vnni = mayiuse(avx512_core_vnni);
+
+ // Assign integer registers
+ M = is_windows ? rcx : rdi;
+ N = is_windows ? rdx : rsi;
+ K = is_windows ? r8 : rdx;
+ A = is_windows ? rsi : r8;
+ B = r9;
+ C = r10;
+ LDC = r11;
+ I = r12;
+ J = r13;
+ LoopCount = rax;
+ AO = r14;
+ BO = r15;
+ CO1 = rbx;
+ CO2 = rbp;
+ AA = is_windows ? rdi : rcx;
+
+ // Assign vector registers
+ dp_scratch = zmm6;
+ ones = zmm7;
+ for (int i = 0; i < (max_unroll_m >> 4); i++)
+ a_regs[i] = Zmm(i);
+ b_regs[0] = zmm4;
+ b_regs[1] = zmm5;
+
+ int rn = 0;
+ for (int i = 0; i < (max_unroll_m >> 4); i++)
+ for (int j = 0; j < max_unroll_n; j++)
+ c_regs[i][j] = Zmm(8 + rn++);
+
+ // Assign stack variables.
+ stack_alloc_size = 32;
+ auto args_offset = stack_alloc_size + get_size_of_abi_save_regs()
+ + 8 + (is_windows ? 48 : 0);
+
+ arg_a = ptr[rsp + (args_offset - 16)];
+ arg_b = ptr[rsp + (args_offset - 8)];
+ arg_c = ptr[rsp + (args_offset + 0)];
+ arg_ldc = ptr[rsp + (args_offset + 8)];
+ arg_coffset_c = ptr[rsp + (args_offset + 16)];
+ arg_coffset_r = ptr[rsp + (args_offset + 24)];
+
+ coffset_cx = qword[rsp + 0];
+ coffset_cy = qword[rsp + 8];
+ coffset_rx = qword[rsp + 16];
+ coffset_ry = qword[rsp + 24];
+
+ generate();
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.hpp
new file mode 100644
index 0000000000..e8efcc1cc8
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemm_s8u8s32_kern.hpp
@@ -0,0 +1,101 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef IGEMM_KERNEL_GENERATOR_HPP
+#define IGEMM_KERNEL_GENERATOR_HPP
+
+#include "jit_generator.hpp"
+
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+class jit_avx512_core_gemm_s8u8s32_kern : public jit_generator {
+public:
+ jit_avx512_core_gemm_s8u8s32_kern(bool beta_zero_, bool enable_offset_c_,
+ bool enable_offset_r_);
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_gemm_s8u8s32_kern);
+
+protected:
+ bool beta_zero;
+ bool enable_offset_c, enable_offset_r;
+ bool vnni;
+
+ void prefetch_a(const Xbyak::Address &src) {
+ prefetcht0(src);
+ }
+ void prefetch_b(const Xbyak::Address &src) {
+ prefetcht0(src);
+ }
+ void prefetch_c(const Xbyak::Address &src) {
+ prefetchw(src);
+ }
+ void prefetch_x(const Xbyak::Address &src) {
+ prefetcht0(src);
+ }
+
+ void c_load(const Xbyak::Xmm &dst, const Xbyak::Address &src, int nelems);
+ void c_store(const Xbyak::Address &dst, const Xbyak::Xmm &src, int nelems);
+
+ void dot_product(const Xbyak::Xmm &dst, const Xbyak::Xmm &src1,
+ const Xbyak::Xmm &src2);
+ void kernel_loop(int unroll_m, int unroll_n, bool cfetch);
+ void remainder_kernel(int unroll_m, int unroll_n, int unroll_k, int bwidth);
+ void innerloop(int unroll_m, int unroll_n);
+ void outerloop(int unroll_x, int unroll_y, Xbyak::Label *&outerloop_label);
+
+ void generate();
+
+
+private:
+ static const int IGEMM_UNROLL_M = 48;
+ static const int IGEMM_UNROLL_N = 8;
+
+ static const int isize = 2;
+ static const int size = 4;
+
+ // Prefetch configuration
+ static const int prefetch_size_a = 32 * 5;
+ static const int prefetch_size_b = 32 * 4;
+
+ static const int offset_a = 256, offset_b = 256;
+ static const int max_unroll_m = 48, max_unroll_n = 8;
+
+ // Integer register assignments
+ Xbyak::Reg64 M, N, K, A, B, C, LDC, I, J, LoopCount;
+ Xbyak::Reg64 AO, BO, CO1, CO2, AA;
+
+ // Vector register assignments
+ Xbyak::Zmm dp_scratch, ones, a_regs[max_unroll_m >> 4], b_regs[2];
+ Xbyak::Zmm c_regs[max_unroll_m >> 4][max_unroll_n];
+
+ // Stack variable assignments
+ int stack_alloc_size;
+ Xbyak::Address arg_a, arg_b, arg_c, arg_ldc, arg_coffset_c, arg_coffset_r;
+ Xbyak::Address coffset_cx, coffset_cy, coffset_rx, coffset_ry;
+
+ void L_aligned(Xbyak::Label &label, int alignment = 16) {
+ align(alignment);
+ L(label);
+ }
+};
+
+}
+}
+}
+
+#endif /* header guard */
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemv_s8u8s32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemv_s8u8s32.cpp
new file mode 100644
index 0000000000..4f0b10dadd
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_gemv_s8u8s32.cpp
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright 2019 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+
+#include "gemv.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+int gemm_s8u8s32_jump_to_gemv_s8u8s32(blas_t *arg) {
+
+ blas_t arg_gemv = *arg;
+
+ if ((arg -> offsetc == FIX_OFFSET) && // Fix offset
+ (arg -> ao == 0) &&
+ (arg -> bo == 0) &&
+ (arg -> co[0] == 0) &&
+ (*(arg -> alpha) == 1.0f) &&
+ ((*(arg -> beta) == 1.0f) || *(arg -> beta) == 0.0f)) {
+
+ if (arg -> n == 1) {
+
+ if (arg -> transa == 1) { // A transpose
+ arg_gemv.n = arg -> k;
+ arg_gemv.ldc = 1;
+ arg_gemv.swap = 0;
+ if (arg -> transb == 0) { // B non transpose
+ arg_gemv.ldb = 1;
+ }
+ // B transpose arg_gemv.ldb = arg -> ldb
+ gemv_threading_driver(&arg_gemv);
+ return 1;
+ }
+ }
+
+ if (arg -> m == 1) {
+
+ if (arg -> transb == 0) { // B non transpose
+ arg_gemv.transa = 1;
+ arg_gemv.m = arg -> n;
+ arg_gemv.n = arg -> k;
+ arg_gemv.a = (int8_t *) arg -> b;
+ arg_gemv.lda = arg -> ldb;
+ arg_gemv.b = (uint8_t *) arg -> a;
+ arg_gemv.swap = 1;
+ if (arg -> transa == 0) { // A non transpose
+ arg_gemv.ldb = arg -> lda;
+ }
+ else { // A transpose
+ arg_gemv.ldb = 1;
+ }
+ gemv_threading_driver(&arg_gemv);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+int gemv_kernel_driver(blas_t *arg) {
+
+ dim_t m = arg -> m;
+ dim_t n = arg -> n;
+ uint8_t *a = (uint8_t *) arg -> a;
+ dim_t lda = arg -> lda;
+ int8_t *b = (int8_t *) arg -> b;
+ float beta = *(arg -> beta);
+
+ if (arg -> swap) {
+ arg -> gemv_u8s8s32_kernel(m, n, 1.0f, a, lda, b, beta, arg -> c);
+ }
+ else {
+ arg -> gemv_s8u8s32_kernel(arg -> m, arg -> n, 1.0f, arg -> a,
+ arg -> lda, arg -> b, *(arg -> beta), arg -> c);
+ }
+
+ return 0;
+}
+
+int gemv_threading_driver(blas_t *arg) {
+
+ dim_t nthr_m, nthr_n = 1;
+ dim_t MB, NB, UM = 16, UN = 64;
+ dim_t BLOCKM = 192, BLOCKN = 3072;
+ int status;
+ dim_t i;
+
+ dim_t nthr = (mkldnn_in_parallel()) ? 1 : mkldnn_get_max_threads();
+
+ uint8_t *new_x = NULL;
+ int32_t *tmp_y = NULL, *new_y = NULL;
+
+ dim_t m = arg -> m, n = arg -> n;
+
+ blas_t arg_seq = *arg;
+ float zero = 0.0f;
+
+ nthr_m = std::min(std::max(m / BLOCKM, (dim_t) 1), nthr);
+ MB = m / nthr_m;
+ MB = (((MB / UM) * UM) == MB) ? MB : (MB / UM) * UM + UM;
+ nthr_m = (((m / MB) * MB) == m) ? m / MB : m / MB + 1;
+ nthr_m = std::min(std::max(nthr_m, (dim_t) 1), nthr);
+
+ while ((nthr_m * (nthr_n + 1) <= nthr) && ((n / (nthr_n + 1)) >= BLOCKN)) {
+ nthr_n++;
+ }
+
+ NB = n / nthr_n;
+ NB = (((NB / UN) * UN) == NB) ? NB : (NB / UN) * UN + UN;
+ nthr_n = (((n / NB) * NB) == n) ? n / NB : n / NB + 1;
+ nthr_n = std::min(std::max(nthr_n, (dim_t) 1), nthr / nthr_m);
+
+ nthr = nthr_m * nthr_n;
+
+ if (arg -> ldb != 1) {
+ new_x = (uint8_t *)malloc(n, 64);
+ if (new_x == NULL)
+ return 1;
+ for (i = 0; i < n; i++) {
+ new_x[i] = (arg -> b)[i * arg -> ldb];
+ }
+ arg_seq.b = new_x;
+ arg_seq.ldb = 1;
+ }
+ else new_x = (uint8_t *) arg -> b;
+
+ if (arg -> ldc != 1) {
+ new_y = (int32_t *) malloc(nthr_m * PADD_BYTESIZE_ONPAGE(MB, sizeof(int32_t)), 64);
+ if (new_y == NULL) {
+ if (arg -> ldb != 1) {
+ free(new_x);
+ }
+ return 1;
+ }
+ }
+
+ // GEMV computation
+ if (nthr == 1) {
+
+ if (arg -> ldc != 1) {
+ if (*(arg -> beta) != 0.0f) {
+ for (i = 0; i < m; i++) {
+ new_y[i] = arg -> c[i * arg -> ldc];
+ }
+ }
+ }
+
+ status = gemv_kernel_driver(&arg_seq);
+
+ if (arg -> ldc != 1) {
+ for (i = 0; i < m; i++) {
+ arg -> c[i * arg -> ldc] = new_y[i];
+ }
+ }
+
+ if (arg -> ldb != 1) {
+ free(new_x);
+ }
+ if (arg -> ldc != 1) {
+ free(new_y);
+ }
+ return status;
+ }
+
+ if (nthr_n > 1) {
+ tmp_y = (int32_t *) malloc((nthr_n - 1) * PADD_BYTESIZE_ONPAGE(m, sizeof(int32_t)), PAGESIZE);
+ if (tmp_y == NULL) {
+ if (arg -> ldb != 1) {
+ free(new_x);
+ }
+ return 1;
+ }
+ }
+
+ parallel_nd((int) nthr, [&](const dim_t ithr) {
+
+ dim_t m_from, m_to, myM;
+ dim_t n_from, n_to, myN;
+
+ dim_t n_id, m_id;
+ dim_t loc_incy = 1;
+ int32_t *loc_y;
+
+ blas_t arg_loc = arg_seq;
+ int j;
+
+ m_id = ithr / nthr_n;
+ n_id = ithr % nthr_n;
+
+ m_from = MB * m_id;
+ m_to = MB * (m_id + 1);
+ if ((m_to > m) || (m_id == nthr_m - 1))
+ m_to = m;
+
+ myM = m_to - m_from;
+
+ n_from = NB * n_id;
+ n_to = NB * (n_id + 1);
+ if ((n_to > n) || (n_id == nthr_n - 1))
+ n_to = n;
+
+ myN = n_to - n_from;
+
+ if (n_id != 0) {
+ arg_loc.beta = &zero;
+ loc_y = tmp_y + (NEXT_THR_STRIDE(m, sizeof(int32_t))) * (n_id - 1) + m_from;
+ }
+ else {
+ if (arg -> ldc == 1) {
+ loc_y = arg_seq.c + m_from;
+ }
+ else {
+ // need to copy the block of c in new_y
+ loc_y = new_y + m_id * NEXT_THR_STRIDE(MB, sizeof(int32_t));
+ if (*(arg -> beta) != 0.0f) {
+ for (j = 0; j < myM; j++) {
+ loc_y[j] = arg -> c[(m_from + j) * arg -> ldc];
+ }
+ }
+ }
+ }
+
+ arg_loc.m = myM;
+ arg_loc.n = myN;
+ arg_loc.a = arg_seq.a + m_from * arg_seq.lda + n_from;
+ arg_loc.b = arg_seq.b + n_from;
+ arg_loc.c = loc_y;
+ arg_loc.ldc = loc_incy;
+
+ gemv_kernel_driver(&arg_loc);
+
+ if ((n_id == 0) && (arg -> ldc != 1)) {
+ for (j = 0; j < myM; j++) {
+ arg -> c[(m_from + j) * arg -> ldc] = loc_y[j];
+ }
+ }
+
+ });
+
+ if (nthr_n > 1) {
+ parallel_nd((int) nthr_m, [&](const dim_t ithr) {
+
+ dim_t j, j_from, j_to, ii;
+ int32_t acc;
+
+ j_from = MB * ithr;
+ j_to = MB * (ithr + 1);
+ if ((j_to > m) || (ithr == nthr - 1))
+ j_to = m;
+
+ for (j = j_from; j < j_to; j++) {
+ acc = 0;
+ for (ii = 0; ii < nthr_n - 1; ii++) {
+ acc += tmp_y[ii * NEXT_THR_STRIDE(m, sizeof(int32_t)) + j];
+ }
+ (arg -> c)[j * arg -> ldc] += acc;
+ }
+ });
+ free(tmp_y);
+ }
+
+ if (arg -> ldb != 1) {
+ free(new_x);
+ }
+
+ if (arg -> ldc != 1) {
+ free(new_y);
+ }
+
+ return 0;
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.cpp
new file mode 100644
index 0000000000..c57a8c1d12
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.cpp
@@ -0,0 +1,411 @@
+/*******************************************************************************
+ * Copyright 2019 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+
+#include "jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp"
+
+#ifdef _WIN32
+#define is_windows 1
+#else
+#define is_windows 0
+#endif
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+void jit_avx512_core_gemv_s8u8s32_kern::vnni(Xbyak::Zmm acc, Xbyak::Zmm b,
+ Xbyak::Zmm a, Xbyak::Zmm tmp,
+ Xbyak::Zmm one, bool swap,
+ int use_vnni) {
+
+ if (use_vnni) {
+ if (swap)
+ vpdpbusd(acc, a, b);
+ else
+ vpdpbusd(acc, b, a);
+ }
+
+ else {
+ if (swap)
+ vpmaddubsw(tmp, a, b);
+ else
+ vpmaddubsw(tmp, b, a);
+ vpmaddwd(tmp, tmp, one);
+ vpaddd(acc, tmp, acc);
+ }
+
+}
+
+void jit_avx512_core_gemv_s8u8s32_kern::n_loop_body(int start_a_idx, int start_acc_idx,
+ int b_idx, int nreg_acc,
+ Xbyak::Reg64 A, Xbyak::Reg64 lda,
+ Xbyak::Reg64 X, Xbyak::Zmm tmp,
+ Xbyak::Zmm one, bool swap, int use_vnni,
+ int use_mask, Xbyak::Opmask mask_n) {
+
+ int i;
+ int nreg_A = nreg_acc / 2 + (nreg_acc % 2);
+
+ // load X + j
+ if (use_mask)
+ vmovdqu8(Xbyak::Zmm(b_idx) | mask_n | T_z, ptr[X]);
+ else
+ vmovdqu8(Xbyak::Zmm(b_idx), ptr[X]);
+
+ xor_(r14, r14);
+ // load values of A
+ for (i = 0; i < nreg_A; i++) {
+ if (use_mask)
+ vmovdqu8(Xbyak::Zmm(start_a_idx + i) | mask_n | T_z, ptr[A + r14]);
+ else
+ vmovdqu8(Xbyak::Zmm(start_a_idx + i), ptr[A + r14]);
+ add(r14, lda);
+ }
+
+ for (i = 0; i < nreg_A; i++) {
+ // vnni (acc, b, a, tmp, one, swap, use_vnni)
+ vnni(Xbyak::Zmm(start_acc_idx + i), Xbyak::Zmm(b_idx),
+ Xbyak::Zmm(start_a_idx + i), tmp, one, swap, use_vnni);
+ }
+
+ for (i = 0; i < nreg_A - (nreg_acc % 2); i++) {
+ if (use_mask)
+ vmovdqu8(Xbyak::Zmm(start_a_idx + i) | mask_n | T_z, ptr[A + r14]);
+ else
+ vmovdqu8(Xbyak::Zmm(start_a_idx + i), ptr[A + r14]);
+ add(r14, lda);
+ }
+
+ for (i = 0; i < nreg_A - (nreg_acc % 2); i++) {
+ vnni(Xbyak::Zmm(start_acc_idx + i + nreg_A), Xbyak::Zmm(b_idx),
+ Xbyak::Zmm(start_a_idx + i), tmp, one, swap, use_vnni);
+ }
+
+}
+
+void jit_avx512_core_gemv_s8u8s32_kern::shuffle_and_add(Xbyak::Zmm dest, Xbyak::Zmm A,
+ Xbyak::Zmm B, Xbyak::Zmm C,
+ Xbyak::Zmm D) {
+
+ vshufi32x4(dest, A, C, 0x44);
+ vshufi32x4(A, A, C, 0xEE);
+ vpaddd(C, dest, A); // C = A0 + A2|A1 + A3|C0 + C2|C1 + C3
+
+ vshufi32x4(dest, B, D, 0x44);
+ vshufi32x4(B, B, D, 0xEE);
+ vpaddd(D, dest, B); // D = B0 + B2|B1 + B3|D0 + D2|D1 + D3
+
+ vshufi32x4(A, C, D, 0x88);
+ vshufi32x4(B, C, D, 0xDD);
+ vpaddd(dest, A, B); // dest = SAi|SBi|SCi|SDi
+
+}
+
+void jit_avx512_core_gemv_s8u8s32_kern::update_c(int nreg_acc, Xbyak::Reg64 Y,
+ int start_a_idx, int start_acc_idx,
+ Xbyak::Xmm beta, int use_mask,
+ Xbyak::Opmask mask_m) {
+
+ int l, i, k, j, last_it;
+ Xbyak::Label store_label;
+
+ l = 0;
+ for (k = 0; k < nreg_acc; k += 8) {
+ for (i = 0, j = k; i < 8; i += 4, j += 2) {
+ if (j < nreg_acc) {
+ // shuffle per block of 4 registers
+ shuffle_and_add(Xbyak::Zmm(start_a_idx + l), // dest
+ Xbyak::Zmm(start_acc_idx + j), // A = acc0
+ Xbyak::Zmm(start_acc_idx + 1 + j), // B = acc1
+ Xbyak::Zmm(start_acc_idx + 4 + j), // C = acc4
+ Xbyak::Zmm(start_acc_idx + 5 + j)); // D = acc5
+
+ // extract low and high from dest and hadd
+ vextracti32x8(Xbyak::Ymm(start_a_idx + l + 1), Xbyak::Zmm(start_a_idx + l), 0);
+ vextracti32x8(Xbyak::Ymm(start_a_idx + l + 2), Xbyak::Zmm(start_a_idx + l), 1);
+ vphaddd(Xbyak::Ymm(start_a_idx + l),
+ Xbyak::Ymm(start_a_idx + l + 1),
+ Xbyak::Ymm(start_a_idx + l + 2));
+ }
+ l++;
+ }
+
+ vphaddd(Xbyak::Ymm(start_a_idx + l),
+ Xbyak::Ymm(start_a_idx + l - 2),
+ Xbyak::Ymm(start_a_idx + l - 1));
+
+ l++;
+ }
+
+ // eventually add with C and store new value
+ vxorps(Xbyak::Ymm(start_a_idx),
+ Xbyak::Ymm(start_a_idx),
+ Xbyak::Ymm(start_a_idx));
+ vucomiss(beta, Xbyak::Ymm(start_a_idx));
+ je(store_label, T_NEAR);
+
+ // beta = 1
+ for (k = 0, l = 2; k < nreg_acc; k += 8, l += 3) {
+ // load Y and add
+ last_it = (k + 8) > nreg_acc;
+ if (use_mask && last_it)
+ vmovdqu32(Xbyak::Ymm(start_a_idx + k / 8) | mask_m | T_z, ptr[Y + (k / 8) * 32]);
+ else
+ vmovdqu32(Xbyak::Ymm(start_a_idx + k / 8), ptr[Y + (k / 8) * 32]);
+
+ vpaddd(Xbyak::Ymm(start_a_idx + l),
+ Xbyak::Ymm(start_a_idx + l),
+ Xbyak::Ymm(start_a_idx + k / 8));
+ }
+
+ // store
+ aligned_label(store_label);
+ for (k = 0, l = 2; k < nreg_acc; k += 8, l += 3) {
+ last_it = (k + 8) > nreg_acc;
+ if (use_mask && last_it)
+ vmovdqu32(ptr[Y + (k / 8) * 32], Xbyak::Ymm(start_a_idx + l) | mask_m);
+ else
+ vmovdqu32(ptr[Y + (k / 8) * 32], Xbyak::Ymm(start_a_idx + l));
+ }
+
+}
+
+template <typename T>
+T jit_avx512_core_gemv_s8u8s32_kern::generate(int use_vnni) {
+
+ Xbyak::Opmask mask_n = k1, mask_m = k2;
+ Xbyak::Label one_label, m_tail_label, m_loop_label, n_loop_label;
+ Xbyak::Label n_tail_label, update_c_label, end_label;
+ constexpr unsigned int n_labels = (1 << unroll_m) - 1;
+ Xbyak::Label m_tail_label_case[n_labels];
+ Xbyak::Label n_loop_label_case[n_labels];
+ Xbyak::Label n_tail_label_case[n_labels];
+ Xbyak::Label update_c_label_case[n_labels];
+
+ int i, ii;
+
+ Xbyak::Zmm one, tmp;
+ Xbyak::Reg64 n = abi_param2, m = abi_param1;
+ Xbyak::Reg64 A = is_windows ? abi_param4 : abi_param3;
+ Xbyak::Reg64 lda = is_windows ? abi_param3 : abi_param4;
+ Xbyak::Reg64 X = is_windows ? rdi : r8;
+ Xbyak::Xmm beta = xmm1;
+ Xbyak::Reg64 Y = is_windows ? rsi : r9;
+
+ bool swap = !std::is_same<T, gemv_s8u8s32_kernel_t>::value;
+
+ // Windows: read on the stack lda, X, beta, Y
+
+ int zmm_idx = 1;
+ int nreg_acc = 1 << unroll_m;
+ int nreg_A = 1 << (unroll_m - 1);
+ int nreg_A_acc = nreg_acc + nreg_A;
+
+ if (!use_vnni) {
+ // set a zmm register to one
+ tmp = Xbyak::Zmm(0);
+ one = Xbyak::Zmm(zmm_idx + 1);
+ zmm_idx += 2; // one + tmp
+ }
+ else {
+ beta = xmm0;
+ }
+
+ preamble();
+
+ if (is_windows) {
+ mov(lda, ptr[rsp + get_size_of_abi_save_regs() + 40]);
+ mov(X, ptr[rsp + get_size_of_abi_save_regs() + 48]);
+ movss(beta, ptr[rsp + get_size_of_abi_save_regs() + 56]);
+ mov(Y, ptr[rsp + get_size_of_abi_save_regs() + 64]);
+ }
+
+ if (use_vnni && !is_windows) {
+ movaps(beta, xmm1);
+ }
+
+ mov(rax, (1 << unroll_n) - 1);
+ kmovq(k3, rax);
+
+ and_(rax, n); // rax contains n & ((1 << unroll_n) - 1)
+ mov(rbx, 1);
+ shlx(rbx, rbx, rax);
+ sub(rbx, 1);
+ kmovq(mask_n, rbx);
+ // mask_n set (AVX512 only), can use rax and rbx again
+
+ // set mask_m for update of the C matrix
+ // load/store on the C matrix use Ymm so tail according to Ymm size
+ mov(rax, 7); // 8 * 32 = 256 Ymm size
+ and_(rax, m); // rax contains m & 7
+ mov(rbx, 1);
+ shlx(rbx, rbx, rax);
+ sub(rbx, 1);
+ kmovq(mask_m, rbx);
+ // mask_m set (AVX512 only), can use rax and rbx again
+
+ // setup register of ones when VNNI instructions not available
+ if (!use_vnni) {
+ vmovdqu16(one, ptr[rip + one_label]);
+ }
+
+ // M loop
+ // base pointer for A rax contains a + i * lda
+ // Loop stop when rax >= a + (m & mask_um) * lda = rbx
+ // loop increment r10 = um * lda
+ // rbp = Y + i
+ mov(rax, A); // i = 0
+ mov(rbx, m);
+ and_(rbx, mask_um);
+ imul(rbx, lda);
+ add(rbx, A);
+ mov(r10, lda);
+ sal(r10, unroll_m);
+ mov(rbp, Y);
+
+ // N loop
+ // base pointer for X r11 contains x + j
+ // Loop stop when r11 >= x + n & mask_un = r12
+ // loop increment un
+ // r13 = rax + j = A + i * lda + j
+ mov(r12, n);
+ and_(r12, mask_un);
+ add(r12, X);
+
+ // M loop
+ aligned_label(m_loop_label);
+ cmp(rax, rbx);
+ jge(m_tail_label, T_NEAR);
+
+ // enter M loop
+ for(i = 0; i < nreg_acc; i++) {
+ vpxorq(Xbyak::Zmm(i + zmm_idx + nreg_A),
+ Xbyak::Zmm(i + zmm_idx + nreg_A),
+ Xbyak::Zmm(i + zmm_idx + nreg_A));
+ }
+
+ // N loop
+ mov(r11, X); // j = 0
+ mov(r13, rax);
+ aligned_label(n_loop_label);
+ cmp(r11, r12);
+ jge(n_tail_label, T_NEAR);
+
+ // enter N loop
+
+ n_loop_body(zmm_idx, zmm_idx + nreg_A, zmm_idx + nreg_A_acc, nreg_acc,
+ r13, lda, r11, tmp, one, swap, use_vnni, 0, mask_n);
+
+ // increment rax with un
+ add(r11, 1 << unroll_n);
+ add(r13, 1 << unroll_n);
+ jmp(n_loop_label, T_NEAR);
+ // end N loop
+
+ // N tail
+ aligned_label(n_tail_label);
+
+ ktestq(mask_n, k3);
+ je(update_c_label, T_NEAR);
+ n_loop_body(zmm_idx, zmm_idx + nreg_A, zmm_idx + nreg_A_acc, nreg_acc,
+ r13, lda, r11, tmp, one, swap, use_vnni, 1, mask_n);
+
+ // update C matrix
+ aligned_label(update_c_label);
+
+ update_c(nreg_acc, rbp, zmm_idx, zmm_idx + nreg_A, beta, 0, mask_m);
+
+ // increment rax with um * lda
+ add(rax, r10);
+ add(rbp, 1 << (unroll_m + 2));
+ jmp(m_loop_label, T_NEAR);
+ // end M loop
+
+ // M tail
+ aligned_label(m_tail_label);
+
+ // r10 will contain m_tail = m % unroll_m = m & (1 << unroll_m) - 1
+ mov(r10, m);
+ and_(r10, (1 << unroll_m) - 1);
+ for (ii = 1; ii < 1 << unroll_m; ii++) {
+ aligned_label(m_tail_label_case[ii-1]);
+ cmp(r10, ii);
+ if (ii == (1 << unroll_m) - 1)
+ jne(end_label, T_NEAR);
+ else
+ jne(m_tail_label_case[ii], T_NEAR);
+
+ // m_tail = i, use i accumulators
+
+ for(i = 0; i < ii; i++) {
+ vpxorq(Xbyak::Zmm(i + zmm_idx + nreg_A),
+ Xbyak::Zmm(i + zmm_idx + nreg_A),
+ Xbyak::Zmm(i + zmm_idx + nreg_A));
+ }
+
+ // N loop
+ mov(r11, X); // j = 0
+ mov(r13, rax);
+ aligned_label(n_loop_label_case[ii - 1]);
+ cmp(r11, r12);
+ jge(n_tail_label_case[ii - 1], T_NEAR);
+
+ n_loop_body(zmm_idx, zmm_idx + nreg_A, zmm_idx + nreg_A_acc, ii, r13,
+ lda, r11, tmp, one, swap, use_vnni, 0, mask_n);
+
+ // increment rax with un
+ add(r11, 1 << unroll_n);
+ add(r13, 1 << unroll_n);
+ jmp(n_loop_label_case[ii - 1], T_NEAR);
+ // end N loop
+
+ // N tail
+ aligned_label(n_tail_label_case[ii - 1]);
+ ktestq(mask_n, k3);
+ je(update_c_label_case[ii - 1], T_NEAR);
+ n_loop_body(zmm_idx, zmm_idx + nreg_A, zmm_idx + nreg_A_acc, ii, r13,
+ lda, r11, tmp, one, swap, use_vnni, 1, mask_n);
+
+ // update C matrix
+ aligned_label(update_c_label_case[ii - 1]);
+ update_c(ii, rbp, zmm_idx, zmm_idx + nreg_A, beta, 1, mask_m);
+
+ if (ii < ((1 << unroll_m) - 1))
+ jmp(end_label, T_NEAR);
+ }
+
+ aligned_label(end_label);
+
+ postamble();
+
+ if (!use_vnni) {
+ aligned_label(one_label);
+ for (i = 0; i < size_vec_reg/8; i++)
+ dq(0x0001000100010001);
+ }
+
+ return (T) getCode();
+}
+
+template jit_avx512_core_gemv_s8u8s32_kern::gemv_s8u8s32_kernel_t
+jit_avx512_core_gemv_s8u8s32_kern::generate<jit_avx512_core_gemv_s8u8s32_kern::gemv_s8u8s32_kernel_t>(int);
+
+template jit_avx512_core_gemv_s8u8s32_kern::gemv_u8s8s32_kernel_t
+jit_avx512_core_gemv_s8u8s32_kern::generate<jit_avx512_core_gemv_s8u8s32_kern::gemv_u8s8s32_kernel_t>(int);
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp
new file mode 100644
index 0000000000..9ea23a5f56
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_kernel_gemv_s8u8s32_kern.hpp
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright 2019 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+
+#include "jit_generator.hpp"
+#include "common.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+class jit_avx512_core_gemv_s8u8s32_kern : jit_generator {
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_gemv_s8u8s32_kern);
+
+ // assumes untoll_{m,n} are a power of 2
+ static constexpr unsigned int unroll_m = 4; // real unrolling factor is 2^unroll_m
+ const int mask_um = 0xFFFFFFF0;
+ static constexpr unsigned int unroll_n = 6; // real unrolling factor is 2^unroll_n
+ const int mask_un = 0xFFFFFFC0;
+ const int size_vec_reg = 64; // bytes
+
+ void aligned_label(Xbyak::Label &label, int alignment = 16) {
+ align(alignment);
+ L(label);
+ }
+
+ void vnni(Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm, bool, int);
+ void n_loop_body(int, int, int, int, Xbyak::Reg64, Xbyak::Reg64,
+ Xbyak::Reg64, Xbyak::Zmm, Xbyak::Zmm, bool, int, int, Xbyak::Opmask);
+ void shuffle_and_add(Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm, Xbyak::Zmm);
+ void update_c(int, Xbyak::Reg64, int, int, Xbyak::Xmm, int, Xbyak::Opmask);
+
+public:
+ jit_avx512_core_gemv_s8u8s32_kern() : jit_generator(nullptr, GEMM_CODE_SIZE) {};
+
+ // m, n, alpha, a, lda, x, beta, y
+ typedef void (*gemv_s8u8s32_kernel_t)(const dim_t, const dim_t, const float,
+ const int8_t*, const dim_t, const uint8_t*,
+ const float, int32_t*);
+ typedef void (*gemv_u8s8s32_kernel_t)(const dim_t, const dim_t, const float,
+ const uint8_t*, const dim_t, const int8_t*,
+ const float, int32_t*);
+
+ template <typename T>
+ T generate(int use_vnni);
+
+};
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_an_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_an_kern.cpp
new file mode 100644
index 0000000000..544cd2ff25
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_an_kern.cpp
@@ -0,0 +1,819 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_generator.hpp"
+#include "common.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+jit_avx512_core_u8_copy_an_kern::jit_avx512_core_u8_copy_an_kern(): jit_generator(nullptr, GEMM_CODE_SIZE)
+{
+
+#ifndef _WIN32
+#define M rdi
+#define N rsi
+#define A rdx
+#define LDA rcx
+#define ALPHA r8
+#define B r9
+
+#define I rax
+#define A1 r10
+#define A2 r8
+#define LDA3 r11
+
+#else
+
+#define M rcx
+#define N rdx
+#define A r8
+#define LDA r9
+#define ALPHA rax
+#define B rdi
+
+#define I rax
+#define A1 rsi
+#define A2 r10
+#define LDA3 r11
+
+#define ARG_ALPHA 40+stacksize+rsp
+#define ARG_B 48+stacksize+rsp
+
+#endif
+
+inLocalLabel();
+{
+
+Xbyak::Label l170;
+Xbyak::Label l1f0;
+Xbyak::Label l20;
+Xbyak::Label l224;
+Xbyak::Label l234;
+Xbyak::Label l240;
+Xbyak::Label l254;
+Xbyak::Label l32c;
+Xbyak::Label l34;
+Xbyak::Label l388;
+Xbyak::Label l3b0;
+Xbyak::Label l3c0;
+Xbyak::Label l3cc;
+Xbyak::Label l3dc;
+Xbyak::Label l454;
+Xbyak::Label l48c;
+Xbyak::Label l4a8;
+Xbyak::Label l4b8;
+Xbyak::Label l4c4;
+Xbyak::Label l4d8;
+Xbyak::Label l570;
+Xbyak::Label l5c4;
+Xbyak::Label l5f0;
+Xbyak::Label l60c;
+Xbyak::Label l61c;
+Xbyak::Label l628;
+Xbyak::Label l638;
+Xbyak::Label l6b0;
+Xbyak::Label l6f4;
+Xbyak::Label l720;
+Xbyak::Label l73c;
+Xbyak::Label l74c;
+Xbyak::Label l758;
+Xbyak::Label l76c;
+Xbyak::Label l804;
+Xbyak::Label l858;
+Xbyak::Label l88c;
+Xbyak::Label l8a4;
+Xbyak::Label l8b2;
+Xbyak::Label l8bc;
+Xbyak::Label l8cc;
+Xbyak::Label l944;
+Xbyak::Label l98c;
+Xbyak::Label l9b0;
+Xbyak::Label l9c8;
+Xbyak::Label l9d8;
+
+ preamble();
+#ifdef _WIN32
+ auto stacksize = get_size_of_abi_save_regs();
+ mov(ALPHA, ptr[ARG_ALPHA]);
+ mov(B, ptr[ARG_B]);
+#endif
+
+ mov(M, qword[M]);
+ mov(N, qword[N]);
+ mov(LDA, qword[LDA]);
+ lea(LDA3, ptr[LDA+LDA*2]);
+ sub(A, -128);
+ sub(B, -128);
+ cmp(N, 0x30);
+ jl(l234, T_NEAR);
+ align(4);
+
+L(l20);
+ mov(A1, A);
+ add(A, 0x30);
+ mov(I, M);
+ sar(I, 0x2);
+ jle(l170, T_NEAR);
+ align(4);
+
+L(l34);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpcklbw(xmm2, xmm3);
+ punpckhbw(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqa(xmm2, xmm4);
+ punpcklwd(xmm4, xmm5);
+ punpckhwd(xmm2, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ movdqu(xword[B-0x60], xmm4);
+ movdqu(xword[B-0x50], xmm2);
+ movdqu(xmm0, xword[A1-0x70]);
+ movdqu(xmm1, xword[A1+LDA*1-0x70]);
+ movdqu(xmm2, xword[A1+LDA*2-0x70]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x70]);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpcklbw(xmm2, xmm3);
+ punpckhbw(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqa(xmm2, xmm4);
+ punpcklwd(xmm4, xmm5);
+ punpckhwd(xmm2, xmm5);
+ movdqu(xword[B-0x40], xmm0);
+ movdqu(xword[B-0x30], xmm1);
+ movdqu(xword[B-0x20], xmm4);
+ movdqu(xword[B-0x10], xmm2);
+ movdqu(xmm0, xword[A1-0x60]);
+ movdqu(xmm1, xword[A1+LDA*1-0x60]);
+ movdqu(xmm2, xword[A1+LDA*2-0x60]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x60]);
+ lea(A1, ptr[A1+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpcklbw(xmm2, xmm3);
+ punpckhbw(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqa(xmm2, xmm4);
+ punpcklwd(xmm4, xmm5);
+ punpckhwd(xmm2, xmm5);
+ movdqu(xword[B], xmm0);
+ movdqu(xword[B+0x10], xmm1);
+ movdqu(xword[B+0x20], xmm4);
+ movdqu(xword[B+0x30], xmm2);
+ sub(B, -192);
+ dec(I);
+ jg(l34, T_NEAR);
+ align(4);
+
+L(l170);
+ test(M, 0x2);
+ jle(l1f0, T_NEAR);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1-0x70]);
+ movdqu(xmm2, xword[A1-0x60]);
+ add(A1, LDA);
+ movdqu(xmm3, xword[A1-0x80]);
+ movdqu(xmm4, xword[A1-0x70]);
+ movdqu(xmm5, xword[A1-0x60]);
+ add(A1, LDA);
+ movdqa(xmm6, xmm0);
+ punpcklbw(xmm0, xmm3);
+ punpckhbw(xmm6, xmm3);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm6);
+ movdqa(xmm6, xmm1);
+ punpcklbw(xmm1, xmm4);
+ punpckhbw(xmm6, xmm4);
+ movdqu(xword[B-0x60], xmm1);
+ movdqu(xword[B-0x50], xmm6);
+ movdqa(xmm6, xmm2);
+ punpcklbw(xmm2, xmm5);
+ punpckhbw(xmm6, xmm5);
+ movdqu(xword[B-0x40], xmm2);
+ movdqu(xword[B-0x30], xmm6);
+ sub(B, -96);
+ align(4);
+
+L(l1f0);
+ test(M, 0x1);
+ jle(l224, T_NEAR);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1-0x70]);
+ movdqu(xmm2, xword[A1-0x60]);
+ add(A1, LDA);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ movdqu(xword[B-0x60], xmm2);
+ sub(B, -48);
+ align(4);
+
+L(l224);
+ sub(N, 0x30);
+ cmp(N, 0x30);
+ jge(l20, T_NEAR);
+ align(4);
+
+L(l234);
+ cmp(N, 0x20);
+ jl(l3c0, T_NEAR);
+ align(4);
+
+L(l240);
+ mov(A1, A);
+ add(A, 0x20);
+ mov(I, M);
+ sar(I, 0x2);
+ jle(l32c, T_NEAR);
+ align(4);
+
+L(l254);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpcklbw(xmm2, xmm3);
+ punpckhbw(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqa(xmm2, xmm4);
+ punpcklwd(xmm4, xmm5);
+ punpckhwd(xmm2, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ movdqu(xword[B-0x60], xmm4);
+ movdqu(xword[B-0x50], xmm2);
+ movdqu(xmm0, xword[A1-0x70]);
+ movdqu(xmm1, xword[A1+LDA*1-0x70]);
+ movdqu(xmm2, xword[A1+LDA*2-0x70]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x70]);
+ lea(A1, ptr[A1+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpcklbw(xmm2, xmm3);
+ punpckhbw(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqa(xmm2, xmm4);
+ punpcklwd(xmm4, xmm5);
+ punpckhwd(xmm2, xmm5);
+ movdqu(xword[B-0x40], xmm0);
+ movdqu(xword[B-0x30], xmm1);
+ movdqu(xword[B-0x20], xmm4);
+ movdqu(xword[B-0x10], xmm2);
+ sub(B, -128);
+ dec(I);
+ jg(l254, T_NEAR);
+ align(4);
+
+L(l32c);
+ test(M, 0x2);
+ jle(l388, T_NEAR);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1-0x70]);
+ add(A1, LDA);
+ movdqu(xmm2, xword[A1-0x80]);
+ movdqu(xmm3, xword[A1-0x70]);
+ add(A1, LDA);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm2);
+ punpckhbw(xmm4, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm4);
+ movdqa(xmm4, xmm1);
+ punpcklbw(xmm1, xmm3);
+ punpckhbw(xmm4, xmm3);
+ movdqu(xword[B-0x60], xmm1);
+ movdqu(xword[B-0x50], xmm4);
+ sub(B, -64);
+ align(4);
+
+L(l388);
+ test(M, 0x1);
+ jle(l3b0, T_NEAR);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1-0x70]);
+ add(A1, LDA);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ sub(B, -32);
+ align(4);
+
+L(l3b0);
+ sub(N, 0x20);
+ cmp(N, 0x20);
+ jge(l240, T_NEAR);
+ align(4);
+
+L(l3c0);
+ cmp(N, 0x10);
+ jl(l4b8, T_NEAR);
+ align(4);
+
+L(l3cc);
+ mov(A1, A);
+ add(A, 0x10);
+ mov(I, M);
+ sar(I, 0x2);
+ jle(l454, T_NEAR);
+ align(4);
+
+L(l3dc);
+ movdqu(xmm0, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqu(xmm1, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqu(xmm2, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqu(xmm3, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm4, xmm1);
+ movdqa(xmm1, xmm2);
+ punpcklbw(xmm2, xmm3);
+ punpckhbw(xmm1, xmm3);
+ movdqa(xmm3, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm3, xmm2);
+ movdqa(xmm2, xmm4);
+ punpcklwd(xmm4, xmm1);
+ punpckhwd(xmm2, xmm1);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm3);
+ movdqu(xword[B-0x60], xmm4);
+ movdqu(xword[B-0x50], xmm2);
+ sub(B, -64);
+ dec(I);
+ jg(l3dc, T_NEAR);
+ align(4);
+
+L(l454);
+ test(M, 0x2);
+ jle(l48c, T_NEAR);
+ movdqu(xmm0, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqu(xmm1, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqa(xmm2, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm2, xmm1);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm2);
+ sub(B, -32);
+ align(4);
+
+L(l48c);
+ test(M, 0x1);
+ jle(l4a8, T_NEAR);
+ movdqu(xmm0, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l4a8);
+ sub(N, 0x10);
+ cmp(N, 0x10);
+ jge(l3cc, T_NEAR);
+ align(4);
+
+L(l4b8);
+ cmp(N, 0x8);
+ jl(l61c, T_NEAR);
+ align(4);
+
+L(l4c4);
+ mov(A1, A);
+ add(A, 0x8);
+ mov(I, M);
+ sar(I, 0x3);
+ jle(l570, T_NEAR);
+ align(4);
+
+L(l4d8);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqu(xword[B-0x60], xmm0);
+ movdqu(xword[B-0x50], xmm1);
+ sub(B, -64);
+ dec(I);
+ jg(l4d8, T_NEAR);
+ align(4);
+
+L(l570);
+ test(M, 0x4);
+ jle(l5c4, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ sub(B, -32);
+ align(4);
+
+L(l5c4);
+ test(M, 0x2);
+ jle(l5f0, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l5f0);
+ test(M, 0x1);
+ jle(l60c, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l60c);
+ sub(N, 0x8);
+ cmp(N, 0x8);
+ jge(l4c4, T_NEAR);
+ align(4);
+
+L(l61c);
+ cmp(N, 0x4);
+ jl(l74c, T_NEAR);
+ align(4);
+
+L(l628);
+ mov(A1, A);
+ add(A, 0x4);
+ mov(I, M);
+ sar(I, 0x3);
+ jle(l6b0, T_NEAR);
+ align(4);
+
+L(l638);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ sub(B, -32);
+ dec(I);
+ jg(l638, T_NEAR);
+ align(4);
+
+L(l6b0);
+ test(M, 0x4);
+ jle(l6f4, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l6f4);
+ test(M, 0x2);
+ jle(l720, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l720);
+ test(M, 0x1);
+ jle(l73c, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l73c);
+ sub(N, 0x4);
+ cmp(N, 0x4);
+ jge(l628, T_NEAR);
+ align(4);
+
+L(l74c);
+ cmp(N, 0x2);
+ jl(l8b2, T_NEAR);
+ align(4);
+
+L(l758);
+ mov(A1, A);
+ add(A, 0x2);
+ mov(LDA3, M);
+ sar(LDA3, 0x3);
+ jle(l804, T_NEAR);
+ align(4);
+
+L(l76c);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm4, eax, 0x0);
+ punpcklbw(xmm1, xmm2);
+ punpcklbw(xmm3, xmm4);
+ punpcklwd(xmm1, xmm3);
+ punpcklqdq(xmm0, xmm1);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ dec(LDA3);
+ jg(l76c, T_NEAR);
+ align(4);
+
+L(l804);
+ test(M, 0x4);
+ jle(l858, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l858);
+ test(M, 0x2);
+ jle(l88c, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l88c);
+ test(M, 0x1);
+ jle(l8a4, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ mov(word[B-0x80], ax);
+ sub(B, -2);
+ align(4);
+
+L(l8a4);
+ sub(N, 0x2);
+ cmp(N, 0x2);
+ jge(l758, T_NEAR);
+ align(4);
+
+L(l8b2);
+ cmp(N, 0x1);
+ jl(l9d8, T_NEAR);
+ align(4);
+
+L(l8bc);
+ mov(A1, A);
+ add(A, 0x1);
+ mov(LDA3, M);
+ sar(LDA3, 0x3);
+ jle(l944, T_NEAR);
+ align(4);
+
+L(l8cc);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x7);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ dec(LDA3);
+ jg(l8cc, T_NEAR);
+ align(4);
+
+L(l944);
+ test(M, 0x4);
+ jle(l98c, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x3);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l98c);
+ test(M, 0x2);
+ jle(l9b0, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ mov(byte[B-0x80], al);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ mov(byte[B-0x7f], al);
+ sub(B, -2);
+ align(4);
+
+L(l9b0);
+ test(M, 0x1);
+ jle(l9c8, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ mov(byte[B-0x80], al);
+ sub(B, -1);
+ align(4);
+
+L(l9c8);
+ sub(N, 0x1);
+ cmp(N, 0x1);
+ jge(l8bc, T_NEAR);
+ align(4);
+
+L(l9d8);
+
+ postamble();
+}
+outLocalLabel();
+
+#undef M
+#undef N
+#undef A
+#undef LDA
+#undef ALPHA
+#undef B
+#undef I
+#undef A1
+#undef A2
+#undef LDA3
+#ifdef _WIN32
+#undef ARG_ALPHA
+#undef ARG_B
+#endif
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_at_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_at_kern.cpp
new file mode 100644
index 0000000000..1c11fc6cef
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_at_kern.cpp
@@ -0,0 +1,2209 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_generator.hpp"
+#include "common.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+jit_avx512_core_u8_copy_at_kern::jit_avx512_core_u8_copy_at_kern(): jit_generator(nullptr, GEMM_CODE_SIZE)
+{
+
+#ifndef _WIN32
+#define M rdi
+#define N rsi
+#define A rdx
+#define LDA rcx
+#define ALPHA r8
+#define B r9
+
+#define I rax
+#define A1 r10
+#define A2 r8
+#define LDA3 r11
+
+#else
+
+#define M rcx
+#define N rdx
+#define A r8
+#define LDA r9
+#define ALPHA rax
+#define B rdi
+
+#define I rax
+#define A1 rsi
+#define A2 r10
+#define LDA3 r11
+
+#define ARG_ALPHA 40+stacksize+rsp
+#define ARG_B 48+stacksize+rsp
+
+#endif
+
+inLocalLabel();
+{
+
+Xbyak::Label l1014;
+Xbyak::Label l1390;
+Xbyak::Label l159c;
+Xbyak::Label l173c;
+Xbyak::Label l18e4;
+Xbyak::Label l1a7c;
+Xbyak::Label l1a8c;
+Xbyak::Label l1a98;
+Xbyak::Label l1ab4;
+Xbyak::Label l1c64;
+Xbyak::Label l1d74;
+Xbyak::Label l1e50;
+Xbyak::Label l1f2c;
+Xbyak::Label l1ffc;
+Xbyak::Label l20;
+Xbyak::Label l200c;
+Xbyak::Label l2018;
+Xbyak::Label l2034;
+Xbyak::Label l2110;
+Xbyak::Label l21a0;
+Xbyak::Label l2210;
+Xbyak::Label l2284;
+Xbyak::Label l22f0;
+Xbyak::Label l2300;
+Xbyak::Label l230c;
+Xbyak::Label l2324;
+Xbyak::Label l2398;
+Xbyak::Label l23e8;
+Xbyak::Label l242c;
+Xbyak::Label l2474;
+Xbyak::Label l24b4;
+Xbyak::Label l24c4;
+Xbyak::Label l24d0;
+Xbyak::Label l24e8;
+Xbyak::Label l2520;
+Xbyak::Label l254c;
+Xbyak::Label l2578;
+Xbyak::Label l25a8;
+Xbyak::Label l25c8;
+Xbyak::Label l25d6;
+Xbyak::Label l25e0;
+Xbyak::Label l25f0;
+Xbyak::Label l260c;
+Xbyak::Label l262c;
+Xbyak::Label l264c;
+Xbyak::Label l2668;
+Xbyak::Label l2680;
+Xbyak::Label l2690;
+Xbyak::Label l44;
+Xbyak::Label l58c;
+Xbyak::Label l8b0;
+Xbyak::Label lb14;
+Xbyak::Label ld84;
+Xbyak::Label lfdc;
+Xbyak::Label lfec;
+Xbyak::Label lff8;
+
+ preamble();
+#ifdef _WIN32
+ auto stacksize = get_size_of_abi_save_regs();
+ mov(ALPHA, ptr[ARG_ALPHA]);
+ mov(B, ptr[ARG_B]);
+#endif
+
+ mov(N, qword[N]);
+ mov(M, qword[M]);
+ mov(LDA, qword[LDA]);
+ sub(A, -128);
+ sub(B, -128);
+ lea(LDA3, ptr[LDA+LDA*2]);
+ cmp(N, 0x30);
+ jl(lfec, T_NEAR);
+ align(4);
+
+L(l20);
+ mov(A1, A);
+ mov(I, LDA);
+ shl(I, 0x5);
+ lea(I, ptr[I+LDA*8]);
+ lea(I, ptr[I+LDA*8]);
+ add(A, I);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l58c, T_NEAR);
+ align(4);
+
+L(l44);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B+0x40], xmm1);
+ movdqu(xword[B+0x100], xmm4);
+ movdqu(xword[B+0x1c0], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ movdqu(xword[B+0x50], xmm1);
+ movdqu(xword[B+0x110], xmm4);
+ movdqu(xword[B+0x1d0], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ movdqu(xword[B+0x60], xmm1);
+ movdqu(xword[B+0x120], xmm4);
+ movdqu(xword[B+0x1e0], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x50], xmm0);
+ movdqu(xword[B+0x70], xmm1);
+ movdqu(xword[B+0x130], xmm4);
+ movdqu(xword[B+0x1f0], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x40], xmm0);
+ movdqu(xword[B+0x80], xmm1);
+ movdqu(xword[B+0x140], xmm4);
+ movdqu(xword[B+0x200], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x30], xmm0);
+ movdqu(xword[B+0x90], xmm1);
+ movdqu(xword[B+0x150], xmm4);
+ movdqu(xword[B+0x210], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x20], xmm0);
+ movdqu(xword[B+0xa0], xmm1);
+ movdqu(xword[B+0x160], xmm4);
+ movdqu(xword[B+0x220], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x10], xmm0);
+ movdqu(xword[B+0xb0], xmm1);
+ movdqu(xword[B+0x170], xmm4);
+ movdqu(xword[B+0x230], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B], xmm0);
+ movdqu(xword[B+0xc0], xmm1);
+ movdqu(xword[B+0x180], xmm4);
+ movdqu(xword[B+0x240], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B+0x10], xmm0);
+ movdqu(xword[B+0xd0], xmm1);
+ movdqu(xword[B+0x190], xmm4);
+ movdqu(xword[B+0x250], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B+0x20], xmm0);
+ movdqu(xword[B+0xe0], xmm1);
+ movdqu(xword[B+0x1a0], xmm4);
+ movdqu(xword[B+0x260], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B+0x30], xmm0);
+ movdqu(xword[B+0xf0], xmm1);
+ movdqu(xword[B+0x1b0], xmm4);
+ movdqu(xword[B+0x270], xmm3);
+ sub(A1, -16);
+ sub(B, -768);
+ dec(I);
+ jg(l44, T_NEAR);
+ align(4);
+
+L(l58c);
+ test(M, 0x8);
+ jle(l8b0, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ movq(xmm2, qword[A1+LDA*2-0x80]);
+ movq(xmm3, qword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B+0x40], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ movdqu(xword[B+0x50], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x60], xmm0);
+ movdqu(xword[B+0x60], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x50], xmm0);
+ movdqu(xword[B+0x70], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x40], xmm0);
+ movdqu(xword[B+0x80], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x30], xmm0);
+ movdqu(xword[B+0x90], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x20], xmm0);
+ movdqu(xword[B+0xa0], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x10], xmm0);
+ movdqu(xword[B+0xb0], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B], xmm0);
+ movdqu(xword[B+0xc0], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B+0x10], xmm0);
+ movdqu(xword[B+0xd0], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B+0x20], xmm0);
+ movdqu(xword[B+0xe0], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B+0x30], xmm0);
+ movdqu(xword[B+0xf0], xmm1);
+ sub(A1, -8);
+ sub(B, -384);
+ align(4);
+
+L(l8b0);
+ test(M, 0x4);
+ jle(lb14, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ movd(xmm2, dword[A1+LDA*2-0x80]);
+ movd(xmm3, dword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x60], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x50], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x40], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x30], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x20], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x10], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B+0x10], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B+0x20], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B+0x30], xmm0);
+ sub(A1, -4);
+ sub(B, -192);
+ align(4);
+
+L(lb14);
+ test(M, 0x2);
+ jle(ld84, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A1+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x7);
+ movdqu(xword[B-0x80], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqu(xword[B-0x70], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqu(xword[B-0x60], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqu(xword[B-0x50], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqu(xword[B-0x40], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqu(xword[B-0x30], xmm0);
+ sub(A1, -2);
+ sub(B, -96);
+ align(4);
+
+L(ld84);
+ test(M, 0x1);
+ jle(lfdc, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xf);
+ movdqu(xword[B-0x80], xmm0);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xf);
+ movdqu(xword[B-0x70], xmm0);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xf);
+ movdqu(xword[B-0x60], xmm0);
+ sub(B, -48);
+ align(4);
+
+L(lfdc);
+ sub(N, 0x30);
+ cmp(N, 0x30);
+ jge(l20, T_NEAR);
+ align(4);
+
+L(lfec);
+ cmp(N, 0x20);
+ jl(l1a8c, T_NEAR);
+ align(4);
+
+L(lff8);
+ mov(A1, A);
+ mov(I, LDA);
+ shl(I, 0x5);
+ add(A, I);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l1390, T_NEAR);
+ align(4);
+
+L(l1014);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B], xmm1);
+ movdqu(xword[B+0x80], xmm4);
+ movdqu(xword[B+0x100], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ movdqu(xword[B+0x10], xmm1);
+ movdqu(xword[B+0x90], xmm4);
+ movdqu(xword[B+0x110], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ movdqu(xword[B+0x20], xmm1);
+ movdqu(xword[B+0xa0], xmm4);
+ movdqu(xword[B+0x120], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x50], xmm0);
+ movdqu(xword[B+0x30], xmm1);
+ movdqu(xword[B+0xb0], xmm4);
+ movdqu(xword[B+0x130], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x40], xmm0);
+ movdqu(xword[B+0x40], xmm1);
+ movdqu(xword[B+0xc0], xmm4);
+ movdqu(xword[B+0x140], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x30], xmm0);
+ movdqu(xword[B+0x50], xmm1);
+ movdqu(xword[B+0xd0], xmm4);
+ movdqu(xword[B+0x150], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x20], xmm0);
+ movdqu(xword[B+0x60], xmm1);
+ movdqu(xword[B+0xe0], xmm4);
+ movdqu(xword[B+0x160], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x10], xmm0);
+ movdqu(xword[B+0x70], xmm1);
+ movdqu(xword[B+0xf0], xmm4);
+ movdqu(xword[B+0x170], xmm3);
+ sub(A1, -16);
+ sub(B, -512);
+ dec(I);
+ jg(l1014, T_NEAR);
+ align(4);
+
+L(l1390);
+ test(M, 0x8);
+ jle(l159c, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ movq(xmm2, qword[A1+LDA*2-0x80]);
+ movq(xmm3, qword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ movdqu(xword[B+0x10], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x60], xmm0);
+ movdqu(xword[B+0x20], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x50], xmm0);
+ movdqu(xword[B+0x30], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x40], xmm0);
+ movdqu(xword[B+0x40], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x30], xmm0);
+ movdqu(xword[B+0x50], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x20], xmm0);
+ movdqu(xword[B+0x60], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x10], xmm0);
+ movdqu(xword[B+0x70], xmm1);
+ sub(A1, -8);
+ sub(B, -256);
+ align(4);
+
+L(l159c);
+ test(M, 0x4);
+ jle(l173c, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ movd(xmm2, dword[A1+LDA*2-0x80]);
+ movd(xmm3, dword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x60], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x50], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x40], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x30], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x20], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x10], xmm0);
+ sub(A1, -4);
+ sub(B, -128);
+ align(4);
+
+L(l173c);
+ test(M, 0x2);
+ jle(l18e4, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A1+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x7);
+ movdqu(xword[B-0x80], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqu(xword[B-0x70], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqu(xword[B-0x60], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqu(xword[B-0x50], xmm0);
+ sub(A1, -2);
+ sub(B, -64);
+ align(4);
+
+L(l18e4);
+ test(M, 0x1);
+ jle(l1a7c, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xf);
+ movdqu(xword[B-0x80], xmm0);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xf);
+ movdqu(xword[B-0x70], xmm0);
+ sub(B, -32);
+ align(4);
+
+L(l1a7c);
+ sub(N, 0x20);
+ cmp(N, 0x20);
+ jge(lff8, T_NEAR);
+ align(4);
+
+L(l1a8c);
+ cmp(N, 0x10);
+ jl(l200c, T_NEAR);
+ align(4);
+
+L(l1a98);
+ mov(A1, A);
+ mov(I, LDA);
+ shl(I, 0x4);
+ add(A, I);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l1c64, T_NEAR);
+ align(4);
+
+L(l1ab4);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x40], xmm1);
+ movdqu(xword[B], xmm4);
+ movdqu(xword[B+0x40], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ movdqu(xword[B-0x30], xmm1);
+ movdqu(xword[B+0x10], xmm4);
+ movdqu(xword[B+0x50], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ movdqu(xword[B-0x20], xmm1);
+ movdqu(xword[B+0x20], xmm4);
+ movdqu(xword[B+0x60], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x50], xmm0);
+ movdqu(xword[B-0x10], xmm1);
+ movdqu(xword[B+0x30], xmm4);
+ movdqu(xword[B+0x70], xmm3);
+ sub(A1, -16);
+ sub(B, -256);
+ dec(I);
+ jg(l1ab4, T_NEAR);
+ align(4);
+
+L(l1c64);
+ test(M, 0x8);
+ jle(l1d74, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ movq(xmm2, qword[A1+LDA*2-0x80]);
+ movq(xmm3, qword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x40], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ movdqu(xword[B-0x30], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x60], xmm0);
+ movdqu(xword[B-0x20], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x50], xmm0);
+ movdqu(xword[B-0x10], xmm1);
+ sub(A1, -8);
+ sub(B, -128);
+ align(4);
+
+L(l1d74);
+ test(M, 0x4);
+ jle(l1e50, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ movd(xmm2, dword[A1+LDA*2-0x80]);
+ movd(xmm3, dword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x60], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x50], xmm0);
+ sub(A1, -4);
+ sub(B, -64);
+ align(4);
+
+L(l1e50);
+ test(M, 0x2);
+ jle(l1f2c, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A1+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x7);
+ movdqu(xword[B-0x80], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ movdqu(xword[B-0x70], xmm0);
+ sub(A1, -2);
+ sub(B, -32);
+ align(4);
+
+L(l1f2c);
+ test(M, 0x1);
+ jle(l1ffc, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ pinsrb(xmm0, eax, 0xf);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l1ffc);
+ sub(N, 0x10);
+ cmp(N, 0x10);
+ jge(l1a98, T_NEAR);
+ align(4);
+
+L(l200c);
+ cmp(N, 0x8);
+ jl(l2300, T_NEAR);
+ align(4);
+
+L(l2018);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*4]);
+ lea(I, ptr[A1+LDA*8]);
+ mov(A, I);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l2110, T_NEAR);
+ align(4);
+
+L(l2034);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ sub(A1, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x60], xmm1);
+ movdqu(xword[B-0x40], xmm4);
+ movdqu(xword[B-0x20], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ sub(A2, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ movdqu(xword[B-0x50], xmm1);
+ movdqu(xword[B-0x30], xmm4);
+ movdqu(xword[B-0x10], xmm3);
+ sub(B, -128);
+ dec(I);
+ jg(l2034, T_NEAR);
+ align(4);
+
+L(l2110);
+ test(M, 0x8);
+ jle(l21a0, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ movq(xmm2, qword[A1+LDA*2-0x80]);
+ movq(xmm3, qword[A1+LDA3*1-0x80]);
+ sub(A1, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x60], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ movdqu(xword[B-0x50], xmm1);
+ sub(B, -64);
+ align(4);
+
+L(l21a0);
+ test(M, 0x4);
+ jle(l2210, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ movd(xmm2, dword[A1+LDA*2-0x80]);
+ movd(xmm3, dword[A1+LDA3*1-0x80]);
+ sub(A1, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ sub(B, -32);
+ align(4);
+
+L(l2210);
+ test(M, 0x2);
+ jle(l2284, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A1+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A1+LDA3*1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x7);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l2284);
+ test(M, 0x1);
+ jle(l22f0, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1+LDA3*1-0x80]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ pinsrb(xmm0, eax, 0x7);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l22f0);
+ sub(N, 0x8);
+ cmp(N, 0x8);
+ jge(l2018, T_NEAR);
+ align(4);
+
+L(l2300);
+ cmp(N, 0x4);
+ jl(l24c4, T_NEAR);
+ align(4);
+
+L(l230c);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*2]);
+ lea(I, ptr[A1+LDA*4]);
+ mov(A, I);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l2398, T_NEAR);
+ align(4);
+
+L(l2324);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ sub(A1, -16);
+ movdqu(xmm2, xword[A2-0x80]);
+ movdqu(xmm3, xword[A2+LDA*1-0x80]);
+ sub(A2, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ movdqu(xword[B-0x60], xmm4);
+ movdqu(xword[B-0x50], xmm3);
+ sub(B, -64);
+ dec(I);
+ jg(l2324, T_NEAR);
+ align(4);
+
+L(l2398);
+ test(M, 0x8);
+ jle(l23e8, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ sub(A1, -8);
+ movq(xmm2, qword[A2-0x80]);
+ movq(xmm3, qword[A2+LDA*1-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ sub(B, -32);
+ align(4);
+
+L(l23e8);
+ test(M, 0x4);
+ jle(l242c, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ sub(A1, -4);
+ movd(xmm2, dword[A2-0x80]);
+ movd(xmm3, dword[A2+LDA*1-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l242c);
+ test(M, 0x2);
+ jle(l2474, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA*1-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x3);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l2474);
+ test(M, 0x1);
+ jle(l24b4, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x3);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l24b4);
+ sub(N, 0x4);
+ cmp(N, 0x4);
+ jge(l230c, T_NEAR);
+ align(4);
+
+L(l24c4);
+ cmp(N, 0x2);
+ jl(l25d6, T_NEAR);
+ align(4);
+
+L(l24d0);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*1]);
+ lea(I, ptr[A1+LDA*2]);
+ mov(A, I);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l2520, T_NEAR);
+ align(4);
+
+L(l24e8);
+ movdqu(xmm0, xword[A1-0x80]);
+ sub(A1, -16);
+ movdqu(xmm1, xword[A2-0x80]);
+ sub(A2, -16);
+ movdqa(xmm2, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm2, xmm1);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm2);
+ sub(B, -32);
+ dec(I);
+ jg(l24e8, T_NEAR);
+ align(4);
+
+L(l2520);
+ test(M, 0x8);
+ jle(l254c, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ sub(A1, -8);
+ movq(xmm1, qword[A2-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l254c);
+ test(M, 0x4);
+ jle(l2578, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ sub(A1, -4);
+ movd(xmm1, dword[A2-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l2578);
+ test(M, 0x2);
+ jle(l25a8, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x1);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l25a8);
+ test(M, 0x1);
+ jle(l25c8, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ mov(byte[B-0x80], al);
+ mov(al, byte[A2-0x80]);
+ mov(byte[B-0x7f], al);
+ sub(B, -2);
+ align(4);
+
+L(l25c8);
+ sub(N, 0x2);
+ cmp(N, 0x2);
+ jge(l24d0, T_NEAR);
+ align(4);
+
+L(l25d6);
+ cmp(N, 0x1);
+ jl(l2690, T_NEAR);
+ align(4);
+
+L(l25e0);
+ mov(A1, A);
+ add(A, LDA);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l260c, T_NEAR);
+ align(4);
+
+L(l25f0);
+ movdqu(xmm0, xword[A1-0x80]);
+ sub(A1, -16);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ dec(I);
+ jg(l25f0, T_NEAR);
+ align(4);
+
+L(l260c);
+ test(M, 0x8);
+ jle(l262c, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ sub(A1, -8);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l262c);
+ test(M, 0x4);
+ jle(l264c, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ sub(A1, -4);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l264c);
+ test(M, 0x2);
+ jle(l2668, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ mov(word[B-0x80], ax);
+ sub(A1, -2);
+ sub(B, -2);
+ align(4);
+
+L(l2668);
+ test(M, 0x1);
+ jle(l2680, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ mov(byte[B-0x80], al);
+ sub(B, -1);
+ align(4);
+
+L(l2680);
+ sub(N, 0x1);
+ cmp(N, 0x1);
+ jge(l25e0, T_NEAR);
+ align(4);
+
+L(l2690);
+
+ postamble();
+}
+outLocalLabel();
+
+#undef M
+#undef N
+#undef A
+#undef LDA
+#undef ALPHA
+#undef B
+#undef I
+#undef A1
+#undef A2
+#undef LDA3
+#ifdef _WIN32
+#undef ARG_ALPHA
+#undef ARG_B
+#endif
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bn_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bn_kern.cpp
new file mode 100644
index 0000000000..56c36ee14a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bn_kern.cpp
@@ -0,0 +1,564 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_generator.hpp"
+#include "common.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+jit_avx512_core_u8_copy_bn_kern::jit_avx512_core_u8_copy_bn_kern(): jit_generator(nullptr, GEMM_CODE_SIZE)
+{
+
+#ifndef _WIN32
+#define M rdi
+#define N rsi
+#define A rdx
+#define LDA rcx
+#define ALPHA r8
+#define B r9
+
+#define I rax
+#define A1 r10
+#define A2 r8
+#define LDA3 r11
+
+#else
+
+#define M rcx
+#define N rdx
+#define A r8
+#define LDA r9
+#define ALPHA rax
+#define B rdi
+
+#define I rax
+#define A1 rsi
+#define A2 r10
+#define LDA3 r11
+
+#define ARG_ALPHA 40+stacksize+rsp
+#define ARG_B 48+stacksize+rsp
+
+#endif
+
+inLocalLabel();
+{
+
+Xbyak::Label l118;
+Xbyak::Label l1a8;
+Xbyak::Label l20;
+Xbyak::Label l218;
+Xbyak::Label l28c;
+Xbyak::Label l2f8;
+Xbyak::Label l308;
+Xbyak::Label l314;
+Xbyak::Label l32c;
+Xbyak::Label l3a0;
+Xbyak::Label l3c;
+Xbyak::Label l3f0;
+Xbyak::Label l434;
+Xbyak::Label l47c;
+Xbyak::Label l4bc;
+Xbyak::Label l4cc;
+Xbyak::Label l4d8;
+Xbyak::Label l4f0;
+Xbyak::Label l528;
+Xbyak::Label l554;
+Xbyak::Label l580;
+Xbyak::Label l5b0;
+Xbyak::Label l5d0;
+Xbyak::Label l5de;
+Xbyak::Label l5e8;
+Xbyak::Label l5f8;
+Xbyak::Label l614;
+Xbyak::Label l634;
+Xbyak::Label l654;
+Xbyak::Label l670;
+Xbyak::Label l688;
+Xbyak::Label l698;
+
+ preamble();
+#ifdef _WIN32
+ auto stacksize = get_size_of_abi_save_regs();
+ mov(ALPHA, ptr[ARG_ALPHA]);
+ mov(B, ptr[ARG_B]);
+#endif
+
+ mov(N, qword[N]);
+ mov(M, qword[M]);
+ mov(LDA, qword[LDA]);
+ sub(A, -128);
+ sub(B, -128);
+ lea(LDA3, ptr[LDA+LDA*2]);
+ cmp(N, 0x8);
+ jl(l308, T_NEAR);
+ align(4);
+
+L(l20);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*4]);
+ lea(I, ptr[A1+LDA*8]);
+ mov(A, I);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l118, T_NEAR);
+ align(4);
+
+L(l3c);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ sub(A1, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x60], xmm1);
+ movdqu(xword[B-0x40], xmm4);
+ movdqu(xword[B-0x20], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ sub(A2, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ movdqu(xword[B-0x50], xmm1);
+ movdqu(xword[B-0x30], xmm4);
+ movdqu(xword[B-0x10], xmm3);
+ sub(B, -128);
+ dec(I);
+ jg(l3c, T_NEAR);
+ align(4);
+
+L(l118);
+ test(M, 0x8);
+ jle(l1a8, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ movq(xmm2, qword[A1+LDA*2-0x80]);
+ movq(xmm3, qword[A1+LDA3*1-0x80]);
+ sub(A1, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x60], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ movdqu(xword[B-0x50], xmm1);
+ sub(B, -64);
+ align(4);
+
+L(l1a8);
+ test(M, 0x4);
+ jle(l218, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ movd(xmm2, dword[A1+LDA*2-0x80]);
+ movd(xmm3, dword[A1+LDA3*1-0x80]);
+ sub(A1, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ sub(B, -32);
+ align(4);
+
+L(l218);
+ test(M, 0x2);
+ jle(l28c, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A1+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A1+LDA3*1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x7);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l28c);
+ test(M, 0x1);
+ jle(l2f8, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1+LDA3*1-0x80]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ pinsrb(xmm0, eax, 0x7);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l2f8);
+ sub(N, 0x8);
+ cmp(N, 0x8);
+ jge(l20, T_NEAR);
+ align(4);
+
+L(l308);
+ cmp(N, 0x4);
+ jl(l4cc, T_NEAR);
+ align(4);
+
+L(l314);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*2]);
+ lea(I, ptr[A1+LDA*4]);
+ mov(A, I);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l3a0, T_NEAR);
+ align(4);
+
+L(l32c);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ sub(A1, -16);
+ movdqu(xmm2, xword[A2-0x80]);
+ movdqu(xmm3, xword[A2+LDA*1-0x80]);
+ sub(A2, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ movdqu(xword[B-0x60], xmm4);
+ movdqu(xword[B-0x50], xmm3);
+ sub(B, -64);
+ dec(I);
+ jg(l32c, T_NEAR);
+ align(4);
+
+L(l3a0);
+ test(M, 0x8);
+ jle(l3f0, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ sub(A1, -8);
+ movq(xmm2, qword[A2-0x80]);
+ movq(xmm3, qword[A2+LDA*1-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ sub(B, -32);
+ align(4);
+
+L(l3f0);
+ test(M, 0x4);
+ jle(l434, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ sub(A1, -4);
+ movd(xmm2, dword[A2-0x80]);
+ movd(xmm3, dword[A2+LDA*1-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l434);
+ test(M, 0x2);
+ jle(l47c, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA*1-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x3);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l47c);
+ test(M, 0x1);
+ jle(l4bc, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x3);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l4bc);
+ sub(N, 0x4);
+ cmp(N, 0x4);
+ jge(l314, T_NEAR);
+ align(4);
+
+L(l4cc);
+ cmp(N, 0x2);
+ jl(l5de, T_NEAR);
+ align(4);
+
+L(l4d8);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*1]);
+ lea(I, ptr[A1+LDA*2]);
+ mov(A, I);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l528, T_NEAR);
+ align(4);
+
+L(l4f0);
+ movdqu(xmm0, xword[A1-0x80]);
+ sub(A1, -16);
+ movdqu(xmm1, xword[A2-0x80]);
+ sub(A2, -16);
+ movdqa(xmm2, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm2, xmm1);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm2);
+ sub(B, -32);
+ dec(I);
+ jg(l4f0, T_NEAR);
+ align(4);
+
+L(l528);
+ test(M, 0x8);
+ jle(l554, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ sub(A1, -8);
+ movq(xmm1, qword[A2-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l554);
+ test(M, 0x4);
+ jle(l580, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ sub(A1, -4);
+ movd(xmm1, dword[A2-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l580);
+ test(M, 0x2);
+ jle(l5b0, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x1);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l5b0);
+ test(M, 0x1);
+ jle(l5d0, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ mov(byte[B-0x80], al);
+ mov(al, byte[A2-0x80]);
+ mov(byte[B-0x7f], al);
+ sub(B, -2);
+ align(4);
+
+L(l5d0);
+ sub(N, 0x2);
+ cmp(N, 0x2);
+ jge(l4d8, T_NEAR);
+ align(4);
+
+L(l5de);
+ cmp(N, 0x1);
+ jl(l698, T_NEAR);
+ align(4);
+
+L(l5e8);
+ mov(A1, A);
+ add(A, LDA);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l614, T_NEAR);
+ align(4);
+
+L(l5f8);
+ movdqu(xmm0, xword[A1-0x80]);
+ sub(A1, -16);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ dec(I);
+ jg(l5f8, T_NEAR);
+ align(4);
+
+L(l614);
+ test(M, 0x8);
+ jle(l634, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ sub(A1, -8);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l634);
+ test(M, 0x4);
+ jle(l654, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ sub(A1, -4);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l654);
+ test(M, 0x2);
+ jle(l670, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ mov(word[B-0x80], ax);
+ sub(A1, -2);
+ sub(B, -2);
+ align(4);
+
+L(l670);
+ test(M, 0x1);
+ jle(l688, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ mov(byte[B-0x80], al);
+ sub(B, -1);
+ align(4);
+
+L(l688);
+ sub(N, 0x1);
+ cmp(N, 0x1);
+ jge(l5e8, T_NEAR);
+ align(4);
+
+L(l698);
+
+ postamble();
+}
+outLocalLabel();
+
+#undef M
+#undef N
+#undef A
+#undef LDA
+#undef ALPHA
+#undef B
+#undef I
+#undef A1
+#undef A2
+#undef LDA3
+#ifdef _WIN32
+#undef ARG_ALPHA
+#undef ARG_B
+#endif
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bt_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bt_kern.cpp
new file mode 100644
index 0000000000..53e99d94de
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_bt_kern.cpp
@@ -0,0 +1,501 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_generator.hpp"
+#include "common.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+jit_avx512_core_u8_copy_bt_kern::jit_avx512_core_u8_copy_bt_kern(): jit_generator(nullptr, GEMM_CODE_SIZE)
+{
+
+#ifndef _WIN32
+#define M rdi
+#define N rsi
+#define A rdx
+#define LDA rcx
+#define ALPHA r8
+#define B r9
+
+#define I rax
+#define A1 r10
+#define A2 r8
+#define LDA3 r11
+
+#else
+
+#define M rcx
+#define N rdx
+#define A r8
+#define LDA r9
+#define ALPHA rax
+#define B rdi
+
+#define I rax
+#define A1 rsi
+#define A2 r10
+#define LDA3 r11
+
+#define ARG_ALPHA 40+stacksize+rsp
+#define ARG_B 48+stacksize+rsp
+
+#endif
+
+inLocalLabel();
+{
+
+Xbyak::Label l120;
+Xbyak::Label l14c;
+Xbyak::Label l168;
+Xbyak::Label l178;
+Xbyak::Label l184;
+Xbyak::Label l194;
+Xbyak::Label l20;
+Xbyak::Label l20c;
+Xbyak::Label l250;
+Xbyak::Label l27c;
+Xbyak::Label l298;
+Xbyak::Label l2a8;
+Xbyak::Label l2b4;
+Xbyak::Label l2c8;
+Xbyak::Label l34;
+Xbyak::Label l360;
+Xbyak::Label l3b4;
+Xbyak::Label l3e8;
+Xbyak::Label l400;
+Xbyak::Label l40e;
+Xbyak::Label l418;
+Xbyak::Label l428;
+Xbyak::Label l4a0;
+Xbyak::Label l4e8;
+Xbyak::Label l50c;
+Xbyak::Label l524;
+Xbyak::Label l534;
+Xbyak::Label lcc;
+
+ preamble();
+#ifdef _WIN32
+ auto stacksize = get_size_of_abi_save_regs();
+ mov(ALPHA, ptr[ARG_ALPHA]);
+ mov(B, ptr[ARG_B]);
+#endif
+
+ mov(M, qword[M]);
+ mov(N, qword[N]);
+ mov(LDA, qword[LDA]);
+ lea(LDA3, ptr[LDA+LDA*2]);
+ sub(A, -128);
+ sub(B, -128);
+ cmp(N, 0x8);
+ jl(l178, T_NEAR);
+ align(4);
+
+L(l20);
+ mov(A1, A);
+ add(A, 0x8);
+ mov(I, M);
+ sar(I, 0x3);
+ jle(lcc, T_NEAR);
+ align(4);
+
+L(l34);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqu(xword[B-0x60], xmm0);
+ movdqu(xword[B-0x50], xmm1);
+ sub(B, -64);
+ dec(I);
+ jg(l34, T_NEAR);
+ align(4);
+
+L(lcc);
+ test(M, 0x4);
+ jle(l120, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ sub(B, -32);
+ align(4);
+
+L(l120);
+ test(M, 0x2);
+ jle(l14c, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l14c);
+ test(M, 0x1);
+ jle(l168, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l168);
+ sub(N, 0x8);
+ cmp(N, 0x8);
+ jge(l20, T_NEAR);
+ align(4);
+
+L(l178);
+ cmp(N, 0x4);
+ jl(l2a8, T_NEAR);
+ align(4);
+
+L(l184);
+ mov(A1, A);
+ add(A, 0x4);
+ mov(I, M);
+ sar(I, 0x3);
+ jle(l20c, T_NEAR);
+ align(4);
+
+L(l194);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ movdqu(xword[B-0x70], xmm0);
+ sub(B, -32);
+ dec(I);
+ jg(l194, T_NEAR);
+ align(4);
+
+L(l20c);
+ test(M, 0x4);
+ jle(l250, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l250);
+ test(M, 0x2);
+ jle(l27c, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l27c);
+ test(M, 0x1);
+ jle(l298, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l298);
+ sub(N, 0x4);
+ cmp(N, 0x4);
+ jge(l184, T_NEAR);
+ align(4);
+
+L(l2a8);
+ cmp(N, 0x2);
+ jl(l40e, T_NEAR);
+ align(4);
+
+L(l2b4);
+ mov(A1, A);
+ add(A, 0x2);
+ mov(LDA3, M);
+ sar(LDA3, 0x3);
+ jle(l360, T_NEAR);
+ align(4);
+
+L(l2c8);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm4, eax, 0x0);
+ punpcklbw(xmm1, xmm2);
+ punpcklbw(xmm3, xmm4);
+ punpcklwd(xmm1, xmm3);
+ punpcklqdq(xmm0, xmm1);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ dec(LDA3);
+ jg(l2c8, T_NEAR);
+ align(4);
+
+L(l360);
+ test(M, 0x4);
+ jle(l3b4, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l3b4);
+ test(M, 0x2);
+ jle(l3e8, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l3e8);
+ test(M, 0x1);
+ jle(l400, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ mov(word[B-0x80], ax);
+ sub(B, -2);
+ align(4);
+
+L(l400);
+ sub(N, 0x2);
+ cmp(N, 0x2);
+ jge(l2b4, T_NEAR);
+ align(4);
+
+L(l40e);
+ cmp(N, 0x1);
+ jl(l534, T_NEAR);
+ align(4);
+
+L(l418);
+ mov(A1, A);
+ add(A, 0x1);
+ mov(LDA3, M);
+ sar(LDA3, 0x3);
+ jle(l4a0, T_NEAR);
+ align(4);
+
+L(l428);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x7);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ dec(LDA3);
+ jg(l428, T_NEAR);
+ align(4);
+
+L(l4a0);
+ test(M, 0x4);
+ jle(l4e8, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x3);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l4e8);
+ test(M, 0x2);
+ jle(l50c, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ mov(byte[B-0x80], al);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ mov(byte[B-0x7f], al);
+ sub(B, -2);
+ align(4);
+
+L(l50c);
+ test(M, 0x1);
+ jle(l524, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ mov(byte[B-0x80], al);
+ sub(B, -1);
+ align(4);
+
+L(l524);
+ sub(N, 0x1);
+ cmp(N, 0x1);
+ jge(l418, T_NEAR);
+ align(4);
+
+L(l534);
+
+ postamble();
+}
+outLocalLabel();
+
+#undef M
+#undef N
+#undef A
+#undef LDA
+#undef ALPHA
+#undef B
+#undef I
+#undef A1
+#undef A2
+#undef LDA3
+#ifdef _WIN32
+#undef ARG_ALPHA
+#undef ARG_B
+#endif
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_an_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_an_kern.cpp
new file mode 100644
index 0000000000..49a312fc88
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_an_kern.cpp
@@ -0,0 +1,1283 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_generator.hpp"
+#include "common.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+jit_avx512_core_u8_copy_sum_an_kern::jit_avx512_core_u8_copy_sum_an_kern(): jit_generator(nullptr, GEMM_CODE_SIZE)
+{
+
+#ifndef _WIN32
+#define M rdi
+#define N rsi
+#define A rdx
+#define LDA rcx
+#define ALPHA r8
+#define B r9
+
+#define I rax
+#define A1 r10
+#define A2 r8
+#define LDA3 r11
+
+#define ARG_BIAS 24+stacksize+rsp
+
+#else
+
+#define M rcx
+#define N rdx
+#define A r8
+#define LDA r9
+#define ALPHA rax
+#define B rdi
+
+#define I rax
+#define A1 rsi
+#define A2 r10
+#define LDA3 r11
+
+#define ARG_ALPHA 40+stacksize+rsp
+#define ARG_B 48+stacksize+rsp
+#define ARG_BIAS 72+stacksize+rsp
+
+#endif
+
+inLocalLabel();
+{
+
+Xbyak::Label l1024;
+Xbyak::Label l1090;
+Xbyak::Label l10d4;
+Xbyak::Label l10fc;
+Xbyak::Label l111a;
+Xbyak::Label l1124;
+Xbyak::Label l113c;
+Xbyak::Label l11d4;
+Xbyak::Label l1234;
+Xbyak::Label l1278;
+Xbyak::Label l129c;
+Xbyak::Label l12bc;
+Xbyak::Label l20;
+Xbyak::Label l2a0;
+Xbyak::Label l3c0;
+Xbyak::Label l438;
+Xbyak::Label l480;
+Xbyak::Label l48c;
+Xbyak::Label l4c8;
+Xbyak::Label l5c;
+Xbyak::Label l6a8;
+Xbyak::Label l7b4;
+Xbyak::Label l850;
+Xbyak::Label l89c;
+Xbyak::Label l8a8;
+Xbyak::Label l8d0;
+Xbyak::Label l9d0;
+Xbyak::Label la64;
+Xbyak::Label lab8;
+Xbyak::Label lae8;
+Xbyak::Label laf4;
+Xbyak::Label lb14;
+Xbyak::Label lc30;
+Xbyak::Label lcc8;
+Xbyak::Label ld1c;
+Xbyak::Label ld54;
+Xbyak::Label ld78;
+Xbyak::Label ld84;
+Xbyak::Label ld9c;
+Xbyak::Label le58;
+Xbyak::Label lebc;
+Xbyak::Label lef8;
+Xbyak::Label lf1c;
+Xbyak::Label lf3c;
+Xbyak::Label lf48;
+Xbyak::Label lf60;
+
+ preamble();
+ auto stacksize = get_size_of_abi_save_regs();
+#ifdef _WIN32
+ mov(ALPHA, ptr[ARG_ALPHA]);
+ mov(B, ptr[ARG_B]);
+#endif
+
+ mov(M, qword[M]);
+ mov(N, qword[N]);
+ mov(LDA, qword[LDA]);
+ lea(LDA3, ptr[LDA+LDA*2]);
+ sub(A, -128);
+ sub(B, -128);
+ cmp(N, 0x30);
+ jl(l480, T_NEAR);
+ align(4);
+
+L(l20);
+ mov(A1, A);
+ add(A, 0x30);
+ vxorps(ymm8, ymm8, ymm8);
+ vxorps(ymm9, ymm9, ymm9);
+ vxorps(ymm10, ymm10, ymm10);
+ vxorps(ymm11, ymm11, ymm11);
+ vxorps(ymm12, ymm12, ymm12);
+ vxorps(ymm13, ymm13, ymm13);
+ vxorps(ymm14, ymm14, ymm14);
+ vxorps(ymm15, ymm15, ymm15);
+ mov(I, M);
+ sar(I, 0x2);
+ jle(l2a0, T_NEAR);
+ align(4);
+
+L(l5c);
+ vmovdqu(xmm0, xword[A1-0x80]);
+ vmovdqu(xmm1, xword[A1+LDA*1-0x80]);
+ vmovdqu(xmm2, xword[A1+LDA*2-0x80]);
+ vmovdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ vpunpcklbw(xmm4, xmm0, xmm1);
+ vpunpckhbw(xmm5, xmm0, xmm1);
+ vpunpcklbw(xmm6, xmm2, xmm3);
+ vpunpckhbw(xmm7, xmm2, xmm3);
+ vpunpcklwd(xmm0, xmm4, xmm6);
+ vpunpckhwd(xmm1, xmm4, xmm6);
+ vpunpcklwd(xmm2, xmm5, xmm7);
+ vpunpckhwd(xmm3, xmm5, xmm7);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm1);
+ vmovhlps(xmm7, xmm1, xmm1);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm8, ymm8, ymm5);
+ vmovdqu(xword[B-0x80], xmm0);
+ vmovdqu(xword[B-0x70], xmm1);
+ vpmovsxbw(ymm5, xmm2);
+ vmovhlps(xmm6, xmm2, xmm2);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm3);
+ vmovhlps(xmm7, xmm3, xmm3);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm9, ymm9, ymm5);
+ vmovdqu(xword[B-0x60], xmm2);
+ vmovdqu(xword[B-0x50], xmm3);
+ vmovdqu(xmm0, xword[A1-0x70]);
+ vmovdqu(xmm1, xword[A1+LDA*1-0x70]);
+ vmovdqu(xmm2, xword[A1+LDA*2-0x70]);
+ vmovdqu(xmm3, xword[A1+LDA3*1-0x70]);
+ vpunpcklbw(xmm4, xmm0, xmm1);
+ vpunpckhbw(xmm5, xmm0, xmm1);
+ vpunpcklbw(xmm6, xmm2, xmm3);
+ vpunpckhbw(xmm7, xmm2, xmm3);
+ vpunpcklwd(xmm0, xmm4, xmm6);
+ vpunpckhwd(xmm1, xmm4, xmm6);
+ vpunpcklwd(xmm2, xmm5, xmm7);
+ vpunpckhwd(xmm3, xmm5, xmm7);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm1);
+ vmovhlps(xmm7, xmm1, xmm1);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm10, ymm10, ymm5);
+ vmovdqu(xword[B-0x40], xmm0);
+ vmovdqu(xword[B-0x30], xmm1);
+ vpmovsxbw(ymm5, xmm2);
+ vmovhlps(xmm6, xmm2, xmm2);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm3);
+ vmovhlps(xmm7, xmm3, xmm3);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm11, ymm11, ymm5);
+ vmovdqu(xword[B-0x20], xmm2);
+ vmovdqu(xword[B-0x10], xmm3);
+ vmovdqu(xmm0, xword[A1-0x60]);
+ vmovdqu(xmm1, xword[A1+LDA*1-0x60]);
+ vmovdqu(xmm2, xword[A1+LDA*2-0x60]);
+ vmovdqu(xmm3, xword[A1+LDA3*1-0x60]);
+ lea(A1, ptr[A1+LDA*4]);
+ vpunpcklbw(xmm4, xmm0, xmm1);
+ vpunpckhbw(xmm5, xmm0, xmm1);
+ vpunpcklbw(xmm6, xmm2, xmm3);
+ vpunpckhbw(xmm7, xmm2, xmm3);
+ vpunpcklwd(xmm0, xmm4, xmm6);
+ vpunpckhwd(xmm1, xmm4, xmm6);
+ vpunpcklwd(xmm2, xmm5, xmm7);
+ vpunpckhwd(xmm3, xmm5, xmm7);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm1);
+ vmovhlps(xmm7, xmm1, xmm1);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm12, ymm12, ymm5);
+ vmovdqu(xword[B], xmm0);
+ vmovdqu(xword[B+0x10], xmm1);
+ vpmovsxbw(ymm5, xmm2);
+ vmovhlps(xmm6, xmm2, xmm2);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm3);
+ vmovhlps(xmm7, xmm3, xmm3);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm13, ymm13, ymm5);
+ vmovdqu(xword[B+0x20], xmm2);
+ vmovdqu(xword[B+0x30], xmm3);
+ sub(B, -192);
+ dec(I);
+ jg(l5c, T_NEAR);
+ align(4);
+
+L(l2a0);
+ test(M, 0x2);
+ jle(l3c0, T_NEAR);
+ vmovdqu(xmm0, xword[A1-0x80]);
+ vmovdqu(xmm1, xword[A1-0x70]);
+ vmovdqu(xmm2, xword[A1-0x60]);
+ add(A1, LDA);
+ vmovdqu(xmm6, xword[A1-0x80]);
+ vmovdqu(xmm4, xword[A1-0x70]);
+ vmovdqu(xmm5, xword[A1-0x60]);
+ add(A1, LDA);
+ vpunpcklbw(xmm3, xmm0, xmm6);
+ vpunpckhbw(xmm0, xmm0, xmm6);
+ vpmovsxbw(ymm7, xmm3);
+ vmovhlps(xmm6, xmm3, xmm3);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm7, ymm7, ymm6);
+ vpmovsxwd(ymm7, xmm7);
+ vpaddd(ymm8, ymm8, ymm7);
+ vmovdqu(xword[B-0x80], xmm3);
+ vpmovsxbw(ymm7, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm7, ymm7, ymm6);
+ vpmovsxwd(ymm7, xmm7);
+ vpaddd(ymm9, ymm9, ymm7);
+ vmovdqu(xword[B-0x70], xmm0);
+ vpunpcklbw(xmm3, xmm1, xmm4);
+ vpunpckhbw(xmm0, xmm1, xmm4);
+ vpmovsxbw(ymm7, xmm3);
+ vmovhlps(xmm6, xmm3, xmm3);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm7, ymm7, ymm6);
+ vpmovsxwd(ymm7, xmm7);
+ vpaddd(ymm10, ymm10, ymm7);
+ vmovdqu(xword[B-0x60], xmm3);
+ vpmovsxbw(ymm7, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm7, ymm7, ymm6);
+ vpmovsxwd(ymm7, xmm7);
+ vpaddd(ymm11, ymm11, ymm7);
+ vmovdqu(xword[B-0x50], xmm0);
+ vpunpcklbw(xmm3, xmm2, xmm5);
+ vpunpckhbw(xmm0, xmm2, xmm5);
+ vpmovsxbw(ymm7, xmm3);
+ vmovhlps(xmm6, xmm3, xmm3);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm7, ymm7, ymm6);
+ vpmovsxwd(ymm7, xmm7);
+ vpaddd(ymm12, ymm12, ymm7);
+ vmovdqu(xword[B-0x40], xmm3);
+ vpmovsxbw(ymm7, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm7, ymm7, ymm6);
+ vpmovsxwd(ymm7, xmm7);
+ vpaddd(ymm13, ymm13, ymm7);
+ vmovdqu(xword[B-0x30], xmm0);
+ sub(B, -96);
+ align(4);
+
+L(l3c0);
+ test(M, 0x1);
+ jle(l438, T_NEAR);
+ vmovdqu(xmm0, xword[A1-0x80]);
+ vmovdqu(xmm1, xword[A1-0x70]);
+ vmovdqu(xmm2, xword[A1-0x60]);
+ add(A1, LDA);
+ vpmovsxbd(ymm7, xmm0);
+ vpaddd(ymm8, ymm8, ymm7);
+ vmovhlps(xmm7, xmm0, xmm0);
+ vpmovsxbd(ymm7, xmm7);
+ vpaddd(ymm9, ymm9, ymm7);
+ vmovdqu(xword[B-0x80], xmm0);
+ vpmovsxbd(ymm7, xmm1);
+ vpaddd(ymm10, ymm10, ymm7);
+ vmovhlps(xmm7, xmm1, xmm1);
+ vpmovsxbd(ymm7, xmm7);
+ vpaddd(ymm11, ymm11, ymm7);
+ vmovdqu(xword[B-0x70], xmm1);
+ vpmovsxbd(ymm7, xmm2);
+ vpaddd(ymm12, ymm12, ymm7);
+ vmovhlps(xmm7, xmm2, xmm2);
+ vpmovsxbd(ymm7, xmm7);
+ vpaddd(ymm13, ymm13, ymm7);
+ vmovdqu(xword[B-0x60], xmm2);
+ sub(B, -48);
+ align(4);
+
+L(l438);
+ mov(A1, qword[ARG_BIAS]);
+ vmovdqu(yword[A1], ymm8);
+ vmovdqu(yword[A1+0x20], ymm9);
+ vmovdqu(yword[A1+0x40], ymm10);
+ vmovdqu(yword[A1+0x60], ymm11);
+ vmovdqu(yword[A1+0x80], ymm12);
+ vmovdqu(yword[A1+0xa0], ymm13);
+ add(qword[ARG_BIAS], 0xc0);
+ sub(N, 0x30);
+ cmp(N, 0x30);
+ jge(l20, T_NEAR);
+ vzeroupper();
+ align(4);
+
+L(l480);
+ cmp(N, 0x20);
+ jl(l89c, T_NEAR);
+ align(4);
+
+L(l48c);
+ mov(A1, A);
+ add(A, 0x20);
+ pxor(xmm8, xmm8);
+ pxor(xmm9, xmm9);
+ pxor(xmm10, xmm10);
+ pxor(xmm11, xmm11);
+ pxor(xmm12, xmm12);
+ pxor(xmm13, xmm13);
+ pxor(xmm14, xmm14);
+ pxor(xmm15, xmm15);
+ mov(I, M);
+ sar(I, 0x2);
+ jle(l6a8, T_NEAR);
+ align(4);
+
+L(l4c8);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpcklbw(xmm2, xmm3);
+ punpckhbw(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqa(xmm2, xmm4);
+ punpcklwd(xmm4, xmm5);
+ punpckhwd(xmm2, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B-0x60], xmm4);
+ pmovsxbw(xmm5, xmm2);
+ movhlps(xmm6, xmm2);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B-0x50], xmm2);
+ movdqu(xmm0, xword[A1-0x70]);
+ movdqu(xmm1, xword[A1+LDA*1-0x70]);
+ movdqu(xmm2, xword[A1+LDA*2-0x70]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x70]);
+ lea(A1, ptr[A1+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpcklbw(xmm2, xmm3);
+ punpckhbw(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ movdqa(xmm2, xmm4);
+ punpcklwd(xmm4, xmm5);
+ punpckhwd(xmm2, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm12, xmm5);
+ movdqu(xword[B-0x40], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm13, xmm5);
+ movdqu(xword[B-0x30], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ movdqu(xword[B-0x20], xmm4);
+ pmovsxbw(xmm5, xmm2);
+ movhlps(xmm6, xmm2);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm15, xmm5);
+ movdqu(xword[B-0x10], xmm2);
+ sub(B, -128);
+ dec(I);
+ jg(l4c8, T_NEAR);
+ align(4);
+
+L(l6a8);
+ test(M, 0x2);
+ jle(l7b4, T_NEAR);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1-0x70]);
+ add(A1, LDA);
+ movdqu(xmm2, xword[A1-0x80]);
+ movdqu(xmm3, xword[A1-0x70]);
+ add(A1, LDA);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm2);
+ punpckhbw(xmm4, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm4);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm11, xmm6);
+ movdqu(xword[B-0x70], xmm4);
+ movdqa(xmm4, xmm1);
+ punpcklbw(xmm1, xmm3);
+ punpckhbw(xmm4, xmm3);
+ pmovsxbw(xmm5, xmm1);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm12, xmm5);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm13, xmm6);
+ movdqu(xword[B-0x60], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm15, xmm6);
+ movdqu(xword[B-0x50], xmm4);
+ sub(B, -64);
+ align(4);
+
+L(l7b4);
+ test(M, 0x1);
+ jle(l850, T_NEAR);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1-0x70]);
+ add(A1, LDA);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm8, xmm5);
+ pshufd(xmm6, xmm0, 0x55);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ pshufd(xmm5, xmm0, 0xaa);
+ pmovsxbd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ pshufd(xmm6, xmm0, 0xff);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm11, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbd(xmm5, xmm1);
+ paddd(xmm12, xmm5);
+ pshufd(xmm6, xmm1, 0x55);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm13, xmm6);
+ pshufd(xmm5, xmm1, 0xaa);
+ pmovsxbd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ pshufd(xmm6, xmm1, 0xff);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm15, xmm6);
+ movdqu(xword[B-0x70], xmm1);
+ sub(B, -32);
+ align(4);
+
+L(l850);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm8);
+ movdqu(xword[A1+0x10], xmm9);
+ movdqu(xword[A1+0x20], xmm10);
+ movdqu(xword[A1+0x30], xmm11);
+ movdqu(xword[A1+0x40], xmm12);
+ movdqu(xword[A1+0x50], xmm13);
+ movdqu(xword[A1+0x60], xmm14);
+ movdqu(xword[A1+0x70], xmm15);
+ add(qword[ARG_BIAS], 0x80);
+ sub(N, 0x20);
+ cmp(N, 0x20);
+ jge(l48c, T_NEAR);
+ align(4);
+
+L(l89c);
+ cmp(N, 0x10);
+ jl(lae8, T_NEAR);
+ align(4);
+
+L(l8a8);
+ mov(A1, A);
+ add(A, 0x10);
+ pxor(xmm8, xmm8);
+ pxor(xmm9, xmm9);
+ pxor(xmm10, xmm10);
+ pxor(xmm11, xmm11);
+ mov(I, M);
+ sar(I, 0x2);
+ jle(l9d0, T_NEAR);
+ align(4);
+
+L(l8d0);
+ movdqu(xmm0, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqu(xmm1, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqu(xmm2, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqu(xmm3, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqa(xmm4, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm4, xmm1);
+ movdqa(xmm1, xmm2);
+ punpcklbw(xmm2, xmm3);
+ punpckhbw(xmm1, xmm3);
+ movdqa(xmm3, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm3, xmm2);
+ movdqa(xmm2, xmm4);
+ punpcklwd(xmm4, xmm1);
+ punpckhwd(xmm2, xmm1);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm3);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ pmovsxbw(xmm5, xmm2);
+ movhlps(xmm6, xmm2);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B-0x60], xmm4);
+ movdqu(xword[B-0x50], xmm2);
+ sub(B, -64);
+ dec(I);
+ jg(l8d0, T_NEAR);
+ align(4);
+
+L(l9d0);
+ test(M, 0x2);
+ jle(la64, T_NEAR);
+ movdqu(xmm0, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqu(xmm1, xword[A1-0x80]);
+ add(A1, LDA);
+ movdqa(xmm2, xmm0);
+ punpcklbw(xmm0, xmm1);
+ punpckhbw(xmm2, xmm1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ pmovsxbw(xmm5, xmm2);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movhlps(xmm6, xmm2);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm11, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm2);
+ sub(B, -32);
+ align(4);
+
+L(la64);
+ test(M, 0x1);
+ jle(lab8, T_NEAR);
+ movdqu(xmm0, xword[A1-0x80]);
+ add(A1, LDA);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm8, xmm5);
+ pshufd(xmm6, xmm0, 0x55);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ pshufd(xmm5, xmm0, 0xaa);
+ pmovsxbd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ pshufd(xmm6, xmm0, 0xff);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm11, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(lab8);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm8);
+ movdqu(xword[A1+0x10], xmm9);
+ movdqu(xword[A1+0x20], xmm10);
+ movdqu(xword[A1+0x30], xmm11);
+ add(qword[ARG_BIAS], 0x40);
+ sub(N, 0x10);
+ cmp(N, 0x10);
+ jge(l8a8, T_NEAR);
+ align(4);
+
+L(lae8);
+ cmp(N, 0x8);
+ jl(ld78, T_NEAR);
+ align(4);
+
+L(laf4);
+ mov(A1, A);
+ add(A, 0x8);
+ pxor(xmm8, xmm8);
+ pxor(xmm9, xmm9);
+ mov(I, M);
+ sar(I, 0x3);
+ jle(lc30, T_NEAR);
+ align(4);
+
+L(lb14);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ movdqu(xword[B-0x50], xmm1);
+ sub(B, -64);
+ dec(I);
+ jg(lb14, T_NEAR);
+ align(4);
+
+L(lc30);
+ test(M, 0x4);
+ jle(lcc8, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ sub(B, -32);
+ align(4);
+
+L(lcc8);
+ test(M, 0x2);
+ jle(ld1c, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(ld1c);
+ test(M, 0x1);
+ jle(ld54, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ pmovsxbd(xmm5, xmm0);
+ pshufd(xmm6, xmm0, 0x55);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm8, xmm5);
+ paddd(xmm9, xmm6);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(ld54);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm8);
+ movdqu(xword[A1+0x10], xmm9);
+ add(qword[ARG_BIAS], 0x20);
+ sub(N, 0x8);
+ cmp(N, 0x8);
+ jge(laf4, T_NEAR);
+ align(4);
+
+L(ld78);
+ cmp(N, 0x4);
+ jl(lf3c, T_NEAR);
+ align(4);
+
+L(ld84);
+ mov(A1, A);
+ add(A, 0x4);
+ pxor(xmm7, xmm7);
+ mov(I, M);
+ sar(I, 0x3);
+ jle(le58, T_NEAR);
+ align(4);
+
+L(ld9c);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ sub(B, -32);
+ dec(I);
+ jg(ld9c, T_NEAR);
+ align(4);
+
+L(le58);
+ test(M, 0x4);
+ jle(lebc, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(lebc);
+ test(M, 0x2);
+ jle(lef8, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(lef8);
+ test(M, 0x1);
+ jle(lf1c, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(lf1c);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x10);
+ sub(N, 0x4);
+ cmp(N, 0x4);
+ jge(ld84, T_NEAR);
+ align(4);
+
+L(lf3c);
+ cmp(N, 0x2);
+ jl(l111a, T_NEAR);
+ align(4);
+
+L(lf48);
+ mov(A1, A);
+ add(A, 0x2);
+ pxor(xmm7, xmm7);
+ mov(LDA3, M);
+ sar(LDA3, 0x3);
+ jle(l1024, T_NEAR);
+ align(4);
+
+L(lf60);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm4, eax, 0x0);
+ punpcklbw(xmm1, xmm2);
+ punpcklbw(xmm3, xmm4);
+ punpcklwd(xmm1, xmm3);
+ punpcklqdq(xmm0, xmm1);
+ pshufd(xmm6, xmm0, 0xd8);
+ pmovsxbw(xmm5, xmm6);
+ movhlps(xmm6, xmm6);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ dec(LDA3);
+ jg(lf60, T_NEAR);
+ align(4);
+
+L(l1024);
+ test(M, 0x4);
+ jle(l1090, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l1090);
+ test(M, 0x2);
+ jle(l10d4, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l10d4);
+ test(M, 0x1);
+ jle(l10fc, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ mov(word[B-0x80], ax);
+ sub(B, -2);
+ align(4);
+
+L(l10fc);
+ mov(A1, qword[ARG_BIAS]);
+ movq(qword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x8);
+ sub(N, 0x2);
+ cmp(N, 0x2);
+ jge(lf48, T_NEAR);
+ align(4);
+
+L(l111a);
+ cmp(N, 0x1);
+ jl(l12bc, T_NEAR);
+ align(4);
+
+L(l1124);
+ mov(A1, A);
+ add(A, 0x1);
+ pxor(xmm7, xmm7);
+ mov(LDA3, M);
+ sar(LDA3, 0x3);
+ jle(l11d4, T_NEAR);
+ align(4);
+
+L(l113c);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x7);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ dec(LDA3);
+ jg(l113c, T_NEAR);
+ align(4);
+
+L(l11d4);
+ test(M, 0x4);
+ jle(l1234, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x3);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l1234);
+ test(M, 0x2);
+ jle(l1278, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x0);
+ mov(byte[B-0x80], al);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ mov(byte[B-0x7f], al);
+ sub(B, -2);
+ align(4);
+
+L(l1278);
+ test(M, 0x1);
+ jle(l129c, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ mov(byte[B-0x80], al);
+ sub(B, -1);
+ align(4);
+
+L(l129c);
+ mov(A1, qword[ARG_BIAS]);
+ movd(dword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x4);
+ sub(N, 0x1);
+ cmp(N, 0x1);
+ jge(l1124, T_NEAR);
+ align(4);
+
+L(l12bc);
+
+ postamble();
+}
+outLocalLabel();
+
+#undef M
+#undef N
+#undef A
+#undef LDA
+#undef ALPHA
+#undef B
+#undef I
+#undef A1
+#undef A2
+#undef LDA3
+#ifdef _WIN32
+#undef ARG_ALPHA
+#undef ARG_B
+#endif
+#undef ARG_BIAS
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_at_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_at_kern.cpp
new file mode 100644
index 0000000000..a4f4ff09c6
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_at_kern.cpp
@@ -0,0 +1,3163 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_generator.hpp"
+#include "common.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+jit_avx512_core_u8_copy_sum_at_kern::jit_avx512_core_u8_copy_sum_at_kern(): jit_generator(nullptr, GEMM_CODE_SIZE)
+{
+
+#ifndef _WIN32
+#define M rdi
+#define N rsi
+#define A rdx
+#define LDA rcx
+#define ALPHA r8
+#define B r9
+
+#define I rax
+#define A1 r10
+#define A2 r8
+#define LDA3 r11
+
+#define ARG_BIAS 24+stacksize+rsp
+
+#else
+
+#define M rcx
+#define N rdx
+#define A r8
+#define LDA r9
+#define ALPHA rax
+#define B rdi
+
+#define I rax
+#define A1 rsi
+#define A2 r10
+#define LDA3 r11
+
+#define ARG_ALPHA 40+stacksize+rsp
+#define ARG_B 48+stacksize+rsp
+#define ARG_BIAS 72+stacksize+rsp
+
+#endif
+
+inLocalLabel();
+{
+
+Xbyak::Label l1750;
+Xbyak::Label l1b6c;
+Xbyak::Label l1e14;
+Xbyak::Label l20;
+Xbyak::Label l2068;
+Xbyak::Label l226c;
+Xbyak::Label l22b8;
+Xbyak::Label l22c4;
+Xbyak::Label l22f4;
+Xbyak::Label l26b4;
+Xbyak::Label l28cc;
+Xbyak::Label l2a2c;
+Xbyak::Label l2b5c;
+Xbyak::Label l2c64;
+Xbyak::Label l2c94;
+Xbyak::Label l2ca0;
+Xbyak::Label l2cc8;
+Xbyak::Label l2eac;
+Xbyak::Label l2fc0;
+Xbyak::Label l3078;
+Xbyak::Label l3118;
+Xbyak::Label l319c;
+Xbyak::Label l31c0;
+Xbyak::Label l31cc;
+Xbyak::Label l31ec;
+Xbyak::Label l32e4;
+Xbyak::Label l3378;
+Xbyak::Label l33dc;
+Xbyak::Label l3434;
+Xbyak::Label l347c;
+Xbyak::Label l349c;
+Xbyak::Label l34a8;
+Xbyak::Label l34c8;
+Xbyak::Label l3558;
+Xbyak::Label l35b0;
+Xbyak::Label l35f4;
+Xbyak::Label l3638;
+Xbyak::Label l366c;
+Xbyak::Label l368a;
+Xbyak::Label l3694;
+Xbyak::Label l36a8;
+Xbyak::Label l36ec;
+Xbyak::Label l3728;
+Xbyak::Label l3760;
+Xbyak::Label l3794;
+Xbyak::Label l37b8;
+Xbyak::Label l37d8;
+Xbyak::Label l5cc;
+Xbyak::Label l6c;
+Xbyak::Label l968;
+Xbyak::Label lc80;
+Xbyak::Label lf1c;
+Xbyak::Label lf64;
+Xbyak::Label lf70;
+Xbyak::Label lfb4;
+
+ preamble();
+ auto stacksize = get_size_of_abi_save_regs();
+#ifdef _WIN32
+ mov(ALPHA, ptr[ARG_ALPHA]);
+ mov(B, ptr[ARG_B]);
+#endif
+
+ mov(N, qword[N]);
+ mov(M, qword[M]);
+ mov(LDA, qword[LDA]);
+ sub(A, -128);
+ sub(B, -128);
+ lea(LDA3, ptr[LDA+LDA*2]);
+ cmp(N, 0x30);
+ jl(lf64, T_NEAR);
+ align(4);
+
+L(l20);
+ mov(A1, A);
+ mov(I, LDA);
+ shl(I, 0x5);
+ lea(I, ptr[I+LDA*8]);
+ lea(I, ptr[I+LDA*8]);
+ add(A, I);
+ vxorps(ymm8, ymm8, ymm8);
+ vxorps(ymm9, ymm9, ymm9);
+ vxorps(ymm10, ymm10, ymm10);
+ vxorps(ymm11, ymm11, ymm11);
+ vxorps(ymm12, ymm12, ymm12);
+ vxorps(ymm13, ymm13, ymm13);
+ vxorps(ymm14, ymm14, ymm14);
+ vxorps(ymm15, ymm15, ymm15);
+ mov(I, M);
+ sar(I, 0x3);
+ jle(l5cc, T_NEAR);
+ align(4);
+
+L(l6c);
+ vmovq(xmm0, qword[A1-0x80]);
+ vmovq(xmm1, qword[A1+LDA*1-0x80]);
+ vmovq(xmm2, qword[A1+LDA*2-0x80]);
+ vmovq(xmm3, qword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ vpunpckldq(xmm1, xmm0, xmm1);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm1, xmm3);
+ vpunpckhqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B-0x80], xmm0);
+ vmovdqu(xword[B+0x40], xmm1);
+ vmovq(xmm2, qword[A2-0x80]);
+ vmovq(xmm3, qword[A2+LDA*1-0x80]);
+ vmovq(xmm4, qword[A2+LDA*2-0x80]);
+ vmovq(xmm5, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpckldq(xmm5, xmm4, xmm5);
+ vpunpcklqdq(xmm2, xmm3, xmm5);
+ vpunpckhqdq(xmm3, xmm3, xmm5);
+ vmovdqu(xword[B-0x70], xmm2);
+ vmovdqu(xword[B+0x50], xmm3);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm2);
+ vmovhlps(xmm7, xmm2, xmm2);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm8, ymm8, ymm5);
+ vpmovsxbw(ymm5, xmm1);
+ vmovhlps(xmm6, xmm1, xmm1);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm3);
+ vmovhlps(xmm7, xmm3, xmm3);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm8, ymm8, ymm5);
+ vmovq(xmm0, qword[A2-0x80]);
+ vmovq(xmm1, qword[A2+LDA*1-0x80]);
+ vmovq(xmm2, qword[A2+LDA*2-0x80]);
+ vmovq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm0, xmm1);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm1, xmm3);
+ vpunpckhqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B-0x60], xmm0);
+ vmovdqu(xword[B+0x60], xmm1);
+ vmovq(xmm2, qword[A2-0x80]);
+ vmovq(xmm3, qword[A2+LDA*1-0x80]);
+ vmovq(xmm4, qword[A2+LDA*2-0x80]);
+ vmovq(xmm5, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpckldq(xmm5, xmm4, xmm5);
+ vpunpcklqdq(xmm2, xmm3, xmm5);
+ vpunpckhqdq(xmm3, xmm3, xmm5);
+ vmovdqu(xword[B-0x50], xmm2);
+ vmovdqu(xword[B+0x70], xmm3);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm2);
+ vmovhlps(xmm7, xmm2, xmm2);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm9, ymm9, ymm5);
+ vpmovsxbw(ymm5, xmm1);
+ vmovhlps(xmm6, xmm1, xmm1);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm3);
+ vmovhlps(xmm7, xmm3, xmm3);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm9, ymm9, ymm5);
+ vmovq(xmm0, qword[A2-0x80]);
+ vmovq(xmm1, qword[A2+LDA*1-0x80]);
+ vmovq(xmm2, qword[A2+LDA*2-0x80]);
+ vmovq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm0, xmm1);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm1, xmm3);
+ vpunpckhqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B-0x40], xmm0);
+ vmovdqu(xword[B+0x80], xmm1);
+ vmovq(xmm2, qword[A2-0x80]);
+ vmovq(xmm3, qword[A2+LDA*1-0x80]);
+ vmovq(xmm4, qword[A2+LDA*2-0x80]);
+ vmovq(xmm5, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpckldq(xmm5, xmm4, xmm5);
+ vpunpcklqdq(xmm2, xmm3, xmm5);
+ vpunpckhqdq(xmm3, xmm3, xmm5);
+ vmovdqu(xword[B-0x30], xmm2);
+ vmovdqu(xword[B+0x90], xmm3);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm2);
+ vmovhlps(xmm7, xmm2, xmm2);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm10, ymm10, ymm5);
+ vpmovsxbw(ymm5, xmm1);
+ vmovhlps(xmm6, xmm1, xmm1);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm3);
+ vmovhlps(xmm7, xmm3, xmm3);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm10, ymm10, ymm5);
+ vmovq(xmm0, qword[A2-0x80]);
+ vmovq(xmm1, qword[A2+LDA*1-0x80]);
+ vmovq(xmm2, qword[A2+LDA*2-0x80]);
+ vmovq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm0, xmm1);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm1, xmm3);
+ vpunpckhqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B-0x20], xmm0);
+ vmovdqu(xword[B+0xa0], xmm1);
+ vmovq(xmm2, qword[A2-0x80]);
+ vmovq(xmm3, qword[A2+LDA*1-0x80]);
+ vmovq(xmm4, qword[A2+LDA*2-0x80]);
+ vmovq(xmm5, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpckldq(xmm5, xmm4, xmm5);
+ vpunpcklqdq(xmm2, xmm3, xmm5);
+ vpunpckhqdq(xmm3, xmm3, xmm5);
+ vmovdqu(xword[B-0x10], xmm2);
+ vmovdqu(xword[B+0xb0], xmm3);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm2);
+ vmovhlps(xmm7, xmm2, xmm2);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm11, ymm11, ymm5);
+ vpmovsxbw(ymm5, xmm1);
+ vmovhlps(xmm6, xmm1, xmm1);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm3);
+ vmovhlps(xmm7, xmm3, xmm3);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm11, ymm11, ymm5);
+ vmovq(xmm0, qword[A2-0x80]);
+ vmovq(xmm1, qword[A2+LDA*1-0x80]);
+ vmovq(xmm2, qword[A2+LDA*2-0x80]);
+ vmovq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm0, xmm1);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm1, xmm3);
+ vpunpckhqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B], xmm0);
+ vmovdqu(xword[B+0xc0], xmm1);
+ vmovq(xmm2, qword[A2-0x80]);
+ vmovq(xmm3, qword[A2+LDA*1-0x80]);
+ vmovq(xmm4, qword[A2+LDA*2-0x80]);
+ vmovq(xmm5, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpckldq(xmm5, xmm4, xmm5);
+ vpunpcklqdq(xmm2, xmm3, xmm5);
+ vpunpckhqdq(xmm3, xmm3, xmm5);
+ vmovdqu(xword[B+0x10], xmm2);
+ vmovdqu(xword[B+0xd0], xmm3);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm2);
+ vmovhlps(xmm7, xmm2, xmm2);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm12, ymm12, ymm5);
+ vpmovsxbw(ymm5, xmm1);
+ vmovhlps(xmm6, xmm1, xmm1);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm3);
+ vmovhlps(xmm7, xmm3, xmm3);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm12, ymm12, ymm5);
+ vmovq(xmm0, qword[A2-0x80]);
+ vmovq(xmm1, qword[A2+LDA*1-0x80]);
+ vmovq(xmm2, qword[A2+LDA*2-0x80]);
+ vmovq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm0, xmm1);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm1, xmm3);
+ vpunpckhqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B+0x20], xmm0);
+ vmovdqu(xword[B+0xe0], xmm1);
+ vmovq(xmm2, qword[A2-0x80]);
+ vmovq(xmm3, qword[A2+LDA*1-0x80]);
+ vmovq(xmm4, qword[A2+LDA*2-0x80]);
+ vmovq(xmm5, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm3, xmm2, xmm3);
+ vpunpckldq(xmm5, xmm4, xmm5);
+ vpunpcklqdq(xmm2, xmm3, xmm5);
+ vpunpckhqdq(xmm3, xmm3, xmm5);
+ vmovdqu(xword[B+0x30], xmm2);
+ vmovdqu(xword[B+0xf0], xmm3);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm2);
+ vmovhlps(xmm7, xmm2, xmm2);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm13, ymm13, ymm5);
+ vpmovsxbw(ymm5, xmm1);
+ vmovhlps(xmm6, xmm1, xmm1);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm3);
+ vmovhlps(xmm7, xmm3, xmm3);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm13, ymm13, ymm5);
+ sub(A1, -8);
+ sub(B, -384);
+ dec(I);
+ jg(l6c, T_NEAR);
+ align(4);
+
+L(l5cc);
+ test(M, 0x4);
+ jle(l968, T_NEAR);
+ vmovd(xmm0, dword[A1-0x80]);
+ vmovd(xmm1, dword[A1+LDA*1-0x80]);
+ vmovd(xmm2, dword[A1+LDA*2-0x80]);
+ vmovd(xmm3, dword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ vpunpckldq(xmm0, xmm0, xmm1);
+ vpunpckldq(xmm2, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm0, xmm2);
+ vmovdqu(xword[B-0x80], xmm0);
+ vmovd(xmm1, dword[A2-0x80]);
+ vmovd(xmm2, dword[A2+LDA*1-0x80]);
+ vmovd(xmm3, dword[A2+LDA*2-0x80]);
+ vmovd(xmm4, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm1, xmm2);
+ vpunpckldq(xmm3, xmm3, xmm4);
+ vpunpcklqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B-0x70], xmm1);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm1);
+ vmovhlps(xmm7, xmm1, xmm1);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm8, ymm8, ymm5);
+ vmovd(xmm0, dword[A2-0x80]);
+ vmovd(xmm1, dword[A2+LDA*1-0x80]);
+ vmovd(xmm2, dword[A2+LDA*2-0x80]);
+ vmovd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm0, xmm0, xmm1);
+ vpunpckldq(xmm2, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm0, xmm2);
+ vmovdqu(xword[B-0x60], xmm0);
+ vmovd(xmm1, dword[A2-0x80]);
+ vmovd(xmm2, dword[A2+LDA*1-0x80]);
+ vmovd(xmm3, dword[A2+LDA*2-0x80]);
+ vmovd(xmm4, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm1, xmm2);
+ vpunpckldq(xmm3, xmm3, xmm4);
+ vpunpcklqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B-0x50], xmm1);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm1);
+ vmovhlps(xmm7, xmm1, xmm1);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm9, ymm9, ymm5);
+ vmovd(xmm0, dword[A2-0x80]);
+ vmovd(xmm1, dword[A2+LDA*1-0x80]);
+ vmovd(xmm2, dword[A2+LDA*2-0x80]);
+ vmovd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm0, xmm0, xmm1);
+ vpunpckldq(xmm2, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm0, xmm2);
+ vmovdqu(xword[B-0x40], xmm0);
+ vmovd(xmm1, dword[A2-0x80]);
+ vmovd(xmm2, dword[A2+LDA*1-0x80]);
+ vmovd(xmm3, dword[A2+LDA*2-0x80]);
+ vmovd(xmm4, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm1, xmm2);
+ vpunpckldq(xmm3, xmm3, xmm4);
+ vpunpcklqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B-0x30], xmm1);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm1);
+ vmovhlps(xmm7, xmm1, xmm1);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm10, ymm10, ymm5);
+ vmovd(xmm0, dword[A2-0x80]);
+ vmovd(xmm1, dword[A2+LDA*1-0x80]);
+ vmovd(xmm2, dword[A2+LDA*2-0x80]);
+ vmovd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm0, xmm0, xmm1);
+ vpunpckldq(xmm2, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm0, xmm2);
+ vmovdqu(xword[B-0x20], xmm0);
+ vmovd(xmm1, dword[A2-0x80]);
+ vmovd(xmm2, dword[A2+LDA*1-0x80]);
+ vmovd(xmm3, dword[A2+LDA*2-0x80]);
+ vmovd(xmm4, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm1, xmm2);
+ vpunpckldq(xmm3, xmm3, xmm4);
+ vpunpcklqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B-0x10], xmm1);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm1);
+ vmovhlps(xmm7, xmm1, xmm1);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm11, ymm11, ymm5);
+ vmovd(xmm0, dword[A2-0x80]);
+ vmovd(xmm1, dword[A2+LDA*1-0x80]);
+ vmovd(xmm2, dword[A2+LDA*2-0x80]);
+ vmovd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm0, xmm0, xmm1);
+ vpunpckldq(xmm2, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm0, xmm2);
+ vmovdqu(xword[B], xmm0);
+ vmovd(xmm1, dword[A2-0x80]);
+ vmovd(xmm2, dword[A2+LDA*1-0x80]);
+ vmovd(xmm3, dword[A2+LDA*2-0x80]);
+ vmovd(xmm4, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm1, xmm2);
+ vpunpckldq(xmm3, xmm3, xmm4);
+ vpunpcklqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B+0x10], xmm1);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm1);
+ vmovhlps(xmm7, xmm1, xmm1);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm12, ymm12, ymm5);
+ vmovd(xmm0, dword[A2-0x80]);
+ vmovd(xmm1, dword[A2+LDA*1-0x80]);
+ vmovd(xmm2, dword[A2+LDA*2-0x80]);
+ vmovd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm0, xmm0, xmm1);
+ vpunpckldq(xmm2, xmm2, xmm3);
+ vpunpcklqdq(xmm0, xmm0, xmm2);
+ vmovdqu(xword[B+0x20], xmm0);
+ vmovd(xmm1, dword[A2-0x80]);
+ vmovd(xmm2, dword[A2+LDA*1-0x80]);
+ vmovd(xmm3, dword[A2+LDA*2-0x80]);
+ vmovd(xmm4, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpunpckldq(xmm1, xmm1, xmm2);
+ vpunpckldq(xmm3, xmm3, xmm4);
+ vpunpcklqdq(xmm1, xmm1, xmm3);
+ vmovdqu(xword[B+0x30], xmm1);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxbw(ymm6, xmm1);
+ vmovhlps(xmm7, xmm1, xmm1);
+ vpmovsxbw(ymm7, xmm7);
+ vphaddw(ymm6, ymm6, ymm7);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm13, ymm13, ymm5);
+ sub(A1, -4);
+ sub(B, -192);
+ align(4);
+
+L(l968);
+ test(M, 0x2);
+ jle(lc80, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x1);
+ mov(ax, word[A1+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x2);
+ mov(ax, word[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ vpinsrw(xmm0, xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrw(xmm0, xmm0, eax, 0x7);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm8, ymm8, ymm5);
+ vmovdqu(xword[B-0x80], xmm0);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrw(xmm0, xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm9, ymm9, ymm5);
+ vmovdqu(xword[B-0x70], xmm0);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrw(xmm0, xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm10, ymm10, ymm5);
+ vmovdqu(xword[B-0x60], xmm0);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrw(xmm0, xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm11, ymm11, ymm5);
+ vmovdqu(xword[B-0x50], xmm0);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrw(xmm0, xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm12, ymm12, ymm5);
+ vmovdqu(xword[B-0x40], xmm0);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrw(xmm0, xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ vpinsrw(xmm0, xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ vpmovsxbw(ymm5, xmm0);
+ vmovhlps(xmm6, xmm0, xmm0);
+ vpmovsxbw(ymm6, xmm6);
+ vphaddw(ymm5, ymm5, ymm6);
+ vpmovsxwd(ymm5, xmm5);
+ vpaddd(ymm13, ymm13, ymm5);
+ vmovdqu(xword[B-0x30], xmm0);
+ sub(A1, -2);
+ sub(B, -96);
+ align(4);
+
+L(lc80);
+ test(M, 0x1);
+ jle(lf1c, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x1);
+ mov(al, byte[A1+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x2);
+ mov(al, byte[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0xf);
+ vpmovsxbd(ymm7, xmm0);
+ vpaddd(ymm8, ymm8, ymm7);
+ vmovhlps(xmm7, xmm0, xmm0);
+ vpmovsxbd(ymm7, xmm7);
+ vpaddd(ymm9, ymm9, ymm7);
+ vmovdqu(xword[B-0x80], xmm0);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x0);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x1);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x2);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0xf);
+ vpmovsxbd(ymm7, xmm0);
+ vpaddd(ymm10, ymm10, ymm7);
+ vmovhlps(xmm7, xmm0, xmm0);
+ vpmovsxbd(ymm7, xmm7);
+ vpaddd(ymm11, ymm11, ymm7);
+ vmovdqu(xword[B-0x70], xmm0);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x0);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x1);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x2);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ vpinsrb(xmm0, xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ vpinsrb(xmm0, xmm0, eax, 0xf);
+ vpmovsxbd(ymm7, xmm0);
+ vpaddd(ymm12, ymm12, ymm7);
+ vmovhlps(xmm7, xmm0, xmm0);
+ vpmovsxbd(ymm7, xmm7);
+ vpaddd(ymm13, ymm13, ymm7);
+ vmovdqu(xword[B-0x60], xmm0);
+ sub(B, -48);
+ align(4);
+
+L(lf1c);
+ mov(A1, qword[ARG_BIAS]);
+ vmovdqu(yword[A1], ymm8);
+ vmovdqu(yword[A1+0x20], ymm9);
+ vmovdqu(yword[A1+0x40], ymm10);
+ vmovdqu(yword[A1+0x60], ymm11);
+ vmovdqu(yword[A1+0x80], ymm12);
+ vmovdqu(yword[A1+0xa0], ymm13);
+ add(qword[ARG_BIAS], 0xc0);
+ sub(N, 0x30);
+ cmp(N, 0x30);
+ jge(l20, T_NEAR);
+ vzeroupper();
+ align(4);
+
+L(lf64);
+ cmp(N, 0x20);
+ jl(l22b8, T_NEAR);
+ align(4);
+
+L(lf70);
+ mov(A1, A);
+ mov(I, LDA);
+ shl(I, 0x5);
+ add(A, I);
+ pxor(xmm8, xmm8);
+ pxor(xmm9, xmm9);
+ pxor(xmm10, xmm10);
+ pxor(xmm11, xmm11);
+ pxor(xmm12, xmm12);
+ pxor(xmm13, xmm13);
+ pxor(xmm14, xmm14);
+ pxor(xmm15, xmm15);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l1750, T_NEAR);
+ align(4);
+
+L(lfb4);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B+0x80], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B+0x100], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B+0x10], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B+0x90], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B+0x110], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B+0x20], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B+0xa0], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B+0x120], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B-0x50], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B+0x30], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B+0xb0], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B+0x130], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm12, xmm5);
+ movdqu(xword[B-0x40], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm12, xmm5);
+ movdqu(xword[B+0x40], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm12, xmm5);
+ movdqu(xword[B+0xc0], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm12, xmm5);
+ movdqu(xword[B+0x140], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm13, xmm5);
+ movdqu(xword[B-0x30], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm13, xmm5);
+ movdqu(xword[B+0x50], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm13, xmm5);
+ movdqu(xword[B+0xd0], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm13, xmm5);
+ movdqu(xword[B+0x150], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ movdqu(xword[B-0x20], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ movdqu(xword[B+0x60], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ movdqu(xword[B+0xe0], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ movdqu(xword[B+0x160], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm15, xmm5);
+ movdqu(xword[B-0x10], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm15, xmm5);
+ movdqu(xword[B+0x70], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm15, xmm5);
+ movdqu(xword[B+0xf0], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm15, xmm5);
+ movdqu(xword[B+0x170], xmm3);
+ sub(A1, -16);
+ sub(B, -512);
+ dec(I);
+ jg(lfb4, T_NEAR);
+ align(4);
+
+L(l1750);
+ test(M, 0x8);
+ jle(l1b6c, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ movq(xmm2, qword[A1+LDA*2-0x80]);
+ movq(xmm3, qword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B+0x10], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B+0x20], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B-0x50], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B+0x30], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm12, xmm5);
+ movdqu(xword[B-0x40], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm12, xmm5);
+ movdqu(xword[B+0x40], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm13, xmm5);
+ movdqu(xword[B-0x30], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm13, xmm5);
+ movdqu(xword[B+0x50], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ movdqu(xword[B-0x20], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ movdqu(xword[B+0x60], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm15, xmm5);
+ movdqu(xword[B-0x10], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm15, xmm5);
+ movdqu(xword[B+0x70], xmm1);
+ sub(A1, -8);
+ sub(B, -256);
+ align(4);
+
+L(l1b6c);
+ test(M, 0x4);
+ jle(l1e14, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ movd(xmm2, dword[A1+LDA*2-0x80]);
+ movd(xmm3, dword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B-0x50], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm12, xmm5);
+ movdqu(xword[B-0x40], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm13, xmm5);
+ movdqu(xword[B-0x30], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ movdqu(xword[B-0x20], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm15, xmm5);
+ movdqu(xword[B-0x10], xmm0);
+ sub(A1, -4);
+ sub(B, -128);
+ align(4);
+
+L(l1e14);
+ test(M, 0x2);
+ jle(l2068, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A1+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x7);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm11, xmm6);
+ movdqu(xword[B-0x70], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm12, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm13, xmm6);
+ movdqu(xword[B-0x60], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ lea(A2, ptr[A2+LDA*4]);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm15, xmm6);
+ movdqu(xword[B-0x50], xmm0);
+ sub(A1, -2);
+ sub(B, -64);
+ align(4);
+
+L(l2068);
+ test(M, 0x1);
+ jle(l226c, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xf);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm8, xmm5);
+ pshufd(xmm6, xmm0, 0x55);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ pshufd(xmm5, xmm0, 0xaa);
+ pmovsxbd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ pshufd(xmm6, xmm0, 0xff);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm11, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xf);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm12, xmm5);
+ pshufd(xmm6, xmm0, 0x55);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm13, xmm6);
+ pshufd(xmm5, xmm0, 0xaa);
+ pmovsxbd(xmm5, xmm5);
+ paddd(xmm14, xmm5);
+ pshufd(xmm6, xmm0, 0xff);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm15, xmm6);
+ movdqu(xword[B-0x70], xmm0);
+ sub(B, -32);
+ align(4);
+
+L(l226c);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm8);
+ movdqu(xword[A1+0x10], xmm9);
+ movdqu(xword[A1+0x20], xmm10);
+ movdqu(xword[A1+0x30], xmm11);
+ movdqu(xword[A1+0x40], xmm12);
+ movdqu(xword[A1+0x50], xmm13);
+ movdqu(xword[A1+0x60], xmm14);
+ movdqu(xword[A1+0x70], xmm15);
+ add(qword[ARG_BIAS], 0x80);
+ sub(N, 0x20);
+ cmp(N, 0x20);
+ jge(lf70, T_NEAR);
+ align(4);
+
+L(l22b8);
+ cmp(N, 0x10);
+ jl(l2c94, T_NEAR);
+ align(4);
+
+L(l22c4);
+ mov(A1, A);
+ mov(I, LDA);
+ shl(I, 0x4);
+ add(A, I);
+ pxor(xmm8, xmm8);
+ pxor(xmm9, xmm9);
+ pxor(xmm10, xmm10);
+ pxor(xmm11, xmm11);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l26b4, T_NEAR);
+ align(4);
+
+L(l22f4);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x40], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B+0x40], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x30], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B+0x10], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B+0x50], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B-0x20], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B+0x20], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B+0x60], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B-0x50], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B-0x10], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B+0x30], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B+0x70], xmm3);
+ sub(A1, -16);
+ sub(B, -256);
+ dec(I);
+ jg(l22f4, T_NEAR);
+ align(4);
+
+L(l26b4);
+ test(M, 0x8);
+ jle(l28cc, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ movq(xmm2, qword[A1+LDA*2-0x80]);
+ movq(xmm3, qword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x40], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x30], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B-0x20], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B-0x50], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B-0x10], xmm1);
+ sub(A1, -8);
+ sub(B, -128);
+ align(4);
+
+L(l28cc);
+ test(M, 0x4);
+ jle(l2a2c, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ movd(xmm2, dword[A1+LDA*2-0x80]);
+ movd(xmm3, dword[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm11, xmm5);
+ movdqu(xword[B-0x50], xmm0);
+ sub(A1, -4);
+ sub(B, -64);
+ align(4);
+
+L(l2a2c);
+ test(M, 0x2);
+ jle(l2b5c, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A1+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x7);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ pinsrw(xmm0, eax, 0x7);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm11, xmm6);
+ movdqu(xword[B-0x70], xmm0);
+ sub(A1, -2);
+ sub(B, -32);
+ align(4);
+
+L(l2b5c);
+ test(M, 0x1);
+ jle(l2c64, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1+LDA3*1-0x80]);
+ lea(A2, ptr[A1+LDA*4]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0x7);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x8);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x9);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xa);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ lea(A2, ptr[A2+LDA*4]);
+ pinsrb(xmm0, eax, 0xb);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0xc);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0xd);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0xe);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ pinsrb(xmm0, eax, 0xf);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm8, xmm5);
+ pshufd(xmm6, xmm0, 0x55);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ pshufd(xmm5, xmm0, 0xaa);
+ pmovsxbd(xmm5, xmm5);
+ paddd(xmm10, xmm5);
+ pshufd(xmm6, xmm0, 0xff);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm11, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l2c64);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm8);
+ movdqu(xword[A1+0x10], xmm9);
+ movdqu(xword[A1+0x20], xmm10);
+ movdqu(xword[A1+0x30], xmm11);
+ add(qword[ARG_BIAS], 0x40);
+ sub(N, 0x10);
+ cmp(N, 0x10);
+ jge(l22c4, T_NEAR);
+ align(4);
+
+L(l2c94);
+ cmp(N, 0x8);
+ jl(l31c0, T_NEAR);
+ align(4);
+
+L(l2ca0);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*4]);
+ lea(I, ptr[A1+LDA*8]);
+ mov(A, I);
+ pxor(xmm8, xmm8);
+ pxor(xmm9, xmm9);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l2eac, T_NEAR);
+ align(4);
+
+L(l2cc8);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ sub(A1, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x60], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x40], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x20], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ sub(A2, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x50], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x30], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x10], xmm3);
+ sub(B, -128);
+ dec(I);
+ jg(l2cc8, T_NEAR);
+ align(4);
+
+L(l2eac);
+ test(M, 0x8);
+ jle(l2fc0, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ movq(xmm2, qword[A1+LDA*2-0x80]);
+ movq(xmm3, qword[A1+LDA3*1-0x80]);
+ sub(A1, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x60], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x50], xmm1);
+ sub(B, -64);
+ align(4);
+
+L(l2fc0);
+ test(M, 0x4);
+ jle(l3078, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ movd(xmm2, dword[A1+LDA*2-0x80]);
+ movd(xmm3, dword[A1+LDA3*1-0x80]);
+ sub(A1, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ sub(B, -32);
+ align(4);
+
+L(l3078);
+ test(M, 0x2);
+ jle(l3118, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A1+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A1+LDA3*1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x7);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l3118);
+ test(M, 0x1);
+ jle(l319c, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1+LDA3*1-0x80]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ pinsrb(xmm0, eax, 0x7);
+ pmovsxbd(xmm5, xmm0);
+ pshufd(xmm6, xmm0, 0x55);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm8, xmm5);
+ paddd(xmm9, xmm6);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l319c);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm8);
+ movdqu(xword[A1+0x10], xmm9);
+ add(qword[ARG_BIAS], 0x20);
+ sub(N, 0x8);
+ cmp(N, 0x8);
+ jge(l2ca0, T_NEAR);
+ align(4);
+
+L(l31c0);
+ cmp(N, 0x4);
+ jl(l349c, T_NEAR);
+ align(4);
+
+L(l31cc);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*2]);
+ lea(I, ptr[A1+LDA*4]);
+ mov(A, I);
+ pxor(xmm7, xmm7);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l32e4, T_NEAR);
+ align(4);
+
+L(l31ec);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ sub(A1, -16);
+ movdqu(xmm2, xword[A2-0x80]);
+ movdqu(xmm3, xword[A2+LDA*1-0x80]);
+ sub(A2, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x70], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x60], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x50], xmm3);
+ sub(B, -64);
+ dec(I);
+ jg(l31ec, T_NEAR);
+ align(4);
+
+L(l32e4);
+ test(M, 0x8);
+ jle(l3378, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ sub(A1, -8);
+ movq(xmm2, qword[A2-0x80]);
+ movq(xmm3, qword[A2+LDA*1-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x70], xmm1);
+ sub(B, -32);
+ align(4);
+
+L(l3378);
+ test(M, 0x4);
+ jle(l33dc, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ sub(A1, -4);
+ movd(xmm2, dword[A2-0x80]);
+ movd(xmm3, dword[A2+LDA*1-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l33dc);
+ test(M, 0x2);
+ jle(l3434, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA*1-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x3);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l3434);
+ test(M, 0x1);
+ jle(l347c, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x3);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l347c);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x10);
+ sub(N, 0x4);
+ cmp(N, 0x4);
+ jge(l31cc, T_NEAR);
+ align(4);
+
+L(l349c);
+ cmp(N, 0x2);
+ jl(l368a, T_NEAR);
+ align(4);
+
+L(l34a8);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*1]);
+ lea(I, ptr[A1+LDA*2]);
+ mov(A, I);
+ pxor(xmm7, xmm7);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l3558, T_NEAR);
+ align(4);
+
+L(l34c8);
+ movdqu(xmm0, xword[A1-0x80]);
+ sub(A1, -16);
+ movdqu(xmm1, xword[A2-0x80]);
+ sub(A2, -16);
+ movdqa(xmm2, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm2, xmm1);
+ pshufd(xmm6, xmm0, 0xd8);
+ pmovsxbw(xmm5, xmm6);
+ movhlps(xmm6, xmm6);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pshufd(xmm6, xmm2, 0xd8);
+ pmovsxbw(xmm5, xmm6);
+ movhlps(xmm6, xmm6);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x70], xmm2);
+ sub(B, -32);
+ dec(I);
+ jg(l34c8, T_NEAR);
+ align(4);
+
+L(l3558);
+ test(M, 0x8);
+ jle(l35b0, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ sub(A1, -8);
+ movq(xmm1, qword[A2-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ pshufd(xmm6, xmm0, 0xd8);
+ pmovsxbw(xmm5, xmm6);
+ movhlps(xmm6, xmm6);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l35b0);
+ test(M, 0x4);
+ jle(l35f4, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ sub(A1, -4);
+ movd(xmm1, dword[A2-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l35f4);
+ test(M, 0x2);
+ jle(l3638, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l3638);
+ test(M, 0x1);
+ jle(l366c, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(byte[B-0x80], al);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(byte[B-0x7f], al);
+ sub(B, -2);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ align(4);
+
+L(l366c);
+ mov(A1, qword[ARG_BIAS]);
+ movq(qword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x8);
+ sub(N, 0x2);
+ cmp(N, 0x2);
+ jge(l34a8, T_NEAR);
+ align(4);
+
+L(l368a);
+ cmp(N, 0x1);
+ jl(l37d8, T_NEAR);
+ align(4);
+
+L(l3694);
+ mov(A1, A);
+ add(A, LDA);
+ pxor(xmm7, xmm7);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l36ec, T_NEAR);
+ align(4);
+
+L(l36a8);
+ movdqu(xmm0, xword[A1-0x80]);
+ sub(A1, -16);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ dec(I);
+ jg(l36a8, T_NEAR);
+ align(4);
+
+L(l36ec);
+ test(M, 0x8);
+ jle(l3728, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ sub(A1, -8);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l3728);
+ test(M, 0x4);
+ jle(l3760, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ sub(A1, -4);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l3760);
+ test(M, 0x2);
+ jle(l3794, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ mov(word[B-0x80], ax);
+ sub(A1, -2);
+ sub(B, -2);
+ align(4);
+
+L(l3794);
+ test(M, 0x1);
+ jle(l37b8, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ mov(byte[B-0x80], al);
+ sub(B, -1);
+ align(4);
+
+L(l37b8);
+ mov(A1, qword[ARG_BIAS]);
+ movd(dword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x4);
+ sub(N, 0x1);
+ cmp(N, 0x1);
+ jge(l3694, T_NEAR);
+ align(4);
+
+L(l37d8);
+
+ postamble();
+}
+outLocalLabel();
+
+#undef M
+#undef N
+#undef A
+#undef LDA
+#undef ALPHA
+#undef B
+#undef I
+#undef A1
+#undef A2
+#undef LDA3
+#ifdef _WIN32
+#undef ARG_ALPHA
+#undef ARG_B
+#endif
+#undef ARG_BIAS
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bn_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bn_kern.cpp
new file mode 100644
index 0000000000..c7f1393c9d
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bn_kern.cpp
@@ -0,0 +1,821 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_generator.hpp"
+#include "common.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+jit_avx512_core_u8_copy_sum_bn_kern::jit_avx512_core_u8_copy_sum_bn_kern(): jit_generator(nullptr, GEMM_CODE_SIZE)
+{
+
+#ifndef _WIN32
+#define M rdi
+#define N rsi
+#define A rdx
+#define LDA rcx
+#define ALPHA r8
+#define B r9
+
+#define I rax
+#define A1 r10
+#define A2 r8
+#define LDA3 r11
+
+#define ARG_BIAS 24+stacksize+rsp
+
+#else
+
+#define M rcx
+#define N rdx
+#define A r8
+#define LDA r9
+#define ALPHA rax
+#define B rdi
+
+#define I rax
+#define A1 rsi
+#define A2 r10
+#define LDA3 r11
+
+#define ARG_ALPHA 40+stacksize+rsp
+#define ARG_B 48+stacksize+rsp
+#define ARG_BIAS 72+stacksize+rsp
+
+#endif
+
+inLocalLabel();
+{
+
+Xbyak::Label l20;
+Xbyak::Label l22c;
+Xbyak::Label l340;
+Xbyak::Label l3f8;
+Xbyak::Label l48;
+Xbyak::Label l498;
+Xbyak::Label l51c;
+Xbyak::Label l540;
+Xbyak::Label l54c;
+Xbyak::Label l56c;
+Xbyak::Label l664;
+Xbyak::Label l6f8;
+Xbyak::Label l75c;
+Xbyak::Label l7b4;
+Xbyak::Label l7fc;
+Xbyak::Label l81c;
+Xbyak::Label l828;
+Xbyak::Label l848;
+Xbyak::Label l8d8;
+Xbyak::Label l930;
+Xbyak::Label l974;
+Xbyak::Label l9b8;
+Xbyak::Label l9ec;
+Xbyak::Label la0a;
+Xbyak::Label la14;
+Xbyak::Label la28;
+Xbyak::Label la6c;
+Xbyak::Label laa8;
+Xbyak::Label lae0;
+Xbyak::Label lb14;
+Xbyak::Label lb38;
+Xbyak::Label lb58;
+
+ preamble();
+ auto stacksize = get_size_of_abi_save_regs();
+#ifdef _WIN32
+ mov(ALPHA, ptr[ARG_ALPHA]);
+ mov(B, ptr[ARG_B]);
+#endif
+
+ mov(N, qword[N]);
+ mov(M, qword[M]);
+ mov(LDA, qword[LDA]);
+ sub(A, -128);
+ sub(B, -128);
+ lea(LDA3, ptr[LDA+LDA*2]);
+ cmp(N, 0x8);
+ jl(l540, T_NEAR);
+ align(4);
+
+L(l20);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*4]);
+ lea(I, ptr[A1+LDA*8]);
+ mov(A, I);
+ pxor(xmm8, xmm8);
+ pxor(xmm9, xmm9);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l22c, T_NEAR);
+ align(4);
+
+L(l48);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ movdqu(xmm2, xword[A1+LDA*2-0x80]);
+ movdqu(xmm3, xword[A1+LDA3*1-0x80]);
+ sub(A1, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x60], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x40], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x20], xmm3);
+ movdqu(xmm0, xword[A2-0x80]);
+ movdqu(xmm1, xword[A2+LDA*1-0x80]);
+ movdqu(xmm2, xword[A2+LDA*2-0x80]);
+ movdqu(xmm3, xword[A2+LDA3*1-0x80]);
+ sub(A2, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x50], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x30], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x10], xmm3);
+ sub(B, -128);
+ dec(I);
+ jg(l48, T_NEAR);
+ align(4);
+
+L(l22c);
+ test(M, 0x8);
+ jle(l340, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ movq(xmm2, qword[A1+LDA*2-0x80]);
+ movq(xmm3, qword[A1+LDA3*1-0x80]);
+ sub(A1, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x60], xmm1);
+ movq(xmm0, qword[A2-0x80]);
+ movq(xmm1, qword[A2+LDA*1-0x80]);
+ movq(xmm2, qword[A2+LDA*2-0x80]);
+ movq(xmm3, qword[A2+LDA3*1-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x50], xmm1);
+ sub(B, -64);
+ align(4);
+
+L(l340);
+ test(M, 0x4);
+ jle(l3f8, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ movd(xmm2, dword[A1+LDA*2-0x80]);
+ movd(xmm3, dword[A1+LDA3*1-0x80]);
+ sub(A1, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A2-0x80]);
+ movd(xmm1, dword[A2+LDA*1-0x80]);
+ movd(xmm2, dword[A2+LDA*2-0x80]);
+ movd(xmm3, dword[A2+LDA3*1-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ sub(B, -32);
+ align(4);
+
+L(l3f8);
+ test(M, 0x2);
+ jle(l498, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A1+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A1+LDA3*1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x3);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x4);
+ mov(ax, word[A2+LDA*1-0x80]);
+ pinsrw(xmm0, eax, 0x5);
+ mov(ax, word[A2+LDA*2-0x80]);
+ pinsrw(xmm0, eax, 0x6);
+ mov(ax, word[A2+LDA3*1-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x7);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l498);
+ test(M, 0x1);
+ jle(l51c, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1+LDA3*1-0x80]);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A2+LDA*2-0x80]);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A2+LDA3*1-0x80]);
+ pinsrb(xmm0, eax, 0x7);
+ pmovsxbd(xmm5, xmm0);
+ pshufd(xmm6, xmm0, 0x55);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm8, xmm5);
+ paddd(xmm9, xmm6);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l51c);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm8);
+ movdqu(xword[A1+0x10], xmm9);
+ add(qword[ARG_BIAS], 0x20);
+ sub(N, 0x8);
+ cmp(N, 0x8);
+ jge(l20, T_NEAR);
+ align(4);
+
+L(l540);
+ cmp(N, 0x4);
+ jl(l81c, T_NEAR);
+ align(4);
+
+L(l54c);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*2]);
+ lea(I, ptr[A1+LDA*4]);
+ mov(A, I);
+ pxor(xmm7, xmm7);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l664, T_NEAR);
+ align(4);
+
+L(l56c);
+ movdqu(xmm0, xword[A1-0x80]);
+ movdqu(xmm1, xword[A1+LDA*1-0x80]);
+ sub(A1, -16);
+ movdqu(xmm2, xword[A2-0x80]);
+ movdqu(xmm3, xword[A2+LDA*1-0x80]);
+ sub(A2, -16);
+ movdqa(xmm4, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm4, xmm1);
+ movdqa(xmm5, xmm2);
+ punpckldq(xmm2, xmm3);
+ punpckhdq(xmm5, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ movdqa(xmm3, xmm4);
+ punpcklqdq(xmm4, xmm5);
+ punpckhqdq(xmm3, xmm5);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x70], xmm1);
+ pmovsxbw(xmm5, xmm4);
+ movhlps(xmm6, xmm4);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x60], xmm4);
+ pmovsxbw(xmm5, xmm3);
+ movhlps(xmm6, xmm3);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x50], xmm3);
+ sub(B, -64);
+ dec(I);
+ jg(l56c, T_NEAR);
+ align(4);
+
+L(l664);
+ test(M, 0x8);
+ jle(l6f8, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ movq(xmm1, qword[A1+LDA*1-0x80]);
+ sub(A1, -8);
+ movq(xmm2, qword[A2-0x80]);
+ movq(xmm3, qword[A2+LDA*1-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklqdq(xmm0, xmm2);
+ punpckhqdq(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x70], xmm1);
+ sub(B, -32);
+ align(4);
+
+L(l6f8);
+ test(M, 0x4);
+ jle(l75c, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ movd(xmm1, dword[A1+LDA*1-0x80]);
+ sub(A1, -4);
+ movd(xmm2, dword[A2-0x80]);
+ movd(xmm3, dword[A2+LDA*1-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ punpckldq(xmm2, xmm3);
+ punpcklqdq(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l75c);
+ test(M, 0x2);
+ jle(l7b4, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1+LDA*1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x1);
+ mov(ax, word[A2-0x80]);
+ pinsrw(xmm0, eax, 0x2);
+ mov(ax, word[A2+LDA*1-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x3);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l7b4);
+ test(M, 0x1);
+ jle(l7fc, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A2+LDA*1-0x80]);
+ pinsrb(xmm0, eax, 0x3);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l7fc);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x10);
+ sub(N, 0x4);
+ cmp(N, 0x4);
+ jge(l54c, T_NEAR);
+ align(4);
+
+L(l81c);
+ cmp(N, 0x2);
+ jl(la0a, T_NEAR);
+ align(4);
+
+L(l828);
+ mov(A1, A);
+ lea(A2, ptr[A1+LDA*1]);
+ lea(I, ptr[A1+LDA*2]);
+ mov(A, I);
+ pxor(xmm7, xmm7);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(l8d8, T_NEAR);
+ align(4);
+
+L(l848);
+ movdqu(xmm0, xword[A1-0x80]);
+ sub(A1, -16);
+ movdqu(xmm1, xword[A2-0x80]);
+ sub(A2, -16);
+ movdqa(xmm2, xmm0);
+ punpckldq(xmm0, xmm1);
+ punpckhdq(xmm2, xmm1);
+ pshufd(xmm6, xmm0, 0xd8);
+ pmovsxbw(xmm5, xmm6);
+ movhlps(xmm6, xmm6);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ pshufd(xmm6, xmm2, 0xd8);
+ pmovsxbw(xmm5, xmm6);
+ movhlps(xmm6, xmm6);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x70], xmm2);
+ sub(B, -32);
+ dec(I);
+ jg(l848, T_NEAR);
+ align(4);
+
+L(l8d8);
+ test(M, 0x8);
+ jle(l930, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ sub(A1, -8);
+ movq(xmm1, qword[A2-0x80]);
+ sub(A2, -8);
+ punpckldq(xmm0, xmm1);
+ pshufd(xmm6, xmm0, 0xd8);
+ pmovsxbw(xmm5, xmm6);
+ movhlps(xmm6, xmm6);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l930);
+ test(M, 0x4);
+ jle(l974, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ sub(A1, -4);
+ movd(xmm1, dword[A2-0x80]);
+ sub(A2, -4);
+ punpckldq(xmm0, xmm1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l974);
+ test(M, 0x2);
+ jle(l9b8, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ sub(A1, -2);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A2-0x80]);
+ sub(A2, -2);
+ pinsrw(xmm0, eax, 0x1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l9b8);
+ test(M, 0x1);
+ jle(l9ec, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ mov(byte[B-0x80], al);
+ mov(al, byte[A2-0x80]);
+ pinsrb(xmm0, eax, 0x1);
+ mov(byte[B-0x7f], al);
+ sub(B, -2);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ align(4);
+
+L(l9ec);
+ mov(A1, qword[ARG_BIAS]);
+ movq(qword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x8);
+ sub(N, 0x2);
+ cmp(N, 0x2);
+ jge(l828, T_NEAR);
+ align(4);
+
+L(la0a);
+ cmp(N, 0x1);
+ jl(lb58, T_NEAR);
+ align(4);
+
+L(la14);
+ mov(A1, A);
+ add(A, LDA);
+ pxor(xmm7, xmm7);
+ mov(I, M);
+ sar(I, 0x4);
+ jle(la6c, T_NEAR);
+ align(4);
+
+L(la28);
+ movdqu(xmm0, xword[A1-0x80]);
+ sub(A1, -16);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ dec(I);
+ jg(la28, T_NEAR);
+ align(4);
+
+L(la6c);
+ test(M, 0x8);
+ jle(laa8, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ sub(A1, -8);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(laa8);
+ test(M, 0x4);
+ jle(lae0, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ sub(A1, -4);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(lae0);
+ test(M, 0x2);
+ jle(lb14, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ mov(word[B-0x80], ax);
+ sub(A1, -2);
+ sub(B, -2);
+ align(4);
+
+L(lb14);
+ test(M, 0x1);
+ jle(lb38, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrb(xmm0, eax, 0x0);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ mov(byte[B-0x80], al);
+ sub(B, -1);
+ align(4);
+
+L(lb38);
+ mov(A1, qword[ARG_BIAS]);
+ movd(dword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x4);
+ sub(N, 0x1);
+ cmp(N, 0x1);
+ jge(la14, T_NEAR);
+ align(4);
+
+L(lb58);
+
+ postamble();
+}
+outLocalLabel();
+
+#undef M
+#undef N
+#undef A
+#undef LDA
+#undef ALPHA
+#undef B
+#undef I
+#undef A1
+#undef A2
+#undef LDA3
+#ifdef _WIN32
+#undef ARG_ALPHA
+#undef ARG_B
+#endif
+#undef ARG_BIAS
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bt_kern.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bt_kern.cpp
new file mode 100644
index 0000000000..afe4f1713e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/jit_avx512_core_u8_copy_sum_bt_kern.cpp
@@ -0,0 +1,647 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_generator.hpp"
+#include "common.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+jit_avx512_core_u8_copy_sum_bt_kern::jit_avx512_core_u8_copy_sum_bt_kern(): jit_generator(nullptr, GEMM_CODE_SIZE)
+{
+
+#ifndef _WIN32
+#define M rdi
+#define N rsi
+#define A rdx
+#define LDA rcx
+#define ALPHA r8
+#define B r9
+
+#define I rax
+#define A1 r10
+#define A2 r8
+#define LDA3 r11
+
+#define ARG_BIAS 24+stacksize+rsp
+
+#else
+
+#define M rcx
+#define N rdx
+#define A r8
+#define LDA r9
+#define ALPHA rax
+#define B rdi
+
+#define I rax
+#define A1 rsi
+#define A2 r10
+#define LDA3 r11
+
+#define ARG_ALPHA 40+stacksize+rsp
+#define ARG_B 48+stacksize+rsp
+#define ARG_BIAS 72+stacksize+rsp
+
+#endif
+
+inLocalLabel();
+{
+
+Xbyak::Label l15c;
+Xbyak::Label l1f4;
+Xbyak::Label l20;
+Xbyak::Label l248;
+Xbyak::Label l280;
+Xbyak::Label l2a4;
+Xbyak::Label l2b0;
+Xbyak::Label l2c8;
+Xbyak::Label l384;
+Xbyak::Label l3e8;
+Xbyak::Label l40;
+Xbyak::Label l424;
+Xbyak::Label l448;
+Xbyak::Label l468;
+Xbyak::Label l474;
+Xbyak::Label l48c;
+Xbyak::Label l550;
+Xbyak::Label l5bc;
+Xbyak::Label l600;
+Xbyak::Label l628;
+Xbyak::Label l646;
+Xbyak::Label l650;
+Xbyak::Label l668;
+Xbyak::Label l700;
+Xbyak::Label l760;
+Xbyak::Label l7a4;
+Xbyak::Label l7c8;
+Xbyak::Label l7e8;
+
+ preamble();
+ auto stacksize = get_size_of_abi_save_regs();
+#ifdef _WIN32
+ mov(ALPHA, ptr[ARG_ALPHA]);
+ mov(B, ptr[ARG_B]);
+#endif
+
+ mov(M, qword[M]);
+ mov(N, qword[N]);
+ mov(LDA, qword[LDA]);
+ lea(LDA3, ptr[LDA+LDA*2]);
+ sub(A, -128);
+ sub(B, -128);
+ cmp(N, 0x8);
+ jl(l2a4, T_NEAR);
+ align(4);
+
+L(l20);
+ mov(A1, A);
+ add(A, 0x8);
+ pxor(xmm8, xmm8);
+ pxor(xmm9, xmm9);
+ mov(I, M);
+ sar(I, 0x3);
+ jle(l15c, T_NEAR);
+ align(4);
+
+L(l40);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x60], xmm0);
+ movdqu(xword[B-0x50], xmm1);
+ sub(B, -64);
+ dec(I);
+ jg(l40, T_NEAR);
+ align(4);
+
+L(l15c);
+ test(M, 0x4);
+ jle(l1f4, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm2, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm3, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ movdqa(xmm1, xmm0);
+ punpcklwd(xmm0, xmm2);
+ punpckhwd(xmm1, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ pmovsxbw(xmm5, xmm1);
+ movhlps(xmm6, xmm1);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm9, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movdqu(xword[B-0x70], xmm1);
+ sub(B, -32);
+ align(4);
+
+L(l1f4);
+ test(M, 0x2);
+ jle(l248, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ movq(xmm1, qword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm8, xmm5);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm6, xmm6);
+ pmovsxwd(xmm6, xmm6);
+ paddd(xmm9, xmm6);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l248);
+ test(M, 0x1);
+ jle(l280, T_NEAR);
+ movq(xmm0, qword[A1-0x80]);
+ add(A1, LDA);
+ pmovsxbd(xmm5, xmm0);
+ pshufd(xmm6, xmm0, 0x55);
+ pmovsxbd(xmm6, xmm6);
+ paddd(xmm8, xmm5);
+ paddd(xmm9, xmm6);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l280);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm8);
+ movdqu(xword[A1+0x10], xmm9);
+ add(qword[ARG_BIAS], 0x20);
+ sub(N, 0x8);
+ cmp(N, 0x8);
+ jge(l20, T_NEAR);
+ align(4);
+
+L(l2a4);
+ cmp(N, 0x4);
+ jl(l468, T_NEAR);
+ align(4);
+
+L(l2b0);
+ mov(A1, A);
+ add(A, 0x4);
+ pxor(xmm7, xmm7);
+ mov(I, M);
+ sar(I, 0x3);
+ jle(l384, T_NEAR);
+ align(4);
+
+L(l2c8);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x70], xmm0);
+ sub(B, -32);
+ dec(I);
+ jg(l2c8, T_NEAR);
+ align(4);
+
+L(l384);
+ test(M, 0x4);
+ jle(l3e8, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm2, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm3, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ movhlps(xmm6, xmm0);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ align(4);
+
+L(l3e8);
+ test(M, 0x2);
+ jle(l424, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ add(A1, LDA);
+ movd(xmm1, dword[A1-0x80]);
+ add(A1, LDA);
+ punpcklbw(xmm0, xmm1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l424);
+ test(M, 0x1);
+ jle(l448, T_NEAR);
+ movd(xmm0, dword[A1-0x80]);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l448);
+ mov(A1, qword[ARG_BIAS]);
+ movdqu(xword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x10);
+ sub(N, 0x4);
+ cmp(N, 0x4);
+ jge(l2b0, T_NEAR);
+ align(4);
+
+L(l468);
+ cmp(N, 0x2);
+ jl(l646, T_NEAR);
+ align(4);
+
+L(l474);
+ mov(A1, A);
+ add(A, 0x2);
+ pxor(xmm7, xmm7);
+ mov(LDA3, M);
+ sar(LDA3, 0x3);
+ jle(l550, T_NEAR);
+ align(4);
+
+L(l48c);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm4, eax, 0x0);
+ punpcklbw(xmm1, xmm2);
+ punpcklbw(xmm3, xmm4);
+ punpcklwd(xmm1, xmm3);
+ punpcklqdq(xmm0, xmm1);
+ pshufd(xmm6, xmm0, 0xd8);
+ pmovsxbw(xmm5, xmm6);
+ movhlps(xmm6, xmm6);
+ pmovsxbw(xmm6, xmm6);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movdqu(xword[B-0x80], xmm0);
+ sub(B, -16);
+ dec(LDA3);
+ jg(l48c, T_NEAR);
+ align(4);
+
+L(l550);
+ test(M, 0x4);
+ jle(l5bc, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm2, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm3, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ punpcklbw(xmm2, xmm3);
+ punpcklwd(xmm0, xmm2);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ align(4);
+
+L(l5bc);
+ test(M, 0x2);
+ jle(l600, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm0, eax, 0x0);
+ mov(ax, word[A1-0x80]);
+ add(A1, LDA);
+ pinsrw(xmm1, eax, 0x0);
+ punpcklbw(xmm0, xmm1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l600);
+ test(M, 0x1);
+ jle(l628, T_NEAR);
+ mov(ax, word[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ mov(word[B-0x80], ax);
+ sub(B, -2);
+ align(4);
+
+L(l628);
+ mov(A1, qword[ARG_BIAS]);
+ movq(qword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x8);
+ sub(N, 0x2);
+ cmp(N, 0x2);
+ jge(l474, T_NEAR);
+ align(4);
+
+L(l646);
+ cmp(N, 0x1);
+ jl(l7e8, T_NEAR);
+ align(4);
+
+L(l650);
+ mov(A1, A);
+ add(A, 0x1);
+ pxor(xmm7, xmm7);
+ mov(LDA3, M);
+ sar(LDA3, 0x3);
+ jle(l700, T_NEAR);
+ align(4);
+
+L(l668);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x3);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x4);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x5);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x6);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x7);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm6);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movq(qword[B-0x80], xmm0);
+ sub(B, -8);
+ dec(LDA3);
+ jg(l668, T_NEAR);
+ align(4);
+
+L(l700);
+ test(M, 0x4);
+ jle(l760, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x0);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x1);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x2);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x3);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ movd(dword[B-0x80], xmm0);
+ sub(B, -4);
+ align(4);
+
+L(l760);
+ test(M, 0x2);
+ jle(l7a4, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x0);
+ mov(byte[B-0x80], al);
+ mov(al, byte[A1-0x80]);
+ add(A1, LDA);
+ pinsrb(xmm0, eax, 0x1);
+ pmovsxbw(xmm5, xmm0);
+ phaddw(xmm5, xmm5);
+ pmovsxwd(xmm5, xmm5);
+ paddd(xmm7, xmm5);
+ mov(byte[B-0x7f], al);
+ sub(B, -2);
+ align(4);
+
+L(l7a4);
+ test(M, 0x1);
+ jle(l7c8, T_NEAR);
+ mov(al, byte[A1-0x80]);
+ pinsrw(xmm0, eax, 0x0);
+ pmovsxbd(xmm5, xmm0);
+ paddd(xmm7, xmm5);
+ mov(byte[B-0x80], al);
+ sub(B, -1);
+ align(4);
+
+L(l7c8);
+ mov(A1, qword[ARG_BIAS]);
+ movd(dword[A1], xmm7);
+ add(qword[ARG_BIAS], 0x4);
+ sub(N, 0x1);
+ cmp(N, 0x1);
+ jge(l650, T_NEAR);
+ align(4);
+
+L(l7e8);
+
+ postamble();
+}
+outLocalLabel();
+
+#undef M
+#undef N
+#undef A
+#undef LDA
+#undef ALPHA
+#undef B
+#undef I
+#undef A1
+#undef A2
+#undef LDA3
+#ifdef _WIN32
+#undef ARG_ALPHA
+#undef ARG_B
+#endif
+#undef ARG_BIAS
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.cpp
new file mode 100644
index 0000000000..4fc11afcbc
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.cpp
@@ -0,0 +1,116 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <cstdint>
+
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "../f32/ref_gemm_f32.hpp"
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <typename b_dt>
+mkldnn_status_t ref_gemm_s8x8s32(const char *transa, const char *transb,
+ const char *offsetc, const int *M, const int *N, const int *K,
+ const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao,
+ const b_dt *B, const int *LDB, const int8_t *bo, const float *beta,
+ int32_t *C, const int *LDC, const int32_t *co) {
+
+ if (*M == 0 || *N == 0 || *K == 0)
+ return mkldnn_success;
+
+ bool OCisR = (*offsetc == 'R' || *offsetc == 'r');
+ bool OCisC = (*offsetc == 'C' || *offsetc == 'c');
+ bool AisN = (*transa == 'N' || *transa == 'n');
+ bool BisN = (*transb == 'N' || *transb == 'n');
+
+ int m = *M, n = *N, k = *K, lda = *LDA, ldb = *LDB, ldc = *LDC;
+ size_t sizeA = AisN ? lda * k : lda * m;
+ size_t sizeB = BisN ? ldb * n : ldb * k;
+ size_t sizeC = ldc * n;
+
+ double *dA = (double *)malloc(sizeA * sizeof(double), PAGE_4K);
+ double *dB = (double *)malloc(sizeB * sizeof(double), PAGE_4K);
+ double *dC = (double *)malloc(sizeC * sizeof(double), PAGE_4K);
+
+ if (utils::any_null(dA, dB, dC)) {
+ free(dA);
+ free(dB);
+ free(dC);
+ return mkldnn_out_of_memory;
+ }
+
+ auto da_setter = [=] (int i, int j, double v) { dA[j * lda + i] = v; };
+ auto db_setter = [=] (int i, int j, double v) { dB[j * ldb + i] = v; };
+
+ auto ia_accessor = [=] (int i, int j) { return A[j * lda + i]; };
+ auto ib_accessor = [=] (int i, int j) { return B[j * ldb + i]; };
+
+ const int a_rows = AisN ? m : k;
+ const int a_cols = AisN ? k : m;
+ mkldnn::impl::parallel_nd(a_cols, a_rows, [&](int j, int i) {
+ da_setter(i, j,
+ static_cast<double>(ia_accessor(i, j)) + static_cast<double>(ao[0]));
+ });
+
+ const int b_rows = BisN ? k : n;
+ const int b_cols = BisN ? n : k;
+ mkldnn::impl::parallel_nd(b_cols, b_rows, [&](int j, int i) {
+ db_setter(i, j,
+ static_cast<double>(ib_accessor(i, j)) + static_cast<double>(bo[0]));
+ });
+ double one = 1.0, zero = 0.0;
+ ref_gemm<double>(transa, transb, M, N, K, &one, dA, LDA, dB, LDB, &zero,
+ dC, LDC, nullptr);
+
+ auto i2d = [=] (int32_t v) { return static_cast<double>(v); };
+ auto f2d = [=] (float v) { return static_cast<double>(v); };
+
+ mkldnn::impl::parallel_nd(n, m, [&] (int j, int i) {
+ double coffset = OCisR ? i2d(co[j]) : OCisC ? i2d(co[i]) : i2d(co[0]);
+ double val = ((*beta == 0.0f) ? 0.0 : f2d(*beta) * i2d(C[i + j * ldc]))
+ + f2d(*alpha) * dC[i + j * ldc] + coffset;
+ C[i + j * ldc] = math::out_round<int32_t>(math::saturate<int32_t>(val));
+ });
+
+ free(dA);
+ free(dB);
+ free(dC);
+ return mkldnn_success;
+}
+
+template mkldnn_status_t ref_gemm_s8x8s32<uint8_t>(
+ const char *transa, const char *transb, const char *offsetc,
+ const int *M, const int *N, const int *K,
+ const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao,
+ const uint8_t *B, const int *LDB, const int8_t *bo,
+ const float *beta, int32_t *C, const int *LDC, const int32_t *co);
+
+template mkldnn_status_t ref_gemm_s8x8s32<int8_t>(
+ const char *transa, const char *transb, const char *offsetc,
+ const int *M, const int *N, const int *K,
+ const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao,
+ const int8_t *B, const int *LDB, const int8_t *bo,
+ const float *beta, int32_t *C, const int *LDC, const int32_t *co);
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.hpp
new file mode 100644
index 0000000000..6c0370ae99
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/ref_gemm_s8x8s32.hpp
@@ -0,0 +1,38 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef REF_GEMM_S8X8S32_HPP
+#define REF_GEMM_S8X8S32_HPP
+
+#include <stdint.h>
+
+#include "mkldnn_types.h"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <typename b_dt>
+mkldnn_status_t ref_gemm_s8x8s32(const char *transa, const char *transb,
+ const char *offsetc, const int *M, const int *N, const int *K,
+ const float *alpha, const int8_t *A, const int *LDA, const int8_t *ao,
+ const b_dt *B, const int *LDB, const int8_t *bo, const float *beta,
+ int32_t *C, const int *LDC, const int32_t *co);
+
+}
+}
+}
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.cpp
new file mode 100644
index 0000000000..de1035f3b2
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.cpp
@@ -0,0 +1,180 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "common.hpp"
+#include "nstl.hpp"
+#include "math_utils.hpp"
+
+#include "../gemm.hpp"
+#include "jit_avx512_core_gemm_s8u8s32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+void compensation_init(const char *offsetC, int32_t *compensation, int len,
+ const int32_t *oc) {
+ bool OCisC = (*offsetC == 'C' || *offsetC == 'c');
+ bool OCisF = (*offsetC == 'F' || *offsetC == 'f');
+
+ if (OCisF && (*oc) != 0) {
+ for (int i = 0; i < len; i++)
+ compensation[i] = *oc;
+ } else if (OCisC) {
+ for (int i = 0; i < len; i++)
+ compensation[i] = oc[i];
+ } else {
+ parallel_nd(len, [=](int i) { compensation[i] = 0; });
+ }
+}
+
+void compensation_compute(bool transa, int m, int k, float alpha,
+ const int8_t *a, int lda, int32_t *compensation) {
+ if (!transa) {
+ const int L2_cache_size = get_cache_size(2, true);
+ const int blocking_factor = nstl::min(k, L2_cache_size / lda + 1);
+ const int npanels = k / blocking_factor;
+ const bool has_tile = k % blocking_factor > 0;
+
+ parallel_nd(npanels, m, [&](int j, int i) {
+ int32_t val = 0;
+ for (int jb = 0; jb < blocking_factor; jb++) {
+ val += a[(i + (ptrdiff_t)j * blocking_factor * lda)
+ + (ptrdiff_t)jb * lda];
+ }
+ if (alpha != 1.0f) {
+ val = math::out_round<int32_t>(math::saturate<int32_t>(
+ (double)val * alpha * -128.0));
+ } else {
+ val *= -128;
+ }
+ fetch_and_add(&compensation[i], val);
+ });
+
+ if (has_tile) {
+ parallel_nd(m, [=](int i) {
+ int32_t val = 0;
+ for (int j = npanels * blocking_factor; j < k; j++) {
+ val += a[i + (ptrdiff_t)j * lda];
+ }
+ if (alpha != 1.0f) {
+ val = math::out_round<int32_t>(math::saturate<int32_t>(
+ (double)val * alpha * -128.0));
+ } else {
+ val *= -128;
+ }
+ fetch_and_add(&compensation[i], val);
+ });
+ }
+ } else {
+ parallel_nd(m, [=](int i) {
+ int32_t val = 0;
+ for (int j = 0; j < k; j++) {
+ val += a[j + (ptrdiff_t)i * lda];
+ }
+ if (alpha != 1.0f) {
+ val = math::out_round<int32_t>(math::saturate<int32_t>(
+ (double)val * alpha * -128.0));
+ } else {
+ val *= -128;
+ }
+ compensation[i] += val;
+ });
+ }
+}
+
+void copy_and_shift_b(bool transb, int k, int n, uint8_t *b_u8, int ldb_u8,
+ const int8_t *b_s8, int ldb_s8) {
+ const int b_cols = transb ? k : n;
+
+ parallel_nd(b_cols, [=](int j) {
+ const int b_rows = transb ? n : k;
+
+ uint8_t *pb_u8 = b_u8 + j * ldb_u8;
+ const int8_t *pb_s8 = b_s8 + j * ldb_s8;
+
+ for (int i = 0; i < b_rows; i++) {
+ (*pb_u8) = (*pb_s8) + 128;
+ pb_u8++;
+ pb_s8++;
+ }
+ });
+}
+
+/**
+ * gemm_s8s8s32 operation is defined as follows:
+ * C = alpha * op(A) * (op(B) + B_shift) + beta * C + C_offset + compensation
+ *
+ * where
+ * - compensation is a vector of length m that contains computed compensation
+ * that may contain C_offset if applicable. The compensation is applied inside
+ * gemm_s8u8s32 as a C_offset
+ * - B_shift is a k-by-n matrix, every element of B_shift is equal to 128
+ *
+ * What is the compensation:
+ * In order to prepare the matrix B for gemm_s8u8s32 call the B_shift is applied:
+ * C = alpha * op(A) * (op(B) + B_shift) + beta * C + C_offset =
+ * alpha * op(A) * op(B) + alpha * op(A) * B_shift + beta * C + C_offset
+ * compensation = -alpha * op(A) * B_shift
+ * Since B_shift is a matrix, every element of which is equal to 128 then
+ * - if op(A) = A: compensation contains sum of the elements in each row
+ * scaled by -128 * alpha
+ * - if op(A) = A**T: compensation contains sum of the elements in each column
+ * scaled by -128 * alpha
+ *
+ * The rest of parameters is described in mkldnn.h
+ */
+mkldnn_status_t simple_gemm_s8s8s32(
+ const char *transA, const char *transB, const char *offsetC,
+ const int *m, const int *n, const int *k,
+ const float *alpha, const int8_t *a, const int *lda, const int8_t *oa,
+ const int8_t *b, const int *ldb, const int8_t *ob,
+ const float *beta, int32_t *c, const int *ldc, const int32_t *oc) {
+ if (*oa != 0 || *ob != 0) return mkldnn_unimplemented;
+
+ int M = *m, N = *n, K = *k;
+ bool transa = (*transA == 'T' || *transA == 't');
+ bool transb = (*transB == 'T' || *transB == 't');
+ int ld = transb ? N : K;
+
+ uint8_t *b_u8 = (uint8_t *)malloc(sizeof(uint8_t) * K * N, 64);
+ int32_t *compensation = (int32_t *)malloc(sizeof(int32_t) * M, 64);
+
+ if (utils::any_null(b_u8, compensation)) {
+ free(b_u8);
+ free(compensation);
+ return mkldnn_out_of_memory;
+ }
+
+ compensation_init(offsetC, compensation, M, oc);
+ compensation_compute(transa, M, K, *alpha, a, *lda, compensation);
+ copy_and_shift_b(transb, K, N, b_u8, ld, b, *ldb);
+
+ gemm_s8x8s32(transA, transB, "C", m, n, k, alpha, a, lda, oa, b_u8,
+ &ld, ob, beta, c, ldc, compensation);
+
+ if ((*offsetC == 'R' || *offsetC == 'r'))
+ parallel_nd(M, N,
+ [=](int i, int j) { c[i + (ptrdiff_t)j * *ldc] += oc[j]; });
+
+ free(b_u8);
+ free(compensation);
+
+ return mkldnn_success;
+}
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.hpp
new file mode 100644
index 0000000000..03a3d2f7e0
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm/s8x8s32/simple_gemm_s8s8s32.hpp
@@ -0,0 +1,37 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef SIMPLE_GEMM_S8S8S32_HPP
+#define SIMPLE_GEMM_S8S8S32_HPP
+
+#include <stdint.h>
+#include "mkldnn_types.h"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+mkldnn_status_t simple_gemm_s8s8s32(
+ const char *transA, const char *transB, const char *offsetC,
+ const int *m, const int *n, const int *k,
+ const float *alpha, const int8_t *a, const int *lda, const int8_t *oa,
+ const int8_t *b, const int *ldb, const int8_t *ob,
+ const float *beta, int32_t *c, const int *ldc, const int32_t *oc);
+}
+}
+}
+
+#endif // SIMPLE_GEMM_S8S8S32_HPP
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.cpp
new file mode 100644
index 0000000000..604a728b47
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.cpp
@@ -0,0 +1,307 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn_types.h"
+
+#include "c_types_map.hpp"
+#include "gemm_convolution.hpp"
+#include "utils.hpp"
+#include "type_helpers.hpp"
+#include "mkldnn_thread.hpp"
+#include "ref_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+void gemm_convolution_fwd_t::execute_forward(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ auto col = scratchpad(ctx).get<data_t>(key_conv_gemm_col);
+
+ const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_;
+
+ const int M = jcp.os * jcp.od;
+ const size_t src_step = jcp.ic * jcp.ih * jcp.iw * jcp.id;
+ const size_t dst_step = jcp.oc * M;
+ const size_t weights_g_size = jcp.ic * jcp.oc * jcp.ks;
+
+ assert(IMPLICATION(
+ jcp.id != 1, jcp.oh_block == jcp.oh && jcp.ow_block == jcp.ow));
+ assert(IMPLICATION(jcp.ow_block != jcp.ow, jcp.oh_block == 1));
+
+ const int K = jcp.ic * jcp.ks;
+ const int N = jcp.oc;
+
+ if (jcp.im2col_sz && jcp.id != 1)
+ parallel_nd(jcp.im2col_sz * jcp.nthr,
+ [&](ptrdiff_t i) { col[i] = (data_t)0; });
+
+ const int nb_oh = div_up(jcp.oh, jcp.oh_block);
+ const int nb_ow = div_up(jcp.ow, jcp.ow_block);
+ const size_t work_amount = jcp.ngroups * jcp.mb * jcp.od * nb_oh * nb_ow;
+ parallel(jcp.nthr, [&](const int ithr, const int nthr) {
+ data_t *_col = col + (ptrdiff_t)ithr * jcp.im2col_sz;
+
+ int g{ 0 }, n{ 0 }, od{ 0 }, ohb{ 0 }, owb{ 0 };
+ size_t start = 0, end = 0;
+
+ balance211(work_amount, nthr, ithr, start, end);
+ nd_iterator_init(start, g, jcp.ngroups, n, jcp.mb, od, jcp.od, ohb,
+ nb_oh, owb, nb_ow);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ int oh = ohb * jcp.oh_block;
+ int ow = owb * jcp.ow_block;
+ const data_t *_src = src + (n * jcp.ngroups + g) * src_step;
+ const data_t *_weights = weights + g * weights_g_size;
+ data_t *_dst_im = dst + (n * jcp.ngroups + g) * dst_step;
+ const int h_step = nstl::min(jcp.oh_block, jcp.oh - oh);
+ const int w_step = nstl::min(jcp.ow_block, jcp.ow - ow);
+ if (jcp.im2col_sz) {
+ if (jcp.id == 1)
+ jit_gemm_convolution_utils::im2col(
+ jcp, _src, _col, oh, h_step, ow, w_step);
+ else
+ jit_gemm_convolution_utils::im2col_3d(jcp, _src, _col, od);
+ }
+
+ const data_t one = 1.0;
+
+ const int m = h_step * w_step;
+ const int LDA = jcp.im2col_sz ? m : M;
+ data_t *_dst = _dst_im + od * jcp.os + oh * jcp.ow + ow;
+
+ extended_sgemm("N", "N", &m, &N, &K, &one,
+ jcp.im2col_sz ? _col : _src + od * m, &LDA, _weights, &K,
+ &this->beta_, _dst, &M);
+
+ data_t *d = _dst;
+ if (eltwise_) {
+ // fast branch for ReLU case
+ if (eltwise_->alg_ == alg_kind::eltwise_relu) {
+ parallel_nd(jcp.oc, [&](const int oc) {
+ data_t b = jcp.with_bias ? bias[g * jcp.oc + oc] : 0;
+ data_t *d_ = d + oc * M;
+ PRAGMA_OMP_SIMD()
+ for (int oS = 0; oS < m; ++oS) {
+ d_[oS] += b;
+ if (d_[oS] < 0) d_[oS] *= eltwise_->alpha_;
+ }
+ });
+ } else {
+ parallel_nd(jcp.oc, [&](const int oc) {
+ data_t b = jcp.with_bias ? bias[g * jcp.oc + oc] : 0;
+ data_t *d_ = d + oc * M;
+ PRAGMA_OMP_SIMD()
+ for (int oS = 0; oS < m; ++oS) {
+ d_[oS] += b;
+ d_[oS] = eltwise_->compute_scalar(d_[oS]);
+ }
+ });
+ }
+ } else if (jcp.with_bias) {
+ parallel_nd(jcp.oc, [&](const int oc) {
+ data_t b = bias[g * jcp.oc + oc];
+ data_t *d_ = d + oc * M;
+ PRAGMA_OMP_SIMD()
+ for (int oS = 0; oS < m; ++oS) {
+ d_[oS] += b;
+ }
+ });
+ }
+ nd_iterator_step(g, jcp.ngroups, n, jcp.mb, od, jcp.od, ohb, nb_oh,
+ owb, nb_ow);
+ }
+ });
+}
+
+void gemm_convolution_bwd_data_t::execute_backward_data(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ auto col = scratchpad(ctx).get<data_t>(key_conv_gemm_col);
+
+ const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_;
+
+ const int M = jcp.os * jcp.od;
+ const size_t src_step = jcp.ic * jcp.ih * jcp.iw * jcp.id;
+ const size_t dst_step = jcp.oc * M;
+ const size_t weights_g_size = jcp.ic * jcp.oc * jcp.ks;
+
+ const int m = jcp.os;
+ const int K = jcp.oc;
+ const int N = jcp.ic * jcp.ks;
+ const int LDC = jcp.im2col_sz ? m : M;
+
+ const size_t work_amount = (size_t)jcp.ngroups * jcp.mb;
+
+ if (jcp.id > 1) {
+ const ptrdiff_t diff_src_sz = (ptrdiff_t)(work_amount * src_step);
+ parallel_nd(diff_src_sz, [&](ptrdiff_t i) { diff_src[i] = (data_t)0; });
+ }
+
+ parallel(jcp.nthr, [&](const int ithr, const int nthr) {
+ data_t *_col = col + (ptrdiff_t)ithr * jcp.im2col_sz;
+
+ int g{0}, n{0};
+ size_t start = 0, end = 0;
+ balance211(work_amount, nthr, ithr, start, end);
+ nd_iterator_init(start, g, jcp.ngroups, n, jcp.mb);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+
+ data_t *_diff_src = diff_src + (n * jcp.ngroups + g)*src_step;
+ const data_t *_weights = weights + g * weights_g_size;
+ for (int od = 0; od < jcp.od; ++od) {
+ const data_t *_diff_dst = diff_dst + (n * jcp.ngroups + g)
+ *dst_step + od * m;
+
+ const data_t zero = 0.0, one = 1.0;
+ extended_sgemm("N", "T", &m, &N, &K, &one, _diff_dst, &M,
+ _weights, &N, &zero,
+ jcp.im2col_sz ? _col:_diff_src + od * m, &LDC);
+
+ if (jcp.im2col_sz) {
+ if (jcp.id == 1)
+ jit_gemm_convolution_utils::col2im(jcp, _col,
+ _diff_src);
+ else
+ jit_gemm_convolution_utils::col2im_3d(jcp, _col,
+ _diff_src, od);
+ }
+ }
+ nd_iterator_step(g, jcp.ngroups, n, jcp.mb);
+ }
+ });
+}
+
+void gemm_convolution_bwd_weights_t::execute_backward_weights(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS);
+ auto diff_bias = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS);
+
+ auto col = scratchpad(ctx).get<data_t>(key_conv_gemm_col);
+ auto wei_reduction = scratchpad(ctx).get<data_t>(key_conv_wei_reduction);
+
+ const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_;
+
+ const int K = jcp.os * jcp.od;
+ const size_t src_step = jcp.ic * jcp.ih * jcp.iw * jcp.id;
+ const size_t dst_step = jcp.oc * K;
+ const size_t weights_g_size = jcp.ic * jcp.oc * jcp.ks;
+
+ const int k = jcp.os;
+ const int N = jcp.oc;
+ const int M = jcp.ic * jcp.ks;
+ const int LDA = jcp.im2col_sz ? k : K;
+
+ parallel_nd(jcp.im2col_sz * jcp.nthr,
+ [&](ptrdiff_t i) { col[i] = (data_t)0; });
+
+ parallel(jcp.nthr, [&](const int ithr, const int nthr) {
+ int ithr_g, nthr_g, ithr_mb, nthr_mb;
+ size_t g_start{0}, g_end{0}, mb_start{0}, mb_end{0};
+
+ const int mb_for_balance = jcp.need_wei_reduction ? jcp.mb : 1;
+ jit_gemm_convolution_utils::bwd_weights_balance(ithr, nthr, jcp.ngroups,
+ mb_for_balance, ithr_g, nthr_g, ithr_mb, nthr_mb);
+
+ assert(IMPLICATION(!jcp.need_wei_reduction, nthr_mb == 1));
+ const int need_reduction = nthr_mb != 1;
+
+ if (ithr_g != -1 && ithr_mb != -1) {
+ balance211((size_t)jcp.ngroups, nthr_g, ithr_g, g_start, g_end);
+ balance211((size_t)jcp.mb, nthr_mb, ithr_mb, mb_start, mb_end);
+
+ assert(IMPLICATION((g_end - g_start) > 1, need_reduction == 0));
+
+ data_t *_col = col + (ptrdiff_t)ithr * jcp.im2col_sz;
+ data_t *weights_reduce_base = wei_reduction
+ + ithr_g * nthr_mb * weights_g_size;
+ data_t *weights_reduce = weights_reduce_base
+ + ithr_mb * weights_g_size;
+
+ for (size_t g = g_start; g < g_end; ++g) {
+ data_t *_diff_weights = need_reduction
+ ? weights_reduce : (diff_weights + g * weights_g_size);
+ for (size_t mb = mb_start; mb < mb_end; ++mb) {
+ const data_t *_src = src + (mb*jcp.ngroups+g)*src_step;
+ for (int od = 0; od < jcp.od; ++od) {
+ const data_t *_diff_dst = diff_dst
+ + (mb*jcp.ngroups+g)*dst_step + od * k;
+
+ if (jcp.im2col_sz) {
+ if (jcp.id == 1)
+ jit_gemm_convolution_utils::im2col(
+ jcp, _src, _col, 0, jcp.oh, 0, jcp.ow);
+ else
+ jit_gemm_convolution_utils::im2col_3d(jcp, _src,
+ _col, od);
+ }
+
+ const data_t zero = 0.0, one = 1.0;
+ extended_sgemm(
+ "T", "N", &M, &N, &k, &one,
+ jcp.im2col_sz ? _col : _src + od * k,
+ &LDA, _diff_dst, &K,
+ mb == mb_start && od == 0 ? &zero : &one,
+ _diff_weights, &M);
+ }
+ }
+ }
+ if (need_reduction) {
+ mkldnn_thr_barrier();
+ data_t *weights_base = diff_weights + g_start * weights_g_size;
+ jit_gemm_convolution_utils::bwd_weights_reduction_par(
+ ithr_mb, nthr_mb, jcp, weights_reduce_base, weights_base);
+ }
+ } else
+ if (need_reduction) { mkldnn_thr_barrier(); }
+ });
+
+ if (jcp.with_bias) {
+ parallel_nd(jcp.ngroups, jcp.oc, [&](int g, int oc) {
+ data_t db = 0;
+ size_t offset_ = (size_t)g * dst_step + (size_t)oc * K;
+ for (int mb = 0; mb < jcp.mb; ++mb)
+ {
+ size_t offset = offset_ + (size_t)mb * jcp.ngroups * dst_step;
+ for (int od = 0; od < jcp.od; ++od)
+ for (int oh = 0; oh < jcp.oh; ++oh)
+ PRAGMA_OMP_SIMD(reduction(+:db))
+ for (int ow = 0; ow < jcp.ow; ++ow) {
+ db += diff_dst[offset];
+ offset++;
+ }
+ }
+ diff_bias[g*jcp.oc+oc] = db;
+ });
+ }
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.hpp
new file mode 100644
index 0000000000..302e46369a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution.hpp
@@ -0,0 +1,250 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_GEMM_CONVOLUTION_HPP
+#define CPU_JIT_GEMM_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "gemm_convolution_utils.hpp"
+#include "gemm/gemm.hpp"
+#include "ref_eltwise.hpp"
+
+#include "cpu_convolution_pd.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct gemm_convolution_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc, const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_convolution_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats_common(dat_tag(), wei_tag(), dat_tag())
+ && post_ops_ok()
+ && memory_desc_matches_tag(*src_md(), dat_tag())
+ && memory_desc_matches_tag(*dst_md(), dat_tag())
+ && memory_desc_matches_tag(*weights_md(), wei_tag());
+ if (!ok) return status::unimplemented;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ return jit_gemm_convolution_utils::init_conf(jcp_, scratchpad,
+ *desc(), src_md(), weights_md(0), dst_md(),
+ mkldnn_get_max_threads());
+ }
+
+ jit_gemm_conv_conf_t jcp_;
+
+ protected:
+ format_tag_t dat_tag() const {
+ using namespace format_tag;
+ return utils::pick(ndims() - 3, ncw, nchw, ncdhw);
+ }
+
+ format_tag_t wei_tag() const {
+ using namespace format_tag;
+ return with_groups()
+ ? utils::pick(ndims() - 3, goiw, goihw, goidhw)
+ : utils::pick(ndims() - 3, oiw, oihw, oidhw);
+ }
+
+ bool post_ops_ok() const {
+ auto const &po = attr()->post_ops_;
+ auto is_eltwise = [&](int idx)
+ { return po.entry_[idx].is_eltwise(); };
+ auto is_sum = [&](int idx) { return po.entry_[idx].is_sum(); };
+
+ switch (po.len_) {
+ case 0: return true; // no post_ops
+ case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise
+ case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise
+ default: return false;
+ }
+ return false;
+ }
+ };
+
+ gemm_convolution_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd, true)
+ , eltwise_(nullptr)
+ {
+ const auto &post_ops = pd()->attr()->post_ops_;
+ const data_t one = 1.0, zero = 0.0;
+ beta_ = post_ops.find(primitive_kind::sum) >= 0 ? one : zero;
+
+ const int entry_idx = post_ops.find(primitive_kind::eltwise);
+ if (entry_idx != -1) eltwise_ = new ref_eltwise_scalar_fwd_t(
+ post_ops.entry_[entry_idx].eltwise);
+ }
+
+ ~gemm_convolution_fwd_t() { delete eltwise_; }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ data_t beta_;
+
+ ref_eltwise_scalar_fwd_t* eltwise_;
+};
+
+struct gemm_convolution_bwd_data_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_data_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc, const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_convolution_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_data
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::undef, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats_common(dat_tag(), wei_tag(), dat_tag())
+ && memory_desc_matches_tag(*diff_src_md(), dat_tag())
+ && memory_desc_matches_tag(*diff_dst_md(), dat_tag())
+ && memory_desc_matches_tag(*weights_md(), wei_tag());
+ if (!ok) return status::unimplemented;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ return jit_gemm_convolution_utils::init_conf(jcp_, scratchpad,
+ *desc(), diff_src_md(), weights_md(0), diff_dst_md(),
+ mkldnn_get_max_threads());
+ }
+
+ jit_gemm_conv_conf_t jcp_;
+
+ protected:
+ format_tag_t dat_tag() const {
+ using namespace format_tag;
+ return utils::pick(ndims() - 3, ncw, nchw, ncdhw);
+ }
+
+ format_tag_t wei_tag() const {
+ using namespace format_tag;
+ return with_groups()
+ ? utils::pick(ndims() - 3, goiw, goihw, goidhw)
+ : utils::pick(ndims() - 3, oiw, oihw, oidhw);
+ }
+ };
+
+ gemm_convolution_bwd_data_t(const pd_t *apd)
+ : cpu_primitive_t(apd, true) {}
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_data(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_data(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+struct gemm_convolution_bwd_weights_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_weights_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_convolution_bwd_weights_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_weights
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats_common(dat_tag(), wei_tag(), dat_tag())
+ && memory_desc_matches_tag(*src_md(), dat_tag())
+ && memory_desc_matches_tag(*diff_dst_md(), dat_tag())
+ && memory_desc_matches_tag(*diff_weights_md(), wei_tag());
+ if (!ok) return status::unimplemented;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ return jit_gemm_convolution_utils::init_conf(jcp_, scratchpad,
+ *desc(), src_md(), diff_weights_md(0), diff_dst_md(),
+ mkldnn_get_max_threads());
+ }
+
+ jit_gemm_conv_conf_t jcp_;
+
+ protected:
+ format_tag_t dat_tag() const {
+ using namespace format_tag;
+ return utils::pick(ndims() - 3, ncw, nchw, ncdhw);
+ }
+
+ format_tag_t wei_tag() const {
+ using namespace format_tag;
+ return with_groups()
+ ? utils::pick(ndims() - 3, goiw, goihw, goidhw)
+ : utils::pick(ndims() - 3, oiw, oihw, oidhw);
+ }
+ };
+
+ gemm_convolution_bwd_weights_t(const pd_t *apd)
+ : cpu_primitive_t(apd, true) {}
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_weights(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_weights(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.cpp
new file mode 100644
index 0000000000..f133b1e62b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.cpp
@@ -0,0 +1,771 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn_types.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+#include "cpu_isa_traits.hpp"
+
+#include "gemm_convolution_utils.hpp"
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::utils;
+using namespace prop_kind;
+using namespace data_type;
+
+namespace jit_gemm_convolution_utils {
+
+void im2col_3d(const jit_gemm_conv_conf_t &jcp, const float *im, float *col,
+ int od)
+{
+ const size_t OHW = jcp.oh * jcp.ow;
+ const size_t im_step = jcp.ih * jcp.iw * jcp.id;
+ const size_t col_step = jcp.ks * OHW;
+
+ parallel_nd(jcp.ic, [&](int ic) {
+ const float *__restrict im_loc = im + ic * im_step;
+ float *__restrict col_loc = col + ic * col_step;
+ int id = od * jcp.stride_d - jcp.f_pad;
+ for (int kd = 0; kd < jcp.kd; ++kd) {
+ float *__restrict col_ = col_loc + kd * jcp.kh * jcp.kw * OHW;
+ if (id < 0 || id >= jcp.id) {
+ int ih_ = -jcp.t_pad;
+ for (int kh = 0; kh < jcp.kh; ++kh) {
+ int ih = ih_;
+ for (int oh = 0; oh < jcp.oh; ++oh) {
+ if (ih < 0 || ih >= jcp.ih) {
+ ih += jcp.stride_h;
+ continue;
+ }
+ int iw_ = -jcp.l_pad;
+ for (int kw = 0; kw < jcp.kw; ++kw) {
+ int iw = iw_;
+ for (int ow = 0; ow < jcp.ow; ++ow) {
+ if (iw < 0 || iw >= jcp.iw) {
+ iw += jcp.stride_w;
+ continue;
+ }
+
+ const size_t col_idx = kw * OHW + oh * jcp.ow
+ + ow;
+
+ col_[col_idx] = 0;
+ iw += jcp.stride_w;
+ }
+ iw_ += (1 + jcp.dilate_w);
+ }
+ ih += jcp.stride_h;
+ }
+ ih_ += (1 + jcp.dilate_h);
+ col_ += jcp.kw * OHW;
+ }
+ } else {
+ const float *__restrict im_ = im_loc + id * jcp.ih * jcp.iw;
+ int ih_ = -jcp.t_pad;
+ for (int kh = 0; kh < jcp.kh; ++kh) {
+ int ih = ih_;
+ for (int oh = 0; oh < jcp.oh; ++oh) {
+ if (ih < 0 || ih >= jcp.ih) {
+ ih += jcp.stride_h;
+ continue;
+ }
+ int iw_ = -jcp.l_pad;
+ for (int kw = 0; kw < jcp.kw; ++kw) {
+ int iw = iw_;
+ for (int ow = 0; ow < jcp.ow; ++ow) {
+ if (iw < 0 || iw >= jcp.iw) {
+ iw += jcp.stride_w;
+ continue;
+ }
+
+ const size_t col_idx = kw * OHW + oh * jcp.ow
+ + ow;
+ const size_t im_idx = ih * jcp.iw + iw;
+
+ col_[col_idx] = im_[im_idx];
+ iw += jcp.stride_w;
+ }
+ iw_ += (1 + jcp.dilate_w);
+ }
+ ih += jcp.stride_h;
+ }
+ ih_ += (1 + jcp.dilate_h);
+ col_ += jcp.kw * OHW;
+ }
+ }
+ id += (1 + jcp.dilate_d);
+ }
+ });
+}
+
+/* col[ic][kh][kw][oh][ow] <-- im2col(im[ic][ih][iw]) */
+void im2col(const jit_gemm_conv_conf_t &jcp, const float *__restrict im,
+ float *__restrict col, int hs, int hb, int ws, int wb) {
+ const size_t im_step = jcp.is;
+ const size_t col_step = jcp.ks * hb * wb;
+ if (jcp.stride_w == 1) {
+ // Generated code is more optimized for stride_w == 1
+ // because innermost loop is by width
+ auto ker = [&](int ic, int kh, int kw, int oh) {
+ const float *__restrict im_ = im + ic * im_step;
+ float *__restrict col_
+ = col + ic * col_step + ((kh * jcp.kw + kw) * hb + oh) * wb;
+
+ const int ih = (oh + hs) * jcp.stride_h - jcp.t_pad
+ + kh * (1 + jcp.dilate_h);
+ if (ih < 0 || ih >= jcp.ih) {
+ for (int ow = 0; ow < wb; ++ow)
+ col_[ow] = 0.f;
+ } else {
+ for (int ow = 0; ow < wb; ++ow) {
+ const int iw = ow + ws - jcp.l_pad + kw * (1 + jcp.dilate_w);
+ if (iw < 0 || iw >= jcp.iw)
+ col_[ow] = 0.f;
+ else {
+ const size_t im_idx = ih * jcp.iw + iw;
+ col_[ow] = im_[im_idx];
+ }
+ }
+ }
+ };
+
+ if (jcp.outer_threading) {
+ for (int ic = 0; ic < jcp.ic; ic++)
+ for (int kh = 0; kh < jcp.kh; kh++)
+ for (int kw = 0; kw < jcp.kw; kw++)
+ for (int oh = 0; oh < hb; oh++)
+ ker(ic, kh, kw, oh);
+ }
+ else {
+ parallel_nd(jcp.ic, jcp.kh, jcp.kw, hb, ker);
+ }
+ } else if (jcp.ic == 1) {
+ parallel_nd(jcp.kh, hb, [&](int kh, int oh) {
+ const int ih = (oh + hs) * jcp.stride_h - jcp.t_pad
+ + kh * (1 + jcp.dilate_h);
+ if (ih < 0 || ih >= jcp.ih)
+ for (int kw = 0; kw < jcp.kw; ++kw) {
+ for (int ow = 0; ow < wb; ++ow) {
+ const size_t col_idx
+ = ((kh * jcp.kw + kw) * hb + oh) * wb + ow;
+ col[col_idx] = 0;
+ }
+ }
+ else
+ for (int kw = 0; kw < jcp.kw; ++kw) {
+ for (int ow = 0; ow < wb; ++ow) {
+ const int iw = (ow + ws) * jcp.stride_w - jcp.l_pad
+ + kw * (1 + jcp.dilate_w);
+ const size_t col_idx
+ = ((kh * jcp.kw + kw) * hb + oh) * wb + ow;
+ const size_t im_idx = ih * jcp.iw + iw;
+ if (iw < 0 || iw >= jcp.iw)
+ col[col_idx] = 0;
+ else
+ col[col_idx] = im[im_idx];
+ }
+ }
+ });
+ } else {
+
+ parallel_nd(jcp.ic, jcp.kh, jcp.kw, hb,
+ [&](int ic, int kh, int kw, int oh) {
+ const float *__restrict im_ = im + ic * im_step;
+ float *__restrict col_ = col + ic * col_step
+ + ((kh * jcp.kw + kw) * hb + oh) * wb;
+
+ const int ih = (oh + hs) * jcp.stride_h - jcp.t_pad
+ + kh * (1 + jcp.dilate_h);
+ if (ih < 0 || ih >= jcp.ih) {
+ for (int ow = 0; ow < wb; ++ow)
+ col_[ow] = 0.f;
+ } else {
+ for (int ow = 0; ow < wb; ++ow) {
+ const int iw = (ow + ws) * jcp.stride_w - jcp.l_pad
+ + kw * (1 + jcp.dilate_w);
+ const size_t im_idx = ih * jcp.iw + iw;
+ if (iw < 0 || iw >= jcp.iw)
+ col_[ow] = 0.f;
+ else
+ col_[ow] = im_[im_idx];
+ }
+ }
+ });
+ }
+}
+
+inline int limit(int low, int upper, int value) {
+ return nstl::max(low, nstl::min(upper, value));
+}
+
+/* col[kh][kw][ic][oh][ow] <-- im2col_u8(im[ih][iw][ic]) */
+template <typename T>
+void im2col_u8(const jit_gemm_conv_conf_t &jcp, const T *__restrict im,
+ T *__restrict imtr, uint8_t *__restrict col, int hs, int hb, int ws,
+ int wb) {
+ uint8_t shift = jcp.signed_input ? 128 : 0;
+ const int dh = 1 + jcp.dilate_h;
+ const int dw = 1 + jcp.dilate_w;
+ const int sh = jcp.stride_h;
+ const int sw = jcp.stride_w;
+ const int im_iw_stride = jcp.ic * jcp.ngroups;
+ const int im_ih_stride = jcp.iw * im_iw_stride;
+ const int tp = jcp.t_pad;
+ const int lp = jcp.l_pad;
+
+ if (jcp.outer_threading && sh == 1 && sw == 1 && dh == 1 && dw == 1) {
+ /* im[ih][iw][ic] --> imtr[ic][ih][iw] --> col[kh][kw][ic][oh][ow] */
+ const int hp = hs - tp;
+ const int wp = ws - lp;
+ const int ih_start = limit(0, jcp.ih, hp);
+ const int ih_end = limit(0, jcp.ih, hp + hb + jcp.kh);
+ const int iw_start = limit(0, jcp.iw, wp);
+ const int iw_end = limit(0, jcp.iw, wp + wb + jcp.kw);
+
+ const int ihb = ih_end - ih_start;
+ const int iwb = iw_end - iw_start;
+
+ const int imtr_ic_stride = ihb * iwb;
+ const ptrdiff_t imtr_idx_shift = ih_start * iwb + iw_start;
+ for (int ic = 0; ic < jcp.ic; ic++) {
+ const ptrdiff_t imtr_idx_ic = ic * imtr_ic_stride - imtr_idx_shift;
+ for (int ih = ih_start; ih < ih_end; ih++) {
+ const ptrdiff_t im_idx_ih = ic + ih * im_ih_stride;
+ const ptrdiff_t imtr_idx_ih = imtr_idx_ic + ih * iwb;
+ for (int iw = iw_start; iw < iw_end; iw++)
+ imtr[imtr_idx_ih + iw] = im[im_idx_ih + iw * im_iw_stride];
+ }
+ }
+
+ const int col_ic_str = hb * wb;
+ const int col_kw_stride = jcp.ic * col_ic_str;
+ const int col_kh_stride = jcp.kw * col_kw_stride;
+
+ const int oh_init = ih_start - hp;
+ const int ow_init = iw_start - wp;
+ for (int kh = 0; kh < jcp.kh; kh++) {
+ const ptrdiff_t col_idx_kh = kh * col_kh_stride;
+ const int oh_kh = oh_init - kh;
+ const int oh_start = limit(0, hb, oh_kh);
+ const int oh_end = limit(0, hb, oh_kh + ihb);
+ for (int kw = 0; kw < jcp.kw; kw++) {
+ const ptrdiff_t col_idx_kw
+ = col_idx_kh + kw * jcp.ic * col_ic_str;
+ const int ow_kw = ow_init - kw;
+ const int imtr_shift = oh_kh * iwb + ow_kw;
+ const int ow_start = limit(0, wb, ow_kw);
+ const int ow_end = limit(0, wb, ow_kw + iwb);
+ for (int ic = 0; ic < jcp.ic; ic++) {
+ const ptrdiff_t col_idx_ic = col_idx_kw + ic * col_ic_str;
+ const int imtr_idx_ic = ic * imtr_ic_stride - imtr_shift;
+ for (int oh = 0; oh < oh_start; oh++) {
+ const ptrdiff_t col_idx_oh = col_idx_ic + oh * wb;
+ for (int ow = 0; ow < wb; ++ow)
+ col[col_idx_oh + ow] = shift;
+ }
+ for (int oh = oh_start; oh < oh_end; oh++) {
+ const ptrdiff_t col_idx_oh = col_idx_ic + oh * wb;
+ const ptrdiff_t imtr_idx_oh = imtr_idx_ic + oh * iwb;
+ for (int ow = 0; ow < ow_start; ++ow)
+ col[col_idx_oh + ow] = shift;
+ for (int ow = ow_start; ow < ow_end; ++ow)
+ col[col_idx_oh + ow]
+ = imtr[imtr_idx_oh + ow] + shift;
+ for (int ow = ow_end; ow < wb; ++ow)
+ col[col_idx_oh + ow] = shift;
+ }
+ for (int oh = oh_end; oh < hb; oh++) {
+ const ptrdiff_t col_idx_oh = col_idx_ic + oh * wb;
+ for (int ow = 0; ow < wb; ++ow)
+ col[col_idx_oh + ow] = shift;
+ }
+ }
+ }
+ }
+ } else {
+ parallel_nd(jcp.kh, jcp.kw, jcp.ic, hb,
+ [&](int kh, int kw, int ic, int oh) {
+ const int hp = tp - kh * dh;
+ const int ih = (oh + hs) * sh - hp;
+ const ptrdiff_t col_idx_base
+ = (((kh * jcp.kw + kw) * jcp.ic + ic) * hb + oh) * wb;
+ if (ih < 0 || ih >= jcp.ih)
+ for (int ow = 0; ow < wb; ow++)
+ col[col_idx_base + ow] = shift;
+ else {
+ const int wp = lp - kw * dw;
+ const int ow_start = limit(0, wb, div_up(wp, sw) - ws);
+ const int ow_end
+ = limit(0, wb, div_up(jcp.iw + wp, sw) - ws);
+ for (int ow = 0; ow < ow_start; ow++)
+ col[col_idx_base + ow] = shift;
+ const int iw_base = ws * sw - wp;
+ const ptrdiff_t im_idx_base = ih * im_ih_stride + ic;
+ for (int ow = ow_start; ow < ow_end; ow++) {
+ const int iw = iw_base + ow * sw;
+ const ptrdiff_t im_idx
+ = im_idx_base + iw * im_iw_stride;
+ col[col_idx_base + ow] = im[im_idx] + shift;
+ }
+ for (int ow = ow_end; ow < wb; ow++)
+ col[col_idx_base + ow] = shift;
+ }
+ });
+ }
+}
+
+template void im2col_u8<int8_t>(const jit_gemm_conv_conf_t &jcp,
+ const int8_t *__restrict im, int8_t *__restrict imtr,
+ uint8_t *__restrict col, int hs, int hb, int ws, int wb);
+template void im2col_u8<uint8_t>(const jit_gemm_conv_conf_t &jcp,
+ const uint8_t *__restrict im, uint8_t *__restrict imtr,
+ uint8_t *__restrict col, int hs, int hb, int ws, int wb);
+
+/* im[ih][iw][ic] <-- col2im_s32(col[oh][ow][kh][kw][ic]) */
+void col2im_s32(const jit_gemm_conv_conf_t &jcp, const int32_t *__restrict col,
+ int32_t *__restrict im)
+{
+ parallel(0, [&](const int ithr, const int nthr) {
+ int h_nthr = nstl::min(jcp.ih, nthr);
+ int w_nthr = nstl::min(jcp.iw, nthr / h_nthr);
+ int h_ithr = 1, h_s = 0, h_e = 0, w_ithr = 1, w_s = 0, w_e = 0;
+ if (ithr < h_nthr * w_nthr) {
+ h_ithr = ithr / w_nthr;
+ w_ithr = ithr % w_nthr;
+ balance211(jcp.ih, h_nthr, h_ithr, h_s, h_e);
+ balance211(jcp.iw, w_nthr, w_ithr, w_s, w_e);
+ } else {
+ h_ithr = w_ithr = -ithr;
+ h_s = h_e = w_s = w_e = -1;
+ }
+
+ for (int ih = h_s; ih < h_e; ++ih) {
+ for (int iw = w_s; iw < w_e; ++iw) {
+ PRAGMA_OMP_SIMD()
+ for (int ic = 0; ic < jcp.ic; ++ic) {
+ im[(ih * jcp.iw + iw) * jcp.ic + ic] = 0;
+ }
+ }
+ }
+
+ // TODO: reduce region: [0.. oh] --> [h_s * sh .. h_e * sh]
+ for (int oh = 0; oh < jcp.oh; ++oh) {
+ for (int ow = 0; ow < jcp.ow; ++ow) {
+ for (int kh = 0; kh < jcp.kh; ++kh) {
+ const int ih = oh * jcp.stride_h
+ - jcp.t_pad + kh * (1 + jcp.dilate_h);
+ if (ih < h_s || ih >= h_e) continue;
+
+ for (int kw = 0; kw < jcp.kw; ++kw) {
+ const int iw = ow * jcp.stride_w
+ - jcp.l_pad + kw * (1 + jcp.dilate_w);
+ if (iw < w_s || iw >= w_e) continue;
+
+ const size_t col_idx = (((oh * jcp.ow + ow) * jcp.kh
+ + kh) * jcp.kw + kw) * jcp.ic;
+ const size_t im_idx
+ = (ih * jcp.iw + iw) * jcp.ic;
+ PRAGMA_OMP_SIMD()
+ for (int ic = 0; ic < jcp.ic; ++ic) {
+ im[im_idx + ic] += col[col_idx + ic];
+ }
+ }
+ }
+ }
+ }
+ });
+}
+
+void col2im_3d(const jit_gemm_conv_conf_t &jcp, const float *col, float *im,
+ int od)
+{
+ parallel_nd(jcp.ic, [&](int ic) {
+ const float *__restrict col_ = col + (size_t)ic * jcp.ks * jcp.os;
+ float *__restrict im_ic = im + (size_t)ic * jcp.ih * jcp.iw * jcp.id;
+
+ int id = od * jcp.stride_d - jcp.f_pad;
+ for (int kd = 0; kd < jcp.kd; ++kd) {
+ if (id < 0 || id >= jcp.id) {
+ col_ += jcp.kh * jcp.kw * jcp.os;
+ id += (1 + jcp.dilate_d);
+ continue;
+ }
+
+ float *__restrict im_ = im_ic + id * jcp.ih * jcp.iw;
+
+ for (int oh = 0; oh < jcp.oh; ++oh) {
+ for (int kh = 0; kh < jcp.kh; ++kh) {
+ const int ih = oh * jcp.stride_h - jcp.t_pad
+ + kh * (1 + jcp.dilate_h);
+ if (ih < 0 || ih >= jcp.ih) continue;
+
+ for (int ow = 0; ow < jcp.ow; ++ow) {
+ for (int kw = 0; kw < jcp.kw; ++kw) {
+ const int iw = ow * jcp.stride_w - jcp.l_pad
+ + kw * (1 + jcp.dilate_w);
+ if (iw < 0 || iw >= jcp.iw) continue;
+
+ const size_t col_idx = ((kh*jcp.kw + kw)*jcp.oh+oh)*jcp.ow+ow;
+ const size_t im_idx = ih*jcp.iw + iw;
+ im_[im_idx] += col_[col_idx];
+ }}
+ }}
+
+ col_ += jcp.kh * jcp.kw * jcp.os;
+ id += (1 + jcp.dilate_d);
+ }
+ });
+}
+
+void col2im(const jit_gemm_conv_conf_t &jcp, const float *col, float *im) {
+ const size_t col_step = jcp.ks * jcp.os;
+ const size_t im_step = jcp.ih * jcp.iw;
+ const int iS = jcp.ih * jcp.iw;
+
+ parallel_nd(jcp.ic, [&](int ic) {
+ float *__restrict im_ = im + ic * im_step;
+ const float *__restrict col_ = col + ic * col_step;
+ PRAGMA_OMP_SIMD()
+ for (int is = 0; is < iS; ++is) im_[is] = 0.;
+
+ for (int kh = 0; kh < jcp.kh; ++kh) {
+ for (int oh = 0; oh < jcp.oh; ++oh) {
+ const int ih =
+ oh * jcp.stride_h - jcp.t_pad + kh * (1 + jcp.dilate_h);
+ if (ih < 0 || ih >= jcp.ih) continue;
+
+ for (int kw = 0; kw < jcp.kw; ++kw) {
+ for (int ow = 0; ow < jcp.ow; ++ow) {
+ const int iw =
+ ow * jcp.stride_w - jcp.l_pad + kw * (1 + jcp.dilate_w);
+ if (iw < 0 || iw >= jcp.iw) continue;
+
+ const size_t col_idx = ((kh*jcp.kw + kw)*jcp.oh+oh)*jcp.ow+ow;
+ const size_t im_idx = ih*jcp.iw + iw;
+ im_[im_idx] += col_[col_idx];
+ }
+ }
+ }
+ }
+ });
+}
+
+status_t init_conf(jit_gemm_conv_conf_t &jcp,
+ memory_tracking::registrar_t &scratchpad, const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d, int max_threads) {
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ const int ndims = src_d.ndims();
+ const int is_1d = ndims == 3;
+ const int is_3d = ndims == 5;
+
+ jcp.prop_kind = cd.prop_kind;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.id = is_3d ? src_d.dims()[2] : 1;
+ jcp.ih = is_1d ? 1 : src_d.dims()[ndims - 2];
+ jcp.iw = src_d.dims()[ndims - 1];
+ jcp.od = is_3d ? dst_d.dims()[2] : 1;
+ jcp.oh = is_1d ? 1 : dst_d.dims()[ndims - 2];
+ jcp.ow = dst_d.dims()[ndims - 1];
+
+ jcp.kd = is_3d ? weights_d.dims()[with_groups + 2] : 1;
+ jcp.kh = is_1d ? 1 : weights_d.dims()[with_groups + ndims - 2];
+ jcp.kw = weights_d.dims()[with_groups + ndims - 1];
+
+ jcp.f_pad = is_3d ? cd.padding[0][0] : 0;
+ jcp.t_pad = is_1d ? 0 : cd.padding[0][ndims - 4];
+ jcp.l_pad = cd.padding[0][ndims - 3];
+
+ jcp.stride_d = is_3d ? cd.strides[0] : 1;
+ jcp.stride_h = is_1d ? 1 : cd.strides[ndims - 4];
+ jcp.stride_w = cd.strides[ndims - 3];
+
+ jcp.dilate_d = is_3d ? cd.dilates[0] : 0;
+ jcp.dilate_h = is_1d ? 0 : cd.dilates[ndims - 4];
+ jcp.dilate_w = cd.dilates[ndims - 3];
+
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef
+ || cd.diff_bias_desc.format_kind != format_kind::undef;
+
+ jcp.is = jcp.ih * jcp.iw;
+ jcp.os = jcp.oh * jcp.ow;
+ jcp.ks = jcp.kh * jcp.kw * jcp.kd;
+
+ jcp.signed_input = src_d.data_type() == data_type::s8;
+
+ jcp.im2col_sz = !everyone_is(true,
+ jcp.ow == jcp.iw, jcp.oh == jcp.ih, jcp.od == jcp.id,
+ jcp.stride_w == 1, jcp.stride_h == 1, jcp.stride_d == 1,
+ jcp.ks == 1, !jcp.signed_input)
+ ? (ptrdiff_t)jcp.ic * jcp.ks * jcp.os : 0;
+
+ jcp.outer_threading = false;
+
+ bool is_int8_conv = utils::one_of(src_d.data_type(), s32, s8, u8)
+ && weights_d.data_type() == s8;
+
+ const int vlen = mayiuse(avx512_common)
+ ? cpu_isa_traits<avx512_common>::vlen
+ : mayiuse(avx)
+ ? cpu_isa_traits<avx>::vlen
+ : mayiuse(sse42) ? cpu_isa_traits<sse42>::vlen : 4;
+ const int simd_w = vlen / (is_int8_conv ? 1 : 4);
+
+ const bool is_bwd_d = jcp.prop_kind == backward_data;
+ const bool is_bwd_w = jcp.prop_kind == backward_weights;
+ const bool is_fwd = !is_bwd_d && !is_bwd_w;
+ jcp.oh_block = is_fwd ? jcp.oh : jcp.ih;
+ jcp.ow_block = is_fwd ? jcp.ow : jcp.iw;
+
+ using namespace memory_tracking::names;
+ bool is_depthwise = jcp.ic == 1 && jcp.oc == 1 && jcp.ngroups != 1;
+
+ // TODO: maybe mitigate blocking restriction
+ const int wei_size = jcp.oc * jcp.ic * jcp.kh * jcp.kw;
+ const int L2 = get_cache_size(2, true)
+ / (is_int8_conv ? sizeof(int8_t) : sizeof(float));
+ bool is_blocking_applicable = true
+ && is_fwd && jcp.im2col_sz
+ && jcp.id == 1 && jcp.od == 1
+ && jcp.dilate_h == 0 && jcp.dilate_w == 0
+ && !is_depthwise
+ && wei_size < L2/2;
+ if (is_blocking_applicable) {
+ // looking for oh and ow blocking
+ int h_block{ jcp.oh_block }, w_block{ jcp.ow_block };
+ const int ic = jcp.ic;
+ const int oc = jcp.oc;
+ const int iw = jcp.iw;
+ const int ow = jcp.ow;
+ const int oh = jcp.oh;
+ const int os = oh * ow;
+
+ // 1. cache requirement
+ int row_size = ic * ow * jcp.ks + 2 * (ic * iw + oc * ow);
+ if (is_int8_conv) {
+ // Heuristic rule: gemm needed a lot of memory for internal usage
+ row_size *= 5;
+ // memory for accumulators
+ row_size += oc * ow * sizeof(uint32_t);
+ // memory for transposition
+ row_size += ic * iw;
+ }
+
+ h_block = nstl::max(1, nstl::min(oh, div_up(L2, row_size)));
+ if (h_block == 1) {
+ int col_size = ic * jcp.ks + 2 * (ic + oc);
+ if (is_int8_conv) {
+ col_size *= 5;
+ col_size += oc * sizeof(uint32_t);
+ col_size += ic;
+ }
+ w_block = nstl::max(1, nstl::min(ow, div_up(L2, col_size)));
+ }
+
+ // 2. threading requirement
+ if (h_block != oh)
+ h_block = nstl::max(1, rnd_dn(h_block, 4));
+ if (w_block != ow)
+ w_block = nstl::max(1, rnd_dn(w_block, simd_w));
+
+ float thr_eff = 0.f;
+ float thr_eff_treshold = 0.9f;
+ if (w_block == ow) {
+ do {
+ int nb_h = div_up(oh, h_block);
+ size_t work = jcp.ngroups * jcp.mb * jcp.od * nb_h;
+ float disb = (float)oh / rnd_up(oh, h_block);
+ thr_eff = (float)work / rnd_up(work, max_threads);
+ thr_eff = (thr_eff + disb) / 2.f;
+ if (thr_eff >= thr_eff_treshold)
+ break;
+ h_block = rnd_dn(h_block - 4, 4);
+ } while (h_block > 0);
+ }
+ if (thr_eff < thr_eff_treshold) // we didn't find suitable h_block
+ {
+ h_block = 1;
+ int nb_h = oh;
+ do {
+ int nb_w = div_up(ow, w_block);
+ size_t work_amount = jcp.ngroups * jcp.mb * nb_h * nb_w;
+ float disb = (float)ow / rnd_up(ow, w_block);
+ thr_eff = (float)work_amount / rnd_up(work_amount, max_threads);
+ thr_eff = (thr_eff + disb) / 2.f;
+ if (thr_eff > thr_eff_treshold)
+ break;
+ w_block = rnd_dn(w_block - simd_w, simd_w);
+ } while (w_block > 0);
+ }
+ h_block = nstl::max(1, h_block);
+ w_block = nstl::max(1, w_block);
+ const size_t inner_work = div_up(os, simd_w) * div_up(oc, simd_w);
+ const float inner_thr_eff
+ = (float)inner_work / rnd_up(inner_work, max_threads);
+ if (thr_eff >= inner_thr_eff / 2 && h_block > 0 && w_block > 0) {
+ jcp.oh_block = h_block;
+ jcp.ow_block = w_block;
+ jcp.outer_threading = true;
+ }
+ // updating jcp.im2col_sz
+ if (jcp.oh_block != 1)
+ jcp.ow_block = ow;
+ jcp.im2col_sz = (ptrdiff_t)ic * jcp.ks * jcp.oh_block * jcp.ow_block;
+ }
+ // For threading selection in bwd_d we do:
+ // 1. Rough estimation of efficiency for inner and outer threading.
+ // 2. Gemm size estimation in assumption that it does not work
+ // so effectively for small sizes.
+ // 64K - this is heuristic gemm size per thread threshold.
+ const int gemm_thrld = 64 * 1024;
+
+ if (is_int8_conv) {
+ if (is_fwd) {
+ if (!jcp.outer_threading) {
+ bool is_depthwise = jcp.ic == 1 && jcp.oc == 1 && jcp.ngroups != 1;
+ const size_t outer_work = jcp.ngroups * jcp.mb;
+ const float outer_thr_eff
+ = (float)outer_work / rnd_up(outer_work, max_threads);
+ const size_t inner_work
+ = div_up(jcp.is, simd_w) * div_up(jcp.ic, simd_w);
+ const float inner_thr_eff
+ = (float)inner_work / rnd_up(inner_work, max_threads);
+ jcp.outer_threading = (is_depthwise
+ || (jcp.is / max_threads < 64 && jcp.mb != 1))
+ && (outer_thr_eff / inner_thr_eff >= 1.f
+ || (jcp.os * jcp.ic * jcp.oc) / max_threads < gemm_thrld);
+ }
+ jcp.nthr = jcp.outer_threading ? max_threads : 1;
+ scratchpad.book(key_conv_gemm_col,
+ sizeof(int8_t) * jcp.nthr * jcp.im2col_sz);
+ scratchpad.book(key_conv_int_dat_in_acc_dt,
+ sizeof(int32_t) * jcp.nthr * jcp.oh_block * jcp.ow_block * jcp.oc);
+ scratchpad.book(key_conv_gemm_imtr,
+ sizeof(int8_t) * jcp.nthr * jcp.is * jcp.ic);
+ } else if (is_bwd_d) {
+ bool is_depthwise = jcp.ic == 1 && jcp.oc == 1 && jcp.ngroups != 1;
+ const size_t outer_work = jcp.ngroups * jcp.mb;
+ const float outer_thr_eff
+ = (float)outer_work / rnd_up(outer_work, max_threads);
+ const size_t inner_work
+ = div_up(jcp.is, simd_w) * div_up(jcp.ic, simd_w);
+ const float inner_thr_eff
+ = (float)inner_work / rnd_up(inner_work, max_threads);
+ jcp.outer_threading = (is_depthwise
+ || (jcp.is / max_threads < 64 && jcp.mb != 1))
+ && (outer_thr_eff / inner_thr_eff >= 1.f
+ || (jcp.is * jcp.ic * jcp.oc) / max_threads < gemm_thrld);
+
+ jcp.nthr = jcp.outer_threading ? max_threads : 1;
+ scratchpad.book(key_conv_gemm_col,
+ sizeof(int32_t) * jcp.nthr * jcp.im2col_sz);
+ scratchpad.book(key_conv_int_dat_in_acc_dt,
+ sizeof(int32_t) * jcp.nthr * jcp.is * jcp.ic);
+ } else if (is_bwd_w) {
+ assert(!"unimplemented prop_kind");
+ return status::unimplemented;
+ }
+ } else {
+ if (is_fwd) {
+ if (!jcp.outer_threading) {
+ const size_t outer_work_amount = jcp.ngroups * jcp.mb * jcp.od;
+ const float outer_thr_eff = (float)outer_work_amount
+ / rnd_up(outer_work_amount, max_threads);
+ const size_t inner_work_amount
+ = div_up(jcp.os, simd_w) * div_up(jcp.oc, simd_w);
+ const float inner_thr_eff = (float)inner_work_amount
+ / rnd_up(inner_work_amount, max_threads);
+ jcp.outer_threading = jcp.os / max_threads < 512
+ && IMPLICATION(jcp.od == 1, jcp.mb != 1 || jcp.ngroups > 2)
+ && (outer_thr_eff / inner_thr_eff >= 1.f
+ || (jcp.os * jcp.ic * jcp.oc) / max_threads < gemm_thrld);
+ }
+ } else if (is_bwd_d) {
+ const size_t outer_work_amount = jcp.ngroups * jcp.mb;
+ const float outer_thr_eff = (float)outer_work_amount
+ / rnd_up(outer_work_amount, max_threads);
+ const size_t inner_work
+ = div_up(jcp.is, simd_w) * div_up(jcp.ic, simd_w);
+ const float inner_thr_eff = (float)inner_work
+ / rnd_up(inner_work, max_threads);
+ jcp.outer_threading = (jcp.os / max_threads < 512 || jcp.ks < 64)
+ && (jcp.mb != 1 || jcp.ngroups > 2)
+ && (outer_thr_eff / inner_thr_eff >= 1.f
+ || (jcp.is * jcp.ic * jcp.oc) / max_threads < gemm_thrld);
+ } else if (is_bwd_w)
+ jcp.outer_threading = jcp.os / max_threads < 256
+ && (jcp.mb != 1 || jcp.ngroups > 2);
+
+ jcp.nthr = jcp.outer_threading ? max_threads : 1;
+ scratchpad.book(key_conv_gemm_col,
+ sizeof(float) * jcp.nthr * jcp.im2col_sz);
+
+ if (is_bwd_w) {
+ jcp.need_wei_reduction = mkldnn_thr_syncable()
+ ? jcp.mb != 1 && jcp.nthr != 1 : false;
+ scratchpad.book(key_conv_wei_reduction,
+ sizeof(float) * jcp.nthr * jcp.ngroups * weights_d.size());
+ }
+ }
+
+ return status::success;
+}
+
+void bwd_weights_balance(int ithr, int nthr, int ngroups, int mb, int &ithr_g,
+ int &nthr_g, int &ithr_mb, int &nthr_mb) {
+ nthr_g = nstl::min(ngroups, nthr);
+ nthr_mb = nstl::min(mb, nthr / nthr_g);
+ if (ithr / nthr_mb >= ngroups) {
+ ithr_g = ithr_mb = -1;
+ } else {
+ ithr_g = ithr / nthr_mb;
+ ithr_mb = ithr % nthr_mb;
+ }
+}
+
+void bwd_weights_reduction_par(int ithr, int nthr,
+ const jit_gemm_conv_conf_t &jcp, const float *weights_reduce_ws,
+ float *weights) {
+ const size_t weights_g_size = jcp.ic * jcp.oc * jcp.ks;
+
+ size_t weights_start{0}, weights_end{0};
+ balance211(weights_g_size, nthr, ithr, weights_start, weights_end);
+
+ for (int i = 0; i < nthr; ++i) {
+ const float *ws_i = weights_reduce_ws + i * weights_g_size;
+ for (size_t s = weights_start; s < weights_end; ++s)
+ weights[s] = (i == 0 ? 0 : weights[s]) + ws_i[s];
+ }
+}
+
+};
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.hpp
new file mode 100644
index 0000000000..e006789344
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_convolution_utils.hpp
@@ -0,0 +1,66 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_GEMM_CONVOLUTION_UTILS_HPP
+#define CPU_JIT_GEMM_CONVOLUTION_UTILS_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_engine.hpp"
+#include "jit_primitive_conf.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace jit_gemm_convolution_utils {
+
+void im2col_3d(const jit_gemm_conv_conf_t &jcp, const float *im, float *col,
+ int od);
+void im2col(const jit_gemm_conv_conf_t &jcp, const float *__restrict im,
+ float *__restrict col, int hs, int hb, int ws, int wb);
+template <typename T>
+void im2col_u8(const jit_gemm_conv_conf_t &jcp, const T *__restrict im,
+ T* __restrict imtr, uint8_t *__restrict col,
+ int hs, int hb, int ws, int wb);
+
+void col2im_s32(const jit_gemm_conv_conf_t &jcp, const int32_t *__restrict col,
+ int32_t *__restrict im);
+void col2im_3d(const jit_gemm_conv_conf_t &jcp, const float *col, float *im,
+ int od);
+void col2im(const jit_gemm_conv_conf_t &jcp, const float *col, float *im);
+
+status_t init_conf(jit_gemm_conv_conf_t &jcp,
+ memory_tracking::registrar_t &scratchpad, const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d, int max_threads);
+
+void bwd_weights_balance(int ithr, int nthr, int ngroups, int mb,
+ int &ithr_g, int &nthr_g, int &ithr_mb, int &nthr_mb);
+void bwd_weights_reduction_par(int ithr, int nthr,
+ const jit_gemm_conv_conf_t &jcp, const float *weights_reduce_ws,
+ float *weights);
+
+}
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.cpp
new file mode 100644
index 0000000000..2872122f0d
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.cpp
@@ -0,0 +1,156 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "gemm_inner_product.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::data_type;
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::primitive_kind;
+
+template <impl::data_type_t data_type>
+void gemm_inner_product_fwd_t<data_type>::execute_forward(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const int MB = pd()->MB();
+ const int OC = pd()->OC();
+ const int IC = pd()->IC_total_padded();
+
+ bool wei_tr = !memory_desc_matches_one_of_tag(
+ *pd()->weights_md(), hwio, dhwio, io);
+
+ const auto &post_ops = pd()->attr()->post_ops_;
+ const bool do_relu = post_ops.len_ == 1;
+
+ float alpha = 1.0, beta = 0.0;
+ extended_sgemm(wei_tr ? "T" : "N", "N", &OC, &MB, &IC, &alpha, weights,
+ wei_tr ? &IC : &OC, src, &IC, &beta, dst, &OC, bias);
+
+ if (do_relu) {
+ float nslope = post_ops.entry_[0].eltwise.alpha;
+ parallel_nd(MB, OC, [&](int mb, int oc) {
+ size_t dst_off = mb * OC + oc;
+ if (dst[dst_off] < 0)
+ dst[dst_off] *= nslope;
+ });
+ }
+}
+
+template <impl::data_type_t data_type>
+void gemm_inner_product_bwd_data_t<data_type>::execute_backward_data(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const int MB = pd()->MB();
+ const int OC = pd()->OC();
+ const int IC = pd()->IC_total_padded();
+
+ bool wei_tr = memory_desc_matches_one_of_tag(
+ *pd()->weights_md(), hwio, dhwio, io);
+
+ float alpha = 1.0, beta = 0.0;
+ extended_sgemm(wei_tr ? "T" : "N", "N", &IC, &MB, &OC, &alpha, weights,
+ wei_tr ? &OC : &IC, diff_dst, &OC, &beta, diff_src, &IC);
+}
+
+template <impl::data_type_t data_type>
+void gemm_inner_product_bwd_weights_t<data_type>::execute_backward_weights(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS);
+ auto diff_bias = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_bias_d(pd()->diff_weights_md(1));
+
+ diff_dst += diff_dst_d.offset0();
+
+ const int MB = pd()->MB();
+ const int OC = pd()->OC();
+ const int IC = pd()->IC_total_padded();
+
+ bool wei_tr = memory_desc_matches_one_of_tag(
+ *pd()->diff_weights_md(), hwio, dhwio, io);
+
+ float alpha = 1.0, beta = 0.0;
+ if (wei_tr)
+ extended_sgemm("N", "T", &OC, &IC, &MB, &alpha, diff_dst, &OC, src, &IC,
+ &beta, diff_weights, &OC);
+ else
+ extended_sgemm("N", "T", &IC, &OC, &MB, &alpha, src, &IC, diff_dst, &OC,
+ &beta, diff_weights, &IC);
+
+ if (diff_bias) {
+ diff_bias += diff_bias_d.offset0();
+ constexpr int blksize = 8;
+ const int OC_blocks = OC / blksize;
+ const int rem_OC = OC % blksize;
+ parallel(0, [&](const int ithr, const int nthr) {
+ int oc_st{0}, oc_e{0};
+ balance211(OC_blocks, nthr, ithr, oc_st, oc_e);
+ oc_st = oc_st * blksize;
+ oc_e = oc_e * blksize;
+
+ PRAGMA_OMP_SIMD()
+ for (int oc = oc_st; oc < oc_e; ++oc) {
+ diff_bias[oc] = diff_dst[oc];
+ }
+
+ for (int mb = 1; mb < MB; ++mb) {
+ PRAGMA_OMP_SIMD()
+ for (int oc = oc_st; oc < oc_e; ++oc) {
+ diff_bias[oc] += diff_dst[mb * OC + oc];
+ }
+ }
+
+ if (rem_OC != 0 && ithr == nthr-1) {
+ for (int oc = OC_blocks * blksize; oc < OC; oc++)
+ diff_bias[oc] = diff_dst[oc];
+ for (int mb = 1; mb < MB; ++mb) {
+ for (int oc = OC_blocks * blksize; oc < OC; oc++) {
+ diff_bias[oc] += diff_dst[mb * OC + oc];
+ }
+ }
+ }
+ });
+ }
+}
+
+template struct gemm_inner_product_fwd_t<data_type::f32>;
+template struct gemm_inner_product_bwd_data_t<data_type::f32>;
+template struct gemm_inner_product_bwd_weights_t<data_type::f32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.hpp
new file mode 100644
index 0000000000..acf0a49b9a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_inner_product.hpp
@@ -0,0 +1,157 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_GEMM_INNER_PRODUCT_HPP
+#define CPU_GEMM_INNER_PRODUCT_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "gemm/gemm.hpp"
+
+#include "cpu_inner_product_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t data_type>
+struct gemm_inner_product_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_inner_product_fwd_pd_t {
+ using cpu_inner_product_fwd_pd_t::cpu_inner_product_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_inner_product_fwd_t);
+
+ status_t init() {
+ using namespace utils;
+
+ bool ok = true
+ && set_default_params() == status::success
+ && is_fwd()
+ && !has_zero_dim_memory()
+ && everyone_is(data_type,
+ src_md()->data_type,
+ weights_md()->data_type,
+ dst_md()->data_type,
+ with_bias() ? weights_md(1)->data_type : data_type)
+ && attr()->output_scales_.has_default_values()
+ && attr()->post_ops_.len_ <= 1
+ && IMPLICATION(attr()->post_ops_.len_ == 1,
+ attr()->post_ops_.entry_[0].is_relu(true, false))
+ && dense_gemm_consitency_check(src_md(), weights_md(),
+ dst_md());
+ return ok ? status::success : status::unimplemented;
+ }
+ };
+
+ gemm_inner_product_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t data_type>
+struct gemm_inner_product_bwd_data_t: public cpu_primitive_t {
+ struct pd_t: public cpu_inner_product_bwd_data_pd_t {
+ using cpu_inner_product_bwd_data_pd_t::cpu_inner_product_bwd_data_pd_t;
+
+ DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_inner_product_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && set_default_params() == status::success
+ && desc()->prop_kind == prop_kind::backward_data
+ && !has_zero_dim_memory()
+ && utils::everyone_is(data_type,
+ diff_src_md()->data_type,
+ weights_md()->data_type,
+ diff_dst_md()->data_type)
+ && attr()->has_default_values()
+ && dense_gemm_consitency_check(diff_src_md(), weights_md(),
+ diff_dst_md());
+ return ok ? status::success : status::unimplemented;
+ }
+ };
+
+ gemm_inner_product_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_data(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_data(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t data_type>
+struct gemm_inner_product_bwd_weights_t: public cpu_primitive_t {
+ struct pd_t: public cpu_inner_product_bwd_weights_pd_t {
+ using cpu_inner_product_bwd_weights_pd_t::cpu_inner_product_bwd_weights_pd_t;
+
+ DECLARE_COMMON_PD_T(GEMM_IMPL_STR, gemm_inner_product_bwd_weights_t);
+
+ status_t init() {
+ bool ok = true
+ && set_default_params() == status::success
+ && desc()->prop_kind == prop_kind::backward_weights
+ && !has_zero_dim_memory()
+ && utils::everyone_is(data_type,
+ src_md()->data_type,
+ diff_weights_md()->data_type,
+ diff_dst_md()->data_type,
+ with_bias() ? diff_weights_md(1)->data_type : data_type)
+ && attr()->has_default_values()
+ && dense_gemm_consitency_check(src_md(), diff_weights_md(),
+ diff_dst_md());
+
+ return ok ? status::success : status::unimplemented;
+ }
+ };
+
+ gemm_inner_product_bwd_weights_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_weights(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_weights(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.cpp
new file mode 100644
index 0000000000..fed7e4d693
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.cpp
@@ -0,0 +1,740 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "utils.hpp"
+#include "type_helpers.hpp"
+#include "mkldnn_thread.hpp"
+#include "math_utils.hpp"
+
+#include "simple_q10n.hpp"
+
+#include "gemm/gemm.hpp"
+#include "gemm_x8s8s32x_convolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::math;
+using namespace mkldnn::impl::memory_tracking::names;
+
+template <data_type_t src_type, data_type_t dst_type>
+void _gemm_x8s8s32x_convolution_fwd_t<src_type, dst_type>::
+execute_forward(const exec_ctx_t &ctx) const {
+ auto src_base = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto wei_base = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bia_base = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst_base = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_;
+
+ assert(IMPLICATION(
+ jcp.id != 1, jcp.oh_block == jcp.oh && jcp.ow_block == jcp.ow));
+ assert(IMPLICATION(jcp.ow_block != jcp.ow, jcp.oh_block == 1));
+
+ parallel(jcp.nthr, [&](const int ithr, const int nthr) {
+ execute_forward_thr(ithr, nthr, src_base, wei_base, bia_base, dst_base,
+ scratchpad);
+ });
+}
+
+template <data_type_t src_type, data_type_t dst_type>
+_gemm_x8s8s32x_convolution_fwd_t<src_type, dst_type>::pp_ker_t::pp_ker_t(
+ const pd_t *pd)
+ : ker_(nullptr)
+ , jcp_(pd->jcp_)
+ , OC_(pd->jcp_.oc)
+ , OS_(pd->jcp_.os)
+ , bias_data_type_(data_type::undef)
+ , bias_data_type_size_(0)
+ , scale_idx_mult_(0)
+ , do_bias_(false)
+ , do_relu_(false)
+ , do_sum_(false)
+{
+ using namespace types;
+
+ const auto dst_md = memory_desc_wrapper(pd->dst_md());
+ dst_os_stride_ = dst_md.blk_off(0, 0, 0, 1);
+
+ scale_idx_mult_ = (pd->attr()->output_scales_.mask_ == (1 << 1));
+
+ auto &post_ops = pd->attr()->post_ops_;
+
+ int entry_idx = -1;
+ for (int idx = 0; idx < post_ops.len_; ++idx) {
+ const auto &e = post_ops.entry_[idx];
+ if (e.is_relu(true, false)) {
+ entry_idx = idx;
+ break;
+ }
+ }
+ do_relu_ = entry_idx >= 0;
+
+ do_signed_scaling_ = jcp_.signed_input;
+
+ do_sum_ = post_ops.contain(primitive_kind::sum, 0);
+ do_bias_ = pd->with_bias();
+ bias_data_type_ = pd->desc()->bias_desc.data_type;
+ if (do_bias_) {
+ assert(bias_data_type_ != data_type::undef);
+ bias_data_type_size_ = data_type_size(bias_data_type_);
+ }
+ const size_t vlen_start
+ = cpu_isa_traits<avx512_common>::vlen / sizeof(float);
+
+ for (size_t i = vlen_start; i > 0; i--) {
+ if (OC_ % i == 0) {
+ vlen_ = i;
+ break;
+ }
+ }
+
+ if (!mayiuse(avx512_core))
+ // use fallback code for older CPUs
+ return;
+ else
+ generate();
+}
+
+template <data_type_t src_type, data_type_t dst_type>
+void _gemm_x8s8s32x_convolution_fwd_t<src_type, dst_type>::pp_ker_t::generate()
+{
+ using namespace Xbyak;
+ using namespace utils;
+
+ // TODO: clean-up
+ Reg64 reg_param = abi_param1;
+ Reg64 reg_dst = rdx;
+ Reg64 reg_acc = rax;
+ Reg64 reg_bias = rbx;
+ Reg64 reg_scales = rsi;
+
+ Reg64 reg_len = r8;
+ Reg64 reg_tmp = rcx; // intentional for shifting purposes
+ Reg64 reg_oc_offset = r9;
+ Reg64 reg_rem_mask_short = r10;
+ Reg64 reg_rem_mask_vlen = r11;
+ Opmask kreg_rem_mask_short = k1;
+ Opmask kreg_rem_mask_vlen = k3;
+ Opmask kreg_relu_cmp = k2;
+
+ const size_t vlen = vlen_;
+
+ Zmm vreg_zero = Zmm(0);
+ Zmm vreg_scale = Zmm(1);
+ Zmm vreg_nslope = Zmm(2);
+ Zmm vreg_sum_scale = Zmm(3);
+ Zmm vreg_signed_scale = Zmm(4);
+
+ size_t def_unroll = 4;
+ size_t max_unroll = 12;
+ size_t zmm_step = 2;
+ if (do_sum_) {
+ max_unroll = 8;
+ zmm_step = 3;
+ }
+
+ auto vreg_dst = [&](int idx) {
+ return Zmm(5 + idx * zmm_step + 0);
+ };
+ auto vreg_bias = [&](int idx) {
+ return Zmm(5 + idx * zmm_step + 1);
+ };
+ auto vreg_prev_dst = [&](int idx) {
+ return Zmm(5 + idx * zmm_step + 2);
+ };
+
+ preamble();
+
+#define PARAM_OFF(x) offsetof(ker_args, x)
+ mov(reg_dst, ptr[reg_param + PARAM_OFF(dst)]);
+ mov(reg_acc, ptr[reg_param + PARAM_OFF(acc)]);
+ mov(reg_bias, ptr[reg_param + PARAM_OFF(bias)]);
+ mov(reg_scales, ptr[reg_param + PARAM_OFF(scales)]);
+ mov(reg_len, ptr[reg_param + PARAM_OFF(len)]);
+ mov(reg_oc_offset, ptr[reg_param + PARAM_OFF(oc_offset)]);
+ vbroadcastss(vreg_nslope, ptr[reg_param + PARAM_OFF(nslope)]);
+ vbroadcastss(vreg_sum_scale, ptr[reg_param + PARAM_OFF(sum_scale)]);
+ vbroadcastss(vreg_signed_scale, ptr[reg_param + PARAM_OFF(signed_scale)]);
+ if (scale_idx_mult_ == 0)
+ vbroadcastss(vreg_scale, dword[reg_scales]);
+
+#undef PARAM_OFF
+
+ mov(reg_rem_mask_vlen, 1);
+ shl(reg_rem_mask_vlen, vlen);
+ sub(reg_rem_mask_vlen, 1);
+ kmovq(kreg_rem_mask_vlen, reg_rem_mask_vlen);
+
+ if (do_relu_ || dst_type == data_type::u8)
+ vxorps(vreg_zero, vreg_zero, vreg_zero);
+
+ // Load accumulated value, convert to float, apply sum (if any),
+ // bias (if any), scaling, and relu (if any);
+ // then convert to destination type and store
+ auto compute = [&](size_t offset, int idx, bool apply_mask) {
+ auto acc_addr = ptr[reg_acc + offset * sizeof(acc_data_t)];
+
+ if (scale_idx_mult_ > 0) {
+ assert(scale_idx_mult_ == 1);
+ auto scale_addr = ptr[reg_scales + offset * sizeof(float)];
+ auto vreg_scale_ = vreg_scale;
+ if (apply_mask)
+ vreg_scale_ = vreg_scale_ | kreg_rem_mask_short;
+ else
+ vreg_scale_ = vreg_scale_ | kreg_rem_mask_vlen;
+ vmovups(vreg_scale_, scale_addr);
+ }
+
+ auto vreg_dst_ = vreg_dst(idx);
+ if (apply_mask)
+ vreg_dst_ = vreg_dst_ | kreg_rem_mask_short;
+ else
+ vreg_dst_ = vreg_dst_ | kreg_rem_mask_vlen;
+ vcvtdq2ps(vreg_dst_, acc_addr);
+
+ if (do_signed_scaling_)
+ vmulps(vreg_dst(idx), vreg_dst(idx), vreg_signed_scale);
+
+ if (do_bias_) {
+ auto bias_addr = ptr[reg_bias + offset * bias_data_type_size_];
+ auto vreg_bias_ = vreg_bias(idx);
+ if (apply_mask)
+ vreg_bias_ = vreg_bias_ | kreg_rem_mask_short;
+ else
+ vreg_bias_ = vreg_bias_ | kreg_rem_mask_vlen;
+
+ switch (bias_data_type_) {
+ case data_type::s8:
+ vpmovsxbd(vreg_bias_, bias_addr);
+ break;
+ case data_type::u8:
+ vpmovzxbd(vreg_bias_, bias_addr);
+ break;
+ case data_type::s32:
+ case data_type::f32:
+ vmovups(vreg_bias_, bias_addr);
+ break;
+ default: assert(!"unimplemented");
+ }
+ if (bias_data_type_ != data_type::f32)
+ vcvtdq2ps(vreg_bias(idx), vreg_bias(idx));
+ vaddps(vreg_dst(idx), vreg_dst(idx), vreg_bias(idx));
+ }
+
+ vmulps(vreg_dst(idx), vreg_dst(idx), vreg_scale);
+
+ auto dst_addr = ptr[reg_dst + offset * sizeof(dst_data_t)];
+
+ if (do_sum_)
+ {
+ auto vreg_prev_dst_ = vreg_prev_dst(idx);
+ if (apply_mask)
+ vreg_prev_dst_ = vreg_prev_dst_ | kreg_rem_mask_short;
+ else
+ vreg_prev_dst_ = vreg_prev_dst_ | kreg_rem_mask_vlen;
+
+ switch (dst_type) {
+ case data_type::f32:
+ case data_type::s32: vmovups(vreg_prev_dst_, dst_addr); break;
+ case data_type::s8: vpmovsxbd(vreg_prev_dst_, dst_addr); break;
+ case data_type::u8: vpmovzxbd(vreg_prev_dst_, dst_addr); break;
+ default: assert(!"unsupported data type");
+ }
+ if (dst_type != data_type::f32)
+ vcvtdq2ps(vreg_prev_dst(idx), vreg_prev_dst(idx));
+
+ vfmadd231ps(vreg_dst(idx), vreg_prev_dst(idx), vreg_sum_scale);
+ }
+
+ if (do_relu_) {
+ vcmpps(kreg_relu_cmp, vreg_dst(idx), vreg_zero, _cmp_lt_os);
+ vmulps(vreg_dst(idx) | kreg_relu_cmp, vreg_dst(idx), vreg_nslope);
+ }
+
+ if (dst_type != data_type::f32) {
+ vcvtps2dq(vreg_dst(idx), vreg_dst(idx));
+ }
+
+ if (dst_type == data_type::u8)
+ vpmaxsd(vreg_dst(idx), vreg_dst(idx), vreg_zero);
+
+ switch (dst_type) {
+ case data_type::s8:
+ vpmovsdb(dst_addr, vreg_dst_);
+ break;
+ case data_type::u8:
+ vpmovusdb(dst_addr, vreg_dst_);
+ break;
+ case data_type::f32:
+ case data_type::s32:
+ vmovups(dst_addr, vreg_dst_);
+ break;
+ default: assert(!"unimplemented");
+ }
+ };
+
+ // Advance all pointers by an immediate
+ auto advance_ptrs_imm = [&](size_t offset) {
+ add(reg_dst, offset * sizeof(dst_data_t));
+ add(reg_acc, offset * sizeof(acc_data_t));
+ if (scale_idx_mult_) {
+ assert(scale_idx_mult_ == 1);
+ add(reg_scales, offset * sizeof(float));
+ }
+ if (do_bias_)
+ add(reg_bias, offset * bias_data_type_size_);
+ };
+
+ // Advance all pointers by a value stored in a register
+ auto advance_ptrs_reg = [&](Reg64 offset) {
+ lea(reg_dst, ptr[reg_dst + offset * sizeof(dst_data_t)]);
+ lea(reg_acc, ptr[reg_acc + offset * sizeof(acc_data_t)]);
+ if (scale_idx_mult_) {
+ assert(scale_idx_mult_ == 1);
+ lea(reg_scales, ptr[reg_scales + offset * sizeof(float)]);
+ }
+ if (do_bias_)
+ lea(reg_bias, ptr[reg_bias + offset * bias_data_type_size_]);
+ };
+
+ // Rewind pointers that point to data that is indexed by output channel
+ // (bias or per-oc scaling factors)
+ auto rewind_ptrs = [&]() {
+ if (do_bias_)
+ sub(reg_bias, OC_ * bias_data_type_size_);
+ if (scale_idx_mult_) {
+ assert(scale_idx_mult_ == 1);
+ sub(reg_scales, OC_ * sizeof(float));
+ }
+ add(reg_dst, (dst_os_stride_ - OC_) * sizeof(dst_data_t));
+ };
+
+ // <--------- OC --------------->
+ //
+ // ^ ................+..............+-------------+.......................
+ // | . : not accessed |Prologue loop| .
+ // | . +--------------+-------------+ .
+ // . | | .
+ // O . | Main loop (unrolled) | .
+ // S . | | .
+ // . +--------------+-------------+ .
+ // | . | Epilogue loop|not accessed : .
+ // v ................+--------------+.............+.......................
+
+ Label prologue_end;
+ cmp(reg_oc_offset, 0);
+ je(prologue_end, T_NEAR);
+
+ // Prologue loop
+ {
+ mov(reg_tmp, OC_);
+ sub(reg_tmp, reg_oc_offset);
+ cmp(reg_tmp, reg_len);
+ cmovg(reg_tmp, reg_len);
+ sub(reg_len, reg_tmp);
+
+ Label prologue_loop, prologue_loop_tail, prologue_loop_end;
+ cmp(reg_tmp, vlen);
+ jle(prologue_loop_tail, T_NEAR);
+ L(prologue_loop); {
+ compute(0, 0, false);
+ advance_ptrs_imm(vlen);
+ sub(reg_tmp, vlen);
+ cmp(reg_tmp, vlen);
+ jge(prologue_loop, T_NEAR);
+ }
+
+ L(prologue_loop_tail);
+ mov(reg_rem_mask_short, 1);
+ // cl == reg_tmp because reg_tmp <= vlen here
+ shl(reg_rem_mask_short, cl);
+ sub(reg_rem_mask_short, 1);
+ jz(prologue_loop_end, T_NEAR);
+
+ kmovq(kreg_rem_mask_short, reg_rem_mask_short);
+ compute(0, 0, true);
+ advance_ptrs_reg(reg_tmp);
+
+ L(prologue_loop_end);
+ rewind_ptrs();
+ }
+ L(prologue_end);
+
+ // Main loop
+ Label main_loop_end;
+ {
+ cmp(reg_len, OC_);
+ jle(main_loop_end, T_NEAR);
+
+ Label main_loop;
+ L(main_loop); {
+ size_t OC_loop, OC_tail;
+ if (OC_ < max_unroll * vlen) {
+ // Fully unroll small loops
+ OC_loop = 0;
+ OC_tail = OC_;
+ }
+ else {
+ OC_loop = vlen * def_unroll;
+ OC_tail = OC_ % OC_loop;
+ }
+
+ assert(!!OC_loop || !!OC_tail);
+
+ if (OC_tail % vlen) {
+ int vlen_tail = OC_tail % vlen;
+ unsigned tail_mask = (1 << vlen_tail) - 1;
+ mov(reg_tmp, tail_mask);
+ kmovq(kreg_rem_mask_short, reg_tmp);
+ }
+
+ if (OC_loop) {
+ mov(reg_tmp, rnd_dn(OC_, OC_loop));
+ Label oc_loop;
+ L(oc_loop); {
+ for (size_t offset = 0; offset < OC_loop; offset += vlen)
+ compute(offset, offset / vlen, false);
+ advance_ptrs_imm(OC_loop);
+ sub(reg_tmp, OC_loop);
+ jnz(oc_loop);
+ }
+ }
+
+ if (OC_tail) {
+ for (size_t offset = 0; offset < OC_tail; offset += vlen) {
+ bool use_mask = (offset + vlen) > OC_tail;
+ compute(offset, offset / vlen, use_mask);
+ }
+ advance_ptrs_imm(OC_tail);
+ }
+
+ rewind_ptrs();
+ sub(reg_len, OC_);
+ cmp(reg_len, OC_);
+ jge(main_loop, T_NEAR);
+ }
+ }
+ L(main_loop_end);
+
+ // Epilogue loop
+ Label epilogue_end;
+ {
+ cmp(reg_len, 0);
+ je(epilogue_end, T_NEAR);
+
+ Label epilogue_loop, epilogue_loop_tail;
+ cmp(reg_len, vlen);
+ jle(epilogue_loop_tail, T_NEAR);
+ L(epilogue_loop); {
+ compute(0, 0, false);
+ sub(reg_len, vlen);
+ advance_ptrs_imm(vlen);
+ cmp(reg_len, vlen);
+ jge(epilogue_loop, T_NEAR);
+ }
+
+ L(epilogue_loop_tail);
+ mov(reg_tmp, reg_len); // reg_tmp is rcx, and we need cl for the shift
+ mov(reg_rem_mask_short, 1);
+ shl(reg_rem_mask_short, cl); // reg_tmp == rcx and reg_tail < vlen
+ sub(reg_rem_mask_short, 1);
+ jz(epilogue_end, T_NEAR);
+ kmovq(kreg_rem_mask_short, reg_rem_mask_short);
+ compute(0, 0, true);
+ }
+
+ L(epilogue_end);
+
+ postamble();
+
+ ker_ = getCode<decltype(ker_)>();
+}
+
+template <data_type_t src_type, data_type_t dst_type>
+void _gemm_x8s8s32x_convolution_fwd_t<src_type, dst_type>::pp_ker_t::operator ()
+ (dst_data_t *dst, const acc_data_t *acc, const char *bias,
+ const float *scales, float nslope, float sum_scale, float signed_scale,
+ int g, size_t start, size_t end)
+{
+ using math::get_bias;
+
+ if (end <= start)
+ return;
+
+ if (ker_) {
+ // JIT
+ ker_args args;
+ size_t oc_offset = start % OC_;
+ size_t os_offset = start / OC_;
+ args.acc = acc + start;
+ args.dst = dst + os_offset * dst_os_stride_ + oc_offset;
+ args.bias = bias + (g * jcp_.oc + oc_offset) * bias_data_type_size_;
+ args.scales = scales + scale_idx_mult_ * (g * jcp_.oc + oc_offset);
+ args.nslope = nslope;
+ args.sum_scale = sum_scale;
+ args.signed_scale = signed_scale;
+ args.len = end - start;
+ args.oc_offset = oc_offset;
+ ker_(&args);
+ }
+ else {
+ // Fallback
+ const size_t first_oc = start % OC_;
+ const size_t last_oc = (end - 1) % OC_;
+ const size_t first_os = start / OC_;
+ const size_t last_os = (end - 1) / OC_;
+ for (size_t os = first_os; os <= last_os; os++) {
+ const size_t start_oc = (os == first_os) ? first_oc : 0;
+ const size_t end_oc = (os == last_os) ? last_oc : OC_ - 1;
+ for (size_t oc = start_oc; oc <= end_oc; oc++) {
+ const size_t acc_off = os * jcp_.oc + oc;
+ const size_t dst_off = os * dst_os_stride_ + oc;
+
+ float d = (float)(acc[acc_off]);
+ if (jcp_.signed_input)
+ d *= signed_scale;
+
+ if (do_bias_)
+ d += get_bias(bias, g * jcp_.oc + oc,
+ bias_data_type_);
+
+ d *= scales[(g * jcp_.oc + oc) * scale_idx_mult_];
+ if (do_sum_)
+ d += sum_scale * dst[dst_off];
+ if (do_relu_ && d < 0)
+ d *= nslope;
+ dst[dst_off] = qz_a1b0<float, dst_data_t>()(d);
+ }
+ }
+ }
+};
+
+template <data_type_t src_type, data_type_t dst_type>
+void _gemm_x8s8s32x_convolution_fwd_t<src_type, dst_type>::
+execute_forward_thr(const int ithr, const int nthr, const src_data_t *src_base,
+ const wei_data_t *wei_base, const char *bia_base, dst_data_t *dst_base,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_;
+
+ const auto src_md = memory_desc_wrapper(pd()->src_md());
+ const size_t src_mb_stride = src_md.blk_off(1);
+ const size_t src_g_stride = src_md.blk_off(0, 1) * jcp.ic;
+
+ const auto wei_md = memory_desc_wrapper(pd()->weights_md(0));
+ const size_t wei_g_stride = pd()->with_groups() ? wei_md.blk_off(1) : 0;
+
+ const auto dst_md = memory_desc_wrapper(pd()->dst_md());
+ const size_t dst_mb_stride = dst_md.blk_off(1);
+ const size_t dst_g_stride = dst_md.blk_off(0, 1) * jcp.oc;
+
+ const float *scales = pd()->attr()->output_scales_.scales_;
+
+ const auto &post_ops = pd()->attr()->post_ops_;
+ const bool do_sum = post_ops.contain(primitive_kind::sum, 0);
+ const float sum_scale = do_sum ? post_ops.entry_[0].sum.scale : 0;
+
+ float nslope = 0;
+ for (int idx = 0; idx < post_ops.len_; ++idx) {
+ const auto &e = post_ops.entry_[idx];
+ if (e.is_relu(true, false)) {
+ nslope = e.eltwise.alpha;
+ break;
+ }
+ }
+
+ auto col = scratchpad.get<uint8_t>(key_conv_gemm_col)
+ + (ptrdiff_t)ithr * jcp.im2col_sz;
+ src_data_t *__restrict imtr = scratchpad.get<src_data_t>(key_conv_gemm_imtr)
+ + (ptrdiff_t)ithr * jcp.is * jcp.ic;
+ auto acc = scratchpad.get<acc_data_t>(key_conv_int_dat_in_acc_dt)
+ + (ptrdiff_t)ithr * jcp.oh_block * jcp.ow_block * jcp.oc;
+
+ const ptrdiff_t offset = (ptrdiff_t)jcp.ngroups * jcp.ks * jcp.ic * jcp.oc;
+ const int32_t *_wei_comp = (const int32_t *)(wei_base + offset);
+
+ int g{ 0 }, n{ 0 }, ohb{ 0 }, owb{ 0 };
+ size_t start = 0, end = 0;
+
+ const int nb_oh = div_up(jcp.oh, jcp.oh_block);
+ const int nb_ow = div_up(jcp.ow, jcp.ow_block);
+ const size_t work_amount = jcp.ngroups * jcp.mb * nb_oh * nb_ow;
+ balance211(work_amount, nthr, ithr, start, end);
+ nd_iterator_init(start, n, jcp.mb, g, jcp.ngroups, ohb,
+ nb_oh, owb, nb_ow);
+
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ int oh = ohb * jcp.oh_block;
+ int ow = owb * jcp.ow_block;
+ const src_data_t *__restrict src = src_base + n * src_mb_stride
+ + g * src_g_stride;
+ const wei_data_t *__restrict wei = wei_base + g * wei_g_stride;
+ dst_data_t *__restrict dst =
+ dst_base + n * dst_mb_stride + g * dst_g_stride;
+ const int32_t *wei_comp = _wei_comp + g * jcp.oc;
+ const int h_step = nstl::min(jcp.oh_block, jcp.oh - oh);
+ const int w_step = nstl::min(jcp.ow_block, jcp.ow - ow);
+
+ if (jcp.im2col_sz)
+ jit_gemm_convolution_utils::im2col_u8<src_data_t>(
+ jcp, src, imtr, col, oh, h_step, ow, w_step);
+
+ const int M = jcp.oc;
+ const int K = jcp.ks * jcp.ic;
+ const int N = h_step * w_step;
+ const int LDA = M * jcp.ngroups;
+ const int LDB = jcp.im2col_sz ? N : K;
+ const char *BT = jcp.im2col_sz ? "T" : "N";
+ const int8_t off_a = 0, off_b = 0;
+ const int32_t off_c = 0;
+ const float onef = 1.0, zerof = 0.0;
+ gemm_s8x8s32("N", BT, jcp.signed_input ? "C" : "F",
+ &M, &N, &K, &onef, wei, &LDA, &off_a,
+ jcp.im2col_sz ? col : (uint8_t *)src, &LDB, &off_b,
+ &zerof, acc, &M, jcp.signed_input ? wei_comp : &off_c);
+
+ auto wei_adj_scale =
+ (wei_md.extra().flags | memory_extra_flags::scale_adjust)
+ ? wei_md.extra().scale_adjust : 1.f;
+
+ parallel(0, [&](int ithr, int nthr) {
+ size_t start, end;
+ balance211((size_t)N * jcp.oc, nthr, ithr, start, end);
+ (*pp_ker_)(dst + (oh * jcp.ow + ow) * pp_ker_->dst_os_stride_,
+ acc, bia_base, scales, nslope, sum_scale,
+ 1.f / wei_adj_scale, g, start, end);
+ });
+
+ nd_iterator_step(n, jcp.mb, g, jcp.ngroups, ohb, nb_oh,
+ owb, nb_ow);
+ }
+}
+
+template <data_type_t dst_type>
+void _gemm_u8s8s32x_convolution_bwd_data_t<dst_type>::
+execute_backward_data(const exec_ctx_t &ctx) const {
+ auto diff_dst_base = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST);
+ auto wei_base = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bia_base = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto diff_src_base = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_;
+
+ parallel(jcp.nthr, [&](const int ithr, const int nthr) {
+ execute_backward_data_thr(ithr, nthr, diff_dst_base, wei_base,
+ bia_base, diff_src_base, scratchpad);
+ });
+}
+
+template <data_type_t dst_type>
+void _gemm_u8s8s32x_convolution_bwd_data_t<dst_type>::
+execute_backward_data_thr(const int ithr, const int nthr,
+ const diff_dst_data_t *diff_dst_base, const wei_data_t *wei_base,
+ const char *bia_base, diff_src_data_t *diff_src_base,
+ const memory_tracking::grantor_t &scratchpad) const
+{
+ const jit_gemm_conv_conf_t &jcp = this->pd()->jcp_;
+
+ const auto diff_dst_md = memory_desc_wrapper(pd()->diff_dst_md());
+ const size_t diff_dst_mb_stride = diff_dst_md.blk_off(1);
+ const size_t diff_dst_g_stride = diff_dst_md.blk_off(0, 1) * jcp.oc;
+
+ const auto wei_md = memory_desc_wrapper(pd()->weights_md(0));
+ const size_t wei_g_stride = pd()->with_groups() ? wei_md.blk_off(1) : 0;
+
+ const auto diff_src_md = memory_desc_wrapper(pd()->diff_src_md());
+ const size_t diff_src_mb_stride = diff_src_md.blk_off(1);
+ const size_t diff_src_g_stride = diff_src_md.blk_off(0, 1) * jcp.ic;
+ const size_t diff_src_os_stride = diff_src_md.blk_off(0, 0, 0, 1);
+
+ /* scale_idx_mult = 1 for per_oc scales and 0, otherwise */
+ const int scale_idx_mult = pd()->attr()->output_scales_.mask_ == (1 << 1);
+ const float *scales = pd()->attr()->output_scales_.scales_;
+ const size_t work_amount = jcp.ngroups * jcp.mb;
+
+ auto col = scratchpad.get<acc_data_t>(key_conv_gemm_col)
+ + (ptrdiff_t)ithr * jcp.im2col_sz;
+ auto acc = scratchpad.get<acc_data_t>(key_conv_int_dat_in_acc_dt)
+ + (ptrdiff_t)ithr * jcp.is * jcp.ic;
+
+ int n{0}, g{0};
+ size_t start = 0, end = 0;
+
+ balance211(work_amount, nthr, ithr, start, end);
+ nd_iterator_init(start, n, jcp.mb, g, jcp.ngroups);
+
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ const diff_dst_data_t *diff_dst = diff_dst_base
+ + n * diff_dst_mb_stride + g * diff_dst_g_stride;
+ const wei_data_t *wei = wei_base + g * wei_g_stride;
+ diff_src_data_t *diff_src = diff_src_base + n * diff_src_mb_stride
+ + g * diff_src_g_stride;
+
+ const int M = jcp.ks * jcp.ic;
+ const int N = jcp.os;
+ const int K = jcp.oc;
+ const int8_t off_a = 0, off_b = 0;
+ const int32_t off_c = 0;
+ const float onef = 1.0, zerof = 0.0;
+ const int LD = K * jcp.ngroups;
+
+ gemm_s8x8s32("T", "N", "F", &M, &N, &K, &onef,
+ wei, &LD, &off_a, diff_dst, &LD, &off_b,
+ &zerof, jcp.im2col_sz ? col : acc, &M, &off_c);
+
+ if (jcp.im2col_sz)
+ jit_gemm_convolution_utils::col2im_s32(jcp, col, acc);
+
+ parallel_nd(jcp.is, jcp.ic, [&](int is, int ic) {
+ float d = (float)acc[is * jcp.ic + ic];
+ if (jcp.with_bias)
+ d += get_bias(bia_base, g * jcp.ic + ic,
+ pd()->desc()->bias_desc.data_type);
+ d *= scales[(g * jcp.ic + ic) * scale_idx_mult];
+ const size_t diff_src_off = is * diff_src_os_stride + ic;
+ diff_src[diff_src_off] =
+ qz_a1b0<float, diff_src_data_t>()(d);
+ });
+ nd_iterator_step(n, jcp.mb, g, jcp.ngroups);
+ }
+}
+
+using namespace data_type;
+
+template struct _gemm_x8s8s32x_convolution_fwd_t<u8, f32>;
+template struct _gemm_x8s8s32x_convolution_fwd_t<u8, s32>;
+template struct _gemm_x8s8s32x_convolution_fwd_t<u8, s8>;
+template struct _gemm_x8s8s32x_convolution_fwd_t<u8, u8>;
+
+template struct _gemm_x8s8s32x_convolution_fwd_t<s8, f32>;
+template struct _gemm_x8s8s32x_convolution_fwd_t<s8, s32>;
+template struct _gemm_x8s8s32x_convolution_fwd_t<s8, s8>;
+template struct _gemm_x8s8s32x_convolution_fwd_t<s8, u8>;
+
+template struct _gemm_u8s8s32x_convolution_bwd_data_t<f32>;
+template struct _gemm_u8s8s32x_convolution_bwd_data_t<s32>;
+template struct _gemm_u8s8s32x_convolution_bwd_data_t<s8>;
+template struct _gemm_u8s8s32x_convolution_bwd_data_t<u8>;
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.hpp
new file mode 100644
index 0000000000..9e77b890d5
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_convolution.hpp
@@ -0,0 +1,266 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef GEMM_X8S8S32X_CONVOLUTION_HPP
+#define GEMM_X8S8S32X_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_primitive_conf.hpp"
+#include "jit_generator.hpp"
+#include "gemm_convolution_utils.hpp"
+
+#include "gemm/gemm.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <data_type_t src_type, data_type_t dst_type>
+struct _gemm_x8s8s32x_convolution_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(IGEMM_S8U8S32_IMPL_STR,
+ _gemm_x8s8s32x_convolution_fwd_t<src_type, dst_type>);
+
+ status_t init() {
+ using namespace data_type;
+
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(src_type, s8, data_type::undef, dst_type,
+ s32)
+ && IMPLICATION(with_bias(), utils::one_of(
+ desc()->bias_desc.data_type, f32, s32, s8, u8))
+ && !has_zero_dim_memory()
+ && set_default_formats_common(
+ dat_tag(), format_tag::any, dat_tag())
+ && post_ops_ok()
+ && memory_desc_matches_tag(*src_md(), dat_tag())
+ && memory_desc_matches_tag(*dst_md(), dat_tag())
+ && set_or_check_wei_format();
+ if (!ok) return status::unimplemented;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ return jit_gemm_convolution_utils::init_conf(jcp_, scratchpad,
+ *desc(), src_md(), weights_md(0), dst_md(),
+ mkldnn_get_max_threads());
+ }
+
+ jit_gemm_conv_conf_t jcp_;
+
+ protected:
+ format_tag_t dat_tag() const { return format_tag::nhwc; }
+
+ bool set_or_check_wei_format() {
+ using namespace format_tag;
+
+ const bool is_src_s8 = src_md_.data_type == data_type::s8;
+
+ memory_desc_t want_wei_md = weights_md_;
+ memory_desc_init_by_tag(want_wei_md, with_groups() ? hwigo : hwio);
+
+ if (is_src_s8) {
+ want_wei_md.extra.flags = 0
+ | memory_extra_flags::compensation_conv_s8s8
+ | memory_extra_flags::scale_adjust;
+ want_wei_md.extra.compensation_mask = (1 << 0)
+ + (with_groups() ? (1 << 1) : 0);
+ want_wei_md.extra.scale_adjust =
+ mayiuse(avx512_core_vnni) ? 1.f : 0.5f;
+ }
+
+ if (weights_md_.format_kind == format_kind::any) {
+ weights_md_ = want_wei_md;
+ return true;
+ }
+
+ return weights_md_ == want_wei_md;
+ }
+
+ bool post_ops_ok() const {
+ using namespace mkldnn::impl::primitive_kind;
+ auto const &po = attr()->post_ops_;
+ auto is_relu = [&](int idx) {
+ return po.entry_[idx].is_relu(true, false); };
+
+ switch (po.len_) {
+ case 0: return true;
+ case 1: return is_relu(0) || po.contain(sum, 0);
+ case 2: return po.contain(sum, 0) && is_relu(1);
+ default: return false;
+ }
+ return false;
+ }
+ };
+
+ _gemm_x8s8s32x_convolution_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd, true), pp_ker_(nullptr)
+ { pp_ker_ = new pp_ker_t(pd()); }
+ ~_gemm_x8s8s32x_convolution_fwd_t() { delete pp_ker_; }
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<data_type::s8>::type wei_data_t;
+ typedef typename prec_traits<dst_type>::type dst_data_t;
+ typedef typename prec_traits<data_type::s32>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ // XXX: this is throwaway code that will become unnecessary when we have a
+ // sufficiently advanced igemm jit generator that supports quantization,
+ // relu, and whatnot
+ class pp_ker_t : jit_generator {
+ public:
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(
+ _gemm_x8s8s32x_convolution_fwd_t::pp_kernel);
+ pp_ker_t(const pd_t *pd);
+
+ void operator()(dst_data_t *dst, const acc_data_t *acc,
+ const char *bias, const float *scales,
+ float nslope, float sum_scale, float signed_scale,
+ int g, size_t start, size_t end);
+
+ size_t dst_os_stride_;
+
+ private:
+ void generate();
+
+ struct ker_args {
+ dst_data_t *dst;
+ const acc_data_t *acc;
+ const char *bias;
+ const float *scales;
+ float nslope;
+ float sum_scale;
+ float signed_scale;
+ size_t len;
+ size_t oc_offset;
+ };
+ void(*ker_)(const ker_args *args);
+
+ const jit_gemm_conv_conf_t &jcp_;
+ size_t OC_;
+ size_t OS_;
+ data_type_t bias_data_type_;
+ size_t bias_data_type_size_;
+ size_t scale_idx_mult_;
+ bool do_bias_;
+ bool do_relu_;
+ bool do_sum_;
+ bool do_signed_scaling_;
+ size_t vlen_;
+ };
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ void execute_forward(const exec_ctx_t &ctx) const;
+ void execute_forward_thr(const int ithr, const int nthr,
+ const src_data_t *src_base, const wei_data_t *wei_base,
+ const char *bia_base, dst_data_t *dst_base,
+ const memory_tracking::grantor_t &scratchpad) const;
+
+ int nthr_;
+ pp_ker_t *pp_ker_;
+
+};
+
+template <data_type_t dst_type>
+struct _gemm_u8s8s32x_convolution_bwd_data_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_data_pd_t{
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc, const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(IGEMM_S8U8S32_IMPL_STR,
+ _gemm_u8s8s32x_convolution_bwd_data_t<dst_type>);
+
+ status_t init() {
+ using namespace data_type;
+
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_data
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(dst_type, s8, data_type::undef, u8, s32)
+ && IMPLICATION(with_bias(), utils::one_of(
+ desc()->bias_desc.data_type, f32, s32, s8, u8))
+ && !has_zero_dim_memory()
+ && set_default_formats_common(dat_tag(), wei_tag(), dat_tag())
+ && attr()->post_ops_.has_default_values()
+ && memory_desc_matches_tag(*diff_src_md(), dat_tag())
+ && memory_desc_matches_tag(*diff_dst_md(), dat_tag())
+ && memory_desc_matches_tag(*weights_md(), wei_tag());
+ if (!ok) return status::unimplemented;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ return jit_gemm_convolution_utils::init_conf(jcp_, scratchpad,
+ *desc(), diff_src_md(), weights_md(), diff_dst_md(),
+ mkldnn_get_max_threads());
+ }
+
+ virtual bool support_bias() const override { return true; }
+
+ jit_gemm_conv_conf_t jcp_;
+
+ protected:
+ format_tag_t dat_tag() const { return format_tag::nhwc; }
+
+ format_tag_t wei_tag() const {
+ return with_groups() ? format_tag::hwigo : format_tag::hwio;
+ }
+ };
+
+ _gemm_u8s8s32x_convolution_bwd_data_t(const pd_t *apd)
+ : cpu_primitive_t(apd, true) {}
+
+ typedef typename prec_traits<data_type::u8>::type diff_dst_data_t;
+ typedef typename prec_traits<data_type::s8>::type wei_data_t;
+ typedef typename prec_traits<dst_type>::type diff_src_data_t;
+ typedef typename prec_traits<data_type::s32>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_data(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_data(const exec_ctx_t &ctx) const;
+ void execute_backward_data_thr(const int ithr, const int nthr,
+ const diff_dst_data_t *diff_dst_base, const wei_data_t *wei_base,
+ const char *bia_base, diff_src_data_t *diff_src_base,
+ const memory_tracking::grantor_t &scratchpad) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.cpp
new file mode 100644
index 0000000000..1e435a233a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.cpp
@@ -0,0 +1,453 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+#include "simple_q10n.hpp"
+
+#include "gemm/gemm.hpp"
+#include "gemm_x8s8s32x_inner_product.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace math;
+using namespace format_tag;
+using namespace memory_tracking::names;
+
+template<data_type_t src_type, data_type_t dst_type>
+gemm_x8s8s32x_inner_product_fwd_t<src_type, dst_type>::pp_kernel_t::pp_kernel_t(
+ const pd_t *pd, bool dst_is_acc)
+ : ker_(nullptr), OC_(pd->OC())
+ , bias_data_type_(data_type::undef), bias_data_type_size_(0)
+ , scale_idx_mult_(0), do_bias_(false), do_relu_(false)
+{
+ using namespace types;
+
+ scale_idx_mult_ = (pd->attr()->output_scales_.mask_ == (1 << 1));
+
+ auto &post_ops = pd->attr()->post_ops_;
+ do_relu_ = post_ops.len_ == 1;
+ do_bias_ = pd->with_bias();
+ bias_data_type_ = pd->desc()->bias_desc.data_type;
+ if (do_bias_) {
+ assert(bias_data_type_ != data_type::undef);
+ bias_data_type_size_ = data_type_size(bias_data_type_);
+ }
+
+ if (!mayiuse(avx512_core))
+ // use fallback code for older CPUs since they do not have optimized
+ // x8s8s32 GEMM anyways. The configuration variables above are used by
+ // the fallback code.
+ return;
+ else
+ generate();
+}
+
+template<data_type_t src_type, data_type_t dst_type>
+void gemm_x8s8s32x_inner_product_fwd_t<src_type, dst_type>::pp_kernel_t::generate()
+{
+ using namespace Xbyak;
+ using namespace utils;
+
+ // TODO: clean-up
+ Reg64 reg_param = abi_param1;
+ Reg64 reg_dst = rdx;
+ Reg64 reg_acc = rax;
+ Reg64 reg_bias = rbx;
+ Reg64 reg_scales = rsi;
+
+ Reg64 reg_len = r8;
+ Reg64 reg_tmp = rcx; // intentional for shifting purposes
+ Reg64 reg_oc_offset = r9;
+ Reg64 reg_rem_mask = r10;
+ Opmask kreg_rem_mask = k1;
+ Opmask kreg_relu_cmp = k2;
+
+ const size_t vlen = cpu_isa_traits<avx512_common>::vlen / sizeof(float);
+
+ Zmm vreg_zero = Zmm(0);
+ Zmm vreg_scale = Zmm(1);
+ Zmm vreg_nslope = Zmm(2);
+
+ auto vreg_dst = [&](int idx) { return Zmm(3 + idx * 2 + 0); };
+ auto vreg_bias = [&](int idx) { return Zmm(3 + idx * 2 + 1); };
+
+ preamble();
+
+#define PARAM_OFF(x) offsetof(ker_args, x)
+ mov(reg_dst, ptr[reg_param + PARAM_OFF(dst)]);
+ mov(reg_acc, ptr[reg_param + PARAM_OFF(acc)]);
+ mov(reg_bias, ptr[reg_param + PARAM_OFF(bias)]);
+ mov(reg_scales, ptr[reg_param + PARAM_OFF(scales)]);
+ mov(reg_len, ptr[reg_param + PARAM_OFF(len)]);
+ mov(reg_oc_offset, ptr[reg_param + PARAM_OFF(oc_offset)]);
+ vbroadcastss(vreg_nslope, ptr[reg_param + PARAM_OFF(nslope)]);
+ if (scale_idx_mult_ == 0)
+ vbroadcastss(vreg_scale, dword[reg_scales]);
+#undef PARAM_OFF
+
+ if (do_relu_ || dst_type == data_type::u8)
+ vxorps(vreg_zero, vreg_zero, vreg_zero);
+
+ // Load accumulated value, convert to float, apply bias (if any), scaling,
+ // and relu (if any); then convert to destination type and store
+ auto compute = [&](size_t offset, int idx, bool apply_mask) {
+ auto acc_addr = ptr[reg_acc + offset * sizeof(acc_data_t)];
+
+ if (scale_idx_mult_ > 0) {
+ assert(scale_idx_mult_ == 1);
+ auto scale_addr = ptr[reg_scales + offset * sizeof(float)];
+ auto vreg_scale_ = vreg_scale;
+ if (apply_mask)
+ vreg_scale_ = vreg_scale_ | kreg_rem_mask;
+ vmovups(vreg_scale, scale_addr);
+ }
+
+ auto vreg_dst_ = vreg_dst(idx);
+ if (apply_mask)
+ vreg_dst_ = vreg_dst_ | kreg_rem_mask;
+ vcvtdq2ps(vreg_dst_, acc_addr);
+
+ if (do_bias_) {
+ auto bias_addr = ptr[reg_bias + offset * bias_data_type_size_];
+ auto vreg_bias_ = vreg_bias(idx);
+ if (apply_mask)
+ vreg_bias_ = vreg_bias_ | kreg_rem_mask;
+
+ switch (bias_data_type_) {
+ case data_type::s8:
+ vpmovsxbd(vreg_bias_, bias_addr);
+ break;
+ case data_type::u8:
+ vpmovzxbd(vreg_bias_, bias_addr);
+ break;
+ case data_type::s32:
+ case data_type::f32:
+ vmovups(vreg_bias_, bias_addr);
+ break;
+ default: assert(!"unimplemented");
+ }
+ if (bias_data_type_ != data_type::f32)
+ vcvtdq2ps(vreg_bias(idx), vreg_bias(idx));
+ vaddps(vreg_dst(idx), vreg_dst(idx), vreg_bias(idx));
+ }
+
+ vmulps(vreg_dst(idx), vreg_dst(idx), vreg_scale);
+ if (do_relu_) {
+ vcmpps(kreg_relu_cmp, vreg_dst(idx), vreg_zero, _cmp_lt_os);
+ vmulps(vreg_dst(idx) | kreg_relu_cmp, vreg_dst(idx), vreg_nslope);
+ }
+
+ if (dst_type == data_type::u8)
+ vmaxps(vreg_dst(idx), vreg_dst(idx), vreg_zero);
+
+ if (dst_type != data_type::f32) {
+ vcvtps2dq(vreg_dst(idx), vreg_dst(idx));
+ }
+
+ auto dst_addr = ptr[reg_dst + offset * sizeof(dst_data_t)];
+ switch (dst_type) {
+ case data_type::s8:
+ vpmovsdb(dst_addr, vreg_dst_);
+ break;
+ case data_type::u8:
+ vpmovusdb(dst_addr, vreg_dst_);
+ break;
+ case data_type::f32:
+ case data_type::s32:
+ vmovups(dst_addr, vreg_dst_);
+ break;
+ default: assert(!"unimplemented");
+ }
+ };
+
+ // Advance all pointers by an immediate
+ auto advance_ptrs_imm = [&](size_t offset) {
+ add(reg_dst, offset * sizeof(dst_data_t));
+ add(reg_acc, offset * sizeof(acc_data_t));
+ if (scale_idx_mult_) {
+ assert(scale_idx_mult_ == 1);
+ add(reg_scales, offset * sizeof(float));
+ }
+ if (do_bias_)
+ add(reg_bias, offset * bias_data_type_size_);
+ };
+
+ // Advance all pointers by a value stored in a register
+ auto advance_ptrs_reg = [&](Reg64 offset) {
+ lea(reg_dst, ptr[reg_dst + offset * sizeof(dst_data_t)]);
+ lea(reg_acc, ptr[reg_acc + offset * sizeof(acc_data_t)]);
+ if (scale_idx_mult_) {
+ assert(scale_idx_mult_ == 1);
+ lea(reg_scales, ptr[reg_scales + offset * sizeof(float)]);
+ }
+ if (do_bias_)
+ lea(reg_bias, ptr[reg_bias + offset * bias_data_type_size_]);
+ };
+
+ // Rewind pointers that point to data that is indixed by output channel
+ // (bias or per-oc scaling factors)
+ auto rewind_ptrs = [&]() {
+ if (do_bias_)
+ sub(reg_bias, OC_ * bias_data_type_size_);
+ if (scale_idx_mult_) {
+ assert(scale_idx_mult_ == 1);
+ sub(reg_scales, OC_ * sizeof(float));
+ }
+ };
+
+ // <-------------------- OC ------------------------------->
+ //
+ // ^ +....................+----------------------------------+
+ // | : not accessed | Prologue loop |
+ // | +--------------------+----------------------------------+
+ // | |
+ // M | Main loop (unrolled) |
+ // B | |
+ // +--------------------------------+----------------------+
+ // | | Epilogue loop | not accessed :
+ // v +--------------------------------+......................+
+
+ Label prologue_end;
+ cmp(reg_oc_offset, 0);
+ je(prologue_end, T_NEAR);
+
+ // Prologue loop
+ {
+ mov(reg_tmp, OC_);
+ sub(reg_tmp, reg_oc_offset);
+ cmp(reg_tmp, reg_len);
+ cmovg(reg_tmp, reg_len);
+ sub(reg_len, reg_tmp);
+
+ Label prologue_loop, prologue_loop_tail, prologue_loop_end;
+ cmp(reg_tmp, vlen);
+ jle(prologue_loop_tail, T_NEAR); // Skips for reg_tmp == 16 too (?)
+ L(prologue_loop); {
+ compute(0, 0, false);
+ advance_ptrs_imm(vlen);
+ sub(reg_tmp, vlen);
+ cmp(reg_tmp, vlen);
+ jge(prologue_loop, T_NEAR);
+ }
+
+ L(prologue_loop_tail);
+ mov(reg_rem_mask, 1);
+ shl(reg_rem_mask, cl); // cl == reg_tmp because reg_tmp <= vlen here
+ sub(reg_rem_mask, 1);
+ jz(prologue_loop_end, T_NEAR);
+
+ kmovq(kreg_rem_mask, reg_rem_mask);
+ compute(0, 0, true);
+ advance_ptrs_reg(reg_tmp);
+
+ L(prologue_loop_end);
+ rewind_ptrs();
+ }
+ L(prologue_end);
+
+ // Main loop
+ Label main_loop_end;
+ {
+ cmp(reg_len, OC_);
+ jle(main_loop_end, T_NEAR);
+
+ Label main_loop;
+ L(main_loop); {
+ size_t def_unroll = 4;
+ size_t max_unroll = 13;
+
+ size_t OC_loop, OC_tail;
+ if (OC_ < max_unroll * vlen) {
+ // Fully unroll small loops
+ OC_loop = 0;
+ OC_tail = OC_;
+ } else {
+ OC_loop = vlen * def_unroll;
+ OC_tail = OC_ % OC_loop;
+ }
+
+ assert(!!OC_loop || !!OC_tail);
+
+ if (OC_tail % vlen) {
+ int vlen_tail = OC_tail % vlen;
+ unsigned tail_mask = (1 << vlen_tail) - 1;
+ mov(reg_tmp, tail_mask);
+ kmovq(kreg_rem_mask, reg_tmp);
+ }
+
+ if (OC_loop) {
+ mov(reg_tmp, rnd_dn(OC_, OC_loop));
+ Label oc_loop;
+ L(oc_loop); {
+ for (size_t offset = 0; offset < OC_loop; offset += vlen)
+ compute(offset, offset / vlen, false);
+ advance_ptrs_imm(OC_loop);
+ sub(reg_tmp, OC_loop);
+ jnz(oc_loop);
+ }
+ }
+
+ if (OC_tail) {
+ for (size_t offset = 0; offset < OC_tail; offset += vlen) {
+ bool use_mask = (offset + vlen) > OC_tail;
+ compute(offset, offset / vlen, use_mask);
+ }
+ advance_ptrs_imm(OC_tail);
+ }
+
+ rewind_ptrs();
+ sub(reg_len, OC_);
+ cmp(reg_len, OC_);
+ jge(main_loop, T_NEAR);
+ }
+ }
+ L(main_loop_end);
+
+ // Epilogue loop
+ Label epilogue_end;
+ {
+ cmp(reg_len, 0);
+ je(epilogue_end, T_NEAR);
+
+ Label epilogue_loop, epilogue_loop_tail;
+ cmp(reg_len, vlen);
+ jle(epilogue_loop_tail, T_NEAR); // Skips for reg_len == 16 (?)
+ L(epilogue_loop); {
+ compute(0, 0, false);
+ sub(reg_len, vlen);
+ advance_ptrs_imm(vlen);
+ cmp(reg_len, vlen);
+ jge(epilogue_loop, T_NEAR);
+ }
+
+ L(epilogue_loop_tail);
+ mov(reg_tmp, reg_len); // reg_tmp is rcx, and we need cl for the shift
+ mov(reg_rem_mask, 1);
+ shl(reg_rem_mask, cl); // reg_tmp == rcx and reg_tail < vlen == 16
+ sub(reg_rem_mask, 1);
+ jz(epilogue_end, T_NEAR);
+ kmovq(kreg_rem_mask, reg_rem_mask);
+ compute(0, 0, true);
+ }
+
+ L(epilogue_end);
+
+ postamble();
+
+ ker_ = getCode<decltype(ker_)>();
+}
+
+template<data_type_t src_type, data_type_t dst_type>
+void gemm_x8s8s32x_inner_product_fwd_t<src_type, dst_type>::pp_kernel_t::operator ()(
+ dst_data_t *dst, const acc_data_t *acc,
+ const char *bias, const float *scales, float nslope,
+ size_t start, size_t end)
+{
+ using math::get_bias;
+
+ if (end <= start)
+ return;
+
+ if (ker_) {
+ // JIT
+ ker_args args;
+ size_t oc_offset = start % OC_;
+ args.dst = dst + start;
+ args.acc = acc + start;
+ args.bias = bias + oc_offset * bias_data_type_size_;
+ args.scales = scales + scale_idx_mult_ * oc_offset;
+ args.nslope = nslope;
+ args.len = end - start;
+ args.oc_offset = oc_offset;
+ ker_(&args);
+ } else {
+ // Fallback
+ size_t oc = start % OC_;
+ for (size_t i = start; i < end; i++) {
+ float d = (float)acc[i];
+ float b = get_bias(bias, oc, bias_data_type_);
+ d = d + b;
+ d *= scales[oc * scale_idx_mult_];
+ if (do_relu_ && d < 0)
+ d *= nslope;
+ dst[i] = qz_a1b0<float, dst_data_t>()(d);
+ oc = (oc == OC_ - 1) ? 0 : oc + 1;
+ }
+ }
+};
+
+template <data_type_t src_type, data_type_t dst_type>
+void gemm_x8s8s32x_inner_product_fwd_t<src_type, dst_type>::execute_forward(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ const int MB = pd()->MB();
+ const int OC = pd()->OC();
+
+ bool wei_tr = memory_desc_matches_one_of_tag(
+ *pd()->weights_md(), oiw, oihw, oidhw, oi);
+
+ const int M = OC;
+ const int N = MB;
+ const int K = pd()->IC_total_padded();
+ const int8_t off_a = 0, off_b = 0;
+ const int32_t off_c = 0;
+
+ const float *scales = pd()->attr()->output_scales_.scales_;
+
+ const auto &post_ops = pd()->attr()->post_ops_;
+ const bool do_relu = post_ops.len_ == 1;
+ const float nslope = do_relu ? post_ops.entry_[0].eltwise.alpha : 0.f;
+
+ acc_data_t *acc = pd()->dst_is_acc_
+ ? (acc_data_t *)dst
+ : scratchpad(ctx).template get<acc_data_t>(key_iprod_int_dat_in_acc_dt);
+
+ const float onef = 1.0, zerof = 0.0;
+ gemm_s8x8s32(wei_tr ? "T" : "N", "N", "F", &M, &N, &K, &onef, weights,
+ wei_tr ? &K : &M, &off_a, src, &K, &off_b, &zerof, acc, &M, &off_c);
+
+ if (!pd()->attr()->has_default_values() || !pd()->dst_is_acc_
+ || pd()->with_bias()) {
+ const bool force_sequential = MB * OC < 2000;
+ parallel(force_sequential ? 1 : 0, [&](int ithr, int nthr) {
+ size_t start, end;
+ balance211((size_t)OC * MB, nthr, ithr, start, end);
+ (*pp_kernel_)(dst, acc, bias, scales, nslope, start, end);
+ });
+ }
+}
+
+using namespace data_type;
+
+template struct gemm_x8s8s32x_inner_product_fwd_t<u8, f32>;
+template struct gemm_x8s8s32x_inner_product_fwd_t<u8, s32>;
+template struct gemm_x8s8s32x_inner_product_fwd_t<u8, s8>;
+template struct gemm_x8s8s32x_inner_product_fwd_t<u8, u8>;
+template struct gemm_x8s8s32x_inner_product_fwd_t<s8, f32>;
+template struct gemm_x8s8s32x_inner_product_fwd_t<s8, s32>;
+template struct gemm_x8s8s32x_inner_product_fwd_t<s8, s8>;
+template struct gemm_x8s8s32x_inner_product_fwd_t<s8, u8>;
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.hpp
new file mode 100644
index 0000000000..ac6a5c8f85
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/gemm_x8s8s32x_inner_product.hpp
@@ -0,0 +1,166 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef GEMM_X8S8S32X_INNER_PRODUCT_HPP
+#define GEMM_X8S8S32X_INNER_PRODUCT_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "gemm/gemm.hpp"
+#include "jit_generator.hpp"
+
+#include "cpu_inner_product_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t src_type, impl::data_type_t dst_type>
+struct gemm_x8s8s32x_inner_product_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_inner_product_fwd_pd_t {
+ using cpu_inner_product_fwd_pd_t::cpu_inner_product_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T(src_type == data_type::u8
+ ? IGEMM_S8U8S32_IMPL_STR
+ : IGEMM_S8S8S32_IMPL_STR,
+ gemm_x8s8s32x_inner_product_fwd_t);
+
+ status_t init() {
+ using namespace data_type;
+
+ bool ok = true
+ && set_default_params() == status::success
+ && is_fwd()
+ && !has_zero_dim_memory()
+ && src_md()->data_type == src_type
+ && dst_md()->data_type == dst_type
+ && weights_md()->data_type == s8
+ && IMPLICATION(with_bias(), utils::one_of(
+ weights_md(1)->data_type, f32, s32, s8, u8))
+ && attr()->post_ops_.len_ <= 1
+ && IMPLICATION(attr()->post_ops_.len_,
+ attr()->post_ops_.entry_[0].is_relu(true, false))
+ && dense_gemm_consitency_check(src_md(), weights_md(),
+ dst_md());
+ if (!ok) return status::unimplemented;
+
+ dst_is_acc_ = utils::one_of(dst_type, s32, f32);
+
+ init_scratchpad();
+
+ return status::success;
+ }
+
+ bool dst_is_acc_;
+
+ protected:
+ status_t set_default_params() {
+ using namespace format_tag;
+ if (src_md_.format_kind == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(src_md_,
+ utils::pick(ndims() - 2, nc, nwc, nhwc, ndhwc)));
+ }
+ if (dst_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(dst_md_, nc));
+ if (weights_md_.format_kind == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(weights_md_,
+ utils::pick(ndims() - 2, io, wio, hwio, dhwio)));
+ }
+ return inner_product_fwd_pd_t::set_default_params();
+ }
+
+ private:
+ void init_scratchpad() {
+ if (!dst_is_acc_) {
+ auto scratchpad = scratchpad_registry().registrar();
+ scratchpad.book(
+ memory_tracking::names::key_iprod_int_dat_in_acc_dt,
+ sizeof(acc_data_t) * MB() * OC());
+ }
+ }
+ };
+
+ gemm_x8s8s32x_inner_product_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd, true)
+ { pp_kernel_ = new pp_kernel_t(apd, pd()->dst_is_acc_); }
+ ~gemm_x8s8s32x_inner_product_fwd_t() { delete pp_kernel_; }
+
+ typedef typename prec_traits<dst_type>::type data_t;
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<data_type::s8>::type wei_data_t;
+ typedef typename prec_traits<dst_type>::type dst_data_t;
+ typedef typename prec_traits<data_type::s32>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ // XXX: this is throwaway code that will become unnecessary when we have a
+ // sufficiently advanced igemm jit generator that supports quantization,
+ // relu, and whatnot
+ class pp_kernel_t: jit_generator {
+ public:
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(
+ gemm_x8s8s32x_inner_product_fwd_t::pp_kernel);
+ pp_kernel_t(const pd_t *pd, bool dst_is_acc);
+
+ void operator()(dst_data_t *dst, const acc_data_t *acc,
+ const char *bias, const float *scales, float nslope,
+ size_t start, size_t end);
+ private:
+ void generate();
+
+ struct ker_args {
+ dst_data_t *dst;
+ const acc_data_t *acc;
+ const char *bias;
+ const float *scales;
+ float nslope;
+ size_t len;
+ size_t oc_offset;
+ };
+ void (*ker_)(const ker_args *args);
+
+ size_t OC_;
+ data_type_t bias_data_type_;
+ size_t bias_data_type_size_;
+ size_t scale_idx_mult_;
+ bool do_bias_;
+ bool do_relu_;
+ };
+
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ pp_kernel_t *pp_kernel_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.cpp
new file mode 100644
index 0000000000..6fa251d465
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.cpp
@@ -0,0 +1,674 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+* Copyright 2018 YANDEX LLC
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_memory.hpp"
+
+#include "jit_avx2_1x1_conv_kernel_f32.hpp"
+
+#define GET_OFF(field) offsetof(jit_1x1_conv_call_s, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::utils;
+
+using namespace Xbyak;
+
+void jit_avx2_1x1_conv_kernel_f32::generate_bcast_loop(int load_loop_blk)
+{
+ mov(aux1_reg_bcast_data, reg_bcast_data);
+ mov(aux_reg_output_data, reg_output_data);
+ mov(bcast_loop_iter, reg_bcast_loop_work);
+
+ Label bcast_loop, bcast_loop_tail;
+
+ cmp(bcast_loop_iter, jcp.ur);
+ jl(bcast_loop_tail, T_NEAR);
+
+ L(bcast_loop); {
+ assert(jcp.bcast_block % jcp.ur == 0);
+ int num_substeps = jcp.bcast_block / jcp.ur;
+ assert(num_substeps > 0 && num_substeps < 10);
+ for (int i = 0; i < num_substeps; i++) {
+ generate_reduce_loop(load_loop_blk, jcp.ur);
+ if (i < num_substeps - 1) {
+ add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_substep);
+ add(aux_reg_output_data, jcp.bcast_loop_output_substep);
+ } else {
+ add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_step
+ - (num_substeps - 1) * jcp.bcast_loop_bcast_substep);
+ add(aux_reg_output_data, jcp.bcast_loop_output_step
+ - (num_substeps - 1) * jcp.bcast_loop_output_substep);
+ }
+ }
+ sub(bcast_loop_iter, jcp.bcast_block);
+ cmp(bcast_loop_iter, jcp.bcast_block);
+ jge(bcast_loop, T_NEAR);
+ }
+
+ L(bcast_loop_tail);
+ if (jcp.ur_tail) {
+ Label bcast_loop_tail_out;
+ cmp(bcast_loop_iter, 0);
+ jz(bcast_loop_tail_out, T_NEAR);
+ generate_reduce_loop(load_loop_blk, jcp.ur_tail);
+ L(bcast_loop_tail_out);
+ }
+}
+
+void jit_avx2_1x1_conv_kernel_f32::generate_reduce_loop(
+ int load_loop_blk, int ur)
+{
+ auto vreg_load = [=](int i) {
+ return Ymm(ur * load_loop_blk + i);
+ };
+
+ auto vreg_accum = [=](int i, int j) {
+ return Ymm(j * load_loop_blk + i);
+ };
+
+ auto bias_ptr = [=](int i) {
+ return ptr[reg_bias_data + sizeof(float) * jcp.oc_block * i];
+ };
+
+ auto bcast_ptr = [=](int u, int j) {
+ assert(j < jcp.ur);
+ assert(u <= jcp.reduce_loop_unroll);
+ size_t offt;
+ if (one_of(jcp.prop_kind,
+ forward_training, forward_inference, backward_data))
+ {
+ assert(jcp.reduce_loop_unroll == (jcp.prop_kind == backward_data)
+ ? jcp.oc_block : jcp.ic_block);
+ auto height = (jcp.prop_kind == backward_data) ? jcp.os : jcp.is;
+ offt = (u == jcp.reduce_loop_unroll)
+ ? (height + j) * jcp.reduce_loop_unroll
+ : j * jcp.reduce_loop_unroll + u;
+ } else
+ offt = u * jcp.ic_block + j;
+ return ptr[aux_reg_bcast_data + sizeof(float) * offt];
+ };
+
+ auto load_ptr = [=](int u, int i) {
+ size_t offt;
+ size_t u0 = u % jcp.reduce_loop_unroll;
+ size_t u1 = u / jcp.reduce_loop_unroll;
+ switch (jcp.prop_kind) {
+ case backward_data:
+ offt = (i * jcp.oc_block + u0) * jcp.ic_block;
+ break;
+ case backward_weights:
+ offt = (i * jcp.os + u0) * jcp.oc_block;
+ break;
+ default:
+ offt = (i * jcp.ic + u0) * jcp.oc_block;
+ }
+ return ptr[aux_reg_load_data
+ + u1 * jcp.reduce_loop_load_step + sizeof(float) * offt];
+ };
+
+ auto output_ptr = [=](int i, int j) {
+ switch (jcp.prop_kind) {
+ case backward_data:
+ return ptr[aux_reg_output_data +
+ (i * jcp.is + j) * jcp.ic_block * sizeof(float)];
+ case backward_weights:
+ return ptr[aux_reg_output_data
+ + (i ? reg_output_stride * i : 0) // TODO: Xbyak should allow 0 scale
+ + sizeof(float) * jcp.oc_block * j];
+ default:
+ return ptr[aux_reg_output_data +
+ (i * jcp.os + j) * jcp.oc_block * sizeof(float)];
+ }
+ };
+
+ auto init = [=]() {
+ Label init_done, init_zero;
+
+ if (jcp.with_bias && one_of(jcp.prop_kind, forward_training,
+ forward_inference)) {
+ test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST);
+ jz(init_zero);
+
+ for (int i = 0; i < load_loop_blk; i++)
+ for (int j = 0; j < ur; ++j)
+ vmovups(vreg_accum(i, j), bias_ptr(i));
+ jmp(init_done);
+ }
+
+ L(init_zero);
+ for (int i = 0; i < load_loop_blk; ++i)
+ for (int j = 0; j < ur; ++j) {
+ auto r = vreg_accum(i, j);
+ vxorps(r, r, r);
+ }
+
+ L(init_done);
+ for (int i = 0; i < load_loop_blk; ++i)
+ vmovups(vreg_load(i), load_ptr(0, i));
+ vbroadcastss(vreg_bcast, bcast_ptr(0, 0));
+ };
+
+ auto store = [=]() {
+ Label store_noadd;
+
+ if (!jcp.with_sum) {
+ test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST);
+ jnz(store_noadd, T_NEAR);
+ }
+
+ for (int j = 0; j < ur; ++j)
+ for (int i = 0; i < load_loop_blk; ++i) {
+ auto r = vreg_accum(i, j);
+ vaddps(r, r, output_ptr(i, j));
+ }
+
+ L(store_noadd);
+
+ if (jcp.with_eltwise) {
+ assert(ur * load_loop_blk < 14);
+
+ Label store_norelu;
+ test(reg_reduce_pos_flag, FLAG_REDUCE_LAST);
+ jz(store_norelu, T_NEAR);
+
+ eltwise_injector_->compute_vector_range(0, ur * load_loop_blk);
+
+ L(store_norelu);
+ }
+
+ for (int j = 0; j < ur; ++j)
+ for (int i = 0; i < load_loop_blk; ++i) {
+ vmovups(output_ptr(i, j), vreg_accum(i, j));
+ }
+ };
+
+ auto fma_block = [=](bool last_block) {
+ for (int u = 0; u < jcp.reduce_loop_unroll; ++u) {
+ for (int j = 0; j < ur; ++j) {
+ for (int i = 0; i < load_loop_blk; ++i) {
+ if (mayiuse(avx2))
+ vfmadd231ps(vreg_accum(i, j), vreg_load(i), vreg_bcast);
+ else { // Intel(R) Advanced Vector Extensions (Intel(R) AVX) support
+ vmulps(vtmp, vreg_bcast, vreg_load(i));
+ vaddps(vreg_accum(i, j), vreg_accum(i, j), vtmp);
+ }
+ if (j == ur - 1 && !(last_block
+ && u == jcp.reduce_loop_unroll - 1))
+ vmovups(vreg_load(i), load_ptr(u + 1, i));
+ }
+ if (j < ur - 1)
+ vbroadcastss(vreg_bcast, bcast_ptr(u, j + 1));
+ }
+ if (!last_block || u < jcp.reduce_loop_unroll - 1)
+ vbroadcastss(vreg_bcast, bcast_ptr(u + 1, 0));
+ }
+ };
+
+ Label reduce_loop, reduce_loop_tail;
+
+ mov(aux_reg_load_data, reg_load_data);
+ mov(aux_reg_bcast_data, aux1_reg_bcast_data);
+
+ init();
+
+ mov(reduce_loop_iter, reg_reduce_loop_work);
+ sub(reduce_loop_iter, jcp.reduce_loop_unroll);
+ jle(reduce_loop_tail, T_NEAR);
+
+ L(reduce_loop); {
+ fma_block(false);
+ add(aux_reg_bcast_data, jcp.reduce_loop_bcast_step);
+ add(aux_reg_load_data, jcp.reduce_loop_load_step);
+ sub(reduce_loop_iter, jcp.reduce_loop_unroll);
+ jg(reduce_loop, T_NEAR);
+ }
+
+ L(reduce_loop_tail);
+ fma_block(true);
+
+ store();
+}
+
+void jit_avx2_1x1_conv_kernel_f32::generate_diff_bias_loop(int load_loop_blk)
+{
+ if (!jcp.with_bias || jcp.prop_kind != backward_weights)
+ return;
+
+ Label diff_bias_loop, diff_bias_loop_out, diff_bias_init_out;
+ Label diff_bias_load;
+
+ auto diff_bias_ptr = [=](int i) {
+ return ptr[reg_diff_bias_data + i * jcp.oc_block * sizeof(float)];
+ };
+
+ auto load_ptr = [=](int u, int i) {
+ return ptr[aux_reg_load_data
+ + (i * jcp.os + u) * jcp.oc_block * sizeof(float)];
+ };
+
+ auto diff_bias_reg = [=](int i) { return Ymm(i); };
+
+ mov(reg_diff_bias_data, ptr[rsp + reg_diff_bias_data_stack_offt]);
+ cmp(reg_diff_bias_data, 0);
+ je(diff_bias_loop_out, T_NEAR);
+
+ test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST);
+ jz(diff_bias_load, T_NEAR);
+
+ for (int i = 0; i < load_loop_blk; ++i) {
+ auto r = diff_bias_reg(i);
+ vxorps(r, r, r);
+ }
+ jmp(diff_bias_init_out, T_NEAR);
+
+ L(diff_bias_load);
+ for (int i = 0; i < load_loop_blk; ++i)
+ vmovups(diff_bias_reg(i), diff_bias_ptr(i));
+
+ L(diff_bias_init_out);
+ mov(aux_reg_load_data, reg_load_data);
+ mov(reduce_loop_iter, reg_reduce_loop_work);
+ L(diff_bias_loop); {
+ for(int u = 0; u < jcp.reduce_loop_unroll; ++u)
+ for (int i = 0; i < load_loop_blk; ++i)
+ vaddps(diff_bias_reg(i), diff_bias_reg(i), load_ptr(u, i));
+ assert(jcp.reduce_dim % jcp.reduce_loop_unroll == 0);
+ add(aux_reg_load_data, jcp.reduce_loop_load_step);
+ sub(reduce_loop_iter, jcp.reduce_loop_unroll);
+ jnz(diff_bias_loop, T_NEAR);
+ }
+
+ for (int i = 0; i < load_loop_blk; i++)
+ vmovups(diff_bias_ptr(i), diff_bias_reg(i));
+ add(reg_diff_bias_data, load_loop_blk * jcp.oc_block * sizeof(float));
+ mov(ptr[rsp + reg_diff_bias_data_stack_offt], reg_diff_bias_data);
+
+ L(diff_bias_loop_out);
+}
+
+void jit_avx2_1x1_conv_kernel_f32::generate()
+{
+ preamble();
+
+ mov(reg_bcast_data, ptr[param1 + GET_OFF(bcast_data)]);
+ mov(reg_load_data, ptr[param1 + GET_OFF(load_data)]);
+ mov(reg_output_data, ptr[param1 + GET_OFF(output_data)]);
+ if (jcp.with_bias) {
+ if (jcp.prop_kind == backward_weights) {
+ sub(rsp, stack_space_needed);
+ mov(reg_diff_bias_data, ptr[param1 + GET_OFF(bias_data)]);
+ mov(ptr[rsp + reg_diff_bias_data_stack_offt], reg_diff_bias_data);
+ } else
+ mov(reg_bias_data, ptr[param1 + GET_OFF(bias_data)]);
+ }
+
+ mov(reg_load_loop_work, ptr[param1 + GET_OFF(load_dim)]);
+ mov(reg_bcast_loop_work, ptr[param1 + GET_OFF(bcast_dim)]);
+ mov(reg_reduce_loop_work, ptr[param1 + GET_OFF(reduce_dim)]);
+ mov(reg_reduce_pos_flag, ptr[param1 + GET_OFF(first_last_flag)]);
+ if (jcp.prop_kind == backward_weights)
+ mov(reg_output_stride, ptr[param1 + GET_OFF(output_stride)]);
+
+ auto generate_load_loop_body = [=] (int load_loop_blk) {
+ generate_bcast_loop(load_loop_blk);
+ add(reg_load_data, load_loop_blk * jcp.load_loop_load_step);
+ switch (jcp.prop_kind) {
+ case forward_training:
+ case forward_inference:
+ add(reg_bias_data, load_loop_blk * jcp.oc_block * sizeof(float));
+ add(reg_output_data,
+ load_loop_blk * jcp.os * jcp.oc_block * sizeof(float));
+ break;
+ case backward_data:
+ add(reg_output_data,
+ load_loop_blk * jcp.is * jcp.ic_block * sizeof(float));
+ break;
+ case backward_weights:
+ for (int i = 0; i < load_loop_blk; i++)
+ add(reg_output_data, reg_output_stride);
+ break;
+ default:
+ assert(!"invalid prop_kind");
+ }
+ sub(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step);
+ };
+
+ Label load_loop_blk_8;
+ Label load_loop_blk_16;
+ Label load_loop_blk_24;
+ Label load_loop_blk_end;
+
+ cmp(reg_load_loop_work, 8);
+ jle(load_loop_blk_8, T_NEAR);
+
+ cmp(reg_load_loop_work, 32);
+ je(load_loop_blk_16, T_NEAR);
+
+ cmp(reg_load_loop_work, 16);
+ jle(load_loop_blk_16, T_NEAR);
+
+ L(load_loop_blk_24); {
+ generate_diff_bias_loop(3);
+ generate_load_loop_body(3);
+ cmp(reg_load_loop_work, 32);
+ je(load_loop_blk_16);
+ cmp(reg_load_loop_work, 24);
+ jge(load_loop_blk_24);
+ }
+
+ cmp(reg_load_loop_work, 8);
+ jle(load_loop_blk_8, T_NEAR);
+
+ L(load_loop_blk_16); {
+ generate_diff_bias_loop(2);
+ generate_load_loop_body(2);
+ cmp(reg_load_loop_work, 16);
+ jge(load_loop_blk_16);
+ }
+
+ L(load_loop_blk_8); {
+ cmp(reg_load_loop_work, 0);
+ je(load_loop_blk_end, T_NEAR);
+ generate_diff_bias_loop(1);
+ generate_load_loop_body(1);
+ }
+
+ L(load_loop_blk_end);
+
+ if (jcp.with_bias && jcp.prop_kind == backward_weights)
+ add(rsp, 8);
+
+ postamble();
+
+ if (jcp.with_eltwise)
+ eltwise_injector_->prepare_table();
+}
+
+bool jit_avx2_1x1_conv_kernel_f32::post_ops_ok(
+ jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ const auto &p = attr.post_ops_;
+
+ auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); };
+ auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); };
+
+ switch (p.len_) {
+ case 0: return true; // no post_ops
+ case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise
+ case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise
+ default: return false;
+ }
+
+ return false;
+}
+
+status_t jit_avx2_1x1_conv_kernel_f32::init_conf(jit_1x1_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d,
+ const primitive_attr_t &attr)
+{
+ if (!mayiuse(avx)) return status::unimplemented;
+
+ // TODO (Roma): this code is duplicated from the generic kernel; maybe the
+ // configuration struct could do some stuff below
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ const int ndims = src_d.ndims();
+
+ jcp.prop_kind = cd.prop_kind;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+
+ jcp.ih = (ndims == 3) ? 1 : src_d.dims()[2];
+ jcp.iw = src_d.dims()[ndims - 1];
+ jcp.oh = (ndims == 3) ? 1 : dst_d.dims()[2];
+ jcp.ow = dst_d.dims()[ndims - 1];
+
+ jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + 2];
+ jcp.kw = weights_d.dims()[with_groups + ndims - 1];
+
+ jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][ndims - 3];
+
+ jcp.stride_h = (ndims == 3) ? 1 : cd.strides[0];
+ jcp.stride_w = cd.strides[ndims - 3];
+
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ jcp.os = jcp.oh * jcp.ow;
+ jcp.is = jcp.ih * jcp.iw;
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ jcp.with_sum = p.find(primitive_kind::sum) != -1;
+ const int eltwise_ind = p.find(primitive_kind::eltwise);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise) {
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+ if (!mayiuse(avx2) && jcp.eltwise.alg != alg_kind::eltwise_relu)
+ return status::unimplemented;
+ }
+
+ const int is_bwd_d = jcp.prop_kind == backward_data;
+
+ format_tag_t dat_tag = ndims == 3 ? nCw8c : nChw8c;
+ format_tag_t wei_tag = with_groups
+ ? utils::pick(2 * ndims - 6 + is_bwd_d, gOIw8i8o, gOIw8o8i, gOIhw8i8o,
+ gOIhw8o8i)
+ : utils::pick(2 * ndims - 6 + is_bwd_d, OIw8i8o, OIw8o8i, OIhw8i8o,
+ OIhw8o8i);
+
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag);
+ jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag);
+
+ const int simd_w = 8;
+
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ jcp.ic = rnd_up(jcp.ic, simd_w);
+
+ bool args_ok = true
+ && jcp.ngroups == 1
+ && jcp.src_tag == dat_tag
+ && jcp.wei_tag == wei_tag
+ && jcp.dst_tag == dat_tag;
+ if (!args_ok) return status::unimplemented;
+
+ args_ok = true
+ && jcp.ih == jcp.oh && jcp.iw == jcp.ow
+ && jcp.oc % simd_w == 0 && jcp.ic % simd_w == 0
+ && jcp.t_pad == 0 && jcp.l_pad == 0
+ && jcp.stride_w == 1 && jcp.stride_h == 1 // TODO: support some strides
+ && jcp.kh == 1 && jcp.kw == 1;
+ if (!args_ok) return status::unimplemented;
+
+ // TODO: remove this restriction
+ // optimized 1x1 bwd_w does not support Intel AVX
+ if (jcp.prop_kind == backward_weights && !mayiuse(avx2))
+ return status::unimplemented;
+
+ jcp.ic_block = jcp.oc_block = simd_w;
+
+ jcp.ur = mayiuse(avx2) ? 4 : 3; // Intel AVX support
+
+ int load_blocking{ 0 };
+ int load_blocking_max{ 0 };
+ int bcast_blocking{ 0 };
+ int bcast_blocking_max{ 0 };
+ int reduce_blocking{ 0 };
+
+ if (one_of(jcp.prop_kind, forward_training, forward_inference)) {
+ jcp.reduce_dim = jcp.ic;
+ jcp.reduce_block = jcp.ic_block;
+
+ jcp.load_dim = jcp.oc;
+ jcp.load_block = jcp.oc_block;
+
+ jcp.bcast_dim = jcp.is;
+ jcp.bcast_block = jcp.ur;
+
+ jcp.reduce_loop_unroll = jcp.reduce_block;
+ jcp.reduce_loop_bcast_step
+ = jcp.reduce_loop_unroll * jcp.is * sizeof(float);
+ jcp.reduce_loop_load_step
+ = jcp.reduce_loop_unroll * jcp.oc_block * sizeof(float);
+
+ jcp.bcast_loop_output_step = jcp.ur * jcp.oc_block * sizeof(float);
+ jcp.bcast_loop_output_substep = -1; // unused
+ jcp.bcast_loop_bcast_step = jcp.ur * jcp.ic_block * sizeof(float);
+ jcp.bcast_loop_bcast_substep = -1; // unused
+
+ jcp.load_loop_load_step = jcp.ic * jcp.oc_block * sizeof(float);
+ jcp.load_loop_iter_step = jcp.oc_block;
+
+ load_blocking = 120; // assumes the kernel is jcp.ur x 3
+ load_blocking_max = 144;
+ bcast_blocking = 128; // affects load balancing across threads
+ bcast_blocking_max = 192;
+ reduce_blocking = 128; // affects L1$ utilization
+ } else if (jcp.prop_kind == backward_data) {
+ jcp.reduce_dim = jcp.oc;
+ jcp.reduce_block = jcp.oc_block;
+
+ jcp.load_dim = jcp.ic;
+ jcp.load_block = jcp.oc_block;
+
+ jcp.bcast_dim = jcp.os;
+ jcp.bcast_block = jcp.ur;
+
+ jcp.reduce_loop_unroll = jcp.reduce_block;
+ jcp.reduce_loop_bcast_step
+ = jcp.reduce_loop_unroll * jcp.os * sizeof(float);
+ jcp.reduce_loop_load_step
+ = jcp.reduce_loop_unroll * jcp.ic * sizeof(float);
+
+ jcp.bcast_loop_output_step = jcp.ur * jcp.ic_block * sizeof(float);
+ jcp.bcast_loop_output_substep = -1; // unused
+ jcp.bcast_loop_bcast_step = jcp.ur * jcp.oc_block * sizeof(float);
+ jcp.bcast_loop_bcast_substep = -1; // unused
+
+ jcp.load_loop_load_step = jcp.oc_block * jcp.ic_block * sizeof(float);
+ jcp.load_loop_iter_step = jcp.ic_block;
+
+ load_blocking = 96; // assumes the kernel is jcp.ur x 3
+ load_blocking_max = 144;
+ bcast_blocking = 128; // affects load balancing across threads
+ bcast_blocking_max = 196;
+ reduce_blocking = 64; // affects L1$ utilization
+ } else if (jcp.prop_kind == backward_weights) {
+ jcp.reduce_dim = jcp.os;
+ jcp.reduce_block = 1;
+
+ jcp.load_dim = jcp.oc;
+ jcp.load_block = jcp.oc_block;
+
+ jcp.bcast_dim = jcp.ic;
+ jcp.bcast_block = jcp.ic_block;
+
+ jcp.reduce_loop_unroll = jcp.reduce_block;
+ jcp.reduce_loop_bcast_step
+ = jcp.reduce_loop_unroll * jcp.ic_block * sizeof(float);
+ jcp.reduce_loop_load_step
+ = jcp.reduce_loop_unroll * jcp.oc_block * sizeof(float);
+
+ jcp.bcast_loop_output_step = jcp.oc_block * jcp.ic_block * sizeof(float);
+ jcp.bcast_loop_output_substep = jcp.oc_block * jcp.ur * sizeof(float);
+ jcp.bcast_loop_bcast_step = jcp.ic_block * jcp.is * sizeof(float);
+ jcp.bcast_loop_bcast_substep = jcp.ur * sizeof(float);
+
+ jcp.load_loop_load_step = jcp.oc_block * jcp.os * sizeof(float);
+ jcp.load_loop_iter_step = jcp.oc_block;
+
+ /* --- */
+
+ load_blocking = div_up(jcp.load_dim, jcp.load_block);
+ while (true) {
+ if (load_blocking <= 32) break;
+ else if (load_blocking % 2 == 0) load_blocking /= 2;
+ else if (load_blocking % 3 == 0) load_blocking /= 3;
+ else break;
+ }
+ load_blocking *= jcp.load_block;
+ load_blocking_max = load_blocking;
+ assert(jcp.load_dim % load_blocking == 0);
+
+ bcast_blocking = div_up(jcp.bcast_dim, jcp.bcast_block);
+ while (true) {
+ if (bcast_blocking <= 9) break;
+ else if (bcast_blocking % 2 == 0) bcast_blocking /= 2;
+ else if (bcast_blocking % 3 == 0) bcast_blocking /= 3;
+ else break;
+ }
+ bcast_blocking *= jcp.bcast_block;
+ bcast_blocking_max = bcast_blocking;
+ assert(jcp.bcast_dim % bcast_blocking == 0);
+
+ reduce_blocking = 128; // affects L1$ utilization
+ } else
+ return status::unimplemented;
+
+ assert(load_blocking);
+ assert(load_blocking_max);
+ assert(bcast_blocking);
+ assert(bcast_blocking_max);
+ assert(reduce_blocking);
+
+ assert(jcp.bcast_block % jcp.ur == 0);
+ jcp.ur_tail = jcp.bcast_dim % jcp.ur;
+
+ jcp.nb_bcast_blocking = bcast_blocking / jcp.bcast_block;
+ jcp.nb_bcast_blocking_max = bcast_blocking_max / jcp.bcast_block;
+ jcp.nb_load_blocking = load_blocking / jcp.load_block;
+ jcp.nb_load_blocking_max = load_blocking_max / jcp.load_block;
+ jcp.nb_reduce_blocking = reduce_blocking / jcp.reduce_block;
+
+ jcp.nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block);
+ jcp.nb_load = div_up(jcp.load_dim, jcp.load_block);
+ jcp.nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block);
+
+ return status::success;
+}
+
+void jit_avx2_1x1_conv_kernel_f32::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad,
+ const jit_1x1_conv_conf_t &jcp) {
+ using namespace mkldnn::impl::memory_tracking::names;
+
+ if (jcp.prop_kind != backward_data && jcp.oc != jcp.oc_without_padding)
+ scratchpad.book(key_conv_padded_bias, sizeof(float) * jcp.oc);
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.hpp
new file mode 100644
index 0000000000..bfdeb2b18d
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_conv_kernel_f32.hpp
@@ -0,0 +1,110 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_AVX2_1x1_CONV_KERNEL_F32_HPP
+#define JIT_AVX2_1x1_CONV_KERNEL_F32_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "cpu_memory.hpp"
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+#include "jit_uni_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_avx2_1x1_conv_kernel_f32: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx2_1x1_conv_kernel_f32)
+
+ jit_avx2_1x1_conv_kernel_f32(jit_1x1_conv_conf_t ajcp,
+ const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr)
+ {
+ if (jcp.with_eltwise)
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<avx2>(this,
+ jcp.eltwise);
+
+ this->generate();
+ jit_ker = (void (*)(jit_1x1_conv_call_s *))this->getCode();
+ }
+
+ ~jit_avx2_1x1_conv_kernel_f32() {
+ delete eltwise_injector_;
+ }
+
+ static bool post_ops_ok(jit_1x1_conv_conf_t &jcp,
+ const primitive_attr_t &attr);
+
+ static status_t init_conf(jit_1x1_conv_conf_t &jcp,
+ const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d,
+ const primitive_attr_t &attr);
+
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_1x1_conv_conf_t &jcp);
+
+ jit_1x1_conv_conf_t jcp;
+ const primitive_attr_t &attr_;
+ void (*jit_ker)(jit_1x1_conv_call_s *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ using ymm_t = const Xbyak::Ymm;
+
+ reg64_t reg_bcast_data = rax;
+ reg64_t reg_load_data = rsi;
+ reg64_t reg_output_data = rbx;
+ reg64_t aux_reg_bcast_data = rdx;
+ reg64_t aux1_reg_bcast_data = abi_not_param1;
+ reg64_t aux_reg_load_data = abi_param1;
+ reg64_t aux_reg_output_data = rbp;
+ reg64_t reg_load_loop_work = r9;
+ reg64_t reg_bcast_loop_work = r10;
+ reg64_t reg_reduce_loop_work = r11;
+ reg64_t load_loop_iter = r13;
+ reg64_t bcast_loop_iter = r14;
+ reg64_t reduce_loop_iter = r15;
+ reg64_t imm_addr64 = reduce_loop_iter;
+ reg64_t reg_reduce_pos_flag = r8;
+ reg64_t reg_output_stride = r12;
+ reg64_t reg_bias_data = r12;
+ reg64_t reg_diff_bias_data = bcast_loop_iter;
+
+ int reg_diff_bias_data_stack_offt = 0;
+ int stack_space_needed = 8;
+
+ ymm_t vreg_bcast = ymm_t(15);
+ ymm_t vtmp = ymm_t(14);
+
+ jit_uni_eltwise_injector_f32<avx2> *eltwise_injector_;
+
+ void generate_bcast_loop(int load_loop_blk);
+ void generate_reduce_loop(int load_loop_blk, int ur);
+ void generate_diff_bias_loop(int load_loop_blk);
+
+ void generate();
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.cpp
new file mode 100644
index 0000000000..f116ac9056
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.cpp
@@ -0,0 +1,545 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_generator.hpp"
+
+#include "jit_avx2_1x1_convolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+#define data_blk_off(f, n, c, h, w) \
+ ((ndims == 3) \
+ ? (f).blk_off(n, c, w) \
+ : (f).blk_off(n, c, h, w))
+
+/* convolution forward */
+
+void jit_avx2_1x1_convolution_fwd_t::execute_forward(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+ auto rtus_space = scratchpad(ctx).get<data_t>(key_conv_rtus_space);
+
+ const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast;
+ const int ndims = dst_d.ndims();
+
+ const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0];
+ const int stride_w = pd()->desc()->strides[ndims - 3];
+ const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0];
+ const int pad_l = pd()->desc()->padding[0][ndims - 3];
+
+ auto step = [](int default_step, int remaining, int tail_step) {
+ assert(default_step <= tail_step);
+ return remaining < tail_step ? remaining : default_step;
+ };
+
+ auto ker = [&](const int ithr, const int nthr) {
+ // TODO (Roma): remove this restriction
+ assert(jcp.stride_w == 1 && jcp.stride_h == 1);
+
+ auto p = jit_1x1_conv_call_s();
+ auto rp = rtus_driver_t<avx2>::call_params_t();
+
+ const int nb_oc = jcp.nb_load;
+ const int nb_ic = jcp.nb_reduce;
+ const int nb_ic_blocking = jcp.nb_reduce_blocking;
+ const int os_block = jcp.bcast_block;
+
+ int start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ int iwork = start;
+ while (iwork < end) {
+ int n{0}, g{0}, osb{0};
+ nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb,
+ jcp.nb_bcast);
+
+ int bcast_step = step(jcp.nb_bcast_blocking, jcp.nb_bcast - osb,
+ jcp.nb_bcast_blocking_max);
+ bcast_step = nstl::min(bcast_step, end - iwork);
+
+ const int os = osb * os_block;
+ const int oh = os / jcp.ow;
+ const int ow = os % jcp.ow;
+
+ const int ih = nstl::max(oh * stride_h - pad_t, 0);
+ const int iw = nstl::max(ow * stride_w - pad_l, 0);
+ rp.iw_start = iw;
+
+ p.bcast_dim = this_block_size(os, jcp.os, bcast_step * os_block);
+ rp.os = p.bcast_dim;
+
+ int ocb = 0;
+ while (ocb < jcp.nb_load) {
+ const int load_step = step(jcp.nb_load_blocking,
+ jcp.nb_load - ocb, jcp.nb_load_blocking_max);
+
+ const int _ocb = g * nb_oc + ocb;
+ p.load_dim = this_block_size(ocb * jcp.oc_block, jcp.oc,
+ load_step * jcp.oc_block);
+ const size_t dst_off = data_blk_off(dst_d, n, _ocb, oh, ow);
+
+ p.output_data = &dst[dst_off];
+
+ p.bias_data = &bias[_ocb * jcp.oc_block];
+
+ for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) {
+ p.first_last_flag = 0
+ | (icb == 0 ? FLAG_REDUCE_FIRST : 0)
+ | (icb + nb_ic_blocking >= nb_ic
+ ? FLAG_REDUCE_LAST : 0);
+
+ p.reduce_dim = this_block_size(icb * jcp.ic_block, jcp.ic,
+ nb_ic_blocking * jcp.ic_block);
+ rp.icb = p.reduce_dim / jcp.reduce_block;
+
+ p.load_data = &weights[pd()->with_groups()
+ ? weights_d.blk_off(g, ocb, icb)
+ : weights_d.blk_off(ocb, icb)];
+
+ const int _icb = g * nb_ic + icb;
+ if (pd()->rtus_.reduce_src_) {
+ rp.ws = rtus_space
+ + ithr * pd()->rtus_.space_per_thread_
+ + _icb * jcp.is * jcp.ic_block;
+
+ if (ocb == 0) {
+ rp.src = src + data_blk_off(src_d, n, _icb, ih, iw);
+ rtus_driver_->ker_(&rp);
+ }
+
+ p.bcast_data = rp.ws;
+ } else
+ p.bcast_data = src + data_blk_off(src_d, n, _icb, ih, iw);
+
+ kernel_->jit_ker(&p);
+ }
+
+ ocb += load_step;
+ }
+
+ iwork += bcast_step;
+ }
+ };
+
+ if (pd()->wants_padded_bias()) {
+ auto padded_bias = scratchpad(ctx).get<data_t>(key_conv_padded_bias);
+ utils::array_copy(padded_bias, bias, jcp.oc_without_padding);
+ utils::array_set(padded_bias + jcp.oc_without_padding, 0.f,
+ jcp.oc - jcp.oc_without_padding);
+ bias = padded_bias;
+ }
+
+ parallel(0, ker);
+
+ if (pd()->wants_zero_pad_dst())
+ ctx.memory(MKLDNN_ARG_DST)->zero_pad();
+}
+
+/* convolution backward wtr data */
+
+void jit_avx2_1x1_convolution_bwd_data_t::execute_backward_data(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+
+ const auto &jcp = kernel_->jcp;
+ auto rtus_space = scratchpad(ctx).get<data_t>(key_conv_rtus_space);
+
+ // TODO (Roma): remove this restriction
+ assert(jcp.stride_w == 1 && jcp.stride_h == 1);
+ const int ndims = diff_dst_d.ndims();
+
+ const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0];
+ const int stride_w = pd()->desc()->strides[ndims - 3];
+ const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0];
+ const int pad_l = pd()->desc()->padding[0][ndims - 3];
+
+ const int nb_ic = jcp.nb_load;
+ const int nb_oc = jcp.nb_reduce;
+ const int os_block = jcp.bcast_block;
+ const int nb_oc_blocking = jcp.nb_reduce_blocking;
+
+ const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast;
+
+ auto step = [](int default_step, int remaining, int tail_step) {
+ assert(default_step <= tail_step);
+ return remaining < tail_step ? remaining : default_step;
+ };
+
+ auto ker = [&](const int ithr, const int nthr) {
+ auto p = jit_1x1_conv_call_s();
+ auto rp = rtus_driver_t<avx2>::call_params_t();
+
+ int start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ int load_step = 0;
+ for (int icb = 0; icb < jcp.nb_load; icb += load_step) {
+ load_step = step(jcp.nb_load_blocking, jcp.nb_load - icb,
+ jcp.nb_load_blocking_max);
+
+ p.load_dim = this_block_size(icb * jcp.ic_block, jcp.ic,
+ load_step * jcp.ic_block);
+ rp.icb = p.load_dim / jcp.ic_block;
+
+ int bcast_step;
+ for (int iwork = start; iwork < end; iwork += bcast_step) {
+ int n{0}, g{0}, osb{0};
+ nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb,
+ jcp.nb_bcast);
+
+ bcast_step = step(jcp.nb_bcast_blocking, jcp.nb_bcast - osb,
+ jcp.nb_bcast_blocking_max);
+ bcast_step = nstl::min(bcast_step, end - iwork);
+
+ const int os = osb * os_block;
+ p.bcast_dim = this_block_size(os, jcp.os,
+ bcast_step * os_block);
+ rp.os = p.bcast_dim;
+
+ const int oh = os / jcp.ow;
+ const int ow = os % jcp.ow;
+ const int ih = nstl::max(oh * stride_h - pad_t, 0);
+ const int iw = nstl::max(ow * stride_w - pad_l, 0);
+ rp.iw_start = iw;
+
+ const int _icb = g * nb_ic + icb;
+ rp.src = diff_src + data_blk_off(diff_src_d, n, _icb, ih, iw);
+ if (pd()->rtus_.reduce_src_) {
+ rp.ws = rtus_space
+ + ithr * pd()->rtus_.space_per_thread_;
+ p.output_data = rp.ws;
+ } else
+ p.output_data = rp.src;
+
+ for (int ocb = 0; ocb < jcp.nb_reduce;
+ ocb += jcp.nb_reduce_blocking) {
+ const int _ocb = g * nb_oc + ocb;
+ size_t diff_dst_off = data_blk_off(diff_dst_d, n, _ocb, oh,
+ ow);
+ p.bcast_data = &diff_dst[diff_dst_off];
+
+ p.load_data = &weights[pd()->with_groups()
+ ? weights_d.blk_off(g, ocb, icb)
+ : weights_d.blk_off(ocb, icb)];
+
+ p.first_last_flag = ocb == 0 ? FLAG_REDUCE_FIRST : 0;
+
+ p.reduce_dim = this_block_size(ocb * jcp.oc_block, jcp.oc,
+ nb_oc_blocking * jcp.oc_block);
+
+ kernel_->jit_ker(&p);
+ }
+
+ if (pd()->rtus_.reduce_src_)
+ rtus_driver_->ker_(&rp);
+ }
+ }
+ };
+
+ parallel(0, ker);
+}
+
+/* convolution backward wtr weights */
+
+jit_avx2_1x1_convolution_bwd_weights_t::jit_avx2_1x1_convolution_bwd_weights_t(
+ const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , kernel_(nullptr)
+ , rtus_driver_(nullptr)
+{
+ kernel_ = new jit_avx2_1x1_conv_kernel_f32(pd()->jcp_, *pd()->attr());
+ reducer_weights_ =
+ new cpu_reducer_2d_t<data_type::f32>(pd()->reducer_wei_conf_);
+ reducer_bias_ = new cpu_reducer_t<data_type::f32>(pd()->reducer_bia_conf_);
+ init_rtus_driver<avx2>(this);
+}
+
+void jit_avx2_1x1_convolution_bwd_weights_t::execute_backward_weights(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS);
+ auto diff_bias_in = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0));
+ const memory_desc_wrapper diff_bias_d(pd()->diff_weights_md(1));
+
+ const auto &jcp = kernel_->jcp;
+ auto rtus_space = scratchpad.get<data_t>(key_conv_rtus_space);
+
+ data_t *diff_bias = pd()->wants_padded_bias()
+ ? scratchpad.get<data_t>(key_conv_padded_bias) : diff_bias_in;
+
+ auto reducer_bia_scratchpad = memory_tracking::grantor_t(scratchpad,
+ prefix_reducer_bia);
+ auto rb = this->reducer_bias_;
+ rb->init(reducer_bia_scratchpad);
+
+ auto reducer_wei_scratchpad = memory_tracking::grantor_t(scratchpad,
+ prefix_reducer_wei);
+ auto rw = this->reducer_weights_;
+ rw->init(reducer_wei_scratchpad);
+
+ const int ndims = diff_dst_d.ndims();
+ // TODO (Roma): remove this restriction
+ assert(jcp.stride_w == 1 && jcp.stride_h == 1);
+
+ const int nb_ic = jcp.nb_bcast;
+ const int nb_ic_blocking = jcp.nb_bcast_blocking;
+ const int bcast_work = div_up(nb_ic, nb_ic_blocking);
+
+ const int nb_oc = jcp.nb_load;
+ const int nb_oc_blocking = jcp.nb_load_blocking;
+ const int load_work = div_up(nb_oc, nb_oc_blocking);
+
+ const int sp_dim = jcp.reduce_dim;
+ const int mb_sp_work = jcp.mb * sp_dim;
+
+ const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0];
+ const int stride_w = pd()->desc()->strides[ndims - 3];
+ const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0];
+ const int pad_l = pd()->desc()->padding[0][ndims - 3];
+
+ auto step = [](int default_step, int remaining, int tail_step) {
+ assert(default_step <= tail_step);
+ return remaining < tail_step ? remaining : default_step;
+ };
+
+ auto oc_ic_sp_loop = [=](int sp_start, int sp_end, bool first_image,
+ data_t *store_to, size_t store_to_ld, const data_t *diff_dst,
+ const data_t *src, int ithr) {
+ auto p = jit_1x1_conv_call_s();
+ auto rp = rtus_driver_t<avx2>::call_params_t();
+
+ p.output_stride = store_to_ld * sizeof(float);
+ const int sp_step_def = jcp.nb_reduce_blocking * jcp.reduce_block;
+
+ int oc_b_step = 0;
+ for (int oc_b = 0; oc_b < nb_oc_blocking; oc_b += oc_b_step) {
+ oc_b_step = step(12, nb_oc_blocking - oc_b, 18);
+ p.load_dim = oc_b_step * jcp.oc_block;
+
+ int ic_b_step = 0;
+ for (int ic_b = 0; ic_b < nb_ic_blocking; ic_b += ic_b_step) {
+ ic_b_step = step(12, nb_ic_blocking - ic_b, 18);
+ p.bcast_dim = ic_b_step * jcp.ic_block;
+ rp.icb = p.bcast_dim / jcp.ic_block;
+
+ p.output_data = store_to + oc_b * store_to_ld
+ + ic_b * jcp.ic_block * jcp.oc_block;
+
+ /* spatial reduction */
+ int sp_step = 0;
+ for (int sp = sp_start; sp < sp_end; sp += sp_step) {
+ sp_step = step(sp_step_def, sp_end - sp, 192);
+ p.reduce_dim = sp_step;
+ rp.os = p.reduce_dim;
+
+ p.first_last_flag = sp == sp_start && first_image
+ ? FLAG_REDUCE_FIRST : 0;
+
+ p.load_data = diff_dst
+ + (oc_b * jcp.reduce_dim + sp) * jcp.oc_block;
+
+ if (pd()->rtus_.reduce_src_) {
+ const int oh = sp / jcp.ow;
+ const int ow = sp % jcp.ow;
+
+ const int ih = nstl::max(oh * stride_h - pad_t, 0);
+ const int iw = nstl::max(ow * stride_w - pad_l, 0);
+ rp.iw_start = iw;
+
+ rp.ws = rtus_space
+ + ithr * pd()->rtus_.space_per_thread_
+ + (ic_b * jcp.is + sp) * jcp.ic_block;
+ if (ndims == 3)
+ rp.src = src
+ + iw * src_d.blocking_desc().strides[2];
+ else
+ rp.src = src
+ + ih * src_d.blocking_desc().strides[2]
+ + iw * src_d.blocking_desc().strides[3];
+
+ if (oc_b == 0)
+ rtus_driver_->ker_(&rp);
+
+ p.bcast_data = rp.ws;
+ } else
+ p.bcast_data = src
+ + (ic_b * jcp.reduce_dim + sp) * jcp.ic_block;
+
+ kernel_->jit_ker(&p);
+ }
+ }
+ }
+ };
+
+ auto ker = [&](const int ithr, const int nthr) {
+ assert(nthr == rw->balancer().nthr_);
+
+ const int w_njobs = rw->balancer().ithr_njobs(ithr);
+ if (w_njobs == 0) return;
+
+ /* setup: independent work (oc, ic) */
+ const int w_job_start = rw->balancer().ithr_job_off(ithr);
+ int g{0}, load_i{0}, bcast_i{0};
+ nd_iterator_init(w_job_start, g, jcp.ngroups, load_i, load_work,
+ bcast_i, bcast_work);
+
+ /* setup: reduction work (mb, sp) */
+ int mb_sp_start{0}, mb_sp_end{0};
+ balance211(mb_sp_work, rw->balancer().nthr_per_group_,
+ rw->balancer().id_in_group(ithr), mb_sp_start, mb_sp_end);
+ int img_start{0}, sp_start{0};
+ nd_iterator_init(mb_sp_start, img_start, jcp.mb, sp_start, sp_dim);
+
+ /* independent work */
+ for (int iwork = 0; iwork < w_njobs; ++iwork) {
+ const int oc_b = nb_oc_blocking * load_i;
+ const int ic_b = nb_ic_blocking * bcast_i;
+
+ const int _ic_b = g * nb_ic + ic_b;
+ const int _oc_b = g * nb_oc + oc_b;
+
+ data_t *store_to;
+ size_t store_to_ld;
+
+ if (rw->balancer().nthr_per_group_ == 1) {
+ const size_t off = pd()->with_groups()
+ ? diff_weights_d.blk_off(g, oc_b, ic_b)
+ : diff_weights_d.blk_off(oc_b, ic_b);
+ store_to = &diff_weights[off];
+ store_to_ld = jcp.ic * jcp.oc_block;
+ } else {
+ const size_t off = iwork * rw->balancer().job_size_;
+ store_to =
+ rw->get_local_ptr(ithr, reducer_wei_scratchpad) + off;
+ store_to_ld = nb_ic_blocking * jcp.ic_block * jcp.oc_block;
+ }
+
+ /* reduction work */
+ int img = img_start;
+ int sp = sp_start;
+ int sp_step = 0;
+ for (int mb_sp = mb_sp_start; mb_sp < mb_sp_end; mb_sp += sp_step)
+ {
+ sp_step = nstl::min(sp_dim - sp, mb_sp_end - mb_sp);
+
+ const bool first_image = img == img_start;
+ oc_ic_sp_loop(sp, sp + sp_step, first_image, store_to,
+ store_to_ld, &diff_dst[diff_dst_d.blk_off(img, _oc_b)],
+ &src[src_d.blk_off(img, _ic_b)], ithr);
+
+ sp = 0;
+ img += 1;
+ }
+
+ nd_iterator_step(g, jcp.ngroups, load_i, load_work, bcast_i,
+ bcast_work);
+ }
+ rw->reduce(ithr, diff_weights, reducer_wei_scratchpad);
+ };
+
+ auto ker_bias = [&](int ithr, int nthr) {
+ assert(nthr == rb->balancer().nthr_);
+
+ const int b_job_start = rb->balancer().ithr_job_off(ithr);
+ const int b_njobs = rb->balancer().ithr_njobs(ithr);
+
+ if (b_njobs == 0) return;
+
+ /* reduction dimension */
+ int img_start{0}, img_end{0};
+ balance211(jcp.mb, rb->balancer().nthr_per_group_,
+ rb->balancer().id_in_group(ithr), img_start, img_end);
+
+ /* jobs */
+ int g_start{0}, ocb_start{0};
+ nd_iterator_init(b_job_start, g_start, jcp.ngroups, ocb_start, nb_oc);
+
+ for (int img = img_start; img < img_end; ++img) {
+ int g = g_start, ocb = ocb_start;
+ for (int b_job_loc = 0; b_job_loc < b_njobs; ++b_job_loc) {
+ const size_t _oc = g * nb_oc + ocb;
+
+ const data_t *d_dst = &diff_dst[diff_dst_d.blk_off(img, _oc)];
+ data_t *d_bias =
+ rb->get_local_ptr(ithr, diff_bias, reducer_bia_scratchpad)
+ + b_job_loc * rb->balancer().job_size_;
+
+ if (img == img_start)
+ for (int o = 0; o < 8; ++o) d_bias[o] = 0.;
+
+ for (int hw = 0; hw < jcp.oh * jcp.ow; ++hw) {
+ PRAGMA_OMP_SIMD()
+ for (int o = 0; o < 8; ++o)
+ d_bias[o] += d_dst[o];
+ d_dst += 8;
+ }
+
+ nd_iterator_step(g, jcp.ngroups, ocb, nb_oc);
+ }
+ }
+ rb->reduce(ithr, diff_bias, reducer_bia_scratchpad);
+ };
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ ker(ithr, nthr);
+ if (pd()->with_bias())
+ ker_bias(ithr, nthr);
+ });
+
+ /* TODO: put this in ker_bias */
+ if (pd()->wants_padded_bias()) {
+ assert(jcp.ngroups == 1);
+ for (int oc = 0; oc < jcp.oc_without_padding; ++oc)
+ diff_bias_in[oc] = diff_bias[oc];
+ }
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.hpp
new file mode 100644
index 0000000000..9762242173
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_1x1_convolution.hpp
@@ -0,0 +1,344 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX2_1x1_CONVOLUTION_HPP
+#define CPU_JIT_AVX2_1x1_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+#include "cpu_reducer.hpp"
+
+#include "jit_avx2_1x1_conv_kernel_f32.hpp"
+#include "jit_uni_1x1_conv_utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_avx2_1x1_convolution_fwd_t: public cpu_primitive_t {
+ // TODO: (Roma) Code duplication duplication! Remove with templates
+ // (maybe...)!
+ struct pd_t: public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_(), rtus_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_1x1:", avx2, ""),
+ jit_avx2_1x1_convolution_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ const convolution_desc_t *conv_d = desc();
+ const memory_desc_t *src_d = src_md();
+ rtus_prepare(this, conv_d, src_d, dst_md());
+
+ status_t status = jit_avx2_1x1_conv_kernel_f32::init_conf(jcp_,
+ *conv_d, *src_d, *weights_md(), *dst_md(), *attr());
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx2_1x1_conv_kernel_f32::init_scratchpad(scratchpad, jcp_);
+
+ rtus_prepare_space_info(this, scratchpad);
+
+ return status::success;
+ }
+
+ jit_1x1_conv_conf_t jcp_;
+ reduce_to_unit_stride_t rtus_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto wei_tag = with_groups()
+ ? utils::pick(ndims() - 3, gOIw8i8o, gOIhw8i8o)
+ : utils::pick(ndims() - 3, OIw8i8o, OIhw8i8o);
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ template <cpu_isa_t isa, typename conv_t>
+ friend void init_rtus_driver(conv_t *self);
+
+ jit_avx2_1x1_convolution_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , kernel_(nullptr), rtus_driver_(nullptr)
+ {
+ kernel_ = new jit_avx2_1x1_conv_kernel_f32(pd()->jcp_, *pd()->attr());
+ init_rtus_driver<avx2>(this);
+ }
+
+ ~jit_avx2_1x1_convolution_fwd_t() {
+ delete kernel_;
+ delete rtus_driver_;
+ }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx2_1x1_conv_kernel_f32 *kernel_;
+ rtus_driver_t<avx2> *rtus_driver_;
+};
+
+struct jit_avx2_1x1_convolution_bwd_data_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_data_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_(), rtus_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_1x1:", avx2, ""),
+ jit_avx2_1x1_convolution_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_data
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::undef, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ const convolution_desc_t *conv_d = desc();
+ const memory_desc_t *diff_src_d = diff_src_md();
+ rtus_prepare(this, conv_d, diff_src_d, diff_dst_md());
+
+ status_t status = jit_avx2_1x1_conv_kernel_f32::init_conf(jcp_,
+ *conv_d, *diff_src_d, *weights_md(), *diff_dst_md(),
+ *attr());
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx2_1x1_conv_kernel_f32::init_scratchpad(scratchpad, jcp_);
+
+ rtus_prepare_space_info(this, scratchpad);
+
+ return status::success;
+ }
+
+ jit_1x1_conv_conf_t jcp_;
+ reduce_to_unit_stride_t rtus_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto wei_tag = with_groups()
+ ? utils::pick(ndims() - 3, gOIw8o8i, gOIhw8o8i)
+ : utils::pick(ndims() - 3, OIw8o8i, OIhw8o8i);
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ template <cpu_isa_t isa, typename conv_t>
+ friend void init_rtus_driver(conv_t *self);
+
+ jit_avx2_1x1_convolution_bwd_data_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , kernel_(nullptr)
+ , rtus_driver_(nullptr)
+ {
+ kernel_ = new jit_avx2_1x1_conv_kernel_f32(pd()->jcp_, *pd()->attr());
+ init_rtus_driver<avx2>(this);
+ }
+
+ ~jit_avx2_1x1_convolution_bwd_data_t() {
+ delete kernel_;
+ delete rtus_driver_;
+ }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_data(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_data(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx2_1x1_conv_kernel_f32 *kernel_;
+ rtus_driver_t<avx2> *rtus_driver_;
+};
+
+struct jit_avx2_1x1_convolution_bwd_weights_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_weights_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_(), rtus_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_1x1:", avx2, ""),
+ jit_avx2_1x1_convolution_bwd_weights_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_weights
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ const convolution_desc_t *conv_d = desc();
+ const memory_desc_t *src_d = src_md();
+ rtus_prepare(this, conv_d, src_d, diff_dst_md());
+
+ status_t status = jit_avx2_1x1_conv_kernel_f32::init_conf(jcp_,
+ *conv_d, *src_d, *diff_weights_md(), *diff_dst_md(),
+ *attr());
+ if (status != status::success) return status;
+
+ init_balancers();
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx2_1x1_conv_kernel_f32::init_scratchpad(scratchpad, jcp_);
+
+ rtus_prepare_space_info(this, scratchpad);
+
+ auto reducer_bia_scratchpad = memory_tracking::registrar_t(
+ scratchpad, memory_tracking::names::prefix_reducer_bia);
+ reducer_bia_conf_.init_scratchpad(reducer_bia_scratchpad);
+
+ auto reducer_wei_scratchpad = memory_tracking::registrar_t(
+ scratchpad, memory_tracking::names::prefix_reducer_wei);
+ reducer_wei_conf_.init_scratchpad(reducer_wei_scratchpad);
+
+ return status::success;
+ }
+
+ jit_1x1_conv_conf_t jcp_;
+ cpu_reducer_t<data_type::f32>::conf_t reducer_bia_conf_;
+ cpu_reducer_2d_t<data_type::f32>::conf_t reducer_wei_conf_;
+ reduce_to_unit_stride_t rtus_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto wei_tag = with_groups()
+ ? utils::pick(ndims() - 3, gOIw8i8o, gOIhw8i8o)
+ : utils::pick(ndims() - 3, OIw8i8o, OIhw8i8o);
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+
+ private:
+ void init_balancers() {
+ const int ic_block = jcp_.bcast_block;
+ const int nb_ic = jcp_.nb_bcast;
+ const int nb_ic_blocking = jcp_.nb_bcast_blocking;
+ const int bcast_work = utils::div_up(nb_ic, nb_ic_blocking);
+
+ const int oc_block = jcp_.load_block;
+ const int nb_oc = jcp_.nb_load;
+ const int nb_oc_blocking = jcp_.nb_load_blocking;
+ const int load_work = utils::div_up(nb_oc, nb_oc_blocking);
+
+ const int job_size
+ = nb_oc_blocking * nb_ic_blocking * ic_block * oc_block;
+ const int njobs_x = bcast_work;
+ const int njobs_y = jcp_.ngroups * load_work;
+
+ const int max_threads = mkldnn_get_max_threads();
+ const size_t max_buffer_size = max_threads * job_size * 8;
+
+ if (with_bias()) {
+ reducer_bia_conf_.init(reduce_balancer_t(max_threads,
+ oc_block, jcp_.ngroups * jcp_.oc / oc_block,
+ jcp_.mb, max_buffer_size));
+ }
+
+ reducer_wei_conf_.init(
+ reduce_balancer_t(max_threads, job_size, njobs_y * njobs_x,
+ jcp_.mb * jcp_.nb_reduce, max_buffer_size),
+ job_size / nb_oc_blocking, nb_oc_blocking, ic_block,
+ nb_ic * ic_block * oc_block, nb_oc);
+ }
+ };
+
+ template <cpu_isa_t isa, typename conv_t>
+ friend void init_rtus_driver(conv_t *self);
+
+ jit_avx2_1x1_convolution_bwd_weights_t(const pd_t *apd);
+
+ ~jit_avx2_1x1_convolution_bwd_weights_t() {
+ delete kernel_;
+ delete rtus_driver_;
+ delete reducer_weights_;
+ delete reducer_bias_;
+ }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_weights(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_weights(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx2_1x1_conv_kernel_f32 *kernel_;
+ cpu_reducer_2d_t<data_type::f32> *reducer_weights_;
+ cpu_reducer_t<data_type::f32> *reducer_bias_;
+ rtus_driver_t<avx2> *rtus_driver_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.cpp
new file mode 100644
index 0000000000..e24770a2da
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.cpp
@@ -0,0 +1,1501 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+* Copyright 2018 YANDEX LLC
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+#include "cpu_memory.hpp"
+
+#include "jit_avx2_conv_kernel_f32.hpp"
+
+#define GET_OFF(field) offsetof(jit_conv_call_s, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+using namespace Xbyak;
+
+void jit_avx2_conv_fwd_kernel_f32::oh_step_unroll_kw(int ur_w,
+ int pad_l, int pad_r, int oc_blocks)
+{
+ int iw = jcp.iw;
+ int ih = jcp.ih;
+ int id = jcp.id;
+ int kw = jcp.kw;
+ int kh = jcp.kh;
+ int kd = jcp.kd;
+ int nb_ic = jcp.nb_ic;
+ int stride_w = jcp.stride_w;
+ int dilate_w = jcp.dilate_w + 1;
+ int ic_blk = jcp.ic_block;
+ int oc_blk = jcp.oc_block;
+
+ for (int ki = 0; ki < kw; ki++) {
+ int jj_start = nstl::max(0, div_up(pad_l - ki * dilate_w, stride_w));
+ int jj_end = ur_w
+ - nstl::max(0, div_up(ki*dilate_w+pad_r-(kw-1)*dilate_w, stride_w));
+ for (int ifm2 = 0; ifm2 < ic_blk; ifm2++) {
+ for (int jj = jj_start; jj < jj_end; jj++) {
+ size_t inp_off;
+ if (one_of(jcp.src_tag, ncw, nchw, ncdhw))
+ inp_off = sizeof(float)*((size_t)ifm2*id*ih*iw
+ + (ki*dilate_w + jj*stride_w - pad_l));
+ else
+ inp_off = sizeof(float)*((ki*dilate_w + jj*stride_w
+ - pad_l)*ic_blk + ifm2);
+ vbroadcastss(Ymm(oc_blocks * ur_w + jj),
+ make_safe_addr(aux_reg_input, inp_off, reg_long_offt));
+ }
+
+ for (int ii = 0; ii < oc_blocks; ii++) {
+ int ker_off = ii * nb_ic * kd * kh * kw * ic_blk * oc_blk
+ + ki * ic_blk * oc_blk + ifm2 * oc_blk;
+ vmovups(ymm15, ptr[aux_reg_kernel + sizeof(float) * ker_off]);
+ for (int jj = jj_start; jj < jj_end; jj++)
+ if (mayiuse(avx2))
+ vfmadd231ps(Ymm(ur_w * ii + jj),
+ Ymm(oc_blocks * ur_w + jj), ymm15);
+ else { // Intel(R) Advanced Vector Extensions (Intel(R) AVX) support
+ vmulps(ytmp, ymm15, Ymm(oc_blocks * ur_w + jj));
+ vaddps(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj), ytmp);
+ }
+ }
+ }
+ }
+}
+
+void jit_avx2_conv_fwd_kernel_f32::oh_step_nopad(int ur_w,
+ int pad_l, int pad_r, char pad_tag,
+ int oc_blocks, char oc_blocks_tag)
+{
+ Label kw_loop;
+
+ int iw = jcp.iw;
+ int ih = jcp.ih;
+ int id = jcp.id;
+ int kw = jcp.kw;
+ int kh = jcp.kh;
+ int kd = jcp.kd;
+ int nb_ic = jcp.nb_ic;
+ int stride_w = jcp.stride_w;
+ int dilate_w = jcp.dilate_w + 1;
+ int ic_blk = jcp.ic_block;
+ int oc_blk = jcp.oc_block;
+
+ xor_(ki_iter, ki_iter);
+ L(kw_loop);
+ {
+ int jj_start = 0;
+ int jj_end = ur_w;
+ for (int ifm2 = 0; ifm2 < ic_blk; ifm2++) {
+ for (int jj = jj_start; jj < jj_end; jj++) {
+ size_t inp_off;
+ if (one_of(jcp.src_tag, ncw, nchw, ncdhw))
+ inp_off = sizeof(float)*((size_t)ifm2 * id * ih * iw
+ + (jj * stride_w - pad_l));
+ else
+ inp_off = sizeof(float)*((jj * stride_w - pad_l) * ic_blk
+ + ifm2);
+ vbroadcastss(Ymm(oc_blocks * ur_w + jj),
+ make_safe_addr(aux_reg_input, inp_off, reg_long_offt));
+ }
+ for (int ii = 0; ii < oc_blocks; ii++) {
+ int aux_kernel_offset =
+ ii * nb_ic * kd * kh * kw * ic_blk * oc_blk + ifm2 * oc_blk;
+ vmovups(ymm15, ptr[aux_reg_kernel
+ + sizeof(float) * aux_kernel_offset]);
+ for (int jj = jj_start; jj < jj_end; jj++)
+ if (mayiuse(avx2))
+ vfmadd231ps(Ymm(ur_w * ii + jj),
+ Ymm(oc_blocks * ur_w + jj), ymm15);
+ else { // Intel AVX support
+ vmulps(ytmp, ymm15, Ymm(oc_blocks * ur_w + jj));
+ vaddps(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj), ytmp);
+ }
+ }
+ }
+ add(aux_reg_kernel, sizeof(float) * oc_blk * ic_blk);
+ add(aux_reg_input, sizeof(float) * (one_of(jcp.src_tag, ncw, nchw, ncdhw)
+ ? dilate_w : ic_blk * dilate_w));
+
+ inc(ki_iter);
+ cmp(ki_iter, kw);
+ jl(kw_loop, T_NEAR);
+ }
+}
+
+void jit_avx2_conv_fwd_kernel_f32::width_blk_step(int ur_w,
+ int pad_l, int pad_r, char pad_tag,
+ int oc_blocks, char oc_blocks_tag)
+{
+ int iw = jcp.iw;
+ int kw = jcp.kw;
+ int ow = jcp.ow;
+ int oh = jcp.oh;
+ int od = jcp.od;
+ int dilate_h = jcp.dilate_h + 1;
+ int dilate_w = jcp.dilate_w + 1;
+ int ic_blk = jcp.ic_block;
+ int oc_blk = jcp.oc_block;
+ const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw)
+ ? 1 : ic_blk;
+ const int inp_off = one_of(jcp.src_tag, ncw, nchw, ncdhw)
+ ? dilate_w : ic_blk * dilate_w;
+
+ Label init_done, init_first;
+
+ if (!jcp.with_sum) {
+ test(reg_ci_flag, FLAG_IC_FIRST);
+ jne(init_first, T_NEAR);
+ }
+
+ for (int ii = 0; ii < oc_blocks; ii++) {
+ for (int jj = 0; jj < ur_w; jj++) {
+ size_t offt =
+ sizeof(float) * ((size_t)ii * od * oh * ow + jj) * oc_blk;
+ vmovups(Ymm(ur_w * ii + jj),
+ make_safe_addr(reg_output, offt, reg_long_offt));
+ }
+ }
+
+ if (jcp.with_sum && jcp.with_bias) {
+ test(reg_ci_flag, FLAG_IC_FIRST);
+ je(init_done, T_NEAR);
+
+ for (int ii = 0; ii < oc_blocks; ii++)
+ for (int jj = 0; jj < ur_w; jj++)
+ vaddps(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj),
+ yword[reg_bias + sizeof(float) * ii * oc_blk]);
+ }
+
+ jmp(init_done);
+
+ L(init_first);
+ if (this->jcp.with_bias) {
+ for (int ii = 0; ii < oc_blocks; ii++)
+ for (int jj = 0; jj < ur_w; jj++)
+ vmovups(Ymm(ur_w * ii + jj),
+ yword[reg_bias + sizeof(float) * ii * oc_blk]);
+ } else {
+ for (int ii = 0; ii < oc_blocks; ii++)
+ for (int jj = 0; jj < ur_w; jj++)
+ uni_vpxor(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj));
+ }
+
+ L(init_done);
+
+ if (one_of(jcp.ndims, 3, 4)) {
+ mov(aux_reg_input, reg_input);
+ mov(aux_reg_kernel, reg_kernel);
+ }
+
+ Label skip_kh_loop, skip_kd_loop, kd_loop;
+ if (jcp.ndims == 5) {
+ push(reg_output);
+ push(oi_iter);
+
+ mov(reg_ki, ptr[param1 + GET_OFF(kd_padding)]);
+ mov(aux_reg_ker_d, ptr[param1 + GET_OFF(filt)]);
+ mov(aux_reg_inp_d, reg_input);
+
+ if ((jcp.dilate_d >= jcp.id)
+ || (jcp.kd - 1) * (jcp.dilate_d + 1) < jcp.f_pad) {
+ cmp(reg_ki, 0);
+ je(skip_kd_loop, T_NEAR);
+ }
+ L(kd_loop);
+ mov(kj, ptr[param1 + GET_OFF(kh_padding)]);
+ } else {
+ mov(kj, reg_kh);
+ }
+
+ if (jcp.ndims == 5) {
+ mov(aux_reg_input, aux_reg_inp_d);
+ mov(aux_reg_kernel, aux_reg_ker_d);
+ }
+
+ if ((jcp.dilate_h >= jcp.ih)
+ || (jcp.kh - 1) * (jcp.dilate_h + 1) < nstl::max(jcp.t_pad, jcp.b_pad)) {
+ cmp(kj, 0);
+ je(skip_kh_loop, T_NEAR);
+ }
+ Label kh_loop;
+ L(kh_loop);
+ {
+ if (jcp.kw >= 5 && pad_l == 0 && pad_r == 0) {
+ oh_step_nopad(ur_w, pad_l, pad_r, pad_tag, oc_blocks,
+ oc_blocks_tag);
+ sub(aux_reg_input, sizeof(float) * kw * inp_off);
+ add(aux_reg_input, sizeof(float) * iw * dilate_h * inp_mult);
+ } else {
+ oh_step_unroll_kw(ur_w, pad_l, pad_r, oc_blocks);
+ add(aux_reg_kernel, sizeof(float) * kw * oc_blk * ic_blk);
+ add(aux_reg_input, sizeof(float) * iw * dilate_h * inp_mult);
+ }
+
+ dec(kj);
+ cmp(kj, 0);
+ jg(kh_loop, T_NEAR);
+ }
+
+ L(skip_kh_loop);
+
+ if (jcp.ndims == 5) {
+ add(aux_reg_inp_d,
+ sizeof(float) * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * inp_mult);
+ add(aux_reg_ker_d, sizeof(float) * jcp.kw * jcp.kh * jcp.oc_block
+ * jcp.ic_block);
+
+ dec(reg_ki);
+ cmp(reg_ki, 0);
+ jg(kd_loop, T_NEAR);
+ L(skip_kd_loop);
+
+ pop(oi_iter);
+ pop(reg_output);
+ }
+
+ Label regular_store;
+
+ if (jcp.with_eltwise) {
+ test(reg_ci_flag, FLAG_IC_LAST);
+ je(regular_store, T_NEAR);
+
+ eltwise_injector_->compute_vector_range(0, oc_blocks * ur_w);
+
+ L(regular_store);
+ }
+
+ for (int ii = 0; ii < oc_blocks; ii++) {
+ for (int jj = 0; jj < ur_w; jj++) {
+ const size_t o_off
+ = sizeof(float) * ((size_t)ii * od * oh * ow + jj) * oc_blk;
+ Ymm reg_out = Ymm(ur_w * ii + jj);
+ vmovups(make_safe_addr(reg_output, o_off, reg_long_offt), reg_out);
+ }
+ }
+}
+
+inline void jit_avx2_conv_fwd_kernel_f32::solve_common(
+ int oc_blocks, char oc_blocks_tag)
+{
+ int ur_w = jcp.ur_w;
+ int ur_w_tail = jcp.ur_w_tail;
+ int n_oi = jcp.ow / ur_w;
+ int iw = jcp.iw;
+ int kw = jcp.kw;
+ int ic_blk = jcp.ic_block;
+ int oc_blk = jcp.oc_block;
+ int dilate_w = jcp.dilate_w + 1;
+ int str_w = jcp.stride_w;
+ const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw) ? 1 : ic_blk;
+
+ int l_pad = jcp.l_pad;
+ int r_pad = nstl::max(0, (int(jcp.ow) - 1) * str_w + (kw - 1) * dilate_w
+ - (iw + l_pad - 1));
+ int r_pad1 = (ur_w * n_oi - 1) * str_w + (kw - 1) * dilate_w
+ - (iw + l_pad - 1);
+ if (r_pad1 > 0) n_oi--;
+
+ if (l_pad > 0) {
+ n_oi--;
+ if (n_oi < 0 && r_pad1 > 0)
+ width_blk_step(ur_w, l_pad, r_pad1,
+ 'l', oc_blocks, oc_blocks_tag); // "lrpad"
+ else
+ width_blk_step(ur_w, l_pad, 0,
+ 'l', oc_blocks, oc_blocks_tag); // "lpad"
+ add(reg_input, sizeof(float) * (ur_w * str_w - l_pad) * inp_mult);
+ add(reg_output, sizeof(float) * ur_w * oc_blk);
+ }
+
+ Label ow_loop;
+ xor_(oi_iter, oi_iter);
+
+ if (n_oi > 0) {
+ L(ow_loop);
+
+ width_blk_step(ur_w, 0, 0,
+ 'm', oc_blocks, oc_blocks_tag); // "middle"
+ add(reg_input, sizeof(float) * ur_w * str_w * inp_mult);
+ add(reg_output, sizeof(float) * ur_w * oc_blk);
+
+ inc(oi_iter);
+ cmp(oi_iter, n_oi);
+ jl(ow_loop, T_NEAR);
+ }
+
+ if (r_pad1 > 0 && n_oi >=0) {
+ width_blk_step(ur_w, 0, r_pad1,
+ 'r', oc_blocks, oc_blocks_tag); // "rpad"
+ add(reg_input, sizeof(float) * ur_w * str_w * inp_mult);
+ add(reg_output, sizeof(float) * ur_w * oc_blk);
+ }
+
+ if (ur_w_tail != 0)
+ width_blk_step(ur_w_tail, 0, r_pad,
+ 't', oc_blocks, oc_blocks_tag); // "tail"
+}
+
+void jit_avx2_conv_fwd_kernel_f32::generate()
+{
+ this->preamble();
+
+ mov(reg_input, ptr[this->param1 + GET_OFF(src)]);
+ mov(reg_output, ptr[this->param1 + GET_OFF(dst)]);
+ mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]);
+ if (jcp.with_bias)
+ mov(reg_bias, ptr[this->param1 + GET_OFF(bias)]);
+ mov(reg_kh, ptr[this->param1 + GET_OFF(kh_padding)]);
+ mov(reg_ci_flag, ptr[this->param1 + GET_OFF(flags)]);
+ mov(reg_oc_blocks, ptr[this->param1 + GET_OFF(oc_blocks)]);
+
+ int nb_oc_tail = jcp.nb_oc % jcp.nb_oc_blocking;
+ Label tail, exit;
+
+ if (jcp.nb_oc > jcp.nb_oc_blocking) {
+ cmp(reg_oc_blocks, jcp.nb_oc_blocking);
+ jne(nb_oc_tail ? tail : exit, T_NEAR);
+
+ solve_common(jcp.nb_oc_blocking, '0' + jcp.nb_oc_blocking);
+ jmp(exit, T_NEAR);
+
+ if (nb_oc_tail) {
+ L(tail);
+ cmp(reg_oc_blocks, nb_oc_tail);
+ jne(exit, T_NEAR);
+ solve_common(nb_oc_tail, '0' + nb_oc_tail);
+ }
+
+ L(exit);
+ } else if (jcp.nb_oc == jcp.nb_oc_blocking) {
+ solve_common(jcp.nb_oc_blocking, '0' + jcp.nb_oc_blocking);
+ } else {
+ solve_common(nb_oc_tail, '0' + nb_oc_tail);
+ }
+
+ this->postamble();
+
+ if (jcp.with_eltwise)
+ eltwise_injector_->prepare_table();
+}
+
+bool jit_avx2_conv_fwd_kernel_f32::post_ops_ok(
+ jit_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ const auto &p = attr.post_ops_;
+
+ auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); };
+ auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); };
+
+ switch (p.len_) {
+ case 0: return true; // no post_ops
+ case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise
+ case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise
+ default: return false;
+ }
+
+ return false;
+}
+
+status_t jit_avx2_conv_fwd_kernel_f32::init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d,
+ const primitive_attr_t &attr)
+{
+ if (!mayiuse(avx)) return status::unimplemented;
+
+ jcp.prop_kind = cd.prop_kind;
+
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ int ndims = src_d.ndims();
+ jcp.ndims = ndims;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+
+ jcp.id = (ndims == 5) ? src_d.dims()[2] : 1;
+ jcp.ih = (ndims == 3) ? 1 : src_d.dims()[ndims-2];
+ jcp.iw = src_d.dims()[ndims-1];
+ jcp.od = (ndims == 5) ? dst_d.dims()[2] : 1;
+ jcp.oh = (ndims == 3) ? 1 :dst_d.dims()[ndims-2];
+ jcp.ow = dst_d.dims()[ndims-1];
+ jcp.kd = (ndims == 5) ? weights_d.dims()[with_groups + 2] : 1;
+ jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + ndims-2];
+ jcp.kw = weights_d.dims()[with_groups + ndims-1];
+
+ jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0;
+ jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4];
+ jcp.l_pad = cd.padding[0][ndims-3];
+ jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1;
+ jcp.stride_h = (ndims == 3) ? 1 :cd.strides[ndims-4];
+ jcp.stride_w = cd.strides[ndims-3];
+
+ jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0;
+ jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4];
+ jcp.dilate_w = cd.dilates[ndims-3];
+
+ jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1)
+ - (jcp.ih + jcp.t_pad - 1);
+
+ if (ndims == 3) {
+ jcp.src_tag = src_d.matches_one_of_tag(ncw, nwc, nCw8c);
+ jcp.wei_tag = weights_d.matches_one_of_tag(
+ Owi8o, gOwi8o, OIw8i8o, gOIw8i8o);
+ jcp.dst_tag = dst_d.matches_one_of_tag(nCw8c);
+ } else if (ndims == 4) {
+ jcp.src_tag = src_d.matches_one_of_tag(nchw, nhwc, nChw8c);
+ jcp.wei_tag = weights_d.matches_one_of_tag(
+ Ohwi8o, gOhwi8o, OIhw8i8o, gOIhw8i8o);
+ jcp.dst_tag = dst_d.matches_one_of_tag(nChw8c);
+ } else if (ndims == 5) {
+ jcp.src_tag = src_d.matches_one_of_tag(ncdhw, ndhwc, nCdhw8c);
+ jcp.wei_tag = weights_d.matches_one_of_tag(
+ Odhwi8o, gOdhwi8o, OIdhw8i8o, gOIdhw8i8o);
+ jcp.dst_tag = dst_d.matches_one_of_tag(nCdhw8c);
+ }
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ jcp.with_sum = p.find(primitive_kind::sum) != -1;
+ const int eltwise_ind = p.find(primitive_kind::eltwise);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise) {
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+ if (!mayiuse(avx2) && jcp.eltwise.alg != alg_kind::eltwise_relu)
+ return status::unimplemented;
+ }
+
+ const int simd_w = 8;
+ const bool flat = jcp.ic < simd_w;
+ const bool mimo = !flat;
+
+
+ /* Grouped channel offset to support 'non-blocked data' format for
+ * convolution sizes with '(input_channel / ngroups) < simd' */
+ jcp.nonblk_group_off =
+ one_of(jcp.src_tag, ncw, nchw, ncdhw) && jcp.ngroups > 1 ? jcp.ic : 1;
+
+ bool ok_to_pad_channels = true
+ && jcp.ngroups == 1;
+
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ if (mimo)
+ jcp.ic = rnd_up(jcp.ic, simd_w);
+ }
+
+ bool args_ok = true
+ && IMPLICATION(flat, true
+ && one_of(jcp.src_tag, ncw, nwc, nchw, nhwc, ncdhw, ndhwc)
+ && one_of(jcp.wei_tag, Owi8o, gOwi8o, Ohwi8o, gOhwi8o, Odhwi8o,
+ gOdhwi8o))
+ && IMPLICATION(mimo, true
+ && one_of(jcp.src_tag, nCw8c, nChw8c, nCdhw8c)
+ && one_of(jcp.wei_tag, OIw8i8o, gOIw8i8o, OIhw8i8o, gOIhw8i8o,
+ OIdhw8i8o, gOIdhw8i8o))
+ && one_of(jcp.dst_tag, nCw8c, nChw8c, nCdhw8c);
+ if (!args_ok) return status::unimplemented;
+
+ jcp.ur_h = 1; /* no code-unrolling by h so far */
+ jcp.ur_w = 3;
+
+ jcp.oc_block = simd_w;
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+
+ jcp.nb_oc_blocking = 4; /* the optimal value for the kernel */
+
+ // Intel AVX and Intel AVX2 kernels need 2 and 1 temporary YMMs, respectively
+ // Thus, we can only assign 14 or 15 YMMs for data storage
+ const int num_avail_regs = mayiuse(avx2) ? 15 : 14;
+ if (!mayiuse(avx2)) {
+ if ((jcp.nb_oc_blocking + 1) * jcp.ur_w > num_avail_regs) {
+ // current register assignment requires more YMMs than available
+ // adjust one of nb_oc_block, ur_w preserving to ur_w >= l_pad
+ if (jcp.ur_w > jcp.l_pad && jcp.ur_w > 1)
+ jcp.ur_w -= 1;
+ else
+ for (int b = 3; b > 1; b--)
+ if (jcp.nb_oc % b == 0) {
+ jcp.nb_oc_blocking = b;
+ break;
+ }
+ }
+ }
+
+ if (jcp.ow < jcp.ur_w) jcp.ur_w = jcp.ow;
+ jcp.ur_w_tail = jcp.ow % jcp.ur_w;
+
+ args_ok = true
+ && jcp.oc % simd_w == 0
+ && jcp.l_pad <= jcp.ur_w
+ && IMPLICATION(jcp.kw > 7, (jcp.t_pad == 0 && jcp.l_pad == 0)
+ || (jcp.stride_w == 1 && jcp.stride_h == 1))
+ && IMPLICATION(mimo, jcp.ic % simd_w == 0);
+ if (!args_ok) return status::unimplemented;
+
+ int r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1));
+
+ if (r_pad_no_tail > jcp.ur_w * jcp.stride_w && jcp.ow / jcp.ur_w > 1) {
+ /* recalculate ur_w, nb_oc_blocking and ur_w_tail */
+ jcp.ur_w = nstl::min(r_pad_no_tail / jcp.stride_w + jcp.ur_w_tail,
+ nstl::min(jcp.ow, num_avail_regs / 2));
+ jcp.nb_oc_blocking = (num_avail_regs - jcp.ur_w) / jcp.ur_w;
+ jcp.ur_w_tail = jcp.ow % jcp.ur_w;
+ /* check again ... */
+ r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1));
+ if (jcp.ur_w < nstl::max(jcp.l_pad, r_pad_no_tail))
+ return status::unimplemented;
+ }
+ assert(jcp.nb_oc_blocking > 0);
+ assert(jcp.ur_w * (jcp.nb_oc_blocking + 1) <= num_avail_regs);
+
+ jcp.ic_block = (jcp.ic % simd_w != 0) ? jcp.ic : simd_w;
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+
+ if (one_of(jcp.prop_kind, forward_training, forward_inference)) {
+ jcp.nb_ic_blocking = 12;
+ jcp.nb_ic_blocking_max = 16;
+ } else {
+ jcp.nb_ic_blocking = 1;
+ jcp.nb_ic_blocking_max = jcp.nb_ic_blocking;
+ }
+
+ return status::success;
+}
+
+void jit_avx2_conv_fwd_kernel_f32::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) {
+ if (jcp.with_bias && jcp.oc != jcp.oc_without_padding)
+ scratchpad.book(key_conv_padded_bias, sizeof(float) * jcp.oc);
+}
+
+void jit_avx2_conv_bwd_data_kernel_f32::compute_loop(int ur_w, int l_overflow,
+ int r_overflow)
+{
+ int kw = jcp.kw;
+ int kh = jcp.kh;
+ int kd = jcp.kd;
+ int iw = jcp.iw;
+ int ih = jcp.ih;
+ int id = jcp.id;
+ int ow = jcp.ow;
+
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ int nb_ic_block = jcp.nb_ic_blocking;
+ int stride_w = jcp.stride_w;
+ int stride_h = jcp.stride_h;
+
+ Label kd_loop, skip_kd_loop;
+ Label oc_loop, skip_oc_loop;
+
+ for (int ii = 0; ii < nb_ic_block; ii++)
+ for (int jj = 0; jj < ur_w; jj++) {
+ uni_vpxor(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj),
+ Ymm(ur_w * ii + jj));
+ }
+
+ if (one_of(jcp.ndims, 3, 4)) {
+ cmp(reg_channel_work, 0);
+ jle(skip_oc_loop, T_NEAR);
+ xor_(reg_channel, reg_channel);
+
+ mov(aux_reg_ddst_oc_loop, reg_ddst);
+ mov(aux_reg_kernel_oc_loop, reg_kernel);
+
+ L(oc_loop);
+ mov(aux_reg_ddst, aux_reg_ddst_oc_loop);
+ mov(aux_reg_kernel, aux_reg_kernel_oc_loop);
+ }
+
+ if (jcp.ndims == 5) {
+ assert(jcp.nb_oc_blocking == 1);
+ push(oi_iter);
+
+ mov(reg_ki, ptr[this->param1 + GET_OFF(kd_padding)]);
+ mov(aux_reg_dst_d, reg_ddst);
+ mov(aux_reg_ker_d, ptr[this->param1 + GET_OFF(filt)]);
+
+ L(kd_loop);
+ mov(kj, ptr[this->param1 + GET_OFF(kh_padding)]);
+ } else {
+ mov(kj, reg_kh);
+ }
+
+ if (jcp.ndims == 5) {
+ mov(aux_reg_ddst, aux_reg_dst_d);
+ mov(aux_reg_kernel, aux_reg_ker_d);
+ }
+
+ Label kh_loop, skip_kh_loop;
+ cmp(kj, 0);
+ jle(skip_kh_loop, T_NEAR);
+ L(kh_loop); {
+ for (int ki = 0; ki < kw; ki++) {
+ int jj_start = get_iw_start(ki, l_overflow); // 0;
+ int jj_end = get_iw_end(ur_w, ki, r_overflow); // ur_w;
+ for (int ofm2 = 0; ofm2 < jcp.oc_block; ofm2++) {
+
+ for (int jj = jj_start ; jj < jj_end; jj += stride_w) {
+ int aux_output_offset
+ = (jj + jcp.l_pad - ki) / stride_w * jcp.oc_block + ofm2;
+ vbroadcastss(Ymm(nb_ic_block * ur_w + jj / stride_w),
+ ptr[aux_reg_ddst
+ + sizeof(float) * aux_output_offset]);
+ }
+
+ for (int ii = 0; ii < nb_ic_block; ii++) {
+ int aux_kernel_offset
+ = ii * kd * kh * kw * jcp.ic_block * jcp.oc_block
+ + ki * jcp.ic_block * jcp.oc_block
+ + ofm2 * jcp.ic_block;
+ vmovups(ymm15,
+ ptr[aux_reg_kernel
+ + sizeof(float) * aux_kernel_offset]);
+ for (int jj = jj_start; jj < jj_end; jj += stride_w)
+ vfmadd231ps(Ymm(ur_w * ii + jj),
+ Ymm(nb_ic_block * ur_w + jj / stride_w), ymm15);
+ }
+ }
+ }
+ add(aux_reg_kernel, sizeof(float) * stride_h * kw * oc_block
+ * ic_block);
+ sub(aux_reg_ddst, sizeof(float) * ow * oc_block);
+
+ dec(kj);
+ cmp(kj, 0);
+ jg(kh_loop, T_NEAR);
+ }
+ L(skip_kh_loop);
+
+ if (jcp.ndims == 5) {
+ sub(aux_reg_dst_d,
+ sizeof(float) * (jcp.dilate_d + 1) * jcp.oh * ow * ic_block);
+ add(aux_reg_ker_d,
+ sizeof(float) * jcp.kw * jcp.kh * oc_block * ic_block);
+
+ dec(reg_ki);
+ cmp(reg_ki, 0);
+ jg(kd_loop, T_NEAR);
+ L(skip_kd_loop);
+
+ pop(oi_iter);
+ }
+
+ if (one_of(jcp.ndims, 3, 4)) {
+ int ddst_oc_shift = sizeof(float) * jcp.od * jcp.oh * jcp.ow
+ * jcp.oc_block;
+ int kernel_oc_shift = sizeof(float) * jcp.kd * jcp.kh * jcp.kw
+ * jcp.ic * jcp.oc_block;
+
+ add(aux_reg_ddst_oc_loop, ddst_oc_shift);
+ add(aux_reg_kernel_oc_loop, kernel_oc_shift);
+
+ inc(reg_channel);
+ cmp(reg_channel, reg_channel_work);
+ jl(oc_loop, T_NEAR);
+
+ L(skip_oc_loop);
+ mov(reg_channel, ptr[param1 + GET_OFF(channel)]);
+ }
+
+ Label no_update_label;
+ cmp(reg_channel, 0);
+ je(no_update_label, T_NEAR);
+ for (int ii = 0; ii < nb_ic_block; ii++) {
+ for (int jj = 0; jj < ur_w; jj++) {
+ size_t offt =
+ sizeof(float) * ((size_t)ii * id * ih * iw + jj) * ic_block;
+ vmovups(Ymm(15),
+ make_safe_addr(reg_dsrc, offt, reg_long_offt));
+ vaddps(Ymm(ur_w * ii + jj), Ymm(ur_w * ii + jj),
+ Ymm(15));
+
+ }
+ }
+ L(no_update_label);
+
+ for (int ii = 0; ii < nb_ic_block; ii++)
+ for (int jj = 0; jj < ur_w; jj++) {
+ size_t offt =
+ sizeof(float) * ((size_t)ii * id * ih * iw + jj) * ic_block;
+ vmovups(make_safe_addr(reg_dsrc, offt, reg_long_offt),
+ Ymm(ur_w * ii + jj));
+ }
+}
+
+void jit_avx2_conv_bwd_data_kernel_f32::generate() {
+ preamble();
+
+ mov(reg_dsrc, ptr[this->param1 + GET_OFF(src)]);
+ mov(reg_ddst, ptr[this->param1 + GET_OFF(dst)]);
+ mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]);
+ mov(reg_kh, ptr[this->param1 + GET_OFF(kh_padding)]);
+ mov(reg_channel, ptr[param1 + GET_OFF(channel)]);
+ mov(reg_channel_work, ptr[param1 + GET_OFF(ch_blocks)]);
+
+ int ddst_shift = sizeof(float) * (jcp.ur_w / jcp.stride_w) * jcp.ic_block;
+ int dsrc_shift = sizeof(float) * jcp.ur_w * jcp.oc_block;
+
+ int l_overflow = nstl::max(0, (jcp.kw - 1 - jcp.l_pad) / jcp.stride_w);
+ int r_overflow = nstl::max(0, (jcp.kw - 1
+ - nstl::max(0, jcp.r_pad)) / jcp.stride_w);
+ int r_overflow1 = nstl::max(0, (jcp.kw - 1
+ - nstl::max(0, jcp.r_pad) - jcp.ur_w_tail) / jcp.stride_w);
+
+ int n_oi = jcp.iw / jcp.ur_w;
+ if (r_overflow1 > 0)
+ n_oi--;
+
+ if (jcp.ur_w == jcp.iw) {
+ compute_loop(jcp.ur_w, l_overflow, r_overflow);
+ } else if (n_oi == 0) {
+ compute_loop(jcp.ur_w, l_overflow, r_overflow1);
+ add(reg_dsrc, dsrc_shift);
+ add(reg_ddst, ddst_shift);
+ if (jcp.ur_w_tail != 0)
+ compute_loop(jcp.ur_w_tail, 0, r_overflow);
+ } else {
+ xor_(oi_iter, oi_iter);
+ if (l_overflow > 0) {
+ compute_loop(jcp.ur_w, l_overflow, 0);
+ add(reg_dsrc, dsrc_shift);
+ add(reg_ddst, ddst_shift);
+ inc(oi_iter);
+ }
+
+ if ((l_overflow <= 0 && n_oi > 0) || (l_overflow > 0 && n_oi > 1)) {
+ Label ow_loop;
+ L(ow_loop); {
+ compute_loop(jcp.ur_w, 0, 0);
+ add(reg_dsrc, dsrc_shift);
+ add(reg_ddst, ddst_shift);
+ inc(oi_iter);
+ cmp(oi_iter, n_oi); jl(ow_loop, T_NEAR);
+ }
+ }
+
+ if (r_overflow1 > 0 ) {
+ compute_loop(jcp.ur_w, 0, r_overflow1);
+ add(reg_dsrc, dsrc_shift);
+ add(reg_ddst, ddst_shift);
+ }
+
+ if (jcp.ur_w_tail != 0)
+ compute_loop(jcp.ur_w_tail, 0, r_overflow);
+ }
+
+ this->postamble();
+}
+
+status_t jit_avx2_conv_bwd_data_kernel_f32::init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &diff_src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &diff_dst_d)
+{
+ if (!mayiuse(avx2)) return status::unimplemented;
+
+ const bool with_groups = weights_d.ndims() == diff_src_d.ndims() + 1;
+
+ int ndims = diff_src_d.ndims();
+ jcp.ndims = ndims;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = diff_src_d.dims()[0];
+
+ jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = diff_src_d.dims()[1] / jcp.ngroups;
+
+ jcp.id = (ndims == 5) ? diff_src_d.dims()[2] : 1;
+ jcp.ih = (ndims == 3) ? 1 : diff_src_d.dims()[ndims-2];
+ jcp.iw = diff_src_d.dims()[ndims-1];
+ jcp.od = (ndims == 5) ? diff_dst_d.dims()[2] : 1;
+ jcp.oh = (ndims == 3) ? 1 : diff_dst_d.dims()[ndims-2];
+ jcp.ow = diff_dst_d.dims()[ndims-1];
+
+ jcp.kd = (ndims == 5) ? weights_d.dims()[with_groups + 2] : 1;
+ jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + ndims - 2];
+ jcp.kw = weights_d.dims()[with_groups + ndims - 1];
+
+ jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0;
+ jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4];
+ jcp.l_pad = cd.padding[0][ndims-3];
+
+ jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1;
+ jcp.stride_h = (ndims == 3) ? 1 : cd.strides[ndims-4];
+ jcp.stride_w = cd.strides[ndims-3];
+
+ jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0;
+ jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4];
+ jcp.dilate_w = cd.dilates[ndims-3];
+
+ const int simd_w = 8;
+
+ /* derivatives */
+ jcp.idp = jcp.id + 2 * jcp.f_pad;
+ jcp.ihp = jcp.ih + 2 * jcp.t_pad;
+ jcp.iwp = jcp.iw + 2 * jcp.l_pad;
+ jcp.ohp = jcp.oh; /* do we really need */
+ jcp.owp = jcp.ow; /* padded output ??? */
+
+ bool ok_to_pad_channels = true
+ && jcp.ngroups == 1;
+
+ /* gemm-based convolution performs better in these cases */
+ if (jcp.ic < simd_w && jcp.kw > 3 && jcp.stride_w > 1)
+ return status::unimplemented;
+
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ jcp.ic = rnd_up(jcp.ic, simd_w);
+ }
+
+ jcp.ic_block = (jcp.ic % simd_w) ? 1 : simd_w;
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+
+ jcp.oc_block = simd_w;
+ if (jcp.oc % jcp.oc_block) return status::unimplemented;
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+
+ jcp.ur_h = 1; /* no code-unrolling by h so far */
+ jcp.nb_ic_blocking = 1;
+ jcp.nb_oc_blocking = 1;
+ jcp.ur_w = 1;
+
+ if(one_of(ndims, 3, 4) && jcp.ow < 40)
+ jcp.nb_oc_blocking = jcp.ow < 15 ? 4 : 2;
+
+ if (ndims == 3) {
+ jcp.src_tag = diff_src_d.matches_one_of_tag(nCw8c);
+ jcp.wei_tag = weights_d.matches_one_of_tag(OIw8i8o, gOIw8o8i);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(nCw8c);
+ } else if (ndims == 4) {
+ jcp.src_tag = diff_src_d.matches_one_of_tag(nChw8c);
+ jcp.wei_tag = weights_d.matches_one_of_tag(OIhw8o8i, gOIhw8o8i);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(nChw8c);
+ } else if (ndims == 5) {
+ jcp.src_tag = diff_src_d.matches_one_of_tag(nCdhw8c);
+ jcp.wei_tag = weights_d.matches_one_of_tag(OIdhw8o8i, gOIdhw8o8i);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(nCdhw8c);
+ }
+
+ bool args_ok = true
+ && one_of(jcp.src_tag, nCw8c, nChw8c, nCdhw8c)
+ && one_of(jcp.wei_tag, gOIw8o8i, OIw8i8o, gOIhw8o8i, OIhw8o8i,
+ gOIdhw8o8i, OIdhw8o8i)
+ && one_of(jcp.dst_tag, nCw8c, nChw8c, nCdhw8c)
+ && jcp.stride_w == jcp.stride_h
+ && jcp.stride_d == 1
+ && jcp.dilate_d == 0
+ && jcp.dilate_h == 0
+ && jcp.dilate_w == 0
+ && jcp.ic % simd_w == 0
+ && jcp.oc % simd_w == 0
+ && jcp.od == (jcp.idp - jcp.kd) / jcp.stride_d + 1
+ && jcp.oh == (jcp.ihp - jcp.kh) / jcp.stride_h + 1
+ && jcp.ow == (jcp.iwp - jcp.kw) / jcp.stride_w + 1;
+ if (!args_ok) return status::unimplemented;
+ jcp.r_pad = (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad;
+ jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad;
+ int l_overflow = nstl::max(0, (jcp.kw - 1 - jcp.l_pad) / jcp.stride_w);
+
+ const int max_regs = 15; /* Maximun number of registers available for
+ result accumulation and delta dst data.
+ One additional register is reserved for weights
+ data. */
+
+ /* Find the best blocking with maximum number of fma instructions
+ per ur_w * nb_ic_blocking compute loops. Number of required registers
+ is num_regs = ur_w * nb_ic_blocking + ur_w / stride_w <= max_regs.
+ ur_w must be divisible by stride_w */
+ if (jcp.stride_w + 1 > max_regs) /* Minimal possible registers
+ distribution exceeds max_regs */
+ return status::unimplemented;
+
+ int best_nfmas = 0;
+ for (int b = 1; b <= 4; b++)
+ {
+ if (jcp.nb_ic % b != 0)
+ continue;
+
+ for (int u = jcp.stride_w;
+ u * b + u / jcp.stride_w <= max_regs && u < jcp.iw + jcp.stride_w;
+ u += jcp.stride_w)
+ {
+ int ur_w = nstl::min(u, jcp.iw);
+ /* maximum 1 step with l_overflow so far */
+ if (l_overflow * jcp.stride_w > ur_w && ur_w != jcp.iw)
+ continue;
+ int nfmas = utils::div_up(ur_w, jcp.stride_w) * b;
+ if (nfmas > best_nfmas
+ || (nfmas == best_nfmas && jcp.ur_w < ur_w)) {
+ jcp.ur_w = ur_w;
+ jcp.nb_ic_blocking = b;
+ best_nfmas = nfmas;
+ }
+ }
+ }
+ if (best_nfmas == 0) /* can't find appropriate blocking */
+ return status::unimplemented;
+
+ jcp.ur_w_tail = jcp.iw % jcp.ur_w;
+
+ int r_overflow_no_tail = nstl::max(0, (jcp.kw - 1 - jcp.ur_w_tail
+ - nstl::max(0, jcp.r_pad) - jcp.ur_w_tail) / jcp.stride_w);
+ /* maximum 1 ur_w block with r_overflow so far */
+ if (r_overflow_no_tail * jcp.stride_w > jcp.ur_w)
+ return status::unimplemented;
+
+ if ((jcp.iw > jcp.ur_w) && (jcp.ur_w % jcp.stride_w != 0))
+ return status::unimplemented;
+
+ return status::success;
+}
+
+void jit_avx2_conv_bwd_data_kernel_f32::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) {
+ UNUSED(scratchpad);
+ UNUSED(jcp);
+}
+
+void jit_avx2_conv_bwd_weights_kernel_f32::generate() {
+ this->preamble();
+
+ mov(reg_input, ptr[this->param1 + GET_OFF(src)]);
+ mov(reg_output, ptr[this->param1 + GET_OFF(dst)]);
+ mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]);
+ compute_oh_loop_common();
+ this->postamble();
+}
+
+status_t jit_avx2_conv_bwd_weights_kernel_f32::init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &diff_weights_d,
+ const memory_desc_wrapper &diff_dst_d) {
+ if (!mayiuse(avx2)) return status::unimplemented;
+
+ const bool with_groups = diff_weights_d.ndims() == src_d.ndims() + 1;
+ int ndims = src_d.ndims();
+ jcp.ndims = ndims;
+
+ jcp.ngroups = with_groups ? diff_weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+
+ jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+
+ jcp.id = (ndims == 5) ? src_d.dims()[2] : 1;
+ jcp.ih = (ndims == 3) ? 1 : src_d.dims()[ndims-2];
+ jcp.iw = src_d.dims()[ndims-1];
+ jcp.od = (ndims == 5) ? diff_dst_d.dims()[2] : 1;
+ jcp.oh = (ndims == 3) ? 1 : diff_dst_d.dims()[ndims-2];
+ jcp.ow = diff_dst_d.dims()[ndims-1];
+
+ jcp.kd = (ndims == 5) ? diff_weights_d.dims()[with_groups + 2] : 1;
+ jcp.kh = (ndims == 3) ? 1 : diff_weights_d.dims()[with_groups + ndims-2];
+ jcp.kw = diff_weights_d.dims()[with_groups + ndims-1];
+
+ jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0;
+ jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4];
+ jcp.l_pad = cd.padding[0][ndims-3];
+
+ jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1;
+ jcp.stride_h = (ndims == 3) ? 1 : cd.strides[ndims-4];
+ jcp.stride_w = cd.strides[ndims-3];
+
+ jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0;
+ jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4];
+ jcp.dilate_w = cd.dilates[ndims-3];
+
+ if (ndims == 3) {
+ jcp.src_tag = src_d.matches_one_of_tag(ncw, nwc, nCw8c);
+ jcp.wei_tag = diff_weights_d.matches_one_of_tag(
+ Owi8o, gOwi8o, OIw8i8o, gOIw8i8o);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(nCw8c);
+ } else if (ndims == 4) {
+ jcp.src_tag = src_d.matches_one_of_tag(nchw, nhwc, nChw8c);
+ jcp.wei_tag = diff_weights_d.matches_one_of_tag(
+ Ohwi8o, gOhwi8o, OIhw8i8o, gOIhw8i8o);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(nChw8c);
+ } else if (ndims == 5) {
+ jcp.src_tag = src_d.matches_one_of_tag(ncdhw, ndhwc, nCdhw8c);
+ jcp.wei_tag = diff_weights_d.matches_one_of_tag(
+ Odhwi8o, gOdhwi8o, OIdhw8i8o, gOIdhw8i8o);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(nCdhw8c);
+ }
+ jcp.with_bias = cd.diff_bias_desc.format_kind != format_kind::undef;
+
+ const bool flat = jcp.ic == 3;
+ const bool mimo = !flat;
+
+ const int simd_w = 8;
+
+ jcp.b_pad = nstl::max(
+ 0, (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad);
+ jcp.r_pad = nstl::max(
+ 0, (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad);
+
+ int back_pad = nstl::max(0, (jcp.od - 1) * jcp.stride_d + jcp.kd - jcp.id
+ - jcp.f_pad);
+ if (ndims == 5)
+ if (jcp.f_pad != 0 || back_pad != 0)
+ return status::unimplemented;
+
+ const int max_h_pad = ((jcp.kh - 1) * (jcp.dilate_h + 1) + 1);
+ const int max_w_pad = ((jcp.kw - 1) * (jcp.dilate_w + 1) + 1);
+ const bool boundaries_ok = true
+ && jcp.t_pad < max_h_pad && jcp.b_pad < max_h_pad
+ && jcp.l_pad < max_w_pad && jcp.r_pad < max_w_pad;
+ if (!boundaries_ok)
+ return status::unimplemented;
+
+ bool ok_to_pad_channels = true
+ && jcp.ngroups == 1;
+
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ if (mimo)
+ jcp.ic = rnd_up(jcp.ic, simd_w);
+ }
+
+ bool args_ok = true
+ && IMPLICATION(flat, true
+ && one_of(jcp.src_tag, ncw, nwc, nchw, nhwc, ncdhw, ndhwc)
+ && one_of(jcp.wei_tag, Owi8o, gOwi8o, Ohwi8o, gOhwi8o, Odhwi8o,
+ gOdhwi8o))
+ && IMPLICATION(mimo, true
+ && one_of(jcp.src_tag, nCw8c, nChw8c, nCdhw8c)
+ && one_of(jcp.wei_tag, OIw8i8o, gOIw8i8o, OIhw8i8o, gOIhw8i8o,
+ OIdhw8i8o, gOIdhw8i8o))
+ && one_of(jcp.dst_tag, nCw8c, nChw8c, nCdhw8c)
+ && IMPLICATION(mimo, jcp.ic % simd_w == 0)
+ && jcp.oc % simd_w == 0
+ && jcp.kw < 14
+ && jcp.kh <= jcp.t_pad + jcp.ih /* [bwd_w:r1] */
+ && jcp.kh <= jcp.ih /* [bwd_w:r2] */
+ && jcp.kd <= jcp.f_pad + jcp.id
+ && jcp.kd <= jcp.id
+ && jcp.t_pad < jcp.kh /* XXX: must fix the kernel! */
+ && jcp.dilate_d == 0
+ && jcp.dilate_h == 0
+ && jcp.dilate_w == 0;
+ if (!args_ok) return status::unimplemented;
+
+ jcp.ic_block = (jcp.ic % simd_w != 0) ? jcp.ic : simd_w;
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+
+ jcp.oc_block = simd_w;
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+ jcp.nb_ic_blocking = jcp.nb_oc_blocking = 1;
+
+ return status::success;
+}
+
+void jit_avx2_conv_bwd_weights_kernel_f32::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) {
+ if (jcp.with_bias && jcp.oc != jcp.oc_without_padding)
+ scratchpad.book(key_conv_padded_bias, sizeof(float) * jcp.oc);
+}
+
+inline void jit_avx2_conv_bwd_weights_kernel_f32::od_step_comeback_pointers()
+{
+ Label kd_comeback_loop;
+ mov(kj, jcp.kd); //FIXME (Anton): this works only if f_pad = back_pad = 0
+ L(kd_comeback_loop); {
+ const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw)
+ ? 1 : jcp.ic_block;
+ sub(aux_reg_input, sizeof(float) * jcp.iw * jcp.ih * inp_mult);
+ sub(aux_reg_kernel, sizeof(float) * jcp.kw * jcp.kh * jcp.ic_block
+ * jcp.oc_block);
+ dec(kj);
+ cmp(kj, 0);
+ jg(kd_comeback_loop, T_NEAR);
+ }
+}
+
+inline void jit_avx2_conv_bwd_weights_kernel_f32::oh_step_comeback_pointers()
+{
+ mov(kj, reg_kh);
+ Label kh_comeback_loop;
+ L(kh_comeback_loop); {
+ const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw)
+ ? 1 : jcp.ic_block;
+ sub(reg_input, sizeof(float) * jcp.iw * inp_mult);
+ sub(reg_kernel, sizeof(float) * jcp.kw * jcp.ic_block * jcp.oc_block);
+ dec(kj);
+ cmp(kj, 0);
+ jg(kh_comeback_loop, T_NEAR);
+ }
+}
+
+inline void jit_avx2_conv_bwd_weights_kernel_f32::compute_ic_block_step(
+ int ur_w, int pad_l, int pad_r, int ic_block_step, int input_offset,
+ int kernel_offset, int output_offset)
+{
+ const int kw = jcp.kw;
+ const int ic_block = jcp.ic_block;
+ const int oc_block = jcp.oc_block;
+ for (int i_kw = 0; i_kw < kw; i_kw++)
+ for (int i_ic = 0; i_ic < ic_block_step; i_ic++) {
+ size_t off
+ = sizeof(float) * (i_kw * ic_block + i_ic) * jcp.oc_block
+ + kernel_offset;
+ vmovups(Ymm(i_kw * ic_block_step + i_ic), yword[reg_kernel + off]);
+ }
+
+ for (int i_ur = 0; i_ur < ur_w; i_ur++) {
+ vmovups(Ymm(kw * ic_block_step + 0),
+ yword[reg_output
+ + sizeof(float) * i_ur * oc_block + output_offset]);
+
+ for (int i_kw = 0; i_kw < kw; i_kw++) {
+ int i_iw = i_ur * jcp.stride_w + i_kw;
+ if (i_iw - pad_l < 0
+ || i_iw > (ur_w - 1) * jcp.stride_w + kw - 1 - pad_r)
+ continue;
+ for (int i_ic = 0; i_ic < ic_block_step; i_ic++) {
+ size_t i_off = (size_t)input_offset + sizeof(float)*(
+ one_of(jcp.src_tag, ncw, nchw, ncdhw)
+ ? (i_iw - pad_l) + i_ic
+ * ((size_t)jcp.id * jcp.ih * jcp.iw)
+ : (i_iw - pad_l) * ic_block + i_ic);
+ vbroadcastss(Ymm(kw * ic_block_step + 1),
+ make_safe_addr(reg_input, i_off, reg_long_offt));
+ vfmadd231ps(Ymm(i_kw * ic_block_step + i_ic),
+ Ymm(kw * ic_block_step + 0),
+ Ymm(kw * ic_block_step + 1));
+ }
+ }
+ }
+
+ for (int i_kw = 0; i_kw < kw; i_kw++)
+ for (int i_ic = 0; i_ic < ic_block_step; i_ic++) {
+ size_t off
+ = sizeof(float) * (i_kw * ic_block + i_ic) * jcp.oc_block
+ + kernel_offset;
+ vmovups(yword[reg_kernel + off],
+ Ymm(i_kw * ic_block_step + i_ic));
+ }
+}
+
+inline void jit_avx2_conv_bwd_weights_kernel_f32::compute_oh_step_disp()
+{
+ int ic_block_step;
+ if (one_of(jcp.src_tag, ncw, nchw, ncdhw)) {
+ ic_block_step = jcp.kw >= 5 ? 1 : jcp.ic_block;
+ } else {
+ ic_block_step = jcp.kw > 7 ? 1
+ : jcp.kw > 3 ? 2
+ : jcp.kw > 1 ? 4 : 8;
+ }
+
+ const int max_ur_w = jcp.ow > 56 ? 14 : 28;
+
+ if (jcp.ow <= max_ur_w)
+ compute_oh_step_unroll_ow(ic_block_step, max_ur_w);
+ else
+ compute_oh_step_common(ic_block_step, max_ur_w);
+
+ if (jcp.ndims == 5) {
+ od_step_comeback_pointers();
+ mov(reg_input, aux_reg_input);
+ mov(reg_kernel, aux_reg_kernel);
+ } else {
+ oh_step_comeback_pointers();
+ }
+}
+
+inline void jit_avx2_conv_bwd_weights_kernel_f32::compute_oh_step_unroll_ow(
+ int ic_block_step, int max_ur_w)
+{
+ UNUSED(max_ur_w);
+
+ const int ic_block = jcp.ic_block;
+ const int oc_block = jcp.oc_block;
+ int inp_mul = one_of(jcp.src_tag, ncw, nchw, ncdhw) ? 1 : jcp.ic_block;
+ Label kd_loop;
+
+ const int r_pad
+ = nstl::max(0,
+ (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad);
+
+ if (jcp.ndims == 5) {
+ mov(aux_reg_input, reg_input);
+ mov(aux_reg_kernel, reg_kernel);
+ mov(ki, jcp.kd);
+ L(kd_loop);
+ mov(reg_input, aux_reg_input);
+ mov(reg_kernel, aux_reg_kernel);
+ }
+
+ mov(kj, reg_kh);
+ Label kh_loop;
+ L(kh_loop); {
+ xor_(b_ic, b_ic);
+ Label ic_block_loop;
+ L(ic_block_loop); {
+ compute_ic_block_step(jcp.ow, jcp.l_pad, r_pad, ic_block_step, 0,
+ 0, 0);
+ size_t inp_icblk_stride = sizeof(float) * ic_block_step
+ * (one_of(jcp.src_tag, ncw, nchw, ncdhw)
+ ? jcp.id*jcp.ih*jcp.iw : 1);
+ safe_add(reg_input, inp_icblk_stride, reg_long_offt);
+ add(reg_kernel, sizeof(float) * ic_block_step * oc_block);
+ add(b_ic, ic_block_step);
+ cmp(b_ic, ic_block);
+ jl(ic_block_loop, T_NEAR);
+ }
+ if(one_of(jcp.src_tag, ncw, nchw, ncdhw)) {
+ size_t offt = sizeof(float) * jcp.id * jcp.ih * jcp.iw * ic_block;
+ safe_sub(reg_input, offt, reg_long_offt);
+ add(reg_input, sizeof(float) * jcp.iw);
+ } else {
+ add(reg_input, sizeof(float) * (jcp.iw - 1) * ic_block);
+ }
+ add(reg_kernel, sizeof(float) * (jcp.kw - 1) * ic_block * oc_block);
+ dec(kj);
+ cmp(kj, 0);
+ jg(kh_loop, T_NEAR);
+ }
+
+ if (jcp.ndims == 5) {
+ add(aux_reg_input, sizeof(float) * jcp.ih * jcp.iw * inp_mul);
+ add(aux_reg_kernel, sizeof(float) * jcp.kh * jcp.kw * ic_block
+ * oc_block);
+ dec(ki);
+ cmp(ki, 0);
+ jg(kd_loop, T_NEAR);
+ }
+
+}
+
+inline void jit_avx2_conv_bwd_weights_kernel_f32::compute_oh_step_common(
+ int ic_block_step, int max_ur_w)
+{
+ const int ic_block = jcp.ic_block;
+ const int oc_block = jcp.oc_block;
+ const int stride_w = jcp.stride_w;
+ int inp_mul = one_of(jcp.src_tag, ncw, nchw, ncdhw) ? 1 : jcp.ic_block;
+ Label kd_loop;
+
+ const int r_pad = jcp.r_pad;
+
+ int ur_w = nstl::min(jcp.ow, max_ur_w);
+ int ur_w_trips = jcp.ow / ur_w;
+ int ur_w_tail = jcp.ow % ur_w;
+ if ((ur_w_tail == 0 && r_pad != 0) || r_pad >= ur_w_tail) {
+ if (ur_w_trips > 1) {
+ ur_w_tail += ur_w;
+ ur_w_trips--;
+ } else {
+ ur_w_tail += (ur_w - ur_w / 2);
+ ur_w = ur_w / 2;
+ }
+ }
+ const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw) ? 1 : ic_block;
+
+ int input_comeback = (ur_w_trips * ur_w * stride_w - jcp.l_pad) * inp_mult;
+ int output_comeback = ur_w_trips * ur_w * oc_block;
+
+ if (jcp.ndims == 5) {
+ mov(aux_reg_input, reg_input);
+ mov(aux_reg_kernel, reg_kernel);
+ mov(ki, jcp.kd);
+ L(kd_loop);
+ mov(reg_input, aux_reg_input);
+ mov(reg_kernel, aux_reg_kernel);
+ }
+
+ mov(kj, reg_kh);
+ Label kh_loop;
+ L(kh_loop); {
+ xor_(b_ic, b_ic);
+ Label ic_block_loop;
+ L(ic_block_loop); {
+ if (jcp.l_pad != 0) {
+ ur_w_trips--;
+ compute_ic_block_step(ur_w,
+ jcp.l_pad, 0, ic_block_step, 0, 0, 0);
+ add(reg_input, sizeof(float)
+ * (ur_w * stride_w - jcp.l_pad) * inp_mult);
+ add(reg_output, sizeof(float) * ur_w * oc_block);
+ }
+
+ if (ur_w_trips > 0) {
+ xor_(reg_ur_w_trips, reg_ur_w_trips);
+ Label ow_block_loop;
+ L(ow_block_loop); {
+ compute_ic_block_step(ur_w, 0, 0, ic_block_step, 0, 0, 0);
+ add(reg_input, sizeof(float) * ur_w * stride_w * inp_mult);
+ add(reg_output, sizeof(float) * ur_w * oc_block);
+
+ inc(reg_ur_w_trips);
+ cmp(reg_ur_w_trips, ur_w_trips);
+ jl(ow_block_loop, T_NEAR);
+ }
+ }
+
+ if (ur_w_tail > 0)
+ compute_ic_block_step(ur_w_tail,
+ 0, r_pad, ic_block_step, 0, 0, 0);
+
+ sub(reg_input, sizeof(float) * input_comeback);
+ sub(reg_output, sizeof(float) * output_comeback);
+
+ size_t inp_icblk_stride = sizeof(float) * ic_block_step
+ * (one_of(jcp.src_tag, ncw, nchw, ncdhw)
+ ? jcp.id*jcp.ih*jcp.iw : 1);
+ safe_add(reg_input, inp_icblk_stride, reg_long_offt);
+ add(reg_kernel, sizeof(float) * ic_block_step * oc_block);
+
+ add(b_ic, ic_block_step);
+ cmp(b_ic, jcp.ic_block);
+ jl(ic_block_loop, T_NEAR);
+ }
+ if (one_of(jcp.src_tag, ncw, nchw, ncdhw)) {
+ size_t offt = sizeof(float) * jcp.id * jcp.ih * jcp.iw * ic_block;
+ safe_sub(reg_input, offt, reg_long_offt);
+ add(reg_input, sizeof(float) * jcp.iw);
+ } else {
+ add(reg_input, sizeof(float) * (jcp.iw - 1) * ic_block);
+ }
+ add(reg_kernel, sizeof(float) * (jcp.kw - 1) * ic_block * oc_block);
+ dec(kj);
+ cmp(kj, 0);
+ jg(kh_loop, T_NEAR);
+ }
+
+ if (jcp.ndims == 5) {
+ add(aux_reg_input, sizeof(float) * jcp.ih * jcp.iw * inp_mul);
+ add(aux_reg_kernel, sizeof(float) * jcp.kh * jcp.kw * ic_block
+ * oc_block);
+ dec(ki);
+ cmp(ki, 0);
+ jg(kd_loop, T_NEAR);
+ }
+
+}
+
+inline void jit_avx2_conv_bwd_weights_kernel_f32::compute_oh_loop_common()
+{
+ const int icoc_block = jcp.ic_block * jcp.oc_block;
+ const int t_pad = jcp.t_pad;
+ const int stride_h = jcp.stride_h;
+ const int inp_mult = one_of(jcp.src_tag, ncw, nchw, ncdhw)
+ ? 1 : jcp.ic_block;
+ int b_pad = jcp.b_pad;
+
+ Label oh_tpad_loop, oh_loop, oh_loop_end;
+
+ mov(reg_kh, jcp.kh);
+ xor_(reg_ih_count, reg_ih_count);
+ xor_(reg_oj, reg_oj);
+ if (t_pad > 0) {
+ assert(jcp.kh <= t_pad + jcp.ih); /* [bwd_w:r1] */
+ mov(reg_kh, jcp.kh <= t_pad + jcp.ih ? jcp.kh - t_pad : jcp.ih);
+ add(reg_kernel, sizeof(float) * t_pad * jcp.kw * icoc_block);
+
+ L(oh_tpad_loop); {
+ compute_oh_step_disp();
+ add(reg_output, sizeof(float) * jcp.ow * jcp.oc_block);
+ sub(reg_kernel, sizeof(float) * stride_h * jcp.kw * icoc_block);
+
+ inc(reg_oj);
+ add(reg_ih_count, stride_h);
+ add(reg_kh, stride_h);
+
+ /* the overlap between input and kernel may not reach kernel size.
+ * so far we do not support that (until we put constant here) */
+ const int final_inp_ker_overlap = jcp.kh; /* [bwd_w:r2] */
+ cmp(reg_kh, final_inp_ker_overlap);
+ jl(oh_tpad_loop, T_NEAR);
+ }
+
+ if (t_pad % stride_h != 0) {
+ int inp_corr = stride_h - t_pad % stride_h;
+ add(reg_kernel, sizeof(float) * inp_corr * jcp.kw * icoc_block);
+ add(reg_input, sizeof(float) * inp_corr * jcp.iw * inp_mult);
+ }
+ }
+ cmp(reg_ih_count, jcp.ih + t_pad - jcp.kh + 1);
+ jge(oh_loop_end, T_NEAR);
+ cmp(reg_oj, jcp.oh);
+ jge(oh_loop, T_NEAR);
+
+ mov(reg_kh, jcp.kh);
+ L(oh_loop); {
+ compute_oh_step_disp();
+ add(reg_input, sizeof(float) * stride_h * jcp.iw * inp_mult);
+ add(reg_output, sizeof(float) * jcp.ow * jcp.oc_block);
+
+ inc(reg_oj);
+ add(reg_ih_count, stride_h);
+
+ cmp(reg_ih_count, jcp.ih + t_pad - jcp.kh + 1);
+ jge(oh_loop_end, T_NEAR);
+
+ cmp(reg_oj, jcp.oh);
+ jl(oh_loop, T_NEAR);
+ }
+ L(oh_loop_end);
+ if (b_pad > 0) {
+ Label oh_bpad_loop, oh_bpad_loop_end;
+ cmp(reg_oj, jcp.oh);
+ jge(oh_bpad_loop_end, T_NEAR);
+
+ mov(reg_kh, jcp.ih + t_pad);
+ sub(reg_kh, reg_ih_count);
+ L(oh_bpad_loop); {
+ compute_oh_step_disp();
+ add(reg_input, sizeof(float) * stride_h * jcp.iw * inp_mult);
+ add(reg_output, sizeof(float) * jcp.ow * jcp.oc_block);
+
+ sub(reg_kh, stride_h);
+ cmp(reg_kh, 0);
+ jle(oh_bpad_loop_end, T_NEAR);
+
+ inc(reg_oj);
+ cmp(reg_oj, jcp.oh);
+ jl(oh_bpad_loop, T_NEAR);
+ }
+ L(oh_bpad_loop_end);
+ }
+}
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.hpp
new file mode 100644
index 0000000000..412c50c9ee
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.hpp
@@ -0,0 +1,225 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_AVX2_CONV_KERNEL_F32_HPP
+#define JIT_AVX2_CONV_KERNEL_F32_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "cpu_memory.hpp"
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+#include "jit_uni_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_avx2_conv_fwd_kernel_f32: public jit_generator {
+ jit_avx2_conv_fwd_kernel_f32(jit_conv_conf_t ajcp,
+ const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr)
+ {
+ if (jcp.with_eltwise)
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<avx2>(this,
+ jcp.eltwise);
+
+ this->generate();
+ jit_ker = (void (*)(jit_conv_call_s *))this->getCode();
+ }
+
+ ~jit_avx2_conv_fwd_kernel_f32() {
+ delete eltwise_injector_;
+ }
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx2_conv_fwd_kernel_f32)
+
+ static bool post_ops_ok(jit_conv_conf_t &jcp,
+ const primitive_attr_t &attr);
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d,
+ const primitive_attr_t &attr);
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp);
+
+ jit_conv_conf_t jcp;
+ const primitive_attr_t &attr_;
+ void (*jit_ker)(jit_conv_call_s *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ reg64_t reg_input = rax;
+ reg64_t aux_reg_input = r8;
+ reg64_t reg_kernel = rdx;
+ reg64_t aux_reg_kernel = r9;
+ reg64_t reg_output = rsi;
+ reg64_t reg_bias = rbx;
+
+ reg64_t aux_reg_inp_d = r11;
+ reg64_t aux_reg_ker_d = abi_not_param1;
+
+ reg64_t reg_ki = rsi;
+ reg64_t kj = r10;
+ reg64_t oi_iter = r11;
+ reg64_t ki_iter = r12;
+ reg64_t reg_kh = abi_not_param1;
+ reg64_t reg_oc_blocks = r14;
+ reg64_t imm_addr64 = r15;
+ reg64_t reg_long_offt = r15;
+ Xbyak::Reg32 reg_ci_flag = r13d;
+
+ Xbyak::Ymm ytmp = Xbyak::Ymm(14);
+
+ jit_uni_eltwise_injector_f32<avx2> *eltwise_injector_;
+
+ inline void oh_step_unroll_kw(int ur_w, int pad_l, int pad_r,
+ int oc_blocks);
+ inline void oh_step_nopad(int ur_w, int pad_l, int pad_r,
+ char pad_label, int oc_blocks, char oc_blocks_label);
+ inline void width_blk_step(int ur_w, int pad_l, int pad_r,
+ char pad_label, int oc_blocks, char oc_blocks_label);
+ inline void solve_common(int oc_blocks, char oc_blocks_label);
+
+ void generate();
+};
+
+struct jit_avx2_conv_bwd_data_kernel_f32: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx2_conv_bwd_data_kernel_f32)
+
+ jit_avx2_conv_bwd_data_kernel_f32(jit_conv_conf_t ajcp): jcp(ajcp)
+ {
+ this->generate();
+ jit_ker = (void (*)(jit_conv_call_s *))this->getCode();
+ }
+
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &diff_src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &diff_dst_d);
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp);
+
+ jit_conv_conf_t jcp;
+ void (*jit_ker)(jit_conv_call_s *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+
+ reg64_t reg_ddst = rax;
+ reg64_t aux_reg_ddst = r8;
+ reg64_t reg_kernel = rdx;
+ reg64_t aux_reg_kernel = r10;
+ reg64_t reg_dsrc = rsi;
+ reg64_t aux_reg_ddst_oc_loop = rbx; // used in ndims < 5 case only
+ reg64_t aux_reg_kernel_oc_loop = abi_not_param1; /* used in ndims < 5
+ case only */
+
+ reg64_t aux_reg_dst_d = r12; // used in ndims == 5 case only
+ reg64_t aux_reg_ker_d = r14; // used in ndims == 5 case only
+
+ reg64_t reg_ki = abi_not_param1; // used in ndims == 5 case only
+ reg64_t kj = r11;
+ reg64_t oi_iter = r12;
+ reg64_t reg_kh = r14;
+ reg64_t reg_channel = r13; // used in ndims < 5 case only
+ reg64_t reg_channel_work = r9; // used in ndims < 5 case only
+ reg64_t reg_long_offt = r15;
+
+ inline void compute_loop(int ur_w, int l_overflow, int r_overflow);
+
+ void generate();
+
+ inline int get_iw_start(int ki, int l_overflow)
+ {
+ int res = (jcp.iw - 1 + jcp.r_pad) % jcp.stride_w
+ + l_overflow * jcp.stride_w
+ - (jcp.kw - 1 - ki) * (jcp.dilate_w + 1);
+ while (res < 0)
+ res += jcp.stride_w;
+
+ return res;
+ }
+
+ inline int get_iw_end(int ur_w, int ki, int r_overflow)
+ {
+ if (utils::one_of(ur_w, jcp.iw, jcp.ur_w_tail))
+ ur_w += nstl::min(0, jcp.r_pad); // remove negative padding
+ int res = (ur_w - 1 + jcp.l_pad) % jcp.stride_w
+ + r_overflow * jcp.stride_w - ki * (jcp.dilate_w + 1);
+ while (res < 0)
+ res += jcp.stride_w;
+
+ return ur_w - res;
+ }
+};
+
+struct jit_avx2_conv_bwd_weights_kernel_f32: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx2_conv_bwd_weights_kernel_f32)
+
+ jit_avx2_conv_bwd_weights_kernel_f32(jit_conv_conf_t ajcp): jcp(ajcp)
+ {
+ this->generate();
+ jit_ker = (void (*)(jit_conv_call_s *))this->getCode();
+ }
+
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &diff_weights_d,
+ const memory_desc_wrapper &diff_dst_d);
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp);
+
+ jit_conv_conf_t jcp;
+ void (*jit_ker)(jit_conv_call_s *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ reg64_t reg_input = rax;
+ reg64_t reg_kernel = rdx;
+ reg64_t reg_output = rsi;
+ reg64_t b_ic = abi_not_param1;
+ reg64_t kj = r8;
+ reg64_t reg_kh = r9;
+ reg64_t reg_ur_w_trips = r10;
+ reg64_t reg_tmp = r11;
+ reg64_t reg_oj = r15;
+ reg64_t reg_ih_count = rbx;
+ reg64_t aux_reg_input = r12;
+ reg64_t aux_reg_kernel = r13;
+ reg64_t ki = r14;
+ reg64_t reg_long_offt = r11;
+
+ inline void od_step_comeback_pointers();
+ inline void oh_step_comeback_pointers();
+ inline void compute_ic_block_step(int ur_w, int pad_l, int pad_r,
+ int ic_block_step, int input_offset, int kernel_offset,
+ int output_offset);
+ inline void compute_oh_step_disp();
+ inline void compute_oh_step_unroll_ow(int ic_block_step, int max_ur_w);
+ inline void compute_oh_step_common(int ic_block_step, int max_ur_w);
+ inline void compute_oh_loop_common();
+
+ void generate();
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.cpp
new file mode 100644
index 0000000000..13f61e84fe
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.cpp
@@ -0,0 +1,410 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_avx2_convolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+#define src_blk_off(f, n, c, d, h, w) \
+ (pd()->ndims() == 3) \
+ ? (f).blk_off(n, c, w) \
+ : (pd()->ndims() == 4) \
+ ? (f).blk_off(n, c, h, w) \
+ : (f).blk_off(n, c, d, h, w)
+
+#define wht_blk_off_(f, g, ...) \
+ pd()->with_groups() ? (f).blk_off(g, __VA_ARGS__) : (f).blk_off(__VA_ARGS__)
+#define wht_blk_off(f, g, oc, ic, kd, kh, kw) \
+ (pd()->ndims() == 3) \
+ ? wht_blk_off_(f, g, oc, ic, kw) \
+ : (pd()->ndims() == 4) \
+ ? wht_blk_off_(f, g, oc, ic, kh, kw) \
+ : wht_blk_off_(f, g, oc, ic, kd, kh, kw)
+
+void jit_avx2_convolution_fwd_t::execute_forward(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ const auto &jcp = kernel_->jcp;
+
+ int ocb_work = div_up(jcp.nb_oc, jcp.nb_oc_blocking);
+ const size_t work_amount = jcp.mb * jcp.ngroups * ocb_work * jcp.od
+ * jcp.oh;
+
+ auto ker = [&](const int ithr, const int nthr) {
+ size_t start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ int icbb = 0;
+ while (icbb < jcp.nb_ic) {
+ int icb_step = jcp.nb_ic_blocking;
+ int icb_step_rem = jcp.nb_ic - icbb;
+ if (icb_step_rem < jcp.nb_ic_blocking_max)
+ icb_step = icb_step_rem;
+
+ size_t n{0}, g{0}, ocbb{0}, oh{0}, od{0};
+ nd_iterator_init(start, n, jcp.mb, g, jcp.ngroups, ocbb, ocb_work,
+ od, jcp.od, oh, jcp.oh);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ int ocb = ocbb * jcp.nb_oc_blocking;
+ int ocb_num = jcp.nb_oc_blocking;
+
+ for (int icb = icbb; icb < icbb + icb_step; ++icb) {
+ auto par_conv = jit_conv_call_s();
+
+ const int ij = oh * jcp.stride_h;
+ const int i_t_overflow = nstl::max(0, jcp.t_pad - ij);
+ const int i_b_overflow = nstl::max(jcp.ih, ij
+ + (jcp.kh-1) * (jcp.dilate_h+1) - jcp.t_pad+1) - jcp.ih;
+
+ const int dj = od * jcp.stride_d;
+ const int d_t_overflow = nstl::max(0, jcp.f_pad - dj);
+ const int d_b_overflow = nstl::max(jcp.id, dj
+ + (jcp.kd-1) * (jcp.dilate_d+1) - jcp.f_pad+1) - jcp.id;
+
+ const size_t _oc = g * jcp.nb_oc + ocb;
+ const size_t _ic = g * jcp.nb_ic * jcp.nonblk_group_off + icb;
+
+ const int ih = nstl::max(ij - jcp.t_pad
+ + div_up(i_t_overflow,
+ (jcp.dilate_h+1)) * (jcp.dilate_h + 1), 0);
+
+ const int id = nstl::max(dj - jcp.f_pad
+ + div_up(d_t_overflow,
+ (jcp.dilate_d+1)) * (jcp.dilate_d + 1), 0);
+
+ par_conv.src = &src[src_blk_off(src_d, n,
+ jcp.ic == 3 ? 0 : _ic, id, ih, 0)];
+
+ par_conv.dst = &dst[src_blk_off(dst_d, n, _oc, od, oh, 0)];
+
+ const int wh = div_up(i_t_overflow, (jcp.dilate_h + 1));
+ const int wd = div_up(d_t_overflow, (jcp.dilate_d + 1));
+ par_conv.filt = &weights[wht_blk_off(weights_d, g, ocb,
+ jcp.ic == 3 ? 0 : icb, wd, wh, 0)];
+
+ if (icb == 0) {
+ if (bias)
+ par_conv.bias =
+ &bias[bias_d.blk_off(_oc * jcp.oc_block)];
+ par_conv.flags |= FLAG_IC_FIRST;
+ }
+
+ if (jcp.with_eltwise && icb + 1 == jcp.nb_ic) {
+ par_conv.flags |= FLAG_IC_LAST;
+ }
+
+ par_conv.oc_blocks =
+ nstl::min(ocb + ocb_num, jcp.nb_oc) - ocb;
+
+ par_conv.kw_padding = 0;
+ const int kh_padding = jcp.kh
+ - div_up(i_t_overflow, (jcp.dilate_h + 1))
+ - div_up(i_b_overflow, (jcp.dilate_h + 1));
+ par_conv.kh_padding = nstl::max(0, kh_padding);
+
+ const int kd_padding = jcp.kd
+ - div_up(d_t_overflow, (jcp.dilate_d + 1))
+ - div_up(d_b_overflow, (jcp.dilate_d + 1));
+ par_conv.kd_padding = nstl::max(0, kd_padding);
+
+ kernel_->jit_ker(&par_conv);
+ }
+ nd_iterator_step(n, jcp.mb, g, jcp.ngroups, ocbb, ocb_work,
+ od, jcp.od, oh, jcp.oh);
+ }
+ icbb += icb_step;
+ }
+ };
+
+ if (pd()->wants_padded_bias()) {
+ auto padded_bias = scratchpad(ctx).get<data_t>(key_conv_padded_bias);
+ utils::array_copy(padded_bias, bias, jcp.oc_without_padding);
+ utils::array_set(padded_bias + jcp.oc_without_padding, 0.f,
+ jcp.oc - jcp.oc_without_padding);
+ bias = padded_bias;
+ }
+
+ parallel(0, ker);
+
+ if (pd()->wants_zero_pad_dst())
+ ctx.memory(MKLDNN_ARG_DST)->zero_pad();
+}
+
+void jit_avx2_convolution_bwd_data_t::execute_backward_data(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+
+ int icb_work = jcp.nb_ic / jcp.nb_ic_blocking;
+ int ih_block_size = jcp.ih;
+ int num_ih_blocks = utils::div_up(jcp.ih, ih_block_size);
+ size_t work_amount = jcp.mb * jcp.ngroups * icb_work * num_ih_blocks;
+ if (work_amount < (size_t)2 * mkldnn_get_max_threads()) {
+ ih_block_size = 1;
+ num_ih_blocks = utils::div_up(jcp.ih, ih_block_size);
+ work_amount *= num_ih_blocks;
+ }
+
+ auto ker = [&](const int ithr, const int nthr) {
+ size_t start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ size_t n{0}, g{0}, icbb{0}, ihb{0};
+ nd_iterator_init(start, n, jcp.mb, g, jcp.ngroups, icbb, icb_work,
+ ihb, num_ih_blocks);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ for (int oc = 0; oc < jcp.nb_oc; oc += jcp.nb_oc_blocking)
+ for (int id = 0; id < jcp.id; ++id) {
+ auto par_conv = jit_conv_call_s();
+
+ const int idp = jcp.id + 2 * jcp.f_pad;
+ const int d_t_overflow = nstl::max(0,
+ jcp.kd - 1 - id - jcp.f_pad);
+ const int back_pad = idp - jcp.id - jcp.f_pad;
+ const int d_b_overflow = nstl::max(0,
+ jcp.kd - 1 - (jcp.id - 1 - id) - back_pad);
+ const int od = id + jcp.f_pad - d_b_overflow;
+
+ int ih_start = ihb * ih_block_size;
+ int ih_end = nstl::min(jcp.ih, ih_start + ih_block_size);
+ for (int ih = ih_start; ih < ih_end; ++ih) {
+
+ const int i_t_overflow = nstl::max(0, (jcp.kh - 1
+ - ih - jcp.t_pad) / jcp.stride_h);
+ const int i_b_overflow = nstl::max(0, (jcp.kh - jcp.ih
+ + ih - jcp.b_pad) / jcp.stride_h);
+ int overflow_kh_hi = jcp.kh - 1 - abs((jcp.ih - 1
+ + jcp.b_pad - ih) % jcp.stride_h);
+ int overflow_kh_lo = (ih + jcp.t_pad) % jcp.stride_h;
+
+ par_conv.kd_padding = jcp.kd - d_t_overflow - d_b_overflow;
+ par_conv.kh_padding = (overflow_kh_hi - overflow_kh_lo)
+ / jcp.stride_h + 1 - i_t_overflow - i_b_overflow;
+ par_conv.kw_padding = 0;
+
+ const int k_lo = overflow_kh_lo
+ + i_b_overflow * jcp.stride_h;
+ const int oh = (ih + jcp.t_pad - k_lo) / jcp.stride_h;
+
+ par_conv.src = &diff_src[src_blk_off(diff_src_d, n,
+ /*jcp.ic == 3 ? 0 :*/
+ g * jcp.nb_ic + jcp.nb_ic_blocking * icbb, id, ih, 0)];
+ par_conv.dst = &diff_dst[src_blk_off(diff_dst_d,
+ n, g * jcp.nb_oc + oc, od, oh, 0)];
+ par_conv.filt = &weights[wht_blk_off(weights_d, g, oc,
+ jcp.ic == 3 ? 0 : jcp.nb_ic_blocking * icbb,
+ d_b_overflow, k_lo, 0)];
+
+ par_conv.src_prf = nullptr;
+ par_conv.dst_prf = nullptr;
+ par_conv.filt_prf = nullptr;
+ par_conv.channel = oc;
+ par_conv.ch_blocks = nstl::min(jcp.nb_oc - oc,
+ jcp.nb_oc_blocking);
+
+ kernel_->jit_ker(&par_conv);
+ }
+ }
+ nd_iterator_step(n, jcp.mb, g, jcp.ngroups, icbb, icb_work, ihb,
+ num_ih_blocks);
+ }
+ };
+
+ parallel(0, ker);
+}
+
+void jit_avx2_convolution_bwd_weights_t::execute_backward_weights(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS);
+ auto diff_bias_in = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ data_t *diff_bias = pd()->wants_padded_bias()
+ ? scratchpad.get<data_t>(key_conv_padded_bias) : diff_bias_in;
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+
+ auto reducer_bia_scratchpad = memory_tracking::grantor_t(scratchpad,
+ prefix_reducer_bia);
+ auto rb = this->reducer_bias_;
+ rb->init(reducer_bia_scratchpad);
+
+ auto reducer_wei_scratchpad = memory_tracking::grantor_t(scratchpad,
+ prefix_reducer_wei);
+ auto rw = this->reducer_weights_;
+ rw->init(reducer_wei_scratchpad);
+
+ auto ker = [&](int ithr, int nthr) {
+ assert(nthr == rw->balancer().nthr_);
+
+ const int w_job_start = rw->balancer().ithr_job_off(ithr);
+ const int w_njobs = rw->balancer().ithr_njobs(ithr);
+
+ if (w_njobs == 0) return;
+
+ /* reduction dimension */
+ int img_od_start{0}, img_od_end{0}, img{0}, od_s{0};
+ balance211(jcp.mb * jcp.od, rw->balancer().nthr_per_group_,
+ rw->balancer().id_in_group(ithr), img_od_start, img_od_end);
+
+ int img_start = img_od_start, img_end = img_od_end;
+ nd_iterator_init(img_start, img, jcp.mb, od_s, jcp.od);
+ const int img_first = img;
+
+ /* jobs */
+ int g_start{0}, ocb_start{0}, icb_start{0};
+ nd_iterator_init(w_job_start, g_start, jcp.ngroups, ocb_start,
+ jcp.nb_oc, icb_start, jcp.nb_ic);
+
+ while (img_start < img_end) {
+ int g = g_start, ocb = ocb_start, icb = icb_start;
+
+ const int work_rem = img_end - img_start;
+ const int od_e = od_s + work_rem > jcp.od ? jcp.od : od_s + work_rem;
+ const int id_s = od_s * jcp.stride_d;
+ const int idp = jcp.id + jcp.f_pad + jcp.back_pad;
+
+ if (id_s < idp - jcp.back_pad - jcp.kd + 1)
+ for (int w_job_loc = 0; w_job_loc < w_njobs; ++w_job_loc) {
+ const size_t _oc = g * jcp.nb_oc + ocb;
+ const size_t _ic = g * jcp.nb_ic + icb;
+
+ /* TODO: put dw <-- 0 in kernel */
+ if (img == img_first)
+ array_set(rw->get_local_ptr(ithr, diff_weights,
+ reducer_wei_scratchpad) +
+ w_job_loc * rw->balancer().job_size_, 0,
+ rw->balancer().job_size_);
+
+ for (int od = od_s; od < od_e; ++od) {
+ const int id = od * jcp.stride_d;
+ if (id >= jcp.id - jcp.back_pad - jcp.kd + 1) break;
+
+ auto par_conv = jit_conv_call_s();
+ par_conv.src = &src[src_blk_off(src_d, img, _ic, id, 0, 0)];
+ par_conv.dst =
+ &diff_dst[src_blk_off(diff_dst_d, img, _oc, od, 0, 0)];
+ par_conv.filt = rw->get_local_ptr(ithr, diff_weights,
+ reducer_wei_scratchpad) +
+ w_job_loc * rw->balancer().job_size_;
+
+ kernel_->jit_ker(&par_conv);
+ }
+ nd_iterator_step(g, jcp.ngroups, ocb, jcp.nb_oc, icb,
+ jcp.nb_ic);
+ }
+ nd_iterator_jump(img_start, img_end, img, jcp.mb, od_s, jcp.od);
+ }
+ rw->reduce(ithr, diff_weights, reducer_wei_scratchpad);
+ };
+
+ auto ker_bias = [&](int ithr, int nthr) {
+ assert(nthr == rb->balancer().nthr_);
+
+ const int b_job_start = rb->balancer().ithr_job_off(ithr);
+ const int b_njobs = rb->balancer().ithr_njobs(ithr);
+
+ if (b_njobs == 0) return;
+
+ /* reduction dimension */
+ int img_start{0}, img_end{0};
+ balance211(jcp.mb, rb->balancer().nthr_per_group_,
+ rb->balancer().id_in_group(ithr), img_start, img_end);
+
+ /* jobs */
+ int g_start{0}, ocb_start{0};
+ nd_iterator_init(b_job_start, g_start, jcp.ngroups, ocb_start,
+ jcp.nb_oc);
+
+ for (int img = img_start; img < img_end; ++img) {
+ int g = g_start, ocb = ocb_start;
+ for (int b_job_loc = 0; b_job_loc < b_njobs; ++b_job_loc) {
+ const size_t _oc = g * jcp.nb_oc + ocb;
+
+ const data_t *d_dst = &diff_dst[diff_dst_d.blk_off(img, _oc)];
+ data_t *d_bias = rb->get_local_ptr(ithr, diff_bias,
+ reducer_bia_scratchpad) +
+ b_job_loc * rb->balancer().job_size_;
+
+ if (img == img_start)
+ for (int o = 0; o < 8; ++o)
+ d_bias[o] = 0.;
+
+ for (int dhw = 0; dhw < jcp.od * jcp.oh * jcp.ow; ++dhw) {
+ PRAGMA_OMP_SIMD()
+ for (int o = 0; o < 8; ++o)
+ d_bias[o] += d_dst[o];
+ d_dst += 8;
+ }
+
+ nd_iterator_step(g, jcp.ngroups, ocb, jcp.nb_oc);
+ }
+ }
+ rb->reduce(ithr, diff_bias, reducer_bia_scratchpad);
+ };
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ ker(ithr, nthr);
+ if (pd()->with_bias())
+ ker_bias(ithr, nthr);
+ });
+
+ /* TODO: put this in ker_bias */
+ if (pd()->wants_padded_bias()) {
+ assert(jcp.ngroups == 1);
+ for (int oc = 0; oc < jcp.oc_without_padding; ++oc)
+ diff_bias_in[oc] = diff_bias[oc];
+ }
+}
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.hpp
new file mode 100644
index 0000000000..bb65bce79c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx2_convolution.hpp
@@ -0,0 +1,302 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX2_CONVOLUTION_HPP
+#define CPU_JIT_AVX2_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_reducer.hpp"
+
+#include "jit_avx2_conv_kernel_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_avx2_convolution_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", avx2, ""),
+ jit_avx2_convolution_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_avx2_conv_fwd_kernel_f32::init_conf(jcp_,
+ *desc(), src_md(), weights_md(), dst_md(), *attr());
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx2_conv_fwd_kernel_f32::init_scratchpad(scratchpad, jcp_);
+
+ return status::success;
+ }
+
+ jit_conv_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ const bool flat = IC() < 8;
+ auto src_tag = flat
+ ? utils::pick(ndims() - 3, ncw, nchw, ncdhw)
+ : utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto dst_tag =
+ utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto wei_tag = with_groups()
+ ? utils::pick(2 * ndims() - 6 + flat, gOIw8i8o, gOwi8o,
+ gOIhw8i8o, gOhwi8o, gOIdhw8i8o, gOdhwi8o)
+ : utils::pick(2 * ndims() - 6 + flat, OIw8i8o, Owi8o,
+ OIhw8i8o, Ohwi8o, OIdhw8i8o, Odhwi8o);
+
+ return set_default_formats_common(src_tag, wei_tag, dst_tag);
+ }
+ };
+
+ jit_avx2_convolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd)
+ { kernel_ = new jit_avx2_conv_fwd_kernel_f32(pd()->jcp_, *pd()->attr()); }
+ ~jit_avx2_convolution_fwd_t() { delete kernel_; }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx2_conv_fwd_kernel_f32 *kernel_;
+};
+
+struct jit_avx2_convolution_bwd_data_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_data_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_()
+ {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", avx2, ""),
+ jit_avx2_convolution_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_data
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::undef, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_avx2_conv_bwd_data_kernel_f32::init_conf(
+ jcp_, *desc(), *diff_src_md(), *weights_md(),
+ *diff_dst_md());
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx2_conv_bwd_data_kernel_f32::init_scratchpad(scratchpad,
+ jcp_);
+
+ return status::success;
+ }
+
+ jit_conv_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto wei_tag = with_groups()
+ ? utils::pick(ndims() - 3, gOIw8o8i, gOIhw8o8i, gOIdhw8o8i)
+ : utils::pick(ndims() - 3, OIw8o8i, OIhw8o8i, OIdhw8o8i);
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ jit_avx2_convolution_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd)
+ { kernel_ = new jit_avx2_conv_bwd_data_kernel_f32(pd()->jcp_); }
+ ~jit_avx2_convolution_bwd_data_t() { delete kernel_; }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_data(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_data(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx2_conv_bwd_data_kernel_f32 *kernel_;
+};
+
+struct jit_avx2_convolution_bwd_weights_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_weights_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", avx2, ""),
+ jit_avx2_convolution_bwd_weights_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_weights
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_avx2_conv_bwd_weights_kernel_f32::init_conf(
+ jcp_, *desc(), *src_md(), *diff_weights_md(),
+ *diff_dst_md());
+ if (status != status::success) return status;
+
+ init_balancers();
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx2_conv_bwd_weights_kernel_f32::init_scratchpad(scratchpad,
+ jcp_);
+
+ auto reducer_bia_scratchpad = memory_tracking::registrar_t(
+ scratchpad, memory_tracking::names::prefix_reducer_bia);
+ reducer_bia_conf_.init_scratchpad(reducer_bia_scratchpad);
+
+ auto reducer_wei_scratchpad = memory_tracking::registrar_t(
+ scratchpad, memory_tracking::names::prefix_reducer_wei);
+ reducer_wei_conf_.init_scratchpad(reducer_wei_scratchpad);
+
+ return status::success;
+ }
+
+ jit_conv_conf_t jcp_;
+ cpu_reducer_t<data_type::f32>::conf_t reducer_bia_conf_;
+ cpu_reducer_t<data_type::f32>::conf_t reducer_wei_conf_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+ const bool flat = IC() == 3;
+
+ auto src_tag = flat
+ ? utils::pick(ndims() - 3, ncw, nchw, ncdhw)
+ : utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto dst_tag =
+ utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto wei_tag = with_groups()
+ ? utils::pick(2 * ndims() - 6 + flat, gOIw8i8o, gOwi8o,
+ gOIhw8i8o, gOhwi8o, gOIdhw8i8o, gOdhwi8o)
+ : utils::pick(2 * ndims() - 6 + flat, OIw8i8o, Owi8o,
+ OIhw8i8o, Ohwi8o, OIdhw8i8o, Odhwi8o);
+
+ return set_default_formats_common(src_tag, wei_tag, dst_tag);
+ }
+
+ private:
+ void init_balancers() {
+ const int max_threads = mkldnn_get_max_threads();
+ const size_t max_buffer_size = 1<<21; /* just a heuristic */
+
+ if(with_bias()) {
+ reducer_bia_conf_.init(reduce_balancer_t(max_threads,
+ jcp_.oc_block, jcp_.ngroups * jcp_.nb_oc, jcp_.mb,
+ max_buffer_size));
+ }
+
+ reducer_wei_conf_.init(reduce_balancer_t(max_threads,
+ jcp_.kd * jcp_.kh * jcp_.kw
+ * jcp_.ic_block * jcp_.oc_block,
+ jcp_.ngroups * jcp_.nb_ic * jcp_.nb_oc,
+ jcp_.mb * jcp_.od, max_buffer_size));
+ }
+ };
+
+ jit_avx2_convolution_bwd_weights_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , kernel_(nullptr)
+ , reducer_weights_(nullptr)
+ , reducer_bias_(nullptr)
+ {
+ kernel_ = new jit_avx2_conv_bwd_weights_kernel_f32(pd()->jcp_);
+ reducer_bias_ =
+ new cpu_reducer_t<data_type::f32>(pd()->reducer_bia_conf_);
+ reducer_weights_ =
+ new cpu_reducer_t<data_type::f32>(pd()->reducer_wei_conf_);
+ }
+
+ ~jit_avx2_convolution_bwd_weights_t() {
+ delete kernel_;
+ delete reducer_weights_;
+ delete reducer_bias_;
+ }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_weights(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_weights(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx2_conv_bwd_weights_kernel_f32 *kernel_;
+ cpu_reducer_t<data_type::f32> *reducer_weights_, *reducer_bias_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.cpp
new file mode 100644
index 0000000000..635b83b2bf
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.cpp
@@ -0,0 +1,1255 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <float.h>
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_memory.hpp"
+#include "cpu_barrier.hpp"
+
+#include "jit_uni_1x1_conv_utils.hpp"
+#include "jit_avx512_common_1x1_conv_kernel.hpp"
+
+#define GET_OFF(field) offsetof(jit_1x1_conv_call_s, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::utils;
+
+using namespace Xbyak;
+
+void jit_avx512_common_1x1_conv_kernel::bcast_loop(int load_loop_blk)
+{
+ mov(aux1_reg_bcast_data, reg_bcast_data);
+ mov(aux_reg_bcast_data, reg_bcast_data);
+
+ mov(aux_reg_output_data, reg_output_data);
+ mov(bcast_loop_iter, EVEX_compress_addr(rsp, bcast_loop_work_offt));
+
+ if (jcp.ver == ver_4fma)
+ {
+ Label bcast_loop;
+ Label bcast_loop_wraparound;
+ Label bcast_loop_out;
+ Label bcast_loop_ur_full;
+
+ cmp(bcast_loop_iter, jcp.ur);
+ jle(bcast_loop_wraparound, T_NEAR);
+
+ L(bcast_loop); {
+ assert(jcp.bcast_block % jcp.ur == 0);
+ int num_substeps = jcp.bcast_block / jcp.ur;
+ assert(num_substeps > 0 && num_substeps < 10);
+ for (int i = 0; i < num_substeps; i++) {
+ reduce_loop(load_loop_blk, jcp.ur, i, false);
+ if (i < num_substeps - 1) {
+ add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_substep);
+ add(aux_reg_output_data, jcp.bcast_loop_output_substep);
+ }
+ else {
+ add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_step
+ - (num_substeps - 1) * jcp.bcast_loop_bcast_substep);
+ add(aux_reg_output_data, jcp.bcast_loop_output_step
+ - (num_substeps - 1) * jcp.bcast_loop_output_substep);
+ }
+ }
+ sub(bcast_loop_iter, jcp.bcast_block);
+ cmp(bcast_loop_iter, jcp.bcast_block);
+ jg(bcast_loop, T_NEAR);
+ }
+
+ L(bcast_loop_wraparound);
+ if (jcp.ur_tail) {
+ je(bcast_loop_ur_full, T_NEAR);
+ reduce_loop(load_loop_blk, jcp.ur_tail, 0, true);
+ jmp(bcast_loop_out, T_NEAR);
+ }
+ L(bcast_loop_ur_full);
+ reduce_loop(load_loop_blk, jcp.ur, 0, true);
+ L(bcast_loop_out);
+ }
+ else
+ {
+ Label bcast_loop;
+ Label bcast_loop_tail;
+
+ cmp(bcast_loop_iter, jcp.ur);
+ jl(bcast_loop_tail, T_NEAR);
+
+ L(bcast_loop); {
+ assert(jcp.bcast_block % jcp.ur == 0);
+ int num_substeps = jcp.bcast_block / jcp.ur;
+ assert(num_substeps > 0 && num_substeps < 10);
+ for (int i = 0; i < num_substeps; i++) {
+ reduce_loop(load_loop_blk, jcp.ur, i, false);
+ if (i < num_substeps - 1) {
+ add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_substep);
+ add(aux_reg_output_data, jcp.bcast_loop_output_substep);
+ }
+ else {
+ add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_step
+ - (num_substeps - 1) * jcp.bcast_loop_bcast_substep);
+ add(aux_reg_output_data, jcp.bcast_loop_output_step
+ - (num_substeps - 1) * jcp.bcast_loop_output_substep);
+ }
+ }
+ sub(bcast_loop_iter, jcp.bcast_block);
+ cmp(bcast_loop_iter, jcp.bcast_block);
+ jge(bcast_loop, T_NEAR);
+ }
+
+ L(bcast_loop_tail);
+ if (jcp.ur_tail) {
+ Label bcast_loop_tail_out;
+ cmp(bcast_loop_iter, 0);
+ jz(bcast_loop_tail_out, T_NEAR);
+ reduce_loop(load_loop_blk, jcp.ur_tail, 0, true);
+ L(bcast_loop_tail_out);
+ }
+ }
+}
+
+void jit_avx512_common_1x1_conv_kernel::reduce_loop(int load_loop_blk,
+ int ur, int substep, bool wraparound)
+{
+ auto vreg_load = [=](int i_load, int i_fma) {
+ return Zmm(utils::rnd_up(ur * load_loop_blk, jcp.fma_step)
+ + jcp.fma_step * i_load + i_fma);
+ };
+
+ auto vreg_accum = [=](int i_load, int i_ur) {
+ return Zmm(i_ur * load_loop_blk + i_load);
+ };
+
+ auto bias_ptr = [=](int i_load) {
+ return EVEX_compress_addr(reg_bias_data,
+ jcp.typesize_out * jcp.oc_block * i_load);
+ };
+
+ auto bcast_ptr = [=](int i_reduce, int i_ur, bool bcast) {
+ assert(i_ur < jcp.ur);
+ assert(i_reduce <= jcp.reduce_loop_unroll);
+ int offt;
+ if (one_of(jcp.prop_kind, forward_training, forward_inference,
+ backward_data)) {
+ assert(jcp.reduce_loop_unroll == jcp.reduce_block);
+ offt = (i_reduce == jcp.reduce_loop_unroll)
+ ? (jcp.bcast_dim + i_ur) * jcp.reduce_loop_unroll
+ : i_ur * jcp.reduce_loop_unroll + i_reduce;
+ } else {
+ if (jcp.transpose_src) {
+ const int reduce_group = i_reduce / 4;
+ const int reduce_shift = i_reduce % 4;
+ offt = 4 * (reduce_group * jcp.ic_block + i_ur) + reduce_shift;
+ }
+ else
+ offt = i_reduce * jcp.ic_block + i_ur;
+ }
+ return EVEX_compress_addr(aux_reg_bcast_data, jcp.typesize_in * offt,
+ bcast);
+ };
+
+ auto load_ptr = [=](int i_reduce, int i_load) {
+ int offt;
+ int u0 = i_reduce % jcp.reduce_loop_unroll;
+ int u1 = i_reduce / jcp.reduce_loop_unroll;
+ offt = (i_load * jcp.reduce_dim + u0) * jcp.load_block;
+ return EVEX_compress_addr(aux_reg_load_data,
+ u1 * jcp.reduce_loop_load_step
+ + jcp.typesize_in * offt);
+ };
+
+ auto output_ptr = [=](int i_load, int i_ur) {
+ if (one_of(jcp.prop_kind, forward_training, forward_inference,
+ backward_data))
+ return EVEX_compress_addr(aux_reg_output_data,
+ (i_load * jcp.bcast_dim + i_ur) * jcp.load_block
+ * jcp.typesize_out);
+ else
+ return ptr[aux_reg_output_data +
+ (i_load
+ ? reg_output_stride * i_load
+ : 0) // TODO: Xbyak should allow 0 scale
+ + jcp.typesize_out * jcp.load_block * i_ur];
+ };
+
+ auto init = [=]() {
+ Label init_done;
+ Label init_zero;
+
+ if (jcp.with_sum) {
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load) {
+ for (int i_ur = 0; i_ur < ur; ++i_ur) {
+ mic_prefetcht1(output_ptr(i_load, i_ur));
+ }
+ }
+ }
+
+ if (jcp.with_bias
+ && one_of(jcp.prop_kind, forward_training, forward_inference)) {
+ test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST);
+ jz(init_zero, T_NEAR);
+
+ for (int i_load = 0; i_load < load_loop_blk; i_load++)
+ for (int i_ur = 0; i_ur < ur; ++i_ur)
+ vmovups(vreg_accum(i_load, i_ur), bias_ptr(i_load));
+ jmp(init_done, T_NEAR);
+ }
+
+ L(init_zero);
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load)
+ for (int i_ur = 0; i_ur < ur; ++i_ur) {
+ auto r = vreg_accum(i_load, i_ur);
+ vpxord(r, r, r);
+ }
+ L(init_done);
+ };
+
+ auto store = [=]() {
+ Label store_noadd;
+ if (!jcp.with_sum) {
+ test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST);
+ jnz(store_noadd, T_NEAR);
+ }
+
+ for (int i_ur = 0; i_ur < ur; ++i_ur)
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load) {
+ auto r = vreg_accum(i_load, i_ur);
+ vaddps(r, r, output_ptr(i_load, i_ur));
+ }
+
+ L(store_noadd);
+ if (jcp.with_eltwise) {
+ Label store_noeltwise;
+ test(reg_reduce_pos_flag, FLAG_REDUCE_LAST);
+ jz(store_noeltwise, T_NEAR);
+
+ eltwise_injector_->compute_vector_range(0, ur * load_loop_blk);
+
+ L(store_noeltwise);
+ }
+
+ auto store_output = [=](bool output_is_aligned) {
+ for (int i_ur = 0; i_ur < ur; ++i_ur)
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load)
+ if (output_is_aligned && jcp.use_vmovntps)
+ vmovntps(output_ptr(i_load, i_ur),
+ vreg_accum(i_load, i_ur));
+ else
+ vmovups(output_ptr(i_load, i_ur),
+ vreg_accum(i_load, i_ur));
+ };
+
+ Label unaligned_store, end_store;
+ test(aux_reg_output_data, cpu_isa_traits<avx512_common>::vlen - 1);
+ jnz(unaligned_store, T_NEAR);
+ store_output(true);
+ jmp(end_store, T_NEAR);
+ L(unaligned_store); {
+ store_output(false);
+ }
+ L(end_store);
+ };
+
+ auto prefetch_callback = [=](int ur, int i_reduce, int i_ur, int i_load,
+ bool last_block, bool wraparound, int reduce_step)
+ {
+ bool pf_ker_l1 = true;
+ bool pf_ker_l2 = wraparound;
+ int n_ops = (jcp.reduce_loop_unroll / reduce_step) * ur * load_loop_blk;
+ int i_op = (i_reduce / reduce_step) * ur * load_loop_blk +
+ i_ur * load_loop_blk + i_load;
+
+ int n_pf_ker_l1 = pf_ker_l1 ? jcp.reduce_block : 0;
+ int n_pf_ker_l2 = pf_ker_l2 && wraparound ? jcp.reduce_block : 0;
+ int n_pf_out_l1 = jcp.use_vmovntps ? 0 : ur;
+
+ int pf_inp_ops = n_ops / 2; // # of operations during which to pf input
+ int pf_inp_trigger;
+ if (jcp.prop_kind == backward_weights)
+ pf_inp_trigger = nstl::max(1, pf_inp_ops / jcp.reduce_block);
+ else
+ pf_inp_trigger = nstl::max(1, pf_inp_ops / ur);
+
+ int n_other_pf =
+ load_loop_blk * (n_pf_ker_l1 + n_pf_ker_l2 + n_pf_out_l1);
+ int n_other_pf_ops = n_ops - pf_inp_ops;
+ int other_pf_trigger
+ = n_other_pf ? nstl::max(1, n_other_pf_ops / n_other_pf) : 0;
+
+ if (i_op < pf_inp_ops && i_op % pf_inp_trigger == 0) {
+ // input prefetches have the highest priority b/c the
+ // first iteration of the kernel block touches all the
+ // cache lines
+ int i_pf = i_op / pf_inp_trigger;
+ auto pf_reg = wraparound && last_block
+ ? reg_bcast_data
+ : (last_block ? aux1_reg_bcast_data
+ : aux_reg_bcast_data);
+ int offt = i_pf;
+ if (jcp.prop_kind == backward_weights) {
+ offt += wraparound && last_block
+ ? 0
+ : (last_block ? jcp.is : jcp.reduce_block);
+ offt *= jcp.bcast_block;
+ } else {
+ offt += wraparound && last_block
+ ? 0
+ : (last_block ? jcp.ur : jcp.bcast_dim);
+ offt *= jcp.reduce_block;
+ }
+ mic_prefetcht0(ptr[pf_reg + offt * jcp.typesize_in]);
+ } else if (i_op >= pf_inp_ops && n_other_pf) {
+ // remaining prefetches are spread among the rest of the
+ // operations; prefetches for output take priority
+ // TODO: spread L2 prefetches among L1 prefetches
+ i_op -= pf_inp_ops;
+ if (i_op % other_pf_trigger == 0) {
+ int i_pf = i_op / (load_loop_blk * other_pf_trigger);
+ if (i_pf < n_pf_ker_l2) {
+ int offt = (i_pf + (i_load + 1) * jcp.reduce_dim)
+ * jcp.load_block;
+ mic_prefetcht1(ptr[aux_reg_load_data
+ + offt * jcp.typesize_in]);
+ } else if (i_pf < n_pf_ker_l2 + n_pf_ker_l1) {
+ i_pf -= n_pf_ker_l2;
+ auto pf_reg = last_block ? reg_load_data
+ : aux_reg_load_data;
+ int offt = (i_pf + i_load * jcp.reduce_dim
+ + (last_block
+ ? (wraparound ? jcp.reduce_dim : 0)
+ : jcp.reduce_block))
+ * jcp.load_block;
+ mic_prefetcht0(ptr[pf_reg + offt * jcp.typesize_in]);
+ } else if (i_pf < n_pf_ker_l1 + n_pf_ker_l2 + n_pf_out_l1) {
+ i_pf -= n_pf_ker_l1 + n_pf_ker_l2;
+ int offt = i_pf * jcp.load_block;
+ mic_prefetcht0(ptr[aux_reg_output_data
+ + offt * jcp.typesize_out]);
+ }
+ }
+ }
+ };
+
+ auto fma_block = [=](bool last_block) {
+ assert(jcp.reduce_loop_unroll % jcp.fma_step == 0);
+
+ int reduce_step = jcp.fma_step;
+
+ for (int i_reduce = 0; i_reduce < jcp.reduce_loop_unroll;
+ i_reduce += reduce_step) {
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load) {
+ // if transposed input data used and if spatial size is
+ // not divided by transpose step (4) then for last reduce step
+ // we should load only needed load_registers data
+ // and clear remaining
+ if (jcp.transpose_src && jcp.is % jcp.fma_step && last_block
+ && i_reduce == jcp.reduce_loop_unroll - reduce_step) {
+ Label load_all;
+ Label load_finish;
+ test(reg_reduce_pos_flag, FLAG_SP_LAST);
+ jz(load_all, T_NEAR);
+
+ const int n_loads = jcp.is % jcp.fma_step;
+ for (int i_fma = 0; i_fma < jcp.fma_step; i_fma++) {
+ if (i_fma < n_loads)
+ vmovups(vreg_load(i_load, i_fma),
+ load_ptr(i_reduce + i_fma, i_load));
+ else
+ vpxord(vreg_load(i_load, i_fma),
+ vreg_load(i_load, i_fma),
+ vreg_load(i_load, i_fma));
+ }
+ jmp(load_finish);
+
+ L(load_all);
+ for (int i_fma = 0; i_fma < jcp.fma_step; i_fma++) {
+ vmovups(vreg_load(i_load, i_fma),
+ load_ptr(i_reduce + i_fma, i_load));
+ }
+ L(load_finish);
+ } else {
+ for (int i_fma = 0; i_fma < jcp.fma_step; i_fma++) {
+ vmovups(vreg_load(i_load, i_fma),
+ load_ptr(i_reduce + i_fma, i_load));
+ }
+ }
+ }
+
+ for (int i_ur = 0; i_ur < ur; ++i_ur) {
+ if (jcp.ver == ver_avx512_core && jcp.expl_bcast
+ && load_loop_blk > 1)
+ vbroadcastss(vreg_bcast, bcast_ptr(i_reduce, i_ur, false));
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load) {
+ if (jcp.ver == ver_4fma)
+ v4fmaddps(vreg_accum(i_load, i_ur),
+ vreg_load(i_load, 0),
+ bcast_ptr(i_reduce, i_ur, false));
+ else if (jcp.ver == ver_avx512_core && jcp.expl_bcast
+ && load_loop_blk > 1)
+ vfmadd231ps(vreg_accum(i_load, i_ur),
+ vreg_load(i_load, 0), vreg_bcast);
+ else
+ vfmadd231ps(vreg_accum(i_load, i_ur),
+ vreg_load(i_load, 0),
+ bcast_ptr(i_reduce, i_ur, true));
+ prefetch_callback(ur, i_reduce, i_ur, i_load,
+ last_block, wraparound, reduce_step);
+ }
+ }
+ }
+ };
+ Label reduce_loop;
+ Label reduce_loop_tail;
+
+ mov(aux_reg_load_data, reg_load_data);
+
+ mov(aux_reg_bcast_data, aux1_reg_bcast_data);
+ init();
+
+ mov(reduce_loop_iter, reg_reduce_loop_work);
+ sub(reduce_loop_iter, jcp.reduce_loop_unroll);
+ jle(reduce_loop_tail, T_NEAR);
+
+ L(reduce_loop); {
+ fma_block(false);
+ add(aux_reg_bcast_data, jcp.reduce_loop_bcast_step);
+ add(aux_reg_load_data, jcp.reduce_loop_load_step);
+ sub(reduce_loop_iter, jcp.reduce_loop_unroll);
+ jg(reduce_loop, T_NEAR);
+ }
+
+ L(reduce_loop_tail);
+ fma_block(true);
+
+ store();
+}
+
+void jit_avx512_common_1x1_conv_kernel::generate()
+{
+ preamble();
+
+ mov(reg_bcast_data, ptr[param1 + GET_OFF(bcast_data)]);
+ mov(reg_load_data, ptr[param1 + GET_OFF(load_data)]);
+ mov(reg_output_data, ptr[param1 + GET_OFF(output_data)]);
+
+ sub(rsp, stack_space_needed);
+
+ if (jcp.with_bias)
+ mov(reg_bias_data, ptr[param1 + GET_OFF(bias_data)]);
+
+ mov(reg_load_loop_work, ptr[param1 + GET_OFF(load_dim)]);
+ mov(reg_bcast_loop_work, ptr[param1 + GET_OFF(bcast_dim)]);
+ mov(EVEX_compress_addr(rsp, bcast_loop_work_offt), reg_bcast_loop_work);
+ mov(reg_reduce_loop_work, ptr[param1 + GET_OFF(reduce_dim)]);
+ mov(reg_reduce_pos_flag, ptr[param1 + GET_OFF(first_last_flag)]);
+ if (one_of(jcp.prop_kind, forward_training, forward_inference))
+ mov(reg_relu_ns, reinterpret_cast<size_t>(&jcp.eltwise.alpha));
+ if (jcp.prop_kind == backward_weights)
+ mov(reg_output_stride, ptr[param1 + GET_OFF(output_stride)]);
+
+ auto load_loop_body = [=](int load_loop_blk) {
+ bcast_loop(load_loop_blk);
+ add(reg_load_data, load_loop_blk * jcp.load_loop_load_step);
+ switch (jcp.prop_kind) {
+ case forward_training:
+ case forward_inference:
+ add(reg_bias_data,
+ load_loop_blk * jcp.load_block * jcp.typesize_out);
+ add(reg_output_data,
+ load_loop_blk * jcp.bcast_dim * jcp.load_block *
+ jcp.typesize_out);
+ break;
+ case backward_data:
+ add(reg_output_data,
+ load_loop_blk * jcp.bcast_dim * jcp.load_block *
+ jcp.typesize_out);
+ break;
+ case backward_weights:
+ for (int i_load = 0; i_load < load_loop_blk; i_load++)
+ add(reg_output_data, reg_output_stride);
+ break;
+ default:
+ assert(!"invalid prop_kind");
+ }
+ sub(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step);
+ };
+
+ const int simd_w = 16;
+
+ Label load_loop_blk[7];
+
+ static const int ur_cases_fma_embd_bcast[] = { 2, 4, 5, 8, 14, 32 };
+ static const int ur_cases_fma_expl_bcast[] = { 2, 5, 6, 9, 14, 32 };
+ static const int ur_cases_4fma[] = { 2, 4, 6, 12, 32 };
+
+ const int size_ur_cases_fma
+ = (jcp.ver == ver_avx512_core && jcp.expl_bcast) ?
+ sizeof(ur_cases_fma_expl_bcast) :
+ sizeof(ur_cases_fma_embd_bcast);
+ const int size_ur_cases_4fma = sizeof(ur_cases_4fma);
+
+ const int *ur_cases_fma = (jcp.ver == ver_avx512_core && jcp.expl_bcast) ?
+ ur_cases_fma_expl_bcast :
+ ur_cases_fma_embd_bcast;
+ const int *ur_cases = jcp.ver == ver_4fma ? ur_cases_4fma : ur_cases_fma;
+ const int num_ur_cases =
+ (jcp.ver == ver_4fma ? size_ur_cases_4fma : size_ur_cases_fma)
+ / sizeof(*ur_cases);
+
+ for (int ur_idx = num_ur_cases - 1; ur_idx > 0; ur_idx--) {
+ int label_idx = num_ur_cases - ur_idx - 1;
+ if (jcp.ur <= ur_cases[ur_idx]) {
+ cmp(reg_load_loop_work, simd_w * (label_idx + 1));
+ jle(load_loop_blk[label_idx], T_NEAR);
+ }
+ }
+
+ for (int ur_idx = 0; ur_idx < num_ur_cases; ur_idx++) {
+ if (jcp.ur <= ur_cases[ur_idx]) {
+ int label_idx = num_ur_cases - ur_idx - 1;
+ L(load_loop_blk[label_idx]);
+ {
+ if (label_idx == 0) {
+ cmp(reg_load_loop_work, 0);
+ je(load_loop_blk[num_ur_cases], T_NEAR);
+ }
+ load_loop_body(label_idx + 1);
+ if (label_idx - 1 > 0) {
+ cmp(reg_load_loop_work, 2 * label_idx * simd_w);
+ je(load_loop_blk[label_idx - 1], T_NEAR);
+ }
+ cmp(reg_load_loop_work, (label_idx + 1) * simd_w);
+ jge(load_loop_blk[label_idx]);
+ }
+ for (int idx = label_idx - 1; idx > 0; --idx) {
+ cmp(reg_load_loop_work, simd_w * (idx + 1));
+ je(load_loop_blk[idx], T_NEAR);
+ }
+ if (ur_idx < num_ur_cases - 2) {
+ cmp(reg_load_loop_work, simd_w);
+ jle(load_loop_blk[0], T_NEAR);
+ }
+ }
+ }
+ L(load_loop_blk[num_ur_cases]);
+
+ add(rsp, stack_space_needed);
+
+ postamble();
+
+ if (jcp.with_eltwise)
+ eltwise_injector_->prepare_table();
+}
+
+bool jit_avx512_common_1x1_conv_kernel::post_ops_ok(
+ jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ const auto &p = attr.post_ops_;
+
+ auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); };
+ auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); };
+
+ switch (p.len_) {
+ case 0: return true; // no post_ops
+ case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise
+ case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise
+ default: return false;
+ }
+
+ return false;
+}
+
+status_t jit_avx512_common_1x1_conv_kernel::init_conf(jit_1x1_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d,
+ const primitive_attr_t &attr, int nthreads, bool reduce_src) {
+ if (!mayiuse(avx512_common)) return status::unimplemented;
+
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ const int simd_w = cpu_isa_traits<avx512_common>::vlen / sizeof(float);
+ const int ndims = src_d.ndims();
+
+ jcp.prop_kind = cd.prop_kind;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+
+ jcp.oc_without_padding = dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+
+ bool ok_to_pad_channels = true
+ && jcp.ngroups == 1
+ && src_d.data_type() == data_type::f32;
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ jcp.ic = rnd_up(jcp.ic, simd_w);
+ }
+
+ jcp.ih = (ndims == 3) ? 1 : src_d.dims()[2];
+ jcp.iw = src_d.dims()[ndims - 1];
+ jcp.oh = (ndims == 3) ? 1 : dst_d.dims()[2];
+ jcp.ow = dst_d.dims()[ndims - 1];
+
+ jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + 2];
+ jcp.kw = weights_d.dims()[with_groups + ndims - 1];
+
+ jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][ndims - 3];
+
+ jcp.stride_h = (ndims == 3) ? 1 : cd.strides[0];
+ jcp.stride_w = cd.strides[ndims - 3];
+
+ jcp.with_bias = pick_by_prop_kind(jcp.prop_kind, cd.bias_desc.format_kind,
+ format_kind::undef, cd.diff_bias_desc.format_kind)
+ != format_kind::undef;
+
+ jcp.os = jcp.oh * jcp.ow;
+ jcp.is = jcp.ih * jcp.iw;
+ jcp.tr_is = rnd_up(jcp.is, 4);
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ jcp.with_sum = p.find(primitive_kind::sum) != -1;
+ const int eltwise_ind = p.find(primitive_kind::eltwise);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise) {
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+ if (dst_d.data_type() == data_type::s32) return status::unimplemented;
+ }
+
+ auto dat_tag = pick(ndims - 3, nCw16c, nChw16c);
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag);
+
+ bool args_ok = true
+ && jcp.ngroups == 1
+ && jcp.src_tag == dat_tag
+ && jcp.dst_tag == dat_tag;
+ if (!args_ok) return status::unimplemented;
+
+ args_ok = true
+ && jcp.oc % simd_w == 0 && jcp.ic % simd_w == 0
+ && jcp.t_pad == 0 && jcp.l_pad == 0
+ && jcp.stride_w == 1 && jcp.stride_h == 1 // TODO: support some strides
+ && jcp.kh == 1 && jcp.kw == 1;
+ if (!args_ok) return status::unimplemented;
+
+ jcp.ic_block = jcp.oc_block = simd_w;
+ jcp.transpose_src = false;
+
+ if (everyone_is(data_type::f32, src_d.data_type(),
+ weights_d.data_type(), dst_d.data_type()))
+ {
+ const int is_bwd_d = jcp.prop_kind == backward_data;
+ format_tag_t wei_tag = with_groups
+ ? pick(2 * ndims - 6 + is_bwd_d, gOIw16i16o, gIOw16o16i,
+ gOIhw16i16o, gIOhw16o16i)
+ : pick(2 * ndims - 6 + is_bwd_d, OIw16i16o, IOw16o16i,
+ OIhw16i16o, IOhw16o16i);
+
+ jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag);
+ if (jcp.wei_tag != wei_tag)
+ return status::unimplemented;
+
+ if (jcp.prop_kind != backward_weights && mayiuse(avx512_mic_4ops) &&
+ ((jcp.prop_kind == backward_data) ? jcp.oc_block : jcp.ic_block) % 4
+ == 0) {
+ jcp.ver = ver_4fma;
+ jcp.fma_step = 4;
+ } else if (jcp.prop_kind == backward_weights && mayiuse(avx512_mic_4ops)
+ && !reduce_src
+ /* Heuristic condition for relation of src size to oc. Otherwise
+ the src transposition overhead exceed the benefit from 4fma
+ */
+ && ((jcp.is * jcp.ic) / jcp.oc <= 2048)
+ && mkldnn_thr_syncable()
+ )
+ {
+ jcp.transpose_src = true;
+ jcp.ver = ver_4fma;
+ jcp.fma_step = 4;
+ } else {
+ jcp.ver = (mayiuse(avx512_core)) ? ver_avx512_core : ver_fma;
+ jcp.fma_step = 1;
+ }
+ jcp.typesize_in = sizeof(prec_traits<data_type::f32>::type);
+ jcp.typesize_out = sizeof(prec_traits<data_type::f32>::type);
+ } else {
+ return status::unimplemented;
+ }
+
+ /* once all the formats are set, check the padding consistency */
+ args_ok = true
+ && jcp.ic <= src_d.padded_dims()[1]
+ && jcp.oc <= dst_d.padded_dims()[1]
+ && jcp.ic <= weights_d.padded_dims()[with_groups + 1]
+ && jcp.oc <= weights_d.padded_dims()[with_groups + 0];
+ if (!args_ok) return status::unimplemented;
+
+ const int SMALL_SPATIAL = 10;
+ const int BIG_SPATIAL = 28;
+ const int BIG_REDUCE_DIM = 1024;
+ const int BIG_LOAD_DIM = 256;
+
+ int load_blocking{ 0 };
+ int load_blocking_max{ 0 };
+ int bcast_blocking{ 0 };
+ int bcast_blocking_max{ 0 };
+ int reduce_blocking{ 0 };
+ int reduce_blocking_max{ 0 };
+
+ jcp.load_grp_count = 1;
+
+ const int L1_capacity = get_cache_size(1, true) / sizeof(float);
+ const int L2_size = get_cache_size(2, true) / sizeof(float);
+ const int L2_capacity = (L2_size * 3) / 4;
+
+ if (one_of(jcp.prop_kind, forward_training, forward_inference,
+ backward_data)) {
+ if (one_of(jcp.prop_kind, forward_training, forward_inference)) {
+ jcp.reduce_dim = jcp.ic;
+ jcp.reduce_block = jcp.ic_block;
+
+ jcp.load_dim = jcp.oc;
+ jcp.load_block = jcp.oc_block;
+
+ jcp.bcast_dim = jcp.is;
+ } else {
+ jcp.reduce_dim = jcp.oc;
+ jcp.reduce_block = jcp.oc_block;
+
+ jcp.load_dim = jcp.ic;
+ jcp.load_block = jcp.ic_block;
+
+ jcp.bcast_dim = jcp.os;
+ }
+ jcp.reduce_loop_unroll = jcp.reduce_block;
+ jcp.reduce_loop_bcast_step
+ = jcp.reduce_loop_unroll * jcp.bcast_dim * jcp.typesize_in;
+
+ jcp.reduce_loop_load_step
+ = jcp.reduce_loop_unroll * jcp.load_block * jcp.typesize_in;
+ jcp.load_loop_load_step
+ = jcp.reduce_dim * jcp.load_block * jcp.typesize_in;
+
+ // adjusting registry blocking
+ int max_regs, min_regs, size_treshold, ur_step;
+ const int spatial
+ = (one_of(jcp.prop_kind, forward_training, forward_inference)) ?
+ jcp.oh :
+ jcp.ih;
+ if (jcp.ver == ver_avx512_core && (8 * jcp.mb) / nthreads >= 1) {
+ max_regs = 9;
+ min_regs = 6;
+ size_treshold = 14;
+ ur_step = 1;
+ jcp.expl_bcast = true;
+
+ if (jcp.load_dim > 128 && jcp.load_dim < BIG_LOAD_DIM
+ && spatial > SMALL_SPATIAL && spatial < BIG_SPATIAL) {
+ max_regs = 6;
+ min_regs = 5;
+ }
+ } else {
+ max_regs = jcp.ver == ver_4fma ? 28 : 30;
+ min_regs = 9;
+ size_treshold = jcp.ver == ver_4fma ? 28 : 14;
+ ur_step = jcp.ver == ver_4fma ? 4 : 1;
+ jcp.expl_bcast = false;
+ jcp.use_vmovntps = true;
+ }
+ jcp.ur = 1;
+ for (int ur_w = max_regs; ur_w >= min_regs; ur_w -= ur_step) {
+ if ((spatial >= size_treshold && spatial % ur_w == 0)
+ || (spatial < size_treshold && jcp.os % ur_w == 0)) {
+ jcp.ur = ur_w;
+ break;
+ }
+ }
+ if (jcp.ur == 1) {
+ jcp.ur = nstl::min(max_regs, jcp.os);
+ int os_tail = jcp.os % max_regs;
+ for (int i = max_regs; i >= min_regs; i -= ur_step) {
+ int i_tail = jcp.os % i;
+ if (i_tail > os_tail || i_tail == 0) {
+ jcp.ur = i;
+ os_tail = i_tail;
+ if (i_tail == 0)
+ break;
+ }
+ }
+ }
+
+ jcp.reduce_loop_unroll = jcp.reduce_block;
+ jcp.reduce_loop_bcast_step
+ = jcp.reduce_loop_unroll * jcp.bcast_dim * jcp.typesize_in;
+
+ jcp.bcast_block = jcp.ur;
+
+ jcp.bcast_loop_output_step = jcp.ur * jcp.load_block * jcp.typesize_out;
+ jcp.bcast_loop_output_substep = -1; // unused
+ jcp.bcast_loop_bcast_step = jcp.ur * jcp.reduce_block * jcp.typesize_in;
+ jcp.bcast_loop_bcast_substep = -1; // unused
+
+ jcp.load_loop_iter_step = jcp.load_block;
+
+ if (jcp.prop_kind == backward_data)
+ jcp.loop_order = loop_lbr;
+ else
+ jcp.loop_order = reduce_src ? loop_blr : loop_lbr;
+
+ int nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block);
+ int nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block);
+ int nb_load = div_up(jcp.load_dim, jcp.load_block);
+
+ if (jcp.ver == ver_avx512_core && jcp.expl_bcast) {
+ if (jcp.load_dim <= BIG_LOAD_DIM && spatial > SMALL_SPATIAL
+ && spatial < BIG_SPATIAL)
+ reduce_blocking = nstl::min(jcp.reduce_dim, 80);
+ else if (spatial > SMALL_SPATIAL)
+ reduce_blocking = nstl::min(jcp.reduce_dim, 512);
+ else
+ reduce_blocking = nstl::min(jcp.reduce_dim, 256);
+
+ if ((jcp.mb > 28 && spatial >= 28)
+ || (jcp.mb > 112 && spatial >= 17))
+ jcp.use_vmovntps = true;
+ else
+ jcp.use_vmovntps = false;
+ } else {
+
+ reduce_blocking = nb_reduce;
+ if (spatial <= SMALL_SPATIAL && jcp.reduce_dim >= BIG_REDUCE_DIM)
+ reduce_blocking = 16;
+ else if (spatial > SMALL_SPATIAL
+ && jcp.reduce_dim >= BIG_REDUCE_DIM)
+ reduce_blocking = 8;
+ reduce_blocking = best_divider(nb_reduce, 1, reduce_blocking, true);
+ reduce_blocking *= jcp.reduce_block;
+ }
+
+ // Check input data cache aliasing.
+ // For other ISA constants may be updated.
+ // 64 * 1024 is chosen due to 1MB L2 16-way cache.
+ // 7 is empirical value. It is about half of 16.
+ // So we leave about half of the set for other data - weights, dst
+ int way_size = (64 * 1024) / jcp.typesize_in;
+ int max_hits = 7;
+ if (jcp.bcast_dim * reduce_blocking > way_size * max_hits) {
+ int nrb = reduce_blocking / simd_w;
+ int sp = jcp.bcast_dim;
+ int wl = way_size / simd_w;
+ for (int start_off = 0; start_off < jcp.ur; start_off++) {
+ for (int off = start_off, hits = 0; off < sp * nrb; off += wl) {
+ if (off % sp >= jcp.ur || ++hits < max_hits)
+ continue;
+ int max_r_blocking = simd_w * nstl::max(1, (off + wl) / sp);
+ reduce_blocking
+ = nstl::min(reduce_blocking, max_r_blocking);
+ break;
+ }
+ }
+ }
+
+ if (reduce_blocking < jcp.reduce_dim) {
+ jcp.use_vmovntps = false;
+ if (jcp.prop_kind == backward_data)
+ jcp.loop_order = reduce_src ? loop_lbr : loop_rlb;
+ else
+ jcp.loop_order = reduce_src ? loop_rbl : loop_rlb;
+ }
+ load_blocking = jcp.load_dim;
+
+ int load_size = jcp.load_dim * jcp.reduce_dim;
+ int bcast_size = jcp.mb * jcp.ngroups * jcp.bcast_dim * jcp.reduce_dim;
+
+ if (jcp.ver == ver_avx512_core && nthreads <= 28 && jcp.mb < nthreads
+ && nb_load * nb_bcast > nthreads) {
+ // Some heuristic here
+ float calc_koef = 0.01, best_cost = FLT_MAX;
+ int n_lgc = nthreads;
+ float ratio = (float)load_size / (float)bcast_size;
+ int best_lgc = ratio > 1 ? n_lgc : 1;
+ auto calc_job_cost = [&](int lb, int tg, float mem_k) {
+ int bb_size = jcp.mb * div_up(nb_bcast, tg);
+ float calc_size = (float)(bb_size * jcp.ur)
+ * (lb * jcp.load_block) * jcp.reduce_dim;
+ float mem_size = (float)(bb_size * jcp.ur + lb * jcp.load_block)
+ * jcp.reduce_dim;
+ return calc_koef * calc_size + mem_k * mem_size;
+ };
+ for (int lgc, ilgc = 0; ilgc < n_lgc; ilgc++) {
+ lgc = ratio > 1 ? n_lgc - ilgc : ilgc + 1;
+ int min_lb = nb_load / lgc;
+ int max_lb = div_up(nb_load, lgc);
+ int min_tg = nthreads / lgc;
+ int max_tg = div_up(nthreads, lgc);
+ // Some heuristic here
+ float mem_koef = (max_tg == 1) ? 1.f : 1.3f;
+ float job_cost = 0.;
+ if (nthreads % lgc < nb_load % lgc) {
+ job_cost = calc_job_cost(max_lb, min_tg, mem_koef);
+ } else {
+ auto job_cost1 = calc_job_cost(max_lb, max_tg, mem_koef);
+ auto job_cost2 = calc_job_cost(min_lb, min_tg, mem_koef);
+ job_cost = nstl::max(job_cost1, job_cost2);
+ }
+
+ if (job_cost < best_cost) {
+ best_lgc = lgc;
+ best_cost = job_cost;
+ }
+ }
+ jcp.load_grp_count = best_lgc;
+ load_blocking = div_up(nb_load, jcp.load_grp_count) * jcp.load_block;
+ } else {
+ jcp.load_grp_count = div_up(nthreads, jcp.mb * jcp.ngroups * nb_bcast);
+ jcp.load_grp_count = best_divider(
+ nthreads, jcp.load_grp_count, 2 * jcp.load_grp_count, false);
+ }
+
+ if (jcp.ver == ver_avx512_core && jcp.expl_bcast && jcp.bcast_dim <= 64
+ && load_size >= L2_size) {
+ jcp.load_grp_count = nstl::max(jcp.load_grp_count, 4);
+ } else if (jcp.bcast_dim <= 49 && jcp.mb <= nthreads
+ && jcp.load_dim > 512 && jcp.load_dim / jcp.reduce_dim >= 4) {
+ jcp.load_grp_count = nstl::max(jcp.load_grp_count, 2);
+ load_blocking = jcp.load_block;
+ }
+
+ if (jcp.ver == ver_4fma && jcp.bcast_dim * jcp.mb < jcp.load_dim
+ && jcp.oh * jcp.ow > 64
+ && IMPLICATION(reduce_src, jcp.load_dim < 1024)) {
+ /* Looking for best loading dimension blocking
+ * to get the best thread and data read/write efficiency
+ * by finding the optimal 'load_chunk' value
+ * Example:
+ * for 72 threads and convolution with mb=1, ih=iw=7, oc = 512
+ * the 'best' load_chunk value should be 1
+ * TODO: remove heuristic constants in above condition
+ * TODO: check this blocking for other ISA
+ */
+ float best_eff = -1.f;
+ int best_lgc = 1;
+
+ for (int load_chunk = 1; load_chunk <= nb_load; load_chunk++) {
+ int lgc = div_up(nb_load, load_chunk);
+ if (lgc > nthreads)
+ continue;
+ int thr_per_grp = div_up(nthreads, lgc);
+ int bcast_per_thr = div_up(jcp.mb * nb_bcast, thr_per_grp)
+ * jcp.bcast_block;
+ int load_per_thr = load_chunk * simd_w;
+ float data_norm = (bcast_per_thr + load_per_thr) / 2.f;
+ float data_eff = (bcast_per_thr * load_per_thr)
+ / (data_norm * data_norm);
+ float thr_eff_over_grp = (float)nstl::max(1, nthreads / lgc)
+ / div_up(nthreads, lgc);
+ float thr_eff_in_grp = ((float)jcp.mb * nb_bcast)
+ / rnd_up(jcp.mb * nb_bcast, thr_per_grp);
+ float thr_eff = thr_eff_over_grp * thr_eff_in_grp;
+ float load_eff = (float)nb_load / rnd_up(nb_load, lgc);
+ float overall_eff = data_eff + thr_eff + load_eff;
+ if (overall_eff > best_eff) {
+ best_eff = overall_eff;
+ best_lgc = lgc;
+ }
+ }
+ jcp.load_grp_count = best_lgc;
+ load_blocking
+ = div_up(nb_load, jcp.load_grp_count) * jcp.load_block;
+ }
+ bcast_blocking = div_up(jcp.mb * jcp.ngroups * nb_bcast,
+ div_up(nthreads, jcp.load_grp_count))
+ * jcp.bcast_block;
+ bcast_blocking = nstl::min(jcp.bcast_dim, bcast_blocking);
+ bcast_blocking = rnd_up(bcast_blocking, jcp.bcast_block);
+
+ int space_for_bcast
+ = (L2_capacity - /* kernel_size - */
+ 2 * jcp.load_block * reduce_blocking
+ - jcp.ur * reduce_blocking - 3 * 1024);
+ if (jcp.reduce_dim * jcp.bcast_dim > L2_capacity)
+ space_for_bcast /= 2;
+
+ int bcast_in_cache
+ = nstl::max(jcp.bcast_block, space_for_bcast / reduce_blocking);
+ bcast_blocking = nstl::min(
+ bcast_blocking, rnd_dn(bcast_in_cache, jcp.bcast_block));
+
+ load_blocking_max = load_blocking;
+ bcast_blocking_max = bcast_blocking * 3 / 2;
+ reduce_blocking_max = reduce_blocking;
+
+ } else if (jcp.prop_kind == backward_weights) {
+
+ jcp.use_vmovntps = false;
+ if (jcp.is > SMALL_SPATIAL * SMALL_SPATIAL && jcp.ver == ver_4fma)
+ jcp.use_vmovntps = true;
+
+ if (jcp.transpose_src)
+ jcp.reduce_dim = jcp.tr_is;
+ else
+ jcp.reduce_dim = jcp.is;
+
+ if (jcp.ver == ver_4fma) {
+ // reduce_block should be divided by fma_step
+ jcp.reduce_block = best_divider(jcp.reduce_dim, 4, 16, true, 4);
+ } else {
+ jcp.reduce_block = best_divider(jcp.reduce_dim, 7, 16, true);
+ if (jcp.reduce_dim % jcp.reduce_block != 0)
+ jcp.reduce_block = best_divider(jcp.iw, 4, jcp.iw, false);
+ if (jcp.reduce_block > 256) {
+ jcp.reduce_block = 1;
+ }
+
+ }
+
+ jcp.load_dim = jcp.oc;
+ jcp.load_block = jcp.oc_block;
+
+ jcp.bcast_dim = jcp.ic;
+ jcp.bcast_block = jcp.ic_block;
+
+ if (jcp.ver == ver_avx512_core && jcp.reduce_block <= 19) {
+ // if reduce_block is big then generated JIT code may be big
+ // for small values of ur because reduce_loop_unroll = reduce_block
+ jcp.ur = jcp.bcast_block / 2;
+ jcp.expl_bcast = true;
+ } else {
+ jcp.ur = jcp.bcast_block;
+ jcp.expl_bcast = false;
+ }
+
+ jcp.reduce_loop_unroll = jcp.reduce_block;
+ jcp.reduce_loop_bcast_step
+ = jcp.reduce_loop_unroll * jcp.ic_block * jcp.typesize_in;
+ jcp.reduce_loop_load_step
+ = jcp.reduce_loop_unroll * jcp.oc_block * jcp.typesize_in;
+
+ jcp.bcast_loop_output_step =
+ jcp.oc_block * jcp.ic_block * jcp.typesize_out;
+ jcp.bcast_loop_output_substep =
+ jcp.oc_block * jcp.ur * jcp.typesize_out;
+ jcp.bcast_loop_bcast_step =
+ jcp.ic_block * jcp.reduce_dim * jcp.typesize_in;
+ jcp.bcast_loop_bcast_substep = jcp.ur * jcp.typesize_in;
+
+ jcp.load_loop_load_step = jcp.oc_block * jcp.os * jcp.typesize_in;
+ jcp.load_loop_iter_step = jcp.oc_block;
+
+ /* --- */
+ balance(jcp, nthreads);
+
+ load_blocking = div_up(jcp.load_dim, jcp.load_block);
+ load_blocking = best_divider(load_blocking, 16, load_blocking, false);
+ load_blocking *= jcp.load_block;
+
+ load_blocking_max = load_blocking;
+ assert(jcp.load_dim % load_blocking == 0);
+
+ int max_bcast_blocking = div_up(jcp.bcast_dim, jcp.bcast_block);
+ int min_bcast_blocking = 5;
+
+ bcast_blocking = div_up(jcp.bcast_dim, jcp.bcast_block);
+ bcast_blocking = best_divider(
+ bcast_blocking, min_bcast_blocking, max_bcast_blocking, false);
+ bcast_blocking *= jcp.bcast_block;
+ bcast_blocking_max = bcast_blocking;
+ assert(jcp.bcast_dim % bcast_blocking == 0);
+
+ // for reduction balance
+ if (jcp.ver == ver_avx512_core) {
+ int max_reduce_blocking
+ = nstl::min(L1_capacity / jcp.ur, jcp.reduce_dim);
+ int min_reduce_blocking = nstl::min(
+ L1_capacity / jcp.ur, nstl::max(jcp.iw, jcp.ih));
+ reduce_blocking = best_divider(jcp.reduce_dim, min_reduce_blocking,
+ max_reduce_blocking, true);
+ reduce_blocking
+ = nstl::max(rnd_dn(reduce_blocking, jcp.reduce_block),
+ jcp.reduce_block);
+ } else {
+ int max_reduce_blocking = L2_capacity
+ / ((bcast_blocking + load_blocking) * jcp.reduce_block);
+ max_reduce_blocking = nstl::min(max_reduce_blocking,
+ (L1_capacity / (jcp.bcast_block)) / jcp.reduce_block);
+
+ int num_jobs = div_up(jcp.load_dim, load_blocking)
+ * div_up(jcp.bcast_dim, bcast_blocking);
+ int threads_per_job = nstl::max(1, nthreads / num_jobs);
+ reduce_blocking = div_up(jcp.mb * jcp.reduce_dim, jcp.reduce_block);
+ reduce_blocking = div_up(reduce_blocking, threads_per_job);
+
+ reduce_blocking = best_divider(reduce_blocking,
+ max_reduce_blocking - 2, max_reduce_blocking, true);
+ reduce_blocking *= jcp.reduce_block;
+ }
+
+ reduce_blocking_max = rnd_dn(reduce_blocking * 3 / 2, jcp.reduce_block);
+ } else
+ return status::unimplemented;
+
+ assert(load_blocking);
+ assert(load_blocking_max);
+ assert(bcast_blocking);
+ assert(bcast_blocking_max);
+ assert(reduce_blocking);
+ assert(reduce_blocking_max);
+ assert(load_blocking % jcp.load_block == 0);
+ assert(reduce_blocking % jcp.reduce_block == 0);
+ assert(load_blocking_max % jcp.load_block == 0);
+ assert(reduce_blocking_max % jcp.reduce_block == 0);
+ if (jcp.ver == ver_4fma) {
+ assert(jcp.reduce_loop_unroll % jcp.fma_step == 0);
+ assert(jcp.reduce_dim % jcp.reduce_loop_unroll == 0);
+ }
+
+ assert(jcp.bcast_block % jcp.ur == 0);
+ assert(jcp.reduce_dim % jcp.reduce_block == 0);
+
+ jcp.ur_tail = jcp.bcast_dim % jcp.ur;
+
+ jcp.nb_bcast_blocking = bcast_blocking / jcp.bcast_block;
+ jcp.nb_bcast_blocking_max = bcast_blocking_max / jcp.bcast_block;
+ jcp.nb_load_blocking = load_blocking / jcp.load_block;
+ jcp.nb_load_blocking_max = load_blocking_max / jcp.load_block;
+ jcp.nb_reduce_blocking = reduce_blocking / jcp.reduce_block;
+ jcp.nb_reduce_blocking_max = reduce_blocking_max / jcp.reduce_block;
+
+ jcp.nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block);
+ jcp.nb_load = div_up(jcp.load_dim, jcp.load_block);
+ jcp.nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block);
+
+ return status::success;
+}
+
+void jit_avx512_common_1x1_conv_kernel::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad,
+ const jit_1x1_conv_conf_t &jcp) {
+ using namespace mkldnn::impl::memory_tracking::names;
+
+ if (jcp.prop_kind != backward_data && jcp.with_bias
+ && jcp.oc != jcp.oc_without_padding)
+ scratchpad.book(key_conv_padded_bias, jcp.typesize_out * jcp.oc);
+
+ if (jcp.prop_kind == backward_weights) {
+ const size_t wei_size = (size_t)jcp.ngroups * jcp.oc * jcp.ic;
+ scratchpad.book(key_conv_wei_reduction,
+ jcp.typesize_out * wei_size * (jcp.nthr_mb - 1));
+ }
+
+ if (jcp.transpose_src) {
+ const size_t tr_src_size =
+ (size_t)jcp.nthr_mb * jcp.ngroups * jcp.ic * jcp.tr_is;
+ scratchpad.book(key_conv_tr_src, jcp.typesize_out * tr_src_size);
+ scratchpad.book(key_conv_tr_src_bctx,
+ sizeof(simple_barrier::ctx_t) * jcp.nthr);
+ }
+}
+
+void jit_avx512_common_1x1_conv_kernel::balance(jit_1x1_conv_conf_t &jcp,
+ int nthreads)
+{
+ // initialize jcp reduction threading properties
+ jcp.nthr = jcp.nthr_mb = jcp.nthr_g = jcp.nthr_oc_b = jcp.nthr_ic_b = 1;
+ if (nthreads < jcp.ngroups) {
+ /* simplification... fortunately it doesn't hurt much */
+ return;
+ }
+ const int nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block);
+ const int nb_load = div_up(jcp.load_dim, jcp.load_block);
+ const int nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block);
+
+ jcp.nthr_g = jcp.ngroups;
+ const int nthr = nthreads / jcp.nthr_g;
+
+ auto calc_mem_cost = [=](int nthr_mb, int nthr_oc_b, int nthr_ic_b) {
+ /* calculate per thread memory cost (read/write). high level
+ * optimizer tries to minimize memory consumption. few notes: (n1)
+ * unclear why, but that essentially helps first convolution...
+ * (n2) assuming the reduction over minibatch is always there:
+ * - instead of 8 it should be 5 here (write ~= 2 read):
+ * kernel: temporal workspace 1 write
+ * reduction: 1 read from workspace and 1 write to the diff_wei
+ * - but experiments showed 8 works better than 5 or 6... */
+ int bcast_koeff = 1;
+ int load_koeff = 1;
+ int output_koeff = 12;
+ if (jcp.transpose_src) {
+ bcast_koeff = 5;
+ load_koeff = 1;
+ output_koeff = 8;
+ }
+ return 0
+ + (size_t)bcast_koeff * div_up(jcp.mb * nb_reduce, nthr_mb)
+ * div_up(jcp.ngroups, jcp.nthr_g)
+ * div_up(nb_bcast, nthr_ic_b) * jcp.ic_block * jcp.reduce_block
+ / jcp.stride_h / jcp.stride_w /* (n1) */
+ + (size_t)load_koeff * div_up(jcp.mb * nb_reduce, nthr_mb)
+ * div_up(jcp.ngroups, jcp.nthr_g)
+ * div_up(nb_load, nthr_oc_b) * jcp.oc_block * jcp.reduce_block
+ + (size_t)output_koeff /* (n2) */
+ * div_up(jcp.ngroups, jcp.nthr_g) * div_up(nb_load, nthr_oc_b)
+ * div_up(nb_bcast, nthr_ic_b) * jcp.ic_block
+ * jcp.oc_block;
+ };
+
+ int nthr_mb = 1, nthr_oc_b = 1, nthr_ic_b = 1;
+ auto best_mem_cost = calc_mem_cost(nthr_mb, nthr_oc_b, nthr_ic_b);
+
+ /* step 1: find the best thread distribution with lowest memory cost */
+ const int nthr_mb_max = nstl::min(nthr, jcp.mb * nb_reduce);
+ for (nthr_mb = 1; nthr_mb <= nthr_mb_max; ++nthr_mb) {
+ const int nthr_par = nthr / nthr_mb;
+ const int nthr_oc_b_max = nstl::min(nthr_par, nb_load);
+ for (nthr_oc_b = 1; nthr_oc_b <= nthr_oc_b_max; ++nthr_oc_b) {
+ nthr_ic_b = nstl::min(nthr_par / nthr_oc_b, nb_bcast);
+ auto mem_cost = calc_mem_cost(nthr_mb, nthr_oc_b, nthr_ic_b);
+ if (mem_cost <= best_mem_cost) {
+ best_mem_cost = mem_cost;
+ jcp.nthr_mb = nthr_mb;
+ jcp.nthr_oc_b = nthr_oc_b;
+ jcp.nthr_ic_b = nthr_ic_b;
+ }
+ }
+
+ if (!mkldnn_thr_syncable()) { assert(nthr_mb == 1); break; }
+ }
+ if (jcp.nthr_mb > nthreads / 2 && jcp.nthr_mb < nthreads)
+ jcp.nthr_mb = nstl::min(jcp.mb, nthreads);
+
+ jcp.nthr = jcp.nthr_mb * jcp.nthr_g * jcp.nthr_oc_b * jcp.nthr_ic_b;
+ assert(jcp.nthr <= nthreads);
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.hpp
new file mode 100644
index 0000000000..d2ae017943
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_conv_kernel.hpp
@@ -0,0 +1,108 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_AVX512_COMMON_1x1_CONV_KERNEL_HPP
+#define JIT_AVX512_COMMON_1x1_CONV_KERNEL_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+#include "jit_uni_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_avx512_common_1x1_conv_kernel : public jit_generator {
+ jit_avx512_common_1x1_conv_kernel(jit_1x1_conv_conf_t ajcp,
+ const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr)
+ {
+ if (jcp.with_eltwise)
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<avx512_common>(
+ this, jcp.eltwise);
+
+ this->generate();
+ jit_ker = (void (*)(jit_1x1_conv_call_s *)) this->getCode();
+ }
+
+ ~jit_avx512_common_1x1_conv_kernel() {
+ delete eltwise_injector_;
+ }
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_1x1_conv_kernel)
+
+ static bool post_ops_ok(jit_1x1_conv_conf_t &jcp,
+ const primitive_attr_t &attr);
+
+ static status_t init_conf(jit_1x1_conv_conf_t &jcp,
+ const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d,
+ const primitive_attr_t &attr,
+ int nthreads, bool reduce_src);
+
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_1x1_conv_conf_t &jcp);
+
+ jit_1x1_conv_conf_t jcp;
+ const primitive_attr_t &attr_;
+ void (*jit_ker)(jit_1x1_conv_call_s *);
+
+ private:
+ using reg64_t = const Xbyak::Reg64;
+ using zmm_t = const Xbyak::Zmm;
+
+ reg64_t reg_bcast_data = r8;
+ reg64_t reg_load_data = r10;
+ reg64_t reg_output_data = r9;
+ reg64_t aux_reg_bcast_data = r14;
+ reg64_t aux1_reg_bcast_data = rbx;
+ reg64_t aux_reg_load_data = r15;
+ reg64_t imm_addr64 = aux_reg_load_data;
+ reg64_t aux_reg_output_data = abi_not_param1;
+ reg64_t reg_load_loop_work = rsi;
+ reg64_t reg_reduce_loop_work = r11;
+ reg64_t bcast_loop_iter = rdx;
+ reg64_t reduce_loop_iter = abi_param1;
+ reg64_t reg_reduce_pos_flag = rax;
+ reg64_t reg_output_stride = r13;
+ reg64_t reg_bias_data = r12;
+ reg64_t reg_relu_ns = r13;
+ reg64_t reg_bcast_loop_work = aux1_reg_bcast_data;
+
+ Xbyak::Zmm vreg_bcast = Xbyak::Zmm(31);
+
+ jit_uni_eltwise_injector_f32<avx512_common> *eltwise_injector_;
+
+ int bcast_loop_work_offt = 0;
+ int stack_space_needed = 16;
+
+ void bcast_loop(int load_loop_blk);
+ void reduce_loop(int load_loop_blk, int ur, int substep, bool wraparound);
+
+ void generate();
+ static void balance(jit_1x1_conv_conf_t &jcp, int nthreads);
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.cpp
new file mode 100644
index 0000000000..54d58c8a39
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.cpp
@@ -0,0 +1,816 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_generator.hpp"
+
+#include "jit_avx512_common_1x1_convolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+#define data_blk_off(f, n, c, h, w) \
+ ((ndims == 3) \
+ ? (f).blk_off(n, c, w) \
+ : (f).blk_off(n, c, h, w))
+
+
+namespace {
+template <typename T, typename U>
+void balance2D(U nthr, U ithr, T ny, T &ny_start, T &ny_end,
+ T nx, T &nx_start, T &nx_end, T nx_divider)
+{
+ const int grp_count = nstl::min(nx_divider, nthr);
+ const int grp_size_big = nthr / grp_count + 1;
+ const int grp_size_small = nthr / grp_count;
+ const int n_grp_big = nthr % grp_count;
+ const int threads_in_big_groups = n_grp_big * grp_size_big;
+
+ const int ithr_bound_distance = ithr - threads_in_big_groups;
+ T grp, grp_ithr, grp_nthr;
+ if (ithr_bound_distance < 0) { // ithr in first groups
+ grp = ithr / grp_size_big;
+ grp_ithr = ithr % grp_size_big;
+ grp_nthr = grp_size_big;
+ } else { // ithr in last groups
+ grp = n_grp_big + ithr_bound_distance / grp_size_small;
+ grp_ithr = ithr_bound_distance % grp_size_small;
+ grp_nthr = grp_size_small;
+ }
+
+ balance211(nx, grp_count, grp, nx_start, nx_end);
+ balance211(ny, grp_nthr, grp_ithr, ny_start, ny_end);
+}
+}
+/* convolution forward */
+
+template <data_type_t src_type, data_type_t wei_type, data_type_t dst_type>
+void jit_avx512_common_1x1_convolution_fwd_t<src_type, wei_type, dst_type>::
+execute_forward(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const dst_data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ const auto &jcp = kernel_->jcp;
+ if (pd()->wants_padded_bias()) {
+ auto padded_bias = scratchpad.template get<dst_data_t>(
+ key_conv_padded_bias);
+ utils::array_copy(padded_bias, bias, jcp.oc_without_padding);
+ utils::array_set(padded_bias + jcp.oc_without_padding, 0.f,
+ jcp.oc - jcp.oc_without_padding);
+ bias = padded_bias;
+ }
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ execute_forward_thr(ithr, nthr, src, weights, bias, dst, scratchpad);
+ });
+
+ if (pd()->wants_zero_pad_dst())
+ ctx.memory(MKLDNN_ARG_DST)->zero_pad();
+}
+
+template <data_type_t src_type, data_type_t wei_type, data_type_t dst_type>
+void jit_avx512_common_1x1_convolution_fwd_t<src_type, wei_type, dst_type>::
+execute_forward_thr(const int ithr, const int nthr, const src_data_t *src,
+ const wei_data_t *weights, const dst_data_t *bias, dst_data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+ auto rtus_space = scratchpad.get<src_data_t>(key_conv_rtus_space);
+
+ const int ndims = src_d.ndims();
+ const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0];
+ const int stride_w = pd()->desc()->strides[ndims - 3];
+ const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0];
+ const int pad_l = pd()->desc()->padding[0][ndims - 3];
+
+ const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast;
+
+ auto step = [](int default_step, int remaining, int tail_step) {
+ assert(default_step <= tail_step);
+ return remaining < tail_step ? remaining : default_step;
+ };
+
+ auto p = jit_1x1_conv_call_s();
+
+ auto rp = rtus_driver_t<avx512_common>::call_params_t();
+
+ const int nb_oc = jcp.nb_load;
+ const int nb_ic = jcp.nb_reduce;
+ const int nb_ic_blocking = jcp.nb_reduce_blocking;
+ const int os_block = jcp.bcast_block;
+
+ int bcast_start{0}, bcast_end{0}, ocb_start{0}, ocb_end{0};
+ balance2D(nthr, ithr, work_amount, bcast_start, bcast_end,
+ jcp.nb_load, ocb_start, ocb_end, jcp.load_grp_count);
+
+ auto init_bcast = [&](int iwork, int &n, int &g, int &bcast_step,
+ int &oh, int &ow, int &ih, int &iw)
+ {
+ int osb{0};
+ nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb,
+ jcp.nb_bcast);
+ bcast_step = step(jcp.nb_bcast_blocking, jcp.nb_bcast - osb,
+ jcp.nb_bcast_blocking_max);
+ bcast_step = nstl::min(bcast_step, bcast_end - iwork);
+
+ const int os = osb * os_block;
+ oh = os / jcp.ow;
+ ow = os % jcp.ow;
+
+ ih = nstl::max(oh * stride_h - pad_t, 0);
+ iw = nstl::max(ow * stride_w - pad_l, 0);
+ rp.iw_start = iw;
+
+ p.bcast_dim = this_block_size(os, jcp.os,
+ bcast_step * os_block);
+ rp.os = p.bcast_dim;
+ };
+
+ auto init_load = [&](int ocb, int &load_step)
+ {
+ load_step = step(jcp.nb_load_blocking, ocb_end - ocb,
+ jcp.nb_load_blocking_max);
+ p.load_dim = this_block_size(ocb * jcp.oc_block,
+ ocb_end * jcp.oc_block, load_step * jcp.oc_block);
+ };
+
+ auto init_reduce = [&](int icb)
+ {
+ const int nb_ic_blocking_step =
+ nstl::min(icb + nb_ic_blocking, nb_ic) - icb;
+ p.first_last_flag = 0
+ | (icb == 0 ? FLAG_REDUCE_FIRST : 0)
+ | (icb + nb_ic_blocking_step >= nb_ic
+ ? FLAG_REDUCE_LAST : 0);
+
+ p.reduce_dim = this_block_size(icb * jcp.ic_block,
+ jcp.ic, nb_ic_blocking_step * jcp.ic_block);
+ rp.icb = p.reduce_dim / jcp.reduce_block;
+ };
+
+ auto inner_ker = [&](int ocb, int icb, int n, int g, int oh, int ow,
+ int ih, int iw)
+ {
+
+ const int _ocb = g * nb_oc + ocb;
+ const size_t dst_off = data_blk_off(dst_d, n, _ocb, oh, ow);
+
+ p.output_data = &dst[dst_off];
+ p.bias_data = &bias[_ocb * jcp.oc_block];
+ p.load_data = &weights[pd()->with_groups()
+ ? weights_d.blk_off(g, ocb, icb)
+ : weights_d.blk_off(ocb, icb)];
+
+ const int _icb = g * nb_ic + icb;
+ if (pd()->rtus_.reduce_src_) {
+ rp.ws = rtus_space + ithr * pd()->rtus_.space_per_thread_
+ + _icb * jcp.is * jcp.ic_block;
+ if (ocb == ocb_start) {
+ rp.src = src + data_blk_off(src_d, n, _icb, ih, iw);
+ rtus_driver_->ker_(&rp);
+ }
+ p.bcast_data = rp.ws;
+ } else
+ p.bcast_data = src + data_blk_off(src_d, n, _icb, ih, iw);
+
+ kernel_->jit_ker(&p);
+ };
+
+ if (jcp.loop_order == loop_rlb) {
+ for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) {
+ init_reduce(icb);
+ int ocb = ocb_start;
+ while (ocb < ocb_end) {
+ int load_step;
+ init_load(ocb, load_step);
+ int iwork = bcast_start;
+ while (iwork < bcast_end) {
+ int n, g, bcast_step, oh, ow, ih, iw;
+ init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw);
+ inner_ker(ocb, icb, n, g, oh, ow, ih, iw);
+ iwork += bcast_step;
+ }
+ ocb += load_step;
+ }
+ }
+ } else if (jcp.loop_order == loop_lbr) {
+ int ocb = ocb_start;
+ while (ocb < ocb_end) {
+ int load_step;
+ init_load(ocb, load_step);
+ int iwork = bcast_start;
+ while (iwork < bcast_end) {
+ int n, g, bcast_step, oh, ow, ih, iw;
+ init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw);
+ for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) {
+ init_reduce(icb);
+ inner_ker(ocb, icb, n, g, oh, ow, ih, iw);
+ }
+ iwork += bcast_step;
+ }
+ ocb += load_step;
+ }
+ } else if (jcp.loop_order == loop_rbl) {
+ for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) {
+ init_reduce(icb);
+ int iwork = bcast_start;
+ while (iwork < bcast_end) {
+ int n, g, bcast_step, oh, ow, ih, iw;
+ init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw);
+ int ocb = ocb_start;
+ while (ocb < ocb_end) {
+ int load_step;
+ init_load(ocb, load_step);
+ inner_ker(ocb, icb, n, g, oh, ow, ih, iw);
+ ocb += load_step;
+ }
+ iwork += bcast_step;
+ }
+ }
+ } else if (jcp.loop_order == loop_blr) {
+ int iwork = bcast_start;
+ while (iwork < bcast_end) {
+ int n, g, bcast_step, oh, ow, ih, iw;
+ init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw);
+ int ocb = ocb_start;
+ while (ocb < ocb_end) {
+ int load_step;
+ init_load(ocb, load_step);
+ for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) {
+ init_reduce(icb);
+ inner_ker(ocb, icb, n, g, oh, ow, ih, iw);
+ }
+ ocb += load_step;
+ }
+ iwork += bcast_step;
+ }
+ } else {
+ assert(!"unsupported loop order");
+ }
+}
+
+
+template struct jit_avx512_common_1x1_convolution_fwd_t<data_type::f32>;
+/* convolution backward wtr data */
+
+template <data_type_t diff_dst_type, data_type_t wei_type,
+ data_type_t diff_src_type>
+void jit_avx512_common_1x1_convolution_bwd_data_t<diff_dst_type, wei_type,
+ diff_src_type>::execute_backward_data(const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+
+ const auto &jcp = kernel_->jcp;
+ auto rtus_space = scratchpad(ctx).template get<diff_src_data_t>(
+ key_conv_rtus_space);
+
+ const int ndims = diff_src_d.ndims();
+
+ // TODO (Roma): remove this restriction
+ assert(jcp.stride_w == 1 && jcp.stride_h == 1);
+
+ const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0];
+ const int stride_w = pd()->desc()->strides[ndims - 3];
+ const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0];
+ const int pad_l = pd()->desc()->padding[0][ndims - 3];
+
+ const int nb_ic = jcp.nb_load;
+ const int nb_oc = jcp.nb_reduce;
+ const int os_block = jcp.bcast_block;
+ const int nb_oc_blocking = jcp.nb_reduce_blocking;
+
+ const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast;
+
+ auto step = [](int default_step, int remaining, int tail_step) {
+ assert(default_step <= tail_step);
+ return remaining < tail_step ? remaining : default_step;
+ };
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ auto p = jit_1x1_conv_call_s();
+ auto rp = rtus_driver_t<avx512_common>::call_params_t();
+
+ int bcast_start{0}, bcast_end{0}, icb_start{0}, icb_end{0};
+ balance2D(nthr, ithr, work_amount, bcast_start, bcast_end,
+ jcp.nb_load, icb_start, icb_end, jcp.load_grp_count);
+
+ bool reduce_outer = (jcp.loop_order == loop_rbl
+ || jcp.loop_order == loop_rlb);
+ int nboc_outer = reduce_outer ? nb_oc : 1;
+ int ocb_outer_step = reduce_outer ? nb_oc_blocking : 1;
+
+ int nboc_inner = reduce_outer ? 1 : nb_oc;
+ int ocb_inner_step = reduce_outer ? 1 : nb_oc_blocking;
+
+ for (int ocb_outer = 0; ocb_outer < nboc_outer;
+ ocb_outer += ocb_outer_step) {
+ size_t cur_ocb_outer =
+ nstl::min(ocb_outer + ocb_outer_step, nboc_outer) - ocb_outer;
+
+ int load_step = 0;
+ for (int icb = icb_start; icb < icb_end; icb += load_step) {
+ load_step = step(jcp.nb_load_blocking, jcp.nb_load - icb,
+ jcp.nb_load_blocking_max);
+
+ p.load_dim = this_block_size(icb * jcp.ic_block,
+ icb_end * jcp.ic_block, load_step * jcp.ic_block);
+ rp.icb = p.load_dim / jcp.ic_block;
+
+ int bcast_step;
+ for (int iwork = bcast_start; iwork < bcast_end;
+ iwork += bcast_step)
+ {
+ int n{0}, g{0}, osb{0};
+ nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb,
+ jcp.nb_bcast);
+
+ bcast_step = step(jcp.nb_bcast_blocking, jcp.nb_bcast - osb,
+ jcp.nb_bcast_blocking_max);
+ bcast_step = nstl::min(bcast_step, bcast_end - iwork);
+
+ const int os = osb * os_block;
+ p.bcast_dim = this_block_size(os, jcp.os,
+ bcast_step * os_block);
+ rp.os = p.bcast_dim;
+
+ const int oh = os / jcp.ow;
+ const int ow = os % jcp.ow;
+ const int ih = nstl::max(oh * stride_h - pad_t, 0);
+ const int iw = nstl::max(ow * stride_w - pad_l, 0);
+ rp.iw_start = iw;
+
+ const int _icb = g * nb_ic + icb;
+ rp.src = diff_src + data_blk_off(diff_src_d, n, _icb, ih, iw);
+ if (pd()->rtus_.reduce_src_) {
+ rp.ws = rtus_space
+ + ithr * pd()->rtus_.space_per_thread_;
+ p.output_data = rp.ws;
+ } else
+ p.output_data = rp.src;
+
+ for (int ocb_inner = 0; ocb_inner < nboc_inner;
+ ocb_inner += ocb_inner_step) {
+ int cur_ocb_inner =
+ nstl::min(ocb_inner + ocb_inner_step, nboc_inner) -
+ ocb_inner;
+
+ int ocb = reduce_outer ? ocb_outer : ocb_inner;
+ int nb_oc_blocking_step = reduce_outer
+ ? cur_ocb_outer : cur_ocb_inner;
+ const int _ocb = g * nb_oc + ocb;
+ size_t diff_dst_off = data_blk_off(diff_dst_d, n, _ocb, oh, ow);
+ p.bcast_data = &diff_dst[diff_dst_off];
+
+ p.load_data = &weights[pd()->with_groups()
+ ? weights_d.blk_off(g, ocb, icb)
+ : weights_d.blk_off(ocb, icb)];
+
+ p.first_last_flag = ocb == 0 ? FLAG_REDUCE_FIRST : 0;
+
+ p.reduce_dim = this_block_size(ocb * jcp.oc_block,
+ jcp.oc, nb_oc_blocking_step * jcp.oc_block);
+
+ kernel_->jit_ker(&p);
+ }
+ if (pd()->rtus_.reduce_src_)
+ rtus_driver_->ker_(&rp);
+ }
+ }
+ }
+ });
+}
+
+template struct jit_avx512_common_1x1_convolution_bwd_data_t<data_type::f32>;
+
+/* convolution backward wtr weights */
+
+#define wht_blk_off(d, g, ...) \
+ (pd()->with_groups() \
+ ? (d).blk_off((g), __VA_ARGS__) \
+ : (d).blk_off(__VA_ARGS__))
+
+jit_avx512_common_1x1_convolution_bwd_weights_t ::
+ jit_avx512_common_1x1_convolution_bwd_weights_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , kernel_(nullptr), acc_ker_(nullptr), reducer_bias_(nullptr)
+ , trans_kernel_(nullptr), rtus_driver_(nullptr)
+{
+ kernel_ = new jit_avx512_common_1x1_conv_kernel(pd()->jcp_, *pd()->attr());
+ acc_ker_ = new cpu_accumulator_1d_t<data_type::f32>();
+ reducer_bias_ = new cpu_reducer_t<data_type::f32>(pd()->reducer_bia_conf_);
+ init_rtus_driver<avx512_common>(this);
+
+ const auto &jcp = kernel_->jcp;
+
+ if (jcp.transpose_src) {
+ auto tp = jit_transpose4x16_src_t();
+ tp.src_pf0_distance = 4;
+ tp.tr_src_pf0_distance = 0;
+ tp.src_pf1 = true;
+ tp.tr_src_pf1 = false;
+ trans_kernel_ = new jit_transpose4x16_src(&jcp, &tp);
+ }
+}
+
+void jit_avx512_common_1x1_convolution_bwd_weights_t::execute_backward_weights(
+ const exec_ctx_t &ctx) const
+{
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS);
+ auto diff_bias_in = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+
+ const auto scratchpad = this->scratchpad(ctx);
+
+ auto rtus_space = scratchpad.get<data_t>(key_conv_rtus_space);
+ data_t *diff_bias = pd()->wants_padded_bias()
+ ? scratchpad.get<data_t>(key_conv_padded_bias) : diff_bias_in;
+ auto wei_reduction = scratchpad.get<data_t>(key_conv_wei_reduction);
+
+ /* prepare src transposition barriers */
+ auto tr_src = scratchpad.get<data_t>(key_conv_tr_src);
+ auto tr_src_bctx = scratchpad.get<simple_barrier::ctx_t>(
+ key_conv_tr_src_bctx);
+ if (jcp.transpose_src) {
+ for (int i = 0; i < jcp.nthr; ++i)
+ simple_barrier::ctx_init(&tr_src_bctx[i]);
+ }
+
+ const int ndims = src_d.ndims();
+ const int wei_size = jcp.ngroups * jcp.oc * jcp.ic;
+
+ simple_barrier::ctx_t reduction_barrier;
+ simple_barrier::ctx_init(&reduction_barrier);
+
+ const auto reducer_bia_scratchpad = memory_tracking::grantor_t(scratchpad,
+ prefix_reducer_bia);
+ auto rb = this->reducer_bias_;
+ rb->init(reducer_bia_scratchpad);
+
+ // TODO (Roma): remove this restriction
+ assert(jcp.stride_w == 1 && jcp.stride_h == 1);
+
+ const int nb_ic = jcp.nb_bcast;
+ const int nb_ic_blocking = jcp.nb_bcast_blocking;
+
+ const int nb_oc = jcp.nb_load;
+ const int nb_oc_blocking = jcp.nb_load_blocking;
+
+ const int sp_nb = jcp.nb_reduce;
+ const int mb_sp_work = jcp.mb * sp_nb;
+
+ const int stride_h = (ndims == 3) ? 1 : pd()->desc()->strides[0];
+ const int stride_w = pd()->desc()->strides[ndims - 3];
+ const int pad_t = (ndims == 3) ? 0 : pd()->desc()->padding[0][0];
+ const int pad_l = pd()->desc()->padding[0][ndims - 3];
+
+ auto step = [](int default_step, int remaining, int tail_step) {
+ assert(default_step <= tail_step);
+ return remaining < tail_step ? remaining : default_step;
+ };
+
+ // TODO: use memory descriptor with the same fmt as src
+ // (or use a macro :))
+ auto tr_src_off = [&](int img, int icb, int is) {
+ const size_t tr_chn_size = jcp.tr_is * jcp.ic_block;
+ const size_t tr_img_size = tr_chn_size * nb_ic * jcp.ngroups;
+ return img * tr_img_size + icb * tr_chn_size + is * jcp.ic_block;
+ };
+
+ auto uker_trans = [&](int ithr_mb, int img, int sp_b_start, int sp_size,
+ int g_start, int g_work, int ic_b_start, int ic_b_work,
+ int ithr, int nthr, int first_ic_b)
+ {
+ const int work_amount = g_work * ic_b_work;
+
+ int start{ 0 }, end{ 0 };
+ balance211(work_amount, nthr, ithr, start, end);
+
+ int g{ 0 }, ic_b{ 0 };
+ nd_iterator_init(start, g, g_work, ic_b, ic_b_work);
+ g += g_start;
+ const int ic_b_tr = g * nb_ic + first_ic_b + ic_b;
+ ic_b += ic_b_start;
+
+ const int _ic = g * nb_ic + ic_b;
+
+ const int is = sp_b_start * jcp.reduce_block;
+ const int ih = is / jcp.iw;
+ const int iw = is % jcp.iw;
+
+ const int src1_off = data_blk_off(src_d, img, _ic, ih, iw);
+ data_t *src1 = (data_t *)&src[src1_off];
+ data_t *tr_src1 = &tr_src[tr_src_off(ithr_mb, ic_b_tr, is)];
+
+ assert(jcp.ic_block == 16);
+ const int src_stride = jcp.is * jcp.ic_block;
+ const int tr_src_stride = jcp.tr_is * jcp.ic_block;
+
+ const int my_work = end - start;
+ for (int iwork = 0; iwork < my_work; iwork++) {
+ auto par_trans = jit_src_transpose_s();
+ assert(sp_size % 4 == 0 || sp_size % 4 == jcp.is % 4);
+ par_trans.size = sp_size;
+ par_trans.src = src1;
+ par_trans.tr_src = tr_src1;
+ par_trans.src_prf = src1 + 64 * 16;
+ par_trans.tr_src_prf = tr_src1 + 80 * 16;
+ trans_kernel_->jit_ker(&par_trans);
+
+ src1 += src_stride;
+ tr_src1 += tr_src_stride;
+ }
+ };
+
+ auto ker = [&](const int ithr, const int nthr) {
+ assert(nthr == jcp.nthr);
+ assert(IMPLICATION(!mkldnn_thr_syncable(), jcp.nthr_mb == 1));
+
+ const int ithr_ic_b = ithr % jcp.nthr_ic_b;
+ const int ithr_oc_b = ithr / jcp.nthr_ic_b % jcp.nthr_oc_b;
+ const int ithr_g = ithr / jcp.nthr_ic_b / jcp.nthr_oc_b % jcp.nthr_g;
+ const int ithr_mb = ithr / jcp.nthr_ic_b / jcp.nthr_oc_b /
+ jcp.nthr_g;
+
+ const int ithr_but_oc
+ = (ithr_mb * jcp.nthr_g + ithr_g) * jcp.nthr_ic_b + ithr_ic_b;
+
+ /* reduction dimension */
+ int mb_sp_b_start{ 0 }, mb_sp_b_end{ 0 };
+ if (jcp.transpose_src && jcp.nthr_mb < jcp.mb / 2) {
+ // it's preferable to parallelize by mb if possible
+ int img_start{ 0 }, img_end{ 0 };
+ balance211(jcp.mb, jcp.nthr_mb, ithr_mb, img_start, img_end);
+ mb_sp_b_start = img_start * sp_nb;
+ mb_sp_b_end = img_end * sp_nb;
+ }
+ else {
+ balance211(mb_sp_work, jcp.nthr_mb, ithr_mb, mb_sp_b_start,
+ mb_sp_b_end);
+ }
+
+ /* independent dimensions */
+ int g_start{ 0 }, oc_b_start{ 0 }, ic_b_start{ 0 };
+ int g_end{ 0 }, oc_b_end{ 0 }, ic_b_end{ 0 };
+
+ balance211(jcp.ngroups, jcp.nthr_g, ithr_g, g_start, g_end);
+ balance211(jcp.nb_load, jcp.nthr_oc_b, ithr_oc_b, oc_b_start,
+ oc_b_end);
+ balance211(jcp.nb_bcast, jcp.nthr_ic_b, ithr_ic_b, ic_b_start,
+ ic_b_end);
+
+ const int g_work = g_end - g_start;
+ const int oc_b_work = oc_b_end - oc_b_start;
+ const int ic_b_work = ic_b_end - ic_b_start;
+
+ data_t *diff_wei = ithr_mb == 0
+ ? diff_weights : wei_reduction + (ithr_mb - 1) * wei_size;
+
+ int sp_b_step = 0;
+ for (int mb_sp_b = mb_sp_b_start; mb_sp_b < mb_sp_b_end;
+ mb_sp_b += sp_b_step) {
+ int img{ 0 }, sp_b{ 0 };
+ nd_iterator_init(mb_sp_b, img, jcp.mb, sp_b, sp_nb);
+ sp_b_step = step(jcp.nb_reduce_blocking,
+ nstl::min(sp_nb - sp_b, mb_sp_b_end - mb_sp_b),
+ jcp.nb_reduce_blocking_max);
+
+ for (int g = g_start; g < g_end; ++g) {
+ int load_step = 0;
+ int bcast_step = 0;
+ for (int ic_b = ic_b_start; ic_b < ic_b_end;
+ ic_b += bcast_step) {
+ bcast_step = step(nb_ic_blocking, ic_b_end - ic_b,
+ jcp.nb_bcast_blocking_max);
+ if (jcp.transpose_src) {
+ if (jcp.nthr_oc_b > 1)
+ simple_barrier::barrier(
+ &tr_src_bctx[ithr_but_oc], jcp.nthr_oc_b);
+ const int sp_size
+ = nstl::min(sp_b_step * jcp.reduce_block,
+ jcp.is - sp_b * jcp.reduce_block);
+ uker_trans(ithr_mb, img, sp_b, sp_size, g, 1, ic_b,
+ bcast_step, ithr_oc_b, jcp.nthr_oc_b, ic_b_start);
+ if (jcp.nthr_oc_b > 1)
+ simple_barrier::barrier(
+ &tr_src_bctx[ithr_but_oc], jcp.nthr_oc_b);
+ }
+
+ for (int oc_b = oc_b_start; oc_b < oc_b_end;
+ oc_b += load_step) {
+ load_step = step(nb_oc_blocking, oc_b_end - oc_b,
+ jcp.nb_load_blocking_max);
+ const int _ic_b = g * nb_ic + ic_b;
+ const int _ic_b_tr = g * nb_ic + ic_b_start;
+ const int _oc_b = g * nb_oc + oc_b;
+
+ data_t *store_to;
+
+ const size_t off
+ = wht_blk_off(diff_weights_d, g, oc_b, ic_b);
+ store_to = diff_wei + off;
+
+ const data_t *diff_src = jcp.transpose_src ?
+ &tr_src[tr_src_off(ithr_mb, _ic_b_tr, 0)] :
+ &src[src_d.blk_off(img, _ic_b)];
+
+ int sp_b_end = sp_b + sp_b_step;
+ const data_t *pdiff_dst
+ = &diff_dst[diff_dst_d.blk_off(img, _oc_b)];
+ const data_t *local_src = diff_src;
+
+ auto p = jit_1x1_conv_call_s();
+ auto rp = rtus_driver_t<avx512_common>::call_params_t();
+
+ p.output_stride
+ = jcp.ic * jcp.oc_block * jcp.typesize_out;
+
+ p.load_dim = load_step * jcp.oc_block;
+
+ p.bcast_dim = bcast_step * jcp.ic_block;
+ rp.icb = bcast_step;
+ p.output_data = store_to;
+
+ p.reduce_dim = sp_b_step * jcp.reduce_block;
+ rp.os = p.reduce_dim;
+
+ p.first_last_flag = 0
+ | (mb_sp_b == mb_sp_b_start ? FLAG_REDUCE_FIRST : 0)
+ | (sp_b_end == sp_nb ? FLAG_SP_LAST : 0);
+
+ int sp = sp_b * jcp.reduce_block;
+ p.load_data = pdiff_dst + sp * jcp.oc_block;
+
+ if (pd()->rtus_.reduce_src_) {
+ const int oh = sp / jcp.ow;
+ const int ow = sp % jcp.ow;
+
+ const int ih = nstl::max(oh * stride_h - pad_t, 0);
+ const int iw = nstl::max(ow * stride_w - pad_l, 0);
+ rp.iw_start = iw;
+
+ rp.ws = rtus_space
+ + ithr * pd()->rtus_.space_per_thread_
+ + sp * jcp.ic_block;
+
+ if (ndims == 3)
+ rp.src = local_src + iw
+ * src_d.blocking_desc().strides[2];
+ else
+ rp.src = local_src + ih
+ * src_d.blocking_desc().strides[2]
+ + iw * src_d.blocking_desc().strides[3];
+ rtus_driver_->ker_(&rp);
+
+ p.bcast_data = rp.ws;
+ } else
+ p.bcast_data = local_src + sp * jcp.ic_block;
+
+ kernel_->jit_ker(&p);
+ }
+ }
+ }
+ }
+
+ /* diff_weights[:] += sum(wei_reduction[thr_mb][:]) */
+ if (jcp.nthr_mb > 1) {
+ simple_barrier::barrier(&reduction_barrier, jcp.nthr);
+ const int work = g_work * oc_b_work * ic_b_work;
+ int start{ 0 }, end{ 0 };
+ balance211(work, jcp.nthr_mb, ithr_mb, start, end);
+ if (start == end)
+ return;
+
+ for (int thr_mb = 1; thr_mb < jcp.nthr_mb; ++thr_mb) {
+ int w = start;
+ int sub_g_start{ 0 }, sub_oc_b_start{ 0 },
+ sub_ic_b_start{ 0 };
+ nd_iterator_init(w, sub_g_start, g_work, sub_oc_b_start,
+ oc_b_work, sub_ic_b_start, ic_b_work);
+ while (w < end) {
+ const int g = g_start + sub_g_start;
+ const int oc_b = oc_b_start + sub_oc_b_start;
+ const int ic_b = ic_b_start + sub_ic_b_start;
+
+ const int acc_size
+ = nstl::min(end - w, ic_b_work - sub_ic_b_start)
+ * jcp.ic_block * jcp.oc_block;
+
+ const size_t off
+ = wht_blk_off(diff_weights_d, g, oc_b, ic_b);
+ data_t *d = diff_weights + off;
+ data_t *s = wei_reduction + (thr_mb - 1) * wei_size + off;
+
+ acc_ker_->accumulate(d, s, acc_size);
+
+ nd_iterator_jump(w, end, sub_g_start, g_work,
+ sub_oc_b_start, oc_b_work, sub_ic_b_start,
+ ic_b_work);
+ }
+ }
+ }
+ };
+
+ auto ker_bias = [&](int ithr, int nthr) {
+ assert(nthr == rb->balancer().nthr_);
+
+ const int b_job_start = rb->balancer().ithr_job_off(ithr);
+ const int b_njobs = rb->balancer().ithr_njobs(ithr);
+
+ if (b_njobs == 0)
+ return;
+
+ /* reduction dimension */
+ int img_start{ 0 }, img_end{ 0 };
+
+ balance211(jcp.mb, rb->balancer().nthr_per_group_,
+ rb->balancer().id_in_group(ithr), img_start, img_end);
+
+ /* jobs */
+ int g_start{ 0 }, ocb_start{ 0 };
+ nd_iterator_init(
+ b_job_start, g_start, jcp.ngroups, ocb_start, jcp.nb_load);
+
+ for (int img = img_start; img < img_end; ++img) {
+ int g = g_start, ocb = ocb_start;
+ for (int b_job_loc = 0; b_job_loc < b_njobs; ++b_job_loc) {
+ const size_t _oc = g * jcp.nb_load + ocb;
+
+ const data_t *d_dst = &diff_dst[diff_dst_d.blk_off(img, _oc)];
+ data_t *d_bias = rb->get_local_ptr(ithr, diff_bias,
+ reducer_bia_scratchpad)
+ + b_job_loc * rb->balancer().job_size_;
+
+ if (img == img_start)
+ for (int o = 0; o < 16; ++o)
+ d_bias[o] = 0.;
+
+ for (int hw = 0; hw < jcp.oh * jcp.ow; ++hw) {
+ PRAGMA_OMP_SIMD()
+ for (int o = 0; o < 16; ++o)
+ d_bias[o] += d_dst[o];
+ d_dst += 16;
+ }
+
+ nd_iterator_step(g, jcp.ngroups, ocb, jcp.nb_load);
+ }
+ }
+ rb->reduce(ithr, diff_bias, reducer_bia_scratchpad);
+ };
+
+ parallel(jcp.nthr, [&](const int ithr, const int nthr) {
+ ker(ithr, jcp.nthr);
+ if (pd()->with_bias())
+ ker_bias(ithr, jcp.nthr);
+ });
+
+ /* TODO: put this in ker_bias */
+ if (pd()->wants_padded_bias()) {
+ assert(jcp.ngroups == 1);
+ utils::array_copy(diff_bias_in, diff_bias, jcp.oc_without_padding);
+ }
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.hpp
new file mode 100644
index 0000000000..2e9fda76d6
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_1x1_convolution.hpp
@@ -0,0 +1,344 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_COMMON_1x1_CONVOLUTION_HPP
+#define CPU_JIT_AVX512_COMMON_1x1_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+#include "cpu_reducer.hpp"
+
+#include "jit_avx512_common_1x1_conv_kernel.hpp"
+#include "jit_uni_1x1_conv_utils.hpp"
+#include "jit_transpose_src_utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t src_type,
+ impl::data_type_t wei_type = src_type,
+ impl::data_type_t dst_type = src_type>
+struct jit_avx512_common_1x1_convolution_fwd_t : public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_(), rtus_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_1x1:", avx512_common, ""),
+ jit_avx512_common_1x1_convolution_fwd_t);
+
+ status_t init() {
+ using namespace utils;
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(src_type, wei_type, dst_type, dst_type,
+ data_type::undef)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ const convolution_desc_t *conv_d = desc();
+ const memory_desc_t *src_d = src_md();
+ rtus_prepare(this, conv_d, src_d, dst_md());
+
+ status_t status = jit_avx512_common_1x1_conv_kernel::init_conf(
+ jcp_, *conv_d, *src_d, *weights_md(), *dst_md(), *attr(),
+ mkldnn_get_max_threads(), rtus_.reduce_src_);
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx512_common_1x1_conv_kernel::init_scratchpad(scratchpad,
+ jcp_);
+
+ rtus_prepare_space_info(this, scratchpad);
+
+ return status::success;
+ }
+
+ jit_1x1_conv_conf_t jcp_;
+ reduce_to_unit_stride_t rtus_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c);
+ auto wei_tag = utils::pick(2 * ndims() - 6 + with_groups(),
+ OIw16i16o, gOIw16i16o, OIhw16i16o, gOIhw16i16o);
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ template <cpu_isa_t isa, typename conv_t>
+ friend void init_rtus_driver(conv_t *self);
+
+ jit_avx512_common_1x1_convolution_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , kernel_(nullptr), rtus_driver_(nullptr)
+ {
+ kernel_ =
+ new jit_avx512_common_1x1_conv_kernel(pd()->jcp_, *pd()->attr());
+ init_rtus_driver<avx512_common>(this);
+ }
+
+ ~jit_avx512_common_1x1_convolution_fwd_t() {
+ delete kernel_;
+ delete rtus_driver_;
+ }
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<wei_type>::type wei_data_t;
+ typedef typename prec_traits<dst_type>::type dst_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+ private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ void execute_forward_thr(const int ithr, const int nthr,
+ const src_data_t *src, const wei_data_t *weights,
+ const dst_data_t *bias, dst_data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx512_common_1x1_conv_kernel *kernel_;
+ rtus_driver_t<avx512_common> *rtus_driver_;
+};
+
+using jit_avx512_common_1x1_convolution_fwd_f32_t
+ = jit_avx512_common_1x1_convolution_fwd_t<data_type::f32>;
+
+template <impl::data_type_t diff_dst_type,
+ impl::data_type_t wei_type = diff_dst_type,
+ impl::data_type_t diff_src_type = diff_dst_type>
+struct jit_avx512_common_1x1_convolution_bwd_data_t : public cpu_primitive_t {
+ struct pd_t : public cpu_convolution_bwd_data_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_(), rtus_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_1x1:", avx512_common, ""),
+ jit_avx512_common_1x1_convolution_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_data
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(diff_src_type, wei_type, data_type::undef,
+ diff_dst_type, data_type::undef)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ const convolution_desc_t *conv_d = desc();
+ const memory_desc_t *diff_src_d = diff_src_md();
+ rtus_prepare(this, conv_d, diff_src_d, diff_dst_md());
+
+ status_t status = jit_avx512_common_1x1_conv_kernel::init_conf(
+ jcp_, *conv_d, *diff_src_d, *weights_md(), *diff_dst_md(),
+ *attr(), mkldnn_get_max_threads(), rtus_.reduce_src_);
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx512_common_1x1_conv_kernel::init_scratchpad(scratchpad,
+ jcp_);
+
+ rtus_prepare_space_info(this, scratchpad);
+
+ return status::success;
+ }
+
+ // TODO (Roma): structs conf header cleanup
+ jit_1x1_conv_conf_t jcp_;
+ reduce_to_unit_stride_t rtus_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c);
+ auto wei_tag = utils::pick(2 * ndims() - 6 + with_groups(),
+ IOw16o16i, gIOw16o16i, IOhw16o16i, gIOhw16o16i);
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ template <cpu_isa_t isa, typename conv_t>
+ friend void init_rtus_driver(conv_t *self);
+
+ jit_avx512_common_1x1_convolution_bwd_data_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , kernel_(nullptr), rtus_driver_(nullptr)
+ {
+ kernel_ = new jit_avx512_common_1x1_conv_kernel(pd()->jcp_,
+ *pd()->attr());
+ init_rtus_driver<avx512_common>(this);
+ }
+
+ ~jit_avx512_common_1x1_convolution_bwd_data_t() {
+ delete kernel_;
+ delete rtus_driver_;
+ }
+
+ typedef typename prec_traits<diff_dst_type>::type diff_dst_data_t;
+ typedef typename prec_traits<wei_type>::type wei_data_t;
+ typedef typename prec_traits<diff_src_type>::type diff_src_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_data(ctx);
+ return status::success;
+ }
+
+ private:
+ void execute_backward_data(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx512_common_1x1_conv_kernel *kernel_;
+ rtus_driver_t<avx512_common> *rtus_driver_;
+};
+
+using jit_avx512_common_1x1_convolution_bwd_data_f32_t
+ = jit_avx512_common_1x1_convolution_bwd_data_t<data_type::f32>;
+
+struct jit_avx512_common_1x1_convolution_bwd_weights_t : public cpu_primitive_t
+{
+ struct pd_t : public cpu_convolution_bwd_weights_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_(), rtus_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_1x1:", avx512_common, ""),
+ jit_avx512_common_1x1_convolution_bwd_weights_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_weights
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ const convolution_desc_t *conv_d = desc();
+ const memory_desc_t *src_d = src_md();
+ rtus_prepare(this, conv_d, src_d, diff_dst_md());
+
+ status_t status = jit_avx512_common_1x1_conv_kernel::init_conf(
+ jcp_, *conv_d, *src_d, *diff_weights_md(), *diff_dst_md(),
+ *attr(), mkldnn_get_max_threads(), rtus_.reduce_src_);
+ if (status != status::success) return status;
+
+ init_balancers();
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx512_common_1x1_conv_kernel::init_scratchpad(scratchpad,
+ jcp_);
+
+ auto reducer_bia_scratchpad = memory_tracking::registrar_t(
+ scratchpad, memory_tracking::names::prefix_reducer_bia);
+ reducer_bia_conf_.init_scratchpad(reducer_bia_scratchpad);
+
+ rtus_prepare_space_info(this, scratchpad);
+
+ return status::success;
+ }
+
+ // TODO (Roma): structs conf header cleanup
+ jit_1x1_conv_conf_t jcp_;
+ cpu_reducer_t<data_type::f32>::conf_t reducer_bia_conf_;
+ reduce_to_unit_stride_t rtus_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c);
+ auto wei_tag = utils::pick(2 * ndims() - 6 + with_groups(),
+ OIw16i16o, gOIw16i16o, OIhw16i16o, gOIhw16i16o);
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+
+ private:
+ void init_balancers() {
+ const size_t max_buffer_size = jcp_.nthr * 3 * 5 * 5 * 16 * 16;
+ if (with_bias()) {
+ reducer_bia_conf_.init(reduce_balancer_t(jcp_.nthr,
+ jcp_.oc_block, jcp_.ngroups * jcp_.nb_load,
+ jcp_.mb, max_buffer_size));
+ }
+ }
+ };
+
+ template <cpu_isa_t isa, typename conv_t>
+ friend void init_rtus_driver(conv_t *self);
+
+ jit_avx512_common_1x1_convolution_bwd_weights_t(const pd_t *apd);
+
+ ~jit_avx512_common_1x1_convolution_bwd_weights_t() {
+ delete kernel_;
+ delete acc_ker_;
+ delete reducer_bias_;
+ delete rtus_driver_;
+ delete trans_kernel_;
+ }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_weights(ctx);
+ return status::success;
+ }
+
+ private:
+ void execute_backward_weights(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx512_common_1x1_conv_kernel *kernel_;
+ cpu_accumulator_1d_t<data_type::f32> *acc_ker_;
+ cpu_reducer_t<data_type::f32> *reducer_bias_;
+ jit_transpose4x16_src *trans_kernel_;
+ rtus_driver_t<avx512_common> *rtus_driver_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.cpp
new file mode 100644
index 0000000000..235fb02fef
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.cpp
@@ -0,0 +1,4539 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_barrier.hpp"
+
+#include "jit_avx512_common_conv_kernel.hpp"
+
+#define GET_OFF(field) offsetof(jit_conv_call_s, field)
+#define KNx_L2_EFFECTIVE_CAPACITY ((512-64)*1024)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+using namespace Xbyak;
+
+namespace {
+
+constexpr auto small_spatial = 14;
+unsigned int L1_cache_size = get_cache_size(1, true);
+
+inline void pick_loop_order(jit_conv_conf_t &jcp) {
+ using namespace prop_kind;
+ assert(one_of(jcp.prop_kind,
+ forward_training, forward_inference, backward_data));
+ auto w = (jcp.prop_kind == backward_data) ? jcp.iw : jcp.ow;
+ auto h = (jcp.prop_kind == backward_data) ? jcp.ih : jcp.oh;
+
+ // ow-threading is currently implemented for forward only
+ // TODO: single code for fwd and bwd after ow-thr for bwd
+ // meaningless switch was removed
+ if (jcp.prop_kind == backward_data) {
+ jcp.loop_order = (w <= small_spatial && h <= small_spatial)
+ ? loop_cgn : loop_gnc;
+ } else {
+ jcp.loop_order = (w <= small_spatial && h <= small_spatial)
+ ? loop_cwgn : loop_gncw;
+ }
+}
+
+inline bool is_1stconv(const jit_conv_conf_t &jcp) {
+ if (mayiuse(avx512_core))
+ return (jcp.ic < 16 && jcp.ngroups == 1);
+ else
+ return one_of(jcp.ic, 1, 3);
+}
+
+inline bool is_ow_threading_on(const jit_conv_conf_t &jcp) {
+ return (jcp.nb_ow > 1);
+}
+
+inline bool is_owb_prefetching(const jit_conv_conf_t &jcp) {
+ return (jcp.ver == ver_4fma && is_ow_threading_on(jcp));
+}
+
+}
+
+template<typename Vmm>
+void _jit_avx512_common_conv_fwd_kernel<Vmm>::prepare_output(int ur_w)
+{
+ for (int k = 0; k < jcp.nb_oc_blocking; k++)
+ for (int j = 0; j < ur_w; j++) {
+ Vmm vmm = vmm_out(j, k);
+ vpxord(vmm, vmm, vmm);
+ if (!is_owb_prefetching(jcp)) {
+ size_t aux_output_offset = get_output_offset(j, k);
+ mic_prefetcht1(EVEX_compress_addr_safe(reg_out_prf,
+ aux_output_offset, reg_out_long_offt));
+ }
+ }
+}
+
+template<typename Vmm>
+void _jit_avx512_common_conv_fwd_kernel<Vmm>::store_output(int ur_w)
+{
+ Label no_update_label, store_label, eltwise_label;
+
+ mov(reg_channel, ptr[param1 + GET_OFF(channel)]);
+ if (jcp.with_bias) {
+ mov(reg_bias, ptr[param1 + GET_OFF(bias)]);
+ }
+
+ if (!jcp.with_sum) {
+ cmp(reg_channel, 0);
+ je(no_update_label, T_NEAR);
+ }
+
+ for (int k = 0; k < jcp.nb_oc_blocking; k++)
+ for (int j = 0; j < ur_w; j++) {
+ Vmm vmm = vmm_out(j, k);
+ size_t aux_output_offset = get_output_offset(j, k);
+ vaddps(vmm,
+ make_safe_addr(reg_out, aux_output_offset, reg_out_long_offt));
+ }
+
+ if (!jcp.with_sum) {
+ jmp(eltwise_label, T_NEAR);
+ } else {
+ cmp(reg_channel, 0);
+ jne(eltwise_label, T_NEAR);
+ }
+
+ L(no_update_label);
+ if (jcp.with_bias) {
+ for (int k = 0; k < jcp.nb_oc_blocking; k++) {
+ int bias_offset = jcp.typesize_out * k * jcp.oc_block;
+ for (int j = 0; j < ur_w; j++) {
+ Vmm vmm = vmm_out(j, k);
+ vaddps(vmm, EVEX_compress_addr(reg_bias, bias_offset));
+ }
+ mic_prefetcht1(EVEX_compress_addr(reg_bias, bias_offset + 64));
+ }
+ }
+
+ L(eltwise_label);
+ if (jcp.with_eltwise) {
+ cmp(reg_channel, jcp.nb_ic - 1);
+ jl(store_label, T_NEAR);
+
+ if (ur_w == jcp.ur_w) {
+ eltwise_injector_->compute_vector_range(0,
+ jcp.nb_oc_blocking * jcp.ur_w);
+ } else {
+ for (int k = 0; k < jcp.nb_oc_blocking; k++)
+ eltwise_injector_->compute_vector_range(k * jcp.ur_w,
+ k * jcp.ur_w + ur_w);
+ }
+ }
+
+ L(store_label);
+ for (int k = 0; k < jcp.nb_oc_blocking; k++)
+ for (int j = 0; j < ur_w; j++) {
+ Vmm vmm = vmm_out(j, k);
+ size_t aux_output_offset = (size_t)typesize *
+ ((size_t)k * jcp.od * jcp.oh * jcp.ow + j) * jcp.oc_block;
+ vmovups(EVEX_compress_addr_safe(reg_out, aux_output_offset,
+ reg_out_long_offt), vmm);
+ if (!is_owb_prefetching(jcp))
+ mic_prefetcht0(EVEX_compress_addr_safe(reg_out_prf,
+ aux_output_offset, reg_out_long_offt));
+ }
+}
+
+template<typename Vmm>
+void _jit_avx512_common_conv_fwd_kernel<Vmm>::compute_loop_4fma_1st(int ur_w,
+ int pad_l, int pad_r)
+{
+}
+
+template<>
+void _jit_avx512_common_conv_fwd_kernel<Zmm>::compute_loop_4fma_1st(int ur_w,
+ int pad_l, int pad_r)
+{
+ assert(jcp.dilate_d == 0 && jcp.dilate_h == 0 && jcp.dilate_w == 0);
+
+ int iw = jcp.iw;
+ int ih = jcp.ih;
+ int kw = jcp.kw;
+ int stride_w = jcp.stride_w;
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+
+ Label kh_label, kd_label;
+
+ if (one_of(jcp.ndims, 3, 4)) {
+ mov(aux_reg_inp, reg_inp);
+ mov(aux_reg_ker, reg_ker);
+ mov(aux_reg_inp_prf, reg_inp_prf);
+ }
+
+ size_t max_input_offset = (size_t)jcp.typesize_in
+ * ((size_t)(kw + ur_w * stride_w - pad_l)
+ + (size_t)ic_block * iw * ih * jcp.id);
+ assert(reg_inp_prf == reg_long_offt);
+ if (max_input_offset > INT_MAX) push(reg_inp_prf);
+
+ if (jcp.ndims == 5) {
+ push(reg_out_prf);
+ push(reg_out);
+
+ mov(reg_ki, ptr[param1 + GET_OFF(kd_padding)]);
+ mov(aux_reg_ker_d, ptr[param1 + GET_OFF(filt)]);
+ mov(aux_reg_inp_d, reg_inp);
+ mov(aux_reg_inp_d_prf, reg_inp_prf);
+
+ L(kd_label);
+ }
+ mov(reg_kj, reg_kh);
+ if (jcp.ndims == 5) {
+ mov(aux_reg_inp, aux_reg_inp_d);
+ mov(aux_reg_ker, aux_reg_ker_d);
+ mov(aux_reg_inp_prf, aux_reg_inp_d_prf);
+ }
+
+ L(kh_label);
+ for (int ki = 0; ki < kw; ki += 4) {
+ for (int ic = 0; ic < ic_block; ic++) {
+ for (int i = 0; i < 4; i++) {
+ int aux_ker_offset
+ = jcp.typesize_in
+ * ((ki + i) * oc_block
+ + ic * kw * jcp.kh * jcp.kd * oc_block);
+ if (ki + i < kw)
+ vmovups(vmm_ker(i),
+ EVEX_compress_addr(aux_reg_ker, aux_ker_offset));
+ else
+ vpxord(vmm_ker(i), vmm_ker(i), vmm_ker(i));
+ }
+
+ int j_start = get_ow_start(ki, pad_l);
+ int j_end = get_ow_end(ur_w, ki, pad_r);
+
+ for (int j = j_start, prf_count=0; j < j_end; j++) {
+ size_t aux_input_offset = (size_t)jcp.typesize_in
+ * ((size_t)(ki + j * stride_w
+ - pad_l) + (size_t)ic * iw * ih * jcp.id);
+ v4fmaddps(vmm_out(j, 0), vmm_ker(0),
+ EVEX_compress_addr_safe(aux_reg_inp, aux_input_offset,
+ reg_long_offt));
+ if (ki + prf_count < kw && prf_count < 4
+ && ((ki < 2 && j % 4) || j % 2)) {
+ int aux_ker_offset = jcp.typesize_in
+ * ((ki + prf_count) * oc_block
+ + ic * kw * jcp.kh * jcp.kd * oc_block + kw * oc_block);
+ mic_prefetcht0(EVEX_compress_addr(aux_reg_ker,
+ aux_ker_offset));
+ prf_count++;
+ }
+ if (ki == 0
+ && j % (64 / (stride_w * jcp.typesize_in)) == 0) {
+ mic_prefetcht0(EVEX_compress_addr_safe(aux_reg_inp_prf,
+ aux_input_offset, reg_long_offt));
+ }
+ if (ki == 1
+ && j % (64 / (stride_w * jcp.typesize_in)) == 0) {
+ mic_prefetcht0(EVEX_compress_addr_safe(aux_reg_inp,
+ aux_input_offset+jcp.typesize_in * iw, reg_long_offt));
+ }
+ }
+ }
+ }
+ add(aux_reg_ker, jcp.typesize_in * kw * oc_block);
+ add(aux_reg_inp, jcp.typesize_in * iw);
+ add(aux_reg_inp_prf, jcp.typesize_in * iw);
+
+ dec(reg_kj);
+ cmp(reg_kj, 0);
+ jg(kh_label, T_NEAR);
+
+ if (jcp.ndims == 5) {
+ add(aux_reg_inp_d, typesize * jcp.ih * jcp.iw);
+ add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * oc_block);
+ add(aux_reg_inp_d_prf, typesize * jcp.ih * jcp.iw);
+
+ dec(reg_ki);
+ cmp(reg_ki, 0);
+ jg(kd_label, T_NEAR);
+
+ pop(reg_out);
+ pop(reg_out_prf);
+ }
+
+ if (max_input_offset > INT_MAX) pop(reg_inp_prf);
+}
+
+template<typename Vmm>
+void _jit_avx512_common_conv_fwd_kernel<Vmm>::compute_loop_4fma(int ur_w,
+ int pad_l, int pad_r)
+{
+}
+
+template<>
+void _jit_avx512_common_conv_fwd_kernel<Zmm>::compute_loop_4fma(int ur_w,
+ int pad_l, int pad_r)
+{
+ int stride_w = jcp.stride_w;
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ Label kh_label, last_iter_label, loop_end_label, kd_label;
+ int ker_load_number = 4;
+ int shift_kernel_ptr = typesize * jcp.kw * jcp.oc_block * jcp.ic_block;
+ int shift_input_ptr = typesize * (jcp.dilate_h + 1) * jcp.iw * jcp.ic_block;
+
+ bool check_last_kh = (jcp.kh > 3);
+ bool pref_current_inp = (jcp.iw < 14 || jcp.iw > 28);
+
+ int oi_ipref_t0 = get_ow_start(0, pad_l);
+ int ow_end_ipref = get_ow_end(ur_w, 0, pad_r);
+
+ assert(jcp.oc % jcp.nb_oc_blocking == 0);
+
+ auto kernel_offset = [=](int ocb, int ic, int ki) {
+ int blk_idx = ocb * jcp.nb_ic * jcp.kh * jcp.kw * jcp.kd + ki;
+ int blk_offset = blk_idx * jcp.oc_block * jcp.ic_block;
+ int ic_offset = ic * jcp.oc_block;
+ return typesize * (blk_offset + ic_offset);
+ };
+ auto kernel_loads = [=](int ki, int ic, int kk) {
+ for (int ii = 0; ii < ker_load_number; ii++) {
+ int aux_kernel_offset = kernel_offset(kk, ic + ii, ki);
+ vmovups(vmm_ker(ii),
+ EVEX_compress_addr(aux_reg_ker, aux_kernel_offset));
+ }
+ };
+ auto prefetch_inp_next_kh = [&](int ki, int ki_start, int cnt0, int cnt1) {
+ if (cnt1 >= ker_load_number && cnt0 >= ker_load_number
+ && ki >= ki_start && oi_ipref_t0 < ow_end_ipref) {
+ int aux_inp_offset
+ = typesize
+ * ((oi_ipref_t0 * stride_w - pad_l) * ic_block
+ + (jcp.dilate_h + 1) * jcp.iw * ic_block);
+ prefetcht0(EVEX_compress_addr(aux_reg_inp,
+ aux_inp_offset));
+ oi_ipref_t0++;
+ }
+ };
+
+ if (one_of(jcp.ndims, 3, 4)) {
+ mov(aux_reg_inp, reg_inp);
+ mov(aux_reg_ker, reg_ker);
+ mov(aux_reg_ker_prf, reg_ker_prf);
+ mov(aux_reg_inp_prf, reg_inp_prf);
+ }
+
+ if (jcp.ndims == 5) {
+ push(reg_out_prf);
+ push(reg_out);
+
+ mov(reg_ki, ptr[param1 + GET_OFF(kd_padding)]);
+ mov(aux_reg_ker_d, ptr[param1 + GET_OFF(filt)]);
+ mov(aux_reg_inp_d, reg_inp);
+ mov(aux_reg_inp_d_prf, reg_inp_prf);
+ mov(aux_reg_ker_d_prf, reg_ker_prf);
+ L(kd_label);
+ mov(reg_kj, ptr[param1 + GET_OFF(kh_padding)]);
+ } else {
+ mov(reg_kj, reg_kh);
+ }
+ if (jcp.ndims == 5) {
+ mov(aux_reg_inp, aux_reg_inp_d);
+ mov(aux_reg_ker, aux_reg_ker_d);
+ mov(aux_reg_ker_prf, aux_reg_ker_d_prf);
+ mov(aux_reg_inp_prf, aux_reg_inp_d_prf);
+ }
+
+ align(16);
+ L(kh_label);
+ int kw = jcp.kw;
+ if (check_last_kh) {
+ for (int ki = 0; ki < kw; ki++)
+ for (int ic = 0; ic < ic_block; ic += 4)
+ for (int kk = 0; kk < jcp.nb_oc_blocking; kk++) {
+ bool last_kernel_loads = (kk == jcp.nb_oc_blocking - 1
+ && ki == kw - 1 && (ic + 4) == ic_block);
+
+ if (last_kernel_loads) {
+ cmp(reg_kj, 1);
+ je(last_iter_label, T_NEAR);
+ }
+
+ kernel_loads(ki, ic, kk);
+ for (int oi = get_ow_start(ki, pad_l), prf_count_t1 = 0,
+ prf_count_t0 = 0;
+ oi < get_ow_end(ur_w, ki, pad_r); oi++) {
+ int aux_input_offset = typesize
+ * ((ki * (jcp.dilate_w + 1) + oi * stride_w
+ - pad_l) * ic_block
+ + ic);
+ v4fmaddps(vmm_out(oi, kk), vmm_ker(0),
+ EVEX_compress_addr(aux_reg_inp, aux_input_offset));
+
+ if (oi % 2) {
+ if (prf_count_t0 < 4) {
+ int aux_kernel_prf;
+ if (last_kernel_loads)
+ aux_kernel_prf= kernel_offset(0,
+ prf_count_t0 + ic + 4
+ - ic_block, 0) + typesize * kw
+ * oc_block * ic_block;
+ else
+ aux_kernel_prf = kernel_offset(kk, ic + 4
+ + prf_count_t0, ki);
+ mic_prefetcht0(EVEX_compress_addr(aux_reg_ker,
+ aux_kernel_prf));
+ prf_count_t0++;
+ } else if (prf_count_t1 < 4) {
+ mic_prefetcht1(EVEX_compress_addr(
+ aux_reg_ker_prf, kernel_offset(kk, ic
+ + prf_count_t1, ki)));
+ prf_count_t1++;
+ }
+ } else
+ prefetch_inp_next_kh(ki, 2, prf_count_t0,
+ prf_count_t1);
+ }
+
+ if (last_kernel_loads) {
+ jmp(loop_end_label, T_NEAR);
+
+ L(last_iter_label);
+
+ kernel_loads(ki, ic, kk);
+ for (int oi = get_ow_start(ki, pad_l), prf_count_t1 = 0,
+ prf_count_t0 = 0;
+ oi < get_ow_end(ur_w, ki, pad_r); oi++) {
+ int aux_input_offset = typesize
+ * ((ki * (jcp.dilate_w + 1) + oi * stride_w
+ - pad_l) * ic_block
+ + ic);
+ v4fmaddps(vmm_out(oi, kk), vmm_ker(0),
+ EVEX_compress_addr(aux_reg_inp,
+ aux_input_offset));
+ if (oi % 2) {
+ if (prf_count_t0 < 4) {
+ mic_prefetcht0(EVEX_compress_addr(
+ aux_reg_ker_prf, kernel_offset(0,
+ prf_count_t0, 0)));
+ prf_count_t0++;
+ } else if (prf_count_t1 < 4) {
+ mic_prefetcht1(EVEX_compress_addr(
+ aux_reg_ker_prf, kernel_offset(kk,
+ ic + prf_count_t1, ki)));
+ prf_count_t1++;
+ }
+ }
+ }
+ L(loop_end_label);
+ }
+ }
+ } else {
+ for (int ki = 0; ki < kw; ki++)
+ for (int ic = 0; ic < ic_block; ic += 4)
+ for (int kk = 0; kk < jcp.nb_oc_blocking; kk++) {
+ kernel_loads(ki, ic, kk);
+ for (int oi = get_ow_start(ki, pad_l),
+ prf_count_t1 = 0, prf_count_t0 = 0;
+ oi < get_ow_end(ur_w, ki, pad_r); oi++) {
+ int aux_input_offset = typesize
+ * ((ki * (jcp.dilate_w + 1) + oi * stride_w
+ - pad_l) * ic_block + ic);
+ v4fmaddps(vmm_out(oi, kk), vmm_ker(0),
+ EVEX_compress_addr(aux_reg_inp,
+ aux_input_offset));
+
+ if (!is_owb_prefetching(jcp)) {
+ if ((oi % 2) && (prf_count_t1 < 4)) {
+ mic_prefetcht1(EVEX_compress_addr(
+ aux_reg_ker_prf, kernel_offset(kk,
+ ic + prf_count_t1, ki)));
+ prf_count_t1++;
+ }
+ } else {
+ if (!(ki == 0 && ic == 0)
+ && !(ki == kw-1 && ic == 0) &&
+ (oi % 2) && (prf_count_t1 < 4)
+ ) {
+ mic_prefetcht0(EVEX_compress_addr(
+ aux_reg_ker, kernel_offset(kk,
+ ic + 4 + prf_count_t0, ki)));
+ prf_count_t0++;
+ }
+ }
+ if (!is_owb_prefetching(jcp)) {
+ if (pref_current_inp) {
+ if (ki == 0 && ic == 0 && kk == 0)
+ mic_prefetcht0(EVEX_compress_addr(
+ aux_reg_inp,
+ aux_input_offset + shift_input_ptr));
+ } else {
+ if (ki == 1 && ic == 0 && kk == 0)
+ mic_prefetcht1(EVEX_compress_addr(
+ aux_reg_inp_prf, aux_input_offset));
+ }
+ } else {
+ int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block;
+ int inp_shift
+ = jcp.typesize_in * ur_w * stride_w * inp_mult;
+ bool kk_pref_slot = kk ? oi % 2 : !(oi % 2);
+ if (ki == 0 && ic == 0 && kk_pref_slot)
+ mic_prefetcht1(EVEX_compress_addr(
+ aux_reg_inp,
+ aux_input_offset + inp_shift));
+
+ if (ki == kw - 1 && ic == 0 && kk_pref_slot)
+ mic_prefetcht0(EVEX_compress_addr(
+ aux_reg_inp,
+ aux_input_offset + inp_shift));
+ }
+ }
+ }
+ }
+
+ add(aux_reg_ker, shift_kernel_ptr);
+ add(aux_reg_inp, shift_input_ptr);
+ add(aux_reg_ker_prf, shift_kernel_ptr);
+ add(aux_reg_inp_prf, shift_input_ptr);
+
+ dec(reg_kj);
+ cmp(reg_kj, 0);
+ jg(kh_label, T_NEAR);
+
+ if (jcp.ndims == 5) {
+ add(aux_reg_inp_d,
+ typesize * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * jcp.ic_block);
+ add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * jcp.oc_block
+ * jcp.ic_block);
+ add(aux_reg_inp_d_prf,
+ typesize * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * jcp.ic_block);
+ add(aux_reg_ker_d_prf, typesize * jcp.kw * jcp.kh * jcp.oc_block
+ * jcp.ic_block);
+
+ dec(reg_ki);
+ cmp(reg_ki, 0);
+ jg(kd_label, T_NEAR);
+
+ pop(reg_out);
+ pop(reg_out_prf);
+ }
+}
+
+template<typename Vmm>
+void _jit_avx512_common_conv_fwd_kernel<Vmm>::compute_loop_fma(int ur_w,
+ int pad_l, int pad_r)
+{
+ bool prf_ker = true;
+ bool prf_inp = true;
+ int ih = jcp.ih;
+ int stride_w = jcp.stride_w;
+ int id = jcp.id;
+ int iw = jcp.iw;
+ int kw = jcp.kw;
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ int nb_oc_block = jcp.nb_oc_blocking;
+ Label kh_label, kd_label;
+
+ int ker_pipeline_depth = 4;
+ assert(ker_reg_base_idx + ker_pipeline_depth <= 32);
+ assert(oc_block >= ker_pipeline_depth);
+
+ int num_ker_loads = ic_block * nb_oc_block * kw;
+ int num_ker_prfs = prf_ker ? num_ker_loads : 0;
+ int num_inp_prfs = prf_inp ?
+ ur_w * nstl::min(kw, stride_w) + nstl::max(0, kw - stride_w) :
+ 0;
+ if (jcp.is_1stconv && prf_inp) {
+ num_inp_prfs = div_up(num_inp_prfs, jcp.simd_w) * ic_block;
+ }
+ int num_prfs = num_ker_prfs + num_inp_prfs;
+ int num_fmas = num_ker_loads * ur_w;
+ int prf_inst_spacing
+ = (prf_ker || prf_inp) ? nstl::max(1, num_fmas / num_prfs) : 1;
+ int prf_inst_trigger = (num_fmas % prf_inst_spacing) / 2;
+ int inp_mul = !jcp.is_1stconv ? ic_block : 1;
+
+ if (one_of(jcp.ndims, 3, 4)) {
+ mov(aux_reg_inp, reg_inp);
+ mov(aux_reg_ker, reg_ker);
+ mov(aux_reg_inp_prf, reg_inp_prf);
+ mov(aux_reg_ker_prf, reg_ker_prf);
+ }
+
+ size_t max_input_offset = (size_t)jcp.typesize_in * ic_block * iw * ih * id;
+ assert(reg_inp_prf == reg_long_offt);
+ if (max_input_offset > INT_MAX) push(reg_inp_prf);
+
+
+ if (jcp.ndims == 5) {
+ push(reg_out_prf);
+ push(reg_out);
+
+ mov(reg_ki, ptr[param1 + GET_OFF(kd_padding)]);
+ mov(aux_reg_ker_d, ptr[param1 + GET_OFF(filt)]);
+ mov(aux_reg_inp_d, reg_inp);
+ mov(aux_reg_inp_d_prf, reg_inp_prf);
+ mov(aux_reg_ker_d_prf, reg_ker_prf);
+
+ L(kd_label);
+ mov(reg_kj, ptr[param1 + GET_OFF(kh_padding)]);
+ } else {
+ mov(reg_kj, reg_kh);
+ }
+
+ if (jcp.ndims == 5) {
+ mov(aux_reg_inp, aux_reg_inp_d);
+ mov(aux_reg_ker, aux_reg_ker_d);
+ mov(aux_reg_ker_prf, aux_reg_ker_d_prf);
+ mov(aux_reg_inp_prf, aux_reg_inp_d_prf);
+ }
+
+ align(16);
+ L(kh_label);
+ {
+ int step = 0;
+ int ker_prfs = 0;
+ for (int ki = 0; ki < kw; ki++) {
+ for (int ic = 0; ic < ic_block; ic++) {
+ int aux_kernel_offset = 0;
+ if (step == 0) {
+ for (int i = 0; i < ker_pipeline_depth; i++) {
+ aux_kernel_offset = get_kernel_offset(ki, ic, 0, i);
+ vmovups(vmm_ker(i), EVEX_compress_addr(
+ aux_reg_ker, aux_kernel_offset));
+ }
+ } else if (step < num_ker_loads - ker_pipeline_depth + 1) {
+ int load_offset = ker_pipeline_depth - 1;
+ int ker_load_reg_idx
+ = (step + load_offset) % ker_pipeline_depth;
+ aux_kernel_offset
+ = get_kernel_offset(ki, ic, 0, load_offset);
+ vmovups(vmm_ker(ker_load_reg_idx),
+ EVEX_compress_addr(aux_reg_ker, aux_kernel_offset));
+ }
+
+ bool ker_prf_inserted = false;
+ Vmm vmm_kernel = vmm_ker(step % ker_pipeline_depth);
+ int j_start = get_ow_start(ki, pad_l);
+ int j_end = get_ow_end(ur_w, ki, pad_r);
+ for (int j = j_start; j < j_end; j++) {
+ size_t aux_input_offset = get_input_offset(ki, ic, j, pad_l);
+ auto addr = EVEX_compress_addr_safe(aux_reg_inp,
+ aux_input_offset, reg_long_offt, true);
+ vfmadd231ps(vmm_out(j, 0), vmm_kernel, addr);
+ int fma_idx = step * ur_w + j;
+ int prf_slot_idx = fma_idx / prf_inst_spacing;
+ if (fma_idx % prf_inst_spacing == prf_inst_trigger) {
+ if (prf_ker && !ker_prf_inserted
+ && ker_prfs < num_ker_prfs) {
+ int ker_prf_offset
+ = jcp.typesize_in * ker_prfs * jcp.oc_block;
+ mic_prefetcht2(EVEX_compress_addr(
+ aux_reg_ker_prf, ker_prf_offset));
+ ker_prf_inserted = true;
+ ker_prfs++;
+ } else if (prf_inp) {
+ int inp_prf_idx = prf_slot_idx - ker_prfs;
+ if (inp_prf_idx < num_inp_prfs) {
+ size_t inp_prf_stride = nstl::max(kw, stride_w);
+ size_t inp_prf_offset;
+ if (!jcp.is_1stconv) {
+ inp_prf_offset
+ = ic_block * jcp.typesize_in
+ * ((inp_prf_idx / kw)
+ * inp_prf_stride
+ + (inp_prf_idx % kw));
+ } else {
+ size_t ic_prf_stride =
+ (size_t)jcp.typesize_in * iw * ih * id;
+ size_t iw_prf_stride
+ = jcp.typesize_in * jcp.simd_w;
+ inp_prf_offset = ((inp_prf_idx / ic_block)
+ * iw_prf_stride
+ + (inp_prf_idx % ic_block)
+ * ic_prf_stride);
+ }
+ mic_prefetcht0(EVEX_compress_addr_safe(
+ aux_reg_inp_prf, inp_prf_offset,
+ reg_long_offt));
+ }
+ }
+ }
+ }
+ step++;
+ }
+ }
+ add(aux_reg_ker, jcp.typesize_in * kw * oc_block * ic_block);
+ if (prf_ker)
+ add(aux_reg_ker_prf, jcp.typesize_in * kw * oc_block * ic_block);
+ add(aux_reg_inp, jcp.typesize_in * (jcp.dilate_h + 1) * iw * inp_mul);
+ if (prf_inp)
+ add(aux_reg_inp_prf,
+ jcp.typesize_in * (jcp.dilate_h + 1) * iw * inp_mul);
+ dec(reg_kj);
+ cmp(reg_kj, 0);
+ jg(kh_label, T_NEAR);
+ }
+
+
+ if (jcp.ndims == 5) {
+ add(aux_reg_inp_d,
+ typesize * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * inp_mul);
+ add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * jcp.oc_block
+ * jcp.ic_block);
+ add(aux_reg_inp_d_prf,
+ typesize * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * inp_mul);
+ add(aux_reg_ker_d_prf, typesize * jcp.kw * jcp.kh * jcp.oc_block
+ * jcp.ic_block);
+
+ dec(reg_ki);
+ cmp(reg_ki, 0);
+ jg(kd_label, T_NEAR);
+
+ pop(reg_out);
+ pop(reg_out_prf);
+ }
+ if (max_input_offset > INT_MAX) pop(reg_inp_prf);
+}
+
+template<typename Vmm>
+void _jit_avx512_common_conv_fwd_kernel<Vmm>::compute_loop_fma_core(int ur_w,
+ int pad_l, int pad_r)
+{
+ int kw = jcp.kw;
+ int stride_w = jcp.stride_w;
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ int nb_oc_block = jcp.nb_oc_blocking;
+ Label kh_label, kd_label;
+ int shift_kernel_ptr = jcp.typesize_in * jcp.kw * jcp.oc_block
+ * jcp.ic_block;
+ int inp_mul = !jcp.is_1stconv ? ic_block : 1;
+ int shift_input_ptr = jcp.typesize_in * (jcp.dilate_h + 1) * jcp.iw
+ * inp_mul;
+
+
+ auto input_offset = [=](int oi, int ic, int ki) {
+ return (size_t)jcp.typesize_in
+ * ((size_t)(ki * (jcp.dilate_w + 1) + oi * stride_w - pad_l)
+ * inp_mul + (size_t)ic
+ * (!jcp.is_1stconv ? 1 : (size_t)jcp.iw * jcp.ih * jcp.id));
+ };
+
+ if (one_of(jcp.ndims, 3, 4)) {
+ mov(aux_reg_inp, reg_inp);
+ mov(aux_reg_ker, reg_ker);
+ }
+
+ if (jcp.ndims == 5) {
+ push(reg_out);
+
+ mov(reg_ki, ptr[param1 + GET_OFF(kd_padding)]);
+ mov(aux_reg_ker_d, ptr[param1 + GET_OFF(filt)]);
+ mov(aux_reg_inp_d, reg_inp);
+
+ L(kd_label);
+ mov(reg_kj, ptr[param1 + GET_OFF(kh_padding)]);
+ } else {
+ mov(reg_kj, reg_kh);
+ }
+
+ if (jcp.ndims == 5) {
+ mov(aux_reg_inp, aux_reg_inp_d);
+ mov(aux_reg_ker, aux_reg_ker_d);
+ }
+
+ L(kh_label);
+ {
+ for (int ki = 0; ki < kw; ki++) {
+ int jj_start = get_ow_start(ki, pad_l);
+ int jj_end = get_ow_end(ur_w, ki, pad_r);
+ for (int ic = 0; ic < ic_block; ic++) {
+ if (jcp.kernel_kind == expl_bcast) {
+ for (int jj = jj_start; jj < jj_end; jj++) {
+ size_t aux_input_offset = input_offset(jj, ic, ki);
+ vbroadcastss(vmm_inp(jj, nb_oc_block),
+ EVEX_compress_addr_safe(aux_reg_inp,
+ aux_input_offset, reg_long_offt));
+ }
+ }
+ for (int ii = 0; ii < nb_oc_block; ii++) {
+ int aux_kernel_offset = jcp.typesize_in
+ * (ii * jcp.nb_ic * jcp.kh * jcp.kw * jcp.kd * ic_block
+ * oc_block + ki * ic_block * oc_block + ic * oc_block);
+ if (jj_end - jj_start > 0)
+ vmovups(vmm_wei, EVEX_compress_addr(aux_reg_ker,
+ aux_kernel_offset));
+ for (int jj = jj_start; jj < jj_end; jj++)
+ if (jcp.kernel_kind == expl_bcast)
+ vfmadd231ps(vmm_out(jj, ii),
+ vmm_inp(jj, nb_oc_block), vmm_wei);
+ else {
+ size_t aux_input_offset = input_offset(jj, ic, ki);
+ vfmadd231ps(vmm_out(jj, ii), vmm_wei,
+ EVEX_compress_addr_safe(aux_reg_inp,
+ aux_input_offset, reg_long_offt, true));
+ }
+ }
+ }
+ }
+ add(aux_reg_ker, shift_kernel_ptr);
+ add(aux_reg_inp, shift_input_ptr);
+ dec(reg_kj);
+ cmp(reg_kj, 0);
+ jg(kh_label, T_NEAR);
+ }
+
+ if (jcp.ndims == 5) {
+ add(aux_reg_inp_d,
+ typesize * (jcp.dilate_d + 1) * jcp.ih * jcp.iw * inp_mul);
+ add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * jcp.oc_block
+ * jcp.ic_block);
+
+ dec(reg_ki);
+ cmp(reg_ki, 0);
+ jg(kd_label, T_NEAR);
+
+ pop(reg_out);
+ }
+}
+
+template<typename Vmm>
+void _jit_avx512_common_conv_fwd_kernel<Vmm>::compute_loop(int ur_w,
+ int pad_l, int pad_r)
+{
+ if (jcp.ndims == 5) push(reg_oi);
+
+ prepare_output(ur_w);
+
+ Label skip_compute_loop;
+ if (jcp.ndims == 5) {
+ if ((jcp.dilate_d >= jcp.id)
+ || (jcp.kd - 1) * (jcp.dilate_d + 1) < nstl::max(jcp.f_pad, jcp.back_pad)) {
+ mov(reg_kj, ptr[param1 + GET_OFF(kd_padding)]);
+ cmp(reg_kj, 0);
+ je(skip_compute_loop, T_NEAR);
+ }
+ }
+ if ((jcp.dilate_h >= jcp.ih)
+ || (jcp.kh - 1) * (jcp.dilate_h + 1) < nstl::max(jcp.t_pad, jcp.b_pad)) {
+ mov(reg_kj, ptr[param1 + GET_OFF(kh_padding)]);
+ cmp(reg_kj, 0);
+ je(skip_compute_loop, T_NEAR);
+ }
+
+ if (jcp.ver == ver_4fma)
+ if(jcp.is_1stconv)
+ compute_loop_4fma_1st(ur_w, pad_l, pad_r);
+ else
+ compute_loop_4fma(ur_w, pad_l, pad_r);
+ else if (jcp.ver == ver_fma)
+ if ((jcp.is_1stconv && jcp.kernel_kind != expl_bcast)
+ || mayiuse(avx512_mic))
+ compute_loop_fma(ur_w, pad_l, pad_r);
+ else
+ if (jcp.kernel_kind == embd_bcast && jcp.nb_oc_blocking == 1)
+ compute_loop_fma(ur_w, pad_l, pad_r);
+ else
+ compute_loop_fma_core(ur_w, pad_l, pad_r);
+ else
+ assert(!"unknown convolution version");
+
+ L(skip_compute_loop);
+ store_output(ur_w);
+ if (jcp.ndims == 5) pop(reg_oi);
+}
+
+template<typename Vmm>
+void _jit_avx512_common_conv_fwd_kernel<Vmm>::generate()
+{
+ int iw = jcp.iw;
+ int ow = jcp.ow;
+ int ow_block = jcp.ow_block;
+ int nb_ow = jcp.nb_ow;
+ int kw = jcp.kw;
+ int l_pad = jcp.l_pad;
+ int ur_w = jcp.ur_w;
+ int ur_w_tail = jcp.ur_w_tail;
+ int dilate_w = jcp.dilate_w + 1;
+ int stride_w = jcp.stride_w;
+
+ int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block;
+ int inp_shift_pad = jcp.typesize_in * (ur_w * stride_w - l_pad) * inp_mult;
+ int inp_shift = jcp.typesize_in * ur_w * stride_w * inp_mult;
+ int inp_shift_pad_second_block = -1 * jcp.typesize_in * l_pad * inp_mult;
+ int out_shift = jcp.typesize_out * ur_w * jcp.oc_block;
+
+ preamble();
+ mov(reg_inp, ptr[param1 + GET_OFF(src)]);
+ mov(reg_out, ptr[param1 + GET_OFF(dst)]);
+ mov(reg_ker, ptr[param1 + GET_OFF(filt)]);
+ mov(reg_ker_prf, ptr[param1 + GET_OFF(filt_prf)]);
+ mov(reg_kh, ptr[param1 + GET_OFF(kh_padding)]);
+
+ int r_pad = nstl::max(
+ 0, (ow - 1) * stride_w + (kw - 1) * dilate_w - (iw + l_pad - 1));
+ int n_oi = ow / ur_w;
+ int r_pad1 = (ur_w * n_oi - 1) * stride_w + (kw - 1) * dilate_w
+ - (iw + l_pad - 1);
+
+ if (!is_ow_threading_on(jcp)) {
+ // ow is being processed as a whole - with left and right paddings
+ if (r_pad1 > 0) n_oi--;
+
+ if (ow == ur_w) {
+ mov(reg_inp_prf, ptr[param1 + GET_OFF(src_prf)]);
+ mov(reg_out_prf, ptr[param1 + GET_OFF(dst_prf)]);
+ compute_loop(ur_w, l_pad, r_pad);
+ } else {
+ mov(reg_inp_prf, reg_inp);
+ mov(reg_out_prf, reg_out);
+ if (n_oi == 0) {
+ add(reg_inp_prf, inp_shift_pad);
+ add(reg_out_prf, out_shift);
+ compute_loop(ur_w, l_pad, r_pad1);
+ add(reg_inp, inp_shift_pad);
+ add(reg_out, out_shift);
+ if (ur_w_tail != 0) {
+ add(reg_inp_prf, inp_shift);
+ add(reg_out_prf, out_shift);
+ compute_loop(ur_w_tail, 0, r_pad);
+ }
+ } else {
+ xor_(reg_oi, reg_oi);
+ if (l_pad > 0) {
+ add(reg_inp_prf, inp_shift_pad);
+ add(reg_out_prf, out_shift);
+ compute_loop(ur_w, l_pad, 0);
+ add(reg_inp, inp_shift_pad);
+ add(reg_out, out_shift);
+ inc(reg_oi);
+ }
+ if ((l_pad <= 0 && n_oi > 0) || (l_pad > 0 && n_oi > 1)) {
+ Label ow_loop_label;
+ L(ow_loop_label);
+ {
+ add(reg_inp_prf, inp_shift);
+ add(reg_out_prf, out_shift);
+ compute_loop(ur_w, 0, 0);
+ add(reg_inp, inp_shift);
+ add(reg_out, out_shift);
+ inc(reg_oi);
+ cmp(reg_oi, n_oi);
+ jl(ow_loop_label, T_NEAR);
+ }
+ }
+ if (r_pad1 > 0) {
+ add(reg_inp_prf, inp_shift);
+ add(reg_out_prf, out_shift);
+ compute_loop(ur_w, 0, r_pad1);
+ add(reg_inp, inp_shift);
+ add(reg_out, out_shift);
+ }
+ if (ur_w_tail != 0) {
+ add(reg_inp_prf, inp_shift);
+ add(reg_out_prf, out_shift);
+ compute_loop(ur_w_tail, 0, r_pad);
+ }
+ }
+ }
+ } else {
+ // ow block is only processed.
+ // Number of block is passed as parameter owb,
+ // and padding processing depends on this number.
+
+ Label end_label, last_oi_label, middle_ow_blocks_label, tail_label;
+ Label oi_loop_label, oi_loop_start_label, oi_loop_end_label;
+
+ assert(ow_block % ur_w == 0);
+ int n_oi_not_last_ow_block = ow_block / ur_w;
+ // to simplify code (and general regs usage),
+ // size of ow block must be >= 2 * ur_w
+ assert(n_oi_not_last_ow_block > 1);
+ int n_oi_next_last_ow_block = n_oi_not_last_ow_block;
+ int n_oi_first_ow_block = n_oi_not_last_ow_block;
+
+ int n_oi_last_ow_block = (ow - ow_block * (nb_ow-1)) / ur_w;
+
+ // prepare right padding
+ bool next_last_ow_block_padded = r_pad1 > 0 && n_oi_last_ow_block == 0;
+ bool first_ow_block_padded = next_last_ow_block_padded && jcp.nb_ow == 2;
+ bool last_ow_block_padded = r_pad1 > 0 && n_oi_last_ow_block > 0;
+
+ if (last_ow_block_padded) n_oi_last_ow_block--;
+ else if (first_ow_block_padded) n_oi_first_ow_block--;
+ else if (next_last_ow_block_padded) n_oi_next_last_ow_block--;
+
+ mov(reg_owb, ptr[param1 + GET_OFF(owb)]);
+ cmp(reg_owb, 0); // is that the first ow-block ?
+ jg(middle_ow_blocks_label, T_NEAR);
+
+ // the first ow block, compute left padding
+
+ mov(reg_oi, n_oi_first_ow_block);
+ mov(reg_inp_prf, reg_inp);
+ mov(reg_out_prf, reg_out);
+
+ if (l_pad > 0) {
+ mov(reg_ker_prf, ptr[param1 + GET_OFF(filt_prf)]);
+ add(reg_inp_prf, inp_shift_pad);
+ add(reg_out_prf, out_shift);
+ compute_loop(ur_w, l_pad, 0);
+ add(reg_inp, inp_shift_pad);
+ add(reg_out, out_shift);
+ dec(reg_oi);
+ }
+ jmp(oi_loop_label, T_NEAR);
+
+ // middle or last ow block entry
+
+ L(middle_ow_blocks_label);
+
+ if (l_pad > 0) {
+ // just to consider left padding, not compute
+ add(reg_inp, inp_shift_pad_second_block);
+ add(reg_inp_prf, inp_shift_pad_second_block);
+ }
+
+ // set number of iteration for oi-loop
+ cmp(reg_owb, jcp.nb_ow - 1); // last ow-block ?
+ mov(reg_oi, n_oi_last_ow_block);
+ je(oi_loop_label, T_NEAR);
+ cmp(reg_owb, jcp.nb_ow - 2); // next to last ow-block ?
+ mov(reg_oi, n_oi_next_last_ow_block);
+ je(oi_loop_label, T_NEAR);
+ mov(reg_oi, n_oi_not_last_ow_block); // other middle ow-blocks
+
+ // oi loop w/o padding
+ L(oi_loop_label);
+ mov(reg_ker_prf, ptr[param1 + GET_OFF(filt_prf)]);
+ L(oi_loop_start_label);
+ cmp(reg_oi, 0);
+ jle(oi_loop_end_label, T_NEAR);
+
+ add(reg_inp_prf, inp_shift);
+ add(reg_out_prf, out_shift);
+ compute_loop(ur_w, 0, 0);
+ add(reg_inp, inp_shift);
+ add(reg_out, out_shift);
+ dec(reg_oi);
+ jmp(oi_loop_start_label, T_NEAR);
+ L(oi_loop_end_label);
+
+ mov(reg_owb, ptr[param1 + GET_OFF(owb)]);
+
+ cmp(reg_owb, 0); // first ow-block ?
+ if (first_ow_block_padded) {
+ je(last_oi_label, T_NEAR);
+ } else {
+ je(end_label, T_NEAR);
+ }
+ cmp(reg_owb, jcp.nb_ow - 2); // next to last ow-block ?
+ jl(end_label, T_NEAR);
+ if (next_last_ow_block_padded) {
+ je(last_oi_label, T_NEAR);
+ } else {
+ je(end_label, T_NEAR);
+ }
+ // that is last block
+ if (!last_ow_block_padded) {
+ jmp(tail_label, T_NEAR);
+ }
+
+ // last oi block with right padding
+ L(last_oi_label);
+ mov(reg_ker_prf, ptr[param1 + GET_OFF(filt_prf)]);
+ add(reg_inp_prf, inp_shift);
+ add(reg_out_prf, out_shift);
+ compute_loop(ur_w, 0, r_pad1);
+ add(reg_inp, inp_shift);
+ add(reg_out, out_shift);
+
+ mov(reg_owb, ptr[param1 + GET_OFF(owb)]);
+ cmp(reg_owb, jcp.nb_ow - 1); // last ow_block?
+ jl(end_label, T_NEAR);
+
+ L(tail_label);
+ mov(reg_ker_prf, ptr[param1 + GET_OFF(filt_prf)]);
+ if (ur_w_tail != 0) {
+ add(reg_inp_prf, inp_shift);
+ add(reg_out_prf, out_shift);
+ compute_loop(ur_w_tail, 0, r_pad);
+ }
+ L(end_label);
+ }
+ postamble();
+
+ if (jcp.with_eltwise)
+ eltwise_injector_->prepare_table();
+}
+
+bool jit_avx512_common_conv_fwd_kernel::post_ops_ok(
+ jit_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ const auto &p = attr.post_ops_;
+
+ auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); };
+ auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); };
+
+ switch (p.len_) {
+ case 0: return true; // no post_ops
+ case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise
+ case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise
+ default: return false;
+ }
+
+ return false;
+}
+
+status_t jit_avx512_common_conv_fwd_kernel::init_conf(
+ jit_conv_conf_t &jcp, const convolution_desc_t &cd,
+ memory_desc_t &src_md, memory_desc_t &weights_md,
+ memory_desc_t &dst_md, memory_desc_t &bias_md,
+ const primitive_attr_t &attr, int nthreads)
+{
+ using namespace prop_kind;
+
+ if (!mayiuse(avx512_common))
+ return status::unimplemented;
+
+ const memory_desc_wrapper src_d(&src_md);
+ const memory_desc_wrapper weights_d(&weights_md);
+ const memory_desc_wrapper dst_d(&dst_md);
+ const memory_desc_wrapper bias_d(&bias_md);
+
+ const int regs = 28;
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ int ndims = src_d.ndims();
+
+ jcp = zero<decltype(jcp)>();
+ jcp.ndims = ndims;
+ jcp.prop_kind = cd.prop_kind;
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.id = (ndims == 5) ? src_d.dims()[2] : 1;
+ jcp.ih = (ndims == 3) ? 1 : src_d.dims()[ndims-2];
+ jcp.iw = src_d.dims()[ndims-1];
+ jcp.od = (ndims == 5) ? dst_d.dims()[2] : 1;
+ jcp.oh = (ndims == 3) ? 1 : dst_d.dims()[ndims-2];
+ jcp.ow = dst_d.dims()[ndims-1];
+ jcp.kd = (ndims == 5) ? weights_d.dims()[with_groups + 2] : 1;
+ jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + ndims-2];
+ jcp.kw = weights_d.dims()[with_groups + ndims-1];
+ jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0;
+ jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4];
+ jcp.l_pad = cd.padding[0][ndims-3];
+ jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1;
+ jcp.stride_h = (ndims == 3) ? 1 : cd.strides[ndims-4];
+ jcp.stride_w = cd.strides[ndims-3];
+
+ jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0;
+ jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4];
+ jcp.dilate_w = cd.dilates[ndims-3];
+
+ jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1)
+ - (jcp.ih + jcp.t_pad - 1);
+ jcp.back_pad = (jcp.od - 1) * jcp.stride_d
+ + (jcp.kd - 1) * (jcp.dilate_d + 1) - (jcp.id + jcp.f_pad - 1);
+
+ jcp.is_1stconv = is_1stconv(jcp);
+
+ bool ok_to_pad_channels = true
+ && jcp.ngroups == 1
+ && src_d.data_type() == data_type::f32;
+
+ const int full_simd_w = cpu_isa_traits<avx512_common>::vlen / sizeof(float);
+ jcp.simd_w = full_simd_w;
+ bool ok_to_try_xmm = true
+ && mayiuse(avx512_core)
+ && src_d.data_type() == data_type::f32
+ && !jcp.is_1stconv
+ && !ok_to_pad_channels
+ && (jcp.ic % jcp.simd_w != 0 || jcp.oc % jcp.simd_w != 0)
+ && (jcp.ic % 8 != 0 || jcp.oc % 8 != 0);
+ if (ok_to_try_xmm)
+ jcp.simd_w = 4;
+
+ jcp.oc_block = jcp.simd_w;
+ jcp.ic_block = jcp.is_1stconv ? jcp.ic : jcp.simd_w;
+ jcp.aligned_threads = 0;
+
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, jcp.oc_block);
+ jcp.ic = rnd_up(jcp.ic, jcp.ic_block);
+ }
+ bool args_ok = true
+ && jcp.oc % jcp.oc_block == 0
+ && jcp.ic % jcp.ic_block == 0;
+ if (!args_ok)
+ return status::unimplemented;
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ jcp.with_sum = p.find(primitive_kind::sum) != -1;
+ const int eltwise_ind = p.find(primitive_kind::eltwise);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise) {
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+ if (dst_d.data_type() == data_type::s32) return status::unimplemented;
+ }
+
+ auto src_tag = jcp.is_1stconv
+ ? pick(ndims - 3, ncw, nchw, ncdhw)
+ : ((jcp.simd_w == 4)
+ ? pick(ndims - 3, nCw4c, nChw4c, nCdhw4c)
+ : pick(ndims - 3, nCw16c, nChw16c, nCdhw16c));
+ auto dst_tag = (jcp.simd_w == 4)
+ ? pick(ndims - 3, nCw4c, nChw4c, nCdhw4c)
+ : pick(ndims - 3, nCw16c, nChw16c, nCdhw16c);
+ auto wei_tag = with_groups
+ ? ((jcp.simd_w == 4)
+ ? pick(ndims - 3, gOIw4i4o, gOIhw4i4o, gOIdhw4i4o)
+ : pick(ndims - 3, gOIw16i16o, gOIhw16i16o, gOIdhw16i16o))
+ : ((jcp.simd_w == 4)
+ ? pick(ndims - 3, OIw4i4o, OIhw4i4o, OIdhw4i4o)
+ : pick(ndims - 3, OIw16i16o, OIhw16i16o, OIdhw16i16o));
+
+ if (src_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(src_md, src_tag));
+ jcp.src_tag = src_tag;
+ } else {
+ jcp.src_tag = src_d.matches_one_of_tag(src_tag);
+ }
+ if (jcp.src_tag != src_tag)
+ return status::unimplemented;
+
+ if (dst_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(dst_md, dst_tag));
+ jcp.dst_tag = dst_tag;
+ } else {
+ jcp.dst_tag = dst_d.matches_one_of_tag(dst_tag);
+ }
+ if (jcp.dst_tag != dst_tag)
+ return status::unimplemented;
+
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+ if (jcp.with_bias) {
+ if (bias_d.format_kind() == format_kind::any)
+ CHECK(memory_desc_init_by_tag(bias_md, x));
+ }
+
+ if (mayiuse(avx512_common) &&
+ src_d.data_type() == data_type::f32
+ && weights_d.data_type() == data_type::f32
+ && dst_d.data_type() == data_type::f32) {
+ jcp.ver = ver_fma;
+ jcp.typesize_in = sizeof(float);
+ jcp.typesize_out = sizeof(float);
+ if (mayiuse(avx512_mic_4ops))
+ jcp.ver = ver_4fma;
+
+ if (jcp.is_1stconv) {
+ // TODO: fix & remove constraints below
+ bool not_for_4fma
+ = IMPLICATION(everyone_is(0, jcp.l_pad, jcp.t_pad),
+ nstl::max(jcp.kw, jcp.kh) < 7);
+ bool is_dilated
+ = !everyone_is(0, jcp.dilate_d, jcp.dilate_h, jcp.dilate_w);
+ if (one_of(true, not_for_4fma, is_dilated))
+ jcp.ver = ver_fma;
+ if (jcp.ver == ver_4fma) {
+ wei_tag = with_groups
+ ? ((jcp.simd_w == 4)
+ ? pick(ndims - 3, gOiw4o, gOihw4o, gOidhw4o)
+ : pick(ndims - 3, gOiw16o, gOihw16o, gOidhw16o))
+ : ((jcp.simd_w == 4)
+ ? pick(ndims - 3, Oiw4o, Oihw4o, Oidhw4o)
+ : pick(ndims - 3, Oiw16o, Oihw16o, Oidhw16o));
+ } else {
+ wei_tag = with_groups
+ ? ((jcp.simd_w == 4)
+ ? pick(ndims - 3, gOwi4o, gOhwi4o, gOdhwi4o)
+ : pick(ndims - 3, gOwi16o, gOhwi16o, gOdhwi16o))
+ : ((jcp.simd_w == 4)
+ ? pick(ndims - 3, Owi4o, Ohwi4o, Odhwi4o)
+ : pick(ndims - 3, Owi16o, Ohwi16o, Odhwi16o));
+ }
+ }
+ } else {
+ return status::unimplemented;
+ }
+
+ if (weights_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(weights_md, wei_tag));
+ jcp.wei_tag = wei_tag;
+ } else {
+ jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag);
+ }
+ if (jcp.wei_tag != wei_tag)
+ return status::unimplemented;
+
+ if (jcp.is_1stconv) {
+ jcp.ur_w = nstl::min(jcp.ow, regs);
+ } else {
+ // avx512_core guard - just to avoid possible regression for other archs
+ if (jcp.ver == ver_fma && mayiuse(avx512_core)) {
+ jcp.ur_w = nstl::min(jcp.ow, regs);
+ } else {
+ for (int ur_w = regs; ur_w > 0; --ur_w) {
+ if (jcp.ow % ur_w == 0) {
+ jcp.ur_w = ur_w;
+ break;
+ }
+ }
+ }
+ if ((ndims == 5 && jcp.ur_w <= 8) || (jcp.ur_w <= 1)) {
+ jcp.ur_w = nstl::min(jcp.ow, regs);
+ }
+ }
+ // TODO (Tanya): currently applied to Segnet convolutions only.
+ // Need to try for other topologies
+ if (jcp.ow > 150 && jcp.ur_w < regs/2)
+ jcp.ur_w = regs;
+
+ int n_oi = (jcp.ow / jcp.ur_w);
+ int r_pad = (jcp.ur_w * n_oi - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1);
+ if (jcp.l_pad > 0 && r_pad > 0)
+ n_oi--;
+
+ bool large_code_size = jcp.ur_w != jcp.ow && jcp.l_pad > 0 && r_pad > 0
+ && ((jcp.l_pad <= 0 && n_oi > 0) || (jcp.l_pad > 0 && n_oi > 1));
+ if (large_code_size) {
+ const int max_code_size = 24 * 1024;
+ const int num_ops_per_reg = 6 + jcp.ic_block * jcp.kw;
+ int mult = 1;
+ if (jcp.l_pad > 0) mult += 1;
+ if (r_pad > 0) mult += 1;
+ for (int ur_w = jcp.ur_w; ur_w > regs/2; --ur_w) {
+ if (ur_w * mult * num_ops_per_reg * 9.0 < max_code_size) {
+ jcp.ur_w = ur_w;
+ break;
+ }
+ }
+ }
+
+ /* Grouped channel offset to support 'non-blocked data' format for
+ * convolution sizes with '(input_channel / ngroups) < simd' */
+ jcp.nonblk_group_off
+ = (jcp.ngroups > 1 && one_of(jcp.src_tag, ncw, nchw, ncdhw)) ?
+ jcp.ic :
+ 1;
+
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+ jcp.nb_ic_blocking = jcp.nb_oc_blocking = 1;
+
+ auto is_ow_threading_applicable = [=]() {
+ return (true && !jcp.is_1stconv && one_of(jcp.ndims, 3, 4)
+ && IMPLICATION(mayiuse(avx512_mic),
+ jcp.ver == ver_4fma
+ && IMPLICATION(jcp.mb != 1,
+ jcp.ih == 1 && jcp.kh == 1)));
+ };
+
+ if (jcp.ver == ver_4fma && !jcp.is_1stconv) {
+ if ((jcp.kw <= 5 && jcp.kh <= 5 && jcp.kw == jcp.kh && jcp.ow <= 8
+ && jcp.oh <= 8 && jcp.ow == jcp.oh)
+ || (jcp.stride_h != 1 && jcp.ur_w < jcp.ow)) {
+ if (jcp.nb_oc % 2 == 0) {
+ jcp.nb_oc_blocking = 2;
+ jcp.ur_w = nstl::min(jcp.ow, regs / jcp.nb_oc_blocking);
+ }
+ } else {
+ for (int i = jcp.nb_oc; i > 0; i--)
+ if (i * jcp.ur_w <= regs && jcp.nb_oc % i == 0) {
+ jcp.nb_oc_blocking = i;
+ break;
+ }
+ }
+ if (jcp.ver == ver_4fma && is_ow_threading_applicable()) {
+ if (jcp.nb_oc % 2 == 0 && jcp.ur_w < jcp.ow
+ && jcp.ow != 2 * jcp.ur_w) {
+ jcp.nb_oc_blocking = 2;
+ jcp.ur_w = nstl::min(jcp.ow, regs / jcp.nb_oc_blocking);
+ }
+ }
+ }
+
+ jcp.ow_block = jcp.ow;
+
+ auto get_thr_eff = [=](int nb_oc_blocking, int ow_block) {
+ int nb_ow = div_up(jcp.ow, ow_block);
+ int nb_oc_chunks = div_up(jcp.nb_oc, nb_oc_blocking);
+ int work_amount = jcp.mb * jcp.oh * nb_oc_chunks * nb_ow;
+ float disbalance = (float)jcp.ow / rnd_up(jcp.ow, ow_block);
+ float thr_eff = disbalance * (float)work_amount
+ / rnd_up(work_amount, nthreads);
+ return thr_eff;
+ };
+
+ auto get_ow_block = [=](int nb_oc_blocking, int ur_w, float &eff) {
+ int res_ow_block = jcp.ow;
+ eff = get_thr_eff(nb_oc_blocking, res_ow_block);
+ if (!is_ow_threading_applicable())
+ return res_ow_block;
+
+ int L2_part = (get_cache_size(2) * 7 / 8) / typesize;
+ if (jcp.ver == ver_4fma)
+ L2_part /= 2;
+ int size_src_chunk = jcp.ic_block * ur_w * jcp.kh;
+ int size_dst_chunk = jcp.oc_block * nb_oc_blocking * ur_w;
+ int size_wei_chunk = jcp.oc_block * nb_oc_blocking * jcp.ic_block
+ * jcp.kw * jcp.kh;
+ int nurw_cache = (L2_part - 2 * size_wei_chunk)
+ / (2 * size_dst_chunk + 2 * size_src_chunk);
+ // current design of generate() requires ow_block >= 2 * ur_w
+ int ow_block_cache = ur_w * nstl::max(2, nurw_cache);
+
+ int ow_block_thr = ow_block_cache;
+ eff = get_thr_eff(nb_oc_blocking, ow_block_thr);
+
+ int max_nb_ow = div_up(jcp.ow, 2 * ur_w);
+ int start_nb_ow = div_up(jcp.ow, ow_block_thr);
+ for (int nb_ow = start_nb_ow; nb_ow <= max_nb_ow; nb_ow++) {
+ int ow_block
+ = nstl::min(rnd_up(div_up(jcp.ow, nb_ow), ur_w), jcp.ow);
+ float eff_threshold = (jcp.ver == ver_4fma) ? 0.8f : 0.9f;
+ if (ow_block < nb_oc_blocking * jcp.oc_block && eff > eff_threshold)
+ break;
+ if (div_up(jcp.ow, ow_block) != nb_ow)
+ continue;
+ float thr_eff = get_thr_eff(nb_oc_blocking, ow_block);
+ float eff_step = (jcp.ver == ver_4fma) ? 1.1f : 1.f;
+ if (ow_block >= 2 * ur_w && thr_eff > eff_step * eff) {
+ ow_block_thr = ow_block;
+ eff = thr_eff;
+ }
+ eff_threshold = (jcp.ver == ver_4fma) ? 0.9f : 0.98f;
+ if (eff > eff_threshold)
+ break;
+ }
+ res_ow_block = nstl::min(jcp.ow, nstl::max(2 * ur_w, ow_block_thr));
+ eff = get_thr_eff(nb_oc_blocking, res_ow_block);
+ return res_ow_block;
+ };
+
+
+ if (jcp.ver == ver_fma && mayiuse(avx512_core)) {
+ int try_nb_oc_blocking = 2;
+ unsigned int ker_inp_size = typesize * div_up(jcp.iw, jcp.stride_w)
+ * jcp.ic_block * jcp.kh * jcp.kd;
+ unsigned int ker_out_size = typesize * jcp.ow * jcp.oc_block
+ * try_nb_oc_blocking;
+ unsigned int ker_wei_size = typesize * jcp.kh * jcp.kw * jcp.ic_block
+ * jcp.oc_block * try_nb_oc_blocking * jcp.kd;
+ unsigned int ker_total_size = ker_inp_size + ker_out_size
+ + ker_wei_size;
+
+ bool embd_bcast_condition = true
+ && (jcp.kw == 3 && jcp.ow <= 28 && ker_total_size < L1_cache_size)
+ && !(jcp.kw == 3 && jcp.ow == 13 && jcp.ic >= 192)
+ && !(jcp.kw == 3 && jcp.ow == 28 && jcp.ic >= 512);
+
+ if (jcp.mb == 1) {
+ unsigned int inp_size = jcp.mb * div_up(jcp.ih, jcp.stride_h)
+ * div_up(jcp.iw, jcp.stride_w) * jcp.ic;
+ unsigned int wei_size = jcp.ic * jcp.oc * jcp.kh * jcp.kw;
+
+ // Estimate whether we need to limit the number of threads
+ // and calculate this number. Includes some heuristic.
+ int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking;
+ int work_amount = jcp.mb * jcp.ngroups * oc_chunks * jcp.oh;
+ int job_size_min = work_amount / nthreads;
+ int job_size_max = div_up(work_amount, nthreads);
+ int ch_max = rnd_up(jcp.oh, job_size_max);
+ int ch_min = (job_size_min == 0)
+ ? jcp.oh
+ : rnd_up(jcp.oh, job_size_min);
+ bool not_aligned_max = ch_max % jcp.oh != 0 && ch_max / jcp.oh < 2
+ && (jcp.oh != 8 || ch_max / jcp.oh > 1);
+ bool not_aligned_min = ch_min % jcp.oh != 0 && ch_min / jcp.oh < 2
+ && (jcp.oh != 8 || ch_min / jcp.oh > 1);
+ bool eligible_case = (jcp.stride_h == 1 && jcp.stride_w == 1)
+ || nthreads > oc_chunks;
+ if (jcp.loop_order == loop_cgn && oc_chunks > 1 && nthreads > 1
+ && wei_size / inp_size > 24
+ && (not_aligned_max || not_aligned_min)
+ && eligible_case) {
+ // Try to find nthreads > mkldnn_get_max_threads() / 2 such
+ // that oc_chunks is a multiple of nthreads, or nthreads is a
+ // multiple of oc_chunks. Otherwise, keep default value.
+ // TODO: implement a task-based alternative without throttling.
+ jcp.aligned_threads = nthreads;
+ for (int i = nthreads; i > nthreads / 2; i--) {
+ if (oc_chunks % i == 0 || i % oc_chunks == 0) {
+ jcp.aligned_threads = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (jcp.kw > 3
+ || (jcp.stride_w == 1 && jcp.stride_h == 1
+ && embd_bcast_condition)
+ || ((jcp.stride_w != 1 || jcp.stride_h != 1)
+ && ((jcp.mb <= 16 && (jcp.oc <= 192 || jcp.oh <= 10)
+ && embd_bcast_condition)))
+ || (jcp.mb == 1
+ && (jcp.ur_w >= jcp.ow || jcp.is_1stconv
+ || (jcp.ow <= 147 && jcp.oc <= 96)))) {
+ jcp.kernel_kind = embd_bcast;
+ jcp.ur_w = nstl::min(jcp.ow, regs);
+ jcp.nb_ic_blocking = jcp.nb_oc_blocking = 1;
+ if (ker_total_size < L1_cache_size && jcp.ow <= 8 && jcp.kh <= 3
+ && jcp.kw <= 3 && jcp.nb_oc % try_nb_oc_blocking == 0
+ && IMPLICATION(jcp.is_1stconv, jcp.mb == 1)
+ && IMPLICATION(jcp.mb == 1, jcp.ur_w < jcp.ow)) {
+ jcp.nb_oc_blocking = try_nb_oc_blocking;
+ jcp.ur_w = nstl::min(jcp.ow, 31 / (jcp.nb_oc_blocking + 1));
+ }
+ } else {
+ jcp.kernel_kind = expl_bcast;
+ jcp.nb_ic_blocking = 1;
+ if (IMPLICATION(jcp.is_1stconv, jcp.mb > 1)) {
+ float best_thr_eff = 0.f;
+ int best_nb_oc_blocking = 1;
+ for (int i = nstl::min(jcp.nb_oc, 5); i > 0; i--) {
+ if (jcp.nb_oc % i == 0) {
+ float thr_eff;
+ int ur_w = nstl::min(jcp.ow, 31 / (i + 1));
+ get_ow_block(i, ur_w, thr_eff);
+ if (thr_eff > 1.05f * best_thr_eff) {
+ best_nb_oc_blocking = i;
+ best_thr_eff = thr_eff;
+ }
+ }
+ }
+ jcp.nb_oc_blocking = best_nb_oc_blocking;
+ jcp.ur_w = nstl::min(jcp.ow, 31 / (jcp.nb_oc_blocking + 1));
+ }
+ }
+ }
+
+ jcp.ur_w_tail = jcp.ow % jcp.ur_w;
+
+ args_ok = true
+ && jcp.l_pad <= jcp.ur_w
+ && jcp.ic <= src_d.padded_dims()[1]
+ && jcp.oc <= dst_d.padded_dims()[1]
+ && jcp.ic <= weights_d.padded_dims()[with_groups + 1]
+ && jcp.oc <= weights_d.padded_dims()[with_groups + 0];
+ if (!args_ok)
+ return status::unimplemented;
+
+ int r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1)
+ - (jcp.iw + jcp.l_pad - 1));
+ if (r_pad_no_tail > jcp.ur_w)
+ return status::unimplemented;
+
+ pick_loop_order(jcp);
+
+ jcp.nb_ic_L2 = jcp.nb_ic;
+
+ float thr_eff;
+ jcp.ow_block = get_ow_block(jcp.nb_oc_blocking, jcp.ur_w, thr_eff);
+ jcp.nb_ow = div_up(jcp.ow, jcp.ow_block);
+
+ const int L2_size = get_cache_size(2, true) / sizeof(float);
+ // Source and output data needs to fit in L2,
+ // leaving some space for weights and prefetching.
+ int h_L2 = int(((0.6f * L2_size) / jcp.simd_w
+ - nstl::min(0, jcp.kh - jcp.stride_h) * jcp.iw)
+ / (jcp.stride_h * jcp.iw + jcp.ow));
+ jcp.h_blocking = nstl::max(1, nstl::min(jcp.oh, h_L2));
+
+ if (jcp.ver == ver_4fma) {
+ if (!is_ow_threading_on(jcp)) {
+ for (int divf = 2, temp_nb = jcp.nb_ic_L2; divf <= jcp.nb_ic;
+ divf++) {
+ size_t l2_src
+ = (size_t)jcp.iw * jcp.ic_block * jcp.ih * temp_nb * jcp.id;
+ size_t l2_dst = (size_t)jcp.ow * jcp.oc_block * jcp.nb_oc_blocking
+ * jcp.oh * jcp.od;
+ size_t l2_filt = (size_t)jcp.kw * jcp.oc_block * jcp.ic_block
+ * jcp.kh * jcp.nb_oc_blocking * temp_nb * jcp.kd;
+ if (4 * (l2_src + l2_dst + l2_filt) > KNx_L2_EFFECTIVE_CAPACITY) {
+ if (jcp.kh == 3 && jcp.oh == 7) {
+ jcp.nb_ic_L2 = 1;
+ break;
+ }
+ temp_nb = (jcp.nb_ic_L2 % divf == 0 ? jcp.nb_ic_L2 / divf
+ : jcp.nb_ic_L2);
+ } else {
+ jcp.nb_ic_L2 = temp_nb;
+ break;
+ }
+ }
+ } else if (jcp.ic > 64) {
+ jcp.nb_ic_L2 = 2; /* according to performance data*/
+ }
+ }
+
+ return status::success;
+}
+
+void jit_avx512_common_conv_fwd_kernel::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) {
+ if (jcp.with_bias && jcp.oc != jcp.oc_without_padding)
+ scratchpad.book(key_conv_padded_bias, jcp.typesize_out * jcp.oc);
+}
+
+void jit_avx512_common_conv_bwd_data_kernel_f32::prepare_output(int ur_w)
+{
+ for (int k = 0; k < jcp.nb_ic_blocking; k++) {
+ for (int j = 0; j < ur_w; j++) {
+ Zmm zmm = zmm_out(j, k);
+ vpxord(zmm, zmm, zmm);
+ size_t aux_src_offset
+ = (size_t)typesize * ((size_t)k * jcp.ih * jcp.iw * jcp.id + j)
+ * jcp.ic_block;
+ mic_prefetcht1(EVEX_compress_addr_safe(reg_src_prf, aux_src_offset,
+ reg_long_offt));
+ }
+ }
+}
+
+void jit_avx512_common_conv_bwd_data_kernel_f32::store_output(int ur_w)
+{
+ Label no_update_label;
+
+ mov(reg_channel, ptr[param + GET_OFF(channel)]);
+ cmp(reg_channel, 0);
+ je(no_update_label, T_NEAR);
+ for (int k = 0; k < jcp.nb_ic_blocking; k++) {
+ for (int j = 0; j < ur_w; j++) {
+ Zmm zmm = zmm_out(j, k);
+ size_t aux_src_offset = (size_t)typesize
+ * ((size_t)k * jcp.ih * jcp.iw * jcp.id + j) * jcp.ic_block;
+ vaddps(zmm, EVEX_compress_addr_safe(reg_src, aux_src_offset,
+ reg_long_offt));
+ }
+ }
+
+ L(no_update_label);
+ for (int k = 0; k < jcp.nb_ic_blocking; k++) {
+ for (int j = 0; j < ur_w; j++) {
+ Zmm zmm = zmm_out(j, k);
+ size_t aux_src_offset = (size_t)typesize
+ * ((size_t)k * jcp.ih * jcp.iw * jcp.id + j) * jcp.ic_block;
+ vmovups(EVEX_compress_addr_safe(reg_src, aux_src_offset,
+ reg_long_offt), zmm);
+ mic_prefetcht0(EVEX_compress_addr_safe(reg_src_prf, aux_src_offset,
+ reg_long_offt));
+ }
+ }
+}
+
+void jit_avx512_common_conv_bwd_data_kernel_f32::compute_loop_4fma(
+ int ur_w, int l_overflow, int r_overflow)
+{
+ int ow = jcp.ow;
+ int kw = jcp.kw;
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ Label kh_label, last_iter_label, loop_end_label, kd_label;
+ int ker_load_number = 4;
+ int shift_ker_ptr = typesize * kw * oc_block * ic_block;
+ int shift_dst_ptr = typesize * ow * oc_block;
+ int ii_dpref_t0 = get_iw_start(0, l_overflow);
+ int iw_end_ipref = get_iw_end(ur_w, 0, r_overflow);
+
+ bool check_last_kh = (jcp.kh > 3);
+ auto kernel_offset = [=](int icb, int oc, int ki) {
+ int blk_idx = icb * jcp.kh * jcp.kw * jcp.kd + ki;
+ int blk_offset = blk_idx * jcp.oc_block * jcp.ic_block;
+ int oc_offset = oc * jcp.oc_block;
+ return typesize * (blk_offset + oc_offset);
+ };
+ auto kernel_loads = [=](int ki, int oc, int kk) {
+ for (int ii = 0; ii < ker_load_number; ii++) {
+ int aux_kernel_offset = kernel_offset(kk, oc + ii, ki);
+ vmovups(zmm_ker(ii),
+ EVEX_compress_addr(aux_reg_ker, aux_kernel_offset));
+ }
+ };
+ auto prefetch_dst_next_kh = [&](int ki, int ki_start, int cnt0, int cnt1) {
+ if (cnt1 >= ker_load_number && cnt0 >= ker_load_number
+ && ki >= ki_start && ii_dpref_t0 < iw_end_ipref) {
+ int aux_dst_offset = typesize * ((ii_dpref_t0
+ + jcp.l_pad) * oc_block + jcp.ow * oc_block);
+ prefetcht0(EVEX_compress_addr(aux_reg_dst, aux_dst_offset));
+ ii_dpref_t0++;
+ }
+ };
+
+ if (one_of(jcp.ndims, 3, 4)) {
+ mov(aux_reg_dst, reg_dst);
+ mov(aux_reg_ker, reg_ker);
+ mov(aux_reg_dst_prf, reg_dst_prf);
+ mov(aux_reg_ker_prf, reg_ker_prf);
+ }
+
+ if (jcp.ndims == 5) {
+ push(reg_src_prf);
+ push(reg_src);
+
+ mov(reg_ki, ptr[param + GET_OFF(kd_padding)]);
+ mov(aux_reg_dst_d, reg_dst);
+ mov(aux_reg_ker_d, ptr[param + GET_OFF(filt)]);
+ mov(aux_reg_dst_d_prf, reg_dst_prf);
+ mov(aux_reg_ker_d_prf, reg_ker_prf);
+
+ L(kd_label);
+ mov(reg_kj, ptr[param + GET_OFF(kh_padding)]);
+ } else {
+ mov(reg_kj, reg_kh);
+ }
+
+ if (jcp.ndims == 5) {
+ mov(aux_reg_dst, aux_reg_dst_d);
+ mov(aux_reg_ker, aux_reg_ker_d);
+ mov(aux_reg_dst_prf, aux_reg_dst_d_prf);
+ mov(aux_reg_ker_prf, aux_reg_ker_d_prf);
+ }
+
+ align(16);
+ L(kh_label);
+ if (check_last_kh) {
+ for (int ki = 0; ki < kw; ki++)
+ for (int oc = 0; oc < oc_block; oc += 4)
+ for (int kk = 0; kk < jcp.nb_ic_blocking; kk++) {
+ bool last_kernel_loads = (kk == jcp.nb_ic_blocking - 1
+ && ki == kw - 1 && (oc + 4) == oc_block);
+
+ if (last_kernel_loads) {
+ cmp(reg_kj, 1);
+ je(last_iter_label, T_NEAR);
+ }
+
+ kernel_loads(ki, oc, kk);
+ for (int ii = get_iw_start(ki, l_overflow),
+ prf_count_t0 = 0, prf_count_t1 = 0;
+ ii < get_iw_end(ur_w, ki, r_overflow); ii++) {
+ int aux_dst_offset = typesize
+ * ((ii + jcp.l_pad - ki) * oc_block + oc);
+ v4fmaddps(zmm_out(ii, kk), zmm_ker(0),
+ EVEX_compress_addr(aux_reg_dst, aux_dst_offset));
+
+ if (ii % 2) {
+ if (prf_count_t0 < 4) {
+ int aux_kernel_prf;
+ if (last_kernel_loads)
+ aux_kernel_prf= kernel_offset(0, prf_count_t0
+ + oc + 4 - oc_block, 0) + typesize * kw
+ * oc_block * ic_block;
+ else
+ aux_kernel_prf = kernel_offset(kk, oc + 4
+ + prf_count_t0, ki);
+ mic_prefetcht0(EVEX_compress_addr(aux_reg_ker,
+ aux_kernel_prf));
+ prf_count_t0++;
+ } else if (prf_count_t1 < 4) {
+ mic_prefetcht1(EVEX_compress_addr(aux_reg_ker_prf,
+ kernel_offset(kk, oc + prf_count_t1, ki)));
+ prf_count_t1++;
+ }
+ } else
+ prefetch_dst_next_kh(ki, 2, prf_count_t0, prf_count_t1);
+ }
+ if (last_kernel_loads) {
+ jmp(loop_end_label, T_NEAR);
+
+ L(last_iter_label);
+
+ kernel_loads(ki, oc, kk);
+ for (int ii = get_iw_start(ki, l_overflow),
+ prf_count_t0 = 0, prf_count_t1 = 0;
+ ii < get_iw_end(ur_w, ki, r_overflow); ii++) {
+ int aux_dst_offset = typesize
+ * ((ii + jcp.l_pad - ki) * oc_block + oc);
+ v4fmaddps(zmm_out(ii, kk), zmm_ker(0),
+ EVEX_compress_addr(aux_reg_dst, aux_dst_offset));
+ if (ii % 2) {
+ if (prf_count_t0 < 4) {
+ mic_prefetcht0(EVEX_compress_addr(aux_reg_ker_prf,
+ kernel_offset(0, prf_count_t0, 0)));
+ prf_count_t0++;
+ } else if (prf_count_t1 < 4) {
+ mic_prefetcht1(EVEX_compress_addr(aux_reg_ker_prf,
+ kernel_offset(kk, oc + prf_count_t1, ki)));
+ prf_count_t1++;
+ }
+ }
+ }
+ L(loop_end_label);
+ }
+ }
+ } else {
+ for (int ki = 0; ki < kw; ki++)
+ for (int oc = 0; oc < oc_block; oc += 4)
+ for (int kk = 0; kk < jcp.nb_ic_blocking; kk++) {
+ kernel_loads(ki, oc, kk);
+
+ for (int ii = get_iw_start(ki, l_overflow), prf_count_t1 = 0;
+ ii < get_iw_end(ur_w, ki, r_overflow); ii++) {
+ int aux_dst_offset = typesize
+ * ((ii + jcp.l_pad - ki) * oc_block + oc);
+ v4fmaddps(zmm_out(ii, kk), zmm_ker(0),
+ EVEX_compress_addr(aux_reg_dst, aux_dst_offset));
+ if ((ii % 2) && (prf_count_t1 < 4)) {
+ mic_prefetcht1(EVEX_compress_addr(
+ aux_reg_ker_prf, kernel_offset(kk,
+ oc + prf_count_t1, ki)));
+ prf_count_t1++;
+ }
+ if ( ki == 1 && oc == 0 && kk == 0)
+ mic_prefetcht1(EVEX_compress_addr(
+ aux_reg_dst_prf, aux_dst_offset));
+ }
+ }
+ }
+
+ add(aux_reg_ker, shift_ker_ptr);
+ sub(aux_reg_dst, shift_dst_ptr);
+ add(aux_reg_ker_prf, shift_ker_ptr);
+ sub(aux_reg_dst_prf, shift_dst_ptr);
+
+ dec(reg_kj);
+ cmp(reg_kj, 0);
+ jg(kh_label, T_NEAR);
+
+ if (jcp.ndims == 5) {
+ sub(aux_reg_dst_d, typesize * (jcp.oh * ow) * ic_block);
+ add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * oc_block * ic_block);
+ sub(aux_reg_dst_d_prf, typesize * (jcp.oh * ow) * ic_block);
+ add(aux_reg_ker_d_prf, typesize * jcp.kw * jcp.kh *oc_block * ic_block);
+
+ dec(reg_ki);
+ cmp(reg_ki, 0);
+ jg(kd_label, T_NEAR);
+
+ pop(reg_src);
+ pop(reg_src_prf);
+ }
+}
+
+void jit_avx512_common_conv_bwd_data_kernel_f32::compute_loop_fma(
+ int ur_w, int l_overflow, int r_overflow)
+{
+ Label kh_label, kd_label;
+ int kw = jcp.kw;
+ int ow = jcp.ow;
+
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ int l_pad = jcp.l_pad;
+ int dilate_w = jcp.dilate_w + 1;
+ int stride_w = jcp.stride_w;
+ int stride_h = jcp.stride_h;
+
+ int ker_pipeline_depth = 4;
+ assert(ker_reg_base_idx + ker_pipeline_depth <= 32);
+ assert(oc_block >= ker_pipeline_depth);
+
+ int num_ker_loads = oc_block * kw;
+ int num_inp_prfs = ur_w * nstl::min(kw, stride_w)
+ + nstl::max(0, kw - stride_w);
+ int num_prfs = num_ker_loads + num_inp_prfs;
+ int num_fmas = num_ker_loads * ur_w / stride_w;
+ int prf_inst_spacing = nstl::max(1, num_fmas / num_prfs);
+ int prf_inst_trigger = (num_fmas % prf_inst_spacing) / 2;
+
+ if (one_of(jcp.ndims, 3, 4)) {
+ mov(aux_reg_dst, reg_dst);
+ mov(aux_reg_ker, reg_ker);
+
+ mov(aux_reg_dst_prf, reg_dst_prf);
+ mov(aux_reg_ker_prf, reg_ker_prf);
+ }
+
+ if (jcp.ndims == 5) {
+ push(reg_src_prf);
+ push(reg_src);
+
+ mov(reg_ki, ptr[param + GET_OFF(kd_padding)]);
+ mov(aux_reg_dst_d, reg_dst);
+ mov(aux_reg_ker_d, ptr[param + GET_OFF(filt)]);
+ mov(aux_reg_dst_d_prf, reg_dst_prf);
+ mov(aux_reg_ker_d_prf, reg_ker_prf);
+
+ L(kd_label);
+ mov(reg_kj, ptr[param + GET_OFF(kh_padding)]);
+ } else {
+ mov(reg_kj, reg_kh);
+ }
+
+ if (jcp.ndims == 5) {
+ mov(aux_reg_dst, aux_reg_dst_d);
+ mov(aux_reg_ker, aux_reg_ker_d);
+ mov(aux_reg_dst_prf, aux_reg_dst_d_prf);
+ mov(aux_reg_ker_prf, aux_reg_ker_d_prf);
+ }
+
+ L(kh_label); {
+ int step = 0;
+ int ker_prfs = 0;
+ for (int ki = 0; ki < kw; ki++) {
+ for (int oc = 0; oc < oc_block; oc++) {
+ if (step == 0) {
+ for (int i = 0; i < ker_pipeline_depth; i++) {
+ int aux_kernel_offset = typesize * ((oc + i) * oc_block
+ + ki * ic_block * oc_block);
+ vmovups(zmm_ker(i), EVEX_compress_addr(
+ aux_reg_ker, aux_kernel_offset));
+ }
+ } else if (step < num_ker_loads - ker_pipeline_depth + 1) {
+ int load_offset = ker_pipeline_depth - 1;
+ int ker_load_reg_idx
+ = (step + load_offset) % ker_pipeline_depth;
+ int aux_kernel_offset = typesize * ((oc + load_offset)
+ * oc_block + ki * ic_block * oc_block);
+ vmovups(zmm_ker(ker_load_reg_idx),
+ EVEX_compress_addr(aux_reg_ker, aux_kernel_offset));
+ }
+
+ bool ker_prf_inserted = false;
+ auto zmm_kernel = zmm_ker(step % ker_pipeline_depth);
+
+ int jj_start = get_iw_start(ki, l_overflow);
+ int jj_end = get_iw_end(ur_w, ki, r_overflow);
+ assert(stride_w != 1
+ || jj_start == nstl::max(0,
+ l_overflow - (kw - 1 - ki) * dilate_w));
+ assert(stride_w != 1
+ || jj_end == ur_w - nstl::max(0,
+ r_overflow - ki * dilate_w));
+
+ for (int jj = jj_start; jj < jj_end; jj += stride_w) {
+ assert((jj + l_pad - ki * dilate_w) % stride_w == 0);
+ int aux_dst_offset = typesize *
+ (((jj + l_pad - ki * dilate_w)
+ / stride_w) * jcp.oc_block + oc);
+ vfmadd231ps(zmm_out(jj, 0), zmm_kernel,
+ EVEX_compress_addr(aux_reg_dst, aux_dst_offset, true));
+
+ int fma_idx = (step * ur_w + jj) / stride_w;
+ int prf_slot_idx = fma_idx / prf_inst_spacing;
+ if (fma_idx % prf_inst_spacing == prf_inst_trigger) {
+ if (!ker_prf_inserted && ker_prfs < num_ker_loads) {
+ int ker_prf_offset = typesize
+ * ker_prfs * jcp.oc_block;
+ mic_prefetcht1(EVEX_compress_addr(
+ aux_reg_ker_prf, ker_prf_offset));
+ ker_prf_inserted = true;
+ ker_prfs++;
+ } else {
+ int inp_prf_idx = prf_slot_idx - ker_prfs;
+ if (inp_prf_idx < num_inp_prfs) {
+ int inp_prf_offset
+ = ic_block * typesize
+ * ((inp_prf_idx / kw) * kw
+ + (inp_prf_idx % kw));
+ mic_prefetcht0(EVEX_compress_addr(
+ aux_reg_dst_prf, inp_prf_offset));
+ }
+ }
+ }
+ }
+ step++;
+ }
+ }
+
+ add(aux_reg_ker, typesize * stride_h * kw * oc_block * ic_block);
+ sub(aux_reg_dst, typesize * (jcp.dilate_h + 1) * ow * oc_block);
+ add(aux_reg_ker_prf, typesize * stride_h * kw * oc_block * ic_block);
+ sub(aux_reg_dst_prf, typesize * (jcp.dilate_h + 1) * ow * oc_block);
+
+ dec(reg_kj);
+ cmp(reg_kj, 0);
+ jg(kh_label, T_NEAR);
+ }
+ if (jcp.ndims == 5) {
+ sub(aux_reg_dst_d,
+ typesize * (jcp.dilate_d + 1) * jcp.oh * ow * ic_block);
+ add(aux_reg_ker_d, typesize * jcp.stride_d * jcp.kw * jcp.kh
+ * oc_block * ic_block);
+ sub(aux_reg_dst_d_prf,
+ typesize * (jcp.dilate_d + 1) * jcp.oh * ow * ic_block);
+ add(aux_reg_ker_d_prf, typesize * jcp.stride_d * jcp.kw * jcp.kh
+ * oc_block * ic_block);
+
+ dec(reg_ki);
+ cmp(reg_ki, 0);
+ jg(kd_label, T_NEAR);
+ }
+
+ if (jcp.ndims == 5)
+ {
+ pop(reg_src);
+ pop(reg_src_prf);
+ }
+}
+
+void jit_avx512_common_conv_bwd_data_kernel_f32::compute_loop_fma_core(
+ int ur_w, int l_overflow, int r_overflow)
+{
+ int kw = jcp.kw;
+ int ow = jcp.ow;
+ int dilate_w = jcp.dilate_w + 1;
+ int stride_w = jcp.stride_w;
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ int nb_ic_block = jcp.nb_ic_blocking;
+ Label kh_label, kd_label;
+
+ int shift_ker_ptr = typesize * kw * oc_block * ic_block;
+ int shift_dst_ptr = typesize * (jcp.dilate_h + 1) * ow * oc_block;
+
+ auto output_offset = [=](int oi, int oc, int ki) {
+ return typesize *
+ (((oi + jcp.l_pad - ki * dilate_w) / stride_w) * oc_block + oc);
+ };
+ auto kernel_offset = [=](int icb, int oc, int ki) {
+ int blk_idx = icb * jcp.kh * jcp.kw * jcp.kd + ki;
+ int blk_offset = blk_idx * jcp.oc_block * jcp.ic_block;
+ int oc_offset = oc * jcp.oc_block;
+ return typesize * (blk_offset + oc_offset);
+ };
+
+ if (one_of(jcp.ndims, 3, 4)) {
+ mov(aux_reg_dst, reg_dst);
+ mov(aux_reg_ker, reg_ker);
+ }
+
+ if (jcp.ndims == 5) {
+ push(reg_src_prf);
+ push(reg_src);
+
+ mov(reg_ki, ptr[param + GET_OFF(kd_padding)]);
+ mov(aux_reg_dst_d, reg_dst);
+ mov(aux_reg_ker_d, ptr[param + GET_OFF(filt)]);
+
+ L(kd_label);
+ mov(reg_kj, ptr[param + GET_OFF(kh_padding)]);
+ } else {
+ mov(reg_kj, reg_kh);
+ }
+
+ if (jcp.ndims == 5) {
+ mov(aux_reg_dst, aux_reg_dst_d);
+ mov(aux_reg_ker, aux_reg_ker_d);
+ }
+
+ L(kh_label);
+ {
+ for (int ki = 0; ki < kw; ki++) {
+ int jj_start = get_iw_start(ki, l_overflow);
+ int jj_end = get_iw_end(ur_w, ki, r_overflow);
+ for (int oc = 0; oc < oc_block; oc++) {
+ if (jcp.kernel_kind == expl_bcast) {
+ for (int jj = jj_start; jj < jj_end; jj++) {
+ int aux_output_offset = output_offset(jj, oc, ki);
+ vbroadcastss(zmm_inp(jj, nb_ic_block),
+ ptr[aux_reg_dst + aux_output_offset]);
+ }
+ }
+ for (int ii = 0; ii < nb_ic_block; ii++) {
+ int aux_kernel_offset = kernel_offset(ii, oc, ki);
+ if (jj_end - jj_start > 0)
+ vmovups(zmm_wei, EVEX_compress_addr(aux_reg_ker,
+ aux_kernel_offset));
+ for (int jj = jj_start; jj < jj_end; jj += stride_w)
+ if (jcp.kernel_kind == expl_bcast)
+ vfmadd231ps(zmm_out(jj, ii),
+ zmm_inp(jj, nb_ic_block), zmm_wei);
+ else
+ vfmadd231ps(zmm_out(jj, ii), zmm_wei,
+ EVEX_compress_addr(aux_reg_dst,
+ output_offset(jj, oc, ki), true));
+ }
+ }
+ }
+ add(aux_reg_ker, shift_ker_ptr);
+ sub(aux_reg_dst, shift_dst_ptr);
+ dec(reg_kj);
+ cmp(reg_kj, 0);
+ jg(kh_label, T_NEAR);
+ }
+
+ if (jcp.ndims == 5) {
+ sub(aux_reg_dst_d,
+ typesize * (jcp.dilate_d + 1) * jcp.oh * ow * ic_block);
+ add(aux_reg_ker_d, typesize * jcp.kw * jcp.kh * oc_block * ic_block);
+
+ dec(reg_ki);
+ cmp(reg_ki, 0);
+ jg(kd_label, T_NEAR);
+
+ pop(reg_src);
+ pop(reg_src_prf);
+ }
+}
+
+inline void jit_avx512_common_conv_bwd_data_kernel_f32::compute_loop(
+ int ur_w, int l_overflow, int r_overflow)
+{
+ if (jcp.ndims == 5) push(reg_oi);
+
+ prepare_output(ur_w);
+
+ Label skip_compute_loop;
+ if (jcp.ndims == 5) {
+ mov(reg_kj, ptr[param + GET_OFF(kd_padding)]);
+ cmp(reg_kj, 0);
+ je(skip_compute_loop, T_NEAR);
+ }
+ mov(reg_kj, ptr[param + GET_OFF(kh_padding)]);
+ cmp(reg_kj, 0);
+ je(skip_compute_loop, T_NEAR);
+
+ if (jcp.ver == ver_4fma)
+ compute_loop_4fma(ur_w, l_overflow, r_overflow);
+ else if (jcp.ver == ver_fma)
+ if (mayiuse(avx512_mic))
+ compute_loop_fma(ur_w, l_overflow, r_overflow);
+ else
+ if (jcp.kernel_kind == embd_bcast && jcp.nb_ic_blocking == 1)
+ compute_loop_fma(ur_w, l_overflow, r_overflow);
+ else
+ compute_loop_fma_core(ur_w, l_overflow, r_overflow);
+ else
+ assert("!unknown convolution version");
+
+ L(skip_compute_loop);
+ store_output(ur_w);
+ if (jcp.ndims == 5) pop(reg_oi);
+}
+
+void jit_avx512_common_conv_bwd_data_kernel_f32::generate()
+{
+ int iw = jcp.iw;
+ int kw = jcp.kw;
+ int ur_w = jcp.ur_w;
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ int ur_w_tail = jcp.ur_w_tail;
+ int dilate_w = jcp.dilate_w + 1;
+ int stride_w = jcp.stride_w;
+
+ int dst_shift = jcp.typesize_in * (ur_w / stride_w) * ic_block;
+ int src_shift = jcp.typesize_out * ur_w * oc_block;
+
+ preamble();
+
+ mov(reg_src, ptr[param + GET_OFF(src)]);
+ mov(reg_dst, ptr[param + GET_OFF(dst)]);
+ mov(reg_ker, ptr[param + GET_OFF(filt)]);
+
+ mov(reg_kh, ptr[param + GET_OFF(kh_padding)]);
+ mov(reg_src_prf, ptr[param + GET_OFF(src_prf)]);
+ mov(reg_dst_prf, ptr[param + GET_OFF(dst_prf)]);
+ mov(reg_ker_prf, ptr[param + GET_OFF(filt_prf)]);
+
+ int l_overflow = nstl::max(0, ((kw - 1) * dilate_w - jcp.l_pad) / stride_w);
+ int r_overflow = nstl::max(0, ((kw - 1) * dilate_w
+ - nstl::max(0, jcp.r_pad)) / stride_w);
+ int r_overflow1 = nstl::max(0, ((kw - 1) * dilate_w
+ - nstl::max(0, jcp.r_pad) - ur_w_tail) / stride_w);
+
+ int n_oi = iw / ur_w;
+ if (r_overflow1 > 0) n_oi--;
+
+ if (ur_w == iw) {
+ compute_loop(ur_w, l_overflow, r_overflow);
+ } else if (n_oi == 0) {
+ compute_loop(ur_w, l_overflow, r_overflow1);
+ add(reg_src, src_shift);
+ add(reg_dst, dst_shift);
+ add(reg_src_prf, src_shift);
+ add(reg_dst_prf, dst_shift);
+ if (ur_w_tail != 0)
+ compute_loop(ur_w_tail, 0, r_overflow);
+ } else {
+ xor_(reg_oi, reg_oi);
+ if (l_overflow > 0) {
+ compute_loop(ur_w, l_overflow, 0);
+ add(reg_src, src_shift);
+ add(reg_dst, dst_shift);
+ add(reg_src_prf, src_shift);
+ add(reg_dst_prf, dst_shift);
+
+ inc(reg_oi);
+ }
+ if ((l_overflow <= 0 && n_oi > 0)
+ || (l_overflow > 0 && n_oi > 1)) {
+ Label ow_loop_label;
+ L(ow_loop_label); {
+ compute_loop(ur_w, 0, 0);
+ add(reg_src, src_shift);
+ add(reg_dst, dst_shift);
+ add(reg_src_prf, src_shift);
+ add(reg_dst_prf, dst_shift);
+
+ inc(reg_oi);
+ cmp(reg_oi, n_oi);
+ jl(ow_loop_label, T_NEAR);
+ }
+ }
+ if (r_overflow1 > 0) {
+ compute_loop(ur_w, 0, r_overflow1);
+ add(reg_src, src_shift);
+ add(reg_dst, dst_shift);
+ add(reg_src_prf, src_shift);
+ add(reg_dst_prf, dst_shift);
+ }
+ if (ur_w_tail != 0) {
+ compute_loop(ur_w_tail, 0, r_overflow);
+ }
+ }
+
+ postamble();
+}
+
+status_t jit_avx512_common_conv_bwd_data_kernel_f32::init_conf(
+ jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd,
+ const memory_desc_wrapper &diff_src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &diff_dst_d)
+{
+ if (!mayiuse(avx512_common)) return status::unimplemented;
+
+ jcp = zero<decltype(jcp)>();
+
+ jcp.simd_w = cpu_isa_traits<avx512_common>::vlen / sizeof(float);
+ const bool with_groups = weights_d.ndims() == diff_src_d.ndims() + 1;
+ int ndims = diff_src_d.ndims();
+
+ jcp.ndims = ndims;
+ jcp.prop_kind = cd.prop_kind;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = diff_src_d.dims()[0];
+
+ jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = diff_src_d.dims()[1] / jcp.ngroups;
+
+ jcp.id = (ndims == 5) ? diff_src_d.dims()[2] : 1;
+ jcp.ih = (ndims == 3) ? 1 : diff_src_d.dims()[ndims-2];
+ jcp.iw = diff_src_d.dims()[ndims-1];
+ jcp.od = (ndims == 5) ? diff_dst_d.dims()[2] : 1;
+ jcp.oh = (ndims == 3) ? 1 : diff_dst_d.dims()[ndims-2];
+ jcp.ow = diff_dst_d.dims()[ndims-1];
+
+ jcp.kd = (ndims == 5) ? weights_d.dims()[with_groups + 2] : 1;
+ jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + ndims - 2];
+ jcp.kw = weights_d.dims()[with_groups + ndims - 1];
+
+ jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0;
+ jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4];
+ jcp.l_pad = cd.padding[0][ndims-3];
+
+ jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1;
+ jcp.stride_h = (ndims == 3) ? 1 : cd.strides[ndims-4];
+ jcp.stride_w = cd.strides[ndims-3];
+
+ jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0;
+ jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4];
+ jcp.dilate_w = cd.dilates[ndims-3];
+ if ((jcp.dilate_w != 0 && jcp.stride_w != 1)
+ || (jcp.dilate_d != 0 && jcp.stride_d != 1)
+ || (jcp.dilate_h != 0 && jcp.stride_h != 1))
+ return status::unimplemented;
+
+ jcp.r_pad = (jcp.ow - 1) * jcp.stride_w + (jcp.kw - 1) * (jcp.dilate_w + 1)
+ - (jcp.iw + jcp.l_pad - 1);
+ jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1)
+ - (jcp.ih + jcp.t_pad - 1);
+ jcp.back_pad = (jcp.od - 1) * jcp.stride_d
+ + (jcp.kd - 1) * (jcp.dilate_d + 1) - (jcp.id + jcp.f_pad - 1);
+
+ jcp.aligned_threads = 0;
+
+ jcp.is_1stconv = false;
+
+ jcp.oc_block = jcp.simd_w;
+ jcp.ic_block = jcp.is_1stconv ? jcp.ic : jcp.simd_w;
+
+ bool ok_to_pad_channels = true
+ && jcp.ngroups == 1
+ && diff_src_d.data_type() == data_type::f32;
+
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, jcp.oc_block);
+ jcp.ic = rnd_up(jcp.ic, jcp.ic_block);
+ }
+
+ auto dat_tag = pick(ndims - 3, nCw16c, nChw16c, nCdhw16c);
+ auto wei_tag = with_groups
+ ? pick(ndims - 3, gOIw16o16i, gOIhw16o16i, gOIdhw16o16i)
+ : pick(ndims - 3, OIw16o16i, OIhw16o16i, OIdhw16o16i);
+ jcp.src_tag = diff_src_d.matches_one_of_tag(dat_tag);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(dat_tag);
+
+ bool args_ok = true
+ && jcp.oc % jcp.oc_block == 0
+ && jcp.ic % jcp.ic_block == 0
+ && jcp.src_tag == dat_tag
+ && jcp.dst_tag == dat_tag;
+ if (!args_ok)
+ return status::unimplemented;
+
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+
+ jcp.ur_w = jcp.stride_w;
+
+ int regs = 28;
+ if (jcp.iw <= regs)
+ jcp.ur_w = jcp.iw;
+ else {
+ for (int ur_w = regs; ur_w > 0; --ur_w)
+ if (ur_w % jcp.stride_w == 0) {
+ jcp.ur_w = ur_w;
+ break;
+ }
+ }
+ int l_overflow = nstl::max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1)
+ - jcp.l_pad) / jcp.stride_w);
+ int r_overflow1 = nstl::max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1)
+ - nstl::max(0, jcp.r_pad) - jcp.iw % jcp.ur_w) / jcp.stride_w);
+ int n_oi = jcp.iw / jcp.ur_w;
+ if (r_overflow1 > 0) n_oi--;
+
+ if (mayiuse(avx512_common)
+ && diff_dst_d.data_type() == data_type::f32
+ && weights_d.data_type() == data_type::f32
+ && diff_src_d.data_type() == data_type::f32) {
+ jcp.ver = ver_fma;
+ jcp.typesize_in = sizeof(float);
+ jcp.typesize_out = sizeof(float);
+ if (mayiuse(avx512_mic_4ops)
+ && jcp.stride_w == 1 && jcp.stride_h == 1 && jcp.stride_d == 1) {
+ jcp.ver = ver_4fma;
+ }
+ } else {
+ return status::unimplemented;
+ }
+
+ jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag);
+ if (jcp.wei_tag != wei_tag)
+ return status::unimplemented;
+
+ if (!utils::everyone_is(0, jcp.dilate_d, jcp.dilate_h, jcp.dilate_w)
+ && jcp.ver != ver_fma)
+ return status::unimplemented;
+
+ jcp.nb_ic_blocking = jcp.nb_oc_blocking = 1;
+ if (jcp.ver == ver_4fma) {
+ if (jcp.kw == 3 && jcp.kh == 3 && jcp.iw == 7 && jcp.ih == 7) {
+ jcp.nb_ic_blocking = 2;
+ } else {
+ for (int i = jcp.nb_ic; i > 0; i--)
+ if (i * jcp.ur_w <= regs && jcp.nb_ic % i == 0) {
+ jcp.nb_ic_blocking = i;
+ break;
+ }
+ }
+ }
+
+ jcp.loop_order = loop_gnc;
+
+ bool large_code_size = (jcp.ur_w != jcp.ow)
+ && ((l_overflow <= 0 && n_oi > 0) ||(l_overflow > 0 && n_oi > 1))
+ && (r_overflow1 > 0) && (l_overflow > 0);
+ if (large_code_size) {
+ const int max_code_size = 24 * 1024;
+ const int num_ops_per_reg = 6 + jcp.oc_block * jcp.kw;
+ int mult = 1;
+ if (l_overflow > 0) mult += 1;
+ if (r_overflow1 > 0) mult += 1;
+ for (int ur_w = jcp.ur_w; ur_w > regs/2; --ur_w) {
+ if ((ur_w / jcp.stride_w) * mult * num_ops_per_reg * 9.2
+ < max_code_size) {
+ if (ur_w % jcp.stride_w == 0) {
+ jcp.ur_w = ur_w;
+ break;
+ }
+ }
+ }
+ }
+
+ if (jcp.ver == ver_fma && mayiuse(avx512_core)) {
+ int try_nb_ic_blocking = 2;
+ unsigned int ker_inp_size = typesize * jcp.iw * jcp.ic_block
+ * try_nb_ic_blocking * jcp.kh;
+ unsigned int ker_out_size = typesize * jcp.ow * jcp.oc_block;
+ unsigned int ker_wei_size = typesize * jcp.kh * jcp.kw * jcp.ic_block
+ * jcp.oc_block * try_nb_ic_blocking;
+ unsigned int ker_total_size = ker_inp_size + ker_out_size
+ + ker_wei_size;
+ if (!(jcp.kw == 1 || (jcp.kw == 5 && jcp.iw < 8)
+ || (jcp.kw < 5 && ((jcp.iw <= 5 || (jcp.iw > 8 && jcp.iw <= 13))
+ || ker_total_size > L1_cache_size )))
+ || jcp.stride_h > 1 || jcp.stride_d > 1) {
+ jcp.kernel_kind = embd_bcast;
+ jcp.ur_w = nstl::min(jcp.iw, regs);
+ jcp.nb_ic_blocking = jcp.nb_oc_blocking = 1;
+ if (!(jcp.kw > 3 || (jcp.kw == 3 && ker_total_size < L1_cache_size
+ && jcp.ow > 8)) && jcp.stride_h == 1)
+ if (jcp.nb_ic % try_nb_ic_blocking == 0) {
+ jcp.nb_ic_blocking = try_nb_ic_blocking;
+ jcp.ur_w = 31 / (jcp.nb_ic_blocking + 1);
+ if (jcp.iw < jcp.ur_w) jcp.ur_w = jcp.iw;
+ }
+ } else {
+ jcp.kernel_kind = expl_bcast;
+ jcp.nb_oc_blocking = 1;
+ jcp.nb_ic_blocking = 4;
+ if (jcp.nb_ic < jcp.nb_ic_blocking) jcp.nb_ic_blocking = jcp.nb_ic;
+ if (jcp.nb_ic % jcp.nb_ic_blocking != 0)
+ for (int i = jcp.nb_ic_blocking; i > 0; i--)
+ if (jcp.nb_ic % i == 0) {
+ jcp.nb_ic_blocking = i;
+ break;
+ }
+ jcp.ur_w = 31 / (jcp.nb_ic_blocking + 1);
+ if (jcp.iw < jcp.ur_w) jcp.ur_w = jcp.iw;
+ }
+ }
+ jcp.ur_w_tail = jcp.iw % jcp.ur_w;
+
+ if (l_overflow * jcp.stride_w > jcp.ur_w)
+ return status::unimplemented;
+ int r_overflow_no_tail = nstl::max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1)
+ - nstl::max(0, jcp.r_pad) - jcp.ur_w_tail) / jcp.stride_w);
+ if (r_overflow_no_tail * jcp.stride_w > jcp.ur_w)
+ return status::unimplemented;
+ if ((jcp.iw > jcp.ur_w) && (jcp.ur_w % jcp.stride_w != 0))
+ return status::unimplemented;
+
+ pick_loop_order(jcp);
+
+ jcp.nb_oc_L2 = jcp.nb_oc;
+ if (jcp.ver == ver_4fma && (jcp.kh < 5 && jcp.kw < 5)) {
+ for (int divf = 2, temp_nb = jcp.nb_oc_L2; divf <= jcp.nb_oc;
+ divf++) {
+ size_t l2_src = jcp.iw * jcp.ic_block * jcp.nb_ic_blocking * jcp.ih
+ * jcp.id;
+ size_t l2_dst = jcp.ow * jcp.oc_block * temp_nb * jcp.oh * jcp.od;
+ size_t l2_filt = jcp.kw * jcp.oc_block * jcp.ic_block * jcp.kh
+ * jcp.kd * jcp.nb_ic_blocking * temp_nb;
+ if (4 * (l2_src + l2_dst + l2_filt) > KNx_L2_EFFECTIVE_CAPACITY) {
+ if (jcp.kh == 3 && jcp.ih == 7) {
+ jcp.nb_oc_L2 = 1;
+ break;
+ }
+ temp_nb = (jcp.nb_oc_L2 % divf == 0 ? jcp.nb_oc_L2 / divf
+ : jcp.nb_oc_L2);
+ } else {
+ jcp.nb_oc_L2 = temp_nb;
+ break;
+ }
+ }
+ }
+
+ args_ok = true
+ && jcp.ic <= diff_src_d.padded_dims()[1]
+ && jcp.oc <= diff_dst_d.padded_dims()[1]
+ && jcp.ic <= weights_d.padded_dims()[with_groups + 1]
+ && jcp.oc <= weights_d.padded_dims()[with_groups + 0];
+ if (!args_ok) return status::unimplemented;
+
+ return status::success;
+}
+
+void jit_avx512_common_conv_bwd_data_kernel_f32::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) {
+ UNUSED(scratchpad);
+ UNUSED(jcp);
+}
+
+const int jit_avx512_common_conv_bwd_weights_kernel_f32::max_ur_w = 28;
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::od_step_comeback_pointers()
+{
+ Label kd_comeback_label;
+
+ /* 'depth' loop count bound by 'kd_work_size' */
+ mov(kj, reg_kd_count);
+ L(kd_comeback_label); {
+ int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block;
+ int iw = jcp.ver == ver_4fma ? jcp.tr_iw : jcp.iw;
+ sub(reg_input,
+ jcp.typesize_in * (jcp.dilate_d + 1) * jcp.ih * iw * inp_mult);
+ sub(reg_kernel,
+ jcp.typesize_out * jcp.kh * jcp.kw * jcp.ic_block * jcp.oc_block);
+ dec(kj);
+ cmp(kj, 0);
+ jg(kd_comeback_label, T_NEAR);
+ }
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::oh_step_comeback_pointers()
+{
+ Label kh_comeback_label, kd_comeback_label;
+ mov(kj, reg_kh);
+ L(kh_comeback_label); {
+ int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block;
+ int iw = jcp.ver == ver_4fma ? jcp.tr_iw : jcp.iw;
+ sub(reg_input, jcp.typesize_in * (jcp.dilate_h + 1) * iw * inp_mult);
+ sub(reg_kernel,
+ jcp.typesize_out * jcp.kw * jcp.ic_block * jcp.oc_block);
+ dec(kj);
+ cmp(kj, 0);
+ jg(kh_comeback_label, T_NEAR);
+ }
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::compute_ic_block_step_fma(
+ int ur_w, int pad_l, int pad_r,
+ int ic_block_step, int input_offset, int kernel_offset,
+ int output_offset, bool input_wraparound)
+{
+
+ int kw = jcp.kw;
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ for (int i_kw = 0; i_kw < kw; i_kw++)
+ for (int i_ic = 0; i_ic < ic_block_step; i_ic++)
+ vmovups(Zmm(i_kw * ic_block_step + i_ic),
+ EVEX_compress_addr(reg_kernel, typesize * (i_kw * ic_block
+ + i_ic) * jcp.oc_block + kernel_offset));
+
+ for (int i_ur = 0; i_ur < ur_w; i_ur++) {
+ if (i_ur == 0) {
+ vmovups(Zmm(kw * ic_block_step + (i_ur + 0) % 4),
+ EVEX_compress_addr(reg_output, typesize * (i_ur + 0)
+ * oc_block + output_offset));
+ if (ur_w > 1) vmovups(Zmm(kw * ic_block_step + (i_ur + 1) % 4),
+ EVEX_compress_addr(reg_output, typesize * (i_ur + 1) * oc_block
+ + output_offset));
+ if (ur_w > 2) vmovups(Zmm(kw * ic_block_step + (i_ur + 2) % 4),
+ EVEX_compress_addr(reg_output, typesize * (i_ur + 2) * oc_block
+ + output_offset));
+ if (ur_w > 3) vmovups(Zmm(kw * ic_block_step + (i_ur + 3) % 4),
+ EVEX_compress_addr(reg_output, typesize * (i_ur + 3) * oc_block
+ + output_offset));
+ } else if (i_ur + 3 < ur_w)
+ vmovups(Zmm(kw * ic_block_step + (i_ur + 3) % 4),
+ EVEX_compress_addr(reg_output, typesize * (i_ur + 3) * oc_block
+ + output_offset));
+
+ for (int i_kw = 0; i_kw < kw; i_kw++) {
+ int i_iw = i_ur * jcp.stride_w + i_kw * (jcp.dilate_w + 1);
+ if (i_iw - pad_l < 0 || i_iw > (ur_w - 1) * jcp.stride_w +
+ (kw - 1) * (jcp.dilate_w + 1) - pad_r) continue;
+ for (int i_ic = 0; i_ic < ic_block_step; i_ic++) {
+ const size_t i_offset = (size_t)input_offset
+ + (size_t)typesize * (jcp.ver == ver_4fma
+ ? (i_iw - pad_l + i_ic * jcp.tr_iw)
+ : (jcp.is_1stconv
+ ? (i_iw - pad_l) + (size_t)i_ic
+ * ((size_t)jcp.ih*jcp.iw*jcp.id)
+ : (i_iw - pad_l) * ic_block + i_ic));
+ vfmadd231ps(Zmm(i_kw * ic_block_step + i_ic),
+ Zmm(kw * ic_block_step + i_ur % 4),
+ EVEX_compress_addr_safe(reg_input, i_offset, reg_long_offt,
+ true));
+ }
+ }
+ }
+
+ for (int i_kw = 0; i_kw < kw; i_kw++)
+ for (int i_ic = 0; i_ic < ic_block_step; i_ic++)
+ vmovups(EVEX_compress_addr(reg_kernel, typesize
+ * (i_kw * ic_block + i_ic) * jcp.oc_block + kernel_offset),
+ Zmm(i_kw * ic_block_step + i_ic));
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::compute_ic_block_step_4fma(
+ int ur_w, int pad_l, int pad_r,
+ int ic_block_step, int input_offset, int kernel_offset,
+ int output_offset, bool input_wraparound)
+{
+ // TODO: add prefetches to fma version as well
+
+ assert(jcp.ver == ver_4fma);
+
+ int kw = jcp.kw;
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+
+ auto zmm_ker = [=](int i_kw, int i_ic) {
+ return Zmm(i_kw * ic_block_step + i_ic);
+ };
+
+ auto ker_addr = [=](int i_kw, int i_ic) {
+ size_t local_offset
+ = jcp.typesize_out * (i_kw * ic_block + i_ic) * jcp.oc_block;
+ return EVEX_compress_addr(reg_kernel, local_offset + kernel_offset);
+ };
+
+ auto inp_addr = [=](int i_iw, int i_ic, ptrdiff_t extra_offset = 0) {
+ int stride = jcp.tr_iw * (jcp.is_1stconv ? jcp.ih : 1);
+ int local_offset = jcp.typesize_in * (i_iw + i_ic * stride);
+ return EVEX_compress_addr(reg_input,
+ local_offset + input_offset + extra_offset);
+ };
+
+ auto zmm_out = [=](int i_iw) {
+ // TODO: move reg calc to global member funcs
+ const int out_zmm_base_idx = 28;
+ return Zmm(out_zmm_base_idx + i_iw % 4);
+ };
+
+ auto out_addr = [=](int i_ur) {
+ return EVEX_compress_addr(reg_output,
+ jcp.typesize_in * i_ur * oc_block + output_offset);
+ };
+
+ auto pf_callback = [=](int i_ur, int i_kw, int i_ic) {
+ assert(i_ur % 4 == 0);
+ if (i_ur == 0)
+ prefetcht1(ker_addr(i_kw, i_ic));
+ if (i_ur + 4 >= ur_w)
+ prefetcht0(ker_addr(i_kw, i_ic));
+
+ const ptrdiff_t next_input_block_offset
+ = jcp.typesize_in * ic_block_step * jcp.tr_iw;
+ if (i_ur % 16 == 4 && i_kw == 0) {
+ if (i_ur + 16 < ur_w)
+ prefetcht0(inp_addr(i_ur + 16, i_ic));
+ else
+ prefetcht0(inp_addr(0, i_ic, next_input_block_offset));
+ }
+ if (i_ur % 16 == 4 && i_kw == 1) {
+ if (input_wraparound)
+ prefetcht1(inp_addr(i_ur, i_ic, -input_offset));
+ else
+ prefetcht1(inp_addr(i_ur, i_ic, next_input_block_offset));
+ }
+ };
+
+ for (int i_kw = 0; i_kw < kw; i_kw++)
+ for (int i_ic = 0; i_ic < ic_block_step; i_ic++) {
+ auto zmm = zmm_ker(i_kw, i_ic);
+ vpxord(zmm, zmm, zmm);
+ }
+
+ for (int i_ur = 0; i_ur < ur_w; i_ur += 4) {
+
+ for (int i = 0; i < 4; i++) {
+ auto zmm = zmm_out(i_ur + i);
+ if (i_ur + i < ur_w)
+ vmovups(zmm, out_addr(i_ur + i));
+ else
+ vpxord(zmm, zmm, zmm);
+ prefetcht0(out_addr(i_ur + i + 4));
+ }
+
+ for (int i_kw = 0; i_kw < kw; i_kw++)
+ for (int i_ic = 0; i_ic < ic_block_step; i_ic++) {
+ int i_iw = i_ur + i_kw;
+ v4fmaddps(zmm_ker(i_kw, i_ic),
+ zmm_out(i_ur), inp_addr(i_iw, i_ic));
+ pf_callback(i_ur, i_kw, i_ic);
+ }
+ }
+
+ for (int i_kw = 0; i_kw < kw; i_kw++)
+ for (int i_ic = 0; i_ic < ic_block_step; i_ic++) {
+ auto addr = ker_addr(i_kw, i_ic);
+ auto zmm = zmm_ker(i_kw, i_ic);
+ vaddps(zmm, zmm, addr);
+ vmovups(addr, zmm);
+ }
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::compute_ic_block_step(
+ int ur_w, int pad_l, int pad_r,
+ int ic_block_step, int input_offset, int kernel_offset,
+ int output_offset, bool input_wraparound)
+{
+ if (jcp.ver == ver_4fma)
+ compute_ic_block_step_4fma(ur_w, pad_l, pad_r,
+ ic_block_step, input_offset, kernel_offset, output_offset,
+ input_wraparound);
+ else if (jcp.ver == ver_fma)
+ compute_ic_block_step_fma(ur_w, pad_l, pad_r,
+ ic_block_step, input_offset, kernel_offset, output_offset,
+ input_wraparound);
+ else
+ assert(!"unknown convolution version");
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32
+ ::compute_oh_step_unroll_ow_icblock(
+ int ic_block_step, int max_ur_w)
+{
+ UNUSED(max_ur_w);
+
+ Label kh_label, kd_label;
+
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ int inp_mul = !jcp.is_1stconv ? ic_block : 1;
+ int iw = jcp.ver == ver_4fma ? jcp.tr_iw : jcp.iw;
+ int ow = jcp.ow;
+
+ int r_pad = nstl::max(0, (ow - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1));
+ int l_pad = jcp.l_pad;
+
+ if (jcp.ndims == 5) {
+ L(kd_label);
+ mov(reg_input, aux_reg_input);
+ mov(reg_kernel, aux_reg_kernel);
+ }
+
+ mov(kj, reg_kh);
+ L(kh_label);
+ {
+ for (int i_b_ic = 0; i_b_ic < jcp.ic_block; i_b_ic += ic_block_step) {
+ const int input_offset = jcp.typesize_in
+ * (jcp.ver == ver_4fma ? i_b_ic * iw : i_b_ic);
+ compute_ic_block_step(jcp.ur_w, l_pad, r_pad, ic_block_step,
+ input_offset, jcp.typesize_out * i_b_ic * jcp.oc_block, 0,
+ i_b_ic + ic_block_step >= jcp.ic_block);
+ }
+ add(reg_input, jcp.typesize_in * (jcp.dilate_h + 1) * iw * inp_mul);
+ add(reg_kernel, jcp.typesize_out * jcp.kw * ic_block * oc_block);
+ dec(kj);
+ cmp(kj, 0);
+ jg(kh_label, T_NEAR);
+ }
+
+ if (jcp.ndims == 5) {
+ add(aux_reg_input,
+ jcp.typesize_in * (jcp.dilate_d + 1) * jcp.ih * iw * inp_mul);
+ add(aux_reg_kernel, jcp.typesize_out * jcp.kh * jcp.kw * ic_block
+ * oc_block);
+ dec(ki);
+ cmp(ki, 0);
+ jg(kd_label, T_NEAR);
+ }
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32
+ ::compute_oh_step_unroll_ow(
+ int ic_block_step, int max_ur_w)
+{
+ Label kh_label, ic_block_label, kd_label;
+
+ UNUSED(max_ur_w);
+
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+
+ int ow = jcp.ow;
+
+ int r_pad = nstl::max(0,
+ (ow - 1) * jcp.stride_w + (jcp.kw - 1) * (jcp.dilate_w + 1)
+ - (jcp.iw + jcp.l_pad - 1));
+ int l_pad = jcp.l_pad;
+
+ if (jcp.ndims == 5) {
+ L(kd_label);
+ mov(reg_input, aux_reg_input);
+ mov(reg_kernel, aux_reg_kernel);
+ }
+
+ mov(kj, reg_kh);
+ L(kh_label);
+ {
+ xor_(b_ic, b_ic);
+ L(ic_block_label); {
+ compute_ic_block_step(ow, l_pad, r_pad, ic_block_step,
+ 0, 0, 0);
+ size_t inp_icblk_stride = jcp.is_1stconv
+ ? (size_t)jcp.ih * jcp.iw * jcp.id
+ : (jcp.ver == ver_4fma ? jcp.tr_iw : 1);
+ size_t input_offset
+ = inp_icblk_stride * jcp.typesize_in * ic_block_step;
+ safe_add(reg_input, input_offset, reg_long_offt);
+ add(reg_kernel, jcp.typesize_out * ic_block_step * oc_block);
+ add(b_ic, ic_block_step);
+ cmp(b_ic, jcp.ic_block);
+ jl(ic_block_label, T_NEAR);
+ }
+
+ if (jcp.is_1stconv) {
+ size_t input_offset
+ = (size_t)jcp.typesize_in * jcp.id * jcp.ih * jcp.iw * ic_block;
+ safe_sub(reg_input, input_offset, reg_long_offt);
+ add(reg_input, jcp.typesize_in * (jcp.dilate_h + 1) * jcp.iw);
+ } else if (jcp.ver != ver_4fma) {
+ add(reg_input, jcp.typesize_in
+ * ((jcp.dilate_h + 1) * jcp.iw - 1) * ic_block);
+ }
+ add(reg_kernel, jcp.typesize_out * (jcp.kw - 1) * ic_block * oc_block);
+ dec(kj);
+ cmp(kj, 0);
+ jg(kh_label, T_NEAR);
+ }
+ if (jcp.ndims == 5) {
+ add(aux_reg_input, jcp.typesize_in * (jcp.dilate_d + 1) * jcp.ih
+ * jcp.iw * (jcp.is_1stconv ? 1 : ic_block));
+ add(aux_reg_kernel, jcp.typesize_out * jcp.kh * jcp.kw * ic_block
+ * oc_block);
+ dec(ki);
+ cmp(ki, 0);
+ jg(kd_label, T_NEAR);
+ }
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32
+ ::compute_oh_step_common(
+ int ic_block_step, int max_ur_w)
+{
+ Label kh_label, ic_block_label, ow_block_label, kd_label;
+
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+
+ int ow = jcp.ow;
+ int r_pad = nstl::max(0, (ow - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1));
+ int l_pad = jcp.ver == ver_4fma ? 0 : jcp.l_pad;
+
+ int ur_w = nstl::min(ow, max_ur_w);
+ int ur_w_trips = ow / ur_w;
+ int ur_w_tail = ow % ur_w;
+ if ((ur_w_tail == 0 && r_pad != 0)
+ || r_pad >= ur_w_tail) {
+ if (ur_w_trips > 1) {
+ ur_w_tail += ur_w;
+ ur_w_trips--;
+ } else {
+ ur_w_tail += (ur_w - ur_w / 2);
+ ur_w = ur_w / 2;
+ }
+ }
+
+ int inp_mult = (jcp.is_1stconv || jcp.ver == ver_4fma) ? 1 : ic_block;
+ int input_comeback = (ur_w_trips * ur_w * jcp.stride_w - l_pad) * inp_mult;
+ int output_comeback = ur_w_trips * ur_w * oc_block;
+
+ if (jcp.ndims == 5) {
+ L(kd_label);
+ mov(reg_input, aux_reg_input);
+ mov(reg_kernel, aux_reg_kernel);
+ }
+
+ mov(kj, reg_kh);
+ L(kh_label); {
+ xor_(b_ic, b_ic);
+ L(ic_block_label); {
+ if (l_pad != 0) {
+ ur_w_trips--;
+ compute_ic_block_step(ur_w, l_pad, 0, ic_block_step, 0, 0, 0);
+ add(reg_input, jcp.typesize_in * (ur_w * jcp.stride_w - l_pad)
+ * inp_mult);
+ add(reg_output, jcp.typesize_in * ur_w * oc_block);
+ }
+
+ if (ur_w_trips > 0) {
+ xor_(reg_ur_w_trips, reg_ur_w_trips);
+ L(ow_block_label); {
+ compute_ic_block_step(ur_w, 0, 0, ic_block_step, 0, 0, 0);
+ add(reg_input, jcp.typesize_in * ur_w * jcp.stride_w
+ * inp_mult);
+ add(reg_output, jcp.typesize_in * ur_w * oc_block);
+
+ inc(reg_ur_w_trips);
+ cmp(reg_ur_w_trips, ur_w_trips);
+ jl(ow_block_label, T_NEAR);
+ }
+ }
+
+ if (ur_w_tail > 0) compute_ic_block_step(ur_w_tail, 0, r_pad,
+ ic_block_step, 0, 0, 0);
+
+ sub(reg_input, jcp.typesize_in * input_comeback);
+ sub(reg_output, jcp.typesize_in * output_comeback);
+ int inp_icblk_stride = jcp.is_1stconv
+ ? jcp.ih * jcp.iw * jcp.id
+ : (jcp.ver == ver_4fma ? jcp.tr_iw : 1);
+ size_t input_offset
+ = inp_icblk_stride * jcp.typesize_in * ic_block_step;
+ safe_add(reg_input, input_offset, reg_long_offt);
+ add(reg_kernel, jcp.typesize_out * ic_block_step * oc_block);
+
+ add(b_ic, ic_block_step);
+ cmp(b_ic, jcp.ic_block);
+ jl(ic_block_label, T_NEAR);
+ }
+ if (jcp.is_1stconv) {
+ size_t input_offset
+ = (size_t)jcp.typesize_in * jcp.id * jcp.ih * jcp.iw * ic_block;
+ safe_sub(reg_input, input_offset, reg_long_offt);
+ add(reg_input, jcp.typesize_in * (jcp.dilate_h + 1) * jcp.iw);
+ } else if (jcp.ver != ver_4fma) {
+ add(reg_input, jcp.typesize_in
+ * ((jcp.dilate_h + 1 ) * jcp.iw - 1) * ic_block);
+ }
+ add(reg_kernel, jcp.typesize_out * (jcp.kw - 1) * ic_block * oc_block);
+ dec(kj);
+ cmp(kj, 0);
+ jg(kh_label, T_NEAR);
+ }
+ if (jcp.ndims == 5) {
+ add(aux_reg_input, jcp.typesize_in * (jcp.dilate_d + 1) * jcp.ih
+ * jcp.iw * (jcp.is_1stconv ? 1 : ic_block));
+ add(aux_reg_kernel, jcp.typesize_out * jcp.kh * jcp.kw * ic_block
+ * oc_block);
+ dec(ki);
+ cmp(ki, 0);
+ jg(kd_label, T_NEAR);
+ }
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32
+ ::compute_oh_step_disp()
+{
+ int ic_block_step = jcp.kw <= 3 ? 8 : (jcp.kw <= 7 ? 4 : 2);
+ if (jcp.is_1stconv) {
+ bool large_code = jcp.kw >= 7 && (jcp.l_pad > 0 || jcp.t_pad > 0);
+ ic_block_step
+ = (jcp.kw * jcp.ic_block <= 28 && !large_code) ? jcp.ic_block : 1;
+ }
+
+ bool too_large_to_unroll
+ = (jcp.kw > 1 || jcp.kh > 1 || jcp.kd > 1)
+ && (jcp.stride_w > 1 || jcp.stride_h > 1 || jcp.stride_d > 1);
+
+ int ow = jcp.ow;
+ if (jcp.ndims == 5) {
+ /* NOTE: reg_kd_count = aux_reg_input = r12. The following order of
+ * 'movs' must be guaranteed. */
+ mov(ki, reg_kd_count);
+ push(reg_kd_count);
+ mov(aux_reg_input, reg_input);
+ mov(aux_reg_kernel, reg_kernel);
+ }
+
+ if (jcp.kw <= 3 && ow <= 16 && !too_large_to_unroll)
+ compute_oh_step_unroll_ow_icblock(ic_block_step, max_ur_w);
+ else if (ow <= max_ur_w)
+ compute_oh_step_unroll_ow(ic_block_step, max_ur_w);
+ else
+ compute_oh_step_common(ic_block_step, max_ur_w);
+
+ if (jcp.ndims == 5) {
+ mov(reg_input, aux_reg_input);
+ mov(reg_kernel, aux_reg_kernel);
+ pop(reg_kd_count);
+ od_step_comeback_pointers();
+ } else {
+ oh_step_comeback_pointers();
+ }
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::maybe_zero_kernel()
+{
+ Label skip_zeroing, zeroing_loop;
+
+ mov(reg_tmp, ptr[param + GET_OFF(channel)]);
+ cmp(reg_tmp, 0);
+ jz(skip_zeroing, T_NEAR);
+
+ Zmm zero = Zmm(0);
+ vpxord(zero, zero, zero);
+ xor_(reg_tmp, reg_tmp);
+ L(zeroing_loop); {
+ assert(jcp.oc_block * jcp.typesize_out
+ == cpu_isa_traits<avx512_common>::vlen);
+ for (int ic1 = 0; ic1 < jcp.ic_block; ic1++)
+ vmovups(ptr[reg_kernel + reg_tmp + ic1 * jcp.oc_block
+ * jcp.typesize_out], zero);
+ add(reg_tmp, jcp.ic_block * jcp.oc_block * jcp.typesize_out);
+ cmp(reg_tmp, jcp.ic_block * jcp.oc_block * jcp.kw * jcp.kh * jcp.kd
+ * jcp.typesize_out);
+ jnz(zeroing_loop);
+ }
+
+ L(skip_zeroing);
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::bias_kernel()
+{
+ Label skip_bias, bias_loop, skip_load_bias;
+
+ mov(reg_tmp, ptr[param + GET_OFF(flags)]);
+ test(reg_tmp,reg_tmp);
+ jne(skip_bias, T_NEAR);
+
+ mov(reg_bias, ptr[param + GET_OFF(bias)]);
+ mov(reg_output, ptr[param + GET_OFF(dst)]);
+ vpxord(Zmm(1), Zmm(1), Zmm(1));
+
+ mov(reg_tmp, ptr[param + GET_OFF(channel)]);
+ cmp(reg_tmp, 0);
+ jne(skip_load_bias, T_NEAR);
+ vmovups(Zmm(1), ptr[reg_bias]);
+
+ L(skip_load_bias);
+
+ mov(reg_oi, ptr[param + GET_OFF(d_worksize)]);
+ sub(reg_oi, ptr[param + GET_OFF(d_index)]);
+ mov(reg_tmp, jcp.oc_block * jcp.ow * jcp.oh * jcp.typesize_out);
+ imul(reg_oi, reg_tmp);
+
+ xor_(reg_tmp, reg_tmp);
+ L(bias_loop); {
+ vmovups(Zmm(0), ptr[reg_output + reg_tmp]);
+ vaddps(Zmm(1), Zmm(1), Zmm(0));
+ add(reg_tmp, jcp.oc_block * jcp.typesize_out);
+ cmp(reg_tmp, reg_oi);
+ jl(bias_loop);
+ }
+ vmovups(EVEX_compress_addr(reg_bias,0), Zmm(1));
+
+ L(skip_bias);
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32
+ ::compute_oh_loop_common()
+{
+ int b_pad = jcp.b_pad;
+ int t_pad = jcp.t_pad;
+ bool is_dilated = jcp.dilate_h != 0;
+ int dilate_h = jcp.dilate_h + 1;
+ int stride_h = jcp.stride_h;
+ const int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block;
+ int iw = jcp.ver == ver_4fma ? jcp.tr_iw : jcp.iw;
+ Label oh_label, oh_label_end, oh_tpad_label, oh_tpad_tail_label,
+ oh_bpad_label, oh_bpad_label_end, od_label, od_label_end,
+ oh_dilate_label_shift, oh_dilate_label_noshift, oh_dilate_label_end;
+
+ int ow = jcp.ow;
+
+ mov(reg_kh, jcp.kh);
+ xor_(reg_ih_count, reg_ih_count);
+ xor_(reg_oj, reg_oj);
+ /* Compute 'top' edge */
+ if (t_pad > 0) {
+ const int kh_range = 1 + (jcp.kh - 1) * dilate_h;
+ const int overflow
+ = nstl::max(0, jcp.kh - div_up(t_pad + jcp.ih, dilate_h));
+ const int underflow = div_up(t_pad, dilate_h);
+ const int initial_inp_ker_overlap = jcp.kh - overflow - underflow;
+ mov(reg_kh, initial_inp_ker_overlap);
+ add(reg_kernel, jcp.typesize_out * underflow * jcp.kw * jcp.ic_block
+ * jcp.oc_block);
+ // generate loop to process kernel while it remains within t_pad + ih
+ if (kh_range < t_pad + jcp.ih) {
+ if (is_dilated) {
+ const int tail = t_pad % dilate_h;
+ const int shift = tail == 0 ? 0 : dilate_h - tail;
+ mov(reg_tmp, shift);
+ if (tail != 0)
+ add(reg_input, jcp.typesize_in * shift * iw * inp_mult);
+ }
+ L(oh_tpad_label); {
+ compute_oh_step_disp();
+ add(reg_output, jcp.typesize_in * ow * jcp.oc_block);
+ if (is_dilated) {
+ inc(reg_tmp);
+ cmp(reg_tmp, dilate_h);
+ jl(oh_dilate_label_shift, T_NEAR);
+ // unshift input as new kernel element enters
+ sub(reg_input, jcp.typesize_in * (dilate_h - 1) * iw * inp_mult);
+ xor_(reg_tmp, reg_tmp);
+ }
+ // kernel overlap only changes when (t_pad + oj) % dilate_h == 0
+ sub(reg_kernel, jcp.typesize_out * stride_h * jcp.kw
+ * jcp.ic_block * jcp.oc_block);
+ add(reg_kh, stride_h);
+ if (is_dilated) {
+ jmp(oh_dilate_label_noshift, T_NEAR);
+ L(oh_dilate_label_shift);
+ // shift input as old kernel element progresses
+ add(reg_input, jcp.typesize_in * stride_h * iw * inp_mult);
+ L(oh_dilate_label_noshift);
+ }
+ inc(reg_oj);
+ add(reg_ih_count, stride_h);
+
+ // final number of kernel elements that overlap with input
+ const int final_inp_ker_overlap
+ = nstl::min(jcp.kh, div_up(jcp.ih, dilate_h));
+ cmp(reg_kh, final_inp_ker_overlap);
+ jl(oh_tpad_label, T_NEAR);
+ }
+ }
+ // need second loop to process kernel if it is larger than the input
+ // (does not apply to dilations as they must have unit stride)
+ if (kh_range >= jcp.ih + (t_pad % stride_h == 0 ? stride_h :
+ t_pad % stride_h)) {
+ assert(!is_dilated);
+ mov(reg_kh, jcp.ih);
+ L(oh_tpad_tail_label); {
+ compute_oh_step_disp();
+ add(reg_output, jcp.typesize_in * ow * jcp.oc_block);
+ sub(reg_kernel, jcp.typesize_out * stride_h * jcp.kw
+ * jcp.ic_block * jcp.oc_block);
+
+ inc(reg_oj);
+ add(reg_ih_count, stride_h);
+
+ cmp(reg_ih_count, nstl::min(t_pad, jcp.oh * stride_h));
+ jl(oh_tpad_tail_label, T_NEAR);
+ }
+ }
+ // correct any excess shifts to kernel and input
+ // (does not apply to dilations as they must have unit stride,
+ // kernel must fit inside input, and padding is smaller than input)
+ if (t_pad <= jcp.oh * stride_h) {
+ // kernel has moved beyond padding (adjust for stride effects)
+ if (t_pad % stride_h != 0) {
+ assert(!is_dilated);
+ int inp_corr = stride_h - t_pad % stride_h;
+ add(reg_kernel, jcp.typesize_out * inp_corr * jcp.kw
+ * jcp.ic_block * jcp.oc_block);
+ add(reg_input, jcp.typesize_in * inp_corr * iw * inp_mult);
+ }
+ } else {
+ // kernel still overlaps padding (complete reset)
+ assert(!is_dilated);
+ sub(reg_kernel, jcp.typesize_out * (t_pad - jcp.oh * stride_h)
+ * jcp.kw * jcp.ic_block * jcp.oc_block);
+ }
+ }
+
+ cmp(reg_ih_count, jcp.ihp - b_pad - (jcp.kh - 1) * dilate_h);
+ jge(oh_label_end, T_NEAR);
+ cmp(reg_oj, jcp.oh);
+ jge(oh_label, T_NEAR);
+
+ /* Compute middle block(s) */
+ mov(reg_kh, jcp.kh);
+ L(oh_label); {
+ compute_oh_step_disp();
+ add(reg_input, jcp.typesize_in * stride_h * iw * inp_mult);
+ add(reg_output, jcp.typesize_in * ow * jcp.oc_block);
+
+ inc(reg_oj);
+ add(reg_ih_count, stride_h);
+
+ cmp(reg_ih_count, jcp.ihp - b_pad - (jcp.kh - 1) * dilate_h);
+ jge(oh_label_end, T_NEAR);
+
+ cmp(reg_oj, jcp.oh);
+ jl(oh_label, T_NEAR);
+ }
+ L(oh_label_end);
+
+ /* Compute bottom edge */
+ if (b_pad > 0) {
+ cmp(reg_oj, jcp.oh);
+ jge(oh_bpad_label_end, T_NEAR);
+
+ if (is_dilated) {
+ mov(reg_kh, jcp.kh - 1); // assumes unit stride for dilations
+ mov(reg_tmp, 0);
+ } else {
+ mov(reg_kh, jcp.ihp - b_pad);
+ sub(reg_kh, reg_ih_count);
+ }
+ L(oh_bpad_label);
+ {
+ compute_oh_step_disp();
+ add(reg_input, jcp.typesize_in * stride_h * iw * inp_mult);
+ add(reg_output, jcp.typesize_in * ow * jcp.oc_block);
+ if (is_dilated) {
+ inc(reg_tmp);
+ cmp(reg_tmp, dilate_h);
+ jl(oh_dilate_label_end, T_NEAR);
+ xor_(reg_tmp, reg_tmp);
+ }
+ sub(reg_kh, stride_h);
+ cmp(reg_kh, 0);
+ jle(oh_bpad_label_end, T_NEAR);
+ if (is_dilated)
+ L(oh_dilate_label_end);
+
+ inc(reg_oj);
+ cmp(reg_oj, jcp.oh);
+ jl(oh_bpad_label, T_NEAR);
+ }
+ L(oh_bpad_label_end);
+ }
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::compute_d_loop_common() {
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ const int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block;
+ int iw = jcp.ver == ver_4fma ? jcp.tr_iw : jcp.iw;
+ int ow = jcp.ow;
+ const int input_backpad_overlap
+ = div_up(jcp.id + jcp.f_pad - (jcp.kd - 1), jcp.stride_d);
+
+ const size_t filter_shift
+ = jcp.typesize_out * jcp.kh * jcp.kw * ic_block * oc_block;
+ const size_t input_shift = jcp.typesize_in * jcp.ih * iw * inp_mult;
+ const size_t output_shift = jcp.typesize_in * jcp.oh * ow * jcp.oc_block;
+
+ Label d_loop_label, loop_end_label, common_block_label, fpad_end_label,
+ backpad_end_label, backpad_label;
+
+ if (jcp.with_bias) bias_kernel();
+
+ /* initially offset 'kd' by f_pad */
+ add(reg_kernel, ptr[param + GET_OFF(kd_offset)]);
+
+ mov(reg_input_d, ptr[param + GET_OFF(src)]);
+ mov(reg_output_d, ptr[param + GET_OFF(dst)]);
+ mov(reg_d_index, ptr[param + GET_OFF(d_index)]);
+ mov(reg_kd_count, ptr[param + GET_OFF(kd_padding)]);
+
+ cmp(reg_d_index, ptr[param + GET_OFF(d_worksize)]);
+ jge(loop_end_label, T_NEAR);
+
+ L(d_loop_label);
+
+ mov(reg_input, reg_input_d);
+ mov(reg_output, reg_output_d);
+
+ push(reg_input_d);
+ push(reg_output_d);
+ push(reg_d_index);
+
+ compute_oh_loop_common();
+
+ pop(reg_d_index);
+ pop(reg_output_d);
+ pop(reg_input_d);
+
+ /* Compute 'front' edge */
+ if (jcp.f_pad > 0) {
+
+ /* Check if within fpad region */
+ cmp(reg_d_index, div_up(jcp.f_pad, jcp.stride_d));
+ jge(fpad_end_label, T_NEAR);
+
+ /* Fpad steps */
+ sub(reg_kernel, filter_shift * jcp.stride_d);
+ add(reg_kd_count, jcp.stride_d);
+
+ /* Final number of kernel elements that overlap with input */
+ const int inp_ker_overlap = nstl::min(jcp.kd, jcp.id);
+ cmp(reg_kd_count, inp_ker_overlap);
+ jl(common_block_label, T_NEAR);
+
+ /* Correct any excess shifts to kernel and input */
+ if (jcp.f_pad <= jcp.od * jcp.stride_d) {
+ /* Filter has moved beyond padding (adjust for stride effects) */
+ if (jcp.f_pad % jcp.stride_d != 0) {
+ int inp_corr = jcp.stride_d - jcp.f_pad % jcp.stride_d;
+ add(reg_kernel, filter_shift * inp_corr);
+ add(reg_input_d, input_shift * inp_corr);
+ }
+ } else {
+ /* Filter still overlaps padding (complete reset) */
+ sub(reg_kernel, (jcp.f_pad - jcp.od * jcp.stride_d) * filter_shift);
+ }
+
+ /* Apply correction */
+ mov(reg_kd_count, jcp.kd);
+ jmp(common_block_label);
+
+ L(fpad_end_label);
+ }
+
+ /* Compute bottom edge */
+ if (jcp.back_pad > 0) {
+
+ /* Check if within back_pad region */
+ cmp(reg_d_index, input_backpad_overlap - 1);
+ jl(backpad_end_label, T_NEAR);
+ jg(backpad_label, T_NEAR);
+
+ /* Execute overlap correction between the filter and the initial
+ * back_pad region. */
+ mov(reg_kd_count,
+ jcp.id + jcp.f_pad - input_backpad_overlap * jcp.stride_d);
+ jmp(backpad_end_label, T_NEAR);
+
+ L(backpad_label);
+ sub(reg_kd_count, jcp.stride_d);
+ cmp(reg_kd_count, 0);
+ jle(loop_end_label, T_NEAR);
+
+ L(backpad_end_label);
+ }
+
+ /* Compute middle block */
+ add(reg_input_d, input_shift * jcp.stride_d);
+
+ /* Execute common block and loop */
+ L(common_block_label);
+ add(reg_output_d, output_shift);
+ inc(reg_d_index);
+ cmp(reg_d_index, ptr[param + GET_OFF(d_worksize)]);
+ jl(d_loop_label, T_NEAR);
+
+ L(loop_end_label);
+}
+
+bool jit_avx512_common_conv_bwd_weights_kernel_f32::compute_full_spat_loop() {
+ // FIXME: use register mapping from the class declaration
+ bool ok = jcp.ver == ver_4fma
+ && everyone_is(0, jcp.dilate_h, jcp.dilate_w)
+ && everyone_is(1, jcp.stride_h, jcp.stride_w);
+ if (!ok) return false;
+ if (jcp.l_pad != jcp.kw / 2 || jcp.t_pad != jcp.kh / 2)
+ return false;
+
+ // General code layout:
+ //
+ // Blocking over OH -- top level
+ // (Reduces L2 pressure; not very useful right now)
+ // Loop over all KHxKW kernel -- emit_kh_kw_loop()
+ // Loop over OH block -- emit_h_loop()
+ // Loop over OW blocks -- emit_fma_block()
+ // (Supports both fully unrolled and partially unrolled versions to
+ // reduce code size)
+ // Loop over OW block -- emit_fma_step()
+
+ int max_working_set_size = 128 * 1024;
+ int pad_ow = jcp.ow;
+
+ int inp_row_size = jcp.ic_block * jcp.tr_iw * jcp.typesize_in;
+ int out_row_size = jcp.oc_block * pad_ow * jcp.typesize_in;
+ int row_size = inp_row_size + out_row_size;
+
+ int h_block_size = jcp.oh;
+ int working_set_size = row_size * h_block_size;
+
+ if (working_set_size > max_working_set_size) {
+ int opt_working_set_size = 48 * 1024;
+ assert(opt_working_set_size < max_working_set_size);
+
+ while (working_set_size > opt_working_set_size) {
+ for (int i = 2; i <= h_block_size; i++)
+ if (i == h_block_size)
+ h_block_size = h_block_size / 2;
+ else if (h_block_size % i == 0) {
+ h_block_size = h_block_size / i;
+ break;
+ }
+ working_set_size = row_size * h_block_size;
+
+ if (h_block_size == 1 && working_set_size > opt_working_set_size)
+ return false;
+ }
+ }
+
+ // NB1: t_pad <= oh_block_size and b_pad <= last_oh_block_size (see below)
+ if (h_block_size < nstl::max(1, jcp.t_pad)
+ || jcp.b_pad > (jcp.oh % h_block_size == 0 ? h_block_size
+ : jcp.oh % h_block_size))
+ return false;
+
+ // check that we can use simple arithmetic for prefetch address
+ // calculations
+ // TODO: we need some traits for this check (Roma)
+ int cache_line_size = 64;
+ assert(jcp.ic_block * typesize == 64);
+ assert(jcp.oc_block * typesize == 64);
+
+ int num_inp_l2_pfs = jcp.tr_iw * h_block_size;
+ int avg_h_loop_len = h_block_size;
+ int num_inp_l2_pfs_per_fma_block
+ = div_up(num_inp_l2_pfs, avg_h_loop_len * jcp.kw * jcp.kh);
+ int num_out_l2_pfs = pad_ow * h_block_size;
+ int num_out_l2_pfs_per_fma_block
+ = div_up(num_out_l2_pfs, avg_h_loop_len * jcp.kw * jcp.kh);
+
+ Opmask reg_h_block = k1; // 32-bit only on Intel(R) Xeon Phi(TM) processors
+ Reg64 reg_kh = rax;
+ Reg64 reg_kw = rbx;
+ Reg64 reg_tmp = abi_not_param1;
+ Reg32 reg_tmp_w = reg_tmp.cvt32();
+ Reg64 reg_ohs = rdx;
+ Reg64 reg_ihs = rsi;
+ Reg64 reg_h = r8;
+ Reg64 reg_i = r9;
+ Reg64 reg_j = r10;
+
+ Reg64 reg_inp = r13;
+ Reg64 reg_out = r14;
+ Reg64 reg_ker = r15;
+
+ Reg64 reg_inp_pf_l1 = rbp;
+
+ Reg64 reg_inp_pf_l2 = r11;
+ Reg64 reg_out_pf_l2 = r12;
+
+ Xmm reg_inp_pf_save = xmm17;
+ Xmm reg_out_pf_save = xmm18;
+
+ Reg64 reg_inp_save = abi_param1;
+ Reg64 reg_out_save = reg_tmp;
+
+ auto zmm_out = [&](int oi) { return Zmm(24 + oi % 8); };
+ auto zmm_ker = [&](int ic1) { return Zmm(ic1); };
+ auto inp_addr = [&](int oi, int ic1) {
+ return ptr[reg_inp + (ic1 * jcp.tr_iw + oi) * jcp.typesize_in];
+ };
+ auto out_addr = [&](int oi, int oj = 0) {
+ assert(jcp.ver == ver_4fma);
+ return ptr[reg_out
+ + ((oi + oj * jcp.ow) * jcp.oc_block) * jcp.typesize_in];
+ };
+ auto ker_addr = [&](int ic1) {
+ return ptr[reg_ker + ic1 * jcp.oc_block * jcp.typesize_out];
+ };
+
+ auto emit_block = [&](int h_block_size,
+ bool is_last_block, bool is_last_kh_kw_iter, bool is_last_row)
+ {
+ // TODO: add an fma version (Roma)
+ auto pad_ow = jcp.ow;
+
+ int ow4u = rnd_up(pad_ow, 4);
+ int def_step_size = 16;
+
+ bool has_w_tail = (pad_ow % def_step_size != 0
+ || pad_ow % 4 != 0);
+ bool full_w_unroll = pad_ow / def_step_size < 2 + has_w_tail;
+
+ auto emit_step = [&](int ur_ow,
+ int num_inp_l1_pfs_per_fma_step,
+ int num_inp_l2_pfs_per_fma_step,
+ int num_out_l2_pfs_per_fma_step, bool is_w_tail)
+ {
+ bool block_wraparound = is_w_tail && is_last_row;
+
+ assert(ur_ow % 4 == 0);
+ int tail_size = ow4u % ur_ow;
+ int this_ur_ow
+ = (is_w_tail && tail_size) ? tail_size : ur_ow;
+ int ow_last_chunk4 = pad_ow % 4;
+ int ow_zero_tail4 = ow_last_chunk4
+ ? 4 - ow_last_chunk4 : 0;
+
+ auto emit_out_pf = [&](int oi) {
+#if 1
+ if (oi + def_step_size < ur_ow || !block_wraparound)
+ mic_prefetcht0(ptr[reg_out
+ + ((def_step_size + oi)
+ * jcp.oc_block * jcp.typesize_in)]);
+ else {
+ assert(block_wraparound);
+ assert(oi + def_step_size >= ur_ow);
+ mic_prefetcht0(ptr[reg_out_save
+ + ((oi + def_step_size - ur_ow)
+ * jcp.oc_block * jcp.typesize_in)]);
+ }
+#else
+ // XXX: This is an alternative prefetching strategy that
+ // always prefetches the next row. Keeping it here for
+ // future experiments (Roma)
+ if (!block_wraparound)
+ mic_prefetcht0(ptr[reg_out
+ + (jcp.ow + oi) * jcp.oc_block * jcp.typesize_in]);
+ else
+ mic_prefetcht0(ptr[reg_out + reg_ohs
+ - ((h_block_size - 1) * jcp.ow
+ - oi) * jcp.oc_block * jcp.typesize_in]);
+#endif
+ if (oi < num_out_l2_pfs_per_fma_step)
+ mic_prefetcht1(ptr[reg_out_pf_l2
+ + oi * jcp.oc_block * jcp.typesize_in]);
+ };
+
+ auto emit_inp_pf = [&](int oi4, int ic1) {
+ int pf_slot_idx = ic1 + oi4 / 4 * jcp.ic_block;
+ int num_pf_slots = jcp.ic_block * ur_ow / 4;
+
+ int num_pfs = num_inp_l1_pfs_per_fma_step
+ + num_inp_l2_pfs_per_fma_step;
+ int pf_freq = nstl::max(1, num_pf_slots / num_pfs);
+
+ if (pf_slot_idx % pf_freq)
+ return;
+
+ int pf_idx = pf_slot_idx / pf_freq;
+
+ if (pf_idx < num_inp_l2_pfs_per_fma_step)
+ mic_prefetcht1(ptr[reg_inp_pf_l2
+ + pf_idx * jcp.ic_block * jcp.typesize_in]);
+ else {
+ pf_idx -= num_inp_l2_pfs_per_fma_step;
+ // prefetch the 'tail' of the cache line because most of
+ // the accesses are not aligned
+ mic_prefetcht0(ptr[reg_inp_pf_l1
+ + pf_idx * jcp.ic_block * jcp.typesize_in
+ + cache_line_size - jcp.typesize_in]);
+ }
+ };
+
+ auto numloads = 4;
+
+ int steps = this_ur_ow;
+ for (int oi4 = 0; oi4 < steps; oi4 += numloads) {
+ for (int oi1 = 0; oi1 < numloads; oi1++) {
+ int oi = oi4 + oi1;
+ if (!is_w_tail || oi < (this_ur_ow - ow_zero_tail4)) {
+ vmovups(zmm_out(oi), out_addr(oi));
+ emit_out_pf(oi);
+ } else {
+ auto zmm = zmm_out(oi);
+ vpxord(zmm, zmm, zmm);
+ }
+ }
+
+ for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) {
+ if (jcp.ver == ver_4fma) {
+ v4fmaddps(zmm_ker(ic1),
+ zmm_out(oi4), inp_addr(oi4, ic1));
+ } else {
+ assert(!"unknown convolution version");
+ }
+ emit_inp_pf(oi4, ic1);
+ }
+ }
+ };
+
+ // Input is transposed and padded but we only access about jcp.iw
+ // elements so use that to compute the # of cache lines in each 'row'
+ int num_inp_l1_pfs
+ = div_up(jcp.iw * jcp.typesize_in, cache_line_size) * jcp.ic_block;
+
+ if (full_w_unroll) {
+ emit_step(ow4u, num_inp_l1_pfs,
+ num_inp_l2_pfs_per_fma_block,
+ num_out_l2_pfs_per_fma_block, true);
+ add(reg_inp_pf_l2, num_inp_l2_pfs_per_fma_block * cache_line_size);
+ add(reg_out_pf_l2, num_out_l2_pfs_per_fma_block * cache_line_size);
+ } else {
+ Label w_loop;
+ int num_w_iters = pad_ow / def_step_size;
+ int num_w_iters_full = num_w_iters + has_w_tail;
+ int num_inp_l1_pfs_per_fma_step
+ = div_up(num_inp_l1_pfs, num_w_iters_full);
+ int num_inp_l2_pfs_per_fma_step
+ = div_up(num_inp_l2_pfs_per_fma_block, num_w_iters_full);
+ int num_out_l2_pfs_per_fma_step
+ = div_up(num_out_l2_pfs_per_fma_block, num_w_iters_full);
+ mov(reg_i, num_w_iters);
+ L(w_loop); {
+ emit_step(def_step_size, num_inp_l1_pfs_per_fma_step,
+ num_inp_l2_pfs_per_fma_step,
+ num_out_l2_pfs_per_fma_step, false);
+ add(reg_inp, def_step_size * jcp.typesize_in);
+ add(reg_out, def_step_size * jcp.oc_block * jcp.typesize_in);
+ add(reg_inp_pf_l1,
+ num_inp_l1_pfs_per_fma_step * cache_line_size);
+ add(reg_inp_pf_l2,
+ num_inp_l2_pfs_per_fma_step * cache_line_size);
+ add(reg_out_pf_l2,
+ num_out_l2_pfs_per_fma_step * cache_line_size);
+ sub(reg_i, 1);
+ jnz(w_loop);
+ }
+ if (has_w_tail) {
+ emit_step(def_step_size, num_inp_l1_pfs_per_fma_step,
+ num_inp_l2_pfs_per_fma_step,
+ num_out_l2_pfs_per_fma_step, true);
+ add(reg_inp_pf_l2,
+ num_inp_l2_pfs_per_fma_step * cache_line_size);
+ add(reg_out_pf_l2,
+ num_out_l2_pfs_per_fma_step * cache_line_size);
+ }
+ // reset reg_inp and reg_out because emit_h_loop expects
+ // unmodified pointers
+ int w_offset = num_w_iters * def_step_size;
+ sub(reg_inp, w_offset * jcp.typesize_in);
+ sub(reg_out, w_offset * jcp.oc_block * jcp.typesize_in);
+ }
+ };
+
+ auto emit_h_loop = [&](int h_block_size,
+ bool is_last_block, bool is_last_kh_kw_iter)
+ {
+ Label h_loop, skip_h_loop;
+ mov(reg_j, 1);
+ cmp(reg_j, reg_h);
+ je(skip_h_loop, T_NEAR);
+ L(h_loop); {
+
+ lea(reg_inp_pf_l1,
+ ptr[reg_inp + jcp.tr_iw * jcp.ic_block * jcp.typesize_in]);
+ emit_block(h_block_size,
+ is_last_block, is_last_kh_kw_iter, false);
+
+ add(reg_inp, jcp.tr_iw * jcp.ic_block * jcp.typesize_in);
+ add(reg_out, pad_ow * jcp.oc_block * jcp.typesize_in);
+ add(reg_j, 1);
+ cmp(reg_j, reg_h);
+ jb(h_loop);
+ }
+
+ L(skip_h_loop);
+
+ for (int ic1 = 0; ic1 < jcp.ic_block; ic1++)
+ mic_prefetcht0(ker_addr(ic1));
+
+ lea(reg_inp_pf_l1, ptr[reg_inp_save + reg_kw * jcp.typesize_in]);
+ emit_block(h_block_size, is_last_block, is_last_kh_kw_iter, true);
+ };
+
+ auto emit_kh_kw_loop = [&](bool is_first_block, bool is_last_block,
+ int h_block_size)
+ {
+ xor_(reg_kh, reg_kh);
+ Label kh_loop, kh_loop_end;
+
+ int last_oh_block_size
+ = jcp.oh - rnd_up(jcp.oh - h_block_size, h_block_size);
+ int oh_block_size = (is_last_block) ? last_oh_block_size : h_block_size;
+ // NB1: t_pad <= oh_block_size and b_pad <= last_oh_block_size
+ int ih_block_size = oh_block_size - 1 + jcp.kh
+ - is_first_block * jcp.t_pad - is_last_block * jcp.b_pad;
+
+ L(kh_loop); {
+ // determine starting indices for this block
+ if (is_first_block) {
+ xor_(reg_tmp, reg_tmp);
+ mov(reg_ohs, jcp.t_pad);
+ sub(reg_ohs, reg_kh);
+ cmovb(reg_ohs, reg_tmp);
+
+ mov(reg_ihs, reg_ohs);
+ sub(reg_ihs, jcp.t_pad);
+ add(reg_ihs, reg_kh);
+ } else {
+ xor_(reg_ohs, reg_ohs);
+ mov(reg_ihs, reg_kh);
+ }
+
+ // determine effective size of block based on padding
+ mov(reg_tmp, oh_block_size);
+ sub(reg_tmp, reg_ohs);
+ mov(reg_h, ih_block_size);
+ sub(reg_h, reg_ihs);
+ cmp(reg_tmp, reg_h);
+ cmovb(reg_h, reg_tmp);
+
+ Label kh_loop_work;
+ cmp(reg_h, 0);
+ jg(kh_loop_work, T_NEAR);
+
+ // empty h loop for this jcp.kh:
+ // - set the output to 0 if necessary
+ // - move ker pt
+ // - jump to the end
+ sub(reg_h, 1);
+ Label skip_ker_zeroing;
+
+ // The reg_ker ptr has highest bit set if the output needs to be
+ // zeroed. Those who have byte-aligned their data will suffer the
+ // consiquences :(
+ // TODO: move the flag to a mask register? (Roma)
+ test(reg_ker, 1);
+ jz(skip_ker_zeroing, T_NEAR);
+
+ Label zeroing_loop;
+ vpxord(zmm0, zmm0, zmm0);
+ and_(reg_ker, ~1); // temporarily clear the zeroing flag
+ mov(reg_tmp, jcp.kw);
+ L(zeroing_loop); {
+ for (int ic1 = 0; ic1 < jcp.ic_block; ic1++)
+ vmovups(ker_addr(ic1), zmm0);
+ add(reg_ker, jcp.oc_block * jcp.ic_block * jcp.typesize_out);
+ sub(reg_tmp, 1);
+ jnz(zeroing_loop, T_NEAR);
+ }
+ // restore the zeroing flag (it will be cleared after the end of
+ // emit_kh_kw_loop, but we may need it until then)
+ or_(reg_ker, 1);
+ jmp(kh_loop_end, T_NEAR);
+
+ L(skip_ker_zeroing);
+ add(reg_ker, jcp.oc_block * jcp.ic_block * jcp.kw
+ * jcp.typesize_out);
+ jmp(kh_loop_end, T_NEAR);
+
+ L(kh_loop_work);
+
+ mul_by_const(reg_ihs, reg_tmp,
+ jcp.tr_iw * jcp.ic_block * jcp.typesize_in);
+ mul_by_const(reg_ohs, reg_tmp,
+ pad_ow * jcp.oc_block * jcp.typesize_in);
+
+ add(reg_inp, reg_ihs);
+ add(reg_out, reg_ohs);
+
+ Label kw_loop;
+ xor_(reg_kw, reg_kw);
+ L(kw_loop); {
+ for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) {
+ auto zmm = zmm_ker(ic1);
+ vpxord(zmm, zmm, zmm);
+ mic_prefetcht1(ker_addr(ic1));
+ }
+
+ mov(reg_out_save, reg_out);
+ mov(reg_inp_save, reg_inp);
+ lea(reg_inp, ptr[reg_inp + reg_kw * jcp.typesize_in]);
+
+#if 0
+ // XXX: Generate code with special prefetches when switching
+ // blocks or at the end of the last block. Disabled to reduce
+ // code size and because there's no performance benefit (Roma)
+ Label regular_h_loop, end_h_loop;
+ cmp(reg_kw, jcp.kw - 1);
+ jne(regular_h_loop, T_NEAR);
+ cmp(reg_kh, jcp.kh - 1);
+ jne(regular_h_loop, T_NEAR);
+
+ emit_h_loop(oh_block_size, is_last_block, true);
+ jmp(end_h_loop, T_NEAR);
+
+ L(regular_h_loop);
+ emit_h_loop(oh_block_size, is_last_block, false);
+
+ L(end_h_loop);
+#else
+ emit_h_loop(oh_block_size, is_last_block, false);
+#endif
+
+ mov(reg_out, reg_out_save);
+ mov(reg_inp, reg_inp_save);
+
+ Label do_store;
+ // The reg_ker ptr has highest bit set if the output needs to
+ // be zeroed. Those who have byte-aligned their data will
+ // suffer the consiquences :(
+ mov(reg_tmp, reg_ker);
+ and_(reg_ker, ~1);
+ test(reg_tmp, 1);
+ jnz(do_store, T_NEAR);
+
+ for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) {
+ auto zmm = zmm_ker(ic1);
+ if (jcp.ver == ver_4fma) {
+ vaddps(zmm, ker_addr(ic1));
+ } else {
+ assert(!"unknown convolution version");
+ }
+ }
+
+ L(do_store);
+ for (int ic1 = 0; ic1 < jcp.ic_block; ic1++) {
+ auto zmm = zmm_ker(ic1);
+ vmovups(ker_addr(ic1), zmm);
+ }
+
+ mov(reg_ker, reg_tmp);
+ add(reg_ker, jcp.ic_block * jcp.oc_block * jcp.typesize_out);
+ add(reg_kw, 1);
+ cmp(reg_kw, jcp.kw);
+ jl(kw_loop);
+ }
+
+ sub(reg_inp, reg_ihs);
+ sub(reg_out, reg_ohs);
+
+
+ L(kh_loop_end);
+ add(reg_kh, 1);
+ cmp(reg_kh, jcp.kh);
+ jl(kh_loop);
+ }
+ };
+
+ mov(reg_inp, ptr[param + GET_OFF(src)]);
+ mov(reg_out, ptr[param + GET_OFF(dst)]);
+ mov(reg_ker, ptr[param + GET_OFF(filt)]);
+ mov(reg_inp_pf_l2, ptr[param + GET_OFF(src_prf)]);
+ mov(reg_out_pf_l2, ptr[param + GET_OFF(dst_prf)]);
+ mov(reg_tmp, ptr[param + GET_OFF(channel)]);
+ or_(reg_ker, reg_tmp);
+
+ bool single_kh_kw_loop = (h_block_size == jcp.oh);
+
+ size_t inp_row_step = jcp.tr_iw * jcp.ic_block * jcp.typesize_in;
+ size_t first_inp_block_step = inp_row_step * (h_block_size - jcp.t_pad);
+ size_t inp_block_step = inp_row_step * h_block_size;
+ size_t out_block_step = pad_ow * jcp.oc_block * jcp.typesize_in
+ * h_block_size;
+
+ if (!single_kh_kw_loop) {
+ // Save the original prefetch pointers from the OpenMP driver
+ vmovq(reg_inp_pf_save, reg_inp_pf_l2);
+ vmovq(reg_out_pf_save, reg_out_pf_l2);
+ mov(reg_inp_pf_l2, reg_inp);
+ add(reg_inp_pf_l2, first_inp_block_step);
+ mov(reg_out_pf_l2, reg_out);
+ add(reg_out_pf_l2, out_block_step);
+ }
+ emit_kh_kw_loop(true, single_kh_kw_loop, h_block_size);
+
+ if (!single_kh_kw_loop) {
+ size_t ker_reset_offset
+ = jcp.oc_block * jcp.ic_block * jcp.typesize_out * jcp.kw * jcp.kh;
+ sub(reg_ker, ker_reset_offset);
+ and_(reg_ker, ~1); // Clear the zeroing flag for subsequent updates
+
+ add(reg_inp, first_inp_block_step);
+ add(reg_out, out_block_step);
+ mov(reg_inp_pf_l2, reg_inp);
+ add(reg_inp_pf_l2, inp_block_step);
+ mov(reg_out_pf_l2, reg_out);
+ add(reg_out_pf_l2, out_block_step);
+
+ int num_innermost_iters = div_up(jcp.oh, h_block_size) - 2;
+ if (num_innermost_iters > 0) {
+ Label h_block_loop;
+
+ mov(reg_tmp_w, num_innermost_iters);
+ kmovw(reg_h_block, reg_tmp_w);
+ L(h_block_loop); {
+ emit_kh_kw_loop(false, false, h_block_size);
+ sub(reg_ker, ker_reset_offset);
+ add(reg_inp, inp_row_step * h_block_size);
+ add(reg_out, out_block_step);
+ mov(reg_inp_pf_l2, reg_inp);
+ add(reg_inp_pf_l2, inp_block_step);
+ mov(reg_out_pf_l2, reg_out);
+ add(reg_out_pf_l2, out_block_step);
+ kmovw(reg_tmp_w, reg_h_block);
+ sub(reg_tmp_w, 1);
+ kmovw(reg_h_block, reg_tmp_w);
+ jnz(h_block_loop);
+ }
+ }
+
+ // Restore the original prefetch pointers that came from the OpenMP
+ // driver
+ vmovq(reg_inp_pf_l2, reg_inp_pf_save);
+ vmovq(reg_out_pf_l2, reg_out_pf_save);
+ emit_kh_kw_loop(false, true, h_block_size);
+ }
+
+ return true;
+}
+
+bool jit_avx512_common_conv_bwd_weights_kernel_f32
+ ::flat_4ops_compute() {
+ const auto &j = jcp;
+ const bool ok = j.ver == ver_4fma && j.is_1stconv
+ && everyone_is(0, j.dilate_h, j.dilate_w);
+ if (!ok) return false;
+
+ Reg64 reg_ptr_tr_src = r8;
+ Reg64 reg_ptr_dst = r9;
+ Reg64 reg_ptr_wei = r10;
+ Reg64 reg_ptr_bia = r11;
+
+ Reg64 reg_kh_step = rax;
+ Reg64 reg_oh = abi_not_param1;
+ Reg64 reg_kh = rdx;
+
+ Reg32 reg_flag_save = ebx;
+ Reg32 reg_flag = esi;
+
+ Zmm vbia(31);
+
+ auto zmm_wei = [&](int kh, int kw) {
+ return Zmm(8 + kh * j.kw + kw);
+ };
+ auto zmm_dst = [&](int ow) {
+ return Zmm(ow % 8);
+ };
+
+ auto addr_tr_src = [&](int kh, int iw) {
+ return ptr[reg_ptr_tr_src
+ + (kh * j.stride_w * j.tr_ld + iw) * jcp.typesize_in];
+ };
+ auto addr_dst = [&](int ow) {
+ return ptr[reg_ptr_dst + ow * jcp.oc_block * jcp.typesize_in];
+ };
+ auto addr_wei = [&](int kh, int kw) {
+ return ptr[reg_ptr_wei + (kh * j.kw + kw) * j.oc_block
+ * jcp.typesize_out];
+ };
+
+ auto emit_fma_block = [&](int kh_step) {
+ for (int kh = 0; kh < kh_step; ++kh) {
+ for (int kw = 0; kw < j.kw; ++kw) {
+ auto vwei = zmm_wei(kh, kw);
+ vpxord(vwei, vwei, vwei);
+ }
+ }
+
+ for (int ow = 0; ow < j.ow; ow += 4) {
+ for (int _ow = ow; _ow < ow + 4; ++_ow) {
+ auto vdst = zmm_dst(_ow);
+ if (_ow < j.ow)
+ vmovups(vdst, addr_dst(_ow));
+ else
+ vpxord(vdst, vdst, vdst);
+ }
+
+ for (int kh = 0; kh < kh_step; ++kh) {
+ for (int kw = 0; kw < j.kw; ++kw) {
+ const int iw = ow + (kw % j.stride_w) * j.tr_ld
+ + (kw / j.stride_w);
+ v4fmaddps(zmm_wei(kh, kw), zmm_dst(ow),
+ addr_tr_src(kh, iw));
+ if (1 && kh == 0 && kw < 4) {
+ prefetcht1(ptr[reg_ptr_dst
+ + (j.ow + ow + kw) * jcp.oc_block
+ * jcp.typesize_in]);
+ }
+ if (j.with_bias && kh_step == 1) { /* [bwd_w:b:r1] */
+ const int off = kw + 4 - j.kw;
+ if (off >= 0 && ow + off < j.ow)
+ vaddps(vbia, vbia, zmm_dst(ow + off));
+ }
+ }
+ }
+ }
+
+ Label l_store;
+ test(reg_flag, FLAG_MB_FIRST);
+ jnz(l_store, T_NEAR);
+ for (int kh = 0; kh < kh_step; ++kh) {
+ for (int kw = 0; kw < j.kw; ++kw)
+ vaddps(zmm_wei(kh, kw), addr_wei(kh, kw));
+ }
+ L(l_store);
+ for (int kh = 0; kh < kh_step; ++kh) {
+ for (int kw = 0; kw < j.kw; ++kw)
+ vmovups(addr_wei(kh, kw), zmm_wei(kh, kw));
+ }
+ };
+
+ auto emit_kh_loop = [&]() {
+ const int kh_step_rem = j.kh % j.kh_step;
+ xor_(reg_kh, reg_kh);
+ mov(reg_kh_step, j.kh_step);
+
+ Label l_kh_loop;
+ L(l_kh_loop); {
+ Label l_done;
+
+ if (kh_step_rem != 0) {
+ Label l_keep_kh_step;
+ cmp(reg_kh, j.kh - j.kh_step);
+ jle(l_keep_kh_step, T_NEAR);
+
+ mov(reg_kh_step, kh_step_rem);
+ emit_fma_block(kh_step_rem);
+ jmp(l_done, T_NEAR);
+
+ L(l_keep_kh_step);
+ }
+
+ emit_fma_block(j.kh_step);
+
+ L(l_done);
+
+ add(reg_ptr_tr_src, j.kh_step * j.stride_w * j.tr_ld
+ * jcp.typesize_in);
+ add(reg_ptr_wei, j.kh_step * j.kw * j.oc_block * jcp.typesize_out);
+ add(reg_kh, j.kh_step);
+
+ cmp(reg_kh, j.kh);
+ jl(l_kh_loop, T_NEAR);
+ }
+
+ const int kh_steps = rnd_up(j.kh, j.kh_step);
+ sub(reg_ptr_tr_src, kh_steps * j.stride_w * j.tr_ld * jcp.typesize_in);
+ sub(reg_ptr_wei, kh_steps * j.kw * j.oc_block * jcp.typesize_out);
+ };
+
+ auto emit_oh_loop = [&]() {
+ mov(reg_oh, j.oh);
+
+ Label l_oh_loop;
+ L(l_oh_loop); {
+ Label l_restore_mb_flag, l_jump;
+
+ cmp(reg_oh, j.oh);
+ je(l_restore_mb_flag, T_NEAR);
+
+ and_(reg_flag, ~FLAG_MB_FIRST);
+ jmp(l_jump, T_NEAR);
+
+ L(l_restore_mb_flag);
+ mov(reg_flag, reg_flag_save);
+
+ L(l_jump);
+
+ emit_kh_loop();
+
+ add(reg_ptr_tr_src, j.stride_h * j.stride_w * j.tr_ld
+ * jcp.typesize_in);
+ add(reg_ptr_dst, j.ow * j.oc_block * jcp.typesize_in);
+
+ dec(reg_oh);
+ jnz(l_oh_loop, T_NEAR);
+ }
+ };
+
+ auto emit_bia_store = [&]() {
+ if (!j.with_bias) return;
+
+ Label l_bia_store, l_bia_skip;
+ test(reg_flag, FLAG_IC_FIRST);
+ jz(l_bia_skip);
+
+ test(reg_flag, FLAG_MB_FIRST);
+ jnz(l_bia_store, T_NEAR);
+ vaddps(vbia, ptr[reg_ptr_bia]);
+ L(l_bia_store);
+ vmovups(ptr[reg_ptr_bia], vbia);
+ L(l_bia_skip);
+ };
+
+ mov(reg_ptr_tr_src, ptr[param + GET_OFF(src)]);
+ mov(reg_ptr_dst, ptr[param + GET_OFF(dst)]);
+ mov(reg_ptr_wei, ptr[param + GET_OFF(filt)]);
+ mov(reg_ptr_bia, ptr[param + GET_OFF(bias)]);
+ mov(reg_flag_save, ptr[param + GET_OFF(flags)]);
+
+ vpxord(vbia, vbia, vbia);
+ emit_oh_loop();
+ emit_bia_store();
+
+ return true;
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::compute_loop()
+{
+ if (flat_4ops_compute())
+ return;
+ if (compute_full_spat_loop())
+ return;
+
+ maybe_zero_kernel();
+
+ if (jcp.ndims == 5) compute_d_loop_common();
+ else compute_oh_loop_common();
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::generate()
+{
+ preamble();
+
+ mov(reg_input, ptr[param + GET_OFF(src)]);
+ mov(reg_output, ptr[param + GET_OFF(dst)]);
+ mov(reg_kernel, ptr[param + GET_OFF(filt)]);
+
+ compute_loop();
+
+ postamble();
+}
+
+status_t jit_avx512_common_conv_bwd_weights_kernel_f32::init_conf(
+ jit_conv_conf_t &jcp, const convolution_desc_t &cd,
+ memory_desc_t &src_md, memory_desc_t &diff_weights_md,
+ memory_desc_t &diff_bias_md, memory_desc_t &diff_dst_md) {
+ if (!mayiuse(avx512_common))
+ return status::unimplemented;
+
+ const memory_desc_wrapper src_d(&src_md);
+ const memory_desc_wrapper diff_weights_d(&diff_weights_md);
+ const memory_desc_wrapper diff_bias_d(&diff_bias_md);
+ const memory_desc_wrapper diff_dst_d(&diff_dst_md);
+
+ const bool with_groups = diff_weights_d.ndims() == src_d.ndims() + 1;
+ int ndims = src_d.ndims();
+
+ jcp = zero<decltype(jcp)>();
+
+ jcp.simd_w = cpu_isa_traits<avx512_common>::vlen / sizeof(float);
+ jcp.ndims = ndims;
+ jcp.prop_kind = cd.prop_kind;
+
+ jcp.ngroups = with_groups ? diff_weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+
+ jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+
+ jcp.id = (ndims == 5) ? src_d.dims()[2] : 1;
+ jcp.ih = (ndims == 3) ? 1 : src_d.dims()[ndims-2];
+ jcp.iw = src_d.dims()[ndims-1];
+ jcp.od = (ndims == 5) ? diff_dst_d.dims()[2] : 1;
+ jcp.oh = (ndims == 3) ? 1 : diff_dst_d.dims()[ndims-2];
+ jcp.ow = diff_dst_d.dims()[ndims-1];
+
+ jcp.kd = (ndims == 5) ? diff_weights_d.dims()[with_groups + 2] : 1;
+ jcp.kh = (ndims == 3) ? 1 : diff_weights_d.dims()[with_groups + ndims-2];
+ jcp.kw = diff_weights_d.dims()[with_groups + ndims-1];
+
+ jcp.f_pad = (ndims == 5) ? cd.padding[0][0] : 0;
+ jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][ndims-4];
+ jcp.l_pad = cd.padding[0][ndims-3];
+
+ jcp.stride_d = (ndims == 5) ? cd.strides[0] : 1;
+ jcp.stride_h = (ndims == 3) ? 1 : cd.strides[ndims-4];
+ jcp.stride_w = cd.strides[ndims-3];
+
+ jcp.dilate_d = (ndims == 5) ? cd.dilates[0] : 0;
+ jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[ndims-4];
+ jcp.dilate_w = cd.dilates[ndims-3];
+
+ const int kh_range = 1 + (jcp.kh - 1) * (jcp.dilate_h + 1);
+ bool ok = true
+ // general condition to simplify dilations
+ && IMPLICATION(jcp.dilate_d != 0, jcp.stride_d == 1)
+ && IMPLICATION(jcp.dilate_h != 0, jcp.stride_h == 1)
+ && IMPLICATION(jcp.dilate_w != 0, jcp.stride_w == 1)
+ // special condition to simplify dilations in compute_oh_loop_common
+ && IMPLICATION(jcp.dilate_h != 0, kh_range <= jcp.ih);
+ if (!ok)
+ return status::unimplemented;
+
+ jcp.r_pad = nstl::max(0, (jcp.ow - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1));
+ jcp.b_pad = nstl::max(0, (jcp.oh - 1) * jcp.stride_h
+ + (jcp.kh - 1) * (jcp.dilate_h + 1) - (jcp.ih + jcp.t_pad - 1));
+ jcp.back_pad = nstl::max(0, (jcp.od - 1) * jcp.stride_d
+ + (jcp.kd - 1) * (jcp.dilate_d + 1) - (jcp.id + jcp.f_pad - 1));
+
+ /* XXX: currently, does not support dilation_d > 0 */
+ if (ndims == 5)
+ if (jcp.dilate_d > 0)
+ return status::unimplemented;
+
+ jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad;
+ jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad;
+ jcp.ohp = jcp.oh;
+ jcp.owp = jcp.ow;
+ jcp.aligned_threads = 0;
+
+ /* check for the 1st convolution */
+ jcp.is_1stconv = is_1stconv(jcp);
+
+ jcp.oc_block = jcp.simd_w;
+
+ bool ok_to_pad_channels = true
+ && jcp.ngroups == 1
+ && src_d.data_type() == data_type::f32;
+
+ if (ok_to_pad_channels)
+ jcp.oc = rnd_up(jcp.oc, jcp.simd_w);
+
+ if (jcp.oc % jcp.oc_block)
+ return status::unimplemented;
+
+ auto dst_tag = pick(ndims - 3, nCw16c, nChw16c, nCdhw16c);
+ auto wei_tag = with_groups
+ ? pick(ndims - 3, gOIw16i16o, gOIhw16i16o, gOIdhw16i16o)
+ : pick(ndims - 3, OIw16i16o, OIhw16i16o, OIdhw16i16o);
+
+ if (diff_dst_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(diff_dst_md, dst_tag));
+ jcp.dst_tag = dst_tag;
+ } else {
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(dst_tag);
+ }
+ if (jcp.dst_tag != dst_tag)
+ return status::unimplemented;
+
+ /* conditions on bias memory */
+ jcp.with_bias = cd.diff_bias_desc.format_kind != format_kind::undef;
+ if (jcp.with_bias) {
+ if (diff_bias_d.format_kind() == format_kind::any)
+ CHECK(memory_desc_init_by_tag(diff_bias_md, x));
+ }
+
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+
+ /* kernel applicability check wrt boundaries
+ * the conditions are quite general across the kernels we have,
+ * but ideally the check should belong to a specific kernel... */
+ const int max_pad = ((jcp.kh - 1) * (jcp.dilate_h + 1) + 1) / 2;
+ const bool boundaries_ok = true
+ && jcp.t_pad <= max_pad
+ && jcp.b_pad <= max_pad
+ && IMPLICATION(jcp.f_pad > 0, jcp.kd < jcp.id + jcp.f_pad)
+ && jcp.f_pad < jcp.kd;
+ if (!boundaries_ok)
+ return status::unimplemented;
+
+ /* yet another common check */
+ if (jcp.kw > 14)
+ return status::unimplemented;
+
+ /* setting register strategy */
+ for (int ur_w = nstl::min(max_ur_w, jcp.ow); ur_w > 0; --ur_w) {
+ if (jcp.ow % ur_w == 0) { jcp.ur_w = ur_w; break; }
+ }
+
+ if (jcp.is_1stconv) {
+ auto src_tag = pick(ndims - 3, ncw, nchw, ncdhw);
+ if (src_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(src_md, src_tag));
+ jcp.src_tag = src_tag;
+ } else {
+ jcp.src_tag = src_d.matches_one_of_tag(src_tag);
+ if (jcp.ic == 1 && jcp.src_tag != src_tag)
+ jcp.src_tag = src_d.matches_one_of_tag(
+ pick(ndims - 3, nwc, nhwc, ndhwc));
+ }
+ if (jcp.src_tag == format_tag::undef)
+ return status::unimplemented;
+
+ const bool src_ok = true
+ && utils::everyone_is(data_type::f32,
+ src_d.data_type(), diff_weights_d.data_type(),
+ diff_dst_d.data_type())
+ && one_of(jcp.ic, 1, 2, 3)
+ && jcp.ngroups == 1;
+ if (!src_ok)
+ return status::unimplemented;
+
+ const int tr_ld = rnd_up(div_up(jcp.iw + jcp.l_pad + jcp.r_pad,
+ jcp.stride_w), 16);
+ const int kh_step = nstl::max((28 - jcp.with_bias) / jcp.kw, 1);
+ const int kh_step_rem = jcp.kh % kh_step;
+
+ const auto wei_4fma_tag = with_groups
+ ? pick(ndims - 3, gOiw16o, gOihw16o, gOidhw16o)
+ : pick(ndims - 3, Oiw16o, Oihw16o, Oidhw16o);
+
+ auto current_wei_tag = format_tag::undef;
+ if (diff_weights_d.format_kind() != format_kind::any)
+ current_wei_tag = diff_weights_d.matches_one_of_tag(wei_4fma_tag);
+
+ const bool use_4fma = true
+ && one_of(ndims, 3, 4)
+ && mayiuse(avx512_mic_4ops)
+ && mkldnn_thr_syncable()
+ && everyone_is(0, jcp.dilate_d, jcp.dilate_h, jcp.dilate_w)
+ && everyone_is(0, jcp.l_pad, jcp.r_pad, jcp.t_pad, jcp.b_pad)
+ && jcp.kw <= 28 - jcp.with_bias
+ && jcp.stride_w == 4
+ && tr_ld / jcp.simd_w <= 4 /* [bwd_w:tr_src:r1] */
+ && IMPLICATION(jcp.with_bias, kh_step_rem == 1) /* [bwd_w:b:r1] */
+ && IMPLICATION(diff_weights_d.format_kind() != format_kind::any,
+ current_wei_tag == wei_4fma_tag);
+
+ if (use_4fma) {
+ jcp.ver = ver_4fma;
+ jcp.kh_step = kh_step;
+ jcp.tr_ld = tr_ld;
+ jcp.ic_block = 1;
+ if (diff_weights_d.format_kind() == format_kind::any)
+ CHECK(memory_desc_init_by_tag(diff_weights_md, wei_4fma_tag));
+ jcp.wei_tag = wei_4fma_tag;
+ } else {
+ jcp.ver = ver_fma;
+ jcp.ic_block = jcp.ic;
+
+ wei_tag = with_groups
+ ? pick(ndims - 3, gOwi16o, gOhwi16o, gOdhwi16o)
+ : pick(ndims - 3, Owi16o, Ohwi16o, Odhwi16o);
+
+ if (diff_weights_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(diff_weights_md, wei_tag));
+ jcp.wei_tag = wei_tag;
+ } else {
+ jcp.wei_tag = diff_weights_d.matches_one_of_tag(wei_tag);
+ }
+ if (jcp.wei_tag != wei_tag)
+ return status::unimplemented;
+ }
+
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+ } else {
+ auto src_tag = pick(ndims - 3, nCw16c, nChw16c, nCdhw16c);
+ if (src_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(src_md, src_tag));
+ jcp.src_tag = src_tag;
+ } else {
+ jcp.src_tag = src_d.matches_one_of_tag(src_tag);
+ }
+ if (jcp.src_tag != src_tag)
+ return status::unimplemented;
+
+ if (diff_weights_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(diff_weights_md, wei_tag));
+ jcp.wei_tag = wei_tag;
+ } else {
+ jcp.wei_tag = diff_weights_d.matches_one_of_tag(wei_tag);
+ }
+ if (jcp.wei_tag != wei_tag)
+ return status::unimplemented;
+
+ jcp.ic_block = jcp.simd_w;
+ if (ok_to_pad_channels)
+ jcp.ic = rnd_up(jcp.ic, jcp.ic_block);
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+ if ((mayiuse(avx512_mic) || mayiuse(avx512_core))
+ && utils::everyone_is(data_type::f32,
+ src_d.data_type(), diff_weights_d.data_type(),
+ diff_dst_d.data_type())) {
+ jcp.ver = ver_fma;
+ if (one_of(ndims, 3, 4) && mayiuse(avx512_mic_4ops) && jcp.stride_w == 1 &&
+ everyone_is(0, jcp.dilate_d, jcp.dilate_h, jcp.dilate_w) &&
+ mkldnn_thr_syncable()) {
+ jcp.ver = ver_4fma;
+ }
+ } else {
+ return status::unimplemented;
+ }
+ if (jcp.ver == ver_4fma) {
+ jcp.ur_w = jcp.ow;
+ // XXX, BUGBUGBUG, but not a FIXME: this assumes that it's OK to
+ // cross the right boundary. The only requirement is not to have
+ // NaNs there because another multiplicand is always guaranteed to
+ // be zero. This also may require the top-level driver to allocate
+ // four extra guarding elements at the very end of the buffer.
+ // I'm not proud of this hack, but it improves performance by
+ // about 5-10% depending on the dimensions (Roma)
+
+ const int tr_round = 4;
+
+ jcp.tr_iw = rnd_up(jcp.iw + jcp.kw - 1, tr_round);
+ jcp.tr_src_num_guard_elems = tr_round; // upper bound
+ }
+ }
+
+ if (utils::one_of(jcp.ver, ver_4fma, ver_fma)) {
+ jcp.typesize_in = sizeof(float);
+ jcp.typesize_out = sizeof(float);
+ } else
+ return status::unimplemented;
+
+ bool args_ok = true
+ && jcp.ic % jcp.ic_block == 0
+ && jcp.oc % jcp.oc_block == 0
+ && jcp.ic <= src_d.padded_dims()[1]
+ && jcp.oc <= diff_dst_d.padded_dims()[1]
+ && jcp.ic <= diff_weights_d.padded_dims()[with_groups + 1]
+ && jcp.oc <= diff_weights_d.padded_dims()[with_groups + 0];
+ if (!args_ok) return status::unimplemented;
+
+ { // balancing
+ int nthr, nthr_mb, nthr_g, nthr_oc_b, nthr_ic_b;
+ balance(jcp, nthr, nthr_mb, nthr_g, nthr_oc_b, nthr_ic_b);
+ jcp.nthr = nthr;
+ jcp.nthr_mb = nthr_mb;
+ jcp.nthr_g = nthr_g;
+ jcp.nthr_oc_b = nthr_oc_b;
+ jcp.nthr_ic_b = nthr_ic_b;
+ }
+
+ return status::success;
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) {
+ if (jcp.ver == ver_4fma) {
+ if (jcp.is_1stconv) {
+ const size_t tr_src_size =
+ jcp.nthr / jcp.nthr_oc_b * jcp.ih * jcp.stride_w * jcp.tr_ld;
+ scratchpad.book(key_conv_tr_src, jcp.typesize_in * tr_src_size);
+ } else {
+ // XXX: See the comment about tr_iw and guarding elements in
+ // jit_avx512_common_conv_bwd_weights_kernel_f32::init_conf()
+ const size_t max_nthr = jcp.nthr_mb * jcp.ngroups * jcp.nb_ic;
+ const size_t min_tr_src_size_per_thr
+ = jcp.ih * jcp.ic_block * jcp.tr_iw;
+ const size_t tr_src_size = max_nthr * min_tr_src_size_per_thr
+ + jcp.tr_src_num_guard_elems;
+ scratchpad.book(key_conv_tr_src, jcp.typesize_in * tr_src_size);
+ }
+
+ /* prepare synchronization contexts */
+ if (jcp.nthr_oc_b > 1) {
+ const int tr_src_bctx_size = jcp.nthr / jcp.nthr_oc_b;
+ scratchpad.book(key_conv_tr_src_bctx,
+ sizeof(simple_barrier::ctx_t) * tr_src_bctx_size);
+ }
+ }
+
+ if (jcp.nthr_mb > 1) {
+ const int wei_size = jcp.ngroups * jcp.oc * jcp.ic
+ * jcp.kh * jcp.kw * jcp.kd;
+ const int bia_size = jcp.ngroups * jcp.oc;
+ const size_t wei_bia_reduction_size = wei_size + bia_size;
+
+ scratchpad.book(key_conv_wei_bia_reduction,
+ jcp.typesize_out * wei_bia_reduction_size * (jcp.nthr_mb - 1));
+ scratchpad.book(key_conv_wei_bia_reduction_bctx,
+ sizeof(simple_barrier::ctx_t));
+ }
+
+ if (jcp.with_bias && jcp.oc != jcp.oc_without_padding)
+ scratchpad.book(key_conv_padded_bias, jcp.typesize_out * jcp.oc);
+}
+
+void jit_avx512_common_conv_bwd_weights_kernel_f32::balance(
+ const jit_conv_conf_t &j, int &nthr_, int &nthr_mb_, int &nthr_g_,
+ int &nthr_oc_b_, int &nthr_ic_b_)
+{
+ nthr_ = nthr_mb_ = nthr_g_ = nthr_oc_b_ = nthr_ic_b_ = 1;
+
+ const int max_threads = mkldnn_get_max_threads();
+
+ if (max_threads < j.ngroups) {
+ /* simplification... fortunately it doesn't hurt much */
+ return;
+ }
+
+ if (!mkldnn_thr_syncable() && j.ver == ver_4fma) {
+ // should not happen -- the driver is not ready
+ // for TBB-like non-synchronous threading yet
+ return;
+ }
+
+ if (j.ver == ver_4fma && j.is_1stconv) {
+ nthr_g_ = 1;
+ nthr_oc_b_ = 1;
+ nthr_ic_b_ = nstl::min(j.nb_ic, max_threads);
+ nthr_mb_ = nstl::min(max_threads / nthr_ic_b_, j.mb);
+ nthr_ = nthr_mb_ * nthr_oc_b_ * nthr_ic_b_ * nthr_g_;
+ return;
+ }
+
+ nthr_g_ = j.ngroups;
+ const int nthr = max_threads / nthr_g_;
+
+ auto calc_mem_cost = [=](int nthr_mb, int nthr_oc_b, int nthr_ic_b) {
+ /* calculate per thread memory cost (read/write). high level optimizer
+ * tries to minimize memory consumption. few notes:
+ * (n1) unclear why, but that essentially helps first convolution...
+ * (n2) assuming the reduction over minibatch is always there:
+ * - instead of 8 it should be 5 here (write ~= 2 read):
+ * kernel: temporal workspace 1 write
+ * reduction: 1 read from workspace and 1 write to the diff_wei
+ * - but experiments showed 8 works better than 5 or 6... */
+
+ const int src_coef = j.ver == ver_4fma ? 4 : 1;
+ const int dst_coef = 1;
+ const int wei_coef = 8;
+
+ return 0
+ + src_coef
+ * div_up(j.mb, nthr_mb) * div_up(j.ngroups, nthr_g_)
+ * div_up(j.nb_ic, nthr_ic_b) * j.ic_block * j.ih * j.iw * j.id
+ / j.stride_d / j.stride_h / j.stride_w /* (n1) */
+ + dst_coef
+ * div_up(j.mb, nthr_mb) * div_up(j.ngroups, nthr_g_)
+ * div_up(j.nb_oc, nthr_oc_b) * j.oc_block * j.oh * j.ow * j.od
+ + wei_coef /* (n2) */
+ * div_up(j.ngroups, nthr_g_)
+ * div_up(j.nb_oc, nthr_oc_b) * div_up(j.nb_ic, nthr_ic_b)
+ * j.kh * j.kw * j.kd * j.ic_block * j.oc_block;
+ };
+
+ int best_mem_cost = calc_mem_cost(nthr_mb_, nthr_oc_b_, nthr_ic_b_);
+
+ /* step 1: find the best thread distribution with lowest memory cost */
+ const int nthr_mb_max = nstl::min(nthr, j.mb * j.od);
+ for (int nthr_mb = 1; nthr_mb <= nthr_mb_max; ++nthr_mb) {
+ const int nthr_par = nthr / nthr_mb;
+ const int nthr_oc_b_max = nstl::min(nthr_par, j.nb_oc);
+ for (int nthr_oc_b = 1; nthr_oc_b <= nthr_oc_b_max; ++nthr_oc_b) {
+ int nthr_ic_b = nstl::min(nthr_par / nthr_oc_b, j.nb_ic);
+
+ int mem_cost = calc_mem_cost(nthr_mb, nthr_oc_b, nthr_ic_b);
+ if (mem_cost <= best_mem_cost) {
+ best_mem_cost = mem_cost;
+ nthr_mb_ = nthr_mb;
+ nthr_oc_b_ = nthr_oc_b;
+ nthr_ic_b_ = nthr_ic_b;
+ }
+ }
+
+ if (!mkldnn_thr_syncable()) { assert(nthr_mb == 1); break; }
+ }
+
+ if (!mayiuse(avx512_mic)) {
+ auto calc_comp_cost = [=](int nthr_mb, int nthr_oc_b, int nthr_ic_b) {
+ return 1
+ * div_up(j.mb, nthr_mb)
+ * div_up(j.ngroups, nthr_g_)
+ * div_up(j.nb_oc, nthr_oc_b)
+ * div_up(j.nb_ic, nthr_ic_b);
+ };
+
+ /* step 2: search for a thread distribution with lower compute cost.
+ * the constrains:
+ * - memory cost cannot exceed 110% of the best found in the step 1
+ * - unless compute cost is 133% lower than the current best case
+ * note: both constants were found empirically */
+ int best_comp_cost = calc_comp_cost(nthr_mb_, nthr_oc_b_, nthr_ic_b_);
+ for (int nthr_mb = 1; nthr_mb <= nthr_mb_max; ++nthr_mb) {
+ const int nthr_par = nthr / nthr_mb;
+ const int nthr_oc_b_max = nstl::min(nthr_par, j.nb_oc);
+ for (int nthr_oc_b = 1; nthr_oc_b <= nthr_oc_b_max; ++nthr_oc_b) {
+ int nthr_ic_b = nstl::min(nthr_par / nthr_oc_b, j.nb_ic);
+ int mem_cost = calc_mem_cost(nthr_mb, nthr_oc_b, nthr_ic_b);
+ int comp_cost = calc_comp_cost(nthr_mb, nthr_oc_b, nthr_ic_b);
+
+ const bool opt1 = comp_cost <= best_comp_cost
+ && mem_cost < 1.1 * best_mem_cost;
+ const bool opt2 = 4 * comp_cost <= 3 * best_comp_cost;
+
+ if (opt1 || opt2) {
+ best_comp_cost = comp_cost;
+ nthr_mb_ = nthr_mb;
+ nthr_oc_b_ = nthr_oc_b;
+ nthr_ic_b_ = nthr_ic_b;
+ }
+ }
+
+ if (!mkldnn_thr_syncable()) { assert(nthr_mb == 1); break; }
+ }
+ }
+
+ if (nthr_mb_ > max_threads/2 && nthr_mb_ < max_threads)
+ nthr_mb_ = nstl::min(j.mb * j.od, max_threads);
+ nthr_ = nthr_mb_ * nthr_g_ * nthr_oc_b_ * nthr_ic_b_;
+
+ assert(nthr_ <= max_threads);
+ assert(IMPLICATION(!mkldnn_thr_syncable(), nthr_mb_ == 1));
+}
+
+template struct _jit_avx512_common_conv_fwd_kernel<Zmm>;
+template struct _jit_avx512_common_conv_fwd_kernel<Xmm>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.hpp
new file mode 100644
index 0000000000..f76770797a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.hpp
@@ -0,0 +1,423 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_AVX512_COMMON_CONV_KERNEL_F32_HPP
+#define JIT_AVX512_COMMON_CONV_KERNEL_F32_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+#include "jit_uni_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template<typename Vmm>
+struct _jit_avx512_common_conv_fwd_kernel : public jit_generator {
+
+ _jit_avx512_common_conv_fwd_kernel(jit_conv_conf_t ajcp,
+ const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr)
+ {
+ if (jcp.with_eltwise)
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<avx512_common>(
+ this, jcp.eltwise);
+
+ generate();
+ jit_ker_ = (void (*)(jit_conv_call_s *))getCode();
+ }
+
+ ~_jit_avx512_common_conv_fwd_kernel() {
+ delete eltwise_injector_;
+ }
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(_jit_avx512_common_conv_fwd_kernel)
+
+ jit_conv_conf_t jcp;
+ const primitive_attr_t &attr_;
+ void (*jit_ker_)(jit_conv_call_s *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ enum {
+ typesize = sizeof(float),
+ ker_reg_base_idx = 28,
+ };
+
+ reg64_t param = abi_param1;
+ reg64_t reg_inp = r8;
+ reg64_t reg_ker = r9;
+ reg64_t reg_out = r10;
+
+ reg64_t reg_inp_prf = r11;
+ reg64_t reg_ker_prf = r12;
+ reg64_t reg_out_prf = r13;
+ reg64_t reg_owb = r12;
+
+ reg64_t aux_reg_inp = r14;
+ reg64_t aux_reg_ker = r15;
+
+ reg64_t aux_reg_inp_prf = rsi;
+ reg64_t aux_reg_ker_prf = rdx;
+
+ reg64_t reg_channel = rsi;
+ reg64_t reg_bias = rdx;
+
+ reg64_t aux_reg_ker_d = r9;
+ reg64_t aux_reg_inp_d = rbx;
+ reg64_t aux_reg_inp_d_prf = r13;
+ reg64_t aux_reg_ker_d_prf = abi_not_param1;
+ reg64_t reg_ki = r10;
+
+ reg64_t reg_kj = rax;
+ reg64_t reg_relu_ns = rax;
+ reg64_t reg_oi = rbx;
+ reg64_t reg_kh = abi_not_param1;
+
+ reg64_t reg_tmp = rbp;
+
+ reg64_t reg_ic_loop = rdx;
+ reg64_t reg_inp_loop = rsi;
+
+ reg64_t reg_init_flag = r13;
+ reg64_t reg_bias_ptr = param;
+
+ reg64_t aux_reg_ic = r12;
+ reg64_t reg_binp = rax;
+ reg64_t reg_bout = r11;
+ reg64_t aux1_reg_inp = rbx;
+ reg64_t aux_reg_out = abi_not_param1;
+
+ reg64_t reg_long_offt = r11;
+ reg64_t reg_out_long_offt = r14;
+
+ inline Vmm vmm_ker(int i_ic) {
+ assert(i_ic < 4);
+ return Vmm(ker_reg_base_idx + i_ic);
+ }
+
+ inline Vmm vmm_out(int i_ur, int i_oc) {
+ int idx = i_ur + i_oc * jcp.ur_w;
+ assert(idx < ker_reg_base_idx);
+ return Vmm(idx);
+ }
+
+ inline Vmm vmm_inp(int i_ic, int nb_x_blocking) {
+ int idx = i_ic + nb_x_blocking * jcp.ur_w;
+ assert(idx < 31);
+ return Vmm(idx);
+ }
+
+ Xbyak::Reg64 imm_addr64 = r15;
+ Vmm vmm_wei = Vmm(31);
+
+ jit_uni_eltwise_injector_f32<avx512_common> *eltwise_injector_;
+
+ inline void prepare_output(int ur_w);
+ inline void store_output(int ur_w);
+ inline void compute_loop_fma(int ur_w, int pad_l, int pad_r);
+ inline void compute_loop_fma_core(int ur_w, int pad_l, int pad_r);
+ inline void compute_loop_4fma(int ur_w, int pad_l, int pad_r);
+ inline void compute_loop_4fma_1st(int ur_w, int pad_l, int pad_r);
+ inline void compute_loop(int ur_w, int pad_l, int pad_r);
+
+ void generate();
+
+ inline size_t get_output_offset(int oi, int n_oc_block) {
+ return (size_t)jcp.typesize_out * ((size_t)n_oc_block * jcp.oh
+ * jcp.ow * jcp.od + oi) * jcp.oc_block;
+ }
+
+ inline size_t get_input_offset(int ki, int ic, int oi, int pad_l) {
+ size_t iw_str = !jcp.is_1stconv ? jcp.ic_block : 1;
+ size_t ic_str = !jcp.is_1stconv ? 1 : (size_t)jcp.iw * jcp.ih * jcp.id;
+ return (size_t)jcp.typesize_in * ((size_t)(ki * (jcp.dilate_w + 1)
+ + oi * jcp.stride_w - pad_l) * iw_str + ic * ic_str);
+ }
+
+ inline int get_kernel_offset(int ki,int ic,int n_oc_block,int ker_number) {
+ return jcp.typesize_in * jcp.oc_block
+ * (n_oc_block * jcp.nb_ic * jcp.ic_block * jcp.kh * jcp.kw * jcp.kd
+ + (ic + ker_number) + ki * jcp.ic_block);
+ }
+
+ inline int get_ow_start(int ki, int pad_l) {
+ return nstl::max(0,
+ utils::div_up(pad_l - ki * (jcp.dilate_w + 1), jcp.stride_w));
+ }
+
+ inline int get_ow_end(int ur_w, int ki, int pad_r) {
+ return ur_w - nstl::max(0, utils::div_up(pad_r
+ - (jcp.kw - 1 - ki)
+ * (jcp.dilate_w + 1),
+ jcp.stride_w));
+ }
+};
+
+struct jit_avx512_common_conv_fwd_kernel {
+
+ jit_avx512_common_conv_fwd_kernel(jit_conv_conf_t ajcp,
+ const primitive_attr_t &attr) :
+ jit_ker(nullptr),
+ zmm_kernel_(nullptr),
+ xmm_kernel_(nullptr) {
+ int ch_block = ajcp.is_depthwise ? ajcp.ch_block : ajcp.oc_block;
+ switch (ch_block) {
+ case 16:
+ zmm_kernel_ =
+ new _jit_avx512_common_conv_fwd_kernel<Xbyak::Zmm>(
+ ajcp, attr);
+ jit_ker = zmm_kernel_->jit_ker_;
+ return;
+ case 4:
+ xmm_kernel_ =
+ new _jit_avx512_common_conv_fwd_kernel<Xbyak::Xmm>(
+ ajcp, attr);
+ jit_ker = xmm_kernel_->jit_ker_;
+ return;
+ default:
+ assert(!"invalid channel blocking");
+ }
+ }
+
+ ~jit_avx512_common_conv_fwd_kernel() {
+ delete xmm_kernel_;
+ delete zmm_kernel_;
+ }
+
+ enum {
+ typesize = sizeof(float)
+ };
+
+ static bool post_ops_ok(jit_conv_conf_t &jcp,
+ const primitive_attr_t &attr);
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd,
+ memory_desc_t &src_pd,
+ memory_desc_t &weights_pd,
+ memory_desc_t &dst_pd,
+ memory_desc_t &bias_pd,
+ const primitive_attr_t &attr,
+ int nthreads);
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp);
+
+ void(*jit_ker)(jit_conv_call_s *);
+ _jit_avx512_common_conv_fwd_kernel<Xbyak::Zmm> *zmm_kernel_;
+ _jit_avx512_common_conv_fwd_kernel<Xbyak::Xmm> *xmm_kernel_;
+};
+
+struct jit_avx512_common_conv_bwd_data_kernel_f32: public jit_generator {
+
+ jit_avx512_common_conv_bwd_data_kernel_f32(jit_conv_conf_t ajcp): jcp(ajcp)
+ {
+ generate();
+ jit_ker = (void (*)(jit_conv_call_s *))getCode();
+ }
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_conv_bwd_data_kernel_f32)
+
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd,
+ const memory_desc_wrapper &diff_src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &diff_dst_d);
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp);
+
+ jit_conv_conf_t jcp;
+ void (*jit_ker)(jit_conv_call_s *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ enum {
+ typesize = sizeof(float),
+ ker_reg_base_idx = 28,
+ };
+
+ reg64_t param = abi_param1;
+ reg64_t reg_dst = r8;
+ reg64_t reg_ker = r9;
+ reg64_t reg_src = r10;
+
+ reg64_t reg_dst_prf = r11;
+ reg64_t reg_ker_prf = r12;
+ reg64_t reg_src_prf = r13;
+
+ reg64_t aux_reg_dst = r14;
+ reg64_t aux_reg_ker = r15;
+
+ reg64_t aux_reg_dst_prf = rsi;
+ reg64_t aux_reg_ker_prf = rdx;
+
+ reg64_t aux_reg_dst_d_prf = r13;
+ reg64_t aux_reg_dst_d = rbx;
+ reg64_t aux_reg_ker_d_prf = abi_not_param1;
+ reg64_t aux_reg_ker_d = r9;
+ reg64_t reg_ki = r10;
+
+ reg64_t reg_kj = rax;
+ reg64_t reg_oi = rbx;
+ reg64_t reg_kh = abi_not_param1;
+
+ reg64_t reg_channel = rsi;
+
+ reg64_t reg_tmp = rbp;
+ reg64_t reg_long_offt = r14;
+
+ inline Xbyak::Zmm zmm_ker(int i_ic) {
+ assert(i_ic < 4);
+ return Xbyak::Zmm(ker_reg_base_idx + i_ic);
+ }
+ inline Xbyak::Zmm zmm_inp(int i_ic, int nb_x_blocking) {
+ int idx = i_ic + nb_x_blocking * jcp.ur_w;
+ assert(idx < 31);
+ return Xbyak::Zmm(idx);
+ }
+ inline Xbyak::Zmm zmm_out(int i_ur, int i_oc) {
+ int idx = i_ur + i_oc * jcp.ur_w;
+ assert(idx < ker_reg_base_idx);
+ return Xbyak::Zmm(idx);
+ }
+
+ Xbyak::Zmm zmm_wei = Xbyak::Zmm(31);
+
+ inline void prepare_output(int ur_w);
+ inline void store_output(int ur_w);
+ inline void compute_loop_4fma(int ur_w, int l_overflow, int r_overflow);
+ inline void compute_loop_fma(int ur_w, int l_overflow, int r_overflow);
+ inline void compute_loop_fma_core(int ur_w, int l_overflow, int r_overflow);
+ inline void compute_loop(int ur_w, int l_overflow, int r_overflow);
+ void generate();
+
+ inline int get_iw_start(int ki, int l_overflow)
+ {
+ int res = (jcp.iw - 1 + jcp.r_pad) % jcp.stride_w
+ + l_overflow * jcp.stride_w
+ - (jcp.kw - 1 - ki) * (jcp.dilate_w + 1);
+ while (res < 0)
+ res += jcp.stride_w;
+
+ return res;
+ }
+
+ inline int get_iw_end(int ur_w, int ki, int r_overflow)
+ {
+ if (utils::one_of(ur_w, jcp.iw, jcp.ur_w_tail))
+ ur_w += nstl::min(0, jcp.r_pad); // remove negative padding
+ int res = (ur_w - 1 + jcp.l_pad) % jcp.stride_w
+ + r_overflow * jcp.stride_w - ki * (jcp.dilate_w + 1);
+ while (res < 0)
+ res += jcp.stride_w;
+
+ return ur_w - res;
+ }
+};
+
+struct jit_avx512_common_conv_bwd_weights_kernel_f32 : public jit_generator {
+
+ jit_avx512_common_conv_bwd_weights_kernel_f32(jit_conv_conf_t ajcp)
+ : jcp(ajcp)
+ {
+ generate();
+ jit_ker = (void (*)(jit_conv_call_s *))getCode();
+ }
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_conv_bwd_weights_kernel_f32)
+
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd,
+ memory_desc_t &src_md,
+ memory_desc_t &diff_weights_md,
+ memory_desc_t &diff_bias_md,
+ memory_desc_t &diff_dst_md);
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp);
+
+ jit_conv_conf_t jcp;
+ void (*jit_ker)(jit_conv_call_s *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ enum {typesize = sizeof(float)};
+ static const int max_ur_w;
+
+ reg64_t param = abi_param1;
+ reg64_t reg_input = rax;
+ reg64_t reg_kernel = rdx;
+ reg64_t reg_output = rsi;
+ reg64_t b_ic = abi_not_param1;
+ reg64_t kj = r8;
+ reg64_t reg_kh = r9;
+ reg64_t reg_ur_w_trips = r10;
+ reg64_t reg_oj = r15;
+ reg64_t reg_ih_count = rbx;
+ reg64_t reg_tmp = r14;
+ reg64_t reg_long_offt = r14;
+
+ reg64_t ki = r11;
+ reg64_t reg_kd_count = r12;
+ reg64_t reg_oi = r12;
+ reg64_t reg_d_index = r13;
+ reg64_t reg_input_d = r15;
+ reg64_t reg_output_d = rbx;
+ reg64_t aux_reg_input = r12;
+ reg64_t aux_reg_kernel = r13;
+ reg64_t reg_bias = rbx;
+
+ inline void bias_kernel();
+ inline void maybe_zero_kernel();
+ inline void compute_oh_step_unroll_ow_icblock(int ic_block_step,
+ int max_ur_w);
+ inline void od_step_comeback_pointers();
+ inline void oh_step_comeback_pointers();
+ inline void compute_oh_step_unroll_ow(int ic_block_step, int max_ur_w);
+ inline void compute_ic_block_step(int ur_w,
+ int pad_l, int pad_r, int ic_block_step,
+ int input_offset, int kernel_offset, int output_offset,
+ bool input_wraparound = false);
+ inline void compute_ic_block_step_fma(int ur_w,
+ int pad_l, int pad_r, int ic_block_step,
+ int input_offset, int kernel_offset, int output_offset,
+ bool input_wraparound);
+ inline void compute_ic_block_step_4fma(int ur_w,
+ int pad_l, int pad_r, int ic_block_step,
+ int input_offset, int kernel_offset, int output_offset,
+ bool input_wraparound);
+ inline void compute_oh_step_common(int ic_block_step, int max_ur_w);
+ inline void compute_oh_step_disp();
+ inline void compute_oh_loop_common();
+ inline void compute_d_loop_common();
+
+ inline bool compute_full_spat_loop();
+ inline bool flat_4ops_compute();
+
+ inline void compute_loop();
+
+ void generate();
+
+ static void balance(const jit_conv_conf_t &j, int &nthr, int &nthr_mb,
+ int &nthr_g, int &nthr_oc_b, int &nthr_ic_b);
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.cpp
new file mode 100644
index 0000000000..1bdcd0d6a8
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.cpp
@@ -0,0 +1,1163 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+#include "cpu_memory.hpp"
+
+#include <math.h>
+
+#include "jit_avx512_common_conv_winograd_kernel_f32.hpp"
+
+#ifndef KERNEL_SIZE_THRESHOLD
+#define KERNEL_SIZE_THRESHOLD 16
+#endif
+
+#define MIN_REQUIRED_DIMN_REG_BLOCK 14
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace {
+
+using namespace mkldnn::impl::utils;
+
+unsigned int L1_cache_size = get_cache_size(1, true);
+unsigned int L2_cache_size = get_cache_size(2, true);
+unsigned int LLC_data_size = get_cache_size(3, false);
+
+// the test funtion takes jcp, the candidate and the current best.
+// it returns true if the new candidate is better
+int get_divisor_satisfying_cond(jit_conv_winograd_conf_t &jcp, int number,
+ int default_best, bool (*test)(jit_conv_winograd_conf_t &, int, int))
+{
+ int best_divisor = default_best;
+ auto test_num
+ = [&best_divisor, test](jit_conv_winograd_conf_t &jcp, int num) {
+ if (test(jcp, num, best_divisor)) {
+ best_divisor = num;
+ }
+ };
+
+ for (int divisor = 1; divisor <= ::sqrt(number); divisor++) {
+ if (number % divisor == 0) {
+ test_num(jcp, divisor);
+ test_num(jcp, number / divisor);
+ }
+ }
+
+ return best_divisor;
+}
+
+namespace {
+bool is_winograd_faster_than_direct(const jit_conv_winograd_conf_t &jcp) {
+ if (jcp.ver == ver_4fma)
+ return jcp.mb >= 32;
+ else
+ return jcp.mb >= 16;
+}
+}
+
+/* assumes 512 bits registers */
+/* TODO: add support for strides */
+/* TODO: handle the prefetch distance automatically */
+typedef enum cache_t_ { L1, L2, L3 } cache_t;
+
+template <typename data_t>
+struct prefetcher_t {
+ prefetcher_t(jit_generator *generator, Xbyak::Reg64 reg_base_addr,
+ cache_t cache_type, size_t block_size, /* in number of elements*/
+ int nb_instructions_in_block, int fma_ipc)
+ : cg_(generator)
+ , reg_base_addr_(reg_base_addr)
+ , cache_type_(cache_type)
+ , cache_block_size_(block_size)
+ {
+ nb_cache_lines_to_prefetch_ = cache_block_size_ / (64 / sizeof(data_t));
+ prefetch_spread_
+ = div_up(nb_instructions_in_block, nb_cache_lines_to_prefetch_);
+ prefetch_blk_
+ = div_up(nb_cache_lines_to_prefetch_, nb_instructions_in_block);
+
+ /* assumption: when fetch in Li, data is already in L(i+1) */
+ int cache_latency;
+ switch (cache_type_) {
+ case L1: cache_latency = 14; break;
+ case L2:
+ case L3:
+ default: cache_latency = 250; break;
+ }
+
+ prefetch_distance_ = div_up(cache_latency, nb_cache_lines_to_prefetch_);
+ }
+
+ void prefetch(int instruction_number)
+ {
+ if (instruction_number % prefetch_spread_ == 0) {
+ for (int i = 0; (i < prefetch_blk_)
+ && (prefetches_issued_ < nb_cache_lines_to_prefetch_);
+ i++, prefetches_issued_++) {
+ prefetch_inst_(cg_->EVEX_compress_addr(
+ reg_base_addr_, (cache_block_size_ * prefetch_distance_)
+ * sizeof(data_t)
+ + (prefetches_issued_ * 64)));
+ }
+ }
+ }
+
+private:
+ void prefetch_inst_(const Xbyak::Address &addr)
+ {
+ switch (cache_type_) {
+ case L1: cg_->prefetcht0(addr); break;
+ case L2: cg_->prefetcht1(addr); break;
+ case L3: cg_->prefetcht2(addr); break;
+ default:
+ break; // TODO: raise an exception or put an assert
+ }
+ }
+
+ jit_generator *cg_;
+ Xbyak::Reg64 reg_base_addr_;
+ cache_t cache_type_;
+ int cache_block_size_ = 0;
+ int nb_cache_lines_to_prefetch_ = 0;
+ int prefetches_issued_ = 0;
+ int prefetch_spread_ = 0;
+ int prefetch_blk_ = 0;
+ int prefetch_distance_ = 0;
+};
+
+// utilities to support kernel parameter selection
+bool check_cond1(int dimN_reg_block, int dimK_block, int dimK_reg_block,
+ int dimM_block, int dimM_simd_block, float C)
+{
+ float lhs = (dimM_block * dimN_reg_block * dimM_simd_block
+ + dimM_block * dimK_block * dimK_reg_block
+ * dimM_simd_block
+ + dimK_block * dimN_reg_block * dimK_reg_block)
+ * (float)sizeof(float);
+ float rhs = C * L1_cache_size;
+ return (lhs < rhs);
+}
+
+bool check_cond1_bis(int dimN_reg_block, int dimK_block, int dimK_reg_block,
+ int dimM_block, int dimM_simd_block, float C)
+{
+ float lhs = (dimM_block * dimK_block * dimK_reg_block * dimM_simd_block
+ + dimK_block * dimN_reg_block * dimK_reg_block)
+ * (float)sizeof(float);
+ float rhs = C * L1_cache_size;
+ return (lhs < rhs);
+}
+
+bool check_cond2(int nb_dimN_reg_block, int dimN_reg_block, int dimK_nb_block,
+ int dimK_block, int dimK_reg_block, int dimM_block, int dimM_simd_block,
+ float C)
+{
+ float lhs = (nb_dimN_reg_block * dimM_block * dimN_reg_block * dimM_simd_block
+ + dimK_nb_block * dimM_block * dimK_block * dimK_reg_block
+ * dimM_simd_block
+ + nb_dimN_reg_block * dimK_nb_block * dimK_block
+ * dimN_reg_block * dimK_reg_block)
+ * (float)sizeof(float);
+ float rhs = C * L2_cache_size;
+ return (lhs < rhs);
+}
+}
+
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::utils;
+using namespace Xbyak;
+
+void _jit_avx512_common_conv_winograd_data_kernel_f32::gemm_loop_generate(
+ bool is_beta_zero)
+{
+ // const int dimK_simd_block = jcp.dimK_reg_block;
+
+ // for (int dimM_block =0; dimM_block < jcp.dimM_block; dimM_block++)
+ // for (int dimK_block = 0; dimK_block < jcp.dimK_block; dimK_block++)
+ // for (int dimK_reg_block= 0; dimK_reg_block < jcp.dimK_reg_block;
+ // dimK_reg_block++)
+ // for (int tile =0; tile < jcp.dimN_reg_block; tile++)
+ // C[dimM_block][tile] +=
+ // A[dimM_block][dimK_block][dimK_reg_block] *
+ // broadcast(B[dimK_block][tile][dimK_reg_block]);
+ // 1) We do register blocking on A[dimM_block][dimK_block][dimK_reg_block],
+ // so we load it before the loop on tile
+ // 2) the loop on tile must be fully unrolled. Don't know about the one on
+ // dimK_reg_block. I think it should be
+
+ auto inner_loops = [=]() {
+ Label dimM_block_loop, dimK_block_loop;
+ const int inc_dimK_reg_block = jcp.ver == ver_4fma ? 4 : 1;
+ const int fma_ipc = jcp.ver == ver_4fma ? 1 : 2;
+
+ prefetcher_t<float> L1_pf(this, reg_srcB, L1,
+ jcp.dimN_reg_block * jcp.dimK_reg_block,
+ jcp.dimK_reg_block * jcp.dimN_reg_block / inc_dimK_reg_block,
+ fma_ipc);
+ prefetcher_t<float> L2_pf(this, reg_srcB, L2,
+ jcp.dimN_reg_block * jcp.dimK_reg_block,
+ jcp.dimK_reg_block * jcp.dimN_reg_block / inc_dimK_reg_block,
+ fma_ipc);
+
+ if (jcp.dimM_block > 1) {
+ mov(reg_dimM_block_loop_cnt, jcp.dimM_block);
+ L(dimM_block_loop);
+ }
+ {
+ // First, we zero the accumulators if first nb_ic iteration,
+ // otherwise we load them
+ for (int tile = 0; tile < jcp.dimN_reg_block; tile++) {
+ Zmm zmm(jcp.zmm_start + tile);
+ if (is_beta_zero)
+ vpxord(zmm, zmm, zmm);
+ else
+ vmovups(zmm, zword[reg_dstC + 64 * tile]);
+ }
+
+ if (jcp.dimK_block > 1) {
+ mov(reg_dimK_block_loop_cnt, jcp.dimK_block);
+ L(dimK_block_loop);
+ }
+ {
+ auto load_A = [=](int reg_idx, int offset) {
+ for (int i = 0; i < inc_dimK_reg_block; i++)
+ vmovups(Zmm(reg_idx + i),
+ zword[reg_srcA + 64 * (offset + i)]);
+ };
+
+ // Used when doing double buffering
+ int next = 0;
+ if (jcp.double_buffering) {
+ load_A(next, 0);
+ }
+ for (int dimK_reg_block = 0;
+ dimK_reg_block < jcp.dimK_reg_block;
+ dimK_reg_block += inc_dimK_reg_block) {
+ int current;
+ /* Loading the next vector from A */
+ current = next;
+ if (jcp.double_buffering) {
+ next = (dimK_reg_block + inc_dimK_reg_block)
+ % (2 * inc_dimK_reg_block);
+ load_A(next, dimK_reg_block + inc_dimK_reg_block);
+ } else {
+ next = 0;
+ load_A(next, dimK_reg_block);
+ }
+ /* Performing the fmas */
+ for (int tile = 0; tile < jcp.dimN_reg_block; tile++) {
+ Zmm zmm(jcp.zmm_start + tile);
+ if (jcp.ver != ver_avx512_core)
+ L1_pf.prefetch(
+ dimK_reg_block * jcp.dimN_reg_block + tile);
+ if (jcp.ver == ver_4fma)
+ v4fmaddps(zmm, Zmm(current),
+ EVEX_compress_addr(reg_srcB,
+ 64 * tile + dimK_reg_block * 4));
+ else
+ vfmadd231ps(zmm, Zmm(current),
+ EVEX_compress_addr(reg_srcB,
+ 64 * tile + dimK_reg_block * 4,
+ true));
+ if (jcp.ver != ver_avx512_core)
+ L2_pf.prefetch(
+ dimK_reg_block * jcp.dimN_reg_block + tile);
+ }
+ }
+
+ add(reg_srcA, jcp.dimK_reg_block * 64);
+ add(reg_srcB, jcp.dimN_reg_block * 64);
+ if (jcp.dimK_block > 1) {
+ sub(reg_dimK_block_loop_cnt, 1);
+ jnz(dimK_block_loop);
+ }
+ }
+
+
+ auto store_output = [=](bool output_is_aligned) {
+ for (int tile = 0; tile < jcp.dimN_reg_block; tile++) {
+ Zmm zmm(jcp.zmm_start + tile);
+ if (output_is_aligned
+ && jcp.dimK_nb_block == 1
+ && (jcp.dimN * jcp.dimM * alpha * alpha
+ * sizeof(float) > 2 * LLC_data_size))
+ vmovntps(zword[reg_dstC + 64 * tile], zmm);
+ else
+ vmovups(zword[reg_dstC + 64 * tile], zmm);
+ }
+ };
+
+ Label unaligned_store, end_store;
+ test(reg_dstC, cpu_isa_traits<avx512_common>::vlen - 1);
+ jnz(unaligned_store, T_NEAR);
+ store_output(true);
+ jmp(end_store, T_NEAR);
+ L(unaligned_store); {
+ store_output(false);
+ }
+ L(end_store);
+
+ if (jcp.dimM_block > 1) {
+ sub(reg_srcB, jcp.dimK_block * jcp.dimN_reg_block * 64);
+ add(reg_dstC, jcp.dimN_reg_block * 64);
+ sub(reg_dimM_block_loop_cnt, 1);
+ jnz(dimM_block_loop);
+ }
+ }
+ };
+
+ /* Preamble */
+ preamble();
+
+ /* kernel */
+ inner_loops();
+
+ /* Postamble */
+ postamble();
+ ret();
+}
+
+status_t _jit_avx512_common_conv_winograd_data_kernel_f32::init_conf_common(
+ jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d)
+{
+
+ if (mayiuse(avx512_core))
+ return status::unimplemented;
+ else if (!mayiuse(avx512_common))
+ return status::unimplemented;
+ else if (mayiuse(avx512_mic_4ops))
+ jcp.ver = ver_4fma;
+ else
+ jcp.ver = ver_fma;
+
+ jcp.nthr = mkldnn_get_max_threads();
+
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.ih = src_d.dims()[2];
+ jcp.iw = src_d.dims()[3];
+ jcp.oh = dst_d.dims()[2];
+ jcp.ow = dst_d.dims()[3];
+ jcp.kh = weights_d.dims()[with_groups + 2];
+ jcp.kw = weights_d.dims()[with_groups + 3];
+ jcp.t_pad = cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][1];
+ jcp.stride_h = cd.strides[0];
+ jcp.stride_w = cd.strides[1];
+ jcp.dilate_h = cd.dilates[0];
+ jcp.dilate_w = cd.dilates[1];
+ jcp.r_pad = nstl::max(
+ 0, (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad);
+ jcp.b_pad = nstl::max(
+ 0, (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad);
+ jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad;
+ jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad;
+ jcp.ohp = jcp.oh;
+ jcp.owp = jcp.ow;
+
+ bool ok_to_pad_channels = jcp.ngroups == 1;
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ jcp.ic = rnd_up(jcp.ic, simd_w);
+ }
+
+ if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto,
+ is_winograd_faster_than_direct(jcp)))
+ return status::unimplemented;
+
+ // Checking conditions not supported by these kernels
+ if (jcp.ngroups != 1)
+ return status::unimplemented;
+ if ((jcp.kh != 3) || (jcp.kw != 3))
+ return status::unimplemented;
+ if ((jcp.dilate_h != 0) || (jcp.dilate_w != 0))
+ return status::unimplemented;
+ if ((jcp.stride_h != 1) || (jcp.stride_w != 1))
+ return status::unimplemented;
+ if ((jcp.ic % simd_w) != 0 || (jcp.oc % simd_w) != 0)
+ return status::unimplemented;
+
+ format_tag_t dat_tag = nChw16c;
+ format_tag_t wei_tag = with_groups ? gOIhw16i16o : OIhw16i16o;
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag);
+ jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag);
+
+ if (jcp.src_tag != dat_tag) return status::unimplemented;
+ if (jcp.wei_tag != wei_tag) return status::unimplemented;
+ if (jcp.dst_tag != dat_tag) return status::unimplemented;
+
+ bool layout_consistency = true
+ && jcp.ic <= src_d.padded_dims()[1]
+ && jcp.oc <= dst_d.padded_dims()[1]
+ && jcp.ic <= weights_d.padded_dims()[with_groups + 1]
+ && jcp.oc <= weights_d.padded_dims()[with_groups + 0];
+ if (!layout_consistency) return status::unimplemented;
+
+ return status::success;
+}
+
+
+status_t set_wsched_DATA_W_S_G_D_avx512_common(jit_conv_winograd_conf_t &jcp) {
+
+ auto test_cond_dimN_reg_block = [](jit_conv_winograd_conf_t &jcp,
+ int dimN_reg_block, int current_best) {
+ return (dimN_reg_block >= MIN_REQUIRED_DIMN_REG_BLOCK)
+ && (dimN_reg_block < jcp.nb_reg)
+ && (dimN_reg_block < current_best);
+ };
+ jcp.dimN_reg_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimN, jcp.dimN, test_cond_dimN_reg_block);
+
+ if (jcp.dimN_reg_block >= jcp.nb_reg) {
+ auto test_cond_dimN_reg_block = [](jit_conv_winograd_conf_t &jcp,
+ int dimN_reg_block, int current_best) {
+ return (dimN_reg_block < jcp.nb_reg)
+ && (dimN_reg_block > current_best);
+ };
+
+ jcp.dimN_reg_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimN, 1, test_cond_dimN_reg_block);
+ }
+
+ //********************* Choosing dimK_block **********************//
+ auto test_cond1_dimK_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) {
+ return check_cond1(jcp.dimN_reg_block, dimK_block, jcp.dimK_reg_block,
+ 1, jcp.dimM_simd_block, .75f)
+ && (dimK_block > current_best);
+ };
+
+ auto test_cond1_bis_dimK_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) {
+ return check_cond1_bis(jcp.dimN_reg_block, dimK_block,
+ jcp.dimK_reg_block, 1, jcp.dimM_simd_block, .9f)
+ && (dimK_block > current_best);
+ };
+
+ jcp.dimK_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimK / jcp.dimK_reg_block, 1, test_cond1_bis_dimK_block);
+ // If we are not able to use streams, we fall back to condition [1]
+ if (jcp.dimK_block < jcp.dimK / jcp.dimK_reg_block)
+ jcp.dimK_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimK / jcp.dimK_reg_block, 1, test_cond1_dimK_block);
+ jcp.dimK_nb_block = (jcp.dimK / jcp.dimK_reg_block) / jcp.dimK_block;
+
+ //********************* Choosing dimM_block **********************//
+ jcp.dimM_simd_block = 16;
+ /*XXX: Why C=0.5 here but C=0.75 for dimK_block?*/
+ auto test_cond1_dimM_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimM_block, int current_best) {
+ return check_cond1(jcp.dimN_reg_block, jcp.dimK_block,
+ jcp.dimK_reg_block, dimM_block, jcp.dimM_simd_block, .5f)
+ && (dimM_block > current_best);
+ };
+
+ auto test_cond1_bis_dimM_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimM_block, int current_best) {
+ return check_cond1_bis(jcp.dimN_reg_block, jcp.dimK_block,
+ jcp.dimK_reg_block, dimM_block, jcp.dimM_simd_block, .3f)
+ && (dimM_block > current_best);
+ };
+
+ if (jcp.dimK_block < jcp.dimK / jcp.dimK_reg_block)
+ jcp.dimM_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimM / jcp.dimM_simd_block, 1, test_cond1_dimM_block);
+ else
+ jcp.dimM_block = get_divisor_satisfying_cond(jcp,
+ jcp.dimM / jcp.dimM_simd_block, 1, test_cond1_bis_dimM_block);
+ jcp.dimM_nb_block = (jcp.dimM / jcp.dimM_simd_block) / jcp.dimM_block;
+
+ //******************* Choosing dimN_block *******************//
+ auto test_cond2_dimN_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimN_block, int current_best) {
+ return check_cond2(dimN_block, jcp.dimN_reg_block, jcp.dimK_nb_block,
+ jcp.dimK_block, jcp.dimK_reg_block, jcp.dimM_block,
+ jcp.dimM_simd_block, .5f)
+ && (dimN_block > current_best);
+ };
+
+ jcp.dimN_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimN / jcp.dimN_reg_block, 1, test_cond2_dimN_block);
+ jcp.dimN_nb_block = jcp.dimN / (jcp.dimN_reg_block * jcp.dimN_block);
+ jcp.sched_policy = WSCHED_DATA_W_S_G_D;
+ return status::success;
+}
+
+status_t _jit_avx512_common_conv_winograd_data_kernel_f32::init_conf_kernel(
+ jit_conv_winograd_conf_t &jcp, int dimM, int dimN, int dimK)
+{
+ jcp.dimK_reg_block = 16;
+ jcp.dimM_simd_block = 16;
+
+ // TODO: replace double buffering with nuple buffering to maximize register
+ // usage.
+ // the choice of the number of buffers will then come after choosing
+ // dimN_reg_block
+ jcp.double_buffering = true;
+ if (jcp.double_buffering)
+ jcp.zmm_start = 2 * ((jcp.ver == ver_4fma) ? 4 : 2);
+ else
+ jcp.zmm_start = 1;
+ jcp.nb_reg = 32 - jcp.zmm_start;
+
+ jcp.dimN = dimN;
+ jcp.dimK = dimK;
+ jcp.dimM = dimM;
+
+ jcp.sched_policy = WSCHED_INVALID;
+ set_wsched_DATA_W_S_G_D_avx512_common(jcp);
+
+ assert(jcp.sched_policy == WSCHED_DATA_W_S_G_D);
+ return status::success;
+}
+
+bool jit_avx512_common_conv_winograd_fwd_kernel_f32::post_ops_ok(
+ jit_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ const auto &p = attr.post_ops_;
+
+ auto is_relu = [&](int idx) { return p.entry_[idx].is_relu(); };
+ auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); };
+
+ switch (p.len_) {
+ case 0: return true; // no post_ops
+ case 1: return is_relu(0) || is_sum(0); // relu or sum
+ case 2: return (is_sum(0) && is_relu(1)) ||
+ (is_relu(0) && is_sum(1)); // sum->relu or relu->sum
+ case 3: return is_relu(0) && is_sum(1) && is_relu(2); // relu->sum->relu
+ default: return false;
+ }
+
+ return false;
+}
+
+status_t jit_avx512_common_conv_winograd_fwd_kernel_f32::init_conf(
+ jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d, const primitive_attr_t &attr) {
+ status_t st = init_conf_common(jcp, cd, src_d, weights_d, dst_d);
+
+ if (st != status::success)
+ return st;
+
+ // Winograd specific initialization
+ jcp.itiles = (jcp.ow + tile_size - 1) / tile_size;
+ jcp.jtiles = (jcp.oh + tile_size - 1) / tile_size;
+ jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles;
+
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ const int eltwise_ind = p.find(primitive_kind::eltwise, 0, 1);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise) jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+ jcp.with_sum = p.find(primitive_kind::sum, 0) != -1;
+
+ status_t res = init_conf_kernel(jcp, jcp.oc, jcp.ntiles, jcp.ic);
+ jcp.ic_simd_block = jcp.dimK_reg_block;
+ jcp.ic_block = jcp.dimK_block;
+ jcp.nb_ic = jcp.dimK_nb_block;
+ jcp.oc_simd_block = jcp.dimM_simd_block;
+ jcp.oc_block = jcp.dimM_block;
+ jcp.nb_oc = jcp.dimM_nb_block;
+ jcp.tile_block_ur = jcp.dimN_reg_block;
+ jcp.nb_tile_block_ur = jcp.dimN_block;
+ jcp.tile_block = jcp.dimN_nb_block;
+ jcp.tile_4fma_padding = 0; // only relevant for backward weights
+
+ return res;
+}
+
+status_t jit_avx512_common_conv_winograd_bwd_data_kernel_f32::init_conf(
+ jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_wrapper &diff_src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &diff_dst_d)
+{
+ status_t st = init_conf_common(jcp, cd, diff_src_d, weights_d, diff_dst_d);
+
+ if (st != status::success)
+ return st;
+
+ jcp.itiles = (jcp.iw + tile_size - 1) / tile_size;
+ jcp.jtiles = (jcp.ih + tile_size - 1) / tile_size;
+ jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles;
+
+ status_t res = init_conf_kernel(jcp, jcp.ic, jcp.ntiles, jcp.oc);
+ jcp.oc_simd_block = jcp.dimK_reg_block;
+ jcp.oc_block = jcp.dimK_block;
+ jcp.nb_oc = jcp.dimK_nb_block;
+ jcp.ic_simd_block = jcp.dimM_simd_block;
+ jcp.ic_block = jcp.dimM_block;
+ jcp.nb_ic = jcp.dimM_nb_block;
+ jcp.tile_block_ur = jcp.dimN_reg_block;
+ jcp.nb_tile_block_ur = jcp.dimN_block;
+ jcp.tile_block = jcp.dimN_nb_block;
+ jcp.tile_4fma_padding = 0; // only relevant for backward weights
+
+ return res;
+}
+
+void jit_avx512_common_conv_winograd_bwd_weights_kernel_f32::transpose_ker_generate()
+{
+ auto load_B = [=](int reg_idx, int offset) {
+ for (int i = 0; i < 4; i++) {
+ vmovups(Zmm(reg_idx + i), zword[reg_origB + (offset + i) * jcp.dimN_reg_block * sizeof(float)]);
+ }
+ };
+
+ preamble();
+ int curr = 0;
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ int origB_offset = (j * alpha + i) * jcp.dimK_4fma;
+ size_t transB_offset = (size_t)(j * alpha + i) * jcp.dimK_nb_block *
+ jcp.dimN_block * jcp.dimK_block * jcp.dimK_reg_block *
+ jcp.dimK_4fma * jcp.dimN_reg_block * sizeof(float);
+ mov(reg_transB_idx, transB_offset);
+ for (int tb = 0; tb < jcp.dimK_4fma; tb+=4) {
+ /*double buffering to hide load latencies*/
+ int next = (curr + 4) % 8;
+ if (i == 0 && tb == 0) {
+ load_B(0, origB_offset);
+ }
+ if (tb + 4 < (jcp.dimK_4fma -1)) {
+ load_B(next, origB_offset + 4);
+ } else if (i < alpha - 1) {
+ load_B(next, origB_offset + jcp.dimK_4fma);
+ }
+
+ vunpcklps(Zmm(8), Zmm(curr), Zmm(curr + 1));
+ vunpcklps(Zmm(9), Zmm(curr + 2), Zmm(curr + 3));
+ vunpckhps(Zmm(curr), Zmm(curr), Zmm(curr + 1));
+ vunpckhps(Zmm(curr + 1), Zmm(curr + 2), Zmm(curr + 3));
+
+ vunpcklpd(Zmm(curr + 2), Zmm(8), Zmm(9));
+ vunpckhpd(Zmm(curr + 3), Zmm(8), Zmm(9));
+
+ vunpcklpd(Zmm(8), Zmm(curr), Zmm(curr + 1));
+ vunpckhpd(Zmm(9), Zmm(curr), Zmm(curr + 1));
+
+ vmovntps(zword[reg_transB + reg_transB_idx
+ + sizeof(float) * tb * jcp.dimN_reg_block],
+ Zmm(curr+2));
+ vmovntps(zword[reg_transB + reg_transB_idx
+ + sizeof(float) * (tb + 1) * jcp.dimN_reg_block],
+ Zmm(curr+3));
+ vmovntps(zword[reg_transB + reg_transB_idx
+ + sizeof(float) * (tb + 2) * jcp.dimN_reg_block],
+ Zmm(8));
+ vmovntps(zword[reg_transB + reg_transB_idx
+ + sizeof(float) * (tb + 3) * jcp.dimN_reg_block],
+ Zmm(9));
+ curr = next;
+
+ }
+ }
+ }
+ postamble();
+ ret();
+}
+void jit_avx512_common_conv_winograd_bwd_weights_kernel_f32::gemm_loop_generate(
+ bool is_first_tile)
+{
+ // for (int ofm2 = 0; ofm2 < jcp.oc_block; ofm2++)
+ // for (int ifm2 = 0; ifm2 < jcp.ic_block; ifm2++)
+ // for (int nb_tile_block_ur = 0; nb_tile_block_ur <
+ // jcp.nb_tile_block_ur; nb_tile_block_ur++)
+ // for (int tile_block_ur = 0; tile_block_ur <
+ // jcp.tile_block_ur; tile_block_ur++)
+ // for (int ifm3 = 0; ifm3 < jcp.ic_reg_block; ++ifm3)
+ // U[ofm2][ifm2][ofm3][ifm3][0:oc_simd_block] +=
+ // M[ofm2][ofm3][nb_tile_block_ur][tile_block_ur][0:oc_simd_block]
+ // *
+ // broadcast(V[ifm2][nb_tile_block_ur][ifm3][tile_block_ur])
+ auto inner_loops = [=]() {
+ int inc_fma = jcp.ver == ver_4fma ? 4 : 1;
+ const int fma_ipc = jcp.ver == ver_4fma ? 1 : 2;
+ prefetcher_t<float> L1_pf(this, reg_srcB, L1,
+ jcp.dimK_reg_block * jcp.dimN_reg_block * jcp.dimK_4fma,
+ jcp.dimK_reg_block * jcp.dimN_reg_block * jcp.dimK_4fma
+ / inc_fma,
+ fma_ipc);
+ prefetcher_t<float> L2_pf(this, reg_srcB, L2,
+ jcp.dimK_reg_block * jcp.dimN_reg_block * jcp.dimK_4fma,
+ jcp.dimK_reg_block * jcp.dimN_reg_block * jcp.dimK_4fma
+ / inc_fma,
+ fma_ipc);
+
+ auto load_A = [=](int reg_idx, int offset) {
+ for (int i = 0; i < inc_fma; i++) {
+ vmovups(Zmm(reg_idx + i),
+ zword[reg_srcA +
+ sizeof(float) * jcp.dimM_simd_block * (offset + i)]);
+ }
+ };
+
+ Label dimM_block_loop, dimK_block_loop, dimN_block_loop;
+ if (jcp.dimM_block > 1) {
+ mov(reg_dimM_block_loop_cnt, jcp.dimM_block);
+ L(dimM_block_loop);
+ }
+ { /************* OC_block (M) loop ***********/
+ if (jcp.dimN_block > 1) {
+ mov(reg_dimN_block_loop_cnt, jcp.dimN_block);
+ L(dimN_block_loop);
+ }
+ { /*************** IC_block (N) loop *********/
+ for (int dimN_reg_block = 0;
+ dimN_reg_block < jcp.dimN_reg_block; ++dimN_reg_block) {
+ Zmm zmm(jcp.zmm_start + dimN_reg_block);
+ if (is_first_tile)
+ vpxord(zmm, zmm, zmm);
+ else
+ vmovups(zmm, zword[reg_dstC +
+ dimN_reg_block * jcp.dimM_simd_block *
+ sizeof(float)]);
+ }
+
+ if (jcp.dimK_block > 1) {
+ mov(reg_dimK_block_loop_cnt, jcp.dimK_block);
+ L(dimK_block_loop);
+ }
+ { /************* nb_tile_ur(K) loop ********/
+ int next = 0;
+ if (jcp.double_buffering) {
+ load_A(next, 0);
+ }
+ for (int dimK_reg_block = 0;
+ dimK_reg_block < jcp.dimK_reg_block;
+ dimK_reg_block++) {
+ int srcB_offset = dimK_reg_block * jcp.dimK_4fma
+ * jcp.dimN_reg_block;
+ for (int dimK_4fma = 0; dimK_4fma < jcp.dimK_4fma;
+ dimK_4fma += inc_fma) {
+ int current = next;
+ if (jcp.double_buffering) {
+ next = (dimK_reg_block * jcp.dimK_4fma
+ + dimK_4fma + inc_fma)
+ % (2 * inc_fma);
+ load_A(next, dimK_reg_block * jcp.dimK_4fma
+ + dimK_4fma + inc_fma);
+ } else {
+ next = 0;
+ load_A(next, dimK_reg_block * jcp.dimK_4fma
+ + dimK_4fma);
+ }
+ for (int dimN_reg_block = 0;
+ dimN_reg_block < jcp.dimN_reg_block;
+ ++dimN_reg_block) {
+ L1_pf.prefetch(srcB_offset / inc_fma
+ + dimK_4fma / inc_fma
+ * jcp.dimN_reg_block
+ + dimN_reg_block);
+ L2_pf.prefetch(srcB_offset / inc_fma
+ + dimK_4fma / inc_fma
+ * jcp.dimN_reg_block
+ + dimN_reg_block);
+ if (jcp.ver == ver_4fma) {
+ int srcB_trans_offset = (dimK_4fma / 4) * 64
+ + dimK_4fma % 4;
+ v4fmaddps(
+ Zmm(jcp.zmm_start + dimN_reg_block),
+ Zmm(current),
+ EVEX_compress_addr(reg_srcB,
+ sizeof(float) * (
+ srcB_offset +
+ srcB_trans_offset +
+ (dimN_reg_block % 4) * 16 +
+ (dimN_reg_block / 4) * 4)));
+ } else {
+ vfmadd231ps(
+ Zmm(jcp.zmm_start + dimN_reg_block),
+ Zmm(current),
+ EVEX_compress_addr(reg_srcB,
+ sizeof(float) * (srcB_offset + dimN_reg_block),
+ true));
+ }
+ }
+ }
+ }
+ }
+
+ add(reg_srcA, jcp.dimK_reg_block * jcp.dimK_4fma
+ * jcp.dimM_simd_block * sizeof(float));
+ add(reg_srcB, jcp.dimK_reg_block * jcp.dimN_reg_block
+ * jcp.dimK_4fma * sizeof(float));
+ if (jcp.dimK_block > 1) {
+ sub(reg_dimK_block_loop_cnt, 1);
+ jnz(dimK_block_loop);
+ }
+
+ /******** Write C back to memory *******/
+ for (int dimN_reg_block = 0;
+ dimN_reg_block < jcp.dimN_reg_block; ++dimN_reg_block) {
+ Zmm zmm(jcp.zmm_start + dimN_reg_block);
+ vmovups(zword[reg_dstC +
+ dimN_reg_block * jcp.dimM_simd_block * sizeof(float)],
+ zmm);
+ }
+
+ sub(reg_srcA, jcp.dimK_block * jcp.dimK_reg_block *
+ jcp.dimK_4fma * jcp.dimM_simd_block * sizeof(float));
+ add(reg_dstC, jcp.dimN_reg_block * jcp.dimM_simd_block
+ * sizeof(float));
+ if (jcp.dimN_block > 1) {
+ sub(reg_dimN_block_loop_cnt, 1);
+ jnz(dimN_block_loop);
+ }
+ }
+
+ if (jcp.dimM_block > 1) {
+ sub(reg_srcB, jcp.dimN_block * jcp.dimK_block
+ * jcp.dimK_reg_block * jcp.dimN_reg_block
+ * jcp.dimK_4fma * sizeof(float));
+ add(reg_srcA, jcp.dimK_block * jcp.dimK_reg_block
+ * jcp.dimK_4fma * jcp.dimM_simd_block * sizeof(float));
+ sub(reg_dimM_block_loop_cnt, 1);
+ jnz(dimM_block_loop);
+ }
+ }
+ };
+
+ /* Preamble */
+ // register used to handle long fma encoding
+ preamble();
+ mov(reg_srcA, reg_srcA_const);
+ inner_loops();
+
+ /* Postamble */
+ postamble();
+ ret();
+}
+
+namespace {
+bool check_cond1_wu(int dimM_block, int dimM_simdw, int dimK_block,
+ int dimK_reg_block, int dimK_4fma, int dimN_reg_block, float C)
+{
+ float lhs = 1.0f * dimM_block * dimN_reg_block * dimM_simdw;
+ lhs += dimM_block * dimK_block * dimK_reg_block * dimK_4fma * dimM_simdw;
+ lhs += dimK_block * dimN_reg_block * dimK_reg_block * dimK_4fma;
+ lhs *= sizeof(float);
+ float rhs = C * L1_cache_size;
+ return (lhs <= rhs);
+}
+
+bool check_cond1bis_wu(int dimM_block, int dimM_simdw, int dimK_block,
+ int dimK_reg_block, int dimK_4fma, int dimN_reg_block, float C)
+{
+ float lhs = 1.0f * dimM_block * dimK_block * dimK_reg_block * dimK_4fma
+ * dimM_simdw;
+ lhs += dimK_block * dimN_reg_block * dimK_reg_block * dimK_4fma;
+ lhs *= sizeof(float);
+ float rhs = C * L1_cache_size;
+ return (lhs <= rhs);
+}
+
+bool check_cond2bis_wu(int dimM_block, int dimM_simdw, int dimK_block,
+ int dimK_reg_block, int dimK_4fma, int dimN_block, int dimN_reg_block,
+ float C)
+{
+ float lhs = 1.0f * dimM_block * dimM_simdw * dimK_block * dimK_reg_block
+ * dimK_4fma;
+ lhs += dimK_block * dimK_reg_block * dimK_4fma * dimN_block
+ * dimN_reg_block;
+ lhs *= sizeof(float);
+ float rhs = C * L2_cache_size;
+ return (lhs <= rhs);
+}
+
+bool check_cond2_wu(int dimM_block, int dimM_simdw, int dimK_block,
+ int dimK_reg_block, int dimK_4fma, int dimN_block, int dimN_reg_block,
+ float C)
+{
+ float lhs = 1.0f * dimM_block * dimM_simdw * dimN_block * dimN_reg_block;
+ lhs += dimM_block * dimM_simdw * dimK_block * dimK_reg_block * dimK_4fma;
+ lhs += dimK_block * dimK_reg_block * dimK_4fma * dimN_block
+ * dimN_reg_block;
+ lhs *= sizeof(float);
+ float rhs = C * L2_cache_size;
+ return (lhs <= rhs);
+}
+} // namespace
+
+status_t set_wsched_WEI_S_D_G_W_avx512_common(jit_conv_winograd_conf_t &jcp)
+{
+ /*************** Choose dimN_reg_block (ic_simd_block)
+ * *******************************/
+ jcp.dimN = jcp.ic;
+ /*Hardcoded to 16 because N = ic for bwd weights and
+ innermost dimension for ic is assumed 16 in src transforms. This
+ choice covers load latencies while maintaining simplicity of kernel
+ for POR topologies. FIXME in future??: Will not work for future topologies
+ when ic%16 != 0*/
+ jcp.dimN_reg_block = jcp.ic_simd_block;
+
+ /****************************** Choose dimK_block
+ * **************************/
+ // No freedom for choosing dimM_simd_block because ic_simd_block
+ // is determined by input data format
+ jcp.dimM_simd_block = jcp.oc_simd_block;
+
+ auto test_cond1bis_dimK_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) {
+ return check_cond1bis_wu(1, jcp.dimM_simd_block, dimK_block, 1,
+ jcp.dimK_4fma, jcp.dimN_reg_block, 0.4f)
+ && (dimK_block > current_best);
+ };
+
+ auto test_cond1_dimK_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) {
+ return check_cond1_wu(1, jcp.dimM_simd_block, dimK_block, 1,
+ jcp.dimK_4fma, jcp.dimN_reg_block, 0.4f)
+ && (dimK_block > current_best);
+ };
+
+ auto test_cond2bis_dimK_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) {
+ return check_cond2bis_wu(1, jcp.dimM_simd_block, dimK_block, 1,
+ jcp.dimK_4fma, 1, jcp.dimN_reg_block, 0.5f)
+ && (dimK_block > current_best);
+ };
+
+ auto test_cond2_dimK_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) {
+ return check_cond2_wu(1, jcp.dimM_simd_block, dimK_block, 1,
+ jcp.dimK_4fma, 1, jcp.dimN_reg_block, 0.1f)
+ && (dimK_block > current_best);
+ };
+
+ jcp.dimK_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimK / jcp.dimK_4fma, 1, test_cond2bis_dimK_block);
+ if (jcp.dimK_block < jcp.dimK / jcp.dimK_4fma)
+ jcp.dimK_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimK / jcp.dimK_4fma, 1, test_cond2_dimK_block);
+
+ jcp.dimK_reg_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimK_block, 1, test_cond1bis_dimK_block);
+ if (jcp.dimK_reg_block < jcp.dimK_block) {
+ jcp.dimK_reg_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimK_block, 1, test_cond1_dimK_block);
+ }
+ jcp.dimK_block /= jcp.dimK_reg_block;
+ jcp.dimK_nb_block
+ = jcp.dimK / jcp.dimK_4fma / jcp.dimK_reg_block / jcp.dimK_block;
+ jcp.tile_block_ur = jcp.dimK_reg_block;
+ jcp.nb_tile_block_ur = jcp.dimK_block;
+ jcp.tile_block = jcp.dimK_nb_block;
+
+ /***************************** Chose dimN block
+ * ****************************/
+ auto test_cond2_dimN_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimN_block, int current_best) {
+ return check_cond2_wu(1, jcp.dimM_simd_block, jcp.dimK_block,
+ jcp.dimK_reg_block, jcp.dimK_4fma, dimN_block,
+ jcp.dimN_reg_block, 0.5f)
+ && (dimN_block > current_best);
+ };
+
+ jcp.dimN_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimN / jcp.dimN_reg_block, 1, test_cond2_dimN_block);
+ jcp.ic_block = jcp.dimN_block;
+ jcp.dimN_nb_block = jcp.dimN / jcp.dimN_reg_block / jcp.dimN_block;
+ jcp.nb_ic = jcp.dimN_nb_block;
+
+ /********************************* Choose dimM block
+ * ************************/
+ jcp.dimM = jcp.oc;
+
+ auto test_cond1_dimM_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimM_block, int current_best) {
+ return check_cond1_wu(dimM_block, jcp.dimM_simd_block, 1,
+ jcp.dimK_reg_block, jcp.dimK_4fma, jcp.dimN_reg_block,
+ 1.0f)
+ && (dimM_block > current_best)
+ && (jcp.dimM / jcp.dimM_simd_block / dimM_block) >= 2;
+ };
+
+ jcp.dimM_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimM / jcp.dimM_simd_block, 1, test_cond1_dimM_block);
+ jcp.dimM_nb_block = (jcp.dimM / jcp.dimM_simd_block) / jcp.dimM_block;
+
+ jcp.sched_policy = WSCHED_WEI_S_D_G_W;
+ return status::success;
+}
+
+status_t jit_avx512_common_conv_winograd_bwd_weights_kernel_f32::init_conf(
+ jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d, const memory_desc_wrapper &diff_dst_d,
+ const memory_desc_wrapper &diff_weights_d)
+{
+ jcp.nthr = mkldnn_get_max_threads();
+
+ const bool with_groups = diff_weights_d.ndims() == src_d.ndims() + 1;
+
+ jcp.ngroups = with_groups ? diff_weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+ jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.ih = src_d.dims()[2];
+ jcp.iw = src_d.dims()[3];
+ jcp.oh = diff_dst_d.dims()[2];
+ jcp.ow = diff_dst_d.dims()[3];
+ jcp.kh = diff_weights_d.dims()[with_groups + 2];
+ jcp.kw = diff_weights_d.dims()[with_groups + 3];
+ jcp.t_pad = cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][1];
+ jcp.stride_h = cd.strides[0];
+ jcp.stride_w = cd.strides[1];
+ jcp.r_pad = nstl::max(
+ 0, (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad);
+ jcp.b_pad = nstl::max(
+ 0, (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad);
+ jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad;
+ jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad;
+ jcp.ohp = jcp.oh;
+ jcp.owp = jcp.ow;
+ jcp.with_bias = (cd.diff_bias_desc.format_kind != format_kind::undef);
+ jcp.dilate_h = cd.dilates[0];
+ jcp.dilate_w = cd.dilates[1];
+
+ bool ok_to_pad_channels = jcp.ngroups == 1;
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ jcp.ic = rnd_up(jcp.ic, simd_w);
+ }
+
+ if (mayiuse(avx512_core))
+ return status::unimplemented;
+ if (!mayiuse(avx512_common))
+ return status::unimplemented;
+ else if (mayiuse(avx512_mic_4ops))
+ jcp.ver = ver_4fma;
+ else
+ jcp.ver = ver_fma;
+
+ if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto,
+ is_winograd_faster_than_direct(jcp)))
+ return status::unimplemented;
+ // Winograd specific initialization
+ jcp.itiles = (jcp.ow + tile_size - 1) / tile_size;
+ jcp.jtiles = (jcp.oh + tile_size - 1) / tile_size;
+ jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles;
+
+ // Winograd kernel works only for 3x3 convolution with stride 1
+ if (jcp.ngroups != 1)
+ return status::unimplemented;
+ if ((jcp.kh != 3) || (jcp.kw != 3))
+ return status::unimplemented;
+ if ((jcp.dilate_h != 0) || (jcp.dilate_w != 0))
+ return status::unimplemented;
+ if ((jcp.stride_h != 1) || (jcp.stride_w != 1))
+ return status::unimplemented;
+ if ((jcp.ic % simd_w) != 0 || (jcp.oc % simd_w) != 0)
+ return status::unimplemented;
+
+ format_tag_t dat_tag = nChw16c;
+ format_tag_t wei_tag = with_groups ? gOIhw16i16o : OIhw16i16o;
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.wei_tag = diff_weights_d.matches_one_of_tag(wei_tag);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(dat_tag);
+
+ if (jcp.src_tag != dat_tag) return status::unimplemented;
+ if (jcp.wei_tag != wei_tag) return status::unimplemented;
+ if (jcp.dst_tag != dat_tag) return status::unimplemented;
+
+ bool layout_consistency = true
+ && jcp.ic <= src_d.padded_dims()[1]
+ && jcp.oc <= diff_dst_d.padded_dims()[1]
+ && jcp.ic <= diff_weights_d.padded_dims()[with_groups + 1]
+ && jcp.oc <= diff_weights_d.padded_dims()[with_groups + 0];
+ if (!layout_consistency) return status::unimplemented;
+
+ /*************************** New Kernel Parameters
+ * *****************************/
+ jcp.ic_simd_block = simd_w;
+ jcp.oc_simd_block = simd_w;
+ jcp.dimK_4fma = 1;
+ jcp.tile_4fma_padding = 0;
+
+#define MAX_4FMA_UR 8
+ if (jcp.ver == ver_4fma) {
+ auto test_cond_4fma = [](jit_conv_winograd_conf_t &jcp, int dimK_4fma,
+ int current_best) {
+ return (dimK_4fma % 4 == 0) && (dimK_4fma <= MAX_4FMA_UR)
+ && (dimK_4fma > current_best);
+ };
+ jcp.dimK_4fma = get_divisor_satisfying_cond(
+ jcp, jcp.itiles * jcp.jtiles, 4, test_cond_4fma);
+ if (jcp.dimK_4fma == 1)
+ jcp.dimK_4fma = 4;
+ if ((jcp.itiles * jcp.jtiles) % jcp.dimK_4fma != 0)
+ jcp.tile_4fma_padding = jcp.dimK_4fma
+ - ((jcp.itiles * jcp.jtiles) % jcp.dimK_4fma);
+ }
+
+ jcp.tile_4fma = jcp.dimK_4fma;
+ /*NOTE: When (itiles * jtiles) % dimK_4fma != 0, transpose in diff_src
+ * transform
+ * will not work correctly, this is solved by applying padding.*/
+ jcp.dimK = jcp.mb * (jcp.itiles * jcp.jtiles + jcp.tile_4fma_padding);
+ jcp.dimN = jcp.ic;
+ jcp.dimM = jcp.oc;
+
+ jcp.double_buffering = true;
+ if (jcp.double_buffering)
+ jcp.zmm_start = jcp.ver == ver_4fma ? 8 : 2;
+ else
+ jcp.zmm_start = jcp.ver == ver_4fma ? 4 : 1;
+ jcp.nb_reg = 32 - jcp.zmm_start;
+
+ jcp.sched_policy = WSCHED_INVALID;
+ status_t res = set_wsched_WEI_S_D_G_W_avx512_common(jcp);
+ assert(jcp.sched_policy == WSCHED_WEI_S_D_G_W);
+
+ jcp.tile_block_ur = jcp.dimK_reg_block;
+ jcp.nb_tile_block_ur = jcp.dimK_block;
+ jcp.tile_block = jcp.dimK_nb_block;
+
+ jcp.ic_block = jcp.dimN_block;
+ jcp.nb_ic = jcp.dimN_nb_block;
+
+ jcp.oc_block = jcp.dimM_block;
+ jcp.nb_oc = jcp.dimM_nb_block;
+
+ return res;
+
+}
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.hpp
new file mode 100644
index 0000000000..6c117143f5
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.hpp
@@ -0,0 +1,179 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_AVX512_COMMON_CONV_WINOGRAD_KERNEL_F32_HPP
+#define JIT_AVX512_COMMON_CONV_WINOGRAD_KERNEL_F32_HPP
+
+#include "c_types_map.hpp"
+#include "cpu_memory.hpp"
+
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+//alpha determines the output tile_size
+constexpr int alpha = 6;
+constexpr int tile_size = 4;
+//simd length used for vectorization
+constexpr int simd_w = 16;
+
+struct _jit_avx512_common_conv_winograd_data_kernel_f32 : public jit_generator {
+ _jit_avx512_common_conv_winograd_data_kernel_f32(
+ jit_conv_winograd_conf_t ajcp)
+ : jcp(ajcp)
+ {
+ //******************* First iter kernel ********************//
+ this->gemm_loop_generate(true);
+ gemm_loop_ker_first_iter
+ = (decltype(gemm_loop_ker_first_iter)) this->getCode();
+
+ //************** Subsequent iterations kernel **************//
+ if (jcp.dimK_nb_block > 1) {
+ align();
+ const Xbyak::uint8 *addr = getCurr();
+ this->gemm_loop_generate(false);
+ gemm_loop_ker = (decltype(gemm_loop_ker))addr;
+ }
+ }
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(_jit_avx512_common_conv_winograd_data_kernel_f32)
+
+ static status_t init_conf_common(jit_conv_winograd_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d);
+
+ static status_t init_conf_kernel(
+ jit_conv_winograd_conf_t &jcp, int dimM, int dimN, int dimK);
+
+ jit_conv_winograd_conf_t jcp;
+ void (*gemm_loop_ker)(float *, const float *, const float *);
+ void (*gemm_loop_ker_first_iter)(float *, const float *, const float *);
+
+protected:
+ using reg64_t = const Xbyak::Reg64;
+ enum { typesize = sizeof(float) };
+
+ void gemm_loop_generate(bool is_beta_zero);
+
+ /* registers used for GEMM */
+ reg64_t reg_dstC = abi_param1;
+ reg64_t reg_srcA = abi_param2;
+ reg64_t reg_srcB = abi_param3;
+
+ reg64_t reg_dimM_block_loop_cnt = r10;
+ reg64_t reg_dimK_block_loop_cnt = r11;
+};
+
+struct jit_avx512_common_conv_winograd_fwd_kernel_f32
+ : _jit_avx512_common_conv_winograd_data_kernel_f32 {
+ using _jit_avx512_common_conv_winograd_data_kernel_f32::
+ _jit_avx512_common_conv_winograd_data_kernel_f32;
+
+ static bool post_ops_ok(jit_conv_conf_t &jcp, const primitive_attr_t &attr);
+
+ static status_t init_conf(jit_conv_winograd_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d, const primitive_attr_t &attr);
+};
+
+struct jit_avx512_common_conv_winograd_bwd_data_kernel_f32
+ : public _jit_avx512_common_conv_winograd_data_kernel_f32 {
+ using _jit_avx512_common_conv_winograd_data_kernel_f32::
+ _jit_avx512_common_conv_winograd_data_kernel_f32;
+
+ static status_t init_conf(jit_conv_winograd_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &diff_src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &diff_dst_d);
+};
+
+struct jit_avx512_common_conv_winograd_bwd_weights_kernel_f32
+ : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(_jit_avx512_common_conv_winograd_bwd_weights_kernel_f32)
+
+ jit_avx512_common_conv_winograd_bwd_weights_kernel_f32(
+ jit_conv_winograd_conf_t ajcp)
+ : jcp(ajcp)
+ {
+
+ //******************* First iter kernel ********************//
+ {
+ align();
+ const Xbyak::uint8 *addr = getCurr();
+ this->gemm_loop_generate(true);
+ gemm_loop_ker_first_iter = (decltype(gemm_loop_ker_first_iter))addr;
+ }
+
+ if (jcp.tile_block > 1) {
+ align();
+ const Xbyak::uint8 *addr = getCurr();
+ this->gemm_loop_generate(false);
+ gemm_loop_ker = (decltype(gemm_loop_ker))addr;
+ }
+
+ if (jcp.ver == ver_4fma) {
+ align();
+ const Xbyak::uint8 *addr = getCurr();
+ this->transpose_ker_generate();
+ transpose_4fma_ker = (decltype(transpose_4fma_ker))addr;
+ }
+ }
+
+ static status_t init_conf(jit_conv_winograd_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &diff_dst_d,
+ const memory_desc_wrapper &diff_weights_d);
+
+ jit_conv_winograd_conf_t jcp;
+ void (*gemm_loop_ker)(float *, const float *, const float *);
+ void (*gemm_loop_ker_first_iter)(float *, const float *, const float *);
+ void (*transpose_4fma_ker)(float *, float *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ enum { typesize = sizeof(float) };
+
+ void gemm_loop_generate(bool is_first_tile);
+ void transpose_ker_generate();
+
+ reg64_t reg_origB = abi_param2;
+ reg64_t reg_transB = abi_param1;
+
+ reg64_t reg_dstC = abi_param1;
+ reg64_t reg_srcA_const = abi_param2;
+ reg64_t reg_srcB = abi_param3;
+
+ reg64_t reg_sp = rsp;
+ reg64_t reg_srcA = r9;
+ reg64_t reg_nb_ic = r10;
+ reg64_t reg_loop_cpt = r11;
+ reg64_t reg_transB_idx = r13;
+
+ /* Registers used by new kernel */
+ reg64_t reg_dimM_block_loop_cnt = r10;
+ reg64_t reg_dimK_block_loop_cnt = r12;
+ reg64_t reg_dimN_block_loop_cnt = r11;
+};
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.cpp
new file mode 100644
index 0000000000..abddc19221
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.cpp
@@ -0,0 +1,1526 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_avx512_common_convolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+using namespace nstl;
+
+using jit_conv_ker_t = void (*)(jit_conv_call_s *);
+
+#define PIPELINE(field) \
+ do { \
+ p.field = p.field ## _prf; \
+ p.field ## _prf = field; \
+ } while (0)
+
+inline void jit_conv_ker_pipeline(jit_conv_ker_t ker, jit_conv_call_s &p,
+ const void *src, const void *dst, const void *filt, const void *bias,
+ int channel, int kh_padding)
+{
+ PIPELINE(src);
+ PIPELINE(dst);
+ PIPELINE(filt);
+ PIPELINE(bias);
+ PIPELINE(channel);
+ PIPELINE(kh_padding);
+
+ if (p.src)
+ ker(&p);
+}
+// The special case for the driver with ow-parallelization (FWD)
+// TODO: implement it for BWD_D and BWD_W too
+inline void jit_conv_ker_pipeline_ow_thr(jit_conv_ker_t ker, jit_conv_call_s &p,
+ const void *src, const void *dst, const void *filt, const void *bias,
+ int channel, int kh_padding, int owb)
+{
+ PIPELINE(src);
+ PIPELINE(dst);
+ PIPELINE(filt);
+ PIPELINE(bias);
+ PIPELINE(channel);
+ PIPELINE(kh_padding);
+ PIPELINE(owb);
+
+ if (p.src)
+ ker(&p);
+}
+
+inline void jit_conv_3d_ker_pipeline(jit_conv_ker_t ker, jit_conv_call_s &p,
+ const void *src, const void *dst, const void *filt, const void *bias,
+ int channel, int kh_padding, int kd_padding)
+{
+ PIPELINE(src);
+ PIPELINE(dst);
+ PIPELINE(filt);
+ PIPELINE(bias);
+ PIPELINE(channel);
+ PIPELINE(kh_padding);
+ PIPELINE(kd_padding);
+
+ if (p.src)
+ ker(&p);
+}
+// The special case for the driver with ow-parallelization (FWD)
+// TODO: implement it for BWD_D and BWD_W too
+inline void jit_conv_3d_ker_pipeline_ow_thr(jit_conv_ker_t ker,
+ jit_conv_call_s &p, const void *src, const void *dst, const void *filt,
+ const void *bias, int channel, int kh_padding, int kd_padding, int owb)
+{
+ PIPELINE(src);
+ PIPELINE(dst);
+ PIPELINE(filt);
+ PIPELINE(bias);
+ PIPELINE(channel);
+ PIPELINE(kh_padding);
+ PIPELINE(kd_padding);
+ PIPELINE(owb);
+
+ if (p.src)
+ ker(&p);
+}
+
+void jit_conv_3d_ker_bwd_w_pipeline(jit_conv_ker_t ker, jit_conv_call_s &p,
+ const void *src, const void *dst, const void *filt, const void *bias,
+ int channel, int d_index, int d_worksize,
+ int kd_padding /* kd_work_size */, size_t kd_offset) {
+ PIPELINE(src);
+ PIPELINE(dst);
+ PIPELINE(filt);
+ PIPELINE(bias);
+ PIPELINE(channel);
+ PIPELINE(kd_padding);
+ PIPELINE(d_worksize);
+ PIPELINE(d_index);
+ PIPELINE(kd_offset);
+
+ if (p.src)
+ ker(&p);
+}
+#define wht_blk_off(d, g, ...) \
+ (pd()->with_groups() \
+ ? (d).blk_off((g), __VA_ARGS__) \
+ : (d).blk_off(__VA_ARGS__))
+
+template <data_type_t src_type, data_type_t wei_type, data_type_t dst_type>
+void jit_avx512_common_convolution_fwd_t<src_type, wei_type,
+ dst_type>::prepare_padded_bias(const dst_data_t *&bias,
+ const memory_tracking::grantor_t &scratchpad) const {
+ if (!pd()->wants_padded_bias()) return;
+
+ auto padded_bias = scratchpad.template get<dst_data_t>(
+ key_conv_padded_bias);
+ utils::array_copy(padded_bias, bias, pd()->jcp_.oc_without_padding);
+ utils::array_set(padded_bias + pd()->jcp_.oc_without_padding,
+ (dst_data_t)0, pd()->jcp_.oc - pd()->jcp_.oc_without_padding);
+ bias = padded_bias;
+}
+
+template <data_type_t src_type, data_type_t wei_type,
+ data_type_t dst_type>
+void jit_avx512_common_convolution_fwd_t<src_type, wei_type, dst_type>::
+execute_forward_1d(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const dst_data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ prepare_padded_bias(bias, this->scratchpad(ctx));
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const auto &jcp = pd()->jcp_;
+ assert(jcp.nb_oc % jcp.nb_oc_blocking == 0);
+
+ int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking;
+ int work_amount = jcp.mb * jcp.ngroups * oc_chunks * jcp.nb_ow;
+
+ int nthr;
+ if (jcp.aligned_threads)
+ nthr = jcp.aligned_threads;
+ else
+ nthr = mkldnn_get_max_threads();
+
+ parallel(nthr, [&](const int ithr, const int nthr) {
+ int start{0}, end{0}, start_copy;
+ balance211(work_amount, nthr, ithr, start, end);
+ start_copy = start;
+
+ auto par_conv = jit_conv_call_s();
+ size_t src_c_stride = src_d.blk_off(0, 1);
+ size_t wht_ic_stride = wht_blk_off(weights_d, 0, 0, 1);
+
+ for (int icb_l2 = 0 ; icb_l2 < jcp.nb_ic; icb_l2 += jcp.nb_ic_L2) {
+ start = start_copy;
+ int n{0}, g{0}, occ{0}, owb{0};
+
+ if (jcp.loop_order == loop_cwgn) {
+ int dummy{0};
+ nd_iterator_init(start, occ, oc_chunks, owb, jcp.nb_ow,
+ g, jcp.ngroups, n, jcp.mb, dummy, 1);
+ } else if (jcp.loop_order == loop_gncw) {
+ int dummy{0};
+ nd_iterator_init(start, g, jcp.ngroups, n, jcp.mb, occ,
+ oc_chunks, owb, jcp.nb_ow, dummy, 1);
+ } else {
+ assert(!"unsupported loop order");
+ }
+
+ while (start < end) {
+ int ocb = occ * jcp.nb_oc_blocking;
+ int g_ocb = g * jcp.nb_oc + ocb;
+ int g_oc = g_ocb * jcp.oc_block;
+ int g_icb = g * jcp.nb_ic * jcp.nonblk_group_off;
+
+ int ow_s = owb * jcp.ow_block;
+ int iw_s = ow_s * jcp.stride_w;
+ auto bias_w = bias ? bias + g_oc : nullptr;
+ auto dst_w = dst + dst_d.blk_off(n, g_ocb, ow_s);
+ auto src_w = src + src_d.blk_off(n, g_icb + icb_l2, iw_s);
+ auto wht_w = weights + wht_blk_off(weights_d, g, ocb, icb_l2);
+
+ for (int icb = icb_l2;
+ icb < min(jcp.nb_ic, icb_l2 + jcp.nb_ic_L2); ++icb) {
+ jit_conv_ker_pipeline_ow_thr(kernel_->jit_ker, par_conv,
+ src_w, dst_w, wht_w, bias_w, icb, 1, owb);
+
+ src_w += src_c_stride;
+ wht_w += wht_ic_stride;
+ }
+ if (jcp.loop_order == loop_cwgn) {
+ int dummy{0};
+ nd_iterator_jump(start, end, occ, oc_chunks, owb, jcp.nb_ow,
+ g, jcp.ngroups, n, jcp.mb, dummy, 1);
+ } else if (jcp.loop_order == loop_gncw) {
+ int dummy{0};
+ nd_iterator_jump(start, end, g, jcp.ngroups, n, jcp.mb,
+ occ, oc_chunks, owb, jcp.nb_ow, dummy, 1);
+ } else {
+ assert(!"unsupported loop order");
+ }
+ }
+ }
+ jit_conv_ker_pipeline_ow_thr(kernel_->jit_ker, par_conv,
+ src, dst, weights, bias, 0, 0, 0);
+ });
+}
+
+template <data_type_t src_type, data_type_t wei_type,
+ data_type_t dst_type>
+void jit_avx512_common_convolution_fwd_t<src_type, wei_type, dst_type>::
+execute_forward_2d(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const dst_data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ prepare_padded_bias(bias, this->scratchpad(ctx));
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const auto &jcp = pd()->jcp_;
+ assert(jcp.nb_oc % jcp.nb_oc_blocking == 0);
+
+ int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking;
+ int work_amount = jcp.mb * jcp.ngroups * oc_chunks * jcp.oh * jcp.nb_ow;
+
+ int nthr;
+ if (jcp.aligned_threads)
+ nthr = jcp.aligned_threads;
+ else
+ nthr = mkldnn_get_max_threads();
+
+ parallel(nthr, [&](const int ithr, const int nthr) {
+ int start{0}, end{0}, start_copy;
+ balance211(work_amount, nthr, ithr, start, end);
+ start_copy = start;
+
+ auto par_conv = jit_conv_call_s();
+ size_t src_h_stride = src_d.blk_off(0, 0, 1);
+ size_t src_c_stride = src_d.blk_off(0, 1);
+ size_t dst_h_stride = dst_d.blk_off(0, 0, 1);
+ size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 1);
+ size_t wht_ic_stride = wht_blk_off(weights_d, 0, 0, 1);
+
+ for (int icb_l2 = 0 ; icb_l2 < jcp.nb_ic; icb_l2 += jcp.nb_ic_L2) {
+ start = start_copy;
+ int n{0}, g{0}, occ{0}, oh_s{0}, owb{0};
+
+ if (jcp.loop_order == loop_cwgn)
+ nd_iterator_init(start, occ, oc_chunks, owb, jcp.nb_ow,
+ g, jcp.ngroups, n, jcp.mb, oh_s, jcp.oh);
+ else if (jcp.loop_order == loop_gncw)
+ nd_iterator_init(start, g, jcp.ngroups, n, jcp.mb,
+ occ, oc_chunks, owb, jcp.nb_ow, oh_s, jcp.oh);
+ else
+ assert(!"unsupported loop order");
+
+ while (start < end) {
+ int ocb = occ * jcp.nb_oc_blocking;
+ int g_ocb = g * jcp.nb_oc + ocb;
+ int g_oc = g_ocb * jcp.oc_block;
+ int g_icb = g * jcp.nb_ic * jcp.nonblk_group_off;
+
+ int work_rem = end - start;
+
+ int ow_s = owb * jcp.ow_block;
+ int iw_s = ow_s * jcp.stride_w;
+ int oh_e = oh_s + work_rem > jcp.oh ? jcp.oh : oh_s + work_rem;
+ auto bias_w = bias ? bias + g_oc : nullptr;
+
+ for (int oh_b = oh_s; oh_b < oh_e; oh_b += jcp.h_blocking) {
+ int ih_b = -jcp.t_pad + oh_b * jcp.stride_h;
+
+ auto dst_w = dst + dst_d.blk_off(n, g_ocb, oh_b, ow_s);
+ auto src_w
+ = src + src_d.blk_off(n, g_icb + icb_l2, ih_b, iw_s);
+ auto wht_w
+ = weights + wht_blk_off(weights_d, g, ocb, icb_l2);
+
+ for (int icb = icb_l2;
+ icb < min(jcp.nb_ic, icb_l2 + jcp.nb_ic_L2);
+ ++icb) {
+ auto src_c = src_w;
+ auto dst_c = dst_w;
+ for (int oj = oh_b, ij = ih_b;
+ oj < min(oh_e, oh_b + jcp.h_blocking);
+ ++oj, ij += jcp.stride_h) {
+ int dilate_h = jcp.dilate_h + 1;
+ int i_t_overflow = div_up(max(0, -ij), dilate_h);
+ int i_b_overflow = div_up(max(0, ij - jcp.ih
+ + (jcp.kh - 1) * dilate_h + 1), dilate_h);
+ int kh_padding = nstl::max(
+ 0, jcp.kh - i_t_overflow - i_b_overflow);
+
+ auto aux_src = src_c
+ + i_t_overflow * dilate_h * src_h_stride;
+ auto aux_wht = wht_w + i_t_overflow * wht_h_stride;
+
+ jit_conv_ker_pipeline_ow_thr(kernel_->jit_ker,
+ par_conv, aux_src, dst_c, aux_wht, bias_w, icb,
+ kh_padding, owb);
+
+ src_c += src_h_stride * jcp.stride_h;
+ dst_c += dst_h_stride;
+ }
+ src_w += src_c_stride;
+ wht_w += wht_ic_stride;
+ }
+ }
+
+ if (jcp.loop_order == loop_cwgn)
+ nd_iterator_jump(start, end, occ, oc_chunks, owb, jcp.nb_ow,
+ g, jcp.ngroups, n, jcp.mb, oh_s, jcp.oh);
+ else if (jcp.loop_order == loop_gncw)
+ nd_iterator_jump(start, end, g, jcp.ngroups, n, jcp.mb, occ,
+ oc_chunks, owb, jcp.nb_ow, oh_s, jcp.oh);
+ else
+ assert(!"unsupported loop order");
+ }
+ }
+
+ jit_conv_ker_pipeline_ow_thr(kernel_->jit_ker, par_conv,
+ src, dst, weights, bias, 0, 0, 0);
+ });
+}
+
+template <data_type_t src_type, data_type_t wei_type,
+ data_type_t dst_type>
+void jit_avx512_common_convolution_fwd_t<src_type, wei_type, dst_type>::
+execute_forward_3d(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const dst_data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ prepare_padded_bias(bias, this->scratchpad(ctx));
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ const auto &jcp = pd()->jcp_;
+ assert(jcp.nb_oc % jcp.nb_oc_blocking == 0);
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking;
+ int start{0}, end{0}, start_copy;
+ int work_amount = jcp.mb * jcp.ngroups * oc_chunks * jcp.od * jcp.oh
+ * jcp.nb_ow;
+ balance211(work_amount, nthr, ithr, start, end);
+ start_copy = start;
+
+ auto par_conv = jit_conv_call_s();
+ size_t src_d_stride = src_d.blk_off(0, 0, 1);
+ size_t src_h_stride = src_d.blk_off(0, 0, 0, 1);
+ size_t src_c_stride = src_d.blk_off(0, 1);
+ size_t dst_h_stride = dst_d.blk_off(0, 0, 0, 1);
+ size_t wht_d_stride = wht_blk_off(weights_d, 0, 0, 0, 1);
+ size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 0, 1);
+ size_t wht_ic_stride = wht_blk_off(weights_d, 0, 0, 1);
+
+ for (int icb_l2 = 0 ; icb_l2 < jcp.nb_ic; icb_l2 += jcp.nb_ic_L2) {
+ start = start_copy;
+ int n{0}, g{0}, occ{0}, oh_s{0}, od_s{0}, owb{0};
+
+ if (jcp.loop_order == loop_cwgn)
+ nd_iterator_init(start,
+ occ, oc_chunks, owb, jcp.nb_ow, g, jcp.ngroups, n, jcp.mb,
+ od_s, jcp.od, oh_s, jcp.oh);
+ else if (jcp.loop_order == loop_gncw)
+ nd_iterator_init(start,
+ g, jcp.ngroups, n, jcp.mb, occ, oc_chunks, owb, jcp.nb_ow,
+ od_s, jcp.od, oh_s, jcp.oh);
+ else
+ assert(!"unsupported loop order");
+
+ while (start < end) {
+ int ocb = occ * jcp.nb_oc_blocking;
+ int g_ocb = g * jcp.nb_oc + ocb;
+ int g_oc = g_ocb * jcp.oc_block;
+ int g_icb = g * jcp.nb_ic * jcp.nonblk_group_off;
+
+ int work_rem = end - start;
+ int ih_s = -jcp.t_pad + oh_s * jcp.stride_h;
+ int ow_s = owb * jcp.ow_block;
+ int iw_s = ow_s * jcp.stride_w;
+ int oh_e = oh_s + work_rem > jcp.oh ? jcp.oh : oh_s + work_rem;
+
+ int id_s = -jcp.f_pad + od_s * jcp.stride_d;
+
+ int dilate_d = jcp.dilate_d + 1;
+ int d_t_overflow = div_up(max(0, -id_s), dilate_d);
+ int d_b_overflow = div_up(
+ max(0, id_s - jcp.id + (jcp.kd - 1) * dilate_d + 1),
+ dilate_d);
+ int kd_padding = nstl::max(0,
+ jcp.kd - d_t_overflow - d_b_overflow);
+
+ auto bias_w = bias ? bias + bias_d.blk_off(g_oc) : 0;
+ auto dst_w = dst + dst_d.blk_off(n, g_ocb, od_s, oh_s, ow_s);
+ auto src_w = src + src_d.blk_off(n, g_icb + icb_l2, id_s, ih_s,
+ iw_s) + d_t_overflow * dilate_d * src_d_stride;
+ auto wht_w = weights + wht_blk_off(weights_d, g, ocb, icb_l2)
+ + d_t_overflow * wht_d_stride;
+
+ for (int icb = icb_l2;
+ icb < min(jcp.nb_ic, icb_l2 + jcp.nb_ic_L2); ++icb) {
+ auto src_c = src_w;
+ auto dst_c = dst_w;
+ for (int oj = oh_s, ij = ih_s;
+ oj < oh_e; ++oj, ij += jcp.stride_h)
+ {
+ int dilate_h = jcp.dilate_h + 1;
+ int i_t_overflow = div_up(max(0, -ij), dilate_h);
+ int i_b_overflow = div_up(
+ max(0, ij - jcp.ih + (jcp.kh - 1) * dilate_h
+ + 1),
+ dilate_h);
+ int kh_padding = nstl::max(0,
+ jcp.kh - i_t_overflow - i_b_overflow);
+ jit_conv_3d_ker_pipeline_ow_thr(kernel_->jit_ker,
+ par_conv,
+ src_c + i_t_overflow * dilate_h * src_h_stride,
+ dst_c, wht_w + i_t_overflow * wht_h_stride,
+ bias_w, icb, kh_padding, kd_padding, owb);
+
+ src_c += src_h_stride * jcp.stride_h;
+ dst_c += dst_h_stride;
+ }
+ src_w += src_c_stride;
+ wht_w += wht_ic_stride;
+ }
+
+ if (jcp.loop_order == loop_cwgn)
+ nd_iterator_jump(start, end,
+ occ, oc_chunks, owb, jcp.nb_ow, g, jcp.ngroups, n, jcp.mb,
+ od_s, jcp.od, oh_s, jcp.oh);
+ else if (jcp.loop_order == loop_gncw)
+ nd_iterator_jump(start, end,
+ g, jcp.ngroups, n, jcp.mb, occ, oc_chunks, owb, jcp.nb_ow,
+ od_s, jcp.od, oh_s, jcp.oh);
+ else
+ assert(!"unsupported loop order");
+ }
+ }
+ jit_conv_3d_ker_pipeline(kernel_->jit_ker, par_conv,
+ src, dst, weights, bias, 0, 0, 0);
+ });
+}
+
+template struct jit_avx512_common_convolution_fwd_t<data_type::f32>;
+
+template <data_type_t diff_dst_type, data_type_t wei_type,
+ data_type_t diff_src_type>
+void jit_avx512_common_convolution_bwd_data_t<diff_dst_type, wei_type,
+ diff_src_type>::execute_backward_data_1d(const exec_ctx_t &ctx) const
+{
+ auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ int start{0}, end{0}, start_copy;
+ int ic_chunks = jcp.nb_ic / jcp.nb_ic_blocking;
+ int work_amount = jcp.ngroups * jcp.mb * ic_chunks * jcp.ih;
+ balance211(work_amount, nthr, ithr, start, end);
+ start_copy = start;
+
+ auto par_conv = jit_conv_call_s();
+ size_t diff_dst_c_stride = diff_dst_d.blk_off(0, 1);
+ size_t wht_oc_stride = wht_blk_off(weights_d, 0, 1);
+
+ for (int ocb_l2 = 0; ocb_l2 < jcp.nb_oc; ocb_l2 += jcp.nb_oc_L2) {
+ start = start_copy;
+ int n{0}, g{0}, icc{0};
+ if (jcp.loop_order == loop_cgn) {
+ int dummy{0};
+ nd_iterator_init(start, icc, ic_chunks, g, jcp.ngroups, n,
+ jcp.mb, dummy, 1);
+ } else if (jcp.loop_order == loop_gnc) {
+ int dummy{0};
+ nd_iterator_init(start, g, jcp.ngroups, n, jcp.mb, icc,
+ ic_chunks, dummy, 1);
+ } else {
+ assert(!"unsupported loop order");
+ }
+
+ while (start < end) {
+ int icb = icc * jcp.nb_ic_blocking;
+ int g_icb = g * jcp.nb_ic + icb;
+ int g_ocb = g * jcp.nb_oc;
+
+ auto diff_src_w = diff_src + diff_src_d.blk_off(n, g_icb);
+ auto diff_dst_w = diff_dst
+ + diff_dst_d.blk_off(n, g_ocb + ocb_l2);
+ auto wht_w = weights + wht_blk_off(weights_d, g, ocb_l2, icb);
+
+ for (int ocb = ocb_l2;
+ ocb < min(jcp.nb_oc, ocb_l2 + jcp.nb_oc_L2); ++ocb) {
+ jit_conv_ker_pipeline(kernel_->jit_ker, par_conv,
+ diff_src_w, diff_dst_w, wht_w, 0, ocb, 1);
+ diff_dst_w += diff_dst_c_stride;
+ wht_w += wht_oc_stride;
+ }
+
+ if (jcp.loop_order == loop_cgn) {
+ int dummy{0};
+ nd_iterator_jump(start, end, icc, ic_chunks, g, jcp.ngroups,
+ n, jcp.mb, dummy, 1);
+ } else if (jcp.loop_order == loop_gnc) {
+ int dummy{0};
+ nd_iterator_jump(start, end, g, jcp.ngroups, n, jcp.mb, icc,
+ ic_chunks, dummy, 1);
+ } else {
+ assert(!"unsupported loop order");
+ }
+ }
+ }
+
+ jit_conv_ker_pipeline(kernel_->jit_ker, par_conv,
+ diff_src, diff_dst, weights, 0, 0, 1);
+ });
+}
+
+template <data_type_t diff_dst_type, data_type_t wei_type,
+ data_type_t diff_src_type>
+void jit_avx512_common_convolution_bwd_data_t<diff_dst_type, wei_type,
+ diff_src_type>::execute_backward_data_2d(const exec_ctx_t &ctx) const
+{
+ auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ int start{0}, end{0}, start_copy;
+ int ic_chunks = jcp.nb_ic / jcp.nb_ic_blocking;
+ int work_amount = jcp.ngroups * jcp.mb * ic_chunks * jcp.ih;
+ balance211(work_amount, nthr, ithr, start, end);
+ start_copy = start;
+
+ auto par_conv = jit_conv_call_s();
+ size_t diff_src_h_stride = diff_src_d.blk_off(0, 0, 1);
+ size_t diff_dst_h_stride = diff_dst_d.blk_off(0, 0, 1);
+ size_t diff_dst_c_stride = diff_dst_d.blk_off(0, 1);
+ size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 1);
+ size_t wht_oc_stride = wht_blk_off(weights_d, 0, 1);
+
+ bool is_fast_path = jcp.dilate_h == 0 && jcp.stride_h == 1;
+
+ for (int ocb_l2 = 0; ocb_l2 < jcp.nb_oc; ocb_l2 += jcp.nb_oc_L2) {
+ start = start_copy;
+ int n{0}, g{0}, icc{0}, ih_s{0};
+ if (jcp.loop_order == loop_cgn)
+ nd_iterator_init(start,
+ icc, ic_chunks, g, jcp.ngroups, n, jcp.mb, ih_s, jcp.ih);
+ else if (jcp.loop_order == loop_gnc)
+ nd_iterator_init(start,
+ g, jcp.ngroups, n, jcp.mb, icc, ic_chunks, ih_s, jcp.ih);
+ else
+ assert(!"unsupported loop order");
+
+ while (start < end) {
+ int icb = icc * jcp.nb_ic_blocking;
+ int g_icb = g * jcp.nb_ic + icb;
+ int g_ocb = g * jcp.nb_oc;
+
+ int work_rem = end - start;
+ int ih_e = ih_s + work_rem > jcp.ih ? jcp.ih : ih_s + work_rem;
+
+ auto diff_src_w = diff_src + diff_src_d.blk_off(n, g_icb);
+ auto diff_dst_w = diff_dst
+ + diff_dst_d.blk_off(n, g_ocb + ocb_l2);
+ auto wht_w = weights + wht_blk_off(weights_d, g, ocb_l2, icb);
+
+ for (int ocb = ocb_l2;
+ ocb < min(jcp.nb_oc, ocb_l2 + jcp.nb_oc_L2); ++ocb) {
+ for (int ij = ih_s; ij < ih_e; ++ij) {
+ int oj, k_len, k_lo;
+ if (is_fast_path) { // dilate == 0 && stride == 1
+ int i_t_overflow = max(0, jcp.kh - 1 - ij
+ - jcp.t_pad);
+ int i_b_overflow = max(0, jcp.kh - jcp.ih + ij
+ - jcp.b_pad);
+ k_len = jcp.kh - i_t_overflow - i_b_overflow;
+ k_lo = i_b_overflow;
+ oj = ij + jcp.t_pad - i_b_overflow;
+ } else if (jcp.dilate_h != 0) { // stride == 1
+ int dilate_h = jcp.dilate_h + 1;
+ // Note: use div_up to account for "holes" in filter
+ int i_t_overflow
+ = div_up(max(0, (jcp.kh - 1) * dilate_h
+ - ij - jcp.t_pad), dilate_h);
+ int i_b_overflow
+ = div_up(max(0, (jcp.kh - 1) * dilate_h + 1
+ - jcp.ih + ij - jcp.b_pad), dilate_h);
+ k_len = jcp.kh - i_t_overflow - i_b_overflow;
+ k_lo = i_b_overflow;
+ oj = ij + jcp.t_pad - i_b_overflow * dilate_h;
+ } else { // dilate == 0
+ int i_t_overflow = max(0, (jcp.kh - 1 - ij
+ - jcp.t_pad) / jcp.stride_h);
+ int i_b_overflow = max(0, (jcp.kh - jcp.ih + ij
+ - jcp.b_pad) / jcp.stride_h);
+ int overflow_kh_hi = jcp.kh - 1 - abs((jcp.ih - 1
+ + jcp.b_pad - ij) % jcp.stride_h);
+ int overflow_kh_lo = (ij + jcp.t_pad)
+ % jcp.stride_h;
+
+ k_len = (overflow_kh_hi - overflow_kh_lo)
+ / jcp.stride_h + 1 - i_t_overflow
+ - i_b_overflow;
+ k_lo = overflow_kh_lo + i_b_overflow * jcp.stride_h;
+ oj = (ij + jcp.t_pad - k_lo) / jcp.stride_h;
+ }
+ assert(k_len >= 0);
+
+ jit_conv_ker_pipeline(kernel_->jit_ker, par_conv,
+ diff_src_w + ij * diff_src_h_stride,
+ diff_dst_w + oj * diff_dst_h_stride,
+ wht_w + k_lo * wht_h_stride,
+ 0, ocb, k_len);
+ }
+ diff_dst_w += diff_dst_c_stride;
+ wht_w += wht_oc_stride;
+ }
+
+ if (jcp.loop_order == loop_cgn)
+ nd_iterator_jump(start, end,
+ icc, ic_chunks, g, jcp.ngroups, n, jcp.mb, ih_s, jcp.ih);
+ else if (jcp.loop_order == loop_gnc)
+ nd_iterator_jump(start, end,
+ g, jcp.ngroups, n, jcp.mb, icc, ic_chunks, ih_s, jcp.ih);
+ else
+ assert(!"unsupported loop order");
+ }
+ }
+
+ jit_conv_ker_pipeline(kernel_->jit_ker, par_conv,
+ diff_src, diff_dst, weights, 0, 0, 1);
+ });
+}
+
+template <data_type_t diff_dst_type, data_type_t wei_type,
+ data_type_t diff_src_type>
+void jit_avx512_common_convolution_bwd_data_t<diff_dst_type, wei_type,
+ diff_src_type>::execute_backward_data_3d(const exec_ctx_t &ctx) const
+{
+ auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ int start{0}, end{0}, start_copy;
+ int ic_chunks = jcp.nb_ic / jcp.nb_ic_blocking;
+ int work_amount = jcp.ngroups * jcp.mb * ic_chunks * jcp.id * jcp.ih;
+ balance211(work_amount, nthr, ithr, start, end);
+ start_copy = start;
+
+ auto par_conv = jit_conv_call_s();
+ size_t diff_src_h_stride = diff_src_d.blk_off(0, 0, 0, 1);
+ size_t diff_src_d_stride = diff_src_d.blk_off(0, 0, 1);
+ size_t diff_dst_h_stride = diff_dst_d.blk_off(0, 0, 0, 1);
+ size_t diff_dst_d_stride = diff_dst_d.blk_off(0, 0, 1);
+ size_t diff_dst_c_stride = diff_dst_d.blk_off(0, 1);
+ size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 0, 1);
+ size_t wht_d_stride = wht_blk_off(weights_d, 0, 0, 0, 1);
+ size_t wht_oc_stride = wht_blk_off(weights_d, 0, 1);
+
+ bool is_fast_path_d = jcp.dilate_d == 0 && jcp.stride_d == 1;
+ bool is_fast_path_h = jcp.dilate_h == 0 && jcp.stride_h == 1;
+
+ for (int ocb_l2 = 0; ocb_l2 < jcp.nb_oc; ocb_l2 += jcp.nb_oc_L2) {
+ start = start_copy;
+ int n{0}, g{0}, icc{0}, ih_s{0}, id_s{0};
+ if (jcp.loop_order == loop_cgn)
+ nd_iterator_init(start,
+ icc, ic_chunks, g, jcp.ngroups, n, jcp.mb, id_s, jcp.id,
+ ih_s, jcp.ih);
+ else if (jcp.loop_order == loop_gnc)
+ nd_iterator_init(start,
+ g, jcp.ngroups, n, jcp.mb, icc, ic_chunks, id_s, jcp.id,
+ ih_s, jcp.ih);
+ else
+ assert(!"unsupported loop order");
+
+ while (start < end) {
+ int icb = icc * jcp.nb_ic_blocking;
+ int g_icb = g * jcp.nb_ic + icb;
+ int g_ocb = g * jcp.nb_oc;
+
+ int work_rem = end - start;
+ int ih_e = ih_s + work_rem > jcp.ih ? jcp.ih : ih_s + work_rem;
+ int d_len = 0, d_lo = 0, d_oj = 0;
+ if (is_fast_path_d) { // dilate == 0 && stride == 1
+ int d_t_overflow = max(0, jcp.kd - 1 - id_s
+ - jcp.f_pad);
+ int d_b_overflow = max(0, jcp.kd - jcp.id + id_s
+ - jcp.back_pad);
+ d_len = jcp.kd - d_t_overflow - d_b_overflow;
+ d_lo = d_b_overflow;
+ d_oj = id_s + jcp.f_pad - d_b_overflow;
+ } else if (jcp.dilate_d != 0) { // stride == 1
+ int dilate_d = jcp.dilate_d + 1;
+ // Note: use div_up to account for "holes" in filter
+ int d_t_overflow = div_up(max(0, (jcp.kd - 1) * dilate_d
+ - id_s - jcp.f_pad), dilate_d);
+ int d_b_overflow = div_up(max(0, (jcp.kd - 1) * dilate_d + 1
+ - jcp.id + id_s - jcp.back_pad), dilate_d);
+ d_len = jcp.kd - d_t_overflow - d_b_overflow;
+ d_lo = d_b_overflow;
+ d_oj = id_s + jcp.f_pad - d_b_overflow * dilate_d;
+ } else { // dilate == 0
+ int d_t_overflow = max(0, (jcp.kd - 1 - id_s
+ - jcp.f_pad) / jcp.stride_d);
+ int d_b_overflow = max(0, (jcp.kd - jcp.id + id_s
+ - jcp.back_pad) / jcp.stride_d);
+ int overflow_kd_hi = jcp.kd - 1 - abs((jcp.id - 1
+ + jcp.back_pad - id_s) % jcp.stride_d);
+ int overflow_kd_lo = (id_s + jcp.f_pad)
+ % jcp.stride_d;
+
+ d_len = (overflow_kd_hi - overflow_kd_lo)
+ / jcp.stride_d + 1 - d_t_overflow
+ - d_b_overflow;
+ d_lo = overflow_kd_lo + d_b_overflow * jcp.stride_d;
+ d_oj = (id_s + jcp.f_pad - d_lo) / jcp.stride_d;
+ }
+ assert(d_len >= 0);
+
+ auto diff_src_w = diff_src + diff_src_d.blk_off(n, g_icb)
+ + id_s * diff_src_d_stride;
+ auto diff_dst_w = diff_dst
+ + diff_dst_d.blk_off(n, g_ocb + ocb_l2)
+ + d_oj * diff_dst_d_stride;
+ auto wht_w = weights + wht_blk_off(weights_d, g, ocb_l2, icb)
+ + d_lo * wht_d_stride;
+
+ for (int ocb = ocb_l2;
+ ocb < min(jcp.nb_oc, ocb_l2 + jcp.nb_oc_L2); ++ocb) {
+ for (int ij = ih_s; ij < ih_e; ++ij) {
+ int oj, k_len, k_lo;
+ if (is_fast_path_h) { // dilate == 0 && stride == 1
+ int i_t_overflow = max(0, jcp.kh - 1 - ij
+ - jcp.t_pad);
+ int i_b_overflow = max(0, jcp.kh - jcp.ih + ij
+ - jcp.b_pad);
+ k_len = jcp.kh - i_t_overflow - i_b_overflow;
+ k_lo = i_b_overflow;
+ oj = ij + jcp.t_pad - i_b_overflow;
+ } else if (jcp.dilate_h != 0) { // stride == 1
+ int dilate_h = jcp.dilate_h + 1;
+ // Note: use div_up to account for "holes" in filter
+ int i_t_overflow
+ = div_up(max(0, (jcp.kh - 1) * dilate_h
+ - ij - jcp.t_pad), dilate_h);
+ int i_b_overflow
+ = div_up(max(0, (jcp.kh - 1) * dilate_h + 1
+ - jcp.ih + ij - jcp.b_pad), dilate_h);
+ k_len = jcp.kh - i_t_overflow - i_b_overflow;
+ k_lo = i_b_overflow;
+ oj = ij + jcp.t_pad - i_b_overflow * dilate_h;
+ } else { // dilate == 0
+ int i_t_overflow = max(0, (jcp.kh - 1 - ij
+ - jcp.t_pad) / jcp.stride_h);
+ int i_b_overflow = max(0, (jcp.kh - jcp.ih + ij
+ - jcp.b_pad) / jcp.stride_h);
+ int overflow_kh_hi = jcp.kh - 1 - abs((jcp.ih - 1
+ + jcp.b_pad - ij) % jcp.stride_h);
+ int overflow_kh_lo = (ij + jcp.t_pad)
+ % jcp.stride_h;
+
+ k_len = (overflow_kh_hi - overflow_kh_lo)
+ / jcp.stride_h + 1 - i_t_overflow
+ - i_b_overflow;
+ k_lo = overflow_kh_lo + i_b_overflow * jcp.stride_h;
+ oj = (ij + jcp.t_pad - k_lo) / jcp.stride_h;
+ }
+ assert(k_len >= 0);
+
+ jit_conv_3d_ker_pipeline(kernel_->jit_ker, par_conv,
+ diff_src_w + ij * diff_src_h_stride,
+ diff_dst_w + oj * diff_dst_h_stride,
+ wht_w + k_lo * wht_h_stride,
+ 0, ocb, k_len, d_len);
+ }
+ diff_dst_w += diff_dst_c_stride;
+ wht_w += wht_oc_stride;
+ }
+
+ if (jcp.loop_order == loop_cgn)
+ nd_iterator_jump(start, end,
+ icc, ic_chunks, g, jcp.ngroups, n, jcp.mb, id_s, jcp.id,
+ ih_s, jcp.ih);
+ else if (jcp.loop_order == loop_gnc)
+ nd_iterator_jump(start, end,
+ g, jcp.ngroups, n, jcp.mb, icc, ic_chunks, id_s, jcp.id,
+ ih_s, jcp.ih);
+ else
+ assert(!"unsupported loop order");
+ }
+ }
+
+ jit_conv_3d_ker_pipeline(kernel_->jit_ker, par_conv,
+ diff_src, diff_dst, weights, 0, 0, 1, 1);
+ });
+}
+
+template struct jit_avx512_common_convolution_bwd_data_t<data_type::f32>;
+
+template <data_type_t src_type, data_type_t diff_dst_type,
+ data_type_t diff_weights_type>
+jit_avx512_common_convolution_bwd_weights_t<src_type, diff_dst_type,
+ diff_weights_type>::
+jit_avx512_common_convolution_bwd_weights_t(const pd_t *apd)
+ : cpu_primitive_t(apd), kernel_(nullptr)
+ , trans_kernel_(nullptr), acc_ker_(nullptr), reducer_bias_(nullptr)
+{
+ const auto &j = pd()->jcp_;
+
+ nthr_ = j.nthr;
+ nthr_mb_ = j.nthr_mb;
+ nthr_g_ = j.nthr_g;
+ nthr_oc_b_ = j.nthr_oc_b;
+ nthr_ic_b_ = j.nthr_ic_b;
+
+ kernel_ = new jit_avx512_common_conv_bwd_weights_kernel_f32(j);
+
+ if (j.ver == ver_4fma)
+ trans_kernel_ = create_trans_src(&j);
+
+ if (nthr_mb_ > 1)
+ acc_ker_ = new cpu_accumulator_1d_t<diff_weights_type>();
+
+ reducer_bias_ =
+ new cpu_reducer_t<diff_weights_type>(pd()->reducer_bia_conf_);
+}
+
+template <data_type_t src_type, data_type_t diff_dst_type,
+ data_type_t diff_weights_type>
+struct jit_avx512_common_convolution_bwd_weights_t<src_type, diff_dst_type,
+ diff_weights_type>::thread_info_t {
+ const src_data_t *src;
+ const diff_dst_data_t *diff_dst;
+ const diff_weights_data_t *diff_weights;
+ diff_weights_data_t *diff_bias;
+
+ const memory_tracking::grantor_t scratchpad;
+
+ src_data_t *tr_src;
+ simple_barrier::ctx_t *tr_src_bctx;
+
+ diff_dst_data_t *tr_diff_dst;
+ simple_barrier::ctx_t *tr_diff_dst_bctx;
+
+ diff_weights_data_t *wei_bia_reduction;
+ simple_barrier::ctx_t *wei_bia_reduction_bctx;
+
+ int ithr;
+ int ithr_ic_b, ithr_oc_b, ithr_g, ithr_mb;
+ int ithr_but_oc;
+ int ithr_but_ic;
+
+ int img_start = 0, img_end = 0, img_work;
+ int g_start = 0, g_end = 0, g_work;
+ int oc_b_start = 0, oc_b_end = 0, oc_b_work;
+ int ic_b_start = 0, ic_b_end = 0, ic_b_work;
+
+ thread_info_t(const jit_avx512_common_convolution_bwd_weights_t *self,
+ const exec_ctx_t &ctx, int ithr)
+ : scratchpad(self->scratchpad(ctx)), ithr(ithr)
+ {
+ diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST);
+ src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ diff_weights = CTX_OUT_MEM(diff_weights_data_t *, MKLDNN_ARG_DIFF_WEIGHTS);
+ diff_bias = self->pd()->wants_padded_bias()
+ ? scratchpad.template get<diff_weights_data_t>(
+ key_conv_padded_bias)
+ : CTX_OUT_MEM(diff_weights_data_t *, MKLDNN_ARG_DIFF_BIAS);
+
+ tr_src = scratchpad.template get<src_data_t>(key_conv_tr_src);
+ tr_src_bctx = scratchpad.template get<simple_barrier::ctx_t>(
+ key_conv_tr_src_bctx);
+
+ tr_diff_dst = scratchpad.template get<diff_dst_data_t>(
+ key_conv_tr_diff_dst);
+ tr_diff_dst_bctx = scratchpad.template get<simple_barrier::ctx_t>(
+ key_conv_tr_diff_dst_bctx);
+
+ wei_bia_reduction = scratchpad.template get<diff_weights_data_t>(
+ key_conv_wei_bia_reduction);
+ wei_bia_reduction_bctx = scratchpad.template get<simple_barrier::ctx_t>(
+ key_conv_wei_bia_reduction_bctx);
+
+ ithr_ic_b = ithr % self->nthr_ic_b_;
+ ithr_oc_b = ithr / self->nthr_ic_b_ % self->nthr_oc_b_;
+ ithr_g = ithr / self->nthr_ic_b_ / self->nthr_oc_b_ % self->nthr_g_;
+ ithr_mb = ithr / self->nthr_ic_b_ / self->nthr_oc_b_ / self->nthr_g_;
+
+ ithr_but_oc = (ithr_mb * self->nthr_g_ + ithr_g) * self->nthr_ic_b_
+ + ithr_ic_b;
+
+ ithr_but_ic = (ithr_mb * self->nthr_g_ + ithr_g) * self->nthr_oc_b_
+ + ithr_oc_b;
+
+ const auto &jcp = self->kernel_->jcp;
+
+ /* reduction dimension */
+ balance211(jcp.mb*jcp.od, self->nthr_mb_, ithr_mb, img_start, img_end);
+ img_work = img_end - img_start;
+
+ /* independent dimensions */
+ balance211(jcp.ngroups, self->nthr_g_, ithr_g, g_start, g_end);
+ g_work = g_end - g_start;
+
+ balance211(jcp.nb_oc, self->nthr_oc_b_, ithr_oc_b, oc_b_start,
+ oc_b_end);
+ oc_b_work = oc_b_end - oc_b_start;
+
+ balance211(jcp.nb_ic, self->nthr_ic_b_, ithr_ic_b, ic_b_start,
+ ic_b_end);
+ ic_b_work = ic_b_end - ic_b_start;
+ }
+};
+
+template <data_type_t src_type, data_type_t diff_dst_type,
+ data_type_t diff_weights_type>
+void jit_avx512_common_convolution_bwd_weights_t<src_type, diff_dst_type,
+ diff_weights_type>::compute_diff_weights(const thread_info_t *ti) const {
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+ const int wei_size = jcp.ngroups * jcp.oc * jcp.ic * jcp.kh*jcp.kw*jcp.kd;
+
+ diff_weights_data_t *diff_wei = ti->ithr_mb == 0
+ ? (diff_weights_data_t*)ti->diff_weights
+ : ti->wei_bia_reduction + (ti->ithr_mb - 1) * wei_size;
+ diff_weights_data_t *diff_bia = ti->ithr_mb == 0
+ ? (diff_weights_data_t*)ti->diff_bias
+ : ti->wei_bia_reduction + (nthr_mb_ - 1) * wei_size
+ + (ti->ithr_mb - 1) * jcp.ngroups * jcp.oc;
+
+ // TODO: use memory descriptor with the same fmt as src (or use a macro :))
+ auto tr_src_off = [&](int ithr_mb, int ic, int ij) {
+ const size_t tr_row_size = jcp.tr_iw * jcp.ic_block;
+ const size_t tr_chn_size = tr_row_size * jcp.ih;
+ const size_t tr_img_size = tr_chn_size * jcp.nb_ic * jcp.ngroups;
+
+ return ti->ithr_mb * tr_img_size + ic * tr_chn_size + ij * tr_row_size;
+ };
+
+ auto uker_trans = [&](int img) {
+ const int work_amount = ti->g_work * ti->ic_b_work * jcp.ih;
+
+ int start{0}, end{0};
+ balance211(work_amount, nthr_oc_b_, ti->ithr_oc_b, start, end);
+ const int my_work = end - start;
+
+ int g{0}, ic_b{0}, j{0};
+ nd_iterator_init(start, g, ti->g_work, ic_b, ti->ic_b_work, j, jcp.ih);
+ g += ti->g_start;
+ ic_b += ti->ic_b_start;
+
+ const int _ic = g * jcp.nb_ic + ic_b;
+ src_data_t *src1 = (src_data_t*)&ti->src[src_d.blk_off(img, _ic, j)];
+ src_data_t *tr_src1 = &ti->tr_src[tr_src_off(ti->ithr_mb, _ic, j)];
+
+ assert(jcp.ic_block == 16);
+ const int src_stride = jcp.iw * jcp.ic_block;
+ const int tr_src_stride = jcp.tr_iw * jcp.ic_block;
+
+ const int pf_depth = 2;
+ struct { src_data_t *src, *tr_src; } pf_circ_buf[pf_depth];
+
+ for (int iwork = 0; iwork < my_work + pf_depth - 1; iwork++) {
+ pf_circ_buf[iwork % pf_depth] = {src1, tr_src1};
+
+ if (iwork >= pf_depth - 1) {
+ int old_idx = (iwork - pf_depth + 1) % pf_depth;
+ auto ctx = jit_trans_src_t::ctx_t();
+ ctx.src = pf_circ_buf[old_idx].src;
+ ctx.tr_src = pf_circ_buf[old_idx].tr_src;
+ ctx.src_prf = src1;
+ ctx.tr_src_prf = tr_src1;
+ (*trans_kernel_)(&ctx);
+ }
+ src1 += src_stride;
+ tr_src1 += tr_src_stride;
+ }
+#if 0
+ // reference transposition
+ const int l_pad = jcp.l_pad;
+ const int iwlp = l_pad + jcp.iw;
+ const int tr_iw = jcp.tr_iw;
+
+ for (size_t iwork = start; iwork < end; iwork++) {
+ PRAGMA_OMP_SIMD()
+# pragma unroll
+ for (int i = 0; i < l_pad; i++)
+ for (int j = 0; j < jcp.ic_block; j++)
+ tr_src1[j * jcp.tr_iw + i] = (src_data_t)0.0;
+
+ PRAGMA_OMP_SIMD()
+# pragma unroll
+ for (int i = l_pad; i < iwlp; i++)
+ for (int j = 0; j < jcp.ic_block; j++)
+ tr_src1[j * jcp.tr_iw + i]
+ = (src_data_t)src1[(i - l_pad) * 16 + j];
+
+ PRAGMA_OMP_SIMD()
+# pragma unroll
+ for (int i = iwlp; i < tr_iw; i++)
+ for (int j = 0; j < jcp.ic_block; j++)
+ tr_src1[j * jcp.tr_iw + i] = (src_data_t)0.0;
+
+ src1 += src_stride;
+ tr_src1 += tr_src_stride;
+ }
+#endif
+ };
+
+ if (jcp.is_1stconv && jcp.ver == ver_4fma) {
+ /* prepare contexts */
+ auto tr_ctx = jit_trans_src_t::ctx_t();
+ tr_ctx.tr_src = ti->tr_src
+ + ti->ithr_but_oc * jcp.ih * jcp.stride_w * jcp.tr_ld;
+
+ assert(IMPLICATION(!mkldnn_thr_syncable(), nthr_oc_b_ == 1));
+ tr_ctx.nthr_oc_b = nthr_oc_b_;
+ int ih_start{0}, ih_end{0};
+ balance211(jcp.ih, nthr_oc_b_, ti->ithr_oc_b, ih_start, ih_end);
+ tr_ctx.tr_src_ih_start = ih_start;
+ tr_ctx.tr_src_ih_end = ih_end;
+ tr_ctx.tr_src_bctx = ti->tr_src_bctx + ti->ithr_but_oc;
+
+ auto p = jit_conv_call_s();
+ p.src = tr_ctx.tr_src;
+
+ /* zero diff_bias if applicable */
+ if (jcp.with_bias && ti->ithr_ic_b == 0) {
+ assert(jcp.oc_block == 16);
+ for (int oc_b = ti->ic_b_start; oc_b < ti->oc_b_end; ++oc_b) {
+ diff_weights_data_t *db = &diff_bia[oc_b * 16];
+ for (int o = 0; o < 16; ++o)
+ db[o] = 0;
+ }
+ }
+
+ for (int img = ti->img_start; img < ti->img_end; ++img) {
+ p.flags = (img == ti->img_start) * FLAG_MB_FIRST;
+
+ for (int g = ti->g_start; g < ti->g_end; ++g) {
+ for (int ic_b = ti->ic_b_start; ic_b < ti->ic_b_end; ++ic_b) {
+ const int _ic = g * jcp.nb_ic + ic_b;
+ tr_ctx.src = &ti->src[src_d.blk_off(img, _ic)];
+
+ (*trans_kernel_)(&tr_ctx);
+
+ if (ic_b == 0)
+ p.flags |= FLAG_IC_FIRST;
+ else
+ p.flags &= ~FLAG_IC_FIRST;
+
+ for (int oc_b = ti->oc_b_start; oc_b < ti->oc_b_end; ++oc_b) {
+ const int _oc = g * jcp.nb_oc + oc_b;
+ p.dst = &ti->diff_dst[diff_dst_d.blk_off(img, _oc)];
+
+ const size_t off =
+ wht_blk_off(diff_weights_d, g, oc_b, ic_b);
+ p.filt = diff_wei + off;
+ p.bias = diff_bia + _oc * jcp.oc_block;
+
+ kernel_->jit_ker(&p);
+ }
+ }
+ }
+ }
+ } else {
+ for (int img = ti->img_start; img < ti->img_end; ++img) {
+ auto p = jit_conv_call_s();
+
+ if (jcp.ver == ver_4fma) {
+ /* tr_src[nb_ic][ih][16][~iw~] <- src[nb_ic][ih][iw][16] */
+ using simple_barrier::barrier;
+ if (nthr_oc_b_ > 1)
+ barrier(&ti->tr_src_bctx[ti->ithr_but_oc], nthr_oc_b_);
+ uker_trans(img);
+ if (nthr_oc_b_ > 1)
+ barrier(&ti->tr_src_bctx[ti->ithr_but_oc], nthr_oc_b_);
+ }
+
+ for (int g = ti->g_start; g < ti->g_end; ++g) {
+ for (int oc_b = ti->oc_b_start; oc_b < ti->oc_b_end; ++oc_b) {
+ for (int ic_b = ti->ic_b_start; ic_b < ti->ic_b_end; ++ic_b) {
+ const int _oc = g * jcp.nb_oc + oc_b;
+ const int _ic = g * jcp.nb_ic + ic_b;
+
+ jit_conv_ker_pipeline(kernel_->jit_ker, p,
+ jcp.ver == ver_4fma
+ ? &ti->tr_src[tr_src_off(ti->ithr_mb, _ic, 0)]
+ : &ti->src[src_d.blk_off(img, _ic)],
+ &ti->diff_dst[diff_dst_d.blk_off(img, _oc)],
+ diff_wei + wht_blk_off(diff_weights_d, g, oc_b, ic_b),
+ 0, (img == ti->img_start), 0);
+
+ }
+ }
+ }
+
+ const int _oc = ti->g_start * jcp.nb_oc + ti->oc_b_start;
+ const int _ic = ti->g_start * jcp.nb_ic + ti->ic_b_start;
+ jit_conv_ker_pipeline(kernel_->jit_ker, p,
+ jcp.ver == ver_4fma
+ ? &ti->tr_src[tr_src_off(ti->ithr_mb, _ic, 0)]
+ : &ti->src[src_d.blk_off(img + 1, _ic)],
+ &ti->diff_dst[diff_dst_d.blk_off(img + 1, _oc)],
+ diff_wei + wht_blk_off(
+ diff_weights_d, ti->g_start,
+ ti->oc_b_start, ti->ic_b_start),
+ 0, 0, 0);
+ }
+ }
+}
+
+template <data_type_t src_type, data_type_t diff_dst_type,
+ data_type_t diff_weights_type>
+void jit_avx512_common_convolution_bwd_weights_t<src_type, diff_dst_type,
+ diff_weights_type>::compute_diff_weights_3d(const thread_info_t *ti) const
+{
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+ const int wei_size
+ = jcp.ngroups * jcp.oc * jcp.ic * jcp.kh * jcp.kw * jcp.kd;
+
+ diff_weights_data_t *diff_wei = ti->ithr_mb == 0
+ ? (diff_weights_data_t*)ti->diff_weights
+ : ti->wei_bia_reduction + (ti->ithr_mb - 1) * wei_size;
+ diff_weights_data_t *diff_bia = ti->ithr_mb == 0
+ ? (diff_weights_data_t*)ti->diff_bias
+ : ti->wei_bia_reduction + (nthr_mb_ - 1) * wei_size
+ + (ti->ithr_mb - 1) * jcp.ngroups * jcp.oc;
+
+ const int inp_mult = jcp.is_1stconv ? 1 : jcp.ic_block;
+ const int input_step = jcp.ih * jcp.iw * inp_mult;
+ const int output_step = jcp.ow * jcp.oh * jcp.oc_block;
+ int img{0}, od_s{0};
+ int img_start = ti->img_start, img_end = ti->img_end;
+ nd_iterator_init(img_start, img, jcp.mb, od_s, jcp.od);
+ const int img_first = img;
+
+ while (img_start < img_end) {
+ auto p = jit_conv_call_s();
+
+ int work_rem = img_end - img_start;
+ const int od_e = od_s + work_rem > jcp.od ? jcp.od : od_s + work_rem;
+ const int id_s = od_s * jcp.stride_d;
+ const int ik_overlap = nstl::max(0, id_s - jcp.f_pad);
+ const int kd_front_pad = nstl::max(0, jcp.f_pad - id_s);
+ const int kd_back_pad
+ = nstl::max(0, id_s - jcp.f_pad - jcp.id + jcp.kd);
+ int kd_pad_off = nstl::min(jcp.kd - 1, kd_front_pad) * jcp.kh * jcp.kw
+ * jcp.ic_block * jcp.oc_block * jcp.typesize_out;
+
+ for (int g = ti->g_start; g < ti->g_end; ++g) {
+ for (int oc_b = ti->oc_b_start; oc_b < ti->oc_b_end; ++oc_b) {
+ for (int ic_b = ti->ic_b_start; ic_b < ti->ic_b_end; ++ic_b) {
+ const int _oc = g * jcp.nb_oc + oc_b;
+ const int _ic = g * jcp.nb_ic + ic_b;
+
+ auto src = &ti->src[src_d.blk_off(img, _ic)
+ + ik_overlap * input_step];
+ auto dst = &ti->diff_dst[diff_dst_d.blk_off(img, _oc)
+ + od_s * output_step];
+
+ jit_conv_3d_ker_bwd_w_pipeline(kernel_->jit_ker, p, src, dst,
+ diff_wei + wht_blk_off(diff_weights_d, g, oc_b, ic_b),
+ diff_bia + _oc * 16, (img == img_first), od_s, od_e,
+ jcp.kd - kd_front_pad - kd_back_pad, kd_pad_off);
+
+ if (ic_b == 0) p.flags = 0;
+ else p.flags = 1;
+ }
+ }
+ }
+
+ const int _oc = ti->g_start * jcp.nb_oc + ti->oc_b_start;
+ const int _ic = ti->g_start * jcp.nb_ic + ti->ic_b_start;
+ jit_conv_3d_ker_bwd_w_pipeline(kernel_->jit_ker, p,
+ &ti->src[src_d.blk_off(img + 1, _ic)],
+ &ti->diff_dst[diff_dst_d.blk_off(img + 1, _oc)],
+ diff_wei + wht_blk_off(diff_weights_d, ti->g_start,
+ ti->oc_b_start, ti->ic_b_start),
+ diff_bia, 0, 0, 0, 0, 0);
+ nd_iterator_jump(img_start, img_end, img, jcp.mb, od_s, jcp.od);
+ }
+}
+
+template <data_type_t src_type, data_type_t diff_dst_type,
+ data_type_t diff_weights_type>
+void jit_avx512_common_convolution_bwd_weights_t<src_type, diff_dst_type,
+ diff_weights_type>::reduce_diff_weights(const thread_info_t *ti) const {
+ const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+ const int wei_size = jcp.ngroups * jcp.oc * jcp.ic * jcp.kh * jcp.kw;
+ const int bia_size = jcp.ngroups * jcp.oc;
+ const diff_weights_data_t *diff_bias_ws
+ = ti->wei_bia_reduction + (nthr_mb_ - 1) * wei_size;
+
+ /* diff_weights[:] += sum(wei_reduction_[thr_mb][:]) */
+ simple_barrier::barrier(ti->wei_bia_reduction_bctx, nthr_);
+
+ const int ic_b_kh_work = ti->ic_b_work * jcp.kh;
+ const int work = ti->g_work * ti->oc_b_work * ic_b_kh_work;
+
+ int start{0}, end{0};
+ balance211(work, nthr_mb_, ti->ithr_mb, start, end);
+ if (start == end) return;
+
+ for (int thr_mb = 1; thr_mb < nthr_mb_; ++thr_mb) {
+ int w = start;
+ int sub_g_start{0}, sub_oc_b_start{0}, sub_ic_b_kh_start{0};
+ nd_iterator_init(w, sub_g_start, ti->g_work, sub_oc_b_start,
+ ti->oc_b_work, sub_ic_b_kh_start, ic_b_kh_work);
+ while (w < end) {
+ const int g = ti->g_start + sub_g_start;
+ const int oc_b = ti->oc_b_start + sub_oc_b_start;
+ const int ic_b = ti->ic_b_start + sub_ic_b_kh_start / jcp.kh;
+ const int kh = sub_ic_b_kh_start % jcp.kh;
+
+ const int acc_size
+ = nstl::min(end - w, ic_b_kh_work - sub_ic_b_kh_start)
+ * jcp.kw * jcp.ic_block * jcp.oc_block;
+
+ const size_t off
+ = wht_blk_off(diff_weights_d, g, oc_b, ic_b, kh);
+
+ diff_weights_data_t *d
+ = (diff_weights_data_t *)ti->diff_weights + off;
+ diff_weights_data_t *s
+ = ti->wei_bia_reduction + (thr_mb - 1) * wei_size + off;
+
+ acc_ker_->accumulate(d, s, acc_size);
+
+ nd_iterator_jump(w, end, sub_g_start, ti->g_work, sub_oc_b_start,
+ ti->oc_b_work, sub_ic_b_kh_start, ic_b_kh_work);
+ }
+
+ if (jcp.with_bias && jcp.is_1stconv && jcp.ver == ver_4fma) {
+ if (ti->ithr == 0)
+ acc_ker_->accumulate((diff_weights_data_t *)ti->diff_bias,
+ diff_bias_ws, bia_size);
+ diff_bias_ws += bia_size;
+ }
+ }
+}
+
+template <data_type_t src_type, data_type_t diff_dst_type,
+ data_type_t diff_weights_type>
+void jit_avx512_common_convolution_bwd_weights_t<src_type, diff_dst_type,
+ diff_weights_type>::reduce_diff_weights_3d(const thread_info_t *ti) const {
+ const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+ const int wei_size = jcp.ngroups * jcp.oc * jcp.ic * jcp.kh * jcp.kw
+ * jcp.kd;
+
+ /* diff_weights[:] += sum(wei_reduction_[thr_mb][:]) */
+ simple_barrier::barrier(ti->wei_bia_reduction_bctx, nthr_);
+
+ const int ic_b_kh_work = ti->ic_b_work * jcp.kd;
+ const int work = ti->g_work * ti->oc_b_work * ic_b_kh_work;
+
+ int start{0}, end{0};
+ balance211(work, nthr_mb_, ti->ithr_mb, start, end);
+ if (start == end) return;
+
+ for (int thr_mb = 1; thr_mb < nthr_mb_; ++thr_mb) {
+ int w = start;
+ int sub_g_start{0}, sub_oc_b_start{0}, sub_ic_b_kh_start{0};
+ nd_iterator_init(w, sub_g_start, ti->g_work, sub_oc_b_start,
+ ti->oc_b_work, sub_ic_b_kh_start, ic_b_kh_work);
+ while (w < end) {
+ const int g = ti->g_start + sub_g_start;
+ const int oc_b = ti->oc_b_start + sub_oc_b_start;
+ const int ic_b = ti->ic_b_start + sub_ic_b_kh_start / jcp.kd;
+ const int kd = sub_ic_b_kh_start % jcp.kd;
+
+ const int acc_size
+ = nstl::min(end - w, ic_b_kh_work - sub_ic_b_kh_start)
+ * jcp.kw * jcp.ic_block * jcp.oc_block * jcp.kh;
+
+ const size_t off
+ = wht_blk_off(diff_weights_d, g, oc_b, ic_b, kd);
+ diff_weights_data_t *d
+ = (diff_weights_data_t *)ti->diff_weights + off;
+ diff_weights_data_t *s
+ = ti->wei_bia_reduction + (thr_mb - 1) * wei_size + off;
+ acc_ker_->accumulate(d, s, acc_size);
+
+ nd_iterator_jump(w, end, sub_g_start, ti->g_work, sub_oc_b_start,
+ ti->oc_b_work, sub_ic_b_kh_start, ic_b_kh_work);
+ }
+ }
+}
+
+template <data_type_t src_type, data_type_t diff_dst_type,
+ data_type_t diff_weights_type>
+void jit_avx512_common_convolution_bwd_weights_t<src_type, diff_dst_type,
+ diff_weights_type>::compute_diff_bias(const thread_info_t *ti) const {
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+
+ auto rb = this->reducer_bias_;
+ assert(nthr_ == rb->balancer().nthr_);
+
+ const auto reducer_bia_scratchpad = memory_tracking::grantor_t(
+ ti->scratchpad, prefix_reducer_bia);
+
+ const auto &jcp = kernel_->jcp;
+
+ if (jcp.with_bias && jcp.is_1stconv && jcp.ver == ver_4fma) return;
+
+ const int b_job_start = rb->balancer().ithr_job_off(ti->ithr);
+ const int b_njobs = rb->balancer().ithr_njobs(ti->ithr);
+
+ if (b_njobs == 0) return;
+
+ /* reduction dimension */
+ int img_start{0}, img_end{0};
+ balance211(jcp.mb, rb->balancer().nthr_per_group_,
+ rb->balancer().id_in_group(ti->ithr), img_start, img_end);
+
+ /* jobs */
+ int g_start{0}, ocb_start{0};
+ nd_iterator_init(b_job_start, g_start, jcp.ngroups, ocb_start, jcp.nb_oc);
+ for (int img = img_start; img < img_end; ++img) {
+ int g = g_start, ocb = ocb_start;
+ for (int b_job_loc = 0; b_job_loc < b_njobs; ++b_job_loc) {
+ const size_t _oc = g * jcp.nb_oc + ocb;
+
+ const diff_dst_data_t *d_dst
+ = &ti->diff_dst[diff_dst_d.blk_off(img, _oc)];
+ diff_weights_data_t *d_bias = rb->get_local_ptr(ti->ithr,
+ ti->diff_bias, reducer_bia_scratchpad)
+ + b_job_loc * rb->balancer().job_size_;
+
+ if (img == img_start)
+ for (int o = 0; o < 16; ++o)
+ d_bias[o] = 0;
+ for (int hw = 0; hw < jcp.oh * jcp.ow * jcp.od; ++hw) {
+ PRAGMA_OMP_SIMD()
+ for (int o = 0; o < 16; ++o)
+ d_bias[o] += d_dst[o];
+ d_dst += 16;
+ }
+
+ nd_iterator_step(g, jcp.ngroups, ocb, jcp.nb_oc);
+ }
+ }
+
+ rb->reduce(ti->ithr, ti->diff_bias, reducer_bia_scratchpad);
+}
+
+template <data_type_t src_type, data_type_t diff_dst_type,
+ data_type_t diff_weights_type>
+void jit_avx512_common_convolution_bwd_weights_t<src_type, diff_dst_type,
+ diff_weights_type>::compute_diff_bias_3d(const thread_info_t *ti) const {
+
+ const auto &jcp = kernel_->jcp;
+
+ const size_t wei_size = (size_t)jcp.ngroups * jcp.oc * jcp.ic * jcp.kh
+ * jcp.kw * jcp.kd;
+ const int bia_size = jcp.ngroups * jcp.oc;
+ const diff_weights_data_t *diff_bias_ws
+ = ti->wei_bia_reduction + (size_t)(nthr_mb_ - 1) * wei_size;
+
+ if (nthr_mb_ > 1) mkldnn_thr_barrier();
+
+ if (ti->ithr == 0)
+ {
+ for (int thr_mb = 1; thr_mb < nthr_mb_; ++thr_mb) {
+ acc_ker_->accumulate(ti->diff_bias, diff_bias_ws, bia_size);
+ diff_bias_ws += bia_size;
+ }
+ }
+}
+
+template <data_type_t src_type, data_type_t diff_dst_type,
+ data_type_t diff_weights_type>
+void jit_avx512_common_convolution_bwd_weights_t<src_type, diff_dst_type,
+ diff_weights_type>::prepare_scratchpad_data(const exec_ctx_t &ctx) const
+{
+ const auto &j = pd()->jcp_;
+ auto scratchpad = this->scratchpad(ctx);
+
+ if (j.ver == ver_4fma) {
+ if (!j.is_1stconv) {
+ // XXX: See the comment about tr_iw and guarding elements in
+ // jit_avx512_common_conv_bwd_weights_kernel_f32::init_conf()
+ const int max_nthr = j.nthr_mb * j.ngroups * j.nb_ic;
+ const int min_tr_src_size_per_thr = j.ih * j.ic_block * j.tr_iw;
+
+ auto tr_src = scratchpad.template get<src_data_t>(key_conv_tr_src);
+ /* to avoid NaNs in computations we zero tail num_guard_elems for
+ * each possible thread group */
+
+ for (int ithr = 1; ithr <= max_nthr; ++ithr) {
+ src_data_t *ts = &tr_src[ithr * min_tr_src_size_per_thr];
+ for (int i = 0; i < j.tr_src_num_guard_elems; ++i)
+ ts[i] = 0;
+ }
+ }
+
+ if (j.nthr_oc_b > 1) {
+ const int tr_src_bctx_size = j.nthr / j.nthr_oc_b;
+ auto tr_src_bctx = scratchpad.template get<simple_barrier::ctx_t>(
+ key_conv_tr_src_bctx);
+ for (int i = 0; i < tr_src_bctx_size; ++i)
+ simple_barrier::ctx_init(&tr_src_bctx[i]);
+ }
+ }
+
+ if (nthr_mb_ > 1) {
+ simple_barrier::ctx_init(scratchpad.template get<simple_barrier::ctx_t>(
+ key_conv_wei_bia_reduction_bctx));
+ }
+
+ const auto reducer_bia_scratchpad = memory_tracking::grantor_t(scratchpad,
+ prefix_reducer_bia);
+ auto rb = this->reducer_bias_;
+ rb->init(reducer_bia_scratchpad);
+}
+
+template <data_type_t src_type, data_type_t diff_dst_type,
+ data_type_t diff_weights_type>
+void jit_avx512_common_convolution_bwd_weights_t<src_type, diff_dst_type,
+ diff_weights_type>::execute_backward_weights(const exec_ctx_t &ctx) const {
+ prepare_scratchpad_data(ctx);
+
+ parallel(nthr_, [&](const int ithr, const int nthr) {
+ assert(nthr_ == nthr);
+
+ thread_info_t thread_info(this, ctx, ithr);
+
+ if (utils::one_of(pd()->ndims(), 3, 4)) {
+ compute_diff_weights(&thread_info);
+ if (nthr_mb_ > 1) reduce_diff_weights(&thread_info);
+ if (pd()->with_bias()) compute_diff_bias(&thread_info);
+ } else if (pd()->ndims() == 5) {
+ compute_diff_weights_3d(&thread_info);
+ if (nthr_mb_ > 1) reduce_diff_weights_3d(&thread_info);
+ if (pd()->with_bias()) compute_diff_bias_3d(&thread_info);
+ } else {
+ assert(false);
+ }
+ });
+
+ /* TODO: put that into compute_diff_bias() */
+ if (pd()->wants_padded_bias()) {
+ auto diff_bias = scratchpad(ctx).template get<const diff_weights_data_t>(
+ key_conv_padded_bias);
+ auto diff_bias_in = CTX_OUT_MEM(diff_weights_data_t *, MKLDNN_ARG_DIFF_BIAS);
+ for (int oc = 0; oc < pd()->jcp_.oc_without_padding; ++oc)
+ diff_bias_in[oc] = diff_bias[oc];
+ }
+}
+
+template struct jit_avx512_common_convolution_bwd_weights_t<data_type::f32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.hpp
new file mode 100644
index 0000000000..3341c3ebe0
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution.hpp
@@ -0,0 +1,302 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_COMMON_CONVOLUTION_HPP
+#define CPU_JIT_AVX512_COMMON_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "cpu_barrier.hpp"
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+#include "cpu_reducer.hpp"
+
+#include "jit_transpose_src_utils.hpp"
+#include "jit_avx512_common_conv_kernel.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t src_type,
+ impl::data_type_t wei_type = src_type,
+ impl::data_type_t dst_type = src_type>
+struct jit_avx512_common_convolution_fwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_()
+ {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", avx512_common, ""),
+ jit_avx512_common_convolution_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(src_type, wei_type, dst_type, dst_type,
+ data_type::undef)
+ && !has_zero_dim_memory();
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_avx512_common_conv_fwd_kernel::init_conf(
+ jcp_, *desc(), src_md_, weights_md_, dst_md_, bias_md_,
+ *attr(), mkldnn_get_max_threads());
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx512_common_conv_fwd_kernel::init_scratchpad(scratchpad,
+ jcp_);
+
+ return status;
+ }
+
+ jit_conv_conf_t jcp_;
+ };
+
+ jit_avx512_common_convolution_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ {
+ kernel_ = new jit_avx512_common_conv_fwd_kernel(pd()->jcp_,
+ *pd()->attr());
+ }
+ ~jit_avx512_common_convolution_fwd_t() { delete kernel_; }
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<wei_type>::type wei_data_t;
+ typedef typename prec_traits<dst_type>::type dst_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ if (pd()->ndims() == 3)
+ execute_forward_1d(ctx);
+ else if (pd()->ndims() == 4)
+ execute_forward_2d(ctx);
+ else if (pd()->ndims() == 5)
+ execute_forward_3d(ctx);
+ else
+ assert(false);
+
+ if (pd()->wants_zero_pad_dst())
+ ctx.memory(MKLDNN_ARG_DST)->zero_pad();
+
+ return status::success;
+ }
+
+private:
+ void prepare_padded_bias(const dst_data_t *&bias,
+ const memory_tracking::grantor_t &scratchpad) const;
+ void execute_forward_1d(const exec_ctx_t &ctx) const;
+ void execute_forward_2d(const exec_ctx_t &ctx) const;
+ void execute_forward_3d(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx512_common_conv_fwd_kernel *kernel_;
+};
+
+template <impl::data_type_t diff_dst_type,
+ impl::data_type_t wei_type = diff_dst_type,
+ impl::data_type_t diff_src_type = diff_dst_type>
+struct jit_avx512_common_convolution_bwd_data_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_data_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_()
+ {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", avx512_common, ""),
+ jit_avx512_common_convolution_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_data
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(diff_src_type, wei_type,
+ data_type::undef, diff_dst_type, data_type::undef)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ status_t status =
+ jit_avx512_common_conv_bwd_data_kernel_f32::init_conf(jcp_,
+ *desc(), *diff_src_md(), *weights_md(), *diff_dst_md());
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx512_common_conv_bwd_data_kernel_f32::init_scratchpad(
+ scratchpad, jcp_);
+
+ return status::success;
+ }
+
+ jit_conv_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c);
+ auto wei_tag = utils::pick(2 * ndims() - 6 + with_groups(),
+ OIw16o16i, gOIw16o16i, OIhw16o16i, gOIhw16o16i,
+ OIdhw16o16i, gOIdhw16o16i);
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ jit_avx512_common_convolution_bwd_data_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ { kernel_ = new jit_avx512_common_conv_bwd_data_kernel_f32(pd()->jcp_); }
+ ~jit_avx512_common_convolution_bwd_data_t() { delete kernel_; };
+
+ typedef typename prec_traits<diff_dst_type>::type diff_dst_data_t;
+ typedef typename prec_traits<wei_type>::type wei_data_t;
+ typedef typename prec_traits<diff_src_type>::type diff_src_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ if (pd()->ndims() == 3)
+ execute_backward_data_1d(ctx);
+ else if (pd()->ndims() == 4)
+ execute_backward_data_2d(ctx);
+ else if (pd()->ndims() == 5)
+ execute_backward_data_3d(ctx);
+ else
+ assert(false);
+ return status::success;
+ }
+
+private:
+ void execute_backward_data_1d(const exec_ctx_t &ctx) const;
+ void execute_backward_data_2d(const exec_ctx_t &ctx) const;
+ void execute_backward_data_3d(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx512_common_conv_bwd_data_kernel_f32 *kernel_;
+};
+
+template <impl::data_type_t src_type,
+ impl::data_type_t diff_dst_type = src_type,
+ impl::data_type_t diff_weights_type = src_type>
+struct jit_avx512_common_convolution_bwd_weights_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_weights_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", avx512_common, ""),
+ jit_avx512_common_convolution_bwd_weights_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_weights
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(src_type, diff_weights_type,
+ diff_weights_type, diff_dst_type, data_type::undef)
+ && !has_zero_dim_memory();
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_avx512_common_conv_bwd_weights_kernel_f32::
+ init_conf(jcp_, *desc(), src_md_, diff_weights_md_,
+ diff_bias_md_, diff_dst_md_);
+ if (status != status::success) return status;
+
+ init_balancers();
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx512_common_conv_bwd_weights_kernel_f32::init_scratchpad(
+ scratchpad, jcp_);
+
+ auto reducer_bia_scratchpad = memory_tracking::registrar_t(
+ scratchpad, memory_tracking::names::prefix_reducer_bia);
+ reducer_bia_conf_.init_scratchpad(reducer_bia_scratchpad);
+
+ return status;
+ }
+
+ jit_conv_conf_t jcp_;
+ typename cpu_reducer_t<diff_weights_type>::conf_t reducer_bia_conf_;
+
+ private:
+ void init_balancers() {
+ const size_t max_buffer_size = jcp_.nthr * 3 * 5 * 5 * 16 * 16;
+ if (with_bias()) {
+ reducer_bia_conf_.init(reduce_balancer_t(jcp_.nthr,
+ jcp_.oc_block, jcp_.ngroups * jcp_.nb_oc, jcp_.mb,
+ max_buffer_size));
+ }
+ }
+ };
+
+ jit_avx512_common_convolution_bwd_weights_t(const pd_t *apd);
+ ~jit_avx512_common_convolution_bwd_weights_t() {
+ delete kernel_;
+ if (trans_kernel_)
+ delete trans_kernel_;
+ if (acc_ker_)
+ delete acc_ker_;
+ delete reducer_bias_;
+ }
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<diff_dst_type>::type diff_dst_data_t;
+ typedef typename prec_traits<diff_weights_type>::type diff_weights_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_weights(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_weights(const exec_ctx_t &ctx) const;
+ void prepare_scratchpad_data(const exec_ctx_t &ctx) const;
+ struct thread_info_t;
+ void compute_diff_weights(const thread_info_t *) const;
+ void compute_diff_weights_3d(const thread_info_t *) const;
+ void reduce_diff_weights(const thread_info_t *) const;
+ void reduce_diff_weights_3d(const thread_info_t *) const;
+ void compute_diff_bias(const thread_info_t *) const;
+ void compute_diff_bias_3d(const thread_info_t *) const;
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ int nthr_, nthr_mb_, nthr_g_, nthr_oc_b_, nthr_ic_b_;
+
+ jit_avx512_common_conv_bwd_weights_kernel_f32 *kernel_;
+ jit_trans_src_t *trans_kernel_;
+ cpu_accumulator_1d_t<diff_weights_type> *acc_ker_;
+ cpu_reducer_t<diff_weights_type> *reducer_bias_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.cpp
new file mode 100644
index 0000000000..62247c0264
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.cpp
@@ -0,0 +1,1215 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifdef __INTEL_COMPILER
+#include <immintrin.h>
+#endif
+
+#include "mkldnn_types.h"
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_avx512_common_convolution_winograd.hpp"
+
+#ifndef _MSC_VER
+#define pragma_unroll _Pragma("unroll")
+#else
+#define pragma_unroll
+#endif
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace memory_tracking::names;
+
+namespace {
+
+unsigned int LLC_cache_size = get_cache_size(3, false);
+
+void inline load_ps(float *dest, const float *src_mem) {
+#ifdef __INTEL_COMPILER
+ __m512 *Iv512 = (__m512 *)dest;
+ Iv512[0] = _mm512_load_ps(src_mem);
+#else
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) dest[v] = src_mem[v];
+#endif
+}
+
+void inline store_output(float *dest, const float *data, bool streamout) {
+#ifdef __INTEL_COMPILER
+ if (streamout)
+ _mm512_stream_ps(dest, *((__m512 *)data));
+ else
+ _mm512_store_ps(dest, *((__m512 *)data));
+#else
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++)
+ dest[v] = data[v];
+#endif
+}
+
+void inline accum_output(
+ float *dest, float *data, bool streamout, bool with_relu_postsum) {
+#ifdef __INTEL_COMPILER
+ __m512 _data = _mm512_loadu_ps(data);
+ __m512 _dest = _mm512_loadu_ps(dest);
+ _data = _mm512_add_ps(_data, _dest);
+ if (with_relu_postsum)
+ _data = _mm512_max_ps(_data, _mm512_setzero_ps());
+ if (streamout)
+ _mm512_stream_ps(dest, _data);
+ else
+ _mm512_store_ps(dest, _data);
+#else
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++)
+ data[v] += dest[v];
+
+ if (with_relu_postsum) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++)
+ if (data[v] < 0.f)
+ data[v] = 0.f;
+ }
+
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++)
+ dest[v] = data[v];
+#endif
+}
+}
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::utils;
+
+void trans_W_4x4_3x3(float Fw_[6][6][16][16], float F[3][3][16][16]) {
+ float Fw[6][16];
+ float T[6][3][16];
+ float t0[16];
+ float t1[16];
+ float t2[16];
+
+ for (int j = 0; j < 16; j++) {
+#pragma unroll
+ for (int i = 0; i < 3; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int k = 0; k < 16; k++) {
+ t0[k] = 0.26890756302521f * F[2][i][j][k];
+ t1[k] = -t0[k] - 0.688403361344538f * F[0][i][j][k];
+ t2[k] = t0[k] + 0.119514472455649f * F[0][i][j][k];
+
+ T[0][i][k] = 1.13777777777778f * F[0][i][j][k];
+ T[1][i][k] = t1[k] - 0.430252100840336f * F[1][i][j][k];
+ T[2][i][k] = t1[k] + 0.430252100840336f * F[1][i][j][k];
+ T[3][i][k] = t2[k] + 0.179271708683473f * F[1][i][j][k];
+ T[4][i][k] = t2[k] - 0.179271708683473f * F[1][i][j][k];
+ T[5][i][k] = F[2][i][j][k];
+ }
+ }
+#pragma unroll
+ for (int i = 0; i < 6; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int k = 0; k < 16; k++) {
+ t0[k] = 0.26890756302521f * T[i][2][k];
+ t1[k] = -t0[k] - 0.688403361344538f * T[i][0][k];
+ t2[k] = t0[k] + 0.119514472455649f * T[i][0][k];
+
+ Fw[0][k] = 1.13777777777778f * T[i][0][k];
+ Fw[1][k] = t1[k] - 0.430252100840336f * T[i][1][k];
+ Fw[2][k] = t1[k] + 0.430252100840336f * T[i][1][k];
+ Fw[3][k] = t2[k] + 0.179271708683473f * T[i][1][k];
+ Fw[4][k] = t2[k] - 0.179271708683473f * T[i][1][k];
+ Fw[5][k] = T[i][2][k];
+#pragma unroll
+ for (int l = 0; l < 6; l++) {
+ Fw_[i][l][j][k] = Fw[l][k];
+ }
+ }
+ }
+ }
+}
+
+void trans_O_4x4_3x3(float Mw[6][6][16], float O[4][4][16]) {
+ float T[4][6][16];
+ float t0[16];
+ float t1[16];
+ float t2[16];
+ float t3[16];
+
+#pragma unroll
+ for (int i = 0; i < 6; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < 16; v++) {
+ t0[v] = Mw[1][i][v] + Mw[2][i][v];
+ t1[v] = Mw[3][i][v] + Mw[4][i][v];
+ t2[v] = Mw[1][i][v] - Mw[2][i][v];
+ t3[v] = Mw[3][i][v] - Mw[4][i][v];
+
+ T[0][i][v] = t0[v] + t1[v] + Mw[0][i][v];
+ T[1][i][v] = t2[v] * 0.625f + t3[v] * 1.5f;
+ T[2][i][v] = t0[v] * 0.390625f + t1[v] * 2.25f;
+ T[3][i][v] = t2[v] * 0.244140625f + t3[v] * 3.375f + Mw[5][i][v];
+ }
+ }
+#pragma unroll
+ for (int i = 0; i < 4; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < 16; v++) {
+ t0[v] = T[i][1][v] + T[i][2][v];
+ t1[v] = T[i][3][v] + T[i][4][v];
+ t2[v] = T[i][1][v] - T[i][2][v];
+ t3[v] = T[i][3][v] - T[i][4][v];
+
+ O[i][0][v] = t0[v] + t1[v] + T[i][0][v];
+ O[i][1][v] = t2[v] * 0.625f + t3[v] * 1.5f;
+ O[i][2][v] = t0[v] * 0.390625f + t1[v] * 2.25f;
+ O[i][3][v] = t2[v] * 0.244140625f + t3[v] * 3.375f + T[i][5][v];
+ }
+ }
+}
+
+
+void trans_W_3x3_4x4(float Fw[6][6][16], float F[4][6][16])
+{
+ const float rcp3 = 1.0f / 3.0f;
+ const float rcp4 = 1.0f / 4.0f;
+ const float rcp6 = 1.0f / 6.0f;
+ const float rcp12 = 1.0f / 12.0f;
+ const float rcp24 = 1.0f / 24.0f;
+ float t0[16];
+ float t1[16];
+ float t2[16];
+ float t3[16];
+ float t4[16];
+ float T[6][4][16];
+
+pragma_unroll
+ for (int i = 0; i < 4; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < 16; j++) {
+ t0[j] = F[2][i][j] * rcp6;
+ t1[j] = F[0][i][j] * -rcp6 - t0[j];
+ t2[j] = F[0][i][j] * rcp24 + t0[j];
+ t3[j] = (F[1][i][j] + F[3][i][j]) * rcp6;
+ t4[j] = F[1][i][j] * rcp12 + F[3][i][j] * rcp3;
+
+ T[0][i][j] = F[0][i][j] * rcp4;
+ T[1][i][j] = t1[j] - t3[j];
+ T[2][i][j] = t1[j] + t3[j];
+ T[3][i][j] = t2[j] + t4[j];
+ T[4][i][j] = t2[j] - t4[j];
+ T[5][i][j] = F[3][i][j];
+ }
+ }
+pragma_unroll
+ for (int i = 0; i < 6; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < 16; j++) {
+ t0[j] = T[i][2][j] * rcp6;
+ t1[j] = T[i][0][j] * -rcp6 - t0[j];
+ t2[j] = T[i][0][j] * rcp24 + t0[j];
+ t3[j] = (T[i][1][j] + T[i][3][j]) * rcp6;
+ t4[j] = T[i][1][j] * rcp12 + T[i][3][j] * rcp3;
+
+ Fw[i][0][j] = T[i][0][j] * rcp4;
+ Fw[i][1][j] = t1[j] - t3[j];
+ Fw[i][2][j] = t1[j] + t3[j];
+ Fw[i][3][j] = t2[j] + t4[j];
+ Fw[i][4][j] = t2[j] - t4[j];
+ Fw[i][5][j] = T[i][3][j];
+ }
+ }
+}
+
+void trans_O_3x3_4x4(float Mw[6][6][16][16], float M[3][3][16][16])
+{
+ float T[4][6][16];
+ float M_[3][16];
+ float t0[16];
+ float t1[16];
+ float t2[16];
+
+ for (int j = 0; j < 16; j++) {
+pragma_unroll
+ for (int i = 0; i < 6; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int l = 0; l < 16; l++) {
+ t0[l] = Mw[1][i][j][l] + Mw[2][i][j][l];
+ t1[l] = Mw[3][i][j][l] + Mw[4][i][j][l];
+ t2[l] = t1[l] * 4.0f + Mw[5][i][j][l];
+
+ T[0][i][l] = Mw[0][i][j][l] + t0[l] + t1[l];
+ T[1][i][l] = (Mw[1][i][j][l] - Mw[2][i][j][l]) +
+ 2.0f * (Mw[3][i][j][l] - Mw[4][i][j][l]);
+ T[2][i][l] = t0[l] + t2[l];
+ }
+ }
+pragma_unroll
+ for (int i = 0; i < 3; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int l = 0; l < 16; l++) {
+ t0[l] = T[i][1][l] + T[i][2][l];
+ t1[l] = T[i][3][l] + T[i][4][l];
+ t2[l] = t1[l] * 4.0f + T[i][5][l];
+
+ M_[0][l] = T[i][0][l] + t0[l] + t1[l];
+ M_[1][l] = (T[i][1][l] - T[i][2][l]) +
+ 2.0f * (T[i][3][l] - T[i][4][l]);
+ M_[2][l] = t0[l] + t2[l];
+
+ for (int k = 0; k < 3; k++) {
+ M[i][k][j][l] = M_[k][l];
+ }
+ }
+ }
+ }
+}
+
+void trans_I_4x4_3x3(float Iw[6][6][16], float I[6][6][16])
+{
+ float T[6][6][16];
+ float t0[16];
+ float t1[16];
+ float t2[16];
+ float t3[16];
+ float t4[16];
+ float t5[16];
+
+pragma_unroll
+ for (int i = 0; i < 6; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < 16; v++) {
+ t0[v] = I[2][i][v] * -2.25f + I[4][i][v];
+ t1[v] = I[1][i][v] * -2.25f + I[3][i][v];
+ t2[v] = I[2][i][v] * -0.390625f + I[4][i][v];
+ t3[v] = I[1][i][v] * -0.390625f + I[3][i][v];
+ t4[v] = I[0][i][v] * 0.87890625f + I[4][i][v];
+ t5[v] = I[1][i][v] * 0.87890625f + I[5][i][v];
+
+ T[0][i][v] = I[2][i][v] * -2.640625f + t4[v];
+ T[1][i][v] = t1[v] * 0.625f + t0[v];
+ T[2][i][v] = t1[v] * -0.625f + t0[v];
+ T[3][i][v] = t3[v] * 1.5f + t2[v];
+ T[4][i][v] = t3[v] * -1.5f + t2[v];
+ T[5][i][v] = I[3][i][v] * -2.640625f + t5[v];
+ }
+ }
+
+pragma_unroll
+ for (int i = 0; i < 6; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < 16; v++) {
+ t0[v] = T[i][2][v] * -2.25f + T[i][4][v];
+ t1[v] = T[i][1][v] * -2.25f + T[i][3][v];
+ t2[v] = T[i][2][v] * -0.390625f + T[i][4][v];
+ t3[v] = T[i][1][v] * -0.390625f + T[i][3][v];
+ t4[v] = T[i][0][v] * 0.87890625f + T[i][4][v];
+ t5[v] = T[i][1][v] * 0.87890625f + T[i][5][v];
+
+ Iw[i][0][v] = T[i][2][v] * -2.640625f + t4[v];
+ Iw[i][1][v] = t1[v] * 0.625f + t0[v];
+ Iw[i][2][v] = t1[v] * -0.625f + t0[v];
+ Iw[i][3][v] = t3[v] * 1.5f + t2[v];
+ Iw[i][4][v] = t3[v] * -1.5f + t2[v];
+ Iw[i][5][v] = T[i][3][v] * -2.640625f + t5[v];
+ }
+ }
+}
+
+void trans_W_3x3_4x4_wu(float Fw[6][6][16], float F[4][6][16])
+{
+ float T[6][4][16];
+ float t0[16];
+ float t1[16];
+ float t2[16];
+ float t3[16];
+ float t4[16];
+
+pragma_unroll
+ for (int i = 0; i < 4; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < 16; v++) {
+ t0[v] = F[2][i][v] * 0.26890756302521f;
+ t1[v] = F[0][i][v] * -0.688403361344538f - t0[v];
+ t2[v] = F[0][i][v] * 0.119514472455649f + t0[v];
+ t3[v] = F[1][i][v] * 0.430252100840336f +
+ F[3][i][v] * 0.168067226890756f;
+ t4[v] = F[1][i][v] * 0.179271708683473f +
+ F[3][i][v] * 0.403361344537815f;
+
+ T[0][i][v] = F[0][i][v] * 1.13777777777778f;
+ T[1][i][v] = t1[v] - t3[v];
+ T[2][i][v] = t1[v] + t3[v];
+ T[3][i][v] = t2[v] + t4[v];
+ T[4][i][v] = t2[v] - t4[v];
+ T[5][i][v] = F[3][i][v];
+ }
+ }
+pragma_unroll
+ for (int i = 0; i < 6; i++) {
+ for (int v = 0; v < 16; v++) {
+ t0[v] = T[i][2][v] * 0.26890756302521f;
+ t1[v] = T[i][0][v] * -0.688403361344538f - t0[v];
+ t2[v] = T[i][0][v] * 0.119514472455649f + t0[v];
+ t3[v] = T[i][1][v] * 0.430252100840336f +
+ T[i][3][v] * 0.168067226890756f;
+ t4[v] = T[i][1][v] * 0.179271708683473f +
+ T[i][3][v] * 0.403361344537815f;
+
+ Fw[i][0][v] = T[i][0][v] * 1.13777777777778f;
+ Fw[i][1][v] = t1[v] - t3[v];
+ Fw[i][2][v] = t1[v] + t3[v];
+ Fw[i][3][v] = t2[v] + t4[v];
+ Fw[i][4][v] = t2[v] - t4[v];
+ Fw[i][5][v] = T[i][3][v];
+ }
+ }
+}
+
+void trans_O_3x3_4x4_wu(float Mw[6][6][16][16], float M[3][3][16][16])
+{
+ float T[3][6][16];
+ float t0[16];
+ float t1[16];
+ float t2[16];
+ float M_[3][16];
+
+ for (int j = 0; j < 16; j++) {
+pragma_unroll
+ for (int i = 0; i < 6; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < 16; v++) {
+ t0[v] = Mw[1][i][j][v] + Mw[2][i][j][v];
+ t1[v] = Mw[3][i][j][v] + Mw[4][i][j][v];
+ t2[v] = t1[v] * 2.25f + Mw[5][i][j][v];
+
+ T[0][i][v] = Mw[0][i][j][v] + t0[v] + t1[v];
+ T[1][i][v] = 0.625f * (Mw[1][i][j][v] - Mw[2][i][j][v]) +
+ 1.5f * (Mw[3][i][j][v] - Mw[4][i][j][v]);
+ T[2][i][v] = t0[v] * 0.390625f + t2[v];
+ }
+ }
+pragma_unroll
+ for (int i = 0; i < 3; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < 16; v++) {
+ t0[v] = T[i][1][v] + T[i][2][v];
+ t1[v] = T[i][3][v] + T[i][4][v];
+ t2[v] = t1[v] * 2.25f + T[i][5][v];
+
+ M_[0][v] = T[i][0][v] + t0[v] + t1[v];
+ M_[1][v] = 0.625f * (T[i][1][v] - T[i][2][v]) +
+ 1.5f * (T[i][3][v] - T[i][4][v]);
+ M_[2][v] = t0[v] * 0.390625f + t2[v];
+ }
+
+pragma_unroll
+ for (int k = 0; k < 3; k++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < 16; v++) {
+ M[i][k][j][v] = M_[k][v];
+ }
+ }
+ }
+ }
+}
+
+template <bool is_fwd>
+void input_transform_data(int image, const jit_conv_winograd_conf_t &jcp,
+ float *inp, float *tinp, bool streamout = true)
+{
+ const int inpw = is_fwd ? jcp.iw : jcp.ow;
+ const int inph = is_fwd ? jcp.ih : jcp.oh;
+ const int l_pad = is_fwd ? jcp.l_pad : jcp.iw + jcp.r_pad - jcp.ow;
+ const int t_pad = is_fwd ? jcp.t_pad : jcp.ih + jcp.t_pad - jcp.oh;
+ const int wp_max = inpw + l_pad;
+ const int hp_max = inph + t_pad;
+ float Iw[alpha][alpha][simd_w];
+ float I[alpha][alpha][simd_w];
+
+ array_offset_calculator<float, 5> input(inp,
+ jcp.mb, jcp.dimK/simd_w, inph, inpw,
+ simd_w);
+ array_offset_calculator<float, 8> output(tinp,
+ jcp.dimN_nb_block, alpha, alpha,
+ jcp.dimN_block, jcp.dimK_nb_block, jcp.dimK_block,
+ jcp.dimN_reg_block, jcp.dimK_reg_block);
+
+ int tile_base_index = image * jcp.itiles * jcp.jtiles;
+ int tile_block_ur = tile_base_index % jcp.tile_block_ur;
+ int nb_tile_block_ur =
+ (tile_base_index / jcp.tile_block_ur) % jcp.nb_tile_block_ur;
+ int tile_block =
+ (tile_base_index / jcp.tile_block_ur) / jcp.nb_tile_block_ur;
+
+ for (int tj = 0; tj < jcp.jtiles; tj++) {
+ for (int ti = 0; ti < jcp.itiles; ti++) {
+ for (int j = 0; j < alpha; j++) {
+ int ydim = tj * tile_size + j;
+ if ((t_pad <= ydim) && (ydim < hp_max)) {
+ float *pinp_j = inp + (ydim - t_pad) * inpw * 16 ;
+ for (int i = 0; i < alpha; i++) {
+ int xdim = ti * tile_size + i;
+ if ((l_pad <= xdim) && (xdim < wp_max)) {
+ float *pinp_i = pinp_j + (xdim - l_pad) * 16;
+ load_ps(I[j][i], pinp_i);
+ } else {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ I[j][i][v] = 0.0f;
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < alpha; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ I[j][i][v] = 0.0f;
+ }
+ }
+ }
+ }
+
+ trans_I_4x4_3x3(Iw, I);
+
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ store_output(&(output(tile_block, j, i,
+ nb_tile_block_ur, 0, 0,
+ tile_block_ur, 0)),
+ Iw[j][i], streamout);
+ }
+ }
+ tile_block_ur++;
+ if (tile_block_ur >= jcp.tile_block_ur) {
+ tile_block_ur = 0;
+ nb_tile_block_ur++;
+ }
+ if (nb_tile_block_ur >= jcp.nb_tile_block_ur) {
+ nb_tile_block_ur = 0;
+ tile_block++;
+ }
+ }
+ }
+}
+
+template <bool is_fwd>
+void weight_transform_data(const jit_conv_winograd_conf_t &jcp,
+ float *wp, float *twp)
+{
+ const int kh = 3;
+ const int kw = 3;
+ array_offset_calculator<float, 6> input(wp,
+ jcp.oc/jcp.oc_simd_block,
+ jcp.ic/jcp.ic_simd_block,
+ jcp.kh, jcp.kw,
+ simd_w, simd_w);
+ array_offset_calculator<float, 8> output(twp,
+ jcp.dimM_nb_block,
+ alpha, alpha,
+ jcp.dimK_nb_block,
+ jcp.dimM_block, jcp.dimK_block,
+ simd_w, simd_w);
+ float Fw[alpha][alpha][simd_w][simd_w];
+ float F[kh][kw][simd_w][simd_w];
+
+ for (int j = 0; j < kh; j++) {
+ for (int i = 0; i < kw; i++) {
+ for (int v1 = 0; v1 < simd_w; v1++) {
+ float *base_inp = is_fwd
+ ? &(input(0, 0, j, i, v1, 0))
+ : &(input(0, 0, 2 - j, 2 - i, v1, 0));
+ PRAGMA_OMP_SIMD()
+ for (int v2 = 0; v2 < simd_w; v2++) {
+ if (is_fwd)
+ F[j][i][v1][v2] = *(base_inp + v2);
+ else
+ F[j][i][v2][v1] = *(base_inp + v2);
+ }
+ }
+ }
+ }
+
+ trans_W_4x4_3x3(Fw, F);
+
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ for (int v1 = 0; v1 < simd_w; v1++) {
+ PRAGMA_OMP_SIMD()
+ for (int v2 = 0; v2 < simd_w; v2++) {
+ output(0, j, i, 0, 0, 0, v1, v2) = Fw[j][i][v1][v2];
+ }
+ }
+ }
+ }
+}
+
+template <bool is_fwd, bool with_bias, bool with_relu_presum, bool with_sum>
+void output_transform_data(int image, const jit_conv_winograd_conf_t &jcp,
+ const post_ops_t &p_ops, float *toutp, float *pout_b, float *bias,
+ bool streamout = true) {
+ float Ow[alpha][alpha][simd_w];
+ float O[tile_size][tile_size][simd_w];
+ int outw = is_fwd ? jcp.ow : jcp.iw;
+ int outh = is_fwd ? jcp.oh : jcp.ih;
+
+ /* Prepare for PostOps */
+ bool with_relu_postsum = p_ops.find(primitive_kind::eltwise, 1) != -1;
+
+ array_offset_calculator<float, 8> input(toutp,
+ jcp.dimN_nb_block, jcp.dimM_nb_block,
+ alpha, alpha,
+ jcp.dimN_block, jcp.dimM_block,
+ jcp.dimN_reg_block, jcp.dimM_simd_block);
+
+ int tile_base_index = image * jcp.itiles * jcp.jtiles;
+ int tile_block_ur = tile_base_index % jcp.tile_block_ur;
+ int nb_tile_block_ur =
+ (tile_base_index / jcp.tile_block_ur) % jcp.nb_tile_block_ur;
+ int tile_block =
+ (tile_base_index / jcp.tile_block_ur) / jcp.nb_tile_block_ur;
+
+ for (int tj = 0; tj < jcp.jtiles; tj++) {
+ for (int ti = 0; ti < jcp.itiles; ti++) {
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ Ow[j][i][v] = input(tile_block, 0,
+ j, i,
+ nb_tile_block_ur, 0,
+ tile_block_ur, v);
+ }
+ }
+ }
+
+ trans_O_4x4_3x3(Ow, O);
+
+ for (int j = 0; j < tile_size; j++) {
+ int ydim = tj * tile_size + j;
+ if (ydim < outh) {
+ float *pout_j = pout_b + ydim * outw * simd_w;
+ for (int i = 0; i < tile_size; i++) {
+ int xdim = ti * tile_size + i;
+ if (xdim < outw) {
+ float *pout_i = pout_j + xdim * simd_w;
+ if (is_fwd) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ O[j][i][v] += with_bias ? bias[v] : 0.f;
+ O[j][i][v] = true
+ && with_relu_presum && O[j][i][v] < 0.f
+ ? O[j][i][v]
+ * jcp.eltwise.alpha
+ : O[j][i][v];
+ }
+ }
+ if (with_sum)
+ accum_output(pout_i, O[j][i], streamout,
+ with_relu_postsum);
+ else
+ store_output(pout_i, O[j][i], streamout);
+ }
+ }
+ }
+ }
+ tile_block_ur++;
+ if (tile_block_ur >= jcp.tile_block_ur) {
+ tile_block_ur = 0;
+ nb_tile_block_ur++;
+ }
+ if (nb_tile_block_ur >= jcp.nb_tile_block_ur) {
+ nb_tile_block_ur = 0;
+ tile_block++;
+ }
+ }
+ }
+}
+
+template <bool ver_4fma>
+void diff_src_transform_bwd_weights(int image, jit_conv_winograd_conf_t conv,
+ float *inp, float *tinp, float *Iw_temp,
+ void (*transpose_4fma_ker)(float *, float *))
+{
+
+ const int ifwp = conv.iw + conv.l_pad;
+ const int ifhp = conv.ih + conv.t_pad;
+ float I[alpha][alpha][simd_w];
+ float Iw[alpha][alpha][simd_w];
+
+ array_offset_calculator<float, 4> Iw_trans_temp(Iw_temp,
+ alpha, alpha, conv.tile_4fma, simd_w);
+ array_offset_calculator<float, 5> input(inp,
+ conv.mb, conv.ic/simd_w, conv.ih, conv.iw, simd_w);
+ array_offset_calculator<float, 8> output(tinp,
+ conv.nb_ic, alpha, alpha,
+ conv.tile_block, conv.ic_block,
+ conv.nb_tile_block_ur, conv.tile_block_ur,
+ conv.ic_simd_block * conv.tile_4fma);
+
+ int tile_base_index =
+ image * (conv.itiles * conv.jtiles + conv.tile_4fma_padding);
+ int tile_4fma = 0;
+ int tile_block_ur = (tile_base_index / conv.tile_4fma) % conv.tile_block_ur;
+ int nb_tile_block_ur =
+ (tile_base_index / conv.tile_4fma / conv.tile_block_ur)
+ % conv.nb_tile_block_ur;
+ int tile_block = (tile_base_index / conv.tile_4fma / conv.tile_block_ur)
+ / conv.nb_tile_block_ur;
+
+ for (int tj = 0; tj < conv.jtiles; tj++) {
+ for (int ti = 0; ti < conv.itiles; ti++) {
+ for (int j = 0; j < alpha; j++) {
+ int ydim = tj * tile_size + j;
+ if ((conv.t_pad <= ydim) && ydim < ifhp) {
+ for (int i = 0; i < alpha; i++) {
+ int xdim = ti * tile_size + i;
+ if ((conv.l_pad <= xdim) && xdim < ifwp) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ I[j][i][v] = input(0, 0,
+ ydim - conv.t_pad,
+ xdim - conv.l_pad, v);
+ }
+ } else {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ I[j][i][v] = 0.0f;
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < alpha; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ I[j][i][v] = 0.0f;
+ }
+ }
+ }
+ }
+ trans_I_4x4_3x3(Iw, I);
+
+ if (ver_4fma) {
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ float *Iw_temp_base = &(Iw_trans_temp(j, i,
+ tile_4fma, 0));
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ Iw_temp_base[v] = Iw[j][i][v];
+ }
+ }
+ }
+ tile_4fma++;
+ if (tile_4fma == conv.tile_4fma) {
+ float *outp = &(output(0, 0, 0,
+ tile_block, 0,
+ nb_tile_block_ur, tile_block_ur, 0));
+ transpose_4fma_ker(outp, (float *)Iw_temp);
+ tile_4fma = 0;
+ tile_block_ur++;
+ }
+ } else {
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ store_output(&(output(0, j, i,
+ tile_block, 0,
+ nb_tile_block_ur, tile_block_ur, 0)),
+ Iw[j][i], true);
+ }
+ }
+ tile_block_ur++;
+ }
+
+ if (tile_block_ur == conv.tile_block_ur) {
+ tile_block_ur = 0;
+ ++nb_tile_block_ur;
+ }
+ if (nb_tile_block_ur == conv.nb_tile_block_ur) {
+ nb_tile_block_ur = 0;
+ tile_block++;
+ }
+ }
+ }
+
+ if (ver_4fma && tile_4fma < conv.tile_4fma && conv.tile_4fma_padding != 0) {
+
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ for (int tb = tile_4fma; tb < conv.tile_4fma; tb++) {
+ float *Iw_temp_base = &(Iw_trans_temp(j, i, tb, 0));
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ Iw_temp_base[v] = 0;
+ }
+ }
+ }
+ }
+ float *outp = &(output(0, 0, 0,
+ tile_block, 0,
+ nb_tile_block_ur, tile_block_ur, 0));
+ transpose_4fma_ker(outp, (float *)Iw_temp);
+ }
+}
+
+template <bool with_bias>
+void diff_dst_transform_bwd_weights(int image, jit_conv_winograd_conf_t conv,
+ float *inp, float *tinp, float *dbias)
+{
+
+ const int total_tiles = conv.itiles * conv.jtiles + conv.tile_4fma_padding;
+ float I[alpha][alpha][simd_w];
+ float Iw[alpha][alpha][simd_w];
+
+ array_offset_calculator<float, 5> input(inp,
+ conv.mb, conv.oc/simd_w, conv.oh, conv.ow, conv.oc_simd_block);
+ array_offset_calculator<float, 8> output(tinp,
+ conv.nb_oc, alpha, alpha,
+ conv.tile_block, conv.oc_block,
+ conv.nb_tile_block_ur,
+ conv.tile_block_ur * conv.tile_4fma, conv.oc_simd_block);
+
+ int tile_base_index = image * total_tiles;
+ int tile_block_ur = tile_base_index % (conv.tile_block_ur * conv.tile_4fma);
+ int nb_tile_block_ur =
+ (tile_base_index / conv.tile_block_ur / conv.tile_4fma)
+ % conv.nb_tile_block_ur;
+ int tile_block = (tile_base_index / conv.tile_block_ur / conv.tile_4fma)
+ / conv.nb_tile_block_ur;
+
+ for (int tj = 0; tj < conv.jtiles; tj++) {
+ for (int ti = 0; ti < conv.itiles; ti++) {
+ for (int j = 0; j < alpha; j++) {
+ int ydim = tj * tile_size + j;
+ if (ydim < conv.oh) {
+ for (int i = 0; i < alpha; i++) {
+ int xdim = ti * tile_size + i;
+ if (xdim < conv.ow) {
+ float *input_base = &(input(0, 0, ydim, xdim, 0));
+
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ I[j][i][v] = input_base[v];
+ }
+ if (with_bias && j < tile_size && i < tile_size) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ dbias[v] += input_base[v];
+ }
+ }
+ } else {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ I[j][i][v] = 0.0f;
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < alpha; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ I[j][i][v] = 0.0f;
+ }
+ }
+ }
+ }
+
+ trans_W_3x3_4x4_wu(Iw, I);
+
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ store_output(&(output(0, j, i,
+ tile_block, 0,
+ nb_tile_block_ur,
+ tile_block_ur, 0)),
+ Iw[j][i], true);
+ }
+ }
+ tile_block_ur++;
+ if (tile_block_ur >= conv.tile_block_ur * conv.tile_4fma) {
+ tile_block_ur = 0;
+ nb_tile_block_ur++;
+ }
+ if (nb_tile_block_ur >= conv.nb_tile_block_ur) {
+ nb_tile_block_ur = 0;
+ tile_block++;
+ }
+ }
+ }
+}
+
+void diff_weights_transform_bwd_weights(jit_conv_winograd_conf_t conv,
+ float *wp, float *twp)
+{
+ const int kh = 3;
+ const int kw = 3;
+ float Fw[alpha][alpha][simd_w][simd_w];
+ float F[kh][kw][simd_w][simd_w];
+
+ array_offset_calculator<float, 8> input(twp,
+ conv.nb_ic, conv.nb_oc,
+ alpha, alpha,
+ conv.oc_block, conv.ic_block,
+ conv.ic_simd_block, conv.oc_simd_block);
+ array_offset_calculator<float, 6> output(wp,
+ conv.oc/simd_w, conv.ic/simd_w,
+ conv.kh, conv.kw,
+ conv.ic_simd_block, conv.oc_simd_block);
+
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ for (int v = 0; v < conv.ic_simd_block; v++) {
+ PRAGMA_OMP_SIMD()
+ for (int k = 0; k < conv.oc_simd_block; k++) {
+ Fw[j][i][v][k] = input(0, 0, j, i, 0, 0, v, k);
+ }
+ }
+ }
+ }
+
+ trans_O_3x3_4x4_wu(Fw, F);
+
+ for (int j = 0; j < kh; j++) {
+ for (int i = 0; i < kw; i++) {
+ for (int v = 0; v < conv.ic_simd_block; v++) {
+ store_output(&(output(0, 0, j, i, v, 0)),
+ F[j][i][v], true);
+ }
+ }
+ }
+}
+
+template <bool is_fwd>
+void _jit_avx512_common_convolution_winograd_t<is_fwd>::_execute_data_W_S_G_D(
+ float *inp_ptr, float *out_ptr, float *wei_ptr, float *bias_ptr,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const auto &jcp = kernel_->jcp;
+ const auto &p_ops = attr_->post_ops_;
+
+ const int inph = is_fwd ? jcp.ih : jcp.oh;
+ const int inpw = is_fwd ? jcp.iw : jcp.ow;
+ const int outh = is_fwd ? jcp.oh : jcp.ih;
+ const int outw = is_fwd ? jcp.ow : jcp.iw;
+
+ /* Note that jcp.with_eltwise is true for both fused conv+relu primitive
+ * and conv primitive with PostOps with relu before sum
+ * (PostOps relu after sum is handled later) */
+ auto output_transform = jcp.with_bias
+ ? (jcp.with_eltwise
+ ? (jcp.with_sum
+ ? output_transform_data<is_fwd, true, true, true>
+ : output_transform_data<is_fwd, true, true, false>)
+ : (jcp.with_sum
+ ? output_transform_data<is_fwd, true, false, true>
+ : output_transform_data<is_fwd, true, false, false>))
+ : (jcp.with_eltwise
+ ? (jcp.with_sum
+ ? output_transform_data<is_fwd, false, true, true>
+ : output_transform_data<is_fwd, false, true, false>)
+ : (jcp.with_sum
+ ? output_transform_data<is_fwd, false, false, true>
+ : output_transform_data<is_fwd, false, false, false>));
+
+ /* Notation:
+ FWD: dimM:oc, dimN:ntiles, dimK:ic,
+ BWD: dimM:ic, dimN:ntiles, dimK:oc,
+ FWD/BWD: V: src/diff_dst transform, U:weight transform,
+ M:dst/diff_src transform */
+ array_offset_calculator<float, 5> input(inp_ptr,
+ jcp.mb, jcp.dimK/jcp.dimK_reg_block, inph, inpw,
+ jcp.dimK_reg_block);
+ array_offset_calculator<float, 5> output(out_ptr,
+ jcp.mb, jcp.dimM/jcp.dimM_simd_block, outh, outw,
+ jcp.dimM_simd_block);
+ array_offset_calculator<float, 6> weights(wei_ptr,
+ jcp.oc/jcp.oc_simd_block, jcp.ic/jcp.ic_simd_block, jcp.kh, jcp.kw,
+ jcp.ic_simd_block, jcp.oc_simd_block);
+ array_offset_calculator<float, 2> bias(bias_ptr,
+ jcp.dimM/jcp.dimM_simd_block, jcp.dimM_simd_block);
+
+ array_offset_calculator<float, 8> M(is_fwd
+ ? scratchpad.template get<float>(key_wino_M)
+ : scratchpad.template get<float>(key_wino_V),
+ jcp.dimN_nb_block, jcp.dimM_nb_block,
+ alpha, alpha,
+ jcp.dimN_block, jcp.dimM_block,
+ jcp.dimN_reg_block, jcp.dimM_simd_block);
+ array_offset_calculator<float, 8> U(
+ scratchpad.template get<float>(key_wino_U),
+ jcp.dimM_nb_block,
+ alpha, alpha,
+ jcp.dimK_nb_block,
+ jcp.dimM_block, jcp.dimK_block,
+ jcp.dimK_reg_block, jcp.dimM_simd_block);
+ array_offset_calculator<float, 8> V(is_fwd
+ ? scratchpad.template get<float>(key_wino_V)
+ : scratchpad.template get<float>(key_wino_M),
+ jcp.dimN_nb_block, alpha, alpha,
+ jcp.dimN_block, jcp.dimK_nb_block,
+ jcp.dimK_block, jcp.dimN_reg_block, jcp.dimK_reg_block);
+
+ bool V_streamout = jcp.dimN * jcp.dimK * alpha * alpha * sizeof(float)
+ > 2 * LLC_cache_size ? true : false;
+
+ const bool output_is_aligned = ((size_t)out_ptr & (64 - 1)) == 0;
+
+ const bool wants_padded_bias = jcp.with_bias
+ && jcp.oc_without_padding != jcp.oc;
+ float last_slice_bias[simd_w] = {0};
+ if (wants_padded_bias) {
+ for (int oc = 0; oc < jcp.oc_without_padding % jcp.oc_simd_block; ++oc)
+ last_slice_bias[oc] = bias(jcp.dimM / jcp.dimM_simd_block - 1, oc);
+ }
+
+ {
+ parallel_nd(jcp.mb, jcp.dimK_nb_block, jcp.dimK_block,
+ [&](int img, int K_blk1, int K_blk2) {
+ input_transform_data<is_fwd>(img, jcp,
+ &(input(img, K_blk1 * jcp.dimK_block + K_blk2, 0, 0, 0)),
+ &(V(0, 0, 0, 0, K_blk1, K_blk2, 0, 0)), V_streamout);
+ });
+
+ parallel_nd(jcp.nb_oc, jcp.nb_ic, jcp.oc_block, jcp.ic_block,
+ [&](int ofm1, int ifm1, int ofm2, int ifm2) {
+ float *U_base_ptr = is_fwd
+ ? &(U(ofm1, 0, 0, ifm1, ofm2, ifm2, 0, 0))
+ : &(U(ifm1, 0, 0, ofm1, ifm2, ofm2, 0, 0));
+ weight_transform_data<is_fwd>(jcp,
+ &(weights(ofm1 * jcp.oc_block + ofm2,
+ ifm1 * jcp.ic_block + ifm2, 0, 0, 0, 0)), U_base_ptr);
+ });
+
+ parallel_nd(jcp.dimN_nb_block, alpha, alpha, jcp.dimM_nb_block, jcp.dimN_block,
+ [&](int N_blk1, int oj, int oi, int M_blk1, int N_blk2) {
+
+ kernel_->gemm_loop_ker_first_iter(
+ (float *)&(M(N_blk1, M_blk1, oj, oi,
+ N_blk2, 0, 0, 0)),
+ (const float *)&(U(M_blk1, oj, oi,
+ 0, 0, 0, 0, 0)),
+ (const float *)&(V(N_blk1, oj, oi,
+ N_blk2, 0, 0, 0, 0)));
+ for (int K_blk1 = 1; K_blk1 < jcp.dimK_nb_block; K_blk1++) {
+ kernel_->gemm_loop_ker(
+ (float *)&(M(N_blk1, M_blk1, oj, oi,
+ N_blk2, 0, 0, 0)),
+ (const float *)&(U(M_blk1, oj, oi,
+ K_blk1, 0, 0, 0, 0)),
+ (const float *)&(V(N_blk1, oj, oi,
+ N_blk2, K_blk1,
+ 0, 0, 0)));
+ }
+
+ });
+
+ parallel_nd(jcp.mb, jcp.dimM_nb_block, jcp.dimM_block,
+ [&](int img, int M_blk1, int M_blk2) {
+
+ const int M_blk = M_blk1 * jcp.dimM_block + M_blk2;
+
+ float *bias_ptr = wants_padded_bias
+ && M_blk == jcp.dimM / jcp.dimM_simd_block - 1
+ ? last_slice_bias : &bias(M_blk, 0);
+
+ output_transform(img, jcp, p_ops,
+ &(M(0, M_blk1, 0, 0, 0, M_blk2, 0, 0)),
+ &(output(img, M_blk, 0, 0, 0)),
+ bias_ptr, output_is_aligned);
+
+ });
+
+ }
+}
+
+template struct _jit_avx512_common_convolution_winograd_t<true>;
+template struct _jit_avx512_common_convolution_winograd_t<false>;
+
+void jit_avx512_common_convolution_winograd_bwd_weights_t::
+_maybe_execute_diff_bias_copy(float *diff_bias,
+ const memory_tracking::grantor_t &scratchpad) const {
+ if (pd()->wants_padded_bias()) {
+ auto padded_bias = scratchpad.get<float>(key_conv_padded_bias);
+ for (int oc = 0; oc < pd()->jcp_.oc_without_padding; ++oc)
+ diff_bias[oc] = padded_bias[oc];
+ }
+}
+
+void jit_avx512_common_convolution_winograd_bwd_weights_t::
+_execute_backward_weights_S_D_G_W(const exec_ctx_t &ctx,
+ const memory_tracking::grantor_t &scratchpad) const {
+ auto ptr_diff_dst = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST);
+ auto ptr_src = CTX_IN_MEM(const float *, MKLDNN_ARG_SRC);
+ auto ptr_diff_weights = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_WEIGHTS);
+ auto ptr_diff_bias = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_BIAS);
+
+ const auto &jcp = kernel_->jcp;
+ const int nthreads = jcp.nthr;
+
+ auto diff_src_transform_bwd_weights_ver = jcp.ver == ver_4fma ?
+ diff_src_transform_bwd_weights<true> :
+ diff_src_transform_bwd_weights<false>;
+ auto diff_dst_transform_bwd_weights_ver = jcp.with_bias
+ ? diff_dst_transform_bwd_weights<true>
+ : diff_dst_transform_bwd_weights<false>;
+
+ array_offset_calculator<float, 5> src((float *)ptr_src,
+ jcp.mb, jcp.ic/simd_w, jcp.ih, jcp.iw, simd_w);
+ array_offset_calculator<float, 5> diff_dst((float *)ptr_diff_dst,
+ jcp.mb, jcp.oc/simd_w, jcp.oh, jcp.ow, simd_w);
+ array_offset_calculator<float, 6> diff_weights(ptr_diff_weights,
+ jcp.oc/simd_w, jcp.ic/simd_w, jcp.kh, jcp.kw, simd_w, simd_w);
+ array_offset_calculator<float, 2> diff_bias(pd()->wants_padded_bias()
+ ? scratchpad.get<float>(key_conv_padded_bias) : ptr_diff_bias,
+ jcp.oc/simd_w, simd_w);
+
+ array_offset_calculator<float, 8> U(
+ scratchpad.get<float>(key_wino_U),
+ jcp.nb_ic, jcp.nb_oc,
+ alpha, alpha,
+ jcp.oc_block, jcp.ic_block,
+ jcp.ic_simd_block, jcp.oc_simd_block);
+
+ array_offset_calculator<float, 8> M(
+ scratchpad.get<float>(key_wino_M),
+ jcp.nb_oc, alpha, alpha,
+ jcp.tile_block, jcp.oc_block,
+ jcp.nb_tile_block_ur, jcp.tile_block_ur * jcp.tile_4fma,
+ jcp.oc_simd_block);
+ array_offset_calculator<float, 8> V(
+ scratchpad.get<float>(key_wino_V),
+ jcp.nb_ic, alpha, alpha,
+ jcp.tile_block, jcp.ic_block,
+ jcp.nb_tile_block_ur, jcp.tile_block_ur,
+ jcp.ic_simd_block * jcp.tile_4fma);
+
+ const int trans_buffer_size = alpha * alpha * jcp.tile_4fma
+ * jcp.ic_simd_block;
+ array_offset_calculator<float, 2> trans_buffer(
+ scratchpad.get<float>(key_conv_tr_src),
+ nthreads,
+ trans_buffer_size);
+
+ array_offset_calculator<float, 2> diff_bias_prv(
+ scratchpad.get<float>(key_conv_bia_reduction),
+ nthreads,
+ jcp.oc);
+
+PRAGMA_OMP(parallel num_threads(nthreads))
+ {
+ if (jcp.with_bias) {
+ parallel_nd_in_omp(nthreads, jcp.oc, [&](int ithr, int ofm) {
+ diff_bias_prv(ithr, ofm) = 0.0f;
+ });
+
+PRAGMA_OMP(for nowait)
+ for (int bofm = 0; bofm < jcp.oc / simd_w; bofm++) {
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++)
+ diff_bias(bofm, v) = 0.0f;
+ }
+ }
+
+ const int ithread = mkldnn_get_thread_num();
+
+ parallel_nd_in_omp(jcp.mb, jcp.nb_ic, jcp.ic_block,
+ [&](int img, int ifm1, int ifm2) {
+ float *transb = jcp.ver == ver_4fma
+ ? &(trans_buffer(ithread, 0))
+ : NULL;
+ diff_src_transform_bwd_weights_ver(img, jcp,
+ &(src(img, ifm1 * jcp.ic_block + ifm2,
+ 0, 0, 0)),
+ &(V(ifm1, 0, 0, 0, ifm2, 0, 0, 0)),
+ transb,
+ kernel_->transpose_4fma_ker);
+ });
+
+ parallel_nd_in_omp(jcp.mb, jcp.nb_oc, jcp.oc_block,
+ [&](int img, int ofm1, int ofm2) {
+ float *dbias = jcp.with_bias
+ ? &(diff_bias_prv(ithread,
+ simd_w * (ofm1 * jcp.oc_block + ofm2)))
+ : NULL;
+ diff_dst_transform_bwd_weights_ver(img, jcp,
+ &(diff_dst(img, ofm1 * jcp.oc_block + ofm2,
+ 0, 0, 0)),
+ &(M(ofm1, 0, 0, 0, ofm2, 0, 0, 0)),
+ dbias);
+ });
+
+PRAGMA_OMP(barrier)
+
+ for (int ifm1 = 0; ifm1 < jcp.nb_ic; ifm1++) {
+ parallel_nd_in_omp(alpha, alpha, jcp.nb_oc,
+ [&](int oj, int oi, int ofm1) {
+ kernel_->gemm_loop_ker_first_iter(
+ (float *)&(U(ifm1, ofm1, oj, oi,
+ 0, 0, 0, 0)),
+ (const float *)&(M(ofm1, oj, oi,
+ 0, 0, 0, 0, 0)),
+ (const float *)&(V(ifm1, oj, oi,
+ 0, 0, 0, 0, 0)));
+ for (int tile_block = 1; tile_block < jcp.tile_block;
+ tile_block++) {
+ kernel_->gemm_loop_ker((float *)&(U(ifm1, ofm1,
+ oj, oi,
+ 0, 0, 0, 0)),
+ (const float *)&(M(ofm1, oj, oi, tile_block,
+ 0, 0, 0, 0)),
+ (const float *)&(V(ifm1, oj, oi, tile_block,
+ 0, 0, 0, 0)));
+ }
+ });
+ }
+
+PRAGMA_OMP(barrier)
+
+ parallel_nd_in_omp(jcp.nb_ic, jcp.nb_oc, jcp.oc_block, jcp.ic_block,
+ [&](int ifm1, int ofm1, int ofm2, int ifm2) {
+ diff_weights_transform_bwd_weights(jcp,
+ &(diff_weights(ofm1 * jcp.oc_block + ofm2,
+ ifm1 * jcp.ic_block + ifm2, 0, 0, 0, 0)),
+ &(U(ifm1, ofm1, 0, 0, ofm2, ifm2, 0, 0)));
+ });
+
+ if (jcp.with_bias) {
+PRAGMA_OMP(for)
+ for (int ofm1 = 0; ofm1 < jcp.oc / simd_w; ofm1++) {
+ for (int ithr = 0; ithr < nthreads; ithr++) {
+ float* base_bias_ptr = &(diff_bias(ofm1, 0));
+ float* base_bias_prv_ptr = &(diff_bias_prv(
+ ithr * jcp.oc + ofm1 * simd_w));
+ PRAGMA_OMP_SIMD()
+ for (int ofm2 = 0; ofm2 < simd_w; ofm2++) {
+ base_bias_ptr[ofm2] += base_bias_prv_ptr[ofm2];
+ }
+ }
+ }
+ }
+ }
+
+ _maybe_execute_diff_bias_copy(ptr_diff_bias, scratchpad);
+}
+
+}
+}
+}
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.hpp
new file mode 100644
index 0000000000..6c76f37c72
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.hpp
@@ -0,0 +1,318 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_COMMON_CONVOLUTION_WINOGRAD_HPP
+#define CPU_JIT_AVX512_COMMON_CONVOLUTION_WINOGRAD_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_avx512_common_conv_winograd_kernel_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace winograd_avx512_common {
+inline void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_winograd_conf_t &jcp) {
+ using namespace memory_tracking::names;
+
+ size_t U_sz = (size_t)alpha * alpha * jcp.ic * jcp.oc;
+ size_t V_sz = (size_t)alpha * alpha * jcp.mb * jcp.ic
+ * (jcp.itiles * jcp.jtiles + jcp.tile_4fma_padding);
+ size_t M_sz = (size_t)alpha * alpha * jcp.mb * jcp.oc
+ * (jcp.itiles * jcp.jtiles + jcp.tile_4fma_padding);
+
+ scratchpad.book(key_wino_U, sizeof(float) * U_sz, PAGE_2M);
+ scratchpad.book(key_wino_V, sizeof(float) * V_sz, PAGE_2M);
+ scratchpad.book(key_wino_M, sizeof(float) * M_sz, PAGE_2M);
+
+ if (jcp.sched_policy == WSCHED_WEI_S_D_G_W) {
+ const int nthr = mkldnn_get_max_threads();
+
+ size_t tr_src_sz = jcp.ver != ver_4fma ? 0 : (size_t)nthr
+ * alpha * alpha * jcp.tile_4fma * jcp.ic_simd_block;
+ scratchpad.book(key_conv_tr_src, sizeof(float) * tr_src_sz, PAGE_2M);
+
+ size_t br_sz = jcp.with_bias ? nthr * jcp.oc : 0;
+ scratchpad.book(key_conv_bia_reduction, sizeof(float) * br_sz, PAGE_2M);
+
+ size_t padded_bias_sz =
+ jcp.with_bias && jcp.oc_without_padding != jcp.oc ? jcp.oc : 0;
+ scratchpad.book(key_conv_padded_bias, sizeof(float) * padded_bias_sz);
+ }
+}
+}
+
+template <bool is_fwd>
+struct _jit_avx512_common_convolution_winograd_t {
+ _jit_avx512_common_convolution_winograd_t(
+ const jit_conv_winograd_conf_t &jcp, const primitive_attr_t *attr)
+ : kernel_(nullptr), attr_(attr) {
+ kernel_ = new _jit_avx512_common_conv_winograd_data_kernel_f32(jcp);
+ }
+
+ ~_jit_avx512_common_convolution_winograd_t() { delete kernel_; }
+
+ protected:
+ void _execute_data_W_S_G_D(float *inp_ptr, float *out_ptr,
+ float *wei_ptr, float *bias_ptr,
+ const memory_tracking::grantor_t &scratchpad) const;
+ _jit_avx512_common_conv_winograd_data_kernel_f32 *kernel_;
+ const primitive_attr_t *attr_;
+};
+
+struct jit_avx512_common_convolution_winograd_fwd_t
+ : _jit_avx512_common_convolution_winograd_t<true>
+ , public cpu_primitive_t
+ {
+ struct pd_t : public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_wino:", avx512_common, ""),
+ jit_avx512_common_convolution_winograd_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::convolution_auto,
+ alg_kind::convolution_winograd)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_avx512_common_conv_winograd_fwd_kernel_f32::
+ init_conf(jcp_, *desc(), *src_md(), *weights_md(), *dst_md(),
+ *attr());
+ if (status != status::success) return status;
+ set_default_alg_kind(alg_kind::convolution_winograd);
+
+ auto scratchpad = scratchpad_registry().registrar();
+ winograd_avx512_common::init_scratchpad(scratchpad, jcp_);
+
+ return status;
+ }
+
+ jit_conv_winograd_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+ auto wei_tag = with_groups() ? gOIhw16i16o : OIhw16i16o;
+ return set_default_formats_common(nChw16c, wei_tag, nChw16c);
+ }
+ };
+
+ jit_avx512_common_convolution_winograd_fwd_t(const pd_t *apd)
+ : _jit_avx512_common_convolution_winograd_t<true>(apd->jcp_, apd->attr())
+ , cpu_primitive_t(apd, true) {}
+
+ ~jit_avx512_common_convolution_winograd_fwd_t(){};
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override
+ {
+ auto src = CTX_IN_MEM(const float *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const float *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const float *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(float *, MKLDNN_ARG_DST);
+ this->_execute_data_W_S_G_D((float *)src, dst, (float *)weights,
+ (float *)bias, this->scratchpad(ctx));
+ return status::success;
+ }
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+struct jit_avx512_common_convolution_winograd_bwd_data_t
+ : _jit_avx512_common_convolution_winograd_t<false>,
+ public cpu_primitive_t {
+ struct pd_t : public cpu_convolution_bwd_data_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_wino:", avx512_common, ""),
+ jit_avx512_common_convolution_winograd_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_data
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::undef, data_type::f32, data_type::f32)
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::convolution_auto,
+ alg_kind::convolution_winograd)
+ && !has_zero_dim_memory()
+ && set_default_formats()
+ && mkldnn_thr_syncable();
+ if (!ok) return status::unimplemented;
+
+ status_t status =
+ jit_avx512_common_conv_winograd_bwd_data_kernel_f32::init_conf(
+ jcp_, *desc(), *diff_src_md(), *weights_md(),
+ *diff_dst_md());
+ if (status != status::success) return status;
+ set_default_alg_kind(alg_kind::convolution_winograd);
+
+ auto scratchpad = scratchpad_registry().registrar();
+ winograd_avx512_common::init_scratchpad(scratchpad, jcp_);
+
+ return status;
+ }
+
+ jit_conv_winograd_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+ auto wei_tag = with_groups() ? gOIhw16i16o : OIhw16i16o;
+ return set_default_formats_common(nChw16c, wei_tag, nChw16c);
+ }
+ };
+
+ jit_avx512_common_convolution_winograd_bwd_data_t(const pd_t *apd)
+ : _jit_avx512_common_convolution_winograd_t<false>(apd->jcp_, apd->attr())
+ , cpu_primitive_t(apd, true) {}
+
+ ~jit_avx512_common_convolution_winograd_bwd_data_t(){};
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto diff_dst = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const float *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_SRC);
+ this->_execute_data_W_S_G_D((float *)diff_dst, diff_src,
+ (float *)weights, nullptr, this->scratchpad(ctx));
+ return status::success;
+ }
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+struct jit_avx512_common_convolution_winograd_bwd_weights_t
+ : public cpu_primitive_t {
+ struct pd_t : public cpu_convolution_bwd_weights_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr,
+ hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_wino:", avx512_common, ""),
+ jit_avx512_common_convolution_winograd_bwd_weights_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_weights
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::convolution_auto,
+ alg_kind::convolution_winograd)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats()
+ && mkldnn_thr_syncable();
+ if (!ok) return status::unimplemented;
+
+ status_t status =
+ jit_avx512_common_conv_winograd_bwd_weights_kernel_f32::
+ init_conf(jcp_, *desc(), *src_md(), *diff_dst_md(),
+ *diff_weights_md());
+ if (status != status::success) return status;
+ set_default_alg_kind(alg_kind::convolution_winograd);
+
+ auto scratchpad = scratchpad_registry().registrar();
+ winograd_avx512_common::init_scratchpad(scratchpad, jcp_);
+
+ return status;
+ }
+
+ jit_conv_winograd_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+ auto wei_tag = with_groups() ? gOIhw16i16o : OIhw16i16o;
+ return set_default_formats_common(nChw16c, wei_tag, nChw16c);
+ }
+ };
+
+ jit_avx512_common_convolution_winograd_bwd_weights_t(const pd_t *apd)
+ : cpu_primitive_t(apd, true), kernel_(nullptr)
+ {
+ kernel_ = new jit_avx512_common_conv_winograd_bwd_weights_kernel_f32(
+ pd()->jcp_);
+ }
+
+ ~jit_avx512_common_convolution_winograd_bwd_weights_t()
+ { delete kernel_; }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override
+ {
+ _execute_backward_weights_S_D_G_W(ctx, scratchpad(ctx));
+ return status::success;
+ }
+
+private:
+ void _execute_backward_weights_S_D_G_W(const exec_ctx_t &ctx,
+ const memory_tracking::grantor_t &scratchpad) const;
+ void _maybe_execute_diff_bias_copy(float *diff_bias,
+ const memory_tracking::grantor_t &scratchpad) const;
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ jit_avx512_common_conv_winograd_bwd_weights_kernel_f32 *kernel_;
+};
+
+void trans_W_4x4_3x3(float Fw_[6][6][16][16], float F[3][3][16][16]);
+void trans_O_4x4_3x3(float Mw[6][6][16], float O[4][4][16]);
+void trans_W_3x3_4x4(float Fw[6][6][16], float F[4][6][16]);
+void trans_O_3x3_4x4(float Mw[6][6][16][16], float M[3][3][16][16]);
+void trans_I_4x4_3x3(float Iw[6][6][16], float I[6][6][16]);
+void trans_W_3x3_4x4_wu(float Fw[6][6][16], float F[4][6][16]);
+void trans_O_3x3_4x4_wu(float Mw[6][6][16][16], float M[3][3][16][16]);
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.cpp
new file mode 100644
index 0000000000..d4a451c021
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.cpp
@@ -0,0 +1,853 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_avx512_common_lrn.hpp"
+
+#include "jit_generator.hpp"
+
+#define FWD_RBC 4
+#define BWD_RBC 3
+
+#define XMM_SIZE (4*sizeof(float))
+#define ZMM_SIZE (vlen)
+#define BUFFER_BLOCK (XMM_SIZE + ZMM_SIZE + XMM_SIZE)
+#define BUFFER_NEXT_OFFSET (XMM_SIZE + ZMM_SIZE)
+#define SRC_PREV_OFFSET (vlen - XMM_SIZE)
+
+#define IRB_LOOP(statement) for(int irb = 0; irb < loop_size; irb++) { \
+ statement;\
+}
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::utils;
+
+using namespace Xbyak;
+
+enum params { vsize = 16, vlen = 64};
+
+typedef struct {
+ const float *src;
+ float *dst, *ws0, *ws1;
+} jit_args_fwd_t;
+
+typedef struct {
+ const float *src, *diff_dst, *ws0, *ws1;
+ float *diff_src;
+} jit_args_bwd_t;
+
+struct nChw16c_across {
+/* version:
+ * -1: channels 0..15,
+ * 1: channels C-16 .. C-1,
+ * 0: other channels
+ * 3: channels only for this kernel(without prev and next)
+ */
+ int H, W, version;
+ nChw16c_across(int h, int w, int v) : H(h), W(w), version(v) {}
+};
+
+struct jit_avx512_common_lrn_fwd_t::jit_avx512_common_lrn_kernel_f32:
+ public jit_generator {
+ int HW, W;
+ bool is_first;
+ bool is_last;
+ bool is_single;
+
+ Reg64 src = rax;
+ Reg64 dst = r8;
+ Reg64 scratch0 = rdx;
+ Reg64 scratch1 = rsi;
+ Reg64 imm_addr64 = rbx;
+
+ Zmm zalpha = zmm0;
+ Xmm xalpha = xmm0;
+ Zmm zk = zmm1;
+ Xmm xk = xmm1;
+
+ Reg64 param = abi_param1;
+ Reg64 t = rsp;
+ Reg64 hw = r9;
+
+ int xsrc_prev = 2;
+ int zsrc = 7;
+ int xsrc_next = 3;
+ int zc = 7;
+
+ int za = 2;
+ int zb = 3;
+ int zd = 5;
+ int ze = 6;
+ int zsum = 4;
+ int zdst = 2;
+ int zbase = 3;
+ int zsum2 = 5;
+
+ prop_kind_t pk;
+ int use_h_parallelism;
+
+ float alpha, k;
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_lrn_kernel_f32)
+
+ void (*ker)(jit_args_fwd_t *);
+ void operator()(jit_args_fwd_t *arg) { ker(arg); }
+
+ enum {
+ prf0_offt = 1*FWD_RBC,
+ prf2_offt = 8*FWD_RBC
+ };
+
+ inline void compute_loop(int loop_size_param)
+ {
+ // loop_size - param for IRB_LOOP macro
+ int loop_size = FWD_RBC;
+
+ auto xreg = [=](int irb, int i) {
+ return Xmm(irb*3 + i);
+ };
+
+ auto zreg = [=](int irb, int i) {
+ return Zmm(irb*7 + i);
+ };
+
+ if (!is_first && !is_single) {
+ IRB_LOOP(mic_prefetcht0(ptr[src + (irb + prf0_offt - HW)*vlen]));
+ IRB_LOOP(mic_prefetcht2(ptr[src + (irb + prf2_offt - HW)*vlen]));
+ }
+ IRB_LOOP(mic_prefetcht0(EVEX_compress_addr(src, (irb + prf0_offt)*vlen)));
+ IRB_LOOP(mic_prefetcht2(EVEX_compress_addr(src, (irb + prf2_offt)*vlen)));
+ if (!is_last && !is_single) {
+ IRB_LOOP(mic_prefetcht0(ptr[src + (irb + prf0_offt + HW)*vlen]));
+ IRB_LOOP(mic_prefetcht2(ptr[src + (irb + prf2_offt + HW)*vlen]));
+ }
+ if (pk != prop_kind::forward_inference) {
+ IRB_LOOP(mic_prefetcht0(EVEX_compress_addr(scratch0,
+ (irb + prf0_offt)*vlen)));
+ IRB_LOOP(mic_prefetcht2(EVEX_compress_addr(scratch0,
+ (irb + prf2_offt)*vlen)));
+ }
+ IRB_LOOP(mic_prefetcht0(EVEX_compress_addr(dst, (irb + prf0_offt)*vlen)));
+ IRB_LOOP(mic_prefetcht2(EVEX_compress_addr(dst, (irb + prf2_offt)*vlen)));
+ if (pk != prop_kind::forward_inference) {
+ IRB_LOOP(mic_prefetcht0(EVEX_compress_addr(scratch1,
+ (irb + prf0_offt) * vlen)));
+ IRB_LOOP(mic_prefetcht2(EVEX_compress_addr(scratch1,
+ (irb + prf2_offt) * vlen)));
+ }
+
+ loop_size = loop_size_param;
+ if (loop_size == 0)
+ return;
+ if (!is_first && !is_single) {
+ IRB_LOOP(vmovups(xreg(irb, xsrc_prev),
+ ptr[src + (irb - HW) * vlen + SRC_PREV_OFFSET]));
+ }
+ IRB_LOOP(vmovups(zreg(irb, zsrc), EVEX_compress_addr(src,irb*vlen)));
+ if (!is_last && !is_single) {
+ IRB_LOOP(vmovups(xreg(irb, xsrc_next),
+ ptr[src + (irb + HW) * vlen]));
+ }
+
+ if (!is_first && !is_single) {
+ IRB_LOOP(vmovups(ptr[t + irb*BUFFER_BLOCK],
+ xreg(irb, xsrc_prev)));
+ }
+ IRB_LOOP(vmovups(EVEX_compress_addr(t, irb*BUFFER_BLOCK + XMM_SIZE),
+ zreg(irb, zsrc)));
+ if (!is_last && !is_single) {
+ IRB_LOOP(vmovups(ptr[t + irb*BUFFER_BLOCK + BUFFER_NEXT_OFFSET],
+ xreg(irb, xsrc_next)));
+ }
+
+ IRB_LOOP(vmovups(zreg(irb, za), EVEX_compress_addr(t, irb*BUFFER_BLOCK
+ + XMM_SIZE - 2*sizeof(float))));
+ IRB_LOOP(vmovups(zreg(irb, zb), EVEX_compress_addr(t, irb*BUFFER_BLOCK
+ + XMM_SIZE - sizeof(float))));
+ IRB_LOOP(vmovups(zreg(irb, zd), EVEX_compress_addr(t, irb*BUFFER_BLOCK
+ + XMM_SIZE + sizeof(float))));
+ IRB_LOOP(vmovups(zreg(irb, ze), EVEX_compress_addr(t, irb*BUFFER_BLOCK
+ + XMM_SIZE + 2*sizeof(float))));
+
+ assert(zc == zsrc);
+ IRB_LOOP(vmulps(zreg(irb, zsum), zreg(irb, zc), zreg(irb, zc)));
+
+ IRB_LOOP(vfmadd231ps(zreg(irb, zsum), zreg(irb, za), zreg(irb, za)));
+ IRB_LOOP(vfmadd231ps(zreg(irb, zsum), zreg(irb, zb), zreg(irb, zb)));
+ IRB_LOOP(vfmadd231ps(zreg(irb, zsum), zreg(irb, zd), zreg(irb, zd)));
+ IRB_LOOP(vfmadd231ps(zreg(irb, zsum), zreg(irb, ze), zreg(irb, ze)));
+
+ IRB_LOOP(vfmadd132ps(zreg(irb, zsum), zk, zalpha));
+
+ IRB_LOOP(vmovaps(zreg(irb, zbase), zreg(irb, zsum)));
+
+ IRB_LOOP(vmulps(zreg(irb, zsum2), zreg(irb, zsum), zreg(irb, zsum)));
+ IRB_LOOP(vmulps(zreg(irb, zsum), zreg(irb, zsum), zreg(irb, zsum2)));
+
+ IRB_LOOP(vsqrtps(zreg(irb, zsum), zreg(irb, zsum)));
+ IRB_LOOP(vsqrtps(zreg(irb, zsum), zreg(irb, zsum)));
+
+ if (pk != prop_kind::forward_inference) {
+ IRB_LOOP(vmovups(EVEX_compress_addr(scratch0, irb*vlen),
+ zreg(irb, zsum)));
+ }
+ IRB_LOOP(vdivps(zreg(irb, zdst), zreg(irb, zsrc), zreg(irb, zsum)));
+ IRB_LOOP(vmovups(EVEX_compress_addr(dst, irb*vlen), zreg(irb, zdst)));
+ if (pk != prop_kind::forward_inference) {
+ /* ws1 = zdst / zbase = zsrc / (zbase^1.75) */
+ IRB_LOOP(vdivps(zreg(irb, zsum), zreg(irb, zdst), zreg(irb, zbase)));
+ IRB_LOOP(vmovups(EVEX_compress_addr(scratch1, irb*vlen),
+ zreg(irb, zsum)));
+ }
+ }
+
+ jit_avx512_common_lrn_kernel_f32(
+ const struct nChw16c_across &J,
+ prop_kind_t prop_kind,
+ int use_h_parallel,
+ float A,
+ float K,
+ void *code_ptr = nullptr,
+ size_t code_size = 2 * Xbyak::DEFAULT_MAX_CODE_SIZE)
+ : jit_generator(code_ptr, code_size)
+ , pk(prop_kind)
+ , use_h_parallelism(use_h_parallel)
+ , alpha(A)
+ , k(K)
+ {
+ this->preamble();
+
+ mov(src, ptr[param + 0]);
+ mov(dst, ptr[param + 8]);
+ if (pk != prop_kind::forward_inference)
+ {
+ mov(scratch0, ptr[param + 16]);
+ mov(scratch1, ptr[param + 24]);
+ }
+ is_first = J.version == -1 || J.version == -2;
+ is_last = J.version == +1 || J.version == -2;
+ is_single = J.version == 3;
+
+ W = J.W;
+ HW = J.W*J.H;
+ int LSB = use_h_parallelism ? W : HW;
+
+ sub(t, FWD_RBC*BUFFER_BLOCK);
+ mov(imm_addr64, float2int(this->alpha));
+ movq(xalpha, imm_addr64);
+ vbroadcastss(zalpha, xalpha);
+
+ mov(imm_addr64, float2int(this->k));
+ movq(xk, imm_addr64);
+ vbroadcastss(zk, xk);
+
+ if (is_first || is_single) {
+ vxorps(xmm2, xmm2, xmm2);
+ for(int irb = 0; irb < FWD_RBC; irb++) {
+ vmovups(ptr[t + irb*BUFFER_BLOCK], xmm2);
+ }
+ }
+ if (is_last || is_single) {
+ vxorps(xmm2, xmm2, xmm2);
+ for(int irb = 0; irb < FWD_RBC; irb++) {
+ vmovups(ptr[t + irb*BUFFER_BLOCK + BUFFER_NEXT_OFFSET],
+ xmm2);
+ }
+ }
+
+ int LSREST = LSB % FWD_RBC;
+ int LS = LSB - LSREST;
+
+ Label lrn_loop;
+
+ if (LS > 0) {
+ mov(hw, LS);
+
+ L(lrn_loop);
+ {
+ compute_loop(FWD_RBC);
+
+ add(src, FWD_RBC*vlen);
+ add(dst, FWD_RBC*vlen);
+ if (pk != prop_kind::forward_inference)
+ {
+ add(scratch0, FWD_RBC*vlen);
+ add(scratch1, FWD_RBC*vlen);
+ }
+
+ for(int irb = 0; irb < FWD_RBC; irb++)
+ dec(hw);
+ cmp(hw, 0);
+ jne(lrn_loop, T_NEAR);
+ }
+ }
+
+ compute_loop(LSREST);
+
+ add(t, FWD_RBC*BUFFER_BLOCK);
+ this->postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+ }
+};
+
+status_t jit_avx512_common_lrn_fwd_t::pd_t::init() {
+ using namespace prop_kind;
+ using namespace alg_kind;
+
+ const memory_desc_wrapper data_d(src_md());
+ bool ok = true
+ && mayiuse(avx512_common)
+ && is_fwd()
+ && !has_zero_dim_memory()
+ && everyone_is(data_type::f32, data_d.data_type())
+ && data_d.ndims() == 4
+ && data_d.dims()[1] % vsize == 0
+ && attr()->has_default_values();
+ if (!ok) return unimplemented;
+
+ if (desc()->prop_kind == forward_training) {
+ dims_t ws_dims = { MB(), C(), H(), 2*W() };
+ mkldnn_memory_desc_init_by_tag(&ws_md_, 4, ws_dims, data_type::f32,
+ format_tag::nChw16c);
+ }
+
+ bool args_ok_across = true
+ && desc()->alg_kind == lrn_across_channels
+ && desc()->local_size == 5
+ && desc()->lrn_beta == 0.75
+ && data_d.matches_tag(format_tag::nChw16c);
+
+ return args_ok_across ? success : unimplemented;
+}
+
+jit_avx512_common_lrn_fwd_t::jit_avx512_common_lrn_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , use_h_parallelism(0), ker_(nullptr), ker_first_(nullptr)
+ , ker_last_(nullptr) {
+ using namespace alg_kind;
+ const int C = pd()->C();
+ const int H = pd()->H();
+ const int W = pd()->W();
+ const int ls = pd()->desc()->local_size;
+ const float alpha = pd()->desc()->lrn_alpha / ls;
+ const float k = pd()->desc()->lrn_k;
+
+ auto pk = pd()->desc()->prop_kind;
+
+ use_h_parallelism = H > 28 ? 1 : 0;
+
+ if (C / vsize == 1) {
+ ker_ = new jit_avx512_common_lrn_kernel_f32(nChw16c_across(H, W, 3), pk,
+ use_h_parallelism, alpha, k);
+ } else {
+ ker_ = new jit_avx512_common_lrn_kernel_f32(nChw16c_across(H, W, 0), pk,
+ use_h_parallelism, alpha, k);
+ ker_first_ = new jit_avx512_common_lrn_kernel_f32(
+ nChw16c_across(H, W, -1), pk, use_h_parallelism, alpha, k);
+ ker_last_ = new jit_avx512_common_lrn_kernel_f32(
+ nChw16c_across(H, W, +1), pk, use_h_parallelism, alpha, k);
+ }
+}
+
+jit_avx512_common_lrn_fwd_t::~jit_avx512_common_lrn_fwd_t()
+{ delete ker_; delete ker_first_; delete ker_last_; }
+
+void jit_avx512_common_lrn_fwd_t::execute_forward(const exec_ctx_t &ctx) const
+{
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+ auto ws = CTX_OUT_MEM(data_t *, MKLDNN_ARG_WORKSPACE);
+
+ const int N = pd()->MB();
+ const int C = pd()->C();
+ const int H = pd()->H();
+ const int W = pd()->W();
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ size_t start{0}, end{0};
+ const int C16 = C / vsize;
+ const size_t work_amount = use_h_parallelism ? N*C16*H : N*C16;
+
+ balance211(work_amount, nthr, ithr, start, end);
+ if (use_h_parallelism) {
+ int n{0}, c16{0}, h{0};
+ nd_iterator_init(start, n, N, c16, C16, h, H);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ auto offset = n*C*H*W + c16*H*W*vsize
+ + h*W*vsize;
+ auto ws_offset0 = n*C*H*2*W + c16*H*2*W*vsize
+ + h*2*W*vsize;
+ auto ws_offset1 = ws_offset0 + W*vsize;
+
+ jit_args_fwd_t args;
+ args.src = &src[offset];
+ args.dst = &dst[offset];
+ args.ws0 = &ws[ws_offset0];
+ args.ws1 = &ws[ws_offset1];
+
+ if (C16 == 1)
+ (*ker_)(&args);
+ else if (c16 == 0)
+ (*ker_first_)(&args);
+ else if (c16 == C16 - 1)
+ (*ker_last_)(&args);
+ else
+ (*ker_)(&args);
+ nd_iterator_step(n, N, c16, C16, h, H);
+ }
+ } else {
+ int n{0}, c16{0};
+ nd_iterator_init(start, n, N, c16, C16);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ auto offset = n*C*H*W + c16*H*W*vsize;
+ auto ws_offset0 = n*C*H*2*W + c16*H*2*W*vsize;
+ auto ws_offset1 = ws_offset0 + H*W*vsize;
+
+ jit_args_fwd_t args;
+ args.src = &src[offset];
+ args.dst = &dst[offset];
+ args.ws0 = &ws[ws_offset0];
+ args.ws1 = &ws[ws_offset1];
+
+ if (C16 == 1)
+ (*ker_)(&args);
+ else if (c16 == 0)
+ (*ker_first_)(&args);
+ else if (c16 == C16 - 1)
+ (*ker_last_)(&args);
+ else
+ (*ker_)(&args);
+
+ nd_iterator_step(n, N, c16, C16);
+ }
+ }
+ });
+}
+
+struct jit_avx512_common_lrn_bwd_t::jit_avx512_common_lrn_kernel_f32:
+ public jit_generator {
+ int HW, W;
+ bool is_first;
+ bool is_last;
+ bool is_single;
+
+ Reg64 src = rax;
+ Reg64 diffsrc = r8;
+ Reg64 diffdst = r9;
+ Reg64 workspace0 = rdx;
+ Reg64 workspace1 = rsi;
+ Reg64 imm_addr64 = rbx;
+
+ Zmm znalphabeta = zmm0;
+ Xmm xnalphabeta = xmm0;
+
+ Reg64 param = abi_param1;
+ Reg64 t = rsp;
+ Reg64 hw = r10;
+
+ int xws1_prev = 1;
+ int xdiffdst_prev = 2;
+ int zws1 = 1;
+
+ int zsrc = 1;
+ int zdiffdst = 5;
+ int zdiffsrc = 6;
+
+ int xws1_next = 1;
+ int xdiffdst_next = 3;
+
+ int za = 1;
+ int zb = 2;
+ int zd = 3;
+ int ze = 4;
+ int zws0 = 2;
+
+ float nalphabeta;
+
+ int use_h_parallelism;
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_common_lrn_kernel_f32)
+
+ void (*ker)(jit_args_bwd_t *);
+ void operator()(jit_args_bwd_t *arg) { ker(arg); }
+
+ enum {
+ prf0_offt = 1*BWD_RBC,
+ prf2_offt = 8*BWD_RBC
+ };
+
+ inline void compute_loop(int loop_size_param, int prefetchL1,
+ int prefetchL2)
+ {
+ // loop_size - param for IRB_LOOP macro
+ int loop_size = loop_size_param;
+
+ auto xreg = [=](int irb, int i) {
+ return Xmm(irb*6 + i);
+ };
+
+ auto zreg = [=](int irb, int i) {
+ return Zmm(irb*6 + i);
+ };
+
+// ---- prefetching -------------------------------------------
+ if (!is_first && !is_single) {
+ if (prefetchL1)
+ IRB_LOOP(mic_prefetcht0(ptr[workspace1 + (irb + prf0_offt
+ - 2 * HW) * vlen]));
+ if (prefetchL1)
+ IRB_LOOP(mic_prefetcht0(ptr[diffdst + (irb + prf0_offt
+ - HW) * vlen]));
+ }
+
+ if (prefetchL1)
+ IRB_LOOP(mic_prefetcht0(ptr[src + (irb + prf0_offt)*vlen]));
+ if (prefetchL2)
+ IRB_LOOP(mic_prefetcht2(ptr[src + (irb + prf2_offt)*vlen]));
+
+ if (prefetchL1)
+ IRB_LOOP(mic_prefetcht0(ptr[workspace1 + (irb + prf0_offt)*vlen]));
+
+ if (prefetchL1)
+ IRB_LOOP(mic_prefetcht0(ptr[diffdst + (irb + prf0_offt)*vlen]));
+
+ if (!is_last && !is_single) {
+ if (prefetchL1)
+ IRB_LOOP(mic_prefetcht0(ptr[workspace1 + (irb + prf0_offt
+ + 2 * HW) * vlen]));
+ if (prefetchL2)
+ IRB_LOOP(mic_prefetcht2(ptr[workspace1 + (irb + prf2_offt
+ + 2 * HW) * vlen]));
+
+ if (prefetchL1)
+ IRB_LOOP(mic_prefetcht0(ptr[diffdst + (irb + prf0_offt
+ + HW) * vlen]));
+ if (prefetchL2)
+ IRB_LOOP(mic_prefetcht2(ptr[diffdst + (irb + prf2_offt
+ + HW) * vlen]));
+ }
+ if (prefetchL1)
+ IRB_LOOP(mic_prefetcht0(ptr[workspace0 + (irb + prf0_offt)*vlen]));
+ if (prefetchL2)
+ IRB_LOOP(mic_prefetcht2(ptr[workspace0 + (irb + prf2_offt)*vlen]));
+// -----------------------------------------------------------
+
+ if (loop_size_param == 0)
+ return;
+
+ if (!is_first && !is_single) {
+ IRB_LOOP(vmovups(xreg(irb, xws1_prev), ptr[workspace1 + (irb
+ - 2 * HW) * vlen + SRC_PREV_OFFSET]));
+ IRB_LOOP(vmovups(xreg(irb, xdiffdst_prev), ptr[diffdst + (irb
+ - HW) * vlen + SRC_PREV_OFFSET]));
+ IRB_LOOP(vmulps(xreg(irb, xdiffdst_prev), xreg(irb, xdiffdst_prev),
+ xreg(irb, xws1_prev)));
+ }
+
+ IRB_LOOP(vmovups(zreg(irb, zws1),
+ EVEX_compress_addr(workspace1, irb*vlen)));
+ IRB_LOOP(vmovups(zreg(irb, zdiffdst),
+ EVEX_compress_addr(diffdst, irb*vlen)));
+ IRB_LOOP(vmulps(zreg(irb, zdiffsrc), zreg(irb, zdiffdst),
+ zreg(irb, zws1)));
+
+ if (!is_last && !is_single) {
+ IRB_LOOP(vmovups(xreg(irb, xws1_next), ptr[workspace1 + (irb
+ + 2 * HW) * vlen]));
+ IRB_LOOP(vmovups(xreg(irb, xdiffdst_next), ptr[diffdst + (irb
+ + HW) * vlen]));
+ IRB_LOOP(vmulps(xreg(irb, xdiffdst_next), xreg(irb, xdiffdst_next),
+ xreg(irb, xws1_next)));
+ }
+
+ if (!is_first && !is_single) {
+ IRB_LOOP(vmovups(ptr[t + irb*BUFFER_BLOCK],
+ xreg(irb, xdiffdst_prev)));
+ }
+ IRB_LOOP(vmovups(EVEX_compress_addr(t, irb*BUFFER_BLOCK + XMM_SIZE),
+ zreg(irb, zdiffsrc)));
+ if (!is_last && !is_single) {
+ IRB_LOOP(vmovups(ptr[t + irb*BUFFER_BLOCK + BUFFER_NEXT_OFFSET],
+ xreg(irb, xdiffdst_next)));
+ }
+
+ IRB_LOOP(vmovups(zreg(irb, za), EVEX_compress_addr(t, irb*BUFFER_BLOCK
+ + XMM_SIZE - 2*sizeof(float))));
+ IRB_LOOP(vmovups(zreg(irb, zb), EVEX_compress_addr(t, irb*BUFFER_BLOCK
+ + XMM_SIZE - 1*sizeof(float))));
+ IRB_LOOP(vmovups(zreg(irb, zd), EVEX_compress_addr(t, irb*BUFFER_BLOCK
+ + XMM_SIZE + 1*sizeof(float))));
+ IRB_LOOP(vmovups(zreg(irb, ze), EVEX_compress_addr(t, irb*BUFFER_BLOCK
+ + XMM_SIZE + 2*sizeof(float))));
+ IRB_LOOP(vaddps(zreg(irb, zdiffsrc), zreg(irb, zdiffsrc),
+ zreg(irb, za)));
+ assert(zsrc == za);
+ IRB_LOOP(vmovups(zreg(irb, zsrc), EVEX_compress_addr(src, irb*vlen)));
+ IRB_LOOP(vaddps(zreg(irb, zdiffsrc), zreg(irb, zdiffsrc),
+ zreg(irb, zb)));
+ IRB_LOOP(vaddps(zreg(irb, zdiffsrc), zreg(irb, zdiffsrc),
+ zreg(irb, zd)));
+ IRB_LOOP(vaddps(zreg(irb, zdiffsrc), zreg(irb, zdiffsrc),
+ zreg(irb, ze)));
+ IRB_LOOP(vmulps(zreg(irb, zsrc), zreg(irb, zsrc), znalphabeta));
+
+ IRB_LOOP(vmovups(zreg(irb, zws0),
+ EVEX_compress_addr(workspace0, irb*vlen)));
+ IRB_LOOP(vdivps(zreg(irb, zdiffdst), zreg(irb, zdiffdst),
+ zreg(irb, zws0)));
+ IRB_LOOP(vfmadd213ps(zreg(irb, zdiffsrc), zreg(irb, zsrc),
+ zreg(irb, zdiffdst)));
+
+ Label unaligned_store, end_store;
+ test(diffsrc, vlen - 1);
+ jnz(unaligned_store, T_NEAR);
+ IRB_LOOP(uni_vmovntps(EVEX_compress_addr(diffsrc, irb*vlen),
+ zreg(irb, zdiffsrc)));
+ jmp(end_store, T_NEAR);
+ L(unaligned_store); {
+ IRB_LOOP(uni_vmovups(EVEX_compress_addr(diffsrc, irb*vlen),
+ zreg(irb, zdiffsrc)));
+ }
+ L(end_store);
+ }
+
+ jit_avx512_common_lrn_kernel_f32(
+ const struct nChw16c_across &J,
+ float A,
+ float B,
+ int use_h_parallel,
+ void *code_ptr = nullptr,
+ size_t code_size = 1 * Xbyak::DEFAULT_MAX_CODE_SIZE)
+ : jit_generator(code_ptr, code_size)
+ , nalphabeta(-2*A*B)
+ , use_h_parallelism(use_h_parallel)
+ {
+ this->preamble();
+
+ mov(src, ptr[param + 0]);
+ mov(diffdst, ptr[param + 8]);
+ mov(workspace0, ptr[param + 16]);
+ mov(workspace1, ptr[param + 24]);
+ mov(diffsrc, ptr[param + 32]);
+
+ W = J.W;
+ HW = J.H*J.W;
+ int LSB = this->use_h_parallelism ? W : HW;
+
+ sub(t, BWD_RBC*BUFFER_BLOCK);
+ mov(imm_addr64, float2int(this->nalphabeta));
+ movq(xnalphabeta, imm_addr64);
+ vbroadcastss(znalphabeta, xnalphabeta);
+
+ is_first = J.version == -1 || J.version == -2;
+ is_last = J.version == +1 || J.version == +2;
+ is_single = J.version == 3;
+
+ if (is_first || is_single) {
+ vxorps(xmm1, xmm1, xmm1);
+ for(int irb = 0; irb < BWD_RBC; irb++) {
+ vmovups(ptr[t + irb*BUFFER_BLOCK], xmm1);
+ }
+ }
+ if (is_last || is_single) {
+ vxorps(xmm1, xmm1, xmm1);
+ for(int irb = 0; irb < BWD_RBC; irb++) {
+ vmovups(ptr[t + irb*BUFFER_BLOCK + BUFFER_NEXT_OFFSET], xmm1);
+ }
+ }
+
+ int LSREST = LSB % BWD_RBC;
+ int LS = LSB - LSREST;
+
+ Label lrn_loop;
+
+ if (LS > 0) {
+ mov(hw, LS);
+
+ L(lrn_loop);
+ {
+ compute_loop(BWD_RBC, 1, 1);
+
+ add(src, BWD_RBC*vlen);
+ add(diffsrc, BWD_RBC*vlen);
+ add(diffdst, BWD_RBC*vlen);
+ add(workspace0, BWD_RBC*vlen);
+ add(workspace1, BWD_RBC*vlen);
+
+ for(int irb = 0; irb < BWD_RBC; irb++)
+ dec(hw);
+ cmp(hw, 0);
+ jne(lrn_loop, T_NEAR);
+ }
+ }
+
+ compute_loop(LSREST, 1, this->use_h_parallelism ? 0 : 1);
+
+ add(t, BWD_RBC*BUFFER_BLOCK);
+ this->postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+ }
+
+};
+
+status_t jit_avx512_common_lrn_bwd_t::pd_t::init() {
+ using namespace alg_kind;
+
+ const memory_desc_wrapper data_d(src_md());
+ bool ok = true
+ && mayiuse(avx512_common)
+ && !is_fwd()
+ && utils::everyone_is(data_type::f32, data_d.data_type())
+ && !has_zero_dim_memory()
+ && data_d.ndims() == 4
+ && data_d.dims()[1] % vsize == 0
+ && attr()->has_default_values();
+ if (!ok) return unimplemented;
+
+ dims_t ws_dims = { MB(), C(), H(), 2*W() };
+ mkldnn_memory_desc_init_by_tag(&ws_md_, 4, ws_dims, data_type::f32,
+ format_tag::nChw16c);
+
+ if (!compare_ws(hint_fwd_pd_)) return unimplemented;
+
+ bool args_ok_across = true
+ && desc()->alg_kind == lrn_across_channels
+ && desc()->local_size == 5
+ && desc()->lrn_beta == 0.75
+ && data_d.matches_tag(format_tag::nChw16c);
+
+ return args_ok_across ? success : unimplemented;
+}
+
+jit_avx512_common_lrn_bwd_t::jit_avx512_common_lrn_bwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , use_h_parallelism(0), ker_(nullptr), ker_first_(nullptr)
+ , ker_last_(nullptr) {
+ const int C = pd()->C();
+ const int H = pd()->H();
+ const int W = pd()->W();
+ const int ls = pd()->desc()->local_size;
+ const float alpha = pd()->desc()->lrn_alpha / ls;
+ const float beta = pd()->desc()->lrn_beta;
+
+ use_h_parallelism = H > 28 ? 1 : 0;
+
+ if (C / vsize == 1) {
+ ker_ = new jit_avx512_common_lrn_kernel_f32(nChw16c_across(H, W, 3),
+ alpha, beta, use_h_parallelism);
+ } else {
+ ker_ = new jit_avx512_common_lrn_kernel_f32(nChw16c_across(H, W, 0),
+ alpha, beta, use_h_parallelism);
+ ker_first_ = new jit_avx512_common_lrn_kernel_f32(
+ nChw16c_across(H, W, -1), alpha, beta, use_h_parallelism);
+ ker_last_ = new jit_avx512_common_lrn_kernel_f32(
+ nChw16c_across(H, W, +1), alpha, beta, use_h_parallelism);
+ }
+}
+
+jit_avx512_common_lrn_bwd_t::~jit_avx512_common_lrn_bwd_t()
+{ delete ker_; delete ker_first_; delete ker_last_; }
+
+void jit_avx512_common_lrn_bwd_t::execute_backward(const exec_ctx_t &ctx) const
+{
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto ws = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WORKSPACE);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const int N = pd()->MB();
+ const int C = pd()->C();
+ const int H = pd()->H();
+ const int W = pd()->W();
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ size_t start{0}, end{0};
+ const int C16 = C / vsize;
+ const size_t work_amount = use_h_parallelism ? N*C16*H : N*C16;
+
+ balance211(work_amount, nthr, ithr, start, end);
+ if (use_h_parallelism) {
+ int n{0}, c16{0}, h{0};
+ nd_iterator_init(start, n, N, h, H, c16, C16);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ auto offset = n*C*H*W + c16*H*W*vsize
+ + h*W*vsize;
+ auto ws_offset0 = n*C*H*2*W + c16*H*2*W*vsize
+ + h*2*W*vsize;
+ auto ws_offset1 = ws_offset0 + W*vsize;
+
+ jit_args_bwd_t args;
+ args.src = &src[offset];
+ args.diff_dst = &diff_dst[offset];
+ args.ws0 = &ws[ws_offset0];
+ args.ws1 = &ws[ws_offset1];
+ args.diff_src = &diff_src[offset];
+
+ if (C16 == 1)
+ (*ker_)(&args);
+ else if (c16 == 0)
+ (*ker_first_)(&args);
+ else if (c16 == C16 - 1)
+ (*ker_last_)(&args);
+ else
+ (*ker_)(&args);
+ nd_iterator_step(n, N, h, H, c16, C16);
+ }
+ } else {
+ int n{0}, c16{0};
+ nd_iterator_init(start, n, N, c16, C16);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ auto offset = n*C*H*W + c16*H*W*vsize;
+ auto ws_offset0 = n*C*H*2*W + c16*H*2*W*vsize;
+ auto ws_offset1 = ws_offset0 + H*W*vsize;
+
+ jit_args_bwd_t args;
+ args.src = &src[offset];
+ args.diff_dst = &diff_dst[offset];
+ args.ws0 = &ws[ws_offset0];
+ args.ws1 = &ws[ws_offset1];
+ args.diff_src = &diff_src[offset];
+
+ if (C16 == 1)
+ (*ker_)(&args);
+ else if (c16 == 0)
+ (*ker_first_)(&args);
+ else if (c16 == C16 - 1)
+ (*ker_last_)(&args);
+ else
+ (*ker_)(&args);
+
+ nd_iterator_step(n, N, c16, C16);
+ }
+ }
+ });
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.hpp
new file mode 100644
index 0000000000..37fbb9b3e5
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_common_lrn.hpp
@@ -0,0 +1,96 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_COMMON_LRN_HPP
+#define CPU_JIT_AVX512_COMMON_LRN_HPP
+
+#include "c_types_map.hpp"
+
+#include "cpu_isa_traits.hpp"
+#include "cpu_lrn_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_avx512_common_lrn_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_lrn_fwd_pd_t {
+ using cpu_lrn_fwd_pd_t::cpu_lrn_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", avx512_common, ""),
+ jit_avx512_common_lrn_fwd_t);
+
+ status_t init();
+ };
+
+ jit_avx512_common_lrn_fwd_t(const pd_t *apd);
+ ~jit_avx512_common_lrn_fwd_t();
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ int use_h_parallelism;
+ struct jit_avx512_common_lrn_kernel_f32;
+ jit_avx512_common_lrn_kernel_f32 *ker_, *ker_first_, *ker_last_;
+};
+
+struct jit_avx512_common_lrn_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_lrn_bwd_pd_t {
+ using cpu_lrn_bwd_pd_t::cpu_lrn_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", avx512_common, ""),
+ jit_avx512_common_lrn_bwd_t);
+
+ status_t init();
+ };
+
+ jit_avx512_common_lrn_bwd_t(const pd_t *apd);
+ ~jit_avx512_common_lrn_bwd_t();
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ int use_h_parallelism;
+ struct jit_avx512_common_lrn_kernel_f32;
+ jit_avx512_common_lrn_kernel_f32 *ker_, *ker_first_, *ker_last_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.cpp
new file mode 100644
index 0000000000..c58d3fa0a6
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.cpp
@@ -0,0 +1,1103 @@
+/*******************************************************************************
+ * Copyright 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_avx512_core_fp32_wino_conv_2x3.hpp"
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::format_kind;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+using namespace Xbyak;
+
+/// SRC TRANSFORMS /////////////////////////////////////////////////////////////
+struct jit_avx512_core_fp32_wino_conv_2x3_src_trans_t: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(
+ jit_avx512_core_fp32_wino_conv_2x3_src_trans_t)
+
+ jit_conv_conf_2x3_wino_t jcp;
+
+ struct call_params_t {
+ const void *src;
+ const void *wino_src;
+ const void *v_y_masks;
+ const void *v_x_masks;
+ };
+ void (*ker_)(const call_params_t *);
+
+ jit_avx512_core_fp32_wino_conv_2x3_src_trans_t(
+ jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr)
+ : jcp(ajcp) {
+ generate();
+ ker_ =
+ reinterpret_cast<decltype(ker_)>(const_cast<uint8_t*>(getCode()));
+ }
+
+ void generate();
+
+ Zmm vreg_inp(int i) {
+ assert(i < jcp.alpha * jcp.alpha);
+ return Zmm(31 - i);
+ }
+
+ Zmm vreg_tmp(int i) {
+ assert(i < jcp.alpha * jcp.alpha);
+ return Zmm(15 - i);
+ }
+
+ Zmm vreg_out(int i) {
+ assert(i < jcp.alpha * jcp.alpha);
+ return Zmm(31 - i);
+ }
+
+ Opmask y_mask = Opmask(1);
+ Opmask r_mask = Opmask(2);
+ Opmask x_mask(int id) {
+ assert (id < 4);
+ return Opmask(3 + id);
+ }
+
+ Reg64 reg_ptr_v_y_masks = r12;
+ Reg64 reg_ptr_v_x_masks = r11;
+
+ Reg64 reg_aux_ptr_src = r10;
+ Reg64 reg_aux_ptr_dst = r9;
+
+ Reg64 reg_ic_block = r8;
+
+};
+
+void jit_avx512_core_fp32_wino_conv_2x3_src_trans_t::generate() {
+ Label ic_block_label;
+
+ const int load_block = 16;
+ int out_offset = 0, inp_offset = 0;
+ preamble();
+
+#define READ_PARAM(reg, field) \
+ mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)])
+ READ_PARAM(reg_aux_ptr_src, src);
+ READ_PARAM(reg_aux_ptr_dst, wino_src);
+ READ_PARAM(reg_ptr_v_y_masks, v_y_masks);
+ READ_PARAM(reg_ptr_v_x_masks, v_x_masks);
+#undef READ_PARAM
+
+ for (int i = 0; i < jcp.alpha; i++) {
+ kmovw(x_mask(i), ptr[reg_ptr_v_x_masks + sizeof(int16_t) * i]);
+ }
+ mov(reg_ic_block, jcp.ic / load_block);
+ L(ic_block_label);
+ {
+ for (int y = 0; y < jcp.alpha; y++) {
+ kmovw(y_mask, ptr[reg_ptr_v_y_masks + sizeof(int16_t) * y]);
+ for (int x = 0; x < jcp.alpha; x++) {
+ Zmm zmm = vreg_inp(y * jcp.alpha + x);
+
+ vxorps(zmm, zmm, zmm);
+ kandw(r_mask, y_mask, x_mask(x));
+ inp_offset = sizeof(float)
+ * ((-jcp.t_pad + y) * jcp.iw * load_block
+ + (-jcp.l_pad + x) * load_block);
+ vmovups(zmm | r_mask,
+ EVEX_compress_addr(reg_aux_ptr_src, inp_offset));
+ }
+ }
+ for (int y = 0; y < jcp.alpha; y++) {
+ vsubps(vreg_tmp(y * jcp.alpha + 0), vreg_inp(y * jcp.alpha + 0),
+ vreg_inp(y * jcp.alpha + 2));
+ vaddps(vreg_tmp(y * jcp.alpha + 1), vreg_inp(y * jcp.alpha + 1),
+ vreg_inp(y * jcp.alpha + 2));
+ vsubps(vreg_tmp(y * jcp.alpha + 2), vreg_inp(y * jcp.alpha + 2),
+ vreg_inp(y * jcp.alpha + 1));
+ vsubps(vreg_tmp(y * jcp.alpha + 3), vreg_inp(y * jcp.alpha + 1),
+ vreg_inp(y * jcp.alpha + 3));
+ }
+ for (int x = 0; x < jcp.alpha; x++) {
+ vsubps(vreg_out(x + 0 * jcp.alpha), vreg_tmp(x + jcp.alpha * 0),
+ vreg_tmp(x + jcp.alpha * 2));
+ vaddps(vreg_out(x + 1 * jcp.alpha), vreg_tmp(x + jcp.alpha * 1),
+ vreg_tmp(x + jcp.alpha * 2));
+ vsubps(vreg_out(x + 2 * jcp.alpha), vreg_tmp(x + jcp.alpha * 2),
+ vreg_tmp(x + jcp.alpha * 1));
+ vsubps(vreg_out(x + 3 * jcp.alpha), vreg_tmp(x + jcp.alpha * 1),
+ vreg_tmp(x + jcp.alpha * 3));
+ }
+
+ for (int i = 0; i < 16; i++) {
+ out_offset = sizeof(float) * (jcp.inp_stride * i);
+ vmovups(EVEX_compress_addr(reg_aux_ptr_dst, out_offset),
+ vreg_out(i));
+ }
+
+ add(reg_aux_ptr_src, sizeof(float) * jcp.ih * jcp.iw * load_block);
+ add(reg_aux_ptr_dst, sizeof(float) * load_block);
+ }
+ dec(reg_ic_block);
+ cmp(reg_ic_block, 0);
+ jg(ic_block_label, T_NEAR);
+ postamble();
+}
+
+/// DST TRANSFORMS /////////////////////////////////////////////////////////////
+struct jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(
+ jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t)
+
+ jit_conv_conf_2x3_wino_t jcp;
+ const primitive_attr_t &attr_;
+
+ struct call_params_t {
+ const void *wino_dst;
+ const void *dst;
+ const void *v_y_masks;
+ const void *v_x_masks;
+
+ const void *bias;
+ const void *scales;
+ };
+ void (*ker_)(const call_params_t *);
+
+ jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t(
+ jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr) {
+ generate();
+ ker_ = reinterpret_cast<decltype(ker_)>(
+ const_cast<uint8_t *>(getCode()));
+ }
+
+ void generate();
+ bool maybe_relu(int position);
+
+ Zmm vreg_inp(int i) { // 16
+ assert(i < jcp.alpha * jcp.alpha);
+ return Zmm(31 - i);
+ }
+
+ Zmm vreg_stg(int id) { // 8
+ const int id_reg_stg = jcp.alpha * jcp.alpha + id;
+ assert(id_reg_stg < jcp.alpha * jcp.alpha + 8);
+ return Zmm(31 - id_reg_stg);
+ }
+
+ Zmm vreg_out(int id) { // 4
+ const int id_reg_out = jcp.alpha * jcp.alpha + 8 + id;
+ assert(id_reg_out < jcp.alpha * jcp.alpha + 12);
+ return Zmm(31 - id_reg_out);
+ }
+
+ Zmm vreg_tmp(int id) { // 2
+ const int id_reg_tmp = jcp.alpha * jcp.alpha + 12 + id;
+ assert(id_reg_tmp < jcp.alpha * jcp.alpha + 14);
+ return Zmm(31 - id_reg_tmp);
+ }
+
+ Zmm vreg_zero = Zmm(0);
+ Zmm vreg_prev_dst = Zmm(0);
+ Zmm vreg_bias = Zmm(2);
+
+ Opmask y_mask = Opmask(1);
+ Opmask r_mask = Opmask(2);
+ Opmask x_mask(int id) {
+ assert (id < 4);
+ return Opmask(3 + id);
+ }
+
+ Reg64 reg_ptr_v_y_masks = r12;
+ Reg64 reg_ptr_v_x_masks = r11;
+
+ Reg64 reg_aux_ptr_src = r10;
+ Reg64 reg_aux_ptr_dst = r9;
+
+ Reg64 reg_oc_block = r8;
+
+ Reg64 reg_ptr_bias = rbx;
+ Reg64 reg_ptr_scales = abi_not_param1;
+ Reg64 reg_ptr_sum_scale = rdx;
+};
+
+bool jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t::maybe_relu(int position) {
+ using namespace primitive_kind;
+ const auto &p = attr_.post_ops_;
+
+ if (position == 0) {
+ /* relu before sum */
+ return false
+ || p.contain(eltwise, 0);
+ } else if (position == 1) {
+ /* relu after sum */
+ const int sum_idx = p.contain(sum, 0)
+ ? 0 : (p.contain(sum, 1) ? 1 : -1);
+ if (sum_idx == -1)
+ return false;
+
+ return false
+ || p.contain(eltwise, sum_idx + 1);
+ }
+
+ return false;
+}
+
+void jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t::generate() {
+ Label oc_block_label;
+
+ const int load_block = 16;
+
+ auto loop_body = [=]() {
+ const auto &p = attr_.post_ops_;
+ const int sum_idx = p.find(primitive_kind::sum);
+ const float *p_sum_scale = (sum_idx != -1)
+ ? &p.entry_[sum_idx].sum.scale
+ : nullptr;
+ if (p_sum_scale && *p_sum_scale != 1.f)
+ mov(reg_ptr_sum_scale, (size_t)p_sum_scale);
+
+ for (int i = 0; i < 16; i++) {
+ int internal_offset = sizeof(float) * jcp.out_stride * i;
+ vmovups(vreg_inp(i),
+ EVEX_compress_addr(reg_aux_ptr_src, internal_offset));
+ }
+ for (int y = 0; y < jcp.alpha; y++) {
+ vaddps(vreg_tmp(0), vreg_inp(y * 4 + 0), vreg_inp(y * 4 + 1));
+ vaddps(vreg_stg(y * 2), vreg_tmp(0), vreg_inp(y * 4 + 2));
+
+ vsubps(vreg_tmp(1), vreg_inp(y * 4 + 1), vreg_inp(y * 4 + 2));
+ vsubps(vreg_stg(y * 2+1), vreg_tmp(1), vreg_inp(y * 4 + 3));
+ }
+ for (int x = 0; x < jcp.m; x++) {
+ vaddps(vreg_tmp(0), vreg_stg(x), vreg_stg(x+2 * 1));
+ vaddps(vreg_out(x), vreg_tmp(0), vreg_stg(x+2 * 2));
+
+ vsubps(vreg_tmp(1), vreg_stg(x+2 * 1), vreg_stg(x+2 * 2));
+ vsubps(vreg_out(x+2), vreg_tmp(1), vreg_stg(x+2 * 3));
+ }
+
+
+ if (jcp.with_bias) {
+ auto bias_addr = ptr [ reg_ptr_bias ];
+ vmovups(vreg_bias, bias_addr);
+ }
+ for (int y = 0; y < jcp.m; y++) {
+ kmovw(y_mask, ptr[ reg_ptr_v_y_masks + sizeof(int16_t) * y ]);
+ for (int x = 0; x < jcp.m; x++) {
+ kandw(r_mask, y_mask, x_mask(x));
+
+ int i = y * jcp.m + x;
+ int offset = sizeof(float) *
+ (y * jcp.ow * jcp.oc_block + x * jcp.oc_block);
+ Address addr = EVEX_compress_addr(reg_aux_ptr_dst, offset);
+
+ Zmm zmm = vreg_out(i);
+ if (jcp.with_bias)
+ vaddps(zmm, zmm, vreg_bias);
+ vmulps(zmm, zmm, ptr [reg_ptr_scales]);
+
+ if (maybe_relu(0)) {
+ vxorps(vreg_zero, vreg_zero, vreg_zero);
+ vmaxps(zmm, vreg_zero, zmm);
+ }
+ if (p_sum_scale) { // post_op: sum
+ vxorps(vreg_prev_dst, vreg_prev_dst, vreg_prev_dst);
+ vmovups(vreg_prev_dst | r_mask, addr);
+ if (*p_sum_scale == 1.f)
+ vaddps(zmm, vreg_prev_dst);
+ else
+ vfmadd231ps(zmm, vreg_prev_dst,
+ zword_b[reg_ptr_sum_scale]);
+ }
+ if (maybe_relu(1)) {
+ vxorps(vreg_zero, vreg_zero, vreg_zero);
+ vmaxps(zmm, vreg_zero, zmm);
+ }
+
+ vmovups(addr, zmm | r_mask);
+ }
+ }
+ };
+
+ preamble();
+
+#define READ_PARAM(reg, field) \
+ mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)])
+ READ_PARAM(reg_aux_ptr_src, wino_dst);
+ READ_PARAM(reg_aux_ptr_dst, dst);
+ READ_PARAM(reg_ptr_v_y_masks, v_y_masks);
+ READ_PARAM(reg_ptr_v_x_masks, v_x_masks);
+ READ_PARAM(reg_ptr_bias, bias);
+ READ_PARAM(reg_ptr_scales, scales);
+#undef READ_PARAM
+
+ for (int i = 0; i < jcp.alpha * jcp.alpha; i++)
+ vxorps(vreg_inp(i), vreg_inp(i), vreg_inp(i));
+
+ for (int i = 0; i < jcp.alpha; i++)
+ kmovw(x_mask(i), ptr[reg_ptr_v_x_masks + sizeof(int16_t) * i]);
+
+ int oc_blocks = 1;
+ oc_blocks = jcp.oc / load_block;
+ mov(reg_oc_block, oc_blocks);
+ L(oc_block_label);
+ {
+ loop_body();
+ add(reg_aux_ptr_src, sizeof(float) * load_block);
+ add(reg_aux_ptr_dst, sizeof(float) * jcp.oh * jcp.ow * load_block);
+
+ add(reg_ptr_scales, jcp.is_oc_scale * sizeof(float) * load_block);
+ add(reg_ptr_bias, jcp.typesize_bia * load_block);
+ }
+ dec(reg_oc_block);
+ cmp(reg_oc_block, 0);
+ jg(oc_block_label, T_NEAR);
+
+ sub(reg_ptr_scales, jcp.is_oc_scale * sizeof(float) * load_block);
+ sub(reg_ptr_bias, oc_blocks * jcp.typesize_bia * load_block);
+
+ postamble();
+
+}
+
+/// GEMM kernel ////////////////////////////////////////////////////////////////
+struct jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t)
+ jit_conv_conf_2x3_wino_t jcp;
+
+ struct call_params_t {
+ const void *src;
+ const void *dst;
+ const void *wei;
+ const void *dst_b;
+ };
+ void (*ker_)(const call_params_t *);
+
+ void generate();
+ static bool post_ops_ok(jit_conv_conf_2x3_wino_t &jcp,
+ const primitive_attr_t &attr);
+
+ jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t(
+ jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr)
+ : jcp(ajcp) {
+ generate();
+ ker_ = reinterpret_cast<decltype(ker_)>(
+ const_cast<uint8_t *>(getCode()));
+ }
+
+ static status_t init_conf(
+ jit_conv_conf_2x3_wino_t &jcp, const convolution_desc_t &cd,
+ memory_desc_t &src_md, memory_desc_t &weights_md,
+ memory_desc_t &dst_md, memory_desc_t &bias_md,
+ const primitive_attr_t &attr,
+ memory_desc_t& expect_wei_md);
+
+ Zmm vreg_out(int n, int m) {
+ const int id_reg_out = n * jcp.m_block + m;
+ assert(id_reg_out < jcp.n2_block * jcp.m_block);
+ return Zmm(31 - id_reg_out);
+ }
+ Zmm vreg_wei(int i) {
+ assert (31 - jcp.n2_block * jcp.m_block - i > 1);
+ return Zmm(31 - jcp.n2_block * jcp.m_block - i);
+ }
+
+ Zmm vreg_src = Zmm(0);
+ Zmm vreg_one = Zmm(1);
+ Zmm vreg_tmp = Zmm(2);
+
+ Reg64 reg_ptr_src = r15;
+
+ Reg64 reg_aux_dst = r12;
+ Reg64 reg_aux_dst2 = r11;
+ Reg64 reg_aux_wei = r10;
+ Reg64 reg_aux_wei2 = r9;
+ Reg64 reg_aux_src = r8;
+ Reg64 reg_aux_src2 = rax;
+
+ Reg64 reg_mb = rbx;
+ Reg64 reg_nnb = rdx;
+ Reg64 reg_K = rsi;
+
+};
+
+bool jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t::post_ops_ok(
+ jit_conv_conf_2x3_wino_t &jcp, const primitive_attr_t &attr) {
+ using namespace primitive_kind;
+ const auto &p = attr.post_ops_;
+
+ auto is_relu = [&](int idx) { return p.entry_[idx].is_relu(); };
+
+ switch (p.len_) {
+ case 0: return true;
+ case 1: return is_relu(0) || p.contain(sum, 0);
+ case 2: return (p.contain(sum, 0) && is_relu(1)) ||
+ (p.contain(sum, 1) && is_relu(0));
+ case 3: return is_relu(0) && p.contain(sum, 1) && is_relu(2);
+ default: return false;
+ }
+
+ return false;
+}
+
+void jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t::generate() {
+ Label nnb_loop_label, K_loop_label, mb_loop_label;
+
+ preamble();
+#define READ_PARAM(reg, field) \
+ mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)])
+ READ_PARAM(reg_ptr_src, src);
+ READ_PARAM(reg_aux_dst, dst);
+ READ_PARAM(reg_aux_wei, wei);
+#undef READ_PARAM
+
+ if (!jcp.small_mb) {
+ mov(reg_nnb, jcp.n_chunks);
+ L(nnb_loop_label);
+ }
+ mov(reg_aux_dst2, reg_aux_dst);
+ mov(reg_aux_src, reg_ptr_src);
+ mov(reg_mb, jcp.M / jcp.m_block);
+ L(mb_loop_label);
+ {
+ int nb2 = 0;
+ for (nb2 = 0; nb2 < jcp.n2_block; nb2++) {
+ for (int m = 0; m < jcp.m_block; m++) {
+ vxorps(vreg_out(nb2, m), vreg_out(nb2, m), vreg_out(nb2, m));
+ }
+ }
+ mov(reg_aux_src2, reg_aux_src);
+ mov(reg_aux_wei2, reg_aux_wei);
+
+ mov(reg_K, jcp.k_chunks);
+ L(K_loop_label); {
+ int wei_offset = 0;
+ for (int _i = 0; _i < jcp.k2_block; _i++) {
+ for (int nb2 = 0; nb2 < jcp.n2_block; nb2++) {
+ if (jcp.small_mb) {
+ int wei_offset = sizeof(float)
+ * ((nb2 * jcp.nb_ic * jcp.ic_block
+ * jcp.oc_block)
+ + _i * jcp.oc_block);
+ vmovups(vreg_wei(nb2),
+ EVEX_compress_addr(reg_aux_wei2, wei_offset));
+ } else {
+ vmovups(vreg_wei(nb2),
+ EVEX_compress_addr(reg_aux_wei2,
+ sizeof(float) * wei_offset));
+ wei_offset += jcp.oc_block;
+ }
+ }
+ for (int m = 0; m < jcp.m_block; m++) {
+ int inp_offset = sizeof(float) * (m * jcp.K + _i);
+ if (jcp.n2_block > 1) {
+ vbroadcastss(vreg_src,
+ EVEX_compress_addr(reg_aux_src2, inp_offset));
+ for (int nb2 = 0; nb2 < jcp.n2_block; nb2++)
+ vfmadd231ps(vreg_out(nb2, m), vreg_wei(nb2),
+ vreg_src);
+ } else {
+ vfmadd231ps(vreg_out(0, m), vreg_wei(0),
+ EVEX_compress_addr(reg_aux_src2, inp_offset, true));
+ }
+ }
+ }
+ add(reg_aux_src2, sizeof(float) * jcp.ic_block);
+ if (jcp.small_mb)
+ add(reg_aux_wei2, sizeof(float) * jcp.oc_block * jcp.ic_block);
+ else
+ add(reg_aux_wei2,
+ sizeof(float) * jcp.k2_block * jcp.n2_block
+ * jcp.oc_block);
+ }
+ dec(reg_K);
+ cmp(reg_K, 0);
+ jg(K_loop_label, T_NEAR);
+
+ for (int m = 0; m < jcp.m_block; m++) {
+ int nb2 = 0;
+ for (nb2 = 0; nb2 < jcp.n2_block; nb2++) {
+ int offset = sizeof(float) *
+ (m * jcp.N + nb2 * jcp.oc_block);
+ vmovups(EVEX_compress_addr(reg_aux_dst2,offset),
+ vreg_out(nb2, m));
+ }
+ }
+ add(reg_aux_src, sizeof(float) * jcp.m_block * jcp.K);
+ add(reg_aux_dst2, sizeof(float) * jcp.m_block * jcp.N);
+ }
+ dec(reg_mb);
+ cmp(reg_mb, 0);
+ jg(mb_loop_label, T_NEAR);
+
+ if (!jcp.small_mb) {
+ add(reg_aux_dst, sizeof(float) * jcp.n2_block * jcp.oc_block);
+ add(reg_aux_wei,
+ sizeof(float) * jcp.k_chunks * jcp.ic_block * jcp.n2_block
+ * jcp.oc_block);
+
+ dec(reg_nnb);
+ cmp(reg_nnb, 0);
+ jg(nnb_loop_label, T_NEAR);
+ }
+ postamble();
+}
+
+namespace {
+bool is_winograd_faster_than_direct(const jit_conv_conf_2x3_wino_t &jcp) {
+ return jcp.mb >= 4;
+}
+}
+
+status_t jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t ::init_conf(
+ jit_conv_conf_2x3_wino_t &jcp, const convolution_desc_t &cd,
+ memory_desc_t &src_md, memory_desc_t &wei_md,
+ memory_desc_t &dst_md, memory_desc_t &bias_md,
+ const primitive_attr_t &attr, memory_desc_t &expect_wei_md) {
+ const memory_desc_wrapper src_d(&src_md);
+ const memory_desc_wrapper wei_d(&wei_md);
+ const memory_desc_wrapper dst_d(&dst_md);
+ const memory_desc_wrapper bias_d(&bias_md);
+
+ const bool with_groups = wei_d.ndims() == src_d.ndims() + 1;
+
+ jcp.nthr = mkldnn_get_max_threads();
+
+ jcp.ngroups = with_groups ? wei_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.ih = src_d.dims()[2];
+ jcp.iw = src_d.dims()[3];
+ jcp.oh = dst_d.dims()[2];
+ jcp.ow = dst_d.dims()[3];
+ jcp.kh = wei_d.dims()[with_groups + 2];
+ jcp.kw = wei_d.dims()[with_groups + 3];
+ jcp.t_pad = cd.padding[0][0];
+ jcp.b_pad = cd.padding[1][0];
+ jcp.l_pad = cd.padding[0][1];
+ jcp.r_pad = cd.padding[1][1];
+ jcp.stride_h = cd.strides[0];
+ jcp.stride_w = cd.strides[1];
+ jcp.dilate_h = cd.dilates[0];
+ jcp.dilate_w = cd.dilates[1];
+
+ jcp.m = 2;
+ jcp.r = 3;
+ jcp.alpha = jcp.m + jcp.r - 1;
+ int simdw = 16;
+
+ format_tag_t dat_tag = format_tag::nChw16c;
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag);
+
+ if (jcp.src_tag != dat_tag) return status::unimplemented;
+ if (jcp.dst_tag != dat_tag) return status::unimplemented;
+
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ bool ok_to_pad_channels = jcp.ngroups == 1;
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simdw);
+ jcp.ic = rnd_up(jcp.ic, simdw);
+ }
+
+ jcp.ver = ver_avx512_core;
+ if (!(mayiuse(avx512_core)))
+ return status::unimplemented;
+
+ if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto,
+ is_winograd_faster_than_direct(jcp)))
+ return status::unimplemented;
+
+ if (src_d.data_type() != data_type::f32)
+ return status::unimplemented;
+ if (wei_d.data_type() != data_type::f32)
+ return status::unimplemented;
+ if (dst_d.data_type() != data_type::f32)
+ return status::unimplemented;
+
+ jcp.ic_block = simdw;
+ jcp.oc_block = simdw;
+
+ bool ok = true && jcp.kh == 3 && jcp.kw == 3 && jcp.ngroups == 1
+ && jcp.oc % jcp.oc_block == 0 && jcp.ic % jcp.ic_block == 0
+ && jcp.stride_h == 1 && jcp.stride_w == 1 && jcp.dilate_h == 0
+ && jcp.dilate_w == 0 && jcp.t_pad == jcp.b_pad
+ && jcp.l_pad == jcp.r_pad && jcp.t_pad < 2 && jcp.t_pad >= 0
+ && jcp.l_pad < 2 && jcp.l_pad >= 0;
+ if (!ok)
+ return status::unimplemented;
+
+ const int L2_cap = get_cache_size(2, true) / sizeof(float);
+ const int L3_capacity = get_cache_size(3, false) / sizeof(float);
+ int a = jcp.alpha;
+ int aa = a * a;
+ int mb = jcp.mb;
+ int ic = jcp.ic;
+ int oc = jcp.oc;
+ int ih = jcp.ih;
+ int iw = jcp.iw;
+ auto wei_sz = (float)aa * ic * oc;
+ auto inp_sz = (float)mb * ih * iw * ic;
+ auto sp_sz = (float)mb * ih * iw;
+
+ /* Heuristics here. Numbers '28','196' is an observation from data. */
+ if (wei_sz / inp_sz > 5)
+ jcp.small_mb = true;
+ else
+ jcp.small_mb = false;
+
+ if (mb > nstl::min(jcp.nthr, 28)
+ || (!jcp.small_mb
+ && (wei_sz >= 0.9f * L2_cap
+ || inp_sz > L2_cap * jcp.nthr + L3_capacity))
+ || (jcp.small_mb && sp_sz > 196))
+ return status::unimplemented;
+
+ jcp.bia_dt = jcp.with_bias ? cd.bias_desc.data_type : data_type::undef;
+ jcp.dst_dt = cd.dst_desc.data_type;
+
+ jcp.typesize_bia
+ = jcp.with_bias ? types::data_type_size(bias_d.data_type()) : 0;
+
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+
+ const int skx_free_regs = 30;
+
+ auto find_m_n2_blocks = [=](int xb, int yb, int &M, int &m_block,
+ int &n2_block, float &reg_eff) {
+ M = (xb * yb) / jcp.alpha;
+ int max_m_block = m_block = nstl::min(M, skx_free_regs);
+ int max_n2_block = n2_block = nstl::min(jcp.nb_oc, skx_free_regs);
+ reg_eff = 0;
+ for (int im = max_m_block; im > 0; im--) {
+ for (int in2 = max_n2_block; in2 > 0; in2--) {
+ int used_regs = in2 * im + in2;
+ float cur_reg_eff = ((float)in2 * im) / (im + in2) / 2.5f;
+ if (M % im || jcp.nb_oc % in2 || used_regs > skx_free_regs
+ || cur_reg_eff <= reg_eff)
+ continue;
+ reg_eff = cur_reg_eff;
+ m_block = im;
+ n2_block = in2;
+ }
+ }
+ };
+
+ int oh = jcp.oh;
+ int ow = jcp.ow;
+ int nb_oc = jcp.nb_oc;
+ int Z = ic + oc;
+ int Y = ic * oc;
+ const int L3_cap_per_core = get_cache_size(3, true) / sizeof(float);
+
+ /* Selecting xb and yb blocking */
+ int min_yb = jcp.alpha;
+ int min_xb = jcp.alpha;
+ int max_yb = nstl::max(min_yb, rnd_up(ih, 2));
+ int max_xb = nstl::max(min_xb, rnd_up(iw, 2));
+ float best_eff = 0.f;
+ for (int ix = max_xb; ix >= min_xb; ix -= 2) {
+ if (rnd_up(ow, ix) < iw - 2)
+ continue;
+ for (int iy = max_yb; iy >= min_yb; iy -= 2) {
+ if (rnd_up(oh, iy) < ih - 2)
+ continue;
+ int ex_y = rnd_up(oh, iy);
+ int ex_x = rnd_up(ow, ix);
+ float work_eff = (float)(ih * iw) / (ex_y * ex_x);
+
+ int M, m_block, n2_b;
+ float reg_eff, thr_eff, par_eff, mem_eff, req_mem;
+
+ find_m_n2_blocks(ix, iy, M, m_block, n2_b, reg_eff);
+
+ /* outer parallelization */
+ int nblocks = mb * div_up(ih, iy) * div_up(iw, ix);
+ thr_eff = (float)nblocks / rnd_up(nblocks, jcp.nthr);
+
+ mem_eff = 1.f;
+ req_mem = (((float)ix + 2) * (iy + 2) + aa * M) * Z + aa * Y;
+ if (req_mem > L2_cap / 2) {
+ if (req_mem > ((L2_cap + L3_cap_per_core) * 4) / 7)
+ mem_eff /= (n2_b + 1) / 2.f;
+ else
+ mem_eff /= (n2_b + 1) / 3.f;
+ }
+
+ float outer_eff = thr_eff + work_eff + reg_eff + mem_eff;
+
+ /* inner parallelization */
+ int bsz = iy * ix / a;
+ int gemmw = aa * (nb_oc / n2_b);
+ int bsz_r = rnd_up(bsz, jcp.nthr);
+ int gemmw_r = rnd_up(gemmw, jcp.nthr);
+ thr_eff = ((float)Z * bsz / bsz_r + Y * gemmw / gemmw_r) / (Z + Y);
+
+ req_mem = (float)ix * iy * (ic + simdw * n2_b) + simdw * n2_b * ic;
+ mem_eff = nstl::min(1.f, L2_cap / req_mem);
+ int M_per_thr = nstl::max(2, div_up(aa, jcp.nthr));
+ int oc_per_thr =
+ nstl::min(oc, div_up(aa * (nb_oc / n2_b), jcp.nthr));
+ req_mem = (float)aa * oc_per_thr * ic + M_per_thr * M * Z;
+ if (req_mem > L2_cap)
+ mem_eff = 0.1f;
+ par_eff = 1 / (2.f * nblocks);
+
+ float inner_eff = thr_eff + work_eff + mem_eff + par_eff;
+
+ float eff = jcp.small_mb ? inner_eff : outer_eff;
+ if (eff > best_eff) {
+ best_eff = eff;
+ jcp.yb = iy;
+ jcp.xb = ix;
+ jcp.M = M;
+ jcp.m_block = m_block;
+ jcp.n2_block = n2_b;
+ }
+ }
+ }
+
+ assert(jcp.xb % 2 == 0 && jcp.yb % 2 == 0);
+
+ jcp.inp_stride = jcp.M * jcp.ic;
+ jcp.out_stride = jcp.M * jcp.oc;
+ jcp.wei_stride = jcp.ic * jcp.oc;
+ jcp.bia_stride = jcp.oc;
+
+ jcp.N = jcp.oc;
+ jcp.K = jcp.ic;
+
+ jcp.n_block = jcp.oc_block;
+ jcp.k_block = jcp.ic_block;
+
+ assert(jcp.M % jcp.m_block == 0);
+ assert(jcp.nb_oc % jcp.n2_block == 0);
+
+ jcp.n_chunks = jcp.nb_oc / jcp.n2_block;
+ jcp.k2_block = jcp.ic_block;
+ jcp.k_chunks = jcp.K / jcp.k2_block;
+
+ const auto &oscales = attr.output_scales_;
+ jcp.is_oc_scale = oscales.mask_ == 1 << 1;
+ assert(IMPLICATION(!jcp.is_oc_scale, oscales.mask_ == 0));
+
+ /* re-create weights primitive descriptor
+ and set weights wino_blocking */
+ expect_wei_md.format_kind = format_kind::wino;
+ expect_wei_md.data_type = data_type::f32;
+ mkldnn_wino_desc_t &wd = expect_wei_md.format_desc.wino_desc;
+ wd.wino_format
+ = jcp.small_mb ? mkldnn_wino_wei_aaOio : mkldnn_wino_wei_aaOBiOo;
+ wd.r = jcp.r;
+ wd.alpha = jcp.alpha;
+ wd.ic = jcp.ic;
+ wd.oc = jcp.oc;
+ wd.ic_block = jcp.ic_block;
+ wd.oc_block = jcp.oc_block;
+ wd.oc2_block = jcp.n2_block;
+ wd.ic2_block = 1;
+ wd.adj_scale = 1.f;
+ size_t max_size = sizeof(float) * jcp.alpha * jcp.alpha * jcp.ic * jcp.oc;
+ wd.size = max_size;
+
+ return status::success;
+}
+////////////////////////////////////////////////////////////////////////////////
+
+status_t jit_avx512_core_fp32_wino_conv_2x3_fwd_t
+ ::pd_t::jit_conf(memory_desc_t& expect_wei_md) {
+ return jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t::init_conf(
+ jcp_, *this->desc(), this->src_md_, this->weights_md_,
+ this->dst_md_,this->bias_md_, *this->attr(), expect_wei_md);
+}
+
+jit_avx512_core_fp32_wino_conv_2x3_fwd_t::
+ jit_avx512_core_fp32_wino_conv_2x3_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+{
+ kernel_ = new jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t(
+ pd()->jcp_, *pd()->attr());
+ src_trans_ = new jit_avx512_core_fp32_wino_conv_2x3_src_trans_t(
+ pd()->jcp_, *pd()->attr());
+ dst_trans_ = new jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t(
+ pd()->jcp_, *pd()->attr());
+}
+
+jit_avx512_core_fp32_wino_conv_2x3_fwd_t
+ ::~jit_avx512_core_fp32_wino_conv_2x3_fwd_t() {
+ delete kernel_;
+ delete src_trans_;
+ delete dst_trans_;
+}
+
+void jit_avx512_core_fp32_wino_conv_2x3_fwd_t::execute_forward_mbN(
+ const float *src, const float *wei, const float *bia, float *dst,
+ const memory_tracking::grantor_t &scratchpad) const
+{
+ const auto &jcp = kernel_->jcp;
+ const auto &oscales = pd()->attr()->output_scales_;
+
+ const size_t wino_size_offset =
+ (size_t)(pd()->jcp_.yb / 2) * (pd()->jcp_.xb / 2) + (pd()->jcp_.xb);
+ const size_t size_wino_src = wino_size_offset * pd()->jcp_.ic * 16;
+ const size_t size_wino_dst = wino_size_offset * pd()->jcp_.oc * 16;
+
+ if (pd()->wants_padded_bias()) {
+ auto padded_bias = scratchpad.get<float>(key_conv_padded_bias);
+ utils::array_copy(padded_bias, bia, jcp.oc_without_padding);
+ utils::array_set(padded_bias + jcp.oc_without_padding, 0.f,
+ jcp.oc - jcp.oc_without_padding);
+ bia = padded_bias;
+ }
+
+ auto ptr_V = scratchpad.get<float>(key_wino_V);
+ auto ptr_M = scratchpad.get<float>(key_wino_M);
+
+ parallel_nd(jcp.mb, div_up(jcp.oh,jcp.yb), div_up(jcp.ow, jcp.xb),
+ [&](int mb, int tile_y_b, int tile_x_b) {
+ int tile_y = tile_y_b * jcp.yb;
+ int tile_x = tile_x_b * jcp.xb;
+
+ int ithr = mkldnn_get_thread_num();
+ auto wino_src = ptr_V + size_wino_src * ithr;
+ auto wino_dst = ptr_M + size_wino_dst * ithr;
+
+ auto src_trans_p =
+ jit_avx512_core_fp32_wino_conv_2x3_src_trans_t
+ ::call_params_t();
+ auto dst_trans_p =
+ jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t
+ ::call_params_t();
+ auto gemm_p = jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t ::
+ call_params_t();
+
+ /* transformation of input tensor to winograd domain */
+ for (int y_in_block = 0; y_in_block < jcp.yb; y_in_block += 2) {
+ for (int x_in_block = 0; x_in_block < jcp.xb;
+ x_in_block += 2) {
+
+ unsigned short v_y_masks[4], v_x_masks[4];
+
+ int y = y_in_block + tile_y;
+ int x = x_in_block + tile_x;
+ int m = (y_in_block / 2) * (jcp.xb / 2)
+ + (x_in_block / 2);
+
+ int v_ys = nstl::max(0, jcp.t_pad - y);
+ int v_ye = nstl::min(jcp.alpha,
+ nstl::max(0, jcp.ih + jcp.t_pad - y));
+
+ int v_xs = nstl::max(0, jcp.l_pad - x);
+ int v_xe = nstl::min(jcp.alpha,
+ nstl::max(0, jcp.iw + jcp.l_pad - x));
+
+#pragma unroll(4)
+ for (int i = 0; i < jcp.alpha; i++) {
+ v_y_masks[i] = (i < v_ys || i >= v_ye) ? 0 : 0xffff;
+ v_x_masks[i] = (i < v_xs || i >= v_xe) ? 0 : 0xffff;
+ }
+ auto local_s = src
+ + mb * jcp.nb_ic * jcp.ih * jcp.iw
+ * jcp.ic_block
+ + y * jcp.iw * jcp.ic_block + x * jcp.ic_block;
+ auto local_w = wino_src + m * jcp.ic;
+
+ src_trans_p.src = local_s;
+ src_trans_p.wino_src = local_w;
+ src_trans_p.v_y_masks = v_y_masks;
+ src_trans_p.v_x_masks = v_x_masks;
+
+ src_trans_->ker_(&src_trans_p);
+ }
+ }
+ /* gemms */
+ for (int tile_ij = 0; tile_ij < 16; tile_ij++) {
+ int offset = (tile_ij + ithr) % 16;
+ gemm_p.src = wino_src + jcp.inp_stride * offset;
+ gemm_p.dst = wino_dst + jcp.out_stride * offset;
+ gemm_p.wei = wei + jcp.wei_stride * offset;
+
+ kernel_->ker_(&gemm_p);
+ }
+
+ /* transformation from winograd domain to output tensor */
+ for (int y_in_block = 0; y_in_block < jcp.yb; y_in_block += 2) {
+ for (int x_in_block = 0; x_in_block < jcp.xb;
+ x_in_block += 2) {
+ unsigned short v_y_masks[2], v_x_masks[2];
+
+ int y = y_in_block + tile_y;
+ int x = x_in_block + tile_x;
+ int m = (y_in_block / 2) * (jcp.xb / 2)
+ + (x_in_block / 2);
+
+#pragma unroll(2)
+ for (int i = 0; i < jcp.m; i++) {
+ v_x_masks[i] = (x + i < jcp.ow) ? 0xffff : 0;
+ v_y_masks[i] = (y + i < jcp.oh) ? 0xffff : 0;
+ }
+ auto local_d = dst
+ + mb * jcp.nb_oc * jcp.oh * jcp.ow
+ * jcp.oc_block
+ + y * jcp.ow * jcp.oc_block + x * jcp.oc_block;
+ auto local_w = wino_dst + m * jcp.oc;
+
+ auto scales = oscales.scales_;
+ dst_trans_p.dst = local_d;
+ dst_trans_p.wino_dst = local_w;
+ dst_trans_p.v_y_masks = v_y_masks;
+ dst_trans_p.v_x_masks = v_x_masks;
+
+ dst_trans_p.scales = scales;
+ dst_trans_p.bias = bia;
+
+ dst_trans_->ker_(&dst_trans_p);
+ }
+ }
+ });
+}
+
+void jit_avx512_core_fp32_wino_conv_2x3_fwd_t::execute_forward_small_mb(
+ const float *src, const float *wei, const float *bia, float *dst,
+ const memory_tracking::grantor_t &scratchpad) const
+{
+ const auto &jcp = kernel_->jcp;
+ const auto &oscales = pd()->attr()->output_scales_;
+
+ if (pd()->wants_padded_bias()) {
+ auto padded_bias = scratchpad.get<float>(key_conv_padded_bias);
+ utils::array_copy(padded_bias, bia, jcp.oc_without_padding);
+ utils::array_set(padded_bias + jcp.oc_without_padding, 0.f,
+ jcp.oc - jcp.oc_without_padding);
+ bia = padded_bias;
+ }
+
+ auto ptr_V = scratchpad.get<float>(key_wino_V);
+ auto ptr_M = scratchpad.get<float>(key_wino_M);
+
+ for (int mb = 0; mb < jcp.mb; mb++) {
+ for (int tile_y = 0; tile_y < jcp.oh; tile_y += jcp.yb) {
+ for (int tile_x = 0; tile_x < jcp.ow; tile_x += jcp.xb) {
+ /* transformation of input tensor to winograd domain */
+ parallel_nd(div_up(jcp.yb, 2), div_up(jcp.xb, 2),
+ [&](int y_in_block_b, int x_in_block_b) {
+ int y_in_block = y_in_block_b * 2;
+ int x_in_block = x_in_block_b * 2;
+
+ auto src_trans_p = jit_avx512_core_fp32_wino_conv_2x3_src_trans_t ::
+ call_params_t();
+
+ unsigned short v_y_masks[4], v_x_masks[4];
+
+ int y = y_in_block + tile_y;
+ int x = x_in_block + tile_x;
+ int m = (y_in_block / 2) * (jcp.xb / 2) + (x_in_block / 2);
+
+ int v_ys = nstl::max(0, jcp.t_pad - y);
+ int v_ye = nstl::min(
+ jcp.alpha, nstl::max(0, jcp.ih + jcp.t_pad - y));
+
+ int v_xs = nstl::max(0, jcp.l_pad - x);
+ int v_xe = nstl::min(
+ jcp.alpha, nstl::max(0, jcp.iw + jcp.l_pad - x));
+
+#pragma unroll(4)
+ for (int i = 0; i < jcp.alpha; i++) {
+ v_y_masks[i] = (i < v_ys || i >= v_ye) ? 0 : 0xffff;
+ v_x_masks[i] = (i < v_xs || i >= v_xe) ? 0 : 0xffff;
+ }
+ auto local_s = src
+ + mb * jcp.nb_ic * jcp.ih * jcp.iw * jcp.ic_block
+ + y * jcp.iw * jcp.ic_block + x * jcp.ic_block;
+ auto local_w = ptr_V + m * jcp.ic;
+
+ src_trans_p.src = local_s;
+ src_trans_p.wino_src = local_w;
+ src_trans_p.v_y_masks = v_y_masks;
+ src_trans_p.v_x_masks = v_x_masks;
+
+ src_trans_->ker_(&src_trans_p);
+ });
+
+ /* gemms */
+ parallel_nd(16, jcp.n_chunks, [&](int tile_ij, int nnb) {
+ auto gemm_p = jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t ::
+ call_params_t();
+
+ gemm_p.src = ptr_V + jcp.inp_stride * tile_ij;
+ gemm_p.dst = ptr_M + jcp.out_stride * tile_ij
+ + nnb * jcp.n2_block * jcp.n_block;
+ gemm_p.wei = wei + jcp.wei_stride * tile_ij
+ + nnb * jcp.n2_block * jcp.n_block * jcp.K;
+
+ kernel_->ker_(&gemm_p);
+ });
+
+ /* transformation from winograd domain to output tensor */
+
+ parallel_nd(div_up(jcp.yb, 2), div_up(jcp.xb, 2),
+ [&](int y_in_block_b, int x_in_block_b) {
+ int y_in_block = y_in_block_b * 2;
+ int x_in_block = x_in_block_b * 2;
+
+ auto dst_trans_p = jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t ::
+ call_params_t();
+
+ unsigned short v_y_masks[2], v_x_masks[2];
+
+ int y = y_in_block + tile_y;
+ int x = x_in_block + tile_x;
+ int m = (y_in_block / 2) * (jcp.xb / 2) + (x_in_block / 2);
+
+#pragma unroll(2)
+ for (int i = 0; i < jcp.m; i++) {
+ v_x_masks[i] = (x + i < jcp.ow) ? 0xffff : 0;
+ v_y_masks[i] = (y + i < jcp.oh) ? 0xffff : 0;
+ }
+ auto local_d = dst
+ + mb * jcp.nb_oc * jcp.oh * jcp.ow * jcp.oc_block
+ + y * jcp.ow * jcp.oc_block + x * jcp.oc_block;
+ auto local_w = ptr_M + m * jcp.oc;
+
+ auto scales = oscales.scales_;
+ dst_trans_p.dst = local_d;
+ dst_trans_p.wino_dst = local_w;
+ dst_trans_p.v_y_masks = v_y_masks;
+ dst_trans_p.v_x_masks = v_x_masks;
+
+ dst_trans_p.scales = scales;
+ dst_trans_p.bias = bia;
+
+ dst_trans_->ker_(&dst_trans_p);
+ });
+ }}}
+}
+
+} // namespace cpu
+} // namespace impl
+} // namespace mkldnn
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.hpp
new file mode 100644
index 0000000000..7e38b07f5a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.hpp
@@ -0,0 +1,144 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_CORE_FP32_WINO_CONV_2x3_HPP
+#define CPU_JIT_AVX512_CORE_FP32_WINO_CONV_2x3_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_primitive_conf.hpp"
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t;
+struct jit_avx512_core_fp32_wino_conv_2x3_src_trans_t;
+struct jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t;
+
+struct jit_avx512_core_fp32_wino_conv_2x3_fwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_fp32_wino_2x3:", avx512_core, ""),
+ jit_avx512_core_fp32_wino_conv_2x3_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::forward_inference
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::convolution_auto,
+ alg_kind::convolution_winograd)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ memory_desc_t expect_wei_md = *weights_md();
+ status_t jit_conf_result = jit_conf(expect_wei_md);
+ if (jit_conf_result != status::success) return jit_conf_result;
+ set_default_alg_kind(alg_kind::convolution_winograd);
+
+ if (weights_md_.format_kind == format_kind::any)
+ weights_md_ = expect_wei_md;
+ if (weights_md_ != expect_wei_md)
+ return status::unimplemented;
+
+ init_scratchpad();
+
+ return status::success;
+ }
+
+ jit_conv_conf_2x3_wino_t jcp_;
+
+ protected:
+ status_t jit_conf(memory_desc_t& expect_wei_md);
+
+ void init_scratchpad() {
+ using namespace memory_tracking::names;
+
+ auto scratchpad = scratchpad_registry().registrar();
+
+ int wino_size_offset = (jcp_.yb / 2) * (jcp_.xb / 2) + jcp_.xb;
+
+ size_t V_sz = (size_t)jcp_.ic * 16 * wino_size_offset * jcp_.nthr;
+ scratchpad.book(key_wino_V, sizeof(float) * V_sz, PAGE_4K);
+
+ size_t M_sz = (size_t)jcp_.oc * 16 * wino_size_offset * jcp_.nthr;
+ scratchpad.book(key_wino_M, sizeof(float) * M_sz, PAGE_4K);
+
+ if (wants_padded_bias()) {
+ assert(jcp_.ngroups == 1);
+ scratchpad.book(key_conv_padded_bias, sizeof(float) * jcp_.oc);
+ }
+ }
+
+ bool set_default_formats() {
+ using namespace format_tag;
+ return set_default_formats_common(nChw16c, any, nChw16c);
+ }
+ };
+
+ jit_avx512_core_fp32_wino_conv_2x3_fwd_t(const pd_t *apd);
+ ~jit_avx512_core_fp32_wino_conv_2x3_fwd_t();
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto src = CTX_IN_MEM(const float *, MKLDNN_ARG_SRC);
+ auto wei = CTX_IN_MEM(const float *, MKLDNN_ARG_WEIGHTS);
+ auto bia = CTX_IN_MEM(const float *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(float *, MKLDNN_ARG_DST);
+
+ if (pd()->jcp_.small_mb)
+ execute_forward_small_mb(src, wei, bia, dst, this->scratchpad(ctx));
+ else
+ execute_forward_mbN(src, wei, bia, dst, this->scratchpad(ctx));
+
+ return status::success;
+ }
+
+private:
+ void execute_forward_small_mb(const float *src, const float *wei,
+ const float *bia, float *dst,
+ const memory_tracking::grantor_t &scratchpad) const;
+ void execute_forward_mbN(const float *src, const float *wei,
+ const float *bia, float *dst,
+ const memory_tracking::grantor_t &scratchpad) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx512_core_fp32_wino_conv_2x3_fwd_ker_t *kernel_;
+ jit_avx512_core_fp32_wino_conv_2x3_src_trans_t *src_trans_;
+ jit_avx512_core_fp32_wino_conv_2x3_dst_trans_t *dst_trans_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.cpp
new file mode 100644
index 0000000000..96325e3ade
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.cpp
@@ -0,0 +1,1020 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifdef __INTEL_COMPILER
+#include <immintrin.h>
+#endif
+
+#include "mkldnn_types.h"
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_avx512_core_fp32_wino_conv_4x3.hpp"
+
+#ifndef _MSC_VER
+#define pragma_unroll _Pragma("unroll")
+#else
+#define pragma_unroll
+#endif
+
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+template <bool is_fwd>
+void _jit_avx512_core_fp32_wino_conv_4x3_t<is_fwd>
+::weight_transform_data(const jit_conv_winograd_conf_t &jcp,
+ float *wp, float *twp) const
+{
+ float G[] = {0.26890756302521f, 0.688403361344538f, 0.119514472455649f,
+ 1.13777777777778f, 0.430252100840336f, 0.179271708683473f};
+ const int kh = 3;
+ const int kw = 3;
+ float Fw[alpha][alpha][simd_w][simd_w];
+ float F[kh][kw][simd_w][simd_w];
+ float T[alpha][3][simd_w];
+ auto p = jit_wino_transform_call_s();
+
+ p.src = wp;
+ p.dst = twp;
+ p.G = G;
+ p.M = F;
+ p.Mw = Fw;
+ p.T = T;
+
+ kernel_->weights_transform_data_ker(&p);
+}
+
+template<bool is_fwd>
+void _jit_avx512_core_fp32_wino_conv_4x3_t<is_fwd>::output_transform_data
+(int image, const jit_conv_winograd_conf_t &jcp,
+ const post_ops_t &p_ops, float *toutp, float *pout_b, float *bias) const {
+
+ float G[] = {0.625f, 1.5f, 0.390625f, 2.25f, 0.244140625f, 3.375f};
+ float Ow[alpha][alpha][simd_w];
+ float O[tile_size][tile_size][simd_w];
+ float T[tile_size][alpha][simd_w];
+
+ auto p = jit_wino_transform_call_s();
+ p.src = toutp;
+ p.dst = pout_b;
+ p.G = G;
+ p.M = O;
+ p.Mw = Ow;
+ p.T = T;
+ p.bias = bias;
+
+ int tile_base_index = image * jcp.itiles * jcp.jtiles;
+ int tile_block_ur = tile_base_index % jcp.tile_block_ur;
+ int nb_tile_block_ur =
+ (tile_base_index / jcp.tile_block_ur) % jcp.nb_tile_block_ur;
+ int tile_block =
+ (tile_base_index / jcp.tile_block_ur) / jcp.nb_tile_block_ur;
+
+ for (int tj = 0; tj < jcp.jtiles; tj++) {
+ for (int ti = 0; ti < jcp.itiles; ti++) {
+
+ p.tile_block_ur = tile_block_ur;
+ p.nb_tile_block_ur = nb_tile_block_ur;
+ p.tile_block = tile_block;
+ p.tj = tj;
+ p.ti = ti;
+
+ kernel_->output_transform_data_ker(&p);
+
+ tile_block_ur++;
+ if (tile_block_ur >= jcp.tile_block_ur) {
+ tile_block_ur = 0;
+ nb_tile_block_ur++;
+ }
+ if (nb_tile_block_ur >= jcp.nb_tile_block_ur) {
+ nb_tile_block_ur = 0;
+ tile_block++;
+ }
+ }
+ }
+}
+
+template<bool is_fwd>
+void _jit_avx512_core_fp32_wino_conv_4x3_t<is_fwd>
+::output_transform_tileblock_data(int tile_block,
+ const jit_conv_winograd_conf_t &jcp, const post_ops_t &p_ops,
+ float *toutp, float *outp, float *bias) const {
+
+ float G[] = {0.625f, 1.5f, 0.390625f, 2.25f, 0.244140625f, 3.375f};
+ float Ow[alpha][alpha][simd_w];
+ float O[tile_size][tile_size][simd_w];
+ float T[tile_size][alpha][simd_w];
+
+ auto p = jit_wino_transform_call_s();
+ p.src = toutp;
+ p.dst = outp;
+ p.G = G;
+ p.M = O;
+ p.Mw = Ow;
+ p.T = T;
+ p.bias = bias;
+
+ int outw = is_fwd ? jcp.ow : jcp.iw;
+ int outh = is_fwd ? jcp.oh : jcp.ih;
+
+ int tile_index = tile_block * jcp.nb_tile_block_ur * jcp.tile_block_ur;
+
+ for (int nb_tile_block_ur = 0;
+ nb_tile_block_ur < jcp.nb_tile_block_ur;
+ nb_tile_block_ur++) {
+
+ for (int tile_block_ur = 0; tile_block_ur < jcp.tile_block_ur;
+ tile_block_ur++) {
+ int img = tile_index / (jcp.jtiles * jcp.itiles);
+ int ti = tile_index % jcp.itiles;
+ int tj = (tile_index / jcp.itiles) % jcp.jtiles;
+
+ p.tile_block_ur = tile_block_ur;
+ p.nb_tile_block_ur = nb_tile_block_ur;
+ p.tile_block = tile_block;
+ p.tj = tj;
+ p.ti = ti;
+ p.dst = outp + img * (jcp.dimM / jcp.dimM_simd_block)
+ * outh * outw * jcp.dimM_simd_block;
+
+ kernel_->output_transform_data_ker(&p);
+
+ tile_index++;
+ }
+ }
+}
+
+
+template<bool is_fwd>
+void _jit_avx512_core_fp32_wino_conv_4x3_t<is_fwd>
+ ::input_transform_data(int image, const jit_conv_winograd_conf_t &jcp,
+ float *inp, float *tinp) const
+{
+ float G[] = {-2.25f, -0.390625f, 0.87890625f, -2.640625f,
+ 0.625f, -0.625f, 1.5f, -1.5f, -2.640625f};
+
+ float Iw[alpha][alpha][simd_w];
+ float I[alpha][alpha][simd_w];
+ float T[alpha][alpha][simd_w];
+
+ auto p = jit_wino_transform_call_s();
+
+ p.src = inp;
+ p.dst = tinp;
+ p.G = G;
+ p.M = I;
+ p.Mw = Iw;
+ p.T = T;
+
+ int tile_base_index = image * jcp.itiles * jcp.jtiles;
+ int tile_block_ur = tile_base_index % jcp.tile_block_ur;
+ int nb_tile_block_ur =
+ (tile_base_index / jcp.tile_block_ur) % jcp.nb_tile_block_ur;
+ int tile_block =
+ (tile_base_index / jcp.tile_block_ur) / jcp.nb_tile_block_ur;
+
+ for (int tj = 0; tj < jcp.jtiles; tj++) {
+ for (int ti = 0; ti < jcp.itiles; ti++) {
+
+ p.tile_block_ur = tile_block_ur;
+ p.nb_tile_block_ur = nb_tile_block_ur;
+ p.tile_block = tile_block;
+ p.tj = tj;
+ p.ti = ti;
+
+ kernel_->input_transform_data_ker(&p);
+
+ tile_block_ur++;
+ if (tile_block_ur >= jcp.tile_block_ur) {
+ tile_block_ur = 0;
+ nb_tile_block_ur++;
+ }
+ if (nb_tile_block_ur >= jcp.nb_tile_block_ur) {
+ nb_tile_block_ur = 0;
+ tile_block++;
+ }
+ }
+ }
+}
+
+template <bool is_fwd>
+void _jit_avx512_core_fp32_wino_conv_4x3_t<is_fwd>
+ ::input_transform_tileblock_data(int tile_block,
+ const jit_conv_winograd_conf_t &jcp,
+ float *inp, float *tinp) const
+{
+ float G[] = {-2.25f, -0.390625f, 0.87890625f, -2.640625f,
+ 0.625f, -0.625f, 1.5f, -1.5f, -2.640625f};
+ float Iw[alpha][alpha][simd_w];
+ float I[alpha][alpha][simd_w];
+ float T[alpha][alpha][simd_w];
+
+ const int inph = is_fwd ? jcp.ih : jcp.oh;
+ const int inpw = is_fwd ? jcp.iw : jcp.ow;
+
+ array_offset_calculator<float, 5> input(inp,
+ jcp.mb, jcp.dimK / simd_w, inph, inpw, simd_w);
+ array_offset_calculator<float, 7> output(tinp,
+ alpha, alpha,
+ jcp.dimN_block, jcp.dimK_nb_block, jcp.dimK_block,
+ jcp.dimN_reg_block, jcp.dimK_reg_block);
+
+ auto p = jit_wino_transform_call_s();
+
+ p.dst = tinp;
+ p.G = G;
+ p.M = I;
+ p.Mw = Iw;
+ p.T = T;
+
+
+ int tile_index = tile_block * jcp.nb_tile_block_ur * jcp.tile_block_ur;
+
+ for (int nb_tile_block_ur = 0;
+ nb_tile_block_ur < jcp.nb_tile_block_ur;
+ nb_tile_block_ur++) {
+
+ for (int tile_block_ur = 0; tile_block_ur < jcp.tile_block_ur;
+ tile_block_ur++) {
+
+ int img = tile_index / (jcp.jtiles * jcp.itiles);
+ int ti = tile_index % jcp.itiles;
+ int tj = (tile_index / jcp.itiles) % jcp.jtiles;
+ float *pinp_b = &(input(img, 0, 0, 0, 0));
+
+ p.src = pinp_b;
+ p.tile_block_ur = tile_block_ur;
+ p.nb_tile_block_ur = nb_tile_block_ur;
+ p.tj = tj;
+ p.ti = ti;
+
+ kernel_->input_transform_data_ker(&p);
+
+ tile_index++;
+ }
+ }
+}
+
+template <bool is_fwd>
+void _jit_avx512_core_fp32_wino_conv_4x3_t<is_fwd>::_execute_data_W_S_G_D(
+ float *inp_ptr, float *out_ptr, float *wei_ptr, float *bias_ptr,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const auto &jcp = kernel_->jcp;
+ const auto &p_ops = attr_->post_ops_;
+
+ const int inph = is_fwd ? jcp.ih : jcp.oh;
+ const int inpw = is_fwd ? jcp.iw : jcp.ow;
+ const int outh = is_fwd ? jcp.oh : jcp.ih;
+ const int outw = is_fwd ? jcp.ow : jcp.iw;
+
+ /* Notation:
+ FWD: dimM:oc, dimN:ntiles, dimK:ic,
+ BWD: dimM:ic, dimN:ntiles, dimK:oc,
+ FWD/BWD: V: src/diff_dst transform, U:weight transform,
+ M:dst/diff_src transform */
+ array_offset_calculator<float, 5> input(inp_ptr,
+ jcp.mb, jcp.dimK/jcp.dimK_reg_block, inph, inpw,
+ jcp.dimK_reg_block);
+ array_offset_calculator<float, 5> output(out_ptr,
+ jcp.mb, jcp.dimM/jcp.dimM_simd_block, outh, outw,
+ jcp.dimM_simd_block);
+ array_offset_calculator<float, 6> weights(wei_ptr,
+ jcp.oc/jcp.oc_simd_block, jcp.ic/jcp.ic_simd_block, jcp.kh, jcp.kw,
+ jcp.ic_simd_block, jcp.oc_simd_block);
+ array_offset_calculator<float, 2> bias(bias_ptr,
+ jcp.dimM/jcp.dimM_simd_block, jcp.dimM_simd_block);
+
+ array_offset_calculator<float, 8> M(is_fwd
+ ? scratchpad.template get<float>(key_wino_M)
+ : scratchpad.template get<float>(key_wino_V),
+ jcp.dimN_nb_block, jcp.dimM_nb_block,
+ alpha, alpha,
+ jcp.dimN_block, jcp.dimM_block * jcp.dimM_reg_block,
+ jcp.dimN_reg_block, jcp.dimM_simd_block);
+
+ auto wino_wei = (jcp.prop_kind == prop_kind::forward_inference)
+ ? wei_ptr
+ : scratchpad.template get<float>(key_wino_U);
+
+ array_offset_calculator<float, 8> U(wino_wei,
+ jcp.dimM_nb_block,
+ alpha, alpha,
+ jcp.dimK_nb_block,
+ jcp.dimM_block * jcp.dimM_reg_block, jcp.dimK_block,
+ jcp.dimK_reg_block, jcp.dimM_simd_block);
+ array_offset_calculator<float, 8> V(is_fwd
+ ? scratchpad.template get<float>(key_wino_V)
+ : scratchpad.template get<float>(key_wino_M),
+ jcp.dimN_nb_block, alpha, alpha,
+ jcp.dimN_block, jcp.dimK_nb_block,
+ jcp.dimK_block, jcp.dimN_reg_block, jcp.dimK_reg_block);
+
+ const bool wants_padded_bias = jcp.with_bias
+ && jcp.oc_without_padding != jcp.oc;
+ float last_slice_bias[simd_w] = {0};
+ if (wants_padded_bias) {
+ for (int oc = 0; oc < jcp.oc_without_padding % jcp.oc_simd_block; ++oc)
+ last_slice_bias[oc] = bias(jcp.dimM / jcp.dimM_simd_block - 1, oc);
+ }
+
+ {
+
+ parallel_nd(jcp.mb, jcp.dimK_nb_block, jcp.dimK_block,
+ [&](int img, int K_blk1, int K_blk2) {
+ input_transform_data(img, jcp,
+ &(input(img, K_blk1 * jcp.dimK_block + K_blk2,
+ 0, 0, 0)),
+ &(V(0, 0, 0, 0, K_blk1, K_blk2, 0, 0)));
+ });
+
+ if (jcp.prop_kind != prop_kind::forward_inference) {
+ parallel_nd(jcp.nb_oc, jcp.nb_ic, (jcp.oc_block * jcp.oc_reg_block),
+ (jcp.ic_block * jcp.ic_reg_block),
+ [&](int ofm1, int ifm1, int ofm2, int ifm2) {
+ float *U_base_ptr = is_fwd
+ ? &(U(ofm1, 0, 0, ifm1, ofm2, ifm2, 0, 0))
+ : &(U(ifm1, 0, 0, ofm1, ifm2, ofm2, 0, 0));
+ weight_transform_data(jcp,
+ &(weights(
+ ofm1 * jcp.oc_block * jcp.oc_reg_block + ofm2,
+ ifm1 * jcp.ic_block * jcp.ic_reg_block + ifm2,
+ 0, 0, 0, 0)),
+ U_base_ptr);
+ });
+ }
+
+ parallel_nd(jcp.dimN_nb_block, alpha, alpha, jcp.dimM_nb_block,
+ [&](int N_blk1, int oj, int oi, int M_blk1) {
+ for (int K_blk1 = 0; K_blk1 < jcp.dimK_nb_block;
+ K_blk1++)
+ for (int N_blk2 = 0; N_blk2 < jcp.dimN_block; N_blk2++)
+ kernel_->gemm_loop_ker(
+ (float *)&(M(N_blk1, M_blk1, oj, oi,
+ N_blk2, 0, 0, 0)),
+ (const float *)&(U(M_blk1, oj, oi,
+ K_blk1, 0, 0, 0, 0)),
+ (const float *)&(V(N_blk1, oj, oi,
+ N_blk2, K_blk1, 0, 0, 0)), K_blk1);
+ });
+
+ parallel_nd(jcp.mb, jcp.dimM_nb_block, (jcp.dimM_block * jcp.dimM_reg_block),
+ [&](int img, int M_blk1, int M_blk2) {
+ const int M_blk =
+ M_blk1 * jcp.dimM_block * jcp.dimM_reg_block + M_blk2;
+
+ float *bias_ptr = wants_padded_bias
+ && M_blk == jcp.dimM / jcp.dimM_simd_block - 1
+ ? last_slice_bias : &bias(M_blk, 0);
+ output_transform_data(img, jcp, p_ops,
+ &(M(0, M_blk1, 0, 0, 0, M_blk2, 0, 0)),
+ &(output(img, M_blk, 0, 0, 0)), bias_ptr);
+ });
+
+ }
+}
+
+template <bool is_fwd>
+void _jit_avx512_core_fp32_wino_conv_4x3_t<is_fwd>::_execute_data_W_SGD(
+ float *inp_ptr, float *out_ptr, float *wei_ptr, float *bias_ptr,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const auto &jcp = kernel_->jcp;
+ const auto &p_ops = attr_->post_ops_;
+
+ const int inph = is_fwd ? jcp.ih : jcp.oh;
+ const int inpw = is_fwd ? jcp.iw : jcp.ow;
+ const int outh = is_fwd ? jcp.oh : jcp.ih;
+ const int outw = is_fwd ? jcp.ow : jcp.iw;
+
+ array_offset_calculator<float, 5> input(inp_ptr,
+ jcp.mb, jcp.dimK/jcp.dimK_reg_block, inph, inpw, jcp.dimK_reg_block);
+ array_offset_calculator<float, 5> output(out_ptr,
+ jcp.mb, jcp.dimM/jcp.dimM_simd_block, outh, outw, jcp.dimM_simd_block);
+ array_offset_calculator<float, 6> weights(wei_ptr,
+ jcp.oc/jcp.oc_simd_block, jcp.ic/jcp.ic_simd_block, jcp.kh, jcp.kw,
+ jcp.ic_simd_block, jcp.oc_simd_block);
+ array_offset_calculator<float, 2> bias(bias_ptr,
+ jcp.oc/jcp.oc_simd_block, jcp.oc_simd_block);
+
+ auto wino_wei = (jcp.prop_kind == prop_kind::forward_inference)
+ ? wei_ptr
+ : scratchpad.template get<float>(key_wino_U);
+
+ array_offset_calculator<float, 8> U(wino_wei,
+ jcp.dimM_nb_block,
+ alpha, alpha,
+ jcp.dimK_nb_block,
+ jcp.dimM_block * jcp.dimM_reg_block, jcp.dimK_block,
+ jcp.dimK_reg_block, jcp.dimM_simd_block);
+
+ array_offset_calculator<float, 8> M(is_fwd
+ ? scratchpad.template get<float>(key_wino_M)
+ : scratchpad.template get<float>(key_wino_V),
+ 0, jcp.dimM_nb_block, alpha, alpha,
+ jcp.dimN_block, jcp.dimM_block * jcp.dimM_reg_block,
+ jcp.dimN_reg_block, jcp.dimM_simd_block);
+ array_offset_calculator<float, 8> V(is_fwd
+ ? scratchpad.template get<float>(key_wino_V)
+ : scratchpad.template get<float>(key_wino_M),
+ 0, alpha, alpha, jcp.dimN_block,
+ jcp.dimK_nb_block, jcp.dimK_block,
+ jcp.dimN_reg_block, jcp.dimK_reg_block);
+
+ const bool wants_padded_bias = jcp.with_bias
+ && jcp.oc_without_padding != jcp.oc;
+ float last_slice_bias[simd_w] = {0};
+ if (wants_padded_bias) {
+ for (int oc = 0; oc < jcp.oc_without_padding % jcp.oc_simd_block; ++oc)
+ last_slice_bias[oc] = bias(jcp.dimM / jcp.dimM_simd_block - 1, oc);
+ }
+
+ if (jcp.prop_kind != prop_kind::forward_inference) {
+
+ parallel_nd(jcp.nb_oc, jcp.nb_ic, (jcp.oc_block * jcp.oc_reg_block), (jcp.ic_block * jcp.ic_reg_block),
+ [&](int ofm1, int ifm1, int ofm2, int ifm2) {
+ float *U_base_ptr = is_fwd
+ ? &(U(ofm1, 0, 0, ifm1, ofm2, ifm2, 0, 0))
+ : &(U(ifm1, 0, 0, ofm1, ifm2, ofm2, 0, 0));
+ weight_transform_data(jcp,
+ &(weights(
+ ofm1 * jcp.oc_block * jcp.oc_reg_block + ofm2,
+ ifm1 * jcp.ic_block * jcp.ic_reg_block + ifm2,
+ 0, 0, 0, 0)),
+ U_base_ptr);
+ });
+ }
+
+ parallel_nd(jcp.tile_block, [&](int tile_block) {
+ int ithr = mkldnn_get_thread_num();
+
+ for (int K_blk1 = 0; K_blk1 < jcp.dimK_nb_block; K_blk1++) {
+ for (int K_blk2 = 0; K_blk2 < jcp.dimK_block; K_blk2++) {
+
+ input_transform_tileblock_data(
+ tile_block, jcp,
+ &(input(0, K_blk1 * jcp.dimK_block + K_blk2, 0, 0, 0)),
+ &(V(ithr, 0, 0, 0, K_blk1, K_blk2, 0, 0)));
+ }
+ }
+
+ for (int oj = 0; oj < alpha; oj++) {
+ for (int oi = 0; oi < alpha; oi++) {
+ for (int M_blk1 = 0; M_blk1 < jcp.dimM_nb_block; M_blk1++)
+ for (int K_blk1 = 0; K_blk1 < jcp.dimK_nb_block; K_blk1++)
+ for (int N_blk = 0; N_blk < jcp.dimN_block; N_blk++)
+ kernel_->gemm_loop_ker(
+ (float *)&(M(ithr, M_blk1, oj, oi,
+ N_blk, 0, 0, 0)),
+ (const float *)&(U(M_blk1, oj, oi, K_blk1,
+ 0, 0, 0, 0)),
+ (const float *)&(V(ithr, oj, oi,
+ N_blk, K_blk1, 0, 0, 0)), K_blk1);
+ }
+ }
+
+ for (int M_blk1 = 0; M_blk1 < jcp.dimM_nb_block; M_blk1++) {
+ for (int M_blk2 = 0; M_blk2 < jcp.dimM_block * jcp.dimM_reg_block;
+ M_blk2++) {
+ const int M_blk =
+ M_blk1 * jcp.dimM_block * jcp.dimM_reg_block + M_blk2;
+
+ float *bias_ptr = wants_padded_bias
+ && M_blk == jcp.dimM / jcp.dimM_simd_block - 1
+ ? last_slice_bias : &bias(M_blk, 0);
+
+ output_transform_tileblock_data(tile_block, jcp, p_ops,
+ &(M(ithr, M_blk1, 0, 0, 0, M_blk2, 0, 0)),
+ &(output(0, M_blk, 0, 0, 0)), bias_ptr);
+ }
+ }
+ });
+}
+
+template struct _jit_avx512_core_fp32_wino_conv_4x3_t<true>;
+template struct _jit_avx512_core_fp32_wino_conv_4x3_t<false>;
+
+namespace {
+
+void subarray_sum(size_t num_arrs, float *output, size_t nelems,
+ float *input_ptrs[], size_t input_starts[], size_t input_ends[]) {
+ using namespace nstl;
+ const size_t block_size = 16 * 1024 / sizeof(float);
+ const size_t blocks_number = nelems / block_size;
+ const size_t tail = nelems % block_size;
+
+PRAGMA_OMP(parallel)
+ {
+ const int ithr = mkldnn_get_thread_num();
+ const int nthr = mkldnn_get_num_threads();
+ size_t start{ 0 }, end{ 0 };
+ balance211(blocks_number, nthr, ithr, start, end);
+
+ for (size_t nb = start; nb < end; ++nb) {
+ size_t start_e = nb * block_size;
+ size_t end_e = start_e + block_size;
+ size_t input_start = max(start_e, min(input_starts[0], end_e));
+ size_t input_end = max(start_e, min(input_ends[0], end_e));
+
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start_e; e < input_start; e++) {
+ output[e] = 0.f;
+ }
+
+ PRAGMA_OMP_SIMD()
+ for (size_t e = input_start; e < input_end; e++) {
+ output[e] = input_ptrs[0][e];
+ }
+
+ PRAGMA_OMP_SIMD()
+ for (size_t e = input_end; e < end_e; e++) {
+ output[e] = 0.f;
+ }
+
+ for (size_t a = 1; a < num_arrs; a++) {
+ input_start = max(start_e, input_starts[a]);
+ input_end = min(input_ends[a], end_e);
+
+ PRAGMA_OMP_SIMD()
+ for (size_t e = input_start; e < input_end; e++) {
+ output[e] += input_ptrs[a][e];
+ }
+ }
+ }
+
+ if (tail != 0 && ithr == nthr - 1) {
+ size_t start_e = nelems - tail;
+ size_t end_e = nelems;
+ size_t input_start = max(start_e, min(input_starts[0], end_e));
+ size_t input_end = max(start_e, min(input_ends[0], end_e));
+
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start_e; e < input_start; e++) {
+ output[e] = 0.f;
+ }
+
+ PRAGMA_OMP_SIMD()
+ for (size_t e = input_start; e < input_end; e++) {
+ output[e] = input_ptrs[0][e];
+ }
+
+ PRAGMA_OMP_SIMD()
+ for (size_t e = input_end; e < end_e; e++) {
+ output[e] = 0.f;
+ }
+
+ for (size_t a = 1; a < num_arrs; a++) {
+ input_start = max(start_e, input_starts[a]);
+ input_end = min(input_ends[a], end_e);
+
+ PRAGMA_OMP_SIMD()
+ for (size_t e = input_start; e < input_end; e++) {
+ output[e] += input_ptrs[a][e];
+ }
+ }
+ }
+ }
+}
+
+const int max_threads_number = 1024;
+
+// Sum to the first buffer array
+void array_sum(size_t num_arrs, float *output,
+ size_t nelems, float *input_ptrs[], bool reduce_to_first = true) {
+ const size_t block_size = 16 * 1024 / sizeof(float);
+ const size_t blocks_number = nelems / block_size;
+ const size_t tail = nelems % block_size;
+
+PRAGMA_OMP(parallel)
+ {
+ const size_t ithr = mkldnn_get_thread_num();
+ const size_t nthr = mkldnn_get_num_threads();
+ size_t start{ 0 }, end{ 0 };
+ balance211(blocks_number, nthr, ithr, start, end);
+
+ for (size_t nb = start; nb < end; ++nb) {
+ size_t start_e = nb * block_size;
+ size_t end_e = start_e + block_size;
+ if (!reduce_to_first) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start_e; e < end_e; e++) {
+ output[e] = input_ptrs[0][e];
+ }
+ }
+ for (size_t a = 1; a < num_arrs; a++) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start_e; e < end_e; e++) {
+ output[e] += input_ptrs[a][e];
+ }
+ }
+ }
+
+ if (tail != 0 && ithr == nthr - 1) {
+ size_t start_e = nelems - tail;
+ size_t end_e = nelems;
+ if (!reduce_to_first) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start_e; e < end_e; e++) {
+ output[e] = input_ptrs[0][e];
+ }
+ }
+ for (size_t a = 1; a < num_arrs; a++) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start_e; e < end_e; e++) {
+ output[e] += input_ptrs[a][e];
+ }
+ }
+ }
+ }
+}
+} //bwdw namespace
+
+void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t::
+_execute_backward_weights_SDGtWo(const float *ptr_src,
+ const float *ptr_diff_dst, float *ptr_diff_weights,
+ float *ptr_diff_bias,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const auto &jcp = kernel_->jcp;
+ const int nthreads = jcp.nthr;
+
+ array_offset_calculator<float, 5> src((float *)ptr_src,
+ jcp.mb, jcp.ic / simd_w, jcp.ih, jcp.iw, simd_w);
+ array_offset_calculator<float, 5> diff_dst((float *)ptr_diff_dst,
+ jcp.mb, jcp.oc / simd_w, jcp.oh, jcp.ow, simd_w);
+ array_offset_calculator<float, 6> diff_weights(ptr_diff_weights,
+ jcp.oc / simd_w, jcp.ic / simd_w, jcp.kh, jcp.kw, simd_w, simd_w);
+
+ array_offset_calculator<float, 8> Us(scratchpad.get<float>(key_wino_U),
+ 0, alpha, alpha,
+ jcp.oc_block, jcp.ic_block,
+ jcp.ic_simd_block,
+ jcp.oc_reg_block,
+ jcp.oc_simd_block);
+
+ const int U_sz = nthreads * alpha * alpha * jcp.oc / jcp.nb_oc
+ * jcp.ic / jcp.nb_ic;
+ array_offset_calculator<float, 7>diff_weights_prv(
+ scratchpad.get<float>(key_wino_U) + U_sz,
+ 0, jcp.oc / simd_w, jcp.ic / simd_w, jcp.kh, jcp.kw, simd_w, simd_w);
+
+ array_offset_calculator<float, 8> M(scratchpad.get<float>(key_wino_M),
+ 0, alpha, alpha,
+ jcp.oc_block,
+ jcp.nb_tile_block_ur,
+ jcp.tile_block_ur,
+ jcp.oc_reg_block,
+ jcp.oc_simd_block);
+
+ array_offset_calculator<float, 7> V(scratchpad.get<float>(key_wino_V),
+ 0, alpha, alpha,
+ jcp.ic_block,
+ jcp.nb_tile_block_ur,
+ jcp.tile_block_ur,
+ jcp.ic_simd_block);
+
+ array_offset_calculator<float, 2> diff_bias_prv(
+ scratchpad.get<float>(key_conv_bia_reduction), nthreads, jcp.oc);
+
+ auto trans_ker_p = jit_wino_transform_call_s();
+ float I[alpha][alpha][simd_w];
+ float T[alpha][alpha][simd_w];
+ float G_I_3x3_4x4[9] = {-2.25f, -0.390625f, 0.87890625f, -2.640625f,
+ 0.625f, -0.625f, 1.5f, -1.5f, -2.640625f};
+ float G_W_3x3_4x4[8] = {0.26890756302521f, -0.688403361344538f, 0.119514472455649f,
+ 0.430252100840336f, 0.168067226890756f, 0.179271708683473f, 0.403361344537815f,
+ 1.13777777777778f};
+ float G_O_3x3_4x4[4] = {2.25f, 0.625f, 1.5f, 0.390625f};
+
+PRAGMA_OMP(parallel num_threads(nthreads) firstprivate(trans_ker_p, I, T))
+{
+ if (jcp.with_bias) {
+ parallel_nd_in_omp(nthreads, jcp.oc / simd_w,
+ [&](int ithr, int ofm){
+ float *pdbias = &(diff_bias_prv(ithr, ofm * simd_w));
+ PRAGMA_OMP_SIMD()
+ for (int v = 0; v < simd_w; v++) {
+ pdbias[v] = 0.0f;
+ }
+ });
+ }
+
+ int ithr = mkldnn_get_thread_num();
+ for (int ifm1 = 0; ifm1 < jcp.nb_ic; ++ifm1) {
+ int first_tblk = 0;
+PRAGMA_OMP(for)
+ for (int tblk1 = 0; tblk1 < jcp.tile_block; ++tblk1) {
+ int tile_index = tblk1 * jcp.nb_tile_block_ur * jcp.tile_block_ur;
+ int img = tile_index / (jcp.itiles * jcp.jtiles);
+ trans_ker_p.ti = tile_index % jcp.itiles;
+ trans_ker_p.tj = (tile_index / jcp.itiles) % jcp.jtiles;
+ trans_ker_p.M = I;
+ trans_ker_p.T = T;
+ trans_ker_p.G = G_I_3x3_4x4;
+ for (int ifm2 = 0; ifm2 < jcp.ic_block; ++ifm2) {
+ int ifm = ifm1 * jcp.ic_block + ifm2;
+ trans_ker_p.src = (float *)&(src(img, ifm, 0, 0, 0));
+ trans_ker_p.dst = (float *)&(V(ithr, 0, 0, ifm2, 0, 0, 0));
+ kernel_->src_transform(&trans_ker_p);
+ }
+
+ for (int ofm1 = 0; ofm1 < jcp.nb_oc; ++ofm1) {
+ trans_ker_p.G = G_W_3x3_4x4;
+ for (int ofm2 = 0; ofm2 < jcp.oc_block; ++ofm2) {
+ int ofm = (ofm1 * jcp.oc_block + ofm2) * jcp.oc_reg_block;
+ trans_ker_p.src = (float *)&(diff_dst(img, ofm, 0, 0, 0));
+ trans_ker_p.dst = (float *)&(M(ithr, 0, 0, ofm2, 0, 0, 0, 0));
+ if (jcp.with_bias && ifm1 == 0) {
+ trans_ker_p.bias = (float *)&(diff_bias_prv(ithr, ofm * simd_w));
+ kernel_->diff_dst_transform_wbias(&trans_ker_p);
+ } else {
+ kernel_->diff_dst_transform(&trans_ker_p);
+ }
+ }
+
+ for (int oj = 0; oj < alpha; ++oj) {
+ for (int oi = 0; oi < alpha; ++oi) {
+ kernel_->gemm_loop_ker_first_iter(
+ &(Us(ithr, oj, oi, 0, 0, 0, 0, 0)),
+ &(M(ithr, oj, oi, 0, 0, 0, 0, 0)),
+ &(V(ithr, oj, oi, 0, 0, 0, 0)));
+ }
+ }
+ trans_ker_p.G = G_O_3x3_4x4;
+ for (int ofm2 = 0; ofm2 < jcp.oc_block; ++ofm2) {
+ for (int ofm3 = 0; ofm3 < jcp.oc_reg_block; ++ofm3) {
+ int ofm = (ofm1 * jcp.oc_block + ofm2) * jcp.oc_reg_block
+ + ofm3;
+ for (int ifm2 = 0; ifm2 < jcp.ic_block; ++ifm2) {
+ int ifm = ifm1 * jcp.ic_block + ifm2;
+ trans_ker_p.src = (float *)&(Us(ithr, 0, 0,
+ ofm2, ifm2, 0, ofm3, 0));
+ trans_ker_p.dst = (float *)&(diff_weights_prv(ithr,
+ ofm, ifm, 0, 0, 0, 0));
+ if (first_tblk == 0) {
+ kernel_->diff_weights_transform(&trans_ker_p);
+ } else {
+ kernel_->diff_weights_transform_accum(&trans_ker_p);
+ }
+ }
+ }
+ }
+ }
+ ++first_tblk;
+ }
+ }
+}
+
+ // Reduce diff-weights
+ {
+ float *output = ptr_diff_weights;
+ float *input_base = scratchpad.get<float>(key_wino_U) + U_sz;
+ int nelems = jcp.oc * jcp.ic * jcp.kh * jcp.kw;
+ float *input_ptrs[max_threads_number];
+ for (int i = 0; i < nthreads; ++i) {
+ input_ptrs[i] = input_base + nelems * i;
+ }
+ array_sum(nthreads, output, nelems, input_ptrs, false);
+
+ if (jcp.with_bias) {
+ output = ptr_diff_bias;
+ input_base = scratchpad.get<float>(key_conv_bia_reduction);
+ for (int i = 0; i < nthreads; ++i) {
+ input_ptrs[i] = input_base + jcp.oc * i;
+ }
+ array_sum(nthreads, output, jcp.oc_without_padding, input_ptrs,
+ false);
+ }
+ }
+}
+
+void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t::
+_execute_backward_weights_S_D_Giot_W(const float *ptr_src,
+ const float *ptr_diff_dst, float *ptr_diff_weights,
+ float *ptr_diff_bias,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const auto &jcp = kernel_->jcp;
+ const int nthreads = jcp.nthr;
+
+ array_offset_calculator<float, 5> src((float *)ptr_src,
+ jcp.mb, jcp.ic / simd_w, jcp.ih, jcp.iw, simd_w);
+ array_offset_calculator<float, 5> diff_dst((float *)ptr_diff_dst,
+ jcp.mb, jcp.oc / simd_w, jcp.oh, jcp.ow, simd_w);
+ array_offset_calculator<float, 6> diff_weights((float *)ptr_diff_weights,
+ jcp.oc / simd_w, jcp.ic / simd_w, jcp.kh, jcp.kw, simd_w, simd_w);
+ array_offset_calculator<float, 1> diff_bias((float *)ptr_diff_bias, jcp.oc);
+
+ array_offset_calculator<float, 9> U(scratchpad.get<float>(key_wino_U),
+ jcp.nb_ic, jcp.nb_oc,
+ alpha, alpha,
+ jcp.oc_block, jcp.ic_block,
+ jcp.ic_simd_block,
+ jcp.oc_reg_block,
+ jcp.oc_simd_block);
+
+ const int U_size = jcp.oc * jcp.ic * alpha * alpha;
+ array_offset_calculator<float, 10> Us(
+ scratchpad.get<float>(key_wino_U) + U_size,
+ 0, jcp.nb_ic, jcp.nb_oc,
+ alpha, alpha,
+ jcp.oc_block, jcp.ic_block,
+ jcp.ic_simd_block,
+ jcp.oc_reg_block,
+ jcp.oc_simd_block);
+
+ array_offset_calculator<float, 9> M(scratchpad.get<float>(key_wino_M),
+ jcp.nb_oc,
+ jcp.tile_block,
+ alpha, alpha,
+ jcp.oc_block,
+ jcp.nb_tile_block_ur,
+ jcp.tile_block_ur ,
+ jcp.oc_reg_block,
+ jcp.oc_simd_block);
+
+ array_offset_calculator<float, 8> V(scratchpad.get<float>(key_wino_V),
+ jcp.nb_ic,
+ jcp.tile_block,
+ alpha, alpha,
+ jcp.ic_block,
+ jcp.nb_tile_block_ur, jcp.tile_block_ur,
+ jcp.ic_simd_block);
+
+ array_offset_calculator<float, 2> diff_bias_prv(
+ scratchpad.get<float>(key_conv_bia_reduction), nthreads, jcp.oc);
+
+ size_t input_starts[max_threads_number] = {0};
+ size_t input_ends[max_threads_number] = {0};
+ size_t first_tblk = 0;
+
+ auto trans_ker_p = jit_wino_transform_call_s();
+ float G_I_3x3_4x4[9] = {-2.25f, -0.390625f, 0.87890625f, -2.640625f,
+ 0.625f, -0.625f, 1.5f, -1.5f, -2.640625f};
+ float G_W_3x3_4x4[8] = {0.26890756302521f, -0.688403361344538f,
+ 0.119514472455649f, 0.430252100840336f, 0.168067226890756f,
+ 0.179271708683473f, 0.403361344537815f, 1.13777777777778f};
+ float G_O_3x3_4x4[4] = {2.25f, 0.625f, 1.5f, 0.390625f};
+ float I[alpha][alpha][simd_w];
+ float T[alpha][alpha][simd_w];
+
+PRAGMA_OMP(parallel firstprivate(first_tblk, trans_ker_p, I, T))
+{
+ if (jcp.with_bias) {
+ parallel_nd_in_omp(nthreads, jcp.oc, [&](int ithr, int ofm) {
+ diff_bias_prv(ithr, ofm) = 0.0f;
+ });
+ }
+
+ trans_ker_p.G = G_I_3x3_4x4;
+ trans_ker_p.M = I;
+ trans_ker_p.T = T;
+
+ parallel_nd_in_omp(jcp.nb_ic, jcp.ic_block, jcp.mb,
+ [&](int ifm1, int ifm2, int img){
+ size_t ifm = ifm1 * jcp.ic_block + ifm2;
+ size_t tile_base_index = img * (jcp.itiles * jcp.jtiles);
+ size_t tblk3 = tile_base_index % jcp.tile_block_ur;
+ size_t tblk2 = (tile_base_index / jcp.tile_block_ur)
+ % jcp.nb_tile_block_ur;
+ size_t tblk1 = (tile_base_index / jcp.tile_block_ur)
+ / jcp.nb_tile_block_ur;
+ trans_ker_p.tile_count = tblk2 * jcp.tile_block_ur + tblk3;
+ trans_ker_p.src = (float *)&(src(img, ifm, 0, 0, 0));
+ trans_ker_p.dst = (float *)&(V(ifm1, tblk1, 0, 0, ifm2, 0, 0, 0));
+ kernel_->src_transform(&trans_ker_p);
+ });
+
+ int ithr = mkldnn_get_thread_num();
+ trans_ker_p.G = G_W_3x3_4x4;
+ parallel_nd_in_omp(jcp.nb_oc, jcp.oc_block, jcp.mb,
+ [&](int ofm1, int ofm2, int img){
+ int ofm = (ofm1 * jcp.oc_block + ofm2) * jcp.oc_reg_block;
+ size_t tile_base_index = img * (jcp.itiles * jcp.jtiles);
+ size_t tblk3 = tile_base_index % jcp.tile_block_ur;
+ size_t tblk2 = (tile_base_index / jcp.tile_block_ur)
+ % jcp.nb_tile_block_ur;
+ size_t tblk1 = (tile_base_index / jcp.tile_block_ur)
+ / jcp.nb_tile_block_ur;
+ trans_ker_p.tile_count = tblk2 * jcp.tile_block_ur + tblk3;
+ trans_ker_p.src = (float *)&(diff_dst(img, ofm, 0, 0, 0));
+ trans_ker_p.dst = (float *)&(M(ofm1, tblk1, 0, 0, ofm2, 0, 0, 0, 0));
+ if (jcp.with_bias) {
+ trans_ker_p.bias = (float *)&(diff_bias_prv(ithr, ofm * simd_w));
+ kernel_->diff_dst_transform_wbias(&trans_ker_p);
+ } else {
+ kernel_->diff_dst_transform(&trans_ker_p);
+ }
+ });
+
+ PRAGMA_OMP(barrier)
+
+ parallel_nd_in_omp(jcp.nb_ic, jcp.nb_oc, alpha, alpha, jcp.tile_block,
+ [&](int ifm1, int ofm1, int oj, int oi, int tblk1){
+ if (first_tblk == 0) {
+ input_starts[ithr] =
+ (float *)&(Us(ithr, ifm1, ofm1, oj, oi, 0, 0, 0,
+ 0, 0))
+ - (float *)&(Us(ithr, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0));
+ input_ends[ithr] = input_starts[ithr]
+ + jcp.oc_block * jcp.ic_block
+ * jcp.ic_simd_block * jcp.oc_reg_block
+ * jcp.oc_simd_block;
+ }
+ else if (tblk1 == 0) {
+ input_ends[ithr] += jcp.oc_block * jcp.ic_block
+ * jcp.ic_simd_block * jcp.oc_reg_block
+ * jcp.oc_simd_block;
+ }
+
+ if (first_tblk == 0 || tblk1 == 0) {
+ kernel_->gemm_loop_ker_first_iter(
+ &(Us(ithr, ifm1, ofm1, oj, oi,
+ 0, 0, 0, 0, 0)),
+ &(M(ofm1, tblk1, oj, oi, 0, 0, 0, 0, 0)),
+ &(V(ifm1, tblk1, oj, oi, 0, 0, 0, 0)));
+ } else {
+ kernel_->gemm_loop_ker(
+ &(Us(ithr, ifm1, ofm1, oj, oi,
+ 0, 0, 0, 0, 0)),
+ &(M(ofm1, tblk1, oj, oi, 0, 0, 0, 0, 0)),
+ &(V(ifm1, tblk1, oj, oi, 0, 0, 0, 0)));
+ }
+ ++first_tblk;
+ });
+}
+
+ // Reduce diff-weights
+ {
+ float *output = &(U(0, 0, 0, 0, 0, 0, 0, 0, 0));
+ size_t nelems = jcp.ic * jcp.oc * alpha * alpha;
+ float *input_ptrs[max_threads_number];
+ for (int i = 0; i < nthreads; ++i)
+ input_ptrs[i] = output + nelems * (i + 1);
+ subarray_sum(nthreads, output, nelems, input_ptrs,
+ input_starts, input_ends);
+ }
+
+ trans_ker_p.G = G_O_3x3_4x4;
+PRAGMA_OMP(parallel firstprivate(trans_ker_p))
+ {
+ parallel_nd_in_omp(jcp.nb_ic, jcp.nb_oc, jcp.oc_block, jcp.ic_block, jcp.oc_reg_block,
+ [&](int ifm1, int ofm1, int ofm2, int ifm2, int ofm3){
+ int ofm = (ofm1 * jcp.oc_block + ofm2)
+ * jcp.oc_reg_block + ofm3;
+ int ifm = ifm1 * jcp.ic_block + ifm2;
+ trans_ker_p.src = (float *)&(U(ifm1, ofm1, 0, 0,
+ ofm2, ifm2, 0, ofm3, 0));
+ trans_ker_p.dst = (float *)&(diff_weights(ofm, ifm,
+ 0, 0, 0, 0));
+ kernel_->diff_weights_transform(&trans_ker_p);
+ });
+ }
+
+ if (jcp.with_bias) {
+ parallel_nd(jcp.oc / simd_w, [&](int ofm1) {
+ float* pbias = &(diff_bias(ofm1 * simd_w));
+ float *pbias_prv = &(diff_bias_prv(0, ofm1 * simd_w));
+
+ const int blk_sz = ofm1 == jcp.oc / simd_w - 1
+ ? jcp.oc_without_padding - ofm1 * simd_w : simd_w;
+
+ PRAGMA_OMP_SIMD()
+ for (int ofm2 = 0; ofm2 < blk_sz; ++ofm2) {
+ pbias[ofm2] = pbias_prv[ofm2];
+ }
+
+ for (int ithr = 1; ithr < nthreads; ++ithr) {
+ pbias_prv = &(diff_bias_prv(ithr, ofm1 * simd_w));
+ PRAGMA_OMP_SIMD()
+ for (int ofm2 = 0; ofm2 < blk_sz; ++ofm2) {
+ pbias[ofm2] += pbias_prv[ofm2];
+ }
+ }
+ });
+ }
+}
+
+}
+}
+}
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.hpp
new file mode 100644
index 0000000000..f1a56aac70
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.hpp
@@ -0,0 +1,386 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_CORE_FP32_WINO_CONV_4x3_HPP
+#define CPU_JIT_AVX512_CORE_FP32_WINO_CONV_4x3_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace winograd_avx512_core {
+inline void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_winograd_conf_t &jcp) {
+ using namespace utils;
+ using namespace memory_tracking::names;
+
+ size_t U_sz = (size_t)alpha * alpha * jcp.ic * jcp.oc;
+ size_t V_sz = (size_t)alpha * alpha * jcp.mb * jcp.ic * jcp.itiles
+ * jcp.jtiles;
+ size_t M_sz = (size_t)alpha * alpha * jcp.mb * jcp.oc * jcp.itiles
+ * jcp.jtiles;
+
+ switch (jcp.sched_policy) {
+ case WSCHED_DATA_W_SGD:
+ V_sz = (size_t)jcp.nthr * alpha * alpha * jcp.nb_tile_block_ur
+ * jcp.tile_block_ur * jcp.ic;
+ M_sz = (size_t)jcp.nthr * alpha * alpha * jcp.nb_tile_block_ur
+ * jcp.tile_block_ur * jcp.oc;
+ break;
+ case WSCHED_WEI_SDGtWo:
+ U_sz = (size_t)jcp.nthr * (alpha * alpha * jcp.oc
+ * (jcp.ic / jcp.nb_ic) + jcp.ic * jcp.oc * jcp.kh * jcp.kw);
+ M_sz = (size_t)jcp.nthr * alpha * alpha * (jcp.ntiles / jcp.tile_block)
+ * (jcp.oc / jcp.nb_oc);
+ V_sz = (size_t)jcp.nthr * alpha * alpha * (jcp.ntiles / jcp.tile_block)
+ * (jcp.ic / jcp.nb_ic);
+ break;
+ case WSCHED_WEI_S_D_Giot_W:
+ U_sz = (size_t)(jcp.nthr + 1) * alpha * alpha * jcp.ic * jcp.oc;
+ M_sz = (size_t)alpha * alpha * jcp.oc * jcp.ntiles;
+ V_sz = (size_t)alpha * alpha * jcp.ic * jcp.ntiles;
+ break;
+ default: break;
+ }
+
+ scratchpad.book(key_wino_U, sizeof(float) * U_sz, PAGE_2M);
+ scratchpad.book(key_wino_V, sizeof(float) * V_sz, PAGE_2M);
+ scratchpad.book(key_wino_M, sizeof(float) * M_sz, PAGE_2M);
+
+ if (one_of(jcp.sched_policy, WSCHED_WEI_SDGtWo, WSCHED_WEI_S_D_Giot_W)) {
+ size_t br_sz = (size_t)jcp.nthr * jcp.oc;
+ scratchpad.book(key_conv_bia_reduction, sizeof(float) * br_sz, PAGE_2M);
+ }
+}
+}
+
+template <bool is_fwd>
+struct _jit_avx512_core_fp32_wino_conv_4x3_t {
+
+ _jit_avx512_core_fp32_wino_conv_4x3_t(
+ const jit_conv_winograd_conf_t &jcp, const primitive_attr_t *attr)
+ : kernel_(nullptr), attr_(attr) {
+ kernel_ = new _jit_avx512_core_fp32_wino_conv_4x3_data_kernel(jcp);
+ }
+
+ ~_jit_avx512_core_fp32_wino_conv_4x3_t() { delete kernel_; }
+
+ protected:
+ void weight_transform_data(const jit_conv_winograd_conf_t &jcp,
+ float *wp, float *twp) const;
+ void input_transform_data(int image,
+ const jit_conv_winograd_conf_t &jcp,
+ float *inp, float *tinp) const;
+ void input_transform_tileblock_data(int tile_block,
+ const jit_conv_winograd_conf_t &jcp,
+ float *inp, float *tinp) const;
+ void output_transform_data(int image,
+ const jit_conv_winograd_conf_t &jcp,
+ const post_ops_t &p_ops, float *toutp, float *pout_b,
+ float *bias) const;
+ void output_transform_tileblock_data(int tile_block,
+ const jit_conv_winograd_conf_t &jcp, const post_ops_t &p_ops,
+ float *toutp, float *outp, float *bias) const;
+ void _execute_data_W_S_G_D(float *inp_ptr, float *out_ptr,
+ float *wei_ptr, float *bias_ptr,
+ const memory_tracking::grantor_t &scratchpad) const;
+ void _execute_data_W_SGD(float *inp_ptr, float *out_ptr,
+ float *wei_ptr, float *bias_ptr,
+ const memory_tracking::grantor_t &scratchpad) const;
+ _jit_avx512_core_fp32_wino_conv_4x3_data_kernel *kernel_;
+ const primitive_attr_t *attr_;
+};
+
+struct jit_avx512_core_fp32_wino_conv_4x3_fwd_t
+ : _jit_avx512_core_fp32_wino_conv_4x3_t<true>
+ , public cpu_primitive_t
+ {
+ struct pd_t : public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_wino_4x3:", avx512_core, ""),
+ jit_avx512_core_fp32_wino_conv_4x3_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::convolution_auto,
+ alg_kind::convolution_winograd)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_avx512_core_fp32_wino_conv_4x3_fwd_kernel::
+ init_conf(jcp_, *desc(), src_md_, weights_md_, dst_md_,
+ *attr());
+ if (status != status::success) return status;
+ set_default_alg_kind(alg_kind::convolution_winograd);
+
+ auto scratchpad = scratchpad_registry().registrar();
+ winograd_avx512_core::init_scratchpad(scratchpad, jcp_);
+
+ return status;
+ }
+
+ jit_conv_winograd_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+ auto wei_fmt = desc()->prop_kind == prop_kind::forward_training
+ ? (with_groups() ? gOIhw16i16o : OIhw16i16o) : any;
+ return set_default_formats_common(nChw16c, wei_fmt, nChw16c);
+ }
+ };
+
+ jit_avx512_core_fp32_wino_conv_4x3_fwd_t(const pd_t *apd)
+ : _jit_avx512_core_fp32_wino_conv_4x3_t<true>(apd->jcp_, apd->attr())
+ , cpu_primitive_t(apd, true)
+ {}
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto src = CTX_IN_MEM(const float *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const float *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const float *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(float *, MKLDNN_ARG_DST);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ switch ((pd()->jcp_).sched_policy) {
+ case WSCHED_DATA_W_S_G_D:
+ this->_execute_data_W_S_G_D((float *)src, dst, (float *)weights,
+ (float *)bias, scratchpad);
+ break;
+ case WSCHED_DATA_W_SGD:
+ this->_execute_data_W_SGD((float *)src, dst, (float *)weights,
+ (float *)bias, scratchpad);
+ break;
+ default:
+ break;
+ }
+ return status::success;
+ }
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+struct jit_avx512_core_fp32_wino_conv_4x3_bwd_data_t
+ : _jit_avx512_core_fp32_wino_conv_4x3_t<false>,
+ public cpu_primitive_t {
+ struct pd_t : public cpu_convolution_bwd_data_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_wino_4x3:", avx512_core, ""),
+ jit_avx512_core_fp32_wino_conv_4x3_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && mkldnn_thr_syncable()
+ && desc()->prop_kind == prop_kind::backward_data
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::convolution_auto,
+ alg_kind::convolution_winograd)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::undef, data_type::f32, data_type::f32)
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_avx512_core_fp32_wino_conv_4x3_bwd_data_kernel
+ ::init_conf(jcp_, *desc(), *diff_src_md(), *weights_md(),
+ *diff_dst_md());
+ if (status != status::success) return status;
+ set_default_alg_kind(alg_kind::convolution_winograd);
+
+ auto scratchpad = scratchpad_registry().registrar();
+ winograd_avx512_core::init_scratchpad(scratchpad, jcp_);
+
+ return status;
+ }
+
+ jit_conv_winograd_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+ auto wei_fmt = with_groups() ? gOIhw16i16o : OIhw16i16o;
+ return set_default_formats_common(nChw16c, wei_fmt, nChw16c);
+ }
+ };
+
+ jit_avx512_core_fp32_wino_conv_4x3_bwd_data_t(const pd_t *apd)
+ : _jit_avx512_core_fp32_wino_conv_4x3_t<false>(apd->jcp_, apd->attr())
+ , cpu_primitive_t(apd, true)
+ {}
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto diff_dst = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const float *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_SRC);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ switch ((pd()->jcp_).sched_policy) {
+ case WSCHED_DATA_W_S_G_D:
+ this->_execute_data_W_S_G_D((float *)diff_dst, diff_src,
+ (float *)weights, NULL, scratchpad);
+ break;
+
+ case WSCHED_DATA_W_SGD:
+ this->_execute_data_W_SGD((float *)diff_dst, diff_src,
+ (float *)weights, NULL, scratchpad);
+ break;
+
+ default:
+ break;
+ }
+
+ return status::success;
+ }
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+struct jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t
+ : public cpu_primitive_t {
+ struct pd_t : public cpu_convolution_bwd_weights_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_wino_4x3:", avx512_core, ""),
+ jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t);
+
+ status_t init() {
+ bool ok = true
+ && mkldnn_thr_syncable()
+ && desc()->prop_kind == prop_kind::backward_weights
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::convolution_auto,
+ alg_kind::convolution_winograd)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && set_default_formats();
+ if (!ok)
+ return status::unimplemented;
+
+ status_t status =
+ jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel::
+ init_conf(jcp_, *desc(), *src_md(), *diff_dst_md(),
+ *diff_weights_md());
+ if (status != status::success) return status;
+ set_default_alg_kind(alg_kind::convolution_winograd);
+
+ auto scratchpad = scratchpad_registry().registrar();
+ winograd_avx512_core::init_scratchpad(scratchpad, jcp_);
+
+ return status;
+ }
+
+ jit_conv_winograd_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+ auto wei_fmt = with_groups() ? gOIhw16i16o : OIhw16i16o;
+ return set_default_formats_common(nChw16c, wei_fmt, nChw16c);
+ }
+ };
+
+ jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t(const pd_t *apd)
+ : cpu_primitive_t(apd, true)
+ , kernel_(nullptr)
+ {
+ kernel_ = new jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel(
+ pd()->jcp_);
+ }
+
+ ~jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_t()
+ {
+ delete kernel_;
+ }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto diff_dst = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST);
+ auto src = CTX_IN_MEM(const float *, MKLDNN_ARG_SRC);
+ auto diff_weights = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_WEIGHTS);
+ auto diff_bias = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_BIAS);
+
+ switch (kernel_->jcp.sched_policy) {
+ case WSCHED_WEI_SDGtWo:
+ _execute_backward_weights_SDGtWo(src, diff_dst, diff_weights,
+ diff_bias, scratchpad(ctx));
+ break;
+ case WSCHED_WEI_S_D_Giot_W:
+ _execute_backward_weights_S_D_Giot_W(src, diff_dst, diff_weights,
+ diff_bias, scratchpad(ctx));
+ break;
+ default:
+ assert(kernel_->jcp.sched_policy != WSCHED_INVALID);
+ break;
+ }
+ return status::success;
+ }
+
+private:
+ void _execute_backward_weights_SDGtWo(const float *src,
+ const float *diff_dst, float *diff_weights, float *diff_bias,
+ const memory_tracking::grantor_t &scratchpad) const;
+ void _execute_backward_weights_S_D_Giot_W(const float *src,
+ const float *diff_dst, float *diff_weights, float *diff_bias,
+ const memory_tracking::grantor_t &scratchpad) const;
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel *kernel_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.cpp
new file mode 100644
index 0000000000..0d64a2d13a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.cpp
@@ -0,0 +1,2596 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include <math.h>
+
+#include "jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp"
+
+#define GET_OFF(field) offsetof(jit_wino_transform_call_s, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace {
+
+using namespace mkldnn::impl::utils;
+
+unsigned int L1_cache_size = get_cache_size(1, true);
+unsigned int L2_cache_size = get_cache_size(2, true);
+unsigned int LLC_data_size = get_cache_size(3, false);
+
+// the test funtion takes jcp, the candidate and the current best.
+// it returns true if the new candidate is better
+int get_divisor_satisfying_cond(jit_conv_winograd_conf_t &jcp, int number,
+ int default_best, bool (*test)(jit_conv_winograd_conf_t &, int, int))
+{
+ int best_divisor = default_best;
+ auto test_num
+ = [&best_divisor, test](jit_conv_winograd_conf_t &jcp, int num) {
+ if (test(jcp, num, best_divisor)) {
+ best_divisor = num;
+ }
+ };
+
+ for (int divisor = 1; divisor <= ::sqrt(number); divisor++) {
+ if (number % divisor == 0) {
+ test_num(jcp, divisor);
+ test_num(jcp, number / divisor);
+ }
+ }
+
+ return best_divisor;
+}
+
+namespace {
+bool is_winograd_faster_than_direct(const jit_conv_winograd_conf_t &jcp) {
+ /* Determines if current winograd implementation is faster than direct.
+ Following conditions are empirical and based on performance data */
+ unsigned int ncores_per_socket =
+ cpu.getNumCores(Xbyak::util::IntelCpuTopologyLevel::CoreLevel);
+ unsigned int nthreads = mkldnn_get_max_threads();
+
+ if (jcp.prop_kind == prop_kind::forward_inference) {
+ return jcp.mb >= 4;
+ } else if (nthreads > ncores_per_socket) {
+ double src_dst_transforms_per_core = alpha * alpha
+ * (jcp.ic + jcp.oc)
+ * jcp.mb * ((jcp.oh + tile_size - 1) / tile_size)
+ * ((jcp.ow + tile_size - 1) / tile_size)
+ * sizeof(float) / 1024. / 1024. / nthreads;
+ double wei_transform = alpha * alpha
+ * jcp.ic * jcp.oc * sizeof(float) /1024. / 1024.;
+
+ if (jcp.prop_kind == prop_kind::backward_weights) {
+ if (src_dst_transforms_per_core < 0.3
+ || (src_dst_transforms_per_core <= 28 && wei_transform < 4))
+ return false;
+ else
+ return true;
+ } else {
+ if (src_dst_transforms_per_core < 2.0 || wei_transform < 0.02)
+ return false;
+ }
+ }
+
+ return jcp.mb > 8;
+}
+}
+
+/* assumes 512 bits registers */
+/* TODO: add support for strides */
+/* TODO: handle the prefetch distance automatically */
+typedef enum cache_t_ { L1, L2, L3 } cache_t;
+
+template <typename data_t>
+struct prefetcher_t {
+ prefetcher_t(jit_generator *generator, Xbyak::Reg64 reg_base_addr,
+ cache_t cache_type, size_t block_size, /* in number of elements*/
+ int nb_instructions_in_block, int fma_ipc)
+ : cg_(generator)
+ , reg_base_addr_(reg_base_addr)
+ , cache_type_(cache_type)
+ , cache_block_size_(block_size)
+ {
+ nb_cache_lines_to_prefetch_ = cache_block_size_ / (64 / sizeof(data_t));
+ prefetch_spread_
+ = div_up(nb_instructions_in_block, nb_cache_lines_to_prefetch_);
+ prefetch_blk_
+ = div_up(nb_cache_lines_to_prefetch_, nb_instructions_in_block);
+
+ /* assumption: when fetch in Li, data is already in L(i+1) */
+ int cache_latency;
+ switch (cache_type_) {
+ case L1: cache_latency = 14; break;
+ case L2: cache_latency = 250; break;
+ case L3: cache_latency = 250; break;
+ }
+
+ prefetch_distance_ = div_up(cache_latency, nb_cache_lines_to_prefetch_);
+ }
+
+ void prefetch(int instruction_number)
+ {
+ if (instruction_number % prefetch_spread_ == 0) {
+ for (int i = 0; (i < prefetch_blk_)
+ && (prefetches_issued_ < nb_cache_lines_to_prefetch_);
+ i++, prefetches_issued_++) {
+ prefetch_inst_(cg_->EVEX_compress_addr(
+ reg_base_addr_, (cache_block_size_ * prefetch_distance_)
+ * sizeof(data_t)
+ + (prefetches_issued_ * 64)));
+ }
+ }
+ }
+
+private:
+ void prefetch_inst_(const Xbyak::Address &addr)
+ {
+ switch (cache_type_) {
+ case L1: cg_->prefetcht0(addr); break;
+ case L2: cg_->prefetcht1(addr); break;
+ case L3: cg_->prefetcht2(addr); break;
+ default:
+ break; // TODO: raise an exception or put an assert
+ }
+ }
+
+ jit_generator *cg_;
+ Xbyak::Reg64 reg_base_addr_;
+ cache_t cache_type_;
+ int cache_block_size_ = 0;
+ int nb_cache_lines_to_prefetch_ = 0;
+ int prefetches_issued_ = 0;
+ int prefetch_spread_ = 0;
+ int prefetch_blk_ = 0;
+ int prefetch_distance_ = 0;
+};
+
+// utilities to support kernel parameter selection
+bool check_L2_block_per_thread(jit_conv_winograd_conf_t &jcp,
+ int dimN_block, float C2_min, float C2_max) {
+ float block_size = alpha * alpha * (2*(jcp.oc + jcp.ic)
+ * dimN_block * jcp.dimN_reg_block
+ + div_up(jcp.ic * jcp.oc,mkldnn_get_max_threads())) * (float)sizeof(float);
+ float L2_lb = C2_min * L2_cache_size;
+ float L2_ub = C2_max * L2_cache_size;
+ return (block_size > L2_lb && block_size < L2_ub);
+}
+
+bool check_L1_block_gemm(jit_conv_winograd_conf_t &jcp, int dimK_block,
+ int dimM_block, float C1_min, float C1_max) {
+ float gemm_block_size = (dimM_block * jcp.dimM_simd_block * dimK_block
+ * jcp.dimK_reg_block * jcp.dimM_reg_block
+ + dimK_block * jcp.dimK_reg_block * jcp.dimN_reg_block
+ + dimM_block * jcp.dimM_simd_block * jcp.dimN_reg_block)
+ * (float)sizeof(float);
+ float L1_lb = C1_min * L1_cache_size;
+ float L1_ub = C1_max * L1_cache_size;
+ return (gemm_block_size > L1_lb && gemm_block_size < L1_ub);
+}
+bool check_cond1(int dimN_reg_block, int dimK_block, int dimK_reg_block,
+ int dimM_block, int dimM_reg_block, int dimM_simd_block, float C)
+{
+ float lhs = (dimM_block * dimN_reg_block * dimM_simd_block * dimM_reg_block
+ + dimM_block * dimK_block * dimK_reg_block
+ * dimM_simd_block * dimM_reg_block
+ + dimK_block * dimN_reg_block * dimK_reg_block)
+ * (float)sizeof(float);
+ float rhs = C * L1_cache_size;
+ return (lhs < rhs);
+}
+bool check_cond1_bis(int dimN_reg_block, int dimK_block, int dimK_reg_block,
+ int dimM_block, int dimM_reg_block, int dimM_simd_block, float C)
+{
+ float lhs = (dimM_block * dimM_reg_block * dimK_block * dimK_reg_block
+ * dimM_simd_block + dimK_block * dimN_reg_block * dimK_reg_block)
+ * (float)sizeof(float);
+ float rhs = C * L1_cache_size;
+ return (lhs < rhs);
+}
+bool check_cond2(int nb_dimN_reg_block, int dimN_reg_block, int dimK_nb_block,
+ int dimK_block, int dimK_reg_block, int dimM_block, int dimM_reg_block,
+ int dimM_simd_block, float C)
+{
+ float lhs = (nb_dimN_reg_block * dimM_block * dimN_reg_block
+ * dimM_simd_block * dimM_reg_block
+ + dimK_nb_block * dimM_block * dimK_block * dimK_reg_block
+ * dimM_simd_block * dimM_reg_block
+ + nb_dimN_reg_block * dimK_nb_block * dimK_block
+ * dimN_reg_block * dimK_reg_block)
+ * (float)sizeof(float);
+ float rhs = C * L2_cache_size;
+ return (lhs < rhs);
+}
+
+bool check_kernel_cond(int dimM_block, int dimM_reg_block, int dimM_simd_block,
+ int dimN_block, int dimN_reg_block, int dimK, float C1, float C2)
+{
+ float A_size = dimM_block * dimM_reg_block * dimM_simd_block * dimK
+ * (float)sizeof(float);
+ float B_size = dimN_block * dimN_reg_block * dimK
+ * (float)sizeof(float);
+ return (A_size > C1 * L2_cache_size && B_size > C2 * L2_cache_size);
+}
+}
+
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::utils;
+using namespace Xbyak;
+
+void _jit_avx512_core_fp32_wino_conv_4x3_data_kernel::gemm_loop_generate()
+{
+ // for (int dimM_block =0; dimM_block < jcp.dimM_block; dimM_block++)
+ // for (int dimM_reg_block =0; dimM_reg_block < jcp.dimM_reg_block;
+ // dimM_reg_block++) // unrolled
+ // for (int dimK_block = 0; dimK_block < jcp.dimK_block; dimK_block++)
+ // for (int dimK_reg_block= 0; dimK_reg_block < jcp.dimK_reg_block;
+ // dimK_reg_block++) // unrolled
+ // for (int tile =0; tile < jcp.dimN_reg_block; tile++)
+ // C[dimM_block][dimM_reg_block][tile] +=
+ // A[dimM_block][dimM_reg_block][dimK_block][dimK_reg_block]
+ // * broadcast(B[dimK_block][tile][dimK_reg_block]);
+ // Notes:
+ // jcp.kernel_kind defines embedded or explicit broadcast
+ // dimM_reg_block=1 for embedded bcast kernel
+
+ auto zmm_srcA = [=]() {
+ return Xbyak::Zmm(0);
+ };
+ auto zmm_srcB = [=](int tile) {
+ int idx = 1 + tile;
+ assert(idx < 1 + jcp.dimN_reg_block);
+ return Xbyak::Zmm(idx);
+ };
+ auto zmm_dstC = [=](int dimM_reg_block, int tile) {
+ int idx{0};
+ if (jcp.kernel_kind == embd_bcast)
+ idx = 1 + tile;
+ else
+ idx = 1 + jcp.dimN_reg_block
+ + dimM_reg_block * jcp.dimN_reg_block + tile;
+ assert(idx < 32);
+ return Xbyak::Zmm(idx);
+ };
+
+ auto prepare_output = [=]() {
+ for (int dimM_reg_block = 0; dimM_reg_block < jcp.dimM_reg_block;
+ dimM_reg_block++) {
+ for (int tile = 0; tile < jcp.dimN_reg_block; tile++) {
+ Zmm zmm = zmm_dstC(dimM_reg_block, tile);
+ vpxord(zmm, zmm, zmm);
+ }
+ }
+ };
+ auto store_output = [=](bool output_is_aligned) {
+ Label save;
+ cmp(reg_is_beta_zero, 0);
+ je(save, T_NEAR);
+
+ for (int dimM_reg_block = 0; dimM_reg_block < jcp.dimM_reg_block;
+ dimM_reg_block++) {
+ for (int tile = 0; tile < jcp.dimN_reg_block; tile++) {
+ Zmm zmm = zmm_dstC(dimM_reg_block,tile);
+ int output_offset
+ = jcp.dimN_reg_block * dimM_reg_block * 64 + tile * 64;
+ vaddps(zmm, zmm, EVEX_compress_addr(reg_dstC, output_offset));
+ }
+ }
+
+ L(save);
+ for (int dimM_reg_block = 0; dimM_reg_block < jcp.dimM_reg_block;
+ dimM_reg_block++) {
+ for (int tile = 0; tile < jcp.dimN_reg_block; tile++) {
+ Zmm zmm = zmm_dstC(dimM_reg_block,tile);
+ int output_offset
+ = jcp.dimN_reg_block * dimM_reg_block * 64 + tile * 64;
+
+ // In W_SGD, output will be reused.
+ if (output_is_aligned
+ && jcp.dimK_nb_block == 1
+ && jcp.sched_policy == WSCHED_DATA_W_S_G_D
+ && (jcp.dimN * jcp.dimM * alpha * alpha
+ * sizeof(float) > 2 * LLC_data_size))
+ vmovntps(EVEX_compress_addr(reg_dstC, output_offset), zmm);
+ else vmovups(EVEX_compress_addr(reg_dstC, output_offset), zmm);
+ }
+ }
+ };
+
+ auto inner_loops = [=]() {
+ Label dimM_block_loop, dimK_block_loop;
+
+ if (jcp.dimM_block > 1) {
+ mov(reg_dimM_block_loop_cnt, jcp.dimM_block);
+ L(dimM_block_loop);
+ }
+
+ prepare_output();
+
+ if (jcp.dimK_block > 1) {
+ mov(reg_dimK_block_loop_cnt, jcp.dimK_block);
+ L(dimK_block_loop);
+ }
+
+ for (int dimK_reg_block = 0;
+ dimK_reg_block < jcp.dimK_reg_block;
+ dimK_reg_block ++) {
+
+ if (jcp.kernel_kind == expl_bcast) {
+ for (int tile = 0; tile < jcp.dimN_reg_block; tile++) {
+ vbroadcastss(zmm_srcB(tile),
+ ptr[reg_srcB + 64 * tile + dimK_reg_block * 4]);
+ }
+ }
+
+ /* Performing the fmas */
+
+ for (int dimM_reg_block = 0; dimM_reg_block < jcp.dimM_reg_block;
+ dimM_reg_block++) {
+
+ vmovups(zmm_srcA(),
+ zword[reg_srcA
+ + jcp.dimK_reg_block * jcp.dimK_block * 64
+ * dimM_reg_block
+ + dimK_reg_block * 64]
+ );
+
+ for (int tile = 0; tile < jcp.dimN_reg_block; tile++) {
+ if (jcp.kernel_kind == expl_bcast)
+ vfmadd231ps(zmm_dstC(dimM_reg_block, tile), zmm_srcA(),
+ zmm_srcB(tile));
+ else
+ vfmadd231ps(zmm_dstC(dimM_reg_block, tile), zmm_srcA(),
+ EVEX_compress_addr(reg_srcB,
+ 64 * tile + dimK_reg_block * 4, true));
+ }
+ }
+ }
+ add(reg_srcA, jcp.dimK_reg_block * 64);
+ add(reg_srcB, jcp.dimN_reg_block * 64);
+ if (jcp.dimK_block > 1) {
+ sub(reg_dimK_block_loop_cnt, 1);
+ jnz(dimK_block_loop);
+ }
+
+ Label unaligned_store, end_store;
+ test(reg_dstC, cpu_isa_traits<avx512_core>::vlen - 1);
+ jnz(unaligned_store, T_NEAR);
+ store_output(true);
+ jmp(end_store, T_NEAR);
+ L(unaligned_store); {
+ store_output(false);
+ }
+ L(end_store);
+
+ if (jcp.dimM_block > 1) {
+ sub(reg_srcB, jcp.dimK_block * jcp.dimN_reg_block * 64);
+ add(reg_dstC, jcp.dimM_reg_block * jcp.dimN_reg_block * 64);
+ if (jcp.kernel_kind == expl_bcast) {
+ add(reg_srcA,
+ (jcp.dimM_reg_block-1) * jcp.dimK_reg_block * 64
+ * jcp.dimK_block);
+ }
+ sub(reg_dimM_block_loop_cnt, 1);
+ jnz(dimM_block_loop);
+ }
+ };
+
+ /* Preamble */
+ preamble();
+
+ /* kernel */
+ inner_loops();
+
+ /* Postamble */
+ postamble();
+ ret();
+}
+
+void _jit_avx512_core_fp32_wino_conv_4x3_data_kernel
+ ::weights_transform_data_ker_generate()
+{
+ bool is_fwd = one_of(jcp.prop_kind,
+ mkldnn_forward_training, mkldnn_forward_inference);
+ int kh = jcp.kh;
+ int kw = jcp.kw;
+
+ auto zmm_temp = Xbyak::Zmm(31);
+ auto zmm_zero = Xbyak::Zmm(30);
+
+ auto zmm_M = [=](int i) {
+ return Xbyak::Zmm(i);
+ };
+ auto zmm_MT = [=](int i) {
+ return Xbyak::Zmm(i + simd_w);
+ };
+
+ auto zmm_G = [=](int i) {
+ return Xbyak::Zmm(i);
+ };
+ auto zmm_F = [=](int i) {
+ return Xbyak::Zmm(alpha + i);
+ };
+ auto zmm_T = [=](int i) {
+ return Xbyak::Zmm(alpha + 3 + i);
+ };
+ auto zmm_t = [=](int i) {
+ return Xbyak::Zmm(2 * alpha + 3 + i);
+ };
+
+ auto zmm_load = [=](int i) {
+ return Xbyak::Zmm(i);
+ };
+
+ auto init_G = [=]() {
+ mov(wreg_temp, ptr[param1 + GET_OFF(G)]);
+ for (int i = 0; i < alpha; i++) {
+ vbroadcastss(zmm_G(i), ptr[wreg_temp + i * typesize]);
+ }
+ vpxord(zmm_zero, zmm_zero, zmm_zero);
+ };
+
+ auto trans16x16 = [=]() {
+ for (int i = 0; i < simd_w; i+=2 ) {
+ vmovups(zmm_M(i), ptr[wreg_M + i * simd_w * 4]);
+ vmovups(zmm_M(i+1), ptr[wreg_M + (i + 1) * simd_w * 4]);
+ vunpcklps(zmm_MT(i), zmm_M(i), zmm_M(i+1));
+ vunpckhps(zmm_MT(i+1), zmm_M(i), zmm_M(i+1));
+ }
+ for (int i = 0; i < simd_w; i+=4 ) {
+ vunpcklpd(zmm_M(i), zmm_MT(i), zmm_MT(i+2));
+ vunpckhpd(zmm_M(i+1), zmm_MT(i), zmm_MT(i+2));
+ vunpcklpd(zmm_M(i+2), zmm_MT(i+1), zmm_MT(i+3));
+ vunpckhpd(zmm_M(i+3), zmm_MT(i+1), zmm_MT(i+3));
+ }
+ for (int i = 0; i < simd_w; i += 8) {
+ vshuff32x4(zmm_MT(i), zmm_M(i), zmm_M(i + 4), 0x88);
+ vshuff32x4(zmm_MT(i+1), zmm_M(i+1), zmm_M(i + 5), 0x88);
+ vshuff32x4(zmm_MT(i+2), zmm_M(i+2), zmm_M(i + 6), 0x88);
+ vshuff32x4(zmm_MT(i+3), zmm_M(i+3), zmm_M(i + 7), 0x88);
+ vshuff32x4(zmm_MT(i+4), zmm_M(i), zmm_M(i + 4), 0xdd);
+ vshuff32x4(zmm_MT(i+5), zmm_M(i+1), zmm_M(i + 5), 0xdd);
+ vshuff32x4(zmm_MT(i+6), zmm_M(i+2), zmm_M(i + 6), 0xdd);
+ vshuff32x4(zmm_MT(i+7), zmm_M(i+3), zmm_M(i + 7), 0xdd);
+ }
+ {
+ int i = 0;
+ int mask = 0x88;
+ vshuff32x4(zmm_M(0), zmm_MT(i), zmm_MT(i + 8), mask);
+ vmovups(ptr[wreg_MT + 0 * 16 * 4], zmm_M(0));
+ vshuff32x4(zmm_M(1), zmm_MT(i + 1), zmm_MT(i + 9), mask);
+ vmovups(ptr[wreg_MT + 1 * 16 * 4], zmm_M(1));
+ vshuff32x4(zmm_M(2), zmm_MT(i + 2), zmm_MT(i + 10), mask);
+ vmovups(ptr[wreg_MT + 2 * 16 * 4], zmm_M(2));
+ vshuff32x4(zmm_M(3), zmm_MT(i + 3), zmm_MT(i + 11), mask);
+ vmovups(ptr[wreg_MT + 3 * 16 * 4], zmm_M(3));
+ vshuff32x4(zmm_M(4), zmm_MT(i + 4), zmm_MT(i + 12), mask);
+ vmovups(ptr[wreg_MT + 4 * 16 * 4], zmm_M(4));
+ vshuff32x4(zmm_M(5), zmm_MT(i + 5), zmm_MT(i + 13), mask);
+ vmovups(ptr[wreg_MT + 5 * 16 * 4], zmm_M(5));
+ vshuff32x4(zmm_M(6), zmm_MT(i + 6), zmm_MT(i + 14), mask);
+ vmovups(ptr[wreg_MT + 6 * 16 * 4], zmm_M(6));
+ vshuff32x4(zmm_M(7), zmm_MT(i + 7), zmm_MT(i + 15), mask);
+ vmovups(ptr[wreg_MT + 7 * 16 * 4], zmm_M(7));
+ mask = 0xdd;
+ vshuff32x4(zmm_M(8), zmm_MT(i), zmm_MT(i + 8), mask);
+ vmovups(ptr[wreg_MT + 8 * 16 * 4], zmm_M(8));
+ vshuff32x4(zmm_M(9), zmm_MT(i + 1), zmm_MT(i + 9), mask);
+ vmovups(ptr[wreg_MT + 9 * 16 * 4], zmm_M(9));
+ vshuff32x4(zmm_M(10), zmm_MT(i + 2), zmm_MT(i + 10), mask);
+ vmovups(ptr[wreg_MT + 10 * 16 * 4], zmm_M(10));
+ vshuff32x4(zmm_M(11), zmm_MT(i + 3), zmm_MT(i + 11), mask);
+ vmovups(ptr[wreg_MT + 11 * 16 * 4], zmm_M(11));
+ vshuff32x4(zmm_M(12), zmm_MT(i + 4), zmm_MT(i + 12), mask);
+ vmovups(ptr[wreg_MT + 12 * 16 * 4], zmm_M(12));
+ vshuff32x4(zmm_M(13), zmm_MT(i + 5), zmm_MT(i + 13), mask);
+ vmovups(ptr[wreg_MT + 13 * 16 * 4], zmm_M(13));
+ vshuff32x4(zmm_M(14), zmm_MT(i + 6), zmm_MT(i + 14), mask);
+ vmovups(ptr[wreg_MT + 14 * 16 * 4], zmm_M(14));
+ vshuff32x4(zmm_M(15), zmm_MT(i + 7), zmm_MT(i + 15), mask);
+ vmovups(ptr[wreg_MT + 15 * 16 * 4], zmm_M(15));
+ }
+ };
+
+ auto load_src = [=]() {
+ mov(wreg_src, ptr[param1 + GET_OFF(src)]);
+ mov(wreg_F, ptr[param1 + GET_OFF(M)]);
+ for (int j = 0; j < kh; j++) {
+ for (int i = 0; i < kw; i++) {
+ if (is_fwd) {
+ for (int v1 = 0; v1 < simd_w; v1++) {
+ int offset_src = (j * kw * simd_w * simd_w
+ + i * simd_w * simd_w + v1 * simd_w) * typesize;
+ int offset_F = (j * kw * simd_w * simd_w
+ + i * simd_w * simd_w + v1 * simd_w) * typesize;
+ vmovups(zmm_temp, ptr[wreg_src + offset_src]);
+ vmovups(ptr[wreg_F + offset_F], zmm_temp);
+ }
+ } else {
+ int offset_src = ((2 - j) * kw * simd_w * simd_w
+ + (2 - i) * simd_w * simd_w) * typesize;
+ int offset_F = (j * kw * simd_w * simd_w
+ + i * simd_w * simd_w) * typesize;
+ lea(wreg_M, ptr[wreg_src + offset_src]);
+ lea(wreg_MT, ptr[wreg_F + offset_F]);
+ trans16x16();
+ }
+ }
+ }
+ };
+
+ auto store_dst = [=]() {
+ mov(wreg_dst, ptr[param1 + GET_OFF(dst)]);
+ mov(wreg_Fw, ptr[param1 + GET_OFF(Mw)]);
+
+ Label Loop_j;
+ mov(wreg_cnt_j, 0);
+ mov(wreg_dst_aux, wreg_dst);
+ mov(wreg_Fw_aux, wreg_Fw);
+
+ int dim5 = jcp.dimK_nb_block * (jcp.dimM_block * jcp.dimM_reg_block)
+ * jcp.dimK_block * simd_w * simd_w;
+
+ L(Loop_j);
+ {
+ for (int i = 0; i < alpha; i++) {
+ // touch pages
+ vmovups(zmm_load(0), ptr[wreg_Fw_aux
+ + (i * simd_w * simd_w) * typesize]);
+ mov(wreg_dst_idx, i * dim5 * typesize);
+ vmovntps(ptr[wreg_dst_aux + wreg_dst_idx], zmm_load(0));
+ }
+ for (int i = 0; i < alpha; i++) {
+ for (int v1 = 1; v1 < simd_w; v1++) {
+ int offset_Fw = (i * simd_w * simd_w + v1 * simd_w)
+ * typesize;
+ vmovups(zmm_load(v1), ptr[wreg_Fw_aux + offset_Fw]);
+ }
+ mov(wreg_dst_idx, i * dim5 * typesize);
+ for (int v1 = 1; v1 < simd_w; v1++) {
+ int offset_dst = v1 * simd_w * typesize;
+ vmovntps(ptr[wreg_dst_aux + wreg_dst_idx + offset_dst],
+ zmm_load(v1));
+ }
+ }
+ add(wreg_Fw_aux, alpha * simd_w * simd_w * typesize);
+ add(wreg_dst_aux, alpha * dim5 * typesize);
+ add(wreg_cnt_j, 1);
+ cmp(wreg_cnt_j, alpha);
+ jl(Loop_j, T_NEAR);
+ }
+ };
+
+ auto trans_W_4x4_3x3 = [=]() {
+ auto fma4 = [=](Zmm dst, Zmm a, Zmm b, Zmm c) {
+ vmovups(dst, a);
+ vfmadd231ps(dst, b, c);
+ };
+ auto fms4 = [=](Zmm dst, Zmm a, Zmm b, Zmm c) {
+ vmulps(zmm_temp, b, c);
+ vsubps(dst, a, zmm_temp);
+ };
+ auto fnms4 = [=](Zmm dst, Zmm a, Zmm b, Zmm c) {
+ vsubps(dst, zmm_zero, a);
+ vfnmadd231ps(dst, b, c);
+ };
+
+ mov(wreg_Fw, ptr[param1 + GET_OFF(Mw)]);
+ mov(wreg_F, ptr[param1 + GET_OFF(M)]);
+ mov(wreg_T, ptr[param1 + GET_OFF(T)]);
+
+ Label Loop_j;
+ mov(wreg_cnt_j, 0);
+ L(Loop_j);
+ mov(wreg_F_aux, wreg_F);
+ mov(wreg_Fw_aux, wreg_Fw);
+ mov(wreg_temp, wreg_cnt_j);
+ shl(wreg_temp, 4 + 2);
+ lea(wreg_F_aux, ptr[wreg_F + wreg_temp]);
+ lea(wreg_Fw_aux, ptr[wreg_Fw + wreg_temp]);
+
+ for (int i = 0; i < 3; i++) {
+ for (int idx = 0; idx < 3; idx ++) {
+ vmovups(zmm_F(idx), ptr[wreg_F_aux + (idx * 3 * simd_w
+ * simd_w + i * simd_w * simd_w) * typesize]);
+ }
+ vmulps(zmm_t(0), zmm_G(0), zmm_F(2));
+ fnms4(zmm_t(1), zmm_t(0), zmm_G(1), zmm_F(0));
+ fma4(zmm_t(2), zmm_t(0), zmm_G(2), zmm_F(0));
+
+ vmulps(zmm_T(0), zmm_G(3), zmm_F(0));
+ fms4(zmm_T(1), zmm_t(1), zmm_G(4), zmm_F(1));
+ fma4(zmm_T(2), zmm_t(1), zmm_G(4), zmm_F(1));
+ fma4(zmm_T(3), zmm_t(2), zmm_G(5), zmm_F(1));
+ fms4(zmm_T(4), zmm_t(2), zmm_G(5), zmm_F(1));
+ vmovaps(zmm_T(5), zmm_F(2));
+
+ for (int idx = 0; idx < 6; idx ++) {
+ vmovups(ptr[wreg_T + (idx * 3 * simd_w + i * simd_w)
+ * typesize], zmm_T(idx));
+ }
+ }
+ for (int i = 0; i < 6; i++) {
+
+ for (int idx = 0; idx < 3; idx ++) {
+ vmovups(zmm_T(idx), ptr[wreg_T
+ + (i * 3 * simd_w + idx * simd_w) * typesize]);
+ }
+ vmulps(zmm_t(0), zmm_G(0), zmm_T(2));
+ fnms4(zmm_t(1), zmm_t(0), zmm_G(1), zmm_T(0));
+ fma4(zmm_t(2), zmm_t(0), zmm_G(2), zmm_T(0));
+
+ vmulps(zmm_F(0), zmm_G(3), zmm_T(0));
+ fms4(zmm_F(1), zmm_t(1), zmm_G(4), zmm_T(1));
+ fma4(zmm_F(2), zmm_t(1), zmm_G(4), zmm_T(1));
+ fma4(zmm_F(3), zmm_t(2), zmm_G(5), zmm_T(1));
+ fms4(zmm_F(4), zmm_t(2), zmm_G(5), zmm_T(1));
+ vmovaps(zmm_F(5), zmm_T(2));
+
+ for (int l = 0; l < 6; l++) {
+ vmovups(ptr[wreg_Fw_aux + (i * 6 * simd_w * simd_w
+ + l * simd_w * simd_w) * typesize], zmm_F(l));
+ }
+ }
+ add(wreg_cnt_j, 1);
+ cmp(wreg_cnt_j, 16);
+ jl(Loop_j, T_NEAR);
+ };
+
+ auto inner_loops = [=]() {
+ load_src();
+ init_G();
+ trans_W_4x4_3x3();
+ store_dst();
+ };
+
+ preamble();
+ inner_loops();
+ postamble();
+}
+
+void _jit_avx512_core_fp32_wino_conv_4x3_data_kernel
+ ::output_transform_data_ker_generate()
+{
+ bool is_fwd = one_of(jcp.prop_kind,
+ mkldnn_forward_training, mkldnn_forward_inference);
+ int outw = is_fwd ? jcp.ow : jcp.iw;
+ int outh = is_fwd ? jcp.oh : jcp.ih;
+ bool not_tiled = jcp.sched_policy == WSCHED_DATA_W_S_G_D;
+ bool with_bias = jcp.with_bias;
+ bool with_relu = jcp.with_eltwise;
+ bool with_relu_postsum = jcp.with_relu_postsum;
+ bool with_sum = jcp.with_sum;
+
+ auto zmm_zero = Xbyak::Zmm(0);
+ auto zmm_temp = Xbyak::Zmm(31);
+ auto zmm_G = [=](int i) {
+ return Xbyak::Zmm(1 + i);
+ };
+ auto zmm_O = [=](int i) {
+ return Xbyak::Zmm(1 + alpha + i);
+ };
+ auto zmm_T = [=](int i) {
+ return Xbyak::Zmm(1 + 2 * alpha + i);
+ };
+ auto zmm_t = [=](int i) {
+ return Xbyak::Zmm(1 + 3 * alpha + i);
+ };
+
+ auto init_G = [=]() {
+ mov(oreg_temp, ptr[param1 + GET_OFF(G)]);
+ for (int i = 0; i < 6; i++) {
+ vbroadcastss(zmm_G(i), ptr[oreg_temp + i * typesize]);
+ }
+ };
+
+ auto load_src = [=]() {
+ mov(oreg_Ow, ptr[param1 + GET_OFF(Mw)]);
+ mov(oreg_src, ptr[param1 + GET_OFF(src)]);
+
+ mov(oreg_nb_tile_block_ur, ptr[param1 + GET_OFF(nb_tile_block_ur)]);
+ imul(oreg_nb_tile_block_ur, oreg_nb_tile_block_ur,
+ (jcp.dimM_block * jcp.dimM_reg_block) * jcp.dimN_reg_block
+ * jcp.dimM_simd_block * typesize);
+ add(oreg_src, oreg_nb_tile_block_ur);
+
+ mov(oreg_tile_block_ur, ptr[param1 + GET_OFF(tile_block_ur)]);
+ imul(oreg_tile_block_ur, oreg_tile_block_ur,
+ jcp.dimM_simd_block * typesize);
+ add(oreg_src, oreg_tile_block_ur);
+
+ if (not_tiled) {
+ mov(oreg_tile_block, ptr[param1 + GET_OFF(tile_block)]);
+ imul(oreg_tile_block, oreg_tile_block,
+ jcp.dimM_nb_block * alpha * alpha * jcp.dimN_block
+ * (jcp.dimM_block * jcp.dimM_reg_block) * jcp.dimN_reg_block
+ * jcp.dimM_simd_block * typesize);
+ add(oreg_src, oreg_tile_block);
+ }
+
+ int last4dim = jcp.dimN_block * (jcp.dimM_block * jcp.dimM_reg_block)
+ * jcp.dimN_reg_block * jcp.dimM_simd_block * typesize;
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ int j_base_offset = j * alpha * last4dim;
+ int i_base_offset = i * last4dim;
+ vmovups(zmm_temp, ptr[oreg_src + j_base_offset + i_base_offset]);
+ vmovups(ptr[oreg_Ow + (j * alpha * simd_w + i * simd_w)
+ * typesize], zmm_temp);
+ }
+ }
+ };
+
+ auto store_dst = [=]() {
+ vpxord(zmm_zero, zmm_zero, zmm_zero);
+ mov(oreg_dst, ptr[param1 + GET_OFF(dst)]);
+ mov(oreg_O, ptr[param1 + GET_OFF(M)]);
+ mov(oreg_ydim, ptr[param1 + GET_OFF(tj)]);
+ shl(oreg_ydim, 2); // tj * tile_size (==4)
+ mov(oreg_xdim, ptr[param1 + GET_OFF(ti)]);
+ shl(oreg_xdim, 2); // ti * tilesize (==4)
+
+ if (with_bias)
+ mov(oreg_bias, ptr[param1 + GET_OFF(bias)]);
+
+ auto store_one = [=](int j, int i, bool is_aligned) {
+ auto zmm_O = Xbyak::Zmm(31);
+ auto zmm_relu_ns = Xbyak::Zmm(30);
+ auto xmm_relu_ns = Xbyak::Xmm(30);
+ int offset = (j * tile_size * simd_w + i * simd_w) * typesize;
+
+ vmovups(zmm_O, ptr[oreg_O + offset]);
+ if (is_fwd) {
+ if (with_bias) {
+ vaddps(zmm_O, zmm_O, ptr[oreg_bias]);
+ }
+ if (with_relu) {
+ if (jcp.eltwise.alpha == 0) {
+ vmaxps(zmm_O, zmm_O, zmm_zero);
+ } else {
+ Opmask kmask = Opmask(7);
+ mov(imm_addr64, float2int(jcp.eltwise.alpha));
+ vmovq(xmm_relu_ns, imm_addr64);
+ vbroadcastss(zmm_relu_ns, xmm_relu_ns);
+ vcmpps(kmask, zmm_O, zmm_zero, _cmp_lt_os);
+ vmulps(zmm_O | kmask, zmm_O, zmm_relu_ns);
+ }
+ }
+ }
+ if (with_sum) {
+ vaddps(zmm_O, zmm_O, ptr[oreg_out_j + oreg_temp]);
+ if (with_relu_postsum) // orig: with_relu_postsum
+ vmaxps(zmm_O, zmm_O, zmm_zero);
+ }
+ if (is_aligned)
+ vmovntps(ptr[oreg_out_j + oreg_temp], zmm_O);
+ else
+ vmovups(ptr[oreg_out_j + oreg_temp], zmm_O);
+ };
+
+ auto i_loop = [=](int j, bool is_aligned) {
+ for (int i = 0; i < tile_size; i++) {
+ Label next;
+ mov(oreg_temp, oreg_xdim);
+ add(oreg_temp, i);
+ cmp(oreg_temp, outw);
+ jge(next, T_NEAR);
+ shl(oreg_temp, 4 + 2); // * 16 * 4
+
+ store_one(j, i, is_aligned);
+
+ L(next);
+ }
+ };
+
+
+ for (int j = 0; j < tile_size; j++) {
+ Label next, unaligned;
+ mov(oreg_temp, oreg_ydim);
+ add(oreg_temp, j);
+ cmp(oreg_temp, outh);
+ jge(next, T_NEAR);
+
+ mov(oreg_out_j, oreg_dst);
+ imul(oreg_temp, oreg_temp, outw * simd_w * typesize);
+ add(oreg_out_j, oreg_temp);
+
+ test(oreg_dst, 63);
+ jnz(unaligned, T_NEAR);
+
+ i_loop(j, true);
+ jmp(next, T_NEAR);
+
+ L(unaligned);
+ i_loop(j, false);
+
+ L(next);
+ }
+ };
+
+ auto trans_O_4x4_3x3 = [=]() {
+ auto fma2 = [=](Zmm dst, Zmm v1, Zmm u1, Zmm v2, Zmm u2){
+ vmulps(dst, v1, u1);
+ vfmadd231ps(dst, v2, u2);
+ };
+ mov(oreg_Ow, ptr[param1 + GET_OFF(Mw)]);
+ mov(oreg_T, ptr[param1 + GET_OFF(T)]);
+ mov(oreg_O, ptr[param1 + GET_OFF(M)]);
+
+ for (int i = 0; i < alpha; i++) {
+ for (int j = 0; j < alpha; j++) {
+ vmovups(zmm_O(j), ptr[oreg_Ow + (j * alpha * simd_w
+ + i * simd_w) * typesize]);
+ }
+
+ vaddps(zmm_t(0), zmm_O(1), zmm_O(2));
+ vaddps(zmm_t(1), zmm_O(3), zmm_O(4));
+ vsubps(zmm_t(2), zmm_O(1), zmm_O(2));
+ vsubps(zmm_t(3), zmm_O(3), zmm_O(4));
+
+ vaddps(zmm_T(0), zmm_t(0), zmm_t(1));
+ vaddps(zmm_T(0), zmm_T(0), zmm_O(0));
+ fma2(zmm_T(1), zmm_t(2), zmm_G(0), zmm_t(3), zmm_G(1));
+ fma2(zmm_T(2), zmm_t(0), zmm_G(2), zmm_t(1), zmm_G(3));
+ fma2(zmm_T(3), zmm_t(2), zmm_G(4), zmm_t(3), zmm_G(5));
+ vaddps(zmm_T(3), zmm_T(3), zmm_O(5));
+
+ for (int j = 0; j < tile_size; j++) {
+ vmovups(ptr[oreg_T + (j * alpha * simd_w
+ + i * simd_w) * typesize], zmm_T(j));
+ }
+ }
+ for (int j = 0; j < tile_size; j++) {
+ for (int i = 0; i < alpha; i++) {
+ vmovups(zmm_T(i), ptr[oreg_T + (j * alpha * simd_w
+ + i * simd_w) * typesize]);
+ }
+ vaddps(zmm_t(0), zmm_T(1), zmm_T(2));
+ vaddps(zmm_t(1), zmm_T(3), zmm_T(4));
+ vsubps(zmm_t(2), zmm_T(1), zmm_T(2));
+ vsubps(zmm_t(3), zmm_T(3), zmm_T(4));
+
+ vaddps(zmm_O(0), zmm_t(0), zmm_t(1));
+ vaddps(zmm_O(0), zmm_O(0), zmm_T(0));
+ fma2(zmm_O(1), zmm_t(2), zmm_G(0), zmm_t(3), zmm_G(1));
+ fma2(zmm_O(2), zmm_t(0), zmm_G(2), zmm_t(1), zmm_G(3));
+ fma2(zmm_O(3), zmm_t(2), zmm_G(4), zmm_t(3), zmm_G(5));
+ vaddps(zmm_O(3), zmm_O(3), zmm_T(5));
+
+ for (int i = 0; i < tile_size; i++) {
+ vmovups(ptr[oreg_O + (j * tile_size * simd_w
+ + i * simd_w) * typesize], zmm_O(i));
+ }
+ }
+ };
+
+ auto inner_loops = [=]() {
+ init_G();
+ load_src();
+ trans_O_4x4_3x3();
+ store_dst();
+ };
+
+ preamble();
+ inner_loops();
+ postamble();
+}
+
+void _jit_avx512_core_fp32_wino_conv_4x3_data_kernel
+ ::input_transform_data_ker_generate()
+{
+ bool is_fwd = one_of(jcp.prop_kind,
+ mkldnn_forward_training, mkldnn_forward_inference);
+ int inpw = is_fwd ? jcp.iw : jcp.ow;
+ int inph = is_fwd ? jcp.ih : jcp.oh;
+ int l_pad = is_fwd ? jcp.l_pad : jcp.iw + jcp.r_pad - jcp.ow;
+ int t_pad = is_fwd ? jcp.t_pad : jcp.ih + jcp.t_pad - jcp.oh;
+ int wp_max = inpw + l_pad;
+ int hp_max = inph + t_pad;
+ bool not_tiled = jcp.sched_policy == WSCHED_DATA_W_S_G_D;
+ int G_size = 9;
+
+ auto zmm_zero = Xbyak::Zmm(0);
+ auto zmm_temp = Xbyak::Zmm(31);
+ auto zmm_G = [=](int i) {
+ return Xbyak::Zmm(1 + i);
+ };
+ auto zmm_I = [=](int i) {
+ return Xbyak::Zmm(1 + G_size + i);
+ };
+ auto zmm_T = [=](int i) {
+ return Xbyak::Zmm(1 + G_size + alpha + i);
+ };
+ auto zmm_t = [=](int i) {
+ return Xbyak::Zmm(1 + G_size + 2 * alpha + i);
+ };
+
+ auto init_G = [=]() {
+ mov(ireg_temp, ptr[param1 + GET_OFF(G)]);
+ for (int i = 0; i < G_size; i++) {
+ vbroadcastss(zmm_G(i), ptr[ireg_temp + i * typesize]);
+ }
+ };
+
+ auto load_src = [=]() {
+ mov(ireg_src, ptr[param1 + GET_OFF(src)]); // base addr of inp
+ mov(ireg_I, ptr[param1 + GET_OFF(M)]);
+
+ xor_(ireg_zero, ireg_zero);
+ vpxord(zmm_zero, zmm_zero, zmm_zero);
+
+ mov(ireg_ydim, ptr[param1 + GET_OFF(tj)]);
+ shl(ireg_ydim, 2); // tj * tile_size (==4)
+ mov(ireg_xdim, ptr[param1 + GET_OFF(ti)]);
+ shl(ireg_xdim, 2); // ti * tilesize (==4)
+
+ for (int j = 0; j < alpha; j++) {
+ mov(ireg_temp, ireg_ydim);
+ add(ireg_temp, j);
+
+ mov(ireg_mask_j, 0xffff);
+ cmp(ireg_temp, t_pad);
+ cmovl(ireg_mask_j, ireg_zero);
+ cmp(ireg_temp, hp_max);
+ cmovge(ireg_mask_j, ireg_zero);
+
+ sub(ireg_temp, t_pad);
+ imul(ireg_temp, ireg_temp, inpw * simd_w * typesize);
+ mov(ireg_inp_j, ireg_src);
+ add(ireg_inp_j, ireg_temp);
+
+ for (int i = 0; i < alpha; i++) {
+
+ mov(ireg_temp, ireg_xdim);
+ add(ireg_temp, i);
+
+ mov(ireg_mask, 0xffff);
+ cmp(ireg_temp, l_pad);
+ cmovl(ireg_mask, ireg_zero);
+ cmp(ireg_temp, wp_max);
+ cmovge(ireg_mask, ireg_zero);
+ and_(ireg_mask, ireg_mask_j);
+
+ sub(ireg_temp, l_pad);
+ shl(ireg_temp, 4 + 2);
+
+ vpxord(zmm_temp, zmm_temp, zmm_temp);
+ Opmask kmask = Opmask(7);
+ kmovw(kmask, ireg_mask_32);
+ vmovups(zmm_temp | kmask, ptr[ireg_inp_j + ireg_temp]);
+ vmovups(ptr[ireg_I + (j * alpha * simd_w + i * simd_w)
+ * typesize], zmm_temp);
+ }
+ }
+ };
+
+ auto store_Iw = [=]() {
+
+ mov(ireg_Iw, ptr[param1 + GET_OFF(Mw)]);
+ mov(ireg_output, ptr[param1 + GET_OFF(dst)]);
+
+ bool streamout
+ = jcp.dimN * jcp.dimK * alpha * alpha * sizeof(float)
+ > 2 * LLC_data_size
+ ? true : false;
+
+ if (not_tiled) {
+ mov(ireg_tile_block, ptr[param1 + GET_OFF(tile_block)]);
+ imul(ireg_tile_block, ireg_tile_block,
+ alpha * alpha * jcp.dimN_block * jcp.dimK_nb_block
+ * jcp.dimK_block * jcp.dimN_reg_block * jcp.dimK_reg_block
+ * typesize);
+ }
+
+ mov(ireg_nb_tile_block_ur, ptr[param1 + GET_OFF(nb_tile_block_ur)]);
+ imul(ireg_nb_tile_block_ur, ireg_nb_tile_block_ur,
+ jcp.dimK_nb_block * jcp.dimK_block * jcp.dimN_reg_block
+ * jcp.dimK_reg_block * typesize);
+
+ mov(ireg_tile_block_ur, ptr[param1 + GET_OFF(tile_block_ur)]);
+ imul(ireg_tile_block_ur, ireg_tile_block_ur,
+ jcp.dimK_reg_block * typesize);
+
+ add(ireg_output, ireg_nb_tile_block_ur);
+ add(ireg_output, ireg_tile_block_ur);
+ if (not_tiled)
+ add(ireg_output, ireg_tile_block);
+
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ vmovups(zmm_temp,ptr[ireg_Iw + (j * alpha * simd_w
+ + i * simd_w) * typesize]);
+
+ int j_base_offset =
+ j * alpha * jcp.dimN_block * jcp.dimK_nb_block
+ * jcp.dimK_block * jcp.dimN_reg_block * jcp.dimK_reg_block
+ * typesize;
+ int i_base_offset =
+ i * jcp.dimN_block * jcp.dimK_nb_block * jcp.dimK_block
+ * jcp.dimN_reg_block * jcp.dimK_reg_block * typesize;
+
+ if (not_tiled && streamout)
+ vmovntps(ptr[ireg_output + j_base_offset + i_base_offset],
+ zmm_temp);
+ else
+ vmovups(ptr[ireg_output + j_base_offset + i_base_offset],
+ zmm_temp);
+ }
+ }
+ };
+
+ auto fma4 = [=](Zmm dst, Zmm a, Zmm b, Zmm c) {
+ vmulps(zmm_temp, a, b);
+ vaddps(dst, zmm_temp, c);
+ };
+
+ auto trans_I_4x4_3x3 = [=]() {
+ mov(ireg_Iw, ptr[param1 + GET_OFF(Mw)]);
+ mov(ireg_T, ptr[param1 + GET_OFF(T)]);
+ mov(ireg_I, ptr[param1 + GET_OFF(M)]);
+
+ mov(ireg_output, ptr[param1 + GET_OFF(dst)]); // for prefetch
+ for (int i = 0; i < alpha; i++) {
+ for (int idx = 0; idx < alpha; idx++) {
+ vmovups(zmm_I(idx), ptr[ireg_I + (idx * alpha * simd_w
+ + i * simd_w) * typesize]);
+ int j_base_offset =
+ i * alpha * jcp.dimN_block * jcp.dimK_nb_block
+ * jcp.dimK_block * jcp.dimN_reg_block * jcp.dimK_reg_block
+ * typesize;
+ int idx_base_offset =
+ idx * jcp.dimN_block * jcp.dimK_nb_block * jcp.dimK_block
+ * jcp.dimN_reg_block * jcp.dimK_reg_block * typesize;
+ prefetcht0(ptr[ireg_output + j_base_offset + idx_base_offset]);
+ }
+
+ fma4(zmm_t(0), zmm_I(2), zmm_G(0), zmm_I(4));
+ fma4(zmm_t(1), zmm_I(1), zmm_G(0), zmm_I(3));
+ fma4(zmm_t(2), zmm_I(2), zmm_G(1), zmm_I(4));
+ fma4(zmm_t(3), zmm_I(1), zmm_G(1), zmm_I(3));
+ fma4(zmm_t(4), zmm_I(0), zmm_G(2), zmm_I(4));
+ fma4(zmm_t(5), zmm_I(1), zmm_G(2), zmm_I(5));
+
+ fma4(zmm_T(0), zmm_I(2), zmm_G(3), zmm_t(4));
+ fma4(zmm_T(1), zmm_t(1), zmm_G(4), zmm_t(0));
+ fma4(zmm_T(2), zmm_t(1), zmm_G(5), zmm_t(0));
+ fma4(zmm_T(3), zmm_t(3), zmm_G(6), zmm_t(2));
+ fma4(zmm_T(4), zmm_t(3), zmm_G(7), zmm_t(2));
+ fma4(zmm_T(5), zmm_I(3), zmm_G(8), zmm_t(5));
+
+ for (int idx = 0; idx < alpha; idx++) {
+ vmovups(ptr[ireg_T + (idx * alpha * simd_w + i * simd_w)
+ * typesize],zmm_T(idx));
+ }
+ }
+ for (int i = 0; i < alpha; i++) {
+ for (int idx = 0; idx < alpha; idx++) {
+ vmovups(zmm_T(idx), ptr[ireg_T + (i * alpha * simd_w + idx
+ * simd_w) * typesize]);
+ }
+
+ fma4(zmm_t(0), zmm_T(2), zmm_G(0), zmm_T(4));
+ fma4(zmm_t(1), zmm_T(1), zmm_G(0), zmm_T(3));
+ fma4(zmm_t(2), zmm_T(2), zmm_G(1), zmm_T(4));
+ fma4(zmm_t(3), zmm_T(1), zmm_G(1), zmm_T(3));
+ fma4(zmm_t(4), zmm_T(0), zmm_G(2), zmm_T(4));
+ fma4(zmm_t(5), zmm_T(1), zmm_G(2), zmm_T(5));
+
+ fma4(zmm_I(0), zmm_T(2), zmm_G(3), zmm_t(4));
+ fma4(zmm_I(1), zmm_t(1), zmm_G(4), zmm_t(0));
+ fma4(zmm_I(2), zmm_t(1), zmm_G(5), zmm_t(0));
+ fma4(zmm_I(3), zmm_t(3), zmm_G(6), zmm_t(2));
+ fma4(zmm_I(4), zmm_t(3), zmm_G(7), zmm_t(2));
+ fma4(zmm_I(5), zmm_T(3), zmm_G(8), zmm_t(5));
+
+ for (int idx = 0; idx < alpha; idx++) {
+ vmovups(ptr[ireg_Iw + (i * alpha * simd_w + idx * simd_w)
+ * typesize],zmm_I(idx));
+ }
+ }
+ };
+
+ auto inner_loops = [=]() {
+ init_G();
+ load_src();
+ trans_I_4x4_3x3();
+ store_Iw();
+ };
+
+ preamble();
+ inner_loops();
+ postamble();
+}
+
+status_t _jit_avx512_core_fp32_wino_conv_4x3_data_kernel::init_conf_common(
+ jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d)
+{
+ if (!mayiuse(avx512_core)) {
+ return status::unimplemented;
+ }
+
+ jcp.nthr = mkldnn_get_max_threads();
+
+ jcp.ver = ver_avx512_core;
+ jcp.prop_kind = cd.prop_kind;
+
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.ih = src_d.dims()[2];
+ jcp.iw = src_d.dims()[3];
+ jcp.oh = dst_d.dims()[2];
+ jcp.ow = dst_d.dims()[3];
+ jcp.kh = weights_d.dims()[with_groups + 2];
+ jcp.kw = weights_d.dims()[with_groups + 3];
+ jcp.t_pad = cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][1];
+ jcp.stride_h = cd.strides[0];
+ jcp.stride_w = cd.strides[1];
+ jcp.dilate_h = cd.dilates[0];
+ jcp.dilate_w = cd.dilates[1];
+ jcp.r_pad = nstl::max(
+ 0, (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad);
+ jcp.b_pad = nstl::max(
+ 0, (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad);
+ jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad;
+ jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad;
+ jcp.ohp = jcp.oh;
+ jcp.owp = jcp.ow;
+
+ bool ok_to_pad_channels = jcp.ngroups == 1;
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ jcp.ic = rnd_up(jcp.ic, simd_w);
+ }
+
+ // Checking conditions not supported by these kernels
+ if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto,
+ is_winograd_faster_than_direct(jcp)))
+ return status::unimplemented;
+
+ if (jcp.ngroups != 1)
+ return status::unimplemented;
+ if ((jcp.kh != 3) || (jcp.kw != 3))
+ return status::unimplemented;
+ if ((jcp.dilate_h != 0) || (jcp.dilate_w != 0))
+ return status::unimplemented;
+ if ((jcp.stride_h != 1) || (jcp.stride_w != 1))
+ return status::unimplemented;
+ if ((jcp.ic % simd_w) != 0 || (jcp.oc % simd_w) != 0)
+ return status::unimplemented;
+
+ format_tag_t dat_tag = nChw16c;
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag);
+
+ if (jcp.src_tag != dat_tag) return status::unimplemented;
+ if (jcp.dst_tag != dat_tag) return status::unimplemented;
+
+ if (!one_of(weights_d.format_kind(), format_kind::any, format_kind::wino)) {
+ format_tag_t wei_tag = with_groups ? gOIhw16i16o : OIhw16i16o;
+ jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag);
+ if (jcp.wei_tag != wei_tag)
+ return status::unimplemented;
+ }
+
+ bool layout_consistency = true
+ && jcp.ic <= src_d.padded_dims()[1]
+ && jcp.oc <= dst_d.padded_dims()[1]
+ && (one_of(weights_d.format_kind(),
+ format_kind::any, format_kind::wino)
+ || (jcp.ic <= weights_d.padded_dims()[with_groups + 1]
+ && jcp.oc <= weights_d.padded_dims()[with_groups + 0]));
+ if (!layout_consistency)
+ return status::unimplemented;
+
+ return status::success;
+}
+
+void set_kernel_dims_reg_block(jit_conv_winograd_conf_t &jcp) {
+
+ /* ----------- dimM reg block ---------------------*/
+ auto test_cond_dimM_reg_block = [](jit_conv_winograd_conf_t &jcp,
+ int dimM_reg_block, int current_best) {
+ int max_dimM_reg_block = jcp.kernel_kind == embd_bcast ? 1 : 4;
+ return (dimM_reg_block >= 1)
+ && (dimM_reg_block <= max_dimM_reg_block )
+ && (dimM_reg_block > current_best);
+ };
+ jcp.dimM_reg_block = get_divisor_satisfying_cond(jcp,
+ jcp.dimM/jcp.dimM_simd_block, 1, test_cond_dimM_reg_block);
+
+ /* ----------- dimN reg block ---------------------*/
+
+ auto test_cond_dimN_reg_block = [](jit_conv_winograd_conf_t &jcp,
+ int dimN_reg_block, int current_best) {
+ return jcp.kernel_kind == embd_bcast
+ ? dimN_reg_block < jcp.nb_reg && dimN_reg_block > current_best
+ : dimN_reg_block >= 1
+ && (dimN_reg_block * jcp.dimM_reg_block + dimN_reg_block)
+ < jcp.nb_reg
+ && dimN_reg_block > current_best;
+ };
+ jcp.dimN_reg_block = get_divisor_satisfying_cond(jcp,
+ jcp.dimN, 1, test_cond_dimN_reg_block);
+}
+
+status_t set_wsched_DATA_W_SGD_avx512_core(jit_conv_winograd_conf_t &jcp) {
+ if (jcp.ver != ver_avx512_core)
+ return status::unimplemented;
+
+ jcp.kernel_kind = embd_bcast;
+
+ set_kernel_dims_reg_block(jcp);
+
+ /*-------------- L2 blocking for dimN block ---------*/
+
+ auto test_cond_dimN_block = [](jit_conv_winograd_conf_t &jcp,
+ int dimN_block, int current_best) {
+ return check_L2_block_per_thread(jcp, dimN_block, 0.1, 2.0)
+ && (dimN_block > current_best)
+ && ((jcp.dimN / dimN_block / jcp.dimN_reg_block)
+ >= 1.5 * mkldnn_get_max_threads());
+ };
+
+ jcp.dimN_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimN / jcp.dimN_reg_block, 1, test_cond_dimN_block);
+ jcp.dimN_nb_block = jcp.dimN / jcp.dimN_block / jcp.dimN_reg_block;
+
+ if (check_L2_block_per_thread(jcp, jcp.dimN_block, 0.1, 3.2)
+ && (jcp.dimN_nb_block >= 1.5 * mkldnn_get_max_threads())) {
+
+ /* ------------------- L1 blocking for GEMM --------------*/
+ /* -------------------- Choose dimK block ----------------*/
+
+ auto test_cond_dimK_block = [](jit_conv_winograd_conf_t &jcp,
+ int dimK_block, int current_best) {
+ return check_L1_block_gemm(jcp, dimK_block, 1, 0.1, 0.5)
+ && (dimK_block > current_best);
+ };
+
+ jcp.dimK_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimK / jcp.dimK_reg_block, 1, test_cond_dimK_block);
+
+ if (check_L1_block_gemm(jcp, jcp.dimK_block, 1, 0.1, 1.0)) {
+ jcp.dimK_nb_block = jcp.dimK / jcp.dimK_block / jcp.dimK_reg_block;
+
+ /* -------------- Choose dimM block -------------------*/
+ auto test_cond_dimM_block = [](jit_conv_winograd_conf_t &jcp,
+ int dimM_block, int current_best) {
+ return check_L1_block_gemm(jcp, jcp.dimK_block, dimM_block,
+ 0.2, 0.5) && (dimM_block > current_best);
+ };
+
+ jcp.dimM_block = get_divisor_satisfying_cond(jcp,
+ jcp.dimM / (jcp.dimM_simd_block * jcp.dimM_reg_block), 1,
+ test_cond_dimM_block);
+ jcp.dimM_nb_block = jcp.dimM / jcp.dimM_block / jcp.dimM_reg_block
+ / jcp.dimM_simd_block;
+
+ jcp.sched_policy = WSCHED_DATA_W_SGD;
+ return status::success;
+ }
+
+ }
+ return status::unimplemented;
+}
+
+void set_kernel_blocking_DATA_W_S_G_D(jit_conv_winograd_conf_t &jcp) {
+
+ set_kernel_dims_reg_block(jcp);
+
+ //********************* Choosing dimK_block **********************//
+ auto test_cond1_dimK_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) {
+ return check_cond1(jcp.dimN_reg_block, dimK_block, jcp.dimK_reg_block,
+ 1, jcp.dimM_reg_block, jcp.dimM_simd_block, .75f)
+ && (dimK_block > current_best);
+ };
+
+ auto test_cond1_bis_dimK_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimK_block, int current_best) {
+ return check_cond1_bis(jcp.dimN_reg_block, dimK_block,
+ jcp.dimK_reg_block, 1, jcp.dimM_reg_block,
+ jcp.dimM_simd_block, .9f)
+ && (dimK_block > current_best);
+ };
+
+ jcp.dimK_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimK / jcp.dimK_reg_block, 1, test_cond1_bis_dimK_block);
+ // If we are not able to use streams, we fall back to condition [1]
+ if (jcp.dimK_block < jcp.dimK / jcp.dimK_reg_block)
+ jcp.dimK_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimK / jcp.dimK_reg_block, 1, test_cond1_dimK_block);
+ jcp.dimK_nb_block = (jcp.dimK / jcp.dimK_reg_block) / jcp.dimK_block;
+
+ //********************* Choosing dimM_block **********************//
+ auto test_cond1_dimM_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimM_block, int current_best) {
+ return check_cond1(jcp.dimN_reg_block, jcp.dimK_block,
+ jcp.dimK_reg_block, dimM_block, jcp.dimM_reg_block,
+ jcp.dimM_simd_block, .5f)
+ && (dimM_block > current_best);
+ };
+
+ auto test_cond1_bis_dimM_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimM_block, int current_best) {
+ return check_cond1_bis(jcp.dimN_reg_block, jcp.dimK_block,
+ jcp.dimK_reg_block, dimM_block, jcp.dimM_reg_block,
+ jcp.dimM_simd_block, .3f)
+ && (dimM_block > current_best);
+ };
+
+ if (jcp.dimK_block < jcp.dimK / jcp.dimK_reg_block)
+ jcp.dimM_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimM / (jcp.dimM_simd_block*jcp.dimM_reg_block), 1,
+ test_cond1_dimM_block);
+ else
+ jcp.dimM_block = get_divisor_satisfying_cond(jcp,
+ jcp.dimM / (jcp.dimM_simd_block*jcp.dimM_reg_block), 1,
+ test_cond1_bis_dimM_block);
+ jcp.dimM_nb_block = jcp.dimM / (jcp.dimM_simd_block * jcp.dimM_block
+ * jcp.dimM_reg_block);
+
+ //******************* Choosing dimN_block *******************//
+ auto test_cond2_dimN_block = [](
+ jit_conv_winograd_conf_t &jcp, int dimN_block, int current_best) {
+ return check_cond2(dimN_block, jcp.dimN_reg_block, jcp.dimK_nb_block,
+ jcp.dimK_block, jcp.dimK_reg_block, jcp.dimM_block,
+ jcp.dimM_reg_block, jcp.dimM_simd_block, .9f)
+ && (dimN_block > current_best);
+ };
+
+ jcp.dimN_block = get_divisor_satisfying_cond(
+ jcp, jcp.dimN / jcp.dimN_reg_block, 1, test_cond2_dimN_block);
+ jcp.dimN_nb_block = jcp.dimN / (jcp.dimN_reg_block * jcp.dimN_block);
+}
+
+status_t set_wsched_DATA_W_S_G_D_avx512_core(jit_conv_winograd_conf_t &jcp) {
+
+ jcp.kernel_kind = expl_bcast;
+ set_kernel_blocking_DATA_W_S_G_D(jcp);
+ if (!(check_kernel_cond(jcp.dimM_block, jcp.dimM_reg_block,
+ jcp.dimM_simd_block, jcp.dimN_block, jcp.dimN_reg_block, jcp.dimK,
+ .1f, .35f))) {
+ jcp.kernel_kind = embd_bcast;
+ set_kernel_blocking_DATA_W_S_G_D(jcp);
+ }
+ jcp.sched_policy = WSCHED_DATA_W_S_G_D;
+ return status::success;
+}
+
+status_t _jit_avx512_core_fp32_wino_conv_4x3_data_kernel::init_conf_kernel(
+ jit_conv_winograd_conf_t &jcp, int dimM, int dimN, int dimK)
+{
+ jcp.nb_reg = 32;
+ jcp.dimN = dimN;
+ jcp.dimK = dimK;
+ jcp.dimM = dimM;
+ jcp.sched_policy = WSCHED_INVALID;
+
+ jcp.dimK_reg_block = 16;
+ jcp.dimM_simd_block = 16;
+
+ if (jcp.kernel_kind == embd_bcast) {
+ jcp.dimM_reg_block = 1;
+ }
+
+ if (!(set_wsched_DATA_W_SGD_avx512_core(jcp) == status::success))
+ set_wsched_DATA_W_S_G_D_avx512_core(jcp);
+
+ assert(jcp.sched_policy != WSCHED_INVALID);
+ return status::success;
+}
+
+bool jit_avx512_core_fp32_wino_conv_4x3_fwd_kernel::post_ops_ok(
+ jit_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ const auto &p = attr.post_ops_;
+
+ auto is_relu = [&](int idx) { return p.entry_[idx].is_relu(); };
+ auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); };
+
+ switch (p.len_) {
+ case 0: return true; // no post_ops
+ case 1: return is_relu(0) || is_sum(0); // relu or sum
+ case 2: return (is_sum(0) && is_relu(1))
+ || (is_relu(0) && is_sum(1)); // sum->relu or relu->sum
+ case 3: return is_relu(0) && is_sum(1) && is_relu(2); // relu->sum->relu
+ default: return false;
+ }
+
+ return false;
+}
+
+status_t jit_avx512_core_fp32_wino_conv_4x3_fwd_kernel::init_conf(
+ jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_t &src_md, memory_desc_t &weights_md,
+ const memory_desc_t &dst_md, const primitive_attr_t &attr) {
+
+ status_t st = init_conf_common(jcp, cd, src_md, weights_md, dst_md);
+
+ if (st != status::success)
+ return st;
+
+ // Winograd specific initialization
+ jcp.itiles = (jcp.ow + tile_size - 1) / tile_size;
+ jcp.jtiles = (jcp.oh + tile_size - 1) / tile_size;
+ jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles;
+
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ const int eltwise_ind = p.find(primitive_kind::eltwise, 0, 1);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise)
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+
+ jcp.with_sum = p.find(primitive_kind::sum, 0) != -1;
+ jcp.with_relu_postsum = p.find(primitive_kind::eltwise, 1) != -1;
+
+ status_t res = init_conf_kernel(jcp, jcp.oc, jcp.ntiles, jcp.ic);
+
+ jcp.ic_simd_block = jcp.dimK_reg_block;
+ jcp.ic_block = jcp.dimK_block;
+ jcp.nb_ic = jcp.dimK_nb_block;
+ jcp.oc_simd_block = jcp.dimM_simd_block;
+ jcp.oc_block = jcp.dimM_block;
+ jcp.oc_reg_block = jcp.dimM_reg_block;
+ jcp.ic_reg_block = 1;
+ jcp.nb_oc = jcp.dimM_nb_block;
+ jcp.tile_block_ur = jcp.dimN_reg_block;
+ jcp.nb_tile_block_ur = jcp.dimN_block;
+ jcp.tile_block = jcp.dimN_nb_block;
+
+ /* re-create weights primitive descriptor
+ and set weights wino_blocking */
+ if (cd.prop_kind == mkldnn_forward_inference) {
+ memory_desc_t expect_wei_md = weights_md;
+
+ expect_wei_md.format_kind = format_kind::wino;
+ expect_wei_md.data_type = data_type::f32;
+ mkldnn_wino_desc_t &wd = expect_wei_md.format_desc.wino_desc;
+ wd.wino_format = mkldnn_wino_wei_OBaaIBOIio;
+ wd.r = 3;
+ wd.alpha = 6;
+
+ wd.ic = jcp.ic;
+ wd.oc = jcp.oc;
+ wd.ic_block = jcp.dimK_reg_block;
+ wd.oc_block = jcp.dimM_simd_block;
+ wd.ic2_block = jcp.dimK_block;
+ wd.oc2_block = jcp.dimM_block * jcp.dimM_reg_block;
+ size_t max_size = sizeof(float) * wd.alpha * wd.alpha * jcp.ic * jcp.oc;
+ wd.size = max_size;
+ wd.adj_scale = 1.f;
+
+ if (weights_md.format_kind == format_kind::any)
+ weights_md = expect_wei_md;
+ if (weights_md != expect_wei_md)
+ return status::unimplemented;
+ }
+
+ return res;
+}
+
+status_t jit_avx512_core_fp32_wino_conv_4x3_bwd_data_kernel::init_conf(
+ jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_wrapper &diff_src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &diff_dst_d)
+{
+ status_t st = init_conf_common(jcp, cd, diff_src_d, weights_d, diff_dst_d);
+
+ if (st != status::success)
+ return st;
+
+ jcp.itiles = (jcp.iw + tile_size - 1) / tile_size;
+ jcp.jtiles = (jcp.ih + tile_size - 1) / tile_size;
+ jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles;
+
+ status_t res = init_conf_kernel(jcp, jcp.ic, jcp.ntiles, jcp.oc);
+
+ jcp.oc_simd_block = jcp.dimK_reg_block;
+ jcp.oc_block = jcp.dimK_block;
+ jcp.nb_oc = jcp.dimK_nb_block;
+ jcp.ic_simd_block = jcp.dimM_simd_block;
+ jcp.ic_block = jcp.dimM_block;
+ jcp.ic_reg_block = jcp.dimM_reg_block;
+ jcp.oc_reg_block = 1;
+ jcp.nb_ic = jcp.dimM_nb_block;
+ jcp.tile_block_ur = jcp.dimN_reg_block;
+ jcp.nb_tile_block_ur = jcp.dimN_block;
+ jcp.tile_block = jcp.dimN_nb_block;
+
+ return res;
+}
+
+void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel::
+src_transform_generate() {
+ constexpr int G_size = 9;
+ const size_t ifwp = jcp.iw + jcp.l_pad;
+ const size_t ifhp = jcp.ih + jcp.t_pad;
+
+ auto zmm_G = [=](int i) {
+ return Xbyak::Zmm(i);
+ };
+ auto zmm_I = [=](int i) {
+ return Xbyak::Zmm(G_size + i);
+ };
+ auto zmm_T = [=](int i) {
+ return Xbyak::Zmm(G_size + alpha + i);
+ };
+ auto zmm_t = [=](int i) {
+ return Xbyak::Zmm(G_size + 2 * alpha + i);
+ };
+
+ auto init_G = [=]() {
+ mov(reg_G, ptr[reg_transp + GET_OFF(G)]);
+ for (int i = 0; i < G_size; i++) {
+ vbroadcastss(zmm_G(i), ptr[reg_G + i * typesize]);
+ }
+ };
+
+ auto load_src = [=]() {
+ mov(reg_I, ptr[reg_transp + GET_OFF(M)]);
+ xor_(reg_zero, reg_zero);
+
+ mov(reg_ydim, reg_tj);
+ shl(reg_ydim, 2); //tj * tile_size(=4)
+
+ for (int j = 0; j < alpha; j++) {
+ /* check if tile index is within physical spatial boundaries*/
+ mov(reg_maskj, 0xffff);
+ cmp(reg_ydim, jcp.t_pad);
+ cmovl(reg_maskj, reg_zero);
+ cmp(reg_ydim, ifhp);
+ cmovge(reg_maskj, reg_zero);
+
+ /*address offset for tile in src*/
+ mov(reg_src_offset, reg_ydim);
+ sub(reg_src_offset, jcp.t_pad); // tj*tile_size - t_pad
+ imul(reg_src_offset, reg_src_offset, jcp.iw);
+
+ mov(reg_xdim, reg_ti);
+ shl(reg_xdim, 2); // xdim = ti * tile_size
+
+ add(reg_src_offset, reg_xdim);
+ sub(reg_src_offset, jcp.l_pad);
+ imul(reg_src_offset, reg_src_offset, simd_w * typesize);
+ for (int i = 0; i < alpha; i++) {
+ /* check if tile index is within physical spatial boundaries*/
+ mov(reg_maski, 0xffff);
+ cmp(reg_xdim, jcp.l_pad);
+ cmovl(reg_maski, reg_zero);
+ cmp(reg_xdim, ifwp);
+ cmovge(reg_maski, reg_zero);
+ and_(reg_maski, reg_maskj);
+
+ Opmask kmask_src = Xbyak::Opmask(7);
+ auto zmm_src = Xbyak::Zmm(31);
+ kmovw(kmask_src, reg_maski_32);
+ vpxord(zmm_src, zmm_src, zmm_src);
+ vmovups(zmm_src | kmask_src, ptr[reg_src + reg_src_offset]);
+ vmovups(ptr[reg_I], zmm_src);
+
+ add(reg_xdim, 1); //xdim = ti * tile_size + i
+ add(reg_src_offset, simd_w * typesize);
+ add(reg_I, simd_w * typesize);
+ }
+ add(reg_ydim, 1);
+ }
+ };
+
+ auto fma4 = [=](Xbyak::Zmm dst, Xbyak::Zmm a, Xbyak::Zmm b, Xbyak::Zmm c) {
+ vmovups(dst, c);
+ vfmadd231ps(dst, a, b);
+ };
+
+ auto trans_I_3x3_4x4 = [=]() {
+ //Use 24 registers
+ mov(reg_I, ptr[reg_transp + GET_OFF(M)]);
+ mov(reg_T, ptr[reg_transp + GET_OFF(T)]);
+ for (int i = 0; i < alpha; i++) {
+ for (int j = 0; j < alpha; j++) {
+ size_t I_off = (j * alpha + i) * simd_w * typesize;
+ vmovups(zmm_I(j), ptr[reg_I + I_off]);
+ }
+
+ fma4(zmm_t(0), zmm_I(2), zmm_G(0), zmm_I(4));
+ fma4(zmm_t(1), zmm_I(1), zmm_G(0), zmm_I(3));
+ fma4(zmm_t(2), zmm_I(2), zmm_G(1), zmm_I(4));
+ fma4(zmm_t(3), zmm_I(1), zmm_G(1), zmm_I(3));
+ fma4(zmm_t(4), zmm_I(0), zmm_G(2), zmm_I(4));
+ fma4(zmm_t(5), zmm_I(1), zmm_G(2), zmm_I(5));
+
+ fma4(zmm_T(0), zmm_I(2), zmm_G(3), zmm_t(4));
+ fma4(zmm_T(1), zmm_t(1), zmm_G(4), zmm_t(0));
+ fma4(zmm_T(2), zmm_t(1), zmm_G(5), zmm_t(0));
+ fma4(zmm_T(3), zmm_t(3), zmm_G(6), zmm_t(2));
+ fma4(zmm_T(4), zmm_t(3), zmm_G(7), zmm_t(2));
+ fma4(zmm_T(5), zmm_I(3), zmm_G(8), zmm_t(5));
+
+ for (int j = 0; j < alpha; j++) {
+ vmovups(ptr[reg_T + (j * alpha + i) * simd_w * typesize],
+ zmm_T(j));
+ }
+
+ }
+
+ for (int j = 0; j < alpha; j++) {
+ for (int i = 0; i < alpha; i++) {
+ vmovups(zmm_T(i), ptr[reg_T + (j * alpha + i) * simd_w * typesize]);
+ }
+
+ fma4(zmm_t(0), zmm_T(2), zmm_G(0), zmm_T(4));
+ fma4(zmm_t(1), zmm_T(1), zmm_G(0), zmm_T(3));
+ fma4(zmm_t(2), zmm_T(2), zmm_G(1), zmm_T(4));
+ fma4(zmm_t(3), zmm_T(1), zmm_G(1), zmm_T(3));
+ fma4(zmm_t(4), zmm_T(0), zmm_G(2), zmm_T(4));
+ fma4(zmm_t(5), zmm_T(1), zmm_G(2), zmm_T(5));
+
+ fma4(zmm_I(0), zmm_T(2), zmm_G(3), zmm_t(4));
+ fma4(zmm_I(1), zmm_t(1), zmm_G(4), zmm_t(0));
+ fma4(zmm_I(2), zmm_t(1), zmm_G(5), zmm_t(0));
+ fma4(zmm_I(3), zmm_t(3), zmm_G(6), zmm_t(2));
+ fma4(zmm_I(4), zmm_t(3), zmm_G(7), zmm_t(2));
+ fma4(zmm_I(5), zmm_T(3), zmm_G(8), zmm_t(5));
+
+ for (int i = 0; i < alpha; i++) {
+ size_t dst_off = (j * alpha * jcp.ic_block
+ * jcp.nb_tile_block_ur * jcp.tile_block_ur
+ + i * jcp.ic_block * jcp.nb_tile_block_ur * jcp.tile_block_ur)
+ * simd_w * typesize;
+ vmovups(ptr[reg_dst + dst_off], zmm_I(i));
+ }
+ }
+ };
+
+ auto compute_transform_SDGtWo = [=]() {
+ mov(reg_ti, ptr[reg_transp + GET_OFF(ti)]);
+ mov(reg_tj, ptr[reg_transp + GET_OFF(tj)]);
+ mov(reg_src, ptr[reg_transp + GET_OFF(src)]);
+ mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]);
+ xor_(reg_tile_count, reg_tile_count);
+ Label loop_mb, loop_jtiles, loop_itiles, done;
+ L(loop_mb);
+ {
+ L(loop_jtiles);
+ {
+ L(loop_itiles);
+ {
+ load_src();
+
+ trans_I_3x3_4x4();
+
+ add(reg_tile_count, 1);
+ cmp(reg_tile_count, jcp.nb_tile_block_ur * jcp.tile_block_ur);
+ jge(done);
+
+ add(reg_dst, simd_w * typesize);
+ add(reg_ti, 1);
+ cmp(reg_ti, jcp.itiles);
+ jl(loop_itiles);
+ }
+ xor_(reg_ti, reg_ti);
+ add(reg_tj, 1);
+ cmp(reg_tj, jcp.jtiles);
+ jl(loop_jtiles);
+ }
+ xor_(reg_tj, reg_tj);
+ add(reg_src, jcp.ic * jcp.iw * jcp.ih * typesize);
+ jmp(loop_mb);
+ }
+ L(done);
+ };
+
+ auto compute_transform = [=]() {
+ mov(reg_src, ptr[reg_transp + GET_OFF(src)]);
+ xor_(reg_ti, reg_ti);
+ xor_(reg_tj, reg_tj);
+
+ mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]);
+ mov(reg_tile_count, ptr[reg_transp + GET_OFF(tile_count)]);
+ imul(reg_temp, reg_tile_count, simd_w * typesize);
+ add(reg_dst, reg_temp);
+
+ Label loop_jtiles, loop_itiles, next_tile_block, next_tile;
+ L(loop_jtiles);
+
+ {
+ L(loop_itiles);
+ {
+ load_src();
+
+ trans_I_3x3_4x4();
+
+ add(reg_tile_count, 1);
+ cmp(reg_tile_count, jcp.nb_tile_block_ur * jcp.tile_block_ur);
+ jge(next_tile_block);
+ add(reg_dst, simd_w * typesize);
+ jmp(next_tile);
+
+ L(next_tile_block);
+ sub(reg_dst, (jcp.nb_tile_block_ur * jcp.tile_block_ur - 1)
+ * simd_w * typesize);
+ size_t tblk_off = alpha * alpha * jcp.ic_block
+ * jcp.nb_tile_block_ur * jcp.tile_block_ur
+ * simd_w * typesize;
+ add(reg_dst, tblk_off);
+ xor_(reg_tile_count, reg_tile_count);
+
+ L(next_tile);
+ add(reg_ti, 1);
+ cmp(reg_ti, jcp.itiles);
+ jl(loop_itiles);
+ }
+ xor_(reg_ti, reg_ti);
+ add(reg_tj, 1);
+ cmp(reg_tj, jcp.jtiles);
+ jl(loop_jtiles);
+ }
+ };
+
+ preamble();
+ init_G();
+ if (jcp.sched_policy == WSCHED_WEI_SDGtWo)
+ compute_transform_SDGtWo();
+ else
+ compute_transform();
+ postamble();
+}
+
+void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel::
+diff_dst_transform_generate(bool with_bias) {
+
+ constexpr int G_size = 8;
+ auto zmm_G = [](int i) {
+ return Xbyak::Zmm(31);
+ };
+
+ auto zmm_src = [=](int j, int i) {
+ return Xbyak::Zmm(G_size + j * 4 + i);
+ };
+
+ auto zmm_bias = Xbyak::Zmm(31);
+
+ auto load_src = [=]() {
+ if (with_bias) vmovups(zmm_bias, ptr[reg_bias]);
+ mov(reg_ydim, reg_tj);
+ shl(reg_ydim, 2); //tj * tile_size(=4)
+ for (int j = 0; j < tile_size; j++) {
+ /* check if tile index is within physical spatial boundaries*/
+ mov(reg_maskj, 0xffff);
+ cmp(reg_ydim, jcp.oh);
+ cmovge(reg_maskj, reg_zero);
+
+ /*address offset for tile in src*/
+ mov(reg_src_offset, reg_ydim);
+ imul(reg_src_offset, reg_src_offset, jcp.ow);
+
+ mov(reg_xdim, reg_ti);
+ shl(reg_xdim, 2); // xdim = ti * tile_size
+
+ add(reg_src_offset, reg_xdim);
+ imul(reg_src_offset, reg_src_offset, simd_w * typesize);
+ for (int i = 0; i < tile_size; i++) {
+ /* check if tile index is within physical spatial boundaries*/
+ mov(reg_maski, 0xffff);
+ cmp(reg_xdim, jcp.ow);
+ cmovge(reg_maski, reg_zero);
+ and_(reg_maski, reg_maskj);
+
+ Opmask kmask_src = Xbyak::Opmask(7);
+ kmovw(kmask_src, reg_maski_32);
+ vpxord(zmm_src(j, i), zmm_src(j, i), zmm_src(j, i));
+ vmovups(zmm_src(j, i) | kmask_src, ptr[reg_src + reg_src_offset]);
+ if (with_bias) vaddps(zmm_bias | kmask_src, zmm_bias,
+ ptr[reg_src + reg_src_offset]);
+
+ add(reg_xdim, 1); //xdim = ti * tile_size + i
+ add(reg_src_offset, simd_w * typesize);
+ }
+ add(reg_ydim, 1);
+ }
+ if(with_bias) vmovups(ptr[reg_bias], zmm_bias);
+ };
+
+ auto zmm_t = [=](int i) {
+ return Xbyak::Zmm(G_size + 16 + i);
+ };
+
+ auto zmm_T = [=](int j, int i) {
+ return Xbyak::Zmm(j * 4 + i);
+ };
+
+ auto movps = [=](Xbyak::Reg64 reg_dst, size_t dst_off, Xbyak::Zmm a) {
+ if (jcp.sched_policy == WSCHED_WEI_SDGtWo)
+ vmovups(ptr[reg_dst + dst_off], a);
+ else
+ vmovntps(ptr[reg_dst + dst_off], a);
+ };
+
+ auto trans_W_3x3_4x4 = [=]() {
+ mov(reg_G, ptr[reg_transp + GET_OFF(G)]);
+ for (int i = 0; i < tile_size; i++) {
+ vbroadcastss(zmm_G(0), ptr[reg_G]);
+ vmulps(zmm_t(0), zmm_src(2, i), zmm_G(0));
+
+ vbroadcastss(zmm_G(1), ptr[reg_G + typesize]);
+ vmovups(zmm_t(1), zmm_t(0));
+ vfmsub231ps(zmm_t(1), zmm_src(0, i), zmm_G(1));
+
+ vbroadcastss(zmm_G(2), ptr[reg_G + 2 * typesize]);
+ vmovups(zmm_t(2), zmm_t(0));
+ vfmadd231ps(zmm_t(2), zmm_src(0, i), zmm_G(2));
+
+ vbroadcastss(zmm_G(3), ptr[reg_G + 3 * typesize]);
+ vmulps(zmm_t(3), zmm_src(1, i), zmm_G(3));
+
+ vbroadcastss(zmm_G(4), ptr[reg_G + 4 * typesize]);
+ vfmadd231ps(zmm_t(3), zmm_src(3, i), zmm_G(4));
+
+ vbroadcastss(zmm_G(5), ptr[reg_G + 5 * typesize]);
+ vmulps(zmm_t(4), zmm_src(1, i), zmm_G(5));
+
+ vbroadcastss(zmm_G(6), ptr[reg_G + 6 * typesize]);
+ vfmadd231ps(zmm_t(4), zmm_src(3, i), zmm_G(6));
+
+ vbroadcastss(zmm_G(7), ptr[reg_G + 7 * typesize]);
+ vmulps(zmm_T(0, i), zmm_src(0, i), zmm_G(7));
+ vsubps(zmm_T(1, i), zmm_t(1), zmm_t(3));
+ vaddps(zmm_T(2, i), zmm_t(1), zmm_t(3));
+ vaddps(zmm_T(3, i), zmm_t(2), zmm_t(4));
+ vsubps(zmm_T(4, i), zmm_t(2), zmm_t(4));
+ vmovups(zmm_T(5, i), zmm_src(3, i));
+ }
+
+ for (int j = 0; j < alpha; j++) {
+ vbroadcastss(zmm_G(0), ptr[reg_G]);
+ vmulps(zmm_t(0), zmm_T(j, 2), zmm_G(0));
+
+ vbroadcastss(zmm_G(1), ptr[reg_G + typesize]);
+ vmovups(zmm_t(1), zmm_t(0));
+ vfmsub231ps(zmm_t(1), zmm_T(j, 0), zmm_G(1));
+
+ vbroadcastss(zmm_G(2), ptr[reg_G + 2 * typesize]);
+ vmovups(zmm_t(2), zmm_t(0));
+ vfmadd231ps(zmm_t(2), zmm_T(j, 0), zmm_G(2));
+
+ vbroadcastss(zmm_G(3), ptr[reg_G + 3 * typesize]);
+ vmulps(zmm_t(3), zmm_T(j, 1), zmm_G(3));
+
+ vbroadcastss(zmm_G(4), ptr[reg_G + 4 * typesize]);
+ vfmadd231ps(zmm_t(3), zmm_T(j, 3), zmm_G(4));
+
+ vbroadcastss(zmm_G(5), ptr[reg_G + 5 * typesize]);
+ vmulps(zmm_t(4), zmm_T(j, 1), zmm_G(5));
+
+ vbroadcastss(zmm_G(6), ptr[reg_G + 6 * typesize]);
+ vfmadd231ps(zmm_t(4), zmm_T(j, 3), zmm_G(6));
+
+ vbroadcastss(zmm_G(7), ptr[reg_G + 7 * typesize]);
+ vmulps(zmm_t(0), zmm_T(j, 0), zmm_G(7));
+ vsubps(zmm_t(5), zmm_t(1), zmm_t(3));
+ vaddps(zmm_t(1), zmm_t(1), zmm_t(3));
+ vaddps(zmm_t(6), zmm_t(2), zmm_t(4));
+ vsubps(zmm_t(2), zmm_t(2), zmm_t(4));
+ vmovups(zmm_t(3), zmm_T(j, 3));
+
+ int alpha_offset = (jcp.oc / jcp.nb_oc)
+ * (jcp.ntiles / jcp.tile_block) * typesize;
+ int dst_off = j * alpha * alpha_offset;
+ movps(reg_dst, dst_off, zmm_t(0));
+ dst_off += alpha_offset;
+ movps(reg_dst, dst_off, zmm_t(5));
+ dst_off += alpha_offset;
+ movps(reg_dst, dst_off, zmm_t(1));
+ dst_off += alpha_offset;
+ movps(reg_dst, dst_off, zmm_t(6));
+ dst_off += alpha_offset;
+ movps(reg_dst, dst_off, zmm_t(2));
+ dst_off += alpha_offset;
+ movps(reg_dst, dst_off, zmm_t(3));
+ }
+
+ };
+ auto compute_transform_SDGtWo = [=]() {
+ mov(reg_src, ptr[reg_transp + GET_OFF(src)]);
+ mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]);
+ if (with_bias) mov(reg_bias, ptr[reg_transp + GET_OFF(bias)]);
+
+ xor_(reg_zero, reg_zero);
+ xor_(reg_oc_ur, reg_oc_ur);
+ Label loop_mb, loop_jtiles, loop_itiles, loop_oc_ur, tiles_done;
+
+ L(loop_oc_ur);
+ {
+ mov(reg_ti, ptr[reg_transp + GET_OFF(ti)]);
+ mov(reg_tj, ptr[reg_transp + GET_OFF(tj)]);
+ xor_(reg_tile_count, reg_tile_count);
+ L(loop_mb);
+ {
+ L(loop_jtiles);
+ {
+ L(loop_itiles);
+ {
+ load_src();
+
+ trans_W_3x3_4x4();
+
+ add(reg_tile_count, 1);
+ cmp(reg_tile_count, jcp.nb_tile_block_ur * jcp.tile_block_ur);
+ jge(tiles_done);
+
+ add(reg_dst, jcp.oc_reg_block * simd_w * typesize);
+ add(reg_ti, 1);
+ cmp(reg_ti, jcp.itiles);
+ jl(loop_itiles);
+ }
+ xor_(reg_ti, reg_ti);
+ add(reg_tj, 1);
+ cmp(reg_tj, jcp.jtiles);
+ jl(loop_jtiles);
+ }
+ xor_(reg_tj, reg_tj);
+ add(reg_src, jcp.oc * jcp.ow * jcp.oh * typesize);
+ jmp(loop_mb);
+ }
+
+ L(tiles_done);
+ mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]);
+ add(reg_dst, simd_w * typesize);
+ mov(reg_src, ptr[reg_transp + GET_OFF(src)]);
+ add(reg_src, jcp.oh * jcp.ow * simd_w * typesize);
+
+ if (with_bias) add(reg_bias, simd_w * typesize);
+ add(reg_oc_ur, 1);
+ cmp(reg_oc_ur, jcp.oc_reg_block);
+ jl(loop_oc_ur);
+ }
+ };
+
+ auto compute_transform = [=]() {
+ mov(reg_src, ptr[reg_transp + GET_OFF(src)]);
+ mov(reg_G, ptr[reg_transp + GET_OFF(G)]);
+ if (with_bias) mov(reg_bias, ptr[reg_transp + GET_OFF(bias)]);
+
+ mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]);
+ mov(reg_tile_count, ptr[reg_transp + GET_OFF(tile_count)]);
+ imul(reg_temp, reg_tile_count, jcp.oc_reg_block * simd_w * typesize);
+ add(reg_dst, reg_temp);
+
+ xor_(reg_zero, reg_zero);
+ xor_(reg_oc_ur, reg_oc_ur);
+ Label loop_mb, loop_jtiles, loop_itiles, loop_oc_ur, next_tile_block, next_tile;
+
+ L(loop_oc_ur);
+ {
+ xor_(reg_ti, reg_ti);
+ xor_(reg_tj, reg_tj);
+
+ L(loop_jtiles);
+ {
+ L(loop_itiles);
+ {
+ load_src();
+
+ trans_W_3x3_4x4();
+
+ add(reg_tile_count, 1);
+ cmp(reg_tile_count, jcp.nb_tile_block_ur * jcp.tile_block_ur);
+ jge(next_tile_block);
+ add(reg_dst, jcp.oc_reg_block * simd_w * typesize);
+ jmp(next_tile);
+
+ L(next_tile_block);
+ sub(reg_dst, (jcp.nb_tile_block_ur * jcp.tile_block_ur - 1)
+ * jcp.oc_reg_block * simd_w * typesize);
+ int tblk_off = alpha * alpha * (jcp.oc/jcp.nb_oc)
+ * (jcp.ntiles/jcp.tile_block) * typesize;
+ add(reg_dst, tblk_off);
+ xor_(reg_tile_count, reg_tile_count);
+
+ L(next_tile);
+ add(reg_ti, 1);
+ cmp(reg_ti, jcp.itiles);
+ jl(loop_itiles);
+ }
+ xor_(reg_ti, reg_ti);
+ add(reg_tj, 1);
+ cmp(reg_tj, jcp.jtiles);
+ jl(loop_jtiles);
+ }
+
+ mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]);
+ mov(reg_tile_count, ptr[reg_transp + GET_OFF(tile_count)]);
+ imul(reg_temp, reg_tile_count, jcp.oc_reg_block * simd_w * typesize);
+ add(reg_dst, reg_temp);
+ add(reg_dst, simd_w * typesize);
+ mov(reg_src, ptr[reg_transp + GET_OFF(src)]);
+ add(reg_src, jcp.oh * jcp.ow * simd_w * typesize);
+
+ if (with_bias) add(reg_bias, simd_w * typesize);
+ add(reg_oc_ur, 1);
+ cmp(reg_oc_ur, jcp.oc_reg_block);
+ jl(loop_oc_ur);
+ }
+ };
+
+ preamble();
+ if (jcp.sched_policy == WSCHED_WEI_SDGtWo) {
+ compute_transform_SDGtWo();
+ } else {
+ compute_transform();
+ }
+ postamble();
+}
+
+void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel::
+diff_weights_transform_generate(bool first_tile) {
+ int G_size = 4;
+
+ auto zmm_G = [](int i) {
+ return Xbyak::Zmm(i);
+ };
+
+ auto init_G = [=]() {
+ mov(reg_G, ptr[reg_transp + GET_OFF(G)]);
+ for (int i = 0; i < G_size; i++)
+ vbroadcastss(zmm_G(i), ptr[reg_G + i * typesize]);
+ };
+
+ auto zmm_src = [=](int i) {
+ return Xbyak::Zmm(G_size + i);
+ };
+
+ auto load_src = [=](int i) {
+ for (int j = 0; j < alpha; j++) {
+ size_t alpha_offset = jcp.oc_block * jcp.oc_reg_block
+ * jcp.ic_block * simd_w * simd_w * typesize;
+ size_t src_off = (j * alpha + i) * alpha_offset;
+ vmovups(zmm_src(j), EVEX_compress_addr(reg_src, src_off));
+ }
+ };
+
+ auto zmm_t = [=](int i) {
+ return Xbyak::Zmm(G_size + 6 + i);
+ };
+
+ auto zmm_T = [=](int j, int i) {
+ return Xbyak::Zmm(G_size + 6 + 3 + j * 6 + i);
+ };
+
+ auto zmm_dst = [=](int i) {
+ return Xbyak::Zmm(G_size + i);
+ };
+
+ auto zmm_temp = Xbyak::Zmm(31);
+
+ auto store_dst = [=](int j) {
+ for (int i = 0; i < jcp.kw; i++) {
+ size_t dst_off = (j * jcp.kw + i) * simd_w * simd_w * typesize;
+
+ if (!first_tile) {
+ vmovups(zmm_temp, EVEX_compress_addr(reg_dst, dst_off));
+ vaddps(zmm_dst(i), zmm_dst(i), zmm_temp);
+ }
+ vmovntps(EVEX_compress_addr(reg_dst, dst_off), zmm_dst(i));
+ }
+ };
+
+ auto compute_transform = [=] () {
+ mov(reg_src, ptr[reg_transp + GET_OFF(src)]);
+ mov(reg_dst, ptr[reg_transp + GET_OFF(dst)]);
+
+ xor_(reg_ic_simd, reg_ic_simd);
+ Label loop_ic_simd;
+ L(loop_ic_simd);
+ {
+ for (int i = 0; i < alpha; i++) {
+ load_src(i);
+
+ vaddps(zmm_t(0), zmm_src(1), zmm_src(2));
+ vaddps(zmm_t(1), zmm_src(3), zmm_src(4));
+ vmovups(zmm_t(2), zmm_src(5));
+ vfmadd231ps(zmm_t(2), zmm_t(1), zmm_G(0));
+
+ vaddps(zmm_T(0, i), zmm_src(0), zmm_t(0));
+ vaddps(zmm_T(0, i), zmm_T(0, i), zmm_t(1));
+ vsubps(zmm_T(1, i), zmm_src(1), zmm_src(2));
+ vmulps(zmm_T(1, i), zmm_T(1, i), zmm_G(1));
+ vsubps(zmm_temp, zmm_src(3), zmm_src(4));
+ vfmadd231ps(zmm_T(1, i), zmm_temp, zmm_G(2));
+ vmovups(zmm_T(2, i), zmm_t(2));
+ vfmadd231ps(zmm_T(2, i), zmm_t(0), zmm_G(3));
+ }
+
+ for (int j = 0; j < jcp.kh; j++) {
+ vaddps(zmm_t(0), zmm_T(j, 1), zmm_T(j, 2));
+ vaddps(zmm_t(1), zmm_T(j, 3), zmm_T(j, 4));
+ vmovups(zmm_t(2), zmm_T(j, 5));
+ vfmadd231ps(zmm_t(2), zmm_t(1), zmm_G(0));
+
+ vaddps(zmm_dst(0), zmm_T(j, 0), zmm_t(0));
+ vaddps(zmm_dst(0), zmm_dst(0), zmm_t(1));
+ vsubps(zmm_dst(1), zmm_T(j, 1), zmm_T(j, 2));
+ vmulps(zmm_dst(1), zmm_dst(1), zmm_G(1));
+ vsubps(zmm_temp, zmm_T(j, 3), zmm_T(j, 4));
+ vfmadd231ps(zmm_dst(1), zmm_temp, zmm_G(2));
+ vmovups(zmm_dst(2), zmm_t(2));
+ vfmadd231ps(zmm_dst(2), zmm_t(0), zmm_G(3));
+
+ store_dst(j);
+ }
+
+ add(reg_src, jcp.oc_reg_block * simd_w * typesize);
+ add(reg_dst, simd_w * typesize);
+ add(reg_ic_simd, 1);
+ cmp(reg_ic_simd, simd_w);
+ jl(loop_ic_simd);
+ }
+ };
+ preamble();
+ push(reg_EVEX_max_8b_offt);
+ mov(reg_EVEX_max_8b_offt, 2 * EVEX_max_8b_offt);
+ init_G();
+ compute_transform();
+ pop(reg_EVEX_max_8b_offt);
+ postamble();
+}
+
+void jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel::gemm_loop_generate(
+ bool is_first_tile)
+{
+ auto zmm_srcA = [=]() {
+ return Xbyak::Zmm(0);
+ };
+
+ auto zmm_srcB = [=] (size_t N_ur){
+ return Xbyak::Zmm(N_ur + 1);
+ };
+
+ auto broadcastB = [=](size_t K_ur) {
+ for (int N_bcast = 0; N_bcast < jcp.dimN_bcast_ur; N_bcast++) {
+ size_t srcB_off = (K_ur * jcp.dimN_reg_block + N_bcast)
+ * sizeof(float);
+ vbroadcastss(zmm_srcB(N_bcast), EVEX_compress_addr(reg_srcB, srcB_off));
+ }
+ };
+
+ auto load_srcA = [=] (size_t K_ur, int M_ur) {
+ size_t srcA_off = (K_ur * jcp.dimM_reg_block * jcp.dimM_simd_block
+ + M_ur * jcp.dimM_simd_block) * sizeof(float);
+ vmovups(zmm_srcA(), EVEX_compress_addr(reg_srcA, srcA_off));
+ };
+
+ auto zmm_dstC = [=](size_t M_reg_ur, int N_bcast){
+ size_t idx = 1 // zmm_srcA
+ + jcp.dimN_bcast_ur // zmm_srcB
+ + M_reg_ur * jcp.dimN_bcast_ur + N_bcast;
+ assert(idx < 32);
+ return Xbyak::Zmm(idx);
+ };
+ auto prepare_accumm = [=](){
+ for (int M_reg_ur = 0; M_reg_ur < jcp.dimM_reg_block; M_reg_ur++) {
+ for (int N_bcast = 0; N_bcast < jcp.dimN_bcast_ur; N_bcast++) {
+ Zmm zmm = zmm_dstC(M_reg_ur, N_bcast);
+ vpxord(zmm, zmm, zmm);
+ }
+ }
+ };
+
+ auto store_dstC = [=](){
+ /******** Write C back to memory *******/
+ for (int M_reg = 0; M_reg < jcp.dimM_reg_block; M_reg++) {
+ for (int N_ur = 0; N_ur < jcp.dimN_bcast_ur; ++N_ur) {
+ Zmm zmm = zmm_dstC(M_reg, N_ur);
+ size_t C_off = (N_ur * jcp.dimM_reg_block * jcp.dimM_simd_block
+ + M_reg * jcp.dimM_simd_block) * sizeof(float);
+ if (!is_first_tile) {
+ vmovups(Xbyak::Zmm(0), EVEX_compress_addr(reg_dstC, C_off));
+ vaddps(zmm, zmm, Xbyak::Zmm(0));
+ }
+ vmovups(EVEX_compress_addr(reg_dstC, C_off), zmm);
+ }
+ }
+ };
+
+ auto inner_loops = [=]() {
+ Label dimM_block_loop, dimK_block_loop, dimN_block_loop, dimN_bcast_ur;
+
+ mov(reg_dimM_block_loop_cnt, jcp.dimM_block);
+ L(dimM_block_loop);
+ { /************* OC_block (M) loop ***********/
+ mov(reg_dimN_block_loop_cnt, jcp.dimN_block);
+ L(dimN_block_loop);
+ { /*************** IC_block (N) loop *********/
+
+ mov(reg_nb_dimN_bcast_ur, jcp.dimN_reg_block/jcp.dimN_bcast_ur);
+ L(dimN_bcast_ur);
+ {
+ prepare_accumm();
+
+ mov(reg_dimK_block_loop_cnt, jcp.dimK_block);
+ L(dimK_block_loop);
+ {
+ /************* nb_tile_ur(K) loop ********/
+ for (int K_ur = 0; K_ur < jcp.dimK_reg_block; K_ur++) {
+
+ broadcastB(K_ur);
+
+ for (int M_reg_ur = 0; M_reg_ur < jcp.dimM_reg_block; M_reg_ur++) {
+ load_srcA(K_ur, M_reg_ur);
+ for (int N_bcast = 0; N_bcast < jcp.dimN_bcast_ur; ++N_bcast) {
+ vfmadd231ps(zmm_dstC(M_reg_ur, N_bcast), zmm_srcA(),
+ zmm_srcB(N_bcast));
+ }
+ }
+ }
+ add(reg_srcA, jcp.dimK_reg_block
+ * jcp.dimM_reg_block * jcp.dimM_simd_block
+ * sizeof(float));
+ add(reg_srcB, jcp.dimK_reg_block
+ * jcp.dimN_reg_block
+ * sizeof(float));
+ sub(reg_dimK_block_loop_cnt, 1);
+ jnz(dimK_block_loop);
+ }
+
+ store_dstC();
+
+ sub(reg_srcA, jcp.dimK_block * jcp.dimK_reg_block
+ * jcp.dimM_reg_block * jcp.dimM_simd_block
+ * sizeof(float));
+ sub(reg_srcB, jcp.dimK_block * jcp.dimK_reg_block
+ * jcp.dimN_reg_block
+ * sizeof(float));
+ add(reg_srcB, jcp.dimN_bcast_ur * sizeof(float));
+ add(reg_dstC, jcp.dimN_bcast_ur
+ * jcp.dimM_reg_block * jcp.dimM_simd_block
+ * sizeof(float));
+ sub(reg_nb_dimN_bcast_ur, 1);
+ jnz(dimN_bcast_ur);
+ }
+
+ sub(reg_srcB, jcp.dimN_reg_block * sizeof(float));
+ add(reg_srcB, jcp.dimK_block
+ * jcp.dimK_reg_block
+ * jcp.dimN_reg_block * sizeof(float));
+ sub(reg_dimN_block_loop_cnt, 1);
+ jnz(dimN_block_loop);
+ }
+
+ sub(reg_srcB, jcp.dimN_block
+ * jcp.dimK_block * jcp.dimK_reg_block
+ * jcp.dimN_reg_block
+ * sizeof(float));
+ add(reg_srcA, jcp.dimK_block * jcp.dimK_reg_block
+ * jcp.dimM_reg_block * jcp.dimM_simd_block
+ * sizeof(float));
+ sub(reg_dimM_block_loop_cnt, 1);
+ jnz(dimM_block_loop);
+ }
+ };
+
+ /* Preamble */
+ preamble();
+
+ inner_loops();
+
+ /* Postamble */
+ postamble();
+ ret();
+}
+
+namespace {
+
+void set_jcp_WEI_params(jit_conv_winograd_conf_t &jcp) {
+/*M params*/
+ jcp.dimM_nb_block = jcp.dimM / jcp.dimM_block / jcp.dimM_reg_block
+ / jcp.dimM_simd_block;
+ jcp.oc_reg_block = jcp.dimM_reg_block;
+ jcp.oc_block = jcp.dimM_block;
+ jcp.nb_oc = jcp.dimM_nb_block;
+ /*N params*/
+ jcp.dimN_nb_block = jcp.dimN / jcp.dimN_block / jcp.dimN_reg_block;
+ jcp.ic_block = jcp.dimN_block;
+ jcp.nb_ic = jcp.dimN_nb_block;
+
+ /*K params*/
+ jcp.dimK_nb_block = jcp.dimK / jcp.dimK_block / jcp.dimK_reg_block;
+ jcp.tile_block_ur = jcp.dimK_reg_block;
+ jcp.nb_tile_block_ur = jcp.dimK_block;
+ jcp.tile_block = jcp.dimK_nb_block;
+}
+
+status_t set_wsched_WEI_SDGtWo(jit_conv_winograd_conf_t &jcp) {
+
+ size_t K_blk_ur, N_blk, M_blk;
+ /* IS this strategy feasible? */
+ auto test_MV_large_enough = [](jit_conv_winograd_conf_t &jcp) {
+ size_t M_sz = alpha * alpha * jcp.dimM * jcp.dimK * sizeof(float);
+ size_t V_sz = alpha * alpha * jcp.dimN * jcp.dimK * sizeof(float);
+ size_t nthreads = mkldnn_get_max_threads();
+ return (((V_sz + M_sz) / nthreads) >= 2 * L2_cache_size)
+ && (jcp.dimK / nthreads >= 1.0);
+ };
+
+ auto test_min_dimK_L1 = [](jit_conv_winograd_conf_t &jcp, int dimK_block_ur,
+ int max_block=1) {
+ size_t L1_block_M = jcp.dimM_reg_block * jcp.dimM_simd_block * dimK_block_ur * sizeof(float);
+ size_t L1_block_N = jcp.dimN_reg_block * dimK_block_ur * sizeof(float);
+ size_t M_L2_block = alpha * alpha * jcp.dimM * dimK_block_ur * sizeof(float);
+ size_t nthreads = mkldnn_get_max_threads();
+ bool load_balance=true;
+ if (!(jcp.dimK % nthreads)) {
+ load_balance = ((jcp.dimK / dimK_block_ur) % nthreads == 0);
+ }
+ return (L1_block_M + L1_block_N >= 0.1 * L1_cache_size)
+ && (L1_block_M + L1_block_N <= 0.5 * L1_cache_size)
+ && load_balance
+ && (M_L2_block < L2_cache_size);
+ };
+
+ auto test_dimK_ur = [](jit_conv_winograd_conf_t &jcp, int dimK_ur,
+ int useless_arg=0) {
+ return (dimK_ur >= 2) && (dimK_ur <= 8);
+ };
+
+ auto blocking_ok = [&](){
+ size_t M_L2_block = alpha * alpha * M_blk * jcp.dimM_reg_block * jcp.dimM_simd_block
+ * K_blk_ur * sizeof(float);
+ size_t V_L2_block = alpha * alpha * N_blk * jcp.dimN_reg_block
+ * K_blk_ur * sizeof(float);
+ size_t U_L2_block = alpha * alpha * M_blk * jcp.dimM_reg_block * jcp.dimM_simd_block
+ * N_blk * jcp.dimN_reg_block * sizeof(float);
+ size_t L2_block = M_L2_block + V_L2_block + U_L2_block;
+ /*Replace 2.375 with L2+L3 cache size*/
+ return (L2_block > 0.1 * L2_cache_size) && (L2_block <= 1.2 * L2_cache_size);
+ };
+
+ if (test_MV_large_enough(jcp)) {
+ if ((jcp.dimM/jcp.dimM_simd_block) % 2 == 0) {
+ jcp.dimM_reg_block = 2;
+ } else {
+ jcp.dimM_reg_block = 1;
+ }
+ jcp.dimM_simd_block = jcp.oc_simd_block;
+ jcp.dimN_reg_block = jcp.ic_simd_block;
+ jcp.dimN_bcast_ur = 8;
+ /*dimK_block and dimK_ur*/
+ size_t min_dimK_block_ur = get_divisor_satisfying_cond(jcp, jcp.dimK, 1, test_min_dimK_L1);
+
+ jcp.dimM_block = jcp.dimM/jcp.dimM_reg_block/jcp.dimM_simd_block;
+ jcp.dimN_block = jcp.dimN/jcp.dimN_reg_block;
+ for (K_blk_ur = min_dimK_block_ur; K_blk_ur >= 1; --K_blk_ur) {
+ if (test_min_dimK_L1(jcp, K_blk_ur) && !(jcp.dimK % K_blk_ur)) {
+ for (N_blk = jcp.dimN_block; N_blk >= 1; --N_blk) {
+ if (!(jcp.dimN_block % N_blk)) {
+ for (M_blk = jcp.dimM_block; M_blk >= 1; --M_blk) {
+ if (!(jcp.dimM_block % M_blk) && blocking_ok()) {
+ jcp.dimK_reg_block = get_divisor_satisfying_cond(jcp, K_blk_ur, 1, test_dimK_ur);
+ if (!test_dimK_ur(jcp, jcp.dimK_reg_block)) return status::unimplemented;
+ jcp.dimK_block = K_blk_ur / jcp.dimK_reg_block;
+ jcp.dimN_block = N_blk;
+ jcp.dimM_block = M_blk;
+ jcp.sched_policy = WSCHED_WEI_SDGtWo;
+ set_jcp_WEI_params(jcp);
+ jcp.nthr = nstl::min(mkldnn_get_max_threads(),
+ jcp.tile_block);
+ return status::success;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return status::unimplemented;
+}
+
+status_t set_wsched_WEI_S_D_Giot_W(jit_conv_winograd_conf_t &jcp) {
+ if ((jcp.dimM/jcp.dimM_simd_block) % 2 == 0) {
+ jcp.dimM_reg_block = 2;
+ } else {
+ jcp.dimM_reg_block = 1;
+ }
+ jcp.dimN_bcast_ur = 8;
+ jcp.dimN_reg_block = jcp.ic_simd_block;
+ jcp.dimM_simd_block = jcp.oc_simd_block;
+ jcp.dimN_block = jcp.dimN / jcp.dimN_reg_block;
+ jcp.dimM_block = jcp.dimM / jcp.dimM_reg_block / jcp.dimM_simd_block;
+ float C1 = 0.0, C2 = 0.0;
+ float C1_max = 0.5, C2_max = 1.4;
+ int N_blk, M_blk, K_blk_ur;
+
+ auto test_dimK_ur = [](jit_conv_winograd_conf_t &jcp, int dimK_ur,
+ int useless_arg=0) {
+ return (dimK_ur >= 2) && (dimK_ur <= 8);
+ };
+
+ auto blocking_ok = [&]() -> bool {
+ size_t L1_block_M = jcp.dimM_reg_block * jcp.dimM_simd_block * K_blk_ur * sizeof(float);
+ size_t L1_block_N = jcp.dimN_reg_block * K_blk_ur * sizeof(float);
+ bool L1_cond = ((L1_block_N + L1_block_M) >= C1 * L1_cache_size)
+ && ((L1_block_N + L1_block_M) <= C1_max * L1_cache_size);
+
+ size_t nb_N_blk = jcp.dimN/N_blk/jcp.dimN_reg_block;
+ size_t nb_M_blk = jcp.dimM/M_blk/jcp.dimM_reg_block/jcp.dimM_simd_block;
+ size_t nb_K_blk = jcp.dimK / K_blk_ur;
+ size_t nthreads = mkldnn_get_max_threads();
+ bool load_balance = (nb_K_blk * nb_N_blk * nb_M_blk) >= nthreads;
+ if (!(nb_K_blk % nthreads)) {
+ load_balance = load_balance && (nb_K_blk % nthreads == 0);
+ }
+
+ size_t V_L2_block = alpha * alpha * N_blk * jcp.dimN_reg_block * K_blk_ur * sizeof(float);
+
+ size_t L2_block = V_L2_block;
+ /*Replace 2.375 with L2+L3 cache size*/
+ bool L2_cond = (L2_block >= C2 * L2_cache_size) && (L2_block <= C2_max * L2_cache_size);
+ return L1_cond && load_balance && L2_cond;
+ };
+
+ for (K_blk_ur = jcp.dimK; K_blk_ur >= 1; --K_blk_ur) {
+ if (jcp.dimK % K_blk_ur == 0) {
+ for (N_blk = jcp.dimN_block; N_blk >= 1; --N_blk) {
+ if (jcp.dimN_block % N_blk == 0) {
+ for (M_blk = jcp.dimM_block; M_blk >= 1; --M_blk) {
+ if (jcp.dimM_block % M_blk == 0) {
+ if (blocking_ok()) {
+ jcp.dimN_block = N_blk;
+ jcp.dimM_block = M_blk;
+ jcp.dimK_reg_block = get_divisor_satisfying_cond(jcp, K_blk_ur, 1, test_dimK_ur);
+ jcp.dimK_block = K_blk_ur / jcp.dimK_reg_block;
+ jcp.sched_policy = WSCHED_WEI_S_D_Giot_W;
+ set_jcp_WEI_params(jcp);
+ return status::success;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ jcp.dimK_reg_block = 1;
+ jcp.dimK_block = 1;
+ jcp.sched_policy = WSCHED_WEI_S_D_Giot_W;
+ set_jcp_WEI_params(jcp);
+ return status::success;
+}
+} // namespace
+status_t jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel::init_conf(
+ jit_conv_winograd_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d, const memory_desc_wrapper &diff_dst_d,
+ const memory_desc_wrapper &diff_weights_d) {
+ if (!mayiuse(avx512_core))
+ return status::unimplemented;
+ else
+ jcp.ver = ver_avx512_core;
+
+ jcp.nthr = mkldnn_get_max_threads();
+
+ jcp.prop_kind = cd.prop_kind;
+ const bool with_groups = diff_weights_d.ndims() == src_d.ndims() + 1;
+ jcp.mb = src_d.dims()[0];
+ jcp.ngroups = with_groups ? diff_weights_d.dims()[0] : 1;
+ jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.ih = src_d.dims()[2];
+ jcp.iw = src_d.dims()[3];
+ jcp.oh = diff_dst_d.dims()[2];
+ jcp.ow = diff_dst_d.dims()[3];
+ jcp.kh = diff_weights_d.dims()[with_groups + 2];
+ jcp.kw = diff_weights_d.dims()[with_groups + 3];
+ jcp.t_pad = cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][1];
+ jcp.stride_h = cd.strides[0];
+ jcp.stride_w = cd.strides[1];
+ jcp.r_pad = nstl::max(
+ 0, (jcp.ow - 1) * jcp.stride_w + jcp.kw - jcp.iw - jcp.l_pad);
+ jcp.b_pad = nstl::max(
+ 0, (jcp.oh - 1) * jcp.stride_h + jcp.kh - jcp.ih - jcp.t_pad);
+ jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad;
+ jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad;
+ jcp.ohp = jcp.oh;
+ jcp.owp = jcp.ow;
+ jcp.with_bias = (cd.diff_bias_desc.format_kind != format_kind::undef);
+ jcp.dilate_h = cd.dilates[0];
+ jcp.dilate_w = cd.dilates[1];
+
+ bool ok_to_pad_channels = jcp.ngroups == 1;
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ jcp.ic = rnd_up(jcp.ic, simd_w);
+ }
+
+ // Winograd specific initialization
+ jcp.itiles = (jcp.ow + tile_size - 1) / tile_size;
+ jcp.jtiles = (jcp.oh + tile_size - 1) / tile_size;
+ jcp.ntiles = jcp.mb * jcp.itiles * jcp.jtiles;
+
+ // Winograd kernel works only for 3x3 convolution with stride 1
+ if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto,
+ is_winograd_faster_than_direct(jcp)))
+ return status::unimplemented;
+
+ if (jcp.ngroups != 1)
+ return status::unimplemented;
+ if ((jcp.kh != 3) || (jcp.kw != 3))
+ return status::unimplemented;
+ if ((jcp.dilate_h != 0) || (jcp.dilate_w != 0))
+ return status::unimplemented;
+ if ((jcp.stride_h != 1) || (jcp.stride_w != 1))
+ return status::unimplemented;
+ if ((jcp.ic % simd_w) != 0 || (jcp.oc % simd_w) != 0)
+ return status::unimplemented;
+
+ format_tag_t dat_tag = nChw16c;
+ format_tag_t wei_tag = with_groups ? gOIhw16i16o : OIhw16i16o;
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.wei_tag = diff_weights_d.matches_one_of_tag(wei_tag);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(dat_tag);
+
+ if (jcp.src_tag != dat_tag) return status::unimplemented;
+ if (jcp.wei_tag != wei_tag) return status::unimplemented;
+ if (jcp.dst_tag != dat_tag) return status::unimplemented;
+
+ bool layout_consistency = true
+ && jcp.ic <= src_d.padded_dims()[1]
+ && jcp.oc <= diff_dst_d.padded_dims()[1]
+ && jcp.ic <= diff_weights_d.padded_dims()[with_groups + 1]
+ && jcp.oc <= diff_weights_d.padded_dims()[with_groups + 0];
+ if (!layout_consistency) return status::unimplemented;
+
+ /******************Kernel blocking Parameters ***********/
+ jcp.ic_simd_block = simd_w;
+ jcp.oc_simd_block = simd_w;
+
+ jcp.dimK = jcp.ntiles;
+ jcp.dimN = jcp.ic;
+ jcp.dimM = jcp.oc;
+ jcp.dimM_simd_block = jcp.oc_simd_block;
+ jcp.dimN_reg_block = jcp.ic_simd_block;
+ jcp.sched_policy = WSCHED_INVALID;
+ status_t res = set_wsched_WEI_SDGtWo(jcp);
+ if (res == status::unimplemented) {
+ res = set_wsched_WEI_S_D_Giot_W(jcp);
+ assert(res == status::success);
+ }
+ return res;
+}
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp
new file mode 100644
index 0000000000..025a554d92
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.hpp
@@ -0,0 +1,291 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_AVX512_CORE_FP32_WINO_CONV_4x3_KERNEL_HPP
+#define JIT_AVX512_CORE_FP32_WINO_CONV_4x3_KERNEL_HPP
+
+#include "c_types_map.hpp"
+
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+
+#include "jit_avx512_common_conv_winograd_kernel_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct _jit_avx512_core_fp32_wino_conv_4x3_data_kernel
+ : public jit_generator {
+ _jit_avx512_core_fp32_wino_conv_4x3_data_kernel(
+ jit_conv_winograd_conf_t ajcp)
+ : jcp(ajcp) {
+ {
+ this->weights_transform_data_ker_generate();
+ weights_transform_data_ker
+ = (decltype(weights_transform_data_ker)) this->getCode();
+ }
+ {
+ align();
+ const Xbyak::uint8 *addr = getCurr();
+ this->input_transform_data_ker_generate();
+ input_transform_data_ker = (decltype(input_transform_data_ker))addr;
+ }
+ {
+ align();
+ const Xbyak::uint8 *addr = getCurr();
+ this->output_transform_data_ker_generate();
+ output_transform_data_ker
+ = (decltype(output_transform_data_ker))addr;
+ }
+ {
+ align();
+ const Xbyak::uint8 *addr = getCurr();
+ this->gemm_loop_generate();
+ gemm_loop_ker = (decltype(gemm_loop_ker))addr;
+ }
+ }
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(_jit_avx512_core_fp32_wino_conv_4x3_data_kernel)
+
+ static status_t init_conf_common(jit_conv_winograd_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d);
+
+ static status_t init_conf_kernel(
+ jit_conv_winograd_conf_t &jcp, int dimM, int dimN, int dimK);
+
+ jit_conv_winograd_conf_t jcp;
+ void (*gemm_loop_ker)(float *, const float *, const float *, const int);
+ void (*input_transform_data_ker)(jit_wino_transform_call_s *);
+ void (*output_transform_data_ker)(jit_wino_transform_call_s *);
+ void (*weights_transform_data_ker)(jit_wino_transform_call_s *);
+
+protected:
+ using reg64_t = const Xbyak::Reg64;
+ using reg32_t = const Xbyak::Reg32;
+ enum { typesize = sizeof(float) };
+
+ void gemm_loop_generate();
+ void input_transform_data_ker_generate();
+ void output_transform_data_ker_generate();
+ void weights_transform_data_ker_generate();
+
+ /* registers used for GEMM */
+ reg64_t reg_dstC = abi_param1;
+ reg64_t reg_srcA = abi_param2;
+ reg64_t reg_srcB = abi_param3;
+ reg64_t reg_is_beta_zero = abi_param4;
+
+ reg64_t reg_dimM_block_loop_cnt = r10;
+ reg64_t reg_dimK_block_loop_cnt = r11;
+
+ /* registers used for transforms*/
+ reg64_t param = abi_param1;
+
+ /* registers used for output_transform_data_ker */
+ reg64_t oreg_temp = abi_not_param1;
+ reg64_t oreg_Ow = r9;
+ reg64_t oreg_src = r11;
+ reg64_t oreg_tile_block = r12;
+ reg64_t oreg_tile_block_ur = r13;
+ reg64_t oreg_nb_tile_block_ur = r14;
+ reg64_t oreg_O = r8;
+ reg64_t oreg_T = r10;
+ reg64_t oreg_dst = r11;
+ reg64_t oreg_ydim = r14;
+ reg64_t oreg_xdim = r15;
+ reg64_t oreg_out_j = r12;
+ reg64_t oreg_bias = rbx;
+ reg64_t imm_addr64 = rax;
+
+ /* registers used for input_transform_data_ker */
+ reg64_t ireg_temp = abi_not_param1;
+ reg64_t ireg_jtiles = rax;
+ reg64_t ireg_itiles = rbx;
+ reg64_t ireg_I = r8;
+ reg64_t ireg_src = r13;
+ reg64_t ireg_ydim = r14;
+ reg64_t ireg_xdim = r15;
+ reg64_t ireg_inp_j = r12;
+ reg64_t ireg_inp_i = rdx;
+ reg64_t ireg_mask_j = r11;
+ reg64_t ireg_mask = rsi;
+ reg32_t ireg_mask_32 = esi;
+ reg64_t ireg_zero = r9;
+ reg64_t ireg_Iw = r9;
+ reg64_t ireg_T = r10;
+ reg64_t ireg_tile_block = r12;
+ reg64_t ireg_tile_block_ur = r13;
+ reg64_t ireg_nb_tile_block_ur = r14;
+ reg64_t ireg_output = r15;
+
+ /* registers used for wei transform */
+ reg64_t wreg_temp = abi_not_param1;
+ reg64_t wreg_F = r8;
+ reg64_t wreg_src = r9;
+ reg64_t wreg_MT = r15;
+ reg64_t wreg_M = r14;
+ reg64_t wreg_dst = r10;
+ reg64_t wreg_dst_aux = r9;
+ reg64_t wreg_dst_idx = r8;
+ reg64_t wreg_Fw = r11;
+ reg64_t wreg_T = r12;
+ reg64_t wreg_cnt_j = rdx;
+ reg64_t wreg_F_aux = r14;
+ reg64_t wreg_Fw_aux = r15;
+};
+
+struct jit_avx512_core_fp32_wino_conv_4x3_fwd_kernel
+ : _jit_avx512_core_fp32_wino_conv_4x3_data_kernel {
+ using _jit_avx512_core_fp32_wino_conv_4x3_data_kernel::
+ _jit_avx512_core_fp32_wino_conv_4x3_data_kernel;
+
+ static bool post_ops_ok(jit_conv_conf_t &jcp, const primitive_attr_t &attr);
+
+ static status_t init_conf(jit_conv_winograd_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_t &src_md,
+ memory_desc_t &weights_md, const memory_desc_t &dst_md,
+ const primitive_attr_t &attr);
+};
+
+struct jit_avx512_core_fp32_wino_conv_4x3_bwd_data_kernel
+ : public _jit_avx512_core_fp32_wino_conv_4x3_data_kernel {
+ using _jit_avx512_core_fp32_wino_conv_4x3_data_kernel::
+ _jit_avx512_core_fp32_wino_conv_4x3_data_kernel;
+
+ static status_t init_conf(jit_conv_winograd_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &diff_src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &diff_dst_d);
+};
+
+struct jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel
+ : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(
+ _jit_avx512_core_conv_winograd_bwd_weights_kernel_f32)
+
+ jit_avx512_core_fp32_wino_conv_4x3_bwd_weights_kernel(
+ jit_conv_winograd_conf_t ajcp)
+ : jcp(ajcp)
+ {
+ //******************* First iter kernel ********************//
+ this->gemm_loop_generate(true);
+ gemm_loop_ker_first_iter = (decltype(gemm_loop_ker_first_iter))this->getCode();
+
+ align();
+ const Xbyak::uint8 *addr = getCurr();
+ this->src_transform_generate();
+ src_transform = (decltype(src_transform))addr;
+
+ if (jcp.with_bias) {
+ align();
+ addr = getCurr();
+ this->diff_dst_transform_generate(true);
+ diff_dst_transform_wbias = (decltype(diff_dst_transform_wbias))addr;
+ }
+
+ align();
+ addr = getCurr();
+ this->diff_dst_transform_generate(false);
+ diff_dst_transform = (decltype(diff_dst_transform))addr;
+
+ if (jcp.sched_policy != WSCHED_WEI_SDGtWo && jcp.tile_block > 1) {
+ align();
+ addr = getCurr();
+ this->gemm_loop_generate(false);
+ gemm_loop_ker = (decltype(gemm_loop_ker))addr;
+ }
+
+ align();
+ addr = getCurr();
+ this->diff_weights_transform_generate(true);
+ diff_weights_transform = (decltype(diff_weights_transform))addr;
+
+ if (jcp.sched_policy == WSCHED_WEI_SDGtWo) {
+ align();
+ addr = getCurr();
+ this->diff_weights_transform_generate(false);
+ diff_weights_transform_accum =
+ (decltype(diff_weights_transform_accum))addr;
+ };
+ }
+
+ static status_t init_conf(jit_conv_winograd_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &diff_dst_d,
+ const memory_desc_wrapper &diff_weights_d);
+
+ jit_conv_winograd_conf_t jcp;
+ void (*gemm_loop_ker)(float *, const float *, const float *);
+ void (*gemm_loop_ker_first_iter)(float *, const float *, const float *);
+ void (*src_transform)(jit_wino_transform_call_s *);
+ void (*diff_dst_transform)(jit_wino_transform_call_s *);
+ void (*diff_dst_transform_wbias)(jit_wino_transform_call_s *);
+ void (*diff_weights_transform)(jit_wino_transform_call_s *);
+ void (*diff_weights_transform_accum)(jit_wino_transform_call_s *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ using reg32_t = const Xbyak::Reg32;
+ enum { typesize = sizeof(float) };
+
+ void src_transform_generate();
+ void diff_dst_transform_generate(bool with_bias);
+ void diff_weights_transform_generate(bool first_tile);
+
+ /*registers common to transforms*/
+ reg64_t reg_transp = abi_param1;
+ reg64_t reg_ti = rbx;
+ reg64_t reg_tj = abi_not_param1;
+ reg64_t reg_src = r8;
+ reg64_t reg_dst = r9;
+ reg64_t reg_G = rsi; /*TODO: check if this is ok*/
+ reg64_t reg_temp = rsi;
+
+ /*registers common to src/diff_dst transform*/
+ reg64_t reg_I = r10;
+ reg64_t reg_ydim = r11;
+ reg64_t reg_xdim = r12;
+ reg64_t reg_src_offset = r13;
+ reg64_t reg_zero = r14;
+ reg64_t reg_tile_count = r15;
+ reg64_t reg_maski = rsi;
+ reg32_t reg_maski_32 = esi;
+ reg64_t reg_maskj = rdx;
+
+ reg64_t reg_T = rax;
+ reg64_t reg_oc_ur = rax;
+ reg64_t reg_ic_simd = r14;
+ reg64_t reg_bias = r10;
+
+ void gemm_loop_generate(bool is_first_tile);
+
+ reg64_t reg_dstC = abi_param1;
+ reg64_t reg_srcA = abi_param2;
+ reg64_t reg_srcB = abi_param3;
+
+ reg64_t reg_dimM_block_loop_cnt = r9;
+ reg64_t reg_dimN_block_loop_cnt = r10;
+ reg64_t reg_nb_dimN_bcast_ur = r11;
+ reg64_t reg_dimK_block_loop_cnt = r12;
+};
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.cpp
new file mode 100644
index 0000000000..002010ffa2
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.cpp
@@ -0,0 +1,1284 @@
+/*******************************************************************************
+ * Copyright 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_avx512_core_u8s8s32x_wino_convolution.hpp"
+#include "jit_generator.hpp"
+
+#include <string.h>
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+using namespace Xbyak;
+
+namespace {
+ // Below scales are applied to source and weights data accordingly
+ // because this winograd implementation
+ // transforms source which may increase values up to 4x
+ // and transforms weights which may increase values up to 9/4x
+ const float adj_src_scale = 1.f / 4.f;
+ const float adj_wei_scale = 4.f / 9.f;
+ // Winograd transforms need ic and oc to be multiples of 16
+ const int load_block = 16;
+}
+
+/// SRC TRANSFORMS /////////////////////////////////////////////////////////////
+struct jit_avx512_core_u8s8s32x_wino_conv_src_trans_t: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(
+ jit_avx512_core_u8s8s32x_wino_conv_src_trans_t)
+
+ jit_conv_conf_2x3_wino_t jcp;
+ const primitive_attr_t &attr_;
+
+ struct call_params_t {
+ const void *src;
+ const void *wino_src;
+ const void *v_y_masks;
+ const void *v_x_masks;
+ };
+ void (*ker_)(const call_params_t *);
+
+ jit_avx512_core_u8s8s32x_wino_conv_src_trans_t(
+ jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr), unsign_val_in_wino_domain(5) {
+ generate();
+ ker_ = reinterpret_cast<decltype(ker_)>(const_cast<uint8_t*>(getCode()));
+ }
+ void generate();
+
+ int reg_inp_ind(int i) {
+ assert(i < jcp.alpha * jcp.alpha);
+ return (31 - i);
+ }
+
+ Xmm vreg_inp(int i) {
+ return Xmm(reg_inp_ind(i));
+ }
+
+ Zmm zmm_inp(int i) {
+ return Zmm(reg_inp_ind(i));
+ }
+
+ Xmm vreg_tmp(int i) {
+ assert(i < jcp.alpha * jcp.alpha);
+ return Xmm(15 - i);
+ }
+ Xmm vreg_out(int i) {
+ assert(i < jcp.alpha * jcp.alpha);
+ return Xmm(31 - i);
+ }
+
+ Opmask y_mask = Opmask(1);
+ Opmask r_mask = Opmask(2);
+ Opmask x_mask(int id) {
+ assert(id < 4);
+ return Opmask(3 + id);
+ }
+
+ Reg64 reg_ptr_src = r14;
+ Reg64 reg_ptr_dst = r13;
+
+ Reg64 reg_ptr_v_y_masks = r12;
+ Reg64 reg_ptr_v_x_masks = r11;
+
+ Reg64 reg_aux_ptr_src = r10;
+ Reg64 reg_aux_ptr_dst = r9;
+
+ Reg64 reg_ic_block = r8;
+
+ int unsign_val_in_wino_domain;
+
+ Reg64 reg_scratch_src_alpha = rdx;
+ Xmm xmm_src_alpha = Xmm(0);
+ Zmm zmm_src_alpha = Zmm(0);
+
+ Reg64 reg_shift = rax;
+ Xmm xmm_shift = Xmm(1);
+ Xmm xmm_zero = Xmm(0);
+
+ Reg64 reg_maskx = rbx;
+ Reg64 reg_masky = rsi;
+ Reg64 reg_nomask = reg_maskx;
+};
+
+void jit_avx512_core_u8s8s32x_wino_conv_src_trans_t::generate() {
+ Label ic_block_label;
+ Label end_label;
+ Label mask_label;
+ Label nomask_label;
+
+ auto load_src = [=](bool mask) {
+ for (int y = 0; y < jcp.alpha; y++) {
+ if (mask)
+ kmovw(y_mask, ptr[reg_ptr_v_y_masks + sizeof(uint16_t) * y]);
+ for (int x = 0; x < jcp.alpha; x++) {
+ Zmm zmm_i = zmm_inp(y * jcp.alpha + x);
+ Xmm vreg_i = vreg_inp(y * jcp.alpha + x);
+ int inp_offset = sizeof(uint8_t)
+ * ((-jcp.t_pad + y) * jcp.iw * jcp.ic
+ + (-jcp.l_pad + x) * jcp.ic);
+ if (mask) {
+ kandw(r_mask, y_mask, x_mask(x));
+ vmovdqu8(vreg_i | r_mask | T_z,
+ EVEX_compress_addr(reg_aux_ptr_src, inp_offset));
+ } else {
+ vmovdqu8(vreg_i,
+ EVEX_compress_addr(reg_aux_ptr_src, inp_offset));
+ }
+ vpmovzxbd(zmm_i, vreg_i); // to int32
+ vcvtdq2ps(zmm_i, zmm_i); // to fp32
+ vmulps(zmm_i, zmm_i, zmm_src_alpha); // *alpha
+ vcvtps2dq(zmm_i, zmm_i); // to int32
+ vpmovusdb(vreg_i, zmm_i); // to u8
+ }
+ }
+ };
+
+ preamble();
+
+# define READ_PARAM(reg, field) \
+ mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)])
+ READ_PARAM(reg_ptr_src, src);
+ READ_PARAM(reg_ptr_dst, wino_src);
+ READ_PARAM(reg_ptr_v_y_masks, v_y_masks);
+ READ_PARAM(reg_ptr_v_x_masks, v_x_masks);
+# undef READ_PARAM
+
+ mov(reg_maskx, ptr[reg_ptr_v_x_masks]);
+ mov(reg_masky, ptr[reg_ptr_v_y_masks]);
+ test(reg_maskx, reg_maskx);
+ jz(end_label, T_NEAR); // skip kernel if x mask is all 0's
+ test(reg_masky, reg_masky);
+ jz(end_label, T_NEAR); // skip kernel if y mask is all 0's
+ and_(reg_maskx, reg_masky);
+ mov(reg_nomask, reg_maskx);
+ not_(reg_nomask); // zero if x and y masks are all 1's
+
+ xor_(reg_shift, reg_shift);
+ mov(reg_shift.cvt8(), (int8_t)-128);
+
+ mov(reg_aux_ptr_src, reg_ptr_src);
+ mov(reg_aux_ptr_dst, reg_ptr_dst);
+
+ for (int i = 0; i < jcp.alpha; i++) {
+ kmovw(x_mask(i), ptr[reg_ptr_v_x_masks + sizeof(uint16_t) * i]);
+ }
+
+ mov(reg_scratch_src_alpha, float2int(adj_src_scale));
+
+ mov(reg_ic_block, jcp.ic / load_block);
+ L(ic_block_label);
+ {
+ vmovq(xmm_src_alpha, reg_scratch_src_alpha);
+ vbroadcastss(zmm_src_alpha, xmm_src_alpha);
+
+ test(reg_nomask, reg_nomask);
+ jz(nomask_label, T_NEAR);
+ load_src(true);
+ jmp(mask_label, T_NEAR);
+ L(nomask_label);
+ load_src(false);
+ L(mask_label);
+
+ for(int y = 0; y < 4; y++) {
+ vpsubb(vreg_tmp(y*4+0), vreg_inp(y*4+0), vreg_inp(y*4+2));
+ vpaddb(vreg_tmp(y*4+1), vreg_inp(y*4+1), vreg_inp(y*4+2));
+ vpsubb(vreg_tmp(y*4+2), vreg_inp(y*4+2), vreg_inp(y*4+1));
+ vpsubb(vreg_tmp(y*4+3), vreg_inp(y*4+1), vreg_inp(y*4+3));
+ }
+ for(int x = 0;x < 4; x++) {
+ vpsubb(vreg_out(x+0*4), vreg_tmp(x+4*0), vreg_tmp(x+4*2));
+ vpaddb(vreg_out(x+1*4), vreg_tmp(x+4*1), vreg_tmp(x+4*2));
+ vpsubb(vreg_out(x+2*4), vreg_tmp(x+4*2), vreg_tmp(x+4*1));
+ vpsubb(vreg_out(x+3*4), vreg_tmp(x+4*1), vreg_tmp(x+4*3));
+ }
+
+ vmovd(xmm_shift, reg_shift.cvt32());
+ vpxor(xmm_zero, xmm_zero, xmm_zero);
+ vpshufb(xmm_shift, xmm_shift, xmm_zero);
+
+ for (int i = 0; i < 16; i++) {
+ int out_offset = sizeof(uint8_t) * (jcp.inp_stride * i);
+ if (i != unsign_val_in_wino_domain)
+ vpsubb(vreg_out(i), vreg_out(i), Xmm(1));
+ vmovups(EVEX_compress_addr(reg_aux_ptr_dst, out_offset), vreg_out(i));
+ }
+
+ add(reg_aux_ptr_src, sizeof(uint8_t) * load_block);
+ add(reg_aux_ptr_dst, sizeof(uint8_t) * load_block);
+ }
+ dec(reg_ic_block);
+ jnz(ic_block_label, T_NEAR);
+
+ L(end_label);
+ postamble();
+}
+
+/// DST TRANSFORMS /////////////////////////////////////////////////////////////
+struct jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(
+ jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t)
+
+ jit_conv_conf_2x3_wino_t jcp;
+ const primitive_attr_t &attr_;
+
+ struct call_params_t {
+ const void *wino_dst;
+ const void *dst;
+ const void *v_y_masks;
+ const void *v_x_masks;
+
+ const void *bias;
+ const void *scales;
+ };
+ void (*ker_)(const call_params_t *);
+
+ jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t(
+ jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr) {
+ generate();
+ ker_ = reinterpret_cast<decltype(ker_)>(const_cast<uint8_t*>(getCode()));
+ }
+
+ void generate();
+ bool maybe_relu(int position);
+
+ Zmm vreg_inp(int i) { // 16
+ assert(i < jcp.alpha * jcp.alpha);
+ return Zmm(31 - i);
+ }
+ Zmm vreg_stg(int id) { // 8
+ const int id_reg_stg = jcp.alpha * jcp.alpha + id;
+ assert(id < 8);
+ return Zmm(31 - id_reg_stg);
+ }
+ Zmm vreg_out(int id) { // 4
+ const int id_reg_out = jcp.alpha * jcp.alpha + 8 + id;
+ assert(id < 4);
+ return Zmm(31 - id_reg_out);
+ }
+ Xmm xmm_out(int id) { // 4
+ const int id_reg_out = jcp.alpha * jcp.alpha + 8 + id;
+ assert(id < 4);
+ return Xmm(31 - id_reg_out);
+ }
+ Zmm vreg_tmp(int id) { // 2
+ const int id_reg_tmp = jcp.alpha * jcp.alpha + 12 + id;
+ assert(id < 2);
+ return Zmm(31 - id_reg_tmp);
+ }
+
+ Zmm vreg_zero = Zmm(0);
+ Zmm vreg_bias = Zmm(1);
+ Zmm vreg_prev_dst = Zmm(2);
+ Zmm zmm_bias_alpha = Zmm(2);
+ Xmm xmm_bias_alpha = Xmm(2);
+
+ Opmask y_mask = Opmask(1);
+ Opmask r_mask = Opmask(2);
+ Opmask x_mask(int id) {
+ assert(id < 4);
+ return Opmask(3 + id);
+ }
+
+ Reg64 reg_scratch_bias_alpha = r15;
+
+ Reg64 reg_ptr_src = r14;
+ Reg64 reg_ptr_dst = r13;
+
+ Reg64 reg_ptr_v_y_masks = r12;
+ Reg64 reg_ptr_v_x_masks = r11;
+
+ Reg64 reg_aux_ptr_src = r10;
+ Reg64 reg_aux_ptr_dst = r9;
+
+ Reg64 reg_oc_block = r8;
+
+ Reg64 reg_ptr_bias = rbx;
+ Reg64 reg_ptr_scales = abi_not_param1;
+ Reg64 reg_ptr_sum_scale = rdx;
+};
+
+bool jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t::maybe_relu(int position) {
+ using namespace primitive_kind;
+ const auto &p = attr_.post_ops_;
+
+ if (position == 0) {
+ /* relu before sum */
+ return false
+ || p.contain(eltwise, 0)
+ || (jcp.dst_dt == data_type::u8 && !p.contain(sum, 0));
+ } else if (position == 1) {
+ /* relu after sum */
+ const int sum_idx = p.contain(sum, 0)
+ ? 0 : (p.contain(sum, 1) ? 1 : -1);
+ if (sum_idx == -1)
+ return false;
+
+ return false
+ || p.contain(eltwise, sum_idx + 1)
+ || jcp.dst_dt == data_type::u8;
+ }
+
+ return false;
+}
+
+void jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t::generate() {
+ Label oc_block_label;
+
+ auto loop_body = [=]() {
+ const auto &p = attr_.post_ops_;
+ const int sum_idx = p.find(primitive_kind::sum);
+ const float *p_sum_scale = (sum_idx != -1)
+ ? &p.entry_[sum_idx].sum.scale
+ : nullptr;
+ if (p_sum_scale && *p_sum_scale != 1.f)
+ mov(reg_ptr_sum_scale, (size_t)p_sum_scale);
+
+ for(int i = 0; i < 16; i++) {
+ int internal_offset = sizeof(int32_t) * jcp.out_stride * i;
+ vmovups(vreg_inp(i),
+ EVEX_compress_addr(reg_aux_ptr_src, internal_offset));
+ }
+ for(int y = 0; y < jcp.alpha; y++) {
+ vpaddd(vreg_tmp(0), vreg_inp(y*4 + 0), vreg_inp(y*4 + 1));
+ vpaddd(vreg_stg(y*2), vreg_tmp(0), vreg_inp(y*4 + 2));
+
+ vpsubd(vreg_tmp(1), vreg_inp(y*4 + 1), vreg_inp(y*4 + 2));
+ vpsubd(vreg_stg(y*2+1), vreg_tmp(1), vreg_inp(y*4 + 3));
+ }
+ for(int x = 0; x < jcp.m; x++) {
+ vpaddd(vreg_tmp(0), vreg_stg(x), vreg_stg(x+2*1));
+ vpaddd(vreg_out(x), vreg_tmp(0), vreg_stg(x+2*2));
+
+ vpsubd(vreg_tmp(1), vreg_stg(x+2*1), vreg_stg(x+2*2));
+ vpsubd(vreg_out(x+2), vreg_tmp(1), vreg_stg(x+2*3));
+ }
+
+
+ if (jcp.with_bias) {
+ vmovq(xmm_bias_alpha, reg_scratch_bias_alpha);
+ vbroadcastss(zmm_bias_alpha, xmm_bias_alpha);
+
+ auto bias_addr = ptr [ reg_ptr_bias ];
+ switch (jcp.bia_dt) {
+ case data_type::f32:
+ case data_type::s32: vmovups(vreg_bias, bias_addr); break;
+ case data_type::s8: vpmovsxbd(vreg_bias, bias_addr); break;
+ case data_type::u8: vpmovzxbd(vreg_bias, bias_addr); break;
+ default: assert(!"unsupported dst data type");
+ }
+ if (jcp.bia_dt != data_type::f32)
+ vcvtdq2ps(vreg_bias, vreg_bias);
+ vmulps(vreg_bias, vreg_bias, zmm_bias_alpha); // *alpha
+ }
+ for(int y = 0; y < jcp.m; y++) {
+ kmovw(y_mask, ptr[ reg_ptr_v_y_masks + sizeof(uint16_t) * y ]);
+ for(int x = 0; x < jcp.m; x++) {
+ kandw(r_mask, y_mask, x_mask(x));
+
+ int i = y * jcp.m + x;
+ int offset = jcp.typesize_out *
+ (y * jcp.ow * jcp.oc + x * jcp.oc);
+ Address addr = EVEX_compress_addr(reg_aux_ptr_dst, offset);
+
+ Zmm zmm = vreg_out(i);
+ Xmm xmm = xmm_out(i);
+ vcvtdq2ps(zmm, zmm);
+ if (jcp.with_bias)
+ vaddps(zmm, zmm, vreg_bias);
+ vmulps(zmm, zmm, ptr [reg_ptr_scales]);
+ if (maybe_relu(0))
+ vmaxps(zmm, vreg_zero, zmm);
+ if (p_sum_scale) { // post_op: sum
+ vpxord(vreg_prev_dst, vreg_prev_dst, vreg_prev_dst);
+ switch (jcp.dst_dt) {
+ case data_type::f32:
+ case data_type::s32:
+ vmovups(vreg_prev_dst | r_mask, addr); break;
+ case data_type::s8:
+ vpmovsxbd(vreg_prev_dst | r_mask, addr); break;
+ case data_type::u8:
+ vpmovzxbd(vreg_prev_dst | r_mask, addr); break;
+ default: assert(!"unknown dst_dt");
+ }
+ if (jcp.dst_dt != data_type::f32)
+ vcvtdq2ps(vreg_prev_dst, vreg_prev_dst);
+ if (*p_sum_scale == 1.f)
+ vaddps(zmm, vreg_prev_dst);
+ else
+ vfmadd231ps(zmm, vreg_prev_dst,
+ zword_b[reg_ptr_sum_scale]);
+ }
+ if (maybe_relu(1))
+ vmaxps(zmm, vreg_zero, zmm);
+ if (jcp.dst_dt != data_type::f32)
+ vcvtps2dq(zmm, zmm);
+ switch (jcp.dst_dt) {
+ case data_type::f32:
+ case data_type::s32:
+ vmovups(addr, zmm | r_mask); break;
+ case data_type::s8:
+ vpmovsdb(xmm, zmm); vmovups(addr, xmm | r_mask); break;
+ case data_type::u8:
+ vpmovusdb(xmm, zmm); vmovups(addr, xmm | r_mask); break;
+ default: assert(!"unknown dst_dt");
+ }
+ }
+ }
+ };
+
+ preamble();
+
+# define READ_PARAM(reg, field) \
+ mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)])
+ READ_PARAM(reg_ptr_src, wino_dst);
+ READ_PARAM(reg_ptr_dst, dst);
+ READ_PARAM(reg_ptr_v_y_masks, v_y_masks);
+ READ_PARAM(reg_ptr_v_x_masks, v_x_masks);
+ READ_PARAM(reg_ptr_bias, bias);
+ READ_PARAM(reg_ptr_scales, scales);
+# undef READ_PARAM
+
+ if (jcp.with_bias)
+ mov(reg_scratch_bias_alpha, float2int(adj_src_scale * adj_wei_scale));
+
+ mov(reg_aux_ptr_src, reg_ptr_src);
+ mov(reg_aux_ptr_dst, reg_ptr_dst);
+
+ vpxord(vreg_zero, vreg_zero, vreg_zero);
+
+ for (int i = 0; i < jcp.m; i++)
+ kmovw(x_mask(i), ptr[reg_ptr_v_x_masks + sizeof(uint16_t) * i]);
+
+ int oc_blocks = jcp.oc / load_block;
+ mov(reg_oc_block, oc_blocks);
+ L(oc_block_label); {
+ loop_body();
+ add(reg_aux_ptr_src, sizeof(int32_t) * load_block);
+ add(reg_aux_ptr_dst, jcp.typesize_out * load_block);
+
+ add(reg_ptr_scales, jcp.is_oc_scale * sizeof(float) * load_block);
+ add(reg_ptr_bias, sizeof(jcp.typesize_bia) * load_block);
+ }
+ dec(reg_oc_block);
+ jnz(oc_block_label, T_NEAR);
+
+ postamble();
+
+}
+
+/// GEMM kernel ////////////////////////////////////////////////////////////////
+struct jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t)
+ jit_conv_conf_2x3_wino_t jcp;
+ const primitive_attr_t &attr_;
+
+ struct call_params_t {
+ const void *src;
+ const void *dst;
+ const void *wei;
+ const void *dst_b;
+ };
+ void (*ker_)(const call_params_t *);
+
+ void generate();
+ static bool post_ops_ok(jit_conv_conf_2x3_wino_t &jcp,
+ const primitive_attr_t &attr);
+
+ jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t(
+ jit_conv_conf_2x3_wino_t ajcp, const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr)
+ {
+ generate();
+ ker_ = reinterpret_cast<decltype(ker_)>(const_cast<uint8_t*>(getCode()));
+ }
+
+ static status_t init_conf(
+ jit_conv_conf_2x3_wino_t &jcp, const convolution_desc_t &cd,
+ memory_desc_t &src_md, memory_desc_t &weights_md,
+ memory_desc_t &dst_md, memory_desc_t &bias_md,
+ const primitive_attr_t &attr);
+
+ Zmm vreg_out(int n, int m) {
+ const int id_reg_out = n * jcp.m_block + m;
+ assert(id_reg_out < jcp.n2_block * jcp.m_block);
+ return Zmm(31 - id_reg_out);
+ }
+ Zmm vreg_wei(int i) {
+ assert(31 - jcp.n2_block * jcp.m_block - i
+ > (jcp.ver == ver_vnni ? 0 : 2));
+ return Zmm(31 - jcp.n2_block * jcp.m_block - i);
+ }
+
+ Zmm vreg_src = Zmm(0);
+ Zmm vreg_one = Zmm(1);
+ Zmm vreg_tmp = Zmm(2);
+
+ Reg64 reg_ptr_src = r15;
+
+ Reg64 reg_aux_dst_b = r13;
+ Reg64 reg_aux_dst = r12;
+ Reg64 reg_aux_dst2 = r11;
+ Reg64 reg_aux_wei = r10;
+ Reg64 reg_aux_wei2 = r9;
+ Reg64 reg_aux_src = r8;
+ Reg64 reg_aux_src2 = rax;
+ Reg64 reg_mb = rbx;
+ Reg64 reg_nnb = abi_not_param1;
+ Reg64 reg_scratch = rdx;
+ Reg64 reg_K = rsi;
+};
+
+bool jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t::post_ops_ok(
+ jit_conv_conf_2x3_wino_t &jcp, const primitive_attr_t &attr) {
+ using namespace primitive_kind;
+ const auto &p = attr.post_ops_;
+
+ auto is_relu = [&](int idx) { return p.entry_[idx].is_relu(); };
+
+ switch (p.len_) {
+ case 0: return true;
+ case 1: return is_relu(0) || p.contain(sum, 0);
+ case 2: return (p.contain(sum, 0) && is_relu(1)) ||
+ (p.contain(sum, 1) && is_relu(0));
+ case 3: return is_relu(0) && p.contain(sum, 1) && is_relu(2);
+ default: return false;
+ }
+
+ return false;
+}
+
+void jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t::generate() {
+ Label nnb_loop_label, K_loop_label, mb_loop_label;
+
+ auto compute = [=](Zmm vreg_acc, Zmm vreg_wei, Zmm vreg_src) {
+ if (jcp.ver == ver_vnni) {
+ vpdpbusd(vreg_acc, vreg_src, vreg_wei);
+ } else {
+ vpmaddubsw(vreg_tmp, vreg_src, vreg_wei);
+ vpmaddwd(vreg_tmp, vreg_tmp, vreg_one);
+ vpaddd(vreg_acc, vreg_acc, vreg_tmp);
+ }
+ };
+
+ preamble();
+# define READ_PARAM(reg, field) \
+ mov(reg, ptr[abi_param1 + offsetof(call_params_t, field)])
+ READ_PARAM(reg_ptr_src, src);
+ READ_PARAM(reg_aux_dst, dst);
+ READ_PARAM(reg_aux_wei, wei);
+ READ_PARAM(reg_aux_dst_b, dst_b);
+# undef READ_PARAM
+
+ if (jcp.ver != ver_vnni) {
+ xor_(reg_scratch, reg_scratch);
+ Reg16 _t = reg_scratch.cvt16();
+ mov(_t, 0x1);
+ vpbroadcastw(vreg_one, _t);
+ }
+
+ if (!jcp.small_mb) {
+ mov(reg_nnb, jcp.n_chunks);
+ L(nnb_loop_label);
+ }
+ mov(reg_aux_dst2, reg_aux_dst);
+ mov(reg_aux_src, reg_ptr_src);
+ mov(reg_mb, jcp.M / jcp.m_block);
+ L(mb_loop_label);
+ {
+ for (int nb2 = 0; nb2 < jcp.n2_block; nb2++) {
+ for (int m = 0; m < jcp.m_block; m++) {
+ int offset = jcp.typesize_acc * nb2 * jcp.n_block;
+ vmovups(vreg_out(nb2, m),
+ EVEX_compress_addr(reg_aux_dst_b, offset));
+ }
+ }
+ mov(reg_aux_src2, reg_aux_src);
+ mov(reg_aux_wei2, reg_aux_wei);
+ mov(reg_K, jcp.k_chunks);
+ L(K_loop_label);
+ {
+ for (int k = 0; k < jcp.k2_block; k += 4) {
+ for (int nb2 = 0; nb2 < jcp.n2_block; nb2++) {
+ int wei_offset
+ = jcp.typesize_in * (nb2 * jcp.n_block * jcp.K);
+ vmovups(vreg_wei(nb2),
+ EVEX_compress_addr(reg_aux_wei2, wei_offset));
+ }
+ for (int m = 0; m < jcp.m_block; m++) {
+ int inp_offset = jcp.typesize_in * m * jcp.K;
+ vpbroadcastd(vreg_src,
+ EVEX_compress_addr(reg_aux_src2, inp_offset));
+ for (int nb2 = 0; nb2 < jcp.n2_block; nb2++)
+ compute(vreg_out(nb2, m), vreg_wei(nb2), vreg_src);
+ }
+ add(reg_aux_src2, jcp.typesize_in * 4);
+ add(reg_aux_wei2, jcp.typesize_in * 4 * jcp.n_block);
+ }
+ }
+ dec(reg_K);
+ jnz(K_loop_label, T_NEAR);
+
+ for (int m = 0; m < jcp.m_block; m++) {
+ for (int nb2 = 0; nb2 < jcp.n2_block; nb2++) {
+ int offset = jcp.typesize_acc * (m * jcp.N + nb2 * jcp.n_block);
+ vmovups(EVEX_compress_addr(reg_aux_dst2, offset),
+ vreg_out(nb2, m));
+ }
+ }
+ add(reg_aux_src, jcp.typesize_in * jcp.m_block * jcp.K);
+ add(reg_aux_dst2, jcp.typesize_acc * jcp.m_block * jcp.N);
+ }
+ dec(reg_mb);
+ jnz(mb_loop_label, T_NEAR);
+
+ if (!jcp.small_mb) {
+ add(reg_aux_dst, jcp.typesize_acc * jcp.n2_block * jcp.n_block);
+ add(reg_aux_dst_b, jcp.typesize_acc * jcp.n2_block * jcp.n_block);
+ add(reg_aux_wei, jcp.typesize_in * jcp.n2_block * jcp.n_block * jcp.K);
+
+ dec(reg_nnb);
+ jnz(nnb_loop_label, T_NEAR);
+ }
+
+ postamble();
+}
+namespace {
+bool is_winograd_faster_than_direct(const jit_conv_conf_2x3_wino_t &jcp) {
+ if (jcp.ver == ver_vnni) {
+ return (jcp.mb <= mkldnn_get_max_threads()
+ && (jcp.mb > 4
+ && jcp.ic > 64
+ && !(jcp.oc > 128 && jcp.ih < 14)))
+ || jcp.mb > mkldnn_get_max_threads();
+ }
+ return true;
+}
+}
+
+status_t jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t
+::init_conf(jit_conv_conf_2x3_wino_t &jcp,
+ const convolution_desc_t &cd, memory_desc_t &src_md,
+ memory_desc_t &wei_md, memory_desc_t &dst_md,
+ memory_desc_t &bias_md, const primitive_attr_t &attr) {
+ const memory_desc_wrapper src_d(&src_md);
+ const memory_desc_wrapper wei_d(&wei_md);
+ const memory_desc_wrapper dst_d(&dst_md);
+ const memory_desc_wrapper bias_d(&bias_md);
+
+ const bool with_groups = wei_d.ndims() == src_d.ndims() + 1;
+
+ jcp.nthr = mkldnn_get_max_threads();
+
+ jcp.ngroups = with_groups ? wei_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.ih = src_d.dims()[2];
+ jcp.iw = src_d.dims()[3];
+ jcp.oh = dst_d.dims()[2];
+ jcp.ow = dst_d.dims()[3];
+ jcp.kh = wei_d.dims()[with_groups + 2];
+ jcp.kw = wei_d.dims()[with_groups + 3];
+ jcp.t_pad = cd.padding[0][0];
+ jcp.b_pad = cd.padding[1][0];
+ jcp.l_pad = cd.padding[0][1];
+ jcp.r_pad = cd.padding[1][1];
+ jcp.stride_h = cd.strides[0];
+ jcp.stride_w = cd.strides[1];
+ jcp.dilate_h = cd.dilates[0];
+ jcp.dilate_w = cd.dilates[1];
+
+ jcp.ver = ver_avx512_core;
+ if (!(mayiuse(avx512_core) &&
+ src_d.data_type() == data_type::u8
+ && wei_d.data_type() == data_type::s8
+ && one_of(dst_d.data_type(), data_type::f32, data_type::s32,
+ data_type::s8, data_type::u8)))
+ return status::unimplemented;
+ if (mayiuse(avx512_core_vnni))
+ jcp.ver = ver_vnni;
+
+ if (!IMPLICATION(cd.alg_kind == alg_kind::convolution_auto,
+ is_winograd_faster_than_direct(jcp)))
+ return status::unimplemented;
+
+ // block sizes needed for GEMM kernel
+ jcp.ic_block = 4;
+ jcp.oc_block = 16;
+
+ bool ok = true
+ && jcp.ngroups == 1
+ && jcp.oc % load_block == 0 && jcp.ic % load_block == 0
+ && jcp.oc % jcp.oc_block == 0 && jcp.ic % jcp.ic_block == 0
+ && everyone_is(3, jcp.kh, jcp.kw)
+ && everyone_is(1, jcp.stride_h, jcp.stride_w)
+ && everyone_is(0, jcp.dilate_h, jcp.dilate_w)
+ && jcp.t_pad == jcp.b_pad && jcp.l_pad == jcp.r_pad
+ && one_of(jcp.t_pad, 0, 1)
+ && one_of(jcp.l_pad, 0, 1);
+ if (!ok) return status::unimplemented;
+
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ jcp.bia_dt = jcp.with_bias ? cd.bias_desc.data_type : data_type::undef;
+ jcp.dst_dt = cd.dst_desc.data_type;
+
+ jcp.typesize_in = types::data_type_size(src_d.data_type());
+ jcp.typesize_out = types::data_type_size(dst_d.data_type());
+ jcp.typesize_acc = sizeof(int32_t);
+ jcp.typesize_bia = jcp.with_bias
+ ? types::data_type_size(bias_d.data_type())
+ : 0;
+
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+
+ jcp.m = 2;
+ jcp.r = 3;
+ jcp.alpha = jcp.m + jcp.r - 1;
+
+ int aa = jcp.alpha * jcp.alpha;
+ int L1_cap = get_cache_size(1, true);
+ int L2_cap = get_cache_size(2, true);
+ // need 1 extra reg for bcast, and 2 tmp regs for non-vnni
+ int free_regs = jcp.ver == ver_vnni ? 31 : 29;
+
+ auto get_thr_eff = [&](int small_mb, int ix, int iy, int n2_b) {
+ float thr_eff;
+ float Z = (float)jcp.ic + jcp.oc;
+ float Y = (float)jcp.ic * jcp.oc;
+ if (small_mb == 0) { // outer par
+ int nblocks = jcp.mb * div_up(jcp.oh, iy) * div_up(jcp.ow, ix);
+ thr_eff = (float)nblocks / rnd_up(nblocks, jcp.nthr);
+ } else { // inner par
+ int tranw = iy * ix / jcp.alpha;
+ int gemmw = aa * (jcp.nb_oc / n2_b);
+ int tranw_r = rnd_up(tranw, jcp.nthr);
+ int gemmw_r = rnd_up(gemmw, jcp.nthr);
+ thr_eff = (Z * tranw / tranw_r + Y * gemmw / gemmw_r) / (Z + Y);
+ }
+ return thr_eff;
+ };
+
+ auto get_mem_eff = [&](int small_mb, int ix, int iy, int n2_b) {
+ float mem_eff, req_mem;
+ int M = ix * iy / jcp.alpha;
+ if (small_mb == 0) { // outer parallelization strategy
+ // memory for wino transforms (other memory has poor reuse)
+ req_mem = (float)aa * M * (jcp.ic + jcp.typesize_acc * jcp.oc);
+ mem_eff = req_mem < L1_cap ? 1.f : req_mem < L2_cap ? 0.5f : 0.f;
+ } else { // inner parallelization strategy
+ // memory used during gemm
+ int N = jcp.oc_block * n2_b;
+ req_mem = (float)jcp.ic * (M + N) + jcp.typesize_acc * M * N;
+ mem_eff = nstl::min(1.f, L2_cap / req_mem);
+ // memory used during wino transforms
+ int M_per_thr = div_up(M, jcp.nthr);
+ req_mem = (float)aa * M_per_thr
+ * (jcp.ic + jcp.typesize_acc * jcp.oc);
+ if (req_mem > L2_cap)
+ mem_eff = 0.1f;
+ }
+ return mem_eff;
+ };
+
+ auto get_tot_eff = [&](int small_mb, float thr_eff, float work_eff,
+ float mem_eff, float reg_eff) {
+ // these coefficients are chosen empirically
+ float mem_fac = 0.1f, reg_fac = 0.2f;
+ // normalized overhead relative to memory and register components
+ float tot_eff = 1.f + mem_fac * mem_eff + reg_fac * reg_eff;
+ // thread and work components affect all others
+ tot_eff *= thr_eff * work_eff;
+ return tot_eff;
+ };
+
+ auto find_m_n2_blocks = [&](bool small_mb, int ix, int iy, float work_eff,
+ int &m_block, int &n2_block, float &tot_eff) {
+ int M = (ix * iy) / jcp.alpha;
+ int max_m_block = nstl::min(M, free_regs);
+ int max_n2_block = nstl::min(jcp.nb_oc, free_regs);
+ tot_eff = 0.f;
+ for (int im = max_m_block; im > 0; im--) {
+ if (M % im)
+ continue;
+ for (int in2 = max_n2_block; in2 > 0; in2--) {
+ int used_regs = (im + 1) * in2;
+ float mem_eff = get_mem_eff(small_mb, ix, iy, in2);
+ float reg_eff = (float)(im * in2) / (im + in2);
+ float thr_eff = get_thr_eff(small_mb, ix, iy, in2);
+ float cur_tot_eff = get_tot_eff(
+ small_mb, thr_eff, work_eff, mem_eff, reg_eff);
+ if (jcp.nb_oc % in2 || used_regs > free_regs
+ || cur_tot_eff <= tot_eff)
+ continue;
+ tot_eff = cur_tot_eff;
+ m_block = im;
+ n2_block = in2;
+ }
+ }
+ };
+
+ /* Selecting xb and yb blocking */
+ int min_yb = jcp.m;
+ int min_xb = jcp.m;
+ int max_yb = nstl::max(min_yb, rnd_up(jcp.oh, 2));
+ int max_xb = nstl::max(min_xb, rnd_up(jcp.ow, 2));
+ float best_eff = 0.f;
+ for (int ix = min_xb; ix <= max_xb; ix += 2) {
+ assert(rnd_up(jcp.ow, ix) >= jcp.iw - 2);
+ for (int iy = max_yb; iy >= min_yb; iy -= 2) {
+ assert(rnd_up(jcp.oh, iy) >= jcp.ih - 2);
+
+ int m_b[2];
+ int n2_b[2];
+ bool small_mb;
+ float inner_eff, outer_eff, work_eff;
+
+ int tiled_area = rnd_up(jcp.oh, iy) * rnd_up(jcp.ow, ix);
+ work_eff = (float)jcp.oh * jcp.ow / tiled_area;
+ if (best_eff > 0.f && work_eff < 4.f / 9.f)
+ continue; // no gain from Winograd transformation
+
+ /* outer parallelization */
+ find_m_n2_blocks(0, ix, iy, work_eff, m_b[0], n2_b[0], outer_eff);
+
+ /* inner parallelization */
+ find_m_n2_blocks(1, ix, iy, work_eff, m_b[1], n2_b[1], inner_eff);
+
+ small_mb = inner_eff > outer_eff;
+ float eff = small_mb ? inner_eff : outer_eff;
+ if (eff > best_eff) {
+ best_eff = eff;
+ jcp.yb = iy;
+ jcp.xb = ix;
+ jcp.m_block = m_b[small_mb];
+ jcp.n2_block = n2_b[small_mb];
+ jcp.small_mb = small_mb;
+ }
+ }
+ }
+
+ assert((jcp.m_block + 1) * jcp.n2_block <= free_regs);
+ assert(jcp.xb % 2 == 0 && jcp.yb % 2 == 0);
+
+ jcp.mb_block = 1;
+ if (jcp.small_mb) {
+ // For small mb harness, set mb_block as large as possible subject to
+ // the constraint that winograd activations fit into available L3 cache
+ int L3_cap = get_cache_size(3, true);
+ int M = jcp.xb * jcp.yb / 4;
+ int wino_src_size = 16 * M * jcp.ic * jcp.typesize_in;
+ int wino_dst_size = 16 * M * jcp.oc * jcp.typesize_acc;
+ int max_mb_block = nstl::min(
+ jcp.mb, jcp.nthr * L3_cap / (wino_src_size + wino_dst_size));
+ for (int i = max_mb_block; i > 1; i--) {
+ if (jcp.mb % i == 0) {
+ jcp.mb_block = i;
+ break;
+ }
+ }
+ }
+ jcp.nb_mb = jcp.mb / jcp.mb_block;
+
+ jcp.M = jcp.mb_block * jcp.xb * jcp.yb / 4;
+ jcp.N = jcp.oc;
+ jcp.K = jcp.ic;
+
+ jcp.inp_stride = jcp.M * jcp.ic;
+ jcp.out_stride = jcp.M * jcp.oc;
+ jcp.wei_stride = jcp.ic * jcp.oc;
+ jcp.bia_stride = jcp.oc;
+
+ jcp.n_block = jcp.oc_block;
+ jcp.k_block = jcp.ic_block;
+
+ jcp.n_chunks = (jcp.N / jcp.n_block) / jcp.n2_block;
+
+ // We need jcp.k2_block to be a multiple of jcp.k_block = jcp.ic_block = 4
+ // and jcp.K = jcp.ic to be a multiple of jcp.k2_block. Since jcp.ic is
+ // a multiple of load_block = 16, we just use that for now.
+ jcp.k2_block = load_block;
+ jcp.k_chunks = jcp.K / jcp.k2_block;
+
+ const auto &oscales = attr.output_scales_;
+ jcp.is_oc_scale = oscales.mask_ == 1 << 1;
+ assert(IMPLICATION(!jcp.is_oc_scale, oscales.mask_ == 0));
+
+ /* re-create weights primitive descriptor
+ and set weights wino_blocking */
+ memory_desc_t expect_wei_md = wei_md;
+
+ expect_wei_md.format_kind = format_kind::wino;
+ expect_wei_md.data_type = data_type::s8;
+ mkldnn_wino_desc_t &wd = expect_wei_md.format_desc.wino_desc;
+ wd.wino_format = mkldnn_wino_wei_aaOIoi;
+ wd.r = jcp.r;
+ wd.alpha = jcp.alpha;
+ wd.ic = jcp.ic;
+ wd.oc = jcp.oc;
+ wd.ic_block = jcp.ic_block;
+ wd.oc_block = jcp.oc_block;
+ wd.oc2_block = jcp.n2_block;
+ wd.ic2_block = 1;
+ wd.adj_scale = adj_wei_scale;
+
+ size_t max_size = types::data_type_size(data_type::s8) *
+ jcp.alpha * jcp.alpha * jcp.ic * jcp.oc;
+ max_size += types::data_type_size(data_type::s32) *
+ jcp.alpha * jcp.alpha * jcp.oc;
+ wd.size = max_size;
+
+ if (wei_md.format_kind == format_kind::any)
+ wei_md = expect_wei_md;
+ if (wei_md != expect_wei_md)
+ return status::unimplemented;
+
+ const int tilesize = jcp.alpha * jcp.alpha;
+ const int numtiles = jcp.M;
+ const int alltiles = numtiles * tilesize;
+
+ jcp.size_wino_src
+ = utils::rnd_up(jcp.typesize_in * alltiles * jcp.ic, PAGE_4K)
+ / jcp.typesize_in;
+ jcp.size_wino_wei = tilesize * jcp.oc * jcp.ic;
+ jcp.size_wino_dst = alltiles * jcp.oc;
+
+ return status::success;
+}
+////////////////////////////////////////////////////////////////////////////////
+
+template <data_type_t dst_data_type>
+status_t jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<dst_data_type>::
+ pd_t::jit_conf() {
+ return jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t::init_conf(
+ jcp_, *this->desc(), this->src_md_, this->weights_md_,
+ this->dst_md_,this->bias_md_, *this->attr());
+}
+
+template <data_type_t dst_data_type>
+void jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<dst_data_type>::pd_t::
+init_scratchpad() {
+ auto scratchpad = this->scratchpad_registry().registrar();
+
+ int nthr_multiplier = jcp_.small_mb ? 1 : jcp_.nthr;
+ scratchpad.book(key_wino_V,
+ sizeof(src_data_t) * jcp_.size_wino_src * nthr_multiplier, PAGE_4K);
+ scratchpad.book(key_wino_M,
+ sizeof(acc_data_t) * jcp_.size_wino_dst * nthr_multiplier, PAGE_4K);
+
+ dim_t scale_count = attr()->output_scales_.count_;
+ scratchpad.book(key_conv_adjusted_scales,
+ sizeof(float) * nstl::max<dim_t>(scale_count, 16));
+}
+
+template <data_type_t dst_data_type>
+jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<dst_data_type>::
+ jit_avx512_core_u8s8s32x_wino_convolution_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+{
+ kernel_ = new jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t(
+ pd()->jcp_, *pd()->attr());
+ src_trans_ = new jit_avx512_core_u8s8s32x_wino_conv_src_trans_t(
+ pd()->jcp_, *pd()->attr());
+ dst_trans_ = new jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t(
+ pd()->jcp_, *pd()->attr());
+}
+
+template <data_type_t dst_data_type>
+jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<dst_data_type>::
+ ~jit_avx512_core_u8s8s32x_wino_convolution_fwd_t() {
+ delete kernel_;
+ delete src_trans_;
+ delete dst_trans_;
+}
+
+template <data_type_t dst_data_type>
+const float *jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<dst_data_type>::
+adjust_oscales(const memory_tracking::grantor_t &scratchpad) const {
+ const float *oscales = pd()->attr()->output_scales_.scales_;
+ auto loc_scales = scratchpad.template get<float>(key_conv_adjusted_scales);
+ size_t count = pd()->attr()->output_scales_.count_;
+ float factor = 1.f / (adj_src_scale * adj_wei_scale);
+ if (count == 1)
+ utils::array_set(loc_scales, oscales[0] * factor, 16);
+ else
+ for (size_t c = 0; c < count; c++) loc_scales[c] = oscales[c] * factor;
+ return loc_scales;
+}
+
+template <data_type_t dst_data_type>
+void jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<dst_data_type>::
+execute_forward(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ const auto &jcp = kernel_->jcp;
+ if (jcp.small_mb)
+ execute_forward_small_mb(src, weights, bias, dst, this->scratchpad(ctx));
+ else
+ execute_forward_mbN(src, weights, bias, dst, this->scratchpad(ctx));
+}
+
+template <data_type_t dst_data_type>
+void jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<dst_data_type>::
+execute_forward_mbN(const src_data_t *src, const wei_data_t *wei,
+ const char *bia, dst_data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const auto &jcp = kernel_->jcp;
+ const float *oscales = adjust_oscales(scratchpad);
+
+ auto dst_bias = (const acc_data_t *)(wei + jcp.size_wino_wei);
+ auto wino_src_base = scratchpad.template get<src_data_t>(key_wino_V);
+ auto wino_dst_base = scratchpad.template get<acc_data_t>(key_wino_M);
+
+ parallel_nd(jcp.mb, div_up(jcp.oh, jcp.yb), div_up(jcp.ow, jcp.xb),
+ [&](int mb, int tile_y_b, int tile_x_b) {
+
+ int tile_y = tile_y_b * jcp.yb;
+ int tile_x = tile_x_b * jcp.xb;
+
+ int ithr = mkldnn_get_thread_num();
+ auto wino_src = wino_src_base + jcp.size_wino_src * ithr;
+ auto wino_dst = wino_dst_base + jcp.size_wino_dst * ithr;
+
+ auto src_trans_p =
+ jit_avx512_core_u8s8s32x_wino_conv_src_trans_t::call_params_t();
+ auto dst_trans_p =
+ jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t::call_params_t();
+ auto gemm_p =
+ jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t::call_params_t();
+
+ /* transformation of input tensor to winograd domain */
+ for (int y_in_block = 0; y_in_block < jcp.yb; y_in_block += 2) {
+ for (int x_in_block = 0; x_in_block < jcp.xb; x_in_block += 2) {
+ uint16_t v_y_masks[4], v_x_masks[4];
+
+ int y = y_in_block + tile_y;
+ int x = x_in_block + tile_x;
+ int m = (y_in_block / 2) * (jcp.xb / 2) + (x_in_block / 2);
+
+ int v_ys = nstl::max(0, jcp.t_pad - y);
+ int v_ye = nstl::min(jcp.alpha,
+ nstl::max(0, jcp.ih + jcp.t_pad - y));
+
+ int v_xs = nstl::max(0, jcp.l_pad - x);
+ int v_xe = nstl::min(jcp.alpha,
+ nstl::max(0, jcp.iw + jcp.l_pad - x));
+
+#pragma unroll(4)
+ for (int i = 0; i < jcp.alpha; i++) {
+ v_y_masks[i] = uint16_t(i < v_ys || i >= v_ye ? 0 : 0xffff);
+ v_x_masks[i] = uint16_t(i < v_xs || i >= v_xe ? 0 : 0xffff);
+ }
+ auto local_s = src
+ + mb * jcp.ih * jcp.iw * jcp.ic
+ + y * jcp.iw * jcp.ic + x * jcp.ic;
+ auto local_w = wino_src + m * jcp.ic;
+
+ src_trans_p.src = local_s;
+ src_trans_p.wino_src = local_w;
+ src_trans_p.v_y_masks = v_y_masks;
+ src_trans_p.v_x_masks = v_x_masks;
+
+ src_trans_->ker_(&src_trans_p);
+ }
+ }
+ /* gemms */
+ for (int tile_ij = 0; tile_ij < 16; tile_ij++) {
+ // start threads at different GEMMs to help bring weights into LLC
+ int offset = (tile_ij + ithr) % 16;
+ gemm_p.src = wino_src + jcp.inp_stride * offset;
+ gemm_p.dst = wino_dst + jcp.out_stride * offset;
+ gemm_p.wei = wei + jcp.wei_stride * offset;
+ gemm_p.dst_b = dst_bias + jcp.bia_stride * offset;
+
+ kernel_->ker_(&gemm_p);
+ }
+
+ /* transformation from winograd domain to output tensor */
+ for (int y_in_block = 0; y_in_block < jcp.yb; y_in_block += 2) {
+ for (int x_in_block = 0; x_in_block < jcp.xb; x_in_block += 2) {
+ uint16_t v_y_masks[2], v_x_masks[2];
+
+ int y = y_in_block + tile_y;
+ int x = x_in_block + tile_x;
+ int m = (y_in_block / 2) * (jcp.xb / 2) + (x_in_block / 2);
+
+#pragma unroll(2)
+ for (int i = 0; i < jcp.m; i++) {
+ v_x_masks[i] = uint16_t(x + i < jcp.ow ? 0xffff : 0);
+ v_y_masks[i] = uint16_t(y + i < jcp.oh ? 0xffff : 0);
+ }
+ auto local_d = dst
+ + mb * jcp.oh * jcp.ow * jcp.oc
+ + y * jcp.ow * jcp.oc + x * jcp.oc;
+ auto local_w = wino_dst + m * jcp.oc;
+
+ auto scales = oscales;
+ dst_trans_p.dst = local_d;
+ dst_trans_p.wino_dst = local_w;
+ dst_trans_p.v_y_masks = v_y_masks;
+ dst_trans_p.v_x_masks = v_x_masks;
+
+ dst_trans_p.scales = scales;
+ dst_trans_p.bias = bia;
+
+ dst_trans_->ker_(&dst_trans_p);
+ }
+ }
+ });
+}
+
+template <data_type_t dst_data_type>
+void jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<dst_data_type>::
+execute_forward_small_mb(const src_data_t *src, const wei_data_t *wei,
+ const char *bia, dst_data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const auto &jcp = kernel_->jcp;
+ const float *oscales = adjust_oscales(scratchpad);
+
+ auto dst_bias = (const acc_data_t *)(wei + jcp.size_wino_wei);
+ auto wino_src = scratchpad.template get<src_data_t>(key_wino_V);
+ auto wino_dst = scratchpad.template get<acc_data_t>(key_wino_M);
+
+ for (int mbb = 0; mbb < jcp.nb_mb; mbb++) {
+ for (int tile_y = 0; tile_y < jcp.oh; tile_y += jcp.yb) {
+ for (int tile_x = 0; tile_x < jcp.ow; tile_x += jcp.xb) {
+ /* transformation of input tensor to winograd domain */
+ parallel_nd(div_up(jcp.yb, 2), div_up(jcp.xb, 2), jcp.mb_block,
+ [&](int y_in_block_b, int x_in_block_b, int mb) {
+ int y_in_block = y_in_block_b * 2;
+ int x_in_block = x_in_block_b * 2;
+
+ auto src_trans_p =
+ jit_avx512_core_u8s8s32x_wino_conv_src_trans_t::call_params_t();
+
+ uint16_t v_y_masks[4], v_x_masks[4];
+
+ int y = y_in_block + tile_y;
+ int x = x_in_block + tile_x;
+ int m = (mb * (jcp.yb / 2) + (y_in_block / 2)) * (jcp.xb / 2)
+ + (x_in_block / 2);
+
+ int v_ys = nstl::max(0, jcp.t_pad - y);
+ int v_ye = nstl::min(
+ jcp.alpha, nstl::max(0, jcp.ih + jcp.t_pad - y));
+
+ int v_xs = nstl::max(0, jcp.l_pad - x);
+ int v_xe = nstl::min(
+ jcp.alpha, nstl::max(0, jcp.iw + jcp.l_pad - x));
+
+#pragma unroll(4)
+ for (int i = 0; i < jcp.alpha; i++) {
+ v_y_masks[i] = uint16_t(i < v_ys || i >= v_ye ? 0 : 0xffff);
+ v_x_masks[i] = uint16_t(i < v_xs || i >= v_xe ? 0 : 0xffff);
+ }
+ auto local_s = src
+ + (mbb * jcp.mb_block + mb) * jcp.ih * jcp.iw * jcp.ic
+ + y * jcp.iw * jcp.ic + x * jcp.ic;
+ auto local_w = wino_src + m * jcp.ic;
+
+ src_trans_p.src = local_s;
+ src_trans_p.wino_src = local_w;
+ src_trans_p.v_y_masks = v_y_masks;
+ src_trans_p.v_x_masks = v_x_masks;
+
+ src_trans_->ker_(&src_trans_p);
+ });
+
+ /* gemms */
+ parallel_nd(16, jcp.n_chunks, [&](int tile_ij, int nnb) {
+ auto gemm_p = jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t::
+ call_params_t();
+
+ gemm_p.src = wino_src + jcp.inp_stride * tile_ij;
+ gemm_p.dst = wino_dst + jcp.out_stride * tile_ij
+ + nnb * jcp.n2_block * jcp.n_block;
+ gemm_p.wei = wei + jcp.wei_stride * tile_ij
+ + nnb * jcp.n2_block * jcp.n_block * jcp.K;
+ gemm_p.dst_b = dst_bias + jcp.bia_stride * tile_ij
+ + nnb * jcp.n2_block * jcp.n_block;
+
+ kernel_->ker_(&gemm_p);
+ });
+
+ /* transformation from winograd domain to output tensor */
+ parallel_nd(div_up(jcp.yb, 2), div_up(jcp.xb, 2), jcp.mb_block,
+ [&](int y_in_block_b, int x_in_block_b, int mb) {
+ int y_in_block = y_in_block_b * 2;
+ int x_in_block = x_in_block_b * 2;
+
+ auto dst_trans_p =
+ jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t::call_params_t();
+
+ uint16_t v_y_masks[2], v_x_masks[2];
+
+ int y = y_in_block + tile_y;
+ int x = x_in_block + tile_x;
+ int m = (mb * (jcp.yb / 2) + (y_in_block / 2)) * (jcp.xb / 2)
+ + (x_in_block / 2);
+
+#pragma unroll(2)
+ for (int i = 0; i < jcp.m; i++) {
+ v_x_masks[i] = uint16_t(x + i < jcp.ow ? 0xffff : 0);
+ v_y_masks[i] = uint16_t(y + i < jcp.oh ? 0xffff : 0);
+ }
+ auto local_d = dst
+ + (mbb * jcp.mb_block + mb) * jcp.oh * jcp.ow * jcp.oc
+ + y * jcp.ow * jcp.oc + x * jcp.oc;
+ auto local_w = wino_dst + m * jcp.oc;
+
+ auto scales = oscales;
+ dst_trans_p.dst = local_d;
+ dst_trans_p.wino_dst = local_w;
+ dst_trans_p.v_y_masks = v_y_masks;
+ dst_trans_p.v_x_masks = v_x_masks;
+
+ dst_trans_p.scales = scales;
+ dst_trans_p.bias = bia;
+
+ dst_trans_->ker_(&dst_trans_p);
+ });
+ }}}
+}
+
+template struct jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<data_type::s8>;
+template struct jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<data_type::u8>;
+template struct jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<data_type::s32>;
+template struct jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<data_type::f32>;
+
+} // namespace cpu
+} // namespace impl
+} // namespace mkldnn
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.hpp
new file mode 100644
index 0000000000..9e6e57b051
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_u8s8s32x_wino_convolution.hpp
@@ -0,0 +1,128 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_CORE_U8S8S32X_WINO_CONVOLUTION_HPP
+#define CPU_JIT_AVX512_CORE_U8S8S32X_WINO_CONVOLUTION_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_primitive_conf.hpp"
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t;
+struct jit_avx512_core_u8s8s32x_wino_conv_src_trans_t;
+struct jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t;
+
+template <data_type_t dst_data_type>
+struct jit_avx512_core_u8s8s32x_wino_convolution_fwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_()
+ {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_int8_wino:", avx512_core, ""),
+ jit_avx512_core_u8s8s32x_wino_convolution_fwd_t<dst_data_type>);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::convolution_auto,
+ alg_kind::convolution_winograd)
+ && expect_data_types(data_type::u8, data_type::s8,
+ data_type::undef, dst_data_type, data_type::s32)
+ && IMPLICATION(with_bias(), utils::one_of(
+ desc()->bias_desc.data_type, data_type::f32,
+ data_type::s32, data_type::s8, data_type::u8))
+ && !has_zero_dim_memory()
+ && set_default_formats();
+
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_conf();
+ if (status != status::success) return status;
+ set_default_alg_kind(alg_kind::convolution_winograd);
+
+ init_scratchpad();
+
+ return status;
+ }
+
+ jit_conv_conf_2x3_wino_t jcp_;
+
+ protected:
+ status_t jit_conf();
+ void init_scratchpad();
+
+ bool set_default_formats() {
+ using namespace format_tag;
+ return set_default_formats_common(nhwc, any, nhwc);
+ }
+ };
+
+ typedef typename prec_traits<data_type::u8>::type src_data_t;
+ typedef typename prec_traits<data_type::s8>::type wei_data_t;
+ typedef typename prec_traits<data_type::s32>::type acc_data_t;
+ typedef typename prec_traits<dst_data_type>::type dst_data_t;
+
+ jit_avx512_core_u8s8s32x_wino_convolution_fwd_t(const pd_t *apd);
+ ~jit_avx512_core_u8s8s32x_wino_convolution_fwd_t();
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ const float *adjust_oscales(const memory_tracking::grantor_t &scratchpad)
+ const;
+ void execute_forward(const exec_ctx_t &ctx) const;
+ void execute_forward_small_mb(const src_data_t *src, const wei_data_t *wei,
+ const char *bia, dst_data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const;
+ void execute_forward_mbN(const src_data_t *src, const wei_data_t *wei,
+ const char *bia, dst_data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx512_core_u8s8s32x_wino_conv_fwd_ker_t *kernel_;
+ jit_avx512_core_u8s8s32x_wino_conv_src_trans_t *src_trans_;
+ jit_avx512_core_u8s8s32x_wino_conv_dst_trans_t *dst_trans_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.cpp
new file mode 100644
index 0000000000..f4ec29ab00
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.cpp
@@ -0,0 +1,820 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_memory.hpp"
+
+#include "jit_uni_1x1_conv_utils.hpp"
+#include "jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp"
+
+#define GET_OFF(field) offsetof(jit_1x1_conv_call_s, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::utils;
+
+using namespace Xbyak;
+
+bool jit_avx512_core_x8s8s32x_1x1_conv_kernel::maybe_eltwise(int position)
+{
+ using namespace primitive_kind;
+ const auto &p = attr_.post_ops_;
+
+ if (position == 0) {
+ /* eltwise before sum */
+ return p.contain(eltwise, 0);
+ } else if (position == 1) {
+ /* eltwise after sum */
+ return p.contain(sum, 0) && p.contain(eltwise, 1);
+ }
+
+ return false;
+}
+
+void jit_avx512_core_x8s8s32x_1x1_conv_kernel::bcast_loop(int load_loop_blk)
+{
+ mov(aux1_reg_bcast_data, reg_bcast_data);
+ mov(aux_reg_bcast_data, reg_bcast_data);
+
+ mov(aux_reg_output_data, reg_output_data);
+ mov(bcast_loop_iter, EVEX_compress_addr(rsp, bcast_loop_work_off));
+
+ Label bcast_loop;
+ Label bcast_loop_tail;
+
+ cmp(bcast_loop_iter, jcp.ur);
+ jl(bcast_loop_tail, T_NEAR);
+
+ L(bcast_loop); {
+ assert(jcp.bcast_block % jcp.ur == 0);
+ int num_substeps = jcp.bcast_block / jcp.ur;
+ assert(num_substeps > 0 && num_substeps < 10);
+ for (int i = 0; i < num_substeps; i++) {
+ reduce_loop(load_loop_blk, jcp.ur, i, false);
+ if (i < num_substeps - 1) {
+ add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_substep);
+ add(aux_reg_output_data, jcp.bcast_loop_output_substep);
+ }
+ else {
+ add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_step
+ - (num_substeps - 1) * jcp.bcast_loop_bcast_substep);
+ int output_offset = jcp.bcast_loop_output_step
+ - (num_substeps - 1) * jcp.bcast_loop_output_substep;
+
+ add(aux_reg_output_data, output_offset);
+ }
+ }
+ sub(bcast_loop_iter, jcp.bcast_block);
+ cmp(bcast_loop_iter, jcp.bcast_block);
+ jge(bcast_loop, T_NEAR);
+ }
+
+ L(bcast_loop_tail);
+ if (jcp.ur_tail) {
+ Label bcast_loop_tail_out;
+ cmp(bcast_loop_iter, 0);
+ jz(bcast_loop_tail_out, T_NEAR);
+ reduce_loop(load_loop_blk, jcp.ur_tail, 0, true);
+ L(bcast_loop_tail_out);
+ }
+}
+
+void jit_avx512_core_x8s8s32x_1x1_conv_kernel::cvt2ps(data_type_t type_in,
+ zmm_t zmm_in, const Xbyak::Operand &op, bool mask_flag) {
+ zmm_t zmm = mask_flag ? zmm_in | ktail_mask | T_z : zmm_in;
+ switch (type_in) {
+ case data_type::f32:
+ case data_type::s32: vmovups(zmm, op); break;
+ case data_type::s8: vpmovsxbd(zmm, op); break;
+ case data_type::u8: vpmovzxbd(zmm, op); break;
+ default: assert(!"unsupported data type");
+ }
+ if (type_in != data_type::f32)
+ vcvtdq2ps(zmm_in, zmm_in);
+}
+
+void jit_avx512_core_x8s8s32x_1x1_conv_kernel::reduce_loop(int load_loop_blk,
+ int ur, int substep, bool wraparound)
+{
+ auto vreg_load = [=](int i_load) {
+ return Zmm(ur * load_loop_blk + i_load);
+ };
+
+ auto vreg_accum = [=](int i_load, int i_ur) {
+ return Zmm(i_ur * load_loop_blk + i_load);
+ };
+
+ auto zmm_bias_alpha = [=]() {
+ return Zmm(ur * load_loop_blk);
+ };
+
+ auto xmm_bias_alpha = [=]() {
+ return Xmm(ur * load_loop_blk);
+ };
+ auto bias_ptr = [=](int i_load) {
+ return EVEX_compress_addr(reg_bias_data,
+ jcp.typesize_bia * jcp.oc_block * i_load);
+ };
+
+ auto comp_ptr = [=](int i_load) {
+ return EVEX_compress_addr(reg_comp_data,
+ sizeof(int32_t) * jcp.oc_block * i_load);
+ };
+
+ auto scale_ptr = [=](int i_load) {
+ return EVEX_compress_addr(reg_ptr_scales,
+ jcp.is_oc_scale * (sizeof(float) * jcp.oc_block * i_load));
+ };
+
+ auto bcast_ptr = [=](int i_reduce, int i_ur, bool bcast) {
+ assert(i_ur < jcp.ur);
+ assert(i_reduce <= jcp.reduce_loop_unroll);
+ assert(jcp.reduce_loop_unroll == jcp.reduce_block);
+
+ int offt = (jcp.ic_without_padding * i_ur + i_reduce);
+
+ return EVEX_compress_addr(aux_reg_bcast_data, jcp.typesize_in * offt,
+ bcast);
+ };
+
+ auto load_ptr = [=](int i_reduce, int i_load) {
+ int u0 = i_reduce % jcp.reduce_loop_unroll;
+ int u1 = i_reduce / jcp.reduce_loop_unroll;
+
+ int offt = (i_load * jcp.reduce_dim + u0) * jcp.load_block;
+
+ return EVEX_compress_addr(aux_reg_load_data,
+ u1 * jcp.reduce_loop_load_step
+ + jcp.typesize_in * offt);
+ };
+
+ auto output_ptr = [=](int i_load, int i_ur) {
+ return EVEX_compress_addr(aux_reg_output_data,
+ jcp.typesize_out * (jcp.oc_without_padding * i_ur
+ + i_load * jcp.load_block));
+ };
+
+ auto init = [=]() {
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load)
+ for (int i_ur = 0; i_ur < ur; ++i_ur) {
+ auto r = vreg_accum(i_load, i_ur);
+ vpxord(r, r, r);
+ }
+ if (jcp.signed_input) {
+ xor_(reg_scratch, reg_scratch);
+ Reg8 _t8 = reg_scratch.cvt8();
+ mov(_t8, (int8_t)-128);
+ vpbroadcastb(zmm_shift, _t8);
+ }
+ };
+
+ auto store = [=](const bool mask_flag_in) {
+ const auto &p = attr_.post_ops_;
+ const int sum_idx = p.find(primitive_kind::sum);
+ const float *p_sum_scale = (sum_idx != -1)
+ ? &p.entry_[sum_idx].sum.scale
+ : nullptr;
+ mov(EVEX_compress_addr(rsp, reg_bcast_data_off), reg_bcast_data);
+ mov(reg_ptr_scales, EVEX_compress_addr(rsp, reg_ptr_sum_scale_off));
+ if (p_sum_scale && *p_sum_scale != 1.f) {
+ mov(EVEX_compress_addr(rsp, reg_load_data_off), reg_load_data);
+ mov(reg_ptr_sum_scale, (size_t)p_sum_scale);
+ }
+ if (jcp.signed_input && jcp.ver != ver_vnni) {
+ mov(reg_scratch, float2int(jcp.wei_adj_scale));
+ vmovq(xmm_bias_alpha(), reg_scratch);
+ vbroadcastss(zmm_bias_alpha(), xmm_bias_alpha());
+ }
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load) {
+ const bool mask_flag = mask_flag_in && i_load == load_loop_blk - 1;
+ auto zmm_bias = zmm_tmp;
+ auto zmm_comp = zmm_bcast;
+ if (jcp.with_bias) {
+ if (jcp.signed_input)
+ mov(reg_bias_data,
+ EVEX_compress_addr(rsp,reg_bias_data_off));
+ cvt2ps(jcp.bia_dt, zmm_bias, bias_ptr(i_load), mask_flag);
+ if (jcp.signed_input && jcp.ver != ver_vnni)
+ vmulps(zmm_bias, zmm_bias, zmm_bias_alpha());
+ }
+ if (jcp.signed_input) {
+ mov(reg_comp_data, EVEX_compress_addr(rsp, reg_comp_data_off));
+ cvt2ps(data_type::s32, zmm_comp, comp_ptr(i_load), mask_flag);
+ }
+
+ for (int i_ur = 0; i_ur < ur; ++i_ur) {
+ auto r = vreg_accum(i_load, i_ur);
+ vcvtdq2ps(r, r);
+ if (jcp.signed_input)
+ vaddps(r, r, zmm_comp);
+ if (jcp.with_bias)
+ vaddps(r, r, zmm_bias);
+
+ zmm_t mask_zmm = mask_flag ? r | ktail_mask | T_z : r;
+ vmulps(mask_zmm, r, scale_ptr(i_load));
+ }
+ }
+
+ if (maybe_eltwise(0))
+ eltwise_injector_->compute_vector_range(0, ur * load_loop_blk);
+
+ if (p_sum_scale) { // post_op: sum
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load) {
+ const bool mask_flag = mask_flag_in &&
+ i_load == load_loop_blk - 1;
+ for (int i_ur = 0; i_ur < ur; ++i_ur) {
+ vpxord(zmm_zero, zmm_zero, zmm_zero);
+ auto zmm_prev_dst = zmm_zero;
+
+ auto r = vreg_accum(i_load, i_ur);
+ cvt2ps(jcp.dst_dt, zmm_prev_dst, output_ptr(i_load, i_ur),
+ mask_flag);
+
+ if (*p_sum_scale == 1.f)
+ vaddps(r, zmm_prev_dst);
+ else
+ vfmadd231ps(r, zmm_prev_dst, zword_b[reg_ptr_sum_scale]);
+ }
+ }
+ }
+
+ if (maybe_eltwise(1))
+ eltwise_injector_->compute_vector_range(0, ur * load_loop_blk);
+
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load) {
+ const bool mask_flag = mask_flag_in &&
+ i_load == load_loop_blk - 1;
+ for (int i_ur = 0; i_ur < ur; ++i_ur) {
+ auto r = vreg_accum(i_load, i_ur);
+ if (jcp.dst_dt == data_type::u8) {
+ vpxord(zmm_zero, zmm_zero, zmm_zero);
+ vmaxps(r, zmm_zero, r);
+ }
+ if (jcp.dst_dt != data_type::f32)
+ vcvtps2dq(r, r);
+ }
+ for (int i_ur = 0; i_ur < ur; ++i_ur) {
+ auto r = vreg_accum(i_load, i_ur);
+ zmm_t r_zmm = mask_flag ? r | ktail_mask : r;
+
+ switch (jcp.dst_dt) {
+ case data_type::f32:
+ case data_type::s32:
+ vmovups(output_ptr(i_load, i_ur), r_zmm); break;
+ case data_type::s8:
+ vpmovsdb(output_ptr(i_load, i_ur), r_zmm); break;
+ case data_type::u8:
+ vpmovusdb(output_ptr(i_load, i_ur), r_zmm); break;
+ default: assert(!"unknown dst_dt");
+ }
+ }
+ }
+ mov(reg_bcast_data, EVEX_compress_addr(rsp, reg_bcast_data_off));
+ if (p_sum_scale && *p_sum_scale != 1.f)
+ mov(reg_load_data, EVEX_compress_addr(rsp, reg_load_data_off));
+ };
+
+ auto compute = [=](Zmm vreg_acc, Zmm vreg_wei, Zmm vreg_src) {
+ if (jcp.ver == ver_vnni) {
+ vpdpbusd(vreg_acc, vreg_src, vreg_wei);
+ } else {
+ vpmaddubsw(zmm_tmp, vreg_src, vreg_wei);
+ vpmaddwd(zmm_tmp, zmm_tmp, zmm_one);
+ vpaddd(vreg_acc, vreg_acc, zmm_tmp);
+ }
+ };
+
+ auto fma_block = [=](bool last_block) {
+ int reduce_step = 4;
+ int tail_size = jcp.ic_without_padding % reduce_step;
+ int loop_unroll = last_block && jcp.ic != jcp.ic_without_padding
+ ? rnd_up(jcp.ic_without_padding % jcp.ic_block, reduce_step)
+ : jcp.reduce_loop_unroll;
+ for (int i_reduce = 0; i_reduce < loop_unroll;
+ i_reduce += reduce_step) {
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load)
+ vmovups(vreg_load(i_load), load_ptr(i_reduce, i_load));
+ for (int i_ur = 0; i_ur < ur; ++i_ur) {
+ if (last_block && tail_size != 0
+ && i_reduce == loop_unroll - reduce_step) {
+ Xmm xmm_bcast = Xmm(zmm_bcast.getIdx());
+ for (int r = 0; r < tail_size; ++r)
+ vpinsrb(xmm_bcast, xmm_bcast, ptr[aux_reg_bcast_data
+ + jcp.ic_without_padding * i_ur + i_reduce + r], r);
+ vpbroadcastd(zmm_bcast, xmm_bcast);
+ } else {
+ vpbroadcastd(zmm_bcast, bcast_ptr(i_reduce, i_ur, false));
+ }
+ if (jcp.signed_input)
+ vpsubb(zmm_bcast, zmm_bcast, zmm_shift);
+ for (int i_load = 0; i_load < load_loop_blk; ++i_load) {
+ compute(vreg_accum(i_load, i_ur),
+ vreg_load(i_load), zmm_bcast);
+ }
+ }
+ }
+ };
+
+ Label reduce_loop;
+ Label reduce_loop_tail;
+
+ mov(aux_reg_load_data, reg_load_data);
+
+ mov(aux_reg_bcast_data, aux1_reg_bcast_data);
+ init();
+
+ mov(reduce_loop_iter, reg_reduce_loop_work);
+ sub(reduce_loop_iter, jcp.reduce_loop_unroll);
+ jle(reduce_loop_tail, T_NEAR);
+
+ L(reduce_loop); {
+ fma_block(false);
+ add(aux_reg_bcast_data, jcp.reduce_loop_bcast_step);
+ add(aux_reg_load_data, jcp.reduce_loop_load_step);
+ sub(reduce_loop_iter, jcp.reduce_loop_unroll);
+ jg(reduce_loop, T_NEAR);
+ }
+
+ L(reduce_loop_tail);
+ if (jcp.ic != jcp.ic_without_padding) {
+ fma_block(true);
+ } else {
+ fma_block(false);
+ }
+
+ if (jcp.oc_without_padding != jcp.oc) {
+ Label end_store, common_store;
+ mov(EVEX_compress_addr(rsp, reg_bcast_data_off), reg_bcast_data);
+
+ /*Check if it is the last load_loop_blk*/
+ sub(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step);
+ cmp(reg_load_loop_work, 0);
+ jg(common_store, T_NEAR);
+
+ /*Check if it is the last ocb*/
+ test(reg_reduce_pos_flag, FLAG_OC_LAST);
+ jz(common_store, T_NEAR);
+
+ store(true);
+ jmp(end_store, T_NEAR);
+
+ L(common_store);
+ store(false);
+
+ L(end_store);
+
+ add(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step);
+ } else {
+ store(false);
+ }
+}
+
+void jit_avx512_core_x8s8s32x_1x1_conv_kernel::generate()
+{
+ preamble();
+
+ xor_(reg_scratch, reg_scratch);
+ Reg16 _t = reg_scratch.cvt16();
+ mov(_t, 0x1);
+ vpbroadcastw(zmm_one, _t);
+
+ sub(rsp, stack_space_needed);
+
+ if (jcp.oc_without_padding != jcp.oc) {
+ int tail_size = jcp.oc_without_padding % jcp.oc_block;
+ int mask = (1 << tail_size) - 1;
+ Reg32 regw_tmp = reg_last_load.cvt32();
+ mov(regw_tmp, mask);
+ kmovw(ktail_mask, regw_tmp);
+ }
+
+ if (jcp.with_bias)
+ mov(reg_bias_data, ptr[param1 + GET_OFF(bias_data)]);
+ if (jcp.signed_input) {
+ mov(EVEX_compress_addr(rsp, reg_bias_data_off), reg_bias_data);
+ mov(reg_comp_data, ptr[param1 + GET_OFF(compensation)]);
+ mov(EVEX_compress_addr(rsp, reg_comp_data_off), reg_comp_data);
+ }
+ mov(reg_ptr_scales, ptr[param1 + GET_OFF(scales)]);
+ mov(EVEX_compress_addr(rsp, reg_ptr_sum_scale_off), reg_ptr_scales);
+ mov(reg_bcast_data, ptr[param1 + GET_OFF(bcast_data)]);
+ mov(reg_load_data, ptr[param1 + GET_OFF(load_data)]);
+ mov(reg_output_data, ptr[param1 + GET_OFF(output_data)]);
+
+ mov(reg_load_loop_work, ptr[param1 + GET_OFF(load_dim)]);
+ mov(reg_bcast_loop_work, ptr[param1 + GET_OFF(bcast_dim)]);
+ mov(EVEX_compress_addr(rsp, bcast_loop_work_off), reg_bcast_loop_work);
+ mov(reg_reduce_loop_work, ptr[param1 + GET_OFF(reduce_dim)]);
+ mov(reg_reduce_pos_flag, ptr[param1 + GET_OFF(first_last_flag)]);
+
+
+ auto load_loop_body = [=](int load_loop_blk) {
+ bcast_loop(load_loop_blk);
+ add(reg_load_data, load_loop_blk * jcp.load_loop_load_step);
+ if (jcp.with_bias) {
+ if (jcp.signed_input)
+ mov(reg_bias_data, EVEX_compress_addr(rsp, reg_bias_data_off));
+ add(reg_bias_data,
+ load_loop_blk * jcp.load_block * jcp.typesize_bia);
+ if (jcp.signed_input)
+ mov(EVEX_compress_addr(rsp, reg_bias_data_off), reg_bias_data);
+ }
+ if (jcp.signed_input) {
+ mov(reg_comp_data, EVEX_compress_addr(rsp, reg_comp_data_off));
+ add(reg_comp_data,
+ load_loop_blk * jcp.load_block * sizeof(int32_t));
+ mov(EVEX_compress_addr(rsp, reg_comp_data_off), reg_comp_data);
+ }
+ mov(EVEX_compress_addr(rsp, reg_bcast_data_off), reg_bcast_data);
+ mov(reg_ptr_scales, EVEX_compress_addr(rsp, reg_ptr_sum_scale_off));
+ add(reg_ptr_scales,
+ jcp.is_oc_scale * load_loop_blk * jcp.load_block * sizeof(float));
+ mov(EVEX_compress_addr(rsp, reg_ptr_sum_scale_off), reg_ptr_scales);
+ mov(reg_bcast_data, EVEX_compress_addr(rsp, reg_bcast_data_off));
+ add(reg_output_data,
+ load_loop_blk * jcp.load_block * jcp.typesize_out);
+ sub(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step);
+ };
+
+ const int simd_w = 16;
+
+ Label load_loop_blk[7];
+
+ static const int ur_cases_fma_expl_bcast[] = { 2, 5, 6, 9, 14, 32 };
+ const int size_ur_cases_fma = sizeof(ur_cases_fma_expl_bcast);
+ const int *ur_cases_fma = ur_cases_fma_expl_bcast;
+ const int *ur_cases = ur_cases_fma;
+ const int num_ur_cases = (size_ur_cases_fma) / sizeof(*ur_cases);
+
+ for (int ur_idx = num_ur_cases - 1; ur_idx > 0; ur_idx--) {
+ int label_idx = num_ur_cases - ur_idx - 1;
+ if (jcp.ur <= ur_cases[ur_idx]) {
+ cmp(reg_load_loop_work, simd_w * (label_idx + 1));
+ jle(load_loop_blk[label_idx], T_NEAR);
+ }
+ }
+
+ for (int ur_idx = 0; ur_idx < num_ur_cases; ur_idx++) {
+ if (jcp.ur <= ur_cases[ur_idx]) {
+ int label_idx = num_ur_cases - ur_idx - 1;
+ L(load_loop_blk[label_idx]);
+ {
+ if (label_idx == 0) {
+ cmp(reg_load_loop_work, 0);
+ je(load_loop_blk[num_ur_cases], T_NEAR);
+ }
+
+ for (int _i = 1; _i <= label_idx + 1; _i++) {
+ prefetcht0(ptr [ reg_load_data + _i * jcp.ic * jcp.oc_block ]);
+ prefetcht1(ptr [ reg_output_data + _i * jcp.oc_block ]);
+ }
+
+ load_loop_body(label_idx + 1);
+ if (label_idx - 1 > 0) {
+ cmp(reg_load_loop_work, 2 * label_idx * simd_w);
+ je(load_loop_blk[label_idx - 1], T_NEAR);
+ }
+ cmp(reg_load_loop_work, (label_idx + 1) * simd_w);
+ jge(load_loop_blk[label_idx]);
+ }
+ for (int idx = label_idx - 1; idx > 0; --idx) {
+ cmp(reg_load_loop_work, simd_w * (idx + 1));
+ je(load_loop_blk[idx], T_NEAR);
+ }
+ if (ur_idx < num_ur_cases - 2) {
+ cmp(reg_load_loop_work, simd_w);
+ jle(load_loop_blk[0], T_NEAR);
+ }
+ }
+ }
+ L(load_loop_blk[num_ur_cases]);
+
+ add(rsp, stack_space_needed);
+
+ postamble();
+
+ if (jcp.with_eltwise)
+ eltwise_injector_->prepare_table();
+}
+
+bool jit_avx512_core_x8s8s32x_1x1_conv_kernel::post_ops_ok(
+ jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ using namespace primitive_kind;
+ const auto &p = attr.post_ops_;
+
+ auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); };
+
+ switch (p.len_) {
+ case 0: return true;
+ case 1: return is_eltwise(0) || p.contain(sum, 0);
+ case 2: return (p.contain(sum, 0) && is_eltwise(1))
+ || (p.contain(sum, 1) && is_eltwise(0));
+ default: return false;
+ }
+
+ return false;
+}
+
+status_t jit_avx512_core_x8s8s32x_1x1_conv_kernel::init_conf(
+ jit_1x1_conv_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d, const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d, const memory_desc_wrapper &bias_d,
+ const primitive_attr_t &attr, int nthreads, bool reduce_src) {
+ if (!mayiuse(avx512_core)) return status::unimplemented;
+
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ if (!one_of(src_d.data_type(), data_type::u8, data_type::s8)
+ || weights_d.data_type() != data_type::s8
+ || !one_of(dst_d.data_type(),
+ data_type::f32, data_type::s32, data_type::s8, data_type::u8))
+ return status::unimplemented;
+ jcp.ver = ver_avx512_core;
+ if (mayiuse(avx512_core_vnni))
+ jcp.ver = ver_vnni;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.ic_without_padding = jcp.ic;
+ jcp.ih = src_d.dims()[2];
+ jcp.iw = src_d.dims()[3];
+ jcp.oh = dst_d.dims()[2];
+ jcp.ow = dst_d.dims()[3];
+ jcp.kh = weights_d.dims()[with_groups + 2];
+ jcp.kw = weights_d.dims()[with_groups + 3];
+ jcp.t_pad = cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][1];
+ jcp.stride_h = cd.strides[0];
+ jcp.stride_w = cd.strides[1];
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ jcp.signed_input = (src_d.data_type() == data_type::s8) ? true : false;
+
+ jcp.os = jcp.oh * jcp.ow;
+ jcp.is = jcp.ih * jcp.iw;
+ jcp.tr_is = rnd_up(jcp.is, 4);
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ const int eltwise_ind = p.find(primitive_kind::eltwise);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise)
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+
+ format_tag_t dat_tag = format_tag::nhwc;
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag);
+
+ bool args_ok = true
+ && jcp.ngroups == 1
+ && jcp.src_tag == dat_tag
+ && jcp.dst_tag == dat_tag;
+ if (!args_ok) return status::unimplemented;
+
+ const int simd_w = 16;
+
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ jcp.ic = rnd_up(jcp.ic, simd_w);
+
+ args_ok = true
+ && jcp.oc % simd_w == 0 && jcp.ic % simd_w == 0
+ && jcp.t_pad == 0 && jcp.l_pad == 0
+ && jcp.stride_w == 1 && jcp.stride_h == 1 // TODO: support some strides
+ && jcp.kh == 1 && jcp.kw == 1;
+ if (!args_ok) return status::unimplemented;
+
+ jcp.bia_dt = jcp.with_bias ? cd.bias_desc.data_type : data_type::undef;
+ jcp.dst_dt = cd.dst_desc.data_type;
+
+ jcp.ic_block = jcp.oc_block = simd_w;
+
+ jcp.typesize_in = types::data_type_size(src_d.data_type());
+ jcp.typesize_out = types::data_type_size(dst_d.data_type());
+ jcp.typesize_bia = jcp.with_bias
+ ? types::data_type_size(bias_d.data_type())
+ : 0;
+
+ const int SMALL_SPATIAL = 7 * 7;
+ const int BIG_REDUCE_DIM = 1024;
+
+ int load_blocking = 0;
+ int load_blocking_max = 0;
+ int bcast_blocking = 0;
+ int bcast_blocking_max = 0;
+ int reduce_blocking = 0;
+ int reduce_blocking_max = 0;
+ jcp.load_grp_count = 1;
+ jcp.use_vmovntps = false;
+
+ const int L2_size = get_cache_size(2, true) / sizeof(jcp.typesize_in);
+ const int L2_capacity = (L2_size * 3) / 4;
+
+ int size_treshold = 28;
+ int max_regs = 0;
+ int min_regs = 6;
+ if (jcp.ver == ver_vnni)
+ max_regs = ((jcp.oh > size_treshold && jcp.ow > size_treshold)
+ && (jcp.oc < 128 || jcp.ic < 128)) ? min_regs : 9;
+ else
+ max_regs = 8;
+ jcp.expl_bcast = true;
+
+ if (jcp.mb == 1 && jcp.ic > 128
+ && (jcp.oh <= size_treshold && jcp.ow <= size_treshold)) {
+ if (jcp.os <= SMALL_SPATIAL && jcp.oc * jcp.ic < L2_size)
+ max_regs = min_regs; // mobilenet_v2 performance improvement
+ jcp.ur = nstl::min(max_regs, jcp.os);
+ } else {
+ const int spatial = jcp.oh;
+ jcp.ur = 1;
+ for (int ur_w = max_regs; ur_w >= min_regs; ur_w--) {
+ if ((spatial >= size_treshold && spatial % ur_w == 0)
+ || (spatial < size_treshold && jcp.os % ur_w == 0)) {
+ jcp.ur = ur_w;
+ break;
+ }
+ }
+ if (jcp.ur == 1) {
+ jcp.ur = nstl::min(max_regs, jcp.os);
+ int os_tail = jcp.os % max_regs;
+ for (int i = max_regs; i >= min_regs; i--) {
+ int i_tail = jcp.os % i;
+ if (i_tail > os_tail || i_tail == 0) {
+ jcp.ur = i;
+ os_tail = i_tail;
+ if (i_tail == 0)
+ break;
+ }
+ }
+ }
+ }
+
+ jcp.reduce_dim = jcp.ic;
+ jcp.reduce_block = jcp.ic_block;
+
+ jcp.load_dim = jcp.oc;
+ jcp.load_block = jcp.oc_block;
+
+ jcp.bcast_dim = jcp.is;
+
+ jcp.bcast_block = jcp.ur;
+
+ jcp.reduce_loop_unroll = jcp.reduce_block;
+ jcp.reduce_loop_bcast_step
+ = jcp.reduce_loop_unroll * jcp.typesize_in;
+
+ jcp.reduce_loop_load_step
+ = jcp.reduce_loop_unroll * jcp.load_block * jcp.typesize_in;
+
+ jcp.bcast_loop_output_step = jcp.ur * jcp.oc_without_padding * jcp.typesize_out;
+ jcp.bcast_loop_output_substep = -1; // unused
+ jcp.bcast_loop_bcast_step = jcp.ur * jcp.ic_without_padding * jcp.typesize_in;
+ jcp.bcast_loop_bcast_substep = -1; // unused
+
+ jcp.load_loop_load_step
+ = jcp.reduce_dim * jcp.load_block * jcp.typesize_in;
+
+ jcp.load_loop_iter_step = jcp.load_block;
+
+ jcp.loop_order = reduce_src ? loop_blr : loop_lbr;
+
+ int nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block);
+ int nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block);
+
+ reduce_blocking = nb_reduce;
+ if (jcp.bcast_dim <= SMALL_SPATIAL && jcp.reduce_dim >= BIG_REDUCE_DIM)
+ reduce_blocking = 64;
+ else if (jcp.bcast_dim > SMALL_SPATIAL && jcp.reduce_dim >= BIG_REDUCE_DIM)
+ reduce_blocking = 16;
+ reduce_blocking = best_divider(nb_reduce, 1, reduce_blocking, true);
+ reduce_blocking *= jcp.reduce_block;
+
+ bool cmp_reduce = reduce_blocking <= jcp.reduce_dim;
+ if (cmp_reduce)
+ jcp.loop_order = reduce_src ? loop_rbl : loop_rlb;
+ load_blocking = jcp.load_dim;
+
+ jcp.load_grp_count = div_up(nthreads, jcp.mb * jcp.ngroups * nb_bcast);
+ jcp.load_grp_count = best_divider(
+ nthreads, jcp.load_grp_count, 2 * jcp.load_grp_count, false);
+
+ if (jcp.bcast_dim <= SMALL_SPATIAL && jcp.load_dim * jcp.reduce_dim >= L2_size) {
+ jcp.load_grp_count = nstl::max(jcp.load_grp_count, 4);
+ } else if (jcp.bcast_dim <= SMALL_SPATIAL && jcp.mb <= nthreads
+ && jcp.load_dim > 512 && jcp.load_dim / jcp.reduce_dim >= 4) {
+ jcp.load_grp_count = nstl::max(jcp.load_grp_count, 2); //
+ load_blocking = jcp.load_block;
+ }
+
+ bcast_blocking = div_up(jcp.mb * jcp.ngroups * nb_bcast,
+ div_up(nthreads, jcp.load_grp_count)) * jcp.bcast_block;
+ bcast_blocking = nstl::min(jcp.bcast_dim, bcast_blocking);
+ bcast_blocking = rnd_up(bcast_blocking, jcp.bcast_block);
+
+ int space_for_bcast
+ = (L2_capacity - /* kernel_size - */
+ 2 * jcp.load_block * reduce_blocking
+ - jcp.ur * reduce_blocking - 3 * 1024);
+ if (jcp.reduce_dim * jcp.bcast_dim > L2_capacity)
+ space_for_bcast /= 2;
+
+ int bcast_in_cache
+ = nstl::max(jcp.bcast_block, space_for_bcast / reduce_blocking);
+ bcast_blocking = nstl::min(
+ bcast_blocking, rnd_dn(bcast_in_cache, jcp.bcast_block));
+
+ load_blocking_max = load_blocking;
+ bcast_blocking_max = bcast_blocking * 3 / 2;
+ reduce_blocking_max = reduce_blocking;
+
+ assert(load_blocking);
+ assert(load_blocking_max);
+ assert(bcast_blocking);
+ assert(bcast_blocking_max);
+ assert(reduce_blocking);
+ assert(reduce_blocking_max);
+ assert(load_blocking % jcp.load_block == 0);
+ assert(reduce_blocking % jcp.reduce_block == 0);
+ assert(load_blocking_max % jcp.load_block == 0);
+ assert(reduce_blocking_max % jcp.reduce_block == 0);
+
+ assert(jcp.reduce_loop_unroll % 4 == 0);
+ assert(jcp.reduce_dim % jcp.reduce_loop_unroll == 0);
+
+ assert(jcp.bcast_block % jcp.ur == 0);
+ assert(jcp.reduce_dim % jcp.reduce_block == 0);
+
+ jcp.ur_tail = jcp.bcast_dim % jcp.ur;
+
+ jcp.nb_bcast_blocking = bcast_blocking / jcp.bcast_block;
+ jcp.nb_bcast_blocking_max = bcast_blocking_max / jcp.bcast_block;
+ jcp.nb_load_blocking = load_blocking / jcp.load_block;
+ jcp.nb_load_blocking_max = load_blocking_max / jcp.load_block;
+ jcp.nb_reduce_blocking = reduce_blocking / jcp.reduce_block;
+ jcp.nb_reduce_blocking_max = reduce_blocking_max / jcp.reduce_block;
+
+ jcp.nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block);
+ jcp.nb_load = div_up(jcp.load_dim, jcp.load_block);
+ jcp.nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block);
+
+ // miniumum size of load dim chunk for work distribution within threads
+ jcp.nb_load_chunk = 1;
+ // peformance improvements for googlenet_v3, mb=1;
+ // TODO: generalize this condition and rewrite it in appropriate manner
+ if (jcp.mb == 1 && jcp.nb_load % 4 == 0 && jcp.ic / jcp.oc >= 4
+ && jcp.ic * jcp.oc <= L2_size) {
+ jcp.nb_load_chunk = 4;
+ jcp.load_grp_count = nstl::max(jcp.nb_load / 4, jcp.load_grp_count);
+ }
+
+ const auto &oscales = attr.output_scales_;
+ jcp.is_oc_scale = oscales.mask_ == 1 << 1;
+ assert(IMPLICATION(!jcp.is_oc_scale, oscales.mask_ == 0));
+
+ jcp.wei_adj_scale =
+ (weights_d.extra().flags | memory_extra_flags::scale_adjust)
+ ? weights_d.extra().scale_adjust : 1.f;
+
+ return status::success;
+}
+
+void jit_avx512_core_x8s8s32x_1x1_conv_kernel::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad,
+ const jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ using namespace mkldnn::impl::memory_tracking::names;
+
+ if (jcp.signed_input && jcp.ver != ver_vnni) {
+ dim_t count = nstl::max<dim_t>(attr.output_scales_.count_, 16);
+ scratchpad.book(key_conv_adjusted_scales, sizeof(float) * count);
+ }
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp
new file mode 100644
index 0000000000..22e9732a1f
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp
@@ -0,0 +1,131 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_AVX512_CORE_X8S8S32X_1X1_CONV_KERNEL_HPP
+#define JIT_AVX512_CORE_X8S8S32X_1X1_CONV_KERNEL_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+#include "jit_uni_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_avx512_core_x8s8s32x_1x1_conv_kernel: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_x8s8s32x_1x1_conv_fwd_ker_t)
+ jit_avx512_core_x8s8s32x_1x1_conv_kernel(jit_1x1_conv_conf_t ajcp,
+ const primitive_attr_t &attr) : jcp(ajcp), attr_(attr),
+ eltwise_injector_(nullptr)
+ {
+ if (jcp.with_eltwise)
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<avx512_common>(
+ this, jcp.eltwise);
+
+ this->generate();
+ jit_ker = (void (*)(jit_1x1_conv_call_s *)) this->getCode();
+ }
+
+ ~jit_avx512_core_x8s8s32x_1x1_conv_kernel() {
+ delete eltwise_injector_;
+ }
+
+ static bool post_ops_ok(jit_1x1_conv_conf_t &jcp,
+ const primitive_attr_t &attr);
+
+ static status_t init_conf(jit_1x1_conv_conf_t &jcp,
+ const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d,
+ const memory_desc_wrapper &bias_d,
+ const primitive_attr_t &attr,
+ int nthreads, bool reduce_src);
+
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr);
+
+ bool maybe_eltwise(int position);
+
+ jit_1x1_conv_conf_t jcp;
+ const primitive_attr_t &attr_;
+ void (*jit_ker)(jit_1x1_conv_call_s *);
+
+ private:
+ jit_uni_eltwise_injector_f32<avx512_common> *eltwise_injector_;
+
+ using reg64_t = const Xbyak::Reg64;
+ using zmm_t = const Xbyak::Zmm;
+ using mask_t = const Xbyak::Opmask;
+
+ reg64_t reg_bcast_data = r8;
+ reg64_t reg_ptr_scales = r8;
+ reg64_t reg_output_data = r9;
+ reg64_t reg_load_data = r10;
+ reg64_t reg_ptr_sum_scale = r10;
+ reg64_t reg_reduce_loop_work = r11;
+ reg64_t reg_bias_data = r12;
+ reg64_t reg_comp_data = r12;
+ reg64_t reg_scratch = r13;
+ reg64_t aux_reg_bcast_data = r14;
+ reg64_t aux_reg_load_data = r15;
+ reg64_t imm_addr64 = r15;
+ reg64_t reg_reduce_pos_flag = rax;
+ reg64_t aux1_reg_bcast_data = rbx;
+ reg64_t reg_bcast_loop_work = rbx;
+ reg64_t bcast_loop_iter = rdx; // Note: Fix me
+ reg64_t reg_load_loop_work = rsi;
+ reg64_t aux_reg_output_data = abi_not_param1;
+ reg64_t reduce_loop_iter = abi_param1;
+
+ reg64_t reg_last_load = r8;
+ mask_t ktail_mask = k6;
+
+ mask_t vmask = k7;
+
+ Xbyak::Zmm zmm_tmp = Xbyak::Zmm(28);
+ Xbyak::Zmm zmm_one = Xbyak::Zmm(29);
+ Xbyak::Zmm zmm_zero = Xbyak::Zmm(30);
+ Xbyak::Zmm zmm_bcast = Xbyak::Zmm(31);
+ Xbyak::Zmm zmm_shift = Xbyak::Zmm(30);
+
+ Xbyak::Zmm zmm_bias_alpha = Xbyak::Zmm(31);
+ Xbyak::Xmm xmm_bias_alpha = Xbyak::Xmm(31);
+
+ int bcast_loop_work_off = 0;
+ int reg_bias_data_off = 8;
+ int reg_bcast_data_off = 16;
+ int reg_load_data_off = 24;
+ int reg_ptr_sum_scale_off = 32;
+ int reg_comp_data_off = 40;
+ int stack_space_needed = 48;
+
+ void bcast_loop(int load_loop_blk);
+ void reduce_loop(int load_loop_blk, int ur, int substep, bool wraparound);
+
+ void generate();
+ void cvt2ps(data_type_t type_in, zmm_t zmm_in, const Xbyak::Operand &op,
+ bool mask_flag);
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.cpp
new file mode 100644
index 0000000000..0bf09fc677
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.cpp
@@ -0,0 +1,292 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_generator.hpp"
+
+#include "jit_avx512_core_x8s8s32x_1x1_convolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+namespace {
+template <typename T, typename U>
+void balance2D(U nthr, U ithr, T ny, T &ny_start, T &ny_end,
+ T nx, T &nx_start, T &nx_end, T nx_divider)
+{
+ const T grp_size = utils::div_up(nthr, nx_divider);
+ const T grp_count = utils::div_up(nthr, grp_size);
+
+ T grp = ithr / grp_size;
+ T grp_ithr = ithr % grp_size;
+ T grp_nthr = grp_size;
+ T first_grps = nthr % grp_count;
+ if (first_grps > 0 && grp >= first_grps) {
+ ithr -= first_grps * grp_size;
+ grp_nthr--;
+ grp = ithr / grp_nthr + first_grps;
+ grp_ithr = ithr % grp_nthr;
+ }
+ balance211(nx, grp_count, grp, nx_start, nx_end);
+ balance211(ny, grp_nthr, grp_ithr, ny_start, ny_end);
+}
+}
+
+/* convolution forward */
+template <data_type_t src_type, data_type_t dst_type>
+void jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<src_type, dst_type>::
+execute_forward(const exec_ctx_t &ctx) const
+{
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ if (pd()->jcp_.signed_input && pd()->jcp_.ver != ver_vnni) {
+ auto local_scales = scratchpad.template get<float>(
+ key_conv_adjusted_scales);
+ auto scales = pd()->attr()->output_scales_.scales_;
+ size_t count = pd()->attr()->output_scales_.count_;
+ float factor = 1.f / pd()->jcp_.wei_adj_scale;
+ if (count == 1) {
+ utils::array_set(local_scales, scales[0] * factor, 16);
+ } else {
+ for (size_t c = 0; c < count; c++)
+ local_scales[c] = scales[c] * factor;
+ }
+ }
+
+ parallel(kernel_->jcp.nthr, [&](const int ithr, const int nthr) {
+ execute_forward_thr(ithr, nthr, src, weights, bias, dst, scratchpad);
+ });
+}
+
+template <data_type_t src_type, data_type_t dst_type>
+void jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<src_type, dst_type>
+::execute_forward_thr(const int ithr, const int nthr, const src_data_t *src,
+ const wei_data_t *weights, const char *bias, dst_data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const {
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const size_t bia_dt_size = pd()->with_bias()
+ ? types::data_type_size(pd()->desc()->bias_desc.data_type) : 0;
+
+ const auto &jcp = kernel_->jcp;
+ auto rtus_space = scratchpad.get<src_data_t>(key_conv_rtus_space);
+ auto local_scales = scratchpad.get<float>(key_conv_adjusted_scales);
+
+ const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast;
+
+ const int stride_h = pd()->desc()->strides[0];
+ const int stride_w = pd()->desc()->strides[1];
+ const int pad_t = pd()->desc()->padding[0][0];
+ const int pad_l = pd()->desc()->padding[0][1];
+
+ const auto &oscales = pd()->attr()->output_scales_;
+
+ int offset = jcp.ngroups * (jcp.oc / jcp.oc_block) * (jcp.ic / jcp.ic_block)
+ * jcp.oc_block * jcp.ic_block;
+ wei_data_t *w = const_cast<wei_data_t *>(weights);
+ int32_t* compensation = (jcp.signed_input)
+ ? reinterpret_cast<int32_t *>(w + offset) : 0;
+
+ auto step = [](int default_step, int remaining, int tail_step) {
+ assert(default_step <= tail_step);
+ return remaining < tail_step ? remaining : default_step;
+ };
+
+ auto p = jit_1x1_conv_call_s();
+
+ auto rp = rtus_driver_t<avx512_common>::call_params_t();
+ const int nb_oc = jcp.nb_load;
+ const int os_block = jcp.bcast_block;
+
+ int bcast_start{0}, bcast_end{0}, ocb_start{0}, ocb_end{0};
+ balance2D(nthr, ithr, work_amount, bcast_start, bcast_end,
+ jcp.nb_load / jcp.nb_load_chunk, ocb_start, ocb_end,
+ jcp.load_grp_count);
+ if (jcp.nb_load_chunk > 1) {
+ ocb_start *= jcp.nb_load_chunk;
+ ocb_end *= jcp.nb_load_chunk;
+ }
+
+ auto init_bcast = [&](int iwork, int &n, int &g, int &bcast_step,
+ int &oh, int &ow, int &ih, int &iw)
+ {
+ int osb{0};
+ nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb,
+ jcp.nb_bcast);
+ bcast_step = step(jcp.nb_bcast_blocking, jcp.nb_bcast - osb,
+ jcp.nb_bcast_blocking_max);
+ bcast_step = nstl::min(bcast_step, bcast_end - iwork);
+
+ const int os = osb * os_block;
+ oh = os / jcp.ow;
+ ow = os % jcp.ow;
+
+ ih = nstl::max(oh * stride_h - pad_t, 0);
+ iw = nstl::max(ow * stride_w - pad_l, 0);
+ rp.iw_start = iw;
+
+ p.bcast_dim = this_block_size(os, jcp.os,
+ bcast_step * os_block);
+ rp.os = p.bcast_dim;
+ };
+
+ auto init_load = [&](int ocb, int &load_step)
+ {
+ load_step = step(jcp.nb_load_blocking, ocb_end - ocb,
+ jcp.nb_load_blocking_max);
+ p.load_dim = this_block_size(ocb * jcp.oc_block,
+ ocb_end * jcp.oc_block, load_step * jcp.oc_block);
+
+ if (ocb + load_step >= nb_oc)
+ p.first_last_flag |= FLAG_OC_LAST;
+ else
+ p.first_last_flag &= ~FLAG_OC_LAST;
+
+ };
+
+ auto init_reduce = [&]()
+ {
+ p.reduce_dim = this_block_size(0, jcp.ic, jcp.ic);
+ rp.icb = p.reduce_dim / jcp.reduce_block;
+ };
+
+ auto inner_ker = [&](int ocb, int n, int g, int oh, int ow,
+ int ih, int iw)
+ {
+ const int icb = 0; // Start from the first IC block
+ const int _ocb = g * nb_oc + ocb;
+ const int _icb = g;
+
+ const size_t dst_off = dst_d.blk_off(n, _ocb * jcp.oc_block, oh, ow);
+
+ p.output_data = &dst[dst_off];
+ p.load_data = &weights[pd()->with_groups()
+ ? weights_d.blk_off(g, ocb, icb)
+ : weights_d.blk_off(ocb, icb)];
+ p.bias_data = &bias[_ocb * jcp.oc_block * bia_dt_size];
+ p.compensation = (jcp.signed_input)
+ ? &compensation[_ocb * jcp.oc_block] : 0;
+ p.scales = (jcp.signed_input && jcp.ver != ver_vnni)
+ ? &local_scales[jcp.is_oc_scale * _ocb * jcp.oc_block]
+ : &oscales.scales_[jcp.is_oc_scale * _ocb * jcp.oc_block];
+ if (pd()->rtus_.reduce_src_) {
+ rp.ws = rtus_space + ithr * pd()->rtus_.space_per_thread_
+ + _icb * jcp.is * jcp.ic_block;
+ if (ocb == ocb_start) {
+ rp.src = src + src_d.blk_off(n, _icb * jcp.ic_block, ih, iw);
+ rtus_driver_->ker_(&rp);
+ }
+ p.bcast_data = rp.ws;
+ } else
+ p.bcast_data = src + src_d.blk_off(n, _icb * jcp.ic_block, ih, iw);
+
+ kernel_->jit_ker(&p);
+ };
+
+ if (jcp.loop_order == loop_rlb) {
+ init_reduce();
+ int ocb = ocb_start;
+ while (ocb < ocb_end) {
+ int load_step;
+ init_load(ocb, load_step);
+ int iwork = bcast_start;
+ while (iwork < bcast_end) {
+ int n, g, bcast_step, oh, ow, ih, iw;
+ init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw);
+ inner_ker(ocb, n, g, oh, ow, ih, iw);
+ iwork += bcast_step;
+ }
+ ocb += load_step;
+ }
+ } else if (jcp.loop_order == loop_lbr) {
+ int ocb = ocb_start;
+ while (ocb < ocb_end) {
+ int load_step;
+ init_load(ocb, load_step);
+ int iwork = bcast_start;
+ while (iwork < bcast_end) {
+ int n, g, bcast_step, oh, ow, ih, iw;
+ init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw);
+ init_reduce();
+ inner_ker(ocb, n, g, oh, ow, ih, iw);
+ iwork += bcast_step;
+ }
+ ocb += load_step;
+ }
+ } else if (jcp.loop_order == loop_rbl) {
+ init_reduce();
+ int iwork = bcast_start;
+ while (iwork < bcast_end) {
+ int n, g, bcast_step, oh, ow, ih, iw;
+ init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw);
+ int ocb = ocb_start;
+ while (ocb < ocb_end) {
+ int load_step;
+ init_load(ocb, load_step);
+ inner_ker(ocb, n, g, oh, ow, ih, iw);
+ ocb += load_step;
+ }
+ iwork += bcast_step;
+ }
+ } else if (jcp.loop_order == loop_blr) {
+ int iwork = bcast_start;
+ while (iwork < bcast_end) {
+ int n, g, bcast_step, oh, ow, ih, iw;
+ init_bcast(iwork, n, g, bcast_step, oh, ow, ih, iw);
+ int ocb = ocb_start;
+ while (ocb < ocb_end) {
+ int load_step;
+ init_load(ocb, load_step);
+ init_reduce();
+ inner_ker(ocb, n, g, oh, ow, ih, iw);
+ ocb += load_step;
+ }
+ iwork += bcast_step;
+ }
+ } else {
+ assert(!"unsupported loop order");
+ }
+}
+
+using namespace data_type;
+template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<u8, u8>;
+template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<s8, u8>;
+template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<u8, s8>;
+template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<s8, s8>;
+template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<u8, s32>;
+template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<s8, s32>;
+template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<u8, f32>;
+template struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<s8, f32>;
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.hpp
new file mode 100644
index 0000000000..ad9027ac17
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_convolution.hpp
@@ -0,0 +1,159 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_CORE_X8S8S32X_1X1_CONVOLUTION_HPP
+#define CPU_JIT_AVX512_CORE_X8S8S32X_1X1_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_avx512_core_x8s8s32x_1x1_conv_kernel.hpp"
+#include "jit_uni_1x1_conv_utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template<impl::data_type_t src_type, impl::data_type_t dst_type>
+struct jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t : public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_(), rtus_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_int8_1x1:", avx512_core, ""),
+ jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t<
+ src_type, dst_type>);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(src_type, data_type::s8, data_type::undef,
+ dst_type, data_type::s32)
+ && IMPLICATION(with_bias(), utils::one_of(
+ desc()->bias_desc.data_type, data_type::f32,
+ data_type::s32, data_type::s8, data_type::u8))
+ && !has_zero_dim_memory()
+ && set_default_formats_common(dat_tag(), format_tag::any,
+ dat_tag())
+ && set_or_check_wei_format();
+ if (!ok) return status::unimplemented;
+
+ const convolution_desc_t *conv_d = desc();
+ const memory_desc_t *src_d = src_md();
+ rtus_prepare(this, conv_d, src_d, dst_md());
+
+ status_t status = jit_avx512_core_x8s8s32x_1x1_conv_kernel::
+ init_conf(jcp_, *conv_d, *src_d, *weights_md(), *dst_md(),
+ *weights_md(1), *attr(), mkldnn_get_max_threads(),
+ rtus_.reduce_src_);
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx512_core_x8s8s32x_1x1_conv_kernel::init_scratchpad(
+ scratchpad, jcp_, *attr());
+
+ rtus_prepare_space_info(this, scratchpad);
+
+ return status::success;
+ }
+
+ jit_1x1_conv_conf_t jcp_;
+ reduce_to_unit_stride_t rtus_;
+
+ protected:
+ format_tag_t dat_tag() const { return format_tag::nhwc; }
+
+ bool set_or_check_wei_format() {
+ using namespace format_tag;
+
+ const bool is_src_s8 = src_md_.data_type == data_type::s8;
+ format_tag_t wei_tag = with_groups() ? gOIhw4i16o4i : OIhw4i16o4i;
+
+ memory_desc_t want_wei_md = weights_md_;
+ memory_desc_init_by_tag(want_wei_md, wei_tag);
+ if (is_src_s8) {
+ want_wei_md.extra.flags = 0
+ | memory_extra_flags::compensation_conv_s8s8
+ | memory_extra_flags::scale_adjust;
+ want_wei_md.extra.compensation_mask = (1 << 0)
+ + (with_groups() ? (1 << 1) : 0);
+ want_wei_md.extra.scale_adjust =
+ mayiuse(avx512_core_vnni) ? 1.f : 0.5f;
+ }
+
+ if (weights_md_.format_kind == format_kind::any) {
+ weights_md_ = want_wei_md;
+ return true;
+ }
+
+ return weights_md_ == want_wei_md;
+ }
+ };
+
+ template <cpu_isa_t isa, typename conv_t>
+ friend void init_rtus_driver(conv_t *self);
+
+ jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , kernel_(nullptr), rtus_driver_(nullptr)
+ {
+ kernel_ = new jit_avx512_core_x8s8s32x_1x1_conv_kernel(pd()->jcp_,
+ *pd()->attr());
+ init_rtus_driver<avx512_common>(this);
+ }
+
+ ~jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t() {
+ delete kernel_;
+ delete rtus_driver_;
+ }
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<data_type::s8>::type wei_data_t;
+ typedef typename prec_traits<dst_type>::type dst_data_t;
+ typedef typename prec_traits<data_type::s32>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+ private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ void execute_forward_thr(const int ithr, const int nthr,
+ const src_data_t *src, const wei_data_t *weights,
+ const char *bias, dst_data_t *dst,
+ const memory_tracking::grantor_t &scratchpad) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx512_core_x8s8s32x_1x1_conv_kernel *kernel_;
+ rtus_driver_t<avx512_common> *rtus_driver_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_deconvolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_deconvolution.hpp
new file mode 100644
index 0000000000..e89d068302
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_1x1_deconvolution.hpp
@@ -0,0 +1,140 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_CORE_X8S8S32X_1X1_DECONVOLUTION_HPP
+#define CPU_JIT_AVX512_CORE_X8S8S32X_1X1_DECONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+#include "type_helpers.hpp"
+#include "primitive_iterator.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_deconvolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_uni_1x1_conv_utils.hpp"
+#include "jit_avx512_core_x8s8s32x_1x1_convolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t src_type, impl::data_type_t dst_type>
+struct jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t
+ : public cpu_primitive_t {
+ struct pd_t : public cpu_deconvolution_fwd_pd_t {
+ pd_t(engine_t *engine, const deconvolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const deconvolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_deconvolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , conv_pd_(nullptr) {}
+
+ pd_t(const pd_t &other)
+ : cpu_deconvolution_fwd_pd_t(other)
+ , conv_pd_(other.conv_pd_->clone())
+ {}
+
+ ~pd_t() { delete conv_pd_; }
+
+ DECLARE_COMMON_PD_T(conv_pd_->name(),
+ jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t<src_type, dst_type>);
+
+ status_t init_convolution() {
+ convolution_desc_t cd;
+ status_t status;
+
+ auto dd = desc();
+ status = conv_desc_init(&cd, prop_kind::forward_training,
+ alg_kind::convolution_direct, &(dd->src_desc),
+ &(dd->weights_desc), &(dd->bias_desc), &(dd->dst_desc),
+ dd->strides, dd->dilates, dd->padding[0], dd->padding[1],
+ dd->padding_kind);
+
+ if (status == status::success) {
+ status = mkldnn_primitive_desc::create<conv_pd_t>(
+ &conv_pd_, (op_desc_t *)&cd, &attr_, engine_, nullptr);
+ }
+
+ if (status == status::success)
+ status = set_default_params();
+
+ return status;
+ };
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && desc()->alg_kind == alg_kind::deconvolution_direct
+ && !has_zero_dim_memory()
+ && desc()->src_desc.data_type == src_type
+ && desc()->dst_desc.data_type == dst_type
+ && desc()->weights_desc.data_type == data_type::s8
+ && IMPLICATION(with_bias(), utils::one_of(
+ desc()->bias_desc.data_type, data_type::f32,
+ data_type::s32, data_type::s8, data_type::u8))
+ && desc()->accum_data_type == data_type::s32;
+ if (!ok) return status::unimplemented;
+
+ CHECK(init_convolution());
+
+ return status::success;
+ }
+
+ virtual void init_scratchpad_md() override {
+ const auto conv_1x1_pd = static_cast<conv_pd_t *>(conv_pd_);
+ scratchpad_md_ = *conv_1x1_pd->scratchpad_md();
+ }
+
+ protected:
+ status_t set_default_params() {
+ auto conv_1x1_pd_ = static_cast<conv_pd_t *>(conv_pd_);
+ src_md_ = *conv_1x1_pd_->src_md();
+ dst_md_ = *conv_1x1_pd_->dst_md();
+ weights_md_ = *conv_1x1_pd_->weights_md();
+ if (with_bias())
+ bias_md_ = *conv_1x1_pd_->weights_md(1);
+ return status::success;
+ }
+
+ using conv_pd_t = typename jit_avx512_core_x8s8s32x_1x1_convolution_fwd_t
+ <src_type, dst_type>::pd_t;
+ friend jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t;
+ primitive_desc_t *conv_pd_;
+ };
+
+ jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ { pd()->conv_pd_->create_primitive((primitive_t **)&conv_p_); }
+
+ ~jit_avx512_core_x8s8s32x_1x1_deconvolution_fwd_t()
+ { delete conv_p_; }
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ return conv_p_->execute(ctx);
+ }
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ primitive_t *conv_p_;
+};
+
+}
+}
+}
+
+#endif /* CPU_JIT_AVX512_CORE_X8S8S32X_1X1_DECONVOLUTION_HPP */
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.cpp
new file mode 100644
index 0000000000..10e98a00c4
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.cpp
@@ -0,0 +1,1182 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_memory.hpp"
+
+#include "jit_avx512_core_x8s8s32x_conv_kernel.hpp"
+
+#define GET_OFF(field) offsetof(jit_conv_call_s, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+using namespace Xbyak;
+
+namespace {
+void pick_loop_order(jit_conv_conf_t &jcp, int nthr)
+{
+ jcp.loop_order = loop_cwgn;
+ if (jcp.ngroups > 1) {
+ jcp.loop_order = loop_ngcw;
+ if (jcp.mb < nthr)
+ jcp.loop_order = jcp.ndims == 3 ? loop_nwcg : loop_nhwcg;
+ }
+}
+}
+
+template<typename Vmm>
+bool _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::maybe_eltwise(int position)
+{
+ using namespace primitive_kind;
+ const auto &p = attr_.post_ops_;
+
+ if (position == 0) {
+ /* eltwise before sum */
+ return p.contain(eltwise, 0);
+ } else if (position == 1) {
+ /* eltwise after sum */
+ return p.contain(sum, 0) && p.contain(eltwise, 1);
+ }
+
+ return false;
+}
+
+template<typename Vmm>
+void _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::prepare_output(int ur_w)
+{
+ int nb_oc_block
+ = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking;
+ for (int k = 0; k < nb_oc_block; k++)
+ for (int j = 0; j < ur_w; j++) {
+ Vmm vmm = vmm_out(j, k);
+ vpxord(vmm, vmm, vmm);
+ }
+ if (jcp.signed_input) {
+ xor_(reg_scratch, reg_scratch);
+ if (jcp.is_depthwise && !jcp.is_fast_depthwise) {
+ Reg32 _t32 = reg_scratch.cvt32();
+ mov(_t32, (uint32_t)128);
+ vpbroadcastd(vmm_shift, _t32);
+ } else {
+ Reg8 _t8 = reg_scratch.cvt8();
+ mov(_t8, (int8_t)128);
+ vpbroadcastb(vmm_shift, _t8);
+ }
+ }
+}
+
+template<typename Vmm>
+const Vmm _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::
+ vmm_mask(const Vmm vmm_in, bool mask_flag, bool store) {
+ return vmm_in;
+}
+
+template<>
+const Zmm _jit_avx512_core_x8s8s32x_fwd_kernel<Zmm>::
+ vmm_mask(const Zmm zmm_in, bool mask_flag, bool store) {
+ return mask_flag ? (store ? zmm_in | ktail_mask : zmm_in | ktail_mask | T_z)
+ : zmm_in;
+}
+
+
+template<typename Vmm>
+void _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::cvt2ps(data_type_t type_in,
+ const Vmm vmm_in, const Operand &op, bool mask_flag) {
+ //const Vmm vmm = mask_flag ? vmm_in | ktail_mask | T_z : vmm_in;
+ const Vmm vmm = vmm_mask(vmm_in, mask_flag);
+ switch (type_in) {
+ case data_type::f32:
+ case data_type::s32: vmovups(vmm, op); break;
+ case data_type::s8: vpmovsxbd(vmm, op); break;
+ case data_type::u8: vpmovzxbd(vmm, op); break;
+ default: assert(!"unsupported data type");
+ }
+ if (type_in != data_type::f32)
+ vcvtdq2ps(vmm_in, vmm_in);
+}
+
+template<typename Vmm>
+void _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::compute_eltwise(int ur_w) {
+ int nb_oc_block
+ = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking;
+ if (ur_w == jcp.ur_w)
+ eltwise_injector_->compute_vector_range(0, nb_oc_block * jcp.ur_w);
+ else
+ for (int k = 0; k < nb_oc_block; k++)
+ eltwise_injector_->compute_vector_range(k * jcp.ur_w,
+ k * jcp.ur_w + ur_w);
+}
+
+template<typename Vmm>
+void _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::store_output(
+ int ur_w, bool last_oc_block_flag) {
+ int nb_oc_block
+ = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking;
+ int oc_block = jcp.is_depthwise ? jcp.ch_block : jcp.oc_block;
+
+ mov(reg_bias, ptr[param1 + GET_OFF(bias)]);
+ mov(reg_ptr_scales, ptr[param1 + GET_OFF(scales)]);
+ if (jcp.signed_input)
+ mov(reg_compensation, ptr[param1 + GET_OFF(compensation)]);
+
+ const auto &p = attr_.post_ops_;
+ const int sum_idx = p.find(primitive_kind::sum);
+ const float *p_sum_scale = nullptr;
+ if (sum_idx != -1) {
+ const auto &p_entry = p.entry_[sum_idx];
+ p_sum_scale = &p_entry.sum.scale;
+ }
+
+ if (p_sum_scale && *p_sum_scale != 1.f)
+ mov(reg_ptr_sum_scale, (size_t)p_sum_scale);
+
+ if (jcp.signed_input && jcp.ver != ver_vnni) {
+ /* put 'wei_adj_scale = 0.5' for bias calculation */
+ mov(reg_bias_alpha, float2int(jcp.wei_adj_scale));
+ vmovq(xmm_bias_alpha(), reg_bias_alpha);
+ vbroadcastss(vmm_bias_alpha(), xmm_bias_alpha());
+ }
+
+ for (int k = 0; k < nb_oc_block; k++) {
+ const bool mask_flag = last_oc_block_flag && k == nb_oc_block - 1;
+ int scale_offset = jcp.is_oc_scale * (sizeof(float) * k * oc_block);
+ if (jcp.with_bias) {
+ int bias_offset = jcp.typesize_bia * k * oc_block;
+ auto bias_addr = EVEX_compress_addr(reg_bias, bias_offset);
+
+ cvt2ps(jcp.bia_dt, vmm_bias, bias_addr, mask_flag);
+ if (jcp.signed_input && jcp.ver != ver_vnni)
+ /* bias *= 0.5 */
+ vmulps(vmm_bias, vmm_bias, vmm_bias_alpha());
+ }
+ if (jcp.signed_input) {
+ int comp_offset = sizeof(int32_t) * k * oc_block;
+ auto comp_addr = EVEX_compress_addr(reg_compensation, comp_offset);
+
+ cvt2ps(data_type::s32, vmm_comp, comp_addr, mask_flag);
+ }
+ /* add to zmm_accum: compensation, bias and permute */
+ for (int j = 0; j < ur_w; j++) {
+ Vmm vmm = vmm_out(j, k);
+ if (jcp.is_fast_depthwise)
+ vpermd(zmm_out(j, k), zmm_permute, zmm_out(j, k));
+ vcvtdq2ps(vmm, vmm);
+ if (jcp.signed_input)
+ vaddps(vmm, vmm, vmm_comp);
+ if (jcp.with_bias)
+ vaddps(vmm, vmm, vmm_bias);
+
+ const Vmm vmm_k = vmm_mask(vmm, mask_flag);
+ vmulps(vmm_k, vmm,
+ EVEX_compress_addr(reg_ptr_scales, scale_offset));
+ }
+ }
+
+ /* Do post-ops */
+ if (maybe_eltwise(0)) compute_eltwise(ur_w);
+ if (p_sum_scale) { // post_op: sum
+ for (int k = 0; k < nb_oc_block; k++) {
+ const bool mask_flag = last_oc_block_flag && k == nb_oc_block - 1;
+ for (int j = 0; j < ur_w; j++) {
+ int aux_output_offset
+ = jcp.typesize_out
+ * (k * oc_block
+ + j * jcp.oc_without_padding * jcp.ngroups);
+ auto addr = EVEX_compress_addr(reg_out, aux_output_offset);
+ Vmm vmm = vmm_out(j, k);
+ cvt2ps(jcp.dst_dt, vmm_prev_dst, addr, mask_flag);
+ if (*p_sum_scale == 1.f)
+ vaddps(vmm, vmm_prev_dst);
+ else
+ vfmadd231ps(vmm, vmm_prev_dst, zword_b[reg_ptr_sum_scale]);
+ }
+ }
+ }
+ if (maybe_eltwise(1)) compute_eltwise(ur_w);
+
+ /* write out register to output_addr */
+ for (int k = 0; k < nb_oc_block; k++) {
+ const bool mask_flag = last_oc_block_flag && k == nb_oc_block - 1;
+ for (int j = 0; j < ur_w; j++) {
+ Vmm vmm = vmm_out(j, k);
+ if (jcp.dst_dt == data_type::u8) {
+ vpxord(vmm_zero, vmm_zero, vmm_zero);
+ vmaxps(vmm, vmm_zero, vmm);
+ }
+
+ if (jcp.dst_dt != data_type::f32) {
+ /* Note: using Zmm for rounding in Xmm/Ymm kernel
+ because there is no instruction to do rounding
+ from Xmm/Ymm -> Xmm/Ymm.
+ Embedded rounding is not supported for Xmm.
+ TODO: maybe avoid Zmm if it helps performance.*/
+ Zmm zmm = zmm_out(j, k);
+ vcvtps2dq(zmm, zmm);
+ }
+ }
+
+ for (int j = 0; j < ur_w; j++) {
+ int aux_output_offset = jcp.typesize_out
+ * (k * oc_block + j * jcp.oc_without_padding * jcp.ngroups);
+ auto addr = EVEX_compress_addr(reg_out, aux_output_offset);
+
+ Vmm vmm = vmm_out(j, k);
+ const Vmm r_vmm = vmm_mask(vmm, mask_flag, true);
+
+ switch (jcp.dst_dt) {
+ case data_type::f32:
+ case data_type::s32: vmovups(addr, r_vmm); break;
+ case data_type::s8: vpmovsdb(addr, r_vmm); break;
+ case data_type::u8: vpmovusdb(addr, r_vmm); break;
+ default: assert(!"unknown dst_dt");
+ }
+ }
+ }
+
+}
+
+template <typename Vmm>
+void _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::compute_ker_dw(
+ int ur_w, int pad_l, int pad_r, ic_block_t last_ic_block_flag, bool h_padded) {
+ assert(!"invalid group blocking for depthwise convolution");
+}
+
+template <>
+void _jit_avx512_core_x8s8s32x_fwd_kernel<Zmm>::compute_ker_dw(
+ int ur_w, int pad_l, int pad_r, ic_block_t last_ic_block_flag, bool h_padded) {
+
+ auto input_spatial_index = [=](int oi, int ki) {
+ return (ki * (jcp.dilate_w + 1) + oi * jcp.stride_w - pad_l);
+ };
+
+ auto input_offset2 = [=](int ii, int ci) {
+ return jcp.typesize_in * (ii * jcp.ngroups + ci * jcp.ch_block);
+ };
+
+ auto input_offset3 = [=](int oi, int ci, int ki) {
+ return jcp.typesize_in * input_offset2(input_spatial_index(oi, ki), ci);
+ };
+
+ auto kernel_offset = [=](int ci, int ki) {
+ return jcp.typesize_in * ((ci * jcp.kh * jcp.kw + ki) * jcp.ch_block);
+ };
+
+ auto compute = [=](Zmm vreg_acc, Zmm vreg_wei, Zmm vreg_src) {
+ // okay for depthwise since src is zero-extended
+ if (jcp.ver == ver_vnni) {
+ vpdpbusd(vreg_acc, vreg_src, vreg_wei);
+ } else {
+ vpmaddwd(zmm_tmp, vreg_src, vreg_wei);
+ vpaddd(vreg_acc, vreg_acc, zmm_tmp);
+ }
+ };
+
+ int ii_start = 0;
+ int ii_end = -1;
+ if (jcp.is_resrc_depthwise && !h_padded) {
+ // find bounds of input spatial indices
+ bool first = true;
+ for (int ki = 0; ki < jcp.kw; ki++) {
+ int oi_start = get_ow_start(ki, pad_l);
+ int oi_end = get_ow_end(ur_w, ki, pad_r);
+ for (int oi = oi_start; oi < oi_end; oi++) {
+ int ii = input_spatial_index(oi, ki);
+ if (first || ii < ii_start)
+ ii_start = ii;
+ if (first || ii > ii_end)
+ ii_end = ii;
+ first = false;
+ }
+ }
+ }
+
+ if (jcp.signed_input) {
+ vpxord(zmm_shifted_zero, zmm_shifted_zero, zmm_shifted_zero);
+ vpaddb(zmm_shifted_zero, zmm_shifted_zero, vmm_shift);
+ }
+ for (int ci = 0; ci < jcp.nb_ch_blocking; ci++) {
+ const bool mask_flag = last_ic_block_flag != no_last_block
+ && ci == jcp.nb_ch_blocking - 1;
+ if (jcp.is_resrc_depthwise && !h_padded) {
+ // now we can load input once and reuse up to jcp.kw times
+ for (int ii = ii_start; ii <= ii_end; ii++) {
+ int aux_input_offset = input_offset2(ii, ci);
+ const Zmm zmm_inp_tmp = zmm_inp(ii, jcp.nb_ch_blocking);
+ const Zmm zmm_inp_msk = mask_flag
+ ? zmm_inp_tmp | ktail_mask | T_z
+ : zmm_inp_tmp;
+ if (jcp.is_fast_depthwise) {
+ assert(!mask_flag);
+ vbroadcasti32x4(zmm_inp_msk,
+ EVEX_compress_addr(aux_reg_inp, aux_input_offset));
+ } else {
+ vpmovzxbd(zmm_inp_msk,
+ EVEX_compress_addr(aux_reg_inp, aux_input_offset));
+ }
+ if (jcp.signed_input)
+ vpaddb(zmm_inp_tmp, zmm_inp_tmp, vmm_shift);
+ }
+ }
+ for (int ki = 0; ki < jcp.kw; ki++) {
+ int aux_kernel_offset = kernel_offset(ci, ki);
+ if (jcp.is_fast_depthwise) {
+ vbroadcasti32x4(zmm_wei,
+ EVEX_compress_addr(aux_reg_ker, aux_kernel_offset));
+ vmovdqu8(zmm_wei | kblend_mask | T_z, zmm_wei);
+ } else {
+ vpmovsxbd(zmm_wei,
+ EVEX_compress_addr(aux_reg_ker, aux_kernel_offset));
+ }
+ if (h_padded) {
+ assert(jcp.signed_input);
+ for (int oi = 0; oi < ur_w; oi++)
+ compute(zmm_out(oi, ci), zmm_wei, zmm_shifted_zero);
+ } else {
+ const Zmm r_zmm_src = mask_flag ? zmm_src | ktail_mask : zmm_src;
+ int oi_start = get_ow_start(ki, pad_l);
+ int oi_end = get_ow_end(ur_w, ki, pad_r);
+ int start_ = jcp.signed_input ? 0 : oi_start;
+ int end_ = jcp.signed_input ? ur_w : oi_end;
+ for (int oi = start_; oi < end_; oi++) {
+ if (oi >= oi_start && oi < oi_end) {
+ if (jcp.is_resrc_depthwise) {
+ int ii = input_spatial_index(oi, ki);
+ zmm_src = zmm_inp(ii, jcp.nb_ch_blocking);
+ } else {
+ int aux_input_offset = input_offset3(oi, ci, ki);
+ if (jcp.is_fast_depthwise) {
+ assert(!mask_flag);
+ vbroadcasti32x4(r_zmm_src,
+ EVEX_compress_addr(aux_reg_inp,
+ aux_input_offset));
+ } else {
+ vpmovzxbd(r_zmm_src,
+ EVEX_compress_addr(aux_reg_inp,
+ aux_input_offset));
+ }
+ if (jcp.signed_input)
+ vpaddb(zmm_src, zmm_src, vmm_shift);
+ }
+ } else if (jcp.signed_input) {
+ zmm_src = zmm_shifted_zero;
+ }
+ compute(zmm_out(oi, ci), zmm_wei, zmm_src);
+ }
+ }
+ }
+ }
+}
+
+template<typename Vmm>
+void _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::compute_ker(int ur_w, int pad_l,
+ int pad_r, ic_block_t last_ic_block_flag, bool h_padded) {
+ if (jcp.is_depthwise)
+ return compute_ker_dw(ur_w, pad_l, pad_r, last_ic_block_flag, h_padded);
+
+ int kw = jcp.kw;
+ int stride_w = jcp.stride_w;
+ int ic_block = jcp.ic_block;
+ int oc_block = jcp.oc_block;
+ int ch_block_all = jcp.ch_block * ic_block * oc_block;
+
+ int nb_oc_block = jcp.nb_oc_blocking;
+
+ auto input_offset = [=](int oi, int ic, int ki) {
+ return jcp.typesize_in
+ * ((ki * (jcp.dilate_w + 1) + oi * stride_w - pad_l)
+ * jcp.ic_without_padding * jcp.ngroups + 4 * ic);
+ };
+ auto kernel_offset = [=](int ii, int ic, int ki) {
+ return jcp.typesize_in
+ * ((ii * jcp.nb_ic * jcp.kh * jcp.kw + ki) * ch_block_all
+ + 4 * ic * oc_block);
+ };
+ auto compute = [=](Vmm vreg_acc, Vmm vreg_wei, Vmm vreg_src) {
+ if (jcp.ver == ver_vnni) {
+ vpdpbusd(vreg_acc, vreg_src, vreg_wei);
+ } else {
+ vpmaddubsw(vmm_tmp, vreg_src, vreg_wei);
+ vpmaddwd(vmm_tmp, vmm_tmp, vmm_one);
+ vpaddd(vreg_acc, vreg_acc, vmm_tmp);
+ }
+ };
+
+ for (int ki = 0; ki < kw; ki++) {
+ int jj_start = get_ow_start(ki, pad_l);
+ int jj_end = get_ow_end(ur_w, ki, pad_r);
+ int tail_size = jcp.ic_without_padding % 4;
+ int _start = (jcp.signed_input) ? 0 : jj_start;
+ int _end = (jcp.signed_input) ? ur_w : jj_end;
+ /* Skip the last loads of input if (ic%16)/4 < ic_block/4 */
+ int icb = (last_ic_block_flag != no_last_block)
+ ? div_up((jcp.ic_without_padding % ic_block), 4)
+ : ic_block / 4;
+ for (int ic = 0; ic < icb; ic++) {
+ if (h_padded == true) {
+ /* fill padded area with shifted values */
+ Vmm inp = vmm_inp(0,nb_oc_block);
+ vpxord(inp, inp, inp);
+ vpaddb(inp, inp, vmm_shift);
+ } else {
+ for (int jj = _start; jj < _end; jj++) {
+ int aux_input_offset = input_offset(jj, ic, ki);
+ if (jj >= jj_start && jj < jj_end) {
+ if (last_ic_block_flag == last_sp_block
+ && tail_size != 0 && ic == icb - 1) {
+ Xmm xmm_tmp = Xmm(vmm_inp(jj, nb_oc_block).getIdx());
+ for (int r = 0; r < tail_size; ++r)
+ vpinsrb(xmm_tmp, xmm_tmp,
+ ptr[aux_reg_inp + aux_input_offset + r], r);
+ vpbroadcastd(vmm_inp(jj, nb_oc_block), xmm_tmp);
+ } else {
+ vpbroadcastd(vmm_inp(jj, nb_oc_block),
+ EVEX_compress_addr(
+ aux_reg_inp, aux_input_offset));
+ }
+ if (jcp.signed_input)
+ vpaddb(vmm_inp(jj, nb_oc_block),
+ vmm_inp(jj, nb_oc_block), vmm_shift);
+ } else {
+ /* fill padded area with shifted values */
+ if (jcp.signed_input) {
+ Vmm inp = vmm_inp(jj, nb_oc_block);
+ vpxord(inp, inp, inp);
+ vpaddb(inp, inp, vmm_shift);
+ }
+ }
+ }
+ }
+ for (int ii = 0; ii < nb_oc_block; ii++) {
+ int aux_kernel_offset = kernel_offset(ii, ic, ki);
+ vmovups(vmm_wei,
+ EVEX_compress_addr(aux_reg_ker, aux_kernel_offset));
+ for (int jj = _start; jj < _end; jj++) {
+ Vmm inp = (h_padded == true)
+ ? vmm_inp(0,nb_oc_block) : vmm_inp(jj, nb_oc_block);
+ compute(vmm_out(jj, ii), vmm_wei, inp);
+ }
+ }
+ }
+ }
+}
+
+template<typename Vmm>
+void _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::kh_loop(
+ int ur_w, int pad_l, int pad_r, ic_block_t last_ic_block_flag) {
+ Label kh_label, skip_kh_loop;
+ Label t_overflow_label, no_t_overflow_label,
+ b_overflow_label, no_b_overflow_label;
+
+ int ch_block_all = jcp.ch_block * jcp.ic_block * jcp.oc_block;
+ int shift_kernel_ptr = jcp.typesize_in * jcp.kw * ch_block_all;
+ int shift_input_ptr = jcp.typesize_in * (jcp.dilate_h + 1) * jcp.iw
+ * jcp.ic_without_padding * jcp.ngroups;
+
+ mov(aux_reg_inp, reg_inp);
+ mov(aux_reg_ker, reg_ker);
+
+ if (jcp.signed_input && jcp.ndims > 3) {
+ mov(reg_overflow, ptr[param1 + GET_OFF(t_overflow)]);
+ cmp(reg_overflow, 0);
+ je(no_t_overflow_label, T_NEAR);
+ L(t_overflow_label); {
+ compute_ker(ur_w, pad_l, pad_r, last_ic_block_flag, true);
+
+ add(aux_reg_ker, shift_kernel_ptr);
+ dec(reg_overflow);
+ cmp(reg_overflow, 0);
+ jg(t_overflow_label, T_NEAR);
+ }
+ L(no_t_overflow_label);
+ }
+ mov(reg_kj, ptr[param1 + GET_OFF(kh_padding)]);
+ if ((jcp.signed_input) || (!jcp.signed_input &&
+ (jcp.kh - 1) * (jcp.dilate_h + 1) < nstl::max(jcp.t_pad, jcp.b_pad))) {
+ cmp(reg_kj, 0);
+ je(skip_kh_loop, T_NEAR);
+ }
+ L(kh_label); {
+ compute_ker(ur_w, pad_l, pad_r, last_ic_block_flag, false);
+
+ add(aux_reg_ker, shift_kernel_ptr);
+ add(aux_reg_inp, shift_input_ptr);
+ dec(reg_kj);
+ cmp(reg_kj, 0);
+ jg(kh_label, T_NEAR);
+ }
+ L(skip_kh_loop);
+ if (jcp.signed_input && jcp.ndims > 3) {
+ mov(reg_overflow, ptr[param1 + GET_OFF(b_overflow)]);
+ cmp(reg_overflow, 0);
+ je(no_b_overflow_label, T_NEAR);
+ L(b_overflow_label); {
+ compute_ker(ur_w, pad_l, pad_r, last_ic_block_flag, true);
+
+ add(aux_reg_ker, shift_kernel_ptr);
+ dec(reg_overflow);
+ cmp(reg_overflow, 0);
+ jg(b_overflow_label, T_NEAR);
+ }
+ L(no_b_overflow_label);
+ }
+}
+
+template<typename Vmm>
+void _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::icb_loop(
+ int ur_w, int pad_l, int pad_r, bool is_last_sp_block)
+{
+ prepare_output(ur_w);
+
+ // IC loop
+ Label icb_label;
+ mov(reg_icb, jcp.nb_ic);
+ L(icb_label);
+ if (jcp.ngroups % jcp.ch_block != 0 || jcp.ic_without_padding != jcp.ic) {
+ Label common_ker, end_ker;
+
+ cmp(reg_icb, 1); // The last IC block
+ jne(common_ker, T_NEAR);
+
+ kh_loop(ur_w, pad_l, pad_r,
+ is_last_sp_block ? last_sp_block : last_ic_block);
+ jmp(end_ker, T_NEAR);
+
+ L(common_ker);
+ kh_loop(ur_w, pad_l, pad_r, no_last_block);
+
+ L(end_ker);
+ } else {
+ kh_loop(ur_w, pad_l, pad_r, no_last_block);
+ }
+ // End of IC Loop
+ int inp_step = jcp.ic_block;
+ int ker_step = jcp.kh * jcp.kw * jcp.oc_block * jcp.ic_block;
+ add(reg_inp, jcp.typesize_in * inp_step);
+ add(reg_ker, jcp.typesize_in * ker_step);
+
+ dec(reg_icb);
+ cmp(reg_icb, 0);
+ jg(icb_label, T_NEAR);
+
+ sub(reg_inp, jcp.typesize_in * inp_step * jcp.nb_ic);
+ sub(reg_ker, jcp.typesize_in * ker_step * jcp.nb_ic);
+
+ if (jcp.ngroups % jcp.ch_block != 0 || jcp.oc_without_padding != jcp.oc) {
+ Label common_store, end_store;
+
+ if (jcp.is_depthwise)
+ cmp(reg_oc_blocks, jcp.nb_ch - jcp.nb_ch_blocking);
+ else
+ cmp(reg_oc_blocks, jcp.nb_oc - jcp.nb_oc_blocking);
+
+ jne(common_store, T_NEAR);
+
+ store_output(ur_w, true); // last oc block
+ jmp(end_store, T_NEAR);
+
+ L(common_store);
+ store_output(ur_w, false);
+
+ L(end_store);
+ } else {
+ store_output(ur_w, false);
+ }
+}
+
+template<typename Vmm>
+void _jit_avx512_core_x8s8s32x_fwd_kernel<Vmm>::generate()
+{
+ Label permute_index_table;
+ int inp_shift_pad = jcp.typesize_in * (jcp.ur_w * jcp.stride_w - jcp.l_pad)
+ * jcp.ic_without_padding * jcp.ngroups;
+ int inp_shift_pad_second_block = -1 * jcp.typesize_in * jcp.l_pad
+ * jcp.ic_without_padding * jcp.ngroups;
+ int inp_shift = jcp.typesize_in *
+ (jcp.ur_w * jcp.stride_w * jcp.ic_without_padding
+ * jcp.ngroups);
+ int out_shift = jcp.typesize_out *
+ (jcp.ur_w * jcp.oc_without_padding * jcp.ngroups);
+ preamble();
+
+ if (jcp.is_depthwise) {
+ int idx = jcp.max_regs_ur - 1;
+ if (!jcp.is_resrc_depthwise)
+ zmm_src = Zmm(++idx);
+ if (jcp.ver != ver_vnni)
+ zmm_tmp = Zmm(++idx);
+ if (jcp.is_fast_depthwise)
+ zmm_permute = Zmm(++idx);
+ if (jcp.signed_input) {
+ zmm_shifted_zero = Zmm(++idx);
+ ++idx; // due to extra register used for shifts and compensations
+ }
+ assert(idx == ker_dw_reg_base_idx);
+ }
+
+ if (!jcp.is_depthwise && jcp.ver != ver_vnni) {
+ xor_(reg_scratch, reg_scratch);
+ Reg16 _t16 = reg_scratch.cvt16();
+ mov(_t16, 0x1);
+ vpbroadcastw(vmm_one, _t16);
+ }
+
+ mov(reg_inp, ptr[param1 + GET_OFF(src)]);
+ mov(reg_out, ptr[param1 + GET_OFF(dst)]);
+ mov(reg_ker, ptr[param1 + GET_OFF(filt)]);
+
+ if (jcp.ngroups % jcp.ch_block != 0 || jcp.oc_without_padding != jcp.oc) {
+ int tail_size = jcp.is_depthwise
+ ? jcp.ngroups % jcp.ch_block
+ : jcp.oc_without_padding % jcp.oc_block;
+ int mask = (1 << tail_size) - 1;
+ mov(reg_oc_blocks, ptr[param1 + GET_OFF(oc_blocks)]);
+ Reg32 regw_tmp = reg_oi.cvt32();
+ mov(regw_tmp, mask);
+ kmovw(ktail_mask, regw_tmp);
+ }
+ if (jcp.is_fast_depthwise) {
+ // prepare mask register for blending weights
+ mov(reg_scratch, 0x8888444422221111);
+ kmovq(kblend_mask, reg_scratch);
+ // load permute indices from data section
+ mov(reg_scratch, permute_index_table);
+ vmovdqu32(zmm_permute, ptr[reg_scratch]);
+ }
+
+ int r_pad = nstl::max(0, (jcp.ow - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1)
+ - (jcp.iw + jcp.l_pad - 1));
+ int n_oi = jcp.ow / jcp.ur_w;
+ int r_pad1 = (jcp.ur_w * n_oi - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1);
+
+ if (jcp.nb_ow == 1) {
+ if (r_pad1 > 0 || jcp.ur_w_tail == 0)
+ n_oi--;
+
+ xor_(reg_oi, reg_oi);
+ if (jcp.ow == jcp.ur_w) {
+ icb_loop(jcp.ur_w, jcp.l_pad, r_pad, true);
+ } else {
+ if (n_oi == 0) {
+ icb_loop(jcp.ur_w, jcp.l_pad, r_pad1, jcp.ur_w_tail == 0);
+ add(reg_inp, inp_shift_pad);
+ add(reg_out, out_shift);
+ if (jcp.ur_w_tail != 0) {
+ icb_loop(jcp.ur_w_tail, 0, r_pad, true);
+ }
+ } else {
+ if (jcp.l_pad > 0) {
+ icb_loop(jcp.ur_w, jcp.l_pad, 0, false);
+ add(reg_inp, inp_shift_pad);
+ add(reg_out, out_shift);
+
+ inc(reg_oi);
+ }
+ if ((jcp.l_pad <= 0 && n_oi > 0) || (jcp.l_pad > 0 && n_oi > 1))
+ {
+ Label ow_loop_label;
+ L(ow_loop_label); {
+ icb_loop(jcp.ur_w, 0, 0, false);
+ add(reg_inp, inp_shift);
+ add(reg_out, out_shift);
+
+ inc(reg_oi);
+ cmp(reg_oi, n_oi);
+ jl(ow_loop_label, T_NEAR);
+ }
+ }
+ if (r_pad1 > 0 || jcp.ur_w_tail == 0) {
+ icb_loop(jcp.ur_w, 0, r_pad1, jcp.ur_w_tail == 0);
+ add(reg_inp, inp_shift);
+ add(reg_out, out_shift);
+ }
+ if (jcp.ur_w_tail != 0) {
+ icb_loop(jcp.ur_w_tail, 0, r_pad, true);
+ }
+ }
+ }
+ } else {
+ // ow block is only processed.
+ // Number of block is passed as parameter owb,
+ // and padding processing depends on this number.
+ Label end_label, last_oi_label, middle_ow_blocks_label, tail_label,
+ oi_loop_label, oi_loop_end_label;
+
+ assert(jcp.ow_block % jcp.ur_w == 0);
+ int n_oi_not_last_ow_block = jcp.ow_block / jcp.ur_w;
+ // to simplify code (and general regs usage),
+ // size of ow block must be >= 2 * ur_w
+ assert(n_oi_not_last_ow_block > 1);
+ int n_oi_next_last_ow_block = n_oi_not_last_ow_block;
+ int n_oi_first_ow_block = n_oi_not_last_ow_block;
+ int n_oi_last_ow_block
+ = (jcp.ow - jcp.ow_block * (jcp.nb_ow - 1)) / jcp.ur_w;
+ // prepare right padding
+ bool next_last_ow_block_padded = r_pad1 > 0 && n_oi_last_ow_block == 0;
+ bool first_ow_block_padded
+ = next_last_ow_block_padded && jcp.nb_ow == 2;
+ bool last_ow_block_padded
+ = (r_pad1 > 0 || jcp.ur_w_tail == 0) && n_oi_last_ow_block > 0;
+
+ if (last_ow_block_padded) n_oi_last_ow_block--;
+ else if (first_ow_block_padded) n_oi_first_ow_block--;
+ else if (next_last_ow_block_padded) n_oi_next_last_ow_block--;
+
+ mov(reg_owb, ptr[param1 + GET_OFF(owb)]);
+ cmp(reg_owb, 0); // is that the first ow-block ?
+ jg(middle_ow_blocks_label, T_NEAR);
+
+ // the first ow block, compute left padding
+ mov(reg_oi, n_oi_first_ow_block);
+ if (jcp.l_pad > 0) {
+ icb_loop(jcp.ur_w, jcp.l_pad, 0, false);
+ add(reg_inp, inp_shift_pad);
+ add(reg_out, out_shift);
+
+ dec(reg_oi);
+ }
+ jmp(oi_loop_label, T_NEAR);
+
+ // middle or last ow block entry
+ L(middle_ow_blocks_label);
+
+ if (jcp.l_pad > 0) {
+ // just to consider left padding, not compute
+ add(reg_inp, inp_shift_pad_second_block);
+ }
+
+ // set number of iteration for oi-loop
+ if (n_oi_last_ow_block != n_oi_not_last_ow_block) {
+ cmp(reg_owb, jcp.nb_ow - 1); // last ow-block ?
+ mov(reg_oi, n_oi_last_ow_block);
+ je(oi_loop_label, T_NEAR);
+ }
+
+ if (n_oi_next_last_ow_block != n_oi_not_last_ow_block) {
+ cmp(reg_owb, jcp.nb_ow - 2); // next to last ow-block ?
+
+ mov(reg_oi, n_oi_next_last_ow_block);
+ je(oi_loop_label, T_NEAR);
+ }
+ mov(reg_oi, n_oi_not_last_ow_block); // other middle ow-blocks
+
+ // oi loop w/o padding
+ L(oi_loop_label); {
+ cmp(reg_oi, 0);
+ jle(oi_loop_end_label, T_NEAR);
+
+ icb_loop(jcp.ur_w, 0, 0, false);
+
+ add(reg_inp, inp_shift);
+ add(reg_out, out_shift);
+ dec(reg_oi);
+
+ jmp(oi_loop_label, T_NEAR);
+ }
+ L(oi_loop_end_label);
+
+ mov(reg_owb, ptr[param1 + GET_OFF(owb)]);
+ cmp(reg_owb, 0); // first ow-block ?
+ if (first_ow_block_padded)
+ je(last_oi_label, T_NEAR);
+ else
+ je(end_label, T_NEAR);
+
+ cmp(reg_owb, jcp.nb_ow - 2); // next to last ow-block ?
+ jl(end_label, T_NEAR);
+ if (next_last_ow_block_padded)
+ je(last_oi_label, T_NEAR);
+ else
+ je(end_label, T_NEAR);
+
+ // that is last block
+ if (!last_ow_block_padded)
+ jmp(tail_label, T_NEAR);
+
+ // last oi block with right padding
+ L(last_oi_label);
+ icb_loop(jcp.ur_w, 0, r_pad1, jcp.ur_w_tail == 0);
+ add(reg_inp, inp_shift);
+ add(reg_out, out_shift);
+
+ mov(reg_owb, ptr[param1 + GET_OFF(owb)]);
+ cmp(reg_owb, jcp.nb_ow - 1); // last ow_block?
+ jl(end_label, T_NEAR);
+
+ // ur_w tail
+ L(tail_label);
+ if (jcp.ur_w_tail != 0) {
+ icb_loop(jcp.ur_w_tail, 0, r_pad, true);
+ }
+ L(end_label);
+ }
+ postamble();
+
+ if (jcp.with_eltwise)
+ eltwise_injector_->prepare_table();
+
+ if (jcp.is_fast_depthwise) {
+ align(64);
+ L(permute_index_table);
+ const uint32_t _idx[]
+ = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 };
+ for (size_t i = 0; i < sizeof(_idx) / sizeof(_idx[0]); ++i)
+ dd(_idx[i]);
+ }
+}
+
+bool jit_avx512_core_x8s8s32x_fwd_kernel::post_ops_ok(
+ jit_conv_conf_t &jcp, const primitive_attr_t &attr)
+{
+ using namespace primitive_kind;
+ const auto &p = attr.post_ops_;
+
+ auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); };
+
+ switch (p.len_) {
+ case 0: return true;
+ case 1: return is_eltwise(0) || p.contain(sum, 0);
+ case 2: return (p.contain(sum, 0) && is_eltwise(1)) ||
+ (p.contain(sum, 1) && is_eltwise(0));
+ default: return false;
+ }
+
+ return false;
+}
+
+status_t jit_avx512_core_x8s8s32x_fwd_kernel::init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, memory_desc_t &src_md,
+ memory_desc_t &weights_md, memory_desc_t &dst_md,
+ memory_desc_t &bias_md, const primitive_attr_t &attr,
+ int nthreads)
+{
+ using namespace prop_kind;
+
+ const memory_desc_wrapper src_d(&src_md);
+ const memory_desc_wrapper weights_d(&weights_md);
+ const memory_desc_wrapper dst_d(&dst_md);
+ const memory_desc_wrapper bias_d(&bias_md);
+
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ int ndims = src_d.ndims();
+ bool is_1d = ndims == 3;
+
+ if (!(mayiuse(avx512_core)
+ && one_of(src_d.data_type(), data_type::u8, data_type::s8)
+ && weights_d.data_type() == data_type::s8
+ && one_of(dst_d.data_type(), data_type::f32, data_type::s32,
+ data_type::s8, data_type::u8)))
+ return status::unimplemented;
+
+ jcp = zero<decltype(jcp)>();
+ jcp.ndims = ndims;
+ jcp.prop_kind = cd.prop_kind;
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.ic_without_padding = jcp.ic;
+ jcp.ih = is_1d ? 1 : src_d.dims()[ndims - 2];
+ jcp.iw = src_d.dims()[ndims - 1];
+ jcp.oh = is_1d ? 1 : dst_d.dims()[ndims - 2];
+ jcp.ow = dst_d.dims()[ndims - 1];
+ jcp.kh = is_1d ? 1 : weights_d.dims()[with_groups + ndims - 2];
+ jcp.kw = weights_d.dims()[with_groups + ndims - 1];
+ jcp.t_pad = is_1d ? 0 : cd.padding[0][ndims - 4];
+ jcp.l_pad = cd.padding[0][ndims - 3];
+ jcp.stride_h = is_1d ? 1 : cd.strides[ndims - 4];
+ jcp.stride_w = cd.strides[ndims - 3];
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ jcp.ur_h = 1; /* no code-unrolling by h so far */
+
+ jcp.dilate_h = is_1d ? 0 : cd.dilates[ndims - 4];
+ jcp.dilate_w = cd.dilates[ndims - 3];
+
+ jcp.signed_input = (src_d.data_type() == data_type::s8) ? true : false;
+ jcp.is_depthwise = true && with_groups && everyone_is(1, jcp.ic, jcp.oc);
+
+ if (jcp.is_depthwise) {
+ jcp.ch_block = 16;
+ jcp.ic_block = 1;
+ jcp.oc_block = 1;
+ } else {
+ jcp.ch_block = 1;
+ jcp.ic_block = 16;
+ jcp.oc_block = 16;
+
+ if (jcp.ngroups == 1) {
+ /* For non grouped convolutions, pad channels by 16 if needed */
+ jcp.oc = rnd_up(jcp.oc, jcp.oc_block);
+ jcp.ic = rnd_up(jcp.ic, jcp.ic_block);
+ } else if (!is_1d && jcp.ngroups != 1 && jcp.ic % jcp.ic_block != 0) {
+ /* For grouped convolutions, MKL-DNN doesn't support padding.
+ Use Ymm when channels per group is multiple of 8,
+ Xmm when channels per group is multiple of 4 */
+ jcp.ic_block = jcp.ic % 8 == 0 ? 8 : 4;
+ jcp.oc_block = jcp.ic_block;
+ }
+ if (jcp.ic % jcp.ic_block !=0 || jcp.oc % jcp.oc_block != 0)
+ return status::unimplemented;
+ }
+
+ jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1)
+ - (jcp.ih + jcp.t_pad - 1);
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ const int eltwise_ind = p.find(primitive_kind::eltwise);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise)
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+
+ jcp.ver = mayiuse(avx512_core_vnni) ? ver_vnni : ver_avx512_core;
+ jcp.is_fast_depthwise = true && jcp.is_depthwise && jcp.ver == ver_vnni
+ && jcp.ngroups % jcp.ch_block == 0; // for groups not multiple of 16
+ // would require byte masking
+ // for load from src
+ jcp.is_resrc_depthwise = jcp.is_depthwise && jcp.stride_w < jcp.kw
+ && jcp.kw < 4 && jcp.dilate_w == 0;
+ if (jcp.is_depthwise) {
+ jcp.max_regs_ur = 31 - jcp.is_fast_depthwise - !jcp.is_resrc_depthwise
+ - 2 * jcp.signed_input - (jcp.ver != ver_vnni);
+ } else {
+ jcp.max_regs_ur = jcp.ver == ver_vnni ? 31 : 28;
+ }
+
+ auto set_or_check_wei_format = [&]() {
+ using namespace format_tag;
+ format_tag_t wei_tag;
+ if (jcp.ic_block == 16 || jcp.ch_block == 16) {
+ if (is_1d) {
+ wei_tag = with_groups
+ ? jcp.is_depthwise ? Goiw16g : gOIw4i16o4i
+ : OIw4i16o4i;
+ } else {
+ wei_tag = with_groups
+ ? jcp.is_depthwise ? Goihw16g : gOIhw4i16o4i
+ : OIhw4i16o4i;
+ }
+ } else if (with_groups && jcp.ic_block == 8) {
+ wei_tag = gOIhw2i8o4i;
+ } else
+ wei_tag = gOIhw4o4i;
+
+ memory_desc_t want_wei_md = weights_md;
+ memory_desc_init_by_tag(want_wei_md, wei_tag);
+ if (jcp.signed_input) {
+ want_wei_md.extra.flags = 0
+ | memory_extra_flags::compensation_conv_s8s8
+ | memory_extra_flags::scale_adjust;
+ want_wei_md.extra.compensation_mask = (1 << 0)
+ + (with_groups && !jcp.is_depthwise ? (1 << 1) : 0);
+ want_wei_md.extra.scale_adjust =
+ mayiuse(avx512_core_vnni) ? 1.f : 0.5f;
+ }
+
+ if (weights_md.format_kind == format_kind::any) {
+ weights_md = want_wei_md;
+ return true;
+ }
+
+ return weights_md == want_wei_md;
+ };
+
+ if (!set_or_check_wei_format())
+ return status::unimplemented;
+
+ format_tag_t dat_tag = utils::pick(ndims - 3,
+ format_tag::nwc, format_tag::nhwc);
+
+ if (src_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(src_md, dat_tag));
+ jcp.src_tag = dat_tag;
+ } else {
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ }
+ if (jcp.src_tag != dat_tag)
+ return status::unimplemented;
+
+ if (dst_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(dst_md, dat_tag));
+ jcp.dst_tag = dat_tag;
+ } else {
+ jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag);
+ }
+ if (jcp.dst_tag != dat_tag)
+ return status::unimplemented;
+
+ if (jcp.with_bias) {
+ if (bias_d.format_kind() == format_kind::any)
+ CHECK(memory_desc_init_by_tag(bias_md, format_tag::x));
+ }
+
+ jcp.bia_dt = jcp.with_bias ? cd.bias_desc.data_type : data_type::undef;
+ jcp.dst_dt = cd.dst_desc.data_type;
+
+ jcp.typesize_in = types::data_type_size(src_d.data_type());
+ jcp.typesize_out = types::data_type_size(dst_d.data_type());
+ jcp.typesize_bia = jcp.with_bias
+ ? types::data_type_size(bias_d.data_type())
+ : 0;
+
+ jcp.nb_ch = div_up(jcp.ngroups, jcp.ch_block);
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+
+ // Try to use 4 channel-groups at a time to avoid false sharing (depthwise)
+ int nb_ch_blocking = 4;
+ for ( /* init above */ ; nb_ch_blocking > 1; nb_ch_blocking--)
+ if (jcp.nb_ch % nb_ch_blocking == 0)
+ break;
+ jcp.nb_ch_blocking = jcp.is_depthwise ? nb_ch_blocking : 1;
+
+ // If OC blocking is incommensurate with the number of OC blocks (general
+ // requirement for all convolutions), or if it results in an unrolling
+ // factor smaller than the left padding (special requirement for SSD:fc6),
+ // then search for a smaller OC blocking that satisfies both constraints.
+ auto is_oc_blocking_ok = [&](int block) {
+ int ur_w = nstl::min(jcp.ow, jcp.max_regs_ur / (block + 1));
+ return jcp.nb_oc % block == 0
+ && jcp.l_pad <= ur_w && jcp.ow % ur_w != 1;
+ };
+
+ // choose nb_oc work chunk size for distribution within threads
+ int max_threading_nb_oc_chunk = 4;
+ // Performance improvements for googlenet_v3 and resnet_50 with mb = 1;
+ // TODO: generalize this condition and rewrite it in appropriate manner
+ if (jcp.ver == ver_vnni && jcp.mb == 1 && jcp.kh == 3 && jcp.kw == 3
+ && jcp.stride_w == 1 && jcp.ic % 64 == 0)
+ max_threading_nb_oc_chunk = 2;
+ jcp.nb_oc_blocking_thr_chunk =
+ nstl::min(max_threading_nb_oc_chunk, jcp.nb_oc);
+ for (; jcp.nb_oc_blocking_thr_chunk > 1; jcp.nb_oc_blocking_thr_chunk--) {
+ if (is_oc_blocking_ok(jcp.nb_oc_blocking_thr_chunk))
+ break;
+ }
+
+ // choose oc blocking for computational kernel
+ jcp.nb_oc_blocking = jcp.nb_oc_blocking_thr_chunk;
+ // Performance improvements for googlenet_v3 with mb = 1;
+ // TODO: generalize this condition and rewrite it in appropriate manner
+ const int size_treshold_for_nb_oc_blocking_reduction = 17;
+ if (jcp.mb == 1 && jcp.ow <= size_treshold_for_nb_oc_blocking_reduction
+ && jcp.stride_w == 1
+ && !(jcp.kh == 1 && jcp.kw == 3)
+ && !(jcp.kh >= 7 && jcp.oc % 64 == 0)) {
+ const int max_nb_oc_blocking = 2;
+ jcp.nb_oc_blocking = nstl::min(max_nb_oc_blocking, jcp.nb_oc);
+ for (; jcp.nb_oc_blocking > 1; jcp.nb_oc_blocking--)
+ if (jcp.nb_oc_blocking_thr_chunk % jcp.nb_oc_blocking == 0
+ && is_oc_blocking_ok(jcp.nb_oc_blocking))
+ break;
+ }
+
+ if (jcp.is_resrc_depthwise)
+ jcp.ur_w = (jcp.max_regs_ur - jcp.kw + jcp.stride_w)
+ / (jcp.nb_ch_blocking + jcp.stride_w);
+ else
+ jcp.ur_w
+ = jcp.max_regs_ur / (jcp.is_depthwise ? jcp.nb_ch_blocking
+ : jcp.nb_oc_blocking + 1);
+ if (jcp.ow < jcp.ur_w)
+ jcp.ur_w = jcp.ow;
+ jcp.ur_w_tail = jcp.ow % jcp.ur_w;
+
+ jcp.ow_block = jcp.ow;
+ int base_work_amount = jcp.mb * jcp.nb_ch * jcp.oh
+ * (jcp.nb_oc / jcp.nb_oc_blocking_thr_chunk);
+ float best_thr_eff
+ = (float)base_work_amount / rnd_up(base_work_amount, nthreads);
+ int max_nb_ow = div_up(jcp.ow, 2 * jcp.ur_w);
+ for (int nb_ow = 1; nb_ow <= max_nb_ow; nb_ow++) {
+ int ow_block
+ = nstl::min(rnd_up(div_up(jcp.ow, nb_ow), jcp.ur_w), jcp.ow);
+ if (ow_block < jcp.nb_oc_blocking_thr_chunk * jcp.oc_block
+ && best_thr_eff > 0.8f)
+ break;
+ if (div_up(jcp.ow, ow_block) != nb_ow)
+ continue;
+ auto work_amount = base_work_amount * nb_ow;
+ float thr_eff = (float)work_amount / rnd_up(work_amount, nthreads);
+ if (ow_block >= 2 * jcp.ur_w && thr_eff > 1.1f * best_thr_eff) {
+ jcp.ow_block = ow_block;
+ best_thr_eff = thr_eff;
+ }
+ if (best_thr_eff > 0.9f)
+ break;
+ }
+ jcp.nb_ow = div_up(jcp.ow, jcp.ow_block);
+
+ bool args_ok = true
+ && jcp.oc % jcp.oc_block == 0
+ && jcp.l_pad <= jcp.ur_w
+ && IMPLICATION(!jcp.is_1stconv, jcp.ic % jcp.ic_block == 0);
+ if (!args_ok)
+ return status::unimplemented;
+
+ int r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1)
+ - (jcp.iw + jcp.l_pad - 1));
+ if (r_pad_no_tail > jcp.ur_w)
+ return status::unimplemented;
+
+ pick_loop_order(jcp, nthreads);
+
+ jcp.nb_ic_L2 = jcp.nb_ic;
+
+ const auto &oscales = attr.output_scales_;
+ jcp.is_oc_scale = oscales.mask_ == 1 << 1;
+
+ assert(IMPLICATION(!jcp.is_oc_scale, oscales.mask_ == 0));
+
+ jcp.wei_adj_scale =
+ (weights_d.extra().flags | memory_extra_flags::scale_adjust)
+ ? weights_d.extra().scale_adjust : 1.f;
+
+ return status::success;
+}
+
+void jit_avx512_core_x8s8s32x_fwd_kernel::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp,
+ const primitive_attr_t &attr) {
+ if (jcp.signed_input && jcp.ver != ver_vnni) {
+ dim_t count = nstl::max(attr.output_scales_.count_, (dim_t)jcp.ic_block);
+ scratchpad.book(key_conv_adjusted_scales, sizeof(float) * count);
+ }
+}
+
+template struct _jit_avx512_core_x8s8s32x_fwd_kernel<Zmm>;
+template struct _jit_avx512_core_x8s8s32x_fwd_kernel<Ymm>;
+template struct _jit_avx512_core_x8s8s32x_fwd_kernel<Xmm>;
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.hpp
new file mode 100644
index 0000000000..d8a05ad53e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_conv_kernel.hpp
@@ -0,0 +1,239 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_CORE_X8S8S32X_CONV_KERNEL_HPP
+#define CPU_JIT_AVX512_CORE_X8S8S32X_CONV_KERNEL_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+#include "jit_uni_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template<typename Vmm>
+struct _jit_avx512_core_x8s8s32x_fwd_kernel : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(_jit_avx512_core_x8s8s32x_conv_fwd_ker_t)
+
+ enum { STATE_FIRST_DST_LOAD = 0x1U };
+
+ _jit_avx512_core_x8s8s32x_fwd_kernel(jit_conv_conf_t ajcp,
+ const primitive_attr_t &attr) : jcp(ajcp), attr_(attr),
+ eltwise_injector_(nullptr)
+ {
+ if (jcp.with_eltwise)
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<avx512_common>(
+ this, jcp.eltwise);
+
+ generate();
+ jit_ker_ = (void (*)(jit_conv_call_s *))getCode();
+ }
+
+ ~_jit_avx512_core_x8s8s32x_fwd_kernel() {
+ delete eltwise_injector_;
+ }
+
+ jit_conv_conf_t jcp;
+ const primitive_attr_t &attr_;
+ void (*jit_ker_)(jit_conv_call_s *);
+
+private:
+ jit_uni_eltwise_injector_f32<avx512_common> *eltwise_injector_;
+
+ enum {
+ typesize = sizeof(float),
+ ker_reg_base_idx = 28,
+ ker_dw_reg_base_idx = 30,
+ };
+ typedef enum {
+ no_last_block,
+ last_ic_block,
+ last_sp_block,
+ } ic_block_t;
+
+ /* data regs */
+ const Xbyak::Reg64 reg_ptr_scales = rax;
+ const Xbyak::Reg64 reg_inp = r8;
+ const Xbyak::Reg64 reg_ker = r9;
+ const Xbyak::Reg64 reg_out = r10;
+ const Xbyak::Reg64 aux_reg_inp = r11;
+ const Xbyak::Reg64 reg_ptr_sum_scale = r11;
+ const Xbyak::Reg64 aux_reg_ker = r12;
+ const Xbyak::Reg64 reg_compensation = r14;
+ /* counter regs */
+ const Xbyak::Reg64 reg_bias_alpha = abi_not_param1;
+ const Xbyak::Reg64 reg_oi = rbx;
+ const Xbyak::Reg64 reg_bias = rdx;
+ const Xbyak::Reg64 reg_oc_blocks = rsi;
+ const Xbyak::Reg64 reg_owb = aux_reg_ker;
+ const Xbyak::Reg64 reg_scratch = reg_compensation;
+ const Xbyak::Reg64 reg_kj = reg_ptr_scales;
+ const Xbyak::Reg64 reg_overflow = reg_ptr_scales;
+ const Xbyak::Reg64 reg_icb = reg_bias;
+
+ const Xbyak::Opmask ktail_mask = Xbyak::Opmask(2);
+ const Xbyak::Opmask kblend_mask = Xbyak::Opmask(3);
+
+ const Vmm vmm_wei = Vmm(31);
+ /* used during bias section of store_output */
+ const Vmm vmm_comp = Vmm(30); // only for signed input
+ const Vmm vmm_bias = Vmm(31);
+ /* used during post_op sum section of store_output */
+ const Vmm vmm_prev_dst = Vmm(31);
+ /* used during write-out section of store_output */
+ const Vmm vmm_zero = Vmm(31);
+
+ /* used in compute_ker (but set during prepare_output) */
+ const Vmm vmm_shift = vmm_comp; // only for signed input
+ /* used in compute_ker (but only for pre-VNNI machines) */
+ const Vmm vmm_tmp = Vmm(28); // not used for depthwise
+ const Vmm vmm_one = Vmm(29); // set at start of kernel, not used for depthwise.
+
+ /* registers use only for depthwise
+ groups are always blocked by 16(padded if needed),
+ hence use only Zmm registers */
+ const Xbyak::Zmm zmm_wei = Xbyak::Zmm(31);
+ Xbyak::Zmm zmm_tmp;
+ Xbyak::Zmm zmm_src;
+ Xbyak::Zmm zmm_shifted_zero;
+ Xbyak::Zmm zmm_permute;
+
+ Vmm vmm_out(int i_ur, int i_oc) {
+ int idx = i_ur + i_oc * jcp.ur_w;
+ assert(idx < (jcp.is_depthwise
+ ? ker_dw_reg_base_idx : ker_reg_base_idx));
+ return Vmm(idx);
+ }
+ Xbyak::Zmm zmm_out(int i_ur, int i_oc) {
+ int idx = i_ur + i_oc * jcp.ur_w;
+ assert(idx < (jcp.is_depthwise
+ ? ker_dw_reg_base_idx : ker_reg_base_idx));
+ return Xbyak::Zmm(idx);
+ }
+ Vmm vmm_inp(int i_ic, int nb_x_blocking) {
+ int idx = i_ic + nb_x_blocking * jcp.ur_w;
+ assert(idx < 31);
+ return Vmm(idx);
+ }
+ Xbyak::Zmm zmm_inp(int i_ic, int nb_x_blocking) {
+ int idx = i_ic + nb_x_blocking * jcp.ur_w;
+ assert(idx < 31);
+ return Xbyak::Zmm(idx);
+ }
+ Vmm vmm_bias_alpha() {
+ int nb_c_block = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking;
+ return Vmm(nb_c_block * jcp.ur_w);
+ }
+ Xbyak::Xmm xmm_bias_alpha() {
+ int nb_c_block = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking;
+ return Xbyak::Xmm(nb_c_block * jcp.ur_w);
+ }
+ int get_ow_start(int ki, int pad_l) {
+ return nstl::max(0,
+ utils::div_up(pad_l - ki * (jcp.dilate_w + 1), jcp.stride_w));
+ }
+ int get_ow_end(int ur_w, int ki, int pad_r) {
+ return ur_w - nstl::max(0, utils::div_up(pad_r
+ - (jcp.kw - 1 - ki)
+ * (jcp.dilate_w + 1),
+ jcp.stride_w));
+ }
+
+ bool maybe_eltwise(int position);
+ void prepare_output(int ur_w);
+ void store_output(int ur_w, bool last_oc_block_flag);
+ void compute_ker_dw(
+ int ur_w, int pad_l, int pad_r, ic_block_t last_ic_block_flag, bool h_padded);
+ void compute_ker(int ur_w, int pad_l, int pad_r,
+ ic_block_t last_ic_block_flag, bool h_padded = false);
+ void compute_eltwise(int ur_w);
+ void kh_loop(int ur_w, int pad_l, int pad_r, ic_block_t last_ic_block_flag);
+ void icb_loop(
+ int ur_w, int pad_l, int pad_r, bool is_last_spatial_block);
+ void generate();
+ void cvt2ps(data_type_t type_in, Vmm ymm_in, const Xbyak::Operand &op,
+ bool mask_flag);
+ const Vmm vmm_mask(const Vmm vmm_in, bool mask_flag, bool store = false);
+};
+
+struct jit_avx512_core_x8s8s32x_fwd_kernel {
+
+ jit_avx512_core_x8s8s32x_fwd_kernel(jit_conv_conf_t ajcp,
+ const primitive_attr_t &attr) :
+ jit_ker(nullptr),
+ zmm_kernel_(nullptr),
+ ymm_kernel_(nullptr),
+ xmm_kernel_(nullptr) {
+ int ch_block = ajcp.is_depthwise ? ajcp.ch_block : ajcp.ic_block;
+ switch (ch_block) {
+ case 16:
+ zmm_kernel_ =
+ new _jit_avx512_core_x8s8s32x_fwd_kernel<Xbyak::Zmm>(
+ ajcp, attr);
+ jit_ker = zmm_kernel_->jit_ker_;
+ return;
+ case 8:
+ ymm_kernel_ =
+ new _jit_avx512_core_x8s8s32x_fwd_kernel<Xbyak::Ymm>(
+ ajcp, attr);
+ jit_ker = ymm_kernel_->jit_ker_;
+ return;
+ case 4:
+ xmm_kernel_ =
+ new _jit_avx512_core_x8s8s32x_fwd_kernel<Xbyak::Xmm>(
+ ajcp, attr);
+ jit_ker = xmm_kernel_->jit_ker_;
+ return;
+ default:
+ assert(!"invalid channel blocking");
+ }
+ }
+
+ ~jit_avx512_core_x8s8s32x_fwd_kernel() {
+ delete xmm_kernel_;
+ delete ymm_kernel_;
+ delete zmm_kernel_;
+ }
+
+ static bool post_ops_ok(jit_conv_conf_t &jcp,
+ const primitive_attr_t &attr);
+
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd,
+ memory_desc_t &src_pd,
+ memory_desc_t &weights_pd,
+ memory_desc_t &dst_pd,
+ memory_desc_t &bias_pd,
+ const primitive_attr_t &attr,
+ int nthreads);
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp, const primitive_attr_t &attr);
+
+ void (*jit_ker)(jit_conv_call_s *);
+ _jit_avx512_core_x8s8s32x_fwd_kernel<Xbyak::Zmm> *zmm_kernel_;
+ _jit_avx512_core_x8s8s32x_fwd_kernel<Xbyak::Ymm> *ymm_kernel_;
+ _jit_avx512_core_x8s8s32x_fwd_kernel<Xbyak::Xmm> *xmm_kernel_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.cpp
new file mode 100644
index 0000000000..cdbf333d5e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.cpp
@@ -0,0 +1,423 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_avx512_core_x8s8s32x_convolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+using namespace nstl;
+
+using jit_conv_ker_t = void (*)(jit_conv_call_s *);
+
+#define wht_blk_off(d, g, ...) \
+ (pd()->with_groups() \
+ ? (d).blk_off((g), __VA_ARGS__) \
+ : (d).blk_off(__VA_ARGS__))
+
+template <data_type_t src_type, data_type_t dst_type>
+void jit_avx512_core_x8s8s32x_convolution_fwd_t<src_type,
+ dst_type>::execute_forward_1d(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ const size_t bia_dt_size = pd()->with_bias()
+ ? types::data_type_size(pd()->desc()->bias_desc.data_type) : 0;
+
+ const auto &jcp = pd()->jcp_;
+ assert(jcp.nb_oc % jcp.nb_oc_blocking == 0);
+ assert(jcp.nb_ch % jcp.nb_ch_blocking == 0);
+
+ const float *oscales = pd()->attr()->output_scales_.scales_;
+ if (jcp.signed_input && jcp.ver != ver_vnni) {
+ auto local_scales = scratchpad(ctx).template get<float>(
+ key_conv_adjusted_scales);
+ size_t count = pd()->attr()->output_scales_.count_;
+ float factor = 1.f / pd()->jcp_.wei_adj_scale;
+ if (count == 1) {
+ utils::array_set(local_scales, oscales[0] * factor, 16);
+ } else {
+ for (size_t c = 0; c < count; c++)
+ local_scales[c] = oscales[c] * factor;
+ }
+ oscales = local_scales;
+ }
+
+ size_t offset = weights_d.size() - weights_d.additional_buffer_size();
+ auto w = const_cast<wei_data_t *>(weights);
+ int32_t* compensation = (jcp.signed_input)
+ ? reinterpret_cast<int32_t *>(&w[offset]) : 0;
+ int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking;
+ int nb_groups = jcp.nb_ch / jcp.nb_ch_blocking;
+ int group_block = jcp.ch_block;
+ int work_amount = jcp.mb * nb_groups * oc_chunks * jcp.nb_ow;
+
+ parallel(0, [&](const int ithr, const int nthr) {
+
+ int start{ 0 }, end{ 0 };
+ balance211(work_amount, nthr, ithr, start, end);
+
+ auto p = jit_conv_call_s();
+
+ int n{ 0 }, gg{ 0 }, occ{ 0 }, owb{ 0 };
+ switch (jcp.loop_order) {
+ case loop_cwgn:
+ nd_iterator_init(start, occ, oc_chunks, owb, jcp.nb_ow, gg,
+ nb_groups, n, jcp.mb);
+ break;
+ case loop_gncw:
+ nd_iterator_init(start, gg, nb_groups, n, jcp.mb, occ, oc_chunks,
+ owb, jcp.nb_ow);
+ break;
+ case loop_ngcw:
+ nd_iterator_init(start, n, jcp.mb, gg, nb_groups, occ, oc_chunks,
+ owb, jcp.nb_ow);
+ break;
+ case loop_nwcg:
+ nd_iterator_init(start, n, jcp.mb, owb, jcp.nb_ow, occ, oc_chunks,
+ gg, nb_groups);
+ break;
+ default: assert(!"unsupported loop order");
+ }
+ while (start < end) {
+ int ocb = occ * jcp.nb_oc_blocking;
+ int gb = gg * jcp.nb_ch_blocking;
+ int g = gb * group_block;
+ int g_oc = (g * jcp.nb_oc + ocb) * jcp.oc_block;
+ int g_ic = g * jcp.nb_ic * jcp.ic_block;
+ int ow_s = owb * jcp.ow_block;
+ int iw_s = ow_s * jcp.stride_w;
+
+ p.bias = bias ? bias + (bias_d.blk_off(g_oc) * bia_dt_size) : 0;
+ p.compensation = (jcp.signed_input) ? compensation + g_oc : 0;
+ p.dst = dst + dst_d.blk_off(n, g_oc, ow_s);
+ p.src = src + src_d.blk_off(n, g_ic, iw_s);
+ p.filt = weights + wht_blk_off(weights_d, gb, ocb, 0);
+ p.scales = &oscales[jcp.is_oc_scale * g_oc];
+ p.oc_blocks = jcp.is_depthwise ? gb : ocb;
+ p.kh_padding = jcp.kh;
+ p.t_overflow = 0;
+ p.b_overflow = 0;
+ p.owb = owb;
+
+ kernel_->jit_ker(&p);
+
+ ++start;
+ switch (jcp.loop_order) {
+ case loop_cwgn:
+ nd_iterator_step(occ, oc_chunks, owb, jcp.nb_ow, gg, nb_groups,
+ n, jcp.mb);
+ break;
+ case loop_gncw:
+ nd_iterator_step(gg, nb_groups, n, jcp.mb, occ, oc_chunks, owb,
+ jcp.nb_ow);
+ break;
+ case loop_ngcw:
+ nd_iterator_step(n, jcp.mb, gg, nb_groups, occ, oc_chunks, owb,
+ jcp.nb_ow);
+ break;
+ case loop_nwcg:
+ nd_iterator_step(n, jcp.mb, owb, jcp.nb_ow, occ, oc_chunks, gg,
+ nb_groups);
+ break;
+ default: assert(!"unsupported loop order");
+ }
+ }
+ });
+}
+
+template <data_type_t src_type, data_type_t dst_type>
+void jit_avx512_core_x8s8s32x_convolution_fwd_t<src_type,
+ dst_type>::execute_forward_2d(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ const size_t bia_dt_size = pd()->with_bias()
+ ? types::data_type_size(pd()->desc()->bias_desc.data_type) : 0;
+
+ const auto &jcp = pd()->jcp_;
+ assert(jcp.ch_block == 1);
+ assert(jcp.nb_ch_blocking == 1);
+ assert(jcp.nb_oc % jcp.nb_oc_blocking == 0);
+ assert(jcp.nb_ch % jcp.nb_ch_blocking == 0);
+
+ const float *oscales = pd()->attr()->output_scales_.scales_;
+ if (jcp.signed_input && jcp.ver != ver_vnni) {
+ auto local_scales = scratchpad(ctx).template get<float>(
+ key_conv_adjusted_scales);
+ size_t count = pd()->attr()->output_scales_.count_;
+ float factor = 1.f / pd()->jcp_.wei_adj_scale;
+ if (count == 1) {
+ utils::array_set(local_scales, oscales[0] * factor, 16);
+ } else {
+ for (size_t c = 0; c < count; c++)
+ local_scales[c] = oscales[c] * factor;
+ }
+ oscales = local_scales;
+ }
+
+ size_t offset = weights_d.size() - weights_d.additional_buffer_size();
+ auto w = const_cast<wei_data_t *>(weights);
+ int32_t* compensation = (jcp.signed_input)
+ ? reinterpret_cast<int32_t *>(&w[offset]) : 0;
+ int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking_thr_chunk;
+ int nb_groups = jcp.nb_ch;
+ int work_amount = jcp.mb * nb_groups * oc_chunks * jcp.oh * jcp.nb_ow;
+
+ parallel(0, [&](const int ithr, const int nthr) {
+
+ int start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ auto p = jit_conv_call_s();
+
+ size_t src_h_stride = src_d.blk_off(0, 0, 1);
+ size_t dst_h_stride = dst_d.blk_off(0, 0, 1);
+ size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 1);
+
+ int n{ 0 }, g{ 0 }, occ{ 0 }, oh_s{ 0 }, owb{ 0 };
+ switch (jcp.loop_order) {
+ case loop_cwgn:
+ nd_iterator_init(start, occ, oc_chunks, owb, jcp.nb_ow, g,
+ nb_groups, n, jcp.mb, oh_s, jcp.oh);
+ break;
+ case loop_ngcw:
+ nd_iterator_init(start, n, jcp.mb, g, nb_groups, occ, oc_chunks,
+ owb, jcp.nb_ow, oh_s, jcp.oh);
+ break;
+ case loop_nhwcg:
+ nd_iterator_init(start, n, jcp.mb, oh_s, jcp.oh, owb, jcp.nb_ow,
+ occ, oc_chunks, g, nb_groups);
+ break;
+ default: assert(!"unsupported loop order");
+ }
+ while (start < end) {
+ for (int occ1 = 0; occ1 < jcp.nb_oc_blocking_thr_chunk;
+ occ1 += jcp.nb_oc_blocking) {
+ int ocb = occ * jcp.nb_oc_blocking_thr_chunk + occ1;
+ int g_oc = (g * jcp.nb_oc + ocb) * jcp.oc_block;
+
+ int g_ic = g * jcp.nb_ic * jcp.ic_block;
+
+ int work_rem = end - start;
+ int ih_s = -jcp.t_pad + oh_s * jcp.stride_h;
+ int oh_e = oh_s + work_rem > jcp.oh ? jcp.oh : oh_s + work_rem;
+ if (jcp.loop_order == loop_nhwcg)
+ oh_e = oh_s + 1; // step instead
+ int ow_s = owb * jcp.ow_block;
+ int iw_s = ow_s * jcp.stride_w;
+
+ auto bias_w = bias
+ ? bias + (bias_d.blk_off(g_oc) * bia_dt_size)
+ : 0;
+ int32_t *compensation_w = (jcp.signed_input)
+ ? compensation + g_oc : 0;
+
+ auto dst_w = dst + dst_d.blk_off(n, g_oc, oh_s, ow_s);
+ auto src_w = src + src_d.blk_off(n, g_ic, ih_s, iw_s);
+ auto wht_w = weights + wht_blk_off(weights_d, g, ocb, 0);
+
+ auto scales = &oscales[jcp.is_oc_scale * g_oc];
+
+ for (int oj = oh_s, ij = ih_s; oj < oh_e;
+ ++oj, ij += jcp.stride_h) {
+ int dilate_h = jcp.dilate_h + 1;
+ int i_t_overflow = nstl::min(jcp.kh,
+ div_up(max(0, -ij), dilate_h));
+ int i_b_overflow = nstl::min(jcp.kh, div_up(
+ max(0, ij - jcp.ih + (jcp.kh - 1) * dilate_h + 1),
+ dilate_h));
+ int kh_padding = nstl::max(0,
+ jcp.kh - i_t_overflow - i_b_overflow);
+
+ size_t wei_stride = (!jcp.signed_input)
+ ? i_t_overflow * wht_h_stride : 0;
+ p.src = src_w + i_t_overflow * dilate_h * src_h_stride;
+ p.dst = dst_w;
+ p.filt = wht_w + wei_stride;
+ p.bias = bias_w;
+ p.compensation = compensation_w;
+ p.oc_blocks = ocb;
+ p.kh_padding = kh_padding;
+ p.scales = scales;
+ p.t_overflow = i_t_overflow;
+ p.b_overflow = i_b_overflow;
+ p.owb = owb;
+
+ kernel_->jit_ker(&p);
+ src_w += src_h_stride * jcp.stride_h;
+ dst_w += dst_h_stride;
+ }
+ }
+ switch (jcp.loop_order) {
+ case loop_cwgn:
+ nd_iterator_jump(start, end, occ, oc_chunks, owb, jcp.nb_ow, g,
+ nb_groups, n, jcp.mb, oh_s, jcp.oh);
+ break;
+ case loop_ngcw:
+ nd_iterator_jump(start, end, n, jcp.mb, g, nb_groups, occ,
+ oc_chunks, owb, jcp.nb_ow, oh_s, jcp.oh);
+ break;
+ case loop_nhwcg:
+ ++start;
+ nd_iterator_step(n, jcp.mb, oh_s, jcp.oh, owb, jcp.nb_ow, occ,
+ oc_chunks, g, nb_groups);
+ break;
+ default: assert(!"unsupported loop order");
+ }
+ }
+ });
+}
+
+template <data_type_t src_type, data_type_t dst_type>
+void jit_avx512_core_x8s8s32x_convolution_fwd_t<src_type,
+ dst_type>::execute_forward_2d_dw(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ const size_t bia_dt_size = pd()->with_bias()
+ ? types::data_type_size(pd()->desc()->bias_desc.data_type) : 0;
+
+ const auto &jcp = pd()->jcp_;
+ assert(jcp.ic_block == 1);
+ assert(jcp.oc_block == 1);
+ assert(jcp.nb_ic == 1);
+ assert(jcp.nb_oc == 1);
+ assert(jcp.nb_oc_blocking == 1);
+ assert(jcp.nb_ch % jcp.nb_ch_blocking == 0);
+
+ const float *oscales = pd()->attr()->output_scales_.scales_;
+ if (jcp.signed_input && jcp.ver != ver_vnni) {
+ auto local_scales = scratchpad(ctx).template get<float>(
+ key_conv_adjusted_scales);
+ size_t count = pd()->attr()->output_scales_.count_;
+ float factor = 1.f / pd()->jcp_.wei_adj_scale;
+ if (count == 1) {
+ utils::array_set(local_scales, oscales[0] * factor, 16);
+ } else {
+ for (size_t c = 0; c < count; c++)
+ local_scales[c] = oscales[c] * factor;
+ }
+ oscales = local_scales;
+ }
+
+ size_t offset = weights_d.size() - weights_d.additional_buffer_size();
+ auto w = const_cast<wei_data_t *>(weights);
+ int32_t* compensation = (jcp.signed_input)
+ ? reinterpret_cast<int32_t *>(&w[offset]) : 0;
+ int nb_groups = jcp.nb_ch / jcp.nb_ch_blocking;
+ int group_block = jcp.ch_block;
+
+ parallel_nd(jcp.mb, jcp.oh, jcp.nb_ow, nb_groups,
+ [&](int n, int oh_s, int owb, int gg) {
+
+ auto p = jit_conv_call_s();
+
+ size_t src_h_stride = src_d.blk_off(0, 0, 1);
+ size_t wht_h_stride = wht_blk_off(weights_d, 0, 0, 0, 1);
+
+ int gb = gg * jcp.nb_ch_blocking;
+ int g = gb * group_block;
+
+ int ih_s = -jcp.t_pad + oh_s * jcp.stride_h;
+ int ow_s = owb * jcp.ow_block;
+ int iw_s = ow_s * jcp.stride_w;
+
+ auto bias_w = bias ? bias + (bias_d.blk_off(g) * bia_dt_size) : 0;
+ int32_t *compensation_w = jcp.signed_input ? compensation + g : 0;
+
+ auto dst_w = dst + dst_d.blk_off(n, g, oh_s, ow_s);
+ auto src_w = src + src_d.blk_off(n, g, ih_s, iw_s);
+ auto wht_w = weights + wht_blk_off(weights_d, gb, 0);
+
+ auto scales = &oscales[jcp.is_oc_scale * g];
+
+ int dilate_h = jcp.dilate_h + 1;
+ int i_t_overflow = nstl::min(jcp.kh, div_up(max(0, -ih_s), dilate_h));
+ int i_b_overflow = nstl::min(jcp.kh,
+ div_up(max(0, ih_s - jcp.ih + (jcp.kh - 1) * dilate_h + 1),
+ dilate_h));
+ int kh_padding = nstl::max(0, jcp.kh - i_t_overflow - i_b_overflow);
+
+ size_t wei_stride = jcp.signed_input ? 0 : i_t_overflow * wht_h_stride;
+ p.src = src_w + i_t_overflow * dilate_h * src_h_stride;
+ p.dst = dst_w;
+ p.filt = wht_w + wei_stride;
+ p.bias = bias_w;
+ p.compensation = compensation_w;
+ p.oc_blocks = gb;
+ p.kh_padding = kh_padding;
+ p.scales = scales;
+ p.t_overflow = i_t_overflow;
+ p.b_overflow = i_b_overflow;
+ p.owb = owb;
+
+ kernel_->jit_ker(&p);
+ });
+}
+
+template struct jit_avx512_core_x8s8s32x_convolution_fwd_t<
+ data_type::s8, data_type::u8>;
+template struct jit_avx512_core_x8s8s32x_convolution_fwd_t<
+ data_type::u8, data_type::u8>;
+template struct jit_avx512_core_x8s8s32x_convolution_fwd_t<
+ data_type::s8, data_type::s8>;
+template struct jit_avx512_core_x8s8s32x_convolution_fwd_t<
+ data_type::u8, data_type::s8>;
+template struct jit_avx512_core_x8s8s32x_convolution_fwd_t<
+ data_type::s8, data_type::s32>;
+template struct jit_avx512_core_x8s8s32x_convolution_fwd_t<
+ data_type::u8, data_type::s32>;
+template struct jit_avx512_core_x8s8s32x_convolution_fwd_t<
+ data_type::s8, data_type::f32>;
+template struct jit_avx512_core_x8s8s32x_convolution_fwd_t<
+ data_type::u8, data_type::f32>;
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.hpp
new file mode 100644
index 0000000000..203ebdf942
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_convolution.hpp
@@ -0,0 +1,115 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_CORE_X8S8S32X_CONVOLUTION_HPP
+#define CPU_JIT_AVX512_CORE_X8S8S32X_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_avx512_core_x8s8s32x_conv_kernel.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t src_type, impl::data_type_t dst_type>
+struct jit_avx512_core_x8s8s32x_convolution_fwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_()
+ {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_int8:", avx512_core, ""),
+ jit_avx512_core_x8s8s32x_convolution_fwd_t<src_type, dst_type>);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(src_type, data_type::s8, data_type::undef,
+ dst_type, data_type::s32)
+ && IMPLICATION(with_bias(), utils::one_of(bias_md_.data_type,
+ data_type::f32, data_type::s32, data_type::s8,
+ data_type::u8))
+ && !has_zero_dim_memory();
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_avx512_core_x8s8s32x_fwd_kernel::init_conf(
+ jcp_, *desc(), src_md_, weights_md_, dst_md_, bias_md_,
+ *attr(), mkldnn_get_max_threads());
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx512_core_x8s8s32x_fwd_kernel::init_scratchpad(scratchpad,
+ jcp_, *attr());
+
+ return status;
+ }
+
+ jit_conv_conf_t jcp_;
+ };
+
+ jit_avx512_core_x8s8s32x_convolution_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ {
+ kernel_ = new jit_avx512_core_x8s8s32x_fwd_kernel(pd()->jcp_,
+ *pd()->attr());
+ }
+
+ ~jit_avx512_core_x8s8s32x_convolution_fwd_t() { delete kernel_; }
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<data_type::s8>::type wei_data_t;
+ typedef typename prec_traits<dst_type>::type dst_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override
+ {
+ const auto &_pd = pd();
+ if (_pd->ndims() == 3)
+ execute_forward_1d(ctx);
+ else if (_pd->jcp_.is_depthwise)
+ execute_forward_2d_dw(ctx);
+ else
+ execute_forward_2d(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward_1d(const exec_ctx_t &ctx) const;
+ void execute_forward_2d(const exec_ctx_t &ctx) const;
+ void execute_forward_2d_dw(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_avx512_core_x8s8s32x_fwd_kernel *kernel_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.cpp
new file mode 100644
index 0000000000..142af1f541
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.cpp
@@ -0,0 +1,1034 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_avx512_core_x8s8s32x_deconvolution.hpp"
+
+#define GET_OFF(field) offsetof(jit_deconv_call_s, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+using namespace Xbyak;
+
+using namespace nstl;
+
+#define wht_blk_off(d, g, ...) \
+ (pd()->with_groups() ? (d).blk_off((g), __VA_ARGS__) : \
+ (d).blk_off(__VA_ARGS__))
+
+status_t jit_avx512_core_x8s8s32x_deconv_fwd_kernel::init_conf(
+ jit_conv_conf_t &jcp, const deconvolution_desc_t &cd,
+ memory_desc_t &src_md, memory_desc_t &weights_md,
+ memory_desc_t &dst_md, const bool with_bias,
+ memory_desc_t &bias_md, const primitive_attr_t &attr) {
+ const memory_desc_wrapper src_d(&src_md);
+ const memory_desc_wrapper dst_d(&dst_md);
+ const memory_desc_wrapper weights_d(&weights_md);
+ const memory_desc_wrapper bias_d(&bias_md);
+
+ if (!(mayiuse(avx512_core)
+ && one_of(src_d.data_type(), data_type::u8, data_type::s8)
+ && weights_d.data_type() == data_type::s8
+ && one_of(dst_d.data_type(), data_type::f32, data_type::s32,
+ data_type::s8, data_type::u8)))
+ return status::unimplemented;
+
+ jcp = zero<decltype(jcp)>();
+
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ jcp.signed_input = src_d.data_type() == data_type::s8;
+ const int ndims = jcp.ndims = dst_d.ndims();
+ const bool is_1d = ndims == 3;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+ jcp.oc_without_padding = dst_d.dims()[1] / jcp.ngroups;
+ jcp.ic_without_padding = src_d.dims()[1] / jcp.ngroups;
+ jcp.is_depthwise = true && with_groups
+ && utils::everyone_is(1, jcp.ic_without_padding,
+ jcp.oc_without_padding);
+
+ /* TODO: future work, on hold until depthwise specialized kernel is
+ * implemented. */
+ if (jcp.is_depthwise && jcp.signed_input)
+ return status::unimplemented;
+
+ format_tag_t dat_tag = utils::pick(ndims - 3,
+ format_tag::nwc, format_tag::nhwc);
+
+ if (src_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(src_md, dat_tag));
+ jcp.src_tag = dat_tag;
+ } else {
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ }
+ if (jcp.src_tag != dat_tag)
+ return status::unimplemented;
+
+ if (dst_d.format_kind() == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(dst_md, dat_tag));
+ jcp.dst_tag = dat_tag;
+ } else {
+ jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag);
+ }
+ if (jcp.dst_tag != dat_tag)
+ return status::unimplemented;
+
+ auto set_or_check_wei_format = [&]() {
+ using namespace format_tag;
+
+ format_tag_t wei_tag = is_1d
+ ? (jcp.is_depthwise
+ ? Goiw16g : (with_groups ? gOIw4i16o4i : OIw4i16o4i))
+ : (jcp.is_depthwise
+ ? Goihw16g : (with_groups ? gOIhw4i16o4i : OIhw4i16o4i));
+
+ memory_desc_t want_wei_md = weights_md;
+ memory_desc_init_by_tag(want_wei_md, wei_tag);
+ if (jcp.signed_input && !jcp.is_depthwise) {
+ want_wei_md.extra.flags = 0
+ | memory_extra_flags::compensation_conv_s8s8
+ | memory_extra_flags::scale_adjust;
+ want_wei_md.extra.compensation_mask = (1 << 0)
+ + (with_groups && !jcp.is_depthwise ? (1 << 1) : 0);
+ want_wei_md.extra.scale_adjust =
+ mayiuse(avx512_core_vnni) ? 1.f : 0.5f;
+ }
+
+ if (weights_md.format_kind == format_kind::any) {
+ weights_md = want_wei_md;
+ return true;
+ }
+
+ return weights_md == want_wei_md;
+ };
+
+ if (!set_or_check_wei_format())
+ return status::unimplemented;
+
+ jcp.with_bias = with_bias;
+ if (jcp.with_bias) {
+ if (bias_d.format_kind() == format_kind::any)
+ CHECK(memory_desc_init_by_tag(bias_md, format_tag::x));
+ }
+
+ jcp.prop_kind = cd.prop_kind;
+ jcp.mb = src_d.dims()[0];
+ jcp.ih = is_1d ? 1 : src_d.dims()[ndims - 2];
+ jcp.iw = src_d.dims()[ndims - 1];
+ jcp.oh = is_1d ? 1 : dst_d.dims()[ndims - 2];
+ jcp.ow = dst_d.dims()[ndims - 1];
+ jcp.kh = is_1d ? 1 : weights_d.dims()[with_groups + ndims - 2];
+ jcp.kw = weights_d.dims()[with_groups + ndims - 1];
+ jcp.t_pad = is_1d ? 0 : cd.padding[0][ndims - 4];
+ jcp.l_pad = cd.padding[0][ndims - 3];
+ jcp.stride_h = is_1d ? 1 : cd.strides[ndims - 4];
+ jcp.stride_w = cd.strides[ndims - 3];
+
+ if (jcp.is_depthwise) {
+ jcp.ch_block = 16;
+ jcp.oc_block = 1;
+ jcp.ic_block = 1;
+ } else {
+ jcp.ch_block = 1;
+ jcp.oc_block = 16;
+ jcp.ic_block = 16;
+
+ if (jcp.ngroups == 1) {
+ jcp.oc = utils::rnd_up(jcp.oc_without_padding, jcp.oc_block);
+ jcp.ic = utils::rnd_up(jcp.ic_without_padding, jcp.ic_block);
+ }
+ if (jcp.ic % jcp.ic_block != 0)
+ return status::unimplemented;
+ }
+
+ jcp.dilate_h = is_1d ? 0 : cd.dilates[ndims - 4];
+ jcp.dilate_w = cd.dilates[ndims - 3];
+
+ if (!IMPLICATION(jcp.dilate_h, jcp.stride_h == 1)
+ || !IMPLICATION(jcp.dilate_w, jcp.stride_w == 1))
+ return status::unimplemented;
+
+ /* padding: bottom and right */
+ jcp.b_pad = (jcp.ih - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1)
+ - (jcp.oh + jcp.t_pad - 1);
+ jcp.r_pad = (jcp.iw - 1) * jcp.stride_w + (jcp.kw - 1) * (jcp.dilate_w + 1)
+ - (jcp.ow + jcp.l_pad - 1);
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ const int eltwise_ind = p.find(primitive_kind::eltwise);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise)
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+
+ jcp.ver = ver_avx512_core;
+ if (mayiuse(avx512_core_vnni))
+ jcp.ver = ver_vnni;
+ const auto &oscales = attr.output_scales_;
+ jcp.is_oc_scale = oscales.mask_ == 1 << 1;
+
+ assert(IMPLICATION(!jcp.is_oc_scale, oscales.mask_ == 0));
+
+ jcp.dst_dt = dst_d.data_type();
+ jcp.bia_dt = jcp.with_bias ? bias_d.data_type() : data_type::undef;
+ jcp.typesize_bia
+ = jcp.with_bias ? types::data_type_size(bias_d.data_type()) : 0;
+ jcp.typesize_in = types::data_type_size(src_d.data_type());
+ jcp.typesize_out = types::data_type_size(dst_d.data_type());
+
+ jcp.nb_ch = div_up(jcp.ngroups, jcp.ch_block);
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+
+ /* kernel blocking params */
+ const int regs = jcp.ver == ver_vnni ? 30 : 28;
+ jcp.nb_oc_blocking = nstl::min(4, jcp.nb_oc);
+ for (; jcp.nb_oc_blocking > 1; jcp.nb_oc_blocking--)
+ if (jcp.nb_oc % jcp.nb_oc_blocking == 0
+ && jcp.l_pad <= regs / (jcp.nb_oc_blocking + 1))
+ break;
+
+ jcp.ur_w = regs / (jcp.nb_oc_blocking + 1);
+ int l_overflow = max(
+ 0, ((jcp.kw - 1) * (jcp.dilate_w + 1) - jcp.l_pad) / jcp.stride_w);
+
+ if (jcp.ow < jcp.ur_w) {
+ jcp.ur_w = jcp.ow;
+ jcp.ur_w_tail = 0;
+ } else {
+ for (; jcp.ur_w >= 1; jcp.ur_w--) {
+ /* ur_w should be multiple of stride_w in order
+ to simplify logic for get_ow_start and get_ow_end */
+ bool is_multiple_of_stride = jcp.ur_w % jcp.stride_w == 0;
+
+ /* boundary conditions:
+ These conditions ensure all elements close to boundary
+ are computed in a single call of compute loop */
+ bool left_boundary_covered = jcp.ur_w >= l_overflow * jcp.stride_w;
+ jcp.ur_w_tail = jcp.ow % jcp.ur_w;
+ int r_overflow_no_tail
+ = max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1)
+ - max(0, jcp.r_pad) - jcp.ur_w_tail)
+ / jcp.stride_w);
+ bool right_boundary_covered
+ = jcp.ur_w >= r_overflow_no_tail * jcp.stride_w;
+
+ if (is_multiple_of_stride && left_boundary_covered
+ && right_boundary_covered)
+ break;
+ else if (jcp.ur_w == 1)
+ /* The boundary conditions above are also important
+ to maintain simplicity of calls to icb_loop,
+ if those conditions are not satisfied,
+ then special cases will need to be added
+ to use correct l_overflow/r_overflow values
+ when different iterations of compute loop
+ work on the locations close to boundary.
+ So to keep code simple, return unimplemented
+ for extreme case when a good ur_w cannot be found.
+ */
+ return status::unimplemented;
+ }
+ }
+
+ jcp.wei_adj_scale =
+ (weights_d.extra().flags | memory_extra_flags::scale_adjust)
+ ? weights_d.extra().scale_adjust : 1.f;
+
+ jcp.loop_order = jcp.ngroups > 1 ? loop_ngc : loop_cgn;
+ return status::success;
+}
+
+bool jit_avx512_core_x8s8s32x_deconv_fwd_kernel::maybe_eltwise(int position) {
+ using namespace primitive_kind;
+ const auto &p = attr_.post_ops_;
+
+ if (position == 0) {
+ /* eltwise before sum */
+ return p.contain(eltwise, 0);
+ } else if (position == 1) {
+ /* eltwise after sum */
+ return p.contain(sum, 0) && p.contain(eltwise, 1);
+ }
+ return false;
+}
+
+void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::compute_eltwise(int ur_w) {
+ int nb_oc_block
+ = jcp.is_depthwise ? jcp.nb_ch_blocking : jcp.nb_oc_blocking;
+ eltwise_injector_->compute_vector_range(0, nb_oc_block * ur_w);
+}
+
+bool jit_avx512_core_x8s8s32x_deconv_fwd_kernel::post_ops_ok(
+ jit_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ using namespace primitive_kind;
+ const auto &p = attr.post_ops_;
+
+ auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); };
+
+ switch (p.len_) {
+ case 0: return true;
+ case 1: return is_eltwise(0) || p.contain(sum, 0);
+ case 2:
+ return (p.contain(sum, 0) && is_eltwise(1))
+ || (p.contain(sum, 1) && is_eltwise(0));
+ default: return false;
+ }
+
+ return false;
+}
+
+void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp,
+ const primitive_attr_t &attr) {
+ if (jcp.signed_input && jcp.ver != ver_vnni) {
+ dim_t count = nstl::max<dim_t>(attr.output_scales_.count_, 16);
+ scratchpad.book(key_conv_adjusted_scales, sizeof(float) * count);
+ }
+}
+
+void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::compute_ker(int ur_w,
+ int l_overflow, int r_overflow, ker_block_t last_ic_block_flag,
+ bool h_padded) {
+
+ const int ch_block_all = jcp.ch_block * jcp.ic_block * jcp.oc_block;
+ const int ur_w_stride = jcp.signed_input ? 1 : jcp.stride_w;
+
+ auto src_offset = [=](int oj, int icb, int ki) {
+ return jcp.typesize_in
+ * (((oj + jcp.l_pad - ki * (jcp.dilate_w + 1)) / jcp.stride_w)
+ * jcp.ngroups * jcp.ic_without_padding
+ + icb * 4);
+ };
+
+ auto kernel_offset = [=](int ocb, int icb, int ki) {
+ return jcp.typesize_in
+ * (ocb * jcp.nb_ic * jcp.kh * jcp.kw * ch_block_all
+ + icb * jcp.oc_block * jcp.ic_block / 4
+ + ki * ch_block_all);
+ };
+
+ auto compute = [=](zmm_t vreg_acc, zmm_t vreg_wei, zmm_t vreg_src) {
+ if (jcp.ver == ver_vnni) {
+ vpdpbusd(vreg_acc, vreg_src, vreg_wei);
+ } else if (jcp.is_depthwise) {
+ vpmulld(zmm_tmp, vreg_src, vreg_wei);
+ vpaddd(vreg_acc, vreg_acc, zmm_tmp);
+ } else {
+ vpmaddubsw(zmm_tmp, vreg_src, vreg_wei);
+ vpmaddwd(zmm_tmp, zmm_tmp, zmm_one);
+ vpaddd(vreg_acc, vreg_acc, zmm_tmp);
+ }
+ };
+
+ for (int ki = 0; ki < jcp.kw; ki++) {
+
+ int jj_start = get_ow_start(ki, l_overflow);
+ int jj_end = get_ow_end(ur_w, ki, r_overflow);
+
+ int _start = (jcp.signed_input) ? 0 : jj_start;
+ int _end = (jcp.signed_input) ? ur_w : jj_end;
+
+ int tail_size = jcp.ic_without_padding % 4;
+ int n_ic_blocks = jcp.is_depthwise ?
+ 1 :
+ (last_ic_block_flag & ~no_last_block ?
+ div_up(jcp.ic_without_padding % jcp.ic_block,
+ 4) :
+ jcp.ic_block / 4);
+
+ for (int icb1 = 0; icb1 < n_ic_blocks; icb1++) {
+ if (h_padded == true) {
+ /* fill padded area with shifted values */
+ Zmm inp = zmm_inp(0, jcp.nb_oc_blocking);
+ vpxord(inp, inp, inp);
+ vpsubb(inp, inp, zmm_shift);
+ } else {
+
+ for (int jj = _start; jj < _end; jj += ur_w_stride) {
+
+ int aux_src_off = src_offset(jj, icb1, ki);
+
+ if (jj >= jj_start && jj < jj_end
+ && ((jj + jcp.l_pad - ki) % jcp.stride_w == 0)) {
+ if (jcp.is_depthwise) {
+ vpmovzxbd(zmm_inp(jj, jcp.nb_oc_blocking),
+ EVEX_compress_addr(
+ aux_reg_src, aux_src_off));
+ } else if ((last_ic_block_flag & last_sp_block)
+ && tail_size != 0 && icb1 == n_ic_blocks - 1) {
+ xmm_t xmm_tmp = xmm_t(
+ zmm_inp(jj, jcp.nb_oc_blocking).getIdx());
+ for (int r = 0; r < tail_size; ++r)
+ vpinsrb(xmm_tmp, xmm_tmp,
+ ptr[aux_reg_src + aux_src_off + r], r);
+ vpbroadcastd(
+ zmm_inp(jj, jcp.nb_oc_blocking), xmm_tmp);
+ } else {
+ vpbroadcastd(zmm_inp(jj, jcp.nb_oc_blocking),
+ EVEX_compress_addr(
+ aux_reg_src, aux_src_off));
+ }
+ if (jcp.signed_input)
+ vpsubb(zmm_inp(jj, jcp.nb_oc_blocking),
+ zmm_inp(jj, jcp.nb_oc_blocking), zmm_shift);
+ } else {
+ /* fill padded area with shifted values */
+ if (jcp.signed_input) {
+ Zmm inp = zmm_inp(jj, jcp.nb_oc_blocking);
+ vpxord(inp, inp, inp);
+ vpsubb(inp, inp, zmm_shift);
+ }
+ }
+ }
+ }
+ for (int ocb = 0; ocb < jcp.nb_oc_blocking; ocb++) {
+ int aux_filt_off = kernel_offset(ocb, icb1, ki);
+
+ if (_end - _start > 0) {
+ if (jcp.is_depthwise)
+ vpmovsxbd(zmm_wei,
+ EVEX_compress_addr(aux_reg_filt, aux_filt_off));
+ else
+ vmovups(zmm_wei,
+ EVEX_compress_addr(aux_reg_filt, aux_filt_off));
+ }
+ for (int jj = _start; jj < _end; jj += ur_w_stride) {
+ Zmm inp = (h_padded == true) ?
+ zmm_inp(0, jcp.nb_oc_blocking) :
+ zmm_inp(jj, jcp.nb_oc_blocking);
+ compute(zmm_out(jj, ocb), zmm_wei, inp);
+ }
+ }
+ }
+ }
+}
+
+void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::kh_loop(int ur_w,
+ int l_overflow, int r_overflow, ker_block_t last_ic_block_flag) {
+
+ int ch_block_all = jcp.ch_block * jcp.ic_block * jcp.oc_block;
+ int shift_src_ih = jcp.typesize_in * (jcp.dilate_h + 1) * jcp.iw
+ * jcp.ngroups * jcp.ic_without_padding;
+ const int stride_h = jcp.signed_input ? 1 : jcp.stride_h;
+ int shift_filt_kh = jcp.typesize_in * jcp.kw * ch_block_all * stride_h;
+
+ Label kh_loop_label, skip_kh_loop;
+ Label t_overflow_label, no_t_overflow_label, b_overflow_label,
+ no_b_overflow_label;
+
+ mov(aux_reg_src, reg_src);
+ mov(aux_reg_filt, reg_filt);
+
+ if (jcp.signed_input && jcp.ndims > 3) {
+ /* Weights are transposed, so first compute 'bottom' padding. */
+ mov(reg_overflow, ptr[param1 + GET_OFF(b_overflow)]);
+ cmp(reg_overflow, 0);
+ je(no_b_overflow_label, T_NEAR);
+ L(b_overflow_label); {
+ compute_ker(ur_w, 0, 0, last_ic_block_flag, true);
+
+ add(aux_reg_filt, shift_filt_kh);
+ dec(reg_overflow);
+ cmp(reg_overflow, 0);
+ jg(b_overflow_label, T_NEAR);
+ }
+ L(no_b_overflow_label);
+ }
+
+ mov(reg_kh, ptr[param1 + GET_OFF(kh_padding)]);
+
+ if (jcp.signed_input || ((!jcp.signed_input)
+ && ((min(jcp.t_pad, jcp.b_pad) < 0)
+ || ((jcp.kh - 1) * (jcp.dilate_h + 1)
+ < nstl::max(jcp.t_pad, jcp.b_pad))))) {
+ cmp(reg_kh, 0);
+ je(skip_kh_loop, T_NEAR);
+ }
+
+ L(kh_loop_label); {
+ compute_ker(ur_w, l_overflow, r_overflow, last_ic_block_flag, false);
+ sub(aux_reg_src, shift_src_ih);
+ add(aux_reg_filt, shift_filt_kh);
+ dec(reg_kh);
+
+ /* Insert weight compensation in stride 'holes' */
+ if (jcp.signed_input && jcp.stride_h > 1) {
+ Label kh_comp_loop;
+
+ cmp(reg_kh, 0);
+ je(skip_kh_loop, T_NEAR);
+ mov(reg_comp_strides, jcp.stride_h - 1);
+ L(kh_comp_loop);
+ {
+ compute_ker(
+ ur_w, 0, 0, last_ic_block_flag, true);
+ add(aux_reg_filt, shift_filt_kh);
+ dec(reg_comp_strides);
+ cmp(reg_comp_strides, 0);
+ jg(kh_comp_loop, T_NEAR);
+ }
+ }
+ cmp(reg_kh, 0);
+ jg(kh_loop_label, T_NEAR);
+ }
+ L(skip_kh_loop);
+ if (jcp.signed_input && jcp.ndims > 3) {
+ mov(reg_overflow, ptr[param1 + GET_OFF(t_overflow)]);
+ cmp(reg_overflow, 0);
+ je(no_t_overflow_label, T_NEAR);
+ L(t_overflow_label); {
+ compute_ker(ur_w, 0, 0, last_ic_block_flag, true);
+
+ add(aux_reg_filt, shift_filt_kh);
+ dec(reg_overflow);
+ cmp(reg_overflow, 0);
+ jg(t_overflow_label, T_NEAR);
+ }
+ L(no_t_overflow_label);
+ }
+}
+
+void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::prepare_output(int ur_w) {
+ for (int ocb = 0; ocb < jcp.nb_oc_blocking; ocb++) {
+ for (int ur = 0; ur < ur_w; ur++) {
+ zmm_t zmm = zmm_out(ur, ocb);
+ vpxord(zmm, zmm, zmm);
+ }
+ }
+ if (jcp.signed_input) {
+ xor_(reg_scratch, reg_scratch);
+ Reg8 _t8 = reg_scratch.cvt8();
+ mov(_t8, (int8_t)-128);
+ vpbroadcastb(zmm_shift, _t8);
+ }
+}
+
+void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::cvt2ps(
+ data_type_t type_in, zmm_t zmm_in, const Operand &op, bool mask_flag) {
+ zmm_t zmm = mask_flag ? zmm_in | ktail_mask | T_z : zmm_in;
+ switch (type_in) {
+ case data_type::f32:
+ case data_type::s32: vmovups(zmm, op); break;
+ case data_type::s8: vpmovsxbd(zmm, op); break;
+ case data_type::u8: vpmovzxbd(zmm, op); break;
+ default: assert(!"unsupported data type");
+ }
+ if (type_in != data_type::f32)
+ vcvtdq2ps(zmm_in, zmm_in);
+}
+
+void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::store_output(
+ int ur_w, bool last_oc_block) {
+ mov(reg_bias, ptr[param1 + GET_OFF(bias)]);
+ mov(reg_ptr_scales, ptr[param1 + GET_OFF(scales)]);
+
+ if (jcp.signed_input)
+ mov(reg_compensation, ptr[param1 + GET_OFF(compensation)]);
+
+ const auto &p = attr_.post_ops_;
+ const int sum_idx = p.find(primitive_kind::sum);
+ const float *p_sum_scale
+ = (sum_idx != -1) ? &p.entry_[sum_idx].sum.scale : nullptr;
+ if (p_sum_scale && *p_sum_scale != 1.f)
+ mov(reg_ptr_sum_scale, (size_t)p_sum_scale);
+
+ if (jcp.with_bias && jcp.signed_input && jcp.ver != ver_vnni) {
+ mov(reg_bias_alpha, float2int(jcp.wei_adj_scale));
+ vmovq(xmm_bias_alpha(), reg_bias_alpha);
+ vbroadcastss(zmm_bias_alpha(), xmm_bias_alpha());
+ }
+
+ for (int ocb = 0; ocb < jcp.nb_oc_blocking; ocb++) {
+ const bool mask_flag = last_oc_block && ocb == jcp.nb_oc_blocking - 1;
+ int scale_offset
+ = jcp.is_oc_scale * (sizeof(float) * ocb * jcp.oc_block);
+
+ auto zmm_bias = zmm_tmp;
+ if (jcp.with_bias) {
+ int bias_offset = jcp.typesize_bia * ocb * jcp.oc_block;
+ auto bias_addr = EVEX_compress_addr(reg_bias, bias_offset);
+ cvt2ps(jcp.bia_dt, zmm_bias, bias_addr, mask_flag);
+ if (jcp.signed_input && jcp.ver != ver_vnni)
+ vmulps(zmm_bias, zmm_bias, zmm_bias_alpha());
+ }
+ if (jcp.signed_input) {
+ int comp_offset = sizeof(int32_t) * ocb * jcp.oc_block;
+ auto comp_addr = EVEX_compress_addr(reg_compensation, comp_offset);
+ cvt2ps(data_type::s32, zmm_comp, comp_addr, mask_flag);
+ }
+
+ for (int ur = 0; ur < ur_w; ur++) {
+ zmm_t zmm = zmm_out(ur, ocb);
+ vcvtdq2ps(zmm, zmm);
+ if (jcp.signed_input)
+ vaddps(zmm, zmm, zmm_comp);
+ if (jcp.with_bias)
+ vaddps(zmm, zmm, zmm_bias);
+ zmm_t mask_zmm = mask_flag ? zmm | ktail_mask | T_z : zmm;
+ vmulps(mask_zmm, zmm,
+ EVEX_compress_addr(reg_ptr_scales, scale_offset));
+ }
+ }
+ if (maybe_eltwise(0))
+ compute_eltwise(ur_w);
+ if (p_sum_scale) { // post_op: sum
+ for (int k = 0; k < jcp.nb_oc_blocking; k++) {
+ const bool mask_flag
+ = last_oc_block == 1 && k == jcp.nb_oc_blocking - 1;
+ for (int j = 0; j < ur_w; j++) {
+ int aux_output_offset
+ = jcp.typesize_out
+ * (k * jcp.oc_block
+ + j * jcp.oc_without_padding * jcp.ngroups);
+ auto addr = EVEX_compress_addr(reg_dst, aux_output_offset);
+ Zmm zmm = zmm_out(j, k);
+ cvt2ps(jcp.dst_dt, zmm_prev_dst, addr, mask_flag);
+ if (*p_sum_scale == 1.f)
+ vaddps(zmm, zmm_prev_dst);
+ else
+ vfmadd231ps(zmm, zmm_prev_dst, zword_b[reg_ptr_sum_scale]);
+ }
+ }
+ }
+ if (maybe_eltwise(1))
+ compute_eltwise(ur_w);
+
+ for (int ocb = 0; ocb < jcp.nb_oc_blocking; ocb++) {
+ const bool mask_flag = last_oc_block && ocb == jcp.nb_oc_blocking - 1;
+ for (int ur = 0; ur < ur_w; ur++) {
+ zmm_t zmm = zmm_out(ur, ocb);
+ if (jcp.dst_dt == data_type::u8) {
+ vpxord(zmm_zero, zmm_zero, zmm_zero);
+ vmaxps(zmm, zmm_zero, zmm);
+ }
+ if (jcp.dst_dt != data_type::f32)
+ vcvtps2dq(zmm, zmm);
+ }
+ for (int ur = 0; ur < ur_w; ur++) {
+ int aux_dst_off = jcp.typesize_out
+ * (ur * jcp.ngroups * jcp.oc_without_padding
+ + ocb * jcp.oc_block);
+ auto addr = EVEX_compress_addr(reg_dst, aux_dst_off);
+
+ zmm_t zmm = zmm_out(ur, ocb);
+ zmm_t r_zmm = mask_flag ? zmm | ktail_mask : zmm;
+ switch (jcp.dst_dt) {
+ case data_type::f32:
+ case data_type::s32: vmovups(addr, r_zmm); break;
+ case data_type::s8: vpmovsdb(addr, r_zmm); break;
+ case data_type::u8: vpmovusdb(addr, r_zmm); break;
+ default: assert(!"unknown dst_dt");
+ }
+ }
+ }
+}
+
+void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::icb_loop(
+ int ur_w, int l_overflow, int r_overflow, bool is_last_sp_block) {
+
+ int shift_src_icb = jcp.typesize_in * jcp.ic_block;
+ int shift_filt_icb
+ = jcp.typesize_in * jcp.kh * jcp.kw * jcp.ic_block * jcp.oc_block;
+
+ prepare_output(ur_w);
+
+ Label skip_icb_loop, icb_loop_label;
+
+ mov(reg_icb, jcp.nb_ic);
+ L(icb_loop_label); {
+
+ if (jcp.ic_without_padding != jcp.ic) {
+ Label common_ker, end_ker;
+ cmp(reg_icb, 1);
+ jg(common_ker, T_NEAR);
+
+ kh_loop(ur_w, l_overflow, r_overflow,
+ is_last_sp_block ? last_sp_block : last_ic_block);
+ jmp(end_ker, T_NEAR);
+
+ L(common_ker);
+ kh_loop(ur_w, l_overflow, r_overflow, no_last_block);
+
+ L(end_ker);
+ } else {
+ kh_loop(ur_w, l_overflow, r_overflow, no_last_block);
+ }
+
+ add(reg_src, shift_src_icb);
+ add(reg_filt, shift_filt_icb);
+ dec(reg_icb);
+ cmp(reg_icb, 0);
+ jg(icb_loop_label, T_NEAR);
+ }
+
+ /* come-back pointers */
+ sub(reg_src, jcp.nb_ic * shift_src_icb);
+ sub(reg_filt, jcp.nb_ic * shift_filt_icb);
+ L(skip_icb_loop);
+
+ if (jcp.ngroups % jcp.ch_block != 0 || jcp.oc_without_padding != jcp.oc) {
+ Label common_store, end_store;
+ mov(reg_oc_blocks, ptr[param1 + GET_OFF(oc_blocks)]);
+ if (jcp.is_depthwise)
+ cmp(reg_oc_blocks, jcp.nb_ch - 1);
+ else
+ cmp(reg_oc_blocks, jcp.nb_oc - jcp.nb_oc_blocking);
+ jne(common_store, T_NEAR);
+
+ store_output(ur_w, true);
+ jmp(end_store, T_NEAR);
+
+ L(common_store);
+ store_output(ur_w, false);
+
+ L(end_store);
+
+ } else {
+ store_output(ur_w, false);
+ }
+}
+
+void jit_avx512_core_x8s8s32x_deconv_fwd_kernel::generate() {
+ preamble();
+
+ xor_(reg_scratch, reg_scratch);
+ Reg16 _t = reg_scratch.cvt16();
+ mov(_t, 0x1);
+ vpbroadcastw(zmm_one, _t);
+
+ if (jcp.ngroups % jcp.ch_block != 0 || jcp.oc_without_padding != jcp.oc) {
+ int tail_size = jcp.is_depthwise ?
+ jcp.ngroups % jcp.ch_block :
+ jcp.oc_without_padding % jcp.oc_block;
+ int mask = (1 << tail_size) - 1;
+ Reg32 regw_tmp = reg_nur_w.cvt32();
+ mov(regw_tmp, mask);
+ kmovw(ktail_mask, regw_tmp);
+ }
+
+ mov(reg_src, ptr[param1 + GET_OFF(src)]);
+ mov(reg_filt, ptr[param1 + GET_OFF(filt)]);
+ mov(reg_dst, ptr[param1 + GET_OFF(dst)]);
+
+ int dst_shift = jcp.typesize_out * jcp.ur_w * jcp.ngroups
+ * jcp.oc_without_padding;
+ int src_shift = jcp.typesize_in * (jcp.ur_w / jcp.stride_w) * jcp.ngroups
+ * jcp.ic_without_padding;
+
+ int l_overflow = max(
+ 0, ((jcp.kw - 1) * (jcp.dilate_w + 1) - jcp.l_pad) / jcp.stride_w);
+ int r_overflow
+ = max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1) - max(0, jcp.r_pad))
+ / jcp.stride_w);
+
+ int r_overflow1
+ = nstl::max(0, ((jcp.kw - 1) * (jcp.dilate_w + 1)
+ - nstl::max(0, jcp.r_pad) - jcp.ur_w_tail)
+ / jcp.stride_w);
+ int nur_w = jcp.ow / jcp.ur_w;
+ if (r_overflow1 > 0)
+ nur_w--;
+
+ if (jcp.ur_w == jcp.ow) {
+ icb_loop(jcp.ur_w, l_overflow, r_overflow, true);
+ } else if (nur_w == 0) {
+ icb_loop(jcp.ur_w, l_overflow, r_overflow1, jcp.ur_w_tail == 0);
+ add(reg_src, src_shift);
+ add(reg_dst, dst_shift);
+ if (jcp.ur_w_tail != 0)
+ icb_loop(jcp.ur_w_tail, 0, r_overflow, true);
+ } else {
+ xor_(reg_nur_w, reg_nur_w);
+ if (l_overflow > 0) {
+ icb_loop(jcp.ur_w, l_overflow, 0, false);
+ add(reg_src, src_shift);
+ add(reg_dst, dst_shift);
+ inc(reg_nur_w);
+ }
+ if ((l_overflow <= 0 && nur_w > 0) || (l_overflow > 0 && nur_w > 1)) {
+ Label ow_loop_label;
+ L(ow_loop_label);
+ {
+ icb_loop(jcp.ur_w, 0, 0, false);
+ add(reg_src, src_shift);
+ add(reg_dst, dst_shift);
+ inc(reg_nur_w);
+ cmp(reg_nur_w, nur_w);
+ jl(ow_loop_label, T_NEAR);
+ }
+ }
+ if (r_overflow1 > 0) {
+ icb_loop(jcp.ur_w, 0, r_overflow1, jcp.ur_w_tail == 0);
+ add(reg_src, src_shift);
+ add(reg_dst, dst_shift);
+ }
+ if (jcp.ur_w_tail != 0) {
+ icb_loop(jcp.ur_w_tail, 0, r_overflow, true);
+ }
+ }
+ postamble();
+
+ if (jcp.with_eltwise)
+ eltwise_injector_->prepare_table();
+}
+
+template <data_type_t src_type, data_type_t dst_type>
+void _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<src_type,
+ dst_type>::execute_forward_1d(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ auto &jcp = kernel_->jcp;
+
+ int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking;
+ int nb_groups = jcp.nb_ch;
+
+ const float *oscales = pd()->attr()->output_scales_.scales_;
+ if (jcp.signed_input && jcp.ver != ver_vnni) {
+ auto local_scales
+ = scratchpad(ctx).template get<float>(key_conv_adjusted_scales);
+ size_t count = pd()->attr()->output_scales_.count_;
+ float factor = 1.f / pd()->jcp_.wei_adj_scale;
+ if (count == 1) {
+ utils::array_set(local_scales, oscales[0] * factor, 16);
+ } else {
+ for (size_t c = 0; c < count; c++)
+ local_scales[c] = oscales[c] * factor;
+ }
+ oscales = local_scales;
+ }
+ size_t offset = (size_t)jcp.ngroups * jcp.oc * jcp.ic * jcp.kh * jcp.kw;
+ auto w = const_cast<wei_data_t *>(weights);
+ int32_t *compensation
+ = (jcp.signed_input) ? reinterpret_cast<int32_t *>(&w[offset]) : 0;
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ int start{ 0 }, end{ 0 };
+ int work_amount = jcp.mb * nb_groups * oc_chunks;
+ balance211(work_amount, nthr, ithr, start, end);
+
+ auto p = jit_deconv_call_s();
+
+ int n{ 0 }, g{ 0 }, occ{ 0 };
+ if (jcp.loop_order == loop_ngc)
+ nd_iterator_init(start, n, jcp.mb, g, nb_groups, occ, oc_chunks);
+ else if (jcp.loop_order == loop_cgn)
+ nd_iterator_init(start, occ, oc_chunks, g, nb_groups, n, jcp.mb);
+ else
+ assert(!"unsupported loop order");
+ while (start < end) {
+
+ int ocb = occ * jcp.nb_oc_blocking;
+ int g_oc = (g * jcp.ch_block * jcp.nb_oc + ocb) * jcp.oc_block;
+ int g_ic = g * jcp.ch_block * jcp.ic;
+
+ p.dst = dst + dst_d.blk_off(n, g_oc);
+ p.src = src + src_d.blk_off(n, g_ic);
+ p.filt = weights + wht_blk_off(weights_d, g, ocb, 0);
+ p.bias = jcp.with_bias ?
+ bias + (bias_d.blk_off(g_oc) * jcp.typesize_bia) :
+ 0;
+ p.compensation = (jcp.signed_input) ? compensation + g_oc : 0;
+ p.scales = &oscales[jcp.is_oc_scale * g_oc];
+ p.t_overflow = 0;
+ p.b_overflow = 0;
+ p.kh_padding = jcp.kh;
+ p.oc_blocks = jcp.is_depthwise ? g : ocb;
+
+ kernel_->jit_ker(&p);
+
+ ++start;
+ if (jcp.loop_order == loop_ngc)
+ nd_iterator_step(n, jcp.mb, g, nb_groups, occ, oc_chunks);
+ else if (jcp.loop_order == loop_cgn)
+ nd_iterator_step(occ, oc_chunks, g, nb_groups, n, jcp.mb);
+ else
+ assert(!"unsupported loop order");
+ }
+ });
+}
+
+template <data_type_t src_type, data_type_t dst_type>
+void _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<src_type,
+ dst_type>::execute_forward_2d(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ auto &jcp = kernel_->jcp;
+
+ int oc_chunks = jcp.nb_oc / jcp.nb_oc_blocking;
+ int nb_groups = jcp.nb_ch;
+
+ size_t src_h_stride = src_d.blk_off(0, 0, 1);
+ size_t dst_h_stride = dst_d.blk_off(0, 0, 1);
+ size_t wht_kh_stride = wht_blk_off(weights_d, 0, 0, 0, 1);
+
+ const float *oscales = pd()->attr()->output_scales_.scales_;
+ if (jcp.signed_input && jcp.ver != ver_vnni) {
+ auto local_scales
+ = scratchpad(ctx).template get<float>(key_conv_adjusted_scales);
+ size_t count = pd()->attr()->output_scales_.count_;
+ float factor = 1.f / pd()->jcp_.wei_adj_scale;
+ if (count == 1) {
+ utils::array_set(local_scales, oscales[0] * factor, 16);
+ } else {
+ for (size_t c = 0; c < count; c++)
+ local_scales[c] = oscales[c] * factor;
+ }
+ oscales = local_scales;
+ }
+ size_t offset = (size_t)jcp.ngroups * jcp.oc * jcp.ic * jcp.kh * jcp.kw;
+ auto w = const_cast<wei_data_t *>(weights);
+ int32_t *compensation
+ = (jcp.signed_input) ? reinterpret_cast<int32_t *>(&w[offset]) : 0;
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ int start{ 0 }, end{ 0 };
+ int work_amount = jcp.mb * nb_groups * oc_chunks * jcp.oh;
+ balance211(work_amount, nthr, ithr, start, end);
+
+ auto p = jit_deconv_call_s();
+
+ /*loop order = cgn*/
+ int n{ 0 }, g{ 0 }, occ{ 0 }, oh_s{ 0 };
+ if (jcp.loop_order == loop_ngc)
+ nd_iterator_init(start, n, jcp.mb, g, nb_groups, occ, oc_chunks,
+ oh_s, jcp.oh);
+ else if (jcp.loop_order == loop_cgn)
+ nd_iterator_init(start, occ, oc_chunks, g, nb_groups, n, jcp.mb,
+ oh_s, jcp.oh);
+ else
+ assert(!"unsupported loop order");
+ while (start < end) {
+
+ int ocb = occ * jcp.nb_oc_blocking;
+ int g_oc = (g * jcp.ch_block * jcp.nb_oc + ocb) * jcp.oc_block;
+ int g_ic = g * jcp.ch_block * jcp.ic;
+ int work_rem = end - start;
+ int oh_e = oh_s + work_rem > jcp.oh ? jcp.oh : oh_s + work_rem;
+
+ auto dst_w = dst + dst_d.blk_off(n, g_oc);
+ auto src_w = src + src_d.blk_off(n, g_ic);
+ auto wht_w = weights + wht_blk_off(weights_d, g, ocb, 0);
+ auto bias_w = jcp.with_bias ?
+ bias + (bias_d.blk_off(g_oc) * jcp.typesize_bia) :
+ 0;
+ int32_t *compensation_w
+ = (jcp.signed_input) ? compensation + g_oc : 0;
+
+ auto scales = &oscales[jcp.is_oc_scale * g_oc];
+ for (int oj = oh_s; oj < oh_e; oj++) {
+ int ih_max = 0, kh_lo = 0, kh_len = 0;
+ if (jcp.dilate_h != 0 && jcp.stride_h == 1) {
+ /* dilation */
+ int dilate_h = jcp.dilate_h + 1;
+ // Note: use div_up to account for "holes" in filter
+ int o_t_overflow = div_up(
+ max(0, (jcp.kh - 1) * dilate_h - oj - jcp.t_pad),
+ dilate_h);
+ int o_b_overflow
+ = div_up(max(0, (jcp.kh - 1) * dilate_h + 1 - jcp.oh
+ + oj - jcp.b_pad),
+ dilate_h);
+ kh_len = jcp.kh - o_t_overflow - o_b_overflow;
+ kh_lo = o_b_overflow;
+ ih_max = oj + jcp.t_pad - o_b_overflow * dilate_h;
+ } else {
+ int o_t_overflow = max(
+ 0, (jcp.kh - (oj + 1 + jcp.t_pad)) / jcp.stride_h);
+ int o_b_overflow
+ = max(0, ((oj + jcp.kh) - (jcp.oh + jcp.b_pad))
+ / jcp.stride_h);
+ int overflow_kh_hi = jcp.kh - 1
+ - abs(jcp.oh + jcp.b_pad - (oj + 1)) % jcp.stride_h;
+ int overflow_kh_lo = (oj + jcp.t_pad) % jcp.stride_h;
+
+ kh_len = (overflow_kh_hi - overflow_kh_lo) / jcp.stride_h
+ + 1 - o_t_overflow - o_b_overflow;
+ kh_lo = overflow_kh_lo + o_b_overflow * jcp.stride_h;
+ ih_max = (oj + jcp.t_pad - kh_lo) / jcp.stride_h;
+ }
+
+ int wei_stride
+ = (!jcp.signed_input) ? kh_lo * wht_kh_stride : 0;
+ p.src = src_w + ih_max * src_h_stride;
+ p.dst = dst_w + oj * dst_h_stride;
+ p.filt = wht_w + wei_stride;
+ p.bias = bias_w;
+ p.compensation = compensation_w;
+ p.t_overflow = max(
+ 0, jcp.kh - (kh_lo + max(0, kh_len - 1) * jcp.stride_h
+ + 1));
+ p.b_overflow = kh_lo;
+ p.kh_padding = kh_len;
+ p.scales = scales;
+ p.oc_blocks = jcp.is_depthwise ? g : ocb;
+ kernel_->jit_ker(&p);
+ }
+ if (jcp.loop_order == loop_ngc)
+ nd_iterator_jump(start, end, n, jcp.mb, g, nb_groups, occ,
+ oc_chunks, oh_s, jcp.oh);
+ else if (jcp.loop_order == loop_cgn)
+ nd_iterator_jump(start, end, occ, oc_chunks, g, nb_groups, n,
+ jcp.mb, oh_s, jcp.oh);
+ else
+ assert(!"unsupported loop order");
+ }
+ });
+}
+
+template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<data_type::u8,
+ data_type::u8>;
+template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<data_type::u8,
+ data_type::s8>;
+template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<data_type::u8,
+ data_type::f32>;
+template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<data_type::u8,
+ data_type::s32>;
+template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<data_type::s8,
+ data_type::u8>;
+template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<data_type::s8,
+ data_type::s8>;
+template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<data_type::s8,
+ data_type::f32>;
+template struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<data_type::s8,
+ data_type::s32>;
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.hpp
new file mode 100644
index 0000000000..901038fa48
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_avx512_core_x8s8s32x_deconvolution.hpp
@@ -0,0 +1,237 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX512_CORE_U8S8S32X_DECONVOLUTION_HPP
+#define CPU_JIT_AVX512_CORE_U8S8S32X_DECONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "cpu_primitive.hpp"
+#include "cpu_memory.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+#include "nstl.hpp"
+
+#include "cpu_deconvolution_pd.hpp"
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+#include "jit_uni_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+typedef enum {
+ no_last_block = 0x1U,
+ last_ic_block = 0x2U,
+ last_sp_block = 0x4U,
+} ker_block_t;
+
+struct jit_avx512_core_x8s8s32x_deconv_fwd_kernel : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_avx512_core_x8s8s32x_deconv_fwd_ker_t);
+
+ jit_avx512_core_x8s8s32x_deconv_fwd_kernel(
+ const jit_conv_conf_t &ajcp, const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr) {
+ if (jcp.with_eltwise)
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<avx512_common>(
+ this, jcp.eltwise);
+ generate();
+ jit_ker = (void (*)(jit_deconv_call_s *))getCode();
+ }
+
+ ~jit_avx512_core_x8s8s32x_deconv_fwd_kernel() {
+ delete eltwise_injector_;
+ }
+
+ static bool post_ops_ok(jit_conv_conf_t &jcp,
+ const primitive_attr_t &attr);
+
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const deconvolution_desc_t &cd,
+ memory_desc_t &src_md,
+ memory_desc_t &weights_md,
+ memory_desc_t &dst_md,
+ const bool with_bias,
+ memory_desc_t &bias_md,
+ const primitive_attr_t &attr);
+
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp, const primitive_attr_t &attr);
+
+ const jit_conv_conf_t &jcp;
+ const primitive_attr_t &attr_;
+ void (*jit_ker)(jit_deconv_call_s *);
+private:
+ jit_uni_eltwise_injector_f32<avx512_common> *eltwise_injector_;
+ using reg64_t = const Xbyak::Reg64;
+ using zmm_t = const Xbyak::Zmm;
+ using xmm_t = const Xbyak::Xmm;
+
+ reg64_t reg_src = r8;
+ reg64_t reg_filt = r9;
+ reg64_t reg_dst = r10;
+ reg64_t param1 = abi_param1;
+ reg64_t reg_kh = abi_not_param1;
+ reg64_t reg_nur_w = rbx;
+ reg64_t reg_bias = rdx;
+ reg64_t reg_icb = reg_bias;
+ reg64_t reg_ptr_scales = rax;
+ reg64_t reg_oc_blocks = rsi;
+
+ reg64_t aux_reg_src = r11;
+ reg64_t aux_reg_filt = r12;
+
+ reg64_t reg_compensation = r14;
+ reg64_t reg_scratch = r14;
+ reg64_t reg_ptr_sum_scale = r11;
+ reg64_t reg_bias_alpha = abi_not_param1;
+ reg64_t reg_overflow = rax;
+ reg64_t reg_comp_strides = reg_overflow;
+
+ Xbyak::Opmask ktail_mask = Xbyak::Opmask(2);
+ zmm_t zmm_tmp = zmm_t(28);
+ zmm_t zmm_one = zmm_t(29);
+ /* used during write-out section of store_output */
+ zmm_t zmm_zero = zmm_t(31);
+ zmm_t zmm_wei = zmm_t(31);
+
+ /* signed input */
+ zmm_t zmm_shift = zmm_t(30);
+ zmm_t zmm_comp = zmm_t(30);
+ zmm_t zmm_bias = zmm_t(31);
+ zmm_t zmm_prev_dst = zmm_t(31);
+
+ zmm_t zmm_out(int i_ur, int i_oc) {
+ int idx = i_ur * jcp.nb_oc_blocking + i_oc;
+ assert(idx < 31);
+ return zmm_t(idx);
+ }
+ zmm_t zmm_inp(int i_ic, int nb_x_blocking) {
+ int idx = i_ic + nb_x_blocking * jcp.ur_w;
+ assert(idx < 31);
+ return zmm_t(idx);
+ }
+ zmm_t zmm_bias_alpha() {
+ return zmm_t(jcp.nb_oc_blocking * jcp.ur_w);
+ }
+ xmm_t xmm_bias_alpha() {
+ return xmm_t(jcp.nb_oc_blocking * jcp.ur_w);
+ }
+
+ int get_ow_start(int ki, int l_overflow) {
+ int res = (jcp.ow - 1 + jcp.r_pad) % jcp.stride_w
+ + l_overflow * jcp.stride_w
+ - (jcp.kw - 1 - ki) * (jcp.dilate_w + 1);
+ while (res < 0)
+ res += jcp.stride_w;
+ return res;
+ }
+
+ int get_ow_end(int ur_w, int ki, int r_overflow) {
+ if (utils::one_of(ur_w, jcp.ow, jcp.ur_w_tail))
+ ur_w += nstl::min(0, jcp.r_pad); // remove negative padding
+ int res = (ur_w - 1 + jcp.l_pad) % jcp.stride_w
+ + r_overflow * jcp.stride_w - ki * (jcp.dilate_w + 1);
+ while (res < 0)
+ res += jcp.stride_w;
+ return ur_w - res;
+ }
+ bool maybe_eltwise(int position);
+ void compute_eltwise(int ur_w);
+ void prepare_output(int ur_w);
+ void store_output(int ur_w, bool last_oc_block);
+ void compute_ker(int ur_w, int l_overflow, int r_overflow,
+ ker_block_t last_ic_block_flag, bool h_padded = false);
+ void kh_loop(int ur_w, int pad_l, int pad_r, ker_block_t last_ker_block);
+ void icb_loop(int ur_w, int pad_l, int pad_r, bool last_block);
+ void generate();
+ void cvt2ps(data_type_t type_in, zmm_t zmm_in, const Xbyak::Operand &op,
+ bool mask_flag);
+};
+
+template <impl::data_type_t src_type, impl::data_type_t dst_type>
+struct _jit_avx512_core_x8s8s32x_deconvolution_fwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_deconvolution_fwd_pd_t {
+ using cpu_deconvolution_fwd_pd_t::cpu_deconvolution_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_deconvolution:", avx512_core, ""),
+ _jit_avx512_core_x8s8s32x_deconvolution_fwd_t<src_type, dst_type>);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && (desc()->alg_kind & alg_kind::deconvolution_direct)
+ && desc()->src_desc.data_type == src_type
+ && desc()->dst_desc.data_type == dst_type
+ && IMPLICATION(with_bias(), utils::one_of(
+ desc()->bias_desc.data_type, data_type::f32,
+ data_type::s32, data_type::s8, data_type::u8))
+ && desc()->accum_data_type == data_type::s32;
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_avx512_core_x8s8s32x_deconv_fwd_kernel::
+ init_conf(jcp_, *desc(), src_md_, weights_md_, dst_md_,
+ with_bias(), bias_md_, *attr());
+
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_avx512_core_x8s8s32x_deconv_fwd_kernel::init_scratchpad(scratchpad,
+ jcp_, *attr());
+
+ return status::success;
+ }
+
+ jit_conv_conf_t jcp_;
+ };
+
+ _jit_avx512_core_x8s8s32x_deconvolution_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ {
+ kernel_ = new jit_avx512_core_x8s8s32x_deconv_fwd_kernel(pd()->jcp_,
+ *pd()->attr());
+ }
+
+ ~_jit_avx512_core_x8s8s32x_deconvolution_fwd_t() { delete kernel_; }
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<data_type::s8>::type wei_data_t;
+ typedef typename prec_traits<dst_type>::type dst_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ if(pd()->ndims() == 3)
+ execute_forward_1d(ctx);
+ else
+ execute_forward_2d(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward_1d(const exec_ctx_t &ctx) const;
+ void execute_forward_2d(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ jit_avx512_core_x8s8s32x_deconv_fwd_kernel *kernel_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_generator.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_generator.hpp
new file mode 100644
index 0000000000..c09592d5c9
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_generator.hpp
@@ -0,0 +1,773 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_AVX2_GENERATOR_HPP
+#define CPU_JIT_AVX2_GENERATOR_HPP
+
+#include <limits.h>
+
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "cpu_isa_traits.hpp"
+#include "jit_utils/jit_utils.hpp"
+
+#if defined(_WIN32) && !defined(__GNUC__)
+# define STRUCT_ALIGN(al, ...) __declspec(align(al)) __VA_ARGS__
+#else
+# define STRUCT_ALIGN(al, ...) __VA_ARGS__ __attribute__((__aligned__(al)))
+#endif
+
+#if defined(_WIN32)
+# define OFFSET_SHADOWSPACE 0x28
+#endif
+
+#define DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_name) \
+ const char *name() const override { return STRINGIFY(jit_name); } \
+ const char *source_file() const override { return __FILE__; }
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+// TODO: move this to jit_generator class?
+namespace {
+
+typedef enum {
+ PAGE_4K = 4096,
+ PAGE_2M = 2097152,
+} cpu_page_size_t;
+
+// TODO: move this somewhere else? Although this is only used by jit kernels
+// (Roma)
+static inline int float2int(float x) {
+ union {
+ float vfloat;
+ int vint;
+ } cvt;
+ cvt.vfloat = x;
+ return cvt.vint;
+}
+
+// TODO: A GPR class that hides ABI details from the JIT kernels and allows
+// numbering registers from 0 to 14 (x86_64) / 6 (x32) (gpr0, gpr1, ...) and
+// stack register (sr).
+//
+// This will allow using syntax like this:
+//
+// param = gpr0;
+// reg_input = gpr0;
+// reg_output = gpr1;
+// ...
+//
+// #ifndef XBYAK64
+// mov(param, ptr[sr])
+// #endif
+//
+// (Roma)
+
+#ifdef XBYAK64
+constexpr Xbyak::Operand::Code abi_save_gpr_regs[] = {
+ Xbyak::Operand::RBX, Xbyak::Operand::RBP, Xbyak::Operand::R12,
+ Xbyak::Operand::R13, Xbyak::Operand::R14, Xbyak::Operand::R15,
+#ifdef _WIN32
+ Xbyak::Operand::RDI, Xbyak::Operand::RSI,
+#endif
+};
+
+#ifdef _WIN32
+static const Xbyak::Reg64 abi_param1(Xbyak::Operand::RCX),
+ abi_param2(Xbyak::Operand::RDX),
+ abi_param3(Xbyak::Operand::R8),
+ abi_param4(Xbyak::Operand::R9),
+ abi_not_param1(Xbyak::Operand::RDI);
+#else
+static const Xbyak::Reg64 abi_param1(Xbyak::Operand::RDI),
+ abi_param2(Xbyak::Operand::RSI),
+ abi_param3(Xbyak::Operand::RDX),
+ abi_param4(Xbyak::Operand::RCX),
+ abi_param5(Xbyak::Operand::R8),
+ abi_param6(Xbyak::Operand::R9),
+ abi_not_param1(Xbyak::Operand::RCX);
+#endif
+#endif
+
+inline unsigned int get_cache_size(int level, bool per_core = true){
+ unsigned int l = level - 1;
+ // Currently, if XByak is not able to fetch the cache topology
+ // we default to 32KB of L1, 512KB of L2 and 1MB of L3 per core.
+ if (cpu.getDataCacheLevels() == 0){
+ const int L1_cache_per_core = 32000;
+ const int L2_cache_per_core = 512000;
+ const int L3_cache_per_core = 1024000;
+ int num_cores = per_core ? 1 : mkldnn_get_max_threads();
+ switch(l){
+ case(0): return L1_cache_per_core * num_cores;
+ case(1): return L2_cache_per_core * num_cores;
+ case(2): return L3_cache_per_core * num_cores;
+ default: return 0;
+ }
+ }
+ if (l < cpu.getDataCacheLevels()) {
+ return cpu.getDataCacheSize(l)
+ / (per_core ? cpu.getCoresSharingDataCache(l) : 1);
+ } else
+ return 0;
+}
+
+}
+
+class jit_generator : public Xbyak::CodeGenerator
+{
+private:
+ const size_t xmm_len = 16;
+#ifdef _WIN32
+ const size_t xmm_to_preserve_start = 6;
+ const size_t xmm_to_preserve = 10;
+#else
+ const size_t xmm_to_preserve_start = 0;
+ const size_t xmm_to_preserve = 0;
+#endif
+
+ const size_t num_abi_save_gpr_regs
+ = sizeof(abi_save_gpr_regs) / sizeof(abi_save_gpr_regs[0]);
+
+ const size_t size_of_abi_save_regs
+ = num_abi_save_gpr_regs * rax.getBit() / 8
+ + xmm_to_preserve * xmm_len;
+
+public:
+ enum {
+ _cmp_eq_oq = 0u,
+ _cmp_lt_os = 1u,
+ _cmp_le_os = 2u,
+ _cmp_neq_uq = 4u,
+ _cmp_nlt_us = 5u,
+ _cmp_nle_us = 6u,
+
+ _op_floor = 1u,
+ _op_mxcsr = 4u,
+ };
+
+ Xbyak::Reg64 param1 = abi_param1;
+ const int EVEX_max_8b_offt = 0x200;
+ const Xbyak::Reg64 reg_EVEX_max_8b_offt = rbp;
+
+ inline size_t get_size_of_abi_save_regs() {
+ return size_of_abi_save_regs;
+ }
+
+ void preamble() {
+ if (xmm_to_preserve) {
+ sub(rsp, xmm_to_preserve * xmm_len);
+ for (size_t i = 0; i < xmm_to_preserve; ++i)
+ movdqu(ptr[rsp + i * xmm_len], Xbyak::Xmm(xmm_to_preserve_start + i));
+ }
+ for (size_t i = 0; i < num_abi_save_gpr_regs; ++i)
+ push(Xbyak::Reg64(abi_save_gpr_regs[i]));
+ if (mayiuse(avx512_common)) {
+ mov(reg_EVEX_max_8b_offt, 2 * EVEX_max_8b_offt);
+ }
+ }
+
+ void mic_prefetcht0(Xbyak::Address a) {
+ if (mayiuse(avx512_mic))
+ prefetcht0(a);
+ }
+
+ void mic_prefetcht1(Xbyak::Address a) {
+ if (mayiuse(avx512_mic))
+ prefetcht1(a);
+ }
+
+ void mic_prefetcht2(Xbyak::Address a) {
+ if (mayiuse(avx512_mic))
+ prefetcht2(a);
+ }
+
+ void uni_vzeroupper() {
+ if (mayiuse(avx) && !mayiuse(avx512_mic))
+ vzeroupper();
+ }
+
+ void postamble() {
+ for (size_t i = 0; i < num_abi_save_gpr_regs; ++i)
+ pop(Xbyak::Reg64(abi_save_gpr_regs[num_abi_save_gpr_regs - 1 - i]));
+ if (xmm_to_preserve) {
+ for (size_t i = 0; i < xmm_to_preserve; ++i)
+ movdqu(Xbyak::Xmm(xmm_to_preserve_start + i), ptr[rsp + i * xmm_len]);
+ add(rsp, xmm_to_preserve * xmm_len);
+ }
+ uni_vzeroupper();
+ ret();
+ }
+
+ template<typename T>
+ Xbyak::Address EVEX_compress_addr(Xbyak::Reg64 base,
+ T raw_offt, bool bcast = false)
+ {
+ using Xbyak::Zmm;
+ using Xbyak::Reg64;
+ using Xbyak::Address;
+ using Xbyak::RegExp;
+
+ assert(raw_offt <= INT_MAX);
+ auto offt = static_cast<int>(raw_offt);
+
+ int scale = 0;
+
+ if (EVEX_max_8b_offt <= offt && offt < 3 * EVEX_max_8b_offt) {
+ offt = offt - 2 * EVEX_max_8b_offt;
+ scale = 1;
+ } else if (3 * EVEX_max_8b_offt <= offt && offt < 5 * EVEX_max_8b_offt) {
+ offt = offt - 4 * EVEX_max_8b_offt;
+ scale = 2;
+ }
+
+ auto re = RegExp() + base + offt;
+ if (scale)
+ re = re + reg_EVEX_max_8b_offt * scale;
+
+ if (bcast)
+ return zword_b [re];
+ else
+ return zword [re];
+ }
+
+ Xbyak::Address make_safe_addr(const Xbyak::Reg64 &reg_out, size_t offt,
+ const Xbyak::Reg64 &tmp_reg, bool bcast = false) {
+ if (offt > INT_MAX) {
+ mov(tmp_reg, offt);
+ return bcast ? ptr_b[reg_out + tmp_reg] : ptr[reg_out + tmp_reg];
+ } else {
+ return bcast ? ptr_b[reg_out + offt] : ptr[reg_out + offt];
+ }
+ }
+
+ Xbyak::Address EVEX_compress_addr_safe(const Xbyak::Reg64 &base,
+ size_t raw_offt, const Xbyak::Reg64 &reg_offt, bool bcast = false) {
+ if (raw_offt > INT_MAX) {
+ return make_safe_addr(base, raw_offt, reg_offt, bcast);
+ } else {
+ return EVEX_compress_addr(base, raw_offt, bcast);
+ }
+ }
+
+ void safe_add(const Xbyak::Reg64 &base, size_t raw_offt,
+ const Xbyak::Reg64 &reg_offt) {
+ if (raw_offt > INT_MAX) {
+ mov(reg_offt, raw_offt);
+ add(base, reg_offt);
+ } else {
+ add(base, raw_offt);
+ }
+ }
+
+ void safe_sub(const Xbyak::Reg64 &base, size_t raw_offt,
+ const Xbyak::Reg64 &reg_offt) {
+ if (raw_offt > INT_MAX) {
+ mov(reg_offt, raw_offt);
+ sub(base, reg_offt);
+ } else {
+ sub(base, raw_offt);
+ }
+ }
+
+ // Disallow char-based labels completely
+ void L(const char *label) = delete;
+ void L(Xbyak::Label& label) { Xbyak::CodeGenerator::L(label); }
+
+ void uni_vpxor(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op) {
+ assert(x1.getIdx() == x2.getIdx());
+ pxor(x2, op);
+ }
+ void uni_vpxor(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2,
+ const Xbyak::Operand &op) {
+ if (mayiuse(avx2)) {
+ vpxor(x1, x2, op);
+ } else {
+ vxorps(x1, x2, op);
+ }
+ }
+ void uni_vpxor(const Xbyak::Zmm &x1, const Xbyak::Zmm &x2,
+ const Xbyak::Operand &op) {
+ vpxord(x1, x2, op);
+ }
+
+ void uni_vmovss(const Xbyak::Address& addr, const Xbyak::Xmm &x) {
+ movss(addr, x);
+ }
+ void uni_vmovss(const Xbyak::Address& addr, const Xbyak::Ymm &x) {
+ vmovss(addr, x);
+ }
+ void uni_vmovss(const Xbyak::Xmm &x, const Xbyak::Address& addr) {
+ movss(x, addr);
+ }
+ void uni_vmovss(const Xbyak::Ymm &x, const Xbyak::Address& addr) {
+ vmovss(x, addr);
+ }
+
+ void uni_vmovsd(const Xbyak::Address& addr, const Xbyak::Xmm &x) {
+ movsd(addr, x);
+ }
+ void uni_vmovsd(const Xbyak::Address& addr, const Xbyak::Ymm &x) {
+ vmovsd(addr, x);
+ }
+ void uni_vmovsd(const Xbyak::Xmm &x, const Xbyak::Address& addr) {
+ movsd(x, addr);
+ }
+ void uni_vmovsd(const Xbyak::Ymm &x, const Xbyak::Address& addr) {
+ vmovsd(x, addr);
+ }
+
+ void uni_vmovdqu(const Xbyak::Address &addr, const Xbyak::Xmm &x) {
+ movdqu(addr, x);
+ }
+ void uni_vmovdqu(const Xbyak::Address &addr, const Xbyak::Ymm &x) {
+ vmovdqu(addr, x);
+ }
+ void uni_vmovdqu(const Xbyak::Address &addr, const Xbyak::Zmm &x) {
+ vmovdqu32(addr, x);
+ }
+
+ void uni_vmovdqu(const Xbyak::Xmm &x, const Xbyak::Address &addr) {
+ movdqu(x, addr);
+ }
+ void uni_vmovdqu(const Xbyak::Ymm &x, const Xbyak::Address &addr) {
+ vmovdqu(x, addr);
+ }
+ void uni_vmovdqu(const Xbyak::Zmm &x, const Xbyak::Address &addr) {
+ vmovdqu32(x, addr);
+ }
+
+ void uni_vmovups(const Xbyak::Address &addr, const Xbyak::Xmm &x) {
+ movups(addr, x);
+ }
+ void uni_vmovups(const Xbyak::Address &addr, const Xbyak::Ymm &x) {
+ vmovups(addr, x);
+ }
+
+ void uni_vmovups(const Xbyak::Xmm &x, const Xbyak::Operand &op) {
+ movups(x, op);
+ }
+ void uni_vmovups(const Xbyak::Ymm &x, const Xbyak::Operand &op) {
+ vmovups(x, op);
+ }
+
+ void uni_vmovntps(const Xbyak::Address &addr, const Xbyak::Xmm &x) {
+ movntps(addr, x);
+ }
+ void uni_vmovntps(const Xbyak::Address &addr, const Xbyak::Ymm &x) {
+ vmovntps(addr, x);
+ }
+
+ void uni_vbroadcastss(const Xbyak::Xmm &x, const Xbyak::Operand &op) {
+ movss(x, op);
+ shufps(x, x, 0x0);
+ }
+ void uni_vbroadcastss(const Xbyak::Ymm &x, const Xbyak::Operand &op) {
+ if (op.isMEM() || mayiuse(avx2)) {
+ vbroadcastss(x, op);
+ } else {
+ Xbyak::Xmm t(x.getIdx());
+ if (t.getIdx() != op.getIdx()) movss(t, op);
+ vinsertf128(x, x, t, 1);
+ vshufps(x, x, x, 0);
+ }
+ }
+
+ void uni_vpbroadcastd(const Xbyak::Xmm &x, const Xbyak::Operand &op) {
+ movsd(x, op);
+ pshufd(x, x, 0x0);
+ }
+ void uni_vpbroadcastd(const Xbyak::Ymm &x, const Xbyak::Operand &op) {
+ if (mayiuse(avx2)) {
+ vpbroadcastd(x, op);
+ } else {
+ Xbyak::Xmm t(x.getIdx());
+ if (t.getIdx() != op.getIdx()) movsd(t, op);
+ vinsertf128(x, x, t, 1);
+ vshufps(x, x, x, 0);
+ }
+ }
+
+ void uni_vrcpss(const Xbyak::Xmm &x, const Xbyak::Operand &op) {
+ rcpss(x, op);
+ }
+ void uni_vrcpss(const Xbyak::Ymm &x1, const Xbyak::Xmm &x2) {
+ Xbyak::Xmm x1_(x1.getIdx());
+ Xbyak::Xmm x2_(x2.getIdx());
+ vrcpss(x1_, x1_, x2_);
+ }
+ void uni_vrcpss(const Xbyak::Ymm &x, const Xbyak::Address &op) {
+ Xbyak::Xmm x_(x.getIdx());
+ vrcpss(x_, x_, op);
+ }
+
+ void uni_vrcpps(const Xbyak::Xmm &x, const Xbyak::Operand &op) {
+ rcpps(x, op);
+ }
+ void uni_vrcpps(const Xbyak::Ymm &x, const Xbyak::Operand &op) {
+ vrcpps(x, op);
+ }
+ void uni_vrcpps(const Xbyak::Zmm &x, const Xbyak::Operand &op) {
+ vrcp14ps(x, op);
+ }
+
+ void uni_vdivps(const Xbyak::Xmm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ assert(x.getIdx() == op1.getIdx());
+ divps(x, op2);
+ }
+ void uni_vdivps(const Xbyak::Ymm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ vdivps(x, op1, op2);
+ }
+
+ void uni_vdivps(const Xbyak::Xmm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2, const Xbyak::Xmm &buf) {
+ movups(buf, op1);
+ divps(buf, op2);
+ if (x.getIdx() != buf.getIdx()) {
+ movups(x, buf);
+ }
+ }
+
+ void uni_vdivps(const Xbyak::Ymm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2, const Xbyak::Ymm &buf) {
+ vdivps(x, op1, op2);
+ }
+
+ void uni_vaddps(const Xbyak::Xmm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ assert(x.getIdx() == op1.getIdx());
+ addps(x, op2);
+ }
+ void uni_vaddps(const Xbyak::Ymm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ vaddps(x, op1, op2);
+ }
+
+ void uni_vpsignd(const Xbyak::Xmm& x1, const Xbyak::Xmm& x2,
+ const Xbyak::Operand& op) {
+ assert(x1.getIdx() == x2.getIdx());
+ psignd(x1, op);
+ }
+ void uni_vpsignd(const Xbyak::Ymm& x1, const Xbyak::Ymm& x2,
+ const Xbyak::Operand& op) {
+ vpsignd(x1, x2, op);
+ }
+
+ void uni_vsubps(const Xbyak::Xmm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ assert(x.getIdx() == op1.getIdx());
+ subps(x, op2);
+ }
+ void uni_vsubps(const Xbyak::Ymm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ vsubps(x, op1, op2);
+ }
+
+ void uni_vsubps(const Xbyak::Xmm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2, const Xbyak::Xmm &buf) {
+ movups(buf, op1);
+ subps(buf, op2);
+ if (x.getIdx() != buf.getIdx()) {
+ movups(x, buf);
+ }
+ }
+
+ void uni_vsubps(const Xbyak::Ymm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2, const Xbyak::Ymm &buf) {
+ vsubps(x, op1, op2);
+ }
+
+ void uni_vmulps(const Xbyak::Xmm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ assert(x.getIdx() == op1.getIdx());
+ mulps(x, op2);
+ }
+ void uni_vmulps(const Xbyak::Ymm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ vmulps(x, op1, op2);
+ }
+
+ void uni_vfmadd213ps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op) {
+ mulps(x1, x2);
+ addps(x1, op);
+ }
+ void uni_vfmadd213ps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2,
+ const Xbyak::Operand &op) {
+ vfmadd213ps(x1, x2, op);
+ }
+
+ void uni_vfmadd231ps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op) {
+ mulps(x2, op);
+ addps(x1, x2);
+ }
+ void uni_vfmadd231ps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2,
+ const Xbyak::Operand &op) {
+ vfmadd231ps(x1, x2, op);
+ }
+
+ void uni_vfnmadd231ps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op) {
+ mulps(x2, op);
+ subps(x1, x2);
+ }
+
+ void uni_vfnmadd231ps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2,
+ const Xbyak::Operand &op) {
+ vfnmadd231ps(x1, x2, op);
+ }
+
+ void uni_vsqrtps(const Xbyak::Xmm &x, const Xbyak::Operand &op) {
+ sqrtps(x, op);
+ }
+ void uni_vsqrtps(const Xbyak::Ymm &x, const Xbyak::Operand &op) {
+ vsqrtps(x, op);
+ }
+
+ void uni_vpaddd(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op) {
+ assert(x1.getIdx() == x2.getIdx());
+ paddd(x2, op);
+ }
+ void uni_vpaddd(const Xbyak::Ymm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op) {
+ vpaddd(x1, x2, op);
+ }
+
+ void uni_vandps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op = Xbyak::Operand()) {
+ assert(x1.getIdx() == x2.getIdx());
+ andps(x1, op);
+ }
+ void uni_vandps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2,
+ const Xbyak::Operand &op = Xbyak::Operand()) {
+ if (!mayiuse(avx512_common) || x1.getBit() < 512)
+ vandps(x1, x2, op);
+ else
+ vpandd(x1, x2, op);
+ }
+
+ void uni_vorps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op = Xbyak::Operand()) {
+ assert(x1.getIdx() == x2.getIdx());
+ orps(x1, op);
+ }
+ void uni_vorps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2,
+ const Xbyak::Operand &op = Xbyak::Operand()) {
+ if (!mayiuse(avx512_common) || x1.getBit() < 512)
+ vorps(x1, x2, op);
+ else
+ vpord(x1, x2, op);
+ }
+
+ void uni_vpslld(const Xbyak::Xmm &x, const Xbyak::Operand &op,
+ const int imm) {
+ assert(x.getIdx() == op.getIdx());
+ pslld(x, imm);
+ }
+ void uni_vpslld(const Xbyak::Ymm &x, const Xbyak::Operand &op,
+ const int imm) {
+ vpslld(x, op, imm);
+ }
+
+ void uni_vpsrld(const Xbyak::Xmm &x, const Xbyak::Operand &op,
+ const int imm) {
+ assert(x.getIdx() == op.getIdx());
+ psrld(x, imm);
+ }
+ void uni_vpsrld(const Xbyak::Ymm &x, const Xbyak::Operand &op,
+ const int imm) {
+ vpsrld(x, op, imm);
+ }
+
+ void uni_vmaxps(const Xbyak::Xmm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ assert(x.getIdx() == op1.getIdx());
+ maxps(x, op2);
+ }
+ void uni_vmaxps(const Xbyak::Ymm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ vmaxps(x, op1, op2);
+ }
+
+ void uni_vminps(const Xbyak::Xmm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ assert(x.getIdx() == op1.getIdx());
+ minps(x, op2);
+ }
+ void uni_vminps(const Xbyak::Ymm &x, const Xbyak::Operand &op1,
+ const Xbyak::Operand &op2 = Xbyak::Operand()) {
+ vminps(x, op1, op2);
+ }
+
+ void uni_vcmpgtps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op) {
+ assert(x1.getIdx() == x2.getIdx());
+ cmpps(x1, op, _cmp_nle_us);
+ }
+
+ void uni_vcmpgtps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2,
+ const Xbyak::Operand &op) {
+ vcmpgtps(x1, x2, op);
+ }
+
+ void uni_vcmpgeps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op) {
+ assert(x1.getIdx() == x2.getIdx());
+ cmpps(x1, op, _cmp_nlt_us);
+ }
+
+ void uni_vcmpgeps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2,
+ const Xbyak::Operand &op) {
+ vcmpps(x1, x2, op, _cmp_nlt_us);
+ }
+
+ void uni_vtestps(const Xbyak::Xmm &x1, const Xbyak::Operand &op) {
+ ptest(x1, op);
+ }
+
+ void uni_vtestps(const Xbyak::Ymm &x1, const Xbyak::Operand &op) {
+ assert(!(x1.isZMM() || op.isZMM()));
+ vtestps(x1, op);
+ }
+
+ void uni_vblendvps(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2,
+ const Xbyak::Operand &op, const Xbyak::Xmm &msk) {
+ assert(x1.getIdx() == x2.getIdx());
+ assert(msk.getIdx() == 0);
+ blendvps(x1, op);
+ }
+ void uni_vblendvps(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2,
+ const Xbyak::Operand &op, const Xbyak::Ymm &msk) {
+ vblendvps(x1, x2, op, msk);
+ }
+
+ void uni_vroundps(const Xbyak::Xmm &x, const Xbyak::Operand &op,
+ const int imm) {
+ roundps(x, op, imm);
+ }
+ void uni_vroundps(const Xbyak::Ymm &x, const Xbyak::Operand &op,
+ const int imm) {
+ vroundps(x, op, imm);
+ }
+
+ void uni_vcvtps2dq(const Xbyak::Xmm &x, const Xbyak::Operand &op) {
+ cvtps2dq(x, op);
+ }
+ void uni_vcvtps2dq(const Xbyak::Ymm &x, const Xbyak::Operand &op) {
+ vcvtps2dq(x, op);
+ }
+
+ void uni_vcvtdq2ps(const Xbyak::Xmm &x, const Xbyak::Operand &op) {
+ cvtdq2ps(x, op);
+ }
+ void uni_vcvtdq2ps(const Xbyak::Ymm &x, const Xbyak::Operand &op) {
+ vcvtdq2ps(x, op);
+ }
+
+ void uni_vmovmskps(const Xbyak::Reg &x1, const Xbyak::Xmm &x2) {
+ movmskps(x1.cvt64(), x2);
+ }
+ void uni_vmovmskps(const Xbyak::Reg &x1, const Xbyak::Ymm &x2) {
+ vmovmskps(x1, x2);
+ }
+
+ void uni_vpackssdw(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, const Xbyak::Operand &op){
+ assert(x1.getIdx() == x1.getIdx());
+ packssdw(x1, op);
+ }
+ void uni_vpackssdw(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, const Xbyak::Operand &op){
+ vpackssdw(x1, x2, op);
+ }
+
+ void uni_vpackuswb(const Xbyak::Xmm &x1, const Xbyak::Xmm &x2, const Xbyak::Operand &op){
+ assert(x1.getIdx() == x1.getIdx());
+ packuswb(x1, op);
+ }
+ void uni_vpackuswb(const Xbyak::Ymm &x1, const Xbyak::Ymm &x2, const Xbyak::Operand &op){
+ vpackuswb(x1, x2, op);
+ }
+
+
+ void mul_by_const(const Xbyak::Reg &out,
+ const Xbyak::Reg64 &tmp, int value) {
+ // Generates a shift + add sequence for multiplicating contents of the
+ // out register by a known JIT-time value. Clobbers the tmp register.
+ //
+ // Pros compared to mul/imul:
+ // - does not require using known registers
+ // - not microcoded on Intel(R) Xeon Phi(TM) processors
+ // Still, there are probably a lot of cases when mul/imul is faster on
+ // Intel(R) Core(TM) processors. Not intended for critical path.
+
+ // TODO: detect when overflow is emminent (Roma)
+ // TODO: detect when using mul/imul is a better option (Roma)
+
+ int p = 0; // the current power of 2
+ int old_p = 0; // the last seen power of 2 such that value[old_p] != 0
+
+ xor_(tmp, tmp);
+ while (value) {
+ if (value & 1) {
+ int shift = p - old_p;
+ if (shift) {
+ shl(out, shift);
+ old_p = p;
+ }
+ add(tmp, out);
+ }
+ value >>= 1;
+ p++;
+ }
+ mov(out, tmp);
+ }
+
+public:
+ jit_generator(
+ void *code_ptr = nullptr,
+ size_t code_size = 256 * 1024
+ ) : Xbyak::CodeGenerator(code_size, code_ptr)
+ {
+ }
+ virtual ~jit_generator() {}
+
+ virtual const char *name() const = 0;
+ virtual const char *source_file() const = 0;
+
+ const Xbyak::uint8 *getCode() {
+ const Xbyak::uint8 *code = CodeGenerator::getCode();
+ size_t code_size = getSize();
+ jit_utils::register_jit_code(code, code_size, name(), source_file());
+ return code;
+ }
+
+ template<typename F> const F getCode() {
+ return (const F)getCode();
+ }
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_primitive_conf.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_primitive_conf.hpp
new file mode 100644
index 0000000000..56d7f592e2
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_primitive_conf.hpp
@@ -0,0 +1,481 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_PRIMITIVE_CONF_HPP
+#define JIT_PRIMITIVE_CONF_HPP
+
+#include <stdint.h>
+
+#include "common/primitive_attr.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+/* convolution */
+enum conv_version_t {ver_unused, ver_fma, ver_avx512_core, ver_4fma, ver_vnni};
+enum conv_loop_order_t {loop_cgn, loop_gnc, loop_ngc, loop_gncw, loop_cwgn,
+ loop_ngcw, loop_nhwcg, loop_nwcg};
+enum conv_1x1_loop_order_t {loop_rbl, loop_rlb, loop_lbr, loop_lrb, loop_blr,
+ loop_brl};
+enum conv_kernel_kind_t {embd_bcast, expl_bcast};
+
+enum {
+ FLAG_MB_FIRST = 1 << 0, FLAG_MB_LAST = 1 << 1,
+ FLAG_OC_FIRST = 1 << 2, FLAG_OC_LAST = 1 << 3,
+ FLAG_IC_FIRST = 1 << 4, FLAG_IC_LAST = 1 << 5,
+ FLAG_SP_FIRST = 1 << 6, FLAG_SP_LAST = 1 << 7,
+ FLAG_REDUCE_FIRST = 1<<8, FLAG_REDUCE_LAST = 1<<9,
+ FLAG_ZERO_FILTER = 1 << 0, /* Controls whether the inner kernel skips
+ loading weights-data from memory; this
+ needs to happen on the first Group/16
+ iteration. */
+ FLAG_ZERO_BIAS = 1 << 1, /* Controls whether the inner kernel skip
+ loading bias data from memory */
+ FLAG_COMPUTE_BIAS = 1 << 2, /* Controls bias computation during execution
+ pass */
+};
+
+struct jit_conv_conf_t {
+ prop_kind_t prop_kind;
+ conv_version_t ver;
+ conv_loop_order_t loop_order;
+
+ int simd_w;
+ int ndims;
+ int mb;
+ int ngroups, ic, oc, oc_without_padding, ic_without_padding;
+ int id, ih, iw, od, oh, ow;
+ int f_pad, l_pad, t_pad;
+ int back_pad, r_pad, b_pad;
+ int kd, kh, kw;
+ int stride_d, stride_h, stride_w;
+ int dilate_d, dilate_h, dilate_w;
+ format_tag_t src_tag, wei_tag, dst_tag; // temporary workaround
+ bool with_bias;
+ bool with_sum;
+ bool with_eltwise;
+
+ post_ops_t::entry_t::eltwise_t eltwise;
+
+ int nthr, nthr_mb, nthr_g, nthr_oc_b, nthr_ic_b;
+
+ int idp, ihp, iwp, ohp, owp;
+ int nb_ic, ic_block;
+ int nb_oc, oc_block;
+ int nb_ow, ow_block;
+ int nb_oc_blocking; /* used in jit kernels for nb_oc work bloking taking
+ into account vector registers distribution */
+ int nb_oc_blocking_thr_chunk; /* used for distibution of nb_oc work
+ within threads */
+ int nb_ic_blocking, nb_ic_blocking_max; // blocking of nb_ic work
+ int nb_ic_L2;
+ int h_blocking;
+ int nb_oc_L2;
+ int ur_h, ur_w;
+ int ur_w_tail;
+ bool is_1stconv;
+ int nonblk_group_off;
+ /* fma avx512_core */
+ conv_kernel_kind_t kernel_kind;
+ /* 4fma */
+ int tr_iw;
+ int tr_src_num_guard_elems;
+ /* 1st conv: 4fma */
+ int tr_ld;
+ int kh_step;
+ /* 4vnni */
+ int typesize_in;
+ int typesize_out;
+ int typesize_bia;
+ int typesize_acc;
+ /* avx512_u8s8u8 */
+ int ic_nb1, ic_nb2;
+ int oc_nb1;
+ int ur_ow_max, ur_ow, ur_ow_tail;
+ int ur_ow_nsteps;
+ data_type_t bia_dt;
+ data_type_t dst_dt;
+ /* avx512: max possible value is nregs(32) - aux_regs(4) */
+ int src_offsets[28];
+ int src_count;
+ bool expl_bcast;
+ bool large_spatial;
+ int is_oc_scale;
+ int max_regs_ur; // maximum accumulation registers
+ // dw conv
+ int nb_ch, ch_block, nb_ch_blocking;
+ bool is_depthwise, is_fast_depthwise, is_resrc_depthwise;
+ int aligned_threads;
+ // large spatial
+ int oh_blk_size;
+ // s8s8 convolution
+ bool signed_input;
+ float wei_adj_scale;
+};
+
+struct jit_conv_conf_2x3_wino_t {
+ conv_version_t ver;
+
+ int m;
+ int r;
+ int alpha;
+ int tile_h, tile_w;
+
+ int mb;
+ int ngroups, ic, oc, oc_without_padding;
+ int ih, iw, oh, ow;
+ int l_pad, t_pad;
+ int r_pad, b_pad;
+ int kh, kw;
+ int stride_h, stride_w;
+ int dilate_h, dilate_w;
+
+ int nb_ic, ic_block;
+ int nb_oc, oc_block;
+
+ int w_block_size, h_block_size;
+
+ data_type_t bia_dt;
+ data_type_t dst_dt;
+
+ int is_oc_scale;
+ int typesize_in;
+ int typesize_out;
+ int typesize_bia;
+ int typesize_acc;
+
+ format_tag_t src_tag, dst_tag; // temporary workaround
+ bool with_bias;
+ bool small_mb;
+
+ int xb, yb;
+ int inp_stride;
+ int out_stride;
+ int wei_stride;
+ int bia_stride;
+
+ int M, N, K;
+ int m_block, n_block, k_block;
+ int n2_block, n_chunks;
+ int k2_block, k_chunks;
+
+ int mb_block, nb_mb;
+
+ size_t size_wino_src, size_wino_wei, size_wino_dst;
+
+ int nthr;
+};
+
+/*
+ Winograd sched policy:
+
+ Computation Unit:
+ W: weights transform
+ S: src transform
+ D: dst transform
+ G: gemm
+
+ Thread grouping by:
+ i: nb_ic
+ o: nb_oc
+ t: tile_block
+ e: element in tile
+
+ Note: 'i' and 'o' are omited if
+ i. not comblined with t or
+ ii. with discrete transforms
+
+ Current policies supported:
+*/
+enum winograd_sched_t {
+ WSCHED_INVALID = 0,
+
+ /* Forward & backward-data */
+ /* W_S_G_D implements discrete transforms */
+ WSCHED_DATA_W_S_G_D,
+ /* W_SGD implements tiled transforms s.t. GEMM could reuse data in L2*/
+ WSCHED_DATA_W_SGD,
+
+ /* Backward-weights */
+ WSCHED_WEI_S_D_G_W,
+ WSCHED_WEI_SDGtWo,
+ WSCHED_WEI_S_D_Giot_W,
+ WSCHED_WEI_SDGt_W,
+};
+
+struct jit_conv_winograd_conf_t : public jit_conv_conf_t {
+ int itiles;
+ int jtiles;
+ int ntiles;
+ int ic_simd_block=16;
+ int tile_4fma_padding;
+ int tile_4fma;
+ int oc_simd_block=16;
+ int oc_reg_block;
+ int ic_reg_block;
+ int tile_block;
+ int tile_block_ur;
+ int nb_tile_block_ur;
+
+ bool double_buffering;
+ bool with_relu_postsum;
+ int zmm_start;
+ int nb_reg;
+
+ int dimK;
+ int dimK_4fma;
+ int dimK_reg_block;
+ int dimK_block;
+ int dimK_nb_block;
+
+ int dimM;
+ int dimM_reg_block;
+ int dimM_simd_block;
+ int dimM_block;
+ int dimM_nb_block;
+
+ int dimN;
+ int dimN_reg_block;
+ int dimN_bcast_ur;
+ int dimN_block;
+ int dimN_nb_block;
+
+ winograd_sched_t sched_policy;
+};
+
+struct jit_conv_call_s {
+ const void *src; /* hack, non-const for backward_data */
+ const void *dst; /* hack, non-const for forward */
+ const void *filt; /* hack, non-const for backward_weights */
+ const void *bias; /* hack, non-const for backward_bias */
+ const void *src_prf;
+ const void *dst_prf;
+ const void *filt_prf;
+ const void *bias_prf;
+ const void *scales;
+ const void *acc_s32;
+ const void *compensation;
+ size_t kd_offset;
+ size_t kd_offset_prf;
+ size_t d_index;
+ size_t d_index_prf;
+ size_t d_worksize;
+ size_t d_worksize_prf;
+ size_t kd_padding;
+ size_t kd_padding_prf;
+ size_t kh_padding;
+ size_t kh_padding_prf;
+ size_t owb;
+ size_t owb_prf;
+ size_t kw_padding;
+ size_t channel;
+ size_t channel_prf;
+ size_t oc_blocks;
+ size_t ur_w;
+ size_t ur_str_w;
+ size_t ch_blocks;
+ size_t t_overflow;
+ size_t b_overflow;
+ int flags;
+};
+
+struct jit_deconv_call_s {
+ const void *src; /* hack, non-const for backward_data */
+ const void *dst; /* hack, non-const for forward */
+ const void *filt; /* hack, non-const for backward_weights */
+ const void *bias; /* hack, non-const for backward_bias */
+ const void *scales;
+ const void *compensation;
+ size_t t_overflow;
+ size_t b_overflow;
+ size_t kh_padding;
+ size_t oc_blocks;
+};
+
+struct jit_dw_conv_call_s {
+ const void *input;
+ const void *output;
+ const void *filter;
+ const void *bias;
+ size_t kh_count;
+ size_t oh_count;
+ size_t oh_index;
+ size_t filter_pad_off;
+ unsigned char
+ exec_flags; /* Flags passed by driver execution to inner kernel */
+};
+
+struct jit_wino_transform_call_s {
+ size_t tile_block;
+ size_t tile_block_ur;
+ size_t nb_tile_block_ur;
+ size_t tile_count;
+ size_t tj;
+ size_t ti;
+ void *src;
+ void *dst;
+ void *Mw;
+ void *M;
+ void *T;
+ void *G;
+ void *bias;
+};
+
+struct jit_1x1_conv_conf_t {
+ prop_kind_t prop_kind;
+ conv_version_t ver;
+
+ int mb;
+ int ngroups, ic, oc, oc_without_padding, ic_without_padding;
+ int iw, ih, ow, oh;
+ int l_pad, t_pad;
+ int kh, kw;
+ int stride_h, stride_w;
+ format_tag_t src_tag, wei_tag, dst_tag; // temporary workaround
+ bool with_bias;
+ bool with_sum;
+ bool with_eltwise;
+
+ post_ops_t::entry_t::eltwise_t eltwise;
+
+ int is, os;
+ int ic_block, oc_block;
+
+ int ur, ur_tail;
+
+ int reduce_dim, reduce_block, nb_reduce,
+ nb_reduce_blocking, nb_reduce_blocking_max;
+ int load_dim, load_block, nb_load,
+ nb_load_blocking, nb_load_blocking_max, nb_load_chunk;
+ int bcast_dim, bcast_block, nb_bcast,
+ nb_bcast_blocking, nb_bcast_blocking_max;
+
+ int reduce_loop_unroll, reduce_loop_bcast_step, reduce_loop_load_step;
+ int load_loop_load_step, load_loop_iter_step;
+ int bcast_loop_output_step, bcast_loop_output_substep;
+ int bcast_loop_bcast_step, bcast_loop_bcast_substep;
+ int fma_step;
+ int load_grp_count;
+ conv_1x1_loop_order_t loop_order;
+ bool use_vmovntps;
+ /* avx512 core */
+ bool expl_bcast;
+ /* 4vnni */
+ int typesize_in;
+ int typesize_out;
+ int typesize_bia;
+ int typesize_acc;
+ /* 4fma */
+ bool transpose_src;
+ int tr_is;
+ int nthr, nthr_mb, nthr_g, nthr_oc_b, nthr_ic_b;
+ int is_oc_scale;
+ data_type_t bia_dt;
+ data_type_t dst_dt;
+ bool signed_input;
+ float wei_adj_scale;
+};
+
+struct jit_gemm_conv_conf_t {
+ prop_kind_t prop_kind;
+
+ int mb;
+ int ngroups, ic, oc;
+ int iw, ih, id, ow, oh, od;
+ int l_pad, t_pad, f_pad;
+ int kh, kw, kd;
+ int stride_h, stride_w, stride_d;
+ int dilate_h, dilate_w, dilate_d;
+ bool with_bias;
+
+ int is, os, ks;
+ int ic_block, oc_block;
+
+ int nthr;
+ ptrdiff_t im2col_sz;
+ bool need_wei_reduction;
+ bool signed_input;
+ int oh_block;
+ int ow_block;
+ bool outer_threading;
+};
+
+struct jit_1x1_conv_call_s {
+ const void *bcast_data;
+ const void *load_data;
+ const void *output_data;
+ const void *bias_data; // used in forward and backward_weights only
+ const void *acc_s32;
+ const void *scales;
+ const void *compensation;
+
+ size_t load_dim;
+ size_t bcast_dim;
+ size_t reduce_dim;
+
+ size_t output_stride; // used in backward_weights only
+
+ size_t first_last_flag;
+};
+
+/* pooling */
+struct jit_pool_conf_t {
+ int ndims;
+ int mb, c;
+ int id, ih, iw, od, oh, ow;
+ int stride_d, stride_h, stride_w;
+ int kd, kh, kw;
+ int f_pad, t_pad, l_pad;
+ alg_kind_t alg;
+ bool is_training;
+ bool pad_w_is_null;
+ bool is_backward;
+ bool simple_alg;
+ data_type_t ind_dt;
+
+ int c_block, c_tail, nb_c;
+ int ur_c, ur_c_tail;
+ int ur_w;
+ int ur_w_tail;
+ size_t tail[4];
+ data_type_t src_dt;
+ data_type_t dst_dt;
+};
+
+struct jit_pool_call_s {
+ const float *src;
+ const float *dst;
+ const void *indices;
+ const float *src_prf;
+ const float *dst_prf;
+ const void *indices_prf;
+ size_t oh;
+ size_t kd_padding;
+ size_t kh_padding;
+ size_t kh_padding_shift;
+ size_t kd_padding_shift;
+ size_t kw_padding;
+ const float* init_value;
+ float ker_area_h;
+};
+
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.cpp
new file mode 100644
index 0000000000..94d2101d6e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.cpp
@@ -0,0 +1,677 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+#include "cpu_memory.hpp"
+
+#include "jit_sse42_1x1_conv_kernel_f32.hpp"
+
+#define GET_OFF(field) offsetof(jit_1x1_conv_call_s, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::utils;
+
+using namespace Xbyak;
+
+void jit_sse42_1x1_conv_kernel_f32::generate_bcast_loop(int load_loop_blk)
+{
+ mov(aux1_reg_bcast_data, reg_bcast_data);
+ mov(aux_reg_output_data, reg_output_data);
+ mov(bcast_loop_iter, reg_bcast_loop_work);
+
+ Label bcast_loop;
+ Label bcast_loop_tail;
+
+ cmp(bcast_loop_iter, jcp.ur);
+ jl(bcast_loop_tail, T_NEAR);
+
+ L(bcast_loop); {
+ assert(jcp.bcast_block % jcp.ur == 0);
+ int num_substeps = jcp.bcast_block / jcp.ur;
+ assert(num_substeps > 0 && num_substeps < 10);
+ for (int i = 0; i < num_substeps; i++) {
+ generate_reduce_loop(load_loop_blk, jcp.ur);
+ if (i < num_substeps - 1) {
+ add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_substep);
+ add(aux_reg_output_data, jcp.bcast_loop_output_substep);
+ } else {
+ add(aux1_reg_bcast_data, jcp.bcast_loop_bcast_step
+ - (num_substeps - 1) * jcp.bcast_loop_bcast_substep);
+ add(aux_reg_output_data, jcp.bcast_loop_output_step
+ - (num_substeps - 1) * jcp.bcast_loop_output_substep);
+ }
+ }
+ sub(bcast_loop_iter, jcp.bcast_block);
+ cmp(bcast_loop_iter, jcp.bcast_block);
+ jge(bcast_loop, T_NEAR);
+ }
+
+ L(bcast_loop_tail);
+ if (jcp.ur_tail) {
+ Label bcast_loop_tail_out;
+ cmp(bcast_loop_iter, 0);
+ jz(bcast_loop_tail_out, T_NEAR);
+ generate_reduce_loop(load_loop_blk, jcp.ur_tail);
+ L(bcast_loop_tail_out);
+ }
+}
+
+void jit_sse42_1x1_conv_kernel_f32::generate_reduce_loop(
+ int load_loop_blk, int ur)
+{
+ auto reg_load = [=](int i, int n) {
+ return Xmm(2*ur * load_loop_blk + 2*i + n + 1);
+ };
+
+ auto reg_accum = [=](int i, int j, int n) {
+ return Xmm(2*j * load_loop_blk + 2*i + n + 1);
+ };
+
+ auto bias_ptr = [=](int i, int n) {
+ return ptr[reg_bias_data + sizeof(float) * jcp.oc_block * i + n*4*sizeof(float)];
+ };
+
+ auto bcast_ptr = [=](int u, int j) {
+ assert(j < jcp.ur);
+ assert(u <= jcp.reduce_loop_unroll);
+ size_t offt;
+ if (one_of(jcp.prop_kind,
+ forward_training, forward_inference, backward_data)) {
+ assert(jcp.reduce_loop_unroll == (jcp.prop_kind == backward_data)
+ ? jcp.oc_block : jcp.ic_block);
+ auto height = (jcp.prop_kind == backward_data) ? jcp.os : jcp.is;
+ offt = (u == jcp.reduce_loop_unroll)
+ ? (height + j) * jcp.reduce_loop_unroll
+ : j * jcp.reduce_loop_unroll + u;
+ } else
+ offt = u * jcp.ic_block + j;
+ return ptr[aux_reg_bcast_data + sizeof(float) * offt];
+ };
+
+ auto load_ptr = [=](int u, int i, int n) {
+ size_t offt;
+ size_t u0 = u % jcp.reduce_loop_unroll;
+ size_t u1 = u / jcp.reduce_loop_unroll;
+ switch (jcp.prop_kind) {
+ case backward_data:
+ offt = (i * jcp.oc_block + u0) * jcp.ic_block;
+ break;
+ case backward_weights:
+ offt = (i * jcp.os + u0) * jcp.oc_block;
+ break;
+ default:
+ offt = (i * jcp.ic + u0) * jcp.oc_block;
+ }
+ return ptr[aux_reg_load_data
+ + u1 * jcp.reduce_loop_load_step + sizeof(float) * offt + n * 4 * sizeof(float)];
+ };
+
+ auto output_ptr = [=](int i, int j, int n) {
+ switch (jcp.prop_kind) {
+ case backward_data:
+ return ptr[aux_reg_output_data +
+ (i * jcp.is + j) * jcp.ic_block * sizeof(float) + n * 4 * sizeof(float)];
+ case backward_weights:
+ return ptr[aux_reg_output_data
+ + (i ? reg_output_stride * i : 0) // TODO: Xbyak should allow 0 scale
+ + sizeof(float) * jcp.oc_block * j + n * 4 * sizeof(float)];
+ default:
+ return ptr[aux_reg_output_data +
+ (i * jcp.os + j) * jcp.oc_block * sizeof(float) + n*4*sizeof(float)];
+ }
+ };
+
+ auto init = [=]() {
+ Label init_done;
+ Label init_zero;
+
+ if (jcp.with_bias && one_of(jcp.prop_kind, forward_training,
+ forward_inference)) {
+ test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST);
+ jz(init_zero);
+
+ for (int i = 0; i < load_loop_blk; i++)
+ for (int j = 0; j < ur; ++j) {
+ movups(reg_accum(i, j, 0), bias_ptr(i, 0));
+ movups(reg_accum(i, j, 1), bias_ptr(i, 1));
+ }
+ jmp(init_done);
+ }
+
+ L(init_zero);
+ for (int i = 0; i < load_loop_blk; ++i)
+ for (int j = 0; j < ur; ++j) {
+ auto r0 = reg_accum(i, j, 0);
+ auto r1 = reg_accum(i, j, 1);
+ xorps(r0, r0);
+ xorps(r1, r1);
+ }
+
+ L(init_done);
+
+ // load weights
+ for (int i = 0; i < load_loop_blk; ++i) {
+ movups(reg_load(i, 0), load_ptr(0, i, 0));
+ movups(reg_load(i, 1), load_ptr(0, i, 1));
+ }
+
+ movss(reg_bcast, bcast_ptr(0, 0));
+ shufps(reg_bcast, reg_bcast, 0);
+ }; // init()
+
+ auto store = [=]() {
+ Label store_noadd;
+
+ if (!jcp.with_sum) {
+ test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST);
+ jnz(store_noadd, T_NEAR);
+ }
+
+ for (int j = 0; j < ur; ++j)
+ for (int i = 0; i < load_loop_blk; ++i) {
+ auto r0 = reg_accum(i, j, 0);
+ auto r1 = reg_accum(i, j, 1);
+ addps(r0, output_ptr(i, j, 0));
+ addps(r1, output_ptr(i, j, 1));
+ }
+
+ L(store_noadd);
+
+ if (jcp.with_eltwise) {
+ assert(ur * load_loop_blk < 14);
+
+ Label store_norelu;
+ test(reg_reduce_pos_flag, FLAG_REDUCE_LAST);
+ jz(store_norelu, T_NEAR);
+
+ eltwise_injector_->compute_vector_range(1,
+ 2 * ur * load_loop_blk + 1);
+
+ L(store_norelu);
+ }
+
+ for (int j = 0; j < ur; ++j)
+ for (int i = 0; i < load_loop_blk; ++i) {
+ movups(output_ptr(i, j, 0), reg_accum(i, j, 0));
+ movups(output_ptr(i, j, 1), reg_accum(i, j, 1));
+ }
+ };
+
+ auto fma_block = [=](bool last_block) {
+ for (int u = 0; u < jcp.reduce_loop_unroll; ++u) {
+ for (int j = 0; j < ur; ++j) {
+ for (int i = 0; i < load_loop_blk; ++i) {
+ mulps(reg_load(i, 0), reg_bcast);
+ mulps(reg_load(i, 1), reg_bcast);
+ addps(reg_accum(i, j, 0), reg_load(i, 0));
+ addps(reg_accum(i, j, 1), reg_load(i, 1));
+
+ if (j == ur - 1 && !(last_block && u == jcp.reduce_loop_unroll - 1)) {
+ movups(reg_load(i, 0), load_ptr(u + 1, i, 0));
+ movups(reg_load(i, 1), load_ptr(u + 1, i, 1));
+ }
+ }
+ if (j < ur - 1) {
+ movss(reg_bcast, bcast_ptr(u, j + 1));
+ shufps(reg_bcast, reg_bcast, 0);
+ }
+ } // for ur
+ if (!last_block || u < jcp.reduce_loop_unroll - 1) {
+ movss(reg_bcast, bcast_ptr(u + 1, 0));
+ shufps(reg_bcast, reg_bcast, 0);
+ }
+ } // for reduce_loop_unroll
+ };
+
+ Label reduce_loop;
+ Label reduce_loop_tail;
+
+ mov(aux_reg_load_data, reg_load_data);
+ mov(aux_reg_bcast_data, aux1_reg_bcast_data);
+
+ init();
+
+ mov(reduce_loop_iter, reg_reduce_loop_work);
+ sub(reduce_loop_iter, jcp.reduce_loop_unroll);
+ jle(reduce_loop_tail, T_NEAR);
+
+ L(reduce_loop); {
+ fma_block(false);
+ add(aux_reg_bcast_data, jcp.reduce_loop_bcast_step);
+ add(aux_reg_load_data, jcp.reduce_loop_load_step);
+ sub(reduce_loop_iter, jcp.reduce_loop_unroll);
+ jg(reduce_loop, T_NEAR);
+ }
+
+ L(reduce_loop_tail);
+ fma_block(true);
+
+ store();
+} // reduce_loop()
+
+void jit_sse42_1x1_conv_kernel_f32::generate_diff_bias_loop(int load_loop_blk)
+{
+ if (!jcp.with_bias || jcp.prop_kind != backward_weights)
+ return;
+
+ Label diff_bias_loop, diff_bias_loop_out, diff_bias_init_out;
+ Label diff_bias_load;
+
+ auto diff_bias_ptr = [=](int i, int n) {
+ return ptr[reg_diff_bias_data + i * jcp.oc_block * sizeof(float)+ 4*n*sizeof(float)];
+ };
+
+ auto load_ptr = [=](int u, int i, int n) {
+ return ptr[aux_reg_load_data
+ + (i * jcp.os + u) * jcp.oc_block * sizeof(float) + 4*n*sizeof(float)];
+ };
+
+ auto diff_bias_reg = [=](int i, int n) { return Xmm(2*i + n + 1); };
+
+ mov(reg_diff_bias_data, ptr[rsp + reg_diff_bias_data_stack_offt]);
+ cmp(reg_diff_bias_data, 0);
+ je(diff_bias_loop_out, T_NEAR);
+
+ test(reg_reduce_pos_flag, FLAG_REDUCE_FIRST);
+ jz(diff_bias_load, T_NEAR);
+
+ for (int i = 0; i < load_loop_blk; ++i) {
+ auto r0 = diff_bias_reg(i, 0);
+ auto r1 = diff_bias_reg(i, 1);
+ xorps(r0, r0);
+ xorps(r1, r1);
+ }
+ jmp(diff_bias_init_out, T_NEAR);
+
+ L(diff_bias_load);
+ for (int i = 0; i < load_loop_blk; ++i) {
+ movups(diff_bias_reg(i, 0), diff_bias_ptr(i, 0));
+ movups(diff_bias_reg(i, 1), diff_bias_ptr(i, 1));
+ }
+
+ L(diff_bias_init_out);
+ mov(aux_reg_load_data, reg_load_data);
+ mov(reduce_loop_iter, reg_reduce_loop_work);
+ L(diff_bias_loop); {
+ for(int u = 0; u < jcp.reduce_loop_unroll; ++u)
+ for (int i = 0; i < load_loop_blk; ++i) {
+ addps(diff_bias_reg(i, 0), load_ptr(u, i, 0));
+ addps(diff_bias_reg(i, 1), load_ptr(u, i, 1));
+ }
+ assert(jcp.reduce_dim % jcp.reduce_loop_unroll == 0);
+ add(aux_reg_load_data, jcp.reduce_loop_load_step);
+ sub(reduce_loop_iter, jcp.reduce_loop_unroll);
+ jnz(diff_bias_loop, T_NEAR);
+ }
+
+ for (int i = 0; i < load_loop_blk; i++) {
+ movups(diff_bias_ptr(i, 0), diff_bias_reg(i, 0));
+ movups(diff_bias_ptr(i, 1), diff_bias_reg(i, 1));
+ }
+
+ add(reg_diff_bias_data, load_loop_blk * jcp.oc_block * sizeof(float));
+ mov(ptr[rsp + reg_diff_bias_data_stack_offt], reg_diff_bias_data);
+
+ L(diff_bias_loop_out);
+}
+
+void jit_sse42_1x1_conv_kernel_f32::generate()
+{
+ preamble();
+
+ mov(reg_bcast_data, ptr[param1 + GET_OFF(bcast_data)]);
+ mov(reg_load_data, ptr[param1 + GET_OFF(load_data)]);
+ mov(reg_output_data, ptr[param1 + GET_OFF(output_data)]);
+ if (jcp.with_bias) {
+ if (jcp.prop_kind == backward_weights) {
+ sub(rsp, stack_space_needed);
+ mov(reg_diff_bias_data, ptr[param1 + GET_OFF(bias_data)]);
+ mov(ptr[rsp + reg_diff_bias_data_stack_offt], reg_diff_bias_data);
+ } else
+ mov(reg_bias_data, ptr[param1 + GET_OFF(bias_data)]);
+ }
+
+ mov(reg_load_loop_work, ptr[param1 + GET_OFF(load_dim)]);
+ mov(reg_bcast_loop_work, ptr[param1 + GET_OFF(bcast_dim)]);
+ mov(reg_reduce_loop_work, ptr[param1 + GET_OFF(reduce_dim)]);
+ mov(reg_reduce_pos_flag, ptr[param1 + GET_OFF(first_last_flag)]);
+ if (jcp.prop_kind == backward_weights)
+ mov(reg_output_stride, ptr[param1 + GET_OFF(output_stride)]);
+
+ auto generate_load_loop_body = [=] (int load_loop_blk) {
+ generate_bcast_loop(load_loop_blk);
+ add(reg_load_data, load_loop_blk * jcp.load_loop_load_step);
+ switch (jcp.prop_kind) {
+ case forward_training:
+ case forward_inference:
+ add(reg_bias_data, load_loop_blk * jcp.oc_block * sizeof(float));
+ add(reg_output_data,
+ load_loop_blk * jcp.os * jcp.oc_block * sizeof(float));
+ break;
+ case backward_data:
+ add(reg_output_data,
+ load_loop_blk * jcp.is * jcp.ic_block * sizeof(float));
+ break;
+ case backward_weights:
+ for (int i = 0; i < load_loop_blk; i++)
+ add(reg_output_data, reg_output_stride);
+ break;
+ default:
+ assert(!"invalid prop_kind");
+ }
+ sub(reg_load_loop_work, load_loop_blk * jcp.load_loop_iter_step);
+ };
+
+ Label load_loop_blk_8;
+ Label load_loop_blk_16;
+ Label load_loop_blk_24;
+ Label load_loop_blk_end;
+
+ cmp(reg_load_loop_work, 8);
+ jle(load_loop_blk_8, T_NEAR);
+
+ cmp(reg_load_loop_work, 32);
+ je(load_loop_blk_16, T_NEAR);
+
+ cmp(reg_load_loop_work, 16);
+ jle(load_loop_blk_16, T_NEAR);
+
+ L(load_loop_blk_24); {
+ generate_diff_bias_loop(3);
+ generate_load_loop_body(3);
+ cmp(reg_load_loop_work, 32);
+ je(load_loop_blk_16);
+ cmp(reg_load_loop_work, 24);
+ jge(load_loop_blk_24);
+ }
+
+ cmp(reg_load_loop_work, 8);
+ jle(load_loop_blk_8, T_NEAR);
+
+ L(load_loop_blk_16); {
+ generate_diff_bias_loop(2);
+ generate_load_loop_body(2);
+ cmp(reg_load_loop_work, 16);
+ jge(load_loop_blk_16);
+ }
+
+ L(load_loop_blk_8); {
+ cmp(reg_load_loop_work, 0);
+ je(load_loop_blk_end, T_NEAR);
+ generate_diff_bias_loop(1);
+ generate_load_loop_body(1);
+ }
+
+ L(load_loop_blk_end);
+
+ if (jcp.with_bias && jcp.prop_kind == backward_weights)
+ add(rsp, stack_space_needed);
+
+ postamble();
+
+ if (jcp.with_eltwise)
+ eltwise_injector_->prepare_table();
+}
+
+bool jit_sse42_1x1_conv_kernel_f32::post_ops_ok(
+ jit_1x1_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ const auto &p = attr.post_ops_;
+
+ auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); };
+ auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); };
+
+ switch (p.len_) {
+ case 0: return true; // no post_ops
+ case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise
+ case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise
+ default: return false;
+ }
+
+ return false;
+}
+
+status_t jit_sse42_1x1_conv_kernel_f32::init_conf(jit_1x1_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d,
+ const primitive_attr_t &attr)
+{
+ if (!mayiuse(sse42))
+ return status::unimplemented;
+
+ // TODO (Roma): this code is duplicated from the generic kernel; maybe the
+ // configuration struct could do some stuff below
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ const int ndims = src_d.ndims();
+
+ jcp.prop_kind = cd.prop_kind;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+
+ jcp.ih = (ndims == 3) ? 1 : src_d.dims()[2];
+ jcp.iw = src_d.dims()[ndims - 1];
+ jcp.oh = (ndims == 3) ? 1 : dst_d.dims()[2];
+ jcp.ow = dst_d.dims()[ndims - 1];
+
+ jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + 2];
+ jcp.kw = weights_d.dims()[with_groups + ndims - 1];
+
+ jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][ndims - 3];
+
+ jcp.stride_h = (ndims == 3) ? 1 : cd.strides[0];
+ jcp.stride_w = cd.strides[ndims - 3];
+
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ jcp.os = jcp.oh * jcp.ow;
+ jcp.is = jcp.ih * jcp.iw;
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ jcp.with_sum = p.find(primitive_kind::sum) != -1;
+ const int eltwise_ind = p.find(primitive_kind::eltwise);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise)
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+
+ const int is_bwd_d = jcp.prop_kind == backward_data;
+
+ format_tag_t dat_tag = ndims == 3 ? nCw8c : nChw8c;
+ format_tag_t wei_tag = with_groups
+ ? utils::pick(2 * ndims - 6 + is_bwd_d, gOIw8i8o, gOIw8o8i, gOIhw8i8o,
+ gOIhw8o8i)
+ : utils::pick(2 * ndims - 6 + is_bwd_d, OIw8i8o, OIw8o8i, OIhw8i8o,
+ OIhw8o8i);
+
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag);
+ jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag);
+
+ bool args_ok = true
+ && jcp.ngroups == 1
+ && jcp.src_tag == dat_tag
+ && jcp.wei_tag == wei_tag
+ && jcp.dst_tag == dat_tag;
+ if (!args_ok) return status::unimplemented;
+
+ const int simd_w = 4;
+ jcp.ic_block = jcp.oc_block = simd_w*2;
+
+ args_ok = true
+ && jcp.oc % jcp.oc_block == 0
+ && jcp.ic % jcp.ic_block == 0
+ && jcp.t_pad == 0 && jcp.l_pad == 0
+ && jcp.stride_w == 1 && jcp.stride_h == 1 // TODO: support some strides
+ && jcp.kh == 1 && jcp.kw == 1;
+ if (!args_ok) return status::unimplemented;
+
+ jcp.ur = 1;
+
+ int load_blocking{ 0 };
+ int load_blocking_max{ 0 };
+ int bcast_blocking{ 0 };
+ int bcast_blocking_max{ 0 };
+ int reduce_blocking{ 0 };
+
+ if (one_of(jcp.prop_kind, forward_training, forward_inference)) {
+ jcp.reduce_dim = jcp.ic;
+ jcp.reduce_block = jcp.ic_block;
+
+ jcp.load_dim = jcp.oc;
+ jcp.load_block = jcp.oc_block;
+
+ jcp.bcast_dim = jcp.is;
+ jcp.bcast_block = jcp.ur;
+
+ jcp.reduce_loop_unroll = jcp.reduce_block;
+ jcp.reduce_loop_bcast_step
+ = jcp.reduce_loop_unroll * jcp.is * sizeof(float);
+ jcp.reduce_loop_load_step
+ = jcp.reduce_loop_unroll * jcp.oc_block * sizeof(float);
+
+ jcp.bcast_loop_output_step = jcp.ur * jcp.oc_block * sizeof(float);
+ jcp.bcast_loop_output_substep = -1; // unused
+ jcp.bcast_loop_bcast_step = jcp.ur * jcp.ic_block * sizeof(float);
+ jcp.bcast_loop_bcast_substep = -1; // unused
+
+ jcp.load_loop_load_step = jcp.ic * jcp.oc_block * sizeof(float);
+ jcp.load_loop_iter_step = jcp.oc_block;
+
+ load_blocking = 120; // assumes the kernel is jcp.ur x 3
+ load_blocking_max = 144;
+ bcast_blocking = 128; // affects load balancing across threads
+ bcast_blocking_max = 192;
+ reduce_blocking = 128; // affects L1$ utilization
+ } else if (jcp.prop_kind == backward_data) {
+ jcp.reduce_dim = jcp.oc;
+ jcp.reduce_block = jcp.oc_block;
+
+ jcp.load_dim = jcp.ic;
+ jcp.load_block = jcp.oc_block;
+
+ jcp.bcast_dim = jcp.os;
+ jcp.bcast_block = jcp.ur;
+
+ jcp.reduce_loop_unroll = jcp.reduce_block;
+ jcp.reduce_loop_bcast_step
+ = jcp.reduce_loop_unroll * jcp.os * sizeof(float);
+ jcp.reduce_loop_load_step
+ = jcp.reduce_loop_unroll * jcp.ic * sizeof(float);
+
+ jcp.bcast_loop_output_step = jcp.ur * jcp.ic_block * sizeof(float);
+ jcp.bcast_loop_output_substep = -1; // unused
+ jcp.bcast_loop_bcast_step = jcp.ur * jcp.oc_block * sizeof(float);
+ jcp.bcast_loop_bcast_substep = -1; // unused
+
+ jcp.load_loop_load_step = jcp.oc_block * jcp.ic_block * sizeof(float);
+ jcp.load_loop_iter_step = jcp.ic_block;
+
+ load_blocking = 96; // assumes the kernel is jcp.ur x 3
+ load_blocking_max = 144;
+ bcast_blocking = 128; // affects load balancing across threads
+ bcast_blocking_max = 196;
+ reduce_blocking = 64; // affects L1$ utilization
+ } else if (jcp.prop_kind == backward_weights) {
+ jcp.reduce_dim = jcp.os;
+ jcp.reduce_block = 1;
+
+ jcp.load_dim = jcp.oc;
+ jcp.load_block = jcp.oc_block;
+
+ jcp.bcast_dim = jcp.ic;
+ jcp.bcast_block = jcp.ic_block;
+
+ jcp.reduce_loop_unroll = jcp.reduce_block;
+ jcp.reduce_loop_bcast_step
+ = jcp.reduce_loop_unroll * jcp.ic_block * sizeof(float);
+ jcp.reduce_loop_load_step
+ = jcp.reduce_loop_unroll * jcp.oc_block * sizeof(float);
+
+ jcp.bcast_loop_output_step = jcp.oc_block * jcp.ic_block * sizeof(float);
+ jcp.bcast_loop_output_substep = jcp.oc_block * jcp.ur * sizeof(float);
+ jcp.bcast_loop_bcast_step = jcp.ic_block * jcp.is * sizeof(float);
+ jcp.bcast_loop_bcast_substep = jcp.ur * sizeof(float);
+
+ jcp.load_loop_load_step = jcp.oc_block * jcp.os * sizeof(float);
+ jcp.load_loop_iter_step = jcp.oc_block;
+
+ /* --- */
+
+ load_blocking = div_up(jcp.load_dim, jcp.load_block);
+ while (true) {
+ if (load_blocking <= 32) break;
+ else if (load_blocking % 2 == 0) load_blocking /= 2;
+ else if (load_blocking % 3 == 0) load_blocking /= 3;
+ else break;
+ }
+ load_blocking *= jcp.load_block;
+ load_blocking_max = load_blocking;
+ assert(jcp.load_dim % load_blocking == 0);
+
+ bcast_blocking = div_up(jcp.bcast_dim, jcp.bcast_block);
+ while (true) {
+ if (bcast_blocking <= 9) break;
+ else if (bcast_blocking % 2 == 0) bcast_blocking /= 2;
+ else if (bcast_blocking % 3 == 0) bcast_blocking /= 3;
+ else break;
+ }
+ bcast_blocking *= jcp.bcast_block;
+ bcast_blocking_max = bcast_blocking;
+ assert(jcp.bcast_dim % bcast_blocking == 0);
+
+ reduce_blocking = 128; // affects L1$ utilization
+ } else
+ return status::unimplemented;
+
+ assert(load_blocking);
+ assert(load_blocking_max);
+ assert(bcast_blocking);
+ assert(bcast_blocking_max);
+ assert(reduce_blocking);
+
+ assert(jcp.bcast_block % jcp.ur == 0);
+ jcp.ur_tail = jcp.bcast_dim % jcp.ur;
+
+ jcp.nb_bcast_blocking = bcast_blocking / jcp.bcast_block;
+ jcp.nb_bcast_blocking_max = bcast_blocking_max / jcp.bcast_block;
+ jcp.nb_load_blocking = load_blocking / jcp.load_block;
+ jcp.nb_load_blocking_max = load_blocking_max / jcp.load_block;
+ jcp.nb_reduce_blocking = reduce_blocking / jcp.reduce_block;
+
+ jcp.nb_bcast = div_up(jcp.bcast_dim, jcp.bcast_block);
+ jcp.nb_load = div_up(jcp.load_dim, jcp.load_block);
+ jcp.nb_reduce = div_up(jcp.reduce_dim, jcp.reduce_block);
+
+ return status::success;
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.hpp
new file mode 100644
index 0000000000..b314a5098c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_conv_kernel_f32.hpp
@@ -0,0 +1,104 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_SSE42_1x1_CONV_KERNEL_F32_HPP
+#define JIT_SSE42_1x1_CONV_KERNEL_F32_HPP
+
+#include "c_types_map.hpp"
+#include "cpu_memory.hpp"
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+#include "jit_uni_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_sse42_1x1_conv_kernel_f32: public jit_generator {
+ jit_sse42_1x1_conv_kernel_f32(jit_1x1_conv_conf_t ajcp,
+ const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr)
+ {
+ if (jcp.with_eltwise)
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<sse42>(this,
+ jcp.eltwise);
+
+ this->generate();
+ jit_ker = (void (*)(jit_1x1_conv_call_s *))this->getCode();
+ }
+
+ ~jit_sse42_1x1_conv_kernel_f32() {
+ delete eltwise_injector_;
+ }
+
+ static bool post_ops_ok(jit_1x1_conv_conf_t &jcp,
+ const primitive_attr_t &attr);
+
+ static status_t init_conf(jit_1x1_conv_conf_t &jcp,
+ const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d,
+ const primitive_attr_t &attr);
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_sse42_1x1_conv_kernel_f32)
+
+ jit_1x1_conv_conf_t jcp;
+ const primitive_attr_t &attr_;
+ void (*jit_ker)(jit_1x1_conv_call_s *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ using xmm_t = const Xbyak::Xmm;
+
+ reg64_t reg_bcast_data = rax;
+ reg64_t reg_load_data = rsi;
+ reg64_t reg_output_data = rbx;
+ reg64_t aux_reg_bcast_data = rdx;
+ reg64_t aux1_reg_bcast_data = abi_not_param1;
+ reg64_t aux_reg_load_data = abi_param1;
+ reg64_t aux_reg_output_data = rbp;
+ reg64_t reg_load_loop_work = r9;
+ reg64_t reg_bcast_loop_work = r10;
+ reg64_t reg_reduce_loop_work = r11;
+ reg64_t load_loop_iter = r13;
+ reg64_t imm_addr64 = load_loop_iter;
+ reg64_t bcast_loop_iter = r14;
+ reg64_t reduce_loop_iter = r15;
+ reg64_t reg_reduce_pos_flag = r8;
+ reg64_t reg_output_stride = r12;
+ reg64_t reg_bias_data = r12;
+ reg64_t reg_diff_bias_data = bcast_loop_iter;
+
+ int reg_diff_bias_data_stack_offt = 0;
+ int stack_space_needed = 8;
+
+ xmm_t reg_bcast = xmm_t(15);
+
+ jit_uni_eltwise_injector_f32<sse42> *eltwise_injector_;
+
+ void generate_bcast_loop(int load_loop_blk);
+ void generate_reduce_loop(int load_loop_blk, int ur);
+ void generate_diff_bias_loop(int load_loop_blk);
+
+ void generate();
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.cpp
new file mode 100644
index 0000000000..30c137641e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.cpp
@@ -0,0 +1,134 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn_types.h"
+
+#include "c_types_map.hpp"
+#include "jit_sse42_1x1_convolution.hpp"
+#include "utils.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+#define data_blk_off(f, n, c, h, w) \
+ ((ndims == 3) \
+ ? (f).blk_off(n, c, w) \
+ : (f).blk_off(n, c, h, w))
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::utils;
+
+void jit_sse42_1x1_convolution_fwd_t::execute_forward(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+ const int ndims = src_d.ndims();
+
+ const int work_amount = jcp.mb * jcp.ngroups * jcp.nb_bcast;
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ // TODO (Roma): remove this restriction
+ assert(jcp.stride_w == 1 && jcp.stride_h == 1);
+
+ auto par_conv = jit_1x1_conv_call_s();
+
+ const int nb_oc = jcp.nb_load;
+ const int nb_ic = jcp.nb_reduce;
+ const int nb_ic_blocking = jcp.nb_reduce_blocking;
+ const int os_block = jcp.bcast_block;
+
+ int start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+
+ int iwork = start;
+ while (iwork < end) {
+ int n{0}, g{0}, osb{0};
+ nd_iterator_init(iwork, n, jcp.mb, g, jcp.ngroups, osb,
+ jcp.nb_bcast);
+
+ const int bcast_step_rem = jcp.nb_bcast - osb;
+ int bcast_step = bcast_step_rem <= jcp.nb_bcast_blocking_max
+ ? bcast_step_rem : jcp.nb_bcast_blocking;
+ bcast_step = nstl::min<int>(bcast_step, end - iwork);
+
+ const int os = osb * os_block;
+ const int ow = os % jcp.ow;
+ const int oh = os / jcp.ow;
+ const int iw = nstl::max<int>(ow * jcp.stride_w - jcp.l_pad, 0);
+ const int ih = nstl::max<int>(oh * jcp.stride_h - jcp.t_pad, 0);
+
+ par_conv.bcast_dim = this_block_size(os, jcp.os,
+ bcast_step * os_block);
+
+ int ocb = 0;
+ while (ocb < jcp.nb_load) {
+ const int load_step_rem = jcp.nb_load - ocb;
+ const int load_step = load_step_rem < jcp.nb_load_blocking_max
+ ? load_step_rem : jcp.nb_load_blocking;
+
+ const size_t _ocb = g * nb_oc + ocb;
+ par_conv.load_dim = this_block_size(ocb * jcp.oc_block, jcp.oc,
+ load_step * jcp.oc_block);
+
+ const size_t dst_off = data_blk_off(dst_d, n, _ocb, oh, ow);
+ par_conv.output_data = &dst[dst_off];
+
+ par_conv.bias_data = &bias[_ocb * jcp.oc_block];
+
+ for (int icb = 0; icb < nb_ic; icb += nb_ic_blocking) {
+ par_conv.first_last_flag = 0
+ | (icb == 0) * FLAG_REDUCE_FIRST
+ | (icb + nb_ic_blocking >= nb_ic) * FLAG_REDUCE_LAST;
+
+ par_conv.reduce_dim = this_block_size(icb * jcp.ic_block,
+ jcp.ic, nb_ic_blocking * jcp.ic_block);
+
+ const size_t _icb = g * nb_ic + icb;
+ const size_t src_off = data_blk_off(src_d, n, _icb, ih, iw);
+ par_conv.bcast_data = &src[src_off];
+
+ par_conv.load_data = &weights[pd()->with_groups()
+ ? weights_d.blk_off(g, ocb, icb)
+ : weights_d.blk_off(ocb, icb)];
+
+ kernel_->jit_ker(&par_conv);
+ }
+
+ ocb += load_step;
+ }
+
+ iwork += bcast_step;
+ }
+ });
+
+ if (pd()->wants_zero_pad_dst())
+ ctx.memory(MKLDNN_ARG_DST)->zero_pad();
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.hpp
new file mode 100644
index 0000000000..b32b1e4784
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_1x1_convolution.hpp
@@ -0,0 +1,96 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_SSE42_1x1_CONVOLUTION_HPP
+#define CPU_JIT_SSE42_1x1_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+#include "jit_sse42_1x1_conv_kernel_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_sse42_1x1_convolution_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_1x1:", sse42, ""),
+ jit_sse42_1x1_convolution_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ return jit_sse42_1x1_conv_kernel_f32::init_conf(jcp_, *desc(),
+ *src_md(), *weights_md(), *dst_md(), *attr());
+ }
+
+ jit_1x1_conv_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto wei_tag = with_groups()
+ ? utils::pick(ndims() - 3, gOIw8i8o, gOIhw8i8o)
+ : utils::pick(ndims() - 3, OIw8i8o, OIhw8i8o);
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ jit_sse42_1x1_convolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {
+ kernel_ = new jit_sse42_1x1_conv_kernel_f32(pd()->jcp_, *pd()->attr());
+ }
+ ~jit_sse42_1x1_convolution_fwd_t() { delete kernel_; };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ jit_sse42_1x1_conv_kernel_f32 *kernel_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.cpp
new file mode 100644
index 0000000000..17cabc1186
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.cpp
@@ -0,0 +1,497 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "cpu_memory.hpp"
+
+#include "jit_sse42_conv_kernel_f32.hpp"
+
+#define GET_OFF(field) offsetof(jit_conv_call_s, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::utils;
+
+using namespace Xbyak;
+
+void jit_sse42_conv_fwd_kernel_f32::oh_step_unroll_kw(int ur_w,
+ int pad_l, int pad_r, int oc_blocks)
+{
+ int iw = jcp.iw;
+ int ih = jcp.ih;
+ int kw = jcp.kw;
+ int kh = jcp.kh;
+ int nb_ic = jcp.nb_ic;
+ int stride_w = jcp.stride_w;
+ int dilate_w = jcp.dilate_w + 1;
+ int ic_blk = jcp.ic_block;
+ int oc_blk = jcp.oc_block;
+
+ for (int ki = 0; ki < kw; ki++) {
+ int jj_start = nstl::max(0, div_up(pad_l - ki * dilate_w, stride_w));
+ int jj_end = ur_w
+ - nstl::max(0, div_up(ki*dilate_w + pad_r - (kw-1)*dilate_w, stride_w));
+ for (int ifm2 = 0; ifm2 < ic_blk; ifm2++) {
+ for (int jj = jj_start; jj < jj_end; jj++) {
+ int inp_off;
+ if (one_of(jcp.src_tag, ncw, nchw))
+ inp_off = ifm2*ih*iw + (ki*dilate_w + jj*stride_w - pad_l);
+ else
+ inp_off = (ki*dilate_w + jj*stride_w - pad_l)*ic_blk + ifm2;
+
+ movss(Xmm(oc_blocks * ur_w + jj + 1),
+ ptr[aux_reg_input + sizeof(float) * inp_off]);
+ shufps(Xmm(oc_blocks * ur_w + jj + 1),
+ Xmm(oc_blocks * ur_w + jj + 1), 0x0);
+ }
+
+ for (int ii = 0; ii < oc_blocks; ii++) {
+ int ker_off = ii * nb_ic * kh * kw * ic_blk * oc_blk
+ + ki * ic_blk * oc_blk + ifm2 * oc_blk;
+
+ for (int jj = jj_start; jj < jj_end; jj++)
+ {
+ movups(xmm0,
+ ptr[aux_reg_kernel + sizeof(float) * ker_off]);
+ mulps(xmm0, Xmm(oc_blocks * ur_w + jj + 1));
+ addps(Xmm(ur_w * ii + jj + 1), xmm0);
+ }
+ }
+ }
+ }
+}
+
+void jit_sse42_conv_fwd_kernel_f32::oh_step_nopad(int ur_w,
+ int pad_l, int pad_r, int oc_blocks)
+{
+ Label kw_loop;
+
+ int iw = jcp.iw;
+ int ih = jcp.ih;
+ int kw = jcp.kw;
+ int kh = jcp.kh;
+ int nb_ic = jcp.nb_ic;
+ int stride_w = jcp.stride_w;
+ int dilate_w = jcp.dilate_w + 1;
+ int ic_blk = jcp.ic_block;
+ int oc_blk = jcp.oc_block;
+
+ xor_(ki_iter, ki_iter);
+ L(kw_loop);
+ {
+ int jj_start = 0;
+ int jj_end = ur_w;
+ for (int ifm2 = 0; ifm2 < ic_blk; ifm2++) {
+ for (int jj = jj_start; jj < jj_end; jj++) {
+ int inp_off;
+ if (one_of(jcp.src_tag, ncw, nchw))
+ inp_off = ifm2 * ih * iw + (jj * stride_w - pad_l);
+ else
+ inp_off = (jj * stride_w - pad_l) * ic_blk + ifm2;
+
+ movss(Xmm(oc_blocks * ur_w + jj + 1),
+ ptr[aux_reg_input + sizeof(float) * inp_off]);
+ shufps(Xmm(oc_blocks * ur_w + jj + 1),
+ Xmm(oc_blocks * ur_w + jj + 1), 0x0);
+ }
+ for (int ii = 0; ii < oc_blocks; ii++) {
+ int aux_kernel_offset = ii * nb_ic * kh * kw * ic_blk * oc_blk
+ + ifm2 * oc_blk;
+ for (int jj = jj_start; jj < jj_end; jj++) {
+ movups(xmm0,
+ ptr[aux_reg_kernel + sizeof(float) * aux_kernel_offset]);
+ mulps(xmm0, Xmm(oc_blocks * ur_w + jj + 1));
+ addps(Xmm(ur_w * ii + jj + 1), xmm0);
+ }
+ }
+ }
+ add(aux_reg_kernel, sizeof(float) * oc_blk * ic_blk);
+ add(aux_reg_input, sizeof(float) * (one_of(jcp.src_tag, ncw, nchw) ?
+ dilate_w : ic_blk * dilate_w));
+
+ inc(ki_iter);
+ cmp(ki_iter, kw);
+ jl(kw_loop, T_NEAR);
+ }
+}
+
+void jit_sse42_conv_fwd_kernel_f32::width_blk_step(int ur_w,
+ int pad_l, int pad_r, int oc_blocks)
+{
+ int iw = jcp.iw;
+ int kw = jcp.kw;
+ int ow = jcp.ow;
+ int oh = jcp.oh;
+ int dilate_h = jcp.dilate_h + 1;
+ int dilate_w = jcp.dilate_w + 1;
+ int ic_blk = jcp.ic_block;
+ int oc_blk = jcp.oc_block;
+ const int inp_mult = one_of(jcp.src_tag, ncw, nchw)
+ ? dilate_h : ic_blk * dilate_h;
+ const int inp_off = one_of(jcp.src_tag, ncw, nchw)
+ ? dilate_w : ic_blk * dilate_w;
+
+ xor_(simd_iter, simd_iter);
+
+ mov(aux_reg_input, reg_input);
+ mov(aux_reg_kernel, reg_kernel);
+
+ Label init_simd_iter_loop;
+ Label init_done;
+ Label init_first;
+
+ L(init_simd_iter_loop);
+
+ if (!jcp.with_sum) {
+ test(reg_ci_flag, FLAG_IC_FIRST);
+ jne(init_first, T_NEAR);
+ }
+
+ for (int ii = 0; ii < oc_blocks; ii++)
+ for (int jj = 0; jj < ur_w; jj++)
+ movups(Xmm(ur_w * ii + jj + 1), xword[reg_output
+ + sizeof(float) * (ii * oh * ow + jj) * oc_blk]);
+
+ if (jcp.with_sum && jcp.with_bias) {
+ test(reg_ci_flag, FLAG_IC_FIRST);
+ je(init_done, T_NEAR);
+
+ for (int ii = 0; ii < oc_blocks; ii++)
+ for (int jj = 0; jj < ur_w; jj++)
+ addps(Xmm(ur_w * ii + jj + 1),
+ xword[reg_bias + sizeof(float) * ii * oc_blk]);
+ }
+
+ jmp(init_done);
+
+ L(init_first);
+ if (this->jcp.with_bias) {
+ for (int ii = 0; ii < oc_blocks; ii++)
+ for (int jj = 0; jj < ur_w; jj++)
+ movups(Xmm(ur_w * ii + jj + 1),
+ xword[reg_bias + sizeof(float) * ii * oc_blk]);
+ } else {
+ for (int ii = 0; ii < oc_blocks; ii++)
+ for (int jj = 0; jj < ur_w; jj++)
+ pxor(Xmm(ur_w * ii + jj + 1), Xmm(ur_w * ii + jj + 1));
+ }
+
+ L(init_done);
+
+ Label skip_kh_loop;
+ mov(kj, reg_kh);
+ if ((jcp.dilate_h >= jcp.ih)
+ || (jcp.kh - 1) * (jcp.dilate_h + 1) < nstl::max(jcp.t_pad, jcp.b_pad)) {
+ cmp(kj, 0);
+ je(skip_kh_loop, T_NEAR);
+ }
+ Label kh_loop;
+ L(kh_loop);
+ {
+ if (jcp.kw >= 5 && pad_l == 0 && pad_r == 0) {
+ oh_step_nopad(ur_w, pad_l, pad_r, oc_blocks);
+ sub(aux_reg_input, sizeof(float) * kw * inp_off);
+ add(aux_reg_input, sizeof(float) * iw * inp_mult);
+ } else {
+ oh_step_unroll_kw(ur_w, pad_l, pad_r, oc_blocks);
+ add(aux_reg_kernel, sizeof(float) * kw * oc_blk * ic_blk);
+ add(aux_reg_input, sizeof(float) * iw * inp_mult);
+ }
+
+ dec(kj);
+ cmp(kj, 0);
+ jg(kh_loop, T_NEAR);
+ }
+
+ L(skip_kh_loop);
+
+ if (jcp.with_eltwise) {
+ Label regular_store;
+ test(reg_ci_flag, FLAG_IC_LAST);
+ je(regular_store, T_NEAR);
+
+ eltwise_injector_->compute_vector_range(1, oc_blocks * ur_w + 1);
+
+ L(regular_store);
+ }
+
+ for (int ii = 0; ii < oc_blocks; ii++) {
+ for (int jj = 0; jj < ur_w; jj++) {
+ const size_t o_off = (ii * oh * ow + jj) * oc_blk;
+
+ Xmm reg_out = Xmm(ur_w * ii + jj + 1);
+ movups(xword[reg_output + sizeof(float) * o_off], reg_out);
+ }
+ }
+
+ mov(aux_reg_kernel, reg_kernel);
+ mov(aux_reg_input, reg_input);
+ add(aux_reg_kernel, sizeof(float) * 4);
+ add(reg_output, sizeof(float) * 4);
+ add(reg_bias, sizeof(float) * 4);
+
+ inc(simd_iter);
+ cmp(simd_iter, 2);
+ jl(init_simd_iter_loop, T_NEAR);
+
+ sub(reg_output, sizeof(float) * 8);
+ sub(reg_bias, sizeof(float) * 8);
+}
+
+inline void jit_sse42_conv_fwd_kernel_f32::solve_common(int oc_blocks)
+{
+ int ur_w = jcp.ur_w;
+ int ur_w_tail = jcp.ur_w_tail;
+ int n_oi = jcp.ow / ur_w;
+ int iw = jcp.iw;
+ int kw = jcp.kw;
+ int ic_blk = jcp.ic_block;
+ int oc_blk = jcp.oc_block;
+ int dilate_w = jcp.dilate_w + 1;
+ int str_w = jcp.stride_w;
+ const int inp_mult = one_of(jcp.src_tag, ncw, nchw) ? 1 : ic_blk;
+
+ int l_pad = jcp.l_pad;
+ int r_pad = nstl::max(0, (int(jcp.ow) - 1) * str_w + (kw - 1) * dilate_w
+ - (iw + l_pad - 1));
+ int r_pad1 = (ur_w * n_oi - 1) * str_w + (kw - 1) * dilate_w
+ - (iw + l_pad - 1);
+ if (r_pad1 > 0) n_oi--;
+
+ if (l_pad > 0) {
+ n_oi--;
+ if (n_oi < 0 && r_pad1 > 0)
+ width_blk_step(ur_w, l_pad, r_pad1, oc_blocks); // "lrpad"
+ else
+ width_blk_step(ur_w, l_pad, 0, oc_blocks); // "lpad"
+ add(reg_input, sizeof(float) * (ur_w * str_w - l_pad) * inp_mult);
+ add(reg_output, sizeof(float) * ur_w * oc_blk);
+ }
+
+ Label ow_loop;
+ xor_(oi_iter, oi_iter);
+
+ if (n_oi > 0) {
+ L(ow_loop);
+
+ width_blk_step(ur_w, 0, 0, oc_blocks); // "middle"
+ add(reg_input, sizeof(float) * ur_w * str_w * inp_mult);
+ add(reg_output, sizeof(float) * ur_w * oc_blk);
+
+ inc(oi_iter);
+ cmp(oi_iter, n_oi);
+ jl(ow_loop, T_NEAR);
+ }
+
+ if (r_pad1 > 0 && n_oi >=0) {
+ width_blk_step(ur_w, 0, r_pad1, oc_blocks); // "rpad"
+ add(reg_input, sizeof(float) * ur_w * str_w * inp_mult);
+ add(reg_output, sizeof(float) * ur_w * oc_blk);
+ }
+
+ if (ur_w_tail != 0)
+ width_blk_step(ur_w_tail, 0, r_pad, oc_blocks); // "tail"
+}
+
+void jit_sse42_conv_fwd_kernel_f32::generate()
+{
+ this->preamble();
+
+ mov(reg_input, ptr[this->param1 + GET_OFF(src)]);
+ mov(reg_output, ptr[this->param1 + GET_OFF(dst)]);
+ mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]);
+ if (jcp.with_bias)
+ mov(reg_bias, ptr[this->param1 + GET_OFF(bias)]);
+ mov(reg_kh, ptr[this->param1 + GET_OFF(kh_padding)]);
+ mov(reg_ci_flag, ptr[this->param1 + GET_OFF(flags)]);
+ mov(reg_oc_blocks, ptr[this->param1 + GET_OFF(oc_blocks)]);
+
+ int nb_oc_tail = jcp.nb_oc % jcp.nb_oc_blocking;
+ Label tail, exit;
+
+ cmp(reg_oc_blocks, jcp.nb_oc_blocking);
+ jne(nb_oc_tail ? tail : exit, T_NEAR);
+
+ solve_common(jcp.nb_oc_blocking);
+ jmp(exit, T_NEAR);
+
+ if (nb_oc_tail) {
+ L(tail);
+ cmp(reg_oc_blocks, nb_oc_tail);
+ jne(exit, T_NEAR);
+ solve_common(nb_oc_tail);
+ }
+
+ L(exit);
+
+ this->postamble();
+
+ if (jcp.with_eltwise)
+ eltwise_injector_->prepare_table();
+}
+
+bool jit_sse42_conv_fwd_kernel_f32::post_ops_ok(
+ jit_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ const auto &p = attr.post_ops_;
+
+ auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); };
+ auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); };
+
+ switch (p.len_) {
+ case 0: return true; // no post_ops
+ case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise
+ case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise
+ default: return false;
+ }
+
+ return false;
+}
+
+status_t jit_sse42_conv_fwd_kernel_f32::init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d,
+ const primitive_attr_t &attr)
+{
+ if (!mayiuse(sse42)) return status::unimplemented;
+
+ jcp.prop_kind = cd.prop_kind;
+
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ const int ndims = src_d.ndims();
+ jcp.ndims = ndims;
+
+ jcp.ngroups = with_groups ? weights_d.dims()[0] : 1;
+ jcp.mb = src_d.dims()[0];
+
+ jcp.oc = dst_d.dims()[1] / jcp.ngroups;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+
+ jcp.ih = (ndims == 3) ? 1 : src_d.dims()[2];
+ jcp.iw = src_d.dims()[ndims - 1];
+ jcp.oh = (ndims == 3) ? 1 : dst_d.dims()[2];
+ jcp.ow = dst_d.dims()[ndims - 1];
+
+ jcp.kh = (ndims == 3) ? 1 : weights_d.dims()[with_groups + 2];
+ jcp.kw = weights_d.dims()[with_groups + ndims - 1];
+
+ jcp.t_pad = (ndims == 3) ? 0 : cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][ndims - 3];
+
+ jcp.stride_h = (ndims == 3) ? 1 : cd.strides[0];
+ jcp.stride_w = cd.strides[ndims - 3];
+
+ jcp.dilate_h = (ndims == 3) ? 0 : cd.dilates[0];
+ jcp.dilate_w = cd.dilates[ndims - 3];
+ jcp.b_pad = (jcp.oh - 1) * jcp.stride_h + (jcp.kh - 1) * (jcp.dilate_h + 1)
+ - (jcp.ih + jcp.t_pad - 1);
+
+ if (ndims == 3) {
+ jcp.src_tag = src_d.matches_one_of_tag(ncw, nwc, nCw8c);
+ jcp.wei_tag = weights_d.matches_one_of_tag(
+ Owi8o, gOwi8o, OIw8i8o, gOIw8i8o);
+ jcp.dst_tag = dst_d.matches_one_of_tag(nCw8c);
+ } else if (ndims == 4) {
+ jcp.src_tag = src_d.matches_one_of_tag(nchw, nhwc, nChw8c);
+ jcp.wei_tag = weights_d.matches_one_of_tag(
+ Ohwi8o, gOhwi8o, OIhw8i8o, gOIhw8i8o);
+ jcp.dst_tag = dst_d.matches_one_of_tag(nChw8c);
+ }
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ jcp.with_sum = p.find(primitive_kind::sum) != -1;
+ const int eltwise_ind = p.find(primitive_kind::eltwise);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise)
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+
+ const bool flat = jcp.ic == 3;
+ const bool mimo = !flat;
+
+ bool args_ok = true
+ && IMPLICATION(flat, one_of(jcp.src_tag, ncw, nwc, nchw, nhwc)
+ && one_of(jcp.wei_tag, Owi8o, gOwi8o, Ohwi8o, gOhwi8o))
+ && IMPLICATION(mimo, one_of(jcp.src_tag, nCw8c, nChw8c)
+ && one_of(jcp.wei_tag, OIw8i8o, gOIw8i8o, OIhw8i8o, gOIhw8i8o))
+ && one_of(jcp.dst_tag, nCw8c, nChw8c);
+ if (!args_ok) return status::unimplemented;
+
+ const int simd_w = 8; // 2 SSE vectors processing at once
+
+ jcp.ur_h = 1; /* no code-unrolling by h so far */
+ jcp.ur_w = 3;
+ if (jcp.ow < jcp.ur_w) jcp.ur_w = jcp.ow;
+ jcp.ur_w_tail = jcp.ow % jcp.ur_w;
+
+ jcp.nb_oc_blocking = 4; /* the optimal value for the kernel */
+
+ args_ok = true
+ && jcp.oc % simd_w == 0
+ && jcp.l_pad <= jcp.ur_w
+ && IMPLICATION(jcp.kw > 7, (jcp.t_pad == 0 && jcp.l_pad == 0)
+ || (jcp.stride_w == 1 && jcp.stride_h == 1))
+ && IMPLICATION(mimo, jcp.ic % simd_w == 0);
+ if (!args_ok) return status::unimplemented;
+
+ int r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1));
+
+ // kernel needs 1 temporary YMM register
+ const int num_avail_regs = 15;
+ if (r_pad_no_tail > jcp.ur_w * jcp.stride_w && jcp.ow / jcp.ur_w > 1) {
+ /* recalculate ur_w, nb_oc_blocking and ur_w_tail */
+ jcp.ur_w = nstl::min(r_pad_no_tail / jcp.stride_w + jcp.ur_w_tail,
+ nstl::min(jcp.ow, num_avail_regs / 2));
+ jcp.nb_oc_blocking = (num_avail_regs - jcp.ur_w) / jcp.ur_w;
+ jcp.ur_w_tail = jcp.ow % jcp.ur_w;
+ /* check again ... */
+ r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1));
+ if (jcp.ur_w < nstl::max(jcp.l_pad, r_pad_no_tail))
+ return status::unimplemented;
+ }
+ assert(jcp.nb_oc_blocking > 0);
+ assert(jcp.ur_w * (jcp.nb_oc_blocking + 1) <= num_avail_regs);
+
+ jcp.ic_block = (jcp.ic % simd_w != 0) ? jcp.ic : simd_w;
+ jcp.nb_ic = jcp.ic / jcp.ic_block;
+
+ jcp.oc_block = simd_w;
+ jcp.nb_oc = jcp.oc / jcp.oc_block;
+
+ if (one_of(jcp.prop_kind, forward_training, forward_inference)) {
+ jcp.nb_ic_blocking = 12;
+ jcp.nb_ic_blocking_max = 16;
+ } else {
+ jcp.nb_ic_blocking = 1;
+ jcp.nb_ic_blocking_max = jcp.nb_ic_blocking;
+ }
+
+ return status::success;
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.hpp
new file mode 100644
index 0000000000..33c26ef081
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.hpp
@@ -0,0 +1,93 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_SSE42_CONV_KERNEL_F32_HPP
+#define JIT_SSE42_CONV_KERNEL_F32_HPP
+
+#include "c_types_map.hpp"
+#include "cpu_memory.hpp"
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+#include "jit_uni_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_sse42_conv_fwd_kernel_f32: public jit_generator {
+ jit_sse42_conv_fwd_kernel_f32(jit_conv_conf_t ajcp,
+ const primitive_attr_t &attr)
+ : jcp(ajcp), attr_(attr), eltwise_injector_(nullptr)
+ {
+ if (jcp.with_eltwise)
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<sse42>(this,
+ jcp.eltwise);
+
+ this->generate();
+ jit_ker = (void (*)(jit_conv_call_s *))this->getCode();
+ }
+
+ ~jit_sse42_conv_fwd_kernel_f32() {
+ delete eltwise_injector_;
+ }
+
+ static bool post_ops_ok(jit_conv_conf_t &jcp,
+ const primitive_attr_t &attr);
+
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d, const primitive_attr_t &attr);
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_sse42_conv_fwd_kernel_f32)
+ jit_conv_conf_t jcp;
+ const primitive_attr_t &attr_;
+ void (*jit_ker)(jit_conv_call_s *);
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ reg64_t reg_input = rax;
+ reg64_t aux_reg_input = r8;
+ reg64_t reg_kernel = rdx;
+ reg64_t aux_reg_kernel = r9;
+ reg64_t reg_output = rsi;
+ reg64_t reg_bias = rbx;
+
+ reg64_t kj = r10;
+ reg64_t oi_iter = r11;
+ reg64_t ki_iter = r12;
+ reg64_t reg_kh = abi_not_param1;
+ reg64_t simd_iter = r15;
+ reg64_t reg_oc_blocks = r14;
+ reg64_t imm_addr64 = reg_oc_blocks;
+ Xbyak::Reg32 reg_ci_flag = r13d;
+
+ jit_uni_eltwise_injector_f32<sse42> *eltwise_injector_;
+
+ inline void oh_step_unroll_kw(int ur_w, int pad_l, int pad_r,
+ int oc_blocks);
+ inline void oh_step_nopad(int ur_w, int pad_l, int pad_r, int oc_blocks);
+ inline void width_blk_step(int ur_w, int pad_l, int pad_r, int oc_blocks);
+ inline void solve_common(int oc_blocks);
+
+ void generate();
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.cpp
new file mode 100644
index 0000000000..5f77d692f5
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.cpp
@@ -0,0 +1,136 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn_types.h"
+
+#include "c_types_map.hpp"
+#include "jit_sse42_convolution.hpp"
+#include "mkldnn_thread.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::utils;
+
+#define src_blk_off(f, n, c, h, w) \
+ (pd()->ndims() == 3) \
+ ? (f).blk_off(n, c, w) \
+ : (f).blk_off(n, c, h, w)
+
+#define wht_blk_off_(f, g, ...) \
+ pd()->with_groups() \
+ ? (f).blk_off(g, __VA_ARGS__) \
+ : (f).blk_off(__VA_ARGS__)
+#define wht_blk_off(f, g, oc, ic, kh, kw) \
+ pd()->ndims() == 3 \
+ ? wht_blk_off_(f, g, oc, ic, kw) \
+ : wht_blk_off_(f, g, oc, ic, kh, kw)
+
+void jit_sse42_convolution_fwd_t::execute_forward(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ const auto &jcp = kernel_->jcp;
+
+ int ocb_work = div_up(jcp.nb_oc, jcp.nb_oc_blocking);
+ const size_t work_amount = jcp.mb * jcp.ngroups * ocb_work * jcp.oh;
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ size_t start{ 0 }, end{ 0 };
+ balance211(work_amount, nthr, ithr, start, end);
+
+ int icbb = 0;
+ while (icbb < jcp.nb_ic) {
+ int icb_step = jcp.nb_ic_blocking;
+ int icb_step_rem = jcp.nb_ic - icbb;
+ if (icb_step_rem < jcp.nb_ic_blocking_max)
+ icb_step = icb_step_rem;
+
+ size_t n{0}, g{0}, ocbb{0}, oh{0};
+ nd_iterator_init(start, n, jcp.mb, g, jcp.ngroups, ocbb, ocb_work,
+ oh, jcp.oh);
+ for (size_t iwork = start; iwork < end; ++iwork) {
+ int ocb = ocbb * jcp.nb_oc_blocking;
+ int ocb_num = jcp.nb_oc_blocking;
+
+ for (int icb = icbb; icb < icbb + icb_step; ++icb) {
+ auto par_conv = jit_conv_call_s();
+
+ const int ij = oh * jcp.stride_h;
+ const int i_t_overflow = nstl::max(0, jcp.t_pad - ij);
+ const int i_b_overflow = nstl::max(jcp.ih, ij
+ + (jcp.kh-1) * (jcp.dilate_h+1) - jcp.t_pad+1) - jcp.ih;
+
+ const size_t _oc = g * jcp.nb_oc + ocb;
+ const size_t _ic = g * jcp.nb_ic + icb;
+
+ const int ih = nstl::max(ij - jcp.t_pad
+ + div_up(i_t_overflow,
+ (jcp.dilate_h+1)) * (jcp.dilate_h + 1), 0);
+ par_conv.src = &src[src_blk_off(src_d, n,
+ jcp.ic == 3 ? 0 : _ic, ih, 0)];
+
+ par_conv.dst = &dst[src_blk_off(dst_d, n, _oc, oh, 0)];
+
+ const int wh = div_up(i_t_overflow, (jcp.dilate_h + 1));
+ par_conv.filt = &weights[wht_blk_off(weights_d, g, ocb,
+ jcp.ic == 3 ? 0 : icb, wh, 0)];
+
+ if (icb == 0) {
+ if (bias)
+ par_conv.bias =
+ &bias[bias_d.blk_off(_oc * jcp.oc_block)];
+ par_conv.flags |= FLAG_IC_FIRST;
+ }
+
+ if (jcp.with_eltwise && icb + 1 == jcp.nb_ic) {
+ par_conv.flags |= FLAG_IC_LAST;
+ }
+
+ par_conv.oc_blocks =
+ nstl::min(ocb + ocb_num, jcp.nb_oc) - ocb;
+
+ par_conv.kw_padding = 0;
+ const int kh_padding = jcp.kh
+ - div_up(i_t_overflow, (jcp.dilate_h + 1))
+ - div_up(i_b_overflow, (jcp.dilate_h + 1));
+ par_conv.kh_padding = nstl::max(0, kh_padding);
+ kernel_->jit_ker(&par_conv);
+ }
+ nd_iterator_step(n, jcp.mb, g, jcp.ngroups, ocbb, ocb_work,
+ oh, jcp.oh);
+ }
+ icbb += icb_step;
+ }
+ });
+
+ if (pd()->wants_zero_pad_dst())
+ ctx.memory(MKLDNN_ARG_DST)->zero_pad();
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.hpp
new file mode 100644
index 0000000000..d2f0a38c5c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_sse42_convolution.hpp
@@ -0,0 +1,103 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_SSE42_CONVOLUTION_HPP
+#define CPU_JIT_SSE42_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "utils.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_primitive_conf.hpp"
+#include "jit_sse42_conv_kernel_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_sse42_convolution_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", sse42, ""),
+ jit_sse42_convolution_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ return jit_sse42_conv_fwd_kernel_f32::init_conf(jcp_, *desc(),
+ *src_md(), *weights_md(), *dst_md(), *attr());
+ }
+
+ jit_conv_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ const bool flat = IC() == 3;
+ auto src_tag = flat
+ ? utils::pick(ndims() - 3, ncw, nchw, ncdhw)
+ : utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto dst_tag =
+ utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c);
+ auto wei_tag = with_groups()
+ ? utils::pick(2 * ndims() - 6 + flat, gOIw8i8o, gOwi8o,
+ gOIhw8i8o, gOhwi8o, gOIdhw8i8o, gOdhwi8o)
+ : utils::pick(2 * ndims() - 6 + flat, OIw8i8o, Owi8o,
+ OIhw8i8o, Ohwi8o, OIdhw8i8o, Odhwi8o);
+
+ return set_default_formats_common(src_tag, wei_tag, dst_tag);
+ }
+ };
+
+ jit_sse42_convolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd)
+ { kernel_ = new jit_sse42_conv_fwd_kernel_f32(pd()->jcp_, *pd()->attr()); }
+ ~jit_sse42_convolution_fwd_t() { delete kernel_; };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ jit_sse42_conv_fwd_kernel_f32 *kernel_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.cpp
new file mode 100644
index 0000000000..0e734f7265
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.cpp
@@ -0,0 +1,1192 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "nstl.hpp"
+#include "utils.hpp"
+#include "jit_generator.hpp"
+#include "cpu_barrier.hpp"
+
+#include "jit_transpose_src_utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace Xbyak;
+
+#define GET_OFF(x) offsetof(ctx_t, x)
+
+struct jit_trans_iw_ic_t: public jit_trans_src_t, public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_trans_iw_ic_t)
+
+ jit_trans_iw_ic_t(const jit_conv_conf_t *conf): jit_trans_src_t(conf) {
+ generate();
+ ker_ = (decltype(ker_))this->getCode();
+ }
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ using reg32_t = const Xbyak::Reg32;
+ using opmask_t = const Xbyak::Opmask;
+
+ enum { typesize = sizeof(float), transpose_size = 16, small_spatial = 14 };
+ int src_stride, tr_src_stride;
+ int tail;
+ bool enable_prefetch;
+
+ opmask_t k3333 = k1;
+ opmask_t k5555 = k2;
+ opmask_t kAAAA = k3;
+ opmask_t kCCCC = k4;
+ opmask_t k0F0F = k5;
+ opmask_t kF0F0 = k6;
+ opmask_t kTail = k7;
+
+ reg64_t reg_src = r8;
+ reg64_t reg_tr_src = r9;
+ reg64_t reg_src_prf = r10;
+ reg64_t reg_tr_src_prf = r11;
+ reg64_t reg_loop = r12;
+ reg64_t reg_tr_src_tmp = r13;
+ reg32_t regw_tmp = r14d;
+
+ void transpose(int nrows, int l_pad, int r_pad, bool nontemporal_stores);
+ void generate();
+};
+
+void jit_trans_iw_ic_t::transpose(int nrows, int l_pad, int r_pad,
+ bool nontemporal_stores) {
+ assert(nrows >= 0 && nrows <= transpose_size);
+ static_assert(transpose_size == 16, "Unsupported transpose size");
+ if (!nrows)
+ return;
+
+ auto pf_src_t0 = [=](int i) {
+ if(enable_prefetch) prefetcht0(EVEX_compress_addr(reg_src,
+ (transpose_size + i) * src_stride));
+ };
+
+ auto pf_tr_src_t0 = [=](int i) {
+ int offset = (transpose_size) * typesize + i * tr_src_stride;
+ if(enable_prefetch) prefetcht0(EVEX_compress_addr(reg_tr_src, offset));
+ if(enable_prefetch) prefetcht0(EVEX_compress_addr(reg_tr_src,
+ offset + 64));
+ };
+
+ auto pf_src_t1 = [=](int i) {
+ if(enable_prefetch) prefetcht1(EVEX_compress_addr(reg_src_prf,
+ i * src_stride));
+ };
+
+ auto pf_tr_src_t1 = [=](int i) {
+ if(enable_prefetch) prefetchwt1(EVEX_compress_addr(reg_tr_src_prf,
+ i * tr_src_stride));
+ };
+
+ auto src_zmm = [=](int i) {
+ assert(i >= 0 && i < 16);
+ return Zmm(i);
+ };
+
+ auto tmp_zmm = [=](int i) {
+ assert(i >= 0 && i < 16);
+ return Zmm(16 + i);
+ };
+
+ auto load = [=](int i) {
+ vmovups(src_zmm(i), EVEX_compress_addr(reg_src, i * src_stride));
+ };
+
+ auto store = [=](Zmm r, int i) {
+ auto kmovw = [=](Opmask k, unsigned w) {
+ mov(regw_tmp, w);
+ jit_generator::kmovw(k, regw_tmp);
+ };
+
+ auto padding = [=] (Reg64 reg, int pad) {
+ kmovw(kTail, (1 << pad) - 1);
+ auto k = kTail;
+ auto base = reg;
+ base.setOpmaskIdx(k.getIdx(), true);
+
+ auto zmm_zero = r;
+ vpxord(zmm_zero, zmm_zero, zmm_zero);
+ auto addr = EVEX_compress_addr(base, i * tr_src_stride);
+ vmovups(addr, zmm_zero);
+ };
+
+ mov(reg_tr_src_tmp, reg_tr_src);
+ if (l_pad > 0)
+ add(reg_tr_src_tmp, l_pad * typesize);
+
+ if (tail != transpose_size)
+ kmovw(kTail, (1 << tail) - 1);
+
+ // Xbyak does not allow k0 to be specified explicitly via the '|'
+ // operator, so we have to do this via a method call (implicitly
+ // EVEX encoding uses k0 to mean 'no mask')
+ bool partial_store = nrows < 16;
+ auto k = partial_store ? kTail : k0;
+ auto base = reg_tr_src_tmp;
+ base.setOpmaskIdx(k.getIdx(), true);
+
+ auto addr = EVEX_compress_addr(base, i * tr_src_stride);
+ if (nontemporal_stores && !partial_store)
+ vmovntps(addr, r);
+ else
+ vmovups(addr, r);
+
+ if (r_pad > 0) {
+ add(reg_tr_src_tmp, tail * typesize);
+ padding(reg_tr_src_tmp, r_pad);
+ }
+
+ if (l_pad > 0) {
+ padding(reg_tr_src, l_pad);
+ }
+ };
+
+ auto transpose16x8 = [=](int base_idx) {
+ assert(base_idx == 0 || base_idx == 8);
+
+ // swap 1
+ for (int i = 0; i < 4; i++) {
+ int src_idx0 = base_idx + i * 2;
+ int src_idx1 = src_idx0 + 1;
+
+ int next_src_idx0 = src_idx0 + 2;
+ int next_src_idx1 = src_idx1 + 2;
+ bool load_next = base_idx == 0 || i < 3;
+
+ if (base_idx == 0 && i == 0) {
+ load(src_idx0);
+ load(src_idx1);
+ }
+
+ auto tmp0 = tmp_zmm(src_idx0);
+ auto tmp1 = tmp_zmm(src_idx1);
+ auto src0 = src_zmm(src_idx0);
+ auto src1 = src_zmm(src_idx1);
+
+ if (next_src_idx0 < nrows && load_next)
+ load(next_src_idx0);
+ valignd(tmp0, src0, src0, 0x1);
+ pf_src_t1(base_idx + i);
+
+ if (next_src_idx1 < nrows && load_next)
+ load(next_src_idx1);
+ valignd(tmp1, src1, src1, 0xf);
+ pf_src_t0(base_idx + i);
+
+ vmovaps(src0 | kAAAA, tmp1);
+ vmovaps(src1 | k5555, tmp0);
+ }
+ // swap 2
+ for (int i = 0; i < 4; i++) {
+ int select_half = (i < 2) ? 0 : 2;
+ int src_idx0 = base_idx + i + select_half + 0;
+ int src_idx2 = src_idx0 + 2;
+
+ auto tmp0 = tmp_zmm(src_idx0);
+ auto tmp1 = tmp_zmm(src_idx2);
+ auto src0 = src_zmm(src_idx0);
+ auto src2 = src_zmm(src_idx2);
+
+ valignd(tmp0, src0, src0, 0x2);
+ pf_src_t1(base_idx + 4 + i);
+ valignd(tmp1, src2, src2, 0xe);
+ pf_src_t0(base_idx + 4 + i);
+ vmovaps(src2 | k3333, tmp0);
+ vmovaps(src0 | kCCCC, tmp1);
+ }
+
+ // swap 4
+ for (int i = 0; i < 4; i++) {
+ int src_idx0 = base_idx + i;
+ int src_idx4 = src_idx0 + 4;
+
+ auto tmp0 = tmp_zmm(src_idx0);
+ auto src0 = src_zmm(src_idx0);
+ auto src4 = src_zmm(src_idx4);
+
+ vmovaps(tmp0, src0);
+ vshuff32x4(src0 | kF0F0, src4, src4, 0xb1);
+ pf_tr_src_t1(base_idx / 2 + i);
+ vshuff32x4(src4 | k0F0F, tmp0, tmp0, 0xb1);
+ pf_tr_src_t0(base_idx / 2 + i);
+ }
+ };
+
+ auto fixup16x16 = [=]() {
+ // swap 8
+ for (int i = 0; i < 8; i++) {
+ auto tmp = tmp_zmm(i);
+ auto src0 = src_zmm(i);
+ auto src8 = src_zmm(8 + i);
+ vshuff64x2(tmp, src0, src8, 0x44);
+ store(tmp, i);
+ if (i % 2 == 0) {
+ pf_tr_src_t1(8 + i / 2);
+ pf_tr_src_t0(8 + i / 2);
+ }
+ }
+
+ for (int i = 0; i < 8; i++) {
+ auto tmp = tmp_zmm(8 + i);
+ auto src0 = src_zmm(i);
+ auto src8 = src_zmm(8 + i);
+ vshuff64x2(tmp, src0, src8, 0xee);
+ store(tmp, 8 + i);
+ if (i % 2 == 0) {
+ pf_tr_src_t1(12 + i / 2);
+ pf_tr_src_t0(12 + i / 2);
+ }
+ }
+ };
+
+ transpose16x8(0);
+ transpose16x8(8);
+ fixup16x16();
+}
+
+void jit_trans_iw_ic_t::generate() {
+ preamble();
+
+ const int ic_block = conf_->ic_block;
+ const int iw = conf_->iw;
+ const int tr_iw = conf_->tr_iw;
+ const int transposes = utils::div_up(iw, transpose_size);
+ int loop_iters = nstl::max(0, transposes - 1);
+ tail = iw - loop_iters * transpose_size;
+
+ src_stride = ic_block * typesize;
+ assert(src_stride == 64);
+ tr_src_stride = tr_iw * typesize;
+
+ bool nontemporal_stores = false;
+ enable_prefetch = iw > small_spatial ? 1 : 0;
+
+ assert(transpose_size == ic_block);
+ const int src_step = ic_block * transpose_size * typesize;
+ const int tr_src_step = ic_block * typesize;
+
+ const int left_pad = conf_->l_pad;
+ const int right_pad = tr_iw - iw - left_pad;
+
+ mov(reg_src, ptr [param1 + GET_OFF(src)]);
+ mov(reg_tr_src, ptr [param1 + GET_OFF(tr_src)]);
+ mov(reg_src_prf, ptr [param1 + GET_OFF(src_prf)]);
+ mov(reg_tr_src_prf, ptr [param1 + GET_OFF(tr_src_prf)]);
+
+ auto kmovw = [=](Opmask k, unsigned w) {
+ mov(regw_tmp, w);
+ jit_generator::kmovw(k, regw_tmp);
+ };
+
+ kmovw(k3333, 0x3333); // 0011001100110011
+ kmovw(k5555, 0x5555); // 0101010101010101
+ kmovw(kAAAA, 0xaaaa); // 1010101010101010
+ kmovw(kCCCC, 0xcccc); // 1100110011001100
+ kmovw(k0F0F, 0x0f0f); // 0000111100001111
+ kmovw(kF0F0, 0xf0f0); // 1111000011110000
+
+ if (left_pad > 0 && loop_iters > 0) {
+ loop_iters--;
+ transpose(transpose_size, left_pad, 0, nontemporal_stores);
+ add(reg_src, src_step);
+ add(reg_tr_src, tr_src_step + left_pad * typesize);
+ add(reg_src_prf, src_step);
+ add(reg_tr_src_prf, tr_src_step + left_pad * typesize);
+ }
+
+ if (loop_iters) {
+ mov(reg_loop, loop_iters);
+ Label loop;
+ L(loop); {
+ transpose(transpose_size, 0, 0, nontemporal_stores);
+ add(reg_src, src_step);
+ add(reg_tr_src, tr_src_step);
+ add(reg_src_prf, src_step);
+ add(reg_tr_src_prf, tr_src_step);
+ sub(reg_loop, 1);
+ jnz(loop);
+ }
+ }
+ if (transposes > 1)
+ transpose(tail, 0, right_pad, nontemporal_stores);
+ else
+ transpose(tail, left_pad, right_pad, nontemporal_stores);
+
+ postamble();
+}
+
+struct jit_trans_iw_ic_int16_t: public jit_trans_src_t, public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_trans_iw_ic_int16_t)
+ jit_trans_iw_ic_int16_t(const jit_conv_conf_t *conf):
+ jit_trans_src_t(conf) {
+ generate();
+ ker_ = (decltype(ker_))this->getCode();
+ }
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ using reg32_t = const Xbyak::Reg32;
+ using opmask_t = const Xbyak::Opmask;
+
+ enum { typesize = sizeof(int16_t), transpose_size = 16, small_spatial = 14 };
+ int src_stride, tr_src_stride;
+ int tail;
+ bool enable_prefetch;
+
+ opmask_t kFFFF = k1;
+ opmask_t k5555 = k2;
+ opmask_t kAAAA = k3;
+ opmask_t kAA = k4;
+ opmask_t k55 = k5;
+ opmask_t kCC = k6;
+ opmask_t k33 = k7;
+ opmask_t kTail = k1;
+
+ reg64_t reg_src = r8;
+ reg64_t reg_tr_src = r9;
+ reg64_t reg_src_prf = r10;
+ reg64_t reg_tr_src_prf = r11;
+ reg64_t reg_loop = r12;
+ reg64_t reg_tr_src_tmp = r13;
+ reg32_t regw_tmp = r14d;
+ reg64_t imm_addr64 = rbx;
+
+ Xbyak::Zmm vidx1 = zmm31;
+ Xbyak::Zmm vidx2 = zmm30;
+ Xbyak::Zmm vidx3 = zmm29;
+ Xbyak::Zmm vidx4 = zmm28;
+ Xbyak::Zmm vidx5 = zmm27;
+ Xbyak::Zmm zmm_tmp = zmm26;
+
+
+ void transpose(int nrows, int l_pad, int r_pad, bool nontemporal_stores);
+ void generate();
+};
+
+void jit_trans_iw_ic_int16_t::transpose(int nrows, int l_pad, int r_pad,
+ bool nontemporal_stores) {
+ assert(nrows >= 0 && nrows <= transpose_size);
+ static_assert(transpose_size == 16, "Unsupported transpose size");
+ if (!nrows)
+ return;
+
+ auto src_zmm = [=](int i) {
+ return Zmm(i);
+ };
+
+ auto src_ymm = [=](int i) {
+ assert(i >= 0 && i < 16);
+ return Ymm(i);
+ };
+
+ auto load_ymm = [=](int i) {
+ vmovups(src_ymm(i), EVEX_compress_addr(reg_src, i * src_stride));
+ };
+
+ auto kmovw = [=](Opmask k, unsigned w) {
+ mov(regw_tmp, w);
+ jit_generator::kmovw(k, regw_tmp);
+ };
+
+ auto store = [=](Zmm r, int i) {
+
+ auto padding = [=] (Reg64 reg, int pad) {
+ kmovw(kTail, (1 << pad) - 1);
+ auto k = kTail;
+ auto base = reg;
+ base.setOpmaskIdx(k.getIdx(), true);
+
+ auto zmm_zero = zmm_tmp;
+ vpxord(zmm_zero, zmm_zero, zmm_zero);
+ auto addr = EVEX_compress_addr(base, i * tr_src_stride);
+ vmovups(addr, zmm_zero);
+ };
+
+ int store_tail = (nrows%2) ? nrows+1 : nrows;
+
+ int store_pad = (l_pad%2) ? l_pad/2 + 1 : l_pad/2;
+ mov(reg_tr_src_tmp, reg_tr_src);
+ if (l_pad > 0) {
+ padding(reg_tr_src, store_pad);
+ add(reg_tr_src_tmp, l_pad * typesize);
+ }
+ if (r_pad > 0) {
+ store_pad = (r_pad%2) ? r_pad/2 + 1 : r_pad/2;
+ int addr_shift = (r_pad%2) ? 1 : 0;
+ add(reg_tr_src_tmp, (nrows - addr_shift) * typesize);
+ padding(reg_tr_src_tmp, store_pad);
+ }
+
+ mov(reg_tr_src_tmp, reg_tr_src);
+ add(reg_tr_src_tmp, l_pad * typesize);
+
+ kmovw(kTail, (1 << store_tail/2) - 1);
+ auto k = kTail;
+ auto base = reg_tr_src_tmp;
+ base.setOpmaskIdx(k.getIdx(), true);
+
+ auto addr = EVEX_compress_addr(base, i * tr_src_stride);
+ vmovups(addr, r);
+
+ };
+
+ kmovw(kFFFF, 0xffff);
+ //all loads
+ for (int i=0; i<16; i++){
+ vpxord(src_zmm(i), src_zmm(i), src_zmm(i));
+ }
+
+ for (int i = 0; i < nrows/2; i++) {
+ auto src0 = src_ymm(2*i);
+ auto src1 = src_ymm(2*i+1);
+ auto zmm_src0 = src_zmm(2*i);
+ load_ymm(2*i);
+
+ vpunpcklwd(src1, src0,
+ EVEX_compress_addr(reg_src, (2*i+1) * src_stride));
+ vpunpckhwd(src0, src0,
+ EVEX_compress_addr(reg_src, (2*i+1) * src_stride));
+ vinserti64x4(zmm_src0, zmm_src0, src1, 1);
+ vpermps(zmm_src0 | kFFFF, vidx4, zmm_src0);
+ }
+
+ // for odd numbers we need to mix row with zeroes
+ if (nrows%2) {
+ int i = nrows-1;
+ auto src0 = src_ymm(i);
+ auto src1 = src_ymm(i+1); //zero
+
+ auto zmm_src0 = src_zmm(i);
+ vpxor(src1, src1, src1);
+
+ load_ymm(i);
+ vpunpckhwd(src0, src0, src1);
+ vinserti64x4(zmm_tmp, zmm_tmp, src0, 0);
+ vpxor(src0, src0, src0);
+ load_ymm(i);
+ vpunpcklwd(src1, src0, src1);
+ vinserti64x4(zmm_tmp, zmm_tmp, src1, 1);
+ vpxord(zmm_src0, zmm_src0, zmm_src0);
+ vmovups(zmm_src0, zmm_tmp);
+ vpermps(zmm_src0 | kFFFF, vidx4, zmm_src0);
+ }
+
+ // swap 1
+ for (int i=0; i<4; i++) {
+ auto zmm0 = src_zmm(4*i);
+ auto zmm1 = src_zmm(4*i+2);
+ auto tmp0 = src_zmm(4*i+1);
+ auto tmp1 = src_zmm(4*i+3);
+
+ vmovups(tmp0, zmm0);
+ vmovups(tmp1, zmm1);
+
+ vpermps(tmp0 | kAAAA, vidx3, zmm1);
+ vpermps(tmp1 | k5555, vidx3, zmm0);
+ }
+ // swap 2
+ int base_idx;
+ base_idx=0;
+ for (int i=0; i<2; i++) {
+ auto zmm0 = src_zmm(base_idx+2*i+1);
+ auto zmm1 = src_zmm(base_idx+2*i+5);
+
+ auto tmp0 = src_zmm(base_idx+2*i);
+ auto tmp1 = src_zmm(base_idx+2*i+4);
+
+ vmovupd(tmp0, zmm0);
+ vmovupd(tmp1, zmm1);
+
+ vpermpd(tmp0 | kAA, vidx2, zmm1);
+ vpermpd(tmp1 | k55, vidx2, zmm0);
+ }
+ base_idx=8;
+ for (int i=0; i<2; i++) {
+ auto zmm0 = src_zmm(base_idx+2*i+1);
+ auto zmm1 = src_zmm(base_idx+2*i+5);
+
+ auto tmp0 = src_zmm(base_idx+2*i);
+ auto tmp1 = src_zmm(base_idx+2*i+4);
+
+ vmovupd(tmp0, zmm0);
+ vmovupd(tmp1, zmm1);
+
+ vpermpd(tmp0 | kAA, vidx2, zmm1);
+ vpermpd(tmp1 | k55, vidx2, zmm0);
+ }
+
+ // swap 3
+ for (int i=0; i<4; i++) {
+ auto zmm0 = src_zmm(2*i);
+ auto zmm1 = src_zmm(2*i+8);
+
+ auto tmp0 = src_zmm(2*i+1);
+ auto tmp1 = src_zmm(2*i+9);
+
+ vmovupd(tmp0, zmm0);
+ vmovupd(tmp1, zmm1);
+
+ vpermpd(tmp0 | kCC, vidx1, zmm1);
+ vpermpd(tmp1 | k33, vidx1, zmm0);
+ }
+
+ // all stores
+ for (int i=0; i<8; i++)
+ vextracti64x4(src_ymm(2*i), src_zmm(2*i+1), 1);
+
+ store(src_zmm(1), 0);
+ store(src_zmm(0), 1);
+ store(src_zmm(3), 2);
+ store(src_zmm(2), 3);
+ store(src_zmm(9), 4);
+ store(src_zmm(8), 5);
+ store(src_zmm(11), 6);
+ store(src_zmm(10), 7);
+ store(src_zmm(5), 8);
+ store(src_zmm(4), 9);
+ store(src_zmm(7), 10);
+ store(src_zmm(6), 11);
+ store(src_zmm(13), 12);
+ store(src_zmm(12), 13);
+ store(src_zmm(15), 14);
+ store(src_zmm(14), 15);
+
+}
+
+void jit_trans_iw_ic_int16_t::generate() {
+ preamble();
+
+ alignas(64) static constexpr const int64_t idx1[8]
+ = { 2, 3, 0, 1, 6, 7, 4, 5 };
+ alignas(64) static constexpr const int64_t idx2[8]
+ = { 1, 0, 3, 2, 5, 4, 7, 6 };
+ alignas(64) static constexpr const int32_t idx3[16]
+ = { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 };
+ alignas(64) static constexpr const int32_t idx4[16]
+ = { 8, 10, 12, 14, 0, 2, 4, 6, 9, 11, 13, 15, 1, 3, 5, 7 };
+ alignas(64) static constexpr const int32_t idx5[16]
+ = { 8, 10, 12, 14, 0, 2, 4, 6, 9, 11, 13, 15, 1, 3, 5, 7 };
+
+ const int ic_block = conf_->ic_block;
+ const int iw = conf_->iw;
+ const int tr_iw = conf_->tr_iw;
+ const int transposes = utils::div_up(iw, transpose_size);
+ int loop_iters = nstl::max(0, transposes - 1);
+ tail = iw - loop_iters * transpose_size;
+
+ src_stride = ic_block * typesize;
+ tr_src_stride = tr_iw * typesize;
+
+ bool nontemporal_stores = false;
+ enable_prefetch = iw > small_spatial ? 1 : 0;
+
+ assert(transpose_size == ic_block);
+ const int src_step = ic_block * transpose_size * typesize;
+ const int tr_src_step = ic_block * typesize;
+
+ const int left_pad = conf_->l_pad;
+ const int right_pad = tr_iw - iw - left_pad;
+
+ mov(reg_src, ptr [param1 + GET_OFF(src)]);
+ mov(reg_tr_src, ptr [param1 + GET_OFF(tr_src)]);
+ mov(reg_src_prf, ptr [param1 + GET_OFF(src_prf)]);
+ mov(reg_tr_src_prf, ptr [param1 + GET_OFF(tr_src_prf)]);
+
+ auto kmovw = [=](Opmask k, unsigned w) {
+ mov(regw_tmp, w);
+ jit_generator::kmovw(k, regw_tmp);
+ };
+
+ kmovw(kFFFF, 0xffff);
+ kmovw(k5555, 0x5555);
+ kmovw(kAAAA, 0xaaaa);
+ kmovw(kAA, 0xaa);
+ kmovw(k55, 0x55);
+ kmovw(kCC, 0xcc);
+ kmovw(k33, 0x33);
+
+ auto vmovdqa64 = [=](Zmm z, const int64_t *addr) {
+ mov(imm_addr64, reinterpret_cast<size_t>(addr));
+ jit_generator::vmovdqa64(z, ptr[imm_addr64]);
+ };
+
+ auto vmovdqa32 = [=](Zmm z, const int32_t *addr) {
+ mov(imm_addr64, reinterpret_cast<size_t>(addr));
+ jit_generator::vmovdqa32(z, ptr[imm_addr64]);
+ };
+
+ vmovdqa64(vidx1, idx1);
+ vmovdqa64(vidx2, idx2);
+ vmovdqa32(vidx3, idx3);
+ vmovdqa32(vidx4, idx4);
+ vmovdqa32(vidx5, idx5);
+
+ if (left_pad > 0 && loop_iters > 0) {
+ loop_iters--;
+ transpose(transpose_size, left_pad, 0, nontemporal_stores);
+ add(reg_src, src_step);
+ add(reg_tr_src, tr_src_step + left_pad * typesize);
+ add(reg_src_prf, src_step);
+ add(reg_tr_src_prf, tr_src_step + left_pad * typesize);
+ }
+
+ if (loop_iters) {
+ mov(reg_loop, loop_iters);
+ Label loop;
+ L(loop); {
+ transpose(transpose_size, 0, 0, nontemporal_stores);
+ add(reg_src, src_step);
+ add(reg_tr_src, tr_src_step);
+ add(reg_src_prf, src_step);
+ add(reg_tr_src_prf, tr_src_step);
+ sub(reg_loop, 1);
+ jnz(loop);
+ }
+ }
+ if (transposes > 1)
+ transpose(tail, 0, right_pad, nontemporal_stores);
+ else
+ transpose(tail, left_pad, right_pad, nontemporal_stores);
+
+ postamble();
+
+}
+
+struct jit_trans_ow_oc_t: public jit_trans_dst_t, public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_trans_ow_oc_t)
+ jit_trans_ow_oc_t(const jit_conv_conf_t *conf): jit_trans_dst_t(conf) {
+ generate();
+ ker_ = (decltype(ker_))this->getCode();
+ }
+
+private:
+ using reg64_t = const Xbyak::Reg64;
+ using reg32_t = const Xbyak::Reg32;
+ using opmask_t = const Xbyak::Opmask;
+ using zmm = const Xbyak::Zmm;
+
+ enum { typesize = sizeof(int16_t), transpose_size = 16, small_spatial = 14 };
+ int src_stride, tr_src_stride;
+ int tail;
+ bool enable_prefetch;
+
+ opmask_t kFF = k1;
+
+ zmm vidx1 = zmm31;
+
+ reg64_t reg_src = r8;
+ reg64_t reg_tr_src = r9;
+ reg64_t reg_src_prf = r10;
+ reg64_t reg_tr_src_prf = r11;
+ reg64_t reg_loop = r12;
+ reg64_t reg_tr_src_tmp = r13;
+ reg32_t regw_tmp = r14d;
+ reg64_t imm_addr64 = rbx;
+
+ void transpose(int nrows, int l_pad, int r_pad, bool nontemporal_stores);
+ void generate();
+};
+
+void jit_trans_ow_oc_t::transpose(int nrows, int l_pad, int r_pad,
+ bool nontemporal_stores) {
+ assert(nrows >= 0 && nrows <= transpose_size);
+ static_assert(transpose_size == 16, "Unsupported transpose size");
+ if (!nrows)
+ return;
+
+ auto src_zmm = [=](int i) {
+ return Zmm(i);
+ };
+
+ auto src_ymm = [=](int i) {
+ assert(i >= 0 && i < 16);
+ return Ymm(i);
+ };
+
+ auto load_ymm = [=](int i) {
+ vmovups(src_ymm(i), EVEX_compress_addr(reg_src, i * src_stride));
+ };
+
+
+ auto store = [=](Zmm r, int i) {
+ auto addr = EVEX_compress_addr(reg_tr_src, i * tr_src_stride);
+ if (nontemporal_stores)
+ vmovntps(addr, r);
+ else
+ vmovups(addr, r);
+ };
+
+ for (int i = 0; i < nrows/2; i++) {
+ auto src0 = src_ymm(2*i);
+ auto src1 = src_ymm(2*i+1);
+ auto zmm_src0 = src_zmm(2*i);
+ load_ymm(2*i);
+ vpunpcklwd(src1, src0,
+ EVEX_compress_addr(reg_src, (2*i+1) * src_stride));
+ vpunpckhwd(src0, src0,
+ EVEX_compress_addr(reg_src, (2*i+1) * src_stride));
+ vinserti64x4(zmm_src0, zmm_src0, src1, 1);
+ vpermpd(zmm_src0 | kFF, vidx1, zmm_src0);
+ store(zmm_src0, 2*i);
+ }
+ if (r_pad > 0) {
+ auto src0 = src_ymm(nrows-1);
+ auto src1 = src_ymm(nrows);
+ auto zmm_src0 = src_zmm(30);
+ load_ymm(nrows-1);
+
+ vpxor(src1, src1, src1);
+ vpunpckhwd(src1, src0, src1);
+ vinserti64x4(zmm_src0, zmm_src0, src1, 0);
+ vpxor(src1, src1, src1);
+ vpunpcklwd(src0, src0, src1);
+ vinserti64x4(zmm_src0, zmm_src0, src0, 1);
+ vpermpd(zmm_src0 | kFF, vidx1, zmm_src0);
+ store(zmm_src0, nrows-1);
+ }
+}
+
+void jit_trans_ow_oc_t::generate() {
+ preamble();
+
+ alignas(64) static constexpr const int64_t idx1[8]
+ = { 4, 5, 0, 1, 6, 7, 2, 3 };
+
+ const int oc_block = conf_->oc_block;
+ const int ow = conf_->ow;
+ const int transposes = utils::div_up(ow, transpose_size);
+ int loop_iters = nstl::max(0, transposes - 1);
+ tail = ow - loop_iters * transpose_size;
+
+ src_stride = oc_block * typesize;
+ tr_src_stride = oc_block * typesize;
+
+ bool nontemporal_stores = false;
+ enable_prefetch = ow > small_spatial ? 1 : 0;
+
+ const int src_step = oc_block * transpose_size * typesize;
+ const int tr_src_step = oc_block * transpose_size * typesize;
+ const int right_pad = ow % 2;
+
+ mov(reg_src, ptr [param1 + GET_OFF(src)]);
+ mov(reg_tr_src, ptr [param1 + GET_OFF(tr_src)]);
+ mov(reg_src_prf, ptr [param1 + GET_OFF(src_prf)]);
+ mov(reg_tr_src_prf, ptr [param1 + GET_OFF(tr_src_prf)]);
+
+ auto kmovw = [=](Opmask k, unsigned w) {
+ mov(regw_tmp, w);
+ jit_generator::kmovw(k, regw_tmp);
+ };
+
+ kmovw(kFF, 0xFF);
+
+ auto vmovdqa64 = [=](Zmm z, const int64_t *addr) {
+ mov(imm_addr64, reinterpret_cast<size_t>(addr));
+ jit_generator::vmovdqa64(z, ptr[imm_addr64]);
+ };
+
+ vmovdqa64(vidx1, idx1);
+ if (loop_iters) {
+ mov(reg_loop, loop_iters);
+ Label loop;
+ L(loop); {
+ transpose(transpose_size, 0, 0, nontemporal_stores);
+ add(reg_src, src_step);
+ add(reg_tr_src, tr_src_step);
+ add(reg_src_prf, src_step);
+ add(reg_tr_src_prf, tr_src_step);
+ sub(reg_loop, 1);
+ jnz(loop);
+ }
+ }
+ transpose(tail, 0, right_pad, nontemporal_stores);
+
+ postamble();
+}
+
+struct jit_trans_iw_x4_4x_t: public jit_trans_src_t, public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_trans_iw_x4_4x_t)
+
+ jit_trans_iw_x4_4x_t(const jit_conv_conf_t *conf): jit_trans_src_t(conf) {
+ generate();
+ ker_ = (decltype(ker_))this->getCode();
+ }
+
+ void generate();
+ enum { typesize = (int)sizeof(float) };
+};
+
+/** @brief transposition of the form [:][iw/4][4] -> [:][4][iw/4]
+ * required for 1st 4fma backward by weights convolution */
+void jit_trans_iw_x4_4x_t::generate() {
+ using namespace utils;
+
+ /* TODO: put into code */
+ static int mask[16] = {
+ 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, };
+
+ const auto &c = *conf_;
+ const int simd_w = cpu_isa_traits<avx512_common>::vlen / typesize;
+ const int niters = c.tr_ld / simd_w;
+
+ assert(niters <= 4); /* [bwd_w:tr_src:r1] */
+
+ Reg64 reg_ptr_src = r8;
+ Reg64 reg_ptr_tr_src = r9;
+
+ Reg64 reg_ih = rax;
+ Reg64 reg_ih_end = rbx;
+
+ Reg64 reg_nthr_oc_b = rsi;
+ Reg64 reg_ptr_tr_src_bctx = abi_not_param1;
+
+ Reg64 reg_tmp = rdx;
+
+ Zmm vmsk = Zmm(31);
+ Opmask kmsk = k7;
+
+ auto emit_tr_sync = [&]() {
+ simple_barrier::generate(*this, reg_ptr_tr_src_bctx, reg_nthr_oc_b);
+ };
+
+ auto emit_tr_iw = [&]() {
+ auto vreg = [](int iter, int i) {
+ assert(4 * iter + i < 24);
+ return Zmm(4 * iter + i);
+ };
+ auto vtmp = [](int i) { return Zmm(24 + i); };
+
+ auto emit_load = [&](int iter) {
+ for (int i = 0; i < 4; ++i) {
+ auto v = vreg(iter, i);
+ const int off = (iter * 4 + i) * simd_w;
+
+ if (off + simd_w <= c.iw)
+ vmovups(v, ptr[reg_ptr_src + off * typesize]);
+ else if (off < c.iw)
+ vmovups(v | kmsk | T_z, ptr[reg_ptr_src + off * typesize]);
+ else
+ vpxord(v, v, v);
+ }
+ };
+
+ auto emit_tr = [&](int iter) {
+ for (int i = 0; i < 4; ++i)
+ vpermps(vreg(iter, i), vmsk, vreg(iter, i));
+
+ vshuff32x4(vtmp(0), vreg(iter, 0), vreg(iter, 1), 0x88);
+ vshuff32x4(vtmp(1), vreg(iter, 0), vreg(iter, 1), 0xdd);
+ vshuff32x4(vtmp(2), vreg(iter, 2), vreg(iter, 3), 0x88);
+ vshuff32x4(vtmp(3), vreg(iter, 2), vreg(iter, 3), 0xdd);
+
+ vshuff32x4(vreg(iter, 0), vtmp(0), vtmp(2), 0x88);
+ vshuff32x4(vreg(iter, 2), vtmp(0), vtmp(2), 0xdd);
+ vshuff32x4(vreg(iter, 1), vtmp(1), vtmp(3), 0x88);
+ vshuff32x4(vreg(iter, 3), vtmp(1), vtmp(3), 0xdd);
+ };
+
+ auto emit_store = [&]() {
+ for (int i = 0; i < 4; ++i) {
+ for (int iter = 0; iter < niters; ++iter) {
+ const size_t off = i * c.tr_ld + iter * simd_w;
+ vmovups(ptr[reg_ptr_tr_src + off * typesize], vreg(iter, i));
+ }
+ }
+ };
+
+ for (int iter = 0; iter < niters; ++iter)
+ emit_load(iter);
+
+ for (int iter = 0; iter < niters; ++iter)
+ emit_tr(iter);
+
+ emit_store();
+ };
+
+ preamble();
+
+ mov(reg_ptr_src, ptr[abi_param1 + GET_OFF(src)]);
+ mov(reg_ptr_tr_src, ptr[abi_param1 + GET_OFF(tr_src)]);
+
+ mov(reg_nthr_oc_b.cvt32(), ptr[abi_param1 + GET_OFF(nthr_oc_b)]);
+ mov(reg_ih.cvt32(), ptr[abi_param1 + GET_OFF(tr_src_ih_start)]);
+ mov(reg_ih_end.cvt32(), ptr[abi_param1 + GET_OFF(tr_src_ih_end)]);
+ mov(reg_ptr_tr_src_bctx, ptr[abi_param1 + GET_OFF(tr_src_bctx)]);
+
+ emit_tr_sync();
+
+ Label l_ih_loop, l_tr_done;
+ cmp(reg_ih, reg_ih_end);
+ je(l_tr_done, T_NEAR);
+
+ mov(reg_tmp, (size_t)&mask[0]);
+ vmovups(vmsk, ptr[reg_tmp]);
+
+ if (c.iw % simd_w) {
+ const char load_mask = (1 << (c.iw % simd_w)) - 1;
+ mov(reg_tmp, load_mask);
+ kmovw(kmsk, reg_tmp.cvt32());
+ }
+
+ /* src += ih_start * c.iw; */
+ imul(reg_tmp, reg_ih, c.iw * typesize);
+ add(reg_ptr_src, reg_tmp);
+ /* tr_src += ih_start * c.stride_w * c.tr_ld; */
+ imul(reg_tmp, reg_ih, c.stride_w * c.tr_ld * typesize);
+ add(reg_ptr_tr_src, reg_tmp);
+
+ L(l_ih_loop); {
+ emit_tr_iw();
+
+ add(reg_ptr_src, c.iw * typesize);
+ add(reg_ptr_tr_src, c.stride_w * c.tr_ld * typesize);
+
+ inc(reg_ih);
+ cmp(reg_ih, reg_ih_end);
+ jl(l_ih_loop, T_NEAR);
+ }
+
+ L(l_tr_done);
+
+ emit_tr_sync();
+
+ postamble();
+}
+
+/*
+// -------------------------------------------------
+// jit_transpose4x16_src
+// -------------------------------------------------
+*/
+
+void jit_transpose4x16_src::transpose(int nrows)
+{
+ assert(nrows >= 0 && nrows <= transpose_size);
+ static_assert(transpose_size == 4, "Unsupported transpose size");
+ if (!nrows)
+ return;
+
+ auto pf_src_t0 = [=](int i) {
+ if (tparams->src_pf0_distance)
+ prefetcht0(EVEX_compress_addr(
+ reg_src, (tparams->src_pf0_distance + i) * src_stride));
+ };
+
+ auto pf_tr_src_t0 = [=](int i) {
+ if (tparams->tr_src_pf0_distance)
+ prefetcht0(EVEX_compress_addr(reg_tr_src,
+ (tparams->tr_src_pf0_distance + i) * src_stride));
+ };
+
+ auto pf_src_t1 = [=](int i) {
+ if (tparams->src_pf1)
+ prefetcht1(EVEX_compress_addr(reg_src_prf, i * src_stride));
+ };
+
+ auto pf_tr_src_t1 = [=](int i) {
+ if (tparams->tr_src_pf1)
+ prefetchwt1(EVEX_compress_addr(reg_tr_src_prf, i * tr_src_stride));
+ };
+
+ auto src_zmm = [=](int i) {
+ assert(i >= 0 && i < 4);
+ return Zmm(i);
+ };
+
+ auto tmp_zmm = [=](int i) {
+ assert(i >= 0 && i < 4);
+ return Zmm(4 + i);
+ };
+
+ auto load = [=](int i) {
+ vmovups(src_zmm(i), EVEX_compress_addr(reg_src, i * src_stride));
+ };
+
+ auto store = [=](Zmm r, int i) {
+ vmovups(EVEX_compress_addr(reg_tr_src, i * tr_src_stride), r);
+ };
+
+ auto tmp0 = tmp_zmm(0);
+ auto tmp1 = tmp_zmm(1);
+ auto tmp2 = tmp_zmm(2);
+ auto tmp3 = tmp_zmm(3);
+
+ auto src0 = src_zmm(0);
+ auto src1 = src_zmm(1);
+ auto src2 = src_zmm(2);
+ auto src3 = src_zmm(3);
+ for (int i = 0; i < nrows; i++) {
+ load(i);
+ }
+
+ for (size_t i = nrows; i < 4; i++) {
+ vpxord(src_zmm(i), src_zmm(i), src_zmm(i));
+ }
+
+ vmovupd(tmp0, src0);
+ vmovupd(tmp1, src1);
+ pf_src_t0(0);
+ vpermpd(tmp0 | kF0, vidx01, src2);
+ vpermpd(tmp1 | kF0, vidx01, src3);
+
+ valignd(src0, src0, src0, 8);
+ valignd(src1, src1, src1, 8);
+ pf_src_t0(1);
+ vmovupd(tmp2, src0);
+ vmovupd(tmp3, src1);
+ pf_src_t0(2);
+ vpermpd(tmp2 | kF0, vidx10, src2);
+ vpermpd(tmp3 | kF0, vidx10, src3);
+ pf_src_t0(3);
+
+ vmovupd(src0, tmp0);
+ pf_src_t1(0);
+ vmovupd(src1, tmp2);
+ pf_src_t1(1);
+ vmovupd(src2, tmp1);
+ pf_src_t1(2);
+ vmovupd(src3, tmp3);
+ pf_src_t1(3);
+ vpermpd(src0 | kCC, vidx1, tmp1);
+ vpermpd(src1 | kCC, vidx1, tmp3);
+ pf_tr_src_t0(0);
+ vpermpd(src2 | k33, vidx1, tmp0);
+ vpermpd(src3 | k33, vidx1, tmp2);
+ pf_tr_src_t0(1);
+
+ vmovupd(tmp0, src0);
+ vmovupd(tmp1, src2);
+ pf_tr_src_t0(2);
+ vmovupd(tmp2, src1);
+ vmovupd(tmp3, src3);
+ pf_tr_src_t0(3);
+ vpermps(tmp0 | kFFFF, vidxP, src0);
+ pf_tr_src_t1(0);
+ vpermps(tmp1 | kFFFF, vidxP, src2);
+ pf_tr_src_t1(1);
+ vpermps(tmp2 | kFFFF, vidxP, src1);
+ pf_tr_src_t1(3);
+ vpermps(tmp3 | kFFFF, vidxP, src3);
+ pf_tr_src_t1(4);
+
+ store(tmp0, 0);
+ store(tmp1, 1);
+ store(tmp2, 2);
+ store(tmp3, 3);
+}
+
+alignas(64) static constexpr const int64_t idx01[8]
+ = { 0, 0, 0, 0, 0, 1, 2, 3 };
+alignas(64) static constexpr const int64_t idx10[8]
+ = { 0, 0, 0, 0, 4, 5, 6, 7 };
+alignas(64) static constexpr const int64_t idx1[8] = { 2, 3, 0, 1, 6, 7, 4, 5 };
+alignas(64) static constexpr const int32_t idxP[16]
+ = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 };
+
+void jit_transpose4x16_src::generate()
+{
+ preamble();
+
+ const int ic_block = params->ic_block;
+ const int is = params->is;
+ int tail = is % transpose_size;
+
+ src_stride = ic_block * typesize;
+ assert(src_stride == 64);
+ tr_src_stride = ic_block * typesize;
+
+ const int src_step = ic_block * transpose_size * typesize;
+ const int tr_src_step = ic_block * transpose_size * typesize;
+
+#define GET_TR_OFF(x) offsetof(jit_src_transpose_s, x)
+ mov(reg_loop, ptr[param1 + GET_TR_OFF(size)]);
+ mov(reg_src, ptr[param1 + GET_TR_OFF(src)]);
+ mov(reg_tr_src, ptr[param1 + GET_TR_OFF(tr_src)]);
+ mov(reg_src_prf, ptr[param1 + GET_TR_OFF(src_prf)]);
+ mov(reg_tr_src_prf, ptr[param1 + GET_TR_OFF(tr_src_prf)]);
+#undef GET_TR_OFF
+
+ auto kmovw = [=](Opmask k, unsigned w) {
+ mov(regw_tmp, w);
+ jit_generator::kmovw(k, regw_tmp);
+ };
+
+ auto vmovdqa64 = [=](Zmm z, const int64_t *addr) {
+ mov(imm_addr64, reinterpret_cast<size_t>(addr));
+ jit_generator::vmovdqa64(z, ptr[imm_addr64]);
+ };
+
+ auto vmovdqa32 = [=](Zmm z, const int32_t *addr) {
+ mov(imm_addr64, reinterpret_cast<size_t>(addr));
+ jit_generator::vmovdqa32(z, ptr[imm_addr64]);
+ };
+
+ kmovw(kF0, 0xf0); // 11110000
+ kmovw(kCC, 0xcc); // 11001100
+ kmovw(k33, 0x33); // 00110011
+ kmovw(kFFFF, 0xffff); // 1111111111111111
+
+ vmovdqa64(vidx01, idx01);
+ vmovdqa64(vidx10, idx10);
+ vmovdqa64(vidx1, idx1);
+ vmovdqa32(vidxP, idxP);
+
+ Label loop_label;
+ Label tail_label;
+
+ cmp(reg_loop, transpose_size);
+ jl(tail_label, T_NEAR);
+
+ L(loop_label);
+ {
+ transpose(transpose_size);
+ add(reg_src, src_step);
+ add(reg_tr_src, tr_src_step);
+ add(reg_src_prf, src_step);
+ add(reg_tr_src_prf, tr_src_step);
+ sub(reg_loop, transpose_size);
+ cmp(reg_loop, transpose_size);
+ jge(loop_label, T_NEAR);
+ }
+ L(tail_label);
+ transpose(tail);
+
+ postamble();
+}
+
+jit_trans_src_t *create_trans_src(const jit_conv_conf_t *conf) {
+ if (conf->ver == ver_4fma && !conf->is_1stconv)
+ return new jit_trans_iw_ic_t(conf);
+ if (conf->ver == ver_4fma && conf->is_1stconv)
+ return new jit_trans_iw_x4_4x_t(conf);
+ assert(!"unsupported configuration");
+ return nullptr;
+}
+
+jit_trans_dst_t *create_trans_dst(const jit_conv_conf_t *conf) {
+ assert(!"unsupported configuration");
+ return nullptr;
+}
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.hpp
new file mode 100644
index 0000000000..565e97e4fc
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_transpose_src_utils.hpp
@@ -0,0 +1,145 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_TRANSPOSE_SRC_HPP
+#define CPU_JIT_TRANSPOSE_SRC_HPP
+
+#include "cpu_barrier.hpp"
+#include "jit_primitive_conf.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_trans_src_t {
+ struct ctx_t {
+ const void *src;
+ const void *tr_src;
+ const void *src_prf;
+ const void *tr_src_prf;
+
+ /* 1st conv 4fma: backward by weights */
+ int nthr_oc_b; /* number of threads process given src image */
+ int tr_src_ih_start, tr_src_ih_end; /* thread's transposition bounds */
+ simple_barrier::ctx_t *tr_src_bctx; /* transposition synchronization */
+ };
+
+ jit_trans_src_t(const jit_conv_conf_t *conf)
+ : conf_(conf), ker_(nullptr) {}
+ virtual ~jit_trans_src_t() {}
+
+ void operator()(const ctx_t *ctx)
+ { assert(ker_); ker_(ctx); }
+
+ const jit_conv_conf_t *conf_;
+ void (*ker_)(const ctx_t *);
+};
+
+struct jit_src_transpose_s {
+ size_t size;
+ const void *src;
+ const void *tr_src;
+ const void *src_prf;
+ const void *tr_src_prf;
+};
+
+struct jit_trans_dst_t {
+ struct ctx_t {
+ const void *src;
+ const void *tr_src;
+ const void *src_prf;
+ const void *tr_src_prf;
+
+ /* 1st conv 4fma: backward by weights */
+ int nthr_oc_b; /* number of threads process given src image */
+ int tr_src_ih_start, tr_src_ih_end; /* thread's transposition bounds */
+ simple_barrier::ctx_t *tr_src_bctx; /* transposition synchronization */
+ };
+
+ jit_trans_dst_t(const jit_conv_conf_t *conf)
+ : conf_(conf), ker_(nullptr) {}
+ virtual ~jit_trans_dst_t() {}
+
+ void operator()(const ctx_t *ctx)
+ { assert(ker_); ker_(ctx); }
+
+ const jit_conv_conf_t *conf_;
+ void (*ker_)(const ctx_t *);
+};
+
+struct jit_transpose4x16_src_t {
+ int src_pf0_distance;
+ int tr_src_pf0_distance;
+ bool src_pf1;
+ bool tr_src_pf1;
+};
+
+struct jit_transpose4x16_src : public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_transpose4x16_src)
+
+ jit_transpose4x16_src(const jit_1x1_conv_conf_t *aparams,
+ jit_transpose4x16_src_t *tparams_)
+ : params(aparams), tparams(tparams_)
+ {
+ this->generate();
+ jit_ker = (decltype(jit_ker))this->getCode();
+ }
+
+ const jit_1x1_conv_conf_t *params;
+ const jit_transpose4x16_src_t *tparams;
+ void (*jit_ker)(jit_src_transpose_s *);
+
+ void operator()(jit_src_transpose_s *arg) { jit_ker(arg); }
+
+ static const int transpose_size = 4;
+private:
+ static const int typesize = sizeof(float);
+
+ int src_stride, tr_src_stride;
+
+ Xbyak::Reg64 imm_addr64 = rbx;
+
+ Xbyak::Opmask kF0 = k1;
+ Xbyak::Opmask kCC = k2;
+ Xbyak::Opmask k33 = k3;
+ Xbyak::Opmask kFFFF = k4;
+
+ Xbyak::Zmm vidx01 = zmm31;
+ Xbyak::Zmm vidx10 = zmm30;
+ Xbyak::Zmm vidx1 = zmm29;
+ Xbyak::Zmm vidxP = zmm28;
+
+ Xbyak::Reg64 reg_src = r8;
+ Xbyak::Reg64 reg_tr_src = r9;
+ Xbyak::Reg64 reg_src_prf = r10;
+ Xbyak::Reg64 reg_tr_src_prf = r11;
+ Xbyak::Reg64 reg_loop = r12;
+ Xbyak::Reg64 reg_tr_src_tmp = r13;
+ Xbyak::Reg32 regw_tmp = r14d;
+
+ void transpose_block(int ur, int nrows);
+ void transpose(int nrows);
+ void generate();
+};
+
+jit_trans_src_t *create_trans_src(const jit_conv_conf_t *conf);
+jit_trans_dst_t *create_trans_dst(const jit_conv_conf_t *conf);
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_1x1_conv_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_1x1_conv_utils.hpp
new file mode 100644
index 0000000000..53313f9f01
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_1x1_conv_utils.hpp
@@ -0,0 +1,327 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_UNI_1x1_CONV_UTILS_HPP
+#define JIT_UNI_1x1_CONV_UTILS_HPP
+
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::utils;
+
+struct reduce_to_unit_stride_t {
+ convolution_desc_t conv_d_;
+ bool reduce_src_;
+ size_t space_per_thread_;
+};
+
+/* 1x1-kernel does not support non-unit strides so far, so the idea is:
+ * - for fwd or bwd_weights: to copy src to a scratch memory (with strides
+ * equal to 1) and then call the kernel
+ * - for bwd_data: reduce the problem to the one with unit stride by
+ * performing computations in a scratch memory (with strides equal to 1)
+ * and then copy the result to diff_src */
+template <typename conv_pd_t>
+inline void rtus_prepare(conv_pd_t *self, const convolution_desc_t *&conv_d,
+ const memory_desc_t *&src_d, const memory_desc_t *dst_d) {
+ const bool is_bwd_data = self->desc()->prop_kind
+ == prop_kind::backward_data;
+
+ const int ndims = src_d->ndims;
+ const auto dat_tag = ndims == 3
+ ? memory_desc_wrapper(dst_d).matches_one_of_tag(
+ format_tag::nCw8c, format_tag::nCw16c)
+ : memory_desc_wrapper(dst_d).matches_one_of_tag(
+ format_tag::nChw8c, format_tag::nChw16c);
+
+ bool rtus_applicable = true
+ && utils::pick(ndims - 3,
+ (conv_d->strides[0] != 1 && !one_of(conv_d->src_desc.data_type,
+ data_type::s32)),
+ (conv_d->strides[0] != 1 || conv_d->strides[1] != 1))
+ && dat_tag != format_tag::undef;
+ for (int d = 2; d < ndims; ++d) {
+ /* TODO: relax these conditions (by improving reducer) */
+ rtus_applicable = rtus_applicable
+ && conv_d->padding[0][d - 2] == 0
+ && dst_d->dims[d] * conv_d->strides[d - 2] == src_d->dims[d];
+ }
+
+ if (rtus_applicable) {
+ self->rtus_.reduce_src_ = true;
+ conv_d = &(self->rtus_.conv_d_ = *conv_d);
+ self->rtus_.conv_d_.strides[0] = 1;
+ if (ndims == 4)
+ self->rtus_.conv_d_.strides[1] = 1;
+ utils::array_set(self->rtus_.conv_d_.padding[0], 0, 2);
+ if (ndims == 4)
+ utils::array_set(self->rtus_.conv_d_.padding[1], 0, 2);
+ const int ic = src_d->dims[1];
+ if (is_bwd_data) {
+ src_d = &(self->rtus_.conv_d_.diff_src_desc = *dst_d);
+ self->rtus_.conv_d_.diff_src_desc.dims[1] = ic;
+ memory_desc_wrapper::compute_blocking(
+ self->rtus_.conv_d_.diff_src_desc, dat_tag);
+ } else {
+ data_type_t data_type = self->rtus_.conv_d_.src_desc.data_type;
+ src_d = &(self->rtus_.conv_d_.src_desc = *dst_d);
+ self->rtus_.conv_d_.src_desc.dims[1] = ic;
+ self->rtus_.conv_d_.src_desc.data_type = data_type;
+ memory_desc_wrapper::compute_blocking(
+ self->rtus_.conv_d_.src_desc, dat_tag);
+ }
+ }
+}
+
+template <typename conv_pd_t>
+inline void rtus_prepare_space_info(conv_pd_t *self,
+ memory_tracking::registrar_t &scratchpad) {
+ const auto &jcp = self->jcp_;
+
+ const int max_threads = mkldnn_get_max_threads();
+ const size_t factor = utils::pick_by_prop_kind(self->desc()->prop_kind,
+ jcp.nb_reduce, jcp.nb_load_blocking_max, jcp.nb_bcast_blocking);
+ size_t typesize = types::data_type_size(
+ conv_prop_invariant_src_d(self->desc())->data_type);
+
+ self->rtus_.space_per_thread_ = factor * jcp.is * jcp.ic_block;
+ scratchpad.book(memory_tracking::names::key_conv_rtus_space,
+ typesize * max_threads * self->rtus_.space_per_thread_);
+}
+
+template <cpu_isa_t isa>
+struct rtus_driver_t: public jit_generator {
+
+ struct call_params_t {
+ const void *ws; /* reduced image (w/ strides = 1) */
+ const void *src; /* source image (w/ non-unit strides) */
+ size_t icb;
+ size_t os;
+ size_t iw_start;
+ };
+
+ void (*ker_)(const call_params_t *p);
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(rtus_driver_t)
+
+ /* cpu specific part */
+ using Vmm = typename utils::conditional<isa == avx2, Xbyak::Ymm,
+ Xbyak::Zmm>::type;
+
+ Xbyak::Reg64 reg_ws = abi_param1;
+ Xbyak::Reg64 reg_src = abi_not_param1;
+ Xbyak::Reg64 reg_icb = rdx;
+ Xbyak::Reg64 reg_os = r11;
+ Xbyak::Reg64 reg_iw_start = r8;
+
+ Xbyak::Reg64 reg_cur_os = rax;
+ Xbyak::Reg64 reg_cur_iw = r9;
+ Xbyak::Reg64 reg_cur_src = r10;
+
+ int iw_, stride_w_;
+ int src_step_h_, src_step_icb_, ws_step_icb_, vlen_, vlen_shift_;
+ bool src_to_ws_;
+ size_t typesize_;
+ Vmm reg_zero;
+ Vmm reg_v;
+
+ rtus_driver_t(int iw, int stride_w, int src_step_h,
+ int src_step_icb, int ws_step_icb, bool src_to_ws, size_t typesize)
+ : iw_(iw), stride_w_(stride_w), src_step_h_(src_step_h)
+ , src_step_icb_(src_step_icb), ws_step_icb_(ws_step_icb)
+ , src_to_ws_(src_to_ws), typesize_(typesize)
+ {
+ using namespace Xbyak;
+ vlen_ = cpu_isa_traits<isa>::vlen;
+ vlen_shift_ = cpu_isa_traits<isa>::vlen_shift;
+ if (typesize_ == 2) {
+ vlen_ /= 2;
+ vlen_shift_--;
+ }
+
+ reg_zero = Vmm(0);
+ reg_v = Vmm(1);
+
+ generate();
+ }
+
+ void loop_is() {
+ using namespace Xbyak;
+
+ mov(reg_cur_src, reg_src);
+ mov(reg_cur_iw, reg_iw_start);
+ mov(reg_cur_os, reg_os);
+
+ Label is_loop, skip_h_step;
+ L(is_loop);
+
+ if (src_to_ws_) {
+ vmovups(reg_v, ptr[reg_cur_src]);
+ vmovups(ptr[reg_ws], reg_v);
+ } else {
+ vmovups(reg_v, ptr[reg_ws]);
+ vmovups(ptr[reg_cur_src], reg_v);
+ for (int w = 1; w < stride_w_; ++w)
+ vmovups(ptr[reg_cur_src + w * vlen_], reg_zero);
+ }
+
+ add(reg_ws, vlen_);
+
+ add(reg_cur_iw, stride_w_);
+ add(reg_cur_src, stride_w_ * vlen_);
+
+ cmp(reg_cur_iw, iw_);
+ jl(skip_h_step);
+ /* for 1d convolution the loop over h should be skipped */
+ if (src_step_icb_ == iw_) jmp(skip_h_step);
+
+ if (src_to_ws_) {
+ add(reg_cur_src, (src_step_h_ - iw_) * vlen_);
+ } else {
+ Xbyak::Reg64 reg_cur_src_fin = reg_cur_iw; /* just reuse */
+ mov(reg_cur_src_fin, reg_cur_src);
+ add(reg_cur_src_fin, (src_step_h_ - iw_) * vlen_);
+ Label ih_loop;
+ L(ih_loop);
+
+ for (int w = 0; w < stride_w_; ++w)
+ vmovups(ptr[reg_cur_src + w * vlen_], reg_zero);
+
+ add(reg_cur_src, stride_w_ * vlen_);
+ cmp(reg_cur_src, reg_cur_src_fin);
+ jl(ih_loop);
+ }
+ xor_(reg_cur_iw, reg_cur_iw);
+
+ L(skip_h_step);
+
+ sub(reg_cur_os, vlen_);
+ jnz(is_loop);
+
+ /* restore dst */
+ sub(reg_ws, reg_os);
+ }
+
+ void generate() {
+ using namespace Xbyak;
+ assert(isa == avx2 || isa == avx512_common
+ || isa == avx512_core || isa == avx512_mic);
+
+#if defined(_WIN32)
+ assert(reg_src == abi_not_param1 && abi_not_param1 == rdi);
+ push(rdi);
+#endif
+
+#define READ_PARAM(what) \
+ mov(reg_ ## what, ptr[abi_param1 + offsetof(call_params_t, what)])
+ READ_PARAM(src);
+ READ_PARAM(icb);
+ READ_PARAM(os);
+ READ_PARAM(iw_start);
+
+ assert(reg_ws == abi_param1);
+ READ_PARAM(ws); /* reg_ws should always be read the last */
+#undef READ_PARAM
+
+ shl(reg_os, vlen_shift_);
+
+ if (!src_to_ws_)
+ uni_vpxor(reg_zero, reg_zero, reg_zero);
+
+ Label icb_loop;
+ L(icb_loop);
+
+ loop_is();
+
+ add(reg_ws, ws_step_icb_ * vlen_);
+ add(reg_src, src_step_icb_ * vlen_);
+
+ dec(reg_icb);
+ jnz(icb_loop, T_NEAR);
+
+#if defined(_WIN32)
+ pop(rdi);
+#endif
+
+ uni_vzeroupper();
+ ret();
+ this->ker_ = reinterpret_cast<decltype(ker_)>(const_cast<uint8_t*>(
+ this->getCode()));
+ }
+};
+
+template <cpu_isa_t isa, typename conv_t>
+inline void init_rtus_driver(conv_t *self) {
+ const auto &conf = *self->pd();
+ if (!conf.rtus_.reduce_src_) return;
+
+ const auto &cd = *conf.desc();
+ const int ndims = conf.ndims();
+ const int stride_h = (conf.ndims() == 3) ? 1 : cd.strides[0];
+ const int stride_w = cd.strides[ndims - 3];
+
+ const bool is_bwd_data = cd.prop_kind == prop_kind::backward_data;
+ const auto &src_d = is_bwd_data ? *conf.diff_src_md() : *conf.src_md();
+
+ const int ih = ndims == 3 ? 1 : src_d.dims[2];
+ const int iw = src_d.dims[ndims - 1];
+
+ const int src_step_h = stride_h * iw;
+ const int src_step_icb = ih * iw;
+ const int ws_step_icb = conf.jcp_.is;
+ const bool src_to_ws = !is_bwd_data;
+ const size_t typesize = types::data_type_size(
+ conv_prop_invariant_src_d(self->pd()->desc())->data_type);
+
+ self->rtus_driver_ = new rtus_driver_t<isa>(iw, stride_w, src_step_h,
+ src_step_icb, ws_step_icb, src_to_ws, typesize);
+}
+
+inline int best_divider(int value, int min_divider, int max_divider,
+ bool find_max, int step = 1)
+{
+ max_divider = nstl::max(1, nstl::min(max_divider, value));
+ min_divider = nstl::max(1, nstl::min(min_divider, max_divider));
+
+ auto loss_ratio = [](int total, int chunk)
+ { return float(rnd_up(total, chunk) - total) / rnd_up(total, chunk); };
+
+ float min_loss = FLT_MAX;
+ int x_divider = max_divider;
+ for (int divider = max_divider; divider >= min_divider; divider -= step) {
+ const float loss = loss_ratio(value, divider);
+ if ((find_max && loss < min_loss) || (!find_max && loss <= min_loss)) {
+ min_loss = loss;
+ x_divider = divider;
+ }
+ }
+ return x_divider;
+}
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.cpp
new file mode 100644
index 0000000000..72fe3a8109
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.cpp
@@ -0,0 +1,1407 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "math_utils.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_barrier.hpp"
+#include "cpu_batch_normalization_utils.hpp"
+#include "jit_generator.hpp"
+
+#include "jit_uni_batch_normalization.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace {
+
+using namespace memory_tracking::names;
+
+using namespace Xbyak;
+namespace barrier = simple_barrier;
+
+typedef float data_t;
+
+template <cpu_isa_t isa>
+struct jit_bnorm_t: public jit_generator {
+ struct call_params_t {
+ // keep all sizes at 8 bytes -- jit code expects this
+ size_t N_ithr, N_nthr;
+ size_t coff_max, soff_max;
+ size_t mb_stride_Bc, spat_size, spat_size_loc;
+ size_t S_s, S_tail;
+ size_t is_cblk_tail;
+ data_t chan_size, eps, one;
+ const data_t *scale_shift;
+ const data_t *mean, *var;
+ const data_t *diff_scale_shift;
+ const data_t *src, *dst;
+ const data_t *diff_src, *diff_dst;
+ const data_t *rbuf1, *rbuf2;
+ const uint8_t *ws;
+ barrier::ctx_t *barrier;
+ };
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_bnorm_t)
+
+ /* cpu specific part */
+ using Vmm = typename utils::conditional3<isa == sse42, Xmm,
+ isa == avx2, Ymm, Zmm>::type;
+ const AddressFrame &vmmword = (isa == sse42) ? xword :
+ (isa == avx2) ? yword : zword;
+
+ const int vlen = isa == sse42 ? 32 : cpu_isa_traits<isa>::vlen;
+
+ const batch_normalization_pd_t *bdesc_;
+ bool is_spatial_thr_;
+
+ void (*ker)(const call_params_t *);
+ void operator()(const call_params_t *p) { (*ker)(p); }
+
+ Reg64 reg_param = abi_param1;
+
+ Reg64 reg_scale_shift = rbx;
+ Reg64 reg_rbuf1 = abi_not_param1;
+ Reg64 reg_rbuf2 = rdx;
+
+ Reg64 reg_mean = rbp;
+ Reg64 reg_var = reg_param;
+ Reg64 reg_diff_scale_shift = rax;
+
+ Reg64 reg_coff = r8;
+ Reg64 reg_coff_max = r9;
+ Reg64 reg_soff = r10;
+ Reg64 reg_soff_max = r11;
+ Reg64 reg_ctr = r12;
+ Reg64 reg_roff = r13;
+
+ Reg64 reg_mb_stride_Bc = r14;
+
+ Reg64 reg_src = r15;
+ Reg64 reg_diff_src = reg_rbuf1;
+ Reg64 reg_dst = rsi;
+ Reg64 reg_diff_dst = reg_dst;
+
+ Reg64 reg_tmp_off = reg_roff;
+
+ // Reuse loop counters
+ Reg64 reg_bar = reg_coff;
+ Reg64 reg_nnthr = reg_soff; // must be usable w/ loops over coff
+ Reg64 reg_tmp = reg_ctr;
+
+ // Relu section
+ bool with_relu, with_relu_inf_only;
+ Vmm vzero; // is_fwd() ? vdiff_beta : vbeta
+ Reg64 reg_ws = reg_roff;
+ Label l_relu_mask_avx2;
+ Opmask kstore_mask = Opmask(1);
+
+ // channel tail processing
+ Opmask ktail_mask = Opmask(2);
+
+ size_t unroll_blocks;
+ size_t unroll_regs;
+ Vmm vbuf = Vmm(isa == avx512_common ? 20 : 5);
+ Vmm vdiff_beta = Vmm(isa == avx512_common ? 21 : 6);
+ Vmm vdiff_gamma = Vmm(isa == avx512_common ? 22 : 7);
+ Vmm vsqrtvar = Vmm(isa == avx512_common ? 23 : 8);
+ Vmm vone = Vmm(isa == avx512_common ? 24 : 9);
+ Vmm vmean = Vmm(isa == avx512_common ? 25 : 10);
+ Vmm vgamma = Vmm(isa == avx512_common ? 26 : 11);
+ Vmm vbeta = Vmm(isa == avx512_common ? 27 : 12);
+ Vmm veps = Vmm(isa == avx512_common ? 28 : 13);
+ Vmm vchan_size = Vmm(isa == avx512_common ? 29 : 14);
+ Vmm vtail_mask = Vmm(isa == avx512_common ? 30 : 15);
+
+ size_t t0_pf_offt;
+ size_t t1_pf_offt;
+ size_t spat_size;
+ size_t chan_data_offt;
+
+ enum {
+ stack_off_N_nthr = 0,
+ stack_off_N_ithr = 8,
+ stack_off_src = 16,
+ stack_off_dst = 24,
+ stack_off_diff_src = 32,
+ stack_off_diff_dst = 40,
+ stack_off_diff_scale_shift = 48,
+ stack_off_ws = 56,
+ stack_off_barrier = 64,
+ stack_off_spat_size_loc = 72,
+ stack_off_s_s = 80,
+ stack_off_s_tail = 88,
+ stack_off_is_cblk_tail = 96,
+ stack_size_required = 104,
+ };
+
+ bool is_c_padded() const {
+ const memory_desc_wrapper data_d(bdesc_->src_md());
+ return bdesc_->C() != data_d.padded_dims()[1];
+ }
+
+ void compute_static_strides() {
+ spat_size = bdesc_->D() * bdesc_->W() * bdesc_->H();
+ chan_data_offt = bdesc_->C() * sizeof(data_t);
+
+ if (isa == avx512_mic) {
+ t0_pf_offt = 4096;
+ t1_pf_offt = 0;
+ } else {
+ t0_pf_offt = 0;
+ t1_pf_offt = 0;
+ }
+ }
+
+ void load_common_params() {
+# define PARAM_OFF(x) offsetof(call_params_t, x)
+ mov(reg_rbuf1, ptr[reg_param + PARAM_OFF(rbuf1)]);
+ if (bdesc_->is_bwd())
+ mov(reg_rbuf2, ptr[reg_param + PARAM_OFF(rbuf2)]);
+ mov(reg_coff_max, ptr[reg_param + PARAM_OFF(coff_max)]);
+ mov(reg_soff_max, ptr[reg_param + PARAM_OFF(soff_max)]);
+ mov(reg_mb_stride_Bc, ptr[reg_param + PARAM_OFF(mb_stride_Bc)]);
+ shl(reg_coff_max, 2);
+ shl(reg_soff_max, 2);
+ shl(reg_mb_stride_Bc, 2);
+
+ mov(reg_mean, ptr[reg_param + PARAM_OFF(mean)]);
+ mov(reg_scale_shift, ptr[reg_param + PARAM_OFF(scale_shift)]);
+
+ uni_vbroadcastss(vchan_size, vmmword[reg_param + PARAM_OFF(chan_size)]);
+ uni_vbroadcastss(vone, vmmword[reg_param + PARAM_OFF(one)]);
+ uni_vbroadcastss(veps, vmmword[reg_param + PARAM_OFF(eps)]);
+
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(N_nthr)]);
+ mov(ptr[rsp + stack_off_N_nthr], reg_tmp);
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(N_ithr)]);
+ mov(ptr[rsp + stack_off_N_ithr], reg_tmp);
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(src)]);
+ mov(ptr[rsp + stack_off_src], reg_tmp);
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(dst)]);
+ mov(ptr[rsp + stack_off_dst], reg_tmp);
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(diff_src)]);
+ mov(ptr[rsp + stack_off_diff_src], reg_tmp);
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(diff_dst)]);
+ mov(ptr[rsp + stack_off_diff_dst], reg_tmp);
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(ws)]);
+ mov(ptr[rsp + stack_off_ws], reg_tmp);
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(barrier)]);
+ mov(ptr[rsp + stack_off_barrier], reg_tmp);
+ if (is_spatial_thr_) {
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(spat_size_loc)]);
+ mov(ptr[rsp + stack_off_spat_size_loc], reg_tmp);
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(S_s)]);
+ mov(ptr[rsp + stack_off_s_s], reg_tmp);
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(S_tail)]);
+ mov(ptr[rsp + stack_off_s_tail], reg_tmp);
+ }
+ if (is_c_padded()) {
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(is_cblk_tail)]);
+ mov(ptr[rsp + stack_off_is_cblk_tail], reg_tmp);
+ }
+
+ if (bdesc_->is_fwd()) {
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(var)]);
+ mov(reg_var, reg_tmp);
+ } else {
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(diff_scale_shift)]);
+ mov(ptr[rsp + stack_off_diff_scale_shift], reg_tmp);
+ mov(reg_tmp, ptr[reg_param + PARAM_OFF(var)]);
+ mov(reg_var, reg_tmp);
+ }
+# undef PARAM_OFF
+ }
+
+ void prepare_tail_mask_avx512_common() {
+ if (!is_c_padded()) return;
+
+ const int tail = bdesc_->C() % (int)(vlen / sizeof(float));
+ const int mask = (1 << tail) - 1;
+
+ Reg32 regw_tmp = reg_tmp.cvt32();
+ mov(regw_tmp, mask);
+ kmovw(ktail_mask, regw_tmp);
+ }
+
+ void prepare_tail_mask_avx2_common() {
+ if (!is_c_padded()) return;
+
+ const int tail = bdesc_->C() % (int)(vlen / sizeof(float));
+ static const uint32_t mask[16] = {0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+ mov(reg_tmp, reinterpret_cast<size_t>(&mask[8 - tail]));
+ vmovups(vtail_mask, ptr[reg_tmp]);
+ }
+
+ void prepare_relu() {
+ with_relu = bdesc_->is_fwd()
+ ? bdesc_->with_relu_post_op() || bdesc_->fuse_bn_relu()
+ : bdesc_->fuse_bn_relu();
+ with_relu_inf_only = with_relu && bdesc_->is_fwd()
+ && !(bdesc_->fuse_bn_relu() && bdesc_->is_training());
+
+ vzero = bdesc_->is_fwd() ? vdiff_beta : vbeta;
+ if (with_relu) {
+ uni_vpxor(vzero, vzero, vzero);
+ if (!bdesc_->is_fwd() && isa == avx2)
+ prepare_l_relu_mask_avx2();
+ }
+ }
+
+ void prepare_l_relu_mask_avx2() {
+ Label l_mask_after;
+ jmp(l_mask_after);
+ align(32);
+ L(l_relu_mask_avx2); /* [0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01] */
+ for (int i = 0; i < 8; ++i) dd(1<<i);
+ L(l_mask_after);
+ }
+
+ void fwd_process_relu_avx2(Vmm vdst, int offt, Vmm vstore_mask) {
+ Reg64 reg_store_mask = reg_diff_scale_shift;
+ shr(reg_soff, 5);
+ vcmpps(vstore_mask, vzero, vdst, _cmp_lt_os);
+ vmovmskps(reg_store_mask, vstore_mask);
+ mov(ptr[reg_ws + reg_soff + offt / (1 << 5)], reg_store_mask.cvt8());
+ vblendvps(vdst, vzero, vdst, vstore_mask);
+ shl(reg_soff, 5);
+ }
+
+ void fwd_process_relu_avx512_common(Vmm vdst, int offt) {
+ shr(reg_soff, 5);
+ vcmpps(kstore_mask, vzero, vdst, _cmp_lt_os);
+ kmovw(ptr[reg_ws + reg_soff + offt / (1 << 5)], kstore_mask);
+ vblendmps(vdst | kstore_mask, vzero, vdst);
+ shl(reg_soff, 5);
+ }
+
+ void bwd_process_relu_avx2(Vmm vdiff_dst, int offt, Vmm vstore_mask) {
+ shr(reg_soff, 5);
+ vpbroadcastb(vstore_mask, ptr[reg_ws + reg_soff + offt / (1 << 5)]);
+ vpand(vstore_mask, vstore_mask, ptr[rip + l_relu_mask_avx2]);
+ vpcmpeqd(vstore_mask, vstore_mask, ptr[rip + l_relu_mask_avx2]);
+ vblendvps(vdiff_dst, vzero, vdiff_dst, vstore_mask);
+ shl(reg_soff, 5);
+ }
+
+ void bwd_process_relu_avx512_common(Vmm vdiff_dst, int offt) {
+ shr(reg_soff, 5);
+ kmovw(kstore_mask, ptr[reg_ws + reg_soff + offt / (1 << 5)]);
+ vmovups(vdiff_dst | kstore_mask | T_z, vdiff_dst);
+ shl(reg_soff, 5);
+ }
+
+ void uni_vmovups_tail_avx2_common(const Operand &dst,
+ const Operand &src, Label &l_ret) {
+ if (dst.isMEM()) {
+ vmaskmovps(dst.getAddress(), vtail_mask, Vmm(src.getIdx()));
+ } else {
+ vmaskmovps(Vmm(dst.getIdx()), vtail_mask, src.getAddress());
+ }
+ jmp(l_ret);
+ }
+
+ void uni_vmovups_tail_avx512_common(const Operand &dst,
+ const Operand &src, Label &l_ret) {
+ if (dst.isMEM())
+ uni_vmovups(dst.getAddress() | ktail_mask | T_z, Vmm(src.getIdx()));
+ else
+ uni_vmovups(Vmm(dst.getIdx()) | ktail_mask | T_z, src.getAddress());
+
+ jmp(l_ret);
+ }
+
+ void uni_vmovups_maybe_tail(const Operand &dst, const Operand &src) {
+ Label l_no_mask, l_ret;
+
+ if (is_c_padded()) {
+ mov(reg_tmp, ptr[rsp + stack_off_is_cblk_tail]);
+ cmp(reg_tmp, 0);
+ jz(l_no_mask);
+
+ lea(reg_tmp, ptr[reg_coff + vlen]);
+ cmp(reg_tmp, reg_coff_max);
+ jl(l_no_mask);
+ assert(isa == avx512_common || isa == avx2);
+ if (isa == avx512_common)
+ uni_vmovups_tail_avx512_common(dst, src, l_ret);
+ else if (isa == avx2)
+ uni_vmovups_tail_avx2_common(dst, src, l_ret);
+ }
+ L(l_no_mask);
+ if (dst.isMEM())
+ uni_vmovups(dst.getAddress(), Vmm(src.getIdx()));
+ else
+ uni_vmovups(Vmm(dst.getIdx()), src.getAddress());
+
+ L(l_ret);
+ }
+
+ void barrier() {
+ mov(reg_nnthr, ptr[rsp + stack_off_N_nthr]);
+ mov(reg_bar, ptr[rsp + stack_off_barrier]);
+ simple_barrier::generate(*this, reg_bar, reg_nnthr);
+ }
+
+ Address mean_ptr(size_t offt = 0) {
+ return vmmword[reg_mean + reg_coff + offt + 0 * chan_data_offt];
+ }
+
+ Address var_ptr(size_t offt = 0) {
+ return vmmword[reg_var + reg_coff + offt + 0 * chan_data_offt];
+ }
+
+ Address diff_gamma_ptr(size_t offt = 0) {
+ return vmmword[reg_diff_scale_shift + reg_coff + offt
+ + 0 * chan_data_offt];
+ }
+
+ Address diff_beta_ptr(size_t offt = 0) {
+ return vmmword[reg_diff_scale_shift + reg_coff + offt
+ + 1 * chan_data_offt];
+ }
+
+ Address gamma_ptr(size_t offt = 0) {
+ return vmmword[reg_scale_shift + reg_coff + offt + 0 * chan_data_offt];
+ }
+
+ Address beta_ptr(size_t offt = 0) {
+ return vmmword[reg_scale_shift + reg_coff + offt + 1 * chan_data_offt];
+ }
+
+ template <typename init_t, typename body_t, typename fini_t>
+ void spat_loop(size_t len, size_t blocks, size_t regs,
+ init_t init, body_t body, fini_t fini) {
+ size_t factor = regs * blocks;
+ size_t loop_unroll = len / factor * factor;
+ size_t loop_tail = len - loop_unroll;
+ size_t num_active_regs = (len < regs) ? len : regs;
+ for (size_t i = 0; i < num_active_regs; i++)
+ init(i);
+ if (loop_unroll) {
+ if (is_spatial_thr_) {
+ mov(reg_ctr, ptr[rsp + stack_off_spat_size_loc]);
+ add(reg_soff, ptr[rsp + stack_off_s_s]);
+ } else {
+ mov(reg_ctr, loop_unroll);
+ }
+ Label label;
+ L(label); {
+ for (size_t i = 0; i < factor; i++) {
+ size_t base_reg = i % regs;
+ body(base_reg, i);
+ }
+ add(reg_soff, factor * vlen);
+ sub(reg_ctr, factor);
+ jnz(label);
+ }
+ if (is_spatial_thr_) {
+ add(reg_soff, ptr[rsp + stack_off_s_tail]);
+ }
+ }
+
+ for (size_t i = 0; i < loop_tail; i++) {
+ size_t base_reg = i % regs;
+ body(base_reg, i);
+ }
+ if (loop_tail)
+ add(reg_soff, loop_tail * vlen);
+
+ for (size_t i = 0; i < num_active_regs; i++)
+ fini(i);
+ }
+
+ void mean_channels() {
+ Label ch_label;
+ L(ch_label); {
+ uni_vmovups(Vmm(0), vmmword[reg_rbuf1 + reg_coff]);
+ spat_loop(spat_size, unroll_blocks,
+ unroll_regs,
+ [=](size_t base_reg) {
+ Vmm v = Vmm(base_reg * 2);
+ if (base_reg)
+ uni_vpxor(v, v, v);
+ },
+ [=](size_t base_reg, size_t i) {
+ Vmm v0 = Vmm(base_reg * 2 + 0);
+ Vmm v1 = Vmm(base_reg * 2 + 1);
+ size_t offt = i * vlen;
+ uni_vmovups(v1,
+ vmmword[reg_src + reg_soff + offt]);
+ uni_vaddps(v0, v0, v1);
+ mic_prefetcht0(ptr[reg_src + reg_soff + offt
+ + t0_pf_offt]);
+ mic_prefetcht1(ptr[reg_src + reg_soff + offt
+ + t1_pf_offt]);
+ },
+ [=](size_t base_reg) {
+ Vmm b = Vmm(0);
+ Vmm v = Vmm(base_reg * 2);
+ if (base_reg)
+ uni_vaddps(b, b, v);
+ });
+ uni_vmovups(vmmword[reg_rbuf1 + reg_coff], Vmm(0));
+
+ add(reg_coff, vlen);
+ cmp(reg_coff, reg_coff_max);
+ jl(ch_label);
+ }
+ }
+
+ void var_channels() {
+ Label ch_label;
+ L(ch_label); {
+ uni_vmovups_maybe_tail(vmean, mean_ptr());
+ uni_vmovups(Vmm(0), vmmword[reg_rbuf1 + reg_coff]);
+ spat_loop(spat_size, unroll_blocks, unroll_regs,
+ [=](size_t base_reg) {
+ Vmm v = Vmm(base_reg * 3);
+ if (base_reg > 0)
+ uni_vpxor(v, v, v);
+ },
+ [=](size_t base_reg, size_t i) {
+ Vmm v = Vmm(3 * base_reg);
+ Vmm vtmp0 = Vmm(3 * base_reg + 1);
+ Vmm vtmp1 = Vmm(3 * base_reg + 2);
+ size_t offt = i * vlen;
+ uni_vmovups(vtmp0,
+ vmmword[reg_src + reg_soff + offt]);
+ if (isa == sse42) {
+ movups(vtmp1, vmean);
+ subps(vtmp1, vtmp0);
+ } else {
+ vsubps(vtmp1, vmean, vtmp0);
+ }
+ uni_vfmadd231ps(v, vtmp1, vtmp1);
+
+ mic_prefetcht0(ptr[reg_src + reg_soff + offt
+ + t0_pf_offt]);
+ mic_prefetcht1(ptr[reg_src + reg_soff + offt
+ + t1_pf_offt]);
+ },
+ [=](size_t base_reg) {
+ Vmm b = Vmm(0);
+ Vmm v = Vmm(base_reg * 3);
+ if (base_reg)
+ uni_vaddps(b, b, v);
+ });
+ uni_vmovups(vmmword[reg_rbuf1 + reg_coff], Vmm(0));
+ add(reg_coff, vlen);
+ cmp(reg_coff, reg_coff_max);
+ jl(ch_label);
+ }
+ }
+
+ void compute_mean_variance() {
+ uni_vpxor(Vmm(0), Vmm(0), Vmm(0));
+ xor_(reg_coff, reg_coff);
+ Label zero_rbuf;
+ L(zero_rbuf); {
+ uni_vmovups(vmmword[reg_rbuf1 + reg_coff], Vmm(0));
+ add(reg_coff, isa == sse42 ? vlen / 2 : vlen);
+ cmp(reg_coff, reg_coff_max);
+ jne(zero_rbuf);
+ }
+
+ mov(reg_src, ptr[rsp + stack_off_src]);
+
+ xor_(reg_soff, reg_soff);
+ Label mean_spatial;
+ L(mean_spatial); {
+ xor_(reg_coff, reg_coff);
+
+ if (isa == sse42)
+ mov(reg_tmp_off, reg_soff);
+
+ mean_channels();
+
+ if (isa == sse42) {
+ mov(reg_soff, reg_tmp_off);
+ add(reg_src, vlen / 2);
+ mov(reg_coff, vlen / 2);
+
+ mean_channels();
+
+ sub(reg_src, vlen / 2);
+ }
+
+ add(reg_soff, reg_mb_stride_Bc);
+ cmp(reg_soff, reg_soff_max);
+ jne(mean_spatial);
+ }
+
+ Label no_mean_reduction;
+ barrier(); {
+ mov(reg_tmp, ptr[rsp + stack_off_N_ithr]);
+ cmp(reg_tmp, 0);
+ jne(no_mean_reduction);
+ mov(reg_nnthr, ptr[rsp + stack_off_N_nthr]);
+ xor_(reg_coff, reg_coff);
+ Label mean_reduction_channels;
+ L(mean_reduction_channels); {
+ mov(reg_roff, reg_coff);
+ uni_vpxor(Vmm(0), Vmm(0), Vmm(0));
+ uni_vpxor(Vmm(1), Vmm(1), Vmm(1));
+ mov(reg_ctr, reg_nnthr);
+ Label mean_reduction_thrs;
+ L(mean_reduction_thrs); {
+ uni_vaddps(Vmm(1), Vmm(1), vmmword[reg_rbuf1 + reg_roff]);
+ uni_vmovups(vmmword[reg_rbuf1 + reg_roff], Vmm(0));
+ add(reg_roff, reg_coff_max);
+ sub(reg_ctr, 1);
+ jnz(mean_reduction_thrs);
+ }
+ uni_vdivps(Vmm(1), Vmm(1), vchan_size);
+ uni_vmovups_maybe_tail(mean_ptr(), Vmm(1));
+
+ add(reg_coff, isa == sse42 ? vlen / 2 : vlen);
+
+ cmp(reg_coff, reg_coff_max);
+ jne(mean_reduction_channels);
+ }
+ }
+ L(no_mean_reduction);
+ barrier();
+
+ xor_(reg_soff, reg_soff);
+ Label var_spatial;
+ L(var_spatial); {
+ xor_(reg_coff, reg_coff);
+
+ if (isa == sse42)
+ mov(reg_tmp_off, reg_soff);
+
+ var_channels();
+
+ if (isa == sse42) {
+ mov(reg_soff, reg_tmp_off);
+ add(reg_src, vlen / 2);
+ mov(reg_coff, vlen / 2);
+
+ var_channels();
+
+ sub(reg_src, vlen / 2);
+ }
+
+ add(reg_soff, reg_mb_stride_Bc);
+ cmp(reg_soff, reg_soff_max);
+ jne(var_spatial);
+ }
+
+ Label no_var_reduction;
+ barrier(); {
+ mov(reg_tmp, ptr[rsp + stack_off_N_ithr]);
+ cmp(reg_tmp, 0);
+ jne(no_var_reduction);
+
+ mov(reg_nnthr, ptr[rsp + stack_off_N_nthr]);
+ xor_(reg_coff, reg_coff);
+ Label var_reduction_channels;
+ L(var_reduction_channels); {
+ mov(reg_roff, reg_coff);
+ uni_vpxor(Vmm(1), Vmm(1), Vmm(1));
+ mov(reg_ctr, reg_nnthr);
+ Label var_reduction_thrs;
+ L(var_reduction_thrs); { // TODO: unroll (?)
+ uni_vaddps(Vmm(1), Vmm(1), vmmword[reg_rbuf1 + reg_roff]);
+ add(reg_roff, reg_coff_max);
+ sub(reg_ctr, 1);
+ jnz(var_reduction_thrs);
+ }
+ uni_vdivps(Vmm(1), Vmm(1), vchan_size);
+ uni_vmovups_maybe_tail(var_ptr(), Vmm(1));
+ add(reg_coff, isa == sse42 ? vlen / 2 : vlen);
+
+ cmp(reg_coff, reg_coff_max);
+ jne(var_reduction_channels);
+ }
+ }
+ L(no_var_reduction);
+ barrier();
+ }
+
+ void forward_channels() {
+ Label ch_label;
+ L(ch_label); {
+ uni_vmovups_maybe_tail(vmean, mean_ptr());
+ uni_vmovups_maybe_tail(vsqrtvar, var_ptr());
+ uni_vaddps(vsqrtvar, vsqrtvar, veps);
+ uni_vsqrtps(vsqrtvar, vsqrtvar);
+
+ if (bdesc_->use_scaleshift()) {
+ uni_vmovups_maybe_tail(vgamma, gamma_ptr());
+ uni_vmovups_maybe_tail(vbeta, beta_ptr());
+ }
+
+ Vmm vscale = bdesc_->use_scaleshift() ? vgamma : vone;
+ Vmm vdiv = bdesc_->use_scaleshift() ? vgamma : vsqrtvar;
+
+ if (isa == sse42) {
+ movups(vbuf, vscale);
+ divps(vbuf, vsqrtvar);
+ movups(vdiv, vbuf);
+ } else {
+ vdivps(vdiv, vscale, vsqrtvar);
+ }
+
+ auto compute = [=](bool output_is_aligned) {
+ spat_loop(spat_size, unroll_blocks, unroll_regs,
+ [](size_t base_reg) {UNUSED(base_reg);},
+ [=](size_t base_reg, size_t i) {
+ Vmm v = Vmm(base_reg);
+ size_t offt = i * vlen;
+ uni_vmovups(v,
+ vmmword[reg_src + reg_soff + offt]);
+ mic_prefetcht0(ptr[reg_src + reg_soff + offt
+ + t0_pf_offt]);
+ mic_prefetcht1(ptr[reg_src + reg_soff + offt
+ + t1_pf_offt]);
+ uni_vsubps(v, v, vmean);
+ if (bdesc_->use_scaleshift()) {
+ uni_vfmadd213ps(v, vgamma, vbeta);
+ } else {
+ uni_vmulps(v, v, vsqrtvar);
+ }
+ if (with_relu_inf_only) {
+ uni_vmaxps(v, v, vzero);
+ } else if (with_relu) {
+ if (isa == avx512_common)
+ fwd_process_relu_avx512_common(v, offt);
+ else
+ fwd_process_relu_avx2(v, offt, Vmm(3));
+ }
+ if (output_is_aligned) {
+ uni_vmovntps(
+ vmmword[reg_dst + reg_soff + offt], v);
+ } else {
+ uni_vmovups(
+ vmmword[reg_dst + reg_soff + offt], v);
+ }
+ },
+ [](size_t base_reg) {UNUSED(base_reg);});
+ };
+
+ Label unaligned_store, end_store;
+ test(reg_dst, vlen - 1);
+ jnz(unaligned_store, T_NEAR);
+ compute(true);
+ jmp(end_store, T_NEAR);
+ L(unaligned_store); {
+ compute(false);
+ }
+ L(end_store);
+
+ add(reg_coff, vlen);
+ cmp(reg_coff, reg_coff_max);
+ jl(ch_label);
+ }
+ }
+
+ void forward() {
+ mov(reg_src, ptr[rsp + stack_off_src]);
+ mov(reg_dst, ptr[rsp + stack_off_dst]);
+ mov(reg_ws, ptr[rsp + stack_off_ws]);
+
+ xor_(reg_soff, reg_soff);
+ Label dst_spatial;
+ L(dst_spatial); {
+ xor_(reg_coff, reg_coff);
+ if (isa == sse42)
+ mov(reg_tmp_off, reg_soff);
+
+ forward_channels();
+
+ if (isa == sse42) {
+ mov(reg_soff, reg_tmp_off);
+ add(reg_src, vlen / 2);
+ add(reg_dst, vlen / 2);
+ mov(reg_coff, vlen / 2);
+
+ forward_channels();
+
+ sub(reg_src, vlen / 2);
+ sub(reg_dst, vlen / 2);
+ }
+
+ add(reg_soff, reg_mb_stride_Bc);
+ cmp(reg_soff, reg_soff_max);
+ jnz(dst_spatial);
+ }
+ }
+
+ void backward_sh_channels() {
+ Label sh_channels;
+ L(sh_channels); {
+ uni_vmovups_maybe_tail(vmean, mean_ptr());
+ uni_vmovups(Vmm(0), vmmword[reg_rbuf1 + reg_coff]);
+ uni_vmovups(Vmm(1), vmmword[reg_rbuf2 + reg_coff]);
+ spat_loop(spat_size, 1, 1,
+ [=](size_t base_reg) {
+ if (base_reg > 0) {
+ for (int i = 0; i < 2; i++) {
+ Vmm v(base_reg * 5 + i);
+ uni_vpxor(v, v, v);
+ }
+ }
+ },
+ [=](size_t base_reg, size_t i) {
+ Vmm o0 = Vmm(base_reg * 5 + 0);
+ Vmm o1 = Vmm(base_reg * 5 + 1);
+ Vmm t1 = Vmm(base_reg * 5 + 2);
+ Vmm t2 = Vmm(base_reg * 5 + 3);
+ Vmm t3 = Vmm(base_reg * 5 + 4);
+ size_t offt = i * vlen;
+ uni_vmovups(t1, vmmword[reg_src + reg_soff + offt]);
+ uni_vmovups(t2, vmmword[reg_diff_dst + reg_soff
+ + offt]);
+ if (with_relu) {
+ if (isa == avx512_common)
+ bwd_process_relu_avx512_common(t2, offt);
+ else if (isa == avx2)
+ bwd_process_relu_avx2(t2, offt, t3);
+ else
+ assert(false);
+ }
+ uni_vsubps(t3, vmean, t1, t3);
+ if (isa == sse42) {
+ mulps(t3, t2);
+ subps(o0, t3);
+ } else {
+ vfnmadd231ps(o0, t3, t2);
+ }
+ uni_vaddps(o1, o1, t2);
+ mic_prefetcht0(ptr[reg_diff_dst + reg_soff + offt
+ + t0_pf_offt]);
+ mic_prefetcht0(ptr[reg_src + reg_soff + offt
+ + t0_pf_offt]);
+ mic_prefetcht1(ptr[reg_diff_dst + reg_soff + offt
+ + t1_pf_offt]);
+ mic_prefetcht1(ptr[reg_src + reg_soff + offt
+ + t1_pf_offt]);
+ },
+ [=](size_t base_reg) {
+ Vmm b0 = Vmm(0);
+ Vmm b1 = Vmm(1);
+ if (base_reg) {
+ uni_vaddps(b0, b0, Vmm(base_reg * 5 + 0));
+ uni_vaddps(b1, b1, Vmm(base_reg * 5 + 1));
+ }
+ });
+ uni_vmovups(vmmword[reg_rbuf1 + reg_coff], Vmm(0));
+ uni_vmovups(vmmword[reg_rbuf2 + reg_coff], Vmm(1));
+ add(reg_coff, vlen);
+ cmp(reg_coff, reg_coff_max);
+ jl(sh_channels);
+ }
+ }
+
+ void backward_diff_channels() {
+ Label diff_channels;
+ L(diff_channels); {
+ uni_vmovups_maybe_tail(vmean, mean_ptr());
+ uni_vmovups_maybe_tail(vsqrtvar, var_ptr());
+ uni_vaddps(vsqrtvar, vsqrtvar, veps);
+ uni_vsqrtps(vsqrtvar, vsqrtvar);
+ uni_vdivps(vsqrtvar, vone, vsqrtvar, vbuf);
+ if (bdesc_->use_scaleshift())
+ uni_vmovups_maybe_tail(vgamma, gamma_ptr());
+ uni_vmovups_maybe_tail(vdiff_gamma, diff_gamma_ptr());
+ uni_vmovups_maybe_tail(vdiff_beta, diff_beta_ptr());
+ uni_vmulps(vdiff_gamma, vdiff_gamma, vsqrtvar);
+ uni_vdivps(vdiff_beta, vdiff_beta, vchan_size);
+ uni_vdivps(vdiff_gamma, vdiff_gamma, vchan_size);
+
+ auto compute = [=](bool output_is_aligned) {
+ spat_loop(spat_size, unroll_blocks, unroll_regs,
+ [=](size_t base_reg) {UNUSED(base_reg);},
+ [=](size_t base_reg, size_t i) {
+ Vmm v(base_reg * 2 + 0);
+ Vmm t(base_reg * 2 + 1);
+ Vmm t1(base_reg * 2 + 2);
+ size_t offt = i * vlen;
+ uni_vmovups(v, vmmword[reg_diff_dst + reg_soff
+ + offt]);
+ if (with_relu) {
+ if (isa == avx512_common)
+ bwd_process_relu_avx512_common(v, offt);
+ else if (isa == avx2)
+ bwd_process_relu_avx2(v, offt, t);
+ else
+ assert(false);
+ }
+ if (!bdesc_->use_global_stats()) {
+ uni_vsubps(v, v, vdiff_beta);
+ uni_vmovups(t, vmmword[reg_src + reg_soff
+ + offt]);
+ uni_vsubps(t, vmean, t, t1);
+ uni_vmulps(t, t, vdiff_gamma);
+ uni_vaddps(v, v, t);
+ }
+ uni_vmulps(v, v, vsqrtvar);
+ if (bdesc_->use_scaleshift()) {
+ uni_vmulps(v, v, vgamma);
+ }
+ if (output_is_aligned) {
+ uni_vmovntps(
+ vmmword[reg_diff_src + reg_soff + offt],
+ v);
+ } else {
+ uni_vmovups(
+ vmmword[reg_diff_src + reg_soff + offt],
+ v);
+ }
+ mic_prefetcht0(ptr[reg_diff_dst + reg_soff + offt
+ + t0_pf_offt]);
+ mic_prefetcht0(ptr[reg_src + reg_soff + offt
+ + t0_pf_offt]);
+ mic_prefetcht1(ptr[reg_diff_dst + reg_soff
+ + offt + t1_pf_offt]);
+ mic_prefetcht1(ptr[reg_src + reg_soff + offt
+ + t1_pf_offt]);
+ },
+ [=](size_t base_reg) {UNUSED(base_reg);});
+ };
+
+ Label unaligned_store, end_store;
+ test(reg_diff_src, vlen - 1);
+ jnz(unaligned_store, T_NEAR);
+ compute(true);
+ jmp(end_store, T_NEAR);
+ L(unaligned_store); {
+ compute(false);
+ }
+ L(end_store);
+
+ add(reg_coff, vlen);
+ cmp(reg_coff, reg_coff_max);
+ jl(diff_channels);
+ }
+ }
+
+ void backward() {
+ uni_vpxor(Vmm(0), Vmm(0), Vmm(0));
+ xor_(reg_coff, reg_coff);
+ Label zero_rbuf, sh_spatial;
+
+ L(zero_rbuf); {
+ uni_vmovups(vmmword[reg_rbuf1 + reg_coff], Vmm(0));
+ uni_vmovups(vmmword[reg_rbuf2 + reg_coff], Vmm(0));
+ add(reg_coff, isa == sse42 ? vlen / 2 : vlen);
+ cmp(reg_coff, reg_coff_max);
+ jne(zero_rbuf);
+ }
+
+ mov(reg_src, ptr[rsp + stack_off_src]);
+ mov(reg_diff_dst, ptr[rsp + stack_off_diff_dst]);
+ if (with_relu) {
+ assert(isa == avx2 || isa == avx512_common);
+ mov(reg_ws, ptr[rsp + stack_off_ws]);
+ }
+
+ xor_(reg_soff, reg_soff);
+ L(sh_spatial); {
+ xor_(reg_coff, reg_coff);
+ if (isa == sse42) {
+ mov(reg_tmp_off, reg_soff);
+ }
+ backward_sh_channels();
+ if (isa == sse42) {
+ mov(reg_soff, reg_tmp_off);
+ add(reg_diff_dst, vlen / 2);
+ add(reg_src, vlen / 2);
+ mov(reg_coff, vlen / 2);
+ backward_sh_channels();
+ sub(reg_diff_dst, vlen / 2);
+ sub(reg_src, vlen / 2);
+ }
+ add(reg_soff, reg_mb_stride_Bc);
+ cmp(reg_soff, reg_soff_max);
+ jne(sh_spatial);
+ }
+
+ mov(reg_diff_scale_shift, ptr[rsp + stack_off_diff_scale_shift]);
+
+ Label no_sh_reduction;
+ barrier(); {
+ mov(reg_tmp, ptr[rsp + stack_off_N_ithr]);
+ cmp(reg_tmp, 0);
+ Label sh_reduction_channels;
+ jne(no_sh_reduction, T_NEAR);
+
+ mov(reg_nnthr, ptr[rsp + stack_off_N_nthr]);
+ xor_(reg_coff, reg_coff);
+ L(sh_reduction_channels); {
+ mov(reg_roff, reg_coff);
+ uni_vpxor(Vmm(0), Vmm(0), Vmm(0));
+ uni_vpxor(Vmm(1), Vmm(1), Vmm(1));
+ uni_vmovups_maybe_tail(vsqrtvar, var_ptr());
+ uni_vaddps(vsqrtvar, vsqrtvar, veps);
+ uni_vsqrtps(vsqrtvar, vsqrtvar);
+ uni_vdivps(vsqrtvar, vone, vsqrtvar, vbuf);
+ mov(reg_ctr, reg_nnthr);
+ Label sh_reduction_thrs;
+ L(sh_reduction_thrs); { // TODO: unroll (?)
+ uni_vaddps(Vmm(0), Vmm(0), vmmword[reg_rbuf1 + reg_roff]);
+ uni_vaddps(Vmm(1), Vmm(1), vmmword[reg_rbuf2 + reg_roff]);
+ add(reg_roff, reg_coff_max);
+ sub(reg_ctr, 1);
+ jnz(sh_reduction_thrs);
+ }
+ uni_vmulps(Vmm(0), Vmm(0), vsqrtvar);
+ uni_vmovups_maybe_tail(diff_gamma_ptr(), Vmm(0));
+ uni_vmovups_maybe_tail(diff_beta_ptr(), Vmm(1));
+ add(reg_coff, isa == sse42 ? vlen / 2 : vlen);
+ cmp(reg_coff, reg_coff_max);
+ jne(sh_reduction_channels);
+ }
+ }
+ L(no_sh_reduction);
+ barrier();
+
+ mov(reg_diff_src, ptr[rsp + stack_off_diff_src]);
+ if (with_relu) {
+ assert(isa == avx2 || isa == avx512_common);
+ mov(reg_ws, ptr[rsp + stack_off_ws]);
+ }
+
+ xor_(reg_soff, reg_soff);
+ Label diff_spatial;
+ L(diff_spatial); {
+ xor_(reg_coff, reg_coff);
+ if (isa == sse42) {
+ mov(reg_tmp_off, reg_soff);
+ }
+ backward_diff_channels();
+ if (isa == sse42) {
+ mov(reg_soff, reg_tmp_off);
+ add(reg_diff_dst, vlen / 2);
+ add(reg_diff_src, vlen / 2);
+ add(reg_src, vlen / 2);
+ mov(reg_coff, vlen / 2);
+ backward_diff_channels();
+ sub(reg_diff_dst, vlen / 2);
+ sub(reg_diff_src, vlen / 2);
+ sub(reg_src, vlen / 2);
+ }
+ add(reg_soff, reg_mb_stride_Bc);
+ cmp(reg_soff, reg_soff_max);
+ jne(diff_spatial);
+ }
+ }
+
+ jit_bnorm_t(const batch_normalization_pd_t *bdesc): bdesc_(bdesc) {
+ static_assert(isa == sse42 || isa == avx2 || isa == avx512_common
+ || isa == avx512_mic, "unsupported isa");
+
+ const int simd_w = isa == sse42 ? 8 :
+ cpu_isa_traits<isa>::vlen / sizeof(data_t);
+ is_spatial_thr_ =
+ bnorm_utils::is_spatial_thr(bdesc_, simd_w, sizeof(data_t));
+
+ unroll_blocks = isa == avx512_common && !is_spatial_thr_ ? 4 : 1;
+ unroll_regs = isa == avx512_common && !is_spatial_thr_ ? 4 : 1;
+
+ preamble();
+
+ if (isa == avx512_common)
+ prepare_tail_mask_avx512_common();
+ else if (isa == avx2)
+ prepare_tail_mask_avx2_common();
+
+ compute_static_strides();
+ sub(rsp, stack_size_required);
+ load_common_params();
+ prepare_relu();
+
+ if (bdesc_->is_fwd()) {
+ if (!bdesc_->stats_is_src()) {
+ compute_mean_variance();
+ }
+ forward();
+ } else {
+ backward();
+ }
+ add(rsp, stack_size_required);
+ postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+ }
+};
+
+template <cpu_isa_t isa>
+struct uni_bnorm_driver_t: public c_compatible {
+ uni_bnorm_driver_t(const batch_normalization_pd_t *bdesc)
+ : bdesc_(bdesc), ker_(bdesc_)
+ {
+ const int nthrs = mkldnn_get_max_threads();
+ const dim_t C_PADDED = get_c_padded(bdesc_);
+
+ size_t data_size = sizeof(data_t) * bdesc_->MB() * C_PADDED
+ * bdesc_->D() * bdesc_->H() * bdesc_->W();
+ l3_size_ = get_cache_size(3, true) * nthrs / 2;
+ do_blocking_ = (data_size >= l3_size_ / 2 && l3_size_ > 0);
+ }
+
+ ~uni_bnorm_driver_t() {}
+
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const batch_normalization_pd_t *bdesc) {
+ int nthrs = mkldnn_get_max_threads();
+ dim_t C_PADDED = get_c_padded(bdesc);
+
+ int sbuf_sz = use_tmp_stats(bdesc) * 2 * C_PADDED;
+ int pbuf_sz = use_tmp_diff_scale_shift(bdesc) * 2 * C_PADDED;
+ int rbuf_sz = (bdesc->is_fwd() ? 1 : 2) * C_PADDED * nthrs;
+
+ scratchpad.book(key_bnorm_tmp_stats, sizeof(data_t) * sbuf_sz);
+ scratchpad.book(key_bnorm_tmp_diff_ss, sizeof(data_t) * pbuf_sz);
+ scratchpad.book(key_bnorm_reduction, sizeof(data_t) * rbuf_sz);
+
+ if (mkldnn_thr_syncable()) {
+ int n_barriers = C_PADDED / simd_w;
+ scratchpad.book(key_barrier, sizeof(barrier::ctx_t) * n_barriers);
+ }
+ }
+
+ void exec(int ithr, int nthr, const data_t *src, data_t *diff_src,
+ data_t *dst, const data_t *diff_dst, const data_t *scale_shift,
+ data_t *diff_scale_shift, const data_t *mean, const data_t *var,
+ const uint8_t *ws, const memory_tracking::grantor_t &scratchpad) {
+ auto sbuf = scratchpad.get<data_t>(key_bnorm_tmp_stats);
+ auto pbuf = scratchpad.get<data_t>(key_bnorm_tmp_diff_ss);
+ auto rbuf = scratchpad.get<data_t>(key_bnorm_reduction);
+ auto barriers = scratchpad.get<barrier::ctx_t>(key_barrier);
+
+ dim_t N = bdesc_->MB();
+ dim_t C = bdesc_->C();
+ dim_t C_PADDED = get_c_padded(bdesc_);
+ dim_t D = bdesc_->D();
+ dim_t H = bdesc_->H();
+ dim_t W = bdesc_->W();
+ dim_t SP = D * H * W;
+ dim_t img_size = C_PADDED * D * H * W;
+ const int vlen = isa == sse42 ? 32 : cpu_isa_traits<isa>::vlen;
+
+ typename jit_bnorm_t<isa>::call_params_t p;
+
+ p.eps = bdesc_->desc()->batch_norm_epsilon;
+ p.one = 1.0f;
+ p.spat_size = D * H * W;
+ p.chan_size = 1.0f * N * p.spat_size;
+
+ dim_t C_blks = C_PADDED / simd_w;
+
+ int C_ithr{0}, C_nthr{0}, N_ithr{0}, N_nthr{0}, S_ithr{0}, S_nthr{0};
+ dim_t C_blk_s{0}, C_blk_e{0}, N_s{0}, N_e{0}, S_s{0}, S_e{0};
+
+ dim_t C_blks_per_iter{ 1 };
+ int64_t iters{ 1 };
+ if (do_blocking_) {
+ int num_tensors = bdesc_->is_fwd() ? 1 : 2;
+ size_t working_set_size
+ = (N * D * H * W * simd_w * sizeof(data_t)) * num_tensors;
+ bnorm_utils::cache_balance(working_set_size, C_blks,
+ C_blks_per_iter, iters);
+ }
+
+ bool spatial_thr_allowed = bnorm_utils::thread_balance(do_blocking_,
+ true, ithr, nthr, N, do_blocking_ ? C_blks_per_iter : C_blks,
+ SP, C_ithr, C_nthr, C_blk_s, C_blk_e, N_ithr, N_nthr, N_s, N_e,
+ S_ithr, S_nthr, S_s, S_e);
+
+ int SP_N_ithr = N_ithr * S_nthr + S_ithr;
+ int SP_N_nthr = N_nthr * S_nthr;
+ assert(IMPLICATION(!mkldnn_thr_syncable(), SP_N_nthr == 1));
+
+ p.N_ithr = SP_N_ithr;
+ p.N_nthr = SP_N_nthr;
+
+ int last_iter_blks = C_blks - (iters - 1) * C_blks_per_iter;
+ int global_C_blk_s;
+ int global_barriers_per_iter = C_nthr;
+
+ for (int64_t it = 0; it < iters; it++) {
+ if (it == iters - 1 && iters > 1) {
+ C_blk_s = C_blk_e = N_s = N_e = 0;
+ spatial_thr_allowed = bnorm_utils::thread_balance(do_blocking_,
+ spatial_thr_allowed, ithr, nthr, N, last_iter_blks, SP,
+ C_ithr, C_nthr, C_blk_s, C_blk_e, N_ithr, N_nthr, N_s,
+ N_e, S_ithr, S_nthr, S_s, S_e);
+
+ // Update call parameters for JIT, last iteration
+ p.N_ithr = N_ithr * S_nthr + S_ithr;
+ p.N_nthr = N_nthr * S_nthr;
+ }
+
+ global_C_blk_s = do_blocking_ ?
+ (C_blk_s == -1) ? -1 : it * C_blks_per_iter + C_blk_s :
+ C_blk_s;
+
+ int C_blks_thr = C_blk_e - C_blk_s;
+ int N_thr = N_e - N_s;
+
+ size_t coff_base = global_C_blk_s * simd_w;
+ size_t soff_base
+ = global_C_blk_s * p.spat_size * simd_w + N_s * img_size;
+
+ p.spat_size_loc = S_e - S_s;
+ p.S_s = S_s * vlen;
+ p.S_tail = (p.spat_size - S_e) * vlen;
+ p.coff_max = C_blks_thr * simd_w;
+ p.mean = (use_tmp_stats(bdesc_) ? sbuf : mean) + coff_base;
+ p.var = (use_tmp_stats(bdesc_) ? sbuf + C_PADDED : var) + coff_base;
+ p.scale_shift = scale_shift + coff_base;
+ p.diff_scale_shift = (use_tmp_diff_scale_shift(bdesc_)
+ ? pbuf : diff_scale_shift) + coff_base;
+
+ p.soff_max = N_thr * img_size;
+ p.src = src + soff_base;
+ p.dst = dst + soff_base;
+ p.diff_src = diff_src + soff_base;
+ p.diff_dst = diff_dst + soff_base;
+ p.ws = ws + soff_base / 8;
+
+ p.mb_stride_Bc = img_size - p.coff_max * p.spat_size;
+
+ // use SP_N_nthr which is the same as p.N_nthr except maybe for
+ // the last iteration.
+ p.rbuf1 = rbuf + ((it * C_blks_per_iter) * SP_N_nthr
+ + C_blk_s * p.N_nthr + p.N_ithr * C_blks_thr) * simd_w;
+ // rbuf1 and rbuf2 have to be disjoint
+ p.rbuf2 = p.rbuf1 + C_PADDED * nthr;
+ p.is_cblk_tail = (it * C_blks_per_iter + C_blk_e) * simd_w > C;
+
+ size_t iter_bariers
+ = do_blocking_ ? it * global_barriers_per_iter : 0;
+ p.barrier = barriers + C_ithr + iter_bariers;
+ if (p.soff_max != 0 && p.coff_max != 0)
+ ker_(&p);
+ }
+ }
+
+ void init_barriers(const memory_tracking::grantor_t &scratchpad) {
+ auto barriers = scratchpad.get<barrier::ctx_t>(key_barrier);
+ if (barriers) {
+ const int n_barriers = get_c_padded(bdesc_) / simd_w;
+ for (int i = 0; i < n_barriers; ++i)
+ barrier::ctx_init(&barriers[i]);
+ }
+ }
+
+private:
+ enum {
+ simd_w = isa == sse42 ? 8 : cpu_isa_traits<isa>::vlen / sizeof(data_t)
+ };
+
+ static bool use_tmp_stats(const batch_normalization_pd_t *bdesc) {
+ return true
+ && !bdesc->stats_is_src()
+ && bdesc->desc()->prop_kind == prop_kind::forward_inference;
+ }
+
+ static bool use_tmp_diff_scale_shift(const batch_normalization_pd_t *bdesc)
+ {
+ return false
+ || (bdesc->is_bwd() && !bdesc->use_scaleshift())
+ || bdesc->desc()->prop_kind == prop_kind::backward_data;
+ }
+
+ static dim_t get_c_padded(const batch_normalization_pd_t *bdesc)
+ { return bdesc->src_md()->padded_dims[1]; }
+
+ const batch_normalization_pd_t *bdesc_;
+ bool do_blocking_;
+ size_t l3_size_;
+
+ jit_bnorm_t<isa> ker_;
+};
+
+}
+
+using namespace data_type;
+using namespace format_tag;
+using namespace utils;
+
+/* fwd */
+
+template <cpu_isa_t isa>
+status_t jit_uni_batch_normalization_fwd_t<isa>::pd_t::init() {
+ auto desired_fmt_tag = (ndims() == 4)
+ ? isa == avx512_common ? nChw16c : nChw8c
+ : isa == avx512_common ? nCdhw16c : nCdhw8c;
+
+ bool ok = true
+ && mayiuse(isa)
+ && is_fwd()
+ && !has_zero_dim_memory()
+ && one_of(ndims(), 4, 5)
+ && src_md()->data_type == f32
+ && IMPLICATION(use_scaleshift(), weights_md()->data_type == f32)
+ && memory_desc_matches_tag(*src_md(), desired_fmt_tag)
+ && (attr()->has_default_values() || this->with_relu_post_op());
+ if (!ok) return status::unimplemented;
+
+ if (is_training() && fuse_bn_relu()) {
+ if (isa < avx2) return status::unimplemented;
+ init_default_ws(1);
+ }
+
+ if (memory_desc_wrapper(src_md()).padded_dims()[1] != C()
+ && isa < avx2)
+ return status::unimplemented;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ uni_bnorm_driver_t<isa>::init_scratchpad(scratchpad, this);
+
+ return status::success;
+}
+
+template <cpu_isa_t isa>
+jit_uni_batch_normalization_fwd_t<isa>::jit_uni_batch_normalization_fwd_t(
+ const pd_t *apd): cpu_primitive_t(apd)
+{ bnorm_driver_ = new uni_bnorm_driver_t<isa>(pd()); }
+
+template <cpu_isa_t isa>
+status_t jit_uni_batch_normalization_fwd_t<isa>::execute(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto scale_shift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT);
+
+ auto mean = pd()->stats_is_src()
+ ? const_cast<data_t *>(CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN))
+ : CTX_OUT_MEM(data_t *, MKLDNN_ARG_MEAN);
+ auto var = pd()->stats_is_src()
+ ? const_cast<data_t *>(CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE))
+ : CTX_OUT_MEM(data_t *, MKLDNN_ARG_VARIANCE);
+
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+ auto ws = CTX_OUT_MEM(uint8_t *, MKLDNN_ARG_WORKSPACE);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ bnorm_driver_->init_barriers(scratchpad);
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ bnorm_driver_->exec(ithr, nthr, src, nullptr, dst, nullptr,
+ scale_shift, nullptr, mean, var, ws, scratchpad);
+ });
+
+ return status::success;
+}
+
+template <cpu_isa_t isa>
+jit_uni_batch_normalization_fwd_t<isa>::~jit_uni_batch_normalization_fwd_t()
+{ delete bnorm_driver_; }
+
+/* bwd */
+
+template <cpu_isa_t isa>
+status_t jit_uni_batch_normalization_bwd_t<isa>::pd_t::init() {
+ auto desired_fmt_tag = (ndims() == 4)
+ ? one_of(isa, sse42, avx2) ? nChw8c : nChw16c
+ : one_of(isa, sse42, avx2) ? nCdhw8c : nCdhw16c;
+
+ bool ok = true
+ && mayiuse(isa)
+ && is_bwd()
+ && !has_zero_dim_memory()
+ && one_of(ndims(), 4, 5)
+ && everyone_is(f32, src_md()->data_type, diff_src_md()->data_type)
+ && IMPLICATION(use_scaleshift(),
+ utils::everyone_is(f32,
+ weights_md()->data_type,
+ diff_weights_md()->data_type))
+ && memory_desc_matches_tag(*src_md(), desired_fmt_tag)
+ && memory_desc_matches_tag(*diff_src_md(), desired_fmt_tag)
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ if (memory_desc_wrapper(src_md()).padded_dims()[1] != C()
+ && isa < avx2)
+ return status::unimplemented;
+
+ if (fuse_bn_relu()) {
+ if (isa < avx2) return status::unimplemented;
+ init_default_ws(1);
+ if (!compare_ws(hint_fwd_pd_))
+ return status::unimplemented;
+ }
+
+ /* TODO: extra checks required */
+
+ auto scratchpad = scratchpad_registry().registrar();
+ uni_bnorm_driver_t<isa>::init_scratchpad(scratchpad, this);
+
+ return status::success;
+}
+
+template <cpu_isa_t isa>
+jit_uni_batch_normalization_bwd_t<isa>::jit_uni_batch_normalization_bwd_t(
+ const pd_t *apd): cpu_primitive_t(apd)
+{ bnorm_driver_ = new uni_bnorm_driver_t<isa>(pd()); }
+
+template <cpu_isa_t isa>
+status_t jit_uni_batch_normalization_bwd_t<isa>::execute(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto mean = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN);
+ auto var = CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto scale_shift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT);
+ auto ws = CTX_IN_MEM(const uint8_t *, MKLDNN_ARG_WORKSPACE);
+
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+ auto diff_scale_shift = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SCALE_SHIFT);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ bnorm_driver_->init_barriers(scratchpad);
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ bnorm_driver_->exec(ithr, nthr, src, diff_src, nullptr, diff_dst,
+ scale_shift, diff_scale_shift, mean, var, ws, scratchpad);
+ });
+
+ return status::success;
+}
+
+template <cpu_isa_t isa>
+jit_uni_batch_normalization_bwd_t<isa>::~jit_uni_batch_normalization_bwd_t()
+{ delete bnorm_driver_; }
+
+/* struct instantiation */
+template struct jit_uni_batch_normalization_fwd_t<sse42>;
+template struct jit_uni_batch_normalization_bwd_t<sse42>;
+template struct jit_uni_batch_normalization_fwd_t<avx2>;
+template struct jit_uni_batch_normalization_bwd_t<avx2>;
+template struct jit_uni_batch_normalization_fwd_t<avx512_common>;
+template struct jit_uni_batch_normalization_bwd_t<avx512_common>;
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.hpp
new file mode 100644
index 0000000000..96410ec84e
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_batch_normalization.hpp
@@ -0,0 +1,100 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_UNI_BATCH_NORMALIZATION_HPP
+#define JIT_UNI_BATCH_NORMALIZATION_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_batch_normalization_pd.hpp"
+#include "cpu_isa_traits.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace { template <cpu_isa_t isa> struct uni_bnorm_driver_t; }
+
+template <cpu_isa_t isa>
+struct jit_uni_batch_normalization_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_batch_normalization_fwd_pd_t {
+ pd_t(engine_t *engine, const batch_normalization_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const batch_normalization_fwd_pd_t *hint_fwd_pd)
+ : cpu_batch_normalization_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", isa, ""),
+ jit_uni_batch_normalization_fwd_t<isa>);
+
+ status_t init();
+ };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ jit_uni_batch_normalization_fwd_t(const pd_t *apd);
+ ~jit_uni_batch_normalization_fwd_t();
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override;
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ uni_bnorm_driver_t<isa> *bnorm_driver_;
+};
+
+template <cpu_isa_t isa>
+struct jit_uni_batch_normalization_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_batch_normalization_bwd_pd_t {
+ pd_t(engine_t *engine, const batch_normalization_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const batch_normalization_fwd_pd_t *hint_fwd_pd)
+ : cpu_batch_normalization_bwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", isa, ""),
+ jit_uni_batch_normalization_bwd_t<isa>);
+
+ status_t init();
+ };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ jit_uni_batch_normalization_bwd_t(const pd_t *apd);
+ ~jit_uni_batch_normalization_bwd_t();
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override;
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ uni_bnorm_driver_t<isa> *bnorm_driver_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.cpp
new file mode 100644
index 0000000000..b7dc5f85c5
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.cpp
@@ -0,0 +1,1302 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+#include "cpu_memory.hpp"
+
+#include "jit_uni_dw_conv_kernel_f32.hpp"
+
+#define GET_OFF(field) offsetof(jit_conv_call_s, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::prop_kind;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+using namespace Xbyak;
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_fwd_kernel_f32<isa>::load_src(int ur_ch_blocks, int ur_w) {
+ int repeats = isa == sse42 ? 2 : 1;
+ for (int i = 0; i < repeats; i++) {
+ for (int ch = 0; ch < ur_ch_blocks; ch++) {
+ for (int ow = 0; ow < ur_w; ow++) {
+ Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_w + ch*ur_w + ow);
+
+ int b_off = ch*jcp.ch_block + i*4;
+ if (this->jcp.with_bias)
+ uni_vmovups(vmm_acc,
+ vmmword[reg_bias + b_off*sizeof(float)]);
+ else
+ uni_vpxor(vmm_acc, vmm_acc, vmm_acc);
+
+ int o_off = ch*jcp.oh*jcp.ow*jcp.ch_block
+ + ow*jcp.ch_block + i*4;
+ if (this->jcp.with_sum)
+ uni_vaddps(vmm_acc, vmm_acc,
+ vmmword[reg_output + o_off*sizeof(float)]);
+ }
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_fwd_kernel_f32<isa>::apply_filter(
+ int ur_ch_blocks, int ur_w) {
+ int ch_blk = jcp.ch_block;
+ int dilate_h = jcp.dilate_h + 1;
+ int dilate_w = jcp.dilate_w + 1;
+ int stride_w = jcp.stride_w;
+
+ Label iter_exit_label;
+
+ cmp(reg_kh, 0);
+ je(iter_exit_label, T_NEAR);
+ cmp(reg_kw, 0);
+ je(iter_exit_label, T_NEAR);
+
+ mov(iter_kh, reg_kh);
+ Label kh_label;
+ L(kh_label); {
+ mov(iter_kw, reg_kw);
+ mov(aux1_reg_input, aux_reg_input);
+ mov(aux1_reg_kernel, aux_reg_kernel);
+
+ Label kw_label;
+ L(kw_label); {
+ int repeats = isa == sse42 ? 2 : 1;
+ for (int i = 0; i < repeats; i++) {
+ for (int ch = 0; ch < ur_ch_blocks; ch++) {
+ int ker_off = ch*jcp.kh*jcp.kw*ch_blk + i*4;
+ Vmm vmm_ker = get_ker_reg(0);
+ uni_vmovups(vmm_ker, ptr[aux1_reg_kernel
+ + ker_off*sizeof(float)]);
+
+ for (int ow = 0; ow < ur_w; ow++) {
+ int inp_off = ch*jcp.ih*jcp.iw*ch_blk
+ + ow*stride_w*ch_blk + i*4;
+ Vmm vmm_src = get_src_reg(0);
+ uni_vmovups(vmm_src, ptr[aux1_reg_input
+ + inp_off*sizeof(float)]);
+
+ Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_w
+ + ch*ur_w + ow);
+ uni_vfmadd231ps(vmm_acc, vmm_src, vmm_ker);
+ }
+ }
+ }
+ add(aux1_reg_kernel, ch_blk*sizeof(float));
+ add(aux1_reg_input, ch_blk*dilate_w*sizeof(float));
+
+ dec(iter_kw);
+ cmp(iter_kw, 0);
+ jg(kw_label, T_NEAR);
+ }
+ add(aux_reg_kernel, jcp.kw*ch_blk*sizeof(float));
+ add(aux_reg_input, jcp.iw*ch_blk*dilate_h*sizeof(float));
+
+ dec(iter_kh);
+ cmp(iter_kh, 0);
+ jg(kh_label, T_NEAR);
+ }
+
+ L(iter_exit_label);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_fwd_kernel_f32<isa>::apply_filter_unrolled(
+ int ur_ch_blocks, int ur_w) {
+ int ch_blk = jcp.ch_block;
+ int dilate_h = jcp.dilate_h + 1;
+ int dilate_w = jcp.dilate_w + 1;
+ int stride_w = jcp.stride_w;
+
+ Label iter_exit_label;
+
+ cmp(reg_kh, 0);
+ je(iter_exit_label, T_NEAR);
+
+ mov(iter_kh, reg_kh);
+ Label kh_label;
+ L(kh_label); {
+ int repeats = isa == sse42 ? 2 : 1;
+ for (int i = 0; i < repeats; i++) {
+ for (int ch = 0; ch < ur_ch_blocks; ch++) {
+ for (int kw = 0; kw < jcp.kw; kw++) {
+ int ker_off = ch*jcp.kh*jcp.kw*ch_blk + kw*ch_blk + i*4;
+
+ Vmm vmm_ker = get_ker_reg(0);
+ uni_vmovups(vmm_ker, ptr[aux_reg_kernel
+ + ker_off*sizeof(float)]);
+
+ for (int ow = 0; ow < ur_w; ow++) {
+ int inp_off = ch*jcp.ih*jcp.iw*ch_blk
+ + ow*stride_w*ch_blk + kw*ch_blk*dilate_w + i*4;
+
+ Vmm vmm_src = get_src_reg(0);
+ uni_vmovups(vmm_src, ptr[aux_reg_input
+ + inp_off*sizeof(float)]);
+
+ Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_w
+ + ch*ur_w + ow);
+ uni_vfmadd231ps(vmm_acc, vmm_src, vmm_ker);
+ }
+ }
+ }
+ }
+
+ add(aux_reg_kernel, jcp.kw*ch_blk*sizeof(float));
+ add(aux_reg_input, jcp.iw*ch_blk*dilate_h*sizeof(float));
+
+ dec(iter_kh);
+ cmp(iter_kh, 0);
+ jg(kh_label, T_NEAR);
+ }
+
+ L(iter_exit_label);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_fwd_kernel_f32<isa>::apply_activation(
+ int ur_ch_blocks, int ur_w) {
+ if (this->jcp.with_eltwise) {
+ int repeats = isa == sse42 ? 2 : 1;
+ eltwise_injector_->compute_vector_range(4, repeats * ur_w * ur_ch_blocks + 4);
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_fwd_kernel_f32<isa>::store_dst(
+ int ur_ch_blocks, int ur_w) {
+ int ch_blk = jcp.ch_block;
+
+ int repeats = isa == sse42 ? 2 : 1;
+ for (int i = 0; i < repeats; i++) {
+ for (int ch = 0; ch < ur_ch_blocks; ch++) {
+ for (int ow = 0; ow < ur_w; ow++) {
+ int o_off = ch*jcp.oh*jcp.ow*ch_blk + ow*ch_blk + i*4;
+ Vmm vmm_dst = get_acc_reg(i*ur_ch_blocks*ur_w + ch*ur_w + ow);
+
+ uni_vmovups(vmmword[reg_output + o_off*sizeof(float)], vmm_dst);
+ }
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_fwd_kernel_f32<isa>::loop_body(int ur_ch_blocks) {
+ Label unrolled_w_label;
+ Label tail_w_label;
+ Label exit_label;
+
+ L(unrolled_w_label); {
+ int ur_w = jcp.ur_w;
+
+ cmp(reg_ur_w, ur_w);
+ jl(tail_w_label, T_NEAR);
+
+ mov(aux_reg_input, reg_input);
+ mov(aux_reg_kernel, reg_kernel);
+
+ load_src(ur_ch_blocks, ur_w);
+ apply_filter_unrolled(ur_ch_blocks, ur_w);
+ apply_activation(ur_ch_blocks, ur_w);
+ store_dst(ur_ch_blocks, ur_w);
+
+ add(reg_input, sizeof(float) * ur_w * jcp.ch_block * jcp.stride_w);
+ add(reg_output, sizeof(float) * ur_w * jcp.ch_block);
+
+ sub(reg_ur_w, ur_w);
+ jmp(unrolled_w_label);
+ }
+
+ L(tail_w_label); {
+ int ur_w = 1;
+
+ cmp(reg_ur_w, ur_w);
+ jl(exit_label, T_NEAR);
+
+ mov(aux_reg_input, reg_input);
+ mov(aux_reg_kernel, reg_kernel);
+
+ load_src(ur_ch_blocks, ur_w);
+ apply_filter(ur_ch_blocks, ur_w);
+ apply_activation(ur_ch_blocks, ur_w);
+ store_dst(ur_ch_blocks, ur_w);
+
+ add(reg_input, sizeof(float) * ur_w * jcp.ch_block * jcp.stride_w);
+ add(reg_output, sizeof(float) * ur_w * jcp.ch_block);
+
+ sub(reg_ur_w, ur_w);
+ jmp(tail_w_label);
+ }
+
+ L(exit_label);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_fwd_kernel_f32<isa>::generate() {
+ this->preamble();
+
+ mov(reg_input, ptr[this->param1 + GET_OFF(src)]);
+ mov(reg_output, ptr[this->param1 + GET_OFF(dst)]);
+ mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]);
+ if (jcp.with_bias)
+ mov(reg_bias, ptr[this->param1 + GET_OFF(bias)]);
+ mov(reg_kh, ptr[this->param1 + GET_OFF(kh_padding)]);
+ mov(reg_kw, ptr[this->param1 + GET_OFF(kw_padding)]);
+ mov(reg_ch_blocks, ptr[this->param1 + GET_OFF(ch_blocks)]);
+ mov(reg_ur_w, ptr[this->param1 + GET_OFF(ur_w)]);
+
+ Label ch_blocks_tail_label;
+ Label exit_label;
+
+ int ch_blocks_tail = jcp.nb_ch % jcp.nb_ch_blocking;
+
+ cmp(reg_ch_blocks, jcp.nb_ch_blocking);
+ jne(ch_blocks_tail ? ch_blocks_tail_label : exit_label, T_NEAR);
+
+ loop_body(jcp.nb_ch_blocking); // channel main loop
+
+ if (ch_blocks_tail) {
+ L(ch_blocks_tail_label);
+
+ cmp(reg_ch_blocks, ch_blocks_tail);
+ jne(exit_label, T_NEAR);
+
+ loop_body(ch_blocks_tail); // channel tail loop
+ }
+
+ L(exit_label);
+
+ this->postamble();
+
+ if (jcp.with_eltwise)
+ eltwise_injector_->prepare_table();
+}
+
+template <cpu_isa_t isa>
+bool jit_uni_dw_conv_fwd_kernel_f32<isa>::post_ops_ok(
+ jit_conv_conf_t &jcp, const primitive_attr_t &attr) {
+ const auto &p = attr.post_ops_;
+
+ auto is_eltwise = [&](int idx) { return p.entry_[idx].is_eltwise(); };
+ auto is_sum = [&](int idx) { return p.entry_[idx].is_sum(); };
+
+ switch (p.len_) {
+ case 0: return true; // no post_ops
+ case 1: return is_eltwise(0) || is_sum(0); // sum OR eltwise
+ case 2: return is_sum(0) && is_eltwise(1); // sum -> eltwise
+ default: return false;
+ }
+
+ return false;
+}
+
+template <cpu_isa_t isa>
+status_t jit_uni_dw_conv_fwd_kernel_f32<isa>::init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d, const memory_desc_wrapper &dst_d,
+ const primitive_attr_t &attr)
+{
+ if (!mayiuse(isa)) return status::unimplemented;
+
+ const int simd_w = isa == avx512_common ? 16 : 8;
+
+ jcp.prop_kind = cd.prop_kind;
+
+ const bool with_groups = weights_d.ndims() == src_d.ndims() + 1;
+ if (!with_groups) return status::unimplemented;
+
+ jcp.ngroups = weights_d.dims()[0];
+ jcp.mb = src_d.dims()[0];
+
+ jcp.oc = dst_d.dims()[1];
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = src_d.dims()[1];
+
+ jcp.ih = src_d.dims()[2];
+ jcp.iw = src_d.dims()[3];
+ jcp.oh = dst_d.dims()[2];
+ jcp.ow = dst_d.dims()[3];
+
+ jcp.kh = weights_d.dims()[3];
+ jcp.kw = weights_d.dims()[4];
+
+ jcp.t_pad = cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][1];
+ jcp.b_pad = cd.padding[1][0];
+ jcp.r_pad = cd.padding[1][1];
+
+ jcp.stride_h = cd.strides[0];
+ jcp.stride_w = cd.strides[1];
+
+ jcp.dilate_h = cd.dilates[0];
+ jcp.dilate_w = cd.dilates[1];
+
+ jcp.with_bias = cd.bias_desc.format_kind != format_kind::undef;
+
+ if (!post_ops_ok(jcp, attr))
+ return status::unimplemented;
+
+ const auto &p = attr.post_ops_;
+ jcp.with_sum = p.find(primitive_kind::sum) != -1;
+ const int eltwise_ind = p.find(primitive_kind::eltwise);
+ jcp.with_eltwise = eltwise_ind != -1;
+ if (jcp.with_eltwise)
+ jcp.eltwise = p.entry_[eltwise_ind].eltwise;
+
+ bool ok_to_pad_channels = true
+ && jcp.oc == jcp.ngroups
+ && jcp.ic == jcp.ngroups
+ && one_of(isa, avx512_common, avx2);
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ jcp.ic = rnd_up(jcp.oc, simd_w);
+ jcp.ngroups = rnd_up(jcp.ngroups, simd_w);
+ }
+
+ auto dat_tag = isa == avx512_common ? nChw16c : nChw8c;
+ auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g;
+
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag);
+ jcp.dst_tag = dst_d.matches_one_of_tag(dat_tag);
+
+ bool args_ok = true
+ && jcp.oc == jcp.ngroups
+ && jcp.ic == jcp.ngroups
+ && jcp.ngroups % simd_w == 0
+ && jcp.src_tag == dat_tag
+ && jcp.wei_tag == wei_tag
+ && jcp.dst_tag == dat_tag
+ && jcp.ic <= src_d.padded_dims()[1]
+ && jcp.oc <= dst_d.padded_dims()[1]
+ && jcp.ngroups <= weights_d.padded_dims()[0];
+ if (!args_ok) return status::unimplemented;
+
+ jcp.ur_w = isa == avx512_common ? 6 : isa == avx2 ? 4 : 3;
+
+ jcp.ch_block = simd_w;
+ jcp.nb_ch = jcp.oc / jcp.ch_block;
+ jcp.nb_ch_blocking = isa == avx512_common ? 4 : isa == avx2 ? 3 : 2;
+ if (jcp.nb_ch < jcp.nb_ch_blocking)
+ jcp.nb_ch_blocking = jcp.nb_ch;
+
+ return status::success;
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_fwd_kernel_f32<isa>::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) {
+ if (jcp.with_bias && jcp.oc_without_padding != jcp.oc)
+ scratchpad.book(key_conv_padded_bias, sizeof(float) * jcp.oc);
+}
+
+template struct jit_uni_dw_conv_fwd_kernel_f32<avx512_common>;
+template struct jit_uni_dw_conv_fwd_kernel_f32<avx2>;
+template struct jit_uni_dw_conv_fwd_kernel_f32<sse42>;
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_data_kernel_f32<isa>::load_ddst(
+ int ur_ch_blocks, int ur_str_w) {
+ int repeats = isa == sse42 ? 2 : 1;
+ for (int i = 0; i < repeats; i++) {
+ for (int ch = 0; ch < ur_ch_blocks; ch++) {
+ for (int w = 0; w < ur_str_w; w++) {
+ Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_str_w
+ + ch*ur_str_w + w);
+ uni_vpxor(vmm_acc, vmm_acc, vmm_acc);
+ }
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_data_kernel_f32<isa>::apply_filter(
+ int ur_ch_blocks, int ur_str_w) {
+ int kw = jcp.kw;
+ int kh = jcp.kh;
+ int ow = jcp.ow;
+ int oh = jcp.oh;
+
+ int ch_blk = jcp.ch_block;
+ int stride_h = jcp.stride_h;
+ int stride_w = jcp.stride_w;
+
+ Label iter_exit_label;
+
+ cmp(reg_kh, 0);
+ je(iter_exit_label, T_NEAR);
+
+ cmp(reg_kw, 0);
+ je(iter_exit_label, T_NEAR);
+
+ mov(iter_kh, reg_kh);
+ Label kh_label;
+ L(kh_label); {
+ mov(aux1_reg_ddst, aux_reg_ddst);
+ mov(aux1_reg_kernel, aux_reg_kernel);
+
+ mov(iter_kw, reg_kw);
+ Label kw_label;
+ L(kw_label); {
+ int repeats = isa == sse42 ? 2 : 1;
+ for (int i = 0; i < repeats; i++) {
+ for (int ch = 0; ch < ur_ch_blocks; ch++) {
+ int ker_off = ch*kh*kw*ch_blk + i*4;
+ Vmm vmm_ker = get_ker_reg(0);
+ uni_vmovups(vmm_ker, ptr[aux1_reg_kernel
+ + ker_off*sizeof(float)]);
+
+ for (int w = 0; w < ur_str_w; w++) {
+ int ddst_off = (ch*oh*ow + w)*ch_blk + i*4;
+
+ Vmm vmm_src = get_src_reg(0);
+ uni_vmovups(vmm_src, ptr[aux1_reg_ddst
+ + ddst_off*sizeof(float)]);
+
+ Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_str_w
+ + ch*ur_str_w + w);
+ uni_vfmadd231ps(vmm_acc, vmm_src, vmm_ker);
+ }
+ }
+ }
+
+ add(aux1_reg_kernel, ch_blk*stride_w*sizeof(float));
+ sub(aux1_reg_ddst, ch_blk*sizeof(float));
+
+ sub(iter_kw, stride_w);
+ cmp(iter_kw, 0);
+ jg(kw_label, T_NEAR);
+ }
+
+ add(aux_reg_kernel, kw*ch_blk*stride_h*sizeof(float));
+ sub(aux_reg_ddst, ow*ch_blk*sizeof(float));
+
+ sub(iter_kh, stride_h);
+ cmp(iter_kh, 0);
+ jg(kh_label, T_NEAR);
+ }
+
+ L(iter_exit_label);
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_data_kernel_f32<isa>::store_dsrc(
+ int ur_ch_blocks, int ur_str_w) {
+ int ch_blk = jcp.ch_block;
+ int iw = jcp.iw;
+ int ih = jcp.ih;
+ int stride_w = jcp.stride_w;
+
+ int repeats = isa == sse42 ? 2 : 1;
+ for (int i = 0; i < repeats; i++) {
+ for (int ch = 0; ch < ur_ch_blocks; ch++) {
+ for (int w = 0; w < ur_str_w; w++) {
+ int dsrc_off = (ch*ih*iw + w*stride_w)*ch_blk + i*4;
+ Vmm vmm_acc = get_acc_reg(i*ur_ch_blocks*ur_str_w
+ + ch*ur_str_w + w);
+
+ uni_vmovups(ptr[reg_dsrc + dsrc_off*sizeof(float)], vmm_acc);
+ }
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_data_kernel_f32<isa>::loop_body(
+ int ur_ch_blocks) {
+ Label unrolled_w_label;
+ Label tail_w_label;
+ Label exit_label;
+
+ L(unrolled_w_label); {
+ int ur_w = jcp.ur_w;
+
+ cmp(reg_ur_str_w, ur_w);
+ jl(tail_w_label, T_NEAR);
+
+ mov(aux_reg_ddst, reg_ddst);
+ mov(aux_reg_kernel, reg_kernel);
+
+ load_ddst(ur_ch_blocks, ur_w);
+ apply_filter(ur_ch_blocks, ur_w);
+ store_dsrc(ur_ch_blocks, ur_w);
+
+ add(reg_dsrc, sizeof(float) * ur_w * jcp.ch_block * jcp.stride_w);
+ add(reg_ddst, sizeof(float) * ur_w * jcp.ch_block);
+
+ sub(reg_ur_str_w, ur_w);
+ jmp(unrolled_w_label);
+ }
+
+ L(tail_w_label); {
+ int ur_w = 1;
+
+ cmp(reg_ur_str_w, ur_w);
+ jl(exit_label, T_NEAR);
+
+ mov(aux_reg_ddst, reg_ddst);
+ mov(aux_reg_kernel, reg_kernel);
+
+ load_ddst(ur_ch_blocks, ur_w);
+ apply_filter(ur_ch_blocks, ur_w);
+ store_dsrc(ur_ch_blocks, ur_w);
+
+ add(reg_dsrc, sizeof(float) * ur_w * jcp.ch_block * jcp.stride_w);
+ add(reg_ddst, sizeof(float) * ur_w * jcp.ch_block);
+
+ sub(reg_ur_str_w, ur_w);
+ jmp(tail_w_label);
+ }
+
+ L(exit_label);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_bwd_data_kernel_f32<isa>::generate() {
+ preamble();
+
+ mov(reg_dsrc, ptr[this->param1 + GET_OFF(src)]);
+ mov(reg_ddst, ptr[this->param1 + GET_OFF(dst)]);
+ mov(reg_kernel, ptr[this->param1 + GET_OFF(filt)]);
+ mov(reg_kh, ptr[this->param1 + GET_OFF(kh_padding)]);
+ mov(reg_kw, ptr[this->param1 + GET_OFF(kw_padding)]);
+ mov(reg_ch_blocks, ptr[this->param1 + GET_OFF(ch_blocks)]);
+ mov(reg_ur_str_w, ptr[this->param1 + GET_OFF(ur_str_w)]);
+
+ Label ch_blocks_tail_label;
+ Label exit_label;
+
+ int ch_blocks_tail = jcp.nb_ch % jcp.nb_ch_blocking;
+
+ cmp(reg_ch_blocks, jcp.nb_ch_blocking);
+ jne(ch_blocks_tail ? ch_blocks_tail_label : exit_label, T_NEAR);
+
+ loop_body(jcp.nb_ch_blocking); // channel main loop
+
+ if (ch_blocks_tail) {
+ L(ch_blocks_tail_label);
+
+ cmp(reg_ch_blocks, ch_blocks_tail);
+ jne(exit_label, T_NEAR);
+
+ loop_body(ch_blocks_tail); // channel tail loop
+ }
+
+ L(exit_label);
+
+ this->postamble();
+}
+
+template <cpu_isa_t isa>
+status_t jit_uni_dw_conv_bwd_data_kernel_f32<isa>::init_conf(
+ jit_conv_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_wrapper &diff_src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &diff_dst_d) {
+ if (!mayiuse(isa)) return status::unimplemented;
+
+ const int simd_w = isa == avx512_common ? 16 : 8;
+
+ const bool with_groups = weights_d.ndims() == diff_src_d.ndims() + 1;
+ if (!with_groups) return status::unimplemented;
+
+ jcp.ngroups = weights_d.dims()[0];
+ jcp.mb = diff_src_d.dims()[0];
+
+ jcp.oc = diff_dst_d.dims()[1];
+ jcp.oc_without_padding = jcp.oc;
+ jcp.ic = diff_src_d.dims()[1];
+
+ jcp.ih = diff_src_d.dims()[2];
+ jcp.iw = diff_src_d.dims()[3];
+ jcp.oh = diff_dst_d.dims()[2];
+ jcp.ow = diff_dst_d.dims()[3];
+
+ jcp.kh = weights_d.dims()[3];
+ jcp.kw = weights_d.dims()[4];
+
+ jcp.t_pad = cd.padding[0][0];
+ jcp.l_pad = cd.padding[0][1];
+ jcp.b_pad = cd.padding[1][0];
+ jcp.r_pad = cd.padding[1][1];
+
+ jcp.stride_h = cd.strides[0];
+ jcp.stride_w = cd.strides[1];
+
+ jcp.dilate_h = cd.dilates[0];
+ jcp.dilate_w = cd.dilates[1];
+
+ jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad;
+ jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad;
+
+ bool ok_to_pad_channels = true
+ && jcp.oc == jcp.ngroups
+ && jcp.ic == jcp.ngroups
+ && one_of(isa, avx512_common, avx2);
+ if (ok_to_pad_channels) {
+ jcp.oc = rnd_up(jcp.oc, simd_w);
+ jcp.ic = rnd_up(jcp.oc, simd_w);
+ jcp.ngroups = rnd_up(jcp.ngroups, simd_w);
+ }
+
+ auto dat_tag = isa == avx512_common ? nChw16c : nChw8c;
+ auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g;
+
+ jcp.src_tag = diff_src_d.matches_one_of_tag(dat_tag);
+ jcp.wei_tag = weights_d.matches_one_of_tag(wei_tag);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(dat_tag);
+
+ bool args_ok = true
+ && jcp.oc == jcp.ngroups
+ && jcp.ic == jcp.ngroups
+ && jcp.ngroups % simd_w == 0
+ && jcp.dilate_h == 0
+ && jcp.dilate_w == 0
+ && jcp.src_tag == dat_tag
+ && jcp.wei_tag == wei_tag
+ && jcp.dst_tag == dat_tag
+ && jcp.oh == (jcp.ihp - jcp.kh) / jcp.stride_h + 1
+ && jcp.ow == (jcp.iwp - jcp.kw) / jcp.stride_w + 1
+ && jcp.ic <= diff_src_d.padded_dims()[1]
+ && jcp.oc <= diff_dst_d.padded_dims()[1]
+ && jcp.ngroups <= weights_d.padded_dims()[0];
+ if (!args_ok) return status::unimplemented;
+
+ jcp.ur_w = isa == avx512_common ? 6 : isa == avx2 ? 4 : 3;
+
+ jcp.ch_block = simd_w;
+ jcp.nb_ch = jcp.ic / jcp.ch_block;
+ jcp.nb_ch_blocking = isa == avx512_common ? 4 : isa == avx2 ? 3 : 2;
+ if (jcp.nb_ch < jcp.nb_ch_blocking)
+ jcp.nb_ch_blocking = jcp.nb_ch;
+
+ return status::success;
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_bwd_data_kernel_f32<isa>::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) {
+ UNUSED(scratchpad);
+ UNUSED(jcp);
+}
+
+template struct jit_uni_dw_conv_bwd_data_kernel_f32<avx512_common>;
+template struct jit_uni_dw_conv_bwd_data_kernel_f32<avx2>;
+template struct jit_uni_dw_conv_bwd_data_kernel_f32<sse42>;
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::zero_filter() {
+ for (int r = 0; r < reg_repeats; ++r) {
+ for (int i = 0; i < jcp.kw; ++i) {
+ Vmm vmm_acc = get_acc_reg(r * jcp.kw + i);
+ uni_vpxor(vmm_acc, vmm_acc, vmm_acc);
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::load_filter() {
+ for (int r = 0; r < reg_repeats; ++r) {
+ const int reg_set = r * jcp.kw;
+ for (int i = 0; i < jcp.kw; ++i) {
+ int off_filter = (reg_set + i) * simd_w;
+ Vmm vmm_acc = get_acc_reg(reg_set + i);
+ uni_vmovups(vmm_acc,
+ vmmword[reg_tmp_filter + off_filter * sizeof(float)]);
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::zero_bias() {
+ for (int r = 0; r < reg_repeats; ++r) {
+ Vmm vmm_bias = get_bias_reg(r);
+ uni_vpxor(vmm_bias, vmm_bias, vmm_bias);
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::load_bias() {
+ for (int r = 0; r < reg_repeats; ++r) {
+ Vmm vmm_bias = get_bias_reg(r);
+ uni_vmovups(
+ vmm_bias, vmmword[reg_bias_baddr + r * simd_w * sizeof(float)]);
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::compute_ow_step_unroll(
+ int unroll_w, int l_pad, int pad_offset, int ow_block) {
+
+ const int iw_block = ow_block * jcp.stride_w;
+ const int right_border = jcp.iw - iw_block;
+
+ const int cascade_input = nstl::min(jcp.stride_w, jcp.kw);
+
+ /* preamble count for number of cascaded LOAD + FMA operation */
+ const int input_overlap = nstl::max(jcp.kw - l_pad, 0);
+
+ /* LOAD initial input registers, then cascade LOADs and FMAs*/
+ for (int r = 0; r < reg_repeats; ++r) {
+ for (int i_ur = 0; i_ur < unroll_w; ++i_ur) {
+ int off_output = (i_ur * reg_repeats + r) * simd_w;
+ Vmm vmm_output = get_output_reg(r);
+ uni_vmovups(vmm_output,
+ ptr[reg_tmp_output + off_output * sizeof(float)]);
+ if (i_ur == 0) {
+ for (int c = 0; c < input_overlap; ++c) {
+ int off_input
+ = ((c - pad_offset) * reg_repeats + r) * simd_w;
+ Vmm vmm_input
+ = get_input_reg((c % jcp.kw) * reg_repeats + r);
+ uni_vmovups(vmm_input,
+ ptr[reg_tmp_input + off_input * sizeof(float)]);
+ }
+ } else {
+ for (int c = 0; c < cascade_input; ++c) {
+ int overlap = (i_ur - 1) * jcp.stride_w + input_overlap;
+ int off_input
+ = ((overlap + c - pad_offset) * reg_repeats + r)
+ * simd_w;
+ Vmm vmm_input = get_input_reg(
+ ((overlap + c) % jcp.kw) * reg_repeats + r);
+ uni_vmovups(vmm_input,
+ ptr[reg_tmp_input + off_input * sizeof(float)]);
+ }
+ }
+
+ for (int i_kw = 0; i_kw < jcp.kw; ++i_kw) {
+ int io_overlap = i_kw + (i_ur * jcp.stride_w);
+
+ /* Don't apply FMAs that fall into the padded region */
+ if (io_overlap - l_pad < 0
+ || io_overlap - jcp.l_pad >= right_border)
+ continue;
+
+ Vmm vmm_input = get_input_reg(
+ ((io_overlap - l_pad) % jcp.kw) * reg_repeats + r);
+ Vmm vmm_acc = get_acc_reg(i_kw * reg_repeats + r);
+ Vmm vmm_aux = isa == sse42 ? get_aux_reg() : vmm_input;
+ if (isa == sse42)
+ uni_vmovups(vmm_aux, vmm_input);
+ uni_vfmadd231ps(vmm_acc, vmm_aux, vmm_output);
+ }
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+inline void
+jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::compute_bias_step_unroll(
+ const int unroll_w) {
+ for (int r = 0; r < reg_repeats; ++r) {
+ for (int i = 0; i < unroll_w; ++i) {
+ Vmm vmm_bias = get_bias_reg(r);
+ int off_output = (i * reg_repeats + r) * simd_w;
+ if (isa == sse42) {
+ /* Need to support unaligned address loads for SSE42*/
+ Vmm vmm_output = get_output_reg(1 + r);
+ uni_vmovups(vmm_output,
+ ptr[reg_tmp_output + off_output * sizeof(float)]);
+ uni_vaddps(vmm_bias, vmm_bias, vmm_output);
+ } else {
+ uni_vaddps(vmm_bias, vmm_bias,
+ vmmword[reg_tmp_output + off_output * sizeof(float)]);
+ }
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::store_filter() {
+ for (int r = 0; r < reg_repeats; ++r) {
+ const int reg_set = r * jcp.kw;
+ for (int i = 0; i < jcp.kw; ++i) {
+ int off_filter = (i + reg_set) * simd_w;
+ Vmm vmm_acc = get_acc_reg(i + reg_set);
+ uni_vmovups(vmmword[reg_tmp_filter + off_filter * sizeof(float)],
+ vmm_acc);
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::store_bias() {
+ for (int r = 0; r < reg_repeats; ++r) {
+ Vmm vmm_bias = get_bias_reg(r);
+ uni_vmovups(
+ vmmword[reg_bias_baddr + r * simd_w * sizeof(float)], vmm_bias);
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::compute_bias_loop(
+ const int block_size) {
+ Label oh_label;
+ Label ow_blk_label;
+
+ const int unroll_w = nstl::min(block_size, jcp.ow);
+ const int unroll_w_trips = jcp.ow / unroll_w;
+ const int tail_w = jcp.ow > block_size ? jcp.ow % block_size : 0;
+
+ const int ch_offset = jcp.ch_block;
+
+ mov(reg_oh, ptr[this->param1 + offsetof(jit_dw_conv_call_s, oh_index)]);
+ mov(reg_oh_worksize,
+ ptr[this->param1 + offsetof(jit_dw_conv_call_s, oh_count)]);
+
+ mov(reg_tmp_output, reg_output_baddr);
+ L(oh_label);
+ {
+
+ mov(iter_ow_blk, unroll_w_trips);
+ L(ow_blk_label);
+ {
+
+ compute_bias_step_unroll(unroll_w);
+ add(reg_tmp_output, unroll_w * ch_offset * sizeof(float));
+
+ dec(iter_ow_blk);
+ cmp(iter_ow_blk, 0);
+ jg(ow_blk_label, T_NEAR);
+ }
+
+ if (tail_w > 0) {
+ compute_bias_step_unroll(tail_w);
+ add(reg_tmp_output, tail_w * ch_offset * sizeof(float));
+ }
+
+ inc(reg_oh);
+ cmp(reg_oh, reg_oh_worksize);
+ jl(oh_label, T_NEAR);
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::compute_zero_filter() {
+
+ const int ch_offset = jcp.ch_block;
+
+ Label kh_loop_label, skip_zeroing_label;
+
+ mov(reg_exec_flags,
+ ptr[this->param1 + offsetof(jit_dw_conv_call_s, exec_flags)]);
+ and_(reg_exec_flags, FLAG_ZERO_FILTER);
+ test(reg_exec_flags, reg_exec_flags);
+ je(skip_zeroing_label);
+
+ zero_filter();
+
+ mov(reg_tmp_filter, reg_filter_baddr);
+ mov(reg_kh, jcp.kh);
+ L(kh_loop_label);
+ {
+ store_filter();
+
+ add(reg_tmp_filter, jcp.kw * ch_offset * sizeof(float));
+ dec(reg_kh);
+ cmp(reg_kh, 0);
+ jg(kh_loop_label);
+ }
+
+ /* Comeback pointers */
+ sub(reg_tmp_filter, jcp.kh * jcp.kw * ch_offset * sizeof(float));
+
+ L(skip_zeroing_label);
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::compute_h_step(
+ int unroll_w, int l_pad, int pad_offset, int ow_block) {
+
+ const int ch_offset = jcp.ch_block;
+
+ Label kh_loop_label, skip_loop_label;
+
+ cmp(reg_kh_count, 0);
+ je(skip_loop_label, T_NEAR);
+
+ mov(reg_kh, reg_kh_count);
+ L(kh_loop_label);
+ {
+ load_filter();
+ compute_ow_step_unroll(unroll_w, l_pad, pad_offset, ow_block);
+ store_filter();
+
+ add(reg_tmp_filter, jcp.kw * ch_offset * sizeof(float));
+ add(reg_tmp_input, jcp.iw * ch_offset * sizeof(float));
+ dec(reg_kh);
+ cmp(reg_kh, 0);
+ jg(kh_loop_label);
+ }
+
+ /* Comeback pointers */
+ Label kh_comeback_label;
+ mov(reg_kh, reg_kh_count);
+ L(kh_comeback_label);
+ {
+ sub(reg_tmp_input, jcp.iw * ch_offset * sizeof(float));
+ sub(reg_tmp_filter, jcp.kw * ch_offset * sizeof(float));
+ dec(reg_kh);
+ cmp(reg_kh, 0);
+ jg(kh_comeback_label, T_NEAR);
+ }
+
+ L(skip_loop_label);
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::compute_h_loop(
+ int unroll_w, int l_pad, int pad_offset, int ow_block) {
+
+ const size_t io_overlap = jcp.ih / jcp.stride_h < jcp.oh ?
+ jcp.ih / jcp.stride_h - 1 :
+ jcp.oh - jcp.b_pad - 1;
+ const int ch_offset = jcp.ch_block;
+ const int t_overlap_off = jcp.t_pad % jcp.stride_h == 0 ? jcp.stride_h : 1;
+ const int b_overlap_off = jcp.b_pad % jcp.stride_h == 0 ? jcp.stride_h : 1;
+
+ Label tpad_loop_label, h_loop_label, skip_tpad_label, skip_bpad_label,
+ end_h_loop_label;
+
+ mov(reg_oh, ptr[this->param1 + offsetof(jit_dw_conv_call_s, oh_index)]);
+ mov(reg_oh_worksize,
+ ptr[this->param1 + offsetof(jit_dw_conv_call_s, oh_count)]);
+ mov(reg_kh_count,
+ ptr[this->param1 + offsetof(jit_dw_conv_call_s, kh_count)]);
+
+ mov(reg_tmp_output, reg_output_baddr);
+ mov(reg_tmp_input, reg_input_baddr);
+ mov(reg_tmp_filter, reg_filter_baddr);
+
+ L(h_loop_label);
+ {
+
+ compute_h_step(unroll_w, l_pad, pad_offset, ow_block);
+
+ add(reg_tmp_output, jcp.ow * ch_offset * sizeof(float));
+
+ /* If within the top_pad region */
+ if (jcp.t_pad > 0) {
+ /* Skip t_pad area if no longer in initial h_block */
+ cmp(reg_oh, jcp.t_pad);
+ jg(skip_tpad_label, T_NEAR);
+
+ cmp(reg_kh_count, jcp.kh);
+ jge(skip_tpad_label, T_NEAR);
+
+ add(reg_kh_count, t_overlap_off);
+ sub(reg_tmp_filter,
+ t_overlap_off * jcp.kw * ch_offset * sizeof(float));
+
+ /* kernel has moved beyond padding (adjust for stride effects) */
+ if (jcp.t_pad % jcp.stride_h != 0) {
+ int inp_corr = jcp.stride_h - jcp.t_pad % jcp.stride_h;
+ add(reg_tmp_input,
+ inp_corr * jcp.iw * ch_offset * sizeof(float));
+ }
+ jmp(tpad_loop_label, T_NEAR);
+ }
+
+ L(skip_tpad_label);
+
+ cmp(reg_oh, io_overlap);
+ jl(skip_bpad_label, T_NEAR);
+ sub(reg_kh_count, b_overlap_off);
+
+ L(skip_bpad_label);
+ add(reg_tmp_input, jcp.stride_h * jcp.iw * ch_offset * sizeof(float));
+
+ L(tpad_loop_label);
+
+ cmp(reg_oh, jcp.ih / jcp.stride_h);
+ jge(end_h_loop_label, T_NEAR);
+
+ inc(reg_oh);
+
+ cmp(reg_oh, reg_oh_worksize);
+ jl(h_loop_label, T_NEAR);
+ }
+ L(end_h_loop_label);
+}
+
+template <cpu_isa_t isa>
+inline void
+jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::compute_ow_block_unroll() {
+
+ const int ch_offset = jcp.ch_block;
+ int ow = jcp.ow;
+ int pad_offset = 0;
+ int l_pad = jcp.l_pad;
+
+ /* Calculate effective padding */
+ int r_pad = nstl::max(0, (ow - 1) * jcp.stride_w
+ + (jcp.kw - 1) * (jcp.dilate_w + 1)
+ - (jcp.iw + jcp.l_pad - 1));
+
+ /* Is this strictly defined by:
+ * -code-size (?)
+ * -address size (?) */
+ const int max_unroll_w = 30;
+ const int block_size = 15;
+
+ int unroll_w_tail = 0;
+ int unroll_w = 0;
+ int unroll_w_trips = 0;
+
+ if (jcp.ow > max_unroll_w) {
+ unroll_w = nstl::min(block_size, jcp.ow);
+ unroll_w_trips = ow / unroll_w;
+ /* calculate tail */
+ unroll_w_tail = ow % unroll_w;
+ /* Perform some rebalancing if tail too small*/
+ if ((unroll_w_tail == 0 && r_pad != 0)
+ || (r_pad > 0 && r_pad >= unroll_w_tail)) {
+ if (unroll_w_trips > 1) {
+ unroll_w_tail += unroll_w;
+ unroll_w_trips--;
+ } else {
+ /* Idealy, this case shouldn't happen */
+ unroll_w_tail += (unroll_w - unroll_w / 2);
+ unroll_w = unroll_w / 2;
+ }
+ }
+ } else {
+ unroll_w = jcp.ow;
+ unroll_w_trips = nstl::max(1, ow / unroll_w);
+ }
+ if (jcp.with_bias) {
+ Label skip_load_bias;
+ mov(reg_bias_baddr,
+ ptr[this->param1 + offsetof(jit_dw_conv_call_s, bias)]);
+
+ zero_bias();
+
+ mov(reg_exec_flags,
+ ptr[this->param1 + offsetof(jit_dw_conv_call_s, exec_flags)]);
+ and_(reg_exec_flags, FLAG_ZERO_BIAS);
+ test(reg_exec_flags, reg_exec_flags);
+ jne(skip_load_bias);
+
+ load_bias();
+
+ L(skip_load_bias);
+ compute_bias_loop(block_size);
+
+ store_bias();
+ }
+
+ /* Pass filter address, then offset for h_padding. */
+ compute_zero_filter();
+ mov(reg_kh_offset,
+ ptr[this->param1 + offsetof(jit_dw_conv_call_s, filter_pad_off)]);
+ add(reg_filter_baddr, reg_kh_offset);
+
+ /* compute left padded block */
+ if (l_pad) {
+ compute_h_loop(unroll_w, l_pad, 0, 0);
+ add(reg_output_baddr, unroll_w * ch_offset * sizeof(float));
+ add(reg_input_baddr,
+ unroll_w * jcp.stride_w * ch_offset * sizeof(float));
+ unroll_w_trips--;
+ pad_offset = l_pad;
+ l_pad = 0;
+ }
+
+ /* compute middle block */
+ Label ow_blk_label;
+
+ /* Insert loop for 'ow' block when middle block needs to execute more
+ * than once */
+ bool do_ow_blk_loop = unroll_w_trips > 1;
+ if (do_ow_blk_loop) {
+ mov(iter_ow_blk, unroll_w_trips);
+ L(ow_blk_label);
+ }
+ if (unroll_w_trips > 0) {
+ compute_h_loop(unroll_w, l_pad, pad_offset, 0);
+ add(reg_output_baddr, unroll_w * ch_offset * sizeof(float));
+ add(reg_input_baddr,
+ unroll_w * jcp.stride_w * ch_offset * sizeof(float));
+ }
+ if (do_ow_blk_loop) {
+ dec(iter_ow_blk);
+ cmp(iter_ow_blk, 0);
+ jg(ow_blk_label, T_NEAR);
+ }
+
+ /* compute right padded block */
+ if (unroll_w_tail) {
+ compute_h_loop(unroll_w_tail, 0, pad_offset, jcp.ow - unroll_w_tail);
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::generate() {
+ preamble();
+
+ mov(reg_input_baddr,
+ ptr[this->param1 + offsetof(jit_dw_conv_call_s, input)]);
+ mov(reg_output_baddr,
+ ptr[this->param1 + offsetof(jit_dw_conv_call_s, output)]);
+ mov(reg_filter_baddr,
+ ptr[this->param1 + offsetof(jit_dw_conv_call_s, filter)]);
+
+ compute_ow_block_unroll();
+
+ this->postamble();
+}
+
+template <cpu_isa_t isa>
+status_t jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::init_conf(
+ jit_conv_conf_t &jcp, const convolution_desc_t &cd,
+ const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &diff_weights_d,
+ const memory_desc_wrapper &diff_dst_d, int nthreads) {
+ if (!mayiuse(isa))
+ return status::unimplemented;
+
+ jcp.ngroups = diff_weights_d.dims()[0];
+ jcp.oc = diff_dst_d.dims()[1] / jcp.ngroups;
+ jcp.ic = src_d.dims()[1] / jcp.ngroups;
+
+ const bool with_groups = diff_weights_d.ndims() == src_d.ndims() + 1;
+
+ jcp.is_depthwise = true && with_groups && everyone_is(1, jcp.oc, jcp.ic);
+
+ if (!jcp.is_depthwise)
+ return status::unimplemented;
+
+ jcp.ch_block = isa == avx512_common ? 16 : 8;
+
+ jcp.mb = src_d.dims()[0];
+
+ jcp.ih = src_d.dims()[2];
+ jcp.iw = src_d.dims()[3];
+ jcp.oh = diff_dst_d.dims()[2];
+ jcp.ow = diff_dst_d.dims()[3];
+
+ jcp.kh = diff_weights_d.dims()[3];
+ jcp.kw = diff_weights_d.dims()[4];
+
+ jcp.stride_h = cd.strides[0];
+ jcp.stride_w = cd.strides[1];
+
+ jcp.t_pad = cd.padding[0][0];
+ jcp.b_pad = cd.padding[1][0];
+
+ jcp.l_pad = cd.padding[0][1];
+ jcp.r_pad = cd.padding[1][1];
+
+ jcp.dilate_h = cd.dilates[0];
+ jcp.dilate_w = cd.dilates[1];
+
+ jcp.ihp = jcp.ih + jcp.t_pad + jcp.b_pad;
+ jcp.iwp = jcp.iw + jcp.l_pad + jcp.r_pad;
+
+ jcp.with_bias = cd.diff_bias_desc.format_kind != format_kind::undef;
+
+ auto dat_tag = isa == avx512_common ? nChw16c : nChw8c;
+ auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g;
+
+ jcp.src_tag = src_d.matches_one_of_tag(dat_tag);
+ jcp.wei_tag = diff_weights_d.matches_one_of_tag(wei_tag);
+ jcp.dst_tag = diff_dst_d.matches_one_of_tag(dat_tag);
+
+ bool args_ok = true
+ && jcp.src_tag == dat_tag
+ && jcp.wei_tag == wei_tag
+ && jcp.dst_tag == dat_tag
+ && jcp.ngroups % jcp.ch_block == 0 && jcp.dilate_h == 0
+ && jcp.dilate_w == 0 && jcp.kw <= 3
+ && jcp.oh == (jcp.ihp - jcp.kh) / jcp.stride_h + 1
+ && jcp.ow == (jcp.iwp - jcp.kw) / jcp.stride_w + 1;
+ if (!args_ok)
+ return status::unimplemented;
+
+ jcp.nb_ch = jcp.ngroups / jcp.ch_block;
+
+ /* kernel applicability check wrt boundaries
+ * the conditions are quite general across the kernels we have,
+ * but ideally the check should belong to a specific kernel... */
+ const int max_hpad = (jcp.kh - 1 + 1) / 2;
+ const int max_wpad = (jcp.kw - 1 + 1) / 2;
+ const bool boundaries_ok = true && jcp.t_pad <= max_hpad
+ && jcp.b_pad <= max_hpad && jcp.l_pad <= max_wpad
+ && jcp.r_pad <= max_wpad;
+ if (!boundaries_ok)
+ return status::unimplemented;
+
+ balance(jcp, nthreads);
+
+ return status::success;
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::init_scratchpad(
+ memory_tracking::registrar_t &scratchpad, const jit_conv_conf_t &jcp) {
+ /* Notes: if splitting thread work on 'mb', then a reduction has to take
+ * place. Hence, book a per-thread, local weights-buffer for the
+ * reduction */
+ if (jcp.nthr_mb > 1) {
+ const size_t wei_size = jcp.ngroups * jcp.kh * jcp.kw;
+ scratchpad.book(key_conv_wei_reduction,
+ sizeof(float) * wei_size * (jcp.nthr_mb - 1));
+
+ if (jcp.with_bias)
+ scratchpad.book(key_conv_bia_reduction,
+ sizeof(float) * jcp.ngroups * (jcp.nthr_mb - 1));
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::balance(jit_conv_conf_t &jcp,
+ int nthreads) {
+ jcp.nthr = nthreads;
+ jcp.nthr_g = jcp.nthr_mb = 1;
+
+ /* Basic-Heuristics for parallel strategy:
+ * 1) Tries to parallel on the number of Groups (g) where tasks are
+ * independent. Otherwise,
+ * 2) Tries to split the work across g and MiniBatch (mb).
+ * Parallelizing on mb requires computing a reduction for weights.
+ *
+ * NOTE: because of 'task partitioning' scheme, there will be unbalanced
+ * per-thread load when the number of threads is high (e.g. > 16).
+ */
+ jcp.nthr_g = nstl::min(jcp.nb_ch, jcp.nthr);
+ jcp.nthr_mb = nstl::min(nstl::max(1, jcp.nthr / jcp.nthr_g), jcp.mb);
+
+ jcp.nthr = jcp.nthr_g * jcp.nthr_mb;
+}
+
+template struct jit_uni_dw_conv_bwd_weights_kernel_f32<avx512_common>;
+template struct jit_uni_dw_conv_bwd_weights_kernel_f32<avx2>;
+template struct jit_uni_dw_conv_bwd_weights_kernel_f32<sse42>;
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.hpp
new file mode 100644
index 0000000000..9c08fc4a09
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_conv_kernel_f32.hpp
@@ -0,0 +1,253 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_UNI_DW_CONV_KERNEL_F32_HPP
+#define JIT_UNI_DW_CONV_KERNEL_F32_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+#include "jit_uni_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <cpu_isa_t isa>
+struct jit_uni_dw_conv_fwd_kernel_f32: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_dw_conv_fwd_kernel_f32)
+
+ jit_uni_dw_conv_fwd_kernel_f32(jit_conv_conf_t ajcp)
+ : jcp(ajcp), eltwise_injector_(nullptr)
+ {
+ if (jcp.with_eltwise)
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<isa>(this,
+ jcp.eltwise);
+
+ this->generate();
+ jit_ker = (void (*)(jit_conv_call_s *))this->getCode();
+ }
+
+ ~jit_uni_dw_conv_fwd_kernel_f32() {
+ delete eltwise_injector_;
+ }
+
+ static bool post_ops_ok(jit_conv_conf_t &jcp,
+ const primitive_attr_t &attr);
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &dst_d, const primitive_attr_t &attr);
+
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp);
+
+ jit_conv_conf_t jcp;
+ void (*jit_ker)(jit_conv_call_s *);
+
+private:
+ using Vmm = typename utils::conditional3<isa == sse42, Xbyak::Xmm,
+ isa == avx2, Xbyak::Ymm, Xbyak::Zmm>::type;
+ using reg64_t = const Xbyak::Reg64;
+ const Xbyak::AddressFrame &vmmword = (isa == sse42)
+ ? xword : (isa == avx2) ? yword : zword;
+ const int vlen = cpu_isa_traits<isa>::vlen;
+
+ // dw convolution
+ reg64_t reg_input = r8;
+ reg64_t aux_reg_input = r9;
+ reg64_t aux1_reg_input = r10;
+ reg64_t reg_kernel = r11;
+ reg64_t aux_reg_kernel = r12;
+ reg64_t aux1_reg_kernel = r13;
+ reg64_t reg_output = r14;
+ reg64_t reg_bias = r15;
+ reg64_t reg_kh = rax;
+ reg64_t reg_kw = rbx;
+ reg64_t iter_kh = rdx;
+ reg64_t iter_kw = rsi;
+ reg64_t reg_ur_w = rbp;
+ reg64_t reg_ch_blocks = aux1_reg_input;
+ reg64_t imm_addr64 = aux1_reg_input;
+
+ inline Vmm get_ker_reg(int idx) { return Vmm(idx + 0); }
+ inline Vmm get_src_reg(int idx) { return Vmm(idx + 1); }
+ inline Vmm get_acc_reg(int idx) { return Vmm(idx + 4); }
+
+ inline void load_src(int ur_ch_blocks, int ur_w);
+ inline void apply_filter(int ur_ch_blocks, int ur_w);
+ inline void apply_filter_unrolled(int ur_ch_blocks, int ur_w);
+ inline void apply_activation(int ur_ch_blocks, int ur_w);
+ inline void store_dst(int ur_ch_blocks, int ur_w);
+ inline void loop_body(int ur_ch_blocks);
+
+ jit_uni_eltwise_injector_f32<isa> *eltwise_injector_;
+
+ void generate();
+};
+
+template <cpu_isa_t isa>
+struct jit_uni_dw_conv_bwd_data_kernel_f32: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_dw_conv_bwd_data_kernel_f32)
+
+ jit_uni_dw_conv_bwd_data_kernel_f32(jit_conv_conf_t ajcp): jcp(ajcp) {
+ this->generate();
+ jit_ker = (void (*)(jit_conv_call_s *))this->getCode();
+ }
+
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd,
+ const memory_desc_wrapper &diff_src_d,
+ const memory_desc_wrapper &weights_d,
+ const memory_desc_wrapper &diff_dst_d);
+
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp);
+
+ jit_conv_conf_t jcp;
+ void (*jit_ker)(jit_conv_call_s *);
+
+private:
+ using Vmm = typename utils::conditional3<isa == sse42, Xbyak::Xmm,
+ isa == avx2, Xbyak::Ymm, Xbyak::Zmm>::type;
+ using reg64_t = const Xbyak::Reg64;
+
+ inline Vmm get_ker_reg(int idx) { return Vmm(idx + 0); }
+ inline Vmm get_src_reg(int idx) { return Vmm(idx + 1); }
+ inline Vmm get_acc_reg(int idx) { return Vmm(idx + 4); }
+
+ reg64_t reg_ddst = rax;
+ reg64_t aux_reg_ddst = r8;
+ reg64_t aux1_reg_ddst = abi_not_param1;
+ reg64_t reg_kernel = rdx;
+ reg64_t aux_reg_kernel = r10;
+ reg64_t aux1_reg_kernel = rbp;
+ reg64_t reg_dsrc = rsi;
+
+ reg64_t reg_ur_str_w = r9;
+ reg64_t reg_ch_blocks = rbx;
+
+ reg64_t iter_kh = r11;
+ reg64_t iter_kw = r12;
+ reg64_t reg_kh = r13;
+ reg64_t reg_kw = r14;
+
+ inline void loop_body(int ur_ch_blocks);
+ inline void load_ddst(int ur_ch_blocks, int ur_str_w);
+ inline void apply_filter(int ur_ch_blocks, int ur_str_w);
+ inline void store_dsrc(int ur_ch_blocks, int ur_str_w);
+
+ void generate();
+};
+
+template <cpu_isa_t isa>
+struct jit_uni_dw_conv_bwd_weights_kernel_f32 : public jit_generator {
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_dw_conv_bwd_weights_kernel_f32)
+
+ jit_uni_dw_conv_bwd_weights_kernel_f32(jit_conv_conf_t ajcp) : jcp(ajcp) {
+ this->generate();
+ jit_ker = (void (*)(jit_dw_conv_call_s *)) this->getCode();
+ }
+
+ static status_t init_conf(jit_conv_conf_t &jcp,
+ const convolution_desc_t &cd, const memory_desc_wrapper &src_d,
+ const memory_desc_wrapper &diff_weights_d,
+ const memory_desc_wrapper &diff_dst_d, int nthreads);
+
+ static void init_scratchpad(memory_tracking::registrar_t &scratchpad,
+ const jit_conv_conf_t &jcp);
+
+ static void balance(jit_conv_conf_t &jcp, int nthreads);
+
+ jit_conv_conf_t jcp;
+ void (*jit_ker)(jit_dw_conv_call_s *);
+
+private:
+ using Vmm = typename utils::conditional3<isa == sse42, Xbyak::Xmm,
+ isa == avx2, Xbyak::Ymm, Xbyak::Zmm>::type;
+ using reg64_t = const Xbyak::Reg64;
+ const int simd_w = cpu_isa_traits<isa>::vlen / sizeof(float);
+ const int reg_repeats = (isa == sse42) ? 2 : 1;
+
+ const Xbyak::AddressFrame &vmmword
+ = (isa == sse42) ? xword : (isa == avx2) ? yword : zword;
+
+ /* XXX: offset between input and accummulators is 3, therefore, assume 'kw'
+ * is no larger than 3*/
+ inline Vmm get_bias_reg(int idx = 0) { return Vmm(idx); }
+ inline Vmm get_output_reg(int idx) { return Vmm(idx + 1); }
+ inline Vmm get_input_reg(int idx) { return Vmm(idx + 4 * reg_repeats + 1); }
+ inline Vmm get_acc_reg(int idx) { return Vmm(idx + 1 * reg_repeats + 1); }
+ inline Vmm get_aux_reg() { return Vmm(0); }
+
+ reg64_t reg_tmp_input = r9;
+ reg64_t reg_tmp_output = r10;
+ reg64_t reg_tmp_filter = r13;
+ reg64_t reg_kh_offset = rax;
+
+ /* parameter passed by driver into kernel */
+ Xbyak::Reg8 reg_exec_flags = bl;
+
+ reg64_t reg_oh_worksize = r14;
+ reg64_t reg_oh = rax;
+
+ reg64_t iter_ow_blk = r11;
+
+ reg64_t reg_kh = rsi;
+ reg64_t reg_kh_count = rdx;
+
+ /* Base addresses for convolution parameters. */
+ reg64_t reg_input_baddr = r15;
+ reg64_t reg_output_baddr = r12;
+ reg64_t reg_filter_baddr = abi_not_param1;
+ reg64_t reg_bias_baddr = r13;
+
+ /* Micro-kernel JIT'ing, fusing 'kw' and 'ow_block' loops into unrolled FMAs
+ */
+ inline void compute_ow_step_unroll(
+ int unroll_w, int l_pad, int pad_offset, int ow_block);
+
+ /* JIT'ing the outer loops for the micro-kernel -> {kh, oh_block} */
+ inline void compute_h_step(
+ int unroll_w, int l_pad, int pad_offset, int ow_block);
+ inline void compute_h_loop(
+ int unroll_w, int l_pad, int pad_offset, int ow_block);
+
+ /* Write 'width' micro-kernel JITs; depending on the padding and convolution
+ * size, write a micro-kernel for the left ow-block, middle ow-block(s), and
+ * right ow-block.*/
+ inline void compute_ow_block_unroll();
+
+ inline void compute_zero_filter();
+ inline void load_filter();
+ inline void zero_filter();
+ inline void load_bias();
+ inline void zero_bias();
+ inline void compute_bias_step_unroll(const int unroll_w);
+ inline void compute_bias_loop(const int block_size);
+ inline void store_filter();
+ inline void store_bias();
+
+ void generate();
+};
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.cpp
new file mode 100644
index 0000000000..58449601a3
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.cpp
@@ -0,0 +1,427 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "jit_uni_dw_convolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace mkldnn::impl::utils;
+
+template <cpu_isa_t isa>
+void _jit_uni_dw_convolution_fwd_t<isa>::execute_forward(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ const auto &jcp = kernel_->jcp;
+
+ if (pd()->wants_padded_bias()) {
+ auto padded_bias = this->scratchpad(ctx).template get<data_t>(
+ key_conv_padded_bias);
+ utils::array_copy(padded_bias, bias, jcp.oc_without_padding);
+ utils::array_set(padded_bias + jcp.oc_without_padding, 0.f,
+ jcp.oc - jcp.oc_without_padding);
+ bias = padded_bias;
+ }
+
+ int dil_h = jcp.dilate_h + 1;
+ int dil_w = jcp.dilate_w + 1;
+ int str_h = jcp.stride_h;
+ int str_w = jcp.stride_w;
+
+ auto kernel_params = [&](int ur_w_step, int ow, int oh, int ih, int kh,
+ int kh_padding, int ch, int ch_num, int n) {
+ auto par_conv = jit_conv_call_s();
+
+ const int i_l_overflow = nstl::max(0, (jcp.l_pad - ow * str_w));
+ const int i_r_overflow = nstl::max(jcp.iw, (ow * str_w
+ + (jcp.kw - 1)*dil_w - jcp.l_pad + 1)) - jcp.iw;
+
+ const int iw = nstl::max((ow*str_w - jcp.l_pad
+ + div_up(i_l_overflow, dil_w)*dil_w), 0);
+ const int kw = div_up(i_l_overflow, dil_w);
+
+ const int kw_padding = jcp.kw - div_up(i_l_overflow, dil_w)
+ - div_up(i_r_overflow, dil_w);
+
+ par_conv.src = &src[src_d.blk_off(n, ch, ih, iw)];
+ par_conv.dst = &dst[dst_d.blk_off(n, ch, oh, ow)];
+
+ par_conv.filt = &weights[weights_d.blk_off(ch, 0, 0, kh, kw)];
+ if (bias) par_conv.bias = &bias[bias_d.blk_off(ch*jcp.ch_block)];
+
+ par_conv.kh_padding = (size_t)nstl::max(0, kh_padding);
+ par_conv.kw_padding = (size_t)nstl::max(0, kw_padding);
+
+ par_conv.ur_w = (size_t)ur_w_step;
+
+ par_conv.ch_blocks = nstl::min(ch + ch_num, jcp.nb_ch) - ch;
+
+ return par_conv;
+ };
+
+ const int chb_work = utils::div_up(jcp.nb_ch, jcp.nb_ch_blocking);
+ parallel_nd(jcp.mb, chb_work, jcp.oh,
+ [&](int n, int chb, int oh) {
+ int ch = chb * jcp.nb_ch_blocking;
+ int ch_num = jcp.nb_ch_blocking;
+
+ const int i_t_overflow = nstl::max(0, (int)(jcp.t_pad - oh*str_h));
+ const int i_b_overflow = nstl::max(jcp.ih,
+ (int)(oh*str_h + (jcp.kh - 1)*dil_h - jcp.t_pad + 1)) - jcp.ih;
+
+ const int ih = nstl::max((int)(oh*str_h - jcp.t_pad
+ + div_up(i_t_overflow, dil_h)*dil_h), 0);
+ const int kh = div_up(i_t_overflow, dil_h);
+ const int kh_padding = jcp.kh - div_up(i_t_overflow, dil_h)
+ - div_up(i_b_overflow, dil_h);
+
+ // left border
+ int ow = 0;
+ int l_border = nstl::min(div_up(jcp.l_pad, str_w), jcp.ow);
+ int ur_w_step = 1;
+ for (; ow < l_border; ow++) {
+ jit_conv_call_s par_conv = kernel_params(ur_w_step, ow, oh, ih,
+ kh, kh_padding, ch, ch_num, n);
+
+ kernel_->jit_ker(&par_conv);
+ }
+
+ // main loop
+ ur_w_step = (jcp.iw - (jcp.kw - 1)*dil_w + jcp.l_pad - 1)
+ / jcp.stride_w - ow + 1;
+ if (ur_w_step > 0) {
+ jit_conv_call_s par_conv = kernel_params(ur_w_step, ow, oh, ih,
+ kh, kh_padding, ch, ch_num, n);
+
+ kernel_->jit_ker(&par_conv);
+
+ ow += ur_w_step;
+ }
+
+ // right border
+ ur_w_step = 1;
+ for (; ow < jcp.ow; ow++) {
+ jit_conv_call_s par_conv = kernel_params(ur_w_step, ow, oh, ih,
+ kh, kh_padding, ch, ch_num, n);
+
+ kernel_->jit_ker(&par_conv);
+ }
+ });
+
+ if (pd()->wants_zero_pad_dst())
+ ctx.memory(MKLDNN_ARG_DST)->zero_pad();
+}
+
+template struct _jit_uni_dw_convolution_fwd_t<avx512_common>;
+template struct _jit_uni_dw_convolution_fwd_t<avx2>;
+template struct _jit_uni_dw_convolution_fwd_t<sse42>;
+
+template <cpu_isa_t isa>
+void _jit_uni_dw_convolution_bwd_data_t<isa>::execute_backward_data(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+
+ const auto &jcp = kernel_->jcp;
+
+ auto kernel_params = [&](int ur_str_w, int iw, int oh, int ih,
+ int i_t_overflow, int i_b_overflow, int stride_off_h,
+ int ch, int ch_num, int n) {
+ auto par_conv = jit_conv_call_s();
+
+ const int i_l_overflow = nstl::max(0, (jcp.kw - 1 - iw - jcp.l_pad));
+ const int i_r_overflow = nstl::max(0, (jcp.kw - 1 - (jcp.iw - 1 - iw)
+ - jcp.r_pad));
+
+ int ow = iw + jcp.l_pad - i_r_overflow;
+ int stride_off_w = ow % jcp.stride_w;
+ ow /= jcp.stride_w;
+
+ par_conv.src = &diff_src[diff_src_d.blk_off(n, ch, ih, iw)];
+ par_conv.dst = &diff_dst[diff_dst_d.blk_off(n, ch, oh, ow)];
+ par_conv.filt = &weights[weights_d.blk_off(ch, 0, 0, i_b_overflow
+ + stride_off_h, i_r_overflow + stride_off_w)];
+
+ par_conv.kh_padding = nstl::max(0, jcp.kh - i_t_overflow - i_b_overflow
+ - stride_off_h);
+ par_conv.kw_padding = nstl::max(0, jcp.kw - i_l_overflow - i_r_overflow
+ - stride_off_w);
+
+ par_conv.ur_str_w = ur_str_w;
+
+ par_conv.ch_blocks = nstl::min(ch + ch_num, jcp.nb_ch) - ch;
+
+ return par_conv;
+ };
+
+ const int chb_work = utils::div_up(jcp.nb_ch, jcp.nb_ch_blocking);
+ parallel_nd(jcp.mb, chb_work, jcp.ih,
+ [&](int n, int chb, int ih) {
+ int ch = chb * jcp.nb_ch_blocking;
+ int ch_num = jcp.nb_ch_blocking;
+
+ const int i_t_overflow = nstl::max(0, (int)(jcp.kh - 1 - ih
+ - jcp.t_pad));
+ const int i_b_overflow = nstl::max(0, (int)(jcp.kh - 1
+ - (jcp.ih - 1 - ih) - jcp.b_pad));
+
+ int oh = ih + jcp.t_pad - i_b_overflow;
+ int stride_off_h = oh % jcp.stride_h;
+ oh /= jcp.stride_h;
+
+ for (int i_str_w = 0; i_str_w < jcp.stride_w; i_str_w++) {
+ // left border
+ int iw = i_str_w;
+ int l_border = nstl::min(jcp.kw - 1 - jcp.l_pad, jcp.iw);
+ int ur_str_w = 1;
+ for (; iw < l_border; iw += jcp.stride_w) {
+ jit_conv_call_s par_conv = kernel_params(ur_str_w, iw, oh,
+ ih, i_t_overflow, i_b_overflow,
+ stride_off_h, ch, ch_num, n);
+
+ kernel_->jit_ker(&par_conv);
+ }
+
+ // main loop
+ ur_str_w = nstl::min((jcp.iw - jcp.kw + jcp.r_pad - iw)
+ / jcp.stride_w, jcp.iw);
+ if (ur_str_w > 0) {
+ jit_conv_call_s par_conv = kernel_params(ur_str_w, iw, oh,
+ ih, i_t_overflow, i_b_overflow,
+ stride_off_h, ch, ch_num, n);
+
+ kernel_->jit_ker(&par_conv);
+
+ iw += ur_str_w * jcp.stride_w;
+ }
+
+ // right border
+ ur_str_w = 1;
+ for (; iw < jcp.iw; iw += jcp.stride_w) {
+ jit_conv_call_s par_conv = kernel_params(ur_str_w, iw, oh,
+ ih, i_t_overflow, i_b_overflow,
+ stride_off_h, ch, ch_num, n);
+
+ kernel_->jit_ker(&par_conv);
+ }
+ }
+ });
+}
+
+template struct _jit_uni_dw_convolution_bwd_data_t<avx512_common>;
+template struct _jit_uni_dw_convolution_bwd_data_t<avx2>;
+template struct _jit_uni_dw_convolution_bwd_data_t<sse42>;
+
+template <cpu_isa_t isa>
+_jit_uni_dw_convolution_bwd_weights_t<isa>::
+_jit_uni_dw_convolution_bwd_weights_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , kernel_(nullptr), acc_ker_(nullptr)
+{
+ kernel_ = new jit_uni_dw_conv_bwd_weights_kernel_f32<isa>(pd()->jcp_);
+ if (pd()->jcp_.nthr_mb > 1 && do_parallel_reduction())
+ acc_ker_ = new cpu_accumulator_1d_t<data_type::f32>();
+}
+
+template <cpu_isa_t isa>
+void _jit_uni_dw_convolution_bwd_weights_t<isa>::execute_backward_weights(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS);
+ auto diff_bias = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS);
+
+ auto diff_wei_reduction_buf =
+ scratchpad(ctx).template get<data_t>(key_conv_wei_reduction);
+ auto diff_bia_reduction_buf =
+ scratchpad(ctx).template get<data_t>(key_conv_bia_reduction);
+
+ const auto &jcp = kernel_->jcp;
+
+ /* Used when executing a parallel reduction */
+ simple_barrier::ctx_t reduction_bctx;
+ simple_barrier::ctx_init(&reduction_bctx);
+
+ const size_t wei_size = jcp.ngroups * jcp.kh * jcp.kw;
+ const size_t bias_size = jcp.with_bias ? jcp.ngroups : 0;
+
+ const int ch_block = jcp.ch_block;
+
+ auto set_kernel_params = [&](jit_dw_conv_call_s *conv_params,
+ const int batch, const int group, const int oh_start,
+ const int work_size, const unsigned char exec_flag,
+ const size_t kh_padding, const size_t filter_off) {
+ const int tpad_underflow_off = jcp.t_pad - filter_off;
+
+ conv_params->exec_flags = exec_flag;
+ conv_params->kh_count = jcp.kh - kh_padding;
+
+ const int oh_s = oh_start;
+ const int oh_e = oh_start + work_size;
+ const int ih_s = oh_s * jcp.stride_h;
+
+ conv_params->filter_pad_off
+ = filter_off * jcp.kw * ch_block * sizeof(float);
+ conv_params->oh_index = oh_s;
+ conv_params->oh_count = oh_e;
+
+ size_t diff_dst_off
+ = ((batch * (jcp.ngroups / ch_block) + group) * jcp.oh
+ + oh_start)
+ * jcp.ow;
+
+ size_t src_off = ((batch * (jcp.ngroups / ch_block) + group) * jcp.ih
+ + ih_s - tpad_underflow_off) * jcp.iw;
+
+ conv_params->output = &diff_dst[diff_dst_off * ch_block];
+ conv_params->input = &src[src_off * ch_block];
+ };
+
+ parallel(jcp.nthr, [&](const int ithr, const int nthr) {
+ assert(nthr == jcp.nthr);
+
+ auto conv_params = jit_dw_conv_call_s();
+ const int h_block_size = 15;
+
+ /* assign iteration space to thread */
+ const int ithr_g = ithr % jcp.nthr_g;
+ const int ithr_mb = (ithr / jcp.nthr_g) % jcp.nthr_mb;
+
+ /* split dimensions */
+ int g_start{ 0 }, g_end{ 0 };
+ balance211(jcp.nb_ch, jcp.nthr_g, ithr_g, g_start, g_end);
+
+ int mb_start{ 0 }, mb_end{ 0 };
+ balance211(jcp.mb, jcp.nthr_mb, ithr_mb, mb_start, mb_end);
+
+ auto diff_wei = ithr_mb == 0
+ ? diff_weights : diff_wei_reduction_buf + (ithr_mb - 1) * wei_size;
+ auto diff_bia = ithr_mb == 0
+ ? diff_bias : diff_bia_reduction_buf + (ithr_mb - 1) * bias_size;
+
+ for (int g = g_start; g < g_end; ++g) {
+ unsigned char zero_filter_flag = FLAG_ZERO_FILTER;
+ unsigned char zero_bias_flag = jcp.with_bias ? FLAG_ZERO_BIAS : 0;
+
+ size_t diff_wei_off = g * jcp.kh * jcp.kw;
+ conv_params.filter = &diff_wei[diff_wei_off * ch_block];
+
+ if (jcp.with_bias)
+ conv_params.bias = &diff_bia[g * ch_block];
+
+ for (int mb = mb_start; mb < mb_end; ++mb) {
+ int oh = 0;
+ while (oh < jcp.oh) {
+ const int h_work = nstl::min(h_block_size, jcp.oh - oh);
+ auto kh_t_padding = nstl::max(0, jcp.t_pad - oh);
+ auto kh_b_padding
+ = (oh * jcp.stride_h + jcp.kh - 1 > jcp.ih) ?
+ jcp.b_pad - (h_work - 1) :
+ 0;
+
+ set_kernel_params(&conv_params, mb, g, oh, h_work,
+ zero_filter_flag | zero_bias_flag,
+ kh_t_padding + kh_b_padding, kh_t_padding);
+ kernel_->jit_ker(&conv_params);
+
+ zero_bias_flag &= ~FLAG_ZERO_BIAS;
+ zero_filter_flag &= ~FLAG_ZERO_FILTER;
+ oh += h_work;
+ }
+ }
+ }
+
+ if (do_parallel_reduction() && jcp.nthr_mb > 1) {
+ size_t reduct_start{ 0 }, reduct_end{ 0 };
+ balance211(wei_size, nthr, ithr, reduct_start, reduct_end);
+
+ const int acc_size = reduct_end - reduct_start;
+ const size_t reduct_off = reduct_start;
+ auto *acc_data = diff_weights + reduct_off;
+
+ simple_barrier::barrier(&reduction_bctx, nthr);
+
+ for (int thr_mb = 1; thr_mb < jcp.nthr_mb; ++thr_mb) {
+ auto *src_data = diff_wei_reduction_buf
+ + (thr_mb - 1) * wei_size + reduct_off;
+ acc_ker_->accumulate(acc_data, src_data, acc_size);
+ }
+ }
+ });
+
+ if (jcp.nthr_mb <= 1) return;
+
+ /* Apply single-threaded 'mb' reduction */
+ for (int thr_mb = 1; thr_mb < jcp.nthr_mb; ++thr_mb) {
+ size_t mb_accum_offset = (thr_mb - 1) * wei_size;
+ size_t b_accum_offset = (thr_mb - 1) * bias_size;
+
+ for (int g = 0; g < jcp.nb_ch; ++g) {
+ /* Reduction on Bias */
+ if (jcp.with_bias) {
+ PRAGMA_OMP_SIMD()
+ for (int g_block = 0; g_block < ch_block; ++g_block) {
+ size_t bias_offset = g * ch_block + g_block;
+ diff_bias[bias_offset] += diff_bia_reduction_buf[
+ b_accum_offset + bias_offset];
+ }
+ }
+
+ if (do_parallel_reduction()) continue;
+
+ for (int kh = 0; kh < jcp.kh; ++kh)
+ for (int kw = 0; kw < jcp.kw; ++kw)
+ {
+ size_t wei_offset = (g * jcp.kh + kh) * jcp.kw + kw;
+ PRAGMA_OMP_SIMD()
+ for (int g_block = 0; g_block < ch_block; ++g_block) {
+ const size_t off = wei_offset * ch_block + g_block;
+ diff_weights[off] +=
+ diff_wei_reduction_buf[mb_accum_offset + off];
+ }
+ }
+ }
+ }
+}
+
+template struct _jit_uni_dw_convolution_bwd_weights_t<avx512_common>;
+template struct _jit_uni_dw_convolution_bwd_weights_t<avx2>;
+template struct _jit_uni_dw_convolution_bwd_weights_t<sse42>;
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.hpp
new file mode 100644
index 0000000000..ca53749ec2
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_dw_convolution.hpp
@@ -0,0 +1,266 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_UNI_DW_CONVOLUTION_HPP
+#define CPU_JIT_UNI_DW_CONVOLUTION_HPP
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+
+#include "cpu_barrier.hpp"
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+#include "cpu_reducer.hpp"
+
+#include "jit_uni_dw_conv_kernel_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <cpu_isa_t isa>
+struct _jit_uni_dw_convolution_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_fwd_pd_t {
+ pd_t(engine_t *engine, const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const typename pd_t::base_class *hint_fwd_pd)
+ : cpu_convolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_dw:", isa, ""),
+ _jit_uni_dw_convolution_fwd_t<isa>);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_uni_dw_conv_fwd_kernel_f32<isa>::init_conf(
+ jcp_, *desc(), src_md(), *weights_md(), *dst_md(), *attr());
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_uni_dw_conv_fwd_kernel_f32<isa>::init_scratchpad(scratchpad,
+ jcp_);
+
+ return status::success;
+ }
+
+ jit_conv_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = isa == avx512_common ? nChw16c : nChw8c;
+ auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g;
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ _jit_uni_dw_convolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd)
+ { kernel_ = new jit_uni_dw_conv_fwd_kernel_f32<isa>(pd()->jcp_); }
+
+ ~_jit_uni_dw_convolution_fwd_t() { delete kernel_; }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_uni_dw_conv_fwd_kernel_f32<isa> *kernel_;
+};
+
+using jit_avx512_common_dw_convolution_fwd_t =
+ _jit_uni_dw_convolution_fwd_t<avx512_common>;
+using jit_avx2_dw_convolution_fwd_t = _jit_uni_dw_convolution_fwd_t<avx2>;
+using jit_sse42_dw_convolution_fwd_t = _jit_uni_dw_convolution_fwd_t<sse42>;
+
+template <cpu_isa_t isa>
+struct _jit_uni_dw_convolution_bwd_data_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_data_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_()
+ {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_dw:", isa, ""),
+ _jit_uni_dw_convolution_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_data
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::undef, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+
+ if (!ok) return status::unimplemented;
+
+ status_t status = jit_uni_dw_conv_bwd_data_kernel_f32<isa>::
+ init_conf(jcp_, *desc(), *diff_src_md(), *weights_md(),
+ *diff_dst_md());
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_uni_dw_conv_bwd_data_kernel_f32<isa>::init_scratchpad(
+ scratchpad, jcp_);
+
+ return status::success;
+ }
+
+ jit_conv_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = isa == avx512_common ? nChw16c : nChw8c;
+ auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g;
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ _jit_uni_dw_convolution_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd)
+ { kernel_ = new jit_uni_dw_conv_bwd_data_kernel_f32<isa>(pd()->jcp_); }
+ ~_jit_uni_dw_convolution_bwd_data_t() { delete kernel_; };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_data(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_data(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_uni_dw_conv_bwd_data_kernel_f32<isa> *kernel_;
+};
+
+using jit_avx512_common_dw_convolution_bwd_data_t =
+ _jit_uni_dw_convolution_bwd_data_t<avx512_common>;
+using jit_avx2_dw_convolution_bwd_data_t =
+ _jit_uni_dw_convolution_bwd_data_t<avx2>;
+using jit_sse42_dw_convolution_bwd_data_t =
+ _jit_uni_dw_convolution_bwd_data_t<sse42>;
+
+template <cpu_isa_t isa>
+struct _jit_uni_dw_convolution_bwd_weights_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_weights_pd_t {
+ pd_t(engine_t *engine,
+ const convolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const convolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_convolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , jcp_() {}
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit_dw:", isa, ""),
+ _jit_uni_dw_convolution_bwd_weights_t<isa>);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_weights
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(data_type::f32, data_type::f32,
+ data_type::f32, data_type::f32, data_type::f32)
+ && !has_zero_dim_memory()
+ && set_default_formats();
+ if (!ok) return status::unimplemented;
+
+ const int max_threads = mkldnn_in_parallel()
+ ? 1 : mkldnn_get_max_threads();
+
+ status_t status = jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::
+ init_conf(jcp_, *desc(), *src_md(), *diff_weights_md(),
+ *diff_dst_md(), max_threads);
+ if (status != status::success) return status;
+
+ auto scratchpad = scratchpad_registry().registrar();
+ jit_uni_dw_conv_bwd_weights_kernel_f32<isa>::init_scratchpad(
+ scratchpad, jcp_);
+
+ return status::success;
+ }
+
+ jit_conv_conf_t jcp_;
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+
+ auto dat_tag = isa == avx512_common ? nChw16c : nChw8c;
+ auto wei_tag = isa == avx512_common ? Goihw16g : Goihw8g;
+
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ _jit_uni_dw_convolution_bwd_weights_t(const pd_t *apd);
+ ~_jit_uni_dw_convolution_bwd_weights_t() {
+ delete kernel_;
+ delete acc_ker_;
+ };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_weights(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_weights(const exec_ctx_t &ctx) const;
+ bool do_parallel_reduction() const { return false; }
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_uni_dw_conv_bwd_weights_kernel_f32<isa> *kernel_;
+ cpu_accumulator_1d_t<data_type::f32> *acc_ker_;
+};
+
+using jit_avx512_common_dw_convolution_bwd_weights_t =
+ _jit_uni_dw_convolution_bwd_weights_t<avx512_common>;
+using jit_avx2_dw_convolution_bwd_weights_t =
+ _jit_uni_dw_convolution_bwd_weights_t<avx2>;
+using jit_sse42_dw_convolution_bwd_weights_t =
+ _jit_uni_dw_convolution_bwd_weights_t<sse42>;
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.cpp
new file mode 100644
index 0000000000..2af6435871
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.cpp
@@ -0,0 +1,1142 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "nstl.hpp"
+#include "utils.hpp"
+
+#include "jit_uni_eltwise.hpp"
+
+#define GET_OFF(field) offsetof(jit_args, field)
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace Xbyak;
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::injector_preamble(size_t start_idx,
+ size_t end_idx) {
+ preserved_vecs_count = 0;
+ vecs_to_preserve = (size_t)aux_vecs_count(alg_);
+ start_idx_tail = start_idx;
+
+ // For sse42 mask register has to be Xmm(0)
+ if (isa == sse42 && vecs_to_preserve > 0) {
+ size_t idx = 0;
+ assert(idx < start_idx);
+ preserved_vec_idxs[preserved_vecs_count++] = idx;
+ }
+
+ for (size_t idx = preserved_vecs_count; idx < vecs_count; idx++) {
+ if (preserved_vecs_count >= vecs_to_preserve) break;
+ if (start_idx <= idx && idx < end_idx) continue;
+
+ preserved_vec_idxs[preserved_vecs_count++] = idx;
+ }
+
+ size_t preserved_vecs_count_tail = vecs_to_preserve - preserved_vecs_count;
+ for (size_t i = 0; i < preserved_vecs_count_tail; i++) {
+ preserved_vec_idxs[preserved_vecs_count++] = start_idx_tail++;
+ }
+
+ assert(preserved_vecs_count == vecs_to_preserve);
+
+ if (save_state_) {
+ h->push(p_table);
+
+ if (preserved_vecs_count)
+ h->sub(h->rsp, preserved_vecs_count * vlen);
+
+ for (size_t i = 0; i < preserved_vecs_count; ++i)
+ h->uni_vmovups(h->ptr[h->rsp + i * vlen],
+ Vmm(preserved_vec_idxs[i]));
+
+ load_table_addr();
+ }
+
+ assign_regs();
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::injector_preamble_tail(size_t start_idx)
+{
+ size_t tail_vecs_to_preserve = start_idx_tail - start_idx;
+ if (tail_vecs_to_preserve == 0) return;
+
+ const int idx_off = vecs_to_preserve - tail_vecs_to_preserve;
+
+ if (save_state_) {
+ if (idx_off)
+ h->add(h->rsp, idx_off * vlen);
+
+ for (size_t i = 0; i < tail_vecs_to_preserve; ++i)
+ h->uni_vmovups(Vmm(preserved_vec_idxs[idx_off + i]),
+ h->ptr[h->rsp + i * vlen]);
+ }
+
+ for (size_t i = 0; i < tail_vecs_to_preserve; ++i)
+ preserved_vec_idxs[idx_off + i] += tail_vecs_to_preserve;
+
+ if (save_state_) {
+ for (size_t i = 0; i < tail_vecs_to_preserve; ++i)
+ h->uni_vmovups(h->ptr[h->rsp + i * vlen],
+ Vmm(preserved_vec_idxs[idx_off + i]));
+
+ if (idx_off)
+ h->sub(h->rsp, idx_off * vlen);
+ }
+
+ assign_regs();
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::injector_postamble() {
+ if (!save_state_) return;
+
+ for (size_t i = 0; i < preserved_vecs_count; ++i)
+ h->uni_vmovups(Vmm(preserved_vec_idxs[i]),
+ h->ptr[h->rsp + i * vlen]);
+
+ if (preserved_vecs_count)
+ h->add(h->rsp, preserved_vecs_count * vlen);
+
+ h->pop(p_table);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::assign_regs() {
+ vmm_mask = Vmm(preserved_vec_idxs[0]);
+ vmm_aux0 = Vmm(preserved_vec_idxs[0]);
+ vmm_aux1 = Vmm(preserved_vec_idxs[1]);
+ vmm_aux2 = Vmm(preserved_vec_idxs[2]);
+ vmm_aux3 = Vmm(preserved_vec_idxs[3]);
+ vmm_aux4 = Vmm(preserved_vec_idxs[4]);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::exp_compute_vector(const Vmm &vmm_src) {
+ h->uni_vminps(vmm_src, vmm_src, table_val(10));
+ h->uni_vmaxps(vmm_src, vmm_src, table_val(11));
+ h->uni_vmovups(vmm_aux0, vmm_src);
+ //calculate exp(x)
+ // fx = x * log2ef + 0.5
+ h->uni_vmulps(vmm_src, vmm_src, table_val(2));
+ h->uni_vaddps(vmm_src, vmm_src, table_val(1));
+
+ // tmp = floorf(fx)
+ if (isa == avx512_common) {
+ h->vcvtps2dq(vmm_aux1 | h->T_rd_sae, vmm_src);
+ h->vcvtdq2ps(vmm_aux1, vmm_aux1);
+
+ h->vcmpps(k_mask, vmm_aux1, vmm_src, _cmp_nle_us);
+ h->vmovups(vmm_aux3 | k_mask | h->T_z, table_val(0));
+
+ h->uni_vsubps(vmm_aux1, vmm_aux1, vmm_aux3);
+ } else {
+ h->uni_vroundps(vmm_aux1, vmm_src, _op_floor);
+ }
+
+ //keep fx for further computations
+ h->uni_vmovups(vmm_src, vmm_aux1); //vmm_src = fx
+
+ //x = x - fx * ln2
+ h->uni_vfnmadd231ps(vmm_aux0, vmm_aux1, table_val(3));
+
+ // compute 2^n
+ h->uni_vcvtps2dq(vmm_aux1, vmm_src);
+ h->uni_vpaddd(vmm_aux1, vmm_aux1, table_val(4));
+ h->uni_vpslld(vmm_aux1, vmm_aux1, 23); //Vmm(6) = 2^-fx
+
+ // y = p5
+ h->uni_vmovups(vmm_src, table_val(9));
+ // y = y * x + p4
+ h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(8));
+ // y = y * x + p3
+ h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(7));
+ // y = y * x + p2
+ h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(6));
+ // y = y * x + p1
+ h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(0));
+ // y = y * x + p0
+ h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(5)); //exp(q)
+ // y = y * 2^n
+ h->uni_vmulps(vmm_src, vmm_src, vmm_aux1);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::relu_compute_vector(const Vmm &vmm_src)
+{
+ const int alpha_off = 0, zero_off = 1;
+
+ h->uni_vmovups(vmm_aux1, vmm_src);
+ if (isa == sse42) {
+ h->movups(vmm_mask, vmm_src);
+ h->mulps(vmm_src, table_val(alpha_off));
+ h->cmpps(vmm_mask, table_val(zero_off), _cmp_nle_us);
+ h->blendvps(vmm_src, vmm_aux1);
+ } else if (isa == avx2) {
+ h->vmulps(vmm_src, vmm_src, table_val(alpha_off));
+ h->vcmpgtps(vmm_mask, vmm_aux1, table_val(zero_off));
+ h->vblendvps(vmm_src, vmm_src, vmm_aux1, vmm_mask);
+ } else if (isa == avx512_common) {
+ h->vmulps(vmm_src, vmm_src, table_val(alpha_off));
+ h->vcmpps(k_mask, vmm_aux1, table_val(zero_off), _cmp_nle_us);
+ h->vblendmps(vmm_src | k_mask, vmm_src, vmm_aux1);
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::relu_zero_ns_compute_vector(
+ const Vmm &vmm_src) {
+ const int zero_off = 1;
+ h->uni_vmaxps(vmm_src, vmm_src, table_val(zero_off));
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::elu_compute_vector(const Vmm &vmm_src) {
+ const int alpha_off = 23, zero_off = 24;
+
+ // compute exponent
+ h->uni_vmovups(vmm_aux2, vmm_src);
+ exp_compute_vector(vmm_src);
+
+ // alpha * (exp(x) - 1)
+ h->uni_vsubps(vmm_src, vmm_src, table_val(0));
+ h->uni_vmulps(vmm_src, vmm_src, table_val(alpha_off));
+
+ // combine with mask
+ if (isa == sse42) {
+ h->pxor(vmm_mask, vmm_mask);
+ h->cmpps(vmm_mask, vmm_aux2, _cmp_le_os);
+ h->blendvps(vmm_src, vmm_aux2);
+ } else if (isa == avx2) {
+ h->uni_vcmpgtps(vmm_mask, vmm_aux2, table_val(zero_off));
+ h->uni_vblendvps(vmm_src, vmm_src, vmm_aux2, vmm_mask);
+ } else if (isa == avx512_common) {
+ h->vcmpps(k_mask, vmm_aux2, table_val(zero_off), _cmp_nle_us);
+ h->vblendmps(vmm_src | k_mask, vmm_src, vmm_aux2);
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::tanh_compute_vector(const Vmm &vmm_src)
+{
+ // # comes from Taylor expansion error bound
+ // > linear_sat_point = single(sqrt(3) * 1b-12);
+ // # comes from the exp formula cancellation
+ // > exp_bound_point = (single(log(3)/2));
+ // # comes from rounding accuracy in float
+ // > one_sat_point = round(atanh(1 - 1b-25), single, RU);
+ // > P = fpminimax(f, [|1, 3, 5, 7, 9|], [|24... |],
+ // [linear_sat_point, exp_bound_point], relative, floating);
+ // > err_bound = D(sup(supnorm(P, tanh(x),
+ // [linear_sat_point, exp_bound_point], relative, theta)));
+ // 0x1.fffd6f00b9539p-25
+ // > P;
+ // x * (0x1.fffffep-1 + x^0x1p1 * (-0x1.55539ep-2 + x^0x1p1 *
+ // (0x1.10be3ep-3 + x^0x1p1 * (-0x1.ae57b4p-5
+ // + x^0x1p1 * 0x1.09fa1p-6))))
+
+ // register mapping
+ // vmm_src contains input
+ // vmm_aux0 contains mask of currently valid results.
+ // 1 is need computation, 0 is already computed
+ // vmm_aux1 contains current output
+ // vmm_aux2, vmm_aux3 contains auxiliary values
+ // vmm_aux4 contains the original sign of inputs
+
+ Label end_tanh_label;
+
+ auto test_exit =[&](Xbyak::Address threshold){
+ // is not necessary for >AVX, but should not matter on perf
+ h->uni_vmovups(vmm_aux0, vmm_src);
+ if (isa == avx512_common){
+ h->vcmpps(k_mask, vmm_aux0, threshold, 0x5);
+ h->kortestw(k_mask, k_mask);
+ } else {
+ h->uni_vcmpgeps(vmm_aux0, vmm_aux0, threshold);
+ h->uni_vtestps(vmm_aux0, vmm_aux0);
+ }
+ h->jz(end_tanh_label, Xbyak::CodeGenerator::T_NEAR);
+ };
+
+ auto blend_results=[&](Vmm vmm_partial_res){
+ if (isa == avx512_common)
+ h->vblendmps(vmm_aux1 | k_mask, vmm_aux1, vmm_partial_res);
+ else
+ h->uni_vblendvps(vmm_aux1, vmm_aux1, vmm_partial_res, vmm_aux0);
+ };
+
+ // because tanh(x) = -tanh(-x), we extract sign to make x postive
+ // and reapply sign at the end
+ // mov is not necessary for >AVX, but should not matter for performance
+ h->uni_vmovups(vmm_aux4, vmm_src);
+ h->uni_vandps(vmm_aux4, vmm_aux4, table_val(12));
+ h->uni_vandps(vmm_src, vmm_src, table_val(17));
+
+ // if x < linear_sat_point for all inputs, we just return the input
+ h->uni_vmovups(vmm_aux1, vmm_src);
+ test_exit(table_val(13));
+
+ // if one of the mask is one, we have to compute an better approx
+ h->uni_vmovups(vmm_aux2, vmm_src);
+ h->uni_vmulps(vmm_aux2, vmm_aux2, vmm_aux2);
+ h->uni_vmovups(vmm_aux3, table_val(22));
+ h->uni_vfmadd213ps(vmm_aux3, vmm_aux2, table_val(21));
+ h->uni_vfmadd213ps(vmm_aux3, vmm_aux2, table_val(20));
+ h->uni_vfmadd213ps(vmm_aux3, vmm_aux2, table_val(19));
+ h->uni_vfmadd213ps(vmm_aux3, vmm_aux2, table_val(18));
+ h->uni_vmulps(vmm_aux3, vmm_aux3, vmm_src);
+
+ // we blend only the result that need update
+ blend_results(vmm_aux3);
+
+ // if x < exp_bound_point, we go to return point
+ test_exit(table_val(14));
+
+ // if not we use a better approx 1 - 2 / (1 + exp(2x))
+ // compute 2x
+ h->uni_vmovups(vmm_aux3, vmm_src);
+ h->uni_vaddps(vmm_aux3, vmm_aux3, vmm_aux3);
+
+ // Compute exp(2x)
+ // We need to save kmask, vmm_aux0, vmm_aux1 and vmm_src as exp can use them
+ // vmm_src is not more read afterwards, so we do not have to save it
+ auto stack_size = 3 * vlen + (isa == avx512_common) * 4;
+ h->sub(h->rsp, stack_size);
+ h->uni_vmovups(h->ptr[h->rsp + 0 * vlen], vmm_aux0);
+ h->uni_vmovups(h->ptr[h->rsp + 1 * vlen], vmm_aux1);
+ h->uni_vmovups(h->ptr[h->rsp + 2 * vlen], vmm_src);
+ if (isa == avx512_common)
+ h->kmovw(h->ptr[h->rsp + 3 * vlen], k_mask);
+
+ exp_compute_vector(vmm_aux3);
+
+ h->uni_vmovups(vmm_aux0, h->ptr[h->rsp + 0 * vlen]);
+ h->uni_vmovups(vmm_aux1, h->ptr[h->rsp + 1 * vlen]);
+ h->uni_vmovups(vmm_src, h->ptr[h->rsp + 2 * vlen]);
+ if (isa == avx512_common)
+ h->kmovw(k_mask, h->ptr[h->rsp + 3 * vlen]);
+ h->add(h->rsp, stack_size);
+
+ // 1 + exp(2x)
+ h->uni_vaddps(vmm_aux3, vmm_aux3, table_val(0));
+
+ // 1 - 2 / (1 + exp(2x))
+ h->uni_vmovups(vmm_aux2, table_val(16));
+ h->uni_vdivps(vmm_aux2, vmm_aux2, vmm_aux3);
+ h->uni_vaddps(vmm_aux2, vmm_aux2, table_val(0));
+
+ // we blend only the result that need update
+ blend_results(vmm_aux2);
+
+ // finally, we saturate to 1 if needed
+ // TODO: maybe move that up if most inputs saturate in practice
+ if (isa == avx512_common)
+ h->vcmpps(k_mask, vmm_aux0, table_val(15), 0x5);
+ else {
+ h->uni_vmovups(vmm_aux0, vmm_src);
+ h->uni_vcmpgeps(vmm_aux0, vmm_aux0, table_val(15));
+ }
+ h->uni_vmovups(vmm_aux2, table_val(0));
+ blend_results(vmm_aux2);
+
+ h->L(end_tanh_label);
+ {
+ // we apply the sign of x to the result and we are done
+ h->uni_vmovups(vmm_src, vmm_aux1);
+ h->uni_vpxor(vmm_src, vmm_src, vmm_aux4);
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::square_compute_vector(
+ const Vmm &vmm_src) {
+ h->uni_vmulps(vmm_src, vmm_src, vmm_src);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::abs_compute_vector(const Vmm &vmm_src) {
+ // compute abs(x) = _mm_and_ps(x, 01111..111));
+ h->uni_vandps(vmm_src, vmm_src, table_val(0));
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::sqrt_compute_vector(const Vmm &vmm_src)
+{
+ if (isa == avx512_common) {
+ h->vcmpps(k_mask, vmm_src, table_val(0), _cmp_nle_us);
+ h->uni_vsqrtps(vmm_aux1, vmm_src);
+ h->uni_vmovups(vmm_src, table_val(0));
+ h->vblendmps(vmm_src | k_mask, vmm_src, vmm_aux1);
+ } else {
+ h->uni_vmovups(vmm_mask, vmm_src);
+ h->uni_vcmpgtps(vmm_mask, vmm_mask, table_val(0));
+ h->uni_vsqrtps(vmm_aux1, vmm_src);
+ h->uni_vmovups(vmm_src, table_val(0));
+ h->uni_vblendvps(vmm_src, vmm_src, vmm_aux1, vmm_mask);
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::linear_compute_vector(
+ const Vmm &vmm_src) {
+ // compute x = alpha * x + beta;
+ h->uni_vmovups(vmm_aux0, table_val(0));
+ h->uni_vfmadd213ps(vmm_src, vmm_aux0, table_val(1));
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::bounded_relu_compute_vector(
+ const Vmm &vmm_src) {
+ // compute bounded relu */
+ h->uni_vmaxps(vmm_src, vmm_src, table_val(1));
+ h->uni_vminps(vmm_src, vmm_src, table_val(0));
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::soft_relu_compute_vector(
+ const Vmm &vmm_src) {
+ // duplicate src
+ h->uni_vmovups(vmm_aux2, vmm_src);
+
+ h->uni_vminps(vmm_src, vmm_src, table_val(24));
+ h->uni_vmaxps(vmm_src, vmm_src, table_val(25));
+ h->uni_vmovups(vmm_aux1, vmm_src);
+ // calculate exp(x)
+ // fx = x * log2ef + 0.5
+ h->uni_vmulps(vmm_src, vmm_src, table_val(2));
+ h->uni_vaddps(vmm_src, vmm_src, table_val(1));
+
+ // tmp = floorf(fx)
+ if (isa == avx512_common) {
+ h->vcvtps2dq(vmm_aux0 | h->T_rd_sae, vmm_src);
+ h->vcvtdq2ps(vmm_aux0, vmm_aux0);
+
+ h->vcmpps(k_mask, vmm_aux0, vmm_src, _cmp_nle_us);
+ h->vmovups(vmm_aux3 | k_mask | h->T_z, table_val(0));
+
+ h->vsubps(vmm_aux0, vmm_aux0, vmm_aux3);
+ } else {
+ h->uni_vroundps(vmm_aux0, vmm_src, _op_floor);
+ }
+
+ // keep fx for further computations
+ h->uni_vmovups(vmm_src, vmm_aux0); //vmm_src = fx
+ // calculation fx * ln2
+ h->uni_vmulps(vmm_aux0, vmm_aux0, table_val(3));
+ // x = x - fx * ln2
+ h->uni_vsubps(vmm_aux1, vmm_aux1, vmm_aux0);
+ // y = p5
+ h->uni_vmovups(vmm_aux3, table_val(22));
+ // y = y * x + p4
+ h->uni_vfmadd213ps(vmm_aux3, vmm_aux1, table_val(21));
+ // y = y * x + p3
+ h->uni_vfmadd213ps(vmm_aux3, vmm_aux1, table_val(20));
+ // y = y * x + p2
+ h->uni_vfmadd213ps(vmm_aux3, vmm_aux1, table_val(19));
+ // y = y * x + p1
+ h->uni_vfmadd213ps(vmm_aux3, vmm_aux1, table_val(0));
+ // y = y * x + p0
+ h->uni_vfmadd213ps(vmm_aux3, vmm_aux1, table_val(17));
+
+ // compute 2^(-n)
+ if (isa == avx512_common) {
+ h->vmulps(vmm_aux1, vmm_src, table_val(23));
+ h->vcvtps2dq(vmm_aux1, vmm_aux1);
+ } else {
+ h->uni_vcvtps2dq(vmm_aux1, vmm_src);
+ h->uni_vpsignd(vmm_aux1, vmm_aux1, table_val(23));
+ }
+
+ h->uni_vpaddd(vmm_aux1, vmm_aux1, table_val(4));
+ h->uni_vpslld(vmm_aux1, vmm_aux1, 23); //vmm_aux1 = 2^-fx
+ // calculate ln(1 + y)
+ h->uni_vaddps(vmm_aux3, vmm_aux3, vmm_aux1);
+ // x = y; y is free; keep x for further computations
+ h->uni_vmovups(vmm_src, vmm_aux3);
+ // frexp()
+ h->uni_vpsrld(vmm_src, vmm_src, 23);
+ h->uni_vcvtdq2ps(vmm_src, vmm_src);
+ // got n. where n is x = 2^n * y. y = 0.5 .. 1
+ h->uni_vsubps(vmm_src, vmm_src, table_val(5));
+
+ h->uni_vandps(vmm_aux3, vmm_aux3, table_val(6));
+ // got y. (mantisa) 0.5 < y < 1
+ h->uni_vorps(vmm_aux3, vmm_aux3, table_val(7));
+ // y = y - 1
+ h->uni_vsubps(vmm_aux3, vmm_aux3, table_val(0));
+ // y = p8
+ h->uni_vmovups(vmm_aux1, table_val(16));
+ // y = y * x + p7
+ h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(15));
+ // y = y * x + p6
+ h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(14));
+ // y = y * x + p5
+ h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(13));
+ // y = y * x + p4
+ h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(12));
+ // y = y * x + p3
+ h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(11));
+ // y = y * x + p2
+ h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(10));
+ // y = y * x + p1
+ h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(9));
+ // y = y * x + p0 ; p0 = 0
+ h->uni_vfmadd213ps(vmm_aux1, vmm_aux3, table_val(8));
+ //calculate ln(2) * n
+ h->uni_vmulps(vmm_src, vmm_src, table_val(3));
+ h->uni_vaddps(vmm_aux1, vmm_aux1, vmm_src);
+ h->uni_vaddps(vmm_aux1, vmm_aux1, vmm_aux0);
+
+ // get vmm_mask = src > max logf
+ h->uni_vmovups(vmm_mask, vmm_aux2);
+ if (isa == avx512_common) {
+ // y = (x < max log f) ? soft_relu(x) : x
+ h->vcmpps(k_mask, vmm_mask, table_val(24), _cmp_nle_us);
+ h->vblendmps(vmm_aux1 | k_mask, vmm_aux1, vmm_aux2);
+ } else {
+ // y = (x < max log f) ? soft_relu(x) : x
+ h->uni_vcmpgtps(vmm_mask, vmm_mask, table_val(24));
+ h->uni_vblendvps(vmm_aux1, vmm_aux1, vmm_aux2, vmm_mask);
+ }
+
+ h->uni_vmovups(vmm_src, vmm_aux1);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::logistic_compute_vector(
+ const Vmm &vmm_src) {
+ // we store the original sign and make x negative
+ // IMPORTANT: we assume vmm_aux0 to be xmm0, as for sse4.2 path it is required
+ // IMPORTANT: we use vmm_aux2 for the mask as exp_compute does not use it.
+ h->uni_vmovups(vmm_aux2, vmm_src);
+ h->uni_vandps(vmm_aux2, vmm_aux2, table_val(12));
+ h->uni_vorps(vmm_src, vmm_src, table_val(12));
+
+ exp_compute_vector(vmm_src);
+ // dup exp(x)
+ h->uni_vmovups(vmm_aux1, vmm_src);
+ // (exp(x) + 1)
+ h->uni_vaddps(vmm_aux1, vmm_aux1, table_val(0));
+ // y = exp(x) / (exp(x) + 1)
+ h->uni_vdivps(vmm_src, vmm_src, vmm_aux1);
+
+ // Now we have to apply the "symmetry" based on original sign
+ h->uni_vmovups(vmm_aux3, table_val(0));
+ h->uni_vsubps(vmm_aux3, vmm_aux3, vmm_src);
+ if (isa == avx512_common) {
+ h->vptestmd(k_mask, vmm_aux2, vmm_aux2);
+ h->vblendmps(vmm_aux3 | k_mask, vmm_aux3, vmm_src);
+ } else {
+ h->uni_vmovups(vmm_aux0, vmm_aux2);// The mask should be xmm0 for sse4.2
+ h->uni_vblendvps(vmm_aux3, vmm_aux3, vmm_src, vmm_aux0);
+ }
+ h->uni_vmovups(vmm_src, vmm_aux3);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::relu_prepare_table() {
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(float2int(alpha_));
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(0);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::elu_prepare_table() {
+ const unsigned int cvals[] = {
+ 0x3f800000, // [0] 1.0f
+ 0x3f000000, // [1] 0.5f
+ 0x3fb8aa3b, // [2] log2ef = 1.44269502f
+ 0x3f317218, // [3] ln2f = 0.69314718f
+ 0x0000007f, // [4] 0x7f
+ // exp(x) polynom
+ 0x3f800001, // [5] p0 = 1.0000001f
+ 0x3efffe85, // [6] p2 = 0.4999887f
+ 0x3e2aaa3e, // [7] p3 = 0.16666505f
+ 0x3d2bb1b1, // [8] p4 = 0.041917507f
+ 0x3c091ec1, // [9] p5 = 0.008369149f
+ 0x42b0c0a5, //[10] max logf = 88.3762589f
+ 0xc1766666, //[11] min logf = -14.5f
+ // tanh(x) constants,
+ 0x80000000, //[12] mask to extract sign
+ 0x39ddb3d7, //[13] arg below which tanh(x) = x
+ 0x3f0c9f54, //[14] arg below which pol approx is valid
+ 0x41102cb4, //[15] arg after which tanh(x) = 1
+ 0xc0000000, //[16] -2.0f
+ 0x7fffffff, //[17] mask to make positive
+ // tanh pol approx
+ 0x3f7fffff, //[18] p0
+ 0xbeaaa9cf, //[19] p1
+ 0x3e085f1f, //[20] p2
+ 0xbd572bda, //[21] p3
+ 0x3c84fd08, //[22] p4
+ };
+
+ for (size_t i = 0; i < sizeof(cvals) / sizeof(cvals[0]); ++i) {
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(cvals[i]);
+ }
+
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(float2int(alpha_));
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(0);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::soft_relu_prepare_table() {
+ const unsigned int cvals[] = {
+ 0x3f800000, // [0] 1.0f
+ 0x3f000000, // [1] 0.5f
+ 0x3fb8aa3b, // [2] log2ef = 1.44269502f
+ 0x3f317218, // [3] ln2f = 0.69314718f
+ 0x0000007f, // [4] 0x7f
+ 0x42fc0000, // [5] 126
+ 0x807fffff, // [6] and with (to get 0.5 * mantissa)
+ 0x3f000000, // [7] or with (to get 0.5 * mantissa)
+ // ln(1 + x) polynomial
+ 0xb2b4637d, // [8] p0 = 0.0000000244f
+ 0x3f7fff8e, // [9] p1 = 0.9999976971f
+ 0xbf001759, //[10] p2 = -0.5002478215f
+ 0x3ea70608, //[11] p3 = 0.3272714505f
+ 0xbea3d7bf, //[12] p4 = -0.3153830071f
+ 0xbe361d04, //[13] p5 = -0.1701777461f
+ 0xbfa8f1e6, //[14] p6 = -1.3254635147f
+ 0xbfe1e812, //[15] p7 = -1.7971917960f
+ 0xbfc4d30e, //[16] p8 = -1.5652673123f
+ // exp(x) polynomial
+ 0x3f800001, //[17] p0 = 1.0000001f
+ 0x3f800000, //[18] p1 = 1.0f
+ 0x3efffe85, //[19] p2 = 0.4999887f
+ 0x3e2aaa3e, //[20] p3 = 0.16666505f
+ 0x3d2bb1b1, //[21] p4 = 0.041917507f
+ 0x3c091ec1, //[22] p5 = 0.008369149f
+ 0xbf800000, //[23] is required for sign changing
+ 0x42b0c0a5, //[24] max logf = 88.3762589f
+ 0xc1766666 //[25] min logf = -14.5f
+ };
+
+ for (size_t i = 0; i < sizeof(cvals) / sizeof(cvals[0]); ++i) {
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) {
+ h->dd(cvals[i]);
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::abs_prepare_table() {
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(0x7fffffff);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::sqrt_prepare_table() {
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(0);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::linear_prepare_table() {
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(float2int(alpha_));
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(float2int(beta_));
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::bounded_relu_prepare_table() {
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(float2int(alpha_));
+ for (size_t d = 0; d < vlen / sizeof(float); ++d) h->dd(0);
+}
+
+template <cpu_isa_t isa>
+int jit_uni_eltwise_injector_f32<isa>::aux_vecs_count(alg_kind_t alg_) {
+ switch (alg_) {
+ case alg_kind::eltwise_relu: return (alpha_ == 0.f) ? 0 : 2;
+ case alg_kind::eltwise_elu: return 4;
+ case alg_kind::eltwise_tanh: return 5;
+ case alg_kind::eltwise_square: return 0;
+ case alg_kind::eltwise_abs: return 0;
+ case alg_kind::eltwise_sqrt: return 2;
+ case alg_kind::eltwise_linear: return 1;
+ case alg_kind::eltwise_bounded_relu: return 0;
+ case alg_kind::eltwise_soft_relu: return 4;
+ case alg_kind::eltwise_logistic: return 4;
+ default: assert(!"unsupported eltwise algorithm");
+ }
+
+ return 0;
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::compute_body(size_t start_idx,
+ size_t end_idx) {
+ using namespace alg_kind;
+ for (size_t idx = start_idx; idx < end_idx; idx++) {
+ switch (alg_) {
+ case eltwise_relu:
+ if (alpha_ == 0.f) relu_zero_ns_compute_vector(Vmm(idx));
+ else relu_compute_vector(Vmm(idx));
+ break;
+ case eltwise_elu: elu_compute_vector(Vmm(idx)); break;
+ case eltwise_tanh: tanh_compute_vector(Vmm(idx)); break;
+ case eltwise_square: square_compute_vector(Vmm(idx)); break;
+ case eltwise_abs: abs_compute_vector(Vmm(idx)); break;
+ case eltwise_sqrt: sqrt_compute_vector(Vmm(idx)); break;
+ case eltwise_linear: linear_compute_vector(Vmm(idx)); break;
+ case eltwise_bounded_relu: bounded_relu_compute_vector(Vmm(idx)); break;
+ case eltwise_soft_relu: soft_relu_compute_vector(Vmm(idx)); break;
+ case eltwise_logistic: logistic_compute_vector(Vmm(idx)); break;
+ default: assert(!"unsupported eltwise algorithm");
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::compute_vector_range(size_t start_idx,
+ size_t end_idx) {
+ assert(start_idx < end_idx && end_idx <= vecs_count);
+
+ injector_preamble(start_idx, end_idx);
+ compute_body(start_idx_tail, end_idx);
+ injector_preamble_tail(start_idx);
+ compute_body(start_idx, start_idx_tail);
+ injector_postamble();
+}
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_injector_f32<isa>::prepare_table(bool gen_table) {
+ using namespace alg_kind;
+
+ h->align(64);
+ h->L(l_table);
+
+ if (gen_table) {
+ switch (alg_) {
+ case eltwise_relu: relu_prepare_table(); break;
+ case eltwise_elu:
+ case eltwise_tanh:
+ case eltwise_logistic:
+ elu_prepare_table(); break;
+ case eltwise_soft_relu: soft_relu_prepare_table(); break;
+ case eltwise_abs: abs_prepare_table(); break;
+ case eltwise_sqrt: sqrt_prepare_table(); break;
+ case eltwise_linear: linear_prepare_table(); break;
+ case eltwise_bounded_relu: bounded_relu_prepare_table(); break;
+ case eltwise_square: break;
+ default: assert(!"unsupported eltwise algorithm");
+ }
+ }
+}
+
+template struct jit_uni_eltwise_injector_f32<avx512_common>;
+template struct jit_uni_eltwise_injector_f32<avx2>;
+template struct jit_uni_eltwise_injector_f32<sse42>;
+
+
+struct jit_args {
+ const float *from;
+ const float *for_comparison;
+ const float *to;
+ size_t work_amount;
+};
+
+struct jit_uni_eltwise_kernel_f32 : public c_compatible {
+ const eltwise_desc_t &desc_;
+
+ void (*ker_)(const jit_args *);
+ void operator()(const jit_args *args) { assert(ker_); ker_(args); }
+
+ jit_uni_eltwise_kernel_f32(const eltwise_desc_t &desc)
+ : desc_(desc), ker_(nullptr) {}
+ virtual ~jit_uni_eltwise_kernel_f32() {}
+
+protected:
+ bool is_bwd() const { return desc_.prop_kind == prop_kind::backward_data; }
+};
+
+/* jit kernels */
+namespace {
+
+template <cpu_isa_t isa>
+struct jit_uni_relu_kernel_f32 : public jit_uni_eltwise_kernel_f32,
+ public jit_generator
+{
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_relu_kernel_f32)
+
+ void compute_step(bool vectorize, const int uf, const int shift) {
+ for (int i = 0; i < uf; i++) {
+ if (vectorize) {
+ uni_vmovups(Vmm(i + 1), ptr[reg_from + i * shift]);
+ if (is_bwd())
+ uni_vmovups(Vmm(uf + i + 1),
+ ptr[reg_for_comparison + i * shift]);
+ } else {
+ movss(Xmm(i + 1), ptr[reg_from + i * shift]);
+ if (is_bwd())
+ movss(Xmm(uf + i + 1),
+ ptr[reg_for_comparison + i * shift]);
+ }
+ }
+
+ if (isa == sse42) {
+ for (int i = 0; i < uf; i++) {
+ movups(Vmm(2 * uf + i + 1), Vmm(i + 1));
+ mulps(Vmm(2 * uf + i + 1), vmm_ns);
+
+ Vmm mask = Vmm(0);
+ if (is_bwd()) {
+ movups(mask, Vmm(uf + i + 1));
+ cmpps(mask, vmm_zero, _cmp_nle_us);
+ } else {
+ movups(mask, Vmm(i + 1));
+ cmpps(mask, vmm_zero, _cmp_nle_us);
+ }
+ blendvps(Vmm(2 * uf + i + 1), Vmm(i + 1));
+ }
+ } else {
+ for (int i = 0; i < uf; i++) {
+ vmulps(Vmm(2 * uf + i + 1), Vmm(i + 1), vmm_ns);
+ if (isa == avx2) {
+ if (is_bwd())
+ vcmpgtps(vmm_mask, Vmm(uf + i + 1), vmm_zero);
+ else
+ vcmpgtps(vmm_mask, Vmm(i + 1), vmm_zero);
+
+ vblendvps(Vmm(2 * uf + i + 1), Vmm(2 * uf + i + 1),
+ Vmm(i + 1), vmm_mask);
+
+ } else {
+ if (is_bwd())
+ vcmpps(k_mask, Vmm(uf + i + 1), vmm_zero, _cmp_nle_us);
+ else
+ vcmpps(k_mask, Vmm(i + 1), vmm_zero, _cmp_nle_us);
+ vblendmps(Vmm(2 * uf + i + 1) | k_mask, Vmm(2 * uf + i + 1),
+ Vmm(i + 1));
+ }
+ }
+ }
+
+ for (int i = 0; i < uf; i++) {
+ if (vectorize) {
+ uni_vmovups(ptr[reg_to + i * shift], Vmm(2 * uf + i + 1));
+ } else {
+ movss(ptr[reg_to + i * shift], Xmm(2 * uf + i + 1));
+ }
+ }
+ }
+
+ jit_uni_relu_kernel_f32(const eltwise_desc_t &desc)
+ : jit_uni_eltwise_kernel_f32(desc), jit_generator() {
+ assert(desc.alg_kind == alg_kind::eltwise_relu);
+ assert(isa == sse42 || isa == avx2 || isa == avx512_common);
+
+ Reg64 param = abi_param1;
+
+ const int simd_w = cpu_isa_traits<isa>::vlen / sizeof(float);
+ const int loop_dec[] = {simd_w, 1};
+ const int uf[] = {1, 1};
+ const int shift[] = {cpu_isa_traits<isa>::vlen, sizeof(float)};
+ const bool loop_vectorize[] = {true, false};
+
+ this->preamble();
+
+ mov(reg_from, ptr[param + GET_OFF(from)]);
+ if (is_bwd())
+ mov(reg_for_comparison, ptr[param + GET_OFF(for_comparison)]);
+ mov(reg_to, ptr[param + GET_OFF(to)]);
+ mov(reg_work_amount, ptr[param + GET_OFF(work_amount)]);
+
+ mov(imm_addr64, float2int(desc.alpha));
+ movq(xmm_ns, imm_addr64);
+ uni_vbroadcastss(vmm_ns, xmm_ns);
+
+ uni_vpxor(vmm_zero, vmm_zero, vmm_zero);
+
+ Label loop_label[3];
+
+ for (int id = 0; id < 2; id++) {
+ L(loop_label[id]);
+ cmp(reg_work_amount, uf[id] * loop_dec[id] - 1);
+ jle(loop_label[id + 1], T_NEAR);
+
+ compute_step(loop_vectorize[id], uf[id], shift[id]);
+
+ add(reg_from, uf[id] * shift[id]);
+ add(reg_to, uf[id] * shift[id]);
+ if (is_bwd())
+ add(reg_for_comparison, uf[id] * shift[id]);
+
+ sub(reg_work_amount, uf[id] * loop_dec[id]);
+ jmp(loop_label[id]);
+ }
+
+ L(loop_label[2]);
+ this->postamble();
+
+ ker_ = (decltype(ker_))this->getCode();
+ }
+
+private:
+ using Vmm = typename utils::conditional3<isa == sse42, Xmm,
+ isa == avx2, Ymm, Zmm>::type;
+
+ Reg64 reg_from = rax;
+ Reg64 reg_for_comparison = is_bwd() ? rdx : reg_from;
+ Reg64 reg_to = r8;
+ Reg64 reg_work_amount = rsi;
+ Reg64 imm_addr64 = rbx;
+
+ Xmm xmm_ns = Xmm(14);
+
+ Vmm vmm_ns = Vmm(isa == avx512_common ? 30 : 14);
+ Vmm vmm_zero = Vmm(isa == avx512_common ? 31 : 15);
+
+ Vmm vmm_mask = Vmm(isa == avx512_common ? 28 : 12);
+ Opmask k_mask = Opmask(1);
+};
+
+template <cpu_isa_t isa>
+struct jit_uni_kernel_fwd_f32: public jit_uni_eltwise_kernel_f32,
+ public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_kernel_fwd_f32)
+
+ jit_uni_kernel_fwd_f32(const eltwise_desc_t &desc)
+ : jit_uni_eltwise_kernel_f32(desc), jit_generator() {
+
+ eltwise_injector_ = new jit_uni_eltwise_injector_f32<isa>(this,
+ desc.alg_kind, desc.alpha, desc.beta, false, r9, Opmask(1));
+
+ using namespace alg_kind;
+
+ assert(is_bwd() == false);
+ assert(utils::one_of(desc.alg_kind, eltwise_tanh, eltwise_elu,
+ eltwise_square, eltwise_abs, eltwise_sqrt, eltwise_linear,
+ eltwise_bounded_relu, eltwise_soft_relu, eltwise_logistic));
+
+ preamble();
+
+ Reg64 param = abi_param1;
+ mov(reg_from, ptr[param + GET_OFF(from)]);
+ mov(reg_to, ptr[param + GET_OFF(to)]);
+ mov(reg_work_amount, ptr[param + GET_OFF(work_amount)]);
+ eltwise_injector_->load_table_addr();
+
+ Label reminder_loop_start, reminder_loop_end;
+ Label vectorized_loop_start, vectorized_loop_end;
+
+ cmp(reg_work_amount, simd_w);
+ jl(reminder_loop_start, T_NEAR);
+
+ L(vectorized_loop_start);
+
+ uni_vmovups(vmm_src, ptr[reg_from]);
+ eltwise_injector_->compute_vector(vmm_src.getIdx());
+ uni_vmovups(ptr[reg_to], vmm_src);
+
+ add(reg_from, vlen);
+ add(reg_to, vlen);
+
+ sub(reg_work_amount, simd_w);
+ cmp(reg_work_amount, simd_w);
+ jge(vectorized_loop_start, T_NEAR);
+
+ L(vectorized_loop_end);
+
+ L(reminder_loop_start);
+
+ cmp(reg_work_amount, 0);
+ jle(reminder_loop_end, T_NEAR);
+
+ movss(xmm_src, ptr[reg_from]);
+ eltwise_injector_->compute_vector(xmm_src.getIdx());
+ movss(ptr[reg_to], xmm_src);
+
+ add(reg_from, sizeof(float));
+ add(reg_to, sizeof(float));
+
+ dec(reg_work_amount);
+ jmp(reminder_loop_start, T_NEAR);
+
+ L(reminder_loop_end);
+
+ postamble();
+
+ eltwise_injector_->prepare_table();
+
+ ker_ = (decltype(ker_))this->getCode();
+ }
+
+ ~jit_uni_kernel_fwd_f32() { delete eltwise_injector_; }
+
+private:
+ using Vmm = typename utils::conditional3<isa == sse42, Xmm,
+ isa == avx2, Ymm, Zmm>::type;
+
+ const int simd_w = cpu_isa_traits<isa>::vlen / sizeof(float);
+ const int vlen = cpu_isa_traits<isa>::vlen;
+
+ Reg64 reg_from = rax;
+ Reg64 reg_to = r8;
+ Reg64 reg_work_amount = rsi;
+ Reg64 imm_addr64 = rbx;
+
+ Xmm xmm_src = Xmm(1);
+ Vmm vmm_src = Vmm(1);
+
+ jit_uni_eltwise_injector_f32<isa> *eltwise_injector_;
+};
+
+} /* namespace */
+
+template <cpu_isa_t isa>
+status_t jit_uni_eltwise_fwd_t<isa>::pd_t::init() {
+ using namespace alg_kind;
+
+ bool ok = true
+ && mayiuse(isa)
+ && is_fwd()
+ && utils::everyone_is(data_type::f32, desc()->data_desc.data_type)
+ && !has_zero_dim_memory()
+ && utils::one_of(desc()->alg_kind, eltwise_relu, eltwise_tanh,
+ eltwise_elu, eltwise_square, eltwise_abs, eltwise_sqrt,
+ eltwise_linear, eltwise_bounded_relu, eltwise_soft_relu,
+ eltwise_logistic)
+ && memory_desc_wrapper(src_md()).is_dense(true)
+ && IMPLICATION(!memory_desc_wrapper(src_md()).is_dense(false),
+ math::eltwise_fwd_preserves_zero(desc()->alg_kind, true))
+ && attr()->has_default_values();
+
+ return ok ? status::success : status::unimplemented;
+}
+
+template <cpu_isa_t isa>
+jit_uni_eltwise_fwd_t<isa>::jit_uni_eltwise_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd), kernel_(nullptr) {
+ const auto &desc = *pd()->desc();
+ switch (desc.alg_kind) {
+ case alg_kind::eltwise_relu:
+ kernel_ = new jit_uni_relu_kernel_f32<isa>(desc); break;
+ default:
+ kernel_ = new jit_uni_kernel_fwd_f32<isa>(desc);
+ }
+}
+
+template <cpu_isa_t isa>
+jit_uni_eltwise_fwd_t<isa>::~jit_uni_eltwise_fwd_t()
+{ delete kernel_; }
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_fwd_t<isa>::execute_forward(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+
+ const size_t nelems = data_d.nelems(true);
+
+ src += data_d.offset0();
+ dst += data_d.offset0();
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ size_t start{0}, end{0};
+
+ const int cache_line = 16;
+
+ balance211(utils::div_up(nelems, cache_line), nthr, ithr, start, end);
+ start = nstl::min(nelems, start * cache_line);
+ end = nstl::min(nelems, end * cache_line);
+
+ auto arg = jit_args();
+ arg.from = &src[start];
+ arg.for_comparison = &src[start];
+ arg.to = &dst[start];
+ arg.work_amount = end - start;
+ if (arg.work_amount)
+ (*kernel_)(&arg);
+ });
+}
+
+template <cpu_isa_t isa>
+status_t jit_uni_eltwise_bwd_t<isa>::pd_t::init() {
+ bool ok = true
+ && !is_fwd()
+ && utils::one_of(desc()->alg_kind, alg_kind::eltwise_relu)
+ && src_md()->data_type == data_type::f32
+ && !has_zero_dim_memory()
+ && mayiuse(isa)
+ && memory_desc_wrapper(src_md()).is_dense()
+ && memory_desc_wrapper(diff_dst_md()) == memory_desc_wrapper(src_md())
+ && attr()->has_default_values();
+
+ return ok ? status::success : status::unimplemented;
+}
+
+template <cpu_isa_t isa>
+jit_uni_eltwise_bwd_t<isa>::jit_uni_eltwise_bwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd), kernel_(nullptr) {
+ const auto &desc = *pd()->desc();
+ switch (desc.alg_kind) {
+ case alg_kind::eltwise_relu:
+ kernel_ = new jit_uni_relu_kernel_f32<isa>(desc); break;
+ default: assert(!"unknown eltwise alg_kind");
+ }
+}
+
+template <cpu_isa_t isa>
+jit_uni_eltwise_bwd_t<isa>::~jit_uni_eltwise_bwd_t()
+{ delete kernel_; }
+
+template <cpu_isa_t isa>
+void jit_uni_eltwise_bwd_t<isa>::execute_backward(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+ const memory_desc_wrapper diff_data_d(pd()->diff_src_md());
+
+ const size_t nelems = data_d.nelems();
+
+ src += data_d.offset0();
+ diff_dst += diff_data_d.offset0();
+ diff_src += diff_data_d.offset0();
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ size_t start{0}, end{0};
+
+ const int cache_line = 16;
+
+ balance211(utils::div_up(nelems, cache_line), nthr, ithr, start, end);
+ start = nstl::min(nelems, start * cache_line);
+ end = nstl::min(nelems, end * cache_line);
+
+ auto arg = jit_args();
+ arg.from = &diff_dst[start];
+ arg.to = &diff_src[start];
+ arg.for_comparison = &src[start];
+ arg.work_amount = end - start;
+ if (arg.work_amount)
+ (*kernel_)(&arg);
+ });
+}
+
+template struct jit_uni_eltwise_fwd_t<sse42>;
+template struct jit_uni_eltwise_bwd_t<sse42>;
+template struct jit_uni_eltwise_fwd_t<avx2>;
+template struct jit_uni_eltwise_bwd_t<avx2>;
+template struct jit_uni_eltwise_fwd_t<avx512_common>;
+template struct jit_uni_eltwise_bwd_t<avx512_common>;
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.hpp
new file mode 100644
index 0000000000..45436b9f46
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_eltwise.hpp
@@ -0,0 +1,193 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_UNI_ELTWISE_HPP
+#define CPU_JIT_UNI_ELTWISE_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_eltwise_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <cpu_isa_t isa>
+struct jit_uni_eltwise_injector_f32 {
+ using Vmm = typename utils::conditional3<isa == sse42, Xbyak::Xmm,
+ isa == avx2, Xbyak::Ymm, Xbyak::Zmm>::type;
+
+ jit_uni_eltwise_injector_f32(jit_generator *host, alg_kind_t alg,
+ float alpha, float beta, bool save_state = true,
+ Xbyak::Reg64 p_table = Xbyak::util::rax,
+ Xbyak::Opmask k_mask = Xbyak::Opmask(1))
+ : alg_(alg), alpha_(alpha), beta_(beta), h(host)
+ , save_state_(save_state), p_table(p_table), k_mask(k_mask)
+ {
+ using namespace alg_kind;
+ assert(utils::one_of(isa, sse42, avx2, avx512_common));
+ assert(utils::one_of(alg_, eltwise_relu, eltwise_tanh, eltwise_elu,
+ eltwise_square, eltwise_abs, eltwise_sqrt, eltwise_linear,
+ eltwise_bounded_relu, eltwise_soft_relu, eltwise_logistic));
+ }
+
+ // note that eltwise.scale is ignored
+ jit_uni_eltwise_injector_f32(jit_generator *host,
+ const post_ops_t::entry_t::eltwise_t &eltwise,
+ bool save_state = true, Xbyak::Reg64 p_table = Xbyak::util::rax,
+ Xbyak::Opmask k_mask = Xbyak::Opmask(1))
+ : jit_uni_eltwise_injector_f32(host, eltwise.alg, eltwise.alpha,
+ eltwise.beta, save_state, p_table, k_mask) {}
+
+ void compute_vector_range(size_t start_idx, size_t end_idx);
+ void compute_vector(size_t idx) { compute_vector_range(idx, idx + 1); }
+ void prepare_table(bool gen_table=true);
+ void load_table_addr() { h->mov(p_table, l_table); }
+
+ const alg_kind_t alg_;
+ const float alpha_;
+ const float beta_;
+
+ jit_generator * const h;
+
+ const bool save_state_;
+ const Xbyak::Reg64 p_table;
+ const Xbyak::Opmask k_mask;
+ Xbyak::Label l_table;
+
+private:
+ // if only the injector was inherited from jit_generator...
+ enum {
+ _cmp_le_os = jit_generator::_cmp_le_os,
+ _cmp_nle_us = jit_generator::_cmp_nle_us,
+ _op_floor = jit_generator::_op_floor,
+ };
+
+ size_t vlen = cpu_isa_traits<isa>::vlen;
+
+ const static size_t preserved_vecs_max = 5;
+
+ size_t vecs_to_preserve = 0;
+ size_t vecs_count = isa == avx512_common ? 32 : 16;
+ size_t preserved_vecs_count = 0;
+ size_t preserved_vec_idxs[preserved_vecs_max] = {0};
+ size_t start_idx_tail = 0;
+
+ Vmm vmm_mask, vmm_aux0, vmm_aux1, vmm_aux2, vmm_aux3, vmm_aux4;
+
+ Xbyak::Address table_val(int index)
+ { return h->ptr[p_table + index * vlen]; }
+
+ int aux_vecs_count(alg_kind_t alg);
+
+ void compute_body(size_t start_idx, size_t end_idx);
+ void injector_preamble(size_t start_idx, size_t end_idx);
+ void injector_preamble_tail(size_t start_idx);
+ void injector_postamble();
+ void assign_regs();
+
+ void exp_compute_vector(const Vmm &vmm_src);
+ void relu_compute_vector(const Vmm &vmm_src);
+ void relu_zero_ns_compute_vector(const Vmm &vmm_src);
+ void elu_compute_vector(const Vmm &vmm_src);
+ void tanh_compute_vector(const Vmm &vmm_src);
+ void square_compute_vector(const Vmm &vmm_src);
+ void abs_compute_vector(const Vmm &vmm_src);
+ void sqrt_compute_vector(const Vmm &vmm_src);
+ void linear_compute_vector(const Vmm &vmm_src);
+ void bounded_relu_compute_vector(const Vmm &vmm_src);
+ void soft_relu_compute_vector(const Vmm &vmm_src);
+ void logistic_compute_vector(const Vmm &vmm_src);
+
+ void relu_prepare_table();
+ void elu_prepare_table();
+ void soft_relu_prepare_table();
+ void abs_prepare_table();
+ void sqrt_prepare_table();
+ void linear_prepare_table();
+ void bounded_relu_prepare_table();
+};
+
+struct jit_uni_eltwise_kernel_f32;
+
+template <cpu_isa_t isa>
+struct jit_uni_eltwise_fwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_eltwise_fwd_pd_t {
+ using cpu_eltwise_fwd_pd_t::cpu_eltwise_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", isa, ""),
+ jit_uni_eltwise_fwd_t<isa>);
+
+ status_t init();
+ };
+
+ jit_uni_eltwise_fwd_t(const pd_t *apd);
+ ~jit_uni_eltwise_fwd_t();
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ jit_uni_eltwise_kernel_f32 *kernel_;
+};
+
+template <cpu_isa_t isa>
+struct jit_uni_eltwise_bwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_eltwise_bwd_pd_t {
+ using cpu_eltwise_bwd_pd_t::cpu_eltwise_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", isa, ""),
+ jit_uni_eltwise_bwd_t<isa>);
+
+ status_t init();
+ };
+
+ jit_uni_eltwise_bwd_t(const pd_t *apd);
+ ~jit_uni_eltwise_bwd_t();
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ jit_uni_eltwise_kernel_f32 *kernel_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.cpp
new file mode 100644
index 0000000000..a3ca6273a0
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.cpp
@@ -0,0 +1,949 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "jit_uni_i8i8_pooling.hpp"
+
+#include <math.h>
+
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace Xbyak;
+
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::types;
+using namespace alg_kind;
+
+template <cpu_isa_t isa>
+struct jit_uni_i8i8_pooling_fwd_ker_t: public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_i8i8_pooling_fwd_ker_t)
+
+ struct call_params_t {
+ const char *src_i8;
+ const char *dst_i8;
+ size_t kw_range;
+ size_t kh_range;
+ float idivider;
+ };
+
+ using Vmm = typename cpu_isa_traits<isa>::Vmm;
+ Xmm xreg(int idx) const { return Xmm(idx); }
+ Ymm yreg(int idx) const { return Ymm(xreg(idx).getIdx()); }
+ Vmm vreg(int idx) const { return Vmm(xreg(idx).getIdx()); }
+
+ // In case of avx2 with data type i8 we need to use
+ // maskmovdqu instruction which has its destination hardcoded in rdi.
+ // Windows ABI: abi_param1 is rcx - nothing to do else
+ // Unix ABI: abi_param1 is rdi - copy it to rcx and use it as abi_param1
+ Reg64 reg_param = rcx; // Our "unified abi_param1"
+ Reg64 reg_ptr_src_i8 = r8;
+ Reg64 reg_ptr_dst_i8 = r9;
+ Reg64 reg_ptr_maskmovdqu_dst = rdi; // store destination - must be rdi
+
+ Reg64 ki = r10;
+ Reg64 kj = r11;
+ Reg64 reg_kw = r12;
+ Reg64 reg_kh = r13;
+ Reg64 c_iter = r14;
+
+ Reg64 aux_reg_src_h = rax;
+ Reg64 aux_reg_src_w = rbx;
+
+ Reg64 reg_tmp = rdx;
+
+ Reg64 reg_mask = r15;
+
+ Opmask k_cmp_mask = Opmask(7);
+
+ Opmask mask(int idx) {
+ return Opmask(6 - idx);
+ }
+
+ // ref to any of XYZ-regs via xreg/yreg/vreg functions
+ Xmm xmm_tmp = xreg(0); // temp to init vreg_tmp
+ Vmm vreg_tmp = vreg(0); // max pooling : holds minimum values for data_type
+ Vmm vreg_zeros = vreg(1);
+
+ // only in case of <isa> == avx2
+ Vmm vreg_mask = vreg(2); // full byte-mask
+ Xmm xreg_mask_lo = xreg(2); // low 128-bits part of byte-mask (alias for xmm part of vreg_mask)
+ Xmm xreg_mask_hi = xreg(3); // "max" - high 128-bits part of byte-mask (stored separately)
+ Xmm xreg_mask_q = xreg(3); // "avg" - 1/4 part of the mask for s8/u8 operations
+ Vmm vreg_mask_q = vreg(3); // "avg" - 1/4 part for non-zero tails
+
+ enum:int {vidx_base = isa == avx2 ? 4 : 2};
+ Vmm base_vr(int idx) const { return vreg(vidx_base + idx); }
+
+ size_t sizeof_src_dt() const { return data_type_size(jpp.src_dt); }
+ size_t sizeof_dst_dt() const { return data_type_size(jpp.dst_dt); }
+
+ /* max pooling */
+ Vmm vreg_src(int idx) const { return base_vr(idx); } // [0 .. ur_c-1]
+ Vmm vreg_dst(int idx) const { return base_vr(jpp.ur_c + idx); } // [ur_c .. 2*ur_c-1]
+
+ /* avg pooling */
+ // s32 used for processing of s8/u8 data
+ // thus we need to take into account ratio of sizes s32/i8 = 4
+ static constexpr data_type_t avg_proc_dt = data_type::s32;
+ enum:int {
+ s32_to_i8_ratio = sizeof(typename prec_traits<avg_proc_dt>::type)
+ / sizeof(typename prec_traits<data_type::u8>::type),
+ max_num_ll = s32_to_i8_ratio
+ };
+ Vmm vreg_src_s32(int jj, int ll) { return base_vr(3*max_num_ll*jj + ll + 0*max_num_ll); } // ll: 0..4 [0..3]
+ Vmm vreg_dst_s32(int jj, int ll) { return base_vr(3*max_num_ll*jj + ll + 1*max_num_ll); } // ll: 0..4 [4..7]
+ Vmm vreg_dst_f32(int jj, int ll) { return base_vr(3*max_num_ll*jj + ll + 2*max_num_ll); } // ll: 0..4 [8..11]
+
+ void (*ker_)(const call_params_t *);
+ jit_pool_conf_t jpp;
+
+ void init_tmp_reg();
+ void init_mask();
+
+ void load_vreg_mask_q(int ll) {};
+
+ void load_src_max_op(int jj, int ll, size_t offset, bool masked, uint64_t msk);
+ void load_src_avg_op(int jj, int ll, size_t offset, bool masked, uint64_t msk);
+ void load_src(int jj, int ll, int c_tail);
+
+ void store_dst_max_op(int jj, int ll, size_t offset, bool masked, uint64_t msk);
+ void store_dst_avg_op(int jj, int ll, size_t offset, bool masked, uint64_t msk);
+ void store_dst(int jj, int ll, int c_tail);
+
+ void compute_avg_step(int ur_c, int c_tail);
+ void compute_max_op(const int jj);
+ void compute_max_step(int ur_c, int c_tail);
+ void compute_step(int ur_c, int c_tail);
+
+ void compute_c_block();
+ void generate();
+
+ static status_t init_conf(jit_pool_conf_t &jpp, const pooling_pd_t *ppd);
+
+ jit_uni_i8i8_pooling_fwd_ker_t(const jit_pool_conf_t &jpp_)
+ : jpp(jpp_) {
+ generate();
+ ker_ = reinterpret_cast<decltype(ker_)>(const_cast<uint8_t*>(
+ getCode()));
+ }
+};
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx2>::load_vreg_mask_q(int ll) {
+
+ // extract ll-th part of mask (ll-th QWORD)
+ vpblendd(vreg_mask_q, vreg_zeros, vreg_mask, 0x3 << ll); // 0x3 - mask for 2 x DWORD
+
+ // Move mask from ll-th pos to 0-th pos
+ if (ll>0)
+ vpermq(vreg_mask_q, vreg_mask_q, ll);
+};
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx2>::load_src_max_op(int jj, int ll,
+ size_t offset, bool masked, uint64_t msk) {
+ using namespace data_type;
+
+ if (masked) {
+ if (jpp.src_dt == s32) {
+ vpblendd(vreg_src(jj), vreg_tmp, ptr[aux_reg_src_w + offset], static_cast<uint8_t>(msk));
+ } else {
+ vpblendvb(vreg_src(jj), vreg_tmp, ptr[aux_reg_src_w + offset], vreg_mask);
+ }
+ } else
+ vmovups(vreg_src(jj), ptr[aux_reg_src_w + offset]);
+};
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx512_core>::load_src_max_op(int jj, int ll,
+ size_t offset, bool masked, uint64_t msk) {
+ using namespace data_type;
+
+ if (masked) {
+ if (jpp.src_dt == s32)
+ vmovups(vreg_src(jj) | mask(0), ptr[aux_reg_src_w + offset]);
+ else
+ vmovdqu8(vreg_src(jj) | mask(0), ptr[aux_reg_src_w + offset]);
+ } else
+ vmovups(vreg_src(jj), ptr[aux_reg_src_w + offset]);
+};
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx2>::load_src_avg_op(int jj, int ll,
+ size_t offset, bool masked, uint64_t msk) {
+ using namespace data_type;
+
+ // Don't generate useless code
+ if (masked && !msk)
+ return;
+
+ auto load_i8 = [&](bool is_signed, const Vmm& vr_src) {
+
+ // Need to use mask of tail?
+ if (masked) {
+
+ // load ll-th part of mask into vreg_mask_q
+ load_vreg_mask_q(ll);
+
+ // Load by mask from mem into register vr_src
+ vpblendvb(vr_src, vreg_zeros, ptr[aux_reg_src_w + offset], vreg_mask_q);
+
+ // Conversion s8/u8 -> s32
+ if (is_signed)
+ vpmovsxbd(vr_src, vr_src);
+ else
+ vpmovzxbd(vr_src, vr_src);
+ } else {
+
+ // Load from mem into vr_src with conversion
+ if (is_signed)
+ vpmovsxbd(vr_src, ptr[aux_reg_src_w + offset]);
+ else
+ vpmovzxbd(vr_src, ptr[aux_reg_src_w + offset]);
+ }
+ };
+
+ switch (jpp.src_dt) {
+ case s32:
+ if (masked)
+ vpblendd(vreg_src_s32(jj, ll), vreg_zeros, ptr[aux_reg_src_w + offset],
+ static_cast<uint8_t>(msk));
+ else
+ vmovups(vreg_src_s32(jj, ll), ptr[aux_reg_src_w + offset]);
+ break;
+ case s8:
+ load_i8(true, vreg_src_s32(jj, ll));
+ break;
+ case u8:
+ load_i8(false, vreg_src_s32(jj, ll));
+ break;
+ default: assert(!"unsupported src data type");
+ }
+};
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx512_core>::load_src_avg_op(int jj, int ll,
+ size_t offset, bool masked, uint64_t msk) {
+ using namespace data_type;
+
+ // Don't generate useless code
+ if (masked && !msk)
+ return;
+
+ const Vmm& vr_src = masked ?
+ vreg_src_s32(jj, ll) | mask(ll) :
+ vreg_src_s32(jj, ll);
+
+ switch (jpp.src_dt) {
+ case s32:
+ vmovups(vr_src, ptr[aux_reg_src_w + offset]);
+ break;
+ case s8:
+ vpmovsxbd(vr_src, ptr[aux_reg_src_w + offset]);
+ break;
+ case u8:
+ vpmovzxbd(vr_src, ptr[aux_reg_src_w + offset]);
+ break;
+ default: assert(!"unsupported src data type");
+ }
+};
+
+template <cpu_isa_t isa>
+void jit_uni_i8i8_pooling_fwd_ker_t<isa>::load_src(int jj, int ll, int c_tail) {
+ using namespace data_type;
+
+ int c_block = jpp.c_block;
+ int ur_c = jpp.ur_c;
+
+ switch (jpp.alg) {
+ case pooling_max: {
+ auto offset = jj*c_block*sizeof_src_dt();
+ bool masked = jj == ur_c - 1 && c_tail;
+ load_src_max_op(jj, ll, offset, masked, jpp.tail[0]);
+ break;
+ }
+ case pooling_avg_include_padding:
+ case pooling_avg_exclude_padding: {
+ auto offset = (ll*(c_block/max_num_ll) + jj*c_block)*sizeof_src_dt();
+ bool masked = jj == ur_c - 1 && c_tail;
+ load_src_avg_op(jj, ll, offset, masked, jpp.tail[ll]);
+ break;
+ }
+ default: assert(!"unsupported algorithm");
+ }
+}
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx2>::store_dst_max_op(int jj, int ll,
+ size_t offset, bool masked, uint64_t msk) {
+ using namespace data_type;
+
+ int c_block = jpp.c_block;
+
+ if (masked) {
+ switch (jpp.src_dt) {
+ case s32:
+ vpmaskmovd(ptr[reg_ptr_dst_i8 + offset], vreg_mask, vreg_dst(jj));
+ break;
+ case s8:
+ case u8: {
+ // Store low half by mask (bytes 0...15)
+ lea(reg_ptr_maskmovdqu_dst, ptr[reg_ptr_dst_i8 + offset]);
+ maskmovdqu(vreg_dst(jj), xreg_mask_lo);
+
+ // Do we need to store high half (bytes 16...31) ?
+ const uint64_t low_mask = (1ULL << (c_block/2))-1;
+ if (msk & ~low_mask) {
+ vextracti128(Xmm(vreg_dst(jj).getIdx()), vreg_dst(jj), 1);
+ add(reg_ptr_maskmovdqu_dst, c_block / 2);
+ maskmovdqu(vreg_dst(jj), xreg_mask_hi);
+ }
+ } break;
+ default: assert(!"unsupported src data type");
+ }
+ } else
+ vmovups(ptr[reg_ptr_dst_i8 + offset], vreg_dst(jj));
+}
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx512_core>::store_dst_max_op(int jj, int ll,
+ size_t offset, bool masked, uint64_t msk) {
+ using namespace data_type;
+
+ if (masked) {
+ switch (jpp.src_dt) {
+ case s32:
+ vmovups(ptr[reg_ptr_dst_i8 + offset], vreg_dst(jj) | mask(0));
+ break;
+ case s8:
+ case u8:
+ vmovdqu8(ptr[reg_ptr_dst_i8 + offset], vreg_dst(jj) | mask(0));
+ break;
+ default: assert(!"unsupported src data type");
+ }
+ } else
+ vmovups(ptr[reg_ptr_dst_i8 + offset], vreg_dst(jj));
+}
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx2>::store_dst_avg_op(int jj, int ll,
+ size_t offset, bool masked, uint64_t msk){
+ using namespace data_type;
+
+ // Don't generate useless code
+ if (masked && !msk)
+ return;
+
+ auto s32_to_i8 = [&](bool is_signed, const Vmm& vr_dst) {
+
+ // conversion: s32 -> s16/u16 : {8 x s32}{8 x 0} -> {16 x s16/u16}
+ // Result QWORDs (qw0, qw1) permuted: {qw0, 0, qw1, 0}
+ if (is_signed)
+ vpackssdw(vr_dst, vr_dst, vreg_zeros);
+ else
+ vpackusdw(vr_dst, vr_dst, vreg_zeros);
+
+ // Permute qwords to restore original order
+ // {qw0, 0, qw1, 0} -> {qw0, qw1, 0, 0}
+ vpermq(vr_dst, vr_dst, 0x58);
+
+ // conversion: s16/u16 -> s8/u8 : {16 x s16/u16}{16 x 0} -> {32 x s8/u8}
+ // Target QWORD qw = {8 x s8/u8} has proper position: {qw, xx, xx, xx}
+ if (is_signed)
+ vpacksswb(vr_dst, vr_dst, vreg_zeros);
+ else
+ vpackuswb(vr_dst, vr_dst, vreg_zeros);
+
+ };
+
+ auto store_i8 = [&](bool is_signed, bool is_masked, const Vmm& vr_dst) {
+
+ // Conversion s32 -> s8/u8
+ s32_to_i8(is_signed, vr_dst);
+
+ // Need to use mask of tail?
+ if (is_masked) {
+ // load ll-th part of mask into vreg_mask_q
+ load_vreg_mask_q(ll);
+ }
+
+ // store 8 bytes
+ lea(reg_ptr_maskmovdqu_dst, ptr[reg_ptr_dst_i8 + offset]);
+ maskmovdqu(vr_dst, xreg_mask_q);
+ };
+
+ switch (jpp.dst_dt) {
+ case s32:
+ if (masked) {
+ vpmaskmovd(ptr[reg_ptr_dst_i8 + offset], vreg_mask, vreg_dst_s32(jj, ll));
+ } else
+ vmovups(ptr[reg_ptr_dst_i8 + offset], vreg_dst_s32(jj, ll));
+ break;
+ case s8:
+ store_i8(true, masked, vreg_dst_s32(jj, ll));
+ break;
+ case u8:
+ store_i8(false, masked, vreg_dst_s32(jj, ll));
+ break;
+ default: assert(!"unsuppotred dst data_type");
+ }
+}
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx512_core>::store_dst_avg_op(int jj, int ll,
+ size_t offset, bool masked, uint64_t msk) {
+ using namespace data_type;
+
+ // Don't generate useless code
+ if (masked && !msk)
+ return;
+
+ const Vmm& vr_dst = masked ?
+ vreg_dst_s32(jj, ll) | mask(ll) :
+ vreg_dst_s32(jj, ll);
+
+ switch (jpp.dst_dt) {
+ case s32:
+ vmovups(ptr[reg_ptr_dst_i8 + offset], vr_dst);
+ break;
+ case s8:
+ vpmovdb(ptr[reg_ptr_dst_i8 + offset], vr_dst);
+ break;
+ case u8:
+ vpmovusdb(ptr[reg_ptr_dst_i8 + offset], vr_dst);
+ break;
+ default: assert(!"unsupported dst data_type");
+ }
+}
+
+
+template <cpu_isa_t isa>
+void jit_uni_i8i8_pooling_fwd_ker_t<isa>::store_dst(int jj, int ll,
+ int c_tail) {
+ using namespace data_type;
+
+ int c_block = jpp.c_block;
+ int ur_c = jpp.ur_c;
+
+ switch(jpp.alg) {
+ case pooling_max: {
+ auto offset = jj*c_block*sizeof_dst_dt();
+ bool masked = jj == ur_c - 1 && c_tail;
+ store_dst_max_op(jj, ll, offset, masked, jpp.tail[ll]);
+ break;
+ }
+ case pooling_avg_include_padding:
+ case pooling_avg_exclude_padding: {
+ auto offset = (ll*(c_block/max_num_ll) + jj*c_block)*sizeof_dst_dt();
+ bool masked = jj == ur_c - 1 && c_tail;
+ store_dst_avg_op(jj, ll, offset, masked, jpp.tail[ll]);
+ break;
+ }
+ default: assert(!"unsupported pooling algorithm");
+ }
+}
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx2>::compute_max_op(const int jj)
+{
+ using namespace data_type;
+ switch (jpp.src_dt) {
+ case s32:
+ vpmaxsd(vreg_dst(jj), vreg_dst(jj), vreg_src(jj));
+ break;
+ case s8:
+ vpmaxsb(vreg_dst(jj), vreg_dst(jj), vreg_src(jj));
+ break;
+ case u8:
+ vpmaxub(vreg_dst(jj), vreg_dst(jj), vreg_src(jj));
+ break;
+ default: assert(!"unsupported src data type");
+ }
+}
+
+template <>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx512_core>::compute_max_op(const int jj)
+{
+ using namespace data_type;
+
+ // Compare
+ switch (jpp.src_dt) {
+ case s32:
+ vpcmpd(k_cmp_mask, vreg_dst(jj), vreg_src(jj), _cmp_lt_os);
+ break;
+ case s8:
+ vpcmpb(k_cmp_mask, vreg_dst(jj), vreg_src(jj), _cmp_lt_os);
+ break;
+ case u8:
+ vpcmpub(k_cmp_mask, vreg_dst(jj), vreg_src(jj), _cmp_lt_os);
+ break;
+ default: assert(!"unsupported src data type");
+ }
+
+ // move max values into vreg_dst
+ if (jpp.src_dt == s32)
+ vpblendmd(vreg_dst(jj) | k_cmp_mask, vreg_dst(jj), vreg_src(jj));
+ else
+ vpblendmb(vreg_dst(jj) | k_cmp_mask, vreg_dst(jj), vreg_src(jj));
+}
+
+
+template <cpu_isa_t isa>
+void jit_uni_i8i8_pooling_fwd_ker_t<isa>::compute_max_step(int ur_c, int c_tail)
+{
+ Label l_kw, l_kh;
+
+ int iw = jpp.iw;
+ int c = jpp.c;
+
+ for (int jj = 0; jj < ur_c; jj++)
+ vmovups(vreg_dst(jj), vreg_tmp);
+
+ mov(aux_reg_src_h, reg_ptr_src_i8);
+
+ xor_(kj, kj);
+ L(l_kh);
+ {
+ mov(aux_reg_src_w, aux_reg_src_h);
+ xor_(ki, ki);
+ L(l_kw);
+ {
+ for (int jj = 0; jj < ur_c; jj++) {
+ load_src(jj, 0, c_tail);
+ compute_max_op(jj);
+ }
+ add(aux_reg_src_w, c * sizeof_src_dt());
+ inc(ki);
+ cmp(ki, reg_kw);
+ jl(l_kw, T_NEAR);
+ }
+ add(aux_reg_src_h, iw * c * sizeof_src_dt());
+ inc(kj);
+ cmp(kj, reg_kh);
+ jl(l_kh, T_NEAR);
+ }
+
+ for (int jj = 0; jj < ur_c; jj++)
+ store_dst(jj, 0, c_tail);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_i8i8_pooling_fwd_ker_t<isa>::compute_avg_step(int ur_c, int c_tail)
+{
+ using namespace data_type;
+
+ Label l_kw, l_kh;
+
+ int iw = jpp.iw;
+ int c = jpp.c;
+
+ const int num_ll = data_type_size(avg_proc_dt)/data_type_size(jpp.src_dt);
+
+ for (int jj = 0; jj < ur_c; jj++) {
+ for (int ll = 0; ll < num_ll; ll++) {
+ bool masked = jj == ur_c - 1 && c_tail;
+ size_t msk = jpp.tail[ll];
+ if (!(masked && !msk)) {
+ uni_vpxor(vreg_src_s32(jj, ll), vreg_src_s32(jj, ll), vreg_src_s32(jj, ll));
+ uni_vpxor(vreg_dst_s32(jj, ll), vreg_dst_s32(jj, ll), vreg_dst_s32(jj, ll));
+ }
+ }
+ }
+
+ mov(aux_reg_src_h, reg_ptr_src_i8);
+
+ xor_(kj, kj);
+ L(l_kh);
+ {
+ mov(aux_reg_src_w, aux_reg_src_h);
+ xor_(ki, ki);
+ L(l_kw);
+ {
+ for (int jj = 0; jj < ur_c; jj++) {
+ for (int ll = 0; ll < num_ll; ll++) {
+ bool masked = jj == ur_c - 1 && c_tail;
+ size_t msk = jpp.tail[ll];
+ if (!(masked && !msk)) {
+ load_src(jj, ll, c_tail);
+ vpaddd(vreg_dst_s32(jj, ll), vreg_dst_s32(jj, ll),
+ vreg_src_s32(jj, ll));
+ }
+ }
+ }
+ add(aux_reg_src_w, c * sizeof_src_dt());
+ inc(ki);
+ cmp(ki, reg_kw);
+ jl(l_kw, T_NEAR);
+ }
+ add(aux_reg_src_h, iw * c * sizeof_src_dt());
+ inc(kj);
+ cmp(kj, reg_kh);
+ jl(l_kh, T_NEAR);
+ }
+
+ for (int jj = 0; jj < ur_c; jj++) {
+ for (int ll = 0; ll < num_ll; ll++) {
+ bool masked = jj == ur_c - 1 && c_tail;
+ size_t msk = jpp.tail[ll];
+ if (!(masked && !msk)) {
+ vcvtdq2ps(vreg_dst_f32(jj, ll), vreg_dst_s32(jj, ll));
+ vfmadd132ps(vreg_dst_f32(jj, ll), vreg_zeros, vreg_tmp);
+ vcvtps2dq(vreg_dst_s32(jj, ll), vreg_dst_f32(jj, ll));
+ store_dst(jj, ll, c_tail);
+ }
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_i8i8_pooling_fwd_ker_t<isa>::compute_step(int ur_c, int c_tail) {
+ switch (jpp.alg) {
+ case pooling_max:
+ compute_max_step(ur_c, c_tail); break;
+ case pooling_avg_include_padding:
+ case pooling_avg_exclude_padding:
+ compute_avg_step(ur_c, c_tail); break;
+ default: assert(!"unsupported pooling algorithm");
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_i8i8_pooling_fwd_ker_t<isa>::compute_c_block(){
+ Label l_main_loop;
+
+ int nb_c = jpp.nb_c;
+ int c_block = jpp.c_block;
+ int ur_c = jpp.ur_c;
+ int ur_c_tail = jpp.ur_c_tail;
+ int c_steps = nb_c / ur_c;
+ int c_tail = jpp.c_tail;
+
+ xor_(c_iter, c_iter);
+ if (c_steps > 0) {
+ L(l_main_loop); {
+ compute_step(ur_c, 0);
+ add(reg_ptr_src_i8, ur_c*c_block*sizeof_src_dt());
+ add(reg_ptr_dst_i8, ur_c*c_block*sizeof_dst_dt());
+ inc(c_iter);
+ cmp(c_iter, c_steps);
+ jl(l_main_loop, T_NEAR);
+ }
+ }
+
+ if (ur_c_tail != 0) {
+ compute_step(ur_c_tail, c_tail);
+ }
+}
+
+template<>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx2>::init_mask() {
+ using namespace data_type;
+ using cpu_isa = cpu_isa_traits<avx2>;
+
+ // AVX2 mask initialization: mask stored in Ymm-regs
+ auto init = [&](uint64_t bit_mask, bool init_mask_q) {
+ const size_t QW_PER_VREG = cpu_isa::vlen / sizeof(uint64_t);
+
+ uint64_t vmask[QW_PER_VREG];
+ for (size_t i = 0; i < QW_PER_VREG; i++){
+
+ uint64_t qw_vmask=0ULL;
+ const size_t DBITS = 8*sizeof_src_dt();
+ const uint64_t VMSK = 1ULL << (DBITS-1);
+ const size_t D_PER_QW = (8*sizeof(qw_vmask))/DBITS;
+ for (size_t j = 0; j < D_PER_QW; j++) {
+ if (bit_mask & 1)
+ qw_vmask |= VMSK << DBITS * j;
+ bit_mask >>= 1;
+ }
+ vmask[i] = qw_vmask;
+ }
+
+ // Put QWORDS with target mask into xmm regs
+ const int xdst_i[QW_PER_VREG] = {
+ xreg_mask_lo.getIdx(),
+ xreg_mask_lo.getIdx(),
+ xreg_mask_hi.getIdx(),
+ xreg_mask_hi.getIdx()
+ };
+ const int xsrc_i[QW_PER_VREG] = {
+ vreg_zeros.getIdx(), // 0-th qword insert in zeros -> {qw0, 0}
+ xreg_mask_lo.getIdx(), // 1-st and 0-th merge -> {qw0,qw1}
+ vreg_zeros.getIdx(),
+ xreg_mask_hi.getIdx()
+ };
+ const uint8 qw_dst_idx[QW_PER_VREG] = {0, 1, 0, 1}; // qword index in 128-bit xreg
+
+ for (size_t i = 0; i < QW_PER_VREG; i++) {
+ mov(reg_mask, vmask[i]);
+ vpinsrq(Xmm(xdst_i[i]), Xmm(xsrc_i[i]), reg_mask, qw_dst_idx[i]);
+ }
+
+ // Merge Low (xreg_mask_lo alias for vreg_mask.xreg)
+ // and High (xreg_mask_hi) into full vreg_mask
+ // vreg_mask -> {xreg_mask_hi, vreg_mask.xreg}
+ vinserti128(vreg_mask, vreg_mask, xreg_mask_hi, 1);
+
+ // Keep only low qword of mask in xreg_mask_q
+ if (init_mask_q) {
+ mov(reg_mask, vmask[0]);
+ vpinsrq(xreg_mask_q, Xmm(vreg_zeros.getIdx()), reg_mask, 0);
+ }
+ };
+
+ uint64_t tail_mask = (1ULL << jpp.c_tail) - 1;
+ switch (jpp.alg) {
+ case pooling_max:
+ // For "max" we need mask only in case of non-zero tail
+ if (tail_mask)
+ init(tail_mask, false);
+ break;
+ case pooling_avg_include_padding:
+ case pooling_avg_exclude_padding:
+ // For "avg" we need mask:
+ // - s32 - in case of the non-zero tail
+ // - s8/u8 - irrespective of the tail
+ switch (jpp.src_dt) {
+ case s32:
+ if (tail_mask)
+ init(tail_mask, false);
+ break;
+ case s8:
+ case u8:
+ init(tail_mask ? tail_mask : ~0ULL, tail_mask == 0);
+ break;
+ default: assert(!"unsupported src data type");
+ }
+ break;
+ default: assert(!"unsupported pooling algorithm");
+ }
+}
+
+template<>
+void jit_uni_i8i8_pooling_fwd_ker_t<avx512_core>::init_mask() {
+
+ for (int ll = 0; ll < max_num_ll; ll++) {
+ mov(reg_mask, jpp.tail[ll]);
+ kmovq(mask(ll), reg_mask);
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_i8i8_pooling_fwd_ker_t<isa>::init_tmp_reg() {
+ using namespace data_type;
+
+ switch (jpp.alg) {
+ case pooling_avg_include_padding:
+ case pooling_avg_exclude_padding:
+ mov(reg_tmp, ptr[reg_param + offsetof(call_params_t, idivider)]);
+ movq(xmm_tmp, reg_tmp);
+ vpbroadcastd(vreg_tmp, xmm_tmp);
+ break;
+ case pooling_max:
+ switch (jpp.src_dt) {
+ case s32:
+ mov(reg_tmp, nstl::numeric_limits<int32_t>::lowest());
+ break;
+ case s8:
+ mov(reg_tmp, nstl::numeric_limits<int8_t>::lowest());
+ break;
+ case u8:
+ mov(reg_tmp, nstl::numeric_limits<uint8_t>::lowest());
+ break;
+ default: assert(!"unsupported src data_type");
+ }
+
+ movq(xmm_tmp, reg_tmp);
+ if (jpp.src_dt == s32)
+ vpbroadcastd(vreg_tmp, xmm_tmp);
+ else
+ vpbroadcastb(vreg_tmp, xmm_tmp);
+ break;
+ default: assert(!"unsupported pooling algorithm");
+ }
+
+}
+
+template <cpu_isa_t isa>
+void jit_uni_i8i8_pooling_fwd_ker_t<isa>::generate() {
+ preamble();
+
+#if !defined(_WIN32)
+ // Always use rcx as abi_param1 -
+ // see the note about maskmovdqu near reg_param.
+ mov(rcx, rdi);
+#endif
+
+# define READ_PARAM(reg, field) \
+ mov(reg, ptr[reg_param + offsetof(call_params_t, field)])
+ READ_PARAM(reg_ptr_src_i8, src_i8);
+ READ_PARAM(reg_ptr_dst_i8, dst_i8);
+ READ_PARAM(reg_kw, kw_range);
+ READ_PARAM(reg_kh, kh_range);
+
+# undef READ_PARAM
+
+ uni_vpxor(vreg_zeros, vreg_zeros, vreg_zeros);
+
+ init_mask();
+
+ init_tmp_reg();
+
+ compute_c_block();
+
+ postamble();
+}
+
+template <cpu_isa_t isa>
+status_t jit_uni_i8i8_pooling_fwd_ker_t<isa>::init_conf(jit_pool_conf_t &jpp,
+ const pooling_pd_t *ppd) {
+ if (!mayiuse(isa))
+ return status::unimplemented;
+
+ const auto &pd = *ppd->desc();
+ const memory_desc_wrapper src_d(ppd->src_md());
+ const memory_desc_wrapper dst_d(ppd->dst_md());
+
+ jpp.mb = src_d.dims()[0];
+ jpp.c = src_d.dims()[1];
+ jpp.ih = src_d.dims()[2];
+ jpp.iw = src_d.dims()[3];
+ jpp.oh = dst_d.dims()[2];
+ jpp.ow = dst_d.dims()[3];
+
+ jpp.stride_h = pd.strides[0];
+ jpp.stride_w = pd.strides[1];
+ jpp.kh = pd.kernel[0];
+ jpp.kw = pd.kernel[1];
+
+ jpp.t_pad = pd.padding[0][0];
+ jpp.l_pad = pd.padding[0][1];
+
+ jpp.alg = pd.alg_kind;
+
+ jpp.src_dt = pd.src_desc.data_type;
+ jpp.dst_dt = pd.dst_desc.data_type;
+
+ // data_type items per one vreg on the <isa>
+ // isa == avx2 : 32 bytes -> 32 for s8/u8, 8 for s32
+ // isa == avx512* : 64 bytes -> 64 for s8/u8, 16 for s32
+ int simd_w = cpu_isa_traits<isa>::vlen / data_type_size(jpp.src_dt);
+
+ jpp.c_block = simd_w;
+ jpp.c_tail = jpp.c % jpp.c_block;
+ jpp.nb_c = jpp.c / jpp.c_block;
+ jpp.ur_c = 1;
+ jpp.ur_c_tail = jpp.nb_c - (jpp.nb_c / jpp.ur_c)*jpp.ur_c +
+ (jpp.c_tail != 0);
+
+ size_t tail_mask = (1ULL << jpp.c_tail) - 1;
+
+ switch (jpp.alg) {
+ case pooling_max:
+ jpp.tail[0] = tail_mask;
+ jpp.tail[1] = 0;
+ jpp.tail[2] = 0;
+ jpp.tail[3] = 0;
+ break;
+ case pooling_avg_include_padding:
+ case pooling_avg_exclude_padding: {
+ // avg_proc_dt (s32) defines granularity (because u8/s8 processed as s32)
+ // avx2 : 8, avx512 : 16
+ const size_t msk_gran = cpu_isa_traits<isa>::vlen / data_type_size(avg_proc_dt);
+ const size_t msk_msk = (1ULL << msk_gran) - 1;
+ size_t m = tail_mask;
+ for (size_t ll = 0; ll < max_num_ll; ll++) {
+ jpp.tail[ll] = m & msk_msk;
+ m = m >> msk_gran;
+ }
+ break;
+ }
+ default: return status::unimplemented;
+ }
+
+ return status::success;
+}
+
+template <cpu_isa_t isa>
+status_t jit_uni_i8i8_pooling_fwd_t<isa>::pd_t::jit_conf() {
+ return jit_uni_i8i8_pooling_fwd_ker_t<isa>::init_conf(jpp_, this);
+}
+
+template <cpu_isa_t isa>
+jit_uni_i8i8_pooling_fwd_t<isa>::
+jit_uni_i8i8_pooling_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd), ker_(nullptr)
+{ ker_ = new jit_uni_i8i8_pooling_fwd_ker_t<isa>(pd()->jpp_); }
+
+template <cpu_isa_t isa>
+jit_uni_i8i8_pooling_fwd_t<isa>::
+~jit_uni_i8i8_pooling_fwd_t() { delete ker_; }
+
+template <cpu_isa_t isa>
+void jit_uni_i8i8_pooling_fwd_t<isa>::execute_forward(
+ const exec_ctx_t &ctx) const {
+ auto src_i8 = CTX_IN_MEM(const char *, MKLDNN_ARG_SRC);
+ auto dst_i8 = CTX_OUT_MEM(char *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+
+ const auto &jpp = pd()->jpp_;
+
+ parallel_nd(jpp.mb, jpp.oh, jpp.ow,
+ [&](int n, int oh, int ow) {
+ const int ih = nstl::max(oh*jpp.stride_h - jpp.t_pad, 0);
+ const int iw = nstl::max(ow*jpp.stride_w - jpp.l_pad, 0);
+
+ const int kh_start = nstl::max(0, jpp.t_pad - oh * jpp.stride_h);
+ const int kh_end = nstl::min(jpp.kh,
+ jpp.ih + jpp.t_pad - oh * jpp.stride_h);
+ const int kw_start = nstl::max(0, jpp.l_pad - ow * jpp.stride_w);
+ const int kw_end = nstl::min(jpp.kw,
+ jpp.iw + jpp.l_pad - ow * jpp.stride_w);
+
+ auto p = typename jit_uni_i8i8_pooling_fwd_ker_t<isa>::call_params_t();
+ p.src_i8 = &src_i8[
+ src_d.blk_off(n, 0, ih, iw) * src_d.data_type_size()];
+ p.dst_i8 = &dst_i8[
+ dst_d.blk_off(n, 0, oh, ow) * dst_d.data_type_size()];
+ p.kw_range = (size_t)(kw_end - kw_start);
+ p.kh_range = (size_t)(kh_end - kh_start);
+ p.idivider = 1.0f / ((jpp.alg == pooling_avg_exclude_padding) ?
+ p.kh_range*p.kw_range : jpp.kw*jpp.kh);
+
+ ker_->ker_(&p);
+ });
+}
+
+// Explicit instantiation only for supported <isa> values.
+//
+template struct jit_uni_i8i8_pooling_fwd_ker_t<avx512_core>;
+template struct jit_uni_i8i8_pooling_fwd_t<avx512_core>;
+
+template struct jit_uni_i8i8_pooling_fwd_ker_t<avx2>;
+template struct jit_uni_i8i8_pooling_fwd_t<avx2>;
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.hpp
new file mode 100644
index 0000000000..d757679df5
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_i8i8_pooling.hpp
@@ -0,0 +1,89 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_UNI_I8I8_POOLING_HPP
+#define CPU_JIT_UNI_I8I8_POOLING_HPP
+
+#include "c_types_map.hpp"
+
+#include "cpu_pooling_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "cpu_isa_traits.hpp"
+#include "jit_primitive_conf.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <cpu_isa_t isa>
+struct jit_uni_i8i8_pooling_fwd_ker_t;
+
+template <cpu_isa_t isa>
+struct jit_uni_i8i8_pooling_fwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_pooling_fwd_pd_t {
+ using cpu_pooling_fwd_pd_t::cpu_pooling_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", isa, ""),
+ jit_uni_i8i8_pooling_fwd_t<isa>);
+
+ status_t init() {
+ bool ok = true
+ && mayiuse(isa)
+ && ndims() == 4
+ && set_default_params() == status::success
+ && desc()->prop_kind == prop_kind::forward_inference
+ && utils::one_of(desc()->alg_kind, alg_kind::pooling_max,
+ alg_kind::pooling_avg_include_padding,
+ alg_kind::pooling_avg_exclude_padding)
+ && utils::one_of(src_md()->data_type, data_type::s32,
+ data_type::s8, data_type::u8)
+ && src_md()->data_type == dst_md()->data_type
+ && attr()->has_default_values()
+ && memory_desc_matches_tag(*src_md(), format_tag::nhwc)
+ && memory_desc_matches_tag(*dst_md(), format_tag::nhwc);
+ if (!ok) return status::unimplemented;
+
+ return jit_conf();
+ }
+
+ jit_pool_conf_t jpp_;
+
+ protected:
+ status_t jit_conf();
+ };
+
+ jit_uni_i8i8_pooling_fwd_t(const pd_t *apd);
+ ~jit_uni_i8i8_pooling_fwd_t();
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_uni_i8i8_pooling_fwd_ker_t<isa> *ker_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.cpp
new file mode 100644
index 0000000000..2c5a8e8973
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.cpp
@@ -0,0 +1,305 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_uni_lrn_kernel_f32.hpp"
+#include "jit_uni_lrn.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::utils;
+
+template <cpu_isa_t isa>
+jit_uni_lrn_fwd_t<isa>::jit_uni_lrn_fwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd), ker_(nullptr)
+ , ker_first_(nullptr), ker_last_(nullptr)
+{
+ using namespace alg_kind;
+
+ const int C = pd()->C();
+ const int H = pd()->H();
+ const int W = pd()->W();
+ const int ls = pd()->desc()->local_size;
+ float A = pd()->desc()->lrn_alpha / ls;
+ float K = pd()->desc()->lrn_k;
+
+ auto pk = pd()->desc()->prop_kind;
+ auto ak = pd()->desc()->alg_kind;
+ auto dat_tag = pd()->dat_tag_;
+
+ if (dat_tag == nChw8c && ls == 5 && ak == lrn_across_channels) {
+ ker_ = new jit_uni_lrn_fwd_kernel_f32<isa>(
+ nchw8c_across(H, W, 0), A, K, pk);
+ ker_first_ = new jit_uni_lrn_fwd_kernel_f32<isa>(
+ nchw8c_across(H, W, -1), A, K, pk);
+ ker_last_ = new jit_uni_lrn_fwd_kernel_f32<isa>(
+ nchw8c_across(H, W, +1), A, K, pk);
+ } else if (dat_tag == nChw8c && ak == lrn_within_channel) {
+ /* within channel, local_size (x) local_size */
+ A /= ls; /* XXX: why? */
+ ker_ = new jit_uni_lrn_fwd_kernel_f32<isa>(
+ nchw8c_within(H, W, ls), A, K, pk);
+ } else if (dat_tag == nchw && ls == 5 && ak == lrn_across_channels) {
+ ker_ = new jit_uni_lrn_fwd_kernel_f32<isa>(
+ nchw_across(C, H*W, 0), A, K, pk);
+ int remind = (H*W) % VECTOR_LENGTH;
+ if (remind != 0) {
+ ker_last_ = new jit_uni_lrn_fwd_kernel_f32<isa>(
+ nchw_across(C, H*W, remind), A, K, pk);
+ }
+ } else if (true /* XXX: why */) {
+ ker_ = new jit_uni_lrn_fwd_kernel_f32<isa>(nhwc_across(C), A, K, pk);
+ }
+}
+
+template <cpu_isa_t isa>
+jit_uni_lrn_fwd_t<isa>::~jit_uni_lrn_fwd_t()
+{ delete ker_; delete ker_first_; delete ker_last_; }
+
+template <cpu_isa_t isa>
+void jit_uni_lrn_fwd_t<isa>::execute_forward(const exec_ctx_t &ctx) const {
+ using namespace alg_kind;
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+ auto ws = CTX_OUT_MEM(data_t *, MKLDNN_ARG_WORKSPACE);
+
+ const int N = pd()->MB();
+ const int C = pd()->C();
+ const int HW = pd()->H() * pd()->W();
+ const int ls = pd()->desc()->local_size;
+
+ auto ak = pd()->desc()->alg_kind;
+ auto dat_tag = pd()->dat_tag_;
+
+ if (dat_tag == nChw8c && ls == 5 && ak == lrn_across_channels) {
+ parallel_nd(N, C / VECTOR_LENGTH, [&](int n, int c8) {
+ jit_args_fwd_t args;
+ args.src = &src[n*HW*C + c8 * HW * VECTOR_LENGTH];
+ args.dst = &dst[n*HW*C + c8 * HW * VECTOR_LENGTH];
+ args.scratch = &ws[n*HW*C + c8 * HW * VECTOR_LENGTH];
+ if (c8 == 0)
+ (*ker_first_)(&args);
+ else if (c8 == C / VECTOR_LENGTH - 1)
+ (*ker_last_)(&args);
+ else
+ (*ker_)(&args);
+ });
+ }
+ else if (dat_tag == nChw8c && ak == lrn_within_channel) {
+ parallel_nd(N, C / VECTOR_LENGTH, [&](int n, int c8) {
+ jit_args_fwd_t args;
+ args.src = &src[n*HW*C + c8 * HW * VECTOR_LENGTH];
+ args.dst = &dst[n*HW*C + c8 * HW * VECTOR_LENGTH];
+ args.scratch = &ws[n*HW*C + c8 * HW * VECTOR_LENGTH];
+ (*ker_)(&args);
+ });
+ }
+ else if (dat_tag == nchw && ls == 5 && ak == lrn_across_channels) {
+ parallel_nd(N, (HW + VECTOR_LENGTH - 1) / VECTOR_LENGTH,
+ [&](int n, int hw8) {
+ jit_args_fwd_t args;
+ args.src = &src[n*HW*C + hw8 * VECTOR_LENGTH];
+ args.dst = &dst[n*HW*C + hw8 * VECTOR_LENGTH];
+ args.scratch = &ws[n*HW*C + hw8 * VECTOR_LENGTH];
+ if ((hw8 + 1)*VECTOR_LENGTH > HW)
+ (*ker_last_)(&args);
+ else
+ (*ker_)(&args);
+ });
+ }
+ else { // nhwc
+ parallel_nd(N, HW, [&](int n, int hw) {
+ jit_args_fwd_t args;
+ args.src = &src[n*HW*C + hw * C];
+ args.dst = &dst[n*HW*C + hw * C];
+ args.scratch = &ws[n*HW*C + hw * C];
+ (*ker_)(&args);
+ });
+ }
+}
+
+template <cpu_isa_t isa>
+status_t jit_uni_lrn_fwd_t<isa>::pd_t::init() {
+ using namespace prop_kind;
+ using namespace alg_kind;
+
+ const memory_desc_wrapper data_d(src_md());
+ bool ok = true
+ && mayiuse(isa)
+ && is_fwd()
+ && everyone_is(data_type::f32, data_d.data_type())
+ && !has_zero_dim_memory()
+ && data_d.ndims() == 4
+ && data_d.dims()[1] % VECTOR_LENGTH == 0
+ && data_d.dims()[1] >= 2 * VECTOR_LENGTH
+ && desc()->lrn_beta == 0.75
+ && attr()->has_default_values();
+ if (!ok) return unimplemented;
+
+ if (desc_.prop_kind == forward_training) ws_md_ = *src_md();
+
+ dat_tag_ = memory_desc_matches_one_of_tag(*src_md(), nChw8c, nchw, nhwc);
+
+ bool args_ok_across = true
+ && desc()->alg_kind == lrn_across_channels
+ && desc()->local_size == 5
+ && one_of(dat_tag_, nChw8c, nchw, nhwc);
+
+ const int jit_max_local_size = 5; // bigger size triggers too big code size
+ bool args_ok_within = true
+ && desc()->alg_kind == lrn_within_channel
+ && desc()->local_size <= ( jit_max_local_size <= MAX_LOCAL_SIZE
+ ? jit_max_local_size : MAX_LOCAL_SIZE)
+ && data_d.dims()[2] >= desc()->local_size
+ && data_d.dims()[3] >= desc()->local_size
+ && one_of(dat_tag_, nChw8c);
+
+ return args_ok_across || args_ok_within ? success : unimplemented;
+}
+
+template <cpu_isa_t isa>
+jit_uni_lrn_bwd_t<isa>::jit_uni_lrn_bwd_t(const pd_t *apd)
+ : cpu_primitive_t(apd)
+ , ker_(nullptr), ker_first_(nullptr), ker_last_(nullptr)
+{
+ using namespace alg_kind;
+ const int C = pd()->C();
+ const int H = pd()->H();
+ const int W = pd()->W();
+ const int ls = pd()->desc()->local_size;
+ float A = pd()->desc()->lrn_alpha / ls;
+ float B = pd()->desc()->lrn_beta;
+
+ int use_h_parallelizm = 0;// XXX
+ if (C / VECTOR_LENGTH == 1) {
+ ker_ = new jit_uni_lrn_bwd_kernel_f32<isa>(
+ nchw8c_across(H, W, 3), A, B, use_h_parallelizm);
+ }
+ else {
+ ker_ = new jit_uni_lrn_bwd_kernel_f32<isa>(
+ nchw8c_across(H, W, 0), A, B, use_h_parallelizm);
+ ker_first_ = new jit_uni_lrn_bwd_kernel_f32<isa>(
+ nchw8c_across(H, W, -1), A, B, use_h_parallelizm);
+ ker_last_ = new jit_uni_lrn_bwd_kernel_f32<isa>(
+ nchw8c_across(H, W, +1), A, B, use_h_parallelizm);
+ }
+}
+
+template <cpu_isa_t isa>
+jit_uni_lrn_bwd_t<isa>::~jit_uni_lrn_bwd_t()
+{
+ delete ker_; delete ker_first_; delete ker_last_;
+}
+
+template <cpu_isa_t isa>
+void jit_uni_lrn_bwd_t<isa>::execute_backward(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto ws = CTX_IN_MEM(const data_t *, MKLDNN_ARG_WORKSPACE);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const int N = pd()->MB();
+ const int C = pd()->C();
+ const int H = pd()->H();
+ const int W = pd()->W();
+
+ int use_h_parallelizm = 0; // XXX
+ if (use_h_parallelizm) {
+ parallel_nd(N, C / VECTOR_LENGTH, H, [&](int n, int c8, int h) {
+ auto offset = n*C*H*W + c8*H*W*VECTOR_LENGTH
+ + h*W*VECTOR_LENGTH;
+ jit_args_bwd_t args;
+ args.src = &src[offset];
+ args.diff_dst = &diff_dst[offset];
+ args.scratch = &ws[offset];
+ args.diff_src = &diff_src[offset];
+ if (C / VECTOR_LENGTH == 1)
+ (*ker_)(&args);
+ else if (c8 == 0)
+ (*ker_first_)(&args);
+ else if (c8 == C / VECTOR_LENGTH - 1)
+ (*ker_last_)(&args);
+ else
+ (*ker_)(&args);
+ });
+ }
+ else {
+ parallel_nd(N, C / VECTOR_LENGTH, [&](int n, int c8) {
+ auto offset = n*C*H*W + c8*H*W*VECTOR_LENGTH;
+ jit_args_bwd_t args;
+ args.src = &src[offset];
+ args.diff_dst = &diff_dst[offset];
+ args.scratch = &ws[offset];
+ args.diff_src = &diff_src[offset];
+ if (C / VECTOR_LENGTH == 1)
+ (*ker_)(&args);
+ else if (c8 == 0)
+ (*ker_first_)(&args);
+ else if (c8 == C / VECTOR_LENGTH - 1)
+ (*ker_last_)(&args);
+ else
+ (*ker_)(&args);
+ });
+ }
+}
+
+template <cpu_isa_t isa>
+status_t jit_uni_lrn_bwd_t<isa>::pd_t::init() {
+ using namespace prop_kind;
+ using namespace alg_kind;
+
+ const memory_desc_wrapper data_d(src_md());
+ bool ok = true
+ && mayiuse(isa)
+ && !is_fwd()
+ && utils::everyone_is(data_type::f32, data_d.data_type())
+ && !has_zero_dim_memory()
+ && data_d.ndims() == 4
+ && data_d.dims()[1] % VECTOR_LENGTH == 0
+ && desc()->lrn_beta == 0.75
+ && attr()->has_default_values();
+ if (!ok) return unimplemented;
+
+ ws_md_ = *src_md();
+ if (!compare_ws(hint_fwd_pd_)) return unimplemented;
+
+ dat_tag_ = memory_desc_matches_one_of_tag(*src_md(), nChw8c);
+
+ bool args_ok_across = true
+ && desc()->alg_kind == lrn_across_channels
+ && desc()->local_size == 5
+ && utils::one_of(dat_tag_, nChw8c);
+
+ return args_ok_across ? success : unimplemented;
+}
+
+template struct jit_uni_lrn_fwd_t<sse42>;
+template struct jit_uni_lrn_fwd_t<avx2>;
+template struct jit_uni_lrn_bwd_t<avx2>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.hpp
new file mode 100644
index 0000000000..333cd3396d
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn.hpp
@@ -0,0 +1,103 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_UNI_LRN_HPP
+#define CPU_JIT_UNI_LRN_HPP
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_isa_traits.hpp"
+#include "cpu_lrn_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <cpu_isa_t isa> struct jit_uni_lrn_fwd_kernel_f32;
+template <cpu_isa_t isa> struct jit_uni_lrn_bwd_kernel_f32;
+
+template <cpu_isa_t isa>
+struct jit_uni_lrn_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_lrn_fwd_pd_t {
+ using cpu_lrn_fwd_pd_t::cpu_lrn_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", isa, ""),
+ jit_uni_lrn_fwd_t<isa>);
+
+ status_t init();
+
+ format_tag_t dat_tag_;
+ };
+
+ jit_uni_lrn_fwd_t(const pd_t *apd);
+ ~jit_uni_lrn_fwd_t();
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_uni_lrn_fwd_kernel_f32<isa> *ker_, *ker_first_, *ker_last_;
+};
+
+template <cpu_isa_t isa>
+struct jit_uni_lrn_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_lrn_bwd_pd_t {
+ using cpu_lrn_bwd_pd_t::cpu_lrn_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", isa, ""),
+ jit_uni_lrn_bwd_t<isa>);
+
+ status_t init();
+
+ format_tag_t dat_tag_;
+ };
+
+ jit_uni_lrn_bwd_t(const pd_t *apd);
+ ~jit_uni_lrn_bwd_t();
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ jit_uni_lrn_bwd_kernel_f32<isa> *ker_, *ker_first_, *ker_last_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.cpp
new file mode 100644
index 0000000000..89af47272c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.cpp
@@ -0,0 +1,1487 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "utils.hpp"
+
+#include "jit_uni_lrn_kernel_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace Xbyak;
+
+//////////////////////////////////////////////////////////////////////////////
+// forward kernel
+template<cpu_isa_t isa>
+void jit_uni_lrn_fwd_kernel_f32<isa>::within_body(
+ int hoff, int Hoff, int woff, int Woff, int stride,
+ Xbyak::Ymm ysum, Xbyak::Ymm ydst, Xbyak::Ymm ytmp, Xbyak::Ymm ysum2,
+ prop_kind_t pk)
+{
+ vxorps(ysum, ysum, ysum);
+ for (int i = hoff; i <= Hoff; ++i)
+ {
+ for (int j = woff; j <= Woff; ++j)
+ {
+ if (i == 0 && j == 0)
+ {
+ vmovups(ydst, ptr[src]);
+ vfmadd231ps(ysum, ydst, ydst);
+ }
+ else
+ {
+ vmovups(ytmp, ptr[src + (i*stride + j)*VECTOR_LENGTH*4]);
+ vfmadd231ps(ysum, ytmp, ytmp);
+ }
+ }
+ }
+ vfmadd132ps(ysum, yk, yalpha); // ysum <- ysum*yalpha+yk
+ vmovaps(ytmp, ysum);
+ if (pk != prop_kind::forward_inference)
+ vmovups(ptr[scratch], ytmp);
+ vmulps(ysum2, ysum, ysum);
+ vmulps(ysum, ysum, ysum2); // ysum = (ysum*yalpha+yk)^3;
+ vsqrtps(ysum, ysum);
+ vsqrtps(ysum, ysum); // ysum = (ysum*yalpha+yk)^0.75
+ vdivps(ydst, ydst, ysum); // ydst <- ydst / ysum
+ vmovups(ptr[dst], ydst);
+ add(src, 32);
+ add(dst, 32);
+ if (pk != prop_kind::forward_inference)
+ add(scratch, 32);
+}
+
+template<cpu_isa_t isa>
+void jit_uni_lrn_fwd_kernel_f32<isa>::within_body_sse42(
+ int hoff, int Hoff, int woff, int Woff, int stride, prop_kind_t pk)
+{
+ Xbyak::Xmm xtmp_lo = xmm12;
+ Xbyak::Xmm xtmp_hi = xmm13;
+ Xbyak::Xmm xsum_lo = xmm8;
+ Xbyak::Xmm xsum_hi = xmm9;
+ Xbyak::Xmm xdst_lo = xmm10;
+ Xbyak::Xmm xdst_hi = xmm11;
+ Xbyak::Xmm xsum2_lo = xmm14;
+ Xbyak::Xmm xsum2_hi = xmm15;
+
+ xorps(xsum_lo, xsum_lo);
+ xorps(xsum_hi, xsum_hi);
+ for (int i = hoff; i <= Hoff; ++i)
+ {
+ for (int j = woff; j <= Woff; ++j)
+ {
+ if (i == 0 && j == 0)
+ {
+ movups(xdst_lo, ptr[src]);
+ movups(xdst_hi, ptr[src + 4 * sizeof(float)]);
+ mulps(xdst_lo, xdst_lo);
+ mulps(xdst_hi, xdst_hi);
+ addps(xsum_lo, xdst_lo);
+ addps(xsum_hi, xdst_hi);
+ }
+ else
+ {
+ movups(xtmp_lo, ptr[src + (i*stride + j)*VECTOR_LENGTH * 4]);
+ movups(xtmp_hi, ptr[src + (i*stride + j)*VECTOR_LENGTH * 4 + 4 * sizeof(float)]);
+ mulps(xtmp_lo, xtmp_lo);
+ mulps(xtmp_hi, xtmp_hi);
+ addps(xsum_lo, xtmp_lo);
+ addps(xsum_hi, xtmp_hi);
+ }
+ }
+ }
+ mulps(xsum_lo, xalpha);
+ mulps(xsum_hi, xalpha);
+ addps(xsum_lo, xk);
+ addps(xsum_hi, xk); // xsum <- xsum*xalpha+xk
+ movaps(xtmp_lo, xsum_lo);
+ movaps(xtmp_hi, xsum_hi);
+ if (pk != prop_kind::forward_inference) {
+ movups(ptr[scratch], xtmp_lo);
+ movups(ptr[scratch + 4 * sizeof(float)], xtmp_hi);
+ }
+ movaps(xsum2_lo, xsum_lo);
+ movaps(xsum2_hi, xsum_hi);
+ mulps(xsum2_lo, xsum_lo);
+ mulps(xsum2_hi, xsum_hi);
+ mulps(xsum_lo, xsum2_lo);
+ mulps(xsum_hi, xsum2_hi); // xsum = (xsum*xalpha+xk)^3;
+
+ sqrtps(xsum_lo, xsum_lo);
+ sqrtps(xsum_hi, xsum_hi);
+ sqrtps(xsum_lo, xsum_lo);
+ sqrtps(xsum_hi, xsum_hi); // xsum = (xsum*xalpha+xk)^0.75
+
+ movups(xdst_lo, ptr[src]);
+ movups(xdst_hi, ptr[src + 4 * sizeof(float)]);
+ divps(xdst_lo, xsum_lo);
+ divps(xdst_hi, xsum_hi); // xdst <- xdst / xsum
+
+ movups(ptr[dst], xdst_lo);
+ movups(ptr[dst + 4 * sizeof(float)], xdst_hi);
+ add(src, 32);
+ add(dst, 32);
+ if (pk != prop_kind::forward_inference)
+ add(scratch, 32);
+}
+
+template <cpu_isa_t isa>
+jit_uni_lrn_fwd_kernel_f32<isa>::jit_uni_lrn_fwd_kernel_f32(
+ const struct nchw8c_within &J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void *code_ptr,
+ size_t code_size)
+ : jit_generator(code_ptr, code_size)
+ , alpha(A), k(K)
+{
+ Xbyak::Reg64 h = r9;
+ Xbyak::Reg64 w = r10;
+ Vmm ysum = Vmm(isa == avx2 ? 9 : 9);
+ Vmm ysum2 = Vmm(isa == avx2 ? 10 : 10);
+ Vmm ydst = Vmm(isa == avx2 ? 11 : 11);
+ Vmm ytmp = Vmm(isa == avx2 ? 12 : 12);
+
+ this->preamble();
+
+ mov(src, ptr[this->param1 + 0]);
+ mov(dst, ptr[this->param1 + 8]);
+ if (pk != prop_kind::forward_inference)
+ mov(scratch, ptr[this->param1 + 16]);
+
+ mov(imm_addr64, float2int(this->alpha));
+ movq(xalpha, imm_addr64);
+ if (isa == avx2) {
+ vbroadcastss(yalpha, xalpha);
+ } else {
+ shufps(xalpha, xalpha, 0);
+ }
+
+ mov(imm_addr64, float2int(this->k));
+ movq(xk, imm_addr64);
+ if (isa == avx2) {
+ vbroadcastss(yk, xk);
+ } else {
+ shufps(xk, xk, 0);
+ }
+
+ int s2 = (J.size - 1) / 2, S2 = J.size - s2 - 1;
+
+ for (int i = 0; i < s2; ++i)
+ {
+ Label label_t;
+ for (int j = 0; j < s2; ++j) {
+ if (isa == avx2) {
+ within_body(-i, S2, -j, S2, J.W, ysum, ydst, ytmp, ysum2, pk);
+ }
+ else {
+ within_body_sse42(-i, S2, -j, S2, J.W, pk);
+ }
+ }
+ mov(w, J.W - J.size + 1);
+ L(label_t);
+ if (isa == avx2) {
+ within_body(-i, S2, -s2, S2, J.W, ysum, ydst, ytmp, ysum2, pk);
+ } else {
+ within_body_sse42(-i, S2, -s2, S2, J.W, pk);
+ }
+ dec(w);
+ cmp(w, 0);
+ jne(label_t, T_NEAR);
+ for (int j = J.W - S2; j < J.W; ++j) {
+ if (isa == avx2) {
+ within_body(-i, S2, -s2, J.W - 1 - j, J.W,
+ ysum, ydst, ytmp, ysum2, pk);
+ } else {
+ within_body_sse42(-i, S2, -s2, J.W - 1 - j, J.W, pk);
+ }
+ }
+ }
+
+ mov(h, J.H - J.size + 1);
+ Label lrn_loop_h;
+ L(lrn_loop_h);
+ for (int j = 0; j < s2; ++j) {
+ if (isa == avx2) {
+ within_body(-s2, S2, -j, S2, J.W, ysum, ydst, ytmp, ysum2, pk);
+ } else {
+ within_body_sse42(-s2, S2, -j, S2, J.W, pk);
+ }
+ }
+ mov(w, J.W - J.size + 1);
+ Label lrn_loop_w;
+ L(lrn_loop_w);
+ if (isa == avx2) {
+ within_body(-s2, S2, -s2, S2, J.W, ysum, ydst, ytmp, ysum2, pk);
+ } else {
+ within_body_sse42(-s2, S2, -s2, S2, J.W, pk);
+ }
+ dec(w);
+ cmp(w, 0);
+ jne(lrn_loop_w, T_NEAR);
+ for (int j = J.W - S2; j < J.W; ++j) {
+ if (isa == avx2) {
+ within_body(-s2, S2, -s2, J.W - 1 - j, J.W,
+ ysum, ydst, ytmp, ysum2, pk);
+ } else {
+ within_body_sse42(-s2, S2, -s2, J.W - 1 - j, J.W, pk);
+ }
+ }
+ dec(h);
+ cmp(h, 0);
+ jne(lrn_loop_h, T_NEAR);
+
+ for (int i = J.H - S2; i < J.H; ++i)
+ {
+ for (int j = 0; j < s2; ++j) {
+ if (isa == avx2) {
+ within_body(-s2, J.H - 1 - i, -j, S2, J.W,
+ ysum, ydst, ytmp, ysum2, pk);
+ } else {
+ within_body_sse42(-s2, J.H - 1 - i, -j, S2, J.W, pk);
+ }
+ }
+
+ mov(w, J.W - J.size + 1);
+ Label label_b;
+ L(label_b);
+ if (isa == avx2) {
+ within_body(-s2, J.H - 1 - i, -s2, S2, J.W,
+ ysum, ydst, ytmp, ysum2, pk);
+ } else {
+ within_body_sse42(-s2, J.H - 1 - i, -s2, S2, J.W, pk);
+ }
+ dec(w);
+ cmp(w, 0);
+ jne(label_b, T_NEAR);
+
+ for (int j = J.W - S2; j < J.W; ++j) {
+ if (isa == avx2) {
+ within_body(-s2, J.H - 1 - i, -s2, J.W - 1 - j, J.W,
+ ysum, ydst, ytmp, ysum2, pk);
+ } else {
+ within_body_sse42(-s2, J.H - 1 - i, -s2, J.W - 1 - j, J.W, pk);
+ }
+ }
+ }
+
+ this->postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+}
+
+template<>
+jit_uni_lrn_fwd_kernel_f32<avx2>::jit_uni_lrn_fwd_kernel_f32(
+ const struct nchw8c_across &J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void *code_ptr,
+ size_t code_size)
+ : jit_generator(code_ptr, code_size)
+ , alpha(A), k(K)
+{
+ Xbyak::Reg64 t = rsp;
+ Xbyak::Reg64 hw = r9;
+ Xbyak::Xmm xsrc_prev = xmm2;
+ Xbyak::Ymm ysrc = ymm3;
+ Xbyak::Ymm yc = ymm3;
+ Xbyak::Xmm xsrc_next = xmm4;
+ Xbyak::Ymm ya = ymm5;
+ Xbyak::Ymm yb = ymm6;
+ Xbyak::Ymm yd = ymm7;
+ Xbyak::Ymm ye = ymm8;
+ Xbyak::Ymm ysum = ymm9;
+ Xbyak::Ymm ysum2 = ymm10;
+ Xbyak::Ymm ydst = ymm11;
+ Xbyak::Ymm ybase = ymm12;
+
+ this->preamble();
+
+ mov(src, ptr[this->param1 + 0]);
+ mov(dst, ptr[this->param1 + 8]);
+ if (pk != prop_kind::forward_inference)
+ mov(scratch, ptr[this->param1 + 16]);
+ sub(t, 64);
+ mov(imm_addr64, float2int(this->alpha));
+ movq(xalpha, imm_addr64);
+ vbroadcastss(yalpha, xalpha);
+
+ mov(imm_addr64, float2int(this->k));
+ movq(xk, imm_addr64);
+ vbroadcastss(yk, xk);
+
+ if (J.version == -1)
+ {
+ vxorps(xsrc_prev, xsrc_prev, xsrc_prev);
+ vmovups(ptr[t + 0], xsrc_prev);
+ }
+ if (J.version == +1)
+ {
+ vxorps(xsrc_next, xsrc_next, xsrc_next);
+ vmovups(ptr[t + 48], xsrc_next);
+ }
+
+ mov(hw, J.H*J.W);
+
+ Label lrn_loop;
+ L(lrn_loop);
+
+ if (J.version != -1) vmovups(xsrc_prev, ptr[src - J.H*J.W * 32 + 16]);
+ vmovups(ysrc, ptr[src]);
+ if (J.version != +1) vmovups(xsrc_next, ptr[src + J.H*J.W * 32]);
+
+ if (J.version != -1) vmovups(ptr[t + 0], xsrc_prev);
+ vmovups(ptr[t + 16], ysrc);
+ if (J.version != +1) vmovups(ptr[t + 48], xsrc_next);
+
+ vmovups(ya, ptr[t + 16 - 8]);
+ vmovups(yb, ptr[t + 16 - 4]);
+ vmovups(yd, ptr[t + 16 + 4]);
+ vmovups(ye, ptr[t + 16 + 8]);
+ vmulps(ysum, yc, yc);
+ vfmadd231ps(ysum, ya, ya); // ysum <- ysum + ya*ya
+ vfmadd231ps(ysum, yb, yb);
+ vfmadd231ps(ysum, yd, yd);
+ vfmadd231ps(ysum, ye, ye);
+ vfmadd132ps(ysum, yk, yalpha); // ysum <- ysum*yalpha+yk
+
+ vmovaps(ybase, ysum);
+ if (pk != prop_kind::forward_inference)
+ vmovups(ptr[scratch], ybase);
+ vmulps(ysum2, ysum, ysum);
+ vmulps(ysum, ysum, ysum2); // ysum = ybase^3;
+ vsqrtps(ysum, ysum);
+ vsqrtps(ysum, ysum); // ysum = ybase^0.75
+ vdivps(ydst, ysrc, ysum); // ydst = ysrc / ysum
+ vmovups(ptr[dst], ydst);
+
+ add(src, 32);
+ add(dst, 32);
+ if (pk != prop_kind::forward_inference)
+ add(scratch, 32);
+ dec(hw);
+ cmp(hw, 0);
+ jne(lrn_loop, T_NEAR);
+
+ add(t, 64);
+ this->postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+}
+
+template<>
+jit_uni_lrn_fwd_kernel_f32<sse42>::jit_uni_lrn_fwd_kernel_f32(
+ const struct nchw8c_across &J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void *code_ptr,
+ size_t code_size)
+ : jit_generator(code_ptr, code_size)
+ , alpha(A), k(K)
+{
+ Xbyak::Reg64 t = rsp;
+ Xbyak::Reg64 hw = r9;
+
+ Xbyak::Xmm xsrc_lo = xmm2;
+ Xbyak::Xmm xsrc_hi = xmm3;
+ Xbyak::Xmm xc_lo = xmm4;
+ Xbyak::Xmm xc_hi = xmm5;
+ Xbyak::Xmm xsum_lo = xc_lo;
+ Xbyak::Xmm xsum_hi = xc_hi;
+ Xbyak::Xmm xsrc_prev = xmm6;
+ Xbyak::Xmm xsrc_next = xmm7;
+ Xbyak::Xmm xa_lo = xmm8;
+ Xbyak::Xmm xa_hi = xmm9;
+ Xbyak::Xmm xb_lo = xmm10;
+ Xbyak::Xmm xb_hi = xmm11;
+ Xbyak::Xmm xd_lo = xmm12;
+ Xbyak::Xmm xd_hi = xmm13;
+ Xbyak::Xmm xe_lo = xmm14;
+ Xbyak::Xmm xe_hi = xmm15;
+ Xbyak::Xmm xbase_lo = xmm14;
+ Xbyak::Xmm xbase_hi = xmm15;
+
+ this->preamble();
+
+ mov(src, ptr[this->param1 + 0]);
+ mov(dst, ptr[this->param1 + 8]);
+ if (pk != prop_kind::forward_inference)
+ mov(scratch, ptr[this->param1 + 16]);
+ sub(t, 64);
+ mov(imm_addr64, float2int(this->alpha));
+ movq(xalpha, imm_addr64);
+ shufps(xalpha, xalpha, 0);
+
+ mov(imm_addr64, float2int(this->k));
+ movq(xk, imm_addr64);
+ shufps(xk, xk, 0);
+
+ if (J.version == -1)
+ {
+ xorps(xsrc_prev, xsrc_prev);
+ movups(ptr[t + 0], xsrc_prev);
+ }
+ if (J.version == +1)
+ {
+ xorps(xsrc_next, xsrc_next);
+ movups(ptr[t + 48], xsrc_next);
+ }
+
+ mov(hw, J.H*J.W);
+ Label lrn_loop;
+ L(lrn_loop);
+
+ if (J.version != -1) movups(xsrc_prev, ptr[src - J.H*J.W * 32 + 16]);
+ movups(xsrc_lo, ptr[src]);
+ movups(xsrc_hi, ptr[src + 4 * sizeof(float)]);
+ if (J.version != +1) movups(xsrc_next, ptr[src + J.H*J.W * 32]);
+
+ if (J.version != -1) movups(ptr[t + 0], xsrc_prev);
+ movups(ptr[t + 16], xsrc_lo);
+ movups(ptr[t + 16 + 4 * sizeof(float)], xsrc_hi);
+ if (J.version != +1) movups(ptr[t + 48], xsrc_next);
+
+ movups(xa_lo, ptr[t + 16 - 8]);
+ movups(xa_hi, ptr[t + 16 - 8 + 4 * sizeof(float)]);
+ movups(xb_lo, ptr[t + 16 - 4]);
+ movups(xb_hi, ptr[t + 16 - 4 + 4 * sizeof(float)]);
+ movups(xd_lo, ptr[t + 16 + 4]);
+ movups(xd_hi, ptr[t + 16 + 4 + 4 * sizeof(float)]);
+ movups(xe_lo, ptr[t + 16 + 8]);
+ movups(xe_hi, ptr[t + 16 + 8 + 4 * sizeof(float)]);
+ movaps(xc_lo, xsrc_lo);
+ movaps(xc_hi, xsrc_hi);
+ mulps(xsum_lo, xc_lo);
+ mulps(xsum_hi, xc_hi);
+ mulps(xa_lo, xa_lo);
+ mulps(xa_hi, xa_hi);
+ addps(xsum_lo, xa_lo);
+ addps(xsum_hi, xa_hi); // xsum <- xsum + xa*xa
+ mulps(xb_lo, xb_lo);
+ mulps(xb_hi, xb_hi);
+ addps(xsum_lo, xb_lo);
+ addps(xsum_hi, xb_hi);
+ mulps(xd_lo, xd_lo);
+ mulps(xd_hi, xd_hi);
+ addps(xsum_lo, xd_lo);
+ addps(xsum_hi, xd_hi);
+ mulps(xe_lo, xe_lo);
+ mulps(xe_hi, xe_hi);
+ addps(xsum_lo, xe_lo);
+ addps(xsum_hi, xe_hi);
+
+ mulps(xsum_lo, xalpha);
+ mulps(xsum_hi, xalpha);
+ addps(xsum_lo, xk);
+ addps(xsum_hi, xk); // xsum <- xsum*xalpha+xk
+
+ movaps(xbase_lo, xsum_lo);
+ movaps(xbase_hi, xsum_hi);
+ if (pk != prop_kind::forward_inference) {
+ movups(ptr[scratch], xbase_lo);
+ movups(ptr[scratch + 4 * sizeof(float)], xbase_hi);
+ }
+ mulps(xsum_lo, xsum_lo);
+ mulps(xsum_hi, xsum_hi);
+ mulps(xsum_lo, xbase_lo);
+ mulps(xsum_hi, xbase_hi); // xsum = xbase^3;
+ sqrtps(xsum_lo, xsum_lo);
+ sqrtps(xsum_hi, xsum_hi);
+ sqrtps(xsum_lo, xsum_lo);
+ sqrtps(xsum_hi, xsum_hi); // xsum = xbase^0.75
+ divps(xsrc_lo, xsum_lo);
+ divps(xsrc_hi, xsum_hi); // xdst = xsrc / xsum
+ movups(ptr[dst], xsrc_lo);
+ movups(ptr[dst + 4 * sizeof(float)], xsrc_hi);
+
+ add(src, 32);
+ add(dst, 32);
+ if (pk != prop_kind::forward_inference)
+ add(scratch, 32);
+ dec(hw);
+ cmp(hw, 0);
+ jne(lrn_loop, T_NEAR);
+
+ add(t, 64);
+ this->postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+}
+
+template<>
+jit_uni_lrn_fwd_kernel_f32<avx2>::jit_uni_lrn_fwd_kernel_f32(
+ const struct nhwc_across &J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void *code_ptr,
+ size_t code_size)
+ : jit_generator(code_ptr, code_size)
+ , alpha(A), k(K)
+{
+ static const uint32_t mask[] = {
+ 0, 0, 0x80000000, 0x80000000, 0x80000000, 0x80000000,
+ 0x80000000, 0x80000000, 0x80000000, 0, 0
+ };
+
+ Xbyak::Reg64 c = r9;
+ Xbyak::Ymm ya = ymm2;
+ Xbyak::Ymm yb = ymm3;
+ Xbyak::Ymm yc = ymm4;
+ Xbyak::Ymm yd = ymm5;
+ Xbyak::Ymm ye = ymm6;
+ Xbyak::Ymm ysum = ymm7;
+ Xbyak::Ymm ydst = ymm8;
+ Xbyak::Ymm ybase = ymm9;
+ Xbyak::Ymm ymask = ymm10;
+
+ this->preamble();
+
+ mov(src, ptr[this->param1 + 0]);
+ mov(dst, ptr[this->param1 + 8]);
+ if (pk != prop_kind::forward_inference)
+ mov(scratch, ptr[this->param1 + 16]);
+ mov(imm_addr64, float2int(this->alpha));
+ movq(xalpha, imm_addr64);
+ vbroadcastss(yalpha, xalpha);
+
+ mov(imm_addr64, float2int(this->k));
+ movq(xk, imm_addr64);
+ vbroadcastss(yk, xk);
+
+ vxorps(ysum, ysum, ysum);
+
+ mov(imm_addr64, reinterpret_cast<size_t>(&mask[0]));
+ vmovups(ymask, ptr[imm_addr64]);
+ vmaskmovps(ya, ymask, ptr[src - 8]);
+ vfmadd231ps(ysum, ya, ya); // ysum <- ysum + ya^2+yb^2+yc^2+yd^2+ye^2
+
+ mov(imm_addr64, reinterpret_cast<size_t>(&mask[1]));
+ vmovups(ymask, ptr[imm_addr64]);
+ vmaskmovps(yb, ymask, ptr[src - 4]);
+ vfmadd231ps(ysum, yb, yb);
+
+ mov(c, J.C / 8 - 1);
+ Label lrn_loop;
+ L(lrn_loop);
+
+ vmovups(yc, ptr[src]);
+ vmovups(yd, ptr[src + 4]);
+ vmovups(ye, ptr[src + 8]);
+ vfmadd231ps(ysum, yc, yc);
+ vfmadd231ps(ysum, yd, yd);
+ vfmadd231ps(ysum, ye, ye);
+
+ vmovups(ydst, ysum);
+ vfmadd132ps(ydst, yk, yalpha); // ydst <- ysum*yalpha+yk
+
+ vmovaps(ybase, ydst);
+ if (pk != prop_kind::forward_inference)
+ vmovups(ptr[scratch], ybase);
+ vmulps(ydst, ydst, ydst);
+ vmulps(ydst, ydst, ybase); // ydst = (ysum*yalpha+yk)^3;
+ vsqrtps(ydst, ydst);
+ vsqrtps(ydst, ydst); // ydst = (ysum*yalpha+yk)^0.75
+
+ vdivps(ydst, yc, ydst); // ydst = ysrc / (ysum*yalpha+yk)^0.75
+ vmovups(ptr[dst], ydst);
+
+ vxorps(ysum, ysum, ysum);
+
+ add(src, 32);
+ add(dst, 32);
+ if (pk != prop_kind::forward_inference)
+ add(scratch, 32);
+
+ vmovups(ya, ptr[src - 8]);
+ vfmadd231ps(ysum, ya, ya);
+ vmovups(yb, ptr[src - 4]);
+ vfmadd231ps(ysum, yb, yb);
+
+ dec(c);
+ cmp(c, 0);
+ jne(lrn_loop, T_NEAR);
+
+ vmovups(yc, ptr[src]);
+ vfmadd231ps(ysum, yc, yc);
+
+ mov(imm_addr64, reinterpret_cast<size_t>(&mask[2]));
+ vmovups(ymask, ptr[imm_addr64]);
+ vmaskmovps(yd, ymask, ptr[src + 4]);
+ vfmadd231ps(ysum, yd, yd); // ysum <- ysum + ya^2+yb^2+yc^2+yd^2+ye^2
+
+ mov(imm_addr64, reinterpret_cast<size_t>(&mask[3]));
+ vmovups(ymask, ptr[imm_addr64]);
+ vmaskmovps(ye, ymask, ptr[src + 8]);
+ vfmadd231ps(ysum, ye, ye);
+
+ vmovups(ydst, ysum);
+ vfmadd132ps(ydst, yk, yalpha); // ydst <- ysum*yalpha+yk
+
+ vmovaps(ybase, ydst);
+ if (pk != prop_kind::forward_inference)
+ vmovups(ptr[scratch], ybase);
+ vmulps(ydst, ydst, ydst);
+ vmulps(ydst, ydst, ybase); // ydst = (ysum*yalpha+yk)^3;
+ vsqrtps(ydst, ydst);
+ vsqrtps(ydst, ydst); // ydst = (ysum*yalpha+yk)^0.75
+ vdivps(ydst, yc, ydst); // ydst = ysrc / (ysum*yalpha+yk)^0.75
+
+ vmovups(ptr[dst], ydst);
+
+ this->postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+}
+
+template<>
+jit_uni_lrn_fwd_kernel_f32<sse42>::jit_uni_lrn_fwd_kernel_f32(
+ const struct nhwc_across &J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void *code_ptr,
+ size_t code_size)
+ : jit_generator(code_ptr, code_size)
+ , alpha(A), k(K)
+{
+ static const uint32_t mask[] = {
+ 0, 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0, 0
+ };
+
+ static uint32_t store[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ Xbyak::Reg64 c = r9;
+
+ Xbyak::Xmm xdst_lo = xmm0;
+ Xbyak::Xmm xdst_hi = xmm1;
+ Xbyak::Xmm xa_lo = xmm2;
+ Xbyak::Xmm xa_hi = xmm3;
+ Xbyak::Xmm xb_lo = xmm2;
+ Xbyak::Xmm xb_hi = xmm3;
+ Xbyak::Xmm xc_lo = xmm4;
+ Xbyak::Xmm xc_hi = xmm5;
+ Xbyak::Xmm xd_lo = xmm6;
+ Xbyak::Xmm xd_hi = xmm7;
+ Xbyak::Xmm xe_lo = xmm8;
+ Xbyak::Xmm xe_hi = xmm9;
+ Xbyak::Xmm xsum_lo = xmm10;
+ Xbyak::Xmm xsum_hi = xmm11;
+ Xbyak::Xmm xmask_lo = xmm12;
+ Xbyak::Xmm xmask_hi = xmm13;
+ Xbyak::Xmm xbase_lo = xmm14;
+ Xbyak::Xmm xbase_hi = xmm15;
+
+ this->preamble();
+
+ mov(src, ptr[this->param1 + 0]);
+ mov(dst, ptr[this->param1 + 8]);
+ if (pk != prop_kind::forward_inference)
+ mov(scratch, ptr[this->param1 + 16]);
+ mov(imm_addr64, float2int(this->alpha));
+ movq(xalpha, imm_addr64);
+ shufps(xalpha, xalpha, 0);
+
+ mov(imm_addr64, float2int(this->k));
+ movq(xk, imm_addr64);
+ shufps(xk, xk, 0);
+
+ mov(store_addr, reinterpret_cast<size_t>(&store[0]));
+ and_(store_addr, -15);
+ movups(ptr[store_addr], xalpha);
+ movups(ptr[store_addr + 4 * sizeof(float)], xk);
+
+ xorps(xsum_lo, xsum_lo);
+ xorps(xsum_hi, xsum_hi);
+
+ mov(imm_addr64, reinterpret_cast<size_t>(&mask[0]));
+ movups(xmask_lo, ptr[imm_addr64]);
+ movups(xmask_hi, ptr[imm_addr64 + 4 * sizeof(float)]);
+ movups(xa_lo, ptr[src - 8]);
+ movups(xa_hi, ptr[src - 8 + 4 * sizeof(float)]);
+ andps(xa_lo, xmask_lo);
+ andps(xa_hi, xmask_hi);
+ mulps(xa_lo, xa_lo);
+ mulps(xa_hi, xa_hi);
+ addps(xsum_lo, xa_lo);
+ addps(xsum_hi, xa_hi); // xsum <- xsum + xa^2+xb^2+xc^2+xd^2+xe^2
+
+ mov(imm_addr64, reinterpret_cast<size_t>(&mask[1]));
+ movups(xmask_lo, ptr[imm_addr64]);
+ movups(xmask_hi, ptr[imm_addr64 + 4 * sizeof(float)]);
+ movups(xb_lo, ptr[src - 4]);
+ movups(xb_hi, ptr[src - 4 + 4 * sizeof(float)]);
+ andps(xb_lo, xmask_lo);
+ andps(xb_hi, xmask_hi);
+ mulps(xb_lo, xb_lo);
+ mulps(xb_hi, xb_hi);
+ addps(xsum_lo, xb_lo);
+ addps(xsum_hi, xb_hi);
+
+ mov(c, J.C / 8 - 1);
+ Label lrn_loop;
+ L(lrn_loop);
+
+ movups(xc_lo, ptr[src]);
+ movups(xc_hi, ptr[src + 4 * sizeof(float)]);
+ movups(xd_lo, ptr[src + 4]);
+ movups(xd_hi, ptr[src + 4 + 4 * sizeof(float)]);
+ movups(xe_lo, ptr[src + 8]);
+ movups(xe_hi, ptr[src + 8 + 4 * sizeof(float)]);
+ mulps(xc_lo, xc_lo);
+ mulps(xc_hi, xc_hi);
+ addps(xsum_lo, xc_lo);
+ addps(xsum_hi, xc_hi);
+ mulps(xd_lo, xd_lo);
+ mulps(xd_hi, xd_hi);
+ addps(xsum_lo, xd_lo);
+ addps(xsum_hi, xd_hi);
+ mulps(xe_lo, xe_lo);
+ mulps(xe_hi, xe_hi);
+ addps(xsum_lo, xe_lo);
+ addps(xsum_hi, xe_hi);
+
+ movaps(xdst_lo, xsum_lo);
+ movaps(xdst_hi, xsum_hi);
+ // xdst <- xsum*xalpha+xk
+ mulps(xdst_lo, ptr[store_addr]);
+ mulps(xdst_hi, ptr[store_addr]);
+ addps(xdst_lo, ptr[store_addr + 4 * sizeof(float)]);
+ addps(xdst_hi, ptr[store_addr + 4 * sizeof(float)]);
+
+ movaps(xbase_lo, xdst_lo);
+ movaps(xbase_hi, xdst_hi);
+ if (pk != prop_kind::forward_inference) {
+ movups(ptr[scratch], xbase_lo);
+ movups(ptr[scratch + 4 * sizeof(float)], xbase_hi);
+ }
+ mulps(xdst_lo, xdst_lo);
+ mulps(xdst_hi, xdst_hi);
+ mulps(xdst_lo, xbase_lo);
+ mulps(xdst_hi, xbase_hi); // xdst = (xsum*xalpha+xk)^3;
+ sqrtps(xdst_lo, xdst_lo);
+ sqrtps(xdst_hi, xdst_hi);
+ sqrtps(xdst_lo, xdst_lo);
+ sqrtps(xdst_hi, xdst_hi); // xdst = (xsum*xalpha+xk)^0.75
+
+ movups(xc_lo, ptr[src]);
+ movups(xc_hi, ptr[src + 4 * sizeof(float)]);
+ divps(xc_lo, xdst_lo);
+ divps(xc_hi, xdst_hi); // xdst = xsrc / (xsum*xalpha+xk)^0.75
+ movups(ptr[dst], xc_lo);
+ movups(ptr[dst + 4 * sizeof(float)], xc_hi);
+
+ xorps(xsum_lo, xsum_lo);
+ xorps(xsum_hi, xsum_hi);
+
+ add(src, 32);
+ add(dst, 32);
+ if (pk != prop_kind::forward_inference)
+ add(scratch, 32);
+
+ movups(xa_lo, ptr[src - 8]);
+ movups(xa_hi, ptr[src - 8 + 4 * sizeof(float)]);
+ mulps(xa_lo, xa_lo);
+ mulps(xa_hi, xa_hi);
+ addps(xsum_lo, xa_lo);
+ addps(xsum_hi, xa_hi);
+ movups(xb_lo, ptr[src - 4]);
+ movups(xb_hi, ptr[src - 4 + 4 * sizeof(float)]);
+ mulps(xb_lo, xb_lo);
+ mulps(xb_hi, xb_hi);
+ addps(xsum_lo, xb_lo);
+ addps(xsum_hi, xb_hi);
+
+ dec(c);
+ cmp(c, 0);
+ jne(lrn_loop, T_NEAR);
+
+ movups(xc_lo, ptr[src]);
+ movups(xc_hi, ptr[src + 4 * sizeof(float)]);
+ mulps(xc_lo, xc_lo);
+ mulps(xc_hi, xc_hi);
+ addps(xsum_lo, xc_lo);
+ addps(xsum_hi, xc_hi);
+
+ mov(imm_addr64, reinterpret_cast<size_t>(&mask[2]));
+ movups(xmask_lo, ptr[imm_addr64]);
+ movups(xmask_hi, ptr[imm_addr64 + 4 * sizeof(float)]);
+ movups(xd_lo, ptr[src + 4]);
+ movups(xd_hi, ptr[src + 4 + 4 * sizeof(float)]);
+ andps(xd_lo, xmask_lo);
+ andps(xd_hi, xmask_hi);
+ mulps(xd_lo, xd_lo);
+ mulps(xd_hi, xd_hi);
+ addps(xsum_lo, xd_lo);
+ addps(xsum_hi, xd_hi); // xsum <- xsum + xa^2+xb^2+xc^2+xd^2+xe^2
+
+ mov(imm_addr64, reinterpret_cast<size_t>(&mask[3]));
+ movups(xmask_lo, ptr[imm_addr64]);
+ movups(xmask_hi, ptr[imm_addr64 + 4 * sizeof(float)]);
+ movups(xe_lo, ptr[src + 8]);
+ movups(xe_hi, ptr[src + 8 + 4 * sizeof(float)]);
+ andps(xe_lo, xmask_lo);
+ andps(xe_hi, xmask_hi);
+ mulps(xe_lo, xe_lo);
+ mulps(xe_hi, xe_hi);
+ addps(xsum_lo, xe_lo);
+ addps(xsum_hi, xe_hi);
+
+ movups(xdst_lo, xsum_lo);
+ movups(xdst_hi, xsum_hi);
+ // xdst <- xsum*xalpha+xk
+ mulps(xdst_lo, ptr[store_addr]);
+ mulps(xdst_hi, ptr[store_addr]);
+ addps(xdst_lo, ptr[store_addr + 4 * sizeof(float)]);
+ addps(xdst_hi, ptr[store_addr + 4 * sizeof(float)]);
+
+ movaps(xbase_lo, xdst_lo);
+ movaps(xbase_hi, xdst_hi);
+ if (pk != prop_kind::forward_inference) {
+ movups(ptr[scratch], xbase_lo);
+ movups(ptr[scratch + 4 * sizeof(float)], xbase_hi);
+ }
+ mulps(xdst_lo, xdst_lo);
+ mulps(xdst_hi, xdst_hi);
+ mulps(xdst_lo, xbase_lo);
+ mulps(xdst_hi, xbase_hi); // xdst = (xsum*xalpha+xk)^3;
+ sqrtps(xdst_lo, xdst_lo);
+ sqrtps(xdst_hi, xdst_hi);
+ sqrtps(xdst_lo, xdst_lo);
+ sqrtps(xdst_hi, xdst_hi); // xdst = (xsum*xalpha+xk)^0.75
+ movups(xc_lo, ptr[src]);
+ movups(xc_hi, ptr[src + 4 * sizeof(float)]);
+ divps(xc_lo, xdst_lo);
+ divps(xc_hi, xdst_hi); // xdst = xsrc / (xsum*xalpha+xk)^0.75
+
+ movups(ptr[dst], xc_lo);
+ movups(ptr[dst + 4 * sizeof(float)], xc_hi);
+
+ this->postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+}
+
+template<>
+void jit_uni_lrn_fwd_kernel_f32<sse42>::nchw_body(
+ int tail, int HW, prop_kind_t pk,
+ Xbyak::Ymm ymask,
+ Xbyak::Ymm ya,
+ Xbyak::Ymm yb,
+ Xbyak::Ymm yc,
+ Xbyak::Ymm yd,
+ Xbyak::Ymm ye,
+ Xbyak::Ymm ysum) {}
+
+template<>
+void jit_uni_lrn_fwd_kernel_f32<avx2>::nchw_body(
+ int tail, int HW, prop_kind_t pk,
+ Xbyak::Ymm ymask,
+ Xbyak::Ymm ya,
+ Xbyak::Ymm yb,
+ Xbyak::Ymm yc,
+ Xbyak::Ymm yd,
+ Xbyak::Ymm ye,
+ Xbyak::Ymm ysum)
+{
+ Xbyak::Ymm ydst = ymm14;
+ Xbyak::Ymm ybase = ymm15;
+
+ vfmadd231ps(ysum, ye, ye);
+
+ vmovups(ydst, ysum);
+ vfmadd132ps(ydst, yk, yalpha); // ydst <- ysum*yalpha+yk
+
+ vmovaps(ybase, ydst);
+ if (pk != prop_kind::forward_inference)
+ {
+ if (tail != 0)
+ vmaskmovps(ptr[scratch], ymask, ybase);
+ else
+ vmovups(ptr[scratch], ybase);
+ }
+ vmulps(ydst, ydst, ydst);
+ vmulps(ydst, ydst, ybase); // ydst = (ysum*yalpha+yk)^3;
+ vsqrtps(ydst, ydst);
+ vsqrtps(ydst, ydst); // ydst = (ysum*yalpha+yk)^0.75
+ vdivps(ydst, yc, ydst); // ydst = ysrc / (ysum*yalpha+yk)^0.75
+
+ if (tail != 0)
+ vmaskmovps(ptr[dst], ymask, ydst);
+ else
+ vmovups(ptr[dst], ydst);
+
+
+ vfnmadd231ps(ysum, ya, ya);
+ vmovups(ya, yb);
+ vmovups(yb, yc);
+ vmovups(yc, yd);
+ vmovups(yd, ye);
+}
+
+template<>
+void jit_uni_lrn_fwd_kernel_f32<avx2>::nchw_tail_sse42(
+ int tail, Xbyak::Reg64 reg_dst, Xbyak::Xmm xtail_lo, Xbyak::Xmm xtail_hi)
+{}
+
+template<>
+void jit_uni_lrn_fwd_kernel_f32<sse42>::nchw_tail_sse42(
+ int tail, Xbyak::Reg64 reg_dst, Xbyak::Xmm xtail_lo, Xbyak::Xmm xtail_hi)
+{
+ Xbyak::Xmm xmm_tmp = xmm10;
+ movaps(xmm_tmp, xtail_lo);
+ size_t offset = 0;
+
+ if (tail > 4) {
+ movups(ptr[reg_dst], xtail_lo);
+ movaps(xmm_tmp, xtail_hi);
+ offset += 4 * sizeof(float);
+ tail -= 4;
+ }
+ movss(ptr[reg_dst + offset], xmm_tmp);
+ for (int i = 1; i < tail; i++)
+ {
+ psrldq(xmm_tmp, 4);
+ movss(ptr[reg_dst + offset + i * sizeof(float)], xmm_tmp);
+ }
+}
+
+template<>
+void jit_uni_lrn_fwd_kernel_f32<sse42>::nchw_body_sse42(
+ int tail, int HW, prop_kind_t pk,
+ Xbyak::Xmm xmask_lo, Xbyak::Xmm xmask_hi,
+ Xbyak::Xmm xe_lo, Xbyak::Xmm xe_hi,
+ Xbyak::Xmm xsum_lo, Xbyak::Xmm xsum_hi)
+{
+ Xbyak::Xmm xdst_lo = xmm0;
+ Xbyak::Xmm xdst_hi = xmm1;
+ Xbyak::Xmm xbase_lo = xmm6;
+ Xbyak::Xmm xbase_hi = xmm7;
+ Xbyak::Xmm xtmp_lo = xmm8;
+ Xbyak::Xmm xtmp_hi = xmm9;
+ Xbyak::Xmm xa_lo = xmm6;
+ Xbyak::Xmm xa_hi = xmm7;
+ Xbyak::Xmm xb_lo = xmm8;
+ Xbyak::Xmm xb_hi = xmm9;
+ Xbyak::Xmm xc_lo = xmm10;
+ Xbyak::Xmm xc_hi = xmm11;
+ Xbyak::Xmm xd_lo = xmm12;
+ Xbyak::Xmm xd_hi = xmm13;
+
+ // store xe
+ movaps(ptr[store_addr + 10 * 4 * sizeof(float)], xe_lo);
+ movaps(ptr[store_addr + 11 * 4 * sizeof(float)], xe_hi);
+
+ mulps(xe_lo, xe_lo);
+ mulps(xe_hi, xe_hi);
+ addps(xsum_lo, xe_lo);
+ addps(xsum_hi, xe_hi);
+
+ // xdst <- xsum*xalpha+xk
+ movaps(xdst_lo, xsum_lo);
+ movaps(xdst_hi, xsum_hi);
+ mulps(xdst_lo, ptr[store_addr + 0 * 4 * sizeof(float)]);
+ mulps(xdst_hi, ptr[store_addr + 0 * 4 * sizeof(float)]);
+ addps(xdst_lo, ptr[store_addr + 1 * 4 * sizeof(float)]);
+ addps(xdst_hi, ptr[store_addr + 1 * 4 * sizeof(float)]);
+
+ movaps(xbase_lo, xdst_lo);
+ movaps(xbase_hi, xdst_hi);
+ if (pk != prop_kind::forward_inference)
+ {
+ if (tail != 0) {
+ nchw_tail_sse42(tail, scratch, xbase_lo, xbase_hi);
+ }
+ else {
+ movups(ptr[scratch], xbase_lo);
+ movups(ptr[scratch + 4 * sizeof(float)], xbase_hi);
+ }
+ }
+ mulps(xdst_lo, xdst_lo);
+ mulps(xdst_hi, xdst_hi);
+ mulps(xdst_lo, xbase_lo);
+ mulps(xdst_hi, xbase_hi); // xdst = (xsum*xalpha+xk)^3;
+ sqrtps(xdst_lo, xdst_lo);
+ sqrtps(xdst_hi, xdst_hi);
+ sqrtps(xdst_lo, xdst_lo);
+ sqrtps(xdst_hi, xdst_hi); // xdst = (xsum*xalpha+xk)^0.75
+ movaps(xtmp_lo, ptr[store_addr + 6 * 4 * sizeof(float)]);
+ movaps(xtmp_hi, ptr[store_addr + 7 * 4 * sizeof(float)]);
+ divps(xtmp_lo, xdst_lo);
+ divps(xtmp_hi, xdst_hi); // xdst = xsrc / (xsum*xalpha+xk)^0.75
+ movaps(xdst_lo, xtmp_lo);
+ movaps(xdst_hi, xtmp_hi);
+
+ if (tail != 0) {
+ nchw_tail_sse42(tail, dst, xdst_lo, xdst_hi);
+ }
+ else {
+ movups(ptr[dst], xdst_lo);
+ movups(ptr[dst + 4 * sizeof(float)], xdst_hi);
+ }
+
+ movaps(xa_lo, ptr[store_addr + 2 * 4 * sizeof(float)]);
+ movaps(xa_hi, ptr[store_addr + 3 * 4 * sizeof(float)]);
+ mulps(xa_lo, xa_lo);
+ mulps(xa_hi, xa_hi);
+ subps(xsum_lo, xa_lo);
+ subps(xsum_hi, xa_hi);
+
+ // xa <- xb
+ movaps(xb_lo, ptr[store_addr + 4 * 4 * sizeof(float)]);
+ movaps(xb_hi, ptr[store_addr + 5 * 4 * sizeof(float)]);
+ movaps(ptr[store_addr + 2 * 4 * sizeof(float)], xb_lo);
+ movaps(ptr[store_addr + 3 * 4 * sizeof(float)], xb_hi);
+
+ // xb <- xc
+ movaps(xc_lo, ptr[store_addr + 6 * 4 * sizeof(float)]);
+ movaps(xc_hi, ptr[store_addr + 7 * 4 * sizeof(float)]);
+ movaps(ptr[store_addr + 4 * 4 * sizeof(float)], xc_lo);
+ movaps(ptr[store_addr + 5 * 4 * sizeof(float)], xc_hi);
+
+ // xc <- xd
+ movaps(xd_lo, ptr[store_addr + 8 * 4 * sizeof(float)]);
+ movaps(xd_hi, ptr[store_addr + 9 * 4 * sizeof(float)]);
+ movaps(ptr[store_addr + 6 * 4 * sizeof(float)], xd_lo);
+ movaps(ptr[store_addr + 7 * 4 * sizeof(float)], xd_hi);
+
+ // xd <- xe
+ movaps(xe_lo, ptr[store_addr + 10 * 4 * sizeof(float)]);
+ movaps(xe_hi, ptr[store_addr + 11 * 4 * sizeof(float)]);
+ movaps(ptr[store_addr + 8 * 4 * sizeof(float)], xe_lo);
+ movaps(ptr[store_addr + 9 * 4 * sizeof(float)], xe_hi);
+}
+
+template<>
+void jit_uni_lrn_fwd_kernel_f32<avx2>::nchw_body_sse42(
+ int tail, int HW, prop_kind_t pk,
+ Xbyak::Xmm xmask_lo, Xbyak::Xmm xmask_hi,
+ Xbyak::Xmm xe_lo, Xbyak::Xmm xe_hi,
+ Xbyak::Xmm xsum_lo, Xbyak::Xmm xsum_hi) {}
+
+template<>
+jit_uni_lrn_fwd_kernel_f32<avx2>::jit_uni_lrn_fwd_kernel_f32(
+ struct nchw_across J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void* code_ptr,
+ size_t code_size)
+ : jit_generator(code_ptr, code_size)
+ , alpha(A), k(K)
+{
+ static const uint32_t mask[] = {
+ 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000,
+ 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0
+ };
+ Xbyak::Reg64 c = r10;
+ Xbyak::Ymm ymask = ymm2;
+ Xbyak::Ymm ye = ymm3;
+ Xbyak::Ymm ya = ymm4;
+ Xbyak::Ymm yb = ymm5;
+ Xbyak::Ymm yc = ymm6;
+ Xbyak::Ymm yd = ymm7;
+ Xbyak::Ymm ysum = ymm8;
+
+ this->preamble();
+
+ if (J.tail != 0)
+ {
+ mov(imm_addr64, reinterpret_cast<size_t>(&mask[7 - J.tail]));
+ vmovups(ymask, ptr[imm_addr64]);
+ }
+ mov(imm_addr64, float2int(this->alpha));
+ movq(xalpha, imm_addr64);
+ vbroadcastss(yalpha, xalpha);
+
+ mov(imm_addr64, float2int(this->k));
+ movq(xk, imm_addr64);
+ vbroadcastss(yk, xk);
+
+ mov(src, ptr[this->param1 + 0]);
+ mov(dst, ptr[this->param1 + 8]);
+ if (pk != prop_kind::forward_inference)
+ mov(scratch, ptr[this->param1 + 16]);
+
+ vxorps(ya, ya, ya);
+ vxorps(yb, yb, yb);
+ if (J.tail != 0)
+ vmaskmovps(yc, ymask, ptr[src + J.HW * 0]);
+ else
+ vmovups(yc, ptr[src + J.HW * 0]);
+ if (J.tail != 0)
+ vmaskmovps(yd, ymask, ptr[src + J.HW * 4]);
+ else
+ vmovups(yd, ptr[src + J.HW * 4]);
+
+ vxorps(ysum, ysum, ysum);
+ vfmadd231ps(ysum, yc, yc); // ysum <- ysum + ya^2+yb^2+yc^2+yd^2+ye^2
+ vfmadd231ps(ysum, yd, yd);
+
+ mov(c, J.C - 2);
+ Label lrn_loop;
+ L(lrn_loop);
+
+ if (J.tail != 0)
+ vmaskmovps(ye, ymask, ptr[src + J.HW * 8]);
+ else
+ vmovups(ye, ptr[src + J.HW * 8]);
+
+ nchw_body(J.tail, J.HW, pk, ymask, ya, yb, yc, yd, ye, ysum);
+
+ add(src, J.HW * 4);
+ add(dst, J.HW * 4);
+ if (pk != prop_kind::forward_inference)
+ add(scratch, J.HW * 4);
+ dec(c);
+ cmp(c, 0);
+ jne(lrn_loop, T_NEAR);
+
+ vxorps(ye, ye, ye);
+
+ nchw_body(J.tail, J.HW, pk, ymask, ya, yb, yc, yd, ye, ysum);
+ add(src, J.HW * 4);
+ add(dst, J.HW * 4);
+ if (pk != prop_kind::forward_inference)
+ add(scratch, J.HW * 4);
+
+ nchw_body(J.tail, J.HW, pk, ymask, ya, yb, yc, yd, ye, ysum);
+
+ this->postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+}
+
+template<>
+jit_uni_lrn_fwd_kernel_f32<sse42>::jit_uni_lrn_fwd_kernel_f32(
+ struct nchw_across J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void* code_ptr,
+ size_t code_size)
+ : jit_generator(code_ptr, code_size)
+ , alpha(A), k(K)
+{
+ static const uint32_t mask[] = {
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ Xbyak::Reg64 c = r10;
+
+ Xbyak::Xmm xmask_lo = xmm2;
+ Xbyak::Xmm xmask_hi = xmm3;
+ Xbyak::Xmm xsum_lo = xmm4;
+ Xbyak::Xmm xsum_hi = xmm5;
+ Xbyak::Xmm xa_lo = xmm6;
+ Xbyak::Xmm xa_hi = xmm7;
+ Xbyak::Xmm xb_lo = xmm8;
+ Xbyak::Xmm xb_hi = xmm9;
+ Xbyak::Xmm xc_lo = xmm10;
+ Xbyak::Xmm xc_hi = xmm11;
+ Xbyak::Xmm xd_lo = xmm12;
+ Xbyak::Xmm xd_hi = xmm13;
+ Xbyak::Xmm xe_lo = xmm14;
+ Xbyak::Xmm xe_hi = xmm15;
+
+ this->preamble();
+
+ mov(src, ptr[this->param1 + 0]);
+ mov(dst, ptr[this->param1 + 8]);
+ if (pk != prop_kind::forward_inference)
+ mov(scratch, ptr[this->param1 + 16]);
+
+ sub(rsp, stack_space_needed);
+ mov(store_addr, rsp);
+ and_(store_addr, -15);
+
+ mov(imm_addr64, float2int(this->alpha));
+ movq(xalpha, imm_addr64);
+ shufps(xalpha, xalpha, 0);
+
+ mov(imm_addr64, float2int(this->k));
+ movq(xk, imm_addr64);
+ shufps(xk, xk, 0);
+
+ // put alpha and k into store (free up regs)
+ movaps(ptr[store_addr + 0 * 4 * sizeof(float)], xalpha);
+ movaps(ptr[store_addr + 1 * 4 * sizeof(float)], xk);
+
+ if (J.tail != 0)
+ {
+ mov(imm_addr64, reinterpret_cast<size_t>(&mask[7 - J.tail]));
+ movups(xmask_lo, ptr[imm_addr64]);
+ movups(xmask_hi, ptr[imm_addr64 + 4 * sizeof(float)]);
+ }
+ // init xa, xb
+ xorps(xa_lo, xa_lo);
+ xorps(xa_hi, xa_hi);
+ xorps(xb_lo, xb_lo);
+ xorps(xb_hi, xb_hi);
+
+ // read xc, xd
+ if (J.tail != 0) {
+ movups(xc_lo, ptr[src + J.HW * 0]);
+ movups(xc_hi, ptr[src + J.HW * 0 + 4 * sizeof(float)]);
+ andps(xc_lo, xmask_lo);
+ andps(xc_hi, xmask_hi);
+ }
+ else {
+ movups(xc_lo, ptr[src + J.HW * 0]);
+ movups(xc_hi, ptr[src + J.HW * 0 + 4 * sizeof(float)]);
+ }
+ if (J.tail != 0) {
+ movups(xd_lo, ptr[src + J.HW * 4]);
+ movups(xd_hi, ptr[src + J.HW * 4 + 4 * sizeof(float)]);
+ andps(xd_lo, xmask_lo);
+ andps(xd_hi, xmask_hi);
+ }
+ else {
+ movups(xd_lo, ptr[src + J.HW * 4]);
+ movups(xd_hi, ptr[src + J.HW * 4 + 4 * sizeof(float)]);
+ }
+
+ // put xa, xb, xc, xd into store to free-up regs
+ movaps(ptr[store_addr + 2 * 4 * sizeof(float)], xa_lo);
+ movaps(ptr[store_addr + 3 * 4 * sizeof(float)], xa_hi);
+ movaps(ptr[store_addr + 4 * 4 * sizeof(float)], xb_lo);
+ movaps(ptr[store_addr + 5 * 4 * sizeof(float)], xb_hi);
+ movaps(ptr[store_addr + 6 * 4 * sizeof(float)], xc_lo);
+ movaps(ptr[store_addr + 7 * 4 * sizeof(float)], xc_hi);
+ movaps(ptr[store_addr + 8 * 4 * sizeof(float)], xd_lo);
+ movaps(ptr[store_addr + 9 * 4 * sizeof(float)], xd_hi);
+
+ xorps(xsum_lo, xsum_lo);
+ xorps(xsum_hi, xsum_hi);
+ mulps(xc_lo, xc_lo);
+ mulps(xc_hi, xc_hi);
+ addps(xsum_lo, xc_lo);
+ addps(xsum_hi, xc_hi);
+ mulps(xd_lo, xd_lo);
+ mulps(xd_hi, xd_hi);
+ addps(xsum_lo, xd_lo);
+ addps(xsum_hi, xd_hi); // xsum <- xsum + xa^2+xb^2+xc^2+xd^2+xe^2
+
+ mov(c, J.C - 2);
+ Label lrn_loop;
+ L(lrn_loop);
+
+ if (J.tail != 0) {
+ movups(xe_lo, ptr[src + J.HW * 8]);
+ movups(xe_hi, ptr[src + J.HW * 8 + 4 * sizeof(float)]);
+ andps(xe_lo, xmask_lo);
+ andps(xe_hi, xmask_hi);
+ }
+ else {
+ movups(xe_lo, ptr[src + J.HW * 8]);
+ movups(xe_hi, ptr[src + J.HW * 8 + 4 * sizeof(float)]);
+ }
+
+ nchw_body_sse42(J.tail, J.HW, pk, xmask_lo, xmask_hi,
+ xe_lo, xe_hi,
+ xsum_lo, xsum_hi);
+
+ add(src, J.HW * 4);
+ add(dst, J.HW * 4);
+ if (pk != prop_kind::forward_inference)
+ add(scratch, J.HW * 4);
+ dec(c);
+ cmp(c, 0);
+ jne(lrn_loop, T_NEAR);
+
+ xorps(xe_lo, xe_lo);
+ xorps(xe_hi, xe_hi);
+
+ nchw_body_sse42(J.tail, J.HW, pk, xmask_lo, xmask_hi,
+ xe_lo, xe_hi,
+ xsum_lo, xsum_hi);
+ add(src, J.HW * 4);
+ add(dst, J.HW * 4);
+ if (pk != prop_kind::forward_inference)
+ add(scratch, J.HW * 4);
+
+ nchw_body_sse42(J.tail, J.HW, pk, xmask_lo, xmask_hi,
+ xe_lo, xe_hi,
+ xsum_lo, xsum_hi);
+
+ add(rsp, stack_space_needed);
+
+ this->postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// backward kernel
+template <cpu_isa_t isa>
+jit_uni_lrn_bwd_kernel_f32<isa>::jit_uni_lrn_bwd_kernel_f32(
+ const struct nchw8c_across &J,
+ float A,
+ float B,
+ int use_h_parallel,
+ void *code_ptr,
+ size_t code_size)
+ : jit_generator(code_ptr, code_size)
+ , nalphabeta(-2 * A*B)
+ , use_h_parallelizm(use_h_parallel)
+{
+ Xbyak::Reg64 t = rsp;
+ Xbyak::Reg64 hw = r10;
+
+ Xbyak::Xmm xsrc_prev = xmm1;
+ Xbyak::Xmm xws_prev = xmm2;
+ Xbyak::Xmm xdiffdst_prev = xmm3;
+ Xbyak::Ymm ysrc = ymm4;
+ Xbyak::Ymm yws = ymm5;
+ Xbyak::Ymm ydiffdst = ymm6;
+ Xbyak::Xmm xsrc_next = xmm7;
+ Xbyak::Xmm xws_next = xmm8;
+ Xbyak::Xmm xdiffdst_next = xmm9;
+ Xbyak::Ymm ya = ymm10;
+ Xbyak::Xmm xa = xmm10;
+ Xbyak::Ymm yb = ymm11;
+ Xbyak::Ymm yd = ymm12;
+ Xbyak::Ymm ye = ymm13;
+ Xbyak::Ymm ysum = ymm14;
+ Xbyak::Ymm ydiffsrc = ymm15;
+
+ this->preamble();
+
+ mov(src, ptr[this->param1 + 0]);
+ mov(diffdst, ptr[this->param1 + 8]);
+ mov(workspace, ptr[this->param1 + 16]);
+ mov(diffsrc, ptr[this->param1 + 24]);
+
+ sub(t, 64);
+ mov(imm_addr64, float2int(this->nalphabeta));
+ movq(xnalphabeta, imm_addr64);
+ vbroadcastss(ynalphabeta, xnalphabeta);
+
+ bool is_single = J.version == 3;
+ bool is_first = J.version == -1 || J.version == -2;
+ bool is_last = J.version == +1 || J.version == -2;
+
+ if (is_first || is_single) {
+ vxorps(xsrc_prev, xsrc_prev, xsrc_prev);
+ vmovups(ptr[t + 0], xsrc_prev);
+ }
+ if (is_last || is_single) {
+ vxorps(xsrc_next, xsrc_next, xsrc_next);
+ vmovups(ptr[t + 48], xsrc_next);
+ }
+ mov(hw, this->use_h_parallelizm ? J.W : J.H*J.W);
+ Label lrn_loop;
+ L(lrn_loop);
+ {
+ if (!is_first && !is_single) {
+ vmovups(xws_prev, ptr[workspace - J.H*J.W * 32 + 16]);
+ vmovups(xsrc_prev, ptr[src - J.H*J.W * 32 + 16]);
+ vmovups(xdiffdst_prev, ptr[diffdst - J.H*J.W * 32 + 16]);
+ vmulps(xa, xws_prev, xws_prev);
+ vmulps(xa, xa, xws_prev);
+ vsqrtps(xa, xa);
+ vsqrtps(xa, xa);
+ vmulps(xa, xa, xws_prev);
+ vdivps(xsrc_prev, xsrc_prev, xa);
+ vmulps(xdiffdst_prev, xdiffdst_prev, xsrc_prev);
+ }
+
+ vmovups(ysrc, ptr[src]);
+ vmovups(yws, ptr[workspace]);
+ vmovups(ydiffdst, ptr[diffdst]);
+ vmulps(ya, yws, yws);
+ vmulps(ya, ya, yws);
+ vsqrtps(ya, ya);
+ vsqrtps(ya, ya);
+ vdivps(ydiffsrc, ydiffdst, ya);
+ vdivps(ysum, ydiffsrc, yws);
+ vmulps(ysum, ysum, ysrc);
+
+ if (!is_last && !is_single) {
+ vmovups(xws_next, ptr[workspace + J.H*J.W * 32]);
+ vmovups(xsrc_next, ptr[src + J.H*J.W * 32]);
+ vmovups(xdiffdst_next, ptr[diffdst + J.H*J.W * 32]);
+ vmulps(xa, xws_next, xws_next);
+ vmulps(xa, xa, xws_next);
+ vsqrtps(xa, xa);
+ vsqrtps(xa, xa);
+ vmulps(xa, xa, xws_next);
+ vdivps(xsrc_next, xsrc_next, xa);
+ vdivps(xsrc_next, xsrc_next, xws_next);
+ vmulps(xdiffdst_next, xdiffdst_next, xsrc_next);
+ }
+
+ if (!is_first && !is_single) vmovups(ptr[t + 0], xdiffdst_prev);
+ vmovups(ptr[t + 16], ysum);
+ if (!is_last && !is_single) vmovups(ptr[t + 48], xdiffdst_next);
+
+ vmovups(ya, ptr[t + 16 - 8]);
+ vmovups(yb, ptr[t + 16 - 4]);
+ vaddps(ysum, ysum, ya);
+ vmulps(ysrc, ysrc, ynalphabeta);
+ vaddps(ysum, ysum, yb);
+
+ vmovups(yd, ptr[t + 16 + 4]);
+ vmovups(ye, ptr[t + 16 + 8]);
+ vaddps(ysum, ysum, yd);
+ vaddps(ysum, ysum, ye);
+
+ vfmadd231ps(ydiffsrc, ysum, ysrc);
+
+ vmovups(ptr[diffsrc], ydiffsrc);
+
+ add(src, 32);
+ add(diffsrc, 32);
+ add(diffdst, 32);
+ add(workspace, 32);
+
+ dec(hw);
+ cmp(hw, 0);
+ jne(lrn_loop, T_NEAR);
+ }
+
+ add(t, 64);
+ this->postamble();
+
+ ker = reinterpret_cast<decltype(ker)>(const_cast<uint8_t*>(
+ this->getCode()));
+}
+
+template struct jit_uni_lrn_fwd_kernel_f32<sse42>;
+template struct jit_uni_lrn_fwd_kernel_f32<avx2>;
+template struct jit_uni_lrn_bwd_kernel_f32<avx2>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.hpp
new file mode 100644
index 0000000000..2b3ed43cd4
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_lrn_kernel_f32.hpp
@@ -0,0 +1,183 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_UNI_LRN_KERNEL_F32_HPP
+#define CPU_JIT_UNI_LRN_KERNEL_F32_HPP
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+
+#include "jit_generator.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace Xbyak;
+
+enum params { VECTOR_LENGTH = 8, MAX_LOCAL_SIZE = 32 };
+
+typedef struct {
+ const float *src;
+ float *dst, *scratch;
+} jit_args_fwd_t;
+
+typedef struct {
+ const float *src, *diff_dst, *scratch;
+ float *diff_src;
+} jit_args_bwd_t;
+
+struct nchw8c_across {
+ /* version:
+ * -1: channels 0..7,
+ * 1: channels C-8 .. C-1,
+ * 0: other channels
+ * 3: channels only for this kernel(without prev and next)
+ */
+ int H, W, version;
+ nchw8c_across(int h, int w, int v) : H(h), W(w), version(v) {}
+};
+
+struct nchw8c_within {
+ int H, W, size;
+ nchw8c_within(int h, int w, int s) : H(h), W(w), size(s) {}
+};
+
+struct nchw_across {
+ int C, HW, tail;
+ nchw_across(int c, int hw, int t) : C(c), HW(hw), tail(t) {}
+};
+
+struct nhwc_across {
+ int C;
+ nhwc_across(int c) : C(c) {}
+};
+
+template <cpu_isa_t isa>
+struct jit_uni_lrn_fwd_kernel_f32 : public jit_generator {
+ Xbyak::Reg64 src = rax;
+ Xbyak::Reg64 dst = r8;
+ Xbyak::Reg64 scratch = rdx;
+ Xbyak::Reg64 imm_addr64 = rbx;
+ Xbyak::Reg64 store_addr = rbp;
+
+ Xbyak::Xmm xalpha = xmm0;
+ Xbyak::Ymm yalpha = ymm0;
+ Xbyak::Xmm xk = xmm1;
+ Xbyak::Ymm yk = ymm1;
+
+ float alpha;
+ float k;
+
+ int stack_space_needed = 11 * 4 * sizeof(float) + 16;
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_lrn_fwd_kernel_f32)
+
+ /* cpu specific part */
+ using Vmm = typename utils::conditional<isa == avx2, Ymm, Zmm>::type;
+
+ jit_uni_lrn_fwd_kernel_f32(
+ const struct nchw8c_within &J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void *code_ptr = nullptr,
+ size_t code_size = 4 * Xbyak::DEFAULT_MAX_CODE_SIZE);
+ jit_uni_lrn_fwd_kernel_f32(
+ const struct nchw8c_across &J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void *code_ptr = nullptr,
+ size_t code_size = 1 * Xbyak::DEFAULT_MAX_CODE_SIZE);
+ jit_uni_lrn_fwd_kernel_f32(
+ const struct nhwc_across &J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void *code_ptr = nullptr,
+ size_t code_size = 1 * Xbyak::DEFAULT_MAX_CODE_SIZE);
+ jit_uni_lrn_fwd_kernel_f32(
+ struct nchw_across J,
+ float A,
+ float K,
+ prop_kind_t pk,
+ void* code_ptr = nullptr,
+ size_t code_size = 2 * Xbyak::DEFAULT_MAX_CODE_SIZE);
+
+ void within_body(
+ int hoff, int Hoff, int woff, int Woff, int stride,
+ Xbyak::Ymm ysum, Xbyak::Ymm ydst, Xbyak::Ymm ytmp, Xbyak::Ymm ysum2,
+ prop_kind_t pk);
+ void within_body_sse42(
+ int hoff, int Hoff, int woff, int Woff, int stride, prop_kind_t pk);
+
+
+ void nchw_body(int tail, int HW, prop_kind_t pk,
+ Xbyak::Ymm ymask,
+ Xbyak::Ymm ya,
+ Xbyak::Ymm yb,
+ Xbyak::Ymm yc,
+ Xbyak::Ymm yd,
+ Xbyak::Ymm ye,
+ Xbyak::Ymm ysum);
+ void nchw_body_sse42(int tail, int HW, prop_kind_t pk,
+ Xbyak::Xmm xmask_lo, Xbyak::Xmm xmask_hi,
+ Xbyak::Xmm xe_lo, Xbyak::Xmm xe_hi,
+ Xbyak::Xmm xsum_lo, Xbyak::Xmm xsum_hi);
+ void nchw_tail_sse42(int tail, Xbyak::Reg64 reg_dst,
+ Xbyak::Xmm xtail_lo, Xbyak::Xmm xtail_hi);
+
+ void operator()(jit_args_fwd_t *arg) { ker(arg); }
+ void(*ker)(jit_args_fwd_t *);
+};
+
+template <cpu_isa_t isa>
+struct jit_uni_lrn_bwd_kernel_f32 : public jit_generator {
+ Xbyak::Reg64 src = rax;
+ Xbyak::Reg64 diffsrc = r8;
+ Xbyak::Reg64 diffdst = r9;
+ Xbyak::Reg64 workspace = rdx;
+ Xbyak::Reg64 imm_addr64 = rsi;
+
+ Xbyak::Xmm xnalphabeta = xmm0;
+ Xbyak::Ymm ynalphabeta = ymm0;
+
+ float nalphabeta;
+
+ int use_h_parallelizm;
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_lrn_bwd_kernel_f32)
+
+ jit_uni_lrn_bwd_kernel_f32(
+ const struct nchw8c_across &J,
+ float A,
+ float B,
+ int use_h_parallel,
+ void *code_ptr = nullptr,
+ size_t code_size = 1 * Xbyak::DEFAULT_MAX_CODE_SIZE);
+
+ void operator()(jit_args_bwd_t *arg) { ker(arg); }
+ void(*ker)(jit_args_bwd_t *);
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.cpp
new file mode 100644
index 0000000000..bf8e609d23
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.cpp
@@ -0,0 +1,699 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+* Copyright 2018 YANDEX LLC
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "utils.hpp"
+#include "cpu_pooling_pd.hpp"
+
+#include "jit_uni_pool_kernel_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace Xbyak;
+using namespace alg_kind;
+
+#define GET_OFF(field) offsetof(jit_pool_call_s, field)
+
+template <cpu_isa_t isa>
+status_t jit_uni_pool_kernel_f32<isa>::init_conf(jit_pool_conf_t &jpp,
+ const pooling_pd_t *ppd) {
+ const auto &pd = *ppd->desc();
+ const memory_desc_wrapper src_d(
+ ppd->is_fwd() ? ppd->src_md() : ppd->diff_src_md());
+ const memory_desc_wrapper dst_d(
+ ppd->is_fwd() ? ppd->dst_md() : ppd->diff_dst_md());
+
+ bool args_ok = true
+ && mayiuse(isa)
+ && utils::one_of(pd.alg_kind, pooling_max,
+ pooling_avg_include_padding,
+ pooling_avg_exclude_padding);
+ if (!args_ok) return status::unimplemented;
+
+ const int simd_w = isa == avx512_common ? 16 : 8;
+ const int ndims = src_d.ndims();
+
+ jpp.ndims = ndims;
+ jpp.mb = src_d.dims()[0];
+
+ jpp.c = utils::rnd_up(src_d.dims()[1], simd_w);
+ if (jpp.c > src_d.padded_dims()[1])
+ return status::unimplemented;
+
+ jpp.id = (ndims == 5) ? src_d.dims()[2] : 1;
+ jpp.ih = src_d.dims()[ndims-2];
+ jpp.iw = src_d.dims()[ndims-1];
+ jpp.od = (ndims == 5) ? dst_d.dims()[2] : 1;
+ jpp.oh = dst_d.dims()[ndims-2];
+ jpp.ow = dst_d.dims()[ndims-1];
+
+ jpp.stride_d = (ndims == 5 ) ? pd.strides[0] : 1;
+ jpp.stride_h = pd.strides[ndims-4];
+ jpp.stride_w = pd.strides[ndims-3];
+ jpp.kd = (ndims == 5) ? pd.kernel[0] : 1;
+ jpp.kh = pd.kernel[ndims-4];
+ jpp.kw = pd.kernel[ndims-3];
+
+ jpp.f_pad = (ndims == 5 ) ? pd.padding[0][0] : 0;
+ jpp.t_pad = pd.padding[0][ndims-4];
+ jpp.l_pad = pd.padding[0][ndims-3];
+
+ jpp.alg = pd.alg_kind;
+
+ jpp.is_training = pd.prop_kind == prop_kind::forward_training;
+ jpp.is_backward = pd.prop_kind == prop_kind::backward_data;
+ jpp.ind_dt = ppd->workspace_md()
+ ? ppd->workspace_md()->data_type : data_type::undef;
+
+ jpp.simple_alg = jpp.is_training
+ || IMPLICATION(jpp.is_backward, jpp.kd <= jpp.stride_d);
+
+ jpp.c_block = simd_w;
+
+ jpp.nb_c = jpp.c / jpp.c_block;
+ if (jpp.alg == pooling_max) {
+ jpp.ur_w = isa == avx512_common ? 16 : 4;
+ if (jpp.is_training)
+ jpp.ur_w = isa == avx512_common ? 9 : 3;
+ else if (jpp.is_backward)
+ jpp.ur_w = isa == avx512_common ? 6 : 3;
+ } else {
+ if (jpp.is_backward)
+ jpp.ur_w = isa == avx512_common ? 12 : 6;
+ else
+ jpp.ur_w = isa == avx512_common ? 24 : 12;
+ }
+ if (jpp.ow < jpp.ur_w) jpp.ur_w = jpp.ow;
+ if (jpp.l_pad > jpp.ur_w) return status::unimplemented;
+
+ jpp.ur_w_tail = jpp.ow % jpp.ur_w;
+
+ return status::success;
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_pool_kernel_f32<isa>::maybe_recalculate_divisor(int jj,
+ int ur_w, int pad_l, int pad_r) {
+ if (jpp.alg == pooling_avg_exclude_padding) {
+ int kw = jpp.kw;
+ int stride_w = jpp.stride_w;
+
+ int non_zero_kw = kw;
+ non_zero_kw -= nstl::max(0, pad_l - jj*stride_w);
+ non_zero_kw -= nstl::max(0, pad_r - (ur_w - 1 - jj)*stride_w);
+
+ if (non_zero_kw != prev_kw) {
+ mov(tmp_gpr, float2int((float)non_zero_kw));
+ movq(xmm_tmp, tmp_gpr);
+ uni_vbroadcastss(vmm_tmp, xmm_tmp);
+ uni_vmulps(vmm_tmp, vmm_tmp, vmm_ker_area_h);
+ prev_kw = non_zero_kw;
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_pool_kernel_f32<isa>::avg_step(int ur_w, int pad_l,
+ int pad_r) {
+
+ int iw = jpp.iw;
+ int kw = jpp.kw;
+ int stride_w = jpp.stride_w;
+ int c_block = jpp.c_block;
+ Label kd_label, kh_label;
+
+ for (int jj = 0; jj < ur_w; jj++) {
+ if (jpp.is_backward) {
+ uni_vmovups(vreg(jj), ptr[reg_output + sizeof(float)*jj*c_block]);
+ maybe_recalculate_divisor(jj, ur_w, pad_l, pad_r);
+ uni_vdivps(vreg(jj), vreg(jj), vmm_tmp);
+ } else {
+ uni_vpxor(vreg(jj), vreg(jj), vreg(jj));
+ }
+ }
+
+ if (jpp.simple_alg && jpp.ndims == 5) {
+ push(reg_input);
+ push(reg_output);
+ mov(aux_reg_input_d, reg_input);
+ mov(ki, ptr[reg_param + GET_OFF(kd_padding)]);
+ L(kd_label);
+ mov(aux_reg_input, aux_reg_input_d);
+ } else {
+ mov(aux_reg_input, reg_input);
+ }
+
+ xor_(kj, kj);
+ L(kh_label);
+ {
+ for (int ki = 0; ki < kw; ki++) {
+ int jj_start = nstl::max(0, pad_l - ki);
+ int jj_end = ur_w
+ - utils::div_up(nstl::max(0, ki + pad_r - (kw-1)), stride_w);
+ for (int jj = jj_start; jj < jj_end; jj++) {
+ int aux_input_offset = (ki+jj*stride_w-pad_l)* c_block;
+ if (aux_input_offset > iw * c_block)
+ continue;
+ int input_offset = sizeof(float)*aux_input_offset;
+ if (jpp.is_backward) {
+ uni_vmovups(vreg(ur_w+jj),
+ ptr[aux_reg_input + input_offset]);
+ uni_vaddps(vreg(ur_w+jj), vreg(ur_w+jj), vreg(jj));
+ uni_vmovups(vmmword[aux_reg_input + input_offset],
+ vreg(ur_w+jj));
+ } else {
+ uni_vaddps(vreg(jj), vreg(jj),
+ ptr[aux_reg_input + input_offset]);
+ }
+ }
+ }
+ add(aux_reg_input, sizeof(float) * iw * c_block);
+ inc(kj);
+ cmp(kj, reg_kh);
+ jl(kh_label, T_NEAR);
+ }
+
+ if (jpp.simple_alg && jpp.ndims == 5)
+ {
+ add(aux_reg_input_d, sizeof(float) * jpp.ih * iw * c_block);
+ dec(ki);
+ cmp(ki, 0);
+ jg(kd_label, T_NEAR);
+ pop(reg_output);
+ pop(reg_input);
+ }
+
+ if (!jpp.is_backward) {
+ for (int jj = 0; jj < ur_w; jj++) {
+ maybe_recalculate_divisor(jj, ur_w, pad_l, pad_r);
+ uni_vdivps(vreg(jj), vreg(jj), vmm_tmp);
+ uni_vmovups(vmmword[reg_output + sizeof(float)*jj*c_block],
+ vreg(jj));
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_pool_kernel_f32<isa>::max_step_fwd(int ur_w, int pad_l,
+ int pad_r) {
+ int iw = jpp.iw;
+ int kw = jpp.kw;
+ int stride_w = jpp.stride_w;
+ int c_block = jpp.c_block;
+ Label kd_label, kh_label;
+
+ mov(tmp_gpr, float2int(nstl::numeric_limits<float>::lowest()));
+ movq(xmm_tmp, tmp_gpr);
+ uni_vbroadcastss(vmm_tmp, xmm_tmp);
+
+ for (int jj = 0; jj < ur_w; jj++) {
+ uni_vmovups(vreg(jj), vmm_tmp);
+ if (jpp.is_training)
+ uni_vpxor(vreg(2*ur_w+jj), vreg(2*ur_w+jj), vreg(2*ur_w+jj));
+ }
+ if (jpp.is_training)
+ {
+ movq(xmm_tmp, reg_k_shift);
+ uni_vpbroadcastd(vmm_k_offset, xmm_tmp);
+ }
+
+ if (jpp.ndims == 5) {
+ push(reg_input);
+ push(reg_output);
+ mov(aux_reg_input_d, reg_input);
+ mov(ki, ptr[reg_param + GET_OFF(kd_padding)]);
+ L(kd_label);
+ mov(aux_reg_input, aux_reg_input_d);
+ } else {
+ mov(aux_reg_input, reg_input);
+ }
+ xor_(kj, kj);
+ L(kh_label);
+ {
+ for (int ki = 0; ki < kw; ki++) {
+ int jj_start = nstl::max(0, pad_l - ki);
+ int jj_end = ur_w
+ - utils::div_up(nstl::max(0, ki + pad_r - (kw-1)), stride_w);
+ for (int jj = jj_start; jj < jj_end; jj++) {
+ int aux_input_offset = (ki+jj*stride_w-pad_l)* c_block;
+ if (aux_input_offset > iw * c_block)
+ continue;
+ int input_offset = sizeof(float)*aux_input_offset;
+ uni_vmovups(vreg(ur_w+jj), ptr[aux_reg_input + input_offset]);
+ if (isa == sse42) {
+ movups(vmm_mask, vreg(jj));
+ cmpps(vmm_mask, vreg(ur_w+jj), _cmp_lt_os);
+ blendvps(vreg(jj), vreg(ur_w+jj));
+ if (jpp.is_training)
+ blendvps(vreg(2*ur_w+jj), vmm_k_offset);
+ } else if (isa == avx) {
+ vcmpps(vreg(3*ur_w+jj), vreg(jj), vreg(ur_w+jj),
+ _cmp_lt_os);
+ vblendvps(vreg(jj), vreg(jj), vreg(ur_w+jj),
+ vreg(3*ur_w+jj));
+ if (jpp.is_training)
+ vblendvps(vreg(2*ur_w+jj), vreg(2*ur_w+jj),
+ vmm_k_offset, vreg(3*ur_w+jj));
+ } else {
+ vcmpps(k_store_mask, vreg(jj), vreg(ur_w+jj), _cmp_lt_os);
+ vblendmps(vreg(jj) | k_store_mask, vreg(jj), vreg(ur_w+jj));
+ if (jpp.is_training)
+ vblendmps(vreg(2*ur_w+jj) | k_store_mask,
+ vreg(2*ur_w+jj), vmm_k_offset);
+ }
+ }
+ if (jpp.is_training) {
+ if (isa == avx && !mayiuse(avx2)) {
+ avx_vpadd1(vmm_k_offset, vmm_one, xmm_tmp);
+ } else {
+ uni_vpaddd(vmm_k_offset, vmm_k_offset, vmm_one);
+ }
+ }
+ }
+ add(aux_reg_input, sizeof(float) * iw * c_block);
+ inc(kj);
+ cmp(kj, reg_kh);
+ jl(kh_label, T_NEAR);
+ }
+
+ if (jpp.ndims == 5)
+ {
+ add(aux_reg_input_d, sizeof(float) * jpp.ih * iw * c_block);
+ if (jpp.is_training) {
+ mov(tmp_gpr, ptr[reg_param + GET_OFF(kd_padding_shift)]);
+ movq(xmm_tmp, tmp_gpr);
+ uni_vpbroadcastd(vmm_tmp, xmm_tmp);
+ if (isa == avx && !mayiuse(avx2)) {
+ Xmm t(vmm_mask.getIdx());
+ avx_vpadd1(vmm_k_offset, xmm_tmp, t);
+ } else {
+ uni_vpaddd(vmm_k_offset, vmm_k_offset, vmm_tmp);
+ }
+ }
+
+ dec(ki);
+ cmp(ki, 0);
+ jg(kd_label, T_NEAR);
+ pop(reg_output);
+ pop(reg_input);
+ }
+
+ for (int jj = 0; jj < ur_w; jj++) {
+ uni_vmovups(vmmword[reg_output + sizeof(float)*jj*c_block], vreg(jj));
+ if (jpp.is_training) {
+ const size_t step_index
+ = jj * c_block * types::data_type_size(jpp.ind_dt);
+
+ auto x = xreg(2 * ur_w + jj);
+ if (jpp.ind_dt == data_type::u8) {
+ if (isa == sse42) {
+ for (int i = 0; i < 4; ++i)
+ pextrb(ptr[reg_index + step_index + i], x, 4*i);
+ } else if (isa == avx) {
+ auto y = yreg(2 * ur_w + jj);
+ if (jj == 0) {
+ movd(xmm_tmp, reg_shuf_mask);
+ uni_vpbroadcastd(vmm_tmp, xmm_tmp);
+ }
+ if (mayiuse(avx2)) {
+ vpshufb(y, y, vmm_tmp);
+ movd(ptr[reg_index + step_index], x);
+ vperm2i128(y, y, y, 0x1u);
+ movd(ptr[reg_index + step_index + 4], x);
+ } else {
+ Xmm t(vmm_mask.getIdx());
+ vextractf128(t, y, 0);
+ vpshufb(t, t, xmm_tmp);
+ movd(ptr[reg_index + step_index], t);
+ vextractf128(t, y, 1);
+ vpshufb(t, t, xmm_tmp); // ymm_tmp[:128]==ymm_tmp[127:0]
+ movd(ptr[reg_index + step_index + 4], t);
+ }
+ } else {
+ auto v = vreg(2 * ur_w + jj);
+ vpmovusdb(x, v);
+ vmovups(ptr[reg_index + step_index], v | k_index_mask);
+ }
+ } else {
+ uni_vmovups(ptr[reg_index + step_index], vreg(2*ur_w+jj));
+ }
+ }
+ }
+}
+
+template <cpu_isa_t isa>
+inline void jit_uni_pool_kernel_f32<isa>::max_step_bwd(int ur_w, int pad_l,
+ int pad_r) {
+
+ int iw = jpp.iw;
+ int kw = jpp.kw;
+ int stride_w = jpp.stride_w;
+ int c_block = jpp.c_block;
+ Label kd_label, kh_label;
+
+ for (int jj = 0; jj < ur_w; jj++) {
+ uni_vmovups(vreg(jj), ptr[reg_output + sizeof(float)*jj*c_block]);
+
+ const size_t step_index
+ = jj * c_block * types::data_type_size(jpp.ind_dt);
+ if (jpp.ind_dt == data_type::u8) {
+ if (isa == sse42) {
+ movd(xreg(ur_w+jj), ptr[reg_index + step_index]);
+ pmovzxbd(vreg(ur_w+jj), xreg(ur_w+jj));
+ } else if (isa == avx) {
+ movq(xreg(ur_w+jj), ptr[reg_index + step_index]);
+ if (!mayiuse(avx2)) {
+ avx_pmovzxbd(vreg(ur_w+jj), xreg(ur_w+jj), xmm_tmp);
+ } else {
+ vpmovzxbd(vreg(ur_w+jj), xreg(ur_w+jj));
+ }
+ } else {
+ vmovups(vreg(ur_w+jj) | k_index_mask,
+ ptr[reg_index + step_index]);
+ vpmovzxbd(vreg(ur_w+jj), xreg(ur_w+jj));
+ }
+ } else {
+ uni_vmovups(vreg(ur_w+jj), ptr[reg_index + step_index]);
+ }
+ }
+ movq(xmm_tmp, reg_k_shift);
+ uni_vpbroadcastd(vmm_k_offset, xmm_tmp);
+
+ if (jpp.simple_alg && jpp.ndims == 5) {
+ push(reg_input);
+ push(reg_output);
+ if (isa == sse42) {
+ // Save rdi since it is used in maskmovdqu
+ assert(dst_ptr == rdi);
+ push(dst_ptr);
+ }
+ mov(aux_reg_input_d, reg_input);
+ mov(ki, ptr[reg_param + GET_OFF(kd_padding)]);
+ mov(reg_kd_pad_shift, ptr[reg_param + GET_OFF(kd_padding_shift)]);
+ L(kd_label);
+ mov(aux_reg_input, aux_reg_input_d);
+ } else {
+ mov(aux_reg_input, reg_input);
+ }
+
+ xor_(kj, kj);
+ L(kh_label);
+ {
+ for (int ki = 0; ki < kw; ki++) {
+ int jj_start = nstl::max(0, pad_l - ki);
+ int jj_end = ur_w
+ - utils::div_up(nstl::max(0, ki + pad_r - (kw-1)), stride_w);
+ for (int jj = jj_start; jj < jj_end; jj++) {
+ int aux_input_offset = (ki+jj*stride_w-pad_l)* c_block;
+ if (aux_input_offset > iw * c_block)
+ continue;
+ int input_offset = sizeof(float)*aux_input_offset;
+ uni_vmovups(vreg(2*ur_w+jj), ptr[aux_reg_input + input_offset]);
+ if (isa == sse42) {
+ mov(dst_ptr, aux_reg_input);
+ add(dst_ptr, input_offset);
+
+ movups(vreg(3*ur_w+jj), vreg(ur_w+jj));
+ pcmpeqd(vreg(3*ur_w+jj), vmm_k_offset);
+ addps(vreg(2*ur_w+jj), vreg(jj));
+ maskmovdqu(vreg(2*ur_w+jj), vreg(3*ur_w+jj));
+ } else if (isa == avx) {
+ if (mayiuse(avx2)) {
+ vpcmpeqd(vreg(3*ur_w+jj), vreg(ur_w+jj), vmm_k_offset);
+ } else {
+ avx_pcmpeqd(vreg(3*ur_w+jj), vreg(ur_w+jj), vmm_k_offset, xmm_tmp);
+ }
+ vaddps(vreg(2*ur_w+jj), vreg(2*ur_w+jj), vreg(jj));
+ vmaskmovps(vmmword[aux_reg_input + input_offset],
+ vreg(3*ur_w+jj), vreg(2*ur_w+jj));
+ } else {
+ vpcmpeqd(k_store_mask, vreg(ur_w+jj), vmm_k_offset);
+ vblendmps(vmm_tmp | k_store_mask | T_z, vreg(jj), vreg(jj));
+ vaddps(vreg(2*ur_w+jj), vreg(2*ur_w+jj), vmm_tmp);
+ vmovups(vmmword[aux_reg_input +
+ sizeof(float)*aux_input_offset], vreg(2*ur_w+jj));
+ }
+ }
+ if (isa == avx && !mayiuse(avx2)) {
+ avx_vpadd1(vmm_k_offset, vmm_one, xmm_tmp);
+ } else {
+ uni_vpaddd(vmm_k_offset, vmm_k_offset, vmm_one);
+ }
+ }
+ add(aux_reg_input, sizeof(float) * iw * c_block);
+ inc(kj);
+ cmp(kj, reg_kh);
+ jl(kh_label, T_NEAR);
+ }
+ if (jpp.simple_alg && jpp.ndims == 5)
+ {
+ add(aux_reg_input_d, sizeof(float) * jpp.ih * iw * c_block);
+
+ mov(tmp_gpr, reg_kd_pad_shift);
+ movq(xmm_tmp, tmp_gpr);
+ uni_vpbroadcastd(vmm_tmp, xmm_tmp);
+ if (isa == avx && !mayiuse(avx2)) {
+ Xmm t(vmm_mask.getIdx());
+ avx_vpadd1(vmm_k_offset, vmm_tmp, t);
+ } else {
+ uni_vpaddd(vmm_k_offset, vmm_k_offset, vmm_tmp);
+ }
+
+ dec(ki);
+ cmp(ki, 0);
+ jg(kd_label, T_NEAR);
+ if (isa == sse42) {
+ // Save rdi since it is used in maskmovdqu
+ assert(dst_ptr == rdi);
+ pop(dst_ptr);
+ }
+ pop(reg_output);
+ pop(reg_input);
+ }
+}
+
+template <cpu_isa_t isa>
+void jit_uni_pool_kernel_f32<isa>::maybe_zero_diff_src() {
+ assert(jpp.c_block * sizeof(float) % cpu_isa_traits<isa>::vlen == 0);
+ Label l_skip, l_zero;
+
+ auto reg_oh = tmp_gpr;
+ mov(reg_oh, ptr[reg_param + GET_OFF(oh)]);
+ cmp(reg_oh, 0);
+ jz(l_skip, T_NEAR);
+
+ if (jpp.ndims == 5) {
+ mov(zero_size, ptr[reg_param + GET_OFF(oh)]);
+ mov(tmp_gpr, jpp.ih * jpp.iw * jpp.c_block * sizeof(float));
+ imul(zero_size, tmp_gpr);
+ }
+
+ auto vzero = vmm_tmp;
+ uni_vpxor(vzero, vzero, vzero);
+
+ auto reg_off = tmp_gpr;
+ xor_(reg_off, reg_off);
+
+ L(l_zero);
+ {
+ const int dim = jpp.iw * jpp.c_block * sizeof(float);
+ for (int i = 0; i < dim; i += cpu_isa_traits<isa>::vlen)
+ uni_vmovups(ptr[reg_input + reg_off + i], vzero);
+ add(reg_off, dim);
+ if (jpp.ndims == 5) cmp(reg_off, zero_size);
+ else cmp(reg_off, jpp.ih * dim);
+ jl(l_zero, T_NEAR);
+ }
+
+ L(l_skip);
+}
+
+template <cpu_isa_t isa>
+void jit_uni_pool_kernel_f32<isa>::generate() {
+
+ this->preamble();
+
+ int ow = jpp.ow;
+ int iw = jpp.iw;
+ int kw = jpp.kw;
+ int kh = jpp.kh;
+ int ur_w = jpp.ur_w;
+ int c_block = jpp.c_block;
+ int stride_w = jpp.stride_w;
+ int l_pad = jpp.l_pad;
+ int ur_w_tail = jpp.ur_w_tail;
+
+ int n_oi = ow / ur_w;
+
+ prev_kw = 0;
+
+ int vlen = cpu_isa_traits<isa>::vlen;
+
+#if defined(_WIN32)
+ // Always mimic the Unix ABI (see the note about maskmovdqu in the header
+ // file).
+ xor_(rdi, rcx);
+ xor_(rcx, rdi);
+ xor_(rdi, rcx);
+#endif
+
+ mov(reg_input, ptr[reg_param + GET_OFF(src)]);
+ mov(reg_output, ptr[reg_param + GET_OFF(dst)]);
+ if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward))
+ mov(reg_index, ptr[reg_param + GET_OFF(indices)]);
+ mov(reg_kh, ptr[reg_param + GET_OFF(kh_padding)]);
+ mov(reg_k_shift, ptr[reg_param + GET_OFF(kh_padding_shift)]);
+ mov(reg_ker_area_h, ptr[reg_param + GET_OFF(ker_area_h)]);
+
+ if (jpp.is_backward)
+ maybe_zero_diff_src();
+
+ if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward)) {
+ mov(tmp_gpr, 1);
+ movq(xmm_one, tmp_gpr);
+ uni_vpbroadcastd(vmm_one, xmm_one);
+
+ if (isa == avx) {
+ mov(reg_shuf_mask, 0x0c080400);
+ } else if (isa >= avx512_common) {
+ mov(tmp_gpr.cvt32(), 0x000f);
+ kmovw(k_index_mask, tmp_gpr.cvt32());
+ }
+ }
+
+ int r_pad = nstl::max(0, ((ow-1)*stride_w) + kw - 1 - (iw + l_pad - 1));
+ int r_pad1 = (ur_w*n_oi - 1)*stride_w + kw - 1 - (iw + l_pad - 1);
+ if (r_pad1 > 0) n_oi--;
+
+ if (jpp.alg == pooling_avg_exclude_padding) {
+ movq(xmm_ker_area_h, reg_ker_area_h);
+ uni_vpbroadcastd(vmm_ker_area_h, xmm_ker_area_h);
+ }
+
+ if (jpp.alg == pooling_avg_include_padding) {
+ mov(tmp_gpr, float2int((float)(kw * kh * jpp.kd)));
+ movq(xmm_tmp, tmp_gpr);
+ uni_vpbroadcastd(vmm_tmp, xmm_tmp);
+ }
+ if (l_pad > 0) {
+ n_oi--;
+ if (n_oi < 0 && r_pad1 > 0) {
+ step(ur_w, l_pad, r_pad1);
+ } else {
+ step(ur_w, l_pad, 0);
+ }
+
+ if (isa == sse42) {
+ if (n_oi < 0 && r_pad1 > 0) {
+ step_high_half(ur_w, l_pad, r_pad1);
+ } else {
+ step_high_half(ur_w, l_pad, 0);
+ }
+ }
+
+ if (isa == sse42) {
+ add(reg_input, sizeof(float)*(ur_w*stride_w-l_pad)*c_block - vlen);
+ add(reg_output, sizeof(float)*ur_w*c_block - vlen);
+ if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward))
+ add(reg_index, (2 * ur_w - 1) * c_block / 2
+ * types::data_type_size(jpp.ind_dt));
+ } else {
+ add(reg_input, sizeof(float)*(ur_w*stride_w - l_pad)*c_block);
+ add(reg_output, sizeof(float)*ur_w*c_block);
+ if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward))
+ add(reg_index, ur_w * c_block
+ * types::data_type_size(jpp.ind_dt));
+ }
+ }
+
+ xor_(oi_iter, oi_iter);
+ if (n_oi > 0) {
+ Label ow_loop;
+ L(ow_loop); {
+ step(ur_w, 0, 0);
+
+ if (isa == sse42) {
+ step_high_half(ur_w, 0, 0);
+ }
+
+ if (isa == sse42) {
+ add(reg_input, sizeof(float)*ur_w*stride_w*c_block - vlen);
+ add(reg_output, sizeof(float)*ur_w*c_block - vlen);
+ if (jpp.alg == pooling_max &&
+ (jpp.is_training || jpp.is_backward))
+ add(reg_index, (2 * ur_w - 1) * c_block / 2
+ * types::data_type_size(jpp.ind_dt));
+ } else {
+ add(reg_input, sizeof(float)*ur_w*stride_w*c_block);
+ add(reg_output, sizeof(float)*ur_w*c_block);
+ if (jpp.alg == pooling_max &&
+ (jpp.is_training || jpp.is_backward))
+ add(reg_index, ur_w * c_block
+ * types::data_type_size(jpp.ind_dt));
+ }
+
+ inc(oi_iter);
+ cmp(oi_iter, n_oi);
+ jl(ow_loop, T_NEAR);
+ }
+ }
+
+ if (r_pad1 > 0 && n_oi >= 0) {
+ step(ur_w, 0, r_pad1);
+
+ if (isa == sse42) {
+ step_high_half(ur_w, 0, r_pad1);
+ }
+
+ if (isa == sse42) {
+ add(reg_input, sizeof(float)*ur_w*stride_w*c_block - vlen);
+ add(reg_output, sizeof(float)*ur_w*c_block - vlen);
+ if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward))
+ add(reg_index, (2 * ur_w - 1) * c_block / 2
+ * types::data_type_size(jpp.ind_dt));
+ } else {
+ add(reg_input, sizeof(float)*ur_w*stride_w*c_block);
+ add(reg_output, sizeof(float)*ur_w*c_block);
+ if (jpp.alg == pooling_max && (jpp.is_training || jpp.is_backward))
+ add(reg_index, ur_w * c_block
+ * types::data_type_size(jpp.ind_dt));
+ }
+ }
+
+ if (ur_w_tail != 0) {
+ step(ur_w_tail, 0, r_pad);
+
+ if (isa == sse42) {
+ step_high_half(ur_w_tail, 0, r_pad);
+ }
+ }
+
+ this->postamble();
+}
+
+template struct jit_uni_pool_kernel_f32<sse42>;
+template struct jit_uni_pool_kernel_f32<avx>; // implements both <avx> and <avx2>
+template struct jit_uni_pool_kernel_f32<avx512_common>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.hpp
new file mode 100644
index 0000000000..992b526587
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.hpp
@@ -0,0 +1,192 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+* Copyright 2018 YANDEX LLC
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_UNI_POOL_KERNEL_F32_HPP
+#define JIT_UNI_POOL_KERNEL_F32_HPP
+
+#include <cfloat>
+
+#include "c_types_map.hpp"
+#include "pooling_pd.hpp"
+#include "type_helpers.hpp"
+
+#include "jit_generator.hpp"
+#include "jit_primitive_conf.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace Xbyak;
+
+template <cpu_isa_t isa>
+struct jit_uni_pool_kernel_f32: public jit_generator {
+ jit_uni_pool_kernel_f32(jit_pool_conf_t ajpp): jpp(ajpp)
+ {
+ this->generate();
+ jit_ker = (decltype(jit_ker))this->getCode();
+ }
+
+ jit_pool_conf_t jpp;
+
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_pool_kernel_f32)
+
+ void operator()(jit_pool_call_s *arg) { jit_ker(arg); }
+ static status_t init_conf(jit_pool_conf_t &jbp, const pooling_pd_t *ppd);
+
+private:
+ using Vmm = typename utils::conditional3<isa == sse42, Xmm, isa == avx,
+ Ymm, Zmm>::type;
+ Xmm xreg(int idx) { return Xmm((isa == avx512_common ? 31 : 15) - idx); }
+ Ymm yreg(int idx) { return Ymm(xreg(idx).getIdx()); }
+ Vmm vreg(int idx) { return Vmm(xreg(idx).getIdx()); }
+
+ const AddressFrame &vmmword = (isa == sse42) ? xword :
+ (isa == avx) ? yword : zword;
+
+ Xmm vmm_mask = Xmm(0);
+ Xmm xmm_ker_area_h = Xmm(2);
+ Xmm xmm_one = Xmm(2);
+ Xmm xmm_tmp = Xmm(3);
+
+ Vmm vmm_ker_area_h = Vmm(2);
+ Vmm vmm_one = Vmm(2);
+ Vmm vmm_tmp = Vmm(3);
+
+ Vmm vmm_k_offset = Vmm(1);
+
+ Opmask k_index_mask = Opmask(6);
+ Opmask k_store_mask = Opmask(7);
+
+ // Here be some (tame) dragons. This kernel does not follow the regular
+ // OS-agnostic ABI pattern because when isa is sse42 it uses maskmovdqu
+ // instruction which has its destination hardcoded in rdi. Therefore:
+ // - all registers are hardcoded
+ // - on Windows rdi and rcx are swapped to mimic the Unix x86_64 ABI
+ //
+ // While this is only required by the backward pass, the quirk above
+ // is applied to the forward pass as well to keep things simpler.
+
+ using reg64_t = const Xbyak::Reg64;
+ reg64_t reg_param = rdi; // Always mimic the Unix ABI
+ reg64_t reg_input = r8;
+ reg64_t aux_reg_input = r9;
+ reg64_t reg_index = r10;
+ reg64_t reg_output = r12;
+ reg64_t reg_kd_pad_shift = r13;
+ reg64_t dst_ptr = rdi; // Must be rdi due to maskmovdqu
+
+ reg64_t kj = r14;
+ reg64_t oi_iter = r15;
+ reg64_t reg_kh = rax;
+ reg64_t reg_k_shift = rbx;
+ reg64_t tmp_gpr = rcx; // Must be rcx because rdi is used above
+ reg64_t reg_ker_area_h = rdx;
+
+ reg64_t zero_size = r15;
+ reg64_t ki = r12;
+ reg64_t aux_reg_input_d = r8;
+
+ Xbyak::Reg32 reg_shuf_mask = esi;
+
+ int prev_kw;
+ void (*jit_ker)(jit_pool_call_s *);
+
+ void maybe_recalculate_divisor(int jj, int ur_w, int pad_l, int pad_r);
+ void avg_step(int ur_w, int pad_l, int pad_r);
+ void max_step_fwd(int ur_w, int pad_l, int pad_r);
+ void max_step_bwd(int ur_w, int pad_l, int pad_r);
+
+ void maybe_zero_diff_src();
+
+ void step(int ur_w, int pad_l, int pad_r) {
+ if (jpp.alg == alg_kind::pooling_max) {
+ if(jpp.is_backward)
+ max_step_bwd(ur_w, pad_l, pad_r);
+ else
+ max_step_fwd(ur_w, pad_l, pad_r);
+ }
+ else
+ avg_step(ur_w, pad_l, pad_r);
+ }
+
+ void step_high_half(int ur_w, int pad_l, int pad_r) {
+ add(reg_input, sizeof(float) * 4);
+ add(reg_output, sizeof(float) * 4);
+ if (jpp.alg == alg_kind::pooling_max &&
+ (jpp.is_training || jpp.is_backward))
+ add(reg_index, types::data_type_size(jpp.ind_dt) * 4);
+
+ step(ur_w, pad_l, pad_r);
+ }
+
+ void generate();
+
+ void avx_vpadd1(const Ymm& y0, const Xmm& x1, const Xmm& xtmp) {
+ assert(y0.getIdx() != x1.getIdx());
+ vextractf128(xtmp, y0, 0);
+ vpaddd(xtmp, xtmp, x1);
+ vinsertf128(y0, y0, xtmp, 0);
+ vextractf128(xtmp, y0, 1);
+ vpaddd(xtmp, xtmp, x1);
+ vinsertf128(y0, y0, xtmp, 1);
+ }
+
+ void avx_vpadd1(const Xmm& x0, const Xmm& x1, const Xmm&) {
+ assert(false /*function should not be used*/);
+ paddd(x0, x1);
+ }
+
+ void avx_pmovzxbd(const Ymm& y0, const Xmm& x1, const Xmm& xtmp) {
+ Xmm x0(y0.getIdx());
+ pshufd(xmm_tmp, x1, 1);
+ pmovzxbd(x0, x1);
+ pmovzxbd(xmm_tmp, xmm_tmp);
+ vinsertf128(y0, y0, xmm_tmp, 1);
+ }
+
+ void avx_pmovzxbd(const Xmm& x0, const Xmm& x1, const Xmm&) {
+ assert(false /*function should not be used*/);
+ pmovzxbd(x0, x1);
+ }
+
+ void avx_pcmpeqd(const Ymm& y0, const Ymm& y1, const Ymm& y2, const Xmm& xtmp) {
+ assert(y0.getIdx() != y1.getIdx());
+ assert(y0.getIdx() != y2.getIdx());
+ Xmm x0(y0.getIdx());
+ Xmm x2(y2.getIdx());
+ vextractf128(x0, y1, 1);
+ vextractf128(xtmp, y2, 1);
+ pcmpeqd(xtmp, x0);
+ vextractf128(x0, y1, 0);
+ pcmpeqd(x0, x2);
+ vinsertf128(y0, y0, xtmp, 1);
+ }
+
+ void avx_pcmpeqd(const Xmm& x0, const Xmm& x1, const Xmm&, const Xmm&) {
+ assert(false /*function should not be used*/);
+ pcmpeqd(x0, x1);
+ }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.cpp
new file mode 100644
index 0000000000..afbcf996d8
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.cpp
@@ -0,0 +1,264 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn_types.h"
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "nstl.hpp"
+
+#include "jit_uni_pooling.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <cpu_isa_t isa>
+void jit_uni_pooling_fwd_t<isa>::execute_forward(const data_t *src,
+ data_t *dst, char *indices) const {
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper indices_d(pd()->workspace_md());
+ const size_t ind_dt_size = indices
+ ? types::data_type_size(indices_d.data_type()) : 0;
+
+ const auto &jpp = pd()->jpp_;
+
+ auto ker = [&](int n, int b_c, int oh) {
+ auto arg = jit_pool_call_s();
+
+ const int ij = oh * jpp.stride_h;
+ const int i_t_overflow = nstl::max(0, jpp.t_pad-ij);
+ const int i_b_overflow = nstl::max(jpp.ih, ij+jpp.kh-jpp.t_pad)-jpp.ih;
+ const int ih = nstl::max(ij - jpp.t_pad, 0);
+
+ arg.src = &src[src_d.blk_off(n, b_c, ih)];
+ arg.dst = &dst[dst_d.blk_off(n, b_c, oh)];
+ if (indices) {
+ const size_t ind_off = indices_d.blk_off(n, b_c, oh);
+ arg.indices = &indices[ind_off * ind_dt_size];
+ }
+ arg.oh = oh == 0;
+ arg.kh_padding = jpp.kh - i_t_overflow - i_b_overflow;
+ arg.kh_padding_shift = i_t_overflow*jpp.kw;
+ arg.kw_padding = 0;
+ arg.ker_area_h = (float)(jpp.kh -
+ nstl::max(0, oh*jpp.stride_h - jpp.t_pad + jpp.kh - jpp.ih) -
+ nstl::max(0, jpp.t_pad - oh*jpp.stride_h));
+ (*kernel_)(&arg);
+ };
+
+ parallel_nd(jpp.mb, jpp.nb_c, jpp.oh,
+ [&](int n, int b_c, int oh) {
+ ker(n, b_c, oh);
+ });
+}
+
+template <cpu_isa_t isa>
+void jit_uni_pooling_fwd_t<isa>::execute_forward_3d(const data_t *src,
+ data_t *dst, char *indices) const {
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper indices_d(pd()->workspace_md());
+ const size_t ind_dt_size = indices
+ ? types::data_type_size(indices_d.data_type()) : 0;
+
+ const auto &jpp = pd()->jpp_;
+
+ auto ker = [&](int n, int b_c, int od, int oh, int id, int d_t_overflow,
+ int d_b_overflow) {
+ auto arg = jit_pool_call_s();
+
+ const int ij = oh * jpp.stride_h;
+ const int i_t_overflow = nstl::max(0, jpp.t_pad-ij);
+ const int i_b_overflow = nstl::max(jpp.ih, ij+jpp.kh-jpp.t_pad)-jpp.ih;
+ const int ih = nstl::max(ij - jpp.t_pad, 0);
+
+ arg.src = &src[src_d.blk_off(n, b_c, id, ih)];
+ arg.dst = &dst[dst_d.blk_off(n, b_c, od, oh)];
+ if (indices) {
+ const size_t ind_off = indices_d.blk_off(n, b_c, od, oh);
+ arg.indices = &indices[ind_off * ind_dt_size];
+ }
+ arg.oh = (oh + od == 0);
+ arg.kd_padding = jpp.kd - d_t_overflow - d_b_overflow;
+ arg.kh_padding = jpp.kh - i_t_overflow - i_b_overflow;
+ arg.kh_padding_shift = i_t_overflow*jpp.kw + d_t_overflow*jpp.kw*jpp.kh;
+ arg.kd_padding_shift = (i_t_overflow + i_b_overflow)*jpp.kw;
+ arg.kw_padding = 0;
+ arg.ker_area_h = (float)(jpp.kh -
+ nstl::max(0, oh*jpp.stride_h - jpp.t_pad + jpp.kh - jpp.ih) -
+ nstl::max(0, jpp.t_pad - oh*jpp.stride_h)) * (jpp.kd -
+ nstl::max(0, od*jpp.stride_d - jpp.f_pad + jpp.kd - jpp.id) -
+ nstl::max(0, jpp.f_pad - od*jpp.stride_d));
+
+
+ (*kernel_)(&arg);
+ };
+
+ parallel_nd(jpp.mb, jpp.nb_c, jpp.od,
+ [&](int n, int b_c, int od) {
+ const int ik = od * jpp.stride_d;
+ const int d_t_overflow = nstl::max(0, jpp.f_pad-ik);
+ const int d_b_overflow = nstl::max(jpp.id, ik+jpp.kd-jpp.f_pad)
+ -jpp.id;
+ const int id = nstl::max(ik - jpp.f_pad, 0);
+ for (int oh = 0; oh < jpp.oh; ++oh) {
+ ker(n, b_c, od, oh, id, d_t_overflow, d_b_overflow);
+ }
+ });
+}
+
+template <cpu_isa_t isa>
+void jit_uni_pooling_bwd_t<isa>::execute_backward(const data_t *diff_dst,
+ const char *indices, data_t *diff_src) const {
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper indices_d(pd()->workspace_md());
+ const size_t ind_dt_size = indices
+ ? types::data_type_size(indices_d.data_type()) : 0;
+
+ const auto &jpp = pd()->jpp_;
+
+ auto ker = [&](int n, int b_c, int oh) {
+ auto arg = jit_pool_call_s();
+
+ const int ij = oh * jpp.stride_h;
+ const int i_t_overflow = nstl::max(0, jpp.t_pad-ij);
+ const int i_b_overflow = nstl::max(jpp.ih, ij+jpp.kh-jpp.t_pad)-jpp.ih;
+ const int ih = nstl::max(ij - jpp.t_pad, 0);
+
+ arg.src = &diff_src[diff_src_d.blk_off(n, b_c, ih)];
+ arg.dst = &diff_dst[diff_dst_d.blk_off(n, b_c, oh)];
+ if (indices) {
+ const size_t ind_off = indices_d.blk_off(n, b_c, oh);
+ arg.indices = &indices[ind_off * ind_dt_size];
+ }
+ arg.oh = (oh == 0);
+ arg.kh_padding = jpp.kh - i_t_overflow - i_b_overflow;
+ arg.kh_padding_shift = i_t_overflow*jpp.kw;
+ arg.kw_padding = 0;
+ arg.ker_area_h = (float)(jpp.kh -
+ nstl::max(0, oh*jpp.stride_h - jpp.t_pad + jpp.kh - jpp.ih) -
+ nstl::max(0, jpp.t_pad - oh*jpp.stride_h));
+
+ (*kernel_)(&arg);
+ };
+
+ parallel_nd(jpp.mb, jpp.nb_c, [&](int n, int b_c) {
+ for (int oh = 0; oh < jpp.oh; ++oh) {
+ ker(n, b_c, oh);
+ }
+ });
+}
+
+template <cpu_isa_t isa>
+void jit_uni_pooling_bwd_t<isa>::execute_backward_3d(const data_t *diff_dst,
+ const char *indices, data_t *diff_src) const {
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper indices_d(pd()->workspace_md());
+ const size_t ind_dt_size = indices
+ ? types::data_type_size(indices_d.data_type()) : 0;
+
+ const auto &jpp = pd()->jpp_;
+
+ auto ker = [&](int n, int b_c, int od, int oh, int id, int d_t_overflow,
+ int d_b_overflow, int zero_size, int kd) {
+ auto arg = jit_pool_call_s();
+
+ const int ij = oh * jpp.stride_h;
+ const int i_t_overflow = nstl::max(0, jpp.t_pad-ij);
+ const int i_b_overflow = nstl::max(jpp.ih, ij+jpp.kh-jpp.t_pad)-jpp.ih;
+ const int ih = nstl::max(ij - jpp.t_pad, 0);
+
+ arg.src = &diff_src[diff_src_d.blk_off(n, b_c, id + kd, ih)];
+ arg.dst = &diff_dst[diff_dst_d.blk_off(n, b_c, od, oh)];
+ if (indices) {
+ const size_t ind_off = indices_d.blk_off(n, b_c, od, oh);
+ arg.indices = &indices[ind_off * ind_dt_size];
+ }
+ arg.oh = zero_size;
+ arg.kd_padding = jpp.kd - d_t_overflow - d_b_overflow;
+ arg.kh_padding = jpp.kh - i_t_overflow - i_b_overflow;
+ arg.kh_padding_shift = i_t_overflow*jpp.kw + d_t_overflow*jpp.kw*jpp.kh
+ + kd * jpp.kw * jpp.kh;
+ arg.kd_padding_shift = (i_t_overflow + i_b_overflow)*jpp.kw;
+ arg.kw_padding = 0;
+ arg.ker_area_h = (float)(jpp.kh -
+ nstl::max(0, oh*jpp.stride_h - jpp.t_pad + jpp.kh - jpp.ih) -
+ nstl::max(0, jpp.t_pad - oh*jpp.stride_h)) * (jpp.kd -
+ nstl::max(0, od*jpp.stride_d - jpp.f_pad + jpp.kd - jpp.id) -
+ nstl::max(0, jpp.f_pad - od*jpp.stride_d));
+
+ (*kernel_)(&arg);
+ };
+
+ if (jpp.simple_alg) {
+
+ parallel_nd(jpp.mb, jpp.nb_c, jpp.od,
+ [&](int n, int b_c, int od) {
+ const int ik = od * jpp.stride_d;
+ const int d_t_overflow = nstl::max(0, jpp.f_pad - ik);
+ const int d_b_overflow = nstl::max(jpp.id, ik + jpp.kd
+ - jpp.f_pad) - jpp.id;
+ const int id = nstl::max(ik - jpp.f_pad, 0);
+ int zero_s = jpp.stride_d - d_t_overflow - (nstl::max(
+ jpp.id, ik + jpp.stride_d - jpp.f_pad) - jpp.id);
+ for (int oh = 0; oh < jpp.oh; ++oh) {
+ ker(n, b_c, od, oh, id, d_t_overflow, d_b_overflow,
+ (oh == 0) ? zero_s : 0, 0);
+ }
+ });
+ } else {
+ ptrdiff_t nelems = (ptrdiff_t)jpp.mb * (ptrdiff_t)jpp.c
+ * (ptrdiff_t)jpp.id * (ptrdiff_t)jpp.ih * (ptrdiff_t)jpp.iw;
+
+ parallel_nd(nelems, [&](ptrdiff_t i) { diff_src[i] = 0.f; });
+
+ for (int kd = 0; kd < jpp.kd; ++kd) {
+ parallel_nd(jpp.mb, jpp.nb_c, [&](int n, int b_c) {
+ for (int od = 0; od < jpp.od; ++od) {
+ const int ik = od * jpp.stride_d;
+ const int d_t_overflow = nstl::max(0, jpp.f_pad-ik);
+ const int d_b_overflow = nstl::max(jpp.id, ik + jpp.kd
+ - jpp.f_pad) - jpp.id;
+ if (kd >= jpp.kd - d_t_overflow - d_b_overflow)
+ continue;
+ const int id = nstl::max(ik - jpp.f_pad, 0);
+ for (int oh = 0; oh < jpp.oh; ++oh) {
+ ker(n, b_c, od, oh, id, d_t_overflow, d_b_overflow,
+ 0, kd);
+ }
+ }
+ });
+ }
+ }
+}
+
+
+template struct jit_uni_pooling_fwd_t<sse42>;
+template struct jit_uni_pooling_bwd_t<sse42>;
+template struct jit_uni_pooling_fwd_t<avx>;
+template struct jit_uni_pooling_bwd_t<avx>;
+template struct jit_uni_pooling_fwd_t<avx512_common>;
+template struct jit_uni_pooling_bwd_t<avx512_common>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.hpp
new file mode 100644
index 0000000000..57bebacdee
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_pooling.hpp
@@ -0,0 +1,182 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_JIT_UNI_POOLING_HPP
+#define CPU_JIT_UNI_POOLING_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_pooling_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "jit_uni_pool_kernel_f32.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <cpu_isa_t isa>
+struct jit_uni_pooling_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_pooling_fwd_pd_t {
+ using cpu_pooling_fwd_pd_t::cpu_pooling_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", isa, ""),
+ jit_uni_pooling_fwd_t<isa>);
+
+ status_t init() {
+ using namespace utils;
+
+ bool ok = true
+ && set_default_params() == status::success
+ && is_fwd()
+ && !has_zero_dim_memory()
+ && everyone_is(data_type::f32,
+ src_md()->data_type,
+ dst_md()->data_type)
+ && attr()->has_default_values()
+ && memory_desc_matches_tag(*src_md(), desired_fmt_tag())
+ && memory_desc_matches_tag(*dst_md(), desired_fmt_tag());
+ if (!ok) return status::unimplemented;
+
+ bool is_training = desc_.prop_kind == prop_kind::forward_training;
+ if (desc()->alg_kind == alg_kind::pooling_max && is_training)
+ init_default_ws();
+
+ return jit_uni_pool_kernel_f32<isa>::init_conf(jpp_, this);
+ }
+
+ format_tag_t desired_fmt_tag() {
+ using namespace format_tag;
+ return ndims() == 4
+ ? isa == avx512_common ? nChw16c : nChw8c
+ : isa == avx512_common ? nCdhw16c : nCdhw8c;
+ }
+
+ jit_pool_conf_t jpp_;
+ };
+
+ jit_uni_pooling_fwd_t(const pd_t *apd): cpu_primitive_t(apd)
+ { kernel_ = new jit_uni_pool_kernel_f32<isa>(pd()->jpp_); }
+
+ ~jit_uni_pooling_fwd_t() { delete kernel_; }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+ auto ws = CTX_OUT_MEM(char *, MKLDNN_ARG_WORKSPACE);
+
+ if (pd()->ndims() == 5)
+ execute_forward_3d(src, dst, ws);
+ else
+ execute_forward(src, dst, ws);
+
+ return status::success;
+ }
+
+private:
+ void execute_forward(const data_t *src, data_t *dst, char *indices) const;
+ void execute_forward_3d(const data_t *src, data_t *dst,
+ char *indices) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ jit_uni_pool_kernel_f32<isa> *kernel_;
+};
+
+template <cpu_isa_t isa>
+struct jit_uni_pooling_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_pooling_bwd_pd_t {
+ using cpu_pooling_bwd_pd_t::cpu_pooling_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T(
+ JIT_IMPL_NAME_HELPER("jit:", isa, ""),
+ jit_uni_pooling_bwd_t<isa>);
+
+ status_t init() {
+ using namespace utils;
+
+ bool ok = true
+ && set_default_params() == status::success
+ && !is_fwd()
+ && !has_zero_dim_memory()
+ && everyone_is(data_type::f32,
+ diff_src_md()->data_type,
+ diff_dst_md()->data_type)
+ && attr()->has_default_values()
+ && memory_desc_matches_tag(*diff_dst_md(), desired_fmt_tag())
+ && memory_desc_matches_tag(*diff_src_md(), desired_fmt_tag());
+ if (!ok) return status::unimplemented;
+
+ if (desc()->alg_kind == alg_kind::pooling_max) {
+ init_default_ws();
+ if (!compare_ws(hint_fwd_pd_))
+ return status::unimplemented;
+ }
+
+ return jit_uni_pool_kernel_f32<isa>::init_conf(jpp_, this);
+ }
+
+ format_tag_t desired_fmt_tag() {
+ using namespace format_tag;
+ return ndims()
+ ? isa == avx512_common ? nChw16c : nChw8c
+ : isa == avx512_common ? nCdhw16c : nCdhw8c;
+ }
+
+ jit_pool_conf_t jpp_;
+ };
+
+ jit_uni_pooling_bwd_t(const pd_t *apd): cpu_primitive_t(apd)
+ { kernel_ = new jit_uni_pool_kernel_f32<isa>(pd()->jpp_); }
+
+ ~jit_uni_pooling_bwd_t() { delete kernel_; }
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto ws = CTX_IN_MEM(const char *, MKLDNN_ARG_WORKSPACE);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ if (pd()->ndims() == 5)
+ execute_backward_3d(diff_dst, ws, diff_src);
+ else
+ execute_backward(diff_dst, ws, diff_src);
+
+ return status::success;
+ }
+
+private:
+ void execute_backward(const data_t *diff_dst, const char *indices,
+ data_t *diff_src) const;
+ void execute_backward_3d(const data_t *diff_dst, const char *indices,
+ data_t *diff_src) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ jit_uni_pool_kernel_f32<isa> *kernel_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.cpp
new file mode 100644
index 0000000000..98796503b7
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.cpp
@@ -0,0 +1,1006 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_desc_wrapper.hpp"
+#include "mkldnn_debug.h"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+
+#include "cpu_primitive.hpp"
+#include "cpu_reorder_pd.hpp"
+#include "jit_uni_reorder.hpp"
+
+#include "jit_generator.hpp"
+
+// #define TR_DEBUG
+#if defined(TR_DEBUG)
+#define DEBUg(...) do { __VA_ARGS__ } while (0)
+#else
+#define DEBUg(...)
+#endif
+#define DEBUG(...) DEBUg(__VA_ARGS__)
+
+#ifdef _WIN32
+/* seems like s_addr is a reserved macro on Windows */
+#undef s_addr
+#endif
+
+using namespace Xbyak;
+using namespace mkldnn::impl::types;
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace tr {
+
+/** Minimal reasonable/desirable kernel size.
+ * The constant might be used to determine how a problem should be split
+ * between kernel and threading driver. */
+const size_t ker_prb_size_min = 64;
+
+/* kernel */
+struct jit_uni_reorder_kernel_f32: public kernel_t, public jit_generator {
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_reorder_kernel_f32)
+
+ enum {
+ len_unroll_max = 256,
+ ndims_jit_loop_max = 3,
+ };
+
+ struct simple_impl_desc_t {
+ int ndims_full_unroll;
+ int len_last_dim_unroll;
+ int len_unroll;
+ };
+
+ static bool simple_impl_desc_init(const prb_t &prb,
+ simple_impl_desc_t *desc) {
+ const int ndims = prb.ndims;
+
+ int ndims_full_unroll = 0;
+ int len_last_dim_unroll = 1;
+ int len_unroll = 1;
+
+ for (int d = 0; d < ndims; ++d) {
+ auto &node = prb.nodes[d];
+ if (len_unroll * node.n <= len_unroll_max) {
+ ndims_full_unroll++;
+ len_unroll *= node.n;
+ } else {
+ len_last_dim_unroll = len_unroll_max / len_unroll;
+ while (node.n % len_last_dim_unroll)
+ --len_last_dim_unroll;
+ len_unroll *= len_last_dim_unroll;
+ break;
+ }
+ }
+
+ if (prb.ndims - ndims_full_unroll > ndims_jit_loop_max)
+ return false;
+
+ if (desc) {
+ desc->ndims_full_unroll = ndims_full_unroll;
+ desc->len_last_dim_unroll = len_last_dim_unroll;
+ desc->len_unroll = len_unroll;
+ }
+
+ return true;
+ }
+
+ static bool applicable(const prb_t &p) {
+ using namespace data_type;
+
+ bool ok = true
+ && p.ndims > 0
+ && utils::one_of(p.itype, f32, s32, s8, u8)
+ && utils::one_of(p.otype, f32, s32, s8, u8)
+ && utils::everyone_is(0, p.ioff, p.ooff) /* do we need this? */
+ && utils::one_of(p.beta, 0.f, 1.f) /* anything else? */
+ && simple_impl_desc_init(p, nullptr)
+ && mayiuse(sse42)
+ && IMPLICATION(!utils::everyone_is(f32, p.itype, p.otype),
+ mayiuse(avx));
+ if (!ok) return false;
+
+ const ptrdiff_t max_stride = (1LL<<31) - 1;
+ for (int d = 0; d < p.ndims; ++d) {
+ const ptrdiff_t cms = max_stride / p.nodes[d].n;
+ bool strides_ok = true
+ && p.nodes[d].is < cms / (int)data_type_size(p.itype)
+ && p.nodes[d].os < cms / (int)data_type_size(p.otype);
+ if (!strides_ok) return false;
+ }
+
+ return true;
+ }
+
+ int n(int d) { assert(d < prb_.ndims); return (int)prb_.nodes[d].n; }
+ int is(int d) { assert(d < prb_.ndims); return (int)prb_.nodes[d].is; }
+ int os(int d) { assert(d < prb_.ndims); return (int)prb_.nodes[d].os; }
+ int ss(int d) { assert(d < prb_.ndims); return (int)prb_.nodes[d].ss; }
+
+ Address i_addr(int i_off)
+ { return ptr[reg_ptr_in + reg_off_in + i_off * itype_sz]; }
+
+ Address o_addr(int o_off)
+ { return ptr[reg_ptr_out + reg_off_out + o_off * otype_sz]; }
+
+ Address s_addr(int s_off)
+ { return ptr[reg_ptr_scale + reg_off_scale + s_off * stype_sz]; }
+
+ void step(int off, int prev_i_off, int prev_o_off, int prev_s_off,
+ int &i_off, int &o_off, int &s_off, int step_size = 1) {
+ i_off = prev_i_off;
+ o_off = prev_o_off;
+ s_off = prev_s_off;
+
+ if (off == 0) return;
+
+ int start_dim = 0, dims_prod = 1;
+ for (; start_dim < prb_.ndims && dims_prod != step_size; ++start_dim)
+ dims_prod *= n(start_dim);
+ assert(start_dim < prb_.ndims);
+ off /= step_size;
+
+ for (int d = start_dim; d < prb_.ndims; ++d) {
+ i_off += is(d);
+ o_off += os(d);
+ s_off += ss(d);
+
+ if (off % n(d)) break;
+
+ i_off += - n(d) * is(d);
+ o_off += - n(d) * os(d);
+ s_off += - n(d) * ss(d);
+ off /= n(d);
+
+ if (off == 0) break; /* FIXME: is it really required? */
+ }
+ }
+
+ void step(int off, int prev_i_off, int prev_o_off, int &i_off, int &o_off,
+ int step_size = 1) {
+ int dummy = 0;
+ step(off, prev_i_off, prev_o_off, dummy, i_off, o_off, dummy,
+ step_size);
+ }
+
+ void tr8x8_avx2(int i_off, int o_off) {
+ for (int i = 0; i < 8; i++)
+ vmovups(Ymm(i), i_addr(i_off + i * 8));
+
+ for (int i = 0; i < 8 / 2; i++) {
+ vunpcklps(Ymm(8 + i), Ymm(2 * i), Ymm(2 * i + 1));
+ vunpckhps(Ymm(i), Ymm(2 * i), Ymm(2 * i + 1));
+ }
+
+ const unsigned int lfloat = 0x44;
+ const unsigned int ufloat = 0xee;
+ for (int i = 0; i < 8 / 2; i++) {
+ int j = i % 2 == 0 ? 8 + i : i - 1;
+ vshufps(Ymm(8 / 2 + 2 * i), Ymm(j), Ymm(j + 1), lfloat);
+ vshufps(Ymm(8 / 2 + 2 * i + 1), Ymm(j), Ymm(j + 1), ufloat);
+ }
+
+ const unsigned int lquad = 0x20;
+ for (int i = 0; i < 8 / 2; i++)
+ vperm2f128(Ymm(i), Ymm(8 / 2 + i), Ymm(8 + i), lquad);
+
+ const unsigned int uquad = 0x31;
+ for (int i = 8 / 2; i < 8; i++)
+ vperm2f128(Ymm(i), Ymm(i), Ymm(8 / 2 + i), uquad);
+
+ for (int i = 0; i < 8; i++)
+ vmovups(o_addr(o_off + i * 8), Ymm(i));
+ }
+
+ bool process_unroll_tr8x8(int len) {
+ bool can_do = true
+ && mayiuse(avx2)
+ && prb_.ndims >= 2
+ && utils::everyone_is(4, itype_sz, otype_sz)
+ && utils::everyone_is(8, n(0), n(1))
+ && utils::everyone_is(1, os(0), is(1))
+ && utils::everyone_is(8, os(1), is(0))
+ && prb_.scale_type == scale_type_t::NONE
+ && prb_.beta == 0.f;
+ if (!can_do) return false;
+
+ const int step_size = n(0) * n(1);
+ int i_off = 0, o_off = 0;
+ for (int off = 0; off < len; off += step_size) {
+ step(off, i_off, o_off, i_off, o_off, step_size);
+ tr8x8_avx2(i_off, o_off);
+ }
+
+ return true;
+ }
+
+ template <cpu_isa_t isa>
+ bool process_direct_copy(int len) {
+ using namespace data_type;
+
+ using Vmm = typename cpu_isa_traits<isa>::Vmm;
+ const int simd_w = cpu_isa_traits<isa>::vlen / itype_sz;
+
+ bool can_do = true
+ && mayiuse(isa)
+ && utils::everyone_is(1, os(0), is(0))
+ && (false
+ || prb_.itype == prb_.otype
+ || (prb_.itype == s32 && prb_.otype == f32)
+ || (prb_.itype == f32 && prb_.otype == s32)
+ )
+ && len % simd_w == 0
+ && n(0) % len == 0
+ && prb_.scale_type == scale_type_t::NONE
+ && prb_.beta == 0.f;
+ if (!can_do) return false;
+
+ for (int off = 0; off < len;) {
+ const int unroll = nstl::min(16, (len - off) / simd_w);
+
+ for (int ur = 0; ur < unroll; ++ur)
+ uni_vmovups(Vmm(ur), i_addr(off + ur * simd_w));
+
+ if (prb_.itype != prb_.otype) {
+ for (int ur = 0; ur < unroll; ++ur) {
+ if (prb_.itype == s32 && prb_.otype == f32)
+ uni_vcvtdq2ps(Vmm(ur), Vmm(ur));
+ else if (prb_.itype == f32 && prb_.otype == s32)
+ uni_vcvtps2dq(Vmm(ur), Vmm(ur));
+ else assert(!"unreachable");
+ }
+ }
+
+ for (int ur = 0; ur < unroll; ++ur)
+ uni_vmovups(o_addr(off + ur * simd_w), Vmm(ur));
+
+ off += unroll * simd_w;
+ }
+
+ return true;
+ }
+
+ void process_unroll_generic_step(int reg_unroll, const int *i_off,
+ const int *o_off, const int *s_off) {
+ using namespace data_type;
+
+ auto cvt2ps = [=](const Xmm &dst, const Operand &src, data_type_t idt) {
+ Xmm dst_pure = Xmm(dst.getIdx());
+ switch (idt) {
+ case f32:
+ if (src.isMEM() || src.getIdx() != dst.getIdx())
+ vmovups(dst, src);
+ break;
+ case s32: vcvtdq2ps(dst, src); break;
+ case s8: vpmovsxbd(dst, src); vcvtdq2ps(dst_pure, dst); break;
+ case u8: vpmovzxbd(dst, src); vcvtdq2ps(dst_pure, dst); break;
+ default: assert(!"unreachable");
+ }
+ };
+
+ auto cvt2int = [=](const Xmm &xmm, data_type_t odt, data_type_t idt) {
+ switch (odt) {
+ case s32:
+ if (idt == f32) vcvtps2dq(xmm, xmm);
+ else if (idt == s8) vpmovsxbd(xmm, xmm);
+ else if (idt == u8) vpmovzxbd(xmm, xmm);
+ break;
+ case s8:
+ if (idt == f32) vcvtps2dq(xmm, xmm);
+ if (idt == f32 || idt == s32) {
+ if (mayiuse(avx512_core)) {
+ vpmovsdb(xmm, xmm);
+ } else {
+ vpackssdw(xmm, xmm, xmm_zero);
+ vpacksswb(xmm, xmm, xmm_zero);
+ }
+ }
+ if (idt == u8) vpminub(xmm, xmm, xmm_4x127b);
+ break;
+ case u8:
+ if (idt == f32) vcvtps2dq(xmm, xmm);
+ if (idt == f32 || idt == s32) {
+ if (mayiuse(avx512_core)) {
+ vpmaxsd(xmm, xmm, xmm_zero);
+ vpmovusdb(xmm, xmm);
+ } else {
+ vpackssdw(xmm, xmm, xmm_zero);
+ vpackuswb(xmm, xmm, xmm_zero);
+ }
+ }
+ if (idt == s8) vpmaxsb(xmm, xmm, xmm_zero);
+ break;
+ default: assert(!"unreachable");
+ }
+ };
+
+ auto load = [=](const Xmm &xmm, const Address &addr, int size) {
+ switch (size) {
+ case 16: movups(xmm, addr); break;
+ case 4: movss(xmm, addr); break;
+ case 1: pinsrb(xmm, addr, 0x0); break;
+ default: assert(!"unreachable");
+ }
+ };
+
+ auto store = [=](const Address &addr, const Xmm &xmm, int size) {
+ switch (size) {
+ case 16: movups(addr, xmm); break;
+ case 4: movss(addr, xmm); break;
+ case 1: pextrb(addr, xmm, 0x0); break;
+ default: assert(!"unreachable");
+ }
+ };
+
+ /* check whether loading 4 values at once is possible */
+ bool can_load_xmm = mayiuse(avx) && reg_unroll % 4 == 0;
+ for (int ur = 1; ur < reg_unroll; ++ur)
+ if (i_off[ur] != i_off[ur - 1] + 1)
+ can_load_xmm = false;
+ const int load_step = can_load_xmm ? 4 : 1;
+
+ /* check whether storing 4 values at once is possible */
+ bool can_store_xmm = reg_unroll % 4 == 0;
+ for (int ur = 1; ur < reg_unroll; ++ur)
+ if (o_off[ur] != o_off[ur - 1] + 1)
+ can_store_xmm = false;
+ const int ur_step = can_store_xmm ? 4 : 1;
+
+ const bool interim_f32 = false
+ || utils::one_of(f32, prb_.itype, prb_.otype)
+ || prb_.scale_type != scale_type_t::NONE
+ || prb_.beta != 0.f;
+
+ if (!can_load_xmm && can_store_xmm) {
+ assert(ur_step == 4);
+ /* load with stride */
+ for (int ur = 0; ur < reg_unroll; ur += ur_step) {
+ for (int r = 0; r < ur_step; ++r) {
+ if (itype_sz == 4)
+ pinsrd(Xmm(ur), i_addr(i_off[ur + r]), r);
+ else
+ pinsrb(Xmm(ur), i_addr(i_off[ur + r]), r);
+ }
+ }
+ } else {
+ for (int ur = 0; ur < reg_unroll; ur += load_step)
+ load(Xmm(ur), i_addr(i_off[ur]), load_step * itype_sz);
+ }
+
+ /* xmm[:] <-- (f32)xmm[:] */
+ if (interim_f32) {
+ const int cvt_step = nstl::max(load_step, ur_step);
+ for (int ur = 0; ur < reg_unroll; ur += cvt_step)
+ cvt2ps(Xmm(ur), Xmm(ur), prb_.itype);
+ }
+
+ if (can_load_xmm && !can_store_xmm) {
+ const bool fast_return = true // transposition on the fly
+ && prb_.scale_type != scale_type_t::MANY
+ && prb_.beta == 0.f;
+ if (fast_return) {
+ for (int ur = 0; ur < reg_unroll; ur += load_step) {
+ if (prb_.scale_type == scale_type_t::COMMON)
+ mulps(Xmm(ur), xmm_scale);
+ if (prb_.otype != f32)
+ cvt2int(Xmm(ur), prb_.otype,
+ interim_f32 ? f32 : prb_.itype);
+ for (int r = 0; r < load_step; ++r) {
+ if (otype_sz == 4)
+ pextrd(o_addr(o_off[ur + r]), Xmm(ur), r);
+ else
+ pextrb(o_addr(o_off[ur + r]), Xmm(ur), r);
+ }
+ }
+ return;
+ }
+
+ /* scatter elements of xmm into 4 xmms */
+ if (itype_sz == 4 || interim_f32) {
+ for (int ur = 0; ur < reg_unroll; ur += load_step)
+ for (int r = 1; r < load_step; ++r)
+ vshufps(Xmm(ur + r), Xmm(ur), Xmm(ur), r);
+ } else {
+ for (int ur = 0; ur < reg_unroll; ur += load_step)
+ for (int r = 1; r < load_step; ++r)
+ vpalignr(Xmm(ur + r), Xmm(ur), Xmm(ur), r);
+ }
+ }
+
+ /* scale and beta processing */
+ if (can_store_xmm) {
+ /* xmm <-- scale * xmm[:] */
+ if (prb_.scale_type == scale_type_t::COMMON) {
+ for (int ur = 0; ur < reg_unroll; ur += ur_step)
+ mulps(Xmm(ur), xmm_scale);
+ } else if (prb_.scale_type == scale_type_t::MANY) {
+ enum class scale_load_type_t { bcast, load, gather };
+
+ for (int ur = 0; ur < reg_unroll; ur += ur_step) {
+ scale_load_type_t scale_load_type =
+ scale_load_type_t::bcast; // the best case
+
+ for (int r = ur + 1; r < ur + ur_step; ++r)
+ if (s_off[r] != s_off[r - 1] + 0)
+ scale_load_type = scale_load_type_t::load;
+
+ if (scale_load_type == scale_load_type_t::bcast) {
+ movss(xmm_scale, s_addr(s_off[ur]));
+ shufps(xmm_scale, xmm_scale, 0x0);
+ mulps(Xmm(ur), xmm_scale);
+ continue;
+ }
+
+ // bcast doesn't work, the next try -- load
+ for (int r = ur + 1; r < ur + ur_step; ++r)
+ if (s_off[r] != s_off[r - 1] + 1)
+ scale_load_type = scale_load_type_t::gather;
+
+ if (scale_load_type == scale_load_type_t::load) {
+ movups(xmm_scale, s_addr(s_off[ur]));
+ mulps(Xmm(ur), xmm_scale);
+ continue;
+ }
+
+ // load doesn't work as well
+ // so gather the scale factors one by one
+ for (int r = ur; r < ur + ur_step; ++r)
+ pinsrd(xmm_scale, s_addr(s_off[r]), r - ur);
+ mulps(Xmm(ur), xmm_scale);
+ }
+ }
+
+ /* dst <-- beta * dst + xmm[:] */
+ assert(prb_.beta == 0.f || prb_.beta == 1.f);
+ if (prb_.beta == 1.f) {
+ for (int ur = 0; ur < reg_unroll; ur += ur_step) {
+ if (prb_.otype == f32) {
+ /* non VEX instructions do not support unaligned
+ * memory for instructions other than movups. */
+ if (mayiuse(avx)) {
+ vaddps(Xmm(ur), o_addr(o_off[ur]));
+ } else {
+ /* register xmm(1) is unused */
+ movups(Xmm(1), o_addr(o_off[ur]));
+ addps(Xmm(ur), Xmm(1));
+ }
+ } else {
+ cvt2ps(Xmm(1), o_addr(o_off[ur]), prb_.otype);
+ vaddps(Xmm(ur), Xmm(1));
+ }
+ }
+ }
+ } else {
+ /* xmm[0] <-- scale * xmm[0] */
+ if (prb_.scale_type == scale_type_t::COMMON) {
+ for (int ur = 0; ur < reg_unroll; ur += ur_step)
+ mulss(Xmm(ur), xmm_scale);
+ } else if (prb_.scale_type == scale_type_t::MANY) {
+ for (int ur = 0; ur < reg_unroll; ur += ur_step) {
+ mulss(Xmm(ur), s_addr(s_off[ur]));
+ }
+ }
+
+ /* dst <-- beta * dst + xmm[0] */
+ assert(prb_.beta == 0.f || prb_.beta == 1.f);
+ if (prb_.beta == 1.f) {
+ for (int ur = 0; ur < reg_unroll; ur += ur_step) {
+ if (prb_.otype == f32) {
+ addss(Xmm(ur), o_addr(o_off[ur]));
+ } else {
+ if (prb_.otype == s32) {
+ vmovss(xmm_tmp, o_addr(o_off[ur]));
+ } else if (utils::one_of(prb_.otype, s8, u8)) {
+ pinsrb(xmm_tmp, o_addr(o_off[ur]), 0x0);
+ } else {
+ assert(!"unsupported o_type");
+ }
+ cvt2ps(xmm_tmp, xmm_tmp, prb_.otype);
+ addps(Xmm(ur), xmm_tmp);
+ }
+ }
+ }
+ }
+
+ for (int ur = 0; ur < reg_unroll; ur += ur_step) {
+ if (prb_.otype != f32)
+ cvt2int(Xmm(ur), prb_.otype, interim_f32 ? f32 : prb_.itype);
+ store(o_addr(o_off[ur]), Xmm(ur), ur_step * otype_sz);
+ }
+ }
+
+ void process_unroll_generic(int len) {
+ const int blk = 8;
+
+ int i_off[2 * blk] = {0};
+ int o_off[2 * blk] = {0};
+ int s_off[2 * blk] = {0};
+
+ int curr = 0; // will switch between 0 and 1
+
+ for (int off = 0; off < len; off += blk) {
+ const int reg_unroll = nstl::min(off + blk, len) - off;
+
+ /* compute offsets */
+ for (int ur = off != 0 ? 0 : 1; ur < reg_unroll; ++ur) {
+ const int ur_c = curr * blk + ur;
+ const int ur_p = (ur_c - 1 + 2 * blk) % (2 * blk); // prev ur
+ step(off + ur,
+ i_off[ur_p], o_off[ur_p], s_off[ur_p],
+ i_off[ur_c], o_off[ur_c], s_off[ur_c]);
+ }
+
+ process_unroll_generic_step(reg_unroll, i_off + curr * blk,
+ o_off + curr * blk, s_off + curr * blk);
+
+ curr = 1 - curr;
+ }
+ }
+
+ void loop_begin(Label &l, Reg64 reg_cnt, int len) {
+ mov(reg_cnt, len);
+ L(l);
+ }
+
+ void loop_end(Label &l, Reg64 reg_cnt, int len,
+ int i_step, int o_step, int s_step) {
+ add(reg_off_in, i_step * itype_sz);
+ add(reg_off_out, o_step * otype_sz);
+ if (prb_.scale_type == scale_type_t::MANY)
+ add(reg_off_scale, s_step * stype_sz);
+ dec(reg_cnt);
+ jnz(l);
+
+ sub(reg_off_in, len * i_step * itype_sz);
+ sub(reg_off_out, len * o_step * otype_sz);
+ if (prb_.scale_type == scale_type_t::MANY)
+ sub(reg_off_scale, len * s_step * stype_sz);
+ }
+
+ bool simple_impl() {
+ simple_impl_desc_t d;
+ if (!simple_impl_desc_init(prb_, &d)) return false;
+
+ const int nfu = d.ndims_full_unroll;
+ const int ldu = d.len_last_dim_unroll;
+ const int n_jit_loops = prb_.ndims - d.ndims_full_unroll;
+ assert(n_jit_loops <= ndims_jit_loop_max);
+
+ xor_(reg_off_in, reg_off_in);
+ xor_(reg_off_out, reg_off_out);
+ if (prb_.scale_type == scale_type_t::MANY)
+ xor_(reg_off_scale, reg_off_scale);
+
+ Label l_loop[3];
+ Reg64 reg_cnt[3] = {r15, r14, r13};
+
+ if (n_jit_loops > 2)
+ loop_begin(l_loop[2], reg_cnt[2], n(nfu + 2));
+
+ if (n_jit_loops > 1)
+ loop_begin(l_loop[1], reg_cnt[1], n(nfu + 1));
+
+ if (n_jit_loops > 0)
+ loop_begin(l_loop[0], reg_cnt[0], n(nfu + 0) / ldu);
+
+ const bool optimized = false
+ || process_direct_copy<avx>(d.len_unroll)
+ || process_direct_copy<sse42>(d.len_unroll)
+ || process_unroll_tr8x8(d.len_unroll);
+ if (!optimized)
+ process_unroll_generic(d.len_unroll);
+
+ if (n_jit_loops > 0)
+ loop_end(l_loop[0], reg_cnt[0],
+ n(nfu + 0) / ldu, is(nfu + 0) * ldu, os(nfu + 0) * ldu,
+ ss(nfu + 0) * ldu);
+
+ if (n_jit_loops > 1)
+ loop_end(l_loop[1], reg_cnt[1],
+ n(nfu + 1), is(nfu + 1), os(nfu + 1), ss(nfu + 1));
+
+ if (n_jit_loops > 2)
+ loop_end(l_loop[2], reg_cnt[2],
+ n(nfu + 2), is(nfu + 2), os(nfu + 2), ss(nfu + 2));
+
+ return true;
+ }
+
+ void impl() {
+ if (simple_impl()) return;
+ assert(!"no implementation available");
+ }
+
+ jit_uni_reorder_kernel_f32(const desc_t &desc)
+ : kernel_t(desc), jit_generator() {
+ itype_sz = data_type_size(prb_.itype);
+ otype_sz = data_type_size(prb_.otype);
+ stype_sz = sizeof(float);
+
+ preamble();
+# define PARAM(x) ptr[abi_param1 + offsetof(call_param_t, x)]
+ if (prb_.scale_type == scale_type_t::COMMON) {
+ auto reg_ptr_scale_tmp = reg_ptr_in;
+ mov(reg_ptr_scale_tmp, PARAM(scale));
+ movups(xmm_scale, ptr[reg_ptr_scale_tmp]);
+ } else if (prb_.scale_type == scale_type_t::MANY) {
+ mov(reg_ptr_scale, PARAM(scale));
+ }
+ mov(reg_ptr_in, PARAM(in));
+ mov(reg_ptr_out, PARAM(out));
+# undef PARAM
+
+ if (mayiuse(avx)) {
+ vxorps(xmm_zero, xmm_zero, xmm_zero);
+
+ if (prb_.itype == data_type::u8 && prb_.otype == data_type::s8) {
+ mov(reg_tmp.cvt32(), 0x7f7f7f7f);
+ movd(xmm_4x127b, reg_tmp.cvt32());
+ }
+ }
+
+ impl();
+ postamble();
+ ker_ = (void (*)(const call_param_t *))getCode();
+ }
+
+private:
+ int itype_sz;
+ int otype_sz;
+ int stype_sz;
+
+ Reg64 reg_ptr_in = rsi;
+ Reg64 reg_ptr_out = rdx;
+ Reg64 reg_ptr_scale = abi_not_param1;
+
+ Reg64 reg_off_in = r8;
+ Reg64 reg_off_out = r9;
+ Reg64 reg_off_scale = r10;
+
+ Reg64 reg_tmp = rax;
+
+ Xmm xmm_scale = xmm15;
+ Xmm xmm_zero = xmm14;
+ Xmm xmm_4x127b = xmm13; // TODO: unite with xmm_zero
+ Xmm xmm_tmp = xmm12;
+};
+
+status_t kernel_t::desc_init(kernel_t::desc_t &desc, const prb_t &prb,
+ int ndims_ker_max) {
+ desc.prb = prb;
+ desc.prb.ioff = desc.prb.ooff = 0;
+
+ if (ndims_ker_max > prb.ndims)
+ return status::invalid_arguments;
+
+ auto ndims_ker_max_f = [&]() {
+ size_t cur_size = 1;
+ for (int d = 0; d < prb.ndims; cur_size *= prb.nodes[d++].n)
+ if (cur_size >= ker_prb_size_min) return d;
+ return prb.ndims;
+ };
+
+ if (ndims_ker_max <= 0)
+ ndims_ker_max = ndims_ker_max_f();
+
+ /* traverse through kernel implementations */
+ /* TODO: find a better way to do that... */
+ desc.id = 0;
+ for (int ndims_ker = ndims_ker_max; ndims_ker > 0; --ndims_ker) {
+ desc.prb.ndims = ndims_ker;
+ if (jit_uni_reorder_kernel_f32::applicable(desc.prb))
+ return status::success;
+ }
+
+ return status::unimplemented;
+}
+
+kernel_t *kernel_t::create(const kernel_t::desc_t &desc) {
+ switch (desc.id) {
+ case 0: return new jit_uni_reorder_kernel_f32(desc);
+ default: assert(!"unknown kernel id"); return nullptr;
+ }
+
+ return nullptr;
+}
+
+}
+
+static void prb_block_for_cache(tr::prb_t &prb) {
+ if (prb.nodes[0].is % 64 == 0 && prb.nodes[0].n > 16) {
+ /** an attempt to use caches more efficient and
+ * address the 4K-aliasing issue */
+ /* TODO: improve the logic around here */
+ int j = 1;
+ for (; j < prb.ndims && prb.nodes[j].is != 1; ++j);
+ if (j == prb.ndims) return;
+
+ /* it makes sense to re-prioritize sequential read over
+ * sequential write if the former would not trash the
+ * cache, i.e. is == 1 and os % 2^smth != 0. Smth is
+ * set to 2 at the moment */
+ const int move_to = prb.nodes[j].os % 4 != 0 ? 0 : 1;
+ if (j == move_to) return;
+
+ if (prb.nodes[j].n > 16 && prb.nodes[j].n % 16 == 0)
+ prb_node_split(prb, j, 16);
+
+ prb_node_move(prb, j, move_to);
+ DEBUG({ printf("cache: "); prb_dump(prb); });
+ }
+}
+
+/** finds the maximum number of dimension the kernel should process and
+ * optionally splits one of the dimension to achieve better balance between
+ * parallel driver and the kernel. */
+static void prb_thread_kernel_balance(tr::prb_t &prb, int &ndims_ker_max) {
+ size_t sz_total = 1;
+ for (int d = 0; d < prb.ndims; ++d)
+ sz_total *= prb.nodes[d].n;
+
+ /* sz_drv_min is the minimal size for the parallel
+ * driver required for good parallelization */
+ const size_t sz_drv_min = nstl::min<size_t>(
+ 16 * mkldnn_get_max_threads(),
+ utils::div_up(sz_total, 1024));
+
+ /* kdims -- # of dimensions processed by a kernel
+ * sz_ker_cur -- product of the dimension processed by a kernel
+ * sz_drv_cur -- product of the dimension processed by a driver */
+
+ int kdims = prb.ndims;
+ size_t sz_drv_cur = 1;
+ for (; kdims > 1 && sz_drv_cur < sz_drv_min; --kdims)
+ sz_drv_cur *= prb.nodes[kdims - 1].n;
+
+ size_t sz_ker_cur = 1;
+ for (int d = 0; d < kdims; ++d)
+ sz_ker_cur *= prb.nodes[d].n;
+
+ /* Initially kdims is chosen so that sz_drv_cur >= sz_drv_min.
+ *
+ * It might happen that for chosen kdims the sz_ker_cur is too small
+ * (less than tr::ker_prb_size_min). In that case try to split the
+ * innermost driver dimension into two, to increase sz_ker_cur. */
+ bool want_borrow_ker_from_drv = true
+ && kdims < prb.ndims
+ && sz_ker_cur < tr::ker_prb_size_min
+ && sz_drv_cur > sz_drv_min;
+ if (want_borrow_ker_from_drv) {
+ /* sz_want_borrow is the minimal sz, so that:
+ * o) sz_ker_cur * sz_want_borrow >= tr::ker_prb_size_min
+ * o) current innermost driver dimension is divisible by
+ * sz_want_borrow (so that we can evenly split that
+ * dimension into two)
+ *
+ * In the worst case the minimal sz_want_borrow is equal
+ * to the innermost driver dimension itself. In that case
+ * we will sacrifice it in favor of kernel (is it fine?). */
+ size_t sz_want_borrow
+ = utils::div_up(tr::ker_prb_size_min, sz_ker_cur);
+ for (; prb.nodes[kdims].n % sz_want_borrow; ++sz_want_borrow);
+ if (sz_want_borrow != prb.nodes[kdims].n)
+ prb_node_split(prb, kdims, sz_want_borrow);
+ kdims += 1;
+ }
+
+ /* On the other hand it might happen that for chosen kdims
+ * the sz_drv_cur is too small (less than sz_drv_min). In that case
+ * try to split the outermost kernel dimension into two, to increase
+ * sz_drv_cur. */
+ bool want_borrow_drv_from_ker = true
+ && sz_ker_cur > tr::ker_prb_size_min
+ && sz_drv_cur < sz_drv_min;
+ if (want_borrow_drv_from_ker) {
+ size_t sz_want_borrow = utils::div_up(sz_drv_min, sz_drv_cur);
+ for (; prb.nodes[kdims - 1].n % sz_want_borrow; ++sz_want_borrow);
+ if (sz_want_borrow != prb.nodes[kdims - 1].n)
+ prb_node_split(prb, kdims - 1,
+ prb.nodes[kdims - 1].n / sz_want_borrow);
+ }
+
+ ndims_ker_max = kdims;
+
+ if (want_borrow_ker_from_drv || want_borrow_drv_from_ker) {
+ DEBUG({ printf("split: "); prb_dump(prb);
+ printf("ndims_ker_max = %d\n", ndims_ker_max); });
+ }
+}
+
+struct jit_uni_reorder_t : public cpu_primitive_t {
+ struct pd_t : public cpu_reorder_pd_t {
+ using cpu_reorder_pd_t::cpu_reorder_pd_t;
+
+ DECLARE_COMMON_PD_T("jit:uni", jit_uni_reorder_t);
+
+ static status_t create(reorder_pd_t **reorder_pd,
+ engine_t *engine, const primitive_attr_t *attr,
+ engine_t *src_engine, const memory_desc_t *src_md,
+ engine_t *dst_engine, const memory_desc_t *dst_md) {
+ auto prb = tr::prb_t();
+
+ status_t prb_init_status = prb_init(prb, *src_md, *dst_md, attr);
+ if (prb_init_status != status::success) return prb_init_status;
+
+ DEBUG({ printf("init : "); prb_dump(prb); });
+ prb_normalize(prb);
+ DEBUG({ printf("norm : "); prb_dump(prb); });
+ prb_simplify(prb);
+ DEBUG({ printf("smpl : "); prb_dump(prb); });
+
+ prb_block_for_cache(prb);
+
+ int ndims_ker_max;
+ prb_thread_kernel_balance(prb, ndims_ker_max);
+
+ tr::kernel_t::desc_t ker_desc;
+ status_t ker_init_status
+ = tr::kernel_t::desc_init(ker_desc, prb, ndims_ker_max);
+ if (ker_init_status != status::success) return ker_init_status;
+
+ const int ndims_driver = prb.ndims - ker_desc.prb.ndims;
+ if (ndims_driver > jit_uni_reorder_t::ndims_driver_max)
+ return status::unimplemented;
+
+ DEBUG({ printf("ker : "); prb_dump(ker_desc.prb); });
+
+ auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine,
+ dst_md);
+ if (_pd == nullptr) return status::out_of_memory;
+ if (_pd->init() != status::success) {
+ delete _pd;
+ return status::unimplemented;
+ }
+ _pd->prb_ = prb;
+ _pd->ker_desc_ = ker_desc;
+ return safe_ptr_assign<reorder_pd_t>(*reorder_pd, _pd);
+ }
+
+ tr::prb_t prb_;
+ tr::kernel_t::desc_t ker_desc_;
+ };
+
+ jit_uni_reorder_t(const pd_t *apd): cpu_primitive_t(apd) {
+ kernel_ = tr::kernel_t::create(pd()->ker_desc_);
+ assert(kernel_);
+ }
+ ~jit_uni_reorder_t() { delete kernel_; }
+
+ void omp_driver_0d(int off, const char *in, char *out,
+ const float *scale) const {
+ tr::call_param_t c{in, out, scale};
+ (*kernel_)(&c);
+ }
+
+ void omp_driver_1d(int ithr, int nthr, int off, const char *in, char *out,
+ const float *scale) const {
+ const tr::node_t *ns = pd()->prb_.nodes + off;
+ for_nd(ithr, nthr, (ptrdiff_t)ns[0].n, [&](ptrdiff_t d0) {
+ auto c = tr::call_param_t();
+ c.in = in + d0 * ns[0].is * data_type_size(pd()->prb_.itype);
+ c.out = out + d0 * ns[0].os * data_type_size(pd()->prb_.otype);
+ c.scale = scale + d0 * ns[0].ss;
+ (*kernel_)(&c);
+ });
+ }
+
+ void omp_driver_2d(int ithr, int nthr, int off, const char *in, char *out,
+ const float *scale) const {
+ const tr::node_t *ns = pd()->prb_.nodes + off;
+ for_nd(ithr, nthr, (ptrdiff_t)ns[1].n, (ptrdiff_t)ns[0].n,
+ [&](ptrdiff_t d1, ptrdiff_t d0) {
+ auto c = tr::call_param_t();
+ c.in = in + (d0 * ns[0].is + d1 * ns[1].is)
+ * data_type_size(pd()->prb_.itype);
+ c.out = out + (d0 * ns[0].os + d1 * ns[1].os)
+ * data_type_size(pd()->prb_.otype);
+ c.scale = scale + d0 * ns[0].ss + d1 * ns[1].ss;
+ (*kernel_)(&c);
+ });
+ }
+
+ void omp_driver_3d(int ithr, int nthr, int off, const char *in, char *out,
+ const float *scale) const {
+ const tr::node_t *ns = pd()->prb_.nodes + off;
+ for_nd(ithr, nthr, (ptrdiff_t)ns[2].n, (ptrdiff_t)ns[1].n,
+ (ptrdiff_t)ns[0].n,
+ [&](ptrdiff_t d2, ptrdiff_t d1, ptrdiff_t d0) {
+ auto c = tr::call_param_t();
+ c.in = in + (d0 * ns[0].is + d1 * ns[1].is + d2 * ns[2].is)
+ * data_type_size(pd()->prb_.itype);
+ c.out = out + (d0 * ns[0].os + d1 * ns[1].os + d2 * ns[2].os)
+ * data_type_size(pd()->prb_.otype);
+ c.scale = scale + d0 * ns[0].ss + d1 * ns[1].ss + d2 * ns[2].ss;
+ (*kernel_)(&c);
+ });
+ }
+
+ void omp_driver_4d(int ithr, int nthr, int off, const char *in, char *out,
+ const float *scale) const {
+ const tr::node_t *ns = pd()->prb_.nodes + off;
+ for_nd(ithr, nthr, (ptrdiff_t)ns[3].n, (ptrdiff_t)ns[2].n,
+ (ptrdiff_t)ns[1].n, (ptrdiff_t)ns[0].n,
+ [&](ptrdiff_t d3, ptrdiff_t d2, ptrdiff_t d1, ptrdiff_t d0) {
+ auto c = tr::call_param_t();
+ c.in = in + (d0 * ns[0].is + d1 * ns[1].is + d2 * ns[2].is
+ + d3 * ns[3].is) * data_type_size(pd()->prb_.itype);
+ c.out = out + (d0 * ns[0].os + d1 * ns[1].os + d2 * ns[2].os
+ + d3 * ns[3].os) * data_type_size(pd()->prb_.otype);
+ c.scale = scale + d0 * ns[0].ss + d1 * ns[1].ss + d2 * ns[2].ss
+ + d3 * ns[3].ss;
+ (*kernel_)(&c);
+ });
+ }
+
+ void omp_driver(const char *in, char *out, const float *scale) const {
+ in += pd()->prb_.ioff * data_type_size(pd()->prb_.itype);
+ out += pd()->prb_.ooff * data_type_size(pd()->prb_.otype);
+
+ DEBUG({ printf("prb : "); tr::prb_dump(pd()->prb_); });
+ DEBUG({ printf("ker : "); tr::prb_dump(pd()->ker_desc_.prb); });
+
+ int ndims = pd()->prb_.ndims;
+ int ndims_ker = pd()->ker_desc_.prb.ndims;
+ assert(ndims - ndims_ker <= ndims_driver_max);
+
+ if (ndims - ndims_ker == 0) {
+ omp_driver_0d(ndims_ker, in, out, scale);
+ } else {
+ parallel(0, [&](const int ithr, const int nthr) {
+ switch (ndims - ndims_ker) {
+ case 1: omp_driver_1d(ithr, nthr, ndims_ker, in, out, scale); break;
+ case 2: omp_driver_2d(ithr, nthr, ndims_ker, in, out, scale); break;
+ case 3: omp_driver_3d(ithr, nthr, ndims_ker, in, out, scale); break;
+ case 4: omp_driver_4d(ithr, nthr, ndims_ker, in, out, scale); break;
+ default: assert(!"unimplemented");
+ }
+ });
+ }
+ }
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto in = CTX_IN_MEM(const char *, MKLDNN_ARG_FROM);
+ auto out = CTX_OUT_MEM(char *, MKLDNN_ARG_TO);
+
+ omp_driver(in, out, pd()->attr()->output_scales_.scales_);
+
+ return status::success;
+ }
+
+ enum { ndims_driver_max = 4 };
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ tr::kernel_t *kernel_;
+};
+
+status_t jit_uni_reorder_create(reorder_pd_t **reorder_pd,
+ engine_t *engine, const primitive_attr_t *attr,
+ engine_t *src_engine, const memory_desc_t *src_md,
+ engine_t *dst_engine, const memory_desc_t *dst_md) {
+ return jit_uni_reorder_t::pd_t::create(reorder_pd, engine, attr,
+ src_engine, src_md, dst_engine, dst_md);
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.hpp
new file mode 100644
index 0000000000..0746ea61d3
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder.hpp
@@ -0,0 +1,127 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef _JIT_UNI_REORDER_HPP
+#define _JIT_UNI_REORDER_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+
+#include "cpu_primitive.hpp"
+#include "cpu_reorder_pd.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace tr {
+
+constexpr int max_ndims = MKLDNN_MAX_NDIMS;
+
+struct node_t {
+ size_t n;
+ ptrdiff_t is; // input stride
+ ptrdiff_t os; // output stride
+ ptrdiff_t ss; // scale stride
+};
+
+enum class scale_type_t { NONE, COMMON, MANY };
+
+struct prb_t {
+ data_type_t itype;
+ data_type_t otype;
+ int ndims;
+ node_t nodes[max_ndims];
+ ptrdiff_t ioff;
+ ptrdiff_t ooff;
+ scale_type_t scale_type;
+ float beta;
+};
+
+status_t prb_init(prb_t &prb, const memory_desc_t &imd,
+ const memory_desc_t &omd, const primitive_attr_t *attr);
+
+/** sorts the problem nodes so that output strides come in ascending order */
+void prb_normalize(prb_t &p);
+
+/** folds nodes together if possible */
+void prb_simplify(prb_t &p);
+
+/** splits the node dim into two of sizes n1 and n / n1
+ * @warning n must be multiple of n1 */
+void prb_node_split(prb_t &p, int dim, size_t n1);
+
+/** swaps d0 and d1 nodes */
+void prb_node_swap(prb_t &p, int d0, int d1);
+
+/** moves node d0 to the d1 position.
+ * nodes (d0, d1] are shifted to the left if d0 < d1 or
+ * to the right if d0 > d1 */
+void prb_node_move(prb_t &p, int d0, int d1);
+
+/** dumps the problem to stdout */
+void prb_dump(const prb_t &p);
+
+struct call_param_t {
+ const void *in;
+ void *out;
+ const float *scale;
+};
+
+struct kernel_t {
+ struct desc_t {
+ int id;
+ prb_t prb;
+ };
+
+ kernel_t(const desc_t &desc): desc_(desc), ker_(nullptr) {}
+ void operator()(const call_param_t *c) const { assert(ker_); ker_(c); }
+ virtual ~kernel_t() {}
+
+ /** inits kernel descriptor:
+ * desc -- kernel descriptor (output)
+ * prb -- transposition problem (input)
+ * ndims_ker_max -- limit the maximum number of dimensions kernel
+ * will process (optional, 0 -- no limitation) */
+ static status_t desc_init(desc_t &desc, const prb_t &prb,
+ int ndims_ker_max = 0);
+
+ /** creates kernel for the problem described in desc */
+ static kernel_t *create(const desc_t &desc);
+
+protected:
+ const desc_t desc_;
+ const prb_t &prb_ = desc_.prb;
+ void (*ker_)(const call_param_t *);
+};
+
+/* TODO: add trans_t class */
+
+}
+
+/* for cpu reorder list */
+status_t jit_uni_reorder_create(reorder_pd_t **reorder_pd,
+ engine_t *engine, const primitive_attr_t *attr,
+ engine_t *src_engine, const memory_desc_t *src_md,
+ engine_t *dst_engine, const memory_desc_t *dst_md);
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp
new file mode 100644
index 0000000000..69b7a33604
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp
@@ -0,0 +1,313 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_desc_wrapper.hpp"
+#include "mkldnn_debug.h"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "jit_uni_reorder.hpp"
+
+using namespace mkldnn::impl::types;
+using namespace mkldnn::impl::status;
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace tr {
+
+/** ad-hoc structure to describe blocked memory layout */
+struct layout_desc_t {
+ data_type_t dt;
+ int ndims;
+ dims_t id;
+ dims_t dims;
+ strides_t strides;
+};
+
+status_t cvt_mem_desc_to_layout_desc(const memory_desc_t &md_,
+ layout_desc_t &ld) {
+ const auto md = memory_desc_wrapper(md_);
+
+ bool ok = true
+ && md.is_blocking_desc()
+ && md.extra().flags == 0;
+ if (!ok) return invalid_arguments;
+
+ const auto &bd = md.blocking_desc();
+
+ ld.ndims = 0;
+ ld.dt = md.data_type();
+
+ auto P = [&ld](int id, int dim, ptrdiff_t stride) {
+ assert((size_t)ld.ndims < sizeof(ld.dims) / sizeof(ld.dims[0]));
+ ld.id[ld.ndims] = id;
+ ld.dims[ld.ndims] = dim;
+ ld.strides[ld.ndims] = stride;
+ ++ld.ndims;
+ };
+
+ dims_t blocks;
+ md.compute_blocks(blocks);
+
+ for (int d = 0; d < md.ndims(); ++d) {
+ const int ld_ndims_start = ld.ndims;
+ if (blocks[d] != 1) {
+ stride_t stride = 1;
+ for (int iblk = bd.inner_nblks - 1; iblk >= 0; --iblk) {
+ if (bd.inner_idxs[iblk] == d)
+ P(d, bd.inner_blks[iblk], stride);
+ stride *= bd.inner_blks[iblk];
+ }
+ }
+ P(d, md.padded_dims()[d] / blocks[d], bd.strides[d]);
+
+ // TODO: NOW: revisit, do we need a reverse?
+ // TODO: NOW: consider using strides instead of block sizes in md
+ // reverse the order of dims
+ for (int ld_d = 0; ld_d < (ld.ndims - ld_ndims_start) / 2; ++ld_d) {
+ const int idx0 = ld_ndims_start + ld_d;
+ const int idx1 = ld.ndims - 1 - ld_d;
+ nstl::swap(ld.dims[idx0], ld.dims[idx1]);
+ nstl::swap(ld.strides[idx0], ld.strides[idx1]);
+ }
+ }
+
+ return success;
+}
+
+status_t prb_init(prb_t &p, const memory_desc_t &imd, const memory_desc_t &omd,
+ const primitive_attr_t *attr) {
+ auto im_d = memory_desc_wrapper(imd);
+ auto om_d = memory_desc_wrapper(omd);
+
+ bool ok = true
+ && im_d.is_blocking_desc()
+ && om_d.is_blocking_desc()
+ && !im_d.has_zero_dim()
+ && !om_d.has_zero_dim();
+ if (!ok)
+ return unimplemented;
+
+ dims_t iblocks, oblocks;
+ im_d.compute_blocks(iblocks);
+ om_d.compute_blocks(oblocks);
+
+ /* padding_dim consistency check */
+ for (int d = 0; d < im_d.ndims(); ++d) {
+ const auto pdim = im_d.padded_dims()[d];
+ bool ok = true
+ && pdim == om_d.padded_dims()[d]
+ && pdim % iblocks[d] == 0
+ && pdim % oblocks[d] == 0;
+ if (!ok) return unimplemented;
+ }
+
+ layout_desc_t ild, old;
+ status_t status = cvt_mem_desc_to_layout_desc(imd, ild);
+ if (status != success) return status;
+ status = cvt_mem_desc_to_layout_desc(omd, old);
+ if (status != success) return status;
+
+ p.itype = ild.dt;
+ p.otype = old.dt;
+
+ p.scale_type = attr->output_scales_.has_default_values()
+ ? scale_type_t::NONE
+ : (attr->output_scales_.mask_ == 0
+ ? scale_type_t::COMMON
+ : scale_type_t::MANY);
+
+ ptrdiff_t ss[max_ndims] = {0};
+ if (p.scale_type == scale_type_t::MANY) {
+ ptrdiff_t last_ss = 1;
+ for (int d = old.ndims - 1; d >=0; --d) {
+ assert((d == 0 || old.id[d - 1] <= old.id[d])
+ && "logical dimensions should be in ascending order");
+ if (attr->output_scales_.mask_ & (1 << old.id[d])) {
+ ss[d] = last_ss;
+ last_ss *= old.dims[d];
+ }
+ }
+ }
+
+ int ndims = 0;
+
+ int i_pos = 0; /* state for input -- current dimension */
+ int o_pos = 0; /* state for output -- current dimension */
+
+ while (i_pos < ild.ndims && o_pos < old.ndims) {
+ assert(ild.id[i_pos] == old.id[o_pos]);
+ if (ild.id[i_pos] != old.id[o_pos])
+ return runtime_error;
+
+ assert(ndims < max_ndims);
+ if (ndims == max_ndims)
+ return runtime_error;
+
+ if (ild.dims[i_pos] == old.dims[o_pos]) {
+ p.nodes[ndims].n = ild.dims[i_pos];
+ p.nodes[ndims].is = ild.strides[i_pos];
+ p.nodes[ndims].os = old.strides[o_pos];
+ p.nodes[ndims].ss = ss[o_pos];
+ ++ndims;
+ ++i_pos;
+ ++o_pos;
+ } else if (ild.dims[i_pos] < old.dims[o_pos]) {
+ assert(old.dims[o_pos] % ild.dims[i_pos] == 0);
+ int factor = old.dims[o_pos] / ild.dims[i_pos];
+ p.nodes[ndims].n = ild.dims[i_pos];
+ p.nodes[ndims].is = ild.strides[i_pos];
+ p.nodes[ndims].os = old.strides[o_pos] * factor;
+ p.nodes[ndims].ss = ss[o_pos] * factor;
+ ++ndims;
+ ++i_pos;
+ old.dims[o_pos] = factor;
+ } else if (ild.dims[i_pos] > old.dims[o_pos]) {
+ assert(ild.dims[i_pos] % old.dims[o_pos] == 0);
+ int factor = ild.dims[i_pos] / old.dims[o_pos];
+ p.nodes[ndims].n = old.dims[o_pos];
+ p.nodes[ndims].is = ild.strides[i_pos] * factor;
+ p.nodes[ndims].os = old.strides[o_pos];
+ p.nodes[ndims].ss = ss[o_pos];
+ ++ndims;
+ ++o_pos;
+ ild.dims[i_pos] = factor;
+ }
+ }
+ p.ndims = ndims;
+
+ dims_t zero_pos = {0};
+ p.ioff = memory_desc_wrapper(imd).off_v(zero_pos);
+ p.ooff = memory_desc_wrapper(omd).off_v(zero_pos);
+
+ const int sum_idx = attr->post_ops_.find(primitive_kind::sum);
+ p.beta = sum_idx == -1 ? 0.f : attr->post_ops_.entry_[sum_idx].sum.scale;
+
+ return success;
+}
+
+void prb_normalize(prb_t &p) {
+ for (int d = 0; d < p.ndims; ++d) {
+ int min_pos = d;
+ for (int j = d + 1; j < p.ndims; ++j) {
+ bool new_min = false
+ || p.nodes[j].os < p.nodes[min_pos].os
+ || (true
+ && p.nodes[j].os == p.nodes[min_pos].os
+ && p.nodes[j].n < p.nodes[min_pos].n);
+ if (new_min) min_pos = j;
+ }
+ if (min_pos != d)
+ nstl::swap(p.nodes[d], p.nodes[min_pos]);
+ }
+}
+
+void prb_simplify(prb_t &p) {
+#if defined(__GNUC__) && __GNUC__ >= 4
+/* GCC produces bogus array subscript is above array bounds warning for
+ * the `p.nodes[j - 1] = p.nodes[j]` line below, so disable it for now. */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+ for (int d = 0; d < p.ndims - 1; ++d) {
+ auto &this_node = p.nodes[d + 0];
+ auto &next_node = p.nodes[d + 1];
+ const bool fold = false
+ || next_node.n == (size_t)1 // trivial case, just drop next node
+ || (true // or real folding if possible
+ && next_node.is == (ptrdiff_t)this_node.n * this_node.is
+ && next_node.os == (ptrdiff_t)this_node.n * this_node.os
+ && next_node.ss == (ptrdiff_t)this_node.n * this_node.ss);
+ if (fold) {
+ this_node.n *= next_node.n;
+ for (int j = d + 2; j < p.ndims; ++j)
+ p.nodes[j - 1] = p.nodes[j];
+ --p.ndims;
+ --d; // make another try
+ }
+ }
+#if defined(__GNUC__) && __GNUC__ >= 4
+#pragma GCC diagnostic pop
+#endif
+}
+
+void prb_node_split(prb_t &p, int dim, size_t n1) {
+ assert(dim < p.ndims);
+ assert(p.ndims < max_ndims);
+ assert(p.nodes[dim].n % n1 == 0);
+
+ p.ndims += 1;
+
+ for (int d = p.ndims; d > dim + 1; --d)
+ p.nodes[d] = p.nodes[d - 1];
+
+ p.nodes[dim + 1].n = p.nodes[dim].n / n1;
+ p.nodes[dim + 1].is = p.nodes[dim].is * n1;
+ p.nodes[dim + 1].os = p.nodes[dim].os * n1;
+ p.nodes[dim + 1].ss = p.nodes[dim].ss * n1;
+
+ p.nodes[dim].n = n1;
+}
+
+void prb_node_swap(prb_t &p, int d0, int d1) {
+ assert(d0 < p.ndims);
+ assert(d1 < p.ndims);
+ assert(p.ndims < max_ndims);
+
+ if (d0 == d1) return;
+
+ nstl::swap(p.nodes[d0], p.nodes[d1]);
+}
+
+void prb_node_move(prb_t &p, int d0, int d1) {
+ assert(d0 < p.ndims);
+ assert(d1 < p.ndims);
+ assert(p.ndims < max_ndims);
+
+ if (d0 == d1) return;
+
+ node_t node = p.nodes[d0];
+
+ if (d0 < d1)
+ for (int d = d0; d < d1; ++d)
+ p.nodes[d] = p.nodes[d + 1];
+ else
+ for (int d = d0; d > d1; --d)
+ p.nodes[d] = p.nodes[d - 1];
+
+ p.nodes[d1] = node;
+}
+
+void prb_dump(const prb_t &p) {
+ printf("@@@ type:%s:%s ndims:%d ", mkldnn_dt2str(p.itype),
+ mkldnn_dt2str(p.otype), p.ndims);
+ for (int d = 0; d < p.ndims; ++d)
+ printf("[%zu:%td:%td:%td]",
+ p.nodes[d].n, p.nodes[d].is, p.nodes[d].os, p.nodes[d].ss);
+ printf(" off:%zu:%zu\n", p.ioff, p.ooff);
+}
+
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.cpp
new file mode 100644
index 0000000000..08747aa89c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.cpp
@@ -0,0 +1,115 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <mutex>
+
+#include "utils.hpp"
+
+#ifndef MKLDNN_ENABLE_JIT_PROFILING
+#define MKLDNN_ENABLE_JIT_PROFILING 1
+#endif
+
+#ifndef MKLDNN_ENABLE_JIT_DUMP
+#define MKLDNN_ENABLE_JIT_DUMP 1
+#endif
+
+#if MKLDNN_ENABLE_JIT_PROFILING
+#include "jitprofiling/jitprofiling.h"
+#endif
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+namespace jit_utils {
+
+// WARNING: These functions are not thread safe and must be protected by a
+// mutex
+
+void dump_jit_code(const void *code, size_t code_size, const char *code_name)
+{
+#if MKLDNN_ENABLE_JIT_DUMP
+ if (code && jit_dump_enabled()) {
+ static int counter = 0;
+#define MAX_FNAME_LEN 256
+ char fname[MAX_FNAME_LEN + 1];
+ // TODO (Roma): support prefix for code / linux perf dumps
+ snprintf(fname, MAX_FNAME_LEN, "mkldnn_dump_%s.%d.bin", code_name,
+ counter);
+ counter++;
+
+ FILE *fp = fopen(fname, "w+");
+ // Failure to dump code is not fatal
+ if (fp) {
+ size_t unused = fwrite(code, code_size, 1, fp);
+ UNUSED(unused);
+ fclose(fp);
+ }
+ }
+#undef MAX_FNAME_LEN
+#else
+ UNUSED(code);
+ UNUSED(code_size);
+ UNUSED(code_name);
+#endif
+}
+
+void register_jit_code_vtune(const void *code, size_t code_size,
+ const char *code_name, const char *source_file_name)
+{
+#if MKLDNN_ENABLE_JIT_PROFILING
+ if (iJIT_IsProfilingActive() == iJIT_SAMPLING_ON) {
+ auto jmethod = iJIT_Method_Load();
+ jmethod.method_id = iJIT_GetNewMethodID(); // XXX: not thread-safe
+ jmethod.method_name = (char *)code_name; // XXX: dropping const
+ jmethod.class_file_name = NULL;
+ jmethod.source_file_name = (char *)source_file_name; // XXX: dropping const
+ jmethod.method_load_address = (void *)code;
+ jmethod.method_size = (unsigned int)code_size;
+
+ iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
+ (void*)&jmethod);
+ }
+#else
+ UNUSED(code);
+ UNUSED(code_size);
+ UNUSED(code_name);
+ UNUSED(source_file_name);
+#endif
+}
+
+void register_jit_code(const void *code, size_t code_size,
+ const char *code_name, const char *source_file_name)
+{
+ // The #ifdef guards are required to avoid generating a function that only
+ // consists of lock and unlock code
+#if MKLDNN_ENABLE_JIT_PROFILING || MKLDNN_ENABLE_JIT_DUMP
+ static std::mutex m;
+ std::lock_guard<std::mutex> guard(m);
+
+ dump_jit_code(code, code_size, code_name);
+ register_jit_code_vtune(code, code_size, code_name, source_file_name);
+#else
+ UNUSED(code);
+ UNUSED(code_size);
+ UNUSED(code_name);
+ UNUSED(source_file_name);
+#endif
+}
+
+}
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.hpp
new file mode 100644
index 0000000000..2f52dba4ac
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jit_utils.hpp
@@ -0,0 +1,32 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef JIT_SUPPORT_HPP
+#define JIT_SUPPORT_HPP
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+namespace jit_utils {
+
+void register_jit_code(const void *code, size_t code_size,
+ const char *code_name, const char *source_file_name);
+
+}
+}
+}
+}
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/LICENSE.BSD b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/LICENSE.BSD
new file mode 100644
index 0000000000..4fd21cea57
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/LICENSE.BSD
@@ -0,0 +1,27 @@
+Copyright (c) 2011, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/README.md b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/README.md
new file mode 100644
index 0000000000..fc67c4f134
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/README.md
@@ -0,0 +1 @@
+This code is from [Intel SEAPI library](https://github.com/intel/IntelSEAPI)
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_config.h b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_config.h
new file mode 100644
index 0000000000..edbf4a15f0
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_config.h
@@ -0,0 +1,595 @@
+/* <copyright>
+
+ Contact Information:
+ http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
+
+ BSD LICENSE
+
+ Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</copyright> */
+#ifndef _ITTNOTIFY_CONFIG_H_
+#define _ITTNOTIFY_CONFIG_H_
+
+/** @cond exclude_from_documentation */
+#ifndef ITT_OS_WIN
+# define ITT_OS_WIN 1
+#endif /* ITT_OS_WIN */
+
+#ifndef ITT_OS_LINUX
+# define ITT_OS_LINUX 2
+#endif /* ITT_OS_LINUX */
+
+#ifndef ITT_OS_MAC
+# define ITT_OS_MAC 3
+#endif /* ITT_OS_MAC */
+
+#ifndef ITT_OS_FREEBSD
+# define ITT_OS_FREEBSD 4
+#endif /* ITT_OS_FREEBSD */
+
+#ifndef ITT_OS
+# if defined WIN32 || defined _WIN32
+# define ITT_OS ITT_OS_WIN
+# elif defined( __APPLE__ ) && defined( __MACH__ )
+# define ITT_OS ITT_OS_MAC
+# elif defined( __FreeBSD__ )
+# define ITT_OS ITT_OS_FREEBSD
+# else
+# define ITT_OS ITT_OS_LINUX
+# endif
+#endif /* ITT_OS */
+
+#ifndef ITT_PLATFORM_WIN
+# define ITT_PLATFORM_WIN 1
+#endif /* ITT_PLATFORM_WIN */
+
+#ifndef ITT_PLATFORM_POSIX
+# define ITT_PLATFORM_POSIX 2
+#endif /* ITT_PLATFORM_POSIX */
+
+#ifndef ITT_PLATFORM_MAC
+# define ITT_PLATFORM_MAC 3
+#endif /* ITT_PLATFORM_MAC */
+
+#ifndef ITT_PLATFORM_FREEBSD
+# define ITT_PLATFORM_FREEBSD 4
+#endif /* ITT_PLATFORM_FREEBSD */
+
+#ifndef ITT_PLATFORM
+# if ITT_OS==ITT_OS_WIN
+# define ITT_PLATFORM ITT_PLATFORM_WIN
+# elif ITT_OS==ITT_OS_MAC
+# define ITT_PLATFORM ITT_PLATFORM_MAC
+# elif ITT_OS==ITT_OS_FREEBSD
+# define ITT_PLATFORM ITT_PLATFORM_FREEBSD
+# else
+# define ITT_PLATFORM ITT_PLATFORM_POSIX
+# endif
+#endif /* ITT_PLATFORM */
+
+#if defined(_UNICODE) && !defined(UNICODE)
+#define UNICODE
+#endif
+
+#include <stddef.h>
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+#include <tchar.h>
+#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+#include <stdint.h>
+#if defined(UNICODE) || defined(_UNICODE)
+#include <wchar.h>
+#endif /* UNICODE || _UNICODE */
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+
+#ifndef ITTAPI_CDECL
+# if ITT_PLATFORM==ITT_PLATFORM_WIN
+# define ITTAPI_CDECL __cdecl
+# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+# if defined _M_IX86 || defined __i386__
+# define ITTAPI_CDECL __attribute__ ((cdecl))
+# else /* _M_IX86 || __i386__ */
+# define ITTAPI_CDECL /* actual only on x86 platform */
+# endif /* _M_IX86 || __i386__ */
+# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+#endif /* ITTAPI_CDECL */
+
+#ifndef STDCALL
+# if ITT_PLATFORM==ITT_PLATFORM_WIN
+# define STDCALL __stdcall
+# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+# if defined _M_IX86 || defined __i386__
+# define STDCALL __attribute__ ((stdcall))
+# else /* _M_IX86 || __i386__ */
+# define STDCALL /* supported only on x86 platform */
+# endif /* _M_IX86 || __i386__ */
+# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+#endif /* STDCALL */
+
+#define ITTAPI ITTAPI_CDECL
+#define LIBITTAPI ITTAPI_CDECL
+
+/* TODO: Temporary for compatibility! */
+#define ITTAPI_CALL ITTAPI_CDECL
+#define LIBITTAPI_CALL ITTAPI_CDECL
+
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+/* use __forceinline (VC++ specific) */
+#define ITT_INLINE __forceinline
+#define ITT_INLINE_ATTRIBUTE /* nothing */
+#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+/*
+ * Generally, functions are not inlined unless optimization is specified.
+ * For functions declared inline, this attribute inlines the function even
+ * if no optimization level was specified.
+ */
+#ifdef __STRICT_ANSI__
+#define ITT_INLINE static
+#define ITT_INLINE_ATTRIBUTE __attribute__((unused))
+#else /* __STRICT_ANSI__ */
+#define ITT_INLINE static inline
+#define ITT_INLINE_ATTRIBUTE __attribute__((always_inline, unused))
+#endif /* __STRICT_ANSI__ */
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+/** @endcond */
+
+#ifndef ITT_ARCH_IA32
+# define ITT_ARCH_IA32 1
+#endif /* ITT_ARCH_IA32 */
+
+#ifndef ITT_ARCH_IA32E
+# define ITT_ARCH_IA32E 2
+#endif /* ITT_ARCH_IA32E */
+
+#ifndef ITT_ARCH_ARM
+# define ITT_ARCH_ARM 4
+#endif /* ITT_ARCH_ARM */
+
+#ifndef ITT_ARCH_PPC64
+# define ITT_ARCH_PPC64 5
+#endif /* ITT_ARCH_PPC64 */
+
+#ifndef ITT_ARCH
+# if defined _M_IX86 || defined __i386__
+# define ITT_ARCH ITT_ARCH_IA32
+# elif defined _M_X64 || defined _M_AMD64 || defined __x86_64__
+# define ITT_ARCH ITT_ARCH_IA32E
+# elif defined _M_IA64 || defined __ia64__
+# define ITT_ARCH ITT_ARCH_IA64
+# elif defined _M_ARM || defined __arm__
+# define ITT_ARCH ITT_ARCH_ARM
+# elif defined __powerpc64__
+# define ITT_ARCH ITT_ARCH_PPC64
+# endif
+#endif
+
+#ifdef __cplusplus
+# define ITT_EXTERN_C extern "C"
+# define ITT_EXTERN_C_BEGIN extern "C" {
+# define ITT_EXTERN_C_END }
+#else
+# define ITT_EXTERN_C /* nothing */
+# define ITT_EXTERN_C_BEGIN /* nothing */
+# define ITT_EXTERN_C_END /* nothing */
+#endif /* __cplusplus */
+
+#define ITT_TO_STR_AUX(x) #x
+#define ITT_TO_STR(x) ITT_TO_STR_AUX(x)
+
+#define __ITT_BUILD_ASSERT(expr, suffix) do { \
+ static char __itt_build_check_##suffix[(expr) ? 1 : -1]; \
+ __itt_build_check_##suffix[0] = 0; \
+} while(0)
+#define _ITT_BUILD_ASSERT(expr, suffix) __ITT_BUILD_ASSERT((expr), suffix)
+#define ITT_BUILD_ASSERT(expr) _ITT_BUILD_ASSERT((expr), __LINE__)
+
+#define ITT_MAGIC { 0xED, 0xAB, 0xAB, 0xEC, 0x0D, 0xEE, 0xDA, 0x30 }
+
+/* Replace with snapshot date YYYYMMDD for promotion build. */
+#define API_VERSION_BUILD 20151119
+
+#ifndef API_VERSION_NUM
+#define API_VERSION_NUM 0.0.0
+#endif /* API_VERSION_NUM */
+
+#define API_VERSION "ITT-API-Version " ITT_TO_STR(API_VERSION_NUM) \
+ " (" ITT_TO_STR(API_VERSION_BUILD) ")"
+
+/* OS communication functions */
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+#include <windows.h>
+typedef HMODULE lib_t;
+typedef DWORD TIDT;
+typedef CRITICAL_SECTION mutex_t;
+#define MUTEX_INITIALIZER { 0 }
+#define strong_alias(name, aliasname) /* empty for Windows */
+#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+#include <dlfcn.h>
+#if defined(UNICODE) || defined(_UNICODE)
+#include <wchar.h>
+#endif /* UNICODE */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1 /* need for PTHREAD_MUTEX_RECURSIVE */
+#endif /* _GNU_SOURCE */
+#ifndef __USE_UNIX98
+#define __USE_UNIX98 1 /* need for PTHREAD_MUTEX_RECURSIVE, on SLES11.1 with gcc 4.3.4 wherein pthread.h missing dependency on __USE_XOPEN2K8 */
+#endif /*__USE_UNIX98*/
+#include <pthread.h>
+typedef void* lib_t;
+typedef pthread_t TIDT;
+typedef pthread_mutex_t mutex_t;
+#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define _strong_alias(name, aliasname) \
+ extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+#define strong_alias(name, aliasname) _strong_alias(name, aliasname)
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+#define __itt_get_proc(lib, name) GetProcAddress(lib, name)
+#define __itt_mutex_init(mutex) InitializeCriticalSection(mutex)
+#define __itt_mutex_lock(mutex) EnterCriticalSection(mutex)
+#define __itt_mutex_unlock(mutex) LeaveCriticalSection(mutex)
+#define __itt_load_lib(name) LoadLibraryA(name)
+#define __itt_unload_lib(handle) FreeLibrary(handle)
+#define __itt_system_error() (int)GetLastError()
+#define __itt_fstrcmp(s1, s2) lstrcmpA(s1, s2)
+#define __itt_fstrnlen(s, l) strnlen_s(s, l)
+#define __itt_fstrcpyn(s1, b, s2, l) strncpy_s(s1, b, s2, l)
+#define __itt_fstrdup(s) _strdup(s)
+#define __itt_thread_id() GetCurrentThreadId()
+#define __itt_thread_yield() SwitchToThread()
+#ifndef ITT_SIMPLE_INIT
+ITT_INLINE long
+__itt_interlocked_increment(volatile long* ptr) ITT_INLINE_ATTRIBUTE;
+ITT_INLINE long __itt_interlocked_increment(volatile long* ptr)
+{
+ return InterlockedIncrement(ptr);
+}
+#endif /* ITT_SIMPLE_INIT */
+
+#define DL_SYMBOLS (1)
+#define PTHREAD_SYMBOLS (1)
+
+#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
+#define __itt_get_proc(lib, name) dlsym(lib, name)
+#define __itt_mutex_init(mutex) {\
+ pthread_mutexattr_t mutex_attr; \
+ int error_code = pthread_mutexattr_init(&mutex_attr); \
+ if (error_code) \
+ __itt_report_error(__itt_error_system, "pthread_mutexattr_init", \
+ error_code); \
+ error_code = pthread_mutexattr_settype(&mutex_attr, \
+ PTHREAD_MUTEX_RECURSIVE); \
+ if (error_code) \
+ __itt_report_error(__itt_error_system, "pthread_mutexattr_settype", \
+ error_code); \
+ error_code = pthread_mutex_init(mutex, &mutex_attr); \
+ if (error_code) \
+ __itt_report_error(__itt_error_system, "pthread_mutex_init", \
+ error_code); \
+ error_code = pthread_mutexattr_destroy(&mutex_attr); \
+ if (error_code) \
+ __itt_report_error(__itt_error_system, "pthread_mutexattr_destroy", \
+ error_code); \
+}
+#define __itt_mutex_lock(mutex) pthread_mutex_lock(mutex)
+#define __itt_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
+#define __itt_load_lib(name) dlopen(name, RTLD_LAZY)
+#define __itt_unload_lib(handle) dlclose(handle)
+#define __itt_system_error() errno
+#define __itt_fstrcmp(s1, s2) strcmp(s1, s2)
+
+/* makes customer code define safe APIs for SDL_STRNLEN_S and SDL_STRNCPY_S */
+#ifdef SDL_STRNLEN_S
+#define __itt_fstrnlen(s, l) SDL_STRNLEN_S(s, l)
+#else
+#define __itt_fstrnlen(s, l) strlen(s)
+#endif /* SDL_STRNLEN_S */
+#ifdef SDL_STRNCPY_S
+#define __itt_fstrcpyn(s1, b, s2, l) SDL_STRNCPY_S(s1, b, s2, l)
+#else
+#define __itt_fstrcpyn(s1, b, s2, l) strncpy(s1, s2, l)
+#endif /* SDL_STRNCPY_S */
+
+#define __itt_fstrdup(s) strdup(s)
+#define __itt_thread_id() pthread_self()
+#define __itt_thread_yield() sched_yield()
+#if ITT_ARCH==ITT_ARCH_IA64
+#ifdef __INTEL_COMPILER
+#define __TBB_machine_fetchadd4(addr, val) __fetchadd4_acq((void *)addr, val)
+#else /* __INTEL_COMPILER */
+/* TODO: Add Support for not Intel compilers for IA-64 architecture */
+#endif /* __INTEL_COMPILER */
+#elif ITT_ARCH==ITT_ARCH_IA32 || ITT_ARCH==ITT_ARCH_IA32E /* ITT_ARCH!=ITT_ARCH_IA64 */
+ITT_INLINE long
+__TBB_machine_fetchadd4(volatile void* ptr, long addend) ITT_INLINE_ATTRIBUTE;
+ITT_INLINE long __TBB_machine_fetchadd4(volatile void* ptr, long addend)
+{
+ long result;
+ __asm__ __volatile__("lock\nxadd %0,%1"
+ : "=r"(result),"=m"(*(int*)ptr)
+ : "0"(addend), "m"(*(int*)ptr)
+ : "memory");
+ return result;
+}
+#elif ITT_ARCH==ITT_ARCH_ARM || ITT_ARCH==ITT_ARCH_PPC64
+#define __TBB_machine_fetchadd4(addr, val) __sync_fetch_and_add(addr, val)
+#endif /* ITT_ARCH==ITT_ARCH_IA64 */
+#ifndef ITT_SIMPLE_INIT
+ITT_INLINE long
+__itt_interlocked_increment(volatile long* ptr) ITT_INLINE_ATTRIBUTE;
+ITT_INLINE long __itt_interlocked_increment(volatile long* ptr)
+{
+ return __TBB_machine_fetchadd4(ptr, 1) + 1L;
+}
+#endif /* ITT_SIMPLE_INIT */
+
+void* dlopen(const char*, int) __attribute__((weak));
+void* dlsym(void*, const char*) __attribute__((weak));
+int dlclose(void*) __attribute__((weak));
+#define DL_SYMBOLS (dlopen && dlsym && dlclose)
+
+int pthread_mutex_init(pthread_mutex_t*, const pthread_mutexattr_t*) __attribute__((weak));
+int pthread_mutex_lock(pthread_mutex_t*) __attribute__((weak));
+int pthread_mutex_unlock(pthread_mutex_t*) __attribute__((weak));
+int pthread_mutex_destroy(pthread_mutex_t*) __attribute__((weak));
+int pthread_mutexattr_init(pthread_mutexattr_t*) __attribute__((weak));
+int pthread_mutexattr_settype(pthread_mutexattr_t*, int) __attribute__((weak));
+int pthread_mutexattr_destroy(pthread_mutexattr_t*) __attribute__((weak));
+pthread_t pthread_self(void) __attribute__((weak));
+#define PTHREAD_SYMBOLS (pthread_mutex_init && pthread_mutex_lock && pthread_mutex_unlock && pthread_mutex_destroy && pthread_mutexattr_init && pthread_mutexattr_settype && pthread_mutexattr_destroy && pthread_self)
+
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+
+typedef enum {
+ __itt_collection_normal = 0,
+ __itt_collection_paused = 1
+} __itt_collection_state;
+
+typedef enum {
+ __itt_thread_normal = 0,
+ __itt_thread_ignored = 1
+} __itt_thread_state;
+
+#pragma pack(push, 8)
+
+typedef struct ___itt_thread_info
+{
+ const char* nameA; /*!< Copy of original name in ASCII. */
+#if defined(UNICODE) || defined(_UNICODE)
+ const wchar_t* nameW; /*!< Copy of original name in UNICODE. */
+#else /* UNICODE || _UNICODE */
+ void* nameW;
+#endif /* UNICODE || _UNICODE */
+ TIDT tid;
+ __itt_thread_state state; /*!< Thread state (paused or normal) */
+ int extra1; /*!< Reserved to the runtime */
+ void* extra2; /*!< Reserved to the runtime */
+ struct ___itt_thread_info* next;
+} __itt_thread_info;
+
+#include "ittnotify_types.h" /* For __itt_group_id definition */
+
+typedef struct ___itt_api_info_20101001
+{
+ const char* name;
+ void** func_ptr;
+ void* init_func;
+ __itt_group_id group;
+} __itt_api_info_20101001;
+
+typedef struct ___itt_api_info
+{
+ const char* name;
+ void** func_ptr;
+ void* init_func;
+ void* null_func;
+ __itt_group_id group;
+} __itt_api_info;
+
+typedef struct __itt_counter_info
+{
+ const char* nameA; /*!< Copy of original name in ASCII. */
+#if defined(UNICODE) || defined(_UNICODE)
+ const wchar_t* nameW; /*!< Copy of original name in UNICODE. */
+#else /* UNICODE || _UNICODE */
+ void* nameW;
+#endif /* UNICODE || _UNICODE */
+ const char* domainA; /*!< Copy of original name in ASCII. */
+#if defined(UNICODE) || defined(_UNICODE)
+ const wchar_t* domainW; /*!< Copy of original name in UNICODE. */
+#else /* UNICODE || _UNICODE */
+ void* domainW;
+#endif /* UNICODE || _UNICODE */
+ int type;
+ long index;
+ int extra1; /*!< Reserved to the runtime */
+ void* extra2; /*!< Reserved to the runtime */
+ struct __itt_counter_info* next;
+} __itt_counter_info_t;
+
+struct ___itt_domain;
+struct ___itt_string_handle;
+
+typedef struct ___itt_global
+{
+ unsigned char magic[8];
+ unsigned long version_major;
+ unsigned long version_minor;
+ unsigned long version_build;
+ volatile long api_initialized;
+ volatile long mutex_initialized;
+ volatile long atomic_counter;
+ mutex_t mutex;
+ lib_t lib;
+ void* error_handler;
+ const char** dll_path_ptr;
+ __itt_api_info* api_list_ptr;
+ struct ___itt_global* next;
+ /* Joinable structures below */
+ __itt_thread_info* thread_list;
+ struct ___itt_domain* domain_list;
+ struct ___itt_string_handle* string_list;
+ __itt_collection_state state;
+ __itt_counter_info_t* counter_list;
+} __itt_global;
+
+#pragma pack(pop)
+
+#define NEW_THREAD_INFO_W(gptr,h,h_tail,t,s,n) { \
+ h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \
+ if (h != NULL) { \
+ h->tid = t; \
+ h->nameA = NULL; \
+ h->nameW = n ? _wcsdup(n) : NULL; \
+ h->state = s; \
+ h->extra1 = 0; /* reserved */ \
+ h->extra2 = NULL; /* reserved */ \
+ h->next = NULL; \
+ if (h_tail == NULL) \
+ (gptr)->thread_list = h; \
+ else \
+ h_tail->next = h; \
+ } \
+}
+
+#define NEW_THREAD_INFO_A(gptr,h,h_tail,t,s,n) { \
+ h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \
+ if (h != NULL) { \
+ h->tid = t; \
+ h->nameA = n ? __itt_fstrdup(n) : NULL; \
+ h->nameW = NULL; \
+ h->state = s; \
+ h->extra1 = 0; /* reserved */ \
+ h->extra2 = NULL; /* reserved */ \
+ h->next = NULL; \
+ if (h_tail == NULL) \
+ (gptr)->thread_list = h; \
+ else \
+ h_tail->next = h; \
+ } \
+}
+
+#define NEW_DOMAIN_W(gptr,h,h_tail,name) { \
+ h = (__itt_domain*)malloc(sizeof(__itt_domain)); \
+ if (h != NULL) { \
+ h->flags = 1; /* domain is enabled by default */ \
+ h->nameA = NULL; \
+ h->nameW = name ? _wcsdup(name) : NULL; \
+ h->extra1 = 0; /* reserved */ \
+ h->extra2 = NULL; /* reserved */ \
+ h->next = NULL; \
+ if (h_tail == NULL) \
+ (gptr)->domain_list = h; \
+ else \
+ h_tail->next = h; \
+ } \
+}
+
+#define NEW_DOMAIN_A(gptr,h,h_tail,name) { \
+ h = (__itt_domain*)malloc(sizeof(__itt_domain)); \
+ if (h != NULL) { \
+ h->flags = 1; /* domain is enabled by default */ \
+ h->nameA = name ? __itt_fstrdup(name) : NULL; \
+ h->nameW = NULL; \
+ h->extra1 = 0; /* reserved */ \
+ h->extra2 = NULL; /* reserved */ \
+ h->next = NULL; \
+ if (h_tail == NULL) \
+ (gptr)->domain_list = h; \
+ else \
+ h_tail->next = h; \
+ } \
+}
+
+#define NEW_STRING_HANDLE_W(gptr,h,h_tail,name) { \
+ h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \
+ if (h != NULL) { \
+ h->strA = NULL; \
+ h->strW = name ? _wcsdup(name) : NULL; \
+ h->extra1 = 0; /* reserved */ \
+ h->extra2 = NULL; /* reserved */ \
+ h->next = NULL; \
+ if (h_tail == NULL) \
+ (gptr)->string_list = h; \
+ else \
+ h_tail->next = h; \
+ } \
+}
+
+#define NEW_STRING_HANDLE_A(gptr,h,h_tail,name) { \
+ h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \
+ if (h != NULL) { \
+ h->strA = name ? __itt_fstrdup(name) : NULL; \
+ h->strW = NULL; \
+ h->extra1 = 0; /* reserved */ \
+ h->extra2 = NULL; /* reserved */ \
+ h->next = NULL; \
+ if (h_tail == NULL) \
+ (gptr)->string_list = h; \
+ else \
+ h_tail->next = h; \
+ } \
+}
+
+#define NEW_COUNTER_W(gptr,h,h_tail,name,domain,type) { \
+ h = (__itt_counter_info_t*)malloc(sizeof(__itt_counter_info_t)); \
+ if (h != NULL) { \
+ h->nameA = NULL; \
+ h->nameW = name ? _wcsdup(name) : NULL; \
+ h->domainA = NULL; \
+ h->domainW = name ? _wcsdup(domain) : NULL; \
+ h->type = type; \
+ h->index = 0; \
+ h->next = NULL; \
+ if (h_tail == NULL) \
+ (gptr)->counter_list = h; \
+ else \
+ h_tail->next = h; \
+ } \
+}
+
+#define NEW_COUNTER_A(gptr,h,h_tail,name,domain,type) { \
+ h = (__itt_counter_info_t*)malloc(sizeof(__itt_counter_info_t)); \
+ if (h != NULL) { \
+ h->nameA = name ? __itt_fstrdup(name) : NULL; \
+ h->nameW = NULL; \
+ h->domainA = domain ? __itt_fstrdup(domain) : NULL; \
+ h->domainW = NULL; \
+ h->type = type; \
+ h->index = 0; \
+ h->next = NULL; \
+ if (h_tail == NULL) \
+ (gptr)->counter_list = h; \
+ else \
+ h_tail->next = h; \
+ } \
+}
+
+#endif /* _ITTNOTIFY_CONFIG_H_ */
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_types.h b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_types.h
new file mode 100644
index 0000000000..99fbc24054
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/ittnotify_types.h
@@ -0,0 +1,94 @@
+/* <copyright>
+
+ Contact Information:
+ http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
+
+ BSD LICENSE
+
+ Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</copyright> */
+
+#ifndef _ITTNOTIFY_TYPES_H_
+#define _ITTNOTIFY_TYPES_H_
+
+typedef enum ___itt_group_id
+{
+ __itt_group_none = 0,
+ __itt_group_legacy = 1<<0,
+ __itt_group_control = 1<<1,
+ __itt_group_thread = 1<<2,
+ __itt_group_mark = 1<<3,
+ __itt_group_sync = 1<<4,
+ __itt_group_fsync = 1<<5,
+ __itt_group_jit = 1<<6,
+ __itt_group_model = 1<<7,
+ __itt_group_splitter_min = 1<<7,
+ __itt_group_counter = 1<<8,
+ __itt_group_frame = 1<<9,
+ __itt_group_stitch = 1<<10,
+ __itt_group_heap = 1<<11,
+ __itt_group_splitter_max = 1<<12,
+ __itt_group_structure = 1<<12,
+ __itt_group_suppress = 1<<13,
+ __itt_group_arrays = 1<<14,
+ __itt_group_all = -1
+} __itt_group_id;
+
+#pragma pack(push, 8)
+
+typedef struct ___itt_group_list
+{
+ __itt_group_id id;
+ const char* name;
+} __itt_group_list;
+
+#pragma pack(pop)
+
+#define ITT_GROUP_LIST(varname) \
+ static __itt_group_list varname[] = { \
+ { __itt_group_all, "all" }, \
+ { __itt_group_control, "control" }, \
+ { __itt_group_thread, "thread" }, \
+ { __itt_group_mark, "mark" }, \
+ { __itt_group_sync, "sync" }, \
+ { __itt_group_fsync, "fsync" }, \
+ { __itt_group_jit, "jit" }, \
+ { __itt_group_model, "model" }, \
+ { __itt_group_counter, "counter" }, \
+ { __itt_group_frame, "frame" }, \
+ { __itt_group_stitch, "stitch" }, \
+ { __itt_group_heap, "heap" }, \
+ { __itt_group_structure, "structure" }, \
+ { __itt_group_suppress, "suppress" }, \
+ { __itt_group_arrays, "arrays" }, \
+ { __itt_group_none, NULL } \
+ }
+
+#endif /* _ITTNOTIFY_TYPES_H_ */
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.c b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.c
new file mode 100644
index 0000000000..15f4b9929b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.c
@@ -0,0 +1,293 @@
+/* <copyright>
+
+ Contact Information:
+ http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
+
+ BSD LICENSE
+
+ Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</copyright> */
+
+#include "ittnotify_config.h"
+
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+#include <windows.h>
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+#if ITT_PLATFORM != ITT_PLATFORM_MAC && ITT_PLATFORM != ITT_PLATFORM_FREEBSD
+#include <malloc.h>
+#endif
+#include <stdlib.h>
+
+#include "jitprofiling.h"
+
+static const char rcsid[] = "\n@(#) $Revision: 471937 $\n";
+
+#define DLL_ENVIRONMENT_VAR "VS_PROFILER"
+
+#ifndef NEW_DLL_ENVIRONMENT_VAR
+#if ITT_ARCH==ITT_ARCH_IA32
+#define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER32"
+#else
+#define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER64"
+#endif
+#endif /* NEW_DLL_ENVIRONMENT_VAR */
+
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+#define DEFAULT_DLLNAME "JitPI.dll"
+HINSTANCE m_libHandle = NULL;
+#elif ITT_PLATFORM==ITT_PLATFORM_MAC
+#define DEFAULT_DLLNAME "libJitPI.dylib"
+void* m_libHandle = NULL;
+#else
+#define DEFAULT_DLLNAME "libJitPI.so"
+void* m_libHandle = NULL;
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+
+/* default location of JIT profiling agent on Android */
+#define ANDROID_JIT_AGENT_PATH "/data/intel/libittnotify.so"
+
+/* the function pointers */
+typedef unsigned int(JITAPI *TPInitialize)(void);
+static TPInitialize FUNC_Initialize=NULL;
+
+typedef unsigned int(JITAPI *TPNotify)(unsigned int, void*);
+static TPNotify FUNC_NotifyEvent=NULL;
+
+static iJIT_IsProfilingActiveFlags executionMode = iJIT_NOTHING_RUNNING;
+
+/* end collector dll part. */
+
+/* loadiJIT_Funcs() : this function is called just in the beginning
+ * and is responsible to load the functions from BistroJavaCollector.dll
+ * result:
+ * on success: the functions loads, iJIT_DLL_is_missing=0, return value = 1
+ * on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 0
+ */
+static int loadiJIT_Funcs(void);
+
+/* global representing whether the collector can't be loaded */
+static int iJIT_DLL_is_missing = 0;
+
+ITT_EXTERN_C int JITAPI
+iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData)
+{
+ int ReturnValue = 0;
+
+ /* initialization part - the collector has not been loaded yet. */
+ if (!FUNC_NotifyEvent)
+ {
+ if (iJIT_DLL_is_missing)
+ return 0;
+
+ if (!loadiJIT_Funcs())
+ return 0;
+ }
+
+ if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED ||
+ event_type == iJVM_EVENT_TYPE_METHOD_UPDATE)
+ {
+ if (((piJIT_Method_Load)EventSpecificData)->method_id == 0)
+ return 0;
+ }
+ else if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2)
+ {
+ if (((piJIT_Method_Load_V2)EventSpecificData)->method_id == 0)
+ return 0;
+ }
+ else if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V3)
+ {
+ if (((piJIT_Method_Load_V3)EventSpecificData)->method_id == 0)
+ return 0;
+ }
+ else if (event_type == iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED)
+ {
+ if (((piJIT_Method_Inline_Load)EventSpecificData)->method_id == 0 ||
+ ((piJIT_Method_Inline_Load)EventSpecificData)->parent_method_id == 0)
+ return 0;
+ }
+
+ ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData);
+
+ return ReturnValue;
+}
+
+ITT_EXTERN_C iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive()
+{
+ if (!iJIT_DLL_is_missing)
+ {
+ loadiJIT_Funcs();
+ }
+
+ return executionMode;
+}
+
+/* This function loads the collector dll and the relevant functions.
+ * on success: all functions load, iJIT_DLL_is_missing = 0, return value = 1
+ * on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0
+ */
+static int loadiJIT_Funcs()
+{
+ static int bDllWasLoaded = 0;
+ char *dllName = (char*)rcsid; /* !! Just to avoid unused code elimination */
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+ DWORD dNameLength = 0;
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+
+ if(bDllWasLoaded)
+ {
+ /* dll was already loaded, no need to do it for the second time */
+ return 1;
+ }
+
+ /* Assumes that the DLL will not be found */
+ iJIT_DLL_is_missing = 1;
+ FUNC_NotifyEvent = NULL;
+
+ if (m_libHandle)
+ {
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+ FreeLibrary(m_libHandle);
+#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+ dlclose(m_libHandle);
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+ m_libHandle = NULL;
+ }
+
+ /* Try to get the dll name from the environment */
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+ dNameLength = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, NULL, 0);
+ if (dNameLength)
+ {
+ DWORD envret = 0;
+ dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
+ if(dllName != NULL)
+ {
+ envret = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR,
+ dllName, dNameLength);
+ if (envret)
+ {
+ /* Try to load the dll from the PATH... */
+ m_libHandle = LoadLibraryExA(dllName,
+ NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+ }
+ free(dllName);
+ }
+ } else {
+ /* Try to use old VS_PROFILER variable */
+ dNameLength = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, NULL, 0);
+ if (dNameLength)
+ {
+ DWORD envret = 0;
+ dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
+ if(dllName != NULL)
+ {
+ envret = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR,
+ dllName, dNameLength);
+ if (envret)
+ {
+ /* Try to load the dll from the PATH... */
+ m_libHandle = LoadLibraryA(dllName);
+ }
+ free(dllName);
+ }
+ }
+ }
+#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+ dllName = getenv(NEW_DLL_ENVIRONMENT_VAR);
+ if (!dllName)
+ dllName = getenv(DLL_ENVIRONMENT_VAR);
+#if defined(__ANDROID__) || defined(ANDROID)
+ if (!dllName)
+ dllName = ANDROID_JIT_AGENT_PATH;
+#endif
+ if (dllName)
+ {
+ /* Try to load the dll from the PATH... */
+ m_libHandle = dlopen(dllName, RTLD_LAZY);
+ }
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+
+ if (!m_libHandle)
+ {
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+ m_libHandle = LoadLibraryA(DEFAULT_DLLNAME);
+#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+ m_libHandle = dlopen(DEFAULT_DLLNAME, RTLD_LAZY);
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+ }
+
+ /* if the dll wasn't loaded - exit. */
+ if (!m_libHandle)
+ {
+ iJIT_DLL_is_missing = 1; /* don't try to initialize
+ * JIT agent the second time
+ */
+ return 0;
+ }
+
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+ FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent");
+#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+ FUNC_NotifyEvent = (TPNotify)dlsym(m_libHandle, "NotifyEvent");
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+ if (!FUNC_NotifyEvent)
+ {
+ FUNC_Initialize = NULL;
+ return 0;
+ }
+
+#if ITT_PLATFORM==ITT_PLATFORM_WIN
+ FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize");
+#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+ FUNC_Initialize = (TPInitialize)dlsym(m_libHandle, "Initialize");
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
+ if (!FUNC_Initialize)
+ {
+ FUNC_NotifyEvent = NULL;
+ return 0;
+ }
+
+ executionMode = (iJIT_IsProfilingActiveFlags)FUNC_Initialize();
+
+ bDllWasLoaded = 1;
+ iJIT_DLL_is_missing = 0; /* DLL is ok. */
+
+ return 1;
+}
+
+ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID()
+{
+ static unsigned int methodID = 1;
+
+ if (methodID == 0)
+ return 0; /* ERROR : this is not a valid value */
+
+ return methodID++;
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.h b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.h
new file mode 100644
index 0000000000..bf0489b1a1
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.h
@@ -0,0 +1,673 @@
+/* <copyright>
+
+ Contact Information:
+ http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
+
+ BSD LICENSE
+
+ Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</copyright> */
+
+#ifndef __JITPROFILING_H__
+#define __JITPROFILING_H__
+
+/**
+ * @brief JIT Profiling APIs
+ *
+ * The JIT Profiling API is used to report information about just-in-time
+ * generated code that can be used by performance tools. The user inserts
+ * calls in the code generator to report information before JIT-compiled
+ * code goes to execution. This information is collected at runtime and used
+ * by tools like Intel(R) VTune(TM) Amplifier to display performance metrics
+ * associated with JIT-compiled code.
+ *
+ * These APIs can be used to\n
+ * - **Profile trace-based and method-based JIT-compiled
+ * code**. Some examples of environments that you can profile with these APIs:
+ * dynamic JIT compilation of JavaScript code traces, JIT execution in OpenCL(TM)
+ * software technology, Java/.NET managed execution environments, and custom
+ * ISV JIT engines.
+ * @code
+ * #include <jitprofiling.h>
+ *
+ * if (iJIT_IsProfilingActive != iJIT_SAMPLING_ON) {
+ * return;
+ * }
+ *
+ * iJIT_Method_Load jmethod = {0};
+ * jmethod.method_id = iJIT_GetNewMethodID();
+ * jmethod.method_name = "method_name";
+ * jmethod.class_file_name = "class_name";
+ * jmethod.source_file_name = "source_file_name";
+ * jmethod.method_load_address = code_addr;
+ * jmethod.method_size = code_size;
+ *
+ * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod);
+ * iJIT_NotifyEvent(iJVM_EVENT_TYPE_SHUTDOWN, NULL);
+ * @endcode
+ *
+ * * Expected behavior:
+ * * If any iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event overwrites an
+ * already reported method, then such a method becomes invalid and its
+ * memory region is treated as unloaded. VTune Amplifier displays the metrics
+ * collected by the method until it is overwritten.
+ * * If supplied line number information contains multiple source lines for
+ * the same assembly instruction (code location), then VTune Amplifier picks up
+ * the first line number.
+ * * Dynamically generated code can be associated with a module name.
+ * Use the iJIT_Method_Load_V2 structure.\n
+ * Clarification of some cases:
+ * * If you register a function with the same method ID multiple times,
+ * specifying different module names, then the VTune Amplifier picks up
+ * the module name registered first. If you want to distinguish the same
+ * function between different JIT engines, supply different method IDs for
+ * each function. Other symbolic information (for example, source file)
+ * can be identical.
+ *
+ * - **Analyze split functions** (multiple joint or disjoint code regions
+ * belonging to the same function) **including re-JIT**
+ * with potential overlapping of code regions in time, which is common in
+ * resource-limited environments.
+ * @code
+ * #include <jitprofiling.h>
+ *
+ * unsigned int method_id = iJIT_GetNewMethodID();
+ *
+ * iJIT_Method_Load a = {0};
+ * a.method_id = method_id;
+ * a.method_load_address = 0x100;
+ * a.method_size = 0x20;
+ *
+ * iJIT_Method_Load b = {0};
+ * b.method_id = method_id;
+ * b.method_load_address = 0x200;
+ * b.method_size = 0x30;
+ *
+ * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&a);
+ * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&b);
+ * @endcode
+ *
+ * * Expected behaviour:
+ * * If a iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event overwrites an
+ * already reported method, then such a method becomes invalid and
+ * its memory region is treated as unloaded.
+ * * All code regions reported with the same method ID are considered as
+ * belonging to the same method. Symbolic information (method name,
+ * source file name) will be taken from the first notification, and all
+ * subsequent notifications with the same method ID will be processed
+ * only for line number table information. So, the VTune Amplifier will map
+ * samples to a source line using the line number table from the current
+ * notification while taking the source file name from the very first one.\n
+ * Clarification of some cases:\n
+ * * If you register a second code region with a different source file
+ * name and the same method ID, then this information will be saved and
+ * will not be considered as an extension of the first code region, but
+ * VTune Amplifier will use the source file of the first code region and map
+ * performance metrics incorrectly.
+ * * If you register a second code region with the same source file as
+ * for the first region and the same method ID, then the source file will be
+ * discarded but VTune Amplifier will map metrics to the source file correctly.
+ * * If you register a second code region with a null source file and
+ * the same method ID, then provided line number info will be associated
+ * with the source file of the first code region.
+ *
+ * - **Explore inline functions** including multi-level hierarchy of
+ * nested inline methods which shows how performance metrics are distributed through them.
+ * @code
+ * #include <jitprofiling.h>
+ *
+ * // method_id parent_id
+ * // [-- c --] 3000 2000
+ * // [---- d -----] 2001 1000
+ * // [---- b ----] 2000 1000
+ * // [------------ a ----------------] 1000 n/a
+ *
+ * iJIT_Method_Load a = {0};
+ * a.method_id = 1000;
+ *
+ * iJIT_Method_Inline_Load b = {0};
+ * b.method_id = 2000;
+ * b.parent_method_id = 1000;
+ *
+ * iJIT_Method_Inline_Load c = {0};
+ * c.method_id = 3000;
+ * c.parent_method_id = 2000;
+ *
+ * iJIT_Method_Inline_Load d = {0};
+ * d.method_id = 2001;
+ * d.parent_method_id = 1000;
+ *
+ * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&a);
+ * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, (void*)&b);
+ * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, (void*)&c);
+ * iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, (void*)&d);
+ * @endcode
+ *
+ * * Requirements:
+ * * Each inline (iJIT_Method_Inline_Load) method should be associated
+ * with two method IDs: one for itself; one for its immediate parent.
+ * * Address regions of inline methods of the same parent method cannot
+ * overlap each other.
+ * * Execution of the parent method must not be started until it and all
+ * its inline methods are reported.
+ * * Expected behaviour:
+ * * In case of nested inline methods an order of
+ * iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED events is not important.
+ * * If any event overwrites either inline method or top parent method,
+ * then the parent, including inline methods, becomes invalid and its memory
+ * region is treated as unloaded.
+ *
+ * **Life time of allocated data**\n
+ * The client sends an event notification to the agent with event-specific
+ * data, which is a structure. The pointers in the structure refer to memory
+ * allocated by the client, which responsible for releasing it. The pointers are
+ * used by the iJIT_NotifyEvent method to copy client's data in a trace file,
+ * and they are not used after the iJIT_NotifyEvent method returns.
+ */
+
+/**
+ * @defgroup jitapi JIT Profiling
+ * @ingroup internal
+ * @{
+ */
+
+/**
+ * @brief Enumerator for the types of notifications
+ */
+typedef enum iJIT_jvm_event
+{
+ iJVM_EVENT_TYPE_SHUTDOWN = 2, /**<\brief Send this to shutdown the agent.
+ * Use NULL for event data. */
+
+ iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED = 13, /**<\brief Send when dynamic code is
+ * JIT compiled and loaded into
+ * memory by the JIT engine, but
+ * before the code is executed.
+ * Use iJIT_Method_Load as event
+ * data. */
+/** @cond exclude_from_documentation */
+ iJVM_EVENT_TYPE_METHOD_UNLOAD_START, /**<\brief Send when compiled dynamic
+ * code is being unloaded from memory.
+ * Use iJIT_Method_Load as event data.*/
+/** @endcond */
+
+ iJVM_EVENT_TYPE_METHOD_UPDATE, /**<\brief Send to provide new content for
+ * a previously reported dynamic code.
+ * The previous content will be invalidated
+ * starting from the time of the notification.
+ * Use iJIT_Method_Load as event data but
+ * required fields are following:
+ * - method_id identify the code to update.
+ * - method_load_address specify start address
+ * within identified code range
+ * where update should be started.
+ * - method_size specify length of updated code
+ * range. */
+
+
+ iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED, /**<\brief Send when an inline dynamic
+ * code is JIT compiled and loaded
+ * into memory by the JIT engine,
+ * but before the parent code region
+ * starts executing.
+ * Use iJIT_Method_Inline_Load as event data.*/
+
+/** @cond exclude_from_documentation */
+ iJVM_EVENT_TYPE_METHOD_UPDATE_V2,
+/** @endcond */
+
+ iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2 = 21, /**<\brief Send when a dynamic code is
+ * JIT compiled and loaded into
+ * memory by the JIT engine, but
+ * before the code is executed.
+ * Use iJIT_Method_Load_V2 as event data. */
+
+ iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V3 /**<\brief Send when a dynamic code is
+ * JIT compiled and loaded into
+ * memory by the JIT engine, but
+ * before the code is executed.
+ * Use iJIT_Method_Load_V3 as event data. */
+} iJIT_JVM_EVENT;
+
+/**
+ * @brief Enumerator for the agent's mode
+ */
+typedef enum _iJIT_IsProfilingActiveFlags
+{
+ iJIT_NOTHING_RUNNING = 0x0000, /**<\brief The agent is not running;
+ * iJIT_NotifyEvent calls will
+ * not be processed. */
+ iJIT_SAMPLING_ON = 0x0001, /**<\brief The agent is running and
+ * ready to process notifications. */
+} iJIT_IsProfilingActiveFlags;
+
+/**
+ * @brief Description of a single entry in the line number information of a code region.
+ * @details A table of line number entries gives information about how the reported code region
+ * is mapped to source file.
+ * Intel(R) VTune(TM) Amplifier uses line number information to attribute
+ * the samples (virtual address) to a line number. \n
+ * It is acceptable to report different code addresses for the same source line:
+ * @code
+ * Offset LineNumber
+ * 1 2
+ * 12 4
+ * 15 2
+ * 18 1
+ * 21 30
+ *
+ * VTune Amplifier constructs the following table using the client data
+ *
+ * Code subrange Line number
+ * 0-1 2
+ * 1-12 4
+ * 12-15 2
+ * 15-18 1
+ * 18-21 30
+ * @endcode
+ */
+typedef struct _LineNumberInfo
+{
+ unsigned int Offset; /**<\brief Offset from the begining of the code region. */
+ unsigned int LineNumber; /**<\brief Matching source line number offset (from beginning of source file). */
+
+} *pLineNumberInfo, LineNumberInfo;
+
+/**
+ * @brief Enumerator for the code architecture.
+ */
+typedef enum _iJIT_CodeArchitecture
+{
+ iJIT_CA_NATIVE = 0, /**<\brief Native to the process architecture that is calling it. */
+
+ iJIT_CA_32, /**<\brief 32-bit machine code. */
+
+ iJIT_CA_64 /**<\brief 64-bit machine code. */
+
+} iJIT_CodeArchitecture;
+
+#pragma pack(push, 8)
+
+/**
+ * @brief Description of a JIT-compiled method
+ * @details When you use the iJIT_Method_Load structure to describe
+ * the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED
+ * as an event type to report it.
+ */
+typedef struct _iJIT_Method_Load
+{
+ unsigned int method_id; /**<\brief Unique method ID. Cannot be 0.
+ * You must either use the API function
+ * iJIT_GetNewMethodID to get a valid and unique
+ * method ID, or else manage ID uniqueness
+ * and correct range by yourself.\n
+ * You must use the same method ID for all code
+ * regions of the same method, otherwise different
+ * method IDs specify different methods. */
+
+ char* method_name; /**<\brief The name of the method. It can be optionally
+ * prefixed with its class name and appended with
+ * its complete signature. Can't be NULL. */
+
+ void* method_load_address; /**<\brief The start virtual address of the method code
+ * region. If NULL, data provided with
+ * event are not accepted. */
+
+ unsigned int method_size; /**<\brief The code size of the method in memory.
+ * If 0, then data provided with the event are not
+ * accepted. */
+
+ unsigned int line_number_size; /**<\brief The number of entries in the line number
+ * table.0 if none. */
+
+ pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info
+ * array. Can be NULL if
+ * line_number_size is 0. See
+ * LineNumberInfo Structure for a
+ * description of a single entry in
+ * the line number info array */
+
+ unsigned int class_id; /**<\brief This field is obsolete. */
+
+ char* class_file_name; /**<\brief Class name. Can be NULL.*/
+
+ char* source_file_name; /**<\brief Source file name. Can be NULL.*/
+
+} *piJIT_Method_Load, iJIT_Method_Load;
+
+/**
+ * @brief Description of a JIT-compiled method
+ * @details When you use the iJIT_Method_Load_V2 structure to describe
+ * the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2
+ * as an event type to report it.
+ */
+typedef struct _iJIT_Method_Load_V2
+{
+ unsigned int method_id; /**<\brief Unique method ID. Cannot be 0.
+ * You must either use the API function
+ * iJIT_GetNewMethodID to get a valid and unique
+ * method ID, or else manage ID uniqueness
+ * and correct range by yourself.\n
+ * You must use the same method ID for all code
+ * regions of the same method, otherwise different
+ * method IDs specify different methods. */
+
+ char* method_name; /**<\brief The name of the method. It can be optionally
+ * prefixed with its class name and appended with
+ * its complete signature. Can't be NULL. */
+
+ void* method_load_address; /**<\brief The start virtual address of the method code
+ * region. If NULL, then data provided with the
+ * event are not accepted. */
+
+ unsigned int method_size; /**<\brief The code size of the method in memory.
+ * If 0, then data provided with the event are not
+ * accepted. */
+
+ unsigned int line_number_size; /**<\brief The number of entries in the line number
+ * table. 0 if none. */
+
+ pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info
+ * array. Can be NULL if
+ * line_number_size is 0. See
+ * LineNumberInfo Structure for a
+ * description of a single entry in
+ * the line number info array. */
+
+ char* class_file_name; /**<\brief Class name. Can be NULL. */
+
+ char* source_file_name; /**<\brief Source file name. Can be NULL. */
+
+ char* module_name; /**<\brief Module name. Can be NULL.
+ The module name can be useful for distinguishing among
+ different JIT engines. VTune Amplifier will display
+ reported methods grouped by specific module. */
+
+} *piJIT_Method_Load_V2, iJIT_Method_Load_V2;
+
+/**
+ * @brief Description of a JIT-compiled method
+ * @details The iJIT_Method_Load_V3 structure is the same as iJIT_Method_Load_V2
+ * with a newly introduced 'arch' field that specifies architecture of the code region.
+ * When you use the iJIT_Method_Load_V3 structure to describe
+ * the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V3
+ * as an event type to report it.
+ */
+typedef struct _iJIT_Method_Load_V3
+{
+ unsigned int method_id; /**<\brief Unique method ID. Cannot be 0.
+ * You must either use the API function
+ * iJIT_GetNewMethodID to get a valid and unique
+ * method ID, or manage ID uniqueness
+ * and correct range by yourself.\n
+ * You must use the same method ID for all code
+ * regions of the same method, otherwise they are
+ * treated as regions of different methods. */
+
+ char* method_name; /**<\brief The name of the method. It can be optionally
+ * prefixed with its class name and appended with
+ * its complete signature. Cannot be NULL. */
+
+ void* method_load_address; /**<\brief The start virtual address of the method code
+ * region. If NULL, then data provided with the
+ * event are not accepted. */
+
+ unsigned int method_size; /**<\brief The code size of the method in memory.
+ * If 0, then data provided with the event are not
+ * accepted. */
+
+ unsigned int line_number_size; /**<\brief The number of entries in the line number
+ * table. 0 if none. */
+
+ pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info
+ * array. Can be NULL if
+ * line_number_size is 0. See
+ * LineNumberInfo Structure for a
+ * description of a single entry in
+ * the line number info array. */
+
+ char* class_file_name; /**<\brief Class name. Can be NULL. */
+
+ char* source_file_name; /**<\brief Source file name. Can be NULL. */
+
+ char* module_name; /**<\brief Module name. Can be NULL.
+ * The module name can be useful for distinguishing among
+ * different JIT engines. VTune Amplifier will display
+ * reported methods grouped by specific module. */
+
+ iJIT_CodeArchitecture module_arch; /**<\brief Architecture of the method's code region.
+ * By default, it is the same as the process
+ * architecture that is calling it.
+ * For example, you can use it if your 32-bit JIT
+ * engine generates 64-bit code.
+ *
+ * If JIT engine reports both 32-bit and 64-bit types
+ * of methods then VTune Amplifier splits the methods
+ * with the same module name but with different
+ * architectures in two different modules. VTune Amplifier
+ * modifies the original name provided with a 64-bit method
+ * version by ending it with '(64)' */
+
+} *piJIT_Method_Load_V3, iJIT_Method_Load_V3;
+
+/**
+ * @brief Description of an inline JIT-compiled method
+ * @details When you use the_iJIT_Method_Inline_Load structure to describe
+ * the JIT compiled method, use iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED
+ * as an event type to report it.
+ */
+typedef struct _iJIT_Method_Inline_Load
+{
+ unsigned int method_id; /**<\brief Unique method ID. Cannot be 0.
+ * You must either use the API function
+ * iJIT_GetNewMethodID to get a valid and unique
+ * method ID, or else manage ID uniqueness
+ * and correct range by yourself. */
+
+ unsigned int parent_method_id; /**<\brief Unique immediate parent's method ID.
+ * Cannot be 0.
+ * You must either use the API function
+ * iJIT_GetNewMethodID to get a valid and unique
+ * method ID, or else manage ID uniqueness
+ * and correct range by yourself. */
+
+ char* method_name; /**<\brief The name of the method. It can be optionally
+ * prefixed with its class name and appended with
+ * its complete signature. Can't be NULL. */
+
+ void* method_load_address; /** <\brief The virtual address on which the method
+ * is inlined. If NULL, then data provided with
+ * the event are not accepted. */
+
+ unsigned int method_size; /**<\brief The code size of the method in memory.
+ * If 0, then data provided with the event are not
+ * accepted. */
+
+ unsigned int line_number_size; /**<\brief The number of entries in the line number
+ * table. 0 if none. */
+
+ pLineNumberInfo line_number_table; /**<\brief Pointer to the line numbers info
+ * array. Can be NULL if
+ * line_number_size is 0. See
+ * LineNumberInfo Structure for a
+ * description of a single entry in
+ * the line number info array */
+
+ char* class_file_name; /**<\brief Class name. Can be NULL.*/
+
+ char* source_file_name; /**<\brief Source file name. Can be NULL.*/
+
+} *piJIT_Method_Inline_Load, iJIT_Method_Inline_Load;
+
+/** @cond exclude_from_documentation */
+/**
+ * @brief Description of a segment type
+ * @details Use the segment type to specify a type of data supplied
+ * with the iJVM_EVENT_TYPE_METHOD_UPDATE_V2 event to be applied to
+ * a certain code trace.
+ */
+typedef enum _iJIT_SegmentType
+{
+ iJIT_CT_UNKNOWN = 0,
+
+ iJIT_CT_CODE, /**<\brief Executable code. */
+
+ iJIT_CT_DATA, /**<\brief Data (not executable code).
+ * VTune Amplifier uses the format string
+ * (see iJIT_Method_Update) to represent
+ * this data in the VTune Amplifier GUI */
+
+ iJIT_CT_KEEP, /**<\brief Use the previous markup for the trace.
+ * Can be used for the following
+ * iJVM_EVENT_TYPE_METHOD_UPDATE_V2 events,
+ * if the type of the previously reported segment
+ * type is the same. */
+ iJIT_CT_EOF
+} iJIT_SegmentType;
+
+/**
+ * @brief Description of a dynamic update of the content within JIT-compiled method
+ * @details The JIT engine may generate the methods that are updated at runtime
+ * partially by mixed (data + executable code) content. When you use the iJIT_Method_Update
+ * structure to describe the update of the content within a JIT-compiled method,
+ * use iJVM_EVENT_TYPE_METHOD_UPDATE_V2 as an event type to report it.
+ *
+ * On the first Update event, VTune Amplifier copies the original code range reported by
+ * the iJVM_EVENT_TYPE_METHOD_LOAD event, then modifies it with the supplied bytes and
+ * adds the modified range to the original method. For next update events, VTune Amplifier
+ * does the same but it uses the latest modified version of a code region for update.
+ * Eventually, VTune Amplifier GUI displays multiple code ranges for the method reported by
+ * the iJVM_EVENT_TYPE_METHOD_LOAD event.
+ * Notes:
+ * - Multiple update events with different types for the same trace are allowed
+ * but they must be reported for the same code ranges.
+ * Example,
+ * @code
+ * [-- data---] Allowed
+ * [-- code --] Allowed
+ * [code] Ignored
+ * [-- data---] Allowed
+ * [-- code --] Allowed
+ * [------------ trace ---------]
+ * @endcode
+ * - The types of previously reported events can be changed but they must be reported
+ * for the same code ranges.
+ * Example,
+ * @code
+ * [-- data---] Allowed
+ * [-- code --] Allowed
+ * [-- data---] Allowed
+ * [-- code --] Allowed
+ * [------------ trace ---------]
+ * @endcode
+ */
+
+typedef struct _iJIT_Method_Update
+{
+ void* load_address; /**<\brief Start address of the update within a method */
+
+ unsigned int size; /**<\brief The update size */
+
+ iJIT_SegmentType type; /**<\brief Type of the update */
+
+ const char* data_format; /**<\brief C string that contains a format string
+ * that follows the same specifications as format in printf.
+ * The format string is used for iJIT_CT_CODE only
+ * and cannot be NULL.
+ * Format can be changed on the fly. */
+} *piJIT_Method_Update, iJIT_Method_Update;
+
+/** @endcond */
+
+#pragma pack(pop)
+
+/** @cond exclude_from_documentation */
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef JITAPI_CDECL
+# if defined WIN32 || defined _WIN32
+# define JITAPI_CDECL __cdecl
+# else /* defined WIN32 || defined _WIN32 */
+# if defined _M_IX86 || defined __i386__
+# define JITAPI_CDECL __attribute__ ((cdecl))
+# else /* _M_IX86 || __i386__ */
+# define JITAPI_CDECL /* actual only on x86_64 platform */
+# endif /* _M_IX86 || __i386__ */
+# endif /* defined WIN32 || defined _WIN32 */
+#endif /* JITAPI_CDECL */
+
+#define JITAPI JITAPI_CDECL
+/** @endcond */
+
+/**
+ * @brief Generates a new unique method ID.
+ *
+ * You must use this API to obtain unique and valid method IDs for methods or
+ * traces reported to the agent if you don't have your own mechanism to generate
+ * unique method IDs.
+ *
+ * @return a new unique method ID. When out of unique method IDs, this API
+ * returns 0, which is not an accepted value.
+ */
+unsigned int JITAPI iJIT_GetNewMethodID(void);
+
+/**
+ * @brief Returns the current mode of the agent.
+ *
+ * @return iJIT_SAMPLING_ON, indicating that agent is running, or
+ * iJIT_NOTHING_RUNNING if no agent is running.
+ */
+iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive(void);
+
+/**
+ * @brief Reports infomation about JIT-compiled code to the agent.
+ *
+ * The reported information is used to attribute samples obtained from any
+ * Intel(R) VTune(TM) Amplifier collector. This API needs to be called
+ * after JIT compilation and before the first entry into the JIT-compiled
+ * code.
+ *
+ * @param[in] event_type - type of the data sent to the agent
+ * @param[in] EventSpecificData - pointer to event-specific data
+ *
+ * @returns 1 on success, otherwise 0.
+ */
+int JITAPI iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+/** @endcond */
+
+/** @} jitapi group */
+
+#endif /* __JITPROFILING_H__ */
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.cpp
new file mode 100644
index 0000000000..ef4c42bacf
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.cpp
@@ -0,0 +1,317 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <math.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+#include "nstl.hpp"
+
+#include "nchw_pooling.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t data_type>
+void nchw_pooling_fwd_t<data_type>::execute_forward(
+ const exec_ctx_t &ctx) const {
+ using namespace alg_kind;
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+ auto ws = CTX_OUT_MEM(unsigned char *, MKLDNN_ARG_WORKSPACE);
+
+ const memory_desc_wrapper ws_d(pd()->workspace_md());
+ const data_type_t ws_dt = ws ? ws_d.data_type() : data_type::undef;
+
+ const int MB = pd()->MB();
+ const int C = pd()->C();
+ const int OD = pd()->OD();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+ const int ID = pd()->ID();
+ const int IH = pd()->IH();
+ const int IW = pd()->IW();
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+ const int SD = pd()->KSD();
+ const int SH = pd()->KSH();
+ const int SW = pd()->KSW();
+ const int padF = pd()->padFront();
+ const int padT = pd()->padT();
+ const int padL = pd()->padL();
+
+ auto alg = pd()->desc()->alg_kind;
+
+ auto apply_offset = [=](int index, int offset) {
+ return (index > offset) ? index - offset : 0;
+ };
+
+ auto set_ws = [=](int mb, int c, int od, int oh, int ow, int value) {
+ if (ws) {
+ assert(ws_dt == data_type::u8 || ws_dt == data_type::s32);
+ size_t ws_offset
+ = (size_t)OW * OH * OD * C * mb
+ + (size_t)OW * OH * OD * c
+ + (size_t)OW * OH * od
+ + (size_t)OW * oh
+ + (size_t)ow;
+ if (ws_dt == data_type::u8) {
+ assert(0 <= value && value <= 255);
+ ws[ws_offset] = value;
+ } else
+ reinterpret_cast<int *>(ws)[ws_offset] = value;
+ }
+ };
+
+ auto ker_max = [=](data_t *d, int mb, int c, int od, int oh, int ow) {
+ for (int kd = 0; kd < KD; ++kd) {
+ for (int kh = 0; kh < KH; ++kh) {
+ for (int kw = 0; kw < KW; ++kw) {
+ const int id = od * SD - padF + kd;
+ const int ih = oh * SH - padT + kh;
+ const int iw = ow * SW - padL + kw;
+
+ if (id < 0 || id >= ID) continue;
+ if (ih < 0 || ih >= IH) continue;
+ if (iw < 0 || iw >= IW) continue;
+
+ auto src_offset
+ = (size_t)IW * IH * ID * C * mb
+ + (size_t)IW * IH * ID * c
+ + (size_t)IW * IH * id
+ + (size_t)IW * ih
+ + (size_t)iw;
+ auto s = src[src_offset];
+ if (s > d[0]) {
+ d[0] = s;
+ set_ws(mb, c, od, oh, ow, kd*KH*KW + kh*KW + kw);
+ }
+ }
+ }
+ }
+ };
+
+ auto ker_avg = [=](data_t *d, int mb, int c, int od, int oh, int ow) {
+ auto id_start = apply_offset(od*SD, padF);
+ auto ih_start = apply_offset(oh*SH, padT);
+ auto iw_start = apply_offset(ow*SW, padL);
+ auto id_end = nstl::min(od*SD - padF + KD, ID);
+ auto ih_end = nstl::min(oh*SH - padT + KH, IH);
+ auto iw_end = nstl::min(ow*SW - padL + KW, IW);
+
+ auto num_summands = (alg == pooling_avg_include_padding) ? KD*KW*KH
+ : (id_end - id_start)*(ih_end - ih_start)*(iw_end - iw_start);
+
+ for (int id = id_start; id < id_end; ++id) {
+ for (int ih = ih_start; ih < ih_end; ++ih) {
+ for (int iw = iw_start; iw < iw_end; ++iw) {
+ auto src_offset
+ = (size_t)IW * IH * ID * C * mb
+ + (size_t)IW * IH * ID * c
+ + (size_t)IW * IH * id
+ + (size_t)IW * ih
+ + (size_t)iw;
+ d[0] += src[src_offset];
+ }
+ }
+ }
+
+ d[0] = math::out_round<data_t>((float)d[0] / num_summands);
+ };
+
+
+ if (pd()->desc()->alg_kind == pooling_max) {
+ parallel_nd(MB, C, OD, OH, OW,
+ [&](int mb, int c, int od, int oh, int ow) {
+ size_t dst_offset
+ = (size_t)OW * OH * OD * C * mb
+ + (size_t)OW * OH * OD * c
+ + (size_t)OW * OH * od
+ + (size_t)OW * oh
+ + (size_t)ow;
+ data_t *d = &dst[dst_offset];
+ d[0] = nstl::numeric_limits<data_t>::lowest();
+ set_ws(mb, c, od, oh, ow, 0);
+ ker_max(d, mb, c, od, oh, ow);
+ });
+ } else {
+ parallel_nd(MB, C, OD, OH, OW,
+ [&](int mb, int c, int od, int oh, int ow) {
+ size_t dst_offset
+ = (size_t)OW * OH * OD * C * mb
+ + (size_t)OW * OH * OD * c
+ + (size_t)OW * OH * od
+ + (size_t)OW * oh
+ + (size_t)ow;
+ data_t *d = &dst[dst_offset];
+ d[0] = 0;
+ ker_avg(d, mb, c, od, oh, ow);
+ });
+ }
+}
+
+template <impl::data_type_t data_type>
+void nchw_pooling_bwd_t<data_type>::execute_backward(
+ const exec_ctx_t &ctx) const {
+ using namespace alg_kind;
+
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto ws = CTX_IN_MEM(const unsigned char *, MKLDNN_ARG_WORKSPACE);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper ws_d(pd()->workspace_md());
+
+ const int MB = pd()->MB();
+ const int C = pd()->C();
+ const int OD = pd()->OD();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+ const int ID = pd()->ID();
+ const int IH = pd()->IH();
+ const int IW = pd()->IW();
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+ const int SD = pd()->KSD();
+ const int SH = pd()->KSH();
+ const int SW = pd()->KSW();
+ const int padF = pd()->padFront();
+ const int padT = pd()->padT();
+ const int padL = pd()->padL();
+
+ const bool is_3d = pd()->desc()->diff_src_desc.ndims == 5;
+
+ auto alg = pd()->desc()->alg_kind;
+
+ auto apply_offset = [=](int index, int offset) {
+ return (index > offset) ? index - offset : 0;
+ };
+
+ auto ker_zero = [=](int mb, int c) {
+ size_t diff_src_offset = (size_t)mb*C*ID*IH*IW + (size_t)c*ID*IH*IW;
+ for (int id = 0; id < ID; ++id) {
+ for (int ih = 0; ih < IH; ++ih) {
+ for (int iw = 0; iw < IW; ++iw) {
+ diff_src[diff_src_offset++] = 0;
+ }
+ }
+ }
+ };
+
+ auto ker_max = [=](const data_t *d, int mb, int c, int od, int oh, int ow) {
+ auto b_c = ws_d.blocking_desc().inner_nblks == 0
+ ? 1 : ws_d.blocking_desc().inner_blks[0];
+ auto ws_offset = is_3d
+ ? ws_d.blk_off(mb, c / b_c, od, oh, ow) + c % b_c
+ : ws_d.blk_off(mb, c / b_c, oh, ow) + c % b_c;
+
+ const int index = ws_d.data_type() == data_type::u8
+ ? (int)ws[ws_offset] : ((const int *)ws)[ws_offset];
+ const int kw = index % KW;
+ const int kh = (index / KW) % KH;
+ const int kd = (index / KW) / KH;
+
+ const int id = od * SD - padF + kd;
+ const int ih = oh * SH - padT + kh;
+ const int iw = ow * SW - padL + kw;
+
+ // If padding area could fit the kernel,
+ // then input displacement would be out of bounds.
+ // No need to back propagate there as padding is
+ // virtual in pooling_max case.
+ if (id < 0 || id >= ID)
+ return;
+ if (ih < 0 || ih >= IH)
+ return;
+ if (iw < 0 || iw >= IW)
+ return;
+
+ size_t diff_src_offset =
+ (size_t)mb*C*ID*IH*IW + (size_t)c*ID*IH*IW + (size_t)id*IH*IW
+ + (size_t)ih*IW + (size_t)iw;
+ diff_src[diff_src_offset] += d[0];
+ };
+
+ auto ker_avg = [=](const data_t *d, int mb, int c, int od, int oh, int ow) {
+ auto id_start = apply_offset(od*SD, padF);
+ auto ih_start = apply_offset(oh*SH, padT);
+ auto iw_start = apply_offset(ow*SW, padL);
+ auto id_end = nstl::min(od*SD - padF + KD, ID);
+ auto ih_end = nstl::min(oh*SH - padT + KH, IH);
+ auto iw_end = nstl::min(ow*SW - padL + KW, IW);
+
+ size_t num_summands = (alg == pooling_avg_include_padding)
+ ? (size_t)KW*KH*KD
+ : (size_t)(id_end - id_start)*(ih_end - ih_start)
+ *(iw_end - iw_start);
+
+ for (int id = id_start; id < id_end; ++id) {
+ for (int ih = ih_start; ih < ih_end; ++ih) {
+ for (int iw = iw_start; iw < iw_end; ++iw) {
+ size_t diff_src_offset = (size_t)mb*C*ID*IH*IW
+ + (size_t)c*ID*IH*IW + (size_t)id*IH*IW
+ + (size_t)ih*IW + (size_t)iw;
+ diff_src[diff_src_offset] += d[0] / num_summands;
+ }
+ }
+ }
+ };
+
+ if (pd()->desc()->alg_kind == pooling_max) {
+ parallel_nd(MB, C, [&](int mb, int c) {
+ size_t diff_dst_offset = (size_t)mb*C*OD*OH*OW
+ + (size_t)c*OD*OH*OW;
+ ker_zero(mb, c);
+ for (int od = 0; od < OD; ++od) {
+ for (int oh = 0; oh < OH; ++oh) {
+ for (int ow = 0; ow < OW; ++ow) {
+ const data_t *d = &diff_dst[diff_dst_offset++];
+ ker_max(d, mb, c, od, oh, ow);
+ }
+ }
+ }
+ });
+ } else {
+ parallel_nd(MB, C, [&](int mb, int c) {
+ size_t diff_dst_offset = (size_t)mb*C*OD*OH*OW
+ + (size_t)c*OD*OH*OW;
+ ker_zero(mb, c);
+ for (int od = 0; od < OD; ++od) {
+ for (int oh = 0; oh < OH; ++oh) {
+ for (int ow = 0; ow < OW; ++ow) {
+ const data_t *d = &diff_dst[diff_dst_offset++];
+ ker_avg(d, mb, c, od, oh, ow);
+ }
+ }
+ }
+ });
+ }
+}
+
+template struct nchw_pooling_fwd_t<data_type::f32>;
+template struct nchw_pooling_bwd_t<data_type::f32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.hpp
new file mode 100644
index 0000000000..bbdd04f6b9
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/nchw_pooling.hpp
@@ -0,0 +1,147 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_NCHW_POOLING_HPP
+#define CPU_NCHW_POOLING_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_pooling_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t data_type>
+struct nchw_pooling_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_pooling_fwd_pd_t {
+ using cpu_pooling_fwd_pd_t::cpu_pooling_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T("nchw_pooling:any", nchw_pooling_fwd_t);
+
+ status_t init() {
+ const format_tag_t desired_fmt_tag =
+ ndims() == 4 ? format_tag::nchw : format_tag::ncdhw;
+
+ bool ok = true
+ && set_default_params() == status::success
+ && is_fwd()
+ && utils::one_of(desc()->alg_kind, alg_kind::pooling_max,
+ alg_kind::pooling_avg_include_padding,
+ alg_kind::pooling_avg_exclude_padding)
+ && !has_zero_dim_memory()
+ && utils::everyone_is(data_type, src_md()->data_type,
+ dst_md()->data_type)
+ && attr()->has_default_values()
+ && memory_desc_matches_tag(*src_md(), desired_fmt_tag)
+ && memory_desc_matches_tag(*dst_md(), desired_fmt_tag);
+ if (!ok) return status::unimplemented;
+
+ bool is_training = desc_.prop_kind == prop_kind::forward_training;
+ if (desc()->alg_kind == alg_kind::pooling_max && is_training)
+ init_default_ws();
+
+ return status::success;
+ }
+ };
+
+ nchw_pooling_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t data_type>
+struct nchw_pooling_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_pooling_bwd_pd_t {
+ using cpu_pooling_bwd_pd_t::cpu_pooling_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T("nchw:any", nchw_pooling_bwd_t);
+
+ status_t init() {
+ const format_tag_t desired_fmt_tag =
+ ndims() == 4 ? format_tag::nchw : format_tag::ncdhw;
+
+ bool ok = true
+ && set_default_params() == status::success
+ && !is_fwd()
+ && utils::one_of(desc()->alg_kind, alg_kind::pooling_max,
+ alg_kind::pooling_avg_include_padding,
+ alg_kind::pooling_avg_exclude_padding)
+ && !has_zero_dim_memory()
+ && utils::everyone_is(data_type,
+ diff_dst_md()->data_type,
+ diff_src_md()->data_type)
+ && attr()->has_default_values()
+ && memory_desc_matches_tag(*diff_dst_md(), desired_fmt_tag)
+ && memory_desc_matches_tag(*diff_src_md(), desired_fmt_tag);
+ if (!ok) return status::unimplemented;
+
+ if (desc()->alg_kind == alg_kind::pooling_max) {
+ bool ws_ok = true
+ && hint_fwd_pd_
+ && hint_fwd_pd_->workspace_md();
+ if (!ws_ok)
+ return status::unimplemented;
+
+ const auto &ws_blk =
+ hint_fwd_pd_->workspace_md()->format_desc.blocking;
+ ws_ok = ws_ok
+ && ws_blk.inner_nblks < 1
+ && IMPLICATION(ws_blk.inner_nblks == 1,
+ ws_blk.inner_idxs[0] == 1);
+ if (!ws_ok)
+ return status::unimplemented;
+
+ ws_md_ = *hint_fwd_pd_->workspace_md();
+ }
+
+ return status::success;
+ }
+ };
+
+ nchw_pooling_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.cpp
new file mode 100644
index 0000000000..c0e93fefe4
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.cpp
@@ -0,0 +1,382 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <math.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+
+#include "cpu_batch_normalization_utils.hpp"
+#include "jit_generator.hpp"
+
+#include "ncsp_batch_normalization.hpp"
+
+// clang 6 and 7 generate incorrect code with OMP_SIMD in some particular cases
+#if (defined __clang_major__) && (__clang_major__ >= 6)
+#define SAFE_TO_USE_OMP_SIMD 0
+#else
+#define SAFE_TO_USE_OMP_SIMD 1
+#endif
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace memory_tracking::names;
+
+void ncsp_batch_normalization_fwd_t::execute_forward(
+ const exec_ctx_t &ctx) const {
+ const bool calculate_stats = !pd()->stats_is_src();
+ const bool save_stats = pd()->is_training();
+ const bool is_training = pd()->is_training();
+ const bool fuse_bn_relu = pd()->fuse_bn_relu();
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto scaleshift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT);
+
+ auto scratchpad = this->scratchpad(ctx);
+ auto *ws_reduce = scratchpad.get<data_t>(key_bnorm_reduction);
+
+ data_t *mean, *variance;
+ if (!calculate_stats) {
+ mean = const_cast<data_t *>(
+ CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN));
+ variance = const_cast<data_t *>(
+ CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE));
+ } else {
+ if (save_stats) {
+ mean = CTX_OUT_MEM(data_t *, MKLDNN_ARG_MEAN);
+ variance = CTX_OUT_MEM(data_t *, MKLDNN_ARG_VARIANCE);
+ } else {
+ mean = scratchpad.get<data_t>(key_bnorm_tmp_mean);
+ variance = scratchpad.get<data_t>(key_bnorm_tmp_var);
+ }
+ }
+
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+ auto ws = CTX_OUT_MEM(uint8_t *, MKLDNN_ARG_WORKSPACE);
+
+ const float eps = pd()->desc()->batch_norm_epsilon;
+ const bool use_scaleshift = pd()->use_scaleshift();
+ const bool with_relu = pd()->with_relu_post_op();
+ auto maybe_post_op
+ = [&](data_t res) { return (with_relu && res < 0) ? 0 : res; };
+ const bool has_spatial = utils::one_of(pd()->ndims(), 4, 5);
+ dim_t SP = (has_spatial) ? pd()->H() * pd()->W() * pd()->D() : 1;
+ dim_t N = pd()->MB();
+ dim_t C = pd()->C();
+
+ int nthr = mkldnn_get_max_threads();
+ size_t l3_size_ = get_cache_size(3, true) * nthr / 2;
+ size_t data_size = N * C * SP * sizeof(data_t);
+ bool do_blocking = (data_size >= l3_size_ / 2 && l3_size_ > 0);
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ int C_ithr = 0, C_nthr = 0;
+ int N_ithr = 0, N_nthr = 0;
+ int S_ithr = 0, S_nthr = 0;
+
+ dim_t C_blk_gl_s = 0, C_blk_gl_e = 0, C_blk_s = 0, C_blk_e = 0;
+ dim_t N_s = 0, N_e = 0;
+ dim_t S_s = 0, S_e = 0;
+
+ dim_t C_blks_per_iter = 1;
+ int64_t iters = 1;
+
+ if (do_blocking) {
+ size_t working_set_size = N * SP * sizeof(data_t);
+ bnorm_utils::cache_balance(
+ working_set_size, C, C_blks_per_iter, iters);
+ } else
+ C_blks_per_iter = C;
+ int64_t last_iter_blks = C - (iters - 1) * C_blks_per_iter;
+ bool spatial_thr_allowed
+ = bnorm_utils::thread_balance(do_blocking, true, ithr, nthr, N,
+ C_blks_per_iter, SP, C_ithr, C_nthr, C_blk_s, C_blk_e,
+ N_ithr, N_nthr, N_s, N_e, S_ithr, S_nthr, S_s, S_e);
+ balance211(C_blks_per_iter, nthr, ithr, C_blk_gl_s, C_blk_gl_e);
+ int SP_N_ithr = N_ithr * S_nthr + S_ithr;
+ int SP_N_nthr = N_nthr * S_nthr;
+ for (int64_t it = 0; it < iters; ++it) {
+ if (it == iters - 1 && iters > 1) {
+ // On the last iteration the access pattern to ws_reduce
+ // might change (due to re-balance on C). So sync the
+ // threads if they are not synced by the algorithm.
+ if (SP_N_nthr == 1 && mkldnn_thr_syncable())
+ mkldnn_thr_barrier();
+
+ S_s = S_e = C_blk_s = C_blk_e = N_s = N_e = 0;
+ spatial_thr_allowed = bnorm_utils::thread_balance(do_blocking,
+ spatial_thr_allowed, ithr, nthr, N, last_iter_blks, SP,
+ C_ithr, C_nthr, C_blk_s, C_blk_e, N_ithr, N_nthr, N_s,
+ N_e, S_ithr, S_nthr, S_s, S_e);
+ balance211(last_iter_blks, nthr, ithr, C_blk_gl_s, C_blk_gl_e);
+ SP_N_ithr = N_ithr * S_nthr + S_ithr;
+ SP_N_nthr = N_nthr * S_nthr;
+ }
+ size_t C_off = it * C_blks_per_iter;
+ // On the last iteration the access pattern to ws_reduce
+ // might change (due to re-balance on C). Since sync is not always
+ // possible (in case of TBB) use different parts of ws for each
+ // iteration if threads are not synced by the algorithm.
+ size_t ws_iter_off = (mkldnn_thr_syncable() ? 0 : 1) * C_off;
+
+ if (calculate_stats) {
+ data_t *mean_blk = mean + C_off;
+ data_t *variance_blk = variance + C_off;
+ for (dim_t c = C_blk_s; c < C_blk_e; c++) {
+ size_t off = (c + C_off) * SP;
+ data_t sum = 0;
+ for (dim_t n = N_s; n < N_e; ++n)
+ PRAGMA_OMP_SIMD(reduction(+ : sum))
+ for (dim_t sp = S_s; sp < S_e; ++sp) {
+ sum += src[off + n * C * SP + sp];
+ }
+ ws_reduce[ws_iter_off + SP_N_ithr * C_blks_per_iter + c]
+ = sum;
+ }
+
+ if (SP_N_nthr > 1) mkldnn_thr_barrier();
+
+ for (dim_t c = C_blk_gl_s; c < C_blk_gl_e; c++) {
+ mean_blk[c] = 0.;
+ for (dim_t n = 0; n < SP_N_nthr; n++)
+ mean_blk[c] += ws_reduce[ws_iter_off
+ + n * C_blks_per_iter + c];
+ mean_blk[c] /= (N * SP);
+ }
+
+ if (SP_N_nthr > 1) mkldnn_thr_barrier();
+
+ for (dim_t c = C_blk_s; c < C_blk_e; c++) {
+ size_t off = c + C_off;
+ data_t sum = 0.;
+ for (dim_t n = N_s; n < N_e; ++n)
+ PRAGMA_OMP_SIMD(reduction(+ : sum))
+ for (dim_t sp = S_s; sp < S_e; ++sp) {
+ data_t m = src[off * SP + n * C * SP + sp]
+ - mean[off];
+ sum += m * m;
+ }
+ ws_reduce[ws_iter_off + SP_N_ithr * C_blks_per_iter + c]
+ = sum;
+ }
+
+ if (SP_N_nthr > 1) mkldnn_thr_barrier();
+
+ for (dim_t c = C_blk_gl_s; c < C_blk_gl_e; c++) {
+ variance_blk[c] = 0.;
+ for (dim_t n = 0; n < SP_N_nthr; n++)
+ variance_blk[c] += ws_reduce[ws_iter_off
+ + n * C_blks_per_iter + c];
+ variance_blk[c] /= (N * SP);
+ }
+
+ if (SP_N_nthr > 1) mkldnn_thr_barrier();
+ }
+
+ for (dim_t c = C_blk_s; c < C_blk_e; c++) {
+ size_t off = c + C_off;
+ data_t sqrt_variance
+ = static_cast<data_t>(sqrtf(variance[off] + eps));
+ data_t sm = (use_scaleshift ? scaleshift[off] : 1.0f) / sqrt_variance;
+ data_t sv = use_scaleshift ? scaleshift[C + off] : 0;
+ for (dim_t n = N_s; n < N_e; ++n)
+#if SAFE_TO_USE_OMP_SIMD
+ PRAGMA_OMP_SIMD()
+#endif
+ for (dim_t sp = S_s; sp < S_e; ++sp) {
+ size_t d_off = off * SP + n * C * SP + sp;
+ data_t bn_res
+ = sm * (src[d_off] - mean[off]) + sv;
+ if (fuse_bn_relu) {
+ if (bn_res <= 0) {
+ bn_res = 0;
+ if (is_training)
+ ws[d_off] = 0;
+ } else {
+ if (is_training)
+ ws[d_off] = 1;
+ }
+ }
+ dst[d_off] = maybe_post_op(bn_res);
+ }
+ }
+ }
+ });
+}
+
+void ncsp_batch_normalization_bwd_t::execute_backward(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto mean = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN);
+ auto variance = CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto scaleshift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT);
+ auto ws = CTX_IN_MEM(const uint8_t *, MKLDNN_ARG_WORKSPACE);
+
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+ auto diff_scaleshift = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SCALE_SHIFT);
+
+ auto scratchpad = this->scratchpad(ctx);
+ auto *ws_reduce = scratchpad.get<data_t>(key_bnorm_reduction);
+
+ if (diff_scaleshift == nullptr)
+ diff_scaleshift = scratchpad.get<data_t>(key_bnorm_tmp_diff_ss);
+
+ const bool has_spatial = utils::one_of(pd()->ndims(), 4, 5);
+ dim_t SP = (has_spatial) ? pd()->H() * pd()->W() * pd()->D() : 1;
+ dim_t C = pd()->C(), N = pd()->MB();
+ const bool use_scaleshift = pd()->use_scaleshift();
+ const float eps = pd()->desc()->batch_norm_epsilon;
+ const bool calculate_diff_stats = !pd()->use_global_stats();
+ const bool fuse_bn_relu = pd()->fuse_bn_relu();
+
+ int nthr = mkldnn_get_max_threads();
+ size_t l3_size_ = get_cache_size(3, true) * nthr / 2;
+ size_t data_size = N * C * SP * sizeof(data_t);
+ bool do_blocking = (data_size >= l3_size_ / 2 && l3_size_ > 0);
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ int C_ithr = 0, C_nthr = 0;
+ int N_ithr = 0, N_nthr = 0;
+ int S_ithr = 0, S_nthr = 0;
+
+ dim_t C_blk_gl_s = 0, C_blk_gl_e = 0, C_blk_s = 0, C_blk_e = 0;
+ dim_t N_s = 0, N_e = 0;
+ dim_t S_s = 0, S_e = 0;
+
+ dim_t C_blks_per_iter = 1;
+ int64_t iters = 1;
+
+ if (do_blocking) {
+ size_t working_set_size = 2 * N * SP * sizeof(data_t);
+ bnorm_utils::cache_balance(
+ working_set_size, C, C_blks_per_iter, iters);
+ } else
+ C_blks_per_iter = C;
+ int64_t last_iter_blks = C - (iters - 1) * C_blks_per_iter;
+ bool spatial_thr_allowed
+ = bnorm_utils::thread_balance(do_blocking, true, ithr, nthr, N,
+ C_blks_per_iter, SP, C_ithr, C_nthr, C_blk_s, C_blk_e,
+ N_ithr, N_nthr, N_s, N_e, S_ithr, S_nthr, S_s, S_e);
+ balance211(C_blks_per_iter, nthr, ithr, C_blk_gl_s, C_blk_gl_e);
+ int SP_N_ithr = N_ithr * S_nthr + S_ithr;
+ int SP_N_nthr = N_nthr * S_nthr;
+
+ for (int64_t it = 0; it < iters; ++it) {
+ if (it == iters - 1 && iters > 1) {
+ // On the last iteration the access pattern to ws_reduce
+ // might change (due to re-balance on C). So sync the
+ // threads if they are not synced by the algorithm.
+ if (SP_N_nthr == 1 && mkldnn_thr_syncable())
+ mkldnn_thr_barrier();
+
+ C_blk_s = C_blk_e = N_s = N_e = 0;
+ spatial_thr_allowed = bnorm_utils::thread_balance(do_blocking,
+ spatial_thr_allowed, ithr, nthr, N, last_iter_blks, SP,
+ C_ithr, C_nthr, C_blk_s, C_blk_e, N_ithr, N_nthr, N_s,
+ N_e, S_ithr, S_nthr, S_s, S_e);
+ balance211(last_iter_blks, nthr, ithr, C_blk_gl_s, C_blk_gl_e);
+ SP_N_ithr = N_ithr * S_nthr + S_ithr;
+ SP_N_nthr = N_nthr * S_nthr;
+ }
+ size_t C_off = it * C_blks_per_iter;
+ // On the last iteration the access pattern to ws_reduce
+ // might change (due to re-balance on C). Since sync is not always
+ // possible (in case of TBB) use different parts of ws for each
+ // iteration if threads are not synced by the algorithm.
+ size_t ws_iter_off = (mkldnn_thr_syncable() ? 0 : 1) * 2 * C_off;
+
+ data_t *diff_gamma_blk = diff_scaleshift + C_off;
+ data_t *diff_beta_blk = diff_scaleshift + C + C_off;
+ for (dim_t c = C_blk_s; c < C_blk_e; c++) {
+ size_t off = c + C_off;
+ data_t diff_gamma = 0.0, diff_beta = 0.0;
+ data_t v_mean = mean[off];
+ for (dim_t n = N_s; n < N_e; ++n)
+ PRAGMA_OMP_SIMD(reduction(+ : diff_gamma, diff_beta))
+ for (dim_t sp = S_s; sp < S_e; ++sp) {
+ const size_t d_off = off * SP + n * C * SP + sp;
+ data_t dd;
+ if (fuse_bn_relu)
+ dd = (!ws[d_off]) ? 0 : diff_dst[d_off];
+ else
+ dd = diff_dst[d_off];
+ diff_gamma += (src[d_off] - v_mean) * dd;
+ diff_beta += dd;
+ }
+ ws_reduce[ws_iter_off + SP_N_ithr * C_blks_per_iter + c]
+ = diff_gamma;
+ ws_reduce[ws_iter_off + SP_N_nthr * C_blks_per_iter
+ + SP_N_ithr * C_blks_per_iter + c] = diff_beta;
+ }
+
+ if (SP_N_nthr > 1) mkldnn_thr_barrier();
+
+ for (dim_t c = C_blk_gl_s; c < C_blk_gl_e; c++) {
+ data_t sqrt_variance = static_cast<data_t>(
+ 1.0f / sqrtf(variance[c + C_off] + eps));
+ diff_gamma_blk[c] = 0.;
+ diff_beta_blk[c] = 0.;
+ for (dim_t n = 0; n < SP_N_nthr; n++) {
+ diff_gamma_blk[c] += ws_reduce[ws_iter_off
+ + n * C_blks_per_iter + c];
+ diff_beta_blk[c] += ws_reduce[ws_iter_off
+ + SP_N_nthr * C_blks_per_iter + n * C_blks_per_iter
+ + c];
+ }
+ diff_gamma_blk[c] *= sqrt_variance;
+ }
+
+ if (SP_N_nthr > 1) mkldnn_thr_barrier();
+
+ for (dim_t c = C_blk_s; c < C_blk_e; c++) {
+ size_t off = c + C_off;
+ data_t gamma = use_scaleshift ? scaleshift[off] : 1;
+ data_t sqrt_variance
+ = static_cast<data_t>(1.0f / sqrtf(variance[off] + eps));
+ data_t v_mean = mean[off];
+ for (dim_t n = N_s; n < N_e; ++n)
+#if SAFE_TO_USE_OMP_SIMD
+ PRAGMA_OMP_SIMD()
+#endif
+ for (dim_t sp = S_s; sp < S_e; ++sp) {
+ const size_t d_off = off * SP + n * C * SP + sp;
+
+ data_t v_diff_src;
+ if (fuse_bn_relu)
+ v_diff_src = (!ws[d_off]) ? 0 : diff_dst[d_off];
+ else
+ v_diff_src = diff_dst[d_off];
+ if (calculate_diff_stats) {
+ v_diff_src -= diff_beta_blk[c] / (SP * N)
+ + (src[d_off] - v_mean) * diff_gamma_blk[c]
+ * sqrt_variance / (SP * N);
+ }
+ v_diff_src *= gamma * sqrt_variance;
+ diff_src[d_off] = v_diff_src;
+ }
+ }
+ }
+ });
+}
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.hpp
new file mode 100644
index 0000000000..97ca3b003f
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ncsp_batch_normalization.hpp
@@ -0,0 +1,160 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_NCSP_BATCH_NORMALIZATION_HPP
+#define CPU_NCSP_BATCH_NORMALIZATION_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_batch_normalization_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct ncsp_batch_normalization_fwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_batch_normalization_fwd_pd_t {
+ using cpu_batch_normalization_fwd_pd_t::cpu_batch_normalization_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ncsp_bnorm:any", ncsp_batch_normalization_fwd_t);
+
+ status_t init() {
+ using namespace data_type;
+ using namespace prop_kind;
+ using namespace format_tag;
+
+ bool ok = true
+ && is_fwd()
+ && !has_zero_dim_memory()
+ && src_md()->data_type == f32
+ && IMPLICATION(use_scaleshift(), weights_md()->data_type == f32)
+ && memory_desc_matches_one_of_tag(*src_md(), ncdhw, nchw, nc)
+ && (attr()->has_default_values() || this->with_relu_post_op());
+ if (!ok) return status::unimplemented;
+
+ if (is_training() && fuse_bn_relu()) init_default_ws(8);
+
+ init_scratchpad();
+
+ return status::success;
+ }
+
+ private:
+ void init_scratchpad() {
+ using namespace memory_tracking::names;
+ auto scratchpad = scratchpad_registry().registrar();
+ if (!stats_is_src()) {
+ scratchpad.book(key_bnorm_reduction,
+ sizeof(data_t) * C() * mkldnn_get_max_threads());
+
+ if (!is_training()) {
+ scratchpad.book(key_bnorm_tmp_mean, sizeof(data_t) * C());
+ scratchpad.book(key_bnorm_tmp_var, sizeof(data_t) * C());
+ }
+ }
+ }
+ };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ ncsp_batch_normalization_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ ~ncsp_batch_normalization_fwd_t() {}
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+struct ncsp_batch_normalization_bwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_batch_normalization_bwd_pd_t {
+ using cpu_batch_normalization_bwd_pd_t::cpu_batch_normalization_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ncsp_bnorm:any", ncsp_batch_normalization_bwd_t);
+
+ status_t init() {
+ using namespace data_type;
+ using namespace format_tag;
+
+ bool ok = true
+ && is_bwd()
+ && !has_zero_dim_memory()
+ && utils::everyone_is(f32, src_md()->data_type,
+ diff_src_md()->data_type)
+ && IMPLICATION(use_scaleshift(),
+ utils::everyone_is(f32,
+ weights_md()->data_type,
+ diff_weights_md()->data_type))
+ && memory_desc_matches_one_of_tag(*src_md(), ncdhw, nchw, nc)
+ && memory_desc_matches_one_of_tag(*diff_src_md(), ncdhw, nchw, nc)
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ if (fuse_bn_relu()) {
+ init_default_ws(8);
+ if (!compare_ws(hint_fwd_pd_))
+ return status::unimplemented;
+ }
+
+ init_scratchpad();
+
+ return status::success;
+ }
+
+ private:
+ void init_scratchpad() {
+ using namespace memory_tracking::names;
+ auto scratchpad = scratchpad_registry().registrar();
+ scratchpad.book(key_bnorm_reduction,
+ sizeof(data_t) * 2 * C() * mkldnn_get_max_threads());
+ if (!(use_scaleshift() && desc()->prop_kind == prop_kind::backward))
+ scratchpad.book(key_bnorm_tmp_diff_ss,
+ sizeof(data_t) * 2 * C());
+ }
+ };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ ncsp_batch_normalization_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ ~ncsp_batch_normalization_bwd_t() {}
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.cpp
new file mode 100644
index 0000000000..38cfb28dce
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.cpp
@@ -0,0 +1,392 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <math.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+#include "nstl.hpp"
+
+#include "nhwc_pooling.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+#define MEM_D(name) name##_d
+
+#define DECLARE_READ_STRIDES(name) \
+ const size_t name##_n_stride = MEM_D(name).blocking_desc().strides[0]; \
+ const size_t name##_d_stride = (!is_3d) \
+ ? 0 \
+ : MEM_D(name).blocking_desc().strides[2]; \
+ const size_t name##_h_stride = (!is_3d) \
+ ? MEM_D(name).blocking_desc().strides[2] \
+ : MEM_D(name).blocking_desc().strides[3]; \
+ const size_t name##_w_stride = (!is_3d) \
+ ? MEM_D(name).blocking_desc().strides[3] \
+ : MEM_D(name).blocking_desc().strides[4];
+
+namespace nhwc_pooling {
+ size_t strided_offset(const int _n, const size_t _sn,
+ const int _d, const size_t _sd,
+ const int _h, const size_t _sh,
+ const int _w, const size_t _sw)
+ {
+ return _n * _sn
+ + _d * _sd
+ + _h * _sh
+ + _w * _sw;
+ }
+}
+
+template <impl::data_type_t data_type>
+void nhwc_pooling_fwd_t<data_type>::array_div_by_const(const int n,
+ const data_t *src, const size_t num, data_t *dst) const
+{
+ for (int i = 0; i < n; ++i)
+ {
+ float ftmp = (float)src[i];
+ ftmp = ftmp / num;
+ dst[i] = math::out_round<data_t>(ftmp);
+ }
+}
+
+template <impl::data_type_t data_type>
+void nhwc_pooling_fwd_t<data_type>::array_add(const int n, const data_t *src,
+ data_t *dst) const
+{
+ for (int i = 0; i < n; ++i)
+ {
+ dst[i] += src[i];
+ }
+}
+
+template <impl::data_type_t data_type>
+void nhwc_pooling_fwd_t<data_type>::execute_forward(
+ const exec_ctx_t &ctx) const {
+ using namespace alg_kind;
+ using namespace prop_kind;
+ using namespace nhwc_pooling;
+
+ auto alg = pd()->desc()->alg_kind;
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+ auto ws = CTX_OUT_MEM(unsigned char *, MKLDNN_ARG_WORKSPACE);
+
+ const memory_desc_wrapper MEM_D(src)(pd()->src_md());
+ const memory_desc_wrapper MEM_D(dst)(pd()->dst_md());
+ const memory_desc_wrapper MEM_D(ws)(pd()->workspace_md());
+
+ const int ID = pd()->ID();
+ const int IH = pd()->IH();
+ const int IW = pd()->IW();
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+ const int SD = pd()->KSD();
+ const int SH = pd()->KSH();
+ const int SW = pd()->KSW();
+ const int padF = pd()->padFront();
+ const int padT = pd()->padT();
+ const int padL = pd()->padL();
+ const int MB = pd()->MB();
+ const int OC = pd()->C();
+ const int OD = pd()->OD();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+
+ const bool is_3d = pd()->desc()->src_desc.ndims == 5;
+ const data_type_t ws_dt = ws ? ws_d.data_type() : data_type::undef;
+
+ DECLARE_READ_STRIDES(src);
+ DECLARE_READ_STRIDES(dst);
+
+ auto apply_offset = [=](int index, int offset) {
+ return (index > offset) ? index - offset : 0;
+ };
+
+ parallel_nd(MB, OD, OH, OW,
+ [&](int mb, int od, int oh, int ow) {
+ size_t dst_offset_init = strided_offset(mb, dst_n_stride,
+ od, dst_d_stride,
+ oh, dst_h_stride,
+ ow, dst_w_stride);
+ if (alg == pooling_max) {
+ size_t ws_offset_init = 0;
+ if (ws)
+ {
+ DECLARE_READ_STRIDES(ws);
+ ws_offset_init = strided_offset(mb, ws_n_stride,
+ od, ws_d_stride,
+ oh, ws_h_stride,
+ ow, ws_w_stride);
+ }
+ // Note: GCC 4.8.5 won't vectorize below
+ // simple loops unless they are singled out
+ // into separate helper routines:
+ // array_nhwc_initialize, array_nhwc_max
+ if (!ws)
+ array_nhwc_initialize<false>(OC, dst + dst_offset_init,
+ ws, ws_offset_init, ws_dt);
+ else
+ array_nhwc_initialize<true>(OC, dst + dst_offset_init,
+ ws, ws_offset_init, ws_dt);
+
+
+ for (int kd = 0; kd < KD; ++kd)
+ for (int kh = 0; kh < KH; ++kh)
+ for (int kw = 0; kw < KW; ++kw) {
+ const int id = od * SD - padF + kd;
+ const int ih = oh * SH - padT + kh;
+ const int iw = ow * SW - padL + kw;
+
+ if (id < 0 || id >= ID)
+ continue;
+ if (ih < 0 || ih >= IH)
+ continue;
+ if (iw < 0 || iw >= IW)
+ continue;
+
+ size_t src_offset_init = strided_offset(mb, src_n_stride,
+ id, src_d_stride,
+ ih, src_h_stride,
+ iw, src_w_stride);
+
+ if (!ws)
+ array_nhwc_max<false>(OC,
+ dst + dst_offset_init,
+ src + src_offset_init,
+ ws, ws_offset_init,
+ ws_dt,
+ kd * KH * KW + kh * KW + kw
+ );
+ else
+ array_nhwc_max<true>(OC,
+ dst + dst_offset_init,
+ src + src_offset_init,
+ ws, ws_offset_init,
+ ws_dt,
+ kd * KH * KW + kh * KW + kw
+ );
+ }
+ } else {
+ // pooling_avg
+ auto d = dst + dst_offset_init;
+
+ utils::array_set(d, 0, OC);
+
+ auto id_start = apply_offset(od * SD, padF);
+ auto ih_start = apply_offset(oh * SH, padT);
+ auto iw_start = apply_offset(ow * SW, padL);
+ auto id_end = nstl::min(od * SD - padF + KD, ID);
+ auto ih_end = nstl::min(oh * SH - padT + KH, IH);
+ auto iw_end = nstl::min(ow * SW - padL + KW, IW);
+
+ // it is cheaper to actually count this in a loop
+ // as the typical kernel is small
+ size_t num_summands = 0;
+
+ for (int id = id_start; id < id_end; ++id)
+ for (int ih = ih_start; ih < ih_end; ++ih)
+ for (int iw = iw_start; iw < iw_end; ++iw) {
+ size_t src_offset_init = strided_offset(mb, src_n_stride,
+ id, src_d_stride,
+ ih, src_h_stride,
+ iw, src_w_stride);
+ auto s = src + src_offset_init;
+
+ // need to move the loop to separate function
+ // for GCC 4.8.5 to vectorize
+ array_add(OC, s, d);
+
+ num_summands++;
+ }
+
+ num_summands = (alg == pooling_avg_include_padding) ?
+ KW * KH * KD : num_summands;
+
+ // need to move the loop to separate function
+ // for GCC 4.8.5 to vectorize
+ array_div_by_const(OC, d, num_summands, d);
+ }
+ });
+}
+
+template <impl::data_type_t data_type>
+void nhwc_pooling_bwd_t<data_type>::execute_backward(
+ const exec_ctx_t &ctx) const {
+ using namespace alg_kind;
+ using namespace nhwc_pooling;
+
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto ws = CTX_IN_MEM(const unsigned char *, MKLDNN_ARG_WORKSPACE);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper MEM_D(diff_src)(pd()->diff_src_md());
+ const memory_desc_wrapper MEM_D(diff_dst)(pd()->diff_dst_md());
+ const memory_desc_wrapper MEM_D(ws)(pd()->workspace_md());
+
+ const int ID = pd()->ID();
+ const int IH = pd()->IH();
+ const int IW = pd()->IW();
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+ const int SD = pd()->KSD();
+ const int SH = pd()->KSH();
+ const int SW = pd()->KSW();
+ const int OC = pd()->C();
+ const int padF = pd()->padFront();
+ const int padT = pd()->padT();
+ const int padL = pd()->padL();
+ const int OD = pd()->OD();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+
+ const bool is_3d = pd()->desc()->diff_src_desc.ndims == 5;
+ auto alg = pd()->desc()->alg_kind;
+
+ DECLARE_READ_STRIDES(diff_src);
+ DECLARE_READ_STRIDES(diff_dst);
+
+ auto apply_offset = [=](int index, int offset) {
+ return (index > offset) ? index - offset : 0;
+ };
+
+ const int MB = pd()->MB();
+
+ parallel_nd(MB, ID, IH, IW,
+ [&](int mb, int id, int ih, int iw) {
+ size_t src_offset_init = strided_offset(mb, diff_src_n_stride,
+ id, diff_src_d_stride,
+ ih, diff_src_h_stride,
+ iw, diff_src_w_stride);
+
+ // check if kernel windows are disjoint, in this case there's no
+ // update needed and we just write there once, no initialization
+ // required.
+ if (!(KD == SD && KH == SH && KW == SW))
+ for (int oc = 0; oc < OC; ++oc)
+ diff_src[src_offset_init + oc] = data_type_t(0);
+
+ // Find out which output cells may correspond to current
+ // input position. Current input postition divided by
+ // stride, with integer divide rounding down, is the
+ // right-most output.
+ // Left-most output may be computed if we decrement input
+ // by (kernel_size - 1) and then do the same division by
+ // stride.
+ int od_left = nstl::max((id + padF - KD + 1) / SD, 0);
+ int oh_left = nstl::max((ih + padT - KH + 1) / SH, 0);
+ int ow_left = nstl::max((iw + padL - KW + 1) / SW, 0);
+ // Notice +1 here to preserve the C loop "less than"
+ // condition for continuing the for loop.
+ int od_right = nstl::min((id + padF) / SD + 1 , OD);
+ int oh_right = nstl::min((ih + padT) / SH + 1 , OH);
+ int ow_right = nstl::min((iw + padL) / SW + 1 , OW);
+
+ for (int od = od_left; od < od_right; ++od)
+ for (int oh = oh_left; oh < oh_right; ++oh)
+ for (int ow = ow_left; ow < ow_right; ++ow) {
+ const int kd = id - od*SD + padF;
+ const int kh = ih - oh*SH + padT;
+ const int kw = iw - ow*SW + padL;
+
+ if (kd < 0 || kd >= KD)
+ continue;
+ if (kh < 0 || kh >= KH)
+ continue;
+ if (kw < 0 || kw >= KW)
+ continue;
+
+ size_t dst_offset_init = strided_offset(mb, diff_dst_n_stride,
+ od, diff_dst_d_stride,
+ oh, diff_dst_h_stride,
+ ow, diff_dst_w_stride);
+
+ if (alg == pooling_max) {
+ DECLARE_READ_STRIDES(ws);
+ size_t ws_offset_init = strided_offset(mb, ws_n_stride,
+ od, ws_d_stride,
+ oh, ws_h_stride,
+ ow, ws_w_stride);
+ const int index = kd * KH * KW + kh * KW + kw;
+
+ PRAGMA_OMP_SIMD()
+ for (int oc = 0; oc < OC; ++oc) {
+ const int index_from_ws =
+ (MEM_D(ws).data_type() == data_type::u8)
+ ? (int)ws[ws_offset_init + oc]
+ : ((int *)ws)[ws_offset_init + oc];
+
+ const data_t d = diff_dst[dst_offset_init + oc];
+
+ // Check if kernel windows are disjoint, in this case
+ // there's no update needed and we just write there once
+ // otherwise we add value to the contents.
+ if (!(KD == SD && KH == SH && KW == SW))
+ diff_src[src_offset_init + oc] +=
+ (index_from_ws == index)
+ ? d
+ : data_type_t(0);
+ else
+ diff_src[src_offset_init + oc] =
+ (index_from_ws == index)
+ ? d
+ : data_type_t(0);
+ }
+ } else {
+ // pooling_avg
+ auto id_start = apply_offset(od*SD, padF);
+ auto ih_start = apply_offset(oh*SH, padT);
+ auto iw_start = apply_offset(ow*SW, padL);
+ auto id_end = nstl::min(od*SD - padF + KD, ID);
+ auto ih_end = nstl::min(oh*SH - padT + KH, IH);
+ auto iw_end = nstl::min(ow*SW - padL + KW, IW);
+
+ auto num_summands = (alg == pooling_avg_include_padding)
+ ? KW*KH*KD
+ : (ih_end - ih_start)*(iw_end - iw_start)*(id_end - id_start);
+
+ PRAGMA_OMP_SIMD()
+ for (int oc = 0; oc < OC; ++oc) {
+ const data_t d = diff_dst[dst_offset_init + oc];
+ // Check if kernel windows are disjoint, in this case
+ // there's no update needed and we just write there once
+ // otherwise we add value to the contents.
+ if (!(KD == SD && KH == SH && KW == SW))
+ diff_src[src_offset_init + oc] += d / num_summands;
+ else
+ diff_src[src_offset_init + oc] = d / num_summands;
+ }
+ }
+ }
+ });
+}
+
+template struct nhwc_pooling_fwd_t<data_type::f32>;
+template struct nhwc_pooling_bwd_t<data_type::f32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.hpp
new file mode 100644
index 0000000000..7e33b6869f
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/nhwc_pooling.hpp
@@ -0,0 +1,210 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_NHWC_POOLING_HPP
+#define CPU_NHWC_POOLING_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_pooling_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace nhwc_pooling {
+size_t strided_offset(const int _n, const size_t _sn, const int _d,
+ const size_t _sd, const int _h, const size_t _sh, const int _w,
+ const size_t _sw);
+}
+
+template <impl::data_type_t data_type>
+struct nhwc_pooling_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_pooling_fwd_pd_t {
+ using cpu_pooling_fwd_pd_t::cpu_pooling_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T("nhwc_pooling:any", nhwc_pooling_fwd_t);
+
+ status_t init() {
+ const format_tag_t desired_fmt_tag =
+ ndims() == 4 ? format_tag::nhwc : format_tag::ndhwc;
+
+ bool ok = true
+ && set_default_params() == status::success
+ && is_fwd()
+ && utils::one_of(desc()->alg_kind, alg_kind::pooling_max,
+ alg_kind::pooling_avg_include_padding,
+ alg_kind::pooling_avg_exclude_padding)
+ && utils::everyone_is(data_type,
+ src_md()->data_type,
+ dst_md()->data_type)
+ && attr()->has_default_values()
+ && memory_desc_matches_tag(*src_md(), desired_fmt_tag)
+ && memory_desc_matches_tag(*dst_md(), desired_fmt_tag);
+ if (!ok) return status::unimplemented;
+
+ bool is_training = desc_.prop_kind == prop_kind::forward_training;
+ if (desc()->alg_kind == alg_kind::pooling_max && is_training)
+ init_default_ws();
+
+ return status::success;
+ }
+ };
+
+ nhwc_pooling_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ void array_div_by_const(const int n, const data_t *src, const size_t num,
+ data_t *dst) const;
+ void array_add(const int n, const data_t *src, data_t *dst) const;
+
+ template <bool use_workspace>
+ void array_nhwc_max(const int n, data_t *dst, const data_t *src,
+ unsigned char *ws, const size_t ws_offset, const data_type_t ws_dt,
+ const int index) const {
+ assert(!((use_workspace == false) ^ (!ws))); // ensure ws pointer exists
+ PRAGMA_OMP_SIMD()
+ for (int oc = 0; oc < n; ++oc) {
+ auto s = src[oc];
+ data_t mv = dst[oc];
+
+ // update index of maximum
+#if defined __INTEL_COMPILER
+ if ((use_workspace) && (s > mv)) {
+ assert(ws_dt == data_type::u8 || ws_dt == data_type::s32);
+ if (ws_dt == data_type::u8) {
+ assert(0 <= index && index <= 255);
+ ws[ws_offset + oc] = index;
+ } else
+ reinterpret_cast<int *>(ws)[ws_offset + oc] = index;
+ }
+#else
+ // Need to add explicit predicates for GCC to vectorize this.
+ // And although the resulting code is ugly, it is still 4 times
+ // faster than scalar
+ if (use_workspace) {
+ assert(ws_dt == data_type::u8 || ws_dt == data_type::s32);
+
+ if (ws_dt == data_type::u8) {
+ assert(0 <= index && index <= 255);
+ unsigned char predicate = (s > mv) ? 0xff : 0;
+ unsigned char current_value = ws[ws_offset + oc];
+ current_value = (predicate & (unsigned char)index)
+ | ((~predicate) & current_value);
+ ws[ws_offset + oc] = current_value;
+ } else {
+ auto wint = reinterpret_cast<int *>(ws);
+ unsigned int predicate = (s > mv) ? 0xffffffff : 0;
+ unsigned int current_value = wint[ws_offset + oc];
+ current_value = (predicate & (unsigned int)index)
+ | ((~predicate) & current_value);
+ wint[ws_offset + oc] = current_value;
+ }
+ }
+#endif
+ // update maximum
+ dst[oc] = nstl::max(s, mv);
+ }
+ }
+
+ template <bool use_workspace>
+ void array_nhwc_initialize(const int n, data_t *dst, unsigned char *ws,
+ const size_t ws_offset, const data_type_t ws_dt) const {
+ assert(!((use_workspace == false) ^ (!ws))); // ensure ws pointer exists
+ for (int oc = 0; oc < n; ++oc) {
+ if (use_workspace) {
+ assert(ws_dt == data_type::u8 || ws_dt == data_type::s32);
+ if (ws_dt == data_type::u8) {
+ ws[ws_offset + oc] = 0;
+ } else
+ reinterpret_cast<int *>(ws)[ws_offset + oc] = 0;
+ }
+ dst[oc] = nstl::numeric_limits<data_t>::lowest();
+ }
+ }
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t data_type>
+struct nhwc_pooling_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_pooling_bwd_pd_t {
+ using cpu_pooling_bwd_pd_t::cpu_pooling_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T("nhwc:any", nhwc_pooling_bwd_t);
+
+ status_t init() {
+ const format_tag_t desired_fmt_tag =
+ ndims() == 4 ? format_tag::nchw : format_tag::ncdhw;
+
+ bool ok = true
+ && set_default_params() == status::success
+ && !is_fwd()
+ && utils::one_of(desc()->alg_kind, alg_kind::pooling_max,
+ alg_kind::pooling_avg_include_padding,
+ alg_kind::pooling_avg_exclude_padding)
+ && utils::everyone_is(data_type,
+ diff_dst_md()->data_type,
+ diff_src_md()->data_type)
+ && attr()->has_default_values()
+ && memory_desc_matches_tag(*diff_dst_md(), desired_fmt_tag)
+ && memory_desc_matches_tag(*diff_src_md(), desired_fmt_tag);
+ if (!ok) return status::unimplemented;
+
+ if (desc()->alg_kind == alg_kind::pooling_max) {
+ init_default_ws();
+ if (!compare_ws(hint_fwd_pd_))
+ return status::unimplemented;
+ }
+
+ return status::success;
+ }
+ };
+
+ nhwc_pooling_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}// namespace cpu
+}// namespace impl
+}// namespace mkldnn
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.cpp
new file mode 100644
index 0000000000..e20333e66f
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.cpp
@@ -0,0 +1,288 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <math.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+
+#include "cpu_batch_normalization_utils.hpp"
+#include "jit_generator.hpp"
+
+#include "nspc_batch_normalization.hpp"
+
+// clang 6 and 7 generate incorrect code with OMP_SIMD in some particular cases
+#if (defined __clang_major__) && (__clang_major__ >= 6)
+#define SAFE_TO_USE_OMP_SIMD 0
+#else
+#define SAFE_TO_USE_OMP_SIMD 1
+#endif
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace memory_tracking::names;
+
+void nspc_batch_normalization_fwd_t::execute_forward(
+ const exec_ctx_t &ctx) const {
+ const bool save_stats = pd()->is_training();
+ const bool is_training = pd()->is_training();
+ const bool fuse_bn_relu = pd()->fuse_bn_relu();
+ const bool calculate_stats = !pd()->stats_is_src();
+ const bool with_relu = pd()->with_relu_post_op();
+
+ auto scratchpad = this->scratchpad(ctx);
+ auto tmp_mean = scratchpad.get<data_t>(key_bnorm_tmp_mean);
+ auto tmp_var = scratchpad.get<data_t>(key_bnorm_tmp_var);
+ auto *ws_reduce = scratchpad.get<data_t>(key_bnorm_reduction);
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto scaleshift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT);
+
+ data_t *mean, *variance;
+ if (!calculate_stats) {
+ mean = const_cast<data_t *>(
+ CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN));
+ variance = const_cast<data_t *>(
+ CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE));
+ } else {
+ if (save_stats) {
+ mean = CTX_OUT_MEM(data_t *, MKLDNN_ARG_MEAN);
+ variance = CTX_OUT_MEM(data_t *, MKLDNN_ARG_VARIANCE);
+ } else {
+ mean = tmp_mean;
+ variance = tmp_var;
+ }
+ }
+
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+ auto ws = CTX_OUT_MEM(uint8_t *, MKLDNN_ARG_WORKSPACE);
+
+ const dim_t N = pd()->MB();
+ const dim_t C = pd()->C();
+ const dim_t SP = pd()->H() * pd()->W() * pd()->D();
+
+ const float eps = pd()->desc()->batch_norm_epsilon;
+ const bool use_scaleshift = pd()->use_scaleshift();
+ auto maybe_post_op
+ = [&](data_t res) { return (with_relu && res < 0) ? 0 : res; };
+
+ assert(mkldnn_thr_syncable());
+ parallel(0, [&](const int ithr, const int nthr) {
+ dim_t N_s = 0, N_e = 0, C_s = 0, C_e = 0;
+ balance211(N, nthr, ithr, N_s, N_e);
+ balance211(C, nthr, ithr, C_s, C_e);
+ data_t *mean_loc = tmp_mean + nstl::max(C, (dim_t)16) * ithr;
+ data_t *variance_loc = tmp_var + nstl::max(C, (dim_t)16) * ithr;
+
+ if (calculate_stats) {
+ for (dim_t c = 0; c < C; c++)
+ ws_reduce[C * ithr + c] = 0.;
+
+ for (dim_t n = N_s; n < N_e; n++)
+ for (dim_t sp = 0; sp < SP; sp++)
+ PRAGMA_OMP_SIMD()
+ for (dim_t c = 0; c < C; c++)
+ ws_reduce[C * ithr + c] += src[(size_t)n * SP * C
+ + sp * C + c];
+
+ mkldnn_thr_barrier();
+
+ for (dim_t c = C_s; c < C_e; c++) {
+ mean[c] = 0;
+ for (dim_t n = 0; n < nthr; n++)
+ mean[c] += ws_reduce[C * n + c];
+ mean[c] /= SP * N;
+ }
+
+ mkldnn_thr_barrier();
+
+ for (dim_t c = 0; c < C; c++) {
+ mean_loc[c] = mean[c];
+ ws_reduce[C * ithr + c] = 0.;
+ }
+
+ for (dim_t n = N_s; n < N_e; n++)
+ for (dim_t sp = 0; sp < SP; sp++)
+ PRAGMA_OMP_SIMD()
+ for (dim_t c = 0; c < C; c++) {
+ data_t m = src[(size_t)n * SP * C + sp * C + c]
+ - mean_loc[c];
+ ws_reduce[C * ithr + c] += m * m;
+ }
+
+ mkldnn_thr_barrier();
+
+ for (dim_t c = C_s; c < C_e; c++) {
+ variance[c] = 0;
+ for (dim_t n = 0; n < nthr; n++)
+ variance[c] += ws_reduce[C * n + c];
+ variance[c] /= SP * N;
+ }
+
+ mkldnn_thr_barrier();
+
+ for (dim_t c = 0; c < C; c++)
+ variance_loc[c] = variance[c];
+ } else {
+ variance_loc = variance;
+ mean_loc = mean;
+ }
+
+ for (dim_t n = N_s; n < N_e; n++) {
+ for (dim_t sp = 0; sp < SP; sp++) {
+#if SAFE_TO_USE_OMP_SIMD
+ PRAGMA_OMP_SIMD()
+#endif
+ for (dim_t c = 0; c < C; c++) {
+ data_t sqrt_variance = static_cast<data_t>(
+ sqrtf(variance_loc[c] + eps));
+ data_t sm = (use_scaleshift ? scaleshift[c] : 1.0f) / sqrt_variance;
+ data_t sv = use_scaleshift ? scaleshift[C + c] : 0;
+ size_t d_off = (size_t)n * SP * C + sp * C + c;
+ data_t bn_res = sm * (src[d_off] - mean_loc[c]) + sv;
+ if (fuse_bn_relu) {
+ if (bn_res <= 0) {
+ bn_res = 0;
+ if (is_training)
+ ws[d_off] = 0;
+ } else {
+ if (is_training)
+ ws[d_off] = 1;
+ }
+ }
+ dst[d_off] = maybe_post_op(bn_res);
+ }
+ }
+ }
+ });
+}
+
+void nspc_batch_normalization_bwd_t::execute_backward(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto mean = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN);
+ auto variance = CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto scaleshift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT);
+ auto ws = CTX_IN_MEM(const uint8_t *, MKLDNN_ARG_WORKSPACE);
+
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+ auto diff_scaleshift = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SCALE_SHIFT);
+
+ auto scratchpad = this->scratchpad(ctx);
+ auto tmp_diff_ss = scratchpad.get<data_t>(key_bnorm_tmp_diff_ss);
+
+ if (diff_scaleshift == nullptr)
+ diff_scaleshift = tmp_diff_ss;
+
+ const dim_t N = pd()->MB();
+ const dim_t C = pd()->C();
+ const dim_t SP = pd()->D() * pd()->H() * pd()->W();
+ data_t *diff_gamma = diff_scaleshift, *diff_beta = diff_scaleshift + C;
+ auto *ws_reduce = scratchpad.get<data_t>(key_bnorm_reduction);
+
+ const float eps = pd()->desc()->batch_norm_epsilon;
+ const bool use_scaleshift = pd()->use_scaleshift();
+ const bool calculate_diff_stats = !pd()->use_global_stats();
+ const bool fuse_bn_relu = pd()->fuse_bn_relu();
+
+ assert(mkldnn_thr_syncable());
+ parallel(0, [&](const int ithr, const int nthr) {
+ dim_t N_s = 0, N_e = 0, C_s = 0, C_e = 0;
+ balance211(N, nthr, ithr, N_s, N_e);
+ balance211(C, nthr, ithr, C_s, C_e);
+
+ data_t *diff_gamma_loc = tmp_diff_ss + 2 * C + C * ithr;
+ data_t *diff_beta_loc = tmp_diff_ss + 2 * C + C * (nthr + ithr);
+
+ for (dim_t c = 0; c < C; c++) {
+ ws_reduce[C * ithr + c] = 0.;
+ ws_reduce[C * nthr + C * ithr + c] = 0.;
+ }
+
+ for (dim_t n = N_s; n < N_e; n++)
+ for (dim_t sp = 0; sp < SP; sp++)
+#if SAFE_TO_USE_OMP_SIMD
+ PRAGMA_OMP_SIMD()
+#endif
+ for (dim_t c = 0; c < C; c++) {
+ const size_t d_off = (size_t)n * SP * C + sp * C + c;
+ data_t dd;
+ if (fuse_bn_relu)
+ dd = (!ws[d_off]) ? 0 : diff_dst[d_off];
+ else
+ dd = diff_dst[d_off];
+ ws_reduce[C * ithr + c] += (src[d_off] - mean[c]) * dd;
+ ws_reduce[C * nthr + C * ithr + c] += dd;
+ }
+
+ mkldnn_thr_barrier();
+
+ for (dim_t c = C_s; c < C_e; c++) {
+ data_t sqrt_variance
+ = static_cast<data_t>(1.0f / sqrtf(variance[c] + eps));
+ diff_gamma[c] = 0;
+ diff_beta[c] = 0;
+ for (dim_t n = 0; n < nthr; n++) {
+ diff_gamma[c] += ws_reduce[C * n + c];
+ diff_beta[c] += ws_reduce[C * nthr + C * n + c];
+ }
+ diff_gamma[c] *= sqrt_variance;
+ }
+
+ mkldnn_thr_barrier();
+
+ for (dim_t c = 0; c < C; c++) {
+ diff_gamma_loc[c] = diff_gamma[c];
+ diff_beta_loc[c] = diff_beta[c];
+ }
+
+ for (dim_t n = N_s; n < N_e; n++) {
+ for (dim_t sp = 0; sp < SP; sp++) {
+#if SAFE_TO_USE_OMP_SIMD
+ PRAGMA_OMP_SIMD()
+#endif
+ for (dim_t c = 0; c < C; c++) {
+ const size_t d_off = (size_t)n * SP * C + sp * C + c;
+ data_t gamma = use_scaleshift ? scaleshift[c] : 1;
+ data_t sqrt_variance
+ = static_cast<data_t>(1.0f / sqrtf(variance[c] + eps));
+ data_t v_diff_src;
+ if (fuse_bn_relu)
+ v_diff_src = (!ws[d_off]) ? 0 : diff_dst[d_off];
+ else
+ v_diff_src = diff_dst[d_off];
+ if (calculate_diff_stats) {
+ v_diff_src -= diff_beta_loc[c] / (SP * N)
+ + (src[d_off] - mean[c]) * diff_gamma_loc[c]
+ * sqrt_variance / (SP * N);
+ }
+ v_diff_src *= gamma * sqrt_variance;
+ diff_src[d_off] = v_diff_src;
+ }
+ }
+ }
+ });
+}
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.hpp
new file mode 100644
index 0000000000..aad86b05a7
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/nspc_batch_normalization.hpp
@@ -0,0 +1,169 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_NSPC_BATCH_NORMALIZATION_HPP
+#define CPU_NSPC_BATCH_NORMALIZATION_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_batch_normalization_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct nspc_batch_normalization_fwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_batch_normalization_fwd_pd_t {
+ pd_t(engine_t *engine, const batch_normalization_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const batch_normalization_fwd_pd_t *hint_fwd_pd)
+ : cpu_batch_normalization_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ DECLARE_COMMON_PD_T("nspc_bnorm:any", nspc_batch_normalization_fwd_t);
+
+ status_t init() {
+ using namespace data_type;
+ using namespace prop_kind;
+
+ bool ok = true
+ /* the algorithm requires barriers while switching
+ * between parallelization over N and C dimensions */
+ && mkldnn_thr_syncable()
+ && is_fwd()
+ && !has_zero_dim_memory()
+ && src_md()->data_type == f32
+ && IMPLICATION(use_scaleshift(), weights_md()->data_type == f32)
+ && memory_desc_matches_tag(*src_md(), format_tag::nhwc)
+ && (attr()->has_default_values() || this->with_relu_post_op());
+ if (!ok) return status::unimplemented;
+
+ if (is_training() && fuse_bn_relu()) init_default_ws(8);
+
+ init_scratchpad();
+
+ return status::success;
+ }
+
+ private:
+ void init_scratchpad() {
+ using namespace memory_tracking::names;
+ auto scratchpad = scratchpad_registry().registrar();
+ if (!stats_is_src()) {
+ dim_t sz = nstl::max<dim_t>(C(), 16) * mkldnn_get_max_threads();
+ scratchpad.book(key_bnorm_reduction, sizeof(data_t) * sz);
+ scratchpad.book(key_bnorm_tmp_mean, sizeof(data_t) * sz);
+ scratchpad.book(key_bnorm_tmp_var, sizeof(data_t) * sz);
+ }
+ }
+ };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ nspc_batch_normalization_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ ~nspc_batch_normalization_fwd_t() {}
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+struct nspc_batch_normalization_bwd_t : public cpu_primitive_t {
+ struct pd_t : public cpu_batch_normalization_bwd_pd_t {
+ pd_t(engine_t *engine, const batch_normalization_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const batch_normalization_fwd_pd_t *hint_fwd_pd)
+ : cpu_batch_normalization_bwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ DECLARE_COMMON_PD_T("nspc_bnorm:any", nspc_batch_normalization_bwd_t);
+
+ status_t init() {
+ using namespace data_type;
+ using namespace prop_kind;
+
+ bool ok = true
+ /* the algorithm requires barriers while switching
+ * between parallelization over N and C dimensions */
+ && mkldnn_thr_syncable()
+ && is_bwd()
+ && !has_zero_dim_memory()
+ && utils::everyone_is(f32, src_md()->data_type,
+ diff_src_md()->data_type)
+ && IMPLICATION(use_scaleshift(),
+ utils::everyone_is(f32,
+ weights_md()->data_type,
+ diff_weights_md()->data_type))
+ && memory_desc_matches_tag(*src_md(), format_tag::nhwc)
+ && memory_desc_matches_tag(*diff_src_md(), format_tag::nhwc)
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ if (fuse_bn_relu()) {
+ init_default_ws(8);
+ if (!compare_ws(hint_fwd_pd_))
+ return status::unimplemented;
+ }
+
+ init_scratchpad();
+
+ return status::success;
+ }
+
+ private:
+ void init_scratchpad() {
+ using namespace memory_tracking::names;
+ auto scratchpad = scratchpad_registry().registrar();
+ scratchpad.book(key_bnorm_reduction,
+ sizeof(data_t) * 2 * C() * mkldnn_get_max_threads());
+ scratchpad.book(key_bnorm_tmp_diff_ss, sizeof(data_t) * 2 * C()
+ * (mkldnn_get_max_threads() + 1));
+ }
+ };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ nspc_batch_normalization_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ ~nspc_batch_normalization_bwd_t() {}
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.cpp
new file mode 100644
index 0000000000..d79b1a034b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.cpp
@@ -0,0 +1,265 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <math.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "mkldnn_thread.hpp"
+#include "simple_q10n.hpp"
+
+#include "ref_batch_normalization.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t data_type>
+void ref_batch_normalization_fwd_t<data_type>::execute_forward(
+ const exec_ctx_t &ctx) const {
+ /* fast return */
+ if (this->pd()->has_zero_dim_memory()) return;
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto scaleshift = CTX_IN_MEM(const float *, MKLDNN_ARG_SCALE_SHIFT);
+
+ auto mean = pd()->stats_is_src()
+ ? const_cast<float *>(CTX_IN_MEM(const float *, MKLDNN_ARG_MEAN))
+ : CTX_OUT_MEM(float *, MKLDNN_ARG_MEAN);
+ auto variance = pd()->stats_is_src()
+ ? const_cast<float *>(CTX_IN_MEM(const float *, MKLDNN_ARG_VARIANCE))
+ : CTX_OUT_MEM(float *, MKLDNN_ARG_VARIANCE);
+
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+ auto ws = CTX_OUT_MEM(uint8_t *, MKLDNN_ARG_WORKSPACE);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+ const memory_desc_wrapper scaleshift_d(pd()->weights_md());
+
+ const dim_t N = pd()->MB();
+ const dim_t C = pd()->C();
+ dim_t H = 1, W = 1, D = 1;
+ const bool has_spatial = utils::one_of(data_d.ndims(), 4, 5);
+ if (has_spatial) {
+ D = pd()->D();
+ H = pd()->H();
+ W = pd()->W();
+ }
+
+ const float eps = pd()->desc()->batch_norm_epsilon;
+ const bool use_scaleshift = pd()->use_scaleshift();;
+ const bool save_stats = pd()->is_training();
+ const bool is_training = pd()->is_training();
+ const bool fuse_bn_relu = pd()->fuse_bn_relu();
+ const bool calculate_stats = !pd()->stats_is_src();
+
+ const bool with_relu = pd()->with_relu_post_op();
+ auto maybe_post_op = [&](float res) {
+ return (with_relu && res < 0.0f) ? 0.0f : res;
+ };
+ const bool is_3d = data_d.ndims() == 5;
+
+ auto data_offset = [&](const memory_desc_wrapper &data_d, dim_t n, dim_t c,
+ dim_t d, dim_t h, dim_t w) {
+ if (has_spatial) {
+ if (is_3d)
+ return data_d.off(n, c, d, h, w);
+ else
+ return data_d.off(n, c, h, w);
+ } else
+ return data_d.off(n, c);
+ };
+
+ parallel_nd(C, [&](dim_t c) {
+ float v_mean = calculate_stats ? 0 : mean[c];
+ float v_variance = calculate_stats ? 0 : variance[c];
+
+ if (calculate_stats) {
+ for (dim_t n = 0; n < N; ++n)
+ for (dim_t d = 0; d < D; ++d)
+ for (dim_t h = 0; h < H; ++h)
+ for (dim_t w = 0; w < W; ++w)
+ v_mean += src[data_offset(data_d, n, c, d, h, w)];
+ v_mean /= W*N*H*D;
+
+ for (dim_t n = 0; n < N; ++n)
+ for (dim_t d = 0; d < D; ++d)
+ for (dim_t h = 0; h < H; ++h)
+ for (dim_t w = 0; w < W; ++w) {
+ float m = src[data_offset(data_d, n, c, d, h, w)] - v_mean;
+ v_variance += m*m;
+ }
+ v_variance /= W*H*N*D;
+ }
+
+ float sqrt_variance = sqrtf(v_variance + eps);
+ float sm = (use_scaleshift
+ ? scaleshift[scaleshift_d.off(0, c)]
+ : 1.0f) / sqrt_variance;
+ float sv = use_scaleshift ? scaleshift[scaleshift_d.off(1, c)] : 0;
+
+ for (dim_t n = 0; n < N; ++n)
+ for (dim_t d = 0; d < D; ++d)
+ for (dim_t h = 0; h < H; ++h)
+ for (dim_t w = 0; w < W; ++w) {
+ auto d_off = data_offset(data_d,n,c,d,h,w);
+ float bn_res = sm * ((float)src[d_off] - v_mean) + sv;
+ if (fuse_bn_relu) {
+ if (bn_res <= 0) {
+ bn_res = 0;
+ if (is_training)
+ ws[d_off] = 0;
+ } else {
+ if (is_training)
+ ws[d_off] = 1;
+ }
+ }
+ if (data_type == data_type::s8) {
+ dst[d_off] = qz_a1b0<float, data_t>()(maybe_post_op(bn_res));
+ } else {
+ dst[d_off] = static_cast<data_t>(maybe_post_op(bn_res));
+ }
+ }
+
+ if (calculate_stats) {
+ if (save_stats) {
+ mean[c] = v_mean;
+ variance[c] = v_variance;
+ }
+ }
+ });
+}
+
+template struct ref_batch_normalization_fwd_t<data_type::f32>;
+template struct ref_batch_normalization_fwd_t<data_type::s8>;
+
+template <impl::data_type_t data_type>
+void ref_batch_normalization_bwd_t<data_type>::execute_backward(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto mean = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MEAN);
+ auto variance = CTX_IN_MEM(const data_t *, MKLDNN_ARG_VARIANCE);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto scaleshift = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SCALE_SHIFT);
+ auto ws = CTX_IN_MEM(const uint8_t *, MKLDNN_ARG_WORKSPACE);
+
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+ auto diff_scaleshift = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SCALE_SHIFT);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+ const memory_desc_wrapper diff_data_d(pd()->diff_src_md());
+ const memory_desc_wrapper scaleshift_d(pd()->weights_md());
+ const memory_desc_wrapper diff_scaleshift_d(pd()->diff_weights_md());
+
+ const dim_t C = pd()->C();
+
+ /* fast return */
+ if (this->pd()->has_zero_dim_memory()) {
+ if (diff_scaleshift) {
+ for (dim_t c = 0; c < C; ++c) {
+ diff_scaleshift[diff_scaleshift_d.off(0, c)] = 0;
+ diff_scaleshift[diff_scaleshift_d.off(1, c)] = 0;
+ }
+ }
+ return;
+ }
+
+ const dim_t N = pd()->MB();
+ dim_t H = 1, W = 1, D = 1;
+ const bool has_spatial = utils::one_of(data_d.ndims(), 4, 5);
+ if (has_spatial) {
+ D = pd()->D();
+ H = pd()->H();
+ W = pd()->W();
+ }
+
+ const float eps = pd()->desc()->batch_norm_epsilon;
+ const bool use_scaleshift = pd()->use_scaleshift();
+ const bool calculate_diff_stats = !pd()->use_global_stats();
+ const bool fuse_bn_relu = pd()->fuse_bn_relu();
+
+ const bool is_3d = data_d.ndims() == 5;
+
+ auto data_offset = [&](const memory_desc_wrapper &data_d, dim_t n, dim_t c,
+ dim_t d, dim_t h, dim_t w) {
+ if (has_spatial) {
+ if (is_3d)
+ return data_d.off(n, c, d, h, w);
+ else
+ return data_d.off(n, c, h, w);
+ } else
+ return data_d.off(n, c);
+ };
+
+ parallel_nd(C, [&](dim_t c) {
+ data_t v_mean = mean[c];
+ data_t v_variance = variance[c];
+ data_t sqrt_variance = static_cast<data_t>(1.0f / sqrtf(v_variance + eps));
+ data_t gamma = use_scaleshift ? scaleshift[scaleshift_d.off(0, c)] : 1;
+ data_t diff_gamma = data_t(0);
+ data_t diff_beta = data_t(0);
+ diff_gamma = 0.0;
+ diff_beta = 0.0;
+
+ for (dim_t n = 0; n < N; ++n)
+ for (dim_t d = 0; d < D; ++d)
+ for (dim_t h = 0; h < H; ++h)
+ for (dim_t w = 0; w < W; ++w) {
+ const size_t s_off = data_offset(data_d, n, c, d, h, w);
+ data_t dd = diff_dst[data_offset(diff_data_d, n, c, d, h, w)];
+ if (fuse_bn_relu && !ws[s_off])
+ dd = 0;
+
+ diff_gamma += (src[s_off] - v_mean) * dd;
+ diff_beta += dd;
+ }
+ diff_gamma *= sqrt_variance;
+
+ if (diff_scaleshift) {
+ diff_scaleshift[diff_scaleshift_d.off(0, c)] = diff_gamma;
+ diff_scaleshift[diff_scaleshift_d.off(1, c)] = diff_beta;
+ }
+
+ for (dim_t n = 0; n < N; ++n)
+ for (dim_t d = 0; d < D; ++d)
+ for (dim_t h = 0; h < H; ++h)
+ for (dim_t w = 0; w < W; ++w) {
+ const size_t s_off = data_offset(data_d, n, c, d, h, w);
+ const size_t dd_off = data_offset(diff_data_d, n, c, d, h, w);
+ data_t dd = diff_dst[dd_off];
+ if (fuse_bn_relu && !ws[s_off])
+ dd = 0;
+
+ data_t v_diff_src = dd;
+ if (calculate_diff_stats) {
+ v_diff_src -= diff_beta/(D*W*H*N) +
+ (src[s_off] - v_mean) *
+ diff_gamma*sqrt_variance/(D*W*H*N);
+ }
+ v_diff_src *= gamma*sqrt_variance;
+ diff_src[dd_off] = v_diff_src;
+ }
+ });
+}
+
+template struct ref_batch_normalization_bwd_t<data_type::f32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.hpp
new file mode 100644
index 0000000000..aa9f74125a
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_batch_normalization.hpp
@@ -0,0 +1,127 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REF_BATCH_NORMALIZATION_HPP
+#define CPU_REF_BATCH_NORMALIZATION_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_batch_normalization_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t data_type>
+struct ref_batch_normalization_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_batch_normalization_fwd_pd_t {
+ pd_t(engine_t *engine, const batch_normalization_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const batch_normalization_fwd_pd_t *hint_fwd_pd)
+ : cpu_batch_normalization_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ DECLARE_COMMON_PD_T("ref:any", ref_batch_normalization_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && src_md()->data_type == data_type
+ && IMPLICATION(use_scaleshift(),
+ weights_md()->data_type == data_type::f32)
+ && (attr()->has_default_values() || with_relu_post_op());
+ if (!ok) return status::unimplemented;
+
+ if (src_md()->data_type == data_type::s8 && !stats_is_src())
+ return status::unimplemented;
+
+ if (is_training() && fuse_bn_relu()) init_default_ws(8);
+
+ return status::success;
+ }
+ };
+
+ ref_batch_normalization_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t data_type>
+struct ref_batch_normalization_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_batch_normalization_bwd_pd_t {
+ pd_t(engine_t *engine, const batch_normalization_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const batch_normalization_fwd_pd_t *hint_fwd_pd)
+ : cpu_batch_normalization_bwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ {}
+
+ DECLARE_COMMON_PD_T("ref:any", ref_batch_normalization_bwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_bwd()
+ && utils::everyone_is(data_type, src_md()->data_type,
+ diff_src_md()->data_type)
+ && IMPLICATION(use_scaleshift(), utils::everyone_is(data_type,
+ weights_md()->data_type,
+ diff_weights_md()->data_type))
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ if (fuse_bn_relu()) {
+ init_default_ws(8);
+ if (!compare_ws(hint_fwd_pd_))
+ return status::unimplemented;
+ }
+
+ return status::success;
+ }
+ };
+
+ ref_batch_normalization_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_concat.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_concat.hpp
new file mode 100644
index 0000000000..4c534b5508
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_concat.hpp
@@ -0,0 +1,97 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef REF_CONCAT_HPP
+#define REF_CONCAT_HPP
+
+#include "reorder_pd.hpp"
+
+#include "cpu_concat_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct ref_concat_t: public cpu_primitive_t {
+ struct pd_t: public cpu_concat_pd_t {
+ using cpu_concat_pd_t::cpu_concat_pd_t;
+
+ pd_t(const pd_t &rhs): cpu_concat_pd_t(rhs) {
+ for (size_t i = 0; i < rhs.reorder_pds_.size(); ++i)
+ reorder_pds_.push_back(
+ (const reorder_pd_t *)rhs.reorder_pds_[i]->clone());
+ }
+ ~pd_t() { for (auto &rpd: reorder_pds_) delete rpd; }
+
+ DECLARE_CONCAT_PD_T("ref:any", ref_concat_t);
+
+ status_t init() {
+ bool ok = cpu_concat_pd_t::init() == status::success;
+ if (!ok) return status::unimplemented;
+
+ for (int i = 0; i < n_; ++i) {
+ auto r_impls = engine_->get_reorder_implementation_list();
+ for (auto r = r_impls; *r; ++r) {
+ const primitive_attr_t attr; /* alpha == 1. */
+ reorder_pd_t *r_pd = nullptr;
+ if ((*r)(&r_pd, engine_, &attr, engine_, src_md(i),
+ engine_, src_image_md(i)) == status::success) {
+ r_pd->init_info();
+ reorder_pds_.push_back(r_pd);
+ break;
+ }
+ }
+ }
+
+ ok = reorder_pds_.size() == (size_t)n_;
+ return ok ? status::success : status::unimplemented;
+ }
+
+ nstl::vector<const reorder_pd_t *> reorder_pds_;
+ };
+
+ ref_concat_t(const pd_t *apd): cpu_primitive_t(apd) {
+ const int n = pd()->n_inputs();
+ reorders_.resize(n);
+ for (int i = 0; i < n; ++i)
+ pd()->reorder_pds_[i]->create_primitive(&reorders_[i]);
+ }
+
+ ~ref_concat_t() { for (auto &r: reorders_) delete r; }
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ const auto n = pd()->n_inputs();
+ for (int i = 0; i < n; ++i) {
+ exec_args_t r_args;
+ r_args[MKLDNN_ARG_SRC] = ctx.args().at(MKLDNN_ARG_MULTIPLE_SRC + i);
+ r_args[MKLDNN_ARG_DST] = ctx.args().at(MKLDNN_ARG_DST);
+ exec_ctx_t r_ctx(ctx.stream(), std::move(r_args));
+ reorders_[i]->execute(r_ctx);
+ }
+ return status::success;
+ }
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ nstl::vector<primitive_t *> reorders_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.cpp
new file mode 100644
index 0000000000..c0a979c4cf
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.cpp
@@ -0,0 +1,395 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+#include "mkldnn_traits.hpp"
+#include "type_helpers.hpp"
+
+#include "ref_convolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using math::saturate;
+using math::get_bias;
+
+template <data_type_t src_type, data_type_t wei_type,
+ data_type_t dst_type, data_type_t acc_type>
+void ref_convolution_fwd_t<src_type, wei_type, dst_type, acc_type>::
+execute_forward(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ const bool with_groups = pd()->with_groups();
+
+ const int G = pd()->G();
+ const int MB = pd()->MB();
+ const int OD = pd()->OD();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+ const int ID = pd()->ID();
+ const int IH = pd()->IH();
+ const int IW = pd()->IW();
+
+ const int OC = pd()->OC() / G;
+ const int IC = pd()->IC() / G;
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+
+ const int KSD = pd()->KSD();
+ const int KSH = pd()->KSH();
+ const int KSW = pd()->KSW();
+
+ const int KDD = pd()->KDD();
+ const int KDH = pd()->KDH();
+ const int KDW = pd()->KDW();
+
+ const int padFront = pd()->padFront();
+ const int padT = pd()->padT();
+ const int padL = pd()->padL();
+
+ const bool with_relu = 0; // TODO: change if support post_ops
+ const float nslope = 0.f;
+
+ const int ndims = pd()->desc()->src_desc.ndims;
+
+ auto ker = [=](int g, int mb, int oc, int od, int oh,
+ int ow) {
+ acc_data_t d = 0;
+ for (int ic = 0; ic < IC; ++ic)
+ for (int kd = 0; kd < KD; ++kd)
+ for (int kh = 0; kh < KH; ++kh)
+ for (int kw = 0; kw < KW; ++kw) {
+ const int id = od * KSD - padFront + kd * (1 + KDD);
+ const int ih = oh * KSH - padT + kh * (1 + KDH);
+ const int iw = ow * KSW - padL + kw * (1 + KDW);
+
+ if (id < 0 || id >= ID) continue;
+ if (ih < 0 || ih >= IH) continue;
+ if (iw < 0 || iw >= IW) continue;
+
+ if (ndims == 5)
+ d += (acc_data_t)src[src_d.off(mb, g*IC + ic, id, ih, iw)]
+ * (with_groups
+ ? weights[weights_d.off(g, oc, ic, kd, kh, kw)]
+ : weights[weights_d.off(oc, ic, kd, kh, kw)]);
+ else if (ndims == 4)
+ d += (acc_data_t)src[src_d.off(mb, g*IC + ic, ih, iw)]
+ * (with_groups
+ ? weights[weights_d.off(g, oc, ic, kh, kw)]
+ : weights[weights_d.off(oc, ic, kh, kw)]);
+ else if (ndims == 3)
+ d += (acc_data_t)src[src_d.off(mb, g*IC + ic, iw)]
+ * (with_groups
+ ? weights[weights_d.off(g, oc, ic, kw)]
+ : weights[weights_d.off(oc, ic, kw)]);
+ else
+ assert(false);
+
+ }
+ return d;
+ };
+
+ parallel_nd(G, MB, OC, OD, OH, OW,
+ [&](int g, int mb, int oc, int od, int oh, int ow) {
+ float a = bias
+ ? get_bias(bias, bias_d.off(g * OC + oc),
+ pd()->desc()->bias_desc.data_type)
+ : 0;
+ a += ker(g, mb, oc, od, oh, ow);
+ if (with_relu && a < 0)
+ a = a * nslope;
+ if (ndims == 5)
+ dst[dst_d.off(mb, g*OC + oc, od, oh, ow)] = saturate<dst_data_t>(a);
+ else if (ndims == 4)
+ dst[dst_d.off(mb, g*OC + oc, oh, ow)] = saturate<dst_data_t>(a);
+ else if (ndims == 3)
+ dst[dst_d.off(mb, g*OC + oc, ow)] = saturate<dst_data_t>(a);
+ else
+ assert(false);
+ });
+}
+
+template <data_type_t diff_src_type, data_type_t wei_type,
+ data_type_t diff_dst_type, data_type_t acc_type>
+void ref_convolution_bwd_data_t<diff_src_type, wei_type, diff_dst_type,
+ acc_type>::execute_backward_data(const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ const bool with_groups = pd()->with_groups();
+
+ const int G = pd()->G();
+ const int MB = pd()->MB();
+ const int OD = pd()->OD();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+ const int ID = pd()->ID();
+ const int IH = pd()->IH();
+ const int IW = pd()->IW();
+
+ const int OC = pd()->OC() / G;
+ const int IC = pd()->IC() / G;
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+
+ const int KSD = pd()->KSD();
+ const int KSH = pd()->KSH();
+ const int KSW = pd()->KSW();
+
+ const int KDD = pd()->KDD();
+ const int KDH = pd()->KDH();
+ const int KDW = pd()->KDW();
+
+ const int padFront = pd()->padFront();
+ const int padT = pd()->padT();
+ const int padL = pd()->padL();
+
+ const int ndims = pd()->desc()->diff_src_desc.ndims;
+
+ auto ker = [=](int g, int mb, int ic, int id, int ih,
+ int iw) {
+ acc_data_t d = 0;
+ for (int oc = 0; oc < OC; ++oc)
+ for (int kd = 0; kd < KD; ++kd)
+ for (int kh = 0; kh < KH; ++kh)
+ for (int kw = 0; kw < KW; ++kw) {
+ if (iw + padL < kw * (1 + KDW)
+ || ih + padT < kh * (1 + KDH)
+ || id + padFront < kd * (1 + KDD))
+ continue;
+ int ow = iw - kw * (1 + KDW) + padL;
+ int oh = ih - kh * (1 + KDH) + padT;
+ int od = id - kd * (1 + KDD) + padFront;
+ if (ow % KSW != 0 || oh % KSH != 0 || od % KSD != 0)
+ continue;
+
+ ow /= KSW;
+ oh /= KSH;
+ od /= KSD;
+
+ if (od < OD && oh < OH && ow < OW) {
+ if (ndims == 5)
+ d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC
+ + oc, od, oh, ow)] * (with_groups
+ ? weights[weights_d.off(g, oc, ic, kd, kh, kw)]
+ : weights[weights_d.off(oc, ic, kd, kh, kw)]);
+ else if (ndims == 4)
+ d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC
+ + oc, oh, ow)] * (with_groups
+ ? weights[weights_d.off(g, oc, ic, kh, kw)]
+ : weights[weights_d.off(oc, ic, kh, kw)]);
+ else if (ndims == 3)
+ d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC
+ + oc, ow)] * (with_groups
+ ? weights[weights_d.off(g, oc, ic, kw)]
+ : weights[weights_d.off(oc, ic, kw)]);
+ else
+ assert(false);
+ }
+ }
+ return d;
+ };
+
+ parallel_nd(G, MB, IC, ID, IH, IW,
+ [&](int g, int mb, int ic, int id, int ih, int iw) {
+ auto ds_idx = (ndims == 5)
+ ? diff_src_d.off(mb, g*IC + ic, id, ih, iw)
+ : (ndims == 4)
+ ? diff_src_d.off(mb, g*IC + ic, ih, iw)
+ : diff_src_d.off(mb, g*IC + ic, iw);
+ float a = bias
+ ? get_bias(bias, bias_d.off(g * IC + ic),
+ pd()->desc()->bias_desc.data_type)
+ : 0;
+ a += ker(g, mb, ic, id, ih, iw);
+ diff_src[ds_idx] = saturate<diff_src_data_t>(a);
+ });
+}
+
+template <data_type_t src_type, data_type_t diff_wei_type,
+ data_type_t diff_dst_type, data_type_t acc_type>
+void ref_convolution_bwd_weights_t<src_type, diff_wei_type, diff_dst_type,
+ acc_type>::execute_backward_weights(const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST);
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto diff_weights = CTX_OUT_MEM(diff_wei_data_t *, MKLDNN_ARG_DIFF_WEIGHTS);
+ auto diff_bias = CTX_OUT_MEM(diff_wei_data_t *, MKLDNN_ARG_DIFF_BIAS);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0));
+ const memory_desc_wrapper diff_bias_d(pd()->diff_weights_md(1));
+
+ const bool with_groups = pd()->with_groups();
+
+ const int G = pd()->G();
+ const int MB = pd()->MB();
+ const int OD = pd()->OD();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+ const int ID = pd()->ID();
+ const int IH = pd()->IH();
+ const int IW = pd()->IW();
+
+ const int OC = pd()->OC() / G;
+ const int IC = pd()->IC() / G;
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+
+ const int KSD = pd()->KSD();
+ const int KSH = pd()->KSH();
+ const int KSW = pd()->KSW();
+
+ const int KDD = pd()->KDD();
+ const int KDH = pd()->KDH();
+ const int KDW = pd()->KDW();
+
+ const int padFront = pd()->padFront();
+ const int padT = pd()->padT();
+ const int padL = pd()->padL();
+
+ const int ndims = pd()->desc()->src_desc.ndims;
+
+auto ker = [=](acc_data_t &d, int g, int oc, int ic, int kd, int kh, int kw) {
+ for (int mb = 0; mb < MB; ++mb)
+ for (int od = 0; od < OD; ++od)
+ for (int oh = 0; oh < OH; ++oh)
+ for (int ow = 0; ow < OW; ++ow) {
+ if (ow*KSW + kw * (1 + KDW) < padL
+ || oh*KSH + kh * (1 + KDH) < padT
+ || od*KSD + kd * (1 + KDD) < padFront
+ || ow*KSW + kw * (1 + KDW) >= IW + padL
+ || oh*KSH + kh * (1 + KDH) >= IH + padT
+ || od*KSD + kd * (1 + KDD) >= ID + padFront)
+ continue;
+
+ int id = od*KSD - padFront + kd * (1 + KDD);
+ int ih = oh*KSH - padT + kh * (1 + KDH);
+ int iw = ow*KSW - padL + kw * (1 + KDW);
+ if (ndims == 5)
+ d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, od,
+ oh, ow)] * src[src_d.off(mb, g*IC + ic, id, ih, iw)];
+ else if (ndims == 4)
+ d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, oh, ow)]
+ * src[src_d.off(mb, g*IC + ic, ih, iw)];
+ else if (ndims == 3)
+ d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, ow)]
+ * src[src_d.off(mb, g*IC + ic, iw)];
+ else
+ assert(false);
+ }
+ };
+
+ auto ker_bias = [=](acc_data_t &d, int g, int oc) {
+ for (int mb = 0; mb < MB; ++mb)
+ for (int od = 0; od < OD; ++od)
+ for (int oh = 0; oh < OH; ++oh)
+ for (int ow = 0; ow < OW; ++ow) {
+ if (ndims == 5)
+ d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, od, oh,
+ ow)];
+ else if (ndims == 4)
+ d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, oh,
+ ow)];
+ else if (ndims == 3)
+ d += (acc_data_t)diff_dst[diff_dst_d.off(mb, g*OC + oc, ow)];
+ else
+ assert(false);
+ }
+ };
+
+ parallel_nd(G, OC, [&](int g, int oc) {
+ if (diff_bias) {
+ // XXX: loss of precision when bias is a float...
+ acc_data_t db = 0;
+ ker_bias(db, g, oc);
+ diff_bias[diff_bias_d.off(g*OC+oc)]
+ = saturate<diff_wei_data_t>(db);
+ }
+
+ for (int ic = 0; ic < IC; ++ic)
+ for (int kd = 0; kd < KD; ++kd)
+ for (int kh = 0; kh < KH; ++kh)
+ for (int kw = 0; kw < KW; ++kw) {
+ acc_data_t dw = 0;
+ ker(dw, g, oc, ic, kd, kh, kw);
+
+ if (ndims == 5) {
+ auto idx = with_groups
+ ? diff_weights_d.off(g, oc, ic, kd, kh, kw)
+ : diff_weights_d.off(oc, ic, kd, kh, kw);
+ diff_weights[idx] = saturate<diff_wei_data_t>(dw);
+ } else if (ndims == 4) {
+ auto idx = with_groups
+ ? diff_weights_d.off(g, oc, ic, kh, kw)
+ : diff_weights_d.off(oc, ic, kh, kw);
+ diff_weights[idx] = saturate<diff_wei_data_t>(dw);
+ } else if (ndims == 3) {
+ auto idx = with_groups
+ ? diff_weights_d.off(g, oc, ic, kw)
+ : diff_weights_d.off(oc, ic, kw);
+ diff_weights[idx] = saturate<diff_wei_data_t>(dw);
+ } else {
+ assert(false);
+ }
+ }
+ });
+}
+
+using namespace data_type;
+
+template struct ref_convolution_fwd_t<f32>;
+
+template struct ref_convolution_fwd_t<u8, s8, f32, s32>;
+template struct ref_convolution_fwd_t<u8, s8, s32, s32>;
+template struct ref_convolution_fwd_t<u8, s8, s8, s32>;
+template struct ref_convolution_fwd_t<u8, s8, u8, s32>;
+
+template struct ref_convolution_bwd_data_t<f32, f32, f32, f32>;
+
+template struct ref_convolution_bwd_data_t<f32, s8, u8, s32>;
+template struct ref_convolution_bwd_data_t<s32, s8, u8, s32>;
+template struct ref_convolution_bwd_data_t<s8, s8, u8, s32>;
+template struct ref_convolution_bwd_data_t<u8, s8, u8, s32>;
+
+template struct ref_convolution_bwd_weights_t<f32, f32, f32, f32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.hpp
new file mode 100644
index 0000000000..7c83d0c6d4
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_convolution.hpp
@@ -0,0 +1,194 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REF_CONVOLUTION_HPP
+#define CPU_REF_CONVOLUTION_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t src_type,
+ impl::data_type_t wei_type = src_type,
+ impl::data_type_t dst_type = src_type,
+ impl::data_type_t acc_type = dst_type>
+struct ref_convolution_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_fwd_pd_t {
+ using cpu_convolution_fwd_pd_t::cpu_convolution_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_convolution_fwd_t);
+
+ status_t init() {
+ using namespace data_type;
+
+ bool ok = true
+ && is_fwd()
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(src_type, wei_type, data_type::undef,
+ dst_type, acc_type)
+ && IMPLICATION(with_bias(), true
+ && IMPLICATION(src_type == u8,
+ utils::one_of(bias_md_.data_type, f32, s32, s8, u8))
+ && IMPLICATION(src_type == f32,
+ bias_md_.data_type == f32))
+ && set_default_formats()
+ && attr()->has_default_values();
+ return ok ? status::success : status::unimplemented;
+ }
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+ auto dat_tag = utils::pick(ndims() - 3, ncw, nchw, ncdhw);
+ auto wei_tag = with_groups()
+ ? utils::pick(ndims() - 3, goiw, goihw, goidhw)
+ : utils::pick(ndims() - 3, oiw, oihw, oidhw);
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ ref_convolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<wei_type>::type wei_data_t;
+ typedef typename prec_traits<dst_type>::type dst_data_t;
+ typedef typename prec_traits<acc_type>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t diff_src_type, impl::data_type_t wei_type,
+ impl::data_type_t diff_dst_type,
+ impl::data_type_t acc_type = diff_src_type>
+struct ref_convolution_bwd_data_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_data_pd_t {
+ using cpu_convolution_bwd_data_pd_t::cpu_convolution_bwd_data_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_convolution_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_data
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(diff_src_type, wei_type, data_type::undef,
+ diff_dst_type, acc_type)
+ && set_default_formats()
+ && attr()->has_default_values();
+
+ return ok ? status::success : status::unimplemented;
+ }
+
+ virtual bool support_bias() const override { return true; }
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+ auto dat_tag = utils::pick(ndims() - 3, ncw, nchw, ncdhw);
+ auto wei_tag = with_groups()
+ ? utils::pick(ndims() - 3, goiw, goihw, goidhw)
+ : utils::pick(ndims() - 3, oiw, oihw, oidhw);
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ ref_convolution_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ typedef typename prec_traits<diff_src_type>::type diff_src_data_t;
+ typedef typename prec_traits<wei_type>::type wei_data_t;
+ typedef typename prec_traits<diff_dst_type>::type diff_dst_data_t;
+ typedef typename prec_traits<acc_type>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_data(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_data(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t src_type, impl::data_type_t diff_wei_type,
+ impl::data_type_t diff_dst_type,
+ impl::data_type_t acc_type = diff_wei_type>
+struct ref_convolution_bwd_weights_t: public cpu_primitive_t {
+ struct pd_t: public cpu_convolution_bwd_weights_pd_t {
+ using cpu_convolution_bwd_weights_pd_t::cpu_convolution_bwd_weights_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_convolution_bwd_weights_t);
+
+ status_t init() {
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_weights
+ && set_default_alg_kind(alg_kind::convolution_direct)
+ && expect_data_types(src_type, diff_wei_type, diff_wei_type,
+ diff_dst_type, acc_type)
+ && set_default_formats()
+ && attr()->has_default_values();
+ return ok ? status::success : status::unimplemented;
+ }
+
+ protected:
+ bool set_default_formats() {
+ using namespace format_tag;
+ auto dat_tag = utils::pick(ndims() - 3, ncw, nchw, ncdhw);
+ auto wei_tag = with_groups()
+ ? utils::pick(ndims() - 3, goiw, goihw, goidhw)
+ : utils::pick(ndims() - 3, oiw, oihw, oidhw);
+ return set_default_formats_common(dat_tag, wei_tag, dat_tag);
+ }
+ };
+
+ ref_convolution_bwd_weights_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<diff_wei_type>::type diff_wei_data_t;
+ typedef typename prec_traits<diff_dst_type>::type diff_dst_data_t;
+ typedef typename prec_traits<acc_type>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_weights(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_weights(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.cpp
new file mode 100644
index 0000000000..541a303aab
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.cpp
@@ -0,0 +1,199 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "mkldnn_thread.hpp"
+#include "mkldnn_traits.hpp"
+#include "math_utils.hpp"
+
+#include "ref_deconvolution.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+void ref_deconvolution_fwd_t::compute_fwd_bias(const data_t *bias,
+ data_t *dst) const {
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+
+ const int G = pd()->G();
+ const int MB = pd()->MB();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+ const int OD = pd()->OD();
+ const int OC = pd()->OC() / G;
+ const int ndims = pd()->desc()->src_desc.ndims;
+
+ parallel_nd(MB, G, OC, OD, OH, OW,
+ [&](int mb, int g, int oc, int od, int oh, int ow) {
+ auto b = bias[g * OC + oc];
+ switch (ndims) {
+ case 5: dst[dst_d.off(mb, g * OC + oc, od, oh, ow)] += b; break;
+ case 4: dst[dst_d.off(mb, g * OC + oc, oh, ow)] += b; break;
+ case 3: dst[dst_d.off(mb, g * OC + oc, ow)] += b; break;
+ default: assert(!"invalid dimension size");
+ }
+ });
+}
+
+void ref_deconvolution_fwd_t::compute_fwd_bias_ncdhw(const data_t *bias,
+ data_t *dst) const {
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+
+ const int MB = pd()->MB();
+ const int OC = pd()->OC();
+ const int SP = pd()->OW()*pd()->OH()*pd()->OD();
+
+ parallel_nd(MB, OC, [&](int mb, int oc) {
+ PRAGMA_OMP_SIMD()
+ for (int sp = 0; sp < SP; ++sp) {
+ auto offset = (size_t)(mb * OC + oc) * SP + sp;
+ dst[offset] += bias[oc];
+ }
+ });
+}
+
+template <int blksize>
+void ref_deconvolution_fwd_t::compute_fwd_bias_nCdhwXc(const data_t *bias,
+ data_t *dst) const {
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+
+ const int MB = pd()->MB();
+ const int OC = pd()->OC();
+ const int SP = pd()->OW() * pd()->OH() * pd()->OD();
+
+ const ptrdiff_t stride_mb = dst_d.blocking_desc().strides[0];
+
+ parallel_nd(MB, utils::div_up(OC, blksize), SP,
+ [&](int mb, int oc_blk, int sp) {
+ int oc = oc_blk * blksize;
+ auto offset = mb * stride_mb + oc * SP + sp * blksize;
+ const int blk = nstl::min(blksize, OC - oc);
+
+ PRAGMA_OMP_SIMD()
+ for (int i = 0; i < blk; ++i)
+ dst[offset + i] += bias[oc + i];
+ });
+}
+
+void ref_deconvolution_bwd_weights_t::compute_bwd_bias(const data_t *diff_dst,
+ data_t *diff_bias) const {
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+
+ const int G = pd()->G();
+ const int MB = pd()->MB();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+ const int OC = pd()->OC() / G;
+ const int OD = pd()->OD();
+ const int ndims = pd()->desc()->src_desc.ndims;
+
+ parallel_nd(G, OC, [&](int g, int oc) {
+ data_t db = 0;
+ for (int mb = 0; mb < MB; ++mb) {
+ for (int od = 0; od < OD; ++od) {
+ for (int oh = 0; oh < OH; ++oh) {
+ for (int ow = 0; ow < OW; ++ow) {
+ switch (ndims) {
+ case 5:
+ db += diff_dst[diff_dst_d.off(
+ mb, g * OC + oc, od, oh, ow)];
+ break;
+ case 4:
+ db += diff_dst[diff_dst_d.off(
+ mb, g * OC + oc, oh, ow)];
+ break;
+ case 3:
+ db += diff_dst[diff_dst_d.off(mb, g * OC + oc, ow)];
+ break;
+ default: assert(!"invalid dimension size");
+ }
+ }
+ }
+ }
+ }
+ diff_bias[g * OC + oc] = db;
+ });
+}
+
+void ref_deconvolution_bwd_weights_t::compute_bwd_bias_ncdhw(
+ const data_t *diff_dst, data_t *diff_bias) const {
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+
+ const int OC = pd()->OC();
+ const int MB = pd()->MB();
+ const int SP = pd()->OH()*pd()->OW()*pd()->OD();
+
+ parallel_nd(OC, [&](int oc) {
+ data_t db = 0;
+ for (int mb = 0; mb < MB; ++mb) {
+ PRAGMA_OMP_SIMD()
+ for (int sp = 0; sp < SP; ++sp) {
+ auto offset = (size_t)(mb * OC + oc) * SP + sp;
+ db += diff_dst[offset];
+ }
+ }
+ diff_bias[oc] = db;
+ });
+}
+
+template <int blksize>
+void ref_deconvolution_bwd_weights_t::compute_bwd_bias_nCdhwXc(
+ const data_t *diff_dst, data_t *diff_bias) const {
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+
+ const int OC = pd()->OC();
+ const int MB = pd()->MB();
+ const int SP = pd()->OH() * pd()->OW() * pd()->OD();
+
+ const ptrdiff_t stride_mb = diff_dst_d.blocking_desc().strides[0];
+
+ parallel_nd(utils::div_up(OC, blksize), [&](int ocb) {
+ data_t db[blksize] = {0};
+
+ for (int mb = 0; mb < MB; ++mb) {
+ for (int sp = 0; sp < SP; ++sp) {
+ auto offset = mb * stride_mb + (ocb * SP + sp) * blksize;
+
+ PRAGMA_OMP_SIMD()
+ for (int i = 0; i < blksize; ++i)
+ db[i] += diff_dst[offset+i];
+ }
+ }
+
+ const int blk = nstl::min(blksize, OC - ocb * blksize);
+
+ PRAGMA_OMP_SIMD()
+ for (int i = 0; i < blk; ++i)
+ diff_bias[ocb * blksize + i] = db[i];
+ });
+}
+
+template void ref_deconvolution_fwd_t::compute_fwd_bias_nCdhwXc<8>(
+ const data_t *diff_dst, data_t *diff_bias) const;
+template void ref_deconvolution_fwd_t::compute_fwd_bias_nCdhwXc<16>(
+ const data_t *diff_dst, data_t *diff_bias) const;
+template void ref_deconvolution_bwd_weights_t::compute_bwd_bias_nCdhwXc<8>(
+ const data_t *diff_dst, data_t *diff_bias) const;
+template void ref_deconvolution_bwd_weights_t::compute_bwd_bias_nCdhwXc<16>(
+ const data_t *diff_dst, data_t *diff_bias) const;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.hpp
new file mode 100644
index 0000000000..d61903c32d
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_deconvolution.hpp
@@ -0,0 +1,502 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REF_DECONVOLUTION_HPP
+#define CPU_REF_DECONVOLUTION_HPP
+
+#include <assert.h>
+#include <string.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+#include "primitive_iterator.hpp"
+
+#include "cpu_convolution_pd.hpp"
+#include "cpu_deconvolution_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+static status_t compute_blocked_format(bool with_groups,
+ const memory_desc_t *oi_md, memory_desc_t *io_md)
+{
+ /* Computes blocking for *i*o* format from *o*i* format */
+
+ bool sanity_check_ok = true
+ && oi_md->ndims == io_md->ndims
+ && oi_md->format_kind == format_kind::blocked;
+ if (!sanity_check_ok) return status::invalid_arguments;
+
+ const blocking_desc_t &oi_blk = oi_md->format_desc.blocking;
+ blocking_desc_t io_blk = io_md->format_desc.blocking;
+
+ io_md->format_kind = format_kind::blocked;
+ io_blk = oi_blk;
+
+ const int ID_OC = 0 + with_groups;
+ const int ID_IC = 1 + with_groups;
+
+ nstl::swap(io_blk.strides[ID_OC], io_blk.strides[ID_IC]);
+ for (int i_blk = 0; i_blk < io_blk.inner_nblks; ++i_blk) {
+ if (utils::one_of(io_blk.inner_idxs[i_blk], ID_OC, ID_IC)) {
+ io_blk.inner_idxs[i_blk] =
+ (io_blk.inner_idxs[i_blk] == ID_OC ? ID_IC : ID_OC);
+ }
+ }
+
+ return memory_desc_init_by_blocking_desc(*io_md, io_blk);
+}
+
+static status_t conv_descr_create(const deconvolution_desc_t *dd,
+ convolution_desc_t *cd)
+{
+ using namespace prop_kind;
+ alg_kind_t alg_kind = dd->alg_kind == alg_kind::deconvolution_direct
+ ? alg_kind::convolution_direct : alg_kind::convolution_winograd;
+
+ const memory_desc_t *src_md, *dst_md, *d_weights_d;
+ prop_kind_t prop_kind;
+ memory_desc_t c_weights_d;
+ if (utils::one_of(dd->prop_kind, forward_training, forward_inference)) {
+ prop_kind = backward_data;
+ src_md = &dd->dst_desc;
+ dst_md = &dd->src_desc;
+ d_weights_d = &dd->weights_desc;
+ } else if (dd->prop_kind == backward_data) {
+ prop_kind = forward_training;
+ src_md = &dd->diff_dst_desc;
+ dst_md = &dd->diff_src_desc;
+ d_weights_d = &dd->weights_desc;
+ } else {
+ prop_kind = dd->prop_kind;
+ src_md = &dd->diff_dst_desc;
+ dst_md = &dd->src_desc;
+ d_weights_d = &dd->diff_weights_desc;
+ }
+
+ const bool with_groups = d_weights_d->ndims == src_md->ndims + 1;
+
+ /* create weights desc for convolution */
+ c_weights_d = *d_weights_d;
+
+ const int ID_OC = 0 + with_groups;
+ const int ID_IC = 1 + with_groups;
+
+ nstl::swap(c_weights_d.dims[ID_OC], c_weights_d.dims[ID_IC]);
+ nstl::swap(c_weights_d.padded_dims[ID_OC], c_weights_d.padded_dims[ID_IC]);
+ nstl::swap(c_weights_d.padded_offsets[ID_OC], c_weights_d.padded_offsets[ID_IC]);
+
+ if (c_weights_d.format_kind != format_kind::any)
+ CHECK(compute_blocked_format(with_groups, d_weights_d, &c_weights_d));
+
+ return conv_desc_init(cd, prop_kind, alg_kind, src_md, &c_weights_d,
+ prop_kind != backward_weights ? &dd->bias_desc : nullptr,
+ dst_md, dd->strides, dd->dilates,
+ dd->padding[0], dd->padding[1], dd->padding_kind);
+}
+
+struct ref_deconvolution_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_deconvolution_fwd_pd_t {
+ pd_t(engine_t *engine,
+ const deconvolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const deconvolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_deconvolution_fwd_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , conv_pd_(nullptr)
+ {}
+
+ pd_t(const pd_t &other)
+ : cpu_deconvolution_fwd_pd_t(other)
+ , conv_pd_(other.conv_pd_->clone())
+ , conv_supports_bias_(other.conv_supports_bias_)
+ , dst_tag_(other.dst_tag_)
+ {}
+
+ ~pd_t() { delete conv_pd_; }
+
+ DECLARE_COMMON_PD_T(conv_pd_->name(), ref_deconvolution_fwd_t);
+
+ status_t init_convolution() {
+ using namespace types;
+
+ convolution_desc_t cd;
+ CHECK(conv_descr_create(desc(), &cd));
+
+ mkldnn_primitive_desc_iterator it(engine_, (op_desc_t *)&cd,
+ &attr_, nullptr);
+ while (++it != it.end()) {
+ conv_pd_ = *it;
+ conv_supports_bias_ =
+ static_cast<cpu_convolution_bwd_data_pd_t *>(conv_pd_)
+ ->support_bias();
+ bool output_f32 = utils::everyone_is(data_type::f32,
+ desc()->accum_data_type, desc()->dst_desc.data_type);
+
+ bool ok = true
+ && conv_pd_->weights_md()->extra.flags == 0
+ /* deconv reference code can process only f32 bias */
+ && IMPLICATION(with_bias(),
+ conv_supports_bias_ || output_f32);
+ if (ok) return status::success;
+
+ delete conv_pd_;
+ }
+ conv_pd_ = nullptr;
+ return status::unimplemented;
+ }
+
+ status_t init() {
+ using namespace format_tag;
+ bool ok = true
+ && is_fwd()
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::deconvolution_direct,
+ alg_kind::deconvolution_winograd)
+ && attr()->post_ops_.has_default_values();
+
+ if (ok) {
+ CHECK(init_convolution());
+ if (weights_md_.format_kind == format_kind::any) {
+ CHECK(compute_blocked_format(with_groups(),
+ conv_pd_->weights_md(), &desc_.weights_desc));
+ weights_md_ = desc_.weights_desc;
+ }
+ if (src_md_.format_kind == format_kind::any)
+ src_md_ = *conv_pd_->diff_dst_md();
+ if (dst_md_.format_kind == format_kind::any)
+ dst_md_ = *conv_pd_->diff_src_md();
+ if (bias_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(bias_md_, x));
+
+ dst_tag_ = memory_desc_matches_one_of_tag(dst_md_,
+ utils::pick(ndims() - 3, ncw, nchw, ncdhw),
+ utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c),
+ utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c));
+
+ return status::success;
+ }
+
+ return status::unimplemented;
+ }
+
+ virtual void init_scratchpad_md() override {
+ scratchpad_md_ = *conv_pd_->scratchpad_md();
+ }
+
+ primitive_desc_t *conv_pd_;
+ bool conv_supports_bias_;
+ format_tag_t dst_tag_;
+ };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ ref_deconvolution_fwd_t(const pd_t *apd): cpu_primitive_t(apd)
+ { pd()->conv_pd_->create_primitive((primitive_t **)&conv_p_); }
+ ~ref_deconvolution_fwd_t() { delete conv_p_; }
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ const auto &args = ctx.args();
+ exec_args_t conv_args;
+ conv_args[MKLDNN_ARG_DIFF_DST] = args.at(MKLDNN_ARG_SRC);
+ conv_args[MKLDNN_ARG_WEIGHTS] = args.at(MKLDNN_ARG_WEIGHTS);
+ if (pd()->with_bias() && pd()->conv_supports_bias_)
+ conv_args[MKLDNN_ARG_BIAS] = args.at(MKLDNN_ARG_BIAS);
+ conv_args[MKLDNN_ARG_DIFF_SRC] = args.at(MKLDNN_ARG_DST);
+ if (!types::is_zero_md(pd()->scratchpad_md()))
+ conv_args[MKLDNN_ARG_SCRATCHPAD] = args.at(MKLDNN_ARG_SCRATCHPAD);
+ const exec_ctx_t conv_ctx(ctx.stream(), std::move(conv_args));
+
+ conv_p_->execute(conv_ctx);
+
+ if (pd()->with_bias() && !pd()->conv_supports_bias_) {
+ using namespace format_tag;
+
+ auto bias = CTX_IN_MEM(const data_t *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ switch (pd()->dst_tag_) {
+ case ncdhw: case nchw: case ncw:
+ compute_fwd_bias_ncdhw(bias, dst);
+ break;
+ case nCdhw8c: case nChw8c: case nCw8c:
+ compute_fwd_bias_nCdhwXc<8>(bias, dst);
+ break;
+ case nCdhw16c: case nChw16c: case nCw16c:
+ compute_fwd_bias_nCdhwXc<16>(bias, dst);
+ break;
+ default:
+ compute_fwd_bias(bias, dst);
+ break;
+ }
+ }
+ return status::success;
+ }
+
+private:
+ void compute_fwd_bias(const data_t *bias, data_t *dst) const;
+ void compute_fwd_bias_ncdhw(const data_t *bias, data_t *dst) const;
+ template <int blksize> void compute_fwd_bias_nCdhwXc(const data_t *bias,
+ data_t *dst) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ primitive_t *conv_p_;
+};
+
+struct ref_deconvolution_bwd_data_t: public cpu_primitive_t {
+ struct pd_t: public cpu_deconvolution_bwd_data_pd_t {
+ pd_t(engine_t *engine, const deconvolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const deconvolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_deconvolution_bwd_data_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , conv_pd_(nullptr)
+ {}
+
+ pd_t(const pd_t &other)
+ : cpu_deconvolution_bwd_data_pd_t(other)
+ , conv_pd_(other.conv_pd_->clone()) {}
+
+ ~pd_t() { delete conv_pd_; }
+
+ DECLARE_COMMON_PD_T(conv_pd_->name(), ref_deconvolution_bwd_data_t);
+
+ status_t init_convolution() {
+ using namespace types;
+
+ convolution_desc_t cd;
+ status_t status = conv_descr_create(desc(), &cd);
+ if (status != status::success) return status;
+
+ mkldnn_primitive_desc_iterator it(engine_, (op_desc_t *)&cd,
+ &attr_, nullptr);
+ while (++it != it.end()) {
+ conv_pd_ = *it;
+ if (conv_pd_->weights_md()->extra.flags == 0)
+ return status::success;
+ delete conv_pd_;
+ }
+
+ return status::unimplemented;
+ }
+
+ status_t init() {
+ using namespace data_type;
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_data
+ && utils::everyone_is(data_type::f32,
+ desc()->diff_src_desc.data_type,
+ desc()->weights_desc.data_type,
+ desc()->diff_dst_desc.data_type)
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::deconvolution_direct,
+ alg_kind::deconvolution_winograd);
+
+ if (ok) {
+ CHECK(init_convolution());
+ if (weights_md_.format_kind == format_kind::any) {
+ CHECK(compute_blocked_format(with_groups(),
+ conv_pd_->weights_md(), &desc_.weights_desc));
+ weights_md_ = desc_.weights_desc;
+ }
+ if (diff_src_md_.format_kind == format_kind::any)
+ diff_src_md_ = *conv_pd_->dst_md();
+ if (diff_dst_md_.format_kind == format_kind::any)
+ diff_dst_md_ = *conv_pd_->src_md();
+
+ return status::success;
+ }
+
+ return status::unimplemented;
+ }
+
+ virtual void init_scratchpad_md() override {
+ scratchpad_md_ = *conv_pd_->scratchpad_md();
+ }
+
+ primitive_desc_t *conv_pd_;
+ };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ ref_deconvolution_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd)
+ { pd()->conv_pd_->create_primitive((primitive_t **)&conv_p_); }
+ ~ref_deconvolution_bwd_data_t() { delete conv_p_; }
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ const auto &args = ctx.args();
+ exec_args_t conv_args;
+ conv_args[MKLDNN_ARG_SRC] = args.at(MKLDNN_ARG_DIFF_DST);
+ conv_args[MKLDNN_ARG_WEIGHTS] = args.at(MKLDNN_ARG_WEIGHTS);
+ conv_args[MKLDNN_ARG_DST] = args.at(MKLDNN_ARG_DIFF_SRC);
+ if (!types::is_zero_md(pd()->scratchpad_md()))
+ conv_args[MKLDNN_ARG_SCRATCHPAD] = args.at(MKLDNN_ARG_SCRATCHPAD);
+ const exec_ctx_t conv_ctx(ctx.stream(), std::move(conv_args));
+
+ conv_p_->execute(conv_ctx);
+ return status::success;
+ }
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ primitive_t *conv_p_;
+};
+
+struct ref_deconvolution_bwd_weights_t: public cpu_primitive_t {
+ struct pd_t: public cpu_deconvolution_bwd_weights_pd_t {
+ pd_t(engine_t *engine,
+ const deconvolution_desc_t *adesc,
+ const primitive_attr_t *attr,
+ const deconvolution_fwd_pd_t *hint_fwd_pd)
+ : cpu_deconvolution_bwd_weights_pd_t(engine, adesc, attr, hint_fwd_pd)
+ , conv_pd_(nullptr)
+ {}
+
+ pd_t(const pd_t &other)
+ : cpu_deconvolution_bwd_weights_pd_t(other)
+ , conv_pd_(other.conv_pd_->clone())
+ , dst_tag_(other.dst_tag_)
+ {}
+
+ ~pd_t() { delete conv_pd_; }
+
+ DECLARE_COMMON_PD_T(conv_pd_->name(), ref_deconvolution_bwd_weights_t);
+
+ status_t init_convolution() {
+ using namespace types;
+
+ convolution_desc_t cd;
+ status_t status = conv_descr_create(desc(), &cd);
+ if (status != status::success) return status;
+
+ mkldnn_primitive_desc_iterator it(engine_, (op_desc_t *)&cd,
+ &attr_, nullptr);
+ while (++it != it.end()) {
+ conv_pd_ = *it;
+ if (conv_pd_->diff_weights_md()->extra.flags == 0)
+ return status::success;
+ delete conv_pd_;
+ }
+ return status::unimplemented;
+ }
+
+ status_t init() {
+ using namespace format_tag;
+ bool ok = true
+ && desc()->prop_kind == prop_kind::backward_weights
+ && utils::everyone_is(data_type::f32,
+ desc()->src_desc.data_type,
+ desc()->diff_weights_desc.data_type,
+ desc()->diff_dst_desc.data_type)
+ && utils::one_of(desc()->alg_kind,
+ alg_kind::deconvolution_direct,
+ alg_kind::deconvolution_winograd)
+ && attr()->has_default_values();
+ if (ok) {
+ CHECK(init_convolution());
+ if (diff_weights_md_.format_kind == format_kind::any) {
+ CHECK(compute_blocked_format(with_groups(),
+ conv_pd_->diff_weights_md(),
+ &desc_.diff_weights_desc));
+ diff_weights_md_ = desc_.diff_weights_desc;
+ }
+ if (src_md_.format_kind == format_kind::any)
+ src_md_ = *conv_pd_->diff_dst_md();
+ if (diff_dst_md_.format_kind == format_kind::any)
+ diff_dst_md_ = *conv_pd_->src_md();
+ if (diff_bias_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(diff_bias_md_, x));
+
+ dst_tag_ = memory_desc_matches_one_of_tag(diff_dst_md_,
+ utils::pick(ndims() - 3, ncw, nchw, ncdhw),
+ utils::pick(ndims() - 3, nCw8c, nChw8c, nCdhw8c),
+ utils::pick(ndims() - 3, nCw16c, nChw16c, nCdhw16c));
+
+ return status::success;
+ }
+
+ return status::unimplemented;
+ }
+
+ virtual void init_scratchpad_md() override {
+ scratchpad_md_ = *conv_pd_->scratchpad_md();
+ }
+
+ primitive_desc_t *conv_pd_;
+ format_tag_t dst_tag_;
+ };
+
+ typedef typename prec_traits<data_type::f32>::type data_t;
+
+ ref_deconvolution_bwd_weights_t(const pd_t *apd): cpu_primitive_t(apd)
+ { pd()->conv_pd_->create_primitive((primitive_t **)&conv_p_); }
+ ~ref_deconvolution_bwd_weights_t() { delete conv_p_; }
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ const auto &args = ctx.args();
+ exec_args_t conv_args;
+ conv_args[MKLDNN_ARG_DIFF_DST] = args.at(MKLDNN_ARG_SRC);
+ conv_args[MKLDNN_ARG_SRC] = args.at(MKLDNN_ARG_DIFF_DST);
+ conv_args[MKLDNN_ARG_DIFF_WEIGHTS] = args.at(MKLDNN_ARG_DIFF_WEIGHTS);
+ if (!types::is_zero_md(pd()->scratchpad_md()))
+ conv_args[MKLDNN_ARG_SCRATCHPAD] = args.at(MKLDNN_ARG_SCRATCHPAD);
+ const exec_ctx_t conv_ctx(ctx.stream(), std::move(conv_args));
+
+ status_t status = conv_p_->execute(conv_ctx);
+ if (status != status::success) return status;
+
+ if (pd()->with_bias()) {
+ using namespace format_tag;
+
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto diff_bias = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS);
+
+ switch (pd()->dst_tag_) {
+ case ncdhw: case nchw: case ncw:
+ compute_bwd_bias_ncdhw(diff_dst, diff_bias);
+ break;
+ case nCdhw8c: case nChw8c: case nCw8c:
+ compute_bwd_bias_nCdhwXc<8>(diff_dst, diff_bias);
+ break;
+ case nCdhw16c: case nChw16c: case nCw16c:
+ compute_bwd_bias_nCdhwXc<16>(diff_dst, diff_bias);
+ break;
+ default:
+ compute_bwd_bias(diff_dst, diff_bias);
+ break;
+ }
+ }
+ return status::success;
+ }
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ void compute_bwd_bias(const data_t *diff_dst, data_t *diff_bias) const;
+ void compute_bwd_bias_ncdhw(const data_t *diff_dst,
+ data_t *diff_bias) const;
+ template <int blksize> void compute_bwd_bias_nCdhwXc(
+ const data_t *diff_dst, data_t *diff_bias) const;
+
+ primitive_t *conv_p_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.cpp
new file mode 100644
index 0000000000..7beee8d323
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.cpp
@@ -0,0 +1,297 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "ref_eltwise.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace alg_kind;
+using namespace math;
+
+ref_eltwise_scalar_fwd_t::ref_eltwise_scalar_fwd_t(alg_kind_t alg, float alpha,
+ float beta): alg_(alg), alpha_(alpha), beta_(beta) {
+ assert(utils::one_of(alg_, eltwise_relu, eltwise_tanh, eltwise_elu,
+ eltwise_square, eltwise_abs, eltwise_sqrt, eltwise_linear,
+ eltwise_bounded_relu, eltwise_soft_relu, eltwise_logistic));
+}
+
+ref_eltwise_scalar_fwd_t::ref_eltwise_scalar_fwd_t(
+ const post_ops_t::entry_t::eltwise_t &eltwise)
+ : ref_eltwise_scalar_fwd_t(eltwise.alg, eltwise.alpha, eltwise.beta) {}
+
+float ref_eltwise_scalar_fwd_t::compute_scalar(float s) {
+ switch (alg_) {
+ case eltwise_relu: return relu_fwd(s, alpha_);
+ case eltwise_tanh: return tanh_fwd(s);
+ case eltwise_elu: return elu_fwd(s, alpha_);
+ case eltwise_square: return square_fwd(s);
+ case eltwise_abs: return abs_fwd(s);
+ case eltwise_sqrt: return sqrt_fwd(s);
+ case eltwise_linear: return linear_fwd(s, alpha_, beta_);
+ case eltwise_bounded_relu: return bounded_relu_fwd(s, alpha_);
+ case eltwise_soft_relu: return soft_relu_fwd(s);
+ case eltwise_logistic: return logistic_fwd(s);
+ default: assert(!"unknown eltwise alg_kind");
+ }
+
+ return 0.f;
+}
+
+template <impl::data_type_t data_type>
+void ref_eltwise_fwd_t<data_type>::execute_forward_nCspBc_padded(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+ const blocking_desc_t &blk = data_d.blocking_desc();
+ const int block = blk.inner_blks[0];
+
+ const int MB = pd()->MB();
+ const int C = pd()->C() / block;
+ const int C_PADDED = data_d.padded_dims()[1] / block;
+ const int tail = pd()->C() % block;
+ const int SP = pd()->D() * pd()->H() * pd()->W();
+ const auto alg_kind = pd()->desc()->alg_kind;
+ const float alpha = pd()->desc()->alpha;
+ const float beta = pd()->desc()->beta;
+
+ auto ker = [=] (data_t &d, data_t s) {
+ switch (alg_kind) {
+ case eltwise_linear: d = linear_fwd(s, alpha, beta); break;
+ case eltwise_bounded_relu:
+ d = bounded_relu_fwd(s, alpha); break;
+ case eltwise_soft_relu: d = soft_relu_fwd(s); break;
+ case eltwise_logistic: d = logistic_fwd(s); break;
+ default: assert(!"unknown eltwise alg_kind");
+ }
+ };
+
+ // FIXME: integer overflow?
+
+ parallel_nd(MB, C_PADDED, SP,
+ [&](int n, int c, int sp) {
+ auto d_off = (n*C_PADDED*SP + c*SP + sp) * block;
+ if (c < C) {
+ for (int v = 0; v < block; v++)
+ ker(dst[d_off + v], src[d_off + v]);
+ } else {
+ for (int v = 0; v < tail; v++)
+ ker(dst[d_off + v], src[d_off + v]);
+ }
+ });
+}
+
+template <impl::data_type_t data_type>
+void ref_eltwise_fwd_t<data_type>::execute_forward_generic(
+ const exec_ctx_t &ctx) const {
+ /* fast return */
+ if (pd()->has_zero_dim_memory()) return;
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+
+ const int MB = pd()->MB();
+ const int C = pd()->C();
+ const int D = pd()->D();
+ const int H = pd()->H();
+ const int W = pd()->W();
+ const auto alg_kind = pd()->desc()->alg_kind;
+ const float alpha = pd()->desc()->alpha;
+ const float beta = pd()->desc()->beta;
+ const bool is_3d = pd()->desc()->data_desc.ndims == 5;
+
+ parallel_nd(MB, C, D, H, W,
+ [&](int n, int c, int id, int h, int w) {
+ auto d_off = is_3d
+ ? data_d.off(n, c, id, h, w) : data_d.off(n, c, h, w);
+ data_t s = src[d_off];
+ data_t &d = dst[d_off];
+ switch (alg_kind) {
+ case eltwise_relu: d = relu_fwd(s, alpha); break;
+ case eltwise_tanh: d = tanh_fwd(s); break;
+ case eltwise_elu: d = elu_fwd(s, alpha); break;
+ case eltwise_square: d = square_fwd(s); break;
+ case eltwise_abs: d = abs_fwd(s); break;
+ case eltwise_sqrt: d = sqrt_fwd(s); break;
+ case eltwise_linear: d = linear_fwd(s, alpha, beta); break;
+ case eltwise_bounded_relu:
+ d = bounded_relu_fwd(s, alpha); break;
+ case eltwise_soft_relu: d = soft_relu_fwd(s); break;
+ case eltwise_logistic: d = logistic_fwd(s); break;
+ default: assert(!"unknown eltwise alg_kind");
+ }
+ });
+}
+
+template <impl::data_type_t data_type>
+void ref_eltwise_fwd_t<data_type>::execute_forward_dense(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+
+ const ptrdiff_t nelems = static_cast<ptrdiff_t>(data_d.nelems(true));
+ const auto alg_kind = pd()->desc()->alg_kind;
+ const float alpha = pd()->desc()->alpha;
+ const float beta = pd()->desc()->beta;
+
+ src += data_d.offset0();
+ dst += data_d.offset0();
+
+ if (alg_kind == eltwise_relu) {
+ // a fast path for relu as the most popular activation
+ parallel_nd(nelems, [&](ptrdiff_t e) {
+ dst[e] = relu_fwd(src[e], alpha);
+ });
+ return;
+ }
+
+ parallel_nd(nelems, [&](ptrdiff_t e) {
+ const data_t s = src[e];
+ data_t &d = dst[e];
+
+ switch (alg_kind) {
+ case eltwise_tanh: d = tanh_fwd(s); break;
+ case eltwise_elu: d = elu_fwd(s, alpha); break;
+ case eltwise_square: d = square_fwd(s); break;
+ case eltwise_abs: d = abs_fwd(s); break;
+ case eltwise_sqrt: d = sqrt_fwd(s); break;
+ case eltwise_linear: d = linear_fwd(s, alpha, beta); break;
+ case eltwise_bounded_relu: d = bounded_relu_fwd(s, alpha); break;
+ case eltwise_soft_relu: d = soft_relu_fwd(s); break;
+ case eltwise_logistic: d = logistic_fwd(s); break;
+ default: assert(!"unknown eltwise alg_kind");
+ }
+ });
+}
+
+template <impl::data_type_t data_type>
+void ref_eltwise_bwd_t<data_type>::execute_backward_generic(
+ const exec_ctx_t &ctx) const {
+ /* fast return */
+ if (pd()->has_zero_dim_memory()) return;
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+ const memory_desc_wrapper diff_data_d(pd()->diff_src_md());
+
+ const int MB = pd()->MB();
+ const int C = pd()->C();
+ const int D = pd()->D();
+ const int H = pd()->H();
+ const int W = pd()->W();
+ const auto alg_kind = pd()->desc()->alg_kind;
+ const float alpha = pd()->desc()->alpha;
+ const float beta = pd()->desc()->beta;
+ const bool is_3d = pd()->desc()->data_desc.ndims == 5;
+
+ parallel_nd(MB, C, D, H, W,
+ [&](int n, int c, int d, int h, int w) {
+ auto data_off = is_3d
+ ? data_d.off(n, c, d, h, w) : data_d.off(n, c, h, w);
+ auto diff_data_off = is_3d
+ ? diff_data_d.off(n, c, d, h, w)
+ : diff_data_d.off(n, c, h, w);
+ data_t s = src[data_off];
+ data_t dd = diff_dst[diff_data_off];
+ data_t &ds = diff_src[diff_data_off];
+ switch (alg_kind) {
+ case eltwise_relu: ds = relu_bwd(dd, s, alpha); break;
+ case eltwise_tanh: ds = tanh_bwd(dd, s); break;
+ case eltwise_elu: ds = elu_bwd(dd, s, alpha); break;
+ case eltwise_square: ds = square_bwd(dd, s); break;
+ case eltwise_abs: ds = abs_bwd(dd, s); break;
+ case eltwise_sqrt: ds = sqrt_bwd(dd, s); break;
+ case eltwise_linear:
+ ds = linear_bwd(dd, s, alpha, beta); break;
+ case eltwise_bounded_relu:
+ ds = bounded_relu_bwd(dd, s, alpha); break;
+ case eltwise_soft_relu: ds = soft_relu_bwd(dd, s); break;
+ case eltwise_logistic: ds = logistic_bwd(dd, s); break;
+ default: assert(!"unknown eltwise alg_kind");
+ }
+ });
+}
+
+template <impl::data_type_t data_type>
+void ref_eltwise_bwd_t<data_type>::execute_backward_dense(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+ const memory_desc_wrapper diff_data_d(pd()->diff_src_md());
+
+ const ptrdiff_t nelems = static_cast<ptrdiff_t>(data_d.nelems(true));
+ const auto alg_kind = pd()->desc()->alg_kind;
+ const float alpha = pd()->desc()->alpha;
+ const float beta = pd()->desc()->beta;
+
+ src += data_d.offset0();
+ diff_dst += diff_data_d.offset0();
+ diff_src += diff_data_d.offset0();
+
+ parallel_nd(nelems, [&](ptrdiff_t e) {
+ const data_t dd = diff_dst[e];
+ const data_t s = src[e];
+ data_t &ds = diff_src[e];
+
+ switch (alg_kind) {
+ case eltwise_relu: ds = relu_bwd(dd, s, alpha); break;
+ case eltwise_tanh: ds = tanh_bwd(dd, s); break;
+ case eltwise_elu: ds = elu_bwd(dd, s, alpha); break;
+ case eltwise_square: ds = square_bwd(dd, s); break;
+ case eltwise_abs: ds = abs_bwd(dd, s); break;
+ case eltwise_sqrt: ds = sqrt_bwd(dd, s); break;
+ case eltwise_linear: ds = linear_bwd(dd, s, alpha, beta); break;
+ case eltwise_bounded_relu: ds = bounded_relu_bwd(dd, s, alpha); break;
+ case eltwise_soft_relu: ds = soft_relu_bwd(dd, s); break;
+ case eltwise_logistic: ds = logistic_bwd(dd, s); break;
+ default: assert(!"unknown eltwise alg_kind");
+ }
+ });
+}
+
+template struct ref_eltwise_fwd_t<data_type::f32>;
+template struct ref_eltwise_fwd_t<data_type::s32>;
+template struct ref_eltwise_fwd_t<data_type::s8>;
+template struct ref_eltwise_fwd_t<data_type::u8>;
+
+template struct ref_eltwise_bwd_t<data_type::f32>;
+template struct ref_eltwise_bwd_t<data_type::s32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.hpp
new file mode 100644
index 0000000000..8f4ab35413
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_eltwise.hpp
@@ -0,0 +1,168 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REF_ELTWISE_HPP
+#define CPU_REF_ELTWISE_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_eltwise_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct ref_eltwise_scalar_fwd_t {
+public:
+ ref_eltwise_scalar_fwd_t(alg_kind_t alg, float alpha, float beta);
+
+ // note that eltwise.scale is ignored
+ ref_eltwise_scalar_fwd_t(const post_ops_t::entry_t::eltwise_t &eltwise);
+
+ float compute_scalar(float s);
+
+ const alg_kind_t alg_;
+ const float alpha_;
+ const float beta_;
+};
+
+template <impl::data_type_t data_type>
+struct ref_eltwise_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_eltwise_fwd_pd_t {
+ using cpu_eltwise_fwd_pd_t::cpu_eltwise_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_eltwise_fwd_t);
+
+ status_t init() {
+ using namespace utils;
+
+ auto src_d = memory_desc_wrapper(src_md());
+
+ use_dense_ = false
+ || src_d.is_dense()
+ || (src_d.is_dense(true) && is_zero_preserved());
+
+ use_nCspBc_padded_ = !use_dense_
+ && src_d.blocking_desc().inner_nblks == 1
+ && one_of(src_d.blocking_desc().inner_blks[0], 8, 16)
+ && src_d.blocking_desc().inner_idxs[0] == 1
+ && src_d.only_padded_dim(1)
+ && src_d.is_dense(true);
+
+ if (has_zero_dim_memory())
+ use_dense_ = use_nCspBc_padded_ = false;
+
+ const bool use_generic = !use_dense_ && !use_nCspBc_padded_;
+
+ bool ok = true
+ && is_fwd()
+ && everyone_is(data_type, desc()->data_desc.data_type)
+ && IMPLICATION(use_generic, one_of(src_d.ndims(), 4, 5))
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ return status::success;
+ }
+
+ bool use_dense_, use_nCspBc_padded_;
+ };
+
+ ref_eltwise_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ if (pd()->use_dense_)
+ execute_forward_dense(ctx);
+ else if (pd()->use_nCspBc_padded_)
+ execute_forward_nCspBc_padded(ctx);
+ else
+ execute_forward_generic(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward_nCspBc_padded(const exec_ctx_t &ctx) const;
+ void execute_forward_dense(const exec_ctx_t &ctx) const;
+ void execute_forward_generic(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t data_type>
+struct ref_eltwise_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_eltwise_bwd_pd_t {
+ using cpu_eltwise_bwd_pd_t::cpu_eltwise_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_eltwise_bwd_t);
+
+ status_t init() {
+ using namespace utils;
+
+ bool ok = true
+ && !is_fwd()
+ && everyone_is(data_type,
+ desc()->data_desc.data_type,
+ desc()->diff_data_desc.data_type)
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ auto diff_dst_d = memory_desc_wrapper(diff_dst_md());
+ const bool same_fmt_ = diff_dst_d == memory_desc_wrapper(src_md());
+
+ use_dense_ = true
+ && same_fmt_
+ && diff_dst_d.is_dense(true)
+ && is_zero_preserved()
+ && !has_zero_dim_memory();
+ const bool use_generic = !use_dense_;
+
+ if (use_generic && !one_of(diff_dst_d.ndims(), 4, 5))
+ return status::unimplemented;
+
+ return status::success;
+ }
+
+ bool use_dense_;
+ };
+
+ ref_eltwise_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ if (pd()->use_dense_)
+ execute_backward_dense(ctx);
+ else
+ execute_backward_generic(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_dense(const exec_ctx_t &ctx) const;
+ void execute_backward_generic(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.cpp
new file mode 100644
index 0000000000..c807a9ffd0
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.cpp
@@ -0,0 +1,285 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "mkldnn_thread.hpp"
+#include "mkldnn_traits.hpp"
+#include "math_utils.hpp"
+
+#include "ref_inner_product.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using math::saturate;
+using math::get_bias;
+
+template <data_type_t src_type, data_type_t wei_type, data_type_t dst_type,
+ data_type_t acc_type>
+void ref_inner_product_fwd_t<src_type, wei_type, dst_type, acc_type>::
+execute_forward(const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto bias = CTX_IN_MEM(const char *, MKLDNN_ARG_BIAS);
+ auto dst = CTX_OUT_MEM(dst_data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper bias_d(pd()->weights_md(1));
+
+ const int MB = pd()->MB();
+ const int OC = pd()->OC();
+ const int IC = pd()->IC();
+
+ const bool src_has_spatial = utils::one_of(src_d.ndims(), 3, 4, 5);
+ const int ndims = src_d.ndims() - 2;
+
+ const auto &post_ops = pd()->attr()->post_ops_;
+ const bool do_relu = post_ops.len_ == 1;
+ const float nslope = do_relu ? post_ops.entry_[0].eltwise.alpha : 0.f;
+
+ auto ker_has_spatial = [=](int mb, int oc) {
+ acc_data_t d = 0;
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+ for (int ic = 0; ic < IC; ++ic) {
+ for (int kd = 0; kd < KD; ++kd) {
+ for (int kh = 0; kh < KH; ++kh) {
+ for (int kw = 0; kw < KW; ++kw) {
+ switch (ndims) {
+ case 3:
+ d += (acc_data_t)src[src_d.off(mb, ic, kd, kh, kw)]
+ * weights[weights_d.off(
+ oc, ic, kd, kh, kw)];
+ break;
+ case 2:
+ d += (acc_data_t)src[src_d.off(mb, ic, kh, kw)]
+ * weights[weights_d.off(oc, ic, kh, kw)];
+ break;
+ case 1:
+ d += (acc_data_t)src[src_d.off(mb, ic, kw)]
+ * weights[weights_d.off(oc, ic, kw)];
+ break;
+ default: assert(!"unsupported ndims size");
+ }
+ }
+ }
+ }
+ }
+ return d;
+ };
+
+ auto ker_no_spatial = [=](int mb, int oc) {
+ acc_data_t d = 0;
+ for (int ic = 0; ic < IC; ++ic) {
+ d += (acc_data_t)src[src_d.off(mb, ic)]
+ * weights[weights_d.off(oc, ic)];
+ }
+ return d;
+ };
+
+ parallel_nd(MB, OC, [&](int mb, int oc) {
+ float a = bias
+ ? get_bias(bias, bias_d.off(oc), pd()->desc()->bias_desc.data_type)
+ : 0;
+ if (src_has_spatial)
+ a += ker_has_spatial(mb, oc);
+ else
+ a += ker_no_spatial(mb, oc);
+ if (do_relu && a < (acc_data_t)0)
+ a *= nslope;
+ dst[dst_d.off(mb, oc)] = saturate<dst_data_t>(a);
+ });
+}
+
+using namespace data_type;
+template struct ref_inner_product_fwd_t<f32>;
+template struct ref_inner_product_fwd_t<u8, s8, f32, s32>;
+template struct ref_inner_product_fwd_t<u8, s8, s32, s32>;
+template struct ref_inner_product_fwd_t<u8, s8, s8, s32>;
+template struct ref_inner_product_fwd_t<u8, s8, u8, s32>;
+
+template <data_type_t diff_src_type, data_type_t wei_type,
+ data_type_t diff_dst_type, data_type_t acc_type>
+void ref_inner_product_bwd_data_t<diff_src_type, wei_type, diff_dst_type,
+ acc_type>::execute_backward_data(const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const diff_dst_data_t *, MKLDNN_ARG_DIFF_DST);
+ auto weights = CTX_IN_MEM(const wei_data_t *, MKLDNN_ARG_WEIGHTS);
+ auto diff_src = CTX_OUT_MEM(diff_src_data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper weights_d(pd()->weights_md(0));
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+
+ const int MB = pd()->MB();
+ const int OC = pd()->OC();
+ const int IC = pd()->IC();
+
+ const bool diff_src_has_spatial
+ = utils::one_of(diff_src_d.ndims(), 3, 4, 5);
+ const int ndims = diff_src_d.ndims() - 2;
+
+ parallel_nd(MB, IC, [&](int mb, int ic) {
+ if (diff_src_has_spatial) {
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+ for (int kd = 0; kd < KD; ++kd)
+ for (int kh = 0; kh < KH; ++kh)
+ for (int kw = 0; kw < KW; ++kw) {
+ acc_data_t ds = acc_data_t(0);
+ for (int oc = 0; oc < OC; ++oc) {
+ switch (ndims) {
+ case 3:
+ ds += (acc_data_t)(diff_dst[diff_dst_d.off(mb, oc)]
+ * weights[weights_d.off(oc, ic, kd, kh, kw)]);
+ break;
+ case 2:
+ ds += (acc_data_t)(diff_dst[diff_dst_d.off(mb, oc)]
+ * weights[weights_d.off(oc, ic, kh, kw)]);
+ break;
+ case 1:
+ ds += (acc_data_t)(diff_dst[diff_dst_d.off(mb, oc)]
+ * weights[weights_d.off(oc, ic, kw)]);
+ break;
+ default: assert(!"unsupported ndims size");
+ }
+ }
+ switch (ndims) {
+ case 3:
+ diff_src[diff_src_d.off(mb, ic, kd, kh, kw)]
+ = (diff_src_data_t)ds;
+ break;
+ case 2:
+ diff_src[diff_src_d.off(mb, ic, kh, kw)]
+ = (diff_src_data_t)ds;
+ break;
+ case 1:
+ diff_src[diff_src_d.off(mb, ic, kw)] = (diff_src_data_t)ds;
+ break;
+ default: assert(!"unsupported ndims size");
+ }
+ }
+ } else {
+ acc_data_t ds = acc_data_t(0);
+ for (int oc = 0; oc < OC; ++oc) {
+ ds += (acc_data_t)(diff_dst[diff_dst_d.off(mb, oc)] *
+ weights[weights_d.off(oc, ic)]);
+ }
+ diff_src[diff_src_d.off(mb, ic)] = (diff_src_data_t)ds;
+ }
+ });
+}
+
+template struct ref_inner_product_bwd_data_t<f32, f32, f32, f32>;
+
+template <impl::data_type_t data_type>
+void ref_inner_product_bwd_weights_t<data_type>::execute_backward_weights(
+ const exec_ctx_t &ctx) const {
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_weights = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_WEIGHTS);
+ auto diff_bias = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_BIAS);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_weights_d(pd()->diff_weights_md(0));
+ const memory_desc_wrapper diff_bias_d(pd()->diff_weights_md(1));
+
+ const int MB = pd()->MB();
+ const int OC = pd()->OC();
+ const int IC = pd()->IC();
+
+ const bool src_has_spatial = utils::one_of(src_d.ndims(), 3, 4 ,5);
+ const int ndims = src_d.ndims() - 2;
+
+ parallel_nd(OC, IC, [&](int oc, int ic) {
+ if (src_has_spatial) {
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+ for (int kd = 0; kd < KD; ++kd) {
+ for (int kh = 0; kh < KH; ++kh) {
+ for (int kw = 0; kw < KW; ++kw) {
+ data_t *dw(nullptr);
+ switch (ndims) {
+ case 3:
+ dw = &diff_weights[diff_weights_d.off(
+ oc, ic, kd, kh, kw)];
+ break;
+ case 2:
+ dw = &diff_weights[diff_weights_d.off(
+ oc, ic, kh, kw)];
+ break;
+ case 1:
+ dw = &diff_weights[diff_weights_d.off(oc, ic, kw)];
+ break;
+ default: assert(!"unsupported ndims size");
+ }
+ *dw = data_t(0);
+ for (int mb = 0; mb < MB; ++mb) {
+ switch (ndims) {
+ case 3:
+ *dw += diff_dst[diff_dst_d.off(mb, oc)]
+ * src[src_d.off(mb, ic, kd, kh, kw)];
+ break;
+ case 2:
+ *dw += diff_dst[diff_dst_d.off(mb, oc)]
+ * src[src_d.off(mb, ic, kh, kw)];
+ break;
+ case 1:
+ *dw += diff_dst[diff_dst_d.off(mb, oc)]
+ * src[src_d.off(mb, ic, kw)];
+ break;
+ default: assert(!"unsupported ndims size");
+ }
+ }
+ }
+ }
+ }
+ } else {
+ data_t *dw = &diff_weights[diff_weights_d.off(oc, ic)];
+ *dw = data_t(0);
+ for (int mb = 0; mb < MB; ++mb) {
+ *dw += diff_dst[diff_dst_d.off(mb, oc)] *
+ src[src_d.off(mb, ic)];
+ }
+ }
+ });
+
+ if (diff_bias) {
+ diff_bias += diff_bias_d.offset0();
+
+ parallel_nd(OC, [&](int oc) {
+ data_t *db = &diff_bias[oc];
+ *db = data_t(0);
+ for (int mb = 0; mb < MB; ++mb)
+ *db += diff_dst[diff_dst_d.off(mb, oc)];
+ });
+ }
+}
+
+template struct ref_inner_product_bwd_weights_t<data_type::f32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.hpp
new file mode 100644
index 0000000000..bf87dbd514
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_inner_product.hpp
@@ -0,0 +1,159 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REF_INNER_PRODUCT_HPP
+#define CPU_REF_INNER_PRODUCT_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_inner_product_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t src_type, impl::data_type_t wei_type = src_type,
+ impl::data_type_t dst_type = src_type,
+ impl::data_type_t acc_type = dst_type>
+struct ref_inner_product_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_inner_product_fwd_pd_t {
+ using cpu_inner_product_fwd_pd_t::cpu_inner_product_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_inner_product_fwd_t);
+
+ status_t init() {
+ using namespace data_type;
+
+ bool ok = true
+ && set_default_params() == status::success
+ && is_fwd()
+ && src_md()->data_type == src_type
+ && weights_md()->data_type == wei_type
+ && desc()->accum_data_type == acc_type
+ && dst_md()->data_type == dst_type
+ && IMPLICATION(with_bias(), utils::one_of(
+ weights_md(1)->data_type, f32, s32, s8, u8))
+ && attr()->output_scales_.has_default_values()
+ && attr()->post_ops_.len_ <= 1
+ && IMPLICATION(attr()->post_ops_.len_ == 1,
+ attr()->post_ops_.entry_[0].is_relu(true, false));
+ return ok ? status::success : status::unimplemented;
+ }
+ };
+
+ ref_inner_product_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<wei_type>::type wei_data_t;
+ typedef typename prec_traits<dst_type>::type dst_data_t;
+ typedef typename prec_traits<acc_type>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t diff_src_type, impl::data_type_t wei_type,
+ impl::data_type_t diff_dst_type,
+ impl::data_type_t acc_type = diff_src_type>
+struct ref_inner_product_bwd_data_t: public cpu_primitive_t {
+ struct pd_t: public cpu_inner_product_bwd_data_pd_t {
+ using cpu_inner_product_bwd_data_pd_t::cpu_inner_product_bwd_data_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_inner_product_bwd_data_t);
+
+ status_t init() {
+ bool ok = true
+ && set_default_params() == status::success
+ && desc()->prop_kind == prop_kind::backward_data
+ && diff_src_md()->data_type == diff_src_type
+ && weights_md()->data_type == wei_type
+ && desc()->accum_data_type == acc_type
+ && diff_dst_md()->data_type == diff_dst_type
+ && attr()->has_default_values();
+ return ok ? status::success : status::unimplemented;
+ }
+ };
+
+ ref_inner_product_bwd_data_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ typedef typename prec_traits<diff_src_type>::type diff_src_data_t;
+ typedef typename prec_traits<wei_type>::type wei_data_t;
+ typedef typename prec_traits<diff_dst_type>::type diff_dst_data_t;
+ typedef typename prec_traits<acc_type>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_data(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_data(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t data_type>
+struct ref_inner_product_bwd_weights_t: public cpu_primitive_t {
+ struct pd_t: public cpu_inner_product_bwd_weights_pd_t {
+ using cpu_inner_product_bwd_weights_pd_t::cpu_inner_product_bwd_weights_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_inner_product_bwd_weights_t);
+
+ status_t init() {
+ bool ok = true
+ && set_default_params() == status::success
+ && desc()->prop_kind == prop_kind::backward_weights
+ && utils::everyone_is(data_type,
+ src_md()->data_type,
+ diff_dst_md()->data_type,
+ diff_weights_md()->data_type)
+ && IMPLICATION(with_bias(),
+ data_type == diff_weights_md(1)->data_type)
+ && attr()->has_default_values();
+ return ok ? status::success : status::unimplemented;
+ }
+ };
+
+ ref_inner_product_bwd_weights_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward_weights(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_weights(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.cpp
new file mode 100644
index 0000000000..325e97963b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.cpp
@@ -0,0 +1,252 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <math.h>
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+
+#include "ref_lrn.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+static inline float fast_negative_powf(float omega, float beta) {
+ float Y;
+/*
+ * Y = omega^(-3/4) =
+ * = 1.0f / sqrtf(omega) * sqrtf(1.0f / sqrtf(omega))
+ * = sqrtf(1.0f / sqrtf(omega)) * 1.0f / sqrtf(omega)
+ * = sqrtf(1.0f / sqrtf(omega)) / sqrtf(omega)
+ * = sqrtf(1.0f / sqrtf(omega) / omega)
+ * = sqrtf(1.0f / (sqrtf(omega) * omega))
+ */
+ if (beta == 0.75f) {
+ Y = sqrtf(1.0f / (sqrtf(omega) * omega));
+ } else {
+ Y = 1.0f / powf(omega, beta);
+ }
+ return Y;
+};
+
+template <impl::data_type_t data_type>
+template <impl::format_tag_t tag>
+void ref_lrn_fwd_t<data_type>::execute_forward(const exec_ctx_t &ctx) const {
+ using namespace alg_kind;
+ using namespace format_tag;
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+
+ const int C = pd()->C();
+ const int H = pd()->H();
+ const int W = pd()->W();
+ const size_t stride_mb = data_d.blocking_desc().strides[0];
+ const bool across_channels = pd()->desc()->alg_kind == lrn_across_channels;
+ constexpr int blksize = tag == nChw16c ? 16 : 8;
+
+ auto data_off = [&](int mb, int c, int h, int w) -> size_t {
+ switch (tag) {
+ case nChw16c:
+ case nChw8c: return mb * stride_mb + c / blksize * H * W * blksize
+ + h * W * blksize + w * blksize + c % blksize;
+ case nchw: return mb * stride_mb + c * H * W + h * W + w;
+ case nhwc: return mb * stride_mb + h * W * C + w * C + c;
+ default: return data_d.off(mb, c, h, w);
+ }
+ };
+
+ auto ker = [=](data_t *d, int mb, int oc, int oh, int ow) {
+ const float alpha = static_cast<float>(pd()->desc()->lrn_alpha);
+ const float beta = static_cast<float>(pd()->desc()->lrn_beta);
+ const float k = static_cast<float>(pd()->desc()->lrn_k);
+
+ const int size = pd()->desc()->local_size;
+ const int half_size = (size - 1) / 2;
+
+ float sum = 0;
+ if (across_channels) {
+ const int c_st = nstl::max(oc - half_size + 0, 0);
+ const int c_en = nstl::min(oc + half_size + 1, C);
+
+ for (int c = c_st; c < c_en; ++c) {
+ const float s = src[data_off(mb, c, oh, ow)];
+ sum += s * s;
+ }
+ } else {
+ int h_st = nstl::max(oh - half_size + 0, 0);
+ int h_en = nstl::min(oh + half_size + 1, H);
+ int w_st = nstl::max(ow - half_size + 0, 0);
+ int w_en = nstl::min(ow + half_size + 1, W);
+ for (int h = h_st; h < h_en; ++h) {
+ for (int w = w_st; w < w_en; ++w) {
+ const float s = src[data_off(mb, oc, h, w)];
+ sum += s * s;
+ }
+ }
+ }
+ const int summands = across_channels ? size : size * size;
+ sum = k + alpha * sum / summands;
+ size_t off = data_off(mb, oc, oh, ow);
+ d[0] = static_cast<data_t>(src[off] * fast_negative_powf(sum, beta));
+ };
+
+ const int MB = pd()->MB();
+ if (tag == nChw16c || tag == nChw8c) {
+ parallel_nd(MB, utils::div_up(C, blksize), H, W,
+ [&](int mb, int c_blk, int h, int w) {
+ int c = c_blk * blksize;
+ const size_t off = mb * stride_mb + c * H * W
+ + (h * W + w) * blksize;
+ PRAGMA_OMP_SIMD()
+ for (int cc = 0; cc < nstl::min(blksize, C - c); ++cc)
+ ker(&dst[off + cc], mb, c + cc, h, w);
+ });
+ } else if (tag == nhwc) {
+ parallel_nd(MB, H, W, C,
+ [&](int mb, int h, int w, int c) {
+ const size_t off = mb * stride_mb + h * W * C + w * C + c;
+ ker(&dst[off], mb, c, h, w);
+ });
+ } else {
+ parallel_nd(MB, C, H, W,
+ [&](int mb, int c, int h, int w) {
+ const size_t off = data_off(mb, c, h, w);
+ ker(&dst[off], mb, c, h, w);
+ });
+ }
+}
+
+template <impl::data_type_t data_type>
+template <mkldnn_format_tag_t tag>
+void ref_lrn_bwd_t<data_type>::execute_backward(const exec_ctx_t &ctx) const {
+ using namespace alg_kind;
+ using namespace format_tag;
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+
+ const int MB = pd()->MB();
+ const int C = pd()->C();
+ const int H = pd()->H();
+ const int W = pd()->W();
+ const size_t stride_mb = data_d.blocking_desc().strides[0];
+ constexpr int blksize = tag == nChw16c ? 16 : 8;
+
+ const float alpha = static_cast<float>(pd()->desc()->lrn_alpha);
+ const float beta = static_cast<float>(pd()->desc()->lrn_beta);
+ const float k = static_cast<float>(pd()->desc()->lrn_k);
+ const int kernel_size = pd()->desc()->local_size;
+ const int half_ksize = (kernel_size - 1) / 2;
+
+ auto data_off = [&](int mb, int c, int h, int w) -> size_t {
+ switch (tag) {
+ case nChw16c:
+ case nChw8c: return mb * stride_mb + c/blksize * H * W * blksize
+ + h * W * blksize + w * blksize + c%blksize;
+ case nchw: return mb * stride_mb + c * H * W + h * W + w;
+ case nhwc: return mb * stride_mb + h * W * C + w * C + c;
+ default: return data_d.off(mb, c, h, w);
+ }
+ };
+
+ auto ker = [=](data_t *d, int mb, int oc, int oh, int ow) {
+ const int c_st = nstl::max(oc - half_ksize + 0, 0);
+ const int c_en = nstl::min(oc + half_ksize + 1, C);
+
+ float A = 0, B = 0, omega_mid = 0;
+ for (int c = c_st; c < c_en; c++) {
+ float sum = 0.0;
+ const int i_st = nstl::max(c - half_ksize, 0);
+ const int i_en = nstl::min(c + kernel_size - half_ksize, C);
+
+ for (int i = i_st; i < i_en; ++i) {
+ const float value = src[data_off(mb, i, oh, ow)];
+ sum += value * value;
+ }
+ const float omega = static_cast<float>(k + sum * alpha / kernel_size);
+ if (c == oc) omega_mid = omega;
+ float t = src[data_off(mb, c, oh, ow)]
+ * fast_negative_powf(omega, beta);
+ B += 1.0f / omega * t * diff_dst[data_off(mb, c, oh, ow)];
+ }
+
+ const size_t off = data_off(mb, oc, oh, ow);
+ A = fast_negative_powf(omega_mid, beta) * diff_dst[off];
+ B *= src[off];
+ B *= (2.0f * alpha * beta) / kernel_size;
+ *d = static_cast<data_t>(A - B); // final cast down to data_t
+ };
+
+ if (tag == nChw16c || tag == nChw8c) {
+ parallel_nd(MB, utils::div_up(C, blksize), H, W,
+ [&](int mb, int c_blk, int h, int w) {
+ int c = c_blk * blksize;
+ const size_t off = mb * stride_mb + c * H * W +
+ (h * W + w) * blksize;
+ PRAGMA_OMP_SIMD()
+ for (int cc = 0; cc < nstl::min(blksize, C - c); ++cc)
+ ker(&diff_src[off + cc], mb, c + cc, h, w);
+ });
+ } else if (tag == nhwc) {
+ parallel_nd(MB, H, W, C,
+ [&](int mb, int h, int w, int c) {
+ const size_t off = mb * stride_mb + h * W * C + w * C + c;
+ ker(&diff_src[off], mb, c, h, w);
+ });
+ } else {
+ parallel_nd(MB, C, H, W,
+ [&](int mb, int c, int h, int w) {
+ const size_t off = data_off(mb, c, h, w);
+ ker(&diff_src[off], mb, c, h, w);
+ });
+ }
+}
+
+template void ref_lrn_fwd_t<data_type::f32>::
+execute_forward<format_tag::nChw16c>(const exec_ctx_t &ctx) const;
+template void ref_lrn_fwd_t<data_type::f32>::
+execute_forward<format_tag::nChw8c>(const exec_ctx_t &ctx) const;
+template void ref_lrn_fwd_t<data_type::f32>::
+execute_forward<format_tag::nchw>(const exec_ctx_t &ctx) const;
+template void ref_lrn_fwd_t<data_type::f32>::
+execute_forward<format_tag::nhwc>(const exec_ctx_t &ctx) const;
+template void ref_lrn_fwd_t<data_type::f32>::
+execute_forward<format_tag::any>(const exec_ctx_t &ctx) const;
+template void ref_lrn_bwd_t<data_type::f32>::
+execute_backward<format_tag::nChw16c>(const exec_ctx_t &ctx) const;
+template void ref_lrn_bwd_t<data_type::f32>::
+execute_backward<format_tag::nChw8c>(const exec_ctx_t &ctx) const;
+template void ref_lrn_bwd_t<data_type::f32>::
+execute_backward<format_tag::nchw>(const exec_ctx_t &ctx) const;
+template void ref_lrn_bwd_t<data_type::f32>::
+execute_backward<format_tag::nhwc>(const exec_ctx_t &ctx) const;
+template void ref_lrn_bwd_t<data_type::f32>::
+execute_backward<format_tag::any>(const exec_ctx_t &ctx) const;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.hpp
new file mode 100644
index 0000000000..f25cfb7fae
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_lrn.hpp
@@ -0,0 +1,136 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REF_LRN_HPP
+#define CPU_REF_LRN_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_lrn_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t data_type>
+struct ref_lrn_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_lrn_fwd_pd_t {
+ using cpu_lrn_fwd_pd_t::cpu_lrn_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_lrn_fwd_t);
+
+ status_t init() {
+ using namespace format_tag;
+
+ bool ok = true
+ && is_fwd()
+ && src_md()->data_type == data_type
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ dat_tag_ = memory_desc_matches_one_of_tag(
+ *src_md(), nChw16c, nChw8c, nchw, nhwc);
+
+ return status::success;
+ }
+
+ format_tag_t dat_tag_;
+ };
+
+ ref_lrn_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ using namespace format_tag;
+ switch (pd()->dat_tag_) {
+ case nChw16c: execute_forward<nChw16c>(ctx); break;
+ case nChw8c: execute_forward<nChw8c>(ctx); break;
+ case nchw: execute_forward<nchw>(ctx); break;
+ case nhwc: execute_forward<nhwc>(ctx); break;
+ default: execute_forward<any>(ctx);
+ }
+ return status::success;
+ }
+
+private:
+ template<format_tag_t tag>
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t data_type>
+struct ref_lrn_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_lrn_bwd_pd_t {
+ using cpu_lrn_bwd_pd_t::cpu_lrn_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_lrn_bwd_t);
+
+ status_t init() {
+ using namespace format_tag;
+ using namespace alg_kind;
+
+ bool ok = true
+ && !is_fwd()
+ && utils::one_of(desc()->alg_kind, lrn_across_channels
+ /*, lrn_within_channel */) // not supported yet
+ && utils::everyone_is(data_type,
+ src_md()->data_type,
+ diff_src_md()->data_type)
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ dat_tag_ = memory_desc_matches_one_of_tag(
+ *src_md(), nChw16c, nChw8c, nchw, nhwc);
+
+ return status::success;
+ }
+
+ format_tag_t dat_tag_;
+ };
+
+ ref_lrn_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ using namespace format_tag;
+ switch (pd()->dat_tag_) {
+ case nChw16c: execute_backward<nChw16c>(ctx); break;
+ case nChw8c: execute_backward<nChw8c>(ctx); break;
+ case nchw: execute_backward<nchw>(ctx); break;
+ case nhwc: execute_backward<nhwc>(ctx); break;
+ default: execute_backward<any>(ctx);
+ }
+ return status::success;
+ }
+
+private:
+ template<format_tag_t tag>
+ void execute_backward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.cpp
new file mode 100644
index 0000000000..65b934e123
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.cpp
@@ -0,0 +1,381 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <math.h>
+
+#include "c_types_map.hpp"
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+
+#include "ref_pooling.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <data_type_t data_type, data_type_t acc_type>
+void ref_pooling_fwd_t<data_type, acc_type>::execute_forward(
+ const exec_ctx_t &ctx) const {
+ using namespace alg_kind;
+ using namespace prop_kind;
+
+ auto alg = pd()->desc()->alg_kind;
+
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+ auto ws = CTX_OUT_MEM(unsigned char *, MKLDNN_ARG_WORKSPACE);
+
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+ const memory_desc_wrapper ws_d(pd()->workspace_md());
+ const data_type_t ws_dt = ws ? ws_d.data_type() : data_type::undef;
+
+ const int ID = pd()->ID();
+ const int IH = pd()->IH();
+ const int IW = pd()->IW();
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+ const int SD = pd()->KSD();
+ const int SH = pd()->KSH();
+ const int SW = pd()->KSW();
+ const int padF = pd()->padFront();
+ const int padT = pd()->padT();
+ const int padL = pd()->padL();
+
+ const bool is_3d = pd()->desc()->src_desc.ndims == 5;
+
+ auto apply_offset = [=](int index, int offset) {
+ return (index > offset) ? index - offset : 0;
+ };
+
+ auto set_ws = [=](int mb, int oc, int od, int oh, int ow, int value) {
+ if (ws) {
+ assert(ws_dt == data_type::u8 || ws_dt == data_type::s32);
+ size_t offset = is_3d
+ ? ws_d.off(mb, oc, od, oh, ow) : ws_d.off(mb, oc, oh, ow);;
+ if (ws_dt == data_type::u8) {
+ assert(0 <= value && value <= 255);
+ ws[offset] = value;
+ } else
+ reinterpret_cast<int *>(ws)[offset] = value;
+ }
+ };
+
+ auto ker_max = [=](data_t *d, int mb, int oc, int oh, int ow) {
+ for (int kh = 0; kh < KH; ++kh) {
+ for (int kw = 0; kw < KW; ++kw) {
+ const int ih = oh * SH - padT + kh;
+ const int iw = ow * SW - padL + kw;
+
+ if (ih < 0 || ih >= IH) continue;
+ if (iw < 0 || iw >= IW) continue;
+
+ auto s = src[src_d.off(mb, oc, ih, iw)];
+ if (s > d[0]) {
+ d[0] = s;
+ set_ws(mb, oc, 1, oh, ow, kh*KW + kw);
+ }
+ }
+ }
+ };
+
+ auto ker_avg = [=](data_t *d, int mb, int oc, int oh, int ow) {
+ auto ih_start = apply_offset(oh*SH, padT);
+ auto iw_start = apply_offset(ow*SW, padL);
+ auto ih_end = nstl::min(oh*SH - padT + KH, IH);
+ auto iw_end = nstl::min(ow*SW - padL + KW, IW);
+
+ auto num_summands = (alg == pooling_avg_include_padding) ? KW*KH
+ : (ih_end - ih_start)*(iw_end - iw_start);
+
+ acc_data_t dst = 0;
+ for (int ih = ih_start; ih < ih_end; ++ih) {
+ for (int iw = iw_start; iw < iw_end; ++iw) {
+ dst += src[src_d.off(mb, oc, ih, iw)];
+ }
+ }
+
+ d[0] = math::out_round<data_t>((float)dst / num_summands);
+ };
+
+ auto ker_max_3d = [=](data_t *d, int mb, int oc, int od, int oh, int ow) {
+ for (int kd = 0; kd < KD; ++kd) {
+ for (int kh = 0; kh < KH; ++kh) {
+ for (int kw = 0; kw < KW; ++kw) {
+ const int id = od * SD - padF + kd;
+ const int ih = oh * SH - padT + kh;
+ const int iw = ow * SW - padL + kw;
+
+ if (id < 0 || id >= ID) continue;
+ if (ih < 0 || ih >= IH) continue;
+ if (iw < 0 || iw >= IW) continue;
+
+ auto s = src[src_d.off(mb, oc, id, ih, iw)];
+ if (s > d[0]) {
+ d[0] = s;
+ set_ws(mb, oc, od, oh, ow, kd * KH * KW + kh*KW + kw);
+ }
+ }
+ }
+ }
+ };
+
+ auto ker_avg_3d = [=](data_t *d, int mb, int oc, int od, int oh, int ow) {
+ auto id_start = apply_offset(od*SD, padF);
+ auto ih_start = apply_offset(oh*SH, padT);
+ auto iw_start = apply_offset(ow*SW, padL);
+ auto id_end = nstl::min(od*SD - padF + KD, ID);
+ auto ih_end = nstl::min(oh*SH - padT + KH, IH);
+ auto iw_end = nstl::min(ow*SW - padL + KW, IW);
+
+ auto num_summands = (alg == pooling_avg_include_padding) ? KW*KH*KD
+ : (ih_end - ih_start)*(iw_end - iw_start)*(id_end - id_start);
+
+ acc_data_t dst = 0;
+ for (int id = id_start; id < id_end; ++id) {
+ for (int ih = ih_start; ih < ih_end; ++ih) {
+ for (int iw = iw_start; iw < iw_end; ++iw) {
+ dst += src[src_d.off(mb, oc, id, ih, iw)];
+ }
+ }
+ }
+
+ d[0] = math::out_round<data_t>((float)dst / num_summands);
+ };
+
+ const int MB = pd()->MB();
+ const int OC = pd()->C();
+ const int OD = pd()->OD();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+
+ if (alg == pooling_max) {
+ parallel_nd(MB, OC, OD, OH, OW,
+ [&](int mb, int oc, int od, int oh, int ow) {
+ data_t *d = is_3d
+ ? &dst[dst_d.off(mb, oc, od, oh, ow)]
+ : &dst[dst_d.off(mb, oc, oh, ow)];
+ d[0] = nstl::numeric_limits<data_t>::lowest();
+ set_ws(mb, oc, od, oh, ow, 0);
+ if (is_3d) ker_max_3d(d, mb, oc, od, oh, ow);
+ else ker_max(d, mb, oc, oh, ow);
+ });
+ } else {
+ parallel_nd(MB, OC, OD, OH, OW,
+ [&](int mb, int oc, int od, int oh, int ow) {
+ data_t *d = is_3d
+ ? &dst[dst_d.off(mb, oc, od, oh, ow)]
+ : &dst[dst_d.off(mb, oc, oh, ow)];
+ d[0] = 0;
+ if (is_3d) ker_avg_3d(d, mb, oc, od, oh, ow);
+ else ker_avg(d, mb, oc, oh, ow);
+ });
+ }
+}
+
+template <data_type_t data_type, data_type_t acc_type>
+void ref_pooling_bwd_t<data_type, acc_type>::execute_backward(
+ const exec_ctx_t &ctx) const {
+ using namespace alg_kind;
+
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto ws = CTX_IN_MEM(const unsigned char *, MKLDNN_ARG_WORKSPACE);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_dst_d(pd()->diff_dst_md());
+ const memory_desc_wrapper diff_src_d(pd()->diff_src_md());
+ const memory_desc_wrapper ws_d(pd()->workspace_md());
+
+ const int ID = pd()->ID();
+ const int IH = pd()->IH();
+ const int IW = pd()->IW();
+ const int KD = pd()->KD();
+ const int KH = pd()->KH();
+ const int KW = pd()->KW();
+ const int SD = pd()->KSD();
+ const int SH = pd()->KSH();
+ const int SW = pd()->KSW();
+ const int padF = pd()->padFront();
+ const int padT = pd()->padT();
+ const int padL = pd()->padL();
+
+ const bool is_3d = pd()->desc()->diff_src_desc.ndims == 5;
+
+ auto alg = pd()->desc()->alg_kind;
+
+ auto apply_offset = [=](int index, int offset) {
+ return (index > offset) ? index - offset : 0;
+ };
+
+ auto ker_zero = [=](int _mb, int _oc) {
+ for (int ih = 0; ih < IH; ++ih) {
+ for (int iw = 0; iw < IW; ++iw) {
+ diff_src[diff_src_d.off(_mb, _oc, ih, iw)] = data_type_t(0);
+ }
+ }
+ };
+
+ auto ker_max = [=](const data_t *d, int mb, int oc, int oh, int ow) {
+ const size_t ws_off = ws_d.off(mb, oc, oh, ow);
+ const int index = ws_d.data_type() == data_type::u8
+ ? (int)ws[ws_off] : ((int *)ws)[ws_off];
+ const int kw = index % KW;
+ const int kh = index / KW;
+ const int ih = oh * SH - padT + kh;
+ const int iw = ow * SW - padL + kw;
+
+ // If padding area could fit the kernel,
+ // then input displacement would be out of bounds.
+ // No need to back propagate there as padding is
+ // virtual in pooling_max case.
+ if (ih < 0 || ih >= IH)
+ return;
+ if (iw < 0 || iw >= IW)
+ return;
+
+ diff_src[diff_src_d.off(mb, oc, ih, iw)] += d[0];
+ };
+
+ auto ker_avg = [=](const data_t *d, int mb, int oc, int oh, int ow) {
+ auto ih_start = apply_offset(oh*SH, padT);
+ auto iw_start = apply_offset(ow*SW, padL);
+ auto ih_end = nstl::min(oh*SH - padT + KH, IH);
+ auto iw_end = nstl::min(ow*SW - padL + KW, IW);
+
+ auto num_summands = (alg == pooling_avg_include_padding) ? KW*KH
+ : (ih_end - ih_start)*(iw_end - iw_start);
+
+ for (int ih = ih_start; ih < ih_end; ++ih) {
+ for (int iw = iw_start; iw < iw_end; ++iw) {
+ diff_src[diff_src_d.off(mb, oc, ih, iw)] += d[0] / num_summands;
+ }
+ }
+ };
+
+ auto ker_zero_3d = [=](int _mb, int _oc) {
+ for (int id = 0; id < ID; ++id) {
+ for (int ih = 0; ih < IH; ++ih) {
+ for (int iw = 0; iw < IW; ++iw) {
+ diff_src[diff_src_d.off(_mb, _oc, id, ih, iw)] =
+ data_type_t(0);
+ }
+ }
+ }
+ };
+
+ auto ker_max_3d = [=](const data_t *d, int mb, int oc, int od, int oh,
+ int ow) {
+ const size_t ws_off = ws_d.off(mb, oc, od, oh, ow);
+ const int index = ws_d.data_type() == data_type::u8
+ ? (int)ws[ws_off] : ((int *)ws)[ws_off];
+ const int kw = index % KW;
+ const int kh = (index / KW) % KH;
+ const int kd = (index / KW) / KH;
+ const int id = od * SD - padF + kd;
+ const int ih = oh * SH - padT + kh;
+ const int iw = ow * SW - padL + kw;
+
+ // If padding area could fit the kernel,
+ // then input displacement would be out of bounds.
+ // No need to back propagate there as padding is
+ // virtual in pooling_max case.
+ if (id < 0 || id >= ID)
+ return;
+ if (ih < 0 || ih >= IH)
+ return;
+ if (iw < 0 || iw >= IW)
+ return;
+
+ diff_src[diff_src_d.off(mb, oc, id, ih, iw)] += d[0];
+ };
+
+ auto ker_avg_3d = [=](const data_t *d, int mb, int oc, int od, int oh,
+ int ow) {
+ auto id_start = apply_offset(od*SD, padF);
+ auto ih_start = apply_offset(oh*SH, padT);
+ auto iw_start = apply_offset(ow*SW, padL);
+ auto id_end = nstl::min(od*SD - padF + KD, ID);
+ auto ih_end = nstl::min(oh*SH - padT + KH, IH);
+ auto iw_end = nstl::min(ow*SW - padL + KW, IW);
+
+ auto num_summands = (alg == pooling_avg_include_padding) ? KW*KH*KD
+ : (ih_end - ih_start)*(iw_end - iw_start)*(id_end - id_start);
+
+ for (int id = id_start; id < id_end; ++id)
+ for (int ih = ih_start; ih < ih_end; ++ih)
+ for (int iw = iw_start; iw < iw_end; ++iw) {
+ diff_src[diff_src_d.off(mb, oc, id, ih, iw)] += d[0] / num_summands;
+ }
+ };
+
+ const int MB = pd()->MB();
+ const int OC = pd()->C();
+ const int OD = pd()->OD();
+ const int OH = pd()->OH();
+ const int OW = pd()->OW();
+
+ if (pd()->desc()->alg_kind == alg_kind::pooling_max) {
+ parallel_nd(MB, OC, [&](int mb, int oc) {
+ if (is_3d) ker_zero_3d(mb, oc);
+ else ker_zero(mb, oc);
+ for (int od = 0; od < OD; ++od) {
+ for (int oh = 0; oh < OH; ++oh) {
+ for (int ow = 0; ow < OW; ++ow) {
+ const data_t *d = is_3d
+ ? &diff_dst[diff_dst_d.off(mb, oc, od, oh, ow)]
+ : &diff_dst[diff_dst_d.off(mb, oc, oh, ow)];
+ if (is_3d) ker_max_3d(d, mb, oc, od, oh, ow);
+ else ker_max(d, mb, oc, oh, ow);
+ }
+ }
+ }
+ });
+ } else {
+ parallel_nd(MB, OC, [&](int mb, int oc) {
+ if (is_3d) ker_zero_3d(mb, oc);
+ else ker_zero(mb, oc);
+ for (int od = 0; od < OD; ++od) {
+ for (int oh = 0; oh < OH; ++oh) {
+ for (int ow = 0; ow < OW; ++ow) {
+ const data_t *d = is_3d
+ ? &diff_dst[diff_dst_d.off(mb, oc, od, oh, ow)]
+ : &diff_dst[diff_dst_d.off(mb, oc, oh, ow)];
+ if (is_3d) ker_avg_3d(d, mb, oc, od, oh, ow);
+ else ker_avg(d, mb, oc, oh, ow);
+ }
+ }
+ }
+ });
+ }
+}
+
+template struct ref_pooling_fwd_t<data_type::f32>;
+template struct ref_pooling_fwd_t<data_type::s32>;
+template struct ref_pooling_fwd_t<data_type::s8, data_type::s32>;
+template struct ref_pooling_fwd_t<data_type::u8, data_type::s32>;
+
+template struct ref_pooling_bwd_t<data_type::f32>;
+template struct ref_pooling_bwd_t<data_type::s32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.hpp
new file mode 100644
index 0000000000..e43ceaa82b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_pooling.hpp
@@ -0,0 +1,119 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REF_POOLING_HPP
+#define CPU_REF_POOLING_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_pooling_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t data_type, impl::data_type_t acc_type = data_type>
+struct ref_pooling_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_pooling_fwd_pd_t {
+ using cpu_pooling_fwd_pd_t::cpu_pooling_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_pooling_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && set_default_params() == status::success
+ && is_fwd()
+ && utils::everyone_is(data_type, src_md()->data_type,
+ dst_md()->data_type)
+ && desc()->accum_data_type == acc_type
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ bool is_training = desc_.prop_kind == prop_kind::forward_training;
+ if (desc()->alg_kind == alg_kind::pooling_max && is_training)
+ init_default_ws();
+
+ return status::success;
+ }
+ };
+
+ ref_pooling_fwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ typedef typename prec_traits<data_type>::type data_t;
+ typedef typename prec_traits<acc_type>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_forward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <impl::data_type_t data_type, impl::data_type_t acc_type = data_type>
+struct ref_pooling_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_pooling_bwd_pd_t {
+ using cpu_pooling_bwd_pd_t::cpu_pooling_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_pooling_bwd_t);
+
+ status_t init() {
+ bool ok = true
+ && set_default_params() == status::success
+ && !is_fwd()
+ && utils::everyone_is(data_type, diff_dst_md()->data_type,
+ diff_src_md()->data_type)
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ if (desc()->alg_kind == alg_kind::pooling_max) {
+ init_default_ws();
+ if (!compare_ws(hint_fwd_pd_))
+ return status::unimplemented;
+ }
+
+ return status::success;
+ }
+ };
+
+ ref_pooling_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {}
+ typedef typename prec_traits<data_type>::type data_t;
+ typedef typename prec_traits<acc_type>::type acc_data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_backward(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.cpp
new file mode 100644
index 0000000000..af27743110
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.cpp
@@ -0,0 +1,153 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <math.h>
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+
+#include "ref_shuffle.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace format_tag;
+
+template <int data_type_size>
+template <mkldnn_format_tag_t tag>
+void ref_shuffle_t<data_type_size>::execute_(const exec_ctx_t &ctx) const {
+ using namespace prop_kind;
+ using namespace utils;
+
+ const memory_desc_wrapper data_d(pd()->data_md());
+
+ auto i_arg = pd()->is_fwd() ? MKLDNN_ARG_SRC : MKLDNN_ARG_DIFF_DST;
+ auto o_arg = pd()->is_fwd() ? MKLDNN_ARG_DST : MKLDNN_ARG_DIFF_SRC;
+ auto input = CTX_IN_MEM(const data_t *, i_arg);
+ auto output = CTX_OUT_MEM(data_t *, o_arg);
+
+ const int axis = pd()->axis();
+ const int axis_size = pd()->axis_size();
+
+ const int MB = pd()->MB();
+ const int C = pd()->C();
+ int H = 1, W = 1, D = 1, HW = 1, SP = 1;
+ const bool has_spatial = utils::one_of(data_d.ndims(), 3, 4 ,5);
+ if (has_spatial)
+ {
+ D = pd()->D();
+ H = pd()->H();
+ W = pd()->W();
+ HW = H * W;
+ SP = D * HW;
+ }
+ const size_t stride_mb = data_d.blocking_desc().strides[0];
+ constexpr int blksize = one_of(tag, nChw16c, nCdhw16c) ? 16 : 8;
+
+ if (axis == 1 && one_of(tag, nChw16c, nChw8c, nCdhw16c, nCdhw16c)) {
+#if MKLDNN_THR == MKLDNN_THR_OMP
+# pragma omp parallel for collapse(3) schedule(static)
+ for (int mb = 0; mb < MB; ++mb)
+ for (int cb = 0; cb < C; cb += blksize)
+ for (int sp = 0; sp < SP; ++sp) {
+ const size_t off = mb * stride_mb + sp * blksize;
+ const size_t output_off = off + cb * SP;
+ PRAGMA_OMP_SIMD()
+ for (int cc = 0; cc < nstl::min(blksize, C - cb); ++cc)
+ {
+ int input_c = rev_transposed_[cb + cc];
+ const size_t input_off = off + input_c / blksize * SP * blksize
+ + input_c % blksize;
+ output[output_off + cc] = input[input_off];
+ }
+ }
+#else
+ parallel_nd(MB, utils::div_up(C, blksize), SP, [&](int mb, int c,
+ int sp) {
+ const size_t off = mb * stride_mb + sp * blksize;
+ const int cb = c * blksize;
+ const size_t output_off = off + cb * SP;
+ for (int cc = 0; cc < nstl::min(blksize, C - cb); ++cc)
+ {
+ int input_c = rev_transposed_[cb + cc];
+ const size_t input_off = off + input_c / blksize * SP * blksize
+ + input_c % blksize;
+ output[output_off + cc] = input[input_off];
+ }
+ });
+#endif
+ } else if (axis == 1 && one_of(tag, nhwc, ndhwc)) {
+ parallel_nd(MB, SP, [&](int mb, int sp) {
+ const size_t off = mb * stride_mb + sp * C;
+ PRAGMA_OMP_SIMD()
+ for (int c = 0; c < C; ++c)
+ output[off + c] = input[off + rev_transposed_[c]];
+ });
+ } else if (axis == 1 && one_of(tag, nchw, ncdhw)) {
+ parallel_nd(MB, C, [&](int mb, int c) {
+ const size_t output_off = mb * stride_mb + c * SP;
+ const size_t input_off = mb * stride_mb + rev_transposed_[c] * SP;
+ PRAGMA_OMP_SIMD()
+ for (int sp = 0; sp < SP; ++sp) {
+ output[output_off + sp] = input[input_off + sp];
+ }
+ });
+ } else {
+ auto dims = pd()->desc()->data_desc.dims;
+ auto ndims = pd()->desc()->data_desc.ndims;
+ const size_t outer_size = utils::array_product(dims, axis);
+ const size_t inner_size = utils::array_product(dims + axis + 1,
+ ndims - axis - 1);
+ const size_t dim = axis_size * inner_size;
+
+ parallel_nd(outer_size, axis_size, inner_size, [&](size_t ou, int a,
+ size_t in)
+ {
+ const size_t off = ou * dim + in;
+ auto &o = output[data_d.off_l(off + a * inner_size)];
+ o = input[data_d.off_l(off + rev_transposed_[a] * inner_size)];
+ });
+ }
+}
+
+template void ref_shuffle_t<4>::execute_<nCdhw16c>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<4>::execute_<nChw16c>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<4>::execute_<nCdhw8c>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<4>::execute_<nChw8c>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<4>::execute_<ncdhw>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<4>::execute_<nchw>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<4>::execute_<ndhwc>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<4>::execute_<nhwc>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<4>::execute_<any>(const exec_ctx_t &ctx) const;
+
+template void ref_shuffle_t<1>::execute_<nCdhw16c>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<1>::execute_<nChw16c>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<1>::execute_<nCdhw8c>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<1>::execute_<nChw8c>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<1>::execute_<ncdhw>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<1>::execute_<nchw>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<1>::execute_<ndhwc>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<1>::execute_<nhwc>(const exec_ctx_t &ctx) const;
+template void ref_shuffle_t<1>::execute_<any>(const exec_ctx_t &ctx) const;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.hpp
new file mode 100644
index 0000000000..5e09a1a69b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_shuffle.hpp
@@ -0,0 +1,111 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REF_SHUFFLE_HPP
+#define CPU_REF_SHUFFLE_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_shuffle_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template<int data_type_size>
+struct ref_shuffle_t : public cpu_primitive_t {
+ using shuffle_class = ref_shuffle_t<data_type_size>;
+
+ struct pd_t: public cpu_shuffle_pd_t {
+ using cpu_shuffle_pd_t::cpu_shuffle_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", shuffle_class);
+
+ status_t init() {
+ using namespace format_tag;
+
+ bool ok = true
+ && data_type_size
+ == types::data_type_size(data_md()->data_type);
+ if (!ok) return status::unimplemented;
+
+ if (ndims() == 5) {
+ dat_tag_ = memory_desc_matches_one_of_tag(
+ *data_md(), nCdhw16c, nCdhw8c, ncdhw, ndhwc);
+ } else if (ndims() == 4) {
+ dat_tag_ = memory_desc_matches_one_of_tag(
+ *data_md(), nChw16c, nChw8c, nchw, nhwc);
+ } else
+ dat_tag_ = any;
+
+ return status::success;
+ }
+
+ format_tag_t dat_tag_;
+ };
+
+ ref_shuffle_t(const pd_t *apd): cpu_primitive_t(apd) {
+ const int axis_size = pd()->axis_size();
+ const int group_size = pd()->group_size();
+ const int transpose_row = pd()->is_fwd() ? group_size
+ : axis_size / group_size;
+ const int transpose_col = pd()->is_fwd() ? axis_size / group_size
+ : group_size;
+ rev_transposed_ = (int *)malloc(axis_size * sizeof(int), 64);
+ parallel_nd(transpose_col, transpose_row, [&](int i, int j) {
+ rev_transposed_[j * transpose_col + i] = i * transpose_row + j;
+ });
+ }
+
+ ~ref_shuffle_t() { free(rev_transposed_); }
+
+ typedef typename typesize_traits<data_type_size>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ using namespace format_tag;
+ switch (pd()->dat_tag_) {
+ case nCdhw16c: execute_<nCdhw16c>(ctx); break;
+ case nChw16c: execute_<nChw16c>(ctx); break;
+ case nCdhw8c: execute_<nCdhw8c>(ctx); break;
+ case nChw8c: execute_<nChw8c>(ctx); break;
+ case ncdhw: execute_<ncdhw>(ctx); break;
+ case nchw: execute_<nchw>(ctx); break;
+ case ndhwc: execute_<ndhwc>(ctx); break;
+ case nhwc: execute_<nhwc>(ctx); break;
+ default: execute_<any>(ctx); break;
+ }
+ return status::success;
+ }
+
+private:
+ template<format_tag_t tag>
+ void execute_(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ int *rev_transposed_;
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.cpp
new file mode 100644
index 0000000000..36d5237f56
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.cpp
@@ -0,0 +1,264 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+
+#include "c_types_map.hpp"
+#include "mkldnn_thread.hpp"
+#include "type_helpers.hpp"
+
+#include "ref_softmax.hpp"
+#include "gemm/os_blas.hpp"
+
+#ifdef USE_MKL
+#include "mkl_vml_functions.h"
+#endif
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t data_type>
+void ref_softmax_fwd_t<data_type>::execute_forward_dense(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ parallel_nd(outer_size_, [&](int ou) {
+ const data_t *src_data = src + ou * channels_;
+ data_t *dst_data = dst + ou * channels_;
+ data_t scalar = 0;
+
+ _max(channels_, src_data, &scalar);
+ _sub(channels_, scalar, src_data, dst_data);
+ _exp(channels_, dst_data, dst_data);
+ _sum(channels_, dst_data, &scalar);
+ _scal(channels_, data_t(1)/scalar, dst_data);
+ });
+}
+
+template <impl::data_type_t data_type>
+void ref_softmax_fwd_t<data_type>::execute_forward_generic(
+ const exec_ctx_t &ctx) const {
+ auto src = CTX_IN_MEM(const data_t *, MKLDNN_ARG_SRC);
+ auto dst = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ data_t space_max_val = 0, space_denom_val = 0;
+ data_t *space_max = &space_max_val, *space_denom = &space_denom_val;
+ if (inner_size_ > 1) {
+ using namespace memory_tracking::names;
+ space_max = scratchpad(ctx).template get<data_t>(key_softmax_reduction);
+ space_denom = space_max + inner_size_;
+ }
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+ const size_t dim = channels_ * inner_size_;
+
+ for (int ou = 0; ou < outer_size_; ou++) {
+ utils::array_set(space_max, -FLT_MAX, inner_size_);
+ utils::array_set(space_denom, 0, inner_size_);
+
+ for (int c = 0; c < channels_; c++) {
+ for(int in = 0; in < inner_size_; in++) {
+ size_t off = data_d.off_l(ou * dim + c * inner_size_ + in);
+ space_max[in] = nstl::max(space_max[in], src[off]);
+ }
+ }
+
+ for (int c = 0; c < channels_; c++) {
+ for(int in = 0; in < inner_size_; in++) {
+ size_t off = data_d.off_l(ou * dim + c * inner_size_ + in);
+ space_denom[in] += dst[off] = exp(src[off] - space_max[in]);
+ }
+ }
+
+ for (int c = 0; c < channels_; c++) {
+ for (int in = 0; in < inner_size_; in++) {
+ size_t off = data_d.off_l(ou * dim + c * inner_size_ + in);
+ dst[off] /= space_denom[in];
+ }
+ }
+ }
+}
+
+template <impl::data_type_t data_type>
+void ref_softmax_fwd_t<data_type>::_max(int n, const data_t *x,
+ data_t *max_data) const {
+// Intel(R) C++ Compiler generates the maxps + shuffle pattern
+// for the max search which works faster
+#if !defined(__INTEL_COMPILER)
+ // The code below makes a compiler to generate maxps instruction
+ // rather than maxss, which is generated for the 'else' code path
+ auto max_wrapper = [](data_t a, data_t b) { return nstl::max(a, b); };
+ auto min_wrapper = [](int a, int b) { return nstl::min(a, b); };
+
+ constexpr int unroll_factor = 32;
+ data_t max_values[unroll_factor];
+
+ if (n < unroll_factor) {
+ data_t max_val = x[0];
+ for (int i = 1; i < n; i++) {
+ max_val = max_wrapper(max_val, x[i]);
+ }
+ max_data[0] = max_val;
+ return;
+ }
+ for (int i = 0; i < unroll_factor; i++) {
+ max_values[i] = x[i];
+ }
+ for (int i = unroll_factor; i < n; i += unroll_factor) {
+ int offset = min_wrapper(i, n - unroll_factor);
+ for (int j = 0; j < unroll_factor; j++) {
+ max_values[j] = max_wrapper(max_values[j], x[offset + j]);
+ }
+ }
+ data_t max_val = max_values[0];
+ for (int i = 1; i < unroll_factor; i++) {
+ max_val = max_wrapper(max_val, max_values[i]);
+ }
+ max_data[0] = max_val;
+#else
+ max_data[0] = x[0];
+ for (int c = 1; c < n; ++c)
+ max_data[0] = nstl::max(max_data[0], x[c]);
+#endif
+}
+
+template <impl::data_type_t data_type>
+void ref_softmax_fwd_t<data_type>::_sub(int n, data_t alpha, const data_t *x,
+ data_t *y) const {
+ constexpr int unroll_factor = 32;
+ int tail = n % unroll_factor;
+ for (int i = 0; i < n - tail; i += unroll_factor) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < unroll_factor; j++) {
+ y[i + j] = x[i + j] - alpha;
+ }
+ }
+ PRAGMA_OMP_SIMD()
+ for (int i = n - tail; i < n; i++) {
+ y[i] = x[i] - alpha;
+ }
+}
+
+template <impl::data_type_t data_type>
+void ref_softmax_fwd_t<data_type>::_exp(int n, const data_t *a,
+ data_t *r) const {
+#ifdef USE_MKL
+ if (data_type == data_type::f32) {
+ vsExp(n, a, r);
+ return;
+ }
+#endif
+ parallel_nd(n, [&](int c) { r[c] = expf(a[c]); });
+}
+
+template <impl::data_type_t data_type>
+void ref_softmax_fwd_t<data_type>::_sum(int n, const data_t *x,
+ data_t *sum_data) const {
+#ifdef USE_CBLAS
+ // Here we are summing x's eg. e^z , which are positives
+ // so we can use BLAS ASUM
+ if (data_type == data_type::f32) {
+ sum_data[0] = cblas_sasum(n, x, 1);
+ return;
+ }
+#endif
+ data_t tsum = static_cast<data_t>(0);
+ PRAGMA_OMP_SIMD(reduction(+ : tsum))
+ for (int c = 0; c < n; ++c)
+ tsum += x[c];
+ sum_data[0] = tsum;
+}
+
+template <impl::data_type_t data_type>
+void ref_softmax_fwd_t<data_type>::_scal(int n, data_t alpha, data_t *x) const {
+#ifdef USE_CBLAS
+ if (data_type == data_type::f32) {
+ cblas_sscal(n, alpha, x, 1);
+ return;
+ }
+#endif
+ parallel_nd(n, [&](int c) { x[c] *= alpha; });
+}
+
+template struct ref_softmax_fwd_t<data_type::f32>;
+
+
+// NC/NCHW softmax for along final axe (1 for NC, 3 for NCHW)
+template <impl::data_type_t data_type>
+void ref_softmax_bwd_t<data_type>::execute_backward_dense(
+ const exec_ctx_t &ctx) const {
+ auto dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DST);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ parallel_nd(outer_size_, [&](int ou) {
+ data_t sbr = 0;
+ size_t off = channels_*ou;
+ for (int c = 0; c < channels_; c++) {
+ size_t loff = off + c;
+ data_t ldata = dst[loff];
+ sbr += diff_dst[loff]*ldata;
+ diff_src[loff] = ldata;
+ }
+
+ for(int c=0; c < channels_ ; ++c) {
+ size_t loff = off + c;
+ diff_src[loff] *= (diff_dst[loff] - sbr);
+ }
+ });
+}
+
+template <impl::data_type_t data_type>
+void ref_softmax_bwd_t<data_type>::execute_backward_generic(
+ const exec_ctx_t &ctx) const {
+ auto dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DST);
+ auto diff_dst = CTX_IN_MEM(const data_t *, MKLDNN_ARG_DIFF_DST);
+ auto diff_src = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DIFF_SRC);
+
+ const memory_desc_wrapper diff_d(pd()->diff_src_md());
+ const memory_desc_wrapper data_d(pd()->dst_md());
+
+ const size_t dim = channels_ * inner_size_;
+
+ parallel_nd(outer_size_, [&](int ou) {
+ for (int in = 0; in < inner_size_; in++) {
+ data_t sbr = 0;
+ for (int c = 0; c < channels_; c++) {
+ size_t off_diff = diff_d.off_l(ou * dim + c * inner_size_ + in);
+ size_t off_data = diff_d.off_l(ou * dim + c * inner_size_ + in);
+ sbr += diff_dst[off_diff] * dst[off_data];
+ }
+
+ for(int c=0; c < channels_ ; ++c) {
+ size_t off_diff = diff_d.off_l(ou * dim + c * inner_size_ + in);
+ size_t off_data = data_d.off_l(ou * dim + c * inner_size_ + in);
+ diff_src[off_diff] = dst[off_data] * (diff_dst[off_diff] - sbr);
+ }
+ }
+ });
+}
+
+template struct ref_softmax_bwd_t<data_type::f32>;
+
+}
+}
+}
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.hpp
new file mode 100644
index 0000000000..5cb74d8007
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_softmax.hpp
@@ -0,0 +1,186 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REF_SOFTMAX_HPP
+#define CPU_REF_SOFTMAX_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "cpu_softmax_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <impl::data_type_t data_type>
+struct ref_softmax_fwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_softmax_fwd_pd_t {
+ using cpu_softmax_fwd_pd_t::cpu_softmax_fwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_softmax_fwd_t);
+
+ status_t init() {
+ bool ok = true
+ && is_fwd()
+ && src_md()->data_type == data_type
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ init_scratchpad();
+
+ return status::success;
+ }
+
+ private:
+ void init_scratchpad() {
+ const int inner_size = utils::array_product(
+ desc()->data_desc.dims + desc()->softmax_axis + 1,
+ desc()->data_desc.ndims - desc()->softmax_axis - 1);
+
+ if (inner_size > 1) {
+ auto scratchpad = scratchpad_registry().registrar();
+ scratchpad.book(memory_tracking::names::key_softmax_reduction,
+ sizeof(data_t) * 2 * inner_size);
+ }
+ }
+ };
+
+ ref_softmax_fwd_t(const pd_t *apd): cpu_primitive_t(apd)
+ {
+ auto ndims = pd()->desc()->data_desc.ndims;
+ auto dims = pd()->desc()->data_desc.dims;
+ auto axis = pd()->desc()->softmax_axis;
+
+ outer_size_ = utils::array_product(dims, axis);
+ channels_ = dims[axis];
+ inner_size_ = utils::array_product(dims + axis + 1, ndims - axis - 1);
+
+ const memory_desc_wrapper data_d(pd()->src_md());
+
+ bool no_axis_blocking = true;
+ for (int iblk = 0; iblk < data_d.blocking_desc().inner_nblks; ++iblk)
+ if (data_d.blocking_desc().inner_idxs[iblk] == axis)
+ no_axis_blocking = false;
+
+ use_dense_ = inner_size_ == 1 && data_d.is_dense()
+ && no_axis_blocking
+ && data_d.blocking_desc().strides[axis] == 1;
+ }
+
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ if (use_dense_)
+ execute_forward_dense(ctx);
+ else
+ execute_forward_generic(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_forward_dense(const exec_ctx_t &ctx) const;
+ void execute_forward_generic(const exec_ctx_t &ctx) const;
+
+ void _max(int n, const data_t *x, data_t *max_data) const;
+ void _sub(int n, data_t alpha, const data_t *x, data_t *y) const;
+ void _exp(int n, const data_t *a, data_t *r) const;
+ void _sum(int n, const data_t *x, data_t *sum_data) const;
+ void _scal(int n, data_t alpha, data_t *x) const;
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ bool use_dense_;
+ int outer_size_, channels_, inner_size_;
+};
+
+template <impl::data_type_t data_type>
+struct ref_softmax_bwd_t: public cpu_primitive_t {
+ struct pd_t: public cpu_softmax_bwd_pd_t {
+ using cpu_softmax_bwd_pd_t::cpu_softmax_bwd_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", ref_softmax_bwd_t);
+
+ status_t init() {
+ bool ok = true
+ && !is_fwd()
+ && utils::everyone_is(data_type,
+ dst_md()->data_type,
+ diff_src_md()->data_type)
+ && attr()->has_default_values();
+ if (!ok) return status::unimplemented;
+
+ return status::success;
+ }
+ };
+
+ ref_softmax_bwd_t(const pd_t *apd): cpu_primitive_t(apd) {
+ auto dims = pd()->desc()->diff_desc.dims;
+ auto axis = pd()->desc()->softmax_axis;
+ auto ndims = pd()->desc()->diff_desc.ndims;
+
+ outer_size_ = utils::array_product(dims, axis);
+ channels_ = dims[axis];
+ inner_size_ = utils::array_product(dims + axis + 1, ndims - axis - 1);
+
+ const memory_desc_wrapper data_d(pd()->dst_md());
+ const memory_desc_wrapper diff_d(pd()->diff_dst_md());
+
+ bool no_axis_blocking = true;
+ for (int iblk = 0; iblk < diff_d.blocking_desc().inner_nblks; ++iblk)
+ if (diff_d.blocking_desc().inner_idxs[iblk] == axis)
+ no_axis_blocking = false;
+
+ use_dense_ = true
+ && inner_size_ == 1
+ && diff_d == data_d
+ && diff_d.is_dense()
+ && no_axis_blocking
+ && diff_d.blocking_desc().strides[axis] == 1;
+ }
+
+ typedef typename prec_traits<data_type>::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ if (use_dense_)
+ execute_backward_dense(ctx);
+ else
+ execute_backward_generic(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_backward_dense(const exec_ctx_t &ctx) const;
+ void execute_backward_generic(const exec_ctx_t &ctx) const;
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ bool use_dense_;
+ int outer_size_, channels_, inner_size_;
+};
+
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/ref_sum.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/ref_sum.hpp
new file mode 100644
index 0000000000..3b2a75d99b
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/ref_sum.hpp
@@ -0,0 +1,101 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef REF_SUM_HPP
+#define REF_SUM_HPP
+
+#include "reorder_pd.hpp"
+
+#include "cpu_sum_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct ref_sum_t: public cpu_primitive_t {
+ struct pd_t: public cpu_sum_pd_t {
+ using cpu_sum_pd_t::cpu_sum_pd_t;
+
+ pd_t(const pd_t &rhs): cpu_sum_pd_t(rhs) {
+ for (size_t i = 0; i < rhs.reorder_pds_.size(); ++i)
+ reorder_pds_.push_back(
+ (const reorder_pd_t *)rhs.reorder_pds_[i]->clone());
+ }
+
+ ~pd_t() { for (auto &rpd: reorder_pds_) delete rpd; }
+
+ DECLARE_SUM_PD_T("ref:any", ref_sum_t);
+
+ status_t init() {
+ bool ok = cpu_sum_pd_t::init() == status::success;
+ if (!ok) return status::unimplemented;
+
+ for (int i = 0; i < n_; ++i) {
+ auto r_impls = engine_->get_reorder_implementation_list();
+ for (auto r = r_impls; *r; ++r) {
+ primitive_attr_t attr;
+ attr.output_scales_.set(scales_[i]);
+ if (i != 0) attr.post_ops_.append_sum(1.0);
+
+ reorder_pd_t *r_pd;
+ if ((*r)(&r_pd, engine_, &attr, engine_, src_md(i),
+ engine_, dst_md()) == status::success) {
+ r_pd->init_info();
+ reorder_pds_.push_back(r_pd);
+ break;
+ }
+ }
+ }
+
+ ok = reorder_pds_.size() == (size_t)n_;
+ return ok ? status::success : status::unimplemented;
+ }
+
+ nstl::vector<const reorder_pd_t *> reorder_pds_;
+ };
+
+ ref_sum_t(const pd_t *apd): cpu_primitive_t(apd) {
+ const int n = pd()->n_inputs();
+ reorders_.resize(n);
+ for (int i = 0; i < n; ++i)
+ pd()->reorder_pds_[i]->create_primitive(&reorders_[i]);
+ }
+
+ ~ref_sum_t() { for (auto &r: reorders_) delete r; }
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ const auto n = pd()->n_inputs();
+ for (int i = 0; i < n; ++i) {
+ exec_args_t r_args;
+ r_args[MKLDNN_ARG_SRC] = ctx.args().at(MKLDNN_ARG_MULTIPLE_SRC + i);
+ r_args[MKLDNN_ARG_DST] = ctx.args().at(MKLDNN_ARG_DST);
+ exec_ctx_t r_ctx(ctx.stream(), std::move(r_args));
+ reorders_[i]->execute(r_ctx);
+ }
+ return status::success;
+ }
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ nstl::vector<primitive_t *> reorders_;
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_common.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_common.cpp
new file mode 100644
index 0000000000..537084db91
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_common.cpp
@@ -0,0 +1,90 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*
+ * Common for RNN and LSTM cell execution
+ */
+#include "ref_rnn.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+using namespace rnn_utils;
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+rnn_cell_execution_sig(
+ (_ref_rnn_common_t<aprop, src_type, weights_type>::cell_execution)) {
+ if (!rnn.merge_gemm_layer) {
+ (this->*gemm_layer_func)('N', 'N', rnn.n_gates * rnn.dic, rnn.mb,
+ rnn.slc, 1.0, w_layer_[0], rnn.weights_layer_ld,
+ states_t_lm1_, rnn.states_ws_ld, 0.0, ws_gates_,
+ rnn.gates_ws_ld);
+ }
+ (this->*gemm_iter_func)('N', 'N', rnn.n_gates * rnn.dic, rnn.mb, rnn.sic,
+ 1.0, w_iter_[0], rnn.weights_iter_ld, states_tm1_l_,
+ rnn.states_ws_ld, 1.0, ws_gates_, rnn.gates_ws_ld);
+
+ if (rnn_postgemm_ != nullptr)
+ rnn_postgemm_->execute<src_data_t, acc_data_t>(rnn, ws_gates_, states_t_l_, c_states_t_l_,
+ states_tm1_l_, c_states_tm1_l_, diff_states_t_l_,
+ diff_states_t_lp1_, diff_states_tp1_l_, bias_[0], ws_grid_,
+ ws_cell_);
+ else
+ (this->*elemwise_func)(rnn, ws_gates_, states_t_l_, c_states_t_l_,
+ states_tm1_l_, c_states_tm1_l_, diff_states_t_l_,
+ diff_states_t_lp1_, diff_states_tp1_l_, bias_[0], ws_grid_,
+ ws_cell_);
+}
+template rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution);
+template rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution);
+
+template <>
+rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution) {
+ ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_);
+ (this->*elemwise_func)(rnn, ws_gates_, states_t_l_, c_states_t_l_,
+ states_tm1_l_, c_states_tm1_l_, diff_states_t_l_,
+ diff_states_t_lp1_, diff_states_tp1_l_, bias_[0], ws_grid_,
+ ws_cell_);
+
+ /// bwd by data on the cell
+ (this->*gemm_iter_func)('N', 'N', rnn.sic, rnn.mb, rnn.n_gates * rnn.dic,
+ 1.0, w_iter_[0], rnn.weights_iter_ld, ws_gates_, rnn.gates_ws_ld,
+ 0.0, diff_states_t_l_, rnn.states_ws_ld);
+
+ if (!rnn.merge_gemm_layer) {
+ (this->*gemm_layer_func)('N', 'N', rnn.slc, rnn.mb,
+ rnn.n_gates * rnn.dic, 1.0, w_layer_[0],
+ rnn.weights_layer_ld, ws_gates_, rnn.gates_ws_ld, 0.0,
+ &diff_states_t_l(rnn.n_states, 0, 0), rnn.states_ws_ld);
+
+ /// bwd by weights on the cell
+ gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.slc, rnn.mb, 1.0, ws_gates_,
+ rnn.gates_ws_ld, states_t_lm1_, rnn.states_ws_ld, 1.0,
+ diff_w_layer_, rnn.diff_weights_layer_ld);
+ }
+
+ if (!rnn.merge_gemm_iter)
+ gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.sic, rnn.mb, 1.0, ws_gates_,
+ rnn.gates_ws_ld, states_tm1_l_, rnn.states_ws_ld, 1.0,
+ diff_w_iter_, rnn.diff_weights_iter_ld);
+
+ /// bwd by bias we just accumulate diffs from the gates
+ gates_reduction(rnn, ws_gates_, diff_bias_);
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru.cpp
new file mode 100644
index 0000000000..e1a61d4c62
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru.cpp
@@ -0,0 +1,180 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*
+ * Cell execution GRU
+ */
+
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "ref_rnn.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::math;
+using namespace rnn_utils;
+
+#define AOC array_offset_calculator
+template <>
+rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution_gru) {
+ ws_gates_aoc_t ws_gates(rnn, ws_gates_);
+ bias_aoc_t bias(rnn, bias_[0]);
+ ws_states_aoc_t states_t_l(rnn, states_t_l_);
+ ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_);
+
+ // 1. gemm Wx[0-2],x
+ if (!rnn.merge_gemm_layer) {
+ (this->*gemm_layer_func)('N', 'N', rnn.n_gates * rnn.dic, rnn.mb,
+ rnn.slc, 1.0, w_layer_[0], rnn.weights_layer_ld,
+ states_t_lm1_, rnn.states_ws_ld, 0.0, ws_gates_,
+ rnn.gates_ws_ld);
+ }
+
+ // 2. gemm Wh[0-1],h
+ (this->*gemm_iter_func)('N', 'N', (rnn.n_gates - 1) * rnn.dic, rnn.mb,
+ rnn.sic, 1.0, w_iter_[0], rnn.weights_iter_ld, states_tm1_l_,
+ rnn.states_ws_ld, 1.0, ws_gates_, rnn.gates_ws_ld);
+
+ // 3. activation zt and rt + elemwise multiplication rt,ht-1
+ parallel_nd(rnn.mb, [&](int i) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < rnn.dic; j++) {
+ ws_gates(i, 0, j) = logistic_fwd(ws_gates(i, 0, j) + bias(0, j));
+ ws_gates(i, 1, j) = logistic_fwd(ws_gates(i, 1, j) + bias(1, j));
+ states_t_l(i, j) = states_tm1_l(i, j) * ws_gates(i, 1, j);
+ }
+ });
+
+ // 4. gemm Wh[2],h~t
+ (this->*gemm_iter_func)('N', 'N', rnn.dic, rnn.mb, rnn.sic, 1.0, w_iter_[1],
+ rnn.weights_iter_ld, states_t_l_, rnn.states_ws_ld, 1.0,
+ &(ws_gates(0, 2, 0)), rnn.gates_ws_ld);
+
+ // 5. activation h~t + calculate ht
+ parallel_nd(rnn.mb, [&](int i) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < rnn.dic; j++) {
+ ws_gates(i, 2, j) = tanh_fwd(ws_gates(i, 2, j) + bias(2, j));
+ states_t_l(i, j) = states_tm1_l(i, j) * ws_gates(i, 0, j)
+ + (1.0f - ws_gates(i, 0, j)) * ws_gates(i, 2, j);
+ }
+ });
+}
+
+template <>
+rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution_gru) {
+ assert(!"GRU int8 is not supported");
+}
+
+template <>
+rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution_gru) {
+ ws_gates_aoc_t ws_gates(rnn, ws_gates_);
+ ws_states_aoc_t states_t_l(rnn, states_t_l_);
+ ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_);
+ ws_diff_w_iter_aoc_t diff_w_iter(rnn, diff_w_iter_);
+ ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_);
+ ws_diff_states_aoc_t diff_states_tp1_l(rnn, diff_states_tp1_l_);
+ ws_diff_states_aoc_t diff_states_t_lp1(rnn, diff_states_t_lp1_);
+
+ // use state memory for intermediate computations
+ // TODO: use cell ws for that
+ float *dhG1_ = &(diff_states_t_l(rnn.n_states, 0, 0));
+ float *hG1_ = dhG1_;
+ AOC<float, 2> dhG1(dhG1_, rnn.states_nld, rnn.states_ws_ld);
+ AOC<float, 2> hG1(hG1_, rnn.states_nld, rnn.states_ws_ld);
+
+ // 1. calculate dG2, dG1, and part of dht-1
+ // dG2^ = dh * (1 - G0) * (1 - G2^2)
+ // dG0^ = dh * (ht-1 - G2) * u * (1 - G0)
+ // dht-1 (part) = dh * G0
+ parallel_nd(rnn.mb, [&](int i) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < rnn.dic; j++) {
+ float h = states_tm1_l(i, j);
+ float dHt = diff_states_tp1_l(0, i, j)
+ + diff_states_t_lp1(rnn.n_states, i, j);
+ float dG2 = (1.0f - ws_gates(i, 0, j)) * dHt
+ * one_m_square(ws_gates(i, 2, j));
+ float dG0 = (h - ws_gates(i, 2, j)) * dHt
+ * x_m_square(ws_gates(i, 0, j));
+
+ diff_states_t_l(0, i, j) = dHt * ws_gates(i, 0, j);
+ ws_gates(i, 0, j) = dG0;
+ ws_gates(i, 2, j) = dG2;
+ }
+ });
+
+ // 2. calculate intermediate d(hG1)
+ // d(hG1) = dG2 * W2h^t
+ (this->*gemm_iter_func)('N', 'N', rnn.sic, rnn.mb, rnn.dic, 1.0, w_iter_[1],
+ rnn.weights_iter_ld, &(ws_gates(0, 2, 0)), rnn.gates_ws_ld, 0.0,
+ dhG1_, rnn.states_ws_ld);
+
+ // 3. calculate dG1^ and part of dht-1
+ // dG1^ = d(hG1) * h * G1 * (1 - G1)
+ // dht-1 (part) += d(hG1) * G1
+ // h * G1 (required for dWh)
+ parallel_nd(rnn.mb, [&](int i) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < rnn.dic; j++) {
+ float h = states_tm1_l(i, j);
+ float G1 = ws_gates(i, 1, j);
+ diff_states_t_l(0, i, j) += dhG1(i, j) * G1;
+ ws_gates(i, 1, j) = dhG1(i, j) * h * x_m_square(G1);
+ hG1(i, j) = G1 * h;
+ }
+ });
+
+ // 4. calculate diff weights
+ // dWh1 += dG1 * h, dWh2 += dG2 * h, dWh3 += dG3 * (G1(*)h)
+ gemm('N', 'T', (rnn.n_gates - 1) * rnn.dic, rnn.sic, rnn.mb, 1.0, ws_gates_,
+ rnn.gates_ws_ld, states_tm1_l_, rnn.states_ws_ld, 1.0, diff_w_iter_,
+ rnn.diff_weights_iter_ld);
+ gemm('N', 'T', rnn.dic, rnn.sic, rnn.mb, 1.0, &(ws_gates(0, 2, 0)),
+ rnn.gates_ws_ld, hG1_, rnn.states_ws_ld, 1.0,
+ &(diff_w_iter(0, 2, 0)), rnn.diff_weights_iter_ld);
+
+ // 5. calculate diff states
+ // dht-1 += dG1 * W1h + dG0 * W0h
+ (this->*gemm_iter_func)('N', 'N', rnn.sic, rnn.mb,
+ (rnn.n_gates - 1) * rnn.dic, 1.0, w_iter_[0],
+ rnn.weights_iter_ld, ws_gates_, rnn.gates_ws_ld, 1.0,
+ diff_states_t_l_, rnn.states_ws_ld);
+
+ if (!rnn.merge_gemm_layer) {
+ // dWx += [dG0 dG1 dG2] * [x]
+ gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.slc, rnn.mb, 1.0, ws_gates_,
+ rnn.gates_ws_ld, states_t_lm1_, rnn.states_ws_ld, 1.0,
+ diff_w_layer_, rnn.diff_weights_layer_ld);
+ // dx = dG2 * W2x + dG1 * W1x + dG0 * W0x
+ (this->*gemm_layer_func)('N', 'N', rnn.slc, rnn.mb,
+ rnn.n_gates * rnn.dic, 1.0, w_layer_[0],
+ rnn.weights_layer_ld, ws_gates_, rnn.gates_ws_ld, 0.0,
+ &(diff_states_t_l(rnn.n_states, 0, 0)), rnn.states_ws_ld);
+ }
+
+ // 6. calculate diff bias
+ gates_reduction(rnn, ws_gates_, diff_bias_);
+}
+#undef AOC
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru_lbr.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru_lbr.cpp
new file mode 100644
index 0000000000..8dea8c90a4
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_gru_lbr.cpp
@@ -0,0 +1,170 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*
+ * Cell execution GRU with linear before reset
+ */
+
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "ref_rnn.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::math;
+using namespace rnn_utils;
+#define AOC array_offset_calculator
+
+template <>
+rnn_elemwise_sig(ref_rnn_fwd_f32_t::gru_lbr_elemwise) {
+ ws_gates_aoc_t ws_gates(rnn, ws_gates_);
+ bias_aoc_t bias(rnn, bias_);
+ ws_states_aoc_t states_t_l(rnn, states_t_l_);
+ ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_);
+ ws_gates_aoc_t ws_gemm_state(rnn, ws_cell_);
+ AOC<float, 2> ws_Wh_b(ws_grid_, rnn.mb, rnn.dic);
+
+ parallel_nd(rnn.mb, [&](int i) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < rnn.dic; j++) {
+ float Wh_b = ws_gemm_state(i, 2, j) + bias(3, j);
+ ws_gates(i, 0, j) = logistic_fwd(
+ ws_gates(i, 0, j) + ws_gemm_state(i, 0, j) + bias(0, j));
+ ws_gates(i, 1, j) = logistic_fwd(
+ ws_gates(i, 1, j) + ws_gemm_state(i, 1, j) + bias(1, j));
+ ws_gates(i, 2, j) = tanh_fwd(
+ ws_gates(i, 2, j) + ws_gates(i, 1, j) * Wh_b + bias(2, j));
+ states_t_l(i, j) = states_tm1_l(i, j) * ws_gates(i, 0, j)
+ + (1.0f - ws_gates(i, 0, j)) * ws_gates(i, 2, j);
+ if (rnn.is_training)
+ ws_Wh_b(i, j) = Wh_b;
+ }
+ });
+}
+
+template <>
+rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::gru_lbr_elemwise) {
+ assert(!"GRU LBR int8 is not supported");
+}
+
+template <>
+rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution_gru_lbr) {
+ if (!rnn.merge_gemm_layer) {
+ (this->*gemm_layer_func)('N', 'N', rnn.n_gates * rnn.dic, rnn.mb,
+ rnn.slc, 1.0, w_layer_[0], rnn.weights_layer_ld,
+ states_t_lm1_, rnn.states_ws_ld, 0.0, ws_gates_,
+ rnn.gates_ws_ld);
+ }
+ (this->*gemm_iter_func)('N', 'N', rnn.n_gates * rnn.dic, rnn.mb, rnn.sic,
+ 1.0, w_iter_[0], rnn.weights_iter_ld, states_tm1_l_,
+ rnn.states_ws_ld, 0.0, ws_cell_, rnn.gates_ws_ld);
+ (this->*elemwise_func)(rnn, ws_gates_, states_t_l_, c_states_t_l_,
+ states_tm1_l_, c_states_tm1_l_, diff_states_t_l_,
+ diff_states_t_lp1_, diff_states_tp1_l_, bias_[0], ws_grid_,
+ ws_cell_);
+}
+
+template <>
+rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution_gru_lbr) {
+ assert(!"GRU LBR int8 is not supported");
+}
+
+template <>
+rnn_elemwise_sig(ref_rnn_bwd_f32_t::gru_lbr_elemwise) {
+ ws_gates_aoc_t ws_gates(rnn, ws_gates_);
+ ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_);
+ ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_);
+ ws_diff_states_aoc_t diff_states_tp1_l(rnn, diff_states_tp1_l_);
+ ws_diff_states_aoc_t diff_states_t_lp1(rnn, diff_states_t_lp1_);
+ ws_gates_aoc_t ws_gates_r(rnn, ws_cell_);
+ AOC<float, 2> ws_Wh_b(ws_grid_, rnn.mb, rnn.dic);
+
+ // 1. calculate dG1 dG2 dG3
+ // dG0 = (dht - G2) * dht * (1 - G0) * G0
+ // dG1 = (W*h + b) * dG2 * (1 - G1) * G1
+ // dG2 = (1 - G0) * dht * (1 - G2*G2)
+ parallel_nd(rnn.mb, [&](int i) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < rnn.dic; j++) {
+ float h = states_tm1_l(i, j);
+ float dHt = diff_states_tp1_l(0, i, j)
+ + diff_states_t_lp1(rnn.n_states, i, j);
+ float dG0 = (h - ws_gates(i, 2, j)) * dHt
+ * x_m_square(ws_gates(i, 0, j));
+ float dG2 = (1.0f - ws_gates(i, 0, j))
+ * one_m_square(ws_gates(i, 2, j)) * dHt;
+ float dG1 = ws_Wh_b(i, j) * dG2 * x_m_square(ws_gates(i, 1, j));
+
+ diff_states_t_l(0, i, j) = dHt * ws_gates(i, 0, j);
+ ws_gates(i, 2, j) = dG2;
+ ws_gates_r(i, 2, j) = dG2 * ws_gates(i, 1, j);
+ ws_gates(i, 0, j) = ws_gates_r(i, 0, j) = dG0;
+ ws_gates(i, 1, j) = ws_gates_r(i, 1, j) = dG1;
+ }
+ });
+}
+
+template <>
+rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution_gru_lbr) {
+ ws_gates_aoc_t ws_gates_r(rnn, ws_cell_);
+ ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_);
+
+ (this->*elemwise_func)(rnn, ws_gates_, states_t_l_, c_states_t_l_,
+ states_tm1_l_, c_states_tm1_l_, diff_states_t_l_,
+ diff_states_t_lp1_, diff_states_tp1_l_, bias_[0], ws_grid_,
+ ws_cell_);
+
+ if (!rnn.merge_gemm_layer) {
+ // dx = dG * Wx^t
+ (this->*gemm_layer_func)('N', 'N', rnn.slc, rnn.mb,
+ rnn.n_gates * rnn.dic, 1.0, w_layer_[0],
+ rnn.weights_layer_ld, ws_gates_, rnn.gates_ws_ld, 0.0,
+ &diff_states_t_l(rnn.n_states, 0, 0), rnn.states_ws_ld);
+ // dWx += dG^t * x
+ gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.slc, rnn.mb, 1.0, ws_gates_,
+ rnn.gates_ws_ld, states_t_lm1_, rnn.states_ws_ld, 1.0,
+ diff_w_layer_, rnn.diff_weights_layer_ld);
+ }
+ // dh += dGr * Wh^t
+ (this->*gemm_iter_func)('N', 'N', rnn.sic, rnn.mb, rnn.n_gates * rnn.dic,
+ 1.0, w_iter_[0], rnn.weights_iter_ld, ws_cell_, rnn.gates_ws_ld,
+ 1.0, diff_states_t_l_, rnn.states_ws_ld);
+
+ // dWh += dGr^t * h
+ gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.sic, rnn.mb, 1.0, ws_cell_,
+ rnn.gates_ws_ld, states_tm1_l_, rnn.states_ws_ld, 1.0, diff_w_iter_,
+ rnn.diff_weights_layer_ld);
+
+ // db1-3 += e * dG
+ // db4 += e * (r * dG2)
+ gates_reduction(rnn, ws_gates_, diff_bias_);
+
+ parallel_nd(rnn.dic, [&](int j) {
+ for (int i = 0; i < rnn.mb; i++) {
+ diff_bias_[3 * rnn.dic + j] += ws_gates_r(i, 2, j);
+ }
+ });
+}
+
+#undef AOC
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_lstm.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_lstm.cpp
new file mode 100644
index 0000000000..a15ba00d4c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_lstm.cpp
@@ -0,0 +1,143 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*
+ * Cell execution LSTM
+ */
+
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "../simple_q10n.hpp"
+#include "ref_rnn.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::math;
+using namespace rnn_utils;
+
+template <>
+rnn_elemwise_sig(ref_rnn_fwd_f32_t::lstm_elemwise) {
+ ws_gates_aoc_t ws_gates(rnn, ws_gates_);
+ bias_aoc_t bias(rnn, bias_);
+ ws_states_aoc_t states_t_l(rnn, states_t_l_);
+ ws_states_aoc_t c_states_t_l(rnn, c_states_t_l_);
+ ws_states_aoc_t c_states_tm1_l(rnn, c_states_tm1_l_);
+
+ parallel_nd(rnn.mb, [&](int i) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < rnn.dic; j++) {
+ ws_gates(i, 0, j) = logistic_fwd(ws_gates(i, 0, j) + bias(0, j));
+ ws_gates(i, 1, j) = logistic_fwd(ws_gates(i, 1, j) + bias(1, j));
+ ws_gates(i, 2, j) = tanh_fwd(ws_gates(i, 2, j) + bias(2, j));
+ ws_gates(i, 3, j) = logistic_fwd(ws_gates(i, 3, j) + bias(3, j));
+
+ float tmp = ws_gates(i, 1, j) * c_states_tm1_l(i, j)
+ + ws_gates(i, 0, j) * ws_gates(i, 2, j);
+ states_t_l(i, j) = ws_gates(i, 3, j) * tanh_fwd(tmp);
+ c_states_t_l(i, j) = tmp;
+ }
+ });
+}
+
+template <>
+rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::lstm_elemwise) {
+ ws_gates_aoc_s32_t ws_gates_s32(rnn, ws_gates_);
+ bias_aoc_t bias(rnn, bias_);
+ ws_states_aoc_u8_t states_t_l(rnn, states_t_l_);
+ ws_states_aoc_t c_states_t_l(rnn, c_states_t_l_);
+ ws_states_aoc_t c_states_tm1_l(rnn, c_states_tm1_l_);
+
+ float *weights_scales = pd()->attr()->rnn_weights_qparams_.scales_;
+ float data_shift = pd()->attr()->rnn_data_qparams_.shift_;
+ float data_scale = pd()->attr()->rnn_data_qparams_.scale_;
+
+ auto q_d = [&](float f) {
+ float qf = f * data_scale + data_shift;
+ return qz_a1b0<float, src_data_t>()(qf);
+ };
+
+ auto deq_w = [&](acc_data_t s, int gate, int j) {
+ return pd()->attr()->rnn_weights_qparams_.mask_ == 0 ?
+ saturate<float>(s) * (1.f / (weights_scales[0] * data_scale)) :
+ saturate<float>(s) * (1.f / (weights_scales[gate * rnn.dic + j]
+ * data_scale));
+ };
+
+ parallel_nd(rnn.mb, [&](int i) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < rnn.dic; j++) {
+ float G0 = logistic_fwd<float>(
+ deq_w(ws_gates_s32(i, 0, j), 0, j) + bias(0, j));
+ float G1 = logistic_fwd<float>(
+ deq_w(ws_gates_s32(i, 1, j), 1, j) + bias(1, j));
+ float G2 = tanh_fwd<float>(
+ deq_w(ws_gates_s32(i, 2, j), 2, j) + bias(2, j));
+ float G3 = logistic_fwd<float>(
+ deq_w(ws_gates_s32(i, 3, j), 3, j) + bias(3, j));
+ float tmp = G1 * c_states_tm1_l(i, j) + G0 * G2;
+ states_t_l(i, j) = q_d(G3 * tanh_fwd(tmp));
+ c_states_t_l(i, j) = tmp;
+ }
+ });
+}
+
+template <>
+rnn_elemwise_sig(ref_rnn_bwd_f32_t::lstm_elemwise) {
+ ws_gates_aoc_t ws_gates(rnn, ws_gates_);
+ bias_aoc_t bias(rnn, bias_);
+ ws_states_aoc_t c_states_t_l(rnn, c_states_t_l_);
+ ws_states_aoc_t c_states_tm1_l(rnn, c_states_tm1_l_);
+ ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_);
+ ws_diff_states_aoc_t diff_states_tp1_l(rnn, diff_states_tp1_l_);
+ ws_diff_states_aoc_t diff_states_t_lp1(rnn, diff_states_t_lp1_);
+
+ parallel_nd(rnn.mb, [&](int i) {
+ PRAGMA_OMP_SIMD()
+ for (int j = 0; j < rnn.dic; j++) {
+ float Ct = c_states_t_l(i, j);
+ /// @todo save it in the workspace in fwd pass or recompute it to
+ /// save bw
+ float tanhCt = tanh_fwd(Ct);
+ // we have 2 incoming diffs on Ht
+ float dHt = diff_states_tp1_l(0, i, j)
+ + diff_states_t_lp1(rnn.n_states, i, j);
+ float dCt = diff_states_tp1_l(1, i, j)
+ + one_m_square(tanhCt) * ws_gates(i, 3, j) * dHt;
+
+ float dG1 = c_states_tm1_l(i, j) * dCt
+ * x_m_square(ws_gates(i, 1, j));
+ float dG0 = ws_gates(i, 2, j) * dCt * x_m_square(ws_gates(i, 0, j));
+ float dG3 = tanhCt * dHt * x_m_square(ws_gates(i, 3, j));
+ float dG2
+ = ws_gates(i, 0, j) * dCt * one_m_square(ws_gates(i, 2, j));
+
+ diff_states_t_l(1, i, j) = dCt * ws_gates(i, 1, j);
+
+ ws_gates(i, 0, j) = dG0;
+ ws_gates(i, 1, j) = dG1;
+ ws_gates(i, 2, j) = dG2;
+ ws_gates(i, 3, j) = dG3;
+ }
+ });
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_rnn.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_rnn.cpp
new file mode 100644
index 0000000000..4536e8dfad
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cell_rnn.cpp
@@ -0,0 +1,113 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*
+ * Cell execution of Vanilla RNN
+ */
+
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "ref_rnn.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::math;
+using namespace rnn_utils;
+
+template <>
+float activation<alg_kind::eltwise_relu, prop_kind::forward>(
+ float dd, float s, float alpha, float cliping) {
+ return relu_fwd<float>(s, alpha);
+}
+
+template <>
+float activation<alg_kind::eltwise_relu, prop_kind::backward>(
+ float dd, float s, float alpha, float cliping) {
+ return relu_bwd<float>(dd, s, alpha);
+}
+
+template <>
+float activation<alg_kind::eltwise_tanh, prop_kind::forward>(
+ float dd, float s, float alpha, float cliping) {
+ return tanh_fwd<float>(s);
+}
+
+template <>
+float activation<alg_kind::eltwise_tanh, prop_kind::backward>(
+ float dd, float s, float alpha, float cliping) {
+ return dd * one_m_square<float>(s);
+}
+
+template <>
+float activation<alg_kind::eltwise_logistic, prop_kind::forward>(
+ float dd, float s, float alpha, float cliping) {
+ return logistic_fwd<float>(s);
+}
+
+template <>
+float activation<alg_kind::eltwise_logistic, prop_kind::backward>(
+ float dd, float s, float alpha, float cliping) {
+ return dd * x_m_square<float>(s);
+}
+
+template <>
+rnn_elemwise_sig(ref_rnn_fwd_f32_t::rnn_elemwise) {
+ ws_gates_aoc_t ws_gates(rnn, ws_gates_);
+ bias_aoc_t bias(rnn, bias_);
+ ws_states_aoc_t states_t_l(rnn, states_t_l_);
+ ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_);
+
+ parallel_nd(rnn.mb, [&](int i) {
+ for (int j = 0; j < rnn.dic; j++) {
+ const float h
+ = activation_func(0, ws_gates(i, 0, j) + bias(0, j), 0, 0);
+ ws_gates(i, 0, j) = states_t_l(i, j) = h;
+ }
+ });
+}
+
+template <>
+rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::rnn_elemwise) {
+ assert(!"VANILLA RNN int8 is not supported");
+}
+
+template <>
+rnn_elemwise_sig(ref_rnn_bwd_f32_t::rnn_elemwise) {
+ ws_gates_aoc_t ws_gates(rnn, ws_gates_);
+ bias_aoc_t bias(rnn, bias_);
+ ws_states_aoc_t states_t_l(rnn, states_t_l_);
+ ws_states_aoc_t states_tm1_l(rnn, states_tm1_l_);
+ ws_diff_states_aoc_t diff_states_t_l(rnn, diff_states_t_l_);
+ ws_diff_states_aoc_t diff_states_tp1_l(rnn, diff_states_tp1_l_);
+ ws_diff_states_aoc_t diff_states_t_lp1(rnn, diff_states_t_lp1_);
+
+ parallel_nd(rnn.mb, [&](int i) {
+ for (int j = 0; j < rnn.dic; ++j) {
+ const float dH = diff_states_t_lp1(rnn.n_states, i, j)
+ + diff_states_tp1_l(0, i, j);
+ auto g = ws_gates(i, 0, j);
+ ws_gates(i, 0, j) = activation_func(dH, g, 0, 0);
+ }
+ });
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cpu_rnn_pd.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cpu_rnn_pd.hpp
new file mode 100644
index 0000000000..b39427caf9
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/cpu_rnn_pd.hpp
@@ -0,0 +1,191 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_RNN_PD_HPP
+#define CPU_RNN_PD_HPP
+
+#include "c_types_map.hpp"
+#include "nstl.hpp"
+#include "rnn_pd.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+#include "rnn_utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct cpu_rnn_fwd_pd_t : public rnn_fwd_pd_t {
+ using rnn_fwd_pd_t::rnn_fwd_pd_t;
+
+protected:
+ status_t set_default_params() {
+ using namespace format_tag;
+ if (src_layer_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(src_layer_md_, tnc));
+ if (dst_layer_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(dst_layer_md_, tnc));
+
+ // Optional parameters
+ if (with_src_iter() && src_iter_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(src_iter_md_, ldsnc));
+ if (with_bias() && bias_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(bias_md_, ldgo));
+ if (with_dst_iter() && dst_iter_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(dst_iter_md_, ldsnc));
+
+ return status::success;
+ }
+
+ status_t check_layout_consistency() {
+ using namespace format_tag;
+ using namespace data_type;
+ using namespace types;
+
+ auto is_blocked = [&](memory_desc_t md, int ndims) {
+ return md.format_kind == format_kind::blocked && md.ndims == ndims;
+ };
+
+ bool ok = true;
+ ok = ok && is_blocked(src_layer_md_, 3)
+ && is_blocked(dst_layer_md_, 3);
+ ok = ok && IMPLICATION(!is_zero_md(&src_iter_md_),
+ is_blocked(src_iter_md_, 5))
+ && IMPLICATION(!is_zero_md(&dst_iter_md_),
+ is_blocked(dst_iter_md_, 5));
+
+ if (weights_layer_md_.format_kind == format_kind::rnn_packed)
+ ok = ok && (weights_layer_md_.format_desc.rnn_packed_desc.format
+ == mkldnn_ldigo_p);
+ else
+ ok = ok && rnn_utils::is_ldigo(&weights_layer_md_);
+
+ if (weights_iter_md_.format_kind == format_kind::rnn_packed)
+ ok = ok && (weights_iter_md_.format_desc.rnn_packed_desc.format
+ == mkldnn_ldigo_p);
+ else
+ ok = ok && rnn_utils::is_ldigo(&weights_iter_md_);
+
+ ok = ok && IMPLICATION(!is_zero_md(&bias_md_),
+ memory_desc_matches_tag(bias_md_, ldgo));
+
+ /* Int8 is supported only for packed weights */
+ data_type_t weights_iter_dt = weights_iter_md_.data_type;
+ data_type_t weights_layer_dt = weights_layer_md_.data_type;
+ ok = ok && IMPLICATION(
+ weights_iter_dt == s8, weights_iter_md_.format_kind
+ == format_kind::rnn_packed);
+ ok = ok && IMPLICATION(
+ weights_layer_dt == s8, weights_layer_md_.format_kind
+ == format_kind::rnn_packed);
+
+ return ok ? status::success : status::unimplemented;
+ }
+};
+
+struct cpu_rnn_bwd_pd_t : public rnn_bwd_pd_t {
+ using rnn_bwd_pd_t::rnn_bwd_pd_t;
+
+protected:
+ status_t set_default_params() {
+ using namespace format_tag;
+ if (src_layer_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(src_layer_md_, tnc));
+ if (dst_layer_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(dst_layer_md_, tnc));
+
+ if (diff_src_layer_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(diff_src_layer_md_, tnc));
+ if (diff_weights_layer_md_.format_kind == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(diff_weights_layer_md_, ldigo));
+ CHECK(rnn_utils::set_good_strides(diff_weights_layer_md_, ldigo));
+ }
+ if (diff_weights_iter_md_.format_kind == format_kind::any) {
+ CHECK(memory_desc_init_by_tag(diff_weights_iter_md_, ldigo));
+ CHECK(rnn_utils::set_good_strides(diff_weights_iter_md_, ldigo));
+ }
+ if (diff_dst_layer_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(diff_dst_layer_md_, tnc));
+
+ // Optional parameters
+ if (with_src_iter() && src_iter_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(src_iter_md_, ldsnc));
+ if (with_bias() && bias_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(bias_md_, ldgo));
+ if (with_dst_iter() && dst_iter_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(dst_iter_md_, ldsnc));
+
+ if (with_src_iter() && diff_src_iter_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(diff_src_iter_md_, ldsnc));
+ if (with_bias() && diff_bias_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(diff_bias_md_, ldgo));
+ if (with_dst_iter() && diff_dst_iter_md_.format_kind == format_kind::any)
+ CHECK(memory_desc_init_by_tag(diff_dst_iter_md_, ldsnc));
+
+ return status::success;
+ }
+
+ status_t check_layout_consistency() {
+ using namespace format_tag;
+ using namespace types;
+
+ auto is_blocked = [&](memory_desc_t md, int ndims) {
+ return md.format_kind == format_kind::blocked && md.ndims == ndims;
+ };
+
+ bool ok = true;
+ ok = ok && is_blocked(src_layer_md_, 3)
+ && is_blocked(dst_layer_md_, 3);
+ ok = ok && IMPLICATION(!is_zero_md(&src_iter_md_),
+ is_blocked(src_iter_md_, 5))
+ && IMPLICATION(!is_zero_md(&dst_iter_md_),
+ is_blocked(dst_iter_md_, 5));
+
+ if (weights_layer_md_.format_kind == format_kind::rnn_packed)
+ ok = ok && (weights_layer_md_.format_desc.rnn_packed_desc.format
+ == mkldnn_ldgoi_p);
+ else
+ ok = ok && rnn_utils::is_ldgoi(&weights_layer_md_);
+
+ if (weights_iter_md_.format_kind == format_kind::rnn_packed)
+ ok = ok && (weights_iter_md_.format_desc.rnn_packed_desc.format
+ == mkldnn_ldgoi_p);
+ else
+ ok = ok && rnn_utils::is_ldgoi(&weights_iter_md_);
+
+ ok = ok && IMPLICATION(!is_zero_md(&bias_md_),
+ memory_desc_matches_tag(bias_md_, ldgo));
+
+ ok = ok && is_blocked(diff_src_layer_md_, 3)
+ && is_blocked(diff_dst_layer_md_, 3);
+ ok = ok && IMPLICATION(!is_zero_md(&diff_src_iter_md_),
+ is_blocked(diff_src_iter_md_, 5))
+ && IMPLICATION(!is_zero_md(&diff_dst_iter_md_),
+ is_blocked(diff_dst_iter_md_, 5));
+
+ ok = ok && rnn_utils::is_ldigo(&diff_weights_layer_md_)
+ && rnn_utils::is_ldigo(&diff_weights_iter_md_);
+ ok = ok && IMPLICATION(!is_zero_md(&diff_bias_md_),
+ memory_desc_matches_tag(diff_bias_md_, ldgo));
+
+ return ok ? status::success : status::unimplemented;
+ }
+};
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/jit_uni_rnn_postgemm.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/jit_uni_rnn_postgemm.hpp
new file mode 100644
index 0000000000..09445648aa
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/jit_uni_rnn_postgemm.hpp
@@ -0,0 +1,401 @@
+/*******************************************************************************
+* Copyright 2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*
+ * Cell execution LSTM
+ */
+
+#include "rnn_utils.hpp"
+#include "../jit_generator.hpp"
+#include "../jit_uni_eltwise.hpp"
+#include "c_types_map.hpp"
+#include "utils.hpp"
+
+#include "mkldnn_thread.hpp"
+
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+struct jit_uni_rnn_postgemm_kernel : public jit_generator {
+
+ typedef void (*kernel_t)(void *gates_, const void *bias, void *states_t_l_,
+ void *c_states_t_l_, void *c_states_tm1_l_);
+
+ jit_uni_rnn_postgemm_kernel(const rnn_utils::rnn_conf_t &rnn, const primitive_attr_t *attr): rnn_(rnn), attr_(attr){}
+
+ virtual void init() = 0;
+
+template <typename src_data_t, typename acc_data_t>
+ rnn_elemwise_sig(execute) {
+ rnn_utils::ws_gates_aoc<acc_data_t> ws_gates(rnn, ws_gates_);
+ rnn_utils::bias_aoc_t bias(rnn, bias_);
+ rnn_utils::ws_states_aoc<src_data_t> states_t_l(rnn, states_t_l_);
+ rnn_utils::ws_states_aoc_t c_states_t_l(rnn, c_states_t_l_);
+ rnn_utils::ws_states_aoc_t c_states_tm1_l(rnn, c_states_tm1_l_);
+
+ // Todo: add parallelization on dic for the batch 1 case
+ // Assumption: the kernel runs a loop on dic elements
+ parallel_nd(rnn.mb, [&](int i) {
+ auto b_ = &bias(0, 0);
+ auto g_ = &ws_gates(i, 0, 0);
+ auto s_tl_ = &states_t_l(i, 0);
+ auto c_tl_ = &c_states_t_l(i, 0);
+ auto c_tm1l_ = &c_states_tm1_l(i, 0);
+ kernel_(g_, b_, s_tl_, c_tm1l_, c_tl_);
+ });
+ }
+
+protected:
+ kernel_t kernel_;
+ const rnn_utils::rnn_conf_t &rnn_;
+ const primitive_attr_t *attr_;
+};
+
+template <cpu_isa_t isa, impl::data_type_t src_data_t>
+struct jit_uni_lstm_postgemm_kernel_fwd: public jit_uni_rnn_postgemm_kernel
+{
+ DECLARE_CPU_JIT_AUX_FUNCTIONS(jit_uni_lstm_postgemm_kernel_fwd)
+
+ typedef typename utils::conditional<src_data_t == data_type::u8, int32_t,
+ float>::type acc_data_t;
+ typedef typename utils::conditional<isa == avx512_core,
+ jit_uni_eltwise_injector_f32<avx512_common>,
+ jit_uni_eltwise_injector_f32<isa>>::type injector_t;
+
+ jit_uni_lstm_postgemm_kernel_fwd(const rnn_utils::rnn_conf_t &rnn, const primitive_attr_t *attr)
+ : jit_uni_rnn_postgemm_kernel(rnn, attr){}
+
+ void init() override {
+ // we use rax for both constant tables as they use the same table
+ sigmoid_injector_ = new injector_t(this,
+ alg_kind::eltwise_logistic, 0.0f, 0.0f, true, rax);
+ tanh_injector_ = new injector_t(this,
+ alg_kind::eltwise_tanh, 0.0f, 0.0f, true, rax);
+ generate();
+ kernel_ = (kernel_t) this->getCode();
+ }
+
+protected:
+ injector_t *sigmoid_injector_;
+ injector_t *tanh_injector_;
+
+ // register size in bytes
+ using Vmm = typename jit_uni_eltwise_injector_f32<isa>::Vmm;
+ size_t vlen = cpu_isa_traits<isa>::vlen;
+ size_t vlen_dst = (src_data_t == data_type::u8) ? vlen/4 : vlen;
+ size_t cstate_dt_size = sizeof(float);
+ size_t hstate_dt_size = (src_data_t == data_type::u8) ? sizeof(uint8_t) : sizeof(float);
+ size_t gate_dt_size = (src_data_t == data_type::u8) ? sizeof(uint32_t) : sizeof(float);
+ size_t qscale_dt_size = sizeof(float);
+ size_t bias_dt_size = sizeof(float);
+
+ void generate() {
+ using namespace Xbyak;
+
+ int mask = attr_->rnn_weights_qparams_.mask_;
+ float *weights_scales = attr_->rnn_weights_qparams_.scales_;
+ float data_scale = attr_->rnn_data_qparams_.scale_;
+ float data_shift = attr_->rnn_data_qparams_.shift_;
+
+ // Labels declaration
+ Label vector_loop_start_label, vector_loop_end_label;
+ Label rem_loop_start_label, rem_loop_end_label;
+ Label table_label;
+
+ // Register map
+ Reg64 loop_cnt(r11); // loop counter
+ Reg64 table_reg(rbx); // table is used for data scale and shifts
+ Reg64 weights_scales_reg(r13);
+ // We skip vmm0 as it can be used by the injector for masks on sse4.2
+ Vmm G0(1), G1(2), G2(3), G3(4), tmp1_vmm(5), tmp2_vmm(6), zero_vmm(7);
+
+ // constant table map
+ Address dscale_off_addr = ptr[table_reg];
+ Address dshift_off_addr = ptr[table_reg + vlen];
+ Address ymm_perm_mask_addr = ptr[table_reg + 2*vlen];
+ Address zmm_perm_mask_addr = ptr[table_reg + 2*vlen + cpu_isa_traits<avx>::vlen];
+
+ // quantize from float to u8
+ auto q_d = [&](Vmm f, Vmm tmp_vmm) {
+ uni_vpxor(tmp_vmm, tmp_vmm, tmp_vmm);
+ uni_vmulps(f, f, dscale_off_addr); // apply scale
+ uni_vaddps(f, f, dshift_off_addr); // apply shift
+ uni_vcvtps2dq(f, f); // convert to int32
+ uni_vpackssdw(f, f, tmp_vmm); // convert from s32 to s16
+ uni_vpackuswb(f, f, tmp_vmm); // convert from s16 to u8 with saturation
+ // Note that the results are interleaved by 128 bit chunks, so we need to merge them together
+ switch (vlen) {
+ case 64: { //avx512
+ Zmm fz(f.getIdx()), tmpz(tmp_vmm.getIdx());
+ uni_vmovups(tmpz, zmm_perm_mask_addr);
+ vpermd(fz, tmpz, fz);
+ break; }
+ case 32: { //avx
+ Ymm fy(f.getIdx()), tmpy(tmp_vmm.getIdx());
+ uni_vmovups(tmpy, ymm_perm_mask_addr);
+ vpermd(fy, tmpy, fy);
+ break; }
+ case 16: // sse: nothing to do
+ break;
+ default: assert(!"Unsupported case");
+ };
+ };
+
+ auto fast_recip =[&](Vmm s, Vmm tmp, bool packed) {
+ if (packed)
+ uni_vrcpps(tmp, s);
+ else
+ uni_vrcpss(tmp, s); // prevent divide by zero
+ // we add one Newton iteration
+ uni_vmulps(s, s, tmp);
+ uni_vmulps(s, s, tmp); // s <- s * tmp^2
+ uni_vaddps(tmp, tmp, tmp);
+ uni_vsubps(tmp, tmp, s);
+ uni_vmovups(s, tmp); // s <- 2 * tmp - s * tmp^2
+ };
+
+ // dequantize from s32 to float
+ auto deq_w = [&](Vmm s, Vmm tmp1, Vmm tmp2, int gate, bool packed) {
+ // TODO: if mask is 0 precompute mul and inverse
+ if (mask == 0)
+ uni_vbroadcastss(tmp1, ptr[weights_scales_reg]);
+ else
+ uni_vmovups(tmp1, ptr[weights_scales_reg + gate * rnn_.dic * qscale_dt_size]);
+ uni_vcvtdq2ps(s, s);
+ uni_vmulps(tmp1, tmp1, dscale_off_addr);
+ fast_recip(tmp1, tmp2, packed);
+ uni_vmulps(s, s, tmp1);
+ };
+
+ // We start code generations here
+ preamble();
+
+ // extract addresses passed as parameter
+#ifdef _WIN32
+ auto addr_ws_gates_reg = abi_param1;
+ auto addr_bias_reg = abi_param2;
+ auto addr_states_t_l_reg = abi_param3;
+ auto addr_c_states_tm1_l_reg = abi_param4;
+ auto addr_c_states_t_l_reg = r10;
+ // Here we cannot use rbp to have initial stack pointer so we
+ // use rsp and offset it with the size of pushed registers in
+ // preamble
+ mov(addr_c_states_t_l_reg, ptr[rsp + get_size_of_abi_save_regs() + 40]);
+#else
+ auto addr_ws_gates_reg = abi_param1;
+ auto addr_bias_reg = abi_param2;
+ auto addr_states_t_l_reg = abi_param3;
+ auto addr_c_states_tm1_l_reg = abi_param4;
+ auto addr_c_states_t_l_reg = abi_param5;
+#endif
+
+ // initialize registers with addresses and constants
+ mov(table_reg, table_label);
+ mov(weights_scales_reg, size_t(weights_scales));
+ // both sigmoid and tanh use the same table so load address just once in rax
+ sigmoid_injector_->load_table_addr();
+
+ mov(loop_cnt, rnn_.dic * gate_dt_size);
+ cmp(loop_cnt, vlen);
+ jl(vector_loop_end_label, Xbyak::CodeGenerator::T_NEAR);
+
+ L(vector_loop_start_label);
+ {
+ // load G0 G1 G2 G3
+ uni_vmovups(G0, ptr[addr_ws_gates_reg + 0 * rnn_.dic * gate_dt_size]);
+ uni_vmovups(G1, ptr[addr_ws_gates_reg + 1 * rnn_.dic * gate_dt_size]);
+ uni_vmovups(G2, ptr[addr_ws_gates_reg + 2 * rnn_.dic * gate_dt_size]);
+ uni_vmovups(G3, ptr[addr_ws_gates_reg + 3 * rnn_.dic * gate_dt_size]);
+
+ // dequantize the gates from s32 to f32 if needed
+ if (src_data_t == data_type::u8){
+ deq_w(G0, tmp1_vmm, tmp2_vmm, 0, true);
+ deq_w(G1, tmp1_vmm, tmp2_vmm, 1, true);
+ deq_w(G2, tmp1_vmm, tmp2_vmm, 2, true);
+ deq_w(G3, tmp1_vmm, tmp2_vmm, 3, true);
+ }
+
+ // add biases
+ uni_vaddps(G0, G0, ptr[addr_bias_reg + 0 * rnn_.dic * bias_dt_size]);
+ uni_vaddps(G1, G1, ptr[addr_bias_reg + 1 * rnn_.dic * bias_dt_size]);
+ uni_vaddps(G2, G2, ptr[addr_bias_reg + 2 * rnn_.dic * bias_dt_size]);
+ uni_vaddps(G3, G3, ptr[addr_bias_reg + 3 * rnn_.dic * bias_dt_size]);
+
+ // inject eltwise code
+ sigmoid_injector_->compute_vector(G0.getIdx());
+ sigmoid_injector_->compute_vector(G1.getIdx());
+ tanh_injector_->compute_vector(G2.getIdx());
+ sigmoid_injector_->compute_vector(G3.getIdx());
+
+ // compute c_states_t_l = G1 * c_tm1_l + G0 * G2
+ uni_vmovups(tmp1_vmm, ptr[addr_c_states_tm1_l_reg]);
+ uni_vmulps(tmp1_vmm, tmp1_vmm, G1);
+ uni_vfmadd231ps(tmp1_vmm, G0, G2);
+ uni_vmovups(ptr[addr_c_states_t_l_reg], tmp1_vmm);
+
+ // states_t_l = G3 * tanh(c_states_t_l)
+ tanh_injector_->compute_vector(tmp1_vmm.getIdx());
+ uni_vmulps(tmp1_vmm, tmp1_vmm, G3);
+
+ // if int8, we quantize the resulting state
+ if (src_data_t == data_type::u8)
+ q_d(tmp1_vmm, tmp2_vmm);
+
+ // write back the result
+ if(vlen_dst == vlen)
+ uni_vmovups(ptr[addr_states_t_l_reg], tmp1_vmm);
+ else
+ // we write only 1/4 of the register
+ switch(vlen_dst){
+ case 16: uni_vmovups(ptr[addr_states_t_l_reg], Xmm(tmp1_vmm.getIdx())); break;
+ case 8: uni_vmovsd(ptr[addr_states_t_l_reg], Xmm(tmp1_vmm.getIdx())); break;
+ case 4: uni_vmovss(ptr[addr_states_t_l_reg], Xmm(tmp1_vmm.getIdx())); break;
+ default:
+ assert(!"Unsuported vector length for quantization");
+ }
+
+ // increment address pointers
+ add(addr_ws_gates_reg, vlen);
+ add(addr_bias_reg, vlen);
+ add(addr_states_t_l_reg, vlen_dst);
+ add(addr_c_states_tm1_l_reg, vlen);
+ add(addr_c_states_t_l_reg, vlen);
+ if (mask != 0)
+ add(weights_scales_reg, vlen);
+
+ // increment loop counter
+ sub(loop_cnt, vlen);
+ cmp(loop_cnt, vlen);
+ jge(vector_loop_start_label);
+ }
+ L(vector_loop_end_label);
+
+ cmp(loop_cnt, 0);
+ je(rem_loop_end_label, Xbyak::CodeGenerator::T_NEAR);
+ // Same code as above, we just use movuss for accessing inputs
+ // TODO: smarter handling of tails with Zmm -> Ymm -> Xmm -> scalar
+ L(rem_loop_start_label);
+ {
+ // remaping registers to Xmms
+ Xmm G0s(G0.getIdx()), G1s(G1.getIdx()), G2s(G2.getIdx()), G3s(G3.getIdx());
+ Xmm tmp1s_vmm(tmp1_vmm.getIdx());
+
+ // load G0 G1 G2 G3
+ uni_vmovss(G0s, ptr[addr_ws_gates_reg + 0 * rnn_.dic * gate_dt_size]);
+ uni_vmovss(G1s, ptr[addr_ws_gates_reg + 1 * rnn_.dic * gate_dt_size]);
+ uni_vmovss(G2s, ptr[addr_ws_gates_reg + 2 * rnn_.dic * gate_dt_size]);
+ uni_vmovss(G3s, ptr[addr_ws_gates_reg + 3 * rnn_.dic * gate_dt_size]);
+
+ // dequantize the gates from s32 to f32 if needed
+ if (src_data_t == data_type::u8){
+ deq_w(G0, tmp1_vmm, tmp2_vmm, 0, false);
+ deq_w(G1, tmp1_vmm, tmp2_vmm, 1, false);
+ deq_w(G2, tmp1_vmm, tmp2_vmm, 2, false);
+ deq_w(G3, tmp1_vmm, tmp2_vmm, 3, false);
+ }
+
+ // add biases
+ uni_vmovss(tmp1s_vmm, ptr[addr_bias_reg + 0 * rnn_.dic * bias_dt_size]);
+ uni_vaddps(G0s, G0s, tmp1s_vmm);
+ uni_vmovss(tmp1s_vmm, ptr[addr_bias_reg + 1 * rnn_.dic * bias_dt_size]);
+ uni_vaddps(G1s, G1s, tmp1s_vmm);
+ uni_vmovss(tmp1s_vmm, ptr[addr_bias_reg + 2 * rnn_.dic * bias_dt_size]);
+ uni_vaddps(G2s, G2s, tmp1s_vmm);
+ uni_vmovss(tmp1s_vmm, ptr[addr_bias_reg + 3 * rnn_.dic * bias_dt_size]);
+ uni_vaddps(G3s, G3s, tmp1s_vmm);
+
+ // inject eltwise code
+ sigmoid_injector_->compute_vector(G0s.getIdx());
+ sigmoid_injector_->compute_vector(G1s.getIdx());
+ tanh_injector_->compute_vector(G2s.getIdx());
+ sigmoid_injector_->compute_vector(G3s.getIdx());
+
+ // compute c_states_t_l = G1 * c_tm1_l + G0s * G2
+ uni_vmovups(tmp1s_vmm, ptr[addr_c_states_tm1_l_reg]);
+ uni_vmulps(tmp1s_vmm, tmp1s_vmm, G1s);
+ uni_vfmadd231ps(tmp1s_vmm, G0s, G2s);
+ uni_vmovss(ptr[addr_c_states_t_l_reg], tmp1s_vmm);
+
+ // states_t_l = G3 * tanh(c_states_t_l)
+ tanh_injector_->compute_vector(tmp1s_vmm.getIdx());
+ uni_vmulps(tmp1s_vmm, tmp1s_vmm, G3s);
+
+ // if int8, we quantize the resulting state
+ if (src_data_t == data_type::u8)
+ q_d(tmp1_vmm, tmp2_vmm);
+
+ // write back the result
+ if(vlen_dst == vlen)
+ uni_vmovups(ptr[addr_states_t_l_reg], tmp1s_vmm);
+ else
+ // we write only 1/4 of the register
+ switch(vlen_dst){
+ case 16: uni_vmovups(ptr[addr_states_t_l_reg], Xmm(tmp1s_vmm.getIdx())); break;
+ case 8: uni_vmovsd(ptr[addr_states_t_l_reg], Xmm(tmp1s_vmm.getIdx())); break;
+ case 4: uni_vmovss(ptr[addr_states_t_l_reg], Xmm(tmp1s_vmm.getIdx())); break;
+ default:
+ assert(!"Unsuported vector length for quantization");
+ }
+
+ // increment address pointers
+ add(addr_ws_gates_reg, gate_dt_size);
+ add(addr_bias_reg, bias_dt_size);
+ add(addr_states_t_l_reg, hstate_dt_size);
+ add(addr_c_states_tm1_l_reg, cstate_dt_size);
+ add(addr_c_states_t_l_reg, cstate_dt_size);
+ if (mask != 0)
+ add(weights_scales_reg, qscale_dt_size);
+
+ // increment loop counter
+ sub(loop_cnt, gate_dt_size);
+ cmp(loop_cnt, 0);
+ jg(rem_loop_start_label);
+
+ }
+ L(rem_loop_end_label);
+
+ postamble();
+
+ // Again, only one table is needed and shared between sigmoid and tanh
+ sigmoid_injector_->prepare_table(false);
+ tanh_injector_->prepare_table(true);
+
+ L(table_label);
+ {
+ for (size_t i = 0; i < vlen / sizeof(float); i++) dd(float2int(data_scale));
+ for (size_t i = 0; i < vlen / sizeof(float); i++) dd(float2int(data_shift));
+ // perm mask for ymm
+ dd(0); dd(4); dd(2); dd(3); dd(1); dd(5); dd(6); dd(7);
+ // perm mask for zmm
+ dd(0); dd(4); dd(8); dd(12); dd(1); dd(5); dd(6); dd(7);
+ dd(2); dd(9); dd(10); dd(11); dd(3); dd(12); dd(13); dd(14);
+ }
+ }
+
+};
+
+template struct jit_uni_lstm_postgemm_kernel_fwd<sse42, data_type::f32>;
+template struct jit_uni_lstm_postgemm_kernel_fwd<avx2, data_type::f32>;
+template struct jit_uni_lstm_postgemm_kernel_fwd<avx512_core, data_type::f32>;
+
+template struct jit_uni_lstm_postgemm_kernel_fwd<sse42, data_type::u8>;
+template struct jit_uni_lstm_postgemm_kernel_fwd<avx2, data_type::u8>;
+template struct jit_uni_lstm_postgemm_kernel_fwd<avx512_core, data_type::u8>;
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.cpp
new file mode 100644
index 0000000000..ead536816c
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.cpp
@@ -0,0 +1,788 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*
+ General architecture
+
+ for diff states, we have n_states + 1 as we have n_states diff
+ to propagate to the previous iteration and 1 states to propagate
+ to the previous layer
+ index 0 is dh for cell(t-1, l) to consume
+ index 1 is dc for cell(t-1, l) to consume
+ index 2 is dh for cell(t, l-1) to consume
+ this indexing enables to have the same indexing for states in elemwise
+ function
+ only the cell execution function should be impacted
+
+ */
+
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "ref_rnn.hpp"
+#include "../gemm/gemm.hpp"
+#include "../simple_q10n.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::utils;
+using namespace mkldnn::impl::memory_tracking::names;
+using namespace rnn_utils;
+#define AOC array_offset_calculator
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+void _ref_rnn_common_t<aprop, src_type, weights_type>::gates_reduction(
+ const rnn_conf_t &rnn, const acc_data_t *ws_gates_,
+ float *diff_bias_) const {
+ auto body = [&](int i, int k) {
+ for (int j = 0; j < rnn.mb; j++)
+ diff_bias_[i * rnn.dic + k]
+ += ws_gates_[j * rnn.gates_ws_ld + i * rnn.dic + k];
+ };
+
+ // @todo block k on simd-width
+#if MKLDNN_THR == MKLDNN_THR_OMP && _OPENMP >= 201307 \
+ /* icc 17.0 has a problem with simd collapse */ \
+ && !((defined __INTEL_COMPILER) && (__INTEL_COMPILER == 1700))
+#pragma omp parallel for simd collapse(2)
+ for (int i = 0; i < rnn.n_gates; i++)
+ for (int k = 0; k < rnn.dic; k++)
+ body(i, k);
+#else
+ parallel_nd(rnn.n_gates, rnn.dic, body);
+#endif
+}
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+rnn_gemm_sig((_ref_rnn_common_t<aprop, src_type, weights_type>::gemm)) {
+ assert(ldA * ldB * ldC != 0);
+ extended_sgemm(&transA, &transB, &m, &n, &k, &alpha, a_, &ldA, b_, &ldB,
+ &beta, c_, &ldC, nullptr, pd()->rnn_.use_jit_gemm);
+}
+
+template <>
+rnn_gemm_sig((ref_rnn_fwd_u8s8_t::gemm)) {
+ assert(!"non packed gemm is disabled for int8");
+}
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+rnn_gemm_sig((_ref_rnn_common_t<aprop, src_type, weights_type>::packed_gemm)) {
+#if (USE_MKL_PACKED_GEMM)
+ assert(transA == 'N');
+ cblas_sgemm_compute(CblasColMajor, CblasPacked,
+ (transB == 'T') ? CblasTrans : CblasNoTrans, m, n, k, a_, ldA, b_,
+ ldB, beta, c_, ldC);
+#else
+ UNUSED(transA);
+ UNUSED(transB);
+ UNUSED(m);
+ UNUSED(n);
+ UNUSED(k);
+ UNUSED(alpha);
+ UNUSED(ldA);
+ UNUSED(b_);
+ UNUSED(ldB);
+ UNUSED(beta);
+ UNUSED(c_);
+ UNUSED(ldC);
+ assert(!"packed gemm is disabled");
+#endif
+}
+
+template <>
+rnn_gemm_sig((ref_rnn_fwd_u8s8_t::packed_gemm)) {
+#if (USE_MKL_PACKED_GEMM)
+ int8_t offseta = 0, offsetb = 0;
+ int32_t offsetc = 0;
+ cblas_gemm_s8u8s32_compute(CblasColMajor, (CBLAS_TRANSPOSE)CblasPacked,
+ CblasNoTrans, CblasFixOffset, m, n, k, alpha, a_, ldA, offseta, b_,
+ ldB, offsetb, beta, c_, ldC, &offsetc);
+#else
+ UNUSED(transA);
+ UNUSED(transB);
+ UNUSED(m);
+ UNUSED(n);
+ UNUSED(k);
+ UNUSED(alpha);
+ UNUSED(ldA);
+ UNUSED(b_);
+ UNUSED(ldB);
+ UNUSED(beta);
+ UNUSED(c_);
+ UNUSED(ldC);
+ assert(!"packed gemm is disabled");
+#endif
+}
+
+//*************** Grid computations strategy: linear ***************//
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+rnn_grid_execution_sig(
+ (_ref_rnn_common_t<aprop, src_type, weights_type>::linear_execution)) {
+ AOC<src_data_t, 4> ws_states(ws_states_, rnn.n_layer + 1, rnn.n_dir,
+ rnn.n_iter + 1, rnn.states_nld * rnn.states_ws_ld);
+ AOC<float, 4> ws_c_states(ws_c_states_, rnn.n_layer + 1, rnn.n_dir,
+ rnn.n_iter + 1, rnn.states_nld * rnn.states_ws_ld);
+ AOC<float, 5> ws_diff_states(ws_diff_states_, rnn.n_layer + 1, rnn.n_dir,
+ (rnn.n_states + 1), rnn.n_iter + 1,
+ rnn.states_nld * rnn.states_ws_ld);
+ AOC<acc_data_t, 4> ws_gates(ws_gates_, rnn.n_layer, rnn.n_dir, rnn.n_iter,
+ rnn.gates_nld * rnn.gates_ws_ld);
+ AOC<weights_data_t *, 3> weights_input(
+ weights_layer_, rnn.n_layer, rnn.n_dir, rnn.n_parts_weights_layer);
+ AOC<weights_data_t *, 3> weights_states(
+ weights_states_, rnn.n_layer, rnn.n_dir, rnn.n_parts_weights_iter);
+ AOC<float*, 3> bias(
+ bias_, rnn.n_layer, rnn.n_dir, rnn.n_parts_bias);
+ AOC<float, 3> diff_weights_layer(diff_weights_layer_, rnn.n_layer,
+ rnn.n_dir,
+ rnn.diff_weights_layer_nld * rnn.diff_weights_layer_ld);
+ AOC<float, 3> diff_weights_iter(diff_weights_iter_, rnn.n_layer, rnn.n_dir,
+ rnn.diff_weights_iter_nld * rnn.diff_weights_iter_ld);
+ AOC<float, 3> diff_bias(
+ diff_bias_, rnn.n_layer, rnn.n_dir, rnn.n_bias * rnn.dic);
+ AOC<float, 4> ws_grid(
+ ws_grid_, rnn.n_layer, rnn.n_dir, rnn.n_iter, (int)rnn.ws_per_cell);
+
+ // We run the grid of computation
+ for (int dir = 0; dir < rnn.n_dir; dir++) {
+ for (int j = 0; j < rnn.n_layer; j++) {
+ int lay = (aprop == prop_kind::forward) ? j : rnn.n_layer - j - 1;
+
+ if ((aprop == prop_kind::forward) && rnn.merge_gemm_layer) {
+ (this->*gemm_layer_func)('N', 'N', rnn.n_gates * rnn.dic,
+ rnn.mb * rnn.n_iter, rnn.slc, 1.0,
+ weights_input(lay, dir, 0), rnn.weights_iter_ld,
+ &(ws_states(lay, dir, 1, 0)), rnn.states_ws_ld, 0.0,
+ &(ws_gates(lay, dir, 0, 0)), rnn.gates_ws_ld);
+ }
+
+ for (int i = 0; i < rnn.n_iter; i++) {
+ int iter = (aprop == prop_kind::forward) ? i : rnn.n_iter - i - 1;
+ (this->*cell_func)(rnn,
+ &(ws_states(lay + 1, dir, iter + 1, 0)),
+ &(ws_c_states(lay + 1, dir, iter + 1, 0)),
+ &(ws_diff_states(lay, dir, 0, iter, 0)),
+ &(weights_input(lay, dir, 0)),
+ &(weights_states(lay, dir, 0)),
+ &(bias(lay, dir, 0)),
+ &(ws_states(lay, dir, iter + 1, 0)),
+ &(ws_states(lay + 1, dir, iter, 0)),
+ &(ws_c_states(lay + 1, dir, iter, 0)),
+ &(ws_diff_states(lay + 1, dir, 0, iter, 0)),
+ &(ws_diff_states(lay, dir, 0, iter + 1, 0)),
+ &(diff_weights_layer(lay, dir, 0)),
+ &(diff_weights_iter(lay, dir, 0)),
+ &(diff_bias(lay, dir, 0)),
+ &(ws_gates(lay, dir, iter, 0)),
+ &(ws_grid(lay, dir, iter, 0)),
+ ws_cell_);
+ }
+
+ if ((aprop == prop_kind::backward) && rnn.merge_gemm_layer) {
+ (this->*gemm_layer_func)('N', 'N', rnn.slc, rnn.mb * rnn.n_iter,
+ rnn.n_gates * rnn.dic, 1.0, weights_input(lay, dir, 0),
+ rnn.weights_layer_ld,
+ (src_data_t *)(&(ws_gates(lay, dir, 0, 0))),
+ rnn.gates_ws_ld, 0.0,
+ (acc_data_t *)(&(ws_diff_states(
+ lay, dir, rnn.n_states, 0, 0))),
+ rnn.states_ws_ld);
+ gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.slc,
+ rnn.mb * rnn.n_iter, 1.0,
+ (weights_data_t *)(&(ws_gates(lay, dir, 0, 0))),
+ rnn.gates_ws_ld,
+ (src_data_t *)(&(ws_states(lay, dir, 1, 0))),
+ rnn.states_ws_ld, 1.0,
+ (acc_data_t *)(&(diff_weights_layer(lay, dir, 0))),
+ rnn.diff_weights_layer_ld);
+ }
+ if ((aprop == prop_kind::backward) && rnn.merge_gemm_iter) {
+ gemm('N', 'T', rnn.n_gates * rnn.dic, rnn.sic,
+ rnn.mb * rnn.n_iter, 1.0,
+ (weights_data_t *)(&(ws_gates(lay, dir, 0, 0))),
+ rnn.gates_ws_ld,
+ (src_data_t *)(&(ws_states(lay + 1, dir, 0, 0))),
+ rnn.states_ws_ld, 1.0,
+ (acc_data_t *)(&(diff_weights_iter(lay, dir, 0))),
+ rnn.diff_weights_iter_ld);
+ }
+ }
+ }
+}
+
+//********* GRID computations strategy: utility functions **********//
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+void _ref_rnn_common_t<aprop, src_type, weights_type>::copy_init_layer(
+ const rnn_conf_t &rnn, src_data_t *__restrict ws_states_,
+ float *__restrict ws_diff_states_, const src_data_t *__restrict xt_,
+ const float *__restrict diff_dst_layer_) const {
+
+ AOC<src_data_t, 4> ws_states(
+ ws_states_, rnn.n_dir, rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld);
+ auto xt_d = memory_desc_wrapper(pd()->src_md(0));
+
+ parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) {
+ auto xxt = xt_ + xt_d.blk_off(it, b);
+ src_data_t *ws_l2r_ptr = &(ws_states(0, it + 1, b, 0));
+ src_data_t *ws_r2l_ptr = &(ws_states(rnn.n_dir - 1, rnn.n_iter - it, b, 0));
+ if (rnn.exec_dir != r2l)
+ for (int c = 0; c < rnn.slc; c++)
+ ws_l2r_ptr[c] = xxt[c];
+ if (rnn.exec_dir != l2r)
+ for (int c = 0; c < rnn.slc; c++)
+ ws_r2l_ptr[c] = xxt[c];
+ });
+}
+
+template <>
+void ref_rnn_bwd_f32_t::copy_init_layer(const rnn_conf_t &rnn,
+ src_data_t *ws_states_, float *ws_diff_states_, const src_data_t *xt_,
+ const float *diff_dst_layer_) const {
+ AOC<float, 6> ws_diff_states(ws_diff_states_, rnn.n_layer + 1, rnn.n_dir,
+ (rnn.n_states + 1), rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld);
+ auto diff_dst_layer_d = memory_desc_wrapper(pd()->diff_dst_md(0));
+
+ switch (rnn.exec_dir) {
+ case bi_concat:
+ parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) {
+ auto diff_dst_layer_x
+ = diff_dst_layer_ + diff_dst_layer_d.blk_off(it, b);
+ for (int s = 0; s < rnn.dic; s++) {
+ ws_diff_states(rnn.n_layer, 0, rnn.n_states, it, b, s)
+ = diff_dst_layer_x[s];
+ ws_diff_states(
+ rnn.n_layer, 1, rnn.n_states, rnn.n_iter - it - 1, b, s)
+ = diff_dst_layer_x[rnn.dic + s];
+ }
+ });
+ break;
+ case bi_sum:
+ parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) {
+ auto diff_dst_layer_x
+ = diff_dst_layer_ + diff_dst_layer_d.blk_off(it, b);
+ for (int s = 0; s < rnn.dic; s++) {
+ ws_diff_states(rnn.n_layer, 0, rnn.n_states, it, b, s)
+ = diff_dst_layer_x[s];
+ ws_diff_states(
+ rnn.n_layer, 1, rnn.n_states, rnn.n_iter - it - 1, b, s)
+ = diff_dst_layer_x[s];
+ }
+ });
+ break;
+ case l2r:
+ parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) {
+ auto diff_dst_layer_x
+ = diff_dst_layer_ + diff_dst_layer_d.blk_off(it, b);
+ for (int s = 0; s < rnn.dic; s++) {
+ ws_diff_states(rnn.n_layer, 0, rnn.n_states, it, b, s)
+ = diff_dst_layer_x[s];
+ }
+ });
+ break;
+ case r2l:
+ parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) {
+ auto diff_dst_layer_x = diff_dst_layer_
+ + diff_dst_layer_d.blk_off(rnn.n_iter - it - 1, b);
+ for (int s = 0; s < rnn.dic; s++) {
+ ws_diff_states(rnn.n_layer, 0, rnn.n_states, it, b, s)
+ = diff_dst_layer_x[s];
+ }
+ });
+ break;
+ default: assert(!"Unsupported direction"); break;
+ }
+}
+
+/* For int8 configuration, input iteration states may be of types f32 or u8
+ * Internally h_state is always stored in u8 and c_state is always stored in f32
+ * If input states are of type u8 then h state is copied and c state is dequantized
+ * If input states are of type f32 then h state is quantized and c_state is copied
+ * */
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+template <typename input_data_t>
+void _ref_rnn_common_t<aprop, src_type, weights_type>::copy_init_iter(
+ const rnn_conf_t &rnn, src_data_t *__restrict ws_states_,
+ float *__restrict ws_c_states_, float *__restrict ws_diff_states_,
+ const input_data_t *__restrict firstit_states_,
+ const float *__restrict diff_dst_iter_) const {
+ AOC<src_data_t, 5> ws_states(ws_states_, rnn.n_layer + 1, rnn.n_dir,
+ rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld);
+ AOC<float, 5> ws_c_states(ws_c_states_, rnn.n_layer + 1, rnn.n_dir,
+ rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld);
+ float data_shift = pd()->attr()->rnn_data_qparams_.shift_;
+ float data_scale = pd()->attr()->rnn_data_qparams_.scale_;
+
+ const bool quantize = pd()->with_src_iter()
+ && pd()->src_md(1)->data_type == data_type::f32
+ && rnn.dt_conf != all_f32;
+ auto maybe_q = [&](input_data_t f) {
+ if (quantize) {
+ float qf = f * data_scale + data_shift;
+ return qz_a1b0<float, src_data_t>()(qf);
+ } else
+ return (src_data_t)f;
+ };
+
+ const bool dequantize = pd()->with_src_iter()
+ && pd()->src_md(1)->data_type == data_type::u8;
+ auto maybe_deq = [&](input_data_t s) {
+ if (dequantize)
+ return (((float)s - data_shift) / data_scale);
+ else
+ return (float)s;
+ };
+ auto firstit_states_d = memory_desc_wrapper(pd()->src_md(1));
+ if (firstit_states_) {
+ parallel_nd(
+ rnn.n_layer, rnn.n_dir, rnn.mb, [&](int lay, int dir, int b) {
+ for (int s = 0; s < rnn.sic; s++)
+ ws_states(lay + 1, dir, 0, b, s) = maybe_q(
+ firstit_states_[firstit_states_d.blk_off(
+ lay, dir, 0, b, s)]);
+ if (pd()->cell_kind() == alg_kind::vanilla_lstm)
+ for (int s = 0; s < rnn.sic; s++)
+ ws_c_states(lay + 1, dir, 0, b, s) = maybe_deq(
+ firstit_states_[firstit_states_d.blk_off(
+ lay, dir, 1, b, s)]);
+ });
+ } else {
+ parallel_nd(
+ rnn.n_layer, rnn.n_dir, rnn.mb, [&](int lay, int dir, int b) {
+ for (int j = 0; j < rnn.sic; j++) {
+ ws_states(lay + 1, dir, 0, b, j) = (src_data_t)0;
+ ws_c_states(lay + 1, dir, 0, b, j) = 0.0f;
+ }
+ });
+ }
+}
+
+template <>
+template <typename input_data_t>
+void ref_rnn_bwd_f32_t::copy_init_iter(const rnn_conf_t &rnn,
+ src_data_t *ws_states_, float *ws_c_states_, float *ws_diff_states_,
+ const input_data_t *firstit_states_,
+ const float *diff_dst_iter_) const {
+ AOC<float, 6> ws_diff_states(ws_diff_states_, rnn.n_layer + 1, rnn.n_dir,
+ rnn.n_states + 1, rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld);
+ auto diff_dst_iter_d = memory_desc_wrapper(pd()->diff_dst_md(1));
+ if (diff_dst_iter_) {
+ parallel_nd(rnn.n_layer, rnn.n_dir, rnn.n_states, rnn.mb,
+ [&](int lay, int dir, int state, int b) {
+ array_copy(&(ws_diff_states(
+ lay, dir, state, rnn.n_iter, b, 0)),
+ diff_dst_iter_
+ + diff_dst_iter_d.blk_off(
+ lay, dir, state, b),
+ rnn.dic);
+ });
+ } else {
+ parallel_nd(rnn.n_layer, rnn.n_dir, rnn.n_states, rnn.mb,
+ [&](int lay, int dir, int state, int i) {
+ for (int j = 0; j < rnn.dic; j++)
+ ws_diff_states(lay, dir, state, rnn.n_iter, i, j)
+ = 0.0f;
+ });
+ }
+}
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+template <typename dst_data_t>
+void _ref_rnn_common_t<aprop, src_type, weights_type>::copy_res_layer(
+ const rnn_conf_t &rnn, dst_data_t *dst_layer_, float *diff_src_layer,
+ const src_data_t *ws_states_, const float *ws_diff_states_) const {
+
+ auto dst_layer_d = memory_desc_wrapper(pd()->dst_md(0));
+ AOC<const src_data_t, 5> ws_states(ws_states_, rnn.n_layer + 1, rnn.n_dir,
+ rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld);
+ float shift = (pd()->attr()->rnn_data_qparams_.shift_);
+ float scale = (pd()->attr()->rnn_data_qparams_.scale_);
+
+ const bool dequantize = pd()->dst_md(0)->data_type == data_type::f32
+ && rnn.dt_conf != all_f32;
+ auto maybe_deq = [&](src_data_t s) {
+ if (dequantize)
+ return (dst_data_t)(((float)s - shift) / scale);
+ else
+ return (dst_data_t)s;
+ };
+ parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) {
+ int dir = 0;
+ if (rnn.exec_dir != r2l) {
+ for (int s = 0; s < rnn.dic; s++) {
+ dst_layer_[dst_layer_d.blk_off(it, b, dir * rnn.dic + s)]
+ = maybe_deq(ws_states(rnn.n_layer, dir, it + 1, b, s));
+ }
+ dir = 1;
+ }
+ if (rnn.exec_dir != l2r) {
+ for (int s = 0; s < rnn.dic; s++)
+ switch (rnn.exec_dir) {
+ case bi_sum:
+ dst_layer_[dst_layer_d.blk_off(it, b, s)]
+ += maybe_deq(ws_states(
+ rnn.n_layer, dir, rnn.n_iter - it, b, s));
+ break;
+ default:
+ dst_layer_[dst_layer_d.blk_off(it, b, dir * rnn.dic + s)]
+ = maybe_deq(ws_states(
+ rnn.n_layer, dir, rnn.n_iter - it, b, s));
+ }
+ }
+ });
+}
+
+template <>
+template <typename dst_data_t>
+void ref_rnn_bwd_f32_t::copy_res_layer(
+ const rnn_conf_t &rnn, dst_data_t *dst_layer_, float *diff_src_layer_,
+ const src_data_t *ws_states_, const float *ws_diff_states_) const {
+ auto diff_src_layer_d = memory_desc_wrapper(pd()->diff_src_md(0));
+ AOC<const float, 6> ws_diff_states(ws_diff_states_, rnn.n_layer + 1,
+ rnn.n_dir, rnn.n_states + 1, rnn.n_iter + 1, rnn.mb,
+ rnn.states_ws_ld);
+
+ parallel_nd(rnn.n_iter, rnn.mb, [&](int it, int b) {
+ int dir = 0;
+ for (int s = 0; s < rnn.slc; s++) {
+ float *dst_addr = diff_src_layer_
+ + diff_src_layer_d.blk_off(
+ (rnn.exec_dir == r2l) ? rnn.n_iter - 1 - it : it,
+ b, dir * rnn.slc + s);
+ float res = ws_diff_states(0, 0, rnn.n_states, it, b, s);
+ if (rnn.n_dir - 1)
+ res += ws_diff_states(
+ 0, 1, rnn.n_states, rnn.n_iter - 1 - it, b, s);
+ dst_addr[0] = res;
+ }
+ });
+}
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+template <typename output_data_t>
+void _ref_rnn_common_t<aprop, src_type, weights_type>::copy_res_iter(
+ const rnn_conf_t &rnn, output_data_t *dst_iter_, float *diff_src_iter_,
+ const src_data_t *ws_states_, float *ws_c_states_,
+ const float *ws_diff_states_) const {
+ auto dst_iter_d = memory_desc_wrapper(pd()->dst_md(1));
+ AOC<const src_data_t, 5> ws_states(ws_states_, rnn.n_layer + 1, rnn.n_dir,
+ rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld);
+ AOC<const float, 5> ws_c_states(ws_c_states_, rnn.n_layer + 1, rnn.n_dir,
+ rnn.n_iter + 1, rnn.mb, rnn.states_ws_ld);
+ float data_shift = pd()->attr()->rnn_data_qparams_.shift_;
+ float data_scale = pd()->attr()->rnn_data_qparams_.scale_;
+
+ const bool quantize = pd()->with_dst_iter()
+ && pd()->dst_md(1)->data_type == data_type::u8
+ && rnn.dt_conf != all_f32;
+ auto maybe_q = [&](float f) {
+ if (quantize) {
+ float qf = f * data_scale + data_shift;
+ return qz_a1b0<float, output_data_t>()(qf);
+ } else
+ return (output_data_t)f;
+ };
+
+ const bool dequantize = pd()->with_dst_iter()
+ && pd()->dst_md(1)->data_type == data_type::f32
+ && rnn.dt_conf != all_f32;
+ auto maybe_deq = [&](src_data_t s) {
+ if (dequantize)
+ return (output_data_t)(((float)s - data_shift) / data_scale);
+ else
+ return (output_data_t)s;
+ };
+ if (dst_iter_) {
+ parallel_nd(rnn.n_layer, rnn.n_dir, rnn.mb,
+ [&](int lay, int dir, int b) {
+ for (int s = 0; s < rnn.dic; s++) {
+ dst_iter_[dst_iter_d.blk_off(lay, dir, 0, b, s)]
+ = maybe_deq(ws_states(lay + 1, dir, rnn.n_iter, b, s));
+ }
+ if (pd()->cell_kind() == alg_kind::vanilla_lstm)
+ for (int s = 0; s < rnn.dic; s++) {
+ dst_iter_[dst_iter_d.blk_off(lay, dir, 1, b, s)]
+ = maybe_q(ws_c_states(
+ lay + 1, dir, rnn.n_iter, b, s));
+ }
+ });
+ }
+}
+
+template <>
+template <typename output_data_t>
+void ref_rnn_bwd_f32_t::copy_res_iter(
+ const rnn_conf_t &rnn, output_data_t *dst_iter_, float *diff_src_iter_,
+ const src_data_t *ws_states_, float *ws_c_states_,
+ const float *ws_diff_states_) const {
+ auto diff_src_iter_d = memory_desc_wrapper(pd()->diff_src_md(1));
+ AOC<const float, 6> ws_diff_states(ws_diff_states_, rnn.n_layer + 1,
+ rnn.n_dir, rnn.n_states + 1, rnn.n_iter + 1, rnn.mb,
+ rnn.states_ws_ld);
+ if (diff_src_iter_) {
+ parallel_nd(rnn.n_layer, rnn.n_dir, rnn.n_states, rnn.mb,
+ [&](int lay, int dir, int state, int b) {
+ for (int s = 0; s < rnn.sic; s++) {
+ diff_src_iter_[diff_src_iter_d.blk_off(
+ lay, dir, state, b, s)]
+ = ws_diff_states(lay, dir, state, 0, b, s);
+ }
+ });
+ }
+}
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+rnn_bias_prepare_sig((_ref_rnn_common_t<aprop, src_type, weights_type>::bias_prepare)) {
+ /* Original set of bias provided by the user */
+ AOC<const float, 5> b(
+ b_, rnn.n_layer, rnn.n_dir, rnn.n_bias * rnn.dic);
+ /* Array of pointers initialized in packing */
+ AOC<float *, 3> bias(bias_, rnn.n_layer, rnn.n_dir, rnn.n_parts_bias);
+ AOC<float, 3> scratch_bias(
+ scratch_bias_, rnn.n_layer, rnn.n_dir, rnn.n_bias * rnn.dic);
+
+ if (rnn.copy_bias) {
+ parallel_nd(rnn.n_layer * rnn.n_dir * rnn.n_bias * rnn.dic,
+ [&](size_t i) { scratch_bias_[i] = b_[i]; });
+ }
+
+ for (int i = 0; i < rnn.n_layer; i++) {
+ for (int d = 0; d < rnn.n_dir; d++) {
+ int offset_bias = 0;
+ for (int p = 0; p < rnn.n_parts_bias; p++) {
+ bias(i, d, p) = rnn.copy_bias
+ ? (float *) &scratch_bias(i, d, offset_bias)
+ : (float *) &b(i, d, offset_bias);
+ offset_bias += rnn.parts_bias[p] * rnn.dic;
+ }
+ }
+ }
+
+}
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+rnn_bias_finalize_sig(
+ (_ref_rnn_common_t<aprop, src_type, weights_type>::bias_finalize)) {
+ if (rnn.dt_conf != all_f32) {
+ float data_shift = pd()->attr()->rnn_data_qparams_.shift_;
+ float data_scale = pd()->attr()->rnn_data_qparams_.scale_;
+ float *weights_scales = pd()->attr()->rnn_weights_qparams_.scales_;
+ bool scale_per_oc = pd()->attr()->rnn_weights_qparams_.mask_ != 0;
+ for (int i = 0; i < rnn.n_layer * rnn.n_dir; i++)
+ for (int j = 0; j < rnn.n_bias * rnn.dic; j++) {
+ size_t off = i * rnn.n_bias * rnn.dic + j;
+ float weights_scale
+ = scale_per_oc ? weights_scales[j] : weights_scales[0];
+ scratch_bias_[off] -= (w_iter_comp[off] + w_layer_comp[off])
+ * data_shift / (weights_scale * data_scale);
+ }
+ }
+}
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+rnn_weights_assign_sig((_ref_rnn_common_t<aprop, src_type,
+ weights_type>::assign_packed_weights)) {
+ assert(md->format_kind == format_kind::rnn_packed);
+ const auto packed_desc = md->format_desc.rnn_packed_desc;
+ AOC<weights_data_t *, 3> weights(weights_,
+ rnn.n_layer, rnn.n_dir, packed_desc.n_parts);
+
+ size_t offset_packed = 0;
+ for (int l = 0; l < rnn.n_layer; l++)
+ for (int d = 0; d < rnn.n_dir; d++) {
+ for (int p = 0; p < packed_desc.n_parts; p++) {
+ weights(l, d, p) = (weights_data_t *)&w_[offset_packed];
+ offset_packed
+ += packed_desc.part_pack_size[p] / sizeof(weights_data_t);
+ }
+ }
+}
+
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+rnn_weights_assign_sig(
+ (_ref_rnn_common_t<aprop, src_type, weights_type>::assign_weights)) {
+ assert(md->format_kind == format_kind::blocked);
+ const auto &blk = md->format_desc.blocking;
+ /* Original set of weights provided by the user */
+ AOC<const weights_data_t, 3> w(w_,
+ rnn.n_layer, rnn.n_dir, (int)blk.strides[1]);
+ /* Array of pointers for each part of weights */
+ AOC<weights_data_t *, 3> weights(weights_, rnn.n_layer, rnn.n_dir, n_parts);
+
+ for (int i = 0; i < rnn.n_layer; i++)
+ for (int d = 0; d < rnn.n_dir; d++) {
+ size_t offset_weights = 0;
+ for (int p = 0; p < n_parts; p++) {
+ weights(i, d, p) = (weights_data_t *)&w(i, d, offset_weights);
+ offset_weights += gates_per_part[p] * blk.strides[3];
+ }
+ }
+}
+
+//********************* Execution function *********************//
+template <prop_kind_t aprop, data_type_t src_type, data_type_t weights_type>
+void _ref_rnn_common_t<aprop, src_type, weights_type>::execute_(
+ const exec_ctx_t &ctx) const {
+ const rnn_conf_t &rnn = this->pd()->rnn_;
+ auto input = CTX_IN_MEM(const src_data_t *, MKLDNN_ARG_SRC_LAYER);
+ auto states = CTX_IN_MEM(const char *, MKLDNN_ARG_SRC_ITER);
+ auto layer_weights_n_comp = CTX_IN_MEM(const char *, MKLDNN_ARG_WEIGHTS_LAYER);
+ auto iter_weights_n_comp = CTX_IN_MEM(const char *, MKLDNN_ARG_WEIGHTS_ITER);
+ auto bias = CTX_IN_MEM(const float *, MKLDNN_ARG_BIAS);
+
+ auto dst_last_layer = rnn.is_fwd
+ ? CTX_OUT_MEM(char *, MKLDNN_ARG_DST_LAYER)
+ : const_cast<char *>(CTX_IN_MEM(const char *, MKLDNN_ARG_DST_LAYER));
+ auto dst_last_iter = rnn.is_fwd
+ ? CTX_OUT_MEM(char *, MKLDNN_ARG_DST_ITER)
+ : const_cast<char *>(CTX_IN_MEM(const char *, MKLDNN_ARG_DST_ITER));
+
+ auto diff_dst_layer = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST_LAYER);
+ auto diff_dst_iter = CTX_IN_MEM(const float *, MKLDNN_ARG_DIFF_DST_ITER);
+
+ auto w_layer = reinterpret_cast<const weights_data_t *>(layer_weights_n_comp);
+ auto w_iter = reinterpret_cast<const weights_data_t *>(iter_weights_n_comp);
+ auto w_iter_comp = reinterpret_cast<const float *>(
+ iter_weights_n_comp + rnn.weights_iter_comp_offset);
+ auto w_layer_comp = reinterpret_cast<const float *>(
+ layer_weights_n_comp + rnn.weights_layer_comp_offset);
+
+ auto scratchpad = this->scratchpad(ctx);
+
+ auto ptr_wei_layer
+ = scratchpad.template get<weights_data_t *>(key_rnn_ptrs_wei_layer);
+ auto ptr_wei_iter
+ = scratchpad.template get<weights_data_t *>(key_rnn_ptrs_wei_iter);
+ auto ptr_bias =
+ scratchpad.template get<float *>(key_rnn_ptrs_bia);
+
+ // fetchihg buffers from the workspace
+ // if no workspace was provided we use the scratchpad
+ char *scratch_ptr = scratchpad.template get<char>(key_rnn_space);
+ char *ws_ptr = nullptr;
+ if (rnn.use_workspace)
+ ws_ptr = rnn.is_fwd
+ ? CTX_OUT_MEM(char *, MKLDNN_ARG_WORKSPACE)
+ : const_cast<char *>(CTX_IN_MEM(const char *, MKLDNN_ARG_WORKSPACE));
+
+ char *base_ptr = rnn.use_workspace ? ws_ptr : scratch_ptr;
+ acc_data_t *ws_gates = (acc_data_t *)(base_ptr + ws_gates_offset_);
+ src_data_t *ws_states = (src_data_t *)(base_ptr + ws_states_offset_);
+ float *ws_c_states = (float *)(base_ptr + ws_c_states_offset_);
+ float *ws_diff_states = (float *)(base_ptr + ws_diff_states_offset_);
+ float *ws_grid = (float *)(base_ptr + ws_grid_comp_offset_);
+ float *ws_cell = (float *)(base_ptr + ws_cell_comp_offset_);
+
+ auto diff_src_layer = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_SRC_LAYER);
+ auto diff_src_iter = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_SRC_ITER);
+
+ auto diff_weights_layer = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_WEIGHTS_LAYER);
+ auto diff_weights_iter = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_WEIGHTS_ITER);
+ auto diff_bias = CTX_OUT_MEM(float *, MKLDNN_ARG_DIFF_BIAS);
+
+ // Fetching extra buffers from scratchpad
+ float *ws_bias = (float *)(scratch_ptr + ws_bias_offset_);
+
+ // initialize diff_states to 0
+ if (aprop == prop_kind::backward)
+ array_set(ws_diff_states, 0.0f, rnn.ws_diff_states_size / sizeof(float));
+
+ /* Pack(if using packed gemm API) or copy(if input arrays have bad leading
+ * dimension */
+ (this->*bias_preparation_func)(rnn, ptr_bias, bias, ws_bias);
+
+ (this->*weights_iter_assign_func)(rnn, pd()->weights_md(1),
+ rnn.weights_iter_nld, rnn.weights_iter_ld, rnn.dic,
+ rnn.sic, rnn.n_parts_weights_iter, rnn.parts_weights_iter,
+ rnn.part_weights_iter_pack_size, ptr_wei_iter, w_iter,
+ ptr_bias, bias, ws_bias);
+ (this->*weights_layer_assign_func)(rnn, pd()->weights_md(0),
+ rnn.weights_layer_nld, rnn.weights_layer_ld, rnn.dic, rnn.slc,
+ rnn.n_parts_weights_layer, rnn.parts_weights_layer,
+ rnn.part_weights_layer_pack_size, ptr_wei_layer, w_layer, ptr_bias,
+ bias, ws_bias);
+
+ (this->*bias_finalization_func)(rnn, ws_bias, w_iter_comp, w_layer_comp);
+
+ // we first need to copy the initial states and input into ws
+ copy_init_layer(rnn, ws_states, ws_diff_states, input, diff_dst_layer);
+ if (rnn.dt_conf == f32u8f32u8 || rnn.dt_conf == f32u8f32f32
+ || rnn.dt_conf == all_f32)
+ copy_init_iter(rnn, ws_states, ws_c_states, ws_diff_states,
+ (const float *)states, diff_dst_iter);
+ else if (rnn.dt_conf == u8u8u8u8 || rnn.dt_conf == u8u8u8f32)
+ copy_init_iter(rnn, ws_states, ws_c_states, ws_diff_states,
+ (const uint8_t *)states, diff_dst_iter);
+ else
+ assert(!"unimplemented");
+
+ // run the execution on the grid
+ (this->*grid_computation)(rnn, ptr_wei_layer, ptr_wei_iter, ptr_bias,
+ ws_states, ws_c_states, ws_diff_states, ws_gates, ws_cell, ws_grid,
+ diff_weights_layer, diff_weights_iter, diff_bias);
+
+ // Finally we copy the results to the result buffers
+ if (rnn.dt_conf == u8u8u8f32 || rnn.dt_conf == f32u8f32f32
+ || rnn.dt_conf == all_f32)
+ copy_res_layer(rnn, (float *)dst_last_layer, diff_src_layer, ws_states,
+ ws_diff_states);
+ else if (rnn.dt_conf == u8u8u8u8 || rnn.dt_conf == f32u8f32u8)
+ copy_res_layer(rnn, (uint8_t *)dst_last_layer, diff_src_layer,
+ ws_states, ws_diff_states);
+ else
+ assert(!"unimplemented");
+
+ if (rnn.dt_conf == f32u8f32u8 || rnn.dt_conf == f32u8f32f32
+ || rnn.dt_conf == all_f32)
+ copy_res_iter(rnn, (float *)dst_last_iter, diff_src_iter, ws_states,
+ ws_c_states, ws_diff_states);
+ else if (rnn.dt_conf == u8u8u8u8 || rnn.dt_conf == u8u8u8f32)
+ copy_res_iter(rnn, (uint8_t *)dst_last_iter, diff_src_iter, ws_states,
+ ws_c_states, ws_diff_states);
+ else
+ assert(!"unimplemented");
+};
+
+/* Fix for MSVS warning C4661 */
+template<> rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution);
+template<> rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution);
+template<> rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution);
+template<> rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution_gru);
+template<> rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution_gru);
+template<> rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution_gru);
+template<> rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution_gru_lbr);
+template<> rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution_gru_lbr);
+template<> rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution_gru_lbr);
+template<> rnn_elemwise_sig(ref_rnn_fwd_f32_t::rnn_elemwise);
+template<> rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::rnn_elemwise);
+template<> rnn_elemwise_sig(ref_rnn_bwd_f32_t::rnn_elemwise);
+template<> rnn_elemwise_sig(ref_rnn_fwd_f32_t::lstm_elemwise);
+template<> rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::lstm_elemwise);
+template<> rnn_elemwise_sig(ref_rnn_bwd_f32_t::lstm_elemwise);
+template<> rnn_elemwise_sig(ref_rnn_fwd_f32_t::gru_lbr_elemwise);
+template<> rnn_elemwise_sig(ref_rnn_fwd_u8s8_t::gru_lbr_elemwise);
+template<> rnn_elemwise_sig(ref_rnn_bwd_f32_t::gru_lbr_elemwise);
+
+template struct _ref_rnn_common_t<prop_kind::forward, data_type::f32, data_type::f32>;
+template struct _ref_rnn_common_t<prop_kind::forward, data_type::u8, data_type::s8>;
+template struct _ref_rnn_common_t<prop_kind::backward, data_type::f32, data_type::f32>;
+
+#undef AOC
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.hpp
new file mode 100644
index 0000000000..6f449a9016
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/ref_rnn.hpp
@@ -0,0 +1,328 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_REF_RNN_HPP
+#define CPU_REF_RNN_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "memory_tracking.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+#include "../cpu_isa_traits.hpp"
+#include "../gemm/os_blas.hpp"
+
+#include "cpu_rnn_pd.hpp"
+#include "../cpu_primitive.hpp"
+#include "rnn_utils.hpp"
+#include "jit_uni_rnn_postgemm.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <alg_kind_t alg_kind, prop_kind_t prop_kind>
+float activation(float s, float alpha, float cliping, float dd);
+
+template <prop_kind_t aprop, impl::data_type_t src_type,
+ impl::data_type_t weights_type>
+struct _ref_rnn_common_t : public cpu_primitive_t {
+ typedef typename prec_traits<src_type>::type src_data_t;
+ typedef typename prec_traits<weights_type>::type weights_data_t;
+ typedef typename utils::conditional<src_type == data_type::u8, int32_t,
+ float>::type acc_data_t;
+
+ using class_name = _ref_rnn_common_t<aprop, src_type, weights_type>;
+
+ typedef rnn_elemwise_sig((class_name::*elemwise_f));
+ typedef rnn_cell_execution_sig((class_name::*cell_execution_f));
+ typedef rnn_grid_execution_sig((class_name::*grid_execution_f));
+
+ typedef rnn_gemm_sig((class_name::*gemm_t));
+ typedef rnn_bias_prepare_sig((class_name::*bias_prepare_t));
+ typedef rnn_bias_finalize_sig((class_name::*bias_finalize_t));
+ typedef rnn_weights_assign_sig((class_name::*weights_assign_t));
+
+ using base_pd_t =
+ typename utils::conditional<false || aprop == prop_kind::forward,
+ cpu_rnn_fwd_pd_t, cpu_rnn_bwd_pd_t>::type;
+
+ struct pd_t : public base_pd_t {
+ using base_pd_t::base_pd_t;
+
+ DECLARE_COMMON_PD_T("ref:any", class_name);
+
+ status_t init() {
+ using namespace prop_kind;
+ using namespace utils;
+ using namespace format_tag;
+ using namespace rnn_utils;
+ const alg_kind_t cell_kind = this->desc()->cell_desc.cell_kind;
+
+ data_type_t src_layer_dt = this->desc()->src_layer_desc.data_type;
+ data_type_t weights_iter_dt
+ = this->desc()->weights_iter_desc.data_type;
+ data_type_t weights_layer_dt
+ = this->desc()->weights_layer_desc.data_type;
+
+ bool ok = true
+ && one_of(cell_kind, alg_kind::vanilla_rnn,
+ alg_kind::vanilla_lstm, alg_kind::vanilla_gru,
+ alg_kind::gru_linear_before_reset)
+ && IMPLICATION(aprop == prop_kind::forward,
+ one_of(this->desc()->prop_kind, forward_training,
+ forward_inference))
+ && IMPLICATION(aprop == backward,
+ one_of(this->desc()->prop_kind, backward))
+ && src_layer_dt == src_type
+ && everyone_is(
+ weights_type, weights_iter_dt, weights_layer_dt)
+ && this->set_default_params() == status::success
+ && this->with_bias();
+ if (!ok)
+ return status::unimplemented;
+
+ init_conf(rnn_, *this->desc(), this->src_md(0), this->src_md(1),
+ this->weights_md(0), this->weights_md(1), this->dst_md(0));
+
+ if (rnn_.dt_conf == all_f32)
+ ok = ok && this->attr()->has_default_values();
+
+ // Set weights descriptors to desired format
+ memory_desc_t new_weights_layer_md = *this->weights_md(0);
+ CHECK(set_expected_desc(rnn_, new_weights_layer_md, false));
+ if (this->weights_layer_md_.format_kind == format_kind::any) {
+ this->weights_layer_md_ = new_weights_layer_md;
+ } else if (this->weights_layer_md_.format_kind
+ == format_kind::rnn_packed) {
+ if (this->weights_layer_md_ != new_weights_layer_md)
+ return status::unimplemented;
+ }
+
+ memory_desc_t new_weights_iter_md = *this->weights_md(1);
+ CHECK(set_expected_desc(rnn_, new_weights_iter_md, true));
+ if (this->weights_iter_md_.format_kind == format_kind::any) {
+ this->weights_iter_md_ = new_weights_iter_md;
+ } else if (this->weights_iter_md_.format_kind
+ == format_kind::rnn_packed) {
+ if (this->weights_iter_md_ != new_weights_iter_md)
+ return status::unimplemented;
+ }
+
+ CHECK(this->check_layout_consistency());
+
+ set_conf(rnn_, *this->desc(), this->weights_md(0),
+ this->weights_md(1), this->diff_weights_md(0),
+ this->diff_weights_md(1));
+
+ size_t scratchpad_sz{0}, ws_sz{0};
+ get_scratchpad_and_workspace_sizes(rnn_, scratchpad_sz, ws_sz);
+
+ // initialize the workspace if needed
+ if (rnn_.is_training) {
+ dims_t ws_dims = { (int)ws_sz };
+ mkldnn_memory_desc_init_by_tag(&this->ws_md_, 1, ws_dims,
+ data_type::u8, format_tag::x);
+ }
+
+ init_scratchpad(scratchpad_sz);
+
+ return status::success;
+ }
+
+ rnn_utils::rnn_conf_t rnn_;
+
+ private:
+ void init_scratchpad(size_t scratchpad_sz) {
+ using namespace memory_tracking::names;
+ auto scratchpad = this->scratchpad_registry().registrar();
+ scratchpad.book(key_rnn_space, sizeof(float) * scratchpad_sz, 4096);
+
+ int max_nparts = this->cell_kind() == alg_kind::vanilla_gru ? 2 : 1;
+ int ptr_wei_sz = rnn_.n_layer * rnn_.n_dir * max_nparts;
+ scratchpad.book(key_rnn_ptrs_wei_layer,
+ sizeof(float *) * ptr_wei_sz);
+ scratchpad.book(key_rnn_ptrs_wei_iter,
+ sizeof(float *) * ptr_wei_sz);
+ scratchpad.book(key_rnn_ptrs_bia,
+ sizeof(float *) * ptr_wei_sz);
+ }
+ };
+
+ _ref_rnn_common_t(const pd_t *apd)
+ : cpu_primitive_t(apd, true), rnn_postgemm_(nullptr) {
+ /// @todo set max_feature_size assuming that we limit the number of
+ /// iterations and layer to one if slc != dic and sic != dic
+ /// respectively
+
+ bias_preparation_func = &class_name::bias_prepare;
+ bias_finalization_func = &class_name::bias_finalize;
+
+ auto set_gemm_funcs
+ = [](bool packed_gemm, gemm_t &g, weights_assign_t &a) {
+ if (packed_gemm) {
+ g = &class_name::packed_gemm;
+ a = &class_name::assign_packed_weights;
+ } else {
+ g = &class_name::gemm;
+ a = &class_name::assign_weights;
+ }
+ };
+ set_gemm_funcs(pd()->rnn_.use_iter_packed_gemm, gemm_iter_func,
+ weights_iter_assign_func);
+
+ set_gemm_funcs(pd()->rnn_.use_layer_packed_gemm, gemm_layer_func,
+ weights_layer_assign_func);
+
+ switch (pd()->cell_kind()) {
+ case alg_kind::vanilla_lstm:
+ cell_func = &class_name::cell_execution;
+ if (aprop == prop_kind::forward) {
+ if (mayiuse(avx512_core))
+ rnn_postgemm_ = new jit_uni_lstm_postgemm_kernel_fwd<avx512_core, src_type>(
+ pd()->rnn_, pd()->attr());
+ else if (mayiuse(avx2))
+ rnn_postgemm_ = new jit_uni_lstm_postgemm_kernel_fwd<avx2, src_type>(
+ pd()->rnn_, pd()->attr());
+ else if (mayiuse(sse42))
+ rnn_postgemm_ = new jit_uni_lstm_postgemm_kernel_fwd<sse42, src_type>(
+ pd()->rnn_, pd()->attr());
+ assert(rnn_postgemm_ != nullptr);
+ rnn_postgemm_->init();
+ }
+ elemwise_func = &class_name::lstm_elemwise;
+ break;
+ case alg_kind::vanilla_rnn: // @todo switch on cell kind
+ cell_func = &class_name::cell_execution;
+ elemwise_func = &class_name::rnn_elemwise;
+ switch (pd()->activation_kind()) {
+ case alg_kind::eltwise_relu:
+ activation_func = &activation<alg_kind::eltwise_relu, aprop>;
+ break;
+ case alg_kind::eltwise_tanh:
+ activation_func = &activation<alg_kind::eltwise_tanh, aprop>;
+ break;
+ case alg_kind::eltwise_logistic:
+ activation_func = &activation<alg_kind::eltwise_logistic, aprop>;
+ break;
+ default: break;
+ }
+ break;
+ case alg_kind::vanilla_gru:
+ cell_func = &class_name::cell_execution_gru;
+ break;
+ case alg_kind::gru_linear_before_reset:
+ cell_func = &class_name::cell_execution_gru_lbr;
+ elemwise_func = &class_name::gru_lbr_elemwise;
+ break;
+ default: break;
+ }
+
+ grid_computation = &class_name::linear_execution;
+
+ size_t scratchpad_size, workspace_size;
+ rnn_utils::set_offsets(pd()->rnn_, ws_gates_offset_, ws_states_offset_,
+ ws_c_states_offset_, ws_diff_states_offset_,
+ ws_grid_comp_offset_, ws_cell_comp_offset_,
+ ws_bias_offset_, scratchpad_size, workspace_size);
+ }
+
+ ~_ref_rnn_common_t() {}
+
+ // typedef typename prec_traits::type data_t;
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ execute_(ctx);
+ return status::success;
+ }
+
+private:
+ void execute_(const exec_ctx_t &ctx) const;
+ rnn_grid_execution_sig(linear_execution);
+ rnn_cell_execution_sig(cell_execution);
+ rnn_cell_execution_sig(cell_execution_gru);
+ rnn_cell_execution_sig(cell_execution_gru_lbr);
+ rnn_elemwise_sig(rnn_elemwise);
+ rnn_elemwise_sig(lstm_elemwise);
+ rnn_elemwise_sig(gru_lbr_elemwise);
+ rnn_gemm_sig(gemm);
+ rnn_gemm_sig(packed_gemm);
+ rnn_bias_prepare_sig(bias_prepare);
+ rnn_bias_finalize_sig(bias_finalize);
+ rnn_weights_assign_sig(assign_weights);
+ rnn_weights_assign_sig(assign_packed_weights);
+
+ float (*activation_func)(float dd, float s, float alpha, float cliping);
+
+ void copy_init_layer(const rnn_utils::rnn_conf_t &rnn,
+ src_data_t *ws_states_, float *ws_diff_states_,
+ const src_data_t *xt_, const float *diff_dst_layer) const;
+
+ template <typename input_data_t>
+ void copy_init_iter(const rnn_utils::rnn_conf_t &rnn,
+ src_data_t *ws_states_, float *ws_c_states, float *ws_diff_states_,
+ const input_data_t *firstit_states_,
+ const float *diff_dst_iter) const;
+
+ template <typename dst_data_t>
+ void copy_res_layer(const rnn_utils::rnn_conf_t &rnn,
+ dst_data_t *dst_layer_, float *diff_src_layer,
+ const src_data_t *ws_states_, const float *ws_diff_states_) const;
+
+ template <typename output_data_t>
+ void copy_res_iter(const rnn_utils::rnn_conf_t &rnn,
+ output_data_t *dst_iter_, float *diff_src_iter,
+ const src_data_t *ws_states_, float *ws_c_states,
+ const float *ws_diff_states_) const;
+
+ void gates_reduction(const rnn_utils::rnn_conf_t &rnn,
+ const acc_data_t *ws_gates_, float *diff_bias_) const;
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+
+ size_t ws_gates_offset_;
+ size_t ws_states_offset_;
+ size_t ws_c_states_offset_;
+ size_t ws_bias_offset_;
+ size_t ws_diff_states_offset_;
+ size_t ws_grid_comp_offset_;
+ size_t ws_cell_comp_offset_;
+ jit_uni_rnn_postgemm_kernel *rnn_postgemm_;
+
+ grid_execution_f grid_computation;
+ cell_execution_f cell_func;
+
+ bias_prepare_t bias_preparation_func;
+ bias_finalize_t bias_finalization_func;
+ weights_assign_t weights_layer_assign_func;
+ weights_assign_t weights_iter_assign_func;
+
+ gemm_t gemm_layer_func;
+ gemm_t gemm_iter_func;
+ elemwise_f elemwise_func;
+};
+
+using ref_rnn_fwd_f32_t = _ref_rnn_common_t<prop_kind::forward, data_type::f32, data_type::f32>;
+using ref_rnn_bwd_f32_t = _ref_rnn_common_t<prop_kind::backward, data_type::f32, data_type::f32>;
+using ref_rnn_fwd_u8s8_t = _ref_rnn_common_t<prop_kind::forward, data_type::u8, data_type::s8>;
+}
+}
+}
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp
new file mode 100644
index 0000000000..597c63e3f8
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_reorders.hpp
@@ -0,0 +1,380 @@
+/*******************************************************************************
+ * Copyright 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+
+#ifndef CPU_RNN_REORDERS_HPP
+#define CPU_RNN_REORDERS_HPP
+
+#include <assert.h>
+
+#include "type_helpers.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+#include "simple_q10n.hpp"
+#include "cpu_reorder_pd.hpp"
+#include "../gemm/os_blas.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <data_type_t type_i, data_type_t type_o>
+struct rnn_data_reorder_t : public cpu_primitive_t {
+ struct pd_t : public cpu_reorder_pd_t {
+ using cpu_reorder_pd_t::cpu_reorder_pd_t;
+
+ DECLARE_COMMON_PD_T("rnn_data_reorder", rnn_data_reorder_t);
+
+ static status_t create(reorder_pd_t **reorder_pd,
+ engine_t *engine, const primitive_attr_t *attr,
+ engine_t *src_engine, const memory_desc_t *src_md,
+ engine_t *dst_engine, const memory_desc_t *dst_md) {
+ const memory_desc_wrapper id(src_md), od(dst_md);
+ bool args_ok = true
+ && id.data_type() == type_i
+ && od.data_type() == type_o
+ && id.matches_one_of_tag(format_tag::tnc, format_tag::ldsnc)
+ && od == id;
+ if (!args_ok) return status::invalid_arguments;
+
+ auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine,
+ dst_md);
+ if (_pd == nullptr) return out_of_memory;
+ if (_pd->init() != success) { delete _pd; return unimplemented; }
+ return safe_ptr_assign<reorder_pd_t>(*reorder_pd, _pd);
+ }
+ };
+
+private:
+ typedef typename prec_traits<type_i>::type in_data_t;
+ typedef typename prec_traits<type_o>::type out_data_t;
+
+ rnn_data_reorder_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto input = CTX_IN_MEM(const in_data_t *, MKLDNN_ARG_FROM);
+ auto output = CTX_OUT_MEM(out_data_t *, MKLDNN_ARG_TO);
+ const memory_desc_wrapper &input_d = pd()->src_md();
+ const memory_desc_wrapper &output_d = pd()->dst_md();
+ const size_t nelems = input_d.nelems();
+ const float scale = pd()->attr()->rnn_data_qparams_.scale_;
+ const float shift = pd()->attr()->rnn_data_qparams_.shift_;
+
+ parallel_nd(nelems, [&](size_t i) {
+ float in = (float)input[input_d.off_l(i)] * scale + shift;
+ output[output_d.off_l(i)] = qz_a1b0<float, out_data_t>()(in);
+ });
+
+ return status::success;
+ }
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <data_type_t type_i, data_type_t type_o>
+struct rnn_weights_reorder_t : public cpu_primitive_t {
+ struct pd_t : public cpu_reorder_pd_t {
+ using cpu_reorder_pd_t::cpu_reorder_pd_t;
+
+ DECLARE_COMMON_PD_T("rnn_weights_reorder", rnn_weights_reorder_t);
+
+ static status_t create(reorder_pd_t **reorder_pd,
+ engine_t *engine, const primitive_attr_t *attr,
+ engine_t *src_engine, const memory_desc_t *src_md,
+ engine_t *dst_engine, const memory_desc_t *dst_md) {
+#if !USE_MKL_PACKED_GEMM
+ return status::unimplemented;
+#endif
+ const memory_desc_wrapper id(src_md), od(dst_md);
+ bool args_ok = true
+ && id.data_type() == type_i
+ && od.data_type() == type_o
+ && od.format_kind() == format_kind::rnn_packed
+ && od.rnn_packed_desc().format == mkldnn_ldigo_p
+ && od.rnn_packed_desc().n_parts == 1
+ && attr != nullptr;
+ if (!args_ok) return status::invalid_arguments;
+
+ format_tag_t itag = id.matches_one_of_tag(
+ format_tag::ldigo, format_tag::ldgoi);
+ if (itag == format_tag::undef) return status::invalid_arguments;
+
+ const int mask = attr->rnn_weights_qparams_.mask_;
+ if (!utils::one_of(mask, 0, 3)) return status::unimplemented;
+
+ auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine,
+ dst_md);
+ if (_pd == nullptr) return out_of_memory;
+ _pd->itag_ = itag;
+ if (_pd->init() != success) { delete _pd; return unimplemented; }
+ return safe_ptr_assign<reorder_pd_t>(*reorder_pd, _pd);
+ }
+
+ status_t init() {
+ status_t status = cpu_reorder_pd_t::init();
+ if (status != status::success) return status;
+
+ init_scratchpad();
+
+ return status::success;
+ }
+
+ format_tag_t itag_;
+
+ private:
+ void init_scratchpad() {
+ const memory_desc_wrapper id(src_md());
+ const size_t nelems = id.nelems();
+ const auto &dims = id.dims();
+
+ using namespace memory_tracking::names;
+ auto scratchpad = scratchpad_registry().registrar();
+ size_t quantization_size = sizeof(int8_t) * nelems;
+ size_t reduction_size = itag_ == ldigo
+ ? sizeof(int32_t) * mkldnn_get_max_threads() * dims[0]
+ * dims[1] * dims[3] * dims[4]
+ : 0;
+ scratchpad.book(
+ key_reorder_rnn_weights_quantization, quantization_size);
+ scratchpad.book(key_reorder_rnn_weights_reduction, reduction_size);
+ }
+ };
+
+private:
+ typedef typename prec_traits<type_i>::type in_data_t;
+ typedef typename prec_traits<type_o>::type out_data_t;
+
+ rnn_weights_reorder_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+#if USE_MKL_PACKED_GEMM
+ auto input = CTX_IN_MEM(const in_data_t *, MKLDNN_ARG_FROM);
+ auto output = CTX_OUT_MEM(char *, MKLDNN_ARG_TO);
+ const memory_desc_wrapper &input_d = pd()->src_md();
+ const memory_desc_wrapper &output_d = pd()->dst_md();
+ const auto &dims = input_d.dims();
+
+ const int L = dims[0];
+ const int D = dims[1];
+ const int I = dims[2];
+ const int G = dims[3];
+ const int O = dims[4];
+
+ const bool is_igo = pd()->itag_ == format_tag::ldigo;
+
+ /* Quantize input & compute compensation */
+ auto quantized = (int8_t * __restrict)scratchpad(ctx).template get<void>(
+ memory_tracking::names::key_reorder_rnn_weights_quantization);
+ auto reduction = (int32_t * __restrict)scratchpad(ctx).template get<void>(
+ memory_tracking::names::key_reorder_rnn_weights_reduction);
+ float *comp = reinterpret_cast<float *>(
+ output + output_d.rnn_packed_desc().offset_compensation);
+ const float *scales = pd()->attr()->rnn_weights_qparams_.scales_;
+ const int mask = pd()->attr()->rnn_weights_qparams_.mask_;
+
+ if (is_igo) {
+ int nthr = mkldnn_get_max_threads();
+ int LD_nthr = nstl::min(L * D, nthr);
+ int I_nthr = nstl::min(I, nthr / LD_nthr);
+ parallel(nthr, [&](const int ithr, const int nthr) {
+ int LD_ithr = -1, LD_s = -1, LD_e = -1;
+ int I_ithr = -1, I_s = -1, I_e = -1;
+ if (ithr < LD_nthr * I_nthr) {
+ LD_ithr = ithr % LD_nthr;
+ I_ithr = ithr / LD_nthr;
+ balance211(L * D, LD_nthr, LD_ithr, LD_s, LD_e);
+ balance211(I, I_nthr, I_ithr, I_s, I_e);
+ }
+ int32_t *comp_ithr = reduction + I_ithr * L * D * G * O;
+ for (int ld = LD_s; ld < LD_e; ld++) {
+ for (int go = 0; go < G * O; go++)
+ comp_ithr[ld * G * O + go] = 0;
+ for (int i = I_s; i < I_e; i++) {
+ PRAGMA_OMP_SIMD()
+ for (int go = 0; go < G * O; go++) {
+ const float s = scales[(mask == 0) ? 0 : go];
+ int8_t q = qz_b0<in_data_t, out_data_t>()(
+ input[ld * I * G * O + i * G * O + go], s);
+ quantized[ld * I * G * O + i * G * O + go]
+ = (int32_t)q;
+ comp_ithr[ld * G * O + go] += (int32_t)q;
+ }
+ }
+ }
+ });
+ parallel_nd(L * D * G * O,
+ [&](int s) { comp[s] = saturate<float>(reduction[s]); });
+ for (int i = 1; i < I_nthr; i++) {
+ parallel_nd(L * D * G * O, [&](int s) {
+ comp[s] += saturate<float>(
+ reduction[i * L * D * G * O + s]);
+ });
+ }
+ } else {
+ parallel_nd(L * D, G * O, [&](int ld, int go) {
+ int32_t compensation = 0;
+ const float s = scales[(mask == 0) ? 0 : go];
+ PRAGMA_OMP_SIMD()
+ for (int i = 0; i < I; i++) {
+ int8_t q = qz_b0<in_data_t, out_data_t>()(
+ input[ld * G * O * I + go * I + i], s);
+ compensation += (int32_t)q;
+ quantized[ld * G * O * I + go * I + i] = q;
+ }
+ comp[ld * G * O + go] = saturate<float>(compensation);
+ });
+ }
+
+ /* Pack */
+ auto off_igo = [&](int l, int d, int i, int g, int o) {
+ return l * D * I * G * O + d * I * G * O + i * G * O + g * O + o;
+ };
+ auto off_goi = [&](int l, int d, int i, int g, int o) {
+ return l * D * G * O * I + d * G * O * I + g * O * I + o * I + i;
+ };
+ int n_parts = output_d.rnn_packed_desc().n_parts;
+ const size_t *size_packed_cell
+ = output_d.rnn_packed_desc().part_pack_size;
+ const int *parts = output_d.rnn_packed_desc().parts;
+ const int n = output_d.rnn_packed_desc().n;
+ char *to_pack = output;
+ for (int l = 0; l < L; l++) {
+ for (int d = 0; d < D; d++) {
+ for (int p = 0; p < n_parts; p++) {
+ int g = (p > 0) ? parts[p - 1] : 0;
+ int m_p = parts[p] * O;
+ int k_p = I;
+ cblas_gemm_s8u8s32_pack(CblasColMajor, CblasAMatrix,
+ is_igo ? CblasNoTrans : CblasTrans, m_p, n, k_p,
+ &quantized[is_igo ? off_igo(l, d, 0, g, 0) :
+ off_goi(l, d, g, 0, 0)],
+ is_igo ? G * O : I, to_pack);
+ to_pack += size_packed_cell[p];
+ }
+ }
+ }
+#endif
+ return status::success;
+ }
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+template <>
+struct rnn_weights_reorder_t<data_type::f32, data_type::f32>
+ : public cpu_primitive_t {
+ struct pd_t : public cpu_reorder_pd_t {
+ using cpu_reorder_pd_t::cpu_reorder_pd_t;
+
+ DECLARE_COMMON_PD_T("rnn_weights_reorder", rnn_weights_reorder_t);
+
+ static status_t create(reorder_pd_t **reorder_pd,
+ engine_t *engine, const primitive_attr_t *attr,
+ engine_t *src_engine, const memory_desc_t *src_md,
+ engine_t *dst_engine, const memory_desc_t *dst_md) {
+#if !USE_MKL_PACKED_GEMM
+ return status::unimplemented;
+#endif
+ const memory_desc_wrapper id(src_md), od(dst_md);
+ bool args_ok = true
+ && id.data_type() == data_type::f32
+ && od.data_type() == data_type::f32
+ && od.format_kind() == format_kind::rnn_packed
+ && utils::one_of(od.rnn_packed_desc().format,
+ mkldnn_ldigo_p, mkldnn_ldgoi_p)
+ && attr->has_default_values();
+ if (!args_ok) return status::invalid_arguments;
+
+ format_tag_t itag = id.matches_one_of_tag(
+ format_tag::ldigo, format_tag::ldgoi);
+ if (itag == format_tag::undef) return status::invalid_arguments;
+
+ const int mask = attr->rnn_weights_qparams_.mask_;
+ if (!utils::one_of(mask, 0, 3)) return status::unimplemented;
+
+ auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine,
+ dst_md);
+ if (_pd == nullptr) return out_of_memory;
+ if (_pd->init() != success) { delete _pd; return unimplemented; }
+ _pd->itag_ = itag;
+ return safe_ptr_assign<reorder_pd_t>(*reorder_pd, _pd);
+ }
+
+ format_tag_t itag_;
+ };
+
+private:
+ rnn_weights_reorder_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+#if USE_MKL_PACKED_GEMM
+ auto input = CTX_IN_MEM(const float *, MKLDNN_ARG_FROM);
+ auto output = CTX_OUT_MEM(float *, MKLDNN_ARG_TO);
+ const memory_desc_wrapper &input_d = pd()->src_md();
+ const memory_desc_wrapper &output_d = pd()->dst_md();
+ const auto &dims = input_d.dims();
+ const rnn_packed_desc_t &rnn_pdata = output_d.rnn_packed_desc();
+ const int L = dims[0];
+ const int D = dims[1];
+ const int I = dims[2];
+ const int G = dims[3];
+ const int O = dims[4];
+
+ /* Pack */
+ bool cross_case = false
+ || (pd()->itag_ == format_tag::ldigo
+ && rnn_pdata.format == mkldnn_ldgoi_p)
+ || (pd()->itag_ == format_tag::ldgoi
+ && rnn_pdata.format == mkldnn_ldigo_p);
+ auto trans = cross_case ? CblasTrans : CblasNoTrans;
+ int n_parts = rnn_pdata.n_parts;
+ const size_t *size_packed_cell = rnn_pdata.part_pack_size;
+ const int *parts = rnn_pdata.parts;
+ const int n = rnn_pdata.n;
+
+ const bool is_igo = pd()->itag_ == format_tag::ldigo;
+ auto off_igo = [&](int l, int d, int i, int g, int o) {
+ return l * D * I * G * O + d * I * G * O + i * G * O + g * O + o;
+ };
+ auto off_goi = [&](int l, int d, int i, int g, int o) {
+ return l * D * G * O * I + d * G * O * I + g * O * I + o * I + i;
+ };
+ for (int l = 0; l < L; l++) {
+ for (int d = 0; d < D; d++) {
+ for (int p = 0; p < n_parts; p++) {
+ int g = (p > 0) ? parts[p - 1] : 0;
+ int m_p = is_igo ? parts[p] * O : I;
+ int k_p = is_igo ? I : parts[p] * O;
+ int ld = is_igo ? G * O : I;
+ cblas_sgemm_pack(CblasColMajor, CblasAMatrix, trans, m_p, n,
+ k_p, 1.0f, &input[is_igo ? off_igo(l, d, 0, g, 0) :
+ off_goi(l, d, 0, g, 0)],
+ ld, output);
+ output += size_packed_cell[p] / sizeof(float);
+ }
+ }
+ }
+#endif
+ return status::success;
+ }
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+} // namespace cpu
+} // namespace impl
+} // namespace mkldnn
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.cpp
new file mode 100644
index 0000000000..1d60415cbc
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.cpp
@@ -0,0 +1,426 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "c_types_map.hpp"
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+
+#include "ref_rnn.hpp"
+#include "rnn_utils.hpp"
+#include "type_helpers.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::utils;
+using namespace rnn_utils;
+using namespace format_tag;
+using namespace rnn_packed_format;
+using namespace data_type;
+
+bool rnn_utils::is_ldigo(const memory_desc_wrapper &md) {
+ if (md.format_kind() != format_kind::blocked)
+ return false;
+
+ auto blk = md.blocking_desc();
+ auto str = blk.strides;
+ auto dims = md.dims();
+ return md.ndims() == 5 && blk.inner_nblks == 0 && str[4] == 1
+ && str[3] == dims[4] && str[1] == str[2] * dims[2]
+ && str[0] == str[1] * dims[1];
+};
+
+bool rnn_utils::is_ldgoi(const memory_desc_wrapper &md) {
+ if (md.format_kind() != format_kind::blocked)
+ return false;
+
+ auto blk = md.blocking_desc();
+ auto str = blk.strides;
+ auto dims = md.dims();
+ return md.ndims() == 5 && blk.inner_nblks == 0 && str[2] == 1
+ && str[3] == dims[4] * str[4] && str[1] == str[3] * dims[3]
+ && str[0] == str[1] * dims[1];
+};
+
+void rnn_utils::init_conf(rnn_conf_t &rnn, const rnn_desc_t &rd,
+ const memory_desc_wrapper &src_layer_d,
+ const memory_desc_wrapper &src_iter_d,
+ const memory_desc_wrapper &weights_layer_d,
+ const memory_desc_wrapper &weights_iter_d,
+ const memory_desc_wrapper &dst_layer_d) {
+ rnn.is_fwd = utils::one_of(rd.prop_kind, prop_kind::forward_training,
+ prop_kind::forward_inference);
+ rnn.is_training = utils::one_of(
+ rd.prop_kind, prop_kind::forward_training, prop_kind::backward);
+ rnn.is_lbr = rd.cell_desc.cell_kind == mkldnn_gru_linear_before_reset;
+
+ switch (rd.direction) {
+ case mkldnn_unidirectional_left2right: rnn.exec_dir = l2r; break;
+ case mkldnn_unidirectional_right2left: rnn.exec_dir = r2l; break;
+ case mkldnn_bidirectional_concat: rnn.exec_dir = bi_concat; break;
+ case mkldnn_bidirectional_sum: rnn.exec_dir = bi_sum; break;
+ default: break;
+ }
+
+ if (everyone_is(f32, src_layer_d.data_type(), dst_layer_d.data_type(),
+ weights_layer_d.data_type()))
+ rnn.dt_conf = all_f32;
+ else if (dst_layer_d.data_type() == u8) {
+ if (IMPLICATION(src_iter_d.md_, src_iter_d.data_type() == u8))
+ rnn.dt_conf = u8u8u8u8;
+ else
+ rnn.dt_conf = f32u8f32u8;
+ } else {
+ if (IMPLICATION(src_iter_d.md_, src_iter_d.data_type() == u8))
+ rnn.dt_conf = u8u8u8f32;
+ else
+ rnn.dt_conf = f32u8f32f32;
+ }
+
+ rnn.n_layer = weights_layer_d.dims()[0];
+ rnn.n_iter = src_layer_d.dims()[0];
+ rnn.n_dir = weights_layer_d.dims()[1];
+ rnn.n_gates = weights_layer_d.dims()[3];
+ rnn.n_states = mkldnn_rnn_cell_get_states_count(&rd.cell_desc);
+ rnn.n_bias = rnn.n_gates + rnn.is_lbr;
+ rnn.mb = src_layer_d.dims()[1];
+ rnn.sic = weights_iter_d.dims()[2];
+ rnn.slc = weights_layer_d.dims()[2];
+ rnn.dic = weights_layer_d.dims()[4];
+ rnn.dlc = dst_layer_d.dims()[2];
+
+ rnn.gates_ld = rnn.dic * rnn.n_gates;
+ rnn.gates_nld = rnn.mb;
+ rnn.states_nld = rnn.mb;
+
+ /* Set the correct number of weights parts */
+ bool is_orig_gru = rd.cell_desc.cell_kind == alg_kind::vanilla_gru;
+ rnn.n_parts_weights_layer = 1;
+ rnn.parts_weights_layer[0] = rnn.n_gates;
+ rnn.parts_weights_layer[1] = 0;
+
+ rnn.n_parts_weights_iter = is_orig_gru ? 2 : 1;
+ rnn.parts_weights_iter[0] = is_orig_gru ? 2 : rnn.n_gates;
+ rnn.parts_weights_iter[1] = is_orig_gru ? 1 : 0;
+
+ rnn.n_parts_bias = 1;
+ rnn.parts_bias[0] = rnn.n_bias;
+ rnn.parts_bias[1] = 0;
+
+ /* Decide wich gemm implementation to use: packed/nonpacked jit/cblas
+ * and if to mergre gemm across iterations */
+ bool is_int8 = rnn.dt_conf != all_f32;
+ rnn.merge_gemm_layer = ((rnn.is_fwd && rnn.mb < 128) || !rnn.is_fwd)
+ || is_int8;
+ bool is_gru = utils::one_of(rd.cell_desc.cell_kind, alg_kind::vanilla_gru,
+ alg_kind::gru_linear_before_reset);
+ rnn.merge_gemm_iter = !(rnn.is_fwd || is_gru) || is_int8;
+ bool is_inference = !rnn.is_training;
+
+ rnn.use_jit_gemm = !mayiuse(avx512_mic)
+ && ((is_inference && (rnn.n_layer > 1 || rnn.mb < 100))
+ || (rnn.is_training && rnn.dic < 500));
+
+ /* Decide to copy bias */
+ rnn.copy_bias = rnn.dt_conf != all_f32;
+
+#if USE_MKL_PACKED_GEMM
+ rnn.use_layer_packed_gemm
+ = (weights_layer_d.format_kind() == format_kind::any
+ && rnn.slc > 760 && rnn.dic > 760 && is_inference)
+ || is_int8; // packed gemm is the only supported option for int8
+ rnn.use_iter_packed_gemm
+ = (weights_iter_d.format_kind() == format_kind::any && rnn.sic > 760
+ && rnn.dic > 760 && is_inference)
+ || is_int8;
+#else
+ rnn.use_layer_packed_gemm = false;
+ rnn.use_iter_packed_gemm = false;
+#endif
+
+ /* Set packed gemm sizes */
+ if (rnn.use_layer_packed_gemm) {
+ rnn.weights_layer_pack_size = 0;
+ for (int p = 0; p < rnn.n_parts_weights_layer; p++) {
+ int m_p = rnn.is_fwd
+ ? (rnn.parts_weights_layer[p] * rnn.dic)
+ : rnn.slc;
+ int k_p = rnn.is_fwd
+ ? rnn.slc
+ : (rnn.parts_weights_layer[p] * rnn.dic);
+ int n_p = rnn.merge_gemm_layer ? rnn.mb * rnn.n_iter : rnn.mb;
+
+#if USE_MKL_PACKED_GEMM
+ if (rnn.dt_conf == all_f32)
+ rnn.part_weights_layer_pack_size[p] = cblas_sgemm_pack_get_size(
+ CblasAMatrix, m_p, n_p, k_p);
+ else
+ rnn.part_weights_layer_pack_size[p]
+ = cblas_gemm_s8u8s32_pack_get_size(
+ CblasAMatrix, m_p, n_p, k_p);
+#else
+ UNUSED(m_p);
+ UNUSED(k_p);
+ UNUSED(n_p);
+ rnn.part_weights_layer_pack_size[p] = 0;
+#endif
+ rnn.weights_layer_pack_size += rnn.n_layer * rnn.n_dir
+ * rnn.part_weights_layer_pack_size[p];
+ }
+ rnn.weights_layer_comp_offset = rnn.weights_layer_pack_size;
+ rnn.weights_layer_pack_size += rnn.dt_conf == all_f32 ? 0 : rnn.n_layer
+ * rnn.n_dir * rnn.n_gates * rnn.dlc * sizeof(float);
+ }
+
+ if (rnn.use_iter_packed_gemm) {
+ rnn.weights_iter_pack_size = 0;
+ for (int p = 0; p < rnn.n_parts_weights_iter; p++) {
+ int m_p = rnn.is_fwd ? (rnn.parts_weights_iter[p] * rnn.dic) :
+ rnn.sic;
+ int k_p = rnn.is_fwd ? rnn.sic :
+ (rnn.parts_weights_iter[p] * rnn.dic);
+ int n_p = rnn.merge_gemm_iter ? rnn.mb * rnn.n_iter : rnn.mb;
+
+#if USE_MKL_PACKED_GEMM
+ if (rnn.dt_conf == all_f32)
+ rnn.part_weights_iter_pack_size[p] = cblas_sgemm_pack_get_size(
+ CblasAMatrix, m_p, n_p, k_p);
+ else
+ rnn.part_weights_iter_pack_size[p]
+ = cblas_gemm_s8u8s32_pack_get_size(
+ CblasAMatrix, m_p, n_p, k_p);
+#else
+ UNUSED(m_p);
+ UNUSED(k_p);
+ UNUSED(n_p);
+ rnn.part_weights_iter_pack_size[p] = 0;
+#endif
+ rnn.weights_iter_pack_size += rnn.n_layer * rnn.n_dir
+ * rnn.part_weights_iter_pack_size[p];
+ }
+ rnn.weights_iter_comp_offset = rnn.weights_iter_pack_size;
+ rnn.weights_iter_pack_size += rnn.dt_conf == all_f32 ? 0 : rnn.n_layer
+ * rnn.n_dir * rnn.n_gates * rnn.dic * sizeof(float);
+ }
+
+}
+
+void rnn_utils::set_conf(rnn_conf_t &rnn, const rnn_desc_t &rd,
+ const memory_desc_wrapper &weights_layer_d,
+ const memory_desc_wrapper &weights_iter_d,
+ const memory_desc_wrapper &diff_weights_layer_d,
+ const memory_desc_wrapper &diff_weights_iter_d) {
+
+ /* Set leading dimensions for input weights arrays depending on input format
+ */
+ rnn.weights_layer_is_packed
+ = weights_layer_d.format_kind() == format_kind::rnn_packed;
+ rnn.weights_iter_is_packed
+ = weights_iter_d.format_kind() == format_kind::rnn_packed;
+
+ auto set_dims = [&](const memory_desc_wrapper &md, int &ld, int &nld) {
+ ld = 0; nld = 0;
+ if (md.is_blocking_desc()) {
+ if (is_ldigo(md)) {
+ ld = (int)md.blocking_desc().strides[2];
+ nld = md.dims()[2];
+ } else if (is_ldgoi(md)) {
+ ld = (int)md.blocking_desc().strides[4];
+ nld = md.dims()[3] * md.dims()[4];
+ } else
+ assert(!"unsupported weights format");
+ }
+ };
+ set_dims(weights_layer_d, rnn.weights_layer_ld, rnn.weights_layer_nld);
+ set_dims(weights_iter_d, rnn.weights_iter_ld, rnn.weights_iter_nld);
+ if (!rnn.is_fwd) {
+ set_dims(diff_weights_layer_d, rnn.diff_weights_layer_ld,
+ rnn.diff_weights_layer_nld);
+ set_dims(diff_weights_iter_d, rnn.diff_weights_iter_ld,
+ rnn.diff_weights_iter_nld);
+ }
+
+ int sizeof_states_dt
+ = rnn.dt_conf == all_f32 ? sizeof(float) : sizeof(uint8_t);
+ rnn.states_ws_ld
+ = get_good_ld(nstl::max(rnn.slc, nstl::max(rnn.sic, rnn.dic)),
+ sizeof_states_dt);
+ rnn.gates_ws_ld = get_good_ld(rnn.gates_ld, sizeof(float));
+
+ /* Set workspace sizes to store:
+ * states to copmute a pass
+ * diff states to copmute bwd pass (training only)
+ * intermediate results from the gates
+ */
+ rnn.use_workspace = rnn.is_training;
+ rnn.ws_states_size = (size_t)(rnn.n_layer + 1) * rnn.n_dir
+ * (rnn.n_iter + 1) * rnn.mb * rnn.states_ws_ld * sizeof_states_dt;
+ bool is_lstm = rd.cell_desc.cell_kind == mkldnn_vanilla_lstm;
+ rnn.ws_c_states_size = is_lstm
+ ? (size_t)(rnn.n_layer + 1) * rnn.n_dir * (rnn.n_iter + 1) * rnn.mb
+ * rnn.states_ws_ld * sizeof(float)
+ : 0;
+ rnn.ws_diff_states_size = rnn.is_training
+ ? (size_t)(rnn.n_layer + 1) * rnn.n_dir * (rnn.n_iter + 1)
+ * (rnn.n_states + 1) * rnn.mb * rnn.states_ws_ld
+ * sizeof(float)
+ : (size_t)0;
+ rnn.ws_gates_size = (size_t)rnn.n_layer * rnn.n_dir * rnn.n_iter * rnn.mb
+ * rnn.gates_ws_ld * sizeof(float);
+
+ /* set other sizes */
+ rnn.ws_per_cell = (size_t)rnn.is_lbr * rnn.mb * rnn.dic * sizeof(float);
+ rnn.ws_cell_comp_size
+ = rnn.is_lbr || rnn.dt_conf != all_f32
+ ? (size_t) rnn.gates_nld * rnn.gates_ws_ld * sizeof(float)
+ : 0;
+ rnn.ws_grid_comp_size = (size_t)rnn.is_lbr * rnn.is_training * rnn.n_layer
+ * rnn.n_dir * rnn.n_iter * rnn.ws_per_cell * sizeof(float);
+ rnn.ws_bias_size = (size_t)rnn.n_layer * rnn.n_dir * rnn.n_bias * rnn.dic
+ * sizeof(float);
+}
+
+int rnn_utils::get_good_ld(int dim, int sizeof_dt) {
+ // we want matrices leading dimentions to be 64-byte aligned,
+ // and not divisible by 256 to avoid 4K aliasing effects
+ int ld = rnd_up(dim, 64 / sizeof_dt);
+ return (ld % 256 == 0) ? ld + 64 / sizeof_dt : ld;
+}
+
+void rnn_utils::set_offsets(const rnn_conf_t &rnn, size_t &ws_gates_offset,
+ size_t &ws_states_offset, size_t &ws_c_states_offset,
+ size_t &ws_diff_states_offset, size_t &ws_grid_comp_offset,
+ size_t &ws_cell_comp_offset, size_t &ws_bias_offset,
+ size_t &scratchpad_size, size_t &workspace_size) {
+
+ const size_t page_size = 4096; // 2097152;
+ size_t current_offset;
+ /* Mandatory workspaces: go to workspace if use_workspace, scratchpad
+ * otherwise */
+ current_offset = 0; // assumes the workspace base pointer is page aligned
+ ws_gates_offset = current_offset;
+ current_offset += rnn.ws_gates_size;
+
+ current_offset = utils::rnd_up(current_offset, page_size);
+ ws_states_offset = current_offset;
+ current_offset += rnn.ws_states_size;
+
+ current_offset = utils::rnd_up(current_offset, page_size);
+ ws_c_states_offset = current_offset;
+ current_offset += rnn.ws_c_states_size;
+
+ current_offset = utils::rnd_up(current_offset, page_size);
+ ws_diff_states_offset = current_offset;
+ current_offset += rnn.ws_diff_states_size;
+
+ current_offset = utils::rnd_up(current_offset, page_size);
+ ws_grid_comp_offset = current_offset;
+ current_offset += rnn.ws_grid_comp_size;
+
+ current_offset = utils::rnd_up(current_offset, page_size);
+ ws_cell_comp_offset = current_offset;
+ current_offset += rnn.ws_cell_comp_size;
+
+ workspace_size = rnn.use_workspace ? current_offset : 0;
+
+ /* Optional scratchpads */
+ // Assumes the scratchpad base pointer is page aligned.
+ // If use_workspace, the following goes to scratchpad alone,
+ // otherwise, all goes to scratchpad and continue incrementing offset
+ current_offset = rnn.use_workspace ? 0 : current_offset;
+
+ if (rnn.copy_bias) {
+ current_offset = utils::rnd_up(current_offset, page_size);
+ ws_bias_offset = current_offset;
+ current_offset += rnn.ws_bias_size;
+ }
+
+ scratchpad_size = current_offset;
+}
+
+void rnn_utils::get_scratchpad_and_workspace_sizes(const rnn_conf_t &rnn,
+ size_t &scratchpad_size, size_t &workspace_size) {
+ size_t ws_gates_offset, ws_states_offset, ws_c_states_offset,
+ ws_diff_states_offset, ws_grid_comp_offset, ws_cell_comp_offset,
+ ws_bias_offset;
+ set_offsets(rnn, ws_gates_offset, ws_states_offset, ws_diff_states_offset,
+ ws_c_states_offset, ws_grid_comp_offset, ws_cell_comp_offset,
+ ws_bias_offset, scratchpad_size, workspace_size);
+}
+
+status_t rnn_utils::set_good_strides(
+ memory_desc_t &weights_md, format_tag_t tag) {
+ auto &strides = weights_md.format_desc.blocking.strides;
+ auto dims = weights_md.dims;
+
+ if (tag == ldigo) {
+ strides[2] = rnn_utils::get_good_ld((int)strides[2],
+ (int)types::data_type_size(weights_md.data_type));
+ strides[1] = dims[2] * strides[2];
+ strides[0] = dims[1] * strides[1];
+ } else if (tag == ldgoi) {
+ strides[4] = rnn_utils::get_good_ld((int)strides[4],
+ (int)types::data_type_size(weights_md.data_type));
+ strides[3] = dims[4] * strides[4];
+ strides[1] = dims[3] * strides[3];
+ strides[0] = dims[1] * strides[1];
+ } else
+ return status::unimplemented;
+
+ return status::success;
+}
+
+status_t rnn_utils::set_expected_desc(rnn_conf_t &rnn,
+ memory_desc_t &weights_md, bool is_iter) {
+ using namespace format_tag;
+ bool use_packed_gemm = is_iter
+ ? rnn.use_iter_packed_gemm
+ : rnn.use_layer_packed_gemm;
+ if (use_packed_gemm) {
+ weights_md.format_kind = format_kind::rnn_packed;
+ rnn_packed_desc_t &rnn_pdata = weights_md.format_desc.rnn_packed_desc;
+ rnn_pdata.format = rnn.is_fwd ? mkldnn_ldigo_p : mkldnn_ldgoi_p;
+ if (is_iter) {
+ rnn_pdata.n = rnn.mb;
+ rnn_pdata.n_parts = rnn.n_parts_weights_iter;
+ array_copy(rnn_pdata.parts, rnn.parts_weights_iter,
+ MKLDNN_RNN_MAX_N_PARTS);
+ array_copy(rnn_pdata.part_pack_size,
+ rnn.part_weights_iter_pack_size, MKLDNN_RNN_MAX_N_PARTS);
+ rnn_pdata.offset_compensation = rnn.weights_iter_comp_offset;
+ rnn_pdata.size = rnn.weights_iter_pack_size;
+ } else {
+ rnn_pdata.n = rnn.merge_gemm_layer ? rnn.n_iter * rnn.mb : rnn.mb;
+ rnn_pdata.n_parts = rnn.n_parts_weights_layer;
+ array_copy(rnn_pdata.parts, rnn.parts_weights_layer,
+ MKLDNN_RNN_MAX_N_PARTS);
+ array_copy(rnn_pdata.part_pack_size,
+ rnn.part_weights_layer_pack_size, MKLDNN_RNN_MAX_N_PARTS);
+ rnn_pdata.offset_compensation = rnn.weights_layer_comp_offset;
+ rnn_pdata.size = rnn.weights_layer_pack_size;
+ }
+ } else {
+ CHECK(memory_desc_init_by_tag(weights_md, rnn.is_fwd ? ldigo : ldgoi));
+ // Adjust strides for good leading dimension in GEMM
+ CHECK(set_good_strides(weights_md, rnn.is_fwd ? ldigo : ldgoi));
+ }
+ return status::success;
+}
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.hpp
new file mode 100644
index 0000000000..99eb787a64
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/rnn/rnn_utils.hpp
@@ -0,0 +1,225 @@
+/*******************************************************************************
+* Copyright 2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef RNN_UTILS_HPP
+#define RNN_UTILS_HPP
+
+#include "mkldnn.h"
+
+#include "cpu_rnn_pd.hpp"
+
+
+#define rnn_elemwise_sig(f) \
+ void f(const rnn_utils::rnn_conf_t &rnn, acc_data_t *ws_gates_, \
+ src_data_t *states_t_l_, float *c_states_t_l_, \
+ src_data_t *states_tm1_l_, float *c_states_tm1_l_, \
+ float *diff_states_t_l_, float *diff_states_t_lp1_, \
+ float *diff_states_tp1_l_, float *bias_, float *ws_grid_, \
+ float *ws_cell_) const
+
+#define rnn_cell_execution_sig(f) \
+ void f(const rnn_utils::rnn_conf_t &rnn, src_data_t *states_t_l_, \
+ float *c_states_t_l_, float *diff_states_t_l_, \
+ weights_data_t **w_layer_, weights_data_t **w_iter_, \
+ float **bias_, src_data_t *states_t_lm1_, \
+ src_data_t *states_tm1_l_, float *c_states_tm1_l_, \
+ float *diff_states_t_lp1_, float *diff_states_tp1_l_, \
+ float *diff_w_layer_, float *diff_w_iter_, float *diff_bias_, \
+ acc_data_t *ws_gates_, float *ws_grid_, float *ws_cell_) const
+
+#define rnn_grid_execution_sig(f) \
+ void f(const rnn_utils::rnn_conf_t &rnn, weights_data_t **weights_layer_, \
+ weights_data_t **weights_states_, float **bias_, \
+ src_data_t *ws_states_, float *ws_c_states_, \
+ float *ws_diff_states_, acc_data_t *ws_gates_, float *ws_cell_, \
+ float *ws_grid_, float *diff_weights_layer_, \
+ float *diff_weights_iter_, float *diff_bias_) const
+
+#define rnn_gemm_sig(f) \
+ void f(const char transA, const char transB, int m, int n, int k, \
+ const float alpha, const weights_data_t *a_, const int ldA, \
+ const src_data_t *b_, const int ldB, const float beta, \
+ acc_data_t *c_, const int ldC) const
+
+#define rnn_bias_prepare_sig(f) \
+ void f(const rnn_utils::rnn_conf_t &rnn, float **bias_, const float *b_, \
+ float *scratch_bias_) const
+
+#define rnn_bias_finalize_sig(f) \
+ void f(const rnn_utils::rnn_conf_t &rnn, float *scratch_bias_, \
+ const float *w_iter_comp, const float *w_layer_comp) const
+
+#define rnn_weights_assign_sig(f) \
+ void f(const rnn_utils::rnn_conf_t &rnn, const memory_desc_t *md, int nld, \
+ int ld, int OC_size, int IC_size, const int n_parts, \
+ const int *gates_per_part, const size_t *part_weights_pack_size, \
+ weights_data_t **weights_, const weights_data_t *w_, \
+ float **bias_, const float *b_, float *scratch_bias_) const
+
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+namespace rnn_utils {
+
+using namespace mkldnn::impl::utils;
+
+enum execution_direction_t {
+ l2r,
+ r2l,
+ bi_concat,
+ bi_sum,
+};
+
+enum data_type_conf_t {
+ all_f32,
+ u8u8u8f32,
+ f32u8f32f32,
+ u8u8u8u8,
+ f32u8f32u8
+};
+
+struct rnn_conf_t {
+ execution_direction_t exec_dir;
+ data_type_conf_t dt_conf;
+ int n_layer, n_iter, n_dir, n_gates, n_states;
+ int mb;
+ int slc, sic, dic, dlc;
+ int gates_ld, gates_nld, gates_ws_ld;
+ int n_parts_weights_layer, parts_weights_layer[MKLDNN_RNN_MAX_N_PARTS];
+ int n_parts_weights_iter, parts_weights_iter[MKLDNN_RNN_MAX_N_PARTS];
+ int n_bias, n_parts_bias, parts_bias[MKLDNN_RNN_MAX_N_PARTS];
+ size_t part_weights_iter_pack_size[MKLDNN_RNN_MAX_N_PARTS],
+ part_weights_layer_pack_size[MKLDNN_RNN_MAX_N_PARTS];
+ bool weights_layer_is_packed, weights_iter_is_packed;
+ /* Size of packed data in bytes */
+ size_t weights_layer_comp_offset, weights_layer_pack_size,
+ weights_iter_comp_offset, weights_iter_pack_size;
+
+ bool copy_bias;
+ int weights_layer_ld, weights_layer_nld;
+ int diff_weights_layer_ld, diff_weights_layer_nld;
+ int weights_iter_ld, weights_iter_nld;
+ int diff_weights_iter_ld, diff_weights_iter_nld;
+ int states_nld, states_ws_ld;
+ int weights_iter_compensation_size, weights_layer_compensation_size;
+ bool is_fwd, is_training, is_lbr;
+ bool use_workspace;
+
+ /* Size of workspace for each tensor in bytes */
+ size_t ws_gates_size, ws_states_size, ws_c_states_size, ws_diff_states_size,
+ ws_cell_comp_size, ws_grid_comp_size, ws_per_cell, ws_bias_size;
+ bool merge_gemm_iter, merge_gemm_layer, use_jit_gemm, use_layer_packed_gemm,
+ use_iter_packed_gemm;
+};
+
+bool is_ldigo(const memory_desc_wrapper &md);
+bool is_ldgoi(const memory_desc_wrapper &md);
+
+int get_good_ld(int dim, int sizeof_dt);
+
+void init_conf(rnn_conf_t &rnn, const rnn_desc_t &rd,
+ const memory_desc_wrapper &src_layer_d,
+ const memory_desc_wrapper &src_iter_d,
+ const memory_desc_wrapper &weights_layer_d,
+ const memory_desc_wrapper &weights_iter_d,
+ const memory_desc_wrapper &dst_layer_d);
+
+void set_conf(rnn_conf_t &rnn, const rnn_desc_t &rd,
+ const memory_desc_wrapper &weights_layer_d,
+ const memory_desc_wrapper &weights_iter_d,
+ const memory_desc_wrapper &diff_weights_layer_d,
+ const memory_desc_wrapper &diff_weights_iter_d);
+
+void set_offsets(const rnn_conf_t &rnn, size_t &ws_gates_offset,
+ size_t &ws_h_state_offset, size_t &ws_c_state_offset,
+ size_t &ws_diff_states_offset, size_t &ws_grid_comp_offset,
+ size_t &ws_cell_comp_offset, size_t &ws_bias_offset,
+ size_t &scratchpad_size, size_t &workspace_size);
+
+void get_scratchpad_and_workspace_sizes(const rnn_conf_t &rnn,
+ size_t &scratchpad_size, size_t &workspace_size);
+status_t set_expected_desc(
+ rnn_conf_t &rnn, memory_desc_t &weights_md, bool is_iter);
+status_t set_good_strides(memory_desc_t &weights_md, format_tag_t tag);
+
+template <typename T>
+struct ws_gates_aoc {
+ ws_gates_aoc(const rnn_conf_t &rnn, T *data)
+ : gates_(data, rnn.gates_nld, rnn.gates_ws_ld), DIC_(rnn.dic) {}
+ T &operator()(int batch, int gate, int dic) {
+ return gates_(batch, gate * DIC_ + dic);
+ }
+
+private:
+ mkldnn::impl::utils::array_offset_calculator<T, 2> gates_;
+ int DIC_;
+};
+using ws_gates_aoc_t = ws_gates_aoc<float>;
+using ws_gates_aoc_s32_t = ws_gates_aoc<int32_t>;
+
+struct bias_aoc_t {
+ bias_aoc_t(const rnn_conf_t &rnn, const float *data)
+ : bias_(data, rnn.n_bias, rnn.dic) {}
+ const float &operator()(int bias_n, int dic) { return bias_(bias_n, dic); }
+
+private:
+ mkldnn::impl::utils::array_offset_calculator<const float, 2> bias_;
+};
+
+template <typename T>
+struct ws_states_aoc {
+ ws_states_aoc(const rnn_conf_t &rnn, T *data)
+ : state_(data, rnn.states_nld, rnn.states_ws_ld) {}
+ T &operator()(int batch, int dic) { return state_(batch, dic); }
+
+private:
+ mkldnn::impl::utils::array_offset_calculator<T, 2> state_;
+};
+using ws_states_aoc_t = ws_states_aoc<float>;
+using ws_states_aoc_u8_t = ws_states_aoc<uint8_t>;
+
+struct ws_diff_states_aoc_t {
+ ws_diff_states_aoc_t(const rnn_conf_t &rnn, float *data)
+ : diff_states_(data, rnn.n_states + 1, rnn.n_iter + 1, rnn.states_nld,
+ rnn.states_ws_ld) {}
+ float &operator()(int state_n, int batch, int dic) {
+ return diff_states_(state_n, 0, batch, dic);
+ }
+
+private:
+ mkldnn::impl::utils::array_offset_calculator<float, 4> diff_states_;
+};
+
+struct ws_diff_w_iter_aoc_t {
+ ws_diff_w_iter_aoc_t(const rnn_conf_t &rnn, float *data)
+ : diff_weights_iter_(
+ data, rnn.diff_weights_iter_nld, rnn.diff_weights_iter_ld)
+ , DIC_(rnn.dic) {}
+ float &operator()(int sic, int gate, int dic) {
+ return diff_weights_iter_(sic, gate * DIC_ + dic);
+ }
+
+private:
+ mkldnn::impl::utils::array_offset_calculator<float, 2> diff_weights_iter_;
+ int DIC_;
+};
+}
+}
+}
+}
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.cpp
new file mode 100644
index 0000000000..0420f87aa5
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.cpp
@@ -0,0 +1,126 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn_thread.hpp"
+
+#include "simple_concat.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace memory_tracking::names;
+
+template <data_type_t data_type>
+status_t simple_concat_t<data_type>::execute(const exec_ctx_t &ctx) const {
+ auto scratchpad = this->scratchpad(ctx);
+ auto iptrs = scratchpad.template get<const data_t *>(key_concat_iptrs);
+ auto optrs = scratchpad.template get<data_t *>(key_concat_optrs);
+ auto nelems_to_copy = scratchpad.template get<dim_t>(key_concat_nelems);
+ auto is = scratchpad.template get<strides_t>(key_concat_istrides);
+
+ const int num_arrs = pd()->n_inputs();
+ const int *perm = pd()->perm_, *iperm = pd()->iperm_;
+ const int concat_dim = pd()->concat_dim();
+ auto o_base_ptr = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ for (int a = 0; a < num_arrs; ++a) {
+ const memory_desc_wrapper i_d(pd()->src_md(a));
+ const memory_desc_wrapper o_d(pd()->src_image_md(a));
+
+ iptrs[a] = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MULTIPLE_SRC + a)
+ + i_d.blk_off(0);
+ optrs[a] = o_base_ptr + o_d.blk_off(0);
+ nelems_to_copy[a] = pd()->nelems_to_concat(i_d);
+ for (int i = 0; i < MKLDNN_MAX_NDIMS; i++) {
+ if (i < perm[concat_dim])
+ is[a][i] = size_t(i_d.blocking_desc().strides[iperm[i]]);
+ else
+ is[a][i] = 0;
+ }
+ }
+
+ const memory_desc_wrapper o_d(pd()->src_image_md(0));
+
+ strides_t os = { 0 };
+ for (int i = 0; i < perm[concat_dim]; i++)
+ os[i] = o_d.blocking_desc().strides[iperm[i]];
+
+ dims_t phys_dims;
+ for (size_t i = 0; i < sizeof(phys_dims)/sizeof(phys_dims[0]); i++)
+ phys_dims[i] = (i < (size_t)perm[concat_dim])
+ ? o_d.dims()[iperm[i]] / pd()->blocks_[iperm[i]] : 1;
+
+ if (perm[concat_dim] == 0) {
+ for (int a = 0; a < num_arrs; ++a) {
+ const data_t *i = &iptrs[a][0];
+ data_t *o = &optrs[a][0];
+ parallel_nd((ptrdiff_t)nelems_to_copy[a],
+ [&](ptrdiff_t e) { o[e] = i[e]; });
+ }
+ } else {
+ parallel_nd(phys_dims[0], phys_dims[1], phys_dims[2], phys_dims[3],
+ phys_dims[4], num_arrs,
+ [&](dim_t n0, dim_t n1, dim_t n2, dim_t n3, dim_t n4, int a) {
+ // XXX: this code may access uninitialized values in is[*][0-4] --
+ // that's why we have to set them to zero although this is
+ // probably benign
+ size_t in_off = is[a][0] * n0 + is[a][1] * n1 + is[a][2] * n2
+ + is[a][3] * n3 + is[a][4] * n4;
+ size_t out_off = os[0] * n0 + os[1] * n1 + os[2] * n2
+ + os[3] * n3 + os[4] * n4;
+ const data_t *i = &iptrs[a][in_off];
+ data_t *o = &optrs[a][out_off];
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+ // The code below performs data copying: o[e] = i[e]
+ // and uses a workaround to make GNU compilers optimize it
+ uint8_t *ptro = reinterpret_cast<uint8_t *>(o);
+ const uint8_t *ptri = reinterpret_cast<const uint8_t *>(i);
+ const dim_t main_part =
+ nelems_to_copy[a] * sizeof(data_t) / sizeof(uint32_t);
+ const dim_t tail_part =
+ nelems_to_copy[a] % sizeof(data_t) / sizeof(uint32_t);
+
+ PRAGMA_OMP_SIMD()
+ for (dim_t e = 0; e < main_part; ++e) {
+ *(reinterpret_cast<uint32_t *>(ptro))
+ = *(reinterpret_cast<const uint32_t *>(ptri));
+ ptro += sizeof(uint32_t);
+ ptri += sizeof(uint32_t);
+ }
+ for (dim_t e = 0; e < tail_part; ++e) {
+ *ptro = *ptri;
+ ++ptro;
+ ++ptri;
+ }
+#else
+ PRAGMA_OMP_SIMD()
+ for (dim_t e = 0; e < nelems_to_copy[a]; ++e) o[e] = i[e];
+#endif
+ });
+ }
+
+ return status::success;
+}
+
+template struct simple_concat_t<data_type::f32>;
+template struct simple_concat_t<data_type::u8>;
+template struct simple_concat_t<data_type::s8>;
+template struct simple_concat_t<data_type::s32>;
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp
new file mode 100644
index 0000000000..5177275452
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_concat.hpp
@@ -0,0 +1,155 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef SIMPLE_CONCAT_HPP
+#define SIMPLE_CONCAT_HPP
+
+#include "memory_tracking.hpp"
+
+#include "cpu_concat_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <data_type_t data_type>
+struct simple_concat_t: public cpu_primitive_t {
+ struct pd_t: public cpu_concat_pd_t {
+ using cpu_concat_pd_t::cpu_concat_pd_t;
+
+ pd_t(const pd_t &rhs): cpu_concat_pd_t(rhs) {
+ int ndims = rhs.dst_md_.ndims;
+ utils::array_copy(perm_, rhs.perm_, ndims);
+ utils::array_copy(iperm_, rhs.iperm_, ndims);
+ utils::array_copy(blocks_, rhs.blocks_, ndims);
+ }
+
+ DECLARE_CONCAT_PD_T("simple:any", simple_concat_t);
+
+ status_t init() {
+ const memory_desc_wrapper dst_d(dst_md());
+ bool ok = true
+ && cpu_concat_pd_t::init() == status::success
+ && dst_d.ndims() <= 6;
+ if (!ok) return status::unimplemented;
+
+ for (size_t i = 0; i < src_mds_.size(); ++i) {
+ const memory_desc_wrapper i_d(&src_mds_[i]);
+ const memory_desc_wrapper o_d(&src_image_mds_[i]);
+
+ const int ignore_strides = 0;
+
+ ok = ok
+ && utils::everyone_is(data_type, i_d.data_type(),
+ o_d.data_type())
+ && utils::everyone_is(format_kind::blocked,
+ i_d.format_kind(), o_d.format_kind())
+ && types::blocking_desc_is_equal(i_d.blocking_desc(),
+ o_d.blocking_desc(), ignore_strides)
+ && types::blocking_desc_is_equal(i_d.blocking_desc(),
+ dst_d.blocking_desc(), ignore_strides)
+ && !i_d.is_additional_buffer();
+ if (!ok) return status::unimplemented;
+ }
+
+ dst_d.compute_blocks(blocks_);
+ format_perm();
+
+ // start dim is the first dimension after which the concatenation
+ // would happen contiguously
+ const int start_dim = perm_[concat_dim()];
+
+ // check that contiguous part is indeed contiguous (i.e. dense)
+ if (nelems_to_concat(dst_d) !=
+ dst_d.padded_dims()[concat_dim()] / blocks_[concat_dim()]
+ * dst_d.blocking_desc().strides[concat_dim()])
+ return status::unimplemented;
+
+ // check that all inputs have the same strides for the
+ // contiguous part [concat_dim .. ndims] for the *major* dims.
+ // the block part is already checked above
+ for (size_t i = 0; i < src_mds_.size(); ++i) {
+ const memory_desc_wrapper i_d(&src_mds_[i]);
+ for (int d = start_dim; d < dst_d.ndims(); ++d) {
+ if (dst_d.blocking_desc().strides[iperm_[d]]
+ != i_d.blocking_desc().strides[iperm_[d]])
+ return status::unimplemented;
+ }
+ }
+
+ init_scratchpad();
+
+ return status::success;
+ }
+
+ int perm_[MKLDNN_MAX_NDIMS];
+ int iperm_[MKLDNN_MAX_NDIMS];
+ dims_t blocks_;
+
+ dim_t nelems_to_concat(const memory_desc_wrapper &data_d) const {
+ const int ndims = data_d.ndims();
+
+ dim_t nelems = 1;
+ for (int i = perm_[concat_dim()]; i < ndims; i++)
+ nelems *= data_d.dims()[iperm_[i]] / blocks_[iperm_[i]];
+ for (int i = 0; i < ndims; i++)
+ nelems *= blocks_[i];
+
+ return nelems;
+ }
+
+ private:
+ void format_perm() {
+ const memory_desc_wrapper dst_d(dst_md());
+ const int ndims = dst_d.ndims();
+
+ strides_t strides;
+ utils::array_copy(strides, dst_d.blocking_desc().strides, ndims);
+ for (int i = 0; i < ndims; i++) iperm_[i] = i;
+
+ utils::simultaneous_sort(strides, iperm_, ndims,
+ [](stride_t a, stride_t b) { return b - a; });
+
+ for (int i = 0; i < ndims; i++) perm_[iperm_[i]] = i;
+ }
+
+ void init_scratchpad() {
+ using namespace memory_tracking::names;
+ auto scratchpad = scratchpad_registry().registrar();
+ scratchpad.book(key_concat_iptrs, sizeof(data_t *) * n_inputs());
+ scratchpad.book(key_concat_optrs, sizeof(data_t *) * n_inputs());
+ scratchpad.book(key_concat_nelems, sizeof(dim_t) * n_inputs());
+ scratchpad.book(key_concat_istrides,
+ sizeof(strides_t) * n_inputs());
+ }
+ };
+
+ simple_concat_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override;
+
+ typedef typename prec_traits<data_type>::type data_t;
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_q10n.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_q10n.hpp
new file mode 100644
index 0000000000..e6c3b8d7af
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_q10n.hpp
@@ -0,0 +1,98 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_SIMPLE_Q10N_HPP
+#define CPU_SIMPLE_Q10N_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "math_utils.hpp"
+#include "nstl.hpp"
+#include "type_helpers.hpp"
+#include "utils.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::math;
+
+template <typename out_t>
+inline out_t round_and_saturate(float f)
+{ return math::saturate<out_t>(out_round<int>(f)); }
+
+/* Quantization with alpha == 1 and beta == 0 */
+template <typename in_t, typename out_t, typename enabled = void>
+struct qz_a1b0 {
+ out_t operator()(in_t in)
+ { return round_and_saturate<out_t>((float)in); }
+};
+
+template <typename in_t, typename out_t>
+struct qz_a1b0<in_t, out_t,
+ typename utils::enable_if<true
+ && nstl::is_integral<in_t>::value
+ && !is_subset<in_t, out_t>::value
+ >::type> {
+ out_t operator()(in_t in) { return math::saturate<out_t>(in); }
+};
+
+template <typename in_t, typename out_t>
+struct qz_a1b0<in_t, out_t,
+ typename utils::enable_if<is_subset<in_t, out_t>::value>::type> {
+ out_t operator()(in_t in) { return (out_t)in; }
+};
+
+/* Quantization with alpha == 1 */
+template <typename in_t, typename out_t> struct qz_a1 {
+ out_t operator()(in_t in, out_t out, float beta)
+ { return round_and_saturate<out_t>((float)in + beta * out); }
+};
+
+template <typename in_t> struct qz_a1<in_t, float> {
+ float operator()(in_t in, float out, float beta)
+ { return (float)in + beta * out; }
+};
+
+/* Quantization with beta == 0 */
+template <typename in_t, typename out_t> struct qz_b0 {
+ out_t operator()(in_t in, float alpha)
+ { return round_and_saturate<out_t>(alpha * in); }
+};
+
+template <typename in_t> struct qz_b0<in_t, float> {
+ float operator()(in_t in, float alpha) { return alpha * in; }
+};
+
+/* Quantization */
+template <typename in_t, typename out_t> struct qz {
+ out_t operator()(in_t in, out_t out, float alpha, float beta) {
+ return round_and_saturate<out_t>(
+ alpha * in + (beta ? beta * out : 0));
+ }
+};
+
+template <typename in_t> struct qz<in_t, float> {
+ float operator()(in_t in, float out, float alpha, float beta)
+ { return alpha * in + (beta ? beta * out : 0); }
+};
+
+}
+}
+}
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_reorder.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_reorder.hpp
new file mode 100644
index 0000000000..ff845f5bd3
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_reorder.hpp
@@ -0,0 +1,1022 @@
+/*******************************************************************************
+* Copyright 2016-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef CPU_SIMPLE_REORDER_HPP
+#define CPU_SIMPLE_REORDER_HPP
+
+#include <assert.h>
+
+#include "c_types_map.hpp"
+#include "type_helpers.hpp"
+#include "math_utils.hpp"
+#include "mkldnn_thread.hpp"
+#include "utils.hpp"
+
+#include "tag_traits.hpp"
+#include "cpu_reorder_pd.hpp"
+#include "cpu_primitive.hpp"
+
+#include "simple_q10n.hpp"
+#include "cpu_isa_traits.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+using namespace mkldnn::impl::status;
+using namespace mkldnn::impl::format_tag;
+using namespace mkldnn::impl::data_type;
+
+using bd = block_dim_t;
+using ib = inner_blk_t;
+
+using namespace mkldnn::impl::utils;
+using math::saturate;
+
+template<impl::data_type_t type>
+using data_t = typename prec_traits<type>::type;
+
+template<impl::data_type_t type_i, impl::data_type_t type_o>
+using _qz_a1b0 = qz_a1b0<data_t<type_i>, data_t<type_o>>;
+
+template<impl::data_type_t type_i, impl::data_type_t type_o>
+using _qz = qz<data_t<type_i>, data_t<type_o>>;
+
+namespace fmt_order {
+ const bool keep = true;
+ const bool reverse = false;
+ const bool any = keep;
+}
+
+namespace spec {
+struct direct_copy {};
+struct direct_copy_except_dim_0 {};
+struct reference {};
+struct conv_s8s8 {};
+}
+
+#define SIMPLE_REORDER_TEMPL_DECL \
+ impl::data_type_t type_i, impl::format_tag_t tag_i, \
+ impl::data_type_t type_o, impl::format_tag_t tag_o, bool order_keep
+#define SIMPLE_REORDER_TEMPL_CALL \
+ type_i, tag_i, type_o, tag_o, order_keep
+
+#define DECLARE_COMMON_PARAMS() \
+ const memory_desc_wrapper &input_d = pd->src_md(); \
+ const memory_desc_wrapper &output_d = pd->dst_md(); \
+ const float alpha = pd->alpha(); MAYBE_UNUSED(alpha); \
+ const float beta = pd->beta(); MAYBE_UNUSED(beta);
+
+/* specific reorders: common template */
+template <SIMPLE_REORDER_TEMPL_DECL, typename spec = void>
+struct simple_reorder_impl {};
+
+namespace {
+inline bool simple_fmt_check(bool order_keep, impl::format_tag_t tag_i,
+ impl::format_tag_t tag_o, const memory_desc_wrapper &input_d,
+ const memory_desc_wrapper &output_d) {
+ return input_d.matches_tag(order_keep ? tag_i : tag_o)
+ && output_d.matches_tag(order_keep ? tag_o : tag_i);
+}
+inline bool simple_attr_check(const primitive_attr_t *attr, bool many_scales_support) {
+ if (many_scales_support)
+ return true;
+ return IMPLICATION(attr, attr->output_scales_.mask_ == 0);
+}
+}
+
+/* specific reorders: implementation */
+template <SIMPLE_REORDER_TEMPL_DECL>
+struct simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL,
+typename utils::enable_if<tag_i == any && (false
+ || tag_o == hwio
+ || tag_o == hwigo)
+ , spec::conv_s8s8>::type>
+{
+ static bool is_applicable(const memory_desc_wrapper &input_d,
+ const memory_desc_wrapper &output_d, const primitive_attr_t *attr)
+ {
+ const size_t D_mask = utils::array_product(input_d.dims(),
+ math::ilog2q(attr->output_scales_.mask_ + 1));
+ const int oc = (input_d.dims()[tag_o == hwigo + 0]);
+ const int g = (tag_o == hwigo) ? (input_d.dims()[0]) : 1;
+
+ return output_d.matches_tag(tag_o)
+ && (output_d.extra().flags & memory_extra_flags::compensation_conv_s8s8)
+ && (input_d.data_type() == f32 || input_d.data_type() == s8)
+ && output_d.data_type() == s8
+ && (D_mask == 1 || D_mask == (size_t)g * oc);
+ }
+
+ static status_t execute(const cpu_reorder_pd_t *pd,
+ const data_t<type_i> *input, data_t<type_o> *output) {
+ DECLARE_COMMON_PARAMS();
+
+ static constexpr bool w_groups = tag_o == hwigo;
+
+ const auto &dims = input_d.dims();
+ const auto &pdims = output_d.padded_dims();
+
+ const int G = w_groups ? dims[0] : 1;
+ const int OC = dims[w_groups + 0];
+ const int IC = dims[w_groups + 1];
+ const int H = dims[w_groups + 2];
+ const int W = dims[w_groups + 3];
+
+ const float *scales = pd->attr()->output_scales_.scales_;
+ const size_t D_mask = utils::array_product(input_d.dims(),
+ math::ilog2q(pd->attr()->output_scales_.mask_ + 1));
+
+ assert(output_d.extra().flags
+ & memory_extra_flags::compensation_conv_s8s8);
+ float adj_scale =
+ (output_d.extra().flags & memory_extra_flags::scale_adjust)
+ ? output_d.extra().scale_adjust : 1.f;
+
+ size_t offset = G * pdims[w_groups + 0] * pdims[w_groups + 1] * H * W;
+ int32_t *cp = reinterpret_cast<int32_t *>(output + offset);
+
+ parallel_nd(G, OC, [&](int g, int oc) {
+ cp[g * OC + oc] = 0;
+ for (int ic = 0; ic < IC; ic++)
+ for (int h = 0; h < H; h++)
+ for (int w = 0; w < W; w++) {
+ auto i = input[input_d.blk_off<!w_groups>(g, oc, ic, h, w)];
+ auto &o = output[output_d.blk_off<!w_groups>(g, oc, ic, h, w)];
+ const float s = scales[(D_mask == 1) ? 0 : g * OC + oc];
+
+ o = qz_b0<data_t<type_i>, data_t<type_o>>()(
+ i, s * adj_scale);
+ cp[g * OC + oc] -= (int32_t)o;
+ }
+ cp [g * OC + oc] *= 128;
+ });
+ return success;
+ }
+};
+
+template <SIMPLE_REORDER_TEMPL_DECL>
+struct simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL,
+ typename utils::enable_if<
+ (tag_i == goiw && tag_o == gOIw4i16o4i)
+ || (tag_i == oiw && tag_o == OIw4i16o4i)
+ || (tag_i == goihw && tag_o == gOIhw4i16o4i)
+ || (tag_i == oihw && tag_o == OIhw4i16o4i)
+ || (tag_i == goihw && tag_o == gOIhw2i8o4i)
+ || (tag_i == goihw && tag_o == gOIhw4o4i)
+ , spec::conv_s8s8>::type>
+{
+ static bool is_applicable(const memory_desc_wrapper &input_d,
+ const memory_desc_wrapper &output_d, const primitive_attr_t *attr)
+ {
+ const size_t D_mask = utils::array_product(input_d.dims(),
+ math::ilog2q(attr->output_scales_.mask_ + 1));
+ const bool w_groups = !utils::one_of(tag_o, OIw4i16o4i, OIhw4i16o4i);
+ const int oc = (input_d.dims()[w_groups ? 1 : 0]);
+ const int g = w_groups ? input_d.dims()[0] : 1;
+
+ return input_d.matches_tag(tag_i)
+ && output_d.matches_tag(tag_o)
+ && (output_d.extra().flags & memory_extra_flags::compensation_conv_s8s8)
+ && (input_d.data_type() == f32 || input_d.data_type() == s8)
+ && output_d.data_type() == s8
+ && (D_mask == 1 || D_mask == (size_t)g * oc);
+ }
+
+ static status_t execute(const cpu_reorder_pd_t *pd,
+ const data_t<type_i> *input, data_t<type_o> *output) {
+ DECLARE_COMMON_PARAMS();
+
+ static constexpr bool w_groups =
+ !utils::one_of(tag_o, OIw4i16o4i, OIhw4i16o4i);
+ constexpr int is_1d =
+ utils::one_of(tag_o, gOIw4i16o4i, OIw4i16o4i);
+ constexpr int blksize = tag_traits<tag_o>::inner_blks == ib::_4b4c
+ ? 4
+ : tag_traits<tag_o>::inner_blks == ib::_2c8b4c
+ ? 8
+ : 16;
+
+ const auto &_g_oihw_d = order_keep ? input_d : output_d;
+ const auto &dims = input_d.dims();
+ const auto &pdims = order_keep
+ ? output_d.padded_dims()
+ : input_d.padded_dims();
+
+ const int G = w_groups ? dims[0] : 1;
+ const int OC = dims[w_groups + 0];
+ const int NB_OC = pdims[w_groups + 0] / blksize;
+ const int IC = dims[w_groups + 1];
+ const int NB_IC = pdims[w_groups + 1] / blksize;
+ const int H = is_1d ? 1 : dims[w_groups + 2];
+ const int W = dims[w_groups + 3 - is_1d];
+
+ const float *scales = pd->attr()->output_scales_.scales_;
+ const size_t D_mask = utils::array_product(input_d.dims(),
+ math::ilog2q(pd->attr()->output_scales_.mask_ + 1));
+
+ assert(output_d.extra().flags
+ & memory_extra_flags::compensation_conv_s8s8);
+ float adj_scale =
+ (output_d.extra().flags & memory_extra_flags::scale_adjust)
+ ? output_d.extra().scale_adjust : 1.f;
+
+ auto ker = [&](const data_t<type_i> *inp, data_t<type_o> *out,
+ int32_t *c, const float *s, const int oc_block, const int ic_block) {
+# define index AB_or_BC_blk_off<tag_traits<tag_o>::inner_blks>
+
+ for (int ic = 0; ic < ic_block; ++ic) {
+ for (int oc = 0; oc < oc_block; ++oc) {
+ const auto _g_oihw_off =
+ oc * _g_oihw_d.blocking_desc().strides[w_groups + 0]
+ + ic * _g_oihw_d.blocking_desc().strides[w_groups + 1];
+ out[index(oc, ic)]
+ = qz_b0<data_t<type_i>, data_t<type_o>>()(
+ inp[_g_oihw_off], s[oc] * adj_scale);
+ c[oc] -= (128 * (int32_t)(out[index(oc, ic)]));
+ }
+ }
+# undef index
+ };
+
+ constexpr int i_mult = blksize;
+ constexpr int o_mult = 1;
+
+ size_t offset = G * pdims[w_groups+0] * pdims[w_groups+1] * H * W;
+ int32_t *cp = reinterpret_cast<int32_t *>(output + offset);
+ parallel_nd(G * NB_OC * blksize, [&](int i) {
+ cp[i] = 0;
+ });
+
+# define wei_blk_off(md, g, o, i, h, w) \
+ (is_1d ? (md).blk_off<!w_groups>(g, o, i, w) \
+ : (md).blk_off<!w_groups>(g, o, i, h, w))
+
+ parallel_nd(G, NB_OC, [&](int g, int O) {
+ for (int I = 0; I < NB_IC; I++)
+ for (int h = 0; h < H; h++)
+ for (int w = 0; w < W; w++) {
+ auto i = &input[wei_blk_off(
+ input_d, g, i_mult * O, i_mult * I, h, w)];
+ auto o = &output[wei_blk_off(
+ output_d, g, o_mult * O, o_mult * I, h, w)];
+ const int oc_block = nstl::min(blksize, OC - O * blksize);
+ const int ic_block = nstl::min(blksize, IC - I * blksize);
+
+ int _offset = (g * NB_OC + O) * blksize;
+ ker(i, o, (order_keep) ? &cp[_offset] : nullptr,
+ &scales[(D_mask == 1) ? 0 : _offset],
+ oc_block, ic_block);
+ }
+ });
+
+# undef wei_blk_off
+
+ return success;
+ }
+};
+
+template <SIMPLE_REORDER_TEMPL_DECL>
+struct simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL,
+ typename utils::enable_if<false
+ ||(tag_i == goiw && tag_o == Goiw16g)
+ ||(tag_i == goihw && tag_o == Goihw16g)
+ , spec::conv_s8s8>::type>
+{
+ static bool is_applicable(const memory_desc_wrapper &input_d,
+ const memory_desc_wrapper &output_d, const primitive_attr_t *attr) {
+ const size_t D_mask = utils::array_product(input_d.dims(),
+ math::ilog2q(attr->output_scales_.mask_ + 1));
+ const int oc = input_d.dims()[1];
+ const int g = input_d.dims()[0];
+
+ return true
+ && order_keep
+ && input_d.matches_tag(tag_i)
+ && output_d.matches_tag(tag_o)
+ && (output_d.extra().flags & memory_extra_flags::compensation_conv_s8s8)
+ && (input_d.data_type() == f32 || input_d.data_type() == s8)
+ && output_d.data_type() == s8
+ && (D_mask == 1 || D_mask == (size_t)g * oc);
+ }
+
+ static status_t execute(const cpu_reorder_pd_t *pd,
+ const data_t<type_i> *input, data_t<type_o> *output) {
+ DECLARE_COMMON_PARAMS();
+
+ constexpr bool is_1d = tag_i == goiw;
+ constexpr int blksize = 16;
+
+ const auto &dims = input_d.dims();
+ const auto &pdims = output_d.padded_dims();
+ const int G = dims[0];
+ const int Gp = pdims[0];
+ const int OC = dims[1];
+ const int IC = dims[2];
+ const int H = is_1d ? 1 : dims[3];
+ const int W = dims[4 - is_1d];
+
+ const size_t D_mask = utils::array_product(input_d.dims(),
+ math::ilog2q(pd->attr()->output_scales_.mask_ + 1));
+ const float *scales = pd->attr()->output_scales_.scales_;
+
+ assert(output_d.extra().flags
+ & memory_extra_flags::compensation_conv_s8s8);
+ float adj_scale =
+ (output_d.extra().flags & memory_extra_flags::scale_adjust)
+ ? output_d.extra().scale_adjust : 1.f;
+
+ auto ker = [&](const data_t<type_i> *inp, data_t<type_o> *out,
+ int32_t *cp, const float *s, const int g_block) {
+ PRAGMA_OMP_SIMD()
+ for (int g = 0; g < g_block; g++) {
+ const auto i_off = g * input_d.blocking_desc().strides[0];
+ out[g] = qz_b0<data_t<type_i>, data_t<type_o>>()(
+ inp[i_off], s[g * OC] * adj_scale);
+ cp[g * OC] -= 128 * (int32_t)(out[g]);
+ }
+ };
+
+ size_t cp_offset = output_d.size() - output_d.additional_buffer_size();
+ int32_t *cp = reinterpret_cast<int32_t *>(output + cp_offset);
+ parallel_nd((Gp/blksize) * OC, [&](int ib) {
+ PRAGMA_OMP_SIMD()
+ for (int i = 0; i < blksize; i++)
+ cp[ib * blksize + i] = 0;
+ });
+
+# define wei_blk_off(md, g, o, i, h, w) \
+ (is_1d ? (md).blk_off(g, o, i, w) : (md).blk_off(g, o, i, h, w))
+
+ parallel_nd(Gp/blksize, OC, [&](int gb, int O) {
+ for (int I = 0; I < IC; I++) {
+ for (int h = 0; h < H; h++)
+ for (int w = 0; w < W; w++)
+ {
+ const int g_block = nstl::min(G - gb * blksize, blksize);
+ const auto inp = &input[wei_blk_off(
+ input_d, gb * blksize, O, I, h, w)];
+ const auto out = &output[wei_blk_off(
+ output_d, gb, O, I, h, w)];
+ int offset = gb * blksize + O;
+ ker(inp, out, &cp[offset],
+ &scales[(D_mask == 1) ? 0 : offset], g_block);
+ }
+ }
+ });
+
+# undef wei_blk_off
+
+ return success;
+ }
+};
+
+/* reorders with tail support */
+
+template <SIMPLE_REORDER_TEMPL_DECL>
+struct simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL,
+typename utils::enable_if<false
+ || (tag_i == nCdhw8c && tag_o == nCdhw16c)
+ || (tag_i == nChw8c && tag_o == nChw16c)
+ || (tag_i == nCw8c && tag_o == nCw16c)
+ >::type>
+{
+ static bool is_applicable(const memory_desc_wrapper &input_d,
+ const memory_desc_wrapper &output_d, const primitive_attr_t *attr)
+ {
+ return simple_fmt_check(order_keep, tag_i, tag_o, input_d, output_d)
+ && simple_attr_check(attr, false);
+ }
+
+ static status_t execute(const cpu_reorder_pd_t *pd,
+ const data_t<type_i> *input, data_t<type_o> *output) {
+ DECLARE_COMMON_PARAMS();
+
+ constexpr int is_1d = tag_i == nCw8c;
+ constexpr int is_3d = tag_i == nCdhw8c;
+ constexpr int blksize_16 = 16;
+ constexpr int blksize_8 = 8;
+ constexpr int ic_mult = order_keep ? 2 : 1;
+ constexpr int oc_mult = order_keep ? 1 : 2;
+
+ const auto &dims = input_d.dims();
+ const auto &pdims = order_keep ? output_d.padded_dims()
+ : input_d.padded_dims();
+
+ const int C = dims[1];
+ const int D = is_3d ? dims[2] : 1;
+ const int H = is_1d ? 1 : dims[2 + is_3d];
+ const int W = dims[3 + is_3d - is_1d];
+
+ auto ker = [&](const data_t<type_i> *i, data_t<type_o> *o,
+ const int block_16) {
+ const int nb = (block_16 - 1) / blksize_8 + 1;
+ if (alpha == 1.0 && beta == 0.0) {
+ for (int b = 0; b < nb; ++b) {
+ const ptrdiff_t i_off = order_keep ? b : b * blksize_8;
+ const ptrdiff_t o_off = order_keep ? b * blksize_8 : b;
+ const int block_8 = nstl::min(blksize_8,
+ block_16 - b * blksize_8);
+ for (int c = 0; c < block_8; ++c) {
+ o[o_off + c] = _qz_a1b0<type_i, type_o>()(
+ i[i_off + c]);
+ }
+ }
+ } else {
+ for (int b = 0; b < nb; ++b) {
+ const ptrdiff_t i_off = order_keep ? b : b * blksize_8;
+ const ptrdiff_t o_off = order_keep ? b * blksize_8 : b;
+ const int block_8 = nstl::min(blksize_8,
+ block_16 - b * blksize_8);
+ for (int c = 0; c < block_8; ++c) {
+ o[o_off + c] = _qz<type_i, type_o>()(i[i_off + c],
+ o[o_off + c], alpha, beta);
+ }
+ }
+ }
+ };
+
+# define data_blk_off(md, n, c, d, h, w) \
+ ( is_1d ? (md).blk_off(n, c, w) \
+ : is_3d ? (md).blk_off(n, c, d, h, w) : (md).blk_off(n, c, h, w))
+
+ parallel_nd(dims[0], pdims[1] / blksize_16, D, H, W,
+ [&](int n, int nb_c, int d, int h, int w) {
+ auto i = &input[data_blk_off(input_d, n, ic_mult * nb_c, d, h, w)];
+ auto o = &output[data_blk_off(output_d, n, oc_mult * nb_c, d, h, w)];
+ const int block_16 = nstl::min(blksize_16, C - nb_c * blksize_16);
+ ker(i, o, block_16);
+ });
+
+# undef data_blk_off
+
+ return success;
+ }
+};
+
+#define PLAIN_TO_BLOCKED_IS_APPLICABLE() \
+ static bool is_applicable(const memory_desc_wrapper &input_d, \
+ const memory_desc_wrapper &output_d, const primitive_attr_t *attr) { \
+ return simple_attr_check(attr, false) && (order_keep \
+ ? output_d.matches_tag(tag_o) && input_d.is_plain() \
+ : input_d.matches_tag(tag_o) && output_d.is_plain()); \
+ }
+
+template <SIMPLE_REORDER_TEMPL_DECL>
+struct simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL,
+typename utils::enable_if<tag_i == any
+ && (tag_traits<tag_o>::block_dims == bd::_A
+ || tag_traits<tag_o>::block_dims == bd::_B)
+ && tag_traits<tag_o>::ndims >= 3
+ && tag_traits<tag_o>::ndims <= 6
+ >::type>
+{
+ PLAIN_TO_BLOCKED_IS_APPLICABLE();
+
+ static status_t execute(const cpu_reorder_pd_t *pd,
+ const data_t<type_i> *input, data_t<type_o> *output) {
+ DECLARE_COMMON_PARAMS();
+
+ const auto &flat_d = order_keep ? input_d : output_d;
+ const auto &block_d = order_keep ? output_d : input_d;
+ const auto &dims = input_d.dims();
+ const auto &pdims = block_d.padded_dims();
+
+ constexpr int ndims = tag_traits<tag_o>::ndims;
+ constexpr int blk_idx = tag_traits<tag_o>::block_dims == bd::_A ? 0 : 1;
+
+ const dim_t H0 = dims[0];
+ const dim_t H1 = dims[1];
+ const dim_t M0 = ndims >= 6 ? dims[ndims - 4] : 1;
+ const dim_t M1 = ndims >= 5 ? dims[ndims - 3] : 1;
+ const dim_t M2 = ndims >= 4 ? dims[ndims - 2] : 1;
+ const dim_t L = dims[ndims - 1];
+ const dim_t l_blk_stride = block_d.blocking_desc().strides[ndims - 1];
+
+ constexpr int blksize = false ? 0
+ : utils::one_of(tag_traits<tag_o>::inner_blks, ib::_4a, ib::_4b) ? 4
+ : utils::one_of(tag_traits<tag_o>::inner_blks, ib::_8a, ib::_8b) ? 8
+ : 16;
+
+ auto ker = [&](const data_t<type_i> *i, data_t<type_o> *o, int block) {
+ if (alpha == 1.0 && beta == 0.0) {
+ for (int l = 0; l < L; ++l)
+ for (int blk = 0; blk < block; ++blk) {
+ const dim_t flat_off = 0
+ + blk * flat_d.blocking_desc().strides[blk_idx]
+ + l * flat_d.blocking_desc().strides[ndims - 1];
+ if (order_keep) {
+ o[l * l_blk_stride + blk] = _qz_a1b0<type_i, type_o>()(
+ i[flat_off]);
+ } else {
+ o[flat_off] = _qz_a1b0<type_i, type_o>()(
+ i[l * l_blk_stride + blk]);
+ }
+ }
+ } else {
+ for (int l = 0; l < L; ++l)
+ for (int blk = 0; blk < block; ++blk) {
+ const dim_t flat_off = 0
+ + blk * flat_d.blocking_desc().strides[blk_idx]
+ + l * flat_d.blocking_desc().strides[ndims - 1];
+ if (order_keep) {
+ o[l * l_blk_stride + blk] = _qz<type_i, type_o>()(
+ i[flat_off], o[l * blksize + blk],
+ alpha, beta);
+ } else {
+ o[flat_off] = _qz<type_i, type_o>()(
+ i[l * l_blk_stride + blk], o[flat_off],
+ alpha, beta);
+ }
+ }
+ }
+ };
+
+# define off(md, h0, h1, m0, m1, m2) \
+ (ndims >= 6 ? (md).blk_off(h0, h1, m0, m1, m2) \
+ : ndims >= 5 ? (md).blk_off(h0, h1, m1, m2) \
+ : ndims >= 4 ? (md).blk_off(h0, h1, m2) \
+ : /* ndims >= 3 ? */ (md).blk_off(h0, h1))
+
+ constexpr int i_mult = order_keep ? blksize : 1;
+ constexpr int o_mult = order_keep ? 1 : blksize;
+
+ if (blk_idx == 0) {
+ const dim_t BH0 = pdims[0] / blksize;
+ parallel_nd(BH0, H1, M0, M1, M2,
+ [&](dim_t bh0, dim_t h1, dim_t m0, dim_t m1, dim_t m2) {
+ auto i = &input[off(input_d, bh0 * i_mult, h1, m0, m1, m2)];
+ auto o = &output[off(output_d, bh0 * o_mult, h1, m0, m1, m2)];
+ const int block = nstl::min<int>(blksize, H0 - bh0 * blksize);
+ ker(i, o, block);
+ });
+ } else if (blk_idx == 1) {
+ const dim_t BH1 = pdims[1] / blksize;
+ parallel_nd(H0, BH1, M0, M1, M2,
+ [&](dim_t h0, dim_t bh1, dim_t m0, dim_t m1, dim_t m2) {
+ auto i = &input[off(input_d, h0, bh1 * i_mult, m0, m1, m2)];
+ auto o = &output[off(output_d, h0, bh1 * o_mult, m0, m1, m2)];
+ const int block = nstl::min<int>(blksize, H1 - bh1 * blksize);
+ ker(i, o, block);
+ });
+ } else {
+ assert(!"unimplemented");
+ }
+
+# undef off
+
+ return success;
+ }
+};
+
+template <SIMPLE_REORDER_TEMPL_DECL>
+struct simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL,
+typename utils::enable_if<tag_i == any
+ && (tag_traits<tag_o>::block_dims == bd::_AB
+ || tag_traits<tag_o>::block_dims == bd::_BC)
+ && IMPLICATION(tag_traits<tag_o>::block_dims == bd::_AB,
+ tag_traits<tag_o>::ndims >= 3 && tag_traits<tag_o>::ndims <= 5)
+ && IMPLICATION(tag_traits<tag_o>::block_dims == bd::_BC,
+ tag_traits<tag_o>::ndims >= 4 && tag_traits<tag_o>::ndims <= 6)
+ >::type>
+{
+ PLAIN_TO_BLOCKED_IS_APPLICABLE();
+
+ static status_t execute(const cpu_reorder_pd_t *pd,
+ const data_t<type_i> *input, data_t<type_o> *output) {
+ DECLARE_COMMON_PARAMS();
+
+ const auto &flat_d = order_keep ? input_d : output_d;
+ const auto &dims = input_d.dims();
+ const auto &pdims = order_keep
+ ? output_d.padded_dims()
+ : input_d.padded_dims();
+
+ constexpr int ndims = tag_traits<tag_o>::ndims;
+
+ static constexpr bool with_g = tag_traits<tag_o>::block_dims == bd::_BC;
+ const dim_t G = with_g ? dims[0] : 1;
+
+ const dim_t H0 = dims[0 + with_g];
+ const dim_t H1 = dims[1 + with_g];
+
+ const dim_t M0 = ndims >= 5 + with_g ? dims[ndims - 3] : 1;
+ const dim_t M1 = ndims >= 4 + with_g ? dims[ndims - 2] : 1;
+ const dim_t M2 = ndims >= 3 + with_g ? dims[ndims - 1] : 1;
+
+ constexpr int blksize_0 = false ? 0
+ : utils::one_of(tag_traits<tag_o>::inner_blks,
+ ib::_4b4a, ib::_4b4c, ib::_4c4b)
+ ? 4
+ : utils::one_of(tag_traits<tag_o>::inner_blks,
+ ib::_8a8b, ib::_8b8a, ib::_8b8c, ib::_8c8b, ib::_2c8b4c)
+ ? 8
+ : utils::one_of(tag_traits<tag_o>::inner_blks,
+ ib::_16a16b, ib::_16a4b, ib::_16b16a, ib::_16b4c,
+ ib::_16b16c, ib::_16c16b, ib::_8a16b2a, ib::_4b16a4b,
+ ib::_8b16a2b, ib::_8b16c2b, ib::_4c16b4c, ib::_8c16b2c)
+ ? 16 : INT_MIN;
+
+ constexpr int blksize_1 = utils::one_of(tag_traits<tag_o>::inner_blks,
+ ib::_8a8b, ib::_8b8a, ib::_8b8c, ib::_8c8b, ib::_2c8b4c)
+ ? 8
+ : utils::one_of(tag_traits<tag_o>::inner_blks,
+ ib::_16a16b, ib::_16b16a, ib::_16b16c, ib::_16c16b,
+ ib::_8a16b2a, ib::_4b16a4b, ib::_8b16a2b, ib::_8b16c2b,
+ ib::_4c16b4c, ib::_8c16b2c)
+ ? 16
+ : utils::one_of(tag_traits<tag_o>::inner_blks,
+ ib::_4b4a, ib::_4b4c, ib::_4c4b,
+ ib::_16a4b, ib::_16b4c)
+ ? 4
+ : INT_MIN;
+
+ const dim_t NB_H0 = pdims[0 + with_g] / blksize_0;
+ const dim_t NB_H1 = pdims[1 + with_g] / blksize_1;
+
+ auto ker = [&](const data_t<type_i> *i, data_t<type_o> *o,
+ const int block_h0, const int block_h1) {
+# define blk_off AB_or_BC_blk_off<tag_traits<tag_o>::inner_blks>
+
+ if (alpha == 1.0 && beta == 0.0) {
+ for (int h0 = 0; h0 < block_h0; ++h0)
+ for (int h1 = 0; h1 < block_h1; ++h1) {
+ const dim_t flat_off = 0
+ + h0 * flat_d.blocking_desc().strides[with_g + 0]
+ + h1 * flat_d.blocking_desc().strides[with_g + 1];
+ if (order_keep) {
+ o[blk_off(h0, h1)] = _qz_a1b0<type_i, type_o>()(
+ i[flat_off]);
+ } else {
+ o[flat_off] = _qz_a1b0<type_i, type_o>()(
+ i[blk_off(h0, h1)]);
+ }
+ }
+ } else {
+ for (int h0 = 0; h0 < block_h0; ++h0)
+ for (int h1 = 0; h1 < block_h1; ++h1) {
+ const dim_t flat_off = 0
+ + h0 * flat_d.blocking_desc().strides[with_g + 0]
+ + h1 * flat_d.blocking_desc().strides[with_g + 1];
+ if (order_keep) {
+ o[blk_off(h0, h1)] = _qz<type_i, type_o>()(i[flat_off],
+ o[blk_off(h0, h1)], alpha, beta);
+ } else {
+ o[flat_off] = _qz<type_i, type_o>()(i[blk_off(h0, h1)],
+ o[flat_off], alpha, beta);
+ }
+ }
+ }
+
+# undef blk_off
+ };
+
+ constexpr int i_mult_0 = order_keep ? blksize_0 : 1;
+ constexpr int o_mult_0 = order_keep ? 1 : blksize_0;
+
+ constexpr int i_mult_1 = order_keep ? blksize_1 : 1;
+ constexpr int o_mult_1 = order_keep ? 1 : blksize_1;
+
+# define off(md, g, h0, h1, m0, m1, m2) \
+ (ndims >= 5 + with_g ? (md).blk_off<!with_g>(g, h0, h1, m0, m1, m2) \
+ : ndims >= 4 + with_g ? (md).blk_off<!with_g>(g, h0, h1, m1, m2) \
+ : /* ndims >= 3 + with_g ? */ (md).blk_off<!with_g>(g, h0, h1, m2))
+
+ parallel_nd(G, NB_H0, NB_H1, M0, M1, M2,
+ [&](dim_t g, dim_t nb_h0, dim_t nb_h1, dim_t m0, dim_t m1, dim_t m2) {
+ auto i = &input[off(input_d,
+ g, i_mult_0 * nb_h0, i_mult_1 * nb_h1, m0, m1, m2)];
+ auto o = &output[off(output_d,
+ g, o_mult_0 * nb_h0, o_mult_1 * nb_h1, m0, m1, m2)];
+ const int block_h0 = nstl::min<int>(blksize_0, H0 - nb_h0 * blksize_0);
+ const int block_h1 = nstl::min<int>(blksize_1, H1 - nb_h1 * blksize_1);
+ ker(i, o, block_h0, block_h1);
+ });
+
+# undef off
+
+ return success;
+ }
+};
+
+/* generic and direct-copy reorders */
+
+template <SIMPLE_REORDER_TEMPL_DECL>
+struct simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL,
+ typename utils::enable_if<
+ tag_i == any && tag_o == any && order_keep == fmt_order::any,
+ spec::direct_copy>::type>
+{
+ static bool is_applicable(const memory_desc_wrapper &input_d,
+ const memory_desc_wrapper &output_d, const primitive_attr_t *attr) {
+ /* FIXME: is the formula correct? */
+ return input_d.similar_to(output_d, true, false, 0)
+ && input_d.is_dense() && output_d.is_dense()
+ && simple_attr_check(attr, false);
+ }
+
+ static status_t execute(const cpu_reorder_pd_t *pd,
+ const data_t<type_i> *input, data_t<type_o> *output) {
+ DECLARE_COMMON_PARAMS();
+
+ assert(input_d.is_dense());
+
+ input += input_d.blk_off(0);
+ output += output_d.blk_off(0);
+
+ const size_t nelems = input_d.nelems();
+
+ constexpr int block_size = 16;
+ const auto num_blocks = nelems / block_size;
+ const auto rem_elems = nelems % block_size;
+
+ parallel(0, [&](const int ithr, const int nthr) {
+ size_t start{0}, end{0};
+ balance211(num_blocks, nthr, ithr, start, end);
+ start = start * block_size;
+ end = end * block_size;
+
+ if (alpha == 1.0 && beta == 0.0) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start; e < end; ++e) {
+ output[e] = qz_a1b0<data_t<type_i>, data_t<type_o>>()
+ (input[e]);
+ }
+ } else if (alpha == 1.0) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start; e < end; ++e) {
+ output[e] = qz_a1<data_t<type_i>, data_t<type_o>>()
+ (input[e], output[e], beta);
+ }
+ } else if (beta == 0.0) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start; e < end; ++e) {
+ output[e] = qz_b0<data_t<type_i>, data_t<type_o>>()
+ (input[e], alpha);
+ }
+ } else {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start; e < end; ++e) {
+ output[e] = qz<data_t<type_i>, data_t<type_o>>()
+ (input[e], output[e], alpha, beta);
+ }
+ }
+
+ if (rem_elems != 0 && ithr == nthr - 1){
+ if (alpha == 1.0 && beta == 0.0) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = nelems - rem_elems; e < nelems; ++e) {
+ output[e] = qz_a1b0<data_t<type_i>,
+ data_t<type_o>>()(input[e]);
+ }
+ } else if (alpha == 1.0) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = nelems - rem_elems; e < nelems; ++e) {
+ output[e] = qz_a1<data_t<type_i>,
+ data_t<type_o>>()(input[e], output[e], beta);
+ }
+ } else if (beta == 0.0) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = nelems - rem_elems; e < nelems; ++e) {
+ output[e] = qz_b0<data_t<type_i>,
+ data_t<type_o>>()(input[e], alpha);
+ }
+ } else {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = nelems - rem_elems; e < nelems; ++e) {
+ output[e] = qz<data_t<type_i>, data_t<type_o>>()
+ (input[e], output[e], alpha, beta);
+ }
+ }
+ }
+ });
+ return success;
+ }
+};
+
+template <SIMPLE_REORDER_TEMPL_DECL>
+struct simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL,
+ typename utils::enable_if<
+ tag_i == any && tag_o == any && order_keep == fmt_order::any,
+ spec::direct_copy_except_dim_0>::type>
+{
+ static bool is_applicable(const memory_desc_wrapper &input_d,
+ const memory_desc_wrapper &output_d, const primitive_attr_t *attr) {
+ auto is_dense_no_0 = [](const memory_desc_wrapper &data_d) {
+ return nelems_no_dim_0(data_d) == _size_no_dim_0(data_d);
+ };
+ /* FIXME: is the formula correct? */
+ return input_d.similar_to(output_d, true, false, 1)
+ && is_dense_no_0(input_d) && is_dense_no_0(output_d)
+ && simple_attr_check(attr, false);
+ }
+
+ static status_t execute(const cpu_reorder_pd_t *pd,
+ const data_t<type_i> *input, data_t<type_o> *output) {
+ DECLARE_COMMON_PARAMS();
+
+ input += input_d.blk_off(0);
+ output += output_d.blk_off(0);
+
+ const int N = input_d.dims()[0];
+ const dim_t is = input_d.blocking_desc().strides[0];
+ const dim_t os = output_d.blocking_desc().strides[0];
+ const dim_t nelems_no_d0 = nelems_no_dim_0(input_d);
+ const dim_t work_amount = N * nelems_no_d0;
+
+ if (alpha == 1.0 && beta == 0.0) {
+ parallel(0, [&](const int ithr, const int nthr) {
+ dim_t n{0}, dim1_s{0};
+ dim_t start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+ nd_iterator_init(start, n, N, dim1_s, nelems_no_d0);
+ while(start < end) {
+ dim_t work_rem = end - start;
+ dim_t dim1_e = dim1_s + work_rem > nelems_no_d0
+ ? nelems_no_d0 : dim1_s + work_rem;
+ PRAGMA_OMP_SIMD()
+ for (dim_t e = dim1_s; e < dim1_e; ++e) {
+ output[os * n + e] = _qz_a1b0<type_i, type_o>()(
+ input[is * n + e]);
+ }
+ nd_iterator_jump(start, end, n, N, dim1_s, nelems_no_d0);
+ }
+ });
+ } else {
+ parallel(0, [&](const int ithr, const int nthr) {
+ dim_t n{0}, dim1_s{0};
+ dim_t start{0}, end{0};
+ balance211(work_amount, nthr, ithr, start, end);
+ nd_iterator_init(start, n, N, dim1_s, nelems_no_d0);
+ while(start < end) {
+ dim_t work_rem = end - start;
+ dim_t dim1_e =
+ dim1_s + work_rem > nelems_no_d0 ? nelems_no_d0
+ : dim1_s + work_rem;
+ PRAGMA_OMP_SIMD()
+ for (dim_t e = dim1_s; e < dim1_e; ++e){
+ output[os * n + e] = _qz<type_i, type_o>()(
+ input[is * n + e], output[os * n + e], alpha,
+ beta);
+ }
+ nd_iterator_jump(start, end, n, N, dim1_s, nelems_no_d0);
+ }
+ });
+ }
+
+ return success;
+ }
+
+private:
+ static dim_t nelems_no_dim_0(const memory_desc_wrapper &data_d) {
+ const int ndims = data_d.ndims();
+ if (ndims <= 1) return 1;
+ return utils::array_product(data_d.dims() + 1, data_d.ndims() - 1);
+ }
+
+ static dim_t _size_no_dim_0(const memory_desc_wrapper &data_d) {
+ dims_t blocks;
+ data_d.compute_blocks(blocks);
+
+ const auto &blk = data_d.blocking_desc();
+
+ dim_t blk_size = 1;
+ for (int iblk = 0; iblk < blk.inner_nblks; ++iblk)
+ blk_size *= blk.inner_blks[iblk];
+
+ dim_t max_size = blk_size;
+ for (int d = 1; d < data_d.ndims(); ++d) {
+ max_size = nstl::max(max_size,
+ data_d.padded_dims()[d] / blocks[d] * blk.strides[d]);
+ }
+
+ return max_size;
+ }
+};
+
+template <SIMPLE_REORDER_TEMPL_DECL>
+struct simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL,
+ typename utils::enable_if<
+ tag_i == any && tag_o == any && order_keep == fmt_order::any,
+ spec::reference>::type>
+{
+ static bool is_applicable(const memory_desc_wrapper &input_d,
+ const memory_desc_wrapper &output_d, const primitive_attr_t *attr) {
+ /* supported smask: 0x0...011..10...0,
+ * i.e. 1 should be contiguous */
+ int smask = attr ? attr->output_scales_.mask_ : 0;
+ for (; smask > 0 && !(smask & 0x1); smask >>= 1);
+ for (; smask > 0 && smask & 0x1; smask >>= 1);
+ return true
+ && input_d.is_blocking_desc()
+ && output_d.is_blocking_desc()
+ && !output_d.is_additional_buffer()
+ && !input_d.is_additional_buffer()
+ && smask == 0;
+ }
+
+ static status_t execute(const cpu_reorder_pd_t *pd,
+ const data_t<type_i> *input, data_t<type_o> *output) {
+ DECLARE_COMMON_PARAMS();
+
+ const size_t nelems = input_d.nelems();
+
+ int ndims_start = 0, ndims_mask = 0;
+ int smask = pd->attr()->output_scales_.mask_;
+ for (; smask > 0 && !(smask & 0x1); smask >>= 1) ++ndims_start;
+ for (; smask > 0 && smask & 0x1; smask >>= 1) ++ndims_mask;
+ assert(smask == 0);
+
+ const ptrdiff_t D_start
+ = utils::array_product(input_d.dims(), ndims_start);
+ const ptrdiff_t D_mask
+ = utils::array_product(input_d.dims() + ndims_start, ndims_mask);
+ const ptrdiff_t D_rest = nelems / D_start / D_mask;
+
+ const float *scales = pd->attr()->output_scales_.scales_;
+
+ parallel_nd(D_start, D_mask, D_rest,
+ [&](ptrdiff_t ds, ptrdiff_t dm, ptrdiff_t dr) {
+ const float scale = scales[dm];
+
+ const size_t e = (ds * D_mask + dm) * D_rest + dr;
+ const auto &i = input[input_d.off_l(e)];
+ auto &o = output[output_d.off_l(e)];
+
+ o = _qz<type_i, type_o>()(i, o, scale, beta);
+ });
+
+ return success;
+ }
+};
+
+
+/* high level class declaration */
+
+template <SIMPLE_REORDER_TEMPL_DECL, typename spec = void>
+struct simple_reorder_t: public cpu_primitive_t {
+ struct pd_t: public cpu_reorder_pd_t {
+ using cpu_reorder_pd_t::cpu_reorder_pd_t;
+
+ DECLARE_COMMON_PD_T("simple:any", simple_reorder_t);
+
+ static status_t create(reorder_pd_t **reorder_pd,
+ engine_t *engine, const primitive_attr_t *attr,
+ engine_t *src_engine, const memory_desc_t *src_md,
+ engine_t *dst_engine, const memory_desc_t *dst_md) {
+ bool args_ok = true
+ && src_md->data_type == type_i
+ && dst_md->data_type == type_o
+ && simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL, spec>::
+ is_applicable(src_md, dst_md, attr);
+ if (!args_ok)
+ return status::invalid_arguments;
+
+ auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine,
+ dst_md);
+ if (_pd == nullptr) return status::out_of_memory;
+ if (_pd->init() != status::success) {
+ delete _pd;
+ return status::unimplemented;
+ }
+ return safe_ptr_assign<reorder_pd_t>(*reorder_pd, _pd);
+ }
+ };
+
+ simple_reorder_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto input = CTX_IN_MEM(const data_t<type_i> *, MKLDNN_ARG_FROM);
+ auto output = CTX_OUT_MEM(data_t<type_o> *, MKLDNN_ARG_TO);
+ simple_reorder_impl<SIMPLE_REORDER_TEMPL_CALL, spec>::execute(
+ pd(), input, output);
+ return status::success;
+ }
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+#undef SIMPLE_REORDER_TEMPL_DECL
+#undef SIMPLE_REORDER_TEMPL_CALL
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.cpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.cpp
new file mode 100644
index 0000000000..f0947573a9
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.cpp
@@ -0,0 +1,91 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "mkldnn_thread.hpp"
+
+#include "simple_sum.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <data_type_t data_type>
+status_t simple_sum_t<data_type>::execute(const exec_ctx_t &ctx) const {
+ auto output = CTX_OUT_MEM(data_t *, MKLDNN_ARG_DST);
+
+ const memory_desc_wrapper o_d(pd()->dst_md());
+ output += o_d.blk_off(0);
+
+ const int num_arrs = pd()->n_inputs();
+ const data_t *input_ptrs[max_num_arrs];
+ const size_t nelems = o_d.nelems();
+
+ for (int a = 0; a < num_arrs; ++a) {
+ const memory_desc_wrapper i_d(pd()->src_md(a));
+ input_ptrs[a] = CTX_IN_MEM(const data_t *, MKLDNN_ARG_MULTIPLE_SRC + a)
+ + i_d.blk_off(0);
+ }
+
+ const size_t block_size = 16 * 1024 / sizeof(data_type);
+ const size_t blocks_number = nelems / block_size;
+ const size_t tail = nelems % block_size;
+
+ const auto scales = pd()->scales();
+ parallel(0, [&](const int ithr, const int nthr) {
+ size_t start{0}, end{0};
+ balance211(blocks_number, nthr, ithr, start, end);
+
+ for (size_t nb = start; nb < end; ++nb) {
+ size_t start_e = nb * block_size;
+ size_t end_e = start_e + block_size;
+
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start_e; e < end_e; e++) {
+ output[e] = data_t(scales[0] * input_ptrs[0][e]);
+ }
+ for (int a = 1; a < num_arrs; a++) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start_e; e < end_e; e++) {
+ output[e] += data_t(scales[a] * input_ptrs[a][e]);
+ }
+ }
+ }
+
+ if (tail != 0 && ithr == nthr - 1) {
+ size_t start_e = nelems - tail;
+ size_t end_e = nelems;
+
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start_e; e < end_e; e++) {
+ output[e] = data_t(scales[0] * input_ptrs[0][e]);
+ }
+ for (int a = 1; a < num_arrs; a++) {
+ PRAGMA_OMP_SIMD()
+ for (size_t e = start_e; e < end_e; e++) {
+ output[e] += data_t(scales[a] * input_ptrs[a][e]);
+ }
+ }
+ }
+ });
+
+ return status::success;
+}
+
+template struct simple_sum_t<data_type::f32>;
+
+}
+}
+}
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.hpp
new file mode 100644
index 0000000000..2a0187a184
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/simple_sum.hpp
@@ -0,0 +1,74 @@
+/*******************************************************************************
+* Copyright 2017-2018 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#ifndef SIMPLE_SUM_HPP
+#define SIMPLE_SUM_HPP
+
+#include "cpu_sum_pd.hpp"
+#include "cpu_primitive.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <data_type_t data_type>
+struct simple_sum_t: public cpu_primitive_t {
+ struct pd_t: public cpu_sum_pd_t {
+ using cpu_sum_pd_t::cpu_sum_pd_t;
+
+ DECLARE_SUM_PD_T("simple:any", simple_sum_t);
+
+ status_t init() {
+ const int n = n_inputs();
+
+ bool ok = true
+ && cpu_sum_pd_t::init() == status::success
+ && n <= max_num_arrs;
+ if (!ok) return status::unimplemented;
+
+ const memory_desc_wrapper o_d(dst_md());
+ ok = ok
+ && o_d.data_type() == data_type
+ && o_d.is_dense();
+ if (!ok) return status::unimplemented;
+
+ for (int i = 0; i < n; ++i) {
+ const memory_desc_wrapper i_d(src_md(i));
+ if (i_d != o_d) return status::unimplemented;
+ }
+
+ return status::success;
+ }
+ };
+
+ simple_sum_t(const pd_t *apd): cpu_primitive_t(apd) {}
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override;
+
+ enum {max_num_arrs = 16 };
+ typedef typename prec_traits<data_type>::type data_t;
+
+private:
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+};
+
+}
+}
+}
+
+#endif
+
+// vim: et ts=4 sw=4 cindent cino^=l0,\:0,N-s
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/wino_reorder.hpp b/thirdparty/oidn/mkl-dnn/src/cpu/wino_reorder.hpp
new file mode 100644
index 0000000000..c2082d7d62
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/wino_reorder.hpp
@@ -0,0 +1,376 @@
+/*******************************************************************************
+ * Copyright 2017-2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+
+#ifndef CPU_WINO_REORDER_HPP
+#define CPU_WINO_REORDER_HPP
+
+#include "mkldnn_thread.hpp"
+
+#include "simple_q10n.hpp"
+
+namespace mkldnn {
+namespace impl {
+namespace cpu {
+
+template <data_type_t type_i, data_type_t type_o>
+struct wino_reorder_t : public cpu_primitive_t {
+ struct pd_t : public cpu_reorder_pd_t {
+ using cpu_reorder_pd_t::cpu_reorder_pd_t;
+
+ DECLARE_COMMON_PD_T("wino_reorder", wino_reorder_t);
+
+ static status_t create(reorder_pd_t **reorder_pd,
+ engine_t *engine, const primitive_attr_t *attr,
+ engine_t *src_engine, const memory_desc_t *src_md,
+ engine_t *dst_engine, const memory_desc_t *dst_md) {
+ const memory_desc_wrapper id(src_md), od(dst_md);
+ bool args_ok = true
+ && id.data_type() == type_i
+ && od.data_type() == type_o
+ && id.matches_tag(utils::pick(id.ndims() - 4,
+ format_tag::oihw, format_tag::goihw))
+ && od.format_kind() == format_kind::wino
+ && utils::one_of(od.wino_desc().wino_format,
+ mkldnn_wino_wei_aaOIoi, mkldnn_wino_wei_aaOio,
+ mkldnn_wino_wei_aaOBiOo, mkldnn_wino_wei_OBaaIBOIio);
+ if (!args_ok) return status::invalid_arguments;
+
+ auto _pd = new pd_t(engine, attr, src_engine, src_md, dst_engine,
+ dst_md);
+ if (_pd == nullptr) return status::out_of_memory;
+ if (_pd->init() != status::success) {
+ delete _pd;
+ return status::unimplemented;
+ }
+ return safe_ptr_assign<reorder_pd_t>(*reorder_pd, _pd);
+ }
+
+ status_t init() {
+ status_t status = cpu_reorder_pd_t::init();
+ if (status != status::success) return status;
+
+ init_scratchpad();
+
+ return status::success;
+ }
+
+ private:
+ void init_scratchpad() {
+ auto &o = memory_desc_wrapper(dst_md()).wino_desc();
+ size_t transform_space_size = (size_t)o.r * o.alpha * o.oc_block;
+ size_t plain_size = (size_t)o.alpha * o.alpha * o.oc * o.ic;
+
+ using namespace memory_tracking::names;
+ auto scratchpad = scratchpad_registry().registrar();
+ scratchpad.book(key_reorder_wino_transform_space,
+ sizeof(in_data_t) * transform_space_size);
+ scratchpad.book(key_reorder_wino_plain,
+ sizeof(out_data_t) * plain_size);
+ }
+ };
+
+private:
+ typedef typename prec_traits<type_i>::type in_data_t;
+ typedef typename prec_traits<type_o>::type out_data_t;
+ const int unsign_val_in_wino_domain_ = 5;
+
+ wino_reorder_t(const pd_t *apd): cpu_primitive_t(apd) {
+ const memory_desc_wrapper src_d(pd()->src_md());
+ const memory_desc_wrapper dst_d(pd()->dst_md());
+
+ r_ = dst_d.wino_desc().r;
+ w_alpha_ = dst_d.wino_desc().alpha;
+ wino_format_ = dst_d.wino_desc().wino_format;
+
+ const auto &in_dims = src_d.dims();
+ int groups;
+ int groups_offset;
+ if (src_d.ndims() == 5) {
+ groups = in_dims[0];
+ groups_offset = 1;
+ } else {
+ groups = 1;
+ groups_offset = 0;
+ }
+ assert(groups == 1); // groups are not supported now
+ MAYBE_UNUSED(groups);
+
+ or_oc_ = in_dims[0 + groups_offset];
+ or_ic_ = in_dims[1 + groups_offset];
+ kh_ = in_dims[2 + groups_offset];
+ kw_ = in_dims[3 + groups_offset];
+
+ oc_ = dst_d.wino_desc().oc;
+ ic_ = dst_d.wino_desc().ic;
+ oc_block_ = dst_d.wino_desc().oc_block;
+ ic_block_ = dst_d.wino_desc().ic_block;
+ assert(oc_ % oc_block_ == 0 && ic_ % ic_block_ == 0);
+ nb_oc_ = oc_ / oc_block_;
+ nb_ic_ = ic_ / ic_block_;
+ ic2_block_ = 1;
+ if (wino_format_ == mkldnn_wino_wei_OBaaIBOIio)
+ ic2_block_ = dst_d.wino_desc().ic2_block;
+ oc2_block_ = dst_d.wino_desc().oc2_block;
+ assert(nb_ic_ % ic2_block_ == 0 && nb_oc_ % oc2_block_ == 0);
+
+ adj_scale_ = dst_d.wino_desc().adj_scale;
+
+ size_wino_wei_ = w_alpha_ * w_alpha_ * oc_ * ic_;
+ size_wspace_ = r_ * w_alpha_ * oc_block_;
+ }
+
+ void transform(out_data_t *__restrict tmp_wei,
+ const in_data_t *__restrict input,
+ in_data_t *__restrict wspace) const {
+ const memory_desc_wrapper src_d(pd()->src_md());
+
+ const int smask = pd()->attr()->output_scales_.mask_;
+ const int ndims_mask = math::ilog2q(smask + 1);
+ const size_t D_mask = utils::array_product(src_d.dims(), ndims_mask);
+ const float *__restrict scales = pd()->attr()->output_scales_.scales_;
+ assert(D_mask == 1 || D_mask == (size_t)oc_);
+
+ /* transform weights to winograd domain */
+ const float G_2x2_3x3[4][3] = { { 1.0, 0.0, 0.0 }, { 0.5, 0.5, 0.5 },
+ { 0.5, -0.5, 0.5 }, { 0.0, 0.0, 1.0 } };
+
+ const float G_4x4_3x3[6][3] = { { 1.13777777777778f, 0.f, 0.f },
+ { -0.688403361344538f, -0.430252100840336f, -0.26890756302521f },
+ { -0.688403361344538f, 0.430252100840336f, -0.26890756302521f },
+ { 0.119514472455649f, 0.179271708683473f, 0.26890756302521f },
+ { 0.119514472455649f, -0.179271708683473f, 0.26890756302521f },
+ { 0.f, 0.f, 1.f } };
+
+ float *__restrict g;
+ if (utils::one_of(wino_format_, mkldnn_wino_wei_aaOIoi,
+ mkldnn_wino_wei_aaOio, mkldnn_wino_wei_aaOBiOo))
+ g = (float *)G_2x2_3x3;
+ else if (wino_format_ == mkldnn_wino_wei_OBaaIBOIio)
+ g = (float *)G_4x4_3x3;
+ else {
+ assert("Unknown winograd weights target layout");
+ return;
+ }
+
+ int Z = oc_ * ic_;
+ assert(r_ == kh_ && r_ == kw_);
+
+ for (int iic = 0; iic < ic_; iic++) {
+ for (int ob = 0; ob < nb_oc_; ob++) {
+ const in_data_t *__restrict _inp
+ = input + (ob * oc_block_ * or_ic_ + iic) * kh_ * kw_;
+ out_data_t *__restrict _out
+ = tmp_wei + (iic * nb_oc_ + ob) * oc_block_;
+
+ for_nd(0, 1, size_wspace_, [&](int i) { wspace[i] = 0.f; });
+
+ for_nd(0, 1, r_, w_alpha_, oc_block_,
+ [&](int ih, int j, int ioc) {
+ for (int iw = 0; iw < r_; ++iw) {
+ int inp_oc = ob * oc_block_ + ioc;
+ int inp_ic = iic;
+ in_data_t inp_v = (inp_ic < or_ic_ && inp_oc < or_oc_)
+ ? _inp[ioc * or_ic_ * kh_ * kw_ + ih * kw_ + iw]
+ : 0.f;
+ wspace[(ih * w_alpha_ + j) * oc_block_ + ioc]
+ += inp_v * g[j * r_ + iw];
+ }
+ });
+
+ for_nd(0, 1, w_alpha_, w_alpha_, oc_block_,
+ [&](int i, int j, int ioc) {
+ float t = 0;
+ for (int k = 0; k < r_; ++k)
+ t += g[i * r_ + k]
+ * wspace[(k * w_alpha_ + j) * oc_block_ + ioc];
+ if (type_o == data_type::s8) {
+ const float scale = (D_mask == 1)
+ ? scales[0]
+ : scales[ob * oc_block_ + ioc];
+ _out[(i * w_alpha_ + j) * Z + ioc]
+ = qz_b0<in_data_t, out_data_t>()(
+ (in_data_t)t, scale * adj_scale_);
+ } else {
+ _out[(i * w_alpha_ + j) * Z + ioc] = (out_data_t)t;
+ }
+ });
+ }}
+ }
+
+ void reorder_to_aaOIoi(out_data_t *__restrict output,
+ const out_data_t *__restrict tmp_wei) const {
+ int32_t *__restrict dst_bias = nullptr;
+ if (type_o == data_type::s8) {
+ const auto bias_shift = sizeof(out_data_t) * size_wino_wei_;
+ const size_t bias_size = w_alpha_ * w_alpha_ * oc_;
+
+ dst_bias = (int32_t *)(output + bias_shift);
+ utils::array_set((int32_t *)dst_bias, 0, bias_size);
+ }
+ int index = 0;
+ for (int u_h = 0; u_h < w_alpha_; u_h++) {
+ for (int u_w = 0; u_w < w_alpha_; u_w++) {
+ for_nd(0, 1, nb_oc_, oc_block_, [&](int ob, int o) {
+ int u_h_shift = u_h * w_alpha_ * ic_ * oc_;
+ int u_w_shift = u_w * ic_ * oc_;
+ int u_h_shift_b = u_h * w_alpha_ * oc_;
+ int u_w_shift_b = u_w * oc_;
+ int oc_block_shift = ob * oc_block_ * ic_ + o * ic_block_;
+ for (int ib = 0; ib < nb_ic_; ib++) {
+ for (int i = 0; i < ic_block_; i++) {
+ int _i = ib * ic_block_;
+ int _o = ob * oc_block_;
+ int ic_shift = (_i + i) * oc_;
+ int oc_shift = (_o + o);
+ int ic_block_shift = ib * oc_block_ * ic_block_ + i;
+ int src_offset =
+ u_h_shift + u_w_shift + ic_shift + oc_shift;
+ int dst_offset = u_h_shift + u_w_shift + oc_block_shift
+ + ic_block_shift;
+
+ output[dst_offset] = tmp_wei[src_offset];
+ if (type_o == data_type::s8) {
+ int bias_offset = u_h_shift_b + u_w_shift_b + oc_shift;
+ if (index != unsign_val_in_wino_domain_)
+ dst_bias[bias_offset]
+ -= (128 * (int32_t)output[dst_offset]);
+ else
+ dst_bias[bias_offset] = 0;
+ }
+ }}
+ });
+ index++;
+ }}
+ }
+
+ void reorder_to_aaOio(out_data_t *__restrict output,
+ const out_data_t *__restrict tmp_wei) const {
+ for_nd(0, 1, w_alpha_, w_alpha_, nb_oc_,
+ [&](int u_h, int u_w, int ob) {
+ for (int ib = 0; ib < nb_ic_; ib++) {
+ for (int i = 0; i < ic_block_; i++) {
+ for (int o = 0; o < oc_block_; o++) {
+ int src_offset = u_h * w_alpha_ * ic_ * oc_ + u_w * ic_ * oc_
+ + (ib * ic_block_ + i) * oc_ + (ob * oc_block_ + o);
+
+ int dst_offset
+ = u_h * w_alpha_ * nb_oc_ * nb_ic_ * ic_block_ * oc_block_
+ + u_w * nb_oc_ * nb_ic_ * ic_block_ * oc_block_
+ + ob * nb_ic_ * ic_block_ * oc_block_
+ + ib * ic_block_ * oc_block_ + i * oc_block_ + o;
+ output[dst_offset] = tmp_wei[src_offset];
+ }}}
+ });
+ }
+
+ void reorder_to_aaOBiOo(out_data_t *__restrict output,
+ const out_data_t *__restrict tmp_wei) const {
+ int oc_chunks = nb_oc_ / oc2_block_;
+
+ for_nd(0, 1, w_alpha_, w_alpha_, oc_chunks,
+ [&](int u_h, int u_w, int occ) {
+ for (int ib = 0; ib < nb_ic_; ib++) {
+ out_data_t *__restrict wei_ptr = output
+ + (((u_h * w_alpha_ + u_w) * oc_chunks + occ) * nb_ic_ + ib)
+ * oc2_block_ * ic_block_ * oc_block_;
+ int wei_offset = 0;
+ for (int i = 0; i < ic_block_; i++) {
+ for (int ob2 = 0; ob2 < oc2_block_; ob2++) {
+ for (int o = 0; o < oc_block_; o++) {
+ int icp = ib * ic_block_ + i;
+ int ocp =
+ occ * oc2_block_ * oc_block_ + ob2 * oc_block_ + o;
+
+ int src_offset = u_h * w_alpha_ * ic_ * oc_
+ + u_w * ic_ * oc_ + icp * oc_ + ocp;
+ wei_ptr[wei_offset + o] = tmp_wei[src_offset];
+ }
+ wei_offset += oc_block_;
+ }}
+ }
+ });
+ }
+
+ void reorder_to_OBaaIBOIio(out_data_t *__restrict output,
+ const out_data_t *__restrict tmp_wei) const {
+ int ic_chunks = nb_ic_ / ic2_block_;
+ int oc_chunks = nb_oc_ / oc2_block_;
+
+ for_nd(0, 1, oc_chunks, w_alpha_, w_alpha_,
+ [&](int occ, int u_h, int u_w) {
+ for (int icc = 0; icc < ic_chunks; icc++) {
+ for (int ob = 0; ob < oc2_block_; ob++) {
+ int ocp = (occ * oc2_block_ + ob) * oc_block_;
+ for (int ib = 0; ib < ic2_block_; ib++) {
+ for (int i = 0; i < ic_block_; i++) {
+ int icp = (icc * ic2_block_ + ib) * ic_block_ + i;
+
+ int src_offset = u_h * w_alpha_ * ic_ * oc_
+ + u_w * ic_ * oc_ + icp * oc_ + ocp;
+ int wei_offset
+ = ((((((occ * w_alpha_ + u_h) * w_alpha_ + u_w)
+ * ic_chunks + icc) * oc2_block_ + ob) * ic2_block_
+ + ib) * ic_block_ + i) * oc_block_;
+ for (int o = 0; o < oc_block_; o++)
+ output[wei_offset + o] = tmp_wei[src_offset + o];
+ }}
+ }}
+ });
+ }
+
+ virtual status_t execute(const exec_ctx_t &ctx) const override {
+ auto input = CTX_IN_MEM(const in_data_t *, MKLDNN_ARG_FROM);
+ auto output = CTX_OUT_MEM(out_data_t *, MKLDNN_ARG_TO);
+
+ auto wspace = (in_data_t *__restrict)scratchpad(ctx).template get<void>(
+ memory_tracking::names::key_reorder_wino_transform_space);
+ auto tmp_wei = (out_data_t *__restrict)scratchpad(ctx).template get<void>(
+ memory_tracking::names::key_reorder_wino_plain);
+
+ transform(tmp_wei, input, wspace);
+
+ /* reorder to winograd domain */
+ switch (wino_format_) {
+ case mkldnn_wino_wei_aaOIoi:
+ reorder_to_aaOIoi(output, tmp_wei); break;
+ case mkldnn_wino_wei_aaOio:
+ reorder_to_aaOio(output, tmp_wei); break;
+ case mkldnn_wino_wei_aaOBiOo:
+ reorder_to_aaOBiOo(output, tmp_wei); break;
+ case mkldnn_wino_wei_OBaaIBOIio:
+ reorder_to_OBaaIBOIio(output, tmp_wei); break;
+ default: assert("Unknown wino format"); break;
+ }
+
+ return status::success;
+ }
+
+ const pd_t *pd() const { return (const pd_t *)primitive_t::pd(); }
+ int r_, w_alpha_;
+ int ic_, oc_, or_ic_, or_oc_, kh_, kw_;
+ int oc_block_, ic_block_, oc2_block_, ic2_block_;
+ float adj_scale_;
+ int nb_oc_, nb_ic_;
+ mkldnn_wino_memory_format_t wino_format_;
+ int size_wino_wei_;
+ int size_wspace_;
+};
+
+} // namespace cpu
+} // namespace impl
+} // namespace mkldnn
+
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/COPYRIGHT b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/COPYRIGHT
new file mode 100644
index 0000000000..66b6ea55d0
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/COPYRIGHT
@@ -0,0 +1,47 @@
+
+Copyright (c) 2007 MITSUNARI Shigeo
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+Neither the name of the copyright owner nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+ソースコード形å¼ã‹ãƒã‚¤ãƒŠãƒªå½¢å¼ã‹ã€å¤‰æ›´ã™ã‚‹ã‹ã—ãªã„ã‹ã‚’å•ã‚ãšã€ä»¥ä¸‹ã®æ¡ä»¶ã‚’満ãŸ
+ã™å ´åˆã«é™ã‚Šã€å†é ’布ãŠã‚ˆã³ä½¿ç”¨ãŒè¨±å¯ã•ã‚Œã¾ã™ã€‚
+
+ソースコードをå†é ’布ã™ã‚‹å ´åˆã€ä¸Šè¨˜ã®è‘—作権表示ã€æœ¬æ¡ä»¶ä¸€è¦§ã€ãŠã‚ˆã³ä¸‹è¨˜å…責æ¡é …
+ã‚’å«ã‚ã‚‹ã“ã¨ã€‚
+ãƒã‚¤ãƒŠãƒªå½¢å¼ã§å†é ’布ã™ã‚‹å ´åˆã€é ’布物ã«ä»˜å±žã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆç­‰ã®è³‡æ–™ã«ã€ä¸Šè¨˜ã®è‘—作
+権表示ã€æœ¬æ¡ä»¶ä¸€è¦§ã€ãŠã‚ˆã³ä¸‹è¨˜å…責æ¡é …ã‚’å«ã‚ã‚‹ã“ã¨ã€‚
+書é¢ã«ã‚ˆã‚‹ç‰¹åˆ¥ã®è¨±å¯ãªã—ã«ã€æœ¬ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‹ã‚‰æ´¾ç”Ÿã—ãŸè£½å“ã®å®£ä¼ã¾ãŸã¯è²©å£²ä¿ƒé€²
+ã«ã€è‘—作権者ã®åå‰ã¾ãŸã¯ã‚³ãƒ³ãƒˆãƒªãƒ“ューターã®åå‰ã‚’使用ã—ã¦ã¯ãªã‚‰ãªã„。
+本ソフトウェアã¯ã€è‘—作権者ãŠã‚ˆã³ã‚³ãƒ³ãƒˆãƒªãƒ“ューターã«ã‚ˆã£ã¦ã€Œç¾çŠ¶ã®ã¾ã¾ã€æä¾›ã•
+ã‚Œã¦ãŠã‚Šã€æ˜Žç¤ºé»™ç¤ºã‚’å•ã‚ãšã€å•†æ¥­çš„ãªä½¿ç”¨å¯èƒ½æ€§ã€ãŠã‚ˆã³ç‰¹å®šã®ç›®çš„ã«å¯¾ã™ã‚‹é©åˆæ€§
+ã«é–¢ã™ã‚‹æš—é»™ã®ä¿è¨¼ã‚‚å«ã‚ã€ã¾ãŸãã‚Œã«é™å®šã•ã‚Œãªã„ã€ã„ã‹ãªã‚‹ä¿è¨¼ã‚‚ã‚ã‚Šã¾ã›ã‚“。
+著作権者もコントリビューターもã€äº‹ç”±ã®ã„ã‹ã‚“ã‚’å•ã‚ãšã€ æ害発生ã®åŽŸå› ã„ã‹ã‚“ã‚’
+å•ã‚ãšã€ã‹ã¤è²¬ä»»ã®æ ¹æ‹ ãŒå¥‘ç´„ã§ã‚ã‚‹ã‹åŽ³æ ¼è²¬ä»»ã§ã‚ã‚‹ã‹ï¼ˆéŽå¤±ãã®ä»–ã®ï¼‰ä¸æ³•è¡Œç‚ºã§
+ã‚ã‚‹ã‹ã‚’å•ã‚ãšã€ä»®ã«ãã®ã‚ˆã†ãªæ害ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ã‚’知らã•ã‚Œã¦ã„ãŸã¨ã—ã¦ã‚‚ã€
+本ソフトウェアã®ä½¿ç”¨ã«ã‚ˆã£ã¦ç™ºç”Ÿã—ãŸï¼ˆä»£æ›¿å“ã¾ãŸã¯ä»£ç”¨ã‚µãƒ¼ãƒ“スã®èª¿é”ã€ä½¿ç”¨ã®
+喪失ã€ãƒ‡ãƒ¼ã‚¿ã®å–ªå¤±ã€åˆ©ç›Šã®å–ªå¤±ã€æ¥­å‹™ã®ä¸­æ–­ã‚‚å«ã‚ã€ã¾ãŸãã‚Œã«é™å®šã•ã‚Œãªã„)直接
+æ害ã€é–“接æ害ã€å¶ç™ºçš„ãªæ害ã€ç‰¹åˆ¥æ害ã€æ‡²ç½°çš„æ害ã€ã¾ãŸã¯çµæžœæ害ã«ã¤ã„ã¦ã€
+一切責任を負ã‚ãªã„ã‚‚ã®ã¨ã—ã¾ã™ã€‚
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak.h b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak.h
new file mode 100644
index 0000000000..cf5771332f
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak.h
@@ -0,0 +1,2658 @@
+/*******************************************************************************
+* Copyright 2016-2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*******************************************************************************
+* Copyright (c) 2007 MITSUNARI Shigeo
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* Neither the name of the copyright owner nor the names of its contributors may
+* be used to endorse or promote products derived from this software without
+* specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#pragma once
+#ifndef XBYAK_XBYAK_H_
+#define XBYAK_XBYAK_H_
+/*!
+ @file xbyak.h
+ @brief Xbyak ; JIT assembler for x86(IA32)/x64 by C++
+ @author herumi
+ @url https://github.com/herumi/xbyak
+ @note modified new BSD license
+ http://opensource.org/licenses/BSD-3-Clause
+*/
+#ifndef XBYAK_NO_OP_NAMES
+ #if not +0 // trick to detect whether 'not' is operator or not
+ #error "use -fno-operator-names option if you want to use and(), or(), xor(), not() as function names, Or define XBYAK_NO_OP_NAMES and use and_(), or_(), xor_(), not_()."
+ #endif
+#endif
+
+#include <stdio.h> // for debug print
+#include <assert.h>
+#include <list>
+#include <string>
+#include <algorithm>
+#ifndef NDEBUG
+#include <iostream>
+#endif
+
+// #define XBYAK_DISABLE_AVX512
+
+//#define XBYAK_USE_MMAP_ALLOCATOR
+#if !defined(__GNUC__) || defined(__MINGW32__)
+ #undef XBYAK_USE_MMAP_ALLOCATOR
+#endif
+
+#ifdef __GNUC__
+ #define XBYAK_GNUC_PREREQ(major, minor) ((__GNUC__) * 100 + (__GNUC_MINOR__) >= (major) * 100 + (minor))
+#else
+ #define XBYAK_GNUC_PREREQ(major, minor) 0
+#endif
+
+// This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft.
+#if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\
+ ((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)))
+ #include <unordered_set>
+ #define XBYAK_STD_UNORDERED_SET std::unordered_set
+ #include <unordered_map>
+ #define XBYAK_STD_UNORDERED_MAP std::unordered_map
+ #define XBYAK_STD_UNORDERED_MULTIMAP std::unordered_multimap
+
+/*
+ Clang/llvm-gcc and ICC-EDG in 'GCC-mode' always claim to be GCC 4.2, using
+ libstdcxx 20070719 (from GCC 4.2.1, the last GPL 2 version).
+*/
+#elif XBYAK_GNUC_PREREQ(4, 5) || (XBYAK_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || defined(__llvm__)
+ #include <tr1/unordered_set>
+ #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set
+ #include <tr1/unordered_map>
+ #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map
+ #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap
+
+#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER < 1600)
+ #include <unordered_set>
+ #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set
+ #include <unordered_map>
+ #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map
+ #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap
+
+#else
+ #include <set>
+ #define XBYAK_STD_UNORDERED_SET std::set
+ #include <map>
+ #define XBYAK_STD_UNORDERED_MAP std::map
+ #define XBYAK_STD_UNORDERED_MULTIMAP std::multimap
+#endif
+#ifdef _WIN32
+ #include <winsock2.h>
+ #include <windows.h>
+ #include <malloc.h>
+#elif defined(__GNUC__)
+ #include <unistd.h>
+ #include <sys/mman.h>
+ #include <stdlib.h>
+#endif
+#if !defined(_MSC_VER) || (_MSC_VER >= 1600)
+ #include <stdint.h>
+#endif
+
+#if defined(_WIN64) || defined(__MINGW64__) || (defined(__CYGWIN__) && defined(__x86_64__))
+ #define XBYAK64_WIN
+#elif defined(__x86_64__)
+ #define XBYAK64_GCC
+#endif
+#if !defined(XBYAK64) && !defined(XBYAK32)
+ #if defined(XBYAK64_GCC) || defined(XBYAK64_WIN)
+ #define XBYAK64
+ #else
+ #define XBYAK32
+ #endif
+#endif
+
+#if (__cplusplus >= 201103) || (_MSC_VER >= 1800)
+ #define XBYAK_VARIADIC_TEMPLATE
+#endif
+
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable : 4514) /* remove inline function */
+ #pragma warning(disable : 4786) /* identifier is too long */
+ #pragma warning(disable : 4503) /* name is too long */
+ #pragma warning(disable : 4127) /* constant expresison */
+#endif
+
+namespace Xbyak {
+
+enum {
+ DEFAULT_MAX_CODE_SIZE = 4096,
+ VERSION = 0x5760 /* 0xABCD = A.BC(D) */
+};
+
+#ifndef MIE_INTEGER_TYPE_DEFINED
+#define MIE_INTEGER_TYPE_DEFINED
+#ifdef _MSC_VER
+ typedef unsigned __int64 uint64;
+ typedef __int64 sint64;
+#else
+ typedef uint64_t uint64;
+ typedef int64_t sint64;
+#endif
+typedef unsigned int uint32;
+typedef unsigned short uint16;
+typedef unsigned char uint8;
+#endif
+
+#ifndef MIE_ALIGN
+ #ifdef _MSC_VER
+ #define MIE_ALIGN(x) __declspec(align(x))
+ #else
+ #define MIE_ALIGN(x) __attribute__((aligned(x)))
+ #endif
+#endif
+#ifndef MIE_PACK // for shufps
+ #define MIE_PACK(x, y, z, w) ((x) * 64 + (y) * 16 + (z) * 4 + (w))
+#endif
+
+enum {
+ ERR_NONE = 0,
+ ERR_BAD_ADDRESSING,
+ ERR_CODE_IS_TOO_BIG,
+ ERR_BAD_SCALE,
+ ERR_ESP_CANT_BE_INDEX,
+ ERR_BAD_COMBINATION,
+ ERR_BAD_SIZE_OF_REGISTER,
+ ERR_IMM_IS_TOO_BIG,
+ ERR_BAD_ALIGN,
+ ERR_LABEL_IS_REDEFINED,
+ ERR_LABEL_IS_TOO_FAR,
+ ERR_LABEL_IS_NOT_FOUND,
+ ERR_CODE_ISNOT_COPYABLE,
+ ERR_BAD_PARAMETER,
+ ERR_CANT_PROTECT,
+ ERR_CANT_USE_64BIT_DISP,
+ ERR_OFFSET_IS_TOO_BIG,
+ ERR_MEM_SIZE_IS_NOT_SPECIFIED,
+ ERR_BAD_MEM_SIZE,
+ ERR_BAD_ST_COMBINATION,
+ ERR_OVER_LOCAL_LABEL, // not used
+ ERR_UNDER_LOCAL_LABEL,
+ ERR_CANT_ALLOC,
+ ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW,
+ ERR_BAD_PROTECT_MODE,
+ ERR_BAD_PNUM,
+ ERR_BAD_TNUM,
+ ERR_BAD_VSIB_ADDRESSING,
+ ERR_CANT_CONVERT,
+ ERR_LABEL_ISNOT_SET_BY_L,
+ ERR_LABEL_IS_ALREADY_SET_BY_L,
+ ERR_BAD_LABEL_STR,
+ ERR_MUNMAP,
+ ERR_OPMASK_IS_ALREADY_SET,
+ ERR_ROUNDING_IS_ALREADY_SET,
+ ERR_K0_IS_INVALID,
+ ERR_EVEX_IS_INVALID,
+ ERR_SAE_IS_INVALID,
+ ERR_ER_IS_INVALID,
+ ERR_INVALID_BROADCAST,
+ ERR_INVALID_OPMASK_WITH_MEMORY,
+ ERR_INVALID_ZERO,
+ ERR_INVALID_RIP_IN_AUTO_GROW,
+ ERR_INVALID_MIB_ADDRESS,
+ ERR_INTERNAL,
+ ERR_X2APIC_IS_NOT_SUPPORTED
+};
+
+class Error : public std::exception {
+ int err_;
+public:
+ explicit Error(int err) : err_(err)
+ {
+ if (err_ < 0 || err_ > ERR_INTERNAL) {
+ fprintf(stderr, "bad err=%d in Xbyak::Error\n", err_);
+ //exit(1);
+ }
+ }
+ operator int() const { return err_; }
+ const char *what() const throw()
+ {
+ static const char *errTbl[] = {
+ "none",
+ "bad addressing",
+ "code is too big",
+ "bad scale",
+ "esp can't be index",
+ "bad combination",
+ "bad size of register",
+ "imm is too big",
+ "bad align",
+ "label is redefined",
+ "label is too far",
+ "label is not found",
+ "code is not copyable",
+ "bad parameter",
+ "can't protect",
+ "can't use 64bit disp(use (void*))",
+ "offset is too big",
+ "MEM size is not specified",
+ "bad mem size",
+ "bad st combination",
+ "over local label",
+ "under local label",
+ "can't alloc",
+ "T_SHORT is not supported in AutoGrow",
+ "bad protect mode",
+ "bad pNum",
+ "bad tNum",
+ "bad vsib addressing",
+ "can't convert",
+ "label is not set by L()",
+ "label is already set by L()",
+ "bad label string",
+ "err munmap",
+ "opmask is already set",
+ "rounding is already set",
+ "k0 is invalid",
+ "evex is invalid",
+ "sae(suppress all exceptions) is invalid",
+ "er(embedded rounding) is invalid",
+ "invalid broadcast",
+ "invalid opmask with memory",
+ "invalid zero",
+ "invalid rip in AutoGrow",
+ "invalid mib address",
+ "internal error",
+ "x2APIC is not supported"
+ };
+ assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl));
+ return errTbl[err_];
+ }
+};
+
+inline const char *ConvertErrorToString(const Error& err)
+{
+ return err.what();
+}
+
+inline void *AlignedMalloc(size_t size, size_t alignment)
+{
+#ifdef __MINGW32__
+ return __mingw_aligned_malloc(size, alignment);
+#elif defined(_WIN32)
+ return _aligned_malloc(size, alignment);
+#else
+ void *p;
+ int ret = posix_memalign(&p, alignment, size);
+ return (ret == 0) ? p : 0;
+#endif
+}
+
+inline void AlignedFree(void *p)
+{
+#ifdef __MINGW32__
+ __mingw_aligned_free(p);
+#elif defined(_MSC_VER)
+ _aligned_free(p);
+#else
+ free(p);
+#endif
+}
+
+template<class To, class From>
+inline const To CastTo(From p) throw()
+{
+ return (const To)(size_t)(p);
+}
+namespace inner {
+
+static const size_t ALIGN_PAGE_SIZE = 4096;
+
+inline bool IsInDisp8(uint32 x) { return 0xFFFFFF80 <= x || x <= 0x7F; }
+inline bool IsInInt32(uint64 x) { return ~uint64(0x7fffffffu) <= x || x <= 0x7FFFFFFFU; }
+
+inline uint32 VerifyInInt32(uint64 x)
+{
+#ifdef XBYAK64
+ if (!IsInInt32(x)) throw Error(ERR_OFFSET_IS_TOO_BIG);
+#endif
+ return static_cast<uint32>(x);
+}
+
+enum LabelMode {
+ LasIs, // as is
+ Labs, // absolute
+ LaddTop // (addr + top) for mov(reg, label) with AutoGrow
+};
+
+} // inner
+
+/*
+ custom allocator
+*/
+struct Allocator {
+ virtual uint8 *alloc(size_t size) { return reinterpret_cast<uint8*>(AlignedMalloc(size, inner::ALIGN_PAGE_SIZE)); }
+ virtual void free(uint8 *p) { AlignedFree(p); }
+ virtual ~Allocator() {}
+ /* override to return false if you call protect() manually */
+ virtual bool useProtect() const { return true; }
+};
+
+#ifdef XBYAK_USE_MMAP_ALLOCATOR
+class MmapAllocator : Allocator {
+ typedef XBYAK_STD_UNORDERED_MAP<uintptr_t, size_t> SizeList;
+ SizeList sizeList_;
+public:
+ uint8 *alloc(size_t size)
+ {
+ const size_t alignedSizeM1 = inner::ALIGN_PAGE_SIZE - 1;
+ size = (size + alignedSizeM1) & ~alignedSizeM1;
+#ifdef MAP_ANONYMOUS
+ const int mode = MAP_PRIVATE | MAP_ANONYMOUS;
+#elif defined(MAP_ANON)
+ const int mode = MAP_PRIVATE | MAP_ANON;
+#else
+ #error "not supported"
+#endif
+ void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, mode, -1, 0);
+ if (p == MAP_FAILED) throw Error(ERR_CANT_ALLOC);
+ assert(p);
+ sizeList_[(uintptr_t)p] = size;
+ return (uint8*)p;
+ }
+ void free(uint8 *p)
+ {
+ if (p == 0) return;
+ SizeList::iterator i = sizeList_.find((uintptr_t)p);
+ if (i == sizeList_.end()) throw Error(ERR_BAD_PARAMETER);
+ if (munmap((void*)i->first, i->second) < 0) throw Error(ERR_MUNMAP);
+ sizeList_.erase(i);
+ }
+};
+#endif
+
+class Address;
+class Reg;
+
+class Operand {
+ static const uint8 EXT8BIT = 0x20;
+ unsigned int idx_:6; // 0..31 + EXT8BIT = 1 if spl/bpl/sil/dil
+ unsigned int kind_:9;
+ unsigned int bit_:10;
+protected:
+ unsigned int zero_:1;
+ unsigned int mask_:3;
+ unsigned int rounding_:3;
+ void setIdx(int idx) { idx_ = idx; }
+public:
+ enum Kind {
+ NONE = 0,
+ MEM = 1 << 0,
+ REG = 1 << 1,
+ MMX = 1 << 2,
+ FPU = 1 << 3,
+ XMM = 1 << 4,
+ YMM = 1 << 5,
+ ZMM = 1 << 6,
+ OPMASK = 1 << 7,
+ BNDREG = 1 << 8
+ };
+ enum Code {
+#ifdef XBYAK64
+ RAX = 0, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15,
+ R8D = 8, R9D, R10D, R11D, R12D, R13D, R14D, R15D,
+ R8W = 8, R9W, R10W, R11W, R12W, R13W, R14W, R15W,
+ R8B = 8, R9B, R10B, R11B, R12B, R13B, R14B, R15B,
+ SPL = 4, BPL, SIL, DIL,
+#endif
+ EAX = 0, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
+ AX = 0, CX, DX, BX, SP, BP, SI, DI,
+ AL = 0, CL, DL, BL, AH, CH, DH, BH
+ };
+ Operand() : idx_(0), kind_(0), bit_(0), zero_(0), mask_(0), rounding_(0) { }
+ Operand(int idx, Kind kind, int bit, bool ext8bit = 0)
+ : idx_(static_cast<uint8>(idx | (ext8bit ? EXT8BIT : 0)))
+ , kind_(kind)
+ , bit_(bit)
+ , zero_(0), mask_(0), rounding_(0)
+ {
+ assert((bit_ & (bit_ - 1)) == 0); // bit must be power of two
+ }
+ Kind getKind() const { return static_cast<Kind>(kind_); }
+ int getIdx() const { return idx_ & (EXT8BIT - 1); }
+ bool isNone() const { return kind_ == 0; }
+ bool isMMX() const { return is(MMX); }
+ bool isXMM() const { return is(XMM); }
+ bool isYMM() const { return is(YMM); }
+ bool isZMM() const { return is(ZMM); }
+ bool isXMEM() const { return is(XMM | MEM); }
+ bool isYMEM() const { return is(YMM | MEM); }
+ bool isZMEM() const { return is(ZMM | MEM); }
+ bool isOPMASK() const { return is(OPMASK); }
+ bool isBNDREG() const { return is(BNDREG); }
+ bool isREG(int bit = 0) const { return is(REG, bit); }
+ bool isMEM(int bit = 0) const { return is(MEM, bit); }
+ bool isFPU() const { return is(FPU); }
+ bool isExt8bit() const { return (idx_ & EXT8BIT) != 0; }
+ bool isExtIdx() const { return (getIdx() & 8) != 0; }
+ bool isExtIdx2() const { return (getIdx() & 16) != 0; }
+ bool hasEvex() const { return isZMM() || isExtIdx2() || getOpmaskIdx() || getRounding(); }
+ bool hasRex() const { return isExt8bit() || isREG(64) || isExtIdx(); }
+ bool hasZero() const { return zero_; }
+ int getOpmaskIdx() const { return mask_; }
+ int getRounding() const { return rounding_; }
+ void setKind(Kind kind)
+ {
+ if ((kind & (XMM|YMM|ZMM)) == 0) return;
+ kind_ = kind;
+ bit_ = kind == XMM ? 128 : kind == YMM ? 256 : 512;
+ }
+ void setBit(int bit) { bit_ = bit; }
+ void setOpmaskIdx(int idx, bool ignore_idx0 = false)
+ {
+ if (!ignore_idx0 && idx == 0) throw Error(ERR_K0_IS_INVALID);
+ if (mask_) throw Error(ERR_OPMASK_IS_ALREADY_SET);
+ mask_ = idx;
+ }
+ void setRounding(int idx)
+ {
+ if (rounding_) throw Error(ERR_ROUNDING_IS_ALREADY_SET);
+ rounding_ = idx;
+ }
+ void setZero() { zero_ = true; }
+ // ah, ch, dh, bh?
+ bool isHigh8bit() const
+ {
+ if (!isBit(8)) return false;
+ if (isExt8bit()) return false;
+ const int idx = getIdx();
+ return AH <= idx && idx <= BH;
+ }
+ // any bit is accetable if bit == 0
+ bool is(int kind, uint32 bit = 0) const
+ {
+ return (kind == 0 || (kind_ & kind)) && (bit == 0 || (bit_ & bit)); // cf. you can set (8|16)
+ }
+ bool isBit(uint32 bit) const { return (bit_ & bit) != 0; }
+ uint32 getBit() const { return bit_; }
+ const char *toString() const
+ {
+ const int idx = getIdx();
+ if (kind_ == REG) {
+ if (isExt8bit()) {
+ static const char *tbl[4] = { "spl", "bpl", "sil", "dil" };
+ return tbl[idx - 4];
+ }
+ static const char *tbl[4][16] = {
+ { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" },
+ { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" },
+ { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" },
+ { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" },
+ };
+ return tbl[bit_ == 8 ? 0 : bit_ == 16 ? 1 : bit_ == 32 ? 2 : 3][idx];
+ } else if (isOPMASK()) {
+ static const char *tbl[8] = { "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" };
+ return tbl[idx];
+ } else if (isZMM()) {
+ static const char *tbl[32] = {
+ "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15",
+ "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31"
+ };
+ return tbl[idx];
+ } else if (isYMM()) {
+ static const char *tbl[32] = {
+ "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15",
+ "ymm16", "ymm17", "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", "ymm24", "ymm25", "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31"
+ };
+ return tbl[idx];
+ } else if (isXMM()) {
+ static const char *tbl[32] = {
+ "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
+ "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
+ };
+ return tbl[idx];
+ } else if (isMMX()) {
+ static const char *tbl[8] = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" };
+ return tbl[idx];
+ } else if (isFPU()) {
+ static const char *tbl[8] = { "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7" };
+ return tbl[idx];
+ } else if (isBNDREG()) {
+ static const char *tbl[4] = { "bnd0", "bnd1", "bnd2", "bnd3" };
+ return tbl[idx];
+ }
+ throw Error(ERR_INTERNAL);
+ }
+ bool isEqualIfNotInherited(const Operand& rhs) const { return idx_ == rhs.idx_ && kind_ == rhs.kind_ && bit_ == rhs.bit_ && zero_ == rhs.zero_ && mask_ == rhs.mask_ && rounding_ == rhs.rounding_; }
+ bool operator==(const Operand& rhs) const;
+ bool operator!=(const Operand& rhs) const { return !operator==(rhs); }
+ const Address& getAddress() const;
+ const Reg& getReg() const;
+};
+
+class Label;
+
+struct Reg8;
+struct Reg16;
+struct Reg32;
+#ifdef XBYAK64
+struct Reg64;
+#endif
+class Reg : public Operand {
+public:
+ Reg() { }
+ Reg(int idx, Kind kind, int bit = 0, bool ext8bit = false) : Operand(idx, kind, bit, ext8bit) { }
+ Reg changeBit(int bit) const { return Reg(getIdx(), getKind(), bit, isExt8bit()); }
+ uint8 getRexW() const { return isREG(64) ? 8 : 0; }
+ uint8 getRexR() const { return isExtIdx() ? 4 : 0; }
+ uint8 getRexX() const { return isExtIdx() ? 2 : 0; }
+ uint8 getRexB() const { return isExtIdx() ? 1 : 0; }
+ uint8 getRex(const Reg& base = Reg()) const
+ {
+ uint8 rex = getRexW() | getRexR() | base.getRexW() | base.getRexB();
+ if (rex || isExt8bit() || base.isExt8bit()) rex |= 0x40;
+ return rex;
+ }
+ Reg8 cvt8() const;
+ Reg16 cvt16() const;
+ Reg32 cvt32() const;
+#ifdef XBYAK64
+ Reg64 cvt64() const;
+#endif
+};
+
+inline const Reg& Operand::getReg() const
+{
+ assert(!isMEM());
+ return static_cast<const Reg&>(*this);
+}
+
+struct Reg8 : public Reg {
+ explicit Reg8(int idx = 0, bool ext8bit = false) : Reg(idx, Operand::REG, 8, ext8bit) { }
+};
+
+struct Reg16 : public Reg {
+ explicit Reg16(int idx = 0) : Reg(idx, Operand::REG, 16) { }
+};
+
+struct Mmx : public Reg {
+ explicit Mmx(int idx = 0, Kind kind = Operand::MMX, int bit = 64) : Reg(idx, kind, bit) { }
+};
+
+struct EvexModifierRounding {
+ enum {
+ T_RN_SAE = 1,
+ T_RD_SAE = 2,
+ T_RU_SAE = 3,
+ T_RZ_SAE = 4,
+ T_SAE = 5
+ };
+ explicit EvexModifierRounding(int rounding) : rounding(rounding) {}
+ int rounding;
+};
+struct EvexModifierZero{EvexModifierZero() {}};
+
+struct Xmm : public Mmx {
+ explicit Xmm(int idx = 0, Kind kind = Operand::XMM, int bit = 128) : Mmx(idx, kind, bit) { }
+ Xmm(Kind kind, int idx) : Mmx(idx, kind, kind == XMM ? 128 : kind == YMM ? 256 : 512) { }
+ Xmm operator|(const EvexModifierRounding& emr) const { Xmm r(*this); r.setRounding(emr.rounding); return r; }
+ Xmm copyAndSetIdx(int idx) const { Xmm ret(*this); ret.setIdx(idx); return ret; }
+ Xmm copyAndSetKind(Operand::Kind kind) const { Xmm ret(*this); ret.setKind(kind); return ret; }
+};
+
+struct Ymm : public Xmm {
+ explicit Ymm(int idx = 0, Kind kind = Operand::YMM, int bit = 256) : Xmm(idx, kind, bit) { }
+ Ymm operator|(const EvexModifierRounding& emr) const { Ymm r(*this); r.setRounding(emr.rounding); return r; }
+};
+
+struct Zmm : public Ymm {
+ explicit Zmm(int idx = 0) : Ymm(idx, Operand::ZMM, 512) { }
+ Zmm operator|(const EvexModifierRounding& emr) const { Zmm r(*this); r.setRounding(emr.rounding); return r; }
+};
+
+struct Opmask : public Reg {
+ explicit Opmask(int idx = 0) : Reg(idx, Operand::OPMASK, 64) {}
+};
+
+struct BoundsReg : public Reg {
+ explicit BoundsReg(int idx = 0) : Reg(idx, Operand::BNDREG, 128) {}
+};
+
+template<class T>T operator|(const T& x, const Opmask& k) { T r(x); r.setOpmaskIdx(k.getIdx()); return r; }
+template<class T>T operator|(const T& x, const EvexModifierZero&) { T r(x); r.setZero(); return r; }
+template<class T>T operator|(const T& x, const EvexModifierRounding& emr) { T r(x); r.setRounding(emr.rounding); return r; }
+
+struct Fpu : public Reg {
+ explicit Fpu(int idx = 0) : Reg(idx, Operand::FPU, 32) { }
+};
+
+struct Reg32e : public Reg {
+ explicit Reg32e(int idx, int bit) : Reg(idx, Operand::REG, bit) {}
+};
+struct Reg32 : public Reg32e {
+ explicit Reg32(int idx = 0) : Reg32e(idx, 32) {}
+};
+#ifdef XBYAK64
+struct Reg64 : public Reg32e {
+ explicit Reg64(int idx = 0) : Reg32e(idx, 64) {}
+};
+struct RegRip {
+ sint64 disp_;
+ const Label* label_;
+ bool isAddr_;
+ explicit RegRip(sint64 disp = 0, const Label* label = 0, bool isAddr = false) : disp_(disp), label_(label), isAddr_(isAddr) {}
+ friend const RegRip operator+(const RegRip& r, int disp) {
+ return RegRip(r.disp_ + disp, r.label_, r.isAddr_);
+ }
+ friend const RegRip operator-(const RegRip& r, int disp) {
+ return RegRip(r.disp_ - disp, r.label_, r.isAddr_);
+ }
+ friend const RegRip operator+(const RegRip& r, sint64 disp) {
+ return RegRip(r.disp_ + disp, r.label_, r.isAddr_);
+ }
+ friend const RegRip operator-(const RegRip& r, sint64 disp) {
+ return RegRip(r.disp_ - disp, r.label_, r.isAddr_);
+ }
+ friend const RegRip operator+(const RegRip& r, const Label& label) {
+ if (r.label_ || r.isAddr_) throw Error(ERR_BAD_ADDRESSING);
+ return RegRip(r.disp_, &label);
+ }
+ friend const RegRip operator+(const RegRip& r, const void *addr) {
+ if (r.label_ || r.isAddr_) throw Error(ERR_BAD_ADDRESSING);
+ return RegRip(r.disp_ + (sint64)addr, 0, true);
+ }
+};
+#endif
+
+inline Reg8 Reg::cvt8() const
+{
+ const int idx = getIdx();
+ if (isBit(8)) return Reg8(idx, isExt8bit());
+#ifdef XBYAK32
+ if (idx >= 4) throw Error(ERR_CANT_CONVERT);
+#endif
+ return Reg8(idx, 4 <= idx && idx < 8);
+}
+
+inline Reg16 Reg::cvt16() const
+{
+ const int idx = getIdx();
+ if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT);
+ return Reg16(idx);
+}
+
+inline Reg32 Reg::cvt32() const
+{
+ const int idx = getIdx();
+ if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT);
+ return Reg32(idx);
+}
+
+#ifdef XBYAK64
+inline Reg64 Reg::cvt64() const
+{
+ const int idx = getIdx();
+ if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT);
+ return Reg64(idx);
+}
+#endif
+
+#ifndef XBYAK_DISABLE_SEGMENT
+// not derived from Reg
+class Segment {
+ int idx_;
+public:
+ enum {
+ es, cs, ss, ds, fs, gs
+ };
+ explicit Segment(int idx) : idx_(idx) { assert(0 <= idx_ && idx_ < 6); }
+ int getIdx() const { return idx_; }
+ const char *toString() const
+ {
+ static const char tbl[][3] = {
+ "es", "cs", "ss", "ds", "fs", "gs"
+ };
+ return tbl[idx_];
+ }
+};
+#endif
+
+class RegExp {
+public:
+#ifdef XBYAK64
+ enum { i32e = 32 | 64 };
+#else
+ enum { i32e = 32 };
+#endif
+ RegExp(size_t disp = 0) : scale_(0), disp_(disp) { }
+ RegExp(const Reg& r, int scale = 1)
+ : scale_(scale)
+ , disp_(0)
+ {
+ if (!r.isREG(i32e) && !r.is(Reg::XMM|Reg::YMM|Reg::ZMM)) throw Error(ERR_BAD_SIZE_OF_REGISTER);
+ if (scale == 0) return;
+ if (scale != 1 && scale != 2 && scale != 4 && scale != 8) throw Error(ERR_BAD_SCALE);
+ if (r.getBit() >= 128 || scale != 1) { // xmm/ymm is always index
+ index_ = r;
+ } else {
+ base_ = r;
+ }
+ }
+ bool isVsib(int bit = 128 | 256 | 512) const { return index_.isBit(bit); }
+ RegExp optimize() const
+ {
+ RegExp exp = *this;
+ // [reg * 2] => [reg + reg]
+ if (index_.isBit(i32e) && !base_.getBit() && scale_ == 2) {
+ exp.base_ = index_;
+ exp.scale_ = 1;
+ }
+ return exp;
+ }
+ bool operator==(const RegExp& rhs) const
+ {
+ return base_ == rhs.base_ && index_ == rhs.index_ && disp_ == rhs.disp_ && scale_ == rhs.scale_;
+ }
+ const Reg& getBase() const { return base_; }
+ const Reg& getIndex() const { return index_; }
+ int getScale() const { return scale_; }
+ size_t getDisp() const { return disp_; }
+ void verify() const
+ {
+ if (base_.getBit() >= 128) throw Error(ERR_BAD_SIZE_OF_REGISTER);
+ if (index_.getBit() && index_.getBit() <= 64) {
+ if (index_.getIdx() == Operand::ESP) throw Error(ERR_ESP_CANT_BE_INDEX);
+ if (base_.getBit() && base_.getBit() != index_.getBit()) throw Error(ERR_BAD_SIZE_OF_REGISTER);
+ }
+ }
+ friend RegExp operator+(const RegExp& a, const RegExp& b);
+ friend RegExp operator-(const RegExp& e, size_t disp);
+ uint8 getRex() const
+ {
+ uint8 rex = index_.getRexX() | base_.getRexB();
+ return rex ? uint8(rex | 0x40) : 0;
+ }
+private:
+ /*
+ [base_ + index_ * scale_ + disp_]
+ base : Reg32e, index : Reg32e(w/o esp), Xmm, Ymm
+ */
+ Reg base_;
+ Reg index_;
+ int scale_;
+ size_t disp_;
+};
+
+inline RegExp operator+(const RegExp& a, const RegExp& b)
+{
+ if (a.index_.getBit() && b.index_.getBit()) throw Error(ERR_BAD_ADDRESSING);
+ RegExp ret = a;
+ if (!ret.index_.getBit()) { ret.index_ = b.index_; ret.scale_ = b.scale_; }
+ if (b.base_.getBit()) {
+ if (ret.base_.getBit()) {
+ if (ret.index_.getBit()) throw Error(ERR_BAD_ADDRESSING);
+ // base + base => base + index * 1
+ ret.index_ = b.base_;
+ // [reg + esp] => [esp + reg]
+ if (ret.index_.getIdx() == Operand::ESP) std::swap(ret.base_, ret.index_);
+ ret.scale_ = 1;
+ } else {
+ ret.base_ = b.base_;
+ }
+ }
+ ret.disp_ += b.disp_;
+ return ret;
+}
+inline RegExp operator*(const Reg& r, int scale)
+{
+ return RegExp(r, scale);
+}
+inline RegExp operator-(const RegExp& e, size_t disp)
+{
+ RegExp ret = e;
+ ret.disp_ -= disp;
+ return ret;
+}
+
+// 2nd parameter for constructor of CodeArray(maxSize, userPtr, alloc)
+void *const AutoGrow = (void*)1; //-V566
+void *const DontSetProtectRWE = (void*)2; //-V566
+
+class CodeArray {
+ enum Type {
+ USER_BUF = 1, // use userPtr(non alignment, non protect)
+ ALLOC_BUF, // use new(alignment, protect)
+ AUTO_GROW // automatically move and grow memory if necessary
+ };
+ CodeArray(const CodeArray& rhs);
+ void operator=(const CodeArray&);
+ bool isAllocType() const { return type_ == ALLOC_BUF || type_ == AUTO_GROW; }
+ struct AddrInfo {
+ size_t codeOffset; // position to write
+ size_t jmpAddr; // value to write
+ int jmpSize; // size of jmpAddr
+ inner::LabelMode mode;
+ AddrInfo(size_t _codeOffset, size_t _jmpAddr, int _jmpSize, inner::LabelMode _mode)
+ : codeOffset(_codeOffset), jmpAddr(_jmpAddr), jmpSize(_jmpSize), mode(_mode) {}
+ uint64 getVal(const uint8 *top) const
+ {
+ uint64 disp = (mode == inner::LaddTop) ? jmpAddr + size_t(top) : (mode == inner::LasIs) ? jmpAddr : jmpAddr - size_t(top);
+ if (jmpSize == 4) disp = inner::VerifyInInt32(disp);
+ return disp;
+ }
+ };
+ typedef std::list<AddrInfo> AddrInfoList;
+ AddrInfoList addrInfoList_;
+ const Type type_;
+#ifdef XBYAK_USE_MMAP_ALLOCATOR
+ MmapAllocator defaultAllocator_;
+#else
+ Allocator defaultAllocator_;
+#endif
+ Allocator *alloc_;
+protected:
+ size_t maxSize_;
+ uint8 *top_;
+ size_t size_;
+ bool isCalledCalcJmpAddress_;
+
+ bool useProtect() const { return alloc_->useProtect(); }
+ /*
+ allocate new memory and copy old data to the new area
+ */
+ void growMemory()
+ {
+ const size_t newSize = (std::max<size_t>)(DEFAULT_MAX_CODE_SIZE, maxSize_ * 2);
+ uint8 *newTop = alloc_->alloc(newSize);
+ if (newTop == 0) throw Error(ERR_CANT_ALLOC);
+ for (size_t i = 0; i < size_; i++) newTop[i] = top_[i];
+ alloc_->free(top_);
+ top_ = newTop;
+ maxSize_ = newSize;
+ }
+ /*
+ calc jmp address for AutoGrow mode
+ */
+ void calcJmpAddress()
+ {
+ if (isCalledCalcJmpAddress_) return;
+ for (AddrInfoList::const_iterator i = addrInfoList_.begin(), ie = addrInfoList_.end(); i != ie; ++i) {
+ uint64 disp = i->getVal(top_);
+ rewrite(i->codeOffset, disp, i->jmpSize);
+ }
+ isCalledCalcJmpAddress_ = true;
+ }
+public:
+ enum ProtectMode {
+ PROTECT_RW = 0, // read/write
+ PROTECT_RWE = 1, // read/write/exec
+ PROTECT_RE = 2 // read/exec
+ };
+ explicit CodeArray(size_t maxSize, void *userPtr = 0, Allocator *allocator = 0)
+ : type_(userPtr == AutoGrow ? AUTO_GROW : (userPtr == 0 || userPtr == DontSetProtectRWE) ? ALLOC_BUF : USER_BUF)
+ , alloc_(allocator ? allocator : (Allocator*)&defaultAllocator_)
+ , maxSize_(maxSize)
+ , top_(type_ == USER_BUF ? reinterpret_cast<uint8*>(userPtr) : alloc_->alloc((std::max<size_t>)(maxSize, 1)))
+ , size_(0)
+ , isCalledCalcJmpAddress_(false)
+ {
+ if (maxSize_ > 0 && top_ == 0) throw Error(ERR_CANT_ALLOC);
+ if ((type_ == ALLOC_BUF && userPtr != DontSetProtectRWE && useProtect()) && !setProtectMode(PROTECT_RWE, false)) {
+ alloc_->free(top_);
+ throw Error(ERR_CANT_PROTECT);
+ }
+ }
+ virtual ~CodeArray()
+ {
+ if (isAllocType()) {
+ if (useProtect()) setProtectModeRW(false);
+ alloc_->free(top_);
+ }
+ }
+ bool setProtectMode(ProtectMode mode, bool throwException = true)
+ {
+ bool isOK = protect(top_, maxSize_, mode);
+ if (isOK) return true;
+ if (throwException) throw Error(ERR_CANT_PROTECT);
+ return false;
+ }
+ bool setProtectModeRE(bool throwException = true) { return setProtectMode(PROTECT_RE, throwException); }
+ bool setProtectModeRW(bool throwException = true) { return setProtectMode(PROTECT_RW, throwException); }
+ void resetSize()
+ {
+ size_ = 0;
+ addrInfoList_.clear();
+ isCalledCalcJmpAddress_ = false;
+ }
+ void db(int code)
+ {
+ if (size_ >= maxSize_) {
+ if (type_ == AUTO_GROW) {
+ growMemory();
+ } else {
+ throw Error(ERR_CODE_IS_TOO_BIG);
+ }
+ }
+ top_[size_++] = static_cast<uint8>(code);
+ }
+ void db(const uint8 *code, size_t codeSize)
+ {
+ for (size_t i = 0; i < codeSize; i++) db(code[i]);
+ }
+ void db(uint64 code, size_t codeSize)
+ {
+ if (codeSize > 8) throw Error(ERR_BAD_PARAMETER);
+ for (size_t i = 0; i < codeSize; i++) db(static_cast<uint8>(code >> (i * 8)));
+ }
+ void dw(uint32 code) { db(code, 2); }
+ void dd(uint32 code) { db(code, 4); }
+ void dq(uint64 code) { db(code, 8); }
+ const uint8 *getCode() const { return top_; }
+ template<class F>
+ const F getCode() const { return reinterpret_cast<F>(top_); }
+ const uint8 *getCurr() const { return &top_[size_]; }
+ template<class F>
+ const F getCurr() const { return reinterpret_cast<F>(&top_[size_]); }
+ size_t getSize() const { return size_; }
+ void setSize(size_t size)
+ {
+ if (size > maxSize_) throw Error(ERR_OFFSET_IS_TOO_BIG);
+ size_ = size;
+ }
+ void dump() const
+ {
+ const uint8 *p = getCode();
+ size_t bufSize = getSize();
+ size_t remain = bufSize;
+ for (int i = 0; i < 4; i++) {
+ size_t disp = 16;
+ if (remain < 16) {
+ disp = remain;
+ }
+ for (size_t j = 0; j < 16; j++) {
+ if (j < disp) {
+ printf("%02X", p[i * 16 + j]);
+ }
+ }
+ putchar('\n');
+ remain -= disp;
+ if (remain == 0) {
+ break;
+ }
+ }
+ }
+ /*
+ @param offset [in] offset from top
+ @param disp [in] offset from the next of jmp
+ @param size [in] write size(1, 2, 4, 8)
+ */
+ void rewrite(size_t offset, uint64 disp, size_t size)
+ {
+ assert(offset < maxSize_);
+ if (size != 1 && size != 2 && size != 4 && size != 8) throw Error(ERR_BAD_PARAMETER);
+ uint8 *const data = top_ + offset;
+ for (size_t i = 0; i < size; i++) {
+ data[i] = static_cast<uint8>(disp >> (i * 8));
+ }
+ }
+ void save(size_t offset, size_t val, int size, inner::LabelMode mode)
+ {
+ addrInfoList_.push_back(AddrInfo(offset, val, size, mode));
+ }
+ bool isAutoGrow() const { return type_ == AUTO_GROW; }
+ bool isCalledCalcJmpAddress() const { return isCalledCalcJmpAddress_; }
+ /**
+ change exec permission of memory
+ @param addr [in] buffer address
+ @param size [in] buffer size
+ @param protectMode [in] mode(RW/RWE/RE)
+ @return true(success), false(failure)
+ */
+ static inline bool protect(const void *addr, size_t size, int protectMode)
+ {
+#if defined(_WIN32)
+ const DWORD c_rw = PAGE_READWRITE;
+ const DWORD c_rwe = PAGE_EXECUTE_READWRITE;
+ const DWORD c_re = PAGE_EXECUTE_READ;
+ DWORD mode;
+#else
+ const int c_rw = PROT_READ | PROT_WRITE;
+ const int c_rwe = PROT_READ | PROT_WRITE | PROT_EXEC;
+ const int c_re = PROT_READ | PROT_EXEC;
+ int mode;
+#endif
+ switch (protectMode) {
+ case PROTECT_RW: mode = c_rw; break;
+ case PROTECT_RWE: mode = c_rwe; break;
+ case PROTECT_RE: mode = c_re; break;
+ default:
+ return false;
+ }
+#if defined(_WIN32)
+ DWORD oldProtect;
+ return VirtualProtect(const_cast<void*>(addr), size, mode, &oldProtect) != 0;
+#elif defined(__GNUC__)
+ size_t pageSize = sysconf(_SC_PAGESIZE);
+ size_t iaddr = reinterpret_cast<size_t>(addr);
+ size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
+#ifndef NDEBUG
+ if (pageSize != 4096) fprintf(stderr, "large page(%zd) is used. not tested enough.\n", pageSize);
+#endif
+ return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0;
+#else
+ return true;
+#endif
+ }
+ /**
+ get aligned memory pointer
+ @param addr [in] address
+ @param alignedSize [in] power of two
+ @return aligned addr by alingedSize
+ */
+ static inline uint8 *getAlignedAddress(uint8 *addr, size_t alignedSize = 16)
+ {
+ return reinterpret_cast<uint8*>((reinterpret_cast<size_t>(addr) + alignedSize - 1) & ~(alignedSize - static_cast<size_t>(1)));
+ }
+};
+
+class Address : public Operand {
+public:
+ enum Mode {
+ M_ModRM,
+ M_64bitDisp,
+ M_rip,
+ M_ripAddr
+ };
+ Address(uint32 sizeBit, bool broadcast, const RegExp& e)
+ : Operand(0, MEM, sizeBit), e_(e), label_(0), mode_(M_ModRM), broadcast_(broadcast)
+ {
+ e_.verify();
+ }
+#ifdef XBYAK64
+ explicit Address(size_t disp)
+ : Operand(0, MEM, 64), e_(disp), label_(0), mode_(M_64bitDisp), broadcast_(false){ }
+ Address(uint32 sizeBit, bool broadcast, const RegRip& addr)
+ : Operand(0, MEM, sizeBit), e_(addr.disp_), label_(addr.label_), mode_(addr.isAddr_ ? M_ripAddr : M_rip), broadcast_(broadcast) { }
+#endif
+ RegExp getRegExp(bool optimize = true) const
+ {
+ return optimize ? e_.optimize() : e_;
+ }
+ Mode getMode() const { return mode_; }
+ bool is32bit() const { return e_.getBase().getBit() == 32 || e_.getIndex().getBit() == 32; }
+ bool isOnlyDisp() const { return !e_.getBase().getBit() && !e_.getIndex().getBit(); } // for mov eax
+ size_t getDisp() const { return e_.getDisp(); }
+ uint8 getRex() const
+ {
+ if (mode_ != M_ModRM) return 0;
+ return getRegExp().getRex();
+ }
+ bool is64bitDisp() const { return mode_ == M_64bitDisp; } // for moffset
+ bool isBroadcast() const { return broadcast_; }
+ const Label* getLabel() const { return label_; }
+ bool operator==(const Address& rhs) const
+ {
+ return getBit() == rhs.getBit() && e_ == rhs.e_ && label_ == rhs.label_ && mode_ == rhs.mode_ && broadcast_ == rhs.broadcast_;
+ }
+ bool operator!=(const Address& rhs) const { return !operator==(rhs); }
+ bool isVsib() const { return e_.isVsib(); }
+private:
+ RegExp e_;
+ const Label* label_;
+ Mode mode_;
+ bool broadcast_;
+};
+
+inline const Address& Operand::getAddress() const
+{
+ assert(isMEM());
+ return static_cast<const Address&>(*this);
+}
+
+inline bool Operand::operator==(const Operand& rhs) const
+{
+ if (isMEM() && rhs.isMEM()) return this->getAddress() == rhs.getAddress();
+ return isEqualIfNotInherited(rhs);
+}
+
+class AddressFrame {
+ void operator=(const AddressFrame&);
+ AddressFrame(const AddressFrame&);
+public:
+ const uint32 bit_;
+ const bool broadcast_;
+ explicit AddressFrame(uint32 bit, bool broadcast = false) : bit_(bit), broadcast_(broadcast) { }
+ Address operator[](const RegExp& e) const
+ {
+ return Address(bit_, broadcast_, e);
+ }
+ Address operator[](const void *disp) const
+ {
+ return Address(bit_, broadcast_, RegExp(reinterpret_cast<size_t>(disp)));
+ }
+#ifdef XBYAK64
+ Address operator[](uint64 disp) const { return Address(disp); }
+ Address operator[](const RegRip& addr) const { return Address(bit_, broadcast_, addr); }
+#endif
+};
+
+struct JmpLabel {
+ size_t endOfJmp; /* offset from top to the end address of jmp */
+ int jmpSize;
+ inner::LabelMode mode;
+ size_t disp; // disp for [rip + disp]
+ explicit JmpLabel(size_t endOfJmp = 0, int jmpSize = 0, inner::LabelMode mode = inner::LasIs, size_t disp = 0)
+ : endOfJmp(endOfJmp), jmpSize(jmpSize), mode(mode), disp(disp)
+ {
+ }
+};
+
+class LabelManager;
+
+class Label {
+ mutable LabelManager *mgr;
+ mutable int id;
+ friend class LabelManager;
+public:
+ Label() : mgr(0), id(0) {}
+ Label(const Label& rhs);
+ Label& operator=(const Label& rhs);
+ ~Label();
+ void clear() { mgr = 0; id = 0; }
+ int getId() const { return id; }
+ const uint8 *getAddress() const;
+
+ // backward compatibility
+ static inline std::string toStr(int num)
+ {
+ char buf[16];
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+ _snprintf_s
+#else
+ snprintf
+#endif
+ (buf, sizeof(buf), ".%08x", num);
+ return buf;
+ }
+};
+
+class LabelManager {
+ // for string label
+ struct SlabelVal {
+ size_t offset;
+ SlabelVal(size_t offset) : offset(offset) {}
+ };
+ typedef XBYAK_STD_UNORDERED_MAP<std::string, SlabelVal> SlabelDefList;
+ typedef XBYAK_STD_UNORDERED_MULTIMAP<std::string, const JmpLabel> SlabelUndefList;
+ struct SlabelState {
+ SlabelDefList defList;
+ SlabelUndefList undefList;
+ };
+ typedef std::list<SlabelState> StateList;
+ // for Label class
+ struct ClabelVal {
+ ClabelVal(size_t offset = 0) : offset(offset), refCount(1) {}
+ size_t offset;
+ int refCount;
+ };
+ typedef XBYAK_STD_UNORDERED_MAP<int, ClabelVal> ClabelDefList;
+ typedef XBYAK_STD_UNORDERED_MULTIMAP<int, const JmpLabel> ClabelUndefList;
+ typedef XBYAK_STD_UNORDERED_SET<Label*> LabelPtrList;
+
+ CodeArray *base_;
+ // global : stateList_.front(), local : stateList_.back()
+ StateList stateList_;
+ mutable int labelId_;
+ ClabelDefList clabelDefList_;
+ ClabelUndefList clabelUndefList_;
+ LabelPtrList labelPtrList_;
+
+ int getId(const Label& label) const
+ {
+ if (label.id == 0) label.id = labelId_++;
+ return label.id;
+ }
+ template<class DefList, class UndefList, class T>
+ void define_inner(DefList& defList, UndefList& undefList, const T& labelId, size_t addrOffset)
+ {
+ // add label
+ typename DefList::value_type item(labelId, addrOffset);
+ std::pair<typename DefList::iterator, bool> ret = defList.insert(item);
+ if (!ret.second) throw Error(ERR_LABEL_IS_REDEFINED);
+ // search undefined label
+ for (;;) {
+ typename UndefList::iterator itr = undefList.find(labelId);
+ if (itr == undefList.end()) break;
+ const JmpLabel *jmp = &itr->second;
+ const size_t offset = jmp->endOfJmp - jmp->jmpSize;
+ size_t disp;
+ if (jmp->mode == inner::LaddTop) {
+ disp = addrOffset;
+ } else if (jmp->mode == inner::Labs) {
+ disp = size_t(base_->getCurr());
+ } else {
+ disp = addrOffset - jmp->endOfJmp + jmp->disp;
+#ifdef XBYAK64
+ if (jmp->jmpSize <= 4 && !inner::IsInInt32(disp)) throw Error(ERR_OFFSET_IS_TOO_BIG);
+#endif
+ if (jmp->jmpSize == 1 && !inner::IsInDisp8((uint32)disp)) throw Error(ERR_LABEL_IS_TOO_FAR);
+ }
+ if (base_->isAutoGrow()) {
+ base_->save(offset, disp, jmp->jmpSize, jmp->mode);
+ } else {
+ base_->rewrite(offset, disp, jmp->jmpSize);
+ }
+ undefList.erase(itr);
+ }
+ }
+ template<class DefList, class T>
+ bool getOffset_inner(const DefList& defList, size_t *offset, const T& label) const
+ {
+ typename DefList::const_iterator i = defList.find(label);
+ if (i == defList.end()) return false;
+ *offset = i->second.offset;
+ return true;
+ }
+ friend class Label;
+ void incRefCount(int id, Label *label)
+ {
+ clabelDefList_[id].refCount++;
+ labelPtrList_.insert(label);
+ }
+ void decRefCount(int id, Label *label)
+ {
+ labelPtrList_.erase(label);
+ ClabelDefList::iterator i = clabelDefList_.find(id);
+ if (i == clabelDefList_.end()) return;
+ if (i->second.refCount == 1) {
+ clabelDefList_.erase(id);
+ } else {
+ --i->second.refCount;
+ }
+ }
+ template<class T>
+ bool hasUndefinedLabel_inner(const T& list) const
+ {
+#ifndef NDEBUG
+ for (typename T::const_iterator i = list.begin(); i != list.end(); ++i) {
+ std::cerr << "undefined label:" << i->first << std::endl;
+ }
+#endif
+ return !list.empty();
+ }
+ // detach all labels linked to LabelManager
+ void resetLabelPtrList()
+ {
+ for (LabelPtrList::iterator i = labelPtrList_.begin(), ie = labelPtrList_.end(); i != ie; ++i) {
+ (*i)->clear();
+ }
+ labelPtrList_.clear();
+ }
+public:
+ LabelManager()
+ {
+ reset();
+ }
+ ~LabelManager()
+ {
+ resetLabelPtrList();
+ }
+ void reset()
+ {
+ base_ = 0;
+ labelId_ = 1;
+ stateList_.clear();
+ stateList_.push_back(SlabelState());
+ stateList_.push_back(SlabelState());
+ clabelDefList_.clear();
+ clabelUndefList_.clear();
+ resetLabelPtrList();
+ }
+ void enterLocal()
+ {
+ stateList_.push_back(SlabelState());
+ }
+ void leaveLocal()
+ {
+ if (stateList_.size() <= 2) throw Error(ERR_UNDER_LOCAL_LABEL);
+ if (hasUndefinedLabel_inner(stateList_.back().undefList)) throw Error(ERR_LABEL_IS_NOT_FOUND);
+ stateList_.pop_back();
+ }
+ void set(CodeArray *base) { base_ = base; }
+ void defineSlabel(std::string label)
+ {
+ if (label == "@b" || label == "@f") throw Error(ERR_BAD_LABEL_STR);
+ if (label == "@@") {
+ SlabelDefList& defList = stateList_.front().defList;
+ SlabelDefList::iterator i = defList.find("@f");
+ if (i != defList.end()) {
+ defList.erase(i);
+ label = "@b";
+ } else {
+ i = defList.find("@b");
+ if (i != defList.end()) {
+ defList.erase(i);
+ }
+ label = "@f";
+ }
+ }
+ SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
+ define_inner(st.defList, st.undefList, label, base_->getSize());
+ }
+ void defineClabel(Label& label)
+ {
+ define_inner(clabelDefList_, clabelUndefList_, getId(label), base_->getSize());
+ label.mgr = this;
+ labelPtrList_.insert(&label);
+ }
+ void assign(Label& dst, const Label& src)
+ {
+ ClabelDefList::const_iterator i = clabelDefList_.find(src.id);
+ if (i == clabelDefList_.end()) throw Error(ERR_LABEL_ISNOT_SET_BY_L);
+ define_inner(clabelDefList_, clabelUndefList_, dst.id, i->second.offset);
+ dst.mgr = this;
+ labelPtrList_.insert(&dst);
+ }
+ bool getOffset(size_t *offset, std::string& label) const
+ {
+ const SlabelDefList& defList = stateList_.front().defList;
+ if (label == "@b") {
+ if (defList.find("@f") != defList.end()) {
+ label = "@f";
+ } else if (defList.find("@b") == defList.end()) {
+ throw Error(ERR_LABEL_IS_NOT_FOUND);
+ }
+ } else if (label == "@f") {
+ if (defList.find("@f") != defList.end()) {
+ label = "@b";
+ }
+ }
+ const SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
+ return getOffset_inner(st.defList, offset, label);
+ }
+ bool getOffset(size_t *offset, const Label& label) const
+ {
+ return getOffset_inner(clabelDefList_, offset, getId(label));
+ }
+ void addUndefinedLabel(const std::string& label, const JmpLabel& jmp)
+ {
+ SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
+ st.undefList.insert(SlabelUndefList::value_type(label, jmp));
+ }
+ void addUndefinedLabel(const Label& label, const JmpLabel& jmp)
+ {
+ clabelUndefList_.insert(ClabelUndefList::value_type(label.id, jmp));
+ }
+ bool hasUndefSlabel() const
+ {
+ for (StateList::const_iterator i = stateList_.begin(), ie = stateList_.end(); i != ie; ++i) {
+ if (hasUndefinedLabel_inner(i->undefList)) return true;
+ }
+ return false;
+ }
+ bool hasUndefClabel() const { return hasUndefinedLabel_inner(clabelUndefList_); }
+ const uint8 *getCode() const { return base_->getCode(); }
+ bool isReady() const { return !base_->isAutoGrow() || base_->isCalledCalcJmpAddress(); }
+};
+
+inline Label::Label(const Label& rhs)
+{
+ id = rhs.id;
+ mgr = rhs.mgr;
+ if (mgr) mgr->incRefCount(id, this);
+}
+inline Label& Label::operator=(const Label& rhs)
+{
+ if (id) throw Error(ERR_LABEL_IS_ALREADY_SET_BY_L);
+ id = rhs.id;
+ mgr = rhs.mgr;
+ if (mgr) mgr->incRefCount(id, this);
+ return *this;
+}
+inline Label::~Label()
+{
+ if (id && mgr) mgr->decRefCount(id, this);
+}
+inline const uint8* Label::getAddress() const
+{
+ if (mgr == 0 || !mgr->isReady()) return 0;
+ size_t offset;
+ if (!mgr->getOffset(&offset, *this)) return 0;
+ return mgr->getCode() + offset;
+}
+
+class CodeGenerator : public CodeArray {
+public:
+ enum LabelType {
+ T_SHORT,
+ T_NEAR,
+ T_AUTO // T_SHORT if possible
+ };
+private:
+ CodeGenerator operator=(const CodeGenerator&); // don't call
+#ifdef XBYAK64
+ enum { i32e = 32 | 64, BIT = 64 };
+ static const size_t dummyAddr = (size_t(0x11223344) << 32) | 55667788;
+ typedef Reg64 NativeReg;
+#else
+ enum { i32e = 32, BIT = 32 };
+ static const size_t dummyAddr = 0x12345678;
+ typedef Reg32 NativeReg;
+#endif
+ // (XMM, XMM|MEM)
+ static inline bool isXMM_XMMorMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isXMM() && (op2.isXMM() || op2.isMEM());
+ }
+ // (MMX, MMX|MEM) or (XMM, XMM|MEM)
+ static inline bool isXMMorMMX_MEM(const Operand& op1, const Operand& op2)
+ {
+ return (op1.isMMX() && (op2.isMMX() || op2.isMEM())) || isXMM_XMMorMEM(op1, op2);
+ }
+ // (XMM, MMX|MEM)
+ static inline bool isXMM_MMXorMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isXMM() && (op2.isMMX() || op2.isMEM());
+ }
+ // (MMX, XMM|MEM)
+ static inline bool isMMX_XMMorMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isMMX() && (op2.isXMM() || op2.isMEM());
+ }
+ // (XMM, REG32|MEM)
+ static inline bool isXMM_REG32orMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isXMM() && (op2.isREG(i32e) || op2.isMEM());
+ }
+ // (REG32, XMM|MEM)
+ static inline bool isREG32_XMMorMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isREG(i32e) && (op2.isXMM() || op2.isMEM());
+ }
+ // (REG32, REG32|MEM)
+ static inline bool isREG32_REG32orMEM(const Operand& op1, const Operand& op2)
+ {
+ return op1.isREG(i32e) && ((op2.isREG(i32e) && op1.getBit() == op2.getBit()) || op2.isMEM());
+ }
+ void rex(const Operand& op1, const Operand& op2 = Operand())
+ {
+ uint8 rex = 0;
+ const Operand *p1 = &op1, *p2 = &op2;
+ if (p1->isMEM()) std::swap(p1, p2);
+ if (p1->isMEM()) throw Error(ERR_BAD_COMBINATION);
+ if (p2->isMEM()) {
+ const Address& addr = p2->getAddress();
+ if (BIT == 64 && addr.is32bit()) db(0x67);
+ rex = addr.getRex() | p1->getReg().getRex();
+ } else {
+ // ModRM(reg, base);
+ rex = op2.getReg().getRex(op1.getReg());
+ }
+ // except movsx(16bit, 32/64bit)
+ if ((op1.isBit(16) && !op2.isBit(i32e)) || (op2.isBit(16) && !op1.isBit(i32e))) db(0x66);
+ if (rex) db(rex);
+ }
+ enum AVXtype {
+ // low 3 bit
+ T_N1 = 1,
+ T_N2 = 2,
+ T_N4 = 3,
+ T_N8 = 4,
+ T_N16 = 5,
+ T_N32 = 6,
+ T_NX_MASK = 7,
+ //
+ T_N_VL = 1 << 3, // N * (1, 2, 4) for VL
+ T_DUP = 1 << 4, // N = (8, 32, 64)
+ T_66 = 1 << 5,
+ T_F3 = 1 << 6,
+ T_F2 = 1 << 7,
+ T_0F = 1 << 8,
+ T_0F38 = 1 << 9,
+ T_0F3A = 1 << 10,
+ T_L0 = 1 << 11,
+ T_L1 = 1 << 12,
+ T_W0 = 1 << 13,
+ T_W1 = 1 << 14,
+ T_EW0 = 1 << 15,
+ T_EW1 = 1 << 16,
+ T_YMM = 1 << 17, // support YMM, ZMM
+ T_EVEX = 1 << 18,
+ T_ER_X = 1 << 19, // xmm{er}
+ T_ER_Y = 1 << 20, // ymm{er}
+ T_ER_Z = 1 << 21, // zmm{er}
+ T_SAE_X = 1 << 22, // xmm{sae}
+ T_SAE_Y = 1 << 23, // ymm{sae}
+ T_SAE_Z = 1 << 24, // zmm{sae}
+ T_MUST_EVEX = 1 << 25, // contains T_EVEX
+ T_B32 = 1 << 26, // m32bcst
+ T_B64 = 1 << 27, // m64bcst
+ T_M_K = 1 << 28, // mem{k}
+ T_VSIB = 1 << 29,
+ T_MEM_EVEX = 1 << 30, // use evex if mem
+ T_XXX
+ };
+ void vex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false)
+ {
+ int w = (type & T_W1) ? 1 : 0;
+ bool is256 = (type & T_L1) ? true : (type & T_L0) ? false : reg.isYMM();
+ bool r = reg.isExtIdx();
+ bool b = base.isExtIdx();
+ int idx = v ? v->getIdx() : 0;
+ if ((idx | reg.getIdx() | base.getIdx()) >= 16) throw Error(ERR_BAD_COMBINATION);
+ uint32 pp = (type & T_66) ? 1 : (type & T_F3) ? 2 : (type & T_F2) ? 3 : 0;
+ uint32 vvvv = (((~idx) & 15) << 3) | (is256 ? 4 : 0) | pp;
+ if (!b && !x && !w && (type & T_0F)) {
+ db(0xC5); db((r ? 0 : 0x80) | vvvv);
+ } else {
+ uint32 mmmm = (type & T_0F) ? 1 : (type & T_0F38) ? 2 : (type & T_0F3A) ? 3 : 0;
+ db(0xC4); db((r ? 0 : 0x80) | (x ? 0 : 0x40) | (b ? 0 : 0x20) | mmmm); db((w << 7) | vvvv);
+ }
+ db(code);
+ }
+ void verifySAE(const Reg& r, int type) const
+ {
+ if (((type & T_SAE_X) && r.isXMM()) || ((type & T_SAE_Y) && r.isYMM()) || ((type & T_SAE_Z) && r.isZMM())) return;
+ throw Error(ERR_SAE_IS_INVALID);
+ }
+ void verifyER(const Reg& r, int type) const
+ {
+ if (((type & T_ER_X) && r.isXMM()) || ((type & T_ER_Y) && r.isYMM()) || ((type & T_ER_Z) && r.isZMM())) return;
+ throw Error(ERR_ER_IS_INVALID);
+ }
+ // (a, b, c) contains non zero two or three values then err
+ int verifyDuplicate(int a, int b, int c, int err)
+ {
+ int v = a | b | c;
+ if ((a > 0 && a != v) + (b > 0 && b != v) + (c > 0 && c != v) > 0) return Error(err);
+ return v;
+ }
+ int evex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false, bool b = false, int aaa = 0, uint32 VL = 0, bool Hi16Vidx = false)
+ {
+ if (!(type & (T_EVEX | T_MUST_EVEX))) throw Error(ERR_EVEX_IS_INVALID);
+ int w = (type & T_EW1) ? 1 : 0;
+ uint32 mm = (type & T_0F) ? 1 : (type & T_0F38) ? 2 : (type & T_0F3A) ? 3 : 0;
+ uint32 pp = (type & T_66) ? 1 : (type & T_F3) ? 2 : (type & T_F2) ? 3 : 0;
+
+ int idx = v ? v->getIdx() : 0;
+ uint32 vvvv = ~idx;
+
+ bool R = !reg.isExtIdx();
+ bool X = x ? false : !base.isExtIdx2();
+ bool B = !base.isExtIdx();
+ bool Rp = !reg.isExtIdx2();
+ int LL;
+ int rounding = verifyDuplicate(reg.getRounding(), base.getRounding(), v ? v->getRounding() : 0, ERR_ROUNDING_IS_ALREADY_SET);
+ int disp8N = 1;
+ if (rounding) {
+ if (rounding == EvexModifierRounding::T_SAE) {
+ verifySAE(base, type); LL = 0;
+ } else {
+ verifyER(base, type); LL = rounding - 1;
+ }
+ b = true;
+ } else {
+ if (v) VL = (std::max)(VL, v->getBit());
+ VL = (std::max)((std::max)(reg.getBit(), base.getBit()), VL);
+ LL = (VL == 512) ? 2 : (VL == 256) ? 1 : 0;
+ if (b) {
+ disp8N = (type & T_B32) ? 4 : 8;
+ } else if (type & T_DUP) {
+ disp8N = VL == 128 ? 8 : VL == 256 ? 32 : 64;
+ } else {
+ if ((type & (T_NX_MASK | T_N_VL)) == 0) {
+ type |= T_N16 | T_N_VL; // default
+ }
+ int low = type & T_NX_MASK;
+ if (low > 0) {
+ disp8N = 1 << (low - 1);
+ if (type & T_N_VL) disp8N *= (VL == 512 ? 4 : VL == 256 ? 2 : 1);
+ }
+ }
+ }
+ bool Vp = !((v ? v->isExtIdx2() : 0) | Hi16Vidx);
+ bool z = reg.hasZero() || base.hasZero() || (v ? v->hasZero() : false);
+ if (aaa == 0) aaa = verifyDuplicate(base.getOpmaskIdx(), reg.getOpmaskIdx(), (v ? v->getOpmaskIdx() : 0), ERR_OPMASK_IS_ALREADY_SET);
+ db(0x62);
+ db((R ? 0x80 : 0) | (X ? 0x40 : 0) | (B ? 0x20 : 0) | (Rp ? 0x10 : 0) | (mm & 3));
+ db((w == 1 ? 0x80 : 0) | ((vvvv & 15) << 3) | 4 | (pp & 3));
+ db((z ? 0x80 : 0) | ((LL & 3) << 5) | (b ? 0x10 : 0) | (Vp ? 8 : 0) | (aaa & 7));
+ db(code);
+ return disp8N;
+ }
+ void setModRM(int mod, int r1, int r2)
+ {
+ db(static_cast<uint8>((mod << 6) | ((r1 & 7) << 3) | (r2 & 7)));
+ }
+ void setSIB(const RegExp& e, int reg, int disp8N = 0)
+ {
+ size_t disp64 = e.getDisp();
+#ifdef XBYAK64
+ size_t high = disp64 >> 32;
+ if (high != 0 && high != 0xFFFFFFFF) throw Error(ERR_OFFSET_IS_TOO_BIG);
+#endif
+ uint32 disp = static_cast<uint32>(disp64);
+ const Reg& base = e.getBase();
+ const Reg& index = e.getIndex();
+ const int baseIdx = base.getIdx();
+ const int baseBit = base.getBit();
+ const int indexBit = index.getBit();
+ enum {
+ mod00 = 0, mod01 = 1, mod10 = 2
+ };
+ int mod = mod10; // disp32
+ if (!baseBit || ((baseIdx & 7) != Operand::EBP && disp == 0)) {
+ mod = mod00;
+ } else {
+ if (disp8N == 0) {
+ if (inner::IsInDisp8(disp)) {
+ mod = mod01;
+ }
+ } else {
+ // disp must be casted to signed
+ uint32 t = static_cast<uint32>(static_cast<int>(disp) / disp8N);
+ if ((disp % disp8N) == 0 && inner::IsInDisp8(t)) {
+ disp = t;
+ mod = mod01;
+ }
+ }
+ }
+ const int newBaseIdx = baseBit ? (baseIdx & 7) : Operand::EBP;
+ /* ModR/M = [2:3:3] = [Mod:reg/code:R/M] */
+ bool hasSIB = indexBit || (baseIdx & 7) == Operand::ESP;
+#ifdef XBYAK64
+ if (!baseBit && !indexBit) hasSIB = true;
+#endif
+ if (hasSIB) {
+ setModRM(mod, reg, Operand::ESP);
+ /* SIB = [2:3:3] = [SS:index:base(=rm)] */
+ const int idx = indexBit ? (index.getIdx() & 7) : Operand::ESP;
+ const int scale = e.getScale();
+ const int SS = (scale == 8) ? 3 : (scale == 4) ? 2 : (scale == 2) ? 1 : 0;
+ setModRM(SS, idx, newBaseIdx);
+ } else {
+ setModRM(mod, reg, newBaseIdx);
+ }
+ if (mod == mod01) {
+ db(disp);
+ } else if (mod == mod10 || (mod == mod00 && !baseBit)) {
+ dd(disp);
+ }
+ }
+ LabelManager labelMgr_;
+ bool isInDisp16(uint32 x) const { return 0xFFFF8000 <= x || x <= 0x7FFF; }
+ void opModR(const Reg& reg1, const Reg& reg2, int code0, int code1 = NONE, int code2 = NONE)
+ {
+ rex(reg2, reg1);
+ db(code0 | (reg1.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2);
+ setModRM(3, reg1.getIdx(), reg2.getIdx());
+ }
+ void opModM(const Address& addr, const Reg& reg, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0)
+ {
+ if (addr.is64bitDisp()) throw Error(ERR_CANT_USE_64BIT_DISP);
+ rex(addr, reg);
+ db(code0 | (reg.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2);
+ opAddr(addr, reg.getIdx(), immSize);
+ }
+ void opMIB(const Address& addr, const Reg& reg, int code0, int code1)
+ {
+ if (addr.is64bitDisp()) throw Error(ERR_CANT_USE_64BIT_DISP);
+ if (addr.getMode() != Address::M_ModRM) throw Error(ERR_INVALID_MIB_ADDRESS);
+ if (BIT == 64 && addr.is32bit()) db(0x67);
+ const RegExp& regExp = addr.getRegExp(false);
+ uint8 rex = regExp.getRex();
+ if (rex) db(rex);
+ db(code0); db(code1);
+ setSIB(regExp, reg.getIdx());
+ }
+ void makeJmp(uint32 disp, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
+ {
+ const int shortJmpSize = 2;
+ const int longHeaderSize = longPref ? 2 : 1;
+ const int longJmpSize = longHeaderSize + 4;
+ if (type != T_NEAR && inner::IsInDisp8(disp - shortJmpSize)) {
+ db(shortCode); db(disp - shortJmpSize);
+ } else {
+ if (type == T_SHORT) throw Error(ERR_LABEL_IS_TOO_FAR);
+ if (longPref) db(longPref);
+ db(longCode); dd(disp - longJmpSize);
+ }
+ }
+ template<class T>
+ void opJmp(T& label, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
+ {
+ if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory(); /* avoid splitting code of jmp */
+ size_t offset = 0;
+ if (labelMgr_.getOffset(&offset, label)) { /* label exists */
+ makeJmp(inner::VerifyInInt32(offset - size_), type, shortCode, longCode, longPref);
+ } else {
+ int jmpSize = 0;
+ if (type == T_NEAR) {
+ jmpSize = 4;
+ if (longPref) db(longPref);
+ db(longCode); dd(0);
+ } else {
+ jmpSize = 1;
+ db(shortCode); db(0);
+ }
+ JmpLabel jmp(size_, jmpSize, inner::LasIs);
+ labelMgr_.addUndefinedLabel(label, jmp);
+ }
+ }
+ void opJmpAbs(const void *addr, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref = 0)
+ {
+ if (isAutoGrow()) {
+ if (type != T_NEAR) throw Error(ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW);
+ if (size_ + 16 >= maxSize_) growMemory();
+ if (longPref) db(longPref);
+ db(longCode);
+ dd(0);
+ save(size_ - 4, size_t(addr) - size_, 4, inner::Labs);
+ } else {
+ makeJmp(inner::VerifyInInt32(reinterpret_cast<const uint8*>(addr) - getCurr()), type, shortCode, longCode, longPref);
+ }
+
+ }
+ // reg is reg field of ModRM
+ // immSize is the size for immediate value
+ // disp8N = 0(normal), disp8N = 1(force disp32), disp8N = {2, 4, 8} ; compressed displacement
+ void opAddr(const Address &addr, int reg, int immSize = 0, int disp8N = 0, bool permitVisb = false)
+ {
+ if (!permitVisb && addr.isVsib()) throw Error(ERR_BAD_VSIB_ADDRESSING);
+ if (addr.getMode() == Address::M_ModRM) {
+ setSIB(addr.getRegExp(), reg, disp8N);
+ } else if (addr.getMode() == Address::M_rip || addr.getMode() == Address::M_ripAddr) {
+ setModRM(0, reg, 5);
+ if (addr.getLabel()) { // [rip + Label]
+ putL_inner(*addr.getLabel(), true, addr.getDisp() - immSize);
+ } else {
+ size_t disp = addr.getDisp();
+ if (addr.getMode() == Address::M_ripAddr) {
+ if (isAutoGrow()) throw Error(ERR_INVALID_RIP_IN_AUTO_GROW);
+ disp -= (size_t)getCurr() + 4 + immSize;
+ }
+ dd(inner::VerifyInInt32(disp));
+ }
+ }
+ }
+ /* preCode is for SSSE3/SSE4 */
+ void opGen(const Operand& reg, const Operand& op, int code, int pref, bool isValid(const Operand&, const Operand&), int imm8 = NONE, int preCode = NONE)
+ {
+ if (isValid && !isValid(reg, op)) throw Error(ERR_BAD_COMBINATION);
+ if (pref != NONE) db(pref);
+ if (op.isMEM()) {
+ opModM(op.getAddress(), reg.getReg(), 0x0F, preCode, code, (imm8 != NONE) ? 1 : 0);
+ } else {
+ opModR(reg.getReg(), op.getReg(), 0x0F, preCode, code);
+ }
+ if (imm8 != NONE) db(imm8);
+ }
+ void opMMX_IMM(const Mmx& mmx, int imm8, int code, int ext)
+ {
+ if (mmx.isXMM()) db(0x66);
+ opModR(Reg32(ext), mmx, 0x0F, code);
+ db(imm8);
+ }
+ void opMMX(const Mmx& mmx, const Operand& op, int code, int pref = 0x66, int imm8 = NONE, int preCode = NONE)
+ {
+ opGen(mmx, op, code, mmx.isXMM() ? pref : NONE, isXMMorMMX_MEM, imm8, preCode);
+ }
+ void opMovXMM(const Operand& op1, const Operand& op2, int code, int pref)
+ {
+ if (pref != NONE) db(pref);
+ if (op1.isXMM() && op2.isMEM()) {
+ opModM(op2.getAddress(), op1.getReg(), 0x0F, code);
+ } else if (op1.isMEM() && op2.isXMM()) {
+ opModM(op1.getAddress(), op2.getReg(), 0x0F, code | 1);
+ } else {
+ throw Error(ERR_BAD_COMBINATION);
+ }
+ }
+ void opExt(const Operand& op, const Mmx& mmx, int code, int imm, bool hasMMX2 = false)
+ {
+ if (hasMMX2 && op.isREG(i32e)) { /* pextrw is special */
+ if (mmx.isXMM()) db(0x66);
+ opModR(op.getReg(), mmx, 0x0F, 0xC5); db(imm);
+ } else {
+ opGen(mmx, op, code, 0x66, isXMM_REG32orMEM, imm, 0x3A);
+ }
+ }
+ void opR_ModM(const Operand& op, int bit, int ext, int code0, int code1 = NONE, int code2 = NONE, bool disableRex = false, int immSize = 0)
+ {
+ int opBit = op.getBit();
+ if (disableRex && opBit == 64) opBit = 32;
+ if (op.isREG(bit)) {
+ opModR(Reg(ext, Operand::REG, opBit), op.getReg().changeBit(opBit), code0, code1, code2);
+ } else if (op.isMEM()) {
+ opModM(op.getAddress(), Reg(ext, Operand::REG, opBit), code0, code1, code2, immSize);
+ } else {
+ throw Error(ERR_BAD_COMBINATION);
+ }
+ }
+ void opShift(const Operand& op, int imm, int ext)
+ {
+ verifyMemHasSize(op);
+ opR_ModM(op, 0, ext, (0xC0 | ((imm == 1 ? 1 : 0) << 4)), NONE, NONE, false, (imm != 1) ? 1 : 0);
+ if (imm != 1) db(imm);
+ }
+ void opShift(const Operand& op, const Reg8& _cl, int ext)
+ {
+ if (_cl.getIdx() != Operand::CL) throw Error(ERR_BAD_COMBINATION);
+ opR_ModM(op, 0, ext, 0xD2);
+ }
+ void opModRM(const Operand& op1, const Operand& op2, bool condR, bool condM, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0)
+ {
+ if (condR) {
+ opModR(op1.getReg(), op2.getReg(), code0, code1, code2);
+ } else if (condM) {
+ opModM(op2.getAddress(), op1.getReg(), code0, code1, code2, immSize);
+ } else {
+ throw Error(ERR_BAD_COMBINATION);
+ }
+ }
+ void opShxd(const Operand& op, const Reg& reg, uint8 imm, int code, const Reg8 *_cl = 0)
+ {
+ if (_cl && _cl->getIdx() != Operand::CL) throw Error(ERR_BAD_COMBINATION);
+ opModRM(reg, op, (op.isREG(16 | i32e) && op.getBit() == reg.getBit()), op.isMEM() && (reg.isREG(16 | i32e)), 0x0F, code | (_cl ? 1 : 0), NONE, _cl ? 0 : 1);
+ if (!_cl) db(imm);
+ }
+ // (REG, REG|MEM), (MEM, REG)
+ void opRM_RM(const Operand& op1, const Operand& op2, int code)
+ {
+ if (op1.isREG() && op2.isMEM()) {
+ opModM(op2.getAddress(), op1.getReg(), code | 2);
+ } else {
+ opModRM(op2, op1, op1.isREG() && op1.getKind() == op2.getKind(), op1.isMEM() && op2.isREG(), code);
+ }
+ }
+ // (REG|MEM, IMM)
+ void opRM_I(const Operand& op, uint32 imm, int code, int ext)
+ {
+ verifyMemHasSize(op);
+ uint32 immBit = inner::IsInDisp8(imm) ? 8 : isInDisp16(imm) ? 16 : 32;
+ if (op.isBit(8)) immBit = 8;
+ if (op.getBit() < immBit) throw Error(ERR_IMM_IS_TOO_BIG);
+ if (op.isBit(32|64) && immBit == 16) immBit = 32; /* don't use MEM16 if 32/64bit mode */
+ if (op.isREG() && op.getIdx() == 0 && (op.getBit() == immBit || (op.isBit(64) && immBit == 32))) { // rax, eax, ax, al
+ rex(op);
+ db(code | 4 | (immBit == 8 ? 0 : 1));
+ } else {
+ int tmp = immBit < (std::min)(op.getBit(), 32U) ? 2 : 0;
+ opR_ModM(op, 0, ext, 0x80 | tmp, NONE, NONE, false, immBit / 8);
+ }
+ db(imm, immBit / 8);
+ }
+ void opIncDec(const Operand& op, int code, int ext)
+ {
+ verifyMemHasSize(op);
+#ifndef XBYAK64
+ if (op.isREG() && !op.isBit(8)) {
+ rex(op); db(code | op.getIdx());
+ return;
+ }
+#endif
+ code = 0xFE;
+ if (op.isREG()) {
+ opModR(Reg(ext, Operand::REG, op.getBit()), op.getReg(), code);
+ } else {
+ opModM(op.getAddress(), Reg(ext, Operand::REG, op.getBit()), code);
+ }
+ }
+ void opPushPop(const Operand& op, int code, int ext, int alt)
+ {
+ int bit = op.getBit();
+ if (bit == 16 || bit == BIT) {
+ if (bit == 16) db(0x66);
+ if (op.isREG()) {
+ if (op.getReg().getIdx() >= 8) db(0x41);
+ db(alt | (op.getIdx() & 7));
+ return;
+ }
+ if (op.isMEM()) {
+ opModM(op.getAddress(), Reg(ext, Operand::REG, 32), code);
+ return;
+ }
+ }
+ throw Error(ERR_BAD_COMBINATION);
+ }
+ void verifyMemHasSize(const Operand& op) const
+ {
+ if (op.isMEM() && op.getBit() == 0) throw Error(ERR_MEM_SIZE_IS_NOT_SPECIFIED);
+ }
+ /*
+ mov(r, imm) = db(imm, mov_imm(r, imm))
+ */
+ int mov_imm(const Reg& reg, size_t imm)
+ {
+ int bit = reg.getBit();
+ const int idx = reg.getIdx();
+ int code = 0xB0 | ((bit == 8 ? 0 : 1) << 3);
+ if (bit == 64 && (imm & ~size_t(0xffffffffu)) == 0) {
+ rex(Reg32(idx));
+ bit = 32;
+ } else {
+ rex(reg);
+ if (bit == 64 && inner::IsInInt32(imm)) {
+ db(0xC7);
+ code = 0xC0;
+ bit = 32;
+ }
+ }
+ db(code | (idx & 7));
+ return bit / 8;
+ }
+ template<class T>
+ void putL_inner(T& label, bool relative = false, size_t disp = 0)
+ {
+ const int jmpSize = relative ? 4 : (int)sizeof(size_t);
+ if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory();
+ size_t offset = 0;
+ if (labelMgr_.getOffset(&offset, label)) {
+ if (relative) {
+ db(inner::VerifyInInt32(offset + disp - size_ - jmpSize), jmpSize);
+ } else if (isAutoGrow()) {
+ db(uint64(0), jmpSize);
+ save(size_ - jmpSize, offset, jmpSize, inner::LaddTop);
+ } else {
+ db(size_t(top_) + offset, jmpSize);
+ }
+ return;
+ }
+ db(uint64(0), jmpSize);
+ JmpLabel jmp(size_, jmpSize, (relative ? inner::LasIs : isAutoGrow() ? inner::LaddTop : inner::Labs), disp);
+ labelMgr_.addUndefinedLabel(label, jmp);
+ }
+ void opMovxx(const Reg& reg, const Operand& op, uint8 code)
+ {
+ if (op.isBit(32)) throw Error(ERR_BAD_COMBINATION);
+ int w = op.isBit(16);
+#ifdef XBYAK64
+ if (op.isHigh8bit()) throw Error(ERR_BAD_COMBINATION);
+#endif
+ bool cond = reg.isREG() && (reg.getBit() > op.getBit());
+ opModRM(reg, op, cond && op.isREG(), cond && op.isMEM(), 0x0F, code | w);
+ }
+ void opFpuMem(const Address& addr, uint8 m16, uint8 m32, uint8 m64, uint8 ext, uint8 m64ext)
+ {
+ if (addr.is64bitDisp()) throw Error(ERR_CANT_USE_64BIT_DISP);
+ uint8 code = addr.isBit(16) ? m16 : addr.isBit(32) ? m32 : addr.isBit(64) ? m64 : 0;
+ if (!code) throw Error(ERR_BAD_MEM_SIZE);
+ if (m64ext && addr.isBit(64)) ext = m64ext;
+
+ rex(addr, st0);
+ db(code);
+ opAddr(addr, ext);
+ }
+ // use code1 if reg1 == st0
+ // use code2 if reg1 != st0 && reg2 == st0
+ void opFpuFpu(const Fpu& reg1, const Fpu& reg2, uint32 code1, uint32 code2)
+ {
+ uint32 code = reg1.getIdx() == 0 ? code1 : reg2.getIdx() == 0 ? code2 : 0;
+ if (!code) throw Error(ERR_BAD_ST_COMBINATION);
+ db(uint8(code >> 8));
+ db(uint8(code | (reg1.getIdx() | reg2.getIdx())));
+ }
+ void opFpu(const Fpu& reg, uint8 code1, uint8 code2)
+ {
+ db(code1); db(code2 | reg.getIdx());
+ }
+ void opVex(const Reg& r, const Operand *p1, const Operand& op2, int type, int code, int imm8 = NONE)
+ {
+ if (op2.isMEM()) {
+ const Address& addr = op2.getAddress();
+ const RegExp& regExp = addr.getRegExp();
+ const Reg& base = regExp.getBase();
+ const Reg& index = regExp.getIndex();
+ if (BIT == 64 && addr.is32bit()) db(0x67);
+ int disp8N = 0;
+ bool x = index.isExtIdx();
+ if ((type & (T_MUST_EVEX|T_MEM_EVEX)) || r.hasEvex() || (p1 && p1->hasEvex()) || addr.isBroadcast() || addr.getOpmaskIdx()) {
+ int aaa = addr.getOpmaskIdx();
+ if (aaa && !(type & T_M_K)) throw Error(ERR_INVALID_OPMASK_WITH_MEMORY);
+ bool b = false;
+ if (addr.isBroadcast()) {
+ if (!(type & (T_B32 | T_B64))) throw Error(ERR_INVALID_BROADCAST);
+ b = true;
+ }
+ int VL = regExp.isVsib() ? index.getBit() : 0;
+ disp8N = evex(r, base, p1, type, code, x, b, aaa, VL, index.isExtIdx2());
+ } else {
+ vex(r, base, p1, type, code, x);
+ }
+ opAddr(addr, r.getIdx(), (imm8 != NONE) ? 1 : 0, disp8N, (type & T_VSIB) != 0);
+ } else {
+ const Reg& base = op2.getReg();
+ if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || base.hasEvex()) {
+ evex(r, base, p1, type, code);
+ } else {
+ vex(r, base, p1, type, code);
+ }
+ setModRM(3, r.getIdx(), base.getIdx());
+ }
+ if (imm8 != NONE) db(imm8);
+ }
+ // (r, r, r/m) if isR_R_RM
+ // (r, r/m, r)
+ void opGpr(const Reg32e& r, const Operand& op1, const Operand& op2, int type, uint8 code, bool isR_R_RM, int imm8 = NONE)
+ {
+ const Operand *p1 = &op1;
+ const Operand *p2 = &op2;
+ if (!isR_R_RM) std::swap(p1, p2);
+ const unsigned int bit = r.getBit();
+ if (p1->getBit() != bit || (p2->isREG() && p2->getBit() != bit)) throw Error(ERR_BAD_COMBINATION);
+ type |= (bit == 64) ? T_W1 : T_W0;
+ opVex(r, p1, *p2, type, code, imm8);
+ }
+ void opAVX_X_X_XM(const Xmm& x1, const Operand& op1, const Operand& op2, int type, int code0, int imm8 = NONE)
+ {
+ const Xmm *x2 = static_cast<const Xmm*>(&op1);
+ const Operand *op = &op2;
+ if (op2.isNone()) { // (x1, op1) -> (x1, x1, op1)
+ x2 = &x1;
+ op = &op1;
+ }
+ // (x1, x2, op)
+ if (!((x1.isXMM() && x2->isXMM()) || ((type & T_YMM) && ((x1.isYMM() && x2->isYMM()) || (x1.isZMM() && x2->isZMM()))))) throw Error(ERR_BAD_COMBINATION);
+ opVex(x1, x2, *op, type, code0, imm8);
+ }
+ void opAVX_K_X_XM(const Opmask& k, const Xmm& x2, const Operand& op3, int type, int code0, int imm8 = NONE)
+ {
+ if (!op3.isMEM() && (x2.getKind() != op3.getKind())) throw Error(ERR_BAD_COMBINATION);
+ opVex(k, &x2, op3, type, code0, imm8);
+ }
+ // (x, x/m), (y, x/m256), (z, y/m)
+ void checkCvt1(const Operand& x, const Operand& op) const
+ {
+ if (!op.isMEM() && !(x.is(Operand::XMM | Operand::YMM) && op.isXMM()) && !(x.isZMM() && op.isYMM())) throw Error(ERR_BAD_COMBINATION);
+ }
+ // (x, x/m), (x, y/m256), (y, z/m)
+ void checkCvt2(const Xmm& x, const Operand& op) const
+ {
+ if (!(x.isXMM() && op.is(Operand::XMM | Operand::YMM | Operand::MEM)) && !(x.isYMM() && op.is(Operand::ZMM | Operand::MEM))) throw Error(ERR_BAD_COMBINATION);
+ }
+ void opCvt2(const Xmm& x, const Operand& op, int type, int code)
+ {
+ checkCvt2(x, op);
+ Operand::Kind kind = x.isXMM() ? (op.isBit(256) ? Operand::YMM : Operand::XMM) : Operand::ZMM;
+ opVex(x.copyAndSetKind(kind), &xm0, op, type, code);
+ }
+ void opCvt3(const Xmm& x1, const Xmm& x2, const Operand& op, int type, int type64, int type32, uint8 code)
+ {
+ if (!(x1.isXMM() && x2.isXMM() && (op.isREG(i32e) || op.isMEM()))) throw Error(ERR_BAD_SIZE_OF_REGISTER);
+ Xmm x(op.getIdx());
+ const Operand *p = op.isREG() ? &x : &op;
+ opVex(x1, &x2, *p, type | (op.isBit(64) ? type64 : type32), code);
+ }
+ const Xmm& cvtIdx0(const Operand& x) const
+ {
+ return x.isZMM() ? zm0 : x.isYMM() ? ym0 : xm0;
+ }
+ // support (x, x/m, imm), (y, y/m, imm)
+ void opAVX_X_XM_IMM(const Xmm& x, const Operand& op, int type, int code, int imm8 = NONE)
+ {
+ opAVX_X_X_XM(x, cvtIdx0(x), op, type, code, imm8);
+ }
+ // QQQ:need to refactor
+ void opSp1(const Reg& reg, const Operand& op, uint8 pref, uint8 code0, uint8 code1)
+ {
+ if (reg.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER);
+ bool is16bit = reg.isREG(16) && (op.isREG(16) || op.isMEM());
+ if (!is16bit && !(reg.isREG(i32e) && (op.isREG(reg.getBit()) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION);
+ if (is16bit) db(0x66);
+ db(pref); opModRM(reg.changeBit(i32e == 32 ? 32 : reg.getBit()), op, op.isREG(), true, code0, code1);
+ }
+ void opGather(const Xmm& x1, const Address& addr, const Xmm& x2, int type, uint8 code, int mode)
+ {
+ const RegExp& regExp = addr.getRegExp();
+ if (!regExp.isVsib(128 | 256)) throw Error(ERR_BAD_VSIB_ADDRESSING);
+ const int y_vx_y = 0;
+ const int y_vy_y = 1;
+// const int x_vy_x = 2;
+ const bool isAddrYMM = regExp.getIndex().getBit() == 256;
+ if (!x1.isXMM() || isAddrYMM || !x2.isXMM()) {
+ bool isOK = false;
+ if (mode == y_vx_y) {
+ isOK = x1.isYMM() && !isAddrYMM && x2.isYMM();
+ } else if (mode == y_vy_y) {
+ isOK = x1.isYMM() && isAddrYMM && x2.isYMM();
+ } else { // x_vy_x
+ isOK = !x1.isYMM() && isAddrYMM && !x2.isYMM();
+ }
+ if (!isOK) throw Error(ERR_BAD_VSIB_ADDRESSING);
+ }
+ opAVX_X_X_XM(isAddrYMM ? Ymm(x1.getIdx()) : x1, isAddrYMM ? Ymm(x2.getIdx()) : x2, addr, type, code);
+ }
+ enum {
+ xx_yy_zz = 0,
+ xx_yx_zy = 1,
+ xx_xy_yz = 2
+ };
+ void checkGather2(const Xmm& x1, const Reg& x2, int mode) const
+ {
+ if (x1.isXMM() && x2.isXMM()) return;
+ switch (mode) {
+ case xx_yy_zz: if ((x1.isYMM() && x2.isYMM()) || (x1.isZMM() && x2.isZMM())) return;
+ break;
+ case xx_yx_zy: if ((x1.isYMM() && x2.isXMM()) || (x1.isZMM() && x2.isYMM())) return;
+ break;
+ case xx_xy_yz: if ((x1.isXMM() && x2.isYMM()) || (x1.isYMM() && x2.isZMM())) return;
+ break;
+ }
+ throw Error(ERR_BAD_VSIB_ADDRESSING);
+ }
+ void opGather2(const Xmm& x, const Address& addr, int type, uint8 code, int mode)
+ {
+ if (x.hasZero()) throw Error(ERR_INVALID_ZERO);
+ checkGather2(x, addr.getRegExp().getIndex(), mode);
+ opVex(x, 0, addr, type, code);
+ }
+ /*
+ xx_xy_yz ; mode = true
+ xx_xy_xz ; mode = false
+ */
+ void opVmov(const Operand& op, const Xmm& x, int type, uint8 code, bool mode)
+ {
+ if (mode) {
+ if (!op.isMEM() && !((op.isXMM() && x.isXMM()) || (op.isXMM() && x.isYMM()) || (op.isYMM() && x.isZMM()))) throw Error(ERR_BAD_COMBINATION);
+ } else {
+ if (!op.isMEM() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION);
+ }
+ opVex(x, 0, op, type, code);
+ }
+ void opGatherFetch(const Address& addr, const Xmm& x, int type, uint8 code, Operand::Kind kind)
+ {
+ if (addr.hasZero()) throw Error(ERR_INVALID_ZERO);
+ if (addr.getRegExp().getIndex().getKind() != kind) throw Error(ERR_BAD_VSIB_ADDRESSING);
+ opVex(x, 0, addr, type, code);
+ }
+public:
+ unsigned int getVersion() const { return VERSION; }
+ using CodeArray::db;
+ const Mmx mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
+ const Xmm xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
+ const Ymm ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7;
+ const Zmm zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7;
+ const Xmm &xm0, &xm1, &xm2, &xm3, &xm4, &xm5, &xm6, &xm7;
+ const Ymm &ym0, &ym1, &ym2, &ym3, &ym4, &ym5, &ym6, &ym7;
+ const Ymm &zm0, &zm1, &zm2, &zm3, &zm4, &zm5, &zm6, &zm7;
+ const Reg32 eax, ecx, edx, ebx, esp, ebp, esi, edi;
+ const Reg16 ax, cx, dx, bx, sp, bp, si, di;
+ const Reg8 al, cl, dl, bl, ah, ch, dh, bh;
+ const AddressFrame ptr, byte, word, dword, qword, xword, yword, zword; // xword is same as oword of NASM
+ const AddressFrame ptr_b, xword_b, yword_b, zword_b; // broadcast such as {1to2}, {1to4}, {1to8}, {1to16}, {b}
+ const Fpu st0, st1, st2, st3, st4, st5, st6, st7;
+ const Opmask k0, k1, k2, k3, k4, k5, k6, k7;
+ const BoundsReg bnd0, bnd1, bnd2, bnd3;
+ const EvexModifierRounding T_sae, T_rn_sae, T_rd_sae, T_ru_sae, T_rz_sae; // {sae}, {rn-sae}, {rd-sae}, {ru-sae}, {rz-sae}
+ const EvexModifierZero T_z; // {z}
+#ifdef XBYAK64
+ const Reg64 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
+ const Reg32 r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d;
+ const Reg16 r8w, r9w, r10w, r11w, r12w, r13w, r14w, r15w;
+ const Reg8 r8b, r9b, r10b, r11b, r12b, r13b, r14b, r15b;
+ const Reg8 spl, bpl, sil, dil;
+ const Xmm xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
+ const Xmm xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23;
+ const Xmm xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31;
+ const Ymm ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15;
+ const Ymm ymm16, ymm17, ymm18, ymm19, ymm20, ymm21, ymm22, ymm23;
+ const Ymm ymm24, ymm25, ymm26, ymm27, ymm28, ymm29, ymm30, ymm31;
+ const Zmm zmm8, zmm9, zmm10, zmm11, zmm12, zmm13, zmm14, zmm15;
+ const Zmm zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23;
+ const Zmm zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31;
+ const Xmm &xm8, &xm9, &xm10, &xm11, &xm12, &xm13, &xm14, &xm15; // for my convenience
+ const Xmm &xm16, &xm17, &xm18, &xm19, &xm20, &xm21, &xm22, &xm23;
+ const Xmm &xm24, &xm25, &xm26, &xm27, &xm28, &xm29, &xm30, &xm31;
+ const Ymm &ym8, &ym9, &ym10, &ym11, &ym12, &ym13, &ym14, &ym15;
+ const Ymm &ym16, &ym17, &ym18, &ym19, &ym20, &ym21, &ym22, &ym23;
+ const Ymm &ym24, &ym25, &ym26, &ym27, &ym28, &ym29, &ym30, &ym31;
+ const Zmm &zm8, &zm9, &zm10, &zm11, &zm12, &zm13, &zm14, &zm15;
+ const Zmm &zm16, &zm17, &zm18, &zm19, &zm20, &zm21, &zm22, &zm23;
+ const Zmm &zm24, &zm25, &zm26, &zm27, &zm28, &zm29, &zm30, &zm31;
+ const RegRip rip;
+#endif
+#ifndef XBYAK_DISABLE_SEGMENT
+ const Segment es, cs, ss, ds, fs, gs;
+#endif
+ void L(const std::string& label) { labelMgr_.defineSlabel(label); }
+ void L(Label& label) { labelMgr_.defineClabel(label); }
+ Label L() { Label label; L(label); return label; }
+ void inLocalLabel() { labelMgr_.enterLocal(); }
+ void outLocalLabel() { labelMgr_.leaveLocal(); }
+ /*
+ assign src to dst
+ require
+ dst : does not used by L()
+ src : used by L()
+ */
+ void assignL(Label& dst, const Label& src) { labelMgr_.assign(dst, src); }
+ /*
+ put address of label to buffer
+ @note the put size is 4(32-bit), 8(64-bit)
+ */
+ void putL(std::string label) { putL_inner(label); }
+ void putL(const Label& label) { putL_inner(label); }
+
+ void jmp(const Operand& op) { opR_ModM(op, BIT, 4, 0xFF, NONE, NONE, true); }
+ void jmp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); }
+ void jmp(const char *label, LabelType type = T_AUTO) { jmp(std::string(label), type); }
+ void jmp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); }
+ void jmp(const void *addr, LabelType type = T_AUTO) { opJmpAbs(addr, type, 0xEB, 0xE9); }
+
+ void call(const Operand& op) { opR_ModM(op, 16 | i32e, 2, 0xFF, NONE, NONE, true); }
+ // call(string label), not const std::string&
+ void call(std::string label) { opJmp(label, T_NEAR, 0, 0xE8, 0); }
+ void call(const char *label) { call(std::string(label)); }
+ void call(const Label& label) { opJmp(label, T_NEAR, 0, 0xE8, 0); }
+ // call(function pointer)
+#ifdef XBYAK_VARIADIC_TEMPLATE
+ template<class Ret, class... Params>
+ void call(Ret(*func)(Params...)) { call(reinterpret_cast<const void*>(func)); }
+#endif
+ void call(const void *addr) { opJmpAbs(addr, T_NEAR, 0, 0xE8); }
+
+ void test(const Operand& op, const Reg& reg)
+ {
+ opModRM(reg, op, op.isREG() && (op.getKind() == reg.getKind()), op.isMEM(), 0x84);
+ }
+ void test(const Operand& op, uint32 imm)
+ {
+ verifyMemHasSize(op);
+ int immSize = (std::min)(op.getBit() / 8, 4U);
+ if (op.isREG() && op.getIdx() == 0) { // al, ax, eax
+ rex(op);
+ db(0xA8 | (op.isBit(8) ? 0 : 1));
+ } else {
+ opR_ModM(op, 0, 0, 0xF6, NONE, NONE, false, immSize);
+ }
+ db(imm, immSize);
+ }
+ void imul(const Reg& reg, const Operand& op)
+ {
+ opModRM(reg, op, op.isREG() && (reg.getKind() == op.getKind()), op.isMEM(), 0x0F, 0xAF);
+ }
+ void imul(const Reg& reg, const Operand& op, int imm)
+ {
+ int s = inner::IsInDisp8(imm) ? 1 : 0;
+ int immSize = s ? 1 : reg.isREG(16) ? 2 : 4;
+ opModRM(reg, op, op.isREG() && (reg.getKind() == op.getKind()), op.isMEM(), 0x69 | (s << 1), NONE, NONE, immSize);
+ db(imm, immSize);
+ }
+ void push(const Operand& op) { opPushPop(op, 0xFF, 6, 0x50); }
+ void pop(const Operand& op) { opPushPop(op, 0x8F, 0, 0x58); }
+ void push(const AddressFrame& af, uint32 imm)
+ {
+ if (af.bit_ == 8 && inner::IsInDisp8(imm)) {
+ db(0x6A); db(imm);
+ } else if (af.bit_ == 16 && isInDisp16(imm)) {
+ db(0x66); db(0x68); dw(imm);
+ } else {
+ db(0x68); dd(imm);
+ }
+ }
+ /* use "push(word, 4)" if you want "push word 4" */
+ void push(uint32 imm)
+ {
+ if (inner::IsInDisp8(imm)) {
+ push(byte, imm);
+ } else {
+ push(dword, imm);
+ }
+ }
+ void mov(const Operand& reg1, const Operand& reg2)
+ {
+ const Reg *reg = 0;
+ const Address *addr = 0;
+ uint8 code = 0;
+ if (reg1.isREG() && reg1.getIdx() == 0 && reg2.isMEM()) { // mov eax|ax|al, [disp]
+ reg = &reg1.getReg();
+ addr= &reg2.getAddress();
+ code = 0xA0;
+ } else
+ if (reg1.isMEM() && reg2.isREG() && reg2.getIdx() == 0) { // mov [disp], eax|ax|al
+ reg = &reg2.getReg();
+ addr= &reg1.getAddress();
+ code = 0xA2;
+ }
+#ifdef XBYAK64
+ if (addr && addr->is64bitDisp()) {
+ if (code) {
+ rex(*reg);
+ db(reg1.isREG(8) ? 0xA0 : reg1.isREG() ? 0xA1 : reg2.isREG(8) ? 0xA2 : 0xA3);
+ db(addr->getDisp(), 8);
+ } else {
+ throw Error(ERR_BAD_COMBINATION);
+ }
+ } else
+#else
+ if (code && addr->isOnlyDisp()) {
+ rex(*reg, *addr);
+ db(code | (reg->isBit(8) ? 0 : 1));
+ dd(static_cast<uint32>(addr->getDisp()));
+ } else
+#endif
+ {
+ opRM_RM(reg1, reg2, 0x88);
+ }
+ }
+ void mov(const Operand& op, size_t imm)
+ {
+ if (op.isREG()) {
+ const int size = mov_imm(op.getReg(), imm);
+ db(imm, size);
+ } else if (op.isMEM()) {
+ verifyMemHasSize(op);
+ int immSize = op.getBit() / 8;
+ if (immSize <= 4) {
+ sint64 s = sint64(imm) >> (immSize * 8);
+ if (s != 0 && s != -1) throw Error(ERR_IMM_IS_TOO_BIG);
+ } else {
+ if (!inner::IsInInt32(imm)) throw Error(ERR_IMM_IS_TOO_BIG);
+ immSize = 4;
+ }
+ opModM(op.getAddress(), Reg(0, Operand::REG, op.getBit()), 0xC6, NONE, NONE, immSize);
+ db(static_cast<uint32>(imm), immSize);
+ } else {
+ throw Error(ERR_BAD_COMBINATION);
+ }
+ }
+ void mov(const NativeReg& reg, const char *label) // can't use std::string
+ {
+ if (label == 0) {
+ mov(static_cast<const Operand&>(reg), 0); // call imm
+ return;
+ }
+ mov_imm(reg, dummyAddr);
+ putL(label);
+ }
+ void mov(const NativeReg& reg, const Label& label)
+ {
+ mov_imm(reg, dummyAddr);
+ putL(label);
+ }
+ void xchg(const Operand& op1, const Operand& op2)
+ {
+ const Operand *p1 = &op1, *p2 = &op2;
+ if (p1->isMEM() || (p2->isREG(16 | i32e) && p2->getIdx() == 0)) {
+ p1 = &op2; p2 = &op1;
+ }
+ if (p1->isMEM()) throw Error(ERR_BAD_COMBINATION);
+ if (p2->isREG() && (p1->isREG(16 | i32e) && p1->getIdx() == 0)
+#ifdef XBYAK64
+ && (p2->getIdx() != 0 || !p1->isREG(32))
+#endif
+ ) {
+ rex(*p2, *p1); db(0x90 | (p2->getIdx() & 7));
+ return;
+ }
+ opModRM(*p1, *p2, (p1->isREG() && p2->isREG() && (p1->getBit() == p2->getBit())), p2->isMEM(), 0x86 | (p1->isBit(8) ? 0 : 1));
+ }
+
+#ifndef XBYAK_DISABLE_SEGMENT
+ void push(const Segment& seg)
+ {
+ switch (seg.getIdx()) {
+ case Segment::es: db(0x06); break;
+ case Segment::cs: db(0x0E); break;
+ case Segment::ss: db(0x16); break;
+ case Segment::ds: db(0x1E); break;
+ case Segment::fs: db(0x0F); db(0xA0); break;
+ case Segment::gs: db(0x0F); db(0xA8); break;
+ default:
+ assert(0);
+ }
+ }
+ void pop(const Segment& seg)
+ {
+ switch (seg.getIdx()) {
+ case Segment::es: db(0x07); break;
+ case Segment::cs: throw Error(ERR_BAD_COMBINATION);
+ case Segment::ss: db(0x17); break;
+ case Segment::ds: db(0x1F); break;
+ case Segment::fs: db(0x0F); db(0xA1); break;
+ case Segment::gs: db(0x0F); db(0xA9); break;
+ default:
+ assert(0);
+ }
+ }
+ void putSeg(const Segment& seg)
+ {
+ switch (seg.getIdx()) {
+ case Segment::es: db(0x2E); break;
+ case Segment::cs: db(0x36); break;
+ case Segment::ss: db(0x3E); break;
+ case Segment::ds: db(0x26); break;
+ case Segment::fs: db(0x64); break;
+ case Segment::gs: db(0x65); break;
+ default:
+ assert(0);
+ }
+ }
+ void mov(const Operand& op, const Segment& seg)
+ {
+ opModRM(Reg8(seg.getIdx()), op, op.isREG(16|i32e), op.isMEM(), 0x8C);
+ }
+ void mov(const Segment& seg, const Operand& op)
+ {
+ opModRM(Reg8(seg.getIdx()), op.isREG(16|i32e) ? static_cast<const Operand&>(op.getReg().cvt32()) : op, op.isREG(16|i32e), op.isMEM(), 0x8E);
+ }
+#endif
+
+ enum { NONE = 256 };
+ // constructor
+ CodeGenerator(size_t maxSize = DEFAULT_MAX_CODE_SIZE, void *userPtr = 0, Allocator *allocator = 0)
+ : CodeArray(maxSize, userPtr, allocator)
+ , mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7)
+ , xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7)
+ , ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7)
+ , zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6), zmm7(7)
+ // for my convenience
+ , xm0(xmm0), xm1(xmm1), xm2(xmm2), xm3(xmm3), xm4(xmm4), xm5(xmm5), xm6(xmm6), xm7(xmm7)
+ , ym0(ymm0), ym1(ymm1), ym2(ymm2), ym3(ymm3), ym4(ymm4), ym5(ymm5), ym6(ymm6), ym7(ymm7)
+ , zm0(zmm0), zm1(zmm1), zm2(zmm2), zm3(zmm3), zm4(zmm4), zm5(zmm5), zm6(zmm6), zm7(zmm7)
+
+ , eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI)
+ , ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI)
+ , al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH)
+ , ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512)
+ , ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true)
+ , st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7)
+ , k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7)
+ , bnd0(0), bnd1(1), bnd2(2), bnd3(3)
+ , T_sae(EvexModifierRounding::T_SAE), T_rn_sae(EvexModifierRounding::T_RN_SAE), T_rd_sae(EvexModifierRounding::T_RD_SAE), T_ru_sae(EvexModifierRounding::T_RU_SAE), T_rz_sae(EvexModifierRounding::T_RZ_SAE)
+ , T_z()
+#ifdef XBYAK64
+ , rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15)
+ , r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15)
+ , r8w(8), r9w(9), r10w(10), r11w(11), r12w(12), r13w(13), r14w(14), r15w(15)
+ , r8b(8), r9b(9), r10b(10), r11b(11), r12b(12), r13b(13), r14b(14), r15b(15)
+ , spl(Operand::SPL, true), bpl(Operand::BPL, true), sil(Operand::SIL, true), dil(Operand::DIL, true)
+ , xmm8(8), xmm9(9), xmm10(10), xmm11(11), xmm12(12), xmm13(13), xmm14(14), xmm15(15)
+ , xmm16(16), xmm17(17), xmm18(18), xmm19(19), xmm20(20), xmm21(21), xmm22(22), xmm23(23)
+ , xmm24(24), xmm25(25), xmm26(26), xmm27(27), xmm28(28), xmm29(29), xmm30(30), xmm31(31)
+ , ymm8(8), ymm9(9), ymm10(10), ymm11(11), ymm12(12), ymm13(13), ymm14(14), ymm15(15)
+ , ymm16(16), ymm17(17), ymm18(18), ymm19(19), ymm20(20), ymm21(21), ymm22(22), ymm23(23)
+ , ymm24(24), ymm25(25), ymm26(26), ymm27(27), ymm28(28), ymm29(29), ymm30(30), ymm31(31)
+ , zmm8(8), zmm9(9), zmm10(10), zmm11(11), zmm12(12), zmm13(13), zmm14(14), zmm15(15)
+ , zmm16(16), zmm17(17), zmm18(18), zmm19(19), zmm20(20), zmm21(21), zmm22(22), zmm23(23)
+ , zmm24(24), zmm25(25), zmm26(26), zmm27(27), zmm28(28), zmm29(29), zmm30(30), zmm31(31)
+ // for my convenience
+ , xm8(xmm8), xm9(xmm9), xm10(xmm10), xm11(xmm11), xm12(xmm12), xm13(xmm13), xm14(xmm14), xm15(xmm15)
+ , xm16(xmm16), xm17(xmm17), xm18(xmm18), xm19(xmm19), xm20(xmm20), xm21(xmm21), xm22(xmm22), xm23(xmm23)
+ , xm24(xmm24), xm25(xmm25), xm26(xmm26), xm27(xmm27), xm28(xmm28), xm29(xmm29), xm30(xmm30), xm31(xmm31)
+ , ym8(ymm8), ym9(ymm9), ym10(ymm10), ym11(ymm11), ym12(ymm12), ym13(ymm13), ym14(ymm14), ym15(ymm15)
+ , ym16(ymm16), ym17(ymm17), ym18(ymm18), ym19(ymm19), ym20(ymm20), ym21(ymm21), ym22(ymm22), ym23(ymm23)
+ , ym24(ymm24), ym25(ymm25), ym26(ymm26), ym27(ymm27), ym28(ymm28), ym29(ymm29), ym30(ymm30), ym31(ymm31)
+ , zm8(zmm8), zm9(zmm9), zm10(zmm10), zm11(zmm11), zm12(zmm12), zm13(zmm13), zm14(zmm14), zm15(zmm15)
+ , zm16(zmm16), zm17(zmm17), zm18(zmm18), zm19(zmm19), zm20(zmm20), zm21(zmm21), zm22(zmm22), zm23(zmm23)
+ , zm24(zmm24), zm25(zmm25), zm26(zmm26), zm27(zmm27), zm28(zmm28), zm29(zmm29), zm30(zmm30), zm31(zmm31)
+ , rip()
+#endif
+#ifndef XBYAK_DISABLE_SEGMENT
+ , es(Segment::es), cs(Segment::cs), ss(Segment::ss), ds(Segment::ds), fs(Segment::fs), gs(Segment::gs)
+#endif
+ {
+ labelMgr_.set(this);
+ }
+ void reset()
+ {
+ resetSize();
+ labelMgr_.reset();
+ labelMgr_.set(this);
+ }
+ bool hasUndefinedLabel() const { return labelMgr_.hasUndefSlabel() || labelMgr_.hasUndefClabel(); }
+ /*
+ MUST call ready() to complete generating code if you use AutoGrow mode.
+ It is not necessary for the other mode if hasUndefinedLabel() is true.
+ */
+ void ready(ProtectMode mode = PROTECT_RWE)
+ {
+ if (hasUndefinedLabel()) throw Error(ERR_LABEL_IS_NOT_FOUND);
+ if (isAutoGrow()) {
+ calcJmpAddress();
+ if (useProtect()) setProtectMode(mode);
+ }
+ }
+ // set read/exec
+ void readyRE() { return ready(PROTECT_RE); }
+#ifdef XBYAK_TEST
+ void dump(bool doClear = true)
+ {
+ CodeArray::dump();
+ if (doClear) size_ = 0;
+ }
+#endif
+
+#ifdef XBYAK_UNDEF_JNL
+ #undef jnl
+#endif
+
+ /*
+ use single byte nop if useMultiByteNop = false
+ */
+ void nop(size_t size = 1, bool useMultiByteNop = true)
+ {
+ if (!useMultiByteNop) {
+ for (size_t i = 0; i < size; i++) {
+ db(0x90);
+ }
+ return;
+ }
+ /*
+ Intel Architectures Software Developer's Manual Volume 2
+ recommended multi-byte sequence of NOP instruction
+ AMD and Intel seem to agree on the same sequences for up to 9 bytes:
+ https://support.amd.com/TechDocs/55723_SOG_Fam_17h_Processors_3.00.pdf
+ */
+ static const uint8 nopTbl[9][9] = {
+ {0x90},
+ {0x66, 0x90},
+ {0x0F, 0x1F, 0x00},
+ {0x0F, 0x1F, 0x40, 0x00},
+ {0x0F, 0x1F, 0x44, 0x00, 0x00},
+ {0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
+ {0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
+ {0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+ };
+ const size_t n = sizeof(nopTbl) / sizeof(nopTbl[0]);
+ while (size > 0) {
+ size_t len = (std::min)(n, size);
+ const uint8 *seq = nopTbl[len - 1];
+ db(seq, len);
+ size -= len;
+ }
+ }
+
+#ifndef XBYAK_DONT_READ_LIST
+#include "xbyak_mnemonic.h"
+ /*
+ use single byte nop if useMultiByteNop = false
+ */
+ void align(size_t x = 16, bool useMultiByteNop = true)
+ {
+ if (x == 1) return;
+ if (x < 1 || (x & (x - 1))) throw Error(ERR_BAD_ALIGN);
+ if (isAutoGrow() && x > inner::ALIGN_PAGE_SIZE) fprintf(stderr, "warning:autoGrow mode does not support %d align\n", (int)x);
+ size_t remain = size_t(getCurr()) % x;
+ if (remain) {
+ nop(x - remain, useMultiByteNop);
+ }
+ }
+#endif
+};
+
+namespace util {
+static const Mmx mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7);
+static const Xmm xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7);
+static const Ymm ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7);
+static const Zmm zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6), zmm7(7);
+static const Reg32 eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI);
+static const Reg16 ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI);
+static const Reg8 al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH);
+static const AddressFrame ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512);
+static const AddressFrame ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true);
+static const Fpu st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7);
+static const Opmask k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7);
+static const BoundsReg bnd0(0), bnd1(1), bnd2(2), bnd3(3);
+static const EvexModifierRounding T_sae(EvexModifierRounding::T_SAE), T_rn_sae(EvexModifierRounding::T_RN_SAE), T_rd_sae(EvexModifierRounding::T_RD_SAE), T_ru_sae(EvexModifierRounding::T_RU_SAE), T_rz_sae(EvexModifierRounding::T_RZ_SAE);
+static const EvexModifierZero T_z;
+#ifdef XBYAK64
+static const Reg64 rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15);
+static const Reg32 r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15);
+static const Reg16 r8w(8), r9w(9), r10w(10), r11w(11), r12w(12), r13w(13), r14w(14), r15w(15);
+static const Reg8 r8b(8), r9b(9), r10b(10), r11b(11), r12b(12), r13b(13), r14b(14), r15b(15), spl(Operand::SPL, true), bpl(Operand::BPL, true), sil(Operand::SIL, true), dil(Operand::DIL, true);
+static const Xmm xmm8(8), xmm9(9), xmm10(10), xmm11(11), xmm12(12), xmm13(13), xmm14(14), xmm15(15);
+static const Xmm xmm16(16), xmm17(17), xmm18(18), xmm19(19), xmm20(20), xmm21(21), xmm22(22), xmm23(23);
+static const Xmm xmm24(24), xmm25(25), xmm26(26), xmm27(27), xmm28(28), xmm29(29), xmm30(30), xmm31(31);
+static const Ymm ymm8(8), ymm9(9), ymm10(10), ymm11(11), ymm12(12), ymm13(13), ymm14(14), ymm15(15);
+static const Ymm ymm16(16), ymm17(17), ymm18(18), ymm19(19), ymm20(20), ymm21(21), ymm22(22), ymm23(23);
+static const Ymm ymm24(24), ymm25(25), ymm26(26), ymm27(27), ymm28(28), ymm29(29), ymm30(30), ymm31(31);
+static const Zmm zmm8(8), zmm9(9), zmm10(10), zmm11(11), zmm12(12), zmm13(13), zmm14(14), zmm15(15);
+static const Zmm zmm16(16), zmm17(17), zmm18(18), zmm19(19), zmm20(20), zmm21(21), zmm22(22), zmm23(23);
+static const Zmm zmm24(24), zmm25(25), zmm26(26), zmm27(27), zmm28(28), zmm29(29), zmm30(30), zmm31(31);
+static const RegRip rip;
+#endif
+#ifndef XBYAK_DISABLE_SEGMENT
+static const Segment es(Segment::es), cs(Segment::cs), ss(Segment::ss), ds(Segment::ds), fs(Segment::fs), gs(Segment::gs);
+#endif
+} // util
+
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
+
+} // end of namespace
+
+#endif // XBYAK_XBYAK_H_
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_bin2hex.h b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_bin2hex.h
new file mode 100644
index 0000000000..a22e5224c3
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_bin2hex.h
@@ -0,0 +1,303 @@
+/*******************************************************************************
+* Copyright 2016-2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*******************************************************************************
+* Copyright (c) 2007 MITSUNARI Shigeo
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* Neither the name of the copyright owner nor the names of its contributors may
+* be used to endorse or promote products derived from this software without
+* specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+enum {
+ B00000000= 0,
+ B00000001= 1,
+ B00000010= 2,
+ B00000011= 3,
+ B00000100= 4,
+ B00000101= 5,
+ B00000110= 6,
+ B00000111= 7,
+ B00001000= 8,
+ B00001001= 9,
+ B00001010= 10,
+ B00001011= 11,
+ B00001100= 12,
+ B00001101= 13,
+ B00001110= 14,
+ B00001111= 15,
+ B00010000= 16,
+ B00010001= 17,
+ B00010010= 18,
+ B00010011= 19,
+ B00010100= 20,
+ B00010101= 21,
+ B00010110= 22,
+ B00010111= 23,
+ B00011000= 24,
+ B00011001= 25,
+ B00011010= 26,
+ B00011011= 27,
+ B00011100= 28,
+ B00011101= 29,
+ B00011110= 30,
+ B00011111= 31,
+ B00100000= 32,
+ B00100001= 33,
+ B00100010= 34,
+ B00100011= 35,
+ B00100100= 36,
+ B00100101= 37,
+ B00100110= 38,
+ B00100111= 39,
+ B00101000= 40,
+ B00101001= 41,
+ B00101010= 42,
+ B00101011= 43,
+ B00101100= 44,
+ B00101101= 45,
+ B00101110= 46,
+ B00101111= 47,
+ B00110000= 48,
+ B00110001= 49,
+ B00110010= 50,
+ B00110011= 51,
+ B00110100= 52,
+ B00110101= 53,
+ B00110110= 54,
+ B00110111= 55,
+ B00111000= 56,
+ B00111001= 57,
+ B00111010= 58,
+ B00111011= 59,
+ B00111100= 60,
+ B00111101= 61,
+ B00111110= 62,
+ B00111111= 63,
+ B01000000= 64,
+ B01000001= 65,
+ B01000010= 66,
+ B01000011= 67,
+ B01000100= 68,
+ B01000101= 69,
+ B01000110= 70,
+ B01000111= 71,
+ B01001000= 72,
+ B01001001= 73,
+ B01001010= 74,
+ B01001011= 75,
+ B01001100= 76,
+ B01001101= 77,
+ B01001110= 78,
+ B01001111= 79,
+ B01010000= 80,
+ B01010001= 81,
+ B01010010= 82,
+ B01010011= 83,
+ B01010100= 84,
+ B01010101= 85,
+ B01010110= 86,
+ B01010111= 87,
+ B01011000= 88,
+ B01011001= 89,
+ B01011010= 90,
+ B01011011= 91,
+ B01011100= 92,
+ B01011101= 93,
+ B01011110= 94,
+ B01011111= 95,
+ B01100000= 96,
+ B01100001= 97,
+ B01100010= 98,
+ B01100011= 99,
+ B01100100= 100,
+ B01100101= 101,
+ B01100110= 102,
+ B01100111= 103,
+ B01101000= 104,
+ B01101001= 105,
+ B01101010= 106,
+ B01101011= 107,
+ B01101100= 108,
+ B01101101= 109,
+ B01101110= 110,
+ B01101111= 111,
+ B01110000= 112,
+ B01110001= 113,
+ B01110010= 114,
+ B01110011= 115,
+ B01110100= 116,
+ B01110101= 117,
+ B01110110= 118,
+ B01110111= 119,
+ B01111000= 120,
+ B01111001= 121,
+ B01111010= 122,
+ B01111011= 123,
+ B01111100= 124,
+ B01111101= 125,
+ B01111110= 126,
+ B01111111= 127,
+ B10000000= 128,
+ B10000001= 129,
+ B10000010= 130,
+ B10000011= 131,
+ B10000100= 132,
+ B10000101= 133,
+ B10000110= 134,
+ B10000111= 135,
+ B10001000= 136,
+ B10001001= 137,
+ B10001010= 138,
+ B10001011= 139,
+ B10001100= 140,
+ B10001101= 141,
+ B10001110= 142,
+ B10001111= 143,
+ B10010000= 144,
+ B10010001= 145,
+ B10010010= 146,
+ B10010011= 147,
+ B10010100= 148,
+ B10010101= 149,
+ B10010110= 150,
+ B10010111= 151,
+ B10011000= 152,
+ B10011001= 153,
+ B10011010= 154,
+ B10011011= 155,
+ B10011100= 156,
+ B10011101= 157,
+ B10011110= 158,
+ B10011111= 159,
+ B10100000= 160,
+ B10100001= 161,
+ B10100010= 162,
+ B10100011= 163,
+ B10100100= 164,
+ B10100101= 165,
+ B10100110= 166,
+ B10100111= 167,
+ B10101000= 168,
+ B10101001= 169,
+ B10101010= 170,
+ B10101011= 171,
+ B10101100= 172,
+ B10101101= 173,
+ B10101110= 174,
+ B10101111= 175,
+ B10110000= 176,
+ B10110001= 177,
+ B10110010= 178,
+ B10110011= 179,
+ B10110100= 180,
+ B10110101= 181,
+ B10110110= 182,
+ B10110111= 183,
+ B10111000= 184,
+ B10111001= 185,
+ B10111010= 186,
+ B10111011= 187,
+ B10111100= 188,
+ B10111101= 189,
+ B10111110= 190,
+ B10111111= 191,
+ B11000000= 192,
+ B11000001= 193,
+ B11000010= 194,
+ B11000011= 195,
+ B11000100= 196,
+ B11000101= 197,
+ B11000110= 198,
+ B11000111= 199,
+ B11001000= 200,
+ B11001001= 201,
+ B11001010= 202,
+ B11001011= 203,
+ B11001100= 204,
+ B11001101= 205,
+ B11001110= 206,
+ B11001111= 207,
+ B11010000= 208,
+ B11010001= 209,
+ B11010010= 210,
+ B11010011= 211,
+ B11010100= 212,
+ B11010101= 213,
+ B11010110= 214,
+ B11010111= 215,
+ B11011000= 216,
+ B11011001= 217,
+ B11011010= 218,
+ B11011011= 219,
+ B11011100= 220,
+ B11011101= 221,
+ B11011110= 222,
+ B11011111= 223,
+ B11100000= 224,
+ B11100001= 225,
+ B11100010= 226,
+ B11100011= 227,
+ B11100100= 228,
+ B11100101= 229,
+ B11100110= 230,
+ B11100111= 231,
+ B11101000= 232,
+ B11101001= 233,
+ B11101010= 234,
+ B11101011= 235,
+ B11101100= 236,
+ B11101101= 237,
+ B11101110= 238,
+ B11101111= 239,
+ B11110000= 240,
+ B11110001= 241,
+ B11110010= 242,
+ B11110011= 243,
+ B11110100= 244,
+ B11110101= 245,
+ B11110110= 246,
+ B11110111= 247,
+ B11111000= 248,
+ B11111001= 249,
+ B11111010= 250,
+ B11111011= 251,
+ B11111100= 252,
+ B11111101= 253,
+ B11111110= 254,
+ B11111111= 255
+};
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_mnemonic.h b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_mnemonic.h
new file mode 100644
index 0000000000..28d2d222f9
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_mnemonic.h
@@ -0,0 +1,2017 @@
+/*******************************************************************************
+* Copyright 2016-2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*******************************************************************************
+* Copyright (c) 2007 MITSUNARI Shigeo
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* Neither the name of the copyright owner nor the names of its contributors may
+* be used to endorse or promote products derived from this software without
+* specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+const char *getVersionString() const { return "5.76"; }
+void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); }
+void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); }
+void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }
+void add(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x00, 0); }
+void add(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x00); }
+void addpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0x66, isXMM_XMMorMEM); }
+void addps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0x100, isXMM_XMMorMEM); }
+void addsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0xF2, isXMM_XMMorMEM); }
+void addss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0xF3, isXMM_XMMorMEM); }
+void addsubpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xD0, 0x66, isXMM_XMMorMEM); }
+void addsubps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xD0, 0xF2, isXMM_XMMorMEM); }
+void adox(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0xF3, isREG32_REG32orMEM, NONE, 0x38); }
+void aesdec(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDE, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void aesdeclast(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDF, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void aesenc(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDC, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void aesenclast(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDD, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void aesimc(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDB, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void aeskeygenassist(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0xDF, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void and_(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x20, 4); }
+void and_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x20); }
+void andn(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_0F38, 0xf2, true); }
+void andnpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x55, 0x66, isXMM_XMMorMEM); }
+void andnps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x55, 0x100, isXMM_XMMorMEM); }
+void andpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x54, 0x66, isXMM_XMMorMEM); }
+void andps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x54, 0x100, isXMM_XMMorMEM); }
+void bextr(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_0F38, 0xf7, false); }
+void blendpd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0D, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void blendps(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0C, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void blendvpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void blendvps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void blsi(const Reg32e& r, const Operand& op) { opGpr(Reg32e(3, r.getBit()), op, r, T_0F38, 0xf3, false); }
+void blsmsk(const Reg32e& r, const Operand& op) { opGpr(Reg32e(2, r.getBit()), op, r, T_0F38, 0xf3, false); }
+void blsr(const Reg32e& r, const Operand& op) { opGpr(Reg32e(1, r.getBit()), op, r, T_0F38, 0xf3, false); }
+void bnd() { db(0xF2); }
+void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }
+void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); }
+void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }
+void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, 0x0F, 0x1A); }
+void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); }
+void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); }
+void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); }
+void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); }
+void bsf(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBC); }
+void bsr(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBD); }
+void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); }
+void bt(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xA3); }
+void bt(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, 4, 0x0f, 0xba, NONE, false, 1); db(imm); }
+void btc(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xBB); }
+void btc(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, 7, 0x0f, 0xba, NONE, false, 1); db(imm); }
+void btr(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xB3); }
+void btr(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, 6, 0x0f, 0xba, NONE, false, 1); db(imm); }
+void bts(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xAB); }
+void bts(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, 5, 0x0f, 0xba, NONE, false, 1); db(imm); }
+void bzhi(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_0F38, 0xf5, false); }
+void cbw() { db(0x66); db(0x98); }
+void cdq() { db(0x99); }
+void clc() { db(0xF8); }
+void cld() { db(0xFC); }
+void clflush(const Address& addr) { opModM(addr, Reg32(7), 0x0F, 0xAE); }
+void cli() { db(0xFA); }
+void cmc() { db(0xF5); }
+void cmova(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 7); }//-V524
+void cmovae(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524
+void cmovb(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524
+void cmovbe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 6); }//-V524
+void cmovc(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524
+void cmove(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 4); }//-V524
+void cmovg(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 15); }//-V524
+void cmovge(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 13); }//-V524
+void cmovl(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 12); }//-V524
+void cmovle(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 14); }//-V524
+void cmovna(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 6); }//-V524
+void cmovnae(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524
+void cmovnb(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524
+void cmovnbe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 7); }//-V524
+void cmovnc(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524
+void cmovne(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 5); }//-V524
+void cmovng(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 14); }//-V524
+void cmovnge(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 12); }//-V524
+void cmovnl(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 13); }//-V524
+void cmovnle(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 15); }//-V524
+void cmovno(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 1); }//-V524
+void cmovnp(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 11); }//-V524
+void cmovns(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 9); }//-V524
+void cmovnz(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 5); }//-V524
+void cmovo(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 0); }//-V524
+void cmovp(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 10); }//-V524
+void cmovpe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 10); }//-V524
+void cmovpo(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 11); }//-V524
+void cmovs(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 8); }//-V524
+void cmovz(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 4); }//-V524
+void cmp(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x38, 7); }
+void cmp(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x38); }
+void cmpeqpd(const Xmm& x, const Operand& op) { cmppd(x, op, 0); }
+void cmpeqps(const Xmm& x, const Operand& op) { cmpps(x, op, 0); }
+void cmpeqsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 0); }
+void cmpeqss(const Xmm& x, const Operand& op) { cmpss(x, op, 0); }
+void cmplepd(const Xmm& x, const Operand& op) { cmppd(x, op, 2); }
+void cmpleps(const Xmm& x, const Operand& op) { cmpps(x, op, 2); }
+void cmplesd(const Xmm& x, const Operand& op) { cmpsd(x, op, 2); }
+void cmpless(const Xmm& x, const Operand& op) { cmpss(x, op, 2); }
+void cmpltpd(const Xmm& x, const Operand& op) { cmppd(x, op, 1); }
+void cmpltps(const Xmm& x, const Operand& op) { cmpps(x, op, 1); }
+void cmpltsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 1); }
+void cmpltss(const Xmm& x, const Operand& op) { cmpss(x, op, 1); }
+void cmpneqpd(const Xmm& x, const Operand& op) { cmppd(x, op, 4); }
+void cmpneqps(const Xmm& x, const Operand& op) { cmpps(x, op, 4); }
+void cmpneqsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 4); }
+void cmpneqss(const Xmm& x, const Operand& op) { cmpss(x, op, 4); }
+void cmpnlepd(const Xmm& x, const Operand& op) { cmppd(x, op, 6); }
+void cmpnleps(const Xmm& x, const Operand& op) { cmpps(x, op, 6); }
+void cmpnlesd(const Xmm& x, const Operand& op) { cmpsd(x, op, 6); }
+void cmpnless(const Xmm& x, const Operand& op) { cmpss(x, op, 6); }
+void cmpnltpd(const Xmm& x, const Operand& op) { cmppd(x, op, 5); }
+void cmpnltps(const Xmm& x, const Operand& op) { cmpps(x, op, 5); }
+void cmpnltsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 5); }
+void cmpnltss(const Xmm& x, const Operand& op) { cmpss(x, op, 5); }
+void cmpordpd(const Xmm& x, const Operand& op) { cmppd(x, op, 7); }
+void cmpordps(const Xmm& x, const Operand& op) { cmpps(x, op, 7); }
+void cmpordsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 7); }
+void cmpordss(const Xmm& x, const Operand& op) { cmpss(x, op, 7); }
+void cmppd(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC2, 0x66, isXMM_XMMorMEM, imm8); }
+void cmpps(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC2, 0x100, isXMM_XMMorMEM, imm8); }
+void cmpsb() { db(0xA6); }
+void cmpsd() { db(0xA7); }
+void cmpsd(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC2, 0xF2, isXMM_XMMorMEM, imm8); }
+void cmpss(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC2, 0xF3, isXMM_XMMorMEM, imm8); }
+void cmpsw() { db(0x66); db(0xA7); }
+void cmpunordpd(const Xmm& x, const Operand& op) { cmppd(x, op, 3); }
+void cmpunordps(const Xmm& x, const Operand& op) { cmpps(x, op, 3); }
+void cmpunordsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 3); }
+void cmpunordss(const Xmm& x, const Operand& op) { cmpss(x, op, 3); }
+void cmpxchg(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xB0 | (reg.isBit(8) ? 0 : 1)); }
+void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xC7); }
+void comisd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2F, 0x66, isXMM_XMMorMEM); }
+void comiss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2F, 0x100, isXMM_XMMorMEM); }
+void cpuid() { db(0x0F); db(0xA2); }
+void crc32(const Reg32e& reg, const Operand& op) { if (reg.isBit(32) && op.isBit(16)) db(0x66); db(0xF2); opModRM(reg, op, op.isREG(), op.isMEM(), 0x0F, 0x38, 0xF0 | (op.isBit(8) ? 0 : 1)); }
+void cvtdq2pd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0xF3, isXMM_XMMorMEM); }
+void cvtdq2ps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0x100, isXMM_XMMorMEM); }
+void cvtpd2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0xF2, isXMM_XMMorMEM); }
+void cvtpd2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0x66, isMMX_XMMorMEM); }
+void cvtpd2ps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0x66, isXMM_XMMorMEM); }
+void cvtpi2pd(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0x66, isXMM_MMXorMEM); }
+void cvtpi2ps(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0x100, isXMM_MMXorMEM); }
+void cvtps2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0x66, isXMM_XMMorMEM); }
+void cvtps2pd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0x100, isXMM_XMMorMEM); }
+void cvtps2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0x100, isMMX_XMMorMEM); }
+void cvtsd2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0xF2, isREG32_XMMorMEM); }
+void cvtsd2ss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0xF2, isXMM_XMMorMEM); }
+void cvtsi2sd(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0xF2, isXMM_REG32orMEM); }
+void cvtsi2ss(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0xF3, isXMM_REG32orMEM); }
+void cvtss2sd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0xF3, isXMM_XMMorMEM); }
+void cvtss2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0xF3, isREG32_XMMorMEM); }
+void cvttpd2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0x66, isXMM_XMMorMEM); }
+void cvttpd2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0x66, isMMX_XMMorMEM); }
+void cvttps2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0xF3, isXMM_XMMorMEM); }
+void cvttps2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0x100, isMMX_XMMorMEM); }
+void cvttsd2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0xF2, isREG32_XMMorMEM); }
+void cvttss2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0xF3, isREG32_XMMorMEM); }
+void cwd() { db(0x66); db(0x99); }
+void cwde() { db(0x98); }
+void dec(const Operand& op) { opIncDec(op, 0x48, 1); }
+void div(const Operand& op) { opR_ModM(op, 0, 6, 0xF6); }
+void divpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0x66, isXMM_XMMorMEM); }
+void divps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0x100, isXMM_XMMorMEM); }
+void divsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0xF2, isXMM_XMMorMEM); }
+void divss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0xF3, isXMM_XMMorMEM); }
+void dppd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x41, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void dpps(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x40, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void emms() { db(0x0F); db(0x77); }
+void extractps(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x17, imm); }
+void f2xm1() { db(0xD9); db(0xF0); }
+void fabs() { db(0xD9); db(0xE1); }
+void fadd(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 0, 0); }
+void fadd(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8C0, 0xDCC0); }
+void fadd(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8C0, 0xDCC0); }
+void faddp() { db(0xDE); db(0xC1); }
+void faddp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEC0); }
+void faddp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEC0); }
+void fchs() { db(0xD9); db(0xE0); }
+void fcmovb(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAC0, 0x00C0); }
+void fcmovb(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAC0, 0x00C0); }
+void fcmovbe(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAD0, 0x00D0); }
+void fcmovbe(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAD0, 0x00D0); }
+void fcmove(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAC8, 0x00C8); }
+void fcmove(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAC8, 0x00C8); }
+void fcmovnb(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBC0, 0x00C0); }
+void fcmovnb(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBC0, 0x00C0); }
+void fcmovnbe(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBD0, 0x00D0); }
+void fcmovnbe(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBD0, 0x00D0); }
+void fcmovne(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBC8, 0x00C8); }
+void fcmovne(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBC8, 0x00C8); }
+void fcmovnu(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBD8, 0x00D8); }
+void fcmovnu(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBD8, 0x00D8); }
+void fcmovu(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAD8, 0x00D8); }
+void fcmovu(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAD8, 0x00D8); }
+void fcom() { db(0xD8); db(0xD1); }
+void fcom(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 2, 0); }
+void fcom(const Fpu& reg) { opFpu(reg, 0xD8, 0xD0); }
+void fcomi(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBF0, 0x00F0); }
+void fcomi(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBF0, 0x00F0); }
+void fcomip(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDFF0, 0x00F0); }
+void fcomip(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDFF0, 0x00F0); }
+void fcomp() { db(0xD8); db(0xD9); }
+void fcomp(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 3, 0); }
+void fcomp(const Fpu& reg) { opFpu(reg, 0xD8, 0xD8); }
+void fcompp() { db(0xDE); db(0xD9); }
+void fcos() { db(0xD9); db(0xFF); }
+void fdecstp() { db(0xD9); db(0xF6); }
+void fdiv(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 6, 0); }
+void fdiv(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8F0, 0xDCF8); }
+void fdiv(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8F0, 0xDCF8); }
+void fdivp() { db(0xDE); db(0xF9); }
+void fdivp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEF8); }
+void fdivp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEF8); }
+void fdivr(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 7, 0); }
+void fdivr(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8F8, 0xDCF0); }
+void fdivr(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8F8, 0xDCF0); }
+void fdivrp() { db(0xDE); db(0xF1); }
+void fdivrp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEF0); }
+void fdivrp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEF0); }
+void ffree(const Fpu& reg) { opFpu(reg, 0xDD, 0xC0); }
+void fiadd(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 0, 0); }
+void ficom(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 2, 0); }
+void ficomp(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 3, 0); }
+void fidiv(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 6, 0); }
+void fidivr(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 7, 0); }
+void fild(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDF, 0, 5); }
+void fimul(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 1, 0); }
+void fincstp() { db(0xD9); db(0xF7); }
+void finit() { db(0x9B); db(0xDB); db(0xE3); }
+void fist(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0x00, 2, 0); }
+void fistp(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDF, 3, 7); }
+void fisttp(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDD, 1, 0); }
+void fisub(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 4, 0); }
+void fisubr(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 5, 0); }
+void fld(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 0, 0); }
+void fld(const Fpu& reg) { opFpu(reg, 0xD9, 0xC0); }
+void fld1() { db(0xD9); db(0xE8); }
+void fldcw(const Address& addr) { opModM(addr, Reg32(5), 0xD9, 0x100); }
+void fldl2e() { db(0xD9); db(0xEA); }
+void fldl2t() { db(0xD9); db(0xE9); }
+void fldlg2() { db(0xD9); db(0xEC); }
+void fldln2() { db(0xD9); db(0xED); }
+void fldpi() { db(0xD9); db(0xEB); }
+void fldz() { db(0xD9); db(0xEE); }
+void fmul(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 1, 0); }
+void fmul(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8C8, 0xDCC8); }
+void fmul(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8C8, 0xDCC8); }
+void fmulp() { db(0xDE); db(0xC9); }
+void fmulp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEC8); }
+void fmulp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEC8); }
+void fninit() { db(0xDB); db(0xE3); }
+void fnop() { db(0xD9); db(0xD0); }
+void fpatan() { db(0xD9); db(0xF3); }
+void fprem() { db(0xD9); db(0xF8); }
+void fprem1() { db(0xD9); db(0xF5); }
+void fptan() { db(0xD9); db(0xF2); }
+void frndint() { db(0xD9); db(0xFC); }
+void fscale() { db(0xD9); db(0xFD); }
+void fsin() { db(0xD9); db(0xFE); }
+void fsincos() { db(0xD9); db(0xFB); }
+void fsqrt() { db(0xD9); db(0xFA); }
+void fst(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 2, 0); }
+void fst(const Fpu& reg) { opFpu(reg, 0xDD, 0xD0); }
+void fstcw(const Address& addr) { db(0x9B); opModM(addr, Reg32(7), 0xD9, NONE); }
+void fstp(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 3, 0); }
+void fstp(const Fpu& reg) { opFpu(reg, 0xDD, 0xD8); }
+void fsub(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 4, 0); }
+void fsub(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8E0, 0xDCE8); }
+void fsub(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8E0, 0xDCE8); }
+void fsubp() { db(0xDE); db(0xE9); }
+void fsubp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEE8); }
+void fsubp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEE8); }
+void fsubr(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 5, 0); }
+void fsubr(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8E8, 0xDCE0); }
+void fsubr(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8E8, 0xDCE0); }
+void fsubrp() { db(0xDE); db(0xE1); }
+void fsubrp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEE0); }
+void fsubrp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEE0); }
+void ftst() { db(0xD9); db(0xE4); }
+void fucom() { db(0xDD); db(0xE1); }
+void fucom(const Fpu& reg) { opFpu(reg, 0xDD, 0xE0); }
+void fucomi(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBE8, 0x00E8); }
+void fucomi(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBE8, 0x00E8); }
+void fucomip(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDFE8, 0x00E8); }
+void fucomip(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDFE8, 0x00E8); }
+void fucomp() { db(0xDD); db(0xE9); }
+void fucomp(const Fpu& reg) { opFpu(reg, 0xDD, 0xE8); }
+void fucompp() { db(0xDA); db(0xE9); }
+void fwait() { db(0x9B); }
+void fxam() { db(0xD9); db(0xE5); }
+void fxch() { db(0xD9); db(0xC9); }
+void fxch(const Fpu& reg) { opFpu(reg, 0xD9, 0xC8); }
+void fxtract() { db(0xD9); db(0xF4); }
+void fyl2x() { db(0xD9); db(0xF1); }
+void fyl2xp1() { db(0xD9); db(0xF9); }
+void gf2p8affineinvqb(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0xCF, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void gf2p8affineqb(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0xCE, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void gf2p8mulb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCF, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void haddpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0x66, isXMM_XMMorMEM); }
+void haddps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0xF2, isXMM_XMMorMEM); }
+void hsubpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7D, 0x66, isXMM_XMMorMEM); }
+void hsubps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7D, 0xF2, isXMM_XMMorMEM); }
+void idiv(const Operand& op) { opR_ModM(op, 0, 7, 0xF6); }
+void imul(const Operand& op) { opR_ModM(op, 0, 5, 0xF6); }
+void inc(const Operand& op) { opIncDec(op, 0x40, 0); }
+void insertps(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void ja(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524
+void ja(const char *label, LabelType type = T_AUTO) { ja(std::string(label), type); }//-V524
+void ja(const void *addr) { opJmpAbs(addr, T_NEAR, 0x77, 0x87, 0x0F); }//-V524
+void ja(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524
+void jae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jae(const char *label, LabelType type = T_AUTO) { jae(std::string(label), type); }//-V524
+void jae(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524
+void jae(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void jb(const char *label, LabelType type = T_AUTO) { jb(std::string(label), type); }//-V524
+void jb(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524
+void jb(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void jbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524
+void jbe(const char *label, LabelType type = T_AUTO) { jbe(std::string(label), type); }//-V524
+void jbe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x76, 0x86, 0x0F); }//-V524
+void jbe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524
+void jc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void jc(const char *label, LabelType type = T_AUTO) { jc(std::string(label), type); }//-V524
+void jc(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524
+void jc(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void je(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524
+void je(const char *label, LabelType type = T_AUTO) { je(std::string(label), type); }//-V524
+void je(const void *addr) { opJmpAbs(addr, T_NEAR, 0x74, 0x84, 0x0F); }//-V524
+void je(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524
+void jg(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524
+void jg(const char *label, LabelType type = T_AUTO) { jg(std::string(label), type); }//-V524
+void jg(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7F, 0x8F, 0x0F); }//-V524
+void jg(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524
+void jge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524
+void jge(const char *label, LabelType type = T_AUTO) { jge(std::string(label), type); }//-V524
+void jge(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7D, 0x8D, 0x0F); }//-V524
+void jge(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524
+void jl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524
+void jl(const char *label, LabelType type = T_AUTO) { jl(std::string(label), type); }//-V524
+void jl(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7C, 0x8C, 0x0F); }//-V524
+void jl(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524
+void jle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524
+void jle(const char *label, LabelType type = T_AUTO) { jle(std::string(label), type); }//-V524
+void jle(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7E, 0x8E, 0x0F); }//-V524
+void jle(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524
+void jna(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524
+void jna(const char *label, LabelType type = T_AUTO) { jna(std::string(label), type); }//-V524
+void jna(const void *addr) { opJmpAbs(addr, T_NEAR, 0x76, 0x86, 0x0F); }//-V524
+void jna(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524
+void jnae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void jnae(const char *label, LabelType type = T_AUTO) { jnae(std::string(label), type); }//-V524
+void jnae(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524
+void jnae(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524
+void jnb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jnb(const char *label, LabelType type = T_AUTO) { jnb(std::string(label), type); }//-V524
+void jnb(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524
+void jnb(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jnbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524
+void jnbe(const char *label, LabelType type = T_AUTO) { jnbe(std::string(label), type); }//-V524
+void jnbe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x77, 0x87, 0x0F); }//-V524
+void jnbe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524
+void jnc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jnc(const char *label, LabelType type = T_AUTO) { jnc(std::string(label), type); }//-V524
+void jnc(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524
+void jnc(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524
+void jne(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524
+void jne(const char *label, LabelType type = T_AUTO) { jne(std::string(label), type); }//-V524
+void jne(const void *addr) { opJmpAbs(addr, T_NEAR, 0x75, 0x85, 0x0F); }//-V524
+void jne(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524
+void jng(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524
+void jng(const char *label, LabelType type = T_AUTO) { jng(std::string(label), type); }//-V524
+void jng(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7E, 0x8E, 0x0F); }//-V524
+void jng(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524
+void jnge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524
+void jnge(const char *label, LabelType type = T_AUTO) { jnge(std::string(label), type); }//-V524
+void jnge(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7C, 0x8C, 0x0F); }//-V524
+void jnge(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524
+void jnl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524
+void jnl(const char *label, LabelType type = T_AUTO) { jnl(std::string(label), type); }//-V524
+void jnl(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7D, 0x8D, 0x0F); }//-V524
+void jnl(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524
+void jnle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524
+void jnle(const char *label, LabelType type = T_AUTO) { jnle(std::string(label), type); }//-V524
+void jnle(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7F, 0x8F, 0x0F); }//-V524
+void jnle(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524
+void jno(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); }//-V524
+void jno(const char *label, LabelType type = T_AUTO) { jno(std::string(label), type); }//-V524
+void jno(const void *addr) { opJmpAbs(addr, T_NEAR, 0x71, 0x81, 0x0F); }//-V524
+void jno(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); }//-V524
+void jnp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524
+void jnp(const char *label, LabelType type = T_AUTO) { jnp(std::string(label), type); }//-V524
+void jnp(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7B, 0x8B, 0x0F); }//-V524
+void jnp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524
+void jns(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); }//-V524
+void jns(const char *label, LabelType type = T_AUTO) { jns(std::string(label), type); }//-V524
+void jns(const void *addr) { opJmpAbs(addr, T_NEAR, 0x79, 0x89, 0x0F); }//-V524
+void jns(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); }//-V524
+void jnz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524
+void jnz(const char *label, LabelType type = T_AUTO) { jnz(std::string(label), type); }//-V524
+void jnz(const void *addr) { opJmpAbs(addr, T_NEAR, 0x75, 0x85, 0x0F); }//-V524
+void jnz(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524
+void jo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); }//-V524
+void jo(const char *label, LabelType type = T_AUTO) { jo(std::string(label), type); }//-V524
+void jo(const void *addr) { opJmpAbs(addr, T_NEAR, 0x70, 0x80, 0x0F); }//-V524
+void jo(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); }//-V524
+void jp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524
+void jp(const char *label, LabelType type = T_AUTO) { jp(std::string(label), type); }//-V524
+void jp(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7A, 0x8A, 0x0F); }//-V524
+void jp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524
+void jpe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524
+void jpe(const char *label, LabelType type = T_AUTO) { jpe(std::string(label), type); }//-V524
+void jpe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7A, 0x8A, 0x0F); }//-V524
+void jpe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524
+void jpo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524
+void jpo(const char *label, LabelType type = T_AUTO) { jpo(std::string(label), type); }//-V524
+void jpo(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7B, 0x8B, 0x0F); }//-V524
+void jpo(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524
+void js(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); }//-V524
+void js(const char *label, LabelType type = T_AUTO) { js(std::string(label), type); }//-V524
+void js(const void *addr) { opJmpAbs(addr, T_NEAR, 0x78, 0x88, 0x0F); }//-V524
+void js(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); }//-V524
+void jz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524
+void jz(const char *label, LabelType type = T_AUTO) { jz(std::string(label), type); }//-V524
+void jz(const void *addr) { opJmpAbs(addr, T_NEAR, 0x74, 0x84, 0x0F); }//-V524
+void jz(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524
+void lahf() { db(0x9F); }
+void lddqu(const Xmm& xmm, const Address& addr) { db(0xF2); opModM(addr, xmm, 0x0F, 0xF0); }
+void ldmxcsr(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0xAE); }
+void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModM(addr, reg, 0x8D); }
+void lfence() { db(0x0F); db(0xAE); db(0xE8); }
+void lock() { db(0xF0); }
+void lzcnt(const Reg&reg, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xBD); }
+void maskmovdqu(const Xmm& reg1, const Xmm& reg2) { db(0x66); opModR(reg1, reg2, 0x0F, 0xF7); }
+void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) throw Error(ERR_BAD_COMBINATION); opModR(reg1, reg2, 0x0F, 0xF7); }
+void maxpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0x66, isXMM_XMMorMEM); }
+void maxps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0x100, isXMM_XMMorMEM); }
+void maxsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0xF2, isXMM_XMMorMEM); }
+void maxss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0xF3, isXMM_XMMorMEM); }
+void mfence() { db(0x0F); db(0xAE); db(0xF0); }
+void minpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0x66, isXMM_XMMorMEM); }
+void minps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0x100, isXMM_XMMorMEM); }
+void minsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0xF2, isXMM_XMMorMEM); }
+void minss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0xF3, isXMM_XMMorMEM); }
+void monitor() { db(0x0F); db(0x01); db(0xC8); }
+void movapd(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x29); }
+void movapd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x28, 0x66); }
+void movaps(const Address& addr, const Xmm& xmm) { opModM(addr, xmm, 0x0F, 0x29); }
+void movaps(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x28, 0x100); }
+void movbe(const Address& addr, const Reg& reg) { opModM(addr, reg, 0x0F, 0x38, 0xF1); }
+void movbe(const Reg& reg, const Address& addr) { opModM(addr, reg, 0x0F, 0x38, 0xF0); }
+void movd(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x7E); }
+void movd(const Mmx& mmx, const Address& addr) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x6E); }
+void movd(const Mmx& mmx, const Reg32& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }
+void movd(const Reg32& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }
+void movddup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x12, 0xF2, isXMM_XMMorMEM, NONE, NONE); }
+void movdq2q(const Mmx& mmx, const Xmm& xmm) { db(0xF2); opModR(mmx, xmm, 0x0F, 0xD6); }
+void movdqa(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x7F); }
+void movdqa(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x6F, 0x66); }
+void movdqu(const Address& addr, const Xmm& xmm) { db(0xF3); opModM(addr, xmm, 0x0F, 0x7F); }
+void movdqu(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x6F, 0xF3); }
+void movhlps(const Xmm& reg1, const Xmm& reg2) { opModR(reg1, reg2, 0x0F, 0x12); }
+void movhpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x16, 0x66); }
+void movhps(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x16, 0x100); }
+void movlhps(const Xmm& reg1, const Xmm& reg2) { opModR(reg1, reg2, 0x0F, 0x16); }
+void movlpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0x66); }
+void movlps(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0x100); }
+void movmskpd(const Reg32e& reg, const Xmm& xmm) { db(0x66); movmskps(reg, xmm); }
+void movmskps(const Reg32e& reg, const Xmm& xmm) { opModR(reg, xmm, 0x0F, 0x50); }
+void movntdq(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0xE7); }
+void movntdqa(const Xmm& xmm, const Address& addr) { db(0x66); opModM(addr, xmm, 0x0F, 0x38, 0x2A); }
+void movnti(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0xC3); }
+void movntpd(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0x2B); }
+void movntps(const Address& addr, const Xmm& xmm) { opModM(addr, Mmx(xmm.getIdx()), 0x0F, 0x2B); }
+void movntq(const Address& addr, const Mmx& mmx) { if (!mmx.isMMX()) throw Error(ERR_BAD_COMBINATION); opModM(addr, mmx, 0x0F, 0xE7); }
+void movq(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, mmx.isXMM() ? 0xD6 : 0x7F); }
+void movq(const Mmx& mmx, const Operand& op) { if (mmx.isXMM()) db(0xF3); opModRM(mmx, op, (mmx.getKind() == op.getKind()), op.isMEM(), 0x0F, mmx.isXMM() ? 0x7E : 0x6F); }
+void movq2dq(const Xmm& xmm, const Mmx& mmx) { db(0xF3); opModR(xmm, mmx, 0x0F, 0xD6); }
+void movsb() { db(0xA4); }
+void movsd() { db(0xA5); }
+void movsd(const Address& addr, const Xmm& xmm) { db(0xF2); opModM(addr, xmm, 0x0F, 0x11); }
+void movsd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0xF2); }
+void movshdup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x16, 0xF3, isXMM_XMMorMEM, NONE, NONE); }
+void movsldup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x12, 0xF3, isXMM_XMMorMEM, NONE, NONE); }
+void movss(const Address& addr, const Xmm& xmm) { db(0xF3); opModM(addr, xmm, 0x0F, 0x11); }
+void movss(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0xF3); }
+void movsw() { db(0x66); db(0xA5); }
+void movsx(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0xBE); }
+void movupd(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x11); }
+void movupd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0x66); }
+void movups(const Address& addr, const Xmm& xmm) { opModM(addr, xmm, 0x0F, 0x11); }
+void movups(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0x100); }
+void movzx(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0xB6); }
+void mpsadbw(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x42, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void mul(const Operand& op) { opR_ModM(op, 0, 4, 0xF6); }
+void mulpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0x66, isXMM_XMMorMEM); }
+void mulps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0x100, isXMM_XMMorMEM); }
+void mulsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0xF2, isXMM_XMMorMEM); }
+void mulss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0xF3, isXMM_XMMorMEM); }
+void mulx(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F2 | T_0F38, 0xf6, true); }
+void mwait() { db(0x0F); db(0x01); db(0xC9); }
+void neg(const Operand& op) { opR_ModM(op, 0, 3, 0xF6); }
+void not_(const Operand& op) { opR_ModM(op, 0, 2, 0xF6); }
+void or_(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x08, 1); }
+void or_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x08); }
+void orpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x56, 0x66, isXMM_XMMorMEM); }
+void orps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x56, 0x100, isXMM_XMMorMEM); }
+void pabsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1C, 0x66, NONE, 0x38); }
+void pabsd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1E, 0x66, NONE, 0x38); }
+void pabsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1D, 0x66, NONE, 0x38); }
+void packssdw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6B); }
+void packsswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x63); }
+void packusdw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2B, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void packuswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x67); }
+void paddb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFC); }
+void paddd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFE); }
+void paddq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD4); }
+void paddsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEC); }
+void paddsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xED); }
+void paddusb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDC); }
+void paddusw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDD); }
+void paddw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFD); }
+void palignr(const Mmx& mmx, const Operand& op, int imm) { opMMX(mmx, op, 0x0f, 0x66, static_cast<uint8>(imm), 0x3a); }
+void pand(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDB); }
+void pandn(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDF); }
+void pause() { db(0xF3); db(0x90); }
+void pavgb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE0); }
+void pavgw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE3); }
+void pblendvb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x10, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pblendw(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0E, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void pclmulhqhdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x11); }
+void pclmulhqlqdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x01); }
+void pclmullqhdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x10); }
+void pclmullqlqdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x00); }
+void pclmulqdq(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x44, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void pcmpeqb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x74); }
+void pcmpeqd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x76); }
+void pcmpeqq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x29, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pcmpeqw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x75); }
+void pcmpestri(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x61, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void pcmpestrm(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x60, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void pcmpgtb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x64); }
+void pcmpgtd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x66); }
+void pcmpgtq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x37, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pcmpgtw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x65); }
+void pcmpistri(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x63, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void pcmpistrm(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x62, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void pdep(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F2 | T_0F38, 0xf5, true); }
+void pext(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F3 | T_0F38, 0xf5, true); }
+void pextrb(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x14, imm); }
+void pextrd(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x16, imm); }
+void pextrw(const Operand& op, const Mmx& xmm, uint8 imm) { opExt(op, xmm, 0x15, imm, true); }
+void phaddd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x02, 0x66, NONE, 0x38); }
+void phaddsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x03, 0x66, NONE, 0x38); }
+void phaddw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x01, 0x66, NONE, 0x38); }
+void phminposuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x41, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void phsubd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x06, 0x66, NONE, 0x38); }
+void phsubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x07, 0x66, NONE, 0x38); }
+void phsubw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x05, 0x66, NONE, 0x38); }
+void pinsrb(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x20, 0x66, isXMM_REG32orMEM, imm, 0x3A); }
+void pinsrd(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x22, 0x66, isXMM_REG32orMEM, imm, 0x3A); }
+void pinsrw(const Mmx& mmx, const Operand& op, int imm) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(mmx, op, 0xC4, mmx.isXMM() ? 0x66 : NONE, 0, imm); }
+void pmaddubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x04, 0x66, NONE, 0x38); }
+void pmaddwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF5); }
+void pmaxsb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3C, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmaxsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3D, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmaxsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEE); }
+void pmaxub(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDE); }
+void pmaxud(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3F, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmaxuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3E, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pminsb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x38, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pminsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x39, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pminsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEA); }
+void pminub(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDA); }
+void pminud(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3B, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pminuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3A, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovmskb(const Reg32e& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(reg, mmx, 0x0F, 0xD7); }
+void pmovsxbd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovsxbq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x22, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovsxbw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x20, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovsxdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x25, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovsxwd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x23, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovsxwq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x24, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxbd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x31, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxbq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x32, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxbw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x30, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x35, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxwd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x33, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmovzxwq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x34, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmuldq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x28, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmulhrsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x0B, 0x66, NONE, 0x38); }
+void pmulhuw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE4); }
+void pmulhw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE5); }
+void pmulld(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x40, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void pmullw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD5); }
+void pmuludq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF4); }
+void popcnt(const Reg&reg, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xB8); }
+void popf() { db(0x9D); }
+void por(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEB); }
+void prefetchnta(const Address& addr) { opModM(addr, Reg32(0), 0x0F, 0x18); }
+void prefetcht0(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0x18); }
+void prefetcht1(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0x18); }
+void prefetcht2(const Address& addr) { opModM(addr, Reg32(3), 0x0F, 0x18); }
+void prefetchw(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0x0D); }
+void prefetchwt1(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0x0D); }
+void psadbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF6); }
+void pshufb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x00, 0x66, NONE, 0x38); }
+void pshufd(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x70, 0x66, imm8); }
+void pshufhw(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x70, 0xF3, imm8); }
+void pshuflw(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x70, 0xF2, imm8); }
+void pshufw(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x70, 0x00, imm8); }
+void psignb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x08, 0x66, NONE, 0x38); }
+void psignd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x0A, 0x66, NONE, 0x38); }
+void psignw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x09, 0x66, NONE, 0x38); }
+void pslld(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF2); }
+void pslld(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 6); }
+void pslldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x73, 7); }
+void psllq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF3); }
+void psllq(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x73, 6); }
+void psllw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF1); }
+void psllw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 6); }
+void psrad(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE2); }
+void psrad(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 4); }
+void psraw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE1); }
+void psraw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 4); }
+void psrld(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD2); }
+void psrld(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 2); }
+void psrldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x73, 3); }
+void psrlq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD3); }
+void psrlq(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x73, 2); }
+void psrlw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD1); }
+void psrlw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 2); }
+void psubb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF8); }
+void psubd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFA); }
+void psubq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFB); }
+void psubsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE8); }
+void psubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE9); }
+void psubusb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD8); }
+void psubusw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD9); }
+void psubw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF9); }
+void ptest(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x17, 0x66, isXMM_XMMorMEM, NONE, 0x38); }
+void punpckhbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x68); }
+void punpckhdq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6A); }
+void punpckhqdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x6D, 0x66, isXMM_XMMorMEM); }
+void punpckhwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x69); }
+void punpcklbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x60); }
+void punpckldq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x62); }
+void punpcklqdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x6C, 0x66, isXMM_XMMorMEM); }
+void punpcklwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x61); }
+void pushf() { db(0x9C); }
+void pxor(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEF); }
+void rcl(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 2); }
+void rcl(const Operand& op, int imm) { opShift(op, imm, 2); }
+void rcpps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x53, 0x100, isXMM_XMMorMEM); }
+void rcpss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x53, 0xF3, isXMM_XMMorMEM); }
+void rcr(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 3); }
+void rcr(const Operand& op, int imm) { opShift(op, imm, 3); }
+void rdmsr() { db(0x0F); db(0x32); }
+void rdpmc() { db(0x0F); db(0x33); }
+void rdrand(const Reg& r) { if (r.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModR(Reg(6, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }
+void rdseed(const Reg& r) { if (r.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModR(Reg(7, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }
+void rdtsc() { db(0x0F); db(0x31); }
+void rdtscp() { db(0x0F); db(0x01); db(0xF9); }
+void rep() { db(0xF3); }
+void ret(int imm = 0) { if (imm) { db(0xC2); dw(imm); } else { db(0xC3); } }
+void rol(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 0); }
+void rol(const Operand& op, int imm) { opShift(op, imm, 0); }
+void ror(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 1); }
+void ror(const Operand& op, int imm) { opShift(op, imm, 1); }
+void rorx(const Reg32e& r, const Operand& op, uint8 imm) { opGpr(r, op, Reg32e(0, r.getBit()), T_0F3A | T_F2, 0xF0, false, imm); }
+void roundpd(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x09, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void roundps(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x08, 0x66, isXMM_XMMorMEM, imm, 0x3A); }
+void roundsd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0B, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void roundss(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0A, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }
+void rsqrtps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x52, 0x100, isXMM_XMMorMEM); }
+void rsqrtss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x52, 0xF3, isXMM_XMMorMEM); }
+void sahf() { db(0x9E); }
+void sal(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 4); }
+void sal(const Operand& op, int imm) { opShift(op, imm, 4); }
+void sar(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 7); }
+void sar(const Operand& op, int imm) { opShift(op, imm, 7); }
+void sarx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_F3 | T_0F38, 0xf7, false); }
+void sbb(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x18, 3); }
+void sbb(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x18); }
+void scasb() { db(0xAE); }
+void scasd() { db(0xAF); }
+void scasw() { db(0x66); db(0xAF); }
+void seta(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 7); }//-V524
+void setae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524
+void setb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524
+void setbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 6); }//-V524
+void setc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524
+void sete(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 4); }//-V524
+void setg(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 15); }//-V524
+void setge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 13); }//-V524
+void setl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 12); }//-V524
+void setle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 14); }//-V524
+void setna(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 6); }//-V524
+void setnae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524
+void setnb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524
+void setnbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 7); }//-V524
+void setnc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524
+void setne(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 5); }//-V524
+void setng(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 14); }//-V524
+void setnge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 12); }//-V524
+void setnl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 13); }//-V524
+void setnle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 15); }//-V524
+void setno(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 1); }//-V524
+void setnp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 11); }//-V524
+void setns(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 9); }//-V524
+void setnz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 5); }//-V524
+void seto(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 0); }//-V524
+void setp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 10); }//-V524
+void setpe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 10); }//-V524
+void setpo(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 11); }//-V524
+void sets(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 8); }//-V524
+void setz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 4); }//-V524
+void sfence() { db(0x0F); db(0xAE); db(0xF8); }
+void sha1msg1(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xC9, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void sha1msg2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCA, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void sha1nexte(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xC8, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void sha1rnds4(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0xCC, NONE, isXMM_XMMorMEM, imm, 0x3A); }
+void sha256msg1(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCC, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void sha256msg2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCD, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void sha256rnds2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCB, NONE, isXMM_XMMorMEM, NONE, 0x38); }
+void shl(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 4); }
+void shl(const Operand& op, int imm) { opShift(op, imm, 4); }
+void shld(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0xA4, &_cl); }
+void shld(const Operand& op, const Reg& reg, uint8 imm) { opShxd(op, reg, imm, 0xA4); }
+void shlx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_66 | T_0F38, 0xf7, false); }
+void shr(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 5); }
+void shr(const Operand& op, int imm) { opShift(op, imm, 5); }
+void shrd(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0xAC, &_cl); }
+void shrd(const Operand& op, const Reg& reg, uint8 imm) { opShxd(op, reg, imm, 0xAC); }
+void shrx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_F2 | T_0F38, 0xf7, false); }
+void shufpd(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC6, 0x66, isXMM_XMMorMEM, imm8); }
+void shufps(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0xC6, 0x100, isXMM_XMMorMEM, imm8); }
+void sqrtpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0x66, isXMM_XMMorMEM); }
+void sqrtps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0x100, isXMM_XMMorMEM); }
+void sqrtsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0xF2, isXMM_XMMorMEM); }
+void sqrtss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0xF3, isXMM_XMMorMEM); }
+void stac() { db(0x0F); db(0x01); db(0xCB); }
+void stc() { db(0xF9); }
+void std() { db(0xFD); }
+void sti() { db(0xFB); }
+void stmxcsr(const Address& addr) { opModM(addr, Reg32(3), 0x0F, 0xAE); }
+void stosb() { db(0xAA); }
+void stosd() { db(0xAB); }
+void stosw() { db(0x66); db(0xAB); }
+void sub(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x28, 5); }
+void sub(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x28); }
+void subpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0x66, isXMM_XMMorMEM); }
+void subps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0x100, isXMM_XMMorMEM); }
+void subsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0xF2, isXMM_XMMorMEM); }
+void subss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0xF3, isXMM_XMMorMEM); }
+void tzcnt(const Reg&reg, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xBC); }
+void ucomisd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2E, 0x66, isXMM_XMMorMEM); }
+void ucomiss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2E, 0x100, isXMM_XMMorMEM); }
+void ud2() { db(0x0F); db(0x0B); }
+void unpckhpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x66, isXMM_XMMorMEM); }
+void unpckhps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x100, isXMM_XMMorMEM); }
+void unpcklpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x66, isXMM_XMMorMEM); }
+void unpcklps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x100, isXMM_XMMorMEM); }
+void vaddpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x58); }
+void vaddps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x58); }
+void vaddsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x58); }
+void vaddss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x58); }
+void vaddsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0xD0); }
+void vaddsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0xD0); }
+void vaesdec(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDE); }
+void vaesdeclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDF); }
+void vaesenc(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDC); }
+void vaesenclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDD); }
+void vaesimc(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_W0, 0xDB); }
+void vaeskeygenassist(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0xDF, imm); }
+void vandnpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x55); }
+void vandnps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x55); }
+void vandpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x54); }
+void vandps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x54); }
+void vblendpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0D, imm); }
+void vblendps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0C, imm); }
+void vblendvpd(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4B, x4.getIdx() << 4); }
+void vblendvps(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4A, x4.getIdx() << 4); }
+void vbroadcastf128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x1A); }
+void vbroadcasti128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x5A); }
+void vbroadcastsd(const Ymm& y, const Operand& op) { if (!op.isMEM() && !(y.isYMM() && op.isXMM()) && !(y.isZMM() && op.isXMM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(y, op, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_N8, 0x19); }
+void vbroadcastss(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x18); }
+void vcmpeq_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 16); }
+void vcmpeq_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 16); }
+void vcmpeq_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 16); }
+void vcmpeq_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 16); }
+void vcmpeq_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 8); }
+void vcmpeq_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 8); }
+void vcmpeq_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 8); }
+void vcmpeq_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 8); }
+void vcmpeq_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 24); }
+void vcmpeq_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 24); }
+void vcmpeq_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 24); }
+void vcmpeq_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 24); }
+void vcmpeqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 0); }
+void vcmpeqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 0); }
+void vcmpeqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 0); }
+void vcmpeqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 0); }
+void vcmpfalse_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 27); }
+void vcmpfalse_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 27); }
+void vcmpfalse_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 27); }
+void vcmpfalse_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 27); }
+void vcmpfalsepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 11); }
+void vcmpfalseps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 11); }
+void vcmpfalsesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 11); }
+void vcmpfalsess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 11); }
+void vcmpge_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 29); }
+void vcmpge_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 29); }
+void vcmpge_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 29); }
+void vcmpge_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 29); }
+void vcmpgepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 13); }
+void vcmpgeps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 13); }
+void vcmpgesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 13); }
+void vcmpgess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 13); }
+void vcmpgt_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 30); }
+void vcmpgt_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 30); }
+void vcmpgt_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 30); }
+void vcmpgt_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 30); }
+void vcmpgtpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 14); }
+void vcmpgtps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 14); }
+void vcmpgtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 14); }
+void vcmpgtss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 14); }
+void vcmple_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 18); }
+void vcmple_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 18); }
+void vcmple_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 18); }
+void vcmple_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 18); }
+void vcmplepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 2); }
+void vcmpleps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 2); }
+void vcmplesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 2); }
+void vcmpless(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 2); }
+void vcmplt_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 17); }
+void vcmplt_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 17); }
+void vcmplt_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 17); }
+void vcmplt_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 17); }
+void vcmpltpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 1); }
+void vcmpltps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 1); }
+void vcmpltsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 1); }
+void vcmpltss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 1); }
+void vcmpneq_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 12); }
+void vcmpneq_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 12); }
+void vcmpneq_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 12); }
+void vcmpneq_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 12); }
+void vcmpneq_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 28); }
+void vcmpneq_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 28); }
+void vcmpneq_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 28); }
+void vcmpneq_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 28); }
+void vcmpneq_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 20); }
+void vcmpneq_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 20); }
+void vcmpneq_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 20); }
+void vcmpneq_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 20); }
+void vcmpneqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 4); }
+void vcmpneqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 4); }
+void vcmpneqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 4); }
+void vcmpneqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 4); }
+void vcmpnge_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 25); }
+void vcmpnge_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 25); }
+void vcmpnge_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 25); }
+void vcmpnge_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 25); }
+void vcmpngepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 9); }
+void vcmpngeps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 9); }
+void vcmpngesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 9); }
+void vcmpngess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 9); }
+void vcmpngt_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 26); }
+void vcmpngt_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 26); }
+void vcmpngt_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 26); }
+void vcmpngt_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 26); }
+void vcmpngtpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 10); }
+void vcmpngtps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 10); }
+void vcmpngtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 10); }
+void vcmpngtss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 10); }
+void vcmpnle_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 22); }
+void vcmpnle_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 22); }
+void vcmpnle_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 22); }
+void vcmpnle_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 22); }
+void vcmpnlepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 6); }
+void vcmpnleps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 6); }
+void vcmpnlesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 6); }
+void vcmpnless(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 6); }
+void vcmpnlt_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 21); }
+void vcmpnlt_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 21); }
+void vcmpnlt_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 21); }
+void vcmpnlt_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 21); }
+void vcmpnltpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 5); }
+void vcmpnltps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 5); }
+void vcmpnltsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 5); }
+void vcmpnltss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 5); }
+void vcmpord_spd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 23); }
+void vcmpord_sps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 23); }
+void vcmpord_ssd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 23); }
+void vcmpord_sss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 23); }
+void vcmpordpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 7); }
+void vcmpordps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 7); }
+void vcmpordsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 7); }
+void vcmpordss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 7); }
+void vcmppd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xC2, imm); }
+void vcmpps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_0F | T_YMM, 0xC2, imm); }
+void vcmpsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_0F, 0xC2, imm); }
+void vcmpss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0xC2, imm); }
+void vcmptrue_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 31); }
+void vcmptrue_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 31); }
+void vcmptrue_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 31); }
+void vcmptrue_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 31); }
+void vcmptruepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 15); }
+void vcmptrueps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 15); }
+void vcmptruesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 15); }
+void vcmptruess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 15); }
+void vcmpunord_spd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 19); }
+void vcmpunord_sps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 19); }
+void vcmpunord_ssd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 19); }
+void vcmpunord_sss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 19); }
+void vcmpunordpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 3); }
+void vcmpunordps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 3); }
+void vcmpunordsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 3); }
+void vcmpunordss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 3); }
+void vcomisd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_66 | T_0F | T_EW1 | T_EVEX | T_SAE_X, 0x2F); }
+void vcomiss(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x2F); }
+void vcvtdq2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_F3 | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL, 0xE6); }
+void vcvtdq2ps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5B); }
+void vcvtpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_F2 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0xE6); }
+void vcvtpd2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x5A); }
+void vcvtph2ps(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F38 | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x13); }
+void vcvtps2dq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5B); }
+void vcvtps2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_SAE_Y, 0x5A); }
+void vcvtps2ph(const Operand& op, const Xmm& x, uint8 imm) { checkCvt1(x, op); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x1D, imm); }
+void vcvtsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_ER_X, 0x2D); }
+void vcvtsd2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_ER_X, 0x5A); }
+void vcvtsi2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F2 | T_EVEX, T_W1 | T_EW1 | T_ER_X | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); }
+void vcvtsi2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F3 | T_EVEX | T_ER_X, T_W1 | T_EW1 | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); }
+void vcvtss2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x5A); }
+void vcvtss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_ER_X | T_N8, 0x2D); }
+void vcvttpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_66 | T_0F | T_YMM | T_EVEX |T_EW1 | T_B64 | T_ER_Z, 0xE6); }
+void vcvttps2dq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX | T_SAE_Z | T_B32, 0x5B); }
+void vcvttsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_SAE_X, 0x2C); }
+void vcvttss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_SAE_X | T_N8, 0x2C); }
+void vdivpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5E); }
+void vdivps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5E); }
+void vdivsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x5E); }
+void vdivss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x5E); }
+void vdppd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x41, imm); }
+void vdpps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x40, imm); }
+void vextractf128(const Operand& op, const Ymm& y, uint8 imm) { if (!(op.isXMEM() && y.isYMM())) throw Error(ERR_BAD_COMBINATION); opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x19, imm); }
+void vextracti128(const Operand& op, const Ymm& y, uint8 imm) { if (!(op.isXMEM() && y.isYMM())) throw Error(ERR_BAD_COMBINATION); opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x39, imm); }
+void vextractps(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_N4, 0x17, imm); }
+void vfmadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x98); }
+void vfmadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x98); }
+void vfmadd132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x99); }
+void vfmadd132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x99); }
+void vfmadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA8); }
+void vfmadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA8); }
+void vfmadd213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xA9); }
+void vfmadd213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xA9); }
+void vfmadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB8); }
+void vfmadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB8); }
+void vfmadd231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xB9); }
+void vfmadd231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xB9); }
+void vfmaddsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x96); }
+void vfmaddsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x96); }
+void vfmaddsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA6); }
+void vfmaddsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA6); }
+void vfmaddsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB6); }
+void vfmaddsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB6); }
+void vfmsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9A); }
+void vfmsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9A); }
+void vfmsub132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9B); }
+void vfmsub132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9B); }
+void vfmsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAA); }
+void vfmsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAA); }
+void vfmsub213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAB); }
+void vfmsub213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAB); }
+void vfmsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBA); }
+void vfmsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBA); }
+void vfmsub231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBB); }
+void vfmsub231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBB); }
+void vfmsubadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x97); }
+void vfmsubadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x97); }
+void vfmsubadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA7); }
+void vfmsubadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA7); }
+void vfmsubadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB7); }
+void vfmsubadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB7); }
+void vfnmadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9C); }
+void vfnmadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9C); }
+void vfnmadd132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9D); }
+void vfnmadd132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9D); }
+void vfnmadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAC); }
+void vfnmadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAC); }
+void vfnmadd213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAD); }
+void vfnmadd213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAD); }
+void vfnmadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBC); }
+void vfnmadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBC); }
+void vfnmadd231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBD); }
+void vfnmadd231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBD); }
+void vfnmsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9E); }
+void vfnmsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9E); }
+void vfnmsub132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9F); }
+void vfnmsub132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9F); }
+void vfnmsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAE); }
+void vfnmsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAE); }
+void vfnmsub213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAF); }
+void vfnmsub213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAF); }
+void vfnmsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBE); }
+void vfnmsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBE); }
+void vfnmsub231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBF); }
+void vfnmsub231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBF); }
+void vgatherdpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x92, 0); }
+void vgatherdps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x92, 1); }
+void vgatherqpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x93, 1); }
+void vgatherqps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x93, 2); }
+void vgf2p8affineinvqb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_SAE_Z | T_B64, 0xCF, imm); }
+void vgf2p8affineqb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_SAE_Z | T_B64, 0xCE, imm); }
+void vgf2p8mulb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_SAE_Z, 0xCF); }
+void vhaddpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7C); }
+void vhaddps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0x7C); }
+void vhsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7D); }
+void vhsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0x7D); }
+void vinsertf128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x18, imm); }
+void vinserti128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x38, imm); }
+void vinsertps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_W0 | T_EW0 | T_EVEX, 0x21, imm); }
+void vlddqu(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, cvtIdx0(x), addr, T_0F | T_F2 | T_W0 | T_YMM, 0xF0); }
+void vldmxcsr(const Address& addr) { opAVX_X_X_XM(xm2, xm0, addr, T_0F, 0xAE); }
+void vmaskmovdqu(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_66, 0xF7); }
+void vmaskmovpd(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2F); }
+void vmaskmovpd(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2D); }
+void vmaskmovps(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2E); }
+void vmaskmovps(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2C); }
+void vmaxpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5F); }
+void vmaxps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5F); }
+void vmaxsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x5F); }
+void vmaxss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x5F); }
+void vminpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5D); }
+void vminps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5D); }
+void vminsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x5D); }
+void vminss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x5D); }
+void vmovapd(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_M_K, 0x29); }
+void vmovapd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0x28); }
+void vmovaps(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_0F | T_EW0 | T_YMM | T_EVEX | T_M_K, 0x29); }
+void vmovaps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX, 0x28); }
+void vmovd(const Operand& op, const Xmm& x) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x7E); }
+void vmovd(const Xmm& x, const Operand& op) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x6E); }
+void vmovddup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_DUP | T_F2 | T_0F | T_EW1 | T_YMM | T_EVEX | T_ER_X | T_ER_Y | T_ER_Z, 0x12); }
+void vmovdqa(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_YMM, 0x7F); }
+void vmovdqa(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_YMM, 0x6F); }
+void vmovdqu(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_F3 | T_0F | T_YMM, 0x7F); }
+void vmovdqu(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_YMM, 0x6F); }
+void vmovhlps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x12); }
+void vmovhpd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x17); }
+void vmovhpd(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x16); }
+void vmovhps(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_EVEX | T_EW0 | T_N8, 0x17); }
+void vmovhps(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, T_0F | T_EVEX | T_EW0 | T_N8, 0x16); }
+void vmovlhps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x16); }
+void vmovlpd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x13); }
+void vmovlpd(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x12); }
+void vmovlps(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_EVEX | T_EW0 | T_N8, 0x13); }
+void vmovlps(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, T_0F | T_EVEX | T_EW0 | T_N8, 0x12); }
+void vmovmskpd(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_66 | T_W0 | T_YMM, 0x50); }
+void vmovmskps(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_W0 | T_YMM, 0x50); }
+void vmovntdq(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW0, 0xE7); }
+void vmovntdqa(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0, 0x2A); }
+void vmovntpd(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW1, 0x2B); }
+void vmovntps(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_YMM | T_EVEX | T_EW0, 0x2B); }
+void vmovq(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, x.getIdx() < 16 ? 0xD6 : 0x7E); }
+void vmovq(const Xmm& x, const Address& addr) { int type, code; if (x.getIdx() < 16) { type = T_0F | T_F3; code = 0x7E; } else { type = T_0F | T_66 | T_EVEX | T_EW1 | T_N8; code = 0x6E; } opAVX_X_X_XM(x, xm0, addr, type, code); }
+void vmovq(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_F3 | T_EVEX | T_EW1 | T_N8, 0x7E); }
+void vmovsd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_M_K, 0x11); }
+void vmovsd(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX, 0x10); }
+void vmovsd(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX, 0x10); }
+void vmovshdup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX, 0x16); }
+void vmovsldup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX, 0x12); }
+void vmovss(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_M_K, 0x11); }
+void vmovss(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX, 0x10); }
+void vmovss(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX, 0x10); }
+void vmovupd(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_M_K, 0x11); }
+void vmovupd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0x10); }
+void vmovups(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_0F | T_EW0 | T_YMM | T_EVEX | T_M_K, 0x11); }
+void vmovups(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX, 0x10); }
+void vmpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x42, imm); }
+void vmulpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x59); }
+void vmulps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x59); }
+void vmulsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x59); }
+void vmulss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x59); }
+void vorpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x56); }
+void vorps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x56); }
+void vpabsb(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x1C); }
+void vpabsd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x1E); }
+void vpabsw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x1D); }
+void vpackssdw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x6B); }
+void vpacksswb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x63); }
+void vpackusdw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x2B); }
+void vpackuswb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x67); }
+void vpaddb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xFC); }
+void vpaddd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xFE); }
+void vpaddq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xD4); }
+void vpaddsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEC); }
+void vpaddsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xED); }
+void vpaddusb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDC); }
+void vpaddusw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDD); }
+void vpaddw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xFD); }
+void vpalignr(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_YMM | T_EVEX, 0x0F, imm); }
+void vpand(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xDB); }
+void vpandn(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xDF); }
+void vpavgb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE0); }
+void vpavgw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE3); }
+void vpblendd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x02, imm); }
+void vpblendvb(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4C, x4.getIdx() << 4); }
+void vpblendw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0E, imm); }
+void vpbroadcastb(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x78); }
+void vpbroadcastd(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x58); }
+void vpbroadcastq(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX, 0x59); }
+void vpbroadcastw(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x79); }
+void vpclmulqdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM | T_EVEX, 0x44, imm); }
+void vpcmpeqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x74); }
+void vpcmpeqd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x76); }
+void vpcmpeqq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x29); }
+void vpcmpeqw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x75); }
+void vpcmpestri(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x61, imm); }
+void vpcmpestrm(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x60, imm); }
+void vpcmpgtb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x64); }
+void vpcmpgtd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x66); }
+void vpcmpgtq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x37); }
+void vpcmpgtw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x65); }
+void vpcmpistri(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x63, imm); }
+void vpcmpistrm(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x62, imm); }
+void vperm2f128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x06, imm); }
+void vperm2i128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x46, imm); }
+void vpermd(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x36); }
+void vpermilpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x0D); }
+void vpermilpd(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_EVEX | T_B64, 0x05, imm); }
+void vpermilps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x0C); }
+void vpermilps(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_EVEX | T_B32, 0x04, imm); }
+void vpermpd(const Ymm& y, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(y, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x01, imm); }
+void vpermpd(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x16); }
+void vpermps(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x16); }
+void vpermq(const Ymm& y, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(y, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x00, imm); }
+void vpermq(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x36); }
+void vpextrb(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(8|16|i32e) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x14, imm); }
+void vpextrd(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x16, imm); }
+void vpextrq(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(64) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x16, imm); }
+void vpextrw(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(16|i32e) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); if (op.isREG() && x.getIdx() < 16) { opAVX_X_X_XM(Xmm(op.getIdx()), xm0, x, T_0F | T_66, 0xC5, imm); } else { opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N2, 0x15, imm); } }
+void vpgatherdd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x90, 1); }
+void vpgatherdq(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x90, 0); }
+void vpgatherqd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x91, 2); }
+void vpgatherqq(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x91, 1); }
+void vphaddd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x02); }
+void vphaddsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x03); }
+void vphaddw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x01); }
+void vphminposuw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38, 0x41); }
+void vphsubd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x06); }
+void vphsubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x07); }
+void vphsubw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x05); }
+void vpinsrb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x20, imm); }
+void vpinsrd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x22, imm); }
+void vpinsrq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(64) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x22, imm); }
+void vpinsrw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F | T_66 | T_EVEX | T_N2, 0xC4, imm); }
+void vpmaddubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x04); }
+void vpmaddwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF5); }
+void vpmaskmovd(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x8E); }
+void vpmaskmovd(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x8C); }
+void vpmaskmovq(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W1 | T_YMM, 0x8E); }
+void vpmaskmovq(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W1 | T_YMM, 0x8C); }
+void vpmaxsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3C); }
+void vpmaxsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3D); }
+void vpmaxsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEE); }
+void vpmaxub(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDE); }
+void vpmaxud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3F); }
+void vpmaxuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3E); }
+void vpminsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x38); }
+void vpminsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x39); }
+void vpminsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEA); }
+void vpminub(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDA); }
+void vpminud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3B); }
+void vpminuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3A); }
+void vpmovmskb(const Reg32e& r, const Xmm& x) { if (!x.is(Operand::XMM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(x.isYMM() ? Ymm(r.getIdx()) : Xmm(r.getIdx()), 0, x, T_0F | T_66 | T_YMM, 0xD7); }
+void vpmovsxbd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x21); }
+void vpmovsxbq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N2 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x22); }
+void vpmovsxbw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x20); }
+void vpmovsxdq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX, 0x25); }
+void vpmovsxwd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x23); }
+void vpmovsxwq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x24); }
+void vpmovzxbd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x31); }
+void vpmovzxbq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N2 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x32); }
+void vpmovzxbw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x30); }
+void vpmovzxdq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX, 0x35); }
+void vpmovzxwd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x33); }
+void vpmovzxwq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x34); }
+void vpmuldq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x28); }
+void vpmulhrsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x0B); }
+void vpmulhuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE4); }
+void vpmulhw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE5); }
+void vpmulld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x40); }
+void vpmullw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD5); }
+void vpmuludq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xF4); }
+void vpor(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xEB); }
+void vpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF6); }
+void vpshufb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x00); }
+void vpshufd(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x70, imm); }
+void vpshufhw(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_YMM | T_EVEX, 0x70, imm); }
+void vpshuflw(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_F2 | T_0F | T_YMM | T_EVEX, 0x70, imm); }
+void vpsignb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x08); }
+void vpsignd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x0A); }
+void vpsignw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x09); }
+void vpslld(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); }
+void vpslld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xF2); }
+void vpslldq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 7), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x73, imm); }
+void vpsllq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64 | T_MEM_EVEX, 0x73, imm); }
+void vpsllq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0xF3); }
+void vpsllvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x47); }
+void vpsllvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x47); }
+void vpsllw(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); }
+void vpsllw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xF1); }
+void vpsrad(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); }
+void vpsrad(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xE2); }
+void vpsravd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x46); }
+void vpsraw(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); }
+void vpsraw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xE1); }
+void vpsrld(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); }
+void vpsrld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xD2); }
+void vpsrldq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 3), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x73, imm); }
+void vpsrlq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64 | T_MEM_EVEX, 0x73, imm); }
+void vpsrlq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0xD3); }
+void vpsrlvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x45); }
+void vpsrlvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x45); }
+void vpsrlw(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); }
+void vpsrlw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xD1); }
+void vpsubb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF8); }
+void vpsubd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xFA); }
+void vpsubq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xFB); }
+void vpsubsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE8); }
+void vpsubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE9); }
+void vpsubusb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD8); }
+void vpsubusw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD9); }
+void vpsubw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF9); }
+void vptest(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x17); }
+void vpunpckhbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x68); }
+void vpunpckhdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x6A); }
+void vpunpckhqdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x6D); }
+void vpunpckhwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x69); }
+void vpunpcklbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x60); }
+void vpunpckldq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x62); }
+void vpunpcklqdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x6C); }
+void vpunpcklwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x61); }
+void vpxor(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xEF); }
+void vrcpps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_YMM, 0x53); }
+void vrcpss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0x53); }
+void vroundpd(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_YMM, 0x09, imm); }
+void vroundps(const Xmm& xm, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_YMM, 0x08, imm); }
+void vroundsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x0B, imm); }
+void vroundss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x0A, imm); }
+void vrsqrtps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_YMM, 0x52); }
+void vrsqrtss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0x52); }
+void vshufpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xC6, imm); }
+void vshufps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xC6, imm); }
+void vsqrtpd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x51); }
+void vsqrtps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x51); }
+void vsqrtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_ER_X, 0x51); }
+void vsqrtss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_ER_X, 0x51); }
+void vstmxcsr(const Address& addr) { opAVX_X_X_XM(xm3, xm0, addr, T_0F, 0xAE); }
+void vsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5C); }
+void vsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5C); }
+void vsubsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x5C); }
+void vsubss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x5C); }
+void vtestpd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x0F); }
+void vtestps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x0E); }
+void vucomisd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_66 | T_0F | T_EW1 | T_EVEX | T_SAE_X, 0x2E); }
+void vucomiss(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x2E); }
+void vunpckhpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x15); }
+void vunpckhps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x15); }
+void vunpcklpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x14); }
+void vunpcklps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x14); }
+void vxorpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x57); }
+void vxorps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x57); }
+void vzeroall() { db(0xC5); db(0xFC); db(0x77); }
+void vzeroupper() { db(0xC5); db(0xF8); db(0x77); }
+void wait() { db(0x9B); }
+void wbinvd() { db(0x0F); db(0x09); }
+void wrmsr() { db(0x0F); db(0x30); }
+void xadd(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xC0 | (reg.isBit(8) ? 0 : 1)); }
+void xgetbv() { db(0x0F); db(0x01); db(0xD0); }
+void xlatb() { db(0xD7); }
+void xor_(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x30, 6); }
+void xor_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x30); }
+void xorpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x57, 0x66, isXMM_XMMorMEM); }
+void xorps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x57, 0x100, isXMM_XMMorMEM); }
+#ifdef XBYAK_ENABLE_OMITTED_OPERAND
+void vblendpd(const Xmm& x, const Operand& op, uint8 imm) { vblendpd(x, x, op, imm); }
+void vblendps(const Xmm& x, const Operand& op, uint8 imm) { vblendps(x, x, op, imm); }
+void vblendvpd(const Xmm& x1, const Operand& op, const Xmm& x4) { vblendvpd(x1, x1, op, x4); }
+void vblendvps(const Xmm& x1, const Operand& op, const Xmm& x4) { vblendvps(x1, x1, op, x4); }
+void vcmpeq_ospd(const Xmm& x, const Operand& op) { vcmpeq_ospd(x, x, op); }
+void vcmpeq_osps(const Xmm& x, const Operand& op) { vcmpeq_osps(x, x, op); }
+void vcmpeq_ossd(const Xmm& x, const Operand& op) { vcmpeq_ossd(x, x, op); }
+void vcmpeq_osss(const Xmm& x, const Operand& op) { vcmpeq_osss(x, x, op); }
+void vcmpeq_uqpd(const Xmm& x, const Operand& op) { vcmpeq_uqpd(x, x, op); }
+void vcmpeq_uqps(const Xmm& x, const Operand& op) { vcmpeq_uqps(x, x, op); }
+void vcmpeq_uqsd(const Xmm& x, const Operand& op) { vcmpeq_uqsd(x, x, op); }
+void vcmpeq_uqss(const Xmm& x, const Operand& op) { vcmpeq_uqss(x, x, op); }
+void vcmpeq_uspd(const Xmm& x, const Operand& op) { vcmpeq_uspd(x, x, op); }
+void vcmpeq_usps(const Xmm& x, const Operand& op) { vcmpeq_usps(x, x, op); }
+void vcmpeq_ussd(const Xmm& x, const Operand& op) { vcmpeq_ussd(x, x, op); }
+void vcmpeq_usss(const Xmm& x, const Operand& op) { vcmpeq_usss(x, x, op); }
+void vcmpeqpd(const Xmm& x, const Operand& op) { vcmpeqpd(x, x, op); }
+void vcmpeqps(const Xmm& x, const Operand& op) { vcmpeqps(x, x, op); }
+void vcmpeqsd(const Xmm& x, const Operand& op) { vcmpeqsd(x, x, op); }
+void vcmpeqss(const Xmm& x, const Operand& op) { vcmpeqss(x, x, op); }
+void vcmpfalse_ospd(const Xmm& x, const Operand& op) { vcmpfalse_ospd(x, x, op); }
+void vcmpfalse_osps(const Xmm& x, const Operand& op) { vcmpfalse_osps(x, x, op); }
+void vcmpfalse_ossd(const Xmm& x, const Operand& op) { vcmpfalse_ossd(x, x, op); }
+void vcmpfalse_osss(const Xmm& x, const Operand& op) { vcmpfalse_osss(x, x, op); }
+void vcmpfalsepd(const Xmm& x, const Operand& op) { vcmpfalsepd(x, x, op); }
+void vcmpfalseps(const Xmm& x, const Operand& op) { vcmpfalseps(x, x, op); }
+void vcmpfalsesd(const Xmm& x, const Operand& op) { vcmpfalsesd(x, x, op); }
+void vcmpfalsess(const Xmm& x, const Operand& op) { vcmpfalsess(x, x, op); }
+void vcmpge_oqpd(const Xmm& x, const Operand& op) { vcmpge_oqpd(x, x, op); }
+void vcmpge_oqps(const Xmm& x, const Operand& op) { vcmpge_oqps(x, x, op); }
+void vcmpge_oqsd(const Xmm& x, const Operand& op) { vcmpge_oqsd(x, x, op); }
+void vcmpge_oqss(const Xmm& x, const Operand& op) { vcmpge_oqss(x, x, op); }
+void vcmpgepd(const Xmm& x, const Operand& op) { vcmpgepd(x, x, op); }
+void vcmpgeps(const Xmm& x, const Operand& op) { vcmpgeps(x, x, op); }
+void vcmpgesd(const Xmm& x, const Operand& op) { vcmpgesd(x, x, op); }
+void vcmpgess(const Xmm& x, const Operand& op) { vcmpgess(x, x, op); }
+void vcmpgt_oqpd(const Xmm& x, const Operand& op) { vcmpgt_oqpd(x, x, op); }
+void vcmpgt_oqps(const Xmm& x, const Operand& op) { vcmpgt_oqps(x, x, op); }
+void vcmpgt_oqsd(const Xmm& x, const Operand& op) { vcmpgt_oqsd(x, x, op); }
+void vcmpgt_oqss(const Xmm& x, const Operand& op) { vcmpgt_oqss(x, x, op); }
+void vcmpgtpd(const Xmm& x, const Operand& op) { vcmpgtpd(x, x, op); }
+void vcmpgtps(const Xmm& x, const Operand& op) { vcmpgtps(x, x, op); }
+void vcmpgtsd(const Xmm& x, const Operand& op) { vcmpgtsd(x, x, op); }
+void vcmpgtss(const Xmm& x, const Operand& op) { vcmpgtss(x, x, op); }
+void vcmple_oqpd(const Xmm& x, const Operand& op) { vcmple_oqpd(x, x, op); }
+void vcmple_oqps(const Xmm& x, const Operand& op) { vcmple_oqps(x, x, op); }
+void vcmple_oqsd(const Xmm& x, const Operand& op) { vcmple_oqsd(x, x, op); }
+void vcmple_oqss(const Xmm& x, const Operand& op) { vcmple_oqss(x, x, op); }
+void vcmplepd(const Xmm& x, const Operand& op) { vcmplepd(x, x, op); }
+void vcmpleps(const Xmm& x, const Operand& op) { vcmpleps(x, x, op); }
+void vcmplesd(const Xmm& x, const Operand& op) { vcmplesd(x, x, op); }
+void vcmpless(const Xmm& x, const Operand& op) { vcmpless(x, x, op); }
+void vcmplt_oqpd(const Xmm& x, const Operand& op) { vcmplt_oqpd(x, x, op); }
+void vcmplt_oqps(const Xmm& x, const Operand& op) { vcmplt_oqps(x, x, op); }
+void vcmplt_oqsd(const Xmm& x, const Operand& op) { vcmplt_oqsd(x, x, op); }
+void vcmplt_oqss(const Xmm& x, const Operand& op) { vcmplt_oqss(x, x, op); }
+void vcmpltpd(const Xmm& x, const Operand& op) { vcmpltpd(x, x, op); }
+void vcmpltps(const Xmm& x, const Operand& op) { vcmpltps(x, x, op); }
+void vcmpltsd(const Xmm& x, const Operand& op) { vcmpltsd(x, x, op); }
+void vcmpltss(const Xmm& x, const Operand& op) { vcmpltss(x, x, op); }
+void vcmpneq_oqpd(const Xmm& x, const Operand& op) { vcmpneq_oqpd(x, x, op); }
+void vcmpneq_oqps(const Xmm& x, const Operand& op) { vcmpneq_oqps(x, x, op); }
+void vcmpneq_oqsd(const Xmm& x, const Operand& op) { vcmpneq_oqsd(x, x, op); }
+void vcmpneq_oqss(const Xmm& x, const Operand& op) { vcmpneq_oqss(x, x, op); }
+void vcmpneq_ospd(const Xmm& x, const Operand& op) { vcmpneq_ospd(x, x, op); }
+void vcmpneq_osps(const Xmm& x, const Operand& op) { vcmpneq_osps(x, x, op); }
+void vcmpneq_ossd(const Xmm& x, const Operand& op) { vcmpneq_ossd(x, x, op); }
+void vcmpneq_osss(const Xmm& x, const Operand& op) { vcmpneq_osss(x, x, op); }
+void vcmpneq_uspd(const Xmm& x, const Operand& op) { vcmpneq_uspd(x, x, op); }
+void vcmpneq_usps(const Xmm& x, const Operand& op) { vcmpneq_usps(x, x, op); }
+void vcmpneq_ussd(const Xmm& x, const Operand& op) { vcmpneq_ussd(x, x, op); }
+void vcmpneq_usss(const Xmm& x, const Operand& op) { vcmpneq_usss(x, x, op); }
+void vcmpneqpd(const Xmm& x, const Operand& op) { vcmpneqpd(x, x, op); }
+void vcmpneqps(const Xmm& x, const Operand& op) { vcmpneqps(x, x, op); }
+void vcmpneqsd(const Xmm& x, const Operand& op) { vcmpneqsd(x, x, op); }
+void vcmpneqss(const Xmm& x, const Operand& op) { vcmpneqss(x, x, op); }
+void vcmpnge_uqpd(const Xmm& x, const Operand& op) { vcmpnge_uqpd(x, x, op); }
+void vcmpnge_uqps(const Xmm& x, const Operand& op) { vcmpnge_uqps(x, x, op); }
+void vcmpnge_uqsd(const Xmm& x, const Operand& op) { vcmpnge_uqsd(x, x, op); }
+void vcmpnge_uqss(const Xmm& x, const Operand& op) { vcmpnge_uqss(x, x, op); }
+void vcmpngepd(const Xmm& x, const Operand& op) { vcmpngepd(x, x, op); }
+void vcmpngeps(const Xmm& x, const Operand& op) { vcmpngeps(x, x, op); }
+void vcmpngesd(const Xmm& x, const Operand& op) { vcmpngesd(x, x, op); }
+void vcmpngess(const Xmm& x, const Operand& op) { vcmpngess(x, x, op); }
+void vcmpngt_uqpd(const Xmm& x, const Operand& op) { vcmpngt_uqpd(x, x, op); }
+void vcmpngt_uqps(const Xmm& x, const Operand& op) { vcmpngt_uqps(x, x, op); }
+void vcmpngt_uqsd(const Xmm& x, const Operand& op) { vcmpngt_uqsd(x, x, op); }
+void vcmpngt_uqss(const Xmm& x, const Operand& op) { vcmpngt_uqss(x, x, op); }
+void vcmpngtpd(const Xmm& x, const Operand& op) { vcmpngtpd(x, x, op); }
+void vcmpngtps(const Xmm& x, const Operand& op) { vcmpngtps(x, x, op); }
+void vcmpngtsd(const Xmm& x, const Operand& op) { vcmpngtsd(x, x, op); }
+void vcmpngtss(const Xmm& x, const Operand& op) { vcmpngtss(x, x, op); }
+void vcmpnle_uqpd(const Xmm& x, const Operand& op) { vcmpnle_uqpd(x, x, op); }
+void vcmpnle_uqps(const Xmm& x, const Operand& op) { vcmpnle_uqps(x, x, op); }
+void vcmpnle_uqsd(const Xmm& x, const Operand& op) { vcmpnle_uqsd(x, x, op); }
+void vcmpnle_uqss(const Xmm& x, const Operand& op) { vcmpnle_uqss(x, x, op); }
+void vcmpnlepd(const Xmm& x, const Operand& op) { vcmpnlepd(x, x, op); }
+void vcmpnleps(const Xmm& x, const Operand& op) { vcmpnleps(x, x, op); }
+void vcmpnlesd(const Xmm& x, const Operand& op) { vcmpnlesd(x, x, op); }
+void vcmpnless(const Xmm& x, const Operand& op) { vcmpnless(x, x, op); }
+void vcmpnlt_uqpd(const Xmm& x, const Operand& op) { vcmpnlt_uqpd(x, x, op); }
+void vcmpnlt_uqps(const Xmm& x, const Operand& op) { vcmpnlt_uqps(x, x, op); }
+void vcmpnlt_uqsd(const Xmm& x, const Operand& op) { vcmpnlt_uqsd(x, x, op); }
+void vcmpnlt_uqss(const Xmm& x, const Operand& op) { vcmpnlt_uqss(x, x, op); }
+void vcmpnltpd(const Xmm& x, const Operand& op) { vcmpnltpd(x, x, op); }
+void vcmpnltps(const Xmm& x, const Operand& op) { vcmpnltps(x, x, op); }
+void vcmpnltsd(const Xmm& x, const Operand& op) { vcmpnltsd(x, x, op); }
+void vcmpnltss(const Xmm& x, const Operand& op) { vcmpnltss(x, x, op); }
+void vcmpord_spd(const Xmm& x, const Operand& op) { vcmpord_spd(x, x, op); }
+void vcmpord_sps(const Xmm& x, const Operand& op) { vcmpord_sps(x, x, op); }
+void vcmpord_ssd(const Xmm& x, const Operand& op) { vcmpord_ssd(x, x, op); }
+void vcmpord_sss(const Xmm& x, const Operand& op) { vcmpord_sss(x, x, op); }
+void vcmpordpd(const Xmm& x, const Operand& op) { vcmpordpd(x, x, op); }
+void vcmpordps(const Xmm& x, const Operand& op) { vcmpordps(x, x, op); }
+void vcmpordsd(const Xmm& x, const Operand& op) { vcmpordsd(x, x, op); }
+void vcmpordss(const Xmm& x, const Operand& op) { vcmpordss(x, x, op); }
+void vcmppd(const Xmm& x, const Operand& op, uint8 imm) { vcmppd(x, x, op, imm); }
+void vcmpps(const Xmm& x, const Operand& op, uint8 imm) { vcmpps(x, x, op, imm); }
+void vcmpsd(const Xmm& x, const Operand& op, uint8 imm) { vcmpsd(x, x, op, imm); }
+void vcmpss(const Xmm& x, const Operand& op, uint8 imm) { vcmpss(x, x, op, imm); }
+void vcmptrue_uspd(const Xmm& x, const Operand& op) { vcmptrue_uspd(x, x, op); }
+void vcmptrue_usps(const Xmm& x, const Operand& op) { vcmptrue_usps(x, x, op); }
+void vcmptrue_ussd(const Xmm& x, const Operand& op) { vcmptrue_ussd(x, x, op); }
+void vcmptrue_usss(const Xmm& x, const Operand& op) { vcmptrue_usss(x, x, op); }
+void vcmptruepd(const Xmm& x, const Operand& op) { vcmptruepd(x, x, op); }
+void vcmptrueps(const Xmm& x, const Operand& op) { vcmptrueps(x, x, op); }
+void vcmptruesd(const Xmm& x, const Operand& op) { vcmptruesd(x, x, op); }
+void vcmptruess(const Xmm& x, const Operand& op) { vcmptruess(x, x, op); }
+void vcmpunord_spd(const Xmm& x, const Operand& op) { vcmpunord_spd(x, x, op); }
+void vcmpunord_sps(const Xmm& x, const Operand& op) { vcmpunord_sps(x, x, op); }
+void vcmpunord_ssd(const Xmm& x, const Operand& op) { vcmpunord_ssd(x, x, op); }
+void vcmpunord_sss(const Xmm& x, const Operand& op) { vcmpunord_sss(x, x, op); }
+void vcmpunordpd(const Xmm& x, const Operand& op) { vcmpunordpd(x, x, op); }
+void vcmpunordps(const Xmm& x, const Operand& op) { vcmpunordps(x, x, op); }
+void vcmpunordsd(const Xmm& x, const Operand& op) { vcmpunordsd(x, x, op); }
+void vcmpunordss(const Xmm& x, const Operand& op) { vcmpunordss(x, x, op); }
+void vcvtsd2ss(const Xmm& x, const Operand& op) { vcvtsd2ss(x, x, op); }
+void vcvtsi2sd(const Xmm& x, const Operand& op) { vcvtsi2sd(x, x, op); }
+void vcvtsi2ss(const Xmm& x, const Operand& op) { vcvtsi2ss(x, x, op); }
+void vcvtss2sd(const Xmm& x, const Operand& op) { vcvtss2sd(x, x, op); }
+void vdppd(const Xmm& x, const Operand& op, uint8 imm) { vdppd(x, x, op, imm); }
+void vdpps(const Xmm& x, const Operand& op, uint8 imm) { vdpps(x, x, op, imm); }
+void vinsertps(const Xmm& x, const Operand& op, uint8 imm) { vinsertps(x, x, op, imm); }
+void vmpsadbw(const Xmm& x, const Operand& op, uint8 imm) { vmpsadbw(x, x, op, imm); }
+void vpackssdw(const Xmm& x, const Operand& op) { vpackssdw(x, x, op); }
+void vpacksswb(const Xmm& x, const Operand& op) { vpacksswb(x, x, op); }
+void vpackusdw(const Xmm& x, const Operand& op) { vpackusdw(x, x, op); }
+void vpackuswb(const Xmm& x, const Operand& op) { vpackuswb(x, x, op); }
+void vpaddb(const Xmm& x, const Operand& op) { vpaddb(x, x, op); }
+void vpaddd(const Xmm& x, const Operand& op) { vpaddd(x, x, op); }
+void vpaddq(const Xmm& x, const Operand& op) { vpaddq(x, x, op); }
+void vpaddsb(const Xmm& x, const Operand& op) { vpaddsb(x, x, op); }
+void vpaddsw(const Xmm& x, const Operand& op) { vpaddsw(x, x, op); }
+void vpaddusb(const Xmm& x, const Operand& op) { vpaddusb(x, x, op); }
+void vpaddusw(const Xmm& x, const Operand& op) { vpaddusw(x, x, op); }
+void vpaddw(const Xmm& x, const Operand& op) { vpaddw(x, x, op); }
+void vpalignr(const Xmm& x, const Operand& op, uint8 imm) { vpalignr(x, x, op, imm); }
+void vpand(const Xmm& x, const Operand& op) { vpand(x, x, op); }
+void vpandn(const Xmm& x, const Operand& op) { vpandn(x, x, op); }
+void vpavgb(const Xmm& x, const Operand& op) { vpavgb(x, x, op); }
+void vpavgw(const Xmm& x, const Operand& op) { vpavgw(x, x, op); }
+void vpblendd(const Xmm& x, const Operand& op, uint8 imm) { vpblendd(x, x, op, imm); }
+void vpblendvb(const Xmm& x1, const Operand& op, const Xmm& x4) { vpblendvb(x1, x1, op, x4); }
+void vpblendw(const Xmm& x, const Operand& op, uint8 imm) { vpblendw(x, x, op, imm); }
+void vpclmulqdq(const Xmm& x, const Operand& op, uint8 imm) { vpclmulqdq(x, x, op, imm); }
+void vpcmpeqb(const Xmm& x, const Operand& op) { vpcmpeqb(x, x, op); }
+void vpcmpeqd(const Xmm& x, const Operand& op) { vpcmpeqd(x, x, op); }
+void vpcmpeqq(const Xmm& x, const Operand& op) { vpcmpeqq(x, x, op); }
+void vpcmpeqw(const Xmm& x, const Operand& op) { vpcmpeqw(x, x, op); }
+void vpcmpgtb(const Xmm& x, const Operand& op) { vpcmpgtb(x, x, op); }
+void vpcmpgtd(const Xmm& x, const Operand& op) { vpcmpgtd(x, x, op); }
+void vpcmpgtq(const Xmm& x, const Operand& op) { vpcmpgtq(x, x, op); }
+void vpcmpgtw(const Xmm& x, const Operand& op) { vpcmpgtw(x, x, op); }
+void vphaddd(const Xmm& x, const Operand& op) { vphaddd(x, x, op); }
+void vphaddsw(const Xmm& x, const Operand& op) { vphaddsw(x, x, op); }
+void vphaddw(const Xmm& x, const Operand& op) { vphaddw(x, x, op); }
+void vphsubd(const Xmm& x, const Operand& op) { vphsubd(x, x, op); }
+void vphsubsw(const Xmm& x, const Operand& op) { vphsubsw(x, x, op); }
+void vphsubw(const Xmm& x, const Operand& op) { vphsubw(x, x, op); }
+void vpinsrb(const Xmm& x, const Operand& op, uint8 imm) { vpinsrb(x, x, op, imm); }
+void vpinsrd(const Xmm& x, const Operand& op, uint8 imm) { vpinsrd(x, x, op, imm); }
+void vpinsrq(const Xmm& x, const Operand& op, uint8 imm) { vpinsrq(x, x, op, imm); }
+void vpinsrw(const Xmm& x, const Operand& op, uint8 imm) { vpinsrw(x, x, op, imm); }
+void vpmaddubsw(const Xmm& x, const Operand& op) { vpmaddubsw(x, x, op); }
+void vpmaddwd(const Xmm& x, const Operand& op) { vpmaddwd(x, x, op); }
+void vpmaxsb(const Xmm& x, const Operand& op) { vpmaxsb(x, x, op); }
+void vpmaxsd(const Xmm& x, const Operand& op) { vpmaxsd(x, x, op); }
+void vpmaxsw(const Xmm& x, const Operand& op) { vpmaxsw(x, x, op); }
+void vpmaxub(const Xmm& x, const Operand& op) { vpmaxub(x, x, op); }
+void vpmaxud(const Xmm& x, const Operand& op) { vpmaxud(x, x, op); }
+void vpmaxuw(const Xmm& x, const Operand& op) { vpmaxuw(x, x, op); }
+void vpminsb(const Xmm& x, const Operand& op) { vpminsb(x, x, op); }
+void vpminsd(const Xmm& x, const Operand& op) { vpminsd(x, x, op); }
+void vpminsw(const Xmm& x, const Operand& op) { vpminsw(x, x, op); }
+void vpminub(const Xmm& x, const Operand& op) { vpminub(x, x, op); }
+void vpminud(const Xmm& x, const Operand& op) { vpminud(x, x, op); }
+void vpminuw(const Xmm& x, const Operand& op) { vpminuw(x, x, op); }
+void vpmuldq(const Xmm& x, const Operand& op) { vpmuldq(x, x, op); }
+void vpmulhrsw(const Xmm& x, const Operand& op) { vpmulhrsw(x, x, op); }
+void vpmulhuw(const Xmm& x, const Operand& op) { vpmulhuw(x, x, op); }
+void vpmulhw(const Xmm& x, const Operand& op) { vpmulhw(x, x, op); }
+void vpmulld(const Xmm& x, const Operand& op) { vpmulld(x, x, op); }
+void vpmullw(const Xmm& x, const Operand& op) { vpmullw(x, x, op); }
+void vpmuludq(const Xmm& x, const Operand& op) { vpmuludq(x, x, op); }
+void vpor(const Xmm& x, const Operand& op) { vpor(x, x, op); }
+void vpsadbw(const Xmm& x, const Operand& op) { vpsadbw(x, x, op); }
+void vpsignb(const Xmm& x, const Operand& op) { vpsignb(x, x, op); }
+void vpsignd(const Xmm& x, const Operand& op) { vpsignd(x, x, op); }
+void vpsignw(const Xmm& x, const Operand& op) { vpsignw(x, x, op); }
+void vpslld(const Xmm& x, const Operand& op) { vpslld(x, x, op); }
+void vpslld(const Xmm& x, uint8 imm) { vpslld(x, x, imm); }
+void vpslldq(const Xmm& x, uint8 imm) { vpslldq(x, x, imm); }
+void vpsllq(const Xmm& x, const Operand& op) { vpsllq(x, x, op); }
+void vpsllq(const Xmm& x, uint8 imm) { vpsllq(x, x, imm); }
+void vpsllw(const Xmm& x, const Operand& op) { vpsllw(x, x, op); }
+void vpsllw(const Xmm& x, uint8 imm) { vpsllw(x, x, imm); }
+void vpsrad(const Xmm& x, const Operand& op) { vpsrad(x, x, op); }
+void vpsrad(const Xmm& x, uint8 imm) { vpsrad(x, x, imm); }
+void vpsraw(const Xmm& x, const Operand& op) { vpsraw(x, x, op); }
+void vpsraw(const Xmm& x, uint8 imm) { vpsraw(x, x, imm); }
+void vpsrld(const Xmm& x, const Operand& op) { vpsrld(x, x, op); }
+void vpsrld(const Xmm& x, uint8 imm) { vpsrld(x, x, imm); }
+void vpsrldq(const Xmm& x, uint8 imm) { vpsrldq(x, x, imm); }
+void vpsrlq(const Xmm& x, const Operand& op) { vpsrlq(x, x, op); }
+void vpsrlq(const Xmm& x, uint8 imm) { vpsrlq(x, x, imm); }
+void vpsrlw(const Xmm& x, const Operand& op) { vpsrlw(x, x, op); }
+void vpsrlw(const Xmm& x, uint8 imm) { vpsrlw(x, x, imm); }
+void vpsubb(const Xmm& x, const Operand& op) { vpsubb(x, x, op); }
+void vpsubd(const Xmm& x, const Operand& op) { vpsubd(x, x, op); }
+void vpsubq(const Xmm& x, const Operand& op) { vpsubq(x, x, op); }
+void vpsubsb(const Xmm& x, const Operand& op) { vpsubsb(x, x, op); }
+void vpsubsw(const Xmm& x, const Operand& op) { vpsubsw(x, x, op); }
+void vpsubusb(const Xmm& x, const Operand& op) { vpsubusb(x, x, op); }
+void vpsubusw(const Xmm& x, const Operand& op) { vpsubusw(x, x, op); }
+void vpsubw(const Xmm& x, const Operand& op) { vpsubw(x, x, op); }
+void vpunpckhbw(const Xmm& x, const Operand& op) { vpunpckhbw(x, x, op); }
+void vpunpckhdq(const Xmm& x, const Operand& op) { vpunpckhdq(x, x, op); }
+void vpunpckhqdq(const Xmm& x, const Operand& op) { vpunpckhqdq(x, x, op); }
+void vpunpckhwd(const Xmm& x, const Operand& op) { vpunpckhwd(x, x, op); }
+void vpunpcklbw(const Xmm& x, const Operand& op) { vpunpcklbw(x, x, op); }
+void vpunpckldq(const Xmm& x, const Operand& op) { vpunpckldq(x, x, op); }
+void vpunpcklqdq(const Xmm& x, const Operand& op) { vpunpcklqdq(x, x, op); }
+void vpunpcklwd(const Xmm& x, const Operand& op) { vpunpcklwd(x, x, op); }
+void vpxor(const Xmm& x, const Operand& op) { vpxor(x, x, op); }
+void vrcpss(const Xmm& x, const Operand& op) { vrcpss(x, x, op); }
+void vroundsd(const Xmm& x, const Operand& op, uint8 imm) { vroundsd(x, x, op, imm); }
+void vroundss(const Xmm& x, const Operand& op, uint8 imm) { vroundss(x, x, op, imm); }
+void vrsqrtss(const Xmm& x, const Operand& op) { vrsqrtss(x, x, op); }
+void vshufpd(const Xmm& x, const Operand& op, uint8 imm) { vshufpd(x, x, op, imm); }
+void vshufps(const Xmm& x, const Operand& op, uint8 imm) { vshufps(x, x, op, imm); }
+void vsqrtsd(const Xmm& x, const Operand& op) { vsqrtsd(x, x, op); }
+void vsqrtss(const Xmm& x, const Operand& op) { vsqrtss(x, x, op); }
+void vunpckhpd(const Xmm& x, const Operand& op) { vunpckhpd(x, x, op); }
+void vunpckhps(const Xmm& x, const Operand& op) { vunpckhps(x, x, op); }
+void vunpcklpd(const Xmm& x, const Operand& op) { vunpcklpd(x, x, op); }
+void vunpcklps(const Xmm& x, const Operand& op) { vunpcklps(x, x, op); }
+#endif
+#ifdef XBYAK64
+void jecxz(std::string label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jecxz(const Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jrcxz(std::string label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jrcxz(const Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void cdqe() { db(0x48); db(0x98); }
+void cqo() { db(0x48); db(0x99); }
+void cmpsq() { db(0x48); db(0xA7); }
+void movsq() { db(0x48); db(0xA5); }
+void scasq() { db(0x48); db(0xAF); }
+void stosq() { db(0x48); db(0xAB); }
+void cmpxchg16b(const Address& addr) { opModM(addr, Reg64(1), 0x0F, 0xC7); }
+void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }
+void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }
+void movsxd(const Reg64& reg, const Operand& op) { if (!op.isBit(32)) throw Error(ERR_BAD_COMBINATION); opModRM(reg, op, op.isREG(), op.isMEM(), 0x63); }
+void pextrq(const Operand& op, const Xmm& xmm, uint8 imm) { if (!op.isREG(64) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(Reg64(xmm.getIdx()), op, 0x16, 0x66, 0, imm, 0x3A); }
+void pinsrq(const Xmm& xmm, const Operand& op, uint8 imm) { if (!op.isREG(64) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(Reg64(xmm.getIdx()), op, 0x22, 0x66, 0, imm, 0x3A); }
+void vcvtss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_ER_X | T_N8, 0x2D); }
+void vcvttss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_SAE_X | T_N8, 0x2C); }
+void vcvtsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_ER_X, 0x2D); }
+void vcvttsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_SAE_X, 0x2C); }
+void vmovq(const Xmm& x, const Reg64& r) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x6E); }
+void vmovq(const Reg64& r, const Xmm& x) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x7E); }
+#else
+void jcxz(std::string label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jcxz(const Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jecxz(std::string label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void jecxz(const Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
+void aaa() { db(0x37); }
+void aad() { db(0xD5); db(0x0A); }
+void aam() { db(0xD4); db(0x0A); }
+void aas() { db(0x3F); }
+void daa() { db(0x27); }
+void das() { db(0x2F); }
+void popad() { db(0x61); }
+void popfd() { db(0x9D); }
+void pusha() { db(0x60); }
+void pushad() { db(0x60); }
+void pushfd() { db(0x9C); }
+void popa() { db(0x61); }
+#endif
+#ifndef XBYAK_NO_OP_NAMES
+void and(const Operand& op1, const Operand& op2) { and_(op1, op2); }
+void and(const Operand& op, uint32 imm) { and_(op, imm); }
+void or(const Operand& op1, const Operand& op2) { or_(op1, op2); }
+void or(const Operand& op, uint32 imm) { or_(op, imm); }
+void xor(const Operand& op1, const Operand& op2) { xor_(op1, op2); }
+void xor(const Operand& op, uint32 imm) { xor_(op, imm); }
+void not(const Operand& op) { not_(op); }
+#endif
+#ifndef XBYAK_DISABLE_AVX512
+void kaddb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x4A); }
+void kaddd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x4A); }
+void kaddq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x4A); }
+void kaddw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x4A); }
+void kandb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x41); }
+void kandd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x41); }
+void kandnb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x42); }
+void kandnd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x42); }
+void kandnq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x42); }
+void kandnw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x42); }
+void kandq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x41); }
+void kandw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x41); }
+void kmovb(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_66 | T_W0, 0x91); }
+void kmovb(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W0, 0x90); }
+void kmovb(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_66 | T_W0, 0x92); }
+void kmovb(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_66 | T_W0, 0x93); }
+void kmovd(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_66 | T_W1, 0x91); }
+void kmovd(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W1, 0x90); }
+void kmovd(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_F2 | T_W0, 0x92); }
+void kmovd(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_F2 | T_W0, 0x93); }
+void kmovq(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W1, 0x91); }
+void kmovq(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_W1, 0x90); }
+void kmovw(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W0, 0x91); }
+void kmovw(const Opmask& k, const Operand& op) { opVex(k, 0, op, T_L0 | T_0F | T_W0, 0x90); }
+void kmovw(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_W0, 0x92); }
+void kmovw(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_W0, 0x93); }
+void knotb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x44); }
+void knotd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x44); }
+void knotq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x44); }
+void knotw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x44); }
+void korb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x45); }
+void kord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x45); }
+void korq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x45); }
+void kortestb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x98); }
+void kortestd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x98); }
+void kortestq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x98); }
+void kortestw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x98); }
+void korw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x45); }
+void kshiftlb(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x32, imm); }
+void kshiftld(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x33, imm); }
+void kshiftlq(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x33, imm); }
+void kshiftlw(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x32, imm); }
+void kshiftrb(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x30, imm); }
+void kshiftrd(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x31, imm); }
+void kshiftrq(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x31, imm); }
+void kshiftrw(const Opmask& r1, const Opmask& r2, uint8 imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x30, imm); }
+void ktestb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x99); }
+void ktestd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x99); }
+void ktestq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x99); }
+void ktestw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x99); }
+void kunpckbw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x4B); }
+void kunpckdq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x4B); }
+void kunpckwd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x4B); }
+void kxnorb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x46); }
+void kxnord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x46); }
+void kxnorq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x46); }
+void kxnorw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x46); }
+void kxorb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x47); }
+void kxord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x47); }
+void kxorq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x47); }
+void kxorw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x47); }
+void v4fmaddps(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x9A); }
+void v4fmaddss(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_F2 | T_EW0 | T_MUST_EVEX | T_N16, 0x9B); }
+void v4fnmaddps(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0xAA); }
+void v4fnmaddss(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_F2 | T_EW0 | T_MUST_EVEX | T_N16, 0xAB); }
+void valignd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x03, imm); }
+void valignq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x03, imm); }
+void vblendmpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x65); }
+void vblendmps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x65); }
+void vbroadcastf32x2(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N8, 0x19); }
+void vbroadcastf32x4(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N16, 0x1A); }
+void vbroadcastf32x8(const Zmm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N32, 0x1B); }
+void vbroadcastf64x2(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N16, 0x1A); }
+void vbroadcastf64x4(const Zmm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N32, 0x1B); }
+void vbroadcasti32x2(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N8, 0x59); }
+void vbroadcasti32x4(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N16, 0x5A); }
+void vbroadcasti32x8(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N32, 0x5B); }
+void vbroadcasti64x2(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N16, 0x5A); }
+void vbroadcasti64x4(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N32, 0x5B); }
+void vcmppd(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); }
+void vcmpps(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_0F | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); }
+void vcmpsd(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_N8 | T_F2 | T_0F | T_EW1 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); }
+void vcmpss(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_N4 | T_F3 | T_0F | T_EW0 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); }
+void vcompressb(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x63); }
+void vcompresspd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8A); }
+void vcompressps(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8A); }
+void vcompressw(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x63); }
+void vcvtpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7B); }
+void vcvtpd2udq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x79); }
+void vcvtpd2uqq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x79); }
+void vcvtps2qq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_ER_Y, 0x7B); }
+void vcvtps2udq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_0F | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x79); }
+void vcvtps2uqq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_ER_Y, 0x79); }
+void vcvtqq2pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0xE6); }
+void vcvtqq2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x5B); }
+void vcvtsd2usi(const Reg32e& r, const Operand& op) { int type = (T_F2 | T_0F | T_MUST_EVEX | T_N8 | T_ER_X) | (r.isREG(64) ? T_EW1 : T_EW0); opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, type, 0x79); }
+void vcvtss2usi(const Reg32e& r, const Operand& op) { int type = (T_F3 | T_0F | T_MUST_EVEX | T_N4 | T_ER_X) | (r.isREG(64) ? T_EW1 : T_EW0); opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, type, 0x79); }
+void vcvttpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x7A); }
+void vcvttpd2udq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_SAE_Z, 0x78); }
+void vcvttpd2uqq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x78); }
+void vcvttps2qq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_SAE_Y, 0x7A); }
+void vcvttps2udq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_0F | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x78); }
+void vcvttps2uqq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_SAE_Y, 0x78); }
+void vcvttsd2usi(const Reg32e& r, const Operand& op) { int type = (T_F2 | T_0F | T_MUST_EVEX | T_N8 | T_SAE_X) | (r.isREG(64) ? T_EW1 : T_EW0); opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, type, 0x78); }
+void vcvttss2usi(const Reg32e& r, const Operand& op) { int type = (T_F3 | T_0F | T_MUST_EVEX | T_N4 | T_SAE_X) | (r.isREG(64) ? T_EW1 : T_EW0); opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, type, 0x78); }
+void vcvtudq2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_F3 | T_0F | T_YMM | T_MUST_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL, 0x7A); }
+void vcvtudq2ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x7A); }
+void vcvtuqq2pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7A); }
+void vcvtuqq2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_F2 | T_0F | T_YMM | T_MUST_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x7A); }
+void vcvtusi2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_F2 | T_0F | T_MUST_EVEX, T_W1 | T_EW1 | T_ER_X | T_N8, T_W0 | T_EW0 | T_N4, 0x7B); }
+void vcvtusi2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_F3 | T_0F | T_MUST_EVEX | T_ER_X, T_W1 | T_EW1 | T_N8, T_W0 | T_EW0 | T_N4, 0x7B); }
+void vdbpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x42, imm); }
+void vexp2pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xC8); }
+void vexp2ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xC8); }
+void vexpandpd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x88); }
+void vexpandps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x88); }
+void vextractf32x4(const Operand& op, const Ymm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::XMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x19, imm); }
+void vextractf32x8(const Operand& op, const Zmm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x1B, imm); }
+void vextractf64x2(const Operand& op, const Ymm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::XMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x19, imm); }
+void vextractf64x4(const Operand& op, const Zmm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x1B, imm); }
+void vextracti32x4(const Operand& op, const Ymm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::XMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x39, imm); }
+void vextracti32x8(const Operand& op, const Zmm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3B, imm); }
+void vextracti64x2(const Operand& op, const Ymm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::XMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x39, imm); }
+void vextracti64x4(const Operand& op, const Zmm& r, uint8 imm) { if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3B, imm); }
+void vfixupimmpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x54, imm); }
+void vfixupimmps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x54, imm); }
+void vfixupimmsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_Z | T_MUST_EVEX, 0x55, imm); }
+void vfixupimmss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_Z | T_MUST_EVEX, 0x55, imm); }
+void vfpclasspd(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isBit(128|256|512)) throw Error(ERR_BAD_MEM_SIZE); Reg x = k; x.setBit(op.getBit()); opVex(x, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW1 | T_B64, 0x66, imm); }
+void vfpclassps(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isBit(128|256|512)) throw Error(ERR_BAD_MEM_SIZE); Reg x = k; x.setBit(op.getBit()); opVex(x, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW0 | T_B32, 0x66, imm); }
+void vfpclasssd(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isXMEM()) throw Error(ERR_BAD_MEM_SIZE); opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW1 | T_N8, 0x67, imm); }
+void vfpclassss(const Opmask& k, const Operand& op, uint8 imm) { if (!op.isXMEM()) throw Error(ERR_BAD_MEM_SIZE); opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW0 | T_N4, 0x67, imm); }
+void vgatherdpd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x92, 1); }
+void vgatherdps(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x92, 0); }
+void vgatherpf0dpd(const Address& addr) { opGatherFetch(addr, zm1, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); }
+void vgatherpf0dps(const Address& addr) { opGatherFetch(addr, zm1, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); }
+void vgatherpf0qpd(const Address& addr) { opGatherFetch(addr, zm1, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vgatherpf0qps(const Address& addr) { opGatherFetch(addr, zm1, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vgatherpf1dpd(const Address& addr) { opGatherFetch(addr, zm2, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); }
+void vgatherpf1dps(const Address& addr) { opGatherFetch(addr, zm2, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); }
+void vgatherpf1qpd(const Address& addr) { opGatherFetch(addr, zm2, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vgatherpf1qps(const Address& addr) { opGatherFetch(addr, zm2, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vgatherqpd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x93, 0); }
+void vgatherqps(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x93, 2); }
+void vgetexppd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x42); }
+void vgetexpps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x42); }
+void vgetexpsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x43); }
+void vgetexpss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x43); }
+void vgetmantpd(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x26, imm); }
+void vgetmantps(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x26, imm); }
+void vgetmantsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x27, imm); }
+void vgetmantss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x27, imm); }
+void vinsertf32x4(const Ymm& r1, const Ymm& r2, const Operand& op, uint8 imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x18, imm); }
+void vinsertf32x8(const Zmm& r1, const Zmm& r2, const Operand& op, uint8 imm) {if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x1A, imm); }
+void vinsertf64x2(const Ymm& r1, const Ymm& r2, const Operand& op, uint8 imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x18, imm); }
+void vinsertf64x4(const Zmm& r1, const Zmm& r2, const Operand& op, uint8 imm) {if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x1A, imm); }
+void vinserti32x4(const Ymm& r1, const Ymm& r2, const Operand& op, uint8 imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x38, imm); }
+void vinserti32x8(const Zmm& r1, const Zmm& r2, const Operand& op, uint8 imm) {if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3A, imm); }
+void vinserti64x2(const Ymm& r1, const Ymm& r2, const Operand& op, uint8 imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x38, imm); }
+void vinserti64x4(const Zmm& r1, const Zmm& r2, const Operand& op, uint8 imm) {if (!op.is(Operand::MEM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3A, imm); }
+void vmovdqa32(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_66 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqa32(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovdqa64(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_66 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqa64(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovdqu16(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F2 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqu16(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovdqu32(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F3 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqu32(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovdqu64(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqu64(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vmovdqu8(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); }
+void vmovdqu8(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); }
+void vp4dpwssd(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x52); }
+void vp4dpwssds(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x53); }
+void vpabsq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_MUST_EVEX | T_EW1 | T_B64 | T_YMM, 0x1F); }
+void vpandd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xDB); }
+void vpandnd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xDF); }
+void vpandnq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xDF); }
+void vpandq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xDB); }
+void vpblendmb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x66); }
+void vpblendmd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x64); }
+void vpblendmq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x64); }
+void vpblendmw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x66); }
+void vpbroadcastb(const Xmm& x, const Reg8& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7A); }
+void vpbroadcastd(const Xmm& x, const Reg32& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7C); }
+void vpbroadcastmb2q(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1, 0x2A); }
+void vpbroadcastmw2d(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0, 0x3A); }
+void vpbroadcastw(const Xmm& x, const Reg16& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7B); }
+void vpcmpb(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3F, imm); }
+void vpcmpd(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x1F, imm); }
+void vpcmpeqb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x74); }
+void vpcmpeqd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_B32, 0x76); }
+void vpcmpeqq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x29); }
+void vpcmpeqw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x75); }
+void vpcmpgtb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x64); }
+void vpcmpgtd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x66); }
+void vpcmpgtq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x37); }
+void vpcmpgtw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x65); }
+void vpcmpq(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x1F, imm); }
+void vpcmpub(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3E, imm); }
+void vpcmpud(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x1E, imm); }
+void vpcmpuq(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x1E, imm); }
+void vpcmpuw(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3E, imm); }
+void vpcmpw(const Opmask& k, const Xmm& x, const Operand& op, uint8 imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3F, imm); }
+void vpcompressd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8B); }
+void vpcompressq(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8B); }
+void vpconflictd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xC4); }
+void vpconflictq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xC4); }
+void vpdpbusd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x50); }
+void vpdpbusds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x51); }
+void vpdpwssd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x52); }
+void vpdpwssds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x53); }
+void vpermb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8D); }
+void vpermi2b(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x75); }
+void vpermi2d(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x76); }
+void vpermi2pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x77); }
+void vpermi2ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x77); }
+void vpermi2q(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x76); }
+void vpermi2w(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x75); }
+void vpermt2b(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7D); }
+void vpermt2d(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x7E); }
+void vpermt2pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x7F); }
+void vpermt2ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x7F); }
+void vpermt2q(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x7E); }
+void vpermt2w(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x7D); }
+void vpermw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8D); }
+void vpexpandb(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x62); }
+void vpexpandd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x89); }
+void vpexpandq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x89); }
+void vpexpandw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x62); }
+void vpgatherdd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x90, 0); }
+void vpgatherdq(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x90, 1); }
+void vpgatherqd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x91, 2); }
+void vpgatherqq(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x91, 0); }
+void vplzcntd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x44); }
+void vplzcntq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x44); }
+void vpmadd52huq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xB5); }
+void vpmadd52luq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xB4); }
+void vpmaxsq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3D); }
+void vpmaxuq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3F); }
+void vpminsq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x39); }
+void vpminuq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3B); }
+void vpmovb2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x29); }
+void vpmovd2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x39); }
+void vpmovdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x31, false); }
+void vpmovdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x33, true); }
+void vpmovm2b(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x28); }
+void vpmovm2d(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x38); }
+void vpmovm2q(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x38); }
+void vpmovm2w(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x28); }
+void vpmovq2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x39); }
+void vpmovqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x32, false); }
+void vpmovqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x35, true); }
+void vpmovqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x34, false); }
+void vpmovsdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x21, false); }
+void vpmovsdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x23, true); }
+void vpmovsqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x22, false); }
+void vpmovsqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x25, true); }
+void vpmovsqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x24, false); }
+void vpmovswb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x20, true); }
+void vpmovusdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x11, false); }
+void vpmovusdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x13, true); }
+void vpmovusqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x12, false); }
+void vpmovusqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x15, true); }
+void vpmovusqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x14, false); }
+void vpmovuswb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x10, true); }
+void vpmovw2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x29); }
+void vpmovwb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x30, true); }
+void vpmullq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x40); }
+void vpmultishiftqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x83); }
+void vpopcntb(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x54); }
+void vpopcntd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x55); }
+void vpopcntq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x55); }
+void vpopcntw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x54); }
+void vpord(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xEB); }
+void vporq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xEB); }
+void vprold(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 1), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x72, imm); }
+void vprolq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 1), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); }
+void vprolvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x15); }
+void vprolvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x15); }
+void vprord(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 0), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x72, imm); }
+void vprorq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 0), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); }
+void vprorvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x14); }
+void vprorvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x14); }
+void vpscatterdd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA0, 0); }
+void vpscatterdq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA0, 1); }
+void vpscatterqd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA1, 2); }
+void vpscatterqq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA1, 0); }
+void vpshldd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x71, imm); }
+void vpshldq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x71, imm); }
+void vpshldvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x71); }
+void vpshldvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x71); }
+void vpshldvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x70); }
+void vpshldw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x70, imm); }
+void vpshrdd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x73, imm); }
+void vpshrdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x73, imm); }
+void vpshrdvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x73); }
+void vpshrdvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x73); }
+void vpshrdvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x72); }
+void vpshrdw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x72, imm); }
+void vpshufbitqmb(const Opmask& k, const Xmm& x, const Operand& op) { opVex(k, &x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8F); }
+void vpsllvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x12); }
+void vpsraq(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); }
+void vpsraq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX, 0xE2); }
+void vpsravq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x46); }
+void vpsravw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x11); }
+void vpsrlvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x10); }
+void vpternlogd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x25, imm); }
+void vpternlogq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x25, imm); }
+void vptestmb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x26); }
+void vptestmd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x27); }
+void vptestmq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x27); }
+void vptestmw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x26); }
+void vptestnmb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x26); }
+void vptestnmd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x27); }
+void vptestnmq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x27); }
+void vptestnmw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x26); }
+void vpxord(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xEF); }
+void vpxorq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xEF); }
+void vrangepd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x50, imm); }
+void vrangeps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x50, imm); }
+void vrangesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x51, imm); }
+void vrangess(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x51, imm); }
+void vrcp14pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x4C); }
+void vrcp14ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x4C); }
+void vrcp14sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX, 0x4D); }
+void vrcp14ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX, 0x4D); }
+void vrcp28pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xCA); }
+void vrcp28ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xCA); }
+void vrcp28sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0xCB); }
+void vrcp28ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0xCB); }
+void vreducepd(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x56, imm); }
+void vreduceps(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x56, imm); }
+void vreducesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x57, imm); }
+void vreducess(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x57, imm); }
+void vrndscalepd(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x09, imm); }
+void vrndscaleps(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x08, imm); }
+void vrndscalesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_MUST_EVEX, 0x0B, imm); }
+void vrndscaless(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_MUST_EVEX, 0x0A, imm); }
+void vrsqrt14pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x4E); }
+void vrsqrt14ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x4E); }
+void vrsqrt14sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x4F); }
+void vrsqrt14ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x4F); }
+void vrsqrt28pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xCC); }
+void vrsqrt28ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xCC); }
+void vrsqrt28sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0xCD); }
+void vrsqrt28ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0xCD); }
+void vscalefpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x2C); }
+void vscalefps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x2C); }
+void vscalefsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_ER_X | T_MUST_EVEX, 0x2D); }
+void vscalefss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x2D); }
+void vscatterdpd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA2, 1); }
+void vscatterdps(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA2, 0); }
+void vscatterpf0dpd(const Address& addr) { opGatherFetch(addr, zm5, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); }
+void vscatterpf0dps(const Address& addr) { opGatherFetch(addr, zm5, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); }
+void vscatterpf0qpd(const Address& addr) { opGatherFetch(addr, zm5, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vscatterpf0qps(const Address& addr) { opGatherFetch(addr, zm5, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vscatterpf1dpd(const Address& addr) { opGatherFetch(addr, zm6, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); }
+void vscatterpf1dps(const Address& addr) { opGatherFetch(addr, zm6, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); }
+void vscatterpf1qpd(const Address& addr) { opGatherFetch(addr, zm6, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vscatterpf1qps(const Address& addr) { opGatherFetch(addr, zm6, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); }
+void vscatterqpd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA3, 0); }
+void vscatterqps(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA3, 2); }
+void vshuff32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x23, imm); }
+void vshuff64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x23, imm); }
+void vshufi32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x43, imm); }
+void vshufi64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x43, imm); }
+#ifdef XBYAK64
+void kmovq(const Opmask& k, const Reg64& r) { opVex(k, 0, r, T_L0 | T_0F | T_F2 | T_W1, 0x92); }
+void kmovq(const Reg64& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_F2 | T_W1, 0x93); }
+void vpbroadcastq(const Xmm& x, const Reg64& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x7C); }
+#endif
+#endif
diff --git a/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_util.h b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_util.h
new file mode 100644
index 0000000000..8ef076e680
--- /dev/null
+++ b/thirdparty/oidn/mkl-dnn/src/cpu/xbyak/xbyak_util.h
@@ -0,0 +1,772 @@
+/*******************************************************************************
+* Copyright 2016-2019 Intel Corporation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+/*******************************************************************************
+* Copyright (c) 2007 MITSUNARI Shigeo
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+* Neither the name of the copyright owner nor the names of its contributors may
+* be used to endorse or promote products derived from this software without
+* specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef XBYAK_XBYAK_UTIL_H_
+#define XBYAK_XBYAK_UTIL_H_
+
+/**
+ utility class and functions for Xbyak
+ Xbyak::util::Clock ; rdtsc timer
+ Xbyak::util::Cpu ; detect CPU
+ @note this header is UNDER CONSTRUCTION!
+*/
+#include "xbyak.h"
+
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+ #define XBYAK_INTEL_CPU_SPECIFIC
+#endif
+
+#ifdef XBYAK_INTEL_CPU_SPECIFIC
+#ifdef _MSC_VER
+ #if (_MSC_VER < 1400) && defined(XBYAK32)
+ static inline __declspec(naked) void __cpuid(int[4], int)
+ {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+ }
+ #else
+ #include <intrin.h> // for __cpuid
+ #endif
+#else
+ #ifndef __GNUC_PREREQ
+ #define __GNUC_PREREQ(major, minor) ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+ #endif
+ #if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+ #include <cpuid.h>
+ #else
+ #if defined(__APPLE__) && defined(XBYAK32) // avoid err : can't find a register in class `BREG' while reloading `asm'
+ #define __cpuid(eaxIn, a, b, c, d) __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" : "=a"(a), "=S"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+ #define __cpuid_count(eaxIn, ecxIn, a, b, c, d) __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" : "=a"(a), "=S"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+ #else
+ #define __cpuid(eaxIn, a, b, c, d) __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+ #define __cpuid_count(eaxIn, ecxIn, a, b, c, d) __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+ #endif
+ #endif
+#endif
+#endif
+
+namespace Xbyak { namespace util {
+
+typedef enum {
+ SmtLevel = 1,
+ CoreLevel = 2
+} IntelCpuTopologyLevel;
+
+/**
+ CPU detection class
+*/
+class Cpu {
+ uint64 type_;
+ //system topology
+ bool x2APIC_supported_;
+ static const size_t maxTopologyLevels = 2;
+ unsigned int numCores_[maxTopologyLevels];
+
+ static const unsigned int maxNumberCacheLevels = 10;
+ unsigned int dataCacheSize_[maxNumberCacheLevels];
+ unsigned int coresSharignDataCache_[maxNumberCacheLevels];
+ unsigned int dataCacheLevels_;
+
+ unsigned int get32bitAsBE(const char *x) const
+ {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+ }
+ unsigned int mask(int n) const
+ {
+ return (1U << n) - 1;
+ }
+ void setFamily()
+ {
+ unsigned int data[4] = {};
+ getCpuid(1, data);
+ stepping = data[0] & mask(4);
+ model = (data[0] >> 4) & mask(4);
+ family = (data[0] >> 8) & mask(4);
+ // type = (data[0] >> 12) & mask(2);
+ extModel = (data[0] >> 16) & mask(4);
+ extFamily = (data[0] >> 20) & mask(8);
+ if (family == 0x0f) {
+ displayFamily = family + extFamily;
+ } else {
+ displayFamily = family;
+ }
+ if (family == 6 || family == 0x0f) {
+ displayModel = (extModel << 4) + model;
+ } else {
+ displayModel = model;
+ }
+ }
+ unsigned int extractBit(unsigned int val, unsigned int base, unsigned int end)
+ {
+ return (val >> base) & ((1u << (end - base)) - 1);
+ }
+ void setNumCores()
+ {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ getCpuidEx(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2APIC_supported_ = true;
+ for (unsigned int i = 0; i < maxTopologyLevels; i++) {
+ getCpuidEx(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extractBit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ numCores_[level - 1] = extractBit(data[1], 0, 15);
+ }
+ }
+ } else {
+ /*
+ Failed to deremine num of cores without x2APIC support.
+ TODO: USE initial APIC ID to determine ncores.
+ */
+ numCores_[SmtLevel - 1] = 0;
+ numCores_[CoreLevel - 1] = 0;
+ }
+
+ }
+ void setCacheHierarchy()
+ {
+ if ((type_ & tINTEL) == 0) return;
+ const unsigned int NO_CACHE = 0;
+ const unsigned int DATA_CACHE = 1;
+// const unsigned int INSTRUCTION_CACHE = 2;
+ const unsigned int UNIFIED_CACHE = 3;
+ unsigned int smt_width = 0;
+ unsigned int logical_cores = 0;
+ unsigned int data[4] = {};
+
+ if (x2APIC_supported_) {
+ smt_width = numCores_[0];
+ logical_cores = numCores_[1];
+ }
+
+ /*
+ Assumptions:
+ the first level of data cache is not shared (which is the
+ case for every existing architecture) and use this to
+ determine the SMT width for arch not supporting leaf 11.
+ when leaf 4 reports a number of core less than numCores_
+ on socket reported by leaf 11, then it is a correct number
+ of cores not an upperbound.
+ */
+ for (int i = 0; dataCacheLevels_ < maxNumberCacheLevels; i++) {
+ getCpuidEx(0x4, i, data);
+ unsigned int cacheType = extractBit(data[0], 0, 4);
+ if (cacheType == NO_CACHE) break;
+ if (cacheType == DATA_CACHE || cacheType == UNIFIED_CACHE) {
+ unsigned int actual_logical_cores = extractBit(data[0], 14, 25) + 1;
+ if (logical_cores != 0) { // true only if leaf 0xB is supported and valid
+ actual_logical_cores = (std::min)(actual_logical_cores, logical_cores);
+ }
+ assert(actual_logical_cores != 0);
+ dataCacheSize_[dataCacheLevels_] =
+ (extractBit(data[1], 22, 31) + 1)
+ * (extractBit(data[1], 12, 21) + 1)
+ * (extractBit(data[1], 0, 11) + 1)
+ * (data[2] + 1);
+ if (cacheType == DATA_CACHE && smt_width == 0) smt_width = actual_logical_cores;
+ assert(smt_width != 0);
+ // FIXME: check and fix number of cores sharing L3 cache for different configurations
+ // (HT-, 2 sockets), (HT-, 1 socket), (HT+, 2 sockets), (HT+, 1 socket)
+ coresSharignDataCache_[dataCacheLevels_] = (std::max)(actual_logical_cores / smt_width, 1u);
+ dataCacheLevels_++;
+ }
+ }
+ }
+
+public:
+ int model;
+ int family;
+ int stepping;
+ int extModel;
+ int extFamily;
+ int displayFamily; // family + extFamily
+ int displayModel; // model + extModel
+
+ unsigned int getNumCores(IntelCpuTopologyLevel level) {
+ if (level != SmtLevel && level != CoreLevel) throw Error(ERR_BAD_PARAMETER);
+ if (!x2APIC_supported_) throw Error(ERR_X2APIC_IS_NOT_SUPPORTED);
+ return (level == CoreLevel)
+ ? numCores_[level - 1] / numCores_[SmtLevel - 1]
+ : numCores_[level - 1];
+ }
+
+ unsigned int getDataCacheLevels() const { return dataCacheLevels_; }
+ unsigned int getCoresSharingDataCache(unsigned int i) const
+ {
+ if (i >= dataCacheLevels_) throw Error(ERR_BAD_PARAMETER);
+ return coresSharignDataCache_[i];
+ }
+ unsigned int getDataCacheSize(unsigned int i) const
+ {
+ if (i >= dataCacheLevels_) throw Error(ERR_BAD_PARAMETER);
+ return dataCacheSize_[i];
+ }
+
+ /*
+ data[] = { eax, ebx, ecx, edx }
+ */
+ static inline void getCpuid(unsigned int eaxIn, unsigned int data[4])
+ {
+#ifdef XBYAK_INTEL_CPU_SPECIFIC
+ #ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+ #else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+ #endif
+#else
+ (void)eaxIn;
+ (void)data;
+#endif
+ }
+ static inline void getCpuidEx(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4])
+ {
+#ifdef XBYAK_INTEL_CPU_SPECIFIC
+ #ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+ #else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+ #endif
+#else
+ (void)eaxIn;
+ (void)ecxIn;
+ (void)data;
+#endif
+ }
+ static inline uint64 getXfeature()
+ {
+#ifdef XBYAK_INTEL_CPU_SPECIFIC
+ #ifdef _MSC_VER
+ return _xgetbv(0);
+ #else
+ unsigned int eax, edx;
+ // xgetvb is not support on gcc 4.2
+// __asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));
+ __asm__ volatile(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0));
+ return ((uint64)edx << 32) | eax;
+ #endif
+#else
+ return 0;
+#endif
+ }
+ typedef uint64 Type;
+
+ static const Type NONE = 0;
+ static const Type tMMX = 1 << 0;
+ static const Type tMMX2 = 1 << 1;
+ static const Type tCMOV = 1 << 2;
+ static const Type tSSE = 1 << 3;
+ static const Type tSSE2 = 1 << 4;
+ static const Type tSSE3 = 1 << 5;
+ static const Type tSSSE3 = 1 << 6;
+ static const Type tSSE41 = 1 << 7;
+ static const Type tSSE42 = 1 << 8;
+ static const Type tPOPCNT = 1 << 9;
+ static const Type tAESNI = 1 << 10;
+ static const Type tSSE5 = 1 << 11;
+ static const Type tOSXSAVE = 1 << 12;
+ static const Type tPCLMULQDQ = 1 << 13;
+ static const Type tAVX = 1 << 14;
+ static const Type tFMA = 1 << 15;
+
+ static const Type t3DN = 1 << 16;
+ static const Type tE3DN = 1 << 17;
+ static const Type tSSE4a = 1 << 18;
+ static const Type tRDTSCP = 1 << 19;
+ static const Type tAVX2 = 1 << 20;
+ static const Type tBMI1 = 1 << 21; // andn, bextr, blsi, blsmsk, blsr, tzcnt
+ static const Type tBMI2 = 1 << 22; // bzhi, mulx, pdep, pext, rorx, sarx, shlx, shrx
+ static const Type tLZCNT = 1 << 23;
+
+ static const Type tINTEL = 1 << 24;
+ static const Type tAMD = 1 << 25;
+
+ static const Type tENHANCED_REP = 1 << 26; // enhanced rep movsb/stosb
+ static const Type tRDRAND = 1 << 27;
+ static const Type tADX = 1 << 28; // adcx, adox
+ static const Type tRDSEED = 1 << 29; // rdseed
+ static const Type tSMAP = 1 << 30; // stac
+ static const Type tHLE = uint64(1) << 31; // xacquire, xrelease, xtest
+ static const Type tRTM = uint64(1) << 32; // xbegin, xend, xabort
+ static const Type tF16C = uint64(1) << 33; // vcvtph2ps, vcvtps2ph
+ static const Type tMOVBE = uint64(1) << 34; // mobve
+ static const Type tAVX512F = uint64(1) << 35;
+ static const Type tAVX512DQ = uint64(1) << 36;
+ static const Type tAVX512_IFMA = uint64(1) << 37;
+ static const Type tAVX512IFMA = tAVX512_IFMA;
+ static const Type tAVX512PF = uint64(1) << 38;
+ static const Type tAVX512ER = uint64(1) << 39;
+ static const Type tAVX512CD = uint64(1) << 40;
+ static const Type tAVX512BW = uint64(1) << 41;
+ static const Type tAVX512VL = uint64(1) << 42;
+ static const Type tAVX512_VBMI = uint64(1) << 43;
+ static const Type tAVX512VBMI = tAVX512_VBMI; // changed by Intel's manual
+ static const Type tAVX512_4VNNIW = uint64(1) << 44;
+ static const Type tAVX512_4FMAPS = uint64(1) << 45;
+ static const Type tPREFETCHWT1 = uint64(1) << 46;
+ static const Type tPREFETCHW = uint64(1) << 47;
+ static const Type tSHA = uint64(1) << 48;
+ static const Type tMPX = uint64(1) << 49;
+ static const Type tAVX512_VBMI2 = uint64(1) << 50;
+ static const Type tGFNI = uint64(1) << 51;
+ static const Type tVAES = uint64(1) << 52;
+ static const Type tVPCLMULQDQ = uint64(1) << 53;
+ static const Type tAVX512_VNNI = uint64(1) << 54;
+ static const Type tAVX512_BITALG = uint64(1) << 55;
+ static const Type tAVX512_VPOPCNTDQ = uint64(1) << 56;
+
+ Cpu()
+ : type_(NONE)
+ , x2APIC_supported_(false)
+ , numCores_()
+ , dataCacheSize_()
+ , coresSharignDataCache_()
+ , dataCacheLevels_(0)
+ {
+ unsigned int data[4] = {};
+ const unsigned int& EAX = data[0];
+ const unsigned int& EBX = data[1];
+ const unsigned int& ECX = data[2];
+ const unsigned int& EDX = data[3];
+ getCpuid(0, data);
+ const unsigned int maxNum = EAX;
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bitAsBE(amd)) {
+ type_ |= tAMD;
+ getCpuid(0x80000001, data);
+ if (EDX & (1U << 31)) type_ |= t3DN;
+ if (EDX & (1U << 15)) type_ |= tCMOV;
+ if (EDX & (1U << 30)) type_ |= tE3DN;
+ if (EDX & (1U << 22)) type_ |= tMMX2;
+ if (EDX & (1U << 27)) type_ |= tRDTSCP;
+ }
+ if (ECX == get32bitAsBE(intel)) {
+ type_ |= tINTEL;
+ getCpuid(0x80000001, data);
+ if (EDX & (1U << 27)) type_ |= tRDTSCP;
+ if (ECX & (1U << 5)) type_ |= tLZCNT;
+ if (ECX & (1U << 8)) type_ |= tPREFETCHW;
+ }
+ getCpuid(1, data);
+ if (ECX & (1U << 0)) type_ |= tSSE3;
+ if (ECX & (1U << 9)) type_ |= tSSSE3;
+ if (ECX & (1U << 19)) type_ |= tSSE41;
+ if (ECX & (1U << 20)) type_ |= tSSE42;
+ if (ECX & (1U << 22)) type_ |= tMOVBE;
+ if (ECX & (1U << 23)) type_ |= tPOPCNT;
+ if (ECX & (1U << 25)) type_ |= tAESNI;
+ if (ECX & (1U << 1)) type_ |= tPCLMULQDQ;
+ if (ECX & (1U << 27)) type_ |= tOSXSAVE;
+ if (ECX & (1U << 30)) type_ |= tRDRAND;
+ if (ECX & (1U << 29)) type_ |= tF16C;
+
+ if (EDX & (1U << 15)) type_ |= tCMOV;
+ if (EDX & (1U << 23)) type_ |= tMMX;
+ if (EDX & (1U << 25)) type_ |= tMMX2 | tSSE;
+ if (EDX & (1U << 26)) type_ |= tSSE2;
+
+ if (type_ & tOSXSAVE) {
+ // check XFEATURE_ENABLED_MASK[2:1] = '11b'
+ uint64 bv = getXfeature();
+ if ((bv & 6) == 6) {
+ if (ECX & (1U << 28)) type_ |= tAVX;
+ if (ECX & (1U << 12)) type_ |= tFMA;
+ if (((bv >> 5) & 7) == 7) {
+ getCpuidEx(7, 0, data);
+ if (EBX & (1U << 16)) type_ |= tAVX512F;
+ if (type_ & tAVX512F) {
+ if (EBX & (1U << 17)) type_ |= tAVX512DQ;
+ if (EBX & (1U << 21)) type_ |= tAVX512_IFMA;
+ if (EBX & (1U << 26)) type_ |= tAVX512PF;
+ if (EBX & (1U << 27)) type_ |= tAVX512ER;
+ if (EBX & (1U << 28)) type_ |= tAVX512CD;
+ if (EBX & (1U << 30)) type_ |= tAVX512BW;
+ if (EBX & (1U << 31)) type_ |= tAVX512VL;
+ if (ECX & (1U << 1)) type_ |= tAVX512_VBMI;
+ if (ECX & (1U << 6)) type_ |= tAVX512_VBMI2;
+ if (ECX & (1U << 8)) type_ |= tGFNI;
+ if (ECX & (1U << 9)) type_ |= tVAES;
+ if (ECX & (1U << 10)) type_ |= tVPCLMULQDQ;
+ if (ECX & (1U << 11)) type_ |= tAVX512_VNNI;
+ if (ECX & (1U << 12)) type_ |= tAVX512_BITALG;
+ if (ECX & (1U << 14)) type_ |= tAVX512_VPOPCNTDQ;
+ if (EDX & (1U << 2)) type_ |= tAVX512_4VNNIW;
+ if (EDX & (1U << 3)) type_ |= tAVX512_4FMAPS;
+ }
+ }
+ }
+ }
+ if (maxNum >= 7) {
+ getCpuidEx(7, 0, data);
+ if (type_ & tAVX && (EBX & (1U << 5))) type_ |= tAVX2;
+ if (EBX & (1U << 3)) type_ |= tBMI1;
+ if (EBX & (1U << 8)) type_ |= tBMI2;
+ if (EBX & (1U << 9)) type_ |= tENHANCED_REP;
+ if (EBX & (1U << 18)) type_ |= tRDSEED;
+ if (EBX & (1U << 19)) type_ |= tADX;
+ if (EBX & (1U << 20)) type_ |= tSMAP;
+ if (EBX & (1U << 4)) type_ |= tHLE;
+ if (EBX & (1U << 11)) type_ |= tRTM;
+ if (EBX & (1U << 14)) type_ |= tMPX;
+ if (EBX & (1U << 29)) type_ |= tSHA;
+ if (ECX & (1U << 0)) type_ |= tPREFETCHWT1;
+ }
+ setFamily();
+ setNumCores();
+ setCacheHierarchy();
+ }
+ void putFamily() const
+ {
+ printf("family=%d, model=%X, stepping=%d, extFamily=%d, extModel=%X\n",
+ family, model, stepping, extFamily, extModel);
+ printf("display:family=%X, model=%X\n", displayFamily, displayModel);
+ }
+ bool has(Type type) const
+ {
+ return (type & type_) != 0;
+ }
+};
+
+class Clock {
+public:
+ static inline uint64 getRdtsc()
+ {
+#ifdef XBYAK_INTEL_CPU_SPECIFIC
+ #ifdef _MSC_VER
+ return __rdtsc();
+ #else
+ unsigned int eax, edx;
+ __asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx));
+ return ((uint64)edx << 32) | eax;
+ #endif
+#else
+ // TODO: Need another impl of Clock or rdtsc-equivalent for non-x86 cpu
+ return 0;
+#endif
+ }
+ Clock()
+ : clock_(0)
+ , count_(0)
+ {
+ }
+ void begin()
+ {
+ clock_ -= getRdtsc();
+ }
+ void end()
+ {
+ clock_ += getRdtsc();
+ count_++;
+ }
+ int getCount() const { return count_; }
+ uint64 getClock() const { return clock_; }
+ void clear() { count_ = 0; clock_ = 0; }
+private:
+ uint64 clock_;
+ int count_;
+};
+
+#ifdef XBYAK64
+const int UseRCX = 1 << 6;
+const int UseRDX = 1 << 7;
+
+class Pack {
+ static const size_t maxTblNum = 15;
+ const Xbyak::Reg64 *tbl_[maxTblNum];
+ size_t n_;
+public:
+ Pack() : tbl_(), n_(0) {}
+ Pack(const Xbyak::Reg64 *tbl, size_t n) { init(tbl, n); }
+ Pack(const Pack& rhs)
+ : n_(rhs.n_)
+ {
+ for (size_t i = 0; i < n_; i++) tbl_[i] = rhs.tbl_[i];
+ }
+ Pack& operator=(const Pack& rhs)
+ {
+ n_ = rhs.n_;
+ for (size_t i = 0; i < n_; i++) tbl_[i] = rhs.tbl_[i];
+ return *this;
+ }
+ Pack(const Xbyak::Reg64& t0)
+ { n_ = 1; tbl_[0] = &t0; }
+ Pack(const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 2; tbl_[0] = &t0; tbl_[1] = &t1; }
+ Pack(const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 3; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; }
+ Pack(const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 4; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; }
+ Pack(const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 5; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; }
+ Pack(const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 6; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; }
+ Pack(const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 7; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; tbl_[6] = &t6; }
+ Pack(const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 8; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; tbl_[6] = &t6; tbl_[7] = &t7; }
+ Pack(const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 9; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; tbl_[6] = &t6; tbl_[7] = &t7; tbl_[8] = &t8; }
+ Pack(const Xbyak::Reg64& t9, const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0)
+ { n_ = 10; tbl_[0] = &t0; tbl_[1] = &t1; tbl_[2] = &t2; tbl_[3] = &t3; tbl_[4] = &t4; tbl_[5] = &t5; tbl_[6] = &t6; tbl_[7] = &t7; tbl_[8] = &t8; tbl_[9] = &t9; }
+ Pack& append(const Xbyak::Reg64& t)
+ {
+ if (n_ == maxTblNum) {
+ fprintf(stderr, "ERR Pack::can't append\n");
+ throw Error(ERR_BAD_PARAMETER);
+ }
+ tbl_[n_++] = &t;
+ return *this;
+ }
+ void init(const Xbyak::Reg64 *tbl, size_t n)
+ {
+ if (n > maxTblNum) {
+ fprintf(stderr, "ERR Pack::init bad n=%d\n", (int)n);
+ throw Error(ERR_BAD_PARAMETER);
+ }
+ n_ = n;
+ for (size_t i = 0; i < n; i++) {
+ tbl_[i] = &tbl[i];
+ }
+ }
+ const Xbyak::Reg64& operator[](size_t n) const
+ {
+ if (n >= n_) {
+ fprintf(stderr, "ERR Pack bad n=%d(%d)\n", (int)n, (int)n_);
+ throw Error(ERR_BAD_PARAMETER);
+ }
+ return *tbl_[n];
+ }
+ size_t size() const { return n_; }
+ /*
+ get tbl[pos, pos + num)
+ */
+ Pack sub(size_t pos, size_t num = size_t(-1)) const
+ {
+ if (num == size_t(-1)) num = n_ - pos;
+ if (pos + num > n_) {
+ fprintf(stderr, "ERR Pack::sub bad pos=%d, num=%d\n", (int)pos, (int)num);
+ throw Error(ERR_BAD_PARAMETER);
+ }
+ Pack pack;
+ pack.n_ = num;
+ for (size_t i = 0; i < num; i++) {
+ pack.tbl_[i] = tbl_[pos + i];
+ }
+ return pack;
+ }
+ void put() const
+ {
+ for (size_t i = 0; i < n_; i++) {
+ printf("%s ", tbl_[i]->toString());
+ }
+ printf("\n");
+ }
+};
+
+class StackFrame {
+#ifdef XBYAK64_WIN
+ static const int noSaveNum = 6;
+ static const int rcxPos = 0;
+ static const int rdxPos = 1;
+#else
+ static const int noSaveNum = 8;
+ static const int rcxPos = 3;
+ static const int rdxPos = 2;
+#endif
+ static const int maxRegNum = 14; // maxRegNum = 16 - rsp - rax
+ Xbyak::CodeGenerator *code_;
+ int pNum_;
+ int tNum_;
+ bool useRcx_;
+ bool useRdx_;
+ int saveNum_;
+ int P_;
+ bool makeEpilog_;
+ Xbyak::Reg64 pTbl_[4];
+ Xbyak::Reg64 tTbl_[maxRegNum];
+ Pack p_;
+ Pack t_;
+ StackFrame(const StackFrame&);
+ void operator=(const StackFrame&);
+public:
+ const Pack& p;
+ const Pack& t;
+ /*
+ make stack frame
+ @param sf [in] this
+ @param pNum [in] num of function parameter(0 <= pNum <= 4)
+ @param tNum [in] num of temporary register(0 <= tNum, with UseRCX, UseRDX) #{pNum + tNum [+rcx] + [rdx]} <= 14
+ @param stackSizeByte [in] local stack size
+ @param makeEpilog [in] automatically call close() if true
+
+ you can use
+ rax
+ gp0, ..., gp(pNum - 1)
+ gt0, ..., gt(tNum-1)
+ rcx if tNum & UseRCX
+ rdx if tNum & UseRDX
+ rsp[0..stackSizeByte - 1]
+ */
+ StackFrame(Xbyak::CodeGenerator *code, int pNum, int tNum = 0, int stackSizeByte = 0, bool makeEpilog = true)
+ : code_(code)
+ , pNum_(pNum)
+ , tNum_(tNum & ~(UseRCX | UseRDX))
+ , useRcx_((tNum & UseRCX) != 0)
+ , useRdx_((tNum & UseRDX) != 0)
+ , saveNum_(0)
+ , P_(0)
+ , makeEpilog_(makeEpilog)
+ , p(p_)
+ , t(t_)
+ {
+ using namespace Xbyak;
+ if (pNum < 0 || pNum > 4) throw Error(ERR_BAD_PNUM);
+ const int allRegNum = pNum + tNum_ + (useRcx_ ? 1 : 0) + (useRdx_ ? 1 : 0);
+ if (tNum_ < 0 || allRegNum > maxRegNum) throw Error(ERR_BAD_TNUM);
+ const Reg64& _rsp = code->rsp;
+ saveNum_ = (std::max)(0, allRegNum - noSaveNum);
+ const int *tbl = getOrderTbl() + noSaveNum;
+ for (int i = 0; i < saveNum_; i++) {
+ code->push(Reg64(tbl[i]));
+ }
+ P_ = (stackSizeByte + 7) / 8;
+ if (P_ > 0 && (P_ & 1) == (saveNum_ & 1)) P_++; // (rsp % 16) == 8, then increment P_ for 16 byte alignment
+ P_ *= 8;
+ if (P_ > 0) code->sub(_rsp, P_);
+ int pos = 0;
+ for (int i = 0; i < pNum; i++) {
+ pTbl_[i] = Xbyak::Reg64(getRegIdx(pos));
+ }
+ for (int i = 0; i < tNum_; i++) {
+ tTbl_[i] = Xbyak::Reg64(getRegIdx(pos));
+ }
+ if (useRcx_ && rcxPos < pNum) code_->mov(code_->r10, code_->rcx);
+ if (useRdx_ && rdxPos < pNum) code_->mov(code_->r11, code_->rdx);
+ p_.init(pTbl_, pNum);
+ t_.init(tTbl_, tNum_);
+ }
+ /*
+ make epilog manually
+ @param callRet [in] call ret() if true
+ */
+ void close(bool callRet = true)
+ {
+ using namespace Xbyak;
+ const Reg64& _rsp = code_->rsp;
+ const int *tbl = getOrderTbl() + noSaveNum;
+ if (P_ > 0) code_->add(_rsp, P_);
+ for (int i = 0; i < saveNum_; i++) {
+ code_->pop(Reg64(tbl[saveNum_ - 1 - i]));
+ }
+
+ if (callRet) code_->ret();
+ }
+ ~StackFrame()
+ {
+ if (!makeEpilog_) return;
+ try {
+ close();
+ } catch (std::exception& e) {
+ printf("ERR:StackFrame %s\n", e.what());
+ //exit(1);
+ }
+ }
+private:
+ const int *getOrderTbl() const
+ {
+ using namespace Xbyak;
+ static const int tbl[] = {
+#ifdef XBYAK64_WIN
+ Operand::RCX, Operand::RDX, Operand::R8, Operand::R9, Operand::R10, Operand::R11, Operand::RDI, Operand::RSI,
+#else
+ Operand::RDI, Operand::RSI, Operand::RDX, Operand::RCX, Operand::R8, Operand::R9, Operand::R10, Operand::R11,
+#endif
+ Operand::RBX, Operand::RBP, Operand::R12, Operand::R13, Operand::R14, Operand::R15
+ };
+ return &tbl[0];
+ }
+ int getRegIdx(int& pos) const
+ {
+ assert(pos < maxRegNum);
+ using namespace Xbyak;
+ const int *tbl = getOrderTbl();
+ int r = tbl[pos++];
+ if (useRcx_) {
+ if (r == Operand::RCX) { return Operand::R10; }
+ if (r == Operand::R10) { r = tbl[pos++]; }
+ }
+ if (useRdx_) {
+ if (r == Operand::RDX) { return Operand::R11; }
+ if (r == Operand::R11) { return tbl[pos++]; }
+ }
+ return r;
+ }
+};
+#endif
+
+} } // end of util
+#endif
diff --git a/thirdparty/oidn/weights/rtlightmap_hdr.tza b/thirdparty/oidn/weights/rtlightmap_hdr.tza
new file mode 100644
index 0000000000..12459a33bc
--- /dev/null
+++ b/thirdparty/oidn/weights/rtlightmap_hdr.tza
Binary files differ
diff --git a/thirdparty/opus/analysis.c b/thirdparty/opus/analysis.c
index cb46dec582..663431a436 100644
--- a/thirdparty/opus/analysis.c
+++ b/thirdparty/opus/analysis.c
@@ -29,29 +29,20 @@
#include "config.h"
#endif
-#define ANALYSIS_C
-
-#include <stdio.h>
-
-#include "mathops.h"
#include "kiss_fft.h"
#include "celt.h"
#include "modes.h"
#include "arch.h"
#include "quant_bands.h"
+#include <stdio.h>
#include "analysis.h"
#include "mlp.h"
#include "stack_alloc.h"
-#include "float_cast.h"
#ifndef M_PI
#define M_PI 3.141592653
#endif
-#ifndef DISABLE_FLOAT_API
-
-#define TRANSITION_PENALTY 10
-
static const float dct_table[128] = {
0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
@@ -105,118 +96,52 @@ static const float analysis_window[240] = {
};
static const int tbands[NB_TBANDS+1] = {
- 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 136, 160, 192, 240
+ 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120
};
-#define NB_TONAL_SKIP_BANDS 9
+static const int extra_bands[NB_TOT_BANDS+1] = {
+ 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120, 160, 200
+};
-static opus_val32 silk_resampler_down2_hp(
- opus_val32 *S, /* I/O State vector [ 2 ] */
- opus_val32 *out, /* O Output signal [ floor(len/2) ] */
- const opus_val32 *in, /* I Input signal [ len ] */
- int inLen /* I Number of input samples */
-)
-{
- int k, len2 = inLen/2;
- opus_val32 in32, out32, out32_hp, Y, X;
- opus_val64 hp_ener = 0;
- /* Internal variables and state are in Q10 format */
- for( k = 0; k < len2; k++ ) {
- /* Convert to Q10 */
- in32 = in[ 2 * k ];
-
- /* All-pass section for even input sample */
- Y = SUB32( in32, S[ 0 ] );
- X = MULT16_32_Q15(QCONST16(0.6074371f, 15), Y);
- out32 = ADD32( S[ 0 ], X );
- S[ 0 ] = ADD32( in32, X );
- out32_hp = out32;
- /* Convert to Q10 */
- in32 = in[ 2 * k + 1 ];
-
- /* All-pass section for odd input sample, and add to output of previous section */
- Y = SUB32( in32, S[ 1 ] );
- X = MULT16_32_Q15(QCONST16(0.15063f, 15), Y);
- out32 = ADD32( out32, S[ 1 ] );
- out32 = ADD32( out32, X );
- S[ 1 ] = ADD32( in32, X );
-
- Y = SUB32( -in32, S[ 2 ] );
- X = MULT16_32_Q15(QCONST16(0.15063f, 15), Y);
- out32_hp = ADD32( out32_hp, S[ 2 ] );
- out32_hp = ADD32( out32_hp, X );
- S[ 2 ] = ADD32( -in32, X );
-
- hp_ener += out32_hp*(opus_val64)out32_hp;
- /* Add, convert back to int16 and store to output */
- out[ k ] = HALF32(out32);
- }
-#ifdef FIXED_POINT
- /* len2 can be up to 480, so we shift by 8 more to make it fit. */
- hp_ener = hp_ener >> (2*SIG_SHIFT + 8);
-#endif
- return (opus_val32)hp_ener;
-}
+/*static const float tweight[NB_TBANDS+1] = {
+ .3, .4, .5, .6, .7, .8, .9, 1., 1., 1., 1., 1., 1., 1., .8, .7, .6, .5
+};*/
-static opus_val32 downmix_and_resample(downmix_func downmix, const void *_x, opus_val32 *y, opus_val32 S[3], int subframe, int offset, int c1, int c2, int C, int Fs)
-{
- VARDECL(opus_val32, tmp);
- opus_val32 scale;
- int j;
- opus_val32 ret = 0;
- SAVE_STACK;
-
- if (subframe==0) return 0;
- if (Fs == 48000)
- {
- subframe *= 2;
- offset *= 2;
- } else if (Fs == 16000) {
- subframe = subframe*2/3;
- offset = offset*2/3;
- }
- ALLOC(tmp, subframe, opus_val32);
+#define NB_TONAL_SKIP_BANDS 9
- downmix(_x, tmp, subframe, offset, c1, c2, C);
-#ifdef FIXED_POINT
- scale = (1<<SIG_SHIFT);
-#else
- scale = 1.f/32768;
-#endif
- if (c2==-2)
- scale /= C;
- else if (c2>-1)
- scale /= 2;
- for (j=0;j<subframe;j++)
- tmp[j] *= scale;
- if (Fs == 48000)
+#define cA 0.43157974f
+#define cB 0.67848403f
+#define cC 0.08595542f
+#define cE ((float)M_PI/2)
+static OPUS_INLINE float fast_atan2f(float y, float x) {
+ float x2, y2;
+ /* Should avoid underflow on the values we'll get */
+ if (ABS16(x)+ABS16(y)<1e-9f)
{
- ret = silk_resampler_down2_hp(S, y, tmp, subframe);
- } else if (Fs == 24000) {
- OPUS_COPY(y, tmp, subframe);
- } else if (Fs == 16000) {
- VARDECL(opus_val32, tmp3x);
- ALLOC(tmp3x, 3*subframe, opus_val32);
- /* Don't do this at home! This resampler is horrible and it's only (barely)
- usable for the purpose of the analysis because we don't care about all
- the aliasing between 8 kHz and 12 kHz. */
- for (j=0;j<subframe;j++)
- {
- tmp3x[3*j] = tmp[j];
- tmp3x[3*j+1] = tmp[j];
- tmp3x[3*j+2] = tmp[j];
- }
- silk_resampler_down2_hp(S, y, tmp3x, 3*subframe);
+ x*=1e12f;
+ y*=1e12f;
+ }
+ x2 = x*x;
+ y2 = y*y;
+ if(x2<y2){
+ float den = (y2 + cB*x2) * (y2 + cC*x2);
+ if (den!=0)
+ return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE);
+ else
+ return (y<0 ? -cE : cE);
+ }else{
+ float den = (x2 + cB*y2) * (x2 + cC*y2);
+ if (den!=0)
+ return x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
+ else
+ return (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
}
- RESTORE_STACK;
- return ret;
}
-void tonality_analysis_init(TonalityAnalysisState *tonal, opus_int32 Fs)
+void tonality_analysis_init(TonalityAnalysisState *tonal)
{
/* Initialize reusable fields. */
tonal->arch = opus_select_arch();
- tonal->Fs = Fs;
/* Clear remaining fields. */
tonality_analysis_reset(tonal);
}
@@ -232,34 +157,15 @@ void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int
{
int pos;
int curr_lookahead;
- float tonality_max;
- float tonality_avg;
- int tonality_count;
+ float psum;
int i;
- int pos0;
- float prob_avg;
- float prob_count;
- float prob_min, prob_max;
- float vad_prob;
- int mpos, vpos;
- int bandwidth_span;
pos = tonal->read_pos;
curr_lookahead = tonal->write_pos-tonal->read_pos;
if (curr_lookahead<0)
curr_lookahead += DETECT_SIZE;
- tonal->read_subframe += len/(tonal->Fs/400);
- while (tonal->read_subframe>=8)
- {
- tonal->read_subframe -= 8;
- tonal->read_pos++;
- }
- if (tonal->read_pos>=DETECT_SIZE)
- tonal->read_pos-=DETECT_SIZE;
-
- /* On long frames, look at the second analysis window rather than the first. */
- if (len > tonal->Fs/50 && pos != tonal->write_pos)
+ if (len > 480 && pos != tonal->write_pos)
{
pos++;
if (pos==DETECT_SIZE)
@@ -269,177 +175,32 @@ void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int
pos--;
if (pos<0)
pos = DETECT_SIZE-1;
- pos0 = pos;
OPUS_COPY(info_out, &tonal->info[pos], 1);
- if (!info_out->valid)
- return;
- tonality_max = tonality_avg = info_out->tonality;
- tonality_count = 1;
- /* Look at the neighbouring frames and pick largest bandwidth found (to be safe). */
- bandwidth_span = 6;
- /* If possible, look ahead for a tone to compensate for the delay in the tone detector. */
- for (i=0;i<3;i++)
- {
- pos++;
- if (pos==DETECT_SIZE)
- pos = 0;
- if (pos == tonal->write_pos)
- break;
- tonality_max = MAX32(tonality_max, tonal->info[pos].tonality);
- tonality_avg += tonal->info[pos].tonality;
- tonality_count++;
- info_out->bandwidth = IMAX(info_out->bandwidth, tonal->info[pos].bandwidth);
- bandwidth_span--;
- }
- pos = pos0;
- /* Look back in time to see if any has a wider bandwidth than the current frame. */
- for (i=0;i<bandwidth_span;i++)
- {
- pos--;
- if (pos < 0)
- pos = DETECT_SIZE-1;
- if (pos == tonal->write_pos)
- break;
- info_out->bandwidth = IMAX(info_out->bandwidth, tonal->info[pos].bandwidth);
- }
- info_out->tonality = MAX32(tonality_avg/tonality_count, tonality_max-.2f);
-
- mpos = vpos = pos0;
- /* If we have enough look-ahead, compensate for the ~5-frame delay in the music prob and
- ~1 frame delay in the VAD prob. */
- if (curr_lookahead > 15)
+ tonal->read_subframe += len/120;
+ while (tonal->read_subframe>=4)
{
- mpos += 5;
- if (mpos>=DETECT_SIZE)
- mpos -= DETECT_SIZE;
- vpos += 1;
- if (vpos>=DETECT_SIZE)
- vpos -= DETECT_SIZE;
- }
-
- /* The following calculations attempt to minimize a "badness function"
- for the transition. When switching from speech to music, the badness
- of switching at frame k is
- b_k = S*v_k + \sum_{i=0}^{k-1} v_i*(p_i - T)
- where
- v_i is the activity probability (VAD) at frame i,
- p_i is the music probability at frame i
- T is the probability threshold for switching
- S is the penalty for switching during active audio rather than silence
- the current frame has index i=0
-
- Rather than apply badness to directly decide when to switch, what we compute
- instead is the threshold for which the optimal switching point is now. When
- considering whether to switch now (frame 0) or at frame k, we have:
- S*v_0 = S*v_k + \sum_{i=0}^{k-1} v_i*(p_i - T)
- which gives us:
- T = ( \sum_{i=0}^{k-1} v_i*p_i + S*(v_k-v_0) ) / ( \sum_{i=0}^{k-1} v_i )
- We take the min threshold across all positive values of k (up to the maximum
- amount of lookahead we have) to give us the threshold for which the current
- frame is the optimal switch point.
-
- The last step is that we need to consider whether we want to switch at all.
- For that we use the average of the music probability over the entire window.
- If the threshold is higher than that average we're not going to
- switch, so we compute a min with the average as well. The result of all these
- min operations is music_prob_min, which gives the threshold for switching to music
- if we're currently encoding for speech.
-
- We do the exact opposite to compute music_prob_max which is used for switching
- from music to speech.
- */
- prob_min = 1.f;
- prob_max = 0.f;
- vad_prob = tonal->info[vpos].activity_probability;
- prob_count = MAX16(.1f, vad_prob);
- prob_avg = MAX16(.1f, vad_prob)*tonal->info[mpos].music_prob;
- while (1)
- {
- float pos_vad;
- mpos++;
- if (mpos==DETECT_SIZE)
- mpos = 0;
- if (mpos == tonal->write_pos)
- break;
- vpos++;
- if (vpos==DETECT_SIZE)
- vpos = 0;
- if (vpos == tonal->write_pos)
- break;
- pos_vad = tonal->info[vpos].activity_probability;
- prob_min = MIN16((prob_avg - TRANSITION_PENALTY*(vad_prob - pos_vad))/prob_count, prob_min);
- prob_max = MAX16((prob_avg + TRANSITION_PENALTY*(vad_prob - pos_vad))/prob_count, prob_max);
- prob_count += MAX16(.1f, pos_vad);
- prob_avg += MAX16(.1f, pos_vad)*tonal->info[mpos].music_prob;
- }
- info_out->music_prob = prob_avg/prob_count;
- prob_min = MIN16(prob_avg/prob_count, prob_min);
- prob_max = MAX16(prob_avg/prob_count, prob_max);
- prob_min = MAX16(prob_min, 0.f);
- prob_max = MIN16(prob_max, 1.f);
-
- /* If we don't have enough look-ahead, do our best to make a decent decision. */
- if (curr_lookahead < 10)
- {
- float pmin, pmax;
- pmin = prob_min;
- pmax = prob_max;
- pos = pos0;
- /* Look for min/max in the past. */
- for (i=0;i<IMIN(tonal->count-1, 15);i++)
- {
- pos--;
- if (pos < 0)
- pos = DETECT_SIZE-1;
- pmin = MIN16(pmin, tonal->info[pos].music_prob);
- pmax = MAX16(pmax, tonal->info[pos].music_prob);
- }
- /* Bias against switching on active audio. */
- pmin = MAX16(0.f, pmin - .1f*vad_prob);
- pmax = MIN16(1.f, pmax + .1f*vad_prob);
- prob_min += (1.f-.1f*curr_lookahead)*(pmin - prob_min);
- prob_max += (1.f-.1f*curr_lookahead)*(pmax - prob_max);
+ tonal->read_subframe -= 4;
+ tonal->read_pos++;
}
- info_out->music_prob_min = prob_min;
- info_out->music_prob_max = prob_max;
-
- /* printf("%f %f %f %f %f\n", prob_min, prob_max, prob_avg/prob_count, vad_prob, info_out->music_prob); */
-}
-
-static const float std_feature_bias[9] = {
- 5.684947f, 3.475288f, 1.770634f, 1.599784f, 3.773215f,
- 2.163313f, 1.260756f, 1.116868f, 1.918795f
-};
-
-#define LEAKAGE_OFFSET 2.5f
-#define LEAKAGE_SLOPE 2.f
-
-#ifdef FIXED_POINT
-/* For fixed-point, the input is +/-2^15 shifted up by SIG_SHIFT, so we need to
- compensate for that in the energy. */
-#define SCALE_COMPENS (1.f/((opus_int32)1<<(15+SIG_SHIFT)))
-#define SCALE_ENER(e) ((SCALE_COMPENS*SCALE_COMPENS)*(e))
-#else
-#define SCALE_ENER(e) (e)
-#endif
-
-#ifdef FIXED_POINT
-static int is_digital_silence32(const opus_val32* pcm, int frame_size, int channels, int lsb_depth)
-{
- int silence = 0;
- opus_val32 sample_max = 0;
-#ifdef MLP_TRAINING
- return 0;
-#endif
- sample_max = celt_maxabs32(pcm, frame_size*channels);
+ if (tonal->read_pos>=DETECT_SIZE)
+ tonal->read_pos-=DETECT_SIZE;
- silence = (sample_max == 0);
- (void)lsb_depth;
- return silence;
+ /* Compensate for the delay in the features themselves.
+ FIXME: Need a better estimate the 10 I just made up */
+ curr_lookahead = IMAX(curr_lookahead-10, 0);
+
+ psum=0;
+ /* Summing the probability of transition patterns that involve music at
+ time (DETECT_SIZE-curr_lookahead-1) */
+ for (i=0;i<DETECT_SIZE-curr_lookahead;i++)
+ psum += tonal->pmusic[i];
+ for (;i<DETECT_SIZE;i++)
+ psum += tonal->pspeech[i];
+ psum = psum*tonal->music_confidence + (1-psum)*tonal->speech_confidence;
+ /*printf("%f %f %f\n", psum, info_out->music_prob, info_out->tonality);*/
+
+ info_out->music_prob = psum;
}
-#else
-#define is_digital_silence32(pcm, frame_size, channels, lsb_depth) is_digital_silence(pcm, frame_size, channels, lsb_depth)
-#endif
static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix)
{
@@ -469,50 +230,24 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
float alpha, alphaE, alphaE2;
float frame_loudness;
float bandwidth_mask;
- int is_masked[NB_TBANDS+1];
int bandwidth=0;
float maxE = 0;
float noise_floor;
int remaining;
AnalysisInfo *info;
- float hp_ener;
- float tonality2[240];
- float midE[8];
- float spec_variability=0;
- float band_log2[NB_TBANDS+1];
- float leakage_from[NB_TBANDS+1];
- float leakage_to[NB_TBANDS+1];
- float layer_out[MAX_NEURONS];
- float below_max_pitch;
- float above_max_pitch;
- int is_silence;
SAVE_STACK;
- if (!tonal->initialized)
- {
- tonal->mem_fill = 240;
- tonal->initialized = 1;
- }
- alpha = 1.f/IMIN(10, 1+tonal->count);
- alphaE = 1.f/IMIN(25, 1+tonal->count);
- /* Noise floor related decay for bandwidth detection: -2.2 dB/second */
- alphaE2 = 1.f/IMIN(100, 1+tonal->count);
- if (tonal->count <= 1) alphaE2 = 1;
-
- if (tonal->Fs == 48000)
- {
- /* len and offset are now at 24 kHz. */
- len/= 2;
- offset /= 2;
- } else if (tonal->Fs == 16000) {
- len = 3*len/2;
- offset = 3*offset/2;
- }
+ tonal->last_transition++;
+ alpha = 1.f/IMIN(20, 1+tonal->count);
+ alphaE = 1.f/IMIN(50, 1+tonal->count);
+ alphaE2 = 1.f/IMIN(1000, 1+tonal->count);
+ if (tonal->count<4)
+ tonal->music_prob = .5;
kfft = celt_mode->mdct.kfft[0];
- tonal->hp_ener_accum += (float)downmix_and_resample(downmix, x,
- &tonal->inmem[tonal->mem_fill], tonal->downmix_state,
- IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C, tonal->Fs);
+ if (tonal->count==0)
+ tonal->mem_fill = 240;
+ downmix(x, &tonal->inmem[tonal->mem_fill], IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C);
if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE)
{
tonal->mem_fill += len;
@@ -520,13 +255,10 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
RESTORE_STACK;
return;
}
- hp_ener = tonal->hp_ener_accum;
info = &tonal->info[tonal->write_pos++];
if (tonal->write_pos>=DETECT_SIZE)
tonal->write_pos-=DETECT_SIZE;
- is_silence = is_digital_silence32(tonal->inmem, ANALYSIS_BUF_SIZE, 1, lsb_depth);
-
ALLOC(in, 480, kiss_fft_cpx);
ALLOC(out, 480, kiss_fft_cpx);
ALLOC(tonality, 240, float);
@@ -541,20 +273,8 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
}
OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240);
remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill);
- tonal->hp_ener_accum = (float)downmix_and_resample(downmix, x,
- &tonal->inmem[240], tonal->downmix_state, remaining,
- offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C, tonal->Fs);
+ downmix(x, &tonal->inmem[240], remaining, offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C);
tonal->mem_fill = 240 + remaining;
- if (is_silence)
- {
- /* On silence, copy the previous analysis. */
- int prev_pos = tonal->write_pos-2;
- if (prev_pos < 0)
- prev_pos += DETECT_SIZE;
- OPUS_COPY(info, &tonal->info[prev_pos], 1);
- RESTORE_STACK;
- return;
- }
opus_fft(kfft, in, out, tonal->arch);
#ifndef FIXED_POINT
/* If there's any NaN on the input, the entire output will be NaN, so we only need to check one value. */
@@ -585,31 +305,24 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
d_angle2 = angle2 - angle;
d2_angle2 = d_angle2 - d_angle;
- mod1 = d2_angle - (float)float2int(d2_angle);
+ mod1 = d2_angle - (float)floor(.5+d2_angle);
noisiness[i] = ABS16(mod1);
mod1 *= mod1;
mod1 *= mod1;
- mod2 = d2_angle2 - (float)float2int(d2_angle2);
+ mod2 = d2_angle2 - (float)floor(.5+d2_angle2);
noisiness[i] += ABS16(mod2);
mod2 *= mod2;
mod2 *= mod2;
- avg_mod = .25f*(d2A[i]+mod1+2*mod2);
- /* This introduces an extra delay of 2 frames in the detection. */
+ avg_mod = .25f*(d2A[i]+2.f*mod1+mod2);
tonality[i] = 1.f/(1.f+40.f*16.f*pi4*avg_mod)-.015f;
- /* No delay on this detection, but it's less reliable. */
- tonality2[i] = 1.f/(1.f+40.f*16.f*pi4*mod2)-.015f;
A[i] = angle2;
dA[i] = d_angle2;
d2A[i] = mod2;
}
- for (i=2;i<N2-1;i++)
- {
- float tt = MIN32(tonality2[i], MAX32(tonality2[i-1], tonality2[i+1]));
- tonality[i] = .9f*MAX32(tonality[i], tt-.1f);
- }
+
frame_tonality = 0;
max_frame_tonality = 0;
/*tw_sum = 0;*/
@@ -626,22 +339,6 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
}
relativeE = 0;
frame_loudness = 0;
- /* The energy of the very first band is special because of DC. */
- {
- float E = 0;
- float X1r, X2r;
- X1r = 2*(float)out[0].r;
- X2r = 2*(float)out[0].i;
- E = X1r*X1r + X2r*X2r;
- for (i=1;i<4;i++)
- {
- float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
- + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
- E += binE;
- }
- E = SCALE_ENER(E);
- band_log2[0] = .5f*1.442695f*(float)log(E+1e-10f);
- }
for (b=0;b<NB_TBANDS;b++)
{
float E=0, tE=0, nE=0;
@@ -651,9 +348,12 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
{
float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
+ out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
- binE = SCALE_ENER(binE);
+#ifdef FIXED_POINT
+ /* FIXME: It's probably best to change the BFCC filter initial state instead */
+ binE *= 5.55e-17f;
+#endif
E += binE;
- tE += binE*MAX32(0, tonality[i]);
+ tE += binE*tonality[i];
nE += binE*2.f*(.5f-noisiness[i]);
}
#ifndef FIXED_POINT
@@ -671,27 +371,14 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
frame_loudness += (float)sqrt(E+1e-10f);
logE[b] = (float)log(E+1e-10f);
- band_log2[b+1] = .5f*1.442695f*(float)log(E+1e-10f);
- tonal->logE[tonal->E_count][b] = logE[b];
- if (tonal->count==0)
- tonal->highE[b] = tonal->lowE[b] = logE[b];
- if (tonal->highE[b] > tonal->lowE[b] + 7.5)
+ tonal->lowE[b] = MIN32(logE[b], tonal->lowE[b]+.01f);
+ tonal->highE[b] = MAX32(logE[b], tonal->highE[b]-.1f);
+ if (tonal->highE[b] < tonal->lowE[b]+1.f)
{
- if (tonal->highE[b] - logE[b] > logE[b] - tonal->lowE[b])
- tonal->highE[b] -= .01f;
- else
- tonal->lowE[b] += .01f;
+ tonal->highE[b]+=.5f;
+ tonal->lowE[b]-=.5f;
}
- if (logE[b] > tonal->highE[b])
- {
- tonal->highE[b] = logE[b];
- tonal->lowE[b] = MAX32(tonal->highE[b]-15, tonal->lowE[b]);
- } else if (logE[b] < tonal->lowE[b])
- {
- tonal->lowE[b] = logE[b];
- tonal->highE[b] = MIN32(tonal->lowE[b]+15, tonal->highE[b]);
- }
- relativeE += (logE[b]-tonal->lowE[b])/(1e-5f + (tonal->highE[b]-tonal->lowE[b]));
+ relativeE += (logE[b]-tonal->lowE[b])/(1e-15f+tonal->highE[b]-tonal->lowE[b]);
L1=L2=0;
for (i=0;i<NB_FRAMES;i++)
@@ -723,135 +410,45 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
tonal->prev_band_tonality[b] = band_tonality[b];
}
- leakage_from[0] = band_log2[0];
- leakage_to[0] = band_log2[0] - LEAKAGE_OFFSET;
- for (b=1;b<NB_TBANDS+1;b++)
- {
- float leak_slope = LEAKAGE_SLOPE*(tbands[b]-tbands[b-1])/4;
- leakage_from[b] = MIN16(leakage_from[b-1]+leak_slope, band_log2[b]);
- leakage_to[b] = MAX16(leakage_to[b-1]-leak_slope, band_log2[b]-LEAKAGE_OFFSET);
- }
- for (b=NB_TBANDS-2;b>=0;b--)
- {
- float leak_slope = LEAKAGE_SLOPE*(tbands[b+1]-tbands[b])/4;
- leakage_from[b] = MIN16(leakage_from[b+1]+leak_slope, leakage_from[b]);
- leakage_to[b] = MAX16(leakage_to[b+1]-leak_slope, leakage_to[b]);
- }
- celt_assert(NB_TBANDS+1 <= LEAK_BANDS);
- for (b=0;b<NB_TBANDS+1;b++)
- {
- /* leak_boost[] is made up of two terms. The first, based on leakage_to[],
- represents the boost needed to overcome the amount of analysis leakage
- cause in a weaker band b by louder neighbouring bands.
- The second, based on leakage_from[], applies to a loud band b for
- which the quantization noise causes synthesis leakage to the weaker
- neighbouring bands. */
- float boost = MAX16(0, leakage_to[b] - band_log2[b]) +
- MAX16(0, band_log2[b] - (leakage_from[b]+LEAKAGE_OFFSET));
- info->leak_boost[b] = IMIN(255, (int)floor(.5 + 64.f*boost));
- }
- for (;b<LEAK_BANDS;b++) info->leak_boost[b] = 0;
-
- for (i=0;i<NB_FRAMES;i++)
- {
- int j;
- float mindist = 1e15f;
- for (j=0;j<NB_FRAMES;j++)
- {
- int k;
- float dist=0;
- for (k=0;k<NB_TBANDS;k++)
- {
- float tmp;
- tmp = tonal->logE[i][k] - tonal->logE[j][k];
- dist += tmp*tmp;
- }
- if (j!=i)
- mindist = MIN32(mindist, dist);
- }
- spec_variability += mindist;
- }
- spec_variability = (float)sqrt(spec_variability/NB_FRAMES/NB_TBANDS);
bandwidth_mask = 0;
bandwidth = 0;
maxE = 0;
noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8)));
+#ifdef FIXED_POINT
+ noise_floor *= 1<<(15+SIG_SHIFT);
+#endif
noise_floor *= noise_floor;
- below_max_pitch=0;
- above_max_pitch=0;
- for (b=0;b<NB_TBANDS;b++)
+ for (b=0;b<NB_TOT_BANDS;b++)
{
float E=0;
- float Em;
int band_start, band_end;
/* Keep a margin of 300 Hz for aliasing */
- band_start = tbands[b];
- band_end = tbands[b+1];
+ band_start = extra_bands[b];
+ band_end = extra_bands[b+1];
for (i=band_start;i<band_end;i++)
{
float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
+ out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
E += binE;
}
- E = SCALE_ENER(E);
maxE = MAX32(maxE, E);
- if (band_start < 64)
- {
- below_max_pitch += E;
- } else {
- above_max_pitch += E;
- }
tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E);
- Em = MAX32(E, tonal->meanE[b]);
+ E = MAX32(E, tonal->meanE[b]);
+ /* Use a simple follower with 13 dB/Bark slope for spreading function */
+ bandwidth_mask = MAX32(.05f*bandwidth_mask, E);
/* Consider the band "active" only if all these conditions are met:
- 1) less than 90 dB below the peak band (maximal masking possible considering
+ 1) less than 10 dB below the simple follower
+ 2) less than 90 dB below the peak band (maximal masking possible considering
both the ATH and the loudness-dependent slope of the spreading function)
- 2) above the PCM quantization noise floor
- We use b+1 because the first CELT band isn't included in tbands[]
+ 3) above the PCM quantization noise floor
*/
- if (E*1e9f > maxE && (Em > 3*noise_floor*(band_end-band_start) || E > noise_floor*(band_end-band_start)))
- bandwidth = b+1;
- /* Check if the band is masked (see below). */
- is_masked[b] = E < (tonal->prev_bandwidth >= b+1 ? .01f : .05f)*bandwidth_mask;
- /* Use a simple follower with 13 dB/Bark slope for spreading function. */
- bandwidth_mask = MAX32(.05f*bandwidth_mask, E);
+ if (E>.1*bandwidth_mask && E*1e9f > maxE && E > noise_floor*(band_end-band_start))
+ bandwidth = b;
}
- /* Special case for the last two bands, for which we don't have spectrum but only
- the energy above 12 kHz. The difficulty here is that the high-pass we use
- leaks some LF energy, so we need to increase the threshold without accidentally cutting
- off the band. */
- if (tonal->Fs == 48000) {
- float noise_ratio;
- float Em;
- float E = hp_ener*(1.f/(60*60));
- noise_ratio = tonal->prev_bandwidth==20 ? 10.f : 30.f;
-
-#ifdef FIXED_POINT
- /* silk_resampler_down2_hp() shifted right by an extra 8 bits. */
- E *= 256.f*(1.f/Q15ONE)*(1.f/Q15ONE);
-#endif
- above_max_pitch += E;
- tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E);
- Em = MAX32(E, tonal->meanE[b]);
- if (Em > 3*noise_ratio*noise_floor*160 || E > noise_ratio*noise_floor*160)
- bandwidth = 20;
- /* Check if the band is masked (see below). */
- is_masked[b] = E < (tonal->prev_bandwidth == 20 ? .01f : .05f)*bandwidth_mask;
- }
- if (above_max_pitch > below_max_pitch)
- info->max_pitch_ratio = below_max_pitch/above_max_pitch;
- else
- info->max_pitch_ratio = 1;
- /* In some cases, resampling aliasing can create a small amount of energy in the first band
- being cut. So if the last band is masked, we don't include it. */
- if (bandwidth == 20 && is_masked[NB_TBANDS])
- bandwidth-=2;
- else if (bandwidth > 0 && bandwidth <= NB_TBANDS && is_masked[bandwidth-1])
- bandwidth--;
if (tonal->count<=2)
bandwidth = 20;
frame_loudness = 20*(float)log10(frame_loudness);
- tonal->Etracker = MAX32(tonal->Etracker-.003f, frame_loudness);
+ tonal->Etracker = MAX32(tonal->Etracker-.03f, frame_loudness);
tonal->lowECount *= (1-alphaE);
if (frame_loudness < tonal->Etracker-30)
tonal->lowECount += alphaE;
@@ -863,18 +460,11 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
sum += dct_table[i*16+b]*logE[b];
BFCC[i] = sum;
}
- for (i=0;i<8;i++)
- {
- float sum=0;
- for (b=0;b<16;b++)
- sum += dct_table[i*16+b]*.5f*(tonal->highE[b]+tonal->lowE[b]);
- midE[i] = sum;
- }
frame_stationarity /= NB_TBANDS;
relativeE /= NB_TBANDS;
if (tonal->count<10)
- relativeE = .5f;
+ relativeE = .5;
frame_noisiness /= NB_TBANDS;
#if 1
info->activity = frame_noisiness + (1-frame_noisiness)*relativeE;
@@ -889,7 +479,7 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
info->tonality_slope = slope;
tonal->E_count = (tonal->E_count+1)%NB_FRAMES;
- tonal->count = IMIN(tonal->count+1, ANALYSIS_COUNT_MAX);
+ tonal->count++;
info->tonality = frame_tonality;
for (i=0;i<4;i++)
@@ -908,8 +498,6 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
for (i=0;i<9;i++)
tonal->std[i] = (1-alpha)*tonal->std[i] + alpha*features[i]*features[i];
}
- for (i=0;i<4;i++)
- features[i] = BFCC[i]-midE[i];
for (i=0;i<8;i++)
{
@@ -919,31 +507,136 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
tonal->mem[i] = BFCC[i];
}
for (i=0;i<9;i++)
- features[11+i] = (float)sqrt(tonal->std[i]) - std_feature_bias[i];
- features[18] = spec_variability - 0.78f;
- features[20] = info->tonality - 0.154723f;
- features[21] = info->activity - 0.724643f;
- features[22] = frame_stationarity - 0.743717f;
- features[23] = info->tonality_slope + 0.069216f;
- features[24] = tonal->lowECount - 0.067930f;
-
- compute_dense(&layer0, layer_out, features);
- compute_gru(&layer1, tonal->rnn_state, layer_out);
- compute_dense(&layer2, frame_probs, tonal->rnn_state);
-
- /* Probability of speech or music vs noise */
- info->activity_probability = frame_probs[1];
- info->music_prob = frame_probs[0];
-
- /*printf("%f %f %f\n", frame_probs[0], frame_probs[1], info->music_prob);*/
-#ifdef MLP_TRAINING
- for (i=0;i<25;i++)
- printf("%f ", features[i]);
- printf("\n");
+ features[11+i] = (float)sqrt(tonal->std[i]);
+ features[20] = info->tonality;
+ features[21] = info->activity;
+ features[22] = frame_stationarity;
+ features[23] = info->tonality_slope;
+ features[24] = tonal->lowECount;
+
+#ifndef DISABLE_FLOAT_API
+ mlp_process(&net, features, frame_probs);
+ frame_probs[0] = .5f*(frame_probs[0]+1);
+ /* Curve fitting between the MLP probability and the actual probability */
+ frame_probs[0] = .01f + 1.21f*frame_probs[0]*frame_probs[0] - .23f*(float)pow(frame_probs[0], 10);
+ /* Probability of active audio (as opposed to silence) */
+ frame_probs[1] = .5f*frame_probs[1]+.5f;
+ /* Consider that silence has a 50-50 probability. */
+ frame_probs[0] = frame_probs[1]*frame_probs[0] + (1-frame_probs[1])*.5f;
+
+ /*printf("%f %f ", frame_probs[0], frame_probs[1]);*/
+ {
+ /* Probability of state transition */
+ float tau;
+ /* Represents independence of the MLP probabilities, where
+ beta=1 means fully independent. */
+ float beta;
+ /* Denormalized probability of speech (p0) and music (p1) after update */
+ float p0, p1;
+ /* Probabilities for "all speech" and "all music" */
+ float s0, m0;
+ /* Probability sum for renormalisation */
+ float psum;
+ /* Instantaneous probability of speech and music, with beta pre-applied. */
+ float speech0;
+ float music0;
+ float p, q;
+
+ /* One transition every 3 minutes of active audio */
+ tau = .00005f*frame_probs[1];
+ /* Adapt beta based on how "unexpected" the new prob is */
+ p = MAX16(.05f,MIN16(.95f,frame_probs[0]));
+ q = MAX16(.05f,MIN16(.95f,tonal->music_prob));
+ beta = .01f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p));
+ /* p0 and p1 are the probabilities of speech and music at this frame
+ using only information from previous frame and applying the
+ state transition model */
+ p0 = (1-tonal->music_prob)*(1-tau) + tonal->music_prob *tau;
+ p1 = tonal->music_prob *(1-tau) + (1-tonal->music_prob)*tau;
+ /* We apply the current probability with exponent beta to work around
+ the fact that the probability estimates aren't independent. */
+ p0 *= (float)pow(1-frame_probs[0], beta);
+ p1 *= (float)pow(frame_probs[0], beta);
+ /* Normalise the probabilities to get the Marokv probability of music. */
+ tonal->music_prob = p1/(p0+p1);
+ info->music_prob = tonal->music_prob;
+
+ /* This chunk of code deals with delayed decision. */
+ psum=1e-20f;
+ /* Instantaneous probability of speech and music, with beta pre-applied. */
+ speech0 = (float)pow(1-frame_probs[0], beta);
+ music0 = (float)pow(frame_probs[0], beta);
+ if (tonal->count==1)
+ {
+ tonal->pspeech[0]=.5;
+ tonal->pmusic [0]=.5;
+ }
+ /* Updated probability of having only speech (s0) or only music (m0),
+ before considering the new observation. */
+ s0 = tonal->pspeech[0] + tonal->pspeech[1];
+ m0 = tonal->pmusic [0] + tonal->pmusic [1];
+ /* Updates s0 and m0 with instantaneous probability. */
+ tonal->pspeech[0] = s0*(1-tau)*speech0;
+ tonal->pmusic [0] = m0*(1-tau)*music0;
+ /* Propagate the transition probabilities */
+ for (i=1;i<DETECT_SIZE-1;i++)
+ {
+ tonal->pspeech[i] = tonal->pspeech[i+1]*speech0;
+ tonal->pmusic [i] = tonal->pmusic [i+1]*music0;
+ }
+ /* Probability that the latest frame is speech, when all the previous ones were music. */
+ tonal->pspeech[DETECT_SIZE-1] = m0*tau*speech0;
+ /* Probability that the latest frame is music, when all the previous ones were speech. */
+ tonal->pmusic [DETECT_SIZE-1] = s0*tau*music0;
+
+ /* Renormalise probabilities to 1 */
+ for (i=0;i<DETECT_SIZE;i++)
+ psum += tonal->pspeech[i] + tonal->pmusic[i];
+ psum = 1.f/psum;
+ for (i=0;i<DETECT_SIZE;i++)
+ {
+ tonal->pspeech[i] *= psum;
+ tonal->pmusic [i] *= psum;
+ }
+ psum = tonal->pmusic[0];
+ for (i=1;i<DETECT_SIZE;i++)
+ psum += tonal->pspeech[i];
+
+ /* Estimate our confidence in the speech/music decisions */
+ if (frame_probs[1]>.75)
+ {
+ if (tonal->music_prob>.9)
+ {
+ float adapt;
+ adapt = 1.f/(++tonal->music_confidence_count);
+ tonal->music_confidence_count = IMIN(tonal->music_confidence_count, 500);
+ tonal->music_confidence += adapt*MAX16(-.2f,frame_probs[0]-tonal->music_confidence);
+ }
+ if (tonal->music_prob<.1)
+ {
+ float adapt;
+ adapt = 1.f/(++tonal->speech_confidence_count);
+ tonal->speech_confidence_count = IMIN(tonal->speech_confidence_count, 500);
+ tonal->speech_confidence += adapt*MIN16(.2f,frame_probs[0]-tonal->speech_confidence);
+ }
+ } else {
+ if (tonal->music_confidence_count==0)
+ tonal->music_confidence = .9f;
+ if (tonal->speech_confidence_count==0)
+ tonal->speech_confidence = .1f;
+ }
+ }
+ if (tonal->last_music != (tonal->music_prob>.5f))
+ tonal->last_transition=0;
+ tonal->last_music = tonal->music_prob>.5f;
+#else
+ info->music_prob = 0;
#endif
+ /*for (i=0;i<25;i++)
+ printf("%f ", features[i]);
+ printf("\n");*/
info->bandwidth = bandwidth;
- tonal->prev_bandwidth = bandwidth;
/*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/
info->noisiness = frame_noisiness;
info->valid = 1;
@@ -957,25 +650,23 @@ void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, co
int offset;
int pcm_len;
- analysis_frame_size -= analysis_frame_size&1;
if (analysis_pcm != NULL)
{
/* Avoid overflow/wrap-around of the analysis buffer */
- analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/50, analysis_frame_size);
+ analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/100, analysis_frame_size);
pcm_len = analysis_frame_size - analysis->analysis_offset;
offset = analysis->analysis_offset;
- while (pcm_len>0) {
- tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(Fs/50, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
- offset += Fs/50;
- pcm_len -= Fs/50;
- }
+ do {
+ tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
+ offset += 480;
+ pcm_len -= 480;
+ } while (pcm_len>0);
analysis->analysis_offset = analysis_frame_size;
analysis->analysis_offset -= frame_size;
}
+ analysis_info->valid = 0;
tonality_get_info(analysis, analysis_info, frame_size);
}
-
-#endif /* DISABLE_FLOAT_API */
diff --git a/thirdparty/opus/analysis.h b/thirdparty/opus/analysis.h
index 0b66555f21..9eae56a525 100644
--- a/thirdparty/opus/analysis.h
+++ b/thirdparty/opus/analysis.h
@@ -30,24 +30,16 @@
#include "celt.h"
#include "opus_private.h"
-#include "mlp.h"
#define NB_FRAMES 8
#define NB_TBANDS 18
-#define ANALYSIS_BUF_SIZE 720 /* 30 ms at 24 kHz */
+#define NB_TOT_BANDS 21
+#define ANALYSIS_BUF_SIZE 720 /* 15 ms at 48 kHz */
-/* At that point we can stop counting frames because it no longer matters. */
-#define ANALYSIS_COUNT_MAX 10000
-
-#define DETECT_SIZE 100
-
-/* Uncomment this to print the MLP features on stdout. */
-/*#define MLP_TRAINING*/
+#define DETECT_SIZE 200
typedef struct {
int arch;
- int application;
- opus_int32 Fs;
#define TONALITY_ANALYSIS_RESET_START angle
float angle[240];
float d_angle[240];
@@ -56,27 +48,35 @@ typedef struct {
int mem_fill; /* number of usable samples in the buffer */
float prev_band_tonality[NB_TBANDS];
float prev_tonality;
- int prev_bandwidth;
float E[NB_FRAMES][NB_TBANDS];
- float logE[NB_FRAMES][NB_TBANDS];
float lowE[NB_TBANDS];
float highE[NB_TBANDS];
- float meanE[NB_TBANDS+1];
+ float meanE[NB_TOT_BANDS];
float mem[32];
float cmean[8];
float std[9];
+ float music_prob;
float Etracker;
float lowECount;
int E_count;
+ int last_music;
+ int last_transition;
int count;
+ float subframe_mem[3];
int analysis_offset;
+ /** Probability of having speech for time i to DETECT_SIZE-1 (and music before).
+ pspeech[0] is the probability that all frames in the window are speech. */
+ float pspeech[DETECT_SIZE];
+ /** Probability of having music for time i to DETECT_SIZE-1 (and speech before).
+ pmusic[0] is the probability that all frames in the window are music. */
+ float pmusic[DETECT_SIZE];
+ float speech_confidence;
+ float music_confidence;
+ int speech_confidence_count;
+ int music_confidence_count;
int write_pos;
int read_pos;
int read_subframe;
- float hp_ener_accum;
- int initialized;
- float rnn_state[MAX_NEURONS];
- opus_val32 downmix_state[3];
AnalysisInfo info[DETECT_SIZE];
} TonalityAnalysisState;
@@ -86,7 +86,7 @@ typedef struct {
* not be repeated every analysis step. No allocated memory is retained
* by the state struct, so no cleanup call is required.
*/
-void tonality_analysis_init(TonalityAnalysisState *analysis, opus_int32 Fs);
+void tonality_analysis_init(TonalityAnalysisState *analysis);
/** Reset a TonalityAnalysisState stuct.
*
diff --git a/thirdparty/opus/celt/_kiss_fft_guts.h b/thirdparty/opus/celt/_kiss_fft_guts.h
index 17392b3e90..5e3d58fd66 100644
--- a/thirdparty/opus/celt/_kiss_fft_guts.h
+++ b/thirdparty/opus/celt/_kiss_fft_guts.h
@@ -58,12 +58,12 @@
# define S_MUL(a,b) MULT16_32_Q15(b, a)
# define C_MUL(m,a,b) \
- do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
- (m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
+ do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
+ (m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
# define C_MULC(m,a,b) \
- do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
- (m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
+ do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
+ (m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
# define C_MULBYSCALAR( c, s ) \
do{ (c).r = S_MUL( (c).r , s ) ;\
@@ -77,17 +77,17 @@
DIVSCALAR( (c).i , div); }while (0)
#define C_ADD( res, a,b)\
- do {(res).r=ADD32_ovflw((a).r,(b).r); (res).i=ADD32_ovflw((a).i,(b).i); \
+ do {(res).r=ADD32((a).r,(b).r); (res).i=ADD32((a).i,(b).i); \
}while(0)
#define C_SUB( res, a,b)\
- do {(res).r=SUB32_ovflw((a).r,(b).r); (res).i=SUB32_ovflw((a).i,(b).i); \
+ do {(res).r=SUB32((a).r,(b).r); (res).i=SUB32((a).i,(b).i); \
}while(0)
#define C_ADDTO( res , a)\
- do {(res).r = ADD32_ovflw((res).r, (a).r); (res).i = ADD32_ovflw((res).i,(a).i);\
+ do {(res).r = ADD32((res).r, (a).r); (res).i = ADD32((res).i,(a).i);\
}while(0)
#define C_SUBFROM( res , a)\
- do {(res).r = ADD32_ovflw((res).r,(a).r); (res).i = SUB32_ovflw((res).i,(a).i); \
+ do {(res).r = ADD32((res).r,(a).r); (res).i = SUB32((res).i,(a).i); \
}while(0)
#if defined(OPUS_ARM_INLINE_ASM)
diff --git a/thirdparty/opus/celt/arch.h b/thirdparty/opus/celt/arch.h
index 08b07db598..8ceab5fe10 100644
--- a/thirdparty/opus/celt/arch.h
+++ b/thirdparty/opus/celt/arch.h
@@ -46,50 +46,25 @@
# endif
# endif
-#if OPUS_GNUC_PREREQ(3, 0)
-#define opus_likely(x) (__builtin_expect(!!(x), 1))
-#define opus_unlikely(x) (__builtin_expect(!!(x), 0))
-#else
-#define opus_likely(x) (!!(x))
-#define opus_unlikely(x) (!!(x))
-#endif
-
#define CELT_SIG_SCALE 32768.f
-#define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__);
-
-#if defined(ENABLE_ASSERTIONS) || defined(ENABLE_HARDENING)
-#ifdef __GNUC__
-__attribute__((noreturn))
-#endif
-void celt_fatal(const char *str, const char *file, int line);
-
-#if defined(CELT_C) && !defined(OVERRIDE_celt_fatal)
+#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__);
+#ifdef ENABLE_ASSERTIONS
#include <stdio.h>
#include <stdlib.h>
#ifdef __GNUC__
__attribute__((noreturn))
#endif
-void celt_fatal(const char *str, const char *file, int line)
+static OPUS_INLINE void _celt_fatal(const char *str, const char *file, int line)
{
fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
abort();
}
-#endif
-
-#define celt_assert(cond) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond);}}
-#define celt_assert2(cond, message) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond "\n" message);}}
-#define MUST_SUCCEED(call) celt_assert((call) == OPUS_OK)
+#define celt_assert(cond) {if (!(cond)) {celt_fatal("assertion failed: " #cond);}}
+#define celt_assert2(cond, message) {if (!(cond)) {celt_fatal("assertion failed: " #cond "\n" message);}}
#else
#define celt_assert(cond)
#define celt_assert2(cond, message)
-#define MUST_SUCCEED(call) do {if((call) != OPUS_OK) {RESTORE_STACK; return OPUS_INTERNAL_ERROR;} } while (0)
-#endif
-
-#if defined(ENABLE_ASSERTIONS)
-#define celt_sig_assert(cond) {if (!(cond)) {CELT_FATAL("signal assertion failed: " #cond);}}
-#else
-#define celt_sig_assert(cond)
#endif
#define IMUL32(a,b) ((a)*(b))
@@ -118,20 +93,14 @@ void celt_fatal(const char *str, const char *file, int line)
typedef opus_int16 opus_val16;
typedef opus_int32 opus_val32;
-typedef opus_int64 opus_val64;
typedef opus_val32 celt_sig;
typedef opus_val16 celt_norm;
typedef opus_val32 celt_ener;
-#define celt_isnan(x) 0
-
#define Q15ONE 32767
#define SIG_SHIFT 12
-/* Safe saturation value for 32-bit signals. Should be less than
- 2^31*(1-0.85) to avoid blowing up on DC at deemphasis.*/
-#define SIG_SAT (300000000)
#define NORM_SCALING 16384
@@ -160,7 +129,7 @@ static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
#ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR
#include "arm/fixed_arm64.h"
-#elif defined (OPUS_ARM_INLINE_EDSP)
+#elif OPUS_ARM_INLINE_EDSP
#include "arm/fixed_armv5e.h"
#elif defined (OPUS_ARM_INLINE_ASM)
#include "arm/fixed_armv4.h"
@@ -178,7 +147,6 @@ static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
typedef float opus_val16;
typedef float opus_val32;
-typedef float opus_val64;
typedef float celt_sig;
typedef float celt_norm;
@@ -218,7 +186,6 @@ static OPUS_INLINE int celt_isnan(float x)
#define NEG16(x) (-(x))
#define NEG32(x) (-(x))
-#define NEG32_ovflw(x) (-(x))
#define EXTRACT16(x) (x)
#define EXTEND32(x) (x)
#define SHR16(a,shift) (a)
@@ -235,7 +202,6 @@ static OPUS_INLINE int celt_isnan(float x)
#define SATURATE16(x) (x)
#define ROUND16(a,shift) (a)
-#define SROUND16(a,shift) (a)
#define HALF16(x) (.5f*(x))
#define HALF32(x) (.5f*(x))
@@ -243,8 +209,6 @@ static OPUS_INLINE int celt_isnan(float x)
#define SUB16(a,b) ((a)-(b))
#define ADD32(a,b) ((a)+(b))
#define SUB32(a,b) ((a)-(b))
-#define ADD32_ovflw(a,b) ((a)+(b))
-#define SUB32_ovflw(a,b) ((a)-(b))
#define MULT16_16_16(a,b) ((a)*(b))
#define MULT16_16(a,b) ((opus_val32)(a)*(opus_val32)(b))
#define MAC16_16(c,a,b) ((c)+(opus_val32)(a)*(opus_val32)(b))
@@ -279,9 +243,9 @@ static OPUS_INLINE int celt_isnan(float x)
#ifndef GLOBAL_STACK_SIZE
#ifdef FIXED_POINT
-#define GLOBAL_STACK_SIZE 120000
+#define GLOBAL_STACK_SIZE 100000
#else
-#define GLOBAL_STACK_SIZE 120000
+#define GLOBAL_STACK_SIZE 100000
#endif
#endif
diff --git a/thirdparty/opus/celt/arm/arm2gnu.pl b/thirdparty/opus/celt/arm/arm2gnu.pl
index a2895f7445..6c922ac819 100755
--- a/thirdparty/opus/celt/arm/arm2gnu.pl
+++ b/thirdparty/opus/celt/arm/arm2gnu.pl
@@ -164,11 +164,11 @@ while (<>) {
$prefix = "";
if ($proc)
{
- $prefix = $prefix.sprintf("\t.type\t%s, %%function", $proc) unless ($apple);
+ $prefix = $prefix.sprintf("\t.type\t%s, %%function; ",$proc) unless ($apple);
# Make sure we $prefix isn't empty here (for the $apple case).
# We handle mangling the label here, make sure it doesn't match
# the label handling below (if $prefix would be empty).
- $prefix = $prefix."; ";
+ $prefix = "; ";
push(@proc_stack, $proc);
s/^[A-Za-z_\.]\w+/$symprefix$&:/;
}
diff --git a/thirdparty/opus/celt/arm/arm_celt_map.c b/thirdparty/opus/celt/arm/arm_celt_map.c
index ca988b66f5..4d4d069a86 100644
--- a/thirdparty/opus/celt/arm/arm_celt_map.c
+++ b/thirdparty/opus/celt/arm/arm_celt_map.c
@@ -35,29 +35,12 @@
#if defined(OPUS_HAVE_RTCD)
-# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
-opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N) = {
- celt_inner_prod_c, /* ARMv4 */
- celt_inner_prod_c, /* EDSP */
- celt_inner_prod_c, /* Media */
- celt_inner_prod_neon /* NEON */
-};
-
-void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
- int N, opus_val32 *xy1, opus_val32 *xy2) = {
- dual_inner_prod_c, /* ARMv4 */
- dual_inner_prod_c, /* EDSP */
- dual_inner_prod_c, /* Media */
- dual_inner_prod_neon /* NEON */
-};
-# endif
-
# if defined(FIXED_POINT)
# if ((defined(OPUS_ARM_MAY_HAVE_NEON) && !defined(OPUS_ARM_PRESUME_NEON)) || \
(defined(OPUS_ARM_MAY_HAVE_MEDIA) && !defined(OPUS_ARM_PRESUME_MEDIA)) || \
(defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP)))
opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
- const opus_val16 *, opus_val32 *, int, int, int) = {
+ const opus_val16 *, opus_val32 *, int , int) = {
celt_pitch_xcorr_c, /* ARMv4 */
MAY_HAVE_EDSP(celt_pitch_xcorr), /* EDSP */
MAY_HAVE_MEDIA(celt_pitch_xcorr), /* Media */
@@ -68,7 +51,7 @@ opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
# else /* !FIXED_POINT */
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
void (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
- const opus_val16 *, opus_val32 *, int, int, int) = {
+ const opus_val16 *, opus_val32 *, int, int) = {
celt_pitch_xcorr_c, /* ARMv4 */
celt_pitch_xcorr_c, /* EDSP */
celt_pitch_xcorr_c, /* Media */
diff --git a/thirdparty/opus/celt/arm/celt_fft_ne10.c b/thirdparty/opus/celt/arm/celt_ne10_fft.c
index ea5fd7808b..42d96a7117 100644
--- a/thirdparty/opus/celt/arm/celt_fft_ne10.c
+++ b/thirdparty/opus/celt/arm/celt_ne10_fft.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/**
- @file celt_fft_ne10.c
+ @file celt_ne10_fft.c
@brief ARM Neon optimizations for fft using NE10 library
*/
@@ -36,6 +36,7 @@
#endif
#endif
+#include <NE10_init.h>
#include <NE10_dsp.h>
#include "os_support.h"
#include "kiss_fft.h"
diff --git a/thirdparty/opus/celt/arm/celt_mdct_ne10.c b/thirdparty/opus/celt/arm/celt_ne10_mdct.c
index 3531d02d10..293c3efd7a 100644
--- a/thirdparty/opus/celt/arm/celt_mdct_ne10.c
+++ b/thirdparty/opus/celt/arm/celt_ne10_mdct.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/**
- @file celt_mdct_ne10.c
+ @file celt_ne10_mdct.c
@brief ARM Neon optimizations for mdct using NE10 library
*/
diff --git a/thirdparty/opus/celt/arm/celt_neon_intr.c b/thirdparty/opus/celt/arm/celt_neon_intr.c
index effda769d0..47bbe3dc22 100644
--- a/thirdparty/opus/celt/arm/celt_neon_intr.c
+++ b/thirdparty/opus/celt/arm/celt_neon_intr.c
@@ -191,21 +191,121 @@ static void xcorr_kernel_neon_float(const float32_t *x, const float32_t *y,
vst1q_f32(sum, SUMM);
}
+/*
+ * Function: xcorr_kernel_neon_float_process1
+ * ---------------------------------
+ * Computes single correlation values and stores in *sum
+ */
+static void xcorr_kernel_neon_float_process1(const float32_t *x,
+ const float32_t *y, float32_t *sum, int len) {
+ float32x4_t XX[4];
+ float32x4_t YY[4];
+ float32x2_t XX_2;
+ float32x2_t YY_2;
+ float32x4_t SUMM;
+ float32x2_t SUMM_2[2];
+ const float32_t *xi = x;
+ const float32_t *yi = y;
+
+ SUMM = vdupq_n_f32(0);
+
+ /* Work on 16 values per iteration */
+ while (len >= 16) {
+ XX[0] = vld1q_f32(xi);
+ xi += 4;
+ XX[1] = vld1q_f32(xi);
+ xi += 4;
+ XX[2] = vld1q_f32(xi);
+ xi += 4;
+ XX[3] = vld1q_f32(xi);
+ xi += 4;
+
+ YY[0] = vld1q_f32(yi);
+ yi += 4;
+ YY[1] = vld1q_f32(yi);
+ yi += 4;
+ YY[2] = vld1q_f32(yi);
+ yi += 4;
+ YY[3] = vld1q_f32(yi);
+ yi += 4;
+
+ SUMM = vmlaq_f32(SUMM, YY[0], XX[0]);
+ SUMM = vmlaq_f32(SUMM, YY[1], XX[1]);
+ SUMM = vmlaq_f32(SUMM, YY[2], XX[2]);
+ SUMM = vmlaq_f32(SUMM, YY[3], XX[3]);
+ len -= 16;
+ }
+
+ /* Work on 8 values */
+ if (len >= 8) {
+ XX[0] = vld1q_f32(xi);
+ xi += 4;
+ XX[1] = vld1q_f32(xi);
+ xi += 4;
+
+ YY[0] = vld1q_f32(yi);
+ yi += 4;
+ YY[1] = vld1q_f32(yi);
+ yi += 4;
+
+ SUMM = vmlaq_f32(SUMM, YY[0], XX[0]);
+ SUMM = vmlaq_f32(SUMM, YY[1], XX[1]);
+ len -= 8;
+ }
+
+ /* Work on 4 values */
+ if (len >= 4) {
+ XX[0] = vld1q_f32(xi);
+ xi += 4;
+ YY[0] = vld1q_f32(yi);
+ yi += 4;
+ SUMM = vmlaq_f32(SUMM, YY[0], XX[0]);
+ len -= 4;
+ }
+
+ /* Start accumulating results */
+ SUMM_2[0] = vget_low_f32(SUMM);
+ if (len >= 2) {
+ /* While at it, consume 2 more values if available */
+ XX_2 = vld1_f32(xi);
+ xi += 2;
+ YY_2 = vld1_f32(yi);
+ yi += 2;
+ SUMM_2[0] = vmla_f32(SUMM_2[0], YY_2, XX_2);
+ len -= 2;
+ }
+ SUMM_2[1] = vget_high_f32(SUMM);
+ SUMM_2[0] = vadd_f32(SUMM_2[0], SUMM_2[1]);
+ SUMM_2[0] = vpadd_f32(SUMM_2[0], SUMM_2[0]);
+ /* Ok, now we have result accumulated in SUMM_2[0].0 */
+
+ if (len > 0) {
+ /* Case when you have one value left */
+ XX_2 = vld1_dup_f32(xi);
+ YY_2 = vld1_dup_f32(yi);
+ SUMM_2[0] = vmla_f32(SUMM_2[0], XX_2, YY_2);
+ }
+
+ vst1_lane_f32(sum, SUMM_2[0], 0);
+}
+
void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y,
- opus_val32 *xcorr, int len, int max_pitch, int arch) {
+ opus_val32 *xcorr, int len, int max_pitch) {
int i;
- (void)arch;
celt_assert(max_pitch > 0);
- celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
+ celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
for (i = 0; i < (max_pitch-3); i += 4) {
xcorr_kernel_neon_float((const float32_t *)_x, (const float32_t *)_y+i,
(float32_t *)xcorr+i, len);
}
- /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
+ /* In case max_pitch isn't multiple of 4
+ * compute single correlation value per iteration
+ */
for (; i < max_pitch; i++) {
- xcorr[i] = celt_inner_prod_neon(_x, _y+i, len);
+ xcorr_kernel_neon_float_process1((const float32_t *)_x,
+ (const float32_t *)_y+i, (float32_t *)xcorr+i, len);
}
}
#endif
diff --git a/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S
index 10668e54a5..5b2ee55a10 100644
--- a/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S
+++ b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S
@@ -44,7 +44,7 @@
.if OPUS_ARM_MAY_HAVE_NEON
@ Compute sum[k]=sum(x[j]*y[j+k],j=0...len-1), k=0...3
- .type xcorr_kernel_neon, %function; xcorr_kernel_neon: @ PROC
+; xcorr_kernel_neon: @ PROC
xcorr_kernel_neon_start:
@ input:
@ r3 = int len
@@ -156,8 +156,8 @@ xcorr_kernel_neon_process1:
.size xcorr_kernel_neon, .-xcorr_kernel_neon @ ENDP
@ opus_val32 celt_pitch_xcorr_neon(opus_val16 *_x, opus_val16 *_y,
-@ opus_val32 *xcorr, int len, int max_pitch, int arch)
- .type celt_pitch_xcorr_neon, %function; celt_pitch_xcorr_neon: @ PROC
+@ opus_val32 *xcorr, int len, int max_pitch)
+; celt_pitch_xcorr_neon: @ PROC
@ input:
@ r0 = opus_val16 *_x
@ r1 = opus_val16 *_y
@@ -171,8 +171,6 @@ xcorr_kernel_neon_process1:
@ r6 = int max_pitch
@ r12 = int j
@ q15 = int maxcorr[4] (q15 is not used by xcorr_kernel_neon())
- @ ignored:
- @ int arch
STMFD sp!, {r4-r6, lr}
LDR r6, [sp, #16]
VMOV.S32 q15, #1
@@ -262,7 +260,7 @@ celt_pitch_xcorr_neon_done:
@ This will get used on ARMv7 devices without NEON, so it has been optimized
@ to take advantage of dual-issuing where possible.
- .type xcorr_kernel_edsp, %function; xcorr_kernel_edsp: @ PROC
+; xcorr_kernel_edsp: @ PROC
xcorr_kernel_edsp_start:
@ input:
@ r3 = int len
@@ -346,7 +344,7 @@ xcorr_kernel_edsp_done:
LDMFD sp!, {r2,r4,r5,pc}
.size xcorr_kernel_edsp, .-xcorr_kernel_edsp @ ENDP
- .type celt_pitch_xcorr_edsp, %function; celt_pitch_xcorr_edsp: @ PROC
+; celt_pitch_xcorr_edsp: @ PROC
@ input:
@ r0 = opus_val16 *_x (must be 32-bit aligned)
@ r1 = opus_val16 *_y (only needs to be 16-bit aligned)
@@ -363,8 +361,6 @@ xcorr_kernel_edsp_done:
@ r9 = opus_val32 sum3
@ r1 = int max_pitch
@ r12 = int j
- @ ignored:
- @ int arch
STMFD sp!, {r4-r11, lr}
MOV r5, r1
LDR r1, [sp, #36]
diff --git a/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s
index 6e873afc37..f96e0a88bb 100644
--- a/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s
+++ b/thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s
@@ -153,7 +153,7 @@ xcorr_kernel_neon_process1
ENDP
; opus_val32 celt_pitch_xcorr_neon(opus_val16 *_x, opus_val16 *_y,
-; opus_val32 *xcorr, int len, int max_pitch, int arch)
+; opus_val32 *xcorr, int len, int max_pitch)
celt_pitch_xcorr_neon PROC
; input:
; r0 = opus_val16 *_x
@@ -168,8 +168,6 @@ celt_pitch_xcorr_neon PROC
; r6 = int max_pitch
; r12 = int j
; q15 = int maxcorr[4] (q15 is not used by xcorr_kernel_neon())
- ; ignored:
- ; int arch
STMFD sp!, {r4-r6, lr}
LDR r6, [sp, #16]
VMOV.S32 q15, #1
@@ -360,8 +358,6 @@ celt_pitch_xcorr_edsp PROC
; r9 = opus_val32 sum3
; r1 = int max_pitch
; r12 = int j
- ; ignored:
- ; int arch
STMFD sp!, {r4-r11, lr}
MOV r5, r1
LDR r1, [sp, #36]
diff --git a/thirdparty/opus/celt/arm/fft_arm.h b/thirdparty/opus/celt/arm/fft_arm.h
index 0b78175f3a..0cb55d8e22 100644
--- a/thirdparty/opus/celt/arm/fft_arm.h
+++ b/thirdparty/opus/celt/arm/fft_arm.h
@@ -34,6 +34,7 @@
#if !defined(FFT_ARM_H)
#define FFT_ARM_H
+#include "config.h"
#include "kiss_fft.h"
#if defined(HAVE_ARM_NE10)
diff --git a/thirdparty/opus/celt/arm/fixed_armv4.h b/thirdparty/opus/celt/arm/fixed_armv4.h
index d84888a772..efb3b1896a 100644
--- a/thirdparty/opus/celt/arm/fixed_armv4.h
+++ b/thirdparty/opus/celt/arm/fixed_armv4.h
@@ -37,7 +37,7 @@ static OPUS_INLINE opus_val32 MULT16_32_Q16_armv4(opus_val16 a, opus_val32 b)
"#MULT16_32_Q16\n\t"
"smull %0, %1, %2, %3\n\t"
: "=&r"(rd_lo), "=&r"(rd_hi)
- : "%r"(b),"r"(SHL32(a,16))
+ : "%r"(b),"r"(a<<16)
);
return rd_hi;
}
@@ -54,10 +54,10 @@ static OPUS_INLINE opus_val32 MULT16_32_Q15_armv4(opus_val16 a, opus_val32 b)
"#MULT16_32_Q15\n\t"
"smull %0, %1, %2, %3\n\t"
: "=&r"(rd_lo), "=&r"(rd_hi)
- : "%r"(b), "r"(SHL32(a,16))
+ : "%r"(b), "r"(a<<16)
);
/*We intentionally don't OR in the high bit of rd_lo for speed.*/
- return SHL32(rd_hi,1);
+ return rd_hi<<1;
}
#define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv4(a, b))
diff --git a/thirdparty/opus/celt/arm/fixed_armv5e.h b/thirdparty/opus/celt/arm/fixed_armv5e.h
index 6bf73cbace..36a6321101 100644
--- a/thirdparty/opus/celt/arm/fixed_armv5e.h
+++ b/thirdparty/opus/celt/arm/fixed_armv5e.h
@@ -59,7 +59,7 @@ static OPUS_INLINE opus_val32 MULT16_32_Q15_armv5e(opus_val16 a, opus_val32 b)
: "=r"(res)
: "r"(b), "r"(a)
);
- return SHL32(res,1);
+ return res<<1;
}
#define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv5e(a, b))
@@ -76,7 +76,7 @@ static OPUS_INLINE opus_val32 MAC16_32_Q15_armv5e(opus_val32 c, opus_val16 a,
"#MAC16_32_Q15\n\t"
"smlawb %0, %1, %2, %3;\n"
: "=r"(res)
- : "r"(SHL32(b,1)), "r"(a), "r"(c)
+ : "r"(b<<1), "r"(a), "r"(c)
);
return res;
}
diff --git a/thirdparty/opus/celt/arm/mdct_arm.h b/thirdparty/opus/celt/arm/mdct_arm.h
index 14200bac4b..49cbb44576 100644
--- a/thirdparty/opus/celt/arm/mdct_arm.h
+++ b/thirdparty/opus/celt/arm/mdct_arm.h
@@ -33,6 +33,7 @@
#if !defined(MDCT_ARM_H)
#define MDCT_ARM_H
+#include "config.h"
#include "mdct.h"
#if defined(HAVE_ARM_NE10)
diff --git a/thirdparty/opus/celt/arm/pitch_arm.h b/thirdparty/opus/celt/arm/pitch_arm.h
index bed8b04eac..14331169ee 100644
--- a/thirdparty/opus/celt/arm/pitch_arm.h
+++ b/thirdparty/opus/celt/arm/pitch_arm.h
@@ -30,47 +30,11 @@
# include "armcpu.h"
-# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N);
-void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01,
- const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2);
-
-# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
-# define OVERRIDE_CELT_INNER_PROD (1)
-# define OVERRIDE_DUAL_INNER_PROD (1)
-# define celt_inner_prod(x, y, N, arch) ((void)(arch), PRESUME_NEON(celt_inner_prod)(x, y, N))
-# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), PRESUME_NEON(dual_inner_prod)(x, y01, y02, N, xy1, xy2))
-# endif
-# endif
-
-# if !defined(OVERRIDE_CELT_INNER_PROD)
-# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
-extern opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N);
-# define OVERRIDE_CELT_INNER_PROD (1)
-# define celt_inner_prod(x, y, N, arch) ((*CELT_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y, N))
-# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
-# define OVERRIDE_CELT_INNER_PROD (1)
-# define celt_inner_prod(x, y, N, arch) ((void)(arch), celt_inner_prod_neon(x, y, N))
-# endif
-# endif
-
-# if !defined(OVERRIDE_DUAL_INNER_PROD)
-# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
-extern void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x,
- const opus_val16 *y01, const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2);
-# define OVERRIDE_DUAL_INNER_PROD (1)
-# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((*DUAL_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y01, y02, N, xy1, xy2))
-# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
-# define OVERRIDE_DUAL_INNER_PROD (1)
-# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), dual_inner_prod_neon(x, y01, y02, N, xy1, xy2))
-# endif
-# endif
-
# if defined(FIXED_POINT)
# if defined(OPUS_ARM_MAY_HAVE_NEON)
opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y,
- opus_val32 *xcorr, int len, int max_pitch, int arch);
+ opus_val32 *xcorr, int len, int max_pitch);
# endif
# if defined(OPUS_ARM_MAY_HAVE_MEDIA)
@@ -79,7 +43,7 @@ opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y,
# if defined(OPUS_ARM_MAY_HAVE_EDSP)
opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y,
- opus_val32 *xcorr, int len, int max_pitch, int arch);
+ opus_val32 *xcorr, int len, int max_pitch);
# endif
# if defined(OPUS_HAVE_RTCD) && \
@@ -88,17 +52,18 @@ opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y,
(defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP)))
extern opus_val32
(*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
- const opus_val16 *, opus_val32 *, int, int, int);
+ const opus_val16 *, opus_val32 *, int, int);
# define OVERRIDE_PITCH_XCORR (1)
# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
- xcorr, len, max_pitch, arch))
+ xcorr, len, max_pitch))
# elif defined(OPUS_ARM_PRESUME_EDSP) || \
defined(OPUS_ARM_PRESUME_MEDIA) || \
defined(OPUS_ARM_PRESUME_NEON)
# define OVERRIDE_PITCH_XCORR (1)
-# define celt_pitch_xcorr (PRESUME_NEON(celt_pitch_xcorr))
+# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
+ ((void)(arch),PRESUME_NEON(celt_pitch_xcorr)(_x, _y, xcorr, len, max_pitch))
# endif
@@ -134,24 +99,25 @@ extern void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])(
/* Float case */
#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y,
- opus_val32 *xcorr, int len, int max_pitch, int arch);
+ opus_val32 *xcorr, int len, int max_pitch);
#endif
# if defined(OPUS_HAVE_RTCD) && \
(defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
extern void
(*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
- const opus_val16 *, opus_val32 *, int, int, int);
+ const opus_val16 *, opus_val32 *, int, int);
# define OVERRIDE_PITCH_XCORR (1)
# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
- xcorr, len, max_pitch, arch))
+ xcorr, len, max_pitch))
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
# define OVERRIDE_PITCH_XCORR (1)
-# define celt_pitch_xcorr celt_pitch_xcorr_float_neon
+# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
+ ((void)(arch),celt_pitch_xcorr_float_neon(_x, _y, xcorr, len, max_pitch))
# endif
diff --git a/thirdparty/opus/celt/arm/pitch_neon_intr.c b/thirdparty/opus/celt/arm/pitch_neon_intr.c
deleted file mode 100644
index 1ac38c433a..0000000000
--- a/thirdparty/opus/celt/arm/pitch_neon_intr.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/***********************************************************************
-Copyright (c) 2017 Google Inc.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <arm_neon.h>
-#include "pitch.h"
-
-#ifdef FIXED_POINT
-
-opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N)
-{
- int i;
- opus_val32 xy;
- int16x8_t x_s16x8, y_s16x8;
- int32x4_t xy_s32x4 = vdupq_n_s32(0);
- int64x2_t xy_s64x2;
- int64x1_t xy_s64x1;
-
- for (i = 0; i < N - 7; i += 8) {
- x_s16x8 = vld1q_s16(&x[i]);
- y_s16x8 = vld1q_s16(&y[i]);
- xy_s32x4 = vmlal_s16(xy_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y_s16x8));
- xy_s32x4 = vmlal_s16(xy_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y_s16x8));
- }
-
- if (N - i >= 4) {
- const int16x4_t x_s16x4 = vld1_s16(&x[i]);
- const int16x4_t y_s16x4 = vld1_s16(&y[i]);
- xy_s32x4 = vmlal_s16(xy_s32x4, x_s16x4, y_s16x4);
- i += 4;
- }
-
- xy_s64x2 = vpaddlq_s32(xy_s32x4);
- xy_s64x1 = vadd_s64(vget_low_s64(xy_s64x2), vget_high_s64(xy_s64x2));
- xy = vget_lane_s32(vreinterpret_s32_s64(xy_s64x1), 0);
-
- for (; i < N; i++) {
- xy = MAC16_16(xy, x[i], y[i]);
- }
-
-#ifdef OPUS_CHECK_ASM
- celt_assert(celt_inner_prod_c(x, y, N) == xy);
-#endif
-
- return xy;
-}
-
-void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
- int N, opus_val32 *xy1, opus_val32 *xy2)
-{
- int i;
- opus_val32 xy01, xy02;
- int16x8_t x_s16x8, y01_s16x8, y02_s16x8;
- int32x4_t xy01_s32x4 = vdupq_n_s32(0);
- int32x4_t xy02_s32x4 = vdupq_n_s32(0);
- int64x2_t xy01_s64x2, xy02_s64x2;
- int64x1_t xy01_s64x1, xy02_s64x1;
-
- for (i = 0; i < N - 7; i += 8) {
- x_s16x8 = vld1q_s16(&x[i]);
- y01_s16x8 = vld1q_s16(&y01[i]);
- y02_s16x8 = vld1q_s16(&y02[i]);
- xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y01_s16x8));
- xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y02_s16x8));
- xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y01_s16x8));
- xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y02_s16x8));
- }
-
- if (N - i >= 4) {
- const int16x4_t x_s16x4 = vld1_s16(&x[i]);
- const int16x4_t y01_s16x4 = vld1_s16(&y01[i]);
- const int16x4_t y02_s16x4 = vld1_s16(&y02[i]);
- xy01_s32x4 = vmlal_s16(xy01_s32x4, x_s16x4, y01_s16x4);
- xy02_s32x4 = vmlal_s16(xy02_s32x4, x_s16x4, y02_s16x4);
- i += 4;
- }
-
- xy01_s64x2 = vpaddlq_s32(xy01_s32x4);
- xy02_s64x2 = vpaddlq_s32(xy02_s32x4);
- xy01_s64x1 = vadd_s64(vget_low_s64(xy01_s64x2), vget_high_s64(xy01_s64x2));
- xy02_s64x1 = vadd_s64(vget_low_s64(xy02_s64x2), vget_high_s64(xy02_s64x2));
- xy01 = vget_lane_s32(vreinterpret_s32_s64(xy01_s64x1), 0);
- xy02 = vget_lane_s32(vreinterpret_s32_s64(xy02_s64x1), 0);
-
- for (; i < N; i++) {
- xy01 = MAC16_16(xy01, x[i], y01[i]);
- xy02 = MAC16_16(xy02, x[i], y02[i]);
- }
- *xy1 = xy01;
- *xy2 = xy02;
-
-#ifdef OPUS_CHECK_ASM
- {
- opus_val32 xy1_c, xy2_c;
- dual_inner_prod_c(x, y01, y02, N, &xy1_c, &xy2_c);
- celt_assert(xy1_c == *xy1);
- celt_assert(xy2_c == *xy2);
- }
-#endif
-}
-
-#else /* !FIXED_POINT */
-
-/* ========================================================================== */
-
-#ifdef OPUS_CHECK_ASM
-
-/* This part of code simulates floating-point NEON operations. */
-
-/* celt_inner_prod_neon_float_c_simulation() simulates the floating-point */
-/* operations of celt_inner_prod_neon(), and both functions should have bit */
-/* exact output. */
-static opus_val32 celt_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y, int N)
-{
- int i;
- opus_val32 xy, xy0 = 0, xy1 = 0, xy2 = 0, xy3 = 0;
- for (i = 0; i < N - 3; i += 4) {
- xy0 = MAC16_16(xy0, x[i + 0], y[i + 0]);
- xy1 = MAC16_16(xy1, x[i + 1], y[i + 1]);
- xy2 = MAC16_16(xy2, x[i + 2], y[i + 2]);
- xy3 = MAC16_16(xy3, x[i + 3], y[i + 3]);
- }
- xy0 += xy2;
- xy1 += xy3;
- xy = xy0 + xy1;
- for (; i < N; i++) {
- xy = MAC16_16(xy, x[i], y[i]);
- }
- return xy;
-}
-
-/* dual_inner_prod_neon_float_c_simulation() simulates the floating-point */
-/* operations of dual_inner_prod_neon(), and both functions should have bit */
-/* exact output. */
-static void dual_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
- int N, opus_val32 *xy1, opus_val32 *xy2)
-{
- int i;
- opus_val32 xy01, xy02, xy01_0 = 0, xy01_1 = 0, xy01_2 = 0, xy01_3 = 0, xy02_0 = 0, xy02_1 = 0, xy02_2 = 0, xy02_3 = 0;
- for (i = 0; i < N - 3; i += 4) {
- xy01_0 = MAC16_16(xy01_0, x[i + 0], y01[i + 0]);
- xy01_1 = MAC16_16(xy01_1, x[i + 1], y01[i + 1]);
- xy01_2 = MAC16_16(xy01_2, x[i + 2], y01[i + 2]);
- xy01_3 = MAC16_16(xy01_3, x[i + 3], y01[i + 3]);
- xy02_0 = MAC16_16(xy02_0, x[i + 0], y02[i + 0]);
- xy02_1 = MAC16_16(xy02_1, x[i + 1], y02[i + 1]);
- xy02_2 = MAC16_16(xy02_2, x[i + 2], y02[i + 2]);
- xy02_3 = MAC16_16(xy02_3, x[i + 3], y02[i + 3]);
- }
- xy01_0 += xy01_2;
- xy02_0 += xy02_2;
- xy01_1 += xy01_3;
- xy02_1 += xy02_3;
- xy01 = xy01_0 + xy01_1;
- xy02 = xy02_0 + xy02_1;
- for (; i < N; i++) {
- xy01 = MAC16_16(xy01, x[i], y01[i]);
- xy02 = MAC16_16(xy02, x[i], y02[i]);
- }
- *xy1 = xy01;
- *xy2 = xy02;
-}
-
-#endif /* OPUS_CHECK_ASM */
-
-/* ========================================================================== */
-
-opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N)
-{
- int i;
- opus_val32 xy;
- float32x4_t xy_f32x4 = vdupq_n_f32(0);
- float32x2_t xy_f32x2;
-
- for (i = 0; i < N - 7; i += 8) {
- float32x4_t x_f32x4, y_f32x4;
- x_f32x4 = vld1q_f32(&x[i]);
- y_f32x4 = vld1q_f32(&y[i]);
- xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
- x_f32x4 = vld1q_f32(&x[i + 4]);
- y_f32x4 = vld1q_f32(&y[i + 4]);
- xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
- }
-
- if (N - i >= 4) {
- const float32x4_t x_f32x4 = vld1q_f32(&x[i]);
- const float32x4_t y_f32x4 = vld1q_f32(&y[i]);
- xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
- i += 4;
- }
-
- xy_f32x2 = vadd_f32(vget_low_f32(xy_f32x4), vget_high_f32(xy_f32x4));
- xy_f32x2 = vpadd_f32(xy_f32x2, xy_f32x2);
- xy = vget_lane_f32(xy_f32x2, 0);
-
- for (; i < N; i++) {
- xy = MAC16_16(xy, x[i], y[i]);
- }
-
-#ifdef OPUS_CHECK_ASM
- celt_assert(ABS32(celt_inner_prod_neon_float_c_simulation(x, y, N) - xy) <= VERY_SMALL);
-#endif
-
- return xy;
-}
-
-void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
- int N, opus_val32 *xy1, opus_val32 *xy2)
-{
- int i;
- opus_val32 xy01, xy02;
- float32x4_t xy01_f32x4 = vdupq_n_f32(0);
- float32x4_t xy02_f32x4 = vdupq_n_f32(0);
- float32x2_t xy01_f32x2, xy02_f32x2;
-
- for (i = 0; i < N - 7; i += 8) {
- float32x4_t x_f32x4, y01_f32x4, y02_f32x4;
- x_f32x4 = vld1q_f32(&x[i]);
- y01_f32x4 = vld1q_f32(&y01[i]);
- y02_f32x4 = vld1q_f32(&y02[i]);
- xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
- xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
- x_f32x4 = vld1q_f32(&x[i + 4]);
- y01_f32x4 = vld1q_f32(&y01[i + 4]);
- y02_f32x4 = vld1q_f32(&y02[i + 4]);
- xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
- xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
- }
-
- if (N - i >= 4) {
- const float32x4_t x_f32x4 = vld1q_f32(&x[i]);
- const float32x4_t y01_f32x4 = vld1q_f32(&y01[i]);
- const float32x4_t y02_f32x4 = vld1q_f32(&y02[i]);
- xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
- xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
- i += 4;
- }
-
- xy01_f32x2 = vadd_f32(vget_low_f32(xy01_f32x4), vget_high_f32(xy01_f32x4));
- xy02_f32x2 = vadd_f32(vget_low_f32(xy02_f32x4), vget_high_f32(xy02_f32x4));
- xy01_f32x2 = vpadd_f32(xy01_f32x2, xy01_f32x2);
- xy02_f32x2 = vpadd_f32(xy02_f32x2, xy02_f32x2);
- xy01 = vget_lane_f32(xy01_f32x2, 0);
- xy02 = vget_lane_f32(xy02_f32x2, 0);
-
- for (; i < N; i++) {
- xy01 = MAC16_16(xy01, x[i], y01[i]);
- xy02 = MAC16_16(xy02, x[i], y02[i]);
- }
- *xy1 = xy01;
- *xy2 = xy02;
-
-#ifdef OPUS_CHECK_ASM
- {
- opus_val32 xy1_c, xy2_c;
- dual_inner_prod_neon_float_c_simulation(x, y01, y02, N, &xy1_c, &xy2_c);
- celt_assert(ABS32(xy1_c - *xy1) <= VERY_SMALL);
- celt_assert(ABS32(xy2_c - *xy2) <= VERY_SMALL);
- }
-#endif
-}
-
-#endif /* FIXED_POINT */
diff --git a/thirdparty/opus/celt/bands.c b/thirdparty/opus/celt/bands.c
index 2702963c37..87eaa6c031 100644
--- a/thirdparty/opus/celt/bands.c
+++ b/thirdparty/opus/celt/bands.c
@@ -65,19 +65,19 @@ opus_uint32 celt_lcg_rand(opus_uint32 seed)
/* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness
with this approximation is important because it has an impact on the bit allocation */
-opus_int16 bitexact_cos(opus_int16 x)
+static opus_int16 bitexact_cos(opus_int16 x)
{
opus_int32 tmp;
opus_int16 x2;
tmp = (4096+((opus_int32)(x)*(x)))>>13;
- celt_sig_assert(tmp<=32767);
+ celt_assert(tmp<=32767);
x2 = tmp;
x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2)))));
- celt_sig_assert(x2<=32766);
+ celt_assert(x2<=32766);
return 1+x2;
}
-int bitexact_log2tan(int isin,int icos)
+static int bitexact_log2tan(int isin,int icos)
{
int lc;
int ls;
@@ -92,11 +92,10 @@ int bitexact_log2tan(int isin,int icos)
#ifdef FIXED_POINT
/* Compute the amplitude (sqrt energy) in each of the bands */
-void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM)
{
int i, c, N;
const opus_int16 *eBands = m->eBands;
- (void)arch;
N = m->shortMdctSize<<LM;
c=0; do {
for (i=0;i<end;i++)
@@ -156,7 +155,7 @@ void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, cel
#else /* FIXED_POINT */
/* Compute the amplitude (sqrt energy) in each of the bands */
-void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM)
{
int i, c, N;
const opus_int16 *eBands = m->eBands;
@@ -165,7 +164,7 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band
for (i=0;i<end;i++)
{
opus_val32 sum;
- sum = 1e-27f + celt_inner_prod(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM, arch);
+ sum = 1e-27f + celt_inner_prod_c(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM);
bandE[i+c*m->nbEBands] = celt_sqrt(sum);
/*printf ("%f ", bandE[i+c*m->nbEBands]);*/
}
@@ -225,9 +224,9 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
#endif
j=M*eBands[i];
band_end = M*eBands[i+1];
- lg = SATURATE16(ADD32(bandLogE[i], SHL32((opus_val32)eMeans[i],6)));
+ lg = ADD16(bandLogE[i], SHL16((opus_val16)eMeans[i],6));
#ifndef FIXED_POINT
- g = celt_exp2(MIN32(32.f, lg));
+ g = celt_exp2(lg);
#else
/* Handle the integer part of the log energy */
shift = 16-(lg>>DB_SHIFT);
@@ -242,12 +241,12 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
/* Handle extreme gains with negative shift. */
if (shift<0)
{
- /* For shift <= -2 and g > 16384 we'd be likely to overflow, so we're
- capping the gain here, which is equivalent to a cap of 18 on lg.
- This shouldn't trigger unless the bitstream is already corrupted. */
- if (shift <= -2)
+ /* For shift < -2 we'd be likely to overflow, so we're capping
+ the gain here. This shouldn't happen unless the bitstream is
+ already corrupted. */
+ if (shift < -2)
{
- g = 16384;
+ g = 32767;
shift = -2;
}
do {
@@ -282,7 +281,7 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
N0 = m->eBands[i+1]-m->eBands[i];
/* depth in 1/8 bits */
- celt_sig_assert(pulses[i]>=0);
+ celt_assert(pulses[i]>=0);
depth = celt_udiv(1+pulses[i], (m->eBands[i+1]-m->eBands[i]))>>LM;
#ifdef FIXED_POINT
@@ -361,30 +360,6 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
}
}
-/* Compute the weights to use for optimizing normalized distortion across
- channels. We use the amplitude to weight square distortion, which means
- that we use the square root of the value we would have been using if we
- wanted to minimize the MSE in the non-normalized domain. This roughly
- corresponds to some quick-and-dirty perceptual experiments I ran to
- measure inter-aural masking (there doesn't seem to be any published data
- on the topic). */
-static void compute_channel_weights(celt_ener Ex, celt_ener Ey, opus_val16 w[2])
-{
- celt_ener minE;
-#ifdef FIXED_POINT
- int shift;
-#endif
- minE = MIN32(Ex, Ey);
- /* Adjustment to make the weights a bit more conservative. */
- Ex = ADD32(Ex, minE/3);
- Ey = ADD32(Ey, minE/3);
-#ifdef FIXED_POINT
- shift = celt_ilog2(EPSILON+MAX32(Ex, Ey))-14;
-#endif
- w[0] = VSHR32(Ex, shift);
- w[1] = VSHR32(Ey, shift);
-}
-
static void intensity_stereo(const CELTMode *m, celt_norm * OPUS_RESTRICT X, const celt_norm * OPUS_RESTRICT Y, const celt_ener *bandE, int bandID, int N)
{
int i = bandID;
@@ -478,7 +453,7 @@ static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT
/* Decide whether we should spread the pulses in the current frame */
int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
int last_decision, int *hf_average, int *tapset_decision, int update_hf,
- int end, int C, int M, const int *spread_weight)
+ int end, int C, int M)
{
int i, c, N0;
int sum = 0, nbBands=0;
@@ -519,8 +494,8 @@ int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
if (i>m->nbEBands-4)
hf_sum += celt_udiv(32*(tcount[1]+tcount[0]), N);
tmp = (2*tcount[2] >= N) + (2*tcount[1] >= N) + (2*tcount[0] >= N);
- sum += tmp*spread_weight[i];
- nbBands+=spread_weight[i];
+ sum += tmp*256;
+ nbBands++;
}
} while (++c<C);
@@ -544,7 +519,7 @@ int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
/*printf("%d %d %d\n", hf_sum, *hf_average, *tapset_decision);*/
celt_assert(nbBands>0); /* end has to be non-zero */
celt_assert(sum>=0);
- sum = celt_udiv((opus_int32)sum<<8, nbBands);
+ sum = celt_udiv(sum, nbBands);
/* Recursive averaging */
sum = (sum+*average)>>1;
*average = sum;
@@ -672,7 +647,6 @@ static int compute_qn(int N, int b, int offset, int pulse_cap, int stereo)
struct band_ctx {
int encode;
- int resynth;
const CELTMode *m;
int i;
int intensity;
@@ -683,9 +657,6 @@ struct band_ctx {
const celt_ener *bandE;
opus_uint32 seed;
int arch;
- int theta_round;
- int disable_inv;
- int avoid_split_noise;
};
struct split_ctx {
@@ -743,35 +714,8 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
if (qn!=1)
{
if (encode)
- {
- if (!stereo || ctx->theta_round == 0)
- {
- itheta = (itheta*(opus_int32)qn+8192)>>14;
- if (!stereo && ctx->avoid_split_noise && itheta > 0 && itheta < qn)
- {
- /* Check if the selected value of theta will cause the bit allocation
- to inject noise on one side. If so, make sure the energy of that side
- is zero. */
- int unquantized = celt_udiv((opus_int32)itheta*16384, qn);
- imid = bitexact_cos((opus_int16)unquantized);
- iside = bitexact_cos((opus_int16)(16384-unquantized));
- delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid));
- if (delta > *b)
- itheta = qn;
- else if (delta < -*b)
- itheta = 0;
- }
- } else {
- int down;
- /* Bias quantization towards itheta=0 and itheta=16384. */
- int bias = itheta > 8192 ? 32767/qn : -32767/qn;
- down = IMIN(qn-1, IMAX(0, (itheta*(opus_int32)qn + bias)>>14));
- if (ctx->theta_round < 0)
- itheta = down;
- else
- itheta = down+1;
- }
- }
+ itheta = (itheta*(opus_int32)qn+8192)>>14;
+
/* Entropy coding of the angle. We use a uniform pdf for the
time split, a step for stereo, and a triangular one for the rest. */
if (stereo && N>2)
@@ -849,7 +793,7 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
} else if (stereo) {
if (encode)
{
- inv = itheta > 8192 && !ctx->disable_inv;
+ inv = itheta > 8192;
if (inv)
{
int j;
@@ -866,9 +810,6 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
inv = ec_dec_bit_logp(ec, 2);
} else
inv = 0;
- /* inv flag override to avoid problems with downmixing. */
- if (ctx->disable_inv)
- inv = 0;
itheta = 0;
}
qalloc = ec_tell_frac(ec) - tell;
@@ -904,6 +845,11 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y, int b,
celt_norm *lowband_out)
{
+#ifdef RESYNTH
+ int resynth = 1;
+#else
+ int resynth = !ctx->encode;
+#endif
int c;
int stereo;
celt_norm *x = X;
@@ -928,7 +874,7 @@ static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y,
ctx->remaining_bits -= 1<<BITRES;
b-=1<<BITRES;
}
- if (ctx->resynth)
+ if (resynth)
x[0] = sign ? -NORM_SCALING : NORM_SCALING;
x = Y;
} while (++c<1+stereo);
@@ -953,6 +899,11 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
int B0=B;
opus_val16 mid=0, side=0;
unsigned cm=0;
+#ifdef RESYNTH
+ int resynth = 1;
+#else
+ int resynth = !ctx->encode;
+#endif
celt_norm *Y=NULL;
int encode;
const CELTMode *m;
@@ -984,7 +935,8 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
fill = (fill&1)|(fill<<1);
B = (B+1)>>1;
- compute_theta(ctx, &sctx, X, Y, N, &b, B, B0, LM, 0, &fill);
+ compute_theta(ctx, &sctx, X, Y, N, &b, B, B0,
+ LM, 0, &fill);
imid = sctx.imid;
iside = sctx.iside;
delta = sctx.delta;
@@ -1018,20 +970,24 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
rebalance = ctx->remaining_bits;
if (mbits >= sbits)
{
- cm = quant_partition(ctx, X, N, mbits, B, lowband, LM,
+ cm = quant_partition(ctx, X, N, mbits, B,
+ lowband, LM,
MULT16_16_P15(gain,mid), fill);
rebalance = mbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=0)
sbits += rebalance - (3<<BITRES);
- cm |= quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
+ cm |= quant_partition(ctx, Y, N, sbits, B,
+ next_lowband2, LM,
MULT16_16_P15(gain,side), fill>>B)<<(B0>>1);
} else {
- cm = quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
+ cm = quant_partition(ctx, Y, N, sbits, B,
+ next_lowband2, LM,
MULT16_16_P15(gain,side), fill>>B)<<(B0>>1);
rebalance = sbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=16384)
mbits += rebalance - (3<<BITRES);
- cm |= quant_partition(ctx, X, N, mbits, B, lowband, LM,
+ cm |= quant_partition(ctx, X, N, mbits, B,
+ lowband, LM,
MULT16_16_P15(gain,mid), fill);
}
} else {
@@ -1056,14 +1012,18 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
/* Finally do the actual quantization */
if (encode)
{
- cm = alg_quant(X, N, K, spread, B, ec, gain, ctx->resynth, ctx->arch);
+ cm = alg_quant(X, N, K, spread, B, ec
+#ifdef RESYNTH
+ , gain
+#endif
+ );
} else {
cm = alg_unquant(X, N, K, spread, B, ec, gain);
}
} else {
/* If there's no pulse, fill the band anyway */
int j;
- if (ctx->resynth)
+ if (resynth)
{
unsigned cm_mask;
/* B can be as large as 16, so this shift might overflow an int on a
@@ -1120,6 +1080,11 @@ static unsigned quant_band(struct band_ctx *ctx, celt_norm *X,
int recombine=0;
int longBlocks;
unsigned cm=0;
+#ifdef RESYNTH
+ int resynth = 1;
+#else
+ int resynth = !ctx->encode;
+#endif
int k;
int encode;
int tf_change;
@@ -1186,10 +1151,11 @@ static unsigned quant_band(struct band_ctx *ctx, celt_norm *X,
deinterleave_hadamard(lowband, N_B>>recombine, B0<<recombine, longBlocks);
}
- cm = quant_partition(ctx, X, N, b, B, lowband, LM, gain, fill);
+ cm = quant_partition(ctx, X, N, b, B, lowband,
+ LM, gain, fill);
/* This code is used by the decoder and by the resynthesis-enabled encoder */
- if (ctx->resynth)
+ if (resynth)
{
/* Undo the sample reorganization going from time order to frequency order */
if (B0>1)
@@ -1242,6 +1208,11 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
int inv = 0;
opus_val16 mid=0, side=0;
unsigned cm=0;
+#ifdef RESYNTH
+ int resynth = 1;
+#else
+ int resynth = !ctx->encode;
+#endif
int mbits, sbits, delta;
int itheta;
int qalloc;
@@ -1261,7 +1232,8 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
orig_fill = fill;
- compute_theta(ctx, &sctx, X, Y, N, &b, B, B, LM, 1, &fill);
+ compute_theta(ctx, &sctx, X, Y, N, &b, B, B,
+ LM, 1, &fill);
inv = sctx.inv;
imid = sctx.imid;
iside = sctx.iside;
@@ -1309,13 +1281,13 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
sign = 1-2*sign;
/* We use orig_fill here because we want to fold the side, but if
itheta==16384, we'll have cleared the low bits of fill. */
- cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
- lowband_scratch, orig_fill);
+ cm = quant_band(ctx, x2, N, mbits, B, lowband,
+ LM, lowband_out, Q15ONE, lowband_scratch, orig_fill);
/* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse),
and there's no need to worry about mixing with the other channel. */
y2[0] = -sign*x2[1];
y2[1] = sign*x2[0];
- if (ctx->resynth)
+ if (resynth)
{
celt_norm tmp;
X[0] = MULT16_16_Q15(mid, X[0]);
@@ -1342,32 +1314,38 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
{
/* In stereo mode, we do not apply a scaling to the mid because we need the normalized
mid for folding later. */
- cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
- lowband_scratch, fill);
+ cm = quant_band(ctx, X, N, mbits, B,
+ lowband, LM, lowband_out,
+ Q15ONE, lowband_scratch, fill);
rebalance = mbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=0)
sbits += rebalance - (3<<BITRES);
/* For a stereo split, the high bits of fill are always zero, so no
folding will be done to the side. */
- cm |= quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B);
+ cm |= quant_band(ctx, Y, N, sbits, B,
+ NULL, LM, NULL,
+ side, NULL, fill>>B);
} else {
/* For a stereo split, the high bits of fill are always zero, so no
folding will be done to the side. */
- cm = quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B);
+ cm = quant_band(ctx, Y, N, sbits, B,
+ NULL, LM, NULL,
+ side, NULL, fill>>B);
rebalance = sbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=16384)
mbits += rebalance - (3<<BITRES);
/* In stereo mode, we do not apply a scaling to the mid because we need the normalized
mid for folding later. */
- cm |= quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
- lowband_scratch, fill);
+ cm |= quant_band(ctx, X, N, mbits, B,
+ lowband, LM, lowband_out,
+ Q15ONE, lowband_scratch, fill);
}
}
/* This code is used by the decoder and by the resynthesis-enabled encoder */
- if (ctx->resynth)
+ if (resynth)
{
if (N!=2)
stereo_merge(X, Y, mid, N, ctx->arch);
@@ -1381,38 +1359,19 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
return cm;
}
-static void special_hybrid_folding(const CELTMode *m, celt_norm *norm, celt_norm *norm2, int start, int M, int dual_stereo)
-{
- int n1, n2;
- const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
- n1 = M*(eBands[start+1]-eBands[start]);
- n2 = M*(eBands[start+2]-eBands[start+1]);
- /* Duplicate enough of the first band folding data to be able to fold the second band.
- Copies no data for CELT-only mode. */
- OPUS_COPY(&norm[n1], &norm[2*n1 - n2], n2-n1);
- if (dual_stereo)
- OPUS_COPY(&norm2[n1], &norm2[2*n1 - n2], n2-n1);
-}
void quant_all_bands(int encode, const CELTMode *m, int start, int end,
celt_norm *X_, celt_norm *Y_, unsigned char *collapse_masks,
const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
opus_int32 balance, ec_ctx *ec, int LM, int codedBands,
- opus_uint32 *seed, int complexity, int arch, int disable_inv)
+ opus_uint32 *seed, int arch)
{
int i;
opus_int32 remaining_bits;
const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2;
VARDECL(celt_norm, _norm);
- VARDECL(celt_norm, _lowband_scratch);
- VARDECL(celt_norm, X_save);
- VARDECL(celt_norm, Y_save);
- VARDECL(celt_norm, X_save2);
- VARDECL(celt_norm, Y_save2);
- VARDECL(celt_norm, norm_save2);
- int resynth_alloc;
celt_norm *lowband_scratch;
int B;
int M;
@@ -1420,11 +1379,10 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
int update_lowband = 1;
int C = Y_ != NULL ? 2 : 1;
int norm_offset;
- int theta_rdo = encode && Y_!=NULL && !dual_stereo && complexity>=8;
#ifdef RESYNTH
int resynth = 1;
#else
- int resynth = !encode || theta_rdo;
+ int resynth = !encode;
#endif
struct band_ctx ctx;
SAVE_STACK;
@@ -1437,24 +1395,9 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
ALLOC(_norm, C*(M*eBands[m->nbEBands-1]-norm_offset), celt_norm);
norm = _norm;
norm2 = norm + M*eBands[m->nbEBands-1]-norm_offset;
-
- /* For decoding, we can use the last band as scratch space because we don't need that
- scratch space for the last band and we don't care about the data there until we're
- decoding the last band. */
- if (encode && resynth)
- resynth_alloc = M*(eBands[m->nbEBands]-eBands[m->nbEBands-1]);
- else
- resynth_alloc = ALLOC_NONE;
- ALLOC(_lowband_scratch, resynth_alloc, celt_norm);
- if (encode && resynth)
- lowband_scratch = _lowband_scratch;
- else
- lowband_scratch = X_+M*eBands[m->nbEBands-1];
- ALLOC(X_save, resynth_alloc, celt_norm);
- ALLOC(Y_save, resynth_alloc, celt_norm);
- ALLOC(X_save2, resynth_alloc, celt_norm);
- ALLOC(Y_save2, resynth_alloc, celt_norm);
- ALLOC(norm_save2, resynth_alloc, celt_norm);
+ /* We can use the last band as scratch space because we don't need that
+ scratch space for the last band. */
+ lowband_scratch = X_+M*eBands[m->nbEBands-1];
lowband_offset = 0;
ctx.bandE = bandE;
@@ -1465,11 +1408,6 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
ctx.seed = *seed;
ctx.spread = spread;
ctx.arch = arch;
- ctx.disable_inv = disable_inv;
- ctx.resynth = resynth;
- ctx.theta_round = 0;
- /* Avoid injecting noise in the first band on transients. */
- ctx.avoid_split_noise = B > 1;
for (i=start;i<end;i++)
{
opus_int32 tell;
@@ -1492,7 +1430,6 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
else
Y = NULL;
N = M*eBands[i+1]-M*eBands[i];
- celt_assert(N > 0);
tell = ec_tell_frac(ec);
/* Compute how many bits we want to allocate to this band */
@@ -1508,15 +1445,8 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
b = 0;
}
-#ifndef DISABLE_UPDATE_DRAFT
- if (resynth && (M*eBands[i]-N >= M*eBands[start] || i==start+1) && (update_lowband || lowband_offset==0))
- lowband_offset = i;
- if (i == start+1)
- special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
-#else
if (resynth && M*eBands[i]-N >= M*eBands[start] && (update_lowband || lowband_offset==0))
lowband_offset = i;
-#endif
tf_change = tf_res[i];
ctx.tf_change = tf_change;
@@ -1527,7 +1457,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
Y = norm;
lowband_scratch = NULL;
}
- if (last && !theta_rdo)
+ if (i==end-1)
lowband_scratch = NULL;
/* Get a conservative estimate of the collapse_mask's for the bands we're
@@ -1542,11 +1472,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
fold_start = lowband_offset;
while(M*eBands[--fold_start] > effective_lowband+norm_offset);
fold_end = lowband_offset-1;
-#ifndef DISABLE_UPDATE_DRAFT
- while(++fold_end < i && M*eBands[fold_end] < effective_lowband+norm_offset+N);
-#else
while(M*eBands[++fold_end] < effective_lowband+norm_offset+N);
-#endif
x_cm = y_cm = 0;
fold_i = fold_start; do {
x_cm |= collapse_masks[fold_i*C+0];
@@ -1579,79 +1505,13 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
} else {
if (Y!=NULL)
{
- if (theta_rdo && i < intensity)
- {
- ec_ctx ec_save, ec_save2;
- struct band_ctx ctx_save, ctx_save2;
- opus_val32 dist0, dist1;
- unsigned cm, cm2;
- int nstart_bytes, nend_bytes, save_bytes;
- unsigned char *bytes_buf;
- unsigned char bytes_save[1275];
- opus_val16 w[2];
- compute_channel_weights(bandE[i], bandE[i+m->nbEBands], w);
- /* Make a copy. */
- cm = x_cm|y_cm;
- ec_save = *ec;
- ctx_save = ctx;
- OPUS_COPY(X_save, X, N);
- OPUS_COPY(Y_save, Y, N);
- /* Encode and round down. */
- ctx.theta_round = -1;
- x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
- effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
- last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm);
- dist0 = MULT16_32_Q15(w[0], celt_inner_prod(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod(Y_save, Y, N, arch));
-
- /* Save first result. */
- cm2 = x_cm;
- ec_save2 = *ec;
- ctx_save2 = ctx;
- OPUS_COPY(X_save2, X, N);
- OPUS_COPY(Y_save2, Y, N);
- if (!last)
- OPUS_COPY(norm_save2, norm+M*eBands[i]-norm_offset, N);
- nstart_bytes = ec_save.offs;
- nend_bytes = ec_save.storage;
- bytes_buf = ec_save.buf+nstart_bytes;
- save_bytes = nend_bytes-nstart_bytes;
- OPUS_COPY(bytes_save, bytes_buf, save_bytes);
-
- /* Restore */
- *ec = ec_save;
- ctx = ctx_save;
- OPUS_COPY(X, X_save, N);
- OPUS_COPY(Y, Y_save, N);
-#ifndef DISABLE_UPDATE_DRAFT
- if (i == start+1)
- special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
-#endif
- /* Encode and round up. */
- ctx.theta_round = 1;
- x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
- effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
- last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm);
- dist1 = MULT16_32_Q15(w[0], celt_inner_prod(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod(Y_save, Y, N, arch));
- if (dist0 >= dist1) {
- x_cm = cm2;
- *ec = ec_save2;
- ctx = ctx_save2;
- OPUS_COPY(X, X_save2, N);
- OPUS_COPY(Y, Y_save2, N);
- if (!last)
- OPUS_COPY(norm+M*eBands[i]-norm_offset, norm_save2, N);
- OPUS_COPY(bytes_buf, bytes_save, save_bytes);
- }
- } else {
- ctx.theta_round = 0;
- x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
- effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
- last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm);
- }
+ x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+ effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+ last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm);
} else {
x_cm = quant_band(&ctx, X, N, b, B,
effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
- last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm|y_cm);
+ last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm|y_cm);
}
y_cm = x_cm;
}
@@ -1661,9 +1521,6 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
/* Update the folding position only as long as we have 1 bit/sample depth. */
update_lowband = b>(N<<BITRES);
- /* We only need to avoid noise on a split for the first band. After that, we
- have folding. */
- ctx.avoid_split_noise = 0;
}
*seed = ctx.seed;
diff --git a/thirdparty/opus/celt/bands.h b/thirdparty/opus/celt/bands.h
index 422b32cf75..e8bef4bad0 100644
--- a/thirdparty/opus/celt/bands.h
+++ b/thirdparty/opus/celt/bands.h
@@ -36,15 +36,12 @@
#include "entdec.h"
#include "rate.h"
-opus_int16 bitexact_cos(opus_int16 x);
-int bitexact_log2tan(int isin,int icos);
-
/** Compute the amplitude (sqrt energy) in each of the bands
* @param m Mode data
* @param X Spectrum
* @param bandE Square root of the energy for each band (returned)
*/
-void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch);
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM);
/*void compute_noise_energies(const CELTMode *m, const celt_sig *X, const opus_val16 *tonality, celt_ener *bandE);*/
@@ -72,7 +69,7 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
int last_decision, int *hf_average, int *tapset_decision, int update_hf,
- int end, int C, int M, const int *spread_weight);
+ int end, int C, int M);
#ifdef MEASURE_NORM_MSE
void measure_norm_mse(const CELTMode *m, float *X, float *X0, float *bandE, float *bandE0, int M, int N, int C);
@@ -108,7 +105,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
opus_int32 balance, ec_ctx *ec, int M, int codedBands, opus_uint32 *seed,
- int complexity, int arch, int disable_inv);
+ int arch);
void anti_collapse(const CELTMode *m, celt_norm *X_,
unsigned char *collapse_masks, int LM, int C, int size, int start,
diff --git a/thirdparty/opus/celt/celt.c b/thirdparty/opus/celt/celt.c
index 9ce234695c..b121c51a1f 100644
--- a/thirdparty/opus/celt/celt.c
+++ b/thirdparty/opus/celt/celt.c
@@ -111,31 +111,26 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
t = MAC16_32_Q16(x[i], g10, x2);
t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
- t = SATURATE(t, SIG_SAT);
y[i] = t;
x4=SHL32(x[i-T+3],1);
t = MAC16_32_Q16(x[i+1], g10, x1);
t = MAC16_32_Q16(t, g11, ADD32(x0,x2));
t = MAC16_32_Q16(t, g12, ADD32(x4,x3));
- t = SATURATE(t, SIG_SAT);
y[i+1] = t;
x3=SHL32(x[i-T+4],1);
t = MAC16_32_Q16(x[i+2], g10, x0);
t = MAC16_32_Q16(t, g11, ADD32(x4,x1));
t = MAC16_32_Q16(t, g12, ADD32(x3,x2));
- t = SATURATE(t, SIG_SAT);
y[i+2] = t;
x2=SHL32(x[i-T+5],1);
t = MAC16_32_Q16(x[i+3], g10, x4);
t = MAC16_32_Q16(t, g11, ADD32(x3,x0));
t = MAC16_32_Q16(t, g12, ADD32(x2,x1));
- t = SATURATE(t, SIG_SAT);
y[i+3] = t;
x1=SHL32(x[i-T+6],1);
t = MAC16_32_Q16(x[i+4], g10, x3);
t = MAC16_32_Q16(t, g11, ADD32(x2,x4));
t = MAC16_32_Q16(t, g12, ADD32(x1,x0));
- t = SATURATE(t, SIG_SAT);
y[i+4] = t;
}
#ifdef CUSTOM_MODES
@@ -146,7 +141,6 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
t = MAC16_32_Q16(x[i], g10, x2);
t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
- t = SATURATE(t, SIG_SAT);
y[i] = t;
x4=x3;
x3=x2;
@@ -175,7 +169,6 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
+ MULT16_32_Q15(g10,x2)
+ MULT16_32_Q15(g11,ADD32(x1,x3))
+ MULT16_32_Q15(g12,ADD32(x0,x4));
- y[i] = SATURATE(y[i], SIG_SAT);
x4=x3;
x3=x2;
x2=x1;
@@ -207,10 +200,6 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
OPUS_MOVE(y, x, N);
return;
}
- /* When the gain is zero, T0 and/or T1 is set to zero. We need
- to have then be at least 2 to avoid processing garbage data. */
- T0 = IMAX(T0, COMBFILTER_MINPERIOD);
- T1 = IMAX(T1, COMBFILTER_MINPERIOD);
g00 = MULT16_16_P15(g0, gains[tapset0][0]);
g01 = MULT16_16_P15(g0, gains[tapset0][1]);
g02 = MULT16_16_P15(g0, gains[tapset0][2]);
@@ -236,7 +225,6 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
+ MULT16_32_Q15(MULT16_16_Q15(f,g10),x2)
+ MULT16_32_Q15(MULT16_16_Q15(f,g11),ADD32(x1,x3))
+ MULT16_32_Q15(MULT16_16_Q15(f,g12),ADD32(x0,x4));
- y[i] = SATURATE(y[i], SIG_SAT);
x4=x3;
x3=x2;
x2=x1;
@@ -256,16 +244,11 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
}
#endif /* OVERRIDE_comb_filter */
-/* TF change table. Positive values mean better frequency resolution (longer
- effective window), whereas negative values mean better time resolution
- (shorter effective window). The second index is computed as:
- 4*isTransient + 2*tf_select + per_band_flag */
const signed char tf_select_table[4][8] = {
- /*isTransient=0 isTransient=1 */
- {0, -1, 0, -1, 0,-1, 0,-1}, /* 2.5 ms */
- {0, -1, 0, -2, 1, 0, 1,-1}, /* 5 ms */
- {0, -2, 0, -3, 2, 0, 1,-1}, /* 10 ms */
- {0, -2, 0, -3, 3, 0, 1,-1}, /* 20 ms */
+ {0, -1, 0, -1, 0,-1, 0,-1},
+ {0, -1, 0, -2, 1, 0, 1,-1},
+ {0, -2, 0, -3, 2, 0, 1,-1},
+ {0, -2, 0, -3, 3, 0, 1,-1},
};
diff --git a/thirdparty/opus/celt/celt.h b/thirdparty/opus/celt/celt.h
index 24b6b2b520..d1f7eb690d 100644
--- a/thirdparty/opus/celt/celt.h
+++ b/thirdparty/opus/celt/celt.h
@@ -50,8 +50,6 @@ extern "C" {
#define CELTDecoder OpusCustomDecoder
#define CELTMode OpusCustomMode
-#define LEAK_BANDS 19
-
typedef struct {
int valid;
float tonality;
@@ -59,28 +57,18 @@ typedef struct {
float noisiness;
float activity;
float music_prob;
- float music_prob_min;
- float music_prob_max;
- int bandwidth;
- float activity_probability;
- float max_pitch_ratio;
- /* Store as Q6 char to save space. */
- unsigned char leak_boost[LEAK_BANDS];
-} AnalysisInfo;
-
-typedef struct {
- int signalType;
- int offset;
-} SILKInfo;
+ int bandwidth;
+}AnalysisInfo;
#define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
#define __celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr)))
-#define __celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
-
/* Encoder/decoder Requests */
+/* Expose this option again when variable framesize actually works */
+#define OPUS_FRAMESIZE_VARIABLE 5010 /**< Optimize the frame size dynamically */
+
#define CELT_SET_PREDICTION_REQUEST 10002
/** Controls the use of interframe prediction.
@@ -128,9 +116,6 @@ typedef struct {
#define OPUS_SET_ENERGY_MASK_REQUEST 10026
#define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x)
-#define CELT_SET_SILK_INFO_REQUEST 10028
-#define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, __celt_check_silkinfo_ptr(x)
-
/* Encoder stuff */
int celt_encoder_get_size(int channels);
@@ -209,13 +194,6 @@ static OPUS_INLINE int fromOpus(unsigned char c)
extern const signed char tf_select_table[4][8];
-#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
-void validate_celt_decoder(CELTDecoder *st);
-#define VALIDATE_CELT_DECODER(st) validate_celt_decoder(st)
-#else
-#define VALIDATE_CELT_DECODER(st)
-#endif
-
int resampling_factor(opus_int32 rate);
void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
diff --git a/thirdparty/opus/celt/celt_decoder.c b/thirdparty/opus/celt/celt_decoder.c
index e6efce9358..b978bb34d1 100644
--- a/thirdparty/opus/celt/celt_decoder.c
+++ b/thirdparty/opus/celt/celt_decoder.c
@@ -51,14 +51,6 @@
#include "celt_lpc.h"
#include "vq.h"
-/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
- CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
- current value corresponds to a pitch of 66.67 Hz. */
-#define PLC_PITCH_LAG_MAX (720)
-/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
- pitch of 480 Hz. */
-#define PLC_PITCH_LAG_MIN (100)
-
#if defined(SMALL_FOOTPRINT) && defined(FIXED_POINT)
#define NORM_ALIASING_HACK
#endif
@@ -81,7 +73,6 @@ struct OpusCustomDecoder {
int downsample;
int start, end;
int signalling;
- int disable_inv;
int arch;
/* Everything beyond this point gets cleared on a reset */
@@ -109,38 +100,6 @@ struct OpusCustomDecoder {
/* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */
};
-#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
-/* Make basic checks on the CELT state to ensure we don't end
- up writing all over memory. */
-void validate_celt_decoder(CELTDecoder *st)
-{
-#ifndef CUSTOM_MODES
- celt_assert(st->mode == opus_custom_mode_create(48000, 960, NULL));
- celt_assert(st->overlap == 120);
-#endif
- celt_assert(st->channels == 1 || st->channels == 2);
- celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
- celt_assert(st->downsample > 0);
- celt_assert(st->start == 0 || st->start == 17);
- celt_assert(st->start < st->end);
- celt_assert(st->end <= 21);
-#ifdef OPUS_ARCHMASK
- celt_assert(st->arch >= 0);
- celt_assert(st->arch <= OPUS_ARCHMASK);
-#endif
- celt_assert(st->last_pitch_index <= PLC_PITCH_LAG_MAX);
- celt_assert(st->last_pitch_index >= PLC_PITCH_LAG_MIN || st->last_pitch_index == 0);
- celt_assert(st->postfilter_period < MAX_PERIOD);
- celt_assert(st->postfilter_period >= COMBFILTER_MINPERIOD || st->postfilter_period == 0);
- celt_assert(st->postfilter_period_old < MAX_PERIOD);
- celt_assert(st->postfilter_period_old >= COMBFILTER_MINPERIOD || st->postfilter_period_old == 0);
- celt_assert(st->postfilter_tapset <= 2);
- celt_assert(st->postfilter_tapset >= 0);
- celt_assert(st->postfilter_tapset_old <= 2);
- celt_assert(st->postfilter_tapset_old >= 0);
-}
-#endif
-
int celt_decoder_get_size(int channels)
{
const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
@@ -204,11 +163,6 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMod
st->start = 0;
st->end = st->mode->effEBands;
st->signalling = 1;
-#ifndef DISABLE_UPDATE_DRAFT
- st->disable_inv = channels == 1;
-#else
- st->disable_inv = 0;
-#endif
st->arch = opus_select_arch();
opus_custom_decoder_ctl(st, OPUS_RESET_STATE);
@@ -223,36 +177,6 @@ void opus_custom_decoder_destroy(CELTDecoder *st)
}
#endif /* CUSTOM_MODES */
-#ifndef CUSTOM_MODES
-/* Special case for stereo with no downsampling and no accumulation. This is
- quite common and we can make it faster by processing both channels in the
- same loop, reducing overhead due to the dependency loop in the IIR filter. */
-static void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, const opus_val16 coef0,
- celt_sig *mem)
-{
- celt_sig * OPUS_RESTRICT x0;
- celt_sig * OPUS_RESTRICT x1;
- celt_sig m0, m1;
- int j;
- x0=in[0];
- x1=in[1];
- m0 = mem[0];
- m1 = mem[1];
- for (j=0;j<N;j++)
- {
- celt_sig tmp0, tmp1;
- /* Add VERY_SMALL to x[] first to reduce dependency chain. */
- tmp0 = x0[j] + VERY_SMALL + m0;
- tmp1 = x1[j] + VERY_SMALL + m1;
- m0 = MULT16_32_Q15(coef0, tmp0);
- m1 = MULT16_32_Q15(coef0, tmp1);
- pcm[2*j ] = SCALEOUT(SIG2WORD16(tmp0));
- pcm[2*j+1] = SCALEOUT(SIG2WORD16(tmp1));
- }
- mem[0] = m0;
- mem[1] = m1;
-}
-#endif
#ifndef RESYNTH
static
@@ -266,14 +190,6 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
opus_val16 coef0;
VARDECL(celt_sig, scratch);
SAVE_STACK;
-#ifndef CUSTOM_MODES
- /* Short version for common case. */
- if (downsample == 1 && C == 2 && !accum)
- {
- deemphasis_stereo_simple(in, pcm, N, coef[0], mem);
- return;
- }
-#endif
#ifndef FIXED_POINT
(void)accum;
celt_assert(accum==0);
@@ -309,7 +225,7 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
/* Shortcut for the standard (non-custom modes) case */
for (j=0;j<N;j++)
{
- celt_sig tmp = x[j] + VERY_SMALL + m;
+ celt_sig tmp = x[j] + m + VERY_SMALL;
m = MULT16_32_Q15(coef0, tmp);
scratch[j] = tmp;
}
@@ -330,7 +246,7 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
{
for (j=0;j<N;j++)
{
- celt_sig tmp = x[j] + VERY_SMALL + m;
+ celt_sig tmp = x[j] + m + VERY_SMALL;
m = MULT16_32_Q15(coef0, tmp);
y[j*C] = SCALEOUT(SIG2WORD16(tmp));
}
@@ -417,7 +333,7 @@ void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M,
downsample, silence);
for (i=0;i<N;i++)
- freq[i] = ADD32(HALF32(freq[i]), HALF32(freq2[i]));
+ freq[i] = HALF32(ADD32(freq[i],freq2[i]));
for (b=0;b<B;b++)
clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
} else {
@@ -429,12 +345,6 @@ void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);
} while (++c<CC);
}
- /* Saturate IMDCT output so that we can't overflow in the pitch postfilter
- or in the */
- c=0; do {
- for (i=0;i<N;i++)
- out_syn[c][i] = SATURATE(out_syn[c][i], SIG_SAT);
- } while (++c<CC);
RESTORE_STACK;
}
@@ -477,6 +387,14 @@ static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM,
}
}
+/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
+ CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
+ current value corresponds to a pitch of 66.67 Hz. */
+#define PLC_PITCH_LAG_MAX (720)
+/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
+ pitch of 480 Hz. */
+#define PLC_PITCH_LAG_MIN (100)
+
static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
{
int pitch_index;
@@ -586,15 +504,12 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch);
} else {
- int exc_length;
/* Pitch-based PLC */
const opus_val16 *window;
- opus_val16 *exc;
opus_val16 fade = Q15ONE;
int pitch_index;
VARDECL(opus_val32, etmp);
- VARDECL(opus_val16, _exc);
- VARDECL(opus_val16, fir_tmp);
+ VARDECL(opus_val16, exc);
if (loss_count == 0)
{
@@ -604,14 +519,8 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
fade = QCONST16(.8f,15);
}
- /* We want the excitation for 2 pitch periods in order to look for a
- decaying signal, but we can't get more than MAX_PERIOD. */
- exc_length = IMIN(2*pitch_index, MAX_PERIOD);
-
ALLOC(etmp, overlap, opus_val32);
- ALLOC(_exc, MAX_PERIOD+LPC_ORDER, opus_val16);
- ALLOC(fir_tmp, exc_length, opus_val16);
- exc = _exc+LPC_ORDER;
+ ALLOC(exc, MAX_PERIOD, opus_val16);
window = mode->window;
c=0; do {
opus_val16 decay;
@@ -620,11 +529,13 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
celt_sig *buf;
int extrapolation_offset;
int extrapolation_len;
+ int exc_length;
int j;
buf = decode_mem[c];
- for (i=0;i<MAX_PERIOD+LPC_ORDER;i++)
- exc[i-LPC_ORDER] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD-LPC_ORDER+i], SIG_SHIFT);
+ for (i=0;i<MAX_PERIOD;i++) {
+ exc[i] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD+i], SIG_SHIFT);
+ }
if (loss_count == 0)
{
@@ -650,32 +561,22 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
#endif
}
_celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
-#ifdef FIXED_POINT
- /* For fixed-point, apply bandwidth expansion until we can guarantee that
- no overflow can happen in the IIR filter. This means:
- 32768*sum(abs(filter)) < 2^31 */
- while (1) {
- opus_val16 tmp=Q15ONE;
- opus_val32 sum=QCONST16(1., SIG_SHIFT);
- for (i=0;i<LPC_ORDER;i++)
- sum += ABS16(lpc[c*LPC_ORDER+i]);
- if (sum < 65535) break;
- for (i=0;i<LPC_ORDER;i++)
- {
- tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
- lpc[c*LPC_ORDER+i] = MULT16_16_Q15(lpc[c*LPC_ORDER+i], tmp);
- }
- }
-#endif
}
+ /* We want the excitation for 2 pitch periods in order to look for a
+ decaying signal, but we can't get more than MAX_PERIOD. */
+ exc_length = IMIN(2*pitch_index, MAX_PERIOD);
/* Initialize the LPC history with the samples just before the start
of the region for which we're computing the excitation. */
{
- /* Compute the excitation for exc_length samples before the loss. We need the copy
- because celt_fir() cannot filter in-place. */
+ opus_val16 lpc_mem[LPC_ORDER];
+ for (i=0;i<LPC_ORDER;i++)
+ {
+ lpc_mem[i] =
+ ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-1-i], SIG_SHIFT);
+ }
+ /* Compute the excitation for exc_length samples before the loss. */
celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER,
- fir_tmp, exc_length, LPC_ORDER, st->arch);
- OPUS_COPY(exc+MAX_PERIOD-exc_length, fir_tmp, exc_length);
+ exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, lpc_mem, st->arch);
}
/* Check if the waveform is decaying, and if so how fast.
@@ -729,8 +630,9 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
tmp = ROUND16(
buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j],
SIG_SHIFT);
- S1 += SHR32(MULT16_16(tmp, tmp), 10);
+ S1 += SHR32(MULT16_16(tmp, tmp), 8);
}
+
{
opus_val16 lpc_mem[LPC_ORDER];
/* Copy the last decoded samples (prior to the overlap region) to
@@ -742,10 +644,6 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER,
buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER,
lpc_mem, st->arch);
-#ifdef FIXED_POINT
- for (i=0; i < extrapolation_len; i++)
- buf[DECODE_BUFFER_SIZE-N+i] = SATURATE(buf[DECODE_BUFFER_SIZE-N+i], SIG_SAT);
-#endif
}
/* Check if the synthesis energy is higher than expected, which can
@@ -756,7 +654,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
for (i=0;i<extrapolation_len;i++)
{
opus_val16 tmp = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT);
- S2 += SHR32(MULT16_16(tmp, tmp), 10);
+ S2 += SHR32(MULT16_16(tmp, tmp), 8);
}
/* This checks for an "explosion" in the synthesis. */
#ifdef FIXED_POINT
@@ -864,7 +762,6 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
const opus_int16 *eBands;
ALLOC_STACK;
- VALIDATE_CELT_DECODER(st);
mode = st->mode;
nbEBands = mode->nbEBands;
overlap = mode->overlap;
@@ -1059,7 +956,7 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
ALLOC(pulses, nbEBands, int);
ALLOC(fine_priority, nbEBands, int);
- codedBands = clt_compute_allocation(mode, start, end, offsets, cap,
+ codedBands = compute_allocation(mode, start, end, offsets, cap,
alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
fine_quant, fine_priority, C, LM, dec, 0, 0, 0);
@@ -1082,8 +979,7 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
- len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, 0,
- st->arch, st->disable_inv);
+ len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, st->arch);
if (anti_collapse_rsv > 0)
{
@@ -1338,26 +1234,6 @@ int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
*value=st->rng;
}
break;
- case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
- {
- opus_int32 value = va_arg(ap, opus_int32);
- if(value<0 || value>1)
- {
- goto bad_arg;
- }
- st->disable_inv = value;
- }
- break;
- case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
- {
- opus_int32 *value = va_arg(ap, opus_int32*);
- if (!value)
- {
- goto bad_arg;
- }
- *value = st->disable_inv;
- }
- break;
default:
goto bad_request;
}
diff --git a/thirdparty/opus/celt/celt_encoder.c b/thirdparty/opus/celt/celt_encoder.c
index 44cb0850ab..3ee7a4d3f7 100644
--- a/thirdparty/opus/celt/celt_encoder.c
+++ b/thirdparty/opus/celt/celt_encoder.c
@@ -73,8 +73,8 @@ struct OpusCustomEncoder {
int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */
int loss_rate;
int lsb_depth;
+ int variable_duration;
int lfe;
- int disable_inv;
int arch;
/* Everything beyond this point gets cleared on a reset */
@@ -98,7 +98,6 @@ struct OpusCustomEncoder {
#endif
int consec_transient;
AnalysisInfo analysis;
- SILKInfo silk_info;
opus_val32 preemph_memE[2];
opus_val32 preemph_memD[2];
@@ -124,7 +123,6 @@ struct OpusCustomEncoder {
/* opus_val16 oldBandE[], Size = channels*mode->nbEBands */
/* opus_val16 oldLogE[], Size = channels*mode->nbEBands */
/* opus_val16 oldLogE2[], Size = channels*mode->nbEBands */
- /* opus_val16 energyError[], Size = channels*mode->nbEBands */
};
int celt_encoder_get_size(int channels)
@@ -138,10 +136,9 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int
int size = sizeof(struct CELTEncoder)
+ (channels*mode->overlap-1)*sizeof(celt_sig) /* celt_sig in_mem[channels*mode->overlap]; */
+ channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) /* celt_sig prefilter_mem[channels*COMBFILTER_MAXPERIOD]; */
- + 4*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */
+ + 3*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */
/* opus_val16 oldLogE[channels*mode->nbEBands]; */
/* opus_val16 oldLogE2[channels*mode->nbEBands]; */
- /* opus_val16 energyError[channels*mode->nbEBands]; */
return size;
}
@@ -181,6 +178,7 @@ static int opus_custom_encoder_init_arch(CELTEncoder *st, const CELTMode *mode,
st->start = 0;
st->end = st->mode->effEBands;
st->signalling = 1;
+
st->arch = arch;
st->constrained_vbr = 1;
@@ -225,8 +223,7 @@ void opus_custom_encoder_destroy(CELTEncoder *st)
static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int C,
- opus_val16 *tf_estimate, int *tf_chan, int allow_weak_transients,
- int *weak_transient)
+ opus_val16 *tf_estimate, int *tf_chan)
{
int i;
VARDECL(opus_val16, tmp);
@@ -236,12 +233,6 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
int c;
opus_val16 tf_max;
int len2;
- /* Forward masking: 6.7 dB/ms. */
-#ifdef FIXED_POINT
- int forward_shift = 4;
-#else
- opus_val16 forward_decay = QCONST16(.0625f,15);
-#endif
/* Table of 6*64/x, trained on real data to minimize the average error */
static const unsigned char inv_table[128] = {
255,255,156,110, 86, 70, 59, 51, 45, 40, 37, 33, 31, 28, 26, 25,
@@ -256,19 +247,6 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
SAVE_STACK;
ALLOC(tmp, len, opus_val16);
- *weak_transient = 0;
- /* For lower bitrates, let's be more conservative and have a forward masking
- decay of 3.3 dB/ms. This avoids having to code transients at very low
- bitrate (mostly for hybrid), which can result in unstable energy and/or
- partial collapse. */
- if (allow_weak_transients)
- {
-#ifdef FIXED_POINT
- forward_shift = 5;
-#else
- forward_decay = QCONST16(.03125f,15);
-#endif
- }
len2=len/2;
for (c=0;c<C;c++)
{
@@ -291,7 +269,7 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
mem0 = mem1 + y - 2*x;
mem1 = x - .5f*y;
#endif
- tmp[i] = SROUND16(y, 2);
+ tmp[i] = EXTRACT16(SHR32(y,2));
/*printf("%f ", tmp[i]);*/
}
/*printf("\n");*/
@@ -302,7 +280,7 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
/* Normalize tmp to max range */
{
int shift=0;
- shift = 14-celt_ilog2(MAX16(1, celt_maxabs16(tmp, len)));
+ shift = 14-celt_ilog2(1+celt_maxabs16(tmp, len));
if (shift!=0)
{
for (i=0;i<len;i++)
@@ -321,9 +299,9 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
mean += x2;
#ifdef FIXED_POINT
/* FIXME: Use PSHR16() instead */
- tmp[i] = mem0 + PSHR32(x2-mem0,forward_shift);
+ tmp[i] = mem0 + PSHR32(x2-mem0,4);
#else
- tmp[i] = mem0 + MULT16_16_P15(forward_decay,x2-mem0);
+ tmp[i] = mem0 + MULT16_16_P15(QCONST16(.0625f,15),x2-mem0);
#endif
mem0 = tmp[i];
}
@@ -333,7 +311,6 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
/* Backward pass to compute the pre-echo threshold */
for (i=len2-1;i>=0;i--)
{
- /* Backward masking: 13.9 dB/ms. */
#ifdef FIXED_POINT
/* FIXME: Use PSHR16() instead */
tmp[i] = mem0 + PSHR32(tmp[i]-mem0,3);
@@ -362,12 +339,6 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
/* Compute harmonic mean discarding the unreliable boundaries
The data is smooth, so we only take 1/4th of the samples */
unmask=0;
- /* We should never see NaNs here. If we find any, then something really bad happened and we better abort
- before it does any damage later on. If these asserts are disabled (no hardening), then the table
- lookup a few lines below (id = ...) is likely to crash dur to an out-of-bounds read. DO NOT FIX
- that crash on NaN since it could result in a worse issue later on. */
- celt_assert(!celt_isnan(tmp[0]));
- celt_assert(!celt_isnan(norm));
for (i=12;i<len2-5;i+=4)
{
int id;
@@ -388,12 +359,7 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
}
}
is_transient = mask_metric>200;
- /* For low bitrates, define "weak transients" that need to be
- handled differently to avoid partial collapse. */
- if (allow_weak_transients && is_transient && mask_metric<600) {
- is_transient = 0;
- *weak_transient = 1;
- }
+
/* Arbitrary metric for VBR boost */
tf_max = MAX16(0,celt_sqrt(27*mask_metric)-42);
/* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */
@@ -583,7 +549,7 @@ static opus_val32 l1_metric(const celt_norm *tmp, int N, int LM, opus_val16 bias
static int tf_analysis(const CELTMode *m, int len, int isTransient,
int *tf_res, int lambda, celt_norm *X, int N0, int LM,
- opus_val16 tf_estimate, int tf_chan, int *importance)
+ int *tf_sum, opus_val16 tf_estimate, int tf_chan)
{
int i;
VARDECL(int, metric);
@@ -608,6 +574,7 @@ static int tf_analysis(const CELTMode *m, int len, int isTransient,
ALLOC(path0, len, int);
ALLOC(path1, len, int);
+ *tf_sum = 0;
for (i=0;i<len;i++)
{
int k, N;
@@ -662,26 +629,27 @@ static int tf_analysis(const CELTMode *m, int len, int isTransient,
metric[i] = 2*best_level;
else
metric[i] = -2*best_level;
+ *tf_sum += (isTransient ? LM : 0) - metric[i]/2;
/* For bands that can't be split to -1, set the metric to the half-way point to avoid
biasing the decision */
if (narrow && (metric[i]==0 || metric[i]==-2*LM))
metric[i]-=1;
- /*printf("%d ", metric[i]/2 + (!isTransient)*LM);*/
+ /*printf("%d ", metric[i]);*/
}
/*printf("\n");*/
/* Search for the optimal tf resolution, including tf_select */
tf_select = 0;
for (sel=0;sel<2;sel++)
{
- cost0 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*sel+0]);
- cost1 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*sel+1]) + (isTransient ? 0 : lambda);
+ cost0 = 0;
+ cost1 = isTransient ? 0 : lambda;
for (i=1;i<len;i++)
{
int curr0, curr1;
curr0 = IMIN(cost0, cost1 + lambda);
curr1 = IMIN(cost0 + lambda, cost1);
- cost0 = curr0 + importance[i]*abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+0]);
- cost1 = curr1 + importance[i]*abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+1]);
+ cost0 = curr0 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+0]);
+ cost1 = curr1 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+1]);
}
cost0 = IMIN(cost0, cost1);
selcost[sel]=cost0;
@@ -690,8 +658,8 @@ static int tf_analysis(const CELTMode *m, int len, int isTransient,
* If tests confirm it's useful for non-transients, we could allow it. */
if (selcost[1]<selcost[0] && isTransient)
tf_select=1;
- cost0 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*tf_select+0]);
- cost1 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*tf_select+1]) + (isTransient ? 0 : lambda);
+ cost0 = 0;
+ cost1 = isTransient ? 0 : lambda;
/* Viterbi forward pass */
for (i=1;i<len;i++)
{
@@ -719,8 +687,8 @@ static int tf_analysis(const CELTMode *m, int len, int isTransient,
curr1 = from1;
path1[i]= 1;
}
- cost0 = curr0 + importance[i]*abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+0]);
- cost1 = curr1 + importance[i]*abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+1]);
+ cost0 = curr0 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+0]);
+ cost1 = curr1 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+1]);
}
tf_res[len-1] = cost0 < cost1 ? 0 : 1;
/* Viterbi backward pass to check the decisions */
@@ -786,7 +754,7 @@ static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM,
static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
const opus_val16 *bandLogE, int end, int LM, int C, int N0,
AnalysisInfo *analysis, opus_val16 *stereo_saving, opus_val16 tf_estimate,
- int intensity, opus_val16 surround_trim, opus_int32 equiv_rate, int arch)
+ int intensity, opus_val16 surround_trim, int arch)
{
int i;
opus_val32 diff=0;
@@ -794,14 +762,6 @@ static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
int trim_index;
opus_val16 trim = QCONST16(5.f, 8);
opus_val16 logXC, logXC2;
- /* At low bitrate, reducing the trim seems to help. At higher bitrates, it's less
- clear what's best, so we're keeping it as it was before, at least for now. */
- if (equiv_rate < 64000) {
- trim = QCONST16(4.f, 8);
- } else if (equiv_rate < 80000) {
- opus_int32 frac = (equiv_rate-64000) >> 10;
- trim = QCONST16(4.f, 8) + QCONST16(1.f/16.f, 8)*frac;
- }
if (C==2)
{
opus_val16 sum = 0; /* Q10 */
@@ -849,7 +809,7 @@ static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
} while (++c<C);
diff /= C*(end-1);
/*printf("%f\n", diff);*/
- trim -= MAX32(-QCONST16(2.f, 8), MIN32(QCONST16(2.f, 8), SHR32(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 ));
+ trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), SHR16(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 ));
trim -= SHR16(surround_trim, DB_SHIFT-8);
trim -= 2*SHR16(tf_estimate, 14-8);
#ifndef DISABLE_FLOAT_API
@@ -970,8 +930,7 @@ static opus_val16 median_of_3(const opus_val16 *x)
static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 *bandLogE2,
int nbEBands, int start, int end, int C, int *offsets, int lsb_depth, const opus_int16 *logN,
int isTransient, int vbr, int constrained_vbr, const opus_int16 *eBands, int LM,
- int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc,
- AnalysisInfo *analysis, int *importance, int *spread_weight)
+ int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc)
{
int i, c;
opus_int32 tot_boost=0;
@@ -997,42 +956,6 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
for (i=0;i<end;i++)
maxDepth = MAX16(maxDepth, bandLogE[c*nbEBands+i]-noise_floor[i]);
} while (++c<C);
- {
- /* Compute a really simple masking model to avoid taking into account completely masked
- bands when computing the spreading decision. */
- VARDECL(opus_val16, mask);
- VARDECL(opus_val16, sig);
- ALLOC(mask, nbEBands, opus_val16);
- ALLOC(sig, nbEBands, opus_val16);
- for (i=0;i<end;i++)
- mask[i] = bandLogE[i]-noise_floor[i];
- if (C==2)
- {
- for (i=0;i<end;i++)
- mask[i] = MAX16(mask[i], bandLogE[nbEBands+i]-noise_floor[i]);
- }
- OPUS_COPY(sig, mask, end);
- for (i=1;i<end;i++)
- mask[i] = MAX16(mask[i], mask[i-1] - QCONST16(2.f, DB_SHIFT));
- for (i=end-2;i>=0;i--)
- mask[i] = MAX16(mask[i], mask[i+1] - QCONST16(3.f, DB_SHIFT));
- for (i=0;i<end;i++)
- {
- /* Compute SMR: Mask is never more than 72 dB below the peak and never below the noise floor.*/
- opus_val16 smr = sig[i]-MAX16(MAX16(0, maxDepth-QCONST16(12.f, DB_SHIFT)), mask[i]);
- /* Clamp SMR to make sure we're not shifting by something negative or too large. */
-#ifdef FIXED_POINT
- /* FIXME: Use PSHR16() instead */
- int shift = -PSHR32(MAX16(-QCONST16(5.f, DB_SHIFT), MIN16(0, smr)), DB_SHIFT);
-#else
- int shift = IMIN(5, IMAX(0, -(int)floor(.5f + smr)));
-#endif
- spread_weight[i] = 32 >> shift;
- }
- /*for (i=0;i<end;i++)
- printf("%d ", spread_weight[i]);
- printf("\n");*/
- }
/* Make sure that dynamic allocation can't make us bust the budget */
if (effectiveBytes > 50 && LM>=1 && !lfe)
{
@@ -1089,14 +1012,6 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
}
for (i=start;i<end;i++)
follower[i] = MAX16(follower[i], surround_dynalloc[i]);
- for (i=start;i<end;i++)
- {
-#ifdef FIXED_POINT
- importance[i] = PSHR32(13*celt_exp2(MIN16(follower[i], QCONST16(4.f, DB_SHIFT))), 16);
-#else
- importance[i] = (int)floor(.5f+13*celt_exp2(MIN16(follower[i], QCONST16(4.f, DB_SHIFT))));
-#endif
- }
/* For non-transient CBR/CVBR frames, halve the dynalloc contribution */
if ((!vbr || constrained_vbr)&&!isTransient)
{
@@ -1105,26 +1020,14 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
}
for (i=start;i<end;i++)
{
- if (i<8)
- follower[i] *= 2;
- if (i>=12)
- follower[i] = HALF16(follower[i]);
- }
-#ifdef DISABLE_FLOAT_API
- (void)analysis;
-#else
- if (analysis->valid)
- {
- for (i=start;i<IMIN(LEAK_BANDS, end);i++)
- follower[i] = follower[i] + QCONST16(1.f/64.f, DB_SHIFT)*analysis->leak_boost[i];
- }
-#endif
- for (i=start;i<end;i++)
- {
int width;
int boost;
int boost_bits;
+ if (i<8)
+ follower[i] *= 2;
+ if (i>=12)
+ follower[i] = HALF16(follower[i]);
follower[i] = MIN16(follower[i], QCONST16(4, DB_SHIFT));
width = C*(eBands[i+1]-eBands[i])<<LM;
@@ -1139,11 +1042,11 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
boost = (int)SHR32(EXTEND32(follower[i])*width/6,DB_SHIFT);
boost_bits = boost*6<<BITRES;
}
- /* For CBR and non-transient CVBR frames, limit dynalloc to 2/3 of the bits */
+ /* For CBR and non-transient CVBR frames, limit dynalloc to 1/4 of the bits */
if ((!vbr || (constrained_vbr&&!isTransient))
- && (tot_boost+boost_bits)>>BITRES>>3 > 2*effectiveBytes/3)
+ && (tot_boost+boost_bits)>>BITRES>>3 > effectiveBytes/4)
{
- opus_int32 cap = ((2*effectiveBytes/3)<<BITRES<<3);
+ opus_int32 cap = ((effectiveBytes/4)<<BITRES<<3);
offsets[i] = cap-tot_boost;
tot_boost = cap;
break;
@@ -1152,9 +1055,6 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
tot_boost += boost_bits;
}
}
- } else {
- for (i=start;i<end;i++)
- importance[i] = 13;
}
*tot_boost_ = tot_boost;
RESTORE_STACK;
@@ -1163,7 +1063,7 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
static int run_prefilter(CELTEncoder *st, celt_sig *in, celt_sig *prefilter_mem, int CC, int N,
- int prefilter_tapset, int *pitch, opus_val16 *gain, int *qgain, int enabled, int nbAvailableBytes, AnalysisInfo *analysis)
+ int prefilter_tapset, int *pitch, opus_val16 *gain, int *qgain, int enabled, int nbAvailableBytes)
{
int c;
VARDECL(celt_sig, _pre);
@@ -1219,12 +1119,7 @@ static int run_prefilter(CELTEncoder *st, celt_sig *in, celt_sig *prefilter_mem,
gain1 = 0;
pitch_index = COMBFILTER_MINPERIOD;
}
-#ifndef DISABLE_FLOAT_API
- if (analysis->valid)
- gain1 = (opus_val16)(gain1 * analysis->max_pitch_ratio);
-#else
- (void)analysis;
-#endif
+
/* Gain threshold for enabling the prefilter/postfilter */
pf_threshold = QCONST16(.2f,15);
@@ -1298,7 +1193,7 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32
int LM, opus_int32 bitrate, int lastCodedBands, int C, int intensity,
int constrained_vbr, opus_val16 stereo_saving, int tot_boost,
opus_val16 tf_estimate, int pitch_change, opus_val16 maxDepth,
- int lfe, int has_surround_mask, opus_val16 surround_masking,
+ int variable_duration, int lfe, int has_surround_mask, opus_val16 surround_masking,
opus_val16 temporal_vbr)
{
/* The target rate in 8th bits per frame */
@@ -1340,9 +1235,10 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32
SHR32(MULT16_16(stereo_saving-QCONST16(0.1f,8),(coded_stereo_dof<<BITRES)),8));
}
/* Boost the rate according to dynalloc (minus the dynalloc average for calibration). */
- target += tot_boost-(19<<LM);
+ target += tot_boost-(16<<LM);
/* Apply transient boost, compensating for average boost. */
- tf_calibration = QCONST16(0.044f,14);
+ tf_calibration = variable_duration==OPUS_FRAMESIZE_VARIABLE ?
+ QCONST16(0.02f,14) : QCONST16(0.04f,14);
target += (opus_int32)SHL32(MULT16_32_Q15(tf_estimate-tf_calibration, target),1);
#ifndef DISABLE_FLOAT_API
@@ -1353,7 +1249,7 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32
float tonal;
/* Tonality boost (compensating for the average). */
- tonal = MAX16(0.f,analysis->tonality-.15f)-0.12f;
+ tonal = MAX16(0.f,analysis->tonality-.15f)-0.09f;
tonal_target = target + (opus_int32)((coded_bins<<BITRES)*1.2f*tonal);
if (pitch_change)
tonal_target += (opus_int32)((coded_bins<<BITRES)*.8f);
@@ -1383,11 +1279,21 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32
/*printf("%f %d\n", maxDepth, floor_depth);*/
}
- /* Make VBR less aggressive for constrained VBR because we can't keep a higher bitrate
- for long. Needs tuning. */
- if ((!has_surround_mask||lfe) && constrained_vbr)
+ if ((!has_surround_mask||lfe) && (constrained_vbr || bitrate<64000))
{
- target = base_target + (opus_int32)MULT16_32_Q15(QCONST16(0.67f, 15), target-base_target);
+ opus_val16 rate_factor = Q15ONE;
+ if (bitrate < 64000)
+ {
+#ifdef FIXED_POINT
+ rate_factor = MAX16(0,(bitrate-32000));
+#else
+ rate_factor = MAX16(0,(1.f/32768)*(bitrate-32000));
+#endif
+ }
+ if (constrained_vbr)
+ rate_factor = MIN16(rate_factor, QCONST16(0.67f, 15));
+ target = base_target + (opus_int32)MULT16_32_Q15(rate_factor, target-base_target);
+
}
if (!has_surround_mask && tf_estimate < QCONST16(.2f, 14))
@@ -1421,13 +1327,11 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
VARDECL(int, pulses);
VARDECL(int, cap);
VARDECL(int, offsets);
- VARDECL(int, importance);
- VARDECL(int, spread_weight);
VARDECL(int, fine_priority);
VARDECL(int, tf_res);
VARDECL(unsigned char, collapse_masks);
celt_sig *prefilter_mem;
- opus_val16 *oldBandE, *oldLogE, *oldLogE2, *energyError;
+ opus_val16 *oldBandE, *oldLogE, *oldLogE2;
int shortBlocks=0;
int isTransient=0;
const int CC = st->channels;
@@ -1439,6 +1343,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
int end;
int effEnd;
int codedBands;
+ int tf_sum;
int alloc_trim;
int pitch_index=COMBFILTER_MINPERIOD;
opus_val16 gain1 = 0;
@@ -1450,7 +1355,6 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
opus_int32 total_boost;
opus_int32 balance;
opus_int32 tell;
- opus_int32 tell0_frac;
int prefilter_tapset=0;
int pf_on;
int anti_collapse_rsv;
@@ -1472,10 +1376,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
opus_val16 surround_masking=0;
opus_val16 temporal_vbr=0;
opus_val16 surround_trim = 0;
- opus_int32 equiv_rate;
- int hybrid;
- int weak_transient = 0;
- int enable_tf_analysis;
+ opus_int32 equiv_rate = 510000;
VARDECL(opus_val16, surround_dynalloc);
ALLOC_STACK;
@@ -1485,7 +1386,6 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
eBands = mode->eBands;
start = st->start;
end = st->end;
- hybrid = start != 0;
tf_estimate = 0;
if (nbCompressedBytes<2 || pcm==NULL)
{
@@ -1509,14 +1409,12 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
oldBandE = (opus_val16*)(st->in_mem+CC*(overlap+COMBFILTER_MAXPERIOD));
oldLogE = oldBandE + CC*nbEBands;
oldLogE2 = oldLogE + CC*nbEBands;
- energyError = oldLogE2 + CC*nbEBands;
if (enc==NULL)
{
- tell0_frac=tell=1;
+ tell=1;
nbFilledBytes=0;
} else {
- tell0_frac=ec_tell_frac(enc);
tell=ec_tell(enc);
nbFilledBytes=(tell+4)>>3;
}
@@ -1569,11 +1467,10 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
if (st->bitrate!=OPUS_BITRATE_MAX)
nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes,
(tmp+4*mode->Fs)/(8*mode->Fs)-!!st->signalling));
- effectiveBytes = nbCompressedBytes - nbFilledBytes;
+ effectiveBytes = nbCompressedBytes;
}
- equiv_rate = ((opus_int32)nbCompressedBytes*8*50 >> (3-LM)) - (40*C+20)*((400>>LM) - 50);
if (st->bitrate != OPUS_BITRATE_MAX)
- equiv_rate = IMIN(equiv_rate, st->bitrate - (40*C+20)*((400>>LM) - 50));
+ equiv_rate = st->bitrate - (40*C+20)*((400>>LM) - 50);
if (enc==NULL)
{
@@ -1661,17 +1558,17 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
{
int enabled;
int qg;
- enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && !hybrid && !silence && !st->disable_pf
- && st->complexity >= 5;
+ enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && start==0 && !silence && !st->disable_pf
+ && st->complexity >= 5 && !(st->consec_transient && LM!=3 && st->variable_duration==OPUS_FRAMESIZE_VARIABLE);
prefilter_tapset = st->tapset_decision;
- pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes, &st->analysis);
+ pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes);
if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3)
&& (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period))
pitch_change = 1;
if (pf_on==0)
{
- if(!hybrid && tell+16<=total_bits)
+ if(start==0 && tell+16<=total_bits)
ec_enc_bit_logp(enc, 0, 1);
} else {
/*This block is not gated by a total bits check only because
@@ -1692,12 +1589,8 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
shortBlocks = 0;
if (st->complexity >= 1 && !st->lfe)
{
- /* Reduces the likelihood of energy instability on fricatives at low bitrate
- in hybrid mode. It seems like we still want to have real transients on vowels
- though (small SILK quantization offset value). */
- int allow_weak_transients = hybrid && effectiveBytes<15 && st->silk_info.signalType != 2;
isTransient = transient_analysis(in, N+overlap, CC,
- &tf_estimate, &tf_chan, allow_weak_transients, &weak_transient);
+ &tf_estimate, &tf_chan);
}
if (LM>0 && ec_tell(enc)+3<=total_bits)
{
@@ -1717,19 +1610,16 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
if (secondMdct)
{
compute_mdcts(mode, 0, in, freq, C, CC, LM, st->upsample, st->arch);
- compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
+ compute_band_energies(mode, freq, bandE, effEnd, C, LM);
amp2Log2(mode, effEnd, end, bandE, bandLogE2, C);
for (i=0;i<C*nbEBands;i++)
bandLogE2[i] += HALF16(SHL16(LM, DB_SHIFT));
}
compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch);
- /* This should catch any NaN in the CELT input. Since we're not supposed to see any (they're filtered
- at the Opus layer), just abort. */
- celt_assert(!celt_isnan(freq[0]) && (C==1 || !celt_isnan(freq[N])));
if (CC==2&&C==1)
tf_chan = 0;
- compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
+ compute_band_energies(mode, freq, bandE, effEnd, C, LM);
if (st->lfe)
{
@@ -1744,7 +1634,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
ALLOC(surround_dynalloc, C*nbEBands, opus_val16);
OPUS_CLEAR(surround_dynalloc, end);
/* This computes how much masking takes place between surround channels */
- if (!hybrid&&st->energy_mask&&!st->lfe)
+ if (start==0&&st->energy_mask&&!st->lfe)
{
int mask_end;
int midband;
@@ -1846,14 +1736,14 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
/* Last chance to catch any transient we might have missed in the
time-domain analysis */
- if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe && !hybrid)
+ if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe)
{
if (patch_transient_decision(bandLogE, oldBandE, nbEBands, start, end, C))
{
isTransient = 1;
shortBlocks = M;
compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch);
- compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
+ compute_band_energies(mode, freq, bandE, effEnd, C, LM);
amp2Log2(mode, effEnd, end, bandE, bandLogE, C);
/* Compensate for the scaling of short vs long mdcts */
for (i=0;i<C*nbEBands;i++)
@@ -1870,59 +1760,31 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
/* Band normalisation */
normalise_bands(mode, freq, X, bandE, effEnd, C, M);
- enable_tf_analysis = effectiveBytes>=15*C && !hybrid && st->complexity>=2 && !st->lfe;
-
- ALLOC(offsets, nbEBands, int);
- ALLOC(importance, nbEBands, int);
- ALLOC(spread_weight, nbEBands, int);
-
- maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets,
- st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr,
- eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc, &st->analysis, importance, spread_weight);
-
ALLOC(tf_res, nbEBands, int);
/* Disable variable tf resolution for hybrid and at very low bitrate */
- if (enable_tf_analysis)
+ if (effectiveBytes>=15*C && start==0 && st->complexity>=2 && !st->lfe)
{
int lambda;
- lambda = IMAX(80, 20480/effectiveBytes + 2);
- tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, tf_estimate, tf_chan, importance);
+ if (effectiveBytes<40)
+ lambda = 12;
+ else if (effectiveBytes<60)
+ lambda = 6;
+ else if (effectiveBytes<100)
+ lambda = 4;
+ else
+ lambda = 3;
+ lambda*=2;
+ tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, &tf_sum, tf_estimate, tf_chan);
for (i=effEnd;i<end;i++)
tf_res[i] = tf_res[effEnd-1];
- } else if (hybrid && weak_transient)
- {
- /* For weak transients, we rely on the fact that improving time resolution using
- TF on a long window is imperfect and will not result in an energy collapse at
- low bitrate. */
- for (i=0;i<end;i++)
- tf_res[i] = 1;
- tf_select=0;
- } else if (hybrid && effectiveBytes<15 && st->silk_info.signalType != 2)
- {
- /* For low bitrate hybrid, we force temporal resolution to 5 ms rather than 2.5 ms. */
- for (i=0;i<end;i++)
- tf_res[i] = 0;
- tf_select=isTransient;
} else {
+ tf_sum = 0;
for (i=0;i<end;i++)
tf_res[i] = isTransient;
tf_select=0;
}
ALLOC(error, C*nbEBands, opus_val16);
- c=0;
- do {
- for (i=start;i<end;i++)
- {
- /* When the energy is stable, slightly bias energy quantization towards
- the previous error to make the gain more stable (a constant offset is
- better than fluctuations). */
- if (ABS32(SUB32(bandLogE[i+c*nbEBands], oldBandE[i+c*nbEBands])) < QCONST16(2.f, DB_SHIFT))
- {
- bandLogE[i+c*nbEBands] -= MULT16_16_Q15(energyError[i+c*nbEBands], QCONST16(0.25f, 15));
- }
- }
- } while (++c < C);
quant_coarse_energy(mode, start, end, effEnd, bandLogE,
oldBandE, total_bits, error, enc,
C, LM, nbAvailableBytes, st->force_intra,
@@ -1936,15 +1798,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
{
st->tapset_decision = 0;
st->spread_decision = SPREAD_NORMAL;
- } else if (hybrid)
- {
- if (st->complexity == 0)
- st->spread_decision = SPREAD_NONE;
- else if (isTransient)
- st->spread_decision = SPREAD_NORMAL;
- else
- st->spread_decision = SPREAD_AGGRESSIVE;
- } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C)
+ } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C || start != 0)
{
if (st->complexity == 0)
st->spread_decision = SPREAD_NONE;
@@ -1968,7 +1822,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
{
st->spread_decision = spreading_decision(mode, X,
&st->tonal_average, st->spread_decision, &st->hf_average,
- &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M, spread_weight);
+ &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M);
}
/*printf("%d %d\n", st->tapset_decision, st->spread_decision);*/
/*printf("%f %d %f %d\n\n", st->analysis.tonality, st->spread_decision, st->analysis.tonality_slope, st->tapset_decision);*/
@@ -1976,6 +1830,11 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5);
}
+ ALLOC(offsets, nbEBands, int);
+
+ maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets,
+ st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr,
+ eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc);
/* For LFE, everything interesting is in the first band */
if (st->lfe)
offsets[0] = IMIN(8, effectiveBytes/3);
@@ -2037,15 +1896,12 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
alloc_trim = 5;
if (tell+(6<<BITRES) <= total_bits - total_boost)
{
- if (start > 0 || st->lfe)
- {
- st->stereo_saving = 0;
+ if (st->lfe)
alloc_trim = 5;
- } else {
+ else
alloc_trim = alloc_trim_analysis(mode, X, bandLogE,
end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate,
- st->intensity, surround_trim, equiv_rate, st->arch);
- }
+ st->intensity, surround_trim, st->arch);
ec_enc_icdf(enc, alloc_trim, trim_icdf, 7);
tell = ec_tell_frac(enc);
}
@@ -2063,36 +1919,17 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
/* Don't attempt to use more than 510 kb/s, even for frames smaller than 20 ms.
The CELT allocator will just not be able to use more than that anyway. */
nbCompressedBytes = IMIN(nbCompressedBytes,1275>>(3-LM));
- if (!hybrid)
- {
- base_target = vbr_rate - ((40*C+20)<<BITRES);
- } else {
- base_target = IMAX(0, vbr_rate - ((9*C+4)<<BITRES));
- }
+ base_target = vbr_rate - ((40*C+20)<<BITRES);
if (st->constrained_vbr)
base_target += (st->vbr_offset>>lm_diff);
- if (!hybrid)
- {
- target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate,
+ target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate,
st->lastCodedBands, C, st->intensity, st->constrained_vbr,
st->stereo_saving, tot_boost, tf_estimate, pitch_change, maxDepth,
- st->lfe, st->energy_mask!=NULL, surround_masking,
+ st->variable_duration, st->lfe, st->energy_mask!=NULL, surround_masking,
temporal_vbr);
- } else {
- target = base_target;
- /* Tonal frames (offset<100) need more bits than noisy (offset>100) ones. */
- if (st->silk_info.offset < 100) target += 12 << BITRES >> (3-LM);
- if (st->silk_info.offset > 100) target -= 18 << BITRES >> (3-LM);
- /* Boosting bitrate on transients and vowels with significant temporal
- spikes. */
- target += (opus_int32)MULT16_16_Q14(tf_estimate-QCONST16(.25f,14), (50<<BITRES));
- /* If we have a strong transient, let's make sure it has enough bits to code
- the first two bands, so that it can use folding rather than noise. */
- if (tf_estimate > QCONST16(.7f,14))
- target = IMAX(target, 50<<BITRES);
- }
+
/* The current offset is removed from the target and the space used
so far is added*/
target=target+tell;
@@ -2100,16 +1937,11 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
result in the encoder running out of bits.
The margin of 2 bytes ensures that none of the bust-prevention logic
in the decoder will have triggered so far. */
- min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2;
- /* Take into account the 37 bits we need to have left in the packet to
- signal a redundant frame in hybrid mode. Creating a shorter packet would
- create an entropy coder desync. */
- if (hybrid)
- min_allowed = IMAX(min_allowed, (tell0_frac+(37<<BITRES)+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3));
+ min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2 - nbFilledBytes;
nbAvailableBytes = (target+(1<<(BITRES+2)))>>(BITRES+3);
nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes);
- nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes);
+ nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes) - nbFilledBytes;
/* By how much did we "miss" the target on that frame */
delta = target - vbr_rate;
@@ -2156,7 +1988,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
st->vbr_reservoir = 0;
/*printf ("+%d\n", adjust);*/
}
- nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes);
+ nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes);
/*printf("%d\n", nbCompressedBytes*50*8);*/
/* This moves the raw bits to take into account the new compressed size */
ec_enc_shrink(enc, nbCompressedBytes);
@@ -2191,7 +2023,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
#endif
if (st->lfe)
signalBandwidth = 1;
- codedBands = clt_compute_allocation(mode, start, end, offsets, cap,
+ codedBands = compute_allocation(mode, start, end, offsets, cap,
alloc_trim, &st->intensity, &dual_stereo, bits, &balance, pulses,
fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands, signalBandwidth);
if (st->lastCodedBands)
@@ -2206,7 +2038,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
quant_all_bands(1, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
bandE, pulses, shortBlocks, st->spread_decision,
dual_stereo, st->intensity, tf_res, nbCompressedBytes*(8<<BITRES)-anti_collapse_rsv,
- balance, enc, LM, codedBands, &st->rng, st->complexity, st->arch, st->disable_inv);
+ balance, enc, LM, codedBands, &st->rng, st->arch);
if (anti_collapse_rsv > 0)
{
@@ -2217,14 +2049,6 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
ec_enc_bits(enc, anti_collapse_on, 1);
}
quant_energy_finalise(mode, start, end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C);
- OPUS_CLEAR(energyError, nbEBands*CC);
- c=0;
- do {
- for (i=start;i<end;i++)
- {
- energyError[i+c*nbEBands] = MAX16(-QCONST16(0.5f, 15), MIN16(QCONST16(0.5f, 15), error[i+c*nbEBands]));
- }
- } while (++c < C);
if (silence)
{
@@ -2497,24 +2321,10 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
*value=st->lsb_depth;
}
break;
- case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+ case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
- if(value<0 || value>1)
- {
- goto bad_arg;
- }
- st->disable_inv = value;
- }
- break;
- case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
- {
- opus_int32 *value = va_arg(ap, opus_int32*);
- if (!value)
- {
- goto bad_arg;
- }
- *value = st->disable_inv;
+ st->variable_duration = value;
}
break;
case OPUS_RESET_STATE:
@@ -2558,13 +2368,6 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
OPUS_COPY(&st->analysis, info, 1);
}
break;
- case CELT_SET_SILK_INFO_REQUEST:
- {
- SILKInfo *info = va_arg(ap, SILKInfo *);
- if (info)
- OPUS_COPY(&st->silk_info, info, 1);
- }
- break;
case CELT_GET_MODE_REQUEST:
{
const CELTMode ** value = va_arg(ap, const CELTMode**);
diff --git a/thirdparty/opus/celt/celt_lpc.c b/thirdparty/opus/celt/celt_lpc.c
index 8ecb693ee9..b410a21c5f 100644
--- a/thirdparty/opus/celt/celt_lpc.c
+++ b/thirdparty/opus/celt/celt_lpc.c
@@ -89,40 +89,58 @@ int p
void celt_fir_c(
- const opus_val16 *x,
+ const opus_val16 *_x,
const opus_val16 *num,
- opus_val16 *y,
+ opus_val16 *_y,
int N,
int ord,
+ opus_val16 *mem,
int arch)
{
int i,j;
VARDECL(opus_val16, rnum);
+ VARDECL(opus_val16, x);
SAVE_STACK;
- celt_assert(x != y);
+
ALLOC(rnum, ord, opus_val16);
+ ALLOC(x, N+ord, opus_val16);
for(i=0;i<ord;i++)
rnum[i] = num[ord-i-1];
+ for(i=0;i<ord;i++)
+ x[i] = mem[ord-i-1];
+ for (i=0;i<N;i++)
+ x[i+ord]=_x[i];
+ for(i=0;i<ord;i++)
+ mem[i] = _x[N-i-1];
+#ifdef SMALL_FOOTPRINT
+ (void)arch;
+ for (i=0;i<N;i++)
+ {
+ opus_val32 sum = SHL32(EXTEND32(_x[i]), SIG_SHIFT);
+ for (j=0;j<ord;j++)
+ {
+ sum = MAC16_16(sum,rnum[j],x[i+j]);
+ }
+ _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT));
+ }
+#else
for (i=0;i<N-3;i+=4)
{
- opus_val32 sum[4];
- sum[0] = SHL32(EXTEND32(x[i ]), SIG_SHIFT);
- sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT);
- sum[2] = SHL32(EXTEND32(x[i+2]), SIG_SHIFT);
- sum[3] = SHL32(EXTEND32(x[i+3]), SIG_SHIFT);
- xcorr_kernel(rnum, x+i-ord, sum, ord, arch);
- y[i ] = ROUND16(sum[0], SIG_SHIFT);
- y[i+1] = ROUND16(sum[1], SIG_SHIFT);
- y[i+2] = ROUND16(sum[2], SIG_SHIFT);
- y[i+3] = ROUND16(sum[3], SIG_SHIFT);
+ opus_val32 sum[4]={0,0,0,0};
+ xcorr_kernel(rnum, x+i, sum, ord, arch);
+ _y[i ] = SATURATE16(ADD32(EXTEND32(_x[i ]), PSHR32(sum[0], SIG_SHIFT)));
+ _y[i+1] = SATURATE16(ADD32(EXTEND32(_x[i+1]), PSHR32(sum[1], SIG_SHIFT)));
+ _y[i+2] = SATURATE16(ADD32(EXTEND32(_x[i+2]), PSHR32(sum[2], SIG_SHIFT)));
+ _y[i+3] = SATURATE16(ADD32(EXTEND32(_x[i+3]), PSHR32(sum[3], SIG_SHIFT)));
}
for (;i<N;i++)
{
- opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
+ opus_val32 sum = 0;
for (j=0;j<ord;j++)
- sum = MAC16_16(sum,rnum[j],x[i+j-ord]);
- y[i] = ROUND16(sum, SIG_SHIFT);
+ sum = MAC16_16(sum,rnum[j],x[i+j]);
+ _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT)));
}
+#endif
RESTORE_STACK;
}
@@ -148,7 +166,7 @@ void celt_iir(const opus_val32 *_x,
{
mem[j]=mem[j-1];
}
- mem[0] = SROUND16(sum, SIG_SHIFT);
+ mem[0] = ROUND16(sum,SIG_SHIFT);
_y[i] = sum;
}
#else
@@ -177,20 +195,20 @@ void celt_iir(const opus_val32 *_x,
xcorr_kernel(rden, y+i, sum, ord, arch);
/* Patch up the result to compensate for the fact that this is an IIR */
- y[i+ord ] = -SROUND16(sum[0],SIG_SHIFT);
+ y[i+ord ] = -ROUND16(sum[0],SIG_SHIFT);
_y[i ] = sum[0];
sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]);
- y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT);
+ y[i+ord+1] = -ROUND16(sum[1],SIG_SHIFT);
_y[i+1] = sum[1];
sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
sum[2] = MAC16_16(sum[2], y[i+ord ], den[1]);
- y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT);
+ y[i+ord+2] = -ROUND16(sum[2],SIG_SHIFT);
_y[i+2] = sum[2];
sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
sum[3] = MAC16_16(sum[3], y[i+ord ], den[2]);
- y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT);
+ y[i+ord+3] = -ROUND16(sum[3],SIG_SHIFT);
_y[i+3] = sum[3];
}
for (;i<N;i++)
@@ -198,7 +216,7 @@ void celt_iir(const opus_val32 *_x,
opus_val32 sum = _x[i];
for (j=0;j<ord;j++)
sum -= MULT16_16(rden[j],y[i+j]);
- y[i+ord] = SROUND16(sum,SIG_SHIFT);
+ y[i+ord] = ROUND16(sum,SIG_SHIFT);
_y[i] = sum;
}
for(i=0;i<ord;i++)
diff --git a/thirdparty/opus/celt/celt_lpc.h b/thirdparty/opus/celt/celt_lpc.h
index a4c5fd6ea5..323459eb1a 100644
--- a/thirdparty/opus/celt/celt_lpc.h
+++ b/thirdparty/opus/celt/celt_lpc.h
@@ -45,11 +45,12 @@ void celt_fir_c(
opus_val16 *y,
int N,
int ord,
+ opus_val16 *mem,
int arch);
#if !defined(OVERRIDE_CELT_FIR)
-#define celt_fir(x, num, y, N, ord, arch) \
- (celt_fir_c(x, num, y, N, ord, arch))
+#define celt_fir(x, num, y, N, ord, mem, arch) \
+ (celt_fir_c(x, num, y, N, ord, mem, arch))
#endif
void celt_iir(const opus_val32 *x,
diff --git a/thirdparty/opus/celt/cwrs.c b/thirdparty/opus/celt/cwrs.c
index a552e4f0fb..9722f0ac86 100644
--- a/thirdparty/opus/celt/cwrs.c
+++ b/thirdparty/opus/celt/cwrs.c
@@ -482,7 +482,7 @@ static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y){
k0=_k;
q=row[_n];
if(q>_i){
- celt_sig_assert(p>q);
+ celt_assert(p>q);
_k=_n;
do p=CELT_PVQ_U_ROW[--_k][_n];
while(p>_i);
diff --git a/thirdparty/opus/celt/entcode.h b/thirdparty/opus/celt/entcode.h
index 3763e3f284..13d6c84ef0 100644
--- a/thirdparty/opus/celt/entcode.h
+++ b/thirdparty/opus/celt/entcode.h
@@ -122,7 +122,7 @@ opus_uint32 ec_tell_frac(ec_ctx *_this);
/* Tested exhaustively for all n and for 1<=d<=256 */
static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) {
- celt_sig_assert(d>0);
+ celt_assert(d>0);
#ifdef USE_SMALL_DIV_TABLE
if (d>256)
return n/d;
@@ -138,7 +138,7 @@ static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) {
}
static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) {
- celt_sig_assert(d>0);
+ celt_assert(d>0);
#ifdef USE_SMALL_DIV_TABLE
if (n<0)
return -(opus_int32)celt_udiv(-n, d);
diff --git a/thirdparty/opus/celt/entdec.h b/thirdparty/opus/celt/entdec.h
index 025fc1870d..d8ab318730 100644
--- a/thirdparty/opus/celt/entdec.h
+++ b/thirdparty/opus/celt/entdec.h
@@ -85,7 +85,7 @@ int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb);
The bits must have been encoded with ec_enc_uint().
No call to ec_dec_update() is necessary after this call.
_ft: The number of integers that can be decoded (one more than the max).
- This must be at least 2, and no more than 2**32-1.
+ This must be at least one, and no more than 2**32-1.
Return: The decoded bits.*/
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft);
diff --git a/thirdparty/opus/celt/entenc.h b/thirdparty/opus/celt/entenc.h
index f502eaf662..796bc4d572 100644
--- a/thirdparty/opus/celt/entenc.h
+++ b/thirdparty/opus/celt/entenc.h
@@ -67,7 +67,7 @@ void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb);
/*Encodes a raw unsigned integer in the stream.
_fl: The integer to encode.
_ft: The number of integers that can be encoded (one more than the max).
- This must be at least 2, and no more than 2**32-1.*/
+ This must be at least one, and no more than 2**32-1.*/
void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft);
/*Encodes a sequence of raw bits in the stream.
diff --git a/thirdparty/opus/celt/fixed_debug.h b/thirdparty/opus/celt/fixed_debug.h
index f435295234..d28227f5dc 100644
--- a/thirdparty/opus/celt/fixed_debug.h
+++ b/thirdparty/opus/celt/fixed_debug.h
@@ -59,14 +59,6 @@ extern opus_int64 celt_mips;
#define SHR(a,b) SHR32(a,b)
#define PSHR(a,b) PSHR32(a,b)
-/** Add two 32-bit values, ignore any overflows */
-#define ADD32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
-/** Subtract two 32-bit values, ignore any overflows */
-#define SUB32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
-/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
-/** Negate 32-bit value, ignore any overflows */
-#define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a)))
-
static OPUS_INLINE short NEG16(int x)
{
int res;
@@ -235,11 +227,12 @@ static OPUS_INLINE int SHL32_(opus_int64 a, int shift, char *file, int line)
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
#define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
-#define SROUND16(x,a) (celt_mips--,EXTRACT16(SATURATE(PSHR32(x,a), 32767)));
-
#define HALF16(x) (SHR16(x,1))
#define HALF32(x) (SHR32(x,1))
+//#define SHR(a,shift) ((a) >> (shift))
+//#define SHL(a,shift) ((a) << (shift))
+
#define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__)
static OPUS_INLINE short ADD16_(int a, int b, char *file, int line)
{
diff --git a/thirdparty/opus/celt/fixed_generic.h b/thirdparty/opus/celt/fixed_generic.h
index 5f4abda76e..1cfd6d6989 100644
--- a/thirdparty/opus/celt/fixed_generic.h
+++ b/thirdparty/opus/celt/fixed_generic.h
@@ -104,9 +104,6 @@
/** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */
#define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a))))
-/** Shift by a and round-to-neareast 32-bit value. Result is a saturated 16-bit value */
-#define SROUND16(x,a) EXTRACT16(SATURATE(PSHR32(x,a), 32767));
-
/** Divide by two */
#define HALF16(x) (SHR16(x,1))
#define HALF32(x) (SHR32(x,1))
@@ -120,14 +117,6 @@
/** Subtract two 32-bit values */
#define SUB32(a,b) ((opus_val32)(a)-(opus_val32)(b))
-/** Add two 32-bit values, ignore any overflows */
-#define ADD32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
-/** Subtract two 32-bit values, ignore any overflows */
-#define SUB32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
-/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
-/** Negate 32-bit value, ignore any overflows */
-#define NEG32_ovflw(a) ((opus_val32)(0-(opus_uint32)(a)))
-
/** 16x16 multiplication where the result fits in 16 bits */
#define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(b))))
diff --git a/thirdparty/opus/celt/float_cast.h b/thirdparty/opus/celt/float_cast.h
index 889dae965f..ed5a39b543 100644
--- a/thirdparty/opus/celt/float_cast.h
+++ b/thirdparty/opus/celt/float_cast.h
@@ -61,13 +61,7 @@
** the config.h file.
*/
-/* With GCC, when SSE is available, the fastest conversion is cvtss2si. */
-#if defined(__GNUC__) && defined(__SSE__)
-
-#include <xmmintrin.h>
-static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_ss(x));}
-
-#elif defined(HAVE_LRINTF)
+#if (HAVE_LRINTF)
/* These defines enable functionality introduced with the 1999 ISO C
** standard. They must be defined before the inclusion of math.h to
@@ -96,10 +90,10 @@ static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_s
#include <math.h>
#define float2int(x) lrint(x)
-#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1))
+#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_X64)
#include <xmmintrin.h>
- static __inline long int float2int(float value)
+ __inline long int float2int(float value)
{
return _mm_cvtss_si32(_mm_load_ss(&value));
}
@@ -110,7 +104,7 @@ static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_s
** Therefore implement OPUS_INLINE versions of these functions here.
*/
- static __inline long int
+ __inline long int
float2int (float flt)
{ int intgr;
diff --git a/thirdparty/opus/celt/kiss_fft.c b/thirdparty/opus/celt/kiss_fft.c
index 83775165d8..1f8fd05321 100644
--- a/thirdparty/opus/celt/kiss_fft.c
+++ b/thirdparty/opus/celt/kiss_fft.c
@@ -82,8 +82,8 @@ static void kf_bfly2(
C_SUB( Fout2[0] , Fout[0] , t );
C_ADDTO( Fout[0] , t );
- t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw);
- t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw);
+ t.r = S_MUL(Fout2[1].r+Fout2[1].i, tw);
+ t.i = S_MUL(Fout2[1].i-Fout2[1].r, tw);
C_SUB( Fout2[1] , Fout[1] , t );
C_ADDTO( Fout[1] , t );
@@ -92,8 +92,8 @@ static void kf_bfly2(
C_SUB( Fout2[2] , Fout[2] , t );
C_ADDTO( Fout[2] , t );
- t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw);
- t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw);
+ t.r = S_MUL(Fout2[3].i-Fout2[3].r, tw);
+ t.i = S_MUL(-Fout2[3].i-Fout2[3].r, tw);
C_SUB( Fout2[3] , Fout[3] , t );
C_ADDTO( Fout[3] , t );
Fout += 8;
@@ -126,10 +126,10 @@ static void kf_bfly4(
C_ADDTO( *Fout , scratch1 );
C_SUB( scratch1 , Fout[1] , Fout[3] );
- Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i);
- Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r);
- Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i);
- Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r);
+ Fout[1].r = scratch0.r + scratch1.i;
+ Fout[1].i = scratch0.i - scratch1.r;
+ Fout[3].r = scratch0.r - scratch1.i;
+ Fout[3].i = scratch0.i + scratch1.r;
Fout+=4;
}
} else {
@@ -160,10 +160,10 @@ static void kf_bfly4(
tw3 += fstride*3;
C_ADDTO( *Fout , scratch[3] );
- Fout[m].r = ADD32_ovflw(scratch[5].r, scratch[4].i);
- Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r);
- Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i);
- Fout[m3].i = ADD32_ovflw(scratch[5].i, scratch[4].r);
+ Fout[m].r = scratch[5].r + scratch[4].i;
+ Fout[m].i = scratch[5].i - scratch[4].r;
+ Fout[m3].r = scratch[5].r - scratch[4].i;
+ Fout[m3].i = scratch[5].i + scratch[4].r;
++Fout;
}
}
@@ -212,18 +212,18 @@ static void kf_bfly3(
tw1 += fstride;
tw2 += fstride*2;
- Fout[m].r = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r));
- Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i));
+ Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
+ Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
C_MULBYSCALAR( scratch[0] , epi3.i );
C_ADDTO(*Fout,scratch[3]);
- Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i);
- Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r);
+ Fout[m2].r = Fout[m].r + scratch[0].i;
+ Fout[m2].i = Fout[m].i - scratch[0].r;
- Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i);
- Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r);
+ Fout[m].r -= scratch[0].i;
+ Fout[m].i += scratch[0].r;
++Fout;
} while(--k);
@@ -282,22 +282,22 @@ static void kf_bfly5(
C_ADD( scratch[8],scratch[2],scratch[3]);
C_SUB( scratch[9],scratch[2],scratch[3]);
- Fout0->r = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r));
- Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i));
+ Fout0->r += scratch[7].r + scratch[8].r;
+ Fout0->i += scratch[7].i + scratch[8].i;
- scratch[5].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,ya.r), S_MUL(scratch[8].r,yb.r)));
- scratch[5].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,ya.r), S_MUL(scratch[8].i,yb.r)));
+ scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
+ scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
- scratch[6].r = ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i));
- scratch[6].i = NEG32_ovflw(ADD32_ovflw(S_MUL(scratch[10].r,ya.i), S_MUL(scratch[9].r,yb.i)));
+ scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
+ scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
C_SUB(*Fout1,scratch[5],scratch[6]);
C_ADD(*Fout4,scratch[5],scratch[6]);
- scratch[11].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,yb.r), S_MUL(scratch[8].r,ya.r)));
- scratch[11].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,yb.r), S_MUL(scratch[8].i,ya.r)));
- scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i));
- scratch[12].i = SUB32_ovflw(S_MUL(scratch[10].r,yb.i), S_MUL(scratch[9].r,ya.i));
+ scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
+ scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
+ scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
+ scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
C_ADD(*Fout2,scratch[11],scratch[12]);
C_SUB(*Fout3,scratch[11],scratch[12]);
diff --git a/thirdparty/opus/celt/mathops.c b/thirdparty/opus/celt/mathops.c
index 6ee9b9e101..21a01f52e4 100644
--- a/thirdparty/opus/celt/mathops.c
+++ b/thirdparty/opus/celt/mathops.c
@@ -38,8 +38,7 @@
#include "mathops.h"
/*Compute floor(sqrt(_val)) with exact arithmetic.
- _val must be greater than 0.
- This has been tested on all possible 32-bit inputs greater than 0.*/
+ This has been tested on all possible 32-bit inputs.*/
unsigned isqrt32(opus_uint32 _val){
unsigned b;
unsigned g;
@@ -183,7 +182,7 @@ opus_val32 celt_rcp(opus_val32 x)
int i;
opus_val16 n;
opus_val16 r;
- celt_sig_assert(x>0);
+ celt_assert2(x>0, "celt_rcp() only defined for positive values");
i = celt_ilog2(x);
/* n is Q15 with range [0,1). */
n = VSHR32(x,i-15)-32768;
diff --git a/thirdparty/opus/celt/mathops.h b/thirdparty/opus/celt/mathops.h
index 5e86ff0dd2..a0525a9610 100644
--- a/thirdparty/opus/celt/mathops.h
+++ b/thirdparty/opus/celt/mathops.h
@@ -38,44 +38,11 @@
#include "entcode.h"
#include "os_support.h"
-#define PI 3.141592653f
-
/* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */
#define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15)
unsigned isqrt32(opus_uint32 _val);
-/* CELT doesn't need it for fixed-point, by analysis.c does. */
-#if !defined(FIXED_POINT) || defined(ANALYSIS_C)
-#define cA 0.43157974f
-#define cB 0.67848403f
-#define cC 0.08595542f
-#define cE ((float)PI/2)
-static OPUS_INLINE float fast_atan2f(float y, float x) {
- float x2, y2;
- x2 = x*x;
- y2 = y*y;
- /* For very small values, we don't care about the answer, so
- we can just return 0. */
- if (x2 + y2 < 1e-18f)
- {
- return 0;
- }
- if(x2<y2){
- float den = (y2 + cB*x2) * (y2 + cC*x2);
- return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE);
- }else{
- float den = (x2 + cB*y2) * (x2 + cC*y2);
- return x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
- }
-}
-#undef cA
-#undef cB
-#undef cC
-#undef cE
-#endif
-
-
#ifndef OVERRIDE_CELT_MAXABS16
static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len)
{
@@ -113,6 +80,7 @@ static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len)
#ifndef FIXED_POINT
+#define PI 3.141592653f
#define celt_sqrt(x) ((float)sqrt(x))
#define celt_rsqrt(x) (1.f/celt_sqrt(x))
#define celt_rsqrt_norm(x) (celt_rsqrt(x))
@@ -179,7 +147,7 @@ static OPUS_INLINE float celt_exp2(float x)
/** Integer log in base2. Undefined for zero and negative numbers */
static OPUS_INLINE opus_int16 celt_ilog2(opus_int32 x)
{
- celt_sig_assert(x>0);
+ celt_assert2(x>0, "celt_ilog2() only defined for strictly positive numbers");
return EC_ILOG(x)-1;
}
#endif
diff --git a/thirdparty/opus/celt/mdct.c b/thirdparty/opus/celt/mdct.c
index 5c6dab5b75..5315ad11a3 100644
--- a/thirdparty/opus/celt/mdct.c
+++ b/thirdparty/opus/celt/mdct.c
@@ -270,8 +270,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
int rev;
kiss_fft_scalar yr, yi;
rev = *bitrev++;
- yr = ADD32_ovflw(S_MUL(*xp2, t[i]), S_MUL(*xp1, t[N4+i]));
- yi = SUB32_ovflw(S_MUL(*xp1, t[i]), S_MUL(*xp2, t[N4+i]));
+ yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]);
+ yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, t[N4+i]);
/* We swap real and imag because we use an FFT instead of an IFFT. */
yp[2*rev+1] = yr;
yp[2*rev] = yi;
@@ -301,8 +301,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
t0 = t[i];
t1 = t[N4+i];
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
- yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1));
- yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0));
+ yr = S_MUL(re,t0) + S_MUL(im,t1);
+ yi = S_MUL(re,t1) - S_MUL(im,t0);
/* We swap real and imag because we're using an FFT instead of an IFFT. */
re = yp1[1];
im = yp1[0];
@@ -312,8 +312,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
t0 = t[(N4-i-1)];
t1 = t[(N2-i-1)];
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
- yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1));
- yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0));
+ yr = S_MUL(re,t0) + S_MUL(im,t1);
+ yi = S_MUL(re,t1) - S_MUL(im,t0);
yp1[0] = yr;
yp0[1] = yi;
yp0 += 2;
@@ -333,8 +333,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
kiss_fft_scalar x1, x2;
x1 = *xp1;
x2 = *yp1;
- *yp1++ = SUB32_ovflw(MULT16_32_Q15(*wp2, x2), MULT16_32_Q15(*wp1, x1));
- *xp1-- = ADD32_ovflw(MULT16_32_Q15(*wp1, x2), MULT16_32_Q15(*wp2, x1));
+ *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1);
+ *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1);
wp1++;
wp2--;
}
diff --git a/thirdparty/opus/celt/mips/celt_mipsr1.h b/thirdparty/opus/celt/mips/celt_mipsr1.h
index c332fe0471..e85661a661 100644
--- a/thirdparty/opus/celt/mips/celt_mipsr1.h
+++ b/thirdparty/opus/celt/mips/celt_mipsr1.h
@@ -53,7 +53,6 @@
#include "celt_lpc.h"
#include "vq.h"
-#define OVERRIDE_COMB_FILTER_CONST
#define OVERRIDE_comb_filter
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
diff --git a/thirdparty/opus/celt/mips/vq_mipsr1.h b/thirdparty/opus/celt/mips/vq_mipsr1.h
index f26a33e755..54cef86133 100644
--- a/thirdparty/opus/celt/mips/vq_mipsr1.h
+++ b/thirdparty/opus/celt/mips/vq_mipsr1.h
@@ -36,6 +36,11 @@
#include "mathops.h"
#include "arch.h"
+static unsigned extract_collapse_mask(int *iy, int N, int B);
+static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X, int N, opus_val32 Ryy, opus_val16 gain);
+static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread);
+static void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch);
+
#define OVERRIDE_vq_exp_rotation1
static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
{
@@ -64,7 +69,11 @@ static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_
}
#define OVERRIDE_renormalise_vector
-void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch)
+
+#define renormalise_vector(X, N, gain, arch) \
+ (renormalise_vector_mips(X, N, gain, arch))
+
+void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch)
{
int i;
#ifdef FIXED_POINT
diff --git a/thirdparty/opus/celt/modes.c b/thirdparty/opus/celt/modes.c
index 390c5e8aeb..911686e905 100644
--- a/thirdparty/opus/celt/modes.c
+++ b/thirdparty/opus/celt/modes.c
@@ -427,7 +427,7 @@ void opus_custom_mode_destroy(CELTMode *mode)
}
#endif /* CUSTOM_MODES_ONLY */
opus_free((opus_int16*)mode->eBands);
- opus_free((unsigned char*)mode->allocVectors);
+ opus_free((opus_int16*)mode->allocVectors);
opus_free((opus_val16*)mode->window);
opus_free((opus_int16*)mode->logN);
diff --git a/thirdparty/opus/celt/pitch.c b/thirdparty/opus/celt/pitch.c
index 872582a48a..bf46e7d562 100644
--- a/thirdparty/opus/celt/pitch.c
+++ b/thirdparty/opus/celt/pitch.c
@@ -102,9 +102,11 @@ static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len,
}
}
-static void celt_fir5(opus_val16 *x,
+static void celt_fir5(const opus_val16 *x,
const opus_val16 *num,
- int N)
+ opus_val16 *y,
+ int N,
+ opus_val16 *mem)
{
int i;
opus_val16 num0, num1, num2, num3, num4;
@@ -114,11 +116,11 @@ static void celt_fir5(opus_val16 *x,
num2=num[2];
num3=num[3];
num4=num[4];
- mem0=0;
- mem1=0;
- mem2=0;
- mem3=0;
- mem4=0;
+ mem0=mem[0];
+ mem1=mem[1];
+ mem2=mem[2];
+ mem3=mem[3];
+ mem4=mem[4];
for (i=0;i<N;i++)
{
opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
@@ -132,8 +134,13 @@ static void celt_fir5(opus_val16 *x,
mem2 = mem1;
mem1 = mem0;
mem0 = x[i];
- x[i] = ROUND16(sum, SIG_SHIFT);
+ y[i] = ROUND16(sum, SIG_SHIFT);
}
+ mem[0]=mem0;
+ mem[1]=mem1;
+ mem[2]=mem2;
+ mem[3]=mem3;
+ mem[4]=mem4;
}
@@ -143,7 +150,7 @@ void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x
int i;
opus_val32 ac[5];
opus_val16 tmp=Q15ONE;
- opus_val16 lpc[4];
+ opus_val16 lpc[4], mem[5]={0,0,0,0,0};
opus_val16 lpc2[5];
opus_val16 c1 = QCONST16(.8f,15);
#ifdef FIXED_POINT
@@ -204,7 +211,7 @@ void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x
lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
- celt_fir5(x_lp, lpc2, len>>1);
+ celt_fir5(x_lp, lpc2, x_lp, len>>1, mem);
}
/* Pure C implementation. */
@@ -213,8 +220,13 @@ opus_val32
#else
void
#endif
+#if defined(OVERRIDE_PITCH_XCORR)
celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
+ opus_val32 *xcorr, int len, int max_pitch)
+#else
+celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
opus_val32 *xcorr, int len, int max_pitch, int arch)
+#endif
{
#if 0 /* This is a simple version of the pitch correlation that should work
@@ -249,11 +261,15 @@ celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
opus_val32 maxcorr=1;
#endif
celt_assert(max_pitch>0);
- celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
+ celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
for (i=0;i<max_pitch-3;i+=4)
{
opus_val32 sum[4]={0,0,0,0};
+#if defined(OVERRIDE_PITCH_XCORR)
+ xcorr_kernel_c(_x, _y+i, sum, len);
+#else
xcorr_kernel(_x, _y+i, sum, len, arch);
+#endif
xcorr[i]=sum[0];
xcorr[i+1]=sum[1];
xcorr[i+2]=sum[2];
@@ -269,7 +285,11 @@ celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
for (;i<max_pitch;i++)
{
opus_val32 sum;
+#if defined(OVERRIDE_PITCH_XCORR)
+ sum = celt_inner_prod_c(_x, _y+i, len);
+#else
sum = celt_inner_prod(_x, _y+i, len, arch);
+#endif
xcorr[i] = sum;
#ifdef FIXED_POINT
maxcorr = MAX32(maxcorr, sum);
@@ -358,7 +378,7 @@ void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTR
for (j=0;j<len>>1;j++)
sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
#else
- sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
+ sum = celt_inner_prod_c(x_lp, y+i, len>>1);
#endif
xcorr[i] = MAX32(-1, sum);
#ifdef FIXED_POINT
@@ -404,7 +424,7 @@ static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy
sx = celt_ilog2(xx)-14;
sy = celt_ilog2(yy)-14;
shift = sx + sy;
- x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14);
+ x2y2 = MULT16_16_Q14(VSHR32(xx, sx), VSHR32(yy, sy));
if (shift & 1) {
if (x2y2 < 32768)
{
diff --git a/thirdparty/opus/celt/pitch.h b/thirdparty/opus/celt/pitch.h
index e425f56aea..d3503532a0 100644
--- a/thirdparty/opus/celt/pitch.h
+++ b/thirdparty/opus/celt/pitch.h
@@ -46,7 +46,8 @@
#include "mips/pitch_mipsr1.h"
#endif
-#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \
+ || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
# include "arm/pitch_arm.h"
#endif
@@ -183,10 +184,17 @@ opus_val32
void
#endif
celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
+ opus_val32 *xcorr, int len, int max_pitch);
+
+#if !defined(OVERRIDE_PITCH_XCORR)
+#ifdef FIXED_POINT
+opus_val32
+#else
+void
+#endif
+celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
opus_val32 *xcorr, int len, int max_pitch, int arch);
-#ifndef OVERRIDE_PITCH_XCORR
-# define celt_pitch_xcorr celt_pitch_xcorr_c
#endif
#endif
diff --git a/thirdparty/opus/celt/quant_bands.c b/thirdparty/opus/celt/quant_bands.c
index 39a221eda5..95076e0af2 100644
--- a/thirdparty/opus/celt/quant_bands.c
+++ b/thirdparty/opus/celt/quant_bands.c
@@ -418,7 +418,6 @@ void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *ol
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
#endif
oldEBands[i+c*m->nbEBands] += offset;
- error[i+c*m->nbEBands] -= offset;
bits_left--;
} while (++c < C);
}
@@ -457,7 +456,7 @@ void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *ol
/* It would be better to express this invariant as a
test on C at function entry, but that isn't enough
to make the static analyzer happy. */
- celt_sig_assert(c<2);
+ celt_assert(c<2);
tell = ec_tell(dec);
if(budget-tell>=15)
{
@@ -548,15 +547,9 @@ void amp2Log2(const CELTMode *m, int effEnd, int end,
c=0;
do {
for (i=0;i<effEnd;i++)
- {
bandLogE[i+c*m->nbEBands] =
- celt_log2(bandE[i+c*m->nbEBands])
+ celt_log2(SHL32(bandE[i+c*m->nbEBands],2))
- SHL16((opus_val16)eMeans[i],6);
-#ifdef FIXED_POINT
- /* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */
- bandLogE[i+c*m->nbEBands] += QCONST16(2.f, DB_SHIFT);
-#endif
- }
for (i=effEnd;i<end;i++)
bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT);
} while (++c < C);
diff --git a/thirdparty/opus/celt/rate.c b/thirdparty/opus/celt/rate.c
index 465e1ba26c..7dfa5be8a6 100644
--- a/thirdparty/opus/celt/rate.c
+++ b/thirdparty/opus/celt/rate.c
@@ -348,17 +348,12 @@ static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end,
/*This if() block is the only part of the allocation function that
is not a mandatory part of the bitstream: any bands we choose to
skip here must be explicitly signaled.*/
- int depth_threshold;
- /*We choose a threshold with some hysteresis to keep bands from
- fluctuating in and out, but we try not to fold below a certain point. */
- if (codedBands > 17)
- depth_threshold = j<prev ? 7 : 9;
- else
- depth_threshold = 0;
+ /*Choose a threshold with some hysteresis to keep bands from
+ fluctuating in and out.*/
#ifdef FUZZING
if ((rand()&0x1) == 0)
#else
- if (codedBands<=start+2 || (band_bits > (depth_threshold*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth))
+ if (codedBands<=start+2 || (band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth))
#endif
{
ec_enc_bit_logp(ec, 1, 1);
@@ -529,7 +524,7 @@ static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end,
return codedBands;
}
-int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
+int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth)
{
int lo, hi, len, j;
diff --git a/thirdparty/opus/celt/rate.h b/thirdparty/opus/celt/rate.h
index fad5e412da..515f7687ce 100644
--- a/thirdparty/opus/celt/rate.h
+++ b/thirdparty/opus/celt/rate.h
@@ -95,7 +95,7 @@ static OPUS_INLINE int pulses2bits(const CELTMode *m, int band, int LM, int puls
@param pulses Number of pulses per band (returned)
@return Total number of bits allocated
*/
-int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
+int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero,
opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth);
#endif
diff --git a/thirdparty/opus/celt/static_modes_fixed_arm_ne10.h b/thirdparty/opus/celt/static_modes_fixed_arm_ne10.h
index 7623092192..b8ef0cee98 100644
--- a/thirdparty/opus/celt/static_modes_fixed_arm_ne10.h
+++ b/thirdparty/opus/celt/static_modes_fixed_arm_ne10.h
@@ -1,7 +1,7 @@
/* The contents of this file was automatically generated by
* dump_mode_arm_ne10.c with arguments: 48000 960
* It contains static definitions for some pre-defined modes. */
-#include <NE10_types.h>
+#include <NE10_init.h>
#ifndef NE10_FFT_PARAMS48000_960
#define NE10_FFT_PARAMS48000_960
diff --git a/thirdparty/opus/celt/static_modes_float_arm_ne10.h b/thirdparty/opus/celt/static_modes_float_arm_ne10.h
index 66e1abb101..934a82a420 100644
--- a/thirdparty/opus/celt/static_modes_float_arm_ne10.h
+++ b/thirdparty/opus/celt/static_modes_float_arm_ne10.h
@@ -1,7 +1,7 @@
/* The contents of this file was automatically generated by
* dump_mode_arm_ne10.c with arguments: 48000 960
* It contains static definitions for some pre-defined modes. */
-#include <NE10_types.h>
+#include <NE10_init.h>
#ifndef NE10_FFT_PARAMS48000_960
#define NE10_FFT_PARAMS48000_960
diff --git a/thirdparty/opus/celt/tests/test_unit_cwrs32.c b/thirdparty/opus/celt/tests/test_unit_cwrs32.c
new file mode 100644
index 0000000000..36dd8af5f5
--- /dev/null
+++ b/thirdparty/opus/celt/tests/test_unit_cwrs32.c
@@ -0,0 +1,161 @@
+/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation,
+ Gregory Maxwell
+ Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifndef CUSTOM_MODES
+#define CUSTOM_MODES
+#else
+#define TEST_CUSTOM_MODES
+#endif
+
+#define CELT_C
+#include "stack_alloc.h"
+#include "entenc.c"
+#include "entdec.c"
+#include "entcode.c"
+#include "cwrs.c"
+#include "mathops.c"
+#include "rate.h"
+
+#define NMAX (240)
+#define KMAX (128)
+
+#ifdef TEST_CUSTOM_MODES
+
+#define NDIMS (44)
+static const int pn[NDIMS]={
+ 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 18, 20, 22,
+ 24, 26, 28, 30, 32, 36, 40, 44, 48,
+ 52, 56, 60, 64, 72, 80, 88, 96, 104,
+ 112, 120, 128, 144, 160, 176, 192, 208
+};
+static const int pkmax[NDIMS]={
+ 128, 128, 128, 128, 88, 52, 36, 26, 22,
+ 18, 16, 15, 13, 12, 12, 11, 10, 9,
+ 9, 8, 8, 7, 7, 7, 7, 6, 6,
+ 6, 6, 6, 5, 5, 5, 5, 5, 5,
+ 4, 4, 4, 4, 4, 4, 4, 4
+};
+
+#else /* TEST_CUSTOM_MODES */
+
+#define NDIMS (22)
+static const int pn[NDIMS]={
+ 2, 3, 4, 6, 8, 9, 11, 12, 16,
+ 18, 22, 24, 32, 36, 44, 48, 64, 72,
+ 88, 96, 144, 176
+};
+static const int pkmax[NDIMS]={
+ 128, 128, 128, 88, 36, 26, 18, 16, 12,
+ 11, 9, 9, 7, 7, 6, 6, 5, 5,
+ 5, 5, 4, 4
+};
+
+#endif
+
+int main(void){
+ int t;
+ int n;
+ ALLOC_STACK;
+ for(t=0;t<NDIMS;t++){
+ int pseudo;
+ n=pn[t];
+ for(pseudo=1;pseudo<41;pseudo++)
+ {
+ int k;
+#if defined(SMALL_FOOTPRINT)
+ opus_uint32 uu[KMAX+2U];
+#endif
+ opus_uint32 inc;
+ opus_uint32 nc;
+ opus_uint32 i;
+ k=get_pulses(pseudo);
+ if (k>pkmax[t])break;
+ printf("Testing CWRS with N=%i, K=%i...\n",n,k);
+#if defined(SMALL_FOOTPRINT)
+ nc=ncwrs_urow(n,k,uu);
+#else
+ nc=CELT_PVQ_V(n,k);
+#endif
+ inc=nc/20000;
+ if(inc<1)inc=1;
+ for(i=0;i<nc;i+=inc){
+#if defined(SMALL_FOOTPRINT)
+ opus_uint32 u[KMAX+2U];
+#endif
+ int y[NMAX];
+ int sy;
+ opus_uint32 v;
+ opus_uint32 ii;
+ int j;
+#if defined(SMALL_FOOTPRINT)
+ memcpy(u,uu,(k+2U)*sizeof(*u));
+ cwrsi(n,k,i,y,u);
+#else
+ cwrsi(n,k,i,y);
+#endif
+ sy=0;
+ for(j=0;j<n;j++)sy+=abs(y[j]);
+ if(sy!=k){
+ fprintf(stderr,"N=%d Pulse count mismatch in cwrsi (%d!=%d).\n",
+ n,sy,k);
+ return 99;
+ }
+ /*printf("%6u of %u:",i,nc);
+ for(j=0;j<n;j++)printf(" %+3i",y[j]);
+ printf(" ->");*/
+#if defined(SMALL_FOOTPRINT)
+ ii=icwrs(n,k,&v,y,u);
+#else
+ ii=icwrs(n,y);
+ v=CELT_PVQ_V(n,k);
+#endif
+ if(ii!=i){
+ fprintf(stderr,"Combination-index mismatch (%lu!=%lu).\n",
+ (long)ii,(long)i);
+ return 1;
+ }
+ if(v!=nc){
+ fprintf(stderr,"Combination count mismatch (%lu!=%lu).\n",
+ (long)v,(long)nc);
+ return 2;
+ }
+ /*printf(" %6u\n",i);*/
+ }
+ /*printf("\n");*/
+ }
+ }
+ return 0;
+}
diff --git a/thirdparty/opus/celt/tests/test_unit_dft.c b/thirdparty/opus/celt/tests/test_unit_dft.c
new file mode 100644
index 0000000000..6166eb0e4f
--- /dev/null
+++ b/thirdparty/opus/celt/tests/test_unit_dft.c
@@ -0,0 +1,189 @@
+/* Copyright (c) 2008 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define SKIP_CONFIG_H
+
+#ifndef CUSTOM_MODES
+#define CUSTOM_MODES
+#endif
+
+#include <stdio.h>
+
+#define CELT_C
+#define TEST_UNIT_DFT_C
+#include "stack_alloc.h"
+#include "kiss_fft.h"
+#include "kiss_fft.c"
+#include "mathops.c"
+#include "entcode.c"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1)
+# include "x86/x86cpu.c"
+#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+# include "arm/armcpu.c"
+# include "celt_lpc.c"
+# include "pitch.c"
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+# include "arm/celt_neon_intr.c"
+# if defined(HAVE_ARM_NE10)
+# include "mdct.c"
+# include "arm/celt_ne10_fft.c"
+# include "arm/celt_ne10_mdct.c"
+# endif
+# endif
+# include "arm/arm_celt_map.c"
+#endif
+
+#ifndef M_PI
+#define M_PI 3.141592653
+#endif
+
+int ret = 0;
+
+void check(kiss_fft_cpx * in,kiss_fft_cpx * out,int nfft,int isinverse)
+{
+ int bin,k;
+ double errpow=0,sigpow=0, snr;
+
+ for (bin=0;bin<nfft;++bin) {
+ double ansr = 0;
+ double ansi = 0;
+ double difr;
+ double difi;
+
+ for (k=0;k<nfft;++k) {
+ double phase = -2*M_PI*bin*k/nfft;
+ double re = cos(phase);
+ double im = sin(phase);
+ if (isinverse)
+ im = -im;
+
+ if (!isinverse)
+ {
+ re /= nfft;
+ im /= nfft;
+ }
+
+ ansr += in[k].r * re - in[k].i * im;
+ ansi += in[k].r * im + in[k].i * re;
+ }
+ /*printf ("%d %d ", (int)ansr, (int)ansi);*/
+ difr = ansr - out[bin].r;
+ difi = ansi - out[bin].i;
+ errpow += difr*difr + difi*difi;
+ sigpow += ansr*ansr+ansi*ansi;
+ }
+ snr = 10*log10(sigpow/errpow);
+ printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
+ if (snr<60) {
+ printf( "** poor snr: %f ** \n", snr);
+ ret = 1;
+ }
+}
+
+void test1d(int nfft,int isinverse,int arch)
+{
+ size_t buflen = sizeof(kiss_fft_cpx)*nfft;
+
+ kiss_fft_cpx * in = (kiss_fft_cpx*)malloc(buflen);
+ kiss_fft_cpx * out= (kiss_fft_cpx*)malloc(buflen);
+ kiss_fft_state *cfg = opus_fft_alloc(nfft,0,0,arch);
+ int k;
+
+ for (k=0;k<nfft;++k) {
+ in[k].r = (rand() % 32767) - 16384;
+ in[k].i = (rand() % 32767) - 16384;
+ }
+
+ for (k=0;k<nfft;++k) {
+ in[k].r *= 32768;
+ in[k].i *= 32768;
+ }
+
+ if (isinverse)
+ {
+ for (k=0;k<nfft;++k) {
+ in[k].r /= nfft;
+ in[k].i /= nfft;
+ }
+ }
+
+ /*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/
+
+ if (isinverse)
+ opus_ifft(cfg,in,out, arch);
+ else
+ opus_fft(cfg,in,out, arch);
+
+ /*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/
+
+ check(in,out,nfft,isinverse);
+
+ free(in);
+ free(out);
+ opus_fft_free(cfg, arch);
+}
+
+int main(int argc,char ** argv)
+{
+ ALLOC_STACK;
+ int arch = opus_select_arch();
+
+ if (argc>1) {
+ int k;
+ for (k=1;k<argc;++k) {
+ test1d(atoi(argv[k]),0,arch);
+ test1d(atoi(argv[k]),1,arch);
+ }
+ }else{
+ test1d(32,0,arch);
+ test1d(32,1,arch);
+ test1d(128,0,arch);
+ test1d(128,1,arch);
+ test1d(256,0,arch);
+ test1d(256,1,arch);
+#ifndef RADIX_TWO_ONLY
+ test1d(36,0,arch);
+ test1d(36,1,arch);
+ test1d(50,0,arch);
+ test1d(50,1,arch);
+ test1d(60,0,arch);
+ test1d(60,1,arch);
+ test1d(120,0,arch);
+ test1d(120,1,arch);
+ test1d(240,0,arch);
+ test1d(240,1,arch);
+ test1d(480,0,arch);
+ test1d(480,1,arch);
+#endif
+ }
+ return ret;
+}
diff --git a/thirdparty/opus/celt/tests/test_unit_entropy.c b/thirdparty/opus/celt/tests/test_unit_entropy.c
new file mode 100644
index 0000000000..ff9265864c
--- /dev/null
+++ b/thirdparty/opus/celt/tests/test_unit_entropy.c
@@ -0,0 +1,382 @@
+/* Copyright (c) 2007-2011 Xiph.Org Foundation, Mozilla Corporation,
+ Gregory Maxwell
+ Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+#include "entcode.h"
+#include "entenc.h"
+#include "entdec.h"
+#include <string.h>
+
+#include "entenc.c"
+#include "entdec.c"
+#include "entcode.c"
+
+#ifndef M_LOG2E
+# define M_LOG2E 1.4426950408889634074
+#endif
+#define DATA_SIZE 10000000
+#define DATA_SIZE2 10000
+
+int main(int _argc,char **_argv){
+ ec_enc enc;
+ ec_dec dec;
+ long nbits;
+ long nbits2;
+ double entropy;
+ int ft;
+ int ftb;
+ int sz;
+ int i;
+ int ret;
+ unsigned int sym;
+ unsigned int seed;
+ unsigned char *ptr;
+ const char *env_seed;
+ ret=0;
+ entropy=0;
+ if (_argc > 2) {
+ fprintf(stderr, "Usage: %s [<seed>]\n", _argv[0]);
+ return 1;
+ }
+ env_seed = getenv("SEED");
+ if (_argc > 1)
+ seed = atoi(_argv[1]);
+ else if (env_seed)
+ seed = atoi(env_seed);
+ else
+ seed = time(NULL);
+ /*Testing encoding of raw bit values.*/
+ ptr = (unsigned char *)malloc(DATA_SIZE);
+ ec_enc_init(&enc,ptr, DATA_SIZE);
+ for(ft=2;ft<1024;ft++){
+ for(i=0;i<ft;i++){
+ entropy+=log(ft)*M_LOG2E;
+ ec_enc_uint(&enc,i,ft);
+ }
+ }
+ /*Testing encoding of raw bit values.*/
+ for(ftb=1;ftb<16;ftb++){
+ for(i=0;i<(1<<ftb);i++){
+ entropy+=ftb;
+ nbits=ec_tell(&enc);
+ ec_enc_bits(&enc,i,ftb);
+ nbits2=ec_tell(&enc);
+ if(nbits2-nbits!=ftb){
+ fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
+ nbits2-nbits,ftb);
+ ret=-1;
+ }
+ }
+ }
+ nbits=ec_tell_frac(&enc);
+ ec_enc_done(&enc);
+ fprintf(stderr,
+ "Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n",
+ entropy,ldexp(nbits,-3),100*(nbits-ldexp(entropy,3))/nbits);
+ fprintf(stderr,"Packed to %li bytes.\n",(long)ec_range_bytes(&enc));
+ ec_dec_init(&dec,ptr,DATA_SIZE);
+ for(ft=2;ft<1024;ft++){
+ for(i=0;i<ft;i++){
+ sym=ec_dec_uint(&dec,ft);
+ if(sym!=(unsigned)i){
+ fprintf(stderr,"Decoded %i instead of %i with ft of %i.\n",sym,i,ft);
+ ret=-1;
+ }
+ }
+ }
+ for(ftb=1;ftb<16;ftb++){
+ for(i=0;i<(1<<ftb);i++){
+ sym=ec_dec_bits(&dec,ftb);
+ if(sym!=(unsigned)i){
+ fprintf(stderr,"Decoded %i instead of %i with ftb of %i.\n",sym,i,ftb);
+ ret=-1;
+ }
+ }
+ }
+ nbits2=ec_tell_frac(&dec);
+ if(nbits!=nbits2){
+ fprintf(stderr,
+ "Reported number of bits used was %0.2lf, should be %0.2lf.\n",
+ ldexp(nbits2,-3),ldexp(nbits,-3));
+ ret=-1;
+ }
+ /*Testing an encoder bust prefers range coder data over raw bits.
+ This isn't a general guarantee, will only work for data that is buffered in
+ the encoder state and not yet stored in the user buffer, and should never
+ get used in practice.
+ It's mostly here for code coverage completeness.*/
+ /*Start with a 16-bit buffer.*/
+ ec_enc_init(&enc,ptr,2);
+ /*Write 7 raw bits.*/
+ ec_enc_bits(&enc,0x55,7);
+ /*Write 12.3 bits of range coder data.*/
+ ec_enc_uint(&enc,1,2);
+ ec_enc_uint(&enc,1,3);
+ ec_enc_uint(&enc,1,4);
+ ec_enc_uint(&enc,1,5);
+ ec_enc_uint(&enc,2,6);
+ ec_enc_uint(&enc,6,7);
+ ec_enc_done(&enc);
+ ec_dec_init(&dec,ptr,2);
+ if(!enc.error
+ /*The raw bits should have been overwritten by the range coder data.*/
+ ||ec_dec_bits(&dec,7)!=0x05
+ /*And all the range coder data should have been encoded correctly.*/
+ ||ec_dec_uint(&dec,2)!=1
+ ||ec_dec_uint(&dec,3)!=1
+ ||ec_dec_uint(&dec,4)!=1
+ ||ec_dec_uint(&dec,5)!=1
+ ||ec_dec_uint(&dec,6)!=2
+ ||ec_dec_uint(&dec,7)!=6){
+ fprintf(stderr,"Encoder bust overwrote range coder data with raw bits.\n");
+ ret=-1;
+ }
+ srand(seed);
+ fprintf(stderr,"Testing random streams... Random seed: %u (%.4X)\n", seed, rand() % 65536);
+ for(i=0;i<409600;i++){
+ unsigned *data;
+ unsigned *tell;
+ unsigned tell_bits;
+ int j;
+ int zeros;
+ ft=rand()/((RAND_MAX>>(rand()%11U))+1U)+10;
+ sz=rand()/((RAND_MAX>>(rand()%9U))+1U);
+ data=(unsigned *)malloc(sz*sizeof(*data));
+ tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
+ ec_enc_init(&enc,ptr,DATA_SIZE2);
+ zeros = rand()%13==0;
+ tell[0]=ec_tell_frac(&enc);
+ for(j=0;j<sz;j++){
+ if (zeros)
+ data[j]=0;
+ else
+ data[j]=rand()%ft;
+ ec_enc_uint(&enc,data[j],ft);
+ tell[j+1]=ec_tell_frac(&enc);
+ }
+ if (rand()%2==0)
+ while(ec_tell(&enc)%8 != 0)
+ ec_enc_uint(&enc, rand()%2, 2);
+ tell_bits = ec_tell(&enc);
+ ec_enc_done(&enc);
+ if(tell_bits!=(unsigned)ec_tell(&enc)){
+ fprintf(stderr,"ec_tell() changed after ec_enc_done(): %i instead of %i (Random seed: %u)\n",
+ ec_tell(&enc),tell_bits,seed);
+ ret=-1;
+ }
+ if ((tell_bits+7)/8 < ec_range_bytes(&enc))
+ {
+ fprintf (stderr, "ec_tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
+ ec_range_bytes(&enc), (tell_bits+7)/8,seed);
+ ret=-1;
+ }
+ ec_dec_init(&dec,ptr,DATA_SIZE2);
+ if(ec_tell_frac(&dec)!=tell[0]){
+ fprintf(stderr,
+ "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
+ 0,ec_tell_frac(&dec),tell[0],seed);
+ }
+ for(j=0;j<sz;j++){
+ sym=ec_dec_uint(&dec,ft);
+ if(sym!=data[j]){
+ fprintf(stderr,
+ "Decoded %i instead of %i with ft of %i at position %i of %i (Random seed: %u).\n",
+ sym,data[j],ft,j,sz,seed);
+ ret=-1;
+ }
+ if(ec_tell_frac(&dec)!=tell[j+1]){
+ fprintf(stderr,
+ "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
+ j+1,ec_tell_frac(&dec),tell[j+1],seed);
+ }
+ }
+ free(tell);
+ free(data);
+ }
+ /*Test compatibility between multiple different encode/decode routines.*/
+ for(i=0;i<409600;i++){
+ unsigned *logp1;
+ unsigned *data;
+ unsigned *tell;
+ unsigned *enc_method;
+ int j;
+ sz=rand()/((RAND_MAX>>(rand()%9U))+1U);
+ logp1=(unsigned *)malloc(sz*sizeof(*logp1));
+ data=(unsigned *)malloc(sz*sizeof(*data));
+ tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
+ enc_method=(unsigned *)malloc(sz*sizeof(*enc_method));
+ ec_enc_init(&enc,ptr,DATA_SIZE2);
+ tell[0]=ec_tell_frac(&enc);
+ for(j=0;j<sz;j++){
+ data[j]=rand()/((RAND_MAX>>1)+1);
+ logp1[j]=(rand()%15)+1;
+ enc_method[j]=rand()/((RAND_MAX>>2)+1);
+ switch(enc_method[j]){
+ case 0:{
+ ec_encode(&enc,data[j]?(1<<logp1[j])-1:0,
+ (1<<logp1[j])-(data[j]?0:1),1<<logp1[j]);
+ }break;
+ case 1:{
+ ec_encode_bin(&enc,data[j]?(1<<logp1[j])-1:0,
+ (1<<logp1[j])-(data[j]?0:1),logp1[j]);
+ }break;
+ case 2:{
+ ec_enc_bit_logp(&enc,data[j],logp1[j]);
+ }break;
+ case 3:{
+ unsigned char icdf[2];
+ icdf[0]=1;
+ icdf[1]=0;
+ ec_enc_icdf(&enc,data[j],icdf,logp1[j]);
+ }break;
+ }
+ tell[j+1]=ec_tell_frac(&enc);
+ }
+ ec_enc_done(&enc);
+ if((ec_tell(&enc)+7U)/8U<ec_range_bytes(&enc)){
+ fprintf(stderr,"tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
+ ec_range_bytes(&enc),(ec_tell(&enc)+7)/8,seed);
+ ret=-1;
+ }
+ ec_dec_init(&dec,ptr,DATA_SIZE2);
+ if(ec_tell_frac(&dec)!=tell[0]){
+ fprintf(stderr,
+ "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
+ 0,ec_tell_frac(&dec),tell[0],seed);
+ }
+ for(j=0;j<sz;j++){
+ int fs;
+ int dec_method;
+ dec_method=rand()/((RAND_MAX>>2)+1);
+ switch(dec_method){
+ case 0:{
+ fs=ec_decode(&dec,1<<logp1[j]);
+ sym=fs>=(1<<logp1[j])-1;
+ ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
+ (1<<logp1[j])-(sym?0:1),1<<logp1[j]);
+ }break;
+ case 1:{
+ fs=ec_decode_bin(&dec,logp1[j]);
+ sym=fs>=(1<<logp1[j])-1;
+ ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
+ (1<<logp1[j])-(sym?0:1),1<<logp1[j]);
+ }break;
+ case 2:{
+ sym=ec_dec_bit_logp(&dec,logp1[j]);
+ }break;
+ case 3:{
+ unsigned char icdf[2];
+ icdf[0]=1;
+ icdf[1]=0;
+ sym=ec_dec_icdf(&dec,icdf,logp1[j]);
+ }break;
+ }
+ if(sym!=data[j]){
+ fprintf(stderr,
+ "Decoded %i instead of %i with logp1 of %i at position %i of %i (Random seed: %u).\n",
+ sym,data[j],logp1[j],j,sz,seed);
+ fprintf(stderr,"Encoding method: %i, decoding method: %i\n",
+ enc_method[j],dec_method);
+ ret=-1;
+ }
+ if(ec_tell_frac(&dec)!=tell[j+1]){
+ fprintf(stderr,
+ "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
+ j+1,ec_tell_frac(&dec),tell[j+1],seed);
+ }
+ }
+ free(enc_method);
+ free(tell);
+ free(data);
+ free(logp1);
+ }
+ ec_enc_init(&enc,ptr,DATA_SIZE2);
+ ec_enc_bit_logp(&enc,0,1);
+ ec_enc_bit_logp(&enc,0,1);
+ ec_enc_bit_logp(&enc,0,1);
+ ec_enc_bit_logp(&enc,0,1);
+ ec_enc_bit_logp(&enc,0,2);
+ ec_enc_patch_initial_bits(&enc,3,2);
+ if(enc.error){
+ fprintf(stderr,"patch_initial_bits failed");
+ ret=-1;
+ }
+ ec_enc_patch_initial_bits(&enc,0,5);
+ if(!enc.error){
+ fprintf(stderr,"patch_initial_bits didn't fail when it should have");
+ ret=-1;
+ }
+ ec_enc_done(&enc);
+ if(ec_range_bytes(&enc)!=1||ptr[0]!=192){
+ fprintf(stderr,"Got %d when expecting 192 for patch_initial_bits",ptr[0]);
+ ret=-1;
+ }
+ ec_enc_init(&enc,ptr,DATA_SIZE2);
+ ec_enc_bit_logp(&enc,0,1);
+ ec_enc_bit_logp(&enc,0,1);
+ ec_enc_bit_logp(&enc,1,6);
+ ec_enc_bit_logp(&enc,0,2);
+ ec_enc_patch_initial_bits(&enc,0,2);
+ if(enc.error){
+ fprintf(stderr,"patch_initial_bits failed");
+ ret=-1;
+ }
+ ec_enc_done(&enc);
+ if(ec_range_bytes(&enc)!=2||ptr[0]!=63){
+ fprintf(stderr,"Got %d when expecting 63 for patch_initial_bits",ptr[0]);
+ ret=-1;
+ }
+ ec_enc_init(&enc,ptr,2);
+ ec_enc_bit_logp(&enc,0,2);
+ for(i=0;i<48;i++){
+ ec_enc_bits(&enc,0,1);
+ }
+ ec_enc_done(&enc);
+ if(!enc.error){
+ fprintf(stderr,"Raw bits overfill didn't fail when it should have");
+ ret=-1;
+ }
+ ec_enc_init(&enc,ptr,2);
+ for(i=0;i<17;i++){
+ ec_enc_bits(&enc,0,1);
+ }
+ ec_enc_done(&enc);
+ if(!enc.error){
+ fprintf(stderr,"17 raw bits encoded in two bytes");
+ ret=-1;
+ }
+ free(ptr);
+ return ret;
+}
diff --git a/thirdparty/opus/celt/tests/test_unit_laplace.c b/thirdparty/opus/celt/tests/test_unit_laplace.c
new file mode 100644
index 0000000000..22951e29ee
--- /dev/null
+++ b/thirdparty/opus/celt/tests/test_unit_laplace.c
@@ -0,0 +1,93 @@
+/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation
+ Written by Jean-Marc Valin and Timothy B. Terriberry */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "laplace.h"
+#define CELT_C
+#include "stack_alloc.h"
+
+#include "entenc.c"
+#include "entdec.c"
+#include "entcode.c"
+#include "laplace.c"
+
+#define DATA_SIZE 40000
+
+int ec_laplace_get_start_freq(int decay)
+{
+ opus_uint32 ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN+1);
+ int fs = (ft*(16384-decay))/(16384+decay);
+ return fs+LAPLACE_MINP;
+}
+
+int main(void)
+{
+ int i;
+ int ret = 0;
+ ec_enc enc;
+ ec_dec dec;
+ unsigned char *ptr;
+ int val[10000], decay[10000];
+ ALLOC_STACK;
+ ptr = (unsigned char *)malloc(DATA_SIZE);
+ ec_enc_init(&enc,ptr,DATA_SIZE);
+
+ val[0] = 3; decay[0] = 6000;
+ val[1] = 0; decay[1] = 5800;
+ val[2] = -1; decay[2] = 5600;
+ for (i=3;i<10000;i++)
+ {
+ val[i] = rand()%15-7;
+ decay[i] = rand()%11000+5000;
+ }
+ for (i=0;i<10000;i++)
+ ec_laplace_encode(&enc, &val[i],
+ ec_laplace_get_start_freq(decay[i]), decay[i]);
+
+ ec_enc_done(&enc);
+
+ ec_dec_init(&dec,ec_get_buffer(&enc),ec_range_bytes(&enc));
+
+ for (i=0;i<10000;i++)
+ {
+ int d = ec_laplace_decode(&dec,
+ ec_laplace_get_start_freq(decay[i]), decay[i]);
+ if (d != val[i])
+ {
+ fprintf (stderr, "Got %d instead of %d\n", d, val[i]);
+ ret = 1;
+ }
+ }
+
+ free(ptr);
+ return ret;
+}
diff --git a/thirdparty/opus/celt/tests/test_unit_mathops.c b/thirdparty/opus/celt/tests/test_unit_mathops.c
new file mode 100644
index 0000000000..fd3319da91
--- /dev/null
+++ b/thirdparty/opus/celt/tests/test_unit_mathops.c
@@ -0,0 +1,304 @@
+/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation,
+ Gregory Maxwell
+ Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef CUSTOM_MODES
+#define CUSTOM_MODES
+#endif
+
+#define CELT_C
+
+#include <stdio.h>
+#include <math.h>
+#include "mathops.c"
+#include "entenc.c"
+#include "entdec.c"
+#include "entcode.c"
+#include "bands.c"
+#include "quant_bands.c"
+#include "laplace.c"
+#include "vq.c"
+#include "cwrs.c"
+#include "pitch.c"
+#include "celt_lpc.c"
+#include "celt.c"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) || defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1)
+# if defined(OPUS_X86_MAY_HAVE_SSE)
+# include "x86/pitch_sse.c"
+# endif
+# if defined(OPUS_X86_MAY_HAVE_SSE2)
+# include "x86/pitch_sse2.c"
+# endif
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+# include "x86/pitch_sse4_1.c"
+# include "x86/celt_lpc_sse.c"
+# endif
+# include "x86/x86_celt_map.c"
+#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+# include "arm/armcpu.c"
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+# include "arm/celt_neon_intr.c"
+# if defined(HAVE_ARM_NE10)
+# include "kiss_fft.c"
+# include "mdct.c"
+# include "arm/celt_ne10_fft.c"
+# include "arm/celt_ne10_mdct.c"
+# endif
+# endif
+# include "arm/arm_celt_map.c"
+#endif
+
+#ifdef FIXED_POINT
+#define WORD "%d"
+#else
+#define WORD "%f"
+#endif
+
+int ret = 0;
+
+void testdiv(void)
+{
+ opus_int32 i;
+ for (i=1;i<=327670;i++)
+ {
+ double prod;
+ opus_val32 val;
+ val = celt_rcp(i);
+#ifdef FIXED_POINT
+ prod = (1./32768./65526.)*val*i;
+#else
+ prod = val*i;
+#endif
+ if (fabs(prod-1) > .00025)
+ {
+ fprintf (stderr, "div failed: 1/%d="WORD" (product = %f)\n", i, val, prod);
+ ret = 1;
+ }
+ }
+}
+
+void testsqrt(void)
+{
+ opus_int32 i;
+ for (i=1;i<=1000000000;i++)
+ {
+ double ratio;
+ opus_val16 val;
+ val = celt_sqrt(i);
+ ratio = val/sqrt(i);
+ if (fabs(ratio - 1) > .0005 && fabs(val-sqrt(i)) > 2)
+ {
+ fprintf (stderr, "sqrt failed: sqrt(%d)="WORD" (ratio = %f)\n", i, val, ratio);
+ ret = 1;
+ }
+ i+= i>>10;
+ }
+}
+
+void testbitexactcos(void)
+{
+ int i;
+ opus_int32 min_d,max_d,last,chk;
+ chk=max_d=0;
+ last=min_d=32767;
+ for(i=64;i<=16320;i++)
+ {
+ opus_int32 d;
+ opus_int32 q=bitexact_cos(i);
+ chk ^= q*i;
+ d = last - q;
+ if (d>max_d)max_d=d;
+ if (d<min_d)min_d=d;
+ last = q;
+ }
+ if ((chk!=89408644)||(max_d!=5)||(min_d!=0)||(bitexact_cos(64)!=32767)||
+ (bitexact_cos(16320)!=200)||(bitexact_cos(8192)!=23171))
+ {
+ fprintf (stderr, "bitexact_cos failed\n");
+ ret = 1;
+ }
+}
+
+void testbitexactlog2tan(void)
+{
+ int i,fail;
+ opus_int32 min_d,max_d,last,chk;
+ fail=chk=max_d=0;
+ last=min_d=15059;
+ for(i=64;i<8193;i++)
+ {
+ opus_int32 d;
+ opus_int32 mid=bitexact_cos(i);
+ opus_int32 side=bitexact_cos(16384-i);
+ opus_int32 q=bitexact_log2tan(mid,side);
+ chk ^= q*i;
+ d = last - q;
+ if (q!=-1*bitexact_log2tan(side,mid))
+ fail = 1;
+ if (d>max_d)max_d=d;
+ if (d<min_d)min_d=d;
+ last = q;
+ }
+ if ((chk!=15821257)||(max_d!=61)||(min_d!=-2)||fail||
+ (bitexact_log2tan(32767,200)!=15059)||(bitexact_log2tan(30274,12540)!=2611)||
+ (bitexact_log2tan(23171,23171)!=0))
+ {
+ fprintf (stderr, "bitexact_log2tan failed\n");
+ ret = 1;
+ }
+}
+
+#ifndef FIXED_POINT
+void testlog2(void)
+{
+ float x;
+ for (x=0.001;x<1677700.0;x+=(x/8.0))
+ {
+ float error = fabs((1.442695040888963387*log(x))-celt_log2(x));
+ if (error>0.0009)
+ {
+ fprintf (stderr, "celt_log2 failed: fabs((1.442695040888963387*log(x))-celt_log2(x))>0.001 (x = %f, error = %f)\n", x,error);
+ ret = 1;
+ }
+ }
+}
+
+void testexp2(void)
+{
+ float x;
+ for (x=-11.0;x<24.0;x+=0.0007)
+ {
+ float error = fabs(x-(1.442695040888963387*log(celt_exp2(x))));
+ if (error>0.0002)
+ {
+ fprintf (stderr, "celt_exp2 failed: fabs(x-(1.442695040888963387*log(celt_exp2(x))))>0.0005 (x = %f, error = %f)\n", x,error);
+ ret = 1;
+ }
+ }
+}
+
+void testexp2log2(void)
+{
+ float x;
+ for (x=-11.0;x<24.0;x+=0.0007)
+ {
+ float error = fabs(x-(celt_log2(celt_exp2(x))));
+ if (error>0.001)
+ {
+ fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_log2(celt_exp2(x))))>0.001 (x = %f, error = %f)\n", x,error);
+ ret = 1;
+ }
+ }
+}
+#else
+void testlog2(void)
+{
+ opus_val32 x;
+ for (x=8;x<1073741824;x+=(x>>3))
+ {
+ float error = fabs((1.442695040888963387*log(x/16384.0))-celt_log2(x)/1024.0);
+ if (error>0.003)
+ {
+ fprintf (stderr, "celt_log2 failed: x = %ld, error = %f\n", (long)x,error);
+ ret = 1;
+ }
+ }
+}
+
+void testexp2(void)
+{
+ opus_val16 x;
+ for (x=-32768;x<15360;x++)
+ {
+ float error1 = fabs(x/1024.0-(1.442695040888963387*log(celt_exp2(x)/65536.0)));
+ float error2 = fabs(exp(0.6931471805599453094*x/1024.0)-celt_exp2(x)/65536.0);
+ if (error1>0.0002&&error2>0.00004)
+ {
+ fprintf (stderr, "celt_exp2 failed: x = "WORD", error1 = %f, error2 = %f\n", x,error1,error2);
+ ret = 1;
+ }
+ }
+}
+
+void testexp2log2(void)
+{
+ opus_val32 x;
+ for (x=8;x<65536;x+=(x>>3))
+ {
+ float error = fabs(x-0.25*celt_exp2(celt_log2(x)))/16384;
+ if (error>0.004)
+ {
+ fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_exp2(celt_log2(x))))>0.001 (x = %ld, error = %f)\n", (long)x,error);
+ ret = 1;
+ }
+ }
+}
+
+void testilog2(void)
+{
+ opus_val32 x;
+ for (x=1;x<=268435455;x+=127)
+ {
+ opus_val32 lg;
+ opus_val32 y;
+
+ lg = celt_ilog2(x);
+ if (lg<0 || lg>=31)
+ {
+ printf("celt_ilog2 failed: 0<=celt_ilog2(x)<31 (x = %d, celt_ilog2(x) = %d)\n",x,lg);
+ ret = 1;
+ }
+ y = 1<<lg;
+
+ if (x<y || (x>>1)>=y)
+ {
+ printf("celt_ilog2 failed: 2**celt_ilog2(x)<=x<2**(celt_ilog2(x)+1) (x = %d, 2**celt_ilog2(x) = %d)\n",x,y);
+ ret = 1;
+ }
+ }
+}
+#endif
+
+int main(void)
+{
+ testbitexactcos();
+ testbitexactlog2tan();
+ testdiv();
+ testsqrt();
+ testlog2();
+ testexp2();
+ testexp2log2();
+#ifdef FIXED_POINT
+ testilog2();
+#endif
+ return ret;
+}
diff --git a/thirdparty/opus/celt/tests/test_unit_mdct.c b/thirdparty/opus/celt/tests/test_unit_mdct.c
new file mode 100644
index 0000000000..8dbb9caa2e
--- /dev/null
+++ b/thirdparty/opus/celt/tests/test_unit_mdct.c
@@ -0,0 +1,230 @@
+/* Copyright (c) 2008-2011 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define SKIP_CONFIG_H
+
+#ifndef CUSTOM_MODES
+#define CUSTOM_MODES
+#endif
+
+#include <stdio.h>
+
+#define CELT_C
+#include "mdct.h"
+#include "stack_alloc.h"
+
+#include "kiss_fft.c"
+#include "mdct.c"
+#include "mathops.c"
+#include "entcode.c"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1)
+# include "x86/x86cpu.c"
+#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+# include "arm/armcpu.c"
+# include "pitch.c"
+# include "celt_lpc.c"
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+# include "arm/celt_neon_intr.c"
+# if defined(HAVE_ARM_NE10)
+# include "arm/celt_ne10_fft.c"
+# include "arm/celt_ne10_mdct.c"
+# endif
+# endif
+# include "arm/arm_celt_map.c"
+#endif
+
+#ifndef M_PI
+#define M_PI 3.141592653
+#endif
+
+int ret = 0;
+void check(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse)
+{
+ int bin,k;
+ double errpow=0,sigpow=0;
+ double snr;
+ for (bin=0;bin<nfft/2;++bin) {
+ double ansr = 0;
+ double difr;
+
+ for (k=0;k<nfft;++k) {
+ double phase = 2*M_PI*(k+.5+.25*nfft)*(bin+.5)/nfft;
+ double re = cos(phase);
+
+ re /= nfft/4;
+
+ ansr += in[k] * re;
+ }
+ /*printf ("%f %f\n", ansr, out[bin]);*/
+ difr = ansr - out[bin];
+ errpow += difr*difr;
+ sigpow += ansr*ansr;
+ }
+ snr = 10*log10(sigpow/errpow);
+ printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
+ if (snr<60) {
+ printf( "** poor snr: %f **\n", snr);
+ ret = 1;
+ }
+}
+
+void check_inv(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse)
+{
+ int bin,k;
+ double errpow=0,sigpow=0;
+ double snr;
+ for (bin=0;bin<nfft;++bin) {
+ double ansr = 0;
+ double difr;
+
+ for (k=0;k<nfft/2;++k) {
+ double phase = 2*M_PI*(bin+.5+.25*nfft)*(k+.5)/nfft;
+ double re = cos(phase);
+
+ /*re *= 2;*/
+
+ ansr += in[k] * re;
+ }
+ /*printf ("%f %f\n", ansr, out[bin]);*/
+ difr = ansr - out[bin];
+ errpow += difr*difr;
+ sigpow += ansr*ansr;
+ }
+ snr = 10*log10(sigpow/errpow);
+ printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
+ if (snr<60) {
+ printf( "** poor snr: %f **\n", snr);
+ ret = 1;
+ }
+}
+
+
+void test1d(int nfft,int isinverse,int arch)
+{
+ mdct_lookup cfg;
+ size_t buflen = sizeof(kiss_fft_scalar)*nfft;
+
+ kiss_fft_scalar * in = (kiss_fft_scalar*)malloc(buflen);
+ kiss_fft_scalar * in_copy = (kiss_fft_scalar*)malloc(buflen);
+ kiss_fft_scalar * out= (kiss_fft_scalar*)malloc(buflen);
+ opus_val16 * window= (opus_val16*)malloc(sizeof(opus_val16)*nfft/2);
+ int k;
+
+ clt_mdct_init(&cfg, nfft, 0, arch);
+ for (k=0;k<nfft;++k) {
+ in[k] = (rand() % 32768) - 16384;
+ }
+
+ for (k=0;k<nfft/2;++k) {
+ window[k] = Q15ONE;
+ }
+ for (k=0;k<nfft;++k) {
+ in[k] *= 32768;
+ }
+
+ if (isinverse)
+ {
+ for (k=0;k<nfft;++k) {
+ in[k] /= nfft;
+ }
+ }
+
+ for (k=0;k<nfft;++k)
+ in_copy[k] = in[k];
+ /*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/
+
+ if (isinverse)
+ {
+ for (k=0;k<nfft;++k)
+ out[k] = 0;
+ clt_mdct_backward(&cfg,in,out, window, nfft/2, 0, 1, arch);
+ /* apply TDAC because clt_mdct_backward() no longer does that */
+ for (k=0;k<nfft/4;++k)
+ out[nfft-k-1] = out[nfft/2+k];
+ check_inv(in,out,nfft,isinverse);
+ } else {
+ clt_mdct_forward(&cfg,in,out,window, nfft/2, 0, 1, arch);
+ check(in_copy,out,nfft,isinverse);
+ }
+ /*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/
+
+
+ free(in);
+ free(in_copy);
+ free(out);
+ free(window);
+ clt_mdct_clear(&cfg, arch);
+}
+
+int main(int argc,char ** argv)
+{
+ ALLOC_STACK;
+ int arch = opus_select_arch();
+
+ if (argc>1) {
+ int k;
+ for (k=1;k<argc;++k) {
+ test1d(atoi(argv[k]),0,arch);
+ test1d(atoi(argv[k]),1,arch);
+ }
+ }else{
+ test1d(32,0,arch);
+ test1d(32,1,arch);
+ test1d(256,0,arch);
+ test1d(256,1,arch);
+ test1d(512,0,arch);
+ test1d(512,1,arch);
+ test1d(1024,0,arch);
+ test1d(1024,1,arch);
+ test1d(2048,0,arch);
+ test1d(2048,1,arch);
+#ifndef RADIX_TWO_ONLY
+ test1d(36,0,arch);
+ test1d(36,1,arch);
+ test1d(40,0,arch);
+ test1d(40,1,arch);
+ test1d(60,0,arch);
+ test1d(60,1,arch);
+ test1d(120,0,arch);
+ test1d(120,1,arch);
+ test1d(240,0,arch);
+ test1d(240,1,arch);
+ test1d(480,0,arch);
+ test1d(480,1,arch);
+ test1d(960,0,arch);
+ test1d(960,1,arch);
+ test1d(1920,0,arch);
+ test1d(1920,1,arch);
+#endif
+ }
+ return ret;
+}
diff --git a/thirdparty/opus/celt/tests/test_unit_rotation.c b/thirdparty/opus/celt/tests/test_unit_rotation.c
new file mode 100644
index 0000000000..1080c2085d
--- /dev/null
+++ b/thirdparty/opus/celt/tests/test_unit_rotation.c
@@ -0,0 +1,120 @@
+/* Copyright (c) 2008-2011 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef CUSTOM_MODES
+#define CUSTOM_MODES
+#endif
+
+#define CELT_C
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "vq.c"
+#include "cwrs.c"
+#include "entcode.c"
+#include "entenc.c"
+#include "entdec.c"
+#include "mathops.c"
+#include "bands.h"
+#include "pitch.c"
+#include "celt_lpc.c"
+#include "celt.c"
+#include <math.h>
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) || defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1)
+# if defined(OPUS_X86_MAY_HAVE_SSE)
+# include "x86/pitch_sse.c"
+# endif
+# if defined(OPUS_X86_MAY_HAVE_SSE2)
+# include "x86/pitch_sse2.c"
+# endif
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+# include "x86/pitch_sse4_1.c"
+# include "x86/celt_lpc_sse.c"
+# endif
+# include "x86/x86_celt_map.c"
+#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+# include "arm/armcpu.c"
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+# include "arm/celt_neon_intr.c"
+# if defined(HAVE_ARM_NE10)
+# include "kiss_fft.c"
+# include "mdct.c"
+# include "arm/celt_ne10_fft.c"
+# include "arm/celt_ne10_mdct.c"
+# endif
+# endif
+# include "arm/arm_celt_map.c"
+#endif
+
+#define MAX_SIZE 100
+
+int ret=0;
+void test_rotation(int N, int K)
+{
+ int i;
+ double err = 0, ener = 0, snr, snr0;
+ opus_val16 x0[MAX_SIZE];
+ opus_val16 x1[MAX_SIZE];
+ for (i=0;i<N;i++)
+ x1[i] = x0[i] = rand()%32767-16384;
+ exp_rotation(x1, N, 1, 1, K, SPREAD_NORMAL);
+ for (i=0;i<N;i++)
+ {
+ err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]);
+ ener += x0[i]*(double)x0[i];
+ }
+ snr0 = 20*log10(ener/err);
+ err = ener = 0;
+ exp_rotation(x1, N, -1, 1, K, SPREAD_NORMAL);
+ for (i=0;i<N;i++)
+ {
+ err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]);
+ ener += x0[i]*(double)x0[i];
+ }
+ snr = 20*log10(ener/err);
+ printf ("SNR for size %d (%d pulses) is %f (was %f without inverse)\n", N, K, snr, snr0);
+ if (snr < 60 || snr0 > 20)
+ {
+ fprintf(stderr, "FAIL!\n");
+ ret = 1;
+ }
+}
+
+int main(void)
+{
+ ALLOC_STACK;
+ test_rotation(15, 3);
+ test_rotation(23, 5);
+ test_rotation(50, 3);
+ test_rotation(80, 1);
+ return ret;
+}
diff --git a/thirdparty/opus/celt/arm/armopts.s b/thirdparty/opus/celt/tests/test_unit_types.c
index fb9196072a..67a0fb8ed3 100644
--- a/thirdparty/opus/celt/arm/armopts.s
+++ b/thirdparty/opus/celt/tests/test_unit_types.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2013 Mozilla Corporation */
+/* Copyright (c) 2008-2011 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -24,14 +25,26 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-; Set the following to 1 if we have EDSP instructions
-; (LDRD/STRD, etc., ARMv5E and later).
-OPUS_ARM_MAY_HAVE_EDSP *
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
-; Set the following to 1 if we have ARMv6 media instructions.
-OPUS_ARM_MAY_HAVE_MEDIA *
+#include "opus_types.h"
+#include <stdio.h>
-; Set the following to 1 if we have NEON (some ARMv7)
-OPUS_ARM_MAY_HAVE_NEON *
-
-END
+int main(void)
+{
+ opus_int16 i = 1;
+ i <<= 14;
+ if (i>>14 != 1)
+ {
+ fprintf(stderr, "opus_int16 isn't 16 bits\n");
+ return 1;
+ }
+ if (sizeof(opus_int16)*2 != sizeof(opus_int32))
+ {
+ fprintf(stderr, "16*2 != 32\n");
+ return 1;
+ }
+ return 0;
+}
diff --git a/thirdparty/opus/celt/vq.c b/thirdparty/opus/celt/vq.c
index 8011e22548..d29f38fd8e 100644
--- a/thirdparty/opus/celt/vq.c
+++ b/thirdparty/opus/celt/vq.c
@@ -39,10 +39,6 @@
#include "rate.h"
#include "pitch.h"
-#if defined(MIPSr1_ASM)
-#include "mips/vq_mipsr1.h"
-#endif
-
#ifndef OVERRIDE_vq_exp_rotation1
static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
{
@@ -71,7 +67,7 @@ static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_
}
#endif /* OVERRIDE_vq_exp_rotation1 */
-void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
+static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
{
static const int SPREAD_FACTOR[3]={15,10,5};
int i;
@@ -162,27 +158,42 @@ static unsigned extract_collapse_mask(int *iy, int N, int B)
return collapse_mask;
}
-opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
+unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
+#ifdef RESYNTH
+ , opus_val16 gain
+#endif
+ )
{
VARDECL(celt_norm, y);
- VARDECL(int, signx);
+ VARDECL(int, iy);
+ VARDECL(opus_val16, signx);
int i, j;
+ opus_val16 s;
int pulsesLeft;
opus_val32 sum;
opus_val32 xy;
opus_val16 yy;
+ unsigned collapse_mask;
SAVE_STACK;
- (void)arch;
+ celt_assert2(K>0, "alg_quant() needs at least one pulse");
+ celt_assert2(N>1, "alg_quant() needs at least two dimensions");
+
ALLOC(y, N, celt_norm);
- ALLOC(signx, N, int);
+ ALLOC(iy, N, int);
+ ALLOC(signx, N, opus_val16);
+
+ exp_rotation(X, N, 1, B, K, spread);
/* Get rid of the sign */
sum = 0;
j=0; do {
- signx[j] = X[j]<0;
- /* OPT: Make sure the compiler doesn't use a branch on ABS16(). */
- X[j] = ABS16(X[j]);
+ if (X[j]>0)
+ signx[j]=1;
+ else {
+ signx[j]=-1;
+ X[j]=-X[j];
+ }
iy[j] = 0;
y[j] = 0;
} while (++j<N);
@@ -214,12 +225,7 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
while (++j<N);
sum = QCONST16(1.f,14);
}
-#ifdef FIXED_POINT
- rcp = EXTRACT16(MULT16_32_Q16(K, celt_rcp(sum)));
-#else
- /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
- rcp = EXTRACT16(MULT16_32_Q16(K+0.8f, celt_rcp(sum)));
-#endif
+ rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum)));
j=0; do {
#ifdef FIXED_POINT
/* It's really important to round *towards zero* here */
@@ -234,12 +240,12 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
pulsesLeft -= iy[j];
} while (++j<N);
}
- celt_sig_assert(pulsesLeft>=0);
+ celt_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass");
/* This should never happen, but just in case it does (e.g. on silence)
we fill the first bin with pulses. */
#ifdef FIXED_POINT_DEBUG
- celt_sig_assert(pulsesLeft<=N+3);
+ celt_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass");
#endif
if (pulsesLeft > N+3)
{
@@ -250,12 +256,12 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
pulsesLeft=0;
}
+ s = 1;
for (i=0;i<pulsesLeft;i++)
{
- opus_val16 Rxy, Ryy;
int best_id;
- opus_val32 best_num;
- opus_val16 best_den;
+ opus_val32 best_num = -VERY_LARGE16;
+ opus_val16 best_den = 0;
#ifdef FIXED_POINT
int rshift;
#endif
@@ -266,22 +272,9 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
/* The squared magnitude term gets added anyway, so we might as well
add it outside the loop */
yy = ADD16(yy, 1);
-
- /* Calculations for position 0 are out of the loop, in part to reduce
- mispredicted branches (since the if condition is usually false)
- in the loop. */
- /* Temporary sums of the new pulse(s) */
- Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[0])),rshift));
- /* We're multiplying y[j] by two so we don't have to do it here */
- Ryy = ADD16(yy, y[0]);
-
- /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
- Rxy is positive because the sign is pre-computed) */
- Rxy = MULT16_16_Q15(Rxy,Rxy);
- best_den = Ryy;
- best_num = Rxy;
- j=1;
+ j=0;
do {
+ opus_val16 Rxy, Ryy;
/* Temporary sums of the new pulse(s) */
Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[j])),rshift));
/* We're multiplying y[j] by two so we don't have to do it here */
@@ -292,11 +285,8 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
Rxy = MULT16_16_Q15(Rxy,Rxy);
/* The idea is to check for num/den >= best_num/best_den, but that way
we can do it without any division */
- /* OPT: It's not clear whether a cmov is faster than a branch here
- since the condition is more often false than true and using
- a cmov introduces data dependencies across iterations. The optimal
- choice may be architecture-dependent. */
- if (opus_unlikely(MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num)))
+ /* OPT: Make sure to use conditional moves here */
+ if (MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num))
{
best_den = Ryy;
best_num = Rxy;
@@ -311,47 +301,23 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
/* Only now that we've made the final choice, update y/iy */
/* Multiplying y[j] by 2 so we don't have to do it everywhere else */
- y[best_id] += 2;
+ y[best_id] += 2*s;
iy[best_id]++;
}
/* Put the original sign back */
j=0;
do {
- /*iy[j] = signx[j] ? -iy[j] : iy[j];*/
- /* OPT: The is more likely to be compiled without a branch than the code above
- but has the same performance otherwise. */
- iy[j] = (iy[j]^-signx[j]) + signx[j];
+ X[j] = MULT16_16(signx[j],X[j]);
+ if (signx[j] < 0)
+ iy[j] = -iy[j];
} while (++j<N);
- RESTORE_STACK;
- return yy;
-}
-
-unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
- opus_val16 gain, int resynth, int arch)
-{
- VARDECL(int, iy);
- opus_val16 yy;
- unsigned collapse_mask;
- SAVE_STACK;
-
- celt_assert2(K>0, "alg_quant() needs at least one pulse");
- celt_assert2(N>1, "alg_quant() needs at least two dimensions");
-
- /* Covers vectorization by up to 4. */
- ALLOC(iy, N+3, int);
-
- exp_rotation(X, N, 1, B, K, spread);
-
- yy = op_pvq_search(X, iy, K, N, arch);
-
encode_pulses(iy, N, K, enc);
- if (resynth)
- {
- normalise_residual(iy, X, N, yy, gain);
- exp_rotation(X, N, -1, B, K, spread);
- }
+#ifdef RESYNTH
+ normalise_residual(iy, X, N, yy, gain);
+ exp_rotation(X, N, -1, B, K, spread);
+#endif
collapse_mask = extract_collapse_mask(iy, N, B);
RESTORE_STACK;
@@ -435,7 +401,7 @@ int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int
/* 0.63662 = 2/pi */
itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid));
#else
- itheta = (int)floor(.5f+16384*0.63662f*fast_atan2f(side,mid));
+ itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid));
#endif
return itheta;
diff --git a/thirdparty/opus/celt/vq.h b/thirdparty/opus/celt/vq.h
index 45ec55918e..5cfcbe50ea 100644
--- a/thirdparty/opus/celt/vq.h
+++ b/thirdparty/opus/celt/vq.h
@@ -37,18 +37,10 @@
#include "entdec.h"
#include "modes.h"
-#if (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT))
-#include "x86/vq_sse.h"
+#if defined(MIPSr1_ASM)
+#include "mips/vq_mipsr1.h"
#endif
-void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread);
-
-opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch);
-
-#if !defined(OVERRIDE_OP_PVQ_SEARCH)
-#define op_pvq_search(x, iy, K, N, arch) \
- (op_pvq_search_c(x, iy, K, N, arch))
-#endif
/** Algebraic pulse-vector quantiser. The signal x is replaced by the sum of
* the pitch and a combination of pulses such that its norm is still equal
@@ -59,8 +51,12 @@ opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch);
* @param enc Entropy encoder state
* @ret A mask indicating which blocks in the band received pulses
*/
-unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
- opus_val16 gain, int resynth, int arch);
+unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B,
+ ec_enc *enc
+#ifdef RESYNTH
+ , opus_val16 gain
+#endif
+ );
/** Algebraic pulse decoder
* @param X Decoded normalised spectrum (returned)
diff --git a/thirdparty/opus/celt/x86/celt_lpc_sse4_1.c b/thirdparty/opus/celt/x86/celt_lpc_sse.c
index 5478568849..67e5592acf 100644
--- a/thirdparty/opus/celt/x86/celt_lpc_sse4_1.c
+++ b/thirdparty/opus/celt/x86/celt_lpc_sse.c
@@ -40,23 +40,65 @@
#if defined(FIXED_POINT)
-void celt_fir_sse4_1(const opus_val16 *x,
+void celt_fir_sse4_1(const opus_val16 *_x,
const opus_val16 *num,
- opus_val16 *y,
+ opus_val16 *_y,
int N,
int ord,
+ opus_val16 *mem,
int arch)
{
int i,j;
VARDECL(opus_val16, rnum);
+ VARDECL(opus_val16, x);
__m128i vecNoA;
opus_int32 noA ;
SAVE_STACK;
ALLOC(rnum, ord, opus_val16);
+ ALLOC(x, N+ord, opus_val16);
for(i=0;i<ord;i++)
rnum[i] = num[ord-i-1];
+ for(i=0;i<ord;i++)
+ x[i] = mem[ord-i-1];
+
+ for (i=0;i<N-7;i+=8)
+ {
+ x[i+ord ]=_x[i ];
+ x[i+ord+1]=_x[i+1];
+ x[i+ord+2]=_x[i+2];
+ x[i+ord+3]=_x[i+3];
+ x[i+ord+4]=_x[i+4];
+ x[i+ord+5]=_x[i+5];
+ x[i+ord+6]=_x[i+6];
+ x[i+ord+7]=_x[i+7];
+ }
+
+ for (;i<N-3;i+=4)
+ {
+ x[i+ord ]=_x[i ];
+ x[i+ord+1]=_x[i+1];
+ x[i+ord+2]=_x[i+2];
+ x[i+ord+3]=_x[i+3];
+ }
+
+ for (;i<N;i++)
+ x[i+ord]=_x[i];
+
+ for(i=0;i<ord;i++)
+ mem[i] = _x[N-i-1];
+#ifdef SMALL_FOOTPRINT
+ for (i=0;i<N;i++)
+ {
+ opus_val32 sum = SHL32(EXTEND32(_x[i]), SIG_SHIFT);
+ for (j=0;j<ord;j++)
+ {
+ sum = MAC16_16(sum,rnum[j],x[i+j]);
+ }
+ _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT));
+ }
+#else
noA = EXTEND32(1) << SIG_SHIFT >> 1;
vecNoA = _mm_set_epi32(noA, noA, noA, noA);
@@ -65,24 +107,25 @@ void celt_fir_sse4_1(const opus_val16 *x,
opus_val32 sums[4] = {0};
__m128i vecSum, vecX;
- xcorr_kernel(rnum, x+i-ord, sums, ord, arch);
+ xcorr_kernel(rnum, x+i, sums, ord, arch);
vecSum = _mm_loadu_si128((__m128i *)sums);
vecSum = _mm_add_epi32(vecSum, vecNoA);
vecSum = _mm_srai_epi32(vecSum, SIG_SHIFT);
- vecX = OP_CVTEPI16_EPI32_M64(x + i);
+ vecX = OP_CVTEPI16_EPI32_M64(_x + i);
vecSum = _mm_add_epi32(vecSum, vecX);
vecSum = _mm_packs_epi32(vecSum, vecSum);
- _mm_storel_epi64((__m128i *)(y + i), vecSum);
+ _mm_storel_epi64((__m128i *)(_y + i), vecSum);
}
for (;i<N;i++)
{
opus_val32 sum = 0;
for (j=0;j<ord;j++)
- sum = MAC16_16(sum, rnum[j], x[i+j-ord]);
- y[i] = SATURATE16(ADD32(EXTEND32(x[i]), PSHR32(sum, SIG_SHIFT)));
+ sum = MAC16_16(sum, rnum[j], x[i + j]);
+ _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT)));
}
+#endif
RESTORE_STACK;
}
diff --git a/thirdparty/opus/celt/x86/celt_lpc_sse.h b/thirdparty/opus/celt/x86/celt_lpc_sse.h
index 7d1ecf7533..c5ec796ed5 100644
--- a/thirdparty/opus/celt/x86/celt_lpc_sse.h
+++ b/thirdparty/opus/celt/x86/celt_lpc_sse.h
@@ -41,11 +41,12 @@ void celt_fir_sse4_1(
opus_val16 *y,
int N,
int ord,
+ opus_val16 *mem,
int arch);
#if defined(OPUS_X86_PRESUME_SSE4_1)
-#define celt_fir(x, num, y, N, ord, arch) \
- ((void)arch, celt_fir_sse4_1(x, num, y, N, ord, arch))
+#define celt_fir(x, num, y, N, ord, mem, arch) \
+ ((void)arch, celt_fir_sse4_1(x, num, y, N, ord, mem, arch))
#else
@@ -55,10 +56,11 @@ extern void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])(
opus_val16 *y,
int N,
int ord,
+ opus_val16 *mem,
int arch);
-# define celt_fir(x, num, y, N, ord, arch) \
- ((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, arch))
+# define celt_fir(x, num, y, N, ord, mem, arch) \
+ ((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, mem, arch))
#endif
#endif
diff --git a/thirdparty/opus/celt/x86/vq_sse.h b/thirdparty/opus/celt/x86/vq_sse.h
deleted file mode 100644
index b4efe8f249..0000000000
--- a/thirdparty/opus/celt/x86/vq_sse.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright (c) 2016 Jean-Marc Valin */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef VQ_SSE_H
-#define VQ_SSE_H
-
-#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT)
-#define OVERRIDE_OP_PVQ_SEARCH
-
-opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch);
-
-#if defined(OPUS_X86_PRESUME_SSE2)
-#define op_pvq_search(x, iy, K, N, arch) \
- (op_pvq_search_sse2(x, iy, K, N, arch))
-
-#else
-
-extern opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])(
- celt_norm *_X, int *iy, int K, int N, int arch);
-
-# define op_pvq_search(X, iy, K, N, arch) \
- ((*OP_PVQ_SEARCH_IMPL[(arch) & OPUS_ARCHMASK])(X, iy, K, N, arch))
-
-#endif
-#endif
-
-#endif
diff --git a/thirdparty/opus/celt/x86/vq_sse2.c b/thirdparty/opus/celt/x86/vq_sse2.c
deleted file mode 100644
index 775042860d..0000000000
--- a/thirdparty/opus/celt/x86/vq_sse2.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/* Copyright (c) 2007-2008 CSIRO
- Copyright (c) 2007-2009 Xiph.Org Foundation
- Copyright (c) 2007-2016 Jean-Marc Valin */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <xmmintrin.h>
-#include <emmintrin.h>
-#include "celt_lpc.h"
-#include "stack_alloc.h"
-#include "mathops.h"
-#include "vq.h"
-#include "x86cpu.h"
-
-
-#ifndef FIXED_POINT
-
-opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch)
-{
- int i, j;
- int pulsesLeft;
- float xy, yy;
- VARDECL(celt_norm, y);
- VARDECL(celt_norm, X);
- VARDECL(float, signy);
- __m128 signmask;
- __m128 sums;
- __m128i fours;
- SAVE_STACK;
-
- (void)arch;
- /* All bits set to zero, except for the sign bit. */
- signmask = _mm_set_ps1(-0.f);
- fours = _mm_set_epi32(4, 4, 4, 4);
- ALLOC(y, N+3, celt_norm);
- ALLOC(X, N+3, celt_norm);
- ALLOC(signy, N+3, float);
-
- OPUS_COPY(X, _X, N);
- X[N] = X[N+1] = X[N+2] = 0;
- sums = _mm_setzero_ps();
- for (j=0;j<N;j+=4)
- {
- __m128 x4, s4;
- x4 = _mm_loadu_ps(&X[j]);
- s4 = _mm_cmplt_ps(x4, _mm_setzero_ps());
- /* Get rid of the sign */
- x4 = _mm_andnot_ps(signmask, x4);
- sums = _mm_add_ps(sums, x4);
- /* Clear y and iy in case we don't do the projection. */
- _mm_storeu_ps(&y[j], _mm_setzero_ps());
- _mm_storeu_si128((__m128i*)&iy[j], _mm_setzero_si128());
- _mm_storeu_ps(&X[j], x4);
- _mm_storeu_ps(&signy[j], s4);
- }
- sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(1, 0, 3, 2)));
- sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(2, 3, 0, 1)));
-
- xy = yy = 0;
-
- pulsesLeft = K;
-
- /* Do a pre-search by projecting on the pyramid */
- if (K > (N>>1))
- {
- __m128i pulses_sum;
- __m128 yy4, xy4;
- __m128 rcp4;
- opus_val32 sum = _mm_cvtss_f32(sums);
- /* If X is too small, just replace it with a pulse at 0 */
- /* Prevents infinities and NaNs from causing too many pulses
- to be allocated. 64 is an approximation of infinity here. */
- if (!(sum > EPSILON && sum < 64))
- {
- X[0] = QCONST16(1.f,14);
- j=1; do
- X[j]=0;
- while (++j<N);
- sums = _mm_set_ps1(1.f);
- }
- /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
- rcp4 = _mm_mul_ps(_mm_set_ps1((float)(K+.8)), _mm_rcp_ps(sums));
- xy4 = yy4 = _mm_setzero_ps();
- pulses_sum = _mm_setzero_si128();
- for (j=0;j<N;j+=4)
- {
- __m128 rx4, x4, y4;
- __m128i iy4;
- x4 = _mm_loadu_ps(&X[j]);
- rx4 = _mm_mul_ps(x4, rcp4);
- iy4 = _mm_cvttps_epi32(rx4);
- pulses_sum = _mm_add_epi32(pulses_sum, iy4);
- _mm_storeu_si128((__m128i*)&iy[j], iy4);
- y4 = _mm_cvtepi32_ps(iy4);
- xy4 = _mm_add_ps(xy4, _mm_mul_ps(x4, y4));
- yy4 = _mm_add_ps(yy4, _mm_mul_ps(y4, y4));
- /* double the y[] vector so we don't have to do it in the search loop. */
- _mm_storeu_ps(&y[j], _mm_add_ps(y4, y4));
- }
- pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(1, 0, 3, 2)));
- pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(2, 3, 0, 1)));
- pulsesLeft -= _mm_cvtsi128_si32(pulses_sum);
- xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(1, 0, 3, 2)));
- xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(2, 3, 0, 1)));
- xy = _mm_cvtss_f32(xy4);
- yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(1, 0, 3, 2)));
- yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(2, 3, 0, 1)));
- yy = _mm_cvtss_f32(yy4);
- }
- X[N] = X[N+1] = X[N+2] = -100;
- y[N] = y[N+1] = y[N+2] = 100;
- celt_sig_assert(pulsesLeft>=0);
-
- /* This should never happen, but just in case it does (e.g. on silence)
- we fill the first bin with pulses. */
- if (pulsesLeft > N+3)
- {
- opus_val16 tmp = (opus_val16)pulsesLeft;
- yy = MAC16_16(yy, tmp, tmp);
- yy = MAC16_16(yy, tmp, y[0]);
- iy[0] += pulsesLeft;
- pulsesLeft=0;
- }
-
- for (i=0;i<pulsesLeft;i++)
- {
- int best_id;
- __m128 xy4, yy4;
- __m128 max, max2;
- __m128i count;
- __m128i pos;
- /* The squared magnitude term gets added anyway, so we might as well
- add it outside the loop */
- yy = ADD16(yy, 1);
- xy4 = _mm_load1_ps(&xy);
- yy4 = _mm_load1_ps(&yy);
- max = _mm_setzero_ps();
- pos = _mm_setzero_si128();
- count = _mm_set_epi32(3, 2, 1, 0);
- for (j=0;j<N;j+=4)
- {
- __m128 x4, y4, r4;
- x4 = _mm_loadu_ps(&X[j]);
- y4 = _mm_loadu_ps(&y[j]);
- x4 = _mm_add_ps(x4, xy4);
- y4 = _mm_add_ps(y4, yy4);
- y4 = _mm_rsqrt_ps(y4);
- r4 = _mm_mul_ps(x4, y4);
- /* Update the index of the max. */
- pos = _mm_max_epi16(pos, _mm_and_si128(count, _mm_castps_si128(_mm_cmpgt_ps(r4, max))));
- /* Update the max. */
- max = _mm_max_ps(max, r4);
- /* Update the indices (+4) */
- count = _mm_add_epi32(count, fours);
- }
- /* Horizontal max */
- max2 = _mm_max_ps(max, _mm_shuffle_ps(max, max, _MM_SHUFFLE(1, 0, 3, 2)));
- max2 = _mm_max_ps(max2, _mm_shuffle_ps(max2, max2, _MM_SHUFFLE(2, 3, 0, 1)));
- /* Now that max2 contains the max at all positions, look at which value(s) of the
- partial max is equal to the global max. */
- pos = _mm_and_si128(pos, _mm_castps_si128(_mm_cmpeq_ps(max, max2)));
- pos = _mm_max_epi16(pos, _mm_unpackhi_epi64(pos, pos));
- pos = _mm_max_epi16(pos, _mm_shufflelo_epi16(pos, _MM_SHUFFLE(1, 0, 3, 2)));
- best_id = _mm_cvtsi128_si32(pos);
-
- /* Updating the sums of the new pulse(s) */
- xy = ADD32(xy, EXTEND32(X[best_id]));
- /* We're multiplying y[j] by two so we don't have to do it here */
- yy = ADD16(yy, y[best_id]);
-
- /* Only now that we've made the final choice, update y/iy */
- /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
- y[best_id] += 2;
- iy[best_id]++;
- }
-
- /* Put the original sign back */
- for (j=0;j<N;j+=4)
- {
- __m128i y4;
- __m128i s4;
- y4 = _mm_loadu_si128((__m128i*)&iy[j]);
- s4 = _mm_castps_si128(_mm_loadu_ps(&signy[j]));
- y4 = _mm_xor_si128(_mm_add_epi32(y4, s4), s4);
- _mm_storeu_si128((__m128i*)&iy[j], y4);
- }
- RESTORE_STACK;
- return yy;
-}
-
-#endif
diff --git a/thirdparty/opus/celt/x86/x86_celt_map.c b/thirdparty/opus/celt/x86/x86_celt_map.c
index d39d88edec..47ba41b9ee 100644
--- a/thirdparty/opus/celt/x86/x86_celt_map.c
+++ b/thirdparty/opus/celt/x86/x86_celt_map.c
@@ -33,7 +33,6 @@
#include "celt_lpc.h"
#include "pitch.h"
#include "pitch_sse.h"
-#include "vq.h"
#if defined(OPUS_HAVE_RTCD)
@@ -47,6 +46,7 @@ void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])(
opus_val16 *y,
int N,
int ord,
+ opus_val16 *mem,
int arch
) = {
celt_fir_c, /* non-sse */
@@ -151,17 +151,5 @@ void (*const COMB_FILTER_CONST_IMPL[OPUS_ARCHMASK + 1])(
#endif
-#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)
-opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])(
- celt_norm *_X, int *iy, int K, int N, int arch
-) = {
- op_pvq_search_c, /* non-sse */
- op_pvq_search_c,
- MAY_HAVE_SSE2(op_pvq_search),
- MAY_HAVE_SSE2(op_pvq_search),
- MAY_HAVE_SSE2(op_pvq_search)
-};
-#endif
-
#endif
#endif
diff --git a/thirdparty/opus/celt/x86/x86cpu.h b/thirdparty/opus/celt/x86/x86cpu.h
index 1e2bf17b9b..04fd48aac4 100644
--- a/thirdparty/opus/celt/x86/x86cpu.h
+++ b/thirdparty/opus/celt/x86/x86cpu.h
@@ -82,9 +82,7 @@ int opus_select_arch(void);
(_mm_cvtepi8_epi32(*(__m128i *)(x)))
#endif
-/* similar reasoning about the instruction sequence as in the 32-bit macro above,
- */
-# if defined(__clang__) || !defined(__OPTIMIZE__)
+# if !defined(__OPTIMIZE__)
# define OP_CVTEPI16_EPI32_M64(x) \
(_mm_cvtepi16_epi32(_mm_loadl_epi64((__m128i *)(x))))
# else
diff --git a/thirdparty/opus/config.h b/thirdparty/opus/config.h
index 3ed0874d4b..7b9c92c6a8 100644
--- a/thirdparty/opus/config.h
+++ b/thirdparty/opus/config.h
@@ -1,44 +1,5 @@
-/* config.h. Generated from config.h.in by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Get CPU Info by asm method */
-#define CPU_INFO_BY_ASM 1
-
-/* Get CPU Info by c method */
-/* #undef CPU_INFO_BY_C */
-
-/* Custom modes */
-/* #undef CUSTOM_MODES */
-
-/* Do not build the float API */
-/* #undef DISABLE_FLOAT_API */
-
-/* Disable bitstream fixes from RFC 8251 */
-/* #undef DISABLE_UPDATE_DRAFT */
-
-/* Assertions */
-/* #undef ENABLE_ASSERTIONS */
-
-/* Hardening */
-#define ENABLE_HARDENING 1
-
-/* Debug fixed-point implementation */
-/* #undef FIXED_DEBUG */
-
-/* Compile as fixed-point (for machines without a fast enough FPU) */
-/* #undef FIXED_POINT */
-
-/* Float approximations */
-/* #undef FLOAT_APPROX */
-
-/* Fuzzing */
-/* #undef FUZZING */
-
-/* Define to 1 if you have the <alloca.h> header file. */
-/* #undef HAVE_ALLOCA_H */
-
-/* NE10 library is installed on host. Make sure it is on target! */
-/* #undef HAVE_ARM_NE10 */
+/* Opus configuration header */
+/* Based on the output of libopus configure script */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
@@ -46,12 +7,16 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
+#if (!defined( _MSC_VER ) || ( _MSC_VER >= 1800 ))
+
/* Define to 1 if you have the `lrint' function. */
#define HAVE_LRINT 1
/* Define to 1 if you have the `lrintf' function. */
#define HAVE_LRINTF 1
+#endif
+
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
@@ -76,10 +41,8 @@
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
-/* Define to 1 if you have the `__malloc_hook' function. */
-#define HAVE___MALLOC_HOOK 1
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
#define LT_OBJDIR ".libs/"
#ifdef OPUS_ARM_OPT
@@ -129,80 +92,9 @@
#endif // OPUS_ARM64_OPT
-/* Define if binary requires Aarch64 Neon Intrinsics */
-/* #undef OPUS_ARM_PRESUME_AARCH64_NEON_INTR */
-
-/* Define if binary requires EDSP instruction support */
-/* #undef OPUS_ARM_PRESUME_EDSP */
-
-/* Define if binary requires ARMv6 media instruction support */
-/* #undef OPUS_ARM_PRESUME_MEDIA */
-
-/* Define if binary requires NEON instruction support */
-/* #undef OPUS_ARM_PRESUME_NEON */
-
-/* Define if binary requires NEON intrinsics support */
-/* #undef OPUS_ARM_PRESUME_NEON_INTR */
-
/* This is a build of OPUS */
#define OPUS_BUILD /**/
-/* Run bit-exactness checks between optimized and c implementations */
-/* #undef OPUS_CHECK_ASM */
-
-#ifndef OPUS_ARM_OPT
-/* Use run-time CPU capabilities detection */
-#define OPUS_HAVE_RTCD 1
-#endif
-
-/* Compiler supports X86 AVX Intrinsics */
-/* #define OPUS_X86_MAY_HAVE_AVX */
-
-/* Compiler supports X86 SSE Intrinsics */
-/* #define OPUS_X86_MAY_HAVE_SSE */
-
-/* Compiler supports X86 SSE2 Intrinsics */
-/* #define OPUS_X86_MAY_HAVE_SSE2 */
-
-/* Compiler supports X86 SSE4.1 Intrinsics */
-/* #define OPUS_X86_MAY_HAVE_SSE4_1 */
-
-/* Define if binary requires AVX intrinsics support */
-/* #undef OPUS_X86_PRESUME_AVX */
-
-/* Define if binary requires SSE intrinsics support */
-#define OPUS_X86_PRESUME_SSE 1
-
-/* Define if binary requires SSE2 intrinsics support */
-#define OPUS_X86_PRESUME_SSE2 1
-
-/* Define if binary requires SSE4.1 intrinsics support */
-#define OPUS_X86_PRESUME_SSE4_1 1
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "opus@xiph.org"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "opus"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "opus 1.3.1"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "opus"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.3.1"
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Make use of alloca */
-/* #undef USE_ALLOCA */
-
#ifndef WIN32
/* Use C99 variable-size arrays */
#define VAR_ARRAYS 1
@@ -211,13 +103,11 @@
#define USE_ALLOCA 1
#endif
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
#ifndef OPUS_FIXED_POINT
#define FLOAT_APPROX 1
#endif
+
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
@@ -227,7 +117,11 @@
/* Define to the equivalent of the C99 'restrict' keyword, or to
nothing if this is not supported. Do not define if restrict is
supported directly. */
+#if (!defined( _MSC_VER ) || ( _MSC_VER >= 1800 ))
#define restrict __restrict
+#else
+#undef restrict
+#endif
/* Work around a bug in Sun C++: it does not support _Restrict or
__restrict__, even though the corresponding Sun C compiler ends up with
"#define restrict _Restrict" or "#define restrict __restrict__" in the
diff --git a/thirdparty/opus/info.c b/thirdparty/opus/info.c
index 3a1a5bf75b..c36f9a9ee1 100644
--- a/thirdparty/opus/info.c
+++ b/thirdparty/opus/info.c
@@ -107,32 +107,26 @@ static int op_tags_ensure_capacity(OpusTags *_tags,size_t _ncomments){
char **user_comments;
int *comment_lengths;
int cur_ncomments;
+ char *binary_suffix_data;
+ int binary_suffix_len;
size_t size;
if(OP_UNLIKELY(_ncomments>=(size_t)INT_MAX))return OP_EFAULT;
size=sizeof(*_tags->comment_lengths)*(_ncomments+1);
if(size/sizeof(*_tags->comment_lengths)!=_ncomments+1)return OP_EFAULT;
cur_ncomments=_tags->comments;
- /*We only support growing.
- Trimming requires cleaning up the allocated strings in the old space, and
- is best handled separately if it's ever needed.*/
- OP_ASSERT(_ncomments>=(size_t)cur_ncomments);
+ comment_lengths=_tags->comment_lengths;
+ binary_suffix_len=comment_lengths==NULL?0:comment_lengths[cur_ncomments];
comment_lengths=(int *)_ogg_realloc(_tags->comment_lengths,size);
if(OP_UNLIKELY(comment_lengths==NULL))return OP_EFAULT;
- if(_tags->comment_lengths==NULL){
- OP_ASSERT(cur_ncomments==0);
- comment_lengths[cur_ncomments]=0;
- }
- comment_lengths[_ncomments]=comment_lengths[cur_ncomments];
+ comment_lengths[_ncomments]=binary_suffix_len;
_tags->comment_lengths=comment_lengths;
size=sizeof(*_tags->user_comments)*(_ncomments+1);
if(size/sizeof(*_tags->user_comments)!=_ncomments+1)return OP_EFAULT;
+ user_comments=_tags->user_comments;
+ binary_suffix_data=user_comments==NULL?NULL:user_comments[cur_ncomments];
user_comments=(char **)_ogg_realloc(_tags->user_comments,size);
if(OP_UNLIKELY(user_comments==NULL))return OP_EFAULT;
- if(_tags->user_comments==NULL){
- OP_ASSERT(cur_ncomments==0);
- user_comments[cur_ncomments]=NULL;
- }
- user_comments[_ncomments]=user_comments[cur_ncomments];
+ user_comments[_ncomments]=binary_suffix_data;
_tags->user_comments=user_comments;
return 0;
}
@@ -281,30 +275,28 @@ int opus_tags_copy(OpusTags *_dst,const OpusTags *_src){
ret=opus_tags_copy_impl(&dst,_src);
if(OP_UNLIKELY(ret<0))opus_tags_clear(&dst);
else *_dst=*&dst;
- return ret;
+ return 0;
}
int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value){
- char *comment;
- size_t tag_len;
- size_t value_len;
- int ncomments;
- int ret;
+ char *comment;
+ int tag_len;
+ int value_len;
+ int ncomments;
+ int ret;
ncomments=_tags->comments;
ret=op_tags_ensure_capacity(_tags,ncomments+1);
if(OP_UNLIKELY(ret<0))return ret;
tag_len=strlen(_tag);
value_len=strlen(_value);
/*+2 for '=' and '\0'.*/
- if(tag_len+value_len<tag_len)return OP_EFAULT;
- if(tag_len+value_len>(size_t)INT_MAX-2)return OP_EFAULT;
comment=(char *)_ogg_malloc(sizeof(*comment)*(tag_len+value_len+2));
if(OP_UNLIKELY(comment==NULL))return OP_EFAULT;
memcpy(comment,_tag,sizeof(*comment)*tag_len);
comment[tag_len]='=';
memcpy(comment+tag_len+1,_value,sizeof(*comment)*(value_len+1));
_tags->user_comments[ncomments]=comment;
- _tags->comment_lengths[ncomments]=(int)(tag_len+value_len+1);
+ _tags->comment_lengths[ncomments]=tag_len+value_len+1;
_tags->comments=ncomments+1;
return 0;
}
@@ -345,10 +337,7 @@ int opus_tags_set_binary_suffix(OpusTags *_tags,
}
int opus_tagcompare(const char *_tag_name,const char *_comment){
- size_t tag_len;
- tag_len=strlen(_tag_name);
- if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return -1;
- return opus_tagncompare(_tag_name,(int)tag_len,_comment);
+ return opus_tagncompare(_tag_name,strlen(_tag_name),_comment);
}
int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){
@@ -359,18 +348,17 @@ int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){
}
const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count){
- char **user_comments;
- size_t tag_len;
- int found;
- int ncomments;
- int ci;
+ char **user_comments;
+ int tag_len;
+ int found;
+ int ncomments;
+ int ci;
tag_len=strlen(_tag);
- if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return NULL;
ncomments=_tags->comments;
user_comments=_tags->user_comments;
found=0;
for(ci=0;ci<ncomments;ci++){
- if(!opus_tagncompare(_tag,(int)tag_len,user_comments[ci])){
+ if(!opus_tagncompare(_tag,tag_len,user_comments[ci])){
/*We return a pointer to the data, not a copy.*/
if(_count==found++)return user_comments[ci]+tag_len+1;
}
@@ -380,18 +368,17 @@ const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count){
}
int opus_tags_query_count(const OpusTags *_tags,const char *_tag){
- char **user_comments;
- size_t tag_len;
- int found;
- int ncomments;
- int ci;
+ char **user_comments;
+ int tag_len;
+ int found;
+ int ncomments;
+ int ci;
tag_len=strlen(_tag);
- if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return 0;
ncomments=_tags->comments;
user_comments=_tags->user_comments;
found=0;
for(ci=0;ci<ncomments;ci++){
- if(!opus_tagncompare(_tag,(int)tag_len,user_comments[ci]))found++;
+ if(!opus_tagncompare(_tag,tag_len,user_comments[ci]))found++;
}
return found;
}
@@ -416,8 +403,7 @@ static int opus_tags_get_gain(const OpusTags *_tags,int *_gain_q8,
ncomments=_tags->comments;
/*Look for the first valid tag with the name _tag_name and use that.*/
for(ci=0;ci<ncomments;ci++){
- OP_ASSERT(_tag_len<=(size_t)INT_MAX);
- if(opus_tagncompare(_tag_name,(int)_tag_len,comments[ci])==0){
+ if(opus_tagncompare(_tag_name,_tag_len,comments[ci])==0){
char *p;
opus_int32 gain_q8;
int negative;
@@ -453,7 +439,8 @@ int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
}
static int op_is_jpeg(const unsigned char *_buf,size_t _buf_sz){
- return _buf_sz>=3&&memcmp(_buf,"\xFF\xD8\xFF",3)==0;
+ return _buf_sz>=11&&memcmp(_buf,"\xFF\xD8\xFF\xE0",4)==0
+ &&(_buf[4]<<8|_buf[5])>=16&&memcmp(_buf+6,"JFIF",5)==0;
}
/*Tries to extract the width, height, bits per pixel, and palette size of a
diff --git a/thirdparty/opus/internal.h b/thirdparty/opus/internal.h
index 9ac17e028f..ee48ea34c9 100644
--- a/thirdparty/opus/internal.h
+++ b/thirdparty/opus/internal.h
@@ -136,9 +136,6 @@ struct OggOpusLink{
that end-trimming calculations work properly.
This is only valid for seekable sources.*/
opus_int64 end_offset;
- /*The total duration of all prior links.
- This is always zero for non-seekable sources.*/
- ogg_int64_t pcm_file_offset;
/*The granule position of the last sample.
This is only valid for seekable sources.*/
ogg_int64_t pcm_end;
@@ -153,25 +150,23 @@ struct OggOpusLink{
};
struct OggOpusFile{
- /*The callbacks used to access the stream.*/
+ /*The callbacks used to access the data source.*/
OpusFileCallbacks callbacks;
- /*A FILE *, memory buffer, etc.*/
- void *stream;
- /*Whether or not we can seek with this stream.*/
+ /*A FILE *, memory bufer, etc.*/
+ void *source;
+ /*Whether or not we can seek with this data source.*/
int seekable;
/*The number of links in this chained Ogg Opus file.*/
int nlinks;
/*The cached information from each link in a chained Ogg Opus file.
- If stream isn't seekable (e.g., it's a pipe), only the current link
+ If source isn't seekable (e.g., it's a pipe), only the current link
appears.*/
OggOpusLink *links;
/*The number of serial numbers from a single link.*/
int nserialnos;
/*The capacity of the list of serial numbers from a single link.*/
int cserialnos;
- /*Storage for the list of serial numbers from a single link.
- This is a scratch buffer used when scanning the BOS pages at the start of
- each link.*/
+ /*Storage for the list of serial numbers from a single link.*/
ogg_uint32_t *serialnos;
/*This is the current offset of the data processed by the ogg_sync_state.
After a seek, this should be set to the target offset so that we can track
@@ -179,9 +174,9 @@ struct OggOpusFile{
After a call to op_get_next_page(), this will point to the first byte after
that page.*/
opus_int64 offset;
- /*The total size of this stream, or -1 if it's unseekable.*/
+ /*The total size of this data source, or -1 if it's unseekable.*/
opus_int64 end;
- /*Used to locate pages in the stream.*/
+ /*Used to locate pages in the data source.*/
ogg_sync_state oy;
/*One of OP_NOTOPEN, OP_PARTOPEN, OP_OPENED, OP_STREAMSET, OP_INITSET.*/
int ready_state;
@@ -232,7 +227,7 @@ struct OggOpusFile{
/*The number of valid samples in the decoded buffer.*/
int od_buffer_size;
/*The type of gain offset to apply.
- One of OP_HEADER_GAIN, OP_ALBUM_GAIN, OP_TRACK_GAIN, or OP_ABSOLUTE_GAIN.*/
+ One of OP_HEADER_GAIN, OP_TRACK_GAIN, or OP_ABSOLUTE_GAIN.*/
int gain_type;
/*The offset to apply to the gain.*/
opus_int32 gain_offset_q8;
diff --git a/thirdparty/opus/mapping_matrix.c b/thirdparty/opus/mapping_matrix.c
deleted file mode 100644
index 31298af057..0000000000
--- a/thirdparty/opus/mapping_matrix.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/* Copyright (c) 2017 Google Inc.
- Written by Andrew Allen */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arch.h"
-#include "float_cast.h"
-#include "opus_private.h"
-#include "opus_defines.h"
-#include "mapping_matrix.h"
-
-#define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row)
-
-opus_int32 mapping_matrix_get_size(int rows, int cols)
-{
- opus_int32 size;
-
- /* Mapping Matrix must only support up to 255 channels in or out.
- * Additionally, the total cell count must be <= 65004 octets in order
- * for the matrix to be stored in an OGG header.
- */
- if (rows > 255 || cols > 255)
- return 0;
- size = rows * (opus_int32)cols * sizeof(opus_int16);
- if (size > 65004)
- return 0;
-
- return align(sizeof(MappingMatrix)) + align(size);
-}
-
-opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
-{
- /* void* cast avoids clang -Wcast-align warning */
- return (opus_int16*)(void*)((char*)matrix + align(sizeof(MappingMatrix)));
-}
-
-void mapping_matrix_init(MappingMatrix * const matrix,
- int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size)
-{
- int i;
- opus_int16 *ptr;
-
-#if !defined(ENABLE_ASSERTIONS)
- (void)data_size;
-#endif
- celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16)));
-
- matrix->rows = rows;
- matrix->cols = cols;
- matrix->gain = gain;
- ptr = mapping_matrix_get_data(matrix);
- for (i = 0; i < rows * cols; i++)
- {
- ptr[i] = data[i];
- }
-}
-
-#ifndef DISABLE_FLOAT_API
-void mapping_matrix_multiply_channel_in_float(
- const MappingMatrix *matrix,
- const float *input,
- int input_rows,
- opus_val16 *output,
- int output_row,
- int output_rows,
- int frame_size)
-{
- /* Matrix data is ordered col-wise. */
- opus_int16* matrix_data;
- int i, col;
-
- celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
-
- matrix_data = mapping_matrix_get_data(matrix);
-
- for (i = 0; i < frame_size; i++)
- {
- float tmp = 0;
- for (col = 0; col < input_rows; col++)
- {
- tmp +=
- matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
- input[MATRIX_INDEX(input_rows, col, i)];
- }
-#if defined(FIXED_POINT)
- output[output_rows * i] = FLOAT2INT16((1/32768.f)*tmp);
-#else
- output[output_rows * i] = (1/32768.f)*tmp;
-#endif
- }
-}
-
-void mapping_matrix_multiply_channel_out_float(
- const MappingMatrix *matrix,
- const opus_val16 *input,
- int input_row,
- int input_rows,
- float *output,
- int output_rows,
- int frame_size
-)
-{
- /* Matrix data is ordered col-wise. */
- opus_int16* matrix_data;
- int i, row;
- float input_sample;
-
- celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
-
- matrix_data = mapping_matrix_get_data(matrix);
-
- for (i = 0; i < frame_size; i++)
- {
-#if defined(FIXED_POINT)
- input_sample = (1/32768.f)*input[input_rows * i];
-#else
- input_sample = input[input_rows * i];
-#endif
- for (row = 0; row < output_rows; row++)
- {
- float tmp =
- (1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
- input_sample;
- output[MATRIX_INDEX(output_rows, row, i)] += tmp;
- }
- }
-}
-#endif /* DISABLE_FLOAT_API */
-
-void mapping_matrix_multiply_channel_in_short(
- const MappingMatrix *matrix,
- const opus_int16 *input,
- int input_rows,
- opus_val16 *output,
- int output_row,
- int output_rows,
- int frame_size)
-{
- /* Matrix data is ordered col-wise. */
- opus_int16* matrix_data;
- int i, col;
-
- celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
-
- matrix_data = mapping_matrix_get_data(matrix);
-
- for (i = 0; i < frame_size; i++)
- {
- opus_val32 tmp = 0;
- for (col = 0; col < input_rows; col++)
- {
-#if defined(FIXED_POINT)
- tmp +=
- ((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
- (opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
-#else
- tmp +=
- matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
- input[MATRIX_INDEX(input_rows, col, i)];
-#endif
- }
-#if defined(FIXED_POINT)
- output[output_rows * i] = (opus_int16)((tmp + 64) >> 7);
-#else
- output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
-#endif
- }
-}
-
-void mapping_matrix_multiply_channel_out_short(
- const MappingMatrix *matrix,
- const opus_val16 *input,
- int input_row,
- int input_rows,
- opus_int16 *output,
- int output_rows,
- int frame_size)
-{
- /* Matrix data is ordered col-wise. */
- opus_int16* matrix_data;
- int i, row;
- opus_int32 input_sample;
-
- celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
-
- matrix_data = mapping_matrix_get_data(matrix);
-
- for (i = 0; i < frame_size; i++)
- {
-#if defined(FIXED_POINT)
- input_sample = (opus_int32)input[input_rows * i];
-#else
- input_sample = (opus_int32)FLOAT2INT16(input[input_rows * i]);
-#endif
- for (row = 0; row < output_rows; row++)
- {
- opus_int32 tmp =
- (opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
- input_sample;
- output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
- }
- }
-}
-
-const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
-const opus_int16 mapping_matrix_foa_mixing_data[36] = {
- 16384, 0, -16384, 23170, 0, 0, 16384, 23170,
- 16384, 0, 0, 0, 16384, 0, -16384, -23170,
- 0, 0, 16384, -23170, 16384, 0, 0, 0,
- 0, 0, 0, 0, 32767, 0, 0, 0,
- 0, 0, 0, 32767
-};
-
-const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 };
-const opus_int16 mapping_matrix_soa_mixing_data[121] = {
- 10923, 7723, 13377, -13377, 11585, 9459, 7723, -16384,
- -6689, 0, 0, 10923, 7723, 13377, 13377, -11585,
- 9459, 7723, 16384, -6689, 0, 0, 10923, -15447,
- 13377, 0, 0, -18919, 7723, 0, 13377, 0,
- 0, 10923, 7723, -13377, -13377, 11585, -9459, 7723,
- 16384, -6689, 0, 0, 10923, -7723, 0, 13377,
- -16384, 0, -15447, 0, 9459, 0, 0, 10923,
- -7723, 0, -13377, 16384, 0, -15447, 0, 9459,
- 0, 0, 10923, 15447, 0, 0, 0, 0,
- -15447, 0, -18919, 0, 0, 10923, 7723, -13377,
- 13377, -11585, -9459, 7723, -16384, -6689, 0, 0,
- 10923, -15447, -13377, 0, 0, 18919, 7723, 0,
- 13377, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 32767, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 32767
-};
-
-const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 };
-const opus_int16 mapping_matrix_toa_mixing_data[324] = {
- 8208, 0, -881, 14369, 0, 0, -8192, -4163,
- 13218, 0, 0, 0, 11095, -8836, -6218, 14833,
- 0, 0, 8208, -10161, 881, 10161, -13218, -2944,
- -8192, 2944, 0, -10488, -6218, 6248, -11095, -6248,
- 0, -10488, 0, 0, 8208, 10161, 881, -10161,
- -13218, 2944, -8192, -2944, 0, 10488, -6218, -6248,
- -11095, 6248, 0, 10488, 0, 0, 8176, 5566,
- -11552, 5566, 9681, -11205, 8192, -11205, 0, 4920,
- -15158, 9756, -3334, 9756, 0, -4920, 0, 0,
- 8176, 7871, 11552, 0, 0, 15846, 8192, 0,
- -9681, -6958, 0, 13797, 3334, 0, -15158, 0,
- 0, 0, 8176, 0, 11552, 7871, 0, 0,
- 8192, 15846, 9681, 0, 0, 0, 3334, 13797,
- 15158, 6958, 0, 0, 8176, 5566, -11552, -5566,
- -9681, -11205, 8192, 11205, 0, 4920, 15158, 9756,
- -3334, -9756, 0, 4920, 0, 0, 8208, 14369,
- -881, 0, 0, -4163, -8192, 0, -13218, -14833,
- 0, -8836, 11095, 0, 6218, 0, 0, 0,
- 8208, 10161, 881, 10161, 13218, 2944, -8192, 2944,
- 0, 10488, 6218, -6248, -11095, -6248, 0, -10488,
- 0, 0, 8208, -14369, -881, 0, 0, 4163,
- -8192, 0, -13218, 14833, 0, 8836, 11095, 0,
- 6218, 0, 0, 0, 8208, 0, -881, -14369,
- 0, 0, -8192, 4163, 13218, 0, 0, 0,
- 11095, 8836, -6218, -14833, 0, 0, 8176, -5566,
- -11552, 5566, -9681, 11205, 8192, -11205, 0, -4920,
- 15158, -9756, -3334, 9756, 0, -4920, 0, 0,
- 8176, 0, 11552, -7871, 0, 0, 8192, -15846,
- 9681, 0, 0, 0, 3334, -13797, 15158, -6958,
- 0, 0, 8176, -7871, 11552, 0, 0, -15846,
- 8192, 0, -9681, 6958, 0, -13797, 3334, 0,
- -15158, 0, 0, 0, 8176, -5566, -11552, -5566,
- 9681, 11205, 8192, 11205, 0, -4920, -15158, -9756,
- -3334, -9756, 0, 4920, 0, 0, 8208, -10161,
- 881, -10161, 13218, -2944, -8192, -2944, 0, -10488,
- 6218, 6248, -11095, 6248, 0, 10488, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 32767, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 32767
-};
-
-const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 };
-const opus_int16 mapping_matrix_foa_demixing_data[36] = {
- 16384, 16384, 16384, 16384, 0, 0, 0, 23170,
- 0, -23170, 0, 0, -16384, 16384, -16384, 16384,
- 0, 0, 23170, 0, -23170, 0, 0, 0,
- 0, 0, 0, 0, 32767, 0, 0, 0,
- 0, 0, 0, 32767
-};
-
-const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 };
-const opus_int16 mapping_matrix_soa_demixing_data[121] = {
- 2771, 2771, 2771, 2771, 2771, 2771, 2771, 2771,
- 2771, 0, 0, 10033, 10033, -20066, 10033, 14189,
- 14189, -28378, 10033, -20066, 0, 0, 3393, 3393,
- 3393, -3393, 0, 0, 0, -3393, -3393, 0,
- 0, -17378, 17378, 0, -17378, -24576, 24576, 0,
- 17378, 0, 0, 0, -14189, 14189, 0, -14189,
- -28378, 28378, 0, 14189, 0, 0, 0, 2399,
- 2399, -4799, -2399, 0, 0, 0, -2399, 4799,
- 0, 0, 1959, 1959, 1959, 1959, -3918, -3918,
- -3918, 1959, 1959, 0, 0, -4156, 4156, 0,
- 4156, 0, 0, 0, -4156, 0, 0, 0,
- 8192, 8192, -16384, 8192, 16384, 16384, -32768, 8192,
- -16384, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 8312, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 8312
-};
-
-const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 };
-const opus_int16 mapping_matrix_toa_demixing_data[324] = {
- 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
- 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
- 0, 0, 0, -9779, 9779, 6263, 8857, 0,
- 6263, 13829, 9779, -13829, 0, -6263, 0, -8857,
- -6263, -9779, 0, 0, -3413, 3413, 3413, -11359,
- 11359, 11359, -11359, -3413, 3413, -3413, -3413, -11359,
- 11359, 11359, -11359, 3413, 0, 0, 13829, 9779,
- -9779, 6263, 0, 8857, -6263, 0, 9779, 0,
- -13829, 6263, -8857, 0, -6263, -9779, 0, 0,
- 0, -15617, -15617, 6406, 0, 0, -6406, 0,
- 15617, 0, 0, -6406, 0, 0, 6406, 15617,
- 0, 0, 0, -5003, 5003, -10664, 15081, 0,
- -10664, -7075, 5003, 7075, 0, 10664, 0, -15081,
- 10664, -5003, 0, 0, -8176, -8176, -8176, 8208,
- 8208, 8208, 8208, -8176, -8176, -8176, -8176, 8208,
- 8208, 8208, 8208, -8176, 0, 0, -7075, 5003,
- -5003, -10664, 0, 15081, 10664, 0, 5003, 0,
- 7075, -10664, -15081, 0, 10664, -5003, 0, 0,
- 15617, 0, 0, 0, -6406, 6406, 0, -15617,
- 0, -15617, 15617, 0, 6406, -6406, 0, 0,
- 0, 0, 0, -11393, 11393, 2993, -4233, 0,
- 2993, -16112, 11393, 16112, 0, -2993, 0, 4233,
- -2993, -11393, 0, 0, 0, -9974, -9974, -13617,
- 0, 0, 13617, 0, 9974, 0, 0, 13617,
- 0, 0, -13617, 9974, 0, 0, 0, 5579,
- -5579, 10185, 14403, 0, 10185, -7890, -5579, 7890,
- 0, -10185, 0, -14403, -10185, 5579, 0, 0,
- 11826, -11826, -11826, -901, 901, 901, -901, 11826,
- -11826, 11826, 11826, -901, 901, 901, -901, -11826,
- 0, 0, -7890, -5579, 5579, 10185, 0, 14403,
- -10185, 0, -5579, 0, 7890, 10185, -14403, 0,
- -10185, 5579, 0, 0, -9974, 0, 0, 0,
- -13617, 13617, 0, 9974, 0, 9974, -9974, 0,
- 13617, -13617, 0, 0, 0, 0, 16112, -11393,
- 11393, -2993, 0, 4233, 2993, 0, -11393, 0,
- -16112, -2993, -4233, 0, 2993, 11393, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 32767, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 32767
-};
-
diff --git a/thirdparty/opus/mapping_matrix.h b/thirdparty/opus/mapping_matrix.h
deleted file mode 100644
index 98bc82df3e..0000000000
--- a/thirdparty/opus/mapping_matrix.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* Copyright (c) 2017 Google Inc.
- Written by Andrew Allen */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/**
- * @file mapping_matrix.h
- * @brief Opus reference implementation mapping matrix API
- */
-
-#ifndef MAPPING_MATRIX_H
-#define MAPPING_MATRIX_H
-
-#include "opus_types.h"
-#include "opus_projection.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct MappingMatrix
-{
- int rows; /* number of channels outputted from matrix. */
- int cols; /* number of channels inputted to matrix. */
- int gain; /* in dB. S7.8-format. */
- /* Matrix cell data goes here using col-wise ordering. */
-} MappingMatrix;
-
-opus_int32 mapping_matrix_get_size(int rows, int cols);
-
-opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix);
-
-void mapping_matrix_init(
- MappingMatrix * const matrix,
- int rows,
- int cols,
- int gain,
- const opus_int16 *data,
- opus_int32 data_size
-);
-
-#ifndef DISABLE_FLOAT_API
-void mapping_matrix_multiply_channel_in_float(
- const MappingMatrix *matrix,
- const float *input,
- int input_rows,
- opus_val16 *output,
- int output_row,
- int output_rows,
- int frame_size
-);
-
-void mapping_matrix_multiply_channel_out_float(
- const MappingMatrix *matrix,
- const opus_val16 *input,
- int input_row,
- int input_rows,
- float *output,
- int output_rows,
- int frame_size
-);
-#endif /* DISABLE_FLOAT_API */
-
-void mapping_matrix_multiply_channel_in_short(
- const MappingMatrix *matrix,
- const opus_int16 *input,
- int input_rows,
- opus_val16 *output,
- int output_row,
- int output_rows,
- int frame_size
-);
-
-void mapping_matrix_multiply_channel_out_short(
- const MappingMatrix *matrix,
- const opus_val16 *input,
- int input_row,
- int input_rows,
- opus_int16 *output,
- int output_rows,
- int frame_size
-);
-
-/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics.
- * foa: first-order ambisonics
- * soa: second-order ambisonics
- * toa: third-order ambisonics
- */
-extern const MappingMatrix mapping_matrix_foa_mixing;
-extern const opus_int16 mapping_matrix_foa_mixing_data[36];
-
-extern const MappingMatrix mapping_matrix_soa_mixing;
-extern const opus_int16 mapping_matrix_soa_mixing_data[121];
-
-extern const MappingMatrix mapping_matrix_toa_mixing;
-extern const opus_int16 mapping_matrix_toa_mixing_data[324];
-
-extern const MappingMatrix mapping_matrix_foa_demixing;
-extern const opus_int16 mapping_matrix_foa_demixing_data[36];
-
-extern const MappingMatrix mapping_matrix_soa_demixing;
-extern const opus_int16 mapping_matrix_soa_demixing_data[121];
-
-extern const MappingMatrix mapping_matrix_toa_demixing;
-extern const opus_int16 mapping_matrix_toa_demixing_data[324];
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MAPPING_MATRIX_H */
diff --git a/thirdparty/opus/mlp.c b/thirdparty/opus/mlp.c
index 964c6a98f6..ff9e50df47 100644
--- a/thirdparty/opus/mlp.c
+++ b/thirdparty/opus/mlp.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2008-2011 Octasic Inc.
- 2012-2017 Jean-Marc Valin */
+ Written by Jean-Marc Valin */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -29,13 +29,42 @@
#include "config.h"
#endif
-#include <math.h>
#include "opus_types.h"
#include "opus_defines.h"
+
+#include <math.h>
+#include "mlp.h"
#include "arch.h"
#include "tansig_table.h"
-#include "mlp.h"
+#define MAX_NEURONS 100
+#if 0
+static OPUS_INLINE opus_val16 tansig_approx(opus_val32 _x) /* Q19 */
+{
+ int i;
+ opus_val16 xx; /* Q11 */
+ /*double x, y;*/
+ opus_val16 dy, yy; /* Q14 */
+ /*x = 1.9073e-06*_x;*/
+ if (_x>=QCONST32(8,19))
+ return QCONST32(1.,14);
+ if (_x<=-QCONST32(8,19))
+ return -QCONST32(1.,14);
+ xx = EXTRACT16(SHR32(_x, 8));
+ /*i = lrint(25*x);*/
+ i = SHR32(ADD32(1024,MULT16_16(25, xx)),11);
+ /*x -= .04*i;*/
+ xx -= EXTRACT16(SHR32(MULT16_16(20972,i),8));
+ /*x = xx*(1./2048);*/
+ /*y = tansig_table[250+i];*/
+ yy = tansig_table[250+i];
+ /*y = yy*(1./16384);*/
+ dy = 16384-MULT16_16_Q14(yy,yy);
+ yy = yy + MULT16_16_Q14(MULT16_16_Q11(xx,dy),(16384 - MULT16_16_Q11(yy,xx)));
+ return yy;
+}
+#else
+/*extern const float tansig_table[501];*/
static OPUS_INLINE float tansig_approx(float x)
{
int i;
@@ -63,82 +92,54 @@ static OPUS_INLINE float tansig_approx(float x)
y = y + x*dy*(1 - y*x);
return sign*y;
}
+#endif
-static OPUS_INLINE float sigmoid_approx(float x)
-{
- return .5f + .5f*tansig_approx(.5f*x);
-}
-
-static void gemm_accum(float *out, const opus_int8 *weights, int rows, int cols, int col_stride, const float *x)
-{
- int i, j;
- for (i=0;i<rows;i++)
- {
- for (j=0;j<cols;j++)
- out[i] += weights[j*col_stride + i]*x[j];
- }
-}
-
-void compute_dense(const DenseLayer *layer, float *output, const float *input)
+#if 0
+void mlp_process(const MLP *m, const opus_val16 *in, opus_val16 *out)
{
- int i;
- int N, M;
- int stride;
- M = layer->nb_inputs;
- N = layer->nb_neurons;
- stride = N;
- for (i=0;i<N;i++)
- output[i] = layer->bias[i];
- gemm_accum(output, layer->input_weights, N, M, stride, input);
- for (i=0;i<N;i++)
- output[i] *= WEIGHTS_SCALE;
- if (layer->sigmoid) {
- for (i=0;i<N;i++)
- output[i] = sigmoid_approx(output[i]);
- } else {
- for (i=0;i<N;i++)
- output[i] = tansig_approx(output[i]);
- }
+ int j;
+ opus_val16 hidden[MAX_NEURONS];
+ const opus_val16 *W = m->weights;
+ /* Copy to tmp_in */
+ for (j=0;j<m->topo[1];j++)
+ {
+ int k;
+ opus_val32 sum = SHL32(EXTEND32(*W++),8);
+ for (k=0;k<m->topo[0];k++)
+ sum = MAC16_16(sum, in[k],*W++);
+ hidden[j] = tansig_approx(sum);
+ }
+ for (j=0;j<m->topo[2];j++)
+ {
+ int k;
+ opus_val32 sum = SHL32(EXTEND32(*W++),14);
+ for (k=0;k<m->topo[1];k++)
+ sum = MAC16_16(sum, hidden[k], *W++);
+ out[j] = tansig_approx(EXTRACT16(PSHR32(sum,17)));
+ }
}
-
-void compute_gru(const GRULayer *gru, float *state, const float *input)
+#else
+void mlp_process(const MLP *m, const float *in, float *out)
{
- int i;
- int N, M;
- int stride;
- float tmp[MAX_NEURONS];
- float z[MAX_NEURONS];
- float r[MAX_NEURONS];
- float h[MAX_NEURONS];
- M = gru->nb_inputs;
- N = gru->nb_neurons;
- stride = 3*N;
- /* Compute update gate. */
- for (i=0;i<N;i++)
- z[i] = gru->bias[i];
- gemm_accum(z, gru->input_weights, N, M, stride, input);
- gemm_accum(z, gru->recurrent_weights, N, N, stride, state);
- for (i=0;i<N;i++)
- z[i] = sigmoid_approx(WEIGHTS_SCALE*z[i]);
-
- /* Compute reset gate. */
- for (i=0;i<N;i++)
- r[i] = gru->bias[N + i];
- gemm_accum(r, &gru->input_weights[N], N, M, stride, input);
- gemm_accum(r, &gru->recurrent_weights[N], N, N, stride, state);
- for (i=0;i<N;i++)
- r[i] = sigmoid_approx(WEIGHTS_SCALE*r[i]);
-
- /* Compute output. */
- for (i=0;i<N;i++)
- h[i] = gru->bias[2*N + i];
- for (i=0;i<N;i++)
- tmp[i] = state[i] * r[i];
- gemm_accum(h, &gru->input_weights[2*N], N, M, stride, input);
- gemm_accum(h, &gru->recurrent_weights[2*N], N, N, stride, tmp);
- for (i=0;i<N;i++)
- h[i] = z[i]*state[i] + (1-z[i])*tansig_approx(WEIGHTS_SCALE*h[i]);
- for (i=0;i<N;i++)
- state[i] = h[i];
+ int j;
+ float hidden[MAX_NEURONS];
+ const float *W = m->weights;
+ /* Copy to tmp_in */
+ for (j=0;j<m->topo[1];j++)
+ {
+ int k;
+ float sum = *W++;
+ for (k=0;k<m->topo[0];k++)
+ sum = sum + in[k]**W++;
+ hidden[j] = tansig_approx(sum);
+ }
+ for (j=0;j<m->topo[2];j++)
+ {
+ int k;
+ float sum = *W++;
+ for (k=0;k<m->topo[1];k++)
+ sum = sum + hidden[k]**W++;
+ out[j] = tansig_approx(sum);
+ }
}
-
+#endif
diff --git a/thirdparty/opus/mlp.h b/thirdparty/opus/mlp.h
index d7670550fd..618e246e2c 100644
--- a/thirdparty/opus/mlp.h
+++ b/thirdparty/opus/mlp.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2017 Jean-Marc Valin */
+/* Copyright (c) 2008-2011 Octasic Inc.
+ Written by Jean-Marc Valin */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -27,34 +28,16 @@
#ifndef _MLP_H_
#define _MLP_H_
-#include "opus_types.h"
-
-#define WEIGHTS_SCALE (1.f/128)
-
-#define MAX_NEURONS 32
+#include "arch.h"
typedef struct {
- const opus_int8 *bias;
- const opus_int8 *input_weights;
- int nb_inputs;
- int nb_neurons;
- int sigmoid;
-} DenseLayer;
-
-typedef struct {
- const opus_int8 *bias;
- const opus_int8 *input_weights;
- const opus_int8 *recurrent_weights;
- int nb_inputs;
- int nb_neurons;
-} GRULayer;
-
-extern const DenseLayer layer0;
-extern const GRULayer layer1;
-extern const DenseLayer layer2;
+ int layers;
+ const int *topo;
+ const float *weights;
+} MLP;
-void compute_dense(const DenseLayer *layer, float *output, const float *input);
+extern const MLP net;
-void compute_gru(const GRULayer *gru, float *state, const float *input);
+void mlp_process(const MLP *m, const float *in, float *out);
#endif /* _MLP_H_ */
diff --git a/thirdparty/opus/mlp_data.c b/thirdparty/opus/mlp_data.c
index ae4178df76..c2fda4e2e5 100644
--- a/thirdparty/opus/mlp_data.c
+++ b/thirdparty/opus/mlp_data.c
@@ -1,4 +1,5 @@
-/*This file is automatically generated from a Keras model*/
+/* The contents of this file was automatically generated by mlp_train.c
+ It contains multi-layer perceptron (MLP) weights. */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -6,667 +7,103 @@
#include "mlp.h"
-static const opus_int8 layer0_weights[800] = {
- -30, -9, 2, -12, 5, -1, 8, 9,
- 9, 8, -13, 18, -17, -34, -5, 17,
- -11, 0, -4, 10, 2, 10, 15, -8,
- 2, -1, 0, 5, 13, -3, -16, 1,
- -5, 3, 7, -28, -13, 6, 36, -3,
- 19, -60, -17, -28, 7, -11, -30, -7,
- 2, -42, -21, -3, 6, -22, 33, -9,
- 7, -30, 21, -14, 24, -11, -20, -18,
- -5, -12, 12, -49, -50, -49, 16, 9,
- -37, -1, 9, 34, -13, -31, -31, 12,
- 16, 44, -42, 2, -9, 8, -18, -6,
- 9, 36, 19, 11, 13, 12, -21, 3,
- -28, -12, 3, 33, 25, -14, 11, 1,
- -94, -39, 18, -12, -11, -15, -7, 49,
- 52, 10, -43, 9, 57, 8, 21, -6,
- 14, -15, 44, -8, 7, -30, -13, -2,
- -9, 25, -2, -127, 18, -11, -52, 26,
- -27, 27, 10, -10, 7, 43, 6, -24,
- 41, 10, -18, -27, 10, 17, 9, 10,
- -17, -10, 20, -6, 22, 55, 35, -80,
- 36, 25, -24, -36, 15, 9, -19, 88,
- 19, 64, -51, -35, 17, 0, -7, 41,
- -16, 27, 4, 15, -1, 18, -16, 47,
- -39, -54, -8, 13, -25, -20, 102, -18,
- -5, 44, 11, -28, 71, 2, -51, -5,
- 5, 2, -83, -9, -29, 8, 21, -53,
- 58, -37, -7, 13, 38, 9, 34, -1,
- -41, 21, 4, -24, -36, -33, -21, 32,
- 75, -2, 1, -68, -1, 47, -29, 32,
- 20, 12, -65, -87, 5, 16, -12, 24,
- 40, 15, 7, 19, -26, -17, 17, 6,
- -2, -37, -30, -9, 32, -127, -39, 0,
- -31, -27, 4, -22, 23, -6, -77, 35,
- -61, 32, -37, -24, 13, -11, -1, -40,
- -3, 17, -7, 13, 11, 59, -19, 10,
- 6, -18, 0, 13, 3, -6, -23, 19,
- 11, -17, 13, -1, -80, 40, -53, 69,
- -29, -54, 0, -4, 33, -25, -2, 38,
- 35, 36, -15, 46, 2, -13, -16, -8,
- -8, 12, -24, -9, -55, -5, -9, 32,
- 11, 7, 12, -18, -10, -86, -38, 54,
- 37, -25, 18, -43, 7, -27, -27, -54,
- 13, 9, 22, 70, 6, 35, -7, 23,
- -15, -44, -6, 7, -66, -85, 32, 40,
- -19, -9, -7, 12, -15, 7, 2, 6,
- -35, 11, 28, 0, 26, 14, 1, 1,
- 4, 12, 18, 35, 22, -18, -3, 14,
- -1, 7, 14, -8, -14, -3, 4, -3,
- -19, -7, -1, -25, -27, 25, -26, -2,
- 33, -22, -27, -25, 4, -9, 7, 21,
- 26, -30, 10, -9, -20, 11, 27, 10,
- 5, -18, 14, -4, 2, -17, -5, -7,
- -9, -13, 15, 29, 1, -10, -16, -10,
- 35, 36, -7, -22, -44, 17, 30, 22,
- 21, -1, 22, -11, 32, -8, -7, 5,
- -10, 5, 30, -20, 29, -20, -34, 12,
- -4, -6, 6, -13, 10, -5, -68, -1,
- 24, 9, 19, -24, -64, 31, 19, 27,
- -26, 75, -45, 41, 39, -42, 8, 6,
- 23, -30, 16, -25, 30, 34, 8, -38,
- -3, 18, 16, -31, 22, -4, -9, 1,
- 20, 9, 38, -32, 0, -45, 0, -6,
- -13, 11, -25, -32, -22, 31, -24, -11,
- -11, -4, -4, 20, -34, 22, 20, 9,
- -25, 27, -5, 28, -29, 29, 6, 21,
- -6, -18, 54, 4, -46, 23, 21, -14,
- -31, 36, -41, -24, 4, 22, 10, 11,
- 7, 36, -32, -13, -52, -17, 24, 28,
- -37, -36, -1, 24, 9, -38, 35, 48,
- 18, 2, -1, 45, 10, 39, 24, -38,
- 13, 8, -16, 8, 25, 11, 7, -29,
- -11, 7, 20, -30, -38, -45, 14, -18,
- -28, -9, 65, 61, 22, -53, -38, -16,
- 36, 46, 20, -39, 32, -61, -6, -6,
- -36, -33, -18, -28, 56, 101, 45, 11,
- -28, -23, -29, -61, 20, -47, 2, 48,
- 27, -17, 1, 40, 1, 3, -51, 15,
- 35, 28, 22, 35, 53, -61, -29, 12,
- -6, -21, 10, 3, -20, 2, -25, 1,
- -6, 31, 11, -3, 1, -10, -52, 6,
- 126, -105, 122, 127, -128, 127, 127, -128,
- 127, 108, 12, 127, 48, -128, -36, -128,
- 127, 127, -128, -128, 127, 89, -128, 127,
- -128, -128, -128, 127, 127, -128, -128, -93,
- -82, 20, 125, 65, -82, 127, 38, -74,
- 81, 88, -88, 79, 51, -47, -111, -26,
- 14, 83, -88, -112, 24, 35, -101, 98,
- -99, -48, -45, 46, 83, -60, -79, 45,
- -20, -41, 9, 4, 52, 54, 93, -10,
- 4, 13, 3, 123, 6, 94, -111, -69,
- -14, -31, 10, 12, 53, -79, -11, -21,
- -2, -44, -72, 92, 65, -57, 56, -38,
- 127, -56, -128, 127, 127, -128, 86, 117,
- -75, -128, 127, -19, -99, -112, 127, -128,
- 127, -48, 114, 118, -128, -128, 117, -17,
- -6, 121, -128, 127, -128, 82, 54, -106,
- 127, 127, -33, 100, -39, -23, 18, -78,
- -34, -29, -1, -30, 127, -26, 127, -128,
- 126, -128, 27, -23, -79, -120, -127, 127,
- 72, 66, 29, 7, -66, -56, -117, -128
-};
-
-static const opus_int8 layer0_bias[32] = {
- 51, -16, 1, 13, -5, -6, -16, -7,
- 11, -6, 106, 26, 28, -14, 21, -29,
- 7, 18, -18, -17, 21, -17, -9, 20,
- -25, -3, -34, 48, 11, -13, -31, -20
-};
-
-static const opus_int8 layer1_weights[2304] = {
- 22, -1, -7, 7, 29, -27, -31, -17,
- -13, 33, 44, -8, 11, 33, 24, 78,
- 15, 19, 30, -2, -24, 5, 49, 5,
- 36, 29, -14, -11, -48, -33, 21, -42,
- -38, -12, 55, -37, 54, -8, 1, 36,
- 17, 0, 51, 31, 59, 7, -12, 53,
- 4, 32, -14, 48, 5, -10, -16, -8,
- 1, -16, -56, -24, -6, 18, -2, 23,
- 6, 46, -6, -10, 20, 35, -44, -15,
- -49, 36, 16, 5, -7, -79, -67, 12,
- 70, -3, -79, -54, -85, -24, 47, -22,
- 33, 21, 69, -1, 11, 22, 14, -16,
- -16, -22, -28, -11, 11, -41, 31, -26,
- -33, -19, -4, 27, 32, -50, 5, -10,
- -38, -22, -8, 35, -31, 1, -41, -15,
- -11, 44, 28, -17, -41, -23, 17, 2,
- -23, -26, -13, -13, -17, 6, 14, -31,
- -25, 9, -19, 39, -8, 4, 31, -1,
- -45, -11, -28, -92, -46, -15, 21, 118,
- -22, 45, -51, 11, -20, -20, -15, 13,
- -21, -97, -29, -32, -23, -42, 94, 1,
- 23, -8, 63, -3, -46, 19, -26, 32,
- -40, -74, -26, 26, -4, -13, 30, -20,
- -30, -25, -14, -31, -45, -43, 4, -60,
- -48, -12, -34, 2, 2, 3, 13, 15,
- 11, 16, 5, 46, -9, -55, -16, -57,
- 29, 14, 38, -50, -2, -44, -11, -8,
- 52, -27, -38, -7, 20, 47, 17, -59,
- 0, 47, 46, -63, 35, -17, 19, 33,
- 68, -19, 2, 15, -16, 28, -16, -103,
- 26, -35, 47, -39, -60, 30, 31, -23,
- -52, -13, 116, 47, -25, 30, 40, 30,
- -22, 2, 12, -27, -18, 31, -10, 27,
- -8, -66, 12, 14, 4, -26, -28, -13,
- 3, 13, -26, -51, 37, 5, 2, -21,
- 47, 3, 13, 25, -41, -27, -8, -4,
- 5, -76, -33, 28, 10, 9, -46, -74,
- 19, 28, 25, 31, 54, -55, 68, 38,
- -24, -32, 2, 4, 68, 11, -1, 99,
- 5, 16, -2, -74, 40, 26, -26, 33,
- 31, -1, -68, 14, -6, 25, 9, 29,
- 60, 61, 7, -7, 0, -24, 7, 77,
- 4, -1, 16, -7, 13, -15, -19, 28,
- -31, -24, -16, 37, 24, 13, 30, 10,
- -30, 11, 11, -10, 22, 60, 28, 45,
- -3, -40, -62, -5, -102, 9, -32, -27,
- -54, 21, 15, -5, 37, -43, -11, 37,
- -19, 47, -64, -128, -27, -114, 21, -66,
- 59, 46, -3, -12, -87, -9, 4, 19,
- -113, -36, 78, 57, -26, -38, -77, -10,
- 6, 6, -75, 25, -97, -11, 33, -46,
- 1, 13, -21, -33, -20, 16, -6, -3,
- -11, -4, -27, 38, 8, -41, -2, -33,
- 18, 19, -26, 1, -29, -22, -4, -14,
- -55, -11, -80, -3, 11, 34, 90, 51,
- 11, 17, 43, 36, 127, -32, 29, 103,
- 9, 27, 13, 64, 56, 70, -14, 3,
- -12, 10, 37, 3, 12, -22, -10, 46,
- 28, 10, 20, 26, -24, 18, 9, 7,
- 14, 34, -5, -7, 31, -14, -56, 11,
- -18, -8, -17, -7, -10, -40, 10, -33,
- -32, -43, 5, 9, 11, -4, 10, 50,
- -12, -5, 46, 9, 7, 1, 11, 15,
- 91, -17, 7, -50, 23, 6, -30, -99,
- 0, -17, 14, 8, -10, -25, -30, -69,
- -62, 31, 127, 114, -23, 101, -5, -54,
- -6, -22, 7, -56, 39, 18, -29, 0,
- 46, 8, -79, 4, -21, 18, -32, 62,
- -12, -8, -12, -58, 31, -32, 17, 6,
- -24, 25, 24, 9, -4, -19, 45, 6,
- 17, -14, 5, -27, 16, -4, -41, 25,
- -36, 5, 15, 12, 50, 27, 25, 23,
- -44, -69, -9, -19, -48, -8, 4, 12,
- -6, 13, -19, -30, -36, 26, 37, -1,
- -3, -30, -42, -14, -10, -20, 26, -54,
- -27, -44, 4, 73, -26, 90, 32, -69,
- -29, -16, 3, 103, 15, -17, 37, 24,
- -23, -31, 33, -37, -64, 25, 13, -81,
- -28, -32, 27, 5, -35, -23, 15, -22,
- 19, -7, 9, 30, 19, -23, 27, -13,
- 43, 29, -29, -6, 9, -40, -33, -33,
- -32, 9, 11, -48, -8, -23, -52, 46,
- 17, -22, -42, 35, -15, -41, 16, 34,
- 31, -42, -19, -11, 55, 7, -39, 89,
- -11, -33, 20, -14, 22, 32, 3, -17,
- -6, 14, 34, 1, 55, -21, -90, -8,
- 18, 27, 13, -29, 21, 15, -33, -51,
- -9, -11, 4, -16, -18, 23, -4, -4,
- 48, 1, 7, 29, -14, -12, -16, 17,
- 35, 8, 0, -7, -2, 9, 8, 17,
- -6, 53, -32, -21, -50, 5, 99, -60,
- -5, -53, 10, -31, 12, -5, 7, 80,
- 36, 18, -31, 9, 98, 36, -63, -35,
- 4, -13, -28, -24, 28, -13, 18, 16,
- -1, -18, -34, 10, 20, 7, 4, 29,
- 11, 25, -7, 36, 14, 45, 24, 1,
- -16, 30, 6, 35, -6, -11, -24, 13,
- -1, 27, 39, 20, 48, -11, -4, -13,
- 28, 11, -31, -18, 31, -29, 22, -2,
- -20, -16, 5, 30, -12, -28, -3, 93,
- -16, 23, 18, -29, 6, -54, -37, 28,
- -3, -3, -47, -3, -36, -55, -3, 41,
- -10, 47, -2, 23, 42, -7, -71, -27,
- 83, -64, 7, -24, 8, 26, -17, 15,
- 12, 31, -30, -38, -13, -33, -56, 4,
- -17, 20, 18, 1, -30, -5, -6, -31,
- -14, -37, 0, 22, 10, -30, 37, -17,
- 18, 6, 5, 23, -36, -32, 14, 18,
- -13, -61, -52, -69, 44, -30, 16, 18,
- -4, -25, 14, 81, 26, -8, -23, -59,
- 52, -104, 17, 119, -32, 26, 17, 1,
- 23, 45, 29, -64, -57, -14, 73, 21,
- -13, -13, 9, -68, -7, -52, 3, 24,
- -39, 44, -15, 27, 14, 19, -9, -28,
- -11, 5, 3, -34, -2, 2, 22, -6,
- -23, 4, 3, 13, -22, -13, -10, -18,
- 29, 6, 44, -13, -24, -8, 2, 30,
- 14, 43, 6, 17, -73, -6, -7, 20,
- -80, -7, -7, -28, 15, -69, -38, -5,
- -100, -35, 15, -79, 23, 29, -18, -27,
- 21, -66, -37, 8, -22, -39, 48, 4,
- -13, 1, -9, 11, -29, 22, 6, -49,
- 32, -14, 47, -18, -4, 44, -52, -74,
- 43, 30, 23, -14, 5, 0, -27, 4,
- -7, 10, -4, 10, 1, -16, 11, -18,
- -2, -5, 2, -11, 0, -20, -4, 38,
- 74, 59, 39, 64, -10, 26, -3, -40,
- -68, 3, -30, -51, 8, -19, -27, -46,
- 51, 52, 54, 36, 90, 92, 14, 13,
- -5, 0, 16, -62, 16, 11, -47, -37,
- -6, -5, 21, 54, -57, 32, 42, -6,
- 62, -9, 16, 21, 24, 9, -10, -4,
- 33, 50, 13, -15, 1, -35, -48, 18,
- -11, -17, -67, -13, 21, 38, -44, 36,
- -16, 29, 17, 5, -10, 18, 17, -32,
- 2, 8, 22, -56, -15, -32, 40, 43,
- 19, 46, -7, -100, -96, 19, 53, 24,
- 21, -26, -48, -101, -82, 61, 38, -85,
- -28, -34, -1, 63, -5, -5, 39, 39,
- -38, 32, -12, -28, 20, 40, -8, 2,
- 31, 12, -35, -13, 20, -25, 30, 8,
- 3, -13, -9, -20, 2, -13, 24, 37,
- -10, 33, 6, 20, -16, -24, -6, -6,
- -19, -5, 22, 21, 10, 11, -4, -39,
- -1, 6, 49, 41, -15, -57, 21, -62,
- 77, -69, -13, 0, -74, 1, -7, -38,
- -8, 6, 63, 28, 4, 26, -52, 82,
- 63, 13, 45, -33, 44, -52, -65, -21,
- -46, -49, 64, -17, 32, 24, 68, -39,
- -16, -5, -26, 28, 5, -61, -28, 2,
- 24, 11, -12, -33, 9, -37, -3, -28,
- 22, -37, -12, 19, 0, -18, -2, 14,
- 1, 4, 8, -9, -2, 43, -17, -2,
- -66, -31, 56, -40, -87, -36, -2, -4,
- -42, -45, -1, 31, -43, -15, 27, 63,
- -11, 32, -10, -33, 27, -19, 4, 15,
- -26, -34, 29, -4, -39, -65, 14, -20,
- -21, -17, -36, 13, 59, 47, -38, -33,
- 13, -37, -8, -37, -7, -6, -76, -31,
- -12, -46, 7, 24, -21, -30, -14, 9,
- 15, -12, -13, 47, -27, -25, -1, -39,
- 0, 20, -9, 6, 7, 4, 3, 7,
- 39, 50, 22, -7, 14, -20, 1, 70,
- -28, 29, -41, 10, -16, -5, -28, -2,
- -37, 32, -18, 17, 62, -11, -20, -50,
- 36, 21, -62, -12, -56, 52, 50, 17,
- 3, 48, 44, -41, -25, 3, 16, -3,
- 0, 33, -6, 15, 27, 34, -25, 22,
- 9, 17, -11, 36, 16, -2, 12, 21,
- -52, 45, -2, -10, 46, 21, -18, 67,
- -28, -13, 30, 37, 42, 16, -9, 11,
- 75, 7, -64, -40, -10, 29, 57, -23,
- 5, 53, -77, 3, -17, -5, 47, -55,
- -35, -36, -13, 52, -53, -71, 52, -111,
- -23, -26, -28, 29, -43, 55, -19, 43,
- -19, 54, -12, -33, -44, -39, -19, -10,
- -31, -10, 21, 38, -57, -20, 2, -25,
- 8, -6, 50, 12, 15, 25, -25, 15,
- -30, -6, 9, 25, 37, 19, -4, 31,
- -22, 2, 4, 2, 36, 7, 3, -34,
- -80, 36, -10, -2, -5, 31, -36, 49,
- -70, 20, -36, 21, 24, 25, -46, -51,
- 36, -58, -48, -40, -10, 55, 71, 47,
- 10, -1, 1, 2, -46, -68, 16, 13,
- 0, -74, -29, 73, -52, -18, -11, 7,
- -44, -82, -32, -70, -28, -1, -39, -68,
- -6, -41, 12, -22, -16, 40, -11, -25,
- 51, -9, 21, 4, 4, -34, 7, -78,
- 16, 6, -38, -30, -2, -44, 32, 0,
- 22, 64, 5, -72, -2, -14, -10, -16,
- -8, -25, 12, 102, -58, 37, -10, -23,
- 15, 49, 7, -7, 2, -20, -32, 45,
- -6, 48, 28, 30, 33, -1, 22, -6,
- 30, 65, -17, 29, 74, 37, -26, -10,
- 15, -24, 19, -66, 22, -10, -31, -1,
- -18, -9, 11, 37, -4, 45, 5, 41,
- 17, 1, 1, 24, -58, 41, 5, -51,
- 14, 8, 43, 16, -10, -1, 45, 32,
- -64, 3, -33, -25, -3, -27, -68, 12,
- 23, -11, -13, -37, -40, 4, -21, -12,
- 32, -23, -19, 76, 41, -23, -24, -44,
- -65, -1, -15, 1, 71, 63, 5, 20,
- -3, 21, -23, 31, -32, 18, -2, 27,
- 31, 46, -5, -39, -5, -35, 18, -18,
- -40, -10, 3, 12, 2, -2, -22, 40,
- 5, -6, 60, 36, 3, 29, -27, 10,
- 25, -54, 5, 26, 39, 35, -24, -37,
- 30, -91, 28, -4, -21, -27, -39, -6,
- 5, 12, -128, 38, -16, 29, -95, -29,
- 82, -2, 35, 2, 12, 8, -22, 10,
- 80, -47, 2, -25, -73, -79, 16, -30,
- -32, -66, 48, 21, -45, -11, -47, 14,
- -27, -17, -7, 15, -44, -14, -44, -26,
- -32, 26, -23, 17, -7, -28, 26, -6,
- 28, 6, -26, 2, 13, -14, -23, -14,
- 19, 46, 16, 2, -33, -21, 28, -17,
- -42, 44, -37, 1, -39, 28, 84, -46,
- 15, 10, 13, -44, 72, -26, 26, 32,
- -28, -12, -83, 2, 10, -30, -44, -10,
- -28, 53, 45, 65, 0, -25, 57, 36,
- -33, 6, 29, 44, -53, 11, 19, -2,
- -27, 35, 32, 49, 4, 23, 38, 36,
- 24, 10, 51, -39, 4, -7, 26, 37,
- -35, 11, -47, -18, 28, 16, -35, 42,
- 17, -21, -41, 28, 14, -12, 11, -45,
- 7, -43, -15, 18, -5, 38, -40, -50,
- -30, -21, 9, -98, 13, 12, 23, 75,
- -56, -7, -3, -4, -1, -34, 12, -49,
- 11, 26, -18, -28, -17, 33, 13, -14,
- 40, 24, -72, -37, 10, 17, -6, 22,
- 16, 16, -6, -12, -30, -14, 10, 40,
- -23, 12, 15, -3, -15, 13, -56, -4,
- -30, 1, -3, -17, 27, 50, -5, 64,
- -36, -19, 7, 29, 22, 25, 9, -16,
- -58, -69, -40, -61, -71, -14, 42, 93,
- 26, 11, -6, -58, -11, 70, -52, 19,
- 9, -30, -33, 11, -37, -47, -21, -22,
- -40, 10, 47, 4, -23, 17, 48, 41,
- -48, 14, 10, 15, 34, -23, -2, -47,
- 23, -32, -13, -10, -26, -26, -4, 16,
- 38, -14, 0, -12, -7, -7, 20, 44,
- -1, -32, -27, -16, 4, -6, -18, 14,
- 5, 4, -29, 28, 7, -7, 15, -11,
- -20, -45, -36, 16, 84, 34, -59, -30,
- 22, 126, 8, 68, 79, -17, 21, -68,
- 37, 5, 15, 63, 49, 127, -90, 85,
- 43, 7, 16, 9, 6, -45, -57, -43,
- 57, 11, -23, -11, -29, 60, -26, 0,
- 7, 42, -24, 10, 23, -25, 8, -7,
- -40, 19, -17, 35, 4, 27, -39, -91,
- 27, -36, 34, 2, 16, -24, 25, 7,
- -21, 5, 17, 10, -22, -30, 9, -17,
- -61, -26, 33, 21, 58, -51, -14, 69,
- -38, 20, 7, 80, -4, -65, -6, -27,
- 53, -12, 47, -1, -15, 1, 60, 102,
- -79, -4, 12, 9, 22, 37, -8, -4,
- 37, 2, -3, -15, -16, -11, -5, 19,
- -6, -43, 20, -25, -18, 10, -27, 0,
- -28, -27, -11, 10, -18, -2, -4, -16,
- 26, 14, -6, 7, -6, 1, 53, -2,
- -29, 23, 9, -30, -6, -4, -6, 56,
- 70, 0, -33, -20, -17, -9, -24, 46,
- -5, -105, 47, -46, -51, 20, 20, -53,
- -81, -1, -7, 75, -5, -21, -65, 12,
- -52, 22, -50, -12, 49, 54, 76, -81,
- 10, 45, -41, -59, 18, -19, 25, 14,
- -31, -53, -5, 12, 31, 84, -23, 2,
- 7, 2, 10, -32, 39, -2, -12, 1,
- -9, 0, -10, -11, 9, 15, -8, -2,
- 2, -1, 10, 14, -5, -40, 19, -7,
- -7, 26, -4, 2, 1, -27, 35, 32,
- 21, -31, 26, 43, -9, 4, -32, 40,
- -62, -52, 36, 22, 38, 22, 36, -96,
- 6, -10, -23, -49, 15, -33, -18, -3,
- 0, 41, 21, -19, 21, 23, -39, -23,
- -6, 6, 47, 56, 4, 74, 0, -98,
- 29, -47, -14, -36, 21, -22, 22, 16,
- 13, 12, 16, -5, 13, 17, -13, -15,
- 1, -34, -26, 26, 12, 32, 27, 13,
- -67, 27, 2, 8, 10, 18, 16, 20,
- -17, -17, 57, -64, 5, 14, 19, 31,
- -18, -44, -46, -16, 4, -25, 17, -126,
- -24, 39, 4, 8, 55, -25, -34, 39,
- -16, 3, 9, 71, 72, -31, -55, 6,
- 10, -25, 32, -85, -21, 18, -8, 15,
- 12, -27, -7, 1, -21, -2, -5, 48,
- -16, 18, 1, -22, -26, 16, 14, -31,
- 27, -6, -15, -21, 4, -14, 18, -36
-};
-
-static const opus_int8 layer1_recur_weights[1728] = {
- 20, 67, -99, 12, 41, -25, 49, -44,
- 35, 81, 110, 47, 34, -66, -14, 14,
- -60, 34, 29, -73, 10, 41, 35, 89,
- 7, -35, 22, 7, 27, -20, -6, 56,
- 26, 66, 6, 33, -55, 53, 1, -21,
- 14, 17, 68, 55, 59, 0, 18, -9,
- 5, -41, 6, -5, -114, -12, 29, 42,
- -23, 10, 81, -27, 20, -53, -30, -62,
- 40, 95, 25, -4, 3, 18, -8, -15,
- -29, -82, 2, -57, -3, -61, -29, -29,
- 49, 2, -55, 5, -69, -99, -49, -51,
- 6, -25, 12, 89, 44, -33, 5, 41,
- 1, 23, -37, -37, -28, -48, 3, 4,
- -41, -30, -57, -35, -39, -1, -13, -56,
- -5, 50, 49, 41, -4, -4, 33, -22,
- -1, 33, 34, 18, 40, -42, 12, 1,
- -6, -2, 18, 17, 39, 44, 11, 65,
- -60, -45, 10, 91, 21, 9, -62, -11,
- 8, 69, 37, 24, -30, 21, 26, -27,
- 1, -28, 24, 66, -8, 6, -71, 34,
- 24, 44, 58, -78, -19, 57, 17, -60,
- 1, 12, -3, -1, -40, 22, 11, -5,
- 25, 12, 1, 72, 79, 7, -50, 23,
- 18, 13, 21, -11, -20, 5, 77, -94,
- 24, 15, 57, -51, 3, 36, 53, -1,
- 4, 14, 30, -31, 22, 40, 32, -11,
- -34, -36, -59, 58, 25, 21, -54, -23,
- 40, 46, 18, 0, 12, 54, -96, -99,
- -59, 5, 119, -38, 50, 55, 12, -16,
- 67, 0, 34, 35, 39, 35, -1, 69,
- 24, 27, -30, -35, -4, -70, 2, -44,
- -7, -6, 19, -9, 60, 44, -21, -10,
- 37, 43, -16, -3, 30, -15, -65, 31,
- -55, 18, -98, 76, 64, 25, 24, -18,
- -7, -68, -10, 38, 27, -60, 36, 33,
- 16, 30, 34, -39, -37, 31, 12, 53,
- -54, 14, -26, -49, -128, -13, -5, -22,
- -11, -85, 55, -8, -51, -11, -33, -10,
- -31, -76, -41, 23, 44, -40, -54, -127,
- -101, 19, -23, -15, 15, 27, 58, -60,
- 8, 14, -33, 1, 48, -9, -11, -123,
- 3, 53, 23, 4, -28, 22, 2, -29,
- -67, 36, 12, 7, 55, -21, 88, 20,
- -1, -21, -17, 3, 41, 32, -10, -14,
- -5, -57, 67, 57, 21, 23, -2, -27,
- -73, -24, 120, 21, 18, -35, 42, -7,
- 3, -45, -25, 76, -34, 50, 11, -54,
- -91, 3, -113, -20, -5, 47, 15, -47,
- 17, 27, -3, -26, -7, 10, 7, 74,
- -40, 64, -7, -5, -24, -49, -24, -3,
- -10, 27, -17, -8, -3, 14, -27, 33,
- 13, 39, 28, -7, -38, 29, 16, 44,
- 19, 55, -3, 9, -13, -57, 43, 43,
- 31, 0, -93, -17, 19, -56, 4, -12,
- -25, 37, -85, -13, -118, 33, -17, 56,
- 71, -80, -4, 6, -11, -18, 47, -52,
- 25, 9, 48, -107, 1, 21, 20, -3,
- 10, -16, -4, 24, 17, 31, -61, -18,
- -50, 24, -10, 12, 71, 26, 11, -3,
- 4, 1, 0, -7, -40, 18, 38, -34,
- 38, 17, 8, -34, 2, 21, 123, -32,
- -26, 43, 14, -34, -1, -9, 37, -16,
- 6, -17, -62, 68, 22, 17, 11, -75,
- 33, -80, 62, -9, -75, 76, 36, -41,
- -8, -40, -11, -71, 40, -39, 62, -49,
- -81, 16, -9, -52, 52, 61, 17, -103,
- -27, -10, -8, -54, -57, 21, 23, -16,
- -52, 36, 18, 10, -5, 8, 15, -29,
- 5, -19, -37, 8, -53, 6, 19, -37,
- 38, -17, 48, 10, 0, 81, 46, 70,
- -29, 101, 11, 44, -44, -3, 24, 11,
- 3, 14, -9, 11, 14, -45, 13, 46,
- -3, -57, 68, 44, 63, 98, 25, -28,
- -23, 15, 32, -10, 53, -6, -2, -9,
- -6, 16, -107, -11, -11, -28, 59, 57,
- -22, 38, 42, 83, 27, 5, 29, -30,
- 12, -21, -13, 31, 38, -21, 58, -10,
- -10, -15, -2, -5, 11, 12, -73, -28,
- -38, 22, 2, -25, 73, -52, -12, -55,
- 32, -63, 21, 51, 33, 52, -26, 55,
- -26, -26, 57, -32, -4, -52, -61, 21,
- -33, -91, -51, 69, -90, -53, -38, -44,
- 12, -76, -20, 77, -45, -7, 86, 43,
- -109, -33, -105, -40, -121, -10, 0, -72,
- 45, -51, -75, -49, -38, -1, -62, 18,
- -1, 30, -44, -14, -10, -67, 40, -10,
- -34, 46, -64, -32, 29, -13, 33, 3,
- -32, -5, 28, -27, -25, 93, 24, 68,
- -40, 57, 23, -3, -21, -58, 17, -39,
- -17, -22, -89, 11, 18, -46, 27, 24,
- 46, 127, 61, 87, 31, 127, -36, 47,
- -23, 47, 127, -24, 110, 122, 30, 100,
- 0, 96, -12, 6, 50, 44, -13, 73,
- 4, 55, -11, -15, 49, 42, -6, 20,
- -35, 58, 18, 38, 42, 72, 19, -21,
- 11, 9, -37, 7, 29, 31, 16, -17,
- 13, -50, 19, 5, -23, 51, -16, -5,
- 4, -24, 76, 10, -53, -28, -7, -65,
- 74, 40, -16, -29, 32, -16, -49, -35,
- -3, 59, -96, -50, -43, -43, -61, -15,
- -8, -36, -34, -33, -14, 11, -3, -39,
- 4, -114, -123, -11, -49, -21, 14, -56,
- 1, 43, -63, 26, 40, 18, -10, -26,
- -14, -15, -35, -35, -11, 32, -44, -67,
- 2, 22, 7, 3, -9, -30, -51, -28,
- 28, 6, -22, 16, 34, -25, -52, -54,
- -8, -6, 5, 8, 20, -16, -17, -44,
- 27, 3, 31, -5, -48, -1, -3, 116,
- 11, 71, -31, -47, 109, 50, -22, -12,
- -57, 32, 66, 8, -25, -93, -54, -10,
- 19, -76, -34, 97, 48, -36, -18, -30,
- -39, -26, -12, 28, 14, 12, -12, -31,
- 38, 2, 10, 4, -40, 20, 16, -61,
- 2, 64, 39, 5, 15, 33, 40, -61,
- -49, 93, -10, 33, 28, -11, -27, -18,
- 39, -62, -6, -6, 62, 11, -8, 38,
- -67, 12, 27, 39, -27, 123, -18, -6,
- -65, 83, -64, 20, 19, -11, 33, 24,
- 17, 56, 78, 7, -15, 54, -101, -9,
- 115, -96, 50, 51, 35, 34, 27, 37,
- -40, -11, 8, -36, 42, -45, 2, -23,
- 0, 67, -8, -9, -13, 50, -14, -27,
- 4, 0, -8, -14, 30, -9, 29, 15,
- 9, -38, 37, -8, 50, -46, 54, 41,
- -11, -8, -11, -26, 39, 45, 14, -26,
- -17, -27, 69, 38, 39, 98, 66, 0,
- 42, 123, -101, -19, -83, 117, -32, 56,
- 10, 12, -88, 79, -53, 56, 63, 95,
- -62, 9, 36, -13, -79, -16, 37, -46,
- 35, -34, 14, 17, -54, 5, 21, -7,
- 7, 63, 56, 15, 27, -76, -25, 4,
- -26, -63, 28, -67, -52, 43, -47, -70,
- 40, -12, 40, -66, -37, 0, 35, 37,
- -53, 4, -17, -51, 11, 21, 14, -34,
- -4, 24, -42, 29, 22, 7, 28, 12,
- 37, 39, -39, -19, 65, -60, -50, -2,
- 1, 82, 39, 19, -23, -43, -22, -67,
- -35, -34, 32, 102, 81, 127, 36, 67,
- -45, 1, -67, -52, -4, 35, 20, 28,
- 71, 86, -35, -9, -83, -34, 12, 9,
- -23, 2, 14, 28, -23, 7, -25, 45,
- 7, 17, -37, 0, -19, 31, 26, 40,
- -27, -16, 17, 5, -21, 23, 24, 96,
- -55, 52, -19, -14, -6, 1, 50, -34,
- 86, -53, 38, 2, -52, -36, -13, 60,
- -85, -120, 32, 7, -12, 22, 70, -7,
- -94, 38, -76, -31, -20, 15, -28, 7,
- 6, 40, 53, 88, 3, 38, 18, -8,
- -22, -23, 51, 37, -9, 13, -32, 25,
- -21, 27, 31, 20, 18, -9, -13, 1,
- 21, -24, -13, 39, 15, -11, -29, -36,
- 18, 15, 8, 27, 21, -94, -1, -22,
- 49, 66, -1, 6, -3, -40, -18, 6,
- 28, 12, 33, -59, 62, 60, -48, 90,
- -1, 108, 9, 18, -2, 27, 77, -65,
- 82, -48, -38, -19, -11, 127, 50, 66,
- 18, -13, -22, 60, -38, 40, -14, -26,
- -13, 38, 67, 57, 30, 33, 26, 36,
- 38, -17, 27, -28, 20, 12, -64, 18,
- 5, -33, -27, 13, -26, 32, 35, -5,
- -48, -14, 92, 43, -47, -14, 40, 11,
- 51, 66, 22, -63, -16, -61, 4, -28,
- 27, 20, -33, -30, -21, -29, -53, 31,
- -40, 24, 43, -4, -19, 21, 67, 20,
- 100, -16, -93, 78, -6, -18, -52, -37,
- -9, 66, -31, -8, 26, 18, 4, 24,
- -22, 17, -2, -13, 27, 0, 8, -18,
- -25, 5, -21, -24, -7, 18, -93, 21,
- 7, 2, -75, 69, 50, -5, -15, -17,
- 60, -42, 55, 1, -4, 3, 10, 46,
- 16, -13, 45, -7, -10, -44, -108, 49,
- 2, -15, -64, -12, -72, 32, -38, -45,
- 10, -54, 13, -13, -27, -36, -64, 58,
- -62, -101, 88, -86, -71, -39, -9, -128,
- 32, 15, -4, 54, -16, -39, -26, -36,
- 46, 48, -64, -10, 19, 30, -13, 34,
- -8, 50, 60, -22, -6, -11, -30, 5,
- 50, 32, 56, 0, 25, 6, 68, 11,
- -29, 45, -9, -12, 4, 1, 18, -49,
- 0, -38, -19, 90, 29, 35, 51, 8,
- -48, 96, -1, -12, -9, -32, -63, -65,
- -7, 38, 89, 28, -85, -28, -23, -25,
- -128, 56, 79, -36, 99, -6, -37, 7,
- -13, -69, -46, -29, 25, 64, -21, 17,
- 1, 42, -66, 1, 80, 26, -32, 21,
- 15, 15, 6, 6, -10, 15, 127, 5,
- 38, 27, 87, -57, -25, 11, 72, -21,
- -5, 11, -13, -66, 78, 36, -3, 41,
- -21, 8, -33, 23, 73, 28, 57, -25,
- -5, 4, -22, -47, 15, 4, -57, -72,
- 33, 1, 18, 2, 53, -71, -99, -21,
- -3, -111, 108, 71, -14, 82, 25, 61,
- -48, 5, 9, -51, -20, -25, -3, 14,
- -33, 14, -3, -34, 22, 12, -19, -38,
- -16, 2, 21, 16, 26, -31, 75, 44,
- -31, 16, 26, 66, 17, -9, -22, -22,
- 22, -44, 22, 27, 2, 58, -14, 10,
- -73, -42, 55, -25, -61, 72, -1, 30,
- -58, -25, 63, 26, -48, -40, 26, -30,
- 60, 8, -17, -1, -18, -20, 43, -20,
- -4, -28, 127, -106, 29, 70, 64, -27,
- 39, -33, -5, -88, -40, -52, 26, 44,
- -17, 23, 2, -49, 22, -9, -8, 86,
- 49, -43, -60, 1, 10, 45, 36, -53,
- -4, 33, 38, 48, -72, 1, 19, 21,
- -65, 4, -5, -62, 27, -25, 17, -6,
- 6, -45, -39, -46, 4, 26, 127, -9,
- 18, -33, -18, -3, 33, 2, -5, 15,
- -26, -22, -117, -63, -17, -59, 61, -74,
- 7, -47, -58, -128, -67, 15, -16, -128,
- 12, 2, 20, 9, -48, -40, 43, 3,
- -40, -16, -38, -6, -22, -28, -16, -59,
- -22, 6, -5, 11, -12, -66, -40, 27,
- -62, -44, -19, 38, -3, 39, -8, 40,
- -24, 13, 21, 50, -60, -22, 53, -29,
- -6, 1, 22, -59, 0, 17, -39, 115
-};
+/* RMS error was 0.138320, seed was 1361535663 */
-static const opus_int8 layer1_bias[72] = {
- -42, 20, 16, 0, 105, 60, 1, -97,
- 24, 60, 18, 13, 62, 25, 127, 34,
- 79, 55, 118, 127, 95, 31, -4, 87,
- 21, 12, 2, -14, 18, 23, 8, 17,
- -1, -8, 5, 4, 24, 37, 21, 13,
- 36, 13, 17, 18, 37, 30, 33, 1,
- 8, -16, -11, -5, -31, -3, -5, 0,
- 6, 3, 58, -7, -1, -16, 5, -13,
- 16, 10, -2, -14, 11, -4, 3, -11
-};
+static const float weights[422] = {
-static const opus_int8 layer2_weights[48] = {
- -113, -88, 31, -128, -126, -61, 85, -35,
- 118, -128, -61, 127, -128, -17, -128, 127,
- 104, -9, -128, 33, 45, 127, 5, 83,
- 84, -128, -85, -128, -45, 48, -53, -128,
- 46, 127, -17, 125, 117, -41, -117, -91,
- -127, -68, -1, -89, -80, 32, 106, 7
-};
+/* hidden layer */
+-0.0941125f, -0.302976f, -0.603555f, -0.19393f, -0.185983f,
+-0.601617f, -0.0465317f, -0.114563f, -0.103599f, -0.618938f,
+-0.317859f, -0.169949f, -0.0702885f, 0.148065f, 0.409524f,
+0.548432f, 0.367649f, -0.494393f, 0.764306f, -1.83957f,
+0.170849f, 12.786f, -1.08848f, -1.27284f, -16.2606f,
+24.1773f, -5.57454f, -0.17276f, -0.163388f, -0.224421f,
+-0.0948944f, -0.0728695f, -0.26557f, -0.100283f, -0.0515459f,
+-0.146142f, -0.120674f, -0.180655f, 0.12857f, 0.442138f,
+-0.493735f, 0.167767f, 0.206699f, -0.197567f, 0.417999f,
+1.50364f, -0.773341f, -10.0401f, 0.401872f, 2.97966f,
+15.2165f, -1.88905f, -1.19254f, 0.0285397f, -0.00405139f,
+0.0707565f, 0.00825699f, -0.0927269f, -0.010393f, -0.00428882f,
+-0.00489743f, -0.0709731f, -0.00255992f, 0.0395619f, 0.226424f,
+0.0325231f, 0.162175f, -0.100118f, 0.485789f, 0.12697f,
+0.285937f, 0.0155637f, 0.10546f, 3.05558f, 1.15059f,
+-1.00904f, -1.83088f, 3.31766f, -3.42516f, -0.119135f,
+-0.0405654f, 0.00690068f, 0.0179877f, -0.0382487f, 0.00597941f,
+-0.0183611f, 0.00190395f, -0.144322f, -0.0435671f, 0.000990594f,
+0.221087f, 0.142405f, 0.484066f, 0.404395f, 0.511955f,
+-0.237255f, 0.241742f, 0.35045f, -0.699428f, 10.3993f,
+2.6507f, -2.43459f, -4.18838f, 1.05928f, 1.71067f,
+0.00667811f, -0.0721335f, -0.0397346f, 0.0362704f, -0.11496f,
+-0.0235776f, 0.0082161f, -0.0141741f, -0.0329699f, -0.0354253f,
+0.00277404f, -0.290654f, -1.14767f, -0.319157f, -0.686544f,
+0.36897f, 0.478899f, 0.182579f, -0.411069f, 0.881104f,
+-4.60683f, 1.4697f, 0.335845f, -1.81905f, -30.1699f,
+5.55225f, 0.0019508f, -0.123576f, -0.0727332f, -0.0641597f,
+-0.0534458f, -0.108166f, -0.0937368f, -0.0697883f, -0.0275475f,
+-0.192309f, -0.110074f, 0.285375f, -0.405597f, 0.0926724f,
+-0.287881f, -0.851193f, -0.099493f, -0.233764f, -1.2852f,
+1.13611f, 3.12168f, -0.0699f, -1.86216f, 2.65292f,
+-7.31036f, 2.44776f, -0.00111802f, -0.0632786f, -0.0376296f,
+-0.149851f, 0.142963f, 0.184368f, 0.123433f, 0.0756158f,
+0.117312f, 0.0933395f, 0.0692163f, 0.0842592f, 0.0704683f,
+0.0589963f, 0.0942205f, -0.448862f, 0.0262677f, 0.270352f,
+-0.262317f, 0.172586f, 2.00227f, -0.159216f, 0.038422f,
+10.2073f, 4.15536f, -2.3407f, -0.0550265f, 0.00964792f,
+-0.141336f, 0.0274501f, 0.0343921f, -0.0487428f, 0.0950172f,
+-0.00775017f, -0.0372492f, -0.00548121f, -0.0663695f, 0.0960506f,
+-0.200008f, -0.0412827f, 0.58728f, 0.0515787f, 0.337254f,
+0.855024f, 0.668371f, -0.114904f, -3.62962f, -0.467477f,
+-0.215472f, 2.61537f, 0.406117f, -1.36373f, 0.0425394f,
+0.12208f, 0.0934502f, 0.123055f, 0.0340935f, -0.142466f,
+0.035037f, -0.0490666f, 0.0733208f, 0.0576672f, 0.123984f,
+-0.0517194f, -0.253018f, 0.590565f, 0.145849f, 0.315185f,
+0.221534f, -0.149081f, 0.216161f, -0.349575f, 24.5664f,
+-0.994196f, 0.614289f, -18.7905f, -2.83277f, -0.716801f,
+-0.347201f, 0.479515f, -0.246027f, 0.0758683f, 0.137293f,
+-0.17781f, 0.118751f, -0.00108329f, -0.237334f, 0.355732f,
+-0.12991f, -0.0547627f, -0.318576f, -0.325524f, 0.180494f,
+-0.0625604f, 0.141219f, 0.344064f, 0.37658f, -0.591772f,
+5.8427f, -0.38075f, 0.221894f, -1.41934f, -1.87943e+06f,
+1.34114f, 0.0283355f, -0.0447856f, -0.0211466f, -0.0256927f,
+0.0139618f, 0.0207934f, -0.0107666f, 0.0110969f, 0.0586069f,
+-0.0253545f, -0.0328433f, 0.11872f, -0.216943f, 0.145748f,
+0.119808f, -0.0915211f, -0.120647f, -0.0787719f, -0.143644f,
+-0.595116f, -1.152f, -1.25335f, -1.17092f, 4.34023f,
+-975268.f, -1.37033f, -0.0401123f, 0.210602f, -0.136656f,
+0.135962f, -0.0523293f, 0.0444604f, 0.0143928f, 0.00412666f,
+-0.0193003f, 0.218452f, -0.110204f, -2.02563f, 0.918238f,
+-2.45362f, 1.19542f, -0.061362f, -1.92243f, 0.308111f,
+0.49764f, 0.912356f, 0.209272f, -2.34525f, 2.19326f,
+-6.47121f, 1.69771f, -0.725123f, 0.0118929f, 0.0377944f,
+0.0554003f, 0.0226452f, -0.0704421f, -0.0300309f, 0.0122978f,
+-0.0041782f, -0.0686612f, 0.0313115f, 0.039111f, 0.364111f,
+-0.0945548f, 0.0229876f, -0.17414f, 0.329795f, 0.114714f,
+0.30022f, 0.106997f, 0.132355f, 5.79932f, 0.908058f,
+-0.905324f, -3.3561f, 0.190647f, 0.184211f, -0.673648f,
+0.231807f, -0.0586222f, 0.230752f, -0.438277f, 0.245857f,
+-0.17215f, 0.0876383f, -0.720512f, 0.162515f, 0.0170571f,
+0.101781f, 0.388477f, 1.32931f, 1.08548f, -0.936301f,
+-2.36958f, -6.71988f, -3.44376f, 2.13818f, 14.2318f,
+4.91459f, -3.09052f, -9.69191f, -0.768234f, 1.79604f,
+0.0549653f, 0.163399f, 0.0797025f, 0.0343933f, -0.0555876f,
+-0.00505673f, 0.0187258f, 0.0326628f, 0.0231486f, 0.15573f,
+0.0476223f, -0.254824f, 1.60155f, -0.801221f, 2.55496f,
+0.737629f, -1.36249f, -0.695463f, -2.44301f, -1.73188f,
+3.95279f, 1.89068f, 0.486087f, -11.3343f, 3.9416e+06f,
-static const opus_int8 layer2_bias[2] = {
- 14, 117
-};
+/* output layer */
+-0.381439f, 0.12115f, -0.906927f, 2.93878f, 1.6388f,
+0.882811f, 0.874344f, 1.21726f, -0.874545f, 0.321706f,
+0.785055f, 0.946558f, -0.575066f, -3.46553f, 0.884905f,
+0.0924047f, -9.90712f, 0.391338f, 0.160103f, -2.04954f,
+4.1455f, 0.0684029f, -0.144761f, -0.285282f, 0.379244f,
+-1.1584f, -0.0277241f, -9.85f, -4.82386f, 3.71333f,
+3.87308f, 3.52558f};
-const DenseLayer layer0 = {
- layer0_bias,
- layer0_weights,
- 25, 32, 0
-};
+static const int topo[3] = {25, 15, 2};
-const GRULayer layer1 = {
- layer1_bias,
- layer1_weights,
- layer1_recur_weights,
- 32, 24
+const MLP net = {
+ 3,
+ topo,
+ weights
};
-
-const DenseLayer layer2 = {
- layer2_bias,
- layer2_weights,
- 24, 2, 1
-};
-
diff --git a/thirdparty/opus/opus.c b/thirdparty/opus/opus.c
index 538b5ea74e..f76f125cfa 100644
--- a/thirdparty/opus/opus.c
+++ b/thirdparty/opus/opus.c
@@ -107,7 +107,7 @@ OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
/* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math
does not cause output values larger than +/-1, but small enough not
to matter even for 24-bit output. */
- a += a*2.4e-7f;
+ a += a*2.4e-7;
if (x[i*C]>0)
a = -a;
/* Apply soft clipping */
@@ -252,7 +252,7 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
/* Number of frames encoded in bits 0 to 5 */
ch = *data++;
count = ch&0x3F;
- if (count <= 0 || framesize*(opus_int32)count > 5760)
+ if (count <= 0 || framesize*count > 5760)
return OPUS_INVALID_PACKET;
len--;
/* Padding flag is bit 6 */
diff --git a/thirdparty/opus/opus/opus.h b/thirdparty/opus/opus/opus.h
index d282f21d25..5be73ddf4e 100644
--- a/thirdparty/opus/opus/opus.h
+++ b/thirdparty/opus/opus/opus.h
@@ -531,7 +531,7 @@ OPUS_EXPORT int opus_packet_parse(
const unsigned char *frames[48],
opus_int16 size[48],
int *payload_offset
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5);
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Gets the bandwidth of an Opus packet.
* @param [in] data <tt>char*</tt>: Opus packet
diff --git a/thirdparty/opus/opus/opus_defines.h b/thirdparty/opus/opus/opus_defines.h
index d141418b21..315412dd1d 100644
--- a/thirdparty/opus/opus/opus_defines.h
+++ b/thirdparty/opus/opus/opus_defines.h
@@ -165,13 +165,8 @@ extern "C" {
#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
-/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
-#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
-#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
-#define OPUS_GET_IN_DTX_REQUEST 4049
-/** Defines for the presence of extended APIs. */
-#define OPUS_HAVE_OPUS_PROJECTION_H
+/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
@@ -213,9 +208,6 @@ extern "C" {
#define OPUS_FRAMESIZE_20_MS 5004 /**< Use 20 ms frames */
#define OPUS_FRAMESIZE_40_MS 5005 /**< Use 40 ms frames */
#define OPUS_FRAMESIZE_60_MS 5006 /**< Use 60 ms frames */
-#define OPUS_FRAMESIZE_80_MS 5007 /**< Use 80 ms frames */
-#define OPUS_FRAMESIZE_100_MS 5008 /**< Use 100 ms frames */
-#define OPUS_FRAMESIZE_120_MS 5009 /**< Use 120 ms frames */
/**@}*/
@@ -574,9 +566,7 @@ extern "C" {
* <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
- * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
- * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
- * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_VARIABLE</dt><dd>Optimize the frame size dynamically.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x)
@@ -591,9 +581,7 @@ extern "C" {
* <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
- * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
- * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
- * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_VARIABLE</dt><dd>Optimize the frame size dynamically.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x)
@@ -693,40 +681,6 @@ extern "C" {
*/
#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
-/** If set to 1, disables the use of phase inversion for intensity stereo,
- * improving the quality of mono downmixes, but slightly reducing normal
- * stereo quality. Disabling phase inversion in the decoder does not comply
- * with RFC 6716, although it does not cause any interoperability issue and
- * is expected to become part of the Opus standard once RFC 6716 is updated
- * by draft-ietf-codec-opus-update.
- * @see OPUS_GET_PHASE_INVERSION_DISABLED
- * @param[in] x <tt>opus_int32</tt>: Allowed values:
- * <dl>
- * <dt>0</dt><dd>Enable phase inversion (default).</dd>
- * <dt>1</dt><dd>Disable phase inversion.</dd>
- * </dl>
- * @hideinitializer */
-#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int(x)
-/** Gets the encoder's configured phase inversion status.
- * @see OPUS_SET_PHASE_INVERSION_DISABLED
- * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
- * <dl>
- * <dt>0</dt><dd>Stereo phase inversion enabled (default).</dd>
- * <dt>1</dt><dd>Stereo phase inversion disabled.</dd>
- * </dl>
- * @hideinitializer */
-#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
-/** Gets the DTX state of the encoder.
- * Returns whether the last encoded frame was either a comfort noise update
- * during DTX or not encoded because of DTX.
- * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
- * <dl>
- * <dt>0</dt><dd>The encoder is not in DTX.</dd>
- * <dt>1</dt><dd>The encoder is in DTX.</dd>
- * </dl>
- * @hideinitializer */
-#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, __opus_check_int_ptr(x)
-
/**@}*/
/** @defgroup opus_decoderctls Decoder related CTLs
diff --git a/thirdparty/opus/opus/opus_multistream.h b/thirdparty/opus/opus/opus_multistream.h
index babcee6905..3622e009fb 100644
--- a/thirdparty/opus/opus/opus_multistream.h
+++ b/thirdparty/opus/opus/opus_multistream.h
@@ -273,7 +273,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_enc
unsigned char *mapping,
int application,
int *error
-) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
+) OPUS_ARG_NONNULL(5);
/** Initialize a previously allocated multistream encoder state.
* The memory pointed to by \a st must be at least the size returned by
@@ -342,7 +342,7 @@ OPUS_EXPORT int opus_multistream_surround_encoder_init(
int *coupled_streams,
unsigned char *mapping,
int application
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7);
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
/** Encodes a multistream Opus frame.
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
diff --git a/thirdparty/opus/opus/opus_projection.h b/thirdparty/opus/opus/opus_projection.h
deleted file mode 100644
index 9dabf4e85c..0000000000
--- a/thirdparty/opus/opus/opus_projection.h
+++ /dev/null
@@ -1,568 +0,0 @@
-/* Copyright (c) 2017 Google Inc.
- Written by Andrew Allen */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/**
- * @file opus_projection.h
- * @brief Opus projection reference API
- */
-
-#ifndef OPUS_PROJECTION_H
-#define OPUS_PROJECTION_H
-
-#include "opus_multistream.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** @cond OPUS_INTERNAL_DOC */
-
-/** These are the actual encoder and decoder CTL ID numbers.
- * They should not be used directly by applications.c
- * In general, SETs should be even and GETs should be odd.*/
-/**@{*/
-#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST 6001
-#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST 6003
-#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST 6005
-/**@}*/
-
-
-/** @endcond */
-
-/** @defgroup opus_projection_ctls Projection specific encoder and decoder CTLs
- *
- * These are convenience macros that are specific to the
- * opus_projection_encoder_ctl() and opus_projection_decoder_ctl()
- * interface.
- * The CTLs from @ref opus_genericctls, @ref opus_encoderctls,
- * @ref opus_decoderctls, and @ref opus_multistream_ctls may be applied to a
- * projection encoder or decoder as well.
- */
-/**@{*/
-
-/** Gets the gain (in dB. S7.8-format) of the demixing matrix from the encoder.
- * @param[out] x <tt>opus_int32 *</tt>: Returns the gain (in dB. S7.8-format)
- * of the demixing matrix.
- * @hideinitializer
- */
-#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST, __opus_check_int_ptr(x)
-
-
-/** Gets the size in bytes of the demixing matrix from the encoder.
- * @param[out] x <tt>opus_int32 *</tt>: Returns the size in bytes of the
- * demixing matrix.
- * @hideinitializer
- */
-#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, __opus_check_int_ptr(x)
-
-
-/** Copies the demixing matrix to the supplied pointer location.
- * @param[out] x <tt>unsigned char *</tt>: Returns the demixing matrix to the
- * supplied pointer location.
- * @param y <tt>opus_int32</tt>: The size in bytes of the reserved memory at the
- * pointer location.
- * @hideinitializer
- */
-#define OPUS_PROJECTION_GET_DEMIXING_MATRIX(x,y) OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, x, __opus_check_int(y)
-
-
-/**@}*/
-
-/** Opus projection encoder state.
- * This contains the complete state of a projection Opus encoder.
- * It is position independent and can be freely copied.
- * @see opus_projection_ambisonics_encoder_create
- */
-typedef struct OpusProjectionEncoder OpusProjectionEncoder;
-
-
-/** Opus projection decoder state.
- * This contains the complete state of a projection Opus decoder.
- * It is position independent and can be freely copied.
- * @see opus_projection_decoder_create
- * @see opus_projection_decoder_init
- */
-typedef struct OpusProjectionDecoder OpusProjectionDecoder;
-
-
-/**\name Projection encoder functions */
-/**@{*/
-
-/** Gets the size of an OpusProjectionEncoder structure.
- * @param channels <tt>int</tt>: The total number of input channels to encode.
- * This must be no more than 255.
- * @param mapping_family <tt>int</tt>: The mapping family to use for selecting
- * the appropriate projection.
- * @returns The size in bytes on success, or a negative error code
- * (see @ref opus_errorcodes) on error.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_ambisonics_encoder_get_size(
- int channels,
- int mapping_family
-);
-
-
-/** Allocates and initializes a projection encoder state.
- * Call opus_projection_encoder_destroy() to release
- * this object when finished.
- * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param channels <tt>int</tt>: Number of channels in the input signal.
- * This must be at most 255.
- * It may be greater than the number of
- * coded channels (<code>streams +
- * coupled_streams</code>).
- * @param mapping_family <tt>int</tt>: The mapping family to use for selecting
- * the appropriate projection.
- * @param[out] streams <tt>int *</tt>: The total number of streams that will
- * be encoded from the input.
- * @param[out] coupled_streams <tt>int *</tt>: Number of coupled (2 channel)
- * streams that will be encoded from the input.
- * @param application <tt>int</tt>: The target encoder application.
- * This must be one of the following:
- * <dl>
- * <dt>#OPUS_APPLICATION_VOIP</dt>
- * <dd>Process signal for improved speech intelligibility.</dd>
- * <dt>#OPUS_APPLICATION_AUDIO</dt>
- * <dd>Favor faithfulness to the original input.</dd>
- * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
- * <dd>Configure the minimum possible coding delay by disabling certain modes
- * of operation.</dd>
- * </dl>
- * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
- * code (see @ref opus_errorcodes) on
- * failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
- opus_int32 Fs,
- int channels,
- int mapping_family,
- int *streams,
- int *coupled_streams,
- int application,
- int *error
-) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5);
-
-
-/** Initialize a previously allocated projection encoder state.
- * The memory pointed to by \a st must be at least the size returned by
- * opus_projection_ambisonics_encoder_get_size().
- * This is intended for applications which use their own allocator instead of
- * malloc.
- * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
- * @see opus_projection_ambisonics_encoder_create
- * @see opus_projection_ambisonics_encoder_get_size
- * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to initialize.
- * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param channels <tt>int</tt>: Number of channels in the input signal.
- * This must be at most 255.
- * It may be greater than the number of
- * coded channels (<code>streams +
- * coupled_streams</code>).
- * @param streams <tt>int</tt>: The total number of streams to encode from the
- * input.
- * This must be no more than the number of channels.
- * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
- * to encode.
- * This must be no larger than the total
- * number of streams.
- * Additionally, The total number of
- * encoded channels (<code>streams +
- * coupled_streams</code>) must be no
- * more than the number of input channels.
- * @param application <tt>int</tt>: The target encoder application.
- * This must be one of the following:
- * <dl>
- * <dt>#OPUS_APPLICATION_VOIP</dt>
- * <dd>Process signal for improved speech intelligibility.</dd>
- * <dt>#OPUS_APPLICATION_AUDIO</dt>
- * <dd>Favor faithfulness to the original input.</dd>
- * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
- * <dd>Configure the minimum possible coding delay by disabling certain modes
- * of operation.</dd>
- * </dl>
- * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
- * on failure.
- */
-OPUS_EXPORT int opus_projection_ambisonics_encoder_init(
- OpusProjectionEncoder *st,
- opus_int32 Fs,
- int channels,
- int mapping_family,
- int *streams,
- int *coupled_streams,
- int application
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
-
-
-/** Encodes a projection Opus frame.
- * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
- * @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
- * samples.
- * This must contain
- * <code>frame_size*channels</code>
- * samples.
- * @param frame_size <tt>int</tt>: Number of samples per channel in the input
- * signal.
- * This must be an Opus frame size for the
- * encoder's sampling rate.
- * For example, at 48 kHz the permitted values
- * are 120, 240, 480, 960, 1920, and 2880.
- * Passing in a duration of less than 10 ms
- * (480 samples at 48 kHz) will prevent the
- * encoder from using the LPC or hybrid modes.
- * @param[out] data <tt>unsigned char*</tt>: Output payload.
- * This must contain storage for at
- * least \a max_data_bytes.
- * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
- * memory for the output
- * payload. This may be
- * used to impose an upper limit on
- * the instant bitrate, but should
- * not be used as the only bitrate
- * control. Use #OPUS_SET_BITRATE to
- * control the bitrate.
- * @returns The length of the encoded packet (in bytes) on success or a
- * negative error code (see @ref opus_errorcodes) on failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode(
- OpusProjectionEncoder *st,
- const opus_int16 *pcm,
- int frame_size,
- unsigned char *data,
- opus_int32 max_data_bytes
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
-
-
-/** Encodes a projection Opus frame from floating point input.
- * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
- * @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
- * samples with a normal range of
- * +/-1.0.
- * Samples with a range beyond +/-1.0
- * are supported but will be clipped by
- * decoders using the integer API and
- * should only be used if it is known
- * that the far end supports extended
- * dynamic range.
- * This must contain
- * <code>frame_size*channels</code>
- * samples.
- * @param frame_size <tt>int</tt>: Number of samples per channel in the input
- * signal.
- * This must be an Opus frame size for the
- * encoder's sampling rate.
- * For example, at 48 kHz the permitted values
- * are 120, 240, 480, 960, 1920, and 2880.
- * Passing in a duration of less than 10 ms
- * (480 samples at 48 kHz) will prevent the
- * encoder from using the LPC or hybrid modes.
- * @param[out] data <tt>unsigned char*</tt>: Output payload.
- * This must contain storage for at
- * least \a max_data_bytes.
- * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
- * memory for the output
- * payload. This may be
- * used to impose an upper limit on
- * the instant bitrate, but should
- * not be used as the only bitrate
- * control. Use #OPUS_SET_BITRATE to
- * control the bitrate.
- * @returns The length of the encoded packet (in bytes) on success or a
- * negative error code (see @ref opus_errorcodes) on failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode_float(
- OpusProjectionEncoder *st,
- const float *pcm,
- int frame_size,
- unsigned char *data,
- opus_int32 max_data_bytes
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
-
-
-/** Frees an <code>OpusProjectionEncoder</code> allocated by
- * opus_projection_ambisonics_encoder_create().
- * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to be freed.
- */
-OPUS_EXPORT void opus_projection_encoder_destroy(OpusProjectionEncoder *st);
-
-
-/** Perform a CTL function on a projection Opus encoder.
- *
- * Generally the request and subsequent arguments are generated by a
- * convenience macro.
- * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
- * @param request This and all remaining parameters should be replaced by one
- * of the convenience macros in @ref opus_genericctls,
- * @ref opus_encoderctls, @ref opus_multistream_ctls, or
- * @ref opus_projection_ctls
- * @see opus_genericctls
- * @see opus_encoderctls
- * @see opus_multistream_ctls
- * @see opus_projection_ctls
- */
-OPUS_EXPORT int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
-
-
-/**@}*/
-
-/**\name Projection decoder functions */
-/**@{*/
-
-/** Gets the size of an <code>OpusProjectionDecoder</code> structure.
- * @param channels <tt>int</tt>: The total number of output channels.
- * This must be no more than 255.
- * @param streams <tt>int</tt>: The total number of streams coded in the
- * input.
- * This must be no more than 255.
- * @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
- * (2 channel) streams.
- * This must be no larger than the total
- * number of streams.
- * Additionally, The total number of
- * coded channels (<code>streams +
- * coupled_streams</code>) must be no
- * more than 255.
- * @returns The size in bytes on success, or a negative error code
- * (see @ref opus_errorcodes) on error.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_decoder_get_size(
- int channels,
- int streams,
- int coupled_streams
-);
-
-
-/** Allocates and initializes a projection decoder state.
- * Call opus_projection_decoder_destroy() to release
- * this object when finished.
- * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param channels <tt>int</tt>: Number of channels to output.
- * This must be at most 255.
- * It may be different from the number of coded
- * channels (<code>streams +
- * coupled_streams</code>).
- * @param streams <tt>int</tt>: The total number of streams coded in the
- * input.
- * This must be no more than 255.
- * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
- * (2 channel) streams.
- * This must be no larger than the total
- * number of streams.
- * Additionally, The total number of
- * coded channels (<code>streams +
- * coupled_streams</code>) must be no
- * more than 255.
- * @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
- * that mapping from coded channels to output channels,
- * as described in @ref opus_projection and
- * @ref opus_projection_ctls.
- * @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
- * demixing matrix, as
- * described in @ref
- * opus_projection_ctls.
- * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
- * code (see @ref opus_errorcodes) on
- * failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionDecoder *opus_projection_decoder_create(
- opus_int32 Fs,
- int channels,
- int streams,
- int coupled_streams,
- unsigned char *demixing_matrix,
- opus_int32 demixing_matrix_size,
- int *error
-) OPUS_ARG_NONNULL(5);
-
-
-/** Intialize a previously allocated projection decoder state object.
- * The memory pointed to by \a st must be at least the size returned by
- * opus_projection_decoder_get_size().
- * This is intended for applications which use their own allocator instead of
- * malloc.
- * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
- * @see opus_projection_decoder_create
- * @see opus_projection_deocder_get_size
- * @param st <tt>OpusProjectionDecoder*</tt>: Projection encoder state to initialize.
- * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
- * This must be one of 8000, 12000, 16000,
- * 24000, or 48000.
- * @param channels <tt>int</tt>: Number of channels to output.
- * This must be at most 255.
- * It may be different from the number of coded
- * channels (<code>streams +
- * coupled_streams</code>).
- * @param streams <tt>int</tt>: The total number of streams coded in the
- * input.
- * This must be no more than 255.
- * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
- * (2 channel) streams.
- * This must be no larger than the total
- * number of streams.
- * Additionally, The total number of
- * coded channels (<code>streams +
- * coupled_streams</code>) must be no
- * more than 255.
- * @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
- * that mapping from coded channels to output channels,
- * as described in @ref opus_projection and
- * @ref opus_projection_ctls.
- * @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
- * demixing matrix, as
- * described in @ref
- * opus_projection_ctls.
- * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
- * on failure.
- */
-OPUS_EXPORT int opus_projection_decoder_init(
- OpusProjectionDecoder *st,
- opus_int32 Fs,
- int channels,
- int streams,
- int coupled_streams,
- unsigned char *demixing_matrix,
- opus_int32 demixing_matrix_size
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
-
-
-/** Decode a projection Opus packet.
- * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
- * @param[in] data <tt>const unsigned char*</tt>: Input payload.
- * Use a <code>NULL</code>
- * pointer to indicate packet
- * loss.
- * @param len <tt>opus_int32</tt>: Number of bytes in payload.
- * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
- * samples.
- * This must contain room for
- * <code>frame_size*channels</code>
- * samples.
- * @param frame_size <tt>int</tt>: The number of samples per channel of
- * available space in \a pcm.
- * If this is less than the maximum packet duration
- * (120 ms; 5760 for 48kHz), this function will not be capable
- * of decoding some packets. In the case of PLC (data==NULL)
- * or FEC (decode_fec=1), then frame_size needs to be exactly
- * the duration of audio that is missing, otherwise the
- * decoder will not be in the optimal state to decode the
- * next incoming packet. For the PLC and FEC cases, frame_size
- * <b>must</b> be a multiple of 2.5 ms.
- * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
- * forward error correction data be decoded.
- * If no such data is available, the frame is
- * decoded as if it were lost.
- * @returns Number of samples decoded on success or a negative error code
- * (see @ref opus_errorcodes) on failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode(
- OpusProjectionDecoder *st,
- const unsigned char *data,
- opus_int32 len,
- opus_int16 *pcm,
- int frame_size,
- int decode_fec
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
-
-
-/** Decode a projection Opus packet with floating point output.
- * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
- * @param[in] data <tt>const unsigned char*</tt>: Input payload.
- * Use a <code>NULL</code>
- * pointer to indicate packet
- * loss.
- * @param len <tt>opus_int32</tt>: Number of bytes in payload.
- * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
- * samples.
- * This must contain room for
- * <code>frame_size*channels</code>
- * samples.
- * @param frame_size <tt>int</tt>: The number of samples per channel of
- * available space in \a pcm.
- * If this is less than the maximum packet duration
- * (120 ms; 5760 for 48kHz), this function will not be capable
- * of decoding some packets. In the case of PLC (data==NULL)
- * or FEC (decode_fec=1), then frame_size needs to be exactly
- * the duration of audio that is missing, otherwise the
- * decoder will not be in the optimal state to decode the
- * next incoming packet. For the PLC and FEC cases, frame_size
- * <b>must</b> be a multiple of 2.5 ms.
- * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
- * forward error correction data be decoded.
- * If no such data is available, the frame is
- * decoded as if it were lost.
- * @returns Number of samples decoded on success or a negative error code
- * (see @ref opus_errorcodes) on failure.
- */
-OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode_float(
- OpusProjectionDecoder *st,
- const unsigned char *data,
- opus_int32 len,
- float *pcm,
- int frame_size,
- int decode_fec
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
-
-
-/** Perform a CTL function on a projection Opus decoder.
- *
- * Generally the request and subsequent arguments are generated by a
- * convenience macro.
- * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
- * @param request This and all remaining parameters should be replaced by one
- * of the convenience macros in @ref opus_genericctls,
- * @ref opus_decoderctls, @ref opus_multistream_ctls, or
- * @ref opus_projection_ctls.
- * @see opus_genericctls
- * @see opus_decoderctls
- * @see opus_multistream_ctls
- * @see opus_projection_ctls
- */
-OPUS_EXPORT int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
-
-
-/** Frees an <code>OpusProjectionDecoder</code> allocated by
- * opus_projection_decoder_create().
- * @param st <tt>OpusProjectionDecoder</tt>: Projection decoder state to be freed.
- */
-OPUS_EXPORT void opus_projection_decoder_destroy(OpusProjectionDecoder *st);
-
-
-/**@}*/
-
-/**@}*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* OPUS_PROJECTION_H */
diff --git a/thirdparty/opus/opus/opus_types.h b/thirdparty/opus/opus/opus_types.h
index 7cf675580f..b28e03aea2 100644
--- a/thirdparty/opus/opus/opus_types.h
+++ b/thirdparty/opus/opus/opus_types.h
@@ -33,29 +33,14 @@
#ifndef OPUS_TYPES_H
#define OPUS_TYPES_H
-#define opus_int int /* used for counters etc; at least 16 bits */
-#define opus_int64 long long
-#define opus_int8 signed char
-
-#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
-#define opus_uint64 unsigned long long
-#define opus_uint8 unsigned char
-
/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
-#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
+#if (defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
#include <stdint.h>
-# undef opus_int64
-# undef opus_int8
-# undef opus_uint64
-# undef opus_uint8
- typedef int8_t opus_int8;
- typedef uint8_t opus_uint8;
+
typedef int16_t opus_int16;
typedef uint16_t opus_uint16;
typedef int32_t opus_int32;
typedef uint32_t opus_uint32;
- typedef int64_t opus_int64;
- typedef uint64_t opus_uint64;
#elif defined(_WIN32)
# if defined(__CYGWIN__)
@@ -163,4 +148,12 @@
#endif
+#define opus_int int /* used for counters etc; at least 16 bits */
+#define opus_int64 long long
+#define opus_int8 signed char
+
+#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
+#define opus_uint64 unsigned long long
+#define opus_uint8 unsigned char
+
#endif /* OPUS_TYPES_H */
diff --git a/thirdparty/opus/opus/opusfile.h b/thirdparty/opus/opus/opusfile.h
index e3a3dc8389..4bf2fba926 100644
--- a/thirdparty/opus/opus/opusfile.h
+++ b/thirdparty/opus/opus/opusfile.h
@@ -239,8 +239,7 @@ struct OpusHead{
-32768...32767.
The <tt>libopusfile</tt> API will automatically apply this gain to the
decoded output before returning it, scaling it by
- <code>pow(10,output_gain/(20.0*256))</code>.
- You can adjust this behavior with op_set_gain_offset().*/
+ <code>pow(10,output_gain/(20.0*256))</code>.*/
int output_gain;
/**The channel mapping family, in the range 0...255.
Channel mapping family 0 covers mono or stereo in a single stream.
@@ -1155,18 +1154,16 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url,
int *_error,...) OP_ARG_NONNULL(1);
/**Open a stream using the given set of callbacks to access it.
- \param _stream The stream to read from (e.g., a <code>FILE *</code>).
- This value will be passed verbatim as the first
- argument to all of the callbacks.
+ \param _source The stream to read from (e.g., a <code>FILE *</code>).
\param _cb The callbacks with which to access the stream.
<code><a href="#op_read_func">read()</a></code> must
be implemented.
<code><a href="#op_seek_func">seek()</a></code> and
<code><a href="#op_tell_func">tell()</a></code> may
be <code>NULL</code>, or may always return -1 to
- indicate a stream is unseekable, but if
+ indicate a source is unseekable, but if
<code><a href="#op_seek_func">seek()</a></code> is
- implemented and succeeds on a particular stream, then
+ implemented and succeeds on a particular source, then
<code><a href="#op_tell_func">tell()</a></code> must
also.
<code><a href="#op_close_func">close()</a></code> may
@@ -1229,11 +1226,11 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url,
basic validity checks.</dd>
</dl>
\return A freshly opened \c OggOpusFile, or <code>NULL</code> on error.
- <tt>libopusfile</tt> does <em>not</em> take ownership of the stream
+ <tt>libopusfile</tt> does <em>not</em> take ownership of the source
if the call fails.
- The calling application is responsible for closing the stream if
+ The calling application is responsible for closing the source if
this call returns an error.*/
-OP_WARN_UNUSED_RESULT OggOpusFile *op_open_callbacks(void *_stream,
+OP_WARN_UNUSED_RESULT OggOpusFile *op_open_callbacks(void *_source,
const OpusFileCallbacks *_cb,const unsigned char *_initial_data,
size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2);
@@ -1335,20 +1332,18 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url,
For new code, you are likely better off using op_test() instead, which
is less resource-intensive, requires less data to succeed, and imposes a
hard limit on the amount of data it examines (important for unseekable
- streams, where all such data must be buffered until you are sure of the
+ sources, where all such data must be buffered until you are sure of the
stream type).
- \param _stream The stream to read from (e.g., a <code>FILE *</code>).
- This value will be passed verbatim as the first
- argument to all of the callbacks.
+ \param _source The stream to read from (e.g., a <code>FILE *</code>).
\param _cb The callbacks with which to access the stream.
<code><a href="#op_read_func">read()</a></code> must
be implemented.
<code><a href="#op_seek_func">seek()</a></code> and
<code><a href="#op_tell_func">tell()</a></code> may
be <code>NULL</code>, or may always return -1 to
- indicate a stream is unseekable, but if
+ indicate a source is unseekable, but if
<code><a href="#op_seek_func">seek()</a></code> is
- implemented and succeeds on a particular stream, then
+ implemented and succeeds on a particular source, then
<code><a href="#op_tell_func">tell()</a></code> must
also.
<code><a href="#op_close_func">close()</a></code> may
@@ -1378,11 +1373,11 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url,
See op_open_callbacks() for a full list of failure
codes.
\return A partially opened \c OggOpusFile, or <code>NULL</code> on error.
- <tt>libopusfile</tt> does <em>not</em> take ownership of the stream
+ <tt>libopusfile</tt> does <em>not</em> take ownership of the source
if the call fails.
- The calling application is responsible for closing the stream if
+ The calling application is responsible for closing the source if
this call returns an error.*/
-OP_WARN_UNUSED_RESULT OggOpusFile *op_test_callbacks(void *_stream,
+OP_WARN_UNUSED_RESULT OggOpusFile *op_test_callbacks(void *_source,
const OpusFileCallbacks *_cb,const unsigned char *_initial_data,
size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2);
@@ -1439,7 +1434,7 @@ void op_free(OggOpusFile *_of);
Their documention will indicate so explicitly.*/
/*@{*/
-/**Returns whether or not the stream being read is seekable.
+/**Returns whether or not the data source being read is seekable.
This is true if
<ol>
<li>The <code><a href="#op_seek_func">seek()</a></code> and
@@ -1460,9 +1455,9 @@ int op_seekable(const OggOpusFile *_of) OP_ARG_NONNULL(1);
return 1.
The actual number of links is not known until the stream is fully opened.
\param _of The \c OggOpusFile from which to retrieve the link count.
- \return For fully-open seekable streams, this returns the total number of
+ \return For fully-open seekable sources, this returns the total number of
links in the whole stream, which will be at least 1.
- For partially-open or unseekable streams, this always returns 1.*/
+ For partially-open or unseekable sources, this always returns 1.*/
int op_link_count(const OggOpusFile *_of) OP_ARG_NONNULL(1);
/**Get the serial number of the given link in a (possibly-chained) Ogg Opus
@@ -1476,7 +1471,7 @@ int op_link_count(const OggOpusFile *_of) OP_ARG_NONNULL(1);
\return The serial number of the given link.
If \a _li is greater than the total number of links, this returns
the serial number of the last link.
- If the stream is not seekable, this always returns the serial number
+ If the source is not seekable, this always returns the serial number
of the current link.*/
opus_uint32 op_serialno(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
@@ -1493,7 +1488,7 @@ opus_uint32 op_serialno(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
\return The channel count of the given link.
If \a _li is greater than the total number of links, this returns
the channel count of the last link.
- If the stream is not seekable, this always returns the channel count
+ If the source is not seekable, this always returns the channel count
of the current link.*/
int op_channel_count(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
@@ -1512,9 +1507,9 @@ int op_channel_count(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
compressed size of link \a _li if it is non-negative, or a negative
value on error.
The compressed size of the entire stream may be smaller than that
- of the underlying stream if trailing garbage was detected in the
+ of the underlying source if trailing garbage was detected in the
file.
- \retval #OP_EINVAL The stream is not seekable (so we can't know the length),
+ \retval #OP_EINVAL The source is not seekable (so we can't know the length),
\a _li wasn't less than the total number of links in
the stream, or the stream was only partially open.*/
opus_int64 op_raw_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
@@ -1532,7 +1527,7 @@ opus_int64 op_raw_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
\return The PCM length of the entire stream if \a _li is negative, the PCM
length of link \a _li if it is non-negative, or a negative value on
error.
- \retval #OP_EINVAL The stream is not seekable (so we can't know the length),
+ \retval #OP_EINVAL The source is not seekable (so we can't know the length),
\a _li wasn't less than the total number of links in
the stream, or the stream was only partially open.*/
ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
@@ -1580,8 +1575,8 @@ const OpusTags *op_tags(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
\param _of The \c OggOpusFile from which to retrieve the current link index.
\return The index of the current link on success, or a negative value on
failure.
- For seekable streams, this is a number between 0 (inclusive) and the
- value returned by op_link_count() (exclusive).
+ For seekable streams, this is a number between 0 and the value
+ returned by op_link_count().
For unseekable streams, this value starts at 0 and increments by one
each time a new link is encountered (even though op_link_count()
always returns 1).
@@ -1645,10 +1640,10 @@ ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1);
/*@{*/
/**\name Functions for seeking in Opus streams
- These functions let you seek in Opus streams, if the underlying stream
+ These functions let you seek in Opus streams, if the underlying source
support it.
Seeking is implemented for all built-in stream I/O routines, though some
- individual streams may not be seekable (pipes, live HTTP streams, or HTTP
+ individual sources may not be seekable (pipes, live HTTP streams, or HTTP
streams from a server that does not support <code>Range</code> requests).
op_raw_seek() is the fastest: it is guaranteed to perform at most one
@@ -1675,8 +1670,6 @@ ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1);
packets out of the tail of the link to which it seeks.
\param _of The \c OggOpusFile in which to seek.
\param _byte_offset The byte position to seek to.
- This must be between 0 and #op_raw_total(\a _of,\c -1)
- (inclusive).
\return 0 on success, or a negative error code on failure.
\retval #OP_EREAD The underlying seek operation failed.
\retval #OP_EINVAL The stream was only partially open, or the target was
diff --git a/thirdparty/opus/opus_compare.c b/thirdparty/opus/opus_compare.c
index 1956e08fa5..06c67d752f 100644
--- a/thirdparty/opus/opus_compare.c
+++ b/thirdparty/opus/opus_compare.c
@@ -363,9 +363,6 @@ int main(int _argc,const char **_argv){
Ef*=Ef;
err+=Ef*Ef;
}
- free(xb);
- free(X);
- free(Y);
err=pow(err/nframes,1.0/16);
Q=100*(1-0.5*log(1+err)/log(1.13));
if(Q<0){
diff --git a/thirdparty/opus/opus_decoder.c b/thirdparty/opus/opus_decoder.c
index 9113638a00..080bec5072 100644
--- a/thirdparty/opus/opus_decoder.c
+++ b/thirdparty/opus/opus_decoder.c
@@ -78,26 +78,6 @@ struct OpusDecoder {
opus_uint32 rangeFinal;
};
-#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
-static void validate_opus_decoder(OpusDecoder *st)
-{
- celt_assert(st->channels == 1 || st->channels == 2);
- celt_assert(st->Fs == 48000 || st->Fs == 24000 || st->Fs == 16000 || st->Fs == 12000 || st->Fs == 8000);
- celt_assert(st->DecControl.API_sampleRate == st->Fs);
- celt_assert(st->DecControl.internalSampleRate == 0 || st->DecControl.internalSampleRate == 16000 || st->DecControl.internalSampleRate == 12000 || st->DecControl.internalSampleRate == 8000);
- celt_assert(st->DecControl.nChannelsAPI == st->channels);
- celt_assert(st->DecControl.nChannelsInternal == 0 || st->DecControl.nChannelsInternal == 1 || st->DecControl.nChannelsInternal == 2);
- celt_assert(st->DecControl.payloadSize_ms == 0 || st->DecControl.payloadSize_ms == 10 || st->DecControl.payloadSize_ms == 20 || st->DecControl.payloadSize_ms == 40 || st->DecControl.payloadSize_ms == 60);
-#ifdef OPUS_ARCHMASK
- celt_assert(st->arch >= 0);
- celt_assert(st->arch <= OPUS_ARCHMASK);
-#endif
- celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
-}
-#define VALIDATE_OPUS_DECODER(st) validate_opus_decoder(st)
-#else
-#define VALIDATE_OPUS_DECODER(st)
-#endif
int opus_decoder_get_size(int channels)
{
@@ -124,7 +104,7 @@ int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels)
return OPUS_BAD_ARG;
OPUS_CLEAR((char*)st, opus_decoder_get_size(channels));
- /* Initialize SILK decoder */
+ /* Initialize SILK encoder */
ret = silk_Get_Decoder_Size(&silkDecSizeBytes);
if (ret)
return OPUS_INTERNAL_ERROR;
@@ -237,7 +217,6 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
int audiosize;
int mode;
- int bandwidth;
int transition=0;
int start_band;
int redundancy=0;
@@ -274,12 +253,10 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
{
audiosize = st->frame_size;
mode = st->mode;
- bandwidth = st->bandwidth;
ec_dec_init(&dec,(unsigned char*)data,len);
} else {
audiosize = frame_size;
mode = st->prev_mode;
- bandwidth = 0;
if (mode == 0)
{
@@ -378,15 +355,15 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
{
st->DecControl.nChannelsInternal = st->stream_channels;
if( mode == MODE_SILK_ONLY ) {
- if( bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
+ if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
st->DecControl.internalSampleRate = 8000;
- } else if( bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
+ } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
st->DecControl.internalSampleRate = 12000;
- } else if( bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
+ } else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
st->DecControl.internalSampleRate = 16000;
} else {
st->DecControl.internalSampleRate = 16000;
- celt_assert( 0 );
+ silk_assert( 0 );
}
} else {
/* Hybrid mode */
@@ -450,26 +427,10 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
if (mode != MODE_CELT_ONLY)
start_band = 17;
- if (redundancy)
- {
- transition = 0;
- pcm_transition_silk_size=ALLOC_NONE;
- }
-
- ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16);
-
- if (transition && mode != MODE_CELT_ONLY)
- {
- pcm_transition = pcm_transition_silk;
- opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
- }
-
-
- if (bandwidth)
{
int endband=21;
- switch(bandwidth)
+ switch(st->bandwidth)
{
case OPUS_BANDWIDTH_NARROWBAND:
endband = 13;
@@ -484,13 +445,24 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
case OPUS_BANDWIDTH_FULLBAND:
endband = 21;
break;
- default:
- celt_assert(0);
- break;
}
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband)));
+ celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband));
+ celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels));
+ }
+
+ if (redundancy)
+ {
+ transition = 0;
+ pcm_transition_silk_size=ALLOC_NONE;
+ }
+
+ ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16);
+
+ if (transition && mode != MODE_CELT_ONLY)
+ {
+ pcm_transition = pcm_transition_silk;
+ opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
}
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels)));
/* Only allocation memory for redundancy if/when needed */
redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE;
@@ -499,21 +471,21 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
/* 5 ms redundant frame for CELT->SILK*/
if (redundancy && celt_to_silk)
{
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
+ celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
celt_decode_with_ec(celt_dec, data+len, redundancy_bytes,
redundant_audio, F5, NULL, 0);
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)));
+ celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
}
/* MUST be after PLC */
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band)));
+ celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band));
if (mode != MODE_SILK_ONLY)
{
int celt_frame_size = IMIN(F20, frame_size);
/* Make sure to discard any previous CELT state */
if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy)
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_RESET_STATE));
+ celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
/* Decode CELT */
celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data,
len, pcm, celt_frame_size, &dec, celt_accum);
@@ -528,7 +500,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
do a fade-out by decoding a silence frame */
if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) )
{
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
+ celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum);
}
}
@@ -546,18 +518,18 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
{
const CELTMode *celt_mode;
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode)));
+ celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode));
window = celt_mode->window;
}
/* 5 ms redundant frame for SILK->CELT */
if (redundancy && !celt_to_silk)
{
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_RESET_STATE));
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
+ celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
+ celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL, 0);
- MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)));
+ celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
}
@@ -633,7 +605,6 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels;
/* 48 x 2.5 ms = 120 ms */
opus_int16 size[48];
- VALIDATE_OPUS_DECODER(st);
if (decode_fec<0 || decode_fec>1)
return OPUS_BAD_ARG;
/* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */
@@ -769,7 +740,6 @@ int opus_decode_float(OpusDecoder *st, const unsigned char *data,
else
return OPUS_INVALID_PACKET;
}
- celt_assert(st->channels == 1 || st->channels == 2);
ALLOC(out, frame_size*st->channels, opus_int16);
ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0);
@@ -807,7 +777,6 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
else
return OPUS_INVALID_PACKET;
}
- celt_assert(st->channels == 1 || st->channels == 2);
ALLOC(out, frame_size*st->channels, float);
ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1);
@@ -895,7 +864,7 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
goto bad_arg;
}
if (st->prev_mode == MODE_CELT_ONLY)
- ret = celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
+ celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
else
*value = st->DecControl.prevPitchLag;
}
@@ -922,7 +891,7 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
break;
case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
{
- opus_int32 *value = va_arg(ap, opus_int32*);
+ opus_uint32 *value = va_arg(ap, opus_uint32*);
if (!value)
{
goto bad_arg;
@@ -930,26 +899,6 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
*value = st->last_packet_duration;
}
break;
- case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
- {
- opus_int32 value = va_arg(ap, opus_int32);
- if(value<0 || value>1)
- {
- goto bad_arg;
- }
- ret = celt_decoder_ctl(celt_dec, OPUS_SET_PHASE_INVERSION_DISABLED(value));
- }
- break;
- case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
- {
- opus_int32 *value = va_arg(ap, opus_int32*);
- if (!value)
- {
- goto bad_arg;
- }
- ret = celt_decoder_ctl(celt_dec, OPUS_GET_PHASE_INVERSION_DISABLED(value));
- }
- break;
default:
/*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
ret = OPUS_UNIMPLEMENTED;
diff --git a/thirdparty/opus/opus_encoder.c b/thirdparty/opus/opus_encoder.c
index e98ac5b8d0..9a516a884a 100644
--- a/thirdparty/opus/opus_encoder.c
+++ b/thirdparty/opus/opus_encoder.c
@@ -53,10 +53,6 @@
#define MAX_ENCODER_BUFFER 480
-#ifndef DISABLE_FLOAT_API
-#define PSEUDO_SNR_THRESHOLD 316.23f /* 10^(25/10) */
-#endif
-
typedef struct {
opus_val32 XX, XY, YY;
opus_val16 smoothed_width;
@@ -86,7 +82,6 @@ struct OpusEncoder {
int encoder_buffer;
int lfe;
int arch;
- int use_dtx; /* general DTX for both SILK and CELT */
#ifndef DISABLE_FLOAT_API
TonalityAnalysisState analysis;
#endif
@@ -102,8 +97,6 @@ struct OpusEncoder {
int prev_channels;
int prev_framesize;
int bandwidth;
- /* Bandwidth determined automatically from the rate (before any other adjustment) */
- int auto_bandwidth;
int silk_bw_switch;
/* Sampling rate (at the API level) */
int first;
@@ -112,10 +105,7 @@ struct OpusEncoder {
opus_val16 delay_buffer[MAX_ENCODER_BUFFER*2];
#ifndef DISABLE_FLOAT_API
int detected_bandwidth;
- int nb_no_activity_frames;
- opus_val32 peak_signal_energy;
#endif
- int nonfinal_frame; /* current frame is not the final in a packet */
opus_uint32 rangeFinal;
};
@@ -123,46 +113,38 @@ struct OpusEncoder {
middle (memoriless) threshold. The second column is the hysteresis
(difference with the middle) */
static const opus_int32 mono_voice_bandwidth_thresholds[8] = {
- 9000, 700, /* NB<->MB */
- 9000, 700, /* MB<->WB */
- 13500, 1000, /* WB<->SWB */
- 14000, 2000, /* SWB<->FB */
+ 11000, 1000, /* NB<->MB */
+ 14000, 1000, /* MB<->WB */
+ 17000, 1000, /* WB<->SWB */
+ 21000, 2000, /* SWB<->FB */
};
static const opus_int32 mono_music_bandwidth_thresholds[8] = {
- 9000, 700, /* NB<->MB */
- 9000, 700, /* MB<->WB */
- 11000, 1000, /* WB<->SWB */
- 12000, 2000, /* SWB<->FB */
+ 12000, 1000, /* NB<->MB */
+ 15000, 1000, /* MB<->WB */
+ 18000, 2000, /* WB<->SWB */
+ 22000, 2000, /* SWB<->FB */
};
static const opus_int32 stereo_voice_bandwidth_thresholds[8] = {
- 9000, 700, /* NB<->MB */
- 9000, 700, /* MB<->WB */
- 13500, 1000, /* WB<->SWB */
- 14000, 2000, /* SWB<->FB */
+ 11000, 1000, /* NB<->MB */
+ 14000, 1000, /* MB<->WB */
+ 21000, 2000, /* WB<->SWB */
+ 28000, 2000, /* SWB<->FB */
};
static const opus_int32 stereo_music_bandwidth_thresholds[8] = {
- 9000, 700, /* NB<->MB */
- 9000, 700, /* MB<->WB */
- 11000, 1000, /* WB<->SWB */
- 12000, 2000, /* SWB<->FB */
+ 12000, 1000, /* NB<->MB */
+ 18000, 2000, /* MB<->WB */
+ 21000, 2000, /* WB<->SWB */
+ 30000, 2000, /* SWB<->FB */
};
/* Threshold bit-rates for switching between mono and stereo */
-static const opus_int32 stereo_voice_threshold = 19000;
-static const opus_int32 stereo_music_threshold = 17000;
+static const opus_int32 stereo_voice_threshold = 30000;
+static const opus_int32 stereo_music_threshold = 30000;
/* Threshold bit-rate for switching between SILK/hybrid and CELT-only */
static const opus_int32 mode_thresholds[2][2] = {
/* voice */ /* music */
- { 64000, 10000}, /* mono */
- { 44000, 10000}, /* stereo */
-};
-
-static const opus_int32 fec_thresholds[] = {
- 12000, 1000, /* NB */
- 14000, 1000, /* MB */
- 16000, 1000, /* WB */
- 20000, 1000, /* SWB */
- 22000, 1000, /* FB */
+ { 64000, 16000}, /* mono */
+ { 36000, 16000}, /* stereo */
};
int opus_encoder_get_size(int channels)
@@ -263,8 +245,7 @@ int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int applicat
st->bandwidth = OPUS_BANDWIDTH_FULLBAND;
#ifndef DISABLE_FLOAT_API
- tonality_analysis_init(&st->analysis, st->Fs);
- st->analysis.application = st->application;
+ tonality_analysis_init(&st->analysis);
#endif
return OPUS_OK;
@@ -342,11 +323,10 @@ static void silk_biquad_float(
}
#endif
-static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs, int arch)
+static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
{
opus_int32 B_Q28[ 3 ], A_Q28[ 2 ];
opus_int32 Fc_Q19, r_Q28, r_Q22;
- (void)arch;
silk_assert( cutoff_Hz <= silk_int32_MAX / SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ) );
Fc_Q19 = silk_DIV32_16( silk_SMULBB( SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ), cutoff_Hz ), Fs/1000 );
@@ -366,10 +346,9 @@ static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *ou
A_Q28[ 1 ] = silk_SMULWW( r_Q22, r_Q22 );
#ifdef FIXED_POINT
- if( channels == 1 ) {
- silk_biquad_alt_stride1( in, B_Q28, A_Q28, hp_mem, out, len );
- } else {
- silk_biquad_alt_stride2( in, B_Q28, A_Q28, hp_mem, out, len, arch );
+ silk_biquad_alt( in, B_Q28, A_Q28, hp_mem, out, len, channels );
+ if( channels == 2 ) {
+ silk_biquad_alt( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels );
}
#else
silk_biquad_float( in, B_Q28, A_Q28, hp_mem, out, len, channels );
@@ -385,17 +364,21 @@ static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *ou
int c, i;
int shift;
- /* Approximates -round(log2(6.3*cutoff_Hz/Fs)) */
- shift=celt_ilog2(Fs/(cutoff_Hz*4));
+ /* Approximates -round(log2(4.*cutoff_Hz/Fs)) */
+ shift=celt_ilog2(Fs/(cutoff_Hz*3));
for (c=0;c<channels;c++)
{
for (i=0;i<len;i++)
{
- opus_val32 x, y;
- x = SHL32(EXTEND32(in[channels*i+c]), 14);
- y = x-hp_mem[2*c];
+ opus_val32 x, tmp, y;
+ x = SHL32(EXTEND32(in[channels*i+c]), 15);
+ /* First stage */
+ tmp = x-hp_mem[2*c];
hp_mem[2*c] = hp_mem[2*c] + PSHR32(x - hp_mem[2*c], shift);
- out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 14), 32767));
+ /* Second stage */
+ y = tmp - hp_mem[2*c+1];
+ hp_mem[2*c+1] = hp_mem[2*c+1] + PSHR32(tmp - hp_mem[2*c+1], shift);
+ out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 15), 32767));
}
}
}
@@ -403,41 +386,24 @@ static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *ou
#else
static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
{
- int i;
- float coef, coef2;
- coef = 6.3f*cutoff_Hz/Fs;
- coef2 = 1-coef;
- if (channels==2)
+ int c, i;
+ float coef;
+
+ coef = 4.0f*cutoff_Hz/Fs;
+ for (c=0;c<channels;c++)
{
- float m0, m2;
- m0 = hp_mem[0];
- m2 = hp_mem[2];
for (i=0;i<len;i++)
{
- opus_val32 x0, x1, out0, out1;
- x0 = in[2*i+0];
- x1 = in[2*i+1];
- out0 = x0-m0;
- out1 = x1-m2;
- m0 = coef*x0 + VERY_SMALL + coef2*m0;
- m2 = coef*x1 + VERY_SMALL + coef2*m2;
- out[2*i+0] = out0;
- out[2*i+1] = out1;
+ opus_val32 x, tmp, y;
+ x = in[channels*i+c];
+ /* First stage */
+ tmp = x-hp_mem[2*c];
+ hp_mem[2*c] = hp_mem[2*c] + coef*(x - hp_mem[2*c]) + VERY_SMALL;
+ /* Second stage */
+ y = tmp - hp_mem[2*c+1];
+ hp_mem[2*c+1] = hp_mem[2*c+1] + coef*(tmp - hp_mem[2*c+1]) + VERY_SMALL;
+ out[channels*i+c] = y;
}
- hp_mem[0] = m0;
- hp_mem[2] = m2;
- } else {
- float m0;
- m0 = hp_mem[0];
- for (i=0;i<len;i++)
- {
- opus_val32 x, y;
- x = in[i];
- y = x-m0;
- m0 = coef*x + VERY_SMALL + coef2*m0;
- out[i] = y;
- }
- hp_mem[0] = m0;
}
}
#endif
@@ -555,57 +521,287 @@ static opus_int32 user_bitrate_to_bitrate(OpusEncoder *st, int frame_size, int m
}
#ifndef DISABLE_FLOAT_API
+/* Don't use more than 60 ms for the frame size analysis */
+#define MAX_DYNAMIC_FRAMESIZE 24
+/* Estimates how much the bitrate will be boosted based on the sub-frame energy */
+static float transient_boost(const float *E, const float *E_1, int LM, int maxM)
+{
+ int i;
+ int M;
+ float sumE=0, sumE_1=0;
+ float metric;
+
+ M = IMIN(maxM, (1<<LM)+1);
+ for (i=0;i<M;i++)
+ {
+ sumE += E[i];
+ sumE_1 += E_1[i];
+ }
+ metric = sumE*sumE_1/(M*M);
+ /*if (LM==3)
+ printf("%f\n", metric);*/
+ /*return metric>10 ? 1 : 0;*/
+ /*return MAX16(0,1-exp(-.25*(metric-2.)));*/
+ return MIN16(1,(float)sqrt(MAX16(0,.05f*(metric-2))));
+}
+
+/* Viterbi decoding trying to find the best frame size combination using look-ahead
+
+ State numbering:
+ 0: unused
+ 1: 2.5 ms
+ 2: 5 ms (#1)
+ 3: 5 ms (#2)
+ 4: 10 ms (#1)
+ 5: 10 ms (#2)
+ 6: 10 ms (#3)
+ 7: 10 ms (#4)
+ 8: 20 ms (#1)
+ 9: 20 ms (#2)
+ 10: 20 ms (#3)
+ 11: 20 ms (#4)
+ 12: 20 ms (#5)
+ 13: 20 ms (#6)
+ 14: 20 ms (#7)
+ 15: 20 ms (#8)
+*/
+static int transient_viterbi(const float *E, const float *E_1, int N, int frame_cost, int rate)
+{
+ int i;
+ float cost[MAX_DYNAMIC_FRAMESIZE][16];
+ int states[MAX_DYNAMIC_FRAMESIZE][16];
+ float best_cost;
+ int best_state;
+ float factor;
+ /* Take into account that we damp VBR in the 32 kb/s to 64 kb/s range. */
+ if (rate<80)
+ factor=0;
+ else if (rate>160)
+ factor=1;
+ else
+ factor = (rate-80.f)/80.f;
+ /* Makes variable framesize less aggressive at lower bitrates, but I can't
+ find any valid theoretical justification for this (other than it seems
+ to help) */
+ for (i=0;i<16;i++)
+ {
+ /* Impossible state */
+ states[0][i] = -1;
+ cost[0][i] = 1e10;
+ }
+ for (i=0;i<4;i++)
+ {
+ cost[0][1<<i] = (frame_cost + rate*(1<<i))*(1+factor*transient_boost(E, E_1, i, N+1));
+ states[0][1<<i] = i;
+ }
+ for (i=1;i<N;i++)
+ {
+ int j;
+
+ /* Follow continuations */
+ for (j=2;j<16;j++)
+ {
+ cost[i][j] = cost[i-1][j-1];
+ states[i][j] = j-1;
+ }
+
+ /* New frames */
+ for(j=0;j<4;j++)
+ {
+ int k;
+ float min_cost;
+ float curr_cost;
+ states[i][1<<j] = 1;
+ min_cost = cost[i-1][1];
+ for(k=1;k<4;k++)
+ {
+ float tmp = cost[i-1][(1<<(k+1))-1];
+ if (tmp < min_cost)
+ {
+ states[i][1<<j] = (1<<(k+1))-1;
+ min_cost = tmp;
+ }
+ }
+ curr_cost = (frame_cost + rate*(1<<j))*(1+factor*transient_boost(E+i, E_1+i, j, N-i+1));
+ cost[i][1<<j] = min_cost;
+ /* If part of the frame is outside the analysis window, only count part of the cost */
+ if (N-i < (1<<j))
+ cost[i][1<<j] += curr_cost*(float)(N-i)/(1<<j);
+ else
+ cost[i][1<<j] += curr_cost;
+ }
+ }
+
+ best_state=1;
+ best_cost = cost[N-1][1];
+ /* Find best end state (doesn't force a frame to end at N-1) */
+ for (i=2;i<16;i++)
+ {
+ if (cost[N-1][i]<best_cost)
+ {
+ best_cost = cost[N-1][i];
+ best_state = i;
+ }
+ }
+
+ /* Follow transitions back */
+ for (i=N-1;i>=0;i--)
+ {
+ /*printf("%d ", best_state);*/
+ best_state = states[i][best_state];
+ }
+ /*printf("%d\n", best_state);*/
+ return best_state;
+}
+
+static int optimize_framesize(const void *x, int len, int C, opus_int32 Fs,
+ int bitrate, opus_val16 tonality, float *mem, int buffering,
+ downmix_func downmix)
+{
+ int N;
+ int i;
+ float e[MAX_DYNAMIC_FRAMESIZE+4];
+ float e_1[MAX_DYNAMIC_FRAMESIZE+3];
+ opus_val32 memx;
+ int bestLM=0;
+ int subframe;
+ int pos;
+ int offset;
+ VARDECL(opus_val32, sub);
+
+ subframe = Fs/400;
+ ALLOC(sub, subframe, opus_val32);
+ e[0]=mem[0];
+ e_1[0]=1.f/(EPSILON+mem[0]);
+ if (buffering)
+ {
+ /* Consider the CELT delay when not in restricted-lowdelay */
+ /* We assume the buffering is between 2.5 and 5 ms */
+ offset = 2*subframe - buffering;
+ celt_assert(offset>=0 && offset <= subframe);
+ len -= offset;
+ e[1]=mem[1];
+ e_1[1]=1.f/(EPSILON+mem[1]);
+ e[2]=mem[2];
+ e_1[2]=1.f/(EPSILON+mem[2]);
+ pos = 3;
+ } else {
+ pos=1;
+ offset=0;
+ }
+ N=IMIN(len/subframe, MAX_DYNAMIC_FRAMESIZE);
+ /* Just silencing a warning, it's really initialized later */
+ memx = 0;
+ for (i=0;i<N;i++)
+ {
+ float tmp;
+ opus_val32 tmpx;
+ int j;
+ tmp=EPSILON;
+
+ downmix(x, sub, subframe, i*subframe+offset, 0, -2, C);
+ if (i==0)
+ memx = sub[0];
+ for (j=0;j<subframe;j++)
+ {
+ tmpx = sub[j];
+ tmp += (tmpx-memx)*(float)(tmpx-memx);
+ memx = tmpx;
+ }
+ e[i+pos] = tmp;
+ e_1[i+pos] = 1.f/tmp;
+ }
+ /* Hack to get 20 ms working with APPLICATION_AUDIO
+ The real problem is that the corresponding memory needs to use 1.5 ms
+ from this frame and 1 ms from the next frame */
+ e[i+pos] = e[i+pos-1];
+ if (buffering)
+ N=IMIN(MAX_DYNAMIC_FRAMESIZE, N+2);
+ bestLM = transient_viterbi(e, e_1, N, (int)((1.f+.5f*tonality)*(60*C+40)), bitrate/400);
+ mem[0] = e[1<<bestLM];
+ if (buffering)
+ {
+ mem[1] = e[(1<<bestLM)+1];
+ mem[2] = e[(1<<bestLM)+2];
+ }
+ return bestLM;
+}
+
+#endif
+
+#ifndef DISABLE_FLOAT_API
#ifdef FIXED_POINT
#define PCM2VAL(x) FLOAT2INT16(x)
#else
#define PCM2VAL(x) SCALEIN(x)
#endif
-
-void downmix_float(const void *_x, opus_val32 *y, int subframe, int offset, int c1, int c2, int C)
+void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C)
{
const float *x;
+ opus_val32 scale;
int j;
-
x = (const float *)_x;
for (j=0;j<subframe;j++)
- y[j] = PCM2VAL(x[(j+offset)*C+c1]);
+ sub[j] = PCM2VAL(x[(j+offset)*C+c1]);
if (c2>-1)
{
for (j=0;j<subframe;j++)
- y[j] += PCM2VAL(x[(j+offset)*C+c2]);
+ sub[j] += PCM2VAL(x[(j+offset)*C+c2]);
} else if (c2==-2)
{
int c;
for (c=1;c<C;c++)
{
for (j=0;j<subframe;j++)
- y[j] += PCM2VAL(x[(j+offset)*C+c]);
+ sub[j] += PCM2VAL(x[(j+offset)*C+c]);
}
}
+#ifdef FIXED_POINT
+ scale = (1<<SIG_SHIFT);
+#else
+ scale = 1.f;
+#endif
+ if (C==-2)
+ scale /= C;
+ else
+ scale /= 2;
+ for (j=0;j<subframe;j++)
+ sub[j] *= scale;
}
#endif
-void downmix_int(const void *_x, opus_val32 *y, int subframe, int offset, int c1, int c2, int C)
+void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C)
{
const opus_int16 *x;
+ opus_val32 scale;
int j;
-
x = (const opus_int16 *)_x;
for (j=0;j<subframe;j++)
- y[j] = x[(j+offset)*C+c1];
+ sub[j] = x[(j+offset)*C+c1];
if (c2>-1)
{
for (j=0;j<subframe;j++)
- y[j] += x[(j+offset)*C+c2];
+ sub[j] += x[(j+offset)*C+c2];
} else if (c2==-2)
{
int c;
for (c=1;c<C;c++)
{
for (j=0;j<subframe;j++)
- y[j] += x[(j+offset)*C+c];
+ sub[j] += x[(j+offset)*C+c];
}
}
+#ifdef FIXED_POINT
+ scale = (1<<SIG_SHIFT);
+#else
+ scale = 1.f/32768;
+#endif
+ if (C==-2)
+ scale /= C;
+ else
+ scale /= 2;
+ for (j=0;j<subframe;j++)
+ sub[j] *= scale;
}
opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs)
@@ -615,24 +811,53 @@ opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_
return -1;
if (variable_duration == OPUS_FRAMESIZE_ARG)
new_size = frame_size;
- else if (variable_duration >= OPUS_FRAMESIZE_2_5_MS && variable_duration <= OPUS_FRAMESIZE_120_MS)
- {
- if (variable_duration <= OPUS_FRAMESIZE_40_MS)
- new_size = (Fs/400)<<(variable_duration-OPUS_FRAMESIZE_2_5_MS);
- else
- new_size = (variable_duration-OPUS_FRAMESIZE_2_5_MS-2)*Fs/50;
- }
+ else if (variable_duration == OPUS_FRAMESIZE_VARIABLE)
+ new_size = Fs/50;
+ else if (variable_duration >= OPUS_FRAMESIZE_2_5_MS && variable_duration <= OPUS_FRAMESIZE_60_MS)
+ new_size = IMIN(3*Fs/50, (Fs/400)<<(variable_duration-OPUS_FRAMESIZE_2_5_MS));
else
return -1;
if (new_size>frame_size)
return -1;
- if (400*new_size!=Fs && 200*new_size!=Fs && 100*new_size!=Fs &&
- 50*new_size!=Fs && 25*new_size!=Fs && 50*new_size!=3*Fs &&
- 50*new_size!=4*Fs && 50*new_size!=5*Fs && 50*new_size!=6*Fs)
+ if (400*new_size!=Fs && 200*new_size!=Fs && 100*new_size!=Fs &&
+ 50*new_size!=Fs && 25*new_size!=Fs && 50*new_size!=3*Fs)
return -1;
return new_size;
}
+opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size,
+ int variable_duration, int C, opus_int32 Fs, int bitrate_bps,
+ int delay_compensation, downmix_func downmix
+#ifndef DISABLE_FLOAT_API
+ , float *subframe_mem
+#endif
+ )
+{
+#ifndef DISABLE_FLOAT_API
+ if (variable_duration == OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs/200)
+ {
+ int LM = 3;
+ LM = optimize_framesize(analysis_pcm, frame_size, C, Fs, bitrate_bps,
+ 0, subframe_mem, delay_compensation, downmix);
+ while ((Fs/400<<LM)>frame_size)
+ LM--;
+ frame_size = (Fs/400<<LM);
+ } else
+#else
+ (void)analysis_pcm;
+ (void)C;
+ (void)bitrate_bps;
+ (void)delay_compensation;
+ (void)downmix;
+#endif
+ {
+ frame_size = frame_size_select(frame_size, variable_duration, Fs);
+ }
+ if (frame_size<0)
+ return -1;
+ return frame_size;
+}
+
opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem)
{
opus_val32 xx, xy, yy;
@@ -679,12 +904,6 @@ opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int3
xy += SHR32(pxy, 10);
yy += SHR32(pyy, 10);
}
-#ifndef FIXED_POINT
- if (!(xx < 1e9f) || celt_isnan(xx) || !(yy < 1e9f) || celt_isnan(yy))
- {
- xy = xx = yy = 0;
- }
-#endif
mem->XX += MULT16_32_Q15(short_alpha, xx-mem->XX);
mem->XY += MULT16_32_Q15(short_alpha, xy-mem->XY);
mem->YY += MULT16_32_Q15(short_alpha, yy-mem->YY);
@@ -715,354 +934,6 @@ opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int3
return EXTRACT16(MIN32(Q15ONE, MULT16_16(20, mem->max_follower)));
}
-static int decide_fec(int useInBandFEC, int PacketLoss_perc, int last_fec, int mode, int *bandwidth, opus_int32 rate)
-{
- int orig_bandwidth;
- if (!useInBandFEC || PacketLoss_perc == 0 || mode == MODE_CELT_ONLY)
- return 0;
- orig_bandwidth = *bandwidth;
- for (;;)
- {
- opus_int32 hysteresis;
- opus_int32 LBRR_rate_thres_bps;
- /* Compute threshold for using FEC at the current bandwidth setting */
- LBRR_rate_thres_bps = fec_thresholds[2*(*bandwidth - OPUS_BANDWIDTH_NARROWBAND)];
- hysteresis = fec_thresholds[2*(*bandwidth - OPUS_BANDWIDTH_NARROWBAND) + 1];
- if (last_fec == 1) LBRR_rate_thres_bps -= hysteresis;
- if (last_fec == 0) LBRR_rate_thres_bps += hysteresis;
- LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps,
- 125 - silk_min( PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
- /* If loss <= 5%, we look at whether we have enough rate to enable FEC.
- If loss > 5%, we decrease the bandwidth until we can enable FEC. */
- if (rate > LBRR_rate_thres_bps)
- return 1;
- else if (PacketLoss_perc <= 5)
- return 0;
- else if (*bandwidth > OPUS_BANDWIDTH_NARROWBAND)
- (*bandwidth)--;
- else
- break;
- }
- /* Couldn't find any bandwidth to enable FEC, keep original bandwidth. */
- *bandwidth = orig_bandwidth;
- return 0;
-}
-
-static int compute_silk_rate_for_hybrid(int rate, int bandwidth, int frame20ms, int vbr, int fec, int channels) {
- int entry;
- int i;
- int N;
- int silk_rate;
- static int rate_table[][5] = {
- /* |total| |-------- SILK------------|
- |-- No FEC -| |--- FEC ---|
- 10ms 20ms 10ms 20ms */
- { 0, 0, 0, 0, 0},
- {12000, 10000, 10000, 11000, 11000},
- {16000, 13500, 13500, 15000, 15000},
- {20000, 16000, 16000, 18000, 18000},
- {24000, 18000, 18000, 21000, 21000},
- {32000, 22000, 22000, 28000, 28000},
- {64000, 38000, 38000, 50000, 50000}
- };
- /* Do the allocation per-channel. */
- rate /= channels;
- entry = 1 + frame20ms + 2*fec;
- N = sizeof(rate_table)/sizeof(rate_table[0]);
- for (i=1;i<N;i++)
- {
- if (rate_table[i][0] > rate) break;
- }
- if (i == N)
- {
- silk_rate = rate_table[i-1][entry];
- /* For now, just give 50% of the extra bits to SILK. */
- silk_rate += (rate-rate_table[i-1][0])/2;
- } else {
- opus_int32 lo, hi, x0, x1;
- lo = rate_table[i-1][entry];
- hi = rate_table[i][entry];
- x0 = rate_table[i-1][0];
- x1 = rate_table[i][0];
- silk_rate = (lo*(x1-rate) + hi*(rate-x0))/(x1-x0);
- }
- if (!vbr)
- {
- /* Tiny boost to SILK for CBR. We should probably tune this better. */
- silk_rate += 100;
- }
- if (bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND)
- silk_rate += 300;
- silk_rate *= channels;
- /* Small adjustment for stereo (calibrated for 32 kb/s, haven't tried other bitrates). */
- if (channels == 2 && rate >= 12000)
- silk_rate -= 1000;
- return silk_rate;
-}
-
-/* Returns the equivalent bitrate corresponding to 20 ms frames,
- complexity 10 VBR operation. */
-static opus_int32 compute_equiv_rate(opus_int32 bitrate, int channels,
- int frame_rate, int vbr, int mode, int complexity, int loss)
-{
- opus_int32 equiv;
- equiv = bitrate;
- /* Take into account overhead from smaller frames. */
- if (frame_rate > 50)
- equiv -= (40*channels+20)*(frame_rate - 50);
- /* CBR is about a 8% penalty for both SILK and CELT. */
- if (!vbr)
- equiv -= equiv/12;
- /* Complexity makes about 10% difference (from 0 to 10) in general. */
- equiv = equiv * (90+complexity)/100;
- if (mode == MODE_SILK_ONLY || mode == MODE_HYBRID)
- {
- /* SILK complexity 0-1 uses the non-delayed-decision NSQ, which
- costs about 20%. */
- if (complexity<2)
- equiv = equiv*4/5;
- equiv -= equiv*loss/(6*loss + 10);
- } else if (mode == MODE_CELT_ONLY) {
- /* CELT complexity 0-4 doesn't have the pitch filter, which costs
- about 10%. */
- if (complexity<5)
- equiv = equiv*9/10;
- } else {
- /* Mode not known yet */
- /* Half the SILK loss*/
- equiv -= equiv*loss/(12*loss + 20);
- }
- return equiv;
-}
-
-#ifndef DISABLE_FLOAT_API
-
-int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth)
-{
- int silence = 0;
- opus_val32 sample_max = 0;
-#ifdef MLP_TRAINING
- return 0;
-#endif
- sample_max = celt_maxabs16(pcm, frame_size*channels);
-
-#ifdef FIXED_POINT
- silence = (sample_max == 0);
- (void)lsb_depth;
-#else
- silence = (sample_max <= (opus_val16) 1 / (1 << lsb_depth));
-#endif
-
- return silence;
-}
-
-#ifdef FIXED_POINT
-static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, int channels, int arch)
-{
- int i;
- opus_val32 sample_max;
- int max_shift;
- int shift;
- opus_val32 energy = 0;
- int len = frame_size*channels;
- (void)arch;
- /* Max amplitude in the signal */
- sample_max = celt_maxabs16(pcm, len);
-
- /* Compute the right shift required in the MAC to avoid an overflow */
- max_shift = celt_ilog2(len);
- shift = IMAX(0, (celt_ilog2(sample_max) << 1) + max_shift - 28);
-
- /* Compute the energy */
- for (i=0; i<len; i++)
- energy += SHR32(MULT16_16(pcm[i], pcm[i]), shift);
-
- /* Normalize energy by the frame size and left-shift back to the original position */
- energy /= len;
- energy = SHL32(energy, shift);
-
- return energy;
-}
-#else
-static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, int channels, int arch)
-{
- int len = frame_size*channels;
- return celt_inner_prod(pcm, pcm, len, arch)/len;
-}
-#endif
-
-/* Decides if DTX should be turned on (=1) or off (=0) */
-static int decide_dtx_mode(float activity_probability, /* probability that current frame contains speech/music */
- int *nb_no_activity_frames, /* number of consecutive frames with no activity */
- opus_val32 peak_signal_energy, /* peak energy of desired signal detected so far */
- const opus_val16 *pcm, /* input pcm signal */
- int frame_size, /* frame size */
- int channels,
- int is_silence, /* only digital silence detected in this frame */
- int arch
- )
-{
- opus_val32 noise_energy;
-
- if (!is_silence)
- {
- if (activity_probability < DTX_ACTIVITY_THRESHOLD) /* is noise */
- {
- noise_energy = compute_frame_energy(pcm, frame_size, channels, arch);
-
- /* but is sufficiently quiet */
- is_silence = peak_signal_energy >= (PSEUDO_SNR_THRESHOLD * noise_energy);
- }
- }
-
- if (is_silence)
- {
- /* The number of consecutive DTX frames should be within the allowed bounds */
- (*nb_no_activity_frames)++;
-
- if (*nb_no_activity_frames > NB_SPEECH_FRAMES_BEFORE_DTX)
- {
- if (*nb_no_activity_frames <= (NB_SPEECH_FRAMES_BEFORE_DTX + MAX_CONSECUTIVE_DTX))
- /* Valid frame for DTX! */
- return 1;
- else
- (*nb_no_activity_frames) = NB_SPEECH_FRAMES_BEFORE_DTX;
- }
- } else
- (*nb_no_activity_frames) = 0;
-
- return 0;
-}
-
-#endif
-
-static opus_int32 encode_multiframe_packet(OpusEncoder *st,
- const opus_val16 *pcm,
- int nb_frames,
- int frame_size,
- unsigned char *data,
- opus_int32 out_data_bytes,
- int to_celt,
- int lsb_depth,
- int float_api)
-{
- int i;
- int ret = 0;
- VARDECL(unsigned char, tmp_data);
- int bak_mode, bak_bandwidth, bak_channels, bak_to_mono;
- VARDECL(OpusRepacketizer, rp);
- int max_header_bytes;
- opus_int32 bytes_per_frame;
- opus_int32 cbr_bytes;
- opus_int32 repacketize_len;
- int tmp_len;
- ALLOC_STACK;
-
- /* Worst cases:
- * 2 frames: Code 2 with different compressed sizes
- * >2 frames: Code 3 VBR */
- max_header_bytes = nb_frames == 2 ? 3 : (2+(nb_frames-1)*2);
-
- if (st->use_vbr || st->user_bitrate_bps==OPUS_BITRATE_MAX)
- repacketize_len = out_data_bytes;
- else {
- cbr_bytes = 3*st->bitrate_bps/(3*8*st->Fs/(frame_size*nb_frames));
- repacketize_len = IMIN(cbr_bytes, out_data_bytes);
- }
- bytes_per_frame = IMIN(1276, 1+(repacketize_len-max_header_bytes)/nb_frames);
-
- ALLOC(tmp_data, nb_frames*bytes_per_frame, unsigned char);
- ALLOC(rp, 1, OpusRepacketizer);
- opus_repacketizer_init(rp);
-
- bak_mode = st->user_forced_mode;
- bak_bandwidth = st->user_bandwidth;
- bak_channels = st->force_channels;
-
- st->user_forced_mode = st->mode;
- st->user_bandwidth = st->bandwidth;
- st->force_channels = st->stream_channels;
-
- bak_to_mono = st->silk_mode.toMono;
- if (bak_to_mono)
- st->force_channels = 1;
- else
- st->prev_channels = st->stream_channels;
-
- for (i=0;i<nb_frames;i++)
- {
- st->silk_mode.toMono = 0;
- st->nonfinal_frame = i<(nb_frames-1);
-
- /* When switching from SILK/Hybrid to CELT, only ask for a switch at the last frame */
- if (to_celt && i==nb_frames-1)
- st->user_forced_mode = MODE_CELT_ONLY;
-
- tmp_len = opus_encode_native(st, pcm+i*(st->channels*frame_size), frame_size,
- tmp_data+i*bytes_per_frame, bytes_per_frame, lsb_depth, NULL, 0, 0, 0, 0,
- NULL, float_api);
-
- if (tmp_len<0)
- {
- RESTORE_STACK;
- return OPUS_INTERNAL_ERROR;
- }
-
- ret = opus_repacketizer_cat(rp, tmp_data+i*bytes_per_frame, tmp_len);
-
- if (ret<0)
- {
- RESTORE_STACK;
- return OPUS_INTERNAL_ERROR;
- }
- }
-
- ret = opus_repacketizer_out_range_impl(rp, 0, nb_frames, data, repacketize_len, 0, !st->use_vbr);
-
- if (ret<0)
- {
- RESTORE_STACK;
- return OPUS_INTERNAL_ERROR;
- }
-
- /* Discard configs that were forced locally for the purpose of repacketization */
- st->user_forced_mode = bak_mode;
- st->user_bandwidth = bak_bandwidth;
- st->force_channels = bak_channels;
- st->silk_mode.toMono = bak_to_mono;
-
- RESTORE_STACK;
- return ret;
-}
-
-static int compute_redundancy_bytes(opus_int32 max_data_bytes, opus_int32 bitrate_bps, int frame_rate, int channels)
-{
- int redundancy_bytes_cap;
- int redundancy_bytes;
- opus_int32 redundancy_rate;
- int base_bits;
- opus_int32 available_bits;
- base_bits = (40*channels+20);
-
- /* Equivalent rate for 5 ms frames. */
- redundancy_rate = bitrate_bps + base_bits*(200 - frame_rate);
- /* For VBR, further increase the bitrate if we can afford it. It's pretty short
- and we'll avoid artefacts. */
- redundancy_rate = 3*redundancy_rate/2;
- redundancy_bytes = redundancy_rate/1600;
-
- /* Compute the max rate we can use given CBR or VBR with cap. */
- available_bits = max_data_bytes*8 - 2*base_bits;
- redundancy_bytes_cap = (available_bits*240/(240+48000/frame_rate) + base_bits)/8;
- redundancy_bytes = IMIN(redundancy_bytes, redundancy_bytes_cap);
- /* It we can't get enough bits for redundancy to be worth it, rely on the decoder PLC. */
- if (redundancy_bytes > 4 + 8*channels)
- redundancy_bytes = IMIN(257, redundancy_bytes);
- else
- redundancy_bytes = 0;
- return redundancy_bytes;
-}
-
opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
@@ -1100,7 +971,6 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
AnalysisInfo analysis_info;
int analysis_read_pos_bak=-1;
int analysis_read_subframe_bak=-1;
- int is_silence = 0;
#endif
VARDECL(opus_val16, tmp_prefill);
@@ -1109,19 +979,15 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
max_data_bytes = IMIN(1276, out_data_bytes);
st->rangeFinal = 0;
- if (frame_size <= 0 || max_data_bytes <= 0)
+ if ((!st->variable_duration && 400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs &&
+ 50*frame_size != st->Fs && 25*frame_size != st->Fs && 50*frame_size != 3*st->Fs)
+ || (400*frame_size < st->Fs)
+ || max_data_bytes<=0
+ )
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
-
- /* Cannot encode 100 ms in 1 byte */
- if (max_data_bytes==1 && st->Fs==(frame_size*10))
- {
- RESTORE_STACK;
- return OPUS_BUFFER_TOO_SMALL;
- }
-
silk_enc = (char*)st+st->silk_enc_offset;
celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
@@ -1135,55 +1001,31 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
#ifndef DISABLE_FLOAT_API
analysis_info.valid = 0;
#ifdef FIXED_POINT
- if (st->silk_mode.complexity >= 10 && st->Fs>=16000)
+ if (st->silk_mode.complexity >= 10 && st->Fs==48000)
#else
- if (st->silk_mode.complexity >= 7 && st->Fs>=16000)
+ if (st->silk_mode.complexity >= 7 && st->Fs==48000)
#endif
{
- is_silence = is_digital_silence(pcm, frame_size, st->channels, lsb_depth);
analysis_read_pos_bak = st->analysis.read_pos;
analysis_read_subframe_bak = st->analysis.read_subframe;
run_analysis(&st->analysis, celt_mode, analysis_pcm, analysis_size, frame_size,
c1, c2, analysis_channels, st->Fs,
lsb_depth, downmix, &analysis_info);
-
- /* Track the peak signal energy */
- if (!is_silence && analysis_info.activity_probability > DTX_ACTIVITY_THRESHOLD)
- st->peak_signal_energy = MAX32(MULT16_32_Q15(QCONST16(0.999f, 15), st->peak_signal_energy),
- compute_frame_energy(pcm, frame_size, st->channels, st->arch));
- } else if (st->analysis.initialized) {
- tonality_analysis_reset(&st->analysis);
}
#else
(void)analysis_pcm;
(void)analysis_size;
- (void)c1;
- (void)c2;
- (void)analysis_channels;
- (void)downmix;
#endif
-#ifndef DISABLE_FLOAT_API
- /* Reset voice_ratio if this frame is not silent or if analysis is disabled.
- * Otherwise, preserve voice_ratio from the last non-silent frame */
- if (!is_silence)
- st->voice_ratio = -1;
+ st->voice_ratio = -1;
+#ifndef DISABLE_FLOAT_API
st->detected_bandwidth = 0;
if (analysis_info.valid)
{
int analysis_bandwidth;
if (st->signal_type == OPUS_AUTO)
- {
- float prob;
- if (st->prev_mode == 0)
- prob = analysis_info.music_prob;
- else if (st->prev_mode == MODE_CELT_ONLY)
- prob = analysis_info.music_prob_max;
- else
- prob = analysis_info.music_prob_min;
- st->voice_ratio = (int)floor(.5+100*(1-prob));
- }
+ st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob));
analysis_bandwidth = analysis_info.bandwidth;
if (analysis_bandwidth<=12)
@@ -1197,8 +1039,6 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
else
st->detected_bandwidth = OPUS_BANDWIDTH_FULLBAND;
}
-#else
- st->voice_ratio = -1;
#endif
if (st->channels==2 && st->force_channels!=1)
@@ -1212,13 +1052,12 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
if (!st->use_vbr)
{
int cbrBytes;
- /* Multiply by 12 to make sure the division is exact. */
- int frame_rate12 = 12*st->Fs/frame_size;
+ /* Multiply by 3 to make sure the division is exact. */
+ int frame_rate3 = 3*st->Fs/frame_size;
/* We need to make sure that "int" values always fit in 16 bits. */
- cbrBytes = IMIN( (12*st->bitrate_bps/8 + frame_rate12/2)/frame_rate12, max_data_bytes);
- st->bitrate_bps = cbrBytes*(opus_int32)frame_rate12*8/12;
- /* Make sure we provide at least one byte to avoid failing. */
- max_data_bytes = IMAX(1, cbrBytes);
+ cbrBytes = IMIN( (3*st->bitrate_bps/8 + frame_rate3/2)/frame_rate3, max_data_bytes);
+ st->bitrate_bps = cbrBytes*(opus_int32)frame_rate3*8/3;
+ max_data_bytes = cbrBytes;
}
if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8
|| (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400)))
@@ -1226,63 +1065,25 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
/*If the space is too low to do something useful, emit 'PLC' frames.*/
int tocmode = st->mode;
int bw = st->bandwidth == 0 ? OPUS_BANDWIDTH_NARROWBAND : st->bandwidth;
- int packet_code = 0;
- int num_multiframes = 0;
-
if (tocmode==0)
tocmode = MODE_SILK_ONLY;
if (frame_rate>100)
tocmode = MODE_CELT_ONLY;
- /* 40 ms -> 2 x 20 ms if in CELT_ONLY or HYBRID mode */
- if (frame_rate==25 && tocmode!=MODE_SILK_ONLY)
- {
- frame_rate = 50;
- packet_code = 1;
- }
-
- /* >= 60 ms frames */
- if (frame_rate<=16)
- {
- /* 1 x 60 ms, 2 x 40 ms, 2 x 60 ms */
- if (out_data_bytes==1 || (tocmode==MODE_SILK_ONLY && frame_rate!=10))
- {
- tocmode = MODE_SILK_ONLY;
-
- packet_code = frame_rate <= 12;
- frame_rate = frame_rate == 12 ? 25 : 16;
- }
- else
- {
- num_multiframes = 50/frame_rate;
- frame_rate = 50;
- packet_code = 3;
- }
- }
-
+ if (frame_rate < 50)
+ tocmode = MODE_SILK_ONLY;
if(tocmode==MODE_SILK_ONLY&&bw>OPUS_BANDWIDTH_WIDEBAND)
bw=OPUS_BANDWIDTH_WIDEBAND;
else if (tocmode==MODE_CELT_ONLY&&bw==OPUS_BANDWIDTH_MEDIUMBAND)
bw=OPUS_BANDWIDTH_NARROWBAND;
else if (tocmode==MODE_HYBRID&&bw<=OPUS_BANDWIDTH_SUPERWIDEBAND)
bw=OPUS_BANDWIDTH_SUPERWIDEBAND;
-
data[0] = gen_toc(tocmode, frame_rate, bw, st->stream_channels);
- data[0] |= packet_code;
-
- ret = packet_code <= 1 ? 1 : 2;
-
- max_data_bytes = IMAX(max_data_bytes, ret);
-
- if (packet_code==3)
- data[1] = num_multiframes;
-
+ ret = 1;
if (!st->use_vbr)
{
ret = opus_packet_pad(data, ret, max_data_bytes);
if (ret == OPUS_OK)
ret = max_data_bytes;
- else
- ret = OPUS_INTERNAL_ERROR;
}
RESTORE_STACK;
return ret;
@@ -1290,8 +1091,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
max_rate = frame_rate*max_data_bytes*8;
/* Equivalent 20-ms rate for mode/channel/bandwidth decisions */
- equiv_rate = compute_equiv_rate(st->bitrate_bps, st->channels, st->Fs/frame_size,
- st->use_vbr, 0, st->silk_mode.complexity, st->silk_mode.packetLossPercentage);
+ equiv_rate = st->bitrate_bps - (40*st->channels+20)*(st->Fs/frame_size - 50);
if (st->signal_type == OPUS_SIGNAL_VOICE)
voice_est = 127;
@@ -1332,17 +1132,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
}
#endif
}
- /* Update equivalent rate for channels decision. */
- equiv_rate = compute_equiv_rate(st->bitrate_bps, st->stream_channels, st->Fs/frame_size,
- st->use_vbr, 0, st->silk_mode.complexity, st->silk_mode.packetLossPercentage);
-
- /* Allow SILK DTX if DTX is enabled but the generalized DTX cannot be used,
- e.g. because of the complexity setting or sample rate. */
-#ifndef DISABLE_FLOAT_API
- st->silk_mode.useDTX = st->use_dtx && !(analysis_info.valid || is_silence);
-#else
- st->silk_mode.useDTX = st->use_dtx;
-#endif
+ equiv_rate = st->bitrate_bps - (40*st->stream_channels+20)*(st->Fs/frame_size - 50);
/* Mode selection depending on application and signal type */
if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
@@ -1391,15 +1181,10 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
/* When FEC is enabled and there's enough packet loss, use SILK */
if (st->silk_mode.useInBandFEC && st->silk_mode.packetLossPercentage > (128-voice_est)>>4)
st->mode = MODE_SILK_ONLY;
- /* When encoding voice and DTX is enabled but the generalized DTX cannot be used,
- use SILK in order to make use of its DTX. */
+ /* When encoding voice and DTX is enabled, set the encoder to SILK mode (at least for now) */
if (st->silk_mode.useDTX && voice_est > 100)
st->mode = MODE_SILK_ONLY;
#endif
-
- /* If max_data_bytes represents less than 6 kb/s, switch to CELT-only mode */
- if (max_data_bytes < (frame_rate > 50 ? 9000 : 6000)*frame_size / (st->Fs * 8))
- st->mode = MODE_CELT_ONLY;
} else {
st->mode = st->user_forced_mode;
}
@@ -1409,6 +1194,19 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
st->mode = MODE_CELT_ONLY;
if (st->lfe)
st->mode = MODE_CELT_ONLY;
+ /* If max_data_bytes represents less than 8 kb/s, switch to CELT-only mode */
+ if (max_data_bytes < (frame_rate > 50 ? 12000 : 8000)*frame_size / (st->Fs * 8))
+ st->mode = MODE_CELT_ONLY;
+
+ if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0
+ && st->mode != MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)
+ {
+ /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */
+ st->silk_mode.toMono = 1;
+ st->stream_channels = 2;
+ } else {
+ st->silk_mode.toMono = 0;
+ }
if (st->prev_mode > 0 &&
((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) ||
@@ -1428,22 +1226,23 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
}
}
}
-
- /* When encoding multiframes, we can ask for a switch to CELT only in the last frame. This switch
- * is processed above as the requested mode shouldn't interrupt stereo->mono transition. */
- if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0
- && st->mode != MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)
+ /* For the first frame at a new SILK bandwidth */
+ if (st->silk_bw_switch)
{
- /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */
- st->silk_mode.toMono = 1;
- st->stream_channels = 2;
- } else {
- st->silk_mode.toMono = 0;
+ redundancy = 1;
+ celt_to_silk = 1;
+ st->silk_bw_switch = 0;
+ prefill=1;
}
- /* Update equivalent rate with mode decision. */
- equiv_rate = compute_equiv_rate(st->bitrate_bps, st->stream_channels, st->Fs/frame_size,
- st->use_vbr, st->mode, st->silk_mode.complexity, st->silk_mode.packetLossPercentage);
+ if (redundancy)
+ {
+ /* Fair share of the max size allowed */
+ redundancy_bytes = IMIN(257, max_data_bytes*(opus_int32)(st->Fs/200)/(frame_size+st->Fs/200));
+ /* For VBR, target the actual bitrate (subject to the limit above) */
+ if (st->use_vbr)
+ redundancy_bytes = IMIN(redundancy_bytes, st->bitrate_bps/1600);
+ }
if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY)
{
@@ -1458,7 +1257,17 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
const opus_int32 *voice_bandwidth_thresholds, *music_bandwidth_thresholds;
opus_int32 bandwidth_thresholds[8];
int bandwidth = OPUS_BANDWIDTH_FULLBAND;
+ opus_int32 equiv_rate2;
+ equiv_rate2 = equiv_rate;
+ if (st->mode != MODE_CELT_ONLY)
+ {
+ /* Adjust the threshold +/- 10% depending on complexity */
+ equiv_rate2 = equiv_rate2 * (45+st->silk_mode.complexity)/50;
+ /* CBR is less efficient by ~1 kb/s */
+ if (!st->use_vbr)
+ equiv_rate2 -= 1000;
+ }
if (st->channels==2 && st->force_channels!=1)
{
voice_bandwidth_thresholds = stereo_voice_bandwidth_thresholds;
@@ -1479,19 +1288,15 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
hysteresis = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)+1];
if (!st->first)
{
- if (st->auto_bandwidth >= bandwidth)
+ if (st->bandwidth >= bandwidth)
threshold -= hysteresis;
else
threshold += hysteresis;
}
- if (equiv_rate >= threshold)
+ if (equiv_rate2 >= threshold)
break;
} while (--bandwidth>OPUS_BANDWIDTH_NARROWBAND);
- /* We don't use mediumband anymore, except when explicitly requested or during
- mode transitions. */
- if (bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
- bandwidth = OPUS_BANDWIDTH_WIDEBAND;
- st->bandwidth = st->auto_bandwidth = bandwidth;
+ st->bandwidth = bandwidth;
/* Prevents any transition to SWB/FB until the SILK layer has fully
switched to WB mode and turned the variable LP filter off */
if (!st->first && st->mode != MODE_CELT_ONLY && !st->silk_mode.inWBmodeWithoutVariableLP && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)
@@ -1544,8 +1349,6 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
st->bandwidth = IMIN(st->bandwidth, st->detected_bandwidth);
}
#endif
- st->silk_mode.LBRR_coded = decide_fec(st->silk_mode.useInBandFEC, st->silk_mode.packetLossPercentage,
- st->silk_mode.LBRR_coded, st->mode, &st->bandwidth, equiv_rate);
celt_encoder_ctl(celt_enc, OPUS_SET_LSB_DEPTH(lsb_depth));
/* CELT mode doesn't support mediumband, use wideband instead */
@@ -1554,34 +1357,15 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
if (st->lfe)
st->bandwidth = OPUS_BANDWIDTH_NARROWBAND;
- curr_bandwidth = st->bandwidth;
-
- /* Chooses the appropriate mode for speech
- *NEVER* switch to/from CELT-only mode here as this will invalidate some assumptions */
- if (st->mode == MODE_SILK_ONLY && curr_bandwidth > OPUS_BANDWIDTH_WIDEBAND)
- st->mode = MODE_HYBRID;
- if (st->mode == MODE_HYBRID && curr_bandwidth <= OPUS_BANDWIDTH_WIDEBAND)
- st->mode = MODE_SILK_ONLY;
-
- /* Can't support higher than >60 ms frames, and >20 ms when in Hybrid or CELT-only modes */
- if ((frame_size > st->Fs/50 && (st->mode != MODE_SILK_ONLY)) || frame_size > 3*st->Fs/50)
+ /* Can't support higher than wideband for >20 ms frames */
+ if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND))
{
- int enc_frame_size;
+ VARDECL(unsigned char, tmp_data);
int nb_frames;
-
- if (st->mode == MODE_SILK_ONLY)
- {
- if (frame_size == 2*st->Fs/25) /* 80 ms -> 2x 40 ms */
- enc_frame_size = st->Fs/25;
- else if (frame_size == 3*st->Fs/25) /* 120 ms -> 2x 60 ms */
- enc_frame_size = 3*st->Fs/50;
- else /* 100 ms -> 5x 20 ms */
- enc_frame_size = st->Fs/50;
- }
- else
- enc_frame_size = st->Fs/50;
-
- nb_frames = frame_size/enc_frame_size;
+ int bak_mode, bak_bandwidth, bak_channels, bak_to_mono;
+ VARDECL(OpusRepacketizer, rp);
+ opus_int32 bytes_per_frame;
+ opus_int32 repacketize_len;
#ifndef DISABLE_FLOAT_API
if (analysis_read_pos_bak!= -1)
@@ -1591,34 +1375,74 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
}
#endif
- ret = encode_multiframe_packet(st, pcm, nb_frames, enc_frame_size, data,
- out_data_bytes, to_celt, lsb_depth, float_api);
+ nb_frames = frame_size > st->Fs/25 ? 3 : 2;
+ bytes_per_frame = IMIN(1276,(out_data_bytes-3)/nb_frames);
- RESTORE_STACK;
- return ret;
- }
+ ALLOC(tmp_data, nb_frames*bytes_per_frame, unsigned char);
- /* For the first frame at a new SILK bandwidth */
- if (st->silk_bw_switch)
- {
- redundancy = 1;
- celt_to_silk = 1;
- st->silk_bw_switch = 0;
- /* Do a prefill without reseting the sampling rate control. */
- prefill=2;
- }
+ ALLOC(rp, 1, OpusRepacketizer);
+ opus_repacketizer_init(rp);
- /* If we decided to go with CELT, make sure redundancy is off, no matter what
- we decided earlier. */
- if (st->mode == MODE_CELT_ONLY)
- redundancy = 0;
+ bak_mode = st->user_forced_mode;
+ bak_bandwidth = st->user_bandwidth;
+ bak_channels = st->force_channels;
- if (redundancy)
- {
- redundancy_bytes = compute_redundancy_bytes(max_data_bytes, st->bitrate_bps, frame_rate, st->stream_channels);
- if (redundancy_bytes == 0)
- redundancy = 0;
+ st->user_forced_mode = st->mode;
+ st->user_bandwidth = st->bandwidth;
+ st->force_channels = st->stream_channels;
+ bak_to_mono = st->silk_mode.toMono;
+
+ if (bak_to_mono)
+ st->force_channels = 1;
+ else
+ st->prev_channels = st->stream_channels;
+ for (i=0;i<nb_frames;i++)
+ {
+ int tmp_len;
+ st->silk_mode.toMono = 0;
+ /* When switching from SILK/Hybrid to CELT, only ask for a switch at the last frame */
+ if (to_celt && i==nb_frames-1)
+ st->user_forced_mode = MODE_CELT_ONLY;
+ tmp_len = opus_encode_native(st, pcm+i*(st->channels*st->Fs/50), st->Fs/50,
+ tmp_data+i*bytes_per_frame, bytes_per_frame, lsb_depth,
+ NULL, 0, c1, c2, analysis_channels, downmix, float_api);
+ if (tmp_len<0)
+ {
+ RESTORE_STACK;
+ return OPUS_INTERNAL_ERROR;
+ }
+ ret = opus_repacketizer_cat(rp, tmp_data+i*bytes_per_frame, tmp_len);
+ if (ret<0)
+ {
+ RESTORE_STACK;
+ return OPUS_INTERNAL_ERROR;
+ }
+ }
+ if (st->use_vbr)
+ repacketize_len = out_data_bytes;
+ else
+ repacketize_len = IMIN(3*st->bitrate_bps/(3*8*50/nb_frames), out_data_bytes);
+ ret = opus_repacketizer_out_range_impl(rp, 0, nb_frames, data, repacketize_len, 0, !st->use_vbr);
+ if (ret<0)
+ {
+ RESTORE_STACK;
+ return OPUS_INTERNAL_ERROR;
+ }
+ st->user_forced_mode = bak_mode;
+ st->user_bandwidth = bak_bandwidth;
+ st->force_channels = bak_channels;
+ st->silk_mode.toMono = bak_to_mono;
+ RESTORE_STACK;
+ return ret;
}
+ curr_bandwidth = st->bandwidth;
+
+ /* Chooses the appropriate mode for speech
+ *NEVER* switch to/from CELT-only mode here as this will invalidate some assumptions */
+ if (st->mode == MODE_SILK_ONLY && curr_bandwidth > OPUS_BANDWIDTH_WIDEBAND)
+ st->mode = MODE_HYBRID;
+ if (st->mode == MODE_HYBRID && curr_bandwidth <= OPUS_BANDWIDTH_WIDEBAND)
+ st->mode = MODE_SILK_ONLY;
/* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, curr_bandwidth); */
bytes_target = IMIN(max_data_bytes-redundancy_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1;
@@ -1643,7 +1467,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
if (st->application == OPUS_APPLICATION_VOIP)
{
- hp_cutoff(pcm, cutoff_Hz, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs, st->arch);
+ hp_cutoff(pcm, cutoff_Hz, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs);
} else {
dc_reject(pcm, 3, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs);
}
@@ -1668,7 +1492,6 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
if (st->mode != MODE_CELT_ONLY)
{
opus_int32 total_bitRate, celt_rate;
- opus_int activity;
#ifdef FIXED_POINT
const opus_int16 *pcm_silk;
#else
@@ -1676,26 +1499,30 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
ALLOC(pcm_silk, st->channels*frame_size, opus_int16);
#endif
- activity = VAD_NO_DECISION;
-#ifndef DISABLE_FLOAT_API
- if( analysis_info.valid ) {
- /* Inform SILK about the Opus VAD decision */
- activity = ( analysis_info.activity_probability >= DTX_ACTIVITY_THRESHOLD );
- }
-#endif
-
/* Distribute bits between SILK and CELT */
total_bitRate = 8 * bytes_target * frame_rate;
if( st->mode == MODE_HYBRID ) {
+ int HB_gain_ref;
/* Base rate for SILK */
- st->silk_mode.bitRate = compute_silk_rate_for_hybrid(total_bitRate,
- curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded,
- st->stream_channels);
+ st->silk_mode.bitRate = st->stream_channels * ( 5000 + 1000 * ( st->Fs == 100 * frame_size ) );
+ if( curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND ) {
+ /* SILK gets 2/3 of the remaining bits */
+ st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 2 / 3;
+ } else { /* FULLBAND */
+ /* SILK gets 3/5 of the remaining bits */
+ st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 3 / 5;
+ }
+ /* Don't let SILK use more than 80% */
+ if( st->silk_mode.bitRate > total_bitRate * 4/5 ) {
+ st->silk_mode.bitRate = total_bitRate * 4/5;
+ }
if (!st->energy_masking)
{
/* Increasingly attenuate high band when it gets allocated fewer bits */
celt_rate = total_bitRate - st->silk_mode.bitRate;
- HB_gain = Q15ONE - SHR32(celt_exp2(-celt_rate * QCONST16(1.f/1024, 10)), 1);
+ HB_gain_ref = (curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND) ? 3000 : 3600;
+ HB_gain = SHL32((opus_val32)celt_rate, 9) / SHR32((opus_val32)celt_rate + st->stream_channels * HB_gain_ref, 6);
+ HB_gain = HB_gain < (opus_val32)Q15ONE*6/7 ? HB_gain + Q15ONE/7 : Q15ONE;
}
} else {
/* SILK gets all bits */
@@ -1742,6 +1569,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
st->silk_mode.bitRate += 3*rate_offset/5;
else
st->silk_mode.bitRate += rate_offset;
+ bytes_target += rate_offset * frame_size / (8 * st->Fs);
}
st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
@@ -1752,7 +1580,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
} else if (curr_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) {
st->silk_mode.desiredInternalSampleRate = 12000;
} else {
- celt_assert( st->mode == MODE_HYBRID || curr_bandwidth == OPUS_BANDWIDTH_WIDEBAND );
+ silk_assert( st->mode == MODE_HYBRID || curr_bandwidth == OPUS_BANDWIDTH_WIDEBAND );
st->silk_mode.desiredInternalSampleRate = 16000;
}
if( st->mode == MODE_HYBRID ) {
@@ -1762,53 +1590,40 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
st->silk_mode.minInternalSampleRate = 8000;
}
- st->silk_mode.maxInternalSampleRate = 16000;
if (st->mode == MODE_SILK_ONLY)
{
opus_int32 effective_max_rate = max_rate;
+ st->silk_mode.maxInternalSampleRate = 16000;
if (frame_rate > 50)
effective_max_rate = effective_max_rate*2/3;
- if (effective_max_rate < 8000)
+ if (effective_max_rate < 13000)
{
st->silk_mode.maxInternalSampleRate = 12000;
st->silk_mode.desiredInternalSampleRate = IMIN(12000, st->silk_mode.desiredInternalSampleRate);
}
- if (effective_max_rate < 7000)
+ if (effective_max_rate < 9600)
{
st->silk_mode.maxInternalSampleRate = 8000;
st->silk_mode.desiredInternalSampleRate = IMIN(8000, st->silk_mode.desiredInternalSampleRate);
}
+ } else {
+ st->silk_mode.maxInternalSampleRate = 16000;
}
st->silk_mode.useCBR = !st->use_vbr;
/* Call SILK encoder for the low band */
+ nBytes = IMIN(1275, max_data_bytes-1-redundancy_bytes);
- /* Max bits for SILK, counting ToC, redundancy bytes, and optionally redundancy. */
- st->silk_mode.maxBits = (max_data_bytes-1)*8;
- if (redundancy && redundancy_bytes >= 2)
- {
- /* Counting 1 bit for redundancy position and 20 bits for flag+size (only for hybrid). */
- st->silk_mode.maxBits -= redundancy_bytes*8 + 1;
- if (st->mode == MODE_HYBRID)
- st->silk_mode.maxBits -= 20;
- }
+ st->silk_mode.maxBits = nBytes*8;
+ /* Only allow up to 90% of the bits for hybrid mode*/
+ if (st->mode == MODE_HYBRID)
+ st->silk_mode.maxBits = (opus_int32)st->silk_mode.maxBits*9/10;
if (st->silk_mode.useCBR)
{
- if (st->mode == MODE_HYBRID)
- {
- st->silk_mode.maxBits = IMIN(st->silk_mode.maxBits, st->silk_mode.bitRate * frame_size / st->Fs);
- }
- } else {
- /* Constrained VBR. */
- if (st->mode == MODE_HYBRID)
- {
- /* Compute SILK bitrate corresponding to the max total bits available */
- opus_int32 maxBitRate = compute_silk_rate_for_hybrid(st->silk_mode.maxBits*st->Fs / frame_size,
- curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded,
- st->stream_channels);
- st->silk_mode.maxBits = maxBitRate * frame_size / st->Fs;
- }
+ st->silk_mode.maxBits = (st->silk_mode.bitRate * frame_size / (st->Fs * 8))*8;
+ /* Reduce the initial target to make it easier to reach the CBR rate */
+ st->silk_mode.bitRate = IMAX(1, st->silk_mode.bitRate-2000);
}
if (prefill)
@@ -1831,9 +1646,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
for (i=0;i<st->encoder_buffer*st->channels;i++)
pcm_silk[i] = FLOAT2INT16(st->delay_buffer[i]);
#endif
- silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, prefill, activity );
- /* Prevent a second switch in the real encode call. */
- st->silk_mode.opusCanSwitch = 0;
+ silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, 1 );
}
#ifdef FIXED_POINT
@@ -1842,14 +1655,20 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
for (i=0;i<frame_size*st->channels;i++)
pcm_silk[i] = FLOAT2INT16(pcm_buf[total_buffer*st->channels + i]);
#endif
- ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0, activity );
+ ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0 );
if( ret ) {
/*fprintf (stderr, "SILK encode error: %d\n", ret);*/
/* Handle error */
RESTORE_STACK;
return OPUS_INTERNAL_ERROR;
}
-
+ if (nBytes==0)
+ {
+ st->rangeFinal = 0;
+ data[-1] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels);
+ RESTORE_STACK;
+ return 1;
+ }
/* Extract SILK internal bandwidth for signaling in first byte */
if( st->mode == MODE_SILK_ONLY ) {
if( st->silk_mode.internalSampleRate == 8000 ) {
@@ -1860,24 +1679,14 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
curr_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
}
} else {
- celt_assert( st->silk_mode.internalSampleRate == 16000 );
- }
-
- st->silk_mode.opusCanSwitch = st->silk_mode.switchReady && !st->nonfinal_frame;
-
- if (nBytes==0)
- {
- st->rangeFinal = 0;
- data[-1] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels);
- RESTORE_STACK;
- return 1;
+ silk_assert( st->silk_mode.internalSampleRate == 16000 );
}
+ st->silk_mode.opusCanSwitch = st->silk_mode.switchReady;
/* FIXME: How do we allocate the redundancy for CBR? */
if (st->silk_mode.opusCanSwitch)
{
- redundancy_bytes = compute_redundancy_bytes(max_data_bytes, st->bitrate_bps, frame_rate, st->stream_channels);
- redundancy = (redundancy_bytes != 0);
+ redundancy = 1;
celt_to_silk = 0;
st->silk_bw_switch = 1;
}
@@ -1918,18 +1727,40 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
if (st->mode == MODE_HYBRID)
{
+ int len;
+
+ len = (ec_tell(&enc)+7)>>3;
+ if (redundancy)
+ len += st->mode == MODE_HYBRID ? 3 : 1;
if( st->use_vbr ) {
- celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps-st->silk_mode.bitRate));
- celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(0));
+ nb_compr_bytes = len + bytes_target - (st->silk_mode.bitRate * frame_size) / (8 * st->Fs);
+ } else {
+ /* check if SILK used up too much */
+ nb_compr_bytes = len > bytes_target ? len : bytes_target;
}
} else {
if (st->use_vbr)
{
+ opus_int32 bonus=0;
+#ifndef DISABLE_FLOAT_API
+ if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != st->Fs/50)
+ {
+ bonus = (60*st->stream_channels+40)*(st->Fs/frame_size-50);
+ if (analysis_info.valid)
+ bonus = (opus_int32)(bonus*(1.f+.5f*analysis_info.tonality));
+ }
+#endif
celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1));
celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint));
- celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps));
+ celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps+bonus));
+ nb_compr_bytes = max_data_bytes-1-redundancy_bytes;
+ } else {
+ nb_compr_bytes = bytes_target;
}
}
+
+ } else {
+ nb_compr_bytes = 0;
}
ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_val16);
@@ -1955,14 +1786,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
}
st->prev_HB_gain = HB_gain;
if (st->mode != MODE_HYBRID || st->stream_channels==1)
- {
- if (equiv_rate > 32000)
- st->silk_mode.stereoWidth_Q14 = 16384;
- else if (equiv_rate < 16000)
- st->silk_mode.stereoWidth_Q14 = 0;
- else
- st->silk_mode.stereoWidth_Q14 = 16384 - 2048*(opus_int32)(32000-equiv_rate)/(equiv_rate-14000);
- }
+ st->silk_mode.stereoWidth_Q14 = IMIN((1<<14),2*IMAX(0,equiv_rate-30000));
if( !st->energy_masking && st->channels == 2 ) {
/* Apply stereo width reduction (at low bitrates) */
if( st->hybrid_stereo_width_Q14 < (1 << 14) || st->silk_mode.stereoWidth_Q14 < (1 << 14) ) {
@@ -1985,23 +1809,19 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
if ( st->mode != MODE_CELT_ONLY && ec_tell(&enc)+17+20*(st->mode == MODE_HYBRID) <= 8*(max_data_bytes-1))
{
/* For SILK mode, the redundancy is inferred from the length */
- if (st->mode == MODE_HYBRID)
+ if (st->mode == MODE_HYBRID && (redundancy || ec_tell(&enc)+37 <= 8*nb_compr_bytes))
ec_enc_bit_logp(&enc, redundancy, 12);
if (redundancy)
{
int max_redundancy;
ec_enc_bit_logp(&enc, celt_to_silk, 1);
if (st->mode == MODE_HYBRID)
- {
- /* Reserve the 8 bits needed for the redundancy length,
- and at least a few bits for CELT if possible */
- max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+8+3+7)>>3);
- }
+ max_redundancy = (max_data_bytes-1)-nb_compr_bytes;
else
max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+7)>>3);
/* Target the same bit-rate for redundancy as for the rest,
up to a max of 257 bytes */
- redundancy_bytes = IMIN(max_redundancy, redundancy_bytes);
+ redundancy_bytes = IMIN(max_redundancy, st->bitrate_bps/1600);
redundancy_bytes = IMIN(257, IMAX(2, redundancy_bytes));
if (st->mode == MODE_HYBRID)
ec_enc_uint(&enc, redundancy_bytes-2, 256);
@@ -2023,7 +1843,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
ec_enc_done(&enc);
nb_compr_bytes = ret;
} else {
- nb_compr_bytes = (max_data_bytes-1)-redundancy_bytes;
+ nb_compr_bytes = IMIN((max_data_bytes-1)-redundancy_bytes, nb_compr_bytes);
ec_enc_shrink(&enc, nb_compr_bytes);
}
@@ -2031,12 +1851,6 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
if (redundancy || st->mode != MODE_SILK_ONLY)
celt_encoder_ctl(celt_enc, CELT_SET_ANALYSIS(&analysis_info));
#endif
- if (st->mode == MODE_HYBRID) {
- SILKInfo info;
- info.signalType = st->silk_mode.signalType;
- info.offset = st->silk_mode.offset;
- celt_encoder_ctl(celt_enc, CELT_SET_SILK_INFO(&info));
- }
/* 5 ms redundant frame for CELT->SILK */
if (redundancy && celt_to_silk)
@@ -2044,7 +1858,6 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
int err;
celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
- celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX));
err = celt_encode_with_ec(celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes, NULL);
if (err < 0)
{
@@ -2068,25 +1881,15 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
celt_encode_with_ec(celt_enc, tmp_prefill, st->Fs/400, dummy, 2, NULL);
celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
}
- /* If false, we already busted the budget and we'll end up with a "PLC frame" */
+ /* If false, we already busted the budget and we'll end up with a "PLC packet" */
if (ec_tell(&enc) <= 8*nb_compr_bytes)
{
- /* Set the bitrate again if it was overridden in the redundancy code above*/
- if (redundancy && celt_to_silk && st->mode==MODE_HYBRID && st->use_vbr)
- celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps-st->silk_mode.bitRate));
- celt_encoder_ctl(celt_enc, OPUS_SET_VBR(st->use_vbr));
ret = celt_encode_with_ec(celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
if (ret < 0)
{
RESTORE_STACK;
return OPUS_INTERNAL_ERROR;
}
- /* Put CELT->SILK redundancy data in the right place. */
- if (redundancy && celt_to_silk && st->mode==MODE_HYBRID && st->use_vbr)
- {
- OPUS_MOVE(data+ret, data+nb_compr_bytes, redundancy_bytes);
- nb_compr_bytes = nb_compr_bytes+redundancy_bytes;
- }
}
}
@@ -2102,15 +1905,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
- celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
- celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX));
- if (st->mode == MODE_HYBRID)
- {
- /* Shrink packet to what the encoder actually used. */
- nb_compr_bytes = ret;
- ec_enc_shrink(&enc, nb_compr_bytes);
- }
/* NOTE: We could speed this up slightly (at the expense of code size) by just adding a function that prefills the buffer */
celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, dummy, 2, NULL);
@@ -2140,23 +1935,6 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
st->first = 0;
- /* DTX decision */
-#ifndef DISABLE_FLOAT_API
- if (st->use_dtx && (analysis_info.valid || is_silence))
- {
- if (decide_dtx_mode(analysis_info.activity_probability, &st->nb_no_activity_frames,
- st->peak_signal_energy, pcm, frame_size, st->channels, is_silence, st->arch))
- {
- st->rangeFinal = 0;
- data[0] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels);
- RESTORE_STACK;
- return 1;
- }
- } else {
- st->nb_no_activity_frames = 0;
- }
-#endif
-
/* In the unlikely case that the SILK encoder busted its target, tell
the decoder to call the PLC */
if (ec_tell(&enc) > (max_data_bytes-1)*8)
@@ -2184,6 +1962,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
if (!st->use_vbr)
{
if (opus_packet_pad(data, ret, max_data_bytes) != OPUS_OK)
+
{
RESTORE_STACK;
return OPUS_INTERNAL_ERROR;
@@ -2202,15 +1981,18 @@ opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_fra
{
int i, ret;
int frame_size;
+ int delay_compensation;
VARDECL(opus_int16, in);
ALLOC_STACK;
- frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
- if (frame_size <= 0)
- {
- RESTORE_STACK;
- return OPUS_BAD_ARG;
- }
+ if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ delay_compensation = 0;
+ else
+ delay_compensation = st->delay_compensation;
+ frame_size = compute_frame_size(pcm, analysis_frame_size,
+ st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
+ delay_compensation, downmix_float, st->analysis.subframe_mem);
+
ALLOC(in, frame_size*st->channels, opus_int16);
for (i=0;i<frame_size*st->channels;i++)
@@ -2226,7 +2008,18 @@ opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_fram
unsigned char *data, opus_int32 out_data_bytes)
{
int frame_size;
- frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
+ int delay_compensation;
+ if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ delay_compensation = 0;
+ else
+ delay_compensation = st->delay_compensation;
+ frame_size = compute_frame_size(pcm, analysis_frame_size,
+ st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
+ delay_compensation, downmix_int
+#ifndef DISABLE_FLOAT_API
+ , st->analysis.subframe_mem
+#endif
+ );
return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0);
}
@@ -2237,15 +2030,18 @@ opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_fram
{
int i, ret;
int frame_size;
+ int delay_compensation;
VARDECL(float, in);
ALLOC_STACK;
- frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
- if (frame_size <= 0)
- {
- RESTORE_STACK;
- return OPUS_BAD_ARG;
- }
+ if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ delay_compensation = 0;
+ else
+ delay_compensation = st->delay_compensation;
+ frame_size = compute_frame_size(pcm, analysis_frame_size,
+ st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
+ delay_compensation, downmix_int, st->analysis.subframe_mem);
+
ALLOC(in, frame_size*st->channels, float);
for (i=0;i<frame_size*st->channels;i++)
@@ -2259,7 +2055,14 @@ opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_fra
unsigned char *data, opus_int32 out_data_bytes)
{
int frame_size;
- frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
+ int delay_compensation;
+ if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ delay_compensation = 0;
+ else
+ delay_compensation = st->delay_compensation;
+ frame_size = compute_frame_size(pcm, analysis_frame_size,
+ st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
+ delay_compensation, downmix_float, st->analysis.subframe_mem);
return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1);
}
@@ -2290,9 +2093,6 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
break;
}
st->application = value;
-#ifndef DISABLE_FLOAT_API
- st->analysis.application = value;
-#endif
}
break;
case OPUS_GET_APPLICATION_REQUEST:
@@ -2411,7 +2211,7 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
{
goto bad_arg;
}
- st->use_dtx = value;
+ st->silk_mode.useDTX = value;
}
break;
case OPUS_GET_DTX_REQUEST:
@@ -2421,7 +2221,7 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
{
goto bad_arg;
}
- *value = st->use_dtx;
+ *value = st->silk_mode.useDTX;
}
break;
case OPUS_SET_COMPLEXITY_REQUEST:
@@ -2622,15 +2422,15 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
- if (value != OPUS_FRAMESIZE_ARG && value != OPUS_FRAMESIZE_2_5_MS &&
- value != OPUS_FRAMESIZE_5_MS && value != OPUS_FRAMESIZE_10_MS &&
- value != OPUS_FRAMESIZE_20_MS && value != OPUS_FRAMESIZE_40_MS &&
- value != OPUS_FRAMESIZE_60_MS && value != OPUS_FRAMESIZE_80_MS &&
- value != OPUS_FRAMESIZE_100_MS && value != OPUS_FRAMESIZE_120_MS)
+ if (value != OPUS_FRAMESIZE_ARG && value != OPUS_FRAMESIZE_2_5_MS &&
+ value != OPUS_FRAMESIZE_5_MS && value != OPUS_FRAMESIZE_10_MS &&
+ value != OPUS_FRAMESIZE_20_MS && value != OPUS_FRAMESIZE_40_MS &&
+ value != OPUS_FRAMESIZE_60_MS && value != OPUS_FRAMESIZE_VARIABLE)
{
goto bad_arg;
}
st->variable_duration = value;
+ celt_encoder_ctl(celt_enc, OPUS_SET_EXPERT_FRAME_DURATION(value));
}
break;
case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
@@ -2659,26 +2459,6 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
*value = st->silk_mode.reducedDependency;
}
break;
- case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
- {
- opus_int32 value = va_arg(ap, opus_int32);
- if(value<0 || value>1)
- {
- goto bad_arg;
- }
- celt_encoder_ctl(celt_enc, OPUS_SET_PHASE_INVERSION_DISABLED(value));
- }
- break;
- case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
- {
- opus_int32 *value = va_arg(ap, opus_int32*);
- if (!value)
- {
- goto bad_arg;
- }
- celt_encoder_ctl(celt_enc, OPUS_GET_PHASE_INVERSION_DISABLED(value));
- }
- break;
case OPUS_RESET_STATE:
{
void *silk_enc;
@@ -2727,33 +2507,6 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value));
}
break;
- case OPUS_GET_IN_DTX_REQUEST:
- {
- opus_int32 *value = va_arg(ap, opus_int32*);
- if (!value)
- {
- goto bad_arg;
- }
- if (st->silk_mode.useDTX && (st->prev_mode == MODE_SILK_ONLY || st->prev_mode == MODE_HYBRID)) {
- /* DTX determined by Silk. */
- int n;
- void *silk_enc = (char*)st+st->silk_enc_offset;
- *value = 1;
- for (n=0;n<st->silk_mode.nChannelsInternal;n++) {
- *value = *value && ((silk_encoder*)silk_enc)->state_Fxx[n].sCmn.noSpeechCounter >= NB_SPEECH_FRAMES_BEFORE_DTX;
- }
- }
-#ifndef DISABLE_FLOAT_API
- else if (st->use_dtx) {
- /* DTX determined by Opus. */
- *value = st->nb_no_activity_frames >= NB_SPEECH_FRAMES_BEFORE_DTX;
- }
-#endif
- else {
- *value = 0;
- }
- }
- break;
case CELT_GET_MODE_REQUEST:
{
diff --git a/thirdparty/opus/opus_multistream_decoder.c b/thirdparty/opus/opus_multistream_decoder.c
index 0018517aeb..b95eaa6eac 100644
--- a/thirdparty/opus/opus_multistream_decoder.c
+++ b/thirdparty/opus/opus_multistream_decoder.c
@@ -37,19 +37,16 @@
#include "float_cast.h"
#include "os_support.h"
-/* DECODER */
+struct OpusMSDecoder {
+ ChannelLayout layout;
+ /* Decoder states go here */
+};
-#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
-static void validate_ms_decoder(OpusMSDecoder *st)
-{
- validate_layout(&st->layout);
-}
-#define VALIDATE_MS_DECODER(st) validate_ms_decoder(st)
-#else
-#define VALIDATE_MS_DECODER(st)
-#endif
+
+/* DECODER */
+
opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
{
int coupled_size;
@@ -146,6 +143,15 @@ OpusMSDecoder *opus_multistream_decoder_create(
return st;
}
+typedef void (*opus_copy_channel_out_func)(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_val16 *src,
+ int src_stride,
+ int frame_size
+);
+
static int opus_multistream_packet_validate(const unsigned char *data,
opus_int32 len, int nb_streams, opus_int32 Fs)
{
@@ -175,7 +181,7 @@ static int opus_multistream_packet_validate(const unsigned char *data,
return samples;
}
-int opus_multistream_decode_native(
+static int opus_multistream_decode_native(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
@@ -183,8 +189,7 @@ int opus_multistream_decode_native(
opus_copy_channel_out_func copy_channel_out,
int frame_size,
int decode_fec,
- int soft_clip,
- void *user_data
+ int soft_clip
)
{
opus_int32 Fs;
@@ -196,14 +201,8 @@ int opus_multistream_decode_native(
VARDECL(opus_val16, buf);
ALLOC_STACK;
- VALIDATE_MS_DECODER(st);
- if (frame_size <= 0)
- {
- RESTORE_STACK;
- return OPUS_BAD_ARG;
- }
/* Limit frame_size to avoid excessive stack allocations. */
- MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)));
+ opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
frame_size = IMIN(frame_size, Fs/25*3);
ALLOC(buf, 2*frame_size, opus_val16);
ptr = (char*)st + align(sizeof(OpusMSDecoder));
@@ -238,8 +237,7 @@ int opus_multistream_decode_native(
for (s=0;s<st->layout.nb_streams;s++)
{
OpusDecoder *dec;
- opus_int32 packet_offset;
- int ret;
+ int packet_offset, ret;
dec = (OpusDecoder*)ptr;
ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
@@ -267,7 +265,7 @@ int opus_multistream_decode_native(
while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
- buf, 2, frame_size, user_data);
+ buf, 2, frame_size);
prev = chan;
}
prev = -1;
@@ -275,7 +273,7 @@ int opus_multistream_decode_native(
while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
- buf+1, 2, frame_size, user_data);
+ buf+1, 2, frame_size);
prev = chan;
}
} else {
@@ -285,7 +283,7 @@ int opus_multistream_decode_native(
while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
- buf, 1, frame_size, user_data);
+ buf, 1, frame_size);
prev = chan;
}
}
@@ -296,7 +294,7 @@ int opus_multistream_decode_native(
if (st->layout.mapping[c] == 255)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, c,
- NULL, 0, frame_size, user_data);
+ NULL, 0, frame_size);
}
}
RESTORE_STACK;
@@ -310,13 +308,11 @@ static void opus_copy_channel_out_float(
int dst_channel,
const opus_val16 *src,
int src_stride,
- int frame_size,
- void *user_data
+ int frame_size
)
{
float *float_dst;
opus_int32 i;
- (void)user_data;
float_dst = (float*)dst;
if (src != NULL)
{
@@ -341,13 +337,11 @@ static void opus_copy_channel_out_short(
int dst_channel,
const opus_val16 *src,
int src_stride,
- int frame_size,
- void *user_data
+ int frame_size
)
{
opus_int16 *short_dst;
opus_int32 i;
- (void)user_data;
short_dst = (opus_int16*)dst;
if (src != NULL)
{
@@ -378,7 +372,7 @@ int opus_multistream_decode(
)
{
return opus_multistream_decode_native(st, data, len,
- pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0, NULL);
+ pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0);
}
#ifndef DISABLE_FLOAT_API
@@ -386,7 +380,7 @@ int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
return opus_multistream_decode_native(st, data, len,
- pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
+ pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
}
#endif
@@ -396,30 +390,32 @@ int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
{
return opus_multistream_decode_native(st, data, len,
- pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1, NULL);
+ pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1);
}
int opus_multistream_decode_float(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
- opus_val16 *pcm,
+ float *pcm,
int frame_size,
int decode_fec
)
{
return opus_multistream_decode_native(st, data, len,
- pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
+ pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
}
#endif
-int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
- va_list ap)
+int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
{
+ va_list ap;
int coupled_size, mono_size;
char *ptr;
int ret = OPUS_OK;
+ va_start(ap, request);
+
coupled_size = opus_decoder_get_size(2);
mono_size = opus_decoder_get_size(1);
ptr = (char*)st + align(sizeof(OpusMSDecoder));
@@ -429,7 +425,6 @@ int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
case OPUS_GET_SAMPLE_RATE_REQUEST:
case OPUS_GET_GAIN_REQUEST:
case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
- case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
{
OpusDecoder *dec;
/* For int32* GET params, just query the first stream */
@@ -487,7 +482,7 @@ int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
OpusDecoder **value;
stream_id = va_arg(ap, opus_int32);
if (stream_id<0 || stream_id >= st->layout.nb_streams)
- goto bad_arg;
+ ret = OPUS_BAD_ARG;
value = va_arg(ap, OpusDecoder**);
if (!value)
{
@@ -504,7 +499,6 @@ int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
}
break;
case OPUS_SET_GAIN_REQUEST:
- case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
{
int s;
/* This works for int32 params */
@@ -528,20 +522,14 @@ int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
ret = OPUS_UNIMPLEMENTED;
break;
}
+
+ va_end(ap);
return ret;
bad_arg:
+ va_end(ap);
return OPUS_BAD_ARG;
}
-int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
-{
- int ret;
- va_list ap;
- va_start(ap, request);
- ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
- va_end(ap);
- return ret;
-}
void opus_multistream_decoder_destroy(OpusMSDecoder *st)
{
diff --git a/thirdparty/opus/opus_multistream_encoder.c b/thirdparty/opus/opus_multistream_encoder.c
index 93204a14c1..1698223a16 100644
--- a/thirdparty/opus/opus_multistream_encoder.c
+++ b/thirdparty/opus/opus_multistream_encoder.c
@@ -61,6 +61,38 @@ static const VorbisLayout vorbis_mappings[8] = {
{5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
};
+typedef void (*opus_copy_channel_in_func)(
+ opus_val16 *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size
+);
+
+typedef enum {
+ MAPPING_TYPE_NONE,
+ MAPPING_TYPE_SURROUND
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
+ , /* Do not include comma at end of enumerator list */
+ MAPPING_TYPE_AMBISONICS
+#endif
+} MappingType;
+
+struct OpusMSEncoder {
+ ChannelLayout layout;
+ int arch;
+ int lfe_stream;
+ int application;
+ int variable_duration;
+ MappingType mapping_type;
+ opus_int32 bitrate_bps;
+ float subframe_mem[3];
+ /* Encoder states go here */
+ /* then opus_val32 window_mem[channels*120]; */
+ /* then opus_val32 preemph_mem[channels]; */
+};
+
static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
{
int s;
@@ -101,29 +133,6 @@ static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
return (opus_val32*)(void*)ptr;
}
-static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled_streams)
-{
- int order_plus_one;
- int acn_channels;
- int nondiegetic_channels;
-
- if (nb_channels < 1 || nb_channels > 227)
- return 0;
-
- order_plus_one = isqrt32(nb_channels);
- acn_channels = order_plus_one * order_plus_one;
- nondiegetic_channels = nb_channels - acn_channels;
-
- if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
- return 0;
-
- if (nb_streams)
- *nb_streams = acn_channels + (nondiegetic_channels != 0);
- if (nb_coupled_streams)
- *nb_coupled_streams = nondiegetic_channels != 0;
- return 1;
-}
-
static int validate_encoder_layout(const ChannelLayout *layout)
{
int s;
@@ -231,7 +240,6 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
int pos[8] = {0};
int upsample;
int frame_size;
- int freq_size;
opus_val16 channel_offset;
opus_val32 bandE[21];
opus_val16 maskLogE[3][21];
@@ -242,7 +250,6 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
upsample = resampling_factor(rate);
frame_size = len*upsample;
- freq_size = IMIN(960, frame_size);
/* LM = log2(frame_size / 120) */
for (LM=0;LM<celt_mode->maxLM;LM++)
@@ -251,7 +258,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
ALLOC(in, frame_size+overlap, opus_val32);
ALLOC(x, len, opus_val16);
- ALLOC(freq, freq_size, opus_val32);
+ ALLOC(freq, frame_size, opus_val32);
channel_pos(channels, pos);
@@ -261,11 +268,8 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
for (c=0;c<channels;c++)
{
- int frame;
- int nb_frames = frame_size/freq_size;
- celt_assert(nb_frames*freq_size == frame_size);
OPUS_COPY(in, mem+c*overlap, overlap);
- (*copy_channel_in)(x, 1, pcm, channels, c, len, NULL);
+ (*copy_channel_in)(x, 1, pcm, channels, c, len);
celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
#ifndef FIXED_POINT
{
@@ -280,26 +284,18 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
}
}
#endif
- OPUS_CLEAR(bandE, 21);
- for (frame=0;frame<nb_frames;frame++)
+ clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window,
+ overlap, celt_mode->maxLM-LM, 1, arch);
+ if (upsample != 1)
{
- opus_val32 tmpE[21];
- clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window,
- overlap, celt_mode->maxLM-LM, 1, arch);
- if (upsample != 1)
- {
- int bound = freq_size/upsample;
- for (i=0;i<bound;i++)
- freq[i] *= upsample;
- for (;i<freq_size;i++)
- freq[i] = 0;
- }
-
- compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM, arch);
- /* If we have multiple frames, take the max energy. */
- for (i=0;i<21;i++)
- bandE[i] = MAX32(bandE[i], tmpE[i]);
+ int bound = len;
+ for (i=0;i<bound;i++)
+ freq[i] *= upsample;
+ for (;i<frame_size;i++)
+ freq[i] = 0;
}
+
+ compute_band_energies(celt_mode, freq, bandE, 21, 1, LM);
amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
/* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
for (i=1;i<21;i++)
@@ -412,10 +408,12 @@ opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_
{
nb_streams=channels;
nb_coupled_streams=0;
- } else if (mapping_family==2)
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
+ } else if (mapping_family==254)
{
- if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams))
- return 0;
+ nb_streams=channels;
+ nb_coupled_streams=0;
+#endif
} else
return 0;
size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
@@ -450,6 +448,7 @@ static int opus_multistream_encoder_init_impl(
st->layout.nb_channels = channels;
st->layout.nb_streams = streams;
st->layout.nb_coupled_streams = coupled_streams;
+ st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
if (mapping_type != MAPPING_TYPE_SURROUND)
st->lfe_stream = -1;
st->bitrate_bps = OPUS_AUTO;
@@ -457,13 +456,7 @@ static int opus_multistream_encoder_init_impl(
st->variable_duration = OPUS_FRAMESIZE_ARG;
for (i=0;i<st->layout.nb_channels;i++)
st->layout.mapping[i] = mapping[i];
- if (!validate_layout(&st->layout))
- return OPUS_BAD_ARG;
- if (mapping_type == MAPPING_TYPE_SURROUND &&
- !validate_encoder_layout(&st->layout))
- return OPUS_BAD_ARG;
- if (mapping_type == MAPPING_TYPE_AMBISONICS &&
- !validate_ambisonics(st->layout.nb_channels, NULL, NULL))
+ if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
return OPUS_BAD_ARG;
ptr = (char*)st + align(sizeof(OpusMSEncoder));
coupled_size = opus_encoder_get_size(2);
@@ -556,23 +549,25 @@ int opus_multistream_surround_encoder_init(
*coupled_streams=0;
for(i=0;i<channels;i++)
mapping[i] = i;
- } else if (mapping_family==2)
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
+ } else if (mapping_family==254)
{
int i;
- if (!validate_ambisonics(channels, streams, coupled_streams))
- return OPUS_BAD_ARG;
- for(i = 0; i < (*streams - *coupled_streams); i++)
- mapping[i] = i + (*coupled_streams * 2);
- for(i = 0; i < *coupled_streams * 2; i++)
- mapping[i + (*streams - *coupled_streams)] = i;
+ *streams=channels;
+ *coupled_streams=0;
+ for(i=0;i<channels;i++)
+ mapping[i] = i;
+#endif
} else
return OPUS_UNIMPLEMENTED;
if (channels>2 && mapping_family==1) {
mapping_type = MAPPING_TYPE_SURROUND;
- } else if (mapping_family==2)
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
+ } else if (mapping_family==254)
{
mapping_type = MAPPING_TYPE_AMBISONICS;
+#endif
} else
{
mapping_type = MAPPING_TYPE_NONE;
@@ -677,62 +672,62 @@ static void surround_rate_allocation(
int lfe_offset;
int coupled_ratio; /* Q8 */
int lfe_ratio; /* Q8 */
- int nb_lfe;
- int nb_uncoupled;
- int nb_coupled;
- int nb_normal;
- opus_int32 channel_offset;
- opus_int32 bitrate;
- int total;
-
- nb_lfe = (st->lfe_stream!=-1);
- nb_coupled = st->layout.nb_coupled_streams;
- nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
- nb_normal = 2*nb_coupled + nb_uncoupled;
-
- /* Give each non-LFE channel enough bits per channel for coding band energy. */
- channel_offset = 40*IMAX(50, Fs/frame_size);
+ if (st->bitrate_bps > st->layout.nb_channels*40000)
+ stream_offset = 20000;
+ else
+ stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
+ stream_offset += 60*(Fs/frame_size-50);
+ /* We start by giving each stream (coupled or uncoupled) the same bitrate.
+ This models the main saving of coupled channels over uncoupled. */
+ /* The LFE stream is an exception to the above and gets fewer bits. */
+ lfe_offset = 3500 + 60*(Fs/frame_size-50);
+ /* Coupled streams get twice the mono rate after the first 20 kb/s. */
+ coupled_ratio = 512;
+ /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
+ lfe_ratio = 32;
+
+ /* Compute bitrate allocation between streams */
if (st->bitrate_bps==OPUS_AUTO)
{
- bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
+ channel_rate = Fs+60*Fs/frame_size;
} else if (st->bitrate_bps==OPUS_BITRATE_MAX)
{
- bitrate = nb_normal*300000 + nb_lfe*128000;
+ channel_rate = 300000;
} else {
- bitrate = st->bitrate_bps;
+ int nb_lfe;
+ int nb_uncoupled;
+ int nb_coupled;
+ int total;
+ nb_lfe = (st->lfe_stream!=-1);
+ nb_coupled = st->layout.nb_coupled_streams;
+ nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
+ total = (nb_uncoupled<<8) /* mono */
+ + coupled_ratio*nb_coupled /* stereo */
+ + nb_lfe*lfe_ratio;
+ channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
}
-
- /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
- total rate for the non-energy part to avoid problems at really low rate. */
- lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
-
- /* We give each stream (coupled or uncoupled) a starting bitrate.
- This models the main saving of coupled channels over uncoupled. */
- stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
- stream_offset = IMAX(0, IMIN(20000, stream_offset));
-
- /* Coupled streams get twice the mono rate after the offset is allocated. */
- coupled_ratio = 512;
- /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
- lfe_ratio = 32;
-
- total = (nb_uncoupled<<8) /* mono */
- + coupled_ratio*nb_coupled /* stereo */
- + nb_lfe*lfe_ratio;
- channel_rate = 256*(opus_int64)(bitrate - lfe_offset*nb_lfe - stream_offset*(nb_coupled+nb_uncoupled) - channel_offset*nb_normal)/total;
+#ifndef FIXED_POINT
+ if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
+ {
+ opus_int32 bonus;
+ bonus = 60*(Fs/frame_size-50);
+ channel_rate += bonus;
+ }
+#endif
for (i=0;i<st->layout.nb_streams;i++)
{
if (i<st->layout.nb_coupled_streams)
- rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
+ rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
else if (i!=st->lfe_stream)
- rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
+ rate[i] = stream_offset+channel_rate;
else
- rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
+ rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
}
}
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
static void ambisonics_rate_allocation(
OpusMSEncoder *st,
opus_int32 *rate,
@@ -741,31 +736,50 @@ static void ambisonics_rate_allocation(
)
{
int i;
- opus_int32 total_rate;
- opus_int32 per_stream_rate;
+ int non_mono_rate;
+ int total_rate;
- const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
+ /* The mono channel gets (rate_ratio_num / rate_ratio_den) times as many bits
+ * as all other channels */
+ const int rate_ratio_num = 4;
+ const int rate_ratio_den = 3;
+ const int num_channels = st->layout.nb_streams;
if (st->bitrate_bps==OPUS_AUTO)
{
- total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
- (Fs+60*Fs/frame_size) + st->layout.nb_streams * (opus_int32)15000;
+ total_rate = num_channels * (20000 + st->layout.nb_streams*(Fs+60*Fs/frame_size));
} else if (st->bitrate_bps==OPUS_BITRATE_MAX)
{
- total_rate = nb_channels * 320000;
- } else
- {
+ total_rate = num_channels * 320000;
+ } else {
total_rate = st->bitrate_bps;
}
- /* Allocate equal number of bits to Ambisonic (uncoupled) and non-diegetic
- * (coupled) streams */
- per_stream_rate = total_rate / st->layout.nb_streams;
- for (i = 0; i < st->layout.nb_streams; i++)
+ /* Let y be the non-mono rate and let p, q be integers such that the mono
+ * channel rate is (p/q) * y.
+ * Also let T be the total bitrate to allocate. Then
+ * (n - 1) y + (p/q) y = T
+ * y = (T q) / (qn - q + p)
+ */
+ non_mono_rate =
+ total_rate * rate_ratio_den
+ / (rate_ratio_den*num_channels + rate_ratio_num - rate_ratio_den);
+
+#ifndef FIXED_POINT
+ if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
{
- rate[i] = per_stream_rate;
+ opus_int32 bonus = 60*(Fs/frame_size-50);
+ non_mono_rate += bonus;
+ }
+#endif
+
+ rate[0] = total_rate - (num_channels - 1) * non_mono_rate;
+ for (i=1;i<st->layout.nb_streams;i++)
+ {
+ rate[i] = non_mono_rate;
}
}
+#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
static opus_int32 rate_allocation(
OpusMSEncoder *st,
@@ -781,9 +795,11 @@ static opus_int32 rate_allocation(
ptr = (char*)st + align(sizeof(OpusMSEncoder));
opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
ambisonics_rate_allocation(st, rate, frame_size, Fs);
} else
+#endif
{
surround_rate_allocation(st, rate, frame_size, Fs);
}
@@ -796,9 +812,9 @@ static opus_int32 rate_allocation(
return rate_sum;
}
-/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
-#define MS_FRAME_TMP (6*1275+12)
-int opus_multistream_encode_native
+/* Max size in case the encoder decides to return three frames */
+#define MS_FRAME_TMP (3*1275+7)
+static int opus_multistream_encode_native
(
OpusMSEncoder *st,
opus_copy_channel_in_func copy_channel_in,
@@ -808,8 +824,7 @@ int opus_multistream_encode_native
opus_int32 max_data_bytes,
int lsb_depth,
downmix_func downmix,
- int float_api,
- void *user_data
+ int float_api
)
{
opus_int32 Fs;
@@ -844,8 +859,32 @@ int opus_multistream_encode_native
opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
- frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
- if (frame_size <= 0)
+ {
+ opus_int32 delay_compensation;
+ int channels;
+
+ channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
+ opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
+ delay_compensation -= Fs/400;
+ frame_size = compute_frame_size(pcm, analysis_frame_size,
+ st->variable_duration, channels, Fs, st->bitrate_bps,
+ delay_compensation, downmix
+#ifndef DISABLE_FLOAT_API
+ , st->subframe_mem
+#endif
+ );
+ }
+
+ if (400*frame_size < Fs)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+ /* Validate frame_size before using it to allocate stack space.
+ This mirrors the checks in opus_encode[_float](). */
+ if (400*frame_size != Fs && 200*frame_size != Fs &&
+ 100*frame_size != Fs && 50*frame_size != Fs &&
+ 25*frame_size != Fs && 50*frame_size != 3*Fs)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
@@ -853,9 +892,6 @@ int opus_multistream_encode_native
/* Smallest packet the encoder can produce. */
smallest_packet = st->layout.nb_streams*2-1;
- /* 100 ms needs an extra byte per stream for the ToC. */
- if (Fs/frame_size == 10)
- smallest_packet += st->layout.nb_streams;
if (max_data_bytes < smallest_packet)
{
RESTORE_STACK;
@@ -916,9 +952,11 @@ int opus_multistream_encode_native
opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
}
}
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
}
+#endif
}
ptr = (char*)st + align(sizeof(OpusMSEncoder));
@@ -941,9 +979,9 @@ int opus_multistream_encode_native
left = get_left_channel(&st->layout, s, -1);
right = get_right_channel(&st->layout, s, -1);
(*copy_channel_in)(buf, 2,
- pcm, st->layout.nb_channels, left, frame_size, user_data);
+ pcm, st->layout.nb_channels, left, frame_size);
(*copy_channel_in)(buf+1, 2,
- pcm, st->layout.nb_channels, right, frame_size, user_data);
+ pcm, st->layout.nb_channels, right, frame_size);
ptr += align(coupled_size);
if (st->mapping_type == MAPPING_TYPE_SURROUND)
{
@@ -959,7 +997,7 @@ int opus_multistream_encode_native
int i;
int chan = get_mono_channel(&st->layout, s, -1);
(*copy_channel_in)(buf, 1,
- pcm, st->layout.nb_channels, chan, frame_size, user_data);
+ pcm, st->layout.nb_channels, chan, frame_size);
ptr += align(mono_size);
if (st->mapping_type == MAPPING_TYPE_SURROUND)
{
@@ -975,9 +1013,6 @@ int opus_multistream_encode_native
curr_max = max_data_bytes - tot_size;
/* Reserve one byte for the last stream and two for the others */
curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
- /* For 100 ms, reserve an extra byte per stream for the ToC */
- if (Fs/frame_size == 10)
- curr_max -= st->layout.nb_streams-s-1;
curr_max = IMIN(curr_max,MS_FRAME_TMP);
/* Repacketizer will add one or two bytes for self-delimited frames */
if (s != st->layout.nb_streams-1) curr_max -= curr_max>253 ? 2 : 1;
@@ -1018,13 +1053,11 @@ static void opus_copy_channel_in_float(
const void *src,
int src_stride,
int src_channel,
- int frame_size,
- void *user_data
+ int frame_size
)
{
const float *float_src;
opus_int32 i;
- (void)user_data;
float_src = (const float *)src;
for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT)
@@ -1041,13 +1074,11 @@ static void opus_copy_channel_in_short(
const void *src,
int src_stride,
int src_channel,
- int frame_size,
- void *user_data
+ int frame_size
)
{
const opus_int16 *short_src;
opus_int32 i;
- (void)user_data;
short_src = (const opus_int16 *)src;
for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT)
@@ -1068,7 +1099,7 @@ int opus_multistream_encode(
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_short,
- pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
+ pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
}
#ifndef DISABLE_FLOAT_API
@@ -1081,7 +1112,7 @@ int opus_multistream_encode_float(
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
- pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL);
+ pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
}
#endif
@@ -1097,7 +1128,7 @@ int opus_multistream_encode_float
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
- pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL);
+ pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
}
int opus_multistream_encode(
@@ -1109,17 +1140,19 @@ int opus_multistream_encode(
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_short,
- pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
+ pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
}
#endif
-int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
- va_list ap)
+int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
{
+ va_list ap;
int coupled_size, mono_size;
char *ptr;
int ret = OPUS_OK;
+ va_start(ap, request);
+
coupled_size = opus_encoder_get_size(2);
mono_size = opus_encoder_get_size(1);
ptr = (char*)st + align(sizeof(OpusMSEncoder));
@@ -1128,11 +1161,9 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
case OPUS_SET_BITRATE_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
- if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
+ if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
{
- if (value <= 0)
- goto bad_arg;
- value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
+ goto bad_arg;
}
st->bitrate_bps = value;
}
@@ -1175,7 +1206,6 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
case OPUS_GET_INBAND_FEC_REQUEST:
case OPUS_GET_FORCE_CHANNELS_REQUEST:
case OPUS_GET_PREDICTION_DISABLED_REQUEST:
- case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
{
OpusEncoder *enc;
/* For int32* GET params, just query the first stream */
@@ -1222,7 +1252,6 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
case OPUS_SET_FORCE_MODE_REQUEST:
case OPUS_SET_FORCE_CHANNELS_REQUEST:
case OPUS_SET_PREDICTION_DISABLED_REQUEST:
- case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
{
int s;
/* This works for int32 params */
@@ -1249,7 +1278,7 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
OpusEncoder **value;
stream_id = va_arg(ap, opus_int32);
if (stream_id<0 || stream_id >= st->layout.nb_streams)
- goto bad_arg;
+ ret = OPUS_BAD_ARG;
value = va_arg(ap, OpusEncoder**);
if (!value)
{
@@ -1284,6 +1313,7 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
case OPUS_RESET_STATE:
{
int s;
+ st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
if (st->mapping_type == MAPPING_TYPE_SURROUND)
{
OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
@@ -1307,19 +1337,12 @@ int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
ret = OPUS_UNIMPLEMENTED;
break;
}
- return ret;
-bad_arg:
- return OPUS_BAD_ARG;
-}
-int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
-{
- int ret;
- va_list ap;
- va_start(ap, request);
- ret = opus_multistream_encoder_ctl_va_list(st, request, ap);
va_end(ap);
return ret;
+bad_arg:
+ va_end(ap);
+ return OPUS_BAD_ARG;
}
void opus_multistream_encoder_destroy(OpusMSEncoder *st)
diff --git a/thirdparty/opus/opus_private.h b/thirdparty/opus/opus_private.h
index 5e2463f546..3b62eed096 100644
--- a/thirdparty/opus/opus_private.h
+++ b/thirdparty/opus/opus_private.h
@@ -33,7 +33,6 @@
#include "opus.h"
#include "celt.h"
-#include <stdarg.h> /* va_list */
#include <stddef.h> /* offsetof */
struct OpusRepacketizer {
@@ -51,59 +50,12 @@ typedef struct ChannelLayout {
unsigned char mapping[256];
} ChannelLayout;
-typedef enum {
- MAPPING_TYPE_NONE,
- MAPPING_TYPE_SURROUND,
- MAPPING_TYPE_AMBISONICS
-} MappingType;
-
-struct OpusMSEncoder {
- ChannelLayout layout;
- int arch;
- int lfe_stream;
- int application;
- int variable_duration;
- MappingType mapping_type;
- opus_int32 bitrate_bps;
- /* Encoder states go here */
- /* then opus_val32 window_mem[channels*120]; */
- /* then opus_val32 preemph_mem[channels]; */
-};
-
-struct OpusMSDecoder {
- ChannelLayout layout;
- /* Decoder states go here */
-};
-
-int opus_multistream_encoder_ctl_va_list(struct OpusMSEncoder *st, int request,
- va_list ap);
-int opus_multistream_decoder_ctl_va_list(struct OpusMSDecoder *st, int request,
- va_list ap);
-
int validate_layout(const ChannelLayout *layout);
int get_left_channel(const ChannelLayout *layout, int stream_id, int prev);
int get_right_channel(const ChannelLayout *layout, int stream_id, int prev);
int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev);
-typedef void (*opus_copy_channel_in_func)(
- opus_val16 *dst,
- int dst_stride,
- const void *src,
- int src_stride,
- int src_channel,
- int frame_size,
- void *user_data
-);
-
-typedef void (*opus_copy_channel_out_func)(
- void *dst,
- int dst_stride,
- int dst_channel,
- const opus_val16 *src,
- int src_stride,
- int frame_size,
- void *user_data
-);
+
#define MODE_SILK_ONLY 1000
#define MODE_HYBRID 1001
@@ -135,12 +87,19 @@ typedef void (*opus_copy_channel_out_func)(
typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
-int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth);
int encode_size(int size, unsigned char *data);
opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs);
+opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size,
+ int variable_duration, int C, opus_int32 Fs, int bitrate_bps,
+ int delay_compensation, downmix_func downmix
+#ifndef DISABLE_FLOAT_API
+ , float *subframe_mem
+#endif
+ );
+
opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
@@ -172,30 +131,4 @@ opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int
int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len);
-int opus_multistream_encode_native
-(
- struct OpusMSEncoder *st,
- opus_copy_channel_in_func copy_channel_in,
- const void *pcm,
- int analysis_frame_size,
- unsigned char *data,
- opus_int32 max_data_bytes,
- int lsb_depth,
- downmix_func downmix,
- int float_api,
- void *user_data
-);
-
-int opus_multistream_decode_native(
- struct OpusMSDecoder *st,
- const unsigned char *data,
- opus_int32 len,
- void *pcm,
- opus_copy_channel_out_func copy_channel_out,
- int frame_size,
- int decode_fec,
- int soft_clip,
- void *user_data
-);
-
#endif /* OPUS_PRIVATE_H */
diff --git a/thirdparty/opus/opus_projection_decoder.c b/thirdparty/opus/opus_projection_decoder.c
deleted file mode 100644
index c2e07d5bcf..0000000000
--- a/thirdparty/opus/opus_projection_decoder.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/* Copyright (c) 2017 Google Inc.
- Written by Andrew Allen */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mathops.h"
-#include "os_support.h"
-#include "opus_private.h"
-#include "opus_defines.h"
-#include "opus_projection.h"
-#include "opus_multistream.h"
-#include "mapping_matrix.h"
-#include "stack_alloc.h"
-
-struct OpusProjectionDecoder
-{
- opus_int32 demixing_matrix_size_in_bytes;
- /* Encoder states go here */
-};
-
-#if !defined(DISABLE_FLOAT_API)
-static void opus_projection_copy_channel_out_float(
- void *dst,
- int dst_stride,
- int dst_channel,
- const opus_val16 *src,
- int src_stride,
- int frame_size,
- void *user_data)
-{
- float *float_dst;
- const MappingMatrix *matrix;
- float_dst = (float *)dst;
- matrix = (const MappingMatrix *)user_data;
-
- if (dst_channel == 0)
- OPUS_CLEAR(float_dst, frame_size * dst_stride);
-
- if (src != NULL)
- mapping_matrix_multiply_channel_out_float(matrix, src, dst_channel,
- src_stride, float_dst, dst_stride, frame_size);
-}
-#endif
-
-static void opus_projection_copy_channel_out_short(
- void *dst,
- int dst_stride,
- int dst_channel,
- const opus_val16 *src,
- int src_stride,
- int frame_size,
- void *user_data)
-{
- opus_int16 *short_dst;
- const MappingMatrix *matrix;
- short_dst = (opus_int16 *)dst;
- matrix = (const MappingMatrix *)user_data;
- if (dst_channel == 0)
- OPUS_CLEAR(short_dst, frame_size * dst_stride);
-
- if (src != NULL)
- mapping_matrix_multiply_channel_out_short(matrix, src, dst_channel,
- src_stride, short_dst, dst_stride, frame_size);
-}
-
-static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st)
-{
- /* void* cast avoids clang -Wcast-align warning */
- return (MappingMatrix*)(void*)((char*)st +
- align(sizeof(OpusProjectionDecoder)));
-}
-
-static OpusMSDecoder *get_multistream_decoder(OpusProjectionDecoder *st)
-{
- /* void* cast avoids clang -Wcast-align warning */
- return (OpusMSDecoder*)(void*)((char*)st +
- align(sizeof(OpusProjectionDecoder) +
- st->demixing_matrix_size_in_bytes));
-}
-
-opus_int32 opus_projection_decoder_get_size(int channels, int streams,
- int coupled_streams)
-{
- opus_int32 matrix_size;
- opus_int32 decoder_size;
-
- matrix_size =
- mapping_matrix_get_size(streams + coupled_streams, channels);
- if (!matrix_size)
- return 0;
-
- decoder_size = opus_multistream_decoder_get_size(streams, coupled_streams);
- if (!decoder_size)
- return 0;
-
- return align(sizeof(OpusProjectionDecoder)) + matrix_size + decoder_size;
-}
-
-int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
- int channels, int streams, int coupled_streams,
- unsigned char *demixing_matrix, opus_int32 demixing_matrix_size)
-{
- int nb_input_streams;
- opus_int32 expected_matrix_size;
- int i, ret;
- unsigned char mapping[255];
- VARDECL(opus_int16, buf);
- ALLOC_STACK;
-
- /* Verify supplied matrix size. */
- nb_input_streams = streams + coupled_streams;
- expected_matrix_size = nb_input_streams * channels * sizeof(opus_int16);
- if (expected_matrix_size != demixing_matrix_size)
- {
- RESTORE_STACK;
- return OPUS_BAD_ARG;
- }
-
- /* Convert demixing matrix input into internal format. */
- ALLOC(buf, nb_input_streams * channels, opus_int16);
- for (i = 0; i < nb_input_streams * channels; i++)
- {
- int s = demixing_matrix[2*i + 1] << 8 | demixing_matrix[2*i];
- s = ((s & 0xFFFF) ^ 0x8000) - 0x8000;
- buf[i] = (opus_int16)s;
- }
-
- /* Assign demixing matrix. */
- st->demixing_matrix_size_in_bytes =
- mapping_matrix_get_size(channels, nb_input_streams);
- if (!st->demixing_matrix_size_in_bytes)
- {
- RESTORE_STACK;
- return OPUS_BAD_ARG;
- }
-
- mapping_matrix_init(get_dec_demixing_matrix(st), channels, nb_input_streams, 0,
- buf, demixing_matrix_size);
-
- /* Set trivial mapping so each input channel pairs with a matrix column. */
- for (i = 0; i < channels; i++)
- mapping[i] = i;
-
- ret = opus_multistream_decoder_init(
- get_multistream_decoder(st), Fs, channels, streams, coupled_streams, mapping);
- RESTORE_STACK;
- return ret;
-}
-
-OpusProjectionDecoder *opus_projection_decoder_create(
- opus_int32 Fs, int channels, int streams, int coupled_streams,
- unsigned char *demixing_matrix, opus_int32 demixing_matrix_size, int *error)
-{
- int size;
- int ret;
- OpusProjectionDecoder *st;
-
- /* Allocate space for the projection decoder. */
- size = opus_projection_decoder_get_size(channels, streams, coupled_streams);
- if (!size) {
- if (error)
- *error = OPUS_ALLOC_FAIL;
- return NULL;
- }
- st = (OpusProjectionDecoder *)opus_alloc(size);
- if (!st)
- {
- if (error)
- *error = OPUS_ALLOC_FAIL;
- return NULL;
- }
-
- /* Initialize projection decoder with provided settings. */
- ret = opus_projection_decoder_init(st, Fs, channels, streams, coupled_streams,
- demixing_matrix, demixing_matrix_size);
- if (ret != OPUS_OK)
- {
- opus_free(st);
- st = NULL;
- }
- if (error)
- *error = ret;
- return st;
-}
-
-#ifdef FIXED_POINT
-int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
- opus_int32 len, opus_int16 *pcm, int frame_size,
- int decode_fec)
-{
- return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
- pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, 0,
- get_dec_demixing_matrix(st));
-}
-#else
-int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
- opus_int32 len, opus_int16 *pcm, int frame_size,
- int decode_fec)
-{
- return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
- pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, 1,
- get_dec_demixing_matrix(st));
-}
-#endif
-
-#ifndef DISABLE_FLOAT_API
-int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data,
- opus_int32 len, float *pcm, int frame_size, int decode_fec)
-{
- return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
- pcm, opus_projection_copy_channel_out_float, frame_size, decode_fec, 0,
- get_dec_demixing_matrix(st));
-}
-#endif
-
-int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...)
-{
- va_list ap;
- int ret = OPUS_OK;
-
- va_start(ap, request);
- ret = opus_multistream_decoder_ctl_va_list(get_multistream_decoder(st),
- request, ap);
- va_end(ap);
- return ret;
-}
-
-void opus_projection_decoder_destroy(OpusProjectionDecoder *st)
-{
- opus_free(st);
-}
-
diff --git a/thirdparty/opus/opus_projection_encoder.c b/thirdparty/opus/opus_projection_encoder.c
deleted file mode 100644
index 06fb2d2526..0000000000
--- a/thirdparty/opus/opus_projection_encoder.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/* Copyright (c) 2017 Google Inc.
- Written by Andrew Allen */
-/*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mathops.h"
-#include "os_support.h"
-#include "opus_private.h"
-#include "opus_defines.h"
-#include "opus_projection.h"
-#include "opus_multistream.h"
-#include "stack_alloc.h"
-#include "mapping_matrix.h"
-
-struct OpusProjectionEncoder
-{
- opus_int32 mixing_matrix_size_in_bytes;
- opus_int32 demixing_matrix_size_in_bytes;
- /* Encoder states go here */
-};
-
-#if !defined(DISABLE_FLOAT_API)
-static void opus_projection_copy_channel_in_float(
- opus_val16 *dst,
- int dst_stride,
- const void *src,
- int src_stride,
- int src_channel,
- int frame_size,
- void *user_data
-)
-{
- mapping_matrix_multiply_channel_in_float((const MappingMatrix*)user_data,
- (const float*)src, src_stride, dst, src_channel, dst_stride, frame_size);
-}
-#endif
-
-static void opus_projection_copy_channel_in_short(
- opus_val16 *dst,
- int dst_stride,
- const void *src,
- int src_stride,
- int src_channel,
- int frame_size,
- void *user_data
-)
-{
- mapping_matrix_multiply_channel_in_short((const MappingMatrix*)user_data,
- (const opus_int16*)src, src_stride, dst, src_channel, dst_stride, frame_size);
-}
-
-static int get_order_plus_one_from_channels(int channels, int *order_plus_one)
-{
- int order_plus_one_;
- int acn_channels;
- int nondiegetic_channels;
-
- /* Allowed numbers of channels:
- * (1 + n)^2 + 2j, for n = 0...14 and j = 0 or 1.
- */
- if (channels < 1 || channels > 227)
- return OPUS_BAD_ARG;
-
- order_plus_one_ = isqrt32(channels);
- acn_channels = order_plus_one_ * order_plus_one_;
- nondiegetic_channels = channels - acn_channels;
- if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
- return OPUS_BAD_ARG;
-
- if (order_plus_one)
- *order_plus_one = order_plus_one_;
- return OPUS_OK;
-}
-
-static int get_streams_from_channels(int channels, int mapping_family,
- int *streams, int *coupled_streams,
- int *order_plus_one)
-{
- if (mapping_family == 3)
- {
- if (get_order_plus_one_from_channels(channels, order_plus_one) != OPUS_OK)
- return OPUS_BAD_ARG;
- if (streams)
- *streams = (channels + 1) / 2;
- if (coupled_streams)
- *coupled_streams = channels / 2;
- return OPUS_OK;
- }
- return OPUS_BAD_ARG;
-}
-
-static MappingMatrix *get_mixing_matrix(OpusProjectionEncoder *st)
-{
- /* void* cast avoids clang -Wcast-align warning */
- return (MappingMatrix *)(void*)((char*)st +
- align(sizeof(OpusProjectionEncoder)));
-}
-
-static MappingMatrix *get_enc_demixing_matrix(OpusProjectionEncoder *st)
-{
- /* void* cast avoids clang -Wcast-align warning */
- return (MappingMatrix *)(void*)((char*)st +
- align(sizeof(OpusProjectionEncoder) +
- st->mixing_matrix_size_in_bytes));
-}
-
-static OpusMSEncoder *get_multistream_encoder(OpusProjectionEncoder *st)
-{
- /* void* cast avoids clang -Wcast-align warning */
- return (OpusMSEncoder *)(void*)((char*)st +
- align(sizeof(OpusProjectionEncoder) +
- st->mixing_matrix_size_in_bytes +
- st->demixing_matrix_size_in_bytes));
-}
-
-opus_int32 opus_projection_ambisonics_encoder_get_size(int channels,
- int mapping_family)
-{
- int nb_streams;
- int nb_coupled_streams;
- int order_plus_one;
- int mixing_matrix_rows, mixing_matrix_cols;
- int demixing_matrix_rows, demixing_matrix_cols;
- opus_int32 mixing_matrix_size, demixing_matrix_size;
- opus_int32 encoder_size;
- int ret;
-
- ret = get_streams_from_channels(channels, mapping_family, &nb_streams,
- &nb_coupled_streams, &order_plus_one);
- if (ret != OPUS_OK)
- return 0;
-
- if (order_plus_one == 2)
- {
- mixing_matrix_rows = mapping_matrix_foa_mixing.rows;
- mixing_matrix_cols = mapping_matrix_foa_mixing.cols;
- demixing_matrix_rows = mapping_matrix_foa_demixing.rows;
- demixing_matrix_cols = mapping_matrix_foa_demixing.cols;
- }
- else if (order_plus_one == 3)
- {
- mixing_matrix_rows = mapping_matrix_soa_mixing.rows;
- mixing_matrix_cols = mapping_matrix_soa_mixing.cols;
- demixing_matrix_rows = mapping_matrix_soa_demixing.rows;
- demixing_matrix_cols = mapping_matrix_soa_demixing.cols;
- }
- else if (order_plus_one == 4)
- {
- mixing_matrix_rows = mapping_matrix_toa_mixing.rows;
- mixing_matrix_cols = mapping_matrix_toa_mixing.cols;
- demixing_matrix_rows = mapping_matrix_toa_demixing.rows;
- demixing_matrix_cols = mapping_matrix_toa_demixing.cols;
- }
- else
- return 0;
-
- mixing_matrix_size =
- mapping_matrix_get_size(mixing_matrix_rows, mixing_matrix_cols);
- if (!mixing_matrix_size)
- return 0;
-
- demixing_matrix_size =
- mapping_matrix_get_size(demixing_matrix_rows, demixing_matrix_cols);
- if (!demixing_matrix_size)
- return 0;
-
- encoder_size =
- opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
- if (!encoder_size)
- return 0;
-
- return align(sizeof(OpusProjectionEncoder)) +
- mixing_matrix_size + demixing_matrix_size + encoder_size;
-}
-
-int opus_projection_ambisonics_encoder_init(OpusProjectionEncoder *st, opus_int32 Fs,
- int channels, int mapping_family,
- int *streams, int *coupled_streams,
- int application)
-{
- MappingMatrix *mixing_matrix;
- MappingMatrix *demixing_matrix;
- OpusMSEncoder *ms_encoder;
- int i;
- int ret;
- int order_plus_one;
- unsigned char mapping[255];
-
- if (streams == NULL || coupled_streams == NULL) {
- return OPUS_BAD_ARG;
- }
-
- if (get_streams_from_channels(channels, mapping_family, streams,
- coupled_streams, &order_plus_one) != OPUS_OK)
- return OPUS_BAD_ARG;
-
- if (mapping_family == 3)
- {
- /* Assign mixing matrix based on available pre-computed matrices. */
- mixing_matrix = get_mixing_matrix(st);
- if (order_plus_one == 2)
- {
- mapping_matrix_init(mixing_matrix, mapping_matrix_foa_mixing.rows,
- mapping_matrix_foa_mixing.cols, mapping_matrix_foa_mixing.gain,
- mapping_matrix_foa_mixing_data,
- sizeof(mapping_matrix_foa_mixing_data));
- }
- else if (order_plus_one == 3)
- {
- mapping_matrix_init(mixing_matrix, mapping_matrix_soa_mixing.rows,
- mapping_matrix_soa_mixing.cols, mapping_matrix_soa_mixing.gain,
- mapping_matrix_soa_mixing_data,
- sizeof(mapping_matrix_soa_mixing_data));
- }
- else if (order_plus_one == 4)
- {
- mapping_matrix_init(mixing_matrix, mapping_matrix_toa_mixing.rows,
- mapping_matrix_toa_mixing.cols, mapping_matrix_toa_mixing.gain,
- mapping_matrix_toa_mixing_data,
- sizeof(mapping_matrix_toa_mixing_data));
- }
- else
- return OPUS_BAD_ARG;
-
- st->mixing_matrix_size_in_bytes = mapping_matrix_get_size(
- mixing_matrix->rows, mixing_matrix->cols);
- if (!st->mixing_matrix_size_in_bytes)
- return OPUS_BAD_ARG;
-
- /* Assign demixing matrix based on available pre-computed matrices. */
- demixing_matrix = get_enc_demixing_matrix(st);
- if (order_plus_one == 2)
- {
- mapping_matrix_init(demixing_matrix, mapping_matrix_foa_demixing.rows,
- mapping_matrix_foa_demixing.cols, mapping_matrix_foa_demixing.gain,
- mapping_matrix_foa_demixing_data,
- sizeof(mapping_matrix_foa_demixing_data));
- }
- else if (order_plus_one == 3)
- {
- mapping_matrix_init(demixing_matrix, mapping_matrix_soa_demixing.rows,
- mapping_matrix_soa_demixing.cols, mapping_matrix_soa_demixing.gain,
- mapping_matrix_soa_demixing_data,
- sizeof(mapping_matrix_soa_demixing_data));
- }
- else if (order_plus_one == 4)
- {
- mapping_matrix_init(demixing_matrix, mapping_matrix_toa_demixing.rows,
- mapping_matrix_toa_demixing.cols, mapping_matrix_toa_demixing.gain,
- mapping_matrix_toa_demixing_data,
- sizeof(mapping_matrix_toa_demixing_data));
- }
- else
- return OPUS_BAD_ARG;
-
- st->demixing_matrix_size_in_bytes = mapping_matrix_get_size(
- demixing_matrix->rows, demixing_matrix->cols);
- if (!st->demixing_matrix_size_in_bytes)
- return OPUS_BAD_ARG;
- }
- else
- return OPUS_UNIMPLEMENTED;
-
- /* Ensure matrices are large enough for desired coding scheme. */
- if (*streams + *coupled_streams > mixing_matrix->rows ||
- channels > mixing_matrix->cols ||
- channels > demixing_matrix->rows ||
- *streams + *coupled_streams > demixing_matrix->cols)
- return OPUS_BAD_ARG;
-
- /* Set trivial mapping so each input channel pairs with a matrix column. */
- for (i = 0; i < channels; i++)
- mapping[i] = i;
-
- /* Initialize multistream encoder with provided settings. */
- ms_encoder = get_multistream_encoder(st);
- ret = opus_multistream_encoder_init(ms_encoder, Fs, channels, *streams,
- *coupled_streams, mapping, application);
- return ret;
-}
-
-OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
- opus_int32 Fs, int channels, int mapping_family, int *streams,
- int *coupled_streams, int application, int *error)
-{
- int size;
- int ret;
- OpusProjectionEncoder *st;
-
- /* Allocate space for the projection encoder. */
- size = opus_projection_ambisonics_encoder_get_size(channels, mapping_family);
- if (!size) {
- if (error)
- *error = OPUS_ALLOC_FAIL;
- return NULL;
- }
- st = (OpusProjectionEncoder *)opus_alloc(size);
- if (!st)
- {
- if (error)
- *error = OPUS_ALLOC_FAIL;
- return NULL;
- }
-
- /* Initialize projection encoder with provided settings. */
- ret = opus_projection_ambisonics_encoder_init(st, Fs, channels,
- mapping_family, streams, coupled_streams, application);
- if (ret != OPUS_OK)
- {
- opus_free(st);
- st = NULL;
- }
- if (error)
- *error = ret;
- return st;
-}
-
-int opus_projection_encode(OpusProjectionEncoder *st, const opus_int16 *pcm,
- int frame_size, unsigned char *data,
- opus_int32 max_data_bytes)
-{
- return opus_multistream_encode_native(get_multistream_encoder(st),
- opus_projection_copy_channel_in_short, pcm, frame_size, data,
- max_data_bytes, 16, downmix_int, 0, get_mixing_matrix(st));
-}
-
-#ifndef DISABLE_FLOAT_API
-#ifdef FIXED_POINT
-int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
- int frame_size, unsigned char *data,
- opus_int32 max_data_bytes)
-{
- return opus_multistream_encode_native(get_multistream_encoder(st),
- opus_projection_copy_channel_in_float, pcm, frame_size, data,
- max_data_bytes, 16, downmix_float, 1, get_mixing_matrix(st));
-}
-#else
-int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
- int frame_size, unsigned char *data,
- opus_int32 max_data_bytes)
-{
- return opus_multistream_encode_native(get_multistream_encoder(st),
- opus_projection_copy_channel_in_float, pcm, frame_size, data,
- max_data_bytes, 24, downmix_float, 1, get_mixing_matrix(st));
-}
-#endif
-#endif
-
-void opus_projection_encoder_destroy(OpusProjectionEncoder *st)
-{
- opus_free(st);
-}
-
-int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...)
-{
- va_list ap;
- MappingMatrix *demixing_matrix;
- OpusMSEncoder *ms_encoder;
- int ret = OPUS_OK;
-
- ms_encoder = get_multistream_encoder(st);
- demixing_matrix = get_enc_demixing_matrix(st);
-
- va_start(ap, request);
- switch(request)
- {
- case OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST:
- {
- opus_int32 *value = va_arg(ap, opus_int32*);
- if (!value)
- {
- goto bad_arg;
- }
- *value =
- ms_encoder->layout.nb_channels * (ms_encoder->layout.nb_streams
- + ms_encoder->layout.nb_coupled_streams) * sizeof(opus_int16);
- }
- break;
- case OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST:
- {
- opus_int32 *value = va_arg(ap, opus_int32*);
- if (!value)
- {
- goto bad_arg;
- }
- *value = demixing_matrix->gain;
- }
- break;
- case OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST:
- {
- int i, j, k, l;
- int nb_input_streams;
- int nb_output_streams;
- unsigned char *external_char;
- opus_int16 *internal_short;
- opus_int32 external_size;
- opus_int32 internal_size;
-
- /* (I/O is in relation to the decoder's perspective). */
- nb_input_streams = ms_encoder->layout.nb_streams +
- ms_encoder->layout.nb_coupled_streams;
- nb_output_streams = ms_encoder->layout.nb_channels;
-
- external_char = va_arg(ap, unsigned char *);
- external_size = va_arg(ap, opus_int32);
- if (!external_char)
- {
- goto bad_arg;
- }
- internal_short = mapping_matrix_get_data(demixing_matrix);
- internal_size = nb_input_streams * nb_output_streams * sizeof(opus_int16);
- if (external_size != internal_size)
- {
- goto bad_arg;
- }
-
- /* Copy demixing matrix subset to output destination. */
- l = 0;
- for (i = 0; i < nb_input_streams; i++) {
- for (j = 0; j < nb_output_streams; j++) {
- k = demixing_matrix->rows * i + j;
- external_char[2*l] = (unsigned char)internal_short[k];
- external_char[2*l+1] = (unsigned char)(internal_short[k] >> 8);
- l++;
- }
- }
- }
- break;
- default:
- {
- ret = opus_multistream_encoder_ctl_va_list(ms_encoder, request, ap);
- }
- break;
- }
- va_end(ap);
- return ret;
-
-bad_arg:
- va_end(ap);
- return OPUS_BAD_ARG;
-}
-
diff --git a/thirdparty/opus/opusfile.c b/thirdparty/opus/opusfile.c
index 8b000a2c58..b8b3a354cf 100644
--- a/thirdparty/opus/opusfile.c
+++ b/thirdparty/opus/opusfile.c
@@ -86,15 +86,14 @@ int op_test(OpusHead *_head,
This is to prevent us spending a lot of time allocating memory and looking
for Ogg pages in non-Ogg files.*/
if(memcmp(_initial_data,"OggS",4)!=0)return OP_ENOTFORMAT;
- if(OP_UNLIKELY(_initial_bytes>(size_t)LONG_MAX))return OP_EFAULT;
ogg_sync_init(&oy);
- data=ogg_sync_buffer(&oy,(long)_initial_bytes);
+ data=ogg_sync_buffer(&oy,_initial_bytes);
if(data!=NULL){
ogg_stream_state os;
ogg_page og;
int ret;
memcpy(data,_initial_data,_initial_bytes);
- ogg_sync_wrote(&oy,(long)_initial_bytes);
+ ogg_sync_wrote(&oy,_initial_bytes);
ogg_stream_init(&os,-1);
err=OP_FALSE;
do{
@@ -148,7 +147,7 @@ static int op_get_data(OggOpusFile *_of,int _nbytes){
int nbytes;
OP_ASSERT(_nbytes>0);
buffer=(unsigned char *)ogg_sync_buffer(&_of->oy,_nbytes);
- nbytes=(int)(*_of->callbacks.read)(_of->stream,buffer,_nbytes);
+ nbytes=(int)(*_of->callbacks.read)(_of->source,buffer,_nbytes);
OP_ASSERT(nbytes<=_nbytes);
if(OP_LIKELY(nbytes>0))ogg_sync_wrote(&_of->oy,nbytes);
return nbytes;
@@ -158,7 +157,7 @@ static int op_get_data(OggOpusFile *_of,int _nbytes){
static int op_seek_helper(OggOpusFile *_of,opus_int64 _offset){
if(_offset==_of->offset)return 0;
if(_of->callbacks.seek==NULL
- ||(*_of->callbacks.seek)(_of->stream,_offset,SEEK_SET)){
+ ||(*_of->callbacks.seek)(_of->source,_offset,SEEK_SET)){
return OP_EREAD;
}
_of->offset=_offset;
@@ -166,7 +165,7 @@ static int op_seek_helper(OggOpusFile *_of,opus_int64 _offset){
return 0;
}
-/*Get the current position indicator of the underlying stream.
+/*Get the current position indicator of the underlying source.
This should be the same as the value reported by tell().*/
static opus_int64 op_position(const OggOpusFile *_of){
/*The current position indicator is _not_ simply offset.
@@ -370,7 +369,7 @@ static int op_get_prev_page_serial(OggOpusFile *_of,OpusSeekRecord *_sr,
search_start=llret+1;
}
/*We started from the beginning of the stream and found nothing.
- This should be impossible unless the contents of the stream changed out
+ This should be impossible unless the contents of the source changed out
from under us after we read from it.*/
if(OP_UNLIKELY(!begin)&&OP_UNLIKELY(_offset<0))return OP_EBADLINK;
/*Bump up the chunk size.
@@ -456,7 +455,7 @@ static opus_int64 op_get_last_page(OggOpusFile *_of,ogg_int64_t *_gp,
}
}
/*We started from at or before the beginning of the link and found nothing.
- This should be impossible unless the contents of the stream changed out
+ This should be impossible unless the contents of the source changed out
from under us after we read from it.*/
if((OP_UNLIKELY(left_link)||OP_UNLIKELY(!begin))&&OP_UNLIKELY(_offset<0)){
return OP_EBADLINK;
@@ -856,7 +855,6 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
/*Fail if the pre-skip is non-zero, since it's asking us to skip more
samples than exist.*/
if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP;
- _link->pcm_file_offset=0;
/*Set pcm_end and end_offset so we can skip the call to
op_find_final_pcm_offset().*/
_link->pcm_start=_link->pcm_end=0;
@@ -868,8 +866,7 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP;
/*Set pcm_end and end_offset so we can skip the call to
op_find_final_pcm_offset().*/
- _link->pcm_file_offset=0;
- _link->pcm_start=_link->pcm_end=0;
+ _link->pcm_end=_link->pcm_start=0;
_link->end_offset=_link->data_offset;
/*Tell the caller we've got a buffered page for them.*/
return 1;
@@ -954,7 +951,6 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
/*Update the packet count after end-trimming.*/
_of->op_count=pi;
_of->cur_discard_count=_link->head.pre_skip;
- _link->pcm_file_offset=0;
_of->prev_packet_gp=_link->pcm_start=pcm_start;
_of->prev_page_offset=page_offset;
return 0;
@@ -1275,7 +1271,6 @@ static int op_bisect_forward_serialno(OggOpusFile *_of,
always starts with a seek.*/
ret=op_find_initial_pcm_offset(_of,links+nlinks,NULL);
if(OP_UNLIKELY(ret<0))return ret;
- links[nlinks].pcm_file_offset=total_duration;
_searched=_of->offset;
/*Mark the current link count so it can be cleaned up on error.*/
_of->nlinks=++nlinks;
@@ -1395,8 +1390,8 @@ static int op_open_seekable2_impl(OggOpusFile *_of){
opus_int64 data_offset;
int ret;
/*We can seek, so set out learning all about this file.*/
- (*_of->callbacks.seek)(_of->stream,0,SEEK_END);
- _of->offset=_of->end=(*_of->callbacks.tell)(_of->stream);
+ (*_of->callbacks.seek)(_of->source,0,SEEK_END);
+ _of->offset=_of->end=(*_of->callbacks.tell)(_of->source);
if(OP_UNLIKELY(_of->end<0))return OP_EREAD;
data_offset=_of->links[0].data_offset;
if(OP_UNLIKELY(_of->end<data_offset))return OP_EBADLINK;
@@ -1441,7 +1436,7 @@ static int op_open_seekable2(OggOpusFile *_of){
prev_page_offset=_of->prev_page_offset;
start_offset=_of->offset;
memcpy(op_start,_of->op,sizeof(*op_start)*start_op_count);
- OP_ASSERT((*_of->callbacks.tell)(_of->stream)==op_position(_of));
+ OP_ASSERT((*_of->callbacks.tell)(_of->source)==op_position(_of));
ogg_sync_init(&_of->oy);
ogg_stream_init(&_of->os,-1);
ret=op_open_seekable2_impl(_of);
@@ -1459,7 +1454,7 @@ static int op_open_seekable2(OggOpusFile *_of){
_of->cur_discard_count=_of->links[0].head.pre_skip;
if(OP_UNLIKELY(ret<0))return ret;
/*And restore the position indicator.*/
- ret=(*_of->callbacks.seek)(_of->stream,op_position(_of),SEEK_SET);
+ ret=(*_of->callbacks.seek)(_of->source,op_position(_of),SEEK_SET);
return OP_UNLIKELY(ret<0)?OP_EREAD:0;
}
@@ -1498,20 +1493,19 @@ static void op_clear(OggOpusFile *_of){
_ogg_free(_of->serialnos);
ogg_stream_clear(&_of->os);
ogg_sync_clear(&_of->oy);
- if(_of->callbacks.close!=NULL)(*_of->callbacks.close)(_of->stream);
+ if(_of->callbacks.close!=NULL)(*_of->callbacks.close)(_of->source);
}
static int op_open1(OggOpusFile *_of,
- void *_stream,const OpusFileCallbacks *_cb,
+ void *_source,const OpusFileCallbacks *_cb,
const unsigned char *_initial_data,size_t _initial_bytes){
ogg_page og;
ogg_page *pog;
int seekable;
int ret;
memset(_of,0,sizeof(*_of));
- if(OP_UNLIKELY(_initial_bytes>(size_t)LONG_MAX))return OP_EFAULT;
_of->end=-1;
- _of->stream=_stream;
+ _of->source=_source;
*&_of->callbacks=*_cb;
/*At a minimum, we need to be able to read data.*/
if(OP_UNLIKELY(_of->callbacks.read==NULL))return OP_EREAD;
@@ -1526,18 +1520,18 @@ static int op_open1(OggOpusFile *_of,
decoding entire files from RAM.*/
if(_initial_bytes>0){
char *buffer;
- buffer=ogg_sync_buffer(&_of->oy,(long)_initial_bytes);
+ buffer=ogg_sync_buffer(&_of->oy,_initial_bytes);
memcpy(buffer,_initial_data,_initial_bytes*sizeof(*buffer));
- ogg_sync_wrote(&_of->oy,(long)_initial_bytes);
+ ogg_sync_wrote(&_of->oy,_initial_bytes);
}
/*Can we seek?
Stevens suggests the seek test is portable.*/
- seekable=_cb->seek!=NULL&&(*_cb->seek)(_stream,0,SEEK_CUR)!=-1;
+ seekable=_cb->seek!=NULL&&(*_cb->seek)(_source,0,SEEK_CUR)!=-1;
/*If seek is implemented, tell must also be implemented.*/
if(seekable){
opus_int64 pos;
if(OP_UNLIKELY(_of->callbacks.tell==NULL))return OP_EINVAL;
- pos=(*_of->callbacks.tell)(_of->stream);
+ pos=(*_of->callbacks.tell)(_of->source);
/*If the current position is not equal to the initial bytes consumed,
absolute seeking will not work.*/
if(OP_UNLIKELY(pos!=(opus_int64)_initial_bytes))return OP_EINVAL;
@@ -1596,14 +1590,14 @@ static int op_open2(OggOpusFile *_of){
return ret;
}
-OggOpusFile *op_test_callbacks(void *_stream,const OpusFileCallbacks *_cb,
+OggOpusFile *op_test_callbacks(void *_source,const OpusFileCallbacks *_cb,
const unsigned char *_initial_data,size_t _initial_bytes,int *_error){
OggOpusFile *of;
int ret;
of=(OggOpusFile *)_ogg_malloc(sizeof(*of));
ret=OP_EFAULT;
if(OP_LIKELY(of!=NULL)){
- ret=op_open1(of,_stream,_cb,_initial_data,_initial_bytes);
+ ret=op_open1(of,_source,_cb,_initial_data,_initial_bytes);
if(OP_LIKELY(ret>=0)){
if(_error!=NULL)*_error=0;
return of;
@@ -1617,10 +1611,10 @@ OggOpusFile *op_test_callbacks(void *_stream,const OpusFileCallbacks *_cb,
return NULL;
}
-OggOpusFile *op_open_callbacks(void *_stream,const OpusFileCallbacks *_cb,
+OggOpusFile *op_open_callbacks(void *_source,const OpusFileCallbacks *_cb,
const unsigned char *_initial_data,size_t _initial_bytes,int *_error){
OggOpusFile *of;
- of=op_test_callbacks(_stream,_cb,_initial_data,_initial_bytes,_error);
+ of=op_test_callbacks(_source,_cb,_initial_data,_initial_bytes,_error);
if(OP_LIKELY(of!=NULL)){
int ret;
ret=op_open2(of);
@@ -1633,15 +1627,15 @@ OggOpusFile *op_open_callbacks(void *_stream,const OpusFileCallbacks *_cb,
/*Convenience routine to clean up from failure for the open functions that
create their own streams.*/
-static OggOpusFile *op_open_close_on_failure(void *_stream,
+static OggOpusFile *op_open_close_on_failure(void *_source,
const OpusFileCallbacks *_cb,int *_error){
OggOpusFile *of;
- if(OP_UNLIKELY(_stream==NULL)){
+ if(OP_UNLIKELY(_source==NULL)){
if(_error!=NULL)*_error=OP_EFAULT;
return NULL;
}
- of=op_open_callbacks(_stream,_cb,NULL,0,_error);
- if(OP_UNLIKELY(of==NULL))(*_cb->close)(_stream);
+ of=op_open_callbacks(_source,_cb,NULL,0,_error);
+ if(OP_UNLIKELY(of==NULL))(*_cb->close)(_source);
return of;
}
@@ -1659,15 +1653,15 @@ OggOpusFile *op_open_memory(const unsigned char *_data,size_t _size,
/*Convenience routine to clean up from failure for the open functions that
create their own streams.*/
-static OggOpusFile *op_test_close_on_failure(void *_stream,
+static OggOpusFile *op_test_close_on_failure(void *_source,
const OpusFileCallbacks *_cb,int *_error){
OggOpusFile *of;
- if(OP_UNLIKELY(_stream==NULL)){
+ if(OP_UNLIKELY(_source==NULL)){
if(_error!=NULL)*_error=OP_EFAULT;
return NULL;
}
- of=op_test_callbacks(_stream,_cb,NULL,0,_error);
- if(OP_UNLIKELY(of==NULL))(*_cb->close)(_stream);
+ of=op_test_callbacks(_source,_cb,NULL,0,_error);
+ if(OP_UNLIKELY(of==NULL))(*_cb->close)(_source);
return of;
}
@@ -1708,7 +1702,7 @@ int op_link_count(const OggOpusFile *_of){
return _of->nlinks;
}
-opus_uint32 op_serialno(const OggOpusFile *_of,int _li){
+ogg_uint32_t op_serialno(const OggOpusFile *_of,int _li){
if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1;
if(!_of->seekable)_li=0;
return _of->links[_li<0?_of->cur_link:_li].serialno;
@@ -1724,14 +1718,13 @@ opus_int64 op_raw_total(const OggOpusFile *_of,int _li){
||OP_UNLIKELY(_li>=_of->nlinks)){
return OP_EINVAL;
}
- if(_li<0)return _of->end;
+ if(_li<0)return _of->end-_of->links[0].offset;
return (_li+1>=_of->nlinks?_of->end:_of->links[_li+1].offset)
- -(_li>0?_of->links[_li].offset:0);
+ -_of->links[_li].offset;
}
ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li){
OggOpusLink *links;
- ogg_int64_t pcm_total;
ogg_int64_t diff;
int nlinks;
nlinks=_of->nlinks;
@@ -1744,14 +1737,20 @@ ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li){
/*We verify that the granule position differences are larger than the
pre-skip and that the total duration does not overflow during link
enumeration, so we don't have to check here.*/
- pcm_total=0;
if(_li<0){
- pcm_total=links[nlinks-1].pcm_file_offset;
- _li=nlinks-1;
+ ogg_int64_t pcm_total;
+ int li;
+ pcm_total=0;
+ for(li=0;li<nlinks;li++){
+ OP_ALWAYS_TRUE(!op_granpos_diff(&diff,
+ links[li].pcm_end,links[li].pcm_start));
+ pcm_total+=diff-links[li].head.pre_skip;
+ }
+ return pcm_total;
}
OP_ALWAYS_TRUE(!op_granpos_diff(&diff,
links[_li].pcm_end,links[_li].pcm_start));
- return pcm_total+diff-links[_li].head.pre_skip;
+ return diff-links[_li].head.pre_skip;
}
const OpusHead *op_head(const OggOpusFile *_of,int _li){
@@ -1821,34 +1820,6 @@ opus_int32 op_bitrate_instant(OggOpusFile *_of){
return ret;
}
-/*Given a serialno, find a link with a corresponding Opus stream, if it exists.
- Return: The index of the link to which the page belongs, or a negative number
- if it was not a desired Opus bitstream section.*/
-static int op_get_link_from_serialno(const OggOpusFile *_of,int _cur_link,
- opus_int64 _page_offset,ogg_uint32_t _serialno){
- const OggOpusLink *links;
- int nlinks;
- int li_lo;
- int li_hi;
- OP_ASSERT(_of->seekable);
- links=_of->links;
- nlinks=_of->nlinks;
- li_lo=0;
- /*Start off by guessing we're just a multiplexed page in the current link.*/
- li_hi=_cur_link+1<nlinks&&_page_offset<links[_cur_link+1].offset?
- _cur_link+1:nlinks;
- do{
- if(_page_offset>=links[_cur_link].offset)li_lo=_cur_link;
- else li_hi=_cur_link;
- _cur_link=li_lo+(li_hi-li_lo>>1);
- }
- while(li_hi-li_lo>1);
- /*We've identified the link that should contain this page.
- Make sure it's a page we care about.*/
- if(links[_cur_link].serialno!=_serialno)return OP_FALSE;
- return _cur_link;
-}
-
/*Fetch and process a page.
This handles the case where we're at a bitstream boundary and dumps the
decoding machine.
@@ -1905,28 +1876,19 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
if(OP_UNLIKELY(_of->ready_state<OP_STREAMSET)){
if(seekable){
ogg_uint32_t serialno;
+ int nlinks;
+ int li;
serialno=ogg_page_serialno(&og);
- /*Match the serialno to bitstream section.*/
- OP_ASSERT(cur_link>=0&&cur_link<_of->nlinks);
- if(links[cur_link].serialno!=serialno){
- /*It wasn't a page from the current link.
- Is it from the next one?*/
- if(OP_LIKELY(cur_link+1<_of->nlinks&&links[cur_link+1].serialno==
- serialno)){
- cur_link++;
- }
- else{
- int new_link;
- new_link=
- op_get_link_from_serialno(_of,cur_link,_page_offset,serialno);
- /*Not a desired Opus bitstream section.
- Keep trying.*/
- if(new_link<0)continue;
- cur_link=new_link;
- }
- }
+ /*Match the serialno to bitstream section.
+ We use this rather than offset positions to avoid problems near
+ logical bitstream boundaries.*/
+ nlinks=_of->nlinks;
+ for(li=0;li<nlinks&&links[li].serialno!=serialno;li++);
+ /*Not a desired Opus bitstream section.
+ Keep trying.*/
+ if(li>=nlinks)continue;
cur_serialno=serialno;
- _of->cur_link=cur_link;
+ _of->cur_link=cur_link=li;
ogg_stream_reset_serialno(&_of->os,serialno);
_of->ready_state=OP_STREAMSET;
/*If we're at the start of this link, initialize the granule position
@@ -1980,32 +1942,13 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
opus_int32 total_duration;
int durations[255];
int op_count;
- int report_hole;
- report_hole=0;
total_duration=op_collect_audio_packets(_of,durations);
if(OP_UNLIKELY(total_duration<0)){
- /*libogg reported a hole (a gap in the page sequence numbers).
- Drain the packets from the page anyway.
- If we don't, they'll still be there when we fetch the next page.
- Then, when we go to pull out packets, we might get more than 255,
- which would overrun our packet buffer.*/
+ /*Drain the packets from the page anyway.*/
total_duration=op_collect_audio_packets(_of,durations);
OP_ASSERT(total_duration>=0);
- if(!_ignore_holes){
- /*Report the hole to the caller after we finish timestamping the
- packets.*/
- report_hole=1;
- /*We had lost or damaged pages, so reset our granule position
- tracking.
- This makes holes behave the same as a small raw seek.
- If the next page is the EOS page, we'll discard it (because we
- can't perform end trimming properly), and we'll always discard at
- least 80 ms of audio (to allow decoder state to re-converge).
- We could try to fill in the gap with PLC by looking at timestamps
- in the non-EOS case, but that's complicated and error prone and we
- can't rely on the timestamps being valid.*/
- _of->prev_packet_gp=-1;
- }
+ /*Report holes to the caller.*/
+ if(!_ignore_holes)return OP_HOLE;
}
op_count=_of->op_count;
/*If we found at least one audio data packet, compute per-packet granule
@@ -2032,7 +1975,6 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
Proceed to the next link, rather than risk playing back some
samples that shouldn't have been played.*/
_of->op_count=0;
- if(report_hole)return OP_HOLE;
continue;
}
/*By default discard 80 ms of data after a seek, unless we seek
@@ -2078,11 +2020,7 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
&&OP_LIKELY(diff<total_duration)){
cur_packet_gp=prev_packet_gp;
for(pi=0;pi<op_count;pi++){
- /*Check for overflow.*/
- if(diff<0&&OP_UNLIKELY(OP_INT64_MAX+diff<durations[pi])){
- diff=durations[pi]+1;
- }
- else diff=durations[pi]-diff;
+ diff=durations[pi]-diff;
/*If we have samples to trim...*/
if(diff>0){
/*If we trimmed the entire packet, stop (the spec says encoders
@@ -2138,11 +2076,10 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
}
_of->prev_packet_gp=prev_packet_gp;
_of->prev_page_offset=_page_offset;
- _of->op_count=op_count=pi;
+ _of->op_count=pi;
+ /*If end-trimming didn't trim all the packets, we're done.*/
+ if(OP_LIKELY(pi>0))return 0;
}
- if(report_hole)return OP_HOLE;
- /*If end-trimming didn't trim all the packets, we're done.*/
- if(op_count>0)return 0;
}
}
}
@@ -2180,41 +2117,35 @@ static ogg_int64_t op_get_granulepos(const OggOpusFile *_of,
ogg_int64_t _pcm_offset,int *_li){
const OggOpusLink *links;
ogg_int64_t duration;
- ogg_int64_t pcm_start;
- opus_int32 pre_skip;
int nlinks;
- int li_lo;
- int li_hi;
+ int li;
OP_ASSERT(_pcm_offset>=0);
nlinks=_of->nlinks;
links=_of->links;
- li_lo=0;
- li_hi=nlinks;
- do{
- int li;
- li=li_lo+(li_hi-li_lo>>1);
- if(links[li].pcm_file_offset<=_pcm_offset)li_lo=li;
- else li_hi=li;
- }
- while(li_hi-li_lo>1);
- _pcm_offset-=links[li_lo].pcm_file_offset;
- pcm_start=links[li_lo].pcm_start;
- pre_skip=links[li_lo].head.pre_skip;
- OP_ALWAYS_TRUE(!op_granpos_diff(&duration,links[li_lo].pcm_end,pcm_start));
- duration-=pre_skip;
- if(_pcm_offset>=duration)return -1;
- _pcm_offset+=pre_skip;
- if(OP_UNLIKELY(pcm_start>OP_INT64_MAX-_pcm_offset)){
- /*Adding this amount to the granule position would overflow the positive
- half of its 64-bit range.
- Since signed overflow is undefined in C, do it in a way the compiler
- isn't allowed to screw up.*/
- _pcm_offset-=OP_INT64_MAX-pcm_start+1;
- pcm_start=OP_INT64_MIN;
- }
- pcm_start+=_pcm_offset;
- *_li=li_lo;
- return pcm_start;
+ for(li=0;OP_LIKELY(li<nlinks);li++){
+ ogg_int64_t pcm_start;
+ opus_int32 pre_skip;
+ pcm_start=links[li].pcm_start;
+ pre_skip=links[li].head.pre_skip;
+ OP_ALWAYS_TRUE(!op_granpos_diff(&duration,links[li].pcm_end,pcm_start));
+ duration-=pre_skip;
+ if(_pcm_offset<duration){
+ _pcm_offset+=pre_skip;
+ if(OP_UNLIKELY(pcm_start>OP_INT64_MAX-_pcm_offset)){
+ /*Adding this amount to the granule position would overflow the positive
+ half of its 64-bit range.
+ Since signed overflow is undefined in C, do it in a way the compiler
+ isn't allowed to screw up.*/
+ _pcm_offset-=OP_INT64_MAX-pcm_start+1;
+ pcm_start=OP_INT64_MIN;
+ }
+ pcm_start+=_pcm_offset;
+ *_li=li;
+ return pcm_start;
+ }
+ _pcm_offset-=duration;
+ }
+ return -1;
}
/*A small helper to determine if an Ogg page contains data that continues onto
@@ -2601,14 +2532,15 @@ int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset){
ogg_int64_t gp;
gp=_of->prev_packet_gp;
if(OP_LIKELY(gp!=-1)){
- ogg_int64_t discard_count;
- int nbuffered;
+ int nbuffered;
nbuffered=OP_MAX(_of->od_buffer_size-_of->od_buffer_pos,0);
OP_ALWAYS_TRUE(!op_granpos_add(&gp,gp,-nbuffered));
/*We do _not_ add cur_discard_count to gp.
Otherwise the total amount to discard could grow without bound, and it
would be better just to do a full seek.*/
- if(OP_LIKELY(!op_granpos_diff(&discard_count,target_gp,gp))){
+ if(OP_LIKELY(!op_granpos_diff(&diff,gp,pcm_start))){
+ ogg_int64_t discard_count;
+ discard_count=_pcm_offset-diff;
/*We use a threshold of 90 ms instead of 80, since 80 ms is the
_minimum_ we would have discarded after a full seek.
Assuming 20 ms frames (the default), we'd discard 90 ms on average.*/
@@ -2674,14 +2606,22 @@ static ogg_int64_t op_get_pcm_offset(const OggOpusFile *_of,
ogg_int64_t _gp,int _li){
const OggOpusLink *links;
ogg_int64_t pcm_offset;
+ ogg_int64_t delta;
+ int li;
links=_of->links;
- OP_ASSERT(_li>=0&&_li<_of->nlinks);
- pcm_offset=links[_li].pcm_file_offset;
+ pcm_offset=0;
+ OP_ASSERT(_li<_of->nlinks);
+ for(li=0;li<_li;li++){
+ OP_ALWAYS_TRUE(!op_granpos_diff(&delta,
+ links[li].pcm_end,links[li].pcm_start));
+ delta-=links[li].head.pre_skip;
+ pcm_offset+=delta;
+ }
+ OP_ASSERT(_li>=0);
if(_of->seekable&&OP_UNLIKELY(op_granpos_cmp(_gp,links[_li].pcm_end)>0)){
_gp=links[_li].pcm_end;
}
if(OP_LIKELY(op_granpos_cmp(_gp,links[_li].pcm_start)>0)){
- ogg_int64_t delta;
if(OP_UNLIKELY(op_granpos_diff(&delta,_gp,links[_li].pcm_start)<0)){
/*This means an unseekable stream claimed to have a page from more than
2 billion days after we joined.*/
diff --git a/thirdparty/opus/repacketizer.c b/thirdparty/opus/repacketizer.c
index bda44a148a..c80ee7f001 100644
--- a/thirdparty/opus/repacketizer.c
+++ b/thirdparty/opus/repacketizer.c
@@ -213,8 +213,7 @@ opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int
{
/* Using OPUS_MOVE() instead of OPUS_COPY() in case we're doing in-place
padding from opus_packet_pad or opus_packet_unpad(). */
- /* assert disabled because it's not valid in C. */
- /* celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); */
+ celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]);
OPUS_MOVE(ptr, frames[i], len[i]);
ptr += len[i];
}
diff --git a/thirdparty/opus/silk/A2NLSF.c b/thirdparty/opus/silk/A2NLSF.c
index b487686ff9..b6e9e5ffcc 100644
--- a/thirdparty/opus/silk/A2NLSF.c
+++ b/thirdparty/opus/silk/A2NLSF.c
@@ -40,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
/* Number of binary divisions, when not in low complexity mode */
#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
-#define MAX_ITERATIONS_A2NLSF_FIX 16
+#define MAX_ITERATIONS_A2NLSF_FIX 30
/* Helper function for A2NLSF(..) */
/* Transforms polynomials from cos(n*f) to cos(f)^n */
@@ -130,7 +130,7 @@ void silk_A2NLSF(
const opus_int d /* I Filter order (must be even) */
)
{
- opus_int i, k, m, dd, root_ix, ffrac;
+ opus_int i, k, m, dd, root_ix, ffrac;
opus_int32 xlo, xhi, xmid;
opus_int32 ylo, yhi, ymid, thr;
opus_int32 nom, den;
@@ -239,13 +239,13 @@ void silk_A2NLSF(
/* Set NLSFs to white spectrum and exit */
NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
for( k = 1; k < d; k++ ) {
- NLSF[ k ] = (opus_int16)silk_ADD16( NLSF[ k-1 ], NLSF[ 0 ] );
+ NLSF[ k ] = (opus_int16)silk_SMULBB( k + 1, NLSF[ 0 ] );
}
return;
}
/* Error: Apply progressively more bandwidth expansion and run again */
- silk_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) );
+ silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/
silk_A2NLSF_init( a_Q16, P, Q, dd );
p = P; /* Pointer to polynomial */
diff --git a/thirdparty/opus/silk/API.h b/thirdparty/opus/silk/API.h
index 4d90ff9aa3..0131acbb08 100644
--- a/thirdparty/opus/silk/API.h
+++ b/thirdparty/opus/silk/API.h
@@ -80,8 +80,7 @@ opus_int silk_Encode( /* O Returns error co
opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
- const opus_int prefillFlag, /* I Flag to indicate prefilling buffers no coding */
- int activity /* I Decision of Opus voice activity detector */
+ const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */
);
/****************************************/
diff --git a/thirdparty/opus/silk/CNG.c b/thirdparty/opus/silk/CNG.c
index ef8e38df9f..8443ad63bb 100644
--- a/thirdparty/opus/silk/CNG.c
+++ b/thirdparty/opus/silk/CNG.c
@@ -138,16 +138,16 @@ void silk_CNG(
gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
}
gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
-
+
silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
/* Convert CNG NLSF to filter representation */
- silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch );
+ silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
/* Generate CNG signal, by synthesis filtering */
silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
- celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
for( i = 0; i < length; i++ ) {
+ silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
@@ -170,11 +170,11 @@ void silk_CNG(
}
/* Update states */
- CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
-
+ CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q14[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
+
/* Scale with Gain and add to input signal */
frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) );
-
+
}
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
} else {
diff --git a/thirdparty/opus/silk/LPC_analysis_filter.c b/thirdparty/opus/silk/LPC_analysis_filter.c
index d34b5eb709..20906673ff 100644
--- a/thirdparty/opus/silk/LPC_analysis_filter.c
+++ b/thirdparty/opus/silk/LPC_analysis_filter.c
@@ -39,13 +39,6 @@ POSSIBILITY OF SUCH DAMAGE.
/* first d output samples are set to zero */
/*******************************************/
-/* OPT: Using celt_fir() for this function should be faster, but it may cause
- integer overflows in intermediate values (not final results), which the
- current implementation silences by casting to unsigned. Enabling
- this should be safe in pretty much all cases, even though it is not technically
- C89-compliant. */
-#define USE_CELT_FIR 0
-
void silk_LPC_analysis_filter(
opus_int16 *out, /* O Output signal */
const opus_int16 *in, /* I Input signal */
@@ -56,7 +49,8 @@ void silk_LPC_analysis_filter(
)
{
opus_int j;
-#if defined(FIXED_POINT) && USE_CELT_FIR
+#ifdef FIXED_POINT
+ opus_int16 mem[SILK_MAX_ORDER_LPC];
opus_int16 num[SILK_MAX_ORDER_LPC];
#else
int ix;
@@ -64,16 +58,19 @@ void silk_LPC_analysis_filter(
const opus_int16 *in_ptr;
#endif
- celt_assert( d >= 6 );
- celt_assert( (d & 1) == 0 );
- celt_assert( d <= len );
+ silk_assert( d >= 6 );
+ silk_assert( (d & 1) == 0 );
+ silk_assert( d <= len );
-#if defined(FIXED_POINT) && USE_CELT_FIR
- celt_assert( d <= SILK_MAX_ORDER_LPC );
+#ifdef FIXED_POINT
+ silk_assert( d <= SILK_MAX_ORDER_LPC );
for ( j = 0; j < d; j++ ) {
num[ j ] = -B[ j ];
}
- celt_fir( in + d, num, out + d, len - d, d, arch );
+ for (j=0;j<d;j++) {
+ mem[ j ] = in[ d - j - 1 ];
+ }
+ celt_fir( in + d, num, out + d, len - d, d, mem, arch );
for ( j = 0; j < d; j++ ) {
out[ j ] = 0;
}
diff --git a/thirdparty/opus/silk/LPC_fit.c b/thirdparty/opus/silk/LPC_fit.c
deleted file mode 100644
index cdea4f3abc..0000000000
--- a/thirdparty/opus/silk/LPC_fit.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/***********************************************************************
-Copyright (c) 2013, Koen Vos. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "SigProc_FIX.h"
-
-/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
-void silk_LPC_fit(
- opus_int16 *a_QOUT, /* O Output signal */
- opus_int32 *a_QIN, /* I/O Input signal */
- const opus_int QOUT, /* I Input Q domain */
- const opus_int QIN, /* I Input Q domain */
- const opus_int d /* I Filter order */
-)
-{
- opus_int i, k, idx = 0;
- opus_int32 maxabs, absval, chirp_Q16;
-
- /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
- for( i = 0; i < 10; i++ ) {
- /* Find maximum absolute value and its index */
- maxabs = 0;
- for( k = 0; k < d; k++ ) {
- absval = silk_abs( a_QIN[k] );
- if( absval > maxabs ) {
- maxabs = absval;
- idx = k;
- }
- }
- maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT );
-
- if( maxabs > silk_int16_MAX ) {
- /* Reduce magnitude of prediction coefficients */
- maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
- chirp_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
- silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
- silk_bwexpander_32( a_QIN, d, chirp_Q16 );
- } else {
- break;
- }
- }
-
- if( i == 10 ) {
- /* Reached the last iteration, clip the coefficients */
- for( k = 0; k < d; k++ ) {
- a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) );
- a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT );
- }
- } else {
- for( k = 0; k < d; k++ ) {
- a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT );
- }
- }
-}
diff --git a/thirdparty/opus/silk/LPC_inv_pred_gain.c b/thirdparty/opus/silk/LPC_inv_pred_gain.c
index a3746a6ef9..4af89aa5fa 100644
--- a/thirdparty/opus/silk/LPC_inv_pred_gain.c
+++ b/thirdparty/opus/silk/LPC_inv_pred_gain.c
@@ -30,7 +30,6 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "SigProc_FIX.h"
-#include "define.h"
#define QA 24
#define A_LIMIT SILK_FIX_CONST( 0.99975, QA )
@@ -39,103 +38,117 @@ POSSIBILITY OF SUCH DAMAGE.
/* Compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */
-static opus_int32 LPC_inverse_pred_gain_QA_c( /* O Returns inverse prediction gain in energy domain, Q30 */
- opus_int32 A_QA[ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
+static opus_int32 LPC_inverse_pred_gain_QA( /* O Returns inverse prediction gain in energy domain, Q30 */
+ opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
const opus_int order /* I Prediction order */
)
{
opus_int k, n, mult2Q;
- opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
+ opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA;
+ opus_int32 *Aold_QA, *Anew_QA;
- invGain_Q30 = SILK_FIX_CONST( 1, 30 );
+ Anew_QA = A_QA[ order & 1 ];
+
+ invGain_Q30 = (opus_int32)1 << 30;
for( k = order - 1; k > 0; k-- ) {
/* Check for stability */
- if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
+ if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) {
return 0;
}
/* Set RC equal to negated AR coef */
- rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
+ rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA );
/* rc_mult1_Q30 range: [ 1 : 2^30 ] */
- rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
+ rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
+ /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
+ mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
+ rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
+
/* Update inverse gain */
/* invGain_Q30 range: [ 0 : 2^30 ] */
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
silk_assert( invGain_Q30 >= 0 );
silk_assert( invGain_Q30 <= ( 1 << 30 ) );
- if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
- return 0;
- }
- /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
- mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
- rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
+ /* Swap pointers */
+ Aold_QA = Anew_QA;
+ Anew_QA = A_QA[ k & 1 ];
/* Update AR coefficient */
- for( n = 0; n < (k + 1) >> 1; n++ ) {
- opus_int64 tmp64;
- tmp1 = A_QA[ n ];
- tmp2 = A_QA[ k - n - 1 ];
- tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
- MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
- if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
- return 0;
- }
- A_QA[ n ] = ( opus_int32 )tmp64;
- tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
- MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
- if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
- return 0;
- }
- A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
+ for( n = 0; n < k; n++ ) {
+ tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 );
+ Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q );
}
}
/* Check for stability */
- if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
+ if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
return 0;
}
/* Set RC equal to negated AR coef */
- rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
+ rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA );
/* Range: [ 1 : 2^30 ] */
- rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
+ rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
/* Update inverse gain */
/* Range: [ 0 : 2^30 ] */
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
- silk_assert( invGain_Q30 >= 0 );
- silk_assert( invGain_Q30 <= ( 1 << 30 ) );
- if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
- return 0;
- }
+ silk_assert( invGain_Q30 >= 0 );
+ silk_assert( invGain_Q30 <= 1<<30 );
return invGain_Q30;
}
/* For input in Q12 domain */
-opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
+opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
const opus_int order /* I Prediction order */
)
{
opus_int k;
- opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
+ opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
+ opus_int32 *Anew_QA;
opus_int32 DC_resp = 0;
+ Anew_QA = Atmp_QA[ order & 1 ];
+
/* Increase Q domain of the AR coefficients */
for( k = 0; k < order; k++ ) {
DC_resp += (opus_int32)A_Q12[ k ];
- Atmp_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
+ Anew_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
}
/* If the DC is unstable, we don't even need to do the full calculations */
if( DC_resp >= 4096 ) {
return 0;
}
- return LPC_inverse_pred_gain_QA_c( Atmp_QA, order );
+ return LPC_inverse_pred_gain_QA( Atmp_QA, order );
}
+
+#ifdef FIXED_POINT
+
+/* For input in Q24 domain */
+opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */
+ const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
+ const opus_int order /* I Prediction order */
+)
+{
+ opus_int k;
+ opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
+ opus_int32 *Anew_QA;
+
+ Anew_QA = Atmp_QA[ order & 1 ];
+
+ /* Increase Q domain of the AR coefficients */
+ for( k = 0; k < order; k++ ) {
+ Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA );
+ }
+
+ return LPC_inverse_pred_gain_QA( Atmp_QA, order );
+}
+#endif
diff --git a/thirdparty/opus/silk/LP_variable_cutoff.c b/thirdparty/opus/silk/LP_variable_cutoff.c
index 79112ad354..f639e1f899 100644
--- a/thirdparty/opus/silk/LP_variable_cutoff.c
+++ b/thirdparty/opus/silk/LP_variable_cutoff.c
@@ -130,6 +130,6 @@ void silk_LP_variable_cutoff(
/* ARMA low-pass filtering */
silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
- silk_biquad_alt_stride1( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length);
+ silk_biquad_alt( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1);
}
}
diff --git a/thirdparty/opus/silk/MacroCount.h b/thirdparty/opus/silk/MacroCount.h
index 78100ffede..834817d058 100644
--- a/thirdparty/opus/silk/MacroCount.h
+++ b/thirdparty/opus/silk/MacroCount.h
@@ -319,6 +319,14 @@ static OPUS_INLINE opus_int32 silk_ADD_POS_SAT32(opus_int64 a, opus_int64 b){
return(tmp);
}
+#undef silk_ADD_POS_SAT64
+static OPUS_INLINE opus_int64 silk_ADD_POS_SAT64(opus_int64 a, opus_int64 b){
+ opus_int64 tmp;
+ ops_count += 1;
+ tmp = ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)));
+ return(tmp);
+}
+
#undef silk_LSHIFT8
static OPUS_INLINE opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){
opus_int8 ret;
@@ -691,7 +699,7 @@ return(ret);
#undef silk_LIMIT_32
-static OPUS_INLINE opus_int32 silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
+static OPUS_INLINE opus_int silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
{
opus_int32 ret;
ops_count += 6;
diff --git a/thirdparty/opus/silk/MacroDebug.h b/thirdparty/opus/silk/MacroDebug.h
index 8dd4ce2ee2..35aedc5c5f 100644
--- a/thirdparty/opus/silk/MacroDebug.h
+++ b/thirdparty/opus/silk/MacroDebug.h
@@ -539,7 +539,8 @@ static OPUS_INLINE opus_int32 silk_DIV32_16_(opus_int32 a32, opus_int32 b32, cha
no checking needed for silk_POS_SAT32
no checking needed for silk_ADD_POS_SAT8
no checking needed for silk_ADD_POS_SAT16
- no checking needed for silk_ADD_POS_SAT32 */
+ no checking needed for silk_ADD_POS_SAT32
+ no checking needed for silk_ADD_POS_SAT64 */
#undef silk_LSHIFT8
#define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__)
diff --git a/thirdparty/opus/silk/NLSF2A.c b/thirdparty/opus/silk/NLSF2A.c
index d5b7730638..b1c559ea68 100644
--- a/thirdparty/opus/silk/NLSF2A.c
+++ b/thirdparty/opus/silk/NLSF2A.c
@@ -66,8 +66,7 @@ static OPUS_INLINE void silk_NLSF2A_find_poly(
void silk_NLSF2A(
opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
- const opus_int d, /* I filter order (should be even) */
- int arch /* I Run-time architecture */
+ const opus_int d /* I filter order (should be even) */
)
{
/* This ordering was found to maximize quality. It improves numerical accuracy of
@@ -84,14 +83,15 @@ void silk_NLSF2A(
opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
+ opus_int32 maxabs, absval, idx=0, sc_Q16;
silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
- celt_assert( d==10 || d==16 );
+ silk_assert( d==10||d==16 );
/* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
ordering = d == 16 ? ordering16 : ordering10;
for( k = 0; k < d; k++ ) {
- silk_assert( NLSF[k] >= 0 );
+ silk_assert(NLSF[k] >= 0 );
/* f_int on a scale 0-127 (rounded down) */
f_int = silk_RSHIFT( NLSF[k], 15 - 7 );
@@ -126,15 +126,52 @@ void silk_NLSF2A(
a32_QA1[ d-k-1 ] = Qtmp - Ptmp; /* QA+1 */
}
- /* Convert int32 coefficients to Q12 int16 coefs */
- silk_LPC_fit( a_Q12, a32_QA1, 12, QA + 1, d );
+ /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
+ for( i = 0; i < 10; i++ ) {
+ /* Find maximum absolute value and its index */
+ maxabs = 0;
+ for( k = 0; k < d; k++ ) {
+ absval = silk_abs( a32_QA1[k] );
+ if( absval > maxabs ) {
+ maxabs = absval;
+ idx = k;
+ }
+ }
+ maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */
+
+ if( maxabs > silk_int16_MAX ) {
+ /* Reduce magnitude of prediction coefficients */
+ maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
+ sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
+ silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
+ silk_bwexpander_32( a32_QA1, d, sc_Q16 );
+ } else {
+ break;
+ }
+ }
- for( i = 0; silk_LPC_inverse_pred_gain( a_Q12, d, arch ) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
- /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
- /* on the unscaled coefficients, convert to Q12 and measure again */
- silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
+ if( i == 10 ) {
+ /* Reached the last iteration, clip the coefficients */
for( k = 0; k < d; k++ ) {
- a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
+ a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */
+ a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 );
+ }
+ } else {
+ for( k = 0; k < d; k++ ) {
+ a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
+ }
+ }
+
+ for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
+ if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+ /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
+ /* on the unscaled coefficients, convert to Q12 and measure again */
+ silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
+ for( k = 0; k < d; k++ ) {
+ a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
+ }
+ } else {
+ break;
}
}
}
diff --git a/thirdparty/opus/silk/NLSF_VQ.c b/thirdparty/opus/silk/NLSF_VQ.c
index b83182a79c..69b6e22e18 100644
--- a/thirdparty/opus/silk/NLSF_VQ.c
+++ b/thirdparty/opus/silk/NLSF_VQ.c
@@ -33,44 +33,36 @@ POSSIBILITY OF SUCH DAMAGE.
/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */
void silk_NLSF_VQ(
- opus_int32 err_Q24[], /* O Quantization errors [K] */
+ opus_int32 err_Q26[], /* O Quantization errors [K] */
const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */
const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */
- const opus_int16 pWght_Q9[], /* I Codebook weights [K*LPC_order] */
const opus_int K, /* I Number of codebook vectors */
const opus_int LPC_order /* I Number of LPCs */
)
{
- opus_int i, m;
- opus_int32 diff_Q15, diffw_Q24, sum_error_Q24, pred_Q24;
- const opus_int16 *w_Q9_ptr;
- const opus_uint8 *cb_Q8_ptr;
+ opus_int i, m;
+ opus_int32 diff_Q15, sum_error_Q30, sum_error_Q26;
- celt_assert( ( LPC_order & 1 ) == 0 );
+ silk_assert( LPC_order <= 16 );
+ silk_assert( ( LPC_order & 1 ) == 0 );
/* Loop over codebook */
- cb_Q8_ptr = pCB_Q8;
- w_Q9_ptr = pWght_Q9;
for( i = 0; i < K; i++ ) {
- sum_error_Q24 = 0;
- pred_Q24 = 0;
- for( m = LPC_order-2; m >= 0; m -= 2 ) {
- /* Compute weighted absolute predictive quantization error for index m + 1 */
- diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m + 1 ], (opus_int32)cb_Q8_ptr[ m + 1 ], 7 ); /* range: [ -32767 : 32767 ]*/
- diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m + 1 ] );
- sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) );
- pred_Q24 = diffw_Q24;
+ sum_error_Q26 = 0;
+ for( m = 0; m < LPC_order; m += 2 ) {
+ /* Compute weighted squared quantization error for index m */
+ diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
+ sum_error_Q30 = silk_SMULBB( diff_Q15, diff_Q15 );
- /* Compute weighted absolute predictive quantization error for index m */
- diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)cb_Q8_ptr[ m ], 7 ); /* range: [ -32767 : 32767 ]*/
- diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m ] );
- sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) );
- pred_Q24 = diffw_Q24;
+ /* Compute weighted squared quantization error for index m + 1 */
+ diff_Q15 = silk_SUB_LSHIFT32( in_Q15[m + 1], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
+ sum_error_Q30 = silk_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 );
- silk_assert( sum_error_Q24 >= 0 );
+ sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 );
+
+ silk_assert( sum_error_Q26 >= 0 );
+ silk_assert( sum_error_Q30 >= 0 );
}
- err_Q24[ i ] = sum_error_Q24;
- cb_Q8_ptr += LPC_order;
- w_Q9_ptr += LPC_order;
+ err_Q26[ i ] = sum_error_Q26;
}
}
diff --git a/thirdparty/opus/silk/NLSF_VQ_weights_laroia.c b/thirdparty/opus/silk/NLSF_VQ_weights_laroia.c
index 9873bcde10..04894c59ab 100644
--- a/thirdparty/opus/silk/NLSF_VQ_weights_laroia.c
+++ b/thirdparty/opus/silk/NLSF_VQ_weights_laroia.c
@@ -48,8 +48,8 @@ void silk_NLSF_VQ_weights_laroia(
opus_int k;
opus_int32 tmp1_int, tmp2_int;
- celt_assert( D > 0 );
- celt_assert( ( D & 1 ) == 0 );
+ silk_assert( D > 0 );
+ silk_assert( ( D & 1 ) == 0 );
/* First value */
tmp1_int = silk_max_int( pNLSF_Q15[ 0 ], 1 );
diff --git a/thirdparty/opus/silk/NLSF_decode.c b/thirdparty/opus/silk/NLSF_decode.c
index eeb0ba8c92..9f715060b8 100644
--- a/thirdparty/opus/silk/NLSF_decode.c
+++ b/thirdparty/opus/silk/NLSF_decode.c
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main.h"
/* Predictive dequantizer for NLSF residuals */
-static OPUS_INLINE void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */
+static OPUS_INLINE void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */
opus_int16 x_Q10[], /* O Output [ order ] */
const opus_int8 indices[], /* I Quantization indices [ order ] */
const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */
@@ -70,9 +70,15 @@ void silk_NLSF_decode(
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
opus_int16 ec_ix[ MAX_LPC_ORDER ];
opus_int16 res_Q10[ MAX_LPC_ORDER ];
- opus_int32 NLSF_Q15_tmp;
+ opus_int16 W_tmp_QW[ MAX_LPC_ORDER ];
+ opus_int32 W_tmp_Q9, NLSF_Q15_tmp;
const opus_uint8 *pCB_element;
- const opus_int16 *pCB_Wght_Q9;
+
+ /* Decode first stage */
+ pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
+ for( i = 0; i < psNLSF_CB->order; i++ ) {
+ pNLSF_Q15[ i ] = silk_LSHIFT( (opus_int16)pCB_element[ i ], 7 );
+ }
/* Unpack entropy table indices and predictor for current CB1 index */
silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] );
@@ -80,11 +86,13 @@ void silk_NLSF_decode(
/* Predictive residual dequantizer */
silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order );
- /* Apply inverse square-rooted weights to first stage and add to output */
- pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
- pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
+ /* Weights from codebook vector */
+ silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order );
+
+ /* Apply inverse square-rooted weights and add to output */
for( i = 0; i < psNLSF_CB->order; i++ ) {
- NLSF_Q15_tmp = silk_ADD_LSHIFT32( silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), pCB_Wght_Q9[ i ] ), (opus_int16)pCB_element[ i ], 7 );
+ W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
+ NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), W_tmp_Q9 ) );
pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 );
}
diff --git a/thirdparty/opus/silk/NLSF_del_dec_quant.c b/thirdparty/opus/silk/NLSF_del_dec_quant.c
index 44a16acd0b..de88fee060 100644
--- a/thirdparty/opus/silk/NLSF_del_dec_quant.c
+++ b/thirdparty/opus/silk/NLSF_del_dec_quant.c
@@ -84,7 +84,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
nStates = 1;
RD_Q25[ 0 ] = 0;
prev_out_Q10[ 0 ] = 0;
- for( i = order - 1; i >= 0; i-- ) {
+ for( i = order - 1; ; i-- ) {
rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ];
in_Q10 = x_Q10[ i ];
for( j = 0; j < nStates; j++ ) {
@@ -131,7 +131,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
RD_Q25[ j + nStates ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 );
}
- if( nStates <= NLSF_QUANT_DEL_DEC_STATES/2 ) {
+ if( nStates <= ( NLSF_QUANT_DEL_DEC_STATES >> 1 ) ) {
/* double number of states and copy */
for( j = 0; j < nStates; j++ ) {
ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1;
@@ -140,7 +140,7 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
ind[ j ][ i ] = ind[ j - nStates ][ i ];
}
- } else {
+ } else if( i > 0 ) {
/* sort lower and upper half of RD_Q25, pairwise */
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) {
@@ -191,6 +191,8 @@ opus_int32 silk_NLSF_del_dec_quant( /* O Returns
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
ind[ j ][ i ] += silk_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 );
}
+ } else { /* i == 0 */
+ break;
}
}
diff --git a/thirdparty/opus/silk/NLSF_encode.c b/thirdparty/opus/silk/NLSF_encode.c
index 01ac7db78c..f03c3f1c35 100644
--- a/thirdparty/opus/silk/NLSF_encode.c
+++ b/thirdparty/opus/silk/NLSF_encode.c
@@ -37,9 +37,9 @@ POSSIBILITY OF SUCH DAMAGE.
/***********************/
opus_int32 silk_NLSF_encode( /* O Returns RD value in Q25 */
opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
- opus_int16 *pNLSF_Q15, /* I/O (Un)quantized NLSF vector [ LPC_ORDER ] */
+ opus_int16 *pNLSF_Q15, /* I/O Quantized NLSF vector [ LPC_ORDER ] */
const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
- const opus_int16 *pW_Q2, /* I NLSF weight vector [ LPC_ORDER ] */
+ const opus_int16 *pW_QW, /* I NLSF weight vector [ LPC_ORDER ] */
const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */
const opus_int nSurvivors, /* I Max survivors after first stage */
const opus_int signalType /* I Signal type: 0/1/2 */
@@ -47,32 +47,34 @@ opus_int32 silk_NLSF_encode( /* O Returns
{
opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7;
opus_int32 W_tmp_Q9, ret;
- VARDECL( opus_int32, err_Q24 );
+ VARDECL( opus_int32, err_Q26 );
VARDECL( opus_int32, RD_Q25 );
VARDECL( opus_int, tempIndices1 );
VARDECL( opus_int8, tempIndices2 );
+ opus_int16 res_Q15[ MAX_LPC_ORDER ];
opus_int16 res_Q10[ MAX_LPC_ORDER ];
opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ];
+ opus_int16 W_tmp_QW[ MAX_LPC_ORDER ];
opus_int16 W_adj_Q5[ MAX_LPC_ORDER ];
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
opus_int16 ec_ix[ MAX_LPC_ORDER ];
const opus_uint8 *pCB_element, *iCDF_ptr;
- const opus_int16 *pCB_Wght_Q9;
SAVE_STACK;
- celt_assert( signalType >= 0 && signalType <= 2 );
+ silk_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS );
+ silk_assert( signalType >= 0 && signalType <= 2 );
silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 );
/* NLSF stabilization */
silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
/* First stage: VQ */
- ALLOC( err_Q24, psNLSF_CB->nVectors, opus_int32 );
- silk_NLSF_VQ( err_Q24, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->CB1_Wght_Q9, psNLSF_CB->nVectors, psNLSF_CB->order );
+ ALLOC( err_Q26, psNLSF_CB->nVectors, opus_int32 );
+ silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order );
/* Sort the quantization errors */
ALLOC( tempIndices1, nSurvivors, opus_int );
- silk_insertion_sort_increasing( err_Q24, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
+ silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
ALLOC( RD_Q25, nSurvivors, opus_int32 );
ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 );
@@ -83,12 +85,23 @@ opus_int32 silk_NLSF_encode( /* O Returns
/* Residual after first stage */
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ];
- pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ ind1 * psNLSF_CB->order ];
for( i = 0; i < psNLSF_CB->order; i++ ) {
NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 );
- W_tmp_Q9 = pCB_Wght_Q9[ i ];
- res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ], W_tmp_Q9 ), 14 );
- W_adj_Q5[ i ] = silk_DIV32_varQ( (opus_int32)pW_Q2[ i ], silk_SMULBB( W_tmp_Q9, W_tmp_Q9 ), 21 );
+ res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ];
+ }
+
+ /* Weights from codebook vector */
+ silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order );
+
+ /* Apply square-rooted weights */
+ for( i = 0; i < psNLSF_CB->order; i++ ) {
+ W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
+ res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 );
+ }
+
+ /* Modify input weights accordingly */
+ for( i = 0; i < psNLSF_CB->order; i++ ) {
+ W_adj_Q5[ i ] = silk_DIV32_16( silk_LSHIFT( (opus_int32)pW_QW[ i ], 5 ), W_tmp_QW[ i ] );
}
/* Unpack entropy table indices and predictor for current CB1 index */
diff --git a/thirdparty/opus/silk/NSQ.c b/thirdparty/opus/silk/NSQ.c
index 1d64d8e257..43e3fee7e0 100644
--- a/thirdparty/opus/silk/NSQ.c
+++ b/thirdparty/opus/silk/NSQ.c
@@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
static OPUS_INLINE void silk_nsq_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
- const opus_int16 x16[], /* I input */
+ const opus_int32 x_Q3[], /* I input in Q3 */
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
@@ -75,14 +75,14 @@ static OPUS_INLINE void silk_noise_shape_quantizer(
void silk_NSQ_c
(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int16 x16[], /* I Input */
+ const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
@@ -117,7 +117,8 @@ void silk_NSQ_c
LSF_interpolation_flag = 1;
}
- ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+ ALLOC( sLTP_Q15,
+ psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
/* Set up pointers to start of sub frame */
@@ -127,7 +128,7 @@ void silk_NSQ_c
for( k = 0; k < psEncC->nb_subfr; k++ ) {
A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
- AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
+ AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
@@ -143,7 +144,7 @@ void silk_NSQ_c
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- celt_assert( start_idx > 0 );
+ silk_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
@@ -153,13 +154,13 @@ void silk_NSQ_c
}
}
- silk_nsq_scale_states( psEncC, NSQ, x16, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
+ silk_nsq_scale_states( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder, psEncC->arch );
- x16 += psEncC->subfr_length;
+ x_Q3 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
@@ -168,6 +169,7 @@ void silk_NSQ_c
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech and noise shaping signals */
+ /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
@@ -247,15 +249,15 @@ void silk_noise_shape_quantizer(
}
/* Noise shape feedback */
- celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
- n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(&NSQ->sDiff_shp_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
+ silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
+ n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(psLPC_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 );
n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 );
- celt_assert( lag > 0 || signalType != TYPE_VOICED );
+ silk_assert( lag > 0 || signalType != TYPE_VOICED );
/* Combine prediction and noise shaping signals */
tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */
@@ -277,27 +279,14 @@ void silk_noise_shape_quantizer(
r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Flip sign depending on dither */
- if( NSQ->rand_seed < 0 ) {
- r_Q10 = -r_Q10;
+ if ( NSQ->rand_seed < 0 ) {
+ r_Q10 = -r_Q10;
}
r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
- if (Lambda_Q10 > 2048) {
- /* For aggressive RDO, the bias becomes more than one pulse. */
- int rdo_offset = Lambda_Q10/2 - 512;
- if (q1_Q10 > rdo_offset) {
- q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
- } else if (q1_Q10 < -rdo_offset) {
- q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
- } else if (q1_Q10 < 0) {
- q1_Q0 = -1;
- } else {
- q1_Q0 = 0;
- }
- }
if( q1_Q0 > 0 ) {
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
@@ -348,8 +337,7 @@ void silk_noise_shape_quantizer(
/* Update states */
psLPC_Q14++;
*psLPC_Q14 = xq_Q14;
- NSQ->sDiff_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_sc_Q10[ i ], 4 );
- sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( NSQ->sDiff_shp_Q14, n_AR_Q12, 2 );
+ sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 );
NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14;
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 );
@@ -368,7 +356,7 @@ void silk_noise_shape_quantizer(
static OPUS_INLINE void silk_nsq_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
- const opus_int16 x16[], /* I input */
+ const opus_int32 x_Q3[], /* I input in Q3 */
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
@@ -380,18 +368,28 @@ static OPUS_INLINE void silk_nsq_scale_states(
)
{
opus_int i, lag;
- opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
+ opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
lag = pitchL[ subfr ];
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
silk_assert( inv_gain_Q31 != 0 );
+ /* Calculate gain adjustment factor */
+ if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+ gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
+ } else {
+ gain_adj_Q16 = (opus_int32)1 << 16;
+ }
+
/* Scale input */
- inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
+ inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
for( i = 0; i < psEncC->subfr_length; i++ ) {
- x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
+ x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
}
+ /* Save inverse gain */
+ NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
+
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
if( subfr == 0 ) {
@@ -405,9 +403,7 @@ static OPUS_INLINE void silk_nsq_scale_states(
}
/* Adjust for changing gain */
- if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
- gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
-
+ if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
/* Scale long-term shaping state */
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
@@ -421,7 +417,6 @@ static OPUS_INLINE void silk_nsq_scale_states(
}
NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 );
- NSQ->sDiff_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sDiff_shp_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
@@ -430,8 +425,5 @@ static OPUS_INLINE void silk_nsq_scale_states(
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
}
-
- /* Save inverse gain */
- NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
}
}
diff --git a/thirdparty/opus/silk/NSQ_del_dec.c b/thirdparty/opus/silk/NSQ_del_dec.c
index 3fd9fa0d5b..ab6feeac98 100644
--- a/thirdparty/opus/silk/NSQ_del_dec.c
+++ b/thirdparty/opus/silk/NSQ_del_dec.c
@@ -43,7 +43,6 @@ typedef struct {
opus_int32 Shape_Q14[ DECISION_DELAY ];
opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
opus_int32 LF_AR_Q14;
- opus_int32 Diff_Q14;
opus_int32 Seed;
opus_int32 SeedInit;
opus_int32 RD_Q10;
@@ -54,7 +53,6 @@ typedef struct {
opus_int32 RD_Q10;
opus_int32 xq_Q14;
opus_int32 LF_AR_Q14;
- opus_int32 Diff_Q14;
opus_int32 sLTP_shp_Q14;
opus_int32 LPC_exc_Q14;
} NSQ_sample_struct;
@@ -68,7 +66,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
- const opus_int16 x16[], /* I Input */
+ const opus_int32 x_Q3[], /* I Input in Q3 */
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
@@ -109,20 +107,20 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
+ opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
opus_int decisionDelay, /* I */
int arch /* I */
);
void silk_NSQ_del_dec_c(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int16 x16[], /* I Input */
+ const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
@@ -161,7 +159,6 @@ void silk_NSQ_del_dec_c(
psDD->SeedInit = psDD->Seed;
psDD->RD_Q10 = 0;
psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14;
- psDD->Diff_Q14 = NSQ->sDiff_shp_Q14;
psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ];
silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) );
@@ -189,7 +186,8 @@ void silk_NSQ_del_dec_c(
LSF_interpolation_flag = 1;
}
- ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+ ALLOC( sLTP_Q15,
+ psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
@@ -201,7 +199,7 @@ void silk_NSQ_del_dec_c(
for( k = 0; k < psEncC->nb_subfr; k++ ) {
A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
- AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
+ AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
@@ -237,8 +235,7 @@ void silk_NSQ_del_dec_c(
psDD = &psDelDec[ Winner_ind ];
last_smple_idx = smpl_buf_idx + decisionDelay;
for( i = 0; i < decisionDelay; i++ ) {
- last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
- if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
+ last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) );
@@ -250,7 +247,7 @@ void silk_NSQ_del_dec_c(
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- celt_assert( start_idx > 0 );
+ silk_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
@@ -260,7 +257,7 @@ void silk_NSQ_del_dec_c(
}
}
- silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x16, x_sc_Q10, sLTP, sLTP_Q15, k,
+ silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k,
psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
@@ -268,7 +265,7 @@ void silk_NSQ_del_dec_c(
Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay, psEncC->arch );
- x16 += psEncC->subfr_length;
+ x_Q3 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
@@ -289,9 +286,7 @@ void silk_NSQ_del_dec_c(
last_smple_idx = smpl_buf_idx + decisionDelay;
Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
for( i = 0; i < decisionDelay; i++ ) {
- last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
- if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
-
+ last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) );
@@ -302,10 +297,10 @@ void silk_NSQ_del_dec_c(
/* Update states */
NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14;
- NSQ->sDiff_shp_Q14 = psDD->Diff_Q14;
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech signal */
+ /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
@@ -340,7 +335,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
+ opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
opus_int decisionDelay, /* I */
int arch /* I */
)
@@ -361,7 +356,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
NSQ_sample_struct *psSS;
SAVE_STACK;
- celt_assert( nStatesDelayedDecision > 0 );
+ silk_assert( nStatesDelayedDecision > 0 );
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
@@ -419,9 +414,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */
/* Noise shape feedback */
- celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
+ silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
/* Output of lowpass section */
- tmp2 = silk_SMLAWB( psDD->Diff_Q14, psDD->sAR2_Q14[ 0 ], warping_Q16 );
+ tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 );
/* Output of allpass section */
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
psDD->sAR2_Q14[ 0 ] = tmp2;
@@ -467,19 +462,6 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
- if (Lambda_Q10 > 2048) {
- /* For aggressive RDO, the bias becomes more than one pulse. */
- int rdo_offset = Lambda_Q10/2 - 512;
- if (q1_Q10 > rdo_offset) {
- q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
- } else if (q1_Q10 < -rdo_offset) {
- q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
- } else if (q1_Q10 < 0) {
- q1_Q0 = -1;
- } else {
- q1_Q0 = 0;
- }
- }
if( q1_Q0 > 0 ) {
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
@@ -533,8 +515,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
- psSS[ 0 ].Diff_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
- sLF_AR_shp_Q14 = silk_SUB32( psSS[ 0 ].Diff_Q14, n_AR_Q14 );
+ sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14;
@@ -548,22 +529,21 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
exc_Q14 = -exc_Q14;
}
+
/* Add predictions */
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
- psSS[ 1 ].Diff_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
- sLF_AR_shp_Q14 = silk_SUB32( psSS[ 1 ].Diff_Q14, n_AR_Q14 );
+ sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 );
psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 1 ].xq_Q14 = xq_Q14;
}
- *smpl_buf_idx = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
- if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
- last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
+ *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
+ last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
/* Find winner */
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
@@ -627,7 +607,6 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
psDD = &psDelDec[ k ];
psSS = &psSampleState[ k ][ 0 ];
psDD->LF_AR_Q14 = psSS->LF_AR_Q14;
- psDD->Diff_Q14 = psSS->Diff_Q14;
psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14;
psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10;
@@ -652,7 +631,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
- const opus_int16 x16[], /* I Input */
+ const opus_int32 x_Q3[], /* I Input in Q3 */
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
@@ -666,19 +645,29 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
)
{
opus_int i, k, lag;
- opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
+ opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
NSQ_del_dec_struct *psDD;
lag = pitchL[ subfr ];
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
silk_assert( inv_gain_Q31 != 0 );
+ /* Calculate gain adjustment factor */
+ if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+ gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
+ } else {
+ gain_adj_Q16 = (opus_int32)1 << 16;
+ }
+
/* Scale input */
- inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
+ inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
for( i = 0; i < psEncC->subfr_length; i++ ) {
- x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
+ x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
}
+ /* Save inverse gain */
+ NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
+
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
if( subfr == 0 ) {
@@ -692,9 +681,7 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
}
/* Adjust for changing gain */
- if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
- gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
-
+ if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
/* Scale long-term shaping state */
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
@@ -712,7 +699,6 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
/* Scale scalar states */
psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 );
- psDD->Diff_Q14 = silk_SMULWW( gain_adj_Q16, psDD->Diff_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
@@ -726,8 +712,5 @@ static OPUS_INLINE void silk_nsq_del_dec_scale_states(
psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] );
}
}
-
- /* Save inverse gain */
- NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
}
}
diff --git a/thirdparty/opus/silk/PLC.c b/thirdparty/opus/silk/PLC.c
index f89391651c..fb6ea887b7 100644
--- a/thirdparty/opus/silk/PLC.c
+++ b/thirdparty/opus/silk/PLC.c
@@ -275,7 +275,7 @@ static OPUS_INLINE void silk_PLC_conceal(
/* Reduce random noise for unvoiced frames with high LPC gain */
opus_int32 invGain_Q30, down_scale_Q30;
- invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch );
+ invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order );
down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
@@ -291,7 +291,7 @@ static OPUS_INLINE void silk_PLC_conceal(
/* Rewhiten LTP state */
idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
- celt_assert( idx > 0 );
+ silk_assert( idx > 0 );
silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch );
/* Scale LTP state */
inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
@@ -328,10 +328,8 @@ static OPUS_INLINE void silk_PLC_conceal(
for( j = 0; j < LTP_ORDER; j++ ) {
B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
}
- if ( psDec->indices.signalType != TYPE_NO_VOICE_ACTIVITY ) {
- /* Gradually reduce excitation gain */
- rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
- }
+ /* Gradually reduce excitation gain */
+ rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
/* Slowly increase pitch lag */
psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
@@ -347,7 +345,7 @@ static OPUS_INLINE void silk_PLC_conceal(
/* Copy LPC state */
silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
- celt_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
+ silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
for( i = 0; i < psDec->frame_length; i++ ) {
/* partly unrolled */
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
diff --git a/thirdparty/opus/silk/SigProc_FIX.h b/thirdparty/opus/silk/SigProc_FIX.h
index f9ae326326..b63299441e 100644
--- a/thirdparty/opus/silk/SigProc_FIX.h
+++ b/thirdparty/opus/silk/SigProc_FIX.h
@@ -35,7 +35,7 @@ extern "C"
/*#define silk_MACRO_COUNT */ /* Used to enable WMOPS counting */
-#define SILK_MAX_ORDER_LPC 24 /* max order of the LPC analysis in schur() and k2a() */
+#define SILK_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */
#include <string.h> /* for memset(), memcpy(), memmove() */
#include "typedef.h"
@@ -47,11 +47,6 @@ extern "C"
#include "x86/SigProc_FIX_sse.h"
#endif
-#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
-#include "arm/biquad_alt_arm.h"
-#include "arm/LPC_inv_pred_gain_arm.h"
-#endif
-
/********************************************************************/
/* SIGNAL PROCESSING FUNCTIONS */
/********************************************************************/
@@ -101,22 +96,14 @@ void silk_resampler_down2_3(
* slower than biquad() but uses more precise coefficients
* can handle (slowly) varying coefficients
*/
-void silk_biquad_alt_stride1(
+void silk_biquad_alt(
const opus_int16 *in, /* I input signal */
const opus_int32 *B_Q28, /* I MA coefficients [3] */
const opus_int32 *A_Q28, /* I AR coefficients [2] */
opus_int32 *S, /* I/O State vector [2] */
opus_int16 *out, /* O output signal */
- const opus_int32 len /* I signal length (must be even) */
-);
-
-void silk_biquad_alt_stride2_c(
- const opus_int16 *in, /* I input signal */
- const opus_int32 *B_Q28, /* I MA coefficients [3] */
- const opus_int32 *A_Q28, /* I AR coefficients [2] */
- opus_int32 *S, /* I/O State vector [4] */
- opus_int16 *out, /* O output signal */
- const opus_int32 len /* I signal length (must be even) */
+ const opus_int32 len, /* I signal length (must be even) */
+ opus_int stride /* I Operate on interleaved signal if > 1 */
);
/* Variable order MA prediction error filter. */
@@ -145,11 +132,17 @@ void silk_bwexpander_32(
/* Compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */
-opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
+opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
const opus_int order /* I Prediction order */
);
+/* For input in Q24 domain */
+opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */
+ const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
+ const opus_int order /* I Prediction order */
+);
+
/* Split signal in two decimated bands using first-order allpass filters */
void silk_ana_filt_bank_1(
const opus_int16 *in, /* I Input signal [N] */
@@ -159,14 +152,6 @@ void silk_ana_filt_bank_1(
const opus_int32 N /* I Number of input samples */
);
-#if !defined(OVERRIDE_silk_biquad_alt_stride2)
-#define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_c(in, B_Q28, A_Q28, S, out, len))
-#endif
-
-#if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
-#define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_c(A_Q12, order))
-#endif
-
/********************************************************************/
/* SCALAR FUNCTIONS */
/********************************************************************/
@@ -286,17 +271,7 @@ void silk_A2NLSF(
void silk_NLSF2A(
opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
- const opus_int d, /* I filter order (should be even) */
- int arch /* I Run-time architecture */
-);
-
-/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
-void silk_LPC_fit(
- opus_int16 *a_QOUT, /* O Output signal */
- opus_int32 *a_QIN, /* I/O Input signal */
- const opus_int QOUT, /* I Input Q domain */
- const opus_int QIN, /* I Input Q domain */
- const opus_int d /* I Filter order */
+ const opus_int d /* I filter order (should be even) */
);
void silk_insertion_sort_increasing(
@@ -496,7 +471,8 @@ static OPUS_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
/* Add with saturation for positive input values */
#define silk_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b)))
#define silk_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)))
-#define silk_ADD_POS_SAT32(a, b) ((((opus_uint32)(a)+(opus_uint32)(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
+#define silk_ADD_POS_SAT32(a, b) ((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
+#define silk_ADD_POS_SAT64(a, b) ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)))
#define silk_LSHIFT8(a, shift) ((opus_int8)((opus_uint8)(a)<<(shift))) /* shift >= 0, shift < 8 */
#define silk_LSHIFT16(a, shift) ((opus_int16)((opus_uint16)(a)<<(shift))) /* shift >= 0, shift < 16 */
@@ -596,9 +572,7 @@ static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
/* Make sure to store the result as the seed for the next call (also in between */
/* frames), otherwise result won't be random at all. When only using some of the */
/* bits, take the most significant bits by right-shifting. */
-#define RAND_MULTIPLIER 196314165
-#define RAND_INCREMENT 907633515
-#define silk_RAND(seed) (silk_MLA_ovflw((RAND_INCREMENT), (seed), (RAND_MULTIPLIER)))
+#define silk_RAND(seed) (silk_MLA_ovflw(907633515, (seed), 196314165))
/* Add some multiplication functions that can be easily mapped to ARM. */
diff --git a/thirdparty/opus/silk/VAD.c b/thirdparty/opus/silk/VAD.c
index d0cda52162..0a782af2f1 100644
--- a/thirdparty/opus/silk/VAD.c
+++ b/thirdparty/opus/silk/VAD.c
@@ -101,9 +101,9 @@ opus_int silk_VAD_GetSA_Q8_c( /* O Return v
/* Safety checks */
silk_assert( VAD_N_BANDS == 4 );
- celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
- celt_assert( psEncC->frame_length <= 512 );
- celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
+ silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
+ silk_assert( psEncC->frame_length <= 512 );
+ silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
/***********************/
/* Filter and Decimate */
@@ -252,14 +252,15 @@ opus_int silk_VAD_GetSA_Q8_c( /* O Return v
speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
}
- if( psEncC->frame_length == 20 * psEncC->fs_kHz ) {
- speech_nrg = silk_RSHIFT32( speech_nrg, 1 );
- }
/* Power scaling */
if( speech_nrg <= 0 ) {
SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
- } else if( speech_nrg < 16384 ) {
- speech_nrg = silk_LSHIFT32( speech_nrg, 16 );
+ } else if( speech_nrg < 32768 ) {
+ if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
+ speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 );
+ } else {
+ speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 );
+ }
/* square-root */
speech_nrg = silk_SQRT_APPROX( speech_nrg );
@@ -312,8 +313,6 @@ void silk_VAD_GetNoiseLevels(
/* Initially faster smoothing */
if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */
min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 );
- /* Increment frame counter */
- psSilk_VAD->counter++;
} else {
min_coef = 0;
}
@@ -357,4 +356,7 @@ void silk_VAD_GetNoiseLevels(
/* Store as part of state */
psSilk_VAD->NL[ k ] = nl;
}
+
+ /* Increment frame counter */
+ psSilk_VAD->counter++;
}
diff --git a/thirdparty/opus/silk/VQ_WMat_EC.c b/thirdparty/opus/silk/VQ_WMat_EC.c
index 0f3d545c4e..7983f1db80 100644
--- a/thirdparty/opus/silk/VQ_WMat_EC.c
+++ b/thirdparty/opus/silk/VQ_WMat_EC.c
@@ -34,95 +34,84 @@ POSSIBILITY OF SUCH DAMAGE.
/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
void silk_VQ_WMat_EC_c(
opus_int8 *ind, /* O index of best codebook vector */
- opus_int32 *res_nrg_Q15, /* O best residual energy */
- opus_int32 *rate_dist_Q8, /* O best total bitrate */
+ opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
- const opus_int32 *XX_Q17, /* I correlation matrix */
- const opus_int32 *xX_Q17, /* I correlation vector */
+ const opus_int16 *in_Q14, /* I input vector to be quantized */
+ const opus_int32 *W_Q18, /* I weighting matrix */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
- const opus_int subfr_len, /* I number of samples per subframe */
+ const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
- const opus_int L /* I number of vectors in codebook */
+ opus_int L /* I number of vectors in codebook */
)
{
opus_int k, gain_tmp_Q7;
const opus_int8 *cb_row_Q7;
- opus_int32 neg_xX_Q24[ 5 ];
- opus_int32 sum1_Q15, sum2_Q24;
- opus_int32 bits_res_Q8, bits_tot_Q8;
-
- /* Negate and convert to new Q domain */
- neg_xX_Q24[ 0 ] = -silk_LSHIFT32( xX_Q17[ 0 ], 7 );
- neg_xX_Q24[ 1 ] = -silk_LSHIFT32( xX_Q17[ 1 ], 7 );
- neg_xX_Q24[ 2 ] = -silk_LSHIFT32( xX_Q17[ 2 ], 7 );
- neg_xX_Q24[ 3 ] = -silk_LSHIFT32( xX_Q17[ 3 ], 7 );
- neg_xX_Q24[ 4 ] = -silk_LSHIFT32( xX_Q17[ 4 ], 7 );
+ opus_int16 diff_Q14[ 5 ];
+ opus_int32 sum1_Q14, sum2_Q16;
/* Loop over codebook */
- *rate_dist_Q8 = silk_int32_MAX;
- *res_nrg_Q15 = silk_int32_MAX;
+ *rate_dist_Q14 = silk_int32_MAX;
cb_row_Q7 = cb_Q7;
- /* In things go really bad, at least *ind is set to something safe. */
- *ind = 0;
for( k = 0; k < L; k++ ) {
- opus_int32 penalty;
gain_tmp_Q7 = cb_gain_Q7[k];
+
+ diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 );
+ diff_Q14[ 1 ] = in_Q14[ 1 ] - silk_LSHIFT( cb_row_Q7[ 1 ], 7 );
+ diff_Q14[ 2 ] = in_Q14[ 2 ] - silk_LSHIFT( cb_row_Q7[ 2 ], 7 );
+ diff_Q14[ 3 ] = in_Q14[ 3 ] - silk_LSHIFT( cb_row_Q7[ 3 ], 7 );
+ diff_Q14[ 4 ] = in_Q14[ 4 ] - silk_LSHIFT( cb_row_Q7[ 4 ], 7 );
+
/* Weighted rate */
- /* Quantization error: 1 - 2 * xX * cb + cb' * XX * cb */
- sum1_Q15 = SILK_FIX_CONST( 1.001, 15 );
+ sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] );
/* Penalty for too large gain */
- penalty = silk_LSHIFT32( silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 11 );
-
- /* first row of XX_Q17 */
- sum2_Q24 = silk_MLA( neg_xX_Q24[ 0 ], XX_Q17[ 1 ], cb_row_Q7[ 1 ] );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 2 ], cb_row_Q7[ 2 ] );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 3 ], cb_row_Q7[ 3 ] );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 4 ], cb_row_Q7[ 4 ] );
- sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 0 ], cb_row_Q7[ 0 ] );
- sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 0 ] );
-
- /* second row of XX_Q17 */
- sum2_Q24 = silk_MLA( neg_xX_Q24[ 1 ], XX_Q17[ 7 ], cb_row_Q7[ 2 ] );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 8 ], cb_row_Q7[ 3 ] );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 9 ], cb_row_Q7[ 4 ] );
- sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 6 ], cb_row_Q7[ 1 ] );
- sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 1 ] );
-
- /* third row of XX_Q17 */
- sum2_Q24 = silk_MLA( neg_xX_Q24[ 2 ], XX_Q17[ 13 ], cb_row_Q7[ 3 ] );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 14 ], cb_row_Q7[ 4 ] );
- sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 12 ], cb_row_Q7[ 2 ] );
- sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 2 ] );
-
- /* fourth row of XX_Q17 */
- sum2_Q24 = silk_MLA( neg_xX_Q24[ 3 ], XX_Q17[ 19 ], cb_row_Q7[ 4 ] );
- sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 18 ], cb_row_Q7[ 3 ] );
- sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 3 ] );
-
- /* last row of XX_Q17 */
- sum2_Q24 = silk_LSHIFT32( neg_xX_Q24[ 4 ], 1 );
- sum2_Q24 = silk_MLA( sum2_Q24, XX_Q17[ 24 ], cb_row_Q7[ 4 ] );
- sum1_Q15 = silk_SMLAWB( sum1_Q15, sum2_Q24, cb_row_Q7[ 4 ] );
+ sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 );
+
+ silk_assert( sum1_Q14 >= 0 );
+
+ /* first row of W_Q18 */
+ sum2_Q16 = silk_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] );
+ sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] );
+ sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] );
+ sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] );
+ sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
+ sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] );
+ sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] );
+
+ /* second row of W_Q18 */
+ sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] );
+ sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] );
+ sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] );
+ sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
+ sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] );
+ sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] );
+
+ /* third row of W_Q18 */
+ sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] );
+ sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] );
+ sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
+ sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] );
+ sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] );
+
+ /* fourth row of W_Q18 */
+ sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] );
+ sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
+ sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] );
+ sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] );
+
+ /* last row of W_Q18 */
+ sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] );
+ sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] );
+
+ silk_assert( sum1_Q14 >= 0 );
/* find best */
- if( sum1_Q15 >= 0 ) {
- /* Translate residual energy to bits using high-rate assumption (6 dB ==> 1 bit/sample) */
- bits_res_Q8 = silk_SMULBB( subfr_len, silk_lin2log( sum1_Q15 + penalty) - (15 << 7) );
- /* In the following line we reduce the codelength component by half ("-1"); seems to slghtly improve quality */
- bits_tot_Q8 = silk_ADD_LSHIFT32( bits_res_Q8, cl_Q5[ k ], 3-1 );
- if( bits_tot_Q8 <= *rate_dist_Q8 ) {
- *rate_dist_Q8 = bits_tot_Q8;
- *res_nrg_Q15 = sum1_Q15 + penalty;
- *ind = (opus_int8)k;
- *gain_Q7 = gain_tmp_Q7;
- }
+ if( sum1_Q14 < *rate_dist_Q14 ) {
+ *rate_dist_Q14 = sum1_Q14;
+ *ind = (opus_int8)k;
+ *gain_Q7 = gain_tmp_Q7;
}
/* Go to next cbk vector */
diff --git a/thirdparty/opus/silk/arm/LPC_inv_pred_gain_arm.h b/thirdparty/opus/silk/arm/LPC_inv_pred_gain_arm.h
deleted file mode 100644
index 9895b555c8..0000000000
--- a/thirdparty/opus/silk/arm/LPC_inv_pred_gain_arm.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/***********************************************************************
-Copyright (c) 2017 Google Inc.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifndef SILK_LPC_INV_PRED_GAIN_ARM_H
-# define SILK_LPC_INV_PRED_GAIN_ARM_H
-
-# include "celt/arm/armcpu.h"
-
-# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-opus_int32 silk_LPC_inverse_pred_gain_neon( /* O Returns inverse prediction gain in energy domain, Q30 */
- const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
- const opus_int order /* I Prediction order */
-);
-
-# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
-# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
-# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), PRESUME_NEON(silk_LPC_inverse_pred_gain)(A_Q12, order))
-# endif
-# endif
-
-# if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
-/*Is run-time CPU detection enabled on this platform?*/
-# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
-extern opus_int32 (*const SILK_LPC_INVERSE_PRED_GAIN_IMPL[OPUS_ARCHMASK+1])(const opus_int16 *A_Q12, const opus_int order);
-# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
-# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((*SILK_LPC_INVERSE_PRED_GAIN_IMPL[(arch)&OPUS_ARCHMASK])(A_Q12, order))
-# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
-# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
-# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_neon(A_Q12, order))
-# endif
-# endif
-
-#endif /* end SILK_LPC_INV_PRED_GAIN_ARM_H */
diff --git a/thirdparty/opus/silk/arm/LPC_inv_pred_gain_neon_intr.c b/thirdparty/opus/silk/arm/LPC_inv_pred_gain_neon_intr.c
deleted file mode 100644
index ab426bcd66..0000000000
--- a/thirdparty/opus/silk/arm/LPC_inv_pred_gain_neon_intr.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/***********************************************************************
-Copyright (c) 2017 Google Inc.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <arm_neon.h>
-#include "SigProc_FIX.h"
-#include "define.h"
-
-#define QA 24
-#define A_LIMIT SILK_FIX_CONST( 0.99975, QA )
-
-#define MUL32_FRAC_Q(a32, b32, Q) ((opus_int32)(silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q)))
-
-/* The difficulty is how to judge a 64-bit signed integer tmp64 is 32-bit overflowed,
- * since NEON has no 64-bit min, max or comparison instructions.
- * A failed idea is to compare the results of vmovn(tmp64) and vqmovn(tmp64) whether they are equal or not.
- * However, this idea fails when the tmp64 is something like 0xFFFFFFF980000000.
- * Here we know that mult2Q >= 1, so the highest bit (bit 63, sign bit) of tmp64 must equal to bit 62.
- * tmp64 was shifted left by 1 and we got tmp64'. If high_half(tmp64') != 0 and high_half(tmp64') != -1,
- * then we know that bit 31 to bit 63 of tmp64 can not all be the sign bit, and therefore tmp64 is 32-bit overflowed.
- * That is, we judge if tmp64' > 0x00000000FFFFFFFF, or tmp64' <= 0xFFFFFFFF00000000.
- * We use narrowing shift right 31 bits to tmp32' to save data bandwidth and instructions.
- * That is, we judge if tmp32' > 0x00000000, or tmp32' <= 0xFFFFFFFF.
- */
-
-/* Compute inverse of LPC prediction gain, and */
-/* test if LPC coefficients are stable (all poles within unit circle) */
-static OPUS_INLINE opus_int32 LPC_inverse_pred_gain_QA_neon( /* O Returns inverse prediction gain in energy domain, Q30 */
- opus_int32 A_QA[ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
- const opus_int order /* I Prediction order */
-)
-{
- opus_int k, n, mult2Q;
- opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
- opus_int32 max, min;
- int32x4_t max_s32x4, min_s32x4;
- int32x2_t max_s32x2, min_s32x2;
-
- max_s32x4 = vdupq_n_s32( silk_int32_MIN );
- min_s32x4 = vdupq_n_s32( silk_int32_MAX );
- invGain_Q30 = SILK_FIX_CONST( 1, 30 );
- for( k = order - 1; k > 0; k-- ) {
- int32x2_t rc_Q31_s32x2, rc_mult2_s32x2;
- int64x2_t mult2Q_s64x2;
-
- /* Check for stability */
- if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
- return 0;
- }
-
- /* Set RC equal to negated AR coef */
- rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
-
- /* rc_mult1_Q30 range: [ 1 : 2^30 ] */
- rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
- silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
- silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
-
- /* Update inverse gain */
- /* invGain_Q30 range: [ 0 : 2^30 ] */
- invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
- silk_assert( invGain_Q30 >= 0 );
- silk_assert( invGain_Q30 <= ( 1 << 30 ) );
- if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
- return 0;
- }
-
- /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
- mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
- rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
-
- /* Update AR coefficient */
- rc_Q31_s32x2 = vdup_n_s32( rc_Q31 );
- mult2Q_s64x2 = vdupq_n_s64( -mult2Q );
- rc_mult2_s32x2 = vdup_n_s32( rc_mult2 );
-
- for( n = 0; n < ( ( k + 1 ) >> 1 ) - 3; n += 4 ) {
- /* We always calculate extra elements of A_QA buffer when ( k % 4 ) != 0, to take the advantage of SIMD parallelization. */
- int32x4_t tmp1_s32x4, tmp2_s32x4, t0_s32x4, t1_s32x4, s0_s32x4, s1_s32x4, t_QA0_s32x4, t_QA1_s32x4;
- int64x2_t t0_s64x2, t1_s64x2, t2_s64x2, t3_s64x2;
- tmp1_s32x4 = vld1q_s32( A_QA + n );
- tmp2_s32x4 = vld1q_s32( A_QA + k - n - 4 );
- tmp2_s32x4 = vrev64q_s32( tmp2_s32x4 );
- tmp2_s32x4 = vcombine_s32( vget_high_s32( tmp2_s32x4 ), vget_low_s32( tmp2_s32x4 ) );
- t0_s32x4 = vqrdmulhq_lane_s32( tmp2_s32x4, rc_Q31_s32x2, 0 );
- t1_s32x4 = vqrdmulhq_lane_s32( tmp1_s32x4, rc_Q31_s32x2, 0 );
- t_QA0_s32x4 = vqsubq_s32( tmp1_s32x4, t0_s32x4 );
- t_QA1_s32x4 = vqsubq_s32( tmp2_s32x4, t1_s32x4 );
- t0_s64x2 = vmull_s32( vget_low_s32 ( t_QA0_s32x4 ), rc_mult2_s32x2 );
- t1_s64x2 = vmull_s32( vget_high_s32( t_QA0_s32x4 ), rc_mult2_s32x2 );
- t2_s64x2 = vmull_s32( vget_low_s32 ( t_QA1_s32x4 ), rc_mult2_s32x2 );
- t3_s64x2 = vmull_s32( vget_high_s32( t_QA1_s32x4 ), rc_mult2_s32x2 );
- t0_s64x2 = vrshlq_s64( t0_s64x2, mult2Q_s64x2 );
- t1_s64x2 = vrshlq_s64( t1_s64x2, mult2Q_s64x2 );
- t2_s64x2 = vrshlq_s64( t2_s64x2, mult2Q_s64x2 );
- t3_s64x2 = vrshlq_s64( t3_s64x2, mult2Q_s64x2 );
- t0_s32x4 = vcombine_s32( vmovn_s64( t0_s64x2 ), vmovn_s64( t1_s64x2 ) );
- t1_s32x4 = vcombine_s32( vmovn_s64( t2_s64x2 ), vmovn_s64( t3_s64x2 ) );
- s0_s32x4 = vcombine_s32( vshrn_n_s64( t0_s64x2, 31 ), vshrn_n_s64( t1_s64x2, 31 ) );
- s1_s32x4 = vcombine_s32( vshrn_n_s64( t2_s64x2, 31 ), vshrn_n_s64( t3_s64x2, 31 ) );
- max_s32x4 = vmaxq_s32( max_s32x4, s0_s32x4 );
- min_s32x4 = vminq_s32( min_s32x4, s0_s32x4 );
- max_s32x4 = vmaxq_s32( max_s32x4, s1_s32x4 );
- min_s32x4 = vminq_s32( min_s32x4, s1_s32x4 );
- t1_s32x4 = vrev64q_s32( t1_s32x4 );
- t1_s32x4 = vcombine_s32( vget_high_s32( t1_s32x4 ), vget_low_s32( t1_s32x4 ) );
- vst1q_s32( A_QA + n, t0_s32x4 );
- vst1q_s32( A_QA + k - n - 4, t1_s32x4 );
- }
- for( ; n < (k + 1) >> 1; n++ ) {
- opus_int64 tmp64;
- tmp1 = A_QA[ n ];
- tmp2 = A_QA[ k - n - 1 ];
- tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
- MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
- if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
- return 0;
- }
- A_QA[ n ] = ( opus_int32 )tmp64;
- tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
- MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
- if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
- return 0;
- }
- A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
- }
- }
-
- /* Check for stability */
- if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
- return 0;
- }
-
- max_s32x2 = vmax_s32( vget_low_s32( max_s32x4 ), vget_high_s32( max_s32x4 ) );
- min_s32x2 = vmin_s32( vget_low_s32( min_s32x4 ), vget_high_s32( min_s32x4 ) );
- max_s32x2 = vmax_s32( max_s32x2, vreinterpret_s32_s64( vshr_n_s64( vreinterpret_s64_s32( max_s32x2 ), 32 ) ) );
- min_s32x2 = vmin_s32( min_s32x2, vreinterpret_s32_s64( vshr_n_s64( vreinterpret_s64_s32( min_s32x2 ), 32 ) ) );
- max = vget_lane_s32( max_s32x2, 0 );
- min = vget_lane_s32( min_s32x2, 0 );
- if( ( max > 0 ) || ( min < -1 ) ) {
- return 0;
- }
-
- /* Set RC equal to negated AR coef */
- rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
-
- /* Range: [ 1 : 2^30 ] */
- rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
-
- /* Update inverse gain */
- /* Range: [ 0 : 2^30 ] */
- invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
- silk_assert( invGain_Q30 >= 0 );
- silk_assert( invGain_Q30 <= ( 1 << 30 ) );
- if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
- return 0;
- }
-
- return invGain_Q30;
-}
-
-/* For input in Q12 domain */
-opus_int32 silk_LPC_inverse_pred_gain_neon( /* O Returns inverse prediction gain in energy domain, Q30 */
- const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
- const opus_int order /* I Prediction order */
-)
-{
-#ifdef OPUS_CHECK_ASM
- const opus_int32 invGain_Q30_c = silk_LPC_inverse_pred_gain_c( A_Q12, order );
-#endif
-
- opus_int32 invGain_Q30;
- if( ( SILK_MAX_ORDER_LPC != 24 ) || ( order & 1 )) {
- invGain_Q30 = silk_LPC_inverse_pred_gain_c( A_Q12, order );
- }
- else {
- opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
- opus_int32 DC_resp;
- int16x8_t t0_s16x8, t1_s16x8, t2_s16x8;
- int32x4_t t0_s32x4;
- const opus_int leftover = order & 7;
-
- /* Increase Q domain of the AR coefficients */
- t0_s16x8 = vld1q_s16( A_Q12 + 0 );
- t1_s16x8 = vld1q_s16( A_Q12 + 8 );
- t2_s16x8 = vld1q_s16( A_Q12 + 16 );
- t0_s32x4 = vpaddlq_s16( t0_s16x8 );
-
- switch( order - leftover )
- {
- case 24:
- t0_s32x4 = vpadalq_s16( t0_s32x4, t2_s16x8 );
- /* FALLTHROUGH */
-
- case 16:
- t0_s32x4 = vpadalq_s16( t0_s32x4, t1_s16x8 );
- vst1q_s32( Atmp_QA + 16, vshll_n_s16( vget_low_s16 ( t2_s16x8 ), QA - 12 ) );
- vst1q_s32( Atmp_QA + 20, vshll_n_s16( vget_high_s16( t2_s16x8 ), QA - 12 ) );
- /* FALLTHROUGH */
-
- case 8:
- {
- const int32x2_t t_s32x2 = vpadd_s32( vget_low_s32( t0_s32x4 ), vget_high_s32( t0_s32x4 ) );
- const int64x1_t t_s64x1 = vpaddl_s32( t_s32x2 );
- DC_resp = vget_lane_s32( vreinterpret_s32_s64( t_s64x1 ), 0 );
- vst1q_s32( Atmp_QA + 8, vshll_n_s16( vget_low_s16 ( t1_s16x8 ), QA - 12 ) );
- vst1q_s32( Atmp_QA + 12, vshll_n_s16( vget_high_s16( t1_s16x8 ), QA - 12 ) );
- }
- break;
-
- default:
- DC_resp = 0;
- break;
- }
- A_Q12 += order - leftover;
-
- switch( leftover )
- {
- case 6:
- DC_resp += (opus_int32)A_Q12[ 5 ];
- DC_resp += (opus_int32)A_Q12[ 4 ];
- /* FALLTHROUGH */
-
- case 4:
- DC_resp += (opus_int32)A_Q12[ 3 ];
- DC_resp += (opus_int32)A_Q12[ 2 ];
- /* FALLTHROUGH */
-
- case 2:
- DC_resp += (opus_int32)A_Q12[ 1 ];
- DC_resp += (opus_int32)A_Q12[ 0 ];
- /* FALLTHROUGH */
-
- default:
- break;
- }
-
- /* If the DC is unstable, we don't even need to do the full calculations */
- if( DC_resp >= 4096 ) {
- invGain_Q30 = 0;
- } else {
- vst1q_s32( Atmp_QA + 0, vshll_n_s16( vget_low_s16 ( t0_s16x8 ), QA - 12 ) );
- vst1q_s32( Atmp_QA + 4, vshll_n_s16( vget_high_s16( t0_s16x8 ), QA - 12 ) );
- invGain_Q30 = LPC_inverse_pred_gain_QA_neon( Atmp_QA, order );
- }
- }
-
-#ifdef OPUS_CHECK_ASM
- silk_assert( invGain_Q30_c == invGain_Q30 );
-#endif
-
- return invGain_Q30;
-}
diff --git a/thirdparty/opus/silk/arm/NSQ_del_dec_arm.h b/thirdparty/opus/silk/arm/NSQ_del_dec_arm.h
deleted file mode 100644
index 9e76e16927..0000000000
--- a/thirdparty/opus/silk/arm/NSQ_del_dec_arm.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/***********************************************************************
-Copyright (c) 2017 Google Inc.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifndef SILK_NSQ_DEL_DEC_ARM_H
-#define SILK_NSQ_DEL_DEC_ARM_H
-
-#include "celt/arm/armcpu.h"
-
-#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-void silk_NSQ_del_dec_neon(
- const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
- SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
- const opus_int16 PredCoef_Q12[2 * MAX_LPC_ORDER],
- const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
- const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
- const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
- const opus_int Tilt_Q14[MAX_NB_SUBFR],
- const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
- const opus_int32 Gains_Q16[MAX_NB_SUBFR],
- const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
- const opus_int LTP_scale_Q14);
-
-#if !defined(OPUS_HAVE_RTCD)
-#define OVERRIDE_silk_NSQ_del_dec (1)
-#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
- LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
- LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
- LTP_scale_Q14, arch) \
- ((void)(arch), \
- PRESUME_NEON(silk_NSQ_del_dec)( \
- psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, \
- AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
- Lambda_Q10, LTP_scale_Q14))
-#endif
-#endif
-
-#if !defined(OVERRIDE_silk_NSQ_del_dec)
-/*Is run-time CPU detection enabled on this platform?*/
-#if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
- !defined(OPUS_ARM_PRESUME_NEON_INTR))
-extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
- const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
- SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
- const opus_int16 PredCoef_Q12[2 * MAX_LPC_ORDER],
- const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
- const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
- const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
- const opus_int Tilt_Q14[MAX_NB_SUBFR],
- const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
- const opus_int32 Gains_Q16[MAX_NB_SUBFR],
- const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
- const opus_int LTP_scale_Q14);
-#define OVERRIDE_silk_NSQ_del_dec (1)
-#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
- LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
- LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
- LTP_scale_Q14, arch) \
- ((*SILK_NSQ_DEL_DEC_IMPL[(arch)&OPUS_ARCHMASK])( \
- psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, \
- AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
- Lambda_Q10, LTP_scale_Q14))
-#elif defined(OPUS_ARM_PRESUME_NEON_INTR)
-#define OVERRIDE_silk_NSQ_del_dec (1)
-#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
- LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
- LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
- LTP_scale_Q14, arch) \
- ((void)(arch), \
- silk_NSQ_del_dec_neon(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
- LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
- LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
- LTP_scale_Q14))
-#endif
-#endif
-
-#endif /* end SILK_NSQ_DEL_DEC_ARM_H */
diff --git a/thirdparty/opus/silk/arm/NSQ_del_dec_neon_intr.c b/thirdparty/opus/silk/arm/NSQ_del_dec_neon_intr.c
deleted file mode 100644
index 212410f362..0000000000
--- a/thirdparty/opus/silk/arm/NSQ_del_dec_neon_intr.c
+++ /dev/null
@@ -1,1124 +0,0 @@
-/***********************************************************************
-Copyright (c) 2017 Google Inc.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <arm_neon.h>
-#ifdef OPUS_CHECK_ASM
-# include <string.h>
-#endif
-#include "main.h"
-#include "stack_alloc.h"
-
-/* NEON intrinsics optimization now can only parallelize up to 4 delay decision states. */
-/* If there are more states, C function is called, and this optimization must be expanded. */
-#define NEON_MAX_DEL_DEC_STATES 4
-
-typedef struct {
- opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ][ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 RandState[ DECISION_DELAY ][ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 Q_Q10[ DECISION_DELAY ][ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 Xq_Q14[ DECISION_DELAY ][ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 Pred_Q15[ DECISION_DELAY ][ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 Shape_Q14[ DECISION_DELAY ][ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ][ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 LF_AR_Q14[ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 Diff_Q14[ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 Seed[ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 SeedInit[ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 RD_Q10[ NEON_MAX_DEL_DEC_STATES ];
-} NSQ_del_decs_struct;
-
-typedef struct {
- opus_int32 Q_Q10[ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 RD_Q10[ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 xq_Q14[ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 LF_AR_Q14[ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 Diff_Q14[ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 sLTP_shp_Q14[ NEON_MAX_DEL_DEC_STATES ];
- opus_int32 LPC_exc_Q14[ NEON_MAX_DEL_DEC_STATES ];
-} NSQ_samples_struct;
-
-static OPUS_INLINE void silk_nsq_del_dec_scale_states_neon(
- const silk_encoder_state *psEncC, /* I Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- NSQ_del_decs_struct psDelDec[], /* I/O Delayed decision states */
- const opus_int16 x16[], /* I Input */
- opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
- const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
- opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
- opus_int subfr, /* I Subframe number */
- const opus_int LTP_scale_Q14, /* I LTP state scaling */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
- const opus_int signal_type, /* I Signal type */
- const opus_int decisionDelay /* I Decision delay */
-);
-
-/******************************************/
-/* Noise shape quantizer for one subframe */
-/******************************************/
-static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_neon(
- silk_nsq_state *NSQ, /* I/O NSQ state */
- NSQ_del_decs_struct psDelDec[], /* I/O Delayed decision states */
- opus_int signalType, /* I Signal type */
- const opus_int32 x_Q10[], /* I */
- opus_int8 pulses[], /* O */
- opus_int16 xq[], /* O */
- opus_int32 sLTP_Q15[], /* I/O LTP filter state */
- opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
- const opus_int16 a_Q12[], /* I Short term prediction coefs */
- const opus_int16 b_Q14[], /* I Long term prediction coefs */
- const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
- opus_int lag, /* I Pitch lag */
- opus_int32 HarmShapeFIRPacked_Q14, /* I */
- opus_int Tilt_Q14, /* I Spectral tilt */
- opus_int32 LF_shp_Q14, /* I */
- opus_int32 Gain_Q16, /* I */
- opus_int Lambda_Q10, /* I */
- opus_int offset_Q10, /* I */
- opus_int length, /* I Input length */
- opus_int subfr, /* I Subframe number */
- opus_int shapingLPCOrder, /* I Shaping LPC filter order */
- opus_int predictLPCOrder, /* I Prediction filter order */
- opus_int warping_Q16, /* I */
- opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
- opus_int decisionDelay /* I */
-);
-
-static OPUS_INLINE void copy_winner_state_kernel(
- const NSQ_del_decs_struct *psDelDec,
- const opus_int offset,
- const opus_int last_smple_idx,
- const opus_int Winner_ind,
- const int32x2_t gain_lo_s32x2,
- const int32x2_t gain_hi_s32x2,
- const int32x4_t shift_s32x4,
- int32x4_t t0_s32x4,
- int32x4_t t1_s32x4,
- opus_int8 *const pulses,
- opus_int16 *pxq,
- silk_nsq_state *NSQ
-)
-{
- int16x8_t t_s16x8;
- int32x4_t o0_s32x4, o1_s32x4;
-
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 0 ][ Winner_ind ], t0_s32x4, 0 );
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 1 ][ Winner_ind ], t0_s32x4, 1 );
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 2 ][ Winner_ind ], t0_s32x4, 2 );
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 3 ][ Winner_ind ], t0_s32x4, 3 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 4 ][ Winner_ind ], t1_s32x4, 0 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 5 ][ Winner_ind ], t1_s32x4, 1 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 6 ][ Winner_ind ], t1_s32x4, 2 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 7 ][ Winner_ind ], t1_s32x4, 3 );
- t_s16x8 = vcombine_s16( vrshrn_n_s32( t0_s32x4, 10 ), vrshrn_n_s32( t1_s32x4, 10 ) );
- vst1_s8( &pulses[ offset ], vmovn_s16( t_s16x8 ) );
-
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 0 ][ Winner_ind ], t0_s32x4, 0 );
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 1 ][ Winner_ind ], t0_s32x4, 1 );
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 2 ][ Winner_ind ], t0_s32x4, 2 );
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 3 ][ Winner_ind ], t0_s32x4, 3 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 4 ][ Winner_ind ], t1_s32x4, 0 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 5 ][ Winner_ind ], t1_s32x4, 1 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 6 ][ Winner_ind ], t1_s32x4, 2 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 7 ][ Winner_ind ], t1_s32x4, 3 );
- o0_s32x4 = vqdmulhq_lane_s32( t0_s32x4, gain_lo_s32x2, 0 );
- o1_s32x4 = vqdmulhq_lane_s32( t1_s32x4, gain_lo_s32x2, 0 );
- o0_s32x4 = vmlaq_lane_s32( o0_s32x4, t0_s32x4, gain_hi_s32x2, 0 );
- o1_s32x4 = vmlaq_lane_s32( o1_s32x4, t1_s32x4, gain_hi_s32x2, 0 );
- o0_s32x4 = vrshlq_s32( o0_s32x4, shift_s32x4 );
- o1_s32x4 = vrshlq_s32( o1_s32x4, shift_s32x4 );
- vst1_s16( &pxq[ offset + 0 ], vqmovn_s32( o0_s32x4 ) );
- vst1_s16( &pxq[ offset + 4 ], vqmovn_s32( o1_s32x4 ) );
-
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 0 ][ Winner_ind ], t0_s32x4, 0 );
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 1 ][ Winner_ind ], t0_s32x4, 1 );
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 2 ][ Winner_ind ], t0_s32x4, 2 );
- t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 3 ][ Winner_ind ], t0_s32x4, 3 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 4 ][ Winner_ind ], t1_s32x4, 0 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 5 ][ Winner_ind ], t1_s32x4, 1 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 6 ][ Winner_ind ], t1_s32x4, 2 );
- t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 7 ][ Winner_ind ], t1_s32x4, 3 );
- vst1q_s32( &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx + offset + 0 ], t0_s32x4 );
- vst1q_s32( &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx + offset + 4 ], t1_s32x4 );
-}
-
-static OPUS_INLINE void copy_winner_state(
- const NSQ_del_decs_struct *psDelDec,
- const opus_int decisionDelay,
- const opus_int smpl_buf_idx,
- const opus_int Winner_ind,
- const opus_int32 gain,
- const opus_int32 shift,
- opus_int8 *const pulses,
- opus_int16 *pxq,
- silk_nsq_state *NSQ
-)
-{
- opus_int i, last_smple_idx;
- const int32x2_t gain_lo_s32x2 = vdup_n_s32( silk_LSHIFT32( gain & 0x0000FFFF, 15 ) );
- const int32x2_t gain_hi_s32x2 = vdup_n_s32( gain >> 16 );
- const int32x4_t shift_s32x4 = vdupq_n_s32( -shift );
- int32x4_t t0_s32x4, t1_s32x4;
-
- t0_s32x4 = t1_s32x4 = vdupq_n_s32( 0 ); /* initialization */
- last_smple_idx = smpl_buf_idx + decisionDelay - 1 + DECISION_DELAY;
- if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
- if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
-
- for( i = 0; ( i < ( decisionDelay - 7 ) ) && ( last_smple_idx >= 7 ); i += 8, last_smple_idx -= 8 ) {
- copy_winner_state_kernel( psDelDec, i - decisionDelay, last_smple_idx, Winner_ind, gain_lo_s32x2, gain_hi_s32x2, shift_s32x4, t0_s32x4, t1_s32x4, pulses, pxq, NSQ );
- }
- for( ; ( i < decisionDelay ) && ( last_smple_idx >= 0 ); i++, last_smple_idx-- ) {
- pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDelDec->Q_Q10[ last_smple_idx ][ Winner_ind ], 10 );
- pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psDelDec->Xq_Q14[ last_smple_idx ][ Winner_ind ], gain ), shift ) );
- NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDelDec->Shape_Q14[ last_smple_idx ][ Winner_ind ];
- }
-
- last_smple_idx += DECISION_DELAY;
- for( ; i < ( decisionDelay - 7 ); i++, last_smple_idx-- ) {
- copy_winner_state_kernel( psDelDec, i - decisionDelay, last_smple_idx, Winner_ind, gain_lo_s32x2, gain_hi_s32x2, shift_s32x4, t0_s32x4, t1_s32x4, pulses, pxq, NSQ );
- }
- for( ; i < decisionDelay; i++, last_smple_idx-- ) {
- pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDelDec->Q_Q10[ last_smple_idx ][ Winner_ind ], 10 );
- pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psDelDec->Xq_Q14[ last_smple_idx ][ Winner_ind ], gain ), shift ) );
- NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDelDec->Shape_Q14[ last_smple_idx ][ Winner_ind ];
- }
-}
-
-void silk_NSQ_del_dec_neon(
- const silk_encoder_state *psEncC, /* I Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int16 x16[], /* I Input */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
-)
-{
-#ifdef OPUS_CHECK_ASM
- silk_nsq_state NSQ_c;
- SideInfoIndices psIndices_c;
- opus_int8 pulses_c[ MAX_FRAME_LENGTH ];
- const opus_int8 *const pulses_a = pulses;
-
- ( void )pulses_a;
- silk_memcpy( &NSQ_c, NSQ, sizeof( NSQ_c ) );
- silk_memcpy( &psIndices_c, psIndices, sizeof( psIndices_c ) );
- silk_memcpy( pulses_c, pulses, sizeof( pulses_c ) );
- silk_NSQ_del_dec_c( psEncC, &NSQ_c, &psIndices_c, x16, pulses_c, PredCoef_Q12, LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16,
- pitchL, Lambda_Q10, LTP_scale_Q14 );
-#endif
-
- /* The optimization parallelizes the different delay decision states. */
- if(( psEncC->nStatesDelayedDecision > NEON_MAX_DEL_DEC_STATES ) || ( psEncC->nStatesDelayedDecision <= 2 )) {
- /* NEON intrinsics optimization now can only parallelize up to 4 delay decision states. */
- /* If there are more states, C function is called, and this optimization must be expanded. */
- /* When the number of delay decision states is less than 3, there are penalties using this */
- /* optimization, and C function is called. */
- /* When the number of delay decision states is 2, it's better to specialize another */
- /* structure NSQ_del_dec2_struct and optimize with shorter NEON registers. (Low priority) */
- silk_NSQ_del_dec_c( psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14,
- Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14 );
- } else {
- opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
- opus_int smpl_buf_idx, decisionDelay;
- const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
- opus_int16 *pxq;
- VARDECL( opus_int32, sLTP_Q15 );
- VARDECL( opus_int16, sLTP );
- opus_int32 HarmShapeFIRPacked_Q14;
- opus_int offset_Q10;
- opus_int32 RDmin_Q10, Gain_Q10;
- VARDECL( opus_int32, x_sc_Q10 );
- VARDECL( opus_int32, delayedGain_Q10 );
- VARDECL( NSQ_del_decs_struct, psDelDec );
- int32x4_t t_s32x4;
- SAVE_STACK;
-
- /* Set unvoiced lag to the previous one, overwrite later for voiced */
- lag = NSQ->lagPrev;
-
- silk_assert( NSQ->prev_gain_Q16 != 0 );
-
- /* Initialize delayed decision states */
- ALLOC( psDelDec, 1, NSQ_del_decs_struct );
- /* Only RandState and RD_Q10 need to be initialized to 0. */
- silk_memset( psDelDec->RandState, 0, sizeof( psDelDec->RandState ) );
- vst1q_s32( psDelDec->RD_Q10, vdupq_n_s32( 0 ) );
-
- for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) {
- psDelDec->SeedInit[ k ] = psDelDec->Seed[ k ] = ( k + psIndices->Seed ) & 3;
- }
- vst1q_s32( psDelDec->LF_AR_Q14, vld1q_dup_s32( &NSQ->sLF_AR_shp_Q14 ) );
- vst1q_s32( psDelDec->Diff_Q14, vld1q_dup_s32( &NSQ->sDiff_shp_Q14 ) );
- vst1q_s32( psDelDec->Shape_Q14[ 0 ], vld1q_dup_s32( &NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ] ) );
- for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
- vst1q_s32( psDelDec->sLPC_Q14[ i ], vld1q_dup_s32( &NSQ->sLPC_Q14[ i ] ) );
- }
- for( i = 0; i < (opus_int)( sizeof( NSQ->sAR2_Q14 ) / sizeof( NSQ->sAR2_Q14[ 0 ] ) ); i++ ) {
- vst1q_s32( psDelDec->sAR2_Q14[ i ], vld1q_dup_s32( &NSQ->sAR2_Q14[ i ] ) );
- }
-
- offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
- smpl_buf_idx = 0; /* index of oldest samples */
-
- decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length );
-
- /* For voiced frames limit the decision delay to lower than the pitch lag */
- if( psIndices->signalType == TYPE_VOICED ) {
- opus_int pitch_min = pitchL[ 0 ];
- for( k = 1; k < psEncC->nb_subfr; k++ ) {
- pitch_min = silk_min_int( pitch_min, pitchL[ k ] );
- }
- decisionDelay = silk_min_int( decisionDelay, pitch_min - LTP_ORDER / 2 - 1 );
- } else {
- if( lag > 0 ) {
- decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 );
- }
- }
-
- if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
- LSF_interpolation_flag = 0;
- } else {
- LSF_interpolation_flag = 1;
- }
-
- ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
- ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
- ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
- ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
- /* Set up pointers to start of sub frame */
- pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
- NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
- NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
- subfr = 0;
- for( k = 0; k < psEncC->nb_subfr; k++ ) {
- A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
- B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
- AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
-
- /* Noise shape parameters */
- silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
- HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
- HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
-
- NSQ->rewhite_flag = 0;
- if( psIndices->signalType == TYPE_VOICED ) {
- /* Voiced */
- lag = pitchL[ k ];
-
- /* Re-whitening */
- if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
- if( k == 2 ) {
- /* RESET DELAYED DECISIONS */
- /* Find winner */
- int32x4_t RD_Q10_s32x4;
- RDmin_Q10 = psDelDec->RD_Q10[ 0 ];
- Winner_ind = 0;
- for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) {
- if( psDelDec->RD_Q10[ i ] < RDmin_Q10 ) {
- RDmin_Q10 = psDelDec->RD_Q10[ i ];
- Winner_ind = i;
- }
- }
- psDelDec->RD_Q10[ Winner_ind ] -= ( silk_int32_MAX >> 4 );
- RD_Q10_s32x4 = vld1q_s32( psDelDec->RD_Q10 );
- RD_Q10_s32x4 = vaddq_s32( RD_Q10_s32x4, vdupq_n_s32( silk_int32_MAX >> 4 ) );
- vst1q_s32( psDelDec->RD_Q10, RD_Q10_s32x4 );
-
- /* Copy final part of signals from winner state to output and long-term filter states */
- copy_winner_state( psDelDec, decisionDelay, smpl_buf_idx, Winner_ind, Gains_Q16[ 1 ], 14, pulses, pxq, NSQ );
-
- subfr = 0;
- }
-
- /* Rewhiten with new A coefs */
- start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
-
- silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
- A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
-
- NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
- NSQ->rewhite_flag = 1;
- }
- }
-
- silk_nsq_del_dec_scale_states_neon( psEncC, NSQ, psDelDec, x16, x_sc_Q10, sLTP, sLTP_Q15, k,
- LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
-
- silk_noise_shape_quantizer_del_dec_neon( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
- delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ],
- Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
- psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay );
-
- x16 += psEncC->subfr_length;
- pulses += psEncC->subfr_length;
- pxq += psEncC->subfr_length;
- }
-
- /* Find winner */
- RDmin_Q10 = psDelDec->RD_Q10[ 0 ];
- Winner_ind = 0;
- for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) {
- if( psDelDec->RD_Q10[ k ] < RDmin_Q10 ) {
- RDmin_Q10 = psDelDec->RD_Q10[ k ];
- Winner_ind = k;
- }
- }
-
- /* Copy final part of signals from winner state to output and long-term filter states */
- psIndices->Seed = psDelDec->SeedInit[ Winner_ind ];
- Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
- copy_winner_state( psDelDec, decisionDelay, smpl_buf_idx, Winner_ind, Gain_Q10, 8, pulses, pxq, NSQ );
-
- t_s32x4 = vdupq_n_s32( 0 ); /* initialization */
- for( i = 0; i < ( NSQ_LPC_BUF_LENGTH - 3 ); i += 4 ) {
- t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 0 ][ Winner_ind ], t_s32x4, 0 );
- t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 1 ][ Winner_ind ], t_s32x4, 1 );
- t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 2 ][ Winner_ind ], t_s32x4, 2 );
- t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 3 ][ Winner_ind ], t_s32x4, 3 );
- vst1q_s32( &NSQ->sLPC_Q14[ i ], t_s32x4 );
- }
-
- for( ; i < NSQ_LPC_BUF_LENGTH; i++ ) {
- NSQ->sLPC_Q14[ i ] = psDelDec->sLPC_Q14[ i ][ Winner_ind ];
- }
-
- for( i = 0; i < (opus_int)( sizeof( NSQ->sAR2_Q14 ) / sizeof( NSQ->sAR2_Q14[ 0 ] ) - 3 ); i += 4 ) {
- t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 0 ][ Winner_ind ], t_s32x4, 0 );
- t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 1 ][ Winner_ind ], t_s32x4, 1 );
- t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 2 ][ Winner_ind ], t_s32x4, 2 );
- t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 3 ][ Winner_ind ], t_s32x4, 3 );
- vst1q_s32( &NSQ->sAR2_Q14[ i ], t_s32x4 );
- }
-
- for( ; i < (opus_int)( sizeof( NSQ->sAR2_Q14 ) / sizeof( NSQ->sAR2_Q14[ 0 ] ) ); i++ ) {
- NSQ->sAR2_Q14[ i ] = psDelDec->sAR2_Q14[ i ][ Winner_ind ];
- }
-
- /* Update states */
- NSQ->sLF_AR_shp_Q14 = psDelDec->LF_AR_Q14[ Winner_ind ];
- NSQ->sDiff_shp_Q14 = psDelDec->Diff_Q14[ Winner_ind ];
- NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
-
- /* Save quantized speech signal */
- silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
- silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
- RESTORE_STACK;
- }
-
-#ifdef OPUS_CHECK_ASM
- silk_assert( !memcmp( &NSQ_c, NSQ, sizeof( NSQ_c ) ) );
- silk_assert( !memcmp( &psIndices_c, psIndices, sizeof( psIndices_c ) ) );
- silk_assert( !memcmp( pulses_c, pulses_a, sizeof( pulses_c ) ) );
-#endif
-}
-
-/******************************************/
-/* Noise shape quantizer for one subframe */
-/******************************************/
-/* Note: Function silk_short_prediction_create_arch_coef_neon() defined in NSQ_neon.h is actually a hacking C function. */
-/* Therefore here we append "_local" to the NEON function name to avoid confusion. */
-static OPUS_INLINE void silk_short_prediction_create_arch_coef_neon_local(opus_int32 *out, const opus_int16 *in, opus_int order)
-{
- int16x8_t t_s16x8;
- int32x4_t t0_s32x4, t1_s32x4, t2_s32x4, t3_s32x4;
- silk_assert( order == 10 || order == 16 );
-
- t_s16x8 = vld1q_s16( in + 0 ); /* 7 6 5 4 3 2 1 0 */
- t_s16x8 = vrev64q_s16( t_s16x8 ); /* 4 5 6 7 0 1 2 3 */
- t2_s32x4 = vshll_n_s16( vget_high_s16( t_s16x8 ), 15 ); /* 4 5 6 7 */
- t3_s32x4 = vshll_n_s16( vget_low_s16( t_s16x8 ), 15 ); /* 0 1 2 3 */
-
- if( order == 16 ) {
- t_s16x8 = vld1q_s16( in + 8 ); /* F E D C B A 9 8 */
- t_s16x8 = vrev64q_s16( t_s16x8 ); /* C D E F 8 9 A B */
- t0_s32x4 = vshll_n_s16( vget_high_s16( t_s16x8 ), 15 ); /* C D E F */
- t1_s32x4 = vshll_n_s16( vget_low_s16( t_s16x8 ), 15 ); /* 8 9 A B */
- } else {
- int16x4_t t_s16x4;
-
- t0_s32x4 = vdupq_n_s32( 0 ); /* zero zero zero zero */
- t_s16x4 = vld1_s16( in + 6 ); /* 9 8 7 6 */
- t_s16x4 = vrev64_s16( t_s16x4 ); /* 6 7 8 9 */
- t1_s32x4 = vshll_n_s16( t_s16x4, 15 );
- t1_s32x4 = vcombine_s32( vget_low_s32(t0_s32x4), vget_low_s32( t1_s32x4 ) ); /* 8 9 zero zero */
- }
- vst1q_s32( out + 0, t0_s32x4 );
- vst1q_s32( out + 4, t1_s32x4 );
- vst1q_s32( out + 8, t2_s32x4 );
- vst1q_s32( out + 12, t3_s32x4 );
-}
-
-static OPUS_INLINE int32x4_t silk_SMLAWB_lane0_neon(
- const int32x4_t out_s32x4,
- const int32x4_t in_s32x4,
- const int32x2_t coef_s32x2
-)
-{
- return vaddq_s32( out_s32x4, vqdmulhq_lane_s32( in_s32x4, coef_s32x2, 0 ) );
-}
-
-static OPUS_INLINE int32x4_t silk_SMLAWB_lane1_neon(
- const int32x4_t out_s32x4,
- const int32x4_t in_s32x4,
- const int32x2_t coef_s32x2
-)
-{
- return vaddq_s32( out_s32x4, vqdmulhq_lane_s32( in_s32x4, coef_s32x2, 1 ) );
-}
-
-/* Note: This function has different return value than silk_noise_shape_quantizer_short_prediction_neon(). */
-/* Therefore here we append "_local" to the function name to avoid confusion. */
-static OPUS_INLINE int32x4_t silk_noise_shape_quantizer_short_prediction_neon_local(const opus_int32 *buf32, const opus_int32 *a_Q12_arch, opus_int order)
-{
- const int32x4_t a_Q12_arch0_s32x4 = vld1q_s32( a_Q12_arch + 0 );
- const int32x4_t a_Q12_arch1_s32x4 = vld1q_s32( a_Q12_arch + 4 );
- const int32x4_t a_Q12_arch2_s32x4 = vld1q_s32( a_Q12_arch + 8 );
- const int32x4_t a_Q12_arch3_s32x4 = vld1q_s32( a_Q12_arch + 12 );
- int32x4_t LPC_pred_Q14_s32x4;
-
- silk_assert( order == 10 || order == 16 );
- /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
- LPC_pred_Q14_s32x4 = vdupq_n_s32( silk_RSHIFT( order, 1 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 0 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch0_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 1 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch0_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 2 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch0_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 3 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch0_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 4 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch1_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 5 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch1_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 6 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch1_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 7 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch1_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 8 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch2_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 9 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch2_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 10 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch2_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 11 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch2_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 12 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch3_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 13 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32( a_Q12_arch3_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 14 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch3_s32x4 ) );
- LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 15 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch3_s32x4 ) );
-
- return LPC_pred_Q14_s32x4;
-}
-
-static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_neon(
- silk_nsq_state *NSQ, /* I/O NSQ state */
- NSQ_del_decs_struct psDelDec[], /* I/O Delayed decision states */
- opus_int signalType, /* I Signal type */
- const opus_int32 x_Q10[], /* I */
- opus_int8 pulses[], /* O */
- opus_int16 xq[], /* O */
- opus_int32 sLTP_Q15[], /* I/O LTP filter state */
- opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
- const opus_int16 a_Q12[], /* I Short term prediction coefs */
- const opus_int16 b_Q14[], /* I Long term prediction coefs */
- const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
- opus_int lag, /* I Pitch lag */
- opus_int32 HarmShapeFIRPacked_Q14, /* I */
- opus_int Tilt_Q14, /* I Spectral tilt */
- opus_int32 LF_shp_Q14, /* I */
- opus_int32 Gain_Q16, /* I */
- opus_int Lambda_Q10, /* I */
- opus_int offset_Q10, /* I */
- opus_int length, /* I Input length */
- opus_int subfr, /* I Subframe number */
- opus_int shapingLPCOrder, /* I Shaping LPC filter order */
- opus_int predictLPCOrder, /* I Prediction filter order */
- opus_int warping_Q16, /* I */
- opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
- opus_int decisionDelay /* I */
-)
-{
- opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
- opus_int32 Winner_rand_state;
- opus_int32 LTP_pred_Q14, n_LTP_Q14;
- opus_int32 RDmin_Q10, RDmax_Q10;
- opus_int32 Gain_Q10;
- opus_int32 *pred_lag_ptr, *shp_lag_ptr;
- opus_int32 a_Q12_arch[MAX_LPC_ORDER];
- const int32x2_t warping_Q16_s32x2 = vdup_n_s32( silk_LSHIFT32( warping_Q16, 16 ) >> 1 );
- const opus_int32 LF_shp_Q29 = silk_LSHIFT32( LF_shp_Q14, 16 ) >> 1;
- opus_int32 AR_shp_Q28[ MAX_SHAPE_LPC_ORDER ];
- const uint32x4_t rand_multiplier_u32x4 = vdupq_n_u32( RAND_MULTIPLIER );
- const uint32x4_t rand_increment_u32x4 = vdupq_n_u32( RAND_INCREMENT );
-
- VARDECL( NSQ_samples_struct, psSampleState );
- SAVE_STACK;
-
- silk_assert( nStatesDelayedDecision > 0 );
- silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
- ALLOC( psSampleState, 2, NSQ_samples_struct );
-
- shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
- pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
- Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
-
- for( i = 0; i < ( MAX_SHAPE_LPC_ORDER - 7 ); i += 8 ) {
- const int16x8_t t_s16x8 = vld1q_s16( AR_shp_Q13 + i );
- vst1q_s32( AR_shp_Q28 + i + 0, vshll_n_s16( vget_low_s16( t_s16x8 ), 15 ) );
- vst1q_s32( AR_shp_Q28 + i + 4, vshll_n_s16( vget_high_s16( t_s16x8 ), 15 ) );
- }
-
- for( ; i < MAX_SHAPE_LPC_ORDER; i++ ) {
- AR_shp_Q28[i] = silk_LSHIFT32( AR_shp_Q13[i], 15 );
- }
-
- silk_short_prediction_create_arch_coef_neon_local( a_Q12_arch, a_Q12, predictLPCOrder );
-
- for( i = 0; i < length; i++ ) {
- int32x4_t Seed_s32x4, LPC_pred_Q14_s32x4;
- int32x4_t sign_s32x4, tmp1_s32x4, tmp2_s32x4;
- int32x4_t n_AR_Q14_s32x4, n_LF_Q14_s32x4;
- int32x2_t AR_shp_Q28_s32x2;
- int16x4_t r_Q10_s16x4, rr_Q10_s16x4;
-
- /* Perform common calculations used in all states */
-
- /* Long-term prediction */
- if( signalType == TYPE_VOICED ) {
- /* Unrolled loop */
- /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
- LTP_pred_Q14 = 2;
- LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ 0 ], b_Q14[ 0 ] );
- LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
- LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
- LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
- LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
- LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */
- pred_lag_ptr++;
- } else {
- LTP_pred_Q14 = 0;
- }
-
- /* Long-term shaping */
- if( lag > 0 ) {
- /* Symmetric, packed FIR coefficients */
- n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
- n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
- n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */
- shp_lag_ptr++;
- } else {
- n_LTP_Q14 = 0;
- }
-
- /* Generate dither */
- Seed_s32x4 = vld1q_s32( psDelDec->Seed );
- Seed_s32x4 = vreinterpretq_s32_u32( vmlaq_u32( rand_increment_u32x4, vreinterpretq_u32_s32( Seed_s32x4 ), rand_multiplier_u32x4 ) );
- vst1q_s32( psDelDec->Seed, Seed_s32x4 );
-
- /* Short-term prediction */
- LPC_pred_Q14_s32x4 = silk_noise_shape_quantizer_short_prediction_neon_local(psDelDec->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 16 + i ], a_Q12_arch, predictLPCOrder);
- LPC_pred_Q14_s32x4 = vshlq_n_s32( LPC_pred_Q14_s32x4, 4 ); /* Q10 -> Q14 */
-
- /* Noise shape feedback */
- /* Output of lowpass section */
- tmp2_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->Diff_Q14 ), vld1q_s32( psDelDec->sAR2_Q14[ 0 ] ), warping_Q16_s32x2 );
- /* Output of allpass section */
- tmp1_s32x4 = vsubq_s32( vld1q_s32( psDelDec->sAR2_Q14[ 1 ] ), tmp2_s32x4 );
- tmp1_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->sAR2_Q14[ 0 ] ), tmp1_s32x4, warping_Q16_s32x2 );
- vst1q_s32( psDelDec->sAR2_Q14[ 0 ], tmp2_s32x4 );
- AR_shp_Q28_s32x2 = vld1_s32( AR_shp_Q28 );
- n_AR_Q14_s32x4 = vaddq_s32( vdupq_n_s32( silk_RSHIFT( shapingLPCOrder, 1 ) ), vqdmulhq_lane_s32( tmp2_s32x4, AR_shp_Q28_s32x2, 0 ) );
-
- /* Loop over allpass sections */
- for( j = 2; j < shapingLPCOrder; j += 2 ) {
- /* Output of allpass section */
- tmp2_s32x4 = vsubq_s32( vld1q_s32( psDelDec->sAR2_Q14[ j + 0 ] ), tmp1_s32x4 );
- tmp2_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->sAR2_Q14[ j - 1 ] ), tmp2_s32x4, warping_Q16_s32x2 );
- vst1q_s32( psDelDec->sAR2_Q14[ j - 1 ], tmp1_s32x4 );
- n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_lane_s32( tmp1_s32x4, AR_shp_Q28_s32x2, 1 ) );
- /* Output of allpass section */
- tmp1_s32x4 = vsubq_s32( vld1q_s32( psDelDec->sAR2_Q14[ j + 1 ] ), tmp2_s32x4 );
- tmp1_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->sAR2_Q14[ j + 0 ] ), tmp1_s32x4, warping_Q16_s32x2 );
- vst1q_s32( psDelDec->sAR2_Q14[ j + 0 ], tmp2_s32x4 );
- AR_shp_Q28_s32x2 = vld1_s32( &AR_shp_Q28[ j ] );
- n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_lane_s32( tmp2_s32x4, AR_shp_Q28_s32x2, 0 ) );
- }
- vst1q_s32( psDelDec->sAR2_Q14[ shapingLPCOrder - 1 ], tmp1_s32x4 );
- n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_lane_s32( tmp1_s32x4, AR_shp_Q28_s32x2, 1 ) );
- n_AR_Q14_s32x4 = vshlq_n_s32( n_AR_Q14_s32x4, 1 ); /* Q11 -> Q12 */
- n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_n_s32( vld1q_s32( psDelDec->LF_AR_Q14 ), silk_LSHIFT32( Tilt_Q14, 16 ) >> 1 ) ); /* Q12 */
- n_AR_Q14_s32x4 = vshlq_n_s32( n_AR_Q14_s32x4, 2 ); /* Q12 -> Q14 */
- n_LF_Q14_s32x4 = vqdmulhq_n_s32( vld1q_s32( psDelDec->Shape_Q14[ *smpl_buf_idx ] ), LF_shp_Q29 ); /* Q12 */
- n_LF_Q14_s32x4 = vaddq_s32( n_LF_Q14_s32x4, vqdmulhq_n_s32( vld1q_s32( psDelDec->LF_AR_Q14 ), silk_LSHIFT32( LF_shp_Q14 >> 16 , 15 ) ) ); /* Q12 */
- n_LF_Q14_s32x4 = vshlq_n_s32( n_LF_Q14_s32x4, 2 ); /* Q12 -> Q14 */
-
- /* Input minus prediction plus noise feedback */
- /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
- tmp1_s32x4 = vaddq_s32( n_AR_Q14_s32x4, n_LF_Q14_s32x4 ); /* Q14 */
- tmp2_s32x4 = vaddq_s32( vdupq_n_s32( n_LTP_Q14 ), LPC_pred_Q14_s32x4 ); /* Q13 */
- tmp1_s32x4 = vsubq_s32( tmp2_s32x4, tmp1_s32x4 ); /* Q13 */
- tmp1_s32x4 = vrshrq_n_s32( tmp1_s32x4, 4 ); /* Q10 */
- tmp1_s32x4 = vsubq_s32( vdupq_n_s32( x_Q10[ i ] ), tmp1_s32x4 ); /* residual error Q10 */
-
- /* Flip sign depending on dither */
- sign_s32x4 = vreinterpretq_s32_u32( vcltq_s32( Seed_s32x4, vdupq_n_s32( 0 ) ) );
- tmp1_s32x4 = veorq_s32( tmp1_s32x4, sign_s32x4 );
- tmp1_s32x4 = vsubq_s32( tmp1_s32x4, sign_s32x4 );
- tmp1_s32x4 = vmaxq_s32( tmp1_s32x4, vdupq_n_s32( -( 31 << 10 ) ) );
- tmp1_s32x4 = vminq_s32( tmp1_s32x4, vdupq_n_s32( 30 << 10 ) );
- r_Q10_s16x4 = vmovn_s32( tmp1_s32x4 );
-
- /* Find two quantization level candidates and measure their rate-distortion */
- {
- int16x4_t q1_Q10_s16x4 = vsub_s16( r_Q10_s16x4, vdup_n_s16( offset_Q10 ) );
- int16x4_t q1_Q0_s16x4 = vshr_n_s16( q1_Q10_s16x4, 10 );
- int16x4_t q2_Q10_s16x4;
- int32x4_t rd1_Q10_s32x4, rd2_Q10_s32x4;
- uint32x4_t t_u32x4;
-
- if( Lambda_Q10 > 2048 ) {
- /* For aggressive RDO, the bias becomes more than one pulse. */
- const int rdo_offset = Lambda_Q10/2 - 512;
- const uint16x4_t greaterThanRdo = vcgt_s16( q1_Q10_s16x4, vdup_n_s16( rdo_offset ) );
- const uint16x4_t lessThanMinusRdo = vclt_s16( q1_Q10_s16x4, vdup_n_s16( -rdo_offset ) );
- /* If Lambda_Q10 > 32767, then q1_Q0, q1_Q10 and q2_Q10 must change to 32-bit. */
- silk_assert( Lambda_Q10 <= 32767 );
-
- q1_Q0_s16x4 = vreinterpret_s16_u16( vclt_s16( q1_Q10_s16x4, vdup_n_s16( 0 ) ) );
- q1_Q0_s16x4 = vbsl_s16( greaterThanRdo, vsub_s16( q1_Q10_s16x4, vdup_n_s16( rdo_offset ) ), q1_Q0_s16x4 );
- q1_Q0_s16x4 = vbsl_s16( lessThanMinusRdo, vadd_s16( q1_Q10_s16x4, vdup_n_s16( rdo_offset ) ), q1_Q0_s16x4 );
- q1_Q0_s16x4 = vshr_n_s16( q1_Q0_s16x4, 10 );
- }
- {
- const uint16x4_t equal0_u16x4 = vceq_s16( q1_Q0_s16x4, vdup_n_s16( 0 ) );
- const uint16x4_t equalMinus1_u16x4 = vceq_s16( q1_Q0_s16x4, vdup_n_s16( -1 ) );
- const uint16x4_t lessThanMinus1_u16x4 = vclt_s16( q1_Q0_s16x4, vdup_n_s16( -1 ) );
- int16x4_t tmp1_s16x4, tmp2_s16x4;
-
- q1_Q10_s16x4 = vshl_n_s16( q1_Q0_s16x4, 10 );
- tmp1_s16x4 = vadd_s16( q1_Q10_s16x4, vdup_n_s16( offset_Q10 - QUANT_LEVEL_ADJUST_Q10 ) );
- q1_Q10_s16x4 = vadd_s16( q1_Q10_s16x4, vdup_n_s16( offset_Q10 + QUANT_LEVEL_ADJUST_Q10 ) );
- q1_Q10_s16x4 = vbsl_s16( lessThanMinus1_u16x4, q1_Q10_s16x4, tmp1_s16x4 );
- q1_Q10_s16x4 = vbsl_s16( equal0_u16x4, vdup_n_s16( offset_Q10 ), q1_Q10_s16x4 );
- q1_Q10_s16x4 = vbsl_s16( equalMinus1_u16x4, vdup_n_s16( offset_Q10 - ( 1024 - QUANT_LEVEL_ADJUST_Q10 ) ), q1_Q10_s16x4 );
- q2_Q10_s16x4 = vadd_s16( q1_Q10_s16x4, vdup_n_s16( 1024 ) );
- q2_Q10_s16x4 = vbsl_s16( equal0_u16x4, vdup_n_s16( offset_Q10 + 1024 - QUANT_LEVEL_ADJUST_Q10 ), q2_Q10_s16x4 );
- q2_Q10_s16x4 = vbsl_s16( equalMinus1_u16x4, vdup_n_s16( offset_Q10 ), q2_Q10_s16x4 );
- tmp1_s16x4 = q1_Q10_s16x4;
- tmp2_s16x4 = q2_Q10_s16x4;
- tmp1_s16x4 = vbsl_s16( vorr_u16( equalMinus1_u16x4, lessThanMinus1_u16x4 ), vneg_s16( tmp1_s16x4 ), tmp1_s16x4 );
- tmp2_s16x4 = vbsl_s16( lessThanMinus1_u16x4, vneg_s16( tmp2_s16x4 ), tmp2_s16x4 );
- rd1_Q10_s32x4 = vmull_s16( tmp1_s16x4, vdup_n_s16( Lambda_Q10 ) );
- rd2_Q10_s32x4 = vmull_s16( tmp2_s16x4, vdup_n_s16( Lambda_Q10 ) );
- }
-
- rr_Q10_s16x4 = vsub_s16( r_Q10_s16x4, q1_Q10_s16x4 );
- rd1_Q10_s32x4 = vmlal_s16( rd1_Q10_s32x4, rr_Q10_s16x4, rr_Q10_s16x4 );
- rd1_Q10_s32x4 = vshrq_n_s32( rd1_Q10_s32x4, 10 );
-
- rr_Q10_s16x4 = vsub_s16( r_Q10_s16x4, q2_Q10_s16x4 );
- rd2_Q10_s32x4 = vmlal_s16( rd2_Q10_s32x4, rr_Q10_s16x4, rr_Q10_s16x4 );
- rd2_Q10_s32x4 = vshrq_n_s32( rd2_Q10_s32x4, 10 );
-
- tmp2_s32x4 = vld1q_s32( psDelDec->RD_Q10 );
- tmp1_s32x4 = vaddq_s32( tmp2_s32x4, vminq_s32( rd1_Q10_s32x4, rd2_Q10_s32x4 ) );
- tmp2_s32x4 = vaddq_s32( tmp2_s32x4, vmaxq_s32( rd1_Q10_s32x4, rd2_Q10_s32x4 ) );
- vst1q_s32( psSampleState[ 0 ].RD_Q10, tmp1_s32x4 );
- vst1q_s32( psSampleState[ 1 ].RD_Q10, tmp2_s32x4 );
- t_u32x4 = vcltq_s32( rd1_Q10_s32x4, rd2_Q10_s32x4 );
- tmp1_s32x4 = vbslq_s32( t_u32x4, vmovl_s16( q1_Q10_s16x4 ), vmovl_s16( q2_Q10_s16x4 ) );
- tmp2_s32x4 = vbslq_s32( t_u32x4, vmovl_s16( q2_Q10_s16x4 ), vmovl_s16( q1_Q10_s16x4 ) );
- vst1q_s32( psSampleState[ 0 ].Q_Q10, tmp1_s32x4 );
- vst1q_s32( psSampleState[ 1 ].Q_Q10, tmp2_s32x4 );
- }
-
- {
- /* Update states for best quantization */
- int32x4_t exc_Q14_s32x4, LPC_exc_Q14_s32x4, xq_Q14_s32x4, sLF_AR_shp_Q14_s32x4;
-
- /* Quantized excitation */
- exc_Q14_s32x4 = vshlq_n_s32( tmp1_s32x4, 4 );
- exc_Q14_s32x4 = veorq_s32( exc_Q14_s32x4, sign_s32x4 );
- exc_Q14_s32x4 = vsubq_s32( exc_Q14_s32x4, sign_s32x4 );
-
- /* Add predictions */
- LPC_exc_Q14_s32x4 = vaddq_s32( exc_Q14_s32x4, vdupq_n_s32( LTP_pred_Q14 ) );
- xq_Q14_s32x4 = vaddq_s32( LPC_exc_Q14_s32x4, LPC_pred_Q14_s32x4 );
-
- /* Update states */
- tmp1_s32x4 = vsubq_s32( xq_Q14_s32x4, vshlq_n_s32( vdupq_n_s32( x_Q10[ i ] ), 4 ) );
- vst1q_s32( psSampleState[ 0 ].Diff_Q14, tmp1_s32x4 );
- sLF_AR_shp_Q14_s32x4 = vsubq_s32( tmp1_s32x4, n_AR_Q14_s32x4 );
- vst1q_s32( psSampleState[ 0 ].sLTP_shp_Q14, vsubq_s32( sLF_AR_shp_Q14_s32x4, n_LF_Q14_s32x4 ) );
- vst1q_s32( psSampleState[ 0 ].LF_AR_Q14, sLF_AR_shp_Q14_s32x4 );
- vst1q_s32( psSampleState[ 0 ].LPC_exc_Q14, LPC_exc_Q14_s32x4 );
- vst1q_s32( psSampleState[ 0 ].xq_Q14, xq_Q14_s32x4 );
-
- /* Quantized excitation */
- exc_Q14_s32x4 = vshlq_n_s32( tmp2_s32x4, 4 );
- exc_Q14_s32x4 = veorq_s32( exc_Q14_s32x4, sign_s32x4 );
- exc_Q14_s32x4 = vsubq_s32( exc_Q14_s32x4, sign_s32x4 );
-
- /* Add predictions */
- LPC_exc_Q14_s32x4 = vaddq_s32( exc_Q14_s32x4, vdupq_n_s32( LTP_pred_Q14 ) );
- xq_Q14_s32x4 = vaddq_s32( LPC_exc_Q14_s32x4, LPC_pred_Q14_s32x4 );
-
- /* Update states */
- tmp1_s32x4 = vsubq_s32( xq_Q14_s32x4, vshlq_n_s32( vdupq_n_s32( x_Q10[ i ] ), 4 ) );
- vst1q_s32( psSampleState[ 1 ].Diff_Q14, tmp1_s32x4 );
- sLF_AR_shp_Q14_s32x4 = vsubq_s32( tmp1_s32x4, n_AR_Q14_s32x4 );
- vst1q_s32( psSampleState[ 1 ].sLTP_shp_Q14, vsubq_s32( sLF_AR_shp_Q14_s32x4, n_LF_Q14_s32x4 ) );
- vst1q_s32( psSampleState[ 1 ].LF_AR_Q14, sLF_AR_shp_Q14_s32x4 );
- vst1q_s32( psSampleState[ 1 ].LPC_exc_Q14, LPC_exc_Q14_s32x4 );
- vst1q_s32( psSampleState[ 1 ].xq_Q14, xq_Q14_s32x4 );
- }
-
- *smpl_buf_idx = *smpl_buf_idx ? ( *smpl_buf_idx - 1 ) : ( DECISION_DELAY - 1);
- last_smple_idx = *smpl_buf_idx + decisionDelay + DECISION_DELAY;
- if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
- if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
-
- /* Find winner */
- RDmin_Q10 = psSampleState[ 0 ].RD_Q10[ 0 ];
- Winner_ind = 0;
- for( k = 1; k < nStatesDelayedDecision; k++ ) {
- if( psSampleState[ 0 ].RD_Q10[ k ] < RDmin_Q10 ) {
- RDmin_Q10 = psSampleState[ 0 ].RD_Q10[ k ];
- Winner_ind = k;
- }
- }
-
- /* Increase RD values of expired states */
- {
- uint32x4_t t_u32x4;
- Winner_rand_state = psDelDec->RandState[ last_smple_idx ][ Winner_ind ];
- t_u32x4 = vceqq_s32( vld1q_s32( psDelDec->RandState[ last_smple_idx ] ), vdupq_n_s32( Winner_rand_state ) );
- t_u32x4 = vmvnq_u32( t_u32x4 );
- t_u32x4 = vshrq_n_u32( t_u32x4, 5 );
- tmp1_s32x4 = vld1q_s32( psSampleState[ 0 ].RD_Q10 );
- tmp2_s32x4 = vld1q_s32( psSampleState[ 1 ].RD_Q10 );
- tmp1_s32x4 = vaddq_s32( tmp1_s32x4, vreinterpretq_s32_u32( t_u32x4 ) );
- tmp2_s32x4 = vaddq_s32( tmp2_s32x4, vreinterpretq_s32_u32( t_u32x4 ) );
- vst1q_s32( psSampleState[ 0 ].RD_Q10, tmp1_s32x4 );
- vst1q_s32( psSampleState[ 1 ].RD_Q10, tmp2_s32x4 );
-
- /* Find worst in first set and best in second set */
- RDmax_Q10 = psSampleState[ 0 ].RD_Q10[ 0 ];
- RDmin_Q10 = psSampleState[ 1 ].RD_Q10[ 0 ];
- RDmax_ind = 0;
- RDmin_ind = 0;
- for( k = 1; k < nStatesDelayedDecision; k++ ) {
- /* find worst in first set */
- if( psSampleState[ 0 ].RD_Q10[ k ] > RDmax_Q10 ) {
- RDmax_Q10 = psSampleState[ 0 ].RD_Q10[ k ];
- RDmax_ind = k;
- }
- /* find best in second set */
- if( psSampleState[ 1 ].RD_Q10[ k ] < RDmin_Q10 ) {
- RDmin_Q10 = psSampleState[ 1 ].RD_Q10[ k ];
- RDmin_ind = k;
- }
- }
- }
-
- /* Replace a state if best from second set outperforms worst in first set */
- if( RDmin_Q10 < RDmax_Q10 ) {
- opus_int32 (*ptr)[NEON_MAX_DEL_DEC_STATES] = psDelDec->RandState;
- const int numOthers = (int)( ( sizeof( NSQ_del_decs_struct ) - sizeof( ( (NSQ_del_decs_struct *)0 )->sLPC_Q14 ) )
- / ( NEON_MAX_DEL_DEC_STATES * sizeof( opus_int32 ) ) );
- /* Only ( predictLPCOrder - 1 ) of sLPC_Q14 buffer need to be updated, though the first several */
- /* useless sLPC_Q14[] will be different comparing with C when predictLPCOrder < NSQ_LPC_BUF_LENGTH. */
- /* Here just update constant ( NSQ_LPC_BUF_LENGTH - 1 ) for simplicity. */
- for( j = i + 1; j < i + NSQ_LPC_BUF_LENGTH; j++ ) {
- psDelDec->sLPC_Q14[ j ][ RDmax_ind ] = psDelDec->sLPC_Q14[ j ][ RDmin_ind ];
- }
- for( j = 0; j < numOthers; j++ ) {
- ptr[ j ][ RDmax_ind ] = ptr[ j ][ RDmin_ind ];
- }
-
- psSampleState[ 0 ].Q_Q10[ RDmax_ind ] = psSampleState[ 1 ].Q_Q10[ RDmin_ind ];
- psSampleState[ 0 ].RD_Q10[ RDmax_ind ] = psSampleState[ 1 ].RD_Q10[ RDmin_ind ];
- psSampleState[ 0 ].xq_Q14[ RDmax_ind ] = psSampleState[ 1 ].xq_Q14[ RDmin_ind ];
- psSampleState[ 0 ].LF_AR_Q14[ RDmax_ind ] = psSampleState[ 1 ].LF_AR_Q14[ RDmin_ind ];
- psSampleState[ 0 ].Diff_Q14[ RDmax_ind ] = psSampleState[ 1 ].Diff_Q14[ RDmin_ind ];
- psSampleState[ 0 ].sLTP_shp_Q14[ RDmax_ind ] = psSampleState[ 1 ].sLTP_shp_Q14[ RDmin_ind ];
- psSampleState[ 0 ].LPC_exc_Q14[ RDmax_ind ] = psSampleState[ 1 ].LPC_exc_Q14[ RDmin_ind ];
- }
-
- /* Write samples from winner to output and long-term filter states */
- if( subfr > 0 || i >= decisionDelay ) {
- pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDelDec->Q_Q10[ last_smple_idx ][ Winner_ind ], 10 );
- xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
- silk_SMULWW( psDelDec->Xq_Q14[ last_smple_idx ][ Winner_ind ], delayedGain_Q10[ last_smple_idx ] ), 8 ) );
- NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDelDec->Shape_Q14[ last_smple_idx ][ Winner_ind ];
- sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDelDec->Pred_Q15[ last_smple_idx ][ Winner_ind ];
- }
- NSQ->sLTP_shp_buf_idx++;
- NSQ->sLTP_buf_idx++;
-
- /* Update states */
- vst1q_s32( psDelDec->LF_AR_Q14, vld1q_s32( psSampleState[ 0 ].LF_AR_Q14 ) );
- vst1q_s32( psDelDec->Diff_Q14, vld1q_s32( psSampleState[ 0 ].Diff_Q14 ) );
- vst1q_s32( psDelDec->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ], vld1q_s32( psSampleState[ 0 ].xq_Q14 ) );
- vst1q_s32( psDelDec->Xq_Q14[ *smpl_buf_idx ], vld1q_s32( psSampleState[ 0 ].xq_Q14 ) );
- tmp1_s32x4 = vld1q_s32( psSampleState[ 0 ].Q_Q10 );
- vst1q_s32( psDelDec->Q_Q10[ *smpl_buf_idx ], tmp1_s32x4 );
- vst1q_s32( psDelDec->Pred_Q15[ *smpl_buf_idx ], vshlq_n_s32( vld1q_s32( psSampleState[ 0 ].LPC_exc_Q14 ), 1 ) );
- vst1q_s32( psDelDec->Shape_Q14[ *smpl_buf_idx ], vld1q_s32( psSampleState[ 0 ].sLTP_shp_Q14 ) );
- tmp1_s32x4 = vrshrq_n_s32( tmp1_s32x4, 10 );
- tmp1_s32x4 = vaddq_s32( vld1q_s32( psDelDec->Seed ), tmp1_s32x4 );
- vst1q_s32( psDelDec->Seed, tmp1_s32x4 );
- vst1q_s32( psDelDec->RandState[ *smpl_buf_idx ], tmp1_s32x4 );
- vst1q_s32( psDelDec->RD_Q10, vld1q_s32( psSampleState[ 0 ].RD_Q10 ) );
- delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10;
- }
- /* Update LPC states */
- silk_memcpy( psDelDec->sLPC_Q14[ 0 ], psDelDec->sLPC_Q14[ length ], NEON_MAX_DEL_DEC_STATES * NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
-
- RESTORE_STACK;
-}
-
-static OPUS_INLINE void silk_SMULWB_8_neon(
- const opus_int16 *a,
- const int32x2_t b,
- opus_int32 *o
-)
-{
- const int16x8_t a_s16x8 = vld1q_s16( a );
- int32x4_t o0_s32x4, o1_s32x4;
-
- o0_s32x4 = vshll_n_s16( vget_low_s16( a_s16x8 ), 15 );
- o1_s32x4 = vshll_n_s16( vget_high_s16( a_s16x8 ), 15 );
- o0_s32x4 = vqdmulhq_lane_s32( o0_s32x4, b, 0 );
- o1_s32x4 = vqdmulhq_lane_s32( o1_s32x4, b, 0 );
- vst1q_s32( o, o0_s32x4 );
- vst1q_s32( o + 4, o1_s32x4 );
-}
-
-/* Only works when ( b >= -65536 ) && ( b < 65536 ). */
-static OPUS_INLINE void silk_SMULWW_small_b_4_neon(
- opus_int32 *a,
- const int32x2_t b_s32x2)
-{
- int32x4_t o_s32x4;
-
- o_s32x4 = vld1q_s32( a );
- o_s32x4 = vqdmulhq_lane_s32( o_s32x4, b_s32x2, 0 );
- vst1q_s32( a, o_s32x4 );
-}
-
-/* Only works when ( b >= -65536 ) && ( b < 65536 ). */
-static OPUS_INLINE void silk_SMULWW_small_b_8_neon(
- opus_int32 *a,
- const int32x2_t b_s32x2
-)
-{
- int32x4_t o0_s32x4, o1_s32x4;
-
- o0_s32x4 = vld1q_s32( a );
- o1_s32x4 = vld1q_s32( a + 4 );
- o0_s32x4 = vqdmulhq_lane_s32( o0_s32x4, b_s32x2, 0 );
- o1_s32x4 = vqdmulhq_lane_s32( o1_s32x4, b_s32x2, 0 );
- vst1q_s32( a, o0_s32x4 );
- vst1q_s32( a + 4, o1_s32x4 );
-}
-
-static OPUS_INLINE void silk_SMULWW_4_neon(
- opus_int32 *a,
- const int32x2_t b_s32x2)
-{
- int32x4_t a_s32x4, o_s32x4;
-
- a_s32x4 = vld1q_s32( a );
- o_s32x4 = vqdmulhq_lane_s32( a_s32x4, b_s32x2, 0 );
- o_s32x4 = vmlaq_lane_s32( o_s32x4, a_s32x4, b_s32x2, 1 );
- vst1q_s32( a, o_s32x4 );
-}
-
-static OPUS_INLINE void silk_SMULWW_8_neon(
- opus_int32 *a,
- const int32x2_t b_s32x2
-)
-{
- int32x4_t a0_s32x4, a1_s32x4, o0_s32x4, o1_s32x4;
-
- a0_s32x4 = vld1q_s32( a );
- a1_s32x4 = vld1q_s32( a + 4 );
- o0_s32x4 = vqdmulhq_lane_s32( a0_s32x4, b_s32x2, 0 );
- o1_s32x4 = vqdmulhq_lane_s32( a1_s32x4, b_s32x2, 0 );
- o0_s32x4 = vmlaq_lane_s32( o0_s32x4, a0_s32x4, b_s32x2, 1 );
- o1_s32x4 = vmlaq_lane_s32( o1_s32x4, a1_s32x4, b_s32x2, 1 );
- vst1q_s32( a, o0_s32x4 );
- vst1q_s32( a + 4, o1_s32x4 );
-}
-
-static OPUS_INLINE void silk_SMULWW_loop_neon(
- const opus_int16 *a,
- const opus_int32 b,
- opus_int32 *o,
- const opus_int loop_num
-)
-{
- opus_int i;
- int32x2_t b_s32x2;
-
- b_s32x2 = vdup_n_s32( b );
- for( i = 0; i < loop_num - 7; i += 8 ) {
- silk_SMULWB_8_neon( a + i, b_s32x2, o + i );
- }
- for( ; i < loop_num; i++ ) {
- o[ i ] = silk_SMULWW( a[ i ], b );
- }
-}
-
-static OPUS_INLINE void silk_nsq_del_dec_scale_states_neon(
- const silk_encoder_state *psEncC, /* I Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- NSQ_del_decs_struct psDelDec[], /* I/O Delayed decision states */
- const opus_int16 x16[], /* I Input */
- opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
- const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
- opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
- opus_int subfr, /* I Subframe number */
- const opus_int LTP_scale_Q14, /* I LTP state scaling */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
- const opus_int signal_type, /* I Signal type */
- const opus_int decisionDelay /* I Decision delay */
-)
-{
- opus_int i, lag;
- opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
-
- lag = pitchL[ subfr ];
- inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
- silk_assert( inv_gain_Q31 != 0 );
-
- /* Scale input */
- inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
- silk_SMULWW_loop_neon( x16, inv_gain_Q26, x_sc_Q10, psEncC->subfr_length );
-
- /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
- if( NSQ->rewhite_flag ) {
- if( subfr == 0 ) {
- /* Do LTP downscaling */
- inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
- }
- silk_SMULWW_loop_neon( sLTP + NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2, inv_gain_Q31, sLTP_Q15 + NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2, lag + LTP_ORDER / 2 );
- }
-
- /* Adjust for changing gain */
- if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
- int32x2_t gain_adj_Q16_s32x2;
- gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
-
- /* Scale long-term shaping state */
- if( ( gain_adj_Q16 >= -65536 ) && ( gain_adj_Q16 < 65536 ) ) {
- gain_adj_Q16_s32x2 = vdup_n_s32( silk_LSHIFT32( gain_adj_Q16, 15 ) );
- for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 7; i += 8 ) {
- silk_SMULWW_small_b_8_neon( NSQ->sLTP_shp_Q14 + i, gain_adj_Q16_s32x2 );
- }
- for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) {
- NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
- }
-
- /* Scale long-term prediction state */
- if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
- for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay - 7; i += 8 ) {
- silk_SMULWW_small_b_8_neon( sLTP_Q15 + i, gain_adj_Q16_s32x2 );
- }
- for( ; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
- sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
- }
- }
-
- /* Scale scalar states */
- silk_SMULWW_small_b_4_neon( psDelDec->LF_AR_Q14, gain_adj_Q16_s32x2 );
- silk_SMULWW_small_b_4_neon( psDelDec->Diff_Q14, gain_adj_Q16_s32x2 );
-
- /* Scale short-term prediction and shaping states */
- for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
- silk_SMULWW_small_b_4_neon( psDelDec->sLPC_Q14[ i ], gain_adj_Q16_s32x2 );
- }
-
- for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
- silk_SMULWW_small_b_4_neon( psDelDec->sAR2_Q14[ i ], gain_adj_Q16_s32x2 );
- }
-
- for( i = 0; i < DECISION_DELAY; i++ ) {
- silk_SMULWW_small_b_4_neon( psDelDec->Pred_Q15[ i ], gain_adj_Q16_s32x2 );
- silk_SMULWW_small_b_4_neon( psDelDec->Shape_Q14[ i ], gain_adj_Q16_s32x2 );
- }
- } else {
- gain_adj_Q16_s32x2 = vdup_n_s32( silk_LSHIFT32( gain_adj_Q16 & 0x0000FFFF, 15 ) );
- gain_adj_Q16_s32x2 = vset_lane_s32( gain_adj_Q16 >> 16, gain_adj_Q16_s32x2, 1 );
- for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 7; i += 8 ) {
- silk_SMULWW_8_neon( NSQ->sLTP_shp_Q14 + i, gain_adj_Q16_s32x2 );
- }
- for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) {
- NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
- }
-
- /* Scale long-term prediction state */
- if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
- for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay - 7; i += 8 ) {
- silk_SMULWW_8_neon( sLTP_Q15 + i, gain_adj_Q16_s32x2 );
- }
- for( ; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
- sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
- }
- }
-
- /* Scale scalar states */
- silk_SMULWW_4_neon( psDelDec->LF_AR_Q14, gain_adj_Q16_s32x2 );
- silk_SMULWW_4_neon( psDelDec->Diff_Q14, gain_adj_Q16_s32x2 );
-
- /* Scale short-term prediction and shaping states */
- for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
- silk_SMULWW_4_neon( psDelDec->sLPC_Q14[ i ], gain_adj_Q16_s32x2 );
- }
-
- for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
- silk_SMULWW_4_neon( psDelDec->sAR2_Q14[ i ], gain_adj_Q16_s32x2 );
- }
-
- for( i = 0; i < DECISION_DELAY; i++ ) {
- silk_SMULWW_4_neon( psDelDec->Pred_Q15[ i ], gain_adj_Q16_s32x2 );
- silk_SMULWW_4_neon( psDelDec->Shape_Q14[ i ], gain_adj_Q16_s32x2 );
- }
- }
-
- /* Save inverse gain */
- NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
- }
-}
diff --git a/thirdparty/opus/silk/arm/NSQ_neon.h b/thirdparty/opus/silk/arm/NSQ_neon.h
index b31d9442d6..77c946af85 100644
--- a/thirdparty/opus/silk/arm/NSQ_neon.h
+++ b/thirdparty/opus/silk/arm/NSQ_neon.h
@@ -28,31 +28,30 @@ POSSIBILITY OF SUCH DAMAGE.
#define SILK_NSQ_NEON_H
#include "cpu_support.h"
-#include "SigProc_FIX.h"
#undef silk_short_prediction_create_arch_coef
/* For vectorized calc, reverse a_Q12 coefs, convert to 32-bit, and shift for vqdmulhq_s32. */
static OPUS_INLINE void silk_short_prediction_create_arch_coef_neon(opus_int32 *out, const opus_int16 *in, opus_int order)
{
- out[15] = silk_LSHIFT32(in[0], 15);
- out[14] = silk_LSHIFT32(in[1], 15);
- out[13] = silk_LSHIFT32(in[2], 15);
- out[12] = silk_LSHIFT32(in[3], 15);
- out[11] = silk_LSHIFT32(in[4], 15);
- out[10] = silk_LSHIFT32(in[5], 15);
- out[9] = silk_LSHIFT32(in[6], 15);
- out[8] = silk_LSHIFT32(in[7], 15);
- out[7] = silk_LSHIFT32(in[8], 15);
- out[6] = silk_LSHIFT32(in[9], 15);
+ out[15] = in[0] << 15;
+ out[14] = in[1] << 15;
+ out[13] = in[2] << 15;
+ out[12] = in[3] << 15;
+ out[11] = in[4] << 15;
+ out[10] = in[5] << 15;
+ out[9] = in[6] << 15;
+ out[8] = in[7] << 15;
+ out[7] = in[8] << 15;
+ out[6] = in[9] << 15;
if (order == 16)
{
- out[5] = silk_LSHIFT32(in[10], 15);
- out[4] = silk_LSHIFT32(in[11], 15);
- out[3] = silk_LSHIFT32(in[12], 15);
- out[2] = silk_LSHIFT32(in[13], 15);
- out[1] = silk_LSHIFT32(in[14], 15);
- out[0] = silk_LSHIFT32(in[15], 15);
+ out[5] = in[10] << 15;
+ out[4] = in[11] << 15;
+ out[3] = in[12] << 15;
+ out[2] = in[13] << 15;
+ out[1] = in[14] << 15;
+ out[0] = in[15] << 15;
}
else
{
diff --git a/thirdparty/opus/silk/arm/arm_silk_map.c b/thirdparty/opus/silk/arm/arm_silk_map.c
index 0b9bfec2ca..9bd86a7b21 100644
--- a/thirdparty/opus/silk/arm/arm_silk_map.c
+++ b/thirdparty/opus/silk/arm/arm_silk_map.c
@@ -28,62 +28,13 @@ POSSIBILITY OF SUCH DAMAGE.
# include "config.h"
#endif
-#include "main_FIX.h"
#include "NSQ.h"
-#include "SigProc_FIX.h"
#if defined(OPUS_HAVE_RTCD)
# if (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
!defined(OPUS_ARM_PRESUME_NEON_INTR))
-void (*const SILK_BIQUAD_ALT_STRIDE2_IMPL[OPUS_ARCHMASK + 1])(
- const opus_int16 *in, /* I input signal */
- const opus_int32 *B_Q28, /* I MA coefficients [3] */
- const opus_int32 *A_Q28, /* I AR coefficients [2] */
- opus_int32 *S, /* I/O State vector [4] */
- opus_int16 *out, /* O output signal */
- const opus_int32 len /* I signal length (must be even) */
-) = {
- silk_biquad_alt_stride2_c, /* ARMv4 */
- silk_biquad_alt_stride2_c, /* EDSP */
- silk_biquad_alt_stride2_c, /* Media */
- silk_biquad_alt_stride2_neon, /* Neon */
-};
-
-opus_int32 (*const SILK_LPC_INVERSE_PRED_GAIN_IMPL[OPUS_ARCHMASK + 1])( /* O Returns inverse prediction gain in energy domain, Q30 */
- const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
- const opus_int order /* I Prediction order */
-) = {
- silk_LPC_inverse_pred_gain_c, /* ARMv4 */
- silk_LPC_inverse_pred_gain_c, /* EDSP */
- silk_LPC_inverse_pred_gain_c, /* Media */
- silk_LPC_inverse_pred_gain_neon, /* Neon */
-};
-
-void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
- const silk_encoder_state *psEncC, /* I Encoder State */
- silk_nsq_state *NSQ, /* I/O NSQ state */
- SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int16 x16[], /* I Input */
- opus_int8 pulses[], /* O Quantized pulse signal */
- const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
- const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
- const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
- const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
- const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
- const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
- const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
- const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
- const opus_int LTP_scale_Q14 /* I LTP state scaling */
-) = {
- silk_NSQ_del_dec_c, /* ARMv4 */
- silk_NSQ_del_dec_c, /* EDSP */
- silk_NSQ_del_dec_c, /* Media */
- silk_NSQ_del_dec_neon, /* Neon */
-};
-
/*There is no table for silk_noise_shape_quantizer_short_prediction because the
NEON version takes different parameters than the C version.
Instead RTCD is done via if statements at the call sites.
@@ -101,23 +52,4 @@ opus_int32
# endif
-# if defined(FIXED_POINT) && \
- defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
-
-void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK + 1])(
- opus_int32 *corr, /* O Result [order + 1] */
- opus_int *scale, /* O Scaling of the correlation vector */
- const opus_int16 *input, /* I Input data to correlate */
- const opus_int warping_Q16, /* I Warping coefficient */
- const opus_int length, /* I Length of input */
- const opus_int order /* I Correlation order (even) */
-) = {
- silk_warped_autocorrelation_FIX_c, /* ARMv4 */
- silk_warped_autocorrelation_FIX_c, /* EDSP */
- silk_warped_autocorrelation_FIX_c, /* Media */
- silk_warped_autocorrelation_FIX_neon, /* Neon */
-};
-
-# endif
-
#endif /* OPUS_HAVE_RTCD */
diff --git a/thirdparty/opus/silk/arm/biquad_alt_arm.h b/thirdparty/opus/silk/arm/biquad_alt_arm.h
deleted file mode 100644
index 66ea9f43dd..0000000000
--- a/thirdparty/opus/silk/arm/biquad_alt_arm.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/***********************************************************************
-Copyright (c) 2017 Google Inc.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifndef SILK_BIQUAD_ALT_ARM_H
-# define SILK_BIQUAD_ALT_ARM_H
-
-# include "celt/arm/armcpu.h"
-
-# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-void silk_biquad_alt_stride2_neon(
- const opus_int16 *in, /* I input signal */
- const opus_int32 *B_Q28, /* I MA coefficients [3] */
- const opus_int32 *A_Q28, /* I AR coefficients [2] */
- opus_int32 *S, /* I/O State vector [4] */
- opus_int16 *out, /* O output signal */
- const opus_int32 len /* I signal length (must be even) */
-);
-
-# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
-# define OVERRIDE_silk_biquad_alt_stride2 (1)
-# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), PRESUME_NEON(silk_biquad_alt_stride2)(in, B_Q28, A_Q28, S, out, len))
-# endif
-# endif
-
-# if !defined(OVERRIDE_silk_biquad_alt_stride2)
-/*Is run-time CPU detection enabled on this platform?*/
-# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
-extern void (*const SILK_BIQUAD_ALT_STRIDE2_IMPL[OPUS_ARCHMASK+1])(
- const opus_int16 *in, /* I input signal */
- const opus_int32 *B_Q28, /* I MA coefficients [3] */
- const opus_int32 *A_Q28, /* I AR coefficients [2] */
- opus_int32 *S, /* I/O State vector [4] */
- opus_int16 *out, /* O output signal */
- const opus_int32 len /* I signal length (must be even) */
- );
-# define OVERRIDE_silk_biquad_alt_stride2 (1)
-# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((*SILK_BIQUAD_ALT_STRIDE2_IMPL[(arch)&OPUS_ARCHMASK])(in, B_Q28, A_Q28, S, out, len))
-# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
-# define OVERRIDE_silk_biquad_alt_stride2 (1)
-# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_neon(in, B_Q28, A_Q28, S, out, len))
-# endif
-# endif
-
-#endif /* end SILK_BIQUAD_ALT_ARM_H */
diff --git a/thirdparty/opus/silk/arm/biquad_alt_neon_intr.c b/thirdparty/opus/silk/arm/biquad_alt_neon_intr.c
deleted file mode 100644
index 9715733185..0000000000
--- a/thirdparty/opus/silk/arm/biquad_alt_neon_intr.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/***********************************************************************
-Copyright (c) 2017 Google Inc.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <arm_neon.h>
-#ifdef OPUS_CHECK_ASM
-# include <string.h>
-# include "stack_alloc.h"
-#endif
-#include "SigProc_FIX.h"
-
-static inline void silk_biquad_alt_stride2_kernel( const int32x4_t A_L_s32x4, const int32x4_t A_U_s32x4, const int32x4_t B_Q28_s32x4, const int32x2_t t_s32x2, const int32x4_t in_s32x4, int32x4_t *S_s32x4, int32x2_t *out32_Q14_s32x2 )
-{
- int32x4_t t_s32x4, out32_Q14_s32x4;
-
- *out32_Q14_s32x2 = vadd_s32( vget_low_s32( *S_s32x4 ), t_s32x2 ); /* silk_SMLAWB( S{0,1}, B_Q28[ 0 ], in{0,1} ) */
- *S_s32x4 = vcombine_s32( vget_high_s32( *S_s32x4 ), vdup_n_s32( 0 ) ); /* S{0,1} = S{2,3}; S{2,3} = 0; */
- *out32_Q14_s32x2 = vshl_n_s32( *out32_Q14_s32x2, 2 ); /* out32_Q14_{0,1} = silk_LSHIFT( silk_SMLAWB( S{0,1}, B_Q28[ 0 ], in{0,1} ), 2 ); */
- out32_Q14_s32x4 = vcombine_s32( *out32_Q14_s32x2, *out32_Q14_s32x2 ); /* out32_Q14_{0,1,0,1} */
- t_s32x4 = vqdmulhq_s32( out32_Q14_s32x4, A_L_s32x4 ); /* silk_SMULWB( out32_Q14_{0,1,0,1}, A{0,0,1,1}_L_Q28 ) */
- *S_s32x4 = vrsraq_n_s32( *S_s32x4, t_s32x4, 14 ); /* S{0,1} = S{2,3} + silk_RSHIFT_ROUND(); S{2,3} = silk_RSHIFT_ROUND(); */
- t_s32x4 = vqdmulhq_s32( out32_Q14_s32x4, A_U_s32x4 ); /* silk_SMULWB( out32_Q14_{0,1,0,1}, A{0,0,1,1}_U_Q28 ) */
- *S_s32x4 = vaddq_s32( *S_s32x4, t_s32x4 ); /* S0 = silk_SMLAWB( S{0,1,2,3}, out32_Q14_{0,1,0,1}, A{0,0,1,1}_U_Q28 ); */
- t_s32x4 = vqdmulhq_s32( in_s32x4, B_Q28_s32x4 ); /* silk_SMULWB( B_Q28[ {1,1,2,2} ], in{0,1,0,1} ) */
- *S_s32x4 = vaddq_s32( *S_s32x4, t_s32x4 ); /* S0 = silk_SMLAWB( S0, B_Q28[ {1,1,2,2} ], in{0,1,0,1} ); */
-}
-
-void silk_biquad_alt_stride2_neon(
- const opus_int16 *in, /* I input signal */
- const opus_int32 *B_Q28, /* I MA coefficients [3] */
- const opus_int32 *A_Q28, /* I AR coefficients [2] */
- opus_int32 *S, /* I/O State vector [4] */
- opus_int16 *out, /* O output signal */
- const opus_int32 len /* I signal length (must be even) */
-)
-{
- /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
- opus_int k = 0;
- const int32x2_t offset_s32x2 = vdup_n_s32( (1<<14) - 1 );
- const int32x4_t offset_s32x4 = vcombine_s32( offset_s32x2, offset_s32x2 );
- int16x4_t in_s16x4 = vdup_n_s16( 0 );
- int16x4_t out_s16x4;
- int32x2_t A_Q28_s32x2, A_L_s32x2, A_U_s32x2, B_Q28_s32x2, t_s32x2;
- int32x4_t A_L_s32x4, A_U_s32x4, B_Q28_s32x4, S_s32x4, out32_Q14_s32x4;
- int32x2x2_t t0_s32x2x2, t1_s32x2x2, t2_s32x2x2, S_s32x2x2;
-
-#ifdef OPUS_CHECK_ASM
- opus_int32 S_c[ 4 ];
- VARDECL( opus_int16, out_c );
- SAVE_STACK;
- ALLOC( out_c, 2 * len, opus_int16 );
-
- silk_memcpy( &S_c, S, sizeof( S_c ) );
- silk_biquad_alt_stride2_c( in, B_Q28, A_Q28, S_c, out_c, len );
-#endif
-
- /* Negate A_Q28 values and split in two parts */
- A_Q28_s32x2 = vld1_s32( A_Q28 );
- A_Q28_s32x2 = vneg_s32( A_Q28_s32x2 );
- A_L_s32x2 = vshl_n_s32( A_Q28_s32x2, 18 ); /* ( -A_Q28[] & 0x00003FFF ) << 18 */
- A_L_s32x2 = vreinterpret_s32_u32( vshr_n_u32( vreinterpret_u32_s32( A_L_s32x2 ), 3 ) ); /* ( -A_Q28[] & 0x00003FFF ) << 15 */
- A_U_s32x2 = vshr_n_s32( A_Q28_s32x2, 14 ); /* silk_RSHIFT( -A_Q28[], 14 ) */
- A_U_s32x2 = vshl_n_s32( A_U_s32x2, 16 ); /* silk_RSHIFT( -A_Q28[], 14 ) << 16 (Clip two leading bits to conform to C function.) */
- A_U_s32x2 = vshr_n_s32( A_U_s32x2, 1 ); /* silk_RSHIFT( -A_Q28[], 14 ) << 15 */
-
- B_Q28_s32x2 = vld1_s32( B_Q28 );
- t_s32x2 = vld1_s32( B_Q28 + 1 );
- t0_s32x2x2 = vzip_s32( A_L_s32x2, A_L_s32x2 );
- t1_s32x2x2 = vzip_s32( A_U_s32x2, A_U_s32x2 );
- t2_s32x2x2 = vzip_s32( t_s32x2, t_s32x2 );
- A_L_s32x4 = vcombine_s32( t0_s32x2x2.val[ 0 ], t0_s32x2x2.val[ 1 ] ); /* A{0,0,1,1}_L_Q28 */
- A_U_s32x4 = vcombine_s32( t1_s32x2x2.val[ 0 ], t1_s32x2x2.val[ 1 ] ); /* A{0,0,1,1}_U_Q28 */
- B_Q28_s32x4 = vcombine_s32( t2_s32x2x2.val[ 0 ], t2_s32x2x2.val[ 1 ] ); /* B_Q28[ {1,1,2,2} ] */
- S_s32x4 = vld1q_s32( S ); /* S0 = S[ 0 ]; S3 = S[ 3 ]; */
- S_s32x2x2 = vtrn_s32( vget_low_s32( S_s32x4 ), vget_high_s32( S_s32x4 ) ); /* S2 = S[ 1 ]; S1 = S[ 2 ]; */
- S_s32x4 = vcombine_s32( S_s32x2x2.val[ 0 ], S_s32x2x2.val[ 1 ] );
-
- for( ; k < len - 1; k += 2 ) {
- int32x4_t in_s32x4[ 2 ], t_s32x4;
- int32x2_t out32_Q14_s32x2[ 2 ];
-
- /* S[ 2 * i + 0 ], S[ 2 * i + 1 ], S[ 2 * i + 2 ], S[ 2 * i + 3 ]: Q12 */
- in_s16x4 = vld1_s16( &in[ 2 * k ] ); /* in{0,1,2,3} = in[ 2 * k + {0,1,2,3} ]; */
- in_s32x4[ 0 ] = vshll_n_s16( in_s16x4, 15 ); /* in{0,1,2,3} << 15 */
- t_s32x4 = vqdmulhq_lane_s32( in_s32x4[ 0 ], B_Q28_s32x2, 0 ); /* silk_SMULWB( B_Q28[ 0 ], in{0,1,2,3} ) */
- in_s32x4[ 1 ] = vcombine_s32( vget_high_s32( in_s32x4[ 0 ] ), vget_high_s32( in_s32x4[ 0 ] ) ); /* in{2,3,2,3} << 15 */
- in_s32x4[ 0 ] = vcombine_s32( vget_low_s32 ( in_s32x4[ 0 ] ), vget_low_s32 ( in_s32x4[ 0 ] ) ); /* in{0,1,0,1} << 15 */
- silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, vget_low_s32 ( t_s32x4 ), in_s32x4[ 0 ], &S_s32x4, &out32_Q14_s32x2[ 0 ] );
- silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, vget_high_s32( t_s32x4 ), in_s32x4[ 1 ], &S_s32x4, &out32_Q14_s32x2[ 1 ] );
-
- /* Scale back to Q0 and saturate */
- out32_Q14_s32x4 = vcombine_s32( out32_Q14_s32x2[ 0 ], out32_Q14_s32x2[ 1 ] ); /* out32_Q14_{0,1,2,3} */
- out32_Q14_s32x4 = vaddq_s32( out32_Q14_s32x4, offset_s32x4 ); /* out32_Q14_{0,1,2,3} + (1<<14) - 1 */
- out_s16x4 = vqshrn_n_s32( out32_Q14_s32x4, 14 ); /* (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,2,3} + (1<<14) - 1, 14 ) ) */
- vst1_s16( &out[ 2 * k ], out_s16x4 ); /* out[ 2 * k + {0,1,2,3} ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,2,3} + (1<<14) - 1, 14 ) ); */
- }
-
- /* Process leftover. */
- if( k < len ) {
- int32x4_t in_s32x4;
- int32x2_t out32_Q14_s32x2;
-
- /* S[ 2 * i + 0 ], S[ 2 * i + 1 ]: Q12 */
- in_s16x4 = vld1_lane_s16( &in[ 2 * k + 0 ], in_s16x4, 0 ); /* in{0,1} = in[ 2 * k + {0,1} ]; */
- in_s16x4 = vld1_lane_s16( &in[ 2 * k + 1 ], in_s16x4, 1 ); /* in{0,1} = in[ 2 * k + {0,1} ]; */
- in_s32x4 = vshll_n_s16( in_s16x4, 15 ); /* in{0,1} << 15 */
- t_s32x2 = vqdmulh_lane_s32( vget_low_s32( in_s32x4 ), B_Q28_s32x2, 0 ); /* silk_SMULWB( B_Q28[ 0 ], in{0,1} ) */
- in_s32x4 = vcombine_s32( vget_low_s32( in_s32x4 ), vget_low_s32( in_s32x4 ) ); /* in{0,1,0,1} << 15 */
- silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, t_s32x2, in_s32x4, &S_s32x4, &out32_Q14_s32x2 );
-
- /* Scale back to Q0 and saturate */
- out32_Q14_s32x2 = vadd_s32( out32_Q14_s32x2, offset_s32x2 ); /* out32_Q14_{0,1} + (1<<14) - 1 */
- out32_Q14_s32x4 = vcombine_s32( out32_Q14_s32x2, out32_Q14_s32x2 ); /* out32_Q14_{0,1,0,1} + (1<<14) - 1 */
- out_s16x4 = vqshrn_n_s32( out32_Q14_s32x4, 14 ); /* (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,0,1} + (1<<14) - 1, 14 ) ) */
- vst1_lane_s16( &out[ 2 * k + 0 ], out_s16x4, 0 ); /* out[ 2 * k + 0 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_0 + (1<<14) - 1, 14 ) ); */
- vst1_lane_s16( &out[ 2 * k + 1 ], out_s16x4, 1 ); /* out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_1 + (1<<14) - 1, 14 ) ); */
- }
-
- vst1q_lane_s32( &S[ 0 ], S_s32x4, 0 ); /* S[ 0 ] = S0; */
- vst1q_lane_s32( &S[ 1 ], S_s32x4, 2 ); /* S[ 1 ] = S2; */
- vst1q_lane_s32( &S[ 2 ], S_s32x4, 1 ); /* S[ 2 ] = S1; */
- vst1q_lane_s32( &S[ 3 ], S_s32x4, 3 ); /* S[ 3 ] = S3; */
-
-#ifdef OPUS_CHECK_ASM
- silk_assert( !memcmp( S_c, S, sizeof( S_c ) ) );
- silk_assert( !memcmp( out_c, out, 2 * len * sizeof( opus_int16 ) ) );
- RESTORE_STACK;
-#endif
-}
diff --git a/thirdparty/opus/silk/arm/macros_armv4.h b/thirdparty/opus/silk/arm/macros_armv4.h
index 877eb18dd5..3f30e97288 100644
--- a/thirdparty/opus/silk/arm/macros_armv4.h
+++ b/thirdparty/opus/silk/arm/macros_armv4.h
@@ -28,11 +28,6 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef SILK_MACROS_ARMv4_H
#define SILK_MACROS_ARMv4_H
-/* This macro only avoids the undefined behaviour from a left shift of
- a negative value. It should only be used in macros that can't include
- SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
-#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
-
/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
#undef silk_SMULWB
static OPUS_INLINE opus_int32 silk_SMULWB_armv4(opus_int32 a, opus_int16 b)
@@ -43,7 +38,7 @@ static OPUS_INLINE opus_int32 silk_SMULWB_armv4(opus_int32 a, opus_int16 b)
"#silk_SMULWB\n\t"
"smull %0, %1, %2, %3\n\t"
: "=&r"(rd_lo), "=&r"(rd_hi)
- : "%r"(a), "r"(SAFE_SHL(b,16))
+ : "%r"(a), "r"(b<<16)
);
return rd_hi;
}
@@ -85,7 +80,7 @@ static OPUS_INLINE opus_int32 silk_SMULWW_armv4(opus_int32 a, opus_int32 b)
: "=&r"(rd_lo), "=&r"(rd_hi)
: "%r"(a), "r"(b)
);
- return SAFE_SHL(rd_hi,16)+(rd_lo>>16);
+ return (rd_hi<<16)+(rd_lo>>16);
}
#define silk_SMULWW(a, b) (silk_SMULWW_armv4(a, b))
@@ -101,10 +96,8 @@ static OPUS_INLINE opus_int32 silk_SMLAWW_armv4(opus_int32 a, opus_int32 b,
: "=&r"(rd_lo), "=&r"(rd_hi)
: "%r"(b), "r"(c)
);
- return a+SAFE_SHL(rd_hi,16)+(rd_lo>>16);
+ return a+(rd_hi<<16)+(rd_lo>>16);
}
#define silk_SMLAWW(a, b, c) (silk_SMLAWW_armv4(a, b, c))
-#undef SAFE_SHL
-
#endif /* SILK_MACROS_ARMv4_H */
diff --git a/thirdparty/opus/silk/arm/macros_armv5e.h b/thirdparty/opus/silk/arm/macros_armv5e.h
index b14ec65ddb..aad4117e46 100644
--- a/thirdparty/opus/silk/arm/macros_armv5e.h
+++ b/thirdparty/opus/silk/arm/macros_armv5e.h
@@ -29,11 +29,6 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef SILK_MACROS_ARMv5E_H
#define SILK_MACROS_ARMv5E_H
-/* This macro only avoids the undefined behaviour from a left shift of
- a negative value. It should only be used in macros that can't include
- SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
-#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
-
/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
#undef silk_SMULWB
static OPUS_INLINE opus_int32 silk_SMULWB_armv5e(opus_int32 a, opus_int16 b)
@@ -195,7 +190,7 @@ static OPUS_INLINE opus_int32 silk_CLZ16_armv5(opus_int16 in16)
"#silk_CLZ16\n\t"
"clz %0, %1;\n"
: "=r"(res)
- : "r"(SAFE_SHL(in16,16)|0x8000)
+ : "r"(in16<<16|0x8000)
);
return res;
}
@@ -215,6 +210,4 @@ static OPUS_INLINE opus_int32 silk_CLZ32_armv5(opus_int32 in32)
}
#define silk_CLZ32(in32) (silk_CLZ32_armv5(in32))
-#undef SAFE_SHL
-
#endif /* SILK_MACROS_ARMv5E_H */
diff --git a/thirdparty/opus/silk/biquad_alt.c b/thirdparty/opus/silk/biquad_alt.c
index 54566a43c0..d55f5ee92e 100644
--- a/thirdparty/opus/silk/biquad_alt.c
+++ b/thirdparty/opus/silk/biquad_alt.c
@@ -39,13 +39,14 @@ POSSIBILITY OF SUCH DAMAGE.
#include "SigProc_FIX.h"
/* Second order ARMA filter, alternative implementation */
-void silk_biquad_alt_stride1(
+void silk_biquad_alt(
const opus_int16 *in, /* I input signal */
const opus_int32 *B_Q28, /* I MA coefficients [3] */
const opus_int32 *A_Q28, /* I AR coefficients [2] */
opus_int32 *S, /* I/O State vector [2] */
opus_int16 *out, /* O output signal */
- const opus_int32 len /* I signal length (must be even) */
+ const opus_int32 len, /* I signal length (must be even) */
+ opus_int stride /* I Operate on interleaved signal if > 1 */
)
{
/* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
@@ -60,7 +61,7 @@ void silk_biquad_alt_stride1(
for( k = 0; k < len; k++ ) {
/* S[ 0 ], S[ 1 ]: Q12 */
- inval = in[ k ];
+ inval = in[ k * stride ];
out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
@@ -72,50 +73,6 @@ void silk_biquad_alt_stride1(
S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
/* Scale back to Q0 and saturate */
- out[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
- }
-}
-
-void silk_biquad_alt_stride2_c(
- const opus_int16 *in, /* I input signal */
- const opus_int32 *B_Q28, /* I MA coefficients [3] */
- const opus_int32 *A_Q28, /* I AR coefficients [2] */
- opus_int32 *S, /* I/O State vector [4] */
- opus_int16 *out, /* O output signal */
- const opus_int32 len /* I signal length (must be even) */
-)
-{
- /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
- opus_int k;
- opus_int32 A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14[ 2 ];
-
- /* Negate A_Q28 values and split in two parts */
- A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */
- A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */
- A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */
- A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */
-
- for( k = 0; k < len; k++ ) {
- /* S[ 0 ], S[ 1 ], S[ 2 ], S[ 3 ]: Q12 */
- out32_Q14[ 0 ] = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], in[ 2 * k + 0 ] ), 2 );
- out32_Q14[ 1 ] = silk_LSHIFT( silk_SMLAWB( S[ 2 ], B_Q28[ 0 ], in[ 2 * k + 1 ] ), 2 );
-
- S[ 0 ] = S[ 1 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A0_L_Q28 ), 14 );
- S[ 2 ] = S[ 3 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A0_L_Q28 ), 14 );
- S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14[ 0 ], A0_U_Q28 );
- S[ 2 ] = silk_SMLAWB( S[ 2 ], out32_Q14[ 1 ], A0_U_Q28 );
- S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], in[ 2 * k + 0 ] );
- S[ 2 ] = silk_SMLAWB( S[ 2 ], B_Q28[ 1 ], in[ 2 * k + 1 ] );
-
- S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A1_L_Q28 ), 14 );
- S[ 3 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A1_L_Q28 ), 14 );
- S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14[ 0 ], A1_U_Q28 );
- S[ 3 ] = silk_SMLAWB( S[ 3 ], out32_Q14[ 1 ], A1_U_Q28 );
- S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], in[ 2 * k + 0 ] );
- S[ 3 ] = silk_SMLAWB( S[ 3 ], B_Q28[ 2 ], in[ 2 * k + 1 ] );
-
- /* Scale back to Q0 and saturate */
- out[ 2 * k + 0 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 0 ] + (1<<14) - 1, 14 ) );
- out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 1 ] + (1<<14) - 1, 14 ) );
+ out[ k * stride ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
}
}
diff --git a/thirdparty/opus/silk/bwexpander.c b/thirdparty/opus/silk/bwexpander.c
index afa97907ec..2eb4456695 100644
--- a/thirdparty/opus/silk/bwexpander.c
+++ b/thirdparty/opus/silk/bwexpander.c
@@ -45,7 +45,7 @@ void silk_bwexpander(
/* Bias in silk_SMULWB can lead to unstable filters */
for( i = 0; i < d - 1; i++ ) {
ar[ i ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ i ] ), 16 );
- chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
+ chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
}
ar[ d - 1 ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ d - 1 ] ), 16 );
}
diff --git a/thirdparty/opus/silk/check_control_input.c b/thirdparty/opus/silk/check_control_input.c
index 739fb01f1e..b5de9ce48d 100644
--- a/thirdparty/opus/silk/check_control_input.c
+++ b/thirdparty/opus/silk/check_control_input.c
@@ -38,7 +38,7 @@ opus_int check_control_input(
silk_EncControlStruct *encControl /* I Control structure */
)
{
- celt_assert( encControl != NULL );
+ silk_assert( encControl != NULL );
if( ( ( encControl->API_sampleRate != 8000 ) &&
( encControl->API_sampleRate != 12000 ) &&
@@ -59,46 +59,46 @@ opus_int check_control_input(
( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) ||
( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) ||
( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return SILK_ENC_FS_NOT_SUPPORTED;
}
if( encControl->payloadSize_ms != 10 &&
encControl->payloadSize_ms != 20 &&
encControl->payloadSize_ms != 40 &&
encControl->payloadSize_ms != 60 ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;
}
if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return SILK_ENC_INVALID_LOSS_RATE;
}
if( encControl->useDTX < 0 || encControl->useDTX > 1 ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return SILK_ENC_INVALID_DTX_SETTING;
}
if( encControl->useCBR < 0 || encControl->useCBR > 1 ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return SILK_ENC_INVALID_CBR_SETTING;
}
if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return SILK_ENC_INVALID_INBAND_FEC_SETTING;
}
if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
}
if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
}
if( encControl->nChannelsInternal > encControl->nChannelsAPI ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
}
if( encControl->complexity < 0 || encControl->complexity > 10 ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return SILK_ENC_INVALID_COMPLEXITY_SETTING;
}
diff --git a/thirdparty/opus/silk/control.h b/thirdparty/opus/silk/control.h
index b76ec33cd6..747e5426a0 100644
--- a/thirdparty/opus/silk/control.h
+++ b/thirdparty/opus/silk/control.h
@@ -77,9 +77,6 @@ typedef struct {
/* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */
opus_int useInBandFEC;
- /* I: Flag to actually code in-band Forward Error Correction (FEC) in the current packet; 0/1 */
- opus_int LBRR_coded;
-
/* I: Flag to enable discontinuous transmission (DTX); 0/1 */
opus_int useDTX;
@@ -113,11 +110,6 @@ typedef struct {
/* O: Tells the Opus encoder we're ready to switch */
opus_int switchReady;
- /* O: SILK Signal type */
- opus_int signalType;
-
- /* O: SILK offset (dithering) */
- opus_int offset;
} silk_EncControlStruct;
/**************************************************************************/
diff --git a/thirdparty/opus/silk/control_SNR.c b/thirdparty/opus/silk/control_SNR.c
index 9a6db27543..cee87eb0d8 100644
--- a/thirdparty/opus/silk/control_SNR.c
+++ b/thirdparty/opus/silk/control_SNR.c
@@ -32,82 +32,45 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main.h"
#include "tuning_parameters.h"
-/* These tables hold SNR values divided by 21 (so they fit in 8 bits)
- for different target bitrates spaced at 400 bps interval. The first
- 10 values are omitted (0-4 kb/s) because they're all zeros.
- These tables were obtained by running different SNRs through the
- encoder and measuring the active bitrate. */
-static const unsigned char silk_TargetRate_NB_21[117 - 10] = {
- 0, 15, 39, 52, 61, 68,
- 74, 79, 84, 88, 92, 95, 99,102,105,108,111,114,117,119,122,124,
- 126,129,131,133,135,137,139,142,143,145,147,149,151,153,155,157,
- 158,160,162,163,165,167,168,170,171,173,174,176,177,179,180,182,
- 183,185,186,187,189,190,192,193,194,196,197,199,200,201,203,204,
- 205,207,208,209,211,212,213,215,216,217,219,220,221,223,224,225,
- 227,228,230,231,232,234,235,236,238,239,241,242,243,245,246,248,
- 249,250,252,253,255
-};
-
-static const unsigned char silk_TargetRate_MB_21[165 - 10] = {
- 0, 0, 28, 43, 52, 59,
- 65, 70, 74, 78, 81, 85, 87, 90, 93, 95, 98,100,102,105,107,109,
- 111,113,115,116,118,120,122,123,125,127,128,130,131,133,134,136,
- 137,138,140,141,143,144,145,147,148,149,151,152,153,154,156,157,
- 158,159,160,162,163,164,165,166,167,168,169,171,172,173,174,175,
- 176,177,178,179,180,181,182,183,184,185,186,187,188,188,189,190,
- 191,192,193,194,195,196,197,198,199,200,201,202,203,203,204,205,
- 206,207,208,209,210,211,212,213,214,214,215,216,217,218,219,220,
- 221,222,223,224,224,225,226,227,228,229,230,231,232,233,234,235,
- 236,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,
- 251,252,253,254,255
-};
-
-static const unsigned char silk_TargetRate_WB_21[201 - 10] = {
- 0, 0, 0, 8, 29, 41,
- 49, 56, 62, 66, 70, 74, 77, 80, 83, 86, 88, 91, 93, 95, 97, 99,
- 101,103,105,107,108,110,112,113,115,116,118,119,121,122,123,125,
- 126,127,129,130,131,132,134,135,136,137,138,140,141,142,143,144,
- 145,146,147,148,149,150,151,152,153,154,156,157,158,159,159,160,
- 161,162,163,164,165,166,167,168,169,170,171,171,172,173,174,175,
- 176,177,177,178,179,180,181,181,182,183,184,185,185,186,187,188,
- 189,189,190,191,192,192,193,194,195,195,196,197,198,198,199,200,
- 200,201,202,203,203,204,205,206,206,207,208,209,209,210,211,211,
- 212,213,214,214,215,216,216,217,218,219,219,220,221,221,222,223,
- 224,224,225,226,226,227,228,229,229,230,231,232,232,233,234,234,
- 235,236,237,237,238,239,240,240,241,242,243,243,244,245,246,246,
- 247,248,249,249,250,251,252,253,255
-};
-
/* Control SNR of redidual quantizer */
opus_int silk_control_SNR(
silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */
opus_int32 TargetRate_bps /* I Target max bitrate (bps) */
)
{
- int id;
- int bound;
- const unsigned char *snr_table;
+ opus_int k, ret = SILK_NO_ERROR;
+ opus_int32 frac_Q6;
+ const opus_int32 *rateTable;
- psEncC->TargetRate_bps = TargetRate_bps;
- if( psEncC->nb_subfr == 2 ) {
- TargetRate_bps -= 2000 + psEncC->fs_kHz/16;
- }
- if( psEncC->fs_kHz == 8 ) {
- bound = sizeof(silk_TargetRate_NB_21);
- snr_table = silk_TargetRate_NB_21;
- } else if( psEncC->fs_kHz == 12 ) {
- bound = sizeof(silk_TargetRate_MB_21);
- snr_table = silk_TargetRate_MB_21;
- } else {
- bound = sizeof(silk_TargetRate_WB_21);
- snr_table = silk_TargetRate_WB_21;
- }
- id = (TargetRate_bps+200)/400;
- id = silk_min(id - 10, bound-1);
- if( id <= 0 ) {
- psEncC->SNR_dB_Q7 = 0;
- } else {
- psEncC->SNR_dB_Q7 = snr_table[id]*21;
+ /* Set bitrate/coding quality */
+ TargetRate_bps = silk_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS );
+ if( TargetRate_bps != psEncC->TargetRate_bps ) {
+ psEncC->TargetRate_bps = TargetRate_bps;
+
+ /* If new TargetRate_bps, translate to SNR_dB value */
+ if( psEncC->fs_kHz == 8 ) {
+ rateTable = silk_TargetRate_table_NB;
+ } else if( psEncC->fs_kHz == 12 ) {
+ rateTable = silk_TargetRate_table_MB;
+ } else {
+ rateTable = silk_TargetRate_table_WB;
+ }
+
+ /* Reduce bitrate for 10 ms modes in these calculations */
+ if( psEncC->nb_subfr == 2 ) {
+ TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS;
+ }
+
+ /* Find bitrate interval in table and interpolate */
+ for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) {
+ if( TargetRate_bps <= rateTable[ k ] ) {
+ frac_Q6 = silk_DIV32( silk_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ),
+ rateTable[ k ] - rateTable[ k - 1 ] );
+ psEncC->SNR_dB_Q7 = silk_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + silk_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] );
+ break;
+ }
+ }
}
- return SILK_NO_ERROR;
+
+ return ret;
}
diff --git a/thirdparty/opus/silk/control_audio_bandwidth.c b/thirdparty/opus/silk/control_audio_bandwidth.c
index f6d22d8395..4f9bc5cbda 100644
--- a/thirdparty/opus/silk/control_audio_bandwidth.c
+++ b/thirdparty/opus/silk/control_audio_bandwidth.c
@@ -39,15 +39,9 @@ opus_int silk_control_audio_bandwidth(
)
{
opus_int fs_kHz;
- opus_int orig_kHz;
opus_int32 fs_Hz;
- orig_kHz = psEncC->fs_kHz;
- /* Handle a bandwidth-switching reset where we need to be aware what the last sampling rate was. */
- if( orig_kHz == 0 ) {
- orig_kHz = psEncC->sLP.saved_fs_kHz;
- }
- fs_kHz = orig_kHz;
+ fs_kHz = psEncC->fs_kHz;
fs_Hz = silk_SMULBB( fs_kHz, 1000 );
if( fs_Hz == 0 ) {
/* Encoder has just been initialized */
@@ -67,7 +61,7 @@ opus_int silk_control_audio_bandwidth(
}
if( psEncC->allow_bandwidth_switch || encControl->opusCanSwitch ) {
/* Check if we should switch down */
- if( silk_SMULBB( orig_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz )
+ if( silk_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz )
{
/* Switch down */
if( psEncC->sLP.mode == 0 ) {
@@ -82,7 +76,7 @@ opus_int silk_control_audio_bandwidth(
psEncC->sLP.mode = 0;
/* Switch to a lower sample frequency */
- fs_kHz = orig_kHz == 16 ? 12 : 8;
+ fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8;
} else {
if( psEncC->sLP.transition_frame_no <= 0 ) {
encControl->switchReady = 1;
@@ -96,12 +90,12 @@ opus_int silk_control_audio_bandwidth(
}
else
/* Check if we should switch up */
- if( silk_SMULBB( orig_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz )
+ if( silk_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz )
{
/* Switch up */
if( encControl->opusCanSwitch ) {
/* Switch to a higher sample frequency */
- fs_kHz = orig_kHz == 8 ? 12 : 16;
+ fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16;
/* New transition */
psEncC->sLP.transition_frame_no = 0;
diff --git a/thirdparty/opus/silk/control_codec.c b/thirdparty/opus/silk/control_codec.c
index 52aa8fded3..044eea3f2a 100644
--- a/thirdparty/opus/silk/control_codec.c
+++ b/thirdparty/opus/silk/control_codec.c
@@ -57,7 +57,7 @@ static opus_int silk_setup_complexity(
static OPUS_INLINE opus_int silk_setup_LBRR(
silk_encoder_state *psEncC, /* I/O */
- const silk_EncControlStruct *encControl /* I */
+ const opus_int32 TargetRate_bps /* I */
);
@@ -65,6 +65,7 @@ static OPUS_INLINE opus_int silk_setup_LBRR(
opus_int silk_control_encoder(
silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */
silk_EncControlStruct *encControl, /* I Control structure */
+ const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
const opus_int channelNb, /* I Channel number */
const opus_int force_fs_kHz
@@ -124,7 +125,7 @@ opus_int silk_control_encoder(
/********************************************/
/* Set LBRR usage */
/********************************************/
- ret += silk_setup_LBRR( &psEnc->sCmn, encControl );
+ ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps );
psEnc->sCmn.controlled_since_last_payload = 1;
@@ -238,11 +239,12 @@ static opus_int silk_setup_fs(
}
/* Set internal sampling frequency */
- celt_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
- celt_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
+ silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
+ silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
if( psEnc->sCmn.fs_kHz != fs_kHz ) {
/* reset part of the state */
silk_memset( &psEnc->sShape, 0, sizeof( psEnc->sShape ) );
+ silk_memset( &psEnc->sPrefilt, 0, sizeof( psEnc->sPrefilt ) );
silk_memset( &psEnc->sCmn.sNSQ, 0, sizeof( psEnc->sCmn.sNSQ ) );
silk_memset( psEnc->sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
silk_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) );
@@ -253,6 +255,7 @@ static opus_int silk_setup_fs(
/* Initialize non-zero parameters */
psEnc->sCmn.prevLag = 100;
psEnc->sCmn.first_frame_after_reset = 1;
+ psEnc->sPrefilt.lagPrev = 100;
psEnc->sShape.LastGainIndex = 10;
psEnc->sCmn.sNSQ.lagPrev = 100;
psEnc->sCmn.sNSQ.prev_gain_Q16 = 65536;
@@ -290,16 +293,19 @@ static opus_int silk_setup_fs(
psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );
}
if( psEnc->sCmn.fs_kHz == 16 ) {
+ psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 );
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
} else if( psEnc->sCmn.fs_kHz == 12 ) {
+ psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 );
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
} else {
+ psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 );
psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
}
}
/* Check that settings are valid */
- celt_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
+ silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
return ret;
}
@@ -312,76 +318,61 @@ static opus_int silk_setup_complexity(
opus_int ret = 0;
/* Set encoding complexity */
- celt_assert( Complexity >= 0 && Complexity <= 10 );
- if( Complexity < 1 ) {
+ silk_assert( Complexity >= 0 && Complexity <= 10 );
+ if( Complexity < 2 ) {
psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 );
psEncC->pitchEstimationLPCOrder = 6;
- psEncC->shapingLPCOrder = 12;
+ psEncC->shapingLPCOrder = 8;
psEncC->la_shape = 3 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = 1;
psEncC->useInterpolatedNLSFs = 0;
- psEncC->NLSF_MSVQ_Survivors = 2;
- psEncC->warping_Q16 = 0;
- } else if( Complexity < 2 ) {
- psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
- psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 );
- psEncC->pitchEstimationLPCOrder = 8;
- psEncC->shapingLPCOrder = 14;
- psEncC->la_shape = 5 * psEncC->fs_kHz;
- psEncC->nStatesDelayedDecision = 1;
- psEncC->useInterpolatedNLSFs = 0;
- psEncC->NLSF_MSVQ_Survivors = 3;
- psEncC->warping_Q16 = 0;
- } else if( Complexity < 3 ) {
- psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX;
- psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 );
- psEncC->pitchEstimationLPCOrder = 6;
- psEncC->shapingLPCOrder = 12;
- psEncC->la_shape = 3 * psEncC->fs_kHz;
- psEncC->nStatesDelayedDecision = 2;
- psEncC->useInterpolatedNLSFs = 0;
+ psEncC->LTPQuantLowComplexity = 1;
psEncC->NLSF_MSVQ_Survivors = 2;
psEncC->warping_Q16 = 0;
} else if( Complexity < 4 ) {
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 );
psEncC->pitchEstimationLPCOrder = 8;
- psEncC->shapingLPCOrder = 14;
+ psEncC->shapingLPCOrder = 10;
psEncC->la_shape = 5 * psEncC->fs_kHz;
- psEncC->nStatesDelayedDecision = 2;
+ psEncC->nStatesDelayedDecision = 1;
psEncC->useInterpolatedNLSFs = 0;
+ psEncC->LTPQuantLowComplexity = 0;
psEncC->NLSF_MSVQ_Survivors = 4;
psEncC->warping_Q16 = 0;
} else if( Complexity < 6 ) {
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.74, 16 );
psEncC->pitchEstimationLPCOrder = 10;
- psEncC->shapingLPCOrder = 16;
+ psEncC->shapingLPCOrder = 12;
psEncC->la_shape = 5 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = 2;
psEncC->useInterpolatedNLSFs = 1;
- psEncC->NLSF_MSVQ_Survivors = 6;
+ psEncC->LTPQuantLowComplexity = 0;
+ psEncC->NLSF_MSVQ_Survivors = 8;
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
} else if( Complexity < 8 ) {
psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.72, 16 );
psEncC->pitchEstimationLPCOrder = 12;
- psEncC->shapingLPCOrder = 20;
+ psEncC->shapingLPCOrder = 14;
psEncC->la_shape = 5 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = 3;
psEncC->useInterpolatedNLSFs = 1;
- psEncC->NLSF_MSVQ_Survivors = 8;
+ psEncC->LTPQuantLowComplexity = 0;
+ psEncC->NLSF_MSVQ_Survivors = 16;
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
} else {
psEncC->pitchEstimationComplexity = SILK_PE_MAX_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.7, 16 );
psEncC->pitchEstimationLPCOrder = 16;
- psEncC->shapingLPCOrder = 24;
+ psEncC->shapingLPCOrder = 16;
psEncC->la_shape = 5 * psEncC->fs_kHz;
psEncC->nStatesDelayedDecision = MAX_DEL_DEC_STATES;
psEncC->useInterpolatedNLSFs = 1;
- psEncC->NLSF_MSVQ_Survivors = 16;
+ psEncC->LTPQuantLowComplexity = 0;
+ psEncC->NLSF_MSVQ_Survivors = 32;
psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
}
@@ -390,32 +381,46 @@ static opus_int silk_setup_complexity(
psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape;
psEncC->Complexity = Complexity;
- celt_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
- celt_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER );
- celt_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES );
- celt_assert( psEncC->warping_Q16 <= 32767 );
- celt_assert( psEncC->la_shape <= LA_SHAPE_MAX );
- celt_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX );
+ silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
+ silk_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER );
+ silk_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES );
+ silk_assert( psEncC->warping_Q16 <= 32767 );
+ silk_assert( psEncC->la_shape <= LA_SHAPE_MAX );
+ silk_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX );
+ silk_assert( psEncC->NLSF_MSVQ_Survivors <= NLSF_VQ_MAX_SURVIVORS );
return ret;
}
static OPUS_INLINE opus_int silk_setup_LBRR(
silk_encoder_state *psEncC, /* I/O */
- const silk_EncControlStruct *encControl /* I */
+ const opus_int32 TargetRate_bps /* I */
)
{
opus_int LBRR_in_previous_packet, ret = SILK_NO_ERROR;
+ opus_int32 LBRR_rate_thres_bps;
LBRR_in_previous_packet = psEncC->LBRR_enabled;
- psEncC->LBRR_enabled = encControl->LBRR_coded;
- if( psEncC->LBRR_enabled ) {
- /* Set gain increase for coding LBRR excitation */
- if( LBRR_in_previous_packet == 0 ) {
- /* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */
- psEncC->LBRR_GainIncreases = 7;
+ psEncC->LBRR_enabled = 0;
+ if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) {
+ if( psEncC->fs_kHz == 8 ) {
+ LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS;
+ } else if( psEncC->fs_kHz == 12 ) {
+ LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS;
} else {
- psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
+ LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS;
+ }
+ LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
+
+ if( TargetRate_bps > LBRR_rate_thres_bps ) {
+ /* Set gain increase for coding LBRR excitation */
+ if( LBRR_in_previous_packet == 0 ) {
+ /* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */
+ psEncC->LBRR_GainIncreases = 7;
+ } else {
+ psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
+ }
+ psEncC->LBRR_enabled = 1;
}
}
diff --git a/thirdparty/opus/silk/debug.h b/thirdparty/opus/silk/debug.h
index 6f68c1ca0f..efb6d3e99e 100644
--- a/thirdparty/opus/silk/debug.h
+++ b/thirdparty/opus/silk/debug.h
@@ -39,10 +39,23 @@ extern "C"
unsigned long GetHighResolutionTime(void); /* O time in usec*/
-/* Set to 1 to enable DEBUG_STORE_DATA() macros for dumping
- * intermediate signals from the codec.
- */
-#define SILK_DEBUG 0
+/* make SILK_DEBUG dependent on compiler's _DEBUG */
+#if defined _WIN32
+ #ifdef _DEBUG
+ #define SILK_DEBUG 1
+ #else
+ #define SILK_DEBUG 0
+ #endif
+
+ /* overrule the above */
+ #if 0
+ /* #define NO_ASSERTS*/
+ #undef SILK_DEBUG
+ #define SILK_DEBUG 1
+ #endif
+#else
+ #define SILK_DEBUG 0
+#endif
/* Flag for using timers */
#define SILK_TIC_TOC 0
diff --git a/thirdparty/opus/silk/dec_API.c b/thirdparty/opus/silk/dec_API.c
index 7d5ca7fb9f..b7d8ed48d8 100644
--- a/thirdparty/opus/silk/dec_API.c
+++ b/thirdparty/opus/silk/dec_API.c
@@ -104,7 +104,7 @@ opus_int silk_Decode( /* O Returns error co
int delay_stack_alloc;
SAVE_STACK;
- celt_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
+ silk_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
/**********************************/
/* Test if first frame in payload */
@@ -143,13 +143,13 @@ opus_int silk_Decode( /* O Returns error co
channel_state[ n ].nFramesPerPacket = 3;
channel_state[ n ].nb_subfr = 4;
} else {
- celt_assert( 0 );
+ silk_assert( 0 );
RESTORE_STACK;
return SILK_DEC_INVALID_FRAME_SIZE;
}
fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1;
if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) {
- celt_assert( 0 );
+ silk_assert( 0 );
RESTORE_STACK;
return SILK_DEC_INVALID_SAMPLING_FREQUENCY;
}
diff --git a/thirdparty/opus/silk/decode_core.c b/thirdparty/opus/silk/decode_core.c
index 1c352a6522..e569c0e72b 100644
--- a/thirdparty/opus/silk/decode_core.c
+++ b/thirdparty/opus/silk/decode_core.c
@@ -141,7 +141,7 @@ void silk_decode_core(
if( k == 0 || ( k == 2 && NLSF_interpolation_flag ) ) {
/* Rewhiten with new A coefs */
start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
- celt_assert( start_idx > 0 );
+ silk_assert( start_idx > 0 );
if( k == 2 ) {
silk_memcpy( &psDec->outBuf[ psDec->ltp_mem_length ], xq, 2 * psDec->subfr_length * sizeof( opus_int16 ) );
@@ -196,7 +196,7 @@ void silk_decode_core(
for( i = 0; i < psDec->subfr_length; i++ ) {
/* Short-term prediction */
- celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
+ silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] );
@@ -225,6 +225,8 @@ void silk_decode_core(
pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
}
+ /* DEBUG_STORE_DATA( dec.pcm, pxq, psDec->subfr_length * sizeof( opus_int16 ) ) */
+
/* Update LPC filter state */
silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
pexc_Q14 += psDec->subfr_length;
diff --git a/thirdparty/opus/silk/decode_frame.c b/thirdparty/opus/silk/decode_frame.c
index e73825b267..a605d95ac6 100644
--- a/thirdparty/opus/silk/decode_frame.c
+++ b/thirdparty/opus/silk/decode_frame.c
@@ -55,7 +55,7 @@ opus_int silk_decode_frame(
psDecCtrl->LTP_scale_Q14 = 0;
/* Safety checks */
- celt_assert( L > 0 && L <= MAX_FRAME_LENGTH );
+ silk_assert( L > 0 && L <= MAX_FRAME_LENGTH );
if( lostFlag == FLAG_DECODE_NORMAL ||
( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) )
@@ -91,20 +91,19 @@ opus_int silk_decode_frame(
psDec->lossCnt = 0;
psDec->prevSignalType = psDec->indices.signalType;
- celt_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
+ silk_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
/* A frame has been decoded without errors */
psDec->first_frame_after_reset = 0;
} else {
/* Handle packet loss by extrapolation */
- psDec->indices.signalType = psDec->prevSignalType;
silk_PLC( psDec, psDecCtrl, pOut, 1, arch );
}
/*************************/
/* Update output buffer. */
/*************************/
- celt_assert( psDec->ltp_mem_length >= psDec->frame_length );
+ silk_assert( psDec->ltp_mem_length >= psDec->frame_length );
mv_len = psDec->ltp_mem_length - psDec->frame_length;
silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
diff --git a/thirdparty/opus/silk/decode_indices.c b/thirdparty/opus/silk/decode_indices.c
index 0bb4a997a5..7afe5c26c1 100644
--- a/thirdparty/opus/silk/decode_indices.c
+++ b/thirdparty/opus/silk/decode_indices.c
@@ -79,7 +79,7 @@ void silk_decode_indices(
/**********************/
psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 );
silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] );
- celt_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
+ silk_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
for( i = 0; i < psDec->psNLSF_CB->order; i++ ) {
Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
if( Ix == 0 ) {
diff --git a/thirdparty/opus/silk/decode_parameters.c b/thirdparty/opus/silk/decode_parameters.c
index a56a409858..e345b1dcef 100644
--- a/thirdparty/opus/silk/decode_parameters.c
+++ b/thirdparty/opus/silk/decode_parameters.c
@@ -52,7 +52,7 @@ void silk_decode_parameters(
silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB );
/* Convert NLSF parameters to AR prediction filter coefficients */
- silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order, psDec->arch );
+ silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order );
/* If just reset, e.g., because internal Fs changed, do not allow interpolation */
/* improves the case of packet loss in the first frame after a switch */
@@ -69,7 +69,7 @@ void silk_decode_parameters(
}
/* Convert NLSF parameters to AR prediction filter coefficients */
- silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order, psDec->arch );
+ silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order );
} else {
/* Copy LPC coefficients for first half from second half */
silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
diff --git a/thirdparty/opus/silk/decode_pitch.c b/thirdparty/opus/silk/decode_pitch.c
index fd1b6bf551..fedbc6a525 100644
--- a/thirdparty/opus/silk/decode_pitch.c
+++ b/thirdparty/opus/silk/decode_pitch.c
@@ -51,7 +51,7 @@ void silk_decode_pitch(
Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE2_EXT;
} else {
- celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+ silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE2_10MS;
}
@@ -60,7 +60,7 @@ void silk_decode_pitch(
Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+ silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE3_10MS;
}
diff --git a/thirdparty/opus/silk/decode_pulses.c b/thirdparty/opus/silk/decode_pulses.c
index a56d2d3074..d6bbec9225 100644
--- a/thirdparty/opus/silk/decode_pulses.c
+++ b/thirdparty/opus/silk/decode_pulses.c
@@ -56,7 +56,7 @@ void silk_decode_pulses(
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
- celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
+ silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
iter++;
}
diff --git a/thirdparty/opus/silk/decoder_set_fs.c b/thirdparty/opus/silk/decoder_set_fs.c
index d9a13d0f0c..eef0fd25e1 100644
--- a/thirdparty/opus/silk/decoder_set_fs.c
+++ b/thirdparty/opus/silk/decoder_set_fs.c
@@ -40,8 +40,8 @@ opus_int silk_decoder_set_fs(
{
opus_int frame_length, ret = 0;
- celt_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
- celt_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
+ silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
+ silk_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
/* New (sub)frame length */
psDec->subfr_length = silk_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz );
@@ -86,7 +86,7 @@ opus_int silk_decoder_set_fs(
psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
} else {
/* unsupported sampling rate */
- celt_assert( 0 );
+ silk_assert( 0 );
}
psDec->first_frame_after_reset = 1;
psDec->lagPrev = 100;
@@ -101,7 +101,7 @@ opus_int silk_decoder_set_fs(
}
/* Check that settings are valid */
- celt_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
+ silk_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
return ret;
}
diff --git a/thirdparty/opus/silk/define.h b/thirdparty/opus/silk/define.h
index 247cb0bf71..19c9b00e25 100644
--- a/thirdparty/opus/silk/define.h
+++ b/thirdparty/opus/silk/define.h
@@ -46,6 +46,7 @@ extern "C"
/* Limits on bitrate */
#define MIN_TARGET_RATE_BPS 5000
#define MAX_TARGET_RATE_BPS 80000
+#define TARGET_RATE_TAB_SZ 8
/* LBRR thresholds */
#define LBRR_NB_MIN_RATE_BPS 12000
@@ -55,12 +56,6 @@ extern "C"
/* DTX settings */
#define NB_SPEECH_FRAMES_BEFORE_DTX 10 /* eq 200 ms */
#define MAX_CONSECUTIVE_DTX 20 /* eq 400 ms */
-#define DTX_ACTIVITY_THRESHOLD 0.1f
-
-/* VAD decision */
-#define VAD_NO_DECISION -1
-#define VAD_NO_ACTIVITY 0
-#define VAD_ACTIVITY 1
/* Maximum sampling frequency */
#define MAX_FS_KHZ 16
@@ -152,7 +147,7 @@ extern "C"
#define USE_HARM_SHAPING 1
/* Max LPC order of noise shaping filters */
-#define MAX_SHAPE_LPC_ORDER 24
+#define MAX_SHAPE_LPC_ORDER 16
#define HARM_SHAPE_FIR_TAPS 3
@@ -162,7 +157,8 @@ extern "C"
#define LTP_BUF_LENGTH 512
#define LTP_MASK ( LTP_BUF_LENGTH - 1 )
-#define DECISION_DELAY 40
+#define DECISION_DELAY 32
+#define DECISION_DELAY_MASK ( DECISION_DELAY - 1 )
/* Number of subframes for excitation entropy coding */
#define SHELL_CODEC_FRAME_LENGTH 16
@@ -177,7 +173,11 @@ extern "C"
#define MAX_MATRIX_SIZE MAX_LPC_ORDER /* Max of LPC Order and LTP order */
+#if( MAX_LPC_ORDER > DECISION_DELAY )
# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER
+#else
+# define NSQ_LPC_BUF_LENGTH DECISION_DELAY
+#endif
/***************************/
/* Voice activity detector */
@@ -205,6 +205,7 @@ extern "C"
/******************/
#define NLSF_W_Q 2
#define NLSF_VQ_MAX_VECTORS 32
+#define NLSF_VQ_MAX_SURVIVORS 32
#define NLSF_QUANT_MAX_AMPLITUDE 4
#define NLSF_QUANT_MAX_AMPLITUDE_EXT 10
#define NLSF_QUANT_LEVEL_ADJ 0.1
diff --git a/thirdparty/opus/silk/enc_API.c b/thirdparty/opus/silk/enc_API.c
index 55a33f37e9..f8060286db 100644
--- a/thirdparty/opus/silk/enc_API.c
+++ b/thirdparty/opus/silk/enc_API.c
@@ -82,7 +82,7 @@ opus_int silk_InitEncoder( /* O Returns error co
silk_memset( psEnc, 0, sizeof( silk_encoder ) );
for( n = 0; n < ENCODER_NUM_CHANNELS; n++ ) {
if( ret += silk_init_encoder( &psEnc->state_Fxx[ n ], arch ) ) {
- celt_assert( 0 );
+ silk_assert( 0 );
}
}
@@ -91,7 +91,7 @@ opus_int silk_InitEncoder( /* O Returns error co
/* Read control structure */
if( ret += silk_QueryEncoder( encState, encStatus ) ) {
- celt_assert( 0 );
+ silk_assert( 0 );
}
return ret;
@@ -144,8 +144,7 @@ opus_int silk_Encode( /* O Returns error co
opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
- const opus_int prefillFlag, /* I Flag to indicate prefilling buffers no coding */
- opus_int activity /* I Decision of Opus voice activity detector */
+ const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */
)
{
opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0;
@@ -167,7 +166,7 @@ opus_int silk_Encode( /* O Returns error co
/* Check values in encoder control structure */
if( ( ret = check_control_input( encControl ) ) != 0 ) {
- celt_assert( 0 );
+ silk_assert( 0 );
RESTORE_STACK;
return ret;
}
@@ -200,26 +199,16 @@ opus_int silk_Encode( /* O Returns error co
tot_blocks = ( nBlocksOf10ms > 1 ) ? nBlocksOf10ms >> 1 : 1;
curr_block = 0;
if( prefillFlag ) {
- silk_LP_state save_LP;
/* Only accept input length of 10 ms */
if( nBlocksOf10ms != 1 ) {
- celt_assert( 0 );
+ silk_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
- if ( prefillFlag == 2 ) {
- save_LP = psEnc->state_Fxx[ 0 ].sCmn.sLP;
- /* Save the sampling rate so the bandwidth switching code can keep handling transitions. */
- save_LP.saved_fs_kHz = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz;
- }
/* Reset Encoder */
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
ret = silk_init_encoder( &psEnc->state_Fxx[ n ], psEnc->state_Fxx[ n ].sCmn.arch );
- /* Restore the variable LP state. */
- if ( prefillFlag == 2 ) {
- psEnc->state_Fxx[ n ].sCmn.sLP = save_LP;
- }
- celt_assert( !ret );
+ silk_assert( !ret );
}
tmp_payloadSize_ms = encControl->payloadSize_ms;
encControl->payloadSize_ms = 10;
@@ -232,22 +221,23 @@ opus_int silk_Encode( /* O Returns error co
} else {
/* Only accept input lengths that are a multiple of 10 ms */
if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) {
- celt_assert( 0 );
+ silk_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
/* Make sure no more than one packet can be produced */
if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) {
- celt_assert( 0 );
+ silk_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
}
+ TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 );
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
/* Force the side channel to the same rate as the mid */
opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0;
- if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
+ if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
silk_assert( 0 );
RESTORE_STACK;
return ret;
@@ -259,7 +249,7 @@ opus_int silk_Encode( /* O Returns error co
}
psEnc->state_Fxx[ n ].sCmn.inDTX = psEnc->state_Fxx[ n ].sCmn.useDTX;
}
- celt_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
+ silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
/* Input buffering/resampling and encoding */
nSamplesToBufferMax =
@@ -317,7 +307,7 @@ opus_int silk_Encode( /* O Returns error co
}
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
} else {
- celt_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
+ silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16));
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
&psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
@@ -333,8 +323,8 @@ opus_int silk_Encode( /* O Returns error co
/* Silk encoder */
if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) {
/* Enough data in input buffer, so encode */
- celt_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length );
- celt_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length );
+ silk_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length );
+ silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length );
/* Deal with LBRR data */
if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) {
@@ -426,6 +416,7 @@ opus_int silk_Encode( /* O Returns error co
/* Reset side channel encoder memory for first frame with side coding */
if( psEnc->prev_decode_only_middle == 1 ) {
silk_memset( &psEnc->state_Fxx[ 1 ].sShape, 0, sizeof( psEnc->state_Fxx[ 1 ].sShape ) );
+ silk_memset( &psEnc->state_Fxx[ 1 ].sPrefilt, 0, sizeof( psEnc->state_Fxx[ 1 ].sPrefilt ) );
silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sNSQ, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sNSQ ) );
silk_memset( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15 ) );
silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State ) );
@@ -436,7 +427,7 @@ opus_int silk_Encode( /* O Returns error co
psEnc->state_Fxx[ 1 ].sCmn.sNSQ.prev_gain_Q16 = 65536;
psEnc->state_Fxx[ 1 ].sCmn.first_frame_after_reset = 1;
}
- silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ], activity );
+ silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ] );
} else {
psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] = 0;
}
@@ -451,7 +442,7 @@ opus_int silk_Encode( /* O Returns error co
silk_memcpy( psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) );
silk_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length ], 2 * sizeof( opus_int16 ) );
}
- silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ], activity );
+ silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ] );
/* Encode */
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
@@ -566,10 +557,6 @@ opus_int silk_Encode( /* O Returns error co
}
}
- encControl->signalType = psEnc->state_Fxx[0].sCmn.indices.signalType;
- encControl->offset = silk_Quantization_Offsets_Q10
- [ psEnc->state_Fxx[0].sCmn.indices.signalType >> 1 ]
- [ psEnc->state_Fxx[0].sCmn.indices.quantOffsetType ];
RESTORE_STACK;
return ret;
}
diff --git a/thirdparty/opus/silk/encode_indices.c b/thirdparty/opus/silk/encode_indices.c
index 4bcbc3347b..666c8c0b13 100644
--- a/thirdparty/opus/silk/encode_indices.c
+++ b/thirdparty/opus/silk/encode_indices.c
@@ -56,8 +56,8 @@ void silk_encode_indices(
/* Encode signal type and quantizer offset */
/*******************************************/
typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType;
- celt_assert( typeOffset >= 0 && typeOffset < 6 );
- celt_assert( encode_LBRR == 0 || typeOffset >= 2 );
+ silk_assert( typeOffset >= 0 && typeOffset < 6 );
+ silk_assert( encode_LBRR == 0 || typeOffset >= 2 );
if( encode_LBRR || typeOffset >= 2 ) {
ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 );
} else {
@@ -90,7 +90,7 @@ void silk_encode_indices(
/****************/
ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 );
silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] );
- celt_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder );
+ silk_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder );
for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) {
if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) {
ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
diff --git a/thirdparty/opus/silk/encode_pulses.c b/thirdparty/opus/silk/encode_pulses.c
index 8a1999138b..ab00264f99 100644
--- a/thirdparty/opus/silk/encode_pulses.c
+++ b/thirdparty/opus/silk/encode_pulses.c
@@ -86,7 +86,7 @@ void silk_encode_pulses(
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
- celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
+ silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
iter++;
silk_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8));
}
diff --git a/thirdparty/opus/silk/fixed/apply_sine_window_FIX.c b/thirdparty/opus/silk/fixed/apply_sine_window_FIX.c
index 03e088a6de..4502b7130e 100644
--- a/thirdparty/opus/silk/fixed/apply_sine_window_FIX.c
+++ b/thirdparty/opus/silk/fixed/apply_sine_window_FIX.c
@@ -57,15 +57,15 @@ void silk_apply_sine_window(
opus_int k, f_Q16, c_Q16;
opus_int32 S0_Q16, S1_Q16;
- celt_assert( win_type == 1 || win_type == 2 );
+ silk_assert( win_type == 1 || win_type == 2 );
/* Length must be in a range from 16 to 120 and a multiple of 4 */
- celt_assert( length >= 16 && length <= 120 );
- celt_assert( ( length & 3 ) == 0 );
+ silk_assert( length >= 16 && length <= 120 );
+ silk_assert( ( length & 3 ) == 0 );
/* Frequency */
k = ( length >> 2 ) - 4;
- celt_assert( k >= 0 && k <= 26 );
+ silk_assert( k >= 0 && k <= 26 );
f_Q16 = (opus_int)freq_table_Q16[ k ];
/* Factor used for cosine approximation */
diff --git a/thirdparty/opus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h b/thirdparty/opus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h
deleted file mode 100644
index 1992e43288..0000000000
--- a/thirdparty/opus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/***********************************************************************
-Copyright (c) 2017 Google Inc.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifndef SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
-# define SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
-
-# include "celt/arm/armcpu.h"
-
-# if defined(FIXED_POINT)
-
-# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-void silk_warped_autocorrelation_FIX_neon(
- opus_int32 *corr, /* O Result [order + 1] */
- opus_int *scale, /* O Scaling of the correlation vector */
- const opus_int16 *input, /* I Input data to correlate */
- const opus_int warping_Q16, /* I Warping coefficient */
- const opus_int length, /* I Length of input */
- const opus_int order /* I Correlation order (even) */
-);
-
-# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
-# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
-# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
- ((void)(arch), PRESUME_NEON(silk_warped_autocorrelation_FIX)(corr, scale, input, warping_Q16, length, order))
-# endif
-# endif
-
-# if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
-/*Is run-time CPU detection enabled on this platform?*/
-# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
-extern void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK+1])(opus_int32*, opus_int*, const opus_int16*, const opus_int, const opus_int, const opus_int);
-# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
-# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
- ((*SILK_WARPED_AUTOCORRELATION_FIX_IMPL[(arch)&OPUS_ARCHMASK])(corr, scale, input, warping_Q16, length, order))
-# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
-# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
-# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
- ((void)(arch), silk_warped_autocorrelation_FIX_neon(corr, scale, input, warping_Q16, length, order))
-# endif
-# endif
-
-# endif /* end FIXED_POINT */
-
-#endif /* end SILK_WARPED_AUTOCORRELATION_FIX_ARM_H */
diff --git a/thirdparty/opus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c b/thirdparty/opus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c
deleted file mode 100644
index 00a70cb51f..0000000000
--- a/thirdparty/opus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/***********************************************************************
-Copyright (c) 2017 Google Inc., Jean-Marc Valin
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <arm_neon.h>
-#ifdef OPUS_CHECK_ASM
-# include <string.h>
-#endif
-#include "stack_alloc.h"
-#include "main_FIX.h"
-
-static OPUS_INLINE void calc_corr( const opus_int32 *const input_QS, opus_int64 *const corr_QC, const opus_int offset, const int32x4_t state_QS_s32x4 )
-{
- int64x2_t corr_QC_s64x2[ 2 ], t_s64x2[ 2 ];
- const int32x4_t input_QS_s32x4 = vld1q_s32( input_QS + offset );
- corr_QC_s64x2[ 0 ] = vld1q_s64( corr_QC + offset + 0 );
- corr_QC_s64x2[ 1 ] = vld1q_s64( corr_QC + offset + 2 );
- t_s64x2[ 0 ] = vmull_s32( vget_low_s32( state_QS_s32x4 ), vget_low_s32( input_QS_s32x4 ) );
- t_s64x2[ 1 ] = vmull_s32( vget_high_s32( state_QS_s32x4 ), vget_high_s32( input_QS_s32x4 ) );
- corr_QC_s64x2[ 0 ] = vsraq_n_s64( corr_QC_s64x2[ 0 ], t_s64x2[ 0 ], 2 * QS - QC );
- corr_QC_s64x2[ 1 ] = vsraq_n_s64( corr_QC_s64x2[ 1 ], t_s64x2[ 1 ], 2 * QS - QC );
- vst1q_s64( corr_QC + offset + 0, corr_QC_s64x2[ 0 ] );
- vst1q_s64( corr_QC + offset + 2, corr_QC_s64x2[ 1 ] );
-}
-
-static OPUS_INLINE int32x4_t calc_state( const int32x4_t state_QS0_s32x4, const int32x4_t state_QS0_1_s32x4, const int32x4_t state_QS1_1_s32x4, const int32x4_t warping_Q16_s32x4 )
-{
- int32x4_t t_s32x4 = vsubq_s32( state_QS0_s32x4, state_QS0_1_s32x4 );
- t_s32x4 = vqdmulhq_s32( t_s32x4, warping_Q16_s32x4 );
- return vaddq_s32( state_QS1_1_s32x4, t_s32x4 );
-}
-
-void silk_warped_autocorrelation_FIX_neon(
- opus_int32 *corr, /* O Result [order + 1] */
- opus_int *scale, /* O Scaling of the correlation vector */
- const opus_int16 *input, /* I Input data to correlate */
- const opus_int warping_Q16, /* I Warping coefficient */
- const opus_int length, /* I Length of input */
- const opus_int order /* I Correlation order (even) */
-)
-{
- if( ( MAX_SHAPE_LPC_ORDER > 24 ) || ( order < 6 ) ) {
- silk_warped_autocorrelation_FIX_c( corr, scale, input, warping_Q16, length, order );
- } else {
- opus_int n, i, lsh;
- opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; /* In reverse order */
- opus_int64 corr_QC_orderT;
- int64x2_t lsh_s64x2;
- const opus_int orderT = ( order + 3 ) & ~3;
- opus_int64 *corr_QCT;
- opus_int32 *input_QS;
- VARDECL( opus_int32, input_QST );
- VARDECL( opus_int32, state );
- SAVE_STACK;
-
- /* Order must be even */
- silk_assert( ( order & 1 ) == 0 );
- silk_assert( 2 * QS - QC >= 0 );
-
- ALLOC( input_QST, length + 2 * MAX_SHAPE_LPC_ORDER, opus_int32 );
-
- input_QS = input_QST;
- /* input_QS has zero paddings in the beginning and end. */
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
-
- /* Loop over samples */
- for( n = 0; n < length - 7; n += 8, input_QS += 8 ) {
- const int16x8_t t0_s16x4 = vld1q_s16( input + n );
- vst1q_s32( input_QS + 0, vshll_n_s16( vget_low_s16( t0_s16x4 ), QS ) );
- vst1q_s32( input_QS + 4, vshll_n_s16( vget_high_s16( t0_s16x4 ), QS ) );
- }
- for( ; n < length; n++, input_QS++ ) {
- input_QS[ 0 ] = silk_LSHIFT32( (opus_int32)input[ n ], QS );
- }
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS += 4;
- vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
- input_QS = input_QST + MAX_SHAPE_LPC_ORDER - orderT;
-
- /* The following loop runs ( length + order ) times, with ( order ) extra epilogues. */
- /* The zero paddings in input_QS guarantee corr_QC's correctness even with the extra epilogues. */
- /* The values of state_QS will be polluted by the extra epilogues, however they are temporary values. */
-
- /* Keep the C code here to help understand the intrinsics optimization. */
- /*
- {
- opus_int32 state_QS[ 2 ][ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
- opus_int32 *state_QST[ 3 ];
- state_QST[ 0 ] = state_QS[ 0 ];
- state_QST[ 1 ] = state_QS[ 1 ];
- for( n = 0; n < length + order; n++, input_QS++ ) {
- state_QST[ 0 ][ orderT ] = input_QS[ orderT ];
- for( i = 0; i < orderT; i++ ) {
- corr_QC[ i ] += silk_RSHIFT64( silk_SMULL( state_QST[ 0 ][ i ], input_QS[ i ] ), 2 * QS - QC );
- state_QST[ 1 ][ i ] = silk_SMLAWB( state_QST[ 1 ][ i + 1 ], state_QST[ 0 ][ i ] - state_QST[ 0 ][ i + 1 ], warping_Q16 );
- }
- state_QST[ 2 ] = state_QST[ 0 ];
- state_QST[ 0 ] = state_QST[ 1 ];
- state_QST[ 1 ] = state_QST[ 2 ];
- }
- }
- */
-
- {
- const int32x4_t warping_Q16_s32x4 = vdupq_n_s32( warping_Q16 << 15 );
- const opus_int32 *in = input_QS + orderT;
- opus_int o = orderT;
- int32x4_t state_QS_s32x4[ 3 ][ 2 ];
-
- ALLOC( state, length + orderT, opus_int32 );
- state_QS_s32x4[ 2 ][ 1 ] = vdupq_n_s32( 0 );
-
- /* Calculate 8 taps of all inputs in each loop. */
- do {
- state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 0 ][ 1 ] =
- state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 1 ][ 1 ] = vdupq_n_s32( 0 );
- n = 0;
- do {
- calc_corr( input_QS + n, corr_QC, o - 8, state_QS_s32x4[ 0 ][ 0 ] );
- calc_corr( input_QS + n, corr_QC, o - 4, state_QS_s32x4[ 0 ][ 1 ] );
- state_QS_s32x4[ 2 ][ 1 ] = vld1q_s32( in + n );
- vst1q_lane_s32( state + n, state_QS_s32x4[ 0 ][ 0 ], 0 );
- state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 0 ][ 1 ], 1 );
- state_QS_s32x4[ 2 ][ 1 ] = vextq_s32( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], 1 );
- state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 );
- state_QS_s32x4[ 0 ][ 1 ] = calc_state( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], state_QS_s32x4[ 1 ][ 1 ], warping_Q16_s32x4 );
- state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ];
- state_QS_s32x4[ 1 ][ 1 ] = state_QS_s32x4[ 2 ][ 1 ];
- } while( ++n < ( length + order ) );
- in = state;
- o -= 8;
- } while( o > 4 );
-
- if( o ) {
- /* Calculate the last 4 taps of all inputs. */
- opus_int32 *stateT = state;
- silk_assert( o == 4 );
- state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 1 ][ 0 ] = vdupq_n_s32( 0 );
- n = length + order;
- do {
- calc_corr( input_QS, corr_QC, 0, state_QS_s32x4[ 0 ][ 0 ] );
- state_QS_s32x4[ 2 ][ 0 ] = vld1q_s32( stateT );
- vst1q_lane_s32( stateT, state_QS_s32x4[ 0 ][ 0 ], 0 );
- state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], 1 );
- state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 );
- state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ];
- input_QS++;
- stateT++;
- } while( --n );
- }
- }
-
- {
- const opus_int16 *inputT = input;
- int32x4_t t_s32x4;
- int64x1_t t_s64x1;
- int64x2_t t_s64x2 = vdupq_n_s64( 0 );
- for( n = 0; n <= length - 8; n += 8 ) {
- int16x8_t input_s16x8 = vld1q_s16( inputT );
- t_s32x4 = vmull_s16( vget_low_s16( input_s16x8 ), vget_low_s16( input_s16x8 ) );
- t_s32x4 = vmlal_s16( t_s32x4, vget_high_s16( input_s16x8 ), vget_high_s16( input_s16x8 ) );
- t_s64x2 = vaddw_s32( t_s64x2, vget_low_s32( t_s32x4 ) );
- t_s64x2 = vaddw_s32( t_s64x2, vget_high_s32( t_s32x4 ) );
- inputT += 8;
- }
- t_s64x1 = vadd_s64( vget_low_s64( t_s64x2 ), vget_high_s64( t_s64x2 ) );
- corr_QC_orderT = vget_lane_s64( t_s64x1, 0 );
- for( ; n < length; n++ ) {
- corr_QC_orderT += silk_SMULL( input[ n ], input[ n ] );
- }
- corr_QC_orderT = silk_LSHIFT64( corr_QC_orderT, QC );
- corr_QC[ orderT ] = corr_QC_orderT;
- }
-
- corr_QCT = corr_QC + orderT - order;
- lsh = silk_CLZ64( corr_QC_orderT ) - 35;
- lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC );
- *scale = -( QC + lsh );
- silk_assert( *scale >= -30 && *scale <= 12 );
- lsh_s64x2 = vdupq_n_s64( lsh );
- for( i = 0; i <= order - 3; i += 4 ) {
- int32x4_t corr_s32x4;
- int64x2_t corr_QC0_s64x2, corr_QC1_s64x2;
- corr_QC0_s64x2 = vld1q_s64( corr_QCT + i );
- corr_QC1_s64x2 = vld1q_s64( corr_QCT + i + 2 );
- corr_QC0_s64x2 = vshlq_s64( corr_QC0_s64x2, lsh_s64x2 );
- corr_QC1_s64x2 = vshlq_s64( corr_QC1_s64x2, lsh_s64x2 );
- corr_s32x4 = vcombine_s32( vmovn_s64( corr_QC1_s64x2 ), vmovn_s64( corr_QC0_s64x2 ) );
- corr_s32x4 = vrev64q_s32( corr_s32x4 );
- vst1q_s32( corr + order - i - 3, corr_s32x4 );
- }
- if( lsh >= 0 ) {
- for( ; i < order + 1; i++ ) {
- corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QCT[ i ], lsh ) );
- }
- } else {
- for( ; i < order + 1; i++ ) {
- corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QCT[ i ], -lsh ) );
- }
- }
- silk_assert( corr_QCT[ order ] >= 0 ); /* If breaking, decrease QC*/
- RESTORE_STACK;
- }
-
-#ifdef OPUS_CHECK_ASM
- {
- opus_int32 corr_c[ MAX_SHAPE_LPC_ORDER + 1 ];
- opus_int scale_c;
- silk_warped_autocorrelation_FIX_c( corr_c, &scale_c, input, warping_Q16, length, order );
- silk_assert( !memcmp( corr_c, corr, sizeof( corr_c[ 0 ] ) * ( order + 1 ) ) );
- silk_assert( scale_c == *scale );
- }
-#endif
-}
diff --git a/thirdparty/opus/silk/fixed/burg_modified_FIX.c b/thirdparty/opus/silk/fixed/burg_modified_FIX.c
index 274d4b28e1..17d0e0993c 100644
--- a/thirdparty/opus/silk/fixed/burg_modified_FIX.c
+++ b/thirdparty/opus/silk/fixed/burg_modified_FIX.c
@@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */
#define QA 25
-#define N_BITS_HEAD_ROOM 3
+#define N_BITS_HEAD_ROOM 2
#define MIN_RSHIFTS -16
#define MAX_RSHIFTS (32 - QA)
@@ -65,7 +65,7 @@ void silk_burg_modified_c(
opus_int32 xcorr[ SILK_MAX_ORDER_LPC ];
opus_int64 C0_64;
- celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+ silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
/* Compute autocorrelations, added over subframes */
C0_64 = silk_inner_prod16_aligned_64( x, x, subfr_length*nb_subfr, arch );
diff --git a/thirdparty/opus/silk/fixed/corrMatrix_FIX.c b/thirdparty/opus/silk/fixed/corrMatrix_FIX.c
index 1b4a29c232..c1d437c785 100644
--- a/thirdparty/opus/silk/fixed/corrMatrix_FIX.c
+++ b/thirdparty/opus/silk/fixed/corrMatrix_FIX.c
@@ -58,7 +58,7 @@ void silk_corrVector_FIX(
for( lag = 0; lag < order; lag++ ) {
inner_prod = 0;
for( i = 0; i < L; i++ ) {
- inner_prod = silk_ADD_RSHIFT32( inner_prod, silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts );
+ inner_prod += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts );
}
Xt[ lag ] = inner_prod; /* X[:,lag]'*t */
ptr1--; /* Go to next column of X */
@@ -77,54 +77,61 @@ void silk_corrMatrix_FIX(
const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */
const opus_int L, /* I Length of vectors */
const opus_int order, /* I Max lag for correlation */
+ const opus_int head_room, /* I Desired headroom */
opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */
- opus_int32 *nrg, /* O Energy of x vector */
- opus_int *rshifts, /* O Right shifts of correlations and energy */
+ opus_int *rshifts, /* I/O Right shifts of correlations */
int arch /* I Run-time architecture */
)
{
- opus_int i, j, lag;
+ opus_int i, j, lag, rshifts_local, head_room_rshifts;
opus_int32 energy;
const opus_int16 *ptr1, *ptr2;
/* Calculate energy to find shift used to fit in 32 bits */
- silk_sum_sqr_shift( nrg, rshifts, x, L + order - 1 );
- energy = *nrg;
+ silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 );
+ /* Add shifts to get the desired head room */
+ head_room_rshifts = silk_max( head_room - silk_CLZ32( energy ), 0 );
+
+ energy = silk_RSHIFT32( energy, head_room_rshifts );
+ rshifts_local += head_room_rshifts;
/* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */
/* Remove contribution of first order - 1 samples */
for( i = 0; i < order - 1; i++ ) {
- energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), *rshifts );
+ energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), rshifts_local );
+ }
+ if( rshifts_local < *rshifts ) {
+ /* Adjust energy */
+ energy = silk_RSHIFT32( energy, *rshifts - rshifts_local );
+ rshifts_local = *rshifts;
}
/* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */
/* Fill out the diagonal of the correlation matrix */
matrix_ptr( XX, 0, 0, order ) = energy;
- silk_assert( energy >= 0 );
ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */
for( j = 1; j < order; j++ ) {
- energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), *rshifts ) );
- energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), *rshifts ) );
+ energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) );
+ energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) );
matrix_ptr( XX, j, j, order ) = energy;
- silk_assert( energy >= 0 );
}
ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */
/* Calculate the remaining elements of the correlation matrix */
- if( *rshifts > 0 ) {
+ if( rshifts_local > 0 ) {
/* Right shifting used */
for( lag = 1; lag < order; lag++ ) {
/* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */
energy = 0;
for( i = 0; i < L; i++ ) {
- energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), *rshifts );
+ energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local );
}
/* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */
matrix_ptr( XX, lag, 0, order ) = energy;
matrix_ptr( XX, 0, lag, order ) = energy;
for( j = 1; j < ( order - lag ); j++ ) {
- energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), *rshifts ) );
- energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), *rshifts ) );
+ energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) );
+ energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) );
matrix_ptr( XX, lag + j, j, order ) = energy;
matrix_ptr( XX, j, lag + j, order ) = energy;
}
@@ -146,5 +153,6 @@ void silk_corrMatrix_FIX(
ptr2--;/* Update pointer to first sample of next column (lag) in X */
}
}
+ *rshifts = rshifts_local;
}
diff --git a/thirdparty/opus/silk/fixed/encode_frame_FIX.c b/thirdparty/opus/silk/fixed/encode_frame_FIX.c
index a02bf87dbb..5ef44b03fc 100644
--- a/thirdparty/opus/silk/fixed/encode_frame_FIX.c
+++ b/thirdparty/opus/silk/fixed/encode_frame_FIX.c
@@ -29,7 +29,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
#endif
-#include <stdlib.h>
#include "main_FIX.h"
#include "stack_alloc.h"
#include "tuning_parameters.h"
@@ -38,33 +37,26 @@ POSSIBILITY OF SUCH DAMAGE.
static OPUS_INLINE void silk_LBRR_encode_FIX(
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */
- const opus_int16 x16[], /* I Input signal */
+ const opus_int32 xfw_Q3[], /* I Input signal */
opus_int condCoding /* I The type of conditional coding used so far for this frame */
);
void silk_encode_do_VAD_FIX(
- silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
- opus_int activity /* I Decision of Opus voice activity detector */
+ silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */
)
{
- const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
-
/****************************/
/* Voice Activity Detection */
/****************************/
silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
- /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
- if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
- psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
- }
/**************************************************/
/* Convert speech activity into VAD and DTX flags */
/**************************************************/
- if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
+ if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) {
psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
psEnc->sCmn.noSpeechCounter++;
- if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
+ if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.inDTX = 0;
} else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
@@ -102,9 +94,6 @@ opus_int silk_encode_frame_FIX(
opus_int16 ec_prevLagIndex_copy;
opus_int ec_prevSignalType_copy;
opus_int8 LastGainIndex_copy2;
- opus_int gain_lock[ MAX_NB_SUBFR ] = {0};
- opus_int16 best_gain_mult[ MAX_NB_SUBFR ];
- opus_int best_sum[ MAX_NB_SUBFR ];
SAVE_STACK;
/* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
@@ -129,6 +118,7 @@ opus_int silk_encode_frame_FIX(
silk_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) );
if( !psEnc->sCmn.prefillFlag ) {
+ VARDECL( opus_int32, xfw_Q3 );
VARDECL( opus_int16, res_pitch );
VARDECL( opus_uint8, ec_buf_copy );
opus_int16 *res_pitch_frame;
@@ -142,7 +132,7 @@ opus_int silk_encode_frame_FIX(
/*****************************************/
/* Find pitch lags, initial LPC analysis */
/*****************************************/
- silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame - psEnc->sCmn.ltp_mem_length, psEnc->sCmn.arch );
+ silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch );
/************************/
/* Noise shape analysis */
@@ -152,17 +142,23 @@ opus_int silk_encode_frame_FIX(
/***************************************************/
/* Find linear prediction coefficients (LPC + LTP) */
/***************************************************/
- silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
+ silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding );
/****************************************/
/* Process gains */
/****************************************/
silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding );
+ /*****************************************/
+ /* Prefiltering for noise shaper */
+ /*****************************************/
+ ALLOC( xfw_Q3, psEnc->sCmn.frame_length, opus_int32 );
+ silk_prefilter_FIX( psEnc, &sEncCtrl, xfw_Q3, x_frame );
+
/****************************************/
/* Low Bitrate Redundant Encoding */
/****************************************/
- silk_LBRR_encode_FIX( psEnc, &sEncCtrl, x_frame, condCoding );
+ silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw_Q3, condCoding );
/* Loop over quantizer and entropy coding to control bitrate */
maxIter = 6;
@@ -198,21 +194,17 @@ opus_int silk_encode_frame_FIX(
/* Noise shaping quantization */
/*****************************************/
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
- silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
- sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
+ silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses,
+ sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
psEnc->sCmn.arch );
} else {
- silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
- sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
+ silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses,
+ sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
psEnc->sCmn.arch);
}
- if ( iter == maxIter && !found_lower ) {
- silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
- }
-
/****************************************/
/* Encode Parameters */
/****************************************/
@@ -226,33 +218,6 @@ opus_int silk_encode_frame_FIX(
nBits = ec_tell( psRangeEnc );
- /* If we still bust after the last iteration, do some damage control. */
- if ( iter == maxIter && !found_lower && nBits > maxBits ) {
- silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
-
- /* Keep gains the same as the last frame. */
- psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
- for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
- psEnc->sCmn.indices.GainsIndices[ i ] = 4;
- }
- if (condCoding != CODE_CONDITIONALLY) {
- psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
- }
- psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
- psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
- /* Clear all pulses. */
- for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
- psEnc->sCmn.pulses[ i ] = 0;
- }
-
- silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
-
- silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
- psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
-
- nBits = ec_tell( psRangeEnc );
- }
-
if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
break;
}
@@ -262,7 +227,7 @@ opus_int silk_encode_frame_FIX(
if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
/* Restore output state from earlier iteration that did meet the bitrate budget */
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
- celt_assert( sRangeEnc_copy2.offs <= 1275 );
+ silk_assert( sRangeEnc_copy2.offs <= 1275 );
silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
@@ -290,7 +255,7 @@ opus_int silk_encode_frame_FIX(
gainsID_lower = gainsID;
/* Copy part of the output state */
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
- celt_assert( psRangeEnc->offs <= 1275 );
+ silk_assert( psRangeEnc->offs <= 1275 );
silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
@@ -300,35 +265,15 @@ opus_int silk_encode_frame_FIX(
break;
}
- if ( !found_lower && nBits > maxBits ) {
- int j;
- for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
- int sum=0;
- for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
- sum += abs( psEnc->sCmn.pulses[j] );
- }
- if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
- best_sum[i] = sum;
- best_gain_mult[i] = gainMult_Q8;
- } else {
- gain_lock[i] = 1;
- }
- }
- }
if( ( found_lower & found_upper ) == 0 ) {
/* Adjust gain according to high-rate rate/distortion curve */
+ opus_int32 gain_factor_Q16;
+ gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
+ gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) );
if( nBits > maxBits ) {
- if (gainMult_Q8 < 16384) {
- gainMult_Q8 *= 2;
- } else {
- gainMult_Q8 = 32767;
- }
- } else {
- opus_int32 gain_factor_Q16;
- gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
- gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
+ gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
}
-
+ gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
} else {
/* Adjust gain by interpolating */
gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower );
@@ -342,13 +287,7 @@ opus_int silk_encode_frame_FIX(
}
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
- opus_int16 tmp;
- if ( gain_lock[i] ) {
- tmp = best_gain_mult[i];
- } else {
- tmp = gainMult_Q8;
- }
- sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
+ sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 );
}
/* Quantize gains */
@@ -392,7 +331,7 @@ opus_int silk_encode_frame_FIX(
static OPUS_INLINE void silk_LBRR_encode_FIX(
silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */
- const opus_int16 x16[], /* I Input signal */
+ const opus_int32 xfw_Q3[], /* I Input signal */
opus_int condCoding /* I The type of conditional coding used so far for this frame */
)
{
@@ -431,14 +370,14 @@ static OPUS_INLINE void silk_LBRR_encode_FIX(
/* Noise shaping quantization */
/*****************************************/
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
- silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
+ silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3,
psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
- psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
+ psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
} else {
- silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
+ silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3,
psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
- psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
+ psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
}
diff --git a/thirdparty/opus/silk/fixed/find_LPC_FIX.c b/thirdparty/opus/silk/fixed/find_LPC_FIX.c
index c762a0f2a2..e11cdc86e6 100644
--- a/thirdparty/opus/silk/fixed/find_LPC_FIX.c
+++ b/thirdparty/opus/silk/fixed/find_LPC_FIX.c
@@ -92,7 +92,7 @@ void silk_find_LPC_FIX(
silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
/* Convert to LPC for residual energy evaluation */
- silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
+ silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder );
/* Calculate residual energy with NLSF interpolation */
silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder, psEncC->arch );
@@ -146,6 +146,6 @@ void silk_find_LPC_FIX(
silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder );
}
- celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
+ silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
RESTORE_STACK;
}
diff --git a/thirdparty/opus/silk/fixed/find_LTP_FIX.c b/thirdparty/opus/silk/fixed/find_LTP_FIX.c
index 62d4afb250..1314a28137 100644
--- a/thirdparty/opus/silk/fixed/find_LTP_FIX.c
+++ b/thirdparty/opus/silk/fixed/find_LTP_FIX.c
@@ -32,68 +32,214 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main_FIX.h"
#include "tuning_parameters.h"
+/* Head room for correlations */
+#define LTP_CORRS_HEAD_ROOM 2
+
+void silk_fit_LTP(
+ opus_int32 LTP_coefs_Q16[ LTP_ORDER ],
+ opus_int16 LTP_coefs_Q14[ LTP_ORDER ]
+);
+
void silk_find_LTP_FIX(
- opus_int32 XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Correlation matrix */
- opus_int32 xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ], /* O Correlation vector */
- const opus_int16 r_ptr[], /* I Residual signal after LPC */
+ opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
+ opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
+ opus_int *LTPredCodGain_Q7, /* O LTP coding gain */
+ const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
- const opus_int subfr_length, /* I Subframe length */
- const opus_int nb_subfr, /* I Number of subframes */
+ const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */
+ const opus_int subfr_length, /* I subframe length */
+ const opus_int nb_subfr, /* I number of subframes */
+ const opus_int mem_offset, /* I number of samples in LTP memory */
+ opus_int corr_rshifts[ MAX_NB_SUBFR ], /* O right shifts applied to correlations */
int arch /* I Run-time architecture */
)
{
- opus_int i, k, extra_shifts;
- opus_int xx_shifts, xX_shifts, XX_shifts;
- const opus_int16 *lag_ptr;
- opus_int32 *XXLTP_Q17_ptr, *xXLTP_Q17_ptr;
- opus_int32 xx, nrg, temp;
-
- xXLTP_Q17_ptr = xXLTP_Q17;
- XXLTP_Q17_ptr = XXLTP_Q17;
+ opus_int i, k, lshift;
+ const opus_int16 *r_ptr, *lag_ptr;
+ opus_int16 *b_Q14_ptr;
+
+ opus_int32 regu;
+ opus_int32 *WLTP_ptr;
+ opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26;
+ opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits;
+
+ opus_int32 temp32, denom32;
+ opus_int extra_shifts;
+ opus_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs;
+ opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16;
+ opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ];
+ opus_int32 wd, m_Q12;
+
+ b_Q14_ptr = b_Q14;
+ WLTP_ptr = WLTP;
+ r_ptr = &r_lpc[ mem_offset ];
for( k = 0; k < nb_subfr; k++ ) {
lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
- silk_sum_sqr_shift( &xx, &xx_shifts, r_ptr, subfr_length + LTP_ORDER ); /* xx in Q( -xx_shifts ) */
- silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, XXLTP_Q17_ptr, &nrg, &XX_shifts, arch ); /* XXLTP_Q17_ptr and nrg in Q( -XX_shifts ) */
- extra_shifts = xx_shifts - XX_shifts;
- if( extra_shifts > 0 ) {
- /* Shift XX */
- xX_shifts = xx_shifts;
- for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
- XXLTP_Q17_ptr[ i ] = silk_RSHIFT32( XXLTP_Q17_ptr[ i ], extra_shifts ); /* Q( -xX_shifts ) */
- }
- nrg = silk_RSHIFT32( nrg, extra_shifts ); /* Q( -xX_shifts ) */
- } else if( extra_shifts < 0 ) {
- /* Shift xx */
- xX_shifts = XX_shifts;
- xx = silk_RSHIFT32( xx, -extra_shifts ); /* Q( -xX_shifts ) */
- } else {
- xX_shifts = xx_shifts;
+ silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */
+
+ /* Assure headroom */
+ LZs = silk_CLZ32( rr[k] );
+ if( LZs < LTP_CORRS_HEAD_ROOM ) {
+ rr[ k ] = silk_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs );
+ rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs );
}
- silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xXLTP_Q17_ptr, xX_shifts, arch ); /* xXLTP_Q17_ptr in Q( -xX_shifts ) */
+ corr_rshifts[ k ] = rr_shifts;
+ silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ], arch ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */
+
+ /* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */
+ silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ], arch ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */
+ if( corr_rshifts[ k ] > rr_shifts ) {
+ rr[ k ] = silk_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */
+ }
+ silk_assert( rr[ k ] >= 0 );
+
+ regu = 1;
+ regu = silk_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
+ regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
+ regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
+ silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER );
+
+ silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */
+
+ /* Limit and store in Q14 */
+ silk_fit_LTP( b_Q16, b_Q14_ptr );
+
+ /* Calculate residual energy */
+ nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */
+
+ /* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */
+ extra_shifts = silk_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM );
+ denom32 = silk_LSHIFT_SAT32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */
+ silk_RSHIFT( silk_SMULWB( (opus_int32)subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */
+ denom32 = silk_max( denom32, 1 );
+ silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX ); /* Wght always < 0.5 in Q0 */
+ temp32 = silk_DIV32( silk_LSHIFT( (opus_int32)Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */
+ temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */
- /* At this point all correlations are in Q(-xX_shifts) */
- temp = silk_SMLAWB( 1, nrg, SILK_FIX_CONST( LTP_CORR_INV_MAX, 16 ) );
- temp = silk_max( temp, xx );
-TIC(div)
-#if 0
+ /* Limit temp such that the below scaling never wraps around */
+ WLTP_max = 0;
for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
- XXLTP_Q17_ptr[ i ] = silk_DIV32_varQ( XXLTP_Q17_ptr[ i ], temp, 17 );
+ WLTP_max = silk_max( WLTP_ptr[ i ], WLTP_max );
}
+ lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */
+ silk_assert( 26 - 18 + lshift >= 0 );
+ if( 26 - 18 + lshift < 31 ) {
+ temp32 = silk_min_32( temp32, silk_LSHIFT( (opus_int32)1, 26 - 18 + lshift ) );
+ }
+
+ silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */
+
+ w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */
+ silk_assert( w[k] >= 0 );
+
+ r_ptr += subfr_length;
+ b_Q14_ptr += LTP_ORDER;
+ WLTP_ptr += LTP_ORDER * LTP_ORDER;
+ }
+
+ maxRshifts = 0;
+ for( k = 0; k < nb_subfr; k++ ) {
+ maxRshifts = silk_max_int( corr_rshifts[ k ], maxRshifts );
+ }
+
+ /* Compute LTP coding gain */
+ if( LTPredCodGain_Q7 != NULL ) {
+ LPC_LTP_res_nrg = 0;
+ LPC_res_nrg = 0;
+ silk_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */
+ for( k = 0; k < nb_subfr; k++ ) {
+ LPC_res_nrg = silk_ADD32( LPC_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */
+ LPC_LTP_res_nrg = silk_ADD32( LPC_LTP_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */
+ }
+ LPC_LTP_res_nrg = silk_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */
+
+ div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 );
+ *LTPredCodGain_Q7 = ( opus_int )silk_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) );
+
+ silk_assert( *LTPredCodGain_Q7 == ( opus_int )silk_SAT16( silk_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) );
+ }
+
+ /* smoothing */
+ /* d = sum( B, 1 ); */
+ b_Q14_ptr = b_Q14;
+ for( k = 0; k < nb_subfr; k++ ) {
+ d_Q14[ k ] = 0;
for( i = 0; i < LTP_ORDER; i++ ) {
- xXLTP_Q17_ptr[ i ] = silk_DIV32_varQ( xXLTP_Q17_ptr[ i ], temp, 17 );
+ d_Q14[ k ] += b_Q14_ptr[ i ];
}
-#else
- for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
- XXLTP_Q17_ptr[ i ] = (opus_int32)( silk_LSHIFT64( (opus_int64)XXLTP_Q17_ptr[ i ], 17 ) / temp );
+ b_Q14_ptr += LTP_ORDER;
+ }
+
+ /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */
+
+ /* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */
+ max_abs_d_Q14 = 0;
+ max_w_bits = 0;
+ for( k = 0; k < nb_subfr; k++ ) {
+ max_abs_d_Q14 = silk_max_32( max_abs_d_Q14, silk_abs( d_Q14[ k ] ) );
+ /* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */
+ /* Find bits needed in Q( 18 - maxRshifts ) */
+ max_w_bits = silk_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts );
+ }
+
+ /* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -silk_int16_MIN */
+ silk_assert( max_abs_d_Q14 <= ( 5 << 15 ) );
+
+ /* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */
+ extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14;
+
+ /* Subtract what we got available; bits in output var plus maxRshifts */
+ extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */
+ extra_shifts = silk_max_int( extra_shifts, 0 );
+
+ maxRshifts_wxtra = maxRshifts + extra_shifts;
+
+ temp32 = silk_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */
+ wd = 0;
+ for( k = 0; k < nb_subfr; k++ ) {
+ /* w has at least 2 bits of headroom so no overflow should happen */
+ temp32 = silk_ADD32( temp32, silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */
+ wd = silk_ADD32( wd, silk_LSHIFT( silk_SMULWW( silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */
+ }
+ m_Q12 = silk_DIV32_varQ( wd, temp32, 12 );
+
+ b_Q14_ptr = b_Q14;
+ for( k = 0; k < nb_subfr; k++ ) {
+ /* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */
+ if( 2 - corr_rshifts[k] > 0 ) {
+ temp32 = silk_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] );
+ } else {
+ temp32 = silk_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 );
}
+
+ g_Q26 = silk_MUL(
+ silk_DIV32(
+ SILK_FIX_CONST( LTP_SMOOTHING, 26 ),
+ silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */
+ silk_LSHIFT_SAT32( silk_SUB_SAT32( (opus_int32)m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */
+
+ temp32 = 0;
for( i = 0; i < LTP_ORDER; i++ ) {
- xXLTP_Q17_ptr[ i ] = (opus_int32)( silk_LSHIFT64( (opus_int64)xXLTP_Q17_ptr[ i ], 17 ) / temp );
+ delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */
+ temp32 += delta_b_Q14[ i ]; /* Q14 */
}
-#endif
-TOC(div)
- r_ptr += subfr_length;
- XXLTP_Q17_ptr += LTP_ORDER * LTP_ORDER;
- xXLTP_Q17_ptr += LTP_ORDER;
+ temp32 = silk_DIV32( g_Q26, temp32 ); /* Q14 -> Q12 */
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ b_Q14_ptr[ i ] = silk_LIMIT_32( (opus_int32)b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 );
+ }
+ b_Q14_ptr += LTP_ORDER;
+ }
+}
+
+void silk_fit_LTP(
+ opus_int32 LTP_coefs_Q16[ LTP_ORDER ],
+ opus_int16 LTP_coefs_Q14[ LTP_ORDER ]
+)
+{
+ opus_int i;
+
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ LTP_coefs_Q14[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) );
}
}
diff --git a/thirdparty/opus/silk/fixed/find_pitch_lags_FIX.c b/thirdparty/opus/silk/fixed/find_pitch_lags_FIX.c
index 6c3379f2bb..b8440a8247 100644
--- a/thirdparty/opus/silk/fixed/find_pitch_lags_FIX.c
+++ b/thirdparty/opus/silk/fixed/find_pitch_lags_FIX.c
@@ -44,7 +44,7 @@ void silk_find_pitch_lags_FIX(
{
opus_int buf_len, i, scale;
opus_int32 thrhld_Q13, res_nrg;
- const opus_int16 *x_ptr;
+ const opus_int16 *x_buf, *x_buf_ptr;
VARDECL( opus_int16, Wsig );
opus_int16 *Wsig_ptr;
opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ];
@@ -59,7 +59,9 @@ void silk_find_pitch_lags_FIX(
buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
/* Safety check */
- celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
+ silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
+
+ x_buf = x - psEnc->sCmn.ltp_mem_length;
/*************************************/
/* Estimate LPC AR coefficients */
@@ -70,19 +72,19 @@ void silk_find_pitch_lags_FIX(
ALLOC( Wsig, psEnc->sCmn.pitch_LPC_win_length, opus_int16 );
/* First LA_LTP samples */
- x_ptr = x + buf_len - psEnc->sCmn.pitch_LPC_win_length;
+ x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length;
Wsig_ptr = Wsig;
- silk_apply_sine_window( Wsig_ptr, x_ptr, 1, psEnc->sCmn.la_pitch );
+ silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch );
/* Middle un - windowed samples */
Wsig_ptr += psEnc->sCmn.la_pitch;
- x_ptr += psEnc->sCmn.la_pitch;
- silk_memcpy( Wsig_ptr, x_ptr, ( psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) );
+ x_buf_ptr += psEnc->sCmn.la_pitch;
+ silk_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) );
/* Last LA_LTP samples */
Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
- x_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
- silk_apply_sine_window( Wsig_ptr, x_ptr, 2, psEnc->sCmn.la_pitch );
+ x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
+ silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch );
/* Calculate autocorrelation sequence */
silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1, arch );
@@ -110,7 +112,7 @@ void silk_find_pitch_lags_FIX(
/*****************************************/
/* LPC analysis filtering */
/*****************************************/
- silk_LPC_analysis_filter( res, x, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch );
+ silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch );
if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) {
/* Threshold for pitch estimator */
diff --git a/thirdparty/opus/silk/fixed/find_pred_coefs_FIX.c b/thirdparty/opus/silk/fixed/find_pred_coefs_FIX.c
index 606d863347..d308e9cf5f 100644
--- a/thirdparty/opus/silk/fixed/find_pred_coefs_FIX.c
+++ b/thirdparty/opus/silk/fixed/find_pred_coefs_FIX.c
@@ -41,12 +41,13 @@ void silk_find_pred_coefs_FIX(
)
{
opus_int i;
- opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ];
+ opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ];
opus_int16 NLSF_Q15[ MAX_LPC_ORDER ];
const opus_int16 *x_ptr;
opus_int16 *x_pre_ptr;
VARDECL( opus_int16, LPC_in_pre );
- opus_int32 min_gain_Q16, minInvGain_Q30;
+ opus_int32 tmp, min_gain_Q16, minInvGain_Q30;
+ opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ];
SAVE_STACK;
/* weighting for weighted least squares */
@@ -60,11 +61,13 @@ void silk_find_pred_coefs_FIX(
/* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */
invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 );
- /* Limit inverse */
- invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 100 );
+ /* Ensure Wght_Q15 a minimum value 1 */
+ invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 363 );
/* Square the inverted gains */
silk_assert( invGains_Q16[ i ] == silk_SAT16( invGains_Q16[ i ] ) );
+ tmp = silk_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] );
+ Wght_Q15[ i ] = silk_RSHIFT( tmp, 1 );
/* Invert the inverted and normalized gains */
local_gains[ i ] = silk_DIV32( ( (opus_int32)1 << 16 ), invGains_Q16[ i ] );
@@ -74,24 +77,24 @@ void silk_find_pred_coefs_FIX(
psEnc->sCmn.nb_subfr * psEnc->sCmn.predictLPCOrder
+ psEnc->sCmn.frame_length, opus_int16 );
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
- VARDECL( opus_int32, xXLTP_Q17 );
- VARDECL( opus_int32, XXLTP_Q17 );
+ VARDECL( opus_int32, WLTP );
/**********/
/* VOICED */
/**********/
- celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
+ silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
- ALLOC( xXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER, opus_int32 );
- ALLOC( XXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 );
+ ALLOC( WLTP, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 );
/* LTP analysis */
- silk_find_LTP_FIX( XXLTP_Q17, xXLTP_Q17, res_pitch,
- psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
+ silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7,
+ res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length,
+ psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift, psEnc->sCmn.arch );
/* Quantize LTP gain parameters */
silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
- &psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain_Q7, XXLTP_Q17, xXLTP_Q17, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
+ &psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr,
+ psEnc->sCmn.arch);
/* Control LTP scaling */
silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl, condCoding );
diff --git a/thirdparty/opus/silk/fixed/k2a_FIX.c b/thirdparty/opus/silk/fixed/k2a_FIX.c
index 549f6eadaa..5fee599bcb 100644
--- a/thirdparty/opus/silk/fixed/k2a_FIX.c
+++ b/thirdparty/opus/silk/fixed/k2a_FIX.c
@@ -39,15 +39,14 @@ void silk_k2a(
)
{
opus_int k, n;
- opus_int32 rc, tmp1, tmp2;
+ opus_int32 Atmp[ SILK_MAX_ORDER_LPC ];
for( k = 0; k < order; k++ ) {
- rc = rc_Q15[ k ];
- for( n = 0; n < (k + 1) >> 1; n++ ) {
- tmp1 = A_Q24[ n ];
- tmp2 = A_Q24[ k - n - 1 ];
- A_Q24[ n ] = silk_SMLAWB( tmp1, silk_LSHIFT( tmp2, 1 ), rc );
- A_Q24[ k - n - 1 ] = silk_SMLAWB( tmp2, silk_LSHIFT( tmp1, 1 ), rc );
+ for( n = 0; n < k; n++ ) {
+ Atmp[ n ] = A_Q24[ n ];
+ }
+ for( n = 0; n < k; n++ ) {
+ A_Q24[ n ] = silk_SMLAWB( A_Q24[ n ], silk_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] );
}
A_Q24[ k ] = -silk_LSHIFT( (opus_int32)rc_Q15[ k ], 9 );
}
diff --git a/thirdparty/opus/silk/fixed/k2a_Q16_FIX.c b/thirdparty/opus/silk/fixed/k2a_Q16_FIX.c
index 1595aa6212..3b03987544 100644
--- a/thirdparty/opus/silk/fixed/k2a_Q16_FIX.c
+++ b/thirdparty/opus/silk/fixed/k2a_Q16_FIX.c
@@ -39,16 +39,15 @@ void silk_k2a_Q16(
)
{
opus_int k, n;
- opus_int32 rc, tmp1, tmp2;
+ opus_int32 Atmp[ SILK_MAX_ORDER_LPC ];
for( k = 0; k < order; k++ ) {
- rc = rc_Q16[ k ];
- for( n = 0; n < (k + 1) >> 1; n++ ) {
- tmp1 = A_Q24[ n ];
- tmp2 = A_Q24[ k - n - 1 ];
- A_Q24[ n ] = silk_SMLAWW( tmp1, tmp2, rc );
- A_Q24[ k - n - 1 ] = silk_SMLAWW( tmp2, tmp1, rc );
+ for( n = 0; n < k; n++ ) {
+ Atmp[ n ] = A_Q24[ n ];
}
- A_Q24[ k ] = -silk_LSHIFT( rc, 8 );
+ for( n = 0; n < k; n++ ) {
+ A_Q24[ n ] = silk_SMLAWW( A_Q24[ n ], Atmp[ k - n - 1 ], rc_Q16[ k ] );
+ }
+ A_Q24[ k ] = -silk_LSHIFT( rc_Q16[ k ], 8 );
}
}
diff --git a/thirdparty/opus/silk/fixed/main_FIX.h b/thirdparty/opus/silk/fixed/main_FIX.h
index 6d2112e511..375b5eb32e 100644
--- a/thirdparty/opus/silk/fixed/main_FIX.h
+++ b/thirdparty/opus/silk/fixed/main_FIX.h
@@ -36,11 +36,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "debug.h"
#include "entenc.h"
-#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \
- || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
-#include "fixed/arm/warped_autocorrelation_FIX_arm.h"
-#endif
-
#ifndef FORCE_CPP_BUILD
#ifdef __cplusplus
extern "C"
@@ -52,9 +47,6 @@ extern "C"
#define silk_encode_do_VAD_Fxx silk_encode_do_VAD_FIX
#define silk_encode_frame_Fxx silk_encode_frame_FIX
-#define QC 10
-#define QS 13
-
/*********************/
/* Encoder Functions */
/*********************/
@@ -66,8 +58,7 @@ void silk_HP_variable_cutoff(
/* Encoder main function */
void silk_encode_do_VAD_FIX(
- silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
- opus_int activity /* I Decision of Opus voice activity detector */
+ silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */
);
/* Encoder main function */
@@ -90,11 +81,33 @@ opus_int silk_init_encoder(
opus_int silk_control_encoder(
silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */
silk_EncControlStruct *encControl, /* I Control structure */
+ const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
const opus_int channelNb, /* I Channel number */
const opus_int force_fs_kHz
);
+/****************/
+/* Prefiltering */
+/****************/
+void silk_prefilter_FIX(
+ silk_encoder_state_FIX *psEnc, /* I/O Encoder state */
+ const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */
+ opus_int32 xw_Q10[], /* O Weighted signal */
+ const opus_int16 x[] /* I Speech signal */
+);
+
+void silk_warped_LPC_analysis_filter_FIX_c(
+ opus_int32 state[], /* I/O State [order + 1] */
+ opus_int32 res_Q2[], /* O Residual signal [length] */
+ const opus_int16 coef_Q13[], /* I Coefficients [order] */
+ const opus_int16 input[], /* I Input signal [length] */
+ const opus_int16 lambda_Q16, /* I Warping factor */
+ const opus_int length, /* I Length of input signal */
+ const opus_int order /* I Filter order (even) */
+);
+
+
/**************************/
/* Noise shaping analysis */
/**************************/
@@ -108,7 +121,7 @@ void silk_noise_shape_analysis_FIX(
);
/* Autocorrelations for a warped frequency axis */
-void silk_warped_autocorrelation_FIX_c(
+void silk_warped_autocorrelation_FIX(
opus_int32 *corr, /* O Result [order + 1] */
opus_int *scale, /* O Scaling of the correlation vector */
const opus_int16 *input, /* I Input data to correlate */
@@ -117,11 +130,6 @@ void silk_warped_autocorrelation_FIX_c(
const opus_int order /* I Correlation order (even) */
);
-#if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
-#define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
- ((void)(arch), silk_warped_autocorrelation_FIX_c(corr, scale, input, warping_Q16, length, order))
-#endif
-
/* Calculation of LTP state scaling */
void silk_LTP_scale_ctrl_FIX(
silk_encoder_state_FIX *psEnc, /* I/O encoder state */
@@ -160,12 +168,16 @@ void silk_find_LPC_FIX(
/* LTP analysis */
void silk_find_LTP_FIX(
- opus_int32 XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Correlation matrix */
- opus_int32 xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ], /* O Correlation vector */
- const opus_int16 r_lpc[], /* I Residual signal after LPC */
+ opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
+ opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
+ opus_int *LTPredCodGain_Q7, /* O LTP coding gain */
+ const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
- const opus_int subfr_length, /* I Subframe length */
- const opus_int nb_subfr, /* I Number of subframes */
+ const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */
+ const opus_int subfr_length, /* I subframe length */
+ const opus_int nb_subfr, /* I number of subframes */
+ const opus_int mem_offset, /* I number of samples in LTP memory */
+ opus_int corr_rshifts[ MAX_NB_SUBFR ], /* O right shifts applied to correlations */
int arch /* I Run-time architecture */
);
@@ -219,9 +231,9 @@ void silk_corrMatrix_FIX(
const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */
const opus_int L, /* I Length of vectors */
const opus_int order, /* I Max lag for correlation */
+ const opus_int head_room, /* I Desired headroom */
opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */
- opus_int32 *nrg, /* O Energy of x vector */
- opus_int *rshifts, /* O Right shifts of correlations */
+ opus_int *rshifts, /* I/O Right shifts of correlations */
int arch /* I Run-time architecture */
);
@@ -236,6 +248,22 @@ void silk_corrVector_FIX(
int arch /* I Run-time architecture */
);
+/* Add noise to matrix diagonal */
+void silk_regularize_correlations_FIX(
+ opus_int32 *XX, /* I/O Correlation matrices */
+ opus_int32 *xx, /* I/O Correlation values */
+ opus_int32 noise, /* I Noise to add */
+ opus_int D /* I Dimension of XX */
+);
+
+/* Solves Ax = b, assuming A is symmetric */
+void silk_solve_LDL_FIX(
+ opus_int32 *A, /* I Pointer to symetric square matrix A */
+ opus_int M, /* I Size of matrix */
+ const opus_int32 *b, /* I Pointer to b vector */
+ opus_int32 *x_Q16 /* O Pointer to x solution vector */
+);
+
#ifndef FORCE_CPP_BUILD
#ifdef __cplusplus
}
diff --git a/thirdparty/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h b/thirdparty/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h
index 3999b5bd09..c30481e437 100644
--- a/thirdparty/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h
+++ b/thirdparty/opus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h
@@ -169,7 +169,7 @@ void silk_noise_shape_analysis_FIX(
if( psEnc->sCmn.warping_Q16 > 0 ) {
/* Calculate warped auto correlation */
- silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder, arch );
+ silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
} else {
/* Calculate regular auto correlation */
silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch );
@@ -224,8 +224,8 @@ void silk_noise_shape_analysis_FIX(
silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
/* Ratio of prediction gains, in energy domain */
- pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder, arch );
- nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder, arch );
+ pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
+ nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
/*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
diff --git a/thirdparty/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h b/thirdparty/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h
new file mode 100644
index 0000000000..21b256885f
--- /dev/null
+++ b/thirdparty/opus/silk/fixed/mips/prefilter_FIX_mipsr1.h
@@ -0,0 +1,184 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+#ifndef __PREFILTER_FIX_MIPSR1_H__
+#define __PREFILTER_FIX_MIPSR1_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FIX.h"
+#include "stack_alloc.h"
+#include "tuning_parameters.h"
+
+#define OVERRIDE_silk_warped_LPC_analysis_filter_FIX
+void silk_warped_LPC_analysis_filter_FIX(
+ opus_int32 state[], /* I/O State [order + 1] */
+ opus_int32 res_Q2[], /* O Residual signal [length] */
+ const opus_int16 coef_Q13[], /* I Coefficients [order] */
+ const opus_int16 input[], /* I Input signal [length] */
+ const opus_int16 lambda_Q16, /* I Warping factor */
+ const opus_int length, /* I Length of input signal */
+ const opus_int order, /* I Filter order (even) */
+ int arch
+)
+{
+ opus_int n, i;
+ opus_int32 acc_Q11, acc_Q22, tmp1, tmp2, tmp3, tmp4;
+ opus_int32 state_cur, state_next;
+
+ (void)arch;
+
+ /* Order must be even */
+ /* Length must be even */
+
+ silk_assert( ( order & 1 ) == 0 );
+ silk_assert( ( length & 1 ) == 0 );
+
+ for( n = 0; n < length; n+=2 ) {
+ /* Output of lowpass section */
+ tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
+ state_cur = silk_LSHIFT( input[ n ], 14 );
+ /* Output of allpass section */
+ tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
+ state_next = tmp2;
+ acc_Q11 = silk_RSHIFT( order, 1 );
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
+
+
+ /* Output of lowpass section */
+ tmp4 = silk_SMLAWB( state_cur, state_next, lambda_Q16 );
+ state[ 0 ] = silk_LSHIFT( input[ n+1 ], 14 );
+ /* Output of allpass section */
+ tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 );
+ state[ 1 ] = tmp4;
+ acc_Q22 = silk_RSHIFT( order, 1 );
+ acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ 0 ] );
+
+ /* Loop over allpass sections */
+ for( i = 2; i < order; i += 2 ) {
+ /* Output of allpass section */
+ tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
+ state_cur = tmp1;
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
+ /* Output of allpass section */
+ tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
+ state_next = tmp2;
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
+
+
+ /* Output of allpass section */
+ tmp4 = silk_SMLAWB( state_cur, state_next - tmp3, lambda_Q16 );
+ state[ i ] = tmp3;
+ acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ i - 1 ] );
+ /* Output of allpass section */
+ tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 );
+ state[ i + 1 ] = tmp4;
+ acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ i ] );
+ }
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
+ res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
+
+ state[ order ] = tmp3;
+ acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ order - 1 ] );
+ res_Q2[ n+1 ] = silk_LSHIFT( (opus_int32)input[ n+1 ], 2 ) - silk_RSHIFT_ROUND( acc_Q22, 9 );
+ }
+}
+
+
+
+/* Prefilter for finding Quantizer input signal */
+#define OVERRIDE_silk_prefilt_FIX
+static inline void silk_prefilt_FIX(
+ silk_prefilter_state_FIX *P, /* I/O state */
+ opus_int32 st_res_Q12[], /* I short term residual signal */
+ opus_int32 xw_Q3[], /* O prefiltered signal */
+ opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
+ opus_int Tilt_Q14, /* I Tilt shaping coeficient */
+ opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
+ opus_int lag, /* I Lag for harmonic shaping */
+ opus_int length /* I Length of signals */
+)
+{
+ opus_int i, idx, LTP_shp_buf_idx;
+ opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10;
+ opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12;
+ opus_int16 *LTP_shp_buf;
+
+ /* To speed up use temp variables instead of using the struct */
+ LTP_shp_buf = P->sLTP_shp;
+ LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
+ sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12;
+ sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12;
+
+ if( lag > 0 ) {
+ for( i = 0; i < length; i++ ) {
+ /* unrolled loop */
+ silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
+ idx = lag + LTP_shp_buf_idx;
+ n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
+ n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
+ n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
+
+ n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
+ n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
+
+ sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
+ sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) );
+
+ LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
+ LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
+
+ xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 );
+ }
+ }
+ else
+ {
+ for( i = 0; i < length; i++ ) {
+
+ n_LTP_Q12 = 0;
+
+ n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
+ n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
+
+ sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
+ sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) );
+
+ LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
+ LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
+
+ xw_Q3[i] = silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 9 );
+ }
+ }
+
+ /* Copy temp variable back to state */
+ P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12;
+ P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12;
+ P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
+}
+
+#endif /* __PREFILTER_FIX_MIPSR1_H__ */
diff --git a/thirdparty/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h b/thirdparty/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h
index 66eb2ed26d..e803ef0fce 100644
--- a/thirdparty/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h
+++ b/thirdparty/opus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h
@@ -41,8 +41,8 @@ POSSIBILITY OF SUCH DAMAGE.
#define QS 14
/* Autocorrelations for a warped frequency axis */
-#define OVERRIDE_silk_warped_autocorrelation_FIX_c
-void silk_warped_autocorrelation_FIX_c(
+#define OVERRIDE_silk_warped_autocorrelation_FIX
+void silk_warped_autocorrelation_FIX(
opus_int32 *corr, /* O Result [order + 1] */
opus_int *scale, /* O Scaling of the correlation vector */
const opus_int16 *input, /* I Input data to correlate */
diff --git a/thirdparty/opus/silk/fixed/noise_shape_analysis_FIX.c b/thirdparty/opus/silk/fixed/noise_shape_analysis_FIX.c
index 85fea0bf09..22a89f75ae 100644
--- a/thirdparty/opus/silk/fixed/noise_shape_analysis_FIX.c
+++ b/thirdparty/opus/silk/fixed/noise_shape_analysis_FIX.c
@@ -57,79 +57,88 @@ static OPUS_INLINE opus_int32 warped_gain( /* gain in Q16*/
/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */
/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
static OPUS_INLINE void limit_warped_coefs(
- opus_int32 *coefs_Q24,
+ opus_int32 *coefs_syn_Q24,
+ opus_int32 *coefs_ana_Q24,
opus_int lambda_Q16,
opus_int32 limit_Q24,
opus_int order
) {
opus_int i, iter, ind = 0;
- opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_Q16;
+ opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16;
opus_int32 nom_Q16, den_Q24;
- opus_int32 limit_Q20, maxabs_Q20;
/* Convert to monic coefficients */
lambda_Q16 = -lambda_Q16;
for( i = order - 1; i > 0; i-- ) {
- coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
+ coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
+ coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
}
lambda_Q16 = -lambda_Q16;
- nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
- den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_Q24[ 0 ], lambda_Q16 );
- gain_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
+ nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
+ den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
+ gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
+ den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
+ gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
for( i = 0; i < order; i++ ) {
- coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
+ coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
+ coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
}
- limit_Q20 = silk_RSHIFT(limit_Q24, 4);
+
for( iter = 0; iter < 10; iter++ ) {
/* Find maximum absolute value */
maxabs_Q24 = -1;
for( i = 0; i < order; i++ ) {
- tmp = silk_abs_int32( coefs_Q24[ i ] );
+ tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) );
if( tmp > maxabs_Q24 ) {
maxabs_Q24 = tmp;
ind = i;
}
}
- /* Use Q20 to avoid any overflow when multiplying by (ind + 1) later. */
- maxabs_Q20 = silk_RSHIFT(maxabs_Q24, 4);
- if( maxabs_Q20 <= limit_Q20 ) {
+ if( maxabs_Q24 <= limit_Q24 ) {
/* Coefficients are within range - done */
return;
}
/* Convert back to true warped coefficients */
for( i = 1; i < order; i++ ) {
- coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
+ coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
+ coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
}
- gain_Q16 = silk_INVERSE32_varQ( gain_Q16, 32 );
+ gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 );
+ gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 );
for( i = 0; i < order; i++ ) {
- coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
+ coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
+ coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
}
/* Apply bandwidth expansion */
chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ(
- silk_SMULWB( maxabs_Q20 - limit_Q20, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ),
- silk_MUL( maxabs_Q20, ind + 1 ), 22 );
- silk_bwexpander_32( coefs_Q24, order, chirp_Q16 );
+ silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ),
+ silk_MUL( maxabs_Q24, ind + 1 ), 22 );
+ silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 );
+ silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 );
/* Convert to monic warped coefficients */
lambda_Q16 = -lambda_Q16;
for( i = order - 1; i > 0; i-- ) {
- coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
+ coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
+ coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
}
lambda_Q16 = -lambda_Q16;
nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
- den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_Q24[ 0 ], lambda_Q16 );
- gain_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
+ den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
+ gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
+ den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
+ gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
for( i = 0; i < order; i++ ) {
- coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
+ coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
+ coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
}
}
silk_assert( 0 );
}
-/* Disable MIPS version until it's updated. */
-#if 0 && defined(MIPSr1_ASM)
+#if defined(MIPSr1_ASM)
#include "mips/noise_shape_analysis_FIX_mipsr1.h"
#endif
@@ -146,13 +155,14 @@ void silk_noise_shape_analysis_FIX(
)
{
silk_shape_state_FIX *psShapeSt = &psEnc->sShape;
- opus_int k, i, nSamples, nSegs, Qnrg, b_Q14, warping_Q16, scale = 0;
- opus_int32 SNR_adj_dB_Q7, HarmShapeGain_Q16, Tilt_Q16, tmp32;
- opus_int32 nrg, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
- opus_int32 BWExp_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
+ opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0;
+ opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32;
+ opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
+ opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ];
- opus_int32 AR_Q24[ MAX_SHAPE_LPC_ORDER ];
+ opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ];
+ opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ];
VARDECL( opus_int16, x_windowed );
const opus_int16 *x_ptr, *pitch_res_ptr;
SAVE_STACK;
@@ -199,14 +209,14 @@ void silk_noise_shape_analysis_FIX(
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
/* Initially set to 0; may be overruled in process_gains(..) */
psEnc->sCmn.indices.quantOffsetType = 0;
+ psEncCtrl->sparseness_Q8 = 0;
} else {
/* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 );
energy_variation_Q7 = 0;
log_energy_prev_Q7 = 0;
pitch_res_ptr = pitch_res;
- nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
- for( k = 0; k < nSegs; k++ ) {
+ for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples );
nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/
@@ -218,12 +228,18 @@ void silk_noise_shape_analysis_FIX(
pitch_res_ptr += nSamples;
}
+ psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 -
+ SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 );
+
/* Set quantization offset depending on sparseness measure */
- if( energy_variation_Q7 > SILK_FIX_CONST( ENERGY_VARIATION_THRESHOLD_QNT_OFFSET, 7 ) * (nSegs-1) ) {
+ if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) {
psEnc->sCmn.indices.quantOffsetType = 0;
} else {
psEnc->sCmn.indices.quantOffsetType = 1;
}
+
+ /* Increase coding SNR for sparse signals */
+ SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) );
}
/*******************************/
@@ -231,8 +247,14 @@ void silk_noise_shape_analysis_FIX(
/*******************************/
/* More BWE for signals with high prediction gain */
strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) );
- BWExp_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ),
+ BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ),
silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 );
+ delta_Q16 = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ),
+ SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) );
+ BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 );
+ BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 );
+ /* BWExp1 will be applied after BWExp2, so make it relative */
+ BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) );
if( psEnc->sCmn.warping_Q16 > 0 ) {
/* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
@@ -262,7 +284,7 @@ void silk_noise_shape_analysis_FIX(
if( psEnc->sCmn.warping_Q16 > 0 ) {
/* Calculate warped auto correlation */
- silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder, arch );
+ silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
} else {
/* Calculate regular auto correlation */
silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch );
@@ -277,7 +299,7 @@ void silk_noise_shape_analysis_FIX(
silk_assert( nrg >= 0 );
/* Convert reflection coefficients to prediction coefficients */
- silk_k2a_Q16( AR_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );
+ silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );
Qnrg = -scale; /* range: -12...30*/
silk_assert( Qnrg >= -12 );
@@ -296,34 +318,40 @@ void silk_noise_shape_analysis_FIX(
if( psEnc->sCmn.warping_Q16 > 0 ) {
/* Adjust gain for warping */
- gain_mult_Q16 = warped_gain( AR_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder );
- silk_assert( psEncCtrl->Gains_Q16[ k ] > 0 );
- if( psEncCtrl->Gains_Q16[ k ] < SILK_FIX_CONST( 0.25, 16 ) ) {
- psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
+ gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder );
+ silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 );
+ if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) {
+ psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX;
} else {
- psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 );
- if ( psEncCtrl->Gains_Q16[ k ] >= ( silk_int32_MAX >> 1 ) ) {
- psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX;
- } else {
- psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT32( psEncCtrl->Gains_Q16[ k ], 1 );
- }
+ psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
}
- silk_assert( psEncCtrl->Gains_Q16[ k ] > 0 );
}
- /* Bandwidth expansion */
- silk_bwexpander_32( AR_Q24, psEnc->sCmn.shapingLPCOrder, BWExp_Q16 );
+ /* Bandwidth expansion for synthesis filter shaping */
+ silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 );
- if( psEnc->sCmn.warping_Q16 > 0 ) {
- /* Convert to monic warped prediction coefficients and limit absolute values */
- limit_warped_coefs( AR_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
+ /* Compute noise shaping filter coefficients */
+ silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) );
- /* Convert from Q24 to Q13 and store in int16 */
- for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {
- psEncCtrl->AR_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR_Q24[ i ], 11 ) );
- }
- } else {
- silk_LPC_fit( &psEncCtrl->AR_Q13[ k * MAX_SHAPE_LPC_ORDER ], AR_Q24, 13, 24, psEnc->sCmn.shapingLPCOrder );
+ /* Bandwidth expansion for analysis filter shaping */
+ silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) );
+ silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
+
+ /* Ratio of prediction gains, in energy domain */
+ pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
+ nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
+
+ /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
+ pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
+ psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 );
+
+ /* Convert to monic warped prediction coefficients and limit absolute values */
+ limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
+
+ /* Convert from Q24 to Q13 and store in int16 */
+ for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {
+ psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) );
+ psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) );
}
}
@@ -340,6 +368,11 @@ void silk_noise_shape_analysis_FIX(
psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 );
}
+ gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ),
+ psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 );
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] );
+ }
/************************************************/
/* Control low-frequency shaping and noise tilt */
@@ -377,6 +410,14 @@ void silk_noise_shape_analysis_FIX(
/****************************/
/* HARMONIC SHAPING CONTROL */
/****************************/
+ /* Control boosting of harmonic frequencies */
+ HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ),
+ psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) );
+
+ /* More harmonic boost for noisy input signals */
+ HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16,
+ SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) );
+
if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
/* More harmonic noise shaping for high bitrates or noisy input */
HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ),
@@ -394,11 +435,14 @@ void silk_noise_shape_analysis_FIX(
/* Smooth over subframes */
/*************************/
for( k = 0; k < MAX_NB_SUBFR; k++ ) {
+ psShapeSt->HarmBoost_smth_Q16 =
+ silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
psShapeSt->HarmShapeGain_smth_Q16 =
silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
psShapeSt->Tilt_smth_Q16 =
silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
+ psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 );
psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 );
psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 );
}
diff --git a/thirdparty/opus/silk/fixed/pitch_analysis_core_FIX.c b/thirdparty/opus/silk/fixed/pitch_analysis_core_FIX.c
index 14729046d2..01bb9fc0a8 100644
--- a/thirdparty/opus/silk/fixed/pitch_analysis_core_FIX.c
+++ b/thirdparty/opus/silk/fixed/pitch_analysis_core_FIX.c
@@ -80,7 +80,7 @@ static void silk_P_Ana_calc_energy_st3(
/* FIXED POINT CORE PITCH ANALYSIS FUNCTION */
/*************************************************************/
opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */
- const opus_int16 *frame_unscaled, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
+ const opus_int16 *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
opus_int *pitch_out, /* O 4 pitch lag values */
opus_int16 *lagIndex, /* O Lag Index */
opus_int8 *contourIndex, /* O Pitch contour Index */
@@ -94,17 +94,16 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
int arch /* I Run-time architecture */
)
{
- VARDECL( opus_int16, frame_8kHz_buf );
+ VARDECL( opus_int16, frame_8kHz );
VARDECL( opus_int16, frame_4kHz );
- VARDECL( opus_int16, frame_scaled );
opus_int32 filt_state[ 6 ];
- const opus_int16 *frame, *frame_8kHz;
+ const opus_int16 *input_frame_ptr;
opus_int i, k, d, j;
VARDECL( opus_int16, C );
VARDECL( opus_int32, xcorr32 );
const opus_int16 *target_ptr, *basis_ptr;
- opus_int32 cross_corr, normalizer, energy, energy_basis, energy_target;
- opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp, shift;
+ opus_int32 cross_corr, normalizer, energy, shift, energy_basis, energy_target;
+ opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp;
VARDECL( opus_int16, d_comp );
opus_int32 sum, threshold, lag_counter;
opus_int CBimax, CBimax_new, CBimax_old, lag, start_lag, end_lag, lag_new;
@@ -120,13 +119,12 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
opus_int32 delta_lag_log2_sqr_Q7, lag_log2_Q7, prevLag_log2_Q7, prev_lag_bias_Q13;
const opus_int8 *Lag_CB_ptr;
SAVE_STACK;
-
/* Check for valid sampling frequency */
- celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
+ silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
/* Check for valid complexity setting */
- celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
- celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) );
silk_assert( search_thres2_Q13 >= 0 && search_thres2_Q13 <= (1<<13) );
@@ -139,33 +137,17 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
min_lag = PE_MIN_LAG_MS * Fs_kHz;
max_lag = PE_MAX_LAG_MS * Fs_kHz - 1;
- /* Downscale input if necessary */
- silk_sum_sqr_shift( &energy, &shift, frame_unscaled, frame_length );
- shift += 3 - silk_CLZ32( energy ); /* at least two bits headroom */
- ALLOC( frame_scaled, frame_length, opus_int16 );
- if( shift > 0 ) {
- shift = silk_RSHIFT( shift + 1, 1 );
- for( i = 0; i < frame_length; i++ ) {
- frame_scaled[ i ] = silk_RSHIFT( frame_unscaled[ i ], shift );
- }
- frame = frame_scaled;
- } else {
- frame = frame_unscaled;
- }
-
- ALLOC( frame_8kHz_buf, ( Fs_kHz == 8 ) ? 1 : frame_length_8kHz, opus_int16 );
/* Resample from input sampled at Fs_kHz to 8 kHz */
+ ALLOC( frame_8kHz, frame_length_8kHz, opus_int16 );
if( Fs_kHz == 16 ) {
silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
- silk_resampler_down2( filt_state, frame_8kHz_buf, frame, frame_length );
- frame_8kHz = frame_8kHz_buf;
+ silk_resampler_down2( filt_state, frame_8kHz, frame, frame_length );
} else if( Fs_kHz == 12 ) {
silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) );
- silk_resampler_down2_3( filt_state, frame_8kHz_buf, frame, frame_length );
- frame_8kHz = frame_8kHz_buf;
+ silk_resampler_down2_3( filt_state, frame_8kHz, frame, frame_length );
} else {
- celt_assert( Fs_kHz == 8 );
- frame_8kHz = frame;
+ silk_assert( Fs_kHz == 8 );
+ silk_memcpy( frame_8kHz, frame, frame_length_8kHz * sizeof(opus_int16) );
}
/* Decimate again to 4 kHz */
@@ -178,6 +160,19 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
}
+ /*******************************************************************************
+ ** Scale 4 kHz signal down to prevent correlations measures from overflowing
+ ** find scaling as max scaling for each 8kHz(?) subframe
+ *******************************************************************************/
+
+ /* Inner product is calculated with different lengths, so scale for the worst case */
+ silk_sum_sqr_shift( &energy, &shift, frame_4kHz, frame_length_4kHz );
+ if( shift > 0 ) {
+ shift = silk_RSHIFT( shift, 1 );
+ for( i = 0; i < frame_length_4kHz; i++ ) {
+ frame_4kHz[ i ] = silk_RSHIFT( frame_4kHz[ i ], shift );
+ }
+ }
/******************************************************************************
* FIRST STAGE, operating in 4 khz
@@ -188,14 +183,14 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
target_ptr = &frame_4kHz[ silk_LSHIFT( SF_LENGTH_4KHZ, 2 ) ];
for( k = 0; k < nb_subfr >> 1; k++ ) {
/* Check that we are within range of the array */
- celt_assert( target_ptr >= frame_4kHz );
- celt_assert( target_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
+ silk_assert( target_ptr >= frame_4kHz );
+ silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
basis_ptr = target_ptr - MIN_LAG_4KHZ;
/* Check that we are within range of the array */
- celt_assert( basis_ptr >= frame_4kHz );
- celt_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
+ silk_assert( basis_ptr >= frame_4kHz );
+ silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
celt_pitch_xcorr( target_ptr, target_ptr - MAX_LAG_4KHZ, xcorr32, SF_LENGTH_8KHZ, MAX_LAG_4KHZ - MIN_LAG_4KHZ + 1, arch );
@@ -249,7 +244,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
/* Sort */
length_d_srch = silk_ADD_LSHIFT32( 4, complexity, 1 );
- celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
+ silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
silk_insertion_sort_decreasing_int16( C, d_srch, CSTRIDE_4KHZ,
length_d_srch );
@@ -274,7 +269,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
break;
}
}
- celt_assert( length_d_srch > 0 );
+ silk_assert( length_d_srch > 0 );
ALLOC( d_comp, D_COMP_STRIDE, opus_int16 );
for( i = D_COMP_MIN; i < D_COMP_MAX; i++ ) {
@@ -316,6 +311,18 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation
*************************************************************************************/
+ /******************************************************************************
+ ** Scale signal down to avoid correlations measures from overflowing
+ *******************************************************************************/
+ /* find scaling as max scaling for each subframe */
+ silk_sum_sqr_shift( &energy, &shift, frame_8kHz, frame_length_8kHz );
+ if( shift > 0 ) {
+ shift = silk_RSHIFT( shift, 1 );
+ for( i = 0; i < frame_length_8kHz; i++ ) {
+ frame_8kHz[ i ] = silk_RSHIFT( frame_8kHz[ i ], shift );
+ }
+ }
+
/*********************************************************************************
* Find energy of each subframe projected onto its history, for a range of delays
*********************************************************************************/
@@ -325,8 +332,8 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
for( k = 0; k < nb_subfr; k++ ) {
/* Check that we are within range of the array */
- celt_assert( target_ptr >= frame_8kHz );
- celt_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz );
+ silk_assert( target_ptr >= frame_8kHz );
+ silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz );
energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ, arch ), 1 );
for( j = 0; j < length_d_comp; j++ ) {
@@ -455,6 +462,24 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
silk_assert( *LTPCorr_Q15 >= 0 );
if( Fs_kHz > 8 ) {
+ VARDECL( opus_int16, scratch_mem );
+ /***************************************************************************/
+ /* Scale input signal down to avoid correlations measures from overflowing */
+ /***************************************************************************/
+ /* find scaling as max scaling for each subframe */
+ silk_sum_sqr_shift( &energy, &shift, frame, frame_length );
+ ALLOC( scratch_mem, shift > 0 ? frame_length : ALLOC_NONE, opus_int16 );
+ if( shift > 0 ) {
+ /* Move signal to scratch mem because the input signal should be unchanged */
+ shift = silk_RSHIFT( shift, 1 );
+ for( i = 0; i < frame_length; i++ ) {
+ scratch_mem[ i ] = silk_RSHIFT( frame[ i ], shift );
+ }
+ input_frame_ptr = scratch_mem;
+ } else {
+ input_frame_ptr = frame;
+ }
+
/* Search in original signal */
CBimax_old = CBimax;
@@ -494,14 +519,14 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
/* Calculate the correlations and energies needed in stage 3 */
ALLOC( energies_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals );
ALLOC( cross_corr_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals );
- silk_P_Ana_calc_corr_st3( cross_corr_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
- silk_P_Ana_calc_energy_st3( energies_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
+ silk_P_Ana_calc_corr_st3( cross_corr_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch );
+ silk_P_Ana_calc_energy_st3( energies_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch );
lag_counter = 0;
silk_assert( lag == silk_SAT16( lag ) );
contour_bias_Q15 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 15 ), lag );
- target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
+ target_ptr = &input_frame_ptr[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, nb_subfr * sf_length, arch ), 1 );
for( d = start_lag; d <= end_lag; d++ ) {
for( j = 0; j < nb_cbk_search; j++ ) {
@@ -550,7 +575,7 @@ opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0
*lagIndex = (opus_int16)( lag - MIN_LAG_8KHZ );
*contourIndex = (opus_int8)CBimax;
}
- celt_assert( *lagIndex >= 0 );
+ silk_assert( *lagIndex >= 0 );
/* return as voiced */
RESTORE_STACK;
return 0;
@@ -587,8 +612,8 @@ static void silk_P_Ana_calc_corr_st3(
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
SAVE_STACK;
- celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
- celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
@@ -596,7 +621,7 @@ static void silk_P_Ana_calc_corr_st3(
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
@@ -612,7 +637,7 @@ static void silk_P_Ana_calc_corr_st3(
/* Calculate the correlations for each subframe */
lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 );
lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 );
- celt_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
+ silk_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
celt_pitch_xcorr( target_ptr, target_ptr - start_lag - lag_high, xcorr32, sf_length, lag_high - lag_low + 1, arch );
for( j = lag_low; j <= lag_high; j++ ) {
silk_assert( lag_counter < SCRATCH_SIZE );
@@ -659,8 +684,8 @@ static void silk_P_Ana_calc_energy_st3(
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
SAVE_STACK;
- celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
- celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
@@ -668,7 +693,7 @@ static void silk_P_Ana_calc_energy_st3(
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
diff --git a/thirdparty/opus/silk/fixed/prefilter_FIX.c b/thirdparty/opus/silk/fixed/prefilter_FIX.c
new file mode 100644
index 0000000000..6a8e35152e
--- /dev/null
+++ b/thirdparty/opus/silk/fixed/prefilter_FIX.c
@@ -0,0 +1,221 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FIX.h"
+#include "stack_alloc.h"
+#include "tuning_parameters.h"
+
+#if defined(MIPSr1_ASM)
+#include "mips/prefilter_FIX_mipsr1.h"
+#endif
+
+
+#if !defined(OVERRIDE_silk_warped_LPC_analysis_filter_FIX)
+#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
+ ((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
+#endif
+
+/* Prefilter for finding Quantizer input signal */
+static OPUS_INLINE void silk_prefilt_FIX(
+ silk_prefilter_state_FIX *P, /* I/O state */
+ opus_int32 st_res_Q12[], /* I short term residual signal */
+ opus_int32 xw_Q3[], /* O prefiltered signal */
+ opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
+ opus_int Tilt_Q14, /* I Tilt shaping coeficient */
+ opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
+ opus_int lag, /* I Lag for harmonic shaping */
+ opus_int length /* I Length of signals */
+);
+
+void silk_warped_LPC_analysis_filter_FIX_c(
+ opus_int32 state[], /* I/O State [order + 1] */
+ opus_int32 res_Q2[], /* O Residual signal [length] */
+ const opus_int16 coef_Q13[], /* I Coefficients [order] */
+ const opus_int16 input[], /* I Input signal [length] */
+ const opus_int16 lambda_Q16, /* I Warping factor */
+ const opus_int length, /* I Length of input signal */
+ const opus_int order /* I Filter order (even) */
+)
+{
+ opus_int n, i;
+ opus_int32 acc_Q11, tmp1, tmp2;
+
+ /* Order must be even */
+ silk_assert( ( order & 1 ) == 0 );
+
+ for( n = 0; n < length; n++ ) {
+ /* Output of lowpass section */
+ tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
+ state[ 0 ] = silk_LSHIFT( input[ n ], 14 );
+ /* Output of allpass section */
+ tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
+ state[ 1 ] = tmp2;
+ acc_Q11 = silk_RSHIFT( order, 1 );
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
+ /* Loop over allpass sections */
+ for( i = 2; i < order; i += 2 ) {
+ /* Output of allpass section */
+ tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
+ state[ i ] = tmp1;
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
+ /* Output of allpass section */
+ tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
+ state[ i + 1 ] = tmp2;
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
+ }
+ state[ order ] = tmp1;
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
+ res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
+ }
+}
+
+void silk_prefilter_FIX(
+ silk_encoder_state_FIX *psEnc, /* I/O Encoder state */
+ const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */
+ opus_int32 xw_Q3[], /* O Weighted signal */
+ const opus_int16 x[] /* I Speech signal */
+)
+{
+ silk_prefilter_state_FIX *P = &psEnc->sPrefilt;
+ opus_int j, k, lag;
+ opus_int32 tmp_32;
+ const opus_int16 *AR1_shp_Q13;
+ const opus_int16 *px;
+ opus_int32 *pxw_Q3;
+ opus_int HarmShapeGain_Q12, Tilt_Q14;
+ opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14;
+ VARDECL( opus_int32, x_filt_Q12 );
+ VARDECL( opus_int32, st_res_Q2 );
+ opus_int16 B_Q10[ 2 ];
+ SAVE_STACK;
+
+ /* Set up pointers */
+ px = x;
+ pxw_Q3 = xw_Q3;
+ lag = P->lagPrev;
+ ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 );
+ ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 );
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ /* Update Variables that change per sub frame */
+ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+ lag = psEncCtrl->pitchL[ k ];
+ }
+
+ /* Noise shape parameters */
+ HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] );
+ silk_assert( HarmShapeGain_Q12 >= 0 );
+ HarmShapeFIRPacked_Q12 = silk_RSHIFT( HarmShapeGain_Q12, 2 );
+ HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 );
+ Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ];
+ LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ];
+ AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ];
+
+ /* Short term FIR filtering*/
+ silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px,
+ psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder, psEnc->sCmn.arch );
+
+ /* Reduce (mainly) low frequencies during harmonic emphasis */
+ B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 );
+ tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */
+ tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */
+ tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */
+ tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 ); /* Q10 */
+ B_Q10[ 1 ]= silk_SAT16( tmp_32 );
+ x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] );
+ for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) {
+ x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] );
+ }
+ P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ];
+
+ silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length );
+
+ px += psEnc->sCmn.subfr_length;
+ pxw_Q3 += psEnc->sCmn.subfr_length;
+ }
+
+ P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
+ RESTORE_STACK;
+}
+
+#ifndef OVERRIDE_silk_prefilt_FIX
+/* Prefilter for finding Quantizer input signal */
+static OPUS_INLINE void silk_prefilt_FIX(
+ silk_prefilter_state_FIX *P, /* I/O state */
+ opus_int32 st_res_Q12[], /* I short term residual signal */
+ opus_int32 xw_Q3[], /* O prefiltered signal */
+ opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */
+ opus_int Tilt_Q14, /* I Tilt shaping coeficient */
+ opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */
+ opus_int lag, /* I Lag for harmonic shaping */
+ opus_int length /* I Length of signals */
+)
+{
+ opus_int i, idx, LTP_shp_buf_idx;
+ opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10;
+ opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12;
+ opus_int16 *LTP_shp_buf;
+
+ /* To speed up use temp variables instead of using the struct */
+ LTP_shp_buf = P->sLTP_shp;
+ LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
+ sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12;
+ sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12;
+
+ for( i = 0; i < length; i++ ) {
+ if( lag > 0 ) {
+ /* unrolled loop */
+ silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
+ idx = lag + LTP_shp_buf_idx;
+ n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
+ n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
+ n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
+ } else {
+ n_LTP_Q12 = 0;
+ }
+
+ n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
+ n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
+
+ sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
+ sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) );
+
+ LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
+ LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
+
+ xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 );
+ }
+
+ /* Copy temp variable back to state */
+ P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12;
+ P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12;
+ P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
+}
+#endif /* OVERRIDE_silk_prefilt_FIX */
diff --git a/thirdparty/opus/silk/fixed/residual_energy16_FIX.c b/thirdparty/opus/silk/fixed/residual_energy16_FIX.c
index 7f130f3d3d..ebffb2a66f 100644
--- a/thirdparty/opus/silk/fixed/residual_energy16_FIX.c
+++ b/thirdparty/opus/silk/fixed/residual_energy16_FIX.c
@@ -47,10 +47,10 @@ opus_int32 silk_residual_energy16_covar_FIX(
const opus_int32 *pRow;
/* Safety checks */
- celt_assert( D >= 0 );
- celt_assert( D <= 16 );
- celt_assert( cQ > 0 );
- celt_assert( cQ < 16 );
+ silk_assert( D >= 0 );
+ silk_assert( D <= 16 );
+ silk_assert( cQ > 0 );
+ silk_assert( cQ < 16 );
lshifts = 16 - cQ;
Qxtra = lshifts;
diff --git a/thirdparty/opus/silk/fixed/residual_energy_FIX.c b/thirdparty/opus/silk/fixed/residual_energy_FIX.c
index 6c7cade9a0..41f74778e8 100644
--- a/thirdparty/opus/silk/fixed/residual_energy_FIX.c
+++ b/thirdparty/opus/silk/fixed/residual_energy_FIX.c
@@ -58,7 +58,7 @@ void silk_residual_energy_FIX(
/* Filter input to create the LPC residual for each frame half, and measure subframe energies */
ALLOC( LPC_res, ( MAX_NB_SUBFR >> 1 ) * offset, opus_int16 );
- celt_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr );
+ silk_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr );
for( i = 0; i < nb_subfr >> 1; i++ ) {
/* Calculate half frame LPC residual signal including preceding samples */
silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order, arch );
diff --git a/thirdparty/opus/silk/fixed/schur64_FIX.c b/thirdparty/opus/silk/fixed/schur64_FIX.c
index 4b7e19ea59..764a10ef3e 100644
--- a/thirdparty/opus/silk/fixed/schur64_FIX.c
+++ b/thirdparty/opus/silk/fixed/schur64_FIX.c
@@ -43,7 +43,7 @@ opus_int32 silk_schur64( /* O returns residual ene
opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31;
- celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
+ silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
/* Check for invalid input */
if( c[ 0 ] <= 0 ) {
@@ -51,10 +51,9 @@ opus_int32 silk_schur64( /* O returns residual ene
return 0;
}
- k = 0;
- do {
+ for( k = 0; k < order + 1; k++ ) {
C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ];
- } while( ++k <= order );
+ }
for( k = 0; k < order; k++ ) {
/* Check that we won't be getting an unstable rc, otherwise stop here. */
diff --git a/thirdparty/opus/silk/fixed/schur_FIX.c b/thirdparty/opus/silk/fixed/schur_FIX.c
index 2840f6b1aa..c4c0ef23b4 100644
--- a/thirdparty/opus/silk/fixed/schur_FIX.c
+++ b/thirdparty/opus/silk/fixed/schur_FIX.c
@@ -43,29 +43,28 @@ opus_int32 silk_schur( /* O Returns residual ene
opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15;
- celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
+ silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
/* Get number of leading zeros */
lz = silk_CLZ32( c[ 0 ] );
/* Copy correlations and adjust level to Q30 */
- k = 0;
if( lz < 2 ) {
/* lz must be 1, so shift one to the right */
- do {
+ for( k = 0; k < order + 1; k++ ) {
C[ k ][ 0 ] = C[ k ][ 1 ] = silk_RSHIFT( c[ k ], 1 );
- } while( ++k <= order );
+ }
} else if( lz > 2 ) {
/* Shift to the left */
lz -= 2;
- do {
+ for( k = 0; k < order + 1; k++ ) {
C[ k ][ 0 ] = C[ k ][ 1 ] = silk_LSHIFT( c[ k ], lz );
- } while( ++k <= order );
+ }
} else {
/* No need to shift */
- do {
+ for( k = 0; k < order + 1; k++ ) {
C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ];
- } while( ++k <= order );
+ }
}
for( k = 0; k < order; k++ ) {
diff --git a/thirdparty/opus/silk/fixed/solve_LS_FIX.c b/thirdparty/opus/silk/fixed/solve_LS_FIX.c
new file mode 100644
index 0000000000..51d7d49d02
--- /dev/null
+++ b/thirdparty/opus/silk/fixed/solve_LS_FIX.c
@@ -0,0 +1,249 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FIX.h"
+#include "stack_alloc.h"
+#include "tuning_parameters.h"
+
+/*****************************/
+/* Internal function headers */
+/*****************************/
+
+typedef struct {
+ opus_int32 Q36_part;
+ opus_int32 Q48_part;
+} inv_D_t;
+
+/* Factorize square matrix A into LDL form */
+static OPUS_INLINE void silk_LDL_factorize_FIX(
+ opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */
+ opus_int M, /* I Size of Matrix */
+ opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */
+ inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */
+);
+
+/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */
+static OPUS_INLINE void silk_LS_SolveFirst_FIX(
+ const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
+ opus_int M, /* I Dim of Matrix equation */
+ const opus_int32 *b, /* I b Vector */
+ opus_int32 *x_Q16 /* O x Vector */
+);
+
+/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */
+static OPUS_INLINE void silk_LS_SolveLast_FIX(
+ const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
+ const opus_int M, /* I Dim of Matrix equation */
+ const opus_int32 *b, /* I b Vector */
+ opus_int32 *x_Q16 /* O x Vector */
+);
+
+static OPUS_INLINE void silk_LS_divide_Q16_FIX(
+ opus_int32 T[], /* I/O Numenator vector */
+ inv_D_t *inv_D, /* I 1 / D vector */
+ opus_int M /* I dimension */
+);
+
+/* Solves Ax = b, assuming A is symmetric */
+void silk_solve_LDL_FIX(
+ opus_int32 *A, /* I Pointer to symetric square matrix A */
+ opus_int M, /* I Size of matrix */
+ const opus_int32 *b, /* I Pointer to b vector */
+ opus_int32 *x_Q16 /* O Pointer to x solution vector */
+)
+{
+ VARDECL( opus_int32, L_Q16 );
+ opus_int32 Y[ MAX_MATRIX_SIZE ];
+ inv_D_t inv_D[ MAX_MATRIX_SIZE ];
+ SAVE_STACK;
+
+ silk_assert( M <= MAX_MATRIX_SIZE );
+ ALLOC( L_Q16, M * M, opus_int32 );
+
+ /***************************************************
+ Factorize A by LDL such that A = L*D*L',
+ where L is lower triangular with ones on diagonal
+ ****************************************************/
+ silk_LDL_factorize_FIX( A, M, L_Q16, inv_D );
+
+ /****************************************************
+ * substitute D*L'*x = Y. ie:
+ L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b
+ ******************************************************/
+ silk_LS_SolveFirst_FIX( L_Q16, M, b, Y );
+
+ /****************************************************
+ D*L'*x = Y <=> L'*x = inv(D)*Y, because D is
+ diagonal just multiply with 1/d_i
+ ****************************************************/
+ silk_LS_divide_Q16_FIX( Y, inv_D, M );
+
+ /****************************************************
+ x = inv(L') * inv(D) * Y
+ *****************************************************/
+ silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 );
+ RESTORE_STACK;
+}
+
+static OPUS_INLINE void silk_LDL_factorize_FIX(
+ opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */
+ opus_int M, /* I Size of Matrix */
+ opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */
+ inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */
+)
+{
+ opus_int i, j, k, status, loop_count;
+ const opus_int32 *ptr1, *ptr2;
+ opus_int32 diag_min_value, tmp_32, err;
+ opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ];
+ opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48;
+
+ silk_assert( M <= MAX_MATRIX_SIZE );
+
+ status = 1;
+ diag_min_value = silk_max_32( silk_SMMUL( silk_ADD_SAT32( A[ 0 ], A[ silk_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 );
+ for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) {
+ status = 0;
+ for( j = 0; j < M; j++ ) {
+ ptr1 = matrix_adr( L_Q16, j, 0, M );
+ tmp_32 = 0;
+ for( i = 0; i < j; i++ ) {
+ v_Q0[ i ] = silk_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */
+ tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */
+ }
+ tmp_32 = silk_SUB32( matrix_ptr( A, j, j, M ), tmp_32 );
+
+ if( tmp_32 < diag_min_value ) {
+ tmp_32 = silk_SUB32( silk_SMULBB( loop_count + 1, diag_min_value ), tmp_32 );
+ /* Matrix not positive semi-definite, or ill conditioned */
+ for( i = 0; i < M; i++ ) {
+ matrix_ptr( A, i, i, M ) = silk_ADD32( matrix_ptr( A, i, i, M ), tmp_32 );
+ }
+ status = 1;
+ break;
+ }
+ D_Q0[ j ] = tmp_32; /* always < max(Correlation) */
+
+ /* two-step division */
+ one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */
+ one_div_diag_Q40 = silk_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */
+ err = silk_SUB32( (opus_int32)1 << 24, silk_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */
+ one_div_diag_Q48 = silk_SMULWW( err, one_div_diag_Q40 ); /* Q48 */
+
+ /* Save 1/Ds */
+ inv_D[ j ].Q36_part = one_div_diag_Q36;
+ inv_D[ j ].Q48_part = one_div_diag_Q48;
+
+ matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */
+ ptr1 = matrix_adr( A, j, 0, M );
+ ptr2 = matrix_adr( L_Q16, j + 1, 0, M );
+ for( i = j + 1; i < M; i++ ) {
+ tmp_32 = 0;
+ for( k = 0; k < j; k++ ) {
+ tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */
+ }
+ tmp_32 = silk_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */
+
+ /* tmp_32 / D_Q0[j] : Divide to Q16 */
+ matrix_ptr( L_Q16, i, j, M ) = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ),
+ silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) );
+
+ /* go to next column */
+ ptr2 += M;
+ }
+ }
+ }
+
+ silk_assert( status == 0 );
+}
+
+static OPUS_INLINE void silk_LS_divide_Q16_FIX(
+ opus_int32 T[], /* I/O Numenator vector */
+ inv_D_t *inv_D, /* I 1 / D vector */
+ opus_int M /* I dimension */
+)
+{
+ opus_int i;
+ opus_int32 tmp_32;
+ opus_int32 one_div_diag_Q36, one_div_diag_Q48;
+
+ for( i = 0; i < M; i++ ) {
+ one_div_diag_Q36 = inv_D[ i ].Q36_part;
+ one_div_diag_Q48 = inv_D[ i ].Q48_part;
+
+ tmp_32 = T[ i ];
+ T[ i ] = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) );
+ }
+}
+
+/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */
+static OPUS_INLINE void silk_LS_SolveFirst_FIX(
+ const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
+ opus_int M, /* I Dim of Matrix equation */
+ const opus_int32 *b, /* I b Vector */
+ opus_int32 *x_Q16 /* O x Vector */
+)
+{
+ opus_int i, j;
+ const opus_int32 *ptr32;
+ opus_int32 tmp_32;
+
+ for( i = 0; i < M; i++ ) {
+ ptr32 = matrix_adr( L_Q16, i, 0, M );
+ tmp_32 = 0;
+ for( j = 0; j < i; j++ ) {
+ tmp_32 = silk_SMLAWW( tmp_32, ptr32[ j ], x_Q16[ j ] );
+ }
+ x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 );
+ }
+}
+
+/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */
+static OPUS_INLINE void silk_LS_SolveLast_FIX(
+ const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */
+ const opus_int M, /* I Dim of Matrix equation */
+ const opus_int32 *b, /* I b Vector */
+ opus_int32 *x_Q16 /* O x Vector */
+)
+{
+ opus_int i, j;
+ const opus_int32 *ptr32;
+ opus_int32 tmp_32;
+
+ for( i = M - 1; i >= 0; i-- ) {
+ ptr32 = matrix_adr( L_Q16, 0, i, M );
+ tmp_32 = 0;
+ for( j = M - 1; j > i; j-- ) {
+ tmp_32 = silk_SMLAWW( tmp_32, ptr32[ silk_SMULBB( j, M ) ], x_Q16[ j ] );
+ }
+ x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 );
+ }
+}
diff --git a/thirdparty/opus/silk/fixed/structs_FIX.h b/thirdparty/opus/silk/fixed/structs_FIX.h
index 2774a97b24..3294b25128 100644
--- a/thirdparty/opus/silk/fixed/structs_FIX.h
+++ b/thirdparty/opus/silk/fixed/structs_FIX.h
@@ -48,16 +48,30 @@ typedef struct {
} silk_shape_state_FIX;
/********************************/
+/* Prefilter state */
+/********************************/
+typedef struct {
+ opus_int16 sLTP_shp[ LTP_BUF_LENGTH ];
+ opus_int32 sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ];
+ opus_int sLTP_shp_buf_idx;
+ opus_int32 sLF_AR_shp_Q12;
+ opus_int32 sLF_MA_shp_Q12;
+ opus_int32 sHarmHP_Q2;
+ opus_int32 rand_seed;
+ opus_int lagPrev;
+} silk_prefilter_state_FIX;
+
+/********************************/
/* Encoder state FIX */
/********************************/
typedef struct {
silk_encoder_state sCmn; /* Common struct, shared with floating-point code */
silk_shape_state_FIX sShape; /* Shape state */
+ silk_prefilter_state_FIX sPrefilt; /* Prefilter State */
/* Buffer for find pitch and noise shape analysis */
silk_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
opus_int LTPCorr_Q15; /* Normalized correlation from pitch lag estimator */
- opus_int32 resNrgSmth;
} silk_encoder_state_FIX;
/************************/
@@ -73,8 +87,11 @@ typedef struct {
/* Noise shaping parameters */
/* Testing */
- silk_DWORD_ALIGN opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ silk_DWORD_ALIGN opus_int16 AR1_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ silk_DWORD_ALIGN opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */
+ opus_int GainsPre_Q14[ MAX_NB_SUBFR ];
+ opus_int HarmBoost_Q14[ MAX_NB_SUBFR ];
opus_int Tilt_Q14[ MAX_NB_SUBFR ];
opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ];
opus_int Lambda_Q10;
@@ -82,6 +99,7 @@ typedef struct {
opus_int coding_quality_Q14;
/* measures */
+ opus_int sparseness_Q8;
opus_int32 predGain_Q16;
opus_int LTPredCodGain_Q7;
opus_int32 ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
diff --git a/thirdparty/opus/silk/fixed/warped_autocorrelation_FIX.c b/thirdparty/opus/silk/fixed/warped_autocorrelation_FIX.c
index 5c79553bc0..6ca6c1184d 100644
--- a/thirdparty/opus/silk/fixed/warped_autocorrelation_FIX.c
+++ b/thirdparty/opus/silk/fixed/warped_autocorrelation_FIX.c
@@ -31,14 +31,17 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main_FIX.h"
+#define QC 10
+#define QS 14
+
#if defined(MIPSr1_ASM)
#include "mips/warped_autocorrelation_FIX_mipsr1.h"
#endif
+#ifndef OVERRIDE_silk_warped_autocorrelation_FIX
/* Autocorrelations for a warped frequency axis */
-#ifndef OVERRIDE_silk_warped_autocorrelation_FIX_c
-void silk_warped_autocorrelation_FIX_c(
+void silk_warped_autocorrelation_FIX(
opus_int32 *corr, /* O Result [order + 1] */
opus_int *scale, /* O Scaling of the correlation vector */
const opus_int16 *input, /* I Input data to correlate */
@@ -53,7 +56,7 @@ void silk_warped_autocorrelation_FIX_c(
opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
/* Order must be even */
- celt_assert( ( order & 1 ) == 0 );
+ silk_assert( ( order & 1 ) == 0 );
silk_assert( 2 * QS - QC >= 0 );
/* Loop over samples */
@@ -89,4 +92,4 @@ void silk_warped_autocorrelation_FIX_c(
}
silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/
}
-#endif /* OVERRIDE_silk_warped_autocorrelation_FIX_c */
+#endif /* OVERRIDE_silk_warped_autocorrelation_FIX */
diff --git a/thirdparty/opus/silk/fixed/x86/burg_modified_FIX_sse4_1.c b/thirdparty/opus/silk/fixed/x86/burg_modified_FIX_sse.c
index bbb1ce0fcc..3c3583c5fc 100644
--- a/thirdparty/opus/silk/fixed/x86/burg_modified_FIX_sse4_1.c
+++ b/thirdparty/opus/silk/fixed/x86/burg_modified_FIX_sse.c
@@ -72,7 +72,7 @@ void silk_burg_modified_sse4_1(
__m128i FIRST_3210, LAST_3210, ATMP_3210, TMP1_3210, TMP2_3210, T1_3210, T2_3210, PTR_3210, SUBFR_3210, X1_3210, X2_3210;
__m128i CONST1 = _mm_set1_epi32(1);
- celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+ silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
/* Compute autocorrelations, added over subframes */
silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length );
diff --git a/thirdparty/opus/silk/fixed/x86/prefilter_FIX_sse.c b/thirdparty/opus/silk/fixed/x86/prefilter_FIX_sse.c
new file mode 100644
index 0000000000..488a603f5d
--- /dev/null
+++ b/thirdparty/opus/silk/fixed/x86/prefilter_FIX_sse.c
@@ -0,0 +1,160 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+#include <smmintrin.h>
+#include "main.h"
+#include "celt/x86/x86cpu.h"
+
+void silk_warped_LPC_analysis_filter_FIX_sse4_1(
+ opus_int32 state[], /* I/O State [order + 1] */
+ opus_int32 res_Q2[], /* O Residual signal [length] */
+ const opus_int16 coef_Q13[], /* I Coefficients [order] */
+ const opus_int16 input[], /* I Input signal [length] */
+ const opus_int16 lambda_Q16, /* I Warping factor */
+ const opus_int length, /* I Length of input signal */
+ const opus_int order /* I Filter order (even) */
+)
+{
+ opus_int n, i;
+ opus_int32 acc_Q11, tmp1, tmp2;
+
+ /* Order must be even */
+ silk_assert( ( order & 1 ) == 0 );
+
+ if (order == 10)
+ {
+ if (0 == lambda_Q16)
+ {
+ __m128i coef_Q13_3210, coef_Q13_7654;
+ __m128i coef_Q13_0123, coef_Q13_4567;
+ __m128i state_0123, state_4567;
+ __m128i xmm_product1, xmm_product2;
+ __m128i xmm_tempa, xmm_tempb;
+
+ register opus_int32 sum;
+ register opus_int32 state_8, state_9, state_a;
+ register opus_int64 coef_Q13_8, coef_Q13_9;
+
+ silk_assert( length > 0 );
+
+ coef_Q13_3210 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 0 ] );
+ coef_Q13_7654 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 4 ] );
+
+ coef_Q13_0123 = _mm_shuffle_epi32( coef_Q13_3210, _MM_SHUFFLE( 0, 1, 2, 3 ) );
+ coef_Q13_4567 = _mm_shuffle_epi32( coef_Q13_7654, _MM_SHUFFLE( 0, 1, 2, 3 ) );
+
+ coef_Q13_8 = (opus_int64) coef_Q13[ 8 ];
+ coef_Q13_9 = (opus_int64) coef_Q13[ 9 ];
+
+ state_0123 = _mm_loadu_si128( (__m128i *)(&state[ 0 ] ) );
+ state_4567 = _mm_loadu_si128( (__m128i *)(&state[ 4 ] ) );
+
+ state_0123 = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) );
+ state_4567 = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) );
+
+ state_8 = state[ 8 ];
+ state_9 = state[ 9 ];
+ state_a = 0;
+
+ for( n = 0; n < length; n++ )
+ {
+ xmm_product1 = _mm_mul_epi32( coef_Q13_0123, state_0123 ); /* 64-bit multiply, only 2 pairs */
+ xmm_product2 = _mm_mul_epi32( coef_Q13_4567, state_4567 );
+
+ xmm_tempa = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) );
+ xmm_tempb = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) );
+
+ xmm_product1 = _mm_srli_epi64( xmm_product1, 16 ); /* >> 16, zero extending works */
+ xmm_product2 = _mm_srli_epi64( xmm_product2, 16 );
+
+ xmm_tempa = _mm_mul_epi32( coef_Q13_3210, xmm_tempa );
+ xmm_tempb = _mm_mul_epi32( coef_Q13_7654, xmm_tempb );
+
+ xmm_tempa = _mm_srli_epi64( xmm_tempa, 16 );
+ xmm_tempb = _mm_srli_epi64( xmm_tempb, 16 );
+
+ xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_product1 );
+ xmm_tempb = _mm_add_epi32( xmm_tempb, xmm_product2 );
+ xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_tempb );
+
+ sum = (coef_Q13_8 * state_8) >> 16;
+ sum += (coef_Q13_9 * state_9) >> 16;
+
+ xmm_tempa = _mm_add_epi32( xmm_tempa, _mm_shuffle_epi32( xmm_tempa, _MM_SHUFFLE( 0, 0, 0, 2 ) ) );
+ sum += _mm_cvtsi128_si32( xmm_tempa);
+ res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( ( 5 + sum ), 9);
+
+ /* move right */
+ state_a = state_9;
+ state_9 = state_8;
+ state_8 = _mm_cvtsi128_si32( state_4567 );
+ state_4567 = _mm_alignr_epi8( state_0123, state_4567, 4 );
+
+ state_0123 = _mm_alignr_epi8( _mm_cvtsi32_si128( silk_LSHIFT( input[ n ], 14 ) ), state_0123, 4 );
+ }
+
+ _mm_storeu_si128( (__m128i *)( &state[ 0 ] ), _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ) );
+ _mm_storeu_si128( (__m128i *)( &state[ 4 ] ), _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ) );
+ state[ 8 ] = state_8;
+ state[ 9 ] = state_9;
+ state[ 10 ] = state_a;
+
+ return;
+ }
+ }
+
+ for( n = 0; n < length; n++ ) {
+ /* Output of lowpass section */
+ tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
+ state[ 0 ] = silk_LSHIFT( input[ n ], 14 );
+ /* Output of allpass section */
+ tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
+ state[ 1 ] = tmp2;
+ acc_Q11 = silk_RSHIFT( order, 1 );
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
+ /* Loop over allpass sections */
+ for( i = 2; i < order; i += 2 ) {
+ /* Output of allpass section */
+ tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
+ state[ i ] = tmp1;
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
+ /* Output of allpass section */
+ tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
+ state[ i + 1 ] = tmp2;
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
+ }
+ state[ order ] = tmp1;
+ acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
+ res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
+ }
+}
diff --git a/thirdparty/opus/silk/fixed/x86/vector_ops_FIX_sse4_1.c b/thirdparty/opus/silk/fixed/x86/vector_ops_FIX_sse.c
index c1e90564d0..c1e90564d0 100644
--- a/thirdparty/opus/silk/fixed/x86/vector_ops_FIX_sse4_1.c
+++ b/thirdparty/opus/silk/fixed/x86/vector_ops_FIX_sse.c
diff --git a/thirdparty/opus/silk/float/LPC_analysis_filter_FLP.c b/thirdparty/opus/silk/float/LPC_analysis_filter_FLP.c
index 0e1a1fed0f..cae89a0a18 100644
--- a/thirdparty/opus/silk/float/LPC_analysis_filter_FLP.c
+++ b/thirdparty/opus/silk/float/LPC_analysis_filter_FLP.c
@@ -215,7 +215,7 @@ void silk_LPC_analysis_filter_FLP(
const opus_int Order /* I LPC order */
)
{
- celt_assert( Order <= length );
+ silk_assert( Order <= length );
switch( Order ) {
case 6:
@@ -239,7 +239,7 @@ void silk_LPC_analysis_filter_FLP(
break;
default:
- celt_assert( 0 );
+ silk_assert( 0 );
break;
}
diff --git a/thirdparty/opus/silk/float/LPC_inv_pred_gain_FLP.c b/thirdparty/opus/silk/float/LPC_inv_pred_gain_FLP.c
index 2be2122d61..25178bacdd 100644
--- a/thirdparty/opus/silk/float/LPC_inv_pred_gain_FLP.c
+++ b/thirdparty/opus/silk/float/LPC_inv_pred_gain_FLP.c
@@ -31,7 +31,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "SigProc_FIX.h"
#include "SigProc_FLP.h"
-#include "define.h"
+
+#define RC_THRESHOLD 0.9999f
/* compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */
@@ -42,32 +43,34 @@ silk_float silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction ga
)
{
opus_int k, n;
- double invGain, rc, rc_mult1, rc_mult2, tmp1, tmp2;
- silk_float Atmp[ SILK_MAX_ORDER_LPC ];
+ double invGain, rc, rc_mult1, rc_mult2;
+ silk_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ];
+ silk_float *Aold, *Anew;
- silk_memcpy( Atmp, A, order * sizeof(silk_float) );
+ Anew = Atmp[ order & 1 ];
+ silk_memcpy( Anew, A, order * sizeof(silk_float) );
invGain = 1.0;
for( k = order - 1; k > 0; k-- ) {
- rc = -Atmp[ k ];
- rc_mult1 = 1.0f - rc * rc;
- invGain *= rc_mult1;
- if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
+ rc = -Anew[ k ];
+ if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
return 0.0f;
}
+ rc_mult1 = 1.0f - rc * rc;
rc_mult2 = 1.0f / rc_mult1;
- for( n = 0; n < (k + 1) >> 1; n++ ) {
- tmp1 = Atmp[ n ];
- tmp2 = Atmp[ k - n - 1 ];
- Atmp[ n ] = (silk_float)( ( tmp1 - tmp2 * rc ) * rc_mult2 );
- Atmp[ k - n - 1 ] = (silk_float)( ( tmp2 - tmp1 * rc ) * rc_mult2 );
+ invGain *= rc_mult1;
+ /* swap pointers */
+ Aold = Anew;
+ Anew = Atmp[ k & 1 ];
+ for( n = 0; n < k; n++ ) {
+ Anew[ n ] = (silk_float)( ( Aold[ n ] - Aold[ k - n - 1 ] * rc ) * rc_mult2 );
}
}
- rc = -Atmp[ 0 ];
- rc_mult1 = 1.0f - rc * rc;
- invGain *= rc_mult1;
- if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
+ rc = -Anew[ 0 ];
+ if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
return 0.0f;
}
+ rc_mult1 = 1.0f - rc * rc;
+ invGain *= rc_mult1;
return (silk_float)invGain;
}
diff --git a/thirdparty/opus/silk/float/SigProc_FLP.h b/thirdparty/opus/silk/float/SigProc_FLP.h
index 953de8b09e..f0cb3733be 100644
--- a/thirdparty/opus/silk/float/SigProc_FLP.h
+++ b/thirdparty/opus/silk/float/SigProc_FLP.h
@@ -68,6 +68,13 @@ void silk_k2a_FLP(
opus_int32 order /* I prediction order */
);
+/* Solve the normal equations using the Levinson-Durbin recursion */
+silk_float silk_levinsondurbin_FLP( /* O prediction error energy */
+ silk_float A[], /* O prediction coefficients [order] */
+ const silk_float corr[], /* I input auto-correlations [order + 1] */
+ const opus_int order /* I prediction order */
+);
+
/* compute autocorrelation */
void silk_autocorrelation_FLP(
silk_float *results, /* O result (length correlationCount) */
diff --git a/thirdparty/opus/silk/float/apply_sine_window_FLP.c b/thirdparty/opus/silk/float/apply_sine_window_FLP.c
index e49e717991..6aae57c0ab 100644
--- a/thirdparty/opus/silk/float/apply_sine_window_FLP.c
+++ b/thirdparty/opus/silk/float/apply_sine_window_FLP.c
@@ -45,10 +45,10 @@ void silk_apply_sine_window_FLP(
opus_int k;
silk_float freq, c, S0, S1;
- celt_assert( win_type == 1 || win_type == 2 );
+ silk_assert( win_type == 1 || win_type == 2 );
/* Length must be multiple of 4 */
- celt_assert( ( length & 3 ) == 0 );
+ silk_assert( ( length & 3 ) == 0 );
freq = PI / ( length + 1 );
diff --git a/thirdparty/opus/silk/float/burg_modified_FLP.c b/thirdparty/opus/silk/float/burg_modified_FLP.c
index 756b76a35b..ea5dc25a93 100644
--- a/thirdparty/opus/silk/float/burg_modified_FLP.c
+++ b/thirdparty/opus/silk/float/burg_modified_FLP.c
@@ -52,7 +52,7 @@ silk_float silk_burg_modified_FLP( /* O returns residual energy
double CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ];
double Af[ SILK_MAX_ORDER_LPC ];
- celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+ silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
/* Compute autocorrelations, added over subframes */
C0 = silk_energy_FLP( x, nb_subfr * subfr_length );
diff --git a/thirdparty/opus/silk/float/encode_frame_FLP.c b/thirdparty/opus/silk/float/encode_frame_FLP.c
index b029c3f5ca..2092a4d9e2 100644
--- a/thirdparty/opus/silk/float/encode_frame_FLP.c
+++ b/thirdparty/opus/silk/float/encode_frame_FLP.c
@@ -29,7 +29,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
#endif
-#include <stdlib.h>
#include "main_FLP.h"
#include "tuning_parameters.h"
@@ -42,28 +41,21 @@ static OPUS_INLINE void silk_LBRR_encode_FLP(
);
void silk_encode_do_VAD_FLP(
- silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
- opus_int activity /* I Decision of Opus voice activity detector */
+ silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */
)
{
- const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
-
/****************************/
/* Voice Activity Detection */
/****************************/
silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
- /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
- if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
- psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
- }
/**************************************************/
/* Convert speech activity into VAD and DTX flags */
/**************************************************/
- if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
+ if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) {
psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
psEnc->sCmn.noSpeechCounter++;
- if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
+ if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.inDTX = 0;
} else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
@@ -93,6 +85,7 @@ opus_int silk_encode_frame_FLP(
silk_encoder_control_FLP sEncCtrl;
opus_int i, iter, maxIter, found_upper, found_lower, ret = 0;
silk_float *x_frame, *res_pitch_frame;
+ silk_float xfw[ MAX_FRAME_LENGTH ];
silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
ec_enc sRangeEnc_copy, sRangeEnc_copy2;
silk_nsq_state sNSQ_copy, sNSQ_copy2;
@@ -104,9 +97,6 @@ opus_int silk_encode_frame_FLP(
opus_int8 LastGainIndex_copy2;
opus_int32 pGains_Q16[ MAX_NB_SUBFR ];
opus_uint8 ec_buf_copy[ 1275 ];
- opus_int gain_lock[ MAX_NB_SUBFR ] = {0};
- opus_int16 best_gain_mult[ MAX_NB_SUBFR ];
- opus_int best_sum[ MAX_NB_SUBFR ];
/* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
@@ -149,17 +139,22 @@ opus_int silk_encode_frame_FLP(
/***************************************************/
/* Find linear prediction coefficients (LPC + LTP) */
/***************************************************/
- silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
+ silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding );
/****************************************/
/* Process gains */
/****************************************/
silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding );
+ /*****************************************/
+ /* Prefiltering for noise shaper */
+ /*****************************************/
+ silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame );
+
/****************************************/
/* Low Bitrate Redundant Encoding */
/****************************************/
- silk_LBRR_encode_FLP( psEnc, &sEncCtrl, x_frame, condCoding );
+ silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding );
/* Loop over quantizer and entroy coding to control bitrate */
maxIter = 6;
@@ -193,11 +188,7 @@ opus_int silk_encode_frame_FLP(
/*****************************************/
/* Noise shaping quantization */
/*****************************************/
- silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, x_frame );
-
- if ( iter == maxIter && !found_lower ) {
- silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
- }
+ silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw );
/****************************************/
/* Encode Parameters */
@@ -212,33 +203,6 @@ opus_int silk_encode_frame_FLP(
nBits = ec_tell( psRangeEnc );
- /* If we still bust after the last iteration, do some damage control. */
- if ( iter == maxIter && !found_lower && nBits > maxBits ) {
- silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
-
- /* Keep gains the same as the last frame. */
- psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
- for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
- psEnc->sCmn.indices.GainsIndices[ i ] = 4;
- }
- if (condCoding != CODE_CONDITIONALLY) {
- psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
- }
- psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
- psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
- /* Clear all pulses. */
- for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
- psEnc->sCmn.pulses[ i ] = 0;
- }
-
- silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
-
- silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
- psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
-
- nBits = ec_tell( psRangeEnc );
- }
-
if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
break;
}
@@ -248,7 +212,7 @@ opus_int silk_encode_frame_FLP(
if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
/* Restore output state from earlier iteration that did meet the bitrate budget */
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
- celt_assert( sRangeEnc_copy2.offs <= 1275 );
+ silk_assert( sRangeEnc_copy2.offs <= 1275 );
silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
@@ -259,9 +223,7 @@ opus_int silk_encode_frame_FLP(
if( nBits > maxBits ) {
if( found_lower == 0 && iter >= 2 ) {
/* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
- sEncCtrl.Lambda = silk_max_float(sEncCtrl.Lambda*1.5f, 1.5f);
- /* Reducing dithering can help us hit the target. */
- psEnc->sCmn.indices.quantOffsetType = 0;
+ sEncCtrl.Lambda *= 1.5f;
found_upper = 0;
gainsID_upper = -1;
} else {
@@ -278,7 +240,7 @@ opus_int silk_encode_frame_FLP(
gainsID_lower = gainsID;
/* Copy part of the output state */
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
- celt_assert( psRangeEnc->offs <= 1275 );
+ silk_assert( psRangeEnc->offs <= 1275 );
silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
@@ -288,34 +250,15 @@ opus_int silk_encode_frame_FLP(
break;
}
- if ( !found_lower && nBits > maxBits ) {
- int j;
- for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
- int sum=0;
- for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
- sum += abs( psEnc->sCmn.pulses[j] );
- }
- if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
- best_sum[i] = sum;
- best_gain_mult[i] = gainMult_Q8;
- } else {
- gain_lock[i] = 1;
- }
- }
- }
if( ( found_lower & found_upper ) == 0 ) {
/* Adjust gain according to high-rate rate/distortion curve */
+ opus_int32 gain_factor_Q16;
+ gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
+ gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) );
if( nBits > maxBits ) {
- if (gainMult_Q8 < 16384) {
- gainMult_Q8 *= 2;
- } else {
- gainMult_Q8 = 32767;
- }
- } else {
- opus_int32 gain_factor_Q16;
- gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
- gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
+ gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
}
+ gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
} else {
/* Adjust gain by interpolating */
gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower );
@@ -329,13 +272,7 @@ opus_int silk_encode_frame_FLP(
}
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
- opus_int16 tmp;
- if ( gain_lock[i] ) {
- tmp = best_gain_mult[i];
- } else {
- tmp = gainMult_Q8;
- }
- pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
+ pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 );
}
/* Quantize gains */
diff --git a/thirdparty/opus/silk/float/energy_FLP.c b/thirdparty/opus/silk/float/energy_FLP.c
index 7bc7173c9c..24b8179f9e 100644
--- a/thirdparty/opus/silk/float/energy_FLP.c
+++ b/thirdparty/opus/silk/float/energy_FLP.c
@@ -37,12 +37,13 @@ double silk_energy_FLP(
opus_int dataSize
)
{
- opus_int i;
+ opus_int i, dataSize4;
double result;
/* 4x unrolled loop */
result = 0.0;
- for( i = 0; i < dataSize - 3; i += 4 ) {
+ dataSize4 = dataSize & 0xFFFC;
+ for( i = 0; i < dataSize4; i += 4 ) {
result += data[ i + 0 ] * (double)data[ i + 0 ] +
data[ i + 1 ] * (double)data[ i + 1 ] +
data[ i + 2 ] * (double)data[ i + 2 ] +
diff --git a/thirdparty/opus/silk/float/find_LPC_FLP.c b/thirdparty/opus/silk/float/find_LPC_FLP.c
index fa3ffe7f8b..fcfe1c3681 100644
--- a/thirdparty/opus/silk/float/find_LPC_FLP.c
+++ b/thirdparty/opus/silk/float/find_LPC_FLP.c
@@ -73,7 +73,7 @@ void silk_find_LPC_FLP(
silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
/* Convert to LPC for residual energy evaluation */
- silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
+ silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder );
/* Calculate residual energy with LSF interpolation */
silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, psEncC->predictLPCOrder );
@@ -99,6 +99,6 @@ void silk_find_LPC_FLP(
silk_A2NLSF_FLP( NLSF_Q15, a, psEncC->predictLPCOrder );
}
- celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
+ silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
}
diff --git a/thirdparty/opus/silk/float/find_LTP_FLP.c b/thirdparty/opus/silk/float/find_LTP_FLP.c
index f97064930e..7229996014 100644
--- a/thirdparty/opus/silk/float/find_LTP_FLP.c
+++ b/thirdparty/opus/silk/float/find_LTP_FLP.c
@@ -33,32 +33,100 @@ POSSIBILITY OF SUCH DAMAGE.
#include "tuning_parameters.h"
void silk_find_LTP_FLP(
- silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
- silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* O Weight for LTP quantization */
- const silk_float r_ptr[], /* I LPC residual */
- const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
+ silk_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
+ silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
+ silk_float *LTPredCodGain, /* O LTP coding gain */
+ const silk_float r_lpc[], /* I LPC residual */
+ const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
+ const silk_float Wght[ MAX_NB_SUBFR ], /* I Weights */
const opus_int subfr_length, /* I Subframe length */
- const opus_int nb_subfr /* I number of subframes */
+ const opus_int nb_subfr, /* I number of subframes */
+ const opus_int mem_offset /* I Number of samples in LTP memory */
)
{
- opus_int k;
- silk_float *xX_ptr, *XX_ptr;
- const silk_float *lag_ptr;
- silk_float xx, temp;
+ opus_int i, k;
+ silk_float *b_ptr, temp, *WLTP_ptr;
+ silk_float LPC_res_nrg, LPC_LTP_res_nrg;
+ silk_float d[ MAX_NB_SUBFR ], m, g, delta_b[ LTP_ORDER ];
+ silk_float w[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], regu;
+ silk_float Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ];
+ const silk_float *r_ptr, *lag_ptr;
- xX_ptr = xX;
- XX_ptr = XX;
+ b_ptr = b;
+ WLTP_ptr = WLTP;
+ r_ptr = &r_lpc[ mem_offset ];
for( k = 0; k < nb_subfr; k++ ) {
lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
- silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, XX_ptr );
- silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xX_ptr );
- xx = ( silk_float )silk_energy_FLP( r_ptr, subfr_length + LTP_ORDER );
- temp = 1.0f / silk_max( xx, LTP_CORR_INV_MAX * 0.5f * ( XX_ptr[ 0 ] + XX_ptr[ 24 ] ) + 1.0f );
- silk_scale_vector_FLP( XX_ptr, temp, LTP_ORDER * LTP_ORDER );
- silk_scale_vector_FLP( xX_ptr, temp, LTP_ORDER );
- r_ptr += subfr_length;
- XX_ptr += LTP_ORDER * LTP_ORDER;
- xX_ptr += LTP_ORDER;
+ silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, WLTP_ptr );
+ silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr );
+
+ rr[ k ] = ( silk_float )silk_energy_FLP( r_ptr, subfr_length );
+ regu = 1.0f + rr[ k ] +
+ matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ) +
+ matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER );
+ regu *= LTP_DAMPING / 3;
+ silk_regularize_correlations_FLP( WLTP_ptr, &rr[ k ], regu, LTP_ORDER );
+ silk_solve_LDL_FLP( WLTP_ptr, LTP_ORDER, Rr, b_ptr );
+
+ /* Calculate residual energy */
+ nrg[ k ] = silk_residual_energy_covar_FLP( b_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER );
+
+ temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length );
+ silk_scale_vector_FLP( WLTP_ptr, temp, LTP_ORDER * LTP_ORDER );
+ w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER / 2, LTP_ORDER / 2, LTP_ORDER );
+
+ r_ptr += subfr_length;
+ b_ptr += LTP_ORDER;
+ WLTP_ptr += LTP_ORDER * LTP_ORDER;
+ }
+
+ /* Compute LTP coding gain */
+ if( LTPredCodGain != NULL ) {
+ LPC_LTP_res_nrg = 1e-6f;
+ LPC_res_nrg = 0.0f;
+ for( k = 0; k < nb_subfr; k++ ) {
+ LPC_res_nrg += rr[ k ] * Wght[ k ];
+ LPC_LTP_res_nrg += nrg[ k ] * Wght[ k ];
+ }
+
+ silk_assert( LPC_LTP_res_nrg > 0 );
+ *LTPredCodGain = 3.0f * silk_log2( LPC_res_nrg / LPC_LTP_res_nrg );
+ }
+
+ /* Smoothing */
+ /* d = sum( B, 1 ); */
+ b_ptr = b;
+ for( k = 0; k < nb_subfr; k++ ) {
+ d[ k ] = 0;
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ d[ k ] += b_ptr[ i ];
+ }
+ b_ptr += LTP_ORDER;
+ }
+ /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */
+ temp = 1e-3f;
+ for( k = 0; k < nb_subfr; k++ ) {
+ temp += w[ k ];
+ }
+ m = 0;
+ for( k = 0; k < nb_subfr; k++ ) {
+ m += d[ k ] * w[ k ];
+ }
+ m = m / temp;
+
+ b_ptr = b;
+ for( k = 0; k < nb_subfr; k++ ) {
+ g = LTP_SMOOTHING / ( LTP_SMOOTHING + w[ k ] ) * ( m - d[ k ] );
+ temp = 0;
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ delta_b[ i ] = silk_max_float( b_ptr[ i ], 0.1f );
+ temp += delta_b[ i ];
+ }
+ temp = g / temp;
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ b_ptr[ i ] = b_ptr[ i ] + delta_b[ i ] * temp;
+ }
+ b_ptr += LTP_ORDER;
}
}
diff --git a/thirdparty/opus/silk/float/find_pitch_lags_FLP.c b/thirdparty/opus/silk/float/find_pitch_lags_FLP.c
index dedbcd2836..f3b22d25ce 100644
--- a/thirdparty/opus/silk/float/find_pitch_lags_FLP.c
+++ b/thirdparty/opus/silk/float/find_pitch_lags_FLP.c
@@ -56,7 +56,7 @@ void silk_find_pitch_lags_FLP(
buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
/* Safety check */
- celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
+ silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
x_buf = x - psEnc->sCmn.ltp_mem_length;
diff --git a/thirdparty/opus/silk/float/find_pred_coefs_FLP.c b/thirdparty/opus/silk/float/find_pred_coefs_FLP.c
index dcf7c5202d..1af4fe5f1b 100644
--- a/thirdparty/opus/silk/float/find_pred_coefs_FLP.c
+++ b/thirdparty/opus/silk/float/find_pred_coefs_FLP.c
@@ -41,9 +41,8 @@ void silk_find_pred_coefs_FLP(
)
{
opus_int i;
- silk_float XXLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
- silk_float xXLTP[ MAX_NB_SUBFR * LTP_ORDER ];
- silk_float invGains[ MAX_NB_SUBFR ];
+ silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
+ silk_float invGains[ MAX_NB_SUBFR ], Wght[ MAX_NB_SUBFR ];
opus_int16 NLSF_Q15[ MAX_LPC_ORDER ];
const silk_float *x_ptr;
silk_float *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ];
@@ -53,20 +52,23 @@ void silk_find_pred_coefs_FLP(
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
silk_assert( psEncCtrl->Gains[ i ] > 0.0f );
invGains[ i ] = 1.0f / psEncCtrl->Gains[ i ];
+ Wght[ i ] = invGains[ i ] * invGains[ i ];
}
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
/**********/
/* VOICED */
/**********/
- celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
+ silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
/* LTP analysis */
- silk_find_LTP_FLP( XXLTP, xXLTP, res_pitch, psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr );
+ silk_find_LTP_FLP( psEncCtrl->LTPCoef, WLTP, &psEncCtrl->LTPredCodGain, res_pitch,
+ psEncCtrl->pitchL, Wght, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length );
/* Quantize LTP gain parameters */
silk_quant_LTP_gains_FLP( psEncCtrl->LTPCoef, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
- &psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain, XXLTP, xXLTP, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
+ &psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr,
+ psEnc->sCmn.arch );
/* Control LTP scaling */
silk_LTP_scale_ctrl_FLP( psEnc, psEncCtrl, condCoding );
diff --git a/thirdparty/opus/silk/float/inner_product_FLP.c b/thirdparty/opus/silk/float/inner_product_FLP.c
index cdd39d24ce..029c012911 100644
--- a/thirdparty/opus/silk/float/inner_product_FLP.c
+++ b/thirdparty/opus/silk/float/inner_product_FLP.c
@@ -38,12 +38,13 @@ double silk_inner_product_FLP(
opus_int dataSize
)
{
- opus_int i;
+ opus_int i, dataSize4;
double result;
/* 4x unrolled loop */
result = 0.0;
- for( i = 0; i < dataSize - 3; i += 4 ) {
+ dataSize4 = dataSize & 0xFFFC;
+ for( i = 0; i < dataSize4; i += 4 ) {
result += data1[ i + 0 ] * (double)data2[ i + 0 ] +
data1[ i + 1 ] * (double)data2[ i + 1 ] +
data1[ i + 2 ] * (double)data2[ i + 2 ] +
diff --git a/thirdparty/opus/silk/float/k2a_FLP.c b/thirdparty/opus/silk/float/k2a_FLP.c
index 1448008dbb..12af4e7669 100644
--- a/thirdparty/opus/silk/float/k2a_FLP.c
+++ b/thirdparty/opus/silk/float/k2a_FLP.c
@@ -39,16 +39,15 @@ void silk_k2a_FLP(
)
{
opus_int k, n;
- silk_float rck, tmp1, tmp2;
+ silk_float Atmp[ SILK_MAX_ORDER_LPC ];
for( k = 0; k < order; k++ ) {
- rck = rc[ k ];
- for( n = 0; n < (k + 1) >> 1; n++ ) {
- tmp1 = A[ n ];
- tmp2 = A[ k - n - 1 ];
- A[ n ] = tmp1 + tmp2 * rck;
- A[ k - n - 1 ] = tmp2 + tmp1 * rck;
+ for( n = 0; n < k; n++ ) {
+ Atmp[ n ] = A[ n ];
}
- A[ k ] = -rck;
+ for( n = 0; n < k; n++ ) {
+ A[ n ] += Atmp[ k - n - 1 ] * rc[ k ];
+ }
+ A[ k ] = -rc[ k ];
}
}
diff --git a/thirdparty/opus/silk/float/levinsondurbin_FLP.c b/thirdparty/opus/silk/float/levinsondurbin_FLP.c
new file mode 100644
index 0000000000..f0ba606981
--- /dev/null
+++ b/thirdparty/opus/silk/float/levinsondurbin_FLP.c
@@ -0,0 +1,81 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* Solve the normal equations using the Levinson-Durbin recursion */
+silk_float silk_levinsondurbin_FLP( /* O prediction error energy */
+ silk_float A[], /* O prediction coefficients [order] */
+ const silk_float corr[], /* I input auto-correlations [order + 1] */
+ const opus_int order /* I prediction order */
+)
+{
+ opus_int i, mHalf, m;
+ silk_float min_nrg, nrg, t, km, Atmp1, Atmp2;
+
+ min_nrg = 1e-12f * corr[ 0 ] + 1e-9f;
+ nrg = corr[ 0 ];
+ nrg = silk_max_float(min_nrg, nrg);
+ A[ 0 ] = corr[ 1 ] / nrg;
+ nrg -= A[ 0 ] * corr[ 1 ];
+ nrg = silk_max_float(min_nrg, nrg);
+
+ for( m = 1; m < order; m++ )
+ {
+ t = corr[ m + 1 ];
+ for( i = 0; i < m; i++ ) {
+ t -= A[ i ] * corr[ m - i ];
+ }
+
+ /* reflection coefficient */
+ km = t / nrg;
+
+ /* residual energy */
+ nrg -= km * t;
+ nrg = silk_max_float(min_nrg, nrg);
+
+ mHalf = m >> 1;
+ for( i = 0; i < mHalf; i++ ) {
+ Atmp1 = A[ i ];
+ Atmp2 = A[ m - i - 1 ];
+ A[ m - i - 1 ] -= km * Atmp1;
+ A[ i ] -= km * Atmp2;
+ }
+ if( m & 1 ) {
+ A[ mHalf ] -= km * A[ mHalf ];
+ }
+ A[ m ] = km;
+ }
+
+ /* return the residual energy */
+ return nrg;
+}
+
diff --git a/thirdparty/opus/silk/float/main_FLP.h b/thirdparty/opus/silk/float/main_FLP.h
index 5dc0ccf4a4..e5a75972e5 100644
--- a/thirdparty/opus/silk/float/main_FLP.h
+++ b/thirdparty/opus/silk/float/main_FLP.h
@@ -56,8 +56,7 @@ void silk_HP_variable_cutoff(
/* Encoder main function */
void silk_encode_do_VAD_FLP(
- silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
- opus_int activity /* I Decision of Opus voice activity detector */
+ silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */
);
/* Encoder main function */
@@ -80,11 +79,22 @@ opus_int silk_init_encoder(
opus_int silk_control_encoder(
silk_encoder_state_FLP *psEnc, /* I/O Pointer to Silk encoder state FLP */
silk_EncControlStruct *encControl, /* I Control structure */
+ const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
const opus_int channelNb, /* I Channel number */
const opus_int force_fs_kHz
);
+/****************/
+/* Prefiltering */
+/****************/
+void silk_prefilter_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */
+ silk_float xw[], /* O Weighted signal */
+ const silk_float x[] /* I Speech signal */
+);
+
/**************************/
/* Noise shaping analysis */
/**************************/
@@ -143,12 +153,15 @@ void silk_find_LPC_FLP(
/* LTP analysis */
void silk_find_LTP_FLP(
- silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
- silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* O Weight for LTP quantization */
- const silk_float r_ptr[], /* I LPC residual */
+ silk_float b[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
+ silk_float WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
+ silk_float *LTPredCodGain, /* O LTP coding gain */
+ const silk_float r_lpc[], /* I LPC residual */
const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
+ const silk_float Wght[ MAX_NB_SUBFR ], /* I Weights */
const opus_int subfr_length, /* I Subframe length */
- const opus_int nb_subfr /* I number of subframes */
+ const opus_int nb_subfr, /* I number of subframes */
+ const opus_int mem_offset /* I Number of samples in LTP memory */
);
void silk_LTP_analysis_filter_FLP(
@@ -185,15 +198,14 @@ void silk_LPC_analysis_filter_FLP(
/* LTP tap quantizer */
void silk_quant_LTP_gains_FLP(
- silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
+ silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (Un-)quantized LTP gains */
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */
opus_int8 *periodicity_index, /* O Periodicity index */
opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
- silk_float *pred_gain_dB, /* O LTP prediction gain */
- const silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Correlation matrix */
- const silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* I Correlation vector */
- const opus_int subfr_len, /* I Number of samples per subframe */
- const opus_int nb_subfr, /* I Number of subframes */
+ const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */
+ const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */
+ const opus_int lowComplexity, /* I Flag for low complexity */
+ const opus_int nb_subfr, /* I number of subframes */
int arch /* I Run-time architecture */
);
@@ -233,6 +245,22 @@ void silk_corrVector_FLP(
silk_float *Xt /* O X'*t correlation vector [order] */
);
+/* Add noise to matrix diagonal */
+void silk_regularize_correlations_FLP(
+ silk_float *XX, /* I/O Correlation matrices */
+ silk_float *xx, /* I/O Correlation values */
+ const silk_float noise, /* I Noise energy to add */
+ const opus_int D /* I Dimension of XX */
+);
+
+/* Function to solve linear equation Ax = b, where A is an MxM symmetric matrix */
+void silk_solve_LDL_FLP(
+ silk_float *A, /* I/O Symmetric square matrix, out: reg. */
+ const opus_int M, /* I Size of matrix */
+ const silk_float *b, /* I Pointer to b vector */
+ silk_float *x /* O Pointer to x solution vector */
+);
+
/* Apply sine window to signal vector. */
/* Window types: */
/* 1 -> sine window from 0 to pi/2 */
@@ -257,8 +285,7 @@ void silk_A2NLSF_FLP(
void silk_NLSF2A_FLP(
silk_float *pAR, /* O LPC coefficients [ LPC_order ] */
const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */
- const opus_int LPC_order, /* I LPC order */
- int arch /* I Run-time architecture */
+ const opus_int LPC_order /* I LPC order */
);
/* Limit, stabilize, and quantize NLSFs */
diff --git a/thirdparty/opus/silk/float/noise_shape_analysis_FLP.c b/thirdparty/opus/silk/float/noise_shape_analysis_FLP.c
index cb3d8a50b7..65f6ea5870 100644
--- a/thirdparty/opus/silk/float/noise_shape_analysis_FLP.c
+++ b/thirdparty/opus/silk/float/noise_shape_analysis_FLP.c
@@ -55,21 +55,25 @@ static OPUS_INLINE silk_float warped_gain(
/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */
/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
static OPUS_INLINE void warped_true2monic_coefs(
- silk_float *coefs,
+ silk_float *coefs_syn,
+ silk_float *coefs_ana,
silk_float lambda,
silk_float limit,
opus_int order
) {
opus_int i, iter, ind = 0;
- silk_float tmp, maxabs, chirp, gain;
+ silk_float tmp, maxabs, chirp, gain_syn, gain_ana;
/* Convert to monic coefficients */
for( i = order - 1; i > 0; i-- ) {
- coefs[ i - 1 ] -= lambda * coefs[ i ];
+ coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];
+ coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];
}
- gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
+ gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] );
+ gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] );
for( i = 0; i < order; i++ ) {
- coefs[ i ] *= gain;
+ coefs_syn[ i ] *= gain_syn;
+ coefs_ana[ i ] *= gain_ana;
}
/* Limit */
@@ -77,7 +81,7 @@ static OPUS_INLINE void warped_true2monic_coefs(
/* Find maximum absolute value */
maxabs = -1.0f;
for( i = 0; i < order; i++ ) {
- tmp = silk_abs_float( coefs[ i ] );
+ tmp = silk_max( silk_abs_float( coefs_syn[ i ] ), silk_abs_float( coefs_ana[ i ] ) );
if( tmp > maxabs ) {
maxabs = tmp;
ind = i;
@@ -90,59 +94,36 @@ static OPUS_INLINE void warped_true2monic_coefs(
/* Convert back to true warped coefficients */
for( i = 1; i < order; i++ ) {
- coefs[ i - 1 ] += lambda * coefs[ i ];
+ coefs_syn[ i - 1 ] += lambda * coefs_syn[ i ];
+ coefs_ana[ i - 1 ] += lambda * coefs_ana[ i ];
}
- gain = 1.0f / gain;
+ gain_syn = 1.0f / gain_syn;
+ gain_ana = 1.0f / gain_ana;
for( i = 0; i < order; i++ ) {
- coefs[ i ] *= gain;
+ coefs_syn[ i ] *= gain_syn;
+ coefs_ana[ i ] *= gain_ana;
}
/* Apply bandwidth expansion */
chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
- silk_bwexpander_FLP( coefs, order, chirp );
+ silk_bwexpander_FLP( coefs_syn, order, chirp );
+ silk_bwexpander_FLP( coefs_ana, order, chirp );
/* Convert to monic warped coefficients */
for( i = order - 1; i > 0; i-- ) {
- coefs[ i - 1 ] -= lambda * coefs[ i ];
+ coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];
+ coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];
}
- gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
+ gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] );
+ gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] );
for( i = 0; i < order; i++ ) {
- coefs[ i ] *= gain;
+ coefs_syn[ i ] *= gain_syn;
+ coefs_ana[ i ] *= gain_ana;
}
}
silk_assert( 0 );
}
-static OPUS_INLINE void limit_coefs(
- silk_float *coefs,
- silk_float limit,
- opus_int order
-) {
- opus_int i, iter, ind = 0;
- silk_float tmp, maxabs, chirp;
-
- for( iter = 0; iter < 10; iter++ ) {
- /* Find maximum absolute value */
- maxabs = -1.0f;
- for( i = 0; i < order; i++ ) {
- tmp = silk_abs_float( coefs[ i ] );
- if( tmp > maxabs ) {
- maxabs = tmp;
- ind = i;
- }
- }
- if( maxabs <= limit ) {
- /* Coefficients are within range - done */
- return;
- }
-
- /* Apply bandwidth expansion */
- chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
- silk_bwexpander_FLP( coefs, order, chirp );
- }
- silk_assert( 0 );
-}
-
/* Compute noise shaping coefficients and initial gain values */
void silk_noise_shape_analysis_FLP(
silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
@@ -152,13 +133,12 @@ void silk_noise_shape_analysis_FLP(
)
{
silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
- opus_int k, nSamples, nSegs;
- silk_float SNR_adj_dB, HarmShapeGain, Tilt;
- silk_float nrg, log_energy, log_energy_prev, energy_variation;
- silk_float BWExp, gain_mult, gain_add, strength, b, warping;
+ opus_int k, nSamples;
+ silk_float SNR_adj_dB, HarmBoost, HarmShapeGain, Tilt;
+ silk_float nrg, pre_nrg, log_energy, log_energy_prev, energy_variation;
+ silk_float delta, BWExp1, BWExp2, gain_mult, gain_add, strength, b, warping;
silk_float x_windowed[ SHAPE_LPC_WIN_MAX ];
silk_float auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
- silk_float rc[ MAX_SHAPE_LPC_ORDER + 1 ];
const silk_float *x_ptr, *pitch_res_ptr;
/* Point to start of first LPC analysis block */
@@ -196,14 +176,14 @@ void silk_noise_shape_analysis_FLP(
if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
/* Initially set to 0; may be overruled in process_gains(..) */
psEnc->sCmn.indices.quantOffsetType = 0;
+ psEncCtrl->sparseness = 0.0f;
} else {
/* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
nSamples = 2 * psEnc->sCmn.fs_kHz;
energy_variation = 0.0f;
log_energy_prev = 0.0f;
pitch_res_ptr = pitch_res;
- nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
- for( k = 0; k < nSegs; k++ ) {
+ for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
nrg = ( silk_float )nSamples + ( silk_float )silk_energy_FLP( pitch_res_ptr, nSamples );
log_energy = silk_log2( nrg );
if( k > 0 ) {
@@ -212,13 +192,17 @@ void silk_noise_shape_analysis_FLP(
log_energy_prev = log_energy;
pitch_res_ptr += nSamples;
}
+ psEncCtrl->sparseness = silk_sigmoid( 0.4f * ( energy_variation - 5.0f ) );
/* Set quantization offset depending on sparseness measure */
- if( energy_variation > ENERGY_VARIATION_THRESHOLD_QNT_OFFSET * (nSegs-1) ) {
+ if( psEncCtrl->sparseness > SPARSENESS_THRESHOLD_QNT_OFFSET ) {
psEnc->sCmn.indices.quantOffsetType = 0;
} else {
psEnc->sCmn.indices.quantOffsetType = 1;
}
+
+ /* Increase coding SNR for sparse signals */
+ SNR_adj_dB += SPARSE_SNR_INCR_dB * ( psEncCtrl->sparseness - 0.5f );
}
/*******************************/
@@ -226,10 +210,19 @@ void silk_noise_shape_analysis_FLP(
/*******************************/
/* More BWE for signals with high prediction gain */
strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain; /* between 0.0 and 1.0 */
- BWExp = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
-
- /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
- warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
+ BWExp1 = BWExp2 = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
+ delta = LOW_RATE_BANDWIDTH_EXPANSION_DELTA * ( 1.0f - 0.75f * psEncCtrl->coding_quality );
+ BWExp1 -= delta;
+ BWExp2 += delta;
+ /* BWExp1 will be applied after BWExp2, so make it relative */
+ BWExp1 /= BWExp2;
+
+ if( psEnc->sCmn.warping_Q16 > 0 ) {
+ /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
+ warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
+ } else {
+ warping = 0.0f;
+ }
/********************************************/
/* Compute noise shaping AR coefs and gains */
@@ -259,28 +252,37 @@ void silk_noise_shape_analysis_FLP(
}
/* Add white noise, as a fraction of energy */
- auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION + 1.0f;
+ auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION;
/* Convert correlations to prediction coefficients, and compute residual energy */
- nrg = silk_schur_FLP( rc, auto_corr, psEnc->sCmn.shapingLPCOrder );
- silk_k2a_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], rc, psEnc->sCmn.shapingLPCOrder );
+ nrg = silk_levinsondurbin_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], auto_corr, psEnc->sCmn.shapingLPCOrder );
psEncCtrl->Gains[ k ] = ( silk_float )sqrt( nrg );
if( psEnc->sCmn.warping_Q16 > 0 ) {
/* Adjust gain for warping */
- psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
+ psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
}
/* Bandwidth expansion for synthesis filter shaping */
- silk_bwexpander_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp );
+ silk_bwexpander_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp2 );
- if( psEnc->sCmn.warping_Q16 > 0 ) {
- /* Convert to monic warped prediction coefficients and limit absolute values */
- warped_true2monic_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
- } else {
- /* Limit absolute values */
- limit_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], 3.999f, psEnc->sCmn.shapingLPCOrder );
- }
+ /* Compute noise shaping filter coefficients */
+ silk_memcpy(
+ &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ],
+ &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ],
+ psEnc->sCmn.shapingLPCOrder * sizeof( silk_float ) );
+
+ /* Bandwidth expansion for analysis filter shaping */
+ silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 );
+
+ /* Ratio of prediction gains, in energy domain */
+ pre_nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
+ nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
+ psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg );
+
+ /* Convert to monic warped prediction coefficients and limit absolute values */
+ warped_true2monic_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ],
+ warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
}
/*****************/
@@ -294,6 +296,11 @@ void silk_noise_shape_analysis_FLP(
psEncCtrl->Gains[ k ] += gain_add;
}
+ gain_mult = 1.0f + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT;
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ psEncCtrl->GainsPre[ k ] *= gain_mult;
+ }
+
/************************************************/
/* Control low-frequency shaping and noise tilt */
/************************************************/
@@ -324,6 +331,12 @@ void silk_noise_shape_analysis_FLP(
/****************************/
/* HARMONIC SHAPING CONTROL */
/****************************/
+ /* Control boosting of harmonic frequencies */
+ HarmBoost = LOW_RATE_HARMONIC_BOOST * ( 1.0f - psEncCtrl->coding_quality ) * psEnc->LTPCorr;
+
+ /* More harmonic boost for noisy input signals */
+ HarmBoost += LOW_INPUT_QUALITY_HARMONIC_BOOST * ( 1.0f - psEncCtrl->input_quality );
+
if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
/* Harmonic noise shaping */
HarmShapeGain = HARMONIC_SHAPING;
@@ -342,6 +355,8 @@ void silk_noise_shape_analysis_FLP(
/* Smooth over subframes */
/*************************/
for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ psShapeSt->HarmBoost_smth += SUBFR_SMTH_COEF * ( HarmBoost - psShapeSt->HarmBoost_smth );
+ psEncCtrl->HarmBoost[ k ] = psShapeSt->HarmBoost_smth;
psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth );
psEncCtrl->HarmShapeGain[ k ] = psShapeSt->HarmShapeGain_smth;
psShapeSt->Tilt_smth += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth );
diff --git a/thirdparty/opus/silk/float/pitch_analysis_core_FLP.c b/thirdparty/opus/silk/float/pitch_analysis_core_FLP.c
index f351bc3718..d0e637a29d 100644
--- a/thirdparty/opus/silk/float/pitch_analysis_core_FLP.c
+++ b/thirdparty/opus/silk/float/pitch_analysis_core_FLP.c
@@ -109,11 +109,11 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
const opus_int8 *Lag_CB_ptr;
/* Check for valid sampling frequency */
- celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
+ silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
/* Check for valid complexity setting */
- celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
- celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f );
silk_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f );
@@ -148,7 +148,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
silk_resampler_down2_3( filt_state, frame_8_FIX, frame_12_FIX, frame_length );
silk_short2float_array( frame_8kHz, frame_8_FIX, frame_length_8kHz );
} else {
- celt_assert( Fs_kHz == 8 );
+ silk_assert( Fs_kHz == 8 );
silk_float2short_array( frame_8_FIX, frame, frame_length_8kHz );
}
@@ -159,7 +159,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
/* Low-pass filter */
for( i = frame_length_4kHz - 1; i > 0; i-- ) {
- frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
+ frame_4kHz[ i ] += frame_4kHz[ i - 1 ];
}
/******************************************************************************
@@ -169,14 +169,14 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
target_ptr = &frame_4kHz[ silk_LSHIFT( sf_length_4kHz, 2 ) ];
for( k = 0; k < nb_subfr >> 1; k++ ) {
/* Check that we are within range of the array */
- celt_assert( target_ptr >= frame_4kHz );
- celt_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+ silk_assert( target_ptr >= frame_4kHz );
+ silk_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
basis_ptr = target_ptr - min_lag_4kHz;
/* Check that we are within range of the array */
- celt_assert( basis_ptr >= frame_4kHz );
- celt_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+ silk_assert( basis_ptr >= frame_4kHz );
+ silk_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
celt_pitch_xcorr( target_ptr, target_ptr-max_lag_4kHz, xcorr, sf_length_8kHz, max_lag_4kHz - min_lag_4kHz + 1, arch );
@@ -215,7 +215,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
/* Sort */
length_d_srch = 4 + 2 * complexity;
- celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
+ silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
silk_insertion_sort_decreasing_FLP( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch );
/* Escape if correlation is very low already here */
@@ -238,7 +238,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
break;
}
}
- celt_assert( length_d_srch > 0 );
+ silk_assert( length_d_srch > 0 );
for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) {
d_comp[ i ] = 0;
@@ -471,7 +471,7 @@ opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced,
*lagIndex = (opus_int16)( lag - min_lag_8kHz );
*contourIndex = (opus_int8)CBimax;
}
- celt_assert( *lagIndex >= 0 );
+ silk_assert( *lagIndex >= 0 );
/* return as voiced */
return 0;
}
@@ -506,8 +506,8 @@ static void silk_P_Ana_calc_corr_st3(
opus_val32 xcorr[ SCRATCH_SIZE ];
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
- celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
- celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
@@ -515,7 +515,7 @@ static void silk_P_Ana_calc_corr_st3(
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
@@ -572,8 +572,8 @@ static void silk_P_Ana_calc_energy_st3(
silk_float scratch_mem[ SCRATCH_SIZE ];
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
- celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
- celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
@@ -581,7 +581,7 @@ static void silk_P_Ana_calc_energy_st3(
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
diff --git a/thirdparty/opus/silk/float/prefilter_FLP.c b/thirdparty/opus/silk/float/prefilter_FLP.c
new file mode 100644
index 0000000000..8bc32fb410
--- /dev/null
+++ b/thirdparty/opus/silk/float/prefilter_FLP.c
@@ -0,0 +1,206 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+/*
+* Prefilter for finding Quantizer input signal
+*/
+static OPUS_INLINE void silk_prefilt_FLP(
+ silk_prefilter_state_FLP *P, /* I/O state */
+ silk_float st_res[], /* I */
+ silk_float xw[], /* O */
+ silk_float *HarmShapeFIR, /* I */
+ silk_float Tilt, /* I */
+ silk_float LF_MA_shp, /* I */
+ silk_float LF_AR_shp, /* I */
+ opus_int lag, /* I */
+ opus_int length /* I */
+);
+
+static void silk_warped_LPC_analysis_filter_FLP(
+ silk_float state[], /* I/O State [order + 1] */
+ silk_float res[], /* O Residual signal [length] */
+ const silk_float coef[], /* I Coefficients [order] */
+ const silk_float input[], /* I Input signal [length] */
+ const silk_float lambda, /* I Warping factor */
+ const opus_int length, /* I Length of input signal */
+ const opus_int order /* I Filter order (even) */
+)
+{
+ opus_int n, i;
+ silk_float acc, tmp1, tmp2;
+
+ /* Order must be even */
+ silk_assert( ( order & 1 ) == 0 );
+
+ for( n = 0; n < length; n++ ) {
+ /* Output of lowpass section */
+ tmp2 = state[ 0 ] + lambda * state[ 1 ];
+ state[ 0 ] = input[ n ];
+ /* Output of allpass section */
+ tmp1 = state[ 1 ] + lambda * ( state[ 2 ] - tmp2 );
+ state[ 1 ] = tmp2;
+ acc = coef[ 0 ] * tmp2;
+ /* Loop over allpass sections */
+ for( i = 2; i < order; i += 2 ) {
+ /* Output of allpass section */
+ tmp2 = state[ i ] + lambda * ( state[ i + 1 ] - tmp1 );
+ state[ i ] = tmp1;
+ acc += coef[ i - 1 ] * tmp1;
+ /* Output of allpass section */
+ tmp1 = state[ i + 1 ] + lambda * ( state[ i + 2 ] - tmp2 );
+ state[ i + 1 ] = tmp2;
+ acc += coef[ i ] * tmp2;
+ }
+ state[ order ] = tmp1;
+ acc += coef[ order - 1 ] * tmp1;
+ res[ n ] = input[ n ] - acc;
+ }
+}
+
+/*
+* silk_prefilter. Main prefilter function
+*/
+void silk_prefilter_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ const silk_encoder_control_FLP *psEncCtrl, /* I Encoder control FLP */
+ silk_float xw[], /* O Weighted signal */
+ const silk_float x[] /* I Speech signal */
+)
+{
+ silk_prefilter_state_FLP *P = &psEnc->sPrefilt;
+ opus_int j, k, lag;
+ silk_float HarmShapeGain, Tilt, LF_MA_shp, LF_AR_shp;
+ silk_float B[ 2 ];
+ const silk_float *AR1_shp;
+ const silk_float *px;
+ silk_float *pxw;
+ silk_float HarmShapeFIR[ 3 ];
+ silk_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ];
+
+ /* Set up pointers */
+ px = x;
+ pxw = xw;
+ lag = P->lagPrev;
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ /* Update Variables that change per sub frame */
+ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+ lag = psEncCtrl->pitchL[ k ];
+ }
+
+ /* Noise shape parameters */
+ HarmShapeGain = psEncCtrl->HarmShapeGain[ k ] * ( 1.0f - psEncCtrl->HarmBoost[ k ] );
+ HarmShapeFIR[ 0 ] = 0.25f * HarmShapeGain;
+ HarmShapeFIR[ 1 ] = 32767.0f / 65536.0f * HarmShapeGain;
+ HarmShapeFIR[ 2 ] = 0.25f * HarmShapeGain;
+ Tilt = psEncCtrl->Tilt[ k ];
+ LF_MA_shp = psEncCtrl->LF_MA_shp[ k ];
+ LF_AR_shp = psEncCtrl->LF_AR_shp[ k ];
+ AR1_shp = &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ];
+
+ /* Short term FIR filtering */
+ silk_warped_LPC_analysis_filter_FLP( P->sAR_shp, st_res, AR1_shp, px,
+ (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder );
+
+ /* Reduce (mainly) low frequencies during harmonic emphasis */
+ B[ 0 ] = psEncCtrl->GainsPre[ k ];
+ B[ 1 ] = -psEncCtrl->GainsPre[ k ] *
+ ( psEncCtrl->HarmBoost[ k ] * HarmShapeGain + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT );
+ pxw[ 0 ] = B[ 0 ] * st_res[ 0 ] + B[ 1 ] * P->sHarmHP;
+ for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) {
+ pxw[ j ] = B[ 0 ] * st_res[ j ] + B[ 1 ] * st_res[ j - 1 ];
+ }
+ P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ];
+
+ silk_prefilt_FLP( P, pxw, pxw, HarmShapeFIR, Tilt, LF_MA_shp, LF_AR_shp, lag, psEnc->sCmn.subfr_length );
+
+ px += psEnc->sCmn.subfr_length;
+ pxw += psEnc->sCmn.subfr_length;
+ }
+ P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
+}
+
+/*
+* Prefilter for finding Quantizer input signal
+*/
+static OPUS_INLINE void silk_prefilt_FLP(
+ silk_prefilter_state_FLP *P, /* I/O state */
+ silk_float st_res[], /* I */
+ silk_float xw[], /* O */
+ silk_float *HarmShapeFIR, /* I */
+ silk_float Tilt, /* I */
+ silk_float LF_MA_shp, /* I */
+ silk_float LF_AR_shp, /* I */
+ opus_int lag, /* I */
+ opus_int length /* I */
+)
+{
+ opus_int i;
+ opus_int idx, LTP_shp_buf_idx;
+ silk_float n_Tilt, n_LF, n_LTP;
+ silk_float sLF_AR_shp, sLF_MA_shp;
+ silk_float *LTP_shp_buf;
+
+ /* To speed up use temp variables instead of using the struct */
+ LTP_shp_buf = P->sLTP_shp;
+ LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
+ sLF_AR_shp = P->sLF_AR_shp;
+ sLF_MA_shp = P->sLF_MA_shp;
+
+ for( i = 0; i < length; i++ ) {
+ if( lag > 0 ) {
+ silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
+ idx = lag + LTP_shp_buf_idx;
+ n_LTP = LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ] * HarmShapeFIR[ 0 ];
+ n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ] * HarmShapeFIR[ 1 ];
+ n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ] * HarmShapeFIR[ 2 ];
+ } else {
+ n_LTP = 0;
+ }
+
+ n_Tilt = sLF_AR_shp * Tilt;
+ n_LF = sLF_AR_shp * LF_AR_shp + sLF_MA_shp * LF_MA_shp;
+
+ sLF_AR_shp = st_res[ i ] - n_Tilt;
+ sLF_MA_shp = sLF_AR_shp - n_LF;
+
+ LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
+ LTP_shp_buf[ LTP_shp_buf_idx ] = sLF_MA_shp;
+
+ xw[ i ] = sLF_MA_shp - n_LTP;
+ }
+ /* Copy temp variable back to state */
+ P->sLF_AR_shp = sLF_AR_shp;
+ P->sLF_MA_shp = sLF_MA_shp;
+ P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
+}
diff --git a/thirdparty/opus/silk/float/residual_energy_FLP.c b/thirdparty/opus/silk/float/residual_energy_FLP.c
index 1bd07b33a4..b2e03a86a4 100644
--- a/thirdparty/opus/silk/float/residual_energy_FLP.c
+++ b/thirdparty/opus/silk/float/residual_energy_FLP.c
@@ -47,7 +47,7 @@ silk_float silk_residual_energy_covar_FLP( /* O
silk_float tmp, nrg = 0.0f, regularization;
/* Safety checks */
- celt_assert( D >= 0 );
+ silk_assert( D >= 0 );
regularization = REGULARIZATION_FACTOR * ( wXX[ 0 ] + wXX[ D * D - 1 ] );
for( k = 0; k < MAX_ITERATIONS_RESIDUAL_NRG; k++ ) {
diff --git a/thirdparty/opus/silk/float/schur_FLP.c b/thirdparty/opus/silk/float/schur_FLP.c
index 8526c748d3..ee436f8351 100644
--- a/thirdparty/opus/silk/float/schur_FLP.c
+++ b/thirdparty/opus/silk/float/schur_FLP.c
@@ -38,23 +38,22 @@ silk_float silk_schur_FLP( /* O returns residual energy
)
{
opus_int k, n;
- double C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
- double Ctmp1, Ctmp2, rc_tmp;
+ silk_float C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
+ silk_float Ctmp1, Ctmp2, rc_tmp;
- celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
+ silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
/* Copy correlations */
- k = 0;
- do {
+ for( k = 0; k < order+1; k++ ) {
C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ];
- } while( ++k <= order );
+ }
for( k = 0; k < order; k++ ) {
/* Get reflection coefficient */
rc_tmp = -C[ k + 1 ][ 0 ] / silk_max_float( C[ 0 ][ 1 ], 1e-9f );
/* Save the output */
- refl_coef[ k ] = (silk_float)rc_tmp;
+ refl_coef[ k ] = rc_tmp;
/* Update correlations */
for( n = 0; n < order - k; n++ ) {
@@ -66,5 +65,6 @@ silk_float silk_schur_FLP( /* O returns residual energy
}
/* Return residual energy */
- return (silk_float)C[ 0 ][ 1 ];
+ return C[ 0 ][ 1 ];
}
+
diff --git a/thirdparty/opus/silk/float/solve_LS_FLP.c b/thirdparty/opus/silk/float/solve_LS_FLP.c
new file mode 100644
index 0000000000..7c90d665a0
--- /dev/null
+++ b/thirdparty/opus/silk/float/solve_LS_FLP.c
@@ -0,0 +1,207 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+/**********************************************************************
+ * LDL Factorisation. Finds the upper triangular matrix L and the diagonal
+ * Matrix D (only the diagonal elements returned in a vector)such that
+ * the symmetric matric A is given by A = L*D*L'.
+ **********************************************************************/
+static OPUS_INLINE void silk_LDL_FLP(
+ silk_float *A, /* I/O Pointer to Symetric Square Matrix */
+ opus_int M, /* I Size of Matrix */
+ silk_float *L, /* I/O Pointer to Square Upper triangular Matrix */
+ silk_float *Dinv /* I/O Pointer to vector holding the inverse diagonal elements of D */
+);
+
+/**********************************************************************
+ * Function to solve linear equation Ax = b, when A is a MxM lower
+ * triangular matrix, with ones on the diagonal.
+ **********************************************************************/
+static OPUS_INLINE void silk_SolveWithLowerTriangularWdiagOnes_FLP(
+ const silk_float *L, /* I Pointer to Lower Triangular Matrix */
+ opus_int M, /* I Dim of Matrix equation */
+ const silk_float *b, /* I b Vector */
+ silk_float *x /* O x Vector */
+);
+
+/**********************************************************************
+ * Function to solve linear equation (A^T)x = b, when A is a MxM lower
+ * triangular, with ones on the diagonal. (ie then A^T is upper triangular)
+ **********************************************************************/
+static OPUS_INLINE void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP(
+ const silk_float *L, /* I Pointer to Lower Triangular Matrix */
+ opus_int M, /* I Dim of Matrix equation */
+ const silk_float *b, /* I b Vector */
+ silk_float *x /* O x Vector */
+);
+
+/**********************************************************************
+ * Function to solve linear equation Ax = b, when A is a MxM
+ * symmetric square matrix - using LDL factorisation
+ **********************************************************************/
+void silk_solve_LDL_FLP(
+ silk_float *A, /* I/O Symmetric square matrix, out: reg. */
+ const opus_int M, /* I Size of matrix */
+ const silk_float *b, /* I Pointer to b vector */
+ silk_float *x /* O Pointer to x solution vector */
+)
+{
+ opus_int i;
+ silk_float L[ MAX_MATRIX_SIZE ][ MAX_MATRIX_SIZE ];
+ silk_float T[ MAX_MATRIX_SIZE ];
+ silk_float Dinv[ MAX_MATRIX_SIZE ]; /* inverse diagonal elements of D*/
+
+ silk_assert( M <= MAX_MATRIX_SIZE );
+
+ /***************************************************
+ Factorize A by LDL such that A = L*D*(L^T),
+ where L is lower triangular with ones on diagonal
+ ****************************************************/
+ silk_LDL_FLP( A, M, &L[ 0 ][ 0 ], Dinv );
+
+ /****************************************************
+ * substitute D*(L^T) = T. ie:
+ L*D*(L^T)*x = b => L*T = b <=> T = inv(L)*b
+ ******************************************************/
+ silk_SolveWithLowerTriangularWdiagOnes_FLP( &L[ 0 ][ 0 ], M, b, T );
+
+ /****************************************************
+ D*(L^T)*x = T <=> (L^T)*x = inv(D)*T, because D is
+ diagonal just multiply with 1/d_i
+ ****************************************************/
+ for( i = 0; i < M; i++ ) {
+ T[ i ] = T[ i ] * Dinv[ i ];
+ }
+ /****************************************************
+ x = inv(L') * inv(D) * T
+ *****************************************************/
+ silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( &L[ 0 ][ 0 ], M, T, x );
+}
+
+static OPUS_INLINE void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP(
+ const silk_float *L, /* I Pointer to Lower Triangular Matrix */
+ opus_int M, /* I Dim of Matrix equation */
+ const silk_float *b, /* I b Vector */
+ silk_float *x /* O x Vector */
+)
+{
+ opus_int i, j;
+ silk_float temp;
+ const silk_float *ptr1;
+
+ for( i = M - 1; i >= 0; i-- ) {
+ ptr1 = matrix_adr( L, 0, i, M );
+ temp = 0;
+ for( j = M - 1; j > i ; j-- ) {
+ temp += ptr1[ j * M ] * x[ j ];
+ }
+ temp = b[ i ] - temp;
+ x[ i ] = temp;
+ }
+}
+
+static OPUS_INLINE void silk_SolveWithLowerTriangularWdiagOnes_FLP(
+ const silk_float *L, /* I Pointer to Lower Triangular Matrix */
+ opus_int M, /* I Dim of Matrix equation */
+ const silk_float *b, /* I b Vector */
+ silk_float *x /* O x Vector */
+)
+{
+ opus_int i, j;
+ silk_float temp;
+ const silk_float *ptr1;
+
+ for( i = 0; i < M; i++ ) {
+ ptr1 = matrix_adr( L, i, 0, M );
+ temp = 0;
+ for( j = 0; j < i; j++ ) {
+ temp += ptr1[ j ] * x[ j ];
+ }
+ temp = b[ i ] - temp;
+ x[ i ] = temp;
+ }
+}
+
+static OPUS_INLINE void silk_LDL_FLP(
+ silk_float *A, /* I/O Pointer to Symetric Square Matrix */
+ opus_int M, /* I Size of Matrix */
+ silk_float *L, /* I/O Pointer to Square Upper triangular Matrix */
+ silk_float *Dinv /* I/O Pointer to vector holding the inverse diagonal elements of D */
+)
+{
+ opus_int i, j, k, loop_count, err = 1;
+ silk_float *ptr1, *ptr2;
+ double temp, diag_min_value;
+ silk_float v[ MAX_MATRIX_SIZE ], D[ MAX_MATRIX_SIZE ]; /* temp arrays*/
+
+ silk_assert( M <= MAX_MATRIX_SIZE );
+
+ diag_min_value = FIND_LTP_COND_FAC * 0.5f * ( A[ 0 ] + A[ M * M - 1 ] );
+ for( loop_count = 0; loop_count < M && err == 1; loop_count++ ) {
+ err = 0;
+ for( j = 0; j < M; j++ ) {
+ ptr1 = matrix_adr( L, j, 0, M );
+ temp = matrix_ptr( A, j, j, M ); /* element in row j column j*/
+ for( i = 0; i < j; i++ ) {
+ v[ i ] = ptr1[ i ] * D[ i ];
+ temp -= ptr1[ i ] * v[ i ];
+ }
+ if( temp < diag_min_value ) {
+ /* Badly conditioned matrix: add white noise and run again */
+ temp = ( loop_count + 1 ) * diag_min_value - temp;
+ for( i = 0; i < M; i++ ) {
+ matrix_ptr( A, i, i, M ) += ( silk_float )temp;
+ }
+ err = 1;
+ break;
+ }
+ D[ j ] = ( silk_float )temp;
+ Dinv[ j ] = ( silk_float )( 1.0f / temp );
+ matrix_ptr( L, j, j, M ) = 1.0f;
+
+ ptr1 = matrix_adr( A, j, 0, M );
+ ptr2 = matrix_adr( L, j + 1, 0, M);
+ for( i = j + 1; i < M; i++ ) {
+ temp = 0.0;
+ for( k = 0; k < j; k++ ) {
+ temp += ptr2[ k ] * v[ k ];
+ }
+ matrix_ptr( L, i, j, M ) = ( silk_float )( ( ptr1[ i ] - temp ) * Dinv[ j ] );
+ ptr2 += M; /* go to next column*/
+ }
+ }
+ }
+ silk_assert( err == 0 );
+}
+
diff --git a/thirdparty/opus/silk/float/sort_FLP.c b/thirdparty/opus/silk/float/sort_FLP.c
index 0e18f31950..f08d7592c5 100644
--- a/thirdparty/opus/silk/float/sort_FLP.c
+++ b/thirdparty/opus/silk/float/sort_FLP.c
@@ -47,9 +47,9 @@ void silk_insertion_sort_decreasing_FLP(
opus_int i, j;
/* Safety checks */
- celt_assert( K > 0 );
- celt_assert( L > 0 );
- celt_assert( L >= K );
+ silk_assert( K > 0 );
+ silk_assert( L > 0 );
+ silk_assert( L >= K );
/* Write start indices in index vector */
for( i = 0; i < K; i++ ) {
diff --git a/thirdparty/opus/silk/float/structs_FLP.h b/thirdparty/opus/silk/float/structs_FLP.h
index 3150b386e4..14d647ced2 100644
--- a/thirdparty/opus/silk/float/structs_FLP.h
+++ b/thirdparty/opus/silk/float/structs_FLP.h
@@ -42,16 +42,32 @@ extern "C"
/********************************/
typedef struct {
opus_int8 LastGainIndex;
+ silk_float HarmBoost_smth;
silk_float HarmShapeGain_smth;
silk_float Tilt_smth;
} silk_shape_state_FLP;
/********************************/
+/* Prefilter state */
+/********************************/
+typedef struct {
+ silk_float sLTP_shp[ LTP_BUF_LENGTH ];
+ silk_float sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ];
+ opus_int sLTP_shp_buf_idx;
+ silk_float sLF_AR_shp;
+ silk_float sLF_MA_shp;
+ silk_float sHarmHP;
+ opus_int32 rand_seed;
+ opus_int lagPrev;
+} silk_prefilter_state_FLP;
+
+/********************************/
/* Encoder state FLP */
/********************************/
typedef struct {
silk_encoder_state sCmn; /* Common struct, shared with fixed-point code */
silk_shape_state_FLP sShape; /* Noise shaping state */
+ silk_prefilter_state_FLP sPrefilt; /* Prefilter State */
/* Buffer for find pitch and noise shape analysis */
silk_float x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
@@ -70,9 +86,12 @@ typedef struct {
opus_int pitchL[ MAX_NB_SUBFR ];
/* Noise shaping parameters */
- silk_float AR[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ silk_float AR1[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ silk_float AR2[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
silk_float LF_MA_shp[ MAX_NB_SUBFR ];
silk_float LF_AR_shp[ MAX_NB_SUBFR ];
+ silk_float GainsPre[ MAX_NB_SUBFR ];
+ silk_float HarmBoost[ MAX_NB_SUBFR ];
silk_float Tilt[ MAX_NB_SUBFR ];
silk_float HarmShapeGain[ MAX_NB_SUBFR ];
silk_float Lambda;
@@ -80,6 +99,7 @@ typedef struct {
silk_float coding_quality;
/* Measures */
+ silk_float sparseness;
silk_float predGain;
silk_float LTPredCodGain;
silk_float ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
diff --git a/thirdparty/opus/silk/float/warped_autocorrelation_FLP.c b/thirdparty/opus/silk/float/warped_autocorrelation_FLP.c
index 09186e73d4..542414f48e 100644
--- a/thirdparty/opus/silk/float/warped_autocorrelation_FLP.c
+++ b/thirdparty/opus/silk/float/warped_autocorrelation_FLP.c
@@ -42,11 +42,11 @@ void silk_warped_autocorrelation_FLP(
{
opus_int n, i;
double tmp1, tmp2;
- double state[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
- double C[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+ double state[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+ double C[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
/* Order must be even */
- celt_assert( ( order & 1 ) == 0 );
+ silk_assert( ( order & 1 ) == 0 );
/* Loop over samples */
for( n = 0; n < length; n++ ) {
diff --git a/thirdparty/opus/silk/float/wrappers_FLP.c b/thirdparty/opus/silk/float/wrappers_FLP.c
index ad90b874a4..6666b8efaa 100644
--- a/thirdparty/opus/silk/float/wrappers_FLP.c
+++ b/thirdparty/opus/silk/float/wrappers_FLP.c
@@ -54,14 +54,13 @@ void silk_A2NLSF_FLP(
void silk_NLSF2A_FLP(
silk_float *pAR, /* O LPC coefficients [ LPC_order ] */
const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */
- const opus_int LPC_order, /* I LPC order */
- int arch /* I Run-time architecture */
+ const opus_int LPC_order /* I LPC order */
)
{
opus_int i;
opus_int16 a_fix_Q12[ MAX_LPC_ORDER ];
- silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order, arch );
+ silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order );
for( i = 0; i < LPC_order; i++ ) {
pAR[ i ] = ( silk_float )a_fix_Q12[ i ] * ( 1.0f / 4096.0f );
@@ -103,14 +102,14 @@ void silk_NSQ_wrapper_FLP(
)
{
opus_int i, j;
- opus_int16 x16[ MAX_FRAME_LENGTH ];
+ opus_int32 x_Q3[ MAX_FRAME_LENGTH ];
opus_int32 Gains_Q16[ MAX_NB_SUBFR ];
silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
opus_int LTP_scale_Q14;
/* Noise shaping parameters */
- opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */
opus_int Lambda_Q10;
opus_int Tilt_Q14[ MAX_NB_SUBFR ];
@@ -120,7 +119,7 @@ void silk_NSQ_wrapper_FLP(
/* Noise shape parameters */
for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
for( j = 0; j < psEnc->sCmn.shapingLPCOrder; j++ ) {
- AR_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = silk_float2int( psEncCtrl->AR[ i * MAX_SHAPE_LPC_ORDER + j ] * 8192.0f );
+ AR2_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = silk_float2int( psEncCtrl->AR2[ i * MAX_SHAPE_LPC_ORDER + j ] * 8192.0f );
}
}
@@ -156,16 +155,16 @@ void silk_NSQ_wrapper_FLP(
/* Convert input to fix */
for( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
- x16[ i ] = silk_float2int( x[ i ] );
+ x_Q3[ i ] = silk_float2int( 8.0f * x[ i ] );
}
/* Call NSQ */
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
- silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
- AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
+ silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+ AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
} else {
- silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
- AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
+ silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+ AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
}
}
@@ -173,35 +172,31 @@ void silk_NSQ_wrapper_FLP(
/* Floating-point Silk LTP quantiation wrapper */
/***********************************************/
void silk_quant_LTP_gains_FLP(
- silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
+ silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (Un-)quantized LTP gains */
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */
opus_int8 *periodicity_index, /* O Periodicity index */
opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
- silk_float *pred_gain_dB, /* O LTP prediction gain */
- const silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Correlation matrix */
- const silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* I Correlation vector */
- const opus_int subfr_len, /* I Number of samples per subframe */
- const opus_int nb_subfr, /* I Number of subframes */
+ const silk_float W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Error weights */
+ const opus_int mu_Q10, /* I Mu value (R/D tradeoff) */
+ const opus_int lowComplexity, /* I Flag for low complexity */
+ const opus_int nb_subfr, /* I number of subframes */
int arch /* I Run-time architecture */
)
{
- opus_int i, pred_gain_dB_Q7;
+ opus_int i;
opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ];
- opus_int32 XX_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
- opus_int32 xX_Q17[ MAX_NB_SUBFR * LTP_ORDER ];
+ opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ];
- for( i = 0; i < nb_subfr * LTP_ORDER * LTP_ORDER; i++ ) {
- XX_Q17[ i ] = (opus_int32)silk_float2int( XX[ i ] * 131072.0f );
- }
for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) {
- xX_Q17[ i ] = (opus_int32)silk_float2int( xX[ i ] * 131072.0f );
+ B_Q14[ i ] = (opus_int16)silk_float2int( B[ i ] * 16384.0f );
+ }
+ for( i = 0; i < nb_subfr * LTP_ORDER * LTP_ORDER; i++ ) {
+ W_Q18[ i ] = (opus_int32)silk_float2int( W[ i ] * 262144.0f );
}
- silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, &pred_gain_dB_Q7, XX_Q17, xX_Q17, subfr_len, nb_subfr, arch );
+ silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, W_Q18, mu_Q10, lowComplexity, nb_subfr, arch );
for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) {
B[ i ] = (silk_float)B_Q14[ i ] * ( 1.0f / 16384.0f );
}
-
- *pred_gain_dB = (silk_float)pred_gain_dB_Q7 * ( 1.0f / 128.0f );
}
diff --git a/thirdparty/opus/silk/gain_quant.c b/thirdparty/opus/silk/gain_quant.c
index ee65245aa3..64ccd0611b 100644
--- a/thirdparty/opus/silk/gain_quant.c
+++ b/thirdparty/opus/silk/gain_quant.c
@@ -76,7 +76,6 @@ void silk_gains_quant(
/* Accumulate deltas */
if( ind[ k ] > double_step_size_threshold ) {
*prev_ind += silk_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold;
- *prev_ind = silk_min_int( *prev_ind, N_LEVELS_QGAIN - 1 );
} else {
*prev_ind += ind[ k ];
}
diff --git a/thirdparty/opus/silk/init_decoder.c b/thirdparty/opus/silk/init_decoder.c
index 16c03dcd1c..f887c67886 100644
--- a/thirdparty/opus/silk/init_decoder.c
+++ b/thirdparty/opus/silk/init_decoder.c
@@ -44,7 +44,6 @@ opus_int silk_init_decoder(
/* Used to deactivate LSF interpolation */
psDec->first_frame_after_reset = 1;
psDec->prev_gain_Q16 = 65536;
- psDec->arch = opus_select_arch();
/* Reset CNG state */
silk_CNG_Reset( psDec );
diff --git a/thirdparty/opus/silk/interpolate.c b/thirdparty/opus/silk/interpolate.c
index 833c28ef8e..1bd8ca4d53 100644
--- a/thirdparty/opus/silk/interpolate.c
+++ b/thirdparty/opus/silk/interpolate.c
@@ -42,8 +42,8 @@ void silk_interpolate(
{
opus_int i;
- celt_assert( ifact_Q2 >= 0 );
- celt_assert( ifact_Q2 <= 4 );
+ silk_assert( ifact_Q2 >= 0 );
+ silk_assert( ifact_Q2 <= 4 );
for( i = 0; i < d; i++ ) {
xi[ i ] = (opus_int16)silk_ADD_RSHIFT( x0[ i ], silk_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 );
diff --git a/thirdparty/opus/silk/lin2log.c b/thirdparty/opus/silk/lin2log.c
index 0d5155aa86..d4fe515321 100644
--- a/thirdparty/opus/silk/lin2log.c
+++ b/thirdparty/opus/silk/lin2log.c
@@ -41,6 +41,6 @@ opus_int32 silk_lin2log(
silk_CLZ_FRAC( inLin, &lz, &frac_Q7 );
/* Piece-wise parabolic approximation */
- return silk_ADD_LSHIFT32( silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 ), 31 - lz, 7 );
+ return silk_LSHIFT( 31 - lz, 7 ) + silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 );
}
diff --git a/thirdparty/opus/silk/macros.h b/thirdparty/opus/silk/macros.h
index 3c67b6e5d9..d3ca347520 100644
--- a/thirdparty/opus/silk/macros.h
+++ b/thirdparty/opus/silk/macros.h
@@ -36,6 +36,14 @@ POSSIBILITY OF SUCH DAMAGE.
#include "opus_defines.h"
#include "arch.h"
+#if OPUS_GNUC_PREREQ(3, 0)
+#define opus_likely(x) (__builtin_expect(!!(x), 1))
+#define opus_unlikely(x) (__builtin_expect(!!(x), 0))
+#else
+#define opus_likely(x) (!!(x))
+#define opus_unlikely(x) (!!(x))
+#endif
+
/* This is an OPUS_INLINE header file for general platform. */
/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
diff --git a/thirdparty/opus/silk/main.h b/thirdparty/opus/silk/main.h
index 1a33eed549..2f90d68f7d 100644
--- a/thirdparty/opus/silk/main.h
+++ b/thirdparty/opus/silk/main.h
@@ -42,10 +42,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "x86/main_sse.h"
#endif
-#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
-#include "arm/NSQ_del_dec_arm.h"
-#endif
-
/* Convert Left/Right stereo signal to adaptive Mid/Side representation */
void silk_stereo_LR_to_MS(
stereo_enc_state *state, /* I/O State */
@@ -113,22 +109,22 @@ void silk_stereo_decode_mid_only(
/* Encodes signs of excitation */
void silk_encode_signs(
- ec_enc *psRangeEnc, /* I/O Compressor data structure */
- const opus_int8 pulses[], /* I pulse signal */
- opus_int length, /* I length of input */
- const opus_int signalType, /* I Signal type */
- const opus_int quantOffsetType, /* I Quantization offset type */
- const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
+ ec_enc *psRangeEnc, /* I/O Compressor data structure */
+ const opus_int8 pulses[], /* I pulse signal */
+ opus_int length, /* I length of input */
+ const opus_int signalType, /* I Signal type */
+ const opus_int quantOffsetType, /* I Quantization offset type */
+ const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
);
/* Decodes signs of excitation */
void silk_decode_signs(
- ec_dec *psRangeDec, /* I/O Compressor data structure */
- opus_int16 pulses[], /* I/O pulse signal */
- opus_int length, /* I length of input */
- const opus_int signalType, /* I Signal type */
- const opus_int quantOffsetType, /* I Quantization offset type */
- const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int16 pulses[], /* I/O pulse signal */
+ opus_int length, /* I length of input */
+ const opus_int signalType, /* I Signal type */
+ const opus_int quantOffsetType, /* I Quantization offset type */
+ const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
);
/* Check encoder control struct */
@@ -209,37 +205,37 @@ void silk_interpolate(
/* LTP tap quantizer */
void silk_quant_LTP_gains(
- opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
+ opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */
opus_int8 *periodicity_index, /* O Periodicity Index */
opus_int32 *sum_gain_dB_Q7, /* I/O Cumulative max prediction gain */
- opus_int *pred_gain_dB_Q7, /* O LTP prediction gain */
- const opus_int32 XX_Q17[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Correlation matrix in Q18 */
- const opus_int32 xX_Q17[ MAX_NB_SUBFR*LTP_ORDER ], /* I Correlation vector in Q18 */
- const opus_int subfr_len, /* I Number of samples per subframe */
- const opus_int nb_subfr, /* I Number of subframes */
+ const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */
+ opus_int mu_Q9, /* I Mu value (R/D tradeoff) */
+ opus_int lowComplexity, /* I Flag for low complexity */
+ const opus_int nb_subfr, /* I number of subframes */
int arch /* I Run-time architecture */
);
/* Entropy constrained matrix-weighted VQ, for a single input data vector */
void silk_VQ_WMat_EC_c(
opus_int8 *ind, /* O index of best codebook vector */
- opus_int32 *res_nrg_Q15, /* O best residual energy */
- opus_int32 *rate_dist_Q8, /* O best total bitrate */
+ opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
- const opus_int32 *XX_Q17, /* I correlation matrix */
- const opus_int32 *xX_Q17, /* I correlation vector */
+ const opus_int16 *in_Q14, /* I input vector to be quantized */
+ const opus_int32 *W_Q18, /* I weighting matrix */
const opus_int8 *cb_Q7, /* I codebook */
const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
- const opus_int subfr_len, /* I number of samples per subframe */
+ const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */
const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
- const opus_int L /* I number of vectors in codebook */
+ opus_int L /* I number of vectors in codebook */
);
#if !defined(OVERRIDE_silk_VQ_WMat_EC)
-#define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, subfr_len, max_gain_Q7, L, arch) \
- ((void)(arch),silk_VQ_WMat_EC_c(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, subfr_len, max_gain_Q7, L))
+#define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
+ mu_Q9, max_gain_Q7, L, arch) \
+ ((void)(arch),silk_VQ_WMat_EC_c(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
+ mu_Q9, max_gain_Q7, L))
#endif
/************************************/
@@ -247,14 +243,14 @@ void silk_VQ_WMat_EC_c(
/************************************/
void silk_NSQ_c(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int16 x16[], /* I Input */
+ const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
@@ -265,22 +261,22 @@ void silk_NSQ_c(
);
#if !defined(OVERRIDE_silk_NSQ)
-#define silk_NSQ(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+#define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
- ((void)(arch),silk_NSQ_c(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ ((void)(arch),silk_NSQ_c(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#endif
/* Noise shaping using delayed decision */
void silk_NSQ_del_dec_c(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
- const opus_int16 x16[], /* I Input */
+ const opus_int32 x_Q3[], /* I Prefiltered input signal */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
- const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
@@ -291,9 +287,9 @@ void silk_NSQ_del_dec_c(
);
#if !defined(OVERRIDE_silk_NSQ_del_dec)
-#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
- ((void)(arch),silk_NSQ_del_dec_c(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ ((void)(arch),silk_NSQ_del_dec_c(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#endif
@@ -350,7 +346,6 @@ void silk_NLSF_VQ(
opus_int32 err_Q26[], /* O Quantization errors [K] */
const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */
const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */
- const opus_int16 pWght_Q9[], /* I Codebook weights [K*LPC_order] */
const opus_int K, /* I Number of codebook vectors */
const opus_int LPC_order /* I Number of LPCs */
);
diff --git a/thirdparty/opus/silk/mips/NSQ_del_dec_mipsr1.h b/thirdparty/opus/silk/mips/NSQ_del_dec_mipsr1.h
index cd70713a8f..ad1cfe2a9b 100644
--- a/thirdparty/opus/silk/mips/NSQ_del_dec_mipsr1.h
+++ b/thirdparty/opus/silk/mips/NSQ_del_dec_mipsr1.h
@@ -61,7 +61,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
+ opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
opus_int decisionDelay, /* I */
int arch /* I */
)
@@ -323,9 +323,8 @@ static inline void silk_noise_shape_quantizer_del_dec(
psSS[ 1 ].xq_Q14 = xq_Q14;
}
- *smpl_buf_idx = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
- if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
- last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
+ *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
+ last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
/* Find winner */
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
diff --git a/thirdparty/opus/silk/mips/sigproc_fix_mipsr1.h b/thirdparty/opus/silk/mips/sigproc_fix_mipsr1.h
index 51520c0a6f..3b0a695365 100644
--- a/thirdparty/opus/silk/mips/sigproc_fix_mipsr1.h
+++ b/thirdparty/opus/silk/mips/sigproc_fix_mipsr1.h
@@ -28,6 +28,11 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef SILK_SIGPROC_FIX_MIPSR1_H
#define SILK_SIGPROC_FIX_MIPSR1_H
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
#undef silk_SAT16
static inline short int silk_SAT16(int a)
{
diff --git a/thirdparty/opus/silk/process_NLSFs.c b/thirdparty/opus/silk/process_NLSFs.c
index d130809541..0ab71f0163 100644
--- a/thirdparty/opus/silk/process_NLSFs.c
+++ b/thirdparty/opus/silk/process_NLSFs.c
@@ -48,7 +48,7 @@ void silk_process_NLSFs(
silk_assert( psEncC->speech_activity_Q8 >= 0 );
silk_assert( psEncC->speech_activity_Q8 <= SILK_FIX_CONST( 1.0, 8 ) );
- celt_assert( psEncC->useInterpolatedNLSFs == 1 || psEncC->indices.NLSFInterpCoef_Q2 == ( 1 << 2 ) );
+ silk_assert( psEncC->useInterpolatedNLSFs == 1 || psEncC->indices.NLSFInterpCoef_Q2 == ( 1 << 2 ) );
/***********************/
/* Calculate mu values */
@@ -60,7 +60,7 @@ void silk_process_NLSFs(
NLSF_mu_Q20 = silk_ADD_RSHIFT( NLSF_mu_Q20, NLSF_mu_Q20, 1 );
}
- celt_assert( NLSF_mu_Q20 > 0 );
+ silk_assert( NLSF_mu_Q20 > 0 );
silk_assert( NLSF_mu_Q20 <= SILK_FIX_CONST( 0.005, 20 ) );
/* Calculate NLSF weights */
@@ -89,7 +89,7 @@ void silk_process_NLSFs(
NLSF_mu_Q20, psEncC->NLSF_MSVQ_Survivors, psEncC->indices.signalType );
/* Convert quantized NLSFs back to LPC coefficients */
- silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder, psEncC->arch );
+ silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder );
if( doInterpolate ) {
/* Calculate the interpolated, quantized LSF vector for the first half */
@@ -97,11 +97,11 @@ void silk_process_NLSFs(
psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder );
/* Convert back to LPC coefficients */
- silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder, psEncC->arch );
+ silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder );
} else {
/* Copy LPC coefficients for first half from second half */
- celt_assert( psEncC->predictLPCOrder <= MAX_LPC_ORDER );
+ silk_assert( psEncC->predictLPCOrder <= MAX_LPC_ORDER );
silk_memcpy( PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof( opus_int16 ) );
}
}
diff --git a/thirdparty/opus/silk/quant_LTP_gains.c b/thirdparty/opus/silk/quant_LTP_gains.c
index d6b8eff8d1..513a8c4468 100644
--- a/thirdparty/opus/silk/quant_LTP_gains.c
+++ b/thirdparty/opus/silk/quant_LTP_gains.c
@@ -33,15 +33,14 @@ POSSIBILITY OF SUCH DAMAGE.
#include "tuning_parameters.h"
void silk_quant_LTP_gains(
- opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
+ opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */
opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */
opus_int8 *periodicity_index, /* O Periodicity Index */
opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
- opus_int *pred_gain_dB_Q7, /* O LTP prediction gain */
- const opus_int32 XX_Q17[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Correlation matrix in Q18 */
- const opus_int32 xX_Q17[ MAX_NB_SUBFR*LTP_ORDER ], /* I Correlation vector in Q18 */
- const opus_int subfr_len, /* I Number of samples per subframe */
- const opus_int nb_subfr, /* I Number of subframes */
+ const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */
+ opus_int mu_Q9, /* I Mu value (R/D tradeoff) */
+ opus_int lowComplexity, /* I Flag for low complexity */
+ const opus_int nb_subfr, /* I number of subframes */
int arch /* I Run-time architecture */
)
{
@@ -50,16 +49,16 @@ void silk_quant_LTP_gains(
const opus_uint8 *cl_ptr_Q5;
const opus_int8 *cbk_ptr_Q7;
const opus_uint8 *cbk_gain_ptr_Q7;
- const opus_int32 *XX_Q17_ptr, *xX_Q17_ptr;
- opus_int32 res_nrg_Q15_subfr, res_nrg_Q15, rate_dist_Q7_subfr, rate_dist_Q7, min_rate_dist_Q7;
- opus_int32 sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7;
- opus_int gain_Q7;
+ const opus_int16 *b_Q14_ptr;
+ const opus_int32 *W_Q18_ptr;
+ opus_int32 rate_dist_Q14_subfr, rate_dist_Q14, min_rate_dist_Q14;
+ opus_int32 sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7, gain_Q7;
/***************************************************/
/* iterate over different codebooks with different */
/* rates/distortions, and choose best */
/***************************************************/
- min_rate_dist_Q7 = silk_int32_MAX;
+ min_rate_dist_Q14 = silk_int32_MAX;
best_sum_log_gain_Q7 = 0;
for( k = 0; k < 3; k++ ) {
/* Safety margin for pitch gain control, to take into account factors
@@ -71,47 +70,53 @@ void silk_quant_LTP_gains(
cbk_gain_ptr_Q7 = silk_LTP_vq_gain_ptrs_Q7[ k ];
cbk_size = silk_LTP_vq_sizes[ k ];
- /* Set up pointers to first subframe */
- XX_Q17_ptr = XX_Q17;
- xX_Q17_ptr = xX_Q17;
+ /* Set up pointer to first subframe */
+ W_Q18_ptr = W_Q18;
+ b_Q14_ptr = B_Q14;
- res_nrg_Q15 = 0;
- rate_dist_Q7 = 0;
+ rate_dist_Q14 = 0;
sum_log_gain_tmp_Q7 = *sum_log_gain_Q7;
for( j = 0; j < nb_subfr; j++ ) {
max_gain_Q7 = silk_log2lin( ( SILK_FIX_CONST( MAX_SUM_LOG_GAIN_DB / 6.0, 7 ) - sum_log_gain_tmp_Q7 )
+ SILK_FIX_CONST( 7, 7 ) ) - gain_safety;
+
silk_VQ_WMat_EC(
&temp_idx[ j ], /* O index of best codebook vector */
- &res_nrg_Q15_subfr, /* O residual energy */
- &rate_dist_Q7_subfr, /* O best weighted quantization error + mu * rate */
+ &rate_dist_Q14_subfr, /* O best weighted quantization error + mu * rate */
&gain_Q7, /* O sum of absolute LTP coefficients */
- XX_Q17_ptr, /* I correlation matrix */
- xX_Q17_ptr, /* I correlation vector */
+ b_Q14_ptr, /* I input vector to be quantized */
+ W_Q18_ptr, /* I weighting matrix */
cbk_ptr_Q7, /* I codebook */
cbk_gain_ptr_Q7, /* I codebook effective gains */
cl_ptr_Q5, /* I code length for each codebook vector */
- subfr_len, /* I number of samples per subframe */
+ mu_Q9, /* I tradeoff between weighted error and rate */
max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
cbk_size, /* I number of vectors in codebook */
arch /* I Run-time architecture */
);
- res_nrg_Q15 = silk_ADD_POS_SAT32( res_nrg_Q15, res_nrg_Q15_subfr );
- rate_dist_Q7 = silk_ADD_POS_SAT32( rate_dist_Q7, rate_dist_Q7_subfr );
+ rate_dist_Q14 = silk_ADD_POS_SAT32( rate_dist_Q14, rate_dist_Q14_subfr );
sum_log_gain_tmp_Q7 = silk_max(0, sum_log_gain_tmp_Q7
+ silk_lin2log( gain_safety + gain_Q7 ) - SILK_FIX_CONST( 7, 7 ));
- XX_Q17_ptr += LTP_ORDER * LTP_ORDER;
- xX_Q17_ptr += LTP_ORDER;
+ b_Q14_ptr += LTP_ORDER;
+ W_Q18_ptr += LTP_ORDER * LTP_ORDER;
}
- if( rate_dist_Q7 <= min_rate_dist_Q7 ) {
- min_rate_dist_Q7 = rate_dist_Q7;
+ /* Avoid never finding a codebook */
+ rate_dist_Q14 = silk_min( silk_int32_MAX - 1, rate_dist_Q14 );
+
+ if( rate_dist_Q14 < min_rate_dist_Q14 ) {
+ min_rate_dist_Q14 = rate_dist_Q14;
*periodicity_index = (opus_int8)k;
silk_memcpy( cbk_index, temp_idx, nb_subfr * sizeof( opus_int8 ) );
best_sum_log_gain_Q7 = sum_log_gain_tmp_Q7;
}
+
+ /* Break early in low-complexity mode if rate distortion is below threshold */
+ if( lowComplexity && ( rate_dist_Q14 < silk_LTP_gain_middle_avg_RD_Q14 ) ) {
+ break;
+ }
}
cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ *periodicity_index ];
@@ -120,13 +125,5 @@ void silk_quant_LTP_gains(
B_Q14[ j * LTP_ORDER + k ] = silk_LSHIFT( cbk_ptr_Q7[ cbk_index[ j ] * LTP_ORDER + k ], 7 );
}
}
-
- if( nb_subfr == 2 ) {
- res_nrg_Q15 = silk_RSHIFT32( res_nrg_Q15, 1 );
- } else {
- res_nrg_Q15 = silk_RSHIFT32( res_nrg_Q15, 2 );
- }
-
*sum_log_gain_Q7 = best_sum_log_gain_Q7;
- *pred_gain_dB_Q7 = (opus_int)silk_SMULBB( -3, silk_lin2log( res_nrg_Q15 ) - ( 15 << 7 ) );
}
diff --git a/thirdparty/opus/silk/resampler.c b/thirdparty/opus/silk/resampler.c
index 1f11e50891..374fbb3722 100644
--- a/thirdparty/opus/silk/resampler.c
+++ b/thirdparty/opus/silk/resampler.c
@@ -91,14 +91,14 @@ opus_int silk_resampler_init(
if( forEnc ) {
if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000 ) ||
( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return -1;
}
S->inputDelay = delay_matrix_enc[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
} else {
if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 ) ||
( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) {
- celt_assert( 0 );
+ silk_assert( 0 );
return -1;
}
S->inputDelay = delay_matrix_dec[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
@@ -151,7 +151,7 @@ opus_int silk_resampler_init(
S->Coefs = silk_Resampler_1_6_COEFS;
} else {
/* None available */
- celt_assert( 0 );
+ silk_assert( 0 );
return -1;
}
} else {
@@ -181,9 +181,9 @@ opus_int silk_resampler(
opus_int nSamples;
/* Need at least 1 ms of input data */
- celt_assert( inLen >= S->Fs_in_kHz );
+ silk_assert( inLen >= S->Fs_in_kHz );
/* Delay can't exceed the 1 ms of buffering */
- celt_assert( S->inputDelay <= S->Fs_in_kHz );
+ silk_assert( S->inputDelay <= S->Fs_in_kHz );
nSamples = S->Fs_in_kHz - S->inputDelay;
diff --git a/thirdparty/opus/silk/resampler_down2.c b/thirdparty/opus/silk/resampler_down2.c
index 971d7bfd4a..cec3634640 100644
--- a/thirdparty/opus/silk/resampler_down2.c
+++ b/thirdparty/opus/silk/resampler_down2.c
@@ -43,8 +43,8 @@ void silk_resampler_down2(
opus_int32 k, len2 = silk_RSHIFT32( inLen, 1 );
opus_int32 in32, out32, Y, X;
- celt_assert( silk_resampler_down2_0 > 0 );
- celt_assert( silk_resampler_down2_1 < 0 );
+ silk_assert( silk_resampler_down2_0 > 0 );
+ silk_assert( silk_resampler_down2_1 < 0 );
/* Internal variables and state are in Q10 format */
for( k = 0; k < len2; k++ ) {
diff --git a/thirdparty/opus/silk/resampler_private_down_FIR.c b/thirdparty/opus/silk/resampler_private_down_FIR.c
index 3e8735a35a..783e42b356 100644
--- a/thirdparty/opus/silk/resampler_private_down_FIR.c
+++ b/thirdparty/opus/silk/resampler_private_down_FIR.c
@@ -136,7 +136,7 @@ static OPUS_INLINE opus_int16 *silk_resampler_private_down_FIR_INTERPOL(
}
break;
default:
- celt_assert( 0 );
+ silk_assert( 0 );
}
return out;
}
diff --git a/thirdparty/opus/silk/sort.c b/thirdparty/opus/silk/sort.c
index 4fba16f831..7187c9efb1 100644
--- a/thirdparty/opus/silk/sort.c
+++ b/thirdparty/opus/silk/sort.c
@@ -48,9 +48,9 @@ void silk_insertion_sort_increasing(
opus_int i, j;
/* Safety checks */
- celt_assert( K > 0 );
- celt_assert( L > 0 );
- celt_assert( L >= K );
+ silk_assert( K > 0 );
+ silk_assert( L > 0 );
+ silk_assert( L >= K );
/* Write start indices in index vector */
for( i = 0; i < K; i++ ) {
@@ -96,9 +96,9 @@ void silk_insertion_sort_decreasing_int16(
opus_int value;
/* Safety checks */
- celt_assert( K > 0 );
- celt_assert( L > 0 );
- celt_assert( L >= K );
+ silk_assert( K > 0 );
+ silk_assert( L > 0 );
+ silk_assert( L >= K );
/* Write start indices in index vector */
for( i = 0; i < K; i++ ) {
@@ -141,7 +141,7 @@ void silk_insertion_sort_increasing_all_values_int16(
opus_int i, j;
/* Safety checks */
- celt_assert( L > 0 );
+ silk_assert( L > 0 );
/* Sort vector elements by value, increasing order */
for( i = 1; i < L; i++ ) {
diff --git a/thirdparty/opus/silk/stereo_LR_to_MS.c b/thirdparty/opus/silk/stereo_LR_to_MS.c
index c8226663c8..dda0298de2 100644
--- a/thirdparty/opus/silk/stereo_LR_to_MS.c
+++ b/thirdparty/opus/silk/stereo_LR_to_MS.c
@@ -109,7 +109,7 @@ void silk_stereo_LR_to_MS(
if( total_rate_bps < 1 ) {
total_rate_bps = 1;
}
- min_mid_rate_bps = silk_SMLABB( 2000, fs_kHz, 600 );
+ min_mid_rate_bps = silk_SMLABB( 2000, fs_kHz, 900 );
silk_assert( min_mid_rate_bps < 32767 );
/* Default bitrate distribution: 8 parts for Mid and (5+3*frac) parts for Side. so: mid_rate = ( 8 / ( 13 + 3 * frac ) ) * total_ rate */
frac_3_Q16 = silk_MUL( 3, frac_Q16 );
diff --git a/thirdparty/opus/silk/stereo_encode_pred.c b/thirdparty/opus/silk/stereo_encode_pred.c
index 03becb6736..e6dd195066 100644
--- a/thirdparty/opus/silk/stereo_encode_pred.c
+++ b/thirdparty/opus/silk/stereo_encode_pred.c
@@ -41,11 +41,11 @@ void silk_stereo_encode_pred(
/* Entropy coding */
n = 5 * ix[ 0 ][ 2 ] + ix[ 1 ][ 2 ];
- celt_assert( n < 25 );
+ silk_assert( n < 25 );
ec_enc_icdf( psRangeEnc, n, silk_stereo_pred_joint_iCDF, 8 );
for( n = 0; n < 2; n++ ) {
- celt_assert( ix[ n ][ 0 ] < 3 );
- celt_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS );
+ silk_assert( ix[ n ][ 0 ] < 3 );
+ silk_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS );
ec_enc_icdf( psRangeEnc, ix[ n ][ 0 ], silk_uniform3_iCDF, 8 );
ec_enc_icdf( psRangeEnc, ix[ n ][ 1 ], silk_uniform5_iCDF, 8 );
}
diff --git a/thirdparty/opus/silk/structs.h b/thirdparty/opus/silk/structs.h
index 3380c757b2..827829dc6f 100644
--- a/thirdparty/opus/silk/structs.h
+++ b/thirdparty/opus/silk/structs.h
@@ -48,7 +48,6 @@ typedef struct {
opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
opus_int32 sLF_AR_shp_Q14;
- opus_int32 sDiff_shp_Q14;
opus_int lagPrev;
opus_int sLTP_buf_idx;
opus_int sLTP_shp_buf_idx;
@@ -78,7 +77,6 @@ typedef struct {
opus_int32 In_LP_State[ 2 ]; /* Low pass filter state */
opus_int32 transition_frame_no; /* Counter which is mapped to a cut-off frequency */
opus_int mode; /* Operating mode, <0: switch down, >0: switch up; 0: do nothing */
- opus_int32 saved_fs_kHz; /* If non-zero, holds the last sampling rate before a bandwidth switching reset. */
} silk_LP_state;
/* Structure containing NLSF codebook */
@@ -88,7 +86,6 @@ typedef struct {
const opus_int16 quantStepSize_Q16;
const opus_int16 invQuantStepSize_Q6;
const opus_uint8 *CB1_NLSF_Q8;
- const opus_int16 *CB1_Wght_Q9;
const opus_uint8 *CB1_iCDF;
const opus_uint8 *pred_Q8;
const opus_uint8 *ec_sel;
@@ -172,6 +169,8 @@ typedef struct {
opus_int pitchEstimationComplexity; /* Complexity level for pitch estimator */
opus_int pitchEstimationLPCOrder; /* Whitening filter order for pitch estimator */
opus_int32 pitchEstimationThreshold_Q16; /* Threshold for pitch estimator */
+ opus_int LTPQuantLowComplexity; /* Flag for low complexity LTP quantization */
+ opus_int mu_LTP_Q9; /* Rate-distortion tradeoff in LTP quantization */
opus_int32 sum_log_gain_Q7; /* Cumulative max prediction gain */
opus_int NLSF_MSVQ_Survivors; /* Number of survivors in NLSF MSVQ */
opus_int first_frame_after_reset; /* Flag for deactivating NLSF interpolation, pitch prediction */
@@ -302,7 +301,6 @@ typedef struct {
/* Stuff used for PLC */
opus_int lossCnt;
opus_int prevSignalType;
- int arch;
silk_PLC_struct sPLC;
diff --git a/thirdparty/opus/silk/sum_sqr_shift.c b/thirdparty/opus/silk/sum_sqr_shift.c
index 4fd0c3d7d5..129df191d8 100644
--- a/thirdparty/opus/silk/sum_sqr_shift.c
+++ b/thirdparty/opus/silk/sum_sqr_shift.c
@@ -41,40 +41,43 @@ void silk_sum_sqr_shift(
)
{
opus_int i, shft;
- opus_uint32 nrg_tmp;
- opus_int32 nrg;
+ opus_int32 nrg_tmp, nrg;
- /* Do a first run with the maximum shift we could have. */
- shft = 31-silk_CLZ32(len);
- /* Let's be conservative with rounding and start with nrg=len. */
- nrg = len;
- for( i = 0; i < len - 1; i += 2 ) {
- nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
- nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] );
- nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+ nrg = 0;
+ shft = 0;
+ len--;
+ for( i = 0; i < len; i += 2 ) {
+ nrg = silk_SMLABB_ovflw( nrg, x[ i ], x[ i ] );
+ nrg = silk_SMLABB_ovflw( nrg, x[ i + 1 ], x[ i + 1 ] );
+ if( nrg < 0 ) {
+ /* Scale down */
+ nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 );
+ shft = 2;
+ i+=2;
+ break;
+ }
}
- if( i < len ) {
- /* One sample left to process */
- nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
- nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
- }
- silk_assert( nrg >= 0 );
- /* Make sure the result will fit in a 32-bit signed integer with two bits
- of headroom. */
- shft = silk_max_32(0, shft+3 - silk_CLZ32(nrg));
- nrg = 0;
- for( i = 0 ; i < len - 1; i += 2 ) {
+ for( ; i < len; i += 2 ) {
nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] );
- nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+ nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, (opus_uint32)nrg_tmp, shft );
+ if( nrg < 0 ) {
+ /* Scale down */
+ nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 );
+ shft += 2;
+ }
}
- if( i < len ) {
+ if( i == len ) {
/* One sample left to process */
nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
}
- silk_assert( nrg >= 0 );
+ /* Make sure to have at least one extra leading zero (two leading zeros in total) */
+ if( nrg & 0xC0000000 ) {
+ nrg = silk_RSHIFT_uint( (opus_uint32)nrg, 2 );
+ shft += 2;
+ }
/* Output arguments */
*shift = shft;
diff --git a/thirdparty/opus/silk/tables.h b/thirdparty/opus/silk/tables.h
index 95230c451a..7fea6fda39 100644
--- a/thirdparty/opus/silk/tables.h
+++ b/thirdparty/opus/silk/tables.h
@@ -76,8 +76,10 @@ extern const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ];
extern const opus_uint8 silk_LTP_per_index_iCDF[ 3 ]; /* 3 */
extern const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[ NB_LTP_CBKS ]; /* 3 */
extern const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[ NB_LTP_CBKS ]; /* 3 */
+extern const opus_int16 silk_LTP_gain_middle_avg_RD_Q14;
extern const opus_int8 * const silk_LTP_vq_ptrs_Q7[ NB_LTP_CBKS ]; /* 168 */
extern const opus_uint8 * const silk_LTP_vq_gain_ptrs_Q7[NB_LTP_CBKS];
+
extern const opus_int8 silk_LTP_vq_sizes[ NB_LTP_CBKS ]; /* 3 */
extern const opus_uint8 silk_LTPscale_iCDF[ 3 ]; /* 4 */
@@ -97,6 +99,12 @@ extern const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ];
extern const silk_NLSF_CB_struct silk_NLSF_CB_WB; /* 1040 */
extern const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB; /* 728 */
+/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */
+extern const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ]; /* 32 */
+extern const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ]; /* 32 */
+extern const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ]; /* 32 */
+extern const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ]; /* 32 */
+
/* Quantization offsets */
extern const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ]; /* 8 */
diff --git a/thirdparty/opus/silk/tables_LTP.c b/thirdparty/opus/silk/tables_LTP.c
index 5e12c8643e..0e6a0254d5 100644
--- a/thirdparty/opus/silk/tables_LTP.c
+++ b/thirdparty/opus/silk/tables_LTP.c
@@ -51,6 +51,8 @@ static const opus_uint8 silk_LTP_gain_iCDF_2[32] = {
24, 20, 16, 12, 9, 5, 2, 0
};
+const opus_int16 silk_LTP_gain_middle_avg_RD_Q14 = 12304;
+
static const opus_uint8 silk_LTP_gain_BITS_Q5_0[8] = {
15, 131, 138, 138, 155, 155, 173, 173
};
diff --git a/thirdparty/opus/silk/tables_NLSF_CB_NB_MB.c b/thirdparty/opus/silk/tables_NLSF_CB_NB_MB.c
index 195d5b95bd..8c59d207aa 100644
--- a/thirdparty/opus/silk/tables_NLSF_CB_NB_MB.c
+++ b/thirdparty/opus/silk/tables_NLSF_CB_NB_MB.c
@@ -74,41 +74,6 @@ static const opus_uint8 silk_NLSF_CB1_NB_MB_Q8[ 320 ] = {
64, 84, 104, 118, 156, 177, 201, 230
};
-static const opus_int16 silk_NLSF_CB1_Wght_Q9[ 320 ] = {
- 2897, 2314, 2314, 2314, 2287, 2287, 2314, 2300, 2327, 2287,
- 2888, 2580, 2394, 2367, 2314, 2274, 2274, 2274, 2274, 2194,
- 2487, 2340, 2340, 2314, 2314, 2314, 2340, 2340, 2367, 2354,
- 3216, 2766, 2340, 2340, 2314, 2274, 2221, 2207, 2261, 2194,
- 2460, 2474, 2367, 2394, 2394, 2394, 2394, 2367, 2407, 2314,
- 3479, 3056, 2127, 2207, 2274, 2274, 2274, 2287, 2314, 2261,
- 3282, 3141, 2580, 2394, 2247, 2221, 2207, 2194, 2194, 2114,
- 4096, 3845, 2221, 2620, 2620, 2407, 2314, 2394, 2367, 2074,
- 3178, 3244, 2367, 2221, 2553, 2434, 2340, 2314, 2167, 2221,
- 3338, 3488, 2726, 2194, 2261, 2460, 2354, 2367, 2207, 2101,
- 2354, 2420, 2327, 2367, 2394, 2420, 2420, 2420, 2460, 2367,
- 3779, 3629, 2434, 2527, 2367, 2274, 2274, 2300, 2207, 2048,
- 3254, 3225, 2713, 2846, 2447, 2327, 2300, 2300, 2274, 2127,
- 3263, 3300, 2753, 2806, 2447, 2261, 2261, 2247, 2127, 2101,
- 2873, 2981, 2633, 2367, 2407, 2354, 2194, 2247, 2247, 2114,
- 3225, 3197, 2633, 2580, 2274, 2181, 2247, 2221, 2221, 2141,
- 3178, 3310, 2740, 2407, 2274, 2274, 2274, 2287, 2194, 2114,
- 3141, 3272, 2460, 2061, 2287, 2500, 2367, 2487, 2434, 2181,
- 3507, 3282, 2314, 2700, 2647, 2474, 2367, 2394, 2340, 2127,
- 3423, 3535, 3038, 3056, 2300, 1950, 2221, 2274, 2274, 2274,
- 3404, 3366, 2087, 2687, 2873, 2354, 2420, 2274, 2474, 2540,
- 3760, 3488, 1950, 2660, 2897, 2527, 2394, 2367, 2460, 2261,
- 3028, 3272, 2740, 2888, 2740, 2154, 2127, 2287, 2234, 2247,
- 3695, 3657, 2025, 1969, 2660, 2700, 2580, 2500, 2327, 2367,
- 3207, 3413, 2354, 2074, 2888, 2888, 2340, 2487, 2247, 2167,
- 3338, 3366, 2846, 2780, 2327, 2154, 2274, 2287, 2114, 2061,
- 2327, 2300, 2181, 2167, 2181, 2367, 2633, 2700, 2700, 2553,
- 2407, 2434, 2221, 2261, 2221, 2221, 2340, 2420, 2607, 2700,
- 3038, 3244, 2806, 2888, 2474, 2074, 2300, 2314, 2354, 2380,
- 2221, 2154, 2127, 2287, 2500, 2793, 2793, 2620, 2580, 2367,
- 3676, 3713, 2234, 1838, 2181, 2753, 2726, 2673, 2513, 2207,
- 2793, 3160, 2726, 2553, 2846, 2513, 2181, 2394, 2221, 2181
-};
-
static const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = {
212, 178, 148, 129, 108, 96, 85, 82,
79, 77, 61, 59, 57, 56, 51, 49,
@@ -185,7 +150,6 @@ const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB =
SILK_FIX_CONST( 0.18, 16 ),
SILK_FIX_CONST( 1.0 / 0.18, 6 ),
silk_NLSF_CB1_NB_MB_Q8,
- silk_NLSF_CB1_Wght_Q9,
silk_NLSF_CB1_iCDF_NB_MB,
silk_NLSF_PRED_NB_MB_Q8,
silk_NLSF_CB2_SELECT_NB_MB,
diff --git a/thirdparty/opus/silk/tables_NLSF_CB_WB.c b/thirdparty/opus/silk/tables_NLSF_CB_WB.c
index 5cc9f57bff..50af87eb2e 100644
--- a/thirdparty/opus/silk/tables_NLSF_CB_WB.c
+++ b/thirdparty/opus/silk/tables_NLSF_CB_WB.c
@@ -98,41 +98,6 @@ static const opus_uint8 silk_NLSF_CB1_WB_Q8[ 512 ] = {
110, 119, 129, 141, 175, 198, 218, 237
};
-static const opus_int16 silk_NLSF_CB1_WB_Wght_Q9[ 512 ] = {
- 3657, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2963, 2963, 2925, 2846,
- 3216, 3085, 2972, 3056, 3056, 3010, 3010, 3010, 2963, 2963, 3010, 2972, 2888, 2846, 2846, 2726,
- 3920, 4014, 2981, 3207, 3207, 2934, 3056, 2846, 3122, 3244, 2925, 2846, 2620, 2553, 2780, 2925,
- 3516, 3197, 3010, 3103, 3019, 2888, 2925, 2925, 2925, 2925, 2888, 2888, 2888, 2888, 2888, 2753,
- 5054, 5054, 2934, 3573, 3385, 3056, 3085, 2793, 3160, 3160, 2972, 2846, 2513, 2540, 2753, 2888,
- 4428, 4149, 2700, 2753, 2972, 3010, 2925, 2846, 2981, 3019, 2925, 2925, 2925, 2925, 2888, 2726,
- 3620, 3019, 2972, 3056, 3056, 2873, 2806, 3056, 3216, 3047, 2981, 3291, 3291, 2981, 3310, 2991,
- 5227, 5014, 2540, 3338, 3526, 3385, 3197, 3094, 3376, 2981, 2700, 2647, 2687, 2793, 2846, 2673,
- 5081, 5174, 4615, 4428, 2460, 2897, 3047, 3207, 3169, 2687, 2740, 2888, 2846, 2793, 2846, 2700,
- 3122, 2888, 2963, 2925, 2925, 2925, 2925, 2963, 2963, 2963, 2963, 2925, 2925, 2963, 2963, 2963,
- 4202, 3207, 2981, 3103, 3010, 2888, 2888, 2925, 2972, 2873, 2916, 3019, 2972, 3010, 3197, 2873,
- 3760, 3760, 3244, 3103, 2981, 2888, 2925, 2888, 2972, 2934, 2793, 2793, 2846, 2888, 2888, 2660,
- 3854, 4014, 3207, 3122, 3244, 2934, 3047, 2963, 2963, 3085, 2846, 2793, 2793, 2793, 2793, 2580,
- 3845, 4080, 3357, 3516, 3094, 2740, 3010, 2934, 3122, 3085, 2846, 2846, 2647, 2647, 2846, 2806,
- 5147, 4894, 3225, 3845, 3441, 3169, 2897, 3413, 3451, 2700, 2580, 2673, 2740, 2846, 2806, 2753,
- 4109, 3789, 3291, 3160, 2925, 2888, 2888, 2925, 2793, 2740, 2793, 2740, 2793, 2846, 2888, 2806,
- 5081, 5054, 3047, 3545, 3244, 3056, 3085, 2944, 3103, 2897, 2740, 2740, 2740, 2846, 2793, 2620,
- 4309, 4309, 2860, 2527, 3207, 3376, 3376, 3075, 3075, 3376, 3056, 2846, 2647, 2580, 2726, 2753,
- 3056, 2916, 2806, 2888, 2740, 2687, 2897, 3103, 3150, 3150, 3216, 3169, 3056, 3010, 2963, 2846,
- 4375, 3882, 2925, 2888, 2846, 2888, 2846, 2846, 2888, 2888, 2888, 2846, 2888, 2925, 2888, 2846,
- 2981, 2916, 2916, 2981, 2981, 3056, 3122, 3216, 3150, 3056, 3010, 2972, 2972, 2972, 2925, 2740,
- 4229, 4149, 3310, 3347, 2925, 2963, 2888, 2981, 2981, 2846, 2793, 2740, 2846, 2846, 2846, 2793,
- 4080, 4014, 3103, 3010, 2925, 2925, 2925, 2888, 2925, 2925, 2846, 2846, 2846, 2793, 2888, 2780,
- 4615, 4575, 3169, 3441, 3207, 2981, 2897, 3038, 3122, 2740, 2687, 2687, 2687, 2740, 2793, 2700,
- 4149, 4269, 3789, 3657, 2726, 2780, 2888, 2888, 3010, 2972, 2925, 2846, 2687, 2687, 2793, 2888,
- 4215, 3554, 2753, 2846, 2846, 2888, 2888, 2888, 2925, 2925, 2888, 2925, 2925, 2925, 2963, 2888,
- 5174, 4921, 2261, 3432, 3789, 3479, 3347, 2846, 3310, 3479, 3150, 2897, 2460, 2487, 2753, 2925,
- 3451, 3685, 3122, 3197, 3357, 3047, 3207, 3207, 2981, 3216, 3085, 2925, 2925, 2687, 2540, 2434,
- 2981, 3010, 2793, 2793, 2740, 2793, 2846, 2972, 3056, 3103, 3150, 3150, 3150, 3103, 3010, 3010,
- 2944, 2873, 2687, 2726, 2780, 3010, 3432, 3545, 3357, 3244, 3056, 3010, 2963, 2925, 2888, 2846,
- 3019, 2944, 2897, 3010, 3010, 2972, 3019, 3103, 3056, 3056, 3010, 2888, 2846, 2925, 2925, 2888,
- 3920, 3967, 3010, 3197, 3357, 3216, 3291, 3291, 3479, 3704, 3441, 2726, 2181, 2460, 2580, 2607
-};
-
static const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = {
225, 204, 201, 184, 183, 175, 158, 154,
153, 135, 119, 115, 113, 110, 109, 99,
@@ -223,7 +188,6 @@ const silk_NLSF_CB_struct silk_NLSF_CB_WB =
SILK_FIX_CONST( 0.15, 16 ),
SILK_FIX_CONST( 1.0 / 0.15, 6 ),
silk_NLSF_CB1_WB_Q8,
- silk_NLSF_CB1_WB_Wght_Q9,
silk_NLSF_CB1_iCDF_WB,
silk_NLSF_PRED_WB_Q8,
silk_NLSF_CB2_SELECT_WB,
diff --git a/thirdparty/opus/silk/tables_other.c b/thirdparty/opus/silk/tables_other.c
index e34d90777b..398686bf26 100644
--- a/thirdparty/opus/silk/tables_other.c
+++ b/thirdparty/opus/silk/tables_other.c
@@ -38,6 +38,20 @@ extern "C"
{
#endif
+/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */
+const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ] = {
+ 0, 8000, 9400, 11500, 13500, 17500, 25000, MAX_TARGET_RATE_BPS
+};
+const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ] = {
+ 0, 9000, 12000, 14500, 18500, 24500, 35500, MAX_TARGET_RATE_BPS
+};
+const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ] = {
+ 0, 10500, 14000, 17000, 21500, 28500, 42000, MAX_TARGET_RATE_BPS
+};
+const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ] = {
+ 18, 29, 38, 40, 46, 52, 62, 84
+};
+
/* Tables for stereo predictor coding */
const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ] = {
-13732, -10050, -8266, -7526, -6500, -5000, -2950, -820,
diff --git a/thirdparty/opus/silk/tuning_parameters.h b/thirdparty/opus/silk/tuning_parameters.h
index d70275fd8f..5b8f404235 100644
--- a/thirdparty/opus/silk/tuning_parameters.h
+++ b/thirdparty/opus/silk/tuning_parameters.h
@@ -53,12 +53,19 @@ extern "C"
/* LPC analysis regularization */
#define FIND_LPC_COND_FAC 1e-5f
+/* LTP analysis defines */
+#define FIND_LTP_COND_FAC 1e-5f
+#define LTP_DAMPING 0.05f
+#define LTP_SMOOTHING 0.1f
+
+/* LTP quantization settings */
+#define MU_LTP_QUANT_NB 0.03f
+#define MU_LTP_QUANT_MB 0.025f
+#define MU_LTP_QUANT_WB 0.02f
+
/* Max cumulative LTP gain */
#define MAX_SUM_LOG_GAIN_DB 250.0f
-/* LTP analysis defines */
-#define LTP_CORR_INV_MAX 0.03f
-
/***********************/
/* High pass filtering */
/***********************/
@@ -96,16 +103,25 @@ extern "C"
#define SPARSE_SNR_INCR_dB 2.0f
/* threshold for sparseness measure above which to use lower quantization offset during unvoiced */
-#define ENERGY_VARIATION_THRESHOLD_QNT_OFFSET 0.6f
+#define SPARSENESS_THRESHOLD_QNT_OFFSET 0.75f
/* warping control */
#define WARPING_MULTIPLIER 0.015f
/* fraction added to first autocorrelation value */
-#define SHAPE_WHITE_NOISE_FRACTION 3e-5f
+#define SHAPE_WHITE_NOISE_FRACTION 5e-5f
/* noise shaping filter chirp factor */
-#define BANDWIDTH_EXPANSION 0.94f
+#define BANDWIDTH_EXPANSION 0.95f
+
+/* difference between chirp factors for analysis and synthesis noise shaping filters at low bitrates */
+#define LOW_RATE_BANDWIDTH_EXPANSION_DELTA 0.01f
+
+/* extra harmonic boosting (signal shaping) at low bitrates */
+#define LOW_RATE_HARMONIC_BOOST 0.1f
+
+/* extra harmonic boosting (signal shaping) for noisy input signals */
+#define LOW_INPUT_QUALITY_HARMONIC_BOOST 0.1f
/* harmonic noise shaping */
#define HARMONIC_SHAPING 0.3f
diff --git a/thirdparty/opus/silk/x86/NSQ_del_dec_sse4_1.c b/thirdparty/opus/silk/x86/NSQ_del_dec_sse.c
index 2c75ede2dd..21d4a8bc1e 100644
--- a/thirdparty/opus/silk/x86/NSQ_del_dec_sse4_1.c
+++ b/thirdparty/opus/silk/x86/NSQ_del_dec_sse.c
@@ -107,12 +107,12 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
+ opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
opus_int decisionDelay /* I */
);
void silk_NSQ_del_dec_sse4_1(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
@@ -234,8 +234,7 @@ void silk_NSQ_del_dec_sse4_1(
psDD = &psDelDec[ Winner_ind ];
last_smple_idx = smpl_buf_idx + decisionDelay;
for( i = 0; i < decisionDelay; i++ ) {
- last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
- if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
+ last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) );
@@ -247,7 +246,7 @@ void silk_NSQ_del_dec_sse4_1(
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- celt_assert( start_idx > 0 );
+ silk_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
@@ -286,8 +285,7 @@ void silk_NSQ_del_dec_sse4_1(
last_smple_idx = smpl_buf_idx + decisionDelay;
Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
for( i = 0; i < decisionDelay; i++ ) {
- last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
- if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
+ last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) );
@@ -301,6 +299,7 @@ void silk_NSQ_del_dec_sse4_1(
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech signal */
+ /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
@@ -334,7 +333,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
- opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
+ opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */
opus_int decisionDelay /* I */
)
{
@@ -353,7 +352,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
__m128i b_Q12_0123, b_sr_Q12_0123;
SAVE_STACK;
- celt_assert( nStatesDelayedDecision > 0 );
+ silk_assert( nStatesDelayedDecision > 0 );
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
@@ -639,9 +638,8 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_sse4_1(
psSS[ 1 ].xq_Q14 = xq_Q14;
}
}
- *smpl_buf_idx = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
- if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
- last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
+ *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
+ last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
/* Find winner */
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
diff --git a/thirdparty/opus/silk/x86/NSQ_sse4_1.c b/thirdparty/opus/silk/x86/NSQ_sse.c
index b0315e35fc..bb3c5f1955 100644
--- a/thirdparty/opus/silk/x86/NSQ_sse4_1.c
+++ b/thirdparty/opus/silk/x86/NSQ_sse.c
@@ -71,7 +71,7 @@ static OPUS_INLINE void silk_noise_shape_quantizer_10_16_sse4_1(
);
void silk_NSQ_sse4_1(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
@@ -199,7 +199,7 @@ void silk_NSQ_sse4_1(
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- celt_assert( start_idx > 0 );
+ silk_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
@@ -233,6 +233,7 @@ void silk_NSQ_sse4_1(
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech and noise shaping signals */
+ /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
diff --git a/thirdparty/opus/silk/x86/VAD_sse4_1.c b/thirdparty/opus/silk/x86/VAD_sse.c
index d02ddf4ad0..4e90f4410d 100644
--- a/thirdparty/opus/silk/x86/VAD_sse4_1.c
+++ b/thirdparty/opus/silk/x86/VAD_sse.c
@@ -65,9 +65,9 @@ opus_int silk_VAD_GetSA_Q8_sse4_1( /* O Return value, 0 if s
/* Safety checks */
silk_assert( VAD_N_BANDS == 4 );
- celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
- celt_assert( psEncC->frame_length <= 512 );
- celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
+ silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
+ silk_assert( psEncC->frame_length <= 512 );
+ silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
/***********************/
/* Filter and Decimate */
diff --git a/thirdparty/opus/silk/x86/VQ_WMat_EC_sse4_1.c b/thirdparty/opus/silk/x86/VQ_WMat_EC_sse.c
index 74d6c6d0ec..74d6c6d0ec 100644
--- a/thirdparty/opus/silk/x86/VQ_WMat_EC_sse4_1.c
+++ b/thirdparty/opus/silk/x86/VQ_WMat_EC_sse.c
diff --git a/thirdparty/opus/silk/x86/main_sse.h b/thirdparty/opus/silk/x86/main_sse.h
index 2f15d44869..d8d61310ed 100644
--- a/thirdparty/opus/silk/x86/main_sse.h
+++ b/thirdparty/opus/silk/x86/main_sse.h
@@ -34,7 +34,6 @@
# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
-#if 0 /* FIXME: SSE disabled until silk_VQ_WMat_EC_sse4_1() gets updated. */
# define OVERRIDE_silk_VQ_WMat_EC
void silk_VQ_WMat_EC_sse4_1(
@@ -80,13 +79,11 @@ extern void (*const SILK_VQ_WMAT_EC_IMPL[OPUS_ARCHMASK + 1])(
mu_Q9, max_gain_Q7, L))
#endif
-#endif
-#if 0 /* FIXME: SSE disabled until the NSQ code gets updated. */
# define OVERRIDE_silk_NSQ
void silk_NSQ_sse4_1(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
@@ -113,7 +110,7 @@ void silk_NSQ_sse4_1(
#else
extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
@@ -140,7 +137,7 @@ extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])(
# define OVERRIDE_silk_NSQ_del_dec
void silk_NSQ_del_dec_sse4_1(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
@@ -167,7 +164,7 @@ void silk_NSQ_del_dec_sse4_1(
#else
extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
@@ -190,7 +187,6 @@ extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
#endif
-#endif
void silk_noise_shape_quantizer(
silk_nsq_state *NSQ, /* I/O NSQ state */
@@ -242,6 +238,39 @@ extern opus_int (*const SILK_VAD_GETSA_Q8_IMPL[OPUS_ARCHMASK + 1])(
silk_encoder_state *psEnC,
const opus_int16 pIn[]);
+# define OVERRIDE_silk_warped_LPC_analysis_filter_FIX
+
+#endif
+
+void silk_warped_LPC_analysis_filter_FIX_sse4_1(
+ opus_int32 state[], /* I/O State [order + 1] */
+ opus_int32 res_Q2[], /* O Residual signal [length] */
+ const opus_int16 coef_Q13[], /* I Coefficients [order] */
+ const opus_int16 input[], /* I Input signal [length] */
+ const opus_int16 lambda_Q16, /* I Warping factor */
+ const opus_int length, /* I Length of input signal */
+ const opus_int order /* I Filter order (even) */
+);
+
+#if defined(OPUS_X86_PRESUME_SSE4_1)
+#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
+ ((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
+
+#else
+
+extern void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[OPUS_ARCHMASK + 1])(
+ opus_int32 state[], /* I/O State [order + 1] */
+ opus_int32 res_Q2[], /* O Residual signal [length] */
+ const opus_int16 coef_Q13[], /* I Coefficients [order] */
+ const opus_int16 input[], /* I Input signal [length] */
+ const opus_int16 lambda_Q16, /* I Warping factor */
+ const opus_int length, /* I Length of input signal */
+ const opus_int order /* I Filter order (even) */
+);
+
+# define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
+ ((*SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[(arch) & OPUS_ARCHMASK])(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
+
#endif
# endif
diff --git a/thirdparty/opus/silk/x86/x86_silk_map.c b/thirdparty/opus/silk/x86/x86_silk_map.c
index 32dcc3cab7..818841f2c1 100644
--- a/thirdparty/opus/silk/x86/x86_silk_map.c
+++ b/thirdparty/opus/silk/x86/x86_silk_map.c
@@ -66,9 +66,8 @@ opus_int (*const SILK_VAD_GETSA_Q8_IMPL[ OPUS_ARCHMASK + 1 ] )(
MAY_HAVE_SSE4_1( silk_VAD_GetSA_Q8 ) /* avx */
};
-#if 0 /* FIXME: SSE disabled until the NSQ code gets updated. */
void (*const SILK_NSQ_IMPL[ OPUS_ARCHMASK + 1 ] )(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
@@ -90,9 +89,7 @@ void (*const SILK_NSQ_IMPL[ OPUS_ARCHMASK + 1 ] )(
MAY_HAVE_SSE4_1( silk_NSQ ), /* sse4.1 */
MAY_HAVE_SSE4_1( silk_NSQ ) /* avx */
};
-#endif
-#if 0 /* FIXME: SSE disabled until silk_VQ_WMat_EC_sse4_1() gets updated. */
void (*const SILK_VQ_WMAT_EC_IMPL[ OPUS_ARCHMASK + 1 ] )(
opus_int8 *ind, /* O index of best codebook vector */
opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */
@@ -112,11 +109,9 @@ void (*const SILK_VQ_WMAT_EC_IMPL[ OPUS_ARCHMASK + 1 ] )(
MAY_HAVE_SSE4_1( silk_VQ_WMat_EC ), /* sse4.1 */
MAY_HAVE_SSE4_1( silk_VQ_WMat_EC ) /* avx */
};
-#endif
-#if 0 /* FIXME: SSE disabled until the NSQ code gets updated. */
void (*const SILK_NSQ_DEL_DEC_IMPL[ OPUS_ARCHMASK + 1 ] )(
- const silk_encoder_state *psEncC, /* I Encoder State */
+ const silk_encoder_state *psEncC, /* I/O Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int32 x_Q3[], /* I Prefiltered input signal */
@@ -138,10 +133,25 @@ void (*const SILK_NSQ_DEL_DEC_IMPL[ OPUS_ARCHMASK + 1 ] )(
MAY_HAVE_SSE4_1( silk_NSQ_del_dec ), /* sse4.1 */
MAY_HAVE_SSE4_1( silk_NSQ_del_dec ) /* avx */
};
-#endif
#if defined(FIXED_POINT)
+void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[ OPUS_ARCHMASK + 1 ] )(
+ opus_int32 state[], /* I/O State [order + 1] */
+ opus_int32 res_Q2[], /* O Residual signal [length] */
+ const opus_int16 coef_Q13[], /* I Coefficients [order] */
+ const opus_int16 input[], /* I Input signal [length] */
+ const opus_int16 lambda_Q16, /* I Warping factor */
+ const opus_int length, /* I Length of input signal */
+ const opus_int order /* I Filter order (even) */
+) = {
+ silk_warped_LPC_analysis_filter_FIX_c, /* non-sse */
+ silk_warped_LPC_analysis_filter_FIX_c,
+ silk_warped_LPC_analysis_filter_FIX_c,
+ MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ), /* sse4.1 */
+ MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ) /* avx */
+};
+
void (*const SILK_BURG_MODIFIED_IMPL[ OPUS_ARCHMASK + 1 ] )(
opus_int32 *res_nrg, /* O Residual energy */
opus_int *res_nrg_Q, /* O Residual energy Q value */
diff --git a/thirdparty/opus/stream.c b/thirdparty/opus/stream.c
index 6a85197a66..0238a6b31b 100644
--- a/thirdparty/opus/stream.c
+++ b/thirdparty/opus/stream.c
@@ -235,7 +235,8 @@ void *op_fopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode){
fp=fopen(_path,_mode);
#else
fp=NULL;
- {
+ if(_path==NULL||_mode==NULL)errno=EINVAL;
+ else{
wchar_t *wpath;
wchar_t *wmode;
wpath=op_utf8_to_utf16(_path);
@@ -265,7 +266,8 @@ void *op_freopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode,
fp=freopen(_path,_mode,(FILE *)_stream);
#else
fp=NULL;
- {
+ if(_path==NULL||_mode==NULL)errno=EINVAL;
+ else{
wchar_t *wpath;
wchar_t *wmode;
wpath=op_utf8_to_utf16(_path);
diff --git a/thirdparty/pcre2/src/config.h b/thirdparty/pcre2/src/config.h
index 25d45eeb38..787bb9c999 100644
--- a/thirdparty/pcre2/src/config.h
+++ b/thirdparty/pcre2/src/config.h
@@ -218,7 +218,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_NAME "PCRE2"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "PCRE2 10.33"
+#define PACKAGE_STRING "PCRE2 10.34"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre2"
@@ -227,7 +227,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "10.33"
+#define PACKAGE_VERSION "10.34"
/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
parentheses (of any kind) in a pattern. This limits the amount of system
@@ -352,7 +352,7 @@ sure both macros are undefined; an emulation function will then be used. */
#endif
/* Version number of package */
-#define VERSION "10.33"
+#define VERSION "10.34"
/* Define to 1 if on MINIX. */
/* #undef _MINIX */
diff --git a/thirdparty/pcre2/src/pcre2.h b/thirdparty/pcre2/src/pcre2.h
index 102b5d91f1..cb9d61a35b 100644
--- a/thirdparty/pcre2/src/pcre2.h
+++ b/thirdparty/pcre2/src/pcre2.h
@@ -5,7 +5,7 @@
/* This is the public header file for the PCRE library, second API, to be
#included by applications that call PCRE2 functions.
- Copyright (c) 2016-2018 University of Cambridge
+ Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE2_MAJOR 10
-#define PCRE2_MINOR 33
+#define PCRE2_MINOR 34
#define PCRE2_PRERELEASE
-#define PCRE2_DATE 2019-04-16
+#define PCRE2_DATE 2019-11-21
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE2, the appropriate
@@ -142,6 +142,7 @@ D is inspected during pcre2_dfa_match() execution
#define PCRE2_USE_OFFSET_LIMIT 0x00800000u /* J M D */
#define PCRE2_EXTENDED_MORE 0x01000000u /* C */
#define PCRE2_LITERAL 0x02000000u /* C */
+#define PCRE2_MATCH_INVALID_UTF 0x04000000u /* J M D */
/* An additional compile options word is available in the compile context. */
@@ -305,6 +306,8 @@ pcre2_pattern_convert(). */
#define PCRE2_ERROR_INVALID_HYPHEN_IN_OPTIONS 194
#define PCRE2_ERROR_ALPHA_ASSERTION_UNKNOWN 195
#define PCRE2_ERROR_SCRIPT_RUN_NOT_AVAILABLE 196
+#define PCRE2_ERROR_TOO_MANY_CAPTURES 197
+#define PCRE2_ERROR_CONDITION_ATOMIC_ASSERTION_EXPECTED 198
/* "Expected" matching error codes: no match and partial match. */
@@ -390,6 +393,7 @@ released, the numbers must not be changed. */
#define PCRE2_ERROR_HEAPLIMIT (-63)
#define PCRE2_ERROR_CONVERT_SYNTAX (-64)
#define PCRE2_ERROR_INTERNAL_DUPMATCH (-65)
+#define PCRE2_ERROR_DFA_UINVALID_UTF (-66)
/* Request types for pcre2_pattern_info() */
@@ -580,7 +584,7 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_bsr(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
- pcre2_set_character_tables(pcre2_compile_context *, const unsigned char *); \
+ pcre2_set_character_tables(pcre2_compile_context *, const uint8_t *); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_compile_extra_options(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
@@ -675,6 +679,8 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
pcre2_match_data_free(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SPTR PCRE2_CALL_CONVENTION \
pcre2_get_mark(pcre2_match_data *); \
+PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
+ pcre2_get_match_data_size(pcre2_match_data *); \
PCRE2_EXP_DECL uint32_t PCRE2_CALL_CONVENTION \
pcre2_get_ovector_count(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
@@ -773,7 +779,8 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_get_error_message(int, PCRE2_UCHAR *, PCRE2_SIZE); \
PCRE2_EXP_DECL const uint8_t PCRE2_CALL_CONVENTION \
*pcre2_maketables(pcre2_general_context *); \
-
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_maketables_free(pcre2_general_context *, const uint8_t *);
/* Define macros that generate width-specific names from generic versions. The
three-level macro scheme is necessary to get the macros expanded when we want
@@ -838,6 +845,7 @@ pcre2_compile are called by application code. */
#define pcre2_general_context_free PCRE2_SUFFIX(pcre2_general_context_free_)
#define pcre2_get_error_message PCRE2_SUFFIX(pcre2_get_error_message_)
#define pcre2_get_mark PCRE2_SUFFIX(pcre2_get_mark_)
+#define pcre2_get_match_data_size PCRE2_SUFFIX(pcre2_get_match_data_size_)
#define pcre2_get_ovector_pointer PCRE2_SUFFIX(pcre2_get_ovector_pointer_)
#define pcre2_get_ovector_count PCRE2_SUFFIX(pcre2_get_ovector_count_)
#define pcre2_get_startchar PCRE2_SUFFIX(pcre2_get_startchar_)
@@ -848,6 +856,7 @@ pcre2_compile are called by application code. */
#define pcre2_jit_stack_create PCRE2_SUFFIX(pcre2_jit_stack_create_)
#define pcre2_jit_stack_free PCRE2_SUFFIX(pcre2_jit_stack_free_)
#define pcre2_maketables PCRE2_SUFFIX(pcre2_maketables_)
+#define pcre2_maketables_free PCRE2_SUFFIX(pcre2_maketables_free_)
#define pcre2_match PCRE2_SUFFIX(pcre2_match_)
#define pcre2_match_context_copy PCRE2_SUFFIX(pcre2_match_context_copy_)
#define pcre2_match_context_create PCRE2_SUFFIX(pcre2_match_context_create_)
diff --git a/thirdparty/pcre2/src/pcre2_auto_possess.c b/thirdparty/pcre2/src/pcre2_auto_possess.c
index 6d7b7c4a4d..5b95b9b8a8 100644
--- a/thirdparty/pcre2/src/pcre2_auto_possess.c
+++ b/thirdparty/pcre2/src/pcre2_auto_possess.c
@@ -624,6 +624,13 @@ for(;;)
case OP_ASSERTBACK_NOT:
case OP_ONCE:
return !entered_a_group;
+
+ /* Non-atomic assertions - don't possessify last iterator. This needs
+ more thought. */
+
+ case OP_ASSERT_NA:
+ case OP_ASSERTBACK_NA:
+ return FALSE;
}
/* Skip over the bracket and inspect what comes next. */
diff --git a/thirdparty/pcre2/src/pcre2_compile.c b/thirdparty/pcre2/src/pcre2_compile.c
index 068735ae8e..f2e6b6b5bd 100644
--- a/thirdparty/pcre2/src/pcre2_compile.c
+++ b/thirdparty/pcre2/src/pcre2_compile.c
@@ -135,6 +135,9 @@ static BOOL
set_lookbehind_lengths(uint32_t **, int *, int *, parsed_recurse_check *,
compile_block *);
+static int
+ check_lookbehinds(uint32_t *, uint32_t **, parsed_recurse_check *,
+ compile_block *);
/*************************************************
@@ -250,36 +253,41 @@ is present where expected in a conditional group. */
#define META_LOOKBEHIND 0x80250000u /* (?<= */
#define META_LOOKBEHINDNOT 0x80260000u /* (?<! */
+/* These cannot be conditions */
+
+#define META_LOOKAHEAD_NA 0x80270000u /* (*napla: */
+#define META_LOOKBEHIND_NA 0x80280000u /* (*naplb: */
+
/* These must be kept in this order, with consecutive values, and the _ARG
versions of COMMIT, PRUNE, SKIP, and THEN immediately after their non-argument
versions. */
-#define META_MARK 0x80270000u /* (*MARK) */
-#define META_ACCEPT 0x80280000u /* (*ACCEPT) */
-#define META_FAIL 0x80290000u /* (*FAIL) */
-#define META_COMMIT 0x802a0000u /* These */
-#define META_COMMIT_ARG 0x802b0000u /* pairs */
-#define META_PRUNE 0x802c0000u /* must */
-#define META_PRUNE_ARG 0x802d0000u /* be */
-#define META_SKIP 0x802e0000u /* kept */
-#define META_SKIP_ARG 0x802f0000u /* in */
-#define META_THEN 0x80300000u /* this */
-#define META_THEN_ARG 0x80310000u /* order */
+#define META_MARK 0x80290000u /* (*MARK) */
+#define META_ACCEPT 0x802a0000u /* (*ACCEPT) */
+#define META_FAIL 0x802b0000u /* (*FAIL) */
+#define META_COMMIT 0x802c0000u /* These */
+#define META_COMMIT_ARG 0x802d0000u /* pairs */
+#define META_PRUNE 0x802e0000u /* must */
+#define META_PRUNE_ARG 0x802f0000u /* be */
+#define META_SKIP 0x80300000u /* kept */
+#define META_SKIP_ARG 0x80310000u /* in */
+#define META_THEN 0x80320000u /* this */
+#define META_THEN_ARG 0x80330000u /* order */
/* These must be kept in groups of adjacent 3 values, and all together. */
-#define META_ASTERISK 0x80320000u /* * */
-#define META_ASTERISK_PLUS 0x80330000u /* *+ */
-#define META_ASTERISK_QUERY 0x80340000u /* *? */
-#define META_PLUS 0x80350000u /* + */
-#define META_PLUS_PLUS 0x80360000u /* ++ */
-#define META_PLUS_QUERY 0x80370000u /* +? */
-#define META_QUERY 0x80380000u /* ? */
-#define META_QUERY_PLUS 0x80390000u /* ?+ */
-#define META_QUERY_QUERY 0x803a0000u /* ?? */
-#define META_MINMAX 0x803b0000u /* {n,m} repeat */
-#define META_MINMAX_PLUS 0x803c0000u /* {n,m}+ repeat */
-#define META_MINMAX_QUERY 0x803d0000u /* {n,m}? repeat */
+#define META_ASTERISK 0x80340000u /* * */
+#define META_ASTERISK_PLUS 0x80350000u /* *+ */
+#define META_ASTERISK_QUERY 0x80360000u /* *? */
+#define META_PLUS 0x80370000u /* + */
+#define META_PLUS_PLUS 0x80380000u /* ++ */
+#define META_PLUS_QUERY 0x80390000u /* +? */
+#define META_QUERY 0x803a0000u /* ? */
+#define META_QUERY_PLUS 0x803b0000u /* ?+ */
+#define META_QUERY_QUERY 0x803c0000u /* ?? */
+#define META_MINMAX 0x803d0000u /* {n,m} repeat */
+#define META_MINMAX_PLUS 0x803e0000u /* {n,m}+ repeat */
+#define META_MINMAX_QUERY 0x803f0000u /* {n,m}? repeat */
#define META_FIRST_QUANTIFIER META_ASTERISK
#define META_LAST_QUANTIFIER META_MINMAX_QUERY
@@ -335,6 +343,8 @@ static unsigned char meta_extra_lengths[] = {
0, /* META_LOOKAHEADNOT */
SIZEOFFSET, /* META_LOOKBEHIND */
SIZEOFFSET, /* META_LOOKBEHINDNOT */
+ 0, /* META_LOOKAHEAD_NA */
+ SIZEOFFSET, /* META_LOOKBEHIND_NA */
1, /* META_MARK - plus the string length */
0, /* META_ACCEPT */
0, /* META_FAIL */
@@ -634,10 +644,14 @@ typedef struct alasitem {
static const char alasnames[] =
STRING_pla0
STRING_plb0
+ STRING_napla0
+ STRING_naplb0
STRING_nla0
STRING_nlb0
STRING_positive_lookahead0
STRING_positive_lookbehind0
+ STRING_non_atomic_positive_lookahead0
+ STRING_non_atomic_positive_lookbehind0
STRING_negative_lookahead0
STRING_negative_lookbehind0
STRING_atomic0
@@ -649,10 +663,14 @@ static const char alasnames[] =
static const alasitem alasmeta[] = {
{ 3, META_LOOKAHEAD },
{ 3, META_LOOKBEHIND },
+ { 5, META_LOOKAHEAD_NA },
+ { 5, META_LOOKBEHIND_NA },
{ 3, META_LOOKAHEADNOT },
{ 3, META_LOOKBEHINDNOT },
{ 18, META_LOOKAHEAD },
{ 19, META_LOOKBEHIND },
+ { 29, META_LOOKAHEAD_NA },
+ { 30, META_LOOKBEHIND_NA },
{ 18, META_LOOKAHEADNOT },
{ 19, META_LOOKBEHINDNOT },
{ 6, META_ATOMIC },
@@ -746,8 +764,8 @@ are allowed. */
#define PUBLIC_LITERAL_COMPILE_OPTIONS \
(PCRE2_ANCHORED|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_ENDANCHORED| \
- PCRE2_FIRSTLINE|PCRE2_LITERAL|PCRE2_NO_START_OPTIMIZE| \
- PCRE2_NO_UTF_CHECK|PCRE2_USE_OFFSET_LIMIT|PCRE2_UTF)
+ PCRE2_FIRSTLINE|PCRE2_LITERAL|PCRE2_MATCH_INVALID_UTF| \
+ PCRE2_NO_START_OPTIMIZE|PCRE2_NO_UTF_CHECK|PCRE2_USE_OFFSET_LIMIT|PCRE2_UTF)
#define PUBLIC_COMPILE_OPTIONS \
(PUBLIC_LITERAL_COMPILE_OPTIONS| \
@@ -781,7 +799,7 @@ enum { ERR0 = COMPILE_ERROR_BASE,
ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70,
ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80,
ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90,
- ERR91, ERR92, ERR93, ERR94, ERR95, ERR96 };
+ ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98 };
/* This is a table of start-of-pattern options such as (*UTF) and settings such
as (*LIMIT_MATCH=nnnn) and (*CRLF). For completeness and backward
@@ -1012,6 +1030,7 @@ for (;;)
case META_NOCAPTURE: fprintf(stderr, "META (?:"); break;
case META_LOOKAHEAD: fprintf(stderr, "META (?="); break;
case META_LOOKAHEADNOT: fprintf(stderr, "META (?!"); break;
+ case META_LOOKAHEAD_NA: fprintf(stderr, "META (*napla:"); break;
case META_SCRIPT_RUN: fprintf(stderr, "META (*sr:"); break;
case META_KET: fprintf(stderr, "META )"); break;
case META_ALT: fprintf(stderr, "META | %d", meta_arg); break;
@@ -1043,6 +1062,12 @@ for (;;)
fprintf(stderr, "%zd", offset);
break;
+ case META_LOOKBEHIND_NA:
+ fprintf(stderr, "META (*naplb: %d offset=", meta_arg);
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd", offset);
+ break;
+
case META_LOOKBEHINDNOT:
fprintf(stderr, "META (?<! %d offset=", meta_arg);
GETOFFSET(offset, pptr);
@@ -1419,9 +1444,6 @@ the result is "not a repeat quantifier". */
EXIT:
if (yield || *errorcodeptr != 0) *ptrptr = p;
return yield;
-
-
-
}
@@ -2450,8 +2472,9 @@ must be last. */
enum { RANGE_NO, RANGE_STARTED, RANGE_OK_ESCAPED, RANGE_OK_LITERAL };
-/* Only in 32-bit mode can there be literals > META_END. A macros encapsulates
-the storing of literal values in the parsed pattern. */
+/* Only in 32-bit mode can there be literals > META_END. A macro encapsulates
+the storing of literal values in the main parsed pattern, where they can always
+be quantified. */
#if PCRE2_CODE_UNIT_WIDTH == 32
#define PARSED_LITERAL(c, p) \
@@ -2474,6 +2497,7 @@ uint32_t delimiter;
uint32_t namelen;
uint32_t class_range_state;
uint32_t *verblengthptr = NULL; /* Value avoids compiler warning */
+uint32_t *verbstartptr = NULL;
uint32_t *previous_callout = NULL;
uint32_t *parsed_pattern = cb->parsed_pattern;
uint32_t *parsed_pattern_end = cb->parsed_pattern_end;
@@ -2600,10 +2624,20 @@ while (ptr < ptrend)
errorcode = ERR28;
goto FAILED;
}
- if (!inverbname && after_manual_callout-- <= 0)
- parsed_pattern = manage_callouts(thisptr, &previous_callout,
- auto_callout, parsed_pattern, cb);
- PARSED_LITERAL(c, parsed_pattern);
+ if (inverbname)
+ { /* Don't use PARSED_LITERAL() because it */
+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */
+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;
+#endif
+ *parsed_pattern++ = c;
+ }
+ else
+ {
+ if (after_manual_callout-- <= 0)
+ parsed_pattern = manage_callouts(thisptr, &previous_callout,
+ auto_callout, parsed_pattern, cb);
+ PARSED_LITERAL(c, parsed_pattern);
+ }
meta_quantifier = 0;
}
continue; /* Next character */
@@ -2640,13 +2674,15 @@ while (ptr < ptrend)
switch(c)
{
- default:
- PARSED_LITERAL(c, parsed_pattern);
+ default: /* Don't use PARSED_LITERAL() because it */
+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */
+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;
+#endif
+ *parsed_pattern++ = c;
break;
case CHAR_RIGHT_PARENTHESIS:
inverbname = FALSE;
- okquantifier = FALSE; /* Was probably set by literals */
/* This is the length in characters */
verbnamelength = (PCRE2_SIZE)(parsed_pattern - verblengthptr - 1);
/* But the limit on the length is in code units */
@@ -2680,8 +2716,11 @@ while (ptr < ptrend)
switch(escape)
{
- case 0:
- PARSED_LITERAL(c, parsed_pattern);
+ case 0: /* Don't use PARSED_LITERAL() because it */
+#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */
+ if (c >= META_END) *parsed_pattern++ = META_BIGVALUE;
+#endif
+ *parsed_pattern++ = c;
break;
case ESC_Q:
@@ -3135,6 +3174,21 @@ while (ptr < ptrend)
goto FAILED_BACK;
}
+ /* Most (*VERB)s are not allowed to be quantified, but an ungreedy
+ quantifier can be useful for (*ACCEPT) - meaning "succeed on backtrack", a
+ sort of negated (*COMMIT). We therefore allow (*ACCEPT) to be quantified by
+ wrapping it in non-capturing brackets, but we have to allow for a preceding
+ (*MARK) for when (*ACCEPT) has an argument. */
+
+ if (parsed_pattern[-1] == META_ACCEPT)
+ {
+ uint32_t *p;
+ for (p = parsed_pattern - 1; p >= verbstartptr; p--) p[1] = p[0];
+ *verbstartptr = META_NOCAPTURE;
+ parsed_pattern[1] = META_KET;
+ parsed_pattern += 2;
+ }
+
/* Now we can put the quantifier into the parsed pattern vector. At this
stage, we have only the basic quantifier. The check for a following + or ?
modifier happens at the top of the loop, after any intervening comments
@@ -3581,6 +3635,8 @@ while (ptr < ptrend)
if (c == CHAR_RIGHT_SQUARE_BRACKET && !inescq) break;
} /* End of class-processing loop */
+ /* -] at the end of a class is a literal '-' */
+
if (class_range_state == RANGE_STARTED)
{
parsed_pattern[-1] = CHAR_MINUS;
@@ -3611,6 +3667,11 @@ while (ptr < ptrend)
nest_depth++;
if ((options & PCRE2_NO_AUTO_CAPTURE) == 0)
{
+ if (cb->bracount >= MAX_GROUP_NUMBER)
+ {
+ errorcode = ERR97;
+ goto FAILED;
+ }
cb->bracount++;
*parsed_pattern++ = META_CAPTURE | cb->bracount;
}
@@ -3658,19 +3719,20 @@ while (ptr < ptrend)
goto FAILED;
}
- /* Check for expecting an assertion condition. If so, only lookaround
- assertions are valid. */
+ /* Check for expecting an assertion condition. If so, only atomic
+ lookaround assertions are valid. */
meta = alasmeta[i].meta;
if (prev_expect_cond_assert > 0 &&
(meta < META_LOOKAHEAD || meta > META_LOOKBEHINDNOT))
{
- errorcode = ERR28; /* Assertion expected */
+ errorcode = (meta == META_LOOKAHEAD_NA || meta == META_LOOKBEHIND_NA)?
+ ERR98 : ERR28; /* (Atomic) assertion expected */
goto FAILED;
}
- /* The lookaround alphabetic synonyms can be almost entirely handled by
- jumping to the code that handles the traditional symbolic forms. */
+ /* The lookaround alphabetic synonyms can mostly be handled by jumping
+ to the code that handles the traditional symbolic forms. */
switch(meta)
{
@@ -3684,11 +3746,17 @@ while (ptr < ptrend)
case META_LOOKAHEAD:
goto POSITIVE_LOOK_AHEAD;
+ case META_LOOKAHEAD_NA:
+ *parsed_pattern++ = meta;
+ ptr++;
+ goto POST_ASSERTION;
+
case META_LOOKAHEADNOT:
goto NEGATIVE_LOOK_AHEAD;
case META_LOOKBEHIND:
case META_LOOKBEHINDNOT:
+ case META_LOOKBEHIND_NA:
*parsed_pattern++ = meta;
ptr--;
goto POST_LOOKBEHIND;
@@ -3770,6 +3838,12 @@ while (ptr < ptrend)
goto FAILED;
}
+ /* Remember where this verb, possibly with a preceding (*MARK), starts,
+ for handling quantified (*ACCEPT). */
+
+ verbstartptr = parsed_pattern;
+ okquantifier = (verbs[i].meta == META_ACCEPT);
+
/* It appears that Perl allows any characters whatsoever, other than a
closing parenthesis, to appear in arguments ("names"), so we no longer
insist on letters, digits, and underscores. Perl does not, however, do
@@ -4386,7 +4460,7 @@ while (ptr < ptrend)
*parsed_pattern++ = (ptr[1] == CHAR_EQUALS_SIGN)?
META_LOOKBEHIND : META_LOOKBEHINDNOT;
- POST_LOOKBEHIND: /* Come from (*plb: and (*nlb: */
+ POST_LOOKBEHIND: /* Come from (*plb: (*naplb: and (*nlb: */
*has_lookbehind = TRUE;
offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2);
PUTOFFSET(offset, parsed_pattern);
@@ -4435,6 +4509,11 @@ while (ptr < ptrend)
/* We have a name for this capturing group. It is also assigned a number,
which is its primary means of identification. */
+ if (cb->bracount >= MAX_GROUP_NUMBER)
+ {
+ errorcode = ERR97;
+ goto FAILED;
+ }
cb->bracount++;
*parsed_pattern++ = META_CAPTURE | cb->bracount;
nest_depth++;
@@ -4661,6 +4740,7 @@ for (;;)
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
+ case OP_ASSERTBACK_NA:
if (!skipassert) return code;
do code += GET(code, 1); while (*code == OP_ALT);
code += PRIV(OP_lengths)[*code];
@@ -5221,8 +5301,10 @@ PCRE2_UCHAR *tempcode;
PCRE2_UCHAR *previous = NULL;
PCRE2_UCHAR op_previous;
BOOL groupsetfirstcu = FALSE;
+BOOL had_accept = FALSE;
BOOL matched_char = FALSE;
BOOL previous_matched_char = FALSE;
+BOOL reset_caseful = FALSE;
const uint8_t *cbits = cb->cbits;
uint8_t classbits[32];
@@ -5355,7 +5437,7 @@ for (;; pptr++)
if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)
{
previous = code;
- if (matched_char) okreturn = 1;
+ if (matched_char && !had_accept) okreturn = 1;
}
previous_matched_char = matched_char;
@@ -5499,7 +5581,45 @@ for (;; pptr++)
} /* End of 1-char optimization */
/* Handle character classes that contain more than just one literal
- character. */
+ character. If there are exactly two characters in a positive class, see if
+ they are case partners. This can be optimized to generate a caseless single
+ character match (which also sets first/required code units if relevant). */
+
+ if (meta == META_CLASS && pptr[1] < META_END && pptr[2] < META_END &&
+ pptr[3] == META_CLASS_END)
+ {
+ uint32_t c = pptr[1];
+
+#ifdef SUPPORT_UNICODE
+ if (UCD_CASESET(c) == 0)
+#endif
+ {
+ uint32_t d;
+
+#ifdef SUPPORT_UNICODE
+ if (utf && c > 127) d = UCD_OTHERCASE(c); else
+#endif
+ {
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ if (c > 255) d = c; else
+#endif
+ d = TABLE_GET(c, cb->fcc, c);
+ }
+
+ if (c != d && pptr[2] == d)
+ {
+ pptr += 3; /* Move on to class end */
+ meta = c;
+ if ((options & PCRE2_CASELESS) == 0)
+ {
+ reset_caseful = TRUE;
+ options |= PCRE2_CASELESS;
+ req_caseopt = REQ_CASELESS;
+ }
+ goto CLASS_CASELESS_CHAR;
+ }
+ }
+ }
/* If a non-extended class contains a negative special such as \S, we need
to flip the negation flag at the end, so that support for characters > 255
@@ -5994,7 +6114,7 @@ for (;; pptr++)
workspace overflow. Do not set firstcu after *ACCEPT. */
case META_ACCEPT:
- cb->had_accept = TRUE;
+ cb->had_accept = had_accept = TRUE;
for (oc = cb->open_caps;
oc != NULL && oc->assert_depth >= cb->assert_depth;
oc = oc->next)
@@ -6252,6 +6372,11 @@ for (;; pptr++)
cb->assert_depth += 1;
goto GROUP_PROCESS;
+ case META_LOOKAHEAD_NA:
+ bravalue = OP_ASSERT_NA;
+ cb->assert_depth += 1;
+ goto GROUP_PROCESS;
+
/* Optimize (?!) to (*FAIL) unless it is quantified - which is a weird
thing to do, but Perl allows all assertions to be quantified, and when
they contain capturing parentheses there may be a potential use for
@@ -6283,6 +6408,11 @@ for (;; pptr++)
cb->assert_depth += 1;
goto GROUP_PROCESS;
+ case META_LOOKBEHIND_NA:
+ bravalue = OP_ASSERTBACK_NA;
+ cb->assert_depth += 1;
+ goto GROUP_PROCESS;
+
case META_ATOMIC:
bravalue = OP_ONCE;
goto GROUP_PROCESS_NOTE_EMPTY;
@@ -6341,7 +6471,7 @@ for (;; pptr++)
/* If we've just compiled an assertion, pop the assert depth. */
- if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT)
+ if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NA)
cb->assert_depth -= 1;
/* At the end of compiling, code is still pointing to the start of the
@@ -6491,8 +6621,8 @@ for (;; pptr++)
we must only take the reqcu when the group also set a firstcu. Otherwise,
in that example, 'X' ends up set for both. */
- else if (bravalue == OP_ASSERT && subreqcuflags >= 0 &&
- subfirstcuflags >= 0)
+ else if ((bravalue == OP_ASSERT || bravalue == OP_ASSERT_NA) &&
+ subreqcuflags >= 0 && subfirstcuflags >= 0)
{
reqcu = subreqcu;
reqcuflags = subreqcuflags;
@@ -6713,10 +6843,6 @@ for (;; pptr++)
reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY;
op_type = 0;
- /* If the repeat is {1} we can ignore it. */
-
- if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;
-
/* Adjust first and required code units for a zero repeat. */
if (repeat_min == 0)
@@ -6759,7 +6885,10 @@ for (;; pptr++)
tempcode = previous;
op_previous = *previous;
- /* Now handle repetition for the different types of item. */
+ /* Now handle repetition for the different types of item. If the repeat
+ minimum and the repeat maximum are both 1, we can ignore the quantifier for
+ non-parenthesized items, as they have only one alternative. For anything in
+ parentheses, we must not ignore if {1} is possessive. */
switch (op_previous)
{
@@ -6773,6 +6902,7 @@ for (;; pptr++)
case OP_CHARI:
case OP_NOT:
case OP_NOTI:
+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;
op_type = chartypeoffset[op_previous - OP_CHAR];
/* Deal with UTF characters that take up more than one code unit. */
@@ -6819,6 +6949,7 @@ for (;; pptr++)
code = previous;
goto END_REPEAT;
}
+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;
if (repeat_min == 0 && repeat_max == REPEAT_UNLIMITED)
*code++ = OP_CRSTAR + repeat_type;
@@ -6853,6 +6984,8 @@ for (;; pptr++)
repetition. */
case OP_RECURSE:
+ if (repeat_max == 1 && repeat_min == 1 && !possessive_quantifier)
+ goto END_REPEAT;
/* Generate unwrapped repeats for a non-zero minimum, except when the
minimum is 1 and the maximum unlimited, because that can be handled with
@@ -6923,8 +7056,10 @@ for (;; pptr++)
case OP_ASSERT:
case OP_ASSERT_NOT:
+ case OP_ASSERT_NA:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
+ case OP_ASSERTBACK_NA:
case OP_ONCE:
case OP_SCRIPT_RUN:
case OP_BRA:
@@ -6935,6 +7070,9 @@ for (;; pptr++)
PCRE2_UCHAR *bralink = NULL;
PCRE2_UCHAR *brazeroptr = NULL;
+ if (repeat_max == 1 && repeat_min == 1 && !possessive_quantifier)
+ goto END_REPEAT;
+
/* Repeating a DEFINE group (or any group where the condition is always
FALSE and there is only one branch) is pointless, but Perl allows the
syntax, so we just ignore the repeat. */
@@ -7151,11 +7289,12 @@ for (;; pptr++)
and SCRIPT_RUN groups at runtime, but in a different way.]
Then, if the quantifier was possessive and the bracket is not a
- conditional, we convert the BRA code to the POS form, and the KET code to
- KETRPOS. (It turns out to be convenient at runtime to detect this kind of
- subpattern at both the start and at the end.) The use of special opcodes
- makes it possible to reduce greatly the stack usage in pcre2_match(). If
- the group is preceded by OP_BRAZERO, convert this to OP_BRAPOSZERO.
+ conditional, we convert the BRA code to the POS form, and the KET code
+ to KETRPOS. (It turns out to be convenient at runtime to detect this
+ kind of subpattern at both the start and at the end.) The use of
+ special opcodes makes it possible to reduce greatly the stack usage in
+ pcre2_match(). If the group is preceded by OP_BRAZERO, convert this to
+ OP_BRAPOSZERO.
Then, if the minimum number of matches is 1 or 0, cancel the possessive
flag so that the default action below, of wrapping everything inside
@@ -7256,6 +7395,8 @@ for (;; pptr++)
int prop_type, prop_value;
PCRE2_UCHAR *oldcode;
+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;
+
op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
mclength = 0; /* Not a character */
@@ -7718,9 +7859,15 @@ for (;; pptr++)
}
#endif
- /* Caseful matches, or not one of the multicase characters. Get the
- character's code units into mcbuffer, with the length in mclength. When not
- in UTF mode, the length is always 1. */
+ /* Caseful matches, or caseless and not one of the multicase characters. We
+ come here by goto in the case of a positive class that contains only
+ case-partners of a character with just two cases; matched_char has already
+ been set TRUE and options fudged if necessary. */
+
+ CLASS_CASELESS_CHAR:
+
+ /* Get the character's code units into mcbuffer, with the length in
+ mclength. When not in UTF mode, the length is always 1. */
#ifdef SUPPORT_UNICODE
if (utf) mclength = PRIV(ord2utf)(meta, mcbuffer); else
@@ -7752,8 +7899,9 @@ for (;; pptr++)
zeroreqcu = reqcu;
zeroreqcuflags = reqcuflags;
- /* If the character is more than one code unit long, we can set firstcu
- only if it is not to be matched caselessly. */
+ /* If the character is more than one code unit long, we can set a single
+ firstcu only if it is not to be matched caselessly. Multiple possible
+ starting code units may be picked up later in the studying code. */
if (mclength == 1 || req_caseopt == 0)
{
@@ -7783,7 +7931,17 @@ for (;; pptr++)
reqcuflags = req_caseopt | cb->req_varyopt;
}
}
- break; /* End default meta handling */
+
+ /* If caselessness was temporarily instated, reset it. */
+
+ if (reset_caseful)
+ {
+ options &= ~PCRE2_CASELESS;
+ req_caseopt = 0;
+ reset_caseful = FALSE;
+ }
+
+ break; /* End literal character handling */
} /* End of big switch */
} /* End of big loop */
@@ -7874,7 +8032,10 @@ length = 2 + 2*LINK_SIZE + skipunits;
/* Remember if this is a lookbehind assertion, and if it is, save its length
and skip over the pattern offset. */
-lookbehind = *code == OP_ASSERTBACK || *code == OP_ASSERTBACK_NOT;
+lookbehind = *code == OP_ASSERTBACK ||
+ *code == OP_ASSERTBACK_NOT ||
+ *code == OP_ASSERTBACK_NA;
+
if (lookbehind)
{
lookbehindlength = META_DATA(pptr[-1]);
@@ -7948,7 +8109,7 @@ for (;;)
/* If this is not the first branch, the first char and reqcu have to
match the values from all the previous branches, except that if the
previous value for reqcu didn't have REQ_VARY set, it can still match,
- and we set REQ_VARY for the regex. */
+ and we set REQ_VARY for the group from this branch's value. */
else
{
@@ -7987,7 +8148,7 @@ for (;;)
else
{
reqcu = branchreqcu;
- reqcuflags |= branchreqcuflags; /* To "or" REQ_VARY */
+ reqcuflags |= branchreqcuflags; /* To "or" REQ_VARY if present */
}
}
}
@@ -8167,7 +8328,7 @@ do {
/* Positive forward assertion */
- else if (op == OP_ASSERT)
+ else if (op == OP_ASSERT || op == OP_ASSERT_NA)
{
if (!is_anchored(scode, bracket_map, cb, atomcount, TRUE)) return FALSE;
}
@@ -8305,7 +8466,7 @@ do {
/* Positive forward assertions */
- else if (op == OP_ASSERT)
+ else if (op == OP_ASSERT || op == OP_ASSERT_NA)
{
if (!is_startline(scode, bracket_map, cb, atomcount, TRUE))
return FALSE;
@@ -8547,9 +8708,11 @@ do {
case OP_CBRAPOS:
case OP_SCBRAPOS:
case OP_ASSERT:
+ case OP_ASSERT_NA:
case OP_ONCE:
case OP_SCRIPT_RUN:
- d = find_firstassertedcu(scode, &dflags, inassert + ((op==OP_ASSERT)?1:0));
+ d = find_firstassertedcu(scode, &dflags, inassert +
+ ((op == OP_ASSERT || op == OP_ASSERT_NA)?1:0));
if (dflags < 0)
return 0;
if (cflags < 0) { c = d; cflags = dflags; }
@@ -8578,6 +8741,19 @@ do {
case OP_MINPLUSI:
case OP_POSPLUSI:
if (inassert == 0) return 0;
+
+ /* If the character is more than one code unit long, we cannot set its
+ first code unit when matching caselessly. Later scanning may pick up
+ multiple code units. */
+
+#ifdef SUPPORT_UNICODE
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (scode[1] >= 0x80) return 0;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+ if (scode[1] >= 0xd800 && scode[1] <= 0xdfff) return 0;
+#endif
+#endif
+
if (cflags < 0) { c = scode[1]; cflags = REQ_CASELESS; }
else if (c != scode[1]) return 0;
break;
@@ -8745,8 +8921,10 @@ for (;; pptr++)
case META_COND_VERSION:
case META_LOOKAHEAD:
case META_LOOKAHEADNOT:
+ case META_LOOKAHEAD_NA:
case META_LOOKBEHIND:
case META_LOOKBEHINDNOT:
+ case META_LOOKBEHIND_NA:
case META_NOCAPTURE:
case META_SCRIPT_RUN:
nestlevel++;
@@ -8798,7 +8976,7 @@ Returns: the group length or a negative number
static int
get_grouplength(uint32_t **pptrptr, BOOL isinline, int *errcodeptr, int *lcptr,
- int group, parsed_recurse_check *recurses, compile_block *cb)
+ int group, parsed_recurse_check *recurses, compile_block *cb)
{
int branchlength;
int grouplength = -1;
@@ -8847,8 +9025,7 @@ return -1;
*************************************************/
/* Return a fixed length for a branch in a lookbehind, giving an error if the
-length is not fixed. If any lookbehinds are encountered on the way, they get
-their length set. On entry, *pptrptr points to the first element inside the
+length is not fixed. On entry, *pptrptr points to the first element inside the
branch. On exit it is set to point to the ALT or KET.
Arguments:
@@ -8978,15 +9155,16 @@ for (;; pptr++)
}
break;
- /* Lookaheads can be ignored, but we must start the skip inside the group
- so that it isn't treated as a group within the branch. */
+ /* Lookaheads do not contribute to the length of this branch, but they may
+ contain lookbehinds within them whose lengths need to be set. */
case META_LOOKAHEAD:
case META_LOOKAHEADNOT:
- pptr = parsed_skip(pptr + 1, PSKIP_KET);
- if (pptr == NULL) goto PARSED_SKIP_FAILED;
+ case META_LOOKAHEAD_NA:
+ *errcodeptr = check_lookbehinds(pptr + 1, &pptr, recurses, cb);
+ if (*errcodeptr != 0) return -1;
- /* Also ignore any qualifiers that follow a lookahead assertion. */
+ /* Ignore any qualifiers that follow a lookahead assertion. */
switch (pptr[1])
{
@@ -9013,10 +9191,12 @@ for (;; pptr++)
}
break;
- /* Lookbehinds can be ignored, but must themselves be checked. */
+ /* A nested lookbehind does not contribute any length to this lookbehind,
+ but must itself be checked and have its lengths set. */
case META_LOOKBEHIND:
case META_LOOKBEHINDNOT:
+ case META_LOOKBEHIND_NA:
if (!set_lookbehind_lengths(&pptr, errcodeptr, lcptr, recurses, cb))
return -1;
break;
@@ -9178,8 +9358,26 @@ for (;; pptr++)
case META_MINMAX_QUERY:
if (pptr[1] == pptr[2])
{
- if (pptr[1] == 0) branchlength -= lastitemlength;
- else itemlength = (pptr[1] - 1) * lastitemlength;
+ switch(pptr[1])
+ {
+ case 0:
+ branchlength -= lastitemlength;
+ break;
+
+ case 1:
+ itemlength = 0;
+ break;
+
+ default: /* Check for integer overflow */
+ if (lastitemlength != 0 && /* Should not occur, but just in case */
+ INT_MAX/lastitemlength < pptr[1] - 1)
+ {
+ *errcodeptr = ERR87; /* Integer overflow; lookbehind too big */
+ return -1;
+ }
+ itemlength = (pptr[1] - 1) * lastitemlength;
+ break;
+ }
pptr += 2;
break;
}
@@ -9193,24 +9391,23 @@ for (;; pptr++)
return -1;
}
- /* Add the item length to the branchlength, and save it for use if the next
- thing is a quantifier. */
-
- branchlength += itemlength;
- lastitemlength = itemlength;
-
- /* Ensure that the length does not overflow the limit. */
+ /* Add the item length to the branchlength, checking for integer overflow and
+ for the branch length exceeding the limit. */
- if (branchlength > LOOKBEHIND_MAX)
+ if (INT_MAX - branchlength < (int)itemlength ||
+ (branchlength += itemlength) > LOOKBEHIND_MAX)
{
*errcodeptr = ERR87;
return -1;
}
+
+ /* Save this item length for use if the next item is a quantifier. */
+
+ lastitemlength = itemlength;
}
EXIT:
*pptrptr = pptr;
-if (branchlength > cb->max_lookbehind) cb->max_lookbehind = branchlength;
return branchlength;
PARSED_SKIP_FAILED:
@@ -9229,6 +9426,11 @@ branches. An error occurs if any branch does not have a fixed length that is
less than the maximum (65535). On exit, the pointer must be left on the final
ket.
+The function also maintains the max_lookbehind value. Any lookbehind branch
+that contains a nested lookbehind may actually look further back than the
+length of the branch. The additional amount is passed back from
+get_branchlength() as an "extra" value.
+
Arguments:
pptrptr pointer to pointer in the parsed pattern
errcodeptr pointer to error code
@@ -9262,6 +9464,7 @@ do
if (cb->erroroffset == PCRE2_UNSET) cb->erroroffset = offset;
return FALSE;
}
+ if (branchlength > cb->max_lookbehind) cb->max_lookbehind = branchlength;
*bptr |= branchlength; /* branchlength never more than 65535 */
bptr = *pptrptr;
}
@@ -9282,20 +9485,30 @@ set_lookbehind_lengths() for each one. At the start, the errorcode is zero and
the error offset is marked unset. The enables the functions above not to
override settings from deeper nestings.
-Arguments cb points to the compile block
-Returns: 0 on success, or an errorcode (cb->erroroffset will be set)
+This function is called recursively from get_branchlength() for lookaheads in
+order to process any lookbehinds that they may contain. It stops when it hits a
+non-nested closing parenthesis in this case, returning a pointer to it.
+
+Arguments
+ pptr points to where to start (start of pattern or start of lookahead)
+ retptr if not NULL, return the ket pointer here
+ recurses chain of recurse_check to catch mutual recursion
+ cb points to the compile block
+
+Returns: 0 on success, or an errorcode (cb->erroroffset will be set)
*/
static int
-check_lookbehinds(compile_block *cb)
+check_lookbehinds(uint32_t *pptr, uint32_t **retptr,
+ parsed_recurse_check *recurses, compile_block *cb)
{
-uint32_t *pptr;
int errorcode = 0;
int loopcount = 0;
+int nestlevel = 0;
cb->erroroffset = PCRE2_UNSET;
-for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
+for (; *pptr != META_END; pptr++)
{
if (*pptr < META_END) continue; /* Literal */
@@ -9309,14 +9522,31 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
pptr += 1;
break;
+ case META_KET:
+ if (--nestlevel < 0)
+ {
+ if (retptr != NULL) *retptr = pptr;
+ return 0;
+ }
+ break;
+
+ case META_ATOMIC:
+ case META_CAPTURE:
+ case META_COND_ASSERT:
+ case META_LOOKAHEAD:
+ case META_LOOKAHEADNOT:
+ case META_LOOKAHEAD_NA:
+ case META_NOCAPTURE:
+ case META_SCRIPT_RUN:
+ nestlevel++;
+ break;
+
case META_ACCEPT:
case META_ALT:
case META_ASTERISK:
case META_ASTERISK_PLUS:
case META_ASTERISK_QUERY:
- case META_ATOMIC:
case META_BACKREF:
- case META_CAPTURE:
case META_CIRCUMFLEX:
case META_CLASS:
case META_CLASS_EMPTY:
@@ -9324,14 +9554,9 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
case META_CLASS_END:
case META_CLASS_NOT:
case META_COMMIT:
- case META_COND_ASSERT:
case META_DOLLAR:
case META_DOT:
case META_FAIL:
- case META_KET:
- case META_LOOKAHEAD:
- case META_LOOKAHEADNOT:
- case META_NOCAPTURE:
case META_PLUS:
case META_PLUS_PLUS:
case META_PLUS_QUERY:
@@ -9341,7 +9566,6 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
case META_QUERY_QUERY:
case META_RANGE_ESCAPED:
case META_RANGE_LITERAL:
- case META_SCRIPT_RUN:
case META_SKIP:
case META_THEN:
break;
@@ -9351,13 +9575,22 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
break;
case META_BACKREF_BYNAME:
+ case META_RECURSE_BYNAME:
+ pptr += 1 + SIZEOFFSET;
+ break;
+
case META_COND_DEFINE:
case META_COND_NAME:
case META_COND_NUMBER:
case META_COND_RNAME:
case META_COND_RNUMBER:
- case META_RECURSE_BYNAME:
pptr += 1 + SIZEOFFSET;
+ nestlevel++;
+ break;
+
+ case META_COND_VERSION:
+ pptr += 3;
+ nestlevel++;
break;
case META_CALLOUT_STRING:
@@ -9378,7 +9611,6 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
break;
case META_CALLOUT_NUMBER:
- case META_COND_VERSION:
pptr += 3;
break;
@@ -9392,7 +9624,8 @@ for (pptr = cb->parsed_pattern; *pptr != META_END; pptr++)
case META_LOOKBEHIND:
case META_LOOKBEHINDNOT:
- if (!set_lookbehind_lengths(&pptr, &errorcode, &loopcount, NULL, cb))
+ case META_LOOKBEHIND_NA:
+ if (!set_lookbehind_lengths(&pptr, &errorcode, &loopcount, recurses, cb))
return errorcode;
break;
}
@@ -9494,6 +9727,10 @@ if (pattern == NULL)
if (ccontext == NULL)
ccontext = (pcre2_compile_context *)(&PRIV(default_compile_context));
+/* PCRE2_MATCH_INVALID_UTF implies UTF */
+
+if ((options & PCRE2_MATCH_INVALID_UTF) != 0) options |= PCRE2_UTF;
+
/* Check that all undefined public option bits are zero. */
if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0 ||
@@ -9672,7 +9909,7 @@ if ((options & PCRE2_LITERAL) == 0)
ptr += skipatstart;
-/* Can't support UTF or UCP unless PCRE2 has been compiled with UTF support. */
+/* Can't support UTF or UCP if PCRE2 was built without Unicode support. */
#ifndef SUPPORT_UNICODE
if ((cb.external_options & (PCRE2_UTF|PCRE2_UCP)) != 0)
@@ -9842,7 +10079,7 @@ lengths. */
if (has_lookbehind)
{
- errorcode = check_lookbehinds(&cb);
+ errorcode = check_lookbehinds(cb.parsed_pattern, NULL, NULL, &cb);
if (errorcode != 0) goto HAD_CB_ERROR;
}
@@ -9990,8 +10227,9 @@ re->max_lookbehind = cb.max_lookbehind;
if (cb.had_accept)
{
- reqcu = 0; /* Must disable after (*ACCEPT) */
+ reqcu = 0; /* Must disable after (*ACCEPT) */
reqcuflags = REQ_NONE;
+ re->flags |= PCRE2_HASACCEPT; /* Disables minimum length */
}
/* Fill in the final opcode and check for disastrous overflow. If no overflow,
@@ -10112,6 +10350,8 @@ unit. */
if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
{
+ int minminlength = 0; /* For minimal minlength from first/required CU */
+
/* If we do not have a first code unit, see if there is one that is asserted
(these are not saved during the compile because they can cause conflicts with
actual literals that follow). */
@@ -10119,12 +10359,14 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
if (firstcuflags < 0)
firstcu = find_firstassertedcu(codestart, &firstcuflags, 0);
- /* Save the data for a first code unit. */
+ /* Save the data for a first code unit. The existence of one means the
+ minimum length must be at least 1. */
if (firstcuflags >= 0)
{
re->first_codeunit = firstcu;
re->flags |= PCRE2_FIRSTSET;
+ minminlength++;
/* Handle caseless first code units. */
@@ -10158,39 +10400,72 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
is_startline(codestart, 0, &cb, 0, FALSE))
re->flags |= PCRE2_STARTLINE;
- /* Handle the "required code unit", if one is set. In the case of an anchored
- pattern, do this only if it follows a variable length item in the pattern. */
+ /* Handle the "required code unit", if one is set. In the UTF case we can
+ increment the minimum minimum length only if we are sure this really is a
+ different character and not a non-starting code unit of the first character,
+ because the minimum length count is in characters, not code units. */
- if (reqcuflags >= 0 &&
- ((re->overall_options & PCRE2_ANCHORED) == 0 ||
- (reqcuflags & REQ_VARY) != 0))
+ if (reqcuflags >= 0)
{
- re->last_codeunit = reqcu;
- re->flags |= PCRE2_LASTSET;
+#if PCRE2_CODE_UNIT_WIDTH == 16
+ if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */
+ firstcuflags < 0 || /* First not set */
+ (firstcu & 0xf800) != 0xd800 || /* First not surrogate */
+ (reqcu & 0xfc00) != 0xdc00) /* Req not low surrogate */
+#elif PCRE2_CODE_UNIT_WIDTH == 8
+ if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */
+ firstcuflags < 0 || /* First not set */
+ (firstcu & 0x80) == 0 || /* First is ASCII */
+ (reqcu & 0x80) == 0) /* Req is ASCII */
+#endif
+ {
+ minminlength++;
+ }
- /* Handle caseless required code units as for first code units (above). */
+ /* In the case of an anchored pattern, set up the value only if it follows
+ a variable length item in the pattern. */
- if ((reqcuflags & REQ_CASELESS) != 0)
+ if ((re->overall_options & PCRE2_ANCHORED) == 0 ||
+ (reqcuflags & REQ_VARY) != 0)
{
- if (reqcu < 128 || (!utf && reqcu < 255))
+ re->last_codeunit = reqcu;
+ re->flags |= PCRE2_LASTSET;
+
+ /* Handle caseless required code units as for first code units (above). */
+
+ if ((reqcuflags & REQ_CASELESS) != 0)
{
- if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS;
- }
+ if (reqcu < 128 || (!utf && reqcu < 255))
+ {
+ if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS;
+ }
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
- else if (reqcu <= MAX_UTF_CODE_POINT && UCD_OTHERCASE(reqcu) != reqcu)
- re->flags |= PCRE2_LASTCASELESS;
+ else if (reqcu <= MAX_UTF_CODE_POINT && UCD_OTHERCASE(reqcu) != reqcu)
+ re->flags |= PCRE2_LASTCASELESS;
#endif
+ }
}
}
- /* Finally, study the compiled pattern to set up information such as a bitmap
- of starting code units and a minimum matching length. */
+ /* Study the compiled pattern to set up information such as a bitmap of
+ starting code units and a minimum matching length. */
if (PRIV(study)(re) != 0)
{
errorcode = ERR31;
goto HAD_CB_ERROR;
}
+
+ /* If study() set a bitmap of starting code units, it implies a minimum
+ length of at least one. */
+
+ if ((re->flags & PCRE2_FIRSTMAPSET) != 0 && minminlength == 0)
+ minminlength = 1;
+
+ /* If the minimum length set (or not set) by study() is less than the minimum
+ implied by required code units, override it. */
+
+ if (re->minlength < minminlength) re->minlength = minminlength;
} /* End of start-of-match optimizations. */
/* Control ends up here in all cases. When running under valgrind, make a
diff --git a/thirdparty/pcre2/src/pcre2_context.c b/thirdparty/pcre2/src/pcre2_context.c
index 9c2886a6d0..f904a494a0 100644
--- a/thirdparty/pcre2/src/pcre2_context.c
+++ b/thirdparty/pcre2/src/pcre2_context.c
@@ -323,7 +323,7 @@ data. */
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_character_tables(pcre2_compile_context *ccontext,
- const unsigned char *tables)
+ const uint8_t *tables)
{
ccontext->tables = tables;
return 0;
diff --git a/thirdparty/pcre2/src/pcre2_dfa_match.c b/thirdparty/pcre2/src/pcre2_dfa_match.c
index bbf3e21064..7d8ffe8a3e 100644
--- a/thirdparty/pcre2/src/pcre2_dfa_match.c
+++ b/thirdparty/pcre2/src/pcre2_dfa_match.c
@@ -173,6 +173,8 @@ static const uint8_t coptable[] = {
0, /* Assert not */
0, /* Assert behind */
0, /* Assert behind not */
+ 0, /* NA assert */
+ 0, /* NA assert behind */
0, /* ONCE */
0, /* SCRIPT_RUN */
0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */
@@ -248,6 +250,8 @@ static const uint8_t poptable[] = {
0, /* Assert not */
0, /* Assert behind */
0, /* Assert behind not */
+ 0, /* NA assert */
+ 0, /* NA assert behind */
0, /* ONCE */
0, /* SCRIPT_RUN */
0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */
@@ -962,7 +966,7 @@ for (;;)
if (ptr >= end_subject)
{
if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)
- could_continue = TRUE;
+ return PCRE2_ERROR_PARTIAL;
else { ADD_ACTIVE(state_offset + 1, 0); }
}
break;
@@ -1011,10 +1015,12 @@ for (;;)
/*-----------------------------------------------------------------*/
case OP_EODN:
- if (clen == 0 && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)
- could_continue = TRUE;
- else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - mb->nllen))
- { ADD_ACTIVE(state_offset + 1, 0); }
+ if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - mb->nllen))
+ {
+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)
+ return PCRE2_ERROR_PARTIAL;
+ ADD_ACTIVE(state_offset + 1, 0);
+ }
break;
/*-----------------------------------------------------------------*/
@@ -3152,8 +3158,8 @@ for (;;)
/* We have finished the processing at the current subject character. If no
new states have been set for the next character, we have found all the
- matches that we are going to find. If we are at the top level and partial
- matching has been requested, check for appropriate conditions.
+ matches that we are going to find. If partial matching has been requested,
+ check for appropriate conditions.
The "forced_ fail" variable counts the number of (*F) encountered for the
character. If it is equal to the original active_count (saved in
@@ -3165,22 +3171,24 @@ for (;;)
if (new_count <= 0)
{
- if (rlevel == 1 && /* Top level, and */
- could_continue && /* Some could go on, and */
+ if (could_continue && /* Some could go on, and */
forced_fail != workspace[1] && /* Not all forced fail & */
( /* either... */
(mb->moptions & PCRE2_PARTIAL_HARD) != 0 /* Hard partial */
|| /* or... */
((mb->moptions & PCRE2_PARTIAL_SOFT) != 0 && /* Soft partial and */
- match_count < 0) /* no matches */
+ match_count < 0) /* no matches */
) && /* And... */
(
- partial_newline || /* Either partial NL */
- ( /* or ... */
- ptr >= end_subject && /* End of subject and */
- ptr > mb->start_used_ptr) /* Inspected non-empty string */
+ partial_newline || /* Either partial NL */
+ ( /* or ... */
+ ptr >= end_subject && /* End of subject and */
+ ( /* either */
+ ptr > mb->start_used_ptr || /* Inspected non-empty string */
+ mb->allowemptypartial /* or pattern has lookbehind */
+ ) /* or could match empty */
)
- )
+ ))
match_count = PCRE2_ERROR_PARTIAL;
break; /* Exit from loop along the subject string */
}
@@ -3246,6 +3254,11 @@ BOOL utf, anchored, startline, firstline;
BOOL has_first_cu = FALSE;
BOOL has_req_cu = FALSE;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+BOOL memchr_not_found_first_cu = FALSE;
+BOOL memchr_not_found_first_cu2 = FALSE;
+#endif
+
PCRE2_UCHAR first_cu = 0;
PCRE2_UCHAR first_cu2 = 0;
PCRE2_UCHAR req_cu = 0;
@@ -3295,6 +3308,11 @@ if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0 &&
((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)
return PCRE2_ERROR_BADOPTION;
+/* Invalid UTF support is not available for DFA matching. */
+
+if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0)
+ return PCRE2_ERROR_DFA_UINVALID_UTF;
+
/* Check that the first field in the block is the magic number. If it is not,
return with PCRE2_ERROR_BADMAGIC. */
@@ -3404,6 +3422,8 @@ mb->tables = re->tables;
mb->start_subject = subject;
mb->end_subject = end_subject;
mb->start_offset = start_offset;
+mb->allowemptypartial = (re->max_lookbehind > 0) ||
+ (re->flags & PCRE2_MATCH_EMPTY) != 0;
mb->moptions = options;
mb->poptions = re->overall_options;
mb->match_call_count = 0;
@@ -3619,7 +3639,10 @@ for (;;)
/* Not anchored. Advance to a unique first code unit if there is one. In
8-bit mode, the use of memchr() gives a big speed up, even though we have
to call it twice in caseless mode, in order to find the earliest occurrence
- of the character in either of its cases. */
+ of the character in either of its cases. If a call to memchr() that
+ searches the rest of the subject fails to find one case, remember that in
+ order not to keep on repeating the search. This can make a huge difference
+ when the strings are very long and only one case is present. */
else
{
@@ -3633,11 +3656,29 @@ for (;;)
(smc = UCHAR21TEST(start_match)) != first_cu &&
smc != first_cu2)
start_match++;
+
#else /* 8-bit code units */
- PCRE2_SPTR pp1 =
- memchr(start_match, first_cu, end_subject-start_match);
- PCRE2_SPTR pp2 =
- memchr(start_match, first_cu2, end_subject-start_match);
+ PCRE2_SPTR pp1 = NULL;
+ PCRE2_SPTR pp2 = NULL;
+ PCRE2_SIZE cu2size = end_subject - start_match;
+
+ if (!memchr_not_found_first_cu)
+ {
+ pp1 = memchr(start_match, first_cu, end_subject - start_match);
+ if (pp1 == NULL) memchr_not_found_first_cu = TRUE;
+ else cu2size = pp1 - start_match;
+ }
+
+ /* If pp1 is not NULL, we have arranged to search only as far as pp1,
+ to see if the other case is earlier, so we can set "not found" only
+ when both searches have returned NULL. */
+
+ if (!memchr_not_found_first_cu2)
+ {
+ pp2 = memchr(start_match, first_cu2, cu2size);
+ memchr_not_found_first_cu2 = (pp2 == NULL && pp1 == NULL);
+ }
+
if (pp1 == NULL)
start_match = (pp2 == NULL)? end_subject : pp2;
else
@@ -3653,7 +3694,7 @@ for (;;)
while (start_match < end_subject && UCHAR21TEST(start_match) !=
first_cu)
start_match++;
-#else
+#else /* 8-bit code units */
start_match = memchr(start_match, first_cu, end_subject - start_match);
if (start_match == NULL) start_match = end_subject;
#endif
@@ -3740,6 +3781,8 @@ for (;;)
if ((mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) == 0)
{
+ PCRE2_SPTR p;
+
/* The minimum matching length is a lower bound; no actual string of that
length may actually match the pattern. Although the value is, strictly,
in characters, we treat it as code units to avoid spending too much time
@@ -3753,37 +3796,63 @@ for (;;)
point. This optimization can save a huge amount of backtracking in
patterns with nested unlimited repeats that aren't going to match.
Writing separate code for cased/caseless versions makes it go faster, as
- does using an autoincrement and backing off on a match.
+ does using an autoincrement and backing off on a match. As in the case of
+ the first code unit, using memchr() in the 8-bit library gives a big
+ speed up. Unlike the first_cu check above, we do not need to call
+ memchr() twice in the caseless case because we only need to check for the
+ presence of the character in either case, not find the first occurrence.
+
+ The search can be skipped if the code unit was found later than the
+ current starting point in a previous iteration of the bumpalong loop.
HOWEVER: when the subject string is very, very long, searching to its end
can take a long time, and give bad performance on quite ordinary
patterns. This showed up when somebody was matching something like
/^\d+C/ on a 32-megabyte string... so we don't do this when the string is
- sufficiently long. */
+ sufficiently long, but it's worth searching a lot more for unanchored
+ patterns. */
- if (has_req_cu && end_subject - start_match < REQ_CU_MAX)
+ p = start_match + (has_first_cu? 1:0);
+ if (has_req_cu && p > req_cu_ptr)
{
- PCRE2_SPTR p = start_match + (has_first_cu? 1:0);
-
- /* We don't need to repeat the search if we haven't yet reached the
- place we found it at last time. */
+ PCRE2_SIZE check_length = end_subject - start_match;
- if (p > req_cu_ptr)
+ if (check_length < REQ_CU_MAX ||
+ (!anchored && check_length < REQ_CU_MAX * 1000))
{
- if (req_cu != req_cu2)
+ if (req_cu != req_cu2) /* Caseless */
{
+#if PCRE2_CODE_UNIT_WIDTH != 8
while (p < end_subject)
{
uint32_t pp = UCHAR21INCTEST(p);
if (pp == req_cu || pp == req_cu2) { p--; break; }
}
+#else /* 8-bit code units */
+ PCRE2_SPTR pp = p;
+ p = memchr(pp, req_cu, end_subject - pp);
+ if (p == NULL)
+ {
+ p = memchr(pp, req_cu2, end_subject - pp);
+ if (p == NULL) p = end_subject;
+ }
+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */
}
+
+ /* The caseful case */
+
else
{
+#if PCRE2_CODE_UNIT_WIDTH != 8
while (p < end_subject)
{
if (UCHAR21INCTEST(p) == req_cu) { p--; break; }
}
+
+#else /* 8-bit code units */
+ p = memchr(p, req_cu, end_subject - p);
+ if (p == NULL) p = end_subject;
+#endif
}
/* If we can't find the required code unit, break the matching loop,
diff --git a/thirdparty/pcre2/src/pcre2_error.c b/thirdparty/pcre2/src/pcre2_error.c
index 1d02cf14a3..c61648cb7f 100644
--- a/thirdparty/pcre2/src/pcre2_error.c
+++ b/thirdparty/pcre2/src/pcre2_error.c
@@ -184,6 +184,8 @@ static const unsigned char compile_error_texts[] =
/* 95 */
"(*alpha_assertion) not recognized\0"
"script runs require Unicode support, which this version of PCRE2 does not have\0"
+ "too many capturing groups (maximum 65535)\0"
+ "atomic assertion expected after (?( or (?(?C)\0"
;
/* Match-time and UTF error texts are in the same format. */
@@ -268,6 +270,7 @@ static const unsigned char match_error_texts[] =
"invalid syntax\0"
/* 65 */
"internal error - duplicate substitution match\0"
+ "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching\0"
;
diff --git a/thirdparty/pcre2/src/pcre2_internal.h b/thirdparty/pcre2/src/pcre2_internal.h
index 814d91bddb..fe8ffe5c80 100644
--- a/thirdparty/pcre2/src/pcre2_internal.h
+++ b/thirdparty/pcre2/src/pcre2_internal.h
@@ -517,6 +517,7 @@ bytes in a code unit in that mode. */
#define PCRE2_HASBKPORX 0x00100000 /* contains \P, \p, or \X */
#define PCRE2_DUPCAPUSED 0x00200000 /* contains (?| */
#define PCRE2_HASBKC 0x00400000 /* contains \C */
+#define PCRE2_HASACCEPT 0x00800000 /* contains (*ACCEPT) */
#define PCRE2_MODE_MASK (PCRE2_MODE8 | PCRE2_MODE16 | PCRE2_MODE32)
@@ -535,13 +536,14 @@ enum { PCRE2_MATCHEDBY_INTERPRETER, /* pcre2_match() */
#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */
/* The maximum remaining length of subject we are prepared to search for a
-req_unit match. In 8-bit mode, memchr() is used and is much faster than the
-search loop that has to be used in 16-bit and 32-bit modes. */
+req_unit match from an anchored pattern. In 8-bit mode, memchr() is used and is
+much faster than the search loop that has to be used in 16-bit and 32-bit
+modes. */
#if PCRE2_CODE_UNIT_WIDTH == 8
-#define REQ_CU_MAX 2000
+#define REQ_CU_MAX 5000
#else
-#define REQ_CU_MAX 1000
+#define REQ_CU_MAX 2000
#endif
/* Offsets for the bitmap tables in the cbits set of tables. Each table
@@ -881,12 +883,16 @@ a positive value. */
#define STRING_atomic0 "atomic\0"
#define STRING_pla0 "pla\0"
#define STRING_plb0 "plb\0"
+#define STRING_napla0 "napla\0"
+#define STRING_naplb0 "naplb\0"
#define STRING_nla0 "nla\0"
#define STRING_nlb0 "nlb\0"
#define STRING_sr0 "sr\0"
#define STRING_asr0 "asr\0"
#define STRING_positive_lookahead0 "positive_lookahead\0"
#define STRING_positive_lookbehind0 "positive_lookbehind\0"
+#define STRING_non_atomic_positive_lookahead0 "non_atomic_positive_lookahead\0"
+#define STRING_non_atomic_positive_lookbehind0 "non_atomic_positive_lookbehind\0"
#define STRING_negative_lookahead0 "negative_lookahead\0"
#define STRING_negative_lookbehind0 "negative_lookbehind\0"
#define STRING_script_run0 "script_run\0"
@@ -1171,12 +1177,16 @@ only. */
#define STRING_atomic0 STR_a STR_t STR_o STR_m STR_i STR_c "\0"
#define STRING_pla0 STR_p STR_l STR_a "\0"
#define STRING_plb0 STR_p STR_l STR_b "\0"
+#define STRING_napla0 STR_n STR_a STR_p STR_l STR_a "\0"
+#define STRING_naplb0 STR_n STR_a STR_p STR_l STR_b "\0"
#define STRING_nla0 STR_n STR_l STR_a "\0"
#define STRING_nlb0 STR_n STR_l STR_b "\0"
#define STRING_sr0 STR_s STR_r "\0"
#define STRING_asr0 STR_a STR_s STR_r "\0"
#define STRING_positive_lookahead0 STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"
#define STRING_positive_lookbehind0 STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0"
+#define STRING_non_atomic_positive_lookahead0 STR_n STR_o STR_n STR_UNDERSCORE STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"
+#define STRING_non_atomic_positive_lookbehind0 STR_n STR_o STR_n STR_UNDERSCORE STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0"
#define STRING_negative_lookahead0 STR_n STR_e STR_g STR_a STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"
#define STRING_negative_lookbehind0 STR_n STR_e STR_g STR_a STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0"
#define STRING_script_run0 STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n "\0"
@@ -1301,7 +1311,7 @@ enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s,
Starting from 1 (i.e. after OP_END), the values up to OP_EOD must correspond in
order to the list of escapes immediately above. Furthermore, values up to
OP_DOLLM must not be changed without adjusting the table called autoposstab in
-pcre2_auto_possess.c
+pcre2_auto_possess.c.
Whenever this list is updated, the two macro definitions that follow must be
updated to match. The possessification table called "opcode_possessify" in
@@ -1499,80 +1509,81 @@ enum {
OP_KETRMIN, /* 123 order. They are for groups the repeat for ever. */
OP_KETRPOS, /* 124 Possessive unlimited repeat. */
- /* The assertions must come before BRA, CBRA, ONCE, and COND, and the four
- asserts must remain in order. */
+ /* The assertions must come before BRA, CBRA, ONCE, and COND. */
OP_REVERSE, /* 125 Move pointer back - used in lookbehind assertions */
OP_ASSERT, /* 126 Positive lookahead */
OP_ASSERT_NOT, /* 127 Negative lookahead */
OP_ASSERTBACK, /* 128 Positive lookbehind */
OP_ASSERTBACK_NOT, /* 129 Negative lookbehind */
+ OP_ASSERT_NA, /* 130 Positive non-atomic lookahead */
+ OP_ASSERTBACK_NA, /* 131 Positive non-atomic lookbehind */
/* ONCE, SCRIPT_RUN, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come
immediately after the assertions, with ONCE first, as there's a test for >=
ONCE for a subpattern that isn't an assertion. The POS versions must
immediately follow the non-POS versions in each case. */
- OP_ONCE, /* 130 Atomic group, contains captures */
- OP_SCRIPT_RUN, /* 131 Non-capture, but check characters' scripts */
- OP_BRA, /* 132 Start of non-capturing bracket */
- OP_BRAPOS, /* 133 Ditto, with unlimited, possessive repeat */
- OP_CBRA, /* 134 Start of capturing bracket */
- OP_CBRAPOS, /* 135 Ditto, with unlimited, possessive repeat */
- OP_COND, /* 136 Conditional group */
+ OP_ONCE, /* 132 Atomic group, contains captures */
+ OP_SCRIPT_RUN, /* 133 Non-capture, but check characters' scripts */
+ OP_BRA, /* 134 Start of non-capturing bracket */
+ OP_BRAPOS, /* 135 Ditto, with unlimited, possessive repeat */
+ OP_CBRA, /* 136 Start of capturing bracket */
+ OP_CBRAPOS, /* 137 Ditto, with unlimited, possessive repeat */
+ OP_COND, /* 138 Conditional group */
/* These five must follow the previous five, in the same order. There's a
check for >= SBRA to distinguish the two sets. */
- OP_SBRA, /* 137 Start of non-capturing bracket, check empty */
- OP_SBRAPOS, /* 138 Ditto, with unlimited, possessive repeat */
- OP_SCBRA, /* 139 Start of capturing bracket, check empty */
- OP_SCBRAPOS, /* 140 Ditto, with unlimited, possessive repeat */
- OP_SCOND, /* 141 Conditional group, check empty */
+ OP_SBRA, /* 139 Start of non-capturing bracket, check empty */
+ OP_SBRAPOS, /* 149 Ditto, with unlimited, possessive repeat */
+ OP_SCBRA, /* 141 Start of capturing bracket, check empty */
+ OP_SCBRAPOS, /* 142 Ditto, with unlimited, possessive repeat */
+ OP_SCOND, /* 143 Conditional group, check empty */
/* The next two pairs must (respectively) be kept together. */
- OP_CREF, /* 142 Used to hold a capture number as condition */
- OP_DNCREF, /* 143 Used to point to duplicate names as a condition */
- OP_RREF, /* 144 Used to hold a recursion number as condition */
- OP_DNRREF, /* 145 Used to point to duplicate names as a condition */
- OP_FALSE, /* 146 Always false (used by DEFINE and VERSION) */
- OP_TRUE, /* 147 Always true (used by VERSION) */
+ OP_CREF, /* 144 Used to hold a capture number as condition */
+ OP_DNCREF, /* 145 Used to point to duplicate names as a condition */
+ OP_RREF, /* 146 Used to hold a recursion number as condition */
+ OP_DNRREF, /* 147 Used to point to duplicate names as a condition */
+ OP_FALSE, /* 148 Always false (used by DEFINE and VERSION) */
+ OP_TRUE, /* 149 Always true (used by VERSION) */
- OP_BRAZERO, /* 148 These two must remain together and in this */
- OP_BRAMINZERO, /* 149 order. */
- OP_BRAPOSZERO, /* 150 */
+ OP_BRAZERO, /* 150 These two must remain together and in this */
+ OP_BRAMINZERO, /* 151 order. */
+ OP_BRAPOSZERO, /* 152 */
/* These are backtracking control verbs */
- OP_MARK, /* 151 always has an argument */
- OP_PRUNE, /* 152 */
- OP_PRUNE_ARG, /* 153 same, but with argument */
- OP_SKIP, /* 154 */
- OP_SKIP_ARG, /* 155 same, but with argument */
- OP_THEN, /* 156 */
- OP_THEN_ARG, /* 157 same, but with argument */
- OP_COMMIT, /* 158 */
- OP_COMMIT_ARG, /* 159 same, but with argument */
+ OP_MARK, /* 153 always has an argument */
+ OP_PRUNE, /* 154 */
+ OP_PRUNE_ARG, /* 155 same, but with argument */
+ OP_SKIP, /* 156 */
+ OP_SKIP_ARG, /* 157 same, but with argument */
+ OP_THEN, /* 158 */
+ OP_THEN_ARG, /* 159 same, but with argument */
+ OP_COMMIT, /* 160 */
+ OP_COMMIT_ARG, /* 161 same, but with argument */
/* These are forced failure and success verbs. FAIL and ACCEPT do accept an
argument, but these cases can be compiled as, for example, (*MARK:X)(*FAIL)
without the need for a special opcode. */
- OP_FAIL, /* 160 */
- OP_ACCEPT, /* 161 */
- OP_ASSERT_ACCEPT, /* 162 Used inside assertions */
- OP_CLOSE, /* 163 Used before OP_ACCEPT to close open captures */
+ OP_FAIL, /* 162 */
+ OP_ACCEPT, /* 163 */
+ OP_ASSERT_ACCEPT, /* 164 Used inside assertions */
+ OP_CLOSE, /* 165 Used before OP_ACCEPT to close open captures */
/* This is used to skip a subpattern with a {0} quantifier */
- OP_SKIPZERO, /* 164 */
+ OP_SKIPZERO, /* 166 */
/* This is used to identify a DEFINE group during compilation so that it can
be checked for having only one branch. It is changed to OP_FALSE before
compilation finishes. */
- OP_DEFINE, /* 165 */
+ OP_DEFINE, /* 167 */
/* This is not an opcode, but is used to check that tables indexed by opcode
are the correct length, in order to catch updating errors - there have been
@@ -1585,7 +1596,7 @@ enum {
/* *** NOTE NOTE NOTE *** Whenever the list above is updated, the two macro
definitions that follow must also be updated to match. There are also tables
called "opcode_possessify" in pcre2_compile.c and "coptable" and "poptable" in
-pcre2_dfa_exec.c that must be updated. */
+pcre2_dfa_match.c that must be updated. */
/* This macro defines textual names for all the opcodes. These are used only
@@ -1618,7 +1629,9 @@ some cases doesn't actually use these names at all). */
"class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \
"Recurse", "Callout", "CalloutStr", \
"Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \
- "Reverse", "Assert", "Assert not", "AssertB", "AssertB not", \
+ "Reverse", "Assert", "Assert not", \
+ "Assert back", "Assert back not", \
+ "Non-atomic assert", "Non-atomic assert back", \
"Once", \
"Script run", \
"Bra", "BraPos", "CBra", "CBraPos", \
@@ -1703,6 +1716,8 @@ in UTF-8 mode. The code that uses this table must know about such things. */
1+LINK_SIZE, /* Assert not */ \
1+LINK_SIZE, /* Assert behind */ \
1+LINK_SIZE, /* Assert behind not */ \
+ 1+LINK_SIZE, /* NA Assert */ \
+ 1+LINK_SIZE, /* NA Assert behind */ \
1+LINK_SIZE, /* ONCE */ \
1+LINK_SIZE, /* SCRIPT_RUN */ \
1+LINK_SIZE, /* BRA */ \
diff --git a/thirdparty/pcre2/src/pcre2_intmodedep.h b/thirdparty/pcre2/src/pcre2_intmodedep.h
index bf3a235984..ea3b3ec698 100644
--- a/thirdparty/pcre2/src/pcre2_intmodedep.h
+++ b/thirdparty/pcre2/src/pcre2_intmodedep.h
@@ -205,19 +205,19 @@ whether its argument, which is assumed to be one code unit, is less than 256.
The CHMAX_255 macro does not assume one code unit. The maximum length of a MARK
name must fit in one code unit; currently it is set to 255 or 65535. The
TABLE_GET macro is used to access elements of tables containing exactly 256
-items. When code points can be greater than 255, a check is needed before
-accessing these tables. */
+items. Its argument is a code unit. When code points can be greater than 255, a
+check is needed before accessing these tables. */
#if PCRE2_CODE_UNIT_WIDTH == 8
#define MAX_255(c) TRUE
#define MAX_MARK ((1u << 8) - 1)
+#define TABLE_GET(c, table, default) ((table)[c])
#ifdef SUPPORT_UNICODE
#define SUPPORT_WIDE_CHARS
#define CHMAX_255(c) ((c) <= 255u)
#else
#define CHMAX_255(c) TRUE
#endif /* SUPPORT_UNICODE */
-#define TABLE_GET(c, table, default) ((table)[c])
#else /* Code units are 16 or 32 bits */
#define CHMAX_255(c) ((c) <= 255u)
@@ -228,7 +228,6 @@ accessing these tables. */
#endif
-
/* ----------------- Character-handling macros ----------------- */
/* There is a proposed future special "UTF-21" mode, in which only the lowest
@@ -854,6 +853,7 @@ typedef struct match_block {
uint32_t match_call_count; /* Number of times a new frame is created */
BOOL hitend; /* Hit the end of the subject at some point */
BOOL hasthen; /* Pattern contains (*THEN) */
+ BOOL allowemptypartial; /* Allow empty hard partial */
const uint8_t *lcc; /* Points to lower casing table */
const uint8_t *fcc; /* Points to case-flipping table */
const uint8_t *ctypes; /* Points to table of type maps */
@@ -866,6 +866,7 @@ typedef struct match_block {
PCRE2_SPTR name_table; /* Table of group names */
PCRE2_SPTR start_code; /* For use when recursing */
PCRE2_SPTR start_subject; /* Start of the subject string */
+ PCRE2_SPTR check_subject; /* Where UTF-checked from */
PCRE2_SPTR end_subject; /* End of the subject string */
PCRE2_SPTR end_match_ptr; /* Subject position at end match */
PCRE2_SPTR start_used_ptr; /* Earliest consulted character */
@@ -908,6 +909,7 @@ typedef struct dfa_match_block {
uint32_t poptions; /* Pattern options */
uint32_t nltype; /* Newline type */
uint32_t nllen; /* Newline string length */
+ BOOL allowemptypartial; /* Allow empty hard partial */
PCRE2_UCHAR nl[4]; /* Newline string when fixed */
uint16_t bsr_convention; /* \R interpretation */
pcre2_callout_block *cb; /* Points to a callout block */
diff --git a/thirdparty/pcre2/src/pcre2_jit_compile.c b/thirdparty/pcre2/src/pcre2_jit_compile.c
index 1f21bfb6ad..f564127c2a 100644
--- a/thirdparty/pcre2/src/pcre2_jit_compile.c
+++ b/thirdparty/pcre2/src/pcre2_jit_compile.c
@@ -6,8 +6,9 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
+ This module by Zoltan Herczeg
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -212,12 +213,6 @@ typedef struct stub_list {
struct stub_list *next;
} stub_list;
-typedef struct label_addr_list {
- struct sljit_label *label;
- sljit_uw *update_addr;
- struct label_addr_list *next;
-} label_addr_list;
-
enum frame_types {
no_frame = -1,
no_stack = -2
@@ -271,6 +266,8 @@ typedef struct bracket_backtrack {
assert_backtrack *assert;
/* For OP_ONCE. Less than 0 if not needed. */
int framesize;
+ /* For brackets with >3 alternatives. */
+ struct sljit_put_label *matching_put_label;
} u;
/* Points to our private memory word on the stack. */
int private_data_ptr;
@@ -416,6 +413,8 @@ typedef struct compiler_common {
sljit_sw lcc;
/* Mode can be PCRE2_JIT_COMPLETE and others. */
int mode;
+ /* TRUE, when empty match is accepted for partial matching. */
+ BOOL allow_empty_partial;
/* TRUE, when minlength is greater than 0. */
BOOL might_be_empty;
/* \K is found in the pattern. */
@@ -454,7 +453,6 @@ typedef struct compiler_common {
struct sljit_label *accept_label;
struct sljit_label *ff_newline_shortcut;
stub_list *stubs;
- label_addr_list *label_addrs;
recurse_entry *entries;
recurse_entry *currententry;
jump_list *partialmatch;
@@ -563,6 +561,12 @@ typedef struct compare_context {
#define ARGUMENTS SLJIT_S4
#define RETURN_ADDR SLJIT_R4
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+#define HAS_VIRTUAL_REGISTERS 1
+#else
+#define HAS_VIRTUAL_REGISTERS 0
+#endif
+
/* Local space layout. */
/* These two locals can be used by the current opcode. */
#define LOCALS0 (0 * sizeof(sljit_sw))
@@ -696,11 +700,12 @@ the start pointers when the end of the capturing group has not yet reached. */
#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \
{ \
- if (ptr[-1] <= 0x7f) \
- c = *ptr--; \
+ c = ptr[-1]; \
+ if (c <= 0x7f) \
+ ptr--; \
else if (ptr - 1 > start && ptr[-1] >= 0x80 && ptr[-1] < 0xc0) \
{ \
- c = ptr[-1] - 0x80; \
+ c -= 0x80; \
\
if (ptr[-2] >= 0xc2 && ptr[-2] <= 0xdf) \
{ \
@@ -775,11 +780,12 @@ the start pointers when the end of the capturing group has not yet reached. */
#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \
{ \
- if (ptr[-1] < 0xd800 || ptr[-1] >= 0xe000) \
- c = *ptr--; \
- else if (ptr[-1] >= 0xdc00 && ptr - 1 > start && ptr[-2] >= 0xd800 && ptr[-2] < 0xdc00) \
+ c = ptr[-1]; \
+ if (c < 0xd800 || c >= 0xe000) \
+ ptr--; \
+ else if (c >= 0xdc00 && ptr - 1 > start && ptr[-2] >= 0xd800 && ptr[-2] < 0xdc00) \
{ \
- c = (((ptr[-2] - 0xd800) << 10) | (ptr[-1] - 0xdc00)) + 0x10000; \
+ c = (((ptr[-2] - 0xd800) << 10) | (c - 0xdc00)) + 0x10000; \
ptr -= 2; \
} \
else \
@@ -793,7 +799,7 @@ the start pointers when the end of the capturing group has not yet reached. */
#define GETCHARINC_INVALID(c, ptr, end, invalid_action) \
{ \
- if (ptr[0] < 0x110000) \
+ if (ptr[0] < 0xd800 || (ptr[0] >= 0xe000 && ptr[0] < 0x110000)) \
c = *ptr++; \
else \
{ \
@@ -801,6 +807,17 @@ the start pointers when the end of the capturing group has not yet reached. */
} \
}
+#define GETCHARBACK_INVALID(c, ptr, start, invalid_action) \
+ { \
+ c = ptr[-1]; \
+ if (ptr[-1] < 0xd800 || (ptr[-1] >= 0xe000 && ptr[-1] < 0x110000)) \
+ ptr--; \
+ else \
+ { \
+ invalid_action; \
+ } \
+ }
+
#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
#endif /* SUPPORT_UNICODE */
@@ -1033,8 +1050,8 @@ switch(*cc)
return cc + 1 + 2 + cc[1];
default:
- /* All opcodes are supported now! */
- SLJIT_UNREACHABLE();
+ /* Unsupported opcodes: OP_ASSERT_NA and OP_ASSERTBACK_NA */
+ /* SLJIT_UNREACHABLE(); */
return NULL;
}
}
@@ -2371,14 +2388,14 @@ if (base_reg != TMP2)
else
{
status.saved_tmp_regs[1] = RETURN_ADDR;
- if (sljit_get_register_index(RETURN_ADDR) == -1)
+ if (HAS_VIRTUAL_REGISTERS)
status.tmp_regs[1] = STR_PTR;
else
status.tmp_regs[1] = RETURN_ADDR;
}
status.saved_tmp_regs[2] = TMP3;
-if (sljit_get_register_index(TMP3) == -1)
+if (HAS_VIRTUAL_REGISTERS)
status.tmp_regs[2] = STR_END;
else
status.tmp_regs[2] = TMP3;
@@ -2829,20 +2846,6 @@ while (list_item)
common->stubs = NULL;
}
-static void add_label_addr(compiler_common *common, sljit_uw *update_addr)
-{
-DEFINE_COMPILER;
-label_addr_list *label_addr;
-
-label_addr = sljit_alloc_memory(compiler, sizeof(label_addr_list));
-if (label_addr == NULL)
- return;
-label_addr->label = LABEL();
-label_addr->update_addr = update_addr;
-label_addr->next = common->label_addrs;
-common->label_addrs = label_addr;
-}
-
static SLJIT_INLINE void count_match(compiler_common *common)
{
DEFINE_COMPILER;
@@ -2985,12 +2988,18 @@ else
}
}
-OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);
+if (!HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, stack));
+else
+ OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);
+
if (common->mark_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);
if (common->control_head_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
-OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));
+if (HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack));
+
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, end));
}
@@ -3029,21 +3038,36 @@ BOOL has_pre;
OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0);
-OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
-if (common->mark_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
-OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, oveccount));
-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);
-if (common->mark_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);
-OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data),
- SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));
+if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
+ if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
+ OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, oveccount));
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);
+ if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);
+ OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data),
+ SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));
+ }
+else
+ {
+ OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
+ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, match_data));
+ if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
+ OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, oveccount));
+ OP1(SLJIT_MOV, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);
+ if (common->mark_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R0, 0);
+ OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));
+ }
has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS;
GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0));
-OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin));
+OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? SLJIT_R0 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
loop = LABEL();
@@ -3105,20 +3129,22 @@ static SLJIT_INLINE void return_with_partial_match(compiler_common *common, stru
{
DEFINE_COMPILER;
sljit_s32 mov_opcode;
+sljit_s32 arguments_reg = !HAS_VIRTUAL_REGISTERS ? ARGUMENTS : SLJIT_R1;
SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S0, str_end_must_be_saved_reg0);
SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0
&& (common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start != 0 : common->hit_start == 0));
-OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0);
+if (arguments_reg != ARGUMENTS)
+ OP1(SLJIT_MOV, arguments_reg, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP),
common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start : common->start_ptr);
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_PARTIAL);
/* Store match begin and end. */
-OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin));
-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_R2, 0);
-OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, match_data));
+OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, begin));
+OP1(SLJIT_MOV, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_R2, 0);
+OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(arguments_reg), SLJIT_OFFSETOF(jit_arguments, match_data));
mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;
@@ -3279,7 +3305,7 @@ SLJIT_ASSERT(!force || common->mode != PCRE2_JIT_COMPLETE);
if (common->mode == PCRE2_JIT_COMPLETE)
return;
-if (!force)
+if (!force && !common->allow_empty_partial)
jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
jump = CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);
@@ -3341,7 +3367,11 @@ if (common->mode == PCRE2_JIT_COMPLETE)
/* Partial matching mode. */
jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
-add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
+if (!common->allow_empty_partial)
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
+else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1));
+
if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
{
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
@@ -3357,6 +3387,35 @@ else
JUMPHERE(jump);
}
+static void process_partial_match(compiler_common *common)
+{
+DEFINE_COMPILER;
+struct sljit_jump *jump;
+
+/* Partial matching mode. */
+if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
+ {
+ jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
+ JUMPHERE(jump);
+ }
+else if (common->mode == PCRE2_JIT_PARTIAL_HARD)
+ {
+ if (common->partialmatchlabel != NULL)
+ CMPTO(SLJIT_LESS, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0, common->partialmatchlabel);
+ else
+ add_jump(compiler, &common->partialmatch, CMP(SLJIT_LESS, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
+ }
+}
+
+static void detect_partial_match_to(compiler_common *common, struct sljit_label *label)
+{
+DEFINE_COMPILER;
+
+CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, label);
+process_partial_match(common);
+}
+
static void peek_char(compiler_common *common, sljit_u32 max, sljit_s32 dst, sljit_sw dstw, jump_list **backtracks)
{
/* Reads the character into TMP1, keeps STR_PTR.
@@ -3420,12 +3479,21 @@ if (common->utf)
#elif PCRE2_CODE_UNIT_WIDTH == 32
if (common->invalid_utf)
{
+ if (max < 0xd800) return;
+
if (backtracks != NULL)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));
+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));
+ }
else
{
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);
CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
}
}
#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
@@ -3490,8 +3558,12 @@ if (common->utf)
JUMPHERE(jump);
}
#elif PCRE2_CODE_UNIT_WIDTH == 32
- if (common->invalid_utf)
- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));
+if (common->invalid_utf)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));
+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));
+ }
#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
#endif /* SUPPORT_UNICODE */
}
@@ -3653,7 +3725,7 @@ if (common->utf)
/* Skip low surrogate if necessary. */
OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
- if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && sljit_get_register_index(RETURN_ADDR) >= 0)
+ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)
{
if (options & READ_CHAR_UPDATE_STR_PTR)
OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
@@ -3677,11 +3749,18 @@ if (common->utf)
if (common->invalid_utf)
{
if (backtracks != NULL)
+ {
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000));
+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800));
+ }
else
{
+ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);
CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
+ CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
}
}
#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
@@ -3832,7 +3911,7 @@ if (common->utf && negated)
{
OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800);
- if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && sljit_get_register_index(RETURN_ADDR) >= 0)
+ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)
{
OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x400);
@@ -3865,9 +3944,9 @@ if (common->utf && negated)
static void move_back(compiler_common *common, jump_list **backtracks, BOOL must_be_valid)
{
-/* Goes one character back. TMP2 must contain the start of
-the subject buffer. Affects STR_PTR and TMP1. Does not modify
-STR_PTR for invalid character sequences. */
+/* Goes one character back. Affects STR_PTR and TMP1. If must_be_valid is TRUE,
+TMP2 is not used. Otherwise TMP2 must contain the start of the subject buffer,
+and it is destroyed. Does not modify STR_PTR for invalid character sequences. */
DEFINE_COMPILER;
SLJIT_UNUSED_ARG(backtracks);
@@ -4407,7 +4486,7 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
static void do_utfpeakcharback(compiler_common *common)
{
-/* Peak a character back. */
+/* Peak a character back. Does not modify STR_PTR. */
DEFINE_COMPILER;
struct sljit_jump *jump[2];
@@ -4444,7 +4523,7 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
static void do_utfpeakcharback_invalid(compiler_common *common)
{
-/* Peak a character back. */
+/* Peak a character back. Does not modify STR_PTR. */
DEFINE_COMPILER;
sljit_s32 i;
sljit_s32 has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV);
@@ -4672,7 +4751,7 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
static void do_utfpeakcharback_invalid(compiler_common *common)
{
-/* Peak a character back. */
+/* Peak a character back. Does not modify STR_PTR. */
DEFINE_COMPILER;
struct sljit_jump *jump;
struct sljit_jump *exit_invalid[3];
@@ -4786,18 +4865,12 @@ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
-// PH hacking
-//fprintf(stderr, "~~A\n");
- OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);
- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
-
+/* TMP2 is multiplied by 12. Same as (TMP2 << 2) + ((TMP2 << 2) << 1). */
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 1);
- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 0);
-
-// OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
@@ -4866,15 +4939,27 @@ else if ((overall_options & PCRE2_USE_OFFSET_LIMIT) != 0)
/* Check whether offset limit is set and valid. */
SLJIT_ASSERT(common->match_end_ptr != 0);
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, offset_limit));
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, offset_limit));
+ }
+ else
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, offset_limit));
+
OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);
end = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw) PCRE2_UNSET);
- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ if (HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ else
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
+
#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif /* PCRE2_CODE_UNIT_WIDTH == [16|32] */
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
+ if (HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
+
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
end2 = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0);
OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);
@@ -5434,699 +5519,56 @@ CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00, label);
}
#endif
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
+#include "pcre2_jit_simd_inc.h"
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-static struct sljit_jump *jump_if_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg)
-{
-#if PCRE2_CODE_UNIT_WIDTH == 8
-OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);
-return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0x80);
-#elif PCRE2_CODE_UNIT_WIDTH == 16
-OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);
-return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00);
-#else
-#error "Unknown code width"
-#endif
-}
-#endif
-
-static sljit_s32 character_to_int32(PCRE2_UCHAR chr)
-{
-sljit_u32 value = chr;
-#if PCRE2_CODE_UNIT_WIDTH == 8
-#define SSE2_COMPARE_TYPE_INDEX 0
-return (sljit_s32)((value << 24) | (value << 16) | (value << 8) | value);
-#elif PCRE2_CODE_UNIT_WIDTH == 16
-#define SSE2_COMPARE_TYPE_INDEX 1
-return (sljit_s32)((value << 16) | value);
-#elif PCRE2_CODE_UNIT_WIDTH == 32
-#define SSE2_COMPARE_TYPE_INDEX 2
-return (sljit_s32)(value);
-#else
-#error "Unsupported unit width"
-#endif
-}
+#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD
-static void load_from_mem_sse2(struct sljit_compiler *compiler, sljit_s32 dst_xmm_reg, sljit_s32 src_general_reg)
+static BOOL check_fast_forward_char_pair_simd(compiler_common *common, fast_forward_char_data *chars, int max)
{
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-sljit_u8 instruction[5];
-#else
-sljit_u8 instruction[4];
-#endif
-
-SLJIT_ASSERT(dst_xmm_reg < 8);
-
-/* MOVDQA xmm1, xmm2/m128 */
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-if (src_general_reg < 8)
- {
- instruction[0] = 0x66;
- instruction[1] = 0x0f;
- instruction[2] = 0x6f;
- instruction[3] = (dst_xmm_reg << 3) | src_general_reg;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-else
- {
- instruction[0] = 0x66;
- instruction[1] = 0x41;
- instruction[2] = 0x0f;
- instruction[3] = 0x6f;
- instruction[4] = (dst_xmm_reg << 3) | (src_general_reg & 0x7);
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-#else
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-instruction[2] = 0x6f;
-instruction[3] = (dst_xmm_reg << 3) | src_general_reg;
-sljit_emit_op_custom(compiler, instruction, 4);
-#endif
-}
-
-static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, PCRE2_UCHAR char1, PCRE2_UCHAR char2,
- sljit_u32 bit, sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind)
-{
-sljit_u8 instruction[4];
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-
-if (char1 == char2 || bit != 0)
- {
- if (bit != 0)
- {
- /* POR xmm1, xmm2/m128 */
- /* instruction[0] = 0x66; */
- /* instruction[1] = 0x0f; */
- instruction[2] = 0xeb;
- instruction[3] = 0xc0 | (dst_ind << 3) | cmp2_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-
- /* PCMPEQB/W/D xmm1, xmm2/m128 */
- /* instruction[0] = 0x66; */
- /* instruction[1] = 0x0f; */
- instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
- instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-else
- {
- /* MOVDQA xmm1, xmm2/m128 */
- /* instruction[0] = 0x66; */
- /* instruction[1] = 0x0f; */
- instruction[2] = 0x6f;
- instruction[3] = 0xc0 | (tmp_ind << 3) | dst_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
-
- /* PCMPEQB/W/D xmm1, xmm2/m128 */
- /* instruction[0] = 0x66; */
- /* instruction[1] = 0x0f; */
- instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
- instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
-
- instruction[3] = 0xc0 | (tmp_ind << 3) | cmp2_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
-
- /* POR xmm1, xmm2/m128 */
- /* instruction[0] = 0x66; */
- /* instruction[1] = 0x0f; */
- instruction[2] = 0xeb;
- instruction[3] = 0xc0 | (dst_ind << 3) | tmp_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-}
-
-static void fast_forward_first_char2_sse2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
-{
-DEFINE_COMPILER;
-struct sljit_label *start;
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-struct sljit_label *restart;
-#endif
-struct sljit_jump *quit;
-struct sljit_jump *partial_quit[2];
-sljit_u8 instruction[8];
-sljit_s32 tmp1_ind = sljit_get_register_index(TMP1);
-sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR);
-sljit_s32 data_ind = 0;
-sljit_s32 tmp_ind = 1;
-sljit_s32 cmp1_ind = 2;
-sljit_s32 cmp2_ind = 3;
-sljit_u32 bit = 0;
-
-SLJIT_UNUSED_ARG(offset);
-
-if (char1 != char2)
- {
- bit = char1 ^ char2;
- if (!is_powerof2(bit))
- bit = 0;
- }
-
-partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
-if (common->mode == PCRE2_JIT_COMPLETE)
- add_jump(compiler, &common->failed_match, partial_quit[0]);
-
-/* First part (unaligned start) */
-
-OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
-
-SLJIT_ASSERT(tmp1_ind < 8);
-
-/* MOVD xmm, r/m32 */
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-instruction[2] = 0x6e;
-instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-if (char1 != char2)
- {
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
-
- /* MOVD xmm, r/m32 */
- instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-
-OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
-
-/* PSHUFD xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x70;
-instruction[3] = 0xc0 | (cmp1_ind << 3) | 2;
-instruction[4] = 0;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-if (char1 != char2)
- {
- /* PSHUFD xmm1, xmm2/m128, imm8 */
- instruction[3] = 0xc0 | (cmp2_ind << 3) | 3;
- sljit_emit_op_custom(compiler, instruction, 5);
- }
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-restart = LABEL();
-#endif
-OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
-
-load_from_mem_sse2(compiler, data_ind, str_ptr_ind);
-fast_forward_char_pair_sse2_compare(compiler, char1, char2, bit, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
-
-/* PMOVMSKB reg, xmm */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xd7;
-instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
-OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
-
-/* BSF r32, r/m32 */
-instruction[0] = 0x0f;
-instruction[1] = 0xbc;
-instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 3);
-sljit_set_current_flags(compiler, SLJIT_SET_Z);
-
-quit = JUMP(SLJIT_NOT_ZERO);
-
-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
-
-start = LABEL();
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
-
-partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
-if (common->mode == PCRE2_JIT_COMPLETE)
- add_jump(compiler, &common->failed_match, partial_quit[1]);
-
-/* Second part (aligned) */
-
-load_from_mem_sse2(compiler, 0, str_ptr_ind);
-fast_forward_char_pair_sse2_compare(compiler, char1, char2, bit, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
-
-/* PMOVMSKB reg, xmm */
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-instruction[2] = 0xd7;
-instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* BSF r32, r/m32 */
-instruction[0] = 0x0f;
-instruction[1] = 0xbc;
-instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 3);
-sljit_set_current_flags(compiler, SLJIT_SET_Z);
-
-JUMPTO(SLJIT_ZERO, start);
-
-JUMPHERE(quit);
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
-
-if (common->mode != PCRE2_JIT_COMPLETE)
- {
- JUMPHERE(partial_quit[0]);
- JUMPHERE(partial_quit[1]);
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
- CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
- }
-else
- add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-if (common->utf && offset > 0)
- {
- SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);
-
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
-
- quit = jump_if_utf_char_start(compiler, TMP1);
-
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
- OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
- JUMPTO(SLJIT_JUMP, restart);
-
- JUMPHERE(quit);
- }
-#endif
-}
-
-#ifndef _WIN64
-
-static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_sse2_offset(void)
-{
-#if PCRE2_CODE_UNIT_WIDTH == 8
-return 15;
-#elif PCRE2_CODE_UNIT_WIDTH == 16
-return 7;
-#elif PCRE2_CODE_UNIT_WIDTH == 32
-return 3;
-#else
-#error "Unsupported unit width"
-#endif
-}
-
-static void fast_forward_char_pair_sse2(compiler_common *common, sljit_s32 offs1,
- PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)
-{
-DEFINE_COMPILER;
-sljit_u32 bit1 = 0;
-sljit_u32 bit2 = 0;
-sljit_u32 diff = IN_UCHARS(offs1 - offs2);
-sljit_s32 tmp1_ind = sljit_get_register_index(TMP1);
-sljit_s32 tmp2_ind = sljit_get_register_index(TMP2);
-sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR);
-sljit_s32 data1_ind = 0;
-sljit_s32 data2_ind = 1;
-sljit_s32 tmp_ind = 2;
-sljit_s32 cmp1a_ind = 3;
-sljit_s32 cmp1b_ind = 4;
-sljit_s32 cmp2a_ind = 5;
-sljit_s32 cmp2b_ind = 6;
-struct sljit_label *start;
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-struct sljit_label *restart;
-#endif
-struct sljit_jump *jump[2];
-
-sljit_u8 instruction[8];
-
-SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);
-SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_sse2_offset()));
-SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1);
-
-/* Initialize. */
-if (common->match_end_ptr != 0)
- {
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
- OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
-
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
- CMOV(SLJIT_LESS, STR_END, TMP1, 0);
- }
-
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-
-/* MOVD xmm, r/m32 */
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-instruction[2] = 0x6e;
-
-if (char1a == char1b)
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));
-else
- {
- bit1 = char1a ^ char1b;
- if (is_powerof2(bit1))
- {
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a | bit1));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit1));
- }
- else
- {
- bit1 = 0;
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char1b));
- }
- }
-
-instruction[3] = 0xc0 | (cmp1a_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-if (char1a != char1b)
- {
- instruction[3] = 0xc0 | (cmp1b_ind << 3) | tmp2_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-
-if (char2a == char2b)
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));
-else
- {
- bit2 = char2a ^ char2b;
- if (is_powerof2(bit2))
- {
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a | bit2));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit2));
- }
- else
- {
- bit2 = 0;
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char2b));
- }
- }
-
-instruction[3] = 0xc0 | (cmp2a_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-if (char2a != char2b)
- {
- instruction[3] = 0xc0 | (cmp2b_ind << 3) | tmp2_ind;
- sljit_emit_op_custom(compiler, instruction, 4);
- }
-
-/* PSHUFD xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x70;
-instruction[4] = 0;
-
-instruction[3] = 0xc0 | (cmp1a_ind << 3) | cmp1a_ind;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-if (char1a != char1b)
- {
- instruction[3] = 0xc0 | (cmp1b_ind << 3) | cmp1b_ind;
- sljit_emit_op_custom(compiler, instruction, 5);
- }
-
-instruction[3] = 0xc0 | (cmp2a_ind << 3) | cmp2a_ind;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-if (char2a != char2b)
- {
- instruction[3] = 0xc0 | (cmp2b_ind << 3) | cmp2b_ind;
- sljit_emit_op_custom(compiler, instruction, 5);
- }
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-restart = LABEL();
-#endif
-
-OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1 - offs2));
-OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
-OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
-OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, ~0xf);
-
-load_from_mem_sse2(compiler, data1_ind, str_ptr_ind);
-
-jump[0] = CMP(SLJIT_EQUAL, STR_PTR, 0, TMP1, 0);
-
-load_from_mem_sse2(compiler, data2_ind, tmp1_ind);
-
-/* MOVDQA xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x6f;
-instruction[3] = 0xc0 | (tmp_ind << 3) | data1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* PSLLDQ xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x73;
-instruction[3] = 0xc0 | (7 << 3) | tmp_ind;
-instruction[4] = diff;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-/* PSRLDQ xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-/* instruction[2] = 0x73; */
-instruction[3] = 0xc0 | (3 << 3) | data2_ind;
-instruction[4] = 16 - diff;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-/* POR xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xeb;
-instruction[3] = 0xc0 | (data2_ind << 3) | tmp_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-jump[1] = JUMP(SLJIT_JUMP);
-
-JUMPHERE(jump[0]);
-
-/* MOVDQA xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x6f;
-instruction[3] = 0xc0 | (data2_ind << 3) | data1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* PSLLDQ xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x73;
-instruction[3] = 0xc0 | (7 << 3) | data2_ind;
-instruction[4] = diff;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-JUMPHERE(jump[1]);
-
-OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
-
-fast_forward_char_pair_sse2_compare(compiler, char2a, char2b, bit2, data2_ind, cmp2a_ind, cmp2b_ind, tmp_ind);
-fast_forward_char_pair_sse2_compare(compiler, char1a, char1b, bit1, data1_ind, cmp1a_ind, cmp1b_ind, tmp_ind);
-
-/* PAND xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xdb;
-instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* PMOVMSKB reg, xmm */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xd7;
-instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* Ignore matches before the first STR_PTR. */
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
-OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
-
-/* BSF r32, r/m32 */
-instruction[0] = 0x0f;
-instruction[1] = 0xbc;
-instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 3);
-sljit_set_current_flags(compiler, SLJIT_SET_Z);
-
-jump[0] = JUMP(SLJIT_NOT_ZERO);
-
-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
-
-/* Main loop. */
-instruction[0] = 0x66;
-instruction[1] = 0x0f;
-
-start = LABEL();
-
-load_from_mem_sse2(compiler, data2_ind, str_ptr_ind);
-
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-
-load_from_mem_sse2(compiler, data1_ind, str_ptr_ind);
-
-/* PSRLDQ xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x73;
-instruction[3] = 0xc0 | (3 << 3) | data2_ind;
-instruction[4] = 16 - diff;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-/* MOVDQA xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x6f;
-instruction[3] = 0xc0 | (tmp_ind << 3) | data1_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* PSLLDQ xmm1, xmm2/m128, imm8 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0x73;
-instruction[3] = 0xc0 | (7 << 3) | tmp_ind;
-instruction[4] = diff;
-sljit_emit_op_custom(compiler, instruction, 5);
-
-/* POR xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xeb;
-instruction[3] = 0xc0 | (data2_ind << 3) | tmp_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-fast_forward_char_pair_sse2_compare(compiler, char1a, char1b, bit1, data1_ind, cmp1a_ind, cmp1b_ind, tmp_ind);
-fast_forward_char_pair_sse2_compare(compiler, char2a, char2b, bit2, data2_ind, cmp2a_ind, cmp2b_ind, tmp_ind);
-
-/* PAND xmm1, xmm2/m128 */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xdb;
-instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* PMOVMSKB reg, xmm */
-/* instruction[0] = 0x66; */
-/* instruction[1] = 0x0f; */
-instruction[2] = 0xd7;
-instruction[3] = 0xc0 | (tmp1_ind << 3) | 0;
-sljit_emit_op_custom(compiler, instruction, 4);
-
-/* BSF r32, r/m32 */
-instruction[0] = 0x0f;
-instruction[1] = 0xbc;
-instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
-sljit_emit_op_custom(compiler, instruction, 3);
-sljit_set_current_flags(compiler, SLJIT_SET_Z);
-
-JUMPTO(SLJIT_ZERO, start);
-
-JUMPHERE(jump[0]);
-
-OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
-
-add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-
-if (common->match_end_ptr != 0)
- OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-if (common->utf)
- {
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));
-
- jump[0] = jump_if_utf_char_start(compiler, TMP1);
-
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart);
-
- add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP));
-
- JUMPHERE(jump[0]);
- }
-#endif
-
-OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
-
-if (common->match_end_ptr != 0)
- OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
-}
-
-static BOOL check_fast_forward_char_pair_sse2(compiler_common *common, fast_forward_char_data *chars, int max)
-{
-sljit_s32 i, j, priority, count;
-sljit_u32 priorities;
-PCRE2_UCHAR a1, a2, b1, b2;
-
-priorities = 0;
-
-count = 0;
-for (i = 0; i < max; i++)
- {
- if (chars[i].last_count > 2)
- {
- SLJIT_ASSERT(chars[i].last_count <= 7);
-
- priorities |= (1 << chars[i].last_count);
- count++;
- }
- }
-
-if (count < 2)
- return FALSE;
-
-for (priority = 7; priority > 2; priority--)
- {
- if ((priorities & (1 << priority)) == 0)
- continue;
+ sljit_s32 i, j, max_i = 0, max_j = 0;
+ sljit_u32 max_pri = 0;
+ PCRE2_UCHAR a1, a2, a_pri, b1, b2, b_pri;
for (i = max - 1; i >= 1; i--)
- if (chars[i].last_count >= priority)
+ {
+ if (chars[i].last_count > 2)
{
- SLJIT_ASSERT(chars[i].count <= 2 && chars[i].count >= 1);
-
a1 = chars[i].chars[0];
a2 = chars[i].chars[1];
+ a_pri = chars[i].last_count;
- j = i - max_fast_forward_char_pair_sse2_offset();
+ j = i - max_fast_forward_char_pair_offset();
if (j < 0)
j = 0;
while (j < i)
{
- if (chars[j].last_count >= priority)
+ b_pri = chars[j].last_count;
+ if (b_pri > 2 && a_pri + b_pri >= max_pri)
{
b1 = chars[j].chars[0];
b2 = chars[j].chars[1];
if (a1 != b1 && a1 != b2 && a2 != b1 && a2 != b2)
{
- fast_forward_char_pair_sse2(common, i, a1, a2, j, b1, b2);
- return TRUE;
+ max_pri = a_pri + b_pri;
+ max_i = i;
+ max_j = j;
}
}
j++;
}
}
- }
-
-return FALSE;
-}
+ }
-#endif
+if (max_pri == 0)
+ return FALSE;
-#undef SSE2_COMPARE_TYPE_INDEX
+fast_forward_char_pair_simd(common, max_i, chars[max_i].chars[0], chars[max_i].chars[1], max_j, chars[max_j].chars[0], chars[max_j].chars[1]);
+return TRUE;
+}
-#endif
+#endif /* JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD */
static void fast_forward_first_char2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
{
@@ -6154,13 +5596,11 @@ if (has_match_end)
CMOV(SLJIT_GREATER, STR_END, TMP1, 0);
}
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
+#ifdef JIT_HAS_FAST_FORWARD_CHAR_SIMD
-/* SSE2 accelerated first character search. */
-
-if (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
+if (JIT_HAS_FAST_FORWARD_CHAR_SIMD)
{
- fast_forward_first_char2_sse2(common, char1, char2, offset);
+ fast_forward_char_simd(common, char1, char2, offset);
if (offset > 0)
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
@@ -6267,8 +5707,8 @@ for (i = 0; i < max; i++)
chars[i].last_count = (chars[i].count == 255) ? 0 : 1;
}
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND) && !(defined _WIN64)
-if (sljit_has_cpu_feature(SLJIT_HAS_SSE2) && check_fast_forward_char_pair_sse2(common, chars, max))
+#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD
+if (JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD && check_fast_forward_char_pair_simd(common, chars, max))
return TRUE;
#endif
@@ -6353,18 +5793,21 @@ if (common->match_end_ptr != 0)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
- OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));
OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0);
CMOV(SLJIT_GREATER, STR_END, TMP1, 0);
}
else
- OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));
+ }
SLJIT_ASSERT(range_right >= 0);
-#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);
-#endif
+if (!HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);
start = LABEL();
add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0));
@@ -6375,11 +5818,11 @@ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1);
#endif
-#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);
-#else
-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);
-#endif
+if (!HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0);
+else
+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table);
+
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start);
@@ -6473,9 +5916,17 @@ if (common->match_end_ptr != 0)
if (common->nltype == NLTYPE_FIXED && common->newline > 255)
{
lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
+ }
firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));
@@ -6503,9 +5954,15 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
return;
}
-OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ }
+else
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));
+
/* Example: match /^/ to \r\n from offset 1. */
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
move_back(common, NULL, FALSE);
@@ -6586,7 +6043,7 @@ if (!optimize_class(common, start_bits, (start_bits[31] & 0x80) != 0, FALSE, &ma
OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits);
- if (sljit_get_register_index(TMP3) >= 0)
+ if (!HAS_VIRTUAL_REGISTERS)
{
OP2(SLJIT_SHL, TMP3, 0, SLJIT_IMM, 1, TMP2, 0);
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP3, 0);
@@ -6693,7 +6150,7 @@ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -sizeof(sljit_sw));
jump = CMP(SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
-if (sljit_get_register_index(TMP3) < 0)
+if (HAS_VIRTUAL_REGISTERS)
{
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw)));
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -(3 * sizeof(sljit_sw)));
@@ -6718,7 +6175,7 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
JUMPHERE(jump);
OP1(SLJIT_NEG, TMP2, 0, TMP2, 0);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
-if (sljit_get_register_index(TMP3) < 0)
+if (HAS_VIRTUAL_REGISTERS)
{
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw)));
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw));
@@ -6737,7 +6194,11 @@ static void check_wordboundary(compiler_common *common)
DEFINE_COMPILER;
struct sljit_jump *skipread;
jump_list *skipread_list = NULL;
-jump_list *invalid_utf = NULL;
+#ifdef SUPPORT_UNICODE
+struct sljit_label *valid_utf;
+jump_list *invalid_utf1 = NULL;
+#endif /* SUPPORT_UNICODE */
+jump_list *invalid_utf2 = NULL;
#if PCRE2_CODE_UNIT_WIDTH != 8 || defined SUPPORT_UNICODE
struct sljit_jump *jump;
#endif /* PCRE2_CODE_UNIT_WIDTH != 8 || SUPPORT_UNICODE */
@@ -6751,14 +6212,30 @@ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
skipread = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
-if (common->mode == PCRE2_JIT_COMPLETE)
- peek_char_back(common, READ_CHAR_MAX, &invalid_utf);
+#ifdef SUPPORT_UNICODE
+if (common->invalid_utf)
+ {
+ peek_char_back(common, READ_CHAR_MAX, &invalid_utf1);
+
+ if (common->mode != PCRE2_JIT_COMPLETE)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
+ move_back(common, NULL, TRUE);
+ check_start_used_ptr(common);
+ OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);
+ }
+ }
else
+#endif /* SUPPORT_UNICODE */
{
- move_back(common, &invalid_utf, FALSE);
- check_start_used_ptr(common);
- /* No need precise read since match fails anyway. */
- read_char(common, 0, READ_CHAR_MAX, &invalid_utf, READ_CHAR_UPDATE_STR_PTR);
+ if (common->mode == PCRE2_JIT_COMPLETE)
+ peek_char_back(common, READ_CHAR_MAX, NULL);
+ else
+ {
+ move_back(common, NULL, TRUE);
+ check_start_used_ptr(common);
+ read_char(common, 0, READ_CHAR_MAX, NULL, READ_CHAR_UPDATE_STR_PTR);
+ }
}
/* Testing char type. */
@@ -6802,10 +6279,13 @@ JUMPHERE(skipread);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
check_str_end(common, &skipread_list);
-peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, &invalid_utf);
+peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, &invalid_utf2);
/* Testing char type. This is a code duplication. */
#ifdef SUPPORT_UNICODE
+
+valid_utf = LABEL();
+
if (common->use_ucp)
{
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
@@ -6851,13 +6331,19 @@ sljit_emit_fast_return(compiler, TMP1, 0);
#ifdef SUPPORT_UNICODE
if (common->invalid_utf)
{
- SLJIT_ASSERT(invalid_utf != NULL);
+ set_jumps(invalid_utf1, LABEL());
+
+ peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, NULL);
+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR, valid_utf);
- set_jumps(invalid_utf, LABEL());
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, -1);
sljit_emit_fast_return(compiler, TMP1, 0);
- return;
+
+ set_jumps(invalid_utf2, LABEL());
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+ OP1(SLJIT_MOV, TMP2, 0, TMP3, 0);
+ sljit_emit_fast_return(compiler, TMP1, 0);
}
#endif /* SUPPORT_UNICODE */
}
@@ -7225,7 +6711,7 @@ struct sljit_label *label;
int char1_reg;
int char2_reg;
-if (sljit_get_register_index(TMP3) < 0)
+if (HAS_VIRTUAL_REGISTERS)
{
char1_reg = STR_END;
char2_reg = STACK_TOP;
@@ -7307,7 +6793,7 @@ int char2_reg;
int lcc_table;
int opt_type = 0;
-if (sljit_get_register_index(TMP3) < 0)
+if (HAS_VIRTUAL_REGISTERS)
{
char2_reg = STACK_TOP;
lcc_table = STACK_LIMIT;
@@ -7790,8 +7276,6 @@ if (needstype || needsscript)
if (needsscript)
{
// PH hacking
-//fprintf(stderr, "~~B\n");
-
OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
@@ -7845,7 +7329,6 @@ if (needstype || needsscript)
if (!needschar)
{
// PH hacking
-//fprintf(stderr, "~~C\n");
OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
@@ -7860,7 +7343,6 @@ if (needstype || needsscript)
else
{
// PH hacking
-//fprintf(stderr, "~~D\n");
OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
@@ -8174,14 +7656,24 @@ struct sljit_label *label;
switch(type)
{
case OP_SOD:
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ }
+ else
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
return cc;
case OP_SOM:
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ }
+ else
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
return cc;
@@ -8191,9 +7683,7 @@ switch(type)
#ifdef SUPPORT_UNICODE
if (common->invalid_utf)
{
- OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_SIG_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0);
- add_jump(compiler, backtracks, JUMP(SLJIT_SIG_LESS));
- add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_NOT_ZERO : SLJIT_ZERO));
+ add_jump(compiler, backtracks, CMP((type == OP_NOT_WORD_BOUNDARY) ? SLJIT_NOT_EQUAL : SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0));
return cc;
}
#endif /* SUPPORT_UNICODE */
@@ -8267,17 +7757,24 @@ switch(type)
JUMPHERE(jump[3]);
}
JUMPHERE(jump[0]);
- check_partial(common, FALSE);
+ if (common->mode != PCRE2_JIT_COMPLETE)
+ check_partial(common, TRUE);
return cc;
case OP_EOD:
add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0));
- check_partial(common, FALSE);
+ if (common->mode != PCRE2_JIT_COMPLETE)
+ check_partial(common, TRUE);
return cc;
case OP_DOLL:
- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ }
+ else
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
if (!common->endonly)
@@ -8291,8 +7788,13 @@ switch(type)
case OP_DOLLM:
jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ }
+ else
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
check_partial(common, FALSE);
jump[0] = JUMP(SLJIT_JUMP);
@@ -8327,18 +7829,38 @@ switch(type)
return cc;
case OP_CIRC:
- OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
- add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
- add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
+ }
return cc;
case OP_CIRCM:
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
- jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ /* TMP2 might be used by peek_char_back. */
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
+ jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);
+ OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ }
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32));
jump[0] = JUMP(SLJIT_JUMP);
JUMPHERE(jump[1]);
@@ -8367,11 +7889,16 @@ switch(type)
length = GET(cc, 0);
if (length == 0)
return cc + LINK_SIZE;
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
+ }
+ else
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
#ifdef SUPPORT_UNICODE
if (common->utf)
{
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, length);
label = LABEL();
add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0));
@@ -8382,9 +7909,8 @@ switch(type)
else
#endif
{
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length));
- add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0));
+ add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0));
}
check_start_used_ptr(common);
return cc + LINK_SIZE;
@@ -8402,12 +7928,12 @@ static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc)
PCRE2_SPTR start_subject = args->begin;
PCRE2_SPTR end_subject = args->end;
int lgb, rgb, ricount;
-PCRE2_SPTR prevcc, startcc, bptr;
+PCRE2_SPTR prevcc, endcc, bptr;
BOOL first = TRUE;
uint32_t c;
prevcc = cc;
-startcc = NULL;
+endcc = NULL;
do
{
GETCHARINC(c, cc);
@@ -8416,7 +7942,7 @@ do
if (first)
{
lgb = rgb;
- startcc = cc;
+ endcc = cc;
first = FALSE;
continue;
}
@@ -8455,25 +7981,27 @@ do
lgb != ucp_gbExtended_Pictographic)
lgb = rgb;
- prevcc = startcc;
- startcc = cc;
+ prevcc = endcc;
+ endcc = cc;
}
while (cc < end_subject);
-return startcc;
+return endcc;
}
+#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */
+
static PCRE2_SPTR SLJIT_FUNC do_extuni_utf_invalid(jit_arguments *args, PCRE2_SPTR cc)
{
PCRE2_SPTR start_subject = args->begin;
PCRE2_SPTR end_subject = args->end;
int lgb, rgb, ricount;
-PCRE2_SPTR prevcc, startcc, bptr;
+PCRE2_SPTR prevcc, endcc, bptr;
BOOL first = TRUE;
uint32_t c;
prevcc = cc;
-startcc = NULL;
+endcc = NULL;
do
{
GETCHARINC_INVALID(c, cc, end_subject, break);
@@ -8482,7 +8010,7 @@ do
if (first)
{
lgb = rgb;
- startcc = cc;
+ endcc = cc;
first = FALSE;
continue;
}
@@ -8520,16 +8048,14 @@ do
lgb != ucp_gbExtended_Pictographic)
lgb = rgb;
- prevcc = startcc;
- startcc = cc;
+ prevcc = endcc;
+ endcc = cc;
}
while (cc < end_subject);
-return startcc;
+return endcc;
}
-#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */
-
static PCRE2_SPTR SLJIT_FUNC do_extuni_no_utf(jit_arguments *args, PCRE2_SPTR cc)
{
PCRE2_SPTR start_subject = args->begin;
@@ -8538,7 +8064,10 @@ int lgb, rgb, ricount;
PCRE2_SPTR bptr;
uint32_t c;
-GETCHARINC(c, cc);
+/* Patch by PH */
+/* GETCHARINC(c, cc); */
+c = *cc++;
+
#if PCRE2_CODE_UNIT_WIDTH == 32
if (c >= 0x110000)
return NULL;
@@ -8800,8 +8329,10 @@ switch(type)
if (common->invalid_utf)
add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
#else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_extuni_no_utf));
- add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,
+ common->invalid_utf ? SLJIT_FUNC_OFFSET(do_extuni_utf_invalid) : SLJIT_FUNC_OFFSET(do_extuni_no_utf));
+ if (!common->utf || common->invalid_utf)
+ add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
#endif
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
@@ -9198,8 +8729,6 @@ if (common->utf && *cc == OP_REFI)
CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop);
// PH hacking
-//fprintf(stderr, "~~E\n");
-
OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
@@ -10759,10 +10288,23 @@ if (ket != OP_KET || bra != OP_BRA)
if (offset != 0)
stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);
+/* Skip and count the other alternatives. */
+i = 1;
+while (*cc == OP_ALT)
+ {
+ cc += GET(cc, 1);
+ i++;
+ }
+
if (has_alternatives)
{
if (opcode != OP_ONCE)
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
+ {
+ if (i <= 3)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
+ else
+ BACKTRACK_AS(bracket_backtrack)->u.matching_put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));
+ }
if (ket != OP_KETRMAX)
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
}
@@ -10851,9 +10393,6 @@ if (bra == OP_BRAMINZERO)
if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
count_match(common);
-/* Skip the other alternatives. */
-while (*cc == OP_ALT)
- cc += GET(cc, 1);
cc += 1 + LINK_SIZE;
if (opcode == OP_ONCE)
@@ -11412,174 +10951,232 @@ switch(opcode)
JUMPTO(SLJIT_JUMP, label);
if (jump != NULL)
JUMPHERE(jump);
+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
+ break;
}
- else
- {
- charpos_enabled = FALSE;
- charpos_char = 0;
- charpos_othercasebit = 0;
-
- if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI))
- {
- charpos_enabled = TRUE;
#ifdef SUPPORT_UNICODE
- charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]);
-#endif
- if (charpos_enabled && *end == OP_CHARI && char_has_othercase(common, end + 1))
- {
- charpos_othercasebit = char_get_othercase_bit(common, end + 1);
- if (charpos_othercasebit == 0)
- charpos_enabled = FALSE;
- }
-
- if (charpos_enabled)
- {
- charpos_char = end[1];
- /* Consumpe the OP_CHAR opcode. */
- end += 2;
-#if PCRE2_CODE_UNIT_WIDTH == 8
- SLJIT_ASSERT((charpos_othercasebit >> 8) == 0);
-#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
- SLJIT_ASSERT((charpos_othercasebit >> 9) == 0);
- if ((charpos_othercasebit & 0x100) != 0)
- charpos_othercasebit = (charpos_othercasebit & 0xff) << 8;
+ else if (type == OP_ALLANY && !common->invalid_utf)
+#else
+ else if (type == OP_ALLANY)
#endif
- if (charpos_othercasebit != 0)
- charpos_char |= charpos_othercasebit;
-
- BACKTRACK_AS(char_iterator_backtrack)->u.charpos.enabled = TRUE;
- BACKTRACK_AS(char_iterator_backtrack)->u.charpos.chr = charpos_char;
- BACKTRACK_AS(char_iterator_backtrack)->u.charpos.othercasebit = charpos_othercasebit;
- }
- }
-
- if (charpos_enabled)
+ {
+ if (opcode == OP_STAR)
{
- if (opcode == OP_UPTO)
- OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max + 1);
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
- /* Search the first instance of charpos_char. */
- jump = JUMP(SLJIT_JUMP);
- label = LABEL();
- if (opcode == OP_UPTO)
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO));
- }
- compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);
- if (fast_str_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
- JUMPHERE(jump);
+ OP1(SLJIT_MOV, base, offset0, STR_END, 0);
+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
- detect_partial_match(common, &backtrack->topbacktracks);
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
- if (charpos_othercasebit != 0)
- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
+ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
+ process_partial_match(common);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_END, 0);
+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
+ break;
+ }
+#ifdef SUPPORT_UNICODE
+ else if (!common->utf)
+#else
+ else
+#endif
+ {
if (private_data_ptr == 0)
allocate_stack(common, 2);
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+
OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
- if (opcode == OP_UPTO)
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
- }
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max));
- /* Search the last instance of charpos_char. */
- label = LABEL();
- compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
- if (fast_str_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
- detect_partial_match(common, &no_match);
- OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
- if (charpos_othercasebit != 0)
- OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
- if (opcode == OP_STAR)
+ if (common->mode == PCRE2_JIT_COMPLETE)
{
- CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
}
else
{
- jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char);
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);
+ process_partial_match(common);
JUMPHERE(jump);
}
- if (opcode == OP_UPTO)
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- JUMPTO(SLJIT_NOT_ZERO, label);
- }
- else
- JUMPTO(SLJIT_JUMP, label);
-
- set_jumps(no_match, LABEL());
- OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
+ break;
}
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
- else if (common->utf)
+ }
+
+ charpos_enabled = FALSE;
+ charpos_char = 0;
+ charpos_othercasebit = 0;
+
+ if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI))
+ {
+#ifdef SUPPORT_UNICODE
+ charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]);
+#else
+ charpos_enabled = TRUE;
+#endif
+ if (charpos_enabled && *end == OP_CHARI && char_has_othercase(common, end + 1))
{
- if (private_data_ptr == 0)
- allocate_stack(common, 2);
+ charpos_othercasebit = char_get_othercase_bit(common, end + 1);
+ if (charpos_othercasebit == 0)
+ charpos_enabled = FALSE;
+ }
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
- OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+ if (charpos_enabled)
+ {
+ charpos_char = end[1];
+ /* Consumpe the OP_CHAR opcode. */
+ end += 2;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ SLJIT_ASSERT((charpos_othercasebit >> 8) == 0);
+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
+ SLJIT_ASSERT((charpos_othercasebit >> 9) == 0);
+ if ((charpos_othercasebit & 0x100) != 0)
+ charpos_othercasebit = (charpos_othercasebit & 0xff) << 8;
+#endif
+ if (charpos_othercasebit != 0)
+ charpos_char |= charpos_othercasebit;
- if (opcode == OP_UPTO)
- OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+ BACKTRACK_AS(char_iterator_backtrack)->u.charpos.enabled = TRUE;
+ BACKTRACK_AS(char_iterator_backtrack)->u.charpos.chr = charpos_char;
+ BACKTRACK_AS(char_iterator_backtrack)->u.charpos.othercasebit = charpos_othercasebit;
+ }
+ }
- label = LABEL();
- compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ if (charpos_enabled)
+ {
+ if (opcode == OP_UPTO)
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max + 1);
- if (opcode == OP_UPTO)
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- JUMPTO(SLJIT_NOT_ZERO, label);
- }
- else
- JUMPTO(SLJIT_JUMP, label);
+ /* Search the first instance of charpos_char. */
+ jump = JUMP(SLJIT_JUMP);
+ label = LABEL();
+ if (opcode == OP_UPTO)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO));
+ }
+ compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ JUMPHERE(jump);
- set_jumps(no_match, LABEL());
- OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
- if (fast_str_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ detect_partial_match(common, &backtrack->topbacktracks);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ if (charpos_othercasebit != 0)
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
+
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+ if (opcode == OP_UPTO)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
+ }
+
+ /* Search the last instance of charpos_char. */
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ detect_partial_match(common, &no_match);
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
+ if (charpos_othercasebit != 0)
+ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit);
+ if (opcode == OP_STAR)
+ {
+ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
}
-#endif
else
{
- if (private_data_ptr == 0)
- allocate_stack(common, 2);
+ jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ JUMPHERE(jump);
+ }
- OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
- if (opcode == OP_UPTO)
- OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+ if (opcode == OP_UPTO)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ JUMPTO(SLJIT_NOT_ZERO, label);
+ }
+ else
+ JUMPTO(SLJIT_JUMP, label);
- label = LABEL();
- detect_partial_match(common, &no_match);
- compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
- if (opcode == OP_UPTO)
- {
- OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- JUMPTO(SLJIT_NOT_ZERO, label);
- OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- }
- else
- JUMPTO(SLJIT_JUMP, label);
+ set_jumps(no_match, LABEL());
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ }
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ else if (common->utf)
+ {
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
- set_jumps(no_char1_match, LABEL());
- OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- set_jumps(no_match, LABEL());
- OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
- if (fast_str_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+
+ if (opcode == OP_UPTO)
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+
+ detect_partial_match(common, &no_match);
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+
+ if (opcode == OP_UPTO)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
+ }
+
+ detect_partial_match_to(common, label);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+ set_jumps(no_match, LABEL());
+ OP1(SLJIT_MOV, STR_PTR, 0, base, offset0);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ }
+#endif
+ else
+ {
+ if (private_data_ptr == 0)
+ allocate_stack(common, 2);
+
+ OP1(SLJIT_MOV, base, offset1, STR_PTR, 0);
+ if (opcode == OP_UPTO)
+ OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+
+ detect_partial_match(common, &no_match);
+ label = LABEL();
+ compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
+ if (opcode == OP_UPTO)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
}
+
+ detect_partial_match_to(common, label);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
+ set_jumps(no_char1_match, LABEL());
+ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ set_jumps(no_match, LABEL());
+ OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
}
+
BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL();
break;
@@ -11616,25 +11213,47 @@ switch(opcode)
break;
case OP_POSSTAR:
+#if defined SUPPORT_UNICODE
+ if (type == OP_ALLANY && !common->invalid_utf)
+#else
+ if (type == OP_ALLANY)
+#endif
+ {
+ OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
+ process_partial_match(common);
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_END, 0);
+ break;
+ }
+
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf)
{
OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
+ detect_partial_match(common, &no_match);
label = LABEL();
- compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
- JUMPTO(SLJIT_JUMP, label);
+ detect_partial_match_to(common, label);
+
set_jumps(no_match, LABEL());
OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset);
if (fast_str_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ {
+ if (tmp_base == TMP3)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, TMP3, 0);
+ else
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ }
break;
}
#endif
- label = LABEL();
detect_partial_match(common, &no_match);
+ label = LABEL();
compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
- JUMPTO(SLJIT_JUMP, label);
+ detect_partial_match_to(common, label);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
set_jumps(no_char1_match, LABEL());
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
set_jumps(no_match, LABEL());
@@ -11649,23 +11268,52 @@ switch(opcode)
{
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);
OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
+
+ detect_partial_match(common, &no_match);
label = LABEL();
- compile_char1_matchingpath(common, type, cc, &no_match, TRUE);
+ compile_char1_matchingpath(common, type, cc, &no_match, FALSE);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);
OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- JUMPTO(SLJIT_NOT_ZERO, label);
+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
+ detect_partial_match_to(common, label);
+
set_jumps(no_match, LABEL());
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1);
break;
}
#endif
+
+ if (type == OP_ALLANY)
+ {
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(max));
+
+ if (common->mode == PCRE2_JIT_COMPLETE)
+ {
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
+ }
+ else
+ {
+ jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);
+ process_partial_match(common);
+ JUMPHERE(jump);
+ }
+
+ if (fast_str_ptr != 0)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0);
+ break;
+ }
+
OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max);
- label = LABEL();
+
detect_partial_match(common, &no_match);
+ label = LABEL();
compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE);
OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1);
- JUMPTO(SLJIT_NOT_ZERO, label);
+ add_jump(compiler, &no_match, JUMP(SLJIT_ZERO));
+ detect_partial_match_to(common, label);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+
set_jumps(no_char1_match, LABEL());
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
set_jumps(no_match, LABEL());
@@ -11719,8 +11367,15 @@ if (common->accept_label == NULL)
add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)));
else
CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label);
-OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));
+
+if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));
+ }
+else
+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options));
+
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_NOT_ZERO));
OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);
@@ -11728,7 +11383,8 @@ if (common->accept_label == NULL)
add_jump(compiler, &common->accept, JUMP(SLJIT_ZERO));
else
JUMPTO(SLJIT_ZERO, common->accept_label);
-OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+
+OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));
if (common->accept_label == NULL)
add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0));
else
@@ -11778,10 +11434,11 @@ if (opcode == OP_SKIP)
if (opcode == OP_COMMIT_ARG || opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG)
{
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ if (HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);
- OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
}
return ccend;
@@ -12072,11 +11729,12 @@ while (cc < ccend)
SLJIT_ASSERT(common->mark_ptr != 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
allocate_stack(common, common->has_skip_arg ? 5 : 1);
- OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ if (HAS_VIRTUAL_REGISTERS)
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0);
- OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(HAS_VIRTUAL_REGISTERS ? TMP1 : ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0);
if (common->has_skip_arg)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
@@ -12403,16 +12061,15 @@ PCRE2_SPTR ccprev;
PCRE2_UCHAR bra = OP_BRA;
PCRE2_UCHAR ket;
assert_backtrack *assert;
-sljit_uw *next_update_addr = NULL;
BOOL has_alternatives;
BOOL needs_control_head = FALSE;
struct sljit_jump *brazero = NULL;
-struct sljit_jump *alt1 = NULL;
-struct sljit_jump *alt2 = NULL;
+struct sljit_jump *next_alt = NULL;
struct sljit_jump *once = NULL;
struct sljit_jump *cond = NULL;
struct sljit_label *rmin_label = NULL;
struct sljit_label *exact_label = NULL;
+struct sljit_put_label *put_label = NULL;
if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
{
@@ -12561,7 +12218,7 @@ else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)
free_stack(common, 1);
alt_max = 2;
- alt1 = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
}
}
else if (has_alternatives)
@@ -12569,21 +12226,15 @@ else if (has_alternatives)
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
free_stack(common, 1);
- if (alt_max > 4)
+ if (alt_max > 3)
{
- /* Table jump if alt_max is greater than 4. */
- next_update_addr = allocate_read_only_data(common, alt_max * sizeof(sljit_uw));
- if (SLJIT_UNLIKELY(next_update_addr == NULL))
- return;
- sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)next_update_addr);
- add_label_addr(common, next_update_addr++);
+ sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0);
+
+ SLJIT_ASSERT(CURRENT_AS(bracket_backtrack)->u.matching_put_label);
+ sljit_set_put_label(CURRENT_AS(bracket_backtrack)->u.matching_put_label, LABEL());
}
else
- {
- if (alt_max == 4)
- alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
- alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
- }
+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
}
COMPILE_BACKTRACKINGPATH(current->top);
@@ -12620,7 +12271,7 @@ if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND))
if (has_alternatives)
{
- alt_count = sizeof(sljit_uw);
+ alt_count = 1;
do
{
current->top = NULL;
@@ -12699,7 +12350,12 @@ if (has_alternatives)
stacksize = match_capture_common(common, stacksize, offset, private_data_ptr);
if (opcode != OP_ONCE)
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count);
+ {
+ if (alt_max <= 3)
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count);
+ else
+ put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));
+ }
if (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0)
{
@@ -12712,24 +12368,18 @@ if (has_alternatives)
if (opcode != OP_ONCE)
{
- if (alt_max > 4)
- add_label_addr(common, next_update_addr++);
- else
+ if (alt_max <= 3)
{
- if (alt_count != 2 * sizeof(sljit_uw))
- {
- JUMPHERE(alt1);
- if (alt_max == 3 && alt_count == sizeof(sljit_uw))
- alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
- }
- else
+ JUMPHERE(next_alt);
+ alt_count++;
+ if (alt_count < alt_max)
{
- JUMPHERE(alt2);
- if (alt_max == 4)
- alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw));
+ SLJIT_ASSERT(alt_count == 2 && alt_max == 3);
+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 1);
}
}
- alt_count += sizeof(sljit_uw);
+ else
+ sljit_set_put_label(put_label, LABEL());
}
COMPILE_BACKTRACKINGPATH(current->top);
@@ -13219,11 +12869,10 @@ int private_data_size = get_recurse_data_length(common, ccbegin, ccend, &needs_c
int alt_count, alt_max, local_size;
backtrack_common altbacktrack;
jump_list *match = NULL;
-sljit_uw *next_update_addr = NULL;
-struct sljit_jump *alt1 = NULL;
-struct sljit_jump *alt2 = NULL;
+struct sljit_jump *next_alt = NULL;
struct sljit_jump *accept_exit = NULL;
struct sljit_label *quit;
+struct sljit_put_label *put_label;
/* Recurse captures then. */
common->then_trap = NULL;
@@ -13284,7 +12933,12 @@ while (1)
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);
if (alt_max > 1 || has_accept)
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count);
+ {
+ if (alt_max > 3)
+ put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(1));
+ else
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count);
+ }
add_jump(compiler, &match, JUMP(SLJIT_JUMP));
@@ -13298,7 +12952,7 @@ while (1)
sljit_emit_fast_enter(compiler, TMP1, 0);
if (has_accept)
- accept_exit = CMP(SLJIT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_max * sizeof (sljit_sw));
+ accept_exit = CMP(SLJIT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
/* Save return address. */
@@ -13311,44 +12965,30 @@ while (1)
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
free_stack(common, 2);
- if (alt_max > 4)
+ if (alt_max > 3)
{
- /* Table jump if alt_max is greater than 4. */
- next_update_addr = allocate_read_only_data(common, alt_max * sizeof(sljit_uw));
- if (SLJIT_UNLIKELY(next_update_addr == NULL))
- return;
- sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)next_update_addr);
- add_label_addr(common, next_update_addr++);
+ sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0);
+ sljit_set_put_label(put_label, LABEL());
}
else
- {
- if (alt_max == 4)
- alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
- alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw));
- }
+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
}
else
free_stack(common, has_accept ? 2 : 1);
}
- else if (alt_max > 4)
- add_label_addr(common, next_update_addr++);
+ else if (alt_max > 3)
+ sljit_set_put_label(put_label, LABEL());
else
{
- if (alt_count != 2 * sizeof(sljit_uw))
- {
- JUMPHERE(alt1);
- if (alt_max == 3 && alt_count == sizeof(sljit_uw))
- alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw));
- }
- else
+ JUMPHERE(next_alt);
+ if (alt_count + 1 < alt_max)
{
- JUMPHERE(alt2);
- if (alt_max == 4)
- alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw));
+ SLJIT_ASSERT(alt_count == 1 && alt_max == 3);
+ next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 1);
}
}
- alt_count += sizeof(sljit_uw);
+ alt_count++;
compile_backtrackingpath(common, altbacktrack.top);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
@@ -13409,7 +13049,7 @@ if (common->accept != NULL)
OP1(SLJIT_MOV, TMP2, 0, STACK_TOP, 0);
allocate_stack(common, 2);
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);
}
set_jumps(match, LABEL());
@@ -13444,7 +13084,6 @@ executable_functions *functions;
void *executable_func;
sljit_uw executable_size;
sljit_uw total_length;
-label_addr_list *label_addr;
struct sljit_label *mainloop_label = NULL;
struct sljit_label *continue_match_label;
struct sljit_label *empty_match_found_label = NULL;
@@ -13459,6 +13098,14 @@ struct sljit_jump *end_anchor_failed = NULL;
SLJIT_ASSERT(tables);
+#if HAS_VIRTUAL_REGISTERS == 1
+SLJIT_ASSERT(sljit_get_register_index(TMP3) < 0 && sljit_get_register_index(ARGUMENTS) < 0 && sljit_get_register_index(RETURN_ADDR) < 0);
+#elif HAS_VIRTUAL_REGISTERS == 0
+SLJIT_ASSERT(sljit_get_register_index(TMP3) >= 0 && sljit_get_register_index(ARGUMENTS) >= 0 && sljit_get_register_index(RETURN_ADDR) >= 0);
+#else
+#error "Invalid value for HAS_VIRTUAL_REGISTERS"
+#endif
+
memset(&rootbacktrack, 0, sizeof(backtrack_common));
memset(common, 0, sizeof(compiler_common));
common->re = re;
@@ -13476,6 +13123,7 @@ common->fcc = tables + fcc_offset;
common->lcc = (sljit_sw)(tables + lcc_offset);
common->mode = mode;
common->might_be_empty = re->minlength == 0;
+common->allow_empty_partial = (re->max_lookbehind > 0) || (re->flags & PCRE2_MATCH_EMPTY) != 0;
common->nltype = NLTYPE_FIXED;
switch(re->newline_convention)
{
@@ -13742,7 +13390,7 @@ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
sljit_free_compiler(compiler);
SLJIT_FREE(common->optimized_cbracket, allocator_data);
SLJIT_FREE(common->private_data_ptrs, allocator_data);
- PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
@@ -13796,7 +13444,7 @@ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
sljit_free_compiler(compiler);
SLJIT_FREE(common->optimized_cbracket, allocator_data);
SLJIT_FREE(common->private_data_ptrs, allocator_data);
- PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
@@ -13885,7 +13533,7 @@ while (common->currententry != NULL)
sljit_free_compiler(compiler);
SLJIT_FREE(common->optimized_cbracket, allocator_data);
SLJIT_FREE(common->private_data_ptrs, allocator_data);
- PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
flush_stubs(common);
@@ -14028,16 +13676,11 @@ SLJIT_FREE(common->private_data_ptrs, allocator_data);
executable_func = sljit_generate_code(compiler);
executable_size = sljit_get_generated_code_size(compiler);
-label_addr = common->label_addrs;
-while (label_addr != NULL)
- {
- *label_addr->update_addr = sljit_get_label_addr(label_addr->label);
- label_addr = label_addr->next;
- }
sljit_free_compiler(compiler);
+
if (executable_func == NULL)
{
- PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
@@ -14052,7 +13695,7 @@ else
/* This case is highly unlikely since we just recently
freed a lot of memory. Not impossible though. */
sljit_free_code(executable_func);
- PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
memset(functions, 0, sizeof(executable_functions));
@@ -14097,18 +13740,12 @@ Returns: 0: success or (*NOJIT) was used
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_jit_compile(pcre2_code *code, uint32_t options)
{
-#ifndef SUPPORT_JIT
-
-(void)code;
-(void)options;
-return PCRE2_ERROR_JIT_BADOPTION;
-
-#else /* SUPPORT_JIT */
-
pcre2_real_code *re = (pcre2_real_code *)code;
-executable_functions *functions;
-uint32_t excluded_options;
-int result;
+
+#ifdef SUPPORT_JIT
+executable_functions *functions = (executable_functions *)re->executable_jit;
+static int executable_allocator_is_working = 0;
+#endif
if (code == NULL)
return PCRE2_ERROR_NULL;
@@ -14116,30 +13753,98 @@ if (code == NULL)
if ((options & ~PUBLIC_JIT_COMPILE_OPTIONS) != 0)
return PCRE2_ERROR_JIT_BADOPTION;
+/* Support for invalid UTF was first introduced in JIT, with the option
+PCRE2_JIT_INVALID_UTF. Later, support was added to the interpreter, and the
+compile-time option PCRE2_MATCH_INVALID_UTF was created. This is now the
+preferred feature, with the earlier option deprecated. However, for backward
+compatibility, if the earlier option is set, it forces the new option so that
+if JIT matching falls back to the interpreter, there is still support for
+invalid UTF. However, if this function has already been successfully called
+without PCRE2_JIT_INVALID_UTF and without PCRE2_MATCH_INVALID_UTF (meaning that
+non-invalid-supporting JIT code was compiled), give an error.
+
+If in the future support for PCRE2_JIT_INVALID_UTF is withdrawn, the following
+actions are needed:
+
+ 1. Remove the definition from pcre2.h.in and from the list in
+ PUBLIC_JIT_COMPILE_OPTIONS above.
+
+ 2. Replace PCRE2_JIT_INVALID_UTF with a local flag in this module.
+
+ 3. Replace PCRE2_JIT_INVALID_UTF in pcre2_jit_test.c.
+
+ 4. Delete the following short block of code. The setting of "re" and
+ "functions" can be moved into the JIT-only block below, but if that is
+ done, (void)re and (void)functions will be needed in the non-JIT case, to
+ avoid compiler warnings.
+*/
+
+if ((options & PCRE2_JIT_INVALID_UTF) != 0)
+ {
+ if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) == 0)
+ {
+#ifdef SUPPORT_JIT
+ if (functions != NULL) return PCRE2_ERROR_JIT_BADOPTION;
+#endif
+ re->overall_options |= PCRE2_MATCH_INVALID_UTF;
+ }
+ }
+
+/* The above tests are run with and without JIT support. This means that
+PCRE2_JIT_INVALID_UTF propagates back into the regex options (ensuring
+interpreter support) even in the absence of JIT. But now, if there is no JIT
+support, give an error return. */
+
+#ifndef SUPPORT_JIT
+return PCRE2_ERROR_JIT_BADOPTION;
+#else /* SUPPORT_JIT */
+
+/* There is JIT support. Do the necessary. */
+
if ((re->flags & PCRE2_NOJIT) != 0) return 0;
-functions = (executable_functions *)re->executable_jit;
+if (executable_allocator_is_working == 0)
+ {
+ /* Checks whether the executable allocator is working. This check
+ might run multiple times in multi-threaded environments, but the
+ result should not be affected by it. */
+ void *ptr = SLJIT_MALLOC_EXEC(32);
+
+ executable_allocator_is_working = -1;
+
+ if (ptr != NULL)
+ {
+ SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr));
+ executable_allocator_is_working = 1;
+ }
+ }
+
+if (executable_allocator_is_working < 0)
+ return PCRE2_ERROR_NOMEMORY;
+
+if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0)
+ options |= PCRE2_JIT_INVALID_UTF;
if ((options & PCRE2_JIT_COMPLETE) != 0 && (functions == NULL
|| functions->executable_funcs[0] == NULL)) {
- excluded_options = (PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_PARTIAL_HARD);
- result = jit_compile(code, options & ~excluded_options);
+ uint32_t excluded_options = (PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_PARTIAL_HARD);
+ int result = jit_compile(code, options & ~excluded_options);
if (result != 0)
return result;
}
if ((options & PCRE2_JIT_PARTIAL_SOFT) != 0 && (functions == NULL
|| functions->executable_funcs[1] == NULL)) {
- excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_HARD);
- result = jit_compile(code, options & ~excluded_options);
+ uint32_t excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_HARD);
+ int result = jit_compile(code, options & ~excluded_options);
if (result != 0)
return result;
}
if ((options & PCRE2_JIT_PARTIAL_HARD) != 0 && (functions == NULL
|| functions->executable_funcs[2] == NULL)) {
- excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT);
- result = jit_compile(code, options & ~excluded_options);
+ uint32_t excluded_options = (PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT);
+ int result = jit_compile(code, options & ~excluded_options);
if (result != 0)
return result;
}
diff --git a/thirdparty/pcre2/src/pcre2_jit_match.c b/thirdparty/pcre2/src/pcre2_jit_match.c
index eee038644d..7e13b8cfee 100644
--- a/thirdparty/pcre2/src/pcre2_jit_match.c
+++ b/thirdparty/pcre2/src/pcre2_jit_match.c
@@ -74,7 +74,6 @@ Arguments:
options option bits
match_data points to a match_data block
mcontext points to a match context
- jit_stack points to a JIT stack
Returns: > 0 => success; value is the number of ovector pairs filled
= 0 => success, but ovector is not big enough
diff --git a/thirdparty/pcre2/src/pcre2_jit_neon_inc.h b/thirdparty/pcre2/src/pcre2_jit_neon_inc.h
new file mode 100644
index 0000000000..55b1f32ac9
--- /dev/null
+++ b/thirdparty/pcre2/src/pcre2_jit_neon_inc.h
@@ -0,0 +1,321 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ This module by Zoltan Herczeg and Sebastian Pop
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+# if defined(FFCS)
+# if defined(FF_UTF)
+# define FF_FUN ffcs_utf
+# else
+# define FF_FUN ffcs
+# endif
+
+# elif defined(FFCS_2)
+# if defined(FF_UTF)
+# define FF_FUN ffcs_2_utf
+# else
+# define FF_FUN ffcs_2
+# endif
+
+# elif defined(FFCS_MASK)
+# if defined(FF_UTF)
+# define FF_FUN ffcs_mask_utf
+# else
+# define FF_FUN ffcs_mask
+# endif
+
+# elif defined(FFCPS_0)
+# if defined (FF_UTF)
+# define FF_FUN ffcps_0_utf
+# else
+# define FF_FUN ffcps_0
+# endif
+
+# elif defined (FFCPS_1)
+# if defined (FF_UTF)
+# define FF_FUN ffcps_1_utf
+# else
+# define FF_FUN ffcps_1
+# endif
+
+# elif defined (FFCPS_DEFAULT)
+# if defined (FF_UTF)
+# define FF_FUN ffcps_default_utf
+# else
+# define FF_FUN ffcps_default
+# endif
+# endif
+
+static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 *str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)
+#undef FF_FUN
+{
+quad_word qw;
+int_char ic;
+ic.x = chars;
+
+#if defined(FFCS)
+sljit_u8 c1 = ic.c.c1;
+vect_t vc1 = VDUPQ(c1);
+
+#elif defined(FFCS_2)
+sljit_u8 c1 = ic.c.c1;
+vect_t vc1 = VDUPQ(c1);
+sljit_u8 c2 = ic.c.c2;
+vect_t vc2 = VDUPQ(c2);
+
+#elif defined(FFCS_MASK)
+sljit_u8 c1 = ic.c.c1;
+vect_t vc1 = VDUPQ(c1);
+sljit_u8 mask = ic.c.c2;
+vect_t vmask = VDUPQ(mask);
+#endif
+
+#if defined(FFCPS)
+compare_type compare1_type = compare_match1;
+compare_type compare2_type = compare_match1;
+vect_t cmp1a, cmp1b, cmp2a, cmp2b;
+const sljit_u32 diff = IN_UCHARS(offs1 - offs2);
+PCRE2_UCHAR char1a = ic.c.c1;
+PCRE2_UCHAR char2a = ic.c.c3;
+
+# ifdef FFCPS_CHAR1A2A
+cmp1a = VDUPQ(char1a);
+cmp2a = VDUPQ(char2a);
+# else
+PCRE2_UCHAR char1b = ic.c.c2;
+PCRE2_UCHAR char2b = ic.c.c4;
+if (char1a == char1b)
+ cmp1a = VDUPQ(char1a);
+else
+ {
+ sljit_u32 bit1 = char1a ^ char1b;
+ if (is_powerof2(bit1))
+ {
+ compare1_type = compare_match1i;
+ cmp1a = VDUPQ(char1a | bit1);
+ cmp1b = VDUPQ(bit1);
+ }
+ else
+ {
+ compare1_type = compare_match2;
+ cmp1a = VDUPQ(char1a);
+ cmp1b = VDUPQ(char1b);
+ }
+ }
+
+if (char2a == char2b)
+ cmp2a = VDUPQ(char2a);
+else
+ {
+ sljit_u32 bit2 = char2a ^ char2b;
+ if (is_powerof2(bit2))
+ {
+ compare2_type = compare_match1i;
+ cmp2a = VDUPQ(char2a | bit2);
+ cmp2b = VDUPQ(bit2);
+ }
+ else
+ {
+ compare2_type = compare_match2;
+ cmp2a = VDUPQ(char2a);
+ cmp2b = VDUPQ(char2b);
+ }
+ }
+# endif
+
+str_ptr += IN_UCHARS(offs1);
+#endif
+
+#if PCRE2_CODE_UNIT_WIDTH != 8
+vect_t char_mask = VDUPQ(0xff);
+#endif
+
+#if defined(FF_UTF)
+restart:;
+#endif
+
+#if defined(FFCPS)
+sljit_u8 *p1 = str_ptr - diff;
+#endif
+sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);
+str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);
+vect_t data = VLD1Q(str_ptr);
+#if PCRE2_CODE_UNIT_WIDTH != 8
+data = VANDQ(data, char_mask);
+#endif
+
+#if defined(FFCS)
+vect_t eq = VCEQQ(data, vc1);
+
+#elif defined(FFCS_2)
+vect_t eq1 = VCEQQ(data, vc1);
+vect_t eq2 = VCEQQ(data, vc2);
+vect_t eq = VORRQ(eq1, eq2);
+
+#elif defined(FFCS_MASK)
+vect_t eq = VORRQ(data, vmask);
+eq = VCEQQ(eq, vc1);
+
+#elif defined(FFCPS)
+# if defined(FFCPS_DIFF1)
+vect_t prev_data = data;
+# endif
+
+vect_t data2;
+if (p1 < str_ptr)
+ {
+ data2 = VLD1Q(str_ptr - diff);
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ data2 = VANDQ(data2, char_mask);
+#endif
+ }
+else
+ data2 = shift_left_n_lanes(data, offs1 - offs2);
+
+data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
+data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
+vect_t eq = VANDQ(data, data2);
+#endif
+
+VST1Q(qw.mem, eq);
+/* Ignore matches before the first STR_PTR. */
+if (align_offset < 8)
+ {
+ qw.dw[0] >>= align_offset * 8;
+ if (qw.dw[0])
+ {
+ str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
+ goto match;
+ }
+ if (qw.dw[1])
+ {
+ str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
+ goto match;
+ }
+ }
+else
+ {
+ qw.dw[1] >>= (align_offset - 8) * 8;
+ if (qw.dw[1])
+ {
+ str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
+ goto match;
+ }
+ }
+str_ptr += 16;
+
+while (str_ptr < str_end)
+ {
+ vect_t orig_data = VLD1Q(str_ptr);
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ orig_data = VANDQ(orig_data, char_mask);
+#endif
+ data = orig_data;
+
+#if defined(FFCS)
+ eq = VCEQQ(data, vc1);
+
+#elif defined(FFCS_2)
+ eq1 = VCEQQ(data, vc1);
+ eq2 = VCEQQ(data, vc2);
+ eq = VORRQ(eq1, eq2);
+
+#elif defined(FFCS_MASK)
+ eq = VORRQ(data, vmask);
+ eq = VCEQQ(eq, vc1);
+#endif
+
+#if defined(FFCPS)
+# if defined (FFCPS_DIFF1)
+ data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
+# else
+ data2 = VLD1Q(str_ptr - diff);
+# if PCRE2_CODE_UNIT_WIDTH != 8
+ data2 = VANDQ(data2, char_mask);
+# endif
+# endif
+
+# ifdef FFCPS_CHAR1A2A
+ data = VCEQQ(data, cmp1a);
+ data2 = VCEQQ(data2, cmp2a);
+# else
+ data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
+ data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
+# endif
+
+ eq = VANDQ(data, data2);
+#endif
+
+ VST1Q(qw.mem, eq);
+ if (qw.dw[0])
+ str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
+ else if (qw.dw[1])
+ str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
+ else {
+ str_ptr += 16;
+#if defined (FFCPS_DIFF1)
+ prev_data = orig_data;
+#endif
+ continue;
+ }
+
+match:;
+ if (str_ptr >= str_end)
+ /* Failed match. */
+ return NULL;
+
+#if defined(FF_UTF)
+ if (utf_continue(str_ptr + IN_UCHARS(-offs1)))
+ {
+ /* Not a match. */
+ str_ptr += IN_UCHARS(1);
+ goto restart;
+ }
+#endif
+
+ /* Match. */
+#if defined (FFCPS)
+ str_ptr -= IN_UCHARS(offs1);
+#endif
+ return str_ptr;
+ }
+
+/* Failed match. */
+return NULL;
+}
diff --git a/thirdparty/pcre2/src/pcre2_jit_simd_inc.h b/thirdparty/pcre2/src/pcre2_jit_simd_inc.h
new file mode 100644
index 0000000000..f7d56b29f8
--- /dev/null
+++ b/thirdparty/pcre2/src/pcre2_jit_simd_inc.h
@@ -0,0 +1,993 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ This module by Zoltan Herczeg
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND)
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+static struct sljit_jump *jump_if_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg)
+{
+#if PCRE2_CODE_UNIT_WIDTH == 8
+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0);
+return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0x80);
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00);
+return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00);
+#else
+#error "Unknown code width"
+#endif
+}
+#endif
+
+static sljit_s32 character_to_int32(PCRE2_UCHAR chr)
+{
+sljit_u32 value = chr;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+#define SSE2_COMPARE_TYPE_INDEX 0
+return (sljit_s32)((value << 24) | (value << 16) | (value << 8) | value);
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+#define SSE2_COMPARE_TYPE_INDEX 1
+return (sljit_s32)((value << 16) | value);
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+#define SSE2_COMPARE_TYPE_INDEX 2
+return (sljit_s32)(value);
+#else
+#error "Unsupported unit width"
+#endif
+}
+
+static void load_from_mem_sse2(struct sljit_compiler *compiler, sljit_s32 dst_xmm_reg, sljit_s32 src_general_reg, sljit_s8 offset)
+{
+sljit_u8 instruction[5];
+
+SLJIT_ASSERT(dst_xmm_reg < 8);
+SLJIT_ASSERT(src_general_reg < 8);
+
+/* MOVDQA xmm1, xmm2/m128 */
+instruction[0] = ((sljit_u8)offset & 0xf) == 0 ? 0x66 : 0xf3;
+instruction[1] = 0x0f;
+instruction[2] = 0x6f;
+
+if (offset == 0)
+ {
+ instruction[3] = (dst_xmm_reg << 3) | src_general_reg;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+ }
+
+instruction[3] = 0x40 | (dst_xmm_reg << 3) | src_general_reg;
+instruction[4] = (sljit_u8)offset;
+sljit_emit_op_custom(compiler, instruction, 5);
+}
+
+typedef enum {
+ sse2_compare_match1,
+ sse2_compare_match1i,
+ sse2_compare_match2,
+} sse2_compare_type;
+
+static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, sse2_compare_type compare_type,
+ int step, sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind)
+{
+sljit_u8 instruction[4];
+instruction[0] = 0x66;
+instruction[1] = 0x0f;
+
+SLJIT_ASSERT(step >= 0 && step <= 3);
+
+if (compare_type != sse2_compare_match2)
+ {
+ if (step == 0)
+ {
+ if (compare_type == sse2_compare_match1i)
+ {
+ /* POR xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0xeb;
+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp2_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ }
+ return;
+ }
+
+ if (step != 2)
+ return;
+
+ /* PCMPEQB/W/D xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+ }
+
+switch (step)
+ {
+ case 0:
+ /* MOVDQA xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0x6f;
+ instruction[3] = 0xc0 | (tmp_ind << 3) | dst_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+
+ case 1:
+ /* PCMPEQB/W/D xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
+ instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+
+ case 2:
+ /* PCMPEQB/W/D xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX;
+ instruction[3] = 0xc0 | (tmp_ind << 3) | cmp2_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+
+ case 3:
+ /* POR xmm1, xmm2/m128 */
+ /* instruction[0] = 0x66; */
+ /* instruction[1] = 0x0f; */
+ instruction[2] = 0xeb;
+ instruction[3] = 0xc0 | (dst_ind << 3) | tmp_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ return;
+ }
+}
+
+#define JIT_HAS_FAST_FORWARD_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
+
+static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
+{
+DEFINE_COMPILER;
+struct sljit_label *start;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+struct sljit_label *restart;
+#endif
+struct sljit_jump *quit;
+struct sljit_jump *partial_quit[2];
+sse2_compare_type compare_type = sse2_compare_match1;
+sljit_u8 instruction[8];
+sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);
+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);
+sljit_s32 data_ind = 0;
+sljit_s32 tmp_ind = 1;
+sljit_s32 cmp1_ind = 2;
+sljit_s32 cmp2_ind = 3;
+sljit_u32 bit = 0;
+int i;
+
+SLJIT_UNUSED_ARG(offset);
+
+if (char1 != char2)
+ {
+ bit = char1 ^ char2;
+ compare_type = sse2_compare_match1i;
+
+ if (!is_powerof2(bit))
+ {
+ bit = 0;
+ compare_type = sse2_compare_match2;
+ }
+ }
+
+partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+if (common->mode == PCRE2_JIT_COMPLETE)
+ add_jump(compiler, &common->failed_match, partial_quit[0]);
+
+/* First part (unaligned start) */
+
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
+
+SLJIT_ASSERT(tmp1_reg_ind < 8);
+
+/* MOVD xmm, r/m32 */
+instruction[0] = 0x66;
+instruction[1] = 0x0f;
+instruction[2] = 0x6e;
+instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_reg_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (char1 != char2)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
+
+ /* MOVD xmm, r/m32 */
+ instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_reg_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ }
+
+OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
+
+/* PSHUFD xmm1, xmm2/m128, imm8 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0x70;
+instruction[3] = 0xc0 | (cmp1_ind << 3) | cmp1_ind;
+instruction[4] = 0;
+sljit_emit_op_custom(compiler, instruction, 5);
+
+if (char1 != char2)
+ {
+ /* PSHUFD xmm1, xmm2/m128, imm8 */
+ instruction[3] = 0xc0 | (cmp2_ind << 3) | cmp2_ind;
+ sljit_emit_op_custom(compiler, instruction, 5);
+ }
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+restart = LABEL();
+#endif
+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
+
+load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);
+for (i = 0; i < 4; i++)
+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
+
+/* PMOVMSKB reg, xmm */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xd7;
+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);
+
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+
+/* Second part (aligned) */
+start = LABEL();
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
+
+partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+if (common->mode == PCRE2_JIT_COMPLETE)
+ add_jump(compiler, &common->failed_match, partial_quit[1]);
+
+load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);
+for (i = 0; i < 4; i++)
+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
+
+/* PMOVMSKB reg, xmm */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xd7;
+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
+
+JUMPHERE(quit);
+
+/* BSF r32, r/m32 */
+instruction[0] = 0x0f;
+instruction[1] = 0xbc;
+instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;
+sljit_emit_op_custom(compiler, instruction, 3);
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+
+if (common->mode != PCRE2_JIT_COMPLETE)
+ {
+ JUMPHERE(partial_quit[0]);
+ JUMPHERE(partial_quit[1]);
+ OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
+ }
+else
+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+if (common->utf && offset > 0)
+ {
+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);
+
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
+
+ quit = jump_if_utf_char_start(compiler, TMP1);
+
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+ OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
+ JUMPTO(SLJIT_JUMP, restart);
+
+ JUMPHERE(quit);
+ }
+#endif
+}
+
+#ifndef _WIN64
+
+static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)
+{
+#if PCRE2_CODE_UNIT_WIDTH == 8
+return 15;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+return 7;
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+return 3;
+#else
+#error "Unsupported unit width"
+#endif
+}
+
+#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
+
+static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,
+ PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)
+{
+DEFINE_COMPILER;
+sse2_compare_type compare1_type = sse2_compare_match1;
+sse2_compare_type compare2_type = sse2_compare_match1;
+sljit_u32 bit1 = 0;
+sljit_u32 bit2 = 0;
+sljit_u32 diff = IN_UCHARS(offs1 - offs2);
+sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);
+sljit_s32 tmp2_reg_ind = sljit_get_register_index(TMP2);
+sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);
+sljit_s32 data1_ind = 0;
+sljit_s32 data2_ind = 1;
+sljit_s32 tmp1_ind = 2;
+sljit_s32 tmp2_ind = 3;
+sljit_s32 cmp1a_ind = 4;
+sljit_s32 cmp1b_ind = 5;
+sljit_s32 cmp2a_ind = 6;
+sljit_s32 cmp2b_ind = 7;
+struct sljit_label *start;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+struct sljit_label *restart;
+#endif
+struct sljit_jump *jump[2];
+sljit_u8 instruction[8];
+int i;
+
+SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);
+SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));
+SLJIT_ASSERT(tmp1_reg_ind < 8 && tmp2_reg_ind == 1);
+
+/* Initialize. */
+if (common->match_end_ptr != 0)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
+
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
+ CMOV(SLJIT_LESS, STR_END, TMP1, 0);
+ }
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+/* MOVD xmm, r/m32 */
+instruction[0] = 0x66;
+instruction[1] = 0x0f;
+instruction[2] = 0x6e;
+
+if (char1a == char1b)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));
+else
+ {
+ bit1 = char1a ^ char1b;
+ if (is_powerof2(bit1))
+ {
+ compare1_type = sse2_compare_match1i;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a | bit1));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit1));
+ }
+ else
+ {
+ compare1_type = sse2_compare_match2;
+ bit1 = 0;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char1b));
+ }
+ }
+
+instruction[3] = 0xc0 | (cmp1a_ind << 3) | tmp1_reg_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (char1a != char1b)
+ {
+ instruction[3] = 0xc0 | (cmp1b_ind << 3) | tmp2_reg_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ }
+
+if (char2a == char2b)
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));
+else
+ {
+ bit2 = char2a ^ char2b;
+ if (is_powerof2(bit2))
+ {
+ compare2_type = sse2_compare_match1i;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a | bit2));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit2));
+ }
+ else
+ {
+ compare2_type = sse2_compare_match2;
+ bit2 = 0;
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char2b));
+ }
+ }
+
+instruction[3] = 0xc0 | (cmp2a_ind << 3) | tmp1_reg_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+if (char2a != char2b)
+ {
+ instruction[3] = 0xc0 | (cmp2b_ind << 3) | tmp2_reg_ind;
+ sljit_emit_op_custom(compiler, instruction, 4);
+ }
+
+/* PSHUFD xmm1, xmm2/m128, imm8 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0x70;
+instruction[4] = 0;
+
+instruction[3] = 0xc0 | (cmp1a_ind << 3) | cmp1a_ind;
+sljit_emit_op_custom(compiler, instruction, 5);
+
+if (char1a != char1b)
+ {
+ instruction[3] = 0xc0 | (cmp1b_ind << 3) | cmp1b_ind;
+ sljit_emit_op_custom(compiler, instruction, 5);
+ }
+
+instruction[3] = 0xc0 | (cmp2a_ind << 3) | cmp2a_ind;
+sljit_emit_op_custom(compiler, instruction, 5);
+
+if (char2a != char2b)
+ {
+ instruction[3] = 0xc0 | (cmp2b_ind << 3) | cmp2b_ind;
+ sljit_emit_op_custom(compiler, instruction, 5);
+ }
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+restart = LABEL();
+#endif
+
+OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, diff);
+OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
+
+load_from_mem_sse2(compiler, data1_ind, str_ptr_reg_ind, 0);
+
+jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_PTR, 0);
+
+load_from_mem_sse2(compiler, data2_ind, str_ptr_reg_ind, -(sljit_s8)diff);
+jump[1] = JUMP(SLJIT_JUMP);
+
+JUMPHERE(jump[0]);
+
+/* MOVDQA xmm1, xmm2/m128 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0x6f;
+instruction[3] = 0xc0 | (data2_ind << 3) | data1_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+/* PSLLDQ xmm1, imm8 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0x73;
+instruction[3] = 0xc0 | (7 << 3) | data2_ind;
+instruction[4] = diff;
+sljit_emit_op_custom(compiler, instruction, 5);
+
+JUMPHERE(jump[1]);
+
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
+
+for (i = 0; i < 4; i++)
+ {
+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);
+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);
+ }
+
+/* PAND xmm1, xmm2/m128 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xdb;
+instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+/* PMOVMSKB reg, xmm */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xd7;
+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | 0;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+/* Ignore matches before the first STR_PTR. */
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
+
+jump[0] = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);
+
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
+
+/* Main loop. */
+start = LABEL();
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+load_from_mem_sse2(compiler, data1_ind, str_ptr_reg_ind, 0);
+load_from_mem_sse2(compiler, data2_ind, str_ptr_reg_ind, -(sljit_s8)diff);
+
+for (i = 0; i < 4; i++)
+ {
+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp2_ind);
+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp1_ind);
+ }
+
+/* PAND xmm1, xmm2/m128 */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xdb;
+instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+/* PMOVMSKB reg, xmm */
+/* instruction[0] = 0x66; */
+/* instruction[1] = 0x0f; */
+instruction[2] = 0xd7;
+instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | 0;
+sljit_emit_op_custom(compiler, instruction, 4);
+
+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
+
+JUMPHERE(jump[0]);
+
+/* BSF r32, r/m32 */
+instruction[0] = 0x0f;
+instruction[1] = 0xbc;
+instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;
+sljit_emit_op_custom(compiler, instruction, 3);
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+
+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+if (common->match_end_ptr != 0)
+ OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+if (common->utf)
+ {
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));
+
+ jump[0] = jump_if_utf_char_start(compiler, TMP1);
+
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart);
+
+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP));
+
+ JUMPHERE(jump[0]);
+ }
+#endif
+
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
+
+if (common->match_end_ptr != 0)
+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+}
+
+#endif /* !_WIN64 */
+
+#undef SSE2_COMPARE_TYPE_INDEX
+
+#endif /* SLJIT_CONFIG_X86 && !SUPPORT_VALGRIND */
+
+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 && (defined __ARM_NEON || defined __ARM_NEON__))
+
+#include <arm_neon.h>
+
+typedef union {
+ unsigned int x;
+ struct { unsigned char c1, c2, c3, c4; } c;
+} int_char;
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+static SLJIT_INLINE int utf_continue(sljit_u8 *s)
+{
+#if PCRE2_CODE_UNIT_WIDTH == 8
+return (*s & 0xc0) == 0x80;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+return (*s & 0xfc00) == 0xdc00;
+#else
+#error "Unknown code width"
+#endif
+}
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+# define VECTOR_FACTOR 16
+# define vect_t uint8x16_t
+# define VLD1Q(X) vld1q_u8((sljit_u8 *)(X))
+# define VCEQQ vceqq_u8
+# define VORRQ vorrq_u8
+# define VST1Q vst1q_u8
+# define VDUPQ vdupq_n_u8
+# define VEXTQ vextq_u8
+# define VANDQ vandq_u8
+typedef union {
+ uint8_t mem[16];
+ uint64_t dw[2];
+} quad_word;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+# define VECTOR_FACTOR 8
+# define vect_t uint16x8_t
+# define VLD1Q(X) vld1q_u16((sljit_u16 *)(X))
+# define VCEQQ vceqq_u16
+# define VORRQ vorrq_u16
+# define VST1Q vst1q_u16
+# define VDUPQ vdupq_n_u16
+# define VEXTQ vextq_u16
+# define VANDQ vandq_u16
+typedef union {
+ uint16_t mem[8];
+ uint64_t dw[2];
+} quad_word;
+#else
+# define VECTOR_FACTOR 4
+# define vect_t uint32x4_t
+# define VLD1Q(X) vld1q_u32((sljit_u32 *)(X))
+# define VCEQQ vceqq_u32
+# define VORRQ vorrq_u32
+# define VST1Q vst1q_u32
+# define VDUPQ vdupq_n_u32
+# define VEXTQ vextq_u32
+# define VANDQ vandq_u32
+typedef union {
+ uint32_t mem[4];
+ uint64_t dw[2];
+} quad_word;
+#endif
+
+#define FFCS
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCS
+
+#define FFCS_2
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCS_2
+
+#define FFCS_MASK
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCS_MASK
+
+#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1
+
+static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
+{
+DEFINE_COMPILER;
+int_char ic;
+struct sljit_jump *partial_quit;
+/* Save temporary registers. */
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP3, 0);
+
+/* Prepare function arguments */
+OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);
+OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0);
+OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, offset);
+
+if (char1 == char2)
+ {
+ ic.c.c1 = char1;
+ ic.c.c2 = char2;
+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf && offset > 0)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_utf));
+ else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs));
+#else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs));
+#endif
+ }
+else
+ {
+ PCRE2_UCHAR mask = char1 ^ char2;
+ if (is_powerof2(mask))
+ {
+ ic.c.c1 = char1 | mask;
+ ic.c.c2 = mask;
+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf && offset > 0)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask_utf));
+ else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask));
+#else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask));
+#endif
+ }
+ else
+ {
+ ic.c.c1 = char1;
+ ic.c.c2 = char2;
+ OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf && offset > 0)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2_utf));
+ else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2));
+#else
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2));
+#endif
+ }
+ }
+/* Restore registers. */
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
+
+/* Check return value. */
+partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
+if (common->mode == PCRE2_JIT_COMPLETE)
+ add_jump(compiler, &common->failed_match, partial_quit);
+
+/* Fast forward STR_PTR to the result of memchr. */
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
+
+if (common->mode != PCRE2_JIT_COMPLETE)
+ JUMPHERE(partial_quit);
+}
+
+typedef enum {
+ compare_match1,
+ compare_match1i,
+ compare_match2,
+} compare_type;
+
+static inline vect_t fast_forward_char_pair_compare(compare_type ctype, vect_t dst, vect_t cmp1, vect_t cmp2)
+{
+if (ctype == compare_match2)
+ {
+ vect_t tmp = dst;
+ dst = VCEQQ(dst, cmp1);
+ tmp = VCEQQ(tmp, cmp2);
+ dst = VORRQ(dst, tmp);
+ return dst;
+ }
+
+if (ctype == compare_match1i)
+ dst = VORRQ(dst, cmp2);
+dst = VCEQQ(dst, cmp1);
+return dst;
+}
+
+static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)
+{
+#if PCRE2_CODE_UNIT_WIDTH == 8
+return 15;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+return 7;
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+return 3;
+#else
+#error "Unsupported unit width"
+#endif
+}
+
+/* ARM doesn't have a shift left across lanes. */
+static SLJIT_INLINE vect_t shift_left_n_lanes(vect_t a, sljit_u8 n)
+{
+vect_t zero = VDUPQ(0);
+SLJIT_ASSERT(0 < n && n < VECTOR_FACTOR);
+/* VEXTQ takes an immediate as last argument. */
+#define C(X) case X: return VEXTQ(zero, a, VECTOR_FACTOR - X);
+switch (n)
+ {
+ C(1); C(2); C(3);
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ C(4); C(5); C(6); C(7);
+# if PCRE2_CODE_UNIT_WIDTH != 16
+ C(8); C(9); C(10); C(11); C(12); C(13); C(14); C(15);
+# endif
+#endif
+ default:
+ /* Based on the ASSERT(0 < n && n < VECTOR_FACTOR) above, this won't
+ happen. The return is still here for compilers to not warn. */
+ return a;
+ }
+}
+
+#define FFCPS
+#define FFCPS_DIFF1
+#define FFCPS_CHAR1A2A
+
+#define FFCPS_0
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCPS_0
+
+#undef FFCPS_CHAR1A2A
+
+#define FFCPS_1
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCPS_1
+
+#undef FFCPS_DIFF1
+
+#define FFCPS_DEFAULT
+#include "pcre2_jit_neon_inc.h"
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+# define FF_UTF
+# include "pcre2_jit_neon_inc.h"
+# undef FF_UTF
+#endif
+#undef FFCPS
+
+#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD 1
+
+static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,
+ PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)
+{
+DEFINE_COMPILER;
+sljit_u32 diff = IN_UCHARS(offs1 - offs2);
+struct sljit_jump *partial_quit;
+int_char ic;
+SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);
+SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));
+SLJIT_ASSERT(compiler->scratches == 5);
+
+/* Save temporary register STR_PTR. */
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);
+
+/* Prepare arguments for the function call. */
+if (common->match_end_ptr == 0)
+ OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);
+else
+ {
+ OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
+ OP2(SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
+
+ OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, STR_END, 0, SLJIT_R0, 0);
+ CMOV(SLJIT_LESS, SLJIT_R0, STR_END, 0);
+ }
+
+OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0);
+OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_IMM, offs1);
+OP1(SLJIT_MOV_S32, SLJIT_R3, 0, SLJIT_IMM, offs2);
+ic.c.c1 = char1a;
+ic.c.c2 = char1b;
+ic.c.c3 = char2a;
+ic.c.c4 = char2b;
+OP1(SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+
+if (diff == 1) {
+ if (char1a == char1b && char2a == char2b) {
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_0_utf));
+ else
+#endif
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_0));
+ } else {
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_1_utf));
+ else
+#endif
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_1));
+ }
+} else {
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (common->utf)
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_default_utf));
+ else
+#endif
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
+ SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_default));
+}
+
+/* Restore STR_PTR register. */
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+
+/* Check return value. */
+partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
+add_jump(compiler, &common->failed_match, partial_quit);
+
+/* Fast forward STR_PTR to the result of memchr. */
+OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
+
+JUMPHERE(partial_quit);
+}
+
+#endif /* SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 */
diff --git a/thirdparty/pcre2/src/pcre2_maketables.c b/thirdparty/pcre2/src/pcre2_maketables.c
index 5921e90793..8c93b4b573 100644
--- a/thirdparty/pcre2/src/pcre2_maketables.c
+++ b/thirdparty/pcre2/src/pcre2_maketables.c
@@ -147,4 +147,15 @@ for (i = 0; i < 256; i++)
return yield;
}
+#ifndef DFTABLES
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_maketables_free(pcre2_general_context *gcontext, const uint8_t *tables)
+{
+ if (gcontext)
+ gcontext->memctl.free((void *)tables, gcontext->memctl.memory_data);
+ else
+ free((void *)tables);
+}
+#endif
+
/* End of pcre2_maketables.c */
diff --git a/thirdparty/pcre2/src/pcre2_match.c b/thirdparty/pcre2/src/pcre2_match.c
index 419561fd64..48e7b9dbb2 100644
--- a/thirdparty/pcre2/src/pcre2_match.c
+++ b/thirdparty/pcre2/src/pcre2_match.c
@@ -415,8 +415,7 @@ if (caseless)
else
#endif
- /* Not in UTF mode */
-
+ /* Not in UTF mode */
{
for (; length > 0; length--)
{
@@ -491,27 +490,32 @@ heap is used for a larger vector.
*************************************************/
/* These macros pack up tests that are used for partial matching several times
-in the code. We set the "hit end" flag if the pointer is at the end of the
-subject and also past the earliest inspected character (i.e. something has been
-matched, even if not part of the actual matched string). For hard partial
-matching, we then return immediately. The second one is used when we already
-know we are past the end of the subject. */
+in the code. The second one is used when we already know we are past the end of
+the subject. We set the "hit end" flag if the pointer is at the end of the
+subject and either (a) the pointer is past the earliest inspected character
+(i.e. something has been matched, even if not part of the actual matched
+string), or (b) the pattern contains a lookbehind. These are the conditions for
+which adding more characters may allow the current match to continue.
+
+For hard partial matching, we immediately return a partial match. Otherwise,
+carrying on means that a complete match on the current subject will be sought.
+A partial match is returned only if no complete match can be found. */
#define CHECK_PARTIAL()\
- if (mb->partial != 0 && Feptr >= mb->end_subject && \
- Feptr > mb->start_used_ptr) \
+ if (Feptr >= mb->end_subject) \
{ \
- mb->hitend = TRUE; \
- if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \
+ SCHECK_PARTIAL(); \
}
#define SCHECK_PARTIAL()\
- if (mb->partial != 0 && Feptr > mb->start_used_ptr) \
+ if (mb->partial != 0 && \
+ (Feptr > mb->start_used_ptr || mb->allowemptypartial)) \
{ \
mb->hitend = TRUE; \
if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \
}
+
/* These macros are used to implement backtracking. They simulate a recursive
call to the match() function by means of a local vector of frames which
remember the backtracking points. */
@@ -5127,6 +5131,8 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case OP_ASSERT:
case OP_ASSERTBACK:
+ case OP_ASSERT_NA:
+ case OP_ASSERTBACK_NA:
Lframe_type = GF_NOCAPTURE | Fop;
for (;;)
{
@@ -5412,7 +5418,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
{
while (number-- > 0)
{
- if (Feptr <= mb->start_subject) RRETURN(MATCH_NOMATCH);
+ if (Feptr <= mb->check_subject) RRETURN(MATCH_NOMATCH);
Feptr--;
BACKCHAR(Feptr);
}
@@ -5420,7 +5426,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
else
#endif
- /* No UTF-8 support, or not in UTF-8 mode: count is byte count */
+ /* No UTF-8 support, or not in UTF-8 mode: count is code unit count */
{
if ((ptrdiff_t)number > Feptr - mb->start_subject) RRETURN(MATCH_NOMATCH);
@@ -5472,15 +5478,16 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* If we are at the end of an assertion that is a condition, return a
match, discarding any intermediate backtracking points. Copy back the
- captures into the frame before N so that they are set on return. Doing
- this for all assertions, both positive and negative, seems to match what
- Perl does. */
+ mark setting and the captures into the frame before N so that they are
+ set on return. Doing this for all assertions, both positive and negative,
+ seems to match what Perl does. */
if (GF_IDMASK(N->group_frame_type) == GF_CONDASSERT)
{
memcpy((char *)P + offsetof(heapframe, ovector), Fovector,
Foffset_top * sizeof(PCRE2_SIZE));
P->offset_top = Foffset_top;
+ P->mark = Fmark;
Fback_frame = (char *)F - (char *)P;
RRETURN(MATCH_MATCH);
}
@@ -5496,10 +5503,20 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case OP_SCOND:
break;
- /* Positive assertions are like OP_ONCE, except that in addition the
+ /* Non-atomic positive assertions are like OP_BRA, except that the
subject pointer must be put back to where it was at the start of the
assertion. */
+ case OP_ASSERT_NA:
+ case OP_ASSERTBACK_NA:
+ if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
+ Feptr = P->eptr;
+ break;
+
+ /* Atomic positive assertions are like OP_ONCE, except that in addition
+ the subject pointer must be put back to where it was at the start of the
+ assertion. */
+
case OP_ASSERT:
case OP_ASSERTBACK:
if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
@@ -5640,7 +5657,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case OP_EOD:
if (Feptr < mb->end_subject) RRETURN(MATCH_NOMATCH);
- SCHECK_PARTIAL();
+ if (mb->partial != 0)
+ {
+ mb->hitend = TRUE;
+ if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
+ }
Fecode++;
break;
@@ -5665,7 +5686,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* Either at end of string or \n before end. */
- SCHECK_PARTIAL();
+ if (mb->partial != 0)
+ {
+ mb->hitend = TRUE;
+ if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
+ }
Fecode++;
break;
@@ -5743,7 +5768,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
- if (Feptr == mb->start_subject) prev_is_word = FALSE; else
+ if (Feptr == mb->check_subject) prev_is_word = FALSE; else
{
PCRE2_SPTR lastptr = Feptr - 1;
#ifdef SUPPORT_UNICODE
@@ -5946,6 +5971,7 @@ in rrc. */
#define LBL(val) case val: goto L_RM##val;
RETURN_SWITCH:
+if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
if (Frdepth == 0) return rrc; /* Exit from the top level */
F = (heapframe *)((char *)F - Fback_frame); /* Backtrack */
mb->cb->callout_flags |= PCRE2_CALLOUT_BACKTRACK; /* Note for callouts */
@@ -5999,9 +6025,9 @@ Arguments:
Returns: > 0 => success; value is the number of ovector pairs filled
= 0 => success, but ovector is not big enough
- -1 => failed to match (PCRE2_ERROR_NOMATCH)
- -2 => partial match (PCRE2_ERROR_PARTIAL)
- < -2 => some kind of unexpected problem
+ = -1 => failed to match (PCRE2_ERROR_NOMATCH)
+ = -2 => partial match (PCRE2_ERROR_PARTIAL)
+ < -2 => some kind of unexpected problem
*/
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
@@ -6014,7 +6040,6 @@ int was_zero_terminated = 0;
const uint8_t *start_bits = NULL;
const pcre2_real_code *re = (const pcre2_real_code *)code;
-
BOOL anchored;
BOOL firstline;
BOOL has_first_cu = FALSE;
@@ -6022,6 +6047,11 @@ BOOL has_req_cu = FALSE;
BOOL startline;
BOOL utf;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+BOOL memchr_not_found_first_cu = FALSE;
+BOOL memchr_not_found_first_cu2 = FALSE;
+#endif
+
PCRE2_UCHAR first_cu = 0;
PCRE2_UCHAR first_cu2 = 0;
PCRE2_UCHAR req_cu = 0;
@@ -6029,10 +6059,23 @@ PCRE2_UCHAR req_cu2 = 0;
PCRE2_SPTR bumpalong_limit;
PCRE2_SPTR end_subject;
+PCRE2_SPTR true_end_subject;
PCRE2_SPTR start_match = subject + start_offset;
PCRE2_SPTR req_cu_ptr = start_match - 1;
-PCRE2_SPTR start_partial = NULL;
-PCRE2_SPTR match_partial = NULL;
+PCRE2_SPTR start_partial;
+PCRE2_SPTR match_partial;
+
+#ifdef SUPPORT_JIT
+BOOL use_jit;
+#endif
+
+#ifdef SUPPORT_UNICODE
+BOOL allow_invalid;
+uint32_t fragment_options = 0;
+#ifdef SUPPORT_JIT
+BOOL jit_checked_utf = FALSE;
+#endif
+#endif
PCRE2_SIZE frame_size;
@@ -6059,7 +6102,7 @@ if (length == PCRE2_ZERO_TERMINATED)
length = PRIV(strlen)(subject);
was_zero_terminated = 1;
}
-end_subject = subject + length;
+true_end_subject = end_subject = subject + length;
/* Plausibility checks */
@@ -6095,12 +6138,24 @@ options |= (re->flags & FF) / ((FF & (~FF+1)) / (OO & (~OO+1)));
#undef FF
#undef OO
-/* These two settings are used in the code for checking a UTF string that
-follows immediately afterwards. Other values in the mb block are used only
-during interpretive processing, not when the JIT support is in use, so they are
-set up later. */
+/* If the pattern was successfully studied with JIT support, we will run the
+JIT executable instead of the rest of this function. Most options must be set
+at compile time for the JIT code to be usable. */
+
+#ifdef SUPPORT_JIT
+use_jit = (re->executable_jit != NULL &&
+ (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0);
+#endif
+
+/* Initialize UTF parameters. */
utf = (re->overall_options & PCRE2_UTF) != 0;
+#ifdef SUPPORT_UNICODE
+allow_invalid = (re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0;
+#endif
+
+/* Convert the partial matching flags into an integer. */
+
mb->partial = ((options & PCRE2_PARTIAL_HARD) != 0)? 2 :
((options & PCRE2_PARTIAL_SOFT) != 0)? 1 : 0;
@@ -6111,88 +6166,107 @@ if (mb->partial != 0 &&
((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)
return PCRE2_ERROR_BADOPTION;
-/* Check a UTF string for validity if required. For 8-bit and 16-bit strings,
-we must also check that a starting offset does not point into the middle of a
-multiunit character. We check only the portion of the subject that is going to
-be inspected during matching - from the offset minus the maximum back reference
-to the given length. This saves time when a small part of a large subject is
-being matched by the use of a starting offset. Note that the maximum lookbehind
-is a number of characters, not code units. */
+/* It is an error to set an offset limit without setting the flag at compile
+time. */
-#ifdef SUPPORT_UNICODE
-if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)
+if (mcontext != NULL && mcontext->offset_limit != PCRE2_UNSET &&
+ (re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)
+ return PCRE2_ERROR_BADOFFSETLIMIT;
+
+/* If the match data block was previously used with PCRE2_COPY_MATCHED_SUBJECT,
+free the memory that was obtained. Set the field to NULL for no match cases. */
+
+if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)
{
- PCRE2_SPTR check_subject = start_match; /* start_match includes offset */
+ match_data->memctl.free((void *)match_data->subject,
+ match_data->memctl.memory_data);
+ match_data->flags &= ~PCRE2_MD_COPIED_SUBJECT;
+ }
+match_data->subject = NULL;
+
+/* Zero the error offset in case the first code unit is invalid UTF. */
+
+match_data->startchar = 0;
+
+
+/* ============================= JIT matching ============================== */
+
+/* Prepare for JIT matching. Check a UTF string for validity unless no check is
+requested or invalid UTF can be handled. We check only the portion of the
+subject that might be be inspected during matching - from the offset minus the
+maximum lookbehind to the given length. This saves time when a small part of a
+large subject is being matched by the use of a starting offset. Note that the
+maximum lookbehind is a number of characters, not code units. */
- if (start_offset > 0)
+#ifdef SUPPORT_JIT
+if (use_jit)
+ {
+#ifdef SUPPORT_UNICODE
+ if (utf && (options & PCRE2_NO_UTF_CHECK) == 0 && !allow_invalid)
{
#if PCRE2_CODE_UNIT_WIDTH != 32
unsigned int i;
+#endif
+
+ /* For 8-bit and 16-bit UTF, check that the first code unit is a valid
+ character start. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 32
if (start_match < end_subject && NOT_FIRSTCU(*start_match))
- return PCRE2_ERROR_BADUTFOFFSET;
- for (i = re->max_lookbehind; i > 0 && check_subject > subject; i--)
{
- check_subject--;
- while (check_subject > subject &&
+ if (start_offset > 0) return PCRE2_ERROR_BADUTFOFFSET;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ return PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */
+#else
+ return PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */
+#endif
+ }
+#endif /* WIDTH != 32 */
+
+ /* Move back by the maximum lookbehind, just in case it happens at the very
+ start of matching. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ for (i = re->max_lookbehind; i > 0 && start_match > subject; i--)
+ {
+ start_match--;
+ while (start_match > subject &&
#if PCRE2_CODE_UNIT_WIDTH == 8
- (*check_subject & 0xc0) == 0x80)
+ (*start_match & 0xc0) == 0x80)
#else /* 16-bit */
- (*check_subject & 0xfc00) == 0xdc00)
-#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
- check_subject--;
+ (*start_match & 0xfc00) == 0xdc00)
+#endif
+ start_match--;
}
-#else
+#else /* PCRE2_CODE_UNIT_WIDTH != 32 */
+
/* In the 32-bit library, one code unit equals one character. However,
we cannot just subtract the lookbehind and then compare pointers, because
a very large lookbehind could create an invalid pointer. */
if (start_offset >= re->max_lookbehind)
- check_subject -= re->max_lookbehind;
+ start_match -= re->max_lookbehind;
else
- check_subject = subject;
+ start_match = subject;
#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */
- }
- /* Validate the relevant portion of the subject. After an error, adjust the
- offset to be an absolute offset in the whole string. */
+ /* Validate the relevant portion of the subject. Adjust the offset of an
+ invalid code point to be an absolute offset in the whole string. */
- match_data->rc = PRIV(valid_utf)(check_subject,
- length - (check_subject - subject), &(match_data->startchar));
- if (match_data->rc != 0)
- {
- match_data->startchar += check_subject - subject;
- return match_data->rc;
+ match_data->rc = PRIV(valid_utf)(start_match,
+ length - (start_match - subject), &(match_data->startchar));
+ if (match_data->rc != 0)
+ {
+ match_data->startchar += start_match - subject;
+ return match_data->rc;
+ }
+ jit_checked_utf = TRUE;
}
- }
#endif /* SUPPORT_UNICODE */
-/* It is an error to set an offset limit without setting the flag at compile
-time. */
-
-if (mcontext != NULL && mcontext->offset_limit != PCRE2_UNSET &&
- (re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)
- return PCRE2_ERROR_BADOFFSETLIMIT;
-
-/* If the match data block was previously used with PCRE2_COPY_MATCHED_SUBJECT,
-free the memory that was obtained. Set the field to NULL for no match cases. */
+ /* If JIT returns BADOPTION, which means that the selected complete or
+ partial matching mode was not compiled, fall through to the interpreter. */
-if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)
- {
- match_data->memctl.free((void *)match_data->subject,
- match_data->memctl.memory_data);
- match_data->flags &= ~PCRE2_MD_COPIED_SUBJECT;
- }
-match_data->subject = NULL;
-
-/* If the pattern was successfully studied with JIT support, run the JIT
-executable instead of the rest of this function. Most options must be set at
-compile time for the JIT code to be usable. Fallback to the normal code path if
-an unsupported option is set or if JIT returns BADOPTION (which means that the
-selected normal or partial matching mode was not compiled). */
-
-#ifdef SUPPORT_JIT
-if (re->executable_jit != NULL && (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0)
- {
rc = pcre2_jit_match(code, subject, length, start_offset, options,
match_data, mcontext);
if (rc != PCRE2_ERROR_JIT_BADOPTION)
@@ -6209,10 +6283,152 @@ if (re->executable_jit != NULL && (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0)
return rc;
}
}
+#endif /* SUPPORT_JIT */
+
+/* ========================= End of JIT matching ========================== */
+
+
+/* Proceed with non-JIT matching. The default is to allow lookbehinds to the
+start of the subject. A UTF check when there is a non-zero offset may change
+this. */
+
+mb->check_subject = subject;
+
+/* If a UTF subject string was not checked for validity in the JIT code above,
+check it here, and handle support for invalid UTF strings. The check above
+happens only when invalid UTF is not supported and PCRE2_NO_CHECK_UTF is unset.
+If we get here in those circumstances, it means the subject string is valid,
+but for some reason JIT matching was not successful. There is no need to check
+the subject again.
+
+We check only the portion of the subject that might be be inspected during
+matching - from the offset minus the maximum lookbehind to the given length.
+This saves time when a small part of a large subject is being matched by the
+use of a starting offset. Note that the maximum lookbehind is a number of
+characters, not code units.
+
+Note also that support for invalid UTF forces a check, overriding the setting
+of PCRE2_NO_CHECK_UTF. */
+
+#ifdef SUPPORT_UNICODE
+if (utf &&
+#ifdef SUPPORT_JIT
+ !jit_checked_utf &&
+#endif
+ ((options & PCRE2_NO_UTF_CHECK) == 0 || allow_invalid))
+ {
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ BOOL skipped_bad_start = FALSE;
+#endif
+
+ /* For 8-bit and 16-bit UTF, check that the first code unit is a valid
+ character start. If we are handling invalid UTF, just skip over such code
+ units. Otherwise, give an appropriate error. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ if (allow_invalid)
+ {
+ while (start_match < end_subject && NOT_FIRSTCU(*start_match))
+ {
+ start_match++;
+ skipped_bad_start = TRUE;
+ }
+ }
+ else if (start_match < end_subject && NOT_FIRSTCU(*start_match))
+ {
+ if (start_offset > 0) return PCRE2_ERROR_BADUTFOFFSET;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ return PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */
+#else
+ return PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */
+#endif
+ }
+#endif /* WIDTH != 32 */
+
+ /* The mb->check_subject field points to the start of UTF checking;
+ lookbehinds can go back no further than this. */
+
+ mb->check_subject = start_match;
+
+ /* Move back by the maximum lookbehind, just in case it happens at the very
+ start of matching, but don't do this if we skipped bad 8-bit or 16-bit code
+ units above. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ if (!skipped_bad_start)
+ {
+ unsigned int i;
+ for (i = re->max_lookbehind; i > 0 && mb->check_subject > subject; i--)
+ {
+ mb->check_subject--;
+ while (mb->check_subject > subject &&
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ (*mb->check_subject & 0xc0) == 0x80)
+#else /* 16-bit */
+ (*mb->check_subject & 0xfc00) == 0xdc00)
+#endif
+ mb->check_subject--;
+ }
+ }
+#else /* PCRE2_CODE_UNIT_WIDTH != 32 */
+
+ /* In the 32-bit library, one code unit equals one character. However,
+ we cannot just subtract the lookbehind and then compare pointers, because
+ a very large lookbehind could create an invalid pointer. */
+
+ if (start_offset >= re->max_lookbehind)
+ mb->check_subject -= re->max_lookbehind;
+ else
+ mb->check_subject = subject;
+#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */
+
+ /* Validate the relevant portion of the subject. There's a loop in case we
+ encounter bad UTF in the characters preceding start_match which we are
+ scanning because of a lookbehind. */
+
+ for (;;)
+ {
+ match_data->rc = PRIV(valid_utf)(mb->check_subject,
+ length - (mb->check_subject - subject), &(match_data->startchar));
+
+ if (match_data->rc == 0) break; /* Valid UTF string */
+
+ /* Invalid UTF string. Adjust the offset to be an absolute offset in the
+ whole string. If we are handling invalid UTF strings, set end_subject to
+ stop before the bad code unit, and set the options to "not end of line".
+ Otherwise return the error. */
+
+ match_data->startchar += mb->check_subject - subject;
+ if (!allow_invalid || match_data->rc > 0) return match_data->rc;
+ end_subject = subject + match_data->startchar;
+
+ /* If the end precedes start_match, it means there is invalid UTF in the
+ extra code units we reversed over because of a lookbehind. Advance past the
+ first bad code unit, and then skip invalid character starting code units in
+ 8-bit and 16-bit modes, and try again. */
+
+ if (end_subject < start_match)
+ {
+ mb->check_subject = end_subject + 1;
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ while (mb->check_subject < start_match && NOT_FIRSTCU(*mb->check_subject))
+ mb->check_subject++;
#endif
+ }
+
+ /* Otherwise, set the not end of line option, and do the match. */
+
+ else
+ {
+ fragment_options = PCRE2_NOTEOL;
+ break;
+ }
+ }
+ }
+#endif /* SUPPORT_UNICODE */
-/* Carry on with non-JIT matching. A NULL match context means "use a default
-context", but we take the memory control functions from the pattern. */
+/* A NULL match context means "use a default context", but we take the memory
+control functions from the pattern. */
if (mcontext == NULL)
{
@@ -6224,8 +6440,8 @@ else mb->memctl = mcontext->memctl;
anchored = ((re->overall_options | options) & PCRE2_ANCHORED) != 0;
firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;
startline = (re->flags & PCRE2_STARTLINE) != 0;
-bumpalong_limit = (mcontext->offset_limit == PCRE2_UNSET)?
- end_subject : subject + mcontext->offset_limit;
+bumpalong_limit = (mcontext->offset_limit == PCRE2_UNSET)?
+ true_end_subject : subject + mcontext->offset_limit;
/* Initialize and set up the fixed fields in the callout block, with a pointer
in the match block. */
@@ -6236,7 +6452,8 @@ cb.subject = subject;
cb.subject_length = (PCRE2_SIZE)(end_subject - subject);
cb.callout_flags = 0;
-/* Fill in the remaining fields in the match block. */
+/* Fill in the remaining fields in the match block, except for moptions, which
+gets set later. */
mb->callout = mcontext->callout;
mb->callout_data = mcontext->callout_data;
@@ -6245,13 +6462,11 @@ mb->start_subject = subject;
mb->start_offset = start_offset;
mb->end_subject = end_subject;
mb->hasthen = (re->flags & PCRE2_HASTHEN) != 0;
-
-mb->moptions = options; /* Match options */
-mb->poptions = re->overall_options; /* Pattern options */
-
+mb->allowemptypartial = (re->max_lookbehind > 0) ||
+ (re->flags & PCRE2_MATCH_EMPTY) != 0;
+mb->poptions = re->overall_options; /* Pattern options */
mb->ignore_skip_arg = 0;
-mb->mark = mb->nomatch_mark = NULL; /* In case never set */
-mb->hitend = FALSE;
+mb->mark = mb->nomatch_mark = NULL; /* In case never set */
/* The name table is needed for finding all the numbers associated with a
given name, for condition testing. The code follows the name table. */
@@ -6404,6 +6619,13 @@ if ((re->flags & PCRE2_LASTSET) != 0)
/* Loop for handling unanchored repeated matching attempts; for anchored regexs
the loop runs just once. */
+#ifdef SUPPORT_UNICODE
+FRAGMENT_RESTART:
+#endif
+
+start_partial = match_partial = NULL;
+mb->hitend = FALSE;
+
for(;;)
{
PCRE2_SPTR new_start_match;
@@ -6473,7 +6695,10 @@ for(;;)
/* Not anchored. Advance to a unique first code unit if there is one. In
8-bit mode, the use of memchr() gives a big speed up, even though we have
to call it twice in caseless mode, in order to find the earliest occurrence
- of the character in either of its cases. */
+ of the character in either of its cases. If a call to memchr() that
+ searches the rest of the subject fails to find one case, remember that in
+ order not to keep on repeating the search. This can make a huge difference
+ when the strings are very long and only one case is present. */
else
{
@@ -6487,11 +6712,29 @@ for(;;)
(smc = UCHAR21TEST(start_match)) != first_cu &&
smc != first_cu2)
start_match++;
+
#else /* 8-bit code units */
- PCRE2_SPTR pp1 =
- memchr(start_match, first_cu, end_subject-start_match);
- PCRE2_SPTR pp2 =
- memchr(start_match, first_cu2, end_subject-start_match);
+ PCRE2_SPTR pp1 = NULL;
+ PCRE2_SPTR pp2 = NULL;
+ PCRE2_SIZE cu2size = end_subject - start_match;
+
+ if (!memchr_not_found_first_cu)
+ {
+ pp1 = memchr(start_match, first_cu, end_subject - start_match);
+ if (pp1 == NULL) memchr_not_found_first_cu = TRUE;
+ else cu2size = pp1 - start_match;
+ }
+
+ /* If pp1 is not NULL, we have arranged to search only as far as pp1,
+ to see if the other case is earlier, so we can set "not found" only
+ when both searches have returned NULL. */
+
+ if (!memchr_not_found_first_cu2)
+ {
+ pp2 = memchr(start_match, first_cu2, cu2size);
+ memchr_not_found_first_cu2 = (pp2 == NULL && pp1 == NULL);
+ }
+
if (pp1 == NULL)
start_match = (pp2 == NULL)? end_subject : pp2;
else
@@ -6523,7 +6766,7 @@ for(;;)
we also let the cycle run, because the matching string is legitimately
allowed to start with the first code unit of a newline. */
- if (!mb->partial && start_match >= mb->end_subject)
+ if (mb->partial == 0 && start_match >= mb->end_subject)
{
rc = MATCH_NOMATCH;
break;
@@ -6582,7 +6825,7 @@ for(;;)
/* See comment above in first_cu checking about the next few lines. */
- if (!mb->partial && start_match >= mb->end_subject)
+ if (mb->partial == 0 && start_match >= mb->end_subject)
{
rc = MATCH_NOMATCH;
break;
@@ -6596,8 +6839,10 @@ for(;;)
/* The following two optimizations must be disabled for partial matching. */
- if (!mb->partial)
+ if (mb->partial == 0)
{
+ PCRE2_SPTR p;
+
/* The minimum matching length is a lower bound; no string of that length
may actually match the pattern. Although the value is, strictly, in
characters, we treat it as code units to avoid spending too much time in
@@ -6621,60 +6866,57 @@ for(;;)
memchr() twice in the caseless case because we only need to check for the
presence of the character in either case, not find the first occurrence.
+ The search can be skipped if the code unit was found later than the
+ current starting point in a previous iteration of the bumpalong loop.
+
HOWEVER: when the subject string is very, very long, searching to its end
can take a long time, and give bad performance on quite ordinary
- patterns. This showed up when somebody was matching something like
- /^\d+C/ on a 32-megabyte string... so we don't do this when the string is
- sufficiently long. */
+ anchored patterns. This showed up when somebody was matching something
+ like /^\d+C/ on a 32-megabyte string... so we don't do this when the
+ string is sufficiently long, but it's worth searching a lot more for
+ unanchored patterns. */
- if (has_req_cu && end_subject - start_match < REQ_CU_MAX)
+ p = start_match + (has_first_cu? 1:0);
+ if (has_req_cu && p > req_cu_ptr)
{
- PCRE2_SPTR p = start_match + (has_first_cu? 1:0);
-
- /* We don't need to repeat the search if we haven't yet reached the
- place we found it last time round the bumpalong loop. */
+ PCRE2_SIZE check_length = end_subject - start_match;
- if (p > req_cu_ptr)
+ if (check_length < REQ_CU_MAX ||
+ (!anchored && check_length < REQ_CU_MAX * 1000))
{
- if (p < end_subject)
+ if (req_cu != req_cu2) /* Caseless */
{
- if (req_cu != req_cu2) /* Caseless */
- {
#if PCRE2_CODE_UNIT_WIDTH != 8
- do
- {
- uint32_t pp = UCHAR21INCTEST(p);
- if (pp == req_cu || pp == req_cu2) { p--; break; }
- }
- while (p < end_subject);
-
+ while (p < end_subject)
+ {
+ uint32_t pp = UCHAR21INCTEST(p);
+ if (pp == req_cu || pp == req_cu2) { p--; break; }
+ }
#else /* 8-bit code units */
- PCRE2_SPTR pp = p;
- p = memchr(pp, req_cu, end_subject - pp);
- if (p == NULL)
- {
- p = memchr(pp, req_cu2, end_subject - pp);
- if (p == NULL) p = end_subject;
- }
-#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */
+ PCRE2_SPTR pp = p;
+ p = memchr(pp, req_cu, end_subject - pp);
+ if (p == NULL)
+ {
+ p = memchr(pp, req_cu2, end_subject - pp);
+ if (p == NULL) p = end_subject;
}
+#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */
+ }
- /* The caseful case */
+ /* The caseful case */
- else
- {
+ else
+ {
#if PCRE2_CODE_UNIT_WIDTH != 8
- do
- {
- if (UCHAR21INCTEST(p) == req_cu) { p--; break; }
- }
- while (p < end_subject);
+ while (p < end_subject)
+ {
+ if (UCHAR21INCTEST(p) == req_cu) { p--; break; }
+ }
#else /* 8-bit code units */
- p = memchr(p, req_cu, end_subject - p);
- if (p == NULL) p = end_subject;
+ p = memchr(p, req_cu, end_subject - p);
+ if (p == NULL) p = end_subject;
#endif
- }
}
/* If we can't find the required code unit, break the bumpalong loop,
@@ -6714,6 +6956,11 @@ for(;;)
mb->start_used_ptr = start_match;
mb->last_used_ptr = start_match;
+#ifdef SUPPORT_UNICODE
+ mb->moptions = options | fragment_options;
+#else
+ mb->moptions = options;
+#endif
mb->match_call_count = 0;
mb->end_offset_top = 0;
mb->skip_arg_count = 0;
@@ -6839,6 +7086,68 @@ for(;;)
ENDLOOP:
+/* If end_subject != true_end_subject, it means we are handling invalid UTF,
+and have just processed a non-terminal fragment. If this resulted in no match
+or a partial match we must carry on to the next fragment (a partial match is
+returned to the caller only at the very end of the subject). A loop is used to
+avoid trying to match against empty fragments; if the pattern can match an
+empty string it would have done so already. */
+
+#ifdef SUPPORT_UNICODE
+if (utf && end_subject != true_end_subject &&
+ (rc == MATCH_NOMATCH || rc == PCRE2_ERROR_PARTIAL))
+ {
+ for (;;)
+ {
+ /* Advance past the first bad code unit, and then skip invalid character
+ starting code units in 8-bit and 16-bit modes. */
+
+ start_match = end_subject + 1;
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ while (start_match < true_end_subject && NOT_FIRSTCU(*start_match))
+ start_match++;
+#endif
+
+ /* If we have hit the end of the subject, there isn't another non-empty
+ fragment, so give up. */
+
+ if (start_match >= true_end_subject)
+ {
+ rc = MATCH_NOMATCH; /* In case it was partial */
+ break;
+ }
+
+ /* Check the rest of the subject */
+
+ mb->check_subject = start_match;
+ rc = PRIV(valid_utf)(start_match, length - (start_match - subject),
+ &(match_data->startchar));
+
+ /* The rest of the subject is valid UTF. */
+
+ if (rc == 0)
+ {
+ mb->end_subject = end_subject = true_end_subject;
+ fragment_options = PCRE2_NOTBOL;
+ goto FRAGMENT_RESTART;
+ }
+
+ /* A subsequent UTF error has been found; if the next fragment is
+ non-empty, set up to process it. Otherwise, let the loop advance. */
+
+ else if (rc < 0)
+ {
+ mb->end_subject = end_subject = start_match + match_data->startchar;
+ if (end_subject > start_match)
+ {
+ fragment_options = PCRE2_NOTBOL|PCRE2_NOTEOL;
+ goto FRAGMENT_RESTART;
+ }
+ }
+ }
+ }
+#endif /* SUPPORT_UNICODE */
+
/* Release an enlarged frame vector that is on the heap. */
if (mb->match_frames != mb->stack_frames)
diff --git a/thirdparty/pcre2/src/pcre2_match_data.c b/thirdparty/pcre2/src/pcre2_match_data.c
index ccc5f6740e..53e4698707 100644
--- a/thirdparty/pcre2/src/pcre2_match_data.c
+++ b/thirdparty/pcre2/src/pcre2_match_data.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -150,4 +150,17 @@ pcre2_get_startchar(pcre2_match_data *match_data)
return match_data->startchar;
}
+
+
+/*************************************************
+* Get size of match data block *
+*************************************************/
+
+PCRE2_EXP_DEFN PCRE2_SIZE PCRE2_CALL_CONVENTION
+pcre2_get_match_data_size(pcre2_match_data *match_data)
+{
+return offsetof(pcre2_match_data, ovector) +
+ 2 * (match_data->oveccount) * sizeof(PCRE2_SIZE);
+}
+
/* End of pcre2_match_data.c */
diff --git a/thirdparty/pcre2/src/pcre2_study.c b/thirdparty/pcre2/src/pcre2_study.c
index e883c2eb4c..2883868618 100644
--- a/thirdparty/pcre2/src/pcre2_study.c
+++ b/thirdparty/pcre2/src/pcre2_study.c
@@ -88,11 +88,13 @@ Arguments:
countptr pointer to call count (to catch over complexity)
backref_cache vector for caching back references.
+This function is no longer called when the pattern contains (*ACCEPT); however,
+the old code for returning -1 is retained, just in case.
+
Returns: the minimum length
-1 \C in UTF-8 mode
or (*ACCEPT)
or pattern too complicated
- or back reference to duplicate name/number
-2 internal error (missing capturing bracket)
-3 internal error (opcode not listed)
*/
@@ -103,6 +105,7 @@ find_minlength(const pcre2_real_code *re, PCRE2_SPTR code,
int *backref_cache)
{
int length = -1;
+int branchlength = 0;
int prev_cap_recno = -1;
int prev_cap_d = 0;
int prev_recurse_recno = -1;
@@ -110,9 +113,9 @@ int prev_recurse_d = 0;
uint32_t once_fudge = 0;
BOOL had_recurse = FALSE;
BOOL dupcapused = (re->flags & PCRE2_DUPCAPUSED) != 0;
-recurse_check this_recurse;
-int branchlength = 0;
+PCRE2_SPTR nextbranch = code + GET(code, 1);
PCRE2_UCHAR *cc = (PCRE2_UCHAR *)code + 1 + LINK_SIZE;
+recurse_check this_recurse;
/* If this is a "could be empty" group, its minimum length is 0. */
@@ -128,16 +131,20 @@ if ((*countptr)++ > 1000) return -1;
/* Scan along the opcodes for this branch. If we get to the end of the branch,
check the length against that of the other branches. If the accumulated length
-passes 16-bits, stop. */
+passes 16-bits, reset to that value and skip the rest of the branch. */
for (;;)
{
int d, min, recno;
- PCRE2_UCHAR *cs, *ce;
- PCRE2_UCHAR op = *cc;
+ PCRE2_UCHAR op, *cs, *ce;
- if (branchlength >= UINT16_MAX) return UINT16_MAX;
+ if (branchlength >= UINT16_MAX)
+ {
+ branchlength = UINT16_MAX;
+ cc = (PCRE2_UCHAR *)nextbranch;
+ }
+ op = *cc;
switch (op)
{
case OP_COND:
@@ -206,7 +213,9 @@ for (;;)
cc += 1 + LINK_SIZE;
break;
- /* ACCEPT makes things far too complicated; we have to give up. */
+ /* ACCEPT makes things far too complicated; we have to give up. In fact,
+ from 10.34 onwards, if a pattern contains (*ACCEPT), this function is not
+ used. However, leave the code in place, just in case. */
case OP_ACCEPT:
case OP_ASSERT_ACCEPT:
@@ -214,9 +223,9 @@ for (;;)
/* Reached end of a branch; if it's a ket it is the end of a nested
call. If it's ALT it is an alternation in a nested call. If it is END it's
- the end of the outer call. All can be handled by the same code. If an
- ACCEPT was previously encountered, use the length that was in force at that
- time, and pass back the shortest ACCEPT length. */
+ the end of the outer call. All can be handled by the same code. If the
+ length of any branch is zero, there is no need to scan any subsequent
+ branches. */
case OP_ALT:
case OP_KET:
@@ -226,7 +235,8 @@ for (;;)
case OP_END:
if (length < 0 || (!had_recurse && branchlength < length))
length = branchlength;
- if (op != OP_ALT) return length;
+ if (op != OP_ALT || length == 0) return length;
+ nextbranch = cc + GET(cc, 1);
cc += 1 + LINK_SIZE;
branchlength = 0;
had_recurse = FALSE;
@@ -238,6 +248,8 @@ for (;;)
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
+ case OP_ASSERT_NA:
+ case OP_ASSERTBACK_NA:
do cc += GET(cc, 1); while (*cc == OP_ALT);
/* Fall through */
@@ -451,15 +463,17 @@ for (;;)
If PCRE2_MATCH_UNSET_BACKREF is set, a backreference to an unset bracket
matches an empty string (by default it causes a matching failure), so in
- that case we must set the minimum length to zero. */
+ that case we must set the minimum length to zero.
+
+ For backreferenes, if duplicate numbers are present in the pattern we check
+ for a reference to a duplicate. If it is, we don't know which version will
+ be referenced, so we have to set the minimum length to zero. */
- /* Duplicate named pattern back reference. We cannot reliably find a length
- for this if duplicate numbers are present in the pattern. */
+ /* Duplicate named pattern back reference. */
case OP_DNREF:
case OP_DNREFI:
- if (dupcapused) return -1;
- if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
+ if (!dupcapused && (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
{
int count = GET2(cc, 1+IMM2_SIZE);
PCRE2_UCHAR *slot =
@@ -482,28 +496,32 @@ for (;;)
ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno);
if (cs == NULL) return -2;
do ce += GET(ce, 1); while (*ce == OP_ALT);
- if (cc > cs && cc < ce) /* Simple recursion */
- {
- dd = 0;
- had_recurse = TRUE;
- }
- else
+
+ dd = 0;
+ if (!dupcapused ||
+ (PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)
{
- recurse_check *r = recurses;
- for (r = recurses; r != NULL; r = r->prev)
- if (r->group == cs) break;
- if (r != NULL) /* Mutual recursion */
+ if (cc > cs && cc < ce) /* Simple recursion */
{
- dd = 0;
had_recurse = TRUE;
}
else
{
- this_recurse.prev = recurses;
- this_recurse.group = cs;
- dd = find_minlength(re, cs, startcode, utf, &this_recurse,
- countptr, backref_cache);
- if (dd < 0) return dd;
+ recurse_check *r = recurses;
+ for (r = recurses; r != NULL; r = r->prev)
+ if (r->group == cs) break;
+ if (r != NULL) /* Mutual recursion */
+ {
+ had_recurse = TRUE;
+ }
+ else
+ {
+ this_recurse.prev = recurses; /* No recursion */
+ this_recurse.group = cs;
+ dd = find_minlength(re, cs, startcode, utf, &this_recurse,
+ countptr, backref_cache);
+ if (dd < 0) return dd;
+ }
}
}
@@ -521,48 +539,51 @@ for (;;)
cc += 1 + 2*IMM2_SIZE;
goto REPEAT_BACK_REFERENCE;
- /* Single back reference. We cannot find a length for this if duplicate
- numbers are present in the pattern. */
+ /* Single back reference by number. References by name are converted to by
+ number when there is no duplication. */
case OP_REF:
case OP_REFI:
- if (dupcapused) return -1;
recno = GET2(cc, 1);
if (recno <= backref_cache[0] && backref_cache[recno] >= 0)
d = backref_cache[recno];
else
{
int i;
+ d = 0;
+
if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
{
ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno);
if (cs == NULL) return -2;
do ce += GET(ce, 1); while (*ce == OP_ALT);
- if (cc > cs && cc < ce) /* Simple recursion */
- {
- d = 0;
- had_recurse = TRUE;
- }
- else
+
+ if (!dupcapused ||
+ (PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)
{
- recurse_check *r = recurses;
- for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
- if (r != NULL) /* Mutual recursion */
+ if (cc > cs && cc < ce) /* Simple recursion */
{
- d = 0;
had_recurse = TRUE;
}
else
{
- this_recurse.prev = recurses;
- this_recurse.group = cs;
- d = find_minlength(re, cs, startcode, utf, &this_recurse, countptr,
- backref_cache);
- if (d < 0) return d;
+ recurse_check *r = recurses;
+ for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
+ if (r != NULL) /* Mutual recursion */
+ {
+ had_recurse = TRUE;
+ }
+ else /* No recursion */
+ {
+ this_recurse.prev = recurses;
+ this_recurse.group = cs;
+ d = find_minlength(re, cs, startcode, utf, &this_recurse, countptr,
+ backref_cache);
+ if (d < 0) return d;
+ }
}
}
}
- else d = 0;
backref_cache[recno] = d;
for (i = backref_cache[0] + 1; i < recno; i++) backref_cache[i] = -1;
@@ -888,7 +909,7 @@ if (table_limit != 32) for (c = 24; c < 32; c++) re->start_bitmap[c] = 0xff;
/*************************************************
-* Create bitmap of starting bytes *
+* Create bitmap of starting code units *
*************************************************/
/* This function scans a compiled unanchored expression recursively and
@@ -938,6 +959,9 @@ do
{
int rc;
uint8_t *classmap = NULL;
+#ifdef SUPPORT_WIDE_CHARS
+ PCRE2_UCHAR xclassflags;
+#endif
switch(*tcode)
{
@@ -1078,6 +1102,7 @@ do
case OP_ONCE:
case OP_SCRIPT_RUN:
case OP_ASSERT:
+ case OP_ASSERT_NA:
rc = set_start_bits(re, tcode, utf);
if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
if (rc == SSB_DONE) try_next = FALSE; else
@@ -1120,6 +1145,7 @@ do
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
+ case OP_ASSERTBACK_NA:
do tcode += GET(tcode, 1); while (*tcode == OP_ALT);
tcode += 1 + LINK_SIZE;
break;
@@ -1444,20 +1470,59 @@ do
negative XCLASS without a map, give up. If there are no property checks,
there must be wide characters on the XCLASS list, because otherwise an
XCLASS would not have been created. This means that code points >= 255
- are always potential starters. */
+ are potential starters. In the UTF-8 case we can scan them and set bits
+ for the relevant leading bytes. */
#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
- if ((tcode[1 + LINK_SIZE] & XCL_HASPROP) != 0 ||
- (tcode[1 + LINK_SIZE] & (XCL_MAP|XCL_NOT)) == XCL_NOT)
+ xclassflags = tcode[1 + LINK_SIZE];
+ if ((xclassflags & XCL_HASPROP) != 0 ||
+ (xclassflags & (XCL_MAP|XCL_NOT)) == XCL_NOT)
return SSB_FAIL;
/* We have a positive XCLASS or a negative one without a map. Set up the
map pointer if there is one, and fall through. */
- classmap = ((tcode[1 + LINK_SIZE] & XCL_MAP) == 0)? NULL :
+ classmap = ((xclassflags & XCL_MAP) == 0)? NULL :
(uint8_t *)(tcode + 1 + LINK_SIZE + 1);
-#endif
+
+ /* In UTF-8 mode, scan the character list and set bits for leading bytes,
+ then jump to handle the map. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (utf && (xclassflags & XCL_NOT) == 0)
+ {
+ PCRE2_UCHAR b, e;
+ PCRE2_SPTR p = tcode + 1 + LINK_SIZE + 1 + ((classmap == NULL)? 0:32);
+ tcode += GET(tcode, 1);
+
+ for (;;) switch (*p++)
+ {
+ case XCL_SINGLE:
+ b = *p++;
+ while ((*p & 0xc0) == 0x80) p++;
+ re->start_bitmap[b/8] |= (1u << (b&7));
+ break;
+
+ case XCL_RANGE:
+ b = *p++;
+ while ((*p & 0xc0) == 0x80) p++;
+ e = *p++;
+ while ((*p & 0xc0) == 0x80) p++;
+ for (; b <= e; b++)
+ re->start_bitmap[b/8] |= (1u << (b&7));
+ break;
+
+ case XCL_END:
+ goto HANDLE_CLASSMAP;
+
+ default:
+ return SSB_UNKNOWN; /* Internal error, should not occur */
+ }
+ }
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */
+#endif /* SUPPORT_WIDE_CHARS */
+
/* It seems that the fall through comment must be outside the #ifdef if
it is to avoid the gcc compiler warning. */
@@ -1499,6 +1564,9 @@ do
greater than 127. In fact, there are only two possible starting bytes for
characters in the range 128 - 255. */
+#if defined SUPPORT_WIDE_CHARS && PCRE2_CODE_UNIT_WIDTH == 8
+ HANDLE_CLASSMAP:
+#endif
if (classmap != NULL)
{
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
@@ -1569,7 +1637,9 @@ return yield;
/* This function is handed a compiled expression that it must study to produce
information that will speed up the matching.
-Argument: points to the compiled expression
+Argument:
+ re points to the compiled expression
+
Returns: 0 normally; non-zero should never normally occur
1 unknown opcode in set_start_bits
2 missing capturing bracket
@@ -1579,7 +1649,6 @@ Returns: 0 normally; non-zero should never normally occur
int
PRIV(study)(pcre2_real_code *re)
{
-int min;
int count = 0;
PCRE2_UCHAR *code;
BOOL utf = (re->overall_options & PCRE2_UTF) != 0;
@@ -1597,25 +1666,121 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)
{
int rc = set_start_bits(re, code, utf);
if (rc == SSB_UNKNOWN) return 1;
- if (rc == SSB_DONE) re->flags |= PCRE2_FIRSTMAPSET;
+
+ /* If a list of starting code units was set up, scan the list to see if only
+ one or two were listed. Having only one listed is rare because usually a
+ single starting code unit will have been recognized and PCRE2_FIRSTSET set.
+ If two are listed, see if they are caseless versions of the same character;
+ if so we can replace the list with a caseless first code unit. This gives
+ better performance and is plausibly worth doing for patterns such as [Ww]ord
+ or (word|WORD). */
+
+ if (rc == SSB_DONE)
+ {
+ int i;
+ int a = -1;
+ int b = -1;
+ uint8_t *p = re->start_bitmap;
+ uint32_t flags = PCRE2_FIRSTMAPSET;
+
+ for (i = 0; i < 256; p++, i += 8)
+ {
+ uint8_t x = *p;
+ if (x != 0)
+ {
+ int c;
+ uint8_t y = x & (~x + 1); /* Least significant bit */
+ if (y != x) goto DONE; /* More than one bit set */
+
+ /* In the 16-bit and 32-bit libraries, the bit for 0xff means "0xff and
+ all wide characters", so we cannot use it here. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ if (i == 248 && x == 0x80) goto DONE;
+#endif
+
+ /* Compute the character value */
+
+ c = i;
+ switch (x)
+ {
+ case 1: break;
+ case 2: c += 1; break; case 4: c += 2; break;
+ case 8: c += 3; break; case 16: c += 4; break;
+ case 32: c += 5; break; case 64: c += 6; break;
+ case 128: c += 7; break;
+ }
+
+ /* c contains the code unit value, in the range 0-255. In 8-bit UTF
+ mode, only values < 128 can be used. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (c > 127) goto DONE;
+#endif
+ if (a < 0) a = c; /* First one found */
+ else if (b < 0) /* Second one found */
+ {
+ int d = TABLE_GET((unsigned int)c, re->tables + fcc_offset, c);
+
+#ifdef SUPPORT_UNICODE
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (utf && UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */
+#else /* 16-bit or 32-bit */
+ if (UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */
+ if (utf && c > 127) d = UCD_OTHERCASE(c);
+#endif /* Code width */
+#endif /* SUPPORT_UNICODE */
+
+ if (d != a) goto DONE; /* Not other case of a */
+ b = c;
+ }
+ else goto DONE; /* More than two characters found */
+ }
+ }
+
+ /* Replace the start code unit bits with a first code unit, but only if it
+ is not the same as a required later code unit. This is because a search for
+ a required code unit starts after an explicit first code unit, but at a
+ code unit found from the bitmap. Patterns such as /a*a/ don't work
+ if both the start unit and required unit are the same. */
+
+ if (a >= 0 &&
+ (
+ (re->flags & PCRE2_LASTSET) == 0 ||
+ (
+ re->last_codeunit != (uint32_t)a &&
+ (b < 0 || re->last_codeunit != (uint32_t)b)
+ )
+ ))
+ {
+ re->first_codeunit = a;
+ flags = PCRE2_FIRSTSET;
+ if (b >= 0) flags |= PCRE2_FIRSTCASELESS;
+ }
+
+ DONE:
+ re->flags |= flags;
+ }
}
/* Find the minimum length of subject string. If the pattern can match an empty
-string, the minimum length is already known. If there are more back references
-than the size of the vector we are going to cache them in, do nothing. A
-pattern that complicated will probably take a long time to analyze and may in
-any case turn out to be too complicated. Note that back reference minima are
-held as 16-bit numbers. */
-
-if ((re->flags & PCRE2_MATCH_EMPTY) == 0 &&
+string, the minimum length is already known. If the pattern contains (*ACCEPT)
+all bets are off, and we don't even try to find a minimum length. If there are
+more back references than the size of the vector we are going to cache them in,
+do nothing. A pattern that complicated will probably take a long time to
+analyze and may in any case turn out to be too complicated. Note that back
+reference minima are held as 16-bit numbers. */
+
+if ((re->flags & (PCRE2_MATCH_EMPTY|PCRE2_HASACCEPT)) == 0 &&
re->top_backref <= MAX_CACHE_BACKREF)
{
+ int min;
int backref_cache[MAX_CACHE_BACKREF+1];
backref_cache[0] = 0; /* Highest one that is set */
min = find_minlength(re, code, code, utf, NULL, &count, backref_cache);
switch(min)
{
- case -1: /* \C in UTF mode or (*ACCEPT) or over-complex regex */
+ case -1: /* \C in UTF mode or over-complex regex */
break; /* Leave minlength unchanged (will be zero) */
case -2:
@@ -1625,8 +1790,7 @@ if ((re->flags & PCRE2_MATCH_EMPTY) == 0 &&
return 3; /* unrecognized opcode */
default:
- if (min > UINT16_MAX) min = UINT16_MAX;
- re->minlength = min;
+ re->minlength = (min > UINT16_MAX)? UINT16_MAX : min;
break;
}
}
diff --git a/thirdparty/pcre2/src/pcre2_tables.c b/thirdparty/pcre2/src/pcre2_tables.c
index 84019361fc..25531d98c6 100644
--- a/thirdparty/pcre2/src/pcre2_tables.c
+++ b/thirdparty/pcre2/src/pcre2_tables.c
@@ -279,6 +279,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Duployan0 STR_D STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0"
#define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
#define STRING_Elbasan0 STR_E STR_l STR_b STR_a STR_s STR_a STR_n "\0"
+#define STRING_Elymaic0 STR_E STR_l STR_y STR_m STR_a STR_i STR_c "\0"
#define STRING_Ethiopic0 STR_E STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0"
#define STRING_Georgian0 STR_G STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0"
#define STRING_Glagolitic0 STR_G STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0"
@@ -348,6 +349,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0"
#define STRING_N0 STR_N "\0"
#define STRING_Nabataean0 STR_N STR_a STR_b STR_a STR_t STR_a STR_e STR_a STR_n "\0"
+#define STRING_Nandinagari0 STR_N STR_a STR_n STR_d STR_i STR_n STR_a STR_g STR_a STR_r STR_i "\0"
#define STRING_Nd0 STR_N STR_d "\0"
#define STRING_New_Tai_Lue0 STR_N STR_e STR_w STR_UNDERSCORE STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_u STR_e "\0"
#define STRING_Newa0 STR_N STR_e STR_w STR_a "\0"
@@ -355,6 +357,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Nl0 STR_N STR_l "\0"
#define STRING_No0 STR_N STR_o "\0"
#define STRING_Nushu0 STR_N STR_u STR_s STR_h STR_u "\0"
+#define STRING_Nyiakeng_Puachue_Hmong0 STR_N STR_y STR_i STR_a STR_k STR_e STR_n STR_g STR_UNDERSCORE STR_P STR_u STR_a STR_c STR_h STR_u STR_e STR_UNDERSCORE STR_H STR_m STR_o STR_n STR_g "\0"
#define STRING_Ogham0 STR_O STR_g STR_h STR_a STR_m "\0"
#define STRING_Ol_Chiki0 STR_O STR_l STR_UNDERSCORE STR_C STR_h STR_i STR_k STR_i "\0"
#define STRING_Old_Hungarian0 STR_O STR_l STR_d STR_UNDERSCORE STR_H STR_u STR_n STR_g STR_a STR_r STR_i STR_a STR_n "\0"
@@ -419,6 +422,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Ugaritic0 STR_U STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"
#define STRING_Unknown0 STR_U STR_n STR_k STR_n STR_o STR_w STR_n "\0"
#define STRING_Vai0 STR_V STR_a STR_i "\0"
+#define STRING_Wancho0 STR_W STR_a STR_n STR_c STR_h STR_o "\0"
#define STRING_Warang_Citi0 STR_W STR_a STR_r STR_a STR_n STR_g STR_UNDERSCORE STR_C STR_i STR_t STR_i "\0"
#define STRING_Xan0 STR_X STR_a STR_n "\0"
#define STRING_Xps0 STR_X STR_p STR_s "\0"
@@ -474,6 +478,7 @@ const char PRIV(utt_names)[] =
STRING_Duployan0
STRING_Egyptian_Hieroglyphs0
STRING_Elbasan0
+ STRING_Elymaic0
STRING_Ethiopic0
STRING_Georgian0
STRING_Glagolitic0
@@ -543,6 +548,7 @@ const char PRIV(utt_names)[] =
STRING_Myanmar0
STRING_N0
STRING_Nabataean0
+ STRING_Nandinagari0
STRING_Nd0
STRING_New_Tai_Lue0
STRING_Newa0
@@ -550,6 +556,7 @@ const char PRIV(utt_names)[] =
STRING_Nl0
STRING_No0
STRING_Nushu0
+ STRING_Nyiakeng_Puachue_Hmong0
STRING_Ogham0
STRING_Ol_Chiki0
STRING_Old_Hungarian0
@@ -614,6 +621,7 @@ const char PRIV(utt_names)[] =
STRING_Ugaritic0
STRING_Unknown0
STRING_Vai0
+ STRING_Wancho0
STRING_Warang_Citi0
STRING_Xan0
STRING_Xps0
@@ -669,158 +677,162 @@ const ucp_type_table PRIV(utt)[] = {
{ 299, PT_SC, ucp_Duployan },
{ 308, PT_SC, ucp_Egyptian_Hieroglyphs },
{ 329, PT_SC, ucp_Elbasan },
- { 337, PT_SC, ucp_Ethiopic },
- { 346, PT_SC, ucp_Georgian },
- { 355, PT_SC, ucp_Glagolitic },
- { 366, PT_SC, ucp_Gothic },
- { 373, PT_SC, ucp_Grantha },
- { 381, PT_SC, ucp_Greek },
- { 387, PT_SC, ucp_Gujarati },
- { 396, PT_SC, ucp_Gunjala_Gondi },
- { 410, PT_SC, ucp_Gurmukhi },
- { 419, PT_SC, ucp_Han },
- { 423, PT_SC, ucp_Hangul },
- { 430, PT_SC, ucp_Hanifi_Rohingya },
- { 446, PT_SC, ucp_Hanunoo },
- { 454, PT_SC, ucp_Hatran },
- { 461, PT_SC, ucp_Hebrew },
- { 468, PT_SC, ucp_Hiragana },
- { 477, PT_SC, ucp_Imperial_Aramaic },
- { 494, PT_SC, ucp_Inherited },
- { 504, PT_SC, ucp_Inscriptional_Pahlavi },
- { 526, PT_SC, ucp_Inscriptional_Parthian },
- { 549, PT_SC, ucp_Javanese },
- { 558, PT_SC, ucp_Kaithi },
- { 565, PT_SC, ucp_Kannada },
- { 573, PT_SC, ucp_Katakana },
- { 582, PT_SC, ucp_Kayah_Li },
- { 591, PT_SC, ucp_Kharoshthi },
- { 602, PT_SC, ucp_Khmer },
- { 608, PT_SC, ucp_Khojki },
- { 615, PT_SC, ucp_Khudawadi },
- { 625, PT_GC, ucp_L },
- { 627, PT_LAMP, 0 },
- { 630, PT_SC, ucp_Lao },
- { 634, PT_SC, ucp_Latin },
- { 640, PT_SC, ucp_Lepcha },
- { 647, PT_SC, ucp_Limbu },
- { 653, PT_SC, ucp_Linear_A },
- { 662, PT_SC, ucp_Linear_B },
- { 671, PT_SC, ucp_Lisu },
- { 676, PT_PC, ucp_Ll },
- { 679, PT_PC, ucp_Lm },
- { 682, PT_PC, ucp_Lo },
- { 685, PT_PC, ucp_Lt },
- { 688, PT_PC, ucp_Lu },
- { 691, PT_SC, ucp_Lycian },
- { 698, PT_SC, ucp_Lydian },
- { 705, PT_GC, ucp_M },
- { 707, PT_SC, ucp_Mahajani },
- { 716, PT_SC, ucp_Makasar },
- { 724, PT_SC, ucp_Malayalam },
- { 734, PT_SC, ucp_Mandaic },
- { 742, PT_SC, ucp_Manichaean },
- { 753, PT_SC, ucp_Marchen },
- { 761, PT_SC, ucp_Masaram_Gondi },
- { 775, PT_PC, ucp_Mc },
- { 778, PT_PC, ucp_Me },
- { 781, PT_SC, ucp_Medefaidrin },
- { 793, PT_SC, ucp_Meetei_Mayek },
- { 806, PT_SC, ucp_Mende_Kikakui },
- { 820, PT_SC, ucp_Meroitic_Cursive },
- { 837, PT_SC, ucp_Meroitic_Hieroglyphs },
- { 858, PT_SC, ucp_Miao },
- { 863, PT_PC, ucp_Mn },
- { 866, PT_SC, ucp_Modi },
- { 871, PT_SC, ucp_Mongolian },
- { 881, PT_SC, ucp_Mro },
- { 885, PT_SC, ucp_Multani },
- { 893, PT_SC, ucp_Myanmar },
- { 901, PT_GC, ucp_N },
- { 903, PT_SC, ucp_Nabataean },
- { 913, PT_PC, ucp_Nd },
- { 916, PT_SC, ucp_New_Tai_Lue },
- { 928, PT_SC, ucp_Newa },
- { 933, PT_SC, ucp_Nko },
- { 937, PT_PC, ucp_Nl },
- { 940, PT_PC, ucp_No },
- { 943, PT_SC, ucp_Nushu },
- { 949, PT_SC, ucp_Ogham },
- { 955, PT_SC, ucp_Ol_Chiki },
- { 964, PT_SC, ucp_Old_Hungarian },
- { 978, PT_SC, ucp_Old_Italic },
- { 989, PT_SC, ucp_Old_North_Arabian },
- { 1007, PT_SC, ucp_Old_Permic },
- { 1018, PT_SC, ucp_Old_Persian },
- { 1030, PT_SC, ucp_Old_Sogdian },
- { 1042, PT_SC, ucp_Old_South_Arabian },
- { 1060, PT_SC, ucp_Old_Turkic },
- { 1071, PT_SC, ucp_Oriya },
- { 1077, PT_SC, ucp_Osage },
- { 1083, PT_SC, ucp_Osmanya },
- { 1091, PT_GC, ucp_P },
- { 1093, PT_SC, ucp_Pahawh_Hmong },
- { 1106, PT_SC, ucp_Palmyrene },
- { 1116, PT_SC, ucp_Pau_Cin_Hau },
- { 1128, PT_PC, ucp_Pc },
- { 1131, PT_PC, ucp_Pd },
- { 1134, PT_PC, ucp_Pe },
- { 1137, PT_PC, ucp_Pf },
- { 1140, PT_SC, ucp_Phags_Pa },
- { 1149, PT_SC, ucp_Phoenician },
- { 1160, PT_PC, ucp_Pi },
- { 1163, PT_PC, ucp_Po },
- { 1166, PT_PC, ucp_Ps },
- { 1169, PT_SC, ucp_Psalter_Pahlavi },
- { 1185, PT_SC, ucp_Rejang },
- { 1192, PT_SC, ucp_Runic },
- { 1198, PT_GC, ucp_S },
- { 1200, PT_SC, ucp_Samaritan },
- { 1210, PT_SC, ucp_Saurashtra },
- { 1221, PT_PC, ucp_Sc },
- { 1224, PT_SC, ucp_Sharada },
- { 1232, PT_SC, ucp_Shavian },
- { 1240, PT_SC, ucp_Siddham },
- { 1248, PT_SC, ucp_SignWriting },
- { 1260, PT_SC, ucp_Sinhala },
- { 1268, PT_PC, ucp_Sk },
- { 1271, PT_PC, ucp_Sm },
- { 1274, PT_PC, ucp_So },
- { 1277, PT_SC, ucp_Sogdian },
- { 1285, PT_SC, ucp_Sora_Sompeng },
- { 1298, PT_SC, ucp_Soyombo },
- { 1306, PT_SC, ucp_Sundanese },
- { 1316, PT_SC, ucp_Syloti_Nagri },
- { 1329, PT_SC, ucp_Syriac },
- { 1336, PT_SC, ucp_Tagalog },
- { 1344, PT_SC, ucp_Tagbanwa },
- { 1353, PT_SC, ucp_Tai_Le },
- { 1360, PT_SC, ucp_Tai_Tham },
- { 1369, PT_SC, ucp_Tai_Viet },
- { 1378, PT_SC, ucp_Takri },
- { 1384, PT_SC, ucp_Tamil },
- { 1390, PT_SC, ucp_Tangut },
- { 1397, PT_SC, ucp_Telugu },
- { 1404, PT_SC, ucp_Thaana },
- { 1411, PT_SC, ucp_Thai },
- { 1416, PT_SC, ucp_Tibetan },
- { 1424, PT_SC, ucp_Tifinagh },
- { 1433, PT_SC, ucp_Tirhuta },
- { 1441, PT_SC, ucp_Ugaritic },
- { 1450, PT_SC, ucp_Unknown },
- { 1458, PT_SC, ucp_Vai },
- { 1462, PT_SC, ucp_Warang_Citi },
- { 1474, PT_ALNUM, 0 },
- { 1478, PT_PXSPACE, 0 },
- { 1482, PT_SPACE, 0 },
- { 1486, PT_UCNC, 0 },
- { 1490, PT_WORD, 0 },
- { 1494, PT_SC, ucp_Yi },
- { 1497, PT_GC, ucp_Z },
- { 1499, PT_SC, ucp_Zanabazar_Square },
- { 1516, PT_PC, ucp_Zl },
- { 1519, PT_PC, ucp_Zp },
- { 1522, PT_PC, ucp_Zs }
+ { 337, PT_SC, ucp_Elymaic },
+ { 345, PT_SC, ucp_Ethiopic },
+ { 354, PT_SC, ucp_Georgian },
+ { 363, PT_SC, ucp_Glagolitic },
+ { 374, PT_SC, ucp_Gothic },
+ { 381, PT_SC, ucp_Grantha },
+ { 389, PT_SC, ucp_Greek },
+ { 395, PT_SC, ucp_Gujarati },
+ { 404, PT_SC, ucp_Gunjala_Gondi },
+ { 418, PT_SC, ucp_Gurmukhi },
+ { 427, PT_SC, ucp_Han },
+ { 431, PT_SC, ucp_Hangul },
+ { 438, PT_SC, ucp_Hanifi_Rohingya },
+ { 454, PT_SC, ucp_Hanunoo },
+ { 462, PT_SC, ucp_Hatran },
+ { 469, PT_SC, ucp_Hebrew },
+ { 476, PT_SC, ucp_Hiragana },
+ { 485, PT_SC, ucp_Imperial_Aramaic },
+ { 502, PT_SC, ucp_Inherited },
+ { 512, PT_SC, ucp_Inscriptional_Pahlavi },
+ { 534, PT_SC, ucp_Inscriptional_Parthian },
+ { 557, PT_SC, ucp_Javanese },
+ { 566, PT_SC, ucp_Kaithi },
+ { 573, PT_SC, ucp_Kannada },
+ { 581, PT_SC, ucp_Katakana },
+ { 590, PT_SC, ucp_Kayah_Li },
+ { 599, PT_SC, ucp_Kharoshthi },
+ { 610, PT_SC, ucp_Khmer },
+ { 616, PT_SC, ucp_Khojki },
+ { 623, PT_SC, ucp_Khudawadi },
+ { 633, PT_GC, ucp_L },
+ { 635, PT_LAMP, 0 },
+ { 638, PT_SC, ucp_Lao },
+ { 642, PT_SC, ucp_Latin },
+ { 648, PT_SC, ucp_Lepcha },
+ { 655, PT_SC, ucp_Limbu },
+ { 661, PT_SC, ucp_Linear_A },
+ { 670, PT_SC, ucp_Linear_B },
+ { 679, PT_SC, ucp_Lisu },
+ { 684, PT_PC, ucp_Ll },
+ { 687, PT_PC, ucp_Lm },
+ { 690, PT_PC, ucp_Lo },
+ { 693, PT_PC, ucp_Lt },
+ { 696, PT_PC, ucp_Lu },
+ { 699, PT_SC, ucp_Lycian },
+ { 706, PT_SC, ucp_Lydian },
+ { 713, PT_GC, ucp_M },
+ { 715, PT_SC, ucp_Mahajani },
+ { 724, PT_SC, ucp_Makasar },
+ { 732, PT_SC, ucp_Malayalam },
+ { 742, PT_SC, ucp_Mandaic },
+ { 750, PT_SC, ucp_Manichaean },
+ { 761, PT_SC, ucp_Marchen },
+ { 769, PT_SC, ucp_Masaram_Gondi },
+ { 783, PT_PC, ucp_Mc },
+ { 786, PT_PC, ucp_Me },
+ { 789, PT_SC, ucp_Medefaidrin },
+ { 801, PT_SC, ucp_Meetei_Mayek },
+ { 814, PT_SC, ucp_Mende_Kikakui },
+ { 828, PT_SC, ucp_Meroitic_Cursive },
+ { 845, PT_SC, ucp_Meroitic_Hieroglyphs },
+ { 866, PT_SC, ucp_Miao },
+ { 871, PT_PC, ucp_Mn },
+ { 874, PT_SC, ucp_Modi },
+ { 879, PT_SC, ucp_Mongolian },
+ { 889, PT_SC, ucp_Mro },
+ { 893, PT_SC, ucp_Multani },
+ { 901, PT_SC, ucp_Myanmar },
+ { 909, PT_GC, ucp_N },
+ { 911, PT_SC, ucp_Nabataean },
+ { 921, PT_SC, ucp_Nandinagari },
+ { 933, PT_PC, ucp_Nd },
+ { 936, PT_SC, ucp_New_Tai_Lue },
+ { 948, PT_SC, ucp_Newa },
+ { 953, PT_SC, ucp_Nko },
+ { 957, PT_PC, ucp_Nl },
+ { 960, PT_PC, ucp_No },
+ { 963, PT_SC, ucp_Nushu },
+ { 969, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
+ { 992, PT_SC, ucp_Ogham },
+ { 998, PT_SC, ucp_Ol_Chiki },
+ { 1007, PT_SC, ucp_Old_Hungarian },
+ { 1021, PT_SC, ucp_Old_Italic },
+ { 1032, PT_SC, ucp_Old_North_Arabian },
+ { 1050, PT_SC, ucp_Old_Permic },
+ { 1061, PT_SC, ucp_Old_Persian },
+ { 1073, PT_SC, ucp_Old_Sogdian },
+ { 1085, PT_SC, ucp_Old_South_Arabian },
+ { 1103, PT_SC, ucp_Old_Turkic },
+ { 1114, PT_SC, ucp_Oriya },
+ { 1120, PT_SC, ucp_Osage },
+ { 1126, PT_SC, ucp_Osmanya },
+ { 1134, PT_GC, ucp_P },
+ { 1136, PT_SC, ucp_Pahawh_Hmong },
+ { 1149, PT_SC, ucp_Palmyrene },
+ { 1159, PT_SC, ucp_Pau_Cin_Hau },
+ { 1171, PT_PC, ucp_Pc },
+ { 1174, PT_PC, ucp_Pd },
+ { 1177, PT_PC, ucp_Pe },
+ { 1180, PT_PC, ucp_Pf },
+ { 1183, PT_SC, ucp_Phags_Pa },
+ { 1192, PT_SC, ucp_Phoenician },
+ { 1203, PT_PC, ucp_Pi },
+ { 1206, PT_PC, ucp_Po },
+ { 1209, PT_PC, ucp_Ps },
+ { 1212, PT_SC, ucp_Psalter_Pahlavi },
+ { 1228, PT_SC, ucp_Rejang },
+ { 1235, PT_SC, ucp_Runic },
+ { 1241, PT_GC, ucp_S },
+ { 1243, PT_SC, ucp_Samaritan },
+ { 1253, PT_SC, ucp_Saurashtra },
+ { 1264, PT_PC, ucp_Sc },
+ { 1267, PT_SC, ucp_Sharada },
+ { 1275, PT_SC, ucp_Shavian },
+ { 1283, PT_SC, ucp_Siddham },
+ { 1291, PT_SC, ucp_SignWriting },
+ { 1303, PT_SC, ucp_Sinhala },
+ { 1311, PT_PC, ucp_Sk },
+ { 1314, PT_PC, ucp_Sm },
+ { 1317, PT_PC, ucp_So },
+ { 1320, PT_SC, ucp_Sogdian },
+ { 1328, PT_SC, ucp_Sora_Sompeng },
+ { 1341, PT_SC, ucp_Soyombo },
+ { 1349, PT_SC, ucp_Sundanese },
+ { 1359, PT_SC, ucp_Syloti_Nagri },
+ { 1372, PT_SC, ucp_Syriac },
+ { 1379, PT_SC, ucp_Tagalog },
+ { 1387, PT_SC, ucp_Tagbanwa },
+ { 1396, PT_SC, ucp_Tai_Le },
+ { 1403, PT_SC, ucp_Tai_Tham },
+ { 1412, PT_SC, ucp_Tai_Viet },
+ { 1421, PT_SC, ucp_Takri },
+ { 1427, PT_SC, ucp_Tamil },
+ { 1433, PT_SC, ucp_Tangut },
+ { 1440, PT_SC, ucp_Telugu },
+ { 1447, PT_SC, ucp_Thaana },
+ { 1454, PT_SC, ucp_Thai },
+ { 1459, PT_SC, ucp_Tibetan },
+ { 1467, PT_SC, ucp_Tifinagh },
+ { 1476, PT_SC, ucp_Tirhuta },
+ { 1484, PT_SC, ucp_Ugaritic },
+ { 1493, PT_SC, ucp_Unknown },
+ { 1501, PT_SC, ucp_Vai },
+ { 1505, PT_SC, ucp_Wancho },
+ { 1512, PT_SC, ucp_Warang_Citi },
+ { 1524, PT_ALNUM, 0 },
+ { 1528, PT_PXSPACE, 0 },
+ { 1532, PT_SPACE, 0 },
+ { 1536, PT_UCNC, 0 },
+ { 1540, PT_WORD, 0 },
+ { 1544, PT_SC, ucp_Yi },
+ { 1547, PT_GC, ucp_Z },
+ { 1549, PT_SC, ucp_Zanabazar_Square },
+ { 1566, PT_PC, ucp_Zl },
+ { 1569, PT_PC, ucp_Zp },
+ { 1572, PT_PC, ucp_Zs }
};
const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
diff --git a/thirdparty/pcre2/src/pcre2_ucd.c b/thirdparty/pcre2/src/pcre2_ucd.c
index cc53c24001..55ba03bd43 100644
--- a/thirdparty/pcre2/src/pcre2_ucd.c
+++ b/thirdparty/pcre2/src/pcre2_ucd.c
@@ -20,7 +20,7 @@ needed. */
/* Unicode character database. */
/* This file was autogenerated by the MultiStage2.py script. */
-/* Total size: 97152 bytes, block size: 128. */
+/* Total size: 99316 bytes, block size: 128. */
/* The tables herein are needed only when UCP support is built,
and in PCRE2 that happens automatically with UTF support.
@@ -39,7 +39,7 @@ const uint16_t PRIV(ucd_stage2)[] = {0};
const uint32_t PRIV(ucd_caseless_sets)[] = {0};
#else
-const char *PRIV(unicode_version) = "11.0.0";
+const char *PRIV(unicode_version) = "12.1.0";
/* If the 32-bit library is run in non-32-bit mode, character values
greater than 0x10ffff may be encountered. For these we set up a
@@ -116,7 +116,7 @@ set of decimal digits. It is used to ensure that all the digits in
a script run come from the same set. */
const uint32_t PRIV(ucd_digit_sets)[] = {
- 61, /* Number of subsequent values */
+ 63, /* Number of subsequent values */
0x00039, 0x00669, 0x006f9, 0x007c9, 0x0096f, 0x009ef, 0x00a6f, 0x00aef,
0x00b6f, 0x00bef, 0x00c6f, 0x00cef, 0x00d6f, 0x00def, 0x00e59, 0x00ed9,
0x00f29, 0x01049, 0x01099, 0x017e9, 0x01819, 0x0194f, 0x019d9, 0x01a89,
@@ -124,7 +124,7 @@ const uint32_t PRIV(ucd_digit_sets)[] = {
0x0a9d9, 0x0a9f9, 0x0aa59, 0x0abf9, 0x0ff19, 0x104a9, 0x10d39, 0x1106f,
0x110f9, 0x1113f, 0x111d9, 0x112f9, 0x11459, 0x114d9, 0x11659, 0x116c9,
0x11739, 0x118e9, 0x11c59, 0x11d59, 0x11da9, 0x16a69, 0x16b59, 0x1d7d7,
- 0x1d7e1, 0x1d7eb, 0x1d7f5, 0x1d7ff, 0x1e959,
+ 0x1d7e1, 0x1d7eb, 0x1d7f5, 0x1d7ff, 0x1e149, 0x1e2f9, 0x1e959,
};
/* This vector is a list of lists of scripts for the Script Extension
@@ -145,38 +145,42 @@ const uint8_t PRIV(ucd_script_sets)[] = {
/* 31 */ 13, 34, 0,
/* 34 */ 13, 118, 0,
/* 37 */ 15, 107, 0,
- /* 40 */ 15, 100, 0,
- /* 43 */ 15, 54, 0,
- /* 46 */ 17, 34, 0,
- /* 49 */ 107, 54, 0,
- /* 52 */ 21, 108, 0,
- /* 55 */ 22, 129, 0,
- /* 58 */ 27, 30, 0,
- /* 61 */ 38, 65, 0,
- /* 64 */ 1, 50, 56, 0,
- /* 68 */ 3, 96, 49, 0,
- /* 72 */ 96, 39, 53, 0,
- /* 76 */ 12, 110, 36, 0,
- /* 80 */ 15, 107, 29, 0,
- /* 84 */ 15, 107, 34, 0,
- /* 88 */ 23, 27, 30, 0,
- /* 92 */ 69, 34, 39, 0,
- /* 96 */ 1, 144, 50, 56, 0,
- /* 101 */ 3, 15, 107, 29, 0,
- /* 106 */ 7, 25, 52, 51, 0,
- /* 111 */ 15, 142, 85, 111, 0,
- /* 116 */ 4, 24, 23, 27, 30, 0,
- /* 122 */ 4, 24, 23, 27, 30, 61, 0,
- /* 129 */ 15, 29, 37, 44, 54, 55, 0,
- /* 136 */ 132, 1, 95, 112, 121, 144, 148, 50, 0,
- /* 145 */ 15, 142, 21, 22, 108, 85, 111, 114, 109, 102, 124, 0,
- /* 157 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 54, 55, 124, 0,
- /* 170 */ 15, 142, 21, 22, 108, 29, 85, 111, 114, 109, 102, 124, 0,
- /* 183 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 100, 54, 55, 124, 0,
- /* 197 */ 15, 142, 21, 22, 108, 29, 85, 111, 37, 114, 109, 102, 124, 0,
- /* 211 */ 3, 15, 142, 143, 107, 21, 22, 29, 111, 37, 44, 109, 48, 49, 102, 54, 55, 124, 0,
- /* 230 */ 3, 15, 142, 143, 107, 21, 22, 29, 35, 111, 37, 44, 109, 48, 49, 102, 54, 55, 124, 0,
- /* 250 */
+ /* 40 */ 15, 150, 0,
+ /* 43 */ 15, 100, 0,
+ /* 46 */ 15, 54, 0,
+ /* 49 */ 17, 34, 0,
+ /* 52 */ 107, 54, 0,
+ /* 55 */ 21, 108, 0,
+ /* 58 */ 22, 129, 0,
+ /* 61 */ 27, 30, 0,
+ /* 64 */ 29, 150, 0,
+ /* 67 */ 34, 38, 0,
+ /* 70 */ 38, 65, 0,
+ /* 73 */ 1, 50, 56, 0,
+ /* 77 */ 3, 96, 49, 0,
+ /* 81 */ 96, 39, 53, 0,
+ /* 85 */ 12, 110, 36, 0,
+ /* 89 */ 15, 107, 29, 0,
+ /* 93 */ 15, 107, 34, 0,
+ /* 97 */ 23, 27, 30, 0,
+ /* 101 */ 69, 34, 39, 0,
+ /* 105 */ 1, 144, 50, 56, 0,
+ /* 110 */ 3, 15, 107, 29, 0,
+ /* 115 */ 7, 25, 52, 51, 0,
+ /* 120 */ 15, 142, 85, 111, 0,
+ /* 125 */ 4, 24, 23, 27, 30, 0,
+ /* 131 */ 4, 24, 23, 27, 30, 61, 0,
+ /* 138 */ 15, 29, 37, 44, 54, 55, 0,
+ /* 145 */ 132, 1, 95, 112, 121, 144, 148, 50, 0,
+ /* 154 */ 3, 15, 107, 29, 150, 44, 55, 124, 0,
+ /* 163 */ 15, 142, 21, 22, 108, 85, 111, 114, 109, 102, 124, 0,
+ /* 175 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 54, 55, 124, 0,
+ /* 188 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 100, 54, 55, 124, 0,
+ /* 202 */ 15, 142, 21, 22, 108, 29, 85, 111, 114, 150, 109, 102, 124, 0,
+ /* 216 */ 15, 142, 21, 22, 108, 29, 85, 111, 37, 114, 150, 109, 102, 124, 0,
+ /* 231 */ 3, 15, 142, 143, 138, 107, 21, 22, 29, 111, 37, 150, 44, 109, 48, 49, 102, 54, 55, 124, 0,
+ /* 252 */ 3, 15, 142, 143, 138, 107, 21, 22, 29, 35, 111, 37, 150, 44, 109, 48, 49, 102, 54, 55, 124, 0,
+ /* 274 */
};
/* These are the main two-stage UCD tables. The fields in each record are:
@@ -185,7 +189,7 @@ offset to multichar other cases or zero (8 bits), offset to other case
or zero (32 bits, signed), script extension (16 bits, signed), and a dummy
16-bit field to make the whole thing a multiple of 4 bytes. */
-const ucd_record PRIV(ucd_records)[] = { /* 11136 bytes, record size 12 */
+const ucd_record PRIV(ucd_records)[] = { /* 11508 bytes, record size 12 */
{ 10, 0, 2, 0, 0, 10, 256, }, /* 0 */
{ 10, 0, 2, 0, 0, 10, 0, }, /* 1 */
{ 10, 0, 1, 0, 0, 10, 0, }, /* 2 */
@@ -288,832 +292,863 @@ const ucd_record PRIV(ucd_records)[] = { /* 11136 bytes, record size 12 */
{ 34, 5, 12, 0, -214, 34, 0, }, /* 99 */
{ 34, 5, 12, 0, 10727, 34, 0, }, /* 100 */
{ 34, 5, 12, 0, -218, 34, 0, }, /* 101 */
- { 34, 5, 12, 0, 42282, 34, 0, }, /* 102 */
- { 34, 5, 12, 0, -69, 34, 0, }, /* 103 */
- { 34, 5, 12, 0, -217, 34, 0, }, /* 104 */
- { 34, 5, 12, 0, -71, 34, 0, }, /* 105 */
- { 34, 5, 12, 0, -219, 34, 0, }, /* 106 */
- { 34, 5, 12, 0, 42261, 34, 0, }, /* 107 */
- { 34, 5, 12, 0, 42258, 34, 0, }, /* 108 */
- { 34, 6, 12, 0, 0, 34, 0, }, /* 109 */
- { 10, 6, 12, 0, 0, 10, 0, }, /* 110 */
- { 4, 24, 12, 0, 0, 4, 0, }, /* 111 */
- { 28, 12, 3, 0, 0, 28, 0, }, /* 112 */
- { 28, 12, 3, 0, 0, 20, 0, }, /* 113 */
- { 28, 12, 3, 21, 116, 20, 0, }, /* 114 */
- { 28, 12, 3, 0, 0, 34, 0, }, /* 115 */
- { 20, 9, 12, 0, 1, 20, 0, }, /* 116 */
- { 20, 5, 12, 0, -1, 20, 0, }, /* 117 */
- { 20, 24, 12, 0, 0, 20, 0, }, /* 118 */
- { 0, 2, 12, 0, 0, 0, 0, }, /* 119 */
- { 20, 6, 12, 0, 0, 20, 0, }, /* 120 */
- { 20, 5, 12, 0, 130, 20, 0, }, /* 121 */
- { 20, 9, 12, 0, 116, 20, 0, }, /* 122 */
- { 20, 9, 12, 0, 38, 20, 0, }, /* 123 */
- { 20, 9, 12, 0, 37, 20, 0, }, /* 124 */
- { 20, 9, 12, 0, 64, 20, 0, }, /* 125 */
- { 20, 9, 12, 0, 63, 20, 0, }, /* 126 */
- { 20, 5, 12, 0, 0, 20, 0, }, /* 127 */
- { 20, 9, 12, 0, 32, 20, 0, }, /* 128 */
- { 20, 9, 12, 34, 32, 20, 0, }, /* 129 */
- { 20, 9, 12, 59, 32, 20, 0, }, /* 130 */
- { 20, 9, 12, 38, 32, 20, 0, }, /* 131 */
- { 20, 9, 12, 21, 32, 20, 0, }, /* 132 */
- { 20, 9, 12, 51, 32, 20, 0, }, /* 133 */
- { 20, 9, 12, 26, 32, 20, 0, }, /* 134 */
- { 20, 9, 12, 47, 32, 20, 0, }, /* 135 */
- { 20, 9, 12, 55, 32, 20, 0, }, /* 136 */
- { 20, 9, 12, 30, 32, 20, 0, }, /* 137 */
- { 20, 9, 12, 43, 32, 20, 0, }, /* 138 */
- { 20, 9, 12, 96, 32, 20, 0, }, /* 139 */
- { 20, 5, 12, 0, -38, 20, 0, }, /* 140 */
- { 20, 5, 12, 0, -37, 20, 0, }, /* 141 */
- { 20, 5, 12, 0, -32, 20, 0, }, /* 142 */
- { 20, 5, 12, 34, -32, 20, 0, }, /* 143 */
- { 20, 5, 12, 59, -32, 20, 0, }, /* 144 */
- { 20, 5, 12, 38, -32, 20, 0, }, /* 145 */
- { 20, 5, 12, 21, -116, 20, 0, }, /* 146 */
- { 20, 5, 12, 51, -32, 20, 0, }, /* 147 */
- { 20, 5, 12, 26, -775, 20, 0, }, /* 148 */
- { 20, 5, 12, 47, -32, 20, 0, }, /* 149 */
- { 20, 5, 12, 55, -32, 20, 0, }, /* 150 */
- { 20, 5, 12, 30, 1, 20, 0, }, /* 151 */
- { 20, 5, 12, 30, -32, 20, 0, }, /* 152 */
- { 20, 5, 12, 43, -32, 20, 0, }, /* 153 */
- { 20, 5, 12, 96, -32, 20, 0, }, /* 154 */
- { 20, 5, 12, 0, -64, 20, 0, }, /* 155 */
- { 20, 5, 12, 0, -63, 20, 0, }, /* 156 */
- { 20, 9, 12, 0, 8, 20, 0, }, /* 157 */
- { 20, 5, 12, 34, -30, 20, 0, }, /* 158 */
- { 20, 5, 12, 38, -25, 20, 0, }, /* 159 */
- { 20, 9, 12, 0, 0, 20, 0, }, /* 160 */
- { 20, 5, 12, 43, -15, 20, 0, }, /* 161 */
- { 20, 5, 12, 47, -22, 20, 0, }, /* 162 */
- { 20, 5, 12, 0, -8, 20, 0, }, /* 163 */
- { 11, 9, 12, 0, 1, 11, 0, }, /* 164 */
- { 11, 5, 12, 0, -1, 11, 0, }, /* 165 */
- { 20, 5, 12, 51, -54, 20, 0, }, /* 166 */
- { 20, 5, 12, 55, -48, 20, 0, }, /* 167 */
- { 20, 5, 12, 0, 7, 20, 0, }, /* 168 */
- { 20, 5, 12, 0, -116, 20, 0, }, /* 169 */
- { 20, 9, 12, 38, -60, 20, 0, }, /* 170 */
- { 20, 5, 12, 59, -64, 20, 0, }, /* 171 */
- { 20, 25, 12, 0, 0, 20, 0, }, /* 172 */
- { 20, 9, 12, 0, -7, 20, 0, }, /* 173 */
- { 20, 9, 12, 0, -130, 20, 0, }, /* 174 */
- { 13, 9, 12, 0, 80, 13, 0, }, /* 175 */
- { 13, 9, 12, 0, 32, 13, 0, }, /* 176 */
- { 13, 9, 12, 63, 32, 13, 0, }, /* 177 */
- { 13, 9, 12, 67, 32, 13, 0, }, /* 178 */
- { 13, 9, 12, 71, 32, 13, 0, }, /* 179 */
- { 13, 9, 12, 75, 32, 13, 0, }, /* 180 */
- { 13, 9, 12, 79, 32, 13, 0, }, /* 181 */
- { 13, 9, 12, 84, 32, 13, 0, }, /* 182 */
- { 13, 5, 12, 0, -32, 13, 0, }, /* 183 */
- { 13, 5, 12, 63, -32, 13, 0, }, /* 184 */
- { 13, 5, 12, 67, -32, 13, 0, }, /* 185 */
- { 13, 5, 12, 71, -32, 13, 0, }, /* 186 */
- { 13, 5, 12, 75, -32, 13, 0, }, /* 187 */
- { 13, 5, 12, 79, -32, 13, 0, }, /* 188 */
- { 13, 5, 12, 84, -32, 13, 0, }, /* 189 */
- { 13, 5, 12, 0, -80, 13, 0, }, /* 190 */
- { 13, 9, 12, 0, 1, 13, 0, }, /* 191 */
- { 13, 5, 12, 0, -1, 13, 0, }, /* 192 */
- { 13, 9, 12, 88, 1, 13, 0, }, /* 193 */
- { 13, 5, 12, 88, -1, 13, 0, }, /* 194 */
- { 13, 26, 12, 0, 0, 13, 0, }, /* 195 */
- { 13, 12, 3, 0, 0, -34, 0, }, /* 196 */
- { 13, 12, 3, 0, 0, -28, 0, }, /* 197 */
- { 28, 12, 3, 0, 0, -31, 0, }, /* 198 */
- { 13, 11, 3, 0, 0, 13, 0, }, /* 199 */
- { 13, 9, 12, 0, 15, 13, 0, }, /* 200 */
- { 13, 5, 12, 0, -15, 13, 0, }, /* 201 */
- { 2, 9, 12, 0, 48, 2, 0, }, /* 202 */
- { 2, 6, 12, 0, 0, 2, 0, }, /* 203 */
- { 2, 21, 12, 0, 0, 2, 0, }, /* 204 */
- { 2, 5, 12, 0, 0, 2, 0, }, /* 205 */
- { 2, 5, 12, 0, -48, 2, 0, }, /* 206 */
- { 10, 21, 12, 0, 0, -13, 0, }, /* 207 */
- { 2, 17, 12, 0, 0, 2, 0, }, /* 208 */
- { 2, 26, 12, 0, 0, 2, 0, }, /* 209 */
- { 2, 23, 12, 0, 0, 2, 0, }, /* 210 */
- { 26, 12, 3, 0, 0, 26, 0, }, /* 211 */
- { 26, 17, 12, 0, 0, 26, 0, }, /* 212 */
- { 26, 21, 12, 0, 0, 26, 0, }, /* 213 */
- { 26, 7, 12, 0, 0, 26, 0, }, /* 214 */
- { 1, 1, 4, 0, 0, 1, 0, }, /* 215 */
- { 10, 1, 4, 0, 0, 10, 0, }, /* 216 */
- { 1, 25, 12, 0, 0, 1, 0, }, /* 217 */
- { 1, 21, 12, 0, 0, 1, 0, }, /* 218 */
- { 1, 23, 12, 0, 0, 1, 0, }, /* 219 */
- { 10, 21, 12, 0, 0, -96, 0, }, /* 220 */
- { 1, 26, 12, 0, 0, 1, 0, }, /* 221 */
- { 1, 12, 3, 0, 0, 1, 0, }, /* 222 */
- { 1, 1, 2, 0, 0, -64, 0, }, /* 223 */
- { 1, 7, 12, 0, 0, 1, 0, }, /* 224 */
- { 10, 6, 12, 0, 0, -136, 0, }, /* 225 */
- { 28, 12, 3, 0, 0, -7, 0, }, /* 226 */
- { 1, 13, 12, 0, 0, -10, 0, }, /* 227 */
- { 1, 21, 12, 0, 0, -4, 0, }, /* 228 */
- { 1, 6, 12, 0, 0, 1, 0, }, /* 229 */
- { 1, 13, 12, 0, 0, 1, 0, }, /* 230 */
- { 50, 21, 12, 0, 0, 50, 0, }, /* 231 */
- { 50, 1, 4, 0, 0, 50, 0, }, /* 232 */
- { 50, 7, 12, 0, 0, 50, 0, }, /* 233 */
- { 50, 12, 3, 0, 0, 50, 0, }, /* 234 */
- { 56, 7, 12, 0, 0, 56, 0, }, /* 235 */
- { 56, 12, 3, 0, 0, 56, 0, }, /* 236 */
- { 64, 13, 12, 0, 0, 64, 0, }, /* 237 */
- { 64, 7, 12, 0, 0, 64, 0, }, /* 238 */
- { 64, 12, 3, 0, 0, 64, 0, }, /* 239 */
- { 64, 6, 12, 0, 0, 64, 0, }, /* 240 */
- { 64, 26, 12, 0, 0, 64, 0, }, /* 241 */
- { 64, 21, 12, 0, 0, 64, 0, }, /* 242 */
- { 64, 23, 12, 0, 0, 64, 0, }, /* 243 */
- { 90, 7, 12, 0, 0, 90, 0, }, /* 244 */
- { 90, 12, 3, 0, 0, 90, 0, }, /* 245 */
- { 90, 6, 12, 0, 0, 90, 0, }, /* 246 */
- { 90, 21, 12, 0, 0, 90, 0, }, /* 247 */
- { 95, 7, 12, 0, 0, 95, 0, }, /* 248 */
- { 95, 12, 3, 0, 0, 95, 0, }, /* 249 */
- { 95, 21, 12, 0, 0, 95, 0, }, /* 250 */
- { 15, 12, 3, 0, 0, 15, 0, }, /* 251 */
- { 15, 10, 5, 0, 0, 15, 0, }, /* 252 */
- { 15, 7, 12, 0, 0, 15, 0, }, /* 253 */
- { 28, 12, 3, 0, 0, -183, 0, }, /* 254 */
- { 28, 12, 3, 0, 0, -157, 0, }, /* 255 */
- { 10, 21, 12, 0, 0, -211, 0, }, /* 256 */
- { 10, 21, 12, 0, 0, -230, 0, }, /* 257 */
- { 15, 13, 12, 0, 0, -111, 0, }, /* 258 */
- { 15, 21, 12, 0, 0, 15, 0, }, /* 259 */
- { 15, 6, 12, 0, 0, 15, 0, }, /* 260 */
- { 3, 7, 12, 0, 0, 3, 0, }, /* 261 */
- { 3, 12, 3, 0, 0, 3, 0, }, /* 262 */
- { 3, 10, 5, 0, 0, 3, 0, }, /* 263 */
- { 3, 10, 3, 0, 0, 3, 0, }, /* 264 */
- { 3, 13, 12, 0, 0, -68, 0, }, /* 265 */
- { 3, 23, 12, 0, 0, 3, 0, }, /* 266 */
- { 3, 15, 12, 0, 0, 3, 0, }, /* 267 */
- { 3, 26, 12, 0, 0, 3, 0, }, /* 268 */
- { 3, 21, 12, 0, 0, 3, 0, }, /* 269 */
- { 22, 12, 3, 0, 0, 22, 0, }, /* 270 */
- { 22, 10, 5, 0, 0, 22, 0, }, /* 271 */
- { 22, 7, 12, 0, 0, 22, 0, }, /* 272 */
- { 22, 13, 12, 0, 0, -55, 0, }, /* 273 */
- { 22, 21, 12, 0, 0, 22, 0, }, /* 274 */
- { 21, 12, 3, 0, 0, 21, 0, }, /* 275 */
- { 21, 10, 5, 0, 0, 21, 0, }, /* 276 */
- { 21, 7, 12, 0, 0, 21, 0, }, /* 277 */
- { 21, 13, 12, 0, 0, -52, 0, }, /* 278 */
- { 21, 21, 12, 0, 0, 21, 0, }, /* 279 */
- { 21, 23, 12, 0, 0, 21, 0, }, /* 280 */
- { 44, 12, 3, 0, 0, 44, 0, }, /* 281 */
- { 44, 10, 5, 0, 0, 44, 0, }, /* 282 */
- { 44, 7, 12, 0, 0, 44, 0, }, /* 283 */
- { 44, 10, 3, 0, 0, 44, 0, }, /* 284 */
- { 44, 13, 12, 0, 0, 44, 0, }, /* 285 */
- { 44, 26, 12, 0, 0, 44, 0, }, /* 286 */
- { 44, 15, 12, 0, 0, 44, 0, }, /* 287 */
- { 54, 12, 3, 0, 0, 54, 0, }, /* 288 */
- { 54, 7, 12, 0, 0, 54, 0, }, /* 289 */
- { 54, 10, 3, 0, 0, 54, 0, }, /* 290 */
- { 54, 10, 5, 0, 0, 54, 0, }, /* 291 */
- { 54, 13, 12, 0, 0, -49, 0, }, /* 292 */
- { 54, 15, 12, 0, 0, -49, 0, }, /* 293 */
- { 54, 26, 12, 0, 0, -49, 0, }, /* 294 */
- { 54, 26, 12, 0, 0, 54, 0, }, /* 295 */
- { 54, 23, 12, 0, 0, 54, 0, }, /* 296 */
- { 55, 12, 3, 0, 0, 55, 0, }, /* 297 */
- { 55, 10, 5, 0, 0, 55, 0, }, /* 298 */
- { 55, 7, 12, 0, 0, 55, 0, }, /* 299 */
- { 55, 13, 12, 0, 0, 55, 0, }, /* 300 */
- { 55, 15, 12, 0, 0, 55, 0, }, /* 301 */
- { 55, 26, 12, 0, 0, 55, 0, }, /* 302 */
- { 29, 7, 12, 0, 0, 29, 0, }, /* 303 */
- { 29, 12, 3, 0, 0, 29, 0, }, /* 304 */
- { 29, 10, 5, 0, 0, 29, 0, }, /* 305 */
- { 29, 21, 12, 0, 0, 29, 0, }, /* 306 */
- { 29, 10, 3, 0, 0, 29, 0, }, /* 307 */
- { 29, 13, 12, 0, 0, 29, 0, }, /* 308 */
- { 37, 12, 3, 0, 0, 37, 0, }, /* 309 */
- { 37, 10, 5, 0, 0, 37, 0, }, /* 310 */
- { 37, 7, 12, 0, 0, 37, 0, }, /* 311 */
- { 37, 10, 3, 0, 0, 37, 0, }, /* 312 */
- { 37, 7, 4, 0, 0, 37, 0, }, /* 313 */
- { 37, 26, 12, 0, 0, 37, 0, }, /* 314 */
- { 37, 15, 12, 0, 0, 37, 0, }, /* 315 */
- { 37, 13, 12, 0, 0, 37, 0, }, /* 316 */
- { 48, 10, 5, 0, 0, 48, 0, }, /* 317 */
- { 48, 7, 12, 0, 0, 48, 0, }, /* 318 */
- { 48, 12, 3, 0, 0, 48, 0, }, /* 319 */
- { 48, 10, 3, 0, 0, 48, 0, }, /* 320 */
- { 48, 13, 12, 0, 0, 48, 0, }, /* 321 */
- { 48, 21, 12, 0, 0, 48, 0, }, /* 322 */
- { 57, 7, 12, 0, 0, 57, 0, }, /* 323 */
- { 57, 12, 3, 0, 0, 57, 0, }, /* 324 */
- { 57, 7, 5, 0, 0, 57, 0, }, /* 325 */
- { 57, 6, 12, 0, 0, 57, 0, }, /* 326 */
- { 57, 21, 12, 0, 0, 57, 0, }, /* 327 */
- { 57, 13, 12, 0, 0, 57, 0, }, /* 328 */
- { 33, 7, 12, 0, 0, 33, 0, }, /* 329 */
- { 33, 12, 3, 0, 0, 33, 0, }, /* 330 */
- { 33, 7, 5, 0, 0, 33, 0, }, /* 331 */
- { 33, 6, 12, 0, 0, 33, 0, }, /* 332 */
- { 33, 13, 12, 0, 0, 33, 0, }, /* 333 */
- { 58, 7, 12, 0, 0, 58, 0, }, /* 334 */
- { 58, 26, 12, 0, 0, 58, 0, }, /* 335 */
- { 58, 21, 12, 0, 0, 58, 0, }, /* 336 */
- { 58, 12, 3, 0, 0, 58, 0, }, /* 337 */
- { 58, 13, 12, 0, 0, 58, 0, }, /* 338 */
- { 58, 15, 12, 0, 0, 58, 0, }, /* 339 */
- { 58, 22, 12, 0, 0, 58, 0, }, /* 340 */
- { 58, 18, 12, 0, 0, 58, 0, }, /* 341 */
- { 58, 10, 5, 0, 0, 58, 0, }, /* 342 */
- { 39, 7, 12, 0, 0, 39, 0, }, /* 343 */
- { 39, 10, 12, 0, 0, 39, 0, }, /* 344 */
- { 39, 12, 3, 0, 0, 39, 0, }, /* 345 */
- { 39, 10, 5, 0, 0, 39, 0, }, /* 346 */
- { 39, 13, 12, 0, 0, -72, 0, }, /* 347 */
- { 39, 21, 12, 0, 0, 39, 0, }, /* 348 */
- { 39, 13, 12, 0, 0, 39, 0, }, /* 349 */
- { 39, 26, 12, 0, 0, 39, 0, }, /* 350 */
- { 17, 9, 12, 0, 7264, 17, 0, }, /* 351 */
- { 17, 5, 12, 0, 3008, 17, 0, }, /* 352 */
- { 10, 21, 12, 0, 0, -46, 0, }, /* 353 */
- { 17, 6, 12, 0, 0, 17, 0, }, /* 354 */
- { 24, 7, 6, 0, 0, 24, 0, }, /* 355 */
- { 24, 7, 7, 0, 0, 24, 0, }, /* 356 */
- { 24, 7, 8, 0, 0, 24, 0, }, /* 357 */
- { 16, 7, 12, 0, 0, 16, 0, }, /* 358 */
- { 16, 12, 3, 0, 0, 16, 0, }, /* 359 */
- { 16, 21, 12, 0, 0, 16, 0, }, /* 360 */
- { 16, 15, 12, 0, 0, 16, 0, }, /* 361 */
- { 16, 26, 12, 0, 0, 16, 0, }, /* 362 */
- { 9, 9, 12, 0, 38864, 9, 0, }, /* 363 */
- { 9, 9, 12, 0, 8, 9, 0, }, /* 364 */
- { 9, 5, 12, 0, -8, 9, 0, }, /* 365 */
- { 8, 17, 12, 0, 0, 8, 0, }, /* 366 */
- { 8, 7, 12, 0, 0, 8, 0, }, /* 367 */
- { 8, 21, 12, 0, 0, 8, 0, }, /* 368 */
- { 41, 29, 12, 0, 0, 41, 0, }, /* 369 */
- { 41, 7, 12, 0, 0, 41, 0, }, /* 370 */
- { 41, 22, 12, 0, 0, 41, 0, }, /* 371 */
- { 41, 18, 12, 0, 0, 41, 0, }, /* 372 */
- { 46, 7, 12, 0, 0, 46, 0, }, /* 373 */
- { 46, 14, 12, 0, 0, 46, 0, }, /* 374 */
- { 51, 7, 12, 0, 0, 51, 0, }, /* 375 */
- { 51, 12, 3, 0, 0, 51, 0, }, /* 376 */
- { 25, 7, 12, 0, 0, 25, 0, }, /* 377 */
- { 25, 12, 3, 0, 0, 25, 0, }, /* 378 */
- { 10, 21, 12, 0, 0, -106, 0, }, /* 379 */
- { 7, 7, 12, 0, 0, 7, 0, }, /* 380 */
- { 7, 12, 3, 0, 0, 7, 0, }, /* 381 */
- { 52, 7, 12, 0, 0, 52, 0, }, /* 382 */
- { 52, 12, 3, 0, 0, 52, 0, }, /* 383 */
- { 32, 7, 12, 0, 0, 32, 0, }, /* 384 */
- { 32, 12, 3, 0, 0, 32, 0, }, /* 385 */
- { 32, 10, 5, 0, 0, 32, 0, }, /* 386 */
- { 32, 21, 12, 0, 0, 32, 0, }, /* 387 */
- { 32, 6, 12, 0, 0, 32, 0, }, /* 388 */
- { 32, 23, 12, 0, 0, 32, 0, }, /* 389 */
- { 32, 13, 12, 0, 0, 32, 0, }, /* 390 */
- { 32, 15, 12, 0, 0, 32, 0, }, /* 391 */
- { 38, 21, 12, 0, 0, 38, 0, }, /* 392 */
- { 10, 21, 12, 0, 0, -61, 0, }, /* 393 */
- { 38, 17, 12, 0, 0, 38, 0, }, /* 394 */
- { 38, 12, 3, 0, 0, 38, 0, }, /* 395 */
- { 38, 1, 2, 0, 0, 38, 0, }, /* 396 */
- { 38, 13, 12, 0, 0, 38, 0, }, /* 397 */
- { 38, 7, 12, 0, 0, 38, 0, }, /* 398 */
- { 38, 6, 12, 0, 0, 38, 0, }, /* 399 */
- { 35, 7, 12, 0, 0, 35, 0, }, /* 400 */
- { 35, 12, 3, 0, 0, 35, 0, }, /* 401 */
- { 35, 10, 5, 0, 0, 35, 0, }, /* 402 */
- { 35, 26, 12, 0, 0, 35, 0, }, /* 403 */
- { 35, 21, 12, 0, 0, 35, 0, }, /* 404 */
- { 35, 13, 12, 0, 0, 35, 0, }, /* 405 */
- { 53, 7, 12, 0, 0, 53, 0, }, /* 406 */
- { 40, 7, 12, 0, 0, 40, 0, }, /* 407 */
- { 40, 13, 12, 0, 0, 40, 0, }, /* 408 */
- { 40, 15, 12, 0, 0, 40, 0, }, /* 409 */
- { 40, 26, 12, 0, 0, 40, 0, }, /* 410 */
- { 32, 26, 12, 0, 0, 32, 0, }, /* 411 */
- { 6, 7, 12, 0, 0, 6, 0, }, /* 412 */
- { 6, 12, 3, 0, 0, 6, 0, }, /* 413 */
- { 6, 10, 5, 0, 0, 6, 0, }, /* 414 */
- { 6, 21, 12, 0, 0, 6, 0, }, /* 415 */
- { 91, 7, 12, 0, 0, 91, 0, }, /* 416 */
- { 91, 10, 5, 0, 0, 91, 0, }, /* 417 */
- { 91, 12, 3, 0, 0, 91, 0, }, /* 418 */
- { 91, 10, 12, 0, 0, 91, 0, }, /* 419 */
- { 91, 13, 12, 0, 0, 91, 0, }, /* 420 */
- { 91, 21, 12, 0, 0, 91, 0, }, /* 421 */
- { 91, 6, 12, 0, 0, 91, 0, }, /* 422 */
- { 28, 11, 3, 0, 0, 28, 0, }, /* 423 */
- { 62, 12, 3, 0, 0, 62, 0, }, /* 424 */
- { 62, 10, 5, 0, 0, 62, 0, }, /* 425 */
- { 62, 7, 12, 0, 0, 62, 0, }, /* 426 */
- { 62, 13, 12, 0, 0, 62, 0, }, /* 427 */
- { 62, 21, 12, 0, 0, 62, 0, }, /* 428 */
- { 62, 26, 12, 0, 0, 62, 0, }, /* 429 */
- { 76, 12, 3, 0, 0, 76, 0, }, /* 430 */
- { 76, 10, 5, 0, 0, 76, 0, }, /* 431 */
- { 76, 7, 12, 0, 0, 76, 0, }, /* 432 */
- { 76, 13, 12, 0, 0, 76, 0, }, /* 433 */
- { 93, 7, 12, 0, 0, 93, 0, }, /* 434 */
- { 93, 12, 3, 0, 0, 93, 0, }, /* 435 */
- { 93, 10, 5, 0, 0, 93, 0, }, /* 436 */
- { 93, 21, 12, 0, 0, 93, 0, }, /* 437 */
- { 70, 7, 12, 0, 0, 70, 0, }, /* 438 */
- { 70, 10, 5, 0, 0, 70, 0, }, /* 439 */
- { 70, 12, 3, 0, 0, 70, 0, }, /* 440 */
- { 70, 21, 12, 0, 0, 70, 0, }, /* 441 */
- { 70, 13, 12, 0, 0, 70, 0, }, /* 442 */
- { 73, 13, 12, 0, 0, 73, 0, }, /* 443 */
- { 73, 7, 12, 0, 0, 73, 0, }, /* 444 */
- { 73, 6, 12, 0, 0, 73, 0, }, /* 445 */
- { 73, 21, 12, 0, 0, 73, 0, }, /* 446 */
- { 13, 5, 12, 63, -6222, 13, 0, }, /* 447 */
- { 13, 5, 12, 67, -6221, 13, 0, }, /* 448 */
- { 13, 5, 12, 71, -6212, 13, 0, }, /* 449 */
- { 13, 5, 12, 75, -6210, 13, 0, }, /* 450 */
- { 13, 5, 12, 79, -6210, 13, 0, }, /* 451 */
- { 13, 5, 12, 79, -6211, 13, 0, }, /* 452 */
- { 13, 5, 12, 84, -6204, 13, 0, }, /* 453 */
- { 13, 5, 12, 88, -6180, 13, 0, }, /* 454 */
- { 13, 5, 12, 108, 35267, 13, 0, }, /* 455 */
- { 17, 9, 12, 0, -3008, 17, 0, }, /* 456 */
- { 76, 21, 12, 0, 0, 76, 0, }, /* 457 */
- { 28, 12, 3, 0, 0, -101, 0, }, /* 458 */
- { 28, 12, 3, 0, 0, 15, 0, }, /* 459 */
- { 10, 21, 12, 0, 0, -37, 0, }, /* 460 */
- { 28, 12, 3, 0, 0, -16, 0, }, /* 461 */
- { 28, 12, 3, 0, 0, -40, 0, }, /* 462 */
- { 28, 12, 3, 0, 0, -129, 0, }, /* 463 */
- { 10, 10, 5, 0, 0, -16, 0, }, /* 464 */
- { 10, 7, 12, 0, 0, 15, 0, }, /* 465 */
- { 10, 7, 12, 0, 0, -16, 0, }, /* 466 */
- { 10, 10, 5, 0, 0, -37, 0, }, /* 467 */
- { 28, 12, 3, 0, 0, -80, 0, }, /* 468 */
- { 10, 10, 5, 0, 0, 3, 0, }, /* 469 */
- { 28, 12, 3, 0, 0, -37, 0, }, /* 470 */
- { 13, 5, 12, 0, 0, 13, 0, }, /* 471 */
- { 13, 6, 12, 0, 0, 13, 0, }, /* 472 */
- { 34, 5, 12, 0, 35332, 34, 0, }, /* 473 */
- { 34, 5, 12, 0, 3814, 34, 0, }, /* 474 */
- { 34, 9, 12, 92, 1, 34, 0, }, /* 475 */
- { 34, 5, 12, 92, -1, 34, 0, }, /* 476 */
- { 34, 5, 12, 92, -58, 34, 0, }, /* 477 */
- { 34, 9, 12, 0, -7615, 34, 0, }, /* 478 */
- { 20, 5, 12, 0, 8, 20, 0, }, /* 479 */
- { 20, 9, 12, 0, -8, 20, 0, }, /* 480 */
- { 20, 5, 12, 0, 74, 20, 0, }, /* 481 */
- { 20, 5, 12, 0, 86, 20, 0, }, /* 482 */
- { 20, 5, 12, 0, 100, 20, 0, }, /* 483 */
- { 20, 5, 12, 0, 128, 20, 0, }, /* 484 */
- { 20, 5, 12, 0, 112, 20, 0, }, /* 485 */
- { 20, 5, 12, 0, 126, 20, 0, }, /* 486 */
- { 20, 8, 12, 0, -8, 20, 0, }, /* 487 */
- { 20, 5, 12, 0, 9, 20, 0, }, /* 488 */
- { 20, 9, 12, 0, -74, 20, 0, }, /* 489 */
- { 20, 8, 12, 0, -9, 20, 0, }, /* 490 */
- { 20, 5, 12, 21, -7173, 20, 0, }, /* 491 */
- { 20, 9, 12, 0, -86, 20, 0, }, /* 492 */
- { 20, 9, 12, 0, -100, 20, 0, }, /* 493 */
- { 20, 9, 12, 0, -112, 20, 0, }, /* 494 */
- { 20, 9, 12, 0, -128, 20, 0, }, /* 495 */
- { 20, 9, 12, 0, -126, 20, 0, }, /* 496 */
- { 28, 1, 3, 0, 0, 28, 0, }, /* 497 */
- { 28, 1, 13, 0, 0, 28, 0, }, /* 498 */
- { 10, 27, 2, 0, 0, 10, 0, }, /* 499 */
- { 10, 28, 2, 0, 0, 10, 0, }, /* 500 */
- { 10, 21, 14, 0, 0, 10, 0, }, /* 501 */
- { 0, 2, 2, 0, 0, 0, 0, }, /* 502 */
- { 28, 12, 3, 0, 0, -84, 0, }, /* 503 */
- { 10, 9, 12, 0, 0, 10, 0, }, /* 504 */
- { 10, 5, 12, 0, 0, 10, 0, }, /* 505 */
- { 20, 9, 12, 96, -7517, 20, 0, }, /* 506 */
- { 34, 9, 12, 100, -8383, 34, 0, }, /* 507 */
- { 34, 9, 12, 104, -8262, 34, 0, }, /* 508 */
- { 34, 9, 12, 0, 28, 34, 0, }, /* 509 */
- { 10, 7, 12, 0, 0, 10, 0, }, /* 510 */
- { 10, 5, 14, 0, 0, 10, 0, }, /* 511 */
- { 34, 5, 12, 0, -28, 34, 0, }, /* 512 */
- { 34, 14, 12, 0, 16, 34, 0, }, /* 513 */
- { 34, 14, 12, 0, -16, 34, 0, }, /* 514 */
- { 34, 14, 12, 0, 0, 34, 0, }, /* 515 */
- { 10, 25, 14, 0, 0, 10, 0, }, /* 516 */
- { 10, 26, 12, 0, 26, 10, 0, }, /* 517 */
- { 10, 26, 14, 0, 26, 10, 0, }, /* 518 */
- { 10, 26, 12, 0, -26, 10, 0, }, /* 519 */
- { 5, 26, 12, 0, 0, 5, 0, }, /* 520 */
- { 18, 9, 12, 0, 48, 18, 0, }, /* 521 */
- { 18, 5, 12, 0, -48, 18, 0, }, /* 522 */
- { 34, 9, 12, 0, -10743, 34, 0, }, /* 523 */
- { 34, 9, 12, 0, -3814, 34, 0, }, /* 524 */
- { 34, 9, 12, 0, -10727, 34, 0, }, /* 525 */
- { 34, 5, 12, 0, -10795, 34, 0, }, /* 526 */
- { 34, 5, 12, 0, -10792, 34, 0, }, /* 527 */
- { 34, 9, 12, 0, -10780, 34, 0, }, /* 528 */
- { 34, 9, 12, 0, -10749, 34, 0, }, /* 529 */
- { 34, 9, 12, 0, -10783, 34, 0, }, /* 530 */
- { 34, 9, 12, 0, -10782, 34, 0, }, /* 531 */
- { 34, 9, 12, 0, -10815, 34, 0, }, /* 532 */
- { 11, 5, 12, 0, 0, 11, 0, }, /* 533 */
- { 11, 26, 12, 0, 0, 11, 0, }, /* 534 */
- { 11, 12, 3, 0, 0, 11, 0, }, /* 535 */
- { 11, 21, 12, 0, 0, 11, 0, }, /* 536 */
- { 11, 15, 12, 0, 0, 11, 0, }, /* 537 */
- { 17, 5, 12, 0, -7264, 17, 0, }, /* 538 */
- { 59, 7, 12, 0, 0, 59, 0, }, /* 539 */
- { 59, 6, 12, 0, 0, 59, 0, }, /* 540 */
- { 59, 21, 12, 0, 0, 59, 0, }, /* 541 */
- { 59, 12, 3, 0, 0, 59, 0, }, /* 542 */
- { 13, 12, 3, 0, 0, 13, 0, }, /* 543 */
- { 10, 21, 12, 0, 0, -28, 0, }, /* 544 */
- { 23, 26, 12, 0, 0, 23, 0, }, /* 545 */
- { 10, 21, 12, 0, 0, -122, 0, }, /* 546 */
- { 10, 21, 12, 0, 0, -116, 0, }, /* 547 */
- { 23, 6, 12, 0, 0, 23, 0, }, /* 548 */
- { 10, 7, 12, 0, 0, 23, 0, }, /* 549 */
- { 23, 14, 12, 0, 0, 23, 0, }, /* 550 */
- { 10, 22, 12, 0, 0, -122, 0, }, /* 551 */
- { 10, 18, 12, 0, 0, -122, 0, }, /* 552 */
- { 10, 26, 12, 0, 0, -116, 0, }, /* 553 */
- { 10, 17, 12, 0, 0, -116, 0, }, /* 554 */
- { 10, 22, 12, 0, 0, -116, 0, }, /* 555 */
- { 10, 18, 12, 0, 0, -116, 0, }, /* 556 */
- { 28, 12, 3, 0, 0, -19, 0, }, /* 557 */
- { 24, 10, 3, 0, 0, 24, 0, }, /* 558 */
- { 10, 17, 14, 0, 0, -116, 0, }, /* 559 */
- { 10, 6, 12, 0, 0, -58, 0, }, /* 560 */
- { 10, 7, 12, 0, 0, -88, 0, }, /* 561 */
- { 10, 21, 14, 0, 0, -88, 0, }, /* 562 */
- { 10, 26, 12, 0, 0, 23, 0, }, /* 563 */
- { 27, 7, 12, 0, 0, 27, 0, }, /* 564 */
- { 28, 12, 3, 0, 0, -58, 0, }, /* 565 */
- { 10, 24, 12, 0, 0, -58, 0, }, /* 566 */
- { 27, 6, 12, 0, 0, 27, 0, }, /* 567 */
- { 10, 17, 12, 0, 0, -58, 0, }, /* 568 */
- { 30, 7, 12, 0, 0, 30, 0, }, /* 569 */
- { 30, 6, 12, 0, 0, 30, 0, }, /* 570 */
- { 4, 7, 12, 0, 0, 4, 0, }, /* 571 */
- { 24, 7, 12, 0, 0, 24, 0, }, /* 572 */
- { 10, 15, 12, 0, 0, 23, 0, }, /* 573 */
- { 24, 26, 12, 0, 0, 24, 0, }, /* 574 */
- { 10, 26, 14, 0, 0, 23, 0, }, /* 575 */
- { 30, 26, 12, 0, 0, 30, 0, }, /* 576 */
- { 23, 7, 12, 0, 0, 23, 0, }, /* 577 */
- { 61, 7, 12, 0, 0, 61, 0, }, /* 578 */
- { 61, 6, 12, 0, 0, 61, 0, }, /* 579 */
- { 61, 26, 12, 0, 0, 61, 0, }, /* 580 */
- { 86, 7, 12, 0, 0, 86, 0, }, /* 581 */
- { 86, 6, 12, 0, 0, 86, 0, }, /* 582 */
- { 86, 21, 12, 0, 0, 86, 0, }, /* 583 */
- { 77, 7, 12, 0, 0, 77, 0, }, /* 584 */
- { 77, 6, 12, 0, 0, 77, 0, }, /* 585 */
- { 77, 21, 12, 0, 0, 77, 0, }, /* 586 */
- { 77, 13, 12, 0, 0, 77, 0, }, /* 587 */
- { 13, 9, 12, 108, 1, 13, 0, }, /* 588 */
- { 13, 5, 12, 108, -35267, 13, 0, }, /* 589 */
- { 13, 7, 12, 0, 0, 13, 0, }, /* 590 */
- { 13, 21, 12, 0, 0, 13, 0, }, /* 591 */
- { 79, 7, 12, 0, 0, 79, 0, }, /* 592 */
- { 79, 14, 12, 0, 0, 79, 0, }, /* 593 */
- { 79, 12, 3, 0, 0, 79, 0, }, /* 594 */
- { 79, 21, 12, 0, 0, 79, 0, }, /* 595 */
- { 34, 9, 12, 0, -35332, 34, 0, }, /* 596 */
- { 34, 9, 12, 0, -42280, 34, 0, }, /* 597 */
- { 34, 9, 12, 0, -42308, 34, 0, }, /* 598 */
- { 34, 9, 12, 0, -42319, 34, 0, }, /* 599 */
- { 34, 9, 12, 0, -42315, 34, 0, }, /* 600 */
- { 34, 9, 12, 0, -42305, 34, 0, }, /* 601 */
- { 34, 9, 12, 0, -42258, 34, 0, }, /* 602 */
- { 34, 9, 12, 0, -42282, 34, 0, }, /* 603 */
- { 34, 9, 12, 0, -42261, 34, 0, }, /* 604 */
- { 34, 9, 12, 0, 928, 34, 0, }, /* 605 */
- { 49, 7, 12, 0, 0, 49, 0, }, /* 606 */
- { 49, 12, 3, 0, 0, 49, 0, }, /* 607 */
- { 49, 10, 5, 0, 0, 49, 0, }, /* 608 */
- { 49, 26, 12, 0, 0, 49, 0, }, /* 609 */
- { 10, 15, 12, 0, 0, -197, 0, }, /* 610 */
- { 10, 15, 12, 0, 0, -170, 0, }, /* 611 */
- { 10, 26, 12, 0, 0, -145, 0, }, /* 612 */
- { 10, 23, 12, 0, 0, -145, 0, }, /* 613 */
- { 65, 7, 12, 0, 0, 65, 0, }, /* 614 */
- { 65, 21, 12, 0, 0, 65, 0, }, /* 615 */
- { 75, 10, 5, 0, 0, 75, 0, }, /* 616 */
- { 75, 7, 12, 0, 0, 75, 0, }, /* 617 */
- { 75, 12, 3, 0, 0, 75, 0, }, /* 618 */
- { 75, 21, 12, 0, 0, 75, 0, }, /* 619 */
- { 75, 13, 12, 0, 0, 75, 0, }, /* 620 */
- { 15, 12, 3, 0, 0, -16, 0, }, /* 621 */
- { 15, 7, 12, 0, 0, -43, 0, }, /* 622 */
- { 69, 13, 12, 0, 0, 69, 0, }, /* 623 */
- { 69, 7, 12, 0, 0, 69, 0, }, /* 624 */
- { 69, 12, 3, 0, 0, 69, 0, }, /* 625 */
- { 10, 21, 12, 0, 0, -92, 0, }, /* 626 */
- { 69, 21, 12, 0, 0, 69, 0, }, /* 627 */
- { 74, 7, 12, 0, 0, 74, 0, }, /* 628 */
- { 74, 12, 3, 0, 0, 74, 0, }, /* 629 */
- { 74, 10, 5, 0, 0, 74, 0, }, /* 630 */
- { 74, 21, 12, 0, 0, 74, 0, }, /* 631 */
- { 84, 12, 3, 0, 0, 84, 0, }, /* 632 */
- { 84, 10, 5, 0, 0, 84, 0, }, /* 633 */
- { 84, 7, 12, 0, 0, 84, 0, }, /* 634 */
- { 84, 21, 12, 0, 0, 84, 0, }, /* 635 */
- { 10, 6, 12, 0, 0, -22, 0, }, /* 636 */
- { 84, 13, 12, 0, 0, 84, 0, }, /* 637 */
- { 39, 6, 12, 0, 0, 39, 0, }, /* 638 */
- { 68, 7, 12, 0, 0, 68, 0, }, /* 639 */
- { 68, 12, 3, 0, 0, 68, 0, }, /* 640 */
- { 68, 10, 5, 0, 0, 68, 0, }, /* 641 */
- { 68, 13, 12, 0, 0, 68, 0, }, /* 642 */
- { 68, 21, 12, 0, 0, 68, 0, }, /* 643 */
- { 92, 7, 12, 0, 0, 92, 0, }, /* 644 */
- { 92, 12, 3, 0, 0, 92, 0, }, /* 645 */
- { 92, 6, 12, 0, 0, 92, 0, }, /* 646 */
- { 92, 21, 12, 0, 0, 92, 0, }, /* 647 */
- { 87, 7, 12, 0, 0, 87, 0, }, /* 648 */
- { 87, 10, 5, 0, 0, 87, 0, }, /* 649 */
- { 87, 12, 3, 0, 0, 87, 0, }, /* 650 */
- { 87, 21, 12, 0, 0, 87, 0, }, /* 651 */
- { 87, 6, 12, 0, 0, 87, 0, }, /* 652 */
- { 34, 5, 12, 0, -928, 34, 0, }, /* 653 */
- { 9, 5, 12, 0, -38864, 9, 0, }, /* 654 */
- { 87, 13, 12, 0, 0, 87, 0, }, /* 655 */
- { 24, 7, 9, 0, 0, 24, 0, }, /* 656 */
- { 24, 7, 10, 0, 0, 24, 0, }, /* 657 */
- { 0, 4, 2, 0, 0, 0, 0, }, /* 658 */
- { 0, 3, 12, 0, 0, 0, 0, }, /* 659 */
- { 26, 25, 12, 0, 0, 26, 0, }, /* 660 */
- { 1, 24, 12, 0, 0, 1, 0, }, /* 661 */
- { 1, 7, 12, 0, 0, -10, 0, }, /* 662 */
- { 1, 26, 12, 0, 0, -10, 0, }, /* 663 */
- { 10, 6, 3, 0, 0, -58, 0, }, /* 664 */
- { 36, 7, 12, 0, 0, 36, 0, }, /* 665 */
- { 10, 21, 12, 0, 0, -25, 0, }, /* 666 */
- { 10, 15, 12, 0, 0, -76, 0, }, /* 667 */
- { 10, 26, 12, 0, 0, -25, 0, }, /* 668 */
- { 20, 14, 12, 0, 0, 20, 0, }, /* 669 */
- { 20, 15, 12, 0, 0, 20, 0, }, /* 670 */
- { 20, 26, 12, 0, 0, 20, 0, }, /* 671 */
- { 71, 7, 12, 0, 0, 71, 0, }, /* 672 */
- { 67, 7, 12, 0, 0, 67, 0, }, /* 673 */
- { 28, 12, 3, 0, 0, -1, 0, }, /* 674 */
- { 10, 15, 12, 0, 0, -1, 0, }, /* 675 */
- { 42, 7, 12, 0, 0, 42, 0, }, /* 676 */
- { 42, 15, 12, 0, 0, 42, 0, }, /* 677 */
- { 19, 7, 12, 0, 0, 19, 0, }, /* 678 */
- { 19, 14, 12, 0, 0, 19, 0, }, /* 679 */
- { 118, 7, 12, 0, 0, 118, 0, }, /* 680 */
- { 118, 12, 3, 0, 0, 118, 0, }, /* 681 */
- { 60, 7, 12, 0, 0, 60, 0, }, /* 682 */
- { 60, 21, 12, 0, 0, 60, 0, }, /* 683 */
- { 43, 7, 12, 0, 0, 43, 0, }, /* 684 */
- { 43, 21, 12, 0, 0, 43, 0, }, /* 685 */
- { 43, 14, 12, 0, 0, 43, 0, }, /* 686 */
- { 14, 9, 12, 0, 40, 14, 0, }, /* 687 */
- { 14, 5, 12, 0, -40, 14, 0, }, /* 688 */
- { 47, 7, 12, 0, 0, 47, 0, }, /* 689 */
- { 45, 7, 12, 0, 0, 45, 0, }, /* 690 */
- { 45, 13, 12, 0, 0, 45, 0, }, /* 691 */
- { 136, 9, 12, 0, 40, 136, 0, }, /* 692 */
- { 136, 5, 12, 0, -40, 136, 0, }, /* 693 */
- { 106, 7, 12, 0, 0, 106, 0, }, /* 694 */
- { 104, 7, 12, 0, 0, 104, 0, }, /* 695 */
- { 104, 21, 12, 0, 0, 104, 0, }, /* 696 */
- { 110, 7, 12, 0, 0, 110, 0, }, /* 697 */
- { 12, 7, 12, 0, 0, 12, 0, }, /* 698 */
- { 81, 7, 12, 0, 0, 81, 0, }, /* 699 */
- { 81, 21, 12, 0, 0, 81, 0, }, /* 700 */
- { 81, 15, 12, 0, 0, 81, 0, }, /* 701 */
- { 120, 7, 12, 0, 0, 120, 0, }, /* 702 */
- { 120, 26, 12, 0, 0, 120, 0, }, /* 703 */
- { 120, 15, 12, 0, 0, 120, 0, }, /* 704 */
- { 116, 7, 12, 0, 0, 116, 0, }, /* 705 */
- { 116, 15, 12, 0, 0, 116, 0, }, /* 706 */
- { 128, 7, 12, 0, 0, 128, 0, }, /* 707 */
- { 128, 15, 12, 0, 0, 128, 0, }, /* 708 */
- { 66, 7, 12, 0, 0, 66, 0, }, /* 709 */
- { 66, 15, 12, 0, 0, 66, 0, }, /* 710 */
- { 66, 21, 12, 0, 0, 66, 0, }, /* 711 */
- { 72, 7, 12, 0, 0, 72, 0, }, /* 712 */
- { 72, 21, 12, 0, 0, 72, 0, }, /* 713 */
- { 98, 7, 12, 0, 0, 98, 0, }, /* 714 */
- { 97, 7, 12, 0, 0, 97, 0, }, /* 715 */
- { 97, 15, 12, 0, 0, 97, 0, }, /* 716 */
- { 31, 7, 12, 0, 0, 31, 0, }, /* 717 */
- { 31, 12, 3, 0, 0, 31, 0, }, /* 718 */
- { 31, 15, 12, 0, 0, 31, 0, }, /* 719 */
- { 31, 21, 12, 0, 0, 31, 0, }, /* 720 */
- { 88, 7, 12, 0, 0, 88, 0, }, /* 721 */
- { 88, 15, 12, 0, 0, 88, 0, }, /* 722 */
- { 88, 21, 12, 0, 0, 88, 0, }, /* 723 */
- { 117, 7, 12, 0, 0, 117, 0, }, /* 724 */
- { 117, 15, 12, 0, 0, 117, 0, }, /* 725 */
- { 112, 7, 12, 0, 0, 112, 0, }, /* 726 */
- { 112, 26, 12, 0, 0, 112, 0, }, /* 727 */
- { 112, 12, 3, 0, 0, 112, 0, }, /* 728 */
- { 112, 15, 12, 0, 0, 112, 0, }, /* 729 */
- { 112, 21, 12, 0, 0, 112, 0, }, /* 730 */
- { 78, 7, 12, 0, 0, 78, 0, }, /* 731 */
- { 78, 21, 12, 0, 0, 78, 0, }, /* 732 */
- { 83, 7, 12, 0, 0, 83, 0, }, /* 733 */
- { 83, 15, 12, 0, 0, 83, 0, }, /* 734 */
- { 82, 7, 12, 0, 0, 82, 0, }, /* 735 */
- { 82, 15, 12, 0, 0, 82, 0, }, /* 736 */
- { 121, 7, 12, 0, 0, 121, 0, }, /* 737 */
- { 121, 21, 12, 0, 0, 121, 0, }, /* 738 */
- { 121, 15, 12, 0, 0, 121, 0, }, /* 739 */
- { 89, 7, 12, 0, 0, 89, 0, }, /* 740 */
- { 130, 9, 12, 0, 64, 130, 0, }, /* 741 */
- { 130, 5, 12, 0, -64, 130, 0, }, /* 742 */
- { 130, 15, 12, 0, 0, 130, 0, }, /* 743 */
- { 144, 7, 12, 0, 0, 144, 0, }, /* 744 */
- { 144, 12, 3, 0, 0, 144, 0, }, /* 745 */
- { 144, 13, 12, 0, 0, 144, 0, }, /* 746 */
- { 1, 15, 12, 0, 0, 1, 0, }, /* 747 */
- { 147, 7, 12, 0, 0, 147, 0, }, /* 748 */
- { 147, 15, 12, 0, 0, 147, 0, }, /* 749 */
- { 148, 7, 12, 0, 0, 148, 0, }, /* 750 */
- { 148, 12, 3, 0, 0, 148, 0, }, /* 751 */
- { 148, 15, 12, 0, 0, 148, 0, }, /* 752 */
- { 148, 21, 12, 0, 0, 148, 0, }, /* 753 */
- { 94, 10, 5, 0, 0, 94, 0, }, /* 754 */
- { 94, 12, 3, 0, 0, 94, 0, }, /* 755 */
- { 94, 7, 12, 0, 0, 94, 0, }, /* 756 */
- { 94, 21, 12, 0, 0, 94, 0, }, /* 757 */
- { 94, 15, 12, 0, 0, 94, 0, }, /* 758 */
- { 94, 13, 12, 0, 0, 94, 0, }, /* 759 */
- { 85, 12, 3, 0, 0, 85, 0, }, /* 760 */
- { 85, 10, 5, 0, 0, 85, 0, }, /* 761 */
- { 85, 7, 12, 0, 0, 85, 0, }, /* 762 */
- { 85, 21, 12, 0, 0, 85, 0, }, /* 763 */
- { 85, 1, 4, 0, 0, 85, 0, }, /* 764 */
- { 101, 7, 12, 0, 0, 101, 0, }, /* 765 */
- { 101, 13, 12, 0, 0, 101, 0, }, /* 766 */
- { 96, 12, 3, 0, 0, 96, 0, }, /* 767 */
- { 96, 7, 12, 0, 0, 96, 0, }, /* 768 */
- { 96, 10, 5, 0, 0, 96, 0, }, /* 769 */
- { 96, 13, 12, 0, 0, 96, 0, }, /* 770 */
- { 96, 21, 12, 0, 0, 96, 0, }, /* 771 */
- { 111, 7, 12, 0, 0, 111, 0, }, /* 772 */
- { 111, 12, 3, 0, 0, 111, 0, }, /* 773 */
- { 111, 21, 12, 0, 0, 111, 0, }, /* 774 */
- { 100, 12, 3, 0, 0, 100, 0, }, /* 775 */
- { 100, 10, 5, 0, 0, 100, 0, }, /* 776 */
- { 100, 7, 12, 0, 0, 100, 0, }, /* 777 */
- { 100, 7, 4, 0, 0, 100, 0, }, /* 778 */
- { 100, 21, 12, 0, 0, 100, 0, }, /* 779 */
- { 100, 13, 12, 0, 0, 100, 0, }, /* 780 */
- { 48, 15, 12, 0, 0, 48, 0, }, /* 781 */
- { 108, 7, 12, 0, 0, 108, 0, }, /* 782 */
- { 108, 10, 5, 0, 0, 108, 0, }, /* 783 */
- { 108, 12, 3, 0, 0, 108, 0, }, /* 784 */
- { 108, 21, 12, 0, 0, 108, 0, }, /* 785 */
- { 129, 7, 12, 0, 0, 129, 0, }, /* 786 */
- { 129, 21, 12, 0, 0, 129, 0, }, /* 787 */
- { 109, 7, 12, 0, 0, 109, 0, }, /* 788 */
- { 109, 12, 3, 0, 0, 109, 0, }, /* 789 */
- { 109, 10, 5, 0, 0, 109, 0, }, /* 790 */
- { 109, 13, 12, 0, 0, 109, 0, }, /* 791 */
- { 107, 12, 3, 0, 0, 107, 0, }, /* 792 */
- { 107, 12, 3, 0, 0, -49, 0, }, /* 793 */
- { 107, 10, 5, 0, 0, 107, 0, }, /* 794 */
- { 107, 10, 5, 0, 0, -49, 0, }, /* 795 */
- { 107, 7, 12, 0, 0, 107, 0, }, /* 796 */
- { 28, 12, 3, 0, 0, -49, 0, }, /* 797 */
- { 107, 10, 3, 0, 0, 107, 0, }, /* 798 */
- { 135, 7, 12, 0, 0, 135, 0, }, /* 799 */
- { 135, 10, 5, 0, 0, 135, 0, }, /* 800 */
- { 135, 12, 3, 0, 0, 135, 0, }, /* 801 */
- { 135, 21, 12, 0, 0, 135, 0, }, /* 802 */
- { 135, 13, 12, 0, 0, 135, 0, }, /* 803 */
- { 124, 7, 12, 0, 0, 124, 0, }, /* 804 */
- { 124, 10, 3, 0, 0, 124, 0, }, /* 805 */
- { 124, 10, 5, 0, 0, 124, 0, }, /* 806 */
- { 124, 12, 3, 0, 0, 124, 0, }, /* 807 */
- { 124, 21, 12, 0, 0, 124, 0, }, /* 808 */
- { 124, 13, 12, 0, 0, 124, 0, }, /* 809 */
- { 123, 7, 12, 0, 0, 123, 0, }, /* 810 */
- { 123, 10, 3, 0, 0, 123, 0, }, /* 811 */
- { 123, 10, 5, 0, 0, 123, 0, }, /* 812 */
- { 123, 12, 3, 0, 0, 123, 0, }, /* 813 */
- { 123, 21, 12, 0, 0, 123, 0, }, /* 814 */
- { 114, 7, 12, 0, 0, 114, 0, }, /* 815 */
- { 114, 10, 5, 0, 0, 114, 0, }, /* 816 */
- { 114, 12, 3, 0, 0, 114, 0, }, /* 817 */
- { 114, 21, 12, 0, 0, 114, 0, }, /* 818 */
- { 114, 13, 12, 0, 0, 114, 0, }, /* 819 */
- { 102, 7, 12, 0, 0, 102, 0, }, /* 820 */
- { 102, 12, 3, 0, 0, 102, 0, }, /* 821 */
- { 102, 10, 5, 0, 0, 102, 0, }, /* 822 */
- { 102, 13, 12, 0, 0, 102, 0, }, /* 823 */
- { 126, 7, 12, 0, 0, 126, 0, }, /* 824 */
- { 126, 12, 3, 0, 0, 126, 0, }, /* 825 */
- { 126, 10, 5, 0, 0, 126, 0, }, /* 826 */
- { 126, 13, 12, 0, 0, 126, 0, }, /* 827 */
- { 126, 15, 12, 0, 0, 126, 0, }, /* 828 */
- { 126, 21, 12, 0, 0, 126, 0, }, /* 829 */
- { 126, 26, 12, 0, 0, 126, 0, }, /* 830 */
- { 142, 7, 12, 0, 0, 142, 0, }, /* 831 */
- { 142, 10, 5, 0, 0, 142, 0, }, /* 832 */
- { 142, 12, 3, 0, 0, 142, 0, }, /* 833 */
- { 142, 21, 12, 0, 0, 142, 0, }, /* 834 */
- { 125, 9, 12, 0, 32, 125, 0, }, /* 835 */
- { 125, 5, 12, 0, -32, 125, 0, }, /* 836 */
- { 125, 13, 12, 0, 0, 125, 0, }, /* 837 */
- { 125, 15, 12, 0, 0, 125, 0, }, /* 838 */
- { 125, 7, 12, 0, 0, 125, 0, }, /* 839 */
- { 141, 7, 12, 0, 0, 141, 0, }, /* 840 */
- { 141, 12, 3, 0, 0, 141, 0, }, /* 841 */
- { 141, 10, 5, 0, 0, 141, 0, }, /* 842 */
- { 141, 7, 4, 0, 0, 141, 0, }, /* 843 */
- { 141, 21, 12, 0, 0, 141, 0, }, /* 844 */
- { 140, 7, 12, 0, 0, 140, 0, }, /* 845 */
- { 140, 12, 3, 0, 0, 140, 0, }, /* 846 */
- { 140, 10, 5, 0, 0, 140, 0, }, /* 847 */
- { 140, 7, 4, 0, 0, 140, 0, }, /* 848 */
- { 140, 21, 12, 0, 0, 140, 0, }, /* 849 */
- { 122, 7, 12, 0, 0, 122, 0, }, /* 850 */
- { 133, 7, 12, 0, 0, 133, 0, }, /* 851 */
- { 133, 10, 5, 0, 0, 133, 0, }, /* 852 */
- { 133, 12, 3, 0, 0, 133, 0, }, /* 853 */
- { 133, 21, 12, 0, 0, 133, 0, }, /* 854 */
- { 133, 13, 12, 0, 0, 133, 0, }, /* 855 */
- { 133, 15, 12, 0, 0, 133, 0, }, /* 856 */
- { 134, 21, 12, 0, 0, 134, 0, }, /* 857 */
- { 134, 7, 12, 0, 0, 134, 0, }, /* 858 */
- { 134, 12, 3, 0, 0, 134, 0, }, /* 859 */
- { 134, 10, 5, 0, 0, 134, 0, }, /* 860 */
- { 138, 7, 12, 0, 0, 138, 0, }, /* 861 */
- { 138, 12, 3, 0, 0, 138, 0, }, /* 862 */
- { 138, 7, 4, 0, 0, 138, 0, }, /* 863 */
- { 138, 13, 12, 0, 0, 138, 0, }, /* 864 */
- { 143, 7, 12, 0, 0, 143, 0, }, /* 865 */
- { 143, 10, 5, 0, 0, 143, 0, }, /* 866 */
- { 143, 12, 3, 0, 0, 143, 0, }, /* 867 */
- { 143, 13, 12, 0, 0, 143, 0, }, /* 868 */
- { 145, 7, 12, 0, 0, 145, 0, }, /* 869 */
- { 145, 12, 3, 0, 0, 145, 0, }, /* 870 */
- { 145, 10, 5, 0, 0, 145, 0, }, /* 871 */
- { 145, 21, 12, 0, 0, 145, 0, }, /* 872 */
- { 63, 7, 12, 0, 0, 63, 0, }, /* 873 */
- { 63, 14, 12, 0, 0, 63, 0, }, /* 874 */
- { 63, 21, 12, 0, 0, 63, 0, }, /* 875 */
- { 80, 7, 12, 0, 0, 80, 0, }, /* 876 */
- { 127, 7, 12, 0, 0, 127, 0, }, /* 877 */
- { 115, 7, 12, 0, 0, 115, 0, }, /* 878 */
- { 115, 13, 12, 0, 0, 115, 0, }, /* 879 */
- { 115, 21, 12, 0, 0, 115, 0, }, /* 880 */
- { 103, 7, 12, 0, 0, 103, 0, }, /* 881 */
- { 103, 12, 3, 0, 0, 103, 0, }, /* 882 */
- { 103, 21, 12, 0, 0, 103, 0, }, /* 883 */
- { 119, 7, 12, 0, 0, 119, 0, }, /* 884 */
- { 119, 12, 3, 0, 0, 119, 0, }, /* 885 */
- { 119, 21, 12, 0, 0, 119, 0, }, /* 886 */
- { 119, 26, 12, 0, 0, 119, 0, }, /* 887 */
- { 119, 6, 12, 0, 0, 119, 0, }, /* 888 */
- { 119, 13, 12, 0, 0, 119, 0, }, /* 889 */
- { 119, 15, 12, 0, 0, 119, 0, }, /* 890 */
- { 146, 9, 12, 0, 32, 146, 0, }, /* 891 */
- { 146, 5, 12, 0, -32, 146, 0, }, /* 892 */
- { 146, 15, 12, 0, 0, 146, 0, }, /* 893 */
- { 146, 21, 12, 0, 0, 146, 0, }, /* 894 */
- { 99, 7, 12, 0, 0, 99, 0, }, /* 895 */
- { 99, 10, 5, 0, 0, 99, 0, }, /* 896 */
- { 99, 12, 3, 0, 0, 99, 0, }, /* 897 */
- { 99, 6, 12, 0, 0, 99, 0, }, /* 898 */
- { 137, 6, 12, 0, 0, 137, 0, }, /* 899 */
- { 139, 6, 12, 0, 0, 139, 0, }, /* 900 */
- { 137, 7, 12, 0, 0, 137, 0, }, /* 901 */
- { 139, 7, 12, 0, 0, 139, 0, }, /* 902 */
- { 105, 7, 12, 0, 0, 105, 0, }, /* 903 */
- { 105, 26, 12, 0, 0, 105, 0, }, /* 904 */
- { 105, 12, 3, 0, 0, 105, 0, }, /* 905 */
- { 105, 21, 12, 0, 0, 105, 0, }, /* 906 */
- { 10, 1, 2, 0, 0, 105, 0, }, /* 907 */
- { 10, 10, 3, 0, 0, 10, 0, }, /* 908 */
- { 10, 10, 5, 0, 0, 10, 0, }, /* 909 */
- { 20, 12, 3, 0, 0, 20, 0, }, /* 910 */
- { 131, 26, 12, 0, 0, 131, 0, }, /* 911 */
- { 131, 12, 3, 0, 0, 131, 0, }, /* 912 */
- { 131, 21, 12, 0, 0, 131, 0, }, /* 913 */
- { 18, 12, 3, 0, 0, 18, 0, }, /* 914 */
- { 113, 7, 12, 0, 0, 113, 0, }, /* 915 */
- { 113, 15, 12, 0, 0, 113, 0, }, /* 916 */
- { 113, 12, 3, 0, 0, 113, 0, }, /* 917 */
- { 132, 9, 12, 0, 34, 132, 0, }, /* 918 */
- { 132, 5, 12, 0, -34, 132, 0, }, /* 919 */
- { 132, 12, 3, 0, 0, 132, 0, }, /* 920 */
- { 132, 13, 12, 0, 0, 132, 0, }, /* 921 */
- { 132, 21, 12, 0, 0, 132, 0, }, /* 922 */
- { 0, 2, 14, 0, 0, 0, 0, }, /* 923 */
- { 10, 26, 11, 0, 0, 10, 0, }, /* 924 */
- { 27, 26, 12, 0, 0, 27, 0, }, /* 925 */
- { 10, 24, 3, 0, 0, 10, 0, }, /* 926 */
- { 10, 1, 3, 0, 0, 10, 0, }, /* 927 */
+ { 34, 5, 12, 0, 42307, 34, 0, }, /* 102 */
+ { 34, 5, 12, 0, 42282, 34, 0, }, /* 103 */
+ { 34, 5, 12, 0, -69, 34, 0, }, /* 104 */
+ { 34, 5, 12, 0, -217, 34, 0, }, /* 105 */
+ { 34, 5, 12, 0, -71, 34, 0, }, /* 106 */
+ { 34, 5, 12, 0, -219, 34, 0, }, /* 107 */
+ { 34, 5, 12, 0, 42261, 34, 0, }, /* 108 */
+ { 34, 5, 12, 0, 42258, 34, 0, }, /* 109 */
+ { 34, 6, 12, 0, 0, 34, 0, }, /* 110 */
+ { 10, 6, 12, 0, 0, 10, 0, }, /* 111 */
+ { 4, 24, 12, 0, 0, 4, 0, }, /* 112 */
+ { 28, 12, 3, 0, 0, 28, 0, }, /* 113 */
+ { 28, 12, 3, 0, 0, 20, 0, }, /* 114 */
+ { 28, 12, 3, 21, 116, 20, 0, }, /* 115 */
+ { 28, 12, 3, 0, 0, 34, 0, }, /* 116 */
+ { 20, 9, 12, 0, 1, 20, 0, }, /* 117 */
+ { 20, 5, 12, 0, -1, 20, 0, }, /* 118 */
+ { 20, 24, 12, 0, 0, 20, 0, }, /* 119 */
+ { 0, 2, 12, 0, 0, 0, 0, }, /* 120 */
+ { 20, 6, 12, 0, 0, 20, 0, }, /* 121 */
+ { 20, 5, 12, 0, 130, 20, 0, }, /* 122 */
+ { 20, 9, 12, 0, 116, 20, 0, }, /* 123 */
+ { 20, 9, 12, 0, 38, 20, 0, }, /* 124 */
+ { 20, 9, 12, 0, 37, 20, 0, }, /* 125 */
+ { 20, 9, 12, 0, 64, 20, 0, }, /* 126 */
+ { 20, 9, 12, 0, 63, 20, 0, }, /* 127 */
+ { 20, 5, 12, 0, 0, 20, 0, }, /* 128 */
+ { 20, 9, 12, 0, 32, 20, 0, }, /* 129 */
+ { 20, 9, 12, 34, 32, 20, 0, }, /* 130 */
+ { 20, 9, 12, 59, 32, 20, 0, }, /* 131 */
+ { 20, 9, 12, 38, 32, 20, 0, }, /* 132 */
+ { 20, 9, 12, 21, 32, 20, 0, }, /* 133 */
+ { 20, 9, 12, 51, 32, 20, 0, }, /* 134 */
+ { 20, 9, 12, 26, 32, 20, 0, }, /* 135 */
+ { 20, 9, 12, 47, 32, 20, 0, }, /* 136 */
+ { 20, 9, 12, 55, 32, 20, 0, }, /* 137 */
+ { 20, 9, 12, 30, 32, 20, 0, }, /* 138 */
+ { 20, 9, 12, 43, 32, 20, 0, }, /* 139 */
+ { 20, 9, 12, 96, 32, 20, 0, }, /* 140 */
+ { 20, 5, 12, 0, -38, 20, 0, }, /* 141 */
+ { 20, 5, 12, 0, -37, 20, 0, }, /* 142 */
+ { 20, 5, 12, 0, -32, 20, 0, }, /* 143 */
+ { 20, 5, 12, 34, -32, 20, 0, }, /* 144 */
+ { 20, 5, 12, 59, -32, 20, 0, }, /* 145 */
+ { 20, 5, 12, 38, -32, 20, 0, }, /* 146 */
+ { 20, 5, 12, 21, -116, 20, 0, }, /* 147 */
+ { 20, 5, 12, 51, -32, 20, 0, }, /* 148 */
+ { 20, 5, 12, 26, -775, 20, 0, }, /* 149 */
+ { 20, 5, 12, 47, -32, 20, 0, }, /* 150 */
+ { 20, 5, 12, 55, -32, 20, 0, }, /* 151 */
+ { 20, 5, 12, 30, 1, 20, 0, }, /* 152 */
+ { 20, 5, 12, 30, -32, 20, 0, }, /* 153 */
+ { 20, 5, 12, 43, -32, 20, 0, }, /* 154 */
+ { 20, 5, 12, 96, -32, 20, 0, }, /* 155 */
+ { 20, 5, 12, 0, -64, 20, 0, }, /* 156 */
+ { 20, 5, 12, 0, -63, 20, 0, }, /* 157 */
+ { 20, 9, 12, 0, 8, 20, 0, }, /* 158 */
+ { 20, 5, 12, 34, -30, 20, 0, }, /* 159 */
+ { 20, 5, 12, 38, -25, 20, 0, }, /* 160 */
+ { 20, 9, 12, 0, 0, 20, 0, }, /* 161 */
+ { 20, 5, 12, 43, -15, 20, 0, }, /* 162 */
+ { 20, 5, 12, 47, -22, 20, 0, }, /* 163 */
+ { 20, 5, 12, 0, -8, 20, 0, }, /* 164 */
+ { 11, 9, 12, 0, 1, 11, 0, }, /* 165 */
+ { 11, 5, 12, 0, -1, 11, 0, }, /* 166 */
+ { 20, 5, 12, 51, -54, 20, 0, }, /* 167 */
+ { 20, 5, 12, 55, -48, 20, 0, }, /* 168 */
+ { 20, 5, 12, 0, 7, 20, 0, }, /* 169 */
+ { 20, 5, 12, 0, -116, 20, 0, }, /* 170 */
+ { 20, 9, 12, 38, -60, 20, 0, }, /* 171 */
+ { 20, 5, 12, 59, -64, 20, 0, }, /* 172 */
+ { 20, 25, 12, 0, 0, 20, 0, }, /* 173 */
+ { 20, 9, 12, 0, -7, 20, 0, }, /* 174 */
+ { 20, 9, 12, 0, -130, 20, 0, }, /* 175 */
+ { 13, 9, 12, 0, 80, 13, 0, }, /* 176 */
+ { 13, 9, 12, 0, 32, 13, 0, }, /* 177 */
+ { 13, 9, 12, 63, 32, 13, 0, }, /* 178 */
+ { 13, 9, 12, 67, 32, 13, 0, }, /* 179 */
+ { 13, 9, 12, 71, 32, 13, 0, }, /* 180 */
+ { 13, 9, 12, 75, 32, 13, 0, }, /* 181 */
+ { 13, 9, 12, 79, 32, 13, 0, }, /* 182 */
+ { 13, 9, 12, 84, 32, 13, 0, }, /* 183 */
+ { 13, 5, 12, 0, -32, 13, 0, }, /* 184 */
+ { 13, 5, 12, 63, -32, 13, 0, }, /* 185 */
+ { 13, 5, 12, 67, -32, 13, 0, }, /* 186 */
+ { 13, 5, 12, 71, -32, 13, 0, }, /* 187 */
+ { 13, 5, 12, 75, -32, 13, 0, }, /* 188 */
+ { 13, 5, 12, 79, -32, 13, 0, }, /* 189 */
+ { 13, 5, 12, 84, -32, 13, 0, }, /* 190 */
+ { 13, 5, 12, 0, -80, 13, 0, }, /* 191 */
+ { 13, 9, 12, 0, 1, 13, 0, }, /* 192 */
+ { 13, 5, 12, 0, -1, 13, 0, }, /* 193 */
+ { 13, 9, 12, 88, 1, 13, 0, }, /* 194 */
+ { 13, 5, 12, 88, -1, 13, 0, }, /* 195 */
+ { 13, 26, 12, 0, 0, 13, 0, }, /* 196 */
+ { 13, 12, 3, 0, 0, -34, 0, }, /* 197 */
+ { 13, 12, 3, 0, 0, -28, 0, }, /* 198 */
+ { 28, 12, 3, 0, 0, -31, 0, }, /* 199 */
+ { 13, 11, 3, 0, 0, 13, 0, }, /* 200 */
+ { 13, 9, 12, 0, 15, 13, 0, }, /* 201 */
+ { 13, 5, 12, 0, -15, 13, 0, }, /* 202 */
+ { 2, 9, 12, 0, 48, 2, 0, }, /* 203 */
+ { 2, 6, 12, 0, 0, 2, 0, }, /* 204 */
+ { 2, 21, 12, 0, 0, 2, 0, }, /* 205 */
+ { 2, 5, 12, 0, 0, 2, 0, }, /* 206 */
+ { 2, 5, 12, 0, -48, 2, 0, }, /* 207 */
+ { 10, 21, 12, 0, 0, -13, 0, }, /* 208 */
+ { 2, 17, 12, 0, 0, 2, 0, }, /* 209 */
+ { 2, 26, 12, 0, 0, 2, 0, }, /* 210 */
+ { 2, 23, 12, 0, 0, 2, 0, }, /* 211 */
+ { 26, 12, 3, 0, 0, 26, 0, }, /* 212 */
+ { 26, 17, 12, 0, 0, 26, 0, }, /* 213 */
+ { 26, 21, 12, 0, 0, 26, 0, }, /* 214 */
+ { 26, 7, 12, 0, 0, 26, 0, }, /* 215 */
+ { 1, 1, 4, 0, 0, 1, 0, }, /* 216 */
+ { 10, 1, 4, 0, 0, 10, 0, }, /* 217 */
+ { 1, 25, 12, 0, 0, 1, 0, }, /* 218 */
+ { 1, 21, 12, 0, 0, 1, 0, }, /* 219 */
+ { 1, 23, 12, 0, 0, 1, 0, }, /* 220 */
+ { 10, 21, 12, 0, 0, -105, 0, }, /* 221 */
+ { 1, 26, 12, 0, 0, 1, 0, }, /* 222 */
+ { 1, 12, 3, 0, 0, 1, 0, }, /* 223 */
+ { 1, 1, 2, 0, 0, -73, 0, }, /* 224 */
+ { 1, 7, 12, 0, 0, 1, 0, }, /* 225 */
+ { 10, 6, 12, 0, 0, -145, 0, }, /* 226 */
+ { 28, 12, 3, 0, 0, -7, 0, }, /* 227 */
+ { 1, 13, 12, 0, 0, -10, 0, }, /* 228 */
+ { 1, 21, 12, 0, 0, -4, 0, }, /* 229 */
+ { 1, 6, 12, 0, 0, 1, 0, }, /* 230 */
+ { 1, 13, 12, 0, 0, 1, 0, }, /* 231 */
+ { 50, 21, 12, 0, 0, 50, 0, }, /* 232 */
+ { 50, 1, 4, 0, 0, 50, 0, }, /* 233 */
+ { 50, 7, 12, 0, 0, 50, 0, }, /* 234 */
+ { 50, 12, 3, 0, 0, 50, 0, }, /* 235 */
+ { 56, 7, 12, 0, 0, 56, 0, }, /* 236 */
+ { 56, 12, 3, 0, 0, 56, 0, }, /* 237 */
+ { 64, 13, 12, 0, 0, 64, 0, }, /* 238 */
+ { 64, 7, 12, 0, 0, 64, 0, }, /* 239 */
+ { 64, 12, 3, 0, 0, 64, 0, }, /* 240 */
+ { 64, 6, 12, 0, 0, 64, 0, }, /* 241 */
+ { 64, 26, 12, 0, 0, 64, 0, }, /* 242 */
+ { 64, 21, 12, 0, 0, 64, 0, }, /* 243 */
+ { 64, 23, 12, 0, 0, 64, 0, }, /* 244 */
+ { 90, 7, 12, 0, 0, 90, 0, }, /* 245 */
+ { 90, 12, 3, 0, 0, 90, 0, }, /* 246 */
+ { 90, 6, 12, 0, 0, 90, 0, }, /* 247 */
+ { 90, 21, 12, 0, 0, 90, 0, }, /* 248 */
+ { 95, 7, 12, 0, 0, 95, 0, }, /* 249 */
+ { 95, 12, 3, 0, 0, 95, 0, }, /* 250 */
+ { 95, 21, 12, 0, 0, 95, 0, }, /* 251 */
+ { 15, 12, 3, 0, 0, 15, 0, }, /* 252 */
+ { 15, 10, 5, 0, 0, 15, 0, }, /* 253 */
+ { 15, 7, 12, 0, 0, 15, 0, }, /* 254 */
+ { 28, 12, 3, 0, 0, -188, 0, }, /* 255 */
+ { 28, 12, 3, 0, 0, -175, 0, }, /* 256 */
+ { 10, 21, 12, 0, 0, -231, 0, }, /* 257 */
+ { 10, 21, 12, 0, 0, -252, 0, }, /* 258 */
+ { 15, 13, 12, 0, 0, -120, 0, }, /* 259 */
+ { 15, 21, 12, 0, 0, 15, 0, }, /* 260 */
+ { 15, 6, 12, 0, 0, 15, 0, }, /* 261 */
+ { 3, 7, 12, 0, 0, 3, 0, }, /* 262 */
+ { 3, 12, 3, 0, 0, 3, 0, }, /* 263 */
+ { 3, 10, 5, 0, 0, 3, 0, }, /* 264 */
+ { 3, 10, 3, 0, 0, 3, 0, }, /* 265 */
+ { 3, 13, 12, 0, 0, -77, 0, }, /* 266 */
+ { 3, 23, 12, 0, 0, 3, 0, }, /* 267 */
+ { 3, 15, 12, 0, 0, 3, 0, }, /* 268 */
+ { 3, 26, 12, 0, 0, 3, 0, }, /* 269 */
+ { 3, 21, 12, 0, 0, 3, 0, }, /* 270 */
+ { 22, 12, 3, 0, 0, 22, 0, }, /* 271 */
+ { 22, 10, 5, 0, 0, 22, 0, }, /* 272 */
+ { 22, 7, 12, 0, 0, 22, 0, }, /* 273 */
+ { 22, 13, 12, 0, 0, -58, 0, }, /* 274 */
+ { 22, 21, 12, 0, 0, 22, 0, }, /* 275 */
+ { 21, 12, 3, 0, 0, 21, 0, }, /* 276 */
+ { 21, 10, 5, 0, 0, 21, 0, }, /* 277 */
+ { 21, 7, 12, 0, 0, 21, 0, }, /* 278 */
+ { 21, 13, 12, 0, 0, -55, 0, }, /* 279 */
+ { 21, 21, 12, 0, 0, 21, 0, }, /* 280 */
+ { 21, 23, 12, 0, 0, 21, 0, }, /* 281 */
+ { 44, 12, 3, 0, 0, 44, 0, }, /* 282 */
+ { 44, 10, 5, 0, 0, 44, 0, }, /* 283 */
+ { 44, 7, 12, 0, 0, 44, 0, }, /* 284 */
+ { 44, 10, 3, 0, 0, 44, 0, }, /* 285 */
+ { 44, 13, 12, 0, 0, 44, 0, }, /* 286 */
+ { 44, 26, 12, 0, 0, 44, 0, }, /* 287 */
+ { 44, 15, 12, 0, 0, 44, 0, }, /* 288 */
+ { 54, 12, 3, 0, 0, 54, 0, }, /* 289 */
+ { 54, 7, 12, 0, 0, 54, 0, }, /* 290 */
+ { 54, 10, 3, 0, 0, 54, 0, }, /* 291 */
+ { 54, 10, 5, 0, 0, 54, 0, }, /* 292 */
+ { 54, 13, 12, 0, 0, -52, 0, }, /* 293 */
+ { 54, 15, 12, 0, 0, -52, 0, }, /* 294 */
+ { 54, 26, 12, 0, 0, -52, 0, }, /* 295 */
+ { 54, 26, 12, 0, 0, 54, 0, }, /* 296 */
+ { 54, 23, 12, 0, 0, 54, 0, }, /* 297 */
+ { 55, 12, 3, 0, 0, 55, 0, }, /* 298 */
+ { 55, 10, 5, 0, 0, 55, 0, }, /* 299 */
+ { 55, 7, 12, 0, 0, 55, 0, }, /* 300 */
+ { 55, 13, 12, 0, 0, 55, 0, }, /* 301 */
+ { 55, 21, 12, 0, 0, 55, 0, }, /* 302 */
+ { 55, 15, 12, 0, 0, 55, 0, }, /* 303 */
+ { 55, 26, 12, 0, 0, 55, 0, }, /* 304 */
+ { 29, 7, 12, 0, 0, 29, 0, }, /* 305 */
+ { 29, 12, 3, 0, 0, 29, 0, }, /* 306 */
+ { 29, 10, 5, 0, 0, 29, 0, }, /* 307 */
+ { 29, 21, 12, 0, 0, 29, 0, }, /* 308 */
+ { 29, 10, 3, 0, 0, 29, 0, }, /* 309 */
+ { 29, 13, 12, 0, 0, -64, 0, }, /* 310 */
+ { 37, 12, 3, 0, 0, 37, 0, }, /* 311 */
+ { 37, 10, 5, 0, 0, 37, 0, }, /* 312 */
+ { 37, 7, 12, 0, 0, 37, 0, }, /* 313 */
+ { 37, 10, 3, 0, 0, 37, 0, }, /* 314 */
+ { 37, 7, 4, 0, 0, 37, 0, }, /* 315 */
+ { 37, 26, 12, 0, 0, 37, 0, }, /* 316 */
+ { 37, 15, 12, 0, 0, 37, 0, }, /* 317 */
+ { 37, 13, 12, 0, 0, 37, 0, }, /* 318 */
+ { 48, 10, 5, 0, 0, 48, 0, }, /* 319 */
+ { 48, 7, 12, 0, 0, 48, 0, }, /* 320 */
+ { 48, 12, 3, 0, 0, 48, 0, }, /* 321 */
+ { 48, 10, 3, 0, 0, 48, 0, }, /* 322 */
+ { 48, 13, 12, 0, 0, 48, 0, }, /* 323 */
+ { 48, 21, 12, 0, 0, 48, 0, }, /* 324 */
+ { 57, 7, 12, 0, 0, 57, 0, }, /* 325 */
+ { 57, 12, 3, 0, 0, 57, 0, }, /* 326 */
+ { 57, 7, 5, 0, 0, 57, 0, }, /* 327 */
+ { 57, 6, 12, 0, 0, 57, 0, }, /* 328 */
+ { 57, 21, 12, 0, 0, 57, 0, }, /* 329 */
+ { 57, 13, 12, 0, 0, 57, 0, }, /* 330 */
+ { 33, 7, 12, 0, 0, 33, 0, }, /* 331 */
+ { 33, 12, 3, 0, 0, 33, 0, }, /* 332 */
+ { 33, 7, 5, 0, 0, 33, 0, }, /* 333 */
+ { 33, 6, 12, 0, 0, 33, 0, }, /* 334 */
+ { 33, 13, 12, 0, 0, 33, 0, }, /* 335 */
+ { 58, 7, 12, 0, 0, 58, 0, }, /* 336 */
+ { 58, 26, 12, 0, 0, 58, 0, }, /* 337 */
+ { 58, 21, 12, 0, 0, 58, 0, }, /* 338 */
+ { 58, 12, 3, 0, 0, 58, 0, }, /* 339 */
+ { 58, 13, 12, 0, 0, 58, 0, }, /* 340 */
+ { 58, 15, 12, 0, 0, 58, 0, }, /* 341 */
+ { 58, 22, 12, 0, 0, 58, 0, }, /* 342 */
+ { 58, 18, 12, 0, 0, 58, 0, }, /* 343 */
+ { 58, 10, 5, 0, 0, 58, 0, }, /* 344 */
+ { 39, 7, 12, 0, 0, 39, 0, }, /* 345 */
+ { 39, 10, 12, 0, 0, 39, 0, }, /* 346 */
+ { 39, 12, 3, 0, 0, 39, 0, }, /* 347 */
+ { 39, 10, 5, 0, 0, 39, 0, }, /* 348 */
+ { 39, 13, 12, 0, 0, -81, 0, }, /* 349 */
+ { 39, 21, 12, 0, 0, 39, 0, }, /* 350 */
+ { 39, 13, 12, 0, 0, 39, 0, }, /* 351 */
+ { 39, 26, 12, 0, 0, 39, 0, }, /* 352 */
+ { 17, 9, 12, 0, 7264, 17, 0, }, /* 353 */
+ { 17, 5, 12, 0, 3008, 17, 0, }, /* 354 */
+ { 10, 21, 12, 0, 0, -49, 0, }, /* 355 */
+ { 17, 6, 12, 0, 0, 17, 0, }, /* 356 */
+ { 24, 7, 6, 0, 0, 24, 0, }, /* 357 */
+ { 24, 7, 7, 0, 0, 24, 0, }, /* 358 */
+ { 24, 7, 8, 0, 0, 24, 0, }, /* 359 */
+ { 16, 7, 12, 0, 0, 16, 0, }, /* 360 */
+ { 16, 12, 3, 0, 0, 16, 0, }, /* 361 */
+ { 16, 21, 12, 0, 0, 16, 0, }, /* 362 */
+ { 16, 15, 12, 0, 0, 16, 0, }, /* 363 */
+ { 16, 26, 12, 0, 0, 16, 0, }, /* 364 */
+ { 9, 9, 12, 0, 38864, 9, 0, }, /* 365 */
+ { 9, 9, 12, 0, 8, 9, 0, }, /* 366 */
+ { 9, 5, 12, 0, -8, 9, 0, }, /* 367 */
+ { 8, 17, 12, 0, 0, 8, 0, }, /* 368 */
+ { 8, 7, 12, 0, 0, 8, 0, }, /* 369 */
+ { 8, 26, 12, 0, 0, 8, 0, }, /* 370 */
+ { 8, 21, 12, 0, 0, 8, 0, }, /* 371 */
+ { 41, 29, 12, 0, 0, 41, 0, }, /* 372 */
+ { 41, 7, 12, 0, 0, 41, 0, }, /* 373 */
+ { 41, 22, 12, 0, 0, 41, 0, }, /* 374 */
+ { 41, 18, 12, 0, 0, 41, 0, }, /* 375 */
+ { 46, 7, 12, 0, 0, 46, 0, }, /* 376 */
+ { 46, 14, 12, 0, 0, 46, 0, }, /* 377 */
+ { 51, 7, 12, 0, 0, 51, 0, }, /* 378 */
+ { 51, 12, 3, 0, 0, 51, 0, }, /* 379 */
+ { 25, 7, 12, 0, 0, 25, 0, }, /* 380 */
+ { 25, 12, 3, 0, 0, 25, 0, }, /* 381 */
+ { 10, 21, 12, 0, 0, -115, 0, }, /* 382 */
+ { 7, 7, 12, 0, 0, 7, 0, }, /* 383 */
+ { 7, 12, 3, 0, 0, 7, 0, }, /* 384 */
+ { 52, 7, 12, 0, 0, 52, 0, }, /* 385 */
+ { 52, 12, 3, 0, 0, 52, 0, }, /* 386 */
+ { 32, 7, 12, 0, 0, 32, 0, }, /* 387 */
+ { 32, 12, 3, 0, 0, 32, 0, }, /* 388 */
+ { 32, 10, 5, 0, 0, 32, 0, }, /* 389 */
+ { 32, 21, 12, 0, 0, 32, 0, }, /* 390 */
+ { 32, 6, 12, 0, 0, 32, 0, }, /* 391 */
+ { 32, 23, 12, 0, 0, 32, 0, }, /* 392 */
+ { 32, 13, 12, 0, 0, 32, 0, }, /* 393 */
+ { 32, 15, 12, 0, 0, 32, 0, }, /* 394 */
+ { 38, 21, 12, 0, 0, 38, 0, }, /* 395 */
+ { 10, 21, 12, 0, 0, -70, 0, }, /* 396 */
+ { 38, 17, 12, 0, 0, 38, 0, }, /* 397 */
+ { 38, 12, 3, 0, 0, 38, 0, }, /* 398 */
+ { 38, 1, 2, 0, 0, 38, 0, }, /* 399 */
+ { 38, 13, 12, 0, 0, 38, 0, }, /* 400 */
+ { 38, 7, 12, 0, 0, 38, 0, }, /* 401 */
+ { 38, 6, 12, 0, 0, 38, 0, }, /* 402 */
+ { 35, 7, 12, 0, 0, 35, 0, }, /* 403 */
+ { 35, 12, 3, 0, 0, 35, 0, }, /* 404 */
+ { 35, 10, 5, 0, 0, 35, 0, }, /* 405 */
+ { 35, 26, 12, 0, 0, 35, 0, }, /* 406 */
+ { 35, 21, 12, 0, 0, 35, 0, }, /* 407 */
+ { 35, 13, 12, 0, 0, 35, 0, }, /* 408 */
+ { 53, 7, 12, 0, 0, 53, 0, }, /* 409 */
+ { 40, 7, 12, 0, 0, 40, 0, }, /* 410 */
+ { 40, 13, 12, 0, 0, 40, 0, }, /* 411 */
+ { 40, 15, 12, 0, 0, 40, 0, }, /* 412 */
+ { 40, 26, 12, 0, 0, 40, 0, }, /* 413 */
+ { 32, 26, 12, 0, 0, 32, 0, }, /* 414 */
+ { 6, 7, 12, 0, 0, 6, 0, }, /* 415 */
+ { 6, 12, 3, 0, 0, 6, 0, }, /* 416 */
+ { 6, 10, 5, 0, 0, 6, 0, }, /* 417 */
+ { 6, 21, 12, 0, 0, 6, 0, }, /* 418 */
+ { 91, 7, 12, 0, 0, 91, 0, }, /* 419 */
+ { 91, 10, 5, 0, 0, 91, 0, }, /* 420 */
+ { 91, 12, 3, 0, 0, 91, 0, }, /* 421 */
+ { 91, 10, 12, 0, 0, 91, 0, }, /* 422 */
+ { 91, 13, 12, 0, 0, 91, 0, }, /* 423 */
+ { 91, 21, 12, 0, 0, 91, 0, }, /* 424 */
+ { 91, 6, 12, 0, 0, 91, 0, }, /* 425 */
+ { 28, 11, 3, 0, 0, 28, 0, }, /* 426 */
+ { 62, 12, 3, 0, 0, 62, 0, }, /* 427 */
+ { 62, 10, 5, 0, 0, 62, 0, }, /* 428 */
+ { 62, 7, 12, 0, 0, 62, 0, }, /* 429 */
+ { 62, 10, 3, 0, 0, 62, 0, }, /* 430 */
+ { 62, 13, 12, 0, 0, 62, 0, }, /* 431 */
+ { 62, 21, 12, 0, 0, 62, 0, }, /* 432 */
+ { 62, 26, 12, 0, 0, 62, 0, }, /* 433 */
+ { 76, 12, 3, 0, 0, 76, 0, }, /* 434 */
+ { 76, 10, 5, 0, 0, 76, 0, }, /* 435 */
+ { 76, 7, 12, 0, 0, 76, 0, }, /* 436 */
+ { 76, 13, 12, 0, 0, 76, 0, }, /* 437 */
+ { 93, 7, 12, 0, 0, 93, 0, }, /* 438 */
+ { 93, 12, 3, 0, 0, 93, 0, }, /* 439 */
+ { 93, 10, 5, 0, 0, 93, 0, }, /* 440 */
+ { 93, 21, 12, 0, 0, 93, 0, }, /* 441 */
+ { 70, 7, 12, 0, 0, 70, 0, }, /* 442 */
+ { 70, 10, 5, 0, 0, 70, 0, }, /* 443 */
+ { 70, 12, 3, 0, 0, 70, 0, }, /* 444 */
+ { 70, 21, 12, 0, 0, 70, 0, }, /* 445 */
+ { 70, 13, 12, 0, 0, 70, 0, }, /* 446 */
+ { 73, 13, 12, 0, 0, 73, 0, }, /* 447 */
+ { 73, 7, 12, 0, 0, 73, 0, }, /* 448 */
+ { 73, 6, 12, 0, 0, 73, 0, }, /* 449 */
+ { 73, 21, 12, 0, 0, 73, 0, }, /* 450 */
+ { 13, 5, 12, 63, -6222, 13, 0, }, /* 451 */
+ { 13, 5, 12, 67, -6221, 13, 0, }, /* 452 */
+ { 13, 5, 12, 71, -6212, 13, 0, }, /* 453 */
+ { 13, 5, 12, 75, -6210, 13, 0, }, /* 454 */
+ { 13, 5, 12, 79, -6210, 13, 0, }, /* 455 */
+ { 13, 5, 12, 79, -6211, 13, 0, }, /* 456 */
+ { 13, 5, 12, 84, -6204, 13, 0, }, /* 457 */
+ { 13, 5, 12, 88, -6180, 13, 0, }, /* 458 */
+ { 13, 5, 12, 108, 35267, 13, 0, }, /* 459 */
+ { 17, 9, 12, 0, -3008, 17, 0, }, /* 460 */
+ { 76, 21, 12, 0, 0, 76, 0, }, /* 461 */
+ { 28, 12, 3, 0, 0, -110, 0, }, /* 462 */
+ { 28, 12, 3, 0, 0, 15, 0, }, /* 463 */
+ { 10, 21, 12, 0, 0, -37, 0, }, /* 464 */
+ { 28, 12, 3, 0, 0, -16, 0, }, /* 465 */
+ { 28, 12, 3, 0, 0, -43, 0, }, /* 466 */
+ { 28, 12, 3, 0, 0, -138, 0, }, /* 467 */
+ { 10, 10, 5, 0, 0, -16, 0, }, /* 468 */
+ { 10, 7, 12, 0, 0, -40, 0, }, /* 469 */
+ { 10, 7, 12, 0, 0, -16, 0, }, /* 470 */
+ { 10, 7, 12, 0, 0, 15, 0, }, /* 471 */
+ { 10, 7, 12, 0, 0, -154, 0, }, /* 472 */
+ { 10, 7, 12, 0, 0, -37, 0, }, /* 473 */
+ { 28, 12, 3, 0, 0, -89, 0, }, /* 474 */
+ { 10, 10, 5, 0, 0, 3, 0, }, /* 475 */
+ { 28, 12, 3, 0, 0, -37, 0, }, /* 476 */
+ { 10, 7, 12, 0, 0, 150, 0, }, /* 477 */
+ { 13, 5, 12, 0, 0, 13, 0, }, /* 478 */
+ { 13, 6, 12, 0, 0, 13, 0, }, /* 479 */
+ { 34, 5, 12, 0, 35332, 34, 0, }, /* 480 */
+ { 34, 5, 12, 0, 3814, 34, 0, }, /* 481 */
+ { 34, 5, 12, 0, 35384, 34, 0, }, /* 482 */
+ { 34, 9, 12, 92, 1, 34, 0, }, /* 483 */
+ { 34, 5, 12, 92, -1, 34, 0, }, /* 484 */
+ { 34, 5, 12, 92, -58, 34, 0, }, /* 485 */
+ { 34, 9, 12, 0, -7615, 34, 0, }, /* 486 */
+ { 20, 5, 12, 0, 8, 20, 0, }, /* 487 */
+ { 20, 9, 12, 0, -8, 20, 0, }, /* 488 */
+ { 20, 5, 12, 0, 74, 20, 0, }, /* 489 */
+ { 20, 5, 12, 0, 86, 20, 0, }, /* 490 */
+ { 20, 5, 12, 0, 100, 20, 0, }, /* 491 */
+ { 20, 5, 12, 0, 128, 20, 0, }, /* 492 */
+ { 20, 5, 12, 0, 112, 20, 0, }, /* 493 */
+ { 20, 5, 12, 0, 126, 20, 0, }, /* 494 */
+ { 20, 8, 12, 0, -8, 20, 0, }, /* 495 */
+ { 20, 5, 12, 0, 9, 20, 0, }, /* 496 */
+ { 20, 9, 12, 0, -74, 20, 0, }, /* 497 */
+ { 20, 8, 12, 0, -9, 20, 0, }, /* 498 */
+ { 20, 5, 12, 21, -7173, 20, 0, }, /* 499 */
+ { 20, 9, 12, 0, -86, 20, 0, }, /* 500 */
+ { 20, 9, 12, 0, -100, 20, 0, }, /* 501 */
+ { 20, 9, 12, 0, -112, 20, 0, }, /* 502 */
+ { 20, 9, 12, 0, -128, 20, 0, }, /* 503 */
+ { 20, 9, 12, 0, -126, 20, 0, }, /* 504 */
+ { 28, 1, 3, 0, 0, 28, 0, }, /* 505 */
+ { 28, 1, 13, 0, 0, 28, 0, }, /* 506 */
+ { 10, 27, 2, 0, 0, 10, 0, }, /* 507 */
+ { 10, 28, 2, 0, 0, 10, 0, }, /* 508 */
+ { 10, 29, 12, 0, 0, -67, 0, }, /* 509 */
+ { 10, 21, 14, 0, 0, 10, 0, }, /* 510 */
+ { 0, 2, 2, 0, 0, 0, 0, }, /* 511 */
+ { 28, 12, 3, 0, 0, -93, 0, }, /* 512 */
+ { 10, 9, 12, 0, 0, 10, 0, }, /* 513 */
+ { 10, 5, 12, 0, 0, 10, 0, }, /* 514 */
+ { 20, 9, 12, 96, -7517, 20, 0, }, /* 515 */
+ { 34, 9, 12, 100, -8383, 34, 0, }, /* 516 */
+ { 34, 9, 12, 104, -8262, 34, 0, }, /* 517 */
+ { 34, 9, 12, 0, 28, 34, 0, }, /* 518 */
+ { 10, 7, 12, 0, 0, 10, 0, }, /* 519 */
+ { 10, 5, 14, 0, 0, 10, 0, }, /* 520 */
+ { 34, 5, 12, 0, -28, 34, 0, }, /* 521 */
+ { 34, 14, 12, 0, 16, 34, 0, }, /* 522 */
+ { 34, 14, 12, 0, -16, 34, 0, }, /* 523 */
+ { 34, 14, 12, 0, 0, 34, 0, }, /* 524 */
+ { 10, 25, 14, 0, 0, 10, 0, }, /* 525 */
+ { 10, 26, 12, 0, 26, 10, 0, }, /* 526 */
+ { 10, 26, 14, 0, 26, 10, 0, }, /* 527 */
+ { 10, 26, 12, 0, -26, 10, 0, }, /* 528 */
+ { 5, 26, 12, 0, 0, 5, 0, }, /* 529 */
+ { 18, 9, 12, 0, 48, 18, 0, }, /* 530 */
+ { 18, 5, 12, 0, -48, 18, 0, }, /* 531 */
+ { 34, 9, 12, 0, -10743, 34, 0, }, /* 532 */
+ { 34, 9, 12, 0, -3814, 34, 0, }, /* 533 */
+ { 34, 9, 12, 0, -10727, 34, 0, }, /* 534 */
+ { 34, 5, 12, 0, -10795, 34, 0, }, /* 535 */
+ { 34, 5, 12, 0, -10792, 34, 0, }, /* 536 */
+ { 34, 9, 12, 0, -10780, 34, 0, }, /* 537 */
+ { 34, 9, 12, 0, -10749, 34, 0, }, /* 538 */
+ { 34, 9, 12, 0, -10783, 34, 0, }, /* 539 */
+ { 34, 9, 12, 0, -10782, 34, 0, }, /* 540 */
+ { 34, 9, 12, 0, -10815, 34, 0, }, /* 541 */
+ { 11, 5, 12, 0, 0, 11, 0, }, /* 542 */
+ { 11, 26, 12, 0, 0, 11, 0, }, /* 543 */
+ { 11, 12, 3, 0, 0, 11, 0, }, /* 544 */
+ { 11, 21, 12, 0, 0, 11, 0, }, /* 545 */
+ { 11, 15, 12, 0, 0, 11, 0, }, /* 546 */
+ { 17, 5, 12, 0, -7264, 17, 0, }, /* 547 */
+ { 59, 7, 12, 0, 0, 59, 0, }, /* 548 */
+ { 59, 6, 12, 0, 0, 59, 0, }, /* 549 */
+ { 59, 21, 12, 0, 0, 59, 0, }, /* 550 */
+ { 59, 12, 3, 0, 0, 59, 0, }, /* 551 */
+ { 13, 12, 3, 0, 0, 13, 0, }, /* 552 */
+ { 10, 21, 12, 0, 0, -28, 0, }, /* 553 */
+ { 23, 26, 12, 0, 0, 23, 0, }, /* 554 */
+ { 10, 21, 12, 0, 0, -131, 0, }, /* 555 */
+ { 10, 21, 12, 0, 0, -125, 0, }, /* 556 */
+ { 23, 6, 12, 0, 0, 23, 0, }, /* 557 */
+ { 10, 7, 12, 0, 0, 23, 0, }, /* 558 */
+ { 23, 14, 12, 0, 0, 23, 0, }, /* 559 */
+ { 10, 22, 12, 0, 0, -131, 0, }, /* 560 */
+ { 10, 18, 12, 0, 0, -131, 0, }, /* 561 */
+ { 10, 26, 12, 0, 0, -125, 0, }, /* 562 */
+ { 10, 17, 12, 0, 0, -125, 0, }, /* 563 */
+ { 10, 22, 12, 0, 0, -125, 0, }, /* 564 */
+ { 10, 18, 12, 0, 0, -125, 0, }, /* 565 */
+ { 28, 12, 3, 0, 0, -19, 0, }, /* 566 */
+ { 24, 10, 3, 0, 0, 24, 0, }, /* 567 */
+ { 10, 17, 14, 0, 0, -125, 0, }, /* 568 */
+ { 10, 6, 12, 0, 0, -61, 0, }, /* 569 */
+ { 10, 7, 12, 0, 0, -97, 0, }, /* 570 */
+ { 10, 21, 14, 0, 0, -97, 0, }, /* 571 */
+ { 10, 26, 12, 0, 0, 23, 0, }, /* 572 */
+ { 27, 7, 12, 0, 0, 27, 0, }, /* 573 */
+ { 28, 12, 3, 0, 0, -61, 0, }, /* 574 */
+ { 10, 24, 12, 0, 0, -61, 0, }, /* 575 */
+ { 27, 6, 12, 0, 0, 27, 0, }, /* 576 */
+ { 10, 17, 12, 0, 0, -61, 0, }, /* 577 */
+ { 30, 7, 12, 0, 0, 30, 0, }, /* 578 */
+ { 30, 6, 12, 0, 0, 30, 0, }, /* 579 */
+ { 4, 7, 12, 0, 0, 4, 0, }, /* 580 */
+ { 24, 7, 12, 0, 0, 24, 0, }, /* 581 */
+ { 10, 15, 12, 0, 0, 23, 0, }, /* 582 */
+ { 24, 26, 12, 0, 0, 24, 0, }, /* 583 */
+ { 10, 26, 14, 0, 0, 23, 0, }, /* 584 */
+ { 30, 26, 12, 0, 0, 30, 0, }, /* 585 */
+ { 23, 7, 12, 0, 0, 23, 0, }, /* 586 */
+ { 61, 7, 12, 0, 0, 61, 0, }, /* 587 */
+ { 61, 6, 12, 0, 0, 61, 0, }, /* 588 */
+ { 61, 26, 12, 0, 0, 61, 0, }, /* 589 */
+ { 86, 7, 12, 0, 0, 86, 0, }, /* 590 */
+ { 86, 6, 12, 0, 0, 86, 0, }, /* 591 */
+ { 86, 21, 12, 0, 0, 86, 0, }, /* 592 */
+ { 77, 7, 12, 0, 0, 77, 0, }, /* 593 */
+ { 77, 6, 12, 0, 0, 77, 0, }, /* 594 */
+ { 77, 21, 12, 0, 0, 77, 0, }, /* 595 */
+ { 77, 13, 12, 0, 0, 77, 0, }, /* 596 */
+ { 13, 9, 12, 108, 1, 13, 0, }, /* 597 */
+ { 13, 5, 12, 108, -35267, 13, 0, }, /* 598 */
+ { 13, 7, 12, 0, 0, 13, 0, }, /* 599 */
+ { 13, 21, 12, 0, 0, 13, 0, }, /* 600 */
+ { 79, 7, 12, 0, 0, 79, 0, }, /* 601 */
+ { 79, 14, 12, 0, 0, 79, 0, }, /* 602 */
+ { 79, 12, 3, 0, 0, 79, 0, }, /* 603 */
+ { 79, 21, 12, 0, 0, 79, 0, }, /* 604 */
+ { 34, 9, 12, 0, -35332, 34, 0, }, /* 605 */
+ { 34, 9, 12, 0, -42280, 34, 0, }, /* 606 */
+ { 34, 5, 12, 0, 48, 34, 0, }, /* 607 */
+ { 34, 9, 12, 0, -42308, 34, 0, }, /* 608 */
+ { 34, 9, 12, 0, -42319, 34, 0, }, /* 609 */
+ { 34, 9, 12, 0, -42315, 34, 0, }, /* 610 */
+ { 34, 9, 12, 0, -42305, 34, 0, }, /* 611 */
+ { 34, 9, 12, 0, -42258, 34, 0, }, /* 612 */
+ { 34, 9, 12, 0, -42282, 34, 0, }, /* 613 */
+ { 34, 9, 12, 0, -42261, 34, 0, }, /* 614 */
+ { 34, 9, 12, 0, 928, 34, 0, }, /* 615 */
+ { 34, 9, 12, 0, -48, 34, 0, }, /* 616 */
+ { 34, 9, 12, 0, -42307, 34, 0, }, /* 617 */
+ { 34, 9, 12, 0, -35384, 34, 0, }, /* 618 */
+ { 49, 7, 12, 0, 0, 49, 0, }, /* 619 */
+ { 49, 12, 3, 0, 0, 49, 0, }, /* 620 */
+ { 49, 10, 5, 0, 0, 49, 0, }, /* 621 */
+ { 49, 26, 12, 0, 0, 49, 0, }, /* 622 */
+ { 10, 15, 12, 0, 0, -216, 0, }, /* 623 */
+ { 10, 15, 12, 0, 0, -202, 0, }, /* 624 */
+ { 10, 26, 12, 0, 0, -163, 0, }, /* 625 */
+ { 10, 23, 12, 0, 0, -163, 0, }, /* 626 */
+ { 65, 7, 12, 0, 0, 65, 0, }, /* 627 */
+ { 65, 21, 12, 0, 0, 65, 0, }, /* 628 */
+ { 75, 10, 5, 0, 0, 75, 0, }, /* 629 */
+ { 75, 7, 12, 0, 0, 75, 0, }, /* 630 */
+ { 75, 12, 3, 0, 0, 75, 0, }, /* 631 */
+ { 75, 21, 12, 0, 0, 75, 0, }, /* 632 */
+ { 75, 13, 12, 0, 0, 75, 0, }, /* 633 */
+ { 15, 12, 3, 0, 0, -16, 0, }, /* 634 */
+ { 15, 7, 12, 0, 0, -46, 0, }, /* 635 */
+ { 69, 13, 12, 0, 0, 69, 0, }, /* 636 */
+ { 69, 7, 12, 0, 0, 69, 0, }, /* 637 */
+ { 69, 12, 3, 0, 0, 69, 0, }, /* 638 */
+ { 10, 21, 12, 0, 0, -101, 0, }, /* 639 */
+ { 69, 21, 12, 0, 0, 69, 0, }, /* 640 */
+ { 74, 7, 12, 0, 0, 74, 0, }, /* 641 */
+ { 74, 12, 3, 0, 0, 74, 0, }, /* 642 */
+ { 74, 10, 5, 0, 0, 74, 0, }, /* 643 */
+ { 74, 21, 12, 0, 0, 74, 0, }, /* 644 */
+ { 84, 12, 3, 0, 0, 84, 0, }, /* 645 */
+ { 84, 10, 5, 0, 0, 84, 0, }, /* 646 */
+ { 84, 7, 12, 0, 0, 84, 0, }, /* 647 */
+ { 84, 21, 12, 0, 0, 84, 0, }, /* 648 */
+ { 10, 6, 12, 0, 0, -22, 0, }, /* 649 */
+ { 84, 13, 12, 0, 0, 84, 0, }, /* 650 */
+ { 39, 6, 12, 0, 0, 39, 0, }, /* 651 */
+ { 68, 7, 12, 0, 0, 68, 0, }, /* 652 */
+ { 68, 12, 3, 0, 0, 68, 0, }, /* 653 */
+ { 68, 10, 5, 0, 0, 68, 0, }, /* 654 */
+ { 68, 13, 12, 0, 0, 68, 0, }, /* 655 */
+ { 68, 21, 12, 0, 0, 68, 0, }, /* 656 */
+ { 92, 7, 12, 0, 0, 92, 0, }, /* 657 */
+ { 92, 12, 3, 0, 0, 92, 0, }, /* 658 */
+ { 92, 6, 12, 0, 0, 92, 0, }, /* 659 */
+ { 92, 21, 12, 0, 0, 92, 0, }, /* 660 */
+ { 87, 7, 12, 0, 0, 87, 0, }, /* 661 */
+ { 87, 10, 5, 0, 0, 87, 0, }, /* 662 */
+ { 87, 12, 3, 0, 0, 87, 0, }, /* 663 */
+ { 87, 21, 12, 0, 0, 87, 0, }, /* 664 */
+ { 87, 6, 12, 0, 0, 87, 0, }, /* 665 */
+ { 34, 5, 12, 0, -928, 34, 0, }, /* 666 */
+ { 9, 5, 12, 0, -38864, 9, 0, }, /* 667 */
+ { 87, 13, 12, 0, 0, 87, 0, }, /* 668 */
+ { 24, 7, 9, 0, 0, 24, 0, }, /* 669 */
+ { 24, 7, 10, 0, 0, 24, 0, }, /* 670 */
+ { 0, 4, 12, 0, 0, 0, 0, }, /* 671 */
+ { 0, 3, 12, 0, 0, 0, 0, }, /* 672 */
+ { 26, 25, 12, 0, 0, 26, 0, }, /* 673 */
+ { 1, 24, 12, 0, 0, 1, 0, }, /* 674 */
+ { 1, 7, 12, 0, 0, -10, 0, }, /* 675 */
+ { 1, 26, 12, 0, 0, -10, 0, }, /* 676 */
+ { 10, 6, 3, 0, 0, -61, 0, }, /* 677 */
+ { 36, 7, 12, 0, 0, 36, 0, }, /* 678 */
+ { 10, 21, 12, 0, 0, -25, 0, }, /* 679 */
+ { 10, 15, 12, 0, 0, -85, 0, }, /* 680 */
+ { 10, 26, 12, 0, 0, -25, 0, }, /* 681 */
+ { 20, 14, 12, 0, 0, 20, 0, }, /* 682 */
+ { 20, 15, 12, 0, 0, 20, 0, }, /* 683 */
+ { 20, 26, 12, 0, 0, 20, 0, }, /* 684 */
+ { 71, 7, 12, 0, 0, 71, 0, }, /* 685 */
+ { 67, 7, 12, 0, 0, 67, 0, }, /* 686 */
+ { 28, 12, 3, 0, 0, -1, 0, }, /* 687 */
+ { 10, 15, 12, 0, 0, -1, 0, }, /* 688 */
+ { 42, 7, 12, 0, 0, 42, 0, }, /* 689 */
+ { 42, 15, 12, 0, 0, 42, 0, }, /* 690 */
+ { 19, 7, 12, 0, 0, 19, 0, }, /* 691 */
+ { 19, 14, 12, 0, 0, 19, 0, }, /* 692 */
+ { 118, 7, 12, 0, 0, 118, 0, }, /* 693 */
+ { 118, 12, 3, 0, 0, 118, 0, }, /* 694 */
+ { 60, 7, 12, 0, 0, 60, 0, }, /* 695 */
+ { 60, 21, 12, 0, 0, 60, 0, }, /* 696 */
+ { 43, 7, 12, 0, 0, 43, 0, }, /* 697 */
+ { 43, 21, 12, 0, 0, 43, 0, }, /* 698 */
+ { 43, 14, 12, 0, 0, 43, 0, }, /* 699 */
+ { 14, 9, 12, 0, 40, 14, 0, }, /* 700 */
+ { 14, 5, 12, 0, -40, 14, 0, }, /* 701 */
+ { 47, 7, 12, 0, 0, 47, 0, }, /* 702 */
+ { 45, 7, 12, 0, 0, 45, 0, }, /* 703 */
+ { 45, 13, 12, 0, 0, 45, 0, }, /* 704 */
+ { 136, 9, 12, 0, 40, 136, 0, }, /* 705 */
+ { 136, 5, 12, 0, -40, 136, 0, }, /* 706 */
+ { 106, 7, 12, 0, 0, 106, 0, }, /* 707 */
+ { 104, 7, 12, 0, 0, 104, 0, }, /* 708 */
+ { 104, 21, 12, 0, 0, 104, 0, }, /* 709 */
+ { 110, 7, 12, 0, 0, 110, 0, }, /* 710 */
+ { 12, 7, 12, 0, 0, 12, 0, }, /* 711 */
+ { 81, 7, 12, 0, 0, 81, 0, }, /* 712 */
+ { 81, 21, 12, 0, 0, 81, 0, }, /* 713 */
+ { 81, 15, 12, 0, 0, 81, 0, }, /* 714 */
+ { 120, 7, 12, 0, 0, 120, 0, }, /* 715 */
+ { 120, 26, 12, 0, 0, 120, 0, }, /* 716 */
+ { 120, 15, 12, 0, 0, 120, 0, }, /* 717 */
+ { 116, 7, 12, 0, 0, 116, 0, }, /* 718 */
+ { 116, 15, 12, 0, 0, 116, 0, }, /* 719 */
+ { 128, 7, 12, 0, 0, 128, 0, }, /* 720 */
+ { 128, 15, 12, 0, 0, 128, 0, }, /* 721 */
+ { 66, 7, 12, 0, 0, 66, 0, }, /* 722 */
+ { 66, 15, 12, 0, 0, 66, 0, }, /* 723 */
+ { 66, 21, 12, 0, 0, 66, 0, }, /* 724 */
+ { 72, 7, 12, 0, 0, 72, 0, }, /* 725 */
+ { 72, 21, 12, 0, 0, 72, 0, }, /* 726 */
+ { 98, 7, 12, 0, 0, 98, 0, }, /* 727 */
+ { 97, 7, 12, 0, 0, 97, 0, }, /* 728 */
+ { 97, 15, 12, 0, 0, 97, 0, }, /* 729 */
+ { 31, 7, 12, 0, 0, 31, 0, }, /* 730 */
+ { 31, 12, 3, 0, 0, 31, 0, }, /* 731 */
+ { 31, 15, 12, 0, 0, 31, 0, }, /* 732 */
+ { 31, 21, 12, 0, 0, 31, 0, }, /* 733 */
+ { 88, 7, 12, 0, 0, 88, 0, }, /* 734 */
+ { 88, 15, 12, 0, 0, 88, 0, }, /* 735 */
+ { 88, 21, 12, 0, 0, 88, 0, }, /* 736 */
+ { 117, 7, 12, 0, 0, 117, 0, }, /* 737 */
+ { 117, 15, 12, 0, 0, 117, 0, }, /* 738 */
+ { 112, 7, 12, 0, 0, 112, 0, }, /* 739 */
+ { 112, 26, 12, 0, 0, 112, 0, }, /* 740 */
+ { 112, 12, 3, 0, 0, 112, 0, }, /* 741 */
+ { 112, 15, 12, 0, 0, 112, 0, }, /* 742 */
+ { 112, 21, 12, 0, 0, 112, 0, }, /* 743 */
+ { 78, 7, 12, 0, 0, 78, 0, }, /* 744 */
+ { 78, 21, 12, 0, 0, 78, 0, }, /* 745 */
+ { 83, 7, 12, 0, 0, 83, 0, }, /* 746 */
+ { 83, 15, 12, 0, 0, 83, 0, }, /* 747 */
+ { 82, 7, 12, 0, 0, 82, 0, }, /* 748 */
+ { 82, 15, 12, 0, 0, 82, 0, }, /* 749 */
+ { 121, 7, 12, 0, 0, 121, 0, }, /* 750 */
+ { 121, 21, 12, 0, 0, 121, 0, }, /* 751 */
+ { 121, 15, 12, 0, 0, 121, 0, }, /* 752 */
+ { 89, 7, 12, 0, 0, 89, 0, }, /* 753 */
+ { 130, 9, 12, 0, 64, 130, 0, }, /* 754 */
+ { 130, 5, 12, 0, -64, 130, 0, }, /* 755 */
+ { 130, 15, 12, 0, 0, 130, 0, }, /* 756 */
+ { 144, 7, 12, 0, 0, 144, 0, }, /* 757 */
+ { 144, 12, 3, 0, 0, 144, 0, }, /* 758 */
+ { 144, 13, 12, 0, 0, 144, 0, }, /* 759 */
+ { 1, 15, 12, 0, 0, 1, 0, }, /* 760 */
+ { 147, 7, 12, 0, 0, 147, 0, }, /* 761 */
+ { 147, 15, 12, 0, 0, 147, 0, }, /* 762 */
+ { 148, 7, 12, 0, 0, 148, 0, }, /* 763 */
+ { 148, 12, 3, 0, 0, 148, 0, }, /* 764 */
+ { 148, 15, 12, 0, 0, 148, 0, }, /* 765 */
+ { 148, 21, 12, 0, 0, 148, 0, }, /* 766 */
+ { 149, 7, 12, 0, 0, 149, 0, }, /* 767 */
+ { 94, 10, 5, 0, 0, 94, 0, }, /* 768 */
+ { 94, 12, 3, 0, 0, 94, 0, }, /* 769 */
+ { 94, 7, 12, 0, 0, 94, 0, }, /* 770 */
+ { 94, 21, 12, 0, 0, 94, 0, }, /* 771 */
+ { 94, 15, 12, 0, 0, 94, 0, }, /* 772 */
+ { 94, 13, 12, 0, 0, 94, 0, }, /* 773 */
+ { 85, 12, 3, 0, 0, 85, 0, }, /* 774 */
+ { 85, 10, 5, 0, 0, 85, 0, }, /* 775 */
+ { 85, 7, 12, 0, 0, 85, 0, }, /* 776 */
+ { 85, 21, 12, 0, 0, 85, 0, }, /* 777 */
+ { 85, 1, 4, 0, 0, 85, 0, }, /* 778 */
+ { 101, 7, 12, 0, 0, 101, 0, }, /* 779 */
+ { 101, 13, 12, 0, 0, 101, 0, }, /* 780 */
+ { 96, 12, 3, 0, 0, 96, 0, }, /* 781 */
+ { 96, 7, 12, 0, 0, 96, 0, }, /* 782 */
+ { 96, 10, 5, 0, 0, 96, 0, }, /* 783 */
+ { 96, 13, 12, 0, 0, 96, 0, }, /* 784 */
+ { 96, 21, 12, 0, 0, 96, 0, }, /* 785 */
+ { 111, 7, 12, 0, 0, 111, 0, }, /* 786 */
+ { 111, 12, 3, 0, 0, 111, 0, }, /* 787 */
+ { 111, 21, 12, 0, 0, 111, 0, }, /* 788 */
+ { 100, 12, 3, 0, 0, 100, 0, }, /* 789 */
+ { 100, 10, 5, 0, 0, 100, 0, }, /* 790 */
+ { 100, 7, 12, 0, 0, 100, 0, }, /* 791 */
+ { 100, 7, 4, 0, 0, 100, 0, }, /* 792 */
+ { 100, 21, 12, 0, 0, 100, 0, }, /* 793 */
+ { 100, 13, 12, 0, 0, 100, 0, }, /* 794 */
+ { 48, 15, 12, 0, 0, 48, 0, }, /* 795 */
+ { 108, 7, 12, 0, 0, 108, 0, }, /* 796 */
+ { 108, 10, 5, 0, 0, 108, 0, }, /* 797 */
+ { 108, 12, 3, 0, 0, 108, 0, }, /* 798 */
+ { 108, 21, 12, 0, 0, 108, 0, }, /* 799 */
+ { 129, 7, 12, 0, 0, 129, 0, }, /* 800 */
+ { 129, 21, 12, 0, 0, 129, 0, }, /* 801 */
+ { 109, 7, 12, 0, 0, 109, 0, }, /* 802 */
+ { 109, 12, 3, 0, 0, 109, 0, }, /* 803 */
+ { 109, 10, 5, 0, 0, 109, 0, }, /* 804 */
+ { 109, 13, 12, 0, 0, 109, 0, }, /* 805 */
+ { 107, 12, 3, 0, 0, 107, 0, }, /* 806 */
+ { 107, 12, 3, 0, 0, -52, 0, }, /* 807 */
+ { 107, 10, 5, 0, 0, 107, 0, }, /* 808 */
+ { 107, 10, 5, 0, 0, -52, 0, }, /* 809 */
+ { 107, 7, 12, 0, 0, 107, 0, }, /* 810 */
+ { 28, 12, 3, 0, 0, -52, 0, }, /* 811 */
+ { 107, 10, 3, 0, 0, 107, 0, }, /* 812 */
+ { 135, 7, 12, 0, 0, 135, 0, }, /* 813 */
+ { 135, 10, 5, 0, 0, 135, 0, }, /* 814 */
+ { 135, 12, 3, 0, 0, 135, 0, }, /* 815 */
+ { 135, 21, 12, 0, 0, 135, 0, }, /* 816 */
+ { 135, 13, 12, 0, 0, 135, 0, }, /* 817 */
+ { 124, 7, 12, 0, 0, 124, 0, }, /* 818 */
+ { 124, 10, 3, 0, 0, 124, 0, }, /* 819 */
+ { 124, 10, 5, 0, 0, 124, 0, }, /* 820 */
+ { 124, 12, 3, 0, 0, 124, 0, }, /* 821 */
+ { 124, 21, 12, 0, 0, 124, 0, }, /* 822 */
+ { 124, 13, 12, 0, 0, 124, 0, }, /* 823 */
+ { 123, 7, 12, 0, 0, 123, 0, }, /* 824 */
+ { 123, 10, 3, 0, 0, 123, 0, }, /* 825 */
+ { 123, 10, 5, 0, 0, 123, 0, }, /* 826 */
+ { 123, 12, 3, 0, 0, 123, 0, }, /* 827 */
+ { 123, 21, 12, 0, 0, 123, 0, }, /* 828 */
+ { 114, 7, 12, 0, 0, 114, 0, }, /* 829 */
+ { 114, 10, 5, 0, 0, 114, 0, }, /* 830 */
+ { 114, 12, 3, 0, 0, 114, 0, }, /* 831 */
+ { 114, 21, 12, 0, 0, 114, 0, }, /* 832 */
+ { 114, 13, 12, 0, 0, 114, 0, }, /* 833 */
+ { 102, 7, 12, 0, 0, 102, 0, }, /* 834 */
+ { 102, 12, 3, 0, 0, 102, 0, }, /* 835 */
+ { 102, 10, 5, 0, 0, 102, 0, }, /* 836 */
+ { 102, 13, 12, 0, 0, 102, 0, }, /* 837 */
+ { 126, 7, 12, 0, 0, 126, 0, }, /* 838 */
+ { 126, 12, 3, 0, 0, 126, 0, }, /* 839 */
+ { 126, 10, 5, 0, 0, 126, 0, }, /* 840 */
+ { 126, 13, 12, 0, 0, 126, 0, }, /* 841 */
+ { 126, 15, 12, 0, 0, 126, 0, }, /* 842 */
+ { 126, 21, 12, 0, 0, 126, 0, }, /* 843 */
+ { 126, 26, 12, 0, 0, 126, 0, }, /* 844 */
+ { 142, 7, 12, 0, 0, 142, 0, }, /* 845 */
+ { 142, 10, 5, 0, 0, 142, 0, }, /* 846 */
+ { 142, 12, 3, 0, 0, 142, 0, }, /* 847 */
+ { 142, 21, 12, 0, 0, 142, 0, }, /* 848 */
+ { 125, 9, 12, 0, 32, 125, 0, }, /* 849 */
+ { 125, 5, 12, 0, -32, 125, 0, }, /* 850 */
+ { 125, 13, 12, 0, 0, 125, 0, }, /* 851 */
+ { 125, 15, 12, 0, 0, 125, 0, }, /* 852 */
+ { 125, 7, 12, 0, 0, 125, 0, }, /* 853 */
+ { 150, 7, 12, 0, 0, 150, 0, }, /* 854 */
+ { 150, 10, 5, 0, 0, 150, 0, }, /* 855 */
+ { 150, 12, 3, 0, 0, 150, 0, }, /* 856 */
+ { 150, 21, 12, 0, 0, 150, 0, }, /* 857 */
+ { 141, 7, 12, 0, 0, 141, 0, }, /* 858 */
+ { 141, 12, 3, 0, 0, 141, 0, }, /* 859 */
+ { 141, 10, 5, 0, 0, 141, 0, }, /* 860 */
+ { 141, 7, 4, 0, 0, 141, 0, }, /* 861 */
+ { 141, 21, 12, 0, 0, 141, 0, }, /* 862 */
+ { 140, 7, 12, 0, 0, 140, 0, }, /* 863 */
+ { 140, 12, 3, 0, 0, 140, 0, }, /* 864 */
+ { 140, 10, 5, 0, 0, 140, 0, }, /* 865 */
+ { 140, 7, 4, 0, 0, 140, 0, }, /* 866 */
+ { 140, 21, 12, 0, 0, 140, 0, }, /* 867 */
+ { 122, 7, 12, 0, 0, 122, 0, }, /* 868 */
+ { 133, 7, 12, 0, 0, 133, 0, }, /* 869 */
+ { 133, 10, 5, 0, 0, 133, 0, }, /* 870 */
+ { 133, 12, 3, 0, 0, 133, 0, }, /* 871 */
+ { 133, 21, 12, 0, 0, 133, 0, }, /* 872 */
+ { 133, 13, 12, 0, 0, 133, 0, }, /* 873 */
+ { 133, 15, 12, 0, 0, 133, 0, }, /* 874 */
+ { 134, 21, 12, 0, 0, 134, 0, }, /* 875 */
+ { 134, 7, 12, 0, 0, 134, 0, }, /* 876 */
+ { 134, 12, 3, 0, 0, 134, 0, }, /* 877 */
+ { 134, 10, 5, 0, 0, 134, 0, }, /* 878 */
+ { 138, 7, 12, 0, 0, 138, 0, }, /* 879 */
+ { 138, 12, 3, 0, 0, 138, 0, }, /* 880 */
+ { 138, 7, 4, 0, 0, 138, 0, }, /* 881 */
+ { 138, 13, 12, 0, 0, 138, 0, }, /* 882 */
+ { 143, 7, 12, 0, 0, 143, 0, }, /* 883 */
+ { 143, 10, 5, 0, 0, 143, 0, }, /* 884 */
+ { 143, 12, 3, 0, 0, 143, 0, }, /* 885 */
+ { 143, 13, 12, 0, 0, 143, 0, }, /* 886 */
+ { 145, 7, 12, 0, 0, 145, 0, }, /* 887 */
+ { 145, 12, 3, 0, 0, 145, 0, }, /* 888 */
+ { 145, 10, 5, 0, 0, 145, 0, }, /* 889 */
+ { 145, 21, 12, 0, 0, 145, 0, }, /* 890 */
+ { 54, 15, 12, 0, 0, 54, 0, }, /* 891 */
+ { 54, 21, 12, 0, 0, 54, 0, }, /* 892 */
+ { 63, 7, 12, 0, 0, 63, 0, }, /* 893 */
+ { 63, 14, 12, 0, 0, 63, 0, }, /* 894 */
+ { 63, 21, 12, 0, 0, 63, 0, }, /* 895 */
+ { 80, 7, 12, 0, 0, 80, 0, }, /* 896 */
+ { 80, 1, 2, 0, 0, 80, 0, }, /* 897 */
+ { 127, 7, 12, 0, 0, 127, 0, }, /* 898 */
+ { 115, 7, 12, 0, 0, 115, 0, }, /* 899 */
+ { 115, 13, 12, 0, 0, 115, 0, }, /* 900 */
+ { 115, 21, 12, 0, 0, 115, 0, }, /* 901 */
+ { 103, 7, 12, 0, 0, 103, 0, }, /* 902 */
+ { 103, 12, 3, 0, 0, 103, 0, }, /* 903 */
+ { 103, 21, 12, 0, 0, 103, 0, }, /* 904 */
+ { 119, 7, 12, 0, 0, 119, 0, }, /* 905 */
+ { 119, 12, 3, 0, 0, 119, 0, }, /* 906 */
+ { 119, 21, 12, 0, 0, 119, 0, }, /* 907 */
+ { 119, 26, 12, 0, 0, 119, 0, }, /* 908 */
+ { 119, 6, 12, 0, 0, 119, 0, }, /* 909 */
+ { 119, 13, 12, 0, 0, 119, 0, }, /* 910 */
+ { 119, 15, 12, 0, 0, 119, 0, }, /* 911 */
+ { 146, 9, 12, 0, 32, 146, 0, }, /* 912 */
+ { 146, 5, 12, 0, -32, 146, 0, }, /* 913 */
+ { 146, 15, 12, 0, 0, 146, 0, }, /* 914 */
+ { 146, 21, 12, 0, 0, 146, 0, }, /* 915 */
+ { 99, 7, 12, 0, 0, 99, 0, }, /* 916 */
+ { 99, 12, 3, 0, 0, 99, 0, }, /* 917 */
+ { 99, 10, 5, 0, 0, 99, 0, }, /* 918 */
+ { 99, 6, 12, 0, 0, 99, 0, }, /* 919 */
+ { 137, 6, 12, 0, 0, 137, 0, }, /* 920 */
+ { 139, 6, 12, 0, 0, 139, 0, }, /* 921 */
+ { 137, 7, 12, 0, 0, 137, 0, }, /* 922 */
+ { 139, 7, 12, 0, 0, 139, 0, }, /* 923 */
+ { 105, 7, 12, 0, 0, 105, 0, }, /* 924 */
+ { 105, 26, 12, 0, 0, 105, 0, }, /* 925 */
+ { 105, 12, 3, 0, 0, 105, 0, }, /* 926 */
+ { 105, 21, 12, 0, 0, 105, 0, }, /* 927 */
+ { 10, 1, 2, 0, 0, 105, 0, }, /* 928 */
+ { 10, 10, 3, 0, 0, 10, 0, }, /* 929 */
+ { 10, 10, 5, 0, 0, 10, 0, }, /* 930 */
+ { 20, 12, 3, 0, 0, 20, 0, }, /* 931 */
+ { 131, 26, 12, 0, 0, 131, 0, }, /* 932 */
+ { 131, 12, 3, 0, 0, 131, 0, }, /* 933 */
+ { 131, 21, 12, 0, 0, 131, 0, }, /* 934 */
+ { 18, 12, 3, 0, 0, 18, 0, }, /* 935 */
+ { 151, 7, 12, 0, 0, 151, 0, }, /* 936 */
+ { 151, 12, 3, 0, 0, 151, 0, }, /* 937 */
+ { 151, 6, 12, 0, 0, 151, 0, }, /* 938 */
+ { 151, 13, 12, 0, 0, 151, 0, }, /* 939 */
+ { 151, 26, 12, 0, 0, 151, 0, }, /* 940 */
+ { 152, 7, 12, 0, 0, 152, 0, }, /* 941 */
+ { 152, 12, 3, 0, 0, 152, 0, }, /* 942 */
+ { 152, 13, 12, 0, 0, 152, 0, }, /* 943 */
+ { 152, 23, 12, 0, 0, 152, 0, }, /* 944 */
+ { 113, 7, 12, 0, 0, 113, 0, }, /* 945 */
+ { 113, 15, 12, 0, 0, 113, 0, }, /* 946 */
+ { 113, 12, 3, 0, 0, 113, 0, }, /* 947 */
+ { 132, 9, 12, 0, 34, 132, 0, }, /* 948 */
+ { 132, 5, 12, 0, -34, 132, 0, }, /* 949 */
+ { 132, 12, 3, 0, 0, 132, 0, }, /* 950 */
+ { 132, 6, 12, 0, 0, 132, 0, }, /* 951 */
+ { 132, 13, 12, 0, 0, 132, 0, }, /* 952 */
+ { 132, 21, 12, 0, 0, 132, 0, }, /* 953 */
+ { 0, 2, 14, 0, 0, 0, 0, }, /* 954 */
+ { 10, 26, 11, 0, 0, 10, 0, }, /* 955 */
+ { 27, 26, 12, 0, 0, 27, 0, }, /* 956 */
+ { 10, 24, 3, 0, 0, 10, 0, }, /* 957 */
+ { 10, 1, 3, 0, 0, 10, 0, }, /* 958 */
};
const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */
@@ -1150,37 +1185,37 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F000 */
126,126, 98, 98,127,128,129,130,131,131,132,133,134,135,136,137, /* U+F800 */
138,139,140,141,142,143,144,145,146,147,148,142,149,149,150,142, /* U+10000 */
-151,152,153,154,155,156,157,158,159,160,161,142,162,142,163,142, /* U+10800 */
-164,165,166,167,168,169,170,142,171,172,142,173,174,175,176,142, /* U+11000 */
-177,178,142,142,179,180,142,142,181,182,183,184,142,185,142,142, /* U+11800 */
-186,186,186,186,186,186,186,187,188,186,189,142,142,142,142,142, /* U+12000 */
+151,152,153,154,155,156,157,158,159,160,161,142,162,142,163,164, /* U+10800 */
+165,166,167,168,169,170,171,142,172,173,142,174,175,176,177,142, /* U+11000 */
+178,179,142,180,181,182,142,142,183,184,185,186,142,187,142,188, /* U+11800 */
+189,189,189,189,189,189,189,190,191,189,192,142,142,142,142,142, /* U+12000 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+12800 */
-190,190,190,190,190,190,190,190,191,142,142,142,142,142,142,142, /* U+13000 */
+193,193,193,193,193,193,193,193,194,142,142,142,142,142,142,142, /* U+13000 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+13800 */
-142,142,142,142,142,142,142,142,192,192,192,192,193,142,142,142, /* U+14000 */
+142,142,142,142,142,142,142,142,195,195,195,195,196,142,142,142, /* U+14000 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+14800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+15000 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+15800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+16000 */
-194,194,194,194,195,196,197,198,142,142,142,142,199,200,201,202, /* U+16800 */
-203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, /* U+17000 */
-203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203, /* U+17800 */
-203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,204, /* U+18000 */
-203,203,203,203,203,205,142,142,142,142,142,142,142,142,142,142, /* U+18800 */
+197,197,197,197,198,199,200,201,142,142,142,142,202,203,204,205, /* U+16800 */
+206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, /* U+17000 */
+206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, /* U+17800 */
+206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,207, /* U+18000 */
+206,206,206,206,206,208,142,142,142,142,142,142,142,142,142,142, /* U+18800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+19000 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+19800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1A000 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1A800 */
-206,207,208,209,209,210,142,142,142,142,142,142,142,142,142,142, /* U+1B000 */
-142,142,142,142,142,142,142,142,211,212,142,142,142,142,142,142, /* U+1B800 */
+209,210,211,212,212,213,142,142,142,142,142,142,142,142,142,142, /* U+1B000 */
+142,142,142,142,142,142,142,142,214,215,142,142,142,142,142,142, /* U+1B800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1C000 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1C800 */
- 71,213,214,215,216,217,218,142,219,220,221,222,223,224,225,226, /* U+1D000 */
-227,227,227,227,228,229,142,142,142,142,142,142,142,142,142,142, /* U+1D800 */
-230,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1E000 */
-231,232,233,142,142,142,142,142,234,235,142,142,236,237,142,142, /* U+1E800 */
-238,239,240,241,242,243,244,245,244,244,246,244,247,248,249,250, /* U+1F000 */
-251,252,253,254,255,243,243,243,243,243,243,243,243,243,243,256, /* U+1F800 */
+ 71,216,217,218,219,220,221,142,222,223,224,225,226,227,228,229, /* U+1D000 */
+230,230,230,230,231,232,142,142,142,142,142,142,142,142,142,142, /* U+1D800 */
+233,142,234,142,142,235,142,142,142,142,142,142,142,142,142,142, /* U+1E000 */
+236,237,238,142,142,142,142,142,239,240,241,142,242,243,142,142, /* U+1E800 */
+244,245,246,247,248,249,250,251,250,250,252,250,253,254,255,256, /* U+1F000 */
+257,258,259,260,261,262,249,249,249,249,249,249,249,249,249,263, /* U+1F800 */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+20000 */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+20800 */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+21000 */
@@ -1201,18 +1236,18 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+28800 */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+29000 */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+29800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,257, 98, 98, /* U+2A000 */
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,264, 98, 98, /* U+2A000 */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2A800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,258, 98, /* U+2B000 */
-259, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2B800 */
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,265, 98, /* U+2B000 */
+266, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2B800 */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2C000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,260, 98, 98, /* U+2C800 */
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,267, 98, 98, /* U+2C800 */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2D000 */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2D800 */
98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2E000 */
- 98, 98, 98, 98, 98, 98, 98,261,142,142,142,142,142,142,142,142, /* U+2E800 */
+ 98, 98, 98, 98, 98, 98, 98,268,142,142,142,142,142,142,142,142, /* U+2E800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+2F000 */
- 98, 98, 98, 98,262,142,142,142,142,142,142,142,142,142,142,142, /* U+2F800 */
+ 98, 98, 98, 98,269,142,142,142,142,142,142,142,142,142,142,142, /* U+2F800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+30000 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+30800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+31000 */
@@ -1565,8 +1600,8 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DE800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DF000 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DF800 */
-263,264,265,266,264,264,264,264,264,264,264,264,264,264,264,264, /* U+E0000 */
-264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, /* U+E0800 */
+270,271,272,273,271,271,271,271,271,271,271,271,271,271,271,271, /* U+E0000 */
+271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, /* U+E0800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E1000 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E1800 */
142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E2000 */
@@ -1628,7 +1663,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FE000 */
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FE800 */
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FF000 */
-126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,267, /* U+FF800 */
+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,274, /* U+FF800 */
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+100000 */
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+100800 */
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+101000 */
@@ -1660,10 +1695,10 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10E000 */
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10E800 */
126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10F000 */
-126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,267, /* U+10F800 */
+126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,274, /* U+10F800 */
};
-const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
+const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */
/* block 0 */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -1715,534 +1750,534 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
35, 97, 98, 35, 35, 99, 35, 35, 35, 35, 35, 35, 35,100, 35, 35,
/* block 5 */
-101, 35, 35,101, 35, 35, 35,102,101,103,104,104,105, 35, 35, 35,
- 35, 35,106, 35, 22, 35, 35, 35, 35, 35, 35, 35, 35,107,108, 35,
+101, 35,102,101, 35, 35, 35,103,101,104,105,105,106, 35, 35, 35,
+ 35, 35,107, 35, 22, 35, 35, 35, 35, 35, 35, 35, 35,108,109, 35,
35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-109,109,109,109,109,109,109,109,109,110,110,110,110,110,110,110,
-110,110, 15, 15, 15, 15,110,110,110,110,110,110,110,110,110,110,
-110,110, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-109,109,109,109,109, 15, 15, 15, 15, 15,111,111,110, 15,110, 15,
+110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,
+111,111, 15, 15, 15, 15,111,111,111,111,111,111,111,111,111,111,
+111,111, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+110,110,110,110,110, 15, 15, 15, 15, 15,112,112,111, 15,111, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
/* block 6 */
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,113,112,112,114,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,115,115,115,115,115,115,115,115,115,115,115,115,115,
-116,117,116,117,110,118,116,117,119,119,120,121,121,121, 5,122,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,114,113,113,115,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,116,116,116,116,116,116,116,116,116,116,116,116,116,
+117,118,117,118,111,119,117,118,120,120,121,122,122,122, 5,123,
/* block 7 */
-119,119,119,119,118, 15,123, 5,124,124,124,119,125,119,126,126,
-127,128,129,128,128,130,128,128,131,132,133,128,134,128,128,128,
-135,136,119,137,128,128,138,128,128,139,128,128,140,141,141,141,
-127,142,143,142,142,144,142,142,145,146,147,142,148,142,142,142,
-149,150,151,152,142,142,153,142,142,154,142,142,155,156,156,157,
-158,159,160,160,160,161,162,163,116,117,116,117,116,117,116,117,
-116,117,164,165,164,165,164,165,164,165,164,165,164,165,164,165,
-166,167,168,169,170,171,172,116,117,173,116,117,127,174,174,174,
+120,120,120,120,119, 15,124, 5,125,125,125,120,126,120,127,127,
+128,129,130,129,129,131,129,129,132,133,134,129,135,129,129,129,
+136,137,120,138,129,129,139,129,129,140,129,129,141,142,142,142,
+128,143,144,143,143,145,143,143,146,147,148,143,149,143,143,143,
+150,151,152,153,143,143,154,143,143,155,143,143,156,157,157,158,
+159,160,161,161,161,162,163,164,117,118,117,118,117,118,117,118,
+117,118,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
+167,168,169,170,171,172,173,117,118,174,117,118,128,175,175,175,
/* block 8 */
-175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,
-176,176,177,176,178,176,176,176,176,176,176,176,176,176,179,176,
-176,180,181,176,176,176,176,176,176,176,182,176,176,176,176,176,
-183,183,184,183,185,183,183,183,183,183,183,183,183,183,186,183,
-183,187,188,183,183,183,183,183,183,183,189,183,183,183,183,183,
-190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,
-191,192,193,194,191,192,191,192,191,192,191,192,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
+177,177,178,177,179,177,177,177,177,177,177,177,177,177,180,177,
+177,181,182,177,177,177,177,177,177,177,183,177,177,177,177,177,
+184,184,185,184,186,184,184,184,184,184,184,184,184,184,187,184,
+184,188,189,184,184,184,184,184,184,184,190,184,184,184,184,184,
+191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+192,193,194,195,192,193,192,193,192,193,192,193,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
/* block 9 */
-191,192,195,196,197,198,198,197,199,199,191,192,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
-200,191,192,191,192,191,192,191,192,191,192,191,192,191,192,201,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
+192,193,196,197,198,199,199,198,200,200,192,193,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+201,192,193,192,193,192,193,192,193,192,193,192,193,192,193,202,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
/* block 10 */
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
-119,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,
-202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,
-202,202,202,202,202,202,202,119,119,203,204,204,204,204,204,204,
-205,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,
-206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+120,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,
+203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,
+203,203,203,203,203,203,203,120,120,204,205,205,205,205,205,205,
+206,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,
+207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,
/* block 11 */
-206,206,206,206,206,206,206,205,205,207,208,119,119,209,209,210,
-119,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,
-211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,
-211,211,211,211,211,211,211,211,211,211,211,211,211,211,212,211,
-213,211,211,213,211,211,213,211,119,119,119,119,119,119,119,119,
-214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,
-214,214,214,214,214,214,214,214,214,214,214,119,119,119,119,214,
-214,214,214,213,213,119,119,119,119,119,119,119,119,119,119,119,
+207,207,207,207,207,207,207,206,206,208,209,120,120,210,210,211,
+120,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
+212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
+212,212,212,212,212,212,212,212,212,212,212,212,212,212,213,212,
+214,212,212,214,212,212,214,212,120,120,120,120,120,120,120,120,
+215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,
+215,215,215,215,215,215,215,215,215,215,215,120,120,120,120,215,
+215,215,215,214,214,120,120,120,120,120,120,120,120,120,120,120,
/* block 12 */
-215,215,215,215,215,216,217,217,217,218,218,219,220,218,221,221,
-222,222,222,222,222,222,222,222,222,222,222,220,223,119,218,220,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-225,224,224,224,224,224,224,224,224,224,224,226,226,226,226,226,
-226,226,226,226,226,226,222,222,222,222,222,222,222,222,222,222,
-227,227,227,227,227,227,227,227,227,227,218,218,218,218,224,224,
-226,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
+216,216,216,216,216,217,218,218,218,219,219,220,221,219,222,222,
+223,223,223,223,223,223,223,223,223,223,223,221,224,120,219,221,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+226,225,225,225,225,225,225,225,225,225,225,227,227,227,227,227,
+227,227,227,227,227,227,223,223,223,223,223,223,223,223,223,223,
+228,228,228,228,228,228,228,228,228,228,219,219,219,219,225,225,
+227,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
/* block 13 */
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,228,224,222,222,222,222,222,222,222,216,221,222,
-222,222,222,222,222,229,229,222,222,221,222,222,222,222,224,224,
-230,230,230,230,230,230,230,230,230,230,224,224,224,221,221,224,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,229,225,223,223,223,223,223,223,223,217,222,223,
+223,223,223,223,223,230,230,223,223,222,223,223,223,223,225,225,
+231,231,231,231,231,231,231,231,231,231,225,225,225,222,222,225,
/* block 14 */
-231,231,231,231,231,231,231,231,231,231,231,231,231,231,119,232,
-233,234,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
-233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
+232,232,232,232,232,232,232,232,232,232,232,232,232,232,120,233,
+234,235,234,234,234,234,234,234,234,234,234,234,234,234,234,234,
234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,
-234,234,234,234,234,234,234,234,234,234,234,119,119,233,233,233,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
+235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
+235,235,235,235,235,235,235,235,235,235,235,120,120,234,234,234,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
/* block 15 */
-235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
-235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
-235,235,235,235,235,235,236,236,236,236,236,236,236,236,236,236,
-236,235,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-237,237,237,237,237,237,237,237,237,237,238,238,238,238,238,238,
-238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,
-238,238,238,238,238,238,238,238,238,238,238,239,239,239,239,239,
-239,239,239,239,240,240,241,242,242,242,240,119,119,239,243,243,
+236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
+236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
+236,236,236,236,236,236,237,237,237,237,237,237,237,237,237,237,
+237,236,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+238,238,238,238,238,238,238,238,238,238,239,239,239,239,239,239,
+239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,
+239,239,239,239,239,239,239,239,239,239,239,240,240,240,240,240,
+240,240,240,240,241,241,242,243,243,243,241,120,120,240,244,244,
/* block 16 */
-244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
-244,244,244,244,244,244,245,245,245,245,246,245,245,245,245,245,
-245,245,245,245,246,245,245,245,246,245,245,245,245,245,119,119,
-247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,119,
-248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
-248,248,248,248,248,248,248,248,248,249,249,249,119,119,250,119,
-233,233,233,233,233,233,233,233,233,233,233,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
+245,245,245,245,245,245,246,246,246,246,247,246,246,246,246,246,
+246,246,246,246,247,246,246,246,247,246,246,246,246,246,120,120,
+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,120,
+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
+249,249,249,249,249,249,249,249,249,250,250,250,120,120,251,120,
+234,234,234,234,234,234,234,234,234,234,234,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 17 */
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,119,224,224,224,224,224,224,224,224,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,222,222,222,222,222,222,222,222,222,222,222,222,222,
-222,222,216,222,222,222,222,222,222,222,222,222,222,222,222,222,
-222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,120,225,225,225,225,225,225,225,225,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,223,223,223,223,223,223,223,223,223,223,223,223,223,
+223,223,217,223,223,223,223,223,223,223,223,223,223,223,223,223,
+223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
/* block 18 */
-251,251,251,252,253,253,253,253,253,253,253,253,253,253,253,253,
-253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
-253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
-253,253,253,253,253,253,253,253,253,253,251,252,251,253,252,252,
-252,251,251,251,251,251,251,251,251,252,252,252,252,251,252,252,
-253,254,255,251,251,251,251,251,253,253,253,253,253,253,253,253,
-253,253,251,251,256,257,258,258,258,258,258,258,258,258,258,258,
-259,260,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
+252,252,252,253,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,252,253,252,254,253,253,
+253,252,252,252,252,252,252,252,252,253,253,253,253,252,253,253,
+254,255,256,113,113,252,252,252,254,254,254,254,254,254,254,254,
+254,254,252,252,257,258,259,259,259,259,259,259,259,259,259,259,
+260,261,254,254,254,254,254,254,254,254,254,254,254,254,254,254,
/* block 19 */
-261,262,263,263,119,261,261,261,261,261,261,261,261,119,119,261,
-261,119,119,261,261,261,261,261,261,261,261,261,261,261,261,261,
-261,261,261,261,261,261,261,261,261,119,261,261,261,261,261,261,
-261,119,261,119,119,119,261,261,261,261,119,119,262,261,264,263,
-263,262,262,262,262,119,119,263,263,119,119,263,263,262,261,119,
-119,119,119,119,119,119,119,264,119,119,119,119,261,261,119,261,
-261,261,262,262,119,119,265,265,265,265,265,265,265,265,265,265,
-261,261,266,266,267,267,267,267,267,267,268,266,261,269,262,119,
+262,263,264,264,120,262,262,262,262,262,262,262,262,120,120,262,
+262,120,120,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,120,262,262,262,262,262,262,
+262,120,262,120,120,120,262,262,262,262,120,120,263,262,265,264,
+264,263,263,263,263,120,120,264,264,120,120,264,264,263,262,120,
+120,120,120,120,120,120,120,265,120,120,120,120,262,262,120,262,
+262,262,263,263,120,120,266,266,266,266,266,266,266,266,266,266,
+262,262,267,267,268,268,268,268,268,268,269,267,262,270,263,120,
/* block 20 */
-119,270,270,271,119,272,272,272,272,272,272,119,119,119,119,272,
-272,119,119,272,272,272,272,272,272,272,272,272,272,272,272,272,
-272,272,272,272,272,272,272,272,272,119,272,272,272,272,272,272,
-272,119,272,272,119,272,272,119,272,272,119,119,270,119,271,271,
-271,270,270,119,119,119,119,270,270,119,119,270,270,270,119,119,
-119,270,119,119,119,119,119,119,119,272,272,272,272,119,272,119,
-119,119,119,119,119,119,273,273,273,273,273,273,273,273,273,273,
-270,270,272,272,272,270,274,119,119,119,119,119,119,119,119,119,
+120,271,271,272,120,273,273,273,273,273,273,120,120,120,120,273,
+273,120,120,273,273,273,273,273,273,273,273,273,273,273,273,273,
+273,273,273,273,273,273,273,273,273,120,273,273,273,273,273,273,
+273,120,273,273,120,273,273,120,273,273,120,120,271,120,272,272,
+272,271,271,120,120,120,120,271,271,120,120,271,271,271,120,120,
+120,271,120,120,120,120,120,120,120,273,273,273,273,120,273,120,
+120,120,120,120,120,120,274,274,274,274,274,274,274,274,274,274,
+271,271,273,273,273,271,275,120,120,120,120,120,120,120,120,120,
/* block 21 */
-119,275,275,276,119,277,277,277,277,277,277,277,277,277,119,277,
-277,277,119,277,277,277,277,277,277,277,277,277,277,277,277,277,
-277,277,277,277,277,277,277,277,277,119,277,277,277,277,277,277,
-277,119,277,277,119,277,277,277,277,277,119,119,275,277,276,276,
-276,275,275,275,275,275,119,275,275,276,119,276,276,275,119,119,
-277,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-277,277,275,275,119,119,278,278,278,278,278,278,278,278,278,278,
-279,280,119,119,119,119,119,119,119,277,275,275,275,275,275,275,
+120,276,276,277,120,278,278,278,278,278,278,278,278,278,120,278,
+278,278,120,278,278,278,278,278,278,278,278,278,278,278,278,278,
+278,278,278,278,278,278,278,278,278,120,278,278,278,278,278,278,
+278,120,278,278,120,278,278,278,278,278,120,120,276,278,277,277,
+277,276,276,276,276,276,120,276,276,277,120,277,277,276,120,120,
+278,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+278,278,276,276,120,120,279,279,279,279,279,279,279,279,279,279,
+280,281,120,120,120,120,120,120,120,278,276,276,276,276,276,276,
/* block 22 */
-119,281,282,282,119,283,283,283,283,283,283,283,283,119,119,283,
-283,119,119,283,283,283,283,283,283,283,283,283,283,283,283,283,
-283,283,283,283,283,283,283,283,283,119,283,283,283,283,283,283,
-283,119,283,283,119,283,283,283,283,283,119,119,281,283,284,281,
-282,281,281,281,281,119,119,282,282,119,119,282,282,281,119,119,
-119,119,119,119,119,119,281,284,119,119,119,119,283,283,119,283,
-283,283,281,281,119,119,285,285,285,285,285,285,285,285,285,285,
-286,283,287,287,287,287,287,287,119,119,119,119,119,119,119,119,
+120,282,283,283,120,284,284,284,284,284,284,284,284,120,120,284,
+284,120,120,284,284,284,284,284,284,284,284,284,284,284,284,284,
+284,284,284,284,284,284,284,284,284,120,284,284,284,284,284,284,
+284,120,284,284,120,284,284,284,284,284,120,120,282,284,285,282,
+283,282,282,282,282,120,120,283,283,120,120,283,283,282,120,120,
+120,120,120,120,120,120,282,285,120,120,120,120,284,284,120,284,
+284,284,282,282,120,120,286,286,286,286,286,286,286,286,286,286,
+287,284,288,288,288,288,288,288,120,120,120,120,120,120,120,120,
/* block 23 */
-119,119,288,289,119,289,289,289,289,289,289,119,119,119,289,289,
-289,119,289,289,289,289,119,119,119,289,289,119,289,119,289,289,
-119,119,119,289,289,119,119,119,289,289,289,119,119,119,289,289,
-289,289,289,289,289,289,289,289,289,289,119,119,119,119,290,291,
-288,291,291,119,119,119,291,291,291,119,291,291,291,288,119,119,
-289,119,119,119,119,119,119,290,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,292,292,292,292,292,292,292,292,292,292,
-293,293,293,294,295,295,295,295,295,296,295,119,119,119,119,119,
+120,120,289,290,120,290,290,290,290,290,290,120,120,120,290,290,
+290,120,290,290,290,290,120,120,120,290,290,120,290,120,290,290,
+120,120,120,290,290,120,120,120,290,290,290,120,120,120,290,290,
+290,290,290,290,290,290,290,290,290,290,120,120,120,120,291,292,
+289,292,292,120,120,120,292,292,292,120,292,292,292,289,120,120,
+290,120,120,120,120,120,120,291,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,293,293,293,293,293,293,293,293,293,293,
+294,294,294,295,296,296,296,296,296,297,296,120,120,120,120,120,
/* block 24 */
-297,298,298,298,297,299,299,299,299,299,299,299,299,119,299,299,
-299,119,299,299,299,299,299,299,299,299,299,299,299,299,299,299,
-299,299,299,299,299,299,299,299,299,119,299,299,299,299,299,299,
-299,299,299,299,299,299,299,299,299,299,119,119,119,299,297,297,
-297,298,298,298,298,119,297,297,297,119,297,297,297,297,119,119,
-119,119,119,119,119,297,297,119,299,299,299,119,119,119,119,119,
-299,299,297,297,119,119,300,300,300,300,300,300,300,300,300,300,
-119,119,119,119,119,119,119,119,301,301,301,301,301,301,301,302,
+298,299,299,299,298,300,300,300,300,300,300,300,300,120,300,300,
+300,120,300,300,300,300,300,300,300,300,300,300,300,300,300,300,
+300,300,300,300,300,300,300,300,300,120,300,300,300,300,300,300,
+300,300,300,300,300,300,300,300,300,300,120,120,120,300,298,298,
+298,299,299,299,299,120,298,298,298,120,298,298,298,298,120,120,
+120,120,120,120,120,298,298,120,300,300,300,120,120,120,120,120,
+300,300,298,298,120,120,301,301,301,301,301,301,301,301,301,301,
+120,120,120,120,120,120,120,302,303,303,303,303,303,303,303,304,
/* block 25 */
-303,304,305,305,306,303,303,303,303,303,303,303,303,119,303,303,
-303,119,303,303,303,303,303,303,303,303,303,303,303,303,303,303,
-303,303,303,303,303,303,303,303,303,119,303,303,303,303,303,303,
-303,303,303,303,119,303,303,303,303,303,119,119,304,303,305,304,
-305,305,307,305,305,119,304,305,305,119,305,305,304,304,119,119,
-119,119,119,119,119,307,307,119,119,119,119,119,119,119,303,119,
-303,303,304,304,119,119,308,308,308,308,308,308,308,308,308,308,
-119,303,303,119,119,119,119,119,119,119,119,119,119,119,119,119,
+305,306,307,307,308,305,305,305,305,305,305,305,305,120,305,305,
+305,120,305,305,305,305,305,305,305,305,305,305,305,305,305,305,
+305,305,305,305,305,305,305,305,305,120,305,305,305,305,305,305,
+305,305,305,305,120,305,305,305,305,305,120,120,306,305,307,306,
+307,307,309,307,307,120,306,307,307,120,307,307,306,306,120,120,
+120,120,120,120,120,309,309,120,120,120,120,120,120,120,305,120,
+305,305,306,306,120,120,310,310,310,310,310,310,310,310,310,310,
+120,305,305,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 26 */
-309,309,310,310,119,311,311,311,311,311,311,311,311,119,311,311,
-311,119,311,311,311,311,311,311,311,311,311,311,311,311,311,311,
-311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,
-311,311,311,311,311,311,311,311,311,311,311,309,309,311,312,310,
-310,309,309,309,309,119,310,310,310,119,310,310,310,309,313,314,
-119,119,119,119,311,311,311,312,315,315,315,315,315,315,315,311,
-311,311,309,309,119,119,316,316,316,316,316,316,316,316,316,316,
-315,315,315,315,315,315,315,315,315,314,311,311,311,311,311,311,
+311,311,312,312,120,313,313,313,313,313,313,313,313,120,313,313,
+313,120,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
+313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
+313,313,313,313,313,313,313,313,313,313,313,311,311,313,314,312,
+312,311,311,311,311,120,312,312,312,120,312,312,312,311,315,316,
+120,120,120,120,313,313,313,314,317,317,317,317,317,317,317,313,
+313,313,311,311,120,120,318,318,318,318,318,318,318,318,318,318,
+317,317,317,317,317,317,317,317,317,316,313,313,313,313,313,313,
/* block 27 */
-119,119,317,317,119,318,318,318,318,318,318,318,318,318,318,318,
-318,318,318,318,318,318,318,119,119,119,318,318,318,318,318,318,
-318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,
-318,318,119,318,318,318,318,318,318,318,318,318,119,318,119,119,
-318,318,318,318,318,318,318,119,119,119,319,119,119,119,119,320,
-317,317,319,319,319,119,319,119,317,317,317,317,317,317,317,320,
-119,119,119,119,119,119,321,321,321,321,321,321,321,321,321,321,
-119,119,317,317,322,119,119,119,119,119,119,119,119,119,119,119,
+120,120,319,319,120,320,320,320,320,320,320,320,320,320,320,320,
+320,320,320,320,320,320,320,120,120,120,320,320,320,320,320,320,
+320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,
+320,320,120,320,320,320,320,320,320,320,320,320,120,320,120,120,
+320,320,320,320,320,320,320,120,120,120,321,120,120,120,120,322,
+319,319,321,321,321,120,321,120,319,319,319,319,319,319,319,322,
+120,120,120,120,120,120,323,323,323,323,323,323,323,323,323,323,
+120,120,319,319,324,120,120,120,120,120,120,120,120,120,120,120,
/* block 28 */
-119,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
-323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
-323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
-323,324,323,325,324,324,324,324,324,324,324,119,119,119,119, 6,
-323,323,323,323,323,323,326,324,324,324,324,324,324,324,324,327,
-328,328,328,328,328,328,328,328,328,328,327,327,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+120,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,
+325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,
+325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,
+325,326,325,327,326,326,326,326,326,326,326,120,120,120,120, 6,
+325,325,325,325,325,325,328,326,326,326,326,326,326,326,326,329,
+330,330,330,330,330,330,330,330,330,330,329,329,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 29 */
-119,329,329,119,329,119,119,329,329,119,329,119,119,329,119,119,
-119,119,119,119,329,329,329,329,119,329,329,329,329,329,329,329,
-119,329,329,329,119,329,119,329,119,119,329,329,119,329,329,329,
-329,330,329,331,330,330,330,330,330,330,119,330,330,329,119,119,
-329,329,329,329,329,119,332,119,330,330,330,330,330,330,119,119,
-333,333,333,333,333,333,333,333,333,333,119,119,329,329,329,329,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+120,331,331,120,331,120,331,331,331,331,331,120,331,331,331,331,
+331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,
+331,331,331,331,120,331,120,331,331,331,331,331,331,331,331,331,
+331,332,331,333,332,332,332,332,332,332,332,332,332,331,120,120,
+331,331,331,331,331,120,334,120,332,332,332,332,332,332,120,120,
+335,335,335,335,335,335,335,335,335,335,120,120,331,331,331,331,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 30 */
-334,335,335,335,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,336,335,336,335,335,335,337,337,335,335,335,335,335,335,
-338,338,338,338,338,338,338,338,338,338,339,339,339,339,339,339,
-339,339,339,339,335,337,335,337,335,337,340,341,340,341,342,342,
-334,334,334,334,334,334,334,334,119,334,334,334,334,334,334,334,
-334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,
-334,334,334,334,334,334,334,334,334,334,334,334,334,119,119,119,
-119,337,337,337,337,337,337,337,337,337,337,337,337,337,337,342,
+336,337,337,337,338,338,338,338,338,338,338,338,338,338,338,338,
+338,338,338,337,338,337,337,337,339,339,337,337,337,337,337,337,
+340,340,340,340,340,340,340,340,340,340,341,341,341,341,341,341,
+341,341,341,341,337,339,337,339,337,339,342,343,342,343,344,344,
+336,336,336,336,336,336,336,336,120,336,336,336,336,336,336,336,
+336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
+336,336,336,336,336,336,336,336,336,336,336,336,336,120,120,120,
+120,339,339,339,339,339,339,339,339,339,339,339,339,339,339,344,
/* block 31 */
-337,337,337,337,337,336,337,337,334,334,334,334,334,337,337,337,
-337,337,337,337,337,337,337,337,119,337,337,337,337,337,337,337,
-337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,
-337,337,337,337,337,337,337,337,337,337,337,337,337,119,335,335,
-335,335,335,335,335,335,337,335,335,335,335,335,335,119,335,335,
-336,336,336,336,336, 20, 20, 20, 20,336,336,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+339,339,339,339,339,338,339,339,336,336,336,336,336,339,339,339,
+339,339,339,339,339,339,339,339,120,339,339,339,339,339,339,339,
+339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
+339,339,339,339,339,339,339,339,339,339,339,339,339,120,337,337,
+337,337,337,337,337,337,339,337,337,337,337,337,337,120,337,337,
+338,338,338,338,338, 20, 20, 20, 20,338,338,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 32 */
-343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,
-343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,
-343,343,343,343,343,343,343,343,343,343,343,344,344,345,345,345,
-345,346,345,345,345,345,345,345,344,345,345,346,346,345,345,343,
-347,347,347,347,347,347,347,347,347,347,348,348,348,348,348,348,
-343,343,343,343,343,343,346,346,345,345,343,343,343,343,345,345,
-345,343,344,344,344,343,343,344,344,344,344,344,344,344,343,343,
-343,345,345,345,345,343,343,343,343,343,343,343,343,343,343,343,
+345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
+345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
+345,345,345,345,345,345,345,345,345,345,345,346,346,347,347,347,
+347,348,347,347,347,347,347,347,346,347,347,348,348,347,347,345,
+349,349,349,349,349,349,349,349,349,349,350,350,350,350,350,350,
+345,345,345,345,345,345,348,348,347,347,345,345,345,345,347,347,
+347,345,346,346,346,345,345,346,346,346,346,346,346,346,345,345,
+345,347,347,347,347,345,345,345,345,345,345,345,345,345,345,345,
/* block 33 */
-343,343,345,344,346,345,345,344,344,344,344,344,344,345,343,344,
-349,349,349,349,349,349,349,349,349,349,344,344,344,345,350,350,
-351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,
-351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,
-351,351,351,351,351,351,119,351,119,119,119,119,119,351,119,119,
-352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,
-352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,
-352,352,352,352,352,352,352,352,352,352,352,353,354,352,352,352,
+345,345,347,346,348,347,347,346,346,346,346,346,346,347,345,346,
+351,351,351,351,351,351,351,351,351,351,346,346,346,347,352,352,
+353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
+353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
+353,353,353,353,353,353,120,353,120,120,120,120,120,353,120,120,
+354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,
+354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,
+354,354,354,354,354,354,354,354,354,354,354,355,356,354,354,354,
/* block 34 */
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
-356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
-
-/* block 35 */
-356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
-356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
-356,356,356,356,356,356,356,356,357,357,357,357,357,357,357,357,
357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
-
-/* block 36 */
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
+357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,119,358,358,358,358,119,119,
-358,358,358,358,358,358,358,119,358,119,358,358,358,358,119,119,
+
+/* block 35 */
358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
+358,358,358,358,358,358,358,358,359,359,359,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+
+/* block 36 */
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,120,360,360,360,360,120,120,
+360,360,360,360,360,360,360,120,360,120,360,360,360,360,120,120,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
/* block 37 */
-358,358,358,358,358,358,358,358,358,119,358,358,358,358,119,119,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,119,358,358,358,358,119,119,358,358,358,358,358,358,358,119,
-358,119,358,358,358,358,119,119,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,119,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
+360,360,360,360,360,360,360,360,360,120,360,360,360,360,120,120,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,120,360,360,360,360,120,120,360,360,360,360,360,360,360,120,
+360,120,360,360,360,360,120,120,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
/* block 38 */
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,119,358,358,358,358,119,119,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,119,119,359,359,359,
-360,360,360,360,360,360,360,360,360,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,119,119,119,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,120,360,360,360,360,120,120,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,120,120,361,361,361,
+362,362,362,362,362,362,362,362,362,363,363,363,363,363,363,363,
+363,363,363,363,363,363,363,363,363,363,363,363,363,120,120,120,
/* block 39 */
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-362,362,362,362,362,362,362,362,362,362,119,119,119,119,119,119,
-363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,
-363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,
-363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,
-363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,
-363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,
-364,364,364,364,364,364,119,119,365,365,365,365,365,365,119,119,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+364,364,364,364,364,364,364,364,364,364,120,120,120,120,120,120,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+366,366,366,366,366,366,120,120,367,367,367,367,367,367,120,120,
/* block 40 */
-366,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
+368,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
/* block 41 */
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
/* block 42 */
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,368,368,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,370,371,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
/* block 43 */
-369,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,371,372,119,119,119,
-373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
-373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
-373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
-373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
-373,373,373,373,373,373,373,373,373,373,373, 5, 5, 5,374,374,
-374,373,373,373,373,373,373,373,373,119,119,119,119,119,119,119,
+372,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
+373,373,373,373,373,373,373,373,373,373,373,374,375,120,120,120,
+376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,
+376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,
+376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,
+376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,
+376,376,376,376,376,376,376,376,376,376,376, 5, 5, 5,377,377,
+377,376,376,376,376,376,376,376,376,120,120,120,120,120,120,120,
/* block 44 */
-375,375,375,375,375,375,375,375,375,375,375,375,375,119,375,375,
-375,375,376,376,376,119,119,119,119,119,119,119,119,119,119,119,
-377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,
-377,377,378,378,378,379,379,119,119,119,119,119,119,119,119,119,
+378,378,378,378,378,378,378,378,378,378,378,378,378,120,378,378,
+378,378,379,379,379,120,120,120,120,120,120,120,120,120,120,120,
380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,
-380,380,381,381,119,119,119,119,119,119,119,119,119,119,119,119,
-382,382,382,382,382,382,382,382,382,382,382,382,382,119,382,382,
-382,119,383,383,119,119,119,119,119,119,119,119,119,119,119,119,
+380,380,381,381,381,382,382,120,120,120,120,120,120,120,120,120,
+383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,
+383,383,384,384,120,120,120,120,120,120,120,120,120,120,120,120,
+385,385,385,385,385,385,385,385,385,385,385,385,385,120,385,385,
+385,120,386,386,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 45 */
-384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,
-384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,
-384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,
-384,384,384,384,385,385,386,385,385,385,385,385,385,385,386,386,
-386,386,386,386,386,386,385,386,386,385,385,385,385,385,385,385,
-385,385,385,385,387,387,387,388,387,387,387,389,384,385,119,119,
-390,390,390,390,390,390,390,390,390,390,119,119,119,119,119,119,
-391,391,391,391,391,391,391,391,391,391,119,119,119,119,119,119,
+387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
+387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
+387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
+387,387,387,387,388,388,389,388,388,388,388,388,388,388,389,389,
+389,389,389,389,389,389,388,389,389,388,388,388,388,388,388,388,
+388,388,388,388,390,390,390,391,390,390,390,392,387,388,120,120,
+393,393,393,393,393,393,393,393,393,393,120,120,120,120,120,120,
+394,394,394,394,394,394,394,394,394,394,120,120,120,120,120,120,
/* block 46 */
-392,392,393,393,392,393,394,392,392,392,392,395,395,395,396,119,
-397,397,397,397,397,397,397,397,397,397,119,119,119,119,119,119,
-398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,
-398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,
-398,398,398,399,398,398,398,398,398,398,398,398,398,398,398,398,
-398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,
-398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,
-398,398,398,398,398,398,398,398,398,119,119,119,119,119,119,119,
+395,395,396,396,395,396,397,395,395,395,395,398,398,398,399,120,
+400,400,400,400,400,400,400,400,400,400,120,120,120,120,120,120,
+401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,
+401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,
+401,401,401,402,401,401,401,401,401,401,401,401,401,401,401,401,
+401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,
+401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,
+401,401,401,401,401,401,401,401,401,120,120,120,120,120,120,120,
/* block 47 */
-398,398,398,398,398,395,395,398,398,398,398,398,398,398,398,398,
-398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,
-398,398,398,398,398,398,398,398,398,395,398,119,119,119,119,119,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
-367,367,367,367,367,367,119,119,119,119,119,119,119,119,119,119,
+401,401,401,401,401,398,398,401,401,401,401,401,401,401,401,401,
+401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,
+401,401,401,401,401,401,401,401,401,398,401,120,120,120,120,120,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,120,120,120,120,120,120,120,120,120,120,
/* block 48 */
-400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,
-400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,119,
-401,401,401,402,402,402,402,401,401,402,402,402,119,119,119,119,
-402,402,401,402,402,402,402,402,402,401,401,401,119,119,119,119,
-403,119,119,119,404,404,405,405,405,405,405,405,405,405,405,405,
-406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,
-406,406,406,406,406,406,406,406,406,406,406,406,406,406,119,119,
-406,406,406,406,406,119,119,119,119,119,119,119,119,119,119,119,
+403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,
+403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,120,
+404,404,404,405,405,405,405,404,404,405,405,405,120,120,120,120,
+405,405,404,405,405,405,405,405,405,404,404,404,120,120,120,120,
+406,120,120,120,407,407,408,408,408,408,408,408,408,408,408,408,
+409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,
+409,409,409,409,409,409,409,409,409,409,409,409,409,409,120,120,
+409,409,409,409,409,120,120,120,120,120,120,120,120,120,120,120,
/* block 49 */
-407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,
-407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,
-407,407,407,407,407,407,407,407,407,407,407,407,119,119,119,119,
-407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,
-407,407,407,407,407,407,407,407,407,407,119,119,119,119,119,119,
-408,408,408,408,408,408,408,408,408,408,409,119,119,119,410,410,
-411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,
-411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,
+410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+410,410,410,410,410,410,410,410,410,410,410,410,120,120,120,120,
+410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+410,410,410,410,410,410,410,410,410,410,120,120,120,120,120,120,
+411,411,411,411,411,411,411,411,411,411,412,120,120,120,413,413,
+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
+414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
/* block 50 */
-412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
-412,412,412,412,412,412,412,413,413,414,414,413,119,119,415,415,
-416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
-416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
-416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,
-416,416,416,416,416,417,418,417,418,418,418,418,418,418,418,119,
-418,419,418,419,419,418,418,418,418,418,418,418,418,417,417,417,
-417,417,417,418,418,418,418,418,418,418,418,418,418,119,119,418,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,416,416,417,417,416,120,120,418,418,
+419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
+419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
+419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
+419,419,419,419,419,420,421,420,421,421,421,421,421,421,421,120,
+421,422,421,422,422,421,421,421,421,421,421,421,421,420,420,420,
+420,420,420,421,421,421,421,421,421,421,421,421,421,120,120,421,
/* block 51 */
-420,420,420,420,420,420,420,420,420,420,119,119,119,119,119,119,
-420,420,420,420,420,420,420,420,420,420,119,119,119,119,119,119,
-421,421,421,421,421,421,421,422,421,421,421,421,421,421,119,119,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,423,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+423,423,423,423,423,423,423,423,423,423,120,120,120,120,120,120,
+423,423,423,423,423,423,423,423,423,423,120,120,120,120,120,120,
+424,424,424,424,424,424,424,425,424,424,424,424,424,424,120,120,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,426,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 52 */
-424,424,424,424,425,426,426,426,426,426,426,426,426,426,426,426,
-426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
-426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
-426,426,426,426,424,425,424,424,424,424,424,425,424,425,425,425,
-425,425,424,425,425,426,426,426,426,426,426,426,119,119,119,119,
-427,427,427,427,427,427,427,427,427,427,428,428,428,428,428,428,
-428,429,429,429,429,429,429,429,429,429,429,424,424,424,424,424,
-424,424,424,424,429,429,429,429,429,429,429,429,429,119,119,119,
+427,427,427,427,428,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,427,430,427,427,427,427,427,428,427,428,428,428,
+428,428,427,428,428,429,429,429,429,429,429,429,120,120,120,120,
+431,431,431,431,431,431,431,431,431,431,432,432,432,432,432,432,
+432,433,433,433,433,433,433,433,433,433,433,427,427,427,427,427,
+427,427,427,427,433,433,433,433,433,433,433,433,433,120,120,120,
/* block 53 */
-430,430,431,432,432,432,432,432,432,432,432,432,432,432,432,432,
-432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
-432,431,430,430,430,430,431,431,430,430,431,430,430,430,432,432,
-433,433,433,433,433,433,433,433,433,433,432,432,432,432,432,432,
-434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,
-434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,
-434,434,434,434,434,434,435,436,435,435,436,436,436,435,436,435,
-435,435,436,436,119,119,119,119,119,119,119,119,437,437,437,437,
-
-/* block 54 */
+434,434,435,436,436,436,436,436,436,436,436,436,436,436,436,436,
+436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
+436,435,434,434,434,434,435,435,434,434,435,434,434,434,436,436,
+437,437,437,437,437,437,437,437,437,437,436,436,436,436,436,436,
438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,
438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,
-438,438,438,438,439,439,439,439,439,439,439,439,440,440,440,440,
-440,440,440,440,439,439,440,440,119,119,119,441,441,441,441,441,
-442,442,442,442,442,442,442,442,442,442,119,119,119,438,438,438,
-443,443,443,443,443,443,443,443,443,443,444,444,444,444,444,444,
-444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,
-444,444,444,444,444,444,444,444,445,445,445,445,445,445,446,446,
+438,438,438,438,438,438,439,440,439,439,440,440,440,439,440,439,
+439,439,440,440,120,120,120,120,120,120,120,120,441,441,441,441,
+
+/* block 54 */
+442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,
+442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,
+442,442,442,442,443,443,443,443,443,443,443,443,444,444,444,444,
+444,444,444,444,443,443,444,444,120,120,120,445,445,445,445,445,
+446,446,446,446,446,446,446,446,446,446,120,120,120,442,442,442,
+447,447,447,447,447,447,447,447,447,447,448,448,448,448,448,448,
+448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,
+448,448,448,448,448,448,448,448,449,449,449,449,449,449,450,450,
/* block 55 */
-447,448,449,450,451,452,453,454,455,119,119,119,119,119,119,119,
-456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,
-456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,
-456,456,456,456,456,456,456,456,456,456,456,119,119,456,456,456,
-457,457,457,457,457,457,457,457,119,119,119,119,119,119,119,119,
-458,459,458,460,459,461,461,462,461,462,463,459,462,462,459,459,
-462,464,459,459,459,459,459,459,459,465,466,465,465,461,465,465,
-465,465,467,467,468,466,466,469,470,470,119,119,119,119,119,119,
+451,452,453,454,455,456,457,458,459,120,120,120,120,120,120,120,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,120,120,460,460,460,
+461,461,461,461,461,461,461,461,120,120,120,120,120,120,120,120,
+462,463,462,464,463,465,465,466,465,466,467,463,466,466,463,463,
+466,468,463,463,463,463,463,463,463,469,470,471,471,465,471,471,
+471,471,472,473,474,470,470,475,476,476,477,120,120,120,120,120,
/* block 56 */
35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35,127,127,127,127,127,471,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,120,120,120,
-120,120,109,109,109,109,120,120,120,120,120, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,472,473, 35, 35, 35,474, 35, 35,
+ 35, 35, 35, 35, 35, 35,128,128,128,128,128,478,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,121,121,121,
+121,121,110,110,110,110,121,121,121,121,121, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35,479,480, 35, 35, 35,481, 35, 35,
/* block 57 */
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,120,
-113,113,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,119,112,112,112,112,112,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,482, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,121,
+114,114,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,120,113,113,113,113,113,
/* block 58 */
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
@@ -2251,12 +2286,12 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
-475,476, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
+483,484, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
/* block 59 */
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 35, 35, 35, 35, 35,477, 35, 35,478, 35,
+ 32, 33, 32, 33, 32, 33, 35, 35, 35, 35, 35,485, 35, 35,486, 35,
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
@@ -2265,58 +2300,58 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
/* block 60 */
-479,479,479,479,479,479,479,479,480,480,480,480,480,480,480,480,
-479,479,479,479,479,479,119,119,480,480,480,480,480,480,119,119,
-479,479,479,479,479,479,479,479,480,480,480,480,480,480,480,480,
-479,479,479,479,479,479,479,479,480,480,480,480,480,480,480,480,
-479,479,479,479,479,479,119,119,480,480,480,480,480,480,119,119,
-127,479,127,479,127,479,127,479,119,480,119,480,119,480,119,480,
-479,479,479,479,479,479,479,479,480,480,480,480,480,480,480,480,
-481,481,482,482,482,482,483,483,484,484,485,485,486,486,119,119,
+487,487,487,487,487,487,487,487,488,488,488,488,488,488,488,488,
+487,487,487,487,487,487,120,120,488,488,488,488,488,488,120,120,
+487,487,487,487,487,487,487,487,488,488,488,488,488,488,488,488,
+487,487,487,487,487,487,487,487,488,488,488,488,488,488,488,488,
+487,487,487,487,487,487,120,120,488,488,488,488,488,488,120,120,
+128,487,128,487,128,487,128,487,120,488,120,488,120,488,120,488,
+487,487,487,487,487,487,487,487,488,488,488,488,488,488,488,488,
+489,489,490,490,490,490,491,491,492,492,493,493,494,494,120,120,
/* block 61 */
-479,479,479,479,479,479,479,479,487,487,487,487,487,487,487,487,
-479,479,479,479,479,479,479,479,487,487,487,487,487,487,487,487,
-479,479,479,479,479,479,479,479,487,487,487,487,487,487,487,487,
-479,479,127,488,127,119,127,127,480,480,489,489,490,118,491,118,
-118,118,127,488,127,119,127,127,492,492,492,492,490,118,118,118,
-479,479,127,127,119,119,127,127,480,480,493,493,119,118,118,118,
-479,479,127,127,127,168,127,127,480,480,494,494,173,118,118,118,
-119,119,127,488,127,119,127,127,495,495,496,496,490,118,118,119,
+487,487,487,487,487,487,487,487,495,495,495,495,495,495,495,495,
+487,487,487,487,487,487,487,487,495,495,495,495,495,495,495,495,
+487,487,487,487,487,487,487,487,495,495,495,495,495,495,495,495,
+487,487,128,496,128,120,128,128,488,488,497,497,498,119,499,119,
+119,119,128,496,128,120,128,128,500,500,500,500,498,119,119,119,
+487,487,128,128,120,120,128,128,488,488,501,501,120,119,119,119,
+487,487,128,128,128,169,128,128,488,488,502,502,174,119,119,119,
+120,120,128,496,128,120,128,128,503,503,504,504,498,119,119,120,
/* block 62 */
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24,497,498, 24, 24,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24,505,506, 24, 24,
10, 10, 10, 10, 10, 10, 5, 5, 23, 27, 7, 23, 23, 27, 7, 23,
- 5, 5, 5, 5, 5, 5, 5, 5,499,500, 24, 24, 24, 24, 24, 4,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, 27, 5,501, 5, 5, 16,
- 16, 5, 5, 5, 9, 7, 8, 5, 5,501, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,507,508, 24, 24, 24, 24, 24,509,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, 27, 5,510, 5, 5, 16,
+ 16, 5, 5, 5, 9, 7, 8, 5, 5,510, 5, 5, 5, 5, 5, 5,
5, 5, 9, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4,
- 24, 24, 24, 24, 24,502, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 25,109,119,119, 25, 25, 25, 25, 25, 25, 9, 9, 9, 7, 8,109,
+ 24, 24, 24, 24, 24,511, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25,110,120,120, 25, 25, 25, 25, 25, 25, 9, 9, 9, 7, 8,110,
/* block 63 */
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 9, 9, 9, 7, 8,119,
-109,109,109,109,109,109,109,109,109,109,109,109,109,119,119,119,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 9, 9, 9, 7, 8,120,
+110,110,110,110,110,110,110,110,110,110,110,110,110,120,120,120,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-112,112,112,112,112,112,112,112,112,112,112,112,112,423,423,423,
-423,112,423,423,423,112,112,112,112,112,112,112,112,112,112,112,
-503,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+113,113,113,113,113,113,113,113,113,113,113,113,113,426,426,426,
+426,113,426,426,426,113,113,113,113,113,113,113,113,113,113,113,
+512,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 64 */
- 20, 20,504, 20, 20, 20, 20,504, 20, 20,505,504,504,504,505,505,
-504,504,504,505, 20,504, 20, 20, 9,504,504,504,504,504, 20, 20,
- 20, 20, 21, 20,504, 20,506, 20,504, 20,507,508,504,504, 20,505,
-504,504,509,504,505,510,510,510,510,511, 20, 20,505,505,504,504,
- 9, 9, 9, 9, 9,504,505,505,505,505, 20, 9, 20, 20,512, 20,
+ 20, 20,513, 20, 20, 20, 20,513, 20, 20,514,513,513,513,514,514,
+513,513,513,514, 20,513, 20, 20, 9,513,513,513,513,513, 20, 20,
+ 20, 20, 21, 20,513, 20,515, 20,513, 20,516,517,513,513, 20,514,
+513,513,518,513,514,519,519,519,519,520, 20, 20,514,514,513,513,
+ 9, 9, 9, 9, 9,513,514,514,514,514, 20, 9, 20, 20,521, 20,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
-514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
/* block 65 */
-515,515,515, 32, 33,515,515,515,515, 25, 20, 20,119,119,119,119,
- 9, 9, 9, 9,516, 21, 21, 21, 21, 21, 9, 9, 20, 20, 20, 20,
+524,524,524, 32, 33,524,524,524,524, 25, 20, 20,120,120,120,120,
+ 9, 9, 9, 9,525, 21, 21, 21, 21, 21, 9, 9, 20, 20, 20, 20,
9, 20, 20, 9, 20, 20, 9, 20, 20, 21, 21, 20, 20, 20, 9, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 9,
@@ -2357,10 +2392,10 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
/* block 69 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+ 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
@@ -2368,10 +2403,10 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20,517,517,517,517,517,517,517,517,517,517,
-517,517,518,517,517,517,517,517,517,517,517,517,517,517,517,517,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519, 25, 25, 25, 25, 25, 25,
+ 20, 20, 20, 20, 20, 20,526,526,526,526,526,526,526,526,526,526,
+526,526,527,526,526,526,526,526,526,526,526,526,526,526,526,526,
+528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,
+528,528,528,528,528,528,528,528,528,528, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
/* block 71 */
@@ -2392,7 +2427,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
21, 9, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 9, 9, 9,516,516,516,516, 9,
+ 20, 20, 20, 20, 20, 20, 20, 20, 9, 9, 9,525,525,525,525, 9,
/* block 73 */
21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21,
@@ -2401,7 +2436,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,516,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,525,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
/* block 74 */
@@ -2435,20 +2470,20 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
/* block 77 */
-520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
-520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
-520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
-520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
-520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
-520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
-520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
-520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
/* block 78 */
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9,516,516, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9,525,525, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
@@ -2472,167 +2507,167 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
9, 9, 9, 9, 9, 20, 20, 9, 9, 9, 9, 9, 9, 20, 20, 20,
21, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20,119,119, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20,120,120, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
/* block 81 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20,119,119, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20,120,120, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20,119, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,119,
/* block 82 */
-521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,
-521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,
-521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,119,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
-522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,119,
- 32, 33,523,524,525,526,527, 32, 33, 32, 33, 32, 33,528,529,530,
-531, 35, 32, 33, 35, 32, 33, 35, 35, 35, 35, 35,109,109,532,532,
+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,120,
+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,
+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,
+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,120,
+ 32, 33,532,533,534,535,536, 32, 33, 32, 33, 32, 33,537,538,539,
+540, 35, 32, 33, 35, 32, 33, 35, 35, 35, 35, 35,110,110,541,541,
/* block 83 */
-164,165,164,165,164,165,164,165,164,165,164,165,164,165,164,165,
-164,165,164,165,164,165,164,165,164,165,164,165,164,165,164,165,
-164,165,164,165,164,165,164,165,164,165,164,165,164,165,164,165,
-164,165,164,165,164,165,164,165,164,165,164,165,164,165,164,165,
-164,165,164,165,164,165,164,165,164,165,164,165,164,165,164,165,
-164,165,164,165,164,165,164,165,164,165,164,165,164,165,164,165,
-164,165,164,165,533,534,534,534,534,534,534,164,165,164,165,535,
-535,535,164,165,119,119,119,119,119,536,536,536,536,537,536,536,
+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
+165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
+165,166,165,166,542,543,543,543,543,543,543,165,166,165,166,544,
+544,544,165,166,120,120,120,120,120,545,545,545,545,546,545,545,
/* block 84 */
-538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
-538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
-538,538,538,538,538,538,119,538,119,119,119,119,119,538,119,119,
-539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,
-539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,
-539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,
-539,539,539,539,539,539,539,539,119,119,119,119,119,119,119,540,
-541,119,119,119,119,119,119,119,119,119,119,119,119,119,119,542,
+547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,
+547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,
+547,547,547,547,547,547,120,547,120,120,120,120,120,547,120,120,
+548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,
+548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,
+548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,
+548,548,548,548,548,548,548,548,120,120,120,120,120,120,120,549,
+550,120,120,120,120,120,120,120,120,120,120,120,120,120,120,551,
/* block 85 */
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,119,119,119,119,119,119,119,119,119,
-358,358,358,358,358,358,358,119,358,358,358,358,358,358,358,119,
-358,358,358,358,358,358,358,119,358,358,358,358,358,358,358,119,
-358,358,358,358,358,358,358,119,358,358,358,358,358,358,358,119,
-358,358,358,358,358,358,358,119,358,358,358,358,358,358,358,119,
-543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,
-543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,120,120,120,120,120,120,120,120,120,
+360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,120,
+360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,120,
+360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,120,
+360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,120,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
/* block 86 */
5, 5, 23, 27, 23, 27, 5, 5, 5, 23, 27, 5, 23, 27, 5, 5,
5, 5, 5, 5, 5, 5, 5, 10, 5, 5, 10, 5, 23, 27, 5, 5,
- 23, 27, 7, 8, 7, 8, 7, 8, 7, 8, 5, 5, 5, 5, 5,110,
+ 23, 27, 7, 8, 7, 8, 7, 8, 7, 8, 5, 5, 5, 5, 5,111,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 5, 5, 5, 5,
- 10, 5, 7,544, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+ 10, 5, 7,553, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 87 */
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,119,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,119,119,119,119,119,119,119,119,119,119,119,119,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,120,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 88 */
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
/* block 89 */
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
-545,545,545,545,545,545,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,119,119,119,119,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,
/* block 90 */
- 4,546,546,547, 20,548,549,550,551,552,551,552,551,552,551,552,
-551,552, 20,553,551,552,551,552,551,552,551,552,554,555,556,556,
- 20,550,550,550,550,550,550,550,550,550,557,557,557,557,558,558,
-559,560,560,560,560,560, 20,553,550,550,550,548,561,562,563,563,
-119,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
+ 4,555,555,556, 20,557,558,559,560,561,560,561,560,561,560,561,
+560,561, 20,562,560,561,560,561,560,561,560,561,563,564,565,565,
+ 20,559,559,559,559,559,559,559,559,559,566,566,566,566,567,567,
+568,569,569,569,569,569, 20,562,559,559,559,557,570,571,572,572,
+120,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
/* block 91 */
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,119,119,565,565,566,566,567,567,564,
-568,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
-569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
-569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
-569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
-569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
-569,569,569,569,569,569,569,569,569,569,569,546,560,570,570,569,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,120,120,574,574,575,575,576,576,573,
+577,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+578,578,578,578,578,578,578,578,578,578,578,555,569,579,579,578,
/* block 92 */
-119,119,119,119,119,571,571,571,571,571,571,571,571,571,571,571,
-571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,
-571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,
-119,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
-572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
-572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
-572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
-572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
+120,120,120,120,120,580,580,580,580,580,580,580,580,580,580,580,
+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
+120,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
/* block 93 */
-572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,119,
-563,563,573,573,573,573,563,563,563,563,563,563,563,563,563,563,
-571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,
-571,571,571,571,571,571,571,571,571,571,571,119,119,119,119,119,
-563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,
-563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,
-563,563,563,563,119,119,119,119,119,119,119,119,119,119,119,119,
-569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,120,
+572,572,582,582,582,582,572,572,572,572,572,572,572,572,572,572,
+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
+580,580,580,580,580,580,580,580,580,580,580,120,120,120,120,120,
+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
+572,572,572,572,120,120,120,120,120,120,120,120,120,120,120,120,
+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
/* block 94 */
-574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,
-574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,119,
-573,573,573,573,573,573,573,573,573,573,563,563,563,563,563,563,
-563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,
-563,563,563,563,563,563,563,563, 25, 25, 25, 25, 25, 25, 25, 25,
+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,120,
+582,582,582,582,582,582,582,582,582,582,572,572,572,572,572,572,
+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
+572,572,572,572,572,572,572,572, 25, 25, 25, 25, 25, 25, 25, 25,
20, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,
-574,574,574,574,574,574,574,574,574,574,574,574,574,574,574, 20,
+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583, 20,
/* block 95 */
-573,573,573,573,573,573,573,573,573,573,563,563,563,563,563,563,
-563,563,563,563,563,563,563,575,563,575,563,563,563,563,563,563,
-563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,
-563, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-563,563,563,563,563,563,563,563,563,563,563,563, 20, 20, 20, 20,
-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,119,
+582,582,582,582,582,582,582,582,582,582,572,572,572,572,572,572,
+572,572,572,572,572,572,572,584,572,584,572,572,572,572,572,572,
+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
+572, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+572,572,572,572,572,572,572,572,572,572,572,572, 20, 20, 20, 20,
+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,572,
/* block 96 */
-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
-576,576,576,576,576,576,576,576,563,563,563,563,563,563,563,563,
-563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,
-563, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,563,563,563,563,563,
+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
+585,585,585,585,585,585,585,585,572,572,572,572,572,572,572,572,
+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
+572, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,572,572,572,572,572,
/* block 97 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
@@ -2641,1160 +2676,1190 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,
-563,563,563,563,563,563,563,563,563,563,563,563,563,563,563, 20,
+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572, 20,
/* block 98 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
/* block 99 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,119,119,119,119,119,119,119,119,119,119,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,120,120,120,120,120,120,120,120,120,120,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
/* block 100 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 101 */
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,579,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,588,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
/* block 102 */
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
/* block 103 */
-578,578,578,578,578,578,578,578,578,578,578,578,578,119,119,119,
-580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
-580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
-580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
-580,580,580,580,580,580,580,119,119,119,119,119,119,119,119,119,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,581,582,582,582,582,582,582,583,583,
+587,587,587,587,587,587,587,587,587,587,587,587,587,120,120,120,
+589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
+589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
+589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
+589,589,589,589,589,589,589,120,120,120,120,120,120,120,120,120,
+590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
+590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
+590,590,590,590,590,590,590,590,591,591,591,591,591,591,592,592,
/* block 104 */
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
/* block 105 */
-584,584,584,584,584,584,584,584,584,584,584,584,585,586,586,586,
-584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
-587,587,587,587,587,587,587,587,587,587,584,584,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-191,192,191,192,191,192,191,192,191,192,588,589,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,590,197,
-199,199,199,591,543,543,543,543,543,543,543,543,543,543,591,472,
+593,593,593,593,593,593,593,593,593,593,593,593,594,595,595,595,
+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
+596,596,596,596,596,596,596,596,596,596,593,593,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+192,193,192,193,192,193,192,193,192,193,597,598,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,599,198,
+200,200,200,600,552,552,552,552,552,552,552,552,552,552,600,479,
/* block 106 */
-191,192,191,192,191,192,191,192,191,192,191,192,191,192,191,192,
-191,192,191,192,191,192,191,192,191,192,191,192,472,472,543,543,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,593,593,593,593,593,593,593,593,593,593,
-594,594,595,595,595,595,595,595,119,119,119,119,119,119,119,119,
+192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+192,193,192,193,192,193,192,193,192,193,192,193,479,479,552,552,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,602,602,602,602,602,602,602,602,602,602,
+603,603,604,604,604,604,604,604,120,120,120,120,120,120,120,120,
/* block 107 */
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15,110,110,110,110,110,110,110,110,110,
+ 15, 15, 15, 15, 15, 15, 15,111,111,111,111,111,111,111,111,111,
15, 15, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
35, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
-109, 35, 35, 35, 35, 35, 35, 35, 35, 32, 33, 32, 33,596, 32, 33,
+110, 35, 35, 35, 35, 35, 35, 35, 35, 32, 33, 32, 33,605, 32, 33,
/* block 108 */
- 32, 33, 32, 33, 32, 33, 32, 33,110, 15, 15, 32, 33,597, 35, 22,
- 32, 33, 32, 33, 35, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,598,599,600,601,598, 35,
-602,603,604,605, 32, 33, 32, 33, 32, 33,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119, 22,109,109, 35, 22, 22, 22, 22, 22,
+ 32, 33, 32, 33, 32, 33, 32, 33,111, 15, 15, 32, 33,606, 35, 22,
+ 32, 33, 32, 33,607, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
+ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,608,609,610,611,608, 35,
+612,613,614,615, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
+120,120, 32, 33,616,617,618,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120, 22,110,110, 35, 22, 22, 22, 22, 22,
/* block 109 */
-606,606,607,606,606,606,607,606,606,606,606,607,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,608,608,607,607,608,609,609,609,609,119,119,119,119,
-610,610,610,611,611,611,612,612,613,612,119,119,119,119,119,119,
-614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,
-614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,
-614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,
-614,614,614,614,615,615,615,615,119,119,119,119,119,119,119,119,
+619,619,620,619,619,619,620,619,619,619,619,620,619,619,619,619,
+619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,
+619,619,619,621,621,620,620,621,622,622,622,622,120,120,120,120,
+623,623,623,624,624,624,625,625,626,625,120,120,120,120,120,120,
+627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,
+627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,
+627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,
+627,627,627,627,628,628,628,628,120,120,120,120,120,120,120,120,
/* block 110 */
-616,616,617,617,617,617,617,617,617,617,617,617,617,617,617,617,
-617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,
-617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,
-617,617,617,617,616,616,616,616,616,616,616,616,616,616,616,616,
-616,616,616,616,618,618,119,119,119,119,119,119,119,119,619,619,
-620,620,620,620,620,620,620,620,620,620,119,119,119,119,119,119,
-251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,
-251,621,253,622,253,253,253,253,259,259,259,253,259,253,253,251,
+629,629,630,630,630,630,630,630,630,630,630,630,630,630,630,630,
+630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,
+630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,
+630,630,630,630,629,629,629,629,629,629,629,629,629,629,629,629,
+629,629,629,629,631,631,120,120,120,120,120,120,120,120,632,632,
+633,633,633,633,633,633,633,633,633,633,120,120,120,120,120,120,
+252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
+252,634,254,635,254,254,254,254,260,260,260,254,260,254,254,252,
/* block 111 */
-623,623,623,623,623,623,623,623,623,623,624,624,624,624,624,624,
-624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,
-624,624,624,624,624,624,625,625,625,625,625,625,625,625,626,627,
-628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
-628,628,628,628,628,628,628,629,629,629,629,629,629,629,629,629,
-629,629,630,630,119,119,119,119,119,119,119,119,119,119,119,631,
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-355,355,355,355,355,355,355,355,355,355,355,355,355,119,119,119,
+636,636,636,636,636,636,636,636,636,636,637,637,637,637,637,637,
+637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,
+637,637,637,637,637,637,638,638,638,638,638,638,638,638,639,640,
+641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,
+641,641,641,641,641,641,641,642,642,642,642,642,642,642,642,642,
+642,642,643,643,120,120,120,120,120,120,120,120,120,120,120,644,
+357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
+357,357,357,357,357,357,357,357,357,357,357,357,357,120,120,120,
/* block 112 */
-632,632,632,633,634,634,634,634,634,634,634,634,634,634,634,634,
-634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,
-634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,
-634,634,634,632,633,633,632,632,632,632,633,633,632,633,633,633,
-633,635,635,635,635,635,635,635,635,635,635,635,635,635,119,636,
-637,637,637,637,637,637,637,637,637,637,119,119,119,119,635,635,
-343,343,343,343,343,345,638,343,343,343,343,343,343,343,343,343,
-349,349,349,349,349,349,349,349,349,349,343,343,343,343,343,119,
+645,645,645,646,647,647,647,647,647,647,647,647,647,647,647,647,
+647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,
+647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,
+647,647,647,645,646,646,645,645,645,645,646,646,645,645,646,646,
+646,648,648,648,648,648,648,648,648,648,648,648,648,648,120,649,
+650,650,650,650,650,650,650,650,650,650,120,120,120,120,648,648,
+345,345,345,345,345,347,651,345,345,345,345,345,345,345,345,345,
+351,351,351,351,351,351,351,351,351,351,345,345,345,345,345,120,
/* block 113 */
-639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,
-639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,
-639,639,639,639,639,639,639,639,639,640,640,640,640,640,640,641,
-641,640,640,641,641,640,640,119,119,119,119,119,119,119,119,119,
-639,639,639,640,639,639,639,639,639,639,639,639,640,641,119,119,
-642,642,642,642,642,642,642,642,642,642,119,119,643,643,643,643,
-343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,
-638,343,343,343,343,343,343,350,350,350,343,344,345,344,343,343,
+652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,
+652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,
+652,652,652,652,652,652,652,652,652,653,653,653,653,653,653,654,
+654,653,653,654,654,653,653,120,120,120,120,120,120,120,120,120,
+652,652,652,653,652,652,652,652,652,652,652,652,653,654,120,120,
+655,655,655,655,655,655,655,655,655,655,120,120,656,656,656,656,
+345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
+651,345,345,345,345,345,345,352,352,352,345,346,347,346,345,345,
/* block 114 */
-644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,
-644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,
-644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,
-645,644,645,645,645,644,644,645,645,644,644,644,644,644,645,645,
-644,645,644,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,644,644,646,647,647,
-648,648,648,648,648,648,648,648,648,648,648,649,650,650,649,649,
-651,651,648,652,652,649,650,119,119,119,119,119,119,119,119,119,
+657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+658,657,658,658,658,657,657,658,658,657,657,657,657,657,658,658,
+657,658,657,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,657,657,659,660,660,
+661,661,661,661,661,661,661,661,661,661,661,662,663,663,662,662,
+664,664,661,665,665,662,663,120,120,120,120,120,120,120,120,120,
/* block 115 */
-119,358,358,358,358,358,358,119,119,358,358,358,358,358,358,119,
-119,358,358,358,358,358,358,119,119,119,119,119,119,119,119,119,
-358,358,358,358,358,358,358,119,358,358,358,358,358,358,358,119,
+120,360,360,360,360,360,360,120,120,360,360,360,360,360,360,120,
+120,360,360,360,360,360,360,120,120,120,120,120,120,120,120,120,
+360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,120,
35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35,653, 35, 35, 35, 35, 35, 35, 35, 15,109,109,109,109,
- 35, 35, 35, 35, 35,127,119,119,119,119,119,119,119,119,119,119,
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
+ 35, 35, 35,666, 35, 35, 35, 35, 35, 35, 35, 15,110,110,110,110,
+ 35, 35, 35, 35, 35,128, 35, 35,120,120,120,120,120,120,120,120,
+667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
/* block 116 */
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
-648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,
-648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,
-648,648,648,649,649,650,649,649,650,649,649,651,649,650,119,119,
-655,655,655,655,655,655,655,655,655,655,119,119,119,119,119,119,
+667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
+667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
+667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
+667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
+661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,
+661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,
+661,661,661,662,662,663,662,662,663,662,662,664,662,663,120,120,
+668,668,668,668,668,668,668,668,668,668,120,120,120,120,120,120,
/* block 117 */
-656,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,656,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,656,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,656,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-656,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
/* block 118 */
-657,657,657,657,657,657,657,657,657,657,657,657,656,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,656,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,656,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-656,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,656,657,657,657,
+670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670,
/* block 119 */
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,656,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,656,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-656,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,656,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
/* block 120 */
-657,657,657,657,657,657,657,657,656,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,656,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-656,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,656,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,656,657,657,657,657,657,657,657,
+670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670,
/* block 121 */
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,656,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-656,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,656,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,656,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
/* block 122 */
-657,657,657,657,656,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-656,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,656,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,656,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,656,657,657,657,657,657,657,657,657,657,657,657,
+670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670,
/* block 123 */
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-656,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,656,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,656,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,656,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
/* block 124 */
-657,657,657,657,657,657,657,657,656,657,657,657,657,657,657,657,
-657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
-657,657,657,657,119,119,119,119,119,119,119,119,119,119,119,119,
-356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
-356,356,356,356,356,356,356,119,119,119,119,357,357,357,357,357,
-357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
-357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
-357,357,357,357,357,357,357,357,357,357,357,357,119,119,119,119,
+670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,120,120,120,120,120,120,120,120,120,120,120,120,
+358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
+358,358,358,358,358,358,358,120,120,120,120,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,359,359,359,120,120,120,120,
/* block 125 */
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
/* block 126 */
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
/* block 127 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,119,119,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,120,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
/* block 128 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 129 */
- 35, 35, 35, 35, 35, 35, 35,119,119,119,119,119,119,119,119,119,
-119,119,119,205,205,205,205,205,119,119,119,119,119,214,211,214,
-214,214,214,214,214,214,214,214,214,660,214,214,214,214,214,214,
-214,214,214,214,214,214,214,119,214,214,214,214,214,119,214,119,
-214,214,119,214,214,119,214,214,214,214,214,214,214,214,214,214,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
+ 35, 35, 35, 35, 35, 35, 35,120,120,120,120,120,120,120,120,120,
+120,120,120,206,206,206,206,206,120,120,120,120,120,215,212,215,
+215,215,215,215,215,215,215,215,215,673,215,215,215,215,215,215,
+215,215,215,215,215,215,215,120,215,215,215,215,215,120,215,120,
+215,215,120,215,215,120,215,215,215,215,215,215,215,215,215,215,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
/* block 130 */
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,661,661,661,661,661,661,661,661,661,661,661,661,661,661,
-661,661,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,674,674,674,674,674,674,674,674,674,674,674,674,674,674,
+674,674,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
/* block 131 */
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
/* block 132 */
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224, 8, 7,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225, 8, 7,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
/* block 133 */
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-119,119,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-224,224,662,224,224,224,224,224,224,224,224,224,219,663,119,119,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+120,120,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+225,225,675,225,225,225,225,225,225,225,225,225,220,676,120,120,
/* block 134 */
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
- 5, 5, 5, 5, 5, 5, 5, 7, 8, 5,119,119,119,119,119,119,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,543,543,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+ 5, 5, 5, 5, 5, 5, 5, 7, 8, 5,120,120,120,120,120,120,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,552,552,
5, 10, 10, 16, 16, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7,
- 8, 7, 8, 7, 8,547,547, 7, 8, 5, 5, 5, 5, 16, 16, 16,
- 5, 5, 5,119, 5, 5, 5, 5, 10, 7, 8, 7, 8, 7, 8, 5,
- 5, 5, 9, 10, 9, 9, 9,119, 5, 6, 5, 5,119,119,119,119,
-224,224,224,224,224,119,224,224,224,224,224,224,224,224,224,224,
+ 8, 7, 8, 7, 8,556,556, 7, 8, 5, 5, 5, 5, 16, 16, 16,
+ 5, 5, 5,120, 5, 5, 5, 5, 10, 7, 8, 7, 8, 7, 8, 5,
+ 5, 5, 9, 10, 9, 9, 9,120, 5, 6, 5, 5,120,120,120,120,
+225,225,225,225,225,120,225,225,225,225,225,225,225,225,225,225,
/* block 135 */
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,119,119, 24,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,120,120, 24,
/* block 136 */
-119, 5, 5, 5, 6, 5, 5, 5, 7, 8, 5, 9, 5, 10, 5, 5,
+120, 5, 5, 5, 6, 5, 5, 5, 7, 8, 5, 9, 5, 10, 5, 5,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 5, 5, 9, 9, 9, 5,
5, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 5, 8, 15, 16,
15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 7, 9, 8, 9, 7,
- 8,546,551,552,546,546,569,569,569,569,569,569,569,569,569,569,
-560,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
+ 8,555,560,561,555,555,578,578,578,578,578,578,578,578,578,578,
+569,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
/* block 137 */
-569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
-569,569,569,569,569,569,569,569,569,569,569,569,569,569,664,664,
-572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
-572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,119,
-119,119,572,572,572,572,572,572,119,119,572,572,572,572,572,572,
-119,119,572,572,572,572,572,572,119,119,572,572,572,119,119,119,
- 6, 6, 9, 15, 20, 6, 6,119, 20, 9, 9, 9, 9, 20, 20,119,
-502,502,502,502,502,502,502,502,502, 24, 24, 24, 20, 20,119,119,
+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+578,578,578,578,578,578,578,578,578,578,578,578,578,578,677,677,
+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,120,
+120,120,581,581,581,581,581,581,120,120,581,581,581,581,581,581,
+120,120,581,581,581,581,581,581,120,120,581,581,581,120,120,120,
+ 6, 6, 9, 15, 20, 6, 6,120, 20, 9, 9, 9, 9, 20, 20,120,
+511,511,511,511,511,511,511,511,511, 24, 24, 24, 20, 20,120,120,
/* block 138 */
-665,665,665,665,665,665,665,665,665,665,665,665,119,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,119,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,119,665,665,119,665,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,119,119,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+678,678,678,678,678,678,678,678,678,678,678,678,120,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,120,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,120,678,678,120,678,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,120,120,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 139 */
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
-665,665,665,665,665,665,665,665,665,665,665,119,119,119,119,119,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,120,120,120,120,120,
/* block 140 */
-666,666,666,119,119,119,119,667,667,667,667,667,667,667,667,667,
-667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
-667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
-667,667,667,667,119,119,119,668,668,668,668,668,668,668,668,668,
-669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,
-669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,
-669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,
-669,669,669,669,669,670,670,670,670,671,671,671,671,671,671,671,
+679,679,679,120,120,120,120,680,680,680,680,680,680,680,680,680,
+680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,
+680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,
+680,680,680,680,120,120,120,681,681,681,681,681,681,681,681,681,
+682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,
+682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,
+682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,
+682,682,682,682,682,683,683,683,683,684,684,684,684,684,684,684,
/* block 141 */
-671,671,671,671,671,671,671,671,671,671,670,670,671,671,671,119,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,119,119,119,119,
-671,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+684,684,684,684,684,684,684,684,684,684,683,683,684,684,684,120,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,
+684,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,112,119,119,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,113,120,120,
/* block 142 */
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 143 */
-672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
-672,672,672,672,672,672,672,672,672,672,672,672,672,119,119,119,
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
-673,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-674,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,
-675,675,675,675,675,675,675,675,675,675,675,675,119,119,119,119,
+685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
+685,685,685,685,685,685,685,685,685,685,685,685,685,120,120,120,
+686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,
+686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,
+686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,
+686,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+687,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
+688,688,688,688,688,688,688,688,688,688,688,688,120,120,120,120,
/* block 144 */
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-677,677,677,677,119,119,119,119,119,119,119,119,119,676,676,676,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,679,678,678,678,678,678,678,678,678,679,119,119,119,119,119,
-680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,
-680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,
-680,680,680,680,680,680,681,681,681,681,681,119,119,119,119,119,
+689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
+689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
+690,690,690,690,120,120,120,120,120,120,120,120,120,689,689,689,
+691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
+691,692,691,691,691,691,691,691,691,691,692,120,120,120,120,120,
+693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,
+693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,
+693,693,693,693,693,693,694,694,694,694,694,120,120,120,120,120,
/* block 145 */
-682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,
-682,682,682,682,682,682,682,682,682,682,682,682,682,682,119,683,
-684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,
-684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,
-684,684,684,684,119,119,119,119,684,684,684,684,684,684,684,684,
-685,686,686,686,686,686,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,
+695,695,695,695,695,695,695,695,695,695,695,695,695,695,120,696,
+697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
+697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
+697,697,697,697,120,120,120,120,697,697,697,697,697,697,697,697,
+698,699,699,699,699,699,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 146 */
-687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,
-687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,
-687,687,687,687,687,687,687,687,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
-689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
-689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
+700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+700,700,700,700,700,700,700,700,701,701,701,701,701,701,701,701,
+701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,
+701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,
+702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,
+702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,
+702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,
/* block 147 */
-690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,
-690,690,690,690,690,690,690,690,690,690,690,690,690,690,119,119,
-691,691,691,691,691,691,691,691,691,691,119,119,119,119,119,119,
-692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,
-692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,
-692,692,692,692,119,119,119,119,693,693,693,693,693,693,693,693,
-693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,
-693,693,693,693,693,693,693,693,693,693,693,693,119,119,119,119,
+703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,
+703,703,703,703,703,703,703,703,703,703,703,703,703,703,120,120,
+704,704,704,704,704,704,704,704,704,704,120,120,120,120,120,120,
+705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,
+705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,
+705,705,705,705,120,120,120,120,706,706,706,706,706,706,706,706,
+706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,
+706,706,706,706,706,706,706,706,706,706,706,706,120,120,120,120,
/* block 148 */
-694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,
-694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,
-694,694,694,694,694,694,694,694,119,119,119,119,119,119,119,119,
-695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,
-695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,
-695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,
-695,695,695,695,119,119,119,119,119,119,119,119,119,119,119,696,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,120,120,120,120,120,120,120,120,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,120,120,120,120,120,120,120,120,120,120,120,709,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 149 */
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
/* block 150 */
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,119,119,119,119,119,119,119,119,119,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,119,119,119,119,119,119,119,119,119,119,
-697,697,697,697,697,697,697,697,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,120,120,120,120,120,120,120,120,120,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,120,120,120,120,120,120,120,120,120,120,
+710,710,710,710,710,710,710,710,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 151 */
-698,698,698,698,698,698,119,119,698,119,698,698,698,698,698,698,
-698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,
-698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,
-698,698,698,698,698,698,119,698,698,119,119,119,698,119,119,698,
-699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,
-699,699,699,699,699,699,119,700,701,701,701,701,701,701,701,701,
-702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,
-702,702,702,702,702,702,702,703,703,704,704,704,704,704,704,704,
+711,711,711,711,711,711,120,120,711,120,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,120,711,711,120,120,120,711,120,120,711,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,120,713,714,714,714,714,714,714,714,714,
+715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
+715,715,715,715,715,715,715,716,716,717,717,717,717,717,717,717,
/* block 152 */
-705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,
-705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,119,
-119,119,119,119,119,119,119,706,706,706,706,706,706,706,706,706,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
-707,707,707,119,707,707,119,119,119,119,119,708,708,708,708,708,
+718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,
+718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,120,
+120,120,120,120,120,120,120,719,719,719,719,719,719,719,719,719,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
+720,720,720,120,720,720,120,120,120,120,120,721,721,721,721,721,
/* block 153 */
-709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
-709,709,709,709,709,709,710,710,710,710,710,710,119,119,119,711,
-712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
-712,712,712,712,712,712,712,712,712,712,119,119,119,119,119,713,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,
+722,722,722,722,722,722,723,723,723,723,723,723,120,120,120,724,
+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
+725,725,725,725,725,725,725,725,725,725,120,120,120,120,120,726,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 154 */
-714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,
-714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,119,119,119,119,716,716,715,715,
-716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,
-119,119,716,716,716,716,716,716,716,716,716,716,716,716,716,716,
-716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,
-716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,
+727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,
+727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,
+728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,
+728,728,728,728,728,728,728,728,120,120,120,120,729,729,728,728,
+729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,
+120,120,729,729,729,729,729,729,729,729,729,729,729,729,729,729,
+729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,
+729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,
/* block 155 */
-717,718,718,718,119,718,718,119,119,119,119,119,718,718,718,718,
-717,717,717,717,119,717,717,717,119,717,717,717,717,717,717,717,
-717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,
-717,717,717,717,717,717,119,119,718,718,718,119,119,119,119,718,
-719,719,719,719,719,719,719,719,719,119,119,119,119,119,119,119,
-720,720,720,720,720,720,720,720,720,119,119,119,119,119,119,119,
-721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,
-721,721,721,721,721,721,721,721,721,721,721,721,721,722,722,723,
+730,731,731,731,120,731,731,120,120,120,120,120,731,731,731,731,
+730,730,730,730,120,730,730,730,120,730,730,730,730,730,730,730,
+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,
+730,730,730,730,730,730,120,120,731,731,731,120,120,120,120,731,
+732,732,732,732,732,732,732,732,732,120,120,120,120,120,120,120,
+733,733,733,733,733,733,733,733,733,120,120,120,120,120,120,120,
+734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,
+734,734,734,734,734,734,734,734,734,734,734,734,734,735,735,736,
/* block 156 */
-724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
-724,724,724,724,724,724,724,724,724,724,724,724,724,725,725,725,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-726,726,726,726,726,726,726,726,727,726,726,726,726,726,726,726,
-726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,
-726,726,726,726,726,728,728,119,119,119,119,729,729,729,729,729,
-730,730,730,730,730,730,730,119,119,119,119,119,119,119,119,119,
+737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
+737,737,737,737,737,737,737,737,737,737,737,737,737,738,738,738,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+739,739,739,739,739,739,739,739,740,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,741,741,120,120,120,120,742,742,742,742,742,
+743,743,743,743,743,743,743,120,120,120,120,120,120,120,120,120,
/* block 157 */
-731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,
-731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,
-731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,
-731,731,731,731,731,731,119,119,119,732,732,732,732,732,732,732,
-733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,
-733,733,733,733,733,733,119,119,734,734,734,734,734,734,734,734,
-735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,
-735,735,735,119,119,119,119,119,736,736,736,736,736,736,736,736,
+744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
+744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
+744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
+744,744,744,744,744,744,120,120,120,745,745,745,745,745,745,745,
+746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,
+746,746,746,746,746,746,120,120,747,747,747,747,747,747,747,747,
+748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,
+748,748,748,120,120,120,120,120,749,749,749,749,749,749,749,749,
/* block 158 */
-737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
-737,737,119,119,119,119,119,119,119,738,738,738,738,119,119,119,
-119,119,119,119,119,119,119,119,119,739,739,739,739,739,739,739,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,
+750,750,120,120,120,120,120,120,120,751,751,751,751,120,120,120,
+120,120,120,120,120,120,120,120,120,752,752,752,752,752,752,752,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 159 */
-740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,
-740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,
-740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,
-740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,
-740,740,740,740,740,740,740,740,740,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,
+753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,
+753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,
+753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,
+753,753,753,753,753,753,753,753,753,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 160 */
-741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,
-741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,
-741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,
-741,741,741,119,119,119,119,119,119,119,119,119,119,119,119,119,
-742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,
-742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,
-742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,
-742,742,742,119,119,119,119,119,119,119,743,743,743,743,743,743,
+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,
+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,
+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,
+754,754,754,120,120,120,120,120,120,120,120,120,120,120,120,120,
+755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,
+755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,
+755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,
+755,755,755,120,120,120,120,120,120,120,756,756,756,756,756,756,
/* block 161 */
-744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
-744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
-744,744,744,744,745,745,745,745,119,119,119,119,119,119,119,119,
-746,746,746,746,746,746,746,746,746,746,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,
+757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,
+757,757,757,757,758,758,758,758,120,120,120,120,120,120,120,120,
+759,759,759,759,759,759,759,759,759,759,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 162 */
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,
-747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,119,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,
+760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,120,
/* block 163 */
-748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,
-748,748,748,748,748,748,748,748,748,748,748,748,748,749,749,749,
-749,749,749,749,749,749,749,748,119,119,119,119,119,119,119,119,
-750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,
-750,750,750,750,750,750,751,751,751,751,751,751,751,751,751,751,
-751,752,752,752,752,753,753,753,753,753,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,
+761,761,761,761,761,761,761,761,761,761,761,761,761,762,762,762,
+762,762,762,762,762,762,762,761,120,120,120,120,120,120,120,120,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+763,763,763,763,763,763,764,764,764,764,764,764,764,764,764,764,
+764,765,765,765,765,766,766,766,766,766,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 164 */
-754,755,754,756,756,756,756,756,756,756,756,756,756,756,756,756,
-756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,
-756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,
-756,756,756,756,756,756,756,756,755,755,755,755,755,755,755,755,
-755,755,755,755,755,755,755,757,757,757,757,757,757,757,119,119,
-119,119,758,758,758,758,758,758,758,758,758,758,758,758,758,758,
-758,758,758,758,758,758,759,759,759,759,759,759,759,759,759,759,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,755,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,
+767,767,767,767,767,767,767,120,120,120,120,120,120,120,120,120,
/* block 165 */
-760,760,761,762,762,762,762,762,762,762,762,762,762,762,762,762,
-762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,
-762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,
-761,761,761,760,760,760,760,761,761,760,760,763,763,764,763,763,
-763,763,119,119,119,119,119,119,119,119,119,119,119,764,119,119,
-765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,
-765,765,765,765,765,765,765,765,765,119,119,119,119,119,119,119,
-766,766,766,766,766,766,766,766,766,766,119,119,119,119,119,119,
+768,769,768,770,770,770,770,770,770,770,770,770,770,770,770,770,
+770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,
+770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,
+770,770,770,770,770,770,770,770,769,769,769,769,769,769,769,769,
+769,769,769,769,769,769,769,771,771,771,771,771,771,771,120,120,
+120,120,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
+772,772,772,772,772,772,773,773,773,773,773,773,773,773,773,773,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,769,
/* block 166 */
-767,767,767,768,768,768,768,768,768,768,768,768,768,768,768,768,
-768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,
-768,768,768,768,768,768,768,767,767,767,767,767,769,767,767,767,
-767,767,767,767,767,119,770,770,770,770,770,770,770,770,770,770,
-771,771,771,771,768,769,769,119,119,119,119,119,119,119,119,119,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,773,774,774,772,119,119,119,119,119,119,119,119,119,
+774,774,775,776,776,776,776,776,776,776,776,776,776,776,776,776,
+776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
+776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
+775,775,775,774,774,774,774,775,775,774,774,777,777,778,777,777,
+777,777,120,120,120,120,120,120,120,120,120,120,120,778,120,120,
+779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,
+779,779,779,779,779,779,779,779,779,120,120,120,120,120,120,120,
+780,780,780,780,780,780,780,780,780,780,120,120,120,120,120,120,
/* block 167 */
-775,775,776,777,777,777,777,777,777,777,777,777,777,777,777,777,
-777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,
-777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,
-777,777,777,776,776,776,775,775,775,775,775,775,775,775,775,776,
-776,777,778,778,777,779,779,779,779,775,775,775,775,779,119,119,
-780,780,780,780,780,780,780,780,780,780,777,779,777,779,779,779,
-119,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,
-781,781,781,781,781,119,119,119,119,119,119,119,119,119,119,119,
+781,781,781,782,782,782,782,782,782,782,782,782,782,782,782,782,
+782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,
+782,782,782,782,782,782,782,781,781,781,781,781,783,781,781,781,
+781,781,781,781,781,120,784,784,784,784,784,784,784,784,784,784,
+785,785,785,785,782,783,783,120,120,120,120,120,120,120,120,120,
+786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,
+786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,
+786,786,786,787,788,788,786,120,120,120,120,120,120,120,120,120,
/* block 168 */
-782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,
-782,782,119,782,782,782,782,782,782,782,782,782,782,782,782,782,
-782,782,782,782,782,782,782,782,782,782,782,782,783,783,783,784,
-784,784,783,783,784,783,784,784,785,785,785,785,785,785,784,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+789,789,790,791,791,791,791,791,791,791,791,791,791,791,791,791,
+791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,
+791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,
+791,791,791,790,790,790,789,789,789,789,789,789,789,789,789,790,
+790,791,792,792,791,793,793,793,793,789,789,789,789,793,120,120,
+794,794,794,794,794,794,794,794,794,794,791,793,791,793,793,793,
+120,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,
+795,795,795,795,795,120,120,120,120,120,120,120,120,120,120,120,
/* block 169 */
-786,786,786,786,786,786,786,119,786,119,786,786,786,786,119,786,
-786,786,786,786,786,786,786,786,786,786,786,786,786,786,119,786,
-786,786,786,786,786,786,786,786,786,787,119,119,119,119,119,119,
-788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,
-788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,
-788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,789,
-790,790,790,789,789,789,789,789,789,789,789,119,119,119,119,119,
-791,791,791,791,791,791,791,791,791,791,119,119,119,119,119,119,
+796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
+796,796,120,796,796,796,796,796,796,796,796,796,796,796,796,796,
+796,796,796,796,796,796,796,796,796,796,796,796,797,797,797,798,
+798,798,797,797,798,797,798,798,799,799,799,799,799,799,798,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 170 */
-792,793,794,795,119,796,796,796,796,796,796,796,796,119,119,796,
-796,119,119,796,796,796,796,796,796,796,796,796,796,796,796,796,
-796,796,796,796,796,796,796,796,796,119,796,796,796,796,796,796,
-796,119,796,796,119,796,796,796,796,796,119,797,793,796,798,794,
-792,794,794,794,794,119,119,794,794,119,119,794,794,794,119,119,
-796,119,119,119,119,119,119,798,119,119,119,119,119,796,796,796,
-796,796,794,794,119,119,792,792,792,792,792,792,792,119,119,119,
-792,792,792,792,792,119,119,119,119,119,119,119,119,119,119,119,
+800,800,800,800,800,800,800,120,800,120,800,800,800,800,120,800,
+800,800,800,800,800,800,800,800,800,800,800,800,800,800,120,800,
+800,800,800,800,800,800,800,800,800,801,120,120,120,120,120,120,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,803,
+804,804,804,803,803,803,803,803,803,803,803,120,120,120,120,120,
+805,805,805,805,805,805,805,805,805,805,120,120,120,120,120,120,
/* block 171 */
-799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,
-799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,
-799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,
-799,799,799,799,799,800,800,800,801,801,801,801,801,801,801,801,
-800,800,801,801,801,800,801,799,799,799,799,802,802,802,802,802,
-803,803,803,803,803,803,803,803,803,803,119,802,119,802,801,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+806,807,808,809,120,810,810,810,810,810,810,810,810,120,120,810,
+810,120,120,810,810,810,810,810,810,810,810,810,810,810,810,810,
+810,810,810,810,810,810,810,810,810,120,810,810,810,810,810,810,
+810,120,810,810,120,810,810,810,810,810,120,811,807,810,812,808,
+806,808,808,808,808,120,120,808,808,120,120,808,808,808,120,120,
+810,120,120,120,120,120,120,812,120,120,120,120,120,810,810,810,
+810,810,808,808,120,120,806,806,806,806,806,806,806,120,120,120,
+806,806,806,806,806,120,120,120,120,120,120,120,120,120,120,120,
/* block 172 */
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
-804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
-805,806,806,807,807,807,807,807,807,806,807,806,806,805,806,807,
-807,806,807,807,804,804,808,804,119,119,119,119,119,119,119,119,
-809,809,809,809,809,809,809,809,809,809,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,
+813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,
+813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,
+813,813,813,813,813,814,814,814,815,815,815,815,815,815,815,815,
+814,814,815,815,815,814,815,813,813,813,813,816,816,816,816,816,
+817,817,817,817,817,817,817,817,817,817,120,816,120,816,815,813,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 173 */
-810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,
-810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,
-810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,811,
-812,812,813,813,813,813,119,119,812,812,812,812,813,813,812,813,
-813,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,
-814,814,814,814,814,814,814,814,810,810,810,810,813,813,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,
+818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,
+818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,
+819,820,820,821,821,821,821,821,821,820,821,820,820,819,820,821,
+821,820,821,821,818,818,822,818,120,120,120,120,120,120,120,120,
+823,823,823,823,823,823,823,823,823,823,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 174 */
-815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,
-815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,
-815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,
-816,816,816,817,817,817,817,817,817,817,817,816,816,817,816,817,
-817,818,818,818,815,119,119,119,119,119,119,119,119,119,119,119,
-819,819,819,819,819,819,819,819,819,819,119,119,119,119,119,119,
-392,392,392,392,392,392,392,392,392,392,392,392,392,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,825,
+826,826,827,827,827,827,120,120,826,826,826,826,827,827,826,827,
+827,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,
+828,828,828,828,828,828,828,828,824,824,824,824,827,827,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 175 */
-820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
-820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
-820,820,820,820,820,820,820,820,820,820,820,821,822,821,822,822,
-821,821,821,821,821,821,822,821,119,119,119,119,119,119,119,119,
-823,823,823,823,823,823,823,823,823,823,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+830,830,830,831,831,831,831,831,831,831,831,830,830,831,830,831,
+831,832,832,832,829,120,120,120,120,120,120,120,120,120,120,120,
+833,833,833,833,833,833,833,833,833,833,120,120,120,120,120,120,
+395,395,395,395,395,395,395,395,395,395,395,395,395,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 176 */
-824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
-824,824,824,824,824,824,824,824,824,824,824,119,119,825,825,825,
-826,826,825,825,825,825,826,825,825,825,825,825,119,119,119,119,
-827,827,827,827,827,827,827,827,827,827,828,828,829,829,829,830,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,
+834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,
+834,834,834,834,834,834,834,834,834,834,834,835,836,835,836,836,
+835,835,835,835,835,835,836,835,834,120,120,120,120,120,120,120,
+837,837,837,837,837,837,837,837,837,837,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 177 */
-831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
-831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
-831,831,831,831,831,831,831,831,831,831,831,831,832,832,832,833,
-833,833,833,833,833,833,833,833,832,833,833,834,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,120,120,839,839,839,
+840,840,839,839,839,839,840,839,839,839,839,839,120,120,120,120,
+841,841,841,841,841,841,841,841,841,841,842,842,843,843,843,844,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 178 */
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,
-835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,
-836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,
-836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,
-837,837,837,837,837,837,837,837,837,837,838,838,838,838,838,838,
-838,838,838,119,119,119,119,119,119,119,119,119,119,119,119,839,
-
-/* block 179 */
-840,841,841,841,841,841,841,841,841,841,841,840,840,840,840,840,
-840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,
-840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,
-840,840,840,841,841,841,841,841,841,842,843,841,841,841,841,844,
-844,844,844,844,844,844,844,841,119,119,119,119,119,119,119,119,
-845,846,846,846,846,846,846,847,847,846,846,846,845,845,845,845,
845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,
845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,
+845,845,845,845,845,845,845,845,845,845,845,845,846,846,846,847,
+847,847,847,847,847,847,847,847,846,847,847,848,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-/* block 180 */
-845,845,845,845,119,119,848,848,848,848,846,846,846,846,846,846,
-846,846,846,846,846,846,846,847,846,846,849,849,849,845,849,849,
-849,849,849,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,
+/* block 179 */
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,
850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,
-850,850,850,850,850,850,850,850,850,119,119,119,119,119,119,119,
+851,851,851,851,851,851,851,851,851,851,852,852,852,852,852,852,
+852,852,852,120,120,120,120,120,120,120,120,120,120,120,120,853,
+
+/* block 180 */
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+854,854,854,854,854,854,854,854,120,120,854,854,854,854,854,854,
+854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,
+854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,
+854,855,855,855,856,856,856,856,120,120,856,856,855,855,855,855,
+856,854,857,854,855,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 181 */
-851,851,851,851,851,851,851,851,851,119,851,851,851,851,851,851,
-851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,
-851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,852,
-853,853,853,853,853,853,853,119,853,853,853,853,853,853,852,853,
-851,854,854,854,854,854,119,119,119,119,119,119,119,119,119,119,
-855,855,855,855,855,855,855,855,855,855,856,856,856,856,856,856,
-856,856,856,856,856,856,856,856,856,856,856,856,856,119,119,119,
-857,857,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,859,859,859,859,859,859,859,859,859,859,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,859,859,859,859,859,859,860,861,859,859,859,859,862,
+862,862,862,862,862,862,862,859,120,120,120,120,120,120,120,120,
+863,864,864,864,864,864,864,865,865,864,864,864,863,863,863,863,
+863,863,863,863,863,863,863,863,863,863,863,863,863,863,863,863,
+863,863,863,863,863,863,863,863,863,863,863,863,863,863,863,863,
/* block 182 */
-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
-119,119,859,859,859,859,859,859,859,859,859,859,859,859,859,859,
-859,859,859,859,859,859,859,859,119,860,859,859,859,859,859,859,
-859,860,859,859,860,859,859,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+863,863,863,863,866,866,866,866,866,866,864,864,864,864,864,864,
+864,864,864,864,864,864,864,865,864,864,867,867,867,863,867,867,
+867,867,867,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+868,868,868,868,868,868,868,868,868,868,868,868,868,868,868,868,
+868,868,868,868,868,868,868,868,868,868,868,868,868,868,868,868,
+868,868,868,868,868,868,868,868,868,868,868,868,868,868,868,868,
+868,868,868,868,868,868,868,868,868,120,120,120,120,120,120,120,
/* block 183 */
-861,861,861,861,861,861,861,119,861,861,119,861,861,861,861,861,
-861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,
-861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,
-861,862,862,862,862,862,862,119,119,119,862,119,862,862,119,862,
-862,862,862,862,862,862,863,862,119,119,119,119,119,119,119,119,
-864,864,864,864,864,864,864,864,864,864,119,119,119,119,119,119,
-865,865,865,865,865,865,119,865,865,119,865,865,865,865,865,865,
-865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,
+869,869,869,869,869,869,869,869,869,120,869,869,869,869,869,869,
+869,869,869,869,869,869,869,869,869,869,869,869,869,869,869,869,
+869,869,869,869,869,869,869,869,869,869,869,869,869,869,869,870,
+871,871,871,871,871,871,871,120,871,871,871,871,871,871,870,871,
+869,872,872,872,872,872,120,120,120,120,120,120,120,120,120,120,
+873,873,873,873,873,873,873,873,873,873,874,874,874,874,874,874,
+874,874,874,874,874,874,874,874,874,874,874,874,874,120,120,120,
+875,875,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
/* block 184 */
-865,865,865,865,865,865,865,865,865,865,866,866,866,866,866,119,
-867,867,119,866,866,867,866,867,865,119,119,119,119,119,119,119,
-868,868,868,868,868,868,868,868,868,868,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
+120,120,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
+877,877,877,877,877,877,877,877,120,878,877,877,877,877,877,877,
+877,878,877,877,878,877,877,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 185 */
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-869,869,869,869,869,869,869,869,869,869,869,869,869,869,869,869,
-869,869,869,870,870,871,871,872,872,119,119,119,119,119,119,119,
+879,879,879,879,879,879,879,120,879,879,120,879,879,879,879,879,
+879,879,879,879,879,879,879,879,879,879,879,879,879,879,879,879,
+879,879,879,879,879,879,879,879,879,879,879,879,879,879,879,879,
+879,880,880,880,880,880,880,120,120,120,880,120,880,880,120,880,
+880,880,880,880,880,880,881,880,120,120,120,120,120,120,120,120,
+882,882,882,882,882,882,882,882,882,882,120,120,120,120,120,120,
+883,883,883,883,883,883,120,883,883,120,883,883,883,883,883,883,
+883,883,883,883,883,883,883,883,883,883,883,883,883,883,883,883,
/* block 186 */
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
+883,883,883,883,883,883,883,883,883,883,884,884,884,884,884,120,
+885,885,120,884,884,885,884,885,883,120,120,120,120,120,120,120,
+886,886,886,886,886,886,886,886,886,886,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 187 */
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+887,887,887,887,887,887,887,887,887,887,887,887,887,887,887,887,
+887,887,887,888,888,889,889,890,890,120,120,120,120,120,120,120,
/* block 188 */
-874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,
-874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,
-874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,
-874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,
-874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,
-874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,
-874,874,874,874,874,874,874,874,874,874,874,874,874,874,874,119,
-875,875,875,875,875,119,119,119,119,119,119,119,119,119,119,119,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,
+294,294,891,294,891,296,296,296,296,296,296,296,296,297,297,297,
+297,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,
+296,296,120,120,120,120,120,120,120,120,120,120,120,120,120,892,
/* block 189 */
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,873,
-873,873,873,873,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
/* block 190 */
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 191 */
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,
-876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,
+894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,
+894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,
+894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,
+894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,
+894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,
+894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,120,
+895,895,895,895,895,120,120,120,120,120,120,120,120,120,120,120,
/* block 192 */
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
+893,893,893,893,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 193 */
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,877,
-877,877,877,877,877,877,877,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
/* block 194 */
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
+896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,120,
+897,897,897,897,897,897,897,897,897,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 195 */
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,119,119,119,119,119,119,119,
-878,878,878,878,878,878,878,878,878,878,878,878,878,878,878,878,
-878,878,878,878,878,878,878,878,878,878,878,878,878,878,878,119,
-879,879,879,879,879,879,879,879,879,879,119,119,119,119,880,880,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
/* block 196 */
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,
-881,881,881,881,881,881,881,881,881,881,881,881,881,881,119,119,
-882,882,882,882,882,883,119,119,119,119,119,119,119,119,119,119,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,
+898,898,898,898,898,898,898,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 197 */
-884,884,884,884,884,884,884,884,884,884,884,884,884,884,884,884,
-884,884,884,884,884,884,884,884,884,884,884,884,884,884,884,884,
-884,884,884,884,884,884,884,884,884,884,884,884,884,884,884,884,
-885,885,885,885,885,885,885,886,886,886,886,886,887,887,887,887,
-888,888,888,888,886,887,119,119,119,119,119,119,119,119,119,119,
-889,889,889,889,889,889,889,889,889,889,119,890,890,890,890,890,
-890,890,119,884,884,884,884,884,884,884,884,884,884,884,884,884,
-884,884,884,884,884,884,884,884,119,119,119,119,119,884,884,884,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
/* block 198 */
-884,884,884,884,884,884,884,884,884,884,884,884,884,884,884,884,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,120,120,120,120,120,120,120,
+899,899,899,899,899,899,899,899,899,899,899,899,899,899,899,899,
+899,899,899,899,899,899,899,899,899,899,899,899,899,899,899,120,
+900,900,900,900,900,900,900,900,900,900,120,120,120,120,901,901,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 199 */
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,
-891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,
-892,892,892,892,892,892,892,892,892,892,892,892,892,892,892,892,
-892,892,892,892,892,892,892,892,892,892,892,892,892,892,892,892,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
+902,902,902,902,902,902,902,902,902,902,902,902,902,902,120,120,
+903,903,903,903,903,904,120,120,120,120,120,120,120,120,120,120,
/* block 200 */
-893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,
-893,893,893,893,893,893,893,894,894,894,894,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,
+905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,
+905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,
+906,906,906,906,906,906,906,907,907,907,907,907,908,908,908,908,
+909,909,909,909,907,908,120,120,120,120,120,120,120,120,120,120,
+910,910,910,910,910,910,910,910,910,910,120,911,911,911,911,911,
+911,911,120,905,905,905,905,905,905,905,905,905,905,905,905,905,
+905,905,905,905,905,905,905,905,120,120,120,120,120,905,905,905,
/* block 201 */
-895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,
-895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,
-895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,
-895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,
-895,895,895,895,895,119,119,119,119,119,119,119,119,119,119,119,
-895,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
-896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
-896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,119,
+905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 202 */
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,897,
-897,897,897,898,898,898,898,898,898,898,898,898,898,898,898,898,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-899,900,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,
+912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,
+913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,
+913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,
/* block 203 */
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
+914,914,914,914,914,914,914,914,914,914,914,914,914,914,914,914,
+914,914,914,914,914,914,914,915,915,915,915,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 204 */
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,
+916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,
+916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,
+916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,
+916,916,916,916,916,916,916,916,916,916,916,120,120,120,120,917,
+916,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,
+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,
+918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,
/* block 205 */
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,901,
-901,901,901,119,119,119,119,119,119,119,119,119,119,119,119,119,
+918,918,918,918,918,918,918,918,120,120,120,120,120,120,120,917,
+917,917,917,919,919,919,919,919,919,919,919,919,919,919,919,919,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+920,921, 5,111,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 206 */
-569,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
/* block 207 */
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,120,120,120,120,120,120,120,120,
/* block 208 */
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
+922,922,922,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 209 */
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
+578,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
/* block 210 */
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,119,119,119,119,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
/* block 211 */
-903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,
-903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,
-903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,
-903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,
-903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,
-903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,
-903,903,903,903,903,903,903,903,903,903,903,119,119,119,119,119,
-903,903,903,903,903,903,903,903,903,903,903,903,903,119,119,119,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+573,573,573,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,578,578,578,578,120,120,120,120,120,120,120,120,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
/* block 212 */
-903,903,903,903,903,903,903,903,903,119,119,119,119,119,119,119,
-903,903,903,903,903,903,903,903,903,903,119,119,904,905,905,906,
-907,907,907,907,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
/* block 213 */
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+923,923,923,923,923,923,923,923,923,923,923,923,120,120,120,120,
+
+/* block 214 */
+924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
+924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
+924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
+924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
+924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
+924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
+924,924,924,924,924,924,924,924,924,924,924,120,120,120,120,120,
+924,924,924,924,924,924,924,924,924,924,924,924,924,120,120,120,
+
+/* block 215 */
+924,924,924,924,924,924,924,924,924,120,120,120,120,120,120,120,
+924,924,924,924,924,924,924,924,924,924,120,120,925,926,926,927,
+928,928,928,928,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+
+/* block 216 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
@@ -3802,309 +3867,339 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20,119,119,119,119,119,119,119,119,119,119,
+ 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,120,
-/* block 214 */
+/* block 217 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20,119,119, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20,120,120, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20,908,909,112,112,112, 20, 20, 20,909,908,908,
-908,908,908, 24, 24, 24, 24, 24, 24, 24, 24,112,112,112,112,112,
+ 20, 20, 20, 20, 20,929,930,113,113,113, 20, 20, 20,930,929,929,
+929,929,929, 24, 24, 24, 24, 24, 24, 24, 24,113,113,113,113,113,
-/* block 215 */
-112,112,112, 20, 20,112,112,112,112,112,112,112, 20, 20, 20, 20,
+/* block 218 */
+113,113,113, 20, 20,113,113,113,113,113,113,113, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,112,112,112,112, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,113,113,113,113, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-/* block 216 */
-671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
-671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
-671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
-671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
-671,671,910,910,910,671,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+/* block 219 */
+684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,
+684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,
+684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,
+684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,
+684,684,931,931,931,684,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-/* block 217 */
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+/* block 220 */
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25,119,119,119,119,119,119,119,119,119,119,119,119,
+ 25, 25, 25, 25,120,120,120,120,120,120,120,120,120,120,120,120,
-/* block 218 */
+/* block 221 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20,119,119,119,119,119,119,119,119,119,
-573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
-573,573, 25, 25, 25, 25, 25, 25, 25,119,119,119,119,119,119,119,
-
-/* block 219 */
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,504,504,504,504,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,505,505,
-505,505,505,505,505,119,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
-
-/* block 220 */
-504,504,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,504,119,504,504,
-119,119,504,119,119,504,504,119,119,504,504,504,504,119,504,504,
-504,504,504,504,504,504,505,505,505,505,119,505,119,505,505,505,
-505,505,505,505,119,505,505,505,505,505,505,505,505,505,505,505,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-
-/* block 221 */
-505,505,505,505,504,504,119,504,504,504,504,119,119,504,504,504,
-504,504,504,504,504,119,504,504,504,504,504,504,504,119,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,504,504,119,504,504,504,504,119,
-504,504,504,504,504,119,504,119,119,119,504,504,504,504,504,504,
-504,119,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
+ 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,
+582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,
+582,582, 25, 25, 25, 25, 25, 25, 25,120,120,120,120,120,120,120,
/* block 222 */
-504,504,504,504,504,504,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,504,504,504,504,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,514,514,
+514,514,514,514,514,120,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
/* block 223 */
-505,505,505,505,505,505,505,505,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
-504,504,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
+513,513,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,513,120,513,513,
+120,120,513,120,120,513,513,120,120,513,513,513,513,120,513,513,
+513,513,513,513,513,513,514,514,514,514,120,514,120,514,514,514,
+514,514,514,514,120,514,514,514,514,514,514,514,514,514,514,514,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
/* block 224 */
-504,504,504,504,504,504,504,504,504,504,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505,505,119,119,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
-504, 9,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505, 9,505,505,505,505,
-505,505,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,504, 9,505,505,505,505,
+514,514,514,514,513,513,120,513,513,513,513,120,120,513,513,513,
+513,513,513,513,513,120,513,513,513,513,513,513,513,120,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,513,513,120,513,513,513,513,120,
+513,513,513,513,513,120,513,120,120,120,513,513,513,513,513,513,
+513,120,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
/* block 225 */
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505, 9,505,505,505,505,505,505,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
-504,504,504,504,504, 9,505,505,505,505,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505, 9,
-505,505,505,505,505,505,504,504,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504, 9,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
+513,513,513,513,513,513,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
/* block 226 */
-505,505,505,505,505,505,505,505,505, 9,505,505,505,505,505,505,
-504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
-504,504,504,504,504,504,504,504,504, 9,505,505,505,505,505,505,
-505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
-505,505,505, 9,505,505,505,505,505,505,504,505,119,119, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+514,514,514,514,514,514,514,514,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
/* block 227 */
-911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,
-911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,
-911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,
-911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,
-911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,
-911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,
-911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,
-911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,
+513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,120,120,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513, 9,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514, 9,514,514,514,514,
+514,514,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513, 9,514,514,514,514,
/* block 228 */
-912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,
-912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,
-912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,
-912,912,912,912,912,912,912,911,911,911,911,912,912,912,912,912,
-912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,
-912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,
-912,912,912,912,912,912,912,912,912,912,912,912,912,911,911,911,
-911,911,911,911,911,912,911,911,911,911,911,911,911,911,911,911,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514, 9,514,514,514,514,514,514,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,513, 9,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, 9,
+514,514,514,514,514,514,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, 9,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
/* block 229 */
-911,911,911,911,912,911,911,913,913,913,913,913,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,912,912,912,912,912,
-119,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+514,514,514,514,514,514,514,514,514, 9,514,514,514,514,514,514,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513, 9,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514, 9,514,514,514,514,514,514,513,514,120,120, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
/* block 230 */
-914,914,914,914,914,914,914,119,914,914,914,914,914,914,914,914,
-914,914,914,914,914,914,914,914,914,119,119,914,914,914,914,914,
-914,914,119,914,914,119,914,914,914,914,914,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
+932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
+932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
+932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
+932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
+932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
+932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
+932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
/* block 231 */
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
+933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,
+933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,
+933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,
+933,933,933,933,933,933,933,932,932,932,932,933,933,933,933,933,
+933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,
+933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,
+933,933,933,933,933,933,933,933,933,933,933,933,933,932,932,932,
+932,932,932,932,932,933,932,932,932,932,932,932,932,932,932,932,
/* block 232 */
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,915,915,119,119,916,916,916,916,916,916,916,916,916,
-917,917,917,917,917,917,917,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+932,932,932,932,933,932,932,934,934,934,934,934,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,933,933,933,933,933,
+120,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 233 */
-918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,
-918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,
-918,918,919,919,919,919,919,919,919,919,919,919,919,919,919,919,
-919,919,919,919,919,919,919,919,919,919,919,919,919,919,919,919,
-919,919,919,919,920,920,920,920,920,920,920,119,119,119,119,119,
-921,921,921,921,921,921,921,921,921,921,119,119,119,119,922,922,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+935,935,935,935,935,935,935,120,935,935,935,935,935,935,935,935,
+935,935,935,935,935,935,935,935,935,120,120,935,935,935,935,935,
+935,935,120,935,935,120,935,935,935,935,935,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 234 */
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+936,936,936,936,936,936,936,936,936,936,936,936,936,936,936,936,
+936,936,936,936,936,936,936,936,936,936,936,936,936,936,936,936,
+936,936,936,936,936,936,936,936,936,936,936,936,936,120,120,120,
+937,937,937,937,937,937,937,938,938,938,938,938,938,938,120,120,
+939,939,939,939,939,939,939,939,939,939,120,120,120,120,936,940,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 235 */
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 25, 25, 25,
- 6, 25, 25, 25, 25,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+941,941,941,941,941,941,941,941,941,941,941,941,941,941,941,941,
+941,941,941,941,941,941,941,941,941,941,941,941,941,941,941,941,
+941,941,941,941,941,941,941,941,941,941,941,941,942,942,942,942,
+943,943,943,943,943,943,943,943,943,943,120,120,120,120,120,944,
/* block 236 */
-224,224,224,224,119,224,224,224,224,224,224,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-119,224,224,119,224,119,119,224,119,224,224,224,224,224,224,224,
-224,224,224,119,224,224,224,224,119,224,119,224,119,119,119,119,
-119,119,224,119,119,119,119,224,119,224,119,224,119,224,224,224,
-119,224,224,119,224,119,119,224,119,224,119,224,119,224,119,224,
-119,224,224,119,224,119,119,224,224,224,224,119,224,224,224,224,
-224,224,224,119,224,224,224,224,119,224,224,224,224,119,224,119,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
/* block 237 */
-224,224,224,224,224,224,224,224,224,224,119,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,119,119,119,119,
-119,224,224,224,119,224,224,224,224,224,119,224,224,224,224,224,
-224,224,224,224,224,224,224,224,224,224,224,224,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-217,217,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+945,945,945,945,945,120,120,946,946,946,946,946,946,946,946,946,
+947,947,947,947,947,947,947,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 238 */
+948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,
+948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,
+948,948,949,949,949,949,949,949,949,949,949,949,949,949,949,949,
+949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,
+949,949,949,949,950,950,950,950,950,950,950,951,120,120,120,120,
+952,952,952,952,952,952,952,952,952,952,120,120,120,120,953,953,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+
+/* block 239 */
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+
+/* block 240 */
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 25, 25, 25,
+ 6, 25, 25, 25, 25,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+
+/* block 241 */
+120, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+
+/* block 242 */
+225,225,225,225,120,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+120,225,225,120,225,120,120,225,120,225,225,225,225,225,225,225,
+225,225,225,120,225,225,225,225,120,225,120,225,120,120,120,120,
+120,120,225,120,120,120,120,225,120,225,120,225,120,225,225,225,
+120,225,225,120,225,120,120,225,120,225,120,225,120,225,120,225,
+120,225,225,120,225,120,120,225,225,225,225,120,225,225,225,225,
+225,225,225,120,225,225,225,225,120,225,225,225,225,120,225,120,
+
+/* block 243 */
+225,225,225,225,225,225,225,225,225,225,120,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,120,120,120,120,
+120,225,225,225,120,225,225,225,225,225,120,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+218,218,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+
+/* block 244 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,923,923,923,923,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954,954,954,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-/* block 239 */
+/* block 245 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21,923,923,923,923,923,923,923,923,923,923,923,923,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,923,
-923, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-923, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-923, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954,954,954,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,
+954, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+954, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+954, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21,923,923,923,923,923,923,923,923,923,923,
+ 21, 21, 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954,
-/* block 240 */
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,923,923,923,
+/* block 246 */
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,954,954,954,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,923,923,923,923,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,954,954,954,
21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21,
-/* block 241 */
+/* block 247 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 20,
20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,924,924,924,924,924,924,924,924,924,924,
-924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,955,955,955,955,955,955,955,955,955,955,
+955,955,955,955,955,955,955,955,955,955,955,955,955,955,955,955,
-/* block 242 */
-925, 21, 21,923,923,923,923,923,923,923,923,923,923,923,923,923,
+/* block 248 */
+956, 21, 21,954,954,954,954,954,954,954,954,954,954,954,954,954,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
- 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20,923,923,923,923,
- 20, 20, 20, 20, 20, 20, 20, 20, 20,923,923,923,923,923,923,923,
-575,575,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
- 21, 21, 21, 21, 21, 21,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+ 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20,954,954,954,954,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,954,954,954,954,
+584,584,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+ 21, 21, 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
-/* block 243 */
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+/* block 249 */
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
-/* block 244 */
+/* block 250 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
@@ -4114,7 +4209,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-/* block 245 */
+/* block 251 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
@@ -4122,9 +4217,9 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,926,926,926,926,926,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,957,957,957,957,957,
-/* block 246 */
+/* block 252 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
@@ -4134,7 +4229,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-/* block 247 */
+/* block 253 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
@@ -4144,17 +4239,17 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-/* block 248 */
+/* block 254 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21,923,923,923,923,923,923,923,923,923,923,923,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,923,923,923,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,923,923,923,923,923,923,
+ 21, 21, 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954,954,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954,954,954,954,
-/* block 249 */
+/* block 255 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
@@ -4162,187 +4257,197 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 68608 bytes, block = 128 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20,923,923,923,923,923,923,923,923,923,923,923,923,
+ 20, 20, 20, 20,954,954,954,954,954,954,954,954,954,954,954,954,
-/* block 250 */
+/* block 256 */
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 21, 21, 21, 21,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+ 20, 20, 20, 20, 20, 21, 21, 21, 21,954,954,954,954,954,954,954,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
-/* block 251 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,923,923,923,923,
+/* block 257 */
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,954,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20,923,923,923,923,923,923,923,923,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,923,923,923,923,923,923,
+ 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,954,954,954,954,954,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,954,954,954,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-/* block 252 */
- 20, 20, 20, 20, 20, 20, 20, 20,923,923,923,923,923,923,923,923,
+/* block 258 */
+ 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,954,954,954,954,954,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
-/* block 253 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,923,923,923,923,
+/* block 259 */
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,954, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 21, 21, 21,923,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21,923,923, 21, 21, 21, 21,923,923,923, 21,923, 21, 21, 21, 21,
+ 21, 21,954, 21, 21, 21, 21,954,954,954, 21, 21, 21, 21, 21, 21,
-/* block 254 */
+/* block 260 */
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21,923,923,923,923,923,923,923,923,923,923,923,923,923,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,923,923,923,923,923,923,
- 21, 21, 21,923,923,923,923,923,923,923,923,923,923,923,923,923,
+ 21, 21, 21,954,954, 21, 21, 21, 21, 21, 21,954,954,954, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-
-/* block 255 */
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-
-/* block 256 */
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,
-923,923,923,923,923,923,923,923,923,923,923,923,923,923,119,119,
-
-/* block 257 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-
-/* block 258 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,119,119,119,119,119,119,119,119,119,119,119,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-
-/* block 259 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,119,119,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-
-/* block 260 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
/* block 261 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954,954,954,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954,
+ 21, 21, 21, 21,954,954,954,954, 21, 21, 21,954,954,954,954,954,
/* block 262 */
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+ 21, 21, 21,954,954,954,954,954,954,954,954,954,954,954,954,954,
+ 21, 21, 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
/* block 263 */
-502, 24,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
-927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,
-927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,
-927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,
-927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,
-927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,
-927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,
+954,954,954,954,954,954,954,954,954,954,954,954,954,954,120,120,
/* block 264 */
-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
/* block 265 */
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,120,120,120,120,120,120,120,120,120,120,120,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
/* block 266 */
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,120,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
/* block 267 */
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
-659,659,659,659,659,659,659,659,659,659,659,659,659,659,119,119,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+
+/* block 268 */
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+
+/* block 269 */
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+
+/* block 270 */
+511, 24,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
+958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
+958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
+958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
+958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
+958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
+
+/* block 271 */
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+
+/* block 272 */
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+
+/* block 273 */
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+
+/* block 274 */
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,120,120,
};
diff --git a/thirdparty/pcre2/src/pcre2_ucp.h b/thirdparty/pcre2/src/pcre2_ucp.h
index 483abd18fc..84b22fb064 100644
--- a/thirdparty/pcre2/src/pcre2_ucp.h
+++ b/thirdparty/pcre2/src/pcre2_ucp.h
@@ -281,7 +281,12 @@ enum {
ucp_Makasar,
ucp_Medefaidrin,
ucp_Old_Sogdian,
- ucp_Sogdian
+ ucp_Sogdian,
+ /* New for Unicode 12.0.0 */
+ ucp_Elymaic,
+ ucp_Nandinagari,
+ ucp_Nyiakeng_Puachue_Hmong,
+ ucp_Wancho
};
#endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */
diff --git a/thirdparty/pcre2/src/sljit/sljitConfigInternal.h b/thirdparty/pcre2/src/sljit/sljitConfigInternal.h
index ba60311e45..acba9da4be 100644
--- a/thirdparty/pcre2/src/sljit/sljitConfigInternal.h
+++ b/thirdparty/pcre2/src/sljit/sljitConfigInternal.h
@@ -214,6 +214,10 @@
#define SLJIT_MEMCPY(dest, src, len) memcpy(dest, src, len)
#endif
+#ifndef SLJIT_MEMMOVE
+#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)
+#endif
+
#ifndef SLJIT_ZEROMEM
#define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len)
#endif
diff --git a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
index 3b37a9751f..92ddb94914 100644
--- a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
+++ b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
@@ -118,10 +118,20 @@ static SLJIT_INLINE int get_map_jit_flag()
if (map_jit_flag == -1) {
struct utsname name;
+ map_jit_flag = 0;
uname(&name);
/* Kernel version for 10.14.0 (Mojave) */
- map_jit_flag = (atoi(name.release) >= 18) ? MAP_JIT : 0;
+ if (atoi(name.release) >= 18) {
+ /* Only use MAP_JIT if a hardened runtime is used, because MAP_JIT is incompatible with fork(). */
+ void *ptr = mmap(NULL, getpagesize(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+
+ if (ptr == MAP_FAILED) {
+ map_jit_flag = MAP_JIT;
+ } else {
+ munmap(ptr, getpagesize());
+ }
+ }
}
return map_jit_flag;
@@ -137,6 +147,7 @@ static SLJIT_INLINE int get_map_jit_flag()
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
void *retval;
+ const int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
#ifdef MAP_ANON
@@ -146,16 +157,25 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
flags |= get_map_jit_flag();
#endif
- retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, flags, -1, 0);
+ retval = mmap(NULL, size, prot, flags, -1, 0);
#else /* !MAP_ANON */
if (dev_zero < 0) {
if (open_dev_zero())
return NULL;
}
- retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0);
+ retval = mmap(NULL, size, prot, MAP_PRIVATE, dev_zero, 0);
#endif /* MAP_ANON */
- return (retval != MAP_FAILED) ? retval : NULL;
+ if (retval == MAP_FAILED)
+ retval = NULL;
+ else {
+ if (mprotect(retval, size, prot) < 0) {
+ munmap(retval, size);
+ retval = NULL;
+ }
+ }
+
+ return retval;
}
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
diff --git a/thirdparty/pcre2/src/sljit/sljitLir.c b/thirdparty/pcre2/src/sljit/sljitLir.c
index ded9541b31..9bab0c3ec6 100644
--- a/thirdparty/pcre2/src/sljit/sljitLir.c
+++ b/thirdparty/pcre2/src/sljit/sljitLir.c
@@ -144,6 +144,7 @@
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
# define PATCH_MD 0x10
#endif
+# define TYPE_SHIFT 13
#endif
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
@@ -521,6 +522,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
}
}
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label)
+{
+ if (SLJIT_LIKELY(!!put_label))
+ put_label->label = label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
{
SLJIT_UNUSED_ARG(compiler);
@@ -620,6 +627,30 @@ static SLJIT_INLINE sljit_s32 get_arg_count(sljit_s32 arg_types)
return arg_count;
}
+#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+
+static SLJIT_INLINE sljit_uw compute_next_addr(struct sljit_label *label, struct sljit_jump *jump,
+ struct sljit_const *const_, struct sljit_put_label *put_label)
+{
+ sljit_uw result = ~(sljit_uw)0;
+
+ if (label)
+ result = label->size;
+
+ if (jump && jump->addr < result)
+ result = jump->addr;
+
+ if (const_ && const_->addr < result)
+ result = const_->addr;
+
+ if (put_label && put_label->addr < result)
+ result = put_label->addr;
+
+ return result;
+}
+
+#endif /* !SLJIT_CONFIG_X86 */
+
static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,
sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
@@ -687,6 +718,19 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
compiler->last_const = const_;
}
+static SLJIT_INLINE void set_put_label(struct sljit_put_label *put_label, struct sljit_compiler *compiler, sljit_uw offset)
+{
+ put_label->next = NULL;
+ put_label->label = NULL;
+ put_label->addr = compiler->size - offset;
+ put_label->flags = 0;
+ if (compiler->last_put_label)
+ compiler->last_put_label->next = put_label;
+ else
+ compiler->put_labels = put_label;
+ compiler->last_put_label = put_label;
+}
+
#define ADDRESSING_DEPENDS_ON(exp, reg) \
(((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))
@@ -1905,6 +1949,21 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil
CHECK_RETURN_OK;
}
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ FUNCTION_CHECK_DST(dst, dstw, 0);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " put_label ");
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif
+ CHECK_RETURN_OK;
+}
+
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \
@@ -2581,6 +2640,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return NULL;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(dst);
+ SLJIT_UNUSED_ARG(dstw);
+ return NULL;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
SLJIT_UNUSED_ARG(addr);
@@ -2597,4 +2664,4 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
SLJIT_UNREACHABLE();
}
-#endif
+#endif /* !SLJIT_CONFIG_UNSUPPORTED */
diff --git a/thirdparty/pcre2/src/sljit/sljitLir.h b/thirdparty/pcre2/src/sljit/sljitLir.h
index e71890cf7b..836d25cf71 100644
--- a/thirdparty/pcre2/src/sljit/sljitLir.h
+++ b/thirdparty/pcre2/src/sljit/sljitLir.h
@@ -348,13 +348,20 @@ struct sljit_label {
struct sljit_jump {
struct sljit_jump *next;
sljit_uw addr;
- sljit_sw flags;
+ sljit_uw flags;
union {
sljit_uw target;
- struct sljit_label* label;
+ struct sljit_label *label;
} u;
};
+struct sljit_put_label {
+ struct sljit_put_label *next;
+ struct sljit_label *label;
+ sljit_uw addr;
+ sljit_uw flags;
+};
+
struct sljit_const {
struct sljit_const *next;
sljit_uw addr;
@@ -366,10 +373,12 @@ struct sljit_compiler {
struct sljit_label *labels;
struct sljit_jump *jumps;
+ struct sljit_put_label *put_labels;
struct sljit_const *consts;
struct sljit_label *last_label;
struct sljit_jump *last_jump;
struct sljit_const *last_const;
+ struct sljit_put_label *last_put_label;
void *allocator_data;
struct sljit_memory_fragment *buf;
@@ -1314,10 +1323,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
Flags: - (may destroy flags) */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset);
-/* The constant can be changed runtime (see: sljit_set_const)
+/* Store a value that can be changed runtime (see: sljit_get_const_addr / sljit_set_const)
Flags: - (does not modify flags) */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value);
+/* Store the value of a label (see: sljit_set_put_label)
+ Flags: - (does not modify flags) */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);
+
+/* Set the value stored by put_label to this label. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label);
+
/* After the code generation the address for label, jump and const instructions
are computed. Since these structures are freed by sljit_free_compiler, the
addresses must be preserved by the user program elsewere. */
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c
index 6d61eed9a7..71f7bcdadb 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c
@@ -583,8 +583,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_uw *buf_end;
sljit_uw size;
sljit_uw word_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
- sljit_sw jump_addr;
+ sljit_sw addr;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
sljit_uw cpool_size;
sljit_uw cpool_skip_alignment;
@@ -597,6 +598,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -625,11 +627,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ next_addr = 1;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
if (label && label->size == 0) {
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
@@ -669,35 +673,45 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {
#endif
*code_ptr = *buf_ptr++;
+ if (next_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
+
/* These structures are ordered by their address. */
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
- if (jump && jump->addr == word_count) {
+ if (jump && jump->addr == word_count) {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- if (detect_jump_type(jump, code_ptr, code, executable_offset))
- code_ptr--;
- jump->addr = (sljit_uw)code_ptr;
+ if (detect_jump_type(jump, code_ptr, code, executable_offset))
+ code_ptr--;
+ jump->addr = (sljit_uw)code_ptr;
#else
- jump->addr = (sljit_uw)(code_ptr - 2);
- if (detect_jump_type(jump, code_ptr, code, executable_offset))
- code_ptr -= 2;
+ jump->addr = (sljit_uw)(code_ptr - 2);
+ if (detect_jump_type(jump, code_ptr, code, executable_offset))
+ code_ptr -= 2;
#endif
- jump = jump->next;
- }
- if (label && label->size == word_count) {
- /* code_ptr can be affected above. */
- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);
- label->size = (code_ptr + 1) - code;
- label = label->next;
- }
- if (const_ && const_->addr == word_count) {
+ jump = jump->next;
+ }
+ if (label && label->size == word_count) {
+ /* code_ptr can be affected above. */
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);
+ label->size = (code_ptr + 1) - code;
+ label = label->next;
+ }
+ if (const_ && const_->addr == word_count) {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- const_->addr = (sljit_uw)code_ptr;
+ const_->addr = (sljit_uw)code_ptr;
#else
- const_->addr = (sljit_uw)(code_ptr - 1);
+ const_->addr = (sljit_uw)(code_ptr - 1);
#endif
- const_ = const_->next;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == word_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr++;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
@@ -725,6 +739,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
SLJIT_ASSERT(cpool_size == 0);
@@ -755,15 +770,15 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr = (sljit_uw *)jump->addr;
if (jump->flags & PATCH_B) {
- jump_addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
+ addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
if (!(jump->flags & JUMP_ADDR)) {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - jump_addr) >= -0x02000000);
- *buf_ptr |= (((sljit_sw)jump->u.label->addr - jump_addr) >> 2) & 0x00ffffff;
+ SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - addr) >= -0x02000000);
+ *buf_ptr |= (((sljit_sw)jump->u.label->addr - addr) >> 2) & 0x00ffffff;
}
else {
- SLJIT_ASSERT(((sljit_sw)jump->u.target - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - jump_addr) >= -0x02000000);
- *buf_ptr |= (((sljit_sw)jump->u.target - jump_addr) >> 2) & 0x00ffffff;
+ SLJIT_ASSERT(((sljit_sw)jump->u.target - addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - addr) >= -0x02000000);
+ *buf_ptr |= (((sljit_sw)jump->u.target - addr) >> 2) & 0x00ffffff;
}
}
else if (jump->flags & SLJIT_REWRITABLE_JUMP) {
@@ -813,6 +828,22 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
#endif
+ put_label = compiler->put_labels;
+ while (put_label) {
+ addr = put_label->label->addr;
+ buf_ptr = (sljit_uw*)put_label->addr;
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+ SLJIT_ASSERT((buf_ptr[0] & 0xffff0000) == 0xe59f0000);
+ buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr;
+#else
+ SLJIT_ASSERT((buf_ptr[-1] & 0xfff00000) == MOVW && (buf_ptr[0] & 0xfff00000) == MOVT);
+ buf_ptr[-1] |= ((addr << 4) & 0xf0000) | (addr & 0xfff);
+ buf_ptr[0] |= ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff);
+#endif
+ put_label = put_label->next;
+ }
+
SLJIT_ASSERT(code_ptr - code <= (sljit_s32)size);
compiler->error = SLJIT_ERR_COMPILED;
@@ -2639,28 +2670,55 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
- sljit_s32 reg;
+ sljit_s32 dst_r;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+
+#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), init_value));
+ compiler->patches++;
+#else
+ PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));
+#endif
+
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
- reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG2;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), init_value));
+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0));
compiler->patches++;
#else
- PTR_FAIL_IF(emit_imm(compiler, reg, init_value));
+ PTR_FAIL_IF(emit_imm(compiler, dst_r, 0));
#endif
- set_const(const_, compiler);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
- return const_;
+ return put_label;
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c
index b015695c52..e15b3451e8 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c
@@ -161,7 +161,7 @@ static SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm)
inst[3] = MOVK | dst | ((new_imm >> 48) << 5) | (3 << 21);
}
-static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
+static SLJIT_INLINE sljit_sw detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
{
sljit_sw diff;
sljit_uw target_addr;
@@ -196,14 +196,14 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
return 4;
}
- if (target_addr <= 0xffffffffl) {
+ if (target_addr < 0x100000000l) {
if (jump->flags & IS_COND)
code_ptr[-5] -= (2 << 5);
code_ptr[-2] = code_ptr[0];
return 2;
}
- if (target_addr <= 0xffffffffffffl) {
+ if (target_addr < 0x1000000000000l) {
if (jump->flags & IS_COND)
code_ptr[-5] -= (1 << 5);
jump->flags |= PATCH_ABS48;
@@ -215,6 +215,22 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
return 0;
}
+static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
+{
+ if (max_label < 0x100000000l) {
+ put_label->flags = 0;
+ return 2;
+ }
+
+ if (max_label < 0x1000000000000l) {
+ put_label->flags = 1;
+ return 1;
+ }
+
+ put_label->flags = 2;
+ return 0;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
{
struct sljit_memory_fragment *buf;
@@ -223,6 +239,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
sljit_uw addr;
sljit_s32 dst;
@@ -230,6 +247,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -241,34 +259,47 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ next_addr = 0;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
do {
*code_ptr = *buf_ptr++;
- /* These structures are ordered by their address. */
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
- if (label && label->size == word_count) {
- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
- label = label->next;
- }
- if (jump && jump->addr == word_count) {
- jump->addr = (sljit_uw)(code_ptr - 4);
- code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
- jump = jump->next;
- }
- if (const_ && const_->addr == word_count) {
- const_->addr = (sljit_uw)code_ptr;
- const_ = const_->next;
+ if (next_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (label && label->size == word_count) {
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == word_count) {
+ jump->addr = (sljit_uw)(code_ptr - 4);
+ code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
+ jump = jump->next;
+ }
+ if (const_ && const_->addr == word_count) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == word_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)(code_ptr - 3);
+ code_ptr -= put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr ++;
word_count ++;
@@ -286,6 +317,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
jump = compiler->jumps;
@@ -323,6 +355,23 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
+ put_label = compiler->put_labels;
+ while (put_label) {
+ addr = put_label->label->addr;
+ buf_ptr = (sljit_ins *)put_label->addr;
+
+ buf_ptr[0] |= (addr & 0xffff) << 5;
+ buf_ptr[1] |= ((addr >> 16) & 0xffff) << 5;
+
+ if (put_label->flags >= 1)
+ buf_ptr[2] |= ((addr >> 32) & 0xffff) << 5;
+
+ if (put_label->flags >= 2)
+ buf_ptr[3] |= ((addr >> 48) & 0xffff) << 5;
+
+ put_label = put_label->next;
+ }
+
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
@@ -1947,6 +1996,28 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return const_;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, 0));
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 1);
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
+
+ return put_label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins* inst = (sljit_ins*)addr;
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
index d7024b6d7d..cdfe4a4d24 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
@@ -365,11 +365,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_u16 *buf_ptr;
sljit_u16 *buf_end;
sljit_uw half_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -381,34 +383,46 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
half_count = 0;
+ next_addr = 0;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
do {
buf_ptr = (sljit_u16*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 1);
do {
*code_ptr = *buf_ptr++;
- /* These structures are ordered by their address. */
- SLJIT_ASSERT(!label || label->size >= half_count);
- SLJIT_ASSERT(!jump || jump->addr >= half_count);
- SLJIT_ASSERT(!const_ || const_->addr >= half_count);
- if (label && label->size == half_count) {
- label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
- label->size = code_ptr - code;
- label = label->next;
- }
- if (jump && jump->addr == half_count) {
- jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);
- code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
- jump = jump->next;
- }
- if (const_ && const_->addr == half_count) {
- const_->addr = (sljit_uw)code_ptr;
- const_ = const_->next;
+ if (next_addr == half_count) {
+ SLJIT_ASSERT(!label || label->size >= half_count);
+ SLJIT_ASSERT(!jump || jump->addr >= half_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= half_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= half_count);
+
+ /* These structures are ordered by their address. */
+ if (label && label->size == half_count) {
+ label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == half_count) {
+ jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);
+ code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset);
+ jump = jump->next;
+ }
+ if (const_ && const_->addr == half_count) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == half_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr ++;
half_count ++;
@@ -426,6 +440,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
jump = compiler->jumps;
@@ -434,6 +449,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
+ put_label = compiler->put_labels;
+ while (put_label) {
+ modify_imm32_const((sljit_u16 *)put_label->addr, put_label->label->addr);
+ put_label = put_label->next;
+ }
+
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_u16);
@@ -2311,6 +2332,27 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return const_;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, 0));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
+ return put_label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_u16 *inst = (sljit_u16*)addr;
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
index ad970bf25a..16dec052fe 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
@@ -425,6 +425,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
@@ -435,6 +436,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
index e0d6a3f085..7d1d087496 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
@@ -449,6 +449,55 @@ static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_
}
#endif
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+
+static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
+{
+ if (max_label < 0x80000000l) {
+ put_label->flags = 0;
+ return 1;
+ }
+
+ if (max_label < 0x800000000000l) {
+ put_label->flags = 1;
+ return 3;
+ }
+
+ put_label->flags = 2;
+ return 5;
+}
+
+static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
+{
+ sljit_uw addr = put_label->label->addr;
+ sljit_ins *inst = (sljit_ins *)put_label->addr;
+ sljit_s32 reg = *inst;
+
+ if (put_label->flags == 0) {
+ SLJIT_ASSERT(addr < 0x80000000l);
+ inst[0] = LUI | T(reg) | IMM(addr >> 16);
+ }
+ else if (put_label->flags == 1) {
+ SLJIT_ASSERT(addr < 0x800000000000l);
+ inst[0] = LUI | T(reg) | IMM(addr >> 32);
+ inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
+ inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
+ inst += 2;
+ }
+ else {
+ inst[0] = LUI | T(reg) | IMM(addr >> 48);
+ inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);
+ inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
+ inst[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
+ inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);
+ inst += 4;
+ }
+
+ inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
+}
+
+#endif
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
{
struct sljit_memory_fragment *buf;
@@ -457,12 +506,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
sljit_uw addr;
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -474,39 +525,54 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ next_addr = 0;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
do {
*code_ptr = *buf_ptr++;
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
- /* These structures are ordered by their address. */
- if (label && label->size == word_count) {
- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
- label = label->next;
- }
- if (jump && jump->addr == word_count) {
+ if (next_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (label && label->size == word_count) {
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == word_count) {
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- jump->addr = (sljit_uw)(code_ptr - 3);
+ jump->addr = (sljit_uw)(code_ptr - 3);
#else
- jump->addr = (sljit_uw)(code_ptr - 7);
+ jump->addr = (sljit_uw)(code_ptr - 7);
#endif
- code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
- jump = jump->next;
- }
- if (const_ && const_->addr == word_count) {
- /* Just recording the address. */
- const_->addr = (sljit_uw)code_ptr;
- const_ = const_->next;
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+ jump = jump->next;
+ }
+ if (const_ && const_->addr == word_count) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == word_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
+ word_count += 5;
+#endif
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr ++;
word_count ++;
@@ -524,6 +590,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
jump = compiler->jumps;
@@ -571,6 +638,21 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
+ put_label = compiler->put_labels;
+ while (put_label) {
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ addr = put_label->label->addr;
+ buf_ptr = (sljit_ins *)put_label->addr;
+
+ SLJIT_ASSERT((buf_ptr[0] & 0xffe00000) == LUI && (buf_ptr[1] & 0xfc000000) == ORI);
+ buf_ptr[0] |= (addr >> 16) & 0xffff;
+ buf_ptr[1] |= addr & 0xffff;
+#else
+ put_label_set(put_label);
+#endif
+ put_label = put_label->next;
+ }
+
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
@@ -2157,7 +2239,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
- sljit_s32 reg;
+ sljit_s32 dst_r;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -2167,11 +2249,38 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
-
- PTR_FAIL_IF(emit_const(compiler, reg, init_value));
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+
return const_;
}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
+#else
+ PTR_FAIL_IF(push_inst(compiler, dst_r, UNMOVABLE_INS));
+ compiler->size += 5;
+#endif
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+
+ return put_label;
+}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c
index fc185f7847..3ce741153f 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c
@@ -259,6 +259,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
@@ -269,6 +270,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c
index 706b2ba20b..3b73021cc8 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c
@@ -35,9 +35,6 @@
#error "Must implement count leading zeroes"
#endif
-#define RLDI(dst, src, sh, mb, type) \
- (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
-
#define PUSH_RLDICR(reg, shift) \
push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c
index b34e3965ed..e827514315 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c
@@ -231,6 +231,9 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define SIMM_MIN (-0x8000)
#define UIMM_MAX (0xffff)
+#define RLDI(dst, src, sh, mb, type) \
+ (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
+
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)
{
@@ -324,6 +327,55 @@ keep_address:
return 0;
}
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+
+static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
+{
+ if (max_label < 0x100000000l) {
+ put_label->flags = 0;
+ return 1;
+ }
+
+ if (max_label < 0x1000000000000l) {
+ put_label->flags = 1;
+ return 3;
+ }
+
+ put_label->flags = 2;
+ return 4;
+}
+
+static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
+{
+ sljit_uw addr = put_label->label->addr;
+ sljit_ins *inst = (sljit_ins *)put_label->addr;
+ sljit_s32 reg = *inst;
+
+ if (put_label->flags == 0) {
+ SLJIT_ASSERT(addr < 0x100000000l);
+ inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 16);
+ }
+ else {
+ if (put_label->flags == 1) {
+ SLJIT_ASSERT(addr < 0x1000000000000l);
+ inst[0] = ORI | S(TMP_ZERO) | A(reg) | IMM(addr >> 32);
+ }
+ else {
+ inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 48);
+ inst[1] = ORI | S(reg) | A(reg) | IMM((addr >> 32) & 0xffff);
+ inst ++;
+ }
+
+ inst[1] = RLDI(reg, reg, 32, 31, 1);
+ inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff);
+ inst += 2;
+ }
+
+ inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff);
+}
+
+#endif
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
{
struct sljit_memory_fragment *buf;
@@ -332,12 +384,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
sljit_uw addr;
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -356,71 +410,87 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ next_addr = 0;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
do {
*code_ptr = *buf_ptr++;
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
- /* These structures are ordered by their address. */
- if (label && label->size == word_count) {
- /* Just recording the address. */
- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
- label = label->next;
- }
- if (jump && jump->addr == word_count) {
+ if (next_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (label && label->size == word_count) {
+ /* Just recording the address. */
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == word_count) {
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- jump->addr = (sljit_uw)(code_ptr - 3);
+ jump->addr = (sljit_uw)(code_ptr - 3);
#else
- jump->addr = (sljit_uw)(code_ptr - 6);
+ jump->addr = (sljit_uw)(code_ptr - 6);
#endif
- if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
+ if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- code_ptr[-3] = code_ptr[0];
- code_ptr -= 3;
-#else
- if (jump->flags & PATCH_ABS32) {
+ code_ptr[-3] = code_ptr[0];
code_ptr -= 3;
- code_ptr[-1] = code_ptr[2];
- code_ptr[0] = code_ptr[3];
- }
- else if (jump->flags & PATCH_ABS48) {
- code_ptr--;
- code_ptr[-1] = code_ptr[0];
- code_ptr[0] = code_ptr[1];
- /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
- SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
- code_ptr[-3] ^= 0x8422;
- /* oris -> ori */
- code_ptr[-2] ^= 0x4000000;
- }
- else {
- code_ptr[-6] = code_ptr[0];
- code_ptr -= 6;
- }
+#else
+ if (jump->flags & PATCH_ABS32) {
+ code_ptr -= 3;
+ code_ptr[-1] = code_ptr[2];
+ code_ptr[0] = code_ptr[3];
+ }
+ else if (jump->flags & PATCH_ABS48) {
+ code_ptr--;
+ code_ptr[-1] = code_ptr[0];
+ code_ptr[0] = code_ptr[1];
+ /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
+ SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
+ code_ptr[-3] ^= 0x8422;
+ /* oris -> ori */
+ code_ptr[-2] ^= 0x4000000;
+ }
+ else {
+ code_ptr[-6] = code_ptr[0];
+ code_ptr -= 6;
+ }
#endif
- if (jump->flags & REMOVE_COND) {
- code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
- code_ptr++;
- jump->addr += sizeof(sljit_ins);
- code_ptr[0] = Bx;
- jump->flags -= IS_COND;
+ if (jump->flags & REMOVE_COND) {
+ code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
+ code_ptr++;
+ jump->addr += sizeof(sljit_ins);
+ code_ptr[0] = Bx;
+ jump->flags -= IS_COND;
+ }
}
+ jump = jump->next;
}
- jump = jump->next;
- }
- if (const_ && const_->addr == word_count) {
- const_->addr = (sljit_uw)code_ptr;
- const_ = const_->next;
+ if (const_ && const_->addr == word_count) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == word_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
+ word_count += 4;
+#endif
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr ++;
word_count ++;
@@ -438,6 +508,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
+
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)));
#else
@@ -503,6 +575,21 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
+ put_label = compiler->put_labels;
+ while (put_label) {
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ addr = put_label->label->addr;
+ buf_ptr = (sljit_ins *)put_label->addr;
+
+ SLJIT_ASSERT((buf_ptr[0] & 0xfc1f0000) == ADDIS && (buf_ptr[1] & 0xfc000000) == ORI);
+ buf_ptr[0] |= (addr >> 16) & 0xffff;
+ buf_ptr[1] |= addr & 0xffff;
+#else
+ put_label_set(put_label);
+#endif
+ put_label = put_label->next;
+ }
+
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
@@ -2261,7 +2348,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;
- sljit_s32 reg;
+ sljit_s32 dst_r;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -2271,11 +2358,38 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
-
- PTR_FAIL_IF(emit_const(compiler, reg, init_value));
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+
return const_;
}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
+#else
+ PTR_FAIL_IF(push_inst(compiler, dst_r));
+ compiler->size += 4;
+#endif
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+
+ return put_label;
+}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c
index 0671b130cc..8079fad8df 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c
@@ -267,6 +267,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000));
inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff);
inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
@@ -277,6 +278,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
{
sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000));
inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff);
inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c
index 669ecd8152..bfa4ecede2 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c
@@ -298,12 +298,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_ins *buf_ptr;
sljit_ins *buf_end;
sljit_uw word_count;
+ sljit_uw next_addr;
sljit_sw executable_offset;
sljit_uw addr;
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -315,40 +317,52 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code_ptr = code;
word_count = 0;
+ next_addr = 0;
executable_offset = SLJIT_EXEC_OFFSET(code);
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
do {
buf_ptr = (sljit_ins*)buf->memory;
buf_end = buf_ptr + (buf->used_size >> 2);
do {
*code_ptr = *buf_ptr++;
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
- /* These structures are ordered by their address. */
- if (label && label->size == word_count) {
- /* Just recording the address. */
- label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
- label = label->next;
- }
- if (jump && jump->addr == word_count) {
+ if (next_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (label && label->size == word_count) {
+ /* Just recording the address. */
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = code_ptr - code;
+ label = label->next;
+ }
+ if (jump && jump->addr == word_count) {
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
- jump->addr = (sljit_uw)(code_ptr - 3);
+ jump->addr = (sljit_uw)(code_ptr - 3);
#else
- jump->addr = (sljit_uw)(code_ptr - 6);
+ jump->addr = (sljit_uw)(code_ptr - 6);
#endif
- code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
- jump = jump->next;
- }
- if (const_ && const_->addr == word_count) {
- /* Just recording the address. */
- const_->addr = (sljit_uw)code_ptr;
- const_ = const_->next;
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+ jump = jump->next;
+ }
+ if (const_ && const_->addr == word_count) {
+ /* Just recording the address. */
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ }
+ if (put_label && put_label->addr == word_count) {
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+ put_label = put_label->next;
+ }
+ next_addr = compute_next_addr(label, jump, const_, put_label);
}
code_ptr ++;
word_count ++;
@@ -366,6 +380,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size);
jump = compiler->jumps;
@@ -389,8 +404,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* Set the fields of immediate loads. */
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
- buf_ptr[0] = (buf_ptr[0] & 0xffc00000) | ((addr >> 10) & 0x3fffff);
- buf_ptr[1] = (buf_ptr[1] & 0xfffffc00) | (addr & 0x3ff);
+ SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));
+ buf_ptr[0] |= (addr >> 10) & 0x3fffff;
+ buf_ptr[1] |= addr & 0x3ff;
#else
#error "Implementation required"
#endif
@@ -398,6 +414,20 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
+ put_label = compiler->put_labels;
+ while (put_label) {
+ addr = put_label->label->addr;
+ buf_ptr = (sljit_ins *)put_label->addr;
+
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+ SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));
+ buf_ptr[0] |= (addr >> 10) & 0x3fffff;
+ buf_ptr[1] |= addr & 0x3ff;
+#else
+#error "Implementation required"
+#endif
+ put_label = put_label->next;
+ }
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
@@ -1465,8 +1495,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
- sljit_s32 reg;
struct sljit_const *const_;
+ sljit_s32 dst_r;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
@@ -1476,11 +1506,31 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
- reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
-
- PTR_FAIL_IF(emit_const(compiler, reg, init_value));
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
return const_;
}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
+ return put_label;
+}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c
index 074e64b9f2..34a3a3d940 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c
@@ -38,8 +38,10 @@ static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, s
return SLJIT_SUCCESS;
}
-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset)
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset)
{
+ sljit_s32 type = jump->flags >> TYPE_SHIFT;
+
if (type == SLJIT_JUMP) {
*code_ptr++ = JMP_i32;
jump->addr++;
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c
index 8506565614..5758711954 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c
@@ -39,8 +39,10 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg,
return SLJIT_SUCCESS;
}
-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type)
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr)
{
+ sljit_s32 type = jump->flags >> TYPE_SHIFT;
+
int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff);
/* The relative jump below specialized for this case. */
@@ -72,6 +74,56 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
return code_ptr;
}
+static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label)
+{
+ if (max_label > HALFWORD_MAX) {
+ put_label->addr -= put_label->flags;
+ put_label->flags = PATCH_MD;
+ return code_ptr;
+ }
+
+ if (put_label->flags == 0) {
+ /* Destination is register. */
+ code_ptr = (sljit_u8*)put_label->addr - 2 - sizeof(sljit_uw);
+
+ SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);
+ SLJIT_ASSERT((code_ptr[1] & 0xf8) == MOV_r_i32);
+
+ if ((code_ptr[0] & 0x07) != 0) {
+ code_ptr[0] = (sljit_u8)(code_ptr[0] & ~0x08);
+ code_ptr += 2 + sizeof(sljit_s32);
+ }
+ else {
+ code_ptr[0] = code_ptr[1];
+ code_ptr += 1 + sizeof(sljit_s32);
+ }
+
+ put_label->addr = (sljit_uw)code_ptr;
+ return code_ptr;
+ }
+
+ code_ptr -= put_label->flags + (2 + sizeof(sljit_uw));
+ SLJIT_MEMMOVE(code_ptr, code_ptr + (2 + sizeof(sljit_uw)), put_label->flags);
+
+ SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);
+
+ if ((code_ptr[1] & 0xf8) == MOV_r_i32) {
+ code_ptr += 2 + sizeof(sljit_uw);
+ SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);
+ }
+
+ SLJIT_ASSERT(code_ptr[1] == MOV_rm_r);
+
+ code_ptr[0] = (sljit_u8)(code_ptr[0] & ~0x4);
+ code_ptr[1] = MOV_rm_i32;
+ code_ptr[2] = (sljit_u8)(code_ptr[2] & ~(0x7 << 3));
+
+ code_ptr = (sljit_u8*)(put_label->addr - (2 + sizeof(sljit_uw)) + sizeof(sljit_s32));
+ put_label->addr = (sljit_uw)code_ptr;
+ put_label->flags = 0;
+ return code_ptr;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c
index 6f02ee3e8b..6296da5382 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c
@@ -428,13 +428,15 @@ static sljit_u8 get_jump_code(sljit_s32 type)
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset);
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset);
#else
-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type);
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr);
+static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label);
#endif
-static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_s32 type, sljit_sw executable_offset)
+static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)
{
+ sljit_s32 type = jump->flags >> TYPE_SHIFT;
sljit_s32 short_jump;
sljit_uw label_addr;
@@ -447,7 +449,7 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if ((sljit_sw)(label_addr - (jump->addr + 1)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump->addr + 1)) < HALFWORD_MIN)
- return generate_far_jump_code(jump, code_ptr, type);
+ return generate_far_jump_code(jump, code_ptr);
#endif
if (type == SLJIT_JUMP) {
@@ -497,6 +499,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
+ struct sljit_put_label *put_label;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -511,6 +514,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
+ put_label = compiler->put_labels;
executable_offset = SLJIT_EXEC_OFFSET(code);
do {
@@ -525,27 +529,38 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr += len;
}
else {
- if (*buf_ptr >= 2) {
+ switch (*buf_ptr) {
+ case 0:
+ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = code_ptr - code;
+ label = label->next;
+ break;
+ case 1:
jump->addr = (sljit_uw)code_ptr;
if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
- code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 2, executable_offset);
+ code_ptr = generate_near_jump_code(jump, code_ptr, code, executable_offset);
else {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2, executable_offset);
+ code_ptr = generate_far_jump_code(jump, code_ptr, executable_offset);
#else
- code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2);
+ code_ptr = generate_far_jump_code(jump, code_ptr);
#endif
}
jump = jump->next;
- }
- else if (*buf_ptr == 0) {
- label->addr = ((sljit_uw)code_ptr) + executable_offset;
- label->size = code_ptr - code;
- label = label->next;
- }
- else { /* *buf_ptr is 1 */
+ break;
+ case 2:
const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);
const_ = const_->next;
+ break;
+ default:
+ SLJIT_ASSERT(*buf_ptr == 3);
+ SLJIT_ASSERT(put_label->label);
+ put_label->addr = (sljit_uw)code_ptr;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ code_ptr = generate_put_label_code(put_label, code_ptr, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
+#endif
+ put_label = put_label->next;
+ break;
}
buf_ptr++;
}
@@ -557,6 +572,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(!put_label);
+ SLJIT_ASSERT(code_ptr <= code + compiler->size);
jump = compiler->jumps;
while (jump) {
@@ -591,8 +608,24 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
- /* Some space may be wasted because of short jumps. */
- SLJIT_ASSERT(code_ptr <= code + compiler->size);
+ put_label = compiler->put_labels;
+ while (put_label) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_unaligned_store_sw((void*)(put_label->addr - sizeof(sljit_sw)), (sljit_sw)put_label->label->addr);
+#else
+ if (put_label->flags & PATCH_MD) {
+ SLJIT_ASSERT(put_label->label->addr > HALFWORD_MAX);
+ sljit_unaligned_store_sw((void*)(put_label->addr - sizeof(sljit_sw)), (sljit_sw)put_label->label->addr);
+ }
+ else {
+ SLJIT_ASSERT(put_label->label->addr <= HALFWORD_MAX);
+ sljit_unaligned_store_s32((void*)(put_label->addr - sizeof(sljit_s32)), (sljit_s32)put_label->label->addr);
+ }
+#endif
+
+ put_label = put_label->next;
+ }
+
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
compiler->executable_size = code_ptr - code;
@@ -2481,7 +2514,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF_NULL(jump);
- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ set_jump(jump, compiler, (type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT));
type &= 0xff;
/* Worst case size. */
@@ -2495,7 +2528,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
PTR_FAIL_IF_NULL(inst);
*inst++ = 0;
- *inst++ = type + 2;
+ *inst++ = 1;
return jump;
}
@@ -2513,7 +2546,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
if (src == SLJIT_IMM) {
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
FAIL_IF_NULL(jump);
- set_jump(jump, compiler, JUMP_ADDR);
+ set_jump(jump, compiler, JUMP_ADDR | (type << TYPE_SHIFT));
jump->u.target = srcw;
/* Worst case size. */
@@ -2527,7 +2560,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
FAIL_IF_NULL(inst);
*inst++ = 0;
- *inst++ = type + 2;
+ *inst++ = 1;
}
else {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@@ -2831,7 +2864,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
PTR_FAIL_IF(!inst);
*inst++ = 0;
- *inst++ = 1;
+ *inst++ = 2;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (dst & SLJIT_MEM)
@@ -2842,6 +2875,54 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
return const_;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_put_label *put_label;
+ sljit_u8 *inst;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ sljit_s32 reg;
+ sljit_uw start_size;
+#endif
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+
+ put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
+ PTR_FAIL_IF(!put_label);
+ set_put_label(put_label, compiler, 0);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (emit_load_imm64(compiler, reg, 0))
+ return NULL;
+#else
+ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, 0))
+ return NULL;
+#endif
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (dst & SLJIT_MEM) {
+ start_size = compiler->size;
+ if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))
+ return NULL;
+ put_label->flags = compiler->size - start_size;
+ }
+#endif
+
+ inst = (sljit_u8*)ensure_buf(compiler, 2);
+ PTR_FAIL_IF(!inst);
+
+ *inst++ = 0;
+ *inst++ = 3;
+
+ return put_label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
SLJIT_UNUSED_ARG(executable_offset);
diff --git a/thirdparty/pcre2/src/sljit/sljitUtils.c b/thirdparty/pcre2/src/sljit/sljitUtils.c
index 5c2a838932..857492a174 100644
--- a/thirdparty/pcre2/src/sljit/sljitUtils.c
+++ b/thirdparty/pcre2/src/sljit/sljitUtils.c
@@ -154,7 +154,13 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void)
#include "windows.h"
#else
/* Provides mmap function. */
+#include <sys/types.h>
#include <sys/mman.h>
+#ifndef MAP_ANON
+#ifdef MAP_ANONYMOUS
+#define MAP_ANON MAP_ANONYMOUS
+#endif
+#endif
/* For detecting the page size. */
#include <unistd.h>
diff --git a/thirdparty/recastnavigation/Recast/Include/Recast.h b/thirdparty/recastnavigation/Recast/Include/Recast.h
index e85c0d2e29..4d557389b5 100644
--- a/thirdparty/recastnavigation/Recast/Include/Recast.h
+++ b/thirdparty/recastnavigation/Recast/Include/Recast.h
@@ -332,6 +332,8 @@ struct rcCompactSpan
/// @ingroup recast
struct rcCompactHeightfield
{
+ rcCompactHeightfield();
+ ~rcCompactHeightfield();
int width; ///< The width of the heightfield. (Along the x-axis in cell units.)
int height; ///< The height of the heightfield. (Along the z-axis in cell units.)
int spanCount; ///< The number of spans in the heightfield.
@@ -376,6 +378,8 @@ struct rcHeightfieldLayer
/// @see rcAllocHeightfieldLayerSet, rcFreeHeightfieldLayerSet
struct rcHeightfieldLayerSet
{
+ rcHeightfieldLayerSet();
+ ~rcHeightfieldLayerSet();
rcHeightfieldLayer* layers; ///< The layers in the set. [Size: #nlayers]
int nlayers; ///< The number of layers in the set.
};
@@ -395,6 +399,8 @@ struct rcContour
/// @ingroup recast
struct rcContourSet
{
+ rcContourSet();
+ ~rcContourSet();
rcContour* conts; ///< An array of the contours in the set. [Size: #nconts]
int nconts; ///< The number of contours in the set.
float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]
@@ -411,6 +417,8 @@ struct rcContourSet
/// @ingroup recast
struct rcPolyMesh
{
+ rcPolyMesh();
+ ~rcPolyMesh();
unsigned short* verts; ///< The mesh vertices. [Form: (x, y, z) * #nverts]
unsigned short* polys; ///< Polygon and neighbor data. [Length: #maxpolys * 2 * #nvp]
unsigned short* regs; ///< The region id assigned to each polygon. [Length: #maxpolys]
diff --git a/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h b/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h
index 3cdd450d42..e436af9a01 100644
--- a/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h
+++ b/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h
@@ -20,6 +20,9 @@
#define RECASTALLOC_H
#include <stddef.h>
+#include <stdint.h>
+
+#include <RecastAssert.h>
/// Provides hint values to the memory allocator on how long the
/// memory is expected to be used.
@@ -58,64 +61,257 @@ void* rcAlloc(size_t size, rcAllocHint hint);
/// @see rcAlloc
void rcFree(void* ptr);
+/// An implementation of operator new usable for placement new. The default one is part of STL (which we don't use).
+/// rcNewTag is a dummy type used to differentiate our operator from the STL one, in case users import both Recast
+/// and STL.
+struct rcNewTag {};
+inline void* operator new(size_t, const rcNewTag&, void* p) { return p; }
+inline void operator delete(void*, const rcNewTag&, void*) {}
-/// A simple dynamic array of integers.
-class rcIntArray
-{
- int* m_data;
- int m_size, m_cap;
+/// Signed to avoid warnnings when comparing to int loop indexes, and common error with comparing to zero.
+/// MSVC2010 has a bug where ssize_t is unsigned (!!!).
+typedef intptr_t rcSizeType;
+#define RC_SIZE_MAX INTPTR_MAX
- void doResize(int n);
-
- // Explicitly disabled copy constructor and copy assignment operator.
- rcIntArray(const rcIntArray&);
- rcIntArray& operator=(const rcIntArray&);
+/// Macros to hint to the compiler about the likeliest branch. Please add a benchmark that demonstrates a performance
+/// improvement before introducing use cases.
+#if defined(__GNUC__) || defined(__clang__)
+#define rcLikely(x) __builtin_expect((x), true)
+#define rcUnlikely(x) __builtin_expect((x), false)
+#else
+#define rcLikely(x) (x)
+#define rcUnlikely(x) (x)
+#endif
-public:
- /// Constructs an instance with an initial array size of zero.
- rcIntArray() : m_data(0), m_size(0), m_cap(0) {}
+/// Variable-sized storage type. Mimics the interface of std::vector<T> with some notable differences:
+/// * Uses rcAlloc()/rcFree() to handle storage.
+/// * No support for a custom allocator.
+/// * Uses signed size instead of size_t to avoid warnings in for loops: "for (int i = 0; i < foo.size(); i++)"
+/// * Omits methods of limited utility: insert/erase, (bad performance), at (we don't use exceptions), operator=.
+/// * assign() and the pre-sizing constructor follow C++11 semantics -- they don't construct a temporary if no value is provided.
+/// * push_back() and resize() support adding values from the current vector. Range-based constructors and assign(begin, end) do not.
+/// * No specialization for bool.
+template <typename T, rcAllocHint H>
+class rcVectorBase {
+ rcSizeType m_size;
+ rcSizeType m_cap;
+ T* m_data;
+ // Constructs a T at the give address with either the copy constructor or the default.
+ static void construct(T* p, const T& v) { ::new(rcNewTag(), (void*)p) T(v); }
+ static void construct(T* p) { ::new(rcNewTag(), (void*)p) T; }
+ static void construct_range(T* begin, T* end);
+ static void construct_range(T* begin, T* end, const T& value);
+ static void copy_range(T* dst, const T* begin, const T* end);
+ void destroy_range(rcSizeType begin, rcSizeType end);
+ // Creates an array of the given size, copies all of this vector's data into it, and returns it.
+ T* allocate_and_copy(rcSizeType size);
+ void resize_impl(rcSizeType size, const T* value);
+ public:
+ typedef rcSizeType size_type;
+ typedef T value_type;
- /// Constructs an instance initialized to the specified size.
- /// @param[in] n The initial size of the integer array.
- rcIntArray(int n) : m_data(0), m_size(0), m_cap(0) { resize(n); }
- ~rcIntArray() { rcFree(m_data); }
+ rcVectorBase() : m_size(0), m_cap(0), m_data(0) {};
+ rcVectorBase(const rcVectorBase<T, H>& other) : m_size(0), m_cap(0), m_data(0) { assign(other.begin(), other.end()); }
+ explicit rcVectorBase(rcSizeType count) : m_size(0), m_cap(0), m_data(0) { resize(count); }
+ rcVectorBase(rcSizeType count, const T& value) : m_size(0), m_cap(0), m_data(0) { resize(count, value); }
+ rcVectorBase(const T* begin, const T* end) : m_size(0), m_cap(0), m_data(0) { assign(begin, end); }
+ ~rcVectorBase() { destroy_range(0, m_size); rcFree(m_data); }
- /// Specifies the new size of the integer array.
- /// @param[in] n The new size of the integer array.
- void resize(int n)
- {
- if (n > m_cap)
- doResize(n);
-
- m_size = n;
+ // Unlike in std::vector, we return a bool to indicate whether the alloc was successful.
+ bool reserve(rcSizeType size);
+
+ void assign(rcSizeType count, const T& value) { clear(); resize(count, value); }
+ void assign(const T* begin, const T* end);
+
+ void resize(rcSizeType size) { resize_impl(size, NULL); }
+ void resize(rcSizeType size, const T& value) { resize_impl(size, &value); }
+ // Not implemented as resize(0) because resize requires T to be default-constructible.
+ void clear() { destroy_range(0, m_size); m_size = 0; }
+
+ void push_back(const T& value);
+ void pop_back() { rcAssert(m_size > 0); back().~T(); m_size--; }
+
+ rcSizeType size() const { return m_size; }
+ rcSizeType capacity() const { return m_cap; }
+ bool empty() const { return size() == 0; }
+
+ const T& operator[](rcSizeType i) const { rcAssert(i >= 0 && i < m_size); return m_data[i]; }
+ T& operator[](rcSizeType i) { rcAssert(i >= 0 && i < m_size); return m_data[i]; }
+
+ const T& front() const { rcAssert(m_size); return m_data[0]; }
+ T& front() { rcAssert(m_size); return m_data[0]; }
+ const T& back() const { rcAssert(m_size); return m_data[m_size - 1]; };
+ T& back() { rcAssert(m_size); return m_data[m_size - 1]; };
+ const T* data() const { return m_data; }
+ T* data() { return m_data; }
+
+ T* begin() { return m_data; }
+ T* end() { return m_data + m_size; }
+ const T* begin() const { return m_data; }
+ const T* end() const { return m_data + m_size; }
+
+ void swap(rcVectorBase<T, H>& other);
+
+ // Explicitly deleted.
+ rcVectorBase& operator=(const rcVectorBase<T, H>& other);
+};
+
+template<typename T, rcAllocHint H>
+bool rcVectorBase<T, H>::reserve(rcSizeType count) {
+ if (count <= m_cap) {
+ return true;
+ }
+ T* new_data = allocate_and_copy(count);
+ if (!new_data) {
+ return false;
+ }
+ destroy_range(0, m_size);
+ rcFree(m_data);
+ m_data = new_data;
+ m_cap = count;
+ return true;
+}
+template <typename T, rcAllocHint H>
+T* rcVectorBase<T, H>::allocate_and_copy(rcSizeType size) {
+ rcAssert(RC_SIZE_MAX / static_cast<rcSizeType>(sizeof(T)) >= size);
+ T* new_data = static_cast<T*>(rcAlloc(sizeof(T) * size, H));
+ if (new_data) {
+ copy_range(new_data, m_data, m_data + m_size);
+ }
+ return new_data;
+}
+template <typename T, rcAllocHint H>
+void rcVectorBase<T, H>::assign(const T* begin, const T* end) {
+ clear();
+ reserve(end - begin);
+ m_size = end - begin;
+ copy_range(m_data, begin, end);
+}
+template <typename T, rcAllocHint H>
+void rcVectorBase<T, H>::push_back(const T& value) {
+ // rcLikely increases performance by ~50% on BM_rcVector_PushPreallocated,
+ // and by ~2-5% on BM_rcVector_Push.
+ if (rcLikely(m_size < m_cap)) {
+ construct(m_data + m_size++, value);
+ return;
}
- /// Push the specified integer onto the end of the array and increases the size by one.
- /// @param[in] item The new value.
- void push(int item) { resize(m_size+1); m_data[m_size-1] = item; }
+ rcAssert(RC_SIZE_MAX / 2 >= m_size);
+ rcSizeType new_cap = m_size ? 2*m_size : 1;
+ T* data = allocate_and_copy(new_cap);
+ // construct between allocate and destroy+free in case value is
+ // in this vector.
+ construct(data + m_size, value);
+ destroy_range(0, m_size);
+ m_size++;
+ m_cap = new_cap;
+ rcFree(m_data);
+ m_data = data;
+}
+template <typename T, rcAllocHint H>
+void rcVectorBase<T, H>::resize_impl(rcSizeType size, const T* value) {
+ if (size < m_size) {
+ destroy_range(size, m_size);
+ m_size = size;
+ } else if (size > m_size) {
+ T* new_data = allocate_and_copy(size);
+ // We defer deconstructing/freeing old data until after constructing
+ // new elements in case "value" is there.
+ if (value) {
+ construct_range(new_data + m_size, new_data + size, *value);
+ } else {
+ construct_range(new_data + m_size, new_data + size);
+ }
+ destroy_range(0, m_size);
+ rcFree(m_data);
+ m_data = new_data;
+ m_cap = size;
+ m_size = size;
+ }
+}
+template <typename T, rcAllocHint H>
+void rcVectorBase<T, H>::swap(rcVectorBase<T, H>& other) {
+ // TODO: Reorganize headers so we can use rcSwap here.
+ rcSizeType tmp_cap = other.m_cap;
+ rcSizeType tmp_size = other.m_size;
+ T* tmp_data = other.m_data;
- /// Returns the value at the end of the array and reduces the size by one.
- /// @return The value at the end of the array.
- int pop()
- {
- if (m_size > 0)
- m_size--;
-
- return m_data[m_size];
+ other.m_cap = m_cap;
+ other.m_size = m_size;
+ other.m_data = m_data;
+
+ m_cap = tmp_cap;
+ m_size = tmp_size;
+ m_data = tmp_data;
+}
+// static
+template <typename T, rcAllocHint H>
+void rcVectorBase<T, H>::construct_range(T* begin, T* end) {
+ for (T* p = begin; p < end; p++) {
+ construct(p);
+ }
+}
+// static
+template <typename T, rcAllocHint H>
+void rcVectorBase<T, H>::construct_range(T* begin, T* end, const T& value) {
+ for (T* p = begin; p < end; p++) {
+ construct(p, value);
+ }
+}
+// static
+template <typename T, rcAllocHint H>
+void rcVectorBase<T, H>::copy_range(T* dst, const T* begin, const T* end) {
+ for (rcSizeType i = 0 ; i < end - begin; i++) {
+ construct(dst + i, begin[i]);
}
+}
+template <typename T, rcAllocHint H>
+void rcVectorBase<T, H>::destroy_range(rcSizeType begin, rcSizeType end) {
+ for (rcSizeType i = begin; i < end; i++) {
+ m_data[i].~T();
+ }
+}
- /// The value at the specified array index.
- /// @warning Does not provide overflow protection.
- /// @param[in] i The index of the value.
- const int& operator[](int i) const { return m_data[i]; }
+template <typename T>
+class rcTempVector : public rcVectorBase<T, RC_ALLOC_TEMP> {
+ typedef rcVectorBase<T, RC_ALLOC_TEMP> Base;
+public:
+ rcTempVector() : Base() {}
+ explicit rcTempVector(rcSizeType size) : Base(size) {}
+ rcTempVector(rcSizeType size, const T& value) : Base(size, value) {}
+ rcTempVector(const rcTempVector<T>& other) : Base(other) {}
+ rcTempVector(const T* begin, const T* end) : Base(begin, end) {}
+};
+template <typename T>
+class rcPermVector : public rcVectorBase<T, RC_ALLOC_PERM> {
+ typedef rcVectorBase<T, RC_ALLOC_PERM> Base;
+public:
+ rcPermVector() : Base() {}
+ explicit rcPermVector(rcSizeType size) : Base(size) {}
+ rcPermVector(rcSizeType size, const T& value) : Base(size, value) {}
+ rcPermVector(const rcPermVector<T>& other) : Base(other) {}
+ rcPermVector(const T* begin, const T* end) : Base(begin, end) {}
+};
- /// The value at the specified array index.
- /// @warning Does not provide overflow protection.
- /// @param[in] i The index of the value.
- int& operator[](int i) { return m_data[i]; }
- /// The current size of the integer array.
- int size() const { return m_size; }
+/// Legacy class. Prefer rcVector<int>.
+class rcIntArray
+{
+ rcTempVector<int> m_impl;
+public:
+ rcIntArray() {}
+ rcIntArray(int n) : m_impl(n, 0) {}
+ void push(int item) { m_impl.push_back(item); }
+ void resize(int size) { m_impl.resize(size); }
+ int pop()
+ {
+ int v = m_impl.back();
+ m_impl.pop_back();
+ return v;
+ }
+ int size() const { return static_cast<int>(m_impl.size()); }
+ int& operator[](int index) { return m_impl[index]; }
+ int operator[](int index) const { return m_impl[index]; }
};
/// A simple helper class used to delete an array when it goes out of scope.
diff --git a/thirdparty/recastnavigation/Recast/Source/Recast.cpp b/thirdparty/recastnavigation/Recast/Source/Recast.cpp
index 8308d1973e..1b71710cdc 100644
--- a/thirdparty/recastnavigation/Recast/Source/Recast.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/Recast.cpp
@@ -23,11 +23,34 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
-#include <new>
#include "Recast.h"
#include "RecastAlloc.h"
#include "RecastAssert.h"
+namespace
+{
+/// Allocates and constructs an object of the given type, returning a pointer.
+/// TODO: Support constructor args.
+/// @param[in] hint Hint to the allocator.
+template <typename T>
+T* rcNew(rcAllocHint hint) {
+ T* ptr = (T*)rcAlloc(sizeof(T), hint);
+ ::new(rcNewTag(), (void*)ptr) T();
+ return ptr;
+}
+
+/// Destroys and frees an object allocated with rcNew.
+/// @param[in] ptr The object pointer to delete.
+template <typename T>
+void rcDelete(T* ptr) {
+ if (ptr) {
+ ptr->~T();
+ rcFree((void*)ptr);
+ }
+}
+} // namespace
+
+
float rcSqrt(float x)
{
return sqrtf(x);
@@ -73,9 +96,8 @@ void rcContext::log(const rcLogCategory category, const char* format, ...)
rcHeightfield* rcAllocHeightfield()
{
- return new (rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM)) rcHeightfield;
+ return rcNew<rcHeightfield>(RC_ALLOC_PERM);
}
-
rcHeightfield::rcHeightfield()
: width()
, height()
@@ -104,84 +126,133 @@ rcHeightfield::~rcHeightfield()
void rcFreeHeightField(rcHeightfield* hf)
{
- if (!hf) return;
- hf->~rcHeightfield();
- rcFree(hf);
+ rcDelete(hf);
}
rcCompactHeightfield* rcAllocCompactHeightfield()
{
- rcCompactHeightfield* chf = (rcCompactHeightfield*)rcAlloc(sizeof(rcCompactHeightfield), RC_ALLOC_PERM);
- memset(chf, 0, sizeof(rcCompactHeightfield));
- return chf;
+ return rcNew<rcCompactHeightfield>(RC_ALLOC_PERM);
}
void rcFreeCompactHeightfield(rcCompactHeightfield* chf)
{
- if (!chf) return;
- rcFree(chf->cells);
- rcFree(chf->spans);
- rcFree(chf->dist);
- rcFree(chf->areas);
- rcFree(chf);
+ rcDelete(chf);
}
-rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet()
+rcCompactHeightfield::rcCompactHeightfield()
+ : width(),
+ height(),
+ spanCount(),
+ walkableHeight(),
+ walkableClimb(),
+ borderSize(),
+ maxDistance(),
+ maxRegions(),
+ bmin(),
+ bmax(),
+ cs(),
+ ch(),
+ cells(),
+ spans(),
+ dist(),
+ areas()
{
- rcHeightfieldLayerSet* lset = (rcHeightfieldLayerSet*)rcAlloc(sizeof(rcHeightfieldLayerSet), RC_ALLOC_PERM);
- memset(lset, 0, sizeof(rcHeightfieldLayerSet));
- return lset;
+}
+rcCompactHeightfield::~rcCompactHeightfield()
+{
+ rcFree(cells);
+ rcFree(spans);
+ rcFree(dist);
+ rcFree(areas);
}
+rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet()
+{
+ return rcNew<rcHeightfieldLayerSet>(RC_ALLOC_PERM);
+}
void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset)
{
- if (!lset) return;
- for (int i = 0; i < lset->nlayers; ++i)
+ rcDelete(lset);
+}
+
+rcHeightfieldLayerSet::rcHeightfieldLayerSet()
+ : layers(), nlayers() {}
+rcHeightfieldLayerSet::~rcHeightfieldLayerSet()
+{
+ for (int i = 0; i < nlayers; ++i)
{
- rcFree(lset->layers[i].heights);
- rcFree(lset->layers[i].areas);
- rcFree(lset->layers[i].cons);
+ rcFree(layers[i].heights);
+ rcFree(layers[i].areas);
+ rcFree(layers[i].cons);
}
- rcFree(lset->layers);
- rcFree(lset);
+ rcFree(layers);
}
rcContourSet* rcAllocContourSet()
{
- rcContourSet* cset = (rcContourSet*)rcAlloc(sizeof(rcContourSet), RC_ALLOC_PERM);
- memset(cset, 0, sizeof(rcContourSet));
- return cset;
+ return rcNew<rcContourSet>(RC_ALLOC_PERM);
}
-
void rcFreeContourSet(rcContourSet* cset)
{
- if (!cset) return;
- for (int i = 0; i < cset->nconts; ++i)
+ rcDelete(cset);
+}
+
+rcContourSet::rcContourSet()
+ : conts(),
+ nconts(),
+ bmin(),
+ bmax(),
+ cs(),
+ ch(),
+ width(),
+ height(),
+ borderSize(),
+ maxError() {}
+rcContourSet::~rcContourSet()
+{
+ for (int i = 0; i < nconts; ++i)
{
- rcFree(cset->conts[i].verts);
- rcFree(cset->conts[i].rverts);
+ rcFree(conts[i].verts);
+ rcFree(conts[i].rverts);
}
- rcFree(cset->conts);
- rcFree(cset);
+ rcFree(conts);
}
+
rcPolyMesh* rcAllocPolyMesh()
{
- rcPolyMesh* pmesh = (rcPolyMesh*)rcAlloc(sizeof(rcPolyMesh), RC_ALLOC_PERM);
- memset(pmesh, 0, sizeof(rcPolyMesh));
- return pmesh;
+ return rcNew<rcPolyMesh>(RC_ALLOC_PERM);
}
-
void rcFreePolyMesh(rcPolyMesh* pmesh)
{
- if (!pmesh) return;
- rcFree(pmesh->verts);
- rcFree(pmesh->polys);
- rcFree(pmesh->regs);
- rcFree(pmesh->flags);
- rcFree(pmesh->areas);
- rcFree(pmesh);
+ rcDelete(pmesh);
+}
+
+rcPolyMesh::rcPolyMesh()
+ : verts(),
+ polys(),
+ regs(),
+ flags(),
+ areas(),
+ nverts(),
+ npolys(),
+ maxpolys(),
+ nvp(),
+ bmin(),
+ bmax(),
+ cs(),
+ ch(),
+ borderSize(),
+ maxEdgeError() {}
+
+rcPolyMesh::~rcPolyMesh()
+{
+ rcFree(verts);
+ rcFree(polys);
+ rcFree(regs);
+ rcFree(flags);
+ rcFree(areas);
}
rcPolyMeshDetail* rcAllocPolyMeshDetail()
diff --git a/thirdparty/recastnavigation/Recast/Source/RecastAlloc.cpp b/thirdparty/recastnavigation/Recast/Source/RecastAlloc.cpp
index 453b5fa6a6..bdc366116e 100644
--- a/thirdparty/recastnavigation/Recast/Source/RecastAlloc.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/RecastAlloc.cpp
@@ -58,29 +58,3 @@ void rcFree(void* ptr)
if (ptr)
sRecastFreeFunc(ptr);
}
-
-/// @class rcIntArray
-///
-/// While it is possible to pre-allocate a specific array size during
-/// construction or by using the #resize method, certain methods will
-/// automatically resize the array as needed.
-///
-/// @warning The array memory is not initialized to zero when the size is
-/// manually set during construction or when using #resize.
-
-/// @par
-///
-/// Using this method ensures the array is at least large enough to hold
-/// the specified number of elements. This can improve performance by
-/// avoiding auto-resizing during use.
-void rcIntArray::doResize(int n)
-{
- if (!m_cap) m_cap = n;
- while (m_cap < n) m_cap *= 2;
- int* newData = (int*)rcAlloc(m_cap*sizeof(int), RC_ALLOC_TEMP);
- rcAssert(newData);
- if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(int));
- rcFree(m_data);
- m_data = newData;
-}
-
diff --git a/thirdparty/recastnavigation/Recast/Source/RecastContour.cpp b/thirdparty/recastnavigation/Recast/Source/RecastContour.cpp
index 277ab01501..6574c11b6b 100644
--- a/thirdparty/recastnavigation/Recast/Source/RecastContour.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/RecastContour.cpp
@@ -1009,7 +1009,7 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
if (cset.nconts > 0)
{
// Calculate winding of all polygons.
- rcScopedDelete<char> winding((char*)rcAlloc(sizeof(char)*cset.nconts, RC_ALLOC_TEMP));
+ rcScopedDelete<signed char> winding((signed char*)rcAlloc(sizeof(signed char)*cset.nconts, RC_ALLOC_TEMP));
if (!winding)
{
ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'hole' (%d).", cset.nconts);
diff --git a/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp b/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp
index f953132f74..9a423cab8a 100644
--- a/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp
@@ -557,15 +557,16 @@ static float polyMinExtent(const float* verts, const int nverts)
inline int prev(int i, int n) { return i-1 >= 0 ? i-1 : n-1; }
inline int next(int i, int n) { return i+1 < n ? i+1 : 0; }
-static void triangulateHull(const int /*nverts*/, const float* verts, const int nhull, const int* hull, rcIntArray& tris)
+static void triangulateHull(const int /*nverts*/, const float* verts, const int nhull, const int* hull, const int nin, rcIntArray& tris)
{
int start = 0, left = 1, right = nhull-1;
// Start from an ear with shortest perimeter.
// This tends to favor well formed triangles as starting point.
- float dmin = 0;
+ float dmin = FLT_MAX;
for (int i = 0; i < nhull; i++)
{
+ if (hull[i] >= nin) continue; // Ears are triangles with original vertices as middle vertex while others are actually line segments on edges
int pi = prev(i, nhull);
int ni = next(i, nhull);
const float* pv = &verts[hull[pi]*3];
@@ -770,7 +771,7 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
// If the polygon minimum extent is small (sliver or small triangle), do not try to add internal points.
if (minExtent < sampleDist*2)
{
- triangulateHull(nverts, verts, nhull, hull, tris);
+ triangulateHull(nverts, verts, nhull, hull, nin, tris);
return true;
}
@@ -778,7 +779,7 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
// We're using the triangulateHull instead of delaunayHull as it tends to
// create a bit better triangulation for long thin triangles when there
// are no internal points.
- triangulateHull(nverts, verts, nhull, hull, tris);
+ triangulateHull(nverts, verts, nhull, hull, nin, tris);
if (tris.size() == 0)
{
@@ -1140,7 +1141,8 @@ static void getHeightData(rcContext* ctx, const rcCompactHeightfield& chf,
static unsigned char getEdgeFlags(const float* va, const float* vb,
const float* vpoly, const int npoly)
{
- // Return true if edge (va,vb) is part of the polygon.
+ // The flag returned by this function matches dtDetailTriEdgeFlags in Detour.
+ // Figure out if edge (va,vb) is part of the polygon boundary.
static const float thrSqr = rcSqr(0.001f);
for (int i = 0, j = npoly-1; i < npoly; j=i++)
{
diff --git a/thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp b/thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp
index 38a2bd6bfa..e1fc0ee788 100644
--- a/thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp
@@ -25,8 +25,17 @@
#include "Recast.h"
#include "RecastAlloc.h"
#include "RecastAssert.h"
-#include <new>
+namespace
+{
+struct LevelStackEntry
+{
+ LevelStackEntry(int x_, int y_, int index_) : x(x_), y(y_), index(index_) {}
+ int x;
+ int y;
+ int index;
+};
+} // namespace
static void calculateDistanceField(rcCompactHeightfield& chf, unsigned short* src, unsigned short& maxDist)
{
@@ -245,17 +254,15 @@ static bool floodRegion(int x, int y, int i,
unsigned short level, unsigned short r,
rcCompactHeightfield& chf,
unsigned short* srcReg, unsigned short* srcDist,
- rcIntArray& stack)
+ rcTempVector<LevelStackEntry>& stack)
{
const int w = chf.width;
const unsigned char area = chf.areas[i];
// Flood fill mark region.
- stack.resize(0);
- stack.push((int)x);
- stack.push((int)y);
- stack.push((int)i);
+ stack.clear();
+ stack.push_back(LevelStackEntry(x, y, i));
srcReg[i] = r;
srcDist[i] = 0;
@@ -264,9 +271,11 @@ static bool floodRegion(int x, int y, int i,
while (stack.size() > 0)
{
- int ci = stack.pop();
- int cy = stack.pop();
- int cx = stack.pop();
+ LevelStackEntry& back = stack.back();
+ int cx = back.x;
+ int cy = back.y;
+ int ci = back.index;
+ stack.pop_back();
const rcCompactSpan& cs = chf.spans[ci];
@@ -332,9 +341,7 @@ static bool floodRegion(int x, int y, int i,
{
srcReg[ai] = r;
srcDist[ai] = 0;
- stack.push(ax);
- stack.push(ay);
- stack.push(ai);
+ stack.push_back(LevelStackEntry(ax, ay, ai));
}
}
}
@@ -343,12 +350,20 @@ static bool floodRegion(int x, int y, int i,
return count > 0;
}
-static unsigned short* expandRegions(int maxIter, unsigned short level,
- rcCompactHeightfield& chf,
- unsigned short* srcReg, unsigned short* srcDist,
- unsigned short* dstReg, unsigned short* dstDist,
- rcIntArray& stack,
- bool fillStack)
+// Struct to keep track of entries in the region table that have been changed.
+struct DirtyEntry
+{
+ DirtyEntry(int index_, unsigned short region_, unsigned short distance2_)
+ : index(index_), region(region_), distance2(distance2_) {}
+ int index;
+ unsigned short region;
+ unsigned short distance2;
+};
+static void expandRegions(int maxIter, unsigned short level,
+ rcCompactHeightfield& chf,
+ unsigned short* srcReg, unsigned short* srcDist,
+ rcTempVector<LevelStackEntry>& stack,
+ bool fillStack)
{
const int w = chf.width;
const int h = chf.height;
@@ -356,7 +371,7 @@ static unsigned short* expandRegions(int maxIter, unsigned short level,
if (fillStack)
{
// Find cells revealed by the raised level.
- stack.resize(0);
+ stack.clear();
for (int y = 0; y < h; ++y)
{
for (int x = 0; x < w; ++x)
@@ -366,9 +381,7 @@ static unsigned short* expandRegions(int maxIter, unsigned short level,
{
if (chf.dist[i] >= level && srcReg[i] == 0 && chf.areas[i] != RC_NULL_AREA)
{
- stack.push(x);
- stack.push(y);
- stack.push(i);
+ stack.push_back(LevelStackEntry(x, y, i));
}
}
}
@@ -377,27 +390,26 @@ static unsigned short* expandRegions(int maxIter, unsigned short level,
else // use cells in the input stack
{
// mark all cells which already have a region
- for (int j=0; j<stack.size(); j+=3)
+ for (int j=0; j<stack.size(); j++)
{
- int i = stack[j+2];
+ int i = stack[j].index;
if (srcReg[i] != 0)
- stack[j+2] = -1;
+ stack[j].index = -1;
}
}
+ rcTempVector<DirtyEntry> dirtyEntries;
int iter = 0;
while (stack.size() > 0)
{
int failed = 0;
+ dirtyEntries.clear();
- memcpy(dstReg, srcReg, sizeof(unsigned short)*chf.spanCount);
- memcpy(dstDist, srcDist, sizeof(unsigned short)*chf.spanCount);
-
- for (int j = 0; j < stack.size(); j += 3)
+ for (int j = 0; j < stack.size(); j++)
{
- int x = stack[j+0];
- int y = stack[j+1];
- int i = stack[j+2];
+ int x = stack[j].x;
+ int y = stack[j].y;
+ int i = stack[j].index;
if (i < 0)
{
failed++;
@@ -426,9 +438,8 @@ static unsigned short* expandRegions(int maxIter, unsigned short level,
}
if (r)
{
- stack[j+2] = -1; // mark as used
- dstReg[i] = r;
- dstDist[i] = d2;
+ stack[j].index = -1; // mark as used
+ dirtyEntries.push_back(DirtyEntry(i, r, d2));
}
else
{
@@ -436,11 +447,14 @@ static unsigned short* expandRegions(int maxIter, unsigned short level,
}
}
- // rcSwap source and dest.
- rcSwap(srcReg, dstReg);
- rcSwap(srcDist, dstDist);
+ // Copy entries that differ between src and dst to keep them in sync.
+ for (int i = 0; i < dirtyEntries.size(); i++) {
+ int idx = dirtyEntries[i].index;
+ srcReg[idx] = dirtyEntries[i].region;
+ srcDist[idx] = dirtyEntries[i].distance2;
+ }
- if (failed*3 == stack.size())
+ if (failed == stack.size())
break;
if (level > 0)
@@ -450,16 +464,14 @@ static unsigned short* expandRegions(int maxIter, unsigned short level,
break;
}
}
-
- return srcReg;
}
static void sortCellsByLevel(unsigned short startLevel,
rcCompactHeightfield& chf,
- unsigned short* srcReg,
- unsigned int nbStacks, rcIntArray* stacks,
+ const unsigned short* srcReg,
+ unsigned int nbStacks, rcTempVector<LevelStackEntry>* stacks,
unsigned short loglevelsPerStack) // the levels per stack (2 in our case) as a bit shift
{
const int w = chf.width;
@@ -467,7 +479,7 @@ static void sortCellsByLevel(unsigned short startLevel,
startLevel = startLevel >> loglevelsPerStack;
for (unsigned int j=0; j<nbStacks; ++j)
- stacks[j].resize(0);
+ stacks[j].clear();
// put all cells in the level range into the appropriate stacks
for (int y = 0; y < h; ++y)
@@ -487,26 +499,23 @@ static void sortCellsByLevel(unsigned short startLevel,
if (sId < 0)
sId = 0;
- stacks[sId].push(x);
- stacks[sId].push(y);
- stacks[sId].push(i);
+ stacks[sId].push_back(LevelStackEntry(x, y, i));
}
}
}
}
-static void appendStacks(rcIntArray& srcStack, rcIntArray& dstStack,
- unsigned short* srcReg)
+static void appendStacks(const rcTempVector<LevelStackEntry>& srcStack,
+ rcTempVector<LevelStackEntry>& dstStack,
+ const unsigned short* srcReg)
{
- for (int j=0; j<srcStack.size(); j+=3)
+ for (int j=0; j<srcStack.size(); j++)
{
- int i = srcStack[j+2];
+ int i = srcStack[j].index;
if ((i < 0) || (srcReg[i] != 0))
continue;
- dstStack.push(srcStack[j]);
- dstStack.push(srcStack[j+1]);
- dstStack.push(srcStack[j+2]);
+ dstStack.push_back(srcStack[j]);
}
}
@@ -671,7 +680,7 @@ static bool isRegionConnectedToBorder(const rcRegion& reg)
return false;
}
-static bool isSolidEdge(rcCompactHeightfield& chf, unsigned short* srcReg,
+static bool isSolidEdge(rcCompactHeightfield& chf, const unsigned short* srcReg,
int x, int y, int i, int dir)
{
const rcCompactSpan& s = chf.spans[i];
@@ -690,7 +699,7 @@ static bool isSolidEdge(rcCompactHeightfield& chf, unsigned short* srcReg,
static void walkContour(int x, int y, int i, int dir,
rcCompactHeightfield& chf,
- unsigned short* srcReg,
+ const unsigned short* srcReg,
rcIntArray& cont)
{
int startDir = dir;
@@ -786,16 +795,15 @@ static bool mergeAndFilterRegions(rcContext* ctx, int minRegionArea, int mergeRe
const int h = chf.height;
const int nreg = maxRegionId+1;
- rcRegion* regions = (rcRegion*)rcAlloc(sizeof(rcRegion)*nreg, RC_ALLOC_TEMP);
- if (!regions)
- {
+ rcTempVector<rcRegion> regions;
+ if (!regions.reserve(nreg)) {
ctx->log(RC_LOG_ERROR, "mergeAndFilterRegions: Out of memory 'regions' (%d).", nreg);
return false;
}
// Construct regions
for (int i = 0; i < nreg; ++i)
- new(&regions[i]) rcRegion((unsigned short)i);
+ regions.push_back(rcRegion((unsigned short) i));
// Find edge of a region and find connections around the contour.
for (int y = 0; y < h; ++y)
@@ -1021,11 +1029,6 @@ static bool mergeAndFilterRegions(rcContext* ctx, int minRegionArea, int mergeRe
if (regions[i].overlap)
overlaps.push(regions[i].id);
- for (int i = 0; i < nreg; ++i)
- regions[i].~rcRegion();
- rcFree(regions);
-
-
return true;
}
@@ -1041,22 +1044,21 @@ static void addUniqueConnection(rcRegion& reg, int n)
static bool mergeAndFilterLayerRegions(rcContext* ctx, int minRegionArea,
unsigned short& maxRegionId,
rcCompactHeightfield& chf,
- unsigned short* srcReg, rcIntArray& /*overlaps*/)
+ unsigned short* srcReg)
{
const int w = chf.width;
const int h = chf.height;
const int nreg = maxRegionId+1;
- rcRegion* regions = (rcRegion*)rcAlloc(sizeof(rcRegion)*nreg, RC_ALLOC_TEMP);
- if (!regions)
- {
+ rcTempVector<rcRegion> regions;
+
+ // Construct regions
+ if (!regions.reserve(nreg)) {
ctx->log(RC_LOG_ERROR, "mergeAndFilterLayerRegions: Out of memory 'regions' (%d).", nreg);
return false;
}
-
- // Construct regions
for (int i = 0; i < nreg; ++i)
- new(&regions[i]) rcRegion((unsigned short)i);
+ regions.push_back(rcRegion((unsigned short) i));
// Find region neighbours and overlapping regions.
rcIntArray lregs(32);
@@ -1234,10 +1236,6 @@ static bool mergeAndFilterLayerRegions(rcContext* ctx, int minRegionArea,
srcReg[i] = regions[srcReg[i]].id;
}
- for (int i = 0; i < nreg; ++i)
- regions[i].~rcRegion();
- rcFree(regions);
-
return true;
}
@@ -1391,9 +1389,9 @@ bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
paintRectRegion(w-bw, w, 0, h, id|RC_BORDER_REG, chf, srcReg); id++;
paintRectRegion(0, w, 0, bh, id|RC_BORDER_REG, chf, srcReg); id++;
paintRectRegion(0, w, h-bh, h, id|RC_BORDER_REG, chf, srcReg); id++;
-
- chf.borderSize = borderSize;
}
+
+ chf.borderSize = borderSize;
rcIntArray prev(256);
@@ -1535,7 +1533,7 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
const int w = chf.width;
const int h = chf.height;
- rcScopedDelete<unsigned short> buf((unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount*4, RC_ALLOC_TEMP));
+ rcScopedDelete<unsigned short> buf((unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount*2, RC_ALLOC_TEMP));
if (!buf)
{
ctx->log(RC_LOG_ERROR, "rcBuildRegions: Out of memory 'tmp' (%d).", chf.spanCount*4);
@@ -1546,17 +1544,15 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
const int LOG_NB_STACKS = 3;
const int NB_STACKS = 1 << LOG_NB_STACKS;
- rcIntArray lvlStacks[NB_STACKS];
+ rcTempVector<LevelStackEntry> lvlStacks[NB_STACKS];
for (int i=0; i<NB_STACKS; ++i)
- lvlStacks[i].resize(1024);
+ lvlStacks[i].reserve(256);
- rcIntArray stack(1024);
- rcIntArray visited(1024);
+ rcTempVector<LevelStackEntry> stack;
+ stack.reserve(256);
unsigned short* srcReg = buf;
unsigned short* srcDist = buf+chf.spanCount;
- unsigned short* dstReg = buf+chf.spanCount*2;
- unsigned short* dstDist = buf+chf.spanCount*3;
memset(srcReg, 0, sizeof(unsigned short)*chf.spanCount);
memset(srcDist, 0, sizeof(unsigned short)*chf.spanCount);
@@ -1581,9 +1577,9 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
paintRectRegion(w-bw, w, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
paintRectRegion(0, w, 0, bh, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
paintRectRegion(0, w, h-bh, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
-
- chf.borderSize = borderSize;
}
+
+ chf.borderSize = borderSize;
int sId = -1;
while (level > 0)
@@ -1604,22 +1600,19 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
rcScopedTimer timerExpand(ctx, RC_TIMER_BUILD_REGIONS_EXPAND);
// Expand current regions until no empty connected cells found.
- if (expandRegions(expandIters, level, chf, srcReg, srcDist, dstReg, dstDist, lvlStacks[sId], false) != srcReg)
- {
- rcSwap(srcReg, dstReg);
- rcSwap(srcDist, dstDist);
- }
+ expandRegions(expandIters, level, chf, srcReg, srcDist, lvlStacks[sId], false);
}
{
rcScopedTimer timerFloor(ctx, RC_TIMER_BUILD_REGIONS_FLOOD);
// Mark new regions with IDs.
- for (int j = 0; j<lvlStacks[sId].size(); j += 3)
+ for (int j = 0; j<lvlStacks[sId].size(); j++)
{
- int x = lvlStacks[sId][j];
- int y = lvlStacks[sId][j+1];
- int i = lvlStacks[sId][j+2];
+ LevelStackEntry current = lvlStacks[sId][j];
+ int x = current.x;
+ int y = current.y;
+ int i = current.index;
if (i >= 0 && srcReg[i] == 0)
{
if (floodRegion(x, y, i, level, regionId, chf, srcReg, srcDist, stack))
@@ -1638,11 +1631,7 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
}
// Expand current regions until no empty connected cells found.
- if (expandRegions(expandIters*8, 0, chf, srcReg, srcDist, dstReg, dstDist, stack, true) != srcReg)
- {
- rcSwap(srcReg, dstReg);
- rcSwap(srcDist, dstDist);
- }
+ expandRegions(expandIters*8, 0, chf, srcReg, srcDist, stack, true);
ctx->stopTimer(RC_TIMER_BUILD_REGIONS_WATERSHED);
@@ -1709,9 +1698,9 @@ bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf,
paintRectRegion(w-bw, w, 0, h, id|RC_BORDER_REG, chf, srcReg); id++;
paintRectRegion(0, w, 0, bh, id|RC_BORDER_REG, chf, srcReg); id++;
paintRectRegion(0, w, h-bh, h, id|RC_BORDER_REG, chf, srcReg); id++;
-
- chf.borderSize = borderSize;
}
+
+ chf.borderSize = borderSize;
rcIntArray prev(256);
@@ -1809,9 +1798,8 @@ bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf,
rcScopedTimer timerFilter(ctx, RC_TIMER_BUILD_REGIONS_FILTER);
// Merge monotone regions to layers and remove small regions.
- rcIntArray overlaps;
chf.maxRegions = id;
- if (!mergeAndFilterLayerRegions(ctx, minRegionArea, chf.maxRegions, chf, srcReg, overlaps))
+ if (!mergeAndFilterLayerRegions(ctx, minRegionArea, chf.maxRegions, chf, srcReg))
return false;
}
diff --git a/thirdparty/rvo2/LICENSE b/thirdparty/rvo2/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/thirdparty/rvo2/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/thirdparty/rvo2/README.md b/thirdparty/rvo2/README.md
new file mode 100644
index 0000000000..96af597cb6
--- /dev/null
+++ b/thirdparty/rvo2/README.md
@@ -0,0 +1,32 @@
+Optimal Reciprocal Collision Avoidance in Three Dimensions
+==========================================================
+
+<http://gamma.cs.unc.edu/RVO2/>
+
+[![Build Status](https://travis-ci.org/snape/RVO2-3D.png?branch=master)](https://travis-ci.org/snape/RVO2-3D)
+[![Build status](https://ci.appveyor.com/api/projects/status/ov8ec3igv588wpx7/branch/master?svg=true)](https://ci.appveyor.com/project/snape/rvo2-3d)
+
+Copyright 2008 University of North Carolina at Chapel Hill
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+<http://www.apache.org/licenses/LICENSE-2.0>
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Please send all bug reports to [geom@cs.unc.edu](mailto:geom@cs.unc.edu).
+
+The authors may be contacted via:
+
+Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, and Dinesh Manocha
+Dept. of Computer Science
+201 S. Columbia St.
+Frederick P. Brooks, Jr. Computer Science Bldg.
+Chapel Hill, N.C. 27599-3175
+United States of America
diff --git a/thirdparty/rvo2/src/API.h b/thirdparty/rvo2/src/API.h
new file mode 100644
index 0000000000..c64efb452c
--- /dev/null
+++ b/thirdparty/rvo2/src/API.h
@@ -0,0 +1,45 @@
+/*
+ * API.h
+ * RVO2-3D Library
+ *
+ * Copyright 2008 University of North Carolina at Chapel Hill
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Please send all bug reports to <geom@cs.unc.edu>.
+ *
+ * The authors may be contacted via:
+ *
+ * Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
+ * Dept. of Computer Science
+ * 201 S. Columbia St.
+ * Frederick P. Brooks, Jr. Computer Science Bldg.
+ * Chapel Hill, N.C. 27599-3175
+ * United States of America
+ *
+ * <http://gamma.cs.unc.edu/RVO2/>
+ */
+
+/**
+ * \file API.h
+ * \brief Contains definitions related to Microsoft Windows.
+ */
+
+#ifndef RVO_API_H_
+#define RVO_API_H_
+
+// -- GODOT start --
+#define RVO_API
+// -- GODOT end --
+
+#endif /* RVO_API_H_ */
diff --git a/thirdparty/rvo2/src/Agent.cpp b/thirdparty/rvo2/src/Agent.cpp
new file mode 100644
index 0000000000..851d780758
--- /dev/null
+++ b/thirdparty/rvo2/src/Agent.cpp
@@ -0,0 +1,425 @@
+/*
+ * Agent.cpp
+ * RVO2-3D Library
+ *
+ * Copyright 2008 University of North Carolina at Chapel Hill
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Please send all bug reports to <geom@cs.unc.edu>.
+ *
+ * The authors may be contacted via:
+ *
+ * Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
+ * Dept. of Computer Science
+ * 201 S. Columbia St.
+ * Frederick P. Brooks, Jr. Computer Science Bldg.
+ * Chapel Hill, N.C. 27599-3175
+ * United States of America
+ *
+ * <http://gamma.cs.unc.edu/RVO2/>
+ */
+
+#include "Agent.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include "Definitions.h"
+#include "KdTree.h"
+
+namespace RVO {
+/**
+ * \brief A sufficiently small positive number.
+ */
+const float RVO_EPSILON = 0.00001f;
+
+/**
+ * \brief Defines a directed line.
+ */
+class Line {
+public:
+ /**
+ * \brief The direction of the directed line.
+ */
+ Vector3 direction;
+
+ /**
+ * \brief A point on the directed line.
+ */
+ Vector3 point;
+};
+
+/**
+ * \brief Solves a one-dimensional linear program on a specified line subject to linear constraints defined by planes and a spherical constraint.
+ * \param planes Planes defining the linear constraints.
+ * \param planeNo The plane on which the line lies.
+ * \param line The line on which the 1-d linear program is solved
+ * \param radius The radius of the spherical constraint.
+ * \param optVelocity The optimization velocity.
+ * \param directionOpt True if the direction should be optimized.
+ * \param result A reference to the result of the linear program.
+ * \return True if successful.
+ */
+bool linearProgram1(const std::vector<Plane> &planes, size_t planeNo, const Line &line, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result);
+
+/**
+ * \brief Solves a two-dimensional linear program on a specified plane subject to linear constraints defined by planes and a spherical constraint.
+ * \param planes Planes defining the linear constraints.
+ * \param planeNo The plane on which the 2-d linear program is solved
+ * \param radius The radius of the spherical constraint.
+ * \param optVelocity The optimization velocity.
+ * \param directionOpt True if the direction should be optimized.
+ * \param result A reference to the result of the linear program.
+ * \return True if successful.
+ */
+bool linearProgram2(const std::vector<Plane> &planes, size_t planeNo, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result);
+
+/**
+ * \brief Solves a three-dimensional linear program subject to linear constraints defined by planes and a spherical constraint.
+ * \param planes Planes defining the linear constraints.
+ * \param radius The radius of the spherical constraint.
+ * \param optVelocity The optimization velocity.
+ * \param directionOpt True if the direction should be optimized.
+ * \param result A reference to the result of the linear program.
+ * \return The number of the plane it fails on, and the number of planes if successful.
+ */
+size_t linearProgram3(const std::vector<Plane> &planes, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result);
+
+/**
+ * \brief Solves a four-dimensional linear program subject to linear constraints defined by planes and a spherical constraint.
+ * \param planes Planes defining the linear constraints.
+ * \param beginPlane The plane on which the 3-d linear program failed.
+ * \param radius The radius of the spherical constraint.
+ * \param result A reference to the result of the linear program.
+ */
+void linearProgram4(const std::vector<Plane> &planes, size_t beginPlane, float radius, Vector3 &result);
+
+Agent::Agent() :
+ id_(0), maxNeighbors_(0), maxSpeed_(0.0f), neighborDist_(0.0f), radius_(0.0f), timeHorizon_(0.0f), ignore_y_(false) {}
+
+void Agent::computeNeighbors(KdTree *kdTree_) {
+ agentNeighbors_.clear();
+ if (maxNeighbors_ > 0) {
+ kdTree_->computeAgentNeighbors(this, neighborDist_ * neighborDist_);
+ }
+}
+
+#define ABS(m_v) (((m_v) < 0) ? (-(m_v)) : (m_v))
+void Agent::computeNewVelocity(float timeStep) {
+ orcaPlanes_.clear();
+ const float invTimeHorizon = 1.0f / timeHorizon_;
+
+ /* Create agent ORCA planes. */
+ for (size_t i = 0; i < agentNeighbors_.size(); ++i) {
+ const Agent *const other = agentNeighbors_[i].second;
+
+ Vector3 relativePosition = other->position_ - position_;
+ Vector3 relativeVelocity = velocity_ - other->velocity_;
+ const float combinedRadius = radius_ + other->radius_;
+
+ // This is a Godot feature that allow the agents to avoid the collision
+ // by moving only on the horizontal plane relative to the player velocity.
+ if (ignore_y_) {
+ // Skip if these are in two different heights
+ if (ABS(relativePosition[1]) > combinedRadius * 2) {
+ continue;
+ }
+ relativePosition[1] = 0;
+ relativeVelocity[1] = 0;
+ }
+
+ const float distSq = absSq(relativePosition);
+ const float combinedRadiusSq = sqr(combinedRadius);
+
+ Plane plane;
+ Vector3 u;
+
+ if (distSq > combinedRadiusSq) {
+ /* No collision. */
+ const Vector3 w = relativeVelocity - invTimeHorizon * relativePosition;
+ /* Vector from cutoff center to relative velocity. */
+ const float wLengthSq = absSq(w);
+
+ const float dotProduct = w * relativePosition;
+
+ if (dotProduct < 0.0f && sqr(dotProduct) > combinedRadiusSq * wLengthSq) {
+ /* Project on cut-off circle. */
+ const float wLength = std::sqrt(wLengthSq);
+ const Vector3 unitW = w / wLength;
+
+ plane.normal = unitW;
+ u = (combinedRadius * invTimeHorizon - wLength) * unitW;
+ } else {
+ /* Project on cone. */
+ const float a = distSq;
+ const float b = relativePosition * relativeVelocity;
+ const float c = absSq(relativeVelocity) - absSq(cross(relativePosition, relativeVelocity)) / (distSq - combinedRadiusSq);
+ const float t = (b + std::sqrt(sqr(b) - a * c)) / a;
+ const Vector3 w = relativeVelocity - t * relativePosition;
+ const float wLength = abs(w);
+ const Vector3 unitW = w / wLength;
+
+ plane.normal = unitW;
+ u = (combinedRadius * t - wLength) * unitW;
+ }
+ } else {
+ /* Collision. */
+ const float invTimeStep = 1.0f / timeStep;
+ const Vector3 w = relativeVelocity - invTimeStep * relativePosition;
+ const float wLength = abs(w);
+ const Vector3 unitW = w / wLength;
+
+ plane.normal = unitW;
+ u = (combinedRadius * invTimeStep - wLength) * unitW;
+ }
+
+ plane.point = velocity_ + 0.5f * u;
+ orcaPlanes_.push_back(plane);
+ }
+
+ const size_t planeFail = linearProgram3(orcaPlanes_, maxSpeed_, prefVelocity_, false, newVelocity_);
+
+ if (planeFail < orcaPlanes_.size()) {
+ linearProgram4(orcaPlanes_, planeFail, maxSpeed_, newVelocity_);
+ }
+
+ if (ignore_y_) {
+ // Not 100% necessary, but better to have.
+ newVelocity_[1] = prefVelocity_[1];
+ }
+}
+
+void Agent::insertAgentNeighbor(const Agent *agent, float &rangeSq) {
+ if (this != agent) {
+ const float distSq = absSq(position_ - agent->position_);
+
+ if (distSq < rangeSq) {
+ if (agentNeighbors_.size() < maxNeighbors_) {
+ agentNeighbors_.push_back(std::make_pair(distSq, agent));
+ }
+
+ size_t i = agentNeighbors_.size() - 1;
+
+ while (i != 0 && distSq < agentNeighbors_[i - 1].first) {
+ agentNeighbors_[i] = agentNeighbors_[i - 1];
+ --i;
+ }
+
+ agentNeighbors_[i] = std::make_pair(distSq, agent);
+
+ if (agentNeighbors_.size() == maxNeighbors_) {
+ rangeSq = agentNeighbors_.back().first;
+ }
+ }
+ }
+}
+
+bool linearProgram1(const std::vector<Plane> &planes, size_t planeNo, const Line &line, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result) {
+ const float dotProduct = line.point * line.direction;
+ const float discriminant = sqr(dotProduct) + sqr(radius) - absSq(line.point);
+
+ if (discriminant < 0.0f) {
+ /* Max speed sphere fully invalidates line. */
+ return false;
+ }
+
+ const float sqrtDiscriminant = std::sqrt(discriminant);
+ float tLeft = -dotProduct - sqrtDiscriminant;
+ float tRight = -dotProduct + sqrtDiscriminant;
+
+ for (size_t i = 0; i < planeNo; ++i) {
+ const float numerator = (planes[i].point - line.point) * planes[i].normal;
+ const float denominator = line.direction * planes[i].normal;
+
+ if (sqr(denominator) <= RVO_EPSILON) {
+ /* Lines line is (almost) parallel to plane i. */
+ if (numerator > 0.0f) {
+ return false;
+ } else {
+ continue;
+ }
+ }
+
+ const float t = numerator / denominator;
+
+ if (denominator >= 0.0f) {
+ /* Plane i bounds line on the left. */
+ tLeft = std::max(tLeft, t);
+ } else {
+ /* Plane i bounds line on the right. */
+ tRight = std::min(tRight, t);
+ }
+
+ if (tLeft > tRight) {
+ return false;
+ }
+ }
+
+ if (directionOpt) {
+ /* Optimize direction. */
+ if (optVelocity * line.direction > 0.0f) {
+ /* Take right extreme. */
+ result = line.point + tRight * line.direction;
+ } else {
+ /* Take left extreme. */
+ result = line.point + tLeft * line.direction;
+ }
+ } else {
+ /* Optimize closest point. */
+ const float t = line.direction * (optVelocity - line.point);
+
+ if (t < tLeft) {
+ result = line.point + tLeft * line.direction;
+ } else if (t > tRight) {
+ result = line.point + tRight * line.direction;
+ } else {
+ result = line.point + t * line.direction;
+ }
+ }
+
+ return true;
+}
+
+bool linearProgram2(const std::vector<Plane> &planes, size_t planeNo, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result) {
+ const float planeDist = planes[planeNo].point * planes[planeNo].normal;
+ const float planeDistSq = sqr(planeDist);
+ const float radiusSq = sqr(radius);
+
+ if (planeDistSq > radiusSq) {
+ /* Max speed sphere fully invalidates plane planeNo. */
+ return false;
+ }
+
+ const float planeRadiusSq = radiusSq - planeDistSq;
+
+ const Vector3 planeCenter = planeDist * planes[planeNo].normal;
+
+ if (directionOpt) {
+ /* Project direction optVelocity on plane planeNo. */
+ const Vector3 planeOptVelocity = optVelocity - (optVelocity * planes[planeNo].normal) * planes[planeNo].normal;
+ const float planeOptVelocityLengthSq = absSq(planeOptVelocity);
+
+ if (planeOptVelocityLengthSq <= RVO_EPSILON) {
+ result = planeCenter;
+ } else {
+ result = planeCenter + std::sqrt(planeRadiusSq / planeOptVelocityLengthSq) * planeOptVelocity;
+ }
+ } else {
+ /* Project point optVelocity on plane planeNo. */
+ result = optVelocity + ((planes[planeNo].point - optVelocity) * planes[planeNo].normal) * planes[planeNo].normal;
+
+ /* If outside planeCircle, project on planeCircle. */
+ if (absSq(result) > radiusSq) {
+ const Vector3 planeResult = result - planeCenter;
+ const float planeResultLengthSq = absSq(planeResult);
+ result = planeCenter + std::sqrt(planeRadiusSq / planeResultLengthSq) * planeResult;
+ }
+ }
+
+ for (size_t i = 0; i < planeNo; ++i) {
+ if (planes[i].normal * (planes[i].point - result) > 0.0f) {
+ /* Result does not satisfy constraint i. Compute new optimal result. */
+ /* Compute intersection line of plane i and plane planeNo. */
+ Vector3 crossProduct = cross(planes[i].normal, planes[planeNo].normal);
+
+ if (absSq(crossProduct) <= RVO_EPSILON) {
+ /* Planes planeNo and i are (almost) parallel, and plane i fully invalidates plane planeNo. */
+ return false;
+ }
+
+ Line line;
+ line.direction = normalize(crossProduct);
+ const Vector3 lineNormal = cross(line.direction, planes[planeNo].normal);
+ line.point = planes[planeNo].point + (((planes[i].point - planes[planeNo].point) * planes[i].normal) / (lineNormal * planes[i].normal)) * lineNormal;
+
+ if (!linearProgram1(planes, i, line, radius, optVelocity, directionOpt, result)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+size_t linearProgram3(const std::vector<Plane> &planes, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result) {
+ if (directionOpt) {
+ /* Optimize direction. Note that the optimization velocity is of unit length in this case. */
+ result = optVelocity * radius;
+ } else if (absSq(optVelocity) > sqr(radius)) {
+ /* Optimize closest point and outside circle. */
+ result = normalize(optVelocity) * radius;
+ } else {
+ /* Optimize closest point and inside circle. */
+ result = optVelocity;
+ }
+
+ for (size_t i = 0; i < planes.size(); ++i) {
+ if (planes[i].normal * (planes[i].point - result) > 0.0f) {
+ /* Result does not satisfy constraint i. Compute new optimal result. */
+ const Vector3 tempResult = result;
+
+ if (!linearProgram2(planes, i, radius, optVelocity, directionOpt, result)) {
+ result = tempResult;
+ return i;
+ }
+ }
+ }
+
+ return planes.size();
+}
+
+void linearProgram4(const std::vector<Plane> &planes, size_t beginPlane, float radius, Vector3 &result) {
+ float distance = 0.0f;
+
+ for (size_t i = beginPlane; i < planes.size(); ++i) {
+ if (planes[i].normal * (planes[i].point - result) > distance) {
+ /* Result does not satisfy constraint of plane i. */
+ std::vector<Plane> projPlanes;
+
+ for (size_t j = 0; j < i; ++j) {
+ Plane plane;
+
+ const Vector3 crossProduct = cross(planes[j].normal, planes[i].normal);
+
+ if (absSq(crossProduct) <= RVO_EPSILON) {
+ /* Plane i and plane j are (almost) parallel. */
+ if (planes[i].normal * planes[j].normal > 0.0f) {
+ /* Plane i and plane j point in the same direction. */
+ continue;
+ } else {
+ /* Plane i and plane j point in opposite direction. */
+ plane.point = 0.5f * (planes[i].point + planes[j].point);
+ }
+ } else {
+ /* Plane.point is point on line of intersection between plane i and plane j. */
+ const Vector3 lineNormal = cross(crossProduct, planes[i].normal);
+ plane.point = planes[i].point + (((planes[j].point - planes[i].point) * planes[j].normal) / (lineNormal * planes[j].normal)) * lineNormal;
+ }
+
+ plane.normal = normalize(planes[j].normal - planes[i].normal);
+ projPlanes.push_back(plane);
+ }
+
+ const Vector3 tempResult = result;
+
+ if (linearProgram3(projPlanes, radius, planes[i].normal, true, result) < projPlanes.size()) {
+ /* This should in principle not happen. The result is by definition already in the feasible region of this linear program. If it fails, it is due to small floating point error, and the current result is kept. */
+ result = tempResult;
+ }
+
+ distance = planes[i].normal * (planes[i].point - result);
+ }
+ }
+}
+} // namespace RVO
diff --git a/thirdparty/rvo2/src/Agent.h b/thirdparty/rvo2/src/Agent.h
new file mode 100644
index 0000000000..16f75a08f6
--- /dev/null
+++ b/thirdparty/rvo2/src/Agent.h
@@ -0,0 +1,121 @@
+/*
+ * Agent.h
+ * RVO2-3D Library
+ *
+ * Copyright 2008 University of North Carolina at Chapel Hill
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Please send all bug reports to <geom@cs.unc.edu>.
+ *
+ * The authors may be contacted via:
+ *
+ * Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
+ * Dept. of Computer Science
+ * 201 S. Columbia St.
+ * Frederick P. Brooks, Jr. Computer Science Bldg.
+ * Chapel Hill, N.C. 27599-3175
+ * United States of America
+ *
+ * <http://gamma.cs.unc.edu/RVO2/>
+ */
+
+/**
+ * \file Agent.h
+ * \brief Contains the Agent class.
+ */
+#ifndef RVO_AGENT_H_
+#define RVO_AGENT_H_
+
+#include "API.h"
+
+#include <cstddef>
+#include <utility>
+#include <vector>
+
+#include "Vector3.h"
+
+// Note: Slightly modified to work better in Godot.
+// - The agent can be created by anyone.
+// - The simulator pointer is removed.
+// - The update function is removed.
+// - The compute velocity function now need the timeStep.
+// - Moved the `Plane` class here.
+// - Added a new parameter `ignore_y_` in the `Agent`. This parameter is used to control a godot feature that allows to avoid collisions by moving on the horizontal plane.
+namespace RVO {
+/**
+ * \brief Defines a plane.
+ */
+class Plane {
+public:
+ /**
+ * \brief A point on the plane.
+ */
+ Vector3 point;
+
+ /**
+ * \brief The normal to the plane.
+ */
+ Vector3 normal;
+};
+
+/**
+ * \brief Defines an agent in the simulation.
+ */
+class Agent {
+
+public:
+ /**
+ * \brief Constructs an agent instance.
+ * \param sim The simulator instance.
+ */
+ explicit Agent();
+
+ /**
+ * \brief Computes the neighbors of this agent.
+ */
+ void computeNeighbors(class KdTree *kdTree_);
+
+ /**
+ * \brief Computes the new velocity of this agent.
+ */
+ void computeNewVelocity(float timeStep);
+
+ /**
+ * \brief Inserts an agent neighbor into the set of neighbors of this agent.
+ * \param agent A pointer to the agent to be inserted.
+ * \param rangeSq The squared range around this agent.
+ */
+ void insertAgentNeighbor(const Agent *agent, float &rangeSq);
+
+ Vector3 newVelocity_;
+ Vector3 position_;
+ Vector3 prefVelocity_;
+ Vector3 velocity_;
+ size_t id_;
+ size_t maxNeighbors_;
+ float maxSpeed_;
+ float neighborDist_;
+ float radius_;
+ float timeHorizon_;
+ std::vector<std::pair<float, const Agent *> > agentNeighbors_;
+ std::vector<Plane> orcaPlanes_;
+ /// This is a godot feature that allows the Agent to avoid collision by mooving
+ /// on the horizontal plane.
+ bool ignore_y_;
+
+ friend class KdTree;
+};
+} // namespace RVO
+
+#endif /* RVO_AGENT_H_ */
diff --git a/thirdparty/rvo2/src/Definitions.h b/thirdparty/rvo2/src/Definitions.h
new file mode 100644
index 0000000000..a73aca9908
--- /dev/null
+++ b/thirdparty/rvo2/src/Definitions.h
@@ -0,0 +1,55 @@
+/*
+ * Definitions.h
+ * RVO2-3D Library
+ *
+ * Copyright 2008 University of North Carolina at Chapel Hill
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Please send all bug reports to <geom@cs.unc.edu>.
+ *
+ * The authors may be contacted via:
+ *
+ * Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
+ * Dept. of Computer Science
+ * 201 S. Columbia St.
+ * Frederick P. Brooks, Jr. Computer Science Bldg.
+ * Chapel Hill, N.C. 27599-3175
+ * United States of America
+ *
+ * <http://gamma.cs.unc.edu/RVO2/>
+ */
+
+/**
+ * \file Definitions.h
+ * \brief Contains functions and constants used in multiple classes.
+ */
+
+#ifndef RVO_DEFINITIONS_H_
+#define RVO_DEFINITIONS_H_
+
+#include "API.h"
+
+namespace RVO {
+ /**
+ * \brief Computes the square of a float.
+ * \param scalar The float to be squared.
+ * \return The square of the float.
+ */
+ inline float sqr(float scalar)
+ {
+ return scalar * scalar;
+ }
+}
+
+#endif /* RVO_DEFINITIONS_H_ */
diff --git a/thirdparty/rvo2/src/KdTree.cpp b/thirdparty/rvo2/src/KdTree.cpp
new file mode 100644
index 0000000000..bc224614f0
--- /dev/null
+++ b/thirdparty/rvo2/src/KdTree.cpp
@@ -0,0 +1,152 @@
+/*
+ * KdTree.cpp
+ * RVO2-3D Library
+ *
+ * Copyright 2008 University of North Carolina at Chapel Hill
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Please send all bug reports to <geom@cs.unc.edu>.
+ *
+ * The authors may be contacted via:
+ *
+ * Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
+ * Dept. of Computer Science
+ * 201 S. Columbia St.
+ * Frederick P. Brooks, Jr. Computer Science Bldg.
+ * Chapel Hill, N.C. 27599-3175
+ * United States of America
+ *
+ * <http://gamma.cs.unc.edu/RVO2/>
+ */
+
+#include "KdTree.h"
+
+#include <algorithm>
+
+#include "Agent.h"
+#include "Definitions.h"
+
+namespace RVO {
+const size_t RVO_MAX_LEAF_SIZE = 10;
+
+KdTree::KdTree() {}
+
+void KdTree::buildAgentTree(std::vector<Agent *> agents) {
+ agents_.swap(agents);
+
+ if (!agents_.empty()) {
+ agentTree_.resize(2 * agents_.size() - 1);
+ buildAgentTreeRecursive(0, agents_.size(), 0);
+ }
+}
+
+void KdTree::buildAgentTreeRecursive(size_t begin, size_t end, size_t node) {
+ agentTree_[node].begin = begin;
+ agentTree_[node].end = end;
+ agentTree_[node].minCoord = agents_[begin]->position_;
+ agentTree_[node].maxCoord = agents_[begin]->position_;
+
+ for (size_t i = begin + 1; i < end; ++i) {
+ agentTree_[node].maxCoord[0] = std::max(agentTree_[node].maxCoord[0], agents_[i]->position_.x());
+ agentTree_[node].minCoord[0] = std::min(agentTree_[node].minCoord[0], agents_[i]->position_.x());
+ agentTree_[node].maxCoord[1] = std::max(agentTree_[node].maxCoord[1], agents_[i]->position_.y());
+ agentTree_[node].minCoord[1] = std::min(agentTree_[node].minCoord[1], agents_[i]->position_.y());
+ agentTree_[node].maxCoord[2] = std::max(agentTree_[node].maxCoord[2], agents_[i]->position_.z());
+ agentTree_[node].minCoord[2] = std::min(agentTree_[node].minCoord[2], agents_[i]->position_.z());
+ }
+
+ if (end - begin > RVO_MAX_LEAF_SIZE) {
+ /* No leaf node. */
+ size_t coord;
+
+ if (agentTree_[node].maxCoord[0] - agentTree_[node].minCoord[0] > agentTree_[node].maxCoord[1] - agentTree_[node].minCoord[1] && agentTree_[node].maxCoord[0] - agentTree_[node].minCoord[0] > agentTree_[node].maxCoord[2] - agentTree_[node].minCoord[2]) {
+ coord = 0;
+ } else if (agentTree_[node].maxCoord[1] - agentTree_[node].minCoord[1] > agentTree_[node].maxCoord[2] - agentTree_[node].minCoord[2]) {
+ coord = 1;
+ } else {
+ coord = 2;
+ }
+
+ const float splitValue = 0.5f * (agentTree_[node].maxCoord[coord] + agentTree_[node].minCoord[coord]);
+
+ size_t left = begin;
+
+ size_t right = end;
+
+ while (left < right) {
+ while (left < right && agents_[left]->position_[coord] < splitValue) {
+ ++left;
+ }
+
+ while (right > left && agents_[right - 1]->position_[coord] >= splitValue) {
+ --right;
+ }
+
+ if (left < right) {
+ std::swap(agents_[left], agents_[right - 1]);
+ ++left;
+ --right;
+ }
+ }
+
+ size_t leftSize = left - begin;
+
+ if (leftSize == 0) {
+ ++leftSize;
+ ++left;
+ ++right;
+ }
+
+ agentTree_[node].left = node + 1;
+ agentTree_[node].right = node + 2 * leftSize;
+
+ buildAgentTreeRecursive(begin, left, agentTree_[node].left);
+ buildAgentTreeRecursive(left, end, agentTree_[node].right);
+ }
+}
+
+void KdTree::computeAgentNeighbors(Agent *agent, float rangeSq) const {
+ queryAgentTreeRecursive(agent, rangeSq, 0);
+}
+
+void KdTree::queryAgentTreeRecursive(Agent *agent, float &rangeSq, size_t node) const {
+ if (agentTree_[node].end - agentTree_[node].begin <= RVO_MAX_LEAF_SIZE) {
+ for (size_t i = agentTree_[node].begin; i < agentTree_[node].end; ++i) {
+ agent->insertAgentNeighbor(agents_[i], rangeSq);
+ }
+ } else {
+ const float distSqLeft = sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minCoord[0] - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].left].maxCoord[0])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minCoord[1] - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].left].maxCoord[1])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minCoord[2] - agent->position_.z())) + sqr(std::max(0.0f, agent->position_.z() - agentTree_[agentTree_[node].left].maxCoord[2]));
+
+ const float distSqRight = sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minCoord[0] - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].right].maxCoord[0])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minCoord[1] - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].right].maxCoord[1])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minCoord[2] - agent->position_.z())) + sqr(std::max(0.0f, agent->position_.z() - agentTree_[agentTree_[node].right].maxCoord[2]));
+
+ if (distSqLeft < distSqRight) {
+ if (distSqLeft < rangeSq) {
+ queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
+
+ if (distSqRight < rangeSq) {
+ queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);
+ }
+ }
+ } else {
+ if (distSqRight < rangeSq) {
+ queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);
+
+ if (distSqLeft < rangeSq) {
+ queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
+ }
+ }
+ }
+ }
+}
+} // namespace RVO
diff --git a/thirdparty/rvo2/src/KdTree.h b/thirdparty/rvo2/src/KdTree.h
new file mode 100644
index 0000000000..1dbad00ea4
--- /dev/null
+++ b/thirdparty/rvo2/src/KdTree.h
@@ -0,0 +1,124 @@
+/*
+ * KdTree.h
+ * RVO2-3D Library
+ *
+ * Copyright 2008 University of North Carolina at Chapel Hill
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Please send all bug reports to <geom@cs.unc.edu>.
+ *
+ * The authors may be contacted via:
+ *
+ * Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
+ * Dept. of Computer Science
+ * 201 S. Columbia St.
+ * Frederick P. Brooks, Jr. Computer Science Bldg.
+ * Chapel Hill, N.C. 27599-3175
+ * United States of America
+ *
+ * <http://gamma.cs.unc.edu/RVO2/>
+ */
+/**
+ * \file KdTree.h
+ * \brief Contains the KdTree class.
+ */
+#ifndef RVO_KD_TREE_H_
+#define RVO_KD_TREE_H_
+
+#include "API.h"
+
+#include <cstddef>
+#include <vector>
+
+#include "Vector3.h"
+
+// Note: Slightly modified to work better with Godot.
+// - Removed `sim_`.
+// - KdTree things are public
+namespace RVO {
+class Agent;
+class RVOSimulator;
+
+/**
+ * \brief Defines <i>k</i>d-trees for agents in the simulation.
+ */
+class KdTree {
+public:
+ /**
+ * \brief Defines an agent <i>k</i>d-tree node.
+ */
+ class AgentTreeNode {
+ public:
+ /**
+ * \brief The beginning node number.
+ */
+ size_t begin;
+
+ /**
+ * \brief The ending node number.
+ */
+ size_t end;
+
+ /**
+ * \brief The left node number.
+ */
+ size_t left;
+
+ /**
+ * \brief The right node number.
+ */
+ size_t right;
+
+ /**
+ * \brief The maximum coordinates.
+ */
+ Vector3 maxCoord;
+
+ /**
+ * \brief The minimum coordinates.
+ */
+ Vector3 minCoord;
+ };
+
+ /**
+ * \brief Constructs a <i>k</i>d-tree instance.
+ * \param sim The simulator instance.
+ */
+ explicit KdTree();
+
+ /**
+ * \brief Builds an agent <i>k</i>d-tree.
+ */
+ void buildAgentTree(std::vector<Agent *> agents);
+
+ void buildAgentTreeRecursive(size_t begin, size_t end, size_t node);
+
+ /**
+ * \brief Computes the agent neighbors of the specified agent.
+ * \param agent A pointer to the agent for which agent neighbors are to be computed.
+ * \param rangeSq The squared range around the agent.
+ */
+ void computeAgentNeighbors(Agent *agent, float rangeSq) const;
+
+ void queryAgentTreeRecursive(Agent *agent, float &rangeSq, size_t node) const;
+
+ std::vector<Agent *> agents_;
+ std::vector<AgentTreeNode> agentTree_;
+
+ friend class Agent;
+ friend class RVOSimulator;
+};
+} // namespace RVO
+
+#endif /* RVO_KD_TREE_H_ */
diff --git a/thirdparty/rvo2/src/Vector3.h b/thirdparty/rvo2/src/Vector3.h
new file mode 100644
index 0000000000..8c8835c865
--- /dev/null
+++ b/thirdparty/rvo2/src/Vector3.h
@@ -0,0 +1,335 @@
+/*
+ * Vector3.h
+ * RVO2-3D Library
+ *
+ * Copyright 2008 University of North Carolina at Chapel Hill
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Please send all bug reports to <geom@cs.unc.edu>.
+ *
+ * The authors may be contacted via:
+ *
+ * Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
+ * Dept. of Computer Science
+ * 201 S. Columbia St.
+ * Frederick P. Brooks, Jr. Computer Science Bldg.
+ * Chapel Hill, N.C. 27599-3175
+ * United States of America
+ *
+ * <http://gamma.cs.unc.edu/RVO2/>
+ */
+
+/**
+ * \file Vector3.h
+ * \brief Contains the Vector3 class.
+ */
+#ifndef RVO_VECTOR3_H_
+#define RVO_VECTOR3_H_
+
+#include "API.h"
+
+#include <cmath>
+#include <cstddef>
+#include <ostream>
+
+namespace RVO {
+ /**
+ * \brief Defines a three-dimensional vector.
+ */
+ class Vector3 {
+ public:
+ /**
+ * \brief Constructs and initializes a three-dimensional vector instance to zero.
+ */
+ RVO_API inline Vector3()
+ {
+ val_[0] = 0.0f;
+ val_[1] = 0.0f;
+ val_[2] = 0.0f;
+ }
+
+ /**
+ * \brief Constructs and initializes a three-dimensional vector from the specified three-element array.
+ * \param val The three-element array containing the xyz-coordinates.
+ */
+ RVO_API inline explicit Vector3(const float val[3])
+ {
+ val_[0] = val[0];
+ val_[1] = val[1];
+ val_[2] = val[2];
+ }
+
+ /**
+ * \brief Constructs and initializes a three-dimensional vector from the specified xyz-coordinates.
+ * \param x The x-coordinate of the three-dimensional vector.
+ * \param y The y-coordinate of the three-dimensional vector.
+ * \param z The z-coordinate of the three-dimensional vector.
+ */
+ RVO_API inline Vector3(float x, float y, float z)
+ {
+ val_[0] = x;
+ val_[1] = y;
+ val_[2] = z;
+ }
+
+ /**
+ * \brief Returns the x-coordinate of this three-dimensional vector.
+ * \return The x-coordinate of the three-dimensional vector.
+ */
+ RVO_API inline float x() const { return val_[0]; }
+
+ /**
+ * \brief Returns the y-coordinate of this three-dimensional vector.
+ * \return The y-coordinate of the three-dimensional vector.
+ */
+ RVO_API inline float y() const { return val_[1]; }
+
+ /**
+ * \brief Returns the z-coordinate of this three-dimensional vector.
+ * \return The z-coordinate of the three-dimensional vector.
+ */
+ RVO_API inline float z() const { return val_[2]; }
+
+ /**
+ * \brief Returns the specified coordinate of this three-dimensional vector.
+ * \param i The coordinate that should be returned (0 <= i < 3).
+ * \return The specified coordinate of the three-dimensional vector.
+ */
+ RVO_API inline float operator[](size_t i) const { return val_[i]; }
+
+ /**
+ * \brief Returns a reference to the specified coordinate of this three-dimensional vector.
+ * \param i The coordinate to which a reference should be returned (0 <= i < 3).
+ * \return A reference to the specified coordinate of the three-dimensional vector.
+ */
+ RVO_API inline float &operator[](size_t i) { return val_[i]; }
+
+ /**
+ * \brief Computes the negation of this three-dimensional vector.
+ * \return The negation of this three-dimensional vector.
+ */
+ RVO_API inline Vector3 operator-() const
+ {
+ return Vector3(-val_[0], -val_[1], -val_[2]);
+ }
+
+ /**
+ * \brief Computes the dot product of this three-dimensional vector with the specified three-dimensional vector.
+ * \param vector The three-dimensional vector with which the dot product should be computed.
+ * \return The dot product of this three-dimensional vector with a specified three-dimensional vector.
+ */
+ RVO_API inline float operator*(const Vector3 &vector) const
+ {
+ return val_[0] * vector[0] + val_[1] * vector[1] + val_[2] * vector[2];
+ }
+
+ /**
+ * \brief Computes the scalar multiplication of this three-dimensional vector with the specified scalar value.
+ * \param scalar The scalar value with which the scalar multiplication should be computed.
+ * \return The scalar multiplication of this three-dimensional vector with a specified scalar value.
+ */
+ RVO_API inline Vector3 operator*(float scalar) const
+ {
+ return Vector3(val_[0] * scalar, val_[1] * scalar, val_[2] * scalar);
+ }
+
+ /**
+ * \brief Computes the scalar division of this three-dimensional vector with the specified scalar value.
+ * \param scalar The scalar value with which the scalar division should be computed.
+ * \return The scalar division of this three-dimensional vector with a specified scalar value.
+ */
+ RVO_API inline Vector3 operator/(float scalar) const
+ {
+ const float invScalar = 1.0f / scalar;
+
+ return Vector3(val_[0] * invScalar, val_[1] * invScalar, val_[2] * invScalar);
+ }
+
+ /**
+ * \brief Computes the vector sum of this three-dimensional vector with the specified three-dimensional vector.
+ * \param vector The three-dimensional vector with which the vector sum should be computed.
+ * \return The vector sum of this three-dimensional vector with a specified three-dimensional vector.
+ */
+ RVO_API inline Vector3 operator+(const Vector3 &vector) const
+ {
+ return Vector3(val_[0] + vector[0], val_[1] + vector[1], val_[2] + vector[2]);
+ }
+
+ /**
+ * \brief Computes the vector difference of this three-dimensional vector with the specified three-dimensional vector.
+ * \param vector The three-dimensional vector with which the vector difference should be computed.
+ * \return The vector difference of this three-dimensional vector with a specified three-dimensional vector.
+ */
+ RVO_API inline Vector3 operator-(const Vector3 &vector) const
+ {
+ return Vector3(val_[0] - vector[0], val_[1] - vector[1], val_[2] - vector[2]);
+ }
+
+ /**
+ * \brief Tests this three-dimensional vector for equality with the specified three-dimensional vector.
+ * \param vector The three-dimensional vector with which to test for equality.
+ * \return True if the three-dimensional vectors are equal.
+ */
+ RVO_API inline bool operator==(const Vector3 &vector) const
+ {
+ return val_[0] == vector[0] && val_[1] == vector[1] && val_[2] == vector[2];
+ }
+
+ /**
+ * \brief Tests this three-dimensional vector for inequality with the specified three-dimensional vector.
+ * \param vector The three-dimensional vector with which to test for inequality.
+ * \return True if the three-dimensional vectors are not equal.
+ */
+ RVO_API inline bool operator!=(const Vector3 &vector) const
+ {
+ return val_[0] != vector[0] || val_[1] != vector[1] || val_[2] != vector[2];
+ }
+
+ /**
+ * \brief Sets the value of this three-dimensional vector to the scalar multiplication of itself with the specified scalar value.
+ * \param scalar The scalar value with which the scalar multiplication should be computed.
+ * \return A reference to this three-dimensional vector.
+ */
+ RVO_API inline Vector3 &operator*=(float scalar)
+ {
+ val_[0] *= scalar;
+ val_[1] *= scalar;
+ val_[2] *= scalar;
+
+ return *this;
+ }
+
+ /**
+ * \brief Sets the value of this three-dimensional vector to the scalar division of itself with the specified scalar value.
+ * \param scalar The scalar value with which the scalar division should be computed.
+ * \return A reference to this three-dimensional vector.
+ */
+ RVO_API inline Vector3 &operator/=(float scalar)
+ {
+ const float invScalar = 1.0f / scalar;
+
+ val_[0] *= invScalar;
+ val_[1] *= invScalar;
+ val_[2] *= invScalar;
+
+ return *this;
+ }
+
+ /**
+ * \brief Sets the value of this three-dimensional vector to the vector
+ * sum of itself with the specified three-dimensional vector.
+ * \param vector The three-dimensional vector with which the vector sum should be computed.
+ * \return A reference to this three-dimensional vector.
+ */
+ RVO_API inline Vector3 &operator+=(const Vector3 &vector)
+ {
+ val_[0] += vector[0];
+ val_[1] += vector[1];
+ val_[2] += vector[2];
+
+ return *this;
+ }
+
+ /**
+ * \brief Sets the value of this three-dimensional vector to the vector difference of itself with the specified three-dimensional vector.
+ * \param vector The three-dimensional vector with which the vector difference should be computed.
+ * \return A reference to this three-dimensional vector.
+ */
+ RVO_API inline Vector3 &operator-=(const Vector3 &vector)
+ {
+ val_[0] -= vector[0];
+ val_[1] -= vector[1];
+ val_[2] -= vector[2];
+
+ return *this;
+ }
+
+ private:
+ float val_[3];
+ };
+
+
+ /**
+ * \relates Vector3
+ * \brief Computes the scalar multiplication of the specified three-dimensional vector with the specified scalar value.
+ * \param scalar The scalar value with which the scalar multiplication should be computed.
+ * \param vector The three-dimensional vector with which the scalar multiplication should be computed.
+ * \return The scalar multiplication of the three-dimensional vector with the scalar value.
+ */
+ inline Vector3 operator*(float scalar, const Vector3 &vector)
+ {
+ return Vector3(scalar * vector[0], scalar * vector[1], scalar * vector[2]);
+ }
+
+ /**
+ * \relates Vector3
+ * \brief Computes the cross product of the specified three-dimensional vectors.
+ * \param vector1 The first vector with which the cross product should be computed.
+ * \param vector2 The second vector with which the cross product should be computed.
+ * \return The cross product of the two specified vectors.
+ */
+ inline Vector3 cross(const Vector3 &vector1, const Vector3 &vector2)
+ {
+ return Vector3(vector1[1] * vector2[2] - vector1[2] * vector2[1], vector1[2] * vector2[0] - vector1[0] * vector2[2], vector1[0] * vector2[1] - vector1[1] * vector2[0]);
+ }
+
+ /**
+ * \relates Vector3
+ * \brief Inserts the specified three-dimensional vector into the specified output stream.
+ * \param os The output stream into which the three-dimensional vector should be inserted.
+ * \param vector The three-dimensional vector which to insert into the output stream.
+ * \return A reference to the output stream.
+ */
+ inline std::ostream &operator<<(std::ostream &os, const Vector3 &vector)
+ {
+ os << "(" << vector[0] << "," << vector[1] << "," << vector[2] << ")";
+
+ return os;
+ }
+
+ /**
+ * \relates Vector3
+ * \brief Computes the length of a specified three-dimensional vector.
+ * \param vector The three-dimensional vector whose length is to be computed.
+ * \return The length of the three-dimensional vector.
+ */
+ inline float abs(const Vector3 &vector)
+ {
+ return std::sqrt(vector * vector);
+ }
+
+ /**
+ * \relates Vector3
+ * \brief Computes the squared length of a specified three-dimensional vector.
+ * \param vector The three-dimensional vector whose squared length is to be computed.
+ * \return The squared length of the three-dimensional vector.
+ */
+ inline float absSq(const Vector3 &vector)
+ {
+ return vector * vector;
+ }
+
+ /**
+ * \relates Vector3
+ * \brief Computes the normalization of the specified three-dimensional vector.
+ * \param vector The three-dimensional vector whose normalization is to be computed.
+ * \return The normalization of the three-dimensional vector.
+ */
+ inline Vector3 normalize(const Vector3 &vector)
+ {
+ return vector / abs(vector);
+ }
+}
+
+#endif
diff --git a/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h b/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h
new file mode 100644
index 0000000000..a61a2d2935
--- /dev/null
+++ b/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h
@@ -0,0 +1,1077 @@
+/*
+** Copyright (c) 2014-2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and/or associated documentation files (the "Materials"),
+** to deal in the Materials without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute, sublicense,
+** and/or sell copies of the Materials, and to permit persons to whom the
+** Materials are furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Materials.
+**
+** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+** IN THE MATERIALS.
+*/
+
+/*
+** This header is automatically generated by the same tool that creates
+** the Binary Section of the SPIR-V specification.
+*/
+
+/*
+** Enumeration tokens for SPIR-V, in various styles:
+** C, C++, C++11, JSON, Lua, Python
+**
+** - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
+** - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
+** - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
+** - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
+** - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
+**
+** Some tokens act like mask values, which can be OR'd together,
+** while others are mutually exclusive. The mask-like ones have
+** "Mask" in their name, and a parallel enum that has the shift
+** amount (1 << x) for each corresponding enumerant.
+*/
+
+#ifndef spirv_H
+#define spirv_H
+
+typedef unsigned int SpvId;
+
+#define SPV_VERSION 0x10300
+#define SPV_REVISION 1
+
+static const unsigned int SpvMagicNumber = 0x07230203;
+static const unsigned int SpvVersion = 0x00010300;
+static const unsigned int SpvRevision = 1;
+static const unsigned int SpvOpCodeMask = 0xffff;
+static const unsigned int SpvWordCountShift = 16;
+
+typedef enum SpvSourceLanguage_ {
+ SpvSourceLanguageUnknown = 0,
+ SpvSourceLanguageESSL = 1,
+ SpvSourceLanguageGLSL = 2,
+ SpvSourceLanguageOpenCL_C = 3,
+ SpvSourceLanguageOpenCL_CPP = 4,
+ SpvSourceLanguageHLSL = 5,
+ SpvSourceLanguageMax = 0x7fffffff,
+} SpvSourceLanguage;
+
+typedef enum SpvExecutionModel_ {
+ SpvExecutionModelVertex = 0,
+ SpvExecutionModelTessellationControl = 1,
+ SpvExecutionModelTessellationEvaluation = 2,
+ SpvExecutionModelGeometry = 3,
+ SpvExecutionModelFragment = 4,
+ SpvExecutionModelGLCompute = 5,
+ SpvExecutionModelKernel = 6,
+ SpvExecutionModelMax = 0x7fffffff,
+} SpvExecutionModel;
+
+typedef enum SpvAddressingModel_ {
+ SpvAddressingModelLogical = 0,
+ SpvAddressingModelPhysical32 = 1,
+ SpvAddressingModelPhysical64 = 2,
+ SpvAddressingModelMax = 0x7fffffff,
+} SpvAddressingModel;
+
+typedef enum SpvMemoryModel_ {
+ SpvMemoryModelSimple = 0,
+ SpvMemoryModelGLSL450 = 1,
+ SpvMemoryModelOpenCL = 2,
+ SpvMemoryModelMax = 0x7fffffff,
+} SpvMemoryModel;
+
+typedef enum SpvExecutionMode_ {
+ SpvExecutionModeInvocations = 0,
+ SpvExecutionModeSpacingEqual = 1,
+ SpvExecutionModeSpacingFractionalEven = 2,
+ SpvExecutionModeSpacingFractionalOdd = 3,
+ SpvExecutionModeVertexOrderCw = 4,
+ SpvExecutionModeVertexOrderCcw = 5,
+ SpvExecutionModePixelCenterInteger = 6,
+ SpvExecutionModeOriginUpperLeft = 7,
+ SpvExecutionModeOriginLowerLeft = 8,
+ SpvExecutionModeEarlyFragmentTests = 9,
+ SpvExecutionModePointMode = 10,
+ SpvExecutionModeXfb = 11,
+ SpvExecutionModeDepthReplacing = 12,
+ SpvExecutionModeDepthGreater = 14,
+ SpvExecutionModeDepthLess = 15,
+ SpvExecutionModeDepthUnchanged = 16,
+ SpvExecutionModeLocalSize = 17,
+ SpvExecutionModeLocalSizeHint = 18,
+ SpvExecutionModeInputPoints = 19,
+ SpvExecutionModeInputLines = 20,
+ SpvExecutionModeInputLinesAdjacency = 21,
+ SpvExecutionModeTriangles = 22,
+ SpvExecutionModeInputTrianglesAdjacency = 23,
+ SpvExecutionModeQuads = 24,
+ SpvExecutionModeIsolines = 25,
+ SpvExecutionModeOutputVertices = 26,
+ SpvExecutionModeOutputPoints = 27,
+ SpvExecutionModeOutputLineStrip = 28,
+ SpvExecutionModeOutputTriangleStrip = 29,
+ SpvExecutionModeVecTypeHint = 30,
+ SpvExecutionModeContractionOff = 31,
+ SpvExecutionModeInitializer = 33,
+ SpvExecutionModeFinalizer = 34,
+ SpvExecutionModeSubgroupSize = 35,
+ SpvExecutionModeSubgroupsPerWorkgroup = 36,
+ SpvExecutionModeSubgroupsPerWorkgroupId = 37,
+ SpvExecutionModeLocalSizeId = 38,
+ SpvExecutionModeLocalSizeHintId = 39,
+ SpvExecutionModePostDepthCoverage = 4446,
+ SpvExecutionModeStencilRefReplacingEXT = 5027,
+ SpvExecutionModeMax = 0x7fffffff,
+} SpvExecutionMode;
+
+typedef enum SpvStorageClass_ {
+ SpvStorageClassUniformConstant = 0,
+ SpvStorageClassInput = 1,
+ SpvStorageClassUniform = 2,
+ SpvStorageClassOutput = 3,
+ SpvStorageClassWorkgroup = 4,
+ SpvStorageClassCrossWorkgroup = 5,
+ SpvStorageClassPrivate = 6,
+ SpvStorageClassFunction = 7,
+ SpvStorageClassGeneric = 8,
+ SpvStorageClassPushConstant = 9,
+ SpvStorageClassAtomicCounter = 10,
+ SpvStorageClassImage = 11,
+ SpvStorageClassStorageBuffer = 12,
+ SpvStorageClassMax = 0x7fffffff,
+} SpvStorageClass;
+
+typedef enum SpvDim_ {
+ SpvDim1D = 0,
+ SpvDim2D = 1,
+ SpvDim3D = 2,
+ SpvDimCube = 3,
+ SpvDimRect = 4,
+ SpvDimBuffer = 5,
+ SpvDimSubpassData = 6,
+ SpvDimMax = 0x7fffffff,
+} SpvDim;
+
+typedef enum SpvSamplerAddressingMode_ {
+ SpvSamplerAddressingModeNone = 0,
+ SpvSamplerAddressingModeClampToEdge = 1,
+ SpvSamplerAddressingModeClamp = 2,
+ SpvSamplerAddressingModeRepeat = 3,
+ SpvSamplerAddressingModeRepeatMirrored = 4,
+ SpvSamplerAddressingModeMax = 0x7fffffff,
+} SpvSamplerAddressingMode;
+
+typedef enum SpvSamplerFilterMode_ {
+ SpvSamplerFilterModeNearest = 0,
+ SpvSamplerFilterModeLinear = 1,
+ SpvSamplerFilterModeMax = 0x7fffffff,
+} SpvSamplerFilterMode;
+
+typedef enum SpvImageFormat_ {
+ SpvImageFormatUnknown = 0,
+ SpvImageFormatRgba32f = 1,
+ SpvImageFormatRgba16f = 2,
+ SpvImageFormatR32f = 3,
+ SpvImageFormatRgba8 = 4,
+ SpvImageFormatRgba8Snorm = 5,
+ SpvImageFormatRg32f = 6,
+ SpvImageFormatRg16f = 7,
+ SpvImageFormatR11fG11fB10f = 8,
+ SpvImageFormatR16f = 9,
+ SpvImageFormatRgba16 = 10,
+ SpvImageFormatRgb10A2 = 11,
+ SpvImageFormatRg16 = 12,
+ SpvImageFormatRg8 = 13,
+ SpvImageFormatR16 = 14,
+ SpvImageFormatR8 = 15,
+ SpvImageFormatRgba16Snorm = 16,
+ SpvImageFormatRg16Snorm = 17,
+ SpvImageFormatRg8Snorm = 18,
+ SpvImageFormatR16Snorm = 19,
+ SpvImageFormatR8Snorm = 20,
+ SpvImageFormatRgba32i = 21,
+ SpvImageFormatRgba16i = 22,
+ SpvImageFormatRgba8i = 23,
+ SpvImageFormatR32i = 24,
+ SpvImageFormatRg32i = 25,
+ SpvImageFormatRg16i = 26,
+ SpvImageFormatRg8i = 27,
+ SpvImageFormatR16i = 28,
+ SpvImageFormatR8i = 29,
+ SpvImageFormatRgba32ui = 30,
+ SpvImageFormatRgba16ui = 31,
+ SpvImageFormatRgba8ui = 32,
+ SpvImageFormatR32ui = 33,
+ SpvImageFormatRgb10a2ui = 34,
+ SpvImageFormatRg32ui = 35,
+ SpvImageFormatRg16ui = 36,
+ SpvImageFormatRg8ui = 37,
+ SpvImageFormatR16ui = 38,
+ SpvImageFormatR8ui = 39,
+ SpvImageFormatMax = 0x7fffffff,
+} SpvImageFormat;
+
+typedef enum SpvImageChannelOrder_ {
+ SpvImageChannelOrderR = 0,
+ SpvImageChannelOrderA = 1,
+ SpvImageChannelOrderRG = 2,
+ SpvImageChannelOrderRA = 3,
+ SpvImageChannelOrderRGB = 4,
+ SpvImageChannelOrderRGBA = 5,
+ SpvImageChannelOrderBGRA = 6,
+ SpvImageChannelOrderARGB = 7,
+ SpvImageChannelOrderIntensity = 8,
+ SpvImageChannelOrderLuminance = 9,
+ SpvImageChannelOrderRx = 10,
+ SpvImageChannelOrderRGx = 11,
+ SpvImageChannelOrderRGBx = 12,
+ SpvImageChannelOrderDepth = 13,
+ SpvImageChannelOrderDepthStencil = 14,
+ SpvImageChannelOrdersRGB = 15,
+ SpvImageChannelOrdersRGBx = 16,
+ SpvImageChannelOrdersRGBA = 17,
+ SpvImageChannelOrdersBGRA = 18,
+ SpvImageChannelOrderABGR = 19,
+ SpvImageChannelOrderMax = 0x7fffffff,
+} SpvImageChannelOrder;
+
+typedef enum SpvImageChannelDataType_ {
+ SpvImageChannelDataTypeSnormInt8 = 0,
+ SpvImageChannelDataTypeSnormInt16 = 1,
+ SpvImageChannelDataTypeUnormInt8 = 2,
+ SpvImageChannelDataTypeUnormInt16 = 3,
+ SpvImageChannelDataTypeUnormShort565 = 4,
+ SpvImageChannelDataTypeUnormShort555 = 5,
+ SpvImageChannelDataTypeUnormInt101010 = 6,
+ SpvImageChannelDataTypeSignedInt8 = 7,
+ SpvImageChannelDataTypeSignedInt16 = 8,
+ SpvImageChannelDataTypeSignedInt32 = 9,
+ SpvImageChannelDataTypeUnsignedInt8 = 10,
+ SpvImageChannelDataTypeUnsignedInt16 = 11,
+ SpvImageChannelDataTypeUnsignedInt32 = 12,
+ SpvImageChannelDataTypeHalfFloat = 13,
+ SpvImageChannelDataTypeFloat = 14,
+ SpvImageChannelDataTypeUnormInt24 = 15,
+ SpvImageChannelDataTypeUnormInt101010_2 = 16,
+ SpvImageChannelDataTypeMax = 0x7fffffff,
+} SpvImageChannelDataType;
+
+typedef enum SpvImageOperandsShift_ {
+ SpvImageOperandsBiasShift = 0,
+ SpvImageOperandsLodShift = 1,
+ SpvImageOperandsGradShift = 2,
+ SpvImageOperandsConstOffsetShift = 3,
+ SpvImageOperandsOffsetShift = 4,
+ SpvImageOperandsConstOffsetsShift = 5,
+ SpvImageOperandsSampleShift = 6,
+ SpvImageOperandsMinLodShift = 7,
+ SpvImageOperandsMax = 0x7fffffff,
+} SpvImageOperandsShift;
+
+typedef enum SpvImageOperandsMask_ {
+ SpvImageOperandsMaskNone = 0,
+ SpvImageOperandsBiasMask = 0x00000001,
+ SpvImageOperandsLodMask = 0x00000002,
+ SpvImageOperandsGradMask = 0x00000004,
+ SpvImageOperandsConstOffsetMask = 0x00000008,
+ SpvImageOperandsOffsetMask = 0x00000010,
+ SpvImageOperandsConstOffsetsMask = 0x00000020,
+ SpvImageOperandsSampleMask = 0x00000040,
+ SpvImageOperandsMinLodMask = 0x00000080,
+} SpvImageOperandsMask;
+
+typedef enum SpvFPFastMathModeShift_ {
+ SpvFPFastMathModeNotNaNShift = 0,
+ SpvFPFastMathModeNotInfShift = 1,
+ SpvFPFastMathModeNSZShift = 2,
+ SpvFPFastMathModeAllowRecipShift = 3,
+ SpvFPFastMathModeFastShift = 4,
+ SpvFPFastMathModeMax = 0x7fffffff,
+} SpvFPFastMathModeShift;
+
+typedef enum SpvFPFastMathModeMask_ {
+ SpvFPFastMathModeMaskNone = 0,
+ SpvFPFastMathModeNotNaNMask = 0x00000001,
+ SpvFPFastMathModeNotInfMask = 0x00000002,
+ SpvFPFastMathModeNSZMask = 0x00000004,
+ SpvFPFastMathModeAllowRecipMask = 0x00000008,
+ SpvFPFastMathModeFastMask = 0x00000010,
+} SpvFPFastMathModeMask;
+
+typedef enum SpvFPRoundingMode_ {
+ SpvFPRoundingModeRTE = 0,
+ SpvFPRoundingModeRTZ = 1,
+ SpvFPRoundingModeRTP = 2,
+ SpvFPRoundingModeRTN = 3,
+ SpvFPRoundingModeMax = 0x7fffffff,
+} SpvFPRoundingMode;
+
+typedef enum SpvLinkageType_ {
+ SpvLinkageTypeExport = 0,
+ SpvLinkageTypeImport = 1,
+ SpvLinkageTypeMax = 0x7fffffff,
+} SpvLinkageType;
+
+typedef enum SpvAccessQualifier_ {
+ SpvAccessQualifierReadOnly = 0,
+ SpvAccessQualifierWriteOnly = 1,
+ SpvAccessQualifierReadWrite = 2,
+ SpvAccessQualifierMax = 0x7fffffff,
+} SpvAccessQualifier;
+
+typedef enum SpvFunctionParameterAttribute_ {
+ SpvFunctionParameterAttributeZext = 0,
+ SpvFunctionParameterAttributeSext = 1,
+ SpvFunctionParameterAttributeByVal = 2,
+ SpvFunctionParameterAttributeSret = 3,
+ SpvFunctionParameterAttributeNoAlias = 4,
+ SpvFunctionParameterAttributeNoCapture = 5,
+ SpvFunctionParameterAttributeNoWrite = 6,
+ SpvFunctionParameterAttributeNoReadWrite = 7,
+ SpvFunctionParameterAttributeMax = 0x7fffffff,
+} SpvFunctionParameterAttribute;
+
+typedef enum SpvDecoration_ {
+ SpvDecorationRelaxedPrecision = 0,
+ SpvDecorationSpecId = 1,
+ SpvDecorationBlock = 2,
+ SpvDecorationBufferBlock = 3,
+ SpvDecorationRowMajor = 4,
+ SpvDecorationColMajor = 5,
+ SpvDecorationArrayStride = 6,
+ SpvDecorationMatrixStride = 7,
+ SpvDecorationGLSLShared = 8,
+ SpvDecorationGLSLPacked = 9,
+ SpvDecorationCPacked = 10,
+ SpvDecorationBuiltIn = 11,
+ SpvDecorationNoPerspective = 13,
+ SpvDecorationFlat = 14,
+ SpvDecorationPatch = 15,
+ SpvDecorationCentroid = 16,
+ SpvDecorationSample = 17,
+ SpvDecorationInvariant = 18,
+ SpvDecorationRestrict = 19,
+ SpvDecorationAliased = 20,
+ SpvDecorationVolatile = 21,
+ SpvDecorationConstant = 22,
+ SpvDecorationCoherent = 23,
+ SpvDecorationNonWritable = 24,
+ SpvDecorationNonReadable = 25,
+ SpvDecorationUniform = 26,
+ SpvDecorationSaturatedConversion = 28,
+ SpvDecorationStream = 29,
+ SpvDecorationLocation = 30,
+ SpvDecorationComponent = 31,
+ SpvDecorationIndex = 32,
+ SpvDecorationBinding = 33,
+ SpvDecorationDescriptorSet = 34,
+ SpvDecorationOffset = 35,
+ SpvDecorationXfbBuffer = 36,
+ SpvDecorationXfbStride = 37,
+ SpvDecorationFuncParamAttr = 38,
+ SpvDecorationFPRoundingMode = 39,
+ SpvDecorationFPFastMathMode = 40,
+ SpvDecorationLinkageAttributes = 41,
+ SpvDecorationNoContraction = 42,
+ SpvDecorationInputAttachmentIndex = 43,
+ SpvDecorationAlignment = 44,
+ SpvDecorationMaxByteOffset = 45,
+ SpvDecorationAlignmentId = 46,
+ SpvDecorationMaxByteOffsetId = 47,
+ SpvDecorationExplicitInterpAMD = 4999,
+ SpvDecorationOverrideCoverageNV = 5248,
+ SpvDecorationPassthroughNV = 5250,
+ SpvDecorationViewportRelativeNV = 5252,
+ SpvDecorationSecondaryViewportRelativeNV = 5256,
+ SpvDecorationHlslCounterBufferGOOGLE = 5634,
+ SpvDecorationHlslSemanticGOOGLE = 5635,
+ SpvDecorationMax = 0x7fffffff,
+} SpvDecoration;
+
+typedef enum SpvBuiltIn_ {
+ SpvBuiltInPosition = 0,
+ SpvBuiltInPointSize = 1,
+ SpvBuiltInClipDistance = 3,
+ SpvBuiltInCullDistance = 4,
+ SpvBuiltInVertexId = 5,
+ SpvBuiltInInstanceId = 6,
+ SpvBuiltInPrimitiveId = 7,
+ SpvBuiltInInvocationId = 8,
+ SpvBuiltInLayer = 9,
+ SpvBuiltInViewportIndex = 10,
+ SpvBuiltInTessLevelOuter = 11,
+ SpvBuiltInTessLevelInner = 12,
+ SpvBuiltInTessCoord = 13,
+ SpvBuiltInPatchVertices = 14,
+ SpvBuiltInFragCoord = 15,
+ SpvBuiltInPointCoord = 16,
+ SpvBuiltInFrontFacing = 17,
+ SpvBuiltInSampleId = 18,
+ SpvBuiltInSamplePosition = 19,
+ SpvBuiltInSampleMask = 20,
+ SpvBuiltInFragDepth = 22,
+ SpvBuiltInHelperInvocation = 23,
+ SpvBuiltInNumWorkgroups = 24,
+ SpvBuiltInWorkgroupSize = 25,
+ SpvBuiltInWorkgroupId = 26,
+ SpvBuiltInLocalInvocationId = 27,
+ SpvBuiltInGlobalInvocationId = 28,
+ SpvBuiltInLocalInvocationIndex = 29,
+ SpvBuiltInWorkDim = 30,
+ SpvBuiltInGlobalSize = 31,
+ SpvBuiltInEnqueuedWorkgroupSize = 32,
+ SpvBuiltInGlobalOffset = 33,
+ SpvBuiltInGlobalLinearId = 34,
+ SpvBuiltInSubgroupSize = 36,
+ SpvBuiltInSubgroupMaxSize = 37,
+ SpvBuiltInNumSubgroups = 38,
+ SpvBuiltInNumEnqueuedSubgroups = 39,
+ SpvBuiltInSubgroupId = 40,
+ SpvBuiltInSubgroupLocalInvocationId = 41,
+ SpvBuiltInVertexIndex = 42,
+ SpvBuiltInInstanceIndex = 43,
+ SpvBuiltInSubgroupEqMask = 4416,
+ SpvBuiltInSubgroupEqMaskKHR = 4416,
+ SpvBuiltInSubgroupGeMask = 4417,
+ SpvBuiltInSubgroupGeMaskKHR = 4417,
+ SpvBuiltInSubgroupGtMask = 4418,
+ SpvBuiltInSubgroupGtMaskKHR = 4418,
+ SpvBuiltInSubgroupLeMask = 4419,
+ SpvBuiltInSubgroupLeMaskKHR = 4419,
+ SpvBuiltInSubgroupLtMask = 4420,
+ SpvBuiltInSubgroupLtMaskKHR = 4420,
+ SpvBuiltInBaseVertex = 4424,
+ SpvBuiltInBaseInstance = 4425,
+ SpvBuiltInDrawIndex = 4426,
+ SpvBuiltInDeviceIndex = 4438,
+ SpvBuiltInViewIndex = 4440,
+ SpvBuiltInBaryCoordNoPerspAMD = 4992,
+ SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993,
+ SpvBuiltInBaryCoordNoPerspSampleAMD = 4994,
+ SpvBuiltInBaryCoordSmoothAMD = 4995,
+ SpvBuiltInBaryCoordSmoothCentroidAMD = 4996,
+ SpvBuiltInBaryCoordSmoothSampleAMD = 4997,
+ SpvBuiltInBaryCoordPullModelAMD = 4998,
+ SpvBuiltInFragStencilRefEXT = 5014,
+ SpvBuiltInViewportMaskNV = 5253,
+ SpvBuiltInSecondaryPositionNV = 5257,
+ SpvBuiltInSecondaryViewportMaskNV = 5258,
+ SpvBuiltInPositionPerViewNV = 5261,
+ SpvBuiltInViewportMaskPerViewNV = 5262,
+ SpvBuiltInFullyCoveredEXT = 5264,
+ SpvBuiltInMax = 0x7fffffff,
+} SpvBuiltIn;
+
+typedef enum SpvSelectionControlShift_ {
+ SpvSelectionControlFlattenShift = 0,
+ SpvSelectionControlDontFlattenShift = 1,
+ SpvSelectionControlMax = 0x7fffffff,
+} SpvSelectionControlShift;
+
+typedef enum SpvSelectionControlMask_ {
+ SpvSelectionControlMaskNone = 0,
+ SpvSelectionControlFlattenMask = 0x00000001,
+ SpvSelectionControlDontFlattenMask = 0x00000002,
+} SpvSelectionControlMask;
+
+typedef enum SpvLoopControlShift_ {
+ SpvLoopControlUnrollShift = 0,
+ SpvLoopControlDontUnrollShift = 1,
+ SpvLoopControlDependencyInfiniteShift = 2,
+ SpvLoopControlDependencyLengthShift = 3,
+ SpvLoopControlMax = 0x7fffffff,
+} SpvLoopControlShift;
+
+typedef enum SpvLoopControlMask_ {
+ SpvLoopControlMaskNone = 0,
+ SpvLoopControlUnrollMask = 0x00000001,
+ SpvLoopControlDontUnrollMask = 0x00000002,
+ SpvLoopControlDependencyInfiniteMask = 0x00000004,
+ SpvLoopControlDependencyLengthMask = 0x00000008,
+} SpvLoopControlMask;
+
+typedef enum SpvFunctionControlShift_ {
+ SpvFunctionControlInlineShift = 0,
+ SpvFunctionControlDontInlineShift = 1,
+ SpvFunctionControlPureShift = 2,
+ SpvFunctionControlConstShift = 3,
+ SpvFunctionControlMax = 0x7fffffff,
+} SpvFunctionControlShift;
+
+typedef enum SpvFunctionControlMask_ {
+ SpvFunctionControlMaskNone = 0,
+ SpvFunctionControlInlineMask = 0x00000001,
+ SpvFunctionControlDontInlineMask = 0x00000002,
+ SpvFunctionControlPureMask = 0x00000004,
+ SpvFunctionControlConstMask = 0x00000008,
+} SpvFunctionControlMask;
+
+typedef enum SpvMemorySemanticsShift_ {
+ SpvMemorySemanticsAcquireShift = 1,
+ SpvMemorySemanticsReleaseShift = 2,
+ SpvMemorySemanticsAcquireReleaseShift = 3,
+ SpvMemorySemanticsSequentiallyConsistentShift = 4,
+ SpvMemorySemanticsUniformMemoryShift = 6,
+ SpvMemorySemanticsSubgroupMemoryShift = 7,
+ SpvMemorySemanticsWorkgroupMemoryShift = 8,
+ SpvMemorySemanticsCrossWorkgroupMemoryShift = 9,
+ SpvMemorySemanticsAtomicCounterMemoryShift = 10,
+ SpvMemorySemanticsImageMemoryShift = 11,
+ SpvMemorySemanticsMax = 0x7fffffff,
+} SpvMemorySemanticsShift;
+
+typedef enum SpvMemorySemanticsMask_ {
+ SpvMemorySemanticsMaskNone = 0,
+ SpvMemorySemanticsAcquireMask = 0x00000002,
+ SpvMemorySemanticsReleaseMask = 0x00000004,
+ SpvMemorySemanticsAcquireReleaseMask = 0x00000008,
+ SpvMemorySemanticsSequentiallyConsistentMask = 0x00000010,
+ SpvMemorySemanticsUniformMemoryMask = 0x00000040,
+ SpvMemorySemanticsSubgroupMemoryMask = 0x00000080,
+ SpvMemorySemanticsWorkgroupMemoryMask = 0x00000100,
+ SpvMemorySemanticsCrossWorkgroupMemoryMask = 0x00000200,
+ SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000400,
+ SpvMemorySemanticsImageMemoryMask = 0x00000800,
+} SpvMemorySemanticsMask;
+
+typedef enum SpvMemoryAccessShift_ {
+ SpvMemoryAccessVolatileShift = 0,
+ SpvMemoryAccessAlignedShift = 1,
+ SpvMemoryAccessNontemporalShift = 2,
+ SpvMemoryAccessMax = 0x7fffffff,
+} SpvMemoryAccessShift;
+
+typedef enum SpvMemoryAccessMask_ {
+ SpvMemoryAccessMaskNone = 0,
+ SpvMemoryAccessVolatileMask = 0x00000001,
+ SpvMemoryAccessAlignedMask = 0x00000002,
+ SpvMemoryAccessNontemporalMask = 0x00000004,
+} SpvMemoryAccessMask;
+
+typedef enum SpvScope_ {
+ SpvScopeCrossDevice = 0,
+ SpvScopeDevice = 1,
+ SpvScopeWorkgroup = 2,
+ SpvScopeSubgroup = 3,
+ SpvScopeInvocation = 4,
+ SpvScopeMax = 0x7fffffff,
+} SpvScope;
+
+typedef enum SpvGroupOperation_ {
+ SpvGroupOperationReduce = 0,
+ SpvGroupOperationInclusiveScan = 1,
+ SpvGroupOperationExclusiveScan = 2,
+ SpvGroupOperationClusteredReduce = 3,
+ SpvGroupOperationPartitionedReduceNV = 6,
+ SpvGroupOperationPartitionedInclusiveScanNV = 7,
+ SpvGroupOperationPartitionedExclusiveScanNV = 8,
+ SpvGroupOperationMax = 0x7fffffff,
+} SpvGroupOperation;
+
+typedef enum SpvKernelEnqueueFlags_ {
+ SpvKernelEnqueueFlagsNoWait = 0,
+ SpvKernelEnqueueFlagsWaitKernel = 1,
+ SpvKernelEnqueueFlagsWaitWorkGroup = 2,
+ SpvKernelEnqueueFlagsMax = 0x7fffffff,
+} SpvKernelEnqueueFlags;
+
+typedef enum SpvKernelProfilingInfoShift_ {
+ SpvKernelProfilingInfoCmdExecTimeShift = 0,
+ SpvKernelProfilingInfoMax = 0x7fffffff,
+} SpvKernelProfilingInfoShift;
+
+typedef enum SpvKernelProfilingInfoMask_ {
+ SpvKernelProfilingInfoMaskNone = 0,
+ SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001,
+} SpvKernelProfilingInfoMask;
+
+typedef enum SpvCapability_ {
+ SpvCapabilityMatrix = 0,
+ SpvCapabilityShader = 1,
+ SpvCapabilityGeometry = 2,
+ SpvCapabilityTessellation = 3,
+ SpvCapabilityAddresses = 4,
+ SpvCapabilityLinkage = 5,
+ SpvCapabilityKernel = 6,
+ SpvCapabilityVector16 = 7,
+ SpvCapabilityFloat16Buffer = 8,
+ SpvCapabilityFloat16 = 9,
+ SpvCapabilityFloat64 = 10,
+ SpvCapabilityInt64 = 11,
+ SpvCapabilityInt64Atomics = 12,
+ SpvCapabilityImageBasic = 13,
+ SpvCapabilityImageReadWrite = 14,
+ SpvCapabilityImageMipmap = 15,
+ SpvCapabilityPipes = 17,
+ SpvCapabilityGroups = 18,
+ SpvCapabilityDeviceEnqueue = 19,
+ SpvCapabilityLiteralSampler = 20,
+ SpvCapabilityAtomicStorage = 21,
+ SpvCapabilityInt16 = 22,
+ SpvCapabilityTessellationPointSize = 23,
+ SpvCapabilityGeometryPointSize = 24,
+ SpvCapabilityImageGatherExtended = 25,
+ SpvCapabilityStorageImageMultisample = 27,
+ SpvCapabilityUniformBufferArrayDynamicIndexing = 28,
+ SpvCapabilitySampledImageArrayDynamicIndexing = 29,
+ SpvCapabilityStorageBufferArrayDynamicIndexing = 30,
+ SpvCapabilityStorageImageArrayDynamicIndexing = 31,
+ SpvCapabilityClipDistance = 32,
+ SpvCapabilityCullDistance = 33,
+ SpvCapabilityImageCubeArray = 34,
+ SpvCapabilitySampleRateShading = 35,
+ SpvCapabilityImageRect = 36,
+ SpvCapabilitySampledRect = 37,
+ SpvCapabilityGenericPointer = 38,
+ SpvCapabilityInt8 = 39,
+ SpvCapabilityInputAttachment = 40,
+ SpvCapabilitySparseResidency = 41,
+ SpvCapabilityMinLod = 42,
+ SpvCapabilitySampled1D = 43,
+ SpvCapabilityImage1D = 44,
+ SpvCapabilitySampledCubeArray = 45,
+ SpvCapabilitySampledBuffer = 46,
+ SpvCapabilityImageBuffer = 47,
+ SpvCapabilityImageMSArray = 48,
+ SpvCapabilityStorageImageExtendedFormats = 49,
+ SpvCapabilityImageQuery = 50,
+ SpvCapabilityDerivativeControl = 51,
+ SpvCapabilityInterpolationFunction = 52,
+ SpvCapabilityTransformFeedback = 53,
+ SpvCapabilityGeometryStreams = 54,
+ SpvCapabilityStorageImageReadWithoutFormat = 55,
+ SpvCapabilityStorageImageWriteWithoutFormat = 56,
+ SpvCapabilityMultiViewport = 57,
+ SpvCapabilitySubgroupDispatch = 58,
+ SpvCapabilityNamedBarrier = 59,
+ SpvCapabilityPipeStorage = 60,
+ SpvCapabilityGroupNonUniform = 61,
+ SpvCapabilityGroupNonUniformVote = 62,
+ SpvCapabilityGroupNonUniformArithmetic = 63,
+ SpvCapabilityGroupNonUniformBallot = 64,
+ SpvCapabilityGroupNonUniformShuffle = 65,
+ SpvCapabilityGroupNonUniformShuffleRelative = 66,
+ SpvCapabilityGroupNonUniformClustered = 67,
+ SpvCapabilityGroupNonUniformQuad = 68,
+ SpvCapabilitySubgroupBallotKHR = 4423,
+ SpvCapabilityDrawParameters = 4427,
+ SpvCapabilitySubgroupVoteKHR = 4431,
+ SpvCapabilityStorageBuffer16BitAccess = 4433,
+ SpvCapabilityStorageUniformBufferBlock16 = 4433,
+ SpvCapabilityStorageUniform16 = 4434,
+ SpvCapabilityUniformAndStorageBuffer16BitAccess = 4434,
+ SpvCapabilityStoragePushConstant16 = 4435,
+ SpvCapabilityStorageInputOutput16 = 4436,
+ SpvCapabilityDeviceGroup = 4437,
+ SpvCapabilityMultiView = 4439,
+ SpvCapabilityVariablePointersStorageBuffer = 4441,
+ SpvCapabilityVariablePointers = 4442,
+ SpvCapabilityAtomicStorageOps = 4445,
+ SpvCapabilitySampleMaskPostDepthCoverage = 4447,
+ SpvCapabilityFloat16ImageAMD = 5008,
+ SpvCapabilityImageGatherBiasLodAMD = 5009,
+ SpvCapabilityFragmentMaskAMD = 5010,
+ SpvCapabilityStencilExportEXT = 5013,
+ SpvCapabilityImageReadWriteLodAMD = 5015,
+ SpvCapabilitySampleMaskOverrideCoverageNV = 5249,
+ SpvCapabilityGeometryShaderPassthroughNV = 5251,
+ SpvCapabilityShaderViewportIndexLayerEXT = 5254,
+ SpvCapabilityShaderViewportIndexLayerNV = 5254,
+ SpvCapabilityShaderViewportMaskNV = 5255,
+ SpvCapabilityShaderStereoViewNV = 5259,
+ SpvCapabilityPerViewAttributesNV = 5260,
+ SpvCapabilityFragmentFullyCoveredEXT = 5265,
+ SpvCapabilityGroupNonUniformPartitionedNV = 5297,
+ SpvCapabilitySubgroupShuffleINTEL = 5568,
+ SpvCapabilitySubgroupBufferBlockIOINTEL = 5569,
+ SpvCapabilitySubgroupImageBlockIOINTEL = 5570,
+ SpvCapabilityMax = 0x7fffffff,
+} SpvCapability;
+
+typedef enum SpvOp_ {
+ SpvOpNop = 0,
+ SpvOpUndef = 1,
+ SpvOpSourceContinued = 2,
+ SpvOpSource = 3,
+ SpvOpSourceExtension = 4,
+ SpvOpName = 5,
+ SpvOpMemberName = 6,
+ SpvOpString = 7,
+ SpvOpLine = 8,
+ SpvOpExtension = 10,
+ SpvOpExtInstImport = 11,
+ SpvOpExtInst = 12,
+ SpvOpMemoryModel = 14,
+ SpvOpEntryPoint = 15,
+ SpvOpExecutionMode = 16,
+ SpvOpCapability = 17,
+ SpvOpTypeVoid = 19,
+ SpvOpTypeBool = 20,
+ SpvOpTypeInt = 21,
+ SpvOpTypeFloat = 22,
+ SpvOpTypeVector = 23,
+ SpvOpTypeMatrix = 24,
+ SpvOpTypeImage = 25,
+ SpvOpTypeSampler = 26,
+ SpvOpTypeSampledImage = 27,
+ SpvOpTypeArray = 28,
+ SpvOpTypeRuntimeArray = 29,
+ SpvOpTypeStruct = 30,
+ SpvOpTypeOpaque = 31,
+ SpvOpTypePointer = 32,
+ SpvOpTypeFunction = 33,
+ SpvOpTypeEvent = 34,
+ SpvOpTypeDeviceEvent = 35,
+ SpvOpTypeReserveId = 36,
+ SpvOpTypeQueue = 37,
+ SpvOpTypePipe = 38,
+ SpvOpTypeForwardPointer = 39,
+ SpvOpConstantTrue = 41,
+ SpvOpConstantFalse = 42,
+ SpvOpConstant = 43,
+ SpvOpConstantComposite = 44,
+ SpvOpConstantSampler = 45,
+ SpvOpConstantNull = 46,
+ SpvOpSpecConstantTrue = 48,
+ SpvOpSpecConstantFalse = 49,
+ SpvOpSpecConstant = 50,
+ SpvOpSpecConstantComposite = 51,
+ SpvOpSpecConstantOp = 52,
+ SpvOpFunction = 54,
+ SpvOpFunctionParameter = 55,
+ SpvOpFunctionEnd = 56,
+ SpvOpFunctionCall = 57,
+ SpvOpVariable = 59,
+ SpvOpImageTexelPointer = 60,
+ SpvOpLoad = 61,
+ SpvOpStore = 62,
+ SpvOpCopyMemory = 63,
+ SpvOpCopyMemorySized = 64,
+ SpvOpAccessChain = 65,
+ SpvOpInBoundsAccessChain = 66,
+ SpvOpPtrAccessChain = 67,
+ SpvOpArrayLength = 68,
+ SpvOpGenericPtrMemSemantics = 69,
+ SpvOpInBoundsPtrAccessChain = 70,
+ SpvOpDecorate = 71,
+ SpvOpMemberDecorate = 72,
+ SpvOpDecorationGroup = 73,
+ SpvOpGroupDecorate = 74,
+ SpvOpGroupMemberDecorate = 75,
+ SpvOpVectorExtractDynamic = 77,
+ SpvOpVectorInsertDynamic = 78,
+ SpvOpVectorShuffle = 79,
+ SpvOpCompositeConstruct = 80,
+ SpvOpCompositeExtract = 81,
+ SpvOpCompositeInsert = 82,
+ SpvOpCopyObject = 83,
+ SpvOpTranspose = 84,
+ SpvOpSampledImage = 86,
+ SpvOpImageSampleImplicitLod = 87,
+ SpvOpImageSampleExplicitLod = 88,
+ SpvOpImageSampleDrefImplicitLod = 89,
+ SpvOpImageSampleDrefExplicitLod = 90,
+ SpvOpImageSampleProjImplicitLod = 91,
+ SpvOpImageSampleProjExplicitLod = 92,
+ SpvOpImageSampleProjDrefImplicitLod = 93,
+ SpvOpImageSampleProjDrefExplicitLod = 94,
+ SpvOpImageFetch = 95,
+ SpvOpImageGather = 96,
+ SpvOpImageDrefGather = 97,
+ SpvOpImageRead = 98,
+ SpvOpImageWrite = 99,
+ SpvOpImage = 100,
+ SpvOpImageQueryFormat = 101,
+ SpvOpImageQueryOrder = 102,
+ SpvOpImageQuerySizeLod = 103,
+ SpvOpImageQuerySize = 104,
+ SpvOpImageQueryLod = 105,
+ SpvOpImageQueryLevels = 106,
+ SpvOpImageQuerySamples = 107,
+ SpvOpConvertFToU = 109,
+ SpvOpConvertFToS = 110,
+ SpvOpConvertSToF = 111,
+ SpvOpConvertUToF = 112,
+ SpvOpUConvert = 113,
+ SpvOpSConvert = 114,
+ SpvOpFConvert = 115,
+ SpvOpQuantizeToF16 = 116,
+ SpvOpConvertPtrToU = 117,
+ SpvOpSatConvertSToU = 118,
+ SpvOpSatConvertUToS = 119,
+ SpvOpConvertUToPtr = 120,
+ SpvOpPtrCastToGeneric = 121,
+ SpvOpGenericCastToPtr = 122,
+ SpvOpGenericCastToPtrExplicit = 123,
+ SpvOpBitcast = 124,
+ SpvOpSNegate = 126,
+ SpvOpFNegate = 127,
+ SpvOpIAdd = 128,
+ SpvOpFAdd = 129,
+ SpvOpISub = 130,
+ SpvOpFSub = 131,
+ SpvOpIMul = 132,
+ SpvOpFMul = 133,
+ SpvOpUDiv = 134,
+ SpvOpSDiv = 135,
+ SpvOpFDiv = 136,
+ SpvOpUMod = 137,
+ SpvOpSRem = 138,
+ SpvOpSMod = 139,
+ SpvOpFRem = 140,
+ SpvOpFMod = 141,
+ SpvOpVectorTimesScalar = 142,
+ SpvOpMatrixTimesScalar = 143,
+ SpvOpVectorTimesMatrix = 144,
+ SpvOpMatrixTimesVector = 145,
+ SpvOpMatrixTimesMatrix = 146,
+ SpvOpOuterProduct = 147,
+ SpvOpDot = 148,
+ SpvOpIAddCarry = 149,
+ SpvOpISubBorrow = 150,
+ SpvOpUMulExtended = 151,
+ SpvOpSMulExtended = 152,
+ SpvOpAny = 154,
+ SpvOpAll = 155,
+ SpvOpIsNan = 156,
+ SpvOpIsInf = 157,
+ SpvOpIsFinite = 158,
+ SpvOpIsNormal = 159,
+ SpvOpSignBitSet = 160,
+ SpvOpLessOrGreater = 161,
+ SpvOpOrdered = 162,
+ SpvOpUnordered = 163,
+ SpvOpLogicalEqual = 164,
+ SpvOpLogicalNotEqual = 165,
+ SpvOpLogicalOr = 166,
+ SpvOpLogicalAnd = 167,
+ SpvOpLogicalNot = 168,
+ SpvOpSelect = 169,
+ SpvOpIEqual = 170,
+ SpvOpINotEqual = 171,
+ SpvOpUGreaterThan = 172,
+ SpvOpSGreaterThan = 173,
+ SpvOpUGreaterThanEqual = 174,
+ SpvOpSGreaterThanEqual = 175,
+ SpvOpULessThan = 176,
+ SpvOpSLessThan = 177,
+ SpvOpULessThanEqual = 178,
+ SpvOpSLessThanEqual = 179,
+ SpvOpFOrdEqual = 180,
+ SpvOpFUnordEqual = 181,
+ SpvOpFOrdNotEqual = 182,
+ SpvOpFUnordNotEqual = 183,
+ SpvOpFOrdLessThan = 184,
+ SpvOpFUnordLessThan = 185,
+ SpvOpFOrdGreaterThan = 186,
+ SpvOpFUnordGreaterThan = 187,
+ SpvOpFOrdLessThanEqual = 188,
+ SpvOpFUnordLessThanEqual = 189,
+ SpvOpFOrdGreaterThanEqual = 190,
+ SpvOpFUnordGreaterThanEqual = 191,
+ SpvOpShiftRightLogical = 194,
+ SpvOpShiftRightArithmetic = 195,
+ SpvOpShiftLeftLogical = 196,
+ SpvOpBitwiseOr = 197,
+ SpvOpBitwiseXor = 198,
+ SpvOpBitwiseAnd = 199,
+ SpvOpNot = 200,
+ SpvOpBitFieldInsert = 201,
+ SpvOpBitFieldSExtract = 202,
+ SpvOpBitFieldUExtract = 203,
+ SpvOpBitReverse = 204,
+ SpvOpBitCount = 205,
+ SpvOpDPdx = 207,
+ SpvOpDPdy = 208,
+ SpvOpFwidth = 209,
+ SpvOpDPdxFine = 210,
+ SpvOpDPdyFine = 211,
+ SpvOpFwidthFine = 212,
+ SpvOpDPdxCoarse = 213,
+ SpvOpDPdyCoarse = 214,
+ SpvOpFwidthCoarse = 215,
+ SpvOpEmitVertex = 218,
+ SpvOpEndPrimitive = 219,
+ SpvOpEmitStreamVertex = 220,
+ SpvOpEndStreamPrimitive = 221,
+ SpvOpControlBarrier = 224,
+ SpvOpMemoryBarrier = 225,
+ SpvOpAtomicLoad = 227,
+ SpvOpAtomicStore = 228,
+ SpvOpAtomicExchange = 229,
+ SpvOpAtomicCompareExchange = 230,
+ SpvOpAtomicCompareExchangeWeak = 231,
+ SpvOpAtomicIIncrement = 232,
+ SpvOpAtomicIDecrement = 233,
+ SpvOpAtomicIAdd = 234,
+ SpvOpAtomicISub = 235,
+ SpvOpAtomicSMin = 236,
+ SpvOpAtomicUMin = 237,
+ SpvOpAtomicSMax = 238,
+ SpvOpAtomicUMax = 239,
+ SpvOpAtomicAnd = 240,
+ SpvOpAtomicOr = 241,
+ SpvOpAtomicXor = 242,
+ SpvOpPhi = 245,
+ SpvOpLoopMerge = 246,
+ SpvOpSelectionMerge = 247,
+ SpvOpLabel = 248,
+ SpvOpBranch = 249,
+ SpvOpBranchConditional = 250,
+ SpvOpSwitch = 251,
+ SpvOpKill = 252,
+ SpvOpReturn = 253,
+ SpvOpReturnValue = 254,
+ SpvOpUnreachable = 255,
+ SpvOpLifetimeStart = 256,
+ SpvOpLifetimeStop = 257,
+ SpvOpGroupAsyncCopy = 259,
+ SpvOpGroupWaitEvents = 260,
+ SpvOpGroupAll = 261,
+ SpvOpGroupAny = 262,
+ SpvOpGroupBroadcast = 263,
+ SpvOpGroupIAdd = 264,
+ SpvOpGroupFAdd = 265,
+ SpvOpGroupFMin = 266,
+ SpvOpGroupUMin = 267,
+ SpvOpGroupSMin = 268,
+ SpvOpGroupFMax = 269,
+ SpvOpGroupUMax = 270,
+ SpvOpGroupSMax = 271,
+ SpvOpReadPipe = 274,
+ SpvOpWritePipe = 275,
+ SpvOpReservedReadPipe = 276,
+ SpvOpReservedWritePipe = 277,
+ SpvOpReserveReadPipePackets = 278,
+ SpvOpReserveWritePipePackets = 279,
+ SpvOpCommitReadPipe = 280,
+ SpvOpCommitWritePipe = 281,
+ SpvOpIsValidReserveId = 282,
+ SpvOpGetNumPipePackets = 283,
+ SpvOpGetMaxPipePackets = 284,
+ SpvOpGroupReserveReadPipePackets = 285,
+ SpvOpGroupReserveWritePipePackets = 286,
+ SpvOpGroupCommitReadPipe = 287,
+ SpvOpGroupCommitWritePipe = 288,
+ SpvOpEnqueueMarker = 291,
+ SpvOpEnqueueKernel = 292,
+ SpvOpGetKernelNDrangeSubGroupCount = 293,
+ SpvOpGetKernelNDrangeMaxSubGroupSize = 294,
+ SpvOpGetKernelWorkGroupSize = 295,
+ SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296,
+ SpvOpRetainEvent = 297,
+ SpvOpReleaseEvent = 298,
+ SpvOpCreateUserEvent = 299,
+ SpvOpIsValidEvent = 300,
+ SpvOpSetUserEventStatus = 301,
+ SpvOpCaptureEventProfilingInfo = 302,
+ SpvOpGetDefaultQueue = 303,
+ SpvOpBuildNDRange = 304,
+ SpvOpImageSparseSampleImplicitLod = 305,
+ SpvOpImageSparseSampleExplicitLod = 306,
+ SpvOpImageSparseSampleDrefImplicitLod = 307,
+ SpvOpImageSparseSampleDrefExplicitLod = 308,
+ SpvOpImageSparseSampleProjImplicitLod = 309,
+ SpvOpImageSparseSampleProjExplicitLod = 310,
+ SpvOpImageSparseSampleProjDrefImplicitLod = 311,
+ SpvOpImageSparseSampleProjDrefExplicitLod = 312,
+ SpvOpImageSparseFetch = 313,
+ SpvOpImageSparseGather = 314,
+ SpvOpImageSparseDrefGather = 315,
+ SpvOpImageSparseTexelsResident = 316,
+ SpvOpNoLine = 317,
+ SpvOpAtomicFlagTestAndSet = 318,
+ SpvOpAtomicFlagClear = 319,
+ SpvOpImageSparseRead = 320,
+ SpvOpSizeOf = 321,
+ SpvOpTypePipeStorage = 322,
+ SpvOpConstantPipeStorage = 323,
+ SpvOpCreatePipeFromPipeStorage = 324,
+ SpvOpGetKernelLocalSizeForSubgroupCount = 325,
+ SpvOpGetKernelMaxNumSubgroups = 326,
+ SpvOpTypeNamedBarrier = 327,
+ SpvOpNamedBarrierInitialize = 328,
+ SpvOpMemoryNamedBarrier = 329,
+ SpvOpModuleProcessed = 330,
+ SpvOpExecutionModeId = 331,
+ SpvOpDecorateId = 332,
+ SpvOpGroupNonUniformElect = 333,
+ SpvOpGroupNonUniformAll = 334,
+ SpvOpGroupNonUniformAny = 335,
+ SpvOpGroupNonUniformAllEqual = 336,
+ SpvOpGroupNonUniformBroadcast = 337,
+ SpvOpGroupNonUniformBroadcastFirst = 338,
+ SpvOpGroupNonUniformBallot = 339,
+ SpvOpGroupNonUniformInverseBallot = 340,
+ SpvOpGroupNonUniformBallotBitExtract = 341,
+ SpvOpGroupNonUniformBallotBitCount = 342,
+ SpvOpGroupNonUniformBallotFindLSB = 343,
+ SpvOpGroupNonUniformBallotFindMSB = 344,
+ SpvOpGroupNonUniformShuffle = 345,
+ SpvOpGroupNonUniformShuffleXor = 346,
+ SpvOpGroupNonUniformShuffleUp = 347,
+ SpvOpGroupNonUniformShuffleDown = 348,
+ SpvOpGroupNonUniformIAdd = 349,
+ SpvOpGroupNonUniformFAdd = 350,
+ SpvOpGroupNonUniformIMul = 351,
+ SpvOpGroupNonUniformFMul = 352,
+ SpvOpGroupNonUniformSMin = 353,
+ SpvOpGroupNonUniformUMin = 354,
+ SpvOpGroupNonUniformFMin = 355,
+ SpvOpGroupNonUniformSMax = 356,
+ SpvOpGroupNonUniformUMax = 357,
+ SpvOpGroupNonUniformFMax = 358,
+ SpvOpGroupNonUniformBitwiseAnd = 359,
+ SpvOpGroupNonUniformBitwiseOr = 360,
+ SpvOpGroupNonUniformBitwiseXor = 361,
+ SpvOpGroupNonUniformLogicalAnd = 362,
+ SpvOpGroupNonUniformLogicalOr = 363,
+ SpvOpGroupNonUniformLogicalXor = 364,
+ SpvOpGroupNonUniformQuadBroadcast = 365,
+ SpvOpGroupNonUniformQuadSwap = 366,
+ SpvOpSubgroupBallotKHR = 4421,
+ SpvOpSubgroupFirstInvocationKHR = 4422,
+ SpvOpSubgroupAllKHR = 4428,
+ SpvOpSubgroupAnyKHR = 4429,
+ SpvOpSubgroupAllEqualKHR = 4430,
+ SpvOpSubgroupReadInvocationKHR = 4432,
+ SpvOpGroupIAddNonUniformAMD = 5000,
+ SpvOpGroupFAddNonUniformAMD = 5001,
+ SpvOpGroupFMinNonUniformAMD = 5002,
+ SpvOpGroupUMinNonUniformAMD = 5003,
+ SpvOpGroupSMinNonUniformAMD = 5004,
+ SpvOpGroupFMaxNonUniformAMD = 5005,
+ SpvOpGroupUMaxNonUniformAMD = 5006,
+ SpvOpGroupSMaxNonUniformAMD = 5007,
+ SpvOpFragmentMaskFetchAMD = 5011,
+ SpvOpFragmentFetchAMD = 5012,
+ SpvOpGroupNonUniformPartitionNV = 5296,
+ SpvOpSubgroupShuffleINTEL = 5571,
+ SpvOpSubgroupShuffleDownINTEL = 5572,
+ SpvOpSubgroupShuffleUpINTEL = 5573,
+ SpvOpSubgroupShuffleXorINTEL = 5574,
+ SpvOpSubgroupBlockReadINTEL = 5575,
+ SpvOpSubgroupBlockWriteINTEL = 5576,
+ SpvOpSubgroupImageBlockReadINTEL = 5577,
+ SpvOpSubgroupImageBlockWriteINTEL = 5578,
+ SpvOpDecorateStringGOOGLE = 5632,
+ SpvOpMemberDecorateStringGOOGLE = 5633,
+ SpvOpMax = 0x7fffffff,
+} SpvOp;
+
+#endif // #ifndef spirv_H
+
diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c
new file mode 100644
index 0000000000..3df963d1ae
--- /dev/null
+++ b/thirdparty/spirv-reflect/spirv_reflect.c
@@ -0,0 +1,4442 @@
+/*
+ Copyright 2017-2018 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include "spirv_reflect.h"
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+
+#if defined(WIN32)
+ #define _CRTDBG_MAP_ALLOC
+ #include <stdlib.h>
+ #include <crtdbg.h>
+#else
+ #include <stdlib.h>
+#endif
+
+// Temporary enums until these make it into SPIR-V/Vulkan
+// clang-format off
+enum {
+ SpvReflectOpDecorateId = 332,
+ SpvReflectOpDecorateStringGOOGLE = 5632,
+ SpvReflectOpMemberDecorateStringGOOGLE = 5633,
+ SpvReflectDecorationHlslCounterBufferGOOGLE = 5634,
+ SpvReflectDecorationHlslSemanticGOOGLE = 5635
+};
+// clang-format on
+
+// clang-format off
+enum {
+ SPIRV_STARTING_WORD_INDEX = 5,
+ SPIRV_WORD_SIZE = sizeof(uint32_t),
+ SPIRV_BYTE_WIDTH = 8,
+ SPIRV_MINIMUM_FILE_SIZE = SPIRV_STARTING_WORD_INDEX * SPIRV_WORD_SIZE,
+ SPIRV_DATA_ALIGNMENT = 4 * SPIRV_WORD_SIZE, // 16
+ SPIRV_ACCESS_CHAIN_INDEX_OFFSET = 4,
+};
+// clang-format on
+
+// clang-format off
+enum {
+ INVALID_VALUE = 0xFFFFFFFF,
+};
+// clang-format on
+
+// clang-format off
+enum {
+ MAX_NODE_NAME_LENGTH = 1024,
+};
+// clang-format on
+
+// clang-format off
+enum {
+ IMAGE_SAMPLED = 1,
+ IMAGE_STORAGE = 2
+};
+// clang-format on
+
+// clang-format off
+typedef struct ArrayTraits {
+ uint32_t element_type_id;
+ uint32_t length_id;
+} ArrayTraits;
+// clang-format on
+
+// clang-format off
+typedef struct ImageTraits {
+ uint32_t sampled_type_id;
+ SpvDim dim;
+ uint32_t depth;
+ uint32_t arrayed;
+ uint32_t ms;
+ uint32_t sampled;
+ SpvImageFormat image_format;
+} ImageTraits;
+// clang-format on
+
+// clang-format off
+typedef struct NumberDecoration {
+ uint32_t word_offset;
+ uint32_t value;
+} NumberDecoration;
+// clang-format on
+
+// clang-format off
+typedef struct StringDecoration {
+ uint32_t word_offset;
+ const char* value;
+} StringDecoration;
+// clang-format on
+
+// clang-format off
+typedef struct Decorations {
+ bool is_block;
+ bool is_buffer_block;
+ bool is_row_major;
+ bool is_column_major;
+ bool is_built_in;
+ bool is_noperspective;
+ bool is_flat;
+ bool is_non_writable;
+ NumberDecoration set;
+ NumberDecoration binding;
+ NumberDecoration input_attachment_index;
+ NumberDecoration location;
+ NumberDecoration offset;
+ NumberDecoration uav_counter_buffer;
+ StringDecoration semantic;
+ uint32_t array_stride;
+ uint32_t matrix_stride;
+ SpvBuiltIn built_in;
+} Decorations;
+// clang-format on
+
+// clang-format off
+typedef struct Node {
+ uint32_t result_id;
+ SpvOp op;
+ uint32_t result_type_id;
+ uint32_t type_id;
+ SpvStorageClass storage_class;
+ uint32_t word_offset;
+ uint32_t word_count;
+ bool is_type;
+
+ ArrayTraits array_traits;
+ ImageTraits image_traits;
+ uint32_t image_type_id;
+
+ const char* name;
+ Decorations decorations;
+ uint32_t member_count;
+ const char** member_names;
+ Decorations* member_decorations;
+} Node;
+// clang-format on
+
+// clang-format off
+typedef struct String {
+ uint32_t result_id;
+ const char* string;
+} String;
+// clang-format on
+
+// clang-format off
+typedef struct Function {
+ uint32_t id;
+ uint32_t callee_count;
+ uint32_t* callees;
+ struct Function** callee_ptrs;
+ uint32_t accessed_ptr_count;
+ uint32_t* accessed_ptrs;
+} Function;
+// clang-format on
+
+// clang-format off
+typedef struct AccessChain {
+ uint32_t result_id;
+ uint32_t result_type_id;
+ //
+ // Pointing to the base of a composite object.
+ // Generally the id of descriptor block variable
+ uint32_t base_id;
+ //
+ // From spec:
+ // The first index in Indexes will select the
+ // top-level member/element/component/element
+ // of the base composite
+ uint32_t index_count;
+ uint32_t* indexes;
+} AccessChain;
+// clang-format on
+
+// clang-format off
+typedef struct Parser {
+ size_t spirv_word_count;
+ uint32_t* spirv_code;
+ uint32_t string_count;
+ String* strings;
+ SpvSourceLanguage source_language;
+ uint32_t source_language_version;
+ uint32_t source_file_id;
+ String source_embedded;
+ size_t node_count;
+ Node* nodes;
+ uint32_t entry_point_count;
+ uint32_t function_count;
+ Function* functions;
+ uint32_t access_chain_count;
+ AccessChain* access_chains;
+
+ uint32_t type_count;
+ uint32_t descriptor_count;
+ uint32_t push_constant_count;
+} Parser;
+// clang-format on
+
+static uint32_t Max(uint32_t a, uint32_t b)
+{
+ return a > b ? a : b;
+}
+
+static uint32_t RoundUp(uint32_t value, uint32_t multiple)
+{
+ assert(multiple && ((multiple & (multiple - 1)) == 0));
+ return (value + multiple - 1) & ~(multiple - 1);
+}
+
+#define IsNull(ptr) \
+ (ptr == NULL)
+
+#define IsNotNull(ptr) \
+ (ptr != NULL)
+
+#define SafeFree(ptr) \
+ { \
+ if (ptr != NULL) { \
+ free((void*)ptr); \
+ ptr = NULL; \
+ } \
+ }
+
+static int SortCompareUint32(const void* a, const void* b)
+{
+ const uint32_t* p_a = (const uint32_t*)a;
+ const uint32_t* p_b = (const uint32_t*)b;
+
+ return (int)*p_a - (int)*p_b;
+}
+
+//
+// De-duplicates a sorted array and returns the new size.
+//
+// Note: The array doesn't actually need to be sorted, just
+// arranged into "runs" so that all the entries with one
+// value are adjacent.
+//
+static size_t DedupSortedUint32(uint32_t* arr, size_t size)
+{
+ if (size == 0) {
+ return 0;
+ }
+ size_t dedup_idx = 0;
+ for (size_t i = 0; i < size; ++i) {
+ if (arr[dedup_idx] != arr[i]) {
+ ++dedup_idx;
+ arr[dedup_idx] = arr[i];
+ }
+ }
+ return dedup_idx+1;
+}
+
+static bool SearchSortedUint32(const uint32_t* arr, size_t size, uint32_t target)
+{
+ size_t lo = 0;
+ size_t hi = size;
+ while (lo < hi) {
+ size_t mid = (hi - lo) / 2 + lo;
+ if (arr[mid] == target) {
+ return true;
+ } else if (arr[mid] < target) {
+ lo = mid+1;
+ } else {
+ hi = mid;
+ }
+ }
+ return false;
+}
+
+static SpvReflectResult IntersectSortedUint32(
+ const uint32_t* p_arr0,
+ size_t arr0_size,
+ const uint32_t* p_arr1,
+ size_t arr1_size,
+ uint32_t** pp_res,
+ size_t* res_size
+)
+{
+ *res_size = 0;
+ const uint32_t* arr0_end = p_arr0 + arr0_size;
+ const uint32_t* arr1_end = p_arr1 + arr1_size;
+
+ const uint32_t* idx0 = p_arr0;
+ const uint32_t* idx1 = p_arr1;
+ while (idx0 != arr0_end && idx1 != arr1_end) {
+ if (*idx0 < *idx1) {
+ ++idx0;
+ } else if (*idx0 > *idx1) {
+ ++idx1;
+ } else {
+ ++*res_size;
+ ++idx0;
+ ++idx1;
+ }
+ }
+
+ *pp_res = NULL;
+ if (*res_size > 0) {
+ *pp_res = (uint32_t*)calloc(*res_size, sizeof(**pp_res));
+ if (IsNull(*pp_res)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ uint32_t* idxr = *pp_res;
+ idx0 = p_arr0;
+ idx1 = p_arr1;
+ while (idx0 != arr0_end && idx1 != arr1_end) {
+ if (*idx0 < *idx1) {
+ ++idx0;
+ } else if (*idx0 > *idx1) {
+ ++idx1;
+ } else {
+ *(idxr++) = *idx0;
+ ++idx0;
+ ++idx1;
+ }
+ }
+ }
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+
+static bool InRange(const Parser* p_parser, uint32_t index)
+{
+ bool in_range = false;
+ if (IsNotNull(p_parser)) {
+ in_range = (index < p_parser->spirv_word_count);
+ }
+ return in_range;
+}
+
+static SpvReflectResult ReadU32(Parser* p_parser, uint32_t word_offset, uint32_t* p_value)
+{
+ assert(IsNotNull(p_parser));
+ assert(IsNotNull(p_parser->spirv_code));
+ assert(InRange(p_parser, word_offset));
+ SpvReflectResult result = SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF;
+ if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && InRange(p_parser, word_offset)) {
+ *p_value = *(p_parser->spirv_code + word_offset);
+ result = SPV_REFLECT_RESULT_SUCCESS;
+ }
+ return result;
+}
+
+#define CHECKED_READU32(parser, word_offset, value) \
+ { \
+ SpvReflectResult checked_readu32_result = ReadU32(parser, \
+ word_offset, (uint32_t*)&(value)); \
+ if (checked_readu32_result != SPV_REFLECT_RESULT_SUCCESS) { \
+ return checked_readu32_result; \
+ } \
+ }
+
+#define CHECKED_READU32_CAST(parser, word_offset, cast_to_type, value) \
+ { \
+ uint32_t checked_readu32_cast_u32 = UINT32_MAX; \
+ SpvReflectResult checked_readu32_cast_result = ReadU32(parser, \
+ word_offset, \
+ (uint32_t*)&(checked_readu32_cast_u32)); \
+ if (checked_readu32_cast_result != SPV_REFLECT_RESULT_SUCCESS) { \
+ return checked_readu32_cast_result; \
+ } \
+ value = (cast_to_type)checked_readu32_cast_u32; \
+ }
+
+#define IF_READU32(result, parser, word_offset, value) \
+ if ((result) == SPV_REFLECT_RESULT_SUCCESS) { \
+ result = ReadU32(parser, word_offset, (uint32_t*)&(value)); \
+ }
+
+#define IF_READU32_CAST(result, parser, word_offset, cast_to_type, value) \
+ if ((result) == SPV_REFLECT_RESULT_SUCCESS) { \
+ uint32_t if_readu32_cast_u32 = UINT32_MAX; \
+ result = ReadU32(parser, word_offset, &if_readu32_cast_u32); \
+ if ((result) == SPV_REFLECT_RESULT_SUCCESS) { \
+ value = (cast_to_type)if_readu32_cast_u32; \
+ } \
+ }
+
+static SpvReflectResult ReadStr(
+ Parser* p_parser,
+ uint32_t word_offset,
+ uint32_t word_index,
+ uint32_t word_count,
+ uint32_t* p_buf_size,
+ char* p_buf
+)
+{
+ uint32_t limit = (word_offset + word_count);
+ assert(IsNotNull(p_parser));
+ assert(IsNotNull(p_parser->spirv_code));
+ assert(InRange(p_parser, limit));
+ SpvReflectResult result = SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF;
+ if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && InRange(p_parser, limit)) {
+ const char* c_str = (const char*)(p_parser->spirv_code + word_offset + word_index);
+ uint32_t n = word_count * SPIRV_WORD_SIZE;
+ uint32_t length_with_terminator = 0;
+ for (uint32_t i = 0; i < n; ++i) {
+ char c = *(c_str + i);
+ if (c == 0) {
+ length_with_terminator = i + 1;
+ break;
+ }
+ }
+
+ if (length_with_terminator > 0) {
+ result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ if (IsNotNull(p_buf_size) && IsNotNull(p_buf)) {
+ result = SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED;
+ if (length_with_terminator <= *p_buf_size) {
+ memset(p_buf, 0, *p_buf_size);
+ memcpy(p_buf, c_str, length_with_terminator);
+ result = SPV_REFLECT_RESULT_SUCCESS;
+ }
+ }
+ else {
+ if (IsNotNull(p_buf_size)) {
+ *p_buf_size = length_with_terminator;
+ result = SPV_REFLECT_RESULT_SUCCESS;
+ }
+ }
+ }
+ }
+ return result;
+}
+
+static SpvReflectDecorationFlags ApplyDecorations(const Decorations* p_decoration_fields)
+{
+ SpvReflectDecorationFlags decorations = SPV_REFLECT_DECORATION_NONE;
+ if (p_decoration_fields->is_block) {
+ decorations |= SPV_REFLECT_DECORATION_BLOCK;
+ }
+ if (p_decoration_fields->is_buffer_block) {
+ decorations |= SPV_REFLECT_DECORATION_BUFFER_BLOCK;
+ }
+ if (p_decoration_fields->is_row_major) {
+ decorations |= SPV_REFLECT_DECORATION_ROW_MAJOR;
+ }
+ if (p_decoration_fields->is_column_major) {
+ decorations |= SPV_REFLECT_DECORATION_COLUMN_MAJOR;
+ }
+ if (p_decoration_fields->is_built_in) {
+ decorations |= SPV_REFLECT_DECORATION_BUILT_IN;
+ }
+ if (p_decoration_fields->is_noperspective) {
+ decorations |= SPV_REFLECT_DECORATION_NOPERSPECTIVE;
+ }
+ if (p_decoration_fields->is_flat) {
+ decorations |= SPV_REFLECT_DECORATION_FLAT;
+ }
+ if (p_decoration_fields->is_non_writable) {
+ decorations |= SPV_REFLECT_DECORATION_NON_WRITABLE;
+ }
+ return decorations;
+}
+
+static void ApplyNumericTraits(const SpvReflectTypeDescription* p_type, SpvReflectNumericTraits* p_numeric_traits)
+{
+ memcpy(p_numeric_traits, &p_type->traits.numeric, sizeof(p_type->traits.numeric));
+}
+
+static void ApplyArrayTraits(const SpvReflectTypeDescription* p_type, SpvReflectArrayTraits* p_array_traits)
+{
+ memcpy(p_array_traits, &p_type->traits.array, sizeof(p_type->traits.array));
+}
+
+static Node* FindNode(Parser* p_parser, uint32_t result_id)
+{
+ Node* p_node = NULL;
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_elem = &(p_parser->nodes[i]);
+ if (p_elem->result_id == result_id) {
+ p_node = p_elem;
+ break;
+ }
+ }
+ return p_node;
+}
+
+static SpvReflectTypeDescription* FindType(SpvReflectShaderModule* p_module, uint32_t type_id)
+{
+ SpvReflectTypeDescription* p_type = NULL;
+ for (size_t i = 0; i < p_module->_internal->type_description_count; ++i) {
+ SpvReflectTypeDescription* p_elem = &(p_module->_internal->type_descriptions[i]);
+ if (p_elem->id == type_id) {
+ p_type = p_elem;
+ break;
+ }
+ }
+ return p_type;
+}
+
+static SpvReflectResult CreateParser(size_t size, void* p_code, Parser* p_parser)
+{
+ if (p_code == NULL) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ if (size < SPIRV_MINIMUM_FILE_SIZE) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE;
+ }
+ if ((size % 4) != 0) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE;
+ }
+
+ p_parser->spirv_word_count = size / SPIRV_WORD_SIZE;
+ p_parser->spirv_code = (uint32_t*)p_code;
+
+ if (p_parser->spirv_code[0] != SpvMagicNumber) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_MAGIC_NUMBER;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static void DestroyParser(Parser* p_parser)
+{
+ if (!IsNull(p_parser->nodes)) {
+ // Free nodes
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if (IsNotNull(p_node->member_names)) {
+ SafeFree(p_node->member_names);
+ }
+ if (IsNotNull(p_node->member_decorations)) {
+ SafeFree(p_node->member_decorations);
+ }
+ }
+
+ // Free functions
+ for (size_t i = 0; i < p_parser->function_count; ++i) {
+ SafeFree(p_parser->functions[i].callees);
+ SafeFree(p_parser->functions[i].callee_ptrs);
+ SafeFree(p_parser->functions[i].accessed_ptrs);
+ }
+
+ // Free access chains
+ for (uint32_t i = 0; i < p_parser->access_chain_count; ++i) {
+ SafeFree(p_parser->access_chains[i].indexes);
+ }
+
+ SafeFree(p_parser->nodes);
+ SafeFree(p_parser->strings);
+ SafeFree(p_parser->functions);
+ SafeFree(p_parser->access_chains);
+ p_parser->node_count = 0;
+ }
+}
+
+static SpvReflectResult ParseNodes(Parser* p_parser)
+{
+ assert(IsNotNull(p_parser));
+ assert(IsNotNull(p_parser->spirv_code));
+
+ uint32_t* p_spirv = p_parser->spirv_code;
+ uint32_t spirv_word_index = SPIRV_STARTING_WORD_INDEX;
+
+ // Count nodes
+ uint32_t node_count = 0;
+ while (spirv_word_index < p_parser->spirv_word_count) {
+ uint32_t word = p_spirv[spirv_word_index];
+ SpvOp op = (SpvOp)(word & 0xFFFF);
+ uint32_t node_word_count = (word >> 16) & 0xFFFF;
+ if (node_word_count == 0) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION;
+ }
+ if (op == SpvOpAccessChain) {
+ ++(p_parser->access_chain_count);
+ }
+ spirv_word_index += node_word_count;
+ ++node_count;
+ }
+
+ if (node_count == 0) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF;
+ }
+
+ // Allocate nodes
+ p_parser->node_count = node_count;
+ p_parser->nodes = (Node*)calloc(p_parser->node_count, sizeof(*(p_parser->nodes)));
+ if (IsNull(p_parser->nodes)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ // Mark all nodes with an invalid state
+ for (uint32_t i = 0; i < node_count; ++i) {
+ p_parser->nodes[i].op = (SpvOp)INVALID_VALUE;
+ p_parser->nodes[i].storage_class = (SpvStorageClass)INVALID_VALUE;
+ p_parser->nodes[i].decorations.set.value = (uint32_t)INVALID_VALUE;
+ p_parser->nodes[i].decorations.binding.value = (uint32_t)INVALID_VALUE;
+ p_parser->nodes[i].decorations.location.value = (uint32_t)INVALID_VALUE;
+ p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE;
+ p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE;
+ p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE;
+ }
+ // Mark source file id node
+ p_parser->source_file_id = (uint32_t)INVALID_VALUE;
+
+ // Function node
+ uint32_t function_node = (uint32_t)INVALID_VALUE;
+
+ // Allocate access chain
+ if (p_parser->access_chain_count > 0) {
+ p_parser->access_chains = (AccessChain*)calloc(p_parser->access_chain_count, sizeof(*(p_parser->access_chains)));
+ if (IsNull(p_parser->access_chains)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+
+ // Parse nodes
+ uint32_t node_index = 0;
+ uint32_t access_chain_index = 0;
+ spirv_word_index = SPIRV_STARTING_WORD_INDEX;
+ while (spirv_word_index < p_parser->spirv_word_count) {
+ uint32_t word = p_spirv[spirv_word_index];
+ SpvOp op = (SpvOp)(word & 0xFFFF);
+ uint32_t node_word_count = (word >> 16) & 0xFFFF;
+
+ Node* p_node = &(p_parser->nodes[node_index]);
+ p_node->op = op;
+ p_node->word_offset = spirv_word_index;
+ p_node->word_count = node_word_count;
+
+ switch (p_node->op) {
+ default: break;
+
+ case SpvOpString: {
+ ++(p_parser->string_count);
+ }
+ break;
+
+ case SpvOpSource: {
+ CHECKED_READU32_CAST(p_parser, p_node->word_offset + 1, SpvSourceLanguage, p_parser->source_language);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_parser->source_language_version);
+ if (p_node->word_count >= 4) {
+ CHECKED_READU32(p_parser, p_node->word_offset + 3, p_parser->source_file_id);
+ }
+ }
+ break;
+
+ case SpvOpEntryPoint: {
+ ++(p_parser->entry_point_count);
+ }
+ break;
+
+ case SpvOpName:
+ case SpvOpMemberName:
+ {
+ uint32_t member_offset = (p_node->op == SpvOpMemberName) ? 1 : 0;
+ uint32_t name_start = p_node->word_offset + member_offset + 2;
+ p_node->name = (const char*)(p_parser->spirv_code + name_start);
+ }
+ break;
+
+ case SpvOpTypeStruct:
+ {
+ p_node->member_count = p_node->word_count - 2;
+ } // Fall through
+ case SpvOpTypeVoid:
+ case SpvOpTypeBool:
+ case SpvOpTypeInt:
+ case SpvOpTypeFloat:
+ case SpvOpTypeVector:
+ case SpvOpTypeMatrix:
+ case SpvOpTypeSampler:
+ case SpvOpTypeOpaque:
+ case SpvOpTypeFunction:
+ case SpvOpTypeEvent:
+ case SpvOpTypeDeviceEvent:
+ case SpvOpTypeReserveId:
+ case SpvOpTypeQueue:
+ case SpvOpTypePipe:
+ {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);
+ p_node->is_type = true;
+ }
+ break;
+
+ case SpvOpTypeImage: {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->image_traits.sampled_type_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->image_traits.dim);
+ CHECKED_READU32(p_parser, p_node->word_offset + 4, p_node->image_traits.depth);
+ CHECKED_READU32(p_parser, p_node->word_offset + 5, p_node->image_traits.arrayed);
+ CHECKED_READU32(p_parser, p_node->word_offset + 6, p_node->image_traits.ms);
+ CHECKED_READU32(p_parser, p_node->word_offset + 7, p_node->image_traits.sampled);
+ CHECKED_READU32(p_parser, p_node->word_offset + 8, p_node->image_traits.image_format);
+ p_node->is_type = true;
+ }
+ break;
+
+ case SpvOpTypeSampledImage: {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->image_type_id);
+ p_node->is_type = true;
+ }
+ break;
+
+ case SpvOpTypeArray: {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->array_traits.element_type_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->array_traits.length_id);
+ p_node->is_type = true;
+ }
+ break;
+
+ case SpvOpTypeRuntimeArray: {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->array_traits.element_type_id);
+ p_node->is_type = true;
+ }
+ break;
+
+ case SpvOpTypePointer: {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->storage_class);
+ CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->type_id);
+ p_node->is_type = true;
+ }
+ break;
+
+ case SpvOpTypeForwardPointer:
+ {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->storage_class);
+ p_node->is_type = true;
+ }
+ break;
+
+ case SpvOpConstantTrue:
+ case SpvOpConstantFalse:
+ case SpvOpConstant:
+ case SpvOpConstantComposite:
+ case SpvOpConstantSampler:
+ case SpvOpConstantNull: {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
+ }
+ break;
+
+ case SpvOpSpecConstantTrue:
+ case SpvOpSpecConstantFalse:
+ case SpvOpSpecConstant:
+ case SpvOpSpecConstantComposite:
+ case SpvOpSpecConstantOp: {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
+ }
+ break;
+
+ case SpvOpVariable:
+ {
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->type_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->storage_class);
+ }
+ break;
+
+ case SpvOpLoad:
+ {
+ // Only load enough so OpDecorate can reference the node, skip the remaining operands.
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
+ }
+ break;
+
+ case SpvOpAccessChain:
+ {
+ AccessChain* p_access_chain = &(p_parser->access_chains[access_chain_index]);
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_access_chain->result_type_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_access_chain->result_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 3, p_access_chain->base_id);
+ //
+ // SPIRV_ACCESS_CHAIN_INDEX_OFFSET (4) is the number of words up until the first index:
+ // [Node, Result Type Id, Result Id, Base Id, <Indexes>]
+ //
+ p_access_chain->index_count = (node_word_count - SPIRV_ACCESS_CHAIN_INDEX_OFFSET);
+ if (p_access_chain->index_count > 0) {
+ p_access_chain->indexes = (uint32_t*)calloc(p_access_chain->index_count, sizeof(*(p_access_chain->indexes)));
+ if (IsNull( p_access_chain->indexes)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ // Parse any index values for access chain
+ for (uint32_t index_index = 0; index_index < p_access_chain->index_count; ++index_index) {
+ // Read index id
+ uint32_t index_id = 0;
+ CHECKED_READU32(p_parser, p_node->word_offset + SPIRV_ACCESS_CHAIN_INDEX_OFFSET + index_index, index_id);
+ // Find OpConstant node that contains index value
+ Node* p_index_value_node = FindNode(p_parser, index_id);
+ if ((p_index_value_node != NULL) && (p_index_value_node->op == SpvOpConstant)) {
+ // Read index value
+ uint32_t index_value = UINT32_MAX;
+ CHECKED_READU32(p_parser, p_index_value_node->word_offset + 3, index_value);
+ assert(index_value != UINT32_MAX);
+ // Write index value to array
+ p_access_chain->indexes[index_index] = index_value;
+ }
+ }
+ }
+ ++access_chain_index;
+ }
+ break;
+
+ case SpvOpFunction:
+ {
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
+ // Count function definitions, not function declarations. To determine
+ // the difference, set an in-function variable, and then if an OpLabel
+ // is reached before the end of the function increment the function
+ // count.
+ function_node = node_index;
+ }
+ break;
+
+ case SpvOpLabel:
+ {
+ if (function_node != (uint32_t)INVALID_VALUE) {
+ Node* p_func_node = &(p_parser->nodes[function_node]);
+ CHECKED_READU32(p_parser, p_func_node->word_offset + 2, p_func_node->result_id);
+ ++(p_parser->function_count);
+ }
+ } // Fall through
+
+ case SpvOpFunctionEnd:
+ {
+ function_node = (uint32_t)INVALID_VALUE;
+ }
+ break;
+ }
+
+ if (p_node->is_type) {
+ ++(p_parser->type_count);
+ }
+
+ spirv_word_index += node_word_count;
+ ++node_index;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseStrings(Parser* p_parser)
+{
+ assert(IsNotNull(p_parser));
+ assert(IsNotNull(p_parser->spirv_code));
+ assert(IsNotNull(p_parser->nodes));
+
+ // Early out
+ if (p_parser->string_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) {
+ // Allocate string storage
+ p_parser->strings = (String*)calloc(p_parser->string_count, sizeof(*(p_parser->strings)));
+
+ uint32_t string_index = 0;
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if (p_node->op != SpvOpString) {
+ continue;
+ }
+
+ // Paranoid check against string count
+ assert(string_index < p_parser->string_count);
+ if (string_index >= p_parser->string_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+
+ // Result id
+ String* p_string = &(p_parser->strings[string_index]);
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_string->result_id);
+
+ // String
+ uint32_t string_start = p_node->word_offset + 2;
+ p_string->string = (const char*)(p_parser->spirv_code + string_start);
+
+ // Increment string index
+ ++string_index;
+ }
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseSource(Parser* p_parser, SpvReflectShaderModule* p_module)
+{
+ assert(IsNotNull(p_parser));
+ assert(IsNotNull(p_parser->spirv_code));
+
+ if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code)) {
+ // Source file
+ if (IsNotNull(p_parser->strings)) {
+ for (uint32_t i = 0; i < p_parser->string_count; ++i) {
+ String* p_string = &(p_parser->strings[i]);
+ if (p_string->result_id == p_parser->source_file_id) {
+ p_module->source_file = p_string->string;
+ break;
+ }
+ }
+ }
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseFunction(Parser* p_parser, Node* p_func_node, Function* p_func, size_t first_label_index)
+{
+ p_func->id = p_func_node->result_id;
+
+ p_func->callee_count = 0;
+ p_func->accessed_ptr_count = 0;
+
+ for (size_t i = first_label_index; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if (p_node->op == SpvOpFunctionEnd) {
+ break;
+ }
+ switch (p_node->op) {
+ case SpvOpFunctionCall: {
+ ++(p_func->callee_count);
+ }
+ break;
+ case SpvOpLoad:
+ case SpvOpAccessChain:
+ case SpvOpInBoundsAccessChain:
+ case SpvOpPtrAccessChain:
+ case SpvOpArrayLength:
+ case SpvOpGenericPtrMemSemantics:
+ case SpvOpInBoundsPtrAccessChain:
+ case SpvOpStore:
+ {
+ ++(p_func->accessed_ptr_count);
+ }
+ break;
+ case SpvOpCopyMemory:
+ case SpvOpCopyMemorySized:
+ {
+ p_func->accessed_ptr_count += 2;
+ }
+ break;
+ default: break;
+ }
+ }
+
+ if (p_func->callee_count > 0) {
+ p_func->callees = (uint32_t*)calloc(p_func->callee_count,
+ sizeof(*(p_func->callees)));
+ if (IsNull(p_func->callees)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+
+ if (p_func->accessed_ptr_count > 0) {
+ p_func->accessed_ptrs = (uint32_t*)calloc(p_func->accessed_ptr_count,
+ sizeof(*(p_func->accessed_ptrs)));
+ if (IsNull(p_func->accessed_ptrs)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+
+ p_func->callee_count = 0;
+ p_func->accessed_ptr_count = 0;
+ for (size_t i = first_label_index; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if (p_node->op == SpvOpFunctionEnd) {
+ break;
+ }
+ switch (p_node->op) {
+ case SpvOpFunctionCall: {
+ CHECKED_READU32(p_parser, p_node->word_offset + 3,
+ p_func->callees[p_func->callee_count]);
+ (++p_func->callee_count);
+ }
+ break;
+ case SpvOpLoad:
+ case SpvOpAccessChain:
+ case SpvOpInBoundsAccessChain:
+ case SpvOpPtrAccessChain:
+ case SpvOpArrayLength:
+ case SpvOpGenericPtrMemSemantics:
+ case SpvOpInBoundsPtrAccessChain:
+ {
+ CHECKED_READU32(p_parser, p_node->word_offset + 3,
+ p_func->accessed_ptrs[p_func->accessed_ptr_count]);
+ (++p_func->accessed_ptr_count);
+ }
+ break;
+ case SpvOpStore:
+ {
+ CHECKED_READU32(p_parser, p_node->word_offset + 2,
+ p_func->accessed_ptrs[p_func->accessed_ptr_count]);
+ (++p_func->accessed_ptr_count);
+ }
+ break;
+ case SpvOpCopyMemory:
+ case SpvOpCopyMemorySized:
+ {
+ CHECKED_READU32(p_parser, p_node->word_offset + 2,
+ p_func->accessed_ptrs[p_func->accessed_ptr_count]);
+ (++p_func->accessed_ptr_count);
+ CHECKED_READU32(p_parser, p_node->word_offset + 3,
+ p_func->accessed_ptrs[p_func->accessed_ptr_count]);
+ (++p_func->accessed_ptr_count);
+ }
+ break;
+ default: break;
+ }
+ }
+
+ if (p_func->callee_count > 0) {
+ qsort(p_func->callees, p_func->callee_count,
+ sizeof(*(p_func->callees)), SortCompareUint32);
+ }
+ p_func->callee_count = (uint32_t)DedupSortedUint32(p_func->callees,
+ p_func->callee_count);
+
+ if (p_func->accessed_ptr_count > 0) {
+ qsort(p_func->accessed_ptrs, p_func->accessed_ptr_count,
+ sizeof(*(p_func->accessed_ptrs)), SortCompareUint32);
+ }
+ p_func->accessed_ptr_count = (uint32_t)DedupSortedUint32(p_func->accessed_ptrs,
+ p_func->accessed_ptr_count);
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static int SortCompareFunctions(const void* a, const void* b)
+{
+ const Function* af = (const Function*)a;
+ const Function* bf = (const Function*)b;
+ return (int)af->id - (int)bf->id;
+}
+
+static SpvReflectResult ParseFunctions(Parser* p_parser)
+{
+ assert(IsNotNull(p_parser));
+ assert(IsNotNull(p_parser->spirv_code));
+ assert(IsNotNull(p_parser->nodes));
+
+ if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) {
+ if (p_parser->function_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ p_parser->functions = (Function*)calloc(p_parser->function_count,
+ sizeof(*(p_parser->functions)));
+ if (IsNull(p_parser->functions)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+
+ size_t function_index = 0;
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if (p_node->op != SpvOpFunction) {
+ continue;
+ }
+
+ // Skip over function declarations that aren't definitions
+ bool func_definition = false;
+ // Intentionally reuse i to avoid iterating over these nodes more than
+ // once
+ for (; i < p_parser->node_count; ++i) {
+ if (p_parser->nodes[i].op == SpvOpLabel) {
+ func_definition = true;
+ break;
+ }
+ if (p_parser->nodes[i].op == SpvOpFunctionEnd) {
+ break;
+ }
+ }
+ if (!func_definition) {
+ continue;
+ }
+
+ Function* p_function = &(p_parser->functions[function_index]);
+
+ SpvReflectResult result = ParseFunction(p_parser, p_node, p_function, i);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+
+ ++function_index;
+ }
+
+ qsort(p_parser->functions, p_parser->function_count,
+ sizeof(*(p_parser->functions)), SortCompareFunctions);
+
+ // Once they're sorted, link the functions with pointers to improve graph
+ // traversal efficiency
+ for (size_t i = 0; i < p_parser->function_count; ++i) {
+ Function* p_func = &(p_parser->functions[i]);
+ if (p_func->callee_count == 0) {
+ continue;
+ }
+ p_func->callee_ptrs = (Function**)calloc(p_func->callee_count,
+ sizeof(*(p_func->callee_ptrs)));
+ for (size_t j = 0, k = 0; j < p_func->callee_count; ++j) {
+ while (p_parser->functions[k].id != p_func->callees[j]) {
+ ++k;
+ if (k >= p_parser->function_count) {
+ // Invalid called function ID somewhere
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+ p_func->callee_ptrs[j] = &(p_parser->functions[k]);
+ }
+ }
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseMemberCounts(Parser* p_parser)
+{
+ assert(IsNotNull(p_parser));
+ assert(IsNotNull(p_parser->spirv_code));
+ assert(IsNotNull(p_parser->nodes));
+
+ if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) {
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if ((p_node->op != SpvOpMemberName) && (p_node->op != SpvOpMemberDecorate)) {
+ continue;
+ }
+
+ uint32_t target_id = 0;
+ uint32_t member_index = (uint32_t)INVALID_VALUE;
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, target_id);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, member_index);
+ Node* p_target_node = FindNode(p_parser, target_id);
+ // Not all nodes get parsed, so FindNode returning NULL is expected.
+ if (IsNull(p_target_node)) {
+ continue;
+ }
+
+ if (member_index == INVALID_VALUE) {
+ return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED;
+ }
+
+ p_target_node->member_count = Max(p_target_node->member_count, member_index + 1);
+ }
+
+ for (uint32_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if (p_node->member_count == 0) {
+ continue;
+ }
+
+ p_node->member_names = (const char **)calloc(p_node->member_count, sizeof(*(p_node->member_names)));
+ if (IsNull(p_node->member_names)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+
+ p_node->member_decorations = (Decorations*)calloc(p_node->member_count, sizeof(*(p_node->member_decorations)));
+ if (IsNull(p_node->member_decorations)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+ }
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseNames(Parser* p_parser)
+{
+ assert(IsNotNull(p_parser));
+ assert(IsNotNull(p_parser->spirv_code));
+ assert(IsNotNull(p_parser->nodes));
+
+ if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) {
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if ((p_node->op != SpvOpName) && (p_node->op != SpvOpMemberName)) {
+ continue;
+ }
+
+ uint32_t target_id = 0;
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, target_id);
+ Node* p_target_node = FindNode(p_parser, target_id);
+ // Not all nodes get parsed, so FindNode returning NULL is expected.
+ if (IsNull(p_target_node)) {
+ continue;
+ }
+
+ const char** pp_target_name = &(p_target_node->name);
+ if (p_node->op == SpvOpMemberName) {
+ uint32_t member_index = UINT32_MAX;
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, member_index);
+ pp_target_name = &(p_target_node->member_names[member_index]);
+ }
+
+ *pp_target_name = p_node->name;
+ }
+ }
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseDecorations(Parser* p_parser)
+{
+ for (uint32_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+
+ if (((uint32_t)p_node->op != (uint32_t)SpvOpDecorate) &&
+ ((uint32_t)p_node->op != (uint32_t)SpvOpMemberDecorate) &&
+ ((uint32_t)p_node->op != (uint32_t)SpvReflectOpDecorateId) &&
+ ((uint32_t)p_node->op != (uint32_t)SpvReflectOpDecorateStringGOOGLE) &&
+ ((uint32_t)p_node->op != (uint32_t)SpvReflectOpMemberDecorateStringGOOGLE))
+ {
+ continue;
+ }
+
+ // Need to adjust the read offset if this is a member decoration
+ uint32_t member_offset = 0;
+ if (p_node->op == SpvOpMemberDecorate) {
+ member_offset = 1;
+ }
+
+ // Get decoration
+ uint32_t decoration = (uint32_t)INVALID_VALUE;
+ CHECKED_READU32(p_parser, p_node->word_offset + member_offset + 2, decoration);
+
+ // Filter out the decoration that do not affect reflection, otherwise
+ // there will be random crashes because the nodes aren't found.
+ bool skip = false;
+ switch (decoration) {
+ default: {
+ skip = true;
+ }
+ break;
+ case SpvDecorationBlock:
+ case SpvDecorationBufferBlock:
+ case SpvDecorationColMajor:
+ case SpvDecorationRowMajor:
+ case SpvDecorationArrayStride:
+ case SpvDecorationMatrixStride:
+ case SpvDecorationBuiltIn:
+ case SpvDecorationNoPerspective:
+ case SpvDecorationFlat:
+ case SpvDecorationNonWritable:
+ case SpvDecorationLocation:
+ case SpvDecorationBinding:
+ case SpvDecorationDescriptorSet:
+ case SpvDecorationOffset:
+ case SpvDecorationInputAttachmentIndex:
+ case SpvReflectDecorationHlslCounterBufferGOOGLE:
+ case SpvReflectDecorationHlslSemanticGOOGLE: {
+ skip = false;
+ }
+ break;
+ }
+ if (skip) {
+ continue;
+ }
+
+ // Find target target node
+ uint32_t target_id = 0;
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, target_id);
+ Node* p_target_node = FindNode(p_parser, target_id);
+ if (IsNull(p_target_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ // Get decorations
+ Decorations* p_target_decorations = &(p_target_node->decorations);
+ // Update pointer if this is a member member decoration
+ if (p_node->op == SpvOpMemberDecorate) {
+ uint32_t member_index = (uint32_t)INVALID_VALUE;
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, member_index);
+ p_target_decorations = &(p_target_node->member_decorations[member_index]);
+ }
+
+ switch (decoration) {
+ default: break;
+
+ case SpvDecorationBlock: {
+ p_target_decorations->is_block = true;
+ }
+ break;
+
+ case SpvDecorationBufferBlock: {
+ p_target_decorations->is_buffer_block = true;
+ }
+ break;
+
+ case SpvDecorationColMajor: {
+ p_target_decorations->is_column_major = true;
+ }
+ break;
+
+ case SpvDecorationRowMajor: {
+ p_target_decorations->is_row_major = true;
+ }
+ break;
+
+ case SpvDecorationArrayStride: {
+ uint32_t word_offset = p_node->word_offset + member_offset + 3;
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->array_stride);
+ }
+ break;
+
+ case SpvDecorationMatrixStride: {
+ uint32_t word_offset = p_node->word_offset + member_offset + 3;
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->matrix_stride);
+ }
+ break;
+
+ case SpvDecorationBuiltIn: {
+ p_target_decorations->is_built_in = true;
+ uint32_t word_offset = p_node->word_offset + member_offset + 3;
+ CHECKED_READU32_CAST(p_parser, word_offset, SpvBuiltIn, p_target_decorations->built_in);
+ }
+ break;
+
+ case SpvDecorationNoPerspective: {
+ p_target_decorations->is_noperspective = true;
+ }
+ break;
+
+ case SpvDecorationFlat: {
+ p_target_decorations->is_flat = true;
+ }
+ break;
+
+ case SpvDecorationNonWritable: {
+ p_target_decorations->is_non_writable = true;
+ }
+ break;
+
+ case SpvDecorationLocation: {
+ uint32_t word_offset = p_node->word_offset + member_offset + 3;
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->location.value);
+ p_target_decorations->location.word_offset = word_offset;
+ }
+ break;
+
+ case SpvDecorationBinding: {
+ uint32_t word_offset = p_node->word_offset + member_offset+ 3;
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->binding.value);
+ p_target_decorations->binding.word_offset = word_offset;
+ }
+ break;
+
+ case SpvDecorationDescriptorSet: {
+ uint32_t word_offset = p_node->word_offset + member_offset+ 3;
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->set.value);
+ p_target_decorations->set.word_offset = word_offset;
+ }
+ break;
+
+ case SpvDecorationOffset: {
+ uint32_t word_offset = p_node->word_offset + member_offset+ 3;
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->offset.value);
+ p_target_decorations->offset.word_offset = word_offset;
+ }
+ break;
+
+ case SpvDecorationInputAttachmentIndex: {
+ uint32_t word_offset = p_node->word_offset + member_offset+ 3;
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->input_attachment_index.value);
+ p_target_decorations->input_attachment_index.word_offset = word_offset;
+ }
+ break;
+
+ case SpvReflectDecorationHlslCounterBufferGOOGLE: {
+ uint32_t word_offset = p_node->word_offset + member_offset+ 3;
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value);
+ p_target_decorations->uav_counter_buffer.word_offset = word_offset;
+ }
+ break;
+
+ case SpvReflectDecorationHlslSemanticGOOGLE: {
+ uint32_t word_offset = p_node->word_offset + member_offset + 3;
+ p_target_decorations->semantic.value = (const char*)(p_parser->spirv_code + word_offset);
+ p_target_decorations->semantic.word_offset = word_offset;
+ }
+ break;
+ }
+ }
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult EnumerateAllUniforms(
+ SpvReflectShaderModule* p_module,
+ size_t* p_uniform_count,
+ uint32_t** pp_uniforms
+)
+{
+ *p_uniform_count = p_module->descriptor_binding_count;
+ if (*p_uniform_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+ *pp_uniforms = (uint32_t*)calloc(*p_uniform_count, sizeof(**pp_uniforms));
+
+ if (IsNull(*pp_uniforms)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+
+ for (size_t i = 0; i < *p_uniform_count; ++i) {
+ (*pp_uniforms)[i] = p_module->descriptor_bindings[i].spirv_id;
+ }
+ qsort(*pp_uniforms, *p_uniform_count, sizeof(**pp_uniforms),
+ SortCompareUint32);
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseType(
+ Parser* p_parser,
+ Node* p_node,
+ Decorations* p_struct_member_decorations,
+ SpvReflectShaderModule* p_module,
+ SpvReflectTypeDescription* p_type
+)
+{
+ SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS;
+
+ if (p_node->member_count > 0) {
+ p_type->member_count = p_node->member_count;
+ p_type->members = (SpvReflectTypeDescription*)calloc(p_type->member_count, sizeof(*(p_type->members)));
+ if (IsNotNull(p_type->members)) {
+ // Mark all members types with an invalid state
+ for (size_t i = 0; i < p_type->members->member_count; ++i) {
+ SpvReflectTypeDescription* p_member_type = &(p_type->members[i]);
+ p_member_type->id = (uint32_t)INVALID_VALUE;
+ p_member_type->op = (SpvOp)INVALID_VALUE;
+ p_member_type->storage_class = (SpvStorageClass)INVALID_VALUE;
+ }
+ }
+ else {
+ result = SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ // Since the parse descends on type information, these will get overwritten
+ // if not guarded against assignment. Only assign if the id is invalid.
+ if (p_type->id == INVALID_VALUE) {
+ p_type->id = p_node->result_id;
+ p_type->op = p_node->op;
+ p_type->decoration_flags = 0;
+ }
+ // Top level types need to pick up decorations from all types below it.
+ // Issue and fix here: https://github.com/chaoticbob/SPIRV-Reflect/issues/64
+ p_type->decoration_flags = ApplyDecorations(&p_node->decorations);
+
+ switch (p_node->op) {
+ default: break;
+ case SpvOpTypeVoid:
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_VOID;
+ break;
+
+ case SpvOpTypeBool:
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_BOOL;
+ break;
+
+ case SpvOpTypeInt: {
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_INT;
+ IF_READU32(result, p_parser, p_node->word_offset + 2, p_type->traits.numeric.scalar.width);
+ IF_READU32(result, p_parser, p_node->word_offset + 3, p_type->traits.numeric.scalar.signedness);
+ }
+ break;
+
+ case SpvOpTypeFloat: {
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_FLOAT;
+ IF_READU32(result, p_parser, p_node->word_offset + 2, p_type->traits.numeric.scalar.width);
+ }
+ break;
+
+ case SpvOpTypeVector: {
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_VECTOR;
+ uint32_t component_type_id = (uint32_t)INVALID_VALUE;
+ IF_READU32(result, p_parser, p_node->word_offset + 2, component_type_id);
+ IF_READU32(result, p_parser, p_node->word_offset + 3, p_type->traits.numeric.vector.component_count);
+ // Parse component type
+ Node* p_next_node = FindNode(p_parser, component_type_id);
+ if (IsNotNull(p_next_node)) {
+ result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);
+ }
+ else {
+ result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+ break;
+
+ case SpvOpTypeMatrix: {
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_MATRIX;
+ uint32_t column_type_id = (uint32_t)INVALID_VALUE;
+ IF_READU32(result, p_parser, p_node->word_offset + 2, column_type_id);
+ IF_READU32(result, p_parser, p_node->word_offset + 3, p_type->traits.numeric.matrix.column_count);
+ Node* p_next_node = FindNode(p_parser, column_type_id);
+ if (IsNotNull(p_next_node)) {
+ result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);
+ }
+ else {
+ result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ p_type->traits.numeric.matrix.row_count = p_type->traits.numeric.vector.component_count;
+ p_type->traits.numeric.matrix.stride = p_node->decorations.matrix_stride;
+ // NOTE: Matrix stride is decorated using OpMemberDecoreate - not OpDecoreate.
+ if (IsNotNull(p_struct_member_decorations)) {
+ p_type->traits.numeric.matrix.stride = p_struct_member_decorations->matrix_stride;
+ }
+ }
+ break;
+
+ case SpvOpTypeImage: {
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE;
+ IF_READU32_CAST(result, p_parser, p_node->word_offset + 3, SpvDim, p_type->traits.image.dim);
+ IF_READU32(result, p_parser, p_node->word_offset + 4, p_type->traits.image.depth);
+ IF_READU32(result, p_parser, p_node->word_offset + 5, p_type->traits.image.arrayed);
+ IF_READU32(result, p_parser, p_node->word_offset + 6, p_type->traits.image.ms);
+ IF_READU32(result, p_parser, p_node->word_offset + 7, p_type->traits.image.sampled);
+ IF_READU32_CAST(result, p_parser, p_node->word_offset + 8, SpvImageFormat, p_type->traits.image.image_format);
+ }
+ break;
+
+ case SpvOpTypeSampler: {
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER;
+ }
+ break;
+
+ case SpvOpTypeSampledImage: {
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE;
+ uint32_t image_type_id = (uint32_t)INVALID_VALUE;
+ IF_READU32(result, p_parser, p_node->word_offset + 2, image_type_id);
+ Node* p_next_node = FindNode(p_parser, image_type_id);
+ if (IsNotNull(p_next_node)) {
+ result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);
+ }
+ else {
+ result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+ break;
+
+ case SpvOpTypeArray: {
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_ARRAY;
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ uint32_t element_type_id = (uint32_t)INVALID_VALUE;
+ uint32_t length_id = (uint32_t)INVALID_VALUE;
+ IF_READU32(result, p_parser, p_node->word_offset + 2, element_type_id);
+ IF_READU32(result, p_parser, p_node->word_offset + 3, length_id);
+ // NOTE: Array stride is decorated using OpDecorate instead of
+ // OpMemberDecorate, even if the array is apart of a struct.
+ p_type->traits.array.stride = p_node->decorations.array_stride;
+ // Get length for current dimension
+ Node* p_length_node = FindNode(p_parser, length_id);
+ if (IsNotNull(p_length_node)) {
+ if (p_length_node->op == SpvOpSpecConstant ||
+ p_length_node->op == SpvOpSpecConstantOp) {
+ p_type->traits.array.dims[p_type->traits.array.dims_count] = 0xFFFFFFFF;
+ p_type->traits.array.dims_count += 1;
+ } else {
+ uint32_t length = 0;
+ IF_READU32(result, p_parser, p_length_node->word_offset + 3, length);
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ // Write the array dim and increment the count and offset
+ p_type->traits.array.dims[p_type->traits.array.dims_count] = length;
+ p_type->traits.array.dims_count += 1;
+ } else {
+ result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+ // Parse next dimension or element type
+ Node* p_next_node = FindNode(p_parser, element_type_id);
+ if (IsNotNull(p_next_node)) {
+ result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);
+ }
+ }
+ else {
+ result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+ }
+ break;
+
+ case SpvOpTypeRuntimeArray: {
+ uint32_t element_type_id = (uint32_t)INVALID_VALUE;
+ IF_READU32(result, p_parser, p_node->word_offset + 2, element_type_id);
+ // Parse next dimension or element type
+ Node* p_next_node = FindNode(p_parser, element_type_id);
+ if (IsNotNull(p_next_node)) {
+ result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);
+ }
+ else {
+ result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+ break;
+
+ case SpvOpTypeStruct: {
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_STRUCT;
+ p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK;
+ uint32_t word_index = 2;
+ uint32_t member_index = 0;
+ for (; word_index < p_node->word_count; ++word_index, ++member_index) {
+ uint32_t member_id = (uint32_t)INVALID_VALUE;
+ IF_READU32(result, p_parser, p_node->word_offset + word_index, member_id);
+ // Find member node
+ Node* p_member_node = FindNode(p_parser, member_id);
+ if (IsNull(p_member_node)) {
+ result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ break;
+ }
+
+ // Member decorations
+ Decorations* p_member_decorations = &p_node->member_decorations[member_index];
+
+ assert(member_index < p_type->member_count);
+ // Parse member type
+ SpvReflectTypeDescription* p_member_type = &(p_type->members[member_index]);
+ p_member_type->id = member_id;
+ p_member_type->op = p_member_node->op;
+ result = ParseType(p_parser, p_member_node, p_member_decorations, p_module, p_member_type);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ break;
+ }
+ // This looks wrong
+ //p_member_type->type_name = p_member_node->name;
+ p_member_type->struct_member_name = p_node->member_names[member_index];
+ }
+ }
+ break;
+
+ case SpvOpTypeOpaque: break;
+
+ case SpvOpTypePointer: {
+ IF_READU32_CAST(result, p_parser, p_node->word_offset + 2, SpvStorageClass, p_type->storage_class);
+ uint32_t type_id = (uint32_t)INVALID_VALUE;
+ IF_READU32(result, p_parser, p_node->word_offset + 3, type_id);
+ // Parse type
+ Node* p_next_node = FindNode(p_parser, type_id);
+ if (IsNotNull(p_next_node)) {
+ result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);
+ }
+ else {
+ result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+ break;
+ }
+
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ // Names get assigned on the way down. Guard against names
+ // get overwritten on the way up.
+ if (IsNull(p_type->type_name)) {
+ p_type->type_name = p_node->name;
+ }
+ }
+ }
+
+ return result;
+}
+
+static SpvReflectResult ParseTypes(Parser* p_parser, SpvReflectShaderModule* p_module)
+{
+ if (p_parser->type_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ p_module->_internal->type_description_count = p_parser->type_count;
+ p_module->_internal->type_descriptions = (SpvReflectTypeDescription*)calloc(p_module->_internal->type_description_count,
+ sizeof(*(p_module->_internal->type_descriptions)));
+ if (IsNull(p_module->_internal->type_descriptions)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+
+ // Mark all types with an invalid state
+ for (size_t i = 0; i < p_module->_internal->type_description_count; ++i) {
+ SpvReflectTypeDescription* p_type = &(p_module->_internal->type_descriptions[i]);
+ p_type->id = (uint32_t)INVALID_VALUE;
+ p_type->op = (SpvOp)INVALID_VALUE;
+ p_type->storage_class = (SpvStorageClass)INVALID_VALUE;
+ }
+
+ size_t type_index = 0;
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if (! p_node->is_type) {
+ continue;
+ }
+
+ SpvReflectTypeDescription* p_type = &(p_module->_internal->type_descriptions[type_index]);
+ SpvReflectResult result = ParseType(p_parser, p_node, NULL, p_module, p_type);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ ++type_index;
+ }
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static int SortCompareDescriptorBinding(const void* a, const void* b)
+{
+ const SpvReflectDescriptorBinding* p_elem_a = (const SpvReflectDescriptorBinding*)a;
+ const SpvReflectDescriptorBinding* p_elem_b = (const SpvReflectDescriptorBinding*)b;
+ int value = (int)(p_elem_a->binding) - (int)(p_elem_b->binding);
+ if (value == 0) {
+ // use spirv-id as a tiebreaker to ensure a stable ordering, as they're guaranteed
+ // unique.
+ assert(p_elem_a->spirv_id != p_elem_b->spirv_id);
+ value = (int)(p_elem_a->spirv_id) - (int)(p_elem_b->spirv_id);
+ }
+ return value;
+}
+
+static SpvReflectResult ParseDescriptorBindings(Parser* p_parser, SpvReflectShaderModule* p_module)
+{
+ p_module->descriptor_binding_count = 0;
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if ((p_node->op != SpvOpVariable) ||
+ ((p_node->storage_class != SpvStorageClassUniform) && (p_node->storage_class != SpvStorageClassUniformConstant)))
+ {
+ continue;
+ }
+ if ((p_node->decorations.set.value == INVALID_VALUE) || (p_node->decorations.binding.value == INVALID_VALUE)) {
+ continue;
+ }
+
+ p_module->descriptor_binding_count += 1;
+ }
+
+ if (p_module->descriptor_binding_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ p_module->descriptor_bindings = (SpvReflectDescriptorBinding*)calloc(p_module->descriptor_binding_count, sizeof(*(p_module->descriptor_bindings)));
+ if (IsNull(p_module->descriptor_bindings)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+
+ // Mark all types with an invalid state
+ for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) {
+ SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]);
+ p_descriptor->binding = (uint32_t)INVALID_VALUE;
+ p_descriptor->input_attachment_index = (uint32_t)INVALID_VALUE;
+ p_descriptor->set = (uint32_t)INVALID_VALUE;
+ p_descriptor->descriptor_type = (SpvReflectDescriptorType)INVALID_VALUE;
+ p_descriptor->uav_counter_id = (uint32_t)INVALID_VALUE;
+ }
+
+ size_t descriptor_index = 0;
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if ((p_node->op != SpvOpVariable) ||
+ ((p_node->storage_class != SpvStorageClassUniform) && (p_node->storage_class != SpvStorageClassUniformConstant)))\
+ {
+ continue;
+ }
+ if ((p_node->decorations.set.value == INVALID_VALUE) || (p_node->decorations.binding.value == INVALID_VALUE)) {
+ continue;
+ }
+
+ SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id);
+ if (IsNull(p_type)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ // If the type is a pointer, resolve it
+ if (p_type->op == SpvOpTypePointer) {
+ // Find the type's node
+ Node* p_type_node = FindNode(p_parser, p_type->id);
+ if (IsNull(p_type_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ // Should be the resolved type
+ p_type = FindType(p_module, p_type_node->type_id);
+ if (IsNull(p_type)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+
+ SpvReflectDescriptorBinding* p_descriptor = &p_module->descriptor_bindings[descriptor_index];
+ p_descriptor->spirv_id = p_node->result_id;
+ p_descriptor->name = p_node->name;
+ p_descriptor->binding = p_node->decorations.binding.value;
+ p_descriptor->input_attachment_index = p_node->decorations.input_attachment_index.value;
+ p_descriptor->set = p_node->decorations.set.value;
+ p_descriptor->count = 1;
+ p_descriptor->uav_counter_id = p_node->decorations.uav_counter_buffer.value;
+ p_descriptor->type_description = p_type;
+
+ // Copy image traits
+ if ((p_type->type_flags & SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK) == SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE) {
+ memcpy(&p_descriptor->image, &p_type->traits.image, sizeof(p_descriptor->image));
+ }
+
+ // This is a workaround for: https://github.com/KhronosGroup/glslang/issues/1096
+ {
+ const uint32_t resource_mask = SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE | SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE;
+ if ((p_type->type_flags & resource_mask) == resource_mask) {
+ memcpy(&p_descriptor->image, &p_type->traits.image, sizeof(p_descriptor->image));
+ }
+ }
+
+ // Copy array traits
+ if (p_type->traits.array.dims_count > 0) {
+ p_descriptor->array.dims_count = p_type->traits.array.dims_count;
+ for (uint32_t dim_index = 0; dim_index < p_type->traits.array.dims_count; ++dim_index) {
+ uint32_t dim_value = p_type->traits.array.dims[dim_index];
+ p_descriptor->array.dims[dim_index] = dim_value;
+ p_descriptor->count *= dim_value;
+ }
+ }
+
+ // Count
+
+
+ p_descriptor->word_offset.binding = p_node->decorations.binding.word_offset;
+ p_descriptor->word_offset.set = p_node->decorations.set.word_offset;
+
+ ++descriptor_index;
+ }
+
+ if (p_module->descriptor_binding_count > 0) {
+ qsort(p_module->descriptor_bindings,
+ p_module->descriptor_binding_count,
+ sizeof(*(p_module->descriptor_bindings)),
+ SortCompareDescriptorBinding);
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseDescriptorType(SpvReflectShaderModule* p_module)
+{
+ if (p_module->descriptor_binding_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) {
+ SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]);
+ SpvReflectTypeDescription* p_type = p_descriptor->type_description;
+
+ switch (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK) {
+ default: assert(false && "unknown type flag"); break;
+
+ case SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE: {
+ if (p_descriptor->image.dim == SpvDimBuffer) {
+ switch (p_descriptor->image.sampled) {
+ default: assert(false && "unknown texel buffer sampled value"); break;
+ case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; break;
+ case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; break;
+ }
+ }
+ else if(p_descriptor->image.dim == SpvDimSubpassData) {
+ p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
+ }
+ else {
+ switch (p_descriptor->image.sampled) {
+ default: assert(false && "unknown image sampled value"); break;
+ case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE; break;
+ case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE; break;
+ }
+ }
+ }
+ break;
+
+ case SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER: {
+ p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER;
+ }
+ break;
+
+ case (SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE | SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE): {
+ // This is a workaround for: https://github.com/KhronosGroup/glslang/issues/1096
+ if (p_descriptor->image.dim == SpvDimBuffer) {
+ switch (p_descriptor->image.sampled) {
+ default: assert(false && "unknown texel buffer sampled value"); break;
+ case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; break;
+ case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; break;
+ }
+ }
+ else {
+ p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ }
+ }
+ break;
+
+ case SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK: {
+ if (p_type->decoration_flags & SPV_REFLECT_DECORATION_BLOCK) {
+ p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ }
+ else if (p_type->decoration_flags & SPV_REFLECT_DECORATION_BUFFER_BLOCK) {
+ p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ }
+ else {
+ assert(false && "unknown struct");
+ }
+ }
+ break;
+ }
+
+ switch (p_descriptor->descriptor_type) {
+ case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SAMPLER; break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : p_descriptor->resource_type = (SpvReflectResourceType)(SPV_REFLECT_RESOURCE_FLAG_SAMPLER | SPV_REFLECT_RESOURCE_FLAG_SRV); break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_CBV; break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_CBV; break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break;
+
+ case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ break;
+ }
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseUAVCounterBindings(SpvReflectShaderModule* p_module)
+{
+ char name[MAX_NODE_NAME_LENGTH];
+ const char* k_count_tag = "@count";
+
+ for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) {
+ SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]);
+
+ if (p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) {
+ continue;
+ }
+
+ SpvReflectDescriptorBinding* p_counter_descriptor = NULL;
+ // Use UAV counter buffer id if present...
+ if (p_descriptor->uav_counter_id != UINT32_MAX) {
+ for (uint32_t counter_descriptor_index = 0; counter_descriptor_index < p_module->descriptor_binding_count; ++counter_descriptor_index) {
+ SpvReflectDescriptorBinding* p_test_counter_descriptor = &(p_module->descriptor_bindings[counter_descriptor_index]);
+ if (p_test_counter_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) {
+ continue;
+ }
+ if (p_descriptor->uav_counter_id == p_test_counter_descriptor->spirv_id) {
+ p_counter_descriptor = p_test_counter_descriptor;
+ break;
+ }
+ }
+ }
+ // ...otherwise use old @count convention.
+ else {
+ const size_t descriptor_name_length = p_descriptor->name? strlen(p_descriptor->name): 0;
+
+ memset(name, 0, MAX_NODE_NAME_LENGTH);
+ memcpy(name, p_descriptor->name, descriptor_name_length);
+#if defined(WIN32)
+ strcat_s(name, MAX_NODE_NAME_LENGTH, k_count_tag);
+#else
+ strcat(name, k_count_tag);
+#endif
+
+ for (uint32_t counter_descriptor_index = 0; counter_descriptor_index < p_module->descriptor_binding_count; ++counter_descriptor_index) {
+ SpvReflectDescriptorBinding* p_test_counter_descriptor = &(p_module->descriptor_bindings[counter_descriptor_index]);
+ if (p_test_counter_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) {
+ continue;
+ }
+ if (p_test_counter_descriptor->name && strcmp(name, p_test_counter_descriptor->name) == 0) {
+ p_counter_descriptor = p_test_counter_descriptor;
+ break;
+ }
+ }
+ }
+
+ if (p_counter_descriptor != NULL) {
+ p_descriptor->uav_counter_binding = p_counter_descriptor;
+ }
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseDescriptorBlockVariable(
+ Parser* p_parser,
+ SpvReflectShaderModule* p_module,
+ SpvReflectTypeDescription* p_type,
+ SpvReflectBlockVariable* p_var
+)
+{
+ bool has_non_writable = false;
+
+ if (IsNotNull(p_type->members) && (p_type->member_count > 0)) {
+ p_var->member_count = p_type->member_count;
+ p_var->members = (SpvReflectBlockVariable*)calloc(p_var->member_count, sizeof(*p_var->members));
+ if (IsNull(p_var->members)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+
+ Node* p_type_node = FindNode(p_parser, p_type->id);
+ if (IsNull(p_type_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ // Resolve to element type if current type is array or run time array
+ if (p_type_node->op == SpvOpTypeArray) {
+ while (p_type_node->op == SpvOpTypeArray) {
+ p_type_node = FindNode(p_parser, p_type_node->array_traits.element_type_id);
+ if (IsNull(p_type_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+ }
+ else if(p_type_node->op == SpvOpTypeRuntimeArray) {
+ // Element type description
+ p_type = FindType(p_module, p_type_node->array_traits.element_type_id);
+ if (IsNull(p_type)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ // Element type node
+ p_type_node = FindNode(p_parser, p_type->id);
+ if (IsNull(p_type_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+
+ // Parse members
+ for (uint32_t member_index = 0; member_index < p_type->member_count; ++member_index) {
+ SpvReflectTypeDescription* p_member_type = &p_type->members[member_index];
+ SpvReflectBlockVariable* p_member_var = &p_var->members[member_index];
+ bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT;
+ if (is_struct) {
+ SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_member_type, p_member_var);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ }
+
+ p_member_var->name = p_type_node->member_names[member_index];
+ p_member_var->offset = p_type_node->member_decorations[member_index].offset.value;
+ p_member_var->decoration_flags = ApplyDecorations(&p_type_node->member_decorations[member_index]);
+ p_member_var->flags |= SPV_REFLECT_VARIABLE_FLAGS_UNUSED;
+ if (!has_non_writable && (p_member_var->decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE)) {
+ has_non_writable = true;
+ }
+ ApplyNumericTraits(p_member_type, &p_member_var->numeric);
+ if (p_member_type->op == SpvOpTypeArray) {
+ ApplyArrayTraits(p_member_type, &p_member_var->array);
+ }
+
+ p_member_var->type_description = p_member_type;
+ }
+ }
+
+ p_var->name = p_type->type_name;
+ p_var->type_description = p_type;
+ if (has_non_writable) {
+ p_var->decoration_flags |= SPV_REFLECT_DECORATION_NON_WRITABLE;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseDescriptorBlockVariableSizes(
+ Parser* p_parser,
+ SpvReflectShaderModule* p_module,
+ bool is_parent_root,
+ bool is_parent_aos,
+ bool is_parent_rta,
+ SpvReflectBlockVariable* p_var
+)
+{
+ if (p_var->member_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ // Absolute offsets
+ for (uint32_t member_index = 0; member_index < p_var->member_count; ++member_index) {
+ SpvReflectBlockVariable* p_member_var = &p_var->members[member_index];
+ if (is_parent_root) {
+ p_member_var->absolute_offset = p_member_var->offset;
+ }
+ else {
+ p_member_var->absolute_offset = is_parent_aos ? 0 : p_member_var->offset + p_var->absolute_offset;
+ }
+ }
+
+ // Size
+ for (uint32_t member_index = 0; member_index < p_var->member_count; ++member_index) {
+ SpvReflectBlockVariable* p_member_var = &p_var->members[member_index];
+ SpvReflectTypeDescription* p_member_type = p_member_var->type_description;
+
+ switch (p_member_type->op) {
+ case SpvOpTypeBool: {
+ p_member_var->size = SPIRV_WORD_SIZE;
+ }
+ break;
+
+ case SpvOpTypeInt:
+ case SpvOpTypeFloat: {
+ p_member_var->size = p_member_type->traits.numeric.scalar.width / SPIRV_BYTE_WIDTH;
+ }
+ break;
+
+ case SpvOpTypeVector: {
+ uint32_t size = p_member_type->traits.numeric.vector.component_count *
+ (p_member_type->traits.numeric.scalar.width / SPIRV_BYTE_WIDTH);
+ p_member_var->size = size;
+ }
+ break;
+
+ case SpvOpTypeMatrix: {
+ if (p_member_var->decoration_flags & SPV_REFLECT_DECORATION_COLUMN_MAJOR) {
+ p_member_var->size = p_member_var->numeric.matrix.column_count * p_member_var->numeric.matrix.stride;
+ }
+ else if (p_member_var->decoration_flags & SPV_REFLECT_DECORATION_ROW_MAJOR) {
+ p_member_var->size = p_member_var->numeric.matrix.row_count * p_member_var->numeric.matrix.stride;
+ }
+ }
+ break;
+
+ case SpvOpTypeArray: {
+ // If array of structs, parse members first...
+ bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT;
+ if (is_struct) {
+ SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, false, true, is_parent_rta, p_member_var);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ }
+ // ...then array
+ uint32_t element_count = (p_member_var->array.dims_count > 0 ? 1 : 0);
+ for (uint32_t i = 0; i < p_member_var->array.dims_count; ++i) {
+ element_count *= p_member_var->array.dims[i];
+ }
+ p_member_var->size = element_count * p_member_var->array.stride;
+ }
+ break;
+
+ case SpvOpTypeRuntimeArray: {
+ bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT;
+ if (is_struct) {
+ SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, false, true, true, p_member_var);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ }
+ }
+ break;
+
+ case SpvOpTypeStruct: {
+ SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, false, is_parent_aos, is_parent_rta, p_member_var);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // Parse padded size using offset difference for all member except for the last entry...
+ for (uint32_t member_index = 0; member_index < (p_var->member_count - 1); ++member_index) {
+ SpvReflectBlockVariable* p_member_var = &p_var->members[member_index];
+ SpvReflectBlockVariable* p_next_member_var = &p_var->members[member_index + 1];
+ p_member_var->padded_size = p_next_member_var->offset - p_member_var->offset;
+ if (p_member_var->size > p_member_var->padded_size) {
+ p_member_var->size = p_member_var->padded_size;
+ }
+ if (is_parent_rta) {
+ p_member_var->padded_size = p_member_var->size;
+ }
+ }
+ // ...last entry just gets rounded up to near multiple of SPIRV_DATA_ALIGNMENT, which is 16 and
+ // subtract the offset.
+ if (p_var->member_count > 0) {
+ SpvReflectBlockVariable* p_member_var = &p_var->members[p_var->member_count - 1];
+ p_member_var->padded_size = RoundUp(p_member_var->offset + p_member_var->size, SPIRV_DATA_ALIGNMENT) - p_member_var->offset;
+ if (p_member_var->size > p_member_var->padded_size) {
+ p_member_var->size = p_member_var->padded_size;
+ }
+ if (is_parent_rta) {
+ p_member_var->padded_size = p_member_var->size;
+ }
+ }
+
+ // @TODO validate this with assertion
+ p_var->size = p_var->members[p_var->member_count - 1].offset +
+ p_var->members[p_var->member_count - 1].padded_size;
+ p_var->padded_size = p_var->size;
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseDescriptorBlockVariableUsage(
+ Parser* p_parser,
+ SpvReflectShaderModule* p_module,
+ AccessChain* p_access_chain,
+ uint32_t index_index,
+ SpvOp override_op_type,
+ SpvReflectBlockVariable* p_var
+)
+{
+ (void)p_parser;
+ (void)p_access_chain;
+ (void)p_var;
+
+ // Clear the current variable's USED flag
+ p_var->flags &= ~SPV_REFLECT_VARIABLE_FLAGS_UNUSED;
+
+ // Parsing arrays requires overriding the op type for
+ // for the lowest dim's element type.
+ SpvOp op_type = p_var->type_description->op;
+ if (override_op_type != (SpvOp)INVALID_VALUE) {
+ op_type = override_op_type;
+ }
+
+ switch (op_type) {
+ default: break;
+
+ case SpvOpTypeArray: {
+ // Parse through array's type hierarchy to find the actual/non-array element type
+ SpvReflectTypeDescription* p_type = p_var->type_description;
+ while ((p_type->op == SpvOpTypeArray) && (index_index < p_access_chain->index_count)) {
+ // Find the array element type id
+ Node* p_node = FindNode(p_parser, p_type->id);
+ if (p_node == NULL) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ uint32_t element_type_id = p_node->array_traits.element_type_id;
+ // Get the array element type
+ p_type = FindType(p_module, element_type_id);
+ if (p_type == NULL) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ // Next access index
+ index_index += 1;
+ }
+ // Parse current var again with a type override and advanced index index
+ SpvReflectResult result = ParseDescriptorBlockVariableUsage(
+ p_parser,
+ p_module,
+ p_access_chain,
+ index_index,
+ p_type->op,
+ p_var);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ }
+ break;
+
+ case SpvOpTypeStruct: {
+ assert(p_var->member_count > 0);
+ if (p_var->member_count == 0) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA;
+ }
+
+ uint32_t index = p_access_chain->indexes[index_index];
+
+ if (index >= p_var->member_count) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE;
+ }
+
+ SpvReflectBlockVariable* p_member_var = &p_var->members[index];
+ if (index_index < p_access_chain->index_count) {
+ SpvReflectResult result = ParseDescriptorBlockVariableUsage(
+ p_parser,
+ p_module,
+ p_access_chain,
+ index_index + 1,
+ (SpvOp)INVALID_VALUE,
+ p_member_var);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ }
+ }
+ break;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseDescriptorBlocks(Parser* p_parser, SpvReflectShaderModule* p_module)
+{
+ if (p_module->descriptor_binding_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) {
+ SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]);
+ SpvReflectTypeDescription* p_type = p_descriptor->type_description;
+ if ((p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER) &&
+ (p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) )
+ {
+ continue;
+ }
+
+ // Mark UNUSED
+ p_descriptor->block.flags |= SPV_REFLECT_VARIABLE_FLAGS_UNUSED;
+ // Parse descriptor block
+ SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_type, &p_descriptor->block);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+
+ for (uint32_t access_chain_index = 0; access_chain_index < p_parser->access_chain_count; ++access_chain_index) {
+ AccessChain* p_access_chain = &(p_parser->access_chains[access_chain_index]);
+ // Skip any access chains that aren't touching this descriptor block
+ if (p_descriptor->spirv_id != p_access_chain->base_id) {
+ continue;
+ }
+ result = ParseDescriptorBlockVariableUsage(
+ p_parser,
+ p_module,
+ p_access_chain,
+ 0,
+ (SpvOp)INVALID_VALUE,
+ &p_descriptor->block);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ }
+
+ p_descriptor->block.name = p_descriptor->name;
+
+ bool is_parent_rta = (p_descriptor->descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER);
+ result = ParseDescriptorBlockVariableSizes(p_parser, p_module, true, false, is_parent_rta, &p_descriptor->block);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+
+ if (is_parent_rta) {
+ p_descriptor->block.size = 0;
+ p_descriptor->block.padded_size = 0;
+ }
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseFormat(
+ const SpvReflectTypeDescription* p_type,
+ SpvReflectFormat* p_format
+)
+{
+ SpvReflectResult result = SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR;
+ bool signedness = p_type->traits.numeric.scalar.signedness;
+ if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_VECTOR) {
+ uint32_t component_count = p_type->traits.numeric.vector.component_count;
+ if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_FLOAT) {
+ switch (component_count) {
+ case 2: *p_format = SPV_REFLECT_FORMAT_R32G32_SFLOAT; break;
+ case 3: *p_format = SPV_REFLECT_FORMAT_R32G32B32_SFLOAT; break;
+ case 4: *p_format = SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT; break;
+ }
+ result = SPV_REFLECT_RESULT_SUCCESS;
+ }
+ else if (p_type->type_flags & (SPV_REFLECT_TYPE_FLAG_INT | SPV_REFLECT_TYPE_FLAG_BOOL)) {
+ switch (component_count) {
+ case 2: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32_SINT : SPV_REFLECT_FORMAT_R32G32_UINT; break;
+ case 3: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32B32_SINT : SPV_REFLECT_FORMAT_R32G32B32_UINT; break;
+ case 4: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32B32A32_SINT : SPV_REFLECT_FORMAT_R32G32B32A32_UINT; break;
+ }
+ result = SPV_REFLECT_RESULT_SUCCESS;
+ }
+ }
+ else if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_FLOAT) {
+ *p_format = SPV_REFLECT_FORMAT_R32_SFLOAT;
+ result = SPV_REFLECT_RESULT_SUCCESS;
+ }
+ else if (p_type->type_flags & (SPV_REFLECT_TYPE_FLAG_INT | SPV_REFLECT_TYPE_FLAG_BOOL)) {
+ if (signedness) {
+ *p_format = SPV_REFLECT_FORMAT_R32_SINT;
+ result = SPV_REFLECT_RESULT_SUCCESS;
+ }
+ else {
+ *p_format = SPV_REFLECT_FORMAT_R32_UINT;
+ result = SPV_REFLECT_RESULT_SUCCESS;
+ }
+ }
+ else if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) {
+ *p_format = SPV_REFLECT_FORMAT_UNDEFINED;
+ result = SPV_REFLECT_RESULT_SUCCESS;
+ }
+ return result;
+}
+
+static SpvReflectResult ParseInterfaceVariable(
+ Parser* p_parser,
+ const Decorations* p_type_node_decorations,
+ SpvReflectShaderModule* p_module,
+ SpvReflectTypeDescription* p_type,
+ SpvReflectInterfaceVariable* p_var,
+ bool* p_has_built_in
+)
+{
+ Node* p_type_node = FindNode(p_parser, p_type->id);
+ if (IsNull(p_type_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+
+ if (p_type->member_count > 0) {
+ p_var->member_count = p_type->member_count;
+ p_var->members = (SpvReflectInterfaceVariable*)calloc(p_var->member_count, sizeof(*p_var->members));
+ if (IsNull(p_var->members)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+
+ for (uint32_t member_index = 0; member_index < p_type_node->member_count; ++member_index) {
+ Decorations* p_member_decorations = &p_type_node->member_decorations[member_index];
+ SpvReflectTypeDescription* p_member_type = &p_type->members[member_index];
+ SpvReflectInterfaceVariable* p_member_var = &p_var->members[member_index];
+ SpvReflectResult result = ParseInterfaceVariable(p_parser, p_member_decorations, p_module, p_member_type, p_member_var, p_has_built_in);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ }
+ }
+
+ p_var->name = p_type_node->name;
+ p_var->decoration_flags = ApplyDecorations(p_type_node_decorations);
+ p_var->built_in = p_type_node_decorations->built_in;
+ ApplyNumericTraits(p_type, &p_var->numeric);
+ if (p_type->op == SpvOpTypeArray) {
+ ApplyArrayTraits(p_type, &p_var->array);
+ }
+
+ p_var->type_description = p_type;
+
+ *p_has_built_in |= p_type_node_decorations->is_built_in;
+
+ SpvReflectResult result = ParseFormat(p_var->type_description, &p_var->format);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseInterfaceVariables(
+ Parser* p_parser,
+ SpvReflectShaderModule* p_module,
+ SpvReflectEntryPoint* p_entry,
+ size_t io_var_count,
+ uint32_t* io_vars
+)
+{
+ if (io_var_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ p_entry->input_variable_count = 0;
+ p_entry->output_variable_count = 0;
+ for (size_t i = 0; i < io_var_count; ++i) {
+ uint32_t var_result_id = *(io_vars + i);
+ Node* p_node = FindNode(p_parser, var_result_id);
+ if (IsNull(p_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+
+ if (p_node->storage_class == SpvStorageClassInput) {
+ p_entry->input_variable_count += 1;
+ }
+ else if (p_node->storage_class == SpvStorageClassOutput) {
+ p_entry->output_variable_count += 1;
+ }
+ }
+
+ if (p_entry->input_variable_count > 0) {
+ p_entry->input_variables = (SpvReflectInterfaceVariable*)calloc(p_entry->input_variable_count, sizeof(*(p_entry->input_variables)));
+ if (IsNull(p_entry->input_variables)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+
+
+ if (p_entry->output_variable_count > 0) {
+ p_entry->output_variables = (SpvReflectInterfaceVariable*)calloc(p_entry->output_variable_count, sizeof(*(p_entry->output_variables)));
+ if (IsNull(p_entry->output_variables)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+
+ size_t input_index = 0;
+ size_t output_index = 0;
+ for (size_t i = 0; i < io_var_count; ++i) {
+ uint32_t var_result_id = *(io_vars + i);
+ Node* p_node = FindNode(p_parser, var_result_id);
+ if (IsNull(p_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+
+ SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id);
+ if (IsNull(p_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ // If the type is a pointer, resolve it
+ if (p_type->op == SpvOpTypePointer) {
+ // Find the type's node
+ Node* p_type_node = FindNode(p_parser, p_type->id);
+ if (IsNull(p_type_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ // Should be the resolved type
+ p_type = FindType(p_module, p_type_node->type_id);
+ if (IsNull(p_type)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+
+ Node* p_type_node = FindNode(p_parser, p_type->id);
+ if (IsNull(p_type_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+
+ SpvReflectInterfaceVariable* p_var = NULL;
+ if (p_node->storage_class == SpvStorageClassInput) {
+ p_var = &(p_entry->input_variables[input_index]);
+ p_var->storage_class = SpvStorageClassInput;
+ ++input_index;
+ }
+ else if (p_node->storage_class == SpvStorageClassOutput) {
+ p_var = &(p_entry->output_variables[output_index]);
+ p_var->storage_class = SpvStorageClassOutput;
+ ++output_index;
+ } else {
+ // interface variables can only have input or output storage classes;
+ // anything else is either a new addition or an error.
+ assert(false && "Unsupported storage class for interface variable");
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_STORAGE_CLASS;
+ }
+
+ bool has_built_in = p_node->decorations.is_built_in;
+ SpvReflectResult result = ParseInterfaceVariable(
+ p_parser,
+ &p_type_node->decorations,
+ p_module,
+ p_type,
+ p_var,
+ &has_built_in);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+
+ // SPIR-V result id
+ p_var->spirv_id = p_node->result_id;
+ // Name
+ p_var->name = p_node->name;
+ // Semantic
+ p_var->semantic = p_node->decorations.semantic.value;
+
+ // Decorate with built-in if any member is built-in
+ if (has_built_in) {
+ p_var->decoration_flags |= SPV_REFLECT_DECORATION_BUILT_IN;
+ }
+
+ // Location is decorated on OpVariable node, not the type node.
+ p_var->location = p_node->decorations.location.value;
+ p_var->word_offset.location = p_node->decorations.location.word_offset;
+
+ // Built in
+ if (p_node->decorations.is_built_in) {
+ p_var->built_in = p_node->decorations.built_in;
+ }
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult EnumerateAllPushConstants(
+ SpvReflectShaderModule* p_module,
+ size_t* p_push_constant_count,
+ uint32_t** p_push_constants
+)
+{
+ *p_push_constant_count = p_module->push_constant_block_count;
+ if (*p_push_constant_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+ *p_push_constants = (uint32_t*)calloc(*p_push_constant_count, sizeof(**p_push_constants));
+
+ if (IsNull(*p_push_constants)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+
+ for (size_t i = 0; i < *p_push_constant_count; ++i) {
+ (*p_push_constants)[i] = p_module->push_constant_blocks[i].spirv_id;
+ }
+ qsort(*p_push_constants, *p_push_constant_count, sizeof(**p_push_constants),
+ SortCompareUint32);
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult TraverseCallGraph(
+ Parser* p_parser,
+ Function* p_func,
+ size_t* p_func_count,
+ uint32_t* p_func_ids,
+ uint32_t depth
+)
+{
+ if (depth > p_parser->function_count) {
+ // Vulkan does not permit recursion (Vulkan spec Appendix A):
+ // "Recursion: The static function-call graph for an entry point must not
+ // contain cycles."
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_RECURSION;
+ }
+ if (IsNotNull(p_func_ids)) {
+ p_func_ids[(*p_func_count)++] = p_func->id;
+ } else {
+ ++*p_func_count;
+ }
+ for (size_t i = 0; i < p_func->callee_count; ++i) {
+ SpvReflectResult result = TraverseCallGraph(
+ p_parser, p_func->callee_ptrs[i], p_func_count, p_func_ids, depth + 1);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ }
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseStaticallyUsedResources(
+ Parser* p_parser,
+ SpvReflectShaderModule* p_module,
+ SpvReflectEntryPoint* p_entry,
+ size_t uniform_count,
+ uint32_t* uniforms,
+ size_t push_constant_count,
+ uint32_t* push_constants
+)
+{
+ // Find function with the right id
+ Function* p_func = NULL;
+ for (size_t i = 0; i < p_parser->function_count; ++i) {
+ if (p_parser->functions[i].id == p_entry->id) {
+ p_func = &(p_parser->functions[i]);
+ break;
+ }
+ }
+ if (p_func == NULL) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+
+ size_t called_function_count = 0;
+ SpvReflectResult result = TraverseCallGraph(
+ p_parser,
+ p_func,
+ &called_function_count,
+ NULL,
+ 0);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+
+ uint32_t* p_called_functions = NULL;
+ if (called_function_count > 0) {
+ p_called_functions = (uint32_t*)calloc(called_function_count, sizeof(*p_called_functions));
+ if (IsNull(p_called_functions)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+
+ called_function_count = 0;
+ result = TraverseCallGraph(
+ p_parser,
+ p_func,
+ &called_function_count,
+ p_called_functions,
+ 0);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+
+ if (called_function_count > 0) {
+ qsort(
+ p_called_functions,
+ called_function_count,
+ sizeof(*p_called_functions),
+ SortCompareUint32);
+ }
+ called_function_count = DedupSortedUint32(p_called_functions, called_function_count);
+
+ uint32_t used_variable_count = 0;
+ for (size_t i = 0, j = 0; i < called_function_count; ++i) {
+ // No need to bounds check j because a missing ID issue would have been
+ // found during TraverseCallGraph
+ while (p_parser->functions[j].id != p_called_functions[i]) {
+ ++j;
+ }
+ used_variable_count += p_parser->functions[j].accessed_ptr_count;
+ }
+ uint32_t* used_variables = NULL;
+ if (used_variable_count > 0) {
+ used_variables = (uint32_t*)calloc(used_variable_count,
+ sizeof(*used_variables));
+ if (IsNull(used_variables)) {
+ SafeFree(p_called_functions);
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+ used_variable_count = 0;
+ for (size_t i = 0, j = 0; i < called_function_count; ++i) {
+ while (p_parser->functions[j].id != p_called_functions[i]) {
+ ++j;
+ }
+
+ memcpy(&used_variables[used_variable_count],
+ p_parser->functions[j].accessed_ptrs,
+ p_parser->functions[j].accessed_ptr_count * sizeof(*used_variables));
+ used_variable_count += p_parser->functions[j].accessed_ptr_count;
+ }
+ SafeFree(p_called_functions);
+
+ if (used_variable_count > 0) {
+ qsort(used_variables, used_variable_count, sizeof(*used_variables),
+ SortCompareUint32);
+ }
+ used_variable_count = (uint32_t)DedupSortedUint32(used_variables,
+ used_variable_count);
+
+ // Do set intersection to find the used uniform and push constants
+ size_t used_uniform_count = 0;
+ //
+ SpvReflectResult result0 = IntersectSortedUint32(
+ used_variables,
+ used_variable_count,
+ uniforms,
+ uniform_count,
+ &p_entry->used_uniforms,
+ &used_uniform_count);
+
+ size_t used_push_constant_count = 0;
+ //
+ SpvReflectResult result1 = IntersectSortedUint32(
+ used_variables,
+ used_variable_count,
+ push_constants,
+ push_constant_count,
+ &p_entry->used_push_constants,
+ &used_push_constant_count);
+
+ for (uint32_t j = 0; j < p_module->descriptor_binding_count; ++j) {
+ SpvReflectDescriptorBinding* p_binding = &p_module->descriptor_bindings[j];
+ bool found = SearchSortedUint32(
+ used_variables,
+ used_variable_count,
+ p_binding->spirv_id);
+ if (found) {
+ p_binding->accessed = 1;
+ }
+ }
+
+ SafeFree(used_variables);
+ if (result0 != SPV_REFLECT_RESULT_SUCCESS) {
+ return result0;
+ }
+ if (result1 != SPV_REFLECT_RESULT_SUCCESS) {
+ return result1;
+ }
+
+ p_entry->used_uniform_count = (uint32_t)used_uniform_count;
+ p_entry->used_push_constant_count = (uint32_t)used_push_constant_count;
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseEntryPoints(Parser* p_parser, SpvReflectShaderModule* p_module)
+{
+ if (p_parser->entry_point_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ p_module->entry_point_count = p_parser->entry_point_count;
+ p_module->entry_points = (SpvReflectEntryPoint*)calloc(p_module->entry_point_count,
+ sizeof(*(p_module->entry_points)));
+ if (IsNull(p_module->entry_points)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+
+ SpvReflectResult result;
+ size_t uniform_count = 0;
+ uint32_t* uniforms = NULL;
+ if ((result = EnumerateAllUniforms(p_module, &uniform_count, &uniforms)) !=
+ SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ size_t push_constant_count = 0;
+ uint32_t* push_constants = NULL;
+ if ((result = EnumerateAllPushConstants(p_module, &push_constant_count, &push_constants)) !=
+ SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+
+ size_t entry_point_index = 0;
+ for (size_t i = 0; entry_point_index < p_parser->entry_point_count && i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if (p_node->op != SpvOpEntryPoint) {
+ continue;
+ }
+
+ SpvReflectEntryPoint* p_entry_point = &(p_module->entry_points[entry_point_index]);
+ CHECKED_READU32_CAST(p_parser, p_node->word_offset + 1, SpvExecutionModel, p_entry_point->spirv_execution_model);
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_entry_point->id);
+
+ switch (p_entry_point->spirv_execution_model) {
+ default: break;
+ case SpvExecutionModelVertex : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_VERTEX_BIT; break;
+ case SpvExecutionModelTessellationControl : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break;
+ case SpvExecutionModelTessellationEvaluation : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break;
+ case SpvExecutionModelGeometry : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT; break;
+ case SpvExecutionModelFragment : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT; break;
+ case SpvExecutionModelGLCompute : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT; break;
+ }
+
+ ++entry_point_index;
+
+ // Name length is required to calculate next operand
+ uint32_t name_start_word_offset = 3;
+ uint32_t name_length_with_terminator = 0;
+ result = ReadStr(p_parser, p_node->word_offset + name_start_word_offset, 0, p_node->word_count, &name_length_with_terminator, NULL);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ p_entry_point->name = (const char*)(p_parser->spirv_code + p_node->word_offset + name_start_word_offset);
+
+ uint32_t name_word_count = RoundUp(name_length_with_terminator, SPIRV_WORD_SIZE) / SPIRV_WORD_SIZE;
+ size_t interface_variable_count = (p_node->word_count - (name_start_word_offset + name_word_count));
+ uint32_t* interface_variables = NULL;
+ if (interface_variable_count > 0) {
+ interface_variables = (uint32_t*)calloc(interface_variable_count, sizeof(*(interface_variables)));
+ if (IsNull(interface_variables)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+
+ for (uint32_t var_index = 0; var_index < interface_variable_count; ++var_index) {
+ uint32_t var_result_id = (uint32_t)INVALID_VALUE;
+ uint32_t offset = name_start_word_offset + name_word_count + var_index;
+ CHECKED_READU32(p_parser, p_node->word_offset + offset, var_result_id);
+ interface_variables[var_index] = var_result_id;
+ }
+
+ result = ParseInterfaceVariables(
+ p_parser,
+ p_module,
+ p_entry_point,
+ interface_variable_count,
+ interface_variables);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ SafeFree(interface_variables);
+
+ result = ParseStaticallyUsedResources(
+ p_parser,
+ p_module,
+ p_entry_point,
+ uniform_count,
+ uniforms,
+ push_constant_count,
+ push_constants);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ }
+
+ SafeFree(uniforms);
+ SafeFree(push_constants);
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParsePushConstantBlocks(Parser* p_parser, SpvReflectShaderModule* p_module)
+{
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if ((p_node->op != SpvOpVariable) || (p_node->storage_class != SpvStorageClassPushConstant)) {
+ continue;
+ }
+
+ p_module->push_constant_block_count += 1;
+ }
+
+ if (p_module->push_constant_block_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ p_module->push_constant_blocks = (SpvReflectBlockVariable*)calloc(p_module->push_constant_block_count, sizeof(*p_module->push_constant_blocks));
+ if (IsNull(p_module->push_constant_blocks)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+
+ uint32_t push_constant_index = 0;
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
+ Node* p_node = &(p_parser->nodes[i]);
+ if ((p_node->op != SpvOpVariable) || (p_node->storage_class != SpvStorageClassPushConstant)) {
+ continue;
+ }
+
+ SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id);
+ if (IsNull(p_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ // If the type is a pointer, resolve it
+ if (p_type->op == SpvOpTypePointer) {
+ // Find the type's node
+ Node* p_type_node = FindNode(p_parser, p_type->id);
+ if (IsNull(p_type_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ // Should be the resolved type
+ p_type = FindType(p_module, p_type_node->type_id);
+ if (IsNull(p_type)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+ }
+
+ Node* p_type_node = FindNode(p_parser, p_type->id);
+ if (IsNull(p_type_node)) {
+ return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+ }
+
+ SpvReflectBlockVariable* p_push_constant = &p_module->push_constant_blocks[push_constant_index];
+ p_push_constant->spirv_id = p_node->result_id;
+ SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_type, p_push_constant);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+ result = ParseDescriptorBlockVariableSizes(p_parser, p_module, true, false, false, p_push_constant);
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ return result;
+ }
+
+ ++push_constant_index;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static int SortCompareDescriptorSet(const void* a, const void* b)
+{
+ const SpvReflectDescriptorSet* p_elem_a = (const SpvReflectDescriptorSet*)a;
+ const SpvReflectDescriptorSet* p_elem_b = (const SpvReflectDescriptorSet*)b;
+ int value = (int)(p_elem_a->set) - (int)(p_elem_b->set);
+ // We should never see duplicate descriptor set numbers in a shader; if so, a tiebreaker
+ // would be needed here.
+ assert(value != 0);
+ return value;
+}
+
+static SpvReflectResult ParseEntrypointDescriptorSets(SpvReflectShaderModule* p_module) {
+ // Update the entry point's sets
+ for (uint32_t i = 0; i < p_module->entry_point_count; ++i) {
+ SpvReflectEntryPoint* p_entry = &p_module->entry_points[i];
+ for (uint32_t j = 0; j < p_entry->descriptor_set_count; ++j) {
+ SafeFree(p_entry->descriptor_sets[j].bindings);
+ }
+ SafeFree(p_entry->descriptor_sets);
+ p_entry->descriptor_set_count = 0;
+ for (uint32_t j = 0; j < p_module->descriptor_set_count; ++j) {
+ const SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j];
+ for (uint32_t k = 0; k < p_set->binding_count; ++k) {
+ bool found = SearchSortedUint32(
+ p_entry->used_uniforms,
+ p_entry->used_uniform_count,
+ p_set->bindings[k]->spirv_id);
+ if (found) {
+ ++p_entry->descriptor_set_count;
+ break;
+ }
+ }
+ }
+
+ p_entry->descriptor_sets = NULL;
+ if (p_entry->descriptor_set_count > 0) {
+ p_entry->descriptor_sets = (SpvReflectDescriptorSet*)calloc(p_entry->descriptor_set_count,
+ sizeof(*p_entry->descriptor_sets));
+ if (IsNull(p_entry->descriptor_sets)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+ p_entry->descriptor_set_count = 0;
+ for (uint32_t j = 0; j < p_module->descriptor_set_count; ++j) {
+ const SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j];
+ uint32_t count = 0;
+ for (uint32_t k = 0; k < p_set->binding_count; ++k) {
+ bool found = SearchSortedUint32(
+ p_entry->used_uniforms,
+ p_entry->used_uniform_count,
+ p_set->bindings[k]->spirv_id);
+ if (found) {
+ ++count;
+ }
+ }
+ if (count == 0) {
+ continue;
+ }
+ SpvReflectDescriptorSet* p_entry_set = &p_entry->descriptor_sets[
+ p_entry->descriptor_set_count++];
+ p_entry_set->set = p_set->set;
+ p_entry_set->bindings = (SpvReflectDescriptorBinding**)calloc(count,
+ sizeof(*p_entry_set->bindings));
+ if (IsNull(p_entry_set->bindings)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ for (uint32_t k = 0; k < p_set->binding_count; ++k) {
+ bool found = SearchSortedUint32(
+ p_entry->used_uniforms,
+ p_entry->used_uniform_count,
+ p_set->bindings[k]->spirv_id);
+ if (found) {
+ p_entry_set->bindings[p_entry_set->binding_count++] = p_set->bindings[k];
+ }
+ }
+ }
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseDescriptorSets(SpvReflectShaderModule* p_module)
+{
+ // Count the descriptors in each set
+ for (uint32_t i = 0; i < p_module->descriptor_binding_count; ++i) {
+ SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[i]);
+
+ // Look for a target set using the descriptor's set number
+ SpvReflectDescriptorSet* p_target_set = NULL;
+ for (uint32_t j = 0; j < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++j) {
+ SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j];
+ if (p_set->set == p_descriptor->set) {
+ p_target_set = p_set;
+ break;
+ }
+ }
+
+ // If a target set isn't found, find the first available one.
+ if (IsNull(p_target_set)) {
+ for (uint32_t j = 0; j < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++j) {
+ SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j];
+ if (p_set->set == (uint32_t)INVALID_VALUE) {
+ p_target_set = p_set;
+ p_target_set->set = p_descriptor->set;
+ break;
+ }
+ }
+ }
+
+ if (IsNull(p_target_set)) {
+ return SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR;
+ }
+
+ p_target_set->binding_count += 1;
+ }
+
+ // Count the descriptor sets
+ for (uint32_t i = 0; i < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++i) {
+ const SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[i];
+ if (p_set->set != (uint32_t)INVALID_VALUE) {
+ p_module->descriptor_set_count += 1;
+ }
+ }
+
+ // Sort the descriptor sets based on numbers
+ if (p_module->descriptor_set_count > 0) {
+ qsort(p_module->descriptor_sets,
+ p_module->descriptor_set_count,
+ sizeof(*(p_module->descriptor_sets)),
+ SortCompareDescriptorSet);
+ }
+
+ // Build descriptor pointer array
+ for (uint32_t i = 0; i <p_module->descriptor_set_count; ++i) {
+ SpvReflectDescriptorSet* p_set = &(p_module->descriptor_sets[i]);
+ p_set->bindings = (SpvReflectDescriptorBinding **)calloc(p_set->binding_count, sizeof(*(p_set->bindings)));
+
+ uint32_t descriptor_index = 0;
+ for (uint32_t j = 0; j < p_module->descriptor_binding_count; ++j) {
+ SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[j]);
+ if (p_descriptor->set == p_set->set) {
+ assert(descriptor_index < p_set->binding_count);
+ p_set->bindings[descriptor_index] = p_descriptor;
+ ++descriptor_index;
+ }
+ }
+ }
+
+ return ParseEntrypointDescriptorSets(p_module);
+}
+
+static SpvReflectResult DisambiguateStorageBufferSrvUav(SpvReflectShaderModule* p_module)
+{
+ if (p_module->descriptor_binding_count == 0) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
+ for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) {
+ SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]);
+ // Skip everything that isn't a STORAGE_BUFFER descriptor
+ if (p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) {
+ continue;
+ }
+
+ //
+ // Vulkan doesn't disambiguate between SRVs and UAVs so they
+ // come back as STORAGE_BUFFER. The block parsing process will
+ // mark a block as non-writable should any member of the block
+ // or its descendants are non-writable.
+ //
+ if (p_descriptor->block.decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE) {
+ p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV;
+ }
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult SynchronizeDescriptorSets(SpvReflectShaderModule* p_module)
+{
+ // Free and reset all descriptor set numbers
+ for (uint32_t i = 0; i < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++i) {
+ SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[i];
+ SafeFree(p_set->bindings);
+ p_set->binding_count = 0;
+ p_set->set = (uint32_t)INVALID_VALUE;
+ }
+ // Set descriptor set count to zero
+ p_module->descriptor_set_count = 0;
+
+ SpvReflectResult result = ParseDescriptorSets(p_module);
+ return result;
+}
+
+SpvReflectResult spvReflectGetShaderModule(
+ size_t size,
+ const void* p_code,
+ SpvReflectShaderModule* p_module
+)
+{
+ return spvReflectCreateShaderModule(size, p_code, p_module);
+}
+
+SpvReflectResult spvReflectCreateShaderModule(
+ size_t size,
+ const void* p_code,
+ SpvReflectShaderModule* p_module
+)
+{
+ // Initialize all module fields to zero
+ memset(p_module, 0, sizeof(*p_module));
+
+ // Allocate module internals
+#ifdef __cplusplus
+ p_module->_internal = (SpvReflectShaderModule::Internal*)calloc(1, sizeof(*(p_module->_internal)));
+#else
+ p_module->_internal = calloc(1, sizeof(*(p_module->_internal)));
+#endif
+ if (IsNull(p_module->_internal)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ // Allocate SPIR-V code storage
+ p_module->_internal->spirv_size = size;
+ p_module->_internal->spirv_code = (uint32_t*)calloc(1, p_module->_internal->spirv_size);
+ p_module->_internal->spirv_word_count = (uint32_t)(size / SPIRV_WORD_SIZE);
+ if (IsNull(p_module->_internal->spirv_code)) {
+ SafeFree(p_module->_internal);
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ memcpy(p_module->_internal->spirv_code, p_code, size);
+
+ Parser parser = { 0 };
+ SpvReflectResult result = CreateParser(p_module->_internal->spirv_size,
+ p_module->_internal->spirv_code,
+ &parser);
+
+ // Generator
+ {
+ const uint32_t* p_ptr = (const uint32_t*)p_module->_internal->spirv_code;
+ p_module->generator = (SpvReflectGenerator)((*(p_ptr + 2) & 0xFFFF0000) >> 16);
+ }
+
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseNodes(&parser);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseStrings(&parser);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseSource(&parser, p_module);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseFunctions(&parser);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseMemberCounts(&parser);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseNames(&parser);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseDecorations(&parser);
+ }
+
+ // Start of reflection data parsing
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ p_module->source_language = parser.source_language;
+ p_module->source_language_version = parser.source_language_version;
+
+ // Zero out descriptor set data
+ p_module->descriptor_set_count = 0;
+ memset(p_module->descriptor_sets, 0, SPV_REFLECT_MAX_DESCRIPTOR_SETS * sizeof(*p_module->descriptor_sets));
+ // Initialize descriptor set numbers
+ for (uint32_t set_number = 0; set_number < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++set_number) {
+ p_module->descriptor_sets[set_number].set = (uint32_t)INVALID_VALUE;
+ }
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseTypes(&parser, p_module);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseDescriptorBindings(&parser, p_module);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseDescriptorType(p_module);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseUAVCounterBindings(p_module);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseDescriptorBlocks(&parser, p_module);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParsePushConstantBlocks(&parser, p_module);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = ParseEntryPoints(&parser, p_module);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS && p_module->entry_point_count > 0) {
+ SpvReflectEntryPoint* p_entry = &(p_module->entry_points[0]);
+ p_module->entry_point_name = p_entry->name;
+ p_module->entry_point_id = p_entry->id;
+ p_module->spirv_execution_model = p_entry->spirv_execution_model;
+ p_module->shader_stage = p_entry->shader_stage;
+ p_module->input_variable_count = p_entry->input_variable_count;
+ p_module->input_variables = p_entry->input_variables;
+ p_module->output_variable_count = p_entry->output_variable_count;
+ p_module->output_variables = p_entry->output_variables;
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = DisambiguateStorageBufferSrvUav(p_module);
+ }
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
+ result = SynchronizeDescriptorSets(p_module);
+ }
+
+ // Destroy module if parse was not successful
+ if (result != SPV_REFLECT_RESULT_SUCCESS) {
+ spvReflectDestroyShaderModule(p_module);
+ }
+
+ DestroyParser(&parser);
+
+ return result;
+}
+
+static void SafeFreeTypes(SpvReflectTypeDescription* p_type)
+{
+ if (IsNull(p_type)) {
+ return;
+ }
+
+ if (IsNotNull(p_type->members)) {
+ for (size_t i = 0; i < p_type->member_count; ++i) {
+ SpvReflectTypeDescription* p_member = &p_type->members[i];
+ SafeFreeTypes(p_member);
+ }
+
+ SafeFree(p_type->members);
+ p_type->members = NULL;
+ }
+}
+
+static void SafeFreeBlockVariables(SpvReflectBlockVariable* p_block)
+{
+ if (IsNull(p_block)) {
+ return;
+ }
+
+ if (IsNotNull(p_block->members)) {
+ for (size_t i = 0; i < p_block->member_count; ++i) {
+ SpvReflectBlockVariable* p_member = &p_block->members[i];
+ SafeFreeBlockVariables(p_member);
+ }
+
+ SafeFree(p_block->members);
+ p_block->members = NULL;
+ }
+}
+
+static void SafeFreeInterfaceVariable(SpvReflectInterfaceVariable* p_interface)
+{
+ if (IsNull(p_interface)) {
+ return;
+ }
+
+ if (IsNotNull(p_interface->members)) {
+ for (size_t i = 0; i < p_interface->member_count; ++i) {
+ SpvReflectInterfaceVariable* p_member = &p_interface->members[i];
+ SafeFreeInterfaceVariable(p_member);
+ }
+
+ SafeFree(p_interface->members);
+ p_interface->members = NULL;
+ }
+}
+
+void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
+{
+ if (IsNull(p_module->_internal)) {
+ return;
+ }
+
+ // Descriptor set bindings
+ for (size_t i = 0; i < p_module->descriptor_set_count; ++i) {
+ SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[i];
+ free(p_set->bindings);
+ }
+
+ // Descriptor binding blocks
+ for (size_t i = 0; i < p_module->descriptor_binding_count; ++i) {
+ SpvReflectDescriptorBinding* p_descriptor = &p_module->descriptor_bindings[i];
+ SafeFreeBlockVariables(&p_descriptor->block);
+ }
+ SafeFree(p_module->descriptor_bindings);
+
+ // Entry points
+ for (size_t i = 0; i < p_module->entry_point_count; ++i) {
+ SpvReflectEntryPoint* p_entry = &p_module->entry_points[i];
+ for (size_t j = 0; j < p_entry->input_variable_count; j++) {
+ SafeFreeInterfaceVariable(&p_entry->input_variables[j]);
+ }
+ for (size_t j = 0; j < p_entry->output_variable_count; j++) {
+ SafeFreeInterfaceVariable(&p_entry->output_variables[j]);
+ }
+ for (uint32_t j = 0; j < p_entry->descriptor_set_count; ++j) {
+ SafeFree(p_entry->descriptor_sets[j].bindings);
+ }
+ SafeFree(p_entry->descriptor_sets);
+ SafeFree(p_entry->input_variables);
+ SafeFree(p_entry->output_variables);
+ SafeFree(p_entry->used_uniforms);
+ SafeFree(p_entry->used_push_constants);
+ }
+ SafeFree(p_module->entry_points);
+
+ // Push constants
+ for (size_t i = 0; i < p_module->push_constant_block_count; ++i) {
+ SafeFreeBlockVariables(&p_module->push_constant_blocks[i]);
+ }
+ SafeFree(p_module->push_constant_blocks);
+
+ // Type infos
+ for (size_t i = 0; i < p_module->_internal->type_description_count; ++i) {
+ SpvReflectTypeDescription* p_type = &p_module->_internal->type_descriptions[i];
+ if (IsNotNull(p_type->members)) {
+ SafeFreeTypes(p_type);
+ }
+ SafeFree(p_type->members);
+ }
+ SafeFree(p_module->_internal->type_descriptions);
+
+ // Free SPIR-V code
+ SafeFree(p_module->_internal->spirv_code);
+ // Free internal
+ SafeFree(p_module->_internal);
+}
+
+uint32_t spvReflectGetCodeSize(const SpvReflectShaderModule* p_module)
+{
+ if (IsNull(p_module)) {
+ return 0;
+ }
+
+ return (uint32_t)(p_module->_internal->spirv_size);
+}
+
+const uint32_t* spvReflectGetCode(const SpvReflectShaderModule* p_module)
+{
+ if (IsNull(p_module)) {
+ return NULL;
+ }
+
+ return p_module->_internal->spirv_code;
+}
+
+const SpvReflectEntryPoint* spvReflectGetEntryPoint(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point
+) {
+ if (IsNull(p_module) || IsNull(entry_point)) {
+ return NULL;
+ }
+
+ for (uint32_t i = 0; i < p_module->entry_point_count; ++i) {
+ if (strcmp(p_module->entry_points[i].name, entry_point) == 0) {
+ return &p_module->entry_points[i];
+ }
+ }
+ return NULL;
+}
+
+SpvReflectResult spvReflectEnumerateDescriptorBindings(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectDescriptorBinding** pp_bindings
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ if (IsNotNull(pp_bindings)) {
+ if (*p_count != p_module->descriptor_binding_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+
+ for (uint32_t index = 0; index < *p_count; ++index) {
+ SpvReflectDescriptorBinding* p_bindings = (SpvReflectDescriptorBinding*)&p_module->descriptor_bindings[index];
+ pp_bindings[index] = p_bindings;
+ }
+ }
+ else {
+ *p_count = p_module->descriptor_binding_count;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+SpvReflectResult spvReflectEnumerateEntryPointDescriptorBindings(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectDescriptorBinding** pp_bindings
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ const SpvReflectEntryPoint* p_entry =
+ spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+
+ uint32_t count = 0;
+ for (uint32_t i = 0; i < p_module->descriptor_binding_count; ++i) {
+ bool found = SearchSortedUint32(
+ p_entry->used_uniforms,
+ p_entry->used_uniform_count,
+ p_module->descriptor_bindings[i].spirv_id);
+ if (found) {
+ if (IsNotNull(pp_bindings)) {
+ if (count >= *p_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+ pp_bindings[count++] = (SpvReflectDescriptorBinding*)&p_module->descriptor_bindings[i];
+ } else {
+ ++count;
+ }
+ }
+ }
+ if (IsNotNull(pp_bindings)) {
+ if (count != *p_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+ } else {
+ *p_count = count;
+ }
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+SpvReflectResult spvReflectEnumerateDescriptorSets(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectDescriptorSet** pp_sets
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ if (IsNotNull(pp_sets)) {
+ if (*p_count != p_module->descriptor_set_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+
+ for (uint32_t index = 0; index < *p_count; ++index) {
+ SpvReflectDescriptorSet* p_set = (SpvReflectDescriptorSet*)&p_module->descriptor_sets[index];
+ pp_sets[index] = p_set;
+ }
+ }
+ else {
+ *p_count = p_module->descriptor_set_count;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+SpvReflectResult spvReflectEnumerateEntryPointDescriptorSets(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectDescriptorSet** pp_sets
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ const SpvReflectEntryPoint* p_entry =
+ spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+
+ if (IsNotNull(pp_sets)) {
+ if (*p_count != p_entry->descriptor_set_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+
+ for (uint32_t index = 0; index < *p_count; ++index) {
+ SpvReflectDescriptorSet* p_set = (SpvReflectDescriptorSet*)&p_entry->descriptor_sets[index];
+ pp_sets[index] = p_set;
+ }
+ }
+ else {
+ *p_count = p_entry->descriptor_set_count;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+SpvReflectResult spvReflectEnumerateInputVariables(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ if (IsNotNull(pp_variables)) {
+ if (*p_count != p_module->input_variable_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+
+ for (uint32_t index = 0; index < *p_count; ++index) {
+ SpvReflectInterfaceVariable* p_var = (SpvReflectInterfaceVariable*)&p_module->input_variables[index];
+ pp_variables[index] = p_var;
+ }
+ }
+ else {
+ *p_count = p_module->input_variable_count;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+SpvReflectResult spvReflectEnumerateEntryPointInputVariables(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ const SpvReflectEntryPoint* p_entry =
+ spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+
+ if (IsNotNull(pp_variables)) {
+ if (*p_count != p_entry->input_variable_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+
+ for (uint32_t index = 0; index < *p_count; ++index) {
+ SpvReflectInterfaceVariable* p_var = (SpvReflectInterfaceVariable*)&p_entry->input_variables[index];
+ pp_variables[index] = p_var;
+ }
+ }
+ else {
+ *p_count = p_entry->input_variable_count;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+SpvReflectResult spvReflectEnumerateOutputVariables(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ if (IsNotNull(pp_variables)) {
+ if (*p_count != p_module->output_variable_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+
+ for (uint32_t index = 0; index < *p_count; ++index) {
+ SpvReflectInterfaceVariable* p_var = (SpvReflectInterfaceVariable*)&p_module->output_variables[index];
+ pp_variables[index] = p_var;
+ }
+ }
+ else {
+ *p_count = p_module->output_variable_count;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+SpvReflectResult spvReflectEnumerateEntryPointOutputVariables(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ const SpvReflectEntryPoint* p_entry =
+ spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+
+ if (IsNotNull(pp_variables)) {
+ if (*p_count != p_entry->output_variable_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+
+ for (uint32_t index = 0; index < *p_count; ++index) {
+ SpvReflectInterfaceVariable* p_var = (SpvReflectInterfaceVariable*)&p_entry->output_variables[index];
+ pp_variables[index] = p_var;
+ }
+ }
+ else {
+ *p_count = p_entry->output_variable_count;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+SpvReflectResult spvReflectEnumeratePushConstantBlocks(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectBlockVariable** pp_blocks
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ if (pp_blocks != NULL) {
+ if (*p_count != p_module->push_constant_block_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+
+ for (uint32_t index = 0; index < *p_count; ++index) {
+ SpvReflectBlockVariable* p_push_constant_blocks = (SpvReflectBlockVariable*)&p_module->push_constant_blocks[index];
+ pp_blocks[index] = p_push_constant_blocks;
+ }
+ }
+ else {
+ *p_count = p_module->push_constant_block_count;
+ }
+
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+SpvReflectResult spvReflectEnumeratePushConstants(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectBlockVariable** pp_blocks
+)
+{
+ return spvReflectEnumeratePushConstantBlocks(p_module, p_count, pp_blocks);
+}
+
+SpvReflectResult spvReflectEnumerateEntryPointPushConstantBlocks(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectBlockVariable** pp_blocks
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_count)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+
+ const SpvReflectEntryPoint* p_entry =
+ spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+
+ uint32_t count = 0;
+ for (uint32_t i = 0; i < p_module->push_constant_block_count; ++i) {
+ bool found = SearchSortedUint32(p_entry->used_push_constants,
+ p_entry->used_push_constant_count,
+ p_module->push_constant_blocks[i].spirv_id);
+ if (found) {
+ if (IsNotNull(pp_blocks)) {
+ if (count >= *p_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+ pp_blocks[count++] = (SpvReflectBlockVariable*)&p_module->push_constant_blocks[i];
+ } else {
+ ++count;
+ }
+ }
+ }
+ if (IsNotNull(pp_blocks)) {
+ if (count != *p_count) {
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+ }
+ } else {
+ *p_count = count;
+ }
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+const SpvReflectDescriptorBinding* spvReflectGetDescriptorBinding(
+ const SpvReflectShaderModule* p_module,
+ uint32_t binding_number,
+ uint32_t set_number,
+ SpvReflectResult* p_result
+)
+{
+ const SpvReflectDescriptorBinding* p_descriptor = NULL;
+ if (IsNotNull(p_module)) {
+ for (uint32_t index = 0; index < p_module->descriptor_binding_count; ++index) {
+ const SpvReflectDescriptorBinding* p_potential = &p_module->descriptor_bindings[index];
+ if ((p_potential->binding == binding_number) && (p_potential->set == set_number)) {
+ p_descriptor = p_potential;
+ break;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_descriptor)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_descriptor;
+}
+
+const SpvReflectDescriptorBinding* spvReflectGetEntryPointDescriptorBinding(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t binding_number,
+ uint32_t set_number,
+ SpvReflectResult* p_result
+)
+{
+ const SpvReflectEntryPoint* p_entry =
+ spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ const SpvReflectDescriptorBinding* p_descriptor = NULL;
+ if (IsNotNull(p_module)) {
+ for (uint32_t index = 0; index < p_module->descriptor_binding_count; ++index) {
+ const SpvReflectDescriptorBinding* p_potential = &p_module->descriptor_bindings[index];
+ bool found = SearchSortedUint32(
+ p_entry->used_uniforms,
+ p_entry->used_uniform_count,
+ p_potential->spirv_id);
+ if ((p_potential->binding == binding_number) && (p_potential->set == set_number) && found) {
+ p_descriptor = p_potential;
+ break;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_descriptor)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_descriptor;
+}
+
+const SpvReflectDescriptorSet* spvReflectGetDescriptorSet(
+ const SpvReflectShaderModule* p_module,
+ uint32_t set_number,
+ SpvReflectResult* p_result
+)
+{
+ const SpvReflectDescriptorSet* p_set = NULL;
+ if (IsNotNull(p_module)) {
+ for (uint32_t index = 0; index < p_module->descriptor_set_count; ++index) {
+ const SpvReflectDescriptorSet* p_potential = &p_module->descriptor_sets[index];
+ if (p_potential->set == set_number) {
+ p_set = p_potential;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_set)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_set;
+}
+
+const SpvReflectDescriptorSet* spvReflectGetEntryPointDescriptorSet(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t set_number,
+ SpvReflectResult* p_result)
+{
+ const SpvReflectDescriptorSet* p_set = NULL;
+ if (IsNotNull(p_module)) {
+ const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ for (uint32_t index = 0; index < p_entry->descriptor_set_count; ++index) {
+ const SpvReflectDescriptorSet* p_potential = &p_entry->descriptor_sets[index];
+ if (p_potential->set == set_number) {
+ p_set = p_potential;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_set)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_set;
+}
+
+
+const SpvReflectInterfaceVariable* spvReflectGetInputVariableByLocation(
+ const SpvReflectShaderModule* p_module,
+ uint32_t location,
+ SpvReflectResult* p_result
+)
+{
+ if (location == INVALID_VALUE) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ const SpvReflectInterfaceVariable* p_var = NULL;
+ if (IsNotNull(p_module)) {
+ for (uint32_t index = 0; index < p_module->input_variable_count; ++index) {
+ const SpvReflectInterfaceVariable* p_potential = &p_module->input_variables[index];
+ if (p_potential->location == location) {
+ p_var = p_potential;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_var)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_var;
+}
+const SpvReflectInterfaceVariable* spvReflectGetInputVariable(
+ const SpvReflectShaderModule* p_module,
+ uint32_t location,
+ SpvReflectResult* p_result
+)
+{
+ return spvReflectGetInputVariableByLocation(p_module, location, p_result);
+}
+
+const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableByLocation(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t location,
+ SpvReflectResult* p_result
+)
+{
+ if (location == INVALID_VALUE) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+
+ const SpvReflectInterfaceVariable* p_var = NULL;
+ if (IsNotNull(p_module)) {
+ const SpvReflectEntryPoint* p_entry =
+ spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ for (uint32_t index = 0; index < p_entry->input_variable_count; ++index) {
+ const SpvReflectInterfaceVariable* p_potential = &p_entry->input_variables[index];
+ if (p_potential->location == location) {
+ p_var = p_potential;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_var)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_var;
+}
+
+const SpvReflectInterfaceVariable* spvReflectGetInputVariableBySemantic(
+ const SpvReflectShaderModule* p_module,
+ const char* semantic,
+ SpvReflectResult* p_result
+)
+{
+ if (IsNull(semantic)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ return NULL;
+ }
+ if (semantic[0] == '\0') {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ const SpvReflectInterfaceVariable* p_var = NULL;
+ if (IsNotNull(p_module)) {
+ for (uint32_t index = 0; index < p_module->input_variable_count; ++index) {
+ const SpvReflectInterfaceVariable* p_potential = &p_module->input_variables[index];
+ if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) {
+ p_var = p_potential;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_var)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_var;
+}
+
+const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableBySemantic(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ const char* semantic,
+ SpvReflectResult* p_result
+)
+{
+ if (IsNull(semantic)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ return NULL;
+ }
+ if (semantic[0] == '\0') {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ const SpvReflectInterfaceVariable* p_var = NULL;
+ if (IsNotNull(p_module)) {
+ const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ for (uint32_t index = 0; index < p_entry->input_variable_count; ++index) {
+ const SpvReflectInterfaceVariable* p_potential = &p_entry->input_variables[index];
+ if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) {
+ p_var = p_potential;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_var)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_var;
+}
+
+const SpvReflectInterfaceVariable* spvReflectGetOutputVariableByLocation(
+ const SpvReflectShaderModule* p_module,
+ uint32_t location,
+ SpvReflectResult* p_result
+)
+{
+ if (location == INVALID_VALUE) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ const SpvReflectInterfaceVariable* p_var = NULL;
+ if (IsNotNull(p_module)) {
+ for (uint32_t index = 0; index < p_module->output_variable_count; ++index) {
+ const SpvReflectInterfaceVariable* p_potential = &p_module->output_variables[index];
+ if (p_potential->location == location) {
+ p_var = p_potential;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_var)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_var;
+}
+const SpvReflectInterfaceVariable* spvReflectGetOutputVariable(
+ const SpvReflectShaderModule* p_module,
+ uint32_t location,
+ SpvReflectResult* p_result
+)
+{
+ return spvReflectGetOutputVariableByLocation(p_module, location, p_result);
+}
+
+const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableByLocation(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t location,
+ SpvReflectResult* p_result
+)
+{
+ if (location == INVALID_VALUE) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+
+ const SpvReflectInterfaceVariable* p_var = NULL;
+ if (IsNotNull(p_module)) {
+ const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ for (uint32_t index = 0; index < p_entry->output_variable_count; ++index) {
+ const SpvReflectInterfaceVariable* p_potential = &p_entry->output_variables[index];
+ if (p_potential->location == location) {
+ p_var = p_potential;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_var)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_var;
+}
+
+const SpvReflectInterfaceVariable* spvReflectGetOutputVariableBySemantic(
+ const SpvReflectShaderModule* p_module,
+ const char* semantic,
+ SpvReflectResult* p_result
+)
+{
+ if (IsNull(semantic)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ return NULL;
+ }
+ if (semantic[0] == '\0') {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ const SpvReflectInterfaceVariable* p_var = NULL;
+ if (IsNotNull(p_module)) {
+ for (uint32_t index = 0; index < p_module->output_variable_count; ++index) {
+ const SpvReflectInterfaceVariable* p_potential = &p_module->output_variables[index];
+ if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) {
+ p_var = p_potential;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_var)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_var;
+}
+
+const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableBySemantic(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ const char* semantic,
+ SpvReflectResult* p_result)
+{
+ if (IsNull(semantic)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ return NULL;
+ }
+ if (semantic[0] == '\0') {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ const SpvReflectInterfaceVariable* p_var = NULL;
+ if (IsNotNull(p_module)) {
+ const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ for (uint32_t index = 0; index < p_entry->output_variable_count; ++index) {
+ const SpvReflectInterfaceVariable* p_potential = &p_entry->output_variables[index];
+ if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) {
+ p_var = p_potential;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_var)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_var;
+}
+
+const SpvReflectBlockVariable* spvReflectGetPushConstantBlock(
+ const SpvReflectShaderModule* p_module,
+ uint32_t index,
+ SpvReflectResult* p_result
+)
+{
+ const SpvReflectBlockVariable* p_push_constant = NULL;
+ if (IsNotNull(p_module)) {
+ if (index < p_module->push_constant_block_count) {
+ p_push_constant = &p_module->push_constant_blocks[index];
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_push_constant)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_push_constant;
+}
+const SpvReflectBlockVariable* spvReflectGetPushConstant(
+ const SpvReflectShaderModule* p_module,
+ uint32_t index,
+ SpvReflectResult* p_result
+)
+{
+ return spvReflectGetPushConstantBlock(p_module, index, p_result);
+}
+
+const SpvReflectBlockVariable* spvReflectGetEntryPointPushConstantBlock(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ SpvReflectResult* p_result)
+{
+ const SpvReflectBlockVariable* p_push_constant = NULL;
+ if (IsNotNull(p_module)) {
+ const SpvReflectEntryPoint* p_entry =
+ spvReflectGetEntryPoint(p_module, entry_point);
+ if (IsNull(p_entry)) {
+ if (IsNotNull(p_result)) {
+ *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+ }
+ return NULL;
+ }
+ for (uint32_t i = 0; i < p_module->push_constant_block_count; ++i) {
+ bool found = SearchSortedUint32(
+ p_entry->used_push_constants,
+ p_entry->used_push_constant_count,
+ p_module->push_constant_blocks[i].spirv_id);
+ if (found) {
+ p_push_constant = &p_module->push_constant_blocks[i];
+ break;
+ }
+ }
+ }
+ if (IsNotNull(p_result)) {
+ *p_result = IsNotNull(p_push_constant)
+ ? SPV_REFLECT_RESULT_SUCCESS
+ : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER
+ : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);
+ }
+ return p_push_constant;
+}
+
+SpvReflectResult spvReflectChangeDescriptorBindingNumbers(
+ SpvReflectShaderModule* p_module,
+ const SpvReflectDescriptorBinding* p_binding,
+ uint32_t new_binding_number,
+ uint32_t new_set_binding
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_binding)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+
+ SpvReflectDescriptorBinding* p_target_descriptor = NULL;
+ for (uint32_t index = 0; index < p_module->descriptor_binding_count; ++index) {
+ if(&p_module->descriptor_bindings[index] == p_binding) {
+ p_target_descriptor = &p_module->descriptor_bindings[index];
+ break;
+ }
+ }
+
+ if (IsNotNull(p_target_descriptor)) {
+ if (p_target_descriptor->word_offset.binding > (p_module->_internal->spirv_word_count - 1)) {
+ return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED;
+ }
+ // Binding number
+ if (new_binding_number != SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE) {
+ uint32_t* p_code = p_module->_internal->spirv_code + p_target_descriptor->word_offset.binding;
+ *p_code = new_binding_number;
+ p_target_descriptor->binding = new_binding_number;
+ }
+ // Set number
+ if (new_set_binding != SPV_REFLECT_SET_NUMBER_DONT_CHANGE) {
+ uint32_t* p_code = p_module->_internal->spirv_code + p_target_descriptor->word_offset.set;
+ *p_code = new_set_binding;
+ p_target_descriptor->set = new_set_binding;
+ }
+ }
+
+ SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS;
+ if (new_set_binding != SPV_REFLECT_SET_NUMBER_DONT_CHANGE) {
+ result = SynchronizeDescriptorSets(p_module);
+ }
+ return result;
+}
+SpvReflectResult spvReflectChangeDescriptorBindingNumber(
+ SpvReflectShaderModule* p_module,
+ const SpvReflectDescriptorBinding* p_descriptor_binding,
+ uint32_t new_binding_number,
+ uint32_t optional_new_set_number
+)
+{
+ return spvReflectChangeDescriptorBindingNumbers(
+ p_module,p_descriptor_binding,
+ new_binding_number,
+ optional_new_set_number);
+}
+
+SpvReflectResult spvReflectChangeDescriptorSetNumber(
+ SpvReflectShaderModule* p_module,
+ const SpvReflectDescriptorSet* p_set,
+ uint32_t new_set_number
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_set)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ SpvReflectDescriptorSet* p_target_set = NULL;
+ for (uint32_t index = 0; index < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++index) {
+ // The descriptor sets for specific entry points might not be in this set,
+ // so just match on set index.
+ if (p_module->descriptor_sets[index].set == p_set->set) {
+ p_target_set = (SpvReflectDescriptorSet*)p_set;
+ break;
+ }
+ }
+
+ SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS;
+ if (IsNotNull(p_target_set) && new_set_number != SPV_REFLECT_SET_NUMBER_DONT_CHANGE) {
+ for (uint32_t index = 0; index < p_target_set->binding_count; ++index) {
+ SpvReflectDescriptorBinding* p_descriptor = p_target_set->bindings[index];
+ if (p_descriptor->word_offset.set > (p_module->_internal->spirv_word_count - 1)) {
+ return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED;
+ }
+
+ uint32_t* p_code = p_module->_internal->spirv_code + p_descriptor->word_offset.set;
+ *p_code = new_set_number;
+ p_descriptor->set = new_set_number;
+ }
+
+ result = SynchronizeDescriptorSets(p_module);
+ }
+
+ return result;
+}
+
+static SpvReflectResult ChangeVariableLocation(
+ SpvReflectShaderModule* p_module,
+ SpvReflectInterfaceVariable* p_variable,
+ uint32_t new_location
+)
+{
+ if (p_variable->word_offset.location > (p_module->_internal->spirv_word_count - 1)) {
+ return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED;
+ }
+ uint32_t* p_code = p_module->_internal->spirv_code + p_variable->word_offset.location;
+ *p_code = new_location;
+ p_variable->location = new_location;
+ return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+SpvReflectResult spvReflectChangeInputVariableLocation(
+ SpvReflectShaderModule* p_module,
+ const SpvReflectInterfaceVariable* p_input_variable,
+ uint32_t new_location
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_input_variable)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ for (uint32_t index = 0; index < p_module->input_variable_count; ++index) {
+ if(&p_module->input_variables[index] == p_input_variable) {
+ return ChangeVariableLocation(p_module, &p_module->input_variables[index], new_location);
+ }
+ }
+ return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+}
+
+SpvReflectResult spvReflectChangeOutputVariableLocation(
+ SpvReflectShaderModule* p_module,
+ const SpvReflectInterfaceVariable* p_output_variable,
+ uint32_t new_location
+)
+{
+ if (IsNull(p_module)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ if (IsNull(p_output_variable)) {
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
+ }
+ for (uint32_t index = 0; index < p_module->output_variable_count; ++index) {
+ if(&p_module->output_variables[index] == p_output_variable) {
+ return ChangeVariableLocation(p_module, &p_module->output_variables[index], new_location);
+ }
+ }
+ return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;
+}
+
+const char* spvReflectSourceLanguage(SpvSourceLanguage source_lang)
+{
+ switch (source_lang) {
+ case SpvSourceLanguageUnknown : return "Unknown";
+ case SpvSourceLanguageESSL : return "ESSL";
+ case SpvSourceLanguageGLSL : return "GLSL";
+ case SpvSourceLanguageOpenCL_C : return "OpenCL_C";
+ case SpvSourceLanguageOpenCL_CPP : return "OpenCL_CPP";
+ case SpvSourceLanguageHLSL : return "HLSL";
+
+ case SpvSourceLanguageMax:
+ break;
+ }
+ return "";
+}
diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h
new file mode 100644
index 0000000000..6554aaa2cf
--- /dev/null
+++ b/thirdparty/spirv-reflect/spirv_reflect.h
@@ -0,0 +1,2045 @@
+/*
+ Copyright 2017-2018 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+
+VERSION HISTORY
+
+ 1.0 (2018-03-27) Initial public release
+
+*/
+
+/*!
+
+ @file spirv_reflect.h
+
+*/
+#ifndef SPIRV_REFLECT_H
+#define SPIRV_REFLECT_H
+
+#include "./include/spirv/unified1/spirv.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#ifdef _MSC_VER
+ #define SPV_REFLECT_DEPRECATED(msg_str) __declspec(deprecated("This symbol is deprecated. Details: " msg_str))
+#elif defined(__clang__)
+ #define SPV_REFLECT_DEPRECATED(msg_str) __attribute__((deprecated(msg_str)))
+#elif defined(__GNUC__)
+ #if GCC_VERSION >= 40500
+ #define SPV_REFLECT_DEPRECATED(msg_str) __attribute__((deprecated(msg_str)))
+ #else
+ #define SPV_REFLECT_DEPRECATED(msg_str) __attribute__((deprecated))
+ #endif
+#else
+ #define SPV_REFLECT_DEPRECATED(msg_str)
+#endif
+
+/*! @enum SpvReflectResult
+
+*/
+typedef enum SpvReflectResult {
+ SPV_REFLECT_RESULT_SUCCESS,
+ SPV_REFLECT_RESULT_NOT_READY,
+ SPV_REFLECT_RESULT_ERROR_PARSE_FAILED,
+ SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED,
+ SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED,
+ SPV_REFLECT_RESULT_ERROR_NULL_POINTER,
+ SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR,
+ SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH,
+ SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND,
+ SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE,
+ SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_MAGIC_NUMBER,
+ SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF,
+ SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE,
+ SPV_REFLECT_RESULT_ERROR_SPIRV_SET_NUMBER_OVERFLOW,
+ SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_STORAGE_CLASS,
+ SPV_REFLECT_RESULT_ERROR_SPIRV_RECURSION,
+ SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION,
+ SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA,
+ SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE,
+} SpvReflectResult;
+
+/*! @enum SpvReflectTypeFlagBits
+
+*/
+typedef enum SpvReflectTypeFlagBits {
+ SPV_REFLECT_TYPE_FLAG_UNDEFINED = 0x00000000,
+ SPV_REFLECT_TYPE_FLAG_VOID = 0x00000001,
+ SPV_REFLECT_TYPE_FLAG_BOOL = 0x00000002,
+ SPV_REFLECT_TYPE_FLAG_INT = 0x00000004,
+ SPV_REFLECT_TYPE_FLAG_FLOAT = 0x00000008,
+ SPV_REFLECT_TYPE_FLAG_VECTOR = 0x00000100,
+ SPV_REFLECT_TYPE_FLAG_MATRIX = 0x00000200,
+ SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE = 0x00010000,
+ SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER = 0x00020000,
+ SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE = 0x00040000,
+ SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK = 0x00080000,
+ SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK = 0x000F0000,
+ SPV_REFLECT_TYPE_FLAG_STRUCT = 0x10000000,
+ SPV_REFLECT_TYPE_FLAG_ARRAY = 0x20000000,
+} SpvReflectTypeFlagBits;
+
+typedef uint32_t SpvReflectTypeFlags;
+
+/*! @enum SpvReflectDecorationBits
+
+*/
+typedef enum SpvReflectDecorationFlagBits {
+ SPV_REFLECT_DECORATION_NONE = 0x00000000,
+ SPV_REFLECT_DECORATION_BLOCK = 0x00000001,
+ SPV_REFLECT_DECORATION_BUFFER_BLOCK = 0x00000002,
+ SPV_REFLECT_DECORATION_ROW_MAJOR = 0x00000004,
+ SPV_REFLECT_DECORATION_COLUMN_MAJOR = 0x00000008,
+ SPV_REFLECT_DECORATION_BUILT_IN = 0x00000010,
+ SPV_REFLECT_DECORATION_NOPERSPECTIVE = 0x00000020,
+ SPV_REFLECT_DECORATION_FLAT = 0x00000040,
+ SPV_REFLECT_DECORATION_NON_WRITABLE = 0x00000080,
+} SpvReflectDecorationFlagBits;
+
+typedef uint32_t SpvReflectDecorationFlags;
+
+/*! @enum SpvReflectResourceType
+
+*/
+typedef enum SpvReflectResourceType {
+ SPV_REFLECT_RESOURCE_FLAG_UNDEFINED = 0x00000000,
+ SPV_REFLECT_RESOURCE_FLAG_SAMPLER = 0x00000001,
+ SPV_REFLECT_RESOURCE_FLAG_CBV = 0x00000002,
+ SPV_REFLECT_RESOURCE_FLAG_SRV = 0x00000004,
+ SPV_REFLECT_RESOURCE_FLAG_UAV = 0x00000008,
+} SpvReflectResourceType;
+
+/*! @enum SpvReflectFormat
+
+*/
+typedef enum SpvReflectFormat {
+ SPV_REFLECT_FORMAT_UNDEFINED = 0, // = VK_FORMAT_UNDEFINED
+ SPV_REFLECT_FORMAT_R32_UINT = 98, // = VK_FORMAT_R32_UINT
+ SPV_REFLECT_FORMAT_R32_SINT = 99, // = VK_FORMAT_R32_SINT
+ SPV_REFLECT_FORMAT_R32_SFLOAT = 100, // = VK_FORMAT_R32_SFLOAT
+ SPV_REFLECT_FORMAT_R32G32_UINT = 101, // = VK_FORMAT_R32G32_UINT
+ SPV_REFLECT_FORMAT_R32G32_SINT = 102, // = VK_FORMAT_R32G32_SINT
+ SPV_REFLECT_FORMAT_R32G32_SFLOAT = 103, // = VK_FORMAT_R32G32_SFLOAT
+ SPV_REFLECT_FORMAT_R32G32B32_UINT = 104, // = VK_FORMAT_R32G32B32_UINT
+ SPV_REFLECT_FORMAT_R32G32B32_SINT = 105, // = VK_FORMAT_R32G32B32_SINT
+ SPV_REFLECT_FORMAT_R32G32B32_SFLOAT = 106, // = VK_FORMAT_R32G32B32_SFLOAT
+ SPV_REFLECT_FORMAT_R32G32B32A32_UINT = 107, // = VK_FORMAT_R32G32B32A32_UINT
+ SPV_REFLECT_FORMAT_R32G32B32A32_SINT = 108, // = VK_FORMAT_R32G32B32A32_SINT
+ SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT = 109, // = VK_FORMAT_R32G32B32A32_SFLOAT
+} SpvReflectFormat;
+
+/*! @enum SpvReflectVariableFlagBits
+
+*/
+enum SpvReflectVariableFlagBits{
+ SPV_REFLECT_VARIABLE_FLAGS_NONE = 0x00000000,
+ SPV_REFLECT_VARIABLE_FLAGS_UNUSED = 0x00000001,
+};
+
+typedef uint32_t SpvReflectVariableFlags;
+
+/*! @enum SpvReflectDescriptorType
+
+*/
+typedef enum SpvReflectDescriptorType {
+ SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER = 0, // = VK_DESCRIPTOR_TYPE_SAMPLER
+ SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, // = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
+ SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2, // = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
+ SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3, // = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
+ SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4, // = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
+ SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5, // = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
+ SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6, // = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
+ SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7, // = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
+ SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, // = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
+ SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, // = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
+ SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, // = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
+} SpvReflectDescriptorType;
+
+/*! @enum SpvReflectShaderStageFlagBits
+
+*/
+typedef enum SpvReflectShaderStageFlagBits {
+ SPV_REFLECT_SHADER_STAGE_VERTEX_BIT = 0x00000001, // = VK_SHADER_STAGE_VERTEX_BIT
+ SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002, // = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
+ SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004, // = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT
+ SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT = 0x00000008, // = VK_SHADER_STAGE_GEOMETRY_BIT
+ SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT = 0x00000010, // = VK_SHADER_STAGE_FRAGMENT_BIT
+ SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT = 0x00000020, // = VK_SHADER_STAGE_COMPUTE_BIT
+} SpvReflectShaderStageFlagBits;
+
+/*! @enum SpvReflectGenerator
+
+*/
+typedef enum SpvReflectGenerator {
+ SPV_REFLECT_GENERATOR_KHRONOS_LLVM_SPIRV_TRANSLATOR = 6,
+ SPV_REFLECT_GENERATOR_KHRONOS_SPIRV_TOOLS_ASSEMBLER = 7,
+ SPV_REFLECT_GENERATOR_KHRONOS_GLSLANG_REFERENCE_FRONT_END = 8,
+ SPV_REFLECT_GENERATOR_GOOGLE_SHADERC_OVER_GLSLANG = 13,
+ SPV_REFLECT_GENERATOR_GOOGLE_SPIREGG = 14,
+ SPV_REFLECT_GENERATOR_GOOGLE_RSPIRV = 15,
+ SPV_REFLECT_GENERATOR_X_LEGEND_MESA_MESAIR_SPIRV_TRANSLATOR = 16,
+ SPV_REFLECT_GENERATOR_KHRONOS_SPIRV_TOOLS_LINKER = 17,
+ SPV_REFLECT_GENERATOR_WINE_VKD3D_SHADER_COMPILER = 18,
+ SPV_REFLECT_GENERATOR_CLAY_CLAY_SHADER_COMPILER = 19,
+} SpvReflectGenerator;
+
+enum {
+ SPV_REFLECT_MAX_ARRAY_DIMS = 32,
+ SPV_REFLECT_MAX_DESCRIPTOR_SETS = 64,
+};
+
+enum {
+ SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE = ~0,
+ SPV_REFLECT_SET_NUMBER_DONT_CHANGE = ~0
+};
+
+typedef struct SpvReflectNumericTraits {
+ struct Scalar {
+ uint32_t width;
+ uint32_t signedness;
+ } scalar;
+
+ struct Vector {
+ uint32_t component_count;
+ } vector;
+
+ struct Matrix {
+ uint32_t column_count;
+ uint32_t row_count;
+ uint32_t stride; // Measured in bytes
+ } matrix;
+} SpvReflectNumericTraits;
+
+typedef struct SpvReflectImageTraits {
+ SpvDim dim;
+ uint32_t depth;
+ uint32_t arrayed;
+ uint32_t ms; // 0: single-sampled; 1: multisampled
+ uint32_t sampled;
+ SpvImageFormat image_format;
+} SpvReflectImageTraits;
+
+typedef struct SpvReflectArrayTraits {
+ uint32_t dims_count;
+ uint32_t dims[SPV_REFLECT_MAX_ARRAY_DIMS];
+ uint32_t stride; // Measured in bytes
+} SpvReflectArrayTraits;
+
+typedef struct SpvReflectBindingArrayTraits {
+ uint32_t dims_count;
+ uint32_t dims[SPV_REFLECT_MAX_ARRAY_DIMS];
+} SpvReflectBindingArrayTraits;
+
+/*! @struct SpvReflectTypeDescription
+
+*/
+typedef struct SpvReflectTypeDescription {
+ uint32_t id;
+ SpvOp op;
+ const char* type_name;
+ const char* struct_member_name;
+ SpvStorageClass storage_class;
+ SpvReflectTypeFlags type_flags;
+ SpvReflectDecorationFlags decoration_flags;
+
+ struct Traits {
+ SpvReflectNumericTraits numeric;
+ SpvReflectImageTraits image;
+ SpvReflectArrayTraits array;
+ } traits;
+
+ uint32_t member_count;
+ struct SpvReflectTypeDescription* members;
+} SpvReflectTypeDescription;
+
+
+/*! @struct SpvReflectInterfaceVariable
+
+*/
+typedef struct SpvReflectInterfaceVariable {
+ uint32_t spirv_id;
+ const char* name;
+ uint32_t location;
+ SpvStorageClass storage_class;
+ const char* semantic;
+ SpvReflectDecorationFlags decoration_flags;
+ SpvBuiltIn built_in;
+ SpvReflectNumericTraits numeric;
+ SpvReflectArrayTraits array;
+
+ uint32_t member_count;
+ struct SpvReflectInterfaceVariable* members;
+
+ SpvReflectFormat format;
+
+ // NOTE: SPIR-V shares type references for variables
+ // that have the same underlying type. This means
+ // that the same type name will appear for multiple
+ // variables.
+ SpvReflectTypeDescription* type_description;
+
+ struct {
+ uint32_t location;
+ } word_offset;
+} SpvReflectInterfaceVariable;
+
+/*! @struct SpvReflectBlockVariable
+
+*/
+typedef struct SpvReflectBlockVariable {
+ uint32_t spirv_id;
+ const char* name;
+ uint32_t offset; // Measured in bytes
+ uint32_t absolute_offset; // Measured in bytes
+ uint32_t size; // Measured in bytes
+ uint32_t padded_size; // Measured in bytes
+ SpvReflectDecorationFlags decoration_flags;
+ SpvReflectNumericTraits numeric;
+ SpvReflectArrayTraits array;
+ SpvReflectVariableFlags flags;
+
+ uint32_t member_count;
+ struct SpvReflectBlockVariable* members;
+
+ SpvReflectTypeDescription* type_description;
+} SpvReflectBlockVariable;
+
+/*! @struct SpvReflectDescriptorBinding
+
+*/
+typedef struct SpvReflectDescriptorBinding {
+ uint32_t spirv_id;
+ const char* name;
+ uint32_t binding;
+ uint32_t input_attachment_index;
+ uint32_t set;
+ SpvReflectDescriptorType descriptor_type;
+ SpvReflectResourceType resource_type;
+ SpvReflectImageTraits image;
+ SpvReflectBlockVariable block;
+ SpvReflectBindingArrayTraits array;
+ uint32_t count;
+ uint32_t accessed;
+ uint32_t uav_counter_id;
+ struct SpvReflectDescriptorBinding* uav_counter_binding;
+
+ SpvReflectTypeDescription* type_description;
+
+ struct {
+ uint32_t binding;
+ uint32_t set;
+ } word_offset;
+} SpvReflectDescriptorBinding;
+
+/*! @struct SpvReflectDescriptorSet
+
+*/
+typedef struct SpvReflectDescriptorSet {
+ uint32_t set;
+ uint32_t binding_count;
+ SpvReflectDescriptorBinding** bindings;
+} SpvReflectDescriptorSet;
+
+/*! @struct SpvReflectEntryPoint
+
+ */
+typedef struct SpvReflectEntryPoint {
+ const char* name;
+ uint32_t id;
+
+ SpvExecutionModel spirv_execution_model;
+ SpvReflectShaderStageFlagBits shader_stage;
+
+ uint32_t input_variable_count;
+ SpvReflectInterfaceVariable* input_variables;
+ uint32_t output_variable_count;
+ SpvReflectInterfaceVariable* output_variables;
+
+ uint32_t descriptor_set_count;
+ SpvReflectDescriptorSet* descriptor_sets;
+
+ uint32_t used_uniform_count;
+ uint32_t* used_uniforms;
+ uint32_t used_push_constant_count;
+ uint32_t* used_push_constants;
+} SpvReflectEntryPoint;
+
+/*! @struct SpvReflectShaderModule
+
+*/
+typedef struct SpvReflectShaderModule {
+ SpvReflectGenerator generator;
+ const char* entry_point_name;
+ uint32_t entry_point_id;
+ uint32_t entry_point_count;
+ SpvReflectEntryPoint* entry_points;
+ SpvSourceLanguage source_language;
+ uint32_t source_language_version;
+ const char* source_file;
+ const char* source_source;
+ SpvExecutionModel spirv_execution_model;
+ SpvReflectShaderStageFlagBits shader_stage;
+ uint32_t descriptor_binding_count;
+ SpvReflectDescriptorBinding* descriptor_bindings;
+ uint32_t descriptor_set_count;
+ SpvReflectDescriptorSet descriptor_sets[SPV_REFLECT_MAX_DESCRIPTOR_SETS];
+ uint32_t input_variable_count;
+ SpvReflectInterfaceVariable* input_variables;
+ uint32_t output_variable_count;
+ SpvReflectInterfaceVariable* output_variables;
+ uint32_t push_constant_block_count;
+ SpvReflectBlockVariable* push_constant_blocks;
+
+ struct Internal {
+ size_t spirv_size;
+ uint32_t* spirv_code;
+ uint32_t spirv_word_count;
+
+ size_t type_description_count;
+ SpvReflectTypeDescription* type_descriptions;
+ } * _internal;
+
+} SpvReflectShaderModule;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*! @fn spvReflectCreateShaderModule
+
+ @param size Size in bytes of SPIR-V code.
+ @param p_code Pointer to SPIR-V code.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @return SPV_REFLECT_RESULT_SUCCESS on success.
+
+*/
+SpvReflectResult spvReflectCreateShaderModule(
+ size_t size,
+ const void* p_code,
+ SpvReflectShaderModule* p_module
+);
+
+SPV_REFLECT_DEPRECATED("renamed to spvReflectCreateShaderModule")
+SpvReflectResult spvReflectGetShaderModule(
+ size_t size,
+ const void* p_code,
+ SpvReflectShaderModule* p_module
+);
+
+
+/*! @fn spvReflectDestroyShaderModule
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+
+*/
+void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module);
+
+
+/*! @fn spvReflectGetCodeSize
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @return Returns the size of the SPIR-V in bytes
+
+*/
+uint32_t spvReflectGetCodeSize(const SpvReflectShaderModule* p_module);
+
+
+/*! @fn spvReflectGetCode
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @return Returns a const pointer to the compiled SPIR-V bytecode.
+
+*/
+const uint32_t* spvReflectGetCode(const SpvReflectShaderModule* p_module);
+
+/*! @fn spvReflectGetEntryPoint
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point Name of the requested entry point.
+ @return Returns a const pointer to the requested entry point,
+ or NULL if it's not found.
+*/
+const SpvReflectEntryPoint* spvReflectGetEntryPoint(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point
+);
+
+/*! @fn spvReflectEnumerateDescriptorBindings
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_count If pp_bindings is NULL, the module's descriptor binding
+ count (across all descriptor sets) will be stored here.
+ If pp_bindings is not NULL, *p_count must contain the
+ module's descriptor binding count.
+ @param pp_bindings If NULL, the module's total descriptor binding count
+ will be written to *p_count.
+ If non-NULL, pp_bindings must point to an array with
+ *p_count entries, where pointers to the module's
+ descriptor bindings will be written. The caller must not
+ free the binding pointers written to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumerateDescriptorBindings(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectDescriptorBinding** pp_bindings
+);
+
+/*! @fn spvReflectEnumerateEntryPointDescriptorBindings
+ @brief Creates a listing of all descriptor bindings that are used in the
+ static call tree of the given entry point.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point The name of the entry point to get the descriptor bindings for.
+ @param p_count If pp_bindings is NULL, the entry point's descriptor binding
+ count (across all descriptor sets) will be stored here.
+ If pp_bindings is not NULL, *p_count must contain the
+ entry points's descriptor binding count.
+ @param pp_bindings If NULL, the entry point's total descriptor binding count
+ will be written to *p_count.
+ If non-NULL, pp_bindings must point to an array with
+ *p_count entries, where pointers to the entry point's
+ descriptor bindings will be written. The caller must not
+ free the binding pointers written to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumerateEntryPointDescriptorBindings(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectDescriptorBinding** pp_bindings
+);
+
+/*! @fn spvReflectEnumerateDescriptorSets
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_count If pp_sets is NULL, the module's descriptor set
+ count will be stored here.
+ If pp_sets is not NULL, *p_count must contain the
+ module's descriptor set count.
+ @param pp_sets If NULL, the module's total descriptor set count
+ will be written to *p_count.
+ If non-NULL, pp_sets must point to an array with
+ *p_count entries, where pointers to the module's
+ descriptor sets will be written. The caller must not
+ free the descriptor set pointers written to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumerateDescriptorSets(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectDescriptorSet** pp_sets
+);
+
+/*! @fn spvReflectEnumerateEntryPointDescriptorSets
+ @brief Creates a listing of all descriptor sets and their bindings that are
+ used in the static call tree of a given entry point.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point The name of the entry point to get the descriptor bindings for.
+ @param p_count If pp_sets is NULL, the module's descriptor set
+ count will be stored here.
+ If pp_sets is not NULL, *p_count must contain the
+ module's descriptor set count.
+ @param pp_sets If NULL, the module's total descriptor set count
+ will be written to *p_count.
+ If non-NULL, pp_sets must point to an array with
+ *p_count entries, where pointers to the module's
+ descriptor sets will be written. The caller must not
+ free the descriptor set pointers written to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumerateEntryPointDescriptorSets(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectDescriptorSet** pp_sets
+);
+
+
+/*! @fn spvReflectEnumerateInputVariables
+ @brief If the module contains multiple entry points, this will only get
+ the input variables for the first one.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_count If pp_variables is NULL, the module's input variable
+ count will be stored here.
+ If pp_variables is not NULL, *p_count must contain
+ the module's input variable count.
+ @param pp_variables If NULL, the module's input variable count will be
+ written to *p_count.
+ If non-NULL, pp_variables must point to an array with
+ *p_count entries, where pointers to the module's
+ input variables will be written. The caller must not
+ free the interface variables written to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumerateInputVariables(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+);
+
+/*! @fn spvReflectEnumerateEntryPointInputVariables
+ @brief Enumerate the input variables for a given entry point.
+ @param entry_point The name of the entry point to get the input variables for.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_count If pp_variables is NULL, the entry point's input variable
+ count will be stored here.
+ If pp_variables is not NULL, *p_count must contain
+ the entry point's input variable count.
+ @param pp_variables If NULL, the entry point's input variable count will be
+ written to *p_count.
+ If non-NULL, pp_variables must point to an array with
+ *p_count entries, where pointers to the entry point's
+ input variables will be written. The caller must not
+ free the interface variables written to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumerateEntryPointInputVariables(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+);
+
+
+/*! @fn spvReflectEnumerateOutputVariables
+ @brief Note: If the module contains multiple entry points, this will only get
+ the output variables for the first one.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_count If pp_variables is NULL, the module's output variable
+ count will be stored here.
+ If pp_variables is not NULL, *p_count must contain
+ the module's output variable count.
+ @param pp_variables If NULL, the module's output variable count will be
+ written to *p_count.
+ If non-NULL, pp_variables must point to an array with
+ *p_count entries, where pointers to the module's
+ output variables will be written. The caller must not
+ free the interface variables written to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumerateOutputVariables(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+);
+
+/*! @fn spvReflectEnumerateEntryPointOutputVariables
+ @brief Enumerate the output variables for a given entry point.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point The name of the entry point to get the output variables for.
+ @param p_count If pp_variables is NULL, the entry point's output variable
+ count will be stored here.
+ If pp_variables is not NULL, *p_count must contain
+ the entry point's output variable count.
+ @param pp_variables If NULL, the entry point's output variable count will be
+ written to *p_count.
+ If non-NULL, pp_variables must point to an array with
+ *p_count entries, where pointers to the entry point's
+ output variables will be written. The caller must not
+ free the interface variables written to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumerateEntryPointOutputVariables(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+);
+
+
+/*! @fn spvReflectEnumeratePushConstantBlocks
+ @brief Note: If the module contains multiple entry points, this will only get
+ the push constant blocks for the first one.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_count If pp_blocks is NULL, the module's push constant
+ block count will be stored here.
+ If pp_blocks is not NULL, *p_count must
+ contain the module's push constant block count.
+ @param pp_blocks If NULL, the module's push constant block count
+ will be written to *p_count.
+ If non-NULL, pp_blocks must point to an
+ array with *p_count entries, where pointers to
+ the module's push constant blocks will be written.
+ The caller must not free the block variables written
+ to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumeratePushConstantBlocks(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectBlockVariable** pp_blocks
+);
+SPV_REFLECT_DEPRECATED("renamed to spvReflectEnumeratePushConstantBlocks")
+SpvReflectResult spvReflectEnumeratePushConstants(
+ const SpvReflectShaderModule* p_module,
+ uint32_t* p_count,
+ SpvReflectBlockVariable** pp_blocks
+);
+
+/*! @fn spvReflectEnumerateEntryPointPushConstantBlocks
+ @brief Enumerate the push constant blocks used in the static call tree of a
+ given entry point.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_count If pp_blocks is NULL, the entry point's push constant
+ block count will be stored here.
+ If pp_blocks is not NULL, *p_count must
+ contain the entry point's push constant block count.
+ @param pp_blocks If NULL, the entry point's push constant block count
+ will be written to *p_count.
+ If non-NULL, pp_blocks must point to an
+ array with *p_count entries, where pointers to
+ the entry point's push constant blocks will be written.
+ The caller must not free the block variables written
+ to this array.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of the
+ failure.
+
+*/
+SpvReflectResult spvReflectEnumerateEntryPointPushConstantBlocks(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectBlockVariable** pp_blocks
+);
+
+
+/*! @fn spvReflectGetDescriptorBinding
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param binding_number The "binding" value of the requested descriptor
+ binding.
+ @param set_number The "set" value of the requested descriptor binding.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the module contains a descriptor binding that
+ matches the provided [binding_number, set_number]
+ values, a pointer to that binding is returned. The
+ caller must not free this pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+@note If the module contains multiple desriptor bindings
+ with the same set and binding numbers, there are
+ no guarantees about which binding will be returned.
+
+*/
+const SpvReflectDescriptorBinding* spvReflectGetDescriptorBinding(
+ const SpvReflectShaderModule* p_module,
+ uint32_t binding_number,
+ uint32_t set_number,
+ SpvReflectResult* p_result
+);
+
+/*! @fn spvReflectGetEntryPointDescriptorBinding
+ @brief Get the descriptor binding with the given binding number and set
+ number that is used in the static call tree of a certain entry
+ point.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point The entry point to get the binding from.
+ @param binding_number The "binding" value of the requested descriptor
+ binding.
+ @param set_number The "set" value of the requested descriptor binding.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the entry point contains a descriptor binding that
+ matches the provided [binding_number, set_number]
+ values, a pointer to that binding is returned. The
+ caller must not free this pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+@note If the entry point contains multiple desriptor bindings
+ with the same set and binding numbers, there are
+ no guarantees about which binding will be returned.
+
+*/
+const SpvReflectDescriptorBinding* spvReflectGetEntryPointDescriptorBinding(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t binding_number,
+ uint32_t set_number,
+ SpvReflectResult* p_result
+);
+
+
+/*! @fn spvReflectGetDescriptorSet
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param set_number The "set" value of the requested descriptor set.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the module contains a descriptor set with the
+ provided set_number, a pointer to that set is
+ returned. The caller must not free this pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+
+*/
+const SpvReflectDescriptorSet* spvReflectGetDescriptorSet(
+ const SpvReflectShaderModule* p_module,
+ uint32_t set_number,
+ SpvReflectResult* p_result
+);
+
+/*! @fn spvReflectGetEntryPointDescriptorSet
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point The entry point to get the descriptor set from.
+ @param set_number The "set" value of the requested descriptor set.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the entry point contains a descriptor set with the
+ provided set_number, a pointer to that set is
+ returned. The caller must not free this pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+
+*/
+const SpvReflectDescriptorSet* spvReflectGetEntryPointDescriptorSet(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t set_number,
+ SpvReflectResult* p_result
+);
+
+
+/* @fn spvReflectGetInputVariableByLocation
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param location The "location" value of the requested input variable.
+ A location of 0xFFFFFFFF will always return NULL
+ with *p_result == ELEMENT_NOT_FOUND.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the module contains an input interface variable
+ with the provided location value, a pointer to that
+ variable is returned. The caller must not free this
+ pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+@note
+
+*/
+const SpvReflectInterfaceVariable* spvReflectGetInputVariableByLocation(
+ const SpvReflectShaderModule* p_module,
+ uint32_t location,
+ SpvReflectResult* p_result
+);
+SPV_REFLECT_DEPRECATED("renamed to spvReflectGetInputVariableByLocation")
+const SpvReflectInterfaceVariable* spvReflectGetInputVariable(
+ const SpvReflectShaderModule* p_module,
+ uint32_t location,
+ SpvReflectResult* p_result
+);
+
+/* @fn spvReflectGetEntryPointInputVariableByLocation
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point The entry point to get the input variable from.
+ @param location The "location" value of the requested input variable.
+ A location of 0xFFFFFFFF will always return NULL
+ with *p_result == ELEMENT_NOT_FOUND.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the entry point contains an input interface variable
+ with the provided location value, a pointer to that
+ variable is returned. The caller must not free this
+ pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+@note
+
+*/
+const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableByLocation(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t location,
+ SpvReflectResult* p_result
+);
+
+/* @fn spvReflectGetInputVariableBySemantic
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param semantic The "semantic" value of the requested input variable.
+ A semantic of NULL will return NULL.
+ A semantic of "" will always return NULL with
+ *p_result == ELEMENT_NOT_FOUND.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the module contains an input interface variable
+ with the provided semantic, a pointer to that
+ variable is returned. The caller must not free this
+ pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+@note
+
+*/
+const SpvReflectInterfaceVariable* spvReflectGetInputVariableBySemantic(
+ const SpvReflectShaderModule* p_module,
+ const char* semantic,
+ SpvReflectResult* p_result
+);
+
+/* @fn spvReflectGetEntryPointInputVariableBySemantic
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point The entry point to get the input variable from.
+ @param semantic The "semantic" value of the requested input variable.
+ A semantic of NULL will return NULL.
+ A semantic of "" will always return NULL with
+ *p_result == ELEMENT_NOT_FOUND.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the entry point contains an input interface variable
+ with the provided semantic, a pointer to that
+ variable is returned. The caller must not free this
+ pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+@note
+
+*/
+const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableBySemantic(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ const char* semantic,
+ SpvReflectResult* p_result
+);
+
+/* @fn spvReflectGetOutputVariableByLocation
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param location The "location" value of the requested output variable.
+ A location of 0xFFFFFFFF will always return NULL
+ with *p_result == ELEMENT_NOT_FOUND.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the module contains an output interface variable
+ with the provided location value, a pointer to that
+ variable is returned. The caller must not free this
+ pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+@note
+
+*/
+const SpvReflectInterfaceVariable* spvReflectGetOutputVariableByLocation(
+ const SpvReflectShaderModule* p_module,
+ uint32_t location,
+ SpvReflectResult* p_result
+);
+SPV_REFLECT_DEPRECATED("renamed to spvReflectGetOutputVariableByLocation")
+const SpvReflectInterfaceVariable* spvReflectGetOutputVariable(
+ const SpvReflectShaderModule* p_module,
+ uint32_t location,
+ SpvReflectResult* p_result
+);
+
+/* @fn spvReflectGetEntryPointOutputVariableByLocation
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point The entry point to get the output variable from.
+ @param location The "location" value of the requested output variable.
+ A location of 0xFFFFFFFF will always return NULL
+ with *p_result == ELEMENT_NOT_FOUND.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the entry point contains an output interface variable
+ with the provided location value, a pointer to that
+ variable is returned. The caller must not free this
+ pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+@note
+
+*/
+const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableByLocation(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ uint32_t location,
+ SpvReflectResult* p_result
+);
+
+/* @fn spvReflectGetOutputVariableBySemantic
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param semantic The "semantic" value of the requested output variable.
+ A semantic of NULL will return NULL.
+ A semantic of "" will always return NULL with
+ *p_result == ELEMENT_NOT_FOUND.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the module contains an output interface variable
+ with the provided semantic, a pointer to that
+ variable is returned. The caller must not free this
+ pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+@note
+
+*/
+const SpvReflectInterfaceVariable* spvReflectGetOutputVariableBySemantic(
+ const SpvReflectShaderModule* p_module,
+ const char* semantic,
+ SpvReflectResult* p_result
+);
+
+/* @fn spvReflectGetEntryPointOutputVariableBySemantic
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point The entry point to get the output variable from.
+ @param semantic The "semantic" value of the requested output variable.
+ A semantic of NULL will return NULL.
+ A semantic of "" will always return NULL with
+ *p_result == ELEMENT_NOT_FOUND.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the entry point contains an output interface variable
+ with the provided semantic, a pointer to that
+ variable is returned. The caller must not free this
+ pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+@note
+
+*/
+const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableBySemantic(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ const char* semantic,
+ SpvReflectResult* p_result
+);
+
+/*! @fn spvReflectGetPushConstantBlock
+
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param index The index of the desired block within the module's
+ array of push constant blocks.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the provided index is within range, a pointer to
+ the corresponding push constant block is returned.
+ The caller must not free this pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+
+*/
+const SpvReflectBlockVariable* spvReflectGetPushConstantBlock(
+ const SpvReflectShaderModule* p_module,
+ uint32_t index,
+ SpvReflectResult* p_result
+);
+SPV_REFLECT_DEPRECATED("renamed to spvReflectGetPushConstantBlock")
+const SpvReflectBlockVariable* spvReflectGetPushConstant(
+ const SpvReflectShaderModule* p_module,
+ uint32_t index,
+ SpvReflectResult* p_result
+);
+
+/*! @fn spvReflectGetEntryPointPushConstantBlock
+ @brief Get the push constant block corresponding to the given entry point.
+ As by the Vulkan specification there can be no more than one push
+ constant block used by a given entry point, so if there is one it will
+ be returned, otherwise NULL will be returned.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param entry_point The entry point to get the push constant block from.
+ @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be
+ written to *p_result. Otherwise, a error code
+ indicating the cause of the failure will be stored
+ here.
+ @return If the provided index is within range, a pointer to
+ the corresponding push constant block is returned.
+ The caller must not free this pointer.
+ If no match can be found, or if an unrelated error
+ occurs, the return value will be NULL. Detailed
+ error results are written to *pResult.
+
+*/
+const SpvReflectBlockVariable* spvReflectGetEntryPointPushConstantBlock(
+ const SpvReflectShaderModule* p_module,
+ const char* entry_point,
+ SpvReflectResult* p_result
+);
+
+
+/*! @fn spvReflectChangeDescriptorBindingNumbers
+ @brief Assign new set and/or binding numbers to a descriptor binding.
+ In addition to updating the reflection data, this function modifies
+ the underlying SPIR-V bytecode. The updated code can be retrieved
+ with spvReflectGetCode(). If the binding is used in multiple
+ entry points within the module, it will be changed in all of them.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_binding Pointer to the descriptor binding to modify.
+ @param new_binding_number The new binding number to assign to the
+ provided descriptor binding.
+ To leave the binding number unchanged, pass
+ SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE.
+ @param new_set_number The new set number to assign to the
+ provided descriptor binding. Successfully changing
+ a descriptor binding's set number invalidates all
+ existing SpvReflectDescriptorBinding and
+ SpvReflectDescriptorSet pointers from this module.
+ To leave the set number unchanged, pass
+ SPV_REFLECT_SET_NUMBER_DONT_CHANGE.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of
+ the failure.
+*/
+SpvReflectResult spvReflectChangeDescriptorBindingNumbers(
+ SpvReflectShaderModule* p_module,
+ const SpvReflectDescriptorBinding* p_binding,
+ uint32_t new_binding_number,
+ uint32_t new_set_number
+);
+SPV_REFLECT_DEPRECATED("Renamed to spvReflectChangeDescriptorBindingNumbers")
+SpvReflectResult spvReflectChangeDescriptorBindingNumber(
+ SpvReflectShaderModule* p_module,
+ const SpvReflectDescriptorBinding* p_descriptor_binding,
+ uint32_t new_binding_number,
+ uint32_t optional_new_set_number
+);
+
+/*! @fn spvReflectChangeDescriptorSetNumber
+ @brief Assign a new set number to an entire descriptor set (including
+ all descriptor bindings in that set).
+ In addition to updating the reflection data, this function modifies
+ the underlying SPIR-V bytecode. The updated code can be retrieved
+ with spvReflectGetCode(). If the descriptor set is used in
+ multiple entry points within the module, it will be modified in all
+ of them.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_set Pointer to the descriptor binding to modify.
+ @param new_set_number The new set number to assign to the
+ provided descriptor set, and all its descriptor
+ bindings. Successfully changing a descriptor
+ binding's set number invalidates all existing
+ SpvReflectDescriptorBinding and
+ SpvReflectDescriptorSet pointers from this module.
+ To leave the set number unchanged, pass
+ SPV_REFLECT_SET_NUMBER_DONT_CHANGE.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of
+ the failure.
+*/
+SpvReflectResult spvReflectChangeDescriptorSetNumber(
+ SpvReflectShaderModule* p_module,
+ const SpvReflectDescriptorSet* p_set,
+ uint32_t new_set_number
+);
+
+/*! @fn spvReflectChangeInputVariableLocation
+ @brief Assign a new location to an input interface variable.
+ In addition to updating the reflection data, this function modifies
+ the underlying SPIR-V bytecode. The updated code can be retrieved
+ with spvReflectGetCode().
+ It is the caller's responsibility to avoid assigning the same
+ location to multiple input variables. If the input variable is used
+ by multiple entry points in the module, it will be changed in all of
+ them.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_input_variable Pointer to the input variable to update.
+ @param new_location The new location to assign to p_input_variable.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of
+ the failure.
+
+*/
+SpvReflectResult spvReflectChangeInputVariableLocation(
+ SpvReflectShaderModule* p_module,
+ const SpvReflectInterfaceVariable* p_input_variable,
+ uint32_t new_location
+);
+
+
+/*! @fn spvReflectChangeOutputVariableLocation
+ @brief Assign a new location to an output interface variable.
+ In addition to updating the reflection data, this function modifies
+ the underlying SPIR-V bytecode. The updated code can be retrieved
+ with spvReflectGetCode().
+ It is the caller's responsibility to avoid assigning the same
+ location to multiple output variables. If the output variable is used
+ by multiple entry points in the module, it will be changed in all of
+ them.
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
+ @param p_output_variable Pointer to the output variable to update.
+ @param new_location The new location to assign to p_output_variable.
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+ Otherwise, the error code indicates the cause of
+ the failure.
+
+*/
+SpvReflectResult spvReflectChangeOutputVariableLocation(
+ SpvReflectShaderModule* p_module,
+ const SpvReflectInterfaceVariable* p_output_variable,
+ uint32_t new_location
+);
+
+
+/*! @fn spvReflectSourceLanguage
+
+ @param source_lang The source language code.
+ @return Returns string of source language specified in \a source_lang.
+ The caller must not free the memory associated with this string.
+*/
+const char* spvReflectSourceLanguage(SpvSourceLanguage source_lang);
+
+#if defined(__cplusplus)
+};
+#endif
+
+#if defined(__cplusplus)
+#include <cstdlib>
+#include <string>
+#include <vector>
+
+namespace spv_reflect {
+
+/*! \class ShaderModule
+
+*/
+class ShaderModule {
+public:
+ ShaderModule();
+ ShaderModule(size_t size, const void* p_code);
+ ShaderModule(const std::vector<uint8_t>& code);
+ ShaderModule(const std::vector<uint32_t>& code);
+ ~ShaderModule();
+
+ SpvReflectResult GetResult() const;
+
+ const SpvReflectShaderModule& GetShaderModule() const;
+
+ uint32_t GetCodeSize() const;
+ const uint32_t* GetCode() const;
+
+ const char* GetEntryPointName() const;
+
+ const char* GetSourceFile() const;
+
+ uint32_t GetEntryPointCount() const;
+ const char* GetEntryPointName(uint32_t index) const;
+
+ SpvReflectShaderStageFlagBits GetShaderStage() const;
+ SPV_REFLECT_DEPRECATED("Renamed to GetShaderStage")
+ SpvReflectShaderStageFlagBits GetVulkanShaderStage() const {
+ return GetShaderStage();
+ }
+
+ SpvReflectResult EnumerateDescriptorBindings(uint32_t* p_count, SpvReflectDescriptorBinding** pp_bindings) const;
+ SpvReflectResult EnumerateEntryPointDescriptorBindings(const char* entry_point, uint32_t* p_count, SpvReflectDescriptorBinding** pp_bindings) const;
+ SpvReflectResult EnumerateDescriptorSets( uint32_t* p_count, SpvReflectDescriptorSet** pp_sets) const ;
+ SpvReflectResult EnumerateEntryPointDescriptorSets(const char* entry_point, uint32_t* p_count, SpvReflectDescriptorSet** pp_sets) const ;
+ SpvReflectResult EnumerateInputVariables(uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const;
+ SpvReflectResult EnumerateEntryPointInputVariables(const char* entry_point, uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const;
+ SpvReflectResult EnumerateOutputVariables(uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const;
+ SpvReflectResult EnumerateEntryPointOutputVariables(const char* entry_point, uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const;
+ SpvReflectResult EnumeratePushConstantBlocks(uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const;
+ SpvReflectResult EnumerateEntryPointPushConstantBlocks(const char* entry_point, uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const;
+ SPV_REFLECT_DEPRECATED("Renamed to EnumeratePushConstantBlocks")
+ SpvReflectResult EnumeratePushConstants(uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const {
+ return EnumeratePushConstantBlocks(p_count, pp_blocks);
+ }
+
+ const SpvReflectDescriptorBinding* GetDescriptorBinding(uint32_t binding_number, uint32_t set_number, SpvReflectResult* p_result = nullptr) const;
+ const SpvReflectDescriptorBinding* GetEntryPointDescriptorBinding(const char* entry_point, uint32_t binding_number, uint32_t set_number, SpvReflectResult* p_result = nullptr) const;
+ const SpvReflectDescriptorSet* GetDescriptorSet(uint32_t set_number, SpvReflectResult* p_result = nullptr) const;
+ const SpvReflectDescriptorSet* GetEntryPointDescriptorSet(const char* entry_point, uint32_t set_number, SpvReflectResult* p_result = nullptr) const;
+ const SpvReflectInterfaceVariable* GetInputVariableByLocation(uint32_t location, SpvReflectResult* p_result = nullptr) const;
+ SPV_REFLECT_DEPRECATED("Renamed to GetInputVariableByLocation")
+ const SpvReflectInterfaceVariable* GetInputVariable(uint32_t location, SpvReflectResult* p_result = nullptr) const {
+ return GetInputVariableByLocation(location, p_result);
+ }
+ const SpvReflectInterfaceVariable* GetEntryPointInputVariableByLocation(const char* entry_point, uint32_t location, SpvReflectResult* p_result = nullptr) const;
+ const SpvReflectInterfaceVariable* GetInputVariableBySemantic(const char* semantic, SpvReflectResult* p_result = nullptr) const;
+ const SpvReflectInterfaceVariable* GetEntryPointInputVariableBySemantic(const char* entry_point, const char* semantic, SpvReflectResult* p_result = nullptr) const;
+ const SpvReflectInterfaceVariable* GetOutputVariableByLocation(uint32_t location, SpvReflectResult* p_result = nullptr) const;
+ SPV_REFLECT_DEPRECATED("Renamed to GetOutputVariableByLocation")
+ const SpvReflectInterfaceVariable* GetOutputVariable(uint32_t location, SpvReflectResult* p_result = nullptr) const {
+ return GetOutputVariableByLocation(location, p_result);
+ }
+ const SpvReflectInterfaceVariable* GetEntryPointOutputVariableByLocation(const char* entry_point, uint32_t location, SpvReflectResult* p_result = nullptr) const;
+ const SpvReflectInterfaceVariable* GetOutputVariableBySemantic(const char* semantic, SpvReflectResult* p_result = nullptr) const;
+ const SpvReflectInterfaceVariable* GetEntryPointOutputVariableBySemantic(const char* entry_point, const char* semantic, SpvReflectResult* p_result = nullptr) const;
+ const SpvReflectBlockVariable* GetPushConstantBlock(uint32_t index, SpvReflectResult* p_result = nullptr) const;
+ SPV_REFLECT_DEPRECATED("Renamed to GetPushConstantBlock")
+ const SpvReflectBlockVariable* GetPushConstant(uint32_t index, SpvReflectResult* p_result = nullptr) const {
+ return GetPushConstantBlock(index, p_result);
+ }
+ const SpvReflectBlockVariable* GetEntryPointPushConstantBlock(const char* entry_point, SpvReflectResult* p_result = nullptr) const;
+
+ SpvReflectResult ChangeDescriptorBindingNumbers(const SpvReflectDescriptorBinding* p_binding,
+ uint32_t new_binding_number = SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE,
+ uint32_t optional_new_set_number = SPV_REFLECT_SET_NUMBER_DONT_CHANGE);
+ SPV_REFLECT_DEPRECATED("Renamed to ChangeDescriptorBindingNumbers")
+ SpvReflectResult ChangeDescriptorBindingNumber(const SpvReflectDescriptorBinding* p_binding, uint32_t new_binding_number = SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE,
+ uint32_t new_set_number = SPV_REFLECT_SET_NUMBER_DONT_CHANGE) {
+ return ChangeDescriptorBindingNumbers(p_binding, new_binding_number, new_set_number);
+ }
+ SpvReflectResult ChangeDescriptorSetNumber(const SpvReflectDescriptorSet* p_set, uint32_t new_set_number = SPV_REFLECT_SET_NUMBER_DONT_CHANGE);
+ SpvReflectResult ChangeInputVariableLocation(const SpvReflectInterfaceVariable* p_input_variable, uint32_t new_location);
+ SpvReflectResult ChangeOutputVariableLocation(const SpvReflectInterfaceVariable* p_output_variable, uint32_t new_location);
+
+private:
+ mutable SpvReflectResult m_result = SPV_REFLECT_RESULT_NOT_READY;
+ SpvReflectShaderModule m_module = {};
+};
+
+
+// =================================================================================================
+// ShaderModule
+// =================================================================================================
+
+/*! @fn ShaderModule
+
+*/
+inline ShaderModule::ShaderModule() {}
+
+
+/*! @fn ShaderModule
+
+ @param size
+ @param p_code
+
+*/
+inline ShaderModule::ShaderModule(size_t size, const void* p_code) {
+ m_result = spvReflectCreateShaderModule(
+ size,
+ p_code,
+ &m_module);
+}
+
+/*! @fn ShaderModule
+
+ @param code
+
+*/
+inline ShaderModule::ShaderModule(const std::vector<uint8_t>& code) {
+ m_result = spvReflectCreateShaderModule(
+ code.size(),
+ code.data(),
+ &m_module);
+}
+
+/*! @fn ShaderModule
+
+ @param code
+
+*/
+inline ShaderModule::ShaderModule(const std::vector<uint32_t>& code) {
+ m_result = spvReflectCreateShaderModule(
+ code.size() * sizeof(uint32_t),
+ code.data(),
+ &m_module);
+}
+
+/*! @fn ~ShaderModule
+
+*/
+inline ShaderModule::~ShaderModule() {
+ spvReflectDestroyShaderModule(&m_module);
+}
+
+
+/*! @fn GetResult
+
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::GetResult() const {
+ return m_result;
+}
+
+
+/*! @fn GetShaderModule
+
+ @return
+
+*/
+inline const SpvReflectShaderModule& ShaderModule::GetShaderModule() const {
+ return m_module;
+}
+
+
+/*! @fn GetCodeSize
+
+ @return
+
+ */
+inline uint32_t ShaderModule::GetCodeSize() const {
+ return spvReflectGetCodeSize(&m_module);
+}
+
+
+/*! @fn GetCode
+
+ @return
+
+*/
+inline const uint32_t* ShaderModule::GetCode() const {
+ return spvReflectGetCode(&m_module);
+}
+
+
+/*! @fn GetEntryPoint
+
+ @return Returns entry point
+
+*/
+inline const char* ShaderModule::GetEntryPointName() const {
+ return this->GetEntryPointName(0);
+}
+
+/*! @fn GetEntryPoint
+
+ @return Returns entry point
+
+*/
+inline const char* ShaderModule::GetSourceFile() const {
+ return m_module.source_file;
+}
+
+/*! @fn GetEntryPointCount
+
+ @param
+ @return
+*/
+inline uint32_t ShaderModule::GetEntryPointCount() const {
+ return m_module.entry_point_count;
+}
+
+/*! @fn GetEntryPointName
+
+ @param index
+ @return
+*/
+inline const char* ShaderModule::GetEntryPointName(uint32_t index) const {
+ return m_module.entry_points[index].name;
+}
+
+/*! @fn GetShaderStage
+
+ @return Returns Vulkan shader stage
+
+*/
+inline SpvReflectShaderStageFlagBits ShaderModule::GetShaderStage() const {
+ return m_module.shader_stage;
+}
+
+/*! @fn EnumerateDescriptorBindings
+
+ @param count
+ @param p_binding_numbers
+ @param pp_bindings
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::EnumerateDescriptorBindings(
+ uint32_t* p_count,
+ SpvReflectDescriptorBinding** pp_bindings
+) const
+{
+ m_result = spvReflectEnumerateDescriptorBindings(
+ &m_module,
+ p_count,
+ pp_bindings);
+ return m_result;
+}
+
+/*! @fn EnumerateEntryPointDescriptorBindings
+
+ @param entry_point
+ @param count
+ @param pp_bindings
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::EnumerateEntryPointDescriptorBindings(
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectDescriptorBinding** pp_bindings
+) const
+{
+ m_result = spvReflectEnumerateEntryPointDescriptorBindings(
+ &m_module,
+ entry_point,
+ p_count,
+ pp_bindings);
+ return m_result;
+}
+
+
+/*! @fn EnumerateDescriptorSets
+
+ @param count
+ @param pp_sets
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::EnumerateDescriptorSets(
+ uint32_t* p_count,
+ SpvReflectDescriptorSet** pp_sets
+) const
+{
+ m_result = spvReflectEnumerateDescriptorSets(
+ &m_module,
+ p_count,
+ pp_sets);
+ return m_result;
+}
+
+/*! @fn EnumerateEntryPointDescriptorSets
+
+ @param entry_point
+ @param count
+ @param pp_sets
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::EnumerateEntryPointDescriptorSets(
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectDescriptorSet** pp_sets
+) const
+{
+ m_result = spvReflectEnumerateEntryPointDescriptorSets(
+ &m_module,
+ entry_point,
+ p_count,
+ pp_sets);
+ return m_result;
+}
+
+
+/*! @fn EnumerateInputVariables
+
+ @param count
+ @param pp_variables
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::EnumerateInputVariables(
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+) const
+{
+ m_result = spvReflectEnumerateInputVariables(
+ &m_module,
+ p_count,
+ pp_variables);
+ return m_result;
+}
+
+/*! @fn EnumerateEntryPointInputVariables
+
+ @param entry_point
+ @param count
+ @param pp_variables
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::EnumerateEntryPointInputVariables(
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+) const
+{
+ m_result = spvReflectEnumerateEntryPointInputVariables(
+ &m_module,
+ entry_point,
+ p_count,
+ pp_variables);
+ return m_result;
+}
+
+
+/*! @fn EnumerateOutputVariables
+
+ @param count
+ @param pp_variables
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::EnumerateOutputVariables(
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+) const
+{
+ m_result = spvReflectEnumerateOutputVariables(
+ &m_module,
+ p_count,
+ pp_variables);
+ return m_result;
+}
+
+/*! @fn EnumerateEntryPointOutputVariables
+
+ @param entry_point
+ @param count
+ @param pp_variables
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::EnumerateEntryPointOutputVariables(
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectInterfaceVariable** pp_variables
+) const
+{
+ m_result = spvReflectEnumerateEntryPointOutputVariables(
+ &m_module,
+ entry_point,
+ p_count,
+ pp_variables);
+ return m_result;
+}
+
+
+/*! @fn EnumeratePushConstantBlocks
+
+ @param count
+ @param pp_blocks
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::EnumeratePushConstantBlocks(
+ uint32_t* p_count,
+ SpvReflectBlockVariable** pp_blocks
+) const
+{
+ m_result = spvReflectEnumeratePushConstantBlocks(
+ &m_module,
+ p_count,
+ pp_blocks);
+ return m_result;
+}
+
+/*! @fn EnumerateEntryPointPushConstantBlocks
+
+ @param entry_point
+ @param count
+ @param pp_blocks
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::EnumerateEntryPointPushConstantBlocks(
+ const char* entry_point,
+ uint32_t* p_count,
+ SpvReflectBlockVariable** pp_blocks
+) const
+{
+ m_result = spvReflectEnumerateEntryPointPushConstantBlocks(
+ &m_module,
+ entry_point,
+ p_count,
+ pp_blocks);
+ return m_result;
+}
+
+
+/*! @fn GetDescriptorBinding
+
+ @param binding_number
+ @param set_number
+ @param p_result
+ @return
+
+*/
+inline const SpvReflectDescriptorBinding* ShaderModule::GetDescriptorBinding(
+ uint32_t binding_number,
+ uint32_t set_number,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetDescriptorBinding(
+ &m_module,
+ binding_number,
+ set_number,
+ p_result);
+}
+
+/*! @fn GetEntryPointDescriptorBinding
+
+ @param entry_point
+ @param binding_number
+ @param set_number
+ @param p_result
+ @return
+
+*/
+inline const SpvReflectDescriptorBinding* ShaderModule::GetEntryPointDescriptorBinding(
+ const char* entry_point,
+ uint32_t binding_number,
+ uint32_t set_number,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetEntryPointDescriptorBinding(
+ &m_module,
+ entry_point,
+ binding_number,
+ set_number,
+ p_result);
+}
+
+
+/*! @fn GetDescriptorSet
+
+ @param set_number
+ @param p_result
+ @return
+
+*/
+inline const SpvReflectDescriptorSet* ShaderModule::GetDescriptorSet(
+ uint32_t set_number,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetDescriptorSet(
+ &m_module,
+ set_number,
+ p_result);
+}
+
+/*! @fn GetEntryPointDescriptorSet
+
+ @param entry_point
+ @param set_number
+ @param p_result
+ @return
+
+*/
+inline const SpvReflectDescriptorSet* ShaderModule::GetEntryPointDescriptorSet(
+ const char* entry_point,
+ uint32_t set_number,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetEntryPointDescriptorSet(
+ &m_module,
+ entry_point,
+ set_number,
+ p_result);
+}
+
+
+/*! @fn GetInputVariable
+
+ @param location
+ @param p_result
+ @return
+
+*/
+inline const SpvReflectInterfaceVariable* ShaderModule::GetInputVariableByLocation(
+ uint32_t location,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetInputVariableByLocation(
+ &m_module,
+ location,
+ p_result);
+}
+inline const SpvReflectInterfaceVariable* ShaderModule::GetInputVariableBySemantic(
+ const char* semantic,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetInputVariableBySemantic(
+ &m_module,
+ semantic,
+ p_result);
+}
+
+/*! @fn GetEntryPointInputVariable
+
+ @param entry_point
+ @param location
+ @param p_result
+ @return
+
+*/
+inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointInputVariableByLocation(
+ const char* entry_point,
+ uint32_t location,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetEntryPointInputVariableByLocation(
+ &m_module,
+ entry_point,
+ location,
+ p_result);
+}
+inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointInputVariableBySemantic(
+ const char* entry_point,
+ const char* semantic,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetEntryPointInputVariableBySemantic(
+ &m_module,
+ entry_point,
+ semantic,
+ p_result);
+}
+
+
+/*! @fn GetOutputVariable
+
+ @param location
+ @param p_result
+ @return
+
+*/
+inline const SpvReflectInterfaceVariable* ShaderModule::GetOutputVariableByLocation(
+ uint32_t location,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetOutputVariableByLocation(
+ &m_module,
+ location,
+ p_result);
+}
+inline const SpvReflectInterfaceVariable* ShaderModule::GetOutputVariableBySemantic(
+ const char* semantic,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetOutputVariableBySemantic(&m_module,
+ semantic,
+ p_result);
+}
+
+/*! @fn GetEntryPointOutputVariable
+
+ @param entry_point
+ @param location
+ @param p_result
+ @return
+
+*/
+inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointOutputVariableByLocation(
+ const char* entry_point,
+ uint32_t location,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetEntryPointOutputVariableByLocation(
+ &m_module,
+ entry_point,
+ location,
+ p_result);
+}
+inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointOutputVariableBySemantic(
+ const char* entry_point,
+ const char* semantic,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetEntryPointOutputVariableBySemantic(
+ &m_module,
+ entry_point,
+ semantic,
+ p_result);
+}
+
+
+/*! @fn GetPushConstant
+
+ @param index
+ @param p_result
+ @return
+
+*/
+inline const SpvReflectBlockVariable* ShaderModule::GetPushConstantBlock(
+ uint32_t index,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetPushConstantBlock(
+ &m_module,
+ index,
+ p_result);
+}
+
+/*! @fn GetEntryPointPushConstant
+
+ @param entry_point
+ @param index
+ @param p_result
+ @return
+
+*/
+inline const SpvReflectBlockVariable* ShaderModule::GetEntryPointPushConstantBlock(
+ const char* entry_point,
+ SpvReflectResult* p_result
+) const
+{
+ return spvReflectGetEntryPointPushConstantBlock(
+ &m_module,
+ entry_point,
+ p_result);
+}
+
+
+/*! @fn ChangeDescriptorBindingNumbers
+
+ @param p_binding
+ @param new_binding_number
+ @param new_set_number
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::ChangeDescriptorBindingNumbers(
+ const SpvReflectDescriptorBinding* p_binding,
+ uint32_t new_binding_number,
+ uint32_t new_set_number
+)
+{
+ return spvReflectChangeDescriptorBindingNumbers(
+ &m_module,
+ p_binding,
+ new_binding_number,
+ new_set_number);
+}
+
+
+/*! @fn ChangeDescriptorSetNumber
+
+ @param p_set
+ @param new_set_number
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::ChangeDescriptorSetNumber(
+ const SpvReflectDescriptorSet* p_set,
+ uint32_t new_set_number
+)
+{
+ return spvReflectChangeDescriptorSetNumber(
+ &m_module,
+ p_set,
+ new_set_number);
+}
+
+
+/*! @fn ChangeInputVariableLocation
+
+ @param p_input_variable
+ @param new_location
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::ChangeInputVariableLocation(
+ const SpvReflectInterfaceVariable* p_input_variable,
+ uint32_t new_location)
+{
+ return spvReflectChangeInputVariableLocation(
+ &m_module,
+ p_input_variable,
+ new_location);
+}
+
+
+/*! @fn ChangeOutputVariableLocation
+
+ @param p_input_variable
+ @param new_location
+ @return
+
+*/
+inline SpvReflectResult ShaderModule::ChangeOutputVariableLocation(
+ const SpvReflectInterfaceVariable* p_output_variable,
+ uint32_t new_location)
+{
+ return spvReflectChangeOutputVariableLocation(
+ &m_module,
+ p_output_variable,
+ new_location);
+}
+
+} // namespace spv_reflect
+#endif // defined(__cplusplus)
+#endif // SPIRV_REFLECT_H
diff --git a/thirdparty/tinyexr/tinyexr.h b/thirdparty/tinyexr/tinyexr.h
index bfc52b51a5..7e8956f7d3 100644
--- a/thirdparty/tinyexr/tinyexr.h
+++ b/thirdparty/tinyexr/tinyexr.h
@@ -105,6 +105,19 @@ extern "C" {
// http://computation.llnl.gov/projects/floating-point-compression
#endif
+#ifndef TINYEXR_USE_THREAD
+#define TINYEXR_USE_THREAD (0) // No threaded loading.
+// http://computation.llnl.gov/projects/floating-point-compression
+#endif
+
+#ifndef TINYEXR_USE_OPENMP
+#ifdef _OPENMP
+#define TINYEXR_USE_OPENMP (1)
+#else
+#define TINYEXR_USE_OPENMP (0)
+#endif
+#endif
+
#define TINYEXR_SUCCESS (0)
#define TINYEXR_ERROR_INVALID_MAGIC_NUMBER (-1)
#define TINYEXR_ERROR_INVALID_EXR_VERSION (-2)
@@ -118,6 +131,7 @@ extern "C" {
#define TINYEXR_ERROR_UNSUPPORTED_FEATURE (-10)
#define TINYEXR_ERROR_CANT_WRITE_FILE (-11)
#define TINYEXR_ERROR_SERIALZATION_FAILED (-12)
+#define TINYEXR_ERROR_LAYER_NOT_FOUND (-13)
// @note { OpenEXR file format: http://www.openexr.com/openexrfilelayout.pdf }
@@ -263,7 +277,7 @@ typedef struct _DeepImage {
int pad0;
} DeepImage;
-// @deprecated { to be removed. }
+// @deprecated { For backward compatibility. Not recommended to use. }
// Loads single-frame OpenEXR image. Assume EXR image contains A(single channel
// alpha) or RGB(A) channels.
// Application must free image data as returned by `out_rgba`
@@ -273,6 +287,27 @@ typedef struct _DeepImage {
extern int LoadEXR(float **out_rgba, int *width, int *height,
const char *filename, const char **err);
+// Loads single-frame OpenEXR image by specifing layer name. Assume EXR image contains A(single channel
+// alpha) or RGB(A) channels.
+// Application must free image data as returned by `out_rgba`
+// Result image format is: float x RGBA x width x hight
+// Returns negative value and may set error string in `err` when there's an
+// error
+// When the specified layer name is not found in the EXR file, the function will return `TINYEXR_ERROR_LAYER_NOT_FOUND`.
+extern int LoadEXRWithLayer(float **out_rgba, int *width, int *height,
+ const char *filename, const char *layer_name, const char **err);
+
+//
+// Get layer infos from EXR file.
+//
+// @param[out] layer_names List of layer names. Application must free memory after using this.
+// @param[out] num_layers The number of layers
+// @param[out] err Error string(wll be filled when the function returns error code). Free it using FreeEXRErrorMessage after using this value.
+//
+// @return TINYEXR_SUCCEES upon success.
+//
+extern int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, const char **err);
+
// @deprecated { to be removed. }
// Simple wrapper API for ParseEXRHeaderFromFile.
// checking given file is a EXR file(by just look up header)
@@ -472,7 +507,7 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
#include <cstring>
#include <sstream>
-//#include <iostream> // debug
+// #include <iostream> // debug
#include <limits>
#include <string>
@@ -481,9 +516,15 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
#if __cplusplus > 199711L
// C++11
#include <cstdint>
+
+#if TINYEXR_USE_THREAD
+#include <atomic>
+#include <thread>
+#endif
+
#endif // __cplusplus > 199711L
-#ifdef _OPENMP
+#if TINYEXR_USE_OPENMP
#include <omp.h>
#endif
@@ -6917,6 +6958,10 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
}
#endif
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
#endif // MINIZ_HEADER_FILE_ONLY
/*
@@ -6952,9 +6997,6 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
#pragma clang diagnostic pop
#endif
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
} // namespace miniz
#else
@@ -9954,9 +9996,9 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
return false;
}
- if (!tinyexr::DecompressRle(reinterpret_cast<unsigned char *>(&outBuf.at(0)),
- dstLen, data_ptr,
- static_cast<unsigned long>(data_len))) {
+ if (!tinyexr::DecompressRle(
+ reinterpret_cast<unsigned char *>(&outBuf.at(0)), dstLen, data_ptr,
+ static_cast<unsigned long>(data_len))) {
return false;
}
@@ -10272,7 +10314,7 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
return true;
}
-static void DecodeTiledPixelData(
+static bool DecodeTiledPixelData(
unsigned char **out_images, int *width, int *height,
const int *requested_pixel_types, const unsigned char *data_ptr,
size_t data_len, int compression_type, int line_order, int data_width,
@@ -10298,11 +10340,11 @@ static void DecodeTiledPixelData(
}
// Image size = tile size.
- DecodePixelData(out_images, requested_pixel_types, data_ptr, data_len,
- compression_type, line_order, (*width), tile_size_y,
- /* stride */ tile_size_x, /* y */ 0, /* line_no */ 0,
- (*height), pixel_data_size, num_attributes, attributes,
- num_channels, channels, channel_offset_list);
+ return DecodePixelData(out_images, requested_pixel_types, data_ptr, data_len,
+ compression_type, line_order, (*width), tile_size_y,
+ /* stride */ tile_size_x, /* y */ 0, /* line_no */ 0,
+ (*height), pixel_data_size, num_attributes, attributes,
+ num_channels, channels, channel_offset_list);
}
static bool ComputeChannelLayout(std::vector<size_t> *channel_offset_list,
@@ -10851,85 +10893,141 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
exr_image->tiles = static_cast<EXRTile *>(
calloc(sizeof(EXRTile), static_cast<size_t>(num_tiles)));
+ int err_code = TINYEXR_SUCCESS;
+
+#if (__cplusplus > 199711L) && (TINYEXR_USE_THREAD > 0)
+
+ std::vector<std::thread> workers;
+ std::atomic<size_t> tile_count(0);
+
+ int num_threads = std::max(1, int(std::thread::hardware_concurrency()));
+ if (num_threads > int(num_tiles)) {
+ num_threads = int(num_tiles);
+ }
+
+ for (int t = 0; t < num_threads; t++) {
+ workers.emplace_back(std::thread([&]() {
+ size_t tile_idx = 0;
+ while ((tile_idx = tile_count++) < num_tiles) {
+
+#else
for (size_t tile_idx = 0; tile_idx < num_tiles; tile_idx++) {
- // Allocate memory for each tile.
- exr_image->tiles[tile_idx].images = tinyexr::AllocateImage(
- num_channels, exr_header->channels, exr_header->requested_pixel_types,
- exr_header->tile_size_x, exr_header->tile_size_y);
-
- // 16 byte: tile coordinates
- // 4 byte : data size
- // ~ : data(uncompressed or compressed)
- if (offsets[tile_idx] + sizeof(int) * 5 > size) {
- if (err) {
- (*err) += "Insufficient data size.\n";
- }
- return TINYEXR_ERROR_INVALID_DATA;
- }
+#endif
+ // Allocate memory for each tile.
+ exr_image->tiles[tile_idx].images = tinyexr::AllocateImage(
+ num_channels, exr_header->channels,
+ exr_header->requested_pixel_types, exr_header->tile_size_x,
+ exr_header->tile_size_y);
+
+ // 16 byte: tile coordinates
+ // 4 byte : data size
+ // ~ : data(uncompressed or compressed)
+ if (offsets[tile_idx] + sizeof(int) * 5 > size) {
+ // TODO(LTE): atomic
+ if (err) {
+ (*err) += "Insufficient data size.\n";
+ }
+ err_code = TINYEXR_ERROR_INVALID_DATA;
+ break;
+ }
- size_t data_size = size_t(size - (offsets[tile_idx] + sizeof(int) * 5));
- const unsigned char *data_ptr =
- reinterpret_cast<const unsigned char *>(head + offsets[tile_idx]);
+ size_t data_size =
+ size_t(size - (offsets[tile_idx] + sizeof(int) * 5));
+ const unsigned char *data_ptr =
+ reinterpret_cast<const unsigned char *>(head + offsets[tile_idx]);
+
+ int tile_coordinates[4];
+ memcpy(tile_coordinates, data_ptr, sizeof(int) * 4);
+ tinyexr::swap4(
+ reinterpret_cast<unsigned int *>(&tile_coordinates[0]));
+ tinyexr::swap4(
+ reinterpret_cast<unsigned int *>(&tile_coordinates[1]));
+ tinyexr::swap4(
+ reinterpret_cast<unsigned int *>(&tile_coordinates[2]));
+ tinyexr::swap4(
+ reinterpret_cast<unsigned int *>(&tile_coordinates[3]));
+
+ // @todo{ LoD }
+ if (tile_coordinates[2] != 0) {
+ err_code = TINYEXR_ERROR_UNSUPPORTED_FEATURE;
+ break;
+ }
+ if (tile_coordinates[3] != 0) {
+ err_code = TINYEXR_ERROR_UNSUPPORTED_FEATURE;
+ break;
+ }
- int tile_coordinates[4];
- memcpy(tile_coordinates, data_ptr, sizeof(int) * 4);
- tinyexr::swap4(reinterpret_cast<unsigned int *>(&tile_coordinates[0]));
- tinyexr::swap4(reinterpret_cast<unsigned int *>(&tile_coordinates[1]));
- tinyexr::swap4(reinterpret_cast<unsigned int *>(&tile_coordinates[2]));
- tinyexr::swap4(reinterpret_cast<unsigned int *>(&tile_coordinates[3]));
+ int data_len;
+ memcpy(&data_len, data_ptr + 16,
+ sizeof(int)); // 16 = sizeof(tile_coordinates)
+ tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
- // @todo{ LoD }
- if (tile_coordinates[2] != 0) {
- return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
- }
- if (tile_coordinates[3] != 0) {
- return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
- }
+ if (data_len < 4 || size_t(data_len) > data_size) {
+ // TODO(LTE): atomic
+ if (err) {
+ (*err) += "Insufficient data length.\n";
+ }
+ err_code = TINYEXR_ERROR_INVALID_DATA;
+ break;
+ }
- int data_len;
- memcpy(&data_len, data_ptr + 16,
- sizeof(int)); // 16 = sizeof(tile_coordinates)
- tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
+ // Move to data addr: 20 = 16 + 4;
+ data_ptr += 20;
+
+ bool ret = tinyexr::DecodeTiledPixelData(
+ exr_image->tiles[tile_idx].images,
+ &(exr_image->tiles[tile_idx].width),
+ &(exr_image->tiles[tile_idx].height),
+ exr_header->requested_pixel_types, data_ptr,
+ static_cast<size_t>(data_len), exr_header->compression_type,
+ exr_header->line_order, data_width, data_height,
+ tile_coordinates[0], tile_coordinates[1], exr_header->tile_size_x,
+ exr_header->tile_size_y, static_cast<size_t>(pixel_data_size),
+ static_cast<size_t>(exr_header->num_custom_attributes),
+ exr_header->custom_attributes,
+ static_cast<size_t>(exr_header->num_channels),
+ exr_header->channels, channel_offset_list);
+
+ if (!ret) {
+ // TODO(LTE): atomic
+ if (err) {
+ (*err) += "Failed to decode tile data.\n";
+ }
+ err_code = TINYEXR_ERROR_INVALID_DATA;
+ }
- if (data_len < 4 || size_t(data_len) > data_size) {
- if (err) {
- (*err) += "Insufficient data length.\n";
+ exr_image->tiles[tile_idx].offset_x = tile_coordinates[0];
+ exr_image->tiles[tile_idx].offset_y = tile_coordinates[1];
+ exr_image->tiles[tile_idx].level_x = tile_coordinates[2];
+ exr_image->tiles[tile_idx].level_y = tile_coordinates[3];
+
+#if (__cplusplus > 199711L) && (TINYEXR_USE_THREAD > 0)
}
- return TINYEXR_ERROR_INVALID_DATA;
- }
+ }));
+ } // num_thread loop
- // Move to data addr: 20 = 16 + 4;
- data_ptr += 20;
-
- tinyexr::DecodeTiledPixelData(
- exr_image->tiles[tile_idx].images,
- &(exr_image->tiles[tile_idx].width),
- &(exr_image->tiles[tile_idx].height),
- exr_header->requested_pixel_types, data_ptr,
- static_cast<size_t>(data_len), exr_header->compression_type,
- exr_header->line_order, data_width, data_height, tile_coordinates[0],
- tile_coordinates[1], exr_header->tile_size_x, exr_header->tile_size_y,
- static_cast<size_t>(pixel_data_size),
- static_cast<size_t>(exr_header->num_custom_attributes),
- exr_header->custom_attributes,
- static_cast<size_t>(exr_header->num_channels), exr_header->channels,
- channel_offset_list);
-
- exr_image->tiles[tile_idx].offset_x = tile_coordinates[0];
- exr_image->tiles[tile_idx].offset_y = tile_coordinates[1];
- exr_image->tiles[tile_idx].level_x = tile_coordinates[2];
- exr_image->tiles[tile_idx].level_y = tile_coordinates[3];
-
- exr_image->num_tiles = static_cast<int>(num_tiles);
+ for (auto &t : workers) {
+ t.join();
}
+
+#else
+ }
+#endif
+
+ if (err_code != TINYEXR_SUCCESS) {
+ return err_code;
+ }
+
+ exr_image->num_tiles = static_cast<int>(num_tiles);
} else { // scanline format
// Don't allow too large image(256GB * pixel_data_size or more). Workaround
// for #104.
size_t total_data_len =
size_t(data_width) * size_t(data_height) * size_t(num_channels);
- const bool total_data_len_overflown = sizeof(void*) == 8 ? (total_data_len >= 0x4000000000) : false;
- if ((total_data_len == 0) || total_data_len_overflown ) {
+ const bool total_data_len_overflown =
+ sizeof(void *) == 8 ? (total_data_len >= 0x4000000000) : false;
+ if ((total_data_len == 0) || total_data_len_overflown) {
if (err) {
std::stringstream ss;
ss << "Image data size is zero or too large: width = " << data_width
@@ -10944,85 +11042,118 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
num_channels, exr_header->channels, exr_header->requested_pixel_types,
data_width, data_height);
-#ifdef _OPENMP
+#if (__cplusplus > 199711L) && (TINYEXR_USE_THREAD > 0)
+ std::vector<std::thread> workers;
+ std::atomic<int> y_count(0);
+
+ int num_threads = std::max(1, int(std::thread::hardware_concurrency()));
+ if (num_threads > int(num_blocks)) {
+ num_threads = int(num_blocks);
+ }
+
+ for (int t = 0; t < num_threads; t++) {
+ workers.emplace_back(std::thread([&]() {
+ int y = 0;
+ while ((y = y_count++) < int(num_blocks)) {
+
+#else
+
+#if TINYEXR_USE_OPENMP
#pragma omp parallel for
#endif
for (int y = 0; y < static_cast<int>(num_blocks); y++) {
- size_t y_idx = static_cast<size_t>(y);
-
- if (offsets[y_idx] + sizeof(int) * 2 > size) {
- invalid_data = true;
- } else {
- // 4 byte: scan line
- // 4 byte: data size
- // ~ : pixel data(uncompressed or compressed)
- size_t data_size = size_t(size - (offsets[y_idx] + sizeof(int) * 2));
- const unsigned char *data_ptr =
- reinterpret_cast<const unsigned char *>(head + offsets[y_idx]);
-
- int line_no;
- memcpy(&line_no, data_ptr, sizeof(int));
- int data_len;
- memcpy(&data_len, data_ptr + 4, sizeof(int));
- tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no));
- tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
-
- if (size_t(data_len) > data_size) {
- invalid_data = true;
-
- } else if ((line_no > (2 << 20)) || (line_no < -(2 << 20))) {
- // Too large value. Assume this is invalid
- // 2**20 = 1048576 = heuristic value.
- invalid_data = true;
- } else if (data_len == 0) {
- // TODO(syoyo): May be ok to raise the threshold for example `data_len
- // < 4`
- invalid_data = true;
- } else {
- // line_no may be negative.
- int end_line_no = (std::min)(line_no + num_scanline_blocks,
- (exr_header->data_window[3] + 1));
- int num_lines = end_line_no - line_no;
+#endif
+ size_t y_idx = static_cast<size_t>(y);
- if (num_lines <= 0) {
+ if (offsets[y_idx] + sizeof(int) * 2 > size) {
invalid_data = true;
} else {
- // Move to data addr: 8 = 4 + 4;
- data_ptr += 8;
-
- // Adjust line_no with data_window.bmin.y
-
- // overflow check
- tinyexr_int64 lno = static_cast<tinyexr_int64>(line_no) - static_cast<tinyexr_int64>(exr_header->data_window[1]);
- if (lno > std::numeric_limits<int>::max()) {
- line_no = -1; // invalid
- } else if (lno < -std::numeric_limits<int>::max()) {
- line_no = -1; // invalid
- } else {
- line_no -= exr_header->data_window[1];
- }
+ // 4 byte: scan line
+ // 4 byte: data size
+ // ~ : pixel data(uncompressed or compressed)
+ size_t data_size =
+ size_t(size - (offsets[y_idx] + sizeof(int) * 2));
+ const unsigned char *data_ptr =
+ reinterpret_cast<const unsigned char *>(head + offsets[y_idx]);
+
+ int line_no;
+ memcpy(&line_no, data_ptr, sizeof(int));
+ int data_len;
+ memcpy(&data_len, data_ptr + 4, sizeof(int));
+ tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no));
+ tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
+
+ if (size_t(data_len) > data_size) {
+ invalid_data = true;
- if (line_no < 0) {
+ } else if ((line_no > (2 << 20)) || (line_no < -(2 << 20))) {
+ // Too large value. Assume this is invalid
+ // 2**20 = 1048576 = heuristic value.
+ invalid_data = true;
+ } else if (data_len == 0) {
+ // TODO(syoyo): May be ok to raise the threshold for example
+ // `data_len < 4`
invalid_data = true;
} else {
- if (!tinyexr::DecodePixelData(
- exr_image->images, exr_header->requested_pixel_types,
- data_ptr, static_cast<size_t>(data_len),
- exr_header->compression_type, exr_header->line_order,
- data_width, data_height, data_width, y, line_no,
- num_lines, static_cast<size_t>(pixel_data_size),
- static_cast<size_t>(exr_header->num_custom_attributes),
- exr_header->custom_attributes,
- static_cast<size_t>(exr_header->num_channels),
- exr_header->channels, channel_offset_list)) {
+ // line_no may be negative.
+ int end_line_no = (std::min)(line_no + num_scanline_blocks,
+ (exr_header->data_window[3] + 1));
+
+ int num_lines = end_line_no - line_no;
+
+ if (num_lines <= 0) {
invalid_data = true;
+ } else {
+ // Move to data addr: 8 = 4 + 4;
+ data_ptr += 8;
+
+ // Adjust line_no with data_window.bmin.y
+
+ // overflow check
+ tinyexr_int64 lno =
+ static_cast<tinyexr_int64>(line_no) -
+ static_cast<tinyexr_int64>(exr_header->data_window[1]);
+ if (lno > std::numeric_limits<int>::max()) {
+ line_no = -1; // invalid
+ } else if (lno < -std::numeric_limits<int>::max()) {
+ line_no = -1; // invalid
+ } else {
+ line_no -= exr_header->data_window[1];
+ }
+
+ if (line_no < 0) {
+ invalid_data = true;
+ } else {
+ if (!tinyexr::DecodePixelData(
+ exr_image->images, exr_header->requested_pixel_types,
+ data_ptr, static_cast<size_t>(data_len),
+ exr_header->compression_type, exr_header->line_order,
+ data_width, data_height, data_width, y, line_no,
+ num_lines, static_cast<size_t>(pixel_data_size),
+ static_cast<size_t>(
+ exr_header->num_custom_attributes),
+ exr_header->custom_attributes,
+ static_cast<size_t>(exr_header->num_channels),
+ exr_header->channels, channel_offset_list)) {
+ invalid_data = true;
+ }
+ }
}
}
}
+
+#if (__cplusplus > 199711L) && (TINYEXR_USE_THREAD > 0)
}
- }
+ }));
+ }
+
+ for (auto &t : workers) {
+ t.join();
+ }
+#else
} // omp parallel
+#endif
}
if (invalid_data) {
@@ -11219,6 +11350,9 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header,
tinyexr::SetErrorMessage(e, err);
}
+#if 1
+ FreeEXRImage(exr_image);
+#else
// release memory(if exists)
if ((exr_header->num_channels > 0) && exr_image && exr_image->images) {
for (size_t c = 0; c < size_t(exr_header->num_channels); c++) {
@@ -11230,16 +11364,114 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header,
free(exr_image->images);
exr_image->images = NULL;
}
+#endif
}
return ret;
}
}
+static void GetLayers(const EXRHeader& exr_header, std::vector<std::string>& layer_names) {
+ // Naive implementation
+ // Group channels by layers
+ // go over all channel names, split by periods
+ // collect unique names
+ layer_names.clear();
+ for (int c = 0; c < exr_header.num_channels; c++) {
+ std::string full_name(exr_header.channels[c].name);
+ const size_t pos = full_name.find_last_of('.');
+ if (pos != std::string::npos && pos != 0 && pos + 1 < full_name.size()) {
+ full_name.erase(pos);
+ if (std::find(layer_names.begin(), layer_names.end(), full_name) == layer_names.end())
+ layer_names.push_back(full_name);
+ }
+ }
+}
+
+struct LayerChannel {
+ explicit LayerChannel (size_t i, std::string n)
+ : index(i)
+ , name(n)
+ {}
+ size_t index;
+ std::string name;
+};
+
+static void ChannelsInLayer(const EXRHeader& exr_header, const std::string layer_name, std::vector<LayerChannel>& channels) {
+ channels.clear();
+ for (int c = 0; c < exr_header.num_channels; c++) {
+ std::string ch_name(exr_header.channels[c].name);
+ if (layer_name.empty()) {
+ const size_t pos = ch_name.find_last_of('.');
+ if (pos != std::string::npos && pos < ch_name.size()) {
+ ch_name = ch_name.substr(pos + 1);
+ }
+ } else {
+ const size_t pos = ch_name.find(layer_name + '.');
+ if (pos == std::string::npos)
+ continue;
+ if (pos == 0) {
+ ch_name = ch_name.substr(layer_name.size() + 1);
+ }
+ }
+ LayerChannel ch(size_t(c), ch_name);
+ channels.push_back(ch);
+ }
+}
+
} // namespace tinyexr
+int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, const char **err) {
+ EXRVersion exr_version;
+ EXRHeader exr_header;
+ InitEXRHeader(&exr_header);
+
+ {
+ int ret = ParseEXRVersionFromFile(&exr_version, filename);
+ if (ret != TINYEXR_SUCCESS) {
+ tinyexr::SetErrorMessage("Invalid EXR header.", err);
+ return ret;
+ }
+
+ if (exr_version.multipart || exr_version.non_image) {
+ tinyexr::SetErrorMessage(
+ "Loading multipart or DeepImage is not supported in LoadEXR() API",
+ err);
+ return TINYEXR_ERROR_INVALID_DATA; // @fixme.
+ }
+ }
+
+ int ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename, err);
+ if (ret != TINYEXR_SUCCESS) {
+ FreeEXRHeader(&exr_header);
+ return ret;
+ }
+
+ std::vector<std::string> layer_vec;
+ tinyexr::GetLayers(exr_header, layer_vec);
+
+ (*num_layers) = int(layer_vec.size());
+ (*layer_names) = static_cast<const char **>(
+ malloc(sizeof(const char *) * static_cast<size_t>(layer_vec.size())));
+ for (size_t c = 0; c < static_cast<size_t>(layer_vec.size()); c++) {
+#ifdef _MSC_VER
+ (*layer_names)[c] = _strdup(layer_vec[c].c_str());
+#else
+ (*layer_names)[c] = strdup(layer_vec[c].c_str());
+#endif
+ }
+
+ FreeEXRHeader(&exr_header);
+ return TINYEXR_SUCCESS;
+}
+
int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
const char **err) {
+ return LoadEXRWithLayer(out_rgba, width, height, filename, /* layername */NULL, err);
+}
+
+int LoadEXRWithLayer(float **out_rgba, int *width, int *height, const char *filename, const char *layername,
+ const char **err) {
if (out_rgba == NULL) {
tinyexr::SetErrorMessage("Invalid argument for LoadEXR()", err);
return TINYEXR_ERROR_INVALID_ARGUMENT;
@@ -11254,7 +11486,9 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
{
int ret = ParseEXRVersionFromFile(&exr_version, filename);
if (ret != TINYEXR_SUCCESS) {
- tinyexr::SetErrorMessage("Invalid EXR header.", err);
+ std::stringstream ss;
+ ss << "Failed to open EXR file or read version info from EXR file. code(" << ret << ")";
+ tinyexr::SetErrorMessage(ss.str(), err);
return ret;
}
@@ -11281,6 +11515,7 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
}
}
+ // TODO: Probably limit loading to layers (channels) selected by layer index
{
int ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename, err);
if (ret != TINYEXR_SUCCESS) {
@@ -11294,19 +11529,40 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
int idxG = -1;
int idxB = -1;
int idxA = -1;
- for (int c = 0; c < exr_header.num_channels; c++) {
- if (strcmp(exr_header.channels[c].name, "R") == 0) {
- idxR = c;
- } else if (strcmp(exr_header.channels[c].name, "G") == 0) {
- idxG = c;
- } else if (strcmp(exr_header.channels[c].name, "B") == 0) {
- idxB = c;
- } else if (strcmp(exr_header.channels[c].name, "A") == 0) {
- idxA = c;
+
+ std::vector<std::string> layer_names;
+ tinyexr::GetLayers(exr_header, layer_names);
+
+ std::vector<tinyexr::LayerChannel> channels;
+ tinyexr::ChannelsInLayer(exr_header, layername == NULL ? "" : std::string(layername), channels);
+
+ if (channels.size() < 1) {
+ tinyexr::SetErrorMessage("Layer Not Found", err);
+ FreeEXRHeader(&exr_header);
+ FreeEXRImage(&exr_image);
+ return TINYEXR_ERROR_LAYER_NOT_FOUND;
+ }
+
+ size_t ch_count = channels.size() < 4 ? channels.size() : 4;
+ for (size_t c = 0; c < ch_count; c++) {
+ const tinyexr::LayerChannel &ch = channels[c];
+
+ if (ch.name == "R") {
+ idxR = int(ch.index);
+ }
+ else if (ch.name == "G") {
+ idxG = int(ch.index);
+ }
+ else if (ch.name == "B") {
+ idxB = int(ch.index);
+ }
+ else if (ch.name == "A") {
+ idxA = int(ch.index);
}
}
- if (exr_header.num_channels == 1) {
+ if (channels.size() == 1) {
+ int chIdx = int(channels.front().index);
// Grayscale channel only.
(*out_rgba) = reinterpret_cast<float *>(
@@ -11333,19 +11589,19 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
const int srcIdx = i + j * exr_header.tile_size_x;
unsigned char **src = exr_image.tiles[it].images;
(*out_rgba)[4 * idx + 0] =
- reinterpret_cast<float **>(src)[0][srcIdx];
+ reinterpret_cast<float **>(src)[chIdx][srcIdx];
(*out_rgba)[4 * idx + 1] =
- reinterpret_cast<float **>(src)[0][srcIdx];
+ reinterpret_cast<float **>(src)[chIdx][srcIdx];
(*out_rgba)[4 * idx + 2] =
- reinterpret_cast<float **>(src)[0][srcIdx];
+ reinterpret_cast<float **>(src)[chIdx][srcIdx];
(*out_rgba)[4 * idx + 3] =
- reinterpret_cast<float **>(src)[0][srcIdx];
+ reinterpret_cast<float **>(src)[chIdx][srcIdx];
}
}
}
} else {
for (int i = 0; i < exr_image.width * exr_image.height; i++) {
- const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
+ const float val = reinterpret_cast<float **>(exr_image.images)[chIdx][i];
(*out_rgba)[4 * i + 0] = val;
(*out_rgba)[4 * i + 1] = val;
(*out_rgba)[4 * i + 2] = val;
@@ -11358,22 +11614,22 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
if (idxR == -1) {
tinyexr::SetErrorMessage("R channel not found", err);
- // @todo { free exr_image }
FreeEXRHeader(&exr_header);
+ FreeEXRImage(&exr_image);
return TINYEXR_ERROR_INVALID_DATA;
}
if (idxG == -1) {
tinyexr::SetErrorMessage("G channel not found", err);
- // @todo { free exr_image }
FreeEXRHeader(&exr_header);
+ FreeEXRImage(&exr_image);
return TINYEXR_ERROR_INVALID_DATA;
}
if (idxB == -1) {
tinyexr::SetErrorMessage("B channel not found", err);
- // @todo { free exr_image }
FreeEXRHeader(&exr_header);
+ FreeEXRImage(&exr_image);
return TINYEXR_ERROR_INVALID_DATA;
}
@@ -11446,7 +11702,7 @@ int IsEXR(const char *filename) {
int ret = ParseEXRVersionFromFile(&exr_version, filename);
if (ret != TINYEXR_SUCCESS) {
- return TINYEXR_ERROR_INVALID_HEADER;
+ return ret;
}
return TINYEXR_SUCCESS;
@@ -11509,7 +11765,9 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
int ret = ParseEXRVersionFromMemory(&exr_version, memory, size);
if (ret != TINYEXR_SUCCESS) {
- tinyexr::SetErrorMessage("Failed to parse EXR version", err);
+ std::stringstream ss;
+ ss << "Failed to parse EXR version. code(" << ret << ")";
+ tinyexr::SetErrorMessage(ss.str(), err);
return ret;
}
@@ -11967,9 +12225,11 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
}
#endif
+ // TOOD(LTE): C++11 thread
+
// Use signed int since some OpenMP compiler doesn't allow unsigned type for
// `parallel for`
-#ifdef _OPENMP
+#if TINYEXR_USE_OPENMP
#pragma omp parallel for
#endif
for (int i = 0; i < num_blocks; i++) {
diff --git a/thirdparty/vhacd/0003-fix-musl-build.patch b/thirdparty/vhacd/0003-fix-musl-build.patch
new file mode 100644
index 0000000000..67af8546f3
--- /dev/null
+++ b/thirdparty/vhacd/0003-fix-musl-build.patch
@@ -0,0 +1,15 @@
+diff --git a/thirdparty/vhacd/inc/vhacdMutex.h b/thirdparty/vhacd/inc/vhacdMutex.h
+index 6b09259200..d587dd6387 100644
+--- a/thirdparty/vhacd/inc/vhacdMutex.h
++++ b/thirdparty/vhacd/inc/vhacdMutex.h
+@@ -71,7 +71,9 @@
+ #include <pthread.h>
+ #endif
+
+-#if defined(__APPLE__)
++// -- GODOT start --
++#if defined(__APPLE__) || !defined(__GLIBC__)
++// -- GODOT end --
+ #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
+ #endif
+
diff --git a/thirdparty/vhacd/0004-fix-uwp-arm-build.patch b/thirdparty/vhacd/0004-fix-uwp-arm-build.patch
new file mode 100644
index 0000000000..a5bba3fd7d
--- /dev/null
+++ b/thirdparty/vhacd/0004-fix-uwp-arm-build.patch
@@ -0,0 +1,16 @@
+diff --git a/thirdparty/vhacd/inc/btScalar.h b/thirdparty/vhacd/inc/btScalar.h
+index 3999a71521..4c9e0cf7ab 100644
+--- a/thirdparty/vhacd/inc/btScalar.h
++++ b/thirdparty/vhacd/inc/btScalar.h
+@@ -72,7 +72,10 @@ inline int32_t btGetVersion()
+ #define btFsel(a, b, c) __fsel((a), (b), (c))
+ #else
+
+-#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(BT_USE_DOUBLE_PRECISION))
++// -- GODOT start --
++//#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(BT_USE_DOUBLE_PRECISION))
++#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(BT_USE_DOUBLE_PRECISION)) && (!defined(_M_ARM))
++// -- GODOT end --
+ #define BT_USE_SSE
+ #include <emmintrin.h>
+ #endif
diff --git a/thirdparty/vhacd/0005-fix-scale-calculation.patch b/thirdparty/vhacd/0005-fix-scale-calculation.patch
new file mode 100644
index 0000000000..4b05f64fbf
--- /dev/null
+++ b/thirdparty/vhacd/0005-fix-scale-calculation.patch
@@ -0,0 +1,20 @@
+diff --git a/thirdparty/vhacd/inc/vhacdVolume.h b/thirdparty/vhacd/inc/vhacdVolume.h
+index 8c47fa1e2c..c445f20122 100644
+--- a/thirdparty/vhacd/inc/vhacdVolume.h
++++ b/thirdparty/vhacd/inc/vhacdVolume.h
+@@ -316,13 +316,13 @@ void Volume::Voxelize(const T* const points, const uint32_t stridePoints, const
+
+ double d[3] = { m_maxBB[0] - m_minBB[0], m_maxBB[1] - m_minBB[1], m_maxBB[2] - m_minBB[2] };
+ double r;
+- if (d[0] > d[1] && d[0] > d[2]) {
++ if (d[0] >= d[1] && d[0] >= d[2]) {
+ r = d[0];
+ m_dim[0] = dim;
+ m_dim[1] = 2 + static_cast<size_t>(dim * d[1] / d[0]);
+ m_dim[2] = 2 + static_cast<size_t>(dim * d[2] / d[0]);
+ }
+- else if (d[1] > d[0] && d[1] > d[2]) {
++ else if (d[1] >= d[0] && d[1] >= d[2]) {
+ r = d[1];
+ m_dim[1] = dim;
+ m_dim[0] = 2 + static_cast<size_t>(dim * d[0] / d[1]);
diff --git a/thirdparty/vhacd/inc/btScalar.h b/thirdparty/vhacd/inc/btScalar.h
index 3999a71521..4c9e0cf7ab 100644
--- a/thirdparty/vhacd/inc/btScalar.h
+++ b/thirdparty/vhacd/inc/btScalar.h
@@ -72,7 +72,10 @@ inline int32_t btGetVersion()
#define btFsel(a, b, c) __fsel((a), (b), (c))
#else
-#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(BT_USE_DOUBLE_PRECISION))
+// -- GODOT start --
+//#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(BT_USE_DOUBLE_PRECISION))
+#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(BT_USE_DOUBLE_PRECISION)) && (!defined(_M_ARM))
+// -- GODOT end --
#define BT_USE_SSE
#include <emmintrin.h>
#endif
diff --git a/thirdparty/vhacd/inc/vhacdMutex.h b/thirdparty/vhacd/inc/vhacdMutex.h
index 6b09259200..d587dd6387 100644
--- a/thirdparty/vhacd/inc/vhacdMutex.h
+++ b/thirdparty/vhacd/inc/vhacdMutex.h
@@ -71,7 +71,9 @@
#include <pthread.h>
#endif
-#if defined(__APPLE__)
+// -- GODOT start --
+#if defined(__APPLE__) || !defined(__GLIBC__)
+// -- GODOT end --
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
#endif
diff --git a/thirdparty/vhacd/inc/vhacdVolume.h b/thirdparty/vhacd/inc/vhacdVolume.h
index 8c47fa1e2c..c445f20122 100644
--- a/thirdparty/vhacd/inc/vhacdVolume.h
+++ b/thirdparty/vhacd/inc/vhacdVolume.h
@@ -316,13 +316,13 @@ void Volume::Voxelize(const T* const points, const uint32_t stridePoints, const
double d[3] = { m_maxBB[0] - m_minBB[0], m_maxBB[1] - m_minBB[1], m_maxBB[2] - m_minBB[2] };
double r;
- if (d[0] > d[1] && d[0] > d[2]) {
+ if (d[0] >= d[1] && d[0] >= d[2]) {
r = d[0];
m_dim[0] = dim;
m_dim[1] = 2 + static_cast<size_t>(dim * d[1] / d[0]);
m_dim[2] = 2 + static_cast<size_t>(dim * d[2] / d[0]);
}
- else if (d[1] > d[0] && d[1] > d[2]) {
+ else if (d[1] >= d[0] && d[1] >= d[2]) {
r = d[1];
m_dim[1] = dim;
m_dim[0] = 2 + static_cast<size_t>(dim * d[0] / d[1]);
diff --git a/thirdparty/vulkan/LICENSE.txt b/thirdparty/vulkan/LICENSE.txt
new file mode 100644
index 0000000000..6599e310a4
--- /dev/null
+++ b/thirdparty/vulkan/LICENSE.txt
@@ -0,0 +1,207 @@
+The majority of files in this project use the Apache 2.0 License.
+There are a few exceptions and their license can be found in the source.
+Any license deviations from Apache 2.0 are "more permissive" licenses.
+
+===========================================================================================
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/thirdparty/vulkan/android/vk_mem_alloc.cpp b/thirdparty/vulkan/android/vk_mem_alloc.cpp
new file mode 100644
index 0000000000..a28454cf6e
--- /dev/null
+++ b/thirdparty/vulkan/android/vk_mem_alloc.cpp
@@ -0,0 +1,8 @@
+#define VMA_IMPLEMENTATION
+#ifdef DEBUG_ENABLED
+#ifndef _DEBUG
+#define _DEBUG
+#endif
+#endif
+// Include memory allocator from Android NDK
+#include <vk_mem_alloc.h>
diff --git a/thirdparty/vulkan/include/vulkan/vk_icd.h b/thirdparty/vulkan/include/vulkan/vk_icd.h
new file mode 100644
index 0000000000..5dff59a16e
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vk_icd.h
@@ -0,0 +1,183 @@
+//
+// File: vk_icd.h
+//
+/*
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef VKICD_H
+#define VKICD_H
+
+#include "vulkan.h"
+#include <stdbool.h>
+
+// Loader-ICD version negotiation API. Versions add the following features:
+// Version 0 - Initial. Doesn't support vk_icdGetInstanceProcAddr
+// or vk_icdNegotiateLoaderICDInterfaceVersion.
+// Version 1 - Add support for vk_icdGetInstanceProcAddr.
+// Version 2 - Add Loader/ICD Interface version negotiation
+// via vk_icdNegotiateLoaderICDInterfaceVersion.
+// Version 3 - Add ICD creation/destruction of KHR_surface objects.
+// Version 4 - Add unknown physical device extension qyering via
+// vk_icdGetPhysicalDeviceProcAddr.
+// Version 5 - Tells ICDs that the loader is now paying attention to the
+// application version of Vulkan passed into the ApplicationInfo
+// structure during vkCreateInstance. This will tell the ICD
+// that if the loader is older, it should automatically fail a
+// call for any API version > 1.0. Otherwise, the loader will
+// manually determine if it can support the expected version.
+#define CURRENT_LOADER_ICD_INTERFACE_VERSION 5
+#define MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION 0
+#define MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION 4
+typedef VkResult(VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion);
+
+// This is defined in vk_layer.h which will be found by the loader, but if an ICD is building against this
+// file directly, it won't be found.
+#ifndef PFN_GetPhysicalDeviceProcAddr
+typedef PFN_vkVoidFunction(VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char *pName);
+#endif
+
+/*
+ * The ICD must reserve space for a pointer for the loader's dispatch
+ * table, at the start of <each object>.
+ * The ICD must initialize this variable using the SET_LOADER_MAGIC_VALUE macro.
+ */
+
+#define ICD_LOADER_MAGIC 0x01CDC0DE
+
+typedef union {
+ uintptr_t loaderMagic;
+ void *loaderData;
+} VK_LOADER_DATA;
+
+static inline void set_loader_magic_value(void *pNewObject) {
+ VK_LOADER_DATA *loader_info = (VK_LOADER_DATA *)pNewObject;
+ loader_info->loaderMagic = ICD_LOADER_MAGIC;
+}
+
+static inline bool valid_loader_magic_value(void *pNewObject) {
+ const VK_LOADER_DATA *loader_info = (VK_LOADER_DATA *)pNewObject;
+ return (loader_info->loaderMagic & 0xffffffff) == ICD_LOADER_MAGIC;
+}
+
+/*
+ * Windows and Linux ICDs will treat VkSurfaceKHR as a pointer to a struct that
+ * contains the platform-specific connection and surface information.
+ */
+typedef enum {
+ VK_ICD_WSI_PLATFORM_MIR,
+ VK_ICD_WSI_PLATFORM_WAYLAND,
+ VK_ICD_WSI_PLATFORM_WIN32,
+ VK_ICD_WSI_PLATFORM_XCB,
+ VK_ICD_WSI_PLATFORM_XLIB,
+ VK_ICD_WSI_PLATFORM_ANDROID,
+ VK_ICD_WSI_PLATFORM_MACOS,
+ VK_ICD_WSI_PLATFORM_IOS,
+ VK_ICD_WSI_PLATFORM_DISPLAY,
+ VK_ICD_WSI_PLATFORM_HEADLESS,
+ VK_ICD_WSI_PLATFORM_METAL,
+} VkIcdWsiPlatform;
+
+typedef struct {
+ VkIcdWsiPlatform platform;
+} VkIcdSurfaceBase;
+
+#ifdef VK_USE_PLATFORM_MIR_KHR
+typedef struct {
+ VkIcdSurfaceBase base;
+ MirConnection *connection;
+ MirSurface *mirSurface;
+} VkIcdSurfaceMir;
+#endif // VK_USE_PLATFORM_MIR_KHR
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+typedef struct {
+ VkIcdSurfaceBase base;
+ struct wl_display *display;
+ struct wl_surface *surface;
+} VkIcdSurfaceWayland;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+typedef struct {
+ VkIcdSurfaceBase base;
+ HINSTANCE hinstance;
+ HWND hwnd;
+} VkIcdSurfaceWin32;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+typedef struct {
+ VkIcdSurfaceBase base;
+ xcb_connection_t *connection;
+ xcb_window_t window;
+} VkIcdSurfaceXcb;
+#endif // VK_USE_PLATFORM_XCB_KHR
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+typedef struct {
+ VkIcdSurfaceBase base;
+ Display *dpy;
+ Window window;
+} VkIcdSurfaceXlib;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+typedef struct {
+ VkIcdSurfaceBase base;
+ struct ANativeWindow *window;
+} VkIcdSurfaceAndroid;
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+typedef struct {
+ VkIcdSurfaceBase base;
+ const void *pView;
+} VkIcdSurfaceMacOS;
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+typedef struct {
+ VkIcdSurfaceBase base;
+ const void *pView;
+} VkIcdSurfaceIOS;
+#endif // VK_USE_PLATFORM_IOS_MVK
+
+typedef struct {
+ VkIcdSurfaceBase base;
+ VkDisplayModeKHR displayMode;
+ uint32_t planeIndex;
+ uint32_t planeStackIndex;
+ VkSurfaceTransformFlagBitsKHR transform;
+ float globalAlpha;
+ VkDisplayPlaneAlphaFlagBitsKHR alphaMode;
+ VkExtent2D imageExtent;
+} VkIcdSurfaceDisplay;
+
+typedef struct {
+ VkIcdSurfaceBase base;
+} VkIcdSurfaceHeadless;
+
+#ifdef VK_USE_PLATFORM_METAL_EXT
+typedef struct {
+ VkIcdSurfaceBase base;
+ const CAMetalLayer *pLayer;
+} VkIcdSurfaceMetal;
+#endif // VK_USE_PLATFORM_METAL_EXT
+
+#endif // VKICD_H
diff --git a/thirdparty/vulkan/include/vulkan/vk_layer.h b/thirdparty/vulkan/include/vulkan/vk_layer.h
new file mode 100644
index 0000000000..fa76520089
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vk_layer.h
@@ -0,0 +1,202 @@
+//
+// File: vk_layer.h
+//
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/* Need to define dispatch table
+ * Core struct can then have ptr to dispatch table at the top
+ * Along with object ptrs for current and next OBJ
+ */
+#pragma once
+
+#include "vulkan.h"
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define VK_LAYER_EXPORT __attribute__((visibility("default")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
+#define VK_LAYER_EXPORT __attribute__((visibility("default")))
+#else
+#define VK_LAYER_EXPORT
+#endif
+
+#define MAX_NUM_UNKNOWN_EXTS 250
+
+ // Loader-Layer version negotiation API. Versions add the following features:
+ // Versions 0/1 - Initial. Doesn't support vk_layerGetPhysicalDeviceProcAddr
+ // or vk_icdNegotiateLoaderLayerInterfaceVersion.
+ // Version 2 - Add support for vk_layerGetPhysicalDeviceProcAddr and
+ // vk_icdNegotiateLoaderLayerInterfaceVersion.
+#define CURRENT_LOADER_LAYER_INTERFACE_VERSION 2
+#define MIN_SUPPORTED_LOADER_LAYER_INTERFACE_VERSION 1
+
+#define VK_CURRENT_CHAIN_VERSION 1
+
+// Typedef for use in the interfaces below
+typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName);
+
+// Version negotiation values
+typedef enum VkNegotiateLayerStructType {
+ LAYER_NEGOTIATE_UNINTIALIZED = 0,
+ LAYER_NEGOTIATE_INTERFACE_STRUCT = 1,
+} VkNegotiateLayerStructType;
+
+// Version negotiation structures
+typedef struct VkNegotiateLayerInterface {
+ VkNegotiateLayerStructType sType;
+ void *pNext;
+ uint32_t loaderLayerInterfaceVersion;
+ PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr;
+ PFN_GetPhysicalDeviceProcAddr pfnGetPhysicalDeviceProcAddr;
+} VkNegotiateLayerInterface;
+
+// Version negotiation functions
+typedef VkResult (VKAPI_PTR *PFN_vkNegotiateLoaderLayerInterfaceVersion)(VkNegotiateLayerInterface *pVersionStruct);
+
+// Function prototype for unknown physical device extension command
+typedef VkResult(VKAPI_PTR *PFN_PhysDevExt)(VkPhysicalDevice phys_device);
+
+// ------------------------------------------------------------------------------------------------
+// CreateInstance and CreateDevice support structures
+
+/* Sub type of structure for instance and device loader ext of CreateInfo.
+ * When sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
+ * or sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
+ * then VkLayerFunction indicates struct type pointed to by pNext
+ */
+typedef enum VkLayerFunction_ {
+ VK_LAYER_LINK_INFO = 0,
+ VK_LOADER_DATA_CALLBACK = 1,
+ VK_LOADER_LAYER_CREATE_DEVICE_CALLBACK = 2
+} VkLayerFunction;
+
+typedef struct VkLayerInstanceLink_ {
+ struct VkLayerInstanceLink_ *pNext;
+ PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
+ PFN_GetPhysicalDeviceProcAddr pfnNextGetPhysicalDeviceProcAddr;
+} VkLayerInstanceLink;
+
+/*
+ * When creating the device chain the loader needs to pass
+ * down information about it's device structure needed at
+ * the end of the chain. Passing the data via the
+ * VkLayerDeviceInfo avoids issues with finding the
+ * exact instance being used.
+ */
+typedef struct VkLayerDeviceInfo_ {
+ void *device_info;
+ PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
+} VkLayerDeviceInfo;
+
+typedef VkResult (VKAPI_PTR *PFN_vkSetInstanceLoaderData)(VkInstance instance,
+ void *object);
+typedef VkResult (VKAPI_PTR *PFN_vkSetDeviceLoaderData)(VkDevice device,
+ void *object);
+typedef VkResult (VKAPI_PTR *PFN_vkLayerCreateDevice)(VkInstance instance, VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, PFN_vkGetInstanceProcAddr layerGIPA, PFN_vkGetDeviceProcAddr *nextGDPA);
+typedef void (VKAPI_PTR *PFN_vkLayerDestroyDevice)(VkDevice physicalDevice, const VkAllocationCallbacks *pAllocator, PFN_vkDestroyDevice destroyFunction);
+typedef struct {
+ VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
+ const void *pNext;
+ VkLayerFunction function;
+ union {
+ VkLayerInstanceLink *pLayerInfo;
+ PFN_vkSetInstanceLoaderData pfnSetInstanceLoaderData;
+ struct {
+ PFN_vkLayerCreateDevice pfnLayerCreateDevice;
+ PFN_vkLayerDestroyDevice pfnLayerDestroyDevice;
+ } layerDevice;
+ } u;
+} VkLayerInstanceCreateInfo;
+
+typedef struct VkLayerDeviceLink_ {
+ struct VkLayerDeviceLink_ *pNext;
+ PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr pfnNextGetDeviceProcAddr;
+} VkLayerDeviceLink;
+
+typedef struct {
+ VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
+ const void *pNext;
+ VkLayerFunction function;
+ union {
+ VkLayerDeviceLink *pLayerInfo;
+ PFN_vkSetDeviceLoaderData pfnSetDeviceLoaderData;
+ } u;
+} VkLayerDeviceCreateInfo;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct);
+
+typedef enum VkChainType {
+ VK_CHAIN_TYPE_UNKNOWN = 0,
+ VK_CHAIN_TYPE_ENUMERATE_INSTANCE_EXTENSION_PROPERTIES = 1,
+ VK_CHAIN_TYPE_ENUMERATE_INSTANCE_LAYER_PROPERTIES = 2,
+ VK_CHAIN_TYPE_ENUMERATE_INSTANCE_VERSION = 3,
+} VkChainType;
+
+typedef struct VkChainHeader {
+ VkChainType type;
+ uint32_t version;
+ uint32_t size;
+} VkChainHeader;
+
+typedef struct VkEnumerateInstanceExtensionPropertiesChain {
+ VkChainHeader header;
+ VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceExtensionPropertiesChain *, const char *, uint32_t *,
+ VkExtensionProperties *);
+ const struct VkEnumerateInstanceExtensionPropertiesChain *pNextLink;
+
+#if defined(__cplusplus)
+ inline VkResult CallDown(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) const {
+ return pfnNextLayer(pNextLink, pLayerName, pPropertyCount, pProperties);
+ }
+#endif
+} VkEnumerateInstanceExtensionPropertiesChain;
+
+typedef struct VkEnumerateInstanceLayerPropertiesChain {
+ VkChainHeader header;
+ VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceLayerPropertiesChain *, uint32_t *, VkLayerProperties *);
+ const struct VkEnumerateInstanceLayerPropertiesChain *pNextLink;
+
+#if defined(__cplusplus)
+ inline VkResult CallDown(uint32_t *pPropertyCount, VkLayerProperties *pProperties) const {
+ return pfnNextLayer(pNextLink, pPropertyCount, pProperties);
+ }
+#endif
+} VkEnumerateInstanceLayerPropertiesChain;
+
+typedef struct VkEnumerateInstanceVersionChain {
+ VkChainHeader header;
+ VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceVersionChain *, uint32_t *);
+ const struct VkEnumerateInstanceVersionChain *pNextLink;
+
+#if defined(__cplusplus)
+ inline VkResult CallDown(uint32_t *pApiVersion) const {
+ return pfnNextLayer(pNextLink, pApiVersion);
+ }
+#endif
+} VkEnumerateInstanceVersionChain;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vk_platform.h b/thirdparty/vulkan/include/vulkan/vk_platform.h
new file mode 100644
index 0000000000..7289299240
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vk_platform.h
@@ -0,0 +1,92 @@
+//
+// File: vk_platform.h
+//
+/*
+** Copyright (c) 2014-2017 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+
+#ifndef VK_PLATFORM_H_
+#define VK_PLATFORM_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*
+***************************************************************************************************
+* Platform-specific directives and type declarations
+***************************************************************************************************
+*/
+
+/* Platform-specific calling convention macros.
+ *
+ * Platforms should define these so that Vulkan clients call Vulkan commands
+ * with the same calling conventions that the Vulkan implementation expects.
+ *
+ * VKAPI_ATTR - Placed before the return type in function declarations.
+ * Useful for C++11 and GCC/Clang-style function attribute syntax.
+ * VKAPI_CALL - Placed after the return type in function declarations.
+ * Useful for MSVC-style calling convention syntax.
+ * VKAPI_PTR - Placed between the '(' and '*' in function pointer types.
+ *
+ * Function declaration: VKAPI_ATTR void VKAPI_CALL vkCommand(void);
+ * Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void);
+ */
+#if defined(_WIN32)
+ // On Windows, Vulkan commands use the stdcall convention
+ #define VKAPI_ATTR
+ #define VKAPI_CALL __stdcall
+ #define VKAPI_PTR VKAPI_CALL
+#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
+ #error "Vulkan isn't supported for the 'armeabi' NDK ABI"
+#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
+ // On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
+ // calling convention, i.e. float parameters are passed in registers. This
+ // is true even if the rest of the application passes floats on the stack,
+ // as it does by default when compiling for the armeabi-v7a NDK ABI.
+ #define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
+ #define VKAPI_CALL
+ #define VKAPI_PTR VKAPI_ATTR
+#else
+ // On other platforms, use the default calling convention
+ #define VKAPI_ATTR
+ #define VKAPI_CALL
+ #define VKAPI_PTR
+#endif
+
+#include <stddef.h>
+
+#if !defined(VK_NO_STDINT_H)
+ #if defined(_MSC_VER) && (_MSC_VER < 1600)
+ typedef signed __int8 int8_t;
+ typedef unsigned __int8 uint8_t;
+ typedef signed __int16 int16_t;
+ typedef unsigned __int16 uint16_t;
+ typedef signed __int32 int32_t;
+ typedef unsigned __int32 uint32_t;
+ typedef signed __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+ #else
+ #include <stdint.h>
+ #endif
+#endif // !defined(VK_NO_STDINT_H)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vk_sdk_platform.h b/thirdparty/vulkan/include/vulkan/vk_sdk_platform.h
new file mode 100644
index 0000000000..96d8676949
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vk_sdk_platform.h
@@ -0,0 +1,69 @@
+//
+// File: vk_sdk_platform.h
+//
+/*
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VK_SDK_PLATFORM_H
+#define VK_SDK_PLATFORM_H
+
+#if defined(_WIN32)
+#define NOMINMAX
+#ifndef __cplusplus
+#undef inline
+#define inline __inline
+#endif // __cplusplus
+
+#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
+// C99:
+// Microsoft didn't implement C99 in Visual Studio; but started adding it with
+// VS2013. However, VS2013 still didn't have snprintf(). The following is a
+// work-around (Note: The _CRT_SECURE_NO_WARNINGS macro must be set in the
+// "CMakeLists.txt" file).
+// NOTE: This is fixed in Visual Studio 2015.
+#define snprintf _snprintf
+#endif
+
+#define strdup _strdup
+
+#endif // _WIN32
+
+// Check for noexcept support using clang, with fallback to Windows or GCC version numbers
+#ifndef NOEXCEPT
+#if defined(__clang__)
+#if __has_feature(cxx_noexcept)
+#define HAS_NOEXCEPT
+#endif
+#else
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46
+#define HAS_NOEXCEPT
+#else
+#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026 && defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS
+#define HAS_NOEXCEPT
+#endif
+#endif
+#endif
+
+#ifdef HAS_NOEXCEPT
+#define NOEXCEPT noexcept
+#else
+#define NOEXCEPT
+#endif
+#endif
+
+#endif // VK_SDK_PLATFORM_H
diff --git a/thirdparty/vulkan/include/vulkan/vulkan.h b/thirdparty/vulkan/include/vulkan/vulkan.h
new file mode 100644
index 0000000000..5f853f9fc8
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan.h
@@ -0,0 +1,86 @@
+#ifndef VULKAN_H_
+#define VULKAN_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "vk_platform.h"
+#include "vulkan_core.h"
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+#include "vulkan_android.h"
+#endif
+
+#ifdef VK_USE_PLATFORM_FUCHSIA
+#include <zircon/types.h>
+#include "vulkan_fuchsia.h"
+#endif
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+#include "vulkan_ios.h"
+#endif
+
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+#include "vulkan_macos.h"
+#endif
+
+#ifdef VK_USE_PLATFORM_METAL_EXT
+#include "vulkan_metal.h"
+#endif
+
+#ifdef VK_USE_PLATFORM_VI_NN
+#include "vulkan_vi.h"
+#endif
+
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+#include <wayland-client.h>
+#include "vulkan_wayland.h"
+#endif
+
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#include <windows.h>
+#include "vulkan_win32.h"
+#endif
+
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+#include <xcb/xcb.h>
+#include "vulkan_xcb.h"
+#endif
+
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+#include <X11/Xlib.h>
+#include "vulkan_xlib.h"
+#endif
+
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+#include "vulkan_xlib_xrandr.h"
+#endif
+
+
+#ifdef VK_USE_PLATFORM_GGP
+#include <ggp_c/vulkan_types.h>
+#include "vulkan_ggp.h"
+#endif
+
+#endif // VULKAN_H_
diff --git a/thirdparty/vulkan/include/vulkan/vulkan.hpp b/thirdparty/vulkan/include/vulkan/vulkan.hpp
new file mode 100644
index 0000000000..441869898f
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan.hpp
@@ -0,0 +1,71380 @@
+// Copyright (c) 2015-2020 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// ---- Exceptions to the Apache 2.0 License: ----
+//
+// As an exception, if you use this Software to generate code and portions of
+// this Software are embedded into the generated code as a result, you may
+// redistribute such product without providing attribution as would otherwise
+// be required by Sections 4(a), 4(b) and 4(d) of the License.
+//
+// In addition, if you combine or link code generated by this Software with
+// software that is licensed under the GPLv2 or the LGPL v2.0 or 2.1
+// ("`Combined Software`") and if a court of competent jurisdiction determines
+// that the patent provision (Section 3), the indemnity provision (Section 9)
+// or other Section of the License conflicts with the conditions of the
+// applicable GPL or LGPL license, you may retroactively and prospectively
+// choose to deem waived or otherwise exclude such Section(s) of the License,
+// but only in their entirety and only with respect to the Combined Software.
+//
+
+// This header is generated from the Khronos Vulkan XML API Registry.
+
+#ifndef VULKAN_HPP
+#define VULKAN_HPP
+
+#include <algorithm>
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <initializer_list>
+#include <string>
+#include <system_error>
+#include <tuple>
+#include <type_traits>
+#include <vulkan/vulkan.h>
+
+#if !defined(VULKAN_HPP_DISABLE_ENHANCED_MODE)
+# include <memory>
+# include <vector>
+#endif
+
+#if !defined(VULKAN_HPP_ASSERT)
+# include <cassert>
+# define VULKAN_HPP_ASSERT assert
+#endif
+
+#if !defined(VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL)
+# define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 1
+#endif
+
+#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL == 1
+# if defined(__linux__) || defined(__APPLE__)
+# include <dlfcn.h>
+# endif
+
+# if defined(_WIN32)
+# include <windows.h>
+# endif
+#endif
+
+static_assert( VK_HEADER_VERSION == 131 , "Wrong VK_HEADER_VERSION!" );
+
+// 32-bit vulkan is not typesafe for handles, so don't allow copy constructors on this platform by default.
+// To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION
+#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+# if !defined( VULKAN_HPP_TYPESAFE_CONVERSION )
+# define VULKAN_HPP_TYPESAFE_CONVERSION
+# endif
+#endif
+
+// <tuple> includes <sys/sysmacros.h> through some other header
+// this results in major(x) being resolved to gnu_dev_major(x)
+// which is an expression in a constructor initializer list.
+#if defined(major)
+ #undef major
+#endif
+#if defined(minor)
+ #undef minor
+#endif
+
+// Windows defines MemoryBarrier which is deprecated and collides
+// with the VULKAN_HPP_NAMESPACE::MemoryBarrier struct.
+#if defined(MemoryBarrier)
+ #undef MemoryBarrier
+#endif
+
+#if !defined(VULKAN_HPP_HAS_UNRESTRICTED_UNIONS)
+# if defined(__clang__)
+# if __has_feature(cxx_unrestricted_unions)
+# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
+# endif
+# elif defined(__GNUC__)
+# define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+# if 40600 <= GCC_VERSION
+# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
+# endif
+# elif defined(_MSC_VER)
+# if 1900 <= _MSC_VER
+# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
+# endif
+# endif
+#endif
+
+#if !defined(VULKAN_HPP_INLINE)
+# if defined(__clang__)
+# if __has_attribute(always_inline)
+# define VULKAN_HPP_INLINE __attribute__((always_inline)) __inline__
+# else
+# define VULKAN_HPP_INLINE inline
+# endif
+# elif defined(__GNUC__)
+# define VULKAN_HPP_INLINE __attribute__((always_inline)) __inline__
+# elif defined(_MSC_VER)
+# define VULKAN_HPP_INLINE inline
+# else
+# define VULKAN_HPP_INLINE inline
+# endif
+#endif
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+# define VULKAN_HPP_TYPESAFE_EXPLICIT
+#else
+# define VULKAN_HPP_TYPESAFE_EXPLICIT explicit
+#endif
+
+#if defined(__cpp_constexpr)
+# define VULKAN_HPP_CONSTEXPR constexpr
+# if __cpp_constexpr >= 201304
+# define VULKAN_HPP_CONSTEXPR_14 constexpr
+# else
+# define VULKAN_HPP_CONSTEXPR_14
+# endif
+# define VULKAN_HPP_CONST_OR_CONSTEXPR constexpr
+#else
+# define VULKAN_HPP_CONSTEXPR
+# define VULKAN_HPP_CONSTEXPR_14
+# define VULKAN_HPP_CONST_OR_CONSTEXPR const
+#endif
+
+#if !defined(VULKAN_HPP_NOEXCEPT)
+# if defined(_MSC_VER) && (_MSC_VER <= 1800)
+# define VULKAN_HPP_NOEXCEPT
+# else
+# define VULKAN_HPP_NOEXCEPT noexcept
+# define VULKAN_HPP_HAS_NOEXCEPT 1
+# endif
+#endif
+
+#if !defined(VULKAN_HPP_NAMESPACE)
+#define VULKAN_HPP_NAMESPACE vk
+#endif
+
+#define VULKAN_HPP_STRINGIFY2(text) #text
+#define VULKAN_HPP_STRINGIFY(text) VULKAN_HPP_STRINGIFY2(text)
+#define VULKAN_HPP_NAMESPACE_STRING VULKAN_HPP_STRINGIFY(VULKAN_HPP_NAMESPACE)
+
+namespace VULKAN_HPP_NAMESPACE
+{
+#if !defined(VULKAN_HPP_DISABLE_ENHANCED_MODE)
+ template <typename T>
+ class ArrayProxy
+ {
+ public:
+ VULKAN_HPP_CONSTEXPR ArrayProxy(std::nullptr_t) VULKAN_HPP_NOEXCEPT
+ : m_count(0)
+ , m_ptr(nullptr)
+ {}
+
+ ArrayProxy(typename std::remove_reference<T>::type & ptr) VULKAN_HPP_NOEXCEPT
+ : m_count(1)
+ , m_ptr(&ptr)
+ {}
+
+ ArrayProxy(uint32_t count, T * ptr) VULKAN_HPP_NOEXCEPT
+ : m_count(count)
+ , m_ptr(ptr)
+ {}
+
+ template <size_t N>
+ ArrayProxy(std::array<typename std::remove_const<T>::type, N> & data) VULKAN_HPP_NOEXCEPT
+ : m_count(N)
+ , m_ptr(data.data())
+ {}
+
+ template <size_t N>
+ ArrayProxy(std::array<typename std::remove_const<T>::type, N> const& data) VULKAN_HPP_NOEXCEPT
+ : m_count(N)
+ , m_ptr(data.data())
+ {}
+
+ template <class Allocator = std::allocator<typename std::remove_const<T>::type>>
+ ArrayProxy(std::vector<typename std::remove_const<T>::type, Allocator> & data) VULKAN_HPP_NOEXCEPT
+ : m_count(static_cast<uint32_t>(data.size()))
+ , m_ptr(data.data())
+ {}
+
+ template <class Allocator = std::allocator<typename std::remove_const<T>::type>>
+ ArrayProxy(std::vector<typename std::remove_const<T>::type, Allocator> const& data) VULKAN_HPP_NOEXCEPT
+ : m_count(static_cast<uint32_t>(data.size()))
+ , m_ptr(data.data())
+ {}
+
+ ArrayProxy(std::initializer_list<typename std::remove_reference<T>::type> const& data) VULKAN_HPP_NOEXCEPT
+ : m_count(static_cast<uint32_t>(data.end() - data.begin()))
+ , m_ptr(data.begin())
+ {}
+
+ const T * begin() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_ptr;
+ }
+
+ const T * end() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_ptr + m_count;
+ }
+
+ const T & front() const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_ASSERT(m_count && m_ptr);
+ return *m_ptr;
+ }
+
+ const T & back() const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_ASSERT(m_count && m_ptr);
+ return *(m_ptr + m_count - 1);
+ }
+
+ bool empty() const VULKAN_HPP_NOEXCEPT
+ {
+ return (m_count == 0);
+ }
+
+ uint32_t size() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_count;
+ }
+
+ T * data() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_ptr;
+ }
+
+ private:
+ uint32_t m_count;
+ T * m_ptr;
+ };
+#endif
+
+ template <typename FlagBitsType> struct FlagTraits
+ {
+ enum { allFlags = 0 };
+ };
+
+ template <typename BitType, typename MaskType = VkFlags>
+ class Flags
+ {
+ public:
+ // constructors
+ VULKAN_HPP_CONSTEXPR Flags() VULKAN_HPP_NOEXCEPT
+ : m_mask(0)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Flags(BitType bit) VULKAN_HPP_NOEXCEPT
+ : m_mask(static_cast<MaskType>(bit))
+ {}
+
+ VULKAN_HPP_CONSTEXPR Flags(Flags<BitType, MaskType> const& rhs) VULKAN_HPP_NOEXCEPT
+ : m_mask(rhs.m_mask)
+ {}
+
+ VULKAN_HPP_CONSTEXPR explicit Flags(MaskType flags) VULKAN_HPP_NOEXCEPT
+ : m_mask(flags)
+ {}
+
+ // relational operators
+ VULKAN_HPP_CONSTEXPR bool operator<(Flags<BitType, MaskType> const& rhs) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_mask < rhs.m_mask;
+ }
+
+ VULKAN_HPP_CONSTEXPR bool operator<=(Flags<BitType, MaskType> const& rhs) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_mask <= rhs.m_mask;
+ }
+
+ VULKAN_HPP_CONSTEXPR bool operator>(Flags<BitType, MaskType> const& rhs) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_mask > rhs.m_mask;
+ }
+
+ VULKAN_HPP_CONSTEXPR bool operator>=(Flags<BitType, MaskType> const& rhs) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_mask >= rhs.m_mask;
+ }
+
+ VULKAN_HPP_CONSTEXPR bool operator==(Flags<BitType, MaskType> const& rhs) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_mask == rhs.m_mask;
+ }
+
+ VULKAN_HPP_CONSTEXPR bool operator!=(Flags<BitType, MaskType> const& rhs) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_mask != rhs.m_mask;
+ }
+
+ // logical operator
+ VULKAN_HPP_CONSTEXPR bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return !m_mask;
+ }
+
+ // bitwise operators
+ VULKAN_HPP_CONSTEXPR Flags<BitType, MaskType> operator&(Flags<BitType, MaskType> const& rhs) const VULKAN_HPP_NOEXCEPT
+ {
+ return Flags<BitType, MaskType>(m_mask & rhs.m_mask);
+ }
+
+ VULKAN_HPP_CONSTEXPR Flags<BitType, MaskType> operator|(Flags<BitType, MaskType> const& rhs) const VULKAN_HPP_NOEXCEPT
+ {
+ return Flags<BitType, MaskType>(m_mask | rhs.m_mask);
+ }
+
+ VULKAN_HPP_CONSTEXPR Flags<BitType, MaskType> operator^(Flags<BitType, MaskType> const& rhs) const VULKAN_HPP_NOEXCEPT
+ {
+ return Flags<BitType, MaskType>(m_mask ^ rhs.m_mask);
+ }
+
+ VULKAN_HPP_CONSTEXPR Flags<BitType, MaskType> operator~() const VULKAN_HPP_NOEXCEPT
+ {
+ return Flags<BitType, MaskType>(m_mask ^ FlagTraits<BitType>::allFlags);
+ }
+
+ // assignment operators
+ Flags<BitType, MaskType> & operator=(Flags<BitType, MaskType> const& rhs) VULKAN_HPP_NOEXCEPT
+ {
+ m_mask = rhs.m_mask;
+ return *this;
+ }
+
+ Flags<BitType, MaskType> & operator|=(Flags<BitType, MaskType> const& rhs) VULKAN_HPP_NOEXCEPT
+ {
+ m_mask |= rhs.m_mask;
+ return *this;
+ }
+
+ Flags<BitType, MaskType> & operator&=(Flags<BitType, MaskType> const& rhs) VULKAN_HPP_NOEXCEPT
+ {
+ m_mask &= rhs.m_mask;
+ return *this;
+ }
+
+ Flags<BitType, MaskType> & operator^=(Flags<BitType, MaskType> const& rhs) VULKAN_HPP_NOEXCEPT
+ {
+ m_mask ^= rhs.m_mask;
+ return *this;
+ }
+
+ // cast operators
+ explicit VULKAN_HPP_CONSTEXPR operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return !!m_mask;
+ }
+
+ explicit VULKAN_HPP_CONSTEXPR operator MaskType() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_mask;
+ }
+
+ private:
+ MaskType m_mask;
+ };
+
+ // relational operators
+ template <typename BitType, typename MaskType = VkFlags>
+ VULKAN_HPP_CONSTEXPR bool operator<(BitType bit, Flags<BitType, MaskType> const& flags) VULKAN_HPP_NOEXCEPT
+ {
+ return flags > bit;
+ }
+
+ template <typename BitType, typename MaskType = VkFlags>
+ VULKAN_HPP_CONSTEXPR bool operator<=(BitType bit, Flags<BitType, MaskType> const& flags) VULKAN_HPP_NOEXCEPT
+ {
+ return flags >= bit;
+ }
+
+ template <typename BitType, typename MaskType = VkFlags>
+ VULKAN_HPP_CONSTEXPR bool operator>(BitType bit, Flags<BitType, MaskType> const& flags) VULKAN_HPP_NOEXCEPT
+ {
+ return flags < bit;
+ }
+
+ template <typename BitType, typename MaskType = VkFlags>
+ VULKAN_HPP_CONSTEXPR bool operator>=(BitType bit, Flags<BitType, MaskType> const& flags) VULKAN_HPP_NOEXCEPT
+ {
+ return flags <= bit;
+ }
+
+ template <typename BitType, typename MaskType = VkFlags>
+ VULKAN_HPP_CONSTEXPR bool operator==(BitType bit, Flags<BitType, MaskType> const& flags) VULKAN_HPP_NOEXCEPT
+ {
+ return flags == bit;
+ }
+
+ template <typename BitType, typename MaskType = VkFlags>
+ VULKAN_HPP_CONSTEXPR bool operator!=(BitType bit, Flags<BitType, MaskType> const& flags) VULKAN_HPP_NOEXCEPT
+ {
+ return flags != bit;
+ }
+
+ // bitwise operators
+ template <typename BitType, typename MaskType = VkFlags>
+ VULKAN_HPP_CONSTEXPR Flags<BitType, MaskType> operator&(BitType bit, Flags<BitType, MaskType> const& flags) VULKAN_HPP_NOEXCEPT
+ {
+ return flags & bit;
+ }
+
+ template <typename BitType, typename MaskType = VkFlags>
+ VULKAN_HPP_CONSTEXPR Flags<BitType, MaskType> operator|(BitType bit, Flags<BitType, MaskType> const& flags) VULKAN_HPP_NOEXCEPT
+ {
+ return flags | bit;
+ }
+
+ template <typename BitType, typename MaskType = VkFlags>
+ VULKAN_HPP_CONSTEXPR Flags<BitType, MaskType> operator^(BitType bit, Flags<BitType, MaskType> const& flags) VULKAN_HPP_NOEXCEPT
+ {
+ return flags ^ bit;
+ }
+
+ template <typename RefType>
+ class Optional
+ {
+ public:
+ Optional(RefType & reference) VULKAN_HPP_NOEXCEPT { m_ptr = &reference; }
+ Optional(RefType * ptr) VULKAN_HPP_NOEXCEPT { m_ptr = ptr; }
+ Optional(std::nullptr_t) VULKAN_HPP_NOEXCEPT { m_ptr = nullptr; }
+
+ operator RefType*() const VULKAN_HPP_NOEXCEPT { return m_ptr; }
+ RefType const* operator->() const VULKAN_HPP_NOEXCEPT { return m_ptr; }
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT { return !!m_ptr; }
+
+ private:
+ RefType *m_ptr;
+ };
+
+ template <typename X, typename Y> struct isStructureChainValid { enum { value = false }; };
+
+ template <typename P, typename T>
+ struct TypeList
+ {
+ using list = P;
+ using last = T;
+ };
+
+ template <typename List, typename X>
+ struct extendCheck
+ {
+ static const bool valid = isStructureChainValid<typename List::last, X>::value || extendCheck<typename List::list,X>::valid;
+ };
+
+ template <typename T, typename X>
+ struct extendCheck<TypeList<void,T>,X>
+ {
+ static const bool valid = isStructureChainValid<T, X>::value;
+ };
+
+ template <typename X>
+ struct extendCheck<void,X>
+ {
+ static const bool valid = true;
+ };
+
+ template<typename Type, class...>
+ struct isPartOfStructureChain
+ {
+ static const bool valid = false;
+ };
+
+ template<typename Type, typename Head, typename... Tail>
+ struct isPartOfStructureChain<Type, Head, Tail...>
+ {
+ static const bool valid = std::is_same<Type, Head>::value || isPartOfStructureChain<Type, Tail...>::valid;
+ };
+
+ template <class Element>
+ class StructureChainElement
+ {
+ public:
+ explicit operator Element&() VULKAN_HPP_NOEXCEPT { return value; }
+ explicit operator const Element&() const VULKAN_HPP_NOEXCEPT { return value; }
+ private:
+ Element value;
+ };
+
+ template<typename ...StructureElements>
+ class StructureChain : private StructureChainElement<StructureElements>...
+ {
+ public:
+ StructureChain() VULKAN_HPP_NOEXCEPT
+ {
+ link<void, StructureElements...>();
+ }
+
+ StructureChain(StructureChain const &rhs) VULKAN_HPP_NOEXCEPT
+ {
+ linkAndCopy<void, StructureElements...>(rhs);
+ }
+
+ StructureChain(StructureElements const &... elems) VULKAN_HPP_NOEXCEPT
+ {
+ linkAndCopyElements<void, StructureElements...>(elems...);
+ }
+
+ StructureChain& operator=(StructureChain const &rhs) VULKAN_HPP_NOEXCEPT
+ {
+ linkAndCopy<void, StructureElements...>(rhs);
+ return *this;
+ }
+
+ template<typename ClassType> ClassType& get() VULKAN_HPP_NOEXCEPT { return static_cast<ClassType&>(*this);}
+
+ template<typename ClassTypeA, typename ClassTypeB, typename ...ClassTypes>
+ std::tuple<ClassTypeA, ClassTypeB, ClassTypes...> get()
+ {
+ return std::tuple_cat(
+ std::make_tuple(get<ClassTypeA>(),get<ClassTypeB>()),
+ std::make_tuple(get<ClassTypes>()...)
+ );
+ }
+
+ template<typename ClassType>
+ void unlink() VULKAN_HPP_NOEXCEPT
+ {
+ static_assert(isPartOfStructureChain<ClassType, StructureElements...>::valid, "Can't unlink Structure that's not part of this StructureChain!");
+ static_assert(!std::is_same<ClassType, typename std::tuple_element<0, std::tuple<StructureElements...>>::type>::value, "It's not allowed to unlink the first element!");
+ VkBaseOutStructure * ptr = reinterpret_cast<VkBaseOutStructure*>(&get<ClassType>());
+ assert(ptr != nullptr);
+ VkBaseOutStructure ** ppNext = &(reinterpret_cast<VkBaseOutStructure*>(this)->pNext);
+ assert(*ppNext != nullptr);
+ while (*ppNext != ptr)
+ {
+ ppNext = &(*ppNext)->pNext;
+ assert(*ppNext != nullptr); // fires, if the ClassType member has already been unlinked !
+ }
+ assert(*ppNext == ptr);
+ *ppNext = (*ppNext)->pNext;
+ }
+
+ template <typename ClassType>
+ void relink() VULKAN_HPP_NOEXCEPT
+ {
+ static_assert(isPartOfStructureChain<ClassType, StructureElements...>::valid, "Can't relink Structure that's not part of this StructureChain!");
+ static_assert(!std::is_same<ClassType, typename std::tuple_element<0, std::tuple<StructureElements...>>::type>::value, "It's not allowed to have the first element unlinked!");
+ VkBaseOutStructure * ptr = reinterpret_cast<VkBaseOutStructure*>(&get<ClassType>());
+ assert(ptr != nullptr);
+ VkBaseOutStructure ** ppNext = &(reinterpret_cast<VkBaseOutStructure*>(this)->pNext);
+ assert(*ppNext != nullptr);
+#if !defined(NDEBUG)
+ while (*ppNext)
+ {
+ assert(*ppNext != ptr); // fires, if the ClassType member has not been unlinked before
+ ppNext = &(*ppNext)->pNext;
+ }
+ ppNext = &(reinterpret_cast<VkBaseOutStructure*>(this)->pNext);
+#endif
+ ptr->pNext = *ppNext;
+ *ppNext = ptr;
+ }
+
+ private:
+ template<typename List, typename X>
+ void link() VULKAN_HPP_NOEXCEPT
+ {
+ static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
+ }
+
+ template<typename List, typename X, typename Y, typename ...Z>
+ void link() VULKAN_HPP_NOEXCEPT
+ {
+ static_assert(extendCheck<List,X>::valid, "The structure chain is not valid!");
+ X& x = static_cast<X&>(*this);
+ Y& y = static_cast<Y&>(*this);
+ x.pNext = &y;
+ link<TypeList<List, X>, Y, Z...>();
+ }
+
+ template<typename List, typename X>
+ void linkAndCopy(StructureChain const &rhs) VULKAN_HPP_NOEXCEPT
+ {
+ static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
+ static_cast<X&>(*this) = static_cast<X const &>(rhs);
+ }
+
+ template<typename List, typename X, typename Y, typename ...Z>
+ void linkAndCopy(StructureChain const &rhs) VULKAN_HPP_NOEXCEPT
+ {
+ static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
+ X& x = static_cast<X&>(*this);
+ Y& y = static_cast<Y&>(*this);
+ x = static_cast<X const &>(rhs);
+ x.pNext = &y;
+ linkAndCopy<TypeList<List, X>, Y, Z...>(rhs);
+ }
+
+ template<typename List, typename X>
+ void linkAndCopyElements(X const &xelem) VULKAN_HPP_NOEXCEPT
+ {
+ static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
+ static_cast<X&>(*this) = xelem;
+ }
+
+ template<typename List, typename X, typename Y, typename ...Z>
+ void linkAndCopyElements(X const &xelem, Y const &yelem, Z const &... zelem) VULKAN_HPP_NOEXCEPT
+ {
+ static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
+ X& x = static_cast<X&>(*this);
+ Y& y = static_cast<Y&>(*this);
+ x = xelem;
+ x.pNext = &y;
+ linkAndCopyElements<TypeList<List, X>, Y, Z...>(yelem, zelem...);
+ }
+ };
+
+#if !defined(VULKAN_HPP_NO_SMART_HANDLE)
+ template <typename Type, typename Dispatch> class UniqueHandleTraits;
+
+ template <typename Type, typename Dispatch>
+ class UniqueHandle : public UniqueHandleTraits<Type,Dispatch>::deleter
+ {
+ private:
+ using Deleter = typename UniqueHandleTraits<Type,Dispatch>::deleter;
+
+ public:
+ using element_type = Type;
+
+ UniqueHandle()
+ : Deleter()
+ , m_value()
+ {}
+
+ explicit UniqueHandle( Type const& value, Deleter const& deleter = Deleter() ) VULKAN_HPP_NOEXCEPT
+ : Deleter( deleter)
+ , m_value( value )
+ {}
+
+ UniqueHandle( UniqueHandle const& ) = delete;
+
+ UniqueHandle( UniqueHandle && other ) VULKAN_HPP_NOEXCEPT
+ : Deleter( std::move( static_cast<Deleter&>( other ) ) )
+ , m_value( other.release() )
+ {}
+
+ ~UniqueHandle() VULKAN_HPP_NOEXCEPT
+ {
+ if ( m_value ) this->destroy( m_value );
+ }
+
+ UniqueHandle & operator=( UniqueHandle const& ) = delete;
+
+ UniqueHandle & operator=( UniqueHandle && other ) VULKAN_HPP_NOEXCEPT
+ {
+ reset( other.release() );
+ *static_cast<Deleter*>(this) = std::move( static_cast<Deleter&>(other) );
+ return *this;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_value.operator bool();
+ }
+
+ Type const* operator->() const VULKAN_HPP_NOEXCEPT
+ {
+ return &m_value;
+ }
+
+ Type * operator->() VULKAN_HPP_NOEXCEPT
+ {
+ return &m_value;
+ }
+
+ Type const& operator*() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_value;
+ }
+
+ Type & operator*() VULKAN_HPP_NOEXCEPT
+ {
+ return m_value;
+ }
+
+ const Type & get() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_value;
+ }
+
+ Type & get() VULKAN_HPP_NOEXCEPT
+ {
+ return m_value;
+ }
+
+ void reset( Type const& value = Type() ) VULKAN_HPP_NOEXCEPT
+ {
+ if ( m_value != value )
+ {
+ if ( m_value ) this->destroy( m_value );
+ m_value = value;
+ }
+ }
+
+ Type release() VULKAN_HPP_NOEXCEPT
+ {
+ Type value = m_value;
+ m_value = nullptr;
+ return value;
+ }
+
+ void swap( UniqueHandle<Type,Dispatch> & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ std::swap(m_value, rhs.m_value);
+ std::swap(static_cast<Deleter&>(*this), static_cast<Deleter&>(rhs));
+ }
+
+ private:
+ Type m_value;
+ };
+
+ template <typename UniqueType>
+ VULKAN_HPP_INLINE std::vector<typename UniqueType::element_type> uniqueToRaw(std::vector<UniqueType> const& handles)
+ {
+ std::vector<typename UniqueType::element_type> newBuffer(handles.size());
+ std::transform(handles.begin(), handles.end(), newBuffer.begin(), [](UniqueType const& handle) { return handle.get(); });
+ return newBuffer;
+ }
+
+ template <typename Type, typename Dispatch>
+ VULKAN_HPP_INLINE void swap( UniqueHandle<Type,Dispatch> & lhs, UniqueHandle<Type,Dispatch> & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ lhs.swap( rhs );
+ }
+#endif
+
+#if !defined(VK_NO_PROTOTYPES)
+ class DispatchLoaderStatic
+ {
+ public:
+ VkResult vkCreateInstance( const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateInstance( pCreateInfo, pAllocator, pInstance );
+ }
+
+ VkResult vkEnumerateInstanceExtensionProperties( const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkEnumerateInstanceExtensionProperties( pLayerName, pPropertyCount, pProperties );
+ }
+
+ VkResult vkEnumerateInstanceLayerProperties( uint32_t* pPropertyCount, VkLayerProperties* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkEnumerateInstanceLayerProperties( pPropertyCount, pProperties );
+ }
+
+ VkResult vkEnumerateInstanceVersion( uint32_t* pApiVersion ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkEnumerateInstanceVersion( pApiVersion );
+ }
+
+ VkResult vkBeginCommandBuffer( VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkBeginCommandBuffer( commandBuffer, pBeginInfo );
+ }
+
+ void vkCmdBeginConditionalRenderingEXT( VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBeginConditionalRenderingEXT( commandBuffer, pConditionalRenderingBegin );
+ }
+
+ void vkCmdBeginDebugUtilsLabelEXT( VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBeginDebugUtilsLabelEXT( commandBuffer, pLabelInfo );
+ }
+
+ void vkCmdBeginQuery( VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBeginQuery( commandBuffer, queryPool, query, flags );
+ }
+
+ void vkCmdBeginQueryIndexedEXT( VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBeginQueryIndexedEXT( commandBuffer, queryPool, query, flags, index );
+ }
+
+ void vkCmdBeginRenderPass( VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBeginRenderPass( commandBuffer, pRenderPassBegin, contents );
+ }
+
+ void vkCmdBeginRenderPass2( VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBeginRenderPass2( commandBuffer, pRenderPassBegin, pSubpassBeginInfo );
+ }
+
+ void vkCmdBeginRenderPass2KHR( VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBeginRenderPass2KHR( commandBuffer, pRenderPassBegin, pSubpassBeginInfo );
+ }
+
+ void vkCmdBeginTransformFeedbackEXT( VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBeginTransformFeedbackEXT( commandBuffer, firstCounterBuffer, counterBufferCount, pCounterBuffers, pCounterBufferOffsets );
+ }
+
+ void vkCmdBindDescriptorSets( VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBindDescriptorSets( commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets );
+ }
+
+ void vkCmdBindIndexBuffer( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBindIndexBuffer( commandBuffer, buffer, offset, indexType );
+ }
+
+ void vkCmdBindPipeline( VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBindPipeline( commandBuffer, pipelineBindPoint, pipeline );
+ }
+
+ void vkCmdBindShadingRateImageNV( VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBindShadingRateImageNV( commandBuffer, imageView, imageLayout );
+ }
+
+ void vkCmdBindTransformFeedbackBuffersEXT( VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBindTransformFeedbackBuffersEXT( commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets, pSizes );
+ }
+
+ void vkCmdBindVertexBuffers( VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBindVertexBuffers( commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets );
+ }
+
+ void vkCmdBlitImage( VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBlitImage( commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter );
+ }
+
+ void vkCmdBuildAccelerationStructureNV( VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdBuildAccelerationStructureNV( commandBuffer, pInfo, instanceData, instanceOffset, update, dst, src, scratch, scratchOffset );
+ }
+
+ void vkCmdClearAttachments( VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdClearAttachments( commandBuffer, attachmentCount, pAttachments, rectCount, pRects );
+ }
+
+ void vkCmdClearColorImage( VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdClearColorImage( commandBuffer, image, imageLayout, pColor, rangeCount, pRanges );
+ }
+
+ void vkCmdClearDepthStencilImage( VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdClearDepthStencilImage( commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges );
+ }
+
+ void vkCmdCopyAccelerationStructureNV( VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeNV mode ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdCopyAccelerationStructureNV( commandBuffer, dst, src, mode );
+ }
+
+ void vkCmdCopyBuffer( VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdCopyBuffer( commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions );
+ }
+
+ void vkCmdCopyBufferToImage( VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdCopyBufferToImage( commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions );
+ }
+
+ void vkCmdCopyImage( VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdCopyImage( commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions );
+ }
+
+ void vkCmdCopyImageToBuffer( VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdCopyImageToBuffer( commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions );
+ }
+
+ void vkCmdCopyQueryPoolResults( VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdCopyQueryPoolResults( commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags );
+ }
+
+ void vkCmdDebugMarkerBeginEXT( VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDebugMarkerBeginEXT( commandBuffer, pMarkerInfo );
+ }
+
+ void vkCmdDebugMarkerEndEXT( VkCommandBuffer commandBuffer ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDebugMarkerEndEXT( commandBuffer );
+ }
+
+ void vkCmdDebugMarkerInsertEXT( VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDebugMarkerInsertEXT( commandBuffer, pMarkerInfo );
+ }
+
+ void vkCmdDispatch( VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDispatch( commandBuffer, groupCountX, groupCountY, groupCountZ );
+ }
+
+ void vkCmdDispatchBase( VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDispatchBase( commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ );
+ }
+
+ void vkCmdDispatchBaseKHR( VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDispatchBaseKHR( commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ );
+ }
+
+ void vkCmdDispatchIndirect( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDispatchIndirect( commandBuffer, buffer, offset );
+ }
+
+ void vkCmdDraw( VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDraw( commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance );
+ }
+
+ void vkCmdDrawIndexed( VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawIndexed( commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance );
+ }
+
+ void vkCmdDrawIndexedIndirect( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawIndexedIndirect( commandBuffer, buffer, offset, drawCount, stride );
+ }
+
+ void vkCmdDrawIndexedIndirectCount( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawIndexedIndirectCount( commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride );
+ }
+
+ void vkCmdDrawIndexedIndirectCountAMD( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawIndexedIndirectCountAMD( commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride );
+ }
+
+ void vkCmdDrawIndexedIndirectCountKHR( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawIndexedIndirectCountKHR( commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride );
+ }
+
+ void vkCmdDrawIndirect( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawIndirect( commandBuffer, buffer, offset, drawCount, stride );
+ }
+
+ void vkCmdDrawIndirectByteCountEXT( VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawIndirectByteCountEXT( commandBuffer, instanceCount, firstInstance, counterBuffer, counterBufferOffset, counterOffset, vertexStride );
+ }
+
+ void vkCmdDrawIndirectCount( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawIndirectCount( commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride );
+ }
+
+ void vkCmdDrawIndirectCountAMD( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawIndirectCountAMD( commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride );
+ }
+
+ void vkCmdDrawIndirectCountKHR( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawIndirectCountKHR( commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride );
+ }
+
+ void vkCmdDrawMeshTasksIndirectCountNV( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawMeshTasksIndirectCountNV( commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride );
+ }
+
+ void vkCmdDrawMeshTasksIndirectNV( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawMeshTasksIndirectNV( commandBuffer, buffer, offset, drawCount, stride );
+ }
+
+ void vkCmdDrawMeshTasksNV( VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdDrawMeshTasksNV( commandBuffer, taskCount, firstTask );
+ }
+
+ void vkCmdEndConditionalRenderingEXT( VkCommandBuffer commandBuffer ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdEndConditionalRenderingEXT( commandBuffer );
+ }
+
+ void vkCmdEndDebugUtilsLabelEXT( VkCommandBuffer commandBuffer ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdEndDebugUtilsLabelEXT( commandBuffer );
+ }
+
+ void vkCmdEndQuery( VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdEndQuery( commandBuffer, queryPool, query );
+ }
+
+ void vkCmdEndQueryIndexedEXT( VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdEndQueryIndexedEXT( commandBuffer, queryPool, query, index );
+ }
+
+ void vkCmdEndRenderPass( VkCommandBuffer commandBuffer ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdEndRenderPass( commandBuffer );
+ }
+
+ void vkCmdEndRenderPass2( VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdEndRenderPass2( commandBuffer, pSubpassEndInfo );
+ }
+
+ void vkCmdEndRenderPass2KHR( VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdEndRenderPass2KHR( commandBuffer, pSubpassEndInfo );
+ }
+
+ void vkCmdEndTransformFeedbackEXT( VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdEndTransformFeedbackEXT( commandBuffer, firstCounterBuffer, counterBufferCount, pCounterBuffers, pCounterBufferOffsets );
+ }
+
+ void vkCmdExecuteCommands( VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdExecuteCommands( commandBuffer, commandBufferCount, pCommandBuffers );
+ }
+
+ void vkCmdFillBuffer( VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdFillBuffer( commandBuffer, dstBuffer, dstOffset, size, data );
+ }
+
+ void vkCmdInsertDebugUtilsLabelEXT( VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdInsertDebugUtilsLabelEXT( commandBuffer, pLabelInfo );
+ }
+
+ void vkCmdNextSubpass( VkCommandBuffer commandBuffer, VkSubpassContents contents ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdNextSubpass( commandBuffer, contents );
+ }
+
+ void vkCmdNextSubpass2( VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdNextSubpass2( commandBuffer, pSubpassBeginInfo, pSubpassEndInfo );
+ }
+
+ void vkCmdNextSubpass2KHR( VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdNextSubpass2KHR( commandBuffer, pSubpassBeginInfo, pSubpassEndInfo );
+ }
+
+ void vkCmdPipelineBarrier( VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdPipelineBarrier( commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers );
+ }
+
+ void vkCmdProcessCommandsNVX( VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdProcessCommandsNVX( commandBuffer, pProcessCommandsInfo );
+ }
+
+ void vkCmdPushConstants( VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdPushConstants( commandBuffer, layout, stageFlags, offset, size, pValues );
+ }
+
+ void vkCmdPushDescriptorSetKHR( VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdPushDescriptorSetKHR( commandBuffer, pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites );
+ }
+
+ void vkCmdPushDescriptorSetWithTemplateKHR( VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdPushDescriptorSetWithTemplateKHR( commandBuffer, descriptorUpdateTemplate, layout, set, pData );
+ }
+
+ void vkCmdReserveSpaceForCommandsNVX( VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdReserveSpaceForCommandsNVX( commandBuffer, pReserveSpaceInfo );
+ }
+
+ void vkCmdResetEvent( VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdResetEvent( commandBuffer, event, stageMask );
+ }
+
+ void vkCmdResetQueryPool( VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdResetQueryPool( commandBuffer, queryPool, firstQuery, queryCount );
+ }
+
+ void vkCmdResolveImage( VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdResolveImage( commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions );
+ }
+
+ void vkCmdSetBlendConstants( VkCommandBuffer commandBuffer, const float blendConstants[4] ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetBlendConstants( commandBuffer, blendConstants );
+ }
+
+ void vkCmdSetCheckpointNV( VkCommandBuffer commandBuffer, const void* pCheckpointMarker ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetCheckpointNV( commandBuffer, pCheckpointMarker );
+ }
+
+ void vkCmdSetCoarseSampleOrderNV( VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetCoarseSampleOrderNV( commandBuffer, sampleOrderType, customSampleOrderCount, pCustomSampleOrders );
+ }
+
+ void vkCmdSetDepthBias( VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetDepthBias( commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor );
+ }
+
+ void vkCmdSetDepthBounds( VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetDepthBounds( commandBuffer, minDepthBounds, maxDepthBounds );
+ }
+
+ void vkCmdSetDeviceMask( VkCommandBuffer commandBuffer, uint32_t deviceMask ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetDeviceMask( commandBuffer, deviceMask );
+ }
+
+ void vkCmdSetDeviceMaskKHR( VkCommandBuffer commandBuffer, uint32_t deviceMask ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetDeviceMaskKHR( commandBuffer, deviceMask );
+ }
+
+ void vkCmdSetDiscardRectangleEXT( VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetDiscardRectangleEXT( commandBuffer, firstDiscardRectangle, discardRectangleCount, pDiscardRectangles );
+ }
+
+ void vkCmdSetEvent( VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetEvent( commandBuffer, event, stageMask );
+ }
+
+ void vkCmdSetExclusiveScissorNV( VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetExclusiveScissorNV( commandBuffer, firstExclusiveScissor, exclusiveScissorCount, pExclusiveScissors );
+ }
+
+ void vkCmdSetLineStippleEXT( VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetLineStippleEXT( commandBuffer, lineStippleFactor, lineStipplePattern );
+ }
+
+ void vkCmdSetLineWidth( VkCommandBuffer commandBuffer, float lineWidth ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetLineWidth( commandBuffer, lineWidth );
+ }
+
+ VkResult vkCmdSetPerformanceMarkerINTEL( VkCommandBuffer commandBuffer, const VkPerformanceMarkerInfoINTEL* pMarkerInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetPerformanceMarkerINTEL( commandBuffer, pMarkerInfo );
+ }
+
+ VkResult vkCmdSetPerformanceOverrideINTEL( VkCommandBuffer commandBuffer, const VkPerformanceOverrideInfoINTEL* pOverrideInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetPerformanceOverrideINTEL( commandBuffer, pOverrideInfo );
+ }
+
+ VkResult vkCmdSetPerformanceStreamMarkerINTEL( VkCommandBuffer commandBuffer, const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetPerformanceStreamMarkerINTEL( commandBuffer, pMarkerInfo );
+ }
+
+ void vkCmdSetSampleLocationsEXT( VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetSampleLocationsEXT( commandBuffer, pSampleLocationsInfo );
+ }
+
+ void vkCmdSetScissor( VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetScissor( commandBuffer, firstScissor, scissorCount, pScissors );
+ }
+
+ void vkCmdSetStencilCompareMask( VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetStencilCompareMask( commandBuffer, faceMask, compareMask );
+ }
+
+ void vkCmdSetStencilReference( VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetStencilReference( commandBuffer, faceMask, reference );
+ }
+
+ void vkCmdSetStencilWriteMask( VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetStencilWriteMask( commandBuffer, faceMask, writeMask );
+ }
+
+ void vkCmdSetViewport( VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetViewport( commandBuffer, firstViewport, viewportCount, pViewports );
+ }
+
+ void vkCmdSetViewportShadingRatePaletteNV( VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetViewportShadingRatePaletteNV( commandBuffer, firstViewport, viewportCount, pShadingRatePalettes );
+ }
+
+ void vkCmdSetViewportWScalingNV( VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdSetViewportWScalingNV( commandBuffer, firstViewport, viewportCount, pViewportWScalings );
+ }
+
+ void vkCmdTraceRaysNV( VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdTraceRaysNV( commandBuffer, raygenShaderBindingTableBuffer, raygenShaderBindingOffset, missShaderBindingTableBuffer, missShaderBindingOffset, missShaderBindingStride, hitShaderBindingTableBuffer, hitShaderBindingOffset, hitShaderBindingStride, callableShaderBindingTableBuffer, callableShaderBindingOffset, callableShaderBindingStride, width, height, depth );
+ }
+
+ void vkCmdUpdateBuffer( VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdUpdateBuffer( commandBuffer, dstBuffer, dstOffset, dataSize, pData );
+ }
+
+ void vkCmdWaitEvents( VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdWaitEvents( commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers );
+ }
+
+ void vkCmdWriteAccelerationStructuresPropertiesNV( VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdWriteAccelerationStructuresPropertiesNV( commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery );
+ }
+
+ void vkCmdWriteBufferMarkerAMD( VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdWriteBufferMarkerAMD( commandBuffer, pipelineStage, dstBuffer, dstOffset, marker );
+ }
+
+ void vkCmdWriteTimestamp( VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCmdWriteTimestamp( commandBuffer, pipelineStage, queryPool, query );
+ }
+
+ VkResult vkEndCommandBuffer( VkCommandBuffer commandBuffer ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkEndCommandBuffer( commandBuffer );
+ }
+
+ VkResult vkResetCommandBuffer( VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkResetCommandBuffer( commandBuffer, flags );
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkAcquireFullScreenExclusiveModeEXT( VkDevice device, VkSwapchainKHR swapchain ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkAcquireFullScreenExclusiveModeEXT( device, swapchain );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ VkResult vkAcquireNextImage2KHR( VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkAcquireNextImage2KHR( device, pAcquireInfo, pImageIndex );
+ }
+
+ VkResult vkAcquireNextImageKHR( VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkAcquireNextImageKHR( device, swapchain, timeout, semaphore, fence, pImageIndex );
+ }
+
+ VkResult vkAcquirePerformanceConfigurationINTEL( VkDevice device, const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VkPerformanceConfigurationINTEL* pConfiguration ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkAcquirePerformanceConfigurationINTEL( device, pAcquireInfo, pConfiguration );
+ }
+
+ VkResult vkAcquireProfilingLockKHR( VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkAcquireProfilingLockKHR( device, pInfo );
+ }
+
+ VkResult vkAllocateCommandBuffers( VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkAllocateCommandBuffers( device, pAllocateInfo, pCommandBuffers );
+ }
+
+ VkResult vkAllocateDescriptorSets( VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkAllocateDescriptorSets( device, pAllocateInfo, pDescriptorSets );
+ }
+
+ VkResult vkAllocateMemory( VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkAllocateMemory( device, pAllocateInfo, pAllocator, pMemory );
+ }
+
+ VkResult vkBindAccelerationStructureMemoryNV( VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkBindAccelerationStructureMemoryNV( device, bindInfoCount, pBindInfos );
+ }
+
+ VkResult vkBindBufferMemory( VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkBindBufferMemory( device, buffer, memory, memoryOffset );
+ }
+
+ VkResult vkBindBufferMemory2( VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkBindBufferMemory2( device, bindInfoCount, pBindInfos );
+ }
+
+ VkResult vkBindBufferMemory2KHR( VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkBindBufferMemory2KHR( device, bindInfoCount, pBindInfos );
+ }
+
+ VkResult vkBindImageMemory( VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkBindImageMemory( device, image, memory, memoryOffset );
+ }
+
+ VkResult vkBindImageMemory2( VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkBindImageMemory2( device, bindInfoCount, pBindInfos );
+ }
+
+ VkResult vkBindImageMemory2KHR( VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkBindImageMemory2KHR( device, bindInfoCount, pBindInfos );
+ }
+
+ VkResult vkCompileDeferredNV( VkDevice device, VkPipeline pipeline, uint32_t shader ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCompileDeferredNV( device, pipeline, shader );
+ }
+
+ VkResult vkCreateAccelerationStructureNV( VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateAccelerationStructureNV( device, pCreateInfo, pAllocator, pAccelerationStructure );
+ }
+
+ VkResult vkCreateBuffer( VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateBuffer( device, pCreateInfo, pAllocator, pBuffer );
+ }
+
+ VkResult vkCreateBufferView( VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateBufferView( device, pCreateInfo, pAllocator, pView );
+ }
+
+ VkResult vkCreateCommandPool( VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateCommandPool( device, pCreateInfo, pAllocator, pCommandPool );
+ }
+
+ VkResult vkCreateComputePipelines( VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateComputePipelines( device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines );
+ }
+
+ VkResult vkCreateDescriptorPool( VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateDescriptorPool( device, pCreateInfo, pAllocator, pDescriptorPool );
+ }
+
+ VkResult vkCreateDescriptorSetLayout( VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateDescriptorSetLayout( device, pCreateInfo, pAllocator, pSetLayout );
+ }
+
+ VkResult vkCreateDescriptorUpdateTemplate( VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateDescriptorUpdateTemplate( device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate );
+ }
+
+ VkResult vkCreateDescriptorUpdateTemplateKHR( VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateDescriptorUpdateTemplateKHR( device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate );
+ }
+
+ VkResult vkCreateEvent( VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateEvent( device, pCreateInfo, pAllocator, pEvent );
+ }
+
+ VkResult vkCreateFence( VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateFence( device, pCreateInfo, pAllocator, pFence );
+ }
+
+ VkResult vkCreateFramebuffer( VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateFramebuffer( device, pCreateInfo, pAllocator, pFramebuffer );
+ }
+
+ VkResult vkCreateGraphicsPipelines( VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateGraphicsPipelines( device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines );
+ }
+
+ VkResult vkCreateImage( VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateImage( device, pCreateInfo, pAllocator, pImage );
+ }
+
+ VkResult vkCreateImageView( VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateImageView( device, pCreateInfo, pAllocator, pView );
+ }
+
+ VkResult vkCreateIndirectCommandsLayoutNVX( VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateIndirectCommandsLayoutNVX( device, pCreateInfo, pAllocator, pIndirectCommandsLayout );
+ }
+
+ VkResult vkCreateObjectTableNVX( VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateObjectTableNVX( device, pCreateInfo, pAllocator, pObjectTable );
+ }
+
+ VkResult vkCreatePipelineCache( VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreatePipelineCache( device, pCreateInfo, pAllocator, pPipelineCache );
+ }
+
+ VkResult vkCreatePipelineLayout( VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreatePipelineLayout( device, pCreateInfo, pAllocator, pPipelineLayout );
+ }
+
+ VkResult vkCreateQueryPool( VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateQueryPool( device, pCreateInfo, pAllocator, pQueryPool );
+ }
+
+ VkResult vkCreateRayTracingPipelinesNV( VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateRayTracingPipelinesNV( device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines );
+ }
+
+ VkResult vkCreateRenderPass( VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateRenderPass( device, pCreateInfo, pAllocator, pRenderPass );
+ }
+
+ VkResult vkCreateRenderPass2( VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateRenderPass2( device, pCreateInfo, pAllocator, pRenderPass );
+ }
+
+ VkResult vkCreateRenderPass2KHR( VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateRenderPass2KHR( device, pCreateInfo, pAllocator, pRenderPass );
+ }
+
+ VkResult vkCreateSampler( VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateSampler( device, pCreateInfo, pAllocator, pSampler );
+ }
+
+ VkResult vkCreateSamplerYcbcrConversion( VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateSamplerYcbcrConversion( device, pCreateInfo, pAllocator, pYcbcrConversion );
+ }
+
+ VkResult vkCreateSamplerYcbcrConversionKHR( VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateSamplerYcbcrConversionKHR( device, pCreateInfo, pAllocator, pYcbcrConversion );
+ }
+
+ VkResult vkCreateSemaphore( VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateSemaphore( device, pCreateInfo, pAllocator, pSemaphore );
+ }
+
+ VkResult vkCreateShaderModule( VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateShaderModule( device, pCreateInfo, pAllocator, pShaderModule );
+ }
+
+ VkResult vkCreateSharedSwapchainsKHR( VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateSharedSwapchainsKHR( device, swapchainCount, pCreateInfos, pAllocator, pSwapchains );
+ }
+
+ VkResult vkCreateSwapchainKHR( VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateSwapchainKHR( device, pCreateInfo, pAllocator, pSwapchain );
+ }
+
+ VkResult vkCreateValidationCacheEXT( VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateValidationCacheEXT( device, pCreateInfo, pAllocator, pValidationCache );
+ }
+
+ VkResult vkDebugMarkerSetObjectNameEXT( VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDebugMarkerSetObjectNameEXT( device, pNameInfo );
+ }
+
+ VkResult vkDebugMarkerSetObjectTagEXT( VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDebugMarkerSetObjectTagEXT( device, pTagInfo );
+ }
+
+ void vkDestroyAccelerationStructureNV( VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyAccelerationStructureNV( device, accelerationStructure, pAllocator );
+ }
+
+ void vkDestroyBuffer( VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyBuffer( device, buffer, pAllocator );
+ }
+
+ void vkDestroyBufferView( VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyBufferView( device, bufferView, pAllocator );
+ }
+
+ void vkDestroyCommandPool( VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyCommandPool( device, commandPool, pAllocator );
+ }
+
+ void vkDestroyDescriptorPool( VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyDescriptorPool( device, descriptorPool, pAllocator );
+ }
+
+ void vkDestroyDescriptorSetLayout( VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyDescriptorSetLayout( device, descriptorSetLayout, pAllocator );
+ }
+
+ void vkDestroyDescriptorUpdateTemplate( VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyDescriptorUpdateTemplate( device, descriptorUpdateTemplate, pAllocator );
+ }
+
+ void vkDestroyDescriptorUpdateTemplateKHR( VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyDescriptorUpdateTemplateKHR( device, descriptorUpdateTemplate, pAllocator );
+ }
+
+ void vkDestroyDevice( VkDevice device, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyDevice( device, pAllocator );
+ }
+
+ void vkDestroyEvent( VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyEvent( device, event, pAllocator );
+ }
+
+ void vkDestroyFence( VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyFence( device, fence, pAllocator );
+ }
+
+ void vkDestroyFramebuffer( VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyFramebuffer( device, framebuffer, pAllocator );
+ }
+
+ void vkDestroyImage( VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyImage( device, image, pAllocator );
+ }
+
+ void vkDestroyImageView( VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyImageView( device, imageView, pAllocator );
+ }
+
+ void vkDestroyIndirectCommandsLayoutNVX( VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyIndirectCommandsLayoutNVX( device, indirectCommandsLayout, pAllocator );
+ }
+
+ void vkDestroyObjectTableNVX( VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyObjectTableNVX( device, objectTable, pAllocator );
+ }
+
+ void vkDestroyPipeline( VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyPipeline( device, pipeline, pAllocator );
+ }
+
+ void vkDestroyPipelineCache( VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyPipelineCache( device, pipelineCache, pAllocator );
+ }
+
+ void vkDestroyPipelineLayout( VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyPipelineLayout( device, pipelineLayout, pAllocator );
+ }
+
+ void vkDestroyQueryPool( VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyQueryPool( device, queryPool, pAllocator );
+ }
+
+ void vkDestroyRenderPass( VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyRenderPass( device, renderPass, pAllocator );
+ }
+
+ void vkDestroySampler( VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroySampler( device, sampler, pAllocator );
+ }
+
+ void vkDestroySamplerYcbcrConversion( VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroySamplerYcbcrConversion( device, ycbcrConversion, pAllocator );
+ }
+
+ void vkDestroySamplerYcbcrConversionKHR( VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroySamplerYcbcrConversionKHR( device, ycbcrConversion, pAllocator );
+ }
+
+ void vkDestroySemaphore( VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroySemaphore( device, semaphore, pAllocator );
+ }
+
+ void vkDestroyShaderModule( VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyShaderModule( device, shaderModule, pAllocator );
+ }
+
+ void vkDestroySwapchainKHR( VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroySwapchainKHR( device, swapchain, pAllocator );
+ }
+
+ void vkDestroyValidationCacheEXT( VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyValidationCacheEXT( device, validationCache, pAllocator );
+ }
+
+ VkResult vkDeviceWaitIdle( VkDevice device ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDeviceWaitIdle( device );
+ }
+
+ VkResult vkDisplayPowerControlEXT( VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDisplayPowerControlEXT( device, display, pDisplayPowerInfo );
+ }
+
+ VkResult vkFlushMappedMemoryRanges( VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkFlushMappedMemoryRanges( device, memoryRangeCount, pMemoryRanges );
+ }
+
+ void vkFreeCommandBuffers( VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkFreeCommandBuffers( device, commandPool, commandBufferCount, pCommandBuffers );
+ }
+
+ VkResult vkFreeDescriptorSets( VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkFreeDescriptorSets( device, descriptorPool, descriptorSetCount, pDescriptorSets );
+ }
+
+ void vkFreeMemory( VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkFreeMemory( device, memory, pAllocator );
+ }
+
+ VkResult vkGetAccelerationStructureHandleNV( VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetAccelerationStructureHandleNV( device, accelerationStructure, dataSize, pData );
+ }
+
+ void vkGetAccelerationStructureMemoryRequirementsNV( VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetAccelerationStructureMemoryRequirementsNV( device, pInfo, pMemoryRequirements );
+ }
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ VkResult vkGetAndroidHardwareBufferPropertiesANDROID( VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetAndroidHardwareBufferPropertiesANDROID( device, buffer, pProperties );
+ }
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ VkDeviceAddress vkGetBufferDeviceAddress( VkDevice device, const VkBufferDeviceAddressInfo* pInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetBufferDeviceAddress( device, pInfo );
+ }
+
+ VkDeviceAddress vkGetBufferDeviceAddressEXT( VkDevice device, const VkBufferDeviceAddressInfo* pInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetBufferDeviceAddressEXT( device, pInfo );
+ }
+
+ VkDeviceAddress vkGetBufferDeviceAddressKHR( VkDevice device, const VkBufferDeviceAddressInfo* pInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetBufferDeviceAddressKHR( device, pInfo );
+ }
+
+ void vkGetBufferMemoryRequirements( VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetBufferMemoryRequirements( device, buffer, pMemoryRequirements );
+ }
+
+ void vkGetBufferMemoryRequirements2( VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetBufferMemoryRequirements2( device, pInfo, pMemoryRequirements );
+ }
+
+ void vkGetBufferMemoryRequirements2KHR( VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetBufferMemoryRequirements2KHR( device, pInfo, pMemoryRequirements );
+ }
+
+ uint64_t vkGetBufferOpaqueCaptureAddress( VkDevice device, const VkBufferDeviceAddressInfo* pInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetBufferOpaqueCaptureAddress( device, pInfo );
+ }
+
+ uint64_t vkGetBufferOpaqueCaptureAddressKHR( VkDevice device, const VkBufferDeviceAddressInfo* pInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetBufferOpaqueCaptureAddressKHR( device, pInfo );
+ }
+
+ VkResult vkGetCalibratedTimestampsEXT( VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoEXT* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetCalibratedTimestampsEXT( device, timestampCount, pTimestampInfos, pTimestamps, pMaxDeviation );
+ }
+
+ void vkGetDescriptorSetLayoutSupport( VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDescriptorSetLayoutSupport( device, pCreateInfo, pSupport );
+ }
+
+ void vkGetDescriptorSetLayoutSupportKHR( VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDescriptorSetLayoutSupportKHR( device, pCreateInfo, pSupport );
+ }
+
+ void vkGetDeviceGroupPeerMemoryFeatures( VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceGroupPeerMemoryFeatures( device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures );
+ }
+
+ void vkGetDeviceGroupPeerMemoryFeaturesKHR( VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceGroupPeerMemoryFeaturesKHR( device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures );
+ }
+
+ VkResult vkGetDeviceGroupPresentCapabilitiesKHR( VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceGroupPresentCapabilitiesKHR( device, pDeviceGroupPresentCapabilities );
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkGetDeviceGroupSurfacePresentModes2EXT( VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceGroupSurfacePresentModes2EXT( device, pSurfaceInfo, pModes );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ VkResult vkGetDeviceGroupSurfacePresentModesKHR( VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceGroupSurfacePresentModesKHR( device, surface, pModes );
+ }
+
+ void vkGetDeviceMemoryCommitment( VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceMemoryCommitment( device, memory, pCommittedMemoryInBytes );
+ }
+
+ uint64_t vkGetDeviceMemoryOpaqueCaptureAddress( VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceMemoryOpaqueCaptureAddress( device, pInfo );
+ }
+
+ uint64_t vkGetDeviceMemoryOpaqueCaptureAddressKHR( VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceMemoryOpaqueCaptureAddressKHR( device, pInfo );
+ }
+
+ PFN_vkVoidFunction vkGetDeviceProcAddr( VkDevice device, const char* pName ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceProcAddr( device, pName );
+ }
+
+ void vkGetDeviceQueue( VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceQueue( device, queueFamilyIndex, queueIndex, pQueue );
+ }
+
+ void vkGetDeviceQueue2( VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDeviceQueue2( device, pQueueInfo, pQueue );
+ }
+
+ VkResult vkGetEventStatus( VkDevice device, VkEvent event ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetEventStatus( device, event );
+ }
+
+ VkResult vkGetFenceFdKHR( VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetFenceFdKHR( device, pGetFdInfo, pFd );
+ }
+
+ VkResult vkGetFenceStatus( VkDevice device, VkFence fence ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetFenceStatus( device, fence );
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkGetFenceWin32HandleKHR( VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetFenceWin32HandleKHR( device, pGetWin32HandleInfo, pHandle );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ VkResult vkGetImageDrmFormatModifierPropertiesEXT( VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetImageDrmFormatModifierPropertiesEXT( device, image, pProperties );
+ }
+
+ void vkGetImageMemoryRequirements( VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetImageMemoryRequirements( device, image, pMemoryRequirements );
+ }
+
+ void vkGetImageMemoryRequirements2( VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetImageMemoryRequirements2( device, pInfo, pMemoryRequirements );
+ }
+
+ void vkGetImageMemoryRequirements2KHR( VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetImageMemoryRequirements2KHR( device, pInfo, pMemoryRequirements );
+ }
+
+ void vkGetImageSparseMemoryRequirements( VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetImageSparseMemoryRequirements( device, image, pSparseMemoryRequirementCount, pSparseMemoryRequirements );
+ }
+
+ void vkGetImageSparseMemoryRequirements2( VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetImageSparseMemoryRequirements2( device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements );
+ }
+
+ void vkGetImageSparseMemoryRequirements2KHR( VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetImageSparseMemoryRequirements2KHR( device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements );
+ }
+
+ void vkGetImageSubresourceLayout( VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetImageSubresourceLayout( device, image, pSubresource, pLayout );
+ }
+
+ uint32_t vkGetImageViewHandleNVX( VkDevice device, const VkImageViewHandleInfoNVX* pInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetImageViewHandleNVX( device, pInfo );
+ }
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ VkResult vkGetMemoryAndroidHardwareBufferANDROID( VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetMemoryAndroidHardwareBufferANDROID( device, pInfo, pBuffer );
+ }
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ VkResult vkGetMemoryFdKHR( VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetMemoryFdKHR( device, pGetFdInfo, pFd );
+ }
+
+ VkResult vkGetMemoryFdPropertiesKHR( VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetMemoryFdPropertiesKHR( device, handleType, fd, pMemoryFdProperties );
+ }
+
+ VkResult vkGetMemoryHostPointerPropertiesEXT( VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetMemoryHostPointerPropertiesEXT( device, handleType, pHostPointer, pMemoryHostPointerProperties );
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkGetMemoryWin32HandleKHR( VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetMemoryWin32HandleKHR( device, pGetWin32HandleInfo, pHandle );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkGetMemoryWin32HandleNV( VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetMemoryWin32HandleNV( device, memory, handleType, pHandle );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkGetMemoryWin32HandlePropertiesKHR( VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetMemoryWin32HandlePropertiesKHR( device, handleType, handle, pMemoryWin32HandleProperties );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ VkResult vkGetPastPresentationTimingGOOGLE( VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPastPresentationTimingGOOGLE( device, swapchain, pPresentationTimingCount, pPresentationTimings );
+ }
+
+ VkResult vkGetPerformanceParameterINTEL( VkDevice device, VkPerformanceParameterTypeINTEL parameter, VkPerformanceValueINTEL* pValue ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPerformanceParameterINTEL( device, parameter, pValue );
+ }
+
+ VkResult vkGetPipelineCacheData( VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPipelineCacheData( device, pipelineCache, pDataSize, pData );
+ }
+
+ VkResult vkGetPipelineExecutableInternalRepresentationsKHR( VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPipelineExecutableInternalRepresentationsKHR( device, pExecutableInfo, pInternalRepresentationCount, pInternalRepresentations );
+ }
+
+ VkResult vkGetPipelineExecutablePropertiesKHR( VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VkPipelineExecutablePropertiesKHR* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPipelineExecutablePropertiesKHR( device, pPipelineInfo, pExecutableCount, pProperties );
+ }
+
+ VkResult vkGetPipelineExecutableStatisticsKHR( VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VkPipelineExecutableStatisticKHR* pStatistics ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPipelineExecutableStatisticsKHR( device, pExecutableInfo, pStatisticCount, pStatistics );
+ }
+
+ VkResult vkGetQueryPoolResults( VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetQueryPoolResults( device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags );
+ }
+
+ VkResult vkGetRayTracingShaderGroupHandlesNV( VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetRayTracingShaderGroupHandlesNV( device, pipeline, firstGroup, groupCount, dataSize, pData );
+ }
+
+ VkResult vkGetRefreshCycleDurationGOOGLE( VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetRefreshCycleDurationGOOGLE( device, swapchain, pDisplayTimingProperties );
+ }
+
+ void vkGetRenderAreaGranularity( VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetRenderAreaGranularity( device, renderPass, pGranularity );
+ }
+
+ VkResult vkGetSemaphoreCounterValue( VkDevice device, VkSemaphore semaphore, uint64_t* pValue ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetSemaphoreCounterValue( device, semaphore, pValue );
+ }
+
+ VkResult vkGetSemaphoreCounterValueKHR( VkDevice device, VkSemaphore semaphore, uint64_t* pValue ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetSemaphoreCounterValueKHR( device, semaphore, pValue );
+ }
+
+ VkResult vkGetSemaphoreFdKHR( VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetSemaphoreFdKHR( device, pGetFdInfo, pFd );
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkGetSemaphoreWin32HandleKHR( VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetSemaphoreWin32HandleKHR( device, pGetWin32HandleInfo, pHandle );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ VkResult vkGetShaderInfoAMD( VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetShaderInfoAMD( device, pipeline, shaderStage, infoType, pInfoSize, pInfo );
+ }
+
+ VkResult vkGetSwapchainCounterEXT( VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetSwapchainCounterEXT( device, swapchain, counter, pCounterValue );
+ }
+
+ VkResult vkGetSwapchainImagesKHR( VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetSwapchainImagesKHR( device, swapchain, pSwapchainImageCount, pSwapchainImages );
+ }
+
+ VkResult vkGetSwapchainStatusKHR( VkDevice device, VkSwapchainKHR swapchain ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetSwapchainStatusKHR( device, swapchain );
+ }
+
+ VkResult vkGetValidationCacheDataEXT( VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetValidationCacheDataEXT( device, validationCache, pDataSize, pData );
+ }
+
+ VkResult vkImportFenceFdKHR( VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkImportFenceFdKHR( device, pImportFenceFdInfo );
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkImportFenceWin32HandleKHR( VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkImportFenceWin32HandleKHR( device, pImportFenceWin32HandleInfo );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ VkResult vkImportSemaphoreFdKHR( VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkImportSemaphoreFdKHR( device, pImportSemaphoreFdInfo );
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkImportSemaphoreWin32HandleKHR( VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkImportSemaphoreWin32HandleKHR( device, pImportSemaphoreWin32HandleInfo );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ VkResult vkInitializePerformanceApiINTEL( VkDevice device, const VkInitializePerformanceApiInfoINTEL* pInitializeInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkInitializePerformanceApiINTEL( device, pInitializeInfo );
+ }
+
+ VkResult vkInvalidateMappedMemoryRanges( VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkInvalidateMappedMemoryRanges( device, memoryRangeCount, pMemoryRanges );
+ }
+
+ VkResult vkMapMemory( VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkMapMemory( device, memory, offset, size, flags, ppData );
+ }
+
+ VkResult vkMergePipelineCaches( VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkMergePipelineCaches( device, dstCache, srcCacheCount, pSrcCaches );
+ }
+
+ VkResult vkMergeValidationCachesEXT( VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkMergeValidationCachesEXT( device, dstCache, srcCacheCount, pSrcCaches );
+ }
+
+ VkResult vkRegisterDeviceEventEXT( VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkRegisterDeviceEventEXT( device, pDeviceEventInfo, pAllocator, pFence );
+ }
+
+ VkResult vkRegisterDisplayEventEXT( VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkRegisterDisplayEventEXT( device, display, pDisplayEventInfo, pAllocator, pFence );
+ }
+
+ VkResult vkRegisterObjectsNVX( VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkRegisterObjectsNVX( device, objectTable, objectCount, ppObjectTableEntries, pObjectIndices );
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkReleaseFullScreenExclusiveModeEXT( VkDevice device, VkSwapchainKHR swapchain ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkReleaseFullScreenExclusiveModeEXT( device, swapchain );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ VkResult vkReleasePerformanceConfigurationINTEL( VkDevice device, VkPerformanceConfigurationINTEL configuration ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkReleasePerformanceConfigurationINTEL( device, configuration );
+ }
+
+ void vkReleaseProfilingLockKHR( VkDevice device ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkReleaseProfilingLockKHR( device );
+ }
+
+ VkResult vkResetCommandPool( VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkResetCommandPool( device, commandPool, flags );
+ }
+
+ VkResult vkResetDescriptorPool( VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkResetDescriptorPool( device, descriptorPool, flags );
+ }
+
+ VkResult vkResetEvent( VkDevice device, VkEvent event ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkResetEvent( device, event );
+ }
+
+ VkResult vkResetFences( VkDevice device, uint32_t fenceCount, const VkFence* pFences ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkResetFences( device, fenceCount, pFences );
+ }
+
+ void vkResetQueryPool( VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkResetQueryPool( device, queryPool, firstQuery, queryCount );
+ }
+
+ void vkResetQueryPoolEXT( VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkResetQueryPoolEXT( device, queryPool, firstQuery, queryCount );
+ }
+
+ VkResult vkSetDebugUtilsObjectNameEXT( VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkSetDebugUtilsObjectNameEXT( device, pNameInfo );
+ }
+
+ VkResult vkSetDebugUtilsObjectTagEXT( VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkSetDebugUtilsObjectTagEXT( device, pTagInfo );
+ }
+
+ VkResult vkSetEvent( VkDevice device, VkEvent event ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkSetEvent( device, event );
+ }
+
+ void vkSetHdrMetadataEXT( VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkSetHdrMetadataEXT( device, swapchainCount, pSwapchains, pMetadata );
+ }
+
+ void vkSetLocalDimmingAMD( VkDevice device, VkSwapchainKHR swapChain, VkBool32 localDimmingEnable ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkSetLocalDimmingAMD( device, swapChain, localDimmingEnable );
+ }
+
+ VkResult vkSignalSemaphore( VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkSignalSemaphore( device, pSignalInfo );
+ }
+
+ VkResult vkSignalSemaphoreKHR( VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkSignalSemaphoreKHR( device, pSignalInfo );
+ }
+
+ void vkTrimCommandPool( VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkTrimCommandPool( device, commandPool, flags );
+ }
+
+ void vkTrimCommandPoolKHR( VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkTrimCommandPoolKHR( device, commandPool, flags );
+ }
+
+ void vkUninitializePerformanceApiINTEL( VkDevice device ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkUninitializePerformanceApiINTEL( device );
+ }
+
+ void vkUnmapMemory( VkDevice device, VkDeviceMemory memory ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkUnmapMemory( device, memory );
+ }
+
+ VkResult vkUnregisterObjectsNVX( VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkUnregisterObjectsNVX( device, objectTable, objectCount, pObjectEntryTypes, pObjectIndices );
+ }
+
+ void vkUpdateDescriptorSetWithTemplate( VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkUpdateDescriptorSetWithTemplate( device, descriptorSet, descriptorUpdateTemplate, pData );
+ }
+
+ void vkUpdateDescriptorSetWithTemplateKHR( VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkUpdateDescriptorSetWithTemplateKHR( device, descriptorSet, descriptorUpdateTemplate, pData );
+ }
+
+ void vkUpdateDescriptorSets( VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkUpdateDescriptorSets( device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies );
+ }
+
+ VkResult vkWaitForFences( VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkWaitForFences( device, fenceCount, pFences, waitAll, timeout );
+ }
+
+ VkResult vkWaitSemaphores( VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkWaitSemaphores( device, pWaitInfo, timeout );
+ }
+
+ VkResult vkWaitSemaphoresKHR( VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkWaitSemaphoresKHR( device, pWaitInfo, timeout );
+ }
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ VkResult vkCreateAndroidSurfaceKHR( VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateAndroidSurfaceKHR( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ VkResult vkCreateDebugReportCallbackEXT( VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateDebugReportCallbackEXT( instance, pCreateInfo, pAllocator, pCallback );
+ }
+
+ VkResult vkCreateDebugUtilsMessengerEXT( VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateDebugUtilsMessengerEXT( instance, pCreateInfo, pAllocator, pMessenger );
+ }
+
+ VkResult vkCreateDisplayPlaneSurfaceKHR( VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateDisplayPlaneSurfaceKHR( instance, pCreateInfo, pAllocator, pSurface );
+ }
+
+ VkResult vkCreateHeadlessSurfaceEXT( VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateHeadlessSurfaceEXT( instance, pCreateInfo, pAllocator, pSurface );
+ }
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ VkResult vkCreateIOSSurfaceMVK( VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateIOSSurfaceMVK( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_IOS_MVK*/
+
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ VkResult vkCreateImagePipeSurfaceFUCHSIA( VkInstance instance, const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateImagePipeSurfaceFUCHSIA( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_FUCHSIA*/
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ VkResult vkCreateMacOSSurfaceMVK( VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateMacOSSurfaceMVK( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_MACOS_MVK*/
+
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ VkResult vkCreateMetalSurfaceEXT( VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateMetalSurfaceEXT( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_METAL_EXT*/
+
+#ifdef VK_USE_PLATFORM_GGP
+ VkResult vkCreateStreamDescriptorSurfaceGGP( VkInstance instance, const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateStreamDescriptorSurfaceGGP( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_GGP*/
+
+#ifdef VK_USE_PLATFORM_VI_NN
+ VkResult vkCreateViSurfaceNN( VkInstance instance, const VkViSurfaceCreateInfoNN* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateViSurfaceNN( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_VI_NN*/
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ VkResult vkCreateWaylandSurfaceKHR( VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateWaylandSurfaceKHR( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkCreateWin32SurfaceKHR( VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateWin32SurfaceKHR( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ VkResult vkCreateXcbSurfaceKHR( VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateXcbSurfaceKHR( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ VkResult vkCreateXlibSurfaceKHR( VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateXlibSurfaceKHR( instance, pCreateInfo, pAllocator, pSurface );
+ }
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+
+ void vkDebugReportMessageEXT( VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDebugReportMessageEXT( instance, flags, objectType, object, location, messageCode, pLayerPrefix, pMessage );
+ }
+
+ void vkDestroyDebugReportCallbackEXT( VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyDebugReportCallbackEXT( instance, callback, pAllocator );
+ }
+
+ void vkDestroyDebugUtilsMessengerEXT( VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyDebugUtilsMessengerEXT( instance, messenger, pAllocator );
+ }
+
+ void vkDestroyInstance( VkInstance instance, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroyInstance( instance, pAllocator );
+ }
+
+ void vkDestroySurfaceKHR( VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkDestroySurfaceKHR( instance, surface, pAllocator );
+ }
+
+ VkResult vkEnumeratePhysicalDeviceGroups( VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkEnumeratePhysicalDeviceGroups( instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties );
+ }
+
+ VkResult vkEnumeratePhysicalDeviceGroupsKHR( VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkEnumeratePhysicalDeviceGroupsKHR( instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties );
+ }
+
+ VkResult vkEnumeratePhysicalDevices( VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkEnumeratePhysicalDevices( instance, pPhysicalDeviceCount, pPhysicalDevices );
+ }
+
+ PFN_vkVoidFunction vkGetInstanceProcAddr( VkInstance instance, const char* pName ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetInstanceProcAddr( instance, pName );
+ }
+
+ void vkSubmitDebugUtilsMessageEXT( VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkSubmitDebugUtilsMessageEXT( instance, messageSeverity, messageTypes, pCallbackData );
+ }
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ VkResult vkAcquireXlibDisplayEXT( VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkAcquireXlibDisplayEXT( physicalDevice, dpy, display );
+ }
+#endif /*VK_USE_PLATFORM_XLIB_XRANDR_EXT*/
+
+ VkResult vkCreateDevice( VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateDevice( physicalDevice, pCreateInfo, pAllocator, pDevice );
+ }
+
+ VkResult vkCreateDisplayModeKHR( VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkCreateDisplayModeKHR( physicalDevice, display, pCreateInfo, pAllocator, pMode );
+ }
+
+ VkResult vkEnumerateDeviceExtensionProperties( VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkEnumerateDeviceExtensionProperties( physicalDevice, pLayerName, pPropertyCount, pProperties );
+ }
+
+ VkResult vkEnumerateDeviceLayerProperties( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkEnumerateDeviceLayerProperties( physicalDevice, pPropertyCount, pProperties );
+ }
+
+ VkResult vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterKHR* pCounters, VkPerformanceCounterDescriptionKHR* pCounterDescriptions ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( physicalDevice, queueFamilyIndex, pCounterCount, pCounters, pCounterDescriptions );
+ }
+
+ VkResult vkGetDisplayModeProperties2KHR( VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModeProperties2KHR* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDisplayModeProperties2KHR( physicalDevice, display, pPropertyCount, pProperties );
+ }
+
+ VkResult vkGetDisplayModePropertiesKHR( VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDisplayModePropertiesKHR( physicalDevice, display, pPropertyCount, pProperties );
+ }
+
+ VkResult vkGetDisplayPlaneCapabilities2KHR( VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDisplayPlaneCapabilities2KHR( physicalDevice, pDisplayPlaneInfo, pCapabilities );
+ }
+
+ VkResult vkGetDisplayPlaneCapabilitiesKHR( VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDisplayPlaneCapabilitiesKHR( physicalDevice, mode, planeIndex, pCapabilities );
+ }
+
+ VkResult vkGetDisplayPlaneSupportedDisplaysKHR( VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetDisplayPlaneSupportedDisplaysKHR( physicalDevice, planeIndex, pDisplayCount, pDisplays );
+ }
+
+ VkResult vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainEXT* pTimeDomains ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( physicalDevice, pTimeDomainCount, pTimeDomains );
+ }
+
+ VkResult vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesNV* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( physicalDevice, pPropertyCount, pProperties );
+ }
+
+ VkResult vkGetPhysicalDeviceDisplayPlaneProperties2KHR( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlaneProperties2KHR* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceDisplayPlaneProperties2KHR( physicalDevice, pPropertyCount, pProperties );
+ }
+
+ VkResult vkGetPhysicalDeviceDisplayPlanePropertiesKHR( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceDisplayPlanePropertiesKHR( physicalDevice, pPropertyCount, pProperties );
+ }
+
+ VkResult vkGetPhysicalDeviceDisplayProperties2KHR( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayProperties2KHR* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceDisplayProperties2KHR( physicalDevice, pPropertyCount, pProperties );
+ }
+
+ VkResult vkGetPhysicalDeviceDisplayPropertiesKHR( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceDisplayPropertiesKHR( physicalDevice, pPropertyCount, pProperties );
+ }
+
+ void vkGetPhysicalDeviceExternalBufferProperties( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceExternalBufferProperties( physicalDevice, pExternalBufferInfo, pExternalBufferProperties );
+ }
+
+ void vkGetPhysicalDeviceExternalBufferPropertiesKHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceExternalBufferPropertiesKHR( physicalDevice, pExternalBufferInfo, pExternalBufferProperties );
+ }
+
+ void vkGetPhysicalDeviceExternalFenceProperties( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceExternalFenceProperties( physicalDevice, pExternalFenceInfo, pExternalFenceProperties );
+ }
+
+ void vkGetPhysicalDeviceExternalFencePropertiesKHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceExternalFencePropertiesKHR( physicalDevice, pExternalFenceInfo, pExternalFenceProperties );
+ }
+
+ VkResult vkGetPhysicalDeviceExternalImageFormatPropertiesNV( VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceExternalImageFormatPropertiesNV( physicalDevice, format, type, tiling, usage, flags, externalHandleType, pExternalImageFormatProperties );
+ }
+
+ void vkGetPhysicalDeviceExternalSemaphoreProperties( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceExternalSemaphoreProperties( physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties );
+ }
+
+ void vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties );
+ }
+
+ void vkGetPhysicalDeviceFeatures( VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceFeatures( physicalDevice, pFeatures );
+ }
+
+ void vkGetPhysicalDeviceFeatures2( VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceFeatures2( physicalDevice, pFeatures );
+ }
+
+ void vkGetPhysicalDeviceFeatures2KHR( VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceFeatures2KHR( physicalDevice, pFeatures );
+ }
+
+ void vkGetPhysicalDeviceFormatProperties( VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceFormatProperties( physicalDevice, format, pFormatProperties );
+ }
+
+ void vkGetPhysicalDeviceFormatProperties2( VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceFormatProperties2( physicalDevice, format, pFormatProperties );
+ }
+
+ void vkGetPhysicalDeviceFormatProperties2KHR( VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceFormatProperties2KHR( physicalDevice, format, pFormatProperties );
+ }
+
+ void vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( physicalDevice, pFeatures, pLimits );
+ }
+
+ VkResult vkGetPhysicalDeviceImageFormatProperties( VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceImageFormatProperties( physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties );
+ }
+
+ VkResult vkGetPhysicalDeviceImageFormatProperties2( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceImageFormatProperties2( physicalDevice, pImageFormatInfo, pImageFormatProperties );
+ }
+
+ VkResult vkGetPhysicalDeviceImageFormatProperties2KHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceImageFormatProperties2KHR( physicalDevice, pImageFormatInfo, pImageFormatProperties );
+ }
+
+ void vkGetPhysicalDeviceMemoryProperties( VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceMemoryProperties( physicalDevice, pMemoryProperties );
+ }
+
+ void vkGetPhysicalDeviceMemoryProperties2( VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceMemoryProperties2( physicalDevice, pMemoryProperties );
+ }
+
+ void vkGetPhysicalDeviceMemoryProperties2KHR( VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceMemoryProperties2KHR( physicalDevice, pMemoryProperties );
+ }
+
+ void vkGetPhysicalDeviceMultisamplePropertiesEXT( VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceMultisamplePropertiesEXT( physicalDevice, samples, pMultisampleProperties );
+ }
+
+ VkResult vkGetPhysicalDevicePresentRectanglesKHR( VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDevicePresentRectanglesKHR( physicalDevice, surface, pRectCount, pRects );
+ }
+
+ void vkGetPhysicalDeviceProperties( VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceProperties( physicalDevice, pProperties );
+ }
+
+ void vkGetPhysicalDeviceProperties2( VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceProperties2( physicalDevice, pProperties );
+ }
+
+ void vkGetPhysicalDeviceProperties2KHR( VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceProperties2KHR( physicalDevice, pProperties );
+ }
+
+ void vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( VkPhysicalDevice physicalDevice, const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( physicalDevice, pPerformanceQueryCreateInfo, pNumPasses );
+ }
+
+ void vkGetPhysicalDeviceQueueFamilyProperties( VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceQueueFamilyProperties( physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties );
+ }
+
+ void vkGetPhysicalDeviceQueueFamilyProperties2( VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceQueueFamilyProperties2( physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties );
+ }
+
+ void vkGetPhysicalDeviceQueueFamilyProperties2KHR( VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceQueueFamilyProperties2KHR( physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties );
+ }
+
+ void vkGetPhysicalDeviceSparseImageFormatProperties( VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSparseImageFormatProperties( physicalDevice, format, type, samples, usage, tiling, pPropertyCount, pProperties );
+ }
+
+ void vkGetPhysicalDeviceSparseImageFormatProperties2( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSparseImageFormatProperties2( physicalDevice, pFormatInfo, pPropertyCount, pProperties );
+ }
+
+ void vkGetPhysicalDeviceSparseImageFormatProperties2KHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSparseImageFormatProperties2KHR( physicalDevice, pFormatInfo, pPropertyCount, pProperties );
+ }
+
+ VkResult vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( VkPhysicalDevice physicalDevice, uint32_t* pCombinationCount, VkFramebufferMixedSamplesCombinationNV* pCombinations ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( physicalDevice, pCombinationCount, pCombinations );
+ }
+
+ VkResult vkGetPhysicalDeviceSurfaceCapabilities2EXT( VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSurfaceCapabilities2EXT( physicalDevice, surface, pSurfaceCapabilities );
+ }
+
+ VkResult vkGetPhysicalDeviceSurfaceCapabilities2KHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSurfaceCapabilities2KHR( physicalDevice, pSurfaceInfo, pSurfaceCapabilities );
+ }
+
+ VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR( VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSurfaceCapabilitiesKHR( physicalDevice, surface, pSurfaceCapabilities );
+ }
+
+ VkResult vkGetPhysicalDeviceSurfaceFormats2KHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSurfaceFormats2KHR( physicalDevice, pSurfaceInfo, pSurfaceFormatCount, pSurfaceFormats );
+ }
+
+ VkResult vkGetPhysicalDeviceSurfaceFormatsKHR( VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSurfaceFormatsKHR( physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats );
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkResult vkGetPhysicalDeviceSurfacePresentModes2EXT( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSurfacePresentModes2EXT( physicalDevice, pSurfaceInfo, pPresentModeCount, pPresentModes );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ VkResult vkGetPhysicalDeviceSurfacePresentModesKHR( VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSurfacePresentModesKHR( physicalDevice, surface, pPresentModeCount, pPresentModes );
+ }
+
+ VkResult vkGetPhysicalDeviceSurfaceSupportKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceSurfaceSupportKHR( physicalDevice, queueFamilyIndex, surface, pSupported );
+ }
+
+ VkResult vkGetPhysicalDeviceToolPropertiesEXT( VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolPropertiesEXT* pToolProperties ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceToolPropertiesEXT( physicalDevice, pToolCount, pToolProperties );
+ }
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ VkBool32 vkGetPhysicalDeviceWaylandPresentationSupportKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceWaylandPresentationSupportKHR( physicalDevice, queueFamilyIndex, display );
+ }
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkBool32 vkGetPhysicalDeviceWin32PresentationSupportKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceWin32PresentationSupportKHR( physicalDevice, queueFamilyIndex );
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ VkBool32 vkGetPhysicalDeviceXcbPresentationSupportKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceXcbPresentationSupportKHR( physicalDevice, queueFamilyIndex, connection, visual_id );
+ }
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ VkBool32 vkGetPhysicalDeviceXlibPresentationSupportKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetPhysicalDeviceXlibPresentationSupportKHR( physicalDevice, queueFamilyIndex, dpy, visualID );
+ }
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ VkResult vkGetRandROutputDisplayEXT( VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput, VkDisplayKHR* pDisplay ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetRandROutputDisplayEXT( physicalDevice, dpy, rrOutput, pDisplay );
+ }
+#endif /*VK_USE_PLATFORM_XLIB_XRANDR_EXT*/
+
+ VkResult vkReleaseDisplayEXT( VkPhysicalDevice physicalDevice, VkDisplayKHR display ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkReleaseDisplayEXT( physicalDevice, display );
+ }
+
+ void vkGetQueueCheckpointDataNV( VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkGetQueueCheckpointDataNV( queue, pCheckpointDataCount, pCheckpointData );
+ }
+
+ void vkQueueBeginDebugUtilsLabelEXT( VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkQueueBeginDebugUtilsLabelEXT( queue, pLabelInfo );
+ }
+
+ VkResult vkQueueBindSparse( VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkQueueBindSparse( queue, bindInfoCount, pBindInfo, fence );
+ }
+
+ void vkQueueEndDebugUtilsLabelEXT( VkQueue queue ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkQueueEndDebugUtilsLabelEXT( queue );
+ }
+
+ void vkQueueInsertDebugUtilsLabelEXT( VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkQueueInsertDebugUtilsLabelEXT( queue, pLabelInfo );
+ }
+
+ VkResult vkQueuePresentKHR( VkQueue queue, const VkPresentInfoKHR* pPresentInfo ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkQueuePresentKHR( queue, pPresentInfo );
+ }
+
+ VkResult vkQueueSetPerformanceConfigurationINTEL( VkQueue queue, VkPerformanceConfigurationINTEL configuration ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkQueueSetPerformanceConfigurationINTEL( queue, configuration );
+ }
+
+ VkResult vkQueueSubmit( VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkQueueSubmit( queue, submitCount, pSubmits, fence );
+ }
+
+ VkResult vkQueueWaitIdle( VkQueue queue ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ::vkQueueWaitIdle( queue );
+ }
+ };
+#endif
+
+ class DispatchLoaderDynamic;
+#if !defined(VULKAN_HPP_DISPATCH_LOADER_DYNAMIC)
+# if defined(VK_NO_PROTOTYPES)
+# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
+# else
+# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 0
+# endif
+#endif
+
+#if !defined(VULKAN_HPP_DEFAULT_DISPATCHER)
+# if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1
+# define VULKAN_HPP_DEFAULT_DISPATCHER ::VULKAN_HPP_NAMESPACE::defaultDispatchLoaderDynamic
+# define VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE namespace VULKAN_HPP_NAMESPACE { DispatchLoaderDynamic defaultDispatchLoaderDynamic; }
+ extern DispatchLoaderDynamic defaultDispatchLoaderDynamic;
+# else
+# define VULKAN_HPP_DEFAULT_DISPATCHER ::VULKAN_HPP_NAMESPACE::DispatchLoaderStatic()
+# define VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
+# endif
+#endif
+
+#if !defined(VULKAN_HPP_DEFAULT_DISPATCHER_TYPE)
+# if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1
+ #define VULKAN_HPP_DEFAULT_DISPATCHER_TYPE ::VULKAN_HPP_NAMESPACE::DispatchLoaderDynamic
+# else
+# define VULKAN_HPP_DEFAULT_DISPATCHER_TYPE ::VULKAN_HPP_NAMESPACE::DispatchLoaderStatic
+# endif
+#endif
+
+ struct AllocationCallbacks;
+
+ template <typename OwnerType, typename Dispatch>
+ class ObjectDestroy
+ {
+ public:
+ ObjectDestroy()
+ : m_owner()
+ , m_allocationCallbacks( nullptr )
+ , m_dispatch( nullptr )
+ {}
+
+ ObjectDestroy( OwnerType owner, Optional<const AllocationCallbacks> allocationCallbacks = nullptr, Dispatch const &dispatch = VULKAN_HPP_DEFAULT_DISPATCHER ) VULKAN_HPP_NOEXCEPT
+ : m_owner( owner )
+ , m_allocationCallbacks( allocationCallbacks )
+ , m_dispatch( &dispatch )
+ {}
+
+ OwnerType getOwner() const VULKAN_HPP_NOEXCEPT { return m_owner; }
+ Optional<const AllocationCallbacks> getAllocator() const VULKAN_HPP_NOEXCEPT { return m_allocationCallbacks; }
+
+ protected:
+ template <typename T>
+ void destroy(T t) VULKAN_HPP_NOEXCEPT
+ {
+ assert( m_owner && m_dispatch );
+ m_owner.destroy( t, m_allocationCallbacks, *m_dispatch );
+ }
+
+ private:
+ OwnerType m_owner;
+ Optional<const AllocationCallbacks> m_allocationCallbacks;
+ Dispatch const* m_dispatch;
+ };
+
+ class NoParent;
+
+ template <typename Dispatch>
+ class ObjectDestroy<NoParent,Dispatch>
+ {
+ public:
+ ObjectDestroy()
+ : m_allocationCallbacks( nullptr )
+ , m_dispatch( nullptr )
+ {}
+
+ ObjectDestroy( Optional<const AllocationCallbacks> allocationCallbacks, Dispatch const &dispatch = VULKAN_HPP_DEFAULT_DISPATCHER ) VULKAN_HPP_NOEXCEPT
+ : m_allocationCallbacks( allocationCallbacks )
+ , m_dispatch( &dispatch )
+ {}
+
+ Optional<const AllocationCallbacks> getAllocator() const VULKAN_HPP_NOEXCEPT { return m_allocationCallbacks; }
+
+ protected:
+ template <typename T>
+ void destroy(T t) VULKAN_HPP_NOEXCEPT
+ {
+ assert( m_dispatch );
+ t.destroy( m_allocationCallbacks, *m_dispatch );
+ }
+
+ private:
+ Optional<const AllocationCallbacks> m_allocationCallbacks;
+ Dispatch const* m_dispatch;
+ };
+
+ template <typename OwnerType, typename Dispatch>
+ class ObjectFree
+ {
+ public:
+ ObjectFree()
+ : m_owner()
+ , m_allocationCallbacks( nullptr )
+ , m_dispatch( nullptr )
+ {}
+
+ ObjectFree( OwnerType owner, Optional<const AllocationCallbacks> allocationCallbacks, Dispatch const &dispatch ) VULKAN_HPP_NOEXCEPT
+ : m_owner( owner )
+ , m_allocationCallbacks( allocationCallbacks )
+ , m_dispatch( &dispatch )
+ {}
+
+ OwnerType getOwner() const VULKAN_HPP_NOEXCEPT { return m_owner; }
+ Optional<const AllocationCallbacks> getAllocator() const VULKAN_HPP_NOEXCEPT { return m_allocationCallbacks; }
+
+ protected:
+ template <typename T>
+ void destroy(T t) VULKAN_HPP_NOEXCEPT
+ {
+ assert( m_owner && m_dispatch );
+ m_owner.free( t, m_allocationCallbacks, *m_dispatch );
+ }
+
+ private:
+ OwnerType m_owner;
+ Optional<const AllocationCallbacks> m_allocationCallbacks;
+ Dispatch const* m_dispatch;
+ };
+
+ template <typename OwnerType, typename PoolType, typename Dispatch>
+ class PoolFree
+ {
+ public:
+ PoolFree( OwnerType owner = OwnerType(), PoolType pool = PoolType(), Dispatch const &dispatch = VULKAN_HPP_DEFAULT_DISPATCHER ) VULKAN_HPP_NOEXCEPT
+ : m_owner( owner )
+ , m_pool( pool )
+ , m_dispatch( &dispatch )
+ {}
+
+ OwnerType getOwner() const VULKAN_HPP_NOEXCEPT { return m_owner; }
+ PoolType getPool() const VULKAN_HPP_NOEXCEPT { return m_pool; }
+
+ protected:
+ template <typename T>
+ void destroy(T t) VULKAN_HPP_NOEXCEPT
+ {
+ m_owner.free( m_pool, t, *m_dispatch );
+ }
+
+ private:
+ OwnerType m_owner;
+ PoolType m_pool;
+ Dispatch const* m_dispatch;
+ };
+
+ template <typename T, size_t N, size_t I>
+ class ConstExpression1DArrayCopy
+ {
+ public:
+ VULKAN_HPP_CONSTEXPR_14 static void copy(T dst[N], std::array<T,N> const& src) VULKAN_HPP_NOEXCEPT
+ {
+ dst[I-1] = src[I-1];
+ ConstExpression1DArrayCopy<T, N, I - 1>::copy(dst, src);
+ }
+ };
+
+ template <typename T, size_t N>
+ class ConstExpression1DArrayCopy<T, N, 0>
+ {
+ public:
+ VULKAN_HPP_CONSTEXPR_14 static void copy(T /*dst*/[N], std::array<T,N> const& /*src*/) VULKAN_HPP_NOEXCEPT {}
+ };
+
+ template <typename T, size_t N, size_t M, size_t I, size_t J>
+ class ConstExpression2DArrayCopy
+ {
+ public:
+ VULKAN_HPP_CONSTEXPR_14 static void copy(T dst[N][M], std::array<std::array<T,M>, N> const& src) VULKAN_HPP_NOEXCEPT
+ {
+ dst[I - 1][J - 1] = src[I - 1][J - 1];
+ ConstExpression2DArrayCopy<T, N, M, I, J - 1>::copy(dst, src);
+ }
+ };
+
+ template <typename T, size_t N, size_t M, size_t I>
+ class ConstExpression2DArrayCopy<T, N, M, I, 0>
+ {
+ public:
+ VULKAN_HPP_CONSTEXPR_14 static void copy(T dst[N][M], std::array<std::array<T, M>, N> const& src) VULKAN_HPP_NOEXCEPT
+ {
+ ConstExpression2DArrayCopy<T, N, M, I - 1, M>::copy(dst, src);
+ }
+ };
+
+ template <typename T, size_t N, size_t M>
+ class ConstExpression2DArrayCopy<T, N, M, 0, 0>
+ {
+ public:
+ VULKAN_HPP_CONSTEXPR_14 static void copy(T /*dst*/[N][M], std::array<std::array<T, M>, N> const& /*src*/) VULKAN_HPP_NOEXCEPT {}
+ };
+
+ using Bool32 = uint32_t;
+ using DeviceAddress = uint64_t;
+ using DeviceSize = uint64_t;
+ using SampleMask = uint32_t;
+
+ enum class AccelerationStructureMemoryRequirementsTypeNV
+ {
+ eObject = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV,
+ eBuildScratch = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV,
+ eUpdateScratch = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( AccelerationStructureMemoryRequirementsTypeNV value )
+ {
+ switch ( value )
+ {
+ case AccelerationStructureMemoryRequirementsTypeNV::eObject : return "Object";
+ case AccelerationStructureMemoryRequirementsTypeNV::eBuildScratch : return "BuildScratch";
+ case AccelerationStructureMemoryRequirementsTypeNV::eUpdateScratch : return "UpdateScratch";
+ default: return "invalid";
+ }
+ }
+
+ enum class AccelerationStructureTypeNV
+ {
+ eTopLevel = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV,
+ eBottomLevel = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( AccelerationStructureTypeNV value )
+ {
+ switch ( value )
+ {
+ case AccelerationStructureTypeNV::eTopLevel : return "TopLevel";
+ case AccelerationStructureTypeNV::eBottomLevel : return "BottomLevel";
+ default: return "invalid";
+ }
+ }
+
+ enum class AccessFlagBits
+ {
+ eIndirectCommandRead = VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
+ eIndexRead = VK_ACCESS_INDEX_READ_BIT,
+ eVertexAttributeRead = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
+ eUniformRead = VK_ACCESS_UNIFORM_READ_BIT,
+ eInputAttachmentRead = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
+ eShaderRead = VK_ACCESS_SHADER_READ_BIT,
+ eShaderWrite = VK_ACCESS_SHADER_WRITE_BIT,
+ eColorAttachmentRead = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
+ eColorAttachmentWrite = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+ eDepthStencilAttachmentRead = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
+ eDepthStencilAttachmentWrite = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ eTransferRead = VK_ACCESS_TRANSFER_READ_BIT,
+ eTransferWrite = VK_ACCESS_TRANSFER_WRITE_BIT,
+ eHostRead = VK_ACCESS_HOST_READ_BIT,
+ eHostWrite = VK_ACCESS_HOST_WRITE_BIT,
+ eMemoryRead = VK_ACCESS_MEMORY_READ_BIT,
+ eMemoryWrite = VK_ACCESS_MEMORY_WRITE_BIT,
+ eTransformFeedbackWriteEXT = VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT,
+ eTransformFeedbackCounterReadEXT = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
+ eTransformFeedbackCounterWriteEXT = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,
+ eConditionalRenderingReadEXT = VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT,
+ eCommandProcessReadNVX = VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX,
+ eCommandProcessWriteNVX = VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX,
+ eColorAttachmentReadNoncoherentEXT = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT,
+ eShadingRateImageReadNV = VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV,
+ eAccelerationStructureReadNV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV,
+ eAccelerationStructureWriteNV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV,
+ eFragmentDensityMapReadEXT = VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( AccessFlagBits value )
+ {
+ switch ( value )
+ {
+ case AccessFlagBits::eIndirectCommandRead : return "IndirectCommandRead";
+ case AccessFlagBits::eIndexRead : return "IndexRead";
+ case AccessFlagBits::eVertexAttributeRead : return "VertexAttributeRead";
+ case AccessFlagBits::eUniformRead : return "UniformRead";
+ case AccessFlagBits::eInputAttachmentRead : return "InputAttachmentRead";
+ case AccessFlagBits::eShaderRead : return "ShaderRead";
+ case AccessFlagBits::eShaderWrite : return "ShaderWrite";
+ case AccessFlagBits::eColorAttachmentRead : return "ColorAttachmentRead";
+ case AccessFlagBits::eColorAttachmentWrite : return "ColorAttachmentWrite";
+ case AccessFlagBits::eDepthStencilAttachmentRead : return "DepthStencilAttachmentRead";
+ case AccessFlagBits::eDepthStencilAttachmentWrite : return "DepthStencilAttachmentWrite";
+ case AccessFlagBits::eTransferRead : return "TransferRead";
+ case AccessFlagBits::eTransferWrite : return "TransferWrite";
+ case AccessFlagBits::eHostRead : return "HostRead";
+ case AccessFlagBits::eHostWrite : return "HostWrite";
+ case AccessFlagBits::eMemoryRead : return "MemoryRead";
+ case AccessFlagBits::eMemoryWrite : return "MemoryWrite";
+ case AccessFlagBits::eTransformFeedbackWriteEXT : return "TransformFeedbackWriteEXT";
+ case AccessFlagBits::eTransformFeedbackCounterReadEXT : return "TransformFeedbackCounterReadEXT";
+ case AccessFlagBits::eTransformFeedbackCounterWriteEXT : return "TransformFeedbackCounterWriteEXT";
+ case AccessFlagBits::eConditionalRenderingReadEXT : return "ConditionalRenderingReadEXT";
+ case AccessFlagBits::eCommandProcessReadNVX : return "CommandProcessReadNVX";
+ case AccessFlagBits::eCommandProcessWriteNVX : return "CommandProcessWriteNVX";
+ case AccessFlagBits::eColorAttachmentReadNoncoherentEXT : return "ColorAttachmentReadNoncoherentEXT";
+ case AccessFlagBits::eShadingRateImageReadNV : return "ShadingRateImageReadNV";
+ case AccessFlagBits::eAccelerationStructureReadNV : return "AccelerationStructureReadNV";
+ case AccessFlagBits::eAccelerationStructureWriteNV : return "AccelerationStructureWriteNV";
+ case AccessFlagBits::eFragmentDensityMapReadEXT : return "FragmentDensityMapReadEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class AcquireProfilingLockFlagBitsKHR
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( AcquireProfilingLockFlagBitsKHR )
+ {
+ return "(void)";
+ }
+
+ enum class AttachmentDescriptionFlagBits
+ {
+ eMayAlias = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( AttachmentDescriptionFlagBits value )
+ {
+ switch ( value )
+ {
+ case AttachmentDescriptionFlagBits::eMayAlias : return "MayAlias";
+ default: return "invalid";
+ }
+ }
+
+ enum class AttachmentLoadOp
+ {
+ eLoad = VK_ATTACHMENT_LOAD_OP_LOAD,
+ eClear = VK_ATTACHMENT_LOAD_OP_CLEAR,
+ eDontCare = VK_ATTACHMENT_LOAD_OP_DONT_CARE
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( AttachmentLoadOp value )
+ {
+ switch ( value )
+ {
+ case AttachmentLoadOp::eLoad : return "Load";
+ case AttachmentLoadOp::eClear : return "Clear";
+ case AttachmentLoadOp::eDontCare : return "DontCare";
+ default: return "invalid";
+ }
+ }
+
+ enum class AttachmentStoreOp
+ {
+ eStore = VK_ATTACHMENT_STORE_OP_STORE,
+ eDontCare = VK_ATTACHMENT_STORE_OP_DONT_CARE
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( AttachmentStoreOp value )
+ {
+ switch ( value )
+ {
+ case AttachmentStoreOp::eStore : return "Store";
+ case AttachmentStoreOp::eDontCare : return "DontCare";
+ default: return "invalid";
+ }
+ }
+
+ enum class BlendFactor
+ {
+ eZero = VK_BLEND_FACTOR_ZERO,
+ eOne = VK_BLEND_FACTOR_ONE,
+ eSrcColor = VK_BLEND_FACTOR_SRC_COLOR,
+ eOneMinusSrcColor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
+ eDstColor = VK_BLEND_FACTOR_DST_COLOR,
+ eOneMinusDstColor = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
+ eSrcAlpha = VK_BLEND_FACTOR_SRC_ALPHA,
+ eOneMinusSrcAlpha = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+ eDstAlpha = VK_BLEND_FACTOR_DST_ALPHA,
+ eOneMinusDstAlpha = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
+ eConstantColor = VK_BLEND_FACTOR_CONSTANT_COLOR,
+ eOneMinusConstantColor = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
+ eConstantAlpha = VK_BLEND_FACTOR_CONSTANT_ALPHA,
+ eOneMinusConstantAlpha = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
+ eSrcAlphaSaturate = VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
+ eSrc1Color = VK_BLEND_FACTOR_SRC1_COLOR,
+ eOneMinusSrc1Color = VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR,
+ eSrc1Alpha = VK_BLEND_FACTOR_SRC1_ALPHA,
+ eOneMinusSrc1Alpha = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( BlendFactor value )
+ {
+ switch ( value )
+ {
+ case BlendFactor::eZero : return "Zero";
+ case BlendFactor::eOne : return "One";
+ case BlendFactor::eSrcColor : return "SrcColor";
+ case BlendFactor::eOneMinusSrcColor : return "OneMinusSrcColor";
+ case BlendFactor::eDstColor : return "DstColor";
+ case BlendFactor::eOneMinusDstColor : return "OneMinusDstColor";
+ case BlendFactor::eSrcAlpha : return "SrcAlpha";
+ case BlendFactor::eOneMinusSrcAlpha : return "OneMinusSrcAlpha";
+ case BlendFactor::eDstAlpha : return "DstAlpha";
+ case BlendFactor::eOneMinusDstAlpha : return "OneMinusDstAlpha";
+ case BlendFactor::eConstantColor : return "ConstantColor";
+ case BlendFactor::eOneMinusConstantColor : return "OneMinusConstantColor";
+ case BlendFactor::eConstantAlpha : return "ConstantAlpha";
+ case BlendFactor::eOneMinusConstantAlpha : return "OneMinusConstantAlpha";
+ case BlendFactor::eSrcAlphaSaturate : return "SrcAlphaSaturate";
+ case BlendFactor::eSrc1Color : return "Src1Color";
+ case BlendFactor::eOneMinusSrc1Color : return "OneMinusSrc1Color";
+ case BlendFactor::eSrc1Alpha : return "Src1Alpha";
+ case BlendFactor::eOneMinusSrc1Alpha : return "OneMinusSrc1Alpha";
+ default: return "invalid";
+ }
+ }
+
+ enum class BlendOp
+ {
+ eAdd = VK_BLEND_OP_ADD,
+ eSubtract = VK_BLEND_OP_SUBTRACT,
+ eReverseSubtract = VK_BLEND_OP_REVERSE_SUBTRACT,
+ eMin = VK_BLEND_OP_MIN,
+ eMax = VK_BLEND_OP_MAX,
+ eZeroEXT = VK_BLEND_OP_ZERO_EXT,
+ eSrcEXT = VK_BLEND_OP_SRC_EXT,
+ eDstEXT = VK_BLEND_OP_DST_EXT,
+ eSrcOverEXT = VK_BLEND_OP_SRC_OVER_EXT,
+ eDstOverEXT = VK_BLEND_OP_DST_OVER_EXT,
+ eSrcInEXT = VK_BLEND_OP_SRC_IN_EXT,
+ eDstInEXT = VK_BLEND_OP_DST_IN_EXT,
+ eSrcOutEXT = VK_BLEND_OP_SRC_OUT_EXT,
+ eDstOutEXT = VK_BLEND_OP_DST_OUT_EXT,
+ eSrcAtopEXT = VK_BLEND_OP_SRC_ATOP_EXT,
+ eDstAtopEXT = VK_BLEND_OP_DST_ATOP_EXT,
+ eXorEXT = VK_BLEND_OP_XOR_EXT,
+ eMultiplyEXT = VK_BLEND_OP_MULTIPLY_EXT,
+ eScreenEXT = VK_BLEND_OP_SCREEN_EXT,
+ eOverlayEXT = VK_BLEND_OP_OVERLAY_EXT,
+ eDarkenEXT = VK_BLEND_OP_DARKEN_EXT,
+ eLightenEXT = VK_BLEND_OP_LIGHTEN_EXT,
+ eColordodgeEXT = VK_BLEND_OP_COLORDODGE_EXT,
+ eColorburnEXT = VK_BLEND_OP_COLORBURN_EXT,
+ eHardlightEXT = VK_BLEND_OP_HARDLIGHT_EXT,
+ eSoftlightEXT = VK_BLEND_OP_SOFTLIGHT_EXT,
+ eDifferenceEXT = VK_BLEND_OP_DIFFERENCE_EXT,
+ eExclusionEXT = VK_BLEND_OP_EXCLUSION_EXT,
+ eInvertEXT = VK_BLEND_OP_INVERT_EXT,
+ eInvertRgbEXT = VK_BLEND_OP_INVERT_RGB_EXT,
+ eLineardodgeEXT = VK_BLEND_OP_LINEARDODGE_EXT,
+ eLinearburnEXT = VK_BLEND_OP_LINEARBURN_EXT,
+ eVividlightEXT = VK_BLEND_OP_VIVIDLIGHT_EXT,
+ eLinearlightEXT = VK_BLEND_OP_LINEARLIGHT_EXT,
+ ePinlightEXT = VK_BLEND_OP_PINLIGHT_EXT,
+ eHardmixEXT = VK_BLEND_OP_HARDMIX_EXT,
+ eHslHueEXT = VK_BLEND_OP_HSL_HUE_EXT,
+ eHslSaturationEXT = VK_BLEND_OP_HSL_SATURATION_EXT,
+ eHslColorEXT = VK_BLEND_OP_HSL_COLOR_EXT,
+ eHslLuminosityEXT = VK_BLEND_OP_HSL_LUMINOSITY_EXT,
+ ePlusEXT = VK_BLEND_OP_PLUS_EXT,
+ ePlusClampedEXT = VK_BLEND_OP_PLUS_CLAMPED_EXT,
+ ePlusClampedAlphaEXT = VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT,
+ ePlusDarkerEXT = VK_BLEND_OP_PLUS_DARKER_EXT,
+ eMinusEXT = VK_BLEND_OP_MINUS_EXT,
+ eMinusClampedEXT = VK_BLEND_OP_MINUS_CLAMPED_EXT,
+ eContrastEXT = VK_BLEND_OP_CONTRAST_EXT,
+ eInvertOvgEXT = VK_BLEND_OP_INVERT_OVG_EXT,
+ eRedEXT = VK_BLEND_OP_RED_EXT,
+ eGreenEXT = VK_BLEND_OP_GREEN_EXT,
+ eBlueEXT = VK_BLEND_OP_BLUE_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( BlendOp value )
+ {
+ switch ( value )
+ {
+ case BlendOp::eAdd : return "Add";
+ case BlendOp::eSubtract : return "Subtract";
+ case BlendOp::eReverseSubtract : return "ReverseSubtract";
+ case BlendOp::eMin : return "Min";
+ case BlendOp::eMax : return "Max";
+ case BlendOp::eZeroEXT : return "ZeroEXT";
+ case BlendOp::eSrcEXT : return "SrcEXT";
+ case BlendOp::eDstEXT : return "DstEXT";
+ case BlendOp::eSrcOverEXT : return "SrcOverEXT";
+ case BlendOp::eDstOverEXT : return "DstOverEXT";
+ case BlendOp::eSrcInEXT : return "SrcInEXT";
+ case BlendOp::eDstInEXT : return "DstInEXT";
+ case BlendOp::eSrcOutEXT : return "SrcOutEXT";
+ case BlendOp::eDstOutEXT : return "DstOutEXT";
+ case BlendOp::eSrcAtopEXT : return "SrcAtopEXT";
+ case BlendOp::eDstAtopEXT : return "DstAtopEXT";
+ case BlendOp::eXorEXT : return "XorEXT";
+ case BlendOp::eMultiplyEXT : return "MultiplyEXT";
+ case BlendOp::eScreenEXT : return "ScreenEXT";
+ case BlendOp::eOverlayEXT : return "OverlayEXT";
+ case BlendOp::eDarkenEXT : return "DarkenEXT";
+ case BlendOp::eLightenEXT : return "LightenEXT";
+ case BlendOp::eColordodgeEXT : return "ColordodgeEXT";
+ case BlendOp::eColorburnEXT : return "ColorburnEXT";
+ case BlendOp::eHardlightEXT : return "HardlightEXT";
+ case BlendOp::eSoftlightEXT : return "SoftlightEXT";
+ case BlendOp::eDifferenceEXT : return "DifferenceEXT";
+ case BlendOp::eExclusionEXT : return "ExclusionEXT";
+ case BlendOp::eInvertEXT : return "InvertEXT";
+ case BlendOp::eInvertRgbEXT : return "InvertRgbEXT";
+ case BlendOp::eLineardodgeEXT : return "LineardodgeEXT";
+ case BlendOp::eLinearburnEXT : return "LinearburnEXT";
+ case BlendOp::eVividlightEXT : return "VividlightEXT";
+ case BlendOp::eLinearlightEXT : return "LinearlightEXT";
+ case BlendOp::ePinlightEXT : return "PinlightEXT";
+ case BlendOp::eHardmixEXT : return "HardmixEXT";
+ case BlendOp::eHslHueEXT : return "HslHueEXT";
+ case BlendOp::eHslSaturationEXT : return "HslSaturationEXT";
+ case BlendOp::eHslColorEXT : return "HslColorEXT";
+ case BlendOp::eHslLuminosityEXT : return "HslLuminosityEXT";
+ case BlendOp::ePlusEXT : return "PlusEXT";
+ case BlendOp::ePlusClampedEXT : return "PlusClampedEXT";
+ case BlendOp::ePlusClampedAlphaEXT : return "PlusClampedAlphaEXT";
+ case BlendOp::ePlusDarkerEXT : return "PlusDarkerEXT";
+ case BlendOp::eMinusEXT : return "MinusEXT";
+ case BlendOp::eMinusClampedEXT : return "MinusClampedEXT";
+ case BlendOp::eContrastEXT : return "ContrastEXT";
+ case BlendOp::eInvertOvgEXT : return "InvertOvgEXT";
+ case BlendOp::eRedEXT : return "RedEXT";
+ case BlendOp::eGreenEXT : return "GreenEXT";
+ case BlendOp::eBlueEXT : return "BlueEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class BlendOverlapEXT
+ {
+ eUncorrelated = VK_BLEND_OVERLAP_UNCORRELATED_EXT,
+ eDisjoint = VK_BLEND_OVERLAP_DISJOINT_EXT,
+ eConjoint = VK_BLEND_OVERLAP_CONJOINT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( BlendOverlapEXT value )
+ {
+ switch ( value )
+ {
+ case BlendOverlapEXT::eUncorrelated : return "Uncorrelated";
+ case BlendOverlapEXT::eDisjoint : return "Disjoint";
+ case BlendOverlapEXT::eConjoint : return "Conjoint";
+ default: return "invalid";
+ }
+ }
+
+ enum class BorderColor
+ {
+ eFloatTransparentBlack = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
+ eIntTransparentBlack = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,
+ eFloatOpaqueBlack = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,
+ eIntOpaqueBlack = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
+ eFloatOpaqueWhite = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
+ eIntOpaqueWhite = VK_BORDER_COLOR_INT_OPAQUE_WHITE
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( BorderColor value )
+ {
+ switch ( value )
+ {
+ case BorderColor::eFloatTransparentBlack : return "FloatTransparentBlack";
+ case BorderColor::eIntTransparentBlack : return "IntTransparentBlack";
+ case BorderColor::eFloatOpaqueBlack : return "FloatOpaqueBlack";
+ case BorderColor::eIntOpaqueBlack : return "IntOpaqueBlack";
+ case BorderColor::eFloatOpaqueWhite : return "FloatOpaqueWhite";
+ case BorderColor::eIntOpaqueWhite : return "IntOpaqueWhite";
+ default: return "invalid";
+ }
+ }
+
+ enum class BufferCreateFlagBits
+ {
+ eSparseBinding = VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
+ eSparseResidency = VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
+ eSparseAliased = VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
+ eProtected = VK_BUFFER_CREATE_PROTECTED_BIT,
+ eDeviceAddressCaptureReplay = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT,
+ eDeviceAddressCaptureReplayEXT = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT,
+ eDeviceAddressCaptureReplayKHR = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( BufferCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case BufferCreateFlagBits::eSparseBinding : return "SparseBinding";
+ case BufferCreateFlagBits::eSparseResidency : return "SparseResidency";
+ case BufferCreateFlagBits::eSparseAliased : return "SparseAliased";
+ case BufferCreateFlagBits::eProtected : return "Protected";
+ case BufferCreateFlagBits::eDeviceAddressCaptureReplay : return "DeviceAddressCaptureReplay";
+ default: return "invalid";
+ }
+ }
+
+ enum class BufferUsageFlagBits
+ {
+ eTransferSrc = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ eTransferDst = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ eUniformTexelBuffer = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
+ eStorageTexelBuffer = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
+ eUniformBuffer = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+ eStorageBuffer = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+ eIndexBuffer = VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
+ eVertexBuffer = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
+ eIndirectBuffer = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
+ eShaderDeviceAddress = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+ eTransformFeedbackBufferEXT = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT,
+ eTransformFeedbackCounterBufferEXT = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT,
+ eConditionalRenderingEXT = VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT,
+ eRayTracingNV = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV,
+ eShaderDeviceAddressEXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT,
+ eShaderDeviceAddressKHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( BufferUsageFlagBits value )
+ {
+ switch ( value )
+ {
+ case BufferUsageFlagBits::eTransferSrc : return "TransferSrc";
+ case BufferUsageFlagBits::eTransferDst : return "TransferDst";
+ case BufferUsageFlagBits::eUniformTexelBuffer : return "UniformTexelBuffer";
+ case BufferUsageFlagBits::eStorageTexelBuffer : return "StorageTexelBuffer";
+ case BufferUsageFlagBits::eUniformBuffer : return "UniformBuffer";
+ case BufferUsageFlagBits::eStorageBuffer : return "StorageBuffer";
+ case BufferUsageFlagBits::eIndexBuffer : return "IndexBuffer";
+ case BufferUsageFlagBits::eVertexBuffer : return "VertexBuffer";
+ case BufferUsageFlagBits::eIndirectBuffer : return "IndirectBuffer";
+ case BufferUsageFlagBits::eShaderDeviceAddress : return "ShaderDeviceAddress";
+ case BufferUsageFlagBits::eTransformFeedbackBufferEXT : return "TransformFeedbackBufferEXT";
+ case BufferUsageFlagBits::eTransformFeedbackCounterBufferEXT : return "TransformFeedbackCounterBufferEXT";
+ case BufferUsageFlagBits::eConditionalRenderingEXT : return "ConditionalRenderingEXT";
+ case BufferUsageFlagBits::eRayTracingNV : return "RayTracingNV";
+ default: return "invalid";
+ }
+ }
+
+ enum class BufferViewCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( BufferViewCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class BuildAccelerationStructureFlagBitsNV
+ {
+ eAllowUpdate = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV,
+ eAllowCompaction = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV,
+ ePreferFastTrace = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV,
+ ePreferFastBuild = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV,
+ eLowMemory = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( BuildAccelerationStructureFlagBitsNV value )
+ {
+ switch ( value )
+ {
+ case BuildAccelerationStructureFlagBitsNV::eAllowUpdate : return "AllowUpdate";
+ case BuildAccelerationStructureFlagBitsNV::eAllowCompaction : return "AllowCompaction";
+ case BuildAccelerationStructureFlagBitsNV::ePreferFastTrace : return "PreferFastTrace";
+ case BuildAccelerationStructureFlagBitsNV::ePreferFastBuild : return "PreferFastBuild";
+ case BuildAccelerationStructureFlagBitsNV::eLowMemory : return "LowMemory";
+ default: return "invalid";
+ }
+ }
+
+ enum class ChromaLocation
+ {
+ eCositedEven = VK_CHROMA_LOCATION_COSITED_EVEN,
+ eMidpoint = VK_CHROMA_LOCATION_MIDPOINT
+ };
+ using ChromaLocationKHR = ChromaLocation;
+
+ VULKAN_HPP_INLINE std::string to_string( ChromaLocation value )
+ {
+ switch ( value )
+ {
+ case ChromaLocation::eCositedEven : return "CositedEven";
+ case ChromaLocation::eMidpoint : return "Midpoint";
+ default: return "invalid";
+ }
+ }
+
+ enum class CoarseSampleOrderTypeNV
+ {
+ eDefault = VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV,
+ eCustom = VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV,
+ ePixelMajor = VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV,
+ eSampleMajor = VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CoarseSampleOrderTypeNV value )
+ {
+ switch ( value )
+ {
+ case CoarseSampleOrderTypeNV::eDefault : return "Default";
+ case CoarseSampleOrderTypeNV::eCustom : return "Custom";
+ case CoarseSampleOrderTypeNV::ePixelMajor : return "PixelMajor";
+ case CoarseSampleOrderTypeNV::eSampleMajor : return "SampleMajor";
+ default: return "invalid";
+ }
+ }
+
+ enum class ColorComponentFlagBits
+ {
+ eR = VK_COLOR_COMPONENT_R_BIT,
+ eG = VK_COLOR_COMPONENT_G_BIT,
+ eB = VK_COLOR_COMPONENT_B_BIT,
+ eA = VK_COLOR_COMPONENT_A_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ColorComponentFlagBits value )
+ {
+ switch ( value )
+ {
+ case ColorComponentFlagBits::eR : return "R";
+ case ColorComponentFlagBits::eG : return "G";
+ case ColorComponentFlagBits::eB : return "B";
+ case ColorComponentFlagBits::eA : return "A";
+ default: return "invalid";
+ }
+ }
+
+ enum class ColorSpaceKHR
+ {
+ eSrgbNonlinear = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ eDisplayP3NonlinearEXT = VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT,
+ eExtendedSrgbLinearEXT = VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT,
+ eDisplayP3LinearEXT = VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT,
+ eDciP3NonlinearEXT = VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT,
+ eBt709LinearEXT = VK_COLOR_SPACE_BT709_LINEAR_EXT,
+ eBt709NonlinearEXT = VK_COLOR_SPACE_BT709_NONLINEAR_EXT,
+ eBt2020LinearEXT = VK_COLOR_SPACE_BT2020_LINEAR_EXT,
+ eHdr10St2084EXT = VK_COLOR_SPACE_HDR10_ST2084_EXT,
+ eDolbyvisionEXT = VK_COLOR_SPACE_DOLBYVISION_EXT,
+ eHdr10HlgEXT = VK_COLOR_SPACE_HDR10_HLG_EXT,
+ eAdobergbLinearEXT = VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT,
+ eAdobergbNonlinearEXT = VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT,
+ ePassThroughEXT = VK_COLOR_SPACE_PASS_THROUGH_EXT,
+ eExtendedSrgbNonlinearEXT = VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT,
+ eDisplayNativeAMD = VK_COLOR_SPACE_DISPLAY_NATIVE_AMD,
+ eVkColorspaceSrgbNonlinear = VK_COLORSPACE_SRGB_NONLINEAR_KHR,
+ eDciP3LinearEXT = VK_COLOR_SPACE_DCI_P3_LINEAR_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ColorSpaceKHR value )
+ {
+ switch ( value )
+ {
+ case ColorSpaceKHR::eSrgbNonlinear : return "SrgbNonlinear";
+ case ColorSpaceKHR::eDisplayP3NonlinearEXT : return "DisplayP3NonlinearEXT";
+ case ColorSpaceKHR::eExtendedSrgbLinearEXT : return "ExtendedSrgbLinearEXT";
+ case ColorSpaceKHR::eDisplayP3LinearEXT : return "DisplayP3LinearEXT";
+ case ColorSpaceKHR::eDciP3NonlinearEXT : return "DciP3NonlinearEXT";
+ case ColorSpaceKHR::eBt709LinearEXT : return "Bt709LinearEXT";
+ case ColorSpaceKHR::eBt709NonlinearEXT : return "Bt709NonlinearEXT";
+ case ColorSpaceKHR::eBt2020LinearEXT : return "Bt2020LinearEXT";
+ case ColorSpaceKHR::eHdr10St2084EXT : return "Hdr10St2084EXT";
+ case ColorSpaceKHR::eDolbyvisionEXT : return "DolbyvisionEXT";
+ case ColorSpaceKHR::eHdr10HlgEXT : return "Hdr10HlgEXT";
+ case ColorSpaceKHR::eAdobergbLinearEXT : return "AdobergbLinearEXT";
+ case ColorSpaceKHR::eAdobergbNonlinearEXT : return "AdobergbNonlinearEXT";
+ case ColorSpaceKHR::ePassThroughEXT : return "PassThroughEXT";
+ case ColorSpaceKHR::eExtendedSrgbNonlinearEXT : return "ExtendedSrgbNonlinearEXT";
+ case ColorSpaceKHR::eDisplayNativeAMD : return "DisplayNativeAMD";
+ default: return "invalid";
+ }
+ }
+
+ enum class CommandBufferLevel
+ {
+ ePrimary = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ eSecondary = VK_COMMAND_BUFFER_LEVEL_SECONDARY
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CommandBufferLevel value )
+ {
+ switch ( value )
+ {
+ case CommandBufferLevel::ePrimary : return "Primary";
+ case CommandBufferLevel::eSecondary : return "Secondary";
+ default: return "invalid";
+ }
+ }
+
+ enum class CommandBufferResetFlagBits
+ {
+ eReleaseResources = VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CommandBufferResetFlagBits value )
+ {
+ switch ( value )
+ {
+ case CommandBufferResetFlagBits::eReleaseResources : return "ReleaseResources";
+ default: return "invalid";
+ }
+ }
+
+ enum class CommandBufferUsageFlagBits
+ {
+ eOneTimeSubmit = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+ eRenderPassContinue = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
+ eSimultaneousUse = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CommandBufferUsageFlagBits value )
+ {
+ switch ( value )
+ {
+ case CommandBufferUsageFlagBits::eOneTimeSubmit : return "OneTimeSubmit";
+ case CommandBufferUsageFlagBits::eRenderPassContinue : return "RenderPassContinue";
+ case CommandBufferUsageFlagBits::eSimultaneousUse : return "SimultaneousUse";
+ default: return "invalid";
+ }
+ }
+
+ enum class CommandPoolCreateFlagBits
+ {
+ eTransient = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
+ eResetCommandBuffer = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
+ eProtected = VK_COMMAND_POOL_CREATE_PROTECTED_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CommandPoolCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case CommandPoolCreateFlagBits::eTransient : return "Transient";
+ case CommandPoolCreateFlagBits::eResetCommandBuffer : return "ResetCommandBuffer";
+ case CommandPoolCreateFlagBits::eProtected : return "Protected";
+ default: return "invalid";
+ }
+ }
+
+ enum class CommandPoolResetFlagBits
+ {
+ eReleaseResources = VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CommandPoolResetFlagBits value )
+ {
+ switch ( value )
+ {
+ case CommandPoolResetFlagBits::eReleaseResources : return "ReleaseResources";
+ default: return "invalid";
+ }
+ }
+
+ enum class CompareOp
+ {
+ eNever = VK_COMPARE_OP_NEVER,
+ eLess = VK_COMPARE_OP_LESS,
+ eEqual = VK_COMPARE_OP_EQUAL,
+ eLessOrEqual = VK_COMPARE_OP_LESS_OR_EQUAL,
+ eGreater = VK_COMPARE_OP_GREATER,
+ eNotEqual = VK_COMPARE_OP_NOT_EQUAL,
+ eGreaterOrEqual = VK_COMPARE_OP_GREATER_OR_EQUAL,
+ eAlways = VK_COMPARE_OP_ALWAYS
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CompareOp value )
+ {
+ switch ( value )
+ {
+ case CompareOp::eNever : return "Never";
+ case CompareOp::eLess : return "Less";
+ case CompareOp::eEqual : return "Equal";
+ case CompareOp::eLessOrEqual : return "LessOrEqual";
+ case CompareOp::eGreater : return "Greater";
+ case CompareOp::eNotEqual : return "NotEqual";
+ case CompareOp::eGreaterOrEqual : return "GreaterOrEqual";
+ case CompareOp::eAlways : return "Always";
+ default: return "invalid";
+ }
+ }
+
+ enum class ComponentSwizzle
+ {
+ eIdentity = VK_COMPONENT_SWIZZLE_IDENTITY,
+ eZero = VK_COMPONENT_SWIZZLE_ZERO,
+ eOne = VK_COMPONENT_SWIZZLE_ONE,
+ eR = VK_COMPONENT_SWIZZLE_R,
+ eG = VK_COMPONENT_SWIZZLE_G,
+ eB = VK_COMPONENT_SWIZZLE_B,
+ eA = VK_COMPONENT_SWIZZLE_A
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ComponentSwizzle value )
+ {
+ switch ( value )
+ {
+ case ComponentSwizzle::eIdentity : return "Identity";
+ case ComponentSwizzle::eZero : return "Zero";
+ case ComponentSwizzle::eOne : return "One";
+ case ComponentSwizzle::eR : return "R";
+ case ComponentSwizzle::eG : return "G";
+ case ComponentSwizzle::eB : return "B";
+ case ComponentSwizzle::eA : return "A";
+ default: return "invalid";
+ }
+ }
+
+ enum class ComponentTypeNV
+ {
+ eFloat16 = VK_COMPONENT_TYPE_FLOAT16_NV,
+ eFloat32 = VK_COMPONENT_TYPE_FLOAT32_NV,
+ eFloat64 = VK_COMPONENT_TYPE_FLOAT64_NV,
+ eSint8 = VK_COMPONENT_TYPE_SINT8_NV,
+ eSint16 = VK_COMPONENT_TYPE_SINT16_NV,
+ eSint32 = VK_COMPONENT_TYPE_SINT32_NV,
+ eSint64 = VK_COMPONENT_TYPE_SINT64_NV,
+ eUint8 = VK_COMPONENT_TYPE_UINT8_NV,
+ eUint16 = VK_COMPONENT_TYPE_UINT16_NV,
+ eUint32 = VK_COMPONENT_TYPE_UINT32_NV,
+ eUint64 = VK_COMPONENT_TYPE_UINT64_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ComponentTypeNV value )
+ {
+ switch ( value )
+ {
+ case ComponentTypeNV::eFloat16 : return "Float16";
+ case ComponentTypeNV::eFloat32 : return "Float32";
+ case ComponentTypeNV::eFloat64 : return "Float64";
+ case ComponentTypeNV::eSint8 : return "Sint8";
+ case ComponentTypeNV::eSint16 : return "Sint16";
+ case ComponentTypeNV::eSint32 : return "Sint32";
+ case ComponentTypeNV::eSint64 : return "Sint64";
+ case ComponentTypeNV::eUint8 : return "Uint8";
+ case ComponentTypeNV::eUint16 : return "Uint16";
+ case ComponentTypeNV::eUint32 : return "Uint32";
+ case ComponentTypeNV::eUint64 : return "Uint64";
+ default: return "invalid";
+ }
+ }
+
+ enum class CompositeAlphaFlagBitsKHR
+ {
+ eOpaque = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+ ePreMultiplied = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
+ ePostMultiplied = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
+ eInherit = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CompositeAlphaFlagBitsKHR value )
+ {
+ switch ( value )
+ {
+ case CompositeAlphaFlagBitsKHR::eOpaque : return "Opaque";
+ case CompositeAlphaFlagBitsKHR::ePreMultiplied : return "PreMultiplied";
+ case CompositeAlphaFlagBitsKHR::ePostMultiplied : return "PostMultiplied";
+ case CompositeAlphaFlagBitsKHR::eInherit : return "Inherit";
+ default: return "invalid";
+ }
+ }
+
+ enum class ConditionalRenderingFlagBitsEXT
+ {
+ eInverted = VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ConditionalRenderingFlagBitsEXT value )
+ {
+ switch ( value )
+ {
+ case ConditionalRenderingFlagBitsEXT::eInverted : return "Inverted";
+ default: return "invalid";
+ }
+ }
+
+ enum class ConservativeRasterizationModeEXT
+ {
+ eDisabled = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT,
+ eOverestimate = VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT,
+ eUnderestimate = VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ConservativeRasterizationModeEXT value )
+ {
+ switch ( value )
+ {
+ case ConservativeRasterizationModeEXT::eDisabled : return "Disabled";
+ case ConservativeRasterizationModeEXT::eOverestimate : return "Overestimate";
+ case ConservativeRasterizationModeEXT::eUnderestimate : return "Underestimate";
+ default: return "invalid";
+ }
+ }
+
+ enum class CopyAccelerationStructureModeNV
+ {
+ eClone = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV,
+ eCompact = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CopyAccelerationStructureModeNV value )
+ {
+ switch ( value )
+ {
+ case CopyAccelerationStructureModeNV::eClone : return "Clone";
+ case CopyAccelerationStructureModeNV::eCompact : return "Compact";
+ default: return "invalid";
+ }
+ }
+
+ enum class CoverageModulationModeNV
+ {
+ eNone = VK_COVERAGE_MODULATION_MODE_NONE_NV,
+ eRgb = VK_COVERAGE_MODULATION_MODE_RGB_NV,
+ eAlpha = VK_COVERAGE_MODULATION_MODE_ALPHA_NV,
+ eRgba = VK_COVERAGE_MODULATION_MODE_RGBA_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CoverageModulationModeNV value )
+ {
+ switch ( value )
+ {
+ case CoverageModulationModeNV::eNone : return "None";
+ case CoverageModulationModeNV::eRgb : return "Rgb";
+ case CoverageModulationModeNV::eAlpha : return "Alpha";
+ case CoverageModulationModeNV::eRgba : return "Rgba";
+ default: return "invalid";
+ }
+ }
+
+ enum class CoverageReductionModeNV
+ {
+ eMerge = VK_COVERAGE_REDUCTION_MODE_MERGE_NV,
+ eTruncate = VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CoverageReductionModeNV value )
+ {
+ switch ( value )
+ {
+ case CoverageReductionModeNV::eMerge : return "Merge";
+ case CoverageReductionModeNV::eTruncate : return "Truncate";
+ default: return "invalid";
+ }
+ }
+
+ enum class CullModeFlagBits
+ {
+ eNone = VK_CULL_MODE_NONE,
+ eFront = VK_CULL_MODE_FRONT_BIT,
+ eBack = VK_CULL_MODE_BACK_BIT,
+ eFrontAndBack = VK_CULL_MODE_FRONT_AND_BACK
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( CullModeFlagBits value )
+ {
+ switch ( value )
+ {
+ case CullModeFlagBits::eNone : return "None";
+ case CullModeFlagBits::eFront : return "Front";
+ case CullModeFlagBits::eBack : return "Back";
+ case CullModeFlagBits::eFrontAndBack : return "FrontAndBack";
+ default: return "invalid";
+ }
+ }
+
+ enum class DebugReportFlagBitsEXT
+ {
+ eInformation = VK_DEBUG_REPORT_INFORMATION_BIT_EXT,
+ eWarning = VK_DEBUG_REPORT_WARNING_BIT_EXT,
+ ePerformanceWarning = VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
+ eError = VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ eDebug = VK_DEBUG_REPORT_DEBUG_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DebugReportFlagBitsEXT value )
+ {
+ switch ( value )
+ {
+ case DebugReportFlagBitsEXT::eInformation : return "Information";
+ case DebugReportFlagBitsEXT::eWarning : return "Warning";
+ case DebugReportFlagBitsEXT::ePerformanceWarning : return "PerformanceWarning";
+ case DebugReportFlagBitsEXT::eError : return "Error";
+ case DebugReportFlagBitsEXT::eDebug : return "Debug";
+ default: return "invalid";
+ }
+ }
+
+ enum class DebugReportObjectTypeEXT
+ {
+ eUnknown = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
+ eInstance = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
+ ePhysicalDevice = VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
+ eDevice = VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
+ eQueue = VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT,
+ eSemaphore = VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
+ eCommandBuffer = VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+ eFence = VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
+ eDeviceMemory = VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
+ eBuffer = VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
+ eImage = VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ eEvent = VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT,
+ eQueryPool = VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT,
+ eBufferView = VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT,
+ eImageView = VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
+ eShaderModule = VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT,
+ ePipelineCache = VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT,
+ ePipelineLayout = VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT,
+ eRenderPass = VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
+ ePipeline = VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
+ eDescriptorSetLayout = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
+ eSampler = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT,
+ eDescriptorPool = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
+ eDescriptorSet = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
+ eFramebuffer = VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT,
+ eCommandPool = VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT,
+ eSurfaceKHR = VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT,
+ eSwapchainKHR = VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
+ eDebugReportCallbackEXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT,
+ eDisplayKHR = VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT,
+ eDisplayModeKHR = VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT,
+ eObjectTableNVX = VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT,
+ eIndirectCommandsLayoutNVX = VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT,
+ eValidationCacheEXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
+ eSamplerYcbcrConversion = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT,
+ eDescriptorUpdateTemplate = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT,
+ eAccelerationStructureNV = VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT,
+ eDebugReport = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
+ eValidationCache = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT,
+ eDescriptorUpdateTemplateKHR = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT,
+ eSamplerYcbcrConversionKHR = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DebugReportObjectTypeEXT value )
+ {
+ switch ( value )
+ {
+ case DebugReportObjectTypeEXT::eUnknown : return "Unknown";
+ case DebugReportObjectTypeEXT::eInstance : return "Instance";
+ case DebugReportObjectTypeEXT::ePhysicalDevice : return "PhysicalDevice";
+ case DebugReportObjectTypeEXT::eDevice : return "Device";
+ case DebugReportObjectTypeEXT::eQueue : return "Queue";
+ case DebugReportObjectTypeEXT::eSemaphore : return "Semaphore";
+ case DebugReportObjectTypeEXT::eCommandBuffer : return "CommandBuffer";
+ case DebugReportObjectTypeEXT::eFence : return "Fence";
+ case DebugReportObjectTypeEXT::eDeviceMemory : return "DeviceMemory";
+ case DebugReportObjectTypeEXT::eBuffer : return "Buffer";
+ case DebugReportObjectTypeEXT::eImage : return "Image";
+ case DebugReportObjectTypeEXT::eEvent : return "Event";
+ case DebugReportObjectTypeEXT::eQueryPool : return "QueryPool";
+ case DebugReportObjectTypeEXT::eBufferView : return "BufferView";
+ case DebugReportObjectTypeEXT::eImageView : return "ImageView";
+ case DebugReportObjectTypeEXT::eShaderModule : return "ShaderModule";
+ case DebugReportObjectTypeEXT::ePipelineCache : return "PipelineCache";
+ case DebugReportObjectTypeEXT::ePipelineLayout : return "PipelineLayout";
+ case DebugReportObjectTypeEXT::eRenderPass : return "RenderPass";
+ case DebugReportObjectTypeEXT::ePipeline : return "Pipeline";
+ case DebugReportObjectTypeEXT::eDescriptorSetLayout : return "DescriptorSetLayout";
+ case DebugReportObjectTypeEXT::eSampler : return "Sampler";
+ case DebugReportObjectTypeEXT::eDescriptorPool : return "DescriptorPool";
+ case DebugReportObjectTypeEXT::eDescriptorSet : return "DescriptorSet";
+ case DebugReportObjectTypeEXT::eFramebuffer : return "Framebuffer";
+ case DebugReportObjectTypeEXT::eCommandPool : return "CommandPool";
+ case DebugReportObjectTypeEXT::eSurfaceKHR : return "SurfaceKHR";
+ case DebugReportObjectTypeEXT::eSwapchainKHR : return "SwapchainKHR";
+ case DebugReportObjectTypeEXT::eDebugReportCallbackEXT : return "DebugReportCallbackEXT";
+ case DebugReportObjectTypeEXT::eDisplayKHR : return "DisplayKHR";
+ case DebugReportObjectTypeEXT::eDisplayModeKHR : return "DisplayModeKHR";
+ case DebugReportObjectTypeEXT::eObjectTableNVX : return "ObjectTableNVX";
+ case DebugReportObjectTypeEXT::eIndirectCommandsLayoutNVX : return "IndirectCommandsLayoutNVX";
+ case DebugReportObjectTypeEXT::eValidationCacheEXT : return "ValidationCacheEXT";
+ case DebugReportObjectTypeEXT::eSamplerYcbcrConversion : return "SamplerYcbcrConversion";
+ case DebugReportObjectTypeEXT::eDescriptorUpdateTemplate : return "DescriptorUpdateTemplate";
+ case DebugReportObjectTypeEXT::eAccelerationStructureNV : return "AccelerationStructureNV";
+ default: return "invalid";
+ }
+ }
+
+ enum class DebugUtilsMessageSeverityFlagBitsEXT
+ {
+ eVerbose = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
+ eInfo = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
+ eWarning = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
+ eError = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DebugUtilsMessageSeverityFlagBitsEXT value )
+ {
+ switch ( value )
+ {
+ case DebugUtilsMessageSeverityFlagBitsEXT::eVerbose : return "Verbose";
+ case DebugUtilsMessageSeverityFlagBitsEXT::eInfo : return "Info";
+ case DebugUtilsMessageSeverityFlagBitsEXT::eWarning : return "Warning";
+ case DebugUtilsMessageSeverityFlagBitsEXT::eError : return "Error";
+ default: return "invalid";
+ }
+ }
+
+ enum class DebugUtilsMessageTypeFlagBitsEXT
+ {
+ eGeneral = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+ eValidation = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+ ePerformance = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DebugUtilsMessageTypeFlagBitsEXT value )
+ {
+ switch ( value )
+ {
+ case DebugUtilsMessageTypeFlagBitsEXT::eGeneral : return "General";
+ case DebugUtilsMessageTypeFlagBitsEXT::eValidation : return "Validation";
+ case DebugUtilsMessageTypeFlagBitsEXT::ePerformance : return "Performance";
+ default: return "invalid";
+ }
+ }
+
+ enum class DependencyFlagBits
+ {
+ eByRegion = VK_DEPENDENCY_BY_REGION_BIT,
+ eDeviceGroup = VK_DEPENDENCY_DEVICE_GROUP_BIT,
+ eViewLocal = VK_DEPENDENCY_VIEW_LOCAL_BIT,
+ eViewLocalKHR = VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR,
+ eDeviceGroupKHR = VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DependencyFlagBits value )
+ {
+ switch ( value )
+ {
+ case DependencyFlagBits::eByRegion : return "ByRegion";
+ case DependencyFlagBits::eDeviceGroup : return "DeviceGroup";
+ case DependencyFlagBits::eViewLocal : return "ViewLocal";
+ default: return "invalid";
+ }
+ }
+
+ enum class DescriptorBindingFlagBits
+ {
+ eUpdateAfterBind = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
+ eUpdateUnusedWhilePending = VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
+ ePartiallyBound = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT,
+ eVariableDescriptorCount = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
+ };
+ using DescriptorBindingFlagBitsEXT = DescriptorBindingFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorBindingFlagBits value )
+ {
+ switch ( value )
+ {
+ case DescriptorBindingFlagBits::eUpdateAfterBind : return "UpdateAfterBind";
+ case DescriptorBindingFlagBits::eUpdateUnusedWhilePending : return "UpdateUnusedWhilePending";
+ case DescriptorBindingFlagBits::ePartiallyBound : return "PartiallyBound";
+ case DescriptorBindingFlagBits::eVariableDescriptorCount : return "VariableDescriptorCount";
+ default: return "invalid";
+ }
+ }
+
+ enum class DescriptorPoolCreateFlagBits
+ {
+ eFreeDescriptorSet = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
+ eUpdateAfterBind = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
+ eUpdateAfterBindEXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorPoolCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case DescriptorPoolCreateFlagBits::eFreeDescriptorSet : return "FreeDescriptorSet";
+ case DescriptorPoolCreateFlagBits::eUpdateAfterBind : return "UpdateAfterBind";
+ default: return "invalid";
+ }
+ }
+
+ enum class DescriptorSetLayoutCreateFlagBits
+ {
+ eUpdateAfterBindPool = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
+ ePushDescriptorKHR = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
+ eUpdateAfterBindPoolEXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorSetLayoutCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool : return "UpdateAfterBindPool";
+ case DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR : return "PushDescriptorKHR";
+ default: return "invalid";
+ }
+ }
+
+ enum class DescriptorType
+ {
+ eSampler = VK_DESCRIPTOR_TYPE_SAMPLER,
+ eCombinedImageSampler = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ eSampledImage = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ eStorageImage = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ eUniformTexelBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
+ eStorageTexelBuffer = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
+ eUniformBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ eStorageBuffer = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ eUniformBufferDynamic = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ eStorageBufferDynamic = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
+ eInputAttachment = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ eInlineUniformBlockEXT = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT,
+ eAccelerationStructureNV = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorType value )
+ {
+ switch ( value )
+ {
+ case DescriptorType::eSampler : return "Sampler";
+ case DescriptorType::eCombinedImageSampler : return "CombinedImageSampler";
+ case DescriptorType::eSampledImage : return "SampledImage";
+ case DescriptorType::eStorageImage : return "StorageImage";
+ case DescriptorType::eUniformTexelBuffer : return "UniformTexelBuffer";
+ case DescriptorType::eStorageTexelBuffer : return "StorageTexelBuffer";
+ case DescriptorType::eUniformBuffer : return "UniformBuffer";
+ case DescriptorType::eStorageBuffer : return "StorageBuffer";
+ case DescriptorType::eUniformBufferDynamic : return "UniformBufferDynamic";
+ case DescriptorType::eStorageBufferDynamic : return "StorageBufferDynamic";
+ case DescriptorType::eInputAttachment : return "InputAttachment";
+ case DescriptorType::eInlineUniformBlockEXT : return "InlineUniformBlockEXT";
+ case DescriptorType::eAccelerationStructureNV : return "AccelerationStructureNV";
+ default: return "invalid";
+ }
+ }
+
+ enum class DescriptorUpdateTemplateType
+ {
+ eDescriptorSet = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
+ ePushDescriptorsKHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR
+ };
+ using DescriptorUpdateTemplateTypeKHR = DescriptorUpdateTemplateType;
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorUpdateTemplateType value )
+ {
+ switch ( value )
+ {
+ case DescriptorUpdateTemplateType::eDescriptorSet : return "DescriptorSet";
+ case DescriptorUpdateTemplateType::ePushDescriptorsKHR : return "PushDescriptorsKHR";
+ default: return "invalid";
+ }
+ }
+
+ enum class DeviceCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( DeviceCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class DeviceEventTypeEXT
+ {
+ eDisplayHotplug = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DeviceEventTypeEXT value )
+ {
+ switch ( value )
+ {
+ case DeviceEventTypeEXT::eDisplayHotplug : return "DisplayHotplug";
+ default: return "invalid";
+ }
+ }
+
+ enum class DeviceGroupPresentModeFlagBitsKHR
+ {
+ eLocal = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR,
+ eRemote = VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR,
+ eSum = VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR,
+ eLocalMultiDevice = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DeviceGroupPresentModeFlagBitsKHR value )
+ {
+ switch ( value )
+ {
+ case DeviceGroupPresentModeFlagBitsKHR::eLocal : return "Local";
+ case DeviceGroupPresentModeFlagBitsKHR::eRemote : return "Remote";
+ case DeviceGroupPresentModeFlagBitsKHR::eSum : return "Sum";
+ case DeviceGroupPresentModeFlagBitsKHR::eLocalMultiDevice : return "LocalMultiDevice";
+ default: return "invalid";
+ }
+ }
+
+ enum class DeviceQueueCreateFlagBits
+ {
+ eProtected = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DeviceQueueCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case DeviceQueueCreateFlagBits::eProtected : return "Protected";
+ default: return "invalid";
+ }
+ }
+
+ enum class DiscardRectangleModeEXT
+ {
+ eInclusive = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT,
+ eExclusive = VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DiscardRectangleModeEXT value )
+ {
+ switch ( value )
+ {
+ case DiscardRectangleModeEXT::eInclusive : return "Inclusive";
+ case DiscardRectangleModeEXT::eExclusive : return "Exclusive";
+ default: return "invalid";
+ }
+ }
+
+ enum class DisplayEventTypeEXT
+ {
+ eFirstPixelOut = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DisplayEventTypeEXT value )
+ {
+ switch ( value )
+ {
+ case DisplayEventTypeEXT::eFirstPixelOut : return "FirstPixelOut";
+ default: return "invalid";
+ }
+ }
+
+ enum class DisplayPlaneAlphaFlagBitsKHR
+ {
+ eOpaque = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR,
+ eGlobal = VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR,
+ ePerPixel = VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR,
+ ePerPixelPremultiplied = VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DisplayPlaneAlphaFlagBitsKHR value )
+ {
+ switch ( value )
+ {
+ case DisplayPlaneAlphaFlagBitsKHR::eOpaque : return "Opaque";
+ case DisplayPlaneAlphaFlagBitsKHR::eGlobal : return "Global";
+ case DisplayPlaneAlphaFlagBitsKHR::ePerPixel : return "PerPixel";
+ case DisplayPlaneAlphaFlagBitsKHR::ePerPixelPremultiplied : return "PerPixelPremultiplied";
+ default: return "invalid";
+ }
+ }
+
+ enum class DisplayPowerStateEXT
+ {
+ eOff = VK_DISPLAY_POWER_STATE_OFF_EXT,
+ eSuspend = VK_DISPLAY_POWER_STATE_SUSPEND_EXT,
+ eOn = VK_DISPLAY_POWER_STATE_ON_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DisplayPowerStateEXT value )
+ {
+ switch ( value )
+ {
+ case DisplayPowerStateEXT::eOff : return "Off";
+ case DisplayPowerStateEXT::eSuspend : return "Suspend";
+ case DisplayPowerStateEXT::eOn : return "On";
+ default: return "invalid";
+ }
+ }
+
+ enum class DriverId
+ {
+ eAmdProprietary = VK_DRIVER_ID_AMD_PROPRIETARY,
+ eAmdOpenSource = VK_DRIVER_ID_AMD_OPEN_SOURCE,
+ eMesaRadv = VK_DRIVER_ID_MESA_RADV,
+ eNvidiaProprietary = VK_DRIVER_ID_NVIDIA_PROPRIETARY,
+ eIntelProprietaryWindows = VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS,
+ eIntelOpenSourceMESA = VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA,
+ eImaginationProprietary = VK_DRIVER_ID_IMAGINATION_PROPRIETARY,
+ eQualcommProprietary = VK_DRIVER_ID_QUALCOMM_PROPRIETARY,
+ eArmProprietary = VK_DRIVER_ID_ARM_PROPRIETARY,
+ eGoogleSwiftshader = VK_DRIVER_ID_GOOGLE_SWIFTSHADER,
+ eGgpProprietary = VK_DRIVER_ID_GGP_PROPRIETARY,
+ eBroadcomProprietary = VK_DRIVER_ID_BROADCOM_PROPRIETARY,
+ eIntelOpenSourceMesa = VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR
+ };
+ using DriverIdKHR = DriverId;
+
+ VULKAN_HPP_INLINE std::string to_string( DriverId value )
+ {
+ switch ( value )
+ {
+ case DriverId::eAmdProprietary : return "AmdProprietary";
+ case DriverId::eAmdOpenSource : return "AmdOpenSource";
+ case DriverId::eMesaRadv : return "MesaRadv";
+ case DriverId::eNvidiaProprietary : return "NvidiaProprietary";
+ case DriverId::eIntelProprietaryWindows : return "IntelProprietaryWindows";
+ case DriverId::eIntelOpenSourceMESA : return "IntelOpenSourceMESA";
+ case DriverId::eImaginationProprietary : return "ImaginationProprietary";
+ case DriverId::eQualcommProprietary : return "QualcommProprietary";
+ case DriverId::eArmProprietary : return "ArmProprietary";
+ case DriverId::eGoogleSwiftshader : return "GoogleSwiftshader";
+ case DriverId::eGgpProprietary : return "GgpProprietary";
+ case DriverId::eBroadcomProprietary : return "BroadcomProprietary";
+ default: return "invalid";
+ }
+ }
+
+ enum class DynamicState
+ {
+ eViewport = VK_DYNAMIC_STATE_VIEWPORT,
+ eScissor = VK_DYNAMIC_STATE_SCISSOR,
+ eLineWidth = VK_DYNAMIC_STATE_LINE_WIDTH,
+ eDepthBias = VK_DYNAMIC_STATE_DEPTH_BIAS,
+ eBlendConstants = VK_DYNAMIC_STATE_BLEND_CONSTANTS,
+ eDepthBounds = VK_DYNAMIC_STATE_DEPTH_BOUNDS,
+ eStencilCompareMask = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
+ eStencilWriteMask = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
+ eStencilReference = VK_DYNAMIC_STATE_STENCIL_REFERENCE,
+ eViewportWScalingNV = VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV,
+ eDiscardRectangleEXT = VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT,
+ eSampleLocationsEXT = VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
+ eViewportShadingRatePaletteNV = VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV,
+ eViewportCoarseSampleOrderNV = VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV,
+ eExclusiveScissorNV = VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV,
+ eLineStippleEXT = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( DynamicState value )
+ {
+ switch ( value )
+ {
+ case DynamicState::eViewport : return "Viewport";
+ case DynamicState::eScissor : return "Scissor";
+ case DynamicState::eLineWidth : return "LineWidth";
+ case DynamicState::eDepthBias : return "DepthBias";
+ case DynamicState::eBlendConstants : return "BlendConstants";
+ case DynamicState::eDepthBounds : return "DepthBounds";
+ case DynamicState::eStencilCompareMask : return "StencilCompareMask";
+ case DynamicState::eStencilWriteMask : return "StencilWriteMask";
+ case DynamicState::eStencilReference : return "StencilReference";
+ case DynamicState::eViewportWScalingNV : return "ViewportWScalingNV";
+ case DynamicState::eDiscardRectangleEXT : return "DiscardRectangleEXT";
+ case DynamicState::eSampleLocationsEXT : return "SampleLocationsEXT";
+ case DynamicState::eViewportShadingRatePaletteNV : return "ViewportShadingRatePaletteNV";
+ case DynamicState::eViewportCoarseSampleOrderNV : return "ViewportCoarseSampleOrderNV";
+ case DynamicState::eExclusiveScissorNV : return "ExclusiveScissorNV";
+ case DynamicState::eLineStippleEXT : return "LineStippleEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class ExternalFenceFeatureFlagBits
+ {
+ eExportable = VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT,
+ eImportable = VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT
+ };
+ using ExternalFenceFeatureFlagBitsKHR = ExternalFenceFeatureFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalFenceFeatureFlagBits value )
+ {
+ switch ( value )
+ {
+ case ExternalFenceFeatureFlagBits::eExportable : return "Exportable";
+ case ExternalFenceFeatureFlagBits::eImportable : return "Importable";
+ default: return "invalid";
+ }
+ }
+
+ enum class ExternalFenceHandleTypeFlagBits
+ {
+ eOpaqueFd = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT,
+ eOpaqueWin32 = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT,
+ eOpaqueWin32Kmt = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+ eSyncFd = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
+ };
+ using ExternalFenceHandleTypeFlagBitsKHR = ExternalFenceHandleTypeFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalFenceHandleTypeFlagBits value )
+ {
+ switch ( value )
+ {
+ case ExternalFenceHandleTypeFlagBits::eOpaqueFd : return "OpaqueFd";
+ case ExternalFenceHandleTypeFlagBits::eOpaqueWin32 : return "OpaqueWin32";
+ case ExternalFenceHandleTypeFlagBits::eOpaqueWin32Kmt : return "OpaqueWin32Kmt";
+ case ExternalFenceHandleTypeFlagBits::eSyncFd : return "SyncFd";
+ default: return "invalid";
+ }
+ }
+
+ enum class ExternalMemoryFeatureFlagBits
+ {
+ eDedicatedOnly = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT,
+ eExportable = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT,
+ eImportable = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT
+ };
+ using ExternalMemoryFeatureFlagBitsKHR = ExternalMemoryFeatureFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalMemoryFeatureFlagBits value )
+ {
+ switch ( value )
+ {
+ case ExternalMemoryFeatureFlagBits::eDedicatedOnly : return "DedicatedOnly";
+ case ExternalMemoryFeatureFlagBits::eExportable : return "Exportable";
+ case ExternalMemoryFeatureFlagBits::eImportable : return "Importable";
+ default: return "invalid";
+ }
+ }
+
+ enum class ExternalMemoryFeatureFlagBitsNV
+ {
+ eDedicatedOnly = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV,
+ eExportable = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV,
+ eImportable = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalMemoryFeatureFlagBitsNV value )
+ {
+ switch ( value )
+ {
+ case ExternalMemoryFeatureFlagBitsNV::eDedicatedOnly : return "DedicatedOnly";
+ case ExternalMemoryFeatureFlagBitsNV::eExportable : return "Exportable";
+ case ExternalMemoryFeatureFlagBitsNV::eImportable : return "Importable";
+ default: return "invalid";
+ }
+ }
+
+ enum class ExternalMemoryHandleTypeFlagBits
+ {
+ eOpaqueFd = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
+ eOpaqueWin32 = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,
+ eOpaqueWin32Kmt = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+ eD3D11Texture = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT,
+ eD3D11TextureKmt = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT,
+ eD3D12Heap = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT,
+ eD3D12Resource = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,
+ eDmaBufEXT = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ eAndroidHardwareBufferANDROID = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
+ eHostAllocationEXT = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
+ eHostMappedForeignMemoryEXT = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT
+ };
+ using ExternalMemoryHandleTypeFlagBitsKHR = ExternalMemoryHandleTypeFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalMemoryHandleTypeFlagBits value )
+ {
+ switch ( value )
+ {
+ case ExternalMemoryHandleTypeFlagBits::eOpaqueFd : return "OpaqueFd";
+ case ExternalMemoryHandleTypeFlagBits::eOpaqueWin32 : return "OpaqueWin32";
+ case ExternalMemoryHandleTypeFlagBits::eOpaqueWin32Kmt : return "OpaqueWin32Kmt";
+ case ExternalMemoryHandleTypeFlagBits::eD3D11Texture : return "D3D11Texture";
+ case ExternalMemoryHandleTypeFlagBits::eD3D11TextureKmt : return "D3D11TextureKmt";
+ case ExternalMemoryHandleTypeFlagBits::eD3D12Heap : return "D3D12Heap";
+ case ExternalMemoryHandleTypeFlagBits::eD3D12Resource : return "D3D12Resource";
+ case ExternalMemoryHandleTypeFlagBits::eDmaBufEXT : return "DmaBufEXT";
+ case ExternalMemoryHandleTypeFlagBits::eAndroidHardwareBufferANDROID : return "AndroidHardwareBufferANDROID";
+ case ExternalMemoryHandleTypeFlagBits::eHostAllocationEXT : return "HostAllocationEXT";
+ case ExternalMemoryHandleTypeFlagBits::eHostMappedForeignMemoryEXT : return "HostMappedForeignMemoryEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class ExternalMemoryHandleTypeFlagBitsNV
+ {
+ eOpaqueWin32 = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV,
+ eOpaqueWin32Kmt = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV,
+ eD3D11Image = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV,
+ eD3D11ImageKmt = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalMemoryHandleTypeFlagBitsNV value )
+ {
+ switch ( value )
+ {
+ case ExternalMemoryHandleTypeFlagBitsNV::eOpaqueWin32 : return "OpaqueWin32";
+ case ExternalMemoryHandleTypeFlagBitsNV::eOpaqueWin32Kmt : return "OpaqueWin32Kmt";
+ case ExternalMemoryHandleTypeFlagBitsNV::eD3D11Image : return "D3D11Image";
+ case ExternalMemoryHandleTypeFlagBitsNV::eD3D11ImageKmt : return "D3D11ImageKmt";
+ default: return "invalid";
+ }
+ }
+
+ enum class ExternalSemaphoreFeatureFlagBits
+ {
+ eExportable = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT,
+ eImportable = VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT
+ };
+ using ExternalSemaphoreFeatureFlagBitsKHR = ExternalSemaphoreFeatureFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalSemaphoreFeatureFlagBits value )
+ {
+ switch ( value )
+ {
+ case ExternalSemaphoreFeatureFlagBits::eExportable : return "Exportable";
+ case ExternalSemaphoreFeatureFlagBits::eImportable : return "Importable";
+ default: return "invalid";
+ }
+ }
+
+ enum class ExternalSemaphoreHandleTypeFlagBits
+ {
+ eOpaqueFd = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
+ eOpaqueWin32 = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT,
+ eOpaqueWin32Kmt = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+ eD3D12Fence = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT,
+ eSyncFd = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
+ };
+ using ExternalSemaphoreHandleTypeFlagBitsKHR = ExternalSemaphoreHandleTypeFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalSemaphoreHandleTypeFlagBits value )
+ {
+ switch ( value )
+ {
+ case ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd : return "OpaqueFd";
+ case ExternalSemaphoreHandleTypeFlagBits::eOpaqueWin32 : return "OpaqueWin32";
+ case ExternalSemaphoreHandleTypeFlagBits::eOpaqueWin32Kmt : return "OpaqueWin32Kmt";
+ case ExternalSemaphoreHandleTypeFlagBits::eD3D12Fence : return "D3D12Fence";
+ case ExternalSemaphoreHandleTypeFlagBits::eSyncFd : return "SyncFd";
+ default: return "invalid";
+ }
+ }
+
+ enum class FenceCreateFlagBits
+ {
+ eSignaled = VK_FENCE_CREATE_SIGNALED_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( FenceCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case FenceCreateFlagBits::eSignaled : return "Signaled";
+ default: return "invalid";
+ }
+ }
+
+ enum class FenceImportFlagBits
+ {
+ eTemporary = VK_FENCE_IMPORT_TEMPORARY_BIT
+ };
+ using FenceImportFlagBitsKHR = FenceImportFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( FenceImportFlagBits value )
+ {
+ switch ( value )
+ {
+ case FenceImportFlagBits::eTemporary : return "Temporary";
+ default: return "invalid";
+ }
+ }
+
+ enum class Filter
+ {
+ eNearest = VK_FILTER_NEAREST,
+ eLinear = VK_FILTER_LINEAR,
+ eCubicIMG = VK_FILTER_CUBIC_IMG,
+ eCubicEXT = VK_FILTER_CUBIC_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( Filter value )
+ {
+ switch ( value )
+ {
+ case Filter::eNearest : return "Nearest";
+ case Filter::eLinear : return "Linear";
+ case Filter::eCubicIMG : return "CubicIMG";
+ default: return "invalid";
+ }
+ }
+
+ enum class Format
+ {
+ eUndefined = VK_FORMAT_UNDEFINED,
+ eR4G4UnormPack8 = VK_FORMAT_R4G4_UNORM_PACK8,
+ eR4G4B4A4UnormPack16 = VK_FORMAT_R4G4B4A4_UNORM_PACK16,
+ eB4G4R4A4UnormPack16 = VK_FORMAT_B4G4R4A4_UNORM_PACK16,
+ eR5G6B5UnormPack16 = VK_FORMAT_R5G6B5_UNORM_PACK16,
+ eB5G6R5UnormPack16 = VK_FORMAT_B5G6R5_UNORM_PACK16,
+ eR5G5B5A1UnormPack16 = VK_FORMAT_R5G5B5A1_UNORM_PACK16,
+ eB5G5R5A1UnormPack16 = VK_FORMAT_B5G5R5A1_UNORM_PACK16,
+ eA1R5G5B5UnormPack16 = VK_FORMAT_A1R5G5B5_UNORM_PACK16,
+ eR8Unorm = VK_FORMAT_R8_UNORM,
+ eR8Snorm = VK_FORMAT_R8_SNORM,
+ eR8Uscaled = VK_FORMAT_R8_USCALED,
+ eR8Sscaled = VK_FORMAT_R8_SSCALED,
+ eR8Uint = VK_FORMAT_R8_UINT,
+ eR8Sint = VK_FORMAT_R8_SINT,
+ eR8Srgb = VK_FORMAT_R8_SRGB,
+ eR8G8Unorm = VK_FORMAT_R8G8_UNORM,
+ eR8G8Snorm = VK_FORMAT_R8G8_SNORM,
+ eR8G8Uscaled = VK_FORMAT_R8G8_USCALED,
+ eR8G8Sscaled = VK_FORMAT_R8G8_SSCALED,
+ eR8G8Uint = VK_FORMAT_R8G8_UINT,
+ eR8G8Sint = VK_FORMAT_R8G8_SINT,
+ eR8G8Srgb = VK_FORMAT_R8G8_SRGB,
+ eR8G8B8Unorm = VK_FORMAT_R8G8B8_UNORM,
+ eR8G8B8Snorm = VK_FORMAT_R8G8B8_SNORM,
+ eR8G8B8Uscaled = VK_FORMAT_R8G8B8_USCALED,
+ eR8G8B8Sscaled = VK_FORMAT_R8G8B8_SSCALED,
+ eR8G8B8Uint = VK_FORMAT_R8G8B8_UINT,
+ eR8G8B8Sint = VK_FORMAT_R8G8B8_SINT,
+ eR8G8B8Srgb = VK_FORMAT_R8G8B8_SRGB,
+ eB8G8R8Unorm = VK_FORMAT_B8G8R8_UNORM,
+ eB8G8R8Snorm = VK_FORMAT_B8G8R8_SNORM,
+ eB8G8R8Uscaled = VK_FORMAT_B8G8R8_USCALED,
+ eB8G8R8Sscaled = VK_FORMAT_B8G8R8_SSCALED,
+ eB8G8R8Uint = VK_FORMAT_B8G8R8_UINT,
+ eB8G8R8Sint = VK_FORMAT_B8G8R8_SINT,
+ eB8G8R8Srgb = VK_FORMAT_B8G8R8_SRGB,
+ eR8G8B8A8Unorm = VK_FORMAT_R8G8B8A8_UNORM,
+ eR8G8B8A8Snorm = VK_FORMAT_R8G8B8A8_SNORM,
+ eR8G8B8A8Uscaled = VK_FORMAT_R8G8B8A8_USCALED,
+ eR8G8B8A8Sscaled = VK_FORMAT_R8G8B8A8_SSCALED,
+ eR8G8B8A8Uint = VK_FORMAT_R8G8B8A8_UINT,
+ eR8G8B8A8Sint = VK_FORMAT_R8G8B8A8_SINT,
+ eR8G8B8A8Srgb = VK_FORMAT_R8G8B8A8_SRGB,
+ eB8G8R8A8Unorm = VK_FORMAT_B8G8R8A8_UNORM,
+ eB8G8R8A8Snorm = VK_FORMAT_B8G8R8A8_SNORM,
+ eB8G8R8A8Uscaled = VK_FORMAT_B8G8R8A8_USCALED,
+ eB8G8R8A8Sscaled = VK_FORMAT_B8G8R8A8_SSCALED,
+ eB8G8R8A8Uint = VK_FORMAT_B8G8R8A8_UINT,
+ eB8G8R8A8Sint = VK_FORMAT_B8G8R8A8_SINT,
+ eB8G8R8A8Srgb = VK_FORMAT_B8G8R8A8_SRGB,
+ eA8B8G8R8UnormPack32 = VK_FORMAT_A8B8G8R8_UNORM_PACK32,
+ eA8B8G8R8SnormPack32 = VK_FORMAT_A8B8G8R8_SNORM_PACK32,
+ eA8B8G8R8UscaledPack32 = VK_FORMAT_A8B8G8R8_USCALED_PACK32,
+ eA8B8G8R8SscaledPack32 = VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
+ eA8B8G8R8UintPack32 = VK_FORMAT_A8B8G8R8_UINT_PACK32,
+ eA8B8G8R8SintPack32 = VK_FORMAT_A8B8G8R8_SINT_PACK32,
+ eA8B8G8R8SrgbPack32 = VK_FORMAT_A8B8G8R8_SRGB_PACK32,
+ eA2R10G10B10UnormPack32 = VK_FORMAT_A2R10G10B10_UNORM_PACK32,
+ eA2R10G10B10SnormPack32 = VK_FORMAT_A2R10G10B10_SNORM_PACK32,
+ eA2R10G10B10UscaledPack32 = VK_FORMAT_A2R10G10B10_USCALED_PACK32,
+ eA2R10G10B10SscaledPack32 = VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
+ eA2R10G10B10UintPack32 = VK_FORMAT_A2R10G10B10_UINT_PACK32,
+ eA2R10G10B10SintPack32 = VK_FORMAT_A2R10G10B10_SINT_PACK32,
+ eA2B10G10R10UnormPack32 = VK_FORMAT_A2B10G10R10_UNORM_PACK32,
+ eA2B10G10R10SnormPack32 = VK_FORMAT_A2B10G10R10_SNORM_PACK32,
+ eA2B10G10R10UscaledPack32 = VK_FORMAT_A2B10G10R10_USCALED_PACK32,
+ eA2B10G10R10SscaledPack32 = VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
+ eA2B10G10R10UintPack32 = VK_FORMAT_A2B10G10R10_UINT_PACK32,
+ eA2B10G10R10SintPack32 = VK_FORMAT_A2B10G10R10_SINT_PACK32,
+ eR16Unorm = VK_FORMAT_R16_UNORM,
+ eR16Snorm = VK_FORMAT_R16_SNORM,
+ eR16Uscaled = VK_FORMAT_R16_USCALED,
+ eR16Sscaled = VK_FORMAT_R16_SSCALED,
+ eR16Uint = VK_FORMAT_R16_UINT,
+ eR16Sint = VK_FORMAT_R16_SINT,
+ eR16Sfloat = VK_FORMAT_R16_SFLOAT,
+ eR16G16Unorm = VK_FORMAT_R16G16_UNORM,
+ eR16G16Snorm = VK_FORMAT_R16G16_SNORM,
+ eR16G16Uscaled = VK_FORMAT_R16G16_USCALED,
+ eR16G16Sscaled = VK_FORMAT_R16G16_SSCALED,
+ eR16G16Uint = VK_FORMAT_R16G16_UINT,
+ eR16G16Sint = VK_FORMAT_R16G16_SINT,
+ eR16G16Sfloat = VK_FORMAT_R16G16_SFLOAT,
+ eR16G16B16Unorm = VK_FORMAT_R16G16B16_UNORM,
+ eR16G16B16Snorm = VK_FORMAT_R16G16B16_SNORM,
+ eR16G16B16Uscaled = VK_FORMAT_R16G16B16_USCALED,
+ eR16G16B16Sscaled = VK_FORMAT_R16G16B16_SSCALED,
+ eR16G16B16Uint = VK_FORMAT_R16G16B16_UINT,
+ eR16G16B16Sint = VK_FORMAT_R16G16B16_SINT,
+ eR16G16B16Sfloat = VK_FORMAT_R16G16B16_SFLOAT,
+ eR16G16B16A16Unorm = VK_FORMAT_R16G16B16A16_UNORM,
+ eR16G16B16A16Snorm = VK_FORMAT_R16G16B16A16_SNORM,
+ eR16G16B16A16Uscaled = VK_FORMAT_R16G16B16A16_USCALED,
+ eR16G16B16A16Sscaled = VK_FORMAT_R16G16B16A16_SSCALED,
+ eR16G16B16A16Uint = VK_FORMAT_R16G16B16A16_UINT,
+ eR16G16B16A16Sint = VK_FORMAT_R16G16B16A16_SINT,
+ eR16G16B16A16Sfloat = VK_FORMAT_R16G16B16A16_SFLOAT,
+ eR32Uint = VK_FORMAT_R32_UINT,
+ eR32Sint = VK_FORMAT_R32_SINT,
+ eR32Sfloat = VK_FORMAT_R32_SFLOAT,
+ eR32G32Uint = VK_FORMAT_R32G32_UINT,
+ eR32G32Sint = VK_FORMAT_R32G32_SINT,
+ eR32G32Sfloat = VK_FORMAT_R32G32_SFLOAT,
+ eR32G32B32Uint = VK_FORMAT_R32G32B32_UINT,
+ eR32G32B32Sint = VK_FORMAT_R32G32B32_SINT,
+ eR32G32B32Sfloat = VK_FORMAT_R32G32B32_SFLOAT,
+ eR32G32B32A32Uint = VK_FORMAT_R32G32B32A32_UINT,
+ eR32G32B32A32Sint = VK_FORMAT_R32G32B32A32_SINT,
+ eR32G32B32A32Sfloat = VK_FORMAT_R32G32B32A32_SFLOAT,
+ eR64Uint = VK_FORMAT_R64_UINT,
+ eR64Sint = VK_FORMAT_R64_SINT,
+ eR64Sfloat = VK_FORMAT_R64_SFLOAT,
+ eR64G64Uint = VK_FORMAT_R64G64_UINT,
+ eR64G64Sint = VK_FORMAT_R64G64_SINT,
+ eR64G64Sfloat = VK_FORMAT_R64G64_SFLOAT,
+ eR64G64B64Uint = VK_FORMAT_R64G64B64_UINT,
+ eR64G64B64Sint = VK_FORMAT_R64G64B64_SINT,
+ eR64G64B64Sfloat = VK_FORMAT_R64G64B64_SFLOAT,
+ eR64G64B64A64Uint = VK_FORMAT_R64G64B64A64_UINT,
+ eR64G64B64A64Sint = VK_FORMAT_R64G64B64A64_SINT,
+ eR64G64B64A64Sfloat = VK_FORMAT_R64G64B64A64_SFLOAT,
+ eB10G11R11UfloatPack32 = VK_FORMAT_B10G11R11_UFLOAT_PACK32,
+ eE5B9G9R9UfloatPack32 = VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
+ eD16Unorm = VK_FORMAT_D16_UNORM,
+ eX8D24UnormPack32 = VK_FORMAT_X8_D24_UNORM_PACK32,
+ eD32Sfloat = VK_FORMAT_D32_SFLOAT,
+ eS8Uint = VK_FORMAT_S8_UINT,
+ eD16UnormS8Uint = VK_FORMAT_D16_UNORM_S8_UINT,
+ eD24UnormS8Uint = VK_FORMAT_D24_UNORM_S8_UINT,
+ eD32SfloatS8Uint = VK_FORMAT_D32_SFLOAT_S8_UINT,
+ eBc1RgbUnormBlock = VK_FORMAT_BC1_RGB_UNORM_BLOCK,
+ eBc1RgbSrgbBlock = VK_FORMAT_BC1_RGB_SRGB_BLOCK,
+ eBc1RgbaUnormBlock = VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
+ eBc1RgbaSrgbBlock = VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
+ eBc2UnormBlock = VK_FORMAT_BC2_UNORM_BLOCK,
+ eBc2SrgbBlock = VK_FORMAT_BC2_SRGB_BLOCK,
+ eBc3UnormBlock = VK_FORMAT_BC3_UNORM_BLOCK,
+ eBc3SrgbBlock = VK_FORMAT_BC3_SRGB_BLOCK,
+ eBc4UnormBlock = VK_FORMAT_BC4_UNORM_BLOCK,
+ eBc4SnormBlock = VK_FORMAT_BC4_SNORM_BLOCK,
+ eBc5UnormBlock = VK_FORMAT_BC5_UNORM_BLOCK,
+ eBc5SnormBlock = VK_FORMAT_BC5_SNORM_BLOCK,
+ eBc6HUfloatBlock = VK_FORMAT_BC6H_UFLOAT_BLOCK,
+ eBc6HSfloatBlock = VK_FORMAT_BC6H_SFLOAT_BLOCK,
+ eBc7UnormBlock = VK_FORMAT_BC7_UNORM_BLOCK,
+ eBc7SrgbBlock = VK_FORMAT_BC7_SRGB_BLOCK,
+ eEtc2R8G8B8UnormBlock = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
+ eEtc2R8G8B8SrgbBlock = VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
+ eEtc2R8G8B8A1UnormBlock = VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
+ eEtc2R8G8B8A1SrgbBlock = VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
+ eEtc2R8G8B8A8UnormBlock = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
+ eEtc2R8G8B8A8SrgbBlock = VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
+ eEacR11UnormBlock = VK_FORMAT_EAC_R11_UNORM_BLOCK,
+ eEacR11SnormBlock = VK_FORMAT_EAC_R11_SNORM_BLOCK,
+ eEacR11G11UnormBlock = VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
+ eEacR11G11SnormBlock = VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
+ eAstc4x4UnormBlock = VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
+ eAstc4x4SrgbBlock = VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
+ eAstc5x4UnormBlock = VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
+ eAstc5x4SrgbBlock = VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
+ eAstc5x5UnormBlock = VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
+ eAstc5x5SrgbBlock = VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
+ eAstc6x5UnormBlock = VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
+ eAstc6x5SrgbBlock = VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
+ eAstc6x6UnormBlock = VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
+ eAstc6x6SrgbBlock = VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
+ eAstc8x5UnormBlock = VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
+ eAstc8x5SrgbBlock = VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
+ eAstc8x6UnormBlock = VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
+ eAstc8x6SrgbBlock = VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
+ eAstc8x8UnormBlock = VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
+ eAstc8x8SrgbBlock = VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
+ eAstc10x5UnormBlock = VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
+ eAstc10x5SrgbBlock = VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
+ eAstc10x6UnormBlock = VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
+ eAstc10x6SrgbBlock = VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
+ eAstc10x8UnormBlock = VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
+ eAstc10x8SrgbBlock = VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
+ eAstc10x10UnormBlock = VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
+ eAstc10x10SrgbBlock = VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
+ eAstc12x10UnormBlock = VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
+ eAstc12x10SrgbBlock = VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
+ eAstc12x12UnormBlock = VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
+ eAstc12x12SrgbBlock = VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
+ eG8B8G8R8422Unorm = VK_FORMAT_G8B8G8R8_422_UNORM,
+ eB8G8R8G8422Unorm = VK_FORMAT_B8G8R8G8_422_UNORM,
+ eG8B8R83Plane420Unorm = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
+ eG8B8R82Plane420Unorm = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
+ eG8B8R83Plane422Unorm = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
+ eG8B8R82Plane422Unorm = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
+ eG8B8R83Plane444Unorm = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
+ eR10X6UnormPack16 = VK_FORMAT_R10X6_UNORM_PACK16,
+ eR10X6G10X6Unorm2Pack16 = VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
+ eR10X6G10X6B10X6A10X6Unorm4Pack16 = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
+ eG10X6B10X6G10X6R10X6422Unorm4Pack16 = VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
+ eB10X6G10X6R10X6G10X6422Unorm4Pack16 = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
+ eG10X6B10X6R10X63Plane420Unorm3Pack16 = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
+ eG10X6B10X6R10X62Plane420Unorm3Pack16 = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
+ eG10X6B10X6R10X63Plane422Unorm3Pack16 = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
+ eG10X6B10X6R10X62Plane422Unorm3Pack16 = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
+ eG10X6B10X6R10X63Plane444Unorm3Pack16 = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
+ eR12X4UnormPack16 = VK_FORMAT_R12X4_UNORM_PACK16,
+ eR12X4G12X4Unorm2Pack16 = VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
+ eR12X4G12X4B12X4A12X4Unorm4Pack16 = VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
+ eG12X4B12X4G12X4R12X4422Unorm4Pack16 = VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
+ eB12X4G12X4R12X4G12X4422Unorm4Pack16 = VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
+ eG12X4B12X4R12X43Plane420Unorm3Pack16 = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
+ eG12X4B12X4R12X42Plane420Unorm3Pack16 = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
+ eG12X4B12X4R12X43Plane422Unorm3Pack16 = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
+ eG12X4B12X4R12X42Plane422Unorm3Pack16 = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
+ eG12X4B12X4R12X43Plane444Unorm3Pack16 = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
+ eG16B16G16R16422Unorm = VK_FORMAT_G16B16G16R16_422_UNORM,
+ eB16G16R16G16422Unorm = VK_FORMAT_B16G16R16G16_422_UNORM,
+ eG16B16R163Plane420Unorm = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
+ eG16B16R162Plane420Unorm = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
+ eG16B16R163Plane422Unorm = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
+ eG16B16R162Plane422Unorm = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
+ eG16B16R163Plane444Unorm = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
+ ePvrtc12BppUnormBlockIMG = VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
+ ePvrtc14BppUnormBlockIMG = VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,
+ ePvrtc22BppUnormBlockIMG = VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,
+ ePvrtc24BppUnormBlockIMG = VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,
+ ePvrtc12BppSrgbBlockIMG = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
+ ePvrtc14BppSrgbBlockIMG = VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,
+ ePvrtc22BppSrgbBlockIMG = VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,
+ ePvrtc24BppSrgbBlockIMG = VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG,
+ eAstc4x4SfloatBlockEXT = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT,
+ eAstc5x4SfloatBlockEXT = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT,
+ eAstc5x5SfloatBlockEXT = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT,
+ eAstc6x5SfloatBlockEXT = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT,
+ eAstc6x6SfloatBlockEXT = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT,
+ eAstc8x5SfloatBlockEXT = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT,
+ eAstc8x6SfloatBlockEXT = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT,
+ eAstc8x8SfloatBlockEXT = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT,
+ eAstc10x5SfloatBlockEXT = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT,
+ eAstc10x6SfloatBlockEXT = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT,
+ eAstc10x8SfloatBlockEXT = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT,
+ eAstc10x10SfloatBlockEXT = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT,
+ eAstc12x10SfloatBlockEXT = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT,
+ eAstc12x12SfloatBlockEXT = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT,
+ eG8B8G8R8422UnormKHR = VK_FORMAT_G8B8G8R8_422_UNORM_KHR,
+ eB8G8R8G8422UnormKHR = VK_FORMAT_B8G8R8G8_422_UNORM_KHR,
+ eG8B8R83Plane420UnormKHR = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR,
+ eG8B8R82Plane420UnormKHR = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR,
+ eG8B8R83Plane422UnormKHR = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR,
+ eG8B8R82Plane422UnormKHR = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR,
+ eG8B8R83Plane444UnormKHR = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR,
+ eR10X6UnormPack16KHR = VK_FORMAT_R10X6_UNORM_PACK16_KHR,
+ eR10X6G10X6Unorm2Pack16KHR = VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR,
+ eR10X6G10X6B10X6A10X6Unorm4Pack16KHR = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR,
+ eG10X6B10X6G10X6R10X6422Unorm4Pack16KHR = VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR,
+ eB10X6G10X6R10X6G10X6422Unorm4Pack16KHR = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR,
+ eG10X6B10X6R10X63Plane420Unorm3Pack16KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR,
+ eG10X6B10X6R10X62Plane420Unorm3Pack16KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR,
+ eG10X6B10X6R10X63Plane422Unorm3Pack16KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR,
+ eG10X6B10X6R10X62Plane422Unorm3Pack16KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR,
+ eG10X6B10X6R10X63Plane444Unorm3Pack16KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR,
+ eR12X4UnormPack16KHR = VK_FORMAT_R12X4_UNORM_PACK16_KHR,
+ eR12X4G12X4Unorm2Pack16KHR = VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR,
+ eR12X4G12X4B12X4A12X4Unorm4Pack16KHR = VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR,
+ eG12X4B12X4G12X4R12X4422Unorm4Pack16KHR = VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR,
+ eB12X4G12X4R12X4G12X4422Unorm4Pack16KHR = VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR,
+ eG12X4B12X4R12X43Plane420Unorm3Pack16KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR,
+ eG12X4B12X4R12X42Plane420Unorm3Pack16KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR,
+ eG12X4B12X4R12X43Plane422Unorm3Pack16KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR,
+ eG12X4B12X4R12X42Plane422Unorm3Pack16KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR,
+ eG12X4B12X4R12X43Plane444Unorm3Pack16KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR,
+ eG16B16G16R16422UnormKHR = VK_FORMAT_G16B16G16R16_422_UNORM_KHR,
+ eB16G16R16G16422UnormKHR = VK_FORMAT_B16G16R16G16_422_UNORM_KHR,
+ eG16B16R163Plane420UnormKHR = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR,
+ eG16B16R162Plane420UnormKHR = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR,
+ eG16B16R163Plane422UnormKHR = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR,
+ eG16B16R162Plane422UnormKHR = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR,
+ eG16B16R163Plane444UnormKHR = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( Format value )
+ {
+ switch ( value )
+ {
+ case Format::eUndefined : return "Undefined";
+ case Format::eR4G4UnormPack8 : return "R4G4UnormPack8";
+ case Format::eR4G4B4A4UnormPack16 : return "R4G4B4A4UnormPack16";
+ case Format::eB4G4R4A4UnormPack16 : return "B4G4R4A4UnormPack16";
+ case Format::eR5G6B5UnormPack16 : return "R5G6B5UnormPack16";
+ case Format::eB5G6R5UnormPack16 : return "B5G6R5UnormPack16";
+ case Format::eR5G5B5A1UnormPack16 : return "R5G5B5A1UnormPack16";
+ case Format::eB5G5R5A1UnormPack16 : return "B5G5R5A1UnormPack16";
+ case Format::eA1R5G5B5UnormPack16 : return "A1R5G5B5UnormPack16";
+ case Format::eR8Unorm : return "R8Unorm";
+ case Format::eR8Snorm : return "R8Snorm";
+ case Format::eR8Uscaled : return "R8Uscaled";
+ case Format::eR8Sscaled : return "R8Sscaled";
+ case Format::eR8Uint : return "R8Uint";
+ case Format::eR8Sint : return "R8Sint";
+ case Format::eR8Srgb : return "R8Srgb";
+ case Format::eR8G8Unorm : return "R8G8Unorm";
+ case Format::eR8G8Snorm : return "R8G8Snorm";
+ case Format::eR8G8Uscaled : return "R8G8Uscaled";
+ case Format::eR8G8Sscaled : return "R8G8Sscaled";
+ case Format::eR8G8Uint : return "R8G8Uint";
+ case Format::eR8G8Sint : return "R8G8Sint";
+ case Format::eR8G8Srgb : return "R8G8Srgb";
+ case Format::eR8G8B8Unorm : return "R8G8B8Unorm";
+ case Format::eR8G8B8Snorm : return "R8G8B8Snorm";
+ case Format::eR8G8B8Uscaled : return "R8G8B8Uscaled";
+ case Format::eR8G8B8Sscaled : return "R8G8B8Sscaled";
+ case Format::eR8G8B8Uint : return "R8G8B8Uint";
+ case Format::eR8G8B8Sint : return "R8G8B8Sint";
+ case Format::eR8G8B8Srgb : return "R8G8B8Srgb";
+ case Format::eB8G8R8Unorm : return "B8G8R8Unorm";
+ case Format::eB8G8R8Snorm : return "B8G8R8Snorm";
+ case Format::eB8G8R8Uscaled : return "B8G8R8Uscaled";
+ case Format::eB8G8R8Sscaled : return "B8G8R8Sscaled";
+ case Format::eB8G8R8Uint : return "B8G8R8Uint";
+ case Format::eB8G8R8Sint : return "B8G8R8Sint";
+ case Format::eB8G8R8Srgb : return "B8G8R8Srgb";
+ case Format::eR8G8B8A8Unorm : return "R8G8B8A8Unorm";
+ case Format::eR8G8B8A8Snorm : return "R8G8B8A8Snorm";
+ case Format::eR8G8B8A8Uscaled : return "R8G8B8A8Uscaled";
+ case Format::eR8G8B8A8Sscaled : return "R8G8B8A8Sscaled";
+ case Format::eR8G8B8A8Uint : return "R8G8B8A8Uint";
+ case Format::eR8G8B8A8Sint : return "R8G8B8A8Sint";
+ case Format::eR8G8B8A8Srgb : return "R8G8B8A8Srgb";
+ case Format::eB8G8R8A8Unorm : return "B8G8R8A8Unorm";
+ case Format::eB8G8R8A8Snorm : return "B8G8R8A8Snorm";
+ case Format::eB8G8R8A8Uscaled : return "B8G8R8A8Uscaled";
+ case Format::eB8G8R8A8Sscaled : return "B8G8R8A8Sscaled";
+ case Format::eB8G8R8A8Uint : return "B8G8R8A8Uint";
+ case Format::eB8G8R8A8Sint : return "B8G8R8A8Sint";
+ case Format::eB8G8R8A8Srgb : return "B8G8R8A8Srgb";
+ case Format::eA8B8G8R8UnormPack32 : return "A8B8G8R8UnormPack32";
+ case Format::eA8B8G8R8SnormPack32 : return "A8B8G8R8SnormPack32";
+ case Format::eA8B8G8R8UscaledPack32 : return "A8B8G8R8UscaledPack32";
+ case Format::eA8B8G8R8SscaledPack32 : return "A8B8G8R8SscaledPack32";
+ case Format::eA8B8G8R8UintPack32 : return "A8B8G8R8UintPack32";
+ case Format::eA8B8G8R8SintPack32 : return "A8B8G8R8SintPack32";
+ case Format::eA8B8G8R8SrgbPack32 : return "A8B8G8R8SrgbPack32";
+ case Format::eA2R10G10B10UnormPack32 : return "A2R10G10B10UnormPack32";
+ case Format::eA2R10G10B10SnormPack32 : return "A2R10G10B10SnormPack32";
+ case Format::eA2R10G10B10UscaledPack32 : return "A2R10G10B10UscaledPack32";
+ case Format::eA2R10G10B10SscaledPack32 : return "A2R10G10B10SscaledPack32";
+ case Format::eA2R10G10B10UintPack32 : return "A2R10G10B10UintPack32";
+ case Format::eA2R10G10B10SintPack32 : return "A2R10G10B10SintPack32";
+ case Format::eA2B10G10R10UnormPack32 : return "A2B10G10R10UnormPack32";
+ case Format::eA2B10G10R10SnormPack32 : return "A2B10G10R10SnormPack32";
+ case Format::eA2B10G10R10UscaledPack32 : return "A2B10G10R10UscaledPack32";
+ case Format::eA2B10G10R10SscaledPack32 : return "A2B10G10R10SscaledPack32";
+ case Format::eA2B10G10R10UintPack32 : return "A2B10G10R10UintPack32";
+ case Format::eA2B10G10R10SintPack32 : return "A2B10G10R10SintPack32";
+ case Format::eR16Unorm : return "R16Unorm";
+ case Format::eR16Snorm : return "R16Snorm";
+ case Format::eR16Uscaled : return "R16Uscaled";
+ case Format::eR16Sscaled : return "R16Sscaled";
+ case Format::eR16Uint : return "R16Uint";
+ case Format::eR16Sint : return "R16Sint";
+ case Format::eR16Sfloat : return "R16Sfloat";
+ case Format::eR16G16Unorm : return "R16G16Unorm";
+ case Format::eR16G16Snorm : return "R16G16Snorm";
+ case Format::eR16G16Uscaled : return "R16G16Uscaled";
+ case Format::eR16G16Sscaled : return "R16G16Sscaled";
+ case Format::eR16G16Uint : return "R16G16Uint";
+ case Format::eR16G16Sint : return "R16G16Sint";
+ case Format::eR16G16Sfloat : return "R16G16Sfloat";
+ case Format::eR16G16B16Unorm : return "R16G16B16Unorm";
+ case Format::eR16G16B16Snorm : return "R16G16B16Snorm";
+ case Format::eR16G16B16Uscaled : return "R16G16B16Uscaled";
+ case Format::eR16G16B16Sscaled : return "R16G16B16Sscaled";
+ case Format::eR16G16B16Uint : return "R16G16B16Uint";
+ case Format::eR16G16B16Sint : return "R16G16B16Sint";
+ case Format::eR16G16B16Sfloat : return "R16G16B16Sfloat";
+ case Format::eR16G16B16A16Unorm : return "R16G16B16A16Unorm";
+ case Format::eR16G16B16A16Snorm : return "R16G16B16A16Snorm";
+ case Format::eR16G16B16A16Uscaled : return "R16G16B16A16Uscaled";
+ case Format::eR16G16B16A16Sscaled : return "R16G16B16A16Sscaled";
+ case Format::eR16G16B16A16Uint : return "R16G16B16A16Uint";
+ case Format::eR16G16B16A16Sint : return "R16G16B16A16Sint";
+ case Format::eR16G16B16A16Sfloat : return "R16G16B16A16Sfloat";
+ case Format::eR32Uint : return "R32Uint";
+ case Format::eR32Sint : return "R32Sint";
+ case Format::eR32Sfloat : return "R32Sfloat";
+ case Format::eR32G32Uint : return "R32G32Uint";
+ case Format::eR32G32Sint : return "R32G32Sint";
+ case Format::eR32G32Sfloat : return "R32G32Sfloat";
+ case Format::eR32G32B32Uint : return "R32G32B32Uint";
+ case Format::eR32G32B32Sint : return "R32G32B32Sint";
+ case Format::eR32G32B32Sfloat : return "R32G32B32Sfloat";
+ case Format::eR32G32B32A32Uint : return "R32G32B32A32Uint";
+ case Format::eR32G32B32A32Sint : return "R32G32B32A32Sint";
+ case Format::eR32G32B32A32Sfloat : return "R32G32B32A32Sfloat";
+ case Format::eR64Uint : return "R64Uint";
+ case Format::eR64Sint : return "R64Sint";
+ case Format::eR64Sfloat : return "R64Sfloat";
+ case Format::eR64G64Uint : return "R64G64Uint";
+ case Format::eR64G64Sint : return "R64G64Sint";
+ case Format::eR64G64Sfloat : return "R64G64Sfloat";
+ case Format::eR64G64B64Uint : return "R64G64B64Uint";
+ case Format::eR64G64B64Sint : return "R64G64B64Sint";
+ case Format::eR64G64B64Sfloat : return "R64G64B64Sfloat";
+ case Format::eR64G64B64A64Uint : return "R64G64B64A64Uint";
+ case Format::eR64G64B64A64Sint : return "R64G64B64A64Sint";
+ case Format::eR64G64B64A64Sfloat : return "R64G64B64A64Sfloat";
+ case Format::eB10G11R11UfloatPack32 : return "B10G11R11UfloatPack32";
+ case Format::eE5B9G9R9UfloatPack32 : return "E5B9G9R9UfloatPack32";
+ case Format::eD16Unorm : return "D16Unorm";
+ case Format::eX8D24UnormPack32 : return "X8D24UnormPack32";
+ case Format::eD32Sfloat : return "D32Sfloat";
+ case Format::eS8Uint : return "S8Uint";
+ case Format::eD16UnormS8Uint : return "D16UnormS8Uint";
+ case Format::eD24UnormS8Uint : return "D24UnormS8Uint";
+ case Format::eD32SfloatS8Uint : return "D32SfloatS8Uint";
+ case Format::eBc1RgbUnormBlock : return "Bc1RgbUnormBlock";
+ case Format::eBc1RgbSrgbBlock : return "Bc1RgbSrgbBlock";
+ case Format::eBc1RgbaUnormBlock : return "Bc1RgbaUnormBlock";
+ case Format::eBc1RgbaSrgbBlock : return "Bc1RgbaSrgbBlock";
+ case Format::eBc2UnormBlock : return "Bc2UnormBlock";
+ case Format::eBc2SrgbBlock : return "Bc2SrgbBlock";
+ case Format::eBc3UnormBlock : return "Bc3UnormBlock";
+ case Format::eBc3SrgbBlock : return "Bc3SrgbBlock";
+ case Format::eBc4UnormBlock : return "Bc4UnormBlock";
+ case Format::eBc4SnormBlock : return "Bc4SnormBlock";
+ case Format::eBc5UnormBlock : return "Bc5UnormBlock";
+ case Format::eBc5SnormBlock : return "Bc5SnormBlock";
+ case Format::eBc6HUfloatBlock : return "Bc6HUfloatBlock";
+ case Format::eBc6HSfloatBlock : return "Bc6HSfloatBlock";
+ case Format::eBc7UnormBlock : return "Bc7UnormBlock";
+ case Format::eBc7SrgbBlock : return "Bc7SrgbBlock";
+ case Format::eEtc2R8G8B8UnormBlock : return "Etc2R8G8B8UnormBlock";
+ case Format::eEtc2R8G8B8SrgbBlock : return "Etc2R8G8B8SrgbBlock";
+ case Format::eEtc2R8G8B8A1UnormBlock : return "Etc2R8G8B8A1UnormBlock";
+ case Format::eEtc2R8G8B8A1SrgbBlock : return "Etc2R8G8B8A1SrgbBlock";
+ case Format::eEtc2R8G8B8A8UnormBlock : return "Etc2R8G8B8A8UnormBlock";
+ case Format::eEtc2R8G8B8A8SrgbBlock : return "Etc2R8G8B8A8SrgbBlock";
+ case Format::eEacR11UnormBlock : return "EacR11UnormBlock";
+ case Format::eEacR11SnormBlock : return "EacR11SnormBlock";
+ case Format::eEacR11G11UnormBlock : return "EacR11G11UnormBlock";
+ case Format::eEacR11G11SnormBlock : return "EacR11G11SnormBlock";
+ case Format::eAstc4x4UnormBlock : return "Astc4x4UnormBlock";
+ case Format::eAstc4x4SrgbBlock : return "Astc4x4SrgbBlock";
+ case Format::eAstc5x4UnormBlock : return "Astc5x4UnormBlock";
+ case Format::eAstc5x4SrgbBlock : return "Astc5x4SrgbBlock";
+ case Format::eAstc5x5UnormBlock : return "Astc5x5UnormBlock";
+ case Format::eAstc5x5SrgbBlock : return "Astc5x5SrgbBlock";
+ case Format::eAstc6x5UnormBlock : return "Astc6x5UnormBlock";
+ case Format::eAstc6x5SrgbBlock : return "Astc6x5SrgbBlock";
+ case Format::eAstc6x6UnormBlock : return "Astc6x6UnormBlock";
+ case Format::eAstc6x6SrgbBlock : return "Astc6x6SrgbBlock";
+ case Format::eAstc8x5UnormBlock : return "Astc8x5UnormBlock";
+ case Format::eAstc8x5SrgbBlock : return "Astc8x5SrgbBlock";
+ case Format::eAstc8x6UnormBlock : return "Astc8x6UnormBlock";
+ case Format::eAstc8x6SrgbBlock : return "Astc8x6SrgbBlock";
+ case Format::eAstc8x8UnormBlock : return "Astc8x8UnormBlock";
+ case Format::eAstc8x8SrgbBlock : return "Astc8x8SrgbBlock";
+ case Format::eAstc10x5UnormBlock : return "Astc10x5UnormBlock";
+ case Format::eAstc10x5SrgbBlock : return "Astc10x5SrgbBlock";
+ case Format::eAstc10x6UnormBlock : return "Astc10x6UnormBlock";
+ case Format::eAstc10x6SrgbBlock : return "Astc10x6SrgbBlock";
+ case Format::eAstc10x8UnormBlock : return "Astc10x8UnormBlock";
+ case Format::eAstc10x8SrgbBlock : return "Astc10x8SrgbBlock";
+ case Format::eAstc10x10UnormBlock : return "Astc10x10UnormBlock";
+ case Format::eAstc10x10SrgbBlock : return "Astc10x10SrgbBlock";
+ case Format::eAstc12x10UnormBlock : return "Astc12x10UnormBlock";
+ case Format::eAstc12x10SrgbBlock : return "Astc12x10SrgbBlock";
+ case Format::eAstc12x12UnormBlock : return "Astc12x12UnormBlock";
+ case Format::eAstc12x12SrgbBlock : return "Astc12x12SrgbBlock";
+ case Format::eG8B8G8R8422Unorm : return "G8B8G8R8422Unorm";
+ case Format::eB8G8R8G8422Unorm : return "B8G8R8G8422Unorm";
+ case Format::eG8B8R83Plane420Unorm : return "G8B8R83Plane420Unorm";
+ case Format::eG8B8R82Plane420Unorm : return "G8B8R82Plane420Unorm";
+ case Format::eG8B8R83Plane422Unorm : return "G8B8R83Plane422Unorm";
+ case Format::eG8B8R82Plane422Unorm : return "G8B8R82Plane422Unorm";
+ case Format::eG8B8R83Plane444Unorm : return "G8B8R83Plane444Unorm";
+ case Format::eR10X6UnormPack16 : return "R10X6UnormPack16";
+ case Format::eR10X6G10X6Unorm2Pack16 : return "R10X6G10X6Unorm2Pack16";
+ case Format::eR10X6G10X6B10X6A10X6Unorm4Pack16 : return "R10X6G10X6B10X6A10X6Unorm4Pack16";
+ case Format::eG10X6B10X6G10X6R10X6422Unorm4Pack16 : return "G10X6B10X6G10X6R10X6422Unorm4Pack16";
+ case Format::eB10X6G10X6R10X6G10X6422Unorm4Pack16 : return "B10X6G10X6R10X6G10X6422Unorm4Pack16";
+ case Format::eG10X6B10X6R10X63Plane420Unorm3Pack16 : return "G10X6B10X6R10X63Plane420Unorm3Pack16";
+ case Format::eG10X6B10X6R10X62Plane420Unorm3Pack16 : return "G10X6B10X6R10X62Plane420Unorm3Pack16";
+ case Format::eG10X6B10X6R10X63Plane422Unorm3Pack16 : return "G10X6B10X6R10X63Plane422Unorm3Pack16";
+ case Format::eG10X6B10X6R10X62Plane422Unorm3Pack16 : return "G10X6B10X6R10X62Plane422Unorm3Pack16";
+ case Format::eG10X6B10X6R10X63Plane444Unorm3Pack16 : return "G10X6B10X6R10X63Plane444Unorm3Pack16";
+ case Format::eR12X4UnormPack16 : return "R12X4UnormPack16";
+ case Format::eR12X4G12X4Unorm2Pack16 : return "R12X4G12X4Unorm2Pack16";
+ case Format::eR12X4G12X4B12X4A12X4Unorm4Pack16 : return "R12X4G12X4B12X4A12X4Unorm4Pack16";
+ case Format::eG12X4B12X4G12X4R12X4422Unorm4Pack16 : return "G12X4B12X4G12X4R12X4422Unorm4Pack16";
+ case Format::eB12X4G12X4R12X4G12X4422Unorm4Pack16 : return "B12X4G12X4R12X4G12X4422Unorm4Pack16";
+ case Format::eG12X4B12X4R12X43Plane420Unorm3Pack16 : return "G12X4B12X4R12X43Plane420Unorm3Pack16";
+ case Format::eG12X4B12X4R12X42Plane420Unorm3Pack16 : return "G12X4B12X4R12X42Plane420Unorm3Pack16";
+ case Format::eG12X4B12X4R12X43Plane422Unorm3Pack16 : return "G12X4B12X4R12X43Plane422Unorm3Pack16";
+ case Format::eG12X4B12X4R12X42Plane422Unorm3Pack16 : return "G12X4B12X4R12X42Plane422Unorm3Pack16";
+ case Format::eG12X4B12X4R12X43Plane444Unorm3Pack16 : return "G12X4B12X4R12X43Plane444Unorm3Pack16";
+ case Format::eG16B16G16R16422Unorm : return "G16B16G16R16422Unorm";
+ case Format::eB16G16R16G16422Unorm : return "B16G16R16G16422Unorm";
+ case Format::eG16B16R163Plane420Unorm : return "G16B16R163Plane420Unorm";
+ case Format::eG16B16R162Plane420Unorm : return "G16B16R162Plane420Unorm";
+ case Format::eG16B16R163Plane422Unorm : return "G16B16R163Plane422Unorm";
+ case Format::eG16B16R162Plane422Unorm : return "G16B16R162Plane422Unorm";
+ case Format::eG16B16R163Plane444Unorm : return "G16B16R163Plane444Unorm";
+ case Format::ePvrtc12BppUnormBlockIMG : return "Pvrtc12BppUnormBlockIMG";
+ case Format::ePvrtc14BppUnormBlockIMG : return "Pvrtc14BppUnormBlockIMG";
+ case Format::ePvrtc22BppUnormBlockIMG : return "Pvrtc22BppUnormBlockIMG";
+ case Format::ePvrtc24BppUnormBlockIMG : return "Pvrtc24BppUnormBlockIMG";
+ case Format::ePvrtc12BppSrgbBlockIMG : return "Pvrtc12BppSrgbBlockIMG";
+ case Format::ePvrtc14BppSrgbBlockIMG : return "Pvrtc14BppSrgbBlockIMG";
+ case Format::ePvrtc22BppSrgbBlockIMG : return "Pvrtc22BppSrgbBlockIMG";
+ case Format::ePvrtc24BppSrgbBlockIMG : return "Pvrtc24BppSrgbBlockIMG";
+ case Format::eAstc4x4SfloatBlockEXT : return "Astc4x4SfloatBlockEXT";
+ case Format::eAstc5x4SfloatBlockEXT : return "Astc5x4SfloatBlockEXT";
+ case Format::eAstc5x5SfloatBlockEXT : return "Astc5x5SfloatBlockEXT";
+ case Format::eAstc6x5SfloatBlockEXT : return "Astc6x5SfloatBlockEXT";
+ case Format::eAstc6x6SfloatBlockEXT : return "Astc6x6SfloatBlockEXT";
+ case Format::eAstc8x5SfloatBlockEXT : return "Astc8x5SfloatBlockEXT";
+ case Format::eAstc8x6SfloatBlockEXT : return "Astc8x6SfloatBlockEXT";
+ case Format::eAstc8x8SfloatBlockEXT : return "Astc8x8SfloatBlockEXT";
+ case Format::eAstc10x5SfloatBlockEXT : return "Astc10x5SfloatBlockEXT";
+ case Format::eAstc10x6SfloatBlockEXT : return "Astc10x6SfloatBlockEXT";
+ case Format::eAstc10x8SfloatBlockEXT : return "Astc10x8SfloatBlockEXT";
+ case Format::eAstc10x10SfloatBlockEXT : return "Astc10x10SfloatBlockEXT";
+ case Format::eAstc12x10SfloatBlockEXT : return "Astc12x10SfloatBlockEXT";
+ case Format::eAstc12x12SfloatBlockEXT : return "Astc12x12SfloatBlockEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class FormatFeatureFlagBits
+ {
+ eSampledImage = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
+ eStorageImage = VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT,
+ eStorageImageAtomic = VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT,
+ eUniformTexelBuffer = VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT,
+ eStorageTexelBuffer = VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT,
+ eStorageTexelBufferAtomic = VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT,
+ eVertexBuffer = VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT,
+ eColorAttachment = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT,
+ eColorAttachmentBlend = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT,
+ eDepthStencilAttachment = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT,
+ eBlitSrc = VK_FORMAT_FEATURE_BLIT_SRC_BIT,
+ eBlitDst = VK_FORMAT_FEATURE_BLIT_DST_BIT,
+ eSampledImageFilterLinear = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT,
+ eTransferSrc = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT,
+ eTransferDst = VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
+ eMidpointChromaSamples = VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT,
+ eSampledImageYcbcrConversionLinearFilter = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT,
+ eSampledImageYcbcrConversionSeparateReconstructionFilter = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT,
+ eSampledImageYcbcrConversionChromaReconstructionExplicit = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT,
+ eSampledImageYcbcrConversionChromaReconstructionExplicitForceable = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT,
+ eDisjoint = VK_FORMAT_FEATURE_DISJOINT_BIT,
+ eCositedChromaSamples = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT,
+ eSampledImageFilterMinmax = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT,
+ eSampledImageFilterCubicIMG = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG,
+ eFragmentDensityMapEXT = VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT,
+ eTransferSrcKHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR,
+ eTransferDstKHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR,
+ eSampledImageFilterMinmaxEXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT,
+ eMidpointChromaSamplesKHR = VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR,
+ eSampledImageYcbcrConversionLinearFilterKHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR,
+ eSampledImageYcbcrConversionSeparateReconstructionFilterKHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR,
+ eSampledImageYcbcrConversionChromaReconstructionExplicitKHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR,
+ eSampledImageYcbcrConversionChromaReconstructionExplicitForceableKHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR,
+ eDisjointKHR = VK_FORMAT_FEATURE_DISJOINT_BIT_KHR,
+ eCositedChromaSamplesKHR = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR,
+ eSampledImageFilterCubicEXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( FormatFeatureFlagBits value )
+ {
+ switch ( value )
+ {
+ case FormatFeatureFlagBits::eSampledImage : return "SampledImage";
+ case FormatFeatureFlagBits::eStorageImage : return "StorageImage";
+ case FormatFeatureFlagBits::eStorageImageAtomic : return "StorageImageAtomic";
+ case FormatFeatureFlagBits::eUniformTexelBuffer : return "UniformTexelBuffer";
+ case FormatFeatureFlagBits::eStorageTexelBuffer : return "StorageTexelBuffer";
+ case FormatFeatureFlagBits::eStorageTexelBufferAtomic : return "StorageTexelBufferAtomic";
+ case FormatFeatureFlagBits::eVertexBuffer : return "VertexBuffer";
+ case FormatFeatureFlagBits::eColorAttachment : return "ColorAttachment";
+ case FormatFeatureFlagBits::eColorAttachmentBlend : return "ColorAttachmentBlend";
+ case FormatFeatureFlagBits::eDepthStencilAttachment : return "DepthStencilAttachment";
+ case FormatFeatureFlagBits::eBlitSrc : return "BlitSrc";
+ case FormatFeatureFlagBits::eBlitDst : return "BlitDst";
+ case FormatFeatureFlagBits::eSampledImageFilterLinear : return "SampledImageFilterLinear";
+ case FormatFeatureFlagBits::eTransferSrc : return "TransferSrc";
+ case FormatFeatureFlagBits::eTransferDst : return "TransferDst";
+ case FormatFeatureFlagBits::eMidpointChromaSamples : return "MidpointChromaSamples";
+ case FormatFeatureFlagBits::eSampledImageYcbcrConversionLinearFilter : return "SampledImageYcbcrConversionLinearFilter";
+ case FormatFeatureFlagBits::eSampledImageYcbcrConversionSeparateReconstructionFilter : return "SampledImageYcbcrConversionSeparateReconstructionFilter";
+ case FormatFeatureFlagBits::eSampledImageYcbcrConversionChromaReconstructionExplicit : return "SampledImageYcbcrConversionChromaReconstructionExplicit";
+ case FormatFeatureFlagBits::eSampledImageYcbcrConversionChromaReconstructionExplicitForceable : return "SampledImageYcbcrConversionChromaReconstructionExplicitForceable";
+ case FormatFeatureFlagBits::eDisjoint : return "Disjoint";
+ case FormatFeatureFlagBits::eCositedChromaSamples : return "CositedChromaSamples";
+ case FormatFeatureFlagBits::eSampledImageFilterMinmax : return "SampledImageFilterMinmax";
+ case FormatFeatureFlagBits::eSampledImageFilterCubicIMG : return "SampledImageFilterCubicIMG";
+ case FormatFeatureFlagBits::eFragmentDensityMapEXT : return "FragmentDensityMapEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class FramebufferCreateFlagBits
+ {
+ eImageless = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT,
+ eImagelessKHR = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( FramebufferCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case FramebufferCreateFlagBits::eImageless : return "Imageless";
+ default: return "invalid";
+ }
+ }
+
+ enum class FrontFace
+ {
+ eCounterClockwise = VK_FRONT_FACE_COUNTER_CLOCKWISE,
+ eClockwise = VK_FRONT_FACE_CLOCKWISE
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( FrontFace value )
+ {
+ switch ( value )
+ {
+ case FrontFace::eCounterClockwise : return "CounterClockwise";
+ case FrontFace::eClockwise : return "Clockwise";
+ default: return "invalid";
+ }
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ enum class FullScreenExclusiveEXT
+ {
+ eDefault = VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT,
+ eAllowed = VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT,
+ eDisallowed = VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT,
+ eApplicationControlled = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( FullScreenExclusiveEXT value )
+ {
+ switch ( value )
+ {
+ case FullScreenExclusiveEXT::eDefault : return "Default";
+ case FullScreenExclusiveEXT::eAllowed : return "Allowed";
+ case FullScreenExclusiveEXT::eDisallowed : return "Disallowed";
+ case FullScreenExclusiveEXT::eApplicationControlled : return "ApplicationControlled";
+ default: return "invalid";
+ }
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ enum class GeometryFlagBitsNV
+ {
+ eOpaque = VK_GEOMETRY_OPAQUE_BIT_NV,
+ eNoDuplicateAnyHitInvocation = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( GeometryFlagBitsNV value )
+ {
+ switch ( value )
+ {
+ case GeometryFlagBitsNV::eOpaque : return "Opaque";
+ case GeometryFlagBitsNV::eNoDuplicateAnyHitInvocation : return "NoDuplicateAnyHitInvocation";
+ default: return "invalid";
+ }
+ }
+
+ enum class GeometryInstanceFlagBitsNV
+ {
+ eTriangleCullDisable = VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV,
+ eTriangleFrontCounterclockwise = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV,
+ eForceOpaque = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV,
+ eForceNoOpaque = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( GeometryInstanceFlagBitsNV value )
+ {
+ switch ( value )
+ {
+ case GeometryInstanceFlagBitsNV::eTriangleCullDisable : return "TriangleCullDisable";
+ case GeometryInstanceFlagBitsNV::eTriangleFrontCounterclockwise : return "TriangleFrontCounterclockwise";
+ case GeometryInstanceFlagBitsNV::eForceOpaque : return "ForceOpaque";
+ case GeometryInstanceFlagBitsNV::eForceNoOpaque : return "ForceNoOpaque";
+ default: return "invalid";
+ }
+ }
+
+ enum class GeometryTypeNV
+ {
+ eTriangles = VK_GEOMETRY_TYPE_TRIANGLES_NV,
+ eAabbs = VK_GEOMETRY_TYPE_AABBS_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( GeometryTypeNV value )
+ {
+ switch ( value )
+ {
+ case GeometryTypeNV::eTriangles : return "Triangles";
+ case GeometryTypeNV::eAabbs : return "Aabbs";
+ default: return "invalid";
+ }
+ }
+
+ enum class ImageAspectFlagBits
+ {
+ eColor = VK_IMAGE_ASPECT_COLOR_BIT,
+ eDepth = VK_IMAGE_ASPECT_DEPTH_BIT,
+ eStencil = VK_IMAGE_ASPECT_STENCIL_BIT,
+ eMetadata = VK_IMAGE_ASPECT_METADATA_BIT,
+ ePlane0 = VK_IMAGE_ASPECT_PLANE_0_BIT,
+ ePlane1 = VK_IMAGE_ASPECT_PLANE_1_BIT,
+ ePlane2 = VK_IMAGE_ASPECT_PLANE_2_BIT,
+ eMemoryPlane0EXT = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT,
+ eMemoryPlane1EXT = VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT,
+ eMemoryPlane2EXT = VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT,
+ eMemoryPlane3EXT = VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT,
+ ePlane0KHR = VK_IMAGE_ASPECT_PLANE_0_BIT_KHR,
+ ePlane1KHR = VK_IMAGE_ASPECT_PLANE_1_BIT_KHR,
+ ePlane2KHR = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ImageAspectFlagBits value )
+ {
+ switch ( value )
+ {
+ case ImageAspectFlagBits::eColor : return "Color";
+ case ImageAspectFlagBits::eDepth : return "Depth";
+ case ImageAspectFlagBits::eStencil : return "Stencil";
+ case ImageAspectFlagBits::eMetadata : return "Metadata";
+ case ImageAspectFlagBits::ePlane0 : return "Plane0";
+ case ImageAspectFlagBits::ePlane1 : return "Plane1";
+ case ImageAspectFlagBits::ePlane2 : return "Plane2";
+ case ImageAspectFlagBits::eMemoryPlane0EXT : return "MemoryPlane0EXT";
+ case ImageAspectFlagBits::eMemoryPlane1EXT : return "MemoryPlane1EXT";
+ case ImageAspectFlagBits::eMemoryPlane2EXT : return "MemoryPlane2EXT";
+ case ImageAspectFlagBits::eMemoryPlane3EXT : return "MemoryPlane3EXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class ImageCreateFlagBits
+ {
+ eSparseBinding = VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
+ eSparseResidency = VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
+ eSparseAliased = VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
+ eMutableFormat = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
+ eCubeCompatible = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
+ eAlias = VK_IMAGE_CREATE_ALIAS_BIT,
+ eSplitInstanceBindRegions = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT,
+ e2DArrayCompatible = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT,
+ eBlockTexelViewCompatible = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT,
+ eExtendedUsage = VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
+ eProtected = VK_IMAGE_CREATE_PROTECTED_BIT,
+ eDisjoint = VK_IMAGE_CREATE_DISJOINT_BIT,
+ eCornerSampledNV = VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV,
+ eSampleLocationsCompatibleDepthEXT = VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT,
+ eSubsampledEXT = VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT,
+ eSplitInstanceBindRegionsKHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR,
+ e2DArrayCompatibleKHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR,
+ eBlockTexelViewCompatibleKHR = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR,
+ eExtendedUsageKHR = VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR,
+ eDisjointKHR = VK_IMAGE_CREATE_DISJOINT_BIT_KHR,
+ eAliasKHR = VK_IMAGE_CREATE_ALIAS_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ImageCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case ImageCreateFlagBits::eSparseBinding : return "SparseBinding";
+ case ImageCreateFlagBits::eSparseResidency : return "SparseResidency";
+ case ImageCreateFlagBits::eSparseAliased : return "SparseAliased";
+ case ImageCreateFlagBits::eMutableFormat : return "MutableFormat";
+ case ImageCreateFlagBits::eCubeCompatible : return "CubeCompatible";
+ case ImageCreateFlagBits::eAlias : return "Alias";
+ case ImageCreateFlagBits::eSplitInstanceBindRegions : return "SplitInstanceBindRegions";
+ case ImageCreateFlagBits::e2DArrayCompatible : return "2DArrayCompatible";
+ case ImageCreateFlagBits::eBlockTexelViewCompatible : return "BlockTexelViewCompatible";
+ case ImageCreateFlagBits::eExtendedUsage : return "ExtendedUsage";
+ case ImageCreateFlagBits::eProtected : return "Protected";
+ case ImageCreateFlagBits::eDisjoint : return "Disjoint";
+ case ImageCreateFlagBits::eCornerSampledNV : return "CornerSampledNV";
+ case ImageCreateFlagBits::eSampleLocationsCompatibleDepthEXT : return "SampleLocationsCompatibleDepthEXT";
+ case ImageCreateFlagBits::eSubsampledEXT : return "SubsampledEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class ImageLayout
+ {
+ eUndefined = VK_IMAGE_LAYOUT_UNDEFINED,
+ eGeneral = VK_IMAGE_LAYOUT_GENERAL,
+ eColorAttachmentOptimal = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ eDepthStencilAttachmentOptimal = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ eDepthStencilReadOnlyOptimal = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
+ eShaderReadOnlyOptimal = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ eTransferSrcOptimal = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ eTransferDstOptimal = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ ePreinitialized = VK_IMAGE_LAYOUT_PREINITIALIZED,
+ eDepthReadOnlyStencilAttachmentOptimal = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
+ eDepthAttachmentStencilReadOnlyOptimal = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
+ eDepthAttachmentOptimal = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
+ eDepthReadOnlyOptimal = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,
+ eStencilAttachmentOptimal = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL,
+ eStencilReadOnlyOptimal = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL,
+ ePresentSrcKHR = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ eSharedPresentKHR = VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
+ eShadingRateOptimalNV = VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV,
+ eFragmentDensityMapOptimalEXT = VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT,
+ eDepthReadOnlyStencilAttachmentOptimalKHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR,
+ eDepthAttachmentStencilReadOnlyOptimalKHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR,
+ eDepthAttachmentOptimalKHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR,
+ eDepthReadOnlyOptimalKHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR,
+ eStencilAttachmentOptimalKHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR,
+ eStencilReadOnlyOptimalKHR = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ImageLayout value )
+ {
+ switch ( value )
+ {
+ case ImageLayout::eUndefined : return "Undefined";
+ case ImageLayout::eGeneral : return "General";
+ case ImageLayout::eColorAttachmentOptimal : return "ColorAttachmentOptimal";
+ case ImageLayout::eDepthStencilAttachmentOptimal : return "DepthStencilAttachmentOptimal";
+ case ImageLayout::eDepthStencilReadOnlyOptimal : return "DepthStencilReadOnlyOptimal";
+ case ImageLayout::eShaderReadOnlyOptimal : return "ShaderReadOnlyOptimal";
+ case ImageLayout::eTransferSrcOptimal : return "TransferSrcOptimal";
+ case ImageLayout::eTransferDstOptimal : return "TransferDstOptimal";
+ case ImageLayout::ePreinitialized : return "Preinitialized";
+ case ImageLayout::eDepthReadOnlyStencilAttachmentOptimal : return "DepthReadOnlyStencilAttachmentOptimal";
+ case ImageLayout::eDepthAttachmentStencilReadOnlyOptimal : return "DepthAttachmentStencilReadOnlyOptimal";
+ case ImageLayout::eDepthAttachmentOptimal : return "DepthAttachmentOptimal";
+ case ImageLayout::eDepthReadOnlyOptimal : return "DepthReadOnlyOptimal";
+ case ImageLayout::eStencilAttachmentOptimal : return "StencilAttachmentOptimal";
+ case ImageLayout::eStencilReadOnlyOptimal : return "StencilReadOnlyOptimal";
+ case ImageLayout::ePresentSrcKHR : return "PresentSrcKHR";
+ case ImageLayout::eSharedPresentKHR : return "SharedPresentKHR";
+ case ImageLayout::eShadingRateOptimalNV : return "ShadingRateOptimalNV";
+ case ImageLayout::eFragmentDensityMapOptimalEXT : return "FragmentDensityMapOptimalEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class ImageTiling
+ {
+ eOptimal = VK_IMAGE_TILING_OPTIMAL,
+ eLinear = VK_IMAGE_TILING_LINEAR,
+ eDrmFormatModifierEXT = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ImageTiling value )
+ {
+ switch ( value )
+ {
+ case ImageTiling::eOptimal : return "Optimal";
+ case ImageTiling::eLinear : return "Linear";
+ case ImageTiling::eDrmFormatModifierEXT : return "DrmFormatModifierEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class ImageType
+ {
+ e1D = VK_IMAGE_TYPE_1D,
+ e2D = VK_IMAGE_TYPE_2D,
+ e3D = VK_IMAGE_TYPE_3D
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ImageType value )
+ {
+ switch ( value )
+ {
+ case ImageType::e1D : return "1D";
+ case ImageType::e2D : return "2D";
+ case ImageType::e3D : return "3D";
+ default: return "invalid";
+ }
+ }
+
+ enum class ImageUsageFlagBits
+ {
+ eTransferSrc = VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+ eTransferDst = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+ eSampled = VK_IMAGE_USAGE_SAMPLED_BIT,
+ eStorage = VK_IMAGE_USAGE_STORAGE_BIT,
+ eColorAttachment = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ eDepthStencilAttachment = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+ eTransientAttachment = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
+ eInputAttachment = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
+ eShadingRateImageNV = VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV,
+ eFragmentDensityMapEXT = VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ImageUsageFlagBits value )
+ {
+ switch ( value )
+ {
+ case ImageUsageFlagBits::eTransferSrc : return "TransferSrc";
+ case ImageUsageFlagBits::eTransferDst : return "TransferDst";
+ case ImageUsageFlagBits::eSampled : return "Sampled";
+ case ImageUsageFlagBits::eStorage : return "Storage";
+ case ImageUsageFlagBits::eColorAttachment : return "ColorAttachment";
+ case ImageUsageFlagBits::eDepthStencilAttachment : return "DepthStencilAttachment";
+ case ImageUsageFlagBits::eTransientAttachment : return "TransientAttachment";
+ case ImageUsageFlagBits::eInputAttachment : return "InputAttachment";
+ case ImageUsageFlagBits::eShadingRateImageNV : return "ShadingRateImageNV";
+ case ImageUsageFlagBits::eFragmentDensityMapEXT : return "FragmentDensityMapEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class ImageViewCreateFlagBits
+ {
+ eFragmentDensityMapDynamicEXT = VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ImageViewCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case ImageViewCreateFlagBits::eFragmentDensityMapDynamicEXT : return "FragmentDensityMapDynamicEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class ImageViewType
+ {
+ e1D = VK_IMAGE_VIEW_TYPE_1D,
+ e2D = VK_IMAGE_VIEW_TYPE_2D,
+ e3D = VK_IMAGE_VIEW_TYPE_3D,
+ eCube = VK_IMAGE_VIEW_TYPE_CUBE,
+ e1DArray = VK_IMAGE_VIEW_TYPE_1D_ARRAY,
+ e2DArray = VK_IMAGE_VIEW_TYPE_2D_ARRAY,
+ eCubeArray = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ImageViewType value )
+ {
+ switch ( value )
+ {
+ case ImageViewType::e1D : return "1D";
+ case ImageViewType::e2D : return "2D";
+ case ImageViewType::e3D : return "3D";
+ case ImageViewType::eCube : return "Cube";
+ case ImageViewType::e1DArray : return "1DArray";
+ case ImageViewType::e2DArray : return "2DArray";
+ case ImageViewType::eCubeArray : return "CubeArray";
+ default: return "invalid";
+ }
+ }
+
+ enum class IndexType
+ {
+ eUint16 = VK_INDEX_TYPE_UINT16,
+ eUint32 = VK_INDEX_TYPE_UINT32,
+ eNoneNV = VK_INDEX_TYPE_NONE_NV,
+ eUint8EXT = VK_INDEX_TYPE_UINT8_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( IndexType value )
+ {
+ switch ( value )
+ {
+ case IndexType::eUint16 : return "Uint16";
+ case IndexType::eUint32 : return "Uint32";
+ case IndexType::eNoneNV : return "NoneNV";
+ case IndexType::eUint8EXT : return "Uint8EXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class IndirectCommandsLayoutUsageFlagBitsNVX
+ {
+ eUnorderedSequences = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX,
+ eSparseSequences = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX,
+ eEmptyExecutions = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX,
+ eIndexedSequences = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( IndirectCommandsLayoutUsageFlagBitsNVX value )
+ {
+ switch ( value )
+ {
+ case IndirectCommandsLayoutUsageFlagBitsNVX::eUnorderedSequences : return "UnorderedSequences";
+ case IndirectCommandsLayoutUsageFlagBitsNVX::eSparseSequences : return "SparseSequences";
+ case IndirectCommandsLayoutUsageFlagBitsNVX::eEmptyExecutions : return "EmptyExecutions";
+ case IndirectCommandsLayoutUsageFlagBitsNVX::eIndexedSequences : return "IndexedSequences";
+ default: return "invalid";
+ }
+ }
+
+ enum class IndirectCommandsTokenTypeNVX
+ {
+ ePipeline = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX,
+ eDescriptorSet = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX,
+ eIndexBuffer = VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX,
+ eVertexBuffer = VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX,
+ ePushConstant = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX,
+ eDrawIndexed = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX,
+ eDraw = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX,
+ eDispatch = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( IndirectCommandsTokenTypeNVX value )
+ {
+ switch ( value )
+ {
+ case IndirectCommandsTokenTypeNVX::ePipeline : return "Pipeline";
+ case IndirectCommandsTokenTypeNVX::eDescriptorSet : return "DescriptorSet";
+ case IndirectCommandsTokenTypeNVX::eIndexBuffer : return "IndexBuffer";
+ case IndirectCommandsTokenTypeNVX::eVertexBuffer : return "VertexBuffer";
+ case IndirectCommandsTokenTypeNVX::ePushConstant : return "PushConstant";
+ case IndirectCommandsTokenTypeNVX::eDrawIndexed : return "DrawIndexed";
+ case IndirectCommandsTokenTypeNVX::eDraw : return "Draw";
+ case IndirectCommandsTokenTypeNVX::eDispatch : return "Dispatch";
+ default: return "invalid";
+ }
+ }
+
+ enum class InstanceCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( InstanceCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class InternalAllocationType
+ {
+ eExecutable = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( InternalAllocationType value )
+ {
+ switch ( value )
+ {
+ case InternalAllocationType::eExecutable : return "Executable";
+ default: return "invalid";
+ }
+ }
+
+ enum class LineRasterizationModeEXT
+ {
+ eDefault = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT,
+ eRectangular = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT,
+ eBresenham = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT,
+ eRectangularSmooth = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( LineRasterizationModeEXT value )
+ {
+ switch ( value )
+ {
+ case LineRasterizationModeEXT::eDefault : return "Default";
+ case LineRasterizationModeEXT::eRectangular : return "Rectangular";
+ case LineRasterizationModeEXT::eBresenham : return "Bresenham";
+ case LineRasterizationModeEXT::eRectangularSmooth : return "RectangularSmooth";
+ default: return "invalid";
+ }
+ }
+
+ enum class LogicOp
+ {
+ eClear = VK_LOGIC_OP_CLEAR,
+ eAnd = VK_LOGIC_OP_AND,
+ eAndReverse = VK_LOGIC_OP_AND_REVERSE,
+ eCopy = VK_LOGIC_OP_COPY,
+ eAndInverted = VK_LOGIC_OP_AND_INVERTED,
+ eNoOp = VK_LOGIC_OP_NO_OP,
+ eXor = VK_LOGIC_OP_XOR,
+ eOr = VK_LOGIC_OP_OR,
+ eNor = VK_LOGIC_OP_NOR,
+ eEquivalent = VK_LOGIC_OP_EQUIVALENT,
+ eInvert = VK_LOGIC_OP_INVERT,
+ eOrReverse = VK_LOGIC_OP_OR_REVERSE,
+ eCopyInverted = VK_LOGIC_OP_COPY_INVERTED,
+ eOrInverted = VK_LOGIC_OP_OR_INVERTED,
+ eNand = VK_LOGIC_OP_NAND,
+ eSet = VK_LOGIC_OP_SET
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( LogicOp value )
+ {
+ switch ( value )
+ {
+ case LogicOp::eClear : return "Clear";
+ case LogicOp::eAnd : return "And";
+ case LogicOp::eAndReverse : return "AndReverse";
+ case LogicOp::eCopy : return "Copy";
+ case LogicOp::eAndInverted : return "AndInverted";
+ case LogicOp::eNoOp : return "NoOp";
+ case LogicOp::eXor : return "Xor";
+ case LogicOp::eOr : return "Or";
+ case LogicOp::eNor : return "Nor";
+ case LogicOp::eEquivalent : return "Equivalent";
+ case LogicOp::eInvert : return "Invert";
+ case LogicOp::eOrReverse : return "OrReverse";
+ case LogicOp::eCopyInverted : return "CopyInverted";
+ case LogicOp::eOrInverted : return "OrInverted";
+ case LogicOp::eNand : return "Nand";
+ case LogicOp::eSet : return "Set";
+ default: return "invalid";
+ }
+ }
+
+ enum class MemoryAllocateFlagBits
+ {
+ eDeviceMask = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT,
+ eDeviceAddress = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
+ eDeviceAddressCaptureReplay = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT
+ };
+ using MemoryAllocateFlagBitsKHR = MemoryAllocateFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( MemoryAllocateFlagBits value )
+ {
+ switch ( value )
+ {
+ case MemoryAllocateFlagBits::eDeviceMask : return "DeviceMask";
+ case MemoryAllocateFlagBits::eDeviceAddress : return "DeviceAddress";
+ case MemoryAllocateFlagBits::eDeviceAddressCaptureReplay : return "DeviceAddressCaptureReplay";
+ default: return "invalid";
+ }
+ }
+
+ enum class MemoryHeapFlagBits
+ {
+ eDeviceLocal = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
+ eMultiInstance = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT,
+ eMultiInstanceKHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( MemoryHeapFlagBits value )
+ {
+ switch ( value )
+ {
+ case MemoryHeapFlagBits::eDeviceLocal : return "DeviceLocal";
+ case MemoryHeapFlagBits::eMultiInstance : return "MultiInstance";
+ default: return "invalid";
+ }
+ }
+
+ enum class MemoryOverallocationBehaviorAMD
+ {
+ eDefault = VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD,
+ eAllowed = VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD,
+ eDisallowed = VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( MemoryOverallocationBehaviorAMD value )
+ {
+ switch ( value )
+ {
+ case MemoryOverallocationBehaviorAMD::eDefault : return "Default";
+ case MemoryOverallocationBehaviorAMD::eAllowed : return "Allowed";
+ case MemoryOverallocationBehaviorAMD::eDisallowed : return "Disallowed";
+ default: return "invalid";
+ }
+ }
+
+ enum class MemoryPropertyFlagBits
+ {
+ eDeviceLocal = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+ eHostVisible = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+ eHostCoherent = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+ eHostCached = VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
+ eLazilyAllocated = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT,
+ eProtected = VK_MEMORY_PROPERTY_PROTECTED_BIT,
+ eDeviceCoherentAMD = VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD,
+ eDeviceUncachedAMD = VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( MemoryPropertyFlagBits value )
+ {
+ switch ( value )
+ {
+ case MemoryPropertyFlagBits::eDeviceLocal : return "DeviceLocal";
+ case MemoryPropertyFlagBits::eHostVisible : return "HostVisible";
+ case MemoryPropertyFlagBits::eHostCoherent : return "HostCoherent";
+ case MemoryPropertyFlagBits::eHostCached : return "HostCached";
+ case MemoryPropertyFlagBits::eLazilyAllocated : return "LazilyAllocated";
+ case MemoryPropertyFlagBits::eProtected : return "Protected";
+ case MemoryPropertyFlagBits::eDeviceCoherentAMD : return "DeviceCoherentAMD";
+ case MemoryPropertyFlagBits::eDeviceUncachedAMD : return "DeviceUncachedAMD";
+ default: return "invalid";
+ }
+ }
+
+ enum class ObjectEntryTypeNVX
+ {
+ eDescriptorSet = VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX,
+ ePipeline = VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX,
+ eIndexBuffer = VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX,
+ eVertexBuffer = VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX,
+ ePushConstant = VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ObjectEntryTypeNVX value )
+ {
+ switch ( value )
+ {
+ case ObjectEntryTypeNVX::eDescriptorSet : return "DescriptorSet";
+ case ObjectEntryTypeNVX::ePipeline : return "Pipeline";
+ case ObjectEntryTypeNVX::eIndexBuffer : return "IndexBuffer";
+ case ObjectEntryTypeNVX::eVertexBuffer : return "VertexBuffer";
+ case ObjectEntryTypeNVX::ePushConstant : return "PushConstant";
+ default: return "invalid";
+ }
+ }
+
+ enum class ObjectEntryUsageFlagBitsNVX
+ {
+ eGraphics = VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX,
+ eCompute = VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ObjectEntryUsageFlagBitsNVX value )
+ {
+ switch ( value )
+ {
+ case ObjectEntryUsageFlagBitsNVX::eGraphics : return "Graphics";
+ case ObjectEntryUsageFlagBitsNVX::eCompute : return "Compute";
+ default: return "invalid";
+ }
+ }
+
+ enum class ObjectType
+ {
+ eUnknown = VK_OBJECT_TYPE_UNKNOWN,
+ eInstance = VK_OBJECT_TYPE_INSTANCE,
+ ePhysicalDevice = VK_OBJECT_TYPE_PHYSICAL_DEVICE,
+ eDevice = VK_OBJECT_TYPE_DEVICE,
+ eQueue = VK_OBJECT_TYPE_QUEUE,
+ eSemaphore = VK_OBJECT_TYPE_SEMAPHORE,
+ eCommandBuffer = VK_OBJECT_TYPE_COMMAND_BUFFER,
+ eFence = VK_OBJECT_TYPE_FENCE,
+ eDeviceMemory = VK_OBJECT_TYPE_DEVICE_MEMORY,
+ eBuffer = VK_OBJECT_TYPE_BUFFER,
+ eImage = VK_OBJECT_TYPE_IMAGE,
+ eEvent = VK_OBJECT_TYPE_EVENT,
+ eQueryPool = VK_OBJECT_TYPE_QUERY_POOL,
+ eBufferView = VK_OBJECT_TYPE_BUFFER_VIEW,
+ eImageView = VK_OBJECT_TYPE_IMAGE_VIEW,
+ eShaderModule = VK_OBJECT_TYPE_SHADER_MODULE,
+ ePipelineCache = VK_OBJECT_TYPE_PIPELINE_CACHE,
+ ePipelineLayout = VK_OBJECT_TYPE_PIPELINE_LAYOUT,
+ eRenderPass = VK_OBJECT_TYPE_RENDER_PASS,
+ ePipeline = VK_OBJECT_TYPE_PIPELINE,
+ eDescriptorSetLayout = VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT,
+ eSampler = VK_OBJECT_TYPE_SAMPLER,
+ eDescriptorPool = VK_OBJECT_TYPE_DESCRIPTOR_POOL,
+ eDescriptorSet = VK_OBJECT_TYPE_DESCRIPTOR_SET,
+ eFramebuffer = VK_OBJECT_TYPE_FRAMEBUFFER,
+ eCommandPool = VK_OBJECT_TYPE_COMMAND_POOL,
+ eSamplerYcbcrConversion = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
+ eDescriptorUpdateTemplate = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE,
+ eSurfaceKHR = VK_OBJECT_TYPE_SURFACE_KHR,
+ eSwapchainKHR = VK_OBJECT_TYPE_SWAPCHAIN_KHR,
+ eDisplayKHR = VK_OBJECT_TYPE_DISPLAY_KHR,
+ eDisplayModeKHR = VK_OBJECT_TYPE_DISPLAY_MODE_KHR,
+ eDebugReportCallbackEXT = VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT,
+ eObjectTableNVX = VK_OBJECT_TYPE_OBJECT_TABLE_NVX,
+ eIndirectCommandsLayoutNVX = VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX,
+ eDebugUtilsMessengerEXT = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT,
+ eValidationCacheEXT = VK_OBJECT_TYPE_VALIDATION_CACHE_EXT,
+ eAccelerationStructureNV = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV,
+ ePerformanceConfigurationINTEL = VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL,
+ eDescriptorUpdateTemplateKHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR,
+ eSamplerYcbcrConversionKHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ObjectType value )
+ {
+ switch ( value )
+ {
+ case ObjectType::eUnknown : return "Unknown";
+ case ObjectType::eInstance : return "Instance";
+ case ObjectType::ePhysicalDevice : return "PhysicalDevice";
+ case ObjectType::eDevice : return "Device";
+ case ObjectType::eQueue : return "Queue";
+ case ObjectType::eSemaphore : return "Semaphore";
+ case ObjectType::eCommandBuffer : return "CommandBuffer";
+ case ObjectType::eFence : return "Fence";
+ case ObjectType::eDeviceMemory : return "DeviceMemory";
+ case ObjectType::eBuffer : return "Buffer";
+ case ObjectType::eImage : return "Image";
+ case ObjectType::eEvent : return "Event";
+ case ObjectType::eQueryPool : return "QueryPool";
+ case ObjectType::eBufferView : return "BufferView";
+ case ObjectType::eImageView : return "ImageView";
+ case ObjectType::eShaderModule : return "ShaderModule";
+ case ObjectType::ePipelineCache : return "PipelineCache";
+ case ObjectType::ePipelineLayout : return "PipelineLayout";
+ case ObjectType::eRenderPass : return "RenderPass";
+ case ObjectType::ePipeline : return "Pipeline";
+ case ObjectType::eDescriptorSetLayout : return "DescriptorSetLayout";
+ case ObjectType::eSampler : return "Sampler";
+ case ObjectType::eDescriptorPool : return "DescriptorPool";
+ case ObjectType::eDescriptorSet : return "DescriptorSet";
+ case ObjectType::eFramebuffer : return "Framebuffer";
+ case ObjectType::eCommandPool : return "CommandPool";
+ case ObjectType::eSamplerYcbcrConversion : return "SamplerYcbcrConversion";
+ case ObjectType::eDescriptorUpdateTemplate : return "DescriptorUpdateTemplate";
+ case ObjectType::eSurfaceKHR : return "SurfaceKHR";
+ case ObjectType::eSwapchainKHR : return "SwapchainKHR";
+ case ObjectType::eDisplayKHR : return "DisplayKHR";
+ case ObjectType::eDisplayModeKHR : return "DisplayModeKHR";
+ case ObjectType::eDebugReportCallbackEXT : return "DebugReportCallbackEXT";
+ case ObjectType::eObjectTableNVX : return "ObjectTableNVX";
+ case ObjectType::eIndirectCommandsLayoutNVX : return "IndirectCommandsLayoutNVX";
+ case ObjectType::eDebugUtilsMessengerEXT : return "DebugUtilsMessengerEXT";
+ case ObjectType::eValidationCacheEXT : return "ValidationCacheEXT";
+ case ObjectType::eAccelerationStructureNV : return "AccelerationStructureNV";
+ case ObjectType::ePerformanceConfigurationINTEL : return "PerformanceConfigurationINTEL";
+ default: return "invalid";
+ }
+ }
+
+ enum class PeerMemoryFeatureFlagBits
+ {
+ eCopySrc = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT,
+ eCopyDst = VK_PEER_MEMORY_FEATURE_COPY_DST_BIT,
+ eGenericSrc = VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT,
+ eGenericDst = VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT
+ };
+ using PeerMemoryFeatureFlagBitsKHR = PeerMemoryFeatureFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( PeerMemoryFeatureFlagBits value )
+ {
+ switch ( value )
+ {
+ case PeerMemoryFeatureFlagBits::eCopySrc : return "CopySrc";
+ case PeerMemoryFeatureFlagBits::eCopyDst : return "CopyDst";
+ case PeerMemoryFeatureFlagBits::eGenericSrc : return "GenericSrc";
+ case PeerMemoryFeatureFlagBits::eGenericDst : return "GenericDst";
+ default: return "invalid";
+ }
+ }
+
+ enum class PerformanceConfigurationTypeINTEL
+ {
+ eCommandQueueMetricsDiscoveryActivated = VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PerformanceConfigurationTypeINTEL value )
+ {
+ switch ( value )
+ {
+ case PerformanceConfigurationTypeINTEL::eCommandQueueMetricsDiscoveryActivated : return "CommandQueueMetricsDiscoveryActivated";
+ default: return "invalid";
+ }
+ }
+
+ enum class PerformanceCounterDescriptionFlagBitsKHR
+ {
+ ePerformanceImpacting = VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR,
+ eConcurrentlyImpacted = VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PerformanceCounterDescriptionFlagBitsKHR value )
+ {
+ switch ( value )
+ {
+ case PerformanceCounterDescriptionFlagBitsKHR::ePerformanceImpacting : return "PerformanceImpacting";
+ case PerformanceCounterDescriptionFlagBitsKHR::eConcurrentlyImpacted : return "ConcurrentlyImpacted";
+ default: return "invalid";
+ }
+ }
+
+ enum class PerformanceCounterScopeKHR
+ {
+ eCommandBuffer = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR,
+ eRenderPass = VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR,
+ eCommand = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR,
+ eVkQueryScopeCommandBuffer = VK_QUERY_SCOPE_COMMAND_BUFFER_KHR,
+ eVkQueryScopeRenderPass = VK_QUERY_SCOPE_RENDER_PASS_KHR,
+ eVkQueryScopeCommand = VK_QUERY_SCOPE_COMMAND_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PerformanceCounterScopeKHR value )
+ {
+ switch ( value )
+ {
+ case PerformanceCounterScopeKHR::eCommandBuffer : return "CommandBuffer";
+ case PerformanceCounterScopeKHR::eRenderPass : return "RenderPass";
+ case PerformanceCounterScopeKHR::eCommand : return "Command";
+ default: return "invalid";
+ }
+ }
+
+ enum class PerformanceCounterStorageKHR
+ {
+ eInt32 = VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR,
+ eInt64 = VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR,
+ eUint32 = VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR,
+ eUint64 = VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR,
+ eFloat32 = VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR,
+ eFloat64 = VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PerformanceCounterStorageKHR value )
+ {
+ switch ( value )
+ {
+ case PerformanceCounterStorageKHR::eInt32 : return "Int32";
+ case PerformanceCounterStorageKHR::eInt64 : return "Int64";
+ case PerformanceCounterStorageKHR::eUint32 : return "Uint32";
+ case PerformanceCounterStorageKHR::eUint64 : return "Uint64";
+ case PerformanceCounterStorageKHR::eFloat32 : return "Float32";
+ case PerformanceCounterStorageKHR::eFloat64 : return "Float64";
+ default: return "invalid";
+ }
+ }
+
+ enum class PerformanceCounterUnitKHR
+ {
+ eGeneric = VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR,
+ ePercentage = VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR,
+ eNanoseconds = VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR,
+ eBytes = VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR,
+ eBytesPerSecond = VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR,
+ eKelvin = VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR,
+ eWatts = VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR,
+ eVolts = VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR,
+ eAmps = VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR,
+ eHertz = VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR,
+ eCycles = VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PerformanceCounterUnitKHR value )
+ {
+ switch ( value )
+ {
+ case PerformanceCounterUnitKHR::eGeneric : return "Generic";
+ case PerformanceCounterUnitKHR::ePercentage : return "Percentage";
+ case PerformanceCounterUnitKHR::eNanoseconds : return "Nanoseconds";
+ case PerformanceCounterUnitKHR::eBytes : return "Bytes";
+ case PerformanceCounterUnitKHR::eBytesPerSecond : return "BytesPerSecond";
+ case PerformanceCounterUnitKHR::eKelvin : return "Kelvin";
+ case PerformanceCounterUnitKHR::eWatts : return "Watts";
+ case PerformanceCounterUnitKHR::eVolts : return "Volts";
+ case PerformanceCounterUnitKHR::eAmps : return "Amps";
+ case PerformanceCounterUnitKHR::eHertz : return "Hertz";
+ case PerformanceCounterUnitKHR::eCycles : return "Cycles";
+ default: return "invalid";
+ }
+ }
+
+ enum class PerformanceOverrideTypeINTEL
+ {
+ eNullHardware = VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL,
+ eFlushGpuCaches = VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PerformanceOverrideTypeINTEL value )
+ {
+ switch ( value )
+ {
+ case PerformanceOverrideTypeINTEL::eNullHardware : return "NullHardware";
+ case PerformanceOverrideTypeINTEL::eFlushGpuCaches : return "FlushGpuCaches";
+ default: return "invalid";
+ }
+ }
+
+ enum class PerformanceParameterTypeINTEL
+ {
+ eHwCountersSupported = VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL,
+ eStreamMarkerValidBits = VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PerformanceParameterTypeINTEL value )
+ {
+ switch ( value )
+ {
+ case PerformanceParameterTypeINTEL::eHwCountersSupported : return "HwCountersSupported";
+ case PerformanceParameterTypeINTEL::eStreamMarkerValidBits : return "StreamMarkerValidBits";
+ default: return "invalid";
+ }
+ }
+
+ enum class PerformanceValueTypeINTEL
+ {
+ eUint32 = VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL,
+ eUint64 = VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL,
+ eFloat = VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL,
+ eBool = VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL,
+ eString = VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PerformanceValueTypeINTEL value )
+ {
+ switch ( value )
+ {
+ case PerformanceValueTypeINTEL::eUint32 : return "Uint32";
+ case PerformanceValueTypeINTEL::eUint64 : return "Uint64";
+ case PerformanceValueTypeINTEL::eFloat : return "Float";
+ case PerformanceValueTypeINTEL::eBool : return "Bool";
+ case PerformanceValueTypeINTEL::eString : return "String";
+ default: return "invalid";
+ }
+ }
+
+ enum class PhysicalDeviceType
+ {
+ eOther = VK_PHYSICAL_DEVICE_TYPE_OTHER,
+ eIntegratedGpu = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
+ eDiscreteGpu = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
+ eVirtualGpu = VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
+ eCpu = VK_PHYSICAL_DEVICE_TYPE_CPU
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PhysicalDeviceType value )
+ {
+ switch ( value )
+ {
+ case PhysicalDeviceType::eOther : return "Other";
+ case PhysicalDeviceType::eIntegratedGpu : return "IntegratedGpu";
+ case PhysicalDeviceType::eDiscreteGpu : return "DiscreteGpu";
+ case PhysicalDeviceType::eVirtualGpu : return "VirtualGpu";
+ case PhysicalDeviceType::eCpu : return "Cpu";
+ default: return "invalid";
+ }
+ }
+
+ enum class PipelineBindPoint
+ {
+ eGraphics = VK_PIPELINE_BIND_POINT_GRAPHICS,
+ eCompute = VK_PIPELINE_BIND_POINT_COMPUTE,
+ eRayTracingNV = VK_PIPELINE_BIND_POINT_RAY_TRACING_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineBindPoint value )
+ {
+ switch ( value )
+ {
+ case PipelineBindPoint::eGraphics : return "Graphics";
+ case PipelineBindPoint::eCompute : return "Compute";
+ case PipelineBindPoint::eRayTracingNV : return "RayTracingNV";
+ default: return "invalid";
+ }
+ }
+
+ enum class PipelineCacheCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCacheCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineCacheHeaderVersion
+ {
+ eOne = VK_PIPELINE_CACHE_HEADER_VERSION_ONE
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCacheHeaderVersion value )
+ {
+ switch ( value )
+ {
+ case PipelineCacheHeaderVersion::eOne : return "One";
+ default: return "invalid";
+ }
+ }
+
+ enum class PipelineColorBlendStateCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineColorBlendStateCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineCompilerControlFlagBitsAMD
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCompilerControlFlagBitsAMD )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineCreateFlagBits
+ {
+ eDisableOptimization = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT,
+ eAllowDerivatives = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT,
+ eDerivative = VK_PIPELINE_CREATE_DERIVATIVE_BIT,
+ eViewIndexFromDeviceIndex = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT,
+ eDispatchBase = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT,
+ eDeferCompileNV = VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV,
+ eCaptureStatisticsKHR = VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR,
+ eCaptureInternalRepresentationsKHR = VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR,
+ eViewIndexFromDeviceIndexKHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR,
+ eDispatchBaseKHR = VK_PIPELINE_CREATE_DISPATCH_BASE_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case PipelineCreateFlagBits::eDisableOptimization : return "DisableOptimization";
+ case PipelineCreateFlagBits::eAllowDerivatives : return "AllowDerivatives";
+ case PipelineCreateFlagBits::eDerivative : return "Derivative";
+ case PipelineCreateFlagBits::eViewIndexFromDeviceIndex : return "ViewIndexFromDeviceIndex";
+ case PipelineCreateFlagBits::eDispatchBase : return "DispatchBase";
+ case PipelineCreateFlagBits::eDeferCompileNV : return "DeferCompileNV";
+ case PipelineCreateFlagBits::eCaptureStatisticsKHR : return "CaptureStatisticsKHR";
+ case PipelineCreateFlagBits::eCaptureInternalRepresentationsKHR : return "CaptureInternalRepresentationsKHR";
+ default: return "invalid";
+ }
+ }
+
+ enum class PipelineCreationFeedbackFlagBitsEXT
+ {
+ eValid = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT,
+ eApplicationPipelineCacheHit = VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT,
+ eBasePipelineAcceleration = VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCreationFeedbackFlagBitsEXT value )
+ {
+ switch ( value )
+ {
+ case PipelineCreationFeedbackFlagBitsEXT::eValid : return "Valid";
+ case PipelineCreationFeedbackFlagBitsEXT::eApplicationPipelineCacheHit : return "ApplicationPipelineCacheHit";
+ case PipelineCreationFeedbackFlagBitsEXT::eBasePipelineAcceleration : return "BasePipelineAcceleration";
+ default: return "invalid";
+ }
+ }
+
+ enum class PipelineDepthStencilStateCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineDepthStencilStateCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineDynamicStateCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineDynamicStateCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineExecutableStatisticFormatKHR
+ {
+ eBool32 = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR,
+ eInt64 = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR,
+ eUint64 = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR,
+ eFloat64 = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineExecutableStatisticFormatKHR value )
+ {
+ switch ( value )
+ {
+ case PipelineExecutableStatisticFormatKHR::eBool32 : return "Bool32";
+ case PipelineExecutableStatisticFormatKHR::eInt64 : return "Int64";
+ case PipelineExecutableStatisticFormatKHR::eUint64 : return "Uint64";
+ case PipelineExecutableStatisticFormatKHR::eFloat64 : return "Float64";
+ default: return "invalid";
+ }
+ }
+
+ enum class PipelineInputAssemblyStateCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineInputAssemblyStateCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineLayoutCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineLayoutCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineMultisampleStateCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineMultisampleStateCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineRasterizationStateCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineRasterizationStateCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineShaderStageCreateFlagBits
+ {
+ eAllowVaryingSubgroupSizeEXT = VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT,
+ eRequireFullSubgroupsEXT = VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineShaderStageCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case PipelineShaderStageCreateFlagBits::eAllowVaryingSubgroupSizeEXT : return "AllowVaryingSubgroupSizeEXT";
+ case PipelineShaderStageCreateFlagBits::eRequireFullSubgroupsEXT : return "RequireFullSubgroupsEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class PipelineStageFlagBits
+ {
+ eTopOfPipe = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ eDrawIndirect = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
+ eVertexInput = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
+ eVertexShader = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+ eTessellationControlShader = VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT,
+ eTessellationEvaluationShader = VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT,
+ eGeometryShader = VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
+ eFragmentShader = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ eEarlyFragmentTests = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
+ eLateFragmentTests = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+ eColorAttachmentOutput = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ eComputeShader = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
+ eTransfer = VK_PIPELINE_STAGE_TRANSFER_BIT,
+ eBottomOfPipe = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ eHost = VK_PIPELINE_STAGE_HOST_BIT,
+ eAllGraphics = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ eAllCommands = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ eTransformFeedbackEXT = VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
+ eConditionalRenderingEXT = VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT,
+ eCommandProcessNVX = VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX,
+ eShadingRateImageNV = VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV,
+ eRayTracingShaderNV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV,
+ eAccelerationStructureBuildNV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV,
+ eTaskShaderNV = VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV,
+ eMeshShaderNV = VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV,
+ eFragmentDensityProcessEXT = VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineStageFlagBits value )
+ {
+ switch ( value )
+ {
+ case PipelineStageFlagBits::eTopOfPipe : return "TopOfPipe";
+ case PipelineStageFlagBits::eDrawIndirect : return "DrawIndirect";
+ case PipelineStageFlagBits::eVertexInput : return "VertexInput";
+ case PipelineStageFlagBits::eVertexShader : return "VertexShader";
+ case PipelineStageFlagBits::eTessellationControlShader : return "TessellationControlShader";
+ case PipelineStageFlagBits::eTessellationEvaluationShader : return "TessellationEvaluationShader";
+ case PipelineStageFlagBits::eGeometryShader : return "GeometryShader";
+ case PipelineStageFlagBits::eFragmentShader : return "FragmentShader";
+ case PipelineStageFlagBits::eEarlyFragmentTests : return "EarlyFragmentTests";
+ case PipelineStageFlagBits::eLateFragmentTests : return "LateFragmentTests";
+ case PipelineStageFlagBits::eColorAttachmentOutput : return "ColorAttachmentOutput";
+ case PipelineStageFlagBits::eComputeShader : return "ComputeShader";
+ case PipelineStageFlagBits::eTransfer : return "Transfer";
+ case PipelineStageFlagBits::eBottomOfPipe : return "BottomOfPipe";
+ case PipelineStageFlagBits::eHost : return "Host";
+ case PipelineStageFlagBits::eAllGraphics : return "AllGraphics";
+ case PipelineStageFlagBits::eAllCommands : return "AllCommands";
+ case PipelineStageFlagBits::eTransformFeedbackEXT : return "TransformFeedbackEXT";
+ case PipelineStageFlagBits::eConditionalRenderingEXT : return "ConditionalRenderingEXT";
+ case PipelineStageFlagBits::eCommandProcessNVX : return "CommandProcessNVX";
+ case PipelineStageFlagBits::eShadingRateImageNV : return "ShadingRateImageNV";
+ case PipelineStageFlagBits::eRayTracingShaderNV : return "RayTracingShaderNV";
+ case PipelineStageFlagBits::eAccelerationStructureBuildNV : return "AccelerationStructureBuildNV";
+ case PipelineStageFlagBits::eTaskShaderNV : return "TaskShaderNV";
+ case PipelineStageFlagBits::eMeshShaderNV : return "MeshShaderNV";
+ case PipelineStageFlagBits::eFragmentDensityProcessEXT : return "FragmentDensityProcessEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class PipelineTessellationStateCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineTessellationStateCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineVertexInputStateCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineVertexInputStateCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PipelineViewportStateCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineViewportStateCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class PointClippingBehavior
+ {
+ eAllClipPlanes = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES,
+ eUserClipPlanesOnly = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY
+ };
+ using PointClippingBehaviorKHR = PointClippingBehavior;
+
+ VULKAN_HPP_INLINE std::string to_string( PointClippingBehavior value )
+ {
+ switch ( value )
+ {
+ case PointClippingBehavior::eAllClipPlanes : return "AllClipPlanes";
+ case PointClippingBehavior::eUserClipPlanesOnly : return "UserClipPlanesOnly";
+ default: return "invalid";
+ }
+ }
+
+ enum class PolygonMode
+ {
+ eFill = VK_POLYGON_MODE_FILL,
+ eLine = VK_POLYGON_MODE_LINE,
+ ePoint = VK_POLYGON_MODE_POINT,
+ eFillRectangleNV = VK_POLYGON_MODE_FILL_RECTANGLE_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PolygonMode value )
+ {
+ switch ( value )
+ {
+ case PolygonMode::eFill : return "Fill";
+ case PolygonMode::eLine : return "Line";
+ case PolygonMode::ePoint : return "Point";
+ case PolygonMode::eFillRectangleNV : return "FillRectangleNV";
+ default: return "invalid";
+ }
+ }
+
+ enum class PresentModeKHR
+ {
+ eImmediate = VK_PRESENT_MODE_IMMEDIATE_KHR,
+ eMailbox = VK_PRESENT_MODE_MAILBOX_KHR,
+ eFifo = VK_PRESENT_MODE_FIFO_KHR,
+ eFifoRelaxed = VK_PRESENT_MODE_FIFO_RELAXED_KHR,
+ eSharedDemandRefresh = VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR,
+ eSharedContinuousRefresh = VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PresentModeKHR value )
+ {
+ switch ( value )
+ {
+ case PresentModeKHR::eImmediate : return "Immediate";
+ case PresentModeKHR::eMailbox : return "Mailbox";
+ case PresentModeKHR::eFifo : return "Fifo";
+ case PresentModeKHR::eFifoRelaxed : return "FifoRelaxed";
+ case PresentModeKHR::eSharedDemandRefresh : return "SharedDemandRefresh";
+ case PresentModeKHR::eSharedContinuousRefresh : return "SharedContinuousRefresh";
+ default: return "invalid";
+ }
+ }
+
+ enum class PrimitiveTopology
+ {
+ ePointList = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
+ eLineList = VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
+ eLineStrip = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
+ eTriangleList = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+ eTriangleStrip = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
+ eTriangleFan = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
+ eLineListWithAdjacency = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
+ eLineStripWithAdjacency = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
+ eTriangleListWithAdjacency = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
+ eTriangleStripWithAdjacency = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
+ ePatchList = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( PrimitiveTopology value )
+ {
+ switch ( value )
+ {
+ case PrimitiveTopology::ePointList : return "PointList";
+ case PrimitiveTopology::eLineList : return "LineList";
+ case PrimitiveTopology::eLineStrip : return "LineStrip";
+ case PrimitiveTopology::eTriangleList : return "TriangleList";
+ case PrimitiveTopology::eTriangleStrip : return "TriangleStrip";
+ case PrimitiveTopology::eTriangleFan : return "TriangleFan";
+ case PrimitiveTopology::eLineListWithAdjacency : return "LineListWithAdjacency";
+ case PrimitiveTopology::eLineStripWithAdjacency : return "LineStripWithAdjacency";
+ case PrimitiveTopology::eTriangleListWithAdjacency : return "TriangleListWithAdjacency";
+ case PrimitiveTopology::eTriangleStripWithAdjacency : return "TriangleStripWithAdjacency";
+ case PrimitiveTopology::ePatchList : return "PatchList";
+ default: return "invalid";
+ }
+ }
+
+ enum class QueryControlFlagBits
+ {
+ ePrecise = VK_QUERY_CONTROL_PRECISE_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( QueryControlFlagBits value )
+ {
+ switch ( value )
+ {
+ case QueryControlFlagBits::ePrecise : return "Precise";
+ default: return "invalid";
+ }
+ }
+
+ enum class QueryPipelineStatisticFlagBits
+ {
+ eInputAssemblyVertices = VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT,
+ eInputAssemblyPrimitives = VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT,
+ eVertexShaderInvocations = VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT,
+ eGeometryShaderInvocations = VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT,
+ eGeometryShaderPrimitives = VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT,
+ eClippingInvocations = VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT,
+ eClippingPrimitives = VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT,
+ eFragmentShaderInvocations = VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT,
+ eTessellationControlShaderPatches = VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT,
+ eTessellationEvaluationShaderInvocations = VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT,
+ eComputeShaderInvocations = VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( QueryPipelineStatisticFlagBits value )
+ {
+ switch ( value )
+ {
+ case QueryPipelineStatisticFlagBits::eInputAssemblyVertices : return "InputAssemblyVertices";
+ case QueryPipelineStatisticFlagBits::eInputAssemblyPrimitives : return "InputAssemblyPrimitives";
+ case QueryPipelineStatisticFlagBits::eVertexShaderInvocations : return "VertexShaderInvocations";
+ case QueryPipelineStatisticFlagBits::eGeometryShaderInvocations : return "GeometryShaderInvocations";
+ case QueryPipelineStatisticFlagBits::eGeometryShaderPrimitives : return "GeometryShaderPrimitives";
+ case QueryPipelineStatisticFlagBits::eClippingInvocations : return "ClippingInvocations";
+ case QueryPipelineStatisticFlagBits::eClippingPrimitives : return "ClippingPrimitives";
+ case QueryPipelineStatisticFlagBits::eFragmentShaderInvocations : return "FragmentShaderInvocations";
+ case QueryPipelineStatisticFlagBits::eTessellationControlShaderPatches : return "TessellationControlShaderPatches";
+ case QueryPipelineStatisticFlagBits::eTessellationEvaluationShaderInvocations : return "TessellationEvaluationShaderInvocations";
+ case QueryPipelineStatisticFlagBits::eComputeShaderInvocations : return "ComputeShaderInvocations";
+ default: return "invalid";
+ }
+ }
+
+ enum class QueryPoolCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( QueryPoolCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class QueryPoolSamplingModeINTEL
+ {
+ eManual = VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( QueryPoolSamplingModeINTEL value )
+ {
+ switch ( value )
+ {
+ case QueryPoolSamplingModeINTEL::eManual : return "Manual";
+ default: return "invalid";
+ }
+ }
+
+ enum class QueryResultFlagBits
+ {
+ e64 = VK_QUERY_RESULT_64_BIT,
+ eWait = VK_QUERY_RESULT_WAIT_BIT,
+ eWithAvailability = VK_QUERY_RESULT_WITH_AVAILABILITY_BIT,
+ ePartial = VK_QUERY_RESULT_PARTIAL_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( QueryResultFlagBits value )
+ {
+ switch ( value )
+ {
+ case QueryResultFlagBits::e64 : return "64";
+ case QueryResultFlagBits::eWait : return "Wait";
+ case QueryResultFlagBits::eWithAvailability : return "WithAvailability";
+ case QueryResultFlagBits::ePartial : return "Partial";
+ default: return "invalid";
+ }
+ }
+
+ enum class QueryType
+ {
+ eOcclusion = VK_QUERY_TYPE_OCCLUSION,
+ ePipelineStatistics = VK_QUERY_TYPE_PIPELINE_STATISTICS,
+ eTimestamp = VK_QUERY_TYPE_TIMESTAMP,
+ eTransformFeedbackStreamEXT = VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,
+ ePerformanceQueryKHR = VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR,
+ eAccelerationStructureCompactedSizeNV = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV,
+ ePerformanceQueryINTEL = VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( QueryType value )
+ {
+ switch ( value )
+ {
+ case QueryType::eOcclusion : return "Occlusion";
+ case QueryType::ePipelineStatistics : return "PipelineStatistics";
+ case QueryType::eTimestamp : return "Timestamp";
+ case QueryType::eTransformFeedbackStreamEXT : return "TransformFeedbackStreamEXT";
+ case QueryType::ePerformanceQueryKHR : return "PerformanceQueryKHR";
+ case QueryType::eAccelerationStructureCompactedSizeNV : return "AccelerationStructureCompactedSizeNV";
+ case QueryType::ePerformanceQueryINTEL : return "PerformanceQueryINTEL";
+ default: return "invalid";
+ }
+ }
+
+ enum class QueueFlagBits
+ {
+ eGraphics = VK_QUEUE_GRAPHICS_BIT,
+ eCompute = VK_QUEUE_COMPUTE_BIT,
+ eTransfer = VK_QUEUE_TRANSFER_BIT,
+ eSparseBinding = VK_QUEUE_SPARSE_BINDING_BIT,
+ eProtected = VK_QUEUE_PROTECTED_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( QueueFlagBits value )
+ {
+ switch ( value )
+ {
+ case QueueFlagBits::eGraphics : return "Graphics";
+ case QueueFlagBits::eCompute : return "Compute";
+ case QueueFlagBits::eTransfer : return "Transfer";
+ case QueueFlagBits::eSparseBinding : return "SparseBinding";
+ case QueueFlagBits::eProtected : return "Protected";
+ default: return "invalid";
+ }
+ }
+
+ enum class QueueGlobalPriorityEXT
+ {
+ eLow = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT,
+ eMedium = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT,
+ eHigh = VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT,
+ eRealtime = VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( QueueGlobalPriorityEXT value )
+ {
+ switch ( value )
+ {
+ case QueueGlobalPriorityEXT::eLow : return "Low";
+ case QueueGlobalPriorityEXT::eMedium : return "Medium";
+ case QueueGlobalPriorityEXT::eHigh : return "High";
+ case QueueGlobalPriorityEXT::eRealtime : return "Realtime";
+ default: return "invalid";
+ }
+ }
+
+ enum class RasterizationOrderAMD
+ {
+ eStrict = VK_RASTERIZATION_ORDER_STRICT_AMD,
+ eRelaxed = VK_RASTERIZATION_ORDER_RELAXED_AMD
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( RasterizationOrderAMD value )
+ {
+ switch ( value )
+ {
+ case RasterizationOrderAMD::eStrict : return "Strict";
+ case RasterizationOrderAMD::eRelaxed : return "Relaxed";
+ default: return "invalid";
+ }
+ }
+
+ enum class RayTracingShaderGroupTypeNV
+ {
+ eGeneral = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV,
+ eTrianglesHitGroup = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV,
+ eProceduralHitGroup = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( RayTracingShaderGroupTypeNV value )
+ {
+ switch ( value )
+ {
+ case RayTracingShaderGroupTypeNV::eGeneral : return "General";
+ case RayTracingShaderGroupTypeNV::eTrianglesHitGroup : return "TrianglesHitGroup";
+ case RayTracingShaderGroupTypeNV::eProceduralHitGroup : return "ProceduralHitGroup";
+ default: return "invalid";
+ }
+ }
+
+ enum class RenderPassCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( RenderPassCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class ResolveModeFlagBits
+ {
+ eNone = VK_RESOLVE_MODE_NONE,
+ eSampleZero = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
+ eAverage = VK_RESOLVE_MODE_AVERAGE_BIT,
+ eMin = VK_RESOLVE_MODE_MIN_BIT,
+ eMax = VK_RESOLVE_MODE_MAX_BIT
+ };
+ using ResolveModeFlagBitsKHR = ResolveModeFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( ResolveModeFlagBits value )
+ {
+ switch ( value )
+ {
+ case ResolveModeFlagBits::eNone : return "None";
+ case ResolveModeFlagBits::eSampleZero : return "SampleZero";
+ case ResolveModeFlagBits::eAverage : return "Average";
+ case ResolveModeFlagBits::eMin : return "Min";
+ case ResolveModeFlagBits::eMax : return "Max";
+ default: return "invalid";
+ }
+ }
+
+ enum class Result
+ {
+ eSuccess = VK_SUCCESS,
+ eNotReady = VK_NOT_READY,
+ eTimeout = VK_TIMEOUT,
+ eEventSet = VK_EVENT_SET,
+ eEventReset = VK_EVENT_RESET,
+ eIncomplete = VK_INCOMPLETE,
+ eErrorOutOfHostMemory = VK_ERROR_OUT_OF_HOST_MEMORY,
+ eErrorOutOfDeviceMemory = VK_ERROR_OUT_OF_DEVICE_MEMORY,
+ eErrorInitializationFailed = VK_ERROR_INITIALIZATION_FAILED,
+ eErrorDeviceLost = VK_ERROR_DEVICE_LOST,
+ eErrorMemoryMapFailed = VK_ERROR_MEMORY_MAP_FAILED,
+ eErrorLayerNotPresent = VK_ERROR_LAYER_NOT_PRESENT,
+ eErrorExtensionNotPresent = VK_ERROR_EXTENSION_NOT_PRESENT,
+ eErrorFeatureNotPresent = VK_ERROR_FEATURE_NOT_PRESENT,
+ eErrorIncompatibleDriver = VK_ERROR_INCOMPATIBLE_DRIVER,
+ eErrorTooManyObjects = VK_ERROR_TOO_MANY_OBJECTS,
+ eErrorFormatNotSupported = VK_ERROR_FORMAT_NOT_SUPPORTED,
+ eErrorFragmentedPool = VK_ERROR_FRAGMENTED_POOL,
+ eErrorUnknown = VK_ERROR_UNKNOWN,
+ eErrorOutOfPoolMemory = VK_ERROR_OUT_OF_POOL_MEMORY,
+ eErrorInvalidExternalHandle = VK_ERROR_INVALID_EXTERNAL_HANDLE,
+ eErrorFragmentation = VK_ERROR_FRAGMENTATION,
+ eErrorInvalidOpaqueCaptureAddress = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS,
+ eErrorSurfaceLostKHR = VK_ERROR_SURFACE_LOST_KHR,
+ eErrorNativeWindowInUseKHR = VK_ERROR_NATIVE_WINDOW_IN_USE_KHR,
+ eSuboptimalKHR = VK_SUBOPTIMAL_KHR,
+ eErrorOutOfDateKHR = VK_ERROR_OUT_OF_DATE_KHR,
+ eErrorIncompatibleDisplayKHR = VK_ERROR_INCOMPATIBLE_DISPLAY_KHR,
+ eErrorValidationFailedEXT = VK_ERROR_VALIDATION_FAILED_EXT,
+ eErrorInvalidShaderNV = VK_ERROR_INVALID_SHADER_NV,
+ eErrorInvalidDrmFormatModifierPlaneLayoutEXT = VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
+ eErrorNotPermittedEXT = VK_ERROR_NOT_PERMITTED_EXT,
+ eErrorFullScreenExclusiveModeLostEXT = VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT,
+ eErrorOutOfPoolMemoryKHR = VK_ERROR_OUT_OF_POOL_MEMORY_KHR,
+ eErrorInvalidExternalHandleKHR = VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
+ eErrorFragmentationEXT = VK_ERROR_FRAGMENTATION_EXT,
+ eErrorInvalidDeviceAddressEXT = VK_ERROR_INVALID_DEVICE_ADDRESS_EXT,
+ eErrorInvalidOpaqueCaptureAddressKHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( Result value )
+ {
+ switch ( value )
+ {
+ case Result::eSuccess : return "Success";
+ case Result::eNotReady : return "NotReady";
+ case Result::eTimeout : return "Timeout";
+ case Result::eEventSet : return "EventSet";
+ case Result::eEventReset : return "EventReset";
+ case Result::eIncomplete : return "Incomplete";
+ case Result::eErrorOutOfHostMemory : return "ErrorOutOfHostMemory";
+ case Result::eErrorOutOfDeviceMemory : return "ErrorOutOfDeviceMemory";
+ case Result::eErrorInitializationFailed : return "ErrorInitializationFailed";
+ case Result::eErrorDeviceLost : return "ErrorDeviceLost";
+ case Result::eErrorMemoryMapFailed : return "ErrorMemoryMapFailed";
+ case Result::eErrorLayerNotPresent : return "ErrorLayerNotPresent";
+ case Result::eErrorExtensionNotPresent : return "ErrorExtensionNotPresent";
+ case Result::eErrorFeatureNotPresent : return "ErrorFeatureNotPresent";
+ case Result::eErrorIncompatibleDriver : return "ErrorIncompatibleDriver";
+ case Result::eErrorTooManyObjects : return "ErrorTooManyObjects";
+ case Result::eErrorFormatNotSupported : return "ErrorFormatNotSupported";
+ case Result::eErrorFragmentedPool : return "ErrorFragmentedPool";
+ case Result::eErrorUnknown : return "ErrorUnknown";
+ case Result::eErrorOutOfPoolMemory : return "ErrorOutOfPoolMemory";
+ case Result::eErrorInvalidExternalHandle : return "ErrorInvalidExternalHandle";
+ case Result::eErrorFragmentation : return "ErrorFragmentation";
+ case Result::eErrorInvalidOpaqueCaptureAddress : return "ErrorInvalidOpaqueCaptureAddress";
+ case Result::eErrorSurfaceLostKHR : return "ErrorSurfaceLostKHR";
+ case Result::eErrorNativeWindowInUseKHR : return "ErrorNativeWindowInUseKHR";
+ case Result::eSuboptimalKHR : return "SuboptimalKHR";
+ case Result::eErrorOutOfDateKHR : return "ErrorOutOfDateKHR";
+ case Result::eErrorIncompatibleDisplayKHR : return "ErrorIncompatibleDisplayKHR";
+ case Result::eErrorValidationFailedEXT : return "ErrorValidationFailedEXT";
+ case Result::eErrorInvalidShaderNV : return "ErrorInvalidShaderNV";
+ case Result::eErrorInvalidDrmFormatModifierPlaneLayoutEXT : return "ErrorInvalidDrmFormatModifierPlaneLayoutEXT";
+ case Result::eErrorNotPermittedEXT : return "ErrorNotPermittedEXT";
+ case Result::eErrorFullScreenExclusiveModeLostEXT : return "ErrorFullScreenExclusiveModeLostEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class SampleCountFlagBits
+ {
+ e1 = VK_SAMPLE_COUNT_1_BIT,
+ e2 = VK_SAMPLE_COUNT_2_BIT,
+ e4 = VK_SAMPLE_COUNT_4_BIT,
+ e8 = VK_SAMPLE_COUNT_8_BIT,
+ e16 = VK_SAMPLE_COUNT_16_BIT,
+ e32 = VK_SAMPLE_COUNT_32_BIT,
+ e64 = VK_SAMPLE_COUNT_64_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SampleCountFlagBits value )
+ {
+ switch ( value )
+ {
+ case SampleCountFlagBits::e1 : return "1";
+ case SampleCountFlagBits::e2 : return "2";
+ case SampleCountFlagBits::e4 : return "4";
+ case SampleCountFlagBits::e8 : return "8";
+ case SampleCountFlagBits::e16 : return "16";
+ case SampleCountFlagBits::e32 : return "32";
+ case SampleCountFlagBits::e64 : return "64";
+ default: return "invalid";
+ }
+ }
+
+ enum class SamplerAddressMode
+ {
+ eRepeat = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+ eMirroredRepeat = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
+ eClampToEdge = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
+ eClampToBorder = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
+ eMirrorClampToEdge = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
+ eMirrorClampToEdgeKHR = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SamplerAddressMode value )
+ {
+ switch ( value )
+ {
+ case SamplerAddressMode::eRepeat : return "Repeat";
+ case SamplerAddressMode::eMirroredRepeat : return "MirroredRepeat";
+ case SamplerAddressMode::eClampToEdge : return "ClampToEdge";
+ case SamplerAddressMode::eClampToBorder : return "ClampToBorder";
+ case SamplerAddressMode::eMirrorClampToEdge : return "MirrorClampToEdge";
+ default: return "invalid";
+ }
+ }
+
+ enum class SamplerCreateFlagBits
+ {
+ eSubsampledEXT = VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT,
+ eSubsampledCoarseReconstructionEXT = VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SamplerCreateFlagBits value )
+ {
+ switch ( value )
+ {
+ case SamplerCreateFlagBits::eSubsampledEXT : return "SubsampledEXT";
+ case SamplerCreateFlagBits::eSubsampledCoarseReconstructionEXT : return "SubsampledCoarseReconstructionEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class SamplerMipmapMode
+ {
+ eNearest = VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ eLinear = VK_SAMPLER_MIPMAP_MODE_LINEAR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SamplerMipmapMode value )
+ {
+ switch ( value )
+ {
+ case SamplerMipmapMode::eNearest : return "Nearest";
+ case SamplerMipmapMode::eLinear : return "Linear";
+ default: return "invalid";
+ }
+ }
+
+ enum class SamplerReductionMode
+ {
+ eWeightedAverage = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE,
+ eMin = VK_SAMPLER_REDUCTION_MODE_MIN,
+ eMax = VK_SAMPLER_REDUCTION_MODE_MAX
+ };
+ using SamplerReductionModeEXT = SamplerReductionMode;
+
+ VULKAN_HPP_INLINE std::string to_string( SamplerReductionMode value )
+ {
+ switch ( value )
+ {
+ case SamplerReductionMode::eWeightedAverage : return "WeightedAverage";
+ case SamplerReductionMode::eMin : return "Min";
+ case SamplerReductionMode::eMax : return "Max";
+ default: return "invalid";
+ }
+ }
+
+ enum class SamplerYcbcrModelConversion
+ {
+ eRgbIdentity = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
+ eYcbcrIdentity = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY,
+ eYcbcr709 = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709,
+ eYcbcr601 = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601,
+ eYcbcr2020 = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020
+ };
+ using SamplerYcbcrModelConversionKHR = SamplerYcbcrModelConversion;
+
+ VULKAN_HPP_INLINE std::string to_string( SamplerYcbcrModelConversion value )
+ {
+ switch ( value )
+ {
+ case SamplerYcbcrModelConversion::eRgbIdentity : return "RgbIdentity";
+ case SamplerYcbcrModelConversion::eYcbcrIdentity : return "YcbcrIdentity";
+ case SamplerYcbcrModelConversion::eYcbcr709 : return "Ycbcr709";
+ case SamplerYcbcrModelConversion::eYcbcr601 : return "Ycbcr601";
+ case SamplerYcbcrModelConversion::eYcbcr2020 : return "Ycbcr2020";
+ default: return "invalid";
+ }
+ }
+
+ enum class SamplerYcbcrRange
+ {
+ eItuFull = VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
+ eItuNarrow = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW
+ };
+ using SamplerYcbcrRangeKHR = SamplerYcbcrRange;
+
+ VULKAN_HPP_INLINE std::string to_string( SamplerYcbcrRange value )
+ {
+ switch ( value )
+ {
+ case SamplerYcbcrRange::eItuFull : return "ItuFull";
+ case SamplerYcbcrRange::eItuNarrow : return "ItuNarrow";
+ default: return "invalid";
+ }
+ }
+
+ enum class ScopeNV
+ {
+ eDevice = VK_SCOPE_DEVICE_NV,
+ eWorkgroup = VK_SCOPE_WORKGROUP_NV,
+ eSubgroup = VK_SCOPE_SUBGROUP_NV,
+ eQueueFamily = VK_SCOPE_QUEUE_FAMILY_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ScopeNV value )
+ {
+ switch ( value )
+ {
+ case ScopeNV::eDevice : return "Device";
+ case ScopeNV::eWorkgroup : return "Workgroup";
+ case ScopeNV::eSubgroup : return "Subgroup";
+ case ScopeNV::eQueueFamily : return "QueueFamily";
+ default: return "invalid";
+ }
+ }
+
+ enum class SemaphoreCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( SemaphoreCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class SemaphoreImportFlagBits
+ {
+ eTemporary = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT
+ };
+ using SemaphoreImportFlagBitsKHR = SemaphoreImportFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( SemaphoreImportFlagBits value )
+ {
+ switch ( value )
+ {
+ case SemaphoreImportFlagBits::eTemporary : return "Temporary";
+ default: return "invalid";
+ }
+ }
+
+ enum class SemaphoreType
+ {
+ eBinary = VK_SEMAPHORE_TYPE_BINARY,
+ eTimeline = VK_SEMAPHORE_TYPE_TIMELINE
+ };
+ using SemaphoreTypeKHR = SemaphoreType;
+
+ VULKAN_HPP_INLINE std::string to_string( SemaphoreType value )
+ {
+ switch ( value )
+ {
+ case SemaphoreType::eBinary : return "Binary";
+ case SemaphoreType::eTimeline : return "Timeline";
+ default: return "invalid";
+ }
+ }
+
+ enum class SemaphoreWaitFlagBits
+ {
+ eAny = VK_SEMAPHORE_WAIT_ANY_BIT
+ };
+ using SemaphoreWaitFlagBitsKHR = SemaphoreWaitFlagBits;
+
+ VULKAN_HPP_INLINE std::string to_string( SemaphoreWaitFlagBits value )
+ {
+ switch ( value )
+ {
+ case SemaphoreWaitFlagBits::eAny : return "Any";
+ default: return "invalid";
+ }
+ }
+
+ enum class ShaderCorePropertiesFlagBitsAMD
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( ShaderCorePropertiesFlagBitsAMD )
+ {
+ return "(void)";
+ }
+
+ enum class ShaderFloatControlsIndependence
+ {
+ e32BitOnly = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY,
+ eAll = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL,
+ eNone = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE
+ };
+ using ShaderFloatControlsIndependenceKHR = ShaderFloatControlsIndependence;
+
+ VULKAN_HPP_INLINE std::string to_string( ShaderFloatControlsIndependence value )
+ {
+ switch ( value )
+ {
+ case ShaderFloatControlsIndependence::e32BitOnly : return "32BitOnly";
+ case ShaderFloatControlsIndependence::eAll : return "All";
+ case ShaderFloatControlsIndependence::eNone : return "None";
+ default: return "invalid";
+ }
+ }
+
+ enum class ShaderInfoTypeAMD
+ {
+ eStatistics = VK_SHADER_INFO_TYPE_STATISTICS_AMD,
+ eBinary = VK_SHADER_INFO_TYPE_BINARY_AMD,
+ eDisassembly = VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ShaderInfoTypeAMD value )
+ {
+ switch ( value )
+ {
+ case ShaderInfoTypeAMD::eStatistics : return "Statistics";
+ case ShaderInfoTypeAMD::eBinary : return "Binary";
+ case ShaderInfoTypeAMD::eDisassembly : return "Disassembly";
+ default: return "invalid";
+ }
+ }
+
+ enum class ShaderModuleCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( ShaderModuleCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ enum class ShaderStageFlagBits
+ {
+ eVertex = VK_SHADER_STAGE_VERTEX_BIT,
+ eTessellationControl = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
+ eTessellationEvaluation = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
+ eGeometry = VK_SHADER_STAGE_GEOMETRY_BIT,
+ eFragment = VK_SHADER_STAGE_FRAGMENT_BIT,
+ eCompute = VK_SHADER_STAGE_COMPUTE_BIT,
+ eAllGraphics = VK_SHADER_STAGE_ALL_GRAPHICS,
+ eAll = VK_SHADER_STAGE_ALL,
+ eRaygenNV = VK_SHADER_STAGE_RAYGEN_BIT_NV,
+ eAnyHitNV = VK_SHADER_STAGE_ANY_HIT_BIT_NV,
+ eClosestHitNV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV,
+ eMissNV = VK_SHADER_STAGE_MISS_BIT_NV,
+ eIntersectionNV = VK_SHADER_STAGE_INTERSECTION_BIT_NV,
+ eCallableNV = VK_SHADER_STAGE_CALLABLE_BIT_NV,
+ eTaskNV = VK_SHADER_STAGE_TASK_BIT_NV,
+ eMeshNV = VK_SHADER_STAGE_MESH_BIT_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ShaderStageFlagBits value )
+ {
+ switch ( value )
+ {
+ case ShaderStageFlagBits::eVertex : return "Vertex";
+ case ShaderStageFlagBits::eTessellationControl : return "TessellationControl";
+ case ShaderStageFlagBits::eTessellationEvaluation : return "TessellationEvaluation";
+ case ShaderStageFlagBits::eGeometry : return "Geometry";
+ case ShaderStageFlagBits::eFragment : return "Fragment";
+ case ShaderStageFlagBits::eCompute : return "Compute";
+ case ShaderStageFlagBits::eAllGraphics : return "AllGraphics";
+ case ShaderStageFlagBits::eAll : return "All";
+ case ShaderStageFlagBits::eRaygenNV : return "RaygenNV";
+ case ShaderStageFlagBits::eAnyHitNV : return "AnyHitNV";
+ case ShaderStageFlagBits::eClosestHitNV : return "ClosestHitNV";
+ case ShaderStageFlagBits::eMissNV : return "MissNV";
+ case ShaderStageFlagBits::eIntersectionNV : return "IntersectionNV";
+ case ShaderStageFlagBits::eCallableNV : return "CallableNV";
+ case ShaderStageFlagBits::eTaskNV : return "TaskNV";
+ case ShaderStageFlagBits::eMeshNV : return "MeshNV";
+ default: return "invalid";
+ }
+ }
+
+ enum class ShadingRatePaletteEntryNV
+ {
+ eNoInvocations = VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV,
+ e16InvocationsPerPixel = VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV,
+ e8InvocationsPerPixel = VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV,
+ e4InvocationsPerPixel = VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV,
+ e2InvocationsPerPixel = VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV,
+ e1InvocationPerPixel = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV,
+ e1InvocationPer2X1Pixels = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV,
+ e1InvocationPer1X2Pixels = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV,
+ e1InvocationPer2X2Pixels = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV,
+ e1InvocationPer4X2Pixels = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV,
+ e1InvocationPer2X4Pixels = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV,
+ e1InvocationPer4X4Pixels = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ShadingRatePaletteEntryNV value )
+ {
+ switch ( value )
+ {
+ case ShadingRatePaletteEntryNV::eNoInvocations : return "NoInvocations";
+ case ShadingRatePaletteEntryNV::e16InvocationsPerPixel : return "16InvocationsPerPixel";
+ case ShadingRatePaletteEntryNV::e8InvocationsPerPixel : return "8InvocationsPerPixel";
+ case ShadingRatePaletteEntryNV::e4InvocationsPerPixel : return "4InvocationsPerPixel";
+ case ShadingRatePaletteEntryNV::e2InvocationsPerPixel : return "2InvocationsPerPixel";
+ case ShadingRatePaletteEntryNV::e1InvocationPerPixel : return "1InvocationPerPixel";
+ case ShadingRatePaletteEntryNV::e1InvocationPer2X1Pixels : return "1InvocationPer2X1Pixels";
+ case ShadingRatePaletteEntryNV::e1InvocationPer1X2Pixels : return "1InvocationPer1X2Pixels";
+ case ShadingRatePaletteEntryNV::e1InvocationPer2X2Pixels : return "1InvocationPer2X2Pixels";
+ case ShadingRatePaletteEntryNV::e1InvocationPer4X2Pixels : return "1InvocationPer4X2Pixels";
+ case ShadingRatePaletteEntryNV::e1InvocationPer2X4Pixels : return "1InvocationPer2X4Pixels";
+ case ShadingRatePaletteEntryNV::e1InvocationPer4X4Pixels : return "1InvocationPer4X4Pixels";
+ default: return "invalid";
+ }
+ }
+
+ enum class SharingMode
+ {
+ eExclusive = VK_SHARING_MODE_EXCLUSIVE,
+ eConcurrent = VK_SHARING_MODE_CONCURRENT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SharingMode value )
+ {
+ switch ( value )
+ {
+ case SharingMode::eExclusive : return "Exclusive";
+ case SharingMode::eConcurrent : return "Concurrent";
+ default: return "invalid";
+ }
+ }
+
+ enum class SparseImageFormatFlagBits
+ {
+ eSingleMiptail = VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT,
+ eAlignedMipSize = VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT,
+ eNonstandardBlockSize = VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SparseImageFormatFlagBits value )
+ {
+ switch ( value )
+ {
+ case SparseImageFormatFlagBits::eSingleMiptail : return "SingleMiptail";
+ case SparseImageFormatFlagBits::eAlignedMipSize : return "AlignedMipSize";
+ case SparseImageFormatFlagBits::eNonstandardBlockSize : return "NonstandardBlockSize";
+ default: return "invalid";
+ }
+ }
+
+ enum class SparseMemoryBindFlagBits
+ {
+ eMetadata = VK_SPARSE_MEMORY_BIND_METADATA_BIT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SparseMemoryBindFlagBits value )
+ {
+ switch ( value )
+ {
+ case SparseMemoryBindFlagBits::eMetadata : return "Metadata";
+ default: return "invalid";
+ }
+ }
+
+ enum class StencilFaceFlagBits
+ {
+ eFront = VK_STENCIL_FACE_FRONT_BIT,
+ eBack = VK_STENCIL_FACE_BACK_BIT,
+ eFrontAndBack = VK_STENCIL_FACE_FRONT_AND_BACK,
+ eVkStencilFrontAndBack = VK_STENCIL_FRONT_AND_BACK
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( StencilFaceFlagBits value )
+ {
+ switch ( value )
+ {
+ case StencilFaceFlagBits::eFront : return "Front";
+ case StencilFaceFlagBits::eBack : return "Back";
+ case StencilFaceFlagBits::eFrontAndBack : return "FrontAndBack";
+ default: return "invalid";
+ }
+ }
+
+ enum class StencilOp
+ {
+ eKeep = VK_STENCIL_OP_KEEP,
+ eZero = VK_STENCIL_OP_ZERO,
+ eReplace = VK_STENCIL_OP_REPLACE,
+ eIncrementAndClamp = VK_STENCIL_OP_INCREMENT_AND_CLAMP,
+ eDecrementAndClamp = VK_STENCIL_OP_DECREMENT_AND_CLAMP,
+ eInvert = VK_STENCIL_OP_INVERT,
+ eIncrementAndWrap = VK_STENCIL_OP_INCREMENT_AND_WRAP,
+ eDecrementAndWrap = VK_STENCIL_OP_DECREMENT_AND_WRAP
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( StencilOp value )
+ {
+ switch ( value )
+ {
+ case StencilOp::eKeep : return "Keep";
+ case StencilOp::eZero : return "Zero";
+ case StencilOp::eReplace : return "Replace";
+ case StencilOp::eIncrementAndClamp : return "IncrementAndClamp";
+ case StencilOp::eDecrementAndClamp : return "DecrementAndClamp";
+ case StencilOp::eInvert : return "Invert";
+ case StencilOp::eIncrementAndWrap : return "IncrementAndWrap";
+ case StencilOp::eDecrementAndWrap : return "DecrementAndWrap";
+ default: return "invalid";
+ }
+ }
+
+ enum class StructureType
+ {
+ eApplicationInfo = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ eInstanceCreateInfo = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ eDeviceQueueCreateInfo = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ eDeviceCreateInfo = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ eSubmitInfo = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ eMemoryAllocateInfo = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ eMappedMemoryRange = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+ eBindSparseInfo = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO,
+ eFenceCreateInfo = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ eSemaphoreCreateInfo = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+ eEventCreateInfo = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
+ eQueryPoolCreateInfo = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
+ eBufferCreateInfo = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ eBufferViewCreateInfo = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
+ eImageCreateInfo = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ eImageViewCreateInfo = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ eShaderModuleCreateInfo = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ ePipelineCacheCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
+ ePipelineShaderStageCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ ePipelineVertexInputStateCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ ePipelineInputAssemblyStateCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ ePipelineTessellationStateCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
+ ePipelineViewportStateCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+ ePipelineRasterizationStateCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+ ePipelineMultisampleStateCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
+ ePipelineDepthStencilStateCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
+ ePipelineColorBlendStateCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+ ePipelineDynamicStateCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
+ eGraphicsPipelineCreateInfo = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ eComputePipelineCreateInfo = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+ ePipelineLayoutCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ eSamplerCreateInfo = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+ eDescriptorSetLayoutCreateInfo = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ eDescriptorPoolCreateInfo = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ eDescriptorSetAllocateInfo = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ eWriteDescriptorSet = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ eCopyDescriptorSet = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET,
+ eFramebufferCreateInfo = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ eRenderPassCreateInfo = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ eCommandPoolCreateInfo = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ eCommandBufferAllocateInfo = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ eCommandBufferInheritanceInfo = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
+ eCommandBufferBeginInfo = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ eRenderPassBeginInfo = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ eBufferMemoryBarrier = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ eImageMemoryBarrier = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ eMemoryBarrier = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
+ eLoaderInstanceCreateInfo = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO,
+ eLoaderDeviceCreateInfo = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
+ ePhysicalDeviceSubgroupProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES,
+ eBindBufferMemoryInfo = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
+ eBindImageMemoryInfo = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
+ ePhysicalDevice16BitStorageFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES,
+ eMemoryDedicatedRequirements = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
+ eMemoryDedicatedAllocateInfo = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+ eMemoryAllocateFlagsInfo = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
+ eDeviceGroupRenderPassBeginInfo = VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO,
+ eDeviceGroupCommandBufferBeginInfo = VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO,
+ eDeviceGroupSubmitInfo = VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO,
+ eDeviceGroupBindSparseInfo = VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO,
+ eBindBufferMemoryDeviceGroupInfo = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO,
+ eBindImageMemoryDeviceGroupInfo = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO,
+ ePhysicalDeviceGroupProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES,
+ eDeviceGroupDeviceCreateInfo = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO,
+ eBufferMemoryRequirementsInfo2 = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
+ eImageMemoryRequirementsInfo2 = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
+ eImageSparseMemoryRequirementsInfo2 = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2,
+ eMemoryRequirements2 = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
+ eSparseImageMemoryRequirements2 = VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2,
+ ePhysicalDeviceFeatures2 = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
+ ePhysicalDeviceProperties2 = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
+ eFormatProperties2 = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
+ eImageFormatProperties2 = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
+ ePhysicalDeviceImageFormatInfo2 = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+ eQueueFamilyProperties2 = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
+ ePhysicalDeviceMemoryProperties2 = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2,
+ eSparseImageFormatProperties2 = VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2,
+ ePhysicalDeviceSparseImageFormatInfo2 = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2,
+ ePhysicalDevicePointClippingProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES,
+ eRenderPassInputAttachmentAspectCreateInfo = VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO,
+ eImageViewUsageCreateInfo = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
+ ePipelineTessellationDomainOriginStateCreateInfo = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO,
+ eRenderPassMultiviewCreateInfo = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO,
+ ePhysicalDeviceMultiviewFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
+ ePhysicalDeviceMultiviewProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES,
+ ePhysicalDeviceVariablePointersFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES,
+ eProtectedSubmitInfo = VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO,
+ ePhysicalDeviceProtectedMemoryFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
+ ePhysicalDeviceProtectedMemoryProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES,
+ eDeviceQueueInfo2 = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
+ eSamplerYcbcrConversionCreateInfo = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
+ eSamplerYcbcrConversionInfo = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
+ eBindImagePlaneMemoryInfo = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO,
+ eImagePlaneMemoryRequirementsInfo = VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO,
+ ePhysicalDeviceSamplerYcbcrConversionFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
+ eSamplerYcbcrConversionImageFormatProperties = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES,
+ eDescriptorUpdateTemplateCreateInfo = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO,
+ ePhysicalDeviceExternalImageFormatInfo = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
+ eExternalImageFormatProperties = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
+ ePhysicalDeviceExternalBufferInfo = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
+ eExternalBufferProperties = VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
+ ePhysicalDeviceIdProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES,
+ eExternalMemoryBufferCreateInfo = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
+ eExternalMemoryImageCreateInfo = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
+ eExportMemoryAllocateInfo = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
+ ePhysicalDeviceExternalFenceInfo = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
+ eExternalFenceProperties = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
+ eExportFenceCreateInfo = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
+ eExportSemaphoreCreateInfo = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
+ ePhysicalDeviceExternalSemaphoreInfo = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
+ eExternalSemaphoreProperties = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
+ ePhysicalDeviceMaintenance3Properties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES,
+ eDescriptorSetLayoutSupport = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT,
+ ePhysicalDeviceShaderDrawParametersFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES,
+ ePhysicalDeviceVulkan11Features = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
+ ePhysicalDeviceVulkan11Properties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES,
+ ePhysicalDeviceVulkan12Features = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
+ ePhysicalDeviceVulkan12Properties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES,
+ eImageFormatListCreateInfo = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
+ eAttachmentDescription2 = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
+ eAttachmentReference2 = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
+ eSubpassDescription2 = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
+ eSubpassDependency2 = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
+ eRenderPassCreateInfo2 = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
+ eSubpassBeginInfo = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
+ eSubpassEndInfo = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
+ ePhysicalDevice8BitStorageFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES,
+ ePhysicalDeviceDriverProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES,
+ ePhysicalDeviceShaderAtomicInt64Features = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES,
+ ePhysicalDeviceShaderFloat16Int8Features = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES,
+ ePhysicalDeviceFloatControlsProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES,
+ eDescriptorSetLayoutBindingFlagsCreateInfo = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
+ ePhysicalDeviceDescriptorIndexingFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
+ ePhysicalDeviceDescriptorIndexingProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES,
+ eDescriptorSetVariableDescriptorCountAllocateInfo = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO,
+ eDescriptorSetVariableDescriptorCountLayoutSupport = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT,
+ ePhysicalDeviceDepthStencilResolveProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES,
+ eSubpassDescriptionDepthStencilResolve = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,
+ ePhysicalDeviceScalarBlockLayoutFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES,
+ eImageStencilUsageCreateInfo = VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO,
+ ePhysicalDeviceSamplerFilterMinmaxProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES,
+ eSamplerReductionModeCreateInfo = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO,
+ ePhysicalDeviceVulkanMemoryModelFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES,
+ ePhysicalDeviceImagelessFramebufferFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES,
+ eFramebufferAttachmentsCreateInfo = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO,
+ eFramebufferAttachmentImageInfo = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,
+ eRenderPassAttachmentBeginInfo = VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO,
+ ePhysicalDeviceUniformBufferStandardLayoutFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES,
+ ePhysicalDeviceShaderSubgroupExtendedTypesFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES,
+ ePhysicalDeviceSeparateDepthStencilLayoutsFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES,
+ eAttachmentReferenceStencilLayout = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT,
+ eAttachmentDescriptionStencilLayout = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT,
+ ePhysicalDeviceHostQueryResetFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES,
+ ePhysicalDeviceTimelineSemaphoreFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES,
+ ePhysicalDeviceTimelineSemaphoreProperties = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES,
+ eSemaphoreTypeCreateInfo = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
+ eTimelineSemaphoreSubmitInfo = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
+ eSemaphoreWaitInfo = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+ eSemaphoreSignalInfo = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO,
+ ePhysicalDeviceBufferDeviceAddressFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES,
+ eBufferDeviceAddressInfo = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
+ eBufferOpaqueCaptureAddressCreateInfo = VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO,
+ eMemoryOpaqueCaptureAddressAllocateInfo = VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO,
+ eDeviceMemoryOpaqueCaptureAddressInfo = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO,
+ eSwapchainCreateInfoKHR = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+ ePresentInfoKHR = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ eDeviceGroupPresentCapabilitiesKHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR,
+ eImageSwapchainCreateInfoKHR = VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR,
+ eBindImageMemorySwapchainInfoKHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR,
+ eAcquireNextImageInfoKHR = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,
+ eDeviceGroupPresentInfoKHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR,
+ eDeviceGroupSwapchainCreateInfoKHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR,
+ eDisplayModeCreateInfoKHR = VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR,
+ eDisplaySurfaceCreateInfoKHR = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR,
+ eDisplayPresentInfoKHR = VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR,
+ eXlibSurfaceCreateInfoKHR = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
+ eXcbSurfaceCreateInfoKHR = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
+ eWaylandSurfaceCreateInfoKHR = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
+ eAndroidSurfaceCreateInfoKHR = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
+ eWin32SurfaceCreateInfoKHR = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
+ eDebugReportCallbackCreateInfoEXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
+ ePipelineRasterizationStateRasterizationOrderAMD = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD,
+ eDebugMarkerObjectNameInfoEXT = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT,
+ eDebugMarkerObjectTagInfoEXT = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT,
+ eDebugMarkerMarkerInfoEXT = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT,
+ eDedicatedAllocationImageCreateInfoNV = VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV,
+ eDedicatedAllocationBufferCreateInfoNV = VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV,
+ eDedicatedAllocationMemoryAllocateInfoNV = VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV,
+ ePhysicalDeviceTransformFeedbackFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT,
+ ePhysicalDeviceTransformFeedbackPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT,
+ ePipelineRasterizationStateStreamCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT,
+ eImageViewHandleInfoNVX = VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX,
+ eTextureLodGatherFormatPropertiesAMD = VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD,
+ eStreamDescriptorSurfaceCreateInfoGGP = VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP,
+ ePhysicalDeviceCornerSampledImageFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV,
+ eExternalMemoryImageCreateInfoNV = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV,
+ eExportMemoryAllocateInfoNV = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV,
+ eImportMemoryWin32HandleInfoNV = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV,
+ eExportMemoryWin32HandleInfoNV = VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV,
+ eWin32KeyedMutexAcquireReleaseInfoNV = VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV,
+ eValidationFlagsEXT = VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT,
+ eViSurfaceCreateInfoNN = VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN,
+ ePhysicalDeviceTextureCompressionAstcHdrFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT,
+ eImageViewAstcDecodeModeEXT = VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT,
+ ePhysicalDeviceAstcDecodeFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT,
+ eImportMemoryWin32HandleInfoKHR = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
+ eExportMemoryWin32HandleInfoKHR = VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
+ eMemoryWin32HandlePropertiesKHR = VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR,
+ eMemoryGetWin32HandleInfoKHR = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
+ eImportMemoryFdInfoKHR = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
+ eMemoryFdPropertiesKHR = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR,
+ eMemoryGetFdInfoKHR = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
+ eWin32KeyedMutexAcquireReleaseInfoKHR = VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR,
+ eImportSemaphoreWin32HandleInfoKHR = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
+ eExportSemaphoreWin32HandleInfoKHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
+ eD3D12FenceSubmitInfoKHR = VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR,
+ eSemaphoreGetWin32HandleInfoKHR = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
+ eImportSemaphoreFdInfoKHR = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
+ eSemaphoreGetFdInfoKHR = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
+ ePhysicalDevicePushDescriptorPropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR,
+ eCommandBufferInheritanceConditionalRenderingInfoEXT = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT,
+ ePhysicalDeviceConditionalRenderingFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT,
+ eConditionalRenderingBeginInfoEXT = VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT,
+ ePresentRegionsKHR = VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR,
+ eObjectTableCreateInfoNVX = VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX,
+ eIndirectCommandsLayoutCreateInfoNVX = VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX,
+ eCmdProcessCommandsInfoNVX = VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX,
+ eCmdReserveSpaceForCommandsInfoNVX = VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX,
+ eDeviceGeneratedCommandsLimitsNVX = VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX,
+ eDeviceGeneratedCommandsFeaturesNVX = VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX,
+ ePipelineViewportWScalingStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV,
+ eSurfaceCapabilities2EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT,
+ eDisplayPowerInfoEXT = VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT,
+ eDeviceEventInfoEXT = VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT,
+ eDisplayEventInfoEXT = VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT,
+ eSwapchainCounterCreateInfoEXT = VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT,
+ ePresentTimesInfoGOOGLE = VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE,
+ ePhysicalDeviceMultiviewPerViewAttributesPropertiesNVX = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX,
+ ePipelineViewportSwizzleStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV,
+ ePhysicalDeviceDiscardRectanglePropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT,
+ ePipelineDiscardRectangleStateCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT,
+ ePhysicalDeviceConservativeRasterizationPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT,
+ ePipelineRasterizationConservativeStateCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,
+ ePhysicalDeviceDepthClipEnableFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT,
+ ePipelineRasterizationDepthClipStateCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT,
+ eHdrMetadataEXT = VK_STRUCTURE_TYPE_HDR_METADATA_EXT,
+ eSharedPresentSurfaceCapabilitiesKHR = VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR,
+ eImportFenceWin32HandleInfoKHR = VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR,
+ eExportFenceWin32HandleInfoKHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
+ eFenceGetWin32HandleInfoKHR = VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR,
+ eImportFenceFdInfoKHR = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
+ eFenceGetFdInfoKHR = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
+ ePhysicalDevicePerformanceQueryFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR,
+ ePhysicalDevicePerformanceQueryPropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR,
+ eQueryPoolPerformanceCreateInfoKHR = VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR,
+ ePerformanceQuerySubmitInfoKHR = VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR,
+ eAcquireProfilingLockInfoKHR = VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR,
+ ePerformanceCounterKHR = VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR,
+ ePerformanceCounterDescriptionKHR = VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR,
+ ePhysicalDeviceSurfaceInfo2KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
+ eSurfaceCapabilities2KHR = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
+ eSurfaceFormat2KHR = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR,
+ eDisplayProperties2KHR = VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR,
+ eDisplayPlaneProperties2KHR = VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR,
+ eDisplayModeProperties2KHR = VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR,
+ eDisplayPlaneInfo2KHR = VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR,
+ eDisplayPlaneCapabilities2KHR = VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR,
+ eIosSurfaceCreateInfoMVK = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK,
+ eMacosSurfaceCreateInfoMVK = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK,
+ eDebugUtilsObjectNameInfoEXT = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
+ eDebugUtilsObjectTagInfoEXT = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT,
+ eDebugUtilsLabelEXT = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
+ eDebugUtilsMessengerCallbackDataEXT = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT,
+ eDebugUtilsMessengerCreateInfoEXT = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
+ eAndroidHardwareBufferUsageANDROID = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
+ eAndroidHardwareBufferPropertiesANDROID = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
+ eAndroidHardwareBufferFormatPropertiesANDROID = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
+ eImportAndroidHardwareBufferInfoANDROID = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
+ eMemoryGetAndroidHardwareBufferInfoANDROID = VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
+ eExternalFormatANDROID = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
+ ePhysicalDeviceInlineUniformBlockFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT,
+ ePhysicalDeviceInlineUniformBlockPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT,
+ eWriteDescriptorSetInlineUniformBlockEXT = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT,
+ eDescriptorPoolInlineUniformBlockCreateInfoEXT = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT,
+ eSampleLocationsInfoEXT = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
+ eRenderPassSampleLocationsBeginInfoEXT = VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT,
+ ePipelineSampleLocationsStateCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT,
+ ePhysicalDeviceSampleLocationsPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT,
+ eMultisamplePropertiesEXT = VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT,
+ ePhysicalDeviceBlendOperationAdvancedFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT,
+ ePhysicalDeviceBlendOperationAdvancedPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT,
+ ePipelineColorBlendAdvancedStateCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT,
+ ePipelineCoverageToColorStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV,
+ ePipelineCoverageModulationStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV,
+ ePhysicalDeviceShaderSmBuiltinsFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV,
+ ePhysicalDeviceShaderSmBuiltinsPropertiesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV,
+ eDrmFormatModifierPropertiesListEXT = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
+ eDrmFormatModifierPropertiesEXT = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
+ ePhysicalDeviceImageDrmFormatModifierInfoEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
+ eImageDrmFormatModifierListCreateInfoEXT = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
+ eImageDrmFormatModifierExplicitCreateInfoEXT = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
+ eImageDrmFormatModifierPropertiesEXT = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
+ eValidationCacheCreateInfoEXT = VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT,
+ eShaderModuleValidationCacheCreateInfoEXT = VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT,
+ ePipelineViewportShadingRateImageStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV,
+ ePhysicalDeviceShadingRateImageFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV,
+ ePhysicalDeviceShadingRateImagePropertiesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV,
+ ePipelineViewportCoarseSampleOrderStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV,
+ eRayTracingPipelineCreateInfoNV = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV,
+ eAccelerationStructureCreateInfoNV = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV,
+ eGeometryNV = VK_STRUCTURE_TYPE_GEOMETRY_NV,
+ eGeometryTrianglesNV = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV,
+ eGeometryAabbNV = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV,
+ eBindAccelerationStructureMemoryInfoNV = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV,
+ eWriteDescriptorSetAccelerationStructureNV = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV,
+ eAccelerationStructureMemoryRequirementsInfoNV = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV,
+ ePhysicalDeviceRayTracingPropertiesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV,
+ eRayTracingShaderGroupCreateInfoNV = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV,
+ eAccelerationStructureInfoNV = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV,
+ ePhysicalDeviceRepresentativeFragmentTestFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV,
+ ePipelineRepresentativeFragmentTestStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV,
+ ePhysicalDeviceImageViewImageFormatInfoEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT,
+ eFilterCubicImageViewImageFormatPropertiesEXT = VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT,
+ eDeviceQueueGlobalPriorityCreateInfoEXT = VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT,
+ eImportMemoryHostPointerInfoEXT = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
+ eMemoryHostPointerPropertiesEXT = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
+ ePhysicalDeviceExternalMemoryHostPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT,
+ ePhysicalDeviceShaderClockFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR,
+ ePipelineCompilerControlCreateInfoAMD = VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD,
+ eCalibratedTimestampInfoEXT = VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT,
+ ePhysicalDeviceShaderCorePropertiesAMD = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD,
+ eDeviceMemoryOverallocationCreateInfoAMD = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD,
+ ePhysicalDeviceVertexAttributeDivisorPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT,
+ ePipelineVertexInputDivisorStateCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT,
+ ePhysicalDeviceVertexAttributeDivisorFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT,
+ ePresentFrameTokenGGP = VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP,
+ ePipelineCreationFeedbackCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT,
+ ePhysicalDeviceComputeShaderDerivativesFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV,
+ ePhysicalDeviceMeshShaderFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV,
+ ePhysicalDeviceMeshShaderPropertiesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV,
+ ePhysicalDeviceFragmentShaderBarycentricFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV,
+ ePhysicalDeviceShaderImageFootprintFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV,
+ ePipelineViewportExclusiveScissorStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV,
+ ePhysicalDeviceExclusiveScissorFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV,
+ eCheckpointDataNV = VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV,
+ eQueueFamilyCheckpointPropertiesNV = VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV,
+ ePhysicalDeviceShaderIntegerFunctions2FeaturesINTEL = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL,
+ eQueryPoolCreateInfoINTEL = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL,
+ eInitializePerformanceApiInfoINTEL = VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL,
+ ePerformanceMarkerInfoINTEL = VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL,
+ ePerformanceStreamMarkerInfoINTEL = VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL,
+ ePerformanceOverrideInfoINTEL = VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL,
+ ePerformanceConfigurationAcquireInfoINTEL = VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL,
+ ePhysicalDevicePciBusInfoPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT,
+ eDisplayNativeHdrSurfaceCapabilitiesAMD = VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD,
+ eSwapchainDisplayNativeHdrCreateInfoAMD = VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD,
+ eImagepipeSurfaceCreateInfoFUCHSIA = VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA,
+ eMetalSurfaceCreateInfoEXT = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT,
+ ePhysicalDeviceFragmentDensityMapFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT,
+ ePhysicalDeviceFragmentDensityMapPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT,
+ eRenderPassFragmentDensityMapCreateInfoEXT = VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT,
+ ePhysicalDeviceSubgroupSizeControlPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT,
+ ePipelineShaderStageRequiredSubgroupSizeCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT,
+ ePhysicalDeviceSubgroupSizeControlFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT,
+ ePhysicalDeviceShaderCoreProperties2AMD = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD,
+ ePhysicalDeviceCoherentMemoryFeaturesAMD = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD,
+ ePhysicalDeviceMemoryBudgetPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT,
+ ePhysicalDeviceMemoryPriorityFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT,
+ eMemoryPriorityAllocateInfoEXT = VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT,
+ eSurfaceProtectedCapabilitiesKHR = VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR,
+ ePhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV,
+ ePhysicalDeviceBufferDeviceAddressFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT,
+ eBufferDeviceAddressCreateInfoEXT = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT,
+ ePhysicalDeviceToolPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT,
+ eValidationFeaturesEXT = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
+ ePhysicalDeviceCooperativeMatrixFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV,
+ eCooperativeMatrixPropertiesNV = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV,
+ ePhysicalDeviceCooperativeMatrixPropertiesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV,
+ ePhysicalDeviceCoverageReductionModeFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV,
+ ePipelineCoverageReductionStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV,
+ eFramebufferMixedSamplesCombinationNV = VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV,
+ ePhysicalDeviceFragmentShaderInterlockFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT,
+ ePhysicalDeviceYcbcrImageArraysFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT,
+ eSurfaceFullScreenExclusiveInfoEXT = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT,
+ eSurfaceCapabilitiesFullScreenExclusiveEXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT,
+ eSurfaceFullScreenExclusiveWin32InfoEXT = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT,
+ eHeadlessSurfaceCreateInfoEXT = VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT,
+ ePhysicalDeviceLineRasterizationFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT,
+ ePipelineRasterizationLineStateCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT,
+ ePhysicalDeviceLineRasterizationPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT,
+ ePhysicalDeviceIndexTypeUint8FeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT,
+ ePhysicalDevicePipelineExecutablePropertiesFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR,
+ ePipelineInfoKHR = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR,
+ ePipelineExecutablePropertiesKHR = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR,
+ ePipelineExecutableInfoKHR = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR,
+ ePipelineExecutableStatisticKHR = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR,
+ ePipelineExecutableInternalRepresentationKHR = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR,
+ ePhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT,
+ ePhysicalDeviceTexelBufferAlignmentFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT,
+ ePhysicalDeviceTexelBufferAlignmentPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT,
+ ePhysicalDeviceVariablePointerFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES,
+ ePhysicalDeviceShaderDrawParameterFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES,
+ eDebugReportCreateInfoEXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
+ eRenderPassMultiviewCreateInfoKHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR,
+ ePhysicalDeviceMultiviewFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR,
+ ePhysicalDeviceMultiviewPropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR,
+ ePhysicalDeviceFeatures2KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR,
+ ePhysicalDeviceProperties2KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
+ eFormatProperties2KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR,
+ eImageFormatProperties2KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
+ ePhysicalDeviceImageFormatInfo2KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
+ eQueueFamilyProperties2KHR = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR,
+ ePhysicalDeviceMemoryProperties2KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR,
+ eSparseImageFormatProperties2KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR,
+ ePhysicalDeviceSparseImageFormatInfo2KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR,
+ eMemoryAllocateFlagsInfoKHR = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR,
+ eDeviceGroupRenderPassBeginInfoKHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR,
+ eDeviceGroupCommandBufferBeginInfoKHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR,
+ eDeviceGroupSubmitInfoKHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR,
+ eDeviceGroupBindSparseInfoKHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR,
+ eBindBufferMemoryDeviceGroupInfoKHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR,
+ eBindImageMemoryDeviceGroupInfoKHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR,
+ ePhysicalDeviceGroupPropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR,
+ eDeviceGroupDeviceCreateInfoKHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR,
+ ePhysicalDeviceExternalImageFormatInfoKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
+ eExternalImageFormatPropertiesKHR = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
+ ePhysicalDeviceExternalBufferInfoKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
+ eExternalBufferPropertiesKHR = VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
+ ePhysicalDeviceIdPropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR,
+ eExternalMemoryBufferCreateInfoKHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
+ eExternalMemoryImageCreateInfoKHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
+ eExportMemoryAllocateInfoKHR = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
+ ePhysicalDeviceExternalSemaphoreInfoKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
+ eExternalSemaphorePropertiesKHR = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR,
+ eExportSemaphoreCreateInfoKHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR,
+ ePhysicalDeviceShaderFloat16Int8FeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
+ ePhysicalDeviceFloat16Int8FeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR,
+ ePhysicalDevice16BitStorageFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
+ eDescriptorUpdateTemplateCreateInfoKHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
+ ePhysicalDeviceImagelessFramebufferFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR,
+ eFramebufferAttachmentsCreateInfoKHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO_KHR,
+ eFramebufferAttachmentImageInfoKHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO_KHR,
+ eRenderPassAttachmentBeginInfoKHR = VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO_KHR,
+ eAttachmentDescription2KHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR,
+ eAttachmentReference2KHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR,
+ eSubpassDescription2KHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR,
+ eSubpassDependency2KHR = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR,
+ eRenderPassCreateInfo2KHR = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR,
+ eSubpassBeginInfoKHR = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR,
+ eSubpassEndInfoKHR = VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR,
+ ePhysicalDeviceExternalFenceInfoKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR,
+ eExternalFencePropertiesKHR = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR,
+ eExportFenceCreateInfoKHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR,
+ ePhysicalDevicePointClippingPropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR,
+ eRenderPassInputAttachmentAspectCreateInfoKHR = VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR,
+ eImageViewUsageCreateInfoKHR = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,
+ ePipelineTessellationDomainOriginStateCreateInfoKHR = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR,
+ ePhysicalDeviceVariablePointerFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR,
+ ePhysicalDeviceVariablePointersFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR,
+ eMemoryDedicatedRequirementsKHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
+ eMemoryDedicatedAllocateInfoKHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
+ ePhysicalDeviceSamplerFilterMinmaxPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT,
+ eSamplerReductionModeCreateInfoEXT = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT,
+ eBufferMemoryRequirementsInfo2KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR,
+ eImageMemoryRequirementsInfo2KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR,
+ eImageSparseMemoryRequirementsInfo2KHR = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR,
+ eMemoryRequirements2KHR = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
+ eSparseImageMemoryRequirements2KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR,
+ eImageFormatListCreateInfoKHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR,
+ eSamplerYcbcrConversionCreateInfoKHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR,
+ eSamplerYcbcrConversionInfoKHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR,
+ eBindImagePlaneMemoryInfoKHR = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR,
+ eImagePlaneMemoryRequirementsInfoKHR = VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR,
+ ePhysicalDeviceSamplerYcbcrConversionFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR,
+ eSamplerYcbcrConversionImageFormatPropertiesKHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR,
+ eBindBufferMemoryInfoKHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR,
+ eBindImageMemoryInfoKHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR,
+ eDescriptorSetLayoutBindingFlagsCreateInfoEXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT,
+ ePhysicalDeviceDescriptorIndexingFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT,
+ ePhysicalDeviceDescriptorIndexingPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT,
+ eDescriptorSetVariableDescriptorCountAllocateInfoEXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT,
+ eDescriptorSetVariableDescriptorCountLayoutSupportEXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT,
+ ePhysicalDeviceMaintenance3PropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR,
+ eDescriptorSetLayoutSupportKHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR,
+ ePhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR,
+ ePhysicalDevice8BitStorageFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR,
+ ePhysicalDeviceShaderAtomicInt64FeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR,
+ ePhysicalDeviceDriverPropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR,
+ ePhysicalDeviceFloatControlsPropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR,
+ ePhysicalDeviceDepthStencilResolvePropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR,
+ eSubpassDescriptionDepthStencilResolveKHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR,
+ ePhysicalDeviceTimelineSemaphoreFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR,
+ ePhysicalDeviceTimelineSemaphorePropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES_KHR,
+ eSemaphoreTypeCreateInfoKHR = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR,
+ eTimelineSemaphoreSubmitInfoKHR = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR,
+ eSemaphoreWaitInfoKHR = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR,
+ eSemaphoreSignalInfoKHR = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR,
+ ePhysicalDeviceVulkanMemoryModelFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR,
+ ePhysicalDeviceScalarBlockLayoutFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT,
+ ePhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR,
+ eAttachmentReferenceStencilLayoutKHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT_KHR,
+ eAttachmentDescriptionStencilLayoutKHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR,
+ ePhysicalDeviceBufferAddressFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT,
+ eBufferDeviceAddressInfoEXT = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_EXT,
+ eImageStencilUsageCreateInfoEXT = VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT,
+ ePhysicalDeviceUniformBufferStandardLayoutFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR,
+ ePhysicalDeviceBufferDeviceAddressFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR,
+ eBufferDeviceAddressInfoKHR = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR,
+ eBufferOpaqueCaptureAddressCreateInfoKHR = VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO_KHR,
+ eMemoryOpaqueCaptureAddressAllocateInfoKHR = VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO_KHR,
+ eDeviceMemoryOpaqueCaptureAddressInfoKHR = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO_KHR,
+ ePhysicalDeviceHostQueryResetFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( StructureType value )
+ {
+ switch ( value )
+ {
+ case StructureType::eApplicationInfo : return "ApplicationInfo";
+ case StructureType::eInstanceCreateInfo : return "InstanceCreateInfo";
+ case StructureType::eDeviceQueueCreateInfo : return "DeviceQueueCreateInfo";
+ case StructureType::eDeviceCreateInfo : return "DeviceCreateInfo";
+ case StructureType::eSubmitInfo : return "SubmitInfo";
+ case StructureType::eMemoryAllocateInfo : return "MemoryAllocateInfo";
+ case StructureType::eMappedMemoryRange : return "MappedMemoryRange";
+ case StructureType::eBindSparseInfo : return "BindSparseInfo";
+ case StructureType::eFenceCreateInfo : return "FenceCreateInfo";
+ case StructureType::eSemaphoreCreateInfo : return "SemaphoreCreateInfo";
+ case StructureType::eEventCreateInfo : return "EventCreateInfo";
+ case StructureType::eQueryPoolCreateInfo : return "QueryPoolCreateInfo";
+ case StructureType::eBufferCreateInfo : return "BufferCreateInfo";
+ case StructureType::eBufferViewCreateInfo : return "BufferViewCreateInfo";
+ case StructureType::eImageCreateInfo : return "ImageCreateInfo";
+ case StructureType::eImageViewCreateInfo : return "ImageViewCreateInfo";
+ case StructureType::eShaderModuleCreateInfo : return "ShaderModuleCreateInfo";
+ case StructureType::ePipelineCacheCreateInfo : return "PipelineCacheCreateInfo";
+ case StructureType::ePipelineShaderStageCreateInfo : return "PipelineShaderStageCreateInfo";
+ case StructureType::ePipelineVertexInputStateCreateInfo : return "PipelineVertexInputStateCreateInfo";
+ case StructureType::ePipelineInputAssemblyStateCreateInfo : return "PipelineInputAssemblyStateCreateInfo";
+ case StructureType::ePipelineTessellationStateCreateInfo : return "PipelineTessellationStateCreateInfo";
+ case StructureType::ePipelineViewportStateCreateInfo : return "PipelineViewportStateCreateInfo";
+ case StructureType::ePipelineRasterizationStateCreateInfo : return "PipelineRasterizationStateCreateInfo";
+ case StructureType::ePipelineMultisampleStateCreateInfo : return "PipelineMultisampleStateCreateInfo";
+ case StructureType::ePipelineDepthStencilStateCreateInfo : return "PipelineDepthStencilStateCreateInfo";
+ case StructureType::ePipelineColorBlendStateCreateInfo : return "PipelineColorBlendStateCreateInfo";
+ case StructureType::ePipelineDynamicStateCreateInfo : return "PipelineDynamicStateCreateInfo";
+ case StructureType::eGraphicsPipelineCreateInfo : return "GraphicsPipelineCreateInfo";
+ case StructureType::eComputePipelineCreateInfo : return "ComputePipelineCreateInfo";
+ case StructureType::ePipelineLayoutCreateInfo : return "PipelineLayoutCreateInfo";
+ case StructureType::eSamplerCreateInfo : return "SamplerCreateInfo";
+ case StructureType::eDescriptorSetLayoutCreateInfo : return "DescriptorSetLayoutCreateInfo";
+ case StructureType::eDescriptorPoolCreateInfo : return "DescriptorPoolCreateInfo";
+ case StructureType::eDescriptorSetAllocateInfo : return "DescriptorSetAllocateInfo";
+ case StructureType::eWriteDescriptorSet : return "WriteDescriptorSet";
+ case StructureType::eCopyDescriptorSet : return "CopyDescriptorSet";
+ case StructureType::eFramebufferCreateInfo : return "FramebufferCreateInfo";
+ case StructureType::eRenderPassCreateInfo : return "RenderPassCreateInfo";
+ case StructureType::eCommandPoolCreateInfo : return "CommandPoolCreateInfo";
+ case StructureType::eCommandBufferAllocateInfo : return "CommandBufferAllocateInfo";
+ case StructureType::eCommandBufferInheritanceInfo : return "CommandBufferInheritanceInfo";
+ case StructureType::eCommandBufferBeginInfo : return "CommandBufferBeginInfo";
+ case StructureType::eRenderPassBeginInfo : return "RenderPassBeginInfo";
+ case StructureType::eBufferMemoryBarrier : return "BufferMemoryBarrier";
+ case StructureType::eImageMemoryBarrier : return "ImageMemoryBarrier";
+ case StructureType::eMemoryBarrier : return "MemoryBarrier";
+ case StructureType::eLoaderInstanceCreateInfo : return "LoaderInstanceCreateInfo";
+ case StructureType::eLoaderDeviceCreateInfo : return "LoaderDeviceCreateInfo";
+ case StructureType::ePhysicalDeviceSubgroupProperties : return "PhysicalDeviceSubgroupProperties";
+ case StructureType::eBindBufferMemoryInfo : return "BindBufferMemoryInfo";
+ case StructureType::eBindImageMemoryInfo : return "BindImageMemoryInfo";
+ case StructureType::ePhysicalDevice16BitStorageFeatures : return "PhysicalDevice16BitStorageFeatures";
+ case StructureType::eMemoryDedicatedRequirements : return "MemoryDedicatedRequirements";
+ case StructureType::eMemoryDedicatedAllocateInfo : return "MemoryDedicatedAllocateInfo";
+ case StructureType::eMemoryAllocateFlagsInfo : return "MemoryAllocateFlagsInfo";
+ case StructureType::eDeviceGroupRenderPassBeginInfo : return "DeviceGroupRenderPassBeginInfo";
+ case StructureType::eDeviceGroupCommandBufferBeginInfo : return "DeviceGroupCommandBufferBeginInfo";
+ case StructureType::eDeviceGroupSubmitInfo : return "DeviceGroupSubmitInfo";
+ case StructureType::eDeviceGroupBindSparseInfo : return "DeviceGroupBindSparseInfo";
+ case StructureType::eBindBufferMemoryDeviceGroupInfo : return "BindBufferMemoryDeviceGroupInfo";
+ case StructureType::eBindImageMemoryDeviceGroupInfo : return "BindImageMemoryDeviceGroupInfo";
+ case StructureType::ePhysicalDeviceGroupProperties : return "PhysicalDeviceGroupProperties";
+ case StructureType::eDeviceGroupDeviceCreateInfo : return "DeviceGroupDeviceCreateInfo";
+ case StructureType::eBufferMemoryRequirementsInfo2 : return "BufferMemoryRequirementsInfo2";
+ case StructureType::eImageMemoryRequirementsInfo2 : return "ImageMemoryRequirementsInfo2";
+ case StructureType::eImageSparseMemoryRequirementsInfo2 : return "ImageSparseMemoryRequirementsInfo2";
+ case StructureType::eMemoryRequirements2 : return "MemoryRequirements2";
+ case StructureType::eSparseImageMemoryRequirements2 : return "SparseImageMemoryRequirements2";
+ case StructureType::ePhysicalDeviceFeatures2 : return "PhysicalDeviceFeatures2";
+ case StructureType::ePhysicalDeviceProperties2 : return "PhysicalDeviceProperties2";
+ case StructureType::eFormatProperties2 : return "FormatProperties2";
+ case StructureType::eImageFormatProperties2 : return "ImageFormatProperties2";
+ case StructureType::ePhysicalDeviceImageFormatInfo2 : return "PhysicalDeviceImageFormatInfo2";
+ case StructureType::eQueueFamilyProperties2 : return "QueueFamilyProperties2";
+ case StructureType::ePhysicalDeviceMemoryProperties2 : return "PhysicalDeviceMemoryProperties2";
+ case StructureType::eSparseImageFormatProperties2 : return "SparseImageFormatProperties2";
+ case StructureType::ePhysicalDeviceSparseImageFormatInfo2 : return "PhysicalDeviceSparseImageFormatInfo2";
+ case StructureType::ePhysicalDevicePointClippingProperties : return "PhysicalDevicePointClippingProperties";
+ case StructureType::eRenderPassInputAttachmentAspectCreateInfo : return "RenderPassInputAttachmentAspectCreateInfo";
+ case StructureType::eImageViewUsageCreateInfo : return "ImageViewUsageCreateInfo";
+ case StructureType::ePipelineTessellationDomainOriginStateCreateInfo : return "PipelineTessellationDomainOriginStateCreateInfo";
+ case StructureType::eRenderPassMultiviewCreateInfo : return "RenderPassMultiviewCreateInfo";
+ case StructureType::ePhysicalDeviceMultiviewFeatures : return "PhysicalDeviceMultiviewFeatures";
+ case StructureType::ePhysicalDeviceMultiviewProperties : return "PhysicalDeviceMultiviewProperties";
+ case StructureType::ePhysicalDeviceVariablePointersFeatures : return "PhysicalDeviceVariablePointersFeatures";
+ case StructureType::eProtectedSubmitInfo : return "ProtectedSubmitInfo";
+ case StructureType::ePhysicalDeviceProtectedMemoryFeatures : return "PhysicalDeviceProtectedMemoryFeatures";
+ case StructureType::ePhysicalDeviceProtectedMemoryProperties : return "PhysicalDeviceProtectedMemoryProperties";
+ case StructureType::eDeviceQueueInfo2 : return "DeviceQueueInfo2";
+ case StructureType::eSamplerYcbcrConversionCreateInfo : return "SamplerYcbcrConversionCreateInfo";
+ case StructureType::eSamplerYcbcrConversionInfo : return "SamplerYcbcrConversionInfo";
+ case StructureType::eBindImagePlaneMemoryInfo : return "BindImagePlaneMemoryInfo";
+ case StructureType::eImagePlaneMemoryRequirementsInfo : return "ImagePlaneMemoryRequirementsInfo";
+ case StructureType::ePhysicalDeviceSamplerYcbcrConversionFeatures : return "PhysicalDeviceSamplerYcbcrConversionFeatures";
+ case StructureType::eSamplerYcbcrConversionImageFormatProperties : return "SamplerYcbcrConversionImageFormatProperties";
+ case StructureType::eDescriptorUpdateTemplateCreateInfo : return "DescriptorUpdateTemplateCreateInfo";
+ case StructureType::ePhysicalDeviceExternalImageFormatInfo : return "PhysicalDeviceExternalImageFormatInfo";
+ case StructureType::eExternalImageFormatProperties : return "ExternalImageFormatProperties";
+ case StructureType::ePhysicalDeviceExternalBufferInfo : return "PhysicalDeviceExternalBufferInfo";
+ case StructureType::eExternalBufferProperties : return "ExternalBufferProperties";
+ case StructureType::ePhysicalDeviceIdProperties : return "PhysicalDeviceIdProperties";
+ case StructureType::eExternalMemoryBufferCreateInfo : return "ExternalMemoryBufferCreateInfo";
+ case StructureType::eExternalMemoryImageCreateInfo : return "ExternalMemoryImageCreateInfo";
+ case StructureType::eExportMemoryAllocateInfo : return "ExportMemoryAllocateInfo";
+ case StructureType::ePhysicalDeviceExternalFenceInfo : return "PhysicalDeviceExternalFenceInfo";
+ case StructureType::eExternalFenceProperties : return "ExternalFenceProperties";
+ case StructureType::eExportFenceCreateInfo : return "ExportFenceCreateInfo";
+ case StructureType::eExportSemaphoreCreateInfo : return "ExportSemaphoreCreateInfo";
+ case StructureType::ePhysicalDeviceExternalSemaphoreInfo : return "PhysicalDeviceExternalSemaphoreInfo";
+ case StructureType::eExternalSemaphoreProperties : return "ExternalSemaphoreProperties";
+ case StructureType::ePhysicalDeviceMaintenance3Properties : return "PhysicalDeviceMaintenance3Properties";
+ case StructureType::eDescriptorSetLayoutSupport : return "DescriptorSetLayoutSupport";
+ case StructureType::ePhysicalDeviceShaderDrawParametersFeatures : return "PhysicalDeviceShaderDrawParametersFeatures";
+ case StructureType::ePhysicalDeviceVulkan11Features : return "PhysicalDeviceVulkan11Features";
+ case StructureType::ePhysicalDeviceVulkan11Properties : return "PhysicalDeviceVulkan11Properties";
+ case StructureType::ePhysicalDeviceVulkan12Features : return "PhysicalDeviceVulkan12Features";
+ case StructureType::ePhysicalDeviceVulkan12Properties : return "PhysicalDeviceVulkan12Properties";
+ case StructureType::eImageFormatListCreateInfo : return "ImageFormatListCreateInfo";
+ case StructureType::eAttachmentDescription2 : return "AttachmentDescription2";
+ case StructureType::eAttachmentReference2 : return "AttachmentReference2";
+ case StructureType::eSubpassDescription2 : return "SubpassDescription2";
+ case StructureType::eSubpassDependency2 : return "SubpassDependency2";
+ case StructureType::eRenderPassCreateInfo2 : return "RenderPassCreateInfo2";
+ case StructureType::eSubpassBeginInfo : return "SubpassBeginInfo";
+ case StructureType::eSubpassEndInfo : return "SubpassEndInfo";
+ case StructureType::ePhysicalDevice8BitStorageFeatures : return "PhysicalDevice8BitStorageFeatures";
+ case StructureType::ePhysicalDeviceDriverProperties : return "PhysicalDeviceDriverProperties";
+ case StructureType::ePhysicalDeviceShaderAtomicInt64Features : return "PhysicalDeviceShaderAtomicInt64Features";
+ case StructureType::ePhysicalDeviceShaderFloat16Int8Features : return "PhysicalDeviceShaderFloat16Int8Features";
+ case StructureType::ePhysicalDeviceFloatControlsProperties : return "PhysicalDeviceFloatControlsProperties";
+ case StructureType::eDescriptorSetLayoutBindingFlagsCreateInfo : return "DescriptorSetLayoutBindingFlagsCreateInfo";
+ case StructureType::ePhysicalDeviceDescriptorIndexingFeatures : return "PhysicalDeviceDescriptorIndexingFeatures";
+ case StructureType::ePhysicalDeviceDescriptorIndexingProperties : return "PhysicalDeviceDescriptorIndexingProperties";
+ case StructureType::eDescriptorSetVariableDescriptorCountAllocateInfo : return "DescriptorSetVariableDescriptorCountAllocateInfo";
+ case StructureType::eDescriptorSetVariableDescriptorCountLayoutSupport : return "DescriptorSetVariableDescriptorCountLayoutSupport";
+ case StructureType::ePhysicalDeviceDepthStencilResolveProperties : return "PhysicalDeviceDepthStencilResolveProperties";
+ case StructureType::eSubpassDescriptionDepthStencilResolve : return "SubpassDescriptionDepthStencilResolve";
+ case StructureType::ePhysicalDeviceScalarBlockLayoutFeatures : return "PhysicalDeviceScalarBlockLayoutFeatures";
+ case StructureType::eImageStencilUsageCreateInfo : return "ImageStencilUsageCreateInfo";
+ case StructureType::ePhysicalDeviceSamplerFilterMinmaxProperties : return "PhysicalDeviceSamplerFilterMinmaxProperties";
+ case StructureType::eSamplerReductionModeCreateInfo : return "SamplerReductionModeCreateInfo";
+ case StructureType::ePhysicalDeviceVulkanMemoryModelFeatures : return "PhysicalDeviceVulkanMemoryModelFeatures";
+ case StructureType::ePhysicalDeviceImagelessFramebufferFeatures : return "PhysicalDeviceImagelessFramebufferFeatures";
+ case StructureType::eFramebufferAttachmentsCreateInfo : return "FramebufferAttachmentsCreateInfo";
+ case StructureType::eFramebufferAttachmentImageInfo : return "FramebufferAttachmentImageInfo";
+ case StructureType::eRenderPassAttachmentBeginInfo : return "RenderPassAttachmentBeginInfo";
+ case StructureType::ePhysicalDeviceUniformBufferStandardLayoutFeatures : return "PhysicalDeviceUniformBufferStandardLayoutFeatures";
+ case StructureType::ePhysicalDeviceShaderSubgroupExtendedTypesFeatures : return "PhysicalDeviceShaderSubgroupExtendedTypesFeatures";
+ case StructureType::ePhysicalDeviceSeparateDepthStencilLayoutsFeatures : return "PhysicalDeviceSeparateDepthStencilLayoutsFeatures";
+ case StructureType::eAttachmentReferenceStencilLayout : return "AttachmentReferenceStencilLayout";
+ case StructureType::eAttachmentDescriptionStencilLayout : return "AttachmentDescriptionStencilLayout";
+ case StructureType::ePhysicalDeviceHostQueryResetFeatures : return "PhysicalDeviceHostQueryResetFeatures";
+ case StructureType::ePhysicalDeviceTimelineSemaphoreFeatures : return "PhysicalDeviceTimelineSemaphoreFeatures";
+ case StructureType::ePhysicalDeviceTimelineSemaphoreProperties : return "PhysicalDeviceTimelineSemaphoreProperties";
+ case StructureType::eSemaphoreTypeCreateInfo : return "SemaphoreTypeCreateInfo";
+ case StructureType::eTimelineSemaphoreSubmitInfo : return "TimelineSemaphoreSubmitInfo";
+ case StructureType::eSemaphoreWaitInfo : return "SemaphoreWaitInfo";
+ case StructureType::eSemaphoreSignalInfo : return "SemaphoreSignalInfo";
+ case StructureType::ePhysicalDeviceBufferDeviceAddressFeatures : return "PhysicalDeviceBufferDeviceAddressFeatures";
+ case StructureType::eBufferDeviceAddressInfo : return "BufferDeviceAddressInfo";
+ case StructureType::eBufferOpaqueCaptureAddressCreateInfo : return "BufferOpaqueCaptureAddressCreateInfo";
+ case StructureType::eMemoryOpaqueCaptureAddressAllocateInfo : return "MemoryOpaqueCaptureAddressAllocateInfo";
+ case StructureType::eDeviceMemoryOpaqueCaptureAddressInfo : return "DeviceMemoryOpaqueCaptureAddressInfo";
+ case StructureType::eSwapchainCreateInfoKHR : return "SwapchainCreateInfoKHR";
+ case StructureType::ePresentInfoKHR : return "PresentInfoKHR";
+ case StructureType::eDeviceGroupPresentCapabilitiesKHR : return "DeviceGroupPresentCapabilitiesKHR";
+ case StructureType::eImageSwapchainCreateInfoKHR : return "ImageSwapchainCreateInfoKHR";
+ case StructureType::eBindImageMemorySwapchainInfoKHR : return "BindImageMemorySwapchainInfoKHR";
+ case StructureType::eAcquireNextImageInfoKHR : return "AcquireNextImageInfoKHR";
+ case StructureType::eDeviceGroupPresentInfoKHR : return "DeviceGroupPresentInfoKHR";
+ case StructureType::eDeviceGroupSwapchainCreateInfoKHR : return "DeviceGroupSwapchainCreateInfoKHR";
+ case StructureType::eDisplayModeCreateInfoKHR : return "DisplayModeCreateInfoKHR";
+ case StructureType::eDisplaySurfaceCreateInfoKHR : return "DisplaySurfaceCreateInfoKHR";
+ case StructureType::eDisplayPresentInfoKHR : return "DisplayPresentInfoKHR";
+ case StructureType::eXlibSurfaceCreateInfoKHR : return "XlibSurfaceCreateInfoKHR";
+ case StructureType::eXcbSurfaceCreateInfoKHR : return "XcbSurfaceCreateInfoKHR";
+ case StructureType::eWaylandSurfaceCreateInfoKHR : return "WaylandSurfaceCreateInfoKHR";
+ case StructureType::eAndroidSurfaceCreateInfoKHR : return "AndroidSurfaceCreateInfoKHR";
+ case StructureType::eWin32SurfaceCreateInfoKHR : return "Win32SurfaceCreateInfoKHR";
+ case StructureType::eDebugReportCallbackCreateInfoEXT : return "DebugReportCallbackCreateInfoEXT";
+ case StructureType::ePipelineRasterizationStateRasterizationOrderAMD : return "PipelineRasterizationStateRasterizationOrderAMD";
+ case StructureType::eDebugMarkerObjectNameInfoEXT : return "DebugMarkerObjectNameInfoEXT";
+ case StructureType::eDebugMarkerObjectTagInfoEXT : return "DebugMarkerObjectTagInfoEXT";
+ case StructureType::eDebugMarkerMarkerInfoEXT : return "DebugMarkerMarkerInfoEXT";
+ case StructureType::eDedicatedAllocationImageCreateInfoNV : return "DedicatedAllocationImageCreateInfoNV";
+ case StructureType::eDedicatedAllocationBufferCreateInfoNV : return "DedicatedAllocationBufferCreateInfoNV";
+ case StructureType::eDedicatedAllocationMemoryAllocateInfoNV : return "DedicatedAllocationMemoryAllocateInfoNV";
+ case StructureType::ePhysicalDeviceTransformFeedbackFeaturesEXT : return "PhysicalDeviceTransformFeedbackFeaturesEXT";
+ case StructureType::ePhysicalDeviceTransformFeedbackPropertiesEXT : return "PhysicalDeviceTransformFeedbackPropertiesEXT";
+ case StructureType::ePipelineRasterizationStateStreamCreateInfoEXT : return "PipelineRasterizationStateStreamCreateInfoEXT";
+ case StructureType::eImageViewHandleInfoNVX : return "ImageViewHandleInfoNVX";
+ case StructureType::eTextureLodGatherFormatPropertiesAMD : return "TextureLodGatherFormatPropertiesAMD";
+ case StructureType::eStreamDescriptorSurfaceCreateInfoGGP : return "StreamDescriptorSurfaceCreateInfoGGP";
+ case StructureType::ePhysicalDeviceCornerSampledImageFeaturesNV : return "PhysicalDeviceCornerSampledImageFeaturesNV";
+ case StructureType::eExternalMemoryImageCreateInfoNV : return "ExternalMemoryImageCreateInfoNV";
+ case StructureType::eExportMemoryAllocateInfoNV : return "ExportMemoryAllocateInfoNV";
+ case StructureType::eImportMemoryWin32HandleInfoNV : return "ImportMemoryWin32HandleInfoNV";
+ case StructureType::eExportMemoryWin32HandleInfoNV : return "ExportMemoryWin32HandleInfoNV";
+ case StructureType::eWin32KeyedMutexAcquireReleaseInfoNV : return "Win32KeyedMutexAcquireReleaseInfoNV";
+ case StructureType::eValidationFlagsEXT : return "ValidationFlagsEXT";
+ case StructureType::eViSurfaceCreateInfoNN : return "ViSurfaceCreateInfoNN";
+ case StructureType::ePhysicalDeviceTextureCompressionAstcHdrFeaturesEXT : return "PhysicalDeviceTextureCompressionAstcHdrFeaturesEXT";
+ case StructureType::eImageViewAstcDecodeModeEXT : return "ImageViewAstcDecodeModeEXT";
+ case StructureType::ePhysicalDeviceAstcDecodeFeaturesEXT : return "PhysicalDeviceAstcDecodeFeaturesEXT";
+ case StructureType::eImportMemoryWin32HandleInfoKHR : return "ImportMemoryWin32HandleInfoKHR";
+ case StructureType::eExportMemoryWin32HandleInfoKHR : return "ExportMemoryWin32HandleInfoKHR";
+ case StructureType::eMemoryWin32HandlePropertiesKHR : return "MemoryWin32HandlePropertiesKHR";
+ case StructureType::eMemoryGetWin32HandleInfoKHR : return "MemoryGetWin32HandleInfoKHR";
+ case StructureType::eImportMemoryFdInfoKHR : return "ImportMemoryFdInfoKHR";
+ case StructureType::eMemoryFdPropertiesKHR : return "MemoryFdPropertiesKHR";
+ case StructureType::eMemoryGetFdInfoKHR : return "MemoryGetFdInfoKHR";
+ case StructureType::eWin32KeyedMutexAcquireReleaseInfoKHR : return "Win32KeyedMutexAcquireReleaseInfoKHR";
+ case StructureType::eImportSemaphoreWin32HandleInfoKHR : return "ImportSemaphoreWin32HandleInfoKHR";
+ case StructureType::eExportSemaphoreWin32HandleInfoKHR : return "ExportSemaphoreWin32HandleInfoKHR";
+ case StructureType::eD3D12FenceSubmitInfoKHR : return "D3D12FenceSubmitInfoKHR";
+ case StructureType::eSemaphoreGetWin32HandleInfoKHR : return "SemaphoreGetWin32HandleInfoKHR";
+ case StructureType::eImportSemaphoreFdInfoKHR : return "ImportSemaphoreFdInfoKHR";
+ case StructureType::eSemaphoreGetFdInfoKHR : return "SemaphoreGetFdInfoKHR";
+ case StructureType::ePhysicalDevicePushDescriptorPropertiesKHR : return "PhysicalDevicePushDescriptorPropertiesKHR";
+ case StructureType::eCommandBufferInheritanceConditionalRenderingInfoEXT : return "CommandBufferInheritanceConditionalRenderingInfoEXT";
+ case StructureType::ePhysicalDeviceConditionalRenderingFeaturesEXT : return "PhysicalDeviceConditionalRenderingFeaturesEXT";
+ case StructureType::eConditionalRenderingBeginInfoEXT : return "ConditionalRenderingBeginInfoEXT";
+ case StructureType::ePresentRegionsKHR : return "PresentRegionsKHR";
+ case StructureType::eObjectTableCreateInfoNVX : return "ObjectTableCreateInfoNVX";
+ case StructureType::eIndirectCommandsLayoutCreateInfoNVX : return "IndirectCommandsLayoutCreateInfoNVX";
+ case StructureType::eCmdProcessCommandsInfoNVX : return "CmdProcessCommandsInfoNVX";
+ case StructureType::eCmdReserveSpaceForCommandsInfoNVX : return "CmdReserveSpaceForCommandsInfoNVX";
+ case StructureType::eDeviceGeneratedCommandsLimitsNVX : return "DeviceGeneratedCommandsLimitsNVX";
+ case StructureType::eDeviceGeneratedCommandsFeaturesNVX : return "DeviceGeneratedCommandsFeaturesNVX";
+ case StructureType::ePipelineViewportWScalingStateCreateInfoNV : return "PipelineViewportWScalingStateCreateInfoNV";
+ case StructureType::eSurfaceCapabilities2EXT : return "SurfaceCapabilities2EXT";
+ case StructureType::eDisplayPowerInfoEXT : return "DisplayPowerInfoEXT";
+ case StructureType::eDeviceEventInfoEXT : return "DeviceEventInfoEXT";
+ case StructureType::eDisplayEventInfoEXT : return "DisplayEventInfoEXT";
+ case StructureType::eSwapchainCounterCreateInfoEXT : return "SwapchainCounterCreateInfoEXT";
+ case StructureType::ePresentTimesInfoGOOGLE : return "PresentTimesInfoGOOGLE";
+ case StructureType::ePhysicalDeviceMultiviewPerViewAttributesPropertiesNVX : return "PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX";
+ case StructureType::ePipelineViewportSwizzleStateCreateInfoNV : return "PipelineViewportSwizzleStateCreateInfoNV";
+ case StructureType::ePhysicalDeviceDiscardRectanglePropertiesEXT : return "PhysicalDeviceDiscardRectanglePropertiesEXT";
+ case StructureType::ePipelineDiscardRectangleStateCreateInfoEXT : return "PipelineDiscardRectangleStateCreateInfoEXT";
+ case StructureType::ePhysicalDeviceConservativeRasterizationPropertiesEXT : return "PhysicalDeviceConservativeRasterizationPropertiesEXT";
+ case StructureType::ePipelineRasterizationConservativeStateCreateInfoEXT : return "PipelineRasterizationConservativeStateCreateInfoEXT";
+ case StructureType::ePhysicalDeviceDepthClipEnableFeaturesEXT : return "PhysicalDeviceDepthClipEnableFeaturesEXT";
+ case StructureType::ePipelineRasterizationDepthClipStateCreateInfoEXT : return "PipelineRasterizationDepthClipStateCreateInfoEXT";
+ case StructureType::eHdrMetadataEXT : return "HdrMetadataEXT";
+ case StructureType::eSharedPresentSurfaceCapabilitiesKHR : return "SharedPresentSurfaceCapabilitiesKHR";
+ case StructureType::eImportFenceWin32HandleInfoKHR : return "ImportFenceWin32HandleInfoKHR";
+ case StructureType::eExportFenceWin32HandleInfoKHR : return "ExportFenceWin32HandleInfoKHR";
+ case StructureType::eFenceGetWin32HandleInfoKHR : return "FenceGetWin32HandleInfoKHR";
+ case StructureType::eImportFenceFdInfoKHR : return "ImportFenceFdInfoKHR";
+ case StructureType::eFenceGetFdInfoKHR : return "FenceGetFdInfoKHR";
+ case StructureType::ePhysicalDevicePerformanceQueryFeaturesKHR : return "PhysicalDevicePerformanceQueryFeaturesKHR";
+ case StructureType::ePhysicalDevicePerformanceQueryPropertiesKHR : return "PhysicalDevicePerformanceQueryPropertiesKHR";
+ case StructureType::eQueryPoolPerformanceCreateInfoKHR : return "QueryPoolPerformanceCreateInfoKHR";
+ case StructureType::ePerformanceQuerySubmitInfoKHR : return "PerformanceQuerySubmitInfoKHR";
+ case StructureType::eAcquireProfilingLockInfoKHR : return "AcquireProfilingLockInfoKHR";
+ case StructureType::ePerformanceCounterKHR : return "PerformanceCounterKHR";
+ case StructureType::ePerformanceCounterDescriptionKHR : return "PerformanceCounterDescriptionKHR";
+ case StructureType::ePhysicalDeviceSurfaceInfo2KHR : return "PhysicalDeviceSurfaceInfo2KHR";
+ case StructureType::eSurfaceCapabilities2KHR : return "SurfaceCapabilities2KHR";
+ case StructureType::eSurfaceFormat2KHR : return "SurfaceFormat2KHR";
+ case StructureType::eDisplayProperties2KHR : return "DisplayProperties2KHR";
+ case StructureType::eDisplayPlaneProperties2KHR : return "DisplayPlaneProperties2KHR";
+ case StructureType::eDisplayModeProperties2KHR : return "DisplayModeProperties2KHR";
+ case StructureType::eDisplayPlaneInfo2KHR : return "DisplayPlaneInfo2KHR";
+ case StructureType::eDisplayPlaneCapabilities2KHR : return "DisplayPlaneCapabilities2KHR";
+ case StructureType::eIosSurfaceCreateInfoMVK : return "IosSurfaceCreateInfoMVK";
+ case StructureType::eMacosSurfaceCreateInfoMVK : return "MacosSurfaceCreateInfoMVK";
+ case StructureType::eDebugUtilsObjectNameInfoEXT : return "DebugUtilsObjectNameInfoEXT";
+ case StructureType::eDebugUtilsObjectTagInfoEXT : return "DebugUtilsObjectTagInfoEXT";
+ case StructureType::eDebugUtilsLabelEXT : return "DebugUtilsLabelEXT";
+ case StructureType::eDebugUtilsMessengerCallbackDataEXT : return "DebugUtilsMessengerCallbackDataEXT";
+ case StructureType::eDebugUtilsMessengerCreateInfoEXT : return "DebugUtilsMessengerCreateInfoEXT";
+ case StructureType::eAndroidHardwareBufferUsageANDROID : return "AndroidHardwareBufferUsageANDROID";
+ case StructureType::eAndroidHardwareBufferPropertiesANDROID : return "AndroidHardwareBufferPropertiesANDROID";
+ case StructureType::eAndroidHardwareBufferFormatPropertiesANDROID : return "AndroidHardwareBufferFormatPropertiesANDROID";
+ case StructureType::eImportAndroidHardwareBufferInfoANDROID : return "ImportAndroidHardwareBufferInfoANDROID";
+ case StructureType::eMemoryGetAndroidHardwareBufferInfoANDROID : return "MemoryGetAndroidHardwareBufferInfoANDROID";
+ case StructureType::eExternalFormatANDROID : return "ExternalFormatANDROID";
+ case StructureType::ePhysicalDeviceInlineUniformBlockFeaturesEXT : return "PhysicalDeviceInlineUniformBlockFeaturesEXT";
+ case StructureType::ePhysicalDeviceInlineUniformBlockPropertiesEXT : return "PhysicalDeviceInlineUniformBlockPropertiesEXT";
+ case StructureType::eWriteDescriptorSetInlineUniformBlockEXT : return "WriteDescriptorSetInlineUniformBlockEXT";
+ case StructureType::eDescriptorPoolInlineUniformBlockCreateInfoEXT : return "DescriptorPoolInlineUniformBlockCreateInfoEXT";
+ case StructureType::eSampleLocationsInfoEXT : return "SampleLocationsInfoEXT";
+ case StructureType::eRenderPassSampleLocationsBeginInfoEXT : return "RenderPassSampleLocationsBeginInfoEXT";
+ case StructureType::ePipelineSampleLocationsStateCreateInfoEXT : return "PipelineSampleLocationsStateCreateInfoEXT";
+ case StructureType::ePhysicalDeviceSampleLocationsPropertiesEXT : return "PhysicalDeviceSampleLocationsPropertiesEXT";
+ case StructureType::eMultisamplePropertiesEXT : return "MultisamplePropertiesEXT";
+ case StructureType::ePhysicalDeviceBlendOperationAdvancedFeaturesEXT : return "PhysicalDeviceBlendOperationAdvancedFeaturesEXT";
+ case StructureType::ePhysicalDeviceBlendOperationAdvancedPropertiesEXT : return "PhysicalDeviceBlendOperationAdvancedPropertiesEXT";
+ case StructureType::ePipelineColorBlendAdvancedStateCreateInfoEXT : return "PipelineColorBlendAdvancedStateCreateInfoEXT";
+ case StructureType::ePipelineCoverageToColorStateCreateInfoNV : return "PipelineCoverageToColorStateCreateInfoNV";
+ case StructureType::ePipelineCoverageModulationStateCreateInfoNV : return "PipelineCoverageModulationStateCreateInfoNV";
+ case StructureType::ePhysicalDeviceShaderSmBuiltinsFeaturesNV : return "PhysicalDeviceShaderSmBuiltinsFeaturesNV";
+ case StructureType::ePhysicalDeviceShaderSmBuiltinsPropertiesNV : return "PhysicalDeviceShaderSmBuiltinsPropertiesNV";
+ case StructureType::eDrmFormatModifierPropertiesListEXT : return "DrmFormatModifierPropertiesListEXT";
+ case StructureType::eDrmFormatModifierPropertiesEXT : return "DrmFormatModifierPropertiesEXT";
+ case StructureType::ePhysicalDeviceImageDrmFormatModifierInfoEXT : return "PhysicalDeviceImageDrmFormatModifierInfoEXT";
+ case StructureType::eImageDrmFormatModifierListCreateInfoEXT : return "ImageDrmFormatModifierListCreateInfoEXT";
+ case StructureType::eImageDrmFormatModifierExplicitCreateInfoEXT : return "ImageDrmFormatModifierExplicitCreateInfoEXT";
+ case StructureType::eImageDrmFormatModifierPropertiesEXT : return "ImageDrmFormatModifierPropertiesEXT";
+ case StructureType::eValidationCacheCreateInfoEXT : return "ValidationCacheCreateInfoEXT";
+ case StructureType::eShaderModuleValidationCacheCreateInfoEXT : return "ShaderModuleValidationCacheCreateInfoEXT";
+ case StructureType::ePipelineViewportShadingRateImageStateCreateInfoNV : return "PipelineViewportShadingRateImageStateCreateInfoNV";
+ case StructureType::ePhysicalDeviceShadingRateImageFeaturesNV : return "PhysicalDeviceShadingRateImageFeaturesNV";
+ case StructureType::ePhysicalDeviceShadingRateImagePropertiesNV : return "PhysicalDeviceShadingRateImagePropertiesNV";
+ case StructureType::ePipelineViewportCoarseSampleOrderStateCreateInfoNV : return "PipelineViewportCoarseSampleOrderStateCreateInfoNV";
+ case StructureType::eRayTracingPipelineCreateInfoNV : return "RayTracingPipelineCreateInfoNV";
+ case StructureType::eAccelerationStructureCreateInfoNV : return "AccelerationStructureCreateInfoNV";
+ case StructureType::eGeometryNV : return "GeometryNV";
+ case StructureType::eGeometryTrianglesNV : return "GeometryTrianglesNV";
+ case StructureType::eGeometryAabbNV : return "GeometryAabbNV";
+ case StructureType::eBindAccelerationStructureMemoryInfoNV : return "BindAccelerationStructureMemoryInfoNV";
+ case StructureType::eWriteDescriptorSetAccelerationStructureNV : return "WriteDescriptorSetAccelerationStructureNV";
+ case StructureType::eAccelerationStructureMemoryRequirementsInfoNV : return "AccelerationStructureMemoryRequirementsInfoNV";
+ case StructureType::ePhysicalDeviceRayTracingPropertiesNV : return "PhysicalDeviceRayTracingPropertiesNV";
+ case StructureType::eRayTracingShaderGroupCreateInfoNV : return "RayTracingShaderGroupCreateInfoNV";
+ case StructureType::eAccelerationStructureInfoNV : return "AccelerationStructureInfoNV";
+ case StructureType::ePhysicalDeviceRepresentativeFragmentTestFeaturesNV : return "PhysicalDeviceRepresentativeFragmentTestFeaturesNV";
+ case StructureType::ePipelineRepresentativeFragmentTestStateCreateInfoNV : return "PipelineRepresentativeFragmentTestStateCreateInfoNV";
+ case StructureType::ePhysicalDeviceImageViewImageFormatInfoEXT : return "PhysicalDeviceImageViewImageFormatInfoEXT";
+ case StructureType::eFilterCubicImageViewImageFormatPropertiesEXT : return "FilterCubicImageViewImageFormatPropertiesEXT";
+ case StructureType::eDeviceQueueGlobalPriorityCreateInfoEXT : return "DeviceQueueGlobalPriorityCreateInfoEXT";
+ case StructureType::eImportMemoryHostPointerInfoEXT : return "ImportMemoryHostPointerInfoEXT";
+ case StructureType::eMemoryHostPointerPropertiesEXT : return "MemoryHostPointerPropertiesEXT";
+ case StructureType::ePhysicalDeviceExternalMemoryHostPropertiesEXT : return "PhysicalDeviceExternalMemoryHostPropertiesEXT";
+ case StructureType::ePhysicalDeviceShaderClockFeaturesKHR : return "PhysicalDeviceShaderClockFeaturesKHR";
+ case StructureType::ePipelineCompilerControlCreateInfoAMD : return "PipelineCompilerControlCreateInfoAMD";
+ case StructureType::eCalibratedTimestampInfoEXT : return "CalibratedTimestampInfoEXT";
+ case StructureType::ePhysicalDeviceShaderCorePropertiesAMD : return "PhysicalDeviceShaderCorePropertiesAMD";
+ case StructureType::eDeviceMemoryOverallocationCreateInfoAMD : return "DeviceMemoryOverallocationCreateInfoAMD";
+ case StructureType::ePhysicalDeviceVertexAttributeDivisorPropertiesEXT : return "PhysicalDeviceVertexAttributeDivisorPropertiesEXT";
+ case StructureType::ePipelineVertexInputDivisorStateCreateInfoEXT : return "PipelineVertexInputDivisorStateCreateInfoEXT";
+ case StructureType::ePhysicalDeviceVertexAttributeDivisorFeaturesEXT : return "PhysicalDeviceVertexAttributeDivisorFeaturesEXT";
+ case StructureType::ePresentFrameTokenGGP : return "PresentFrameTokenGGP";
+ case StructureType::ePipelineCreationFeedbackCreateInfoEXT : return "PipelineCreationFeedbackCreateInfoEXT";
+ case StructureType::ePhysicalDeviceComputeShaderDerivativesFeaturesNV : return "PhysicalDeviceComputeShaderDerivativesFeaturesNV";
+ case StructureType::ePhysicalDeviceMeshShaderFeaturesNV : return "PhysicalDeviceMeshShaderFeaturesNV";
+ case StructureType::ePhysicalDeviceMeshShaderPropertiesNV : return "PhysicalDeviceMeshShaderPropertiesNV";
+ case StructureType::ePhysicalDeviceFragmentShaderBarycentricFeaturesNV : return "PhysicalDeviceFragmentShaderBarycentricFeaturesNV";
+ case StructureType::ePhysicalDeviceShaderImageFootprintFeaturesNV : return "PhysicalDeviceShaderImageFootprintFeaturesNV";
+ case StructureType::ePipelineViewportExclusiveScissorStateCreateInfoNV : return "PipelineViewportExclusiveScissorStateCreateInfoNV";
+ case StructureType::ePhysicalDeviceExclusiveScissorFeaturesNV : return "PhysicalDeviceExclusiveScissorFeaturesNV";
+ case StructureType::eCheckpointDataNV : return "CheckpointDataNV";
+ case StructureType::eQueueFamilyCheckpointPropertiesNV : return "QueueFamilyCheckpointPropertiesNV";
+ case StructureType::ePhysicalDeviceShaderIntegerFunctions2FeaturesINTEL : return "PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL";
+ case StructureType::eQueryPoolCreateInfoINTEL : return "QueryPoolCreateInfoINTEL";
+ case StructureType::eInitializePerformanceApiInfoINTEL : return "InitializePerformanceApiInfoINTEL";
+ case StructureType::ePerformanceMarkerInfoINTEL : return "PerformanceMarkerInfoINTEL";
+ case StructureType::ePerformanceStreamMarkerInfoINTEL : return "PerformanceStreamMarkerInfoINTEL";
+ case StructureType::ePerformanceOverrideInfoINTEL : return "PerformanceOverrideInfoINTEL";
+ case StructureType::ePerformanceConfigurationAcquireInfoINTEL : return "PerformanceConfigurationAcquireInfoINTEL";
+ case StructureType::ePhysicalDevicePciBusInfoPropertiesEXT : return "PhysicalDevicePciBusInfoPropertiesEXT";
+ case StructureType::eDisplayNativeHdrSurfaceCapabilitiesAMD : return "DisplayNativeHdrSurfaceCapabilitiesAMD";
+ case StructureType::eSwapchainDisplayNativeHdrCreateInfoAMD : return "SwapchainDisplayNativeHdrCreateInfoAMD";
+ case StructureType::eImagepipeSurfaceCreateInfoFUCHSIA : return "ImagepipeSurfaceCreateInfoFUCHSIA";
+ case StructureType::eMetalSurfaceCreateInfoEXT : return "MetalSurfaceCreateInfoEXT";
+ case StructureType::ePhysicalDeviceFragmentDensityMapFeaturesEXT : return "PhysicalDeviceFragmentDensityMapFeaturesEXT";
+ case StructureType::ePhysicalDeviceFragmentDensityMapPropertiesEXT : return "PhysicalDeviceFragmentDensityMapPropertiesEXT";
+ case StructureType::eRenderPassFragmentDensityMapCreateInfoEXT : return "RenderPassFragmentDensityMapCreateInfoEXT";
+ case StructureType::ePhysicalDeviceSubgroupSizeControlPropertiesEXT : return "PhysicalDeviceSubgroupSizeControlPropertiesEXT";
+ case StructureType::ePipelineShaderStageRequiredSubgroupSizeCreateInfoEXT : return "PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT";
+ case StructureType::ePhysicalDeviceSubgroupSizeControlFeaturesEXT : return "PhysicalDeviceSubgroupSizeControlFeaturesEXT";
+ case StructureType::ePhysicalDeviceShaderCoreProperties2AMD : return "PhysicalDeviceShaderCoreProperties2AMD";
+ case StructureType::ePhysicalDeviceCoherentMemoryFeaturesAMD : return "PhysicalDeviceCoherentMemoryFeaturesAMD";
+ case StructureType::ePhysicalDeviceMemoryBudgetPropertiesEXT : return "PhysicalDeviceMemoryBudgetPropertiesEXT";
+ case StructureType::ePhysicalDeviceMemoryPriorityFeaturesEXT : return "PhysicalDeviceMemoryPriorityFeaturesEXT";
+ case StructureType::eMemoryPriorityAllocateInfoEXT : return "MemoryPriorityAllocateInfoEXT";
+ case StructureType::eSurfaceProtectedCapabilitiesKHR : return "SurfaceProtectedCapabilitiesKHR";
+ case StructureType::ePhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV : return "PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV";
+ case StructureType::ePhysicalDeviceBufferDeviceAddressFeaturesEXT : return "PhysicalDeviceBufferDeviceAddressFeaturesEXT";
+ case StructureType::eBufferDeviceAddressCreateInfoEXT : return "BufferDeviceAddressCreateInfoEXT";
+ case StructureType::ePhysicalDeviceToolPropertiesEXT : return "PhysicalDeviceToolPropertiesEXT";
+ case StructureType::eValidationFeaturesEXT : return "ValidationFeaturesEXT";
+ case StructureType::ePhysicalDeviceCooperativeMatrixFeaturesNV : return "PhysicalDeviceCooperativeMatrixFeaturesNV";
+ case StructureType::eCooperativeMatrixPropertiesNV : return "CooperativeMatrixPropertiesNV";
+ case StructureType::ePhysicalDeviceCooperativeMatrixPropertiesNV : return "PhysicalDeviceCooperativeMatrixPropertiesNV";
+ case StructureType::ePhysicalDeviceCoverageReductionModeFeaturesNV : return "PhysicalDeviceCoverageReductionModeFeaturesNV";
+ case StructureType::ePipelineCoverageReductionStateCreateInfoNV : return "PipelineCoverageReductionStateCreateInfoNV";
+ case StructureType::eFramebufferMixedSamplesCombinationNV : return "FramebufferMixedSamplesCombinationNV";
+ case StructureType::ePhysicalDeviceFragmentShaderInterlockFeaturesEXT : return "PhysicalDeviceFragmentShaderInterlockFeaturesEXT";
+ case StructureType::ePhysicalDeviceYcbcrImageArraysFeaturesEXT : return "PhysicalDeviceYcbcrImageArraysFeaturesEXT";
+ case StructureType::eSurfaceFullScreenExclusiveInfoEXT : return "SurfaceFullScreenExclusiveInfoEXT";
+ case StructureType::eSurfaceCapabilitiesFullScreenExclusiveEXT : return "SurfaceCapabilitiesFullScreenExclusiveEXT";
+ case StructureType::eSurfaceFullScreenExclusiveWin32InfoEXT : return "SurfaceFullScreenExclusiveWin32InfoEXT";
+ case StructureType::eHeadlessSurfaceCreateInfoEXT : return "HeadlessSurfaceCreateInfoEXT";
+ case StructureType::ePhysicalDeviceLineRasterizationFeaturesEXT : return "PhysicalDeviceLineRasterizationFeaturesEXT";
+ case StructureType::ePipelineRasterizationLineStateCreateInfoEXT : return "PipelineRasterizationLineStateCreateInfoEXT";
+ case StructureType::ePhysicalDeviceLineRasterizationPropertiesEXT : return "PhysicalDeviceLineRasterizationPropertiesEXT";
+ case StructureType::ePhysicalDeviceIndexTypeUint8FeaturesEXT : return "PhysicalDeviceIndexTypeUint8FeaturesEXT";
+ case StructureType::ePhysicalDevicePipelineExecutablePropertiesFeaturesKHR : return "PhysicalDevicePipelineExecutablePropertiesFeaturesKHR";
+ case StructureType::ePipelineInfoKHR : return "PipelineInfoKHR";
+ case StructureType::ePipelineExecutablePropertiesKHR : return "PipelineExecutablePropertiesKHR";
+ case StructureType::ePipelineExecutableInfoKHR : return "PipelineExecutableInfoKHR";
+ case StructureType::ePipelineExecutableStatisticKHR : return "PipelineExecutableStatisticKHR";
+ case StructureType::ePipelineExecutableInternalRepresentationKHR : return "PipelineExecutableInternalRepresentationKHR";
+ case StructureType::ePhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT : return "PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT";
+ case StructureType::ePhysicalDeviceTexelBufferAlignmentFeaturesEXT : return "PhysicalDeviceTexelBufferAlignmentFeaturesEXT";
+ case StructureType::ePhysicalDeviceTexelBufferAlignmentPropertiesEXT : return "PhysicalDeviceTexelBufferAlignmentPropertiesEXT";
+ default: return "invalid";
+ }
+ }
+
+ enum class SubgroupFeatureFlagBits
+ {
+ eBasic = VK_SUBGROUP_FEATURE_BASIC_BIT,
+ eVote = VK_SUBGROUP_FEATURE_VOTE_BIT,
+ eArithmetic = VK_SUBGROUP_FEATURE_ARITHMETIC_BIT,
+ eBallot = VK_SUBGROUP_FEATURE_BALLOT_BIT,
+ eShuffle = VK_SUBGROUP_FEATURE_SHUFFLE_BIT,
+ eShuffleRelative = VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT,
+ eClustered = VK_SUBGROUP_FEATURE_CLUSTERED_BIT,
+ eQuad = VK_SUBGROUP_FEATURE_QUAD_BIT,
+ ePartitionedNV = VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SubgroupFeatureFlagBits value )
+ {
+ switch ( value )
+ {
+ case SubgroupFeatureFlagBits::eBasic : return "Basic";
+ case SubgroupFeatureFlagBits::eVote : return "Vote";
+ case SubgroupFeatureFlagBits::eArithmetic : return "Arithmetic";
+ case SubgroupFeatureFlagBits::eBallot : return "Ballot";
+ case SubgroupFeatureFlagBits::eShuffle : return "Shuffle";
+ case SubgroupFeatureFlagBits::eShuffleRelative : return "ShuffleRelative";
+ case SubgroupFeatureFlagBits::eClustered : return "Clustered";
+ case SubgroupFeatureFlagBits::eQuad : return "Quad";
+ case SubgroupFeatureFlagBits::ePartitionedNV : return "PartitionedNV";
+ default: return "invalid";
+ }
+ }
+
+ enum class SubpassContents
+ {
+ eInline = VK_SUBPASS_CONTENTS_INLINE,
+ eSecondaryCommandBuffers = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SubpassContents value )
+ {
+ switch ( value )
+ {
+ case SubpassContents::eInline : return "Inline";
+ case SubpassContents::eSecondaryCommandBuffers : return "SecondaryCommandBuffers";
+ default: return "invalid";
+ }
+ }
+
+ enum class SubpassDescriptionFlagBits
+ {
+ ePerViewAttributesNVX = VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX,
+ ePerViewPositionXOnlyNVX = VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SubpassDescriptionFlagBits value )
+ {
+ switch ( value )
+ {
+ case SubpassDescriptionFlagBits::ePerViewAttributesNVX : return "PerViewAttributesNVX";
+ case SubpassDescriptionFlagBits::ePerViewPositionXOnlyNVX : return "PerViewPositionXOnlyNVX";
+ default: return "invalid";
+ }
+ }
+
+ enum class SurfaceCounterFlagBitsEXT
+ {
+ eVblank = VK_SURFACE_COUNTER_VBLANK_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SurfaceCounterFlagBitsEXT value )
+ {
+ switch ( value )
+ {
+ case SurfaceCounterFlagBitsEXT::eVblank : return "Vblank";
+ default: return "invalid";
+ }
+ }
+
+ enum class SurfaceTransformFlagBitsKHR
+ {
+ eIdentity = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
+ eRotate90 = VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR,
+ eRotate180 = VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR,
+ eRotate270 = VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR,
+ eHorizontalMirror = VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR,
+ eHorizontalMirrorRotate90 = VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR,
+ eHorizontalMirrorRotate180 = VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR,
+ eHorizontalMirrorRotate270 = VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR,
+ eInherit = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SurfaceTransformFlagBitsKHR value )
+ {
+ switch ( value )
+ {
+ case SurfaceTransformFlagBitsKHR::eIdentity : return "Identity";
+ case SurfaceTransformFlagBitsKHR::eRotate90 : return "Rotate90";
+ case SurfaceTransformFlagBitsKHR::eRotate180 : return "Rotate180";
+ case SurfaceTransformFlagBitsKHR::eRotate270 : return "Rotate270";
+ case SurfaceTransformFlagBitsKHR::eHorizontalMirror : return "HorizontalMirror";
+ case SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate90 : return "HorizontalMirrorRotate90";
+ case SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate180 : return "HorizontalMirrorRotate180";
+ case SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate270 : return "HorizontalMirrorRotate270";
+ case SurfaceTransformFlagBitsKHR::eInherit : return "Inherit";
+ default: return "invalid";
+ }
+ }
+
+ enum class SwapchainCreateFlagBitsKHR
+ {
+ eSplitInstanceBindRegions = VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR,
+ eProtected = VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR,
+ eMutableFormat = VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SwapchainCreateFlagBitsKHR value )
+ {
+ switch ( value )
+ {
+ case SwapchainCreateFlagBitsKHR::eSplitInstanceBindRegions : return "SplitInstanceBindRegions";
+ case SwapchainCreateFlagBitsKHR::eProtected : return "Protected";
+ case SwapchainCreateFlagBitsKHR::eMutableFormat : return "MutableFormat";
+ default: return "invalid";
+ }
+ }
+
+ enum class SystemAllocationScope
+ {
+ eCommand = VK_SYSTEM_ALLOCATION_SCOPE_COMMAND,
+ eObject = VK_SYSTEM_ALLOCATION_SCOPE_OBJECT,
+ eCache = VK_SYSTEM_ALLOCATION_SCOPE_CACHE,
+ eDevice = VK_SYSTEM_ALLOCATION_SCOPE_DEVICE,
+ eInstance = VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( SystemAllocationScope value )
+ {
+ switch ( value )
+ {
+ case SystemAllocationScope::eCommand : return "Command";
+ case SystemAllocationScope::eObject : return "Object";
+ case SystemAllocationScope::eCache : return "Cache";
+ case SystemAllocationScope::eDevice : return "Device";
+ case SystemAllocationScope::eInstance : return "Instance";
+ default: return "invalid";
+ }
+ }
+
+ enum class TessellationDomainOrigin
+ {
+ eUpperLeft = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT,
+ eLowerLeft = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT
+ };
+ using TessellationDomainOriginKHR = TessellationDomainOrigin;
+
+ VULKAN_HPP_INLINE std::string to_string( TessellationDomainOrigin value )
+ {
+ switch ( value )
+ {
+ case TessellationDomainOrigin::eUpperLeft : return "UpperLeft";
+ case TessellationDomainOrigin::eLowerLeft : return "LowerLeft";
+ default: return "invalid";
+ }
+ }
+
+ enum class TimeDomainEXT
+ {
+ eDevice = VK_TIME_DOMAIN_DEVICE_EXT,
+ eClockMonotonic = VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT,
+ eClockMonotonicRaw = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT,
+ eQueryPerformanceCounter = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( TimeDomainEXT value )
+ {
+ switch ( value )
+ {
+ case TimeDomainEXT::eDevice : return "Device";
+ case TimeDomainEXT::eClockMonotonic : return "ClockMonotonic";
+ case TimeDomainEXT::eClockMonotonicRaw : return "ClockMonotonicRaw";
+ case TimeDomainEXT::eQueryPerformanceCounter : return "QueryPerformanceCounter";
+ default: return "invalid";
+ }
+ }
+
+ enum class ToolPurposeFlagBitsEXT
+ {
+ eValidation = VK_TOOL_PURPOSE_VALIDATION_BIT_EXT,
+ eProfiling = VK_TOOL_PURPOSE_PROFILING_BIT_EXT,
+ eTracing = VK_TOOL_PURPOSE_TRACING_BIT_EXT,
+ eAdditionalFeatures = VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT,
+ eModifyingFeatures = VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT,
+ eDebugReporting = VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT,
+ eDebugMarkers = VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ToolPurposeFlagBitsEXT value )
+ {
+ switch ( value )
+ {
+ case ToolPurposeFlagBitsEXT::eValidation : return "Validation";
+ case ToolPurposeFlagBitsEXT::eProfiling : return "Profiling";
+ case ToolPurposeFlagBitsEXT::eTracing : return "Tracing";
+ case ToolPurposeFlagBitsEXT::eAdditionalFeatures : return "AdditionalFeatures";
+ case ToolPurposeFlagBitsEXT::eModifyingFeatures : return "ModifyingFeatures";
+ case ToolPurposeFlagBitsEXT::eDebugReporting : return "DebugReporting";
+ case ToolPurposeFlagBitsEXT::eDebugMarkers : return "DebugMarkers";
+ default: return "invalid";
+ }
+ }
+
+ enum class ValidationCacheHeaderVersionEXT
+ {
+ eOne = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ValidationCacheHeaderVersionEXT value )
+ {
+ switch ( value )
+ {
+ case ValidationCacheHeaderVersionEXT::eOne : return "One";
+ default: return "invalid";
+ }
+ }
+
+ enum class ValidationCheckEXT
+ {
+ eAll = VK_VALIDATION_CHECK_ALL_EXT,
+ eShaders = VK_VALIDATION_CHECK_SHADERS_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ValidationCheckEXT value )
+ {
+ switch ( value )
+ {
+ case ValidationCheckEXT::eAll : return "All";
+ case ValidationCheckEXT::eShaders : return "Shaders";
+ default: return "invalid";
+ }
+ }
+
+ enum class ValidationFeatureDisableEXT
+ {
+ eAll = VK_VALIDATION_FEATURE_DISABLE_ALL_EXT,
+ eShaders = VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT,
+ eThreadSafety = VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT,
+ eApiParameters = VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT,
+ eObjectLifetimes = VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT,
+ eCoreChecks = VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT,
+ eUniqueHandles = VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ValidationFeatureDisableEXT value )
+ {
+ switch ( value )
+ {
+ case ValidationFeatureDisableEXT::eAll : return "All";
+ case ValidationFeatureDisableEXT::eShaders : return "Shaders";
+ case ValidationFeatureDisableEXT::eThreadSafety : return "ThreadSafety";
+ case ValidationFeatureDisableEXT::eApiParameters : return "ApiParameters";
+ case ValidationFeatureDisableEXT::eObjectLifetimes : return "ObjectLifetimes";
+ case ValidationFeatureDisableEXT::eCoreChecks : return "CoreChecks";
+ case ValidationFeatureDisableEXT::eUniqueHandles : return "UniqueHandles";
+ default: return "invalid";
+ }
+ }
+
+ enum class ValidationFeatureEnableEXT
+ {
+ eGpuAssisted = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
+ eGpuAssistedReserveBindingSlot = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
+ eBestPractices = VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ValidationFeatureEnableEXT value )
+ {
+ switch ( value )
+ {
+ case ValidationFeatureEnableEXT::eGpuAssisted : return "GpuAssisted";
+ case ValidationFeatureEnableEXT::eGpuAssistedReserveBindingSlot : return "GpuAssistedReserveBindingSlot";
+ case ValidationFeatureEnableEXT::eBestPractices : return "BestPractices";
+ default: return "invalid";
+ }
+ }
+
+ enum class VendorId
+ {
+ eVIV = VK_VENDOR_ID_VIV,
+ eVSI = VK_VENDOR_ID_VSI,
+ eKazan = VK_VENDOR_ID_KAZAN
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( VendorId value )
+ {
+ switch ( value )
+ {
+ case VendorId::eVIV : return "VIV";
+ case VendorId::eVSI : return "VSI";
+ case VendorId::eKazan : return "Kazan";
+ default: return "invalid";
+ }
+ }
+
+ enum class VertexInputRate
+ {
+ eVertex = VK_VERTEX_INPUT_RATE_VERTEX,
+ eInstance = VK_VERTEX_INPUT_RATE_INSTANCE
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( VertexInputRate value )
+ {
+ switch ( value )
+ {
+ case VertexInputRate::eVertex : return "Vertex";
+ case VertexInputRate::eInstance : return "Instance";
+ default: return "invalid";
+ }
+ }
+
+ enum class ViewportCoordinateSwizzleNV
+ {
+ ePositiveX = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV,
+ eNegativeX = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV,
+ ePositiveY = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV,
+ eNegativeY = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV,
+ ePositiveZ = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV,
+ eNegativeZ = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV,
+ ePositiveW = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV,
+ eNegativeW = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV
+ };
+
+ VULKAN_HPP_INLINE std::string to_string( ViewportCoordinateSwizzleNV value )
+ {
+ switch ( value )
+ {
+ case ViewportCoordinateSwizzleNV::ePositiveX : return "PositiveX";
+ case ViewportCoordinateSwizzleNV::eNegativeX : return "NegativeX";
+ case ViewportCoordinateSwizzleNV::ePositiveY : return "PositiveY";
+ case ViewportCoordinateSwizzleNV::eNegativeY : return "NegativeY";
+ case ViewportCoordinateSwizzleNV::ePositiveZ : return "PositiveZ";
+ case ViewportCoordinateSwizzleNV::eNegativeZ : return "NegativeZ";
+ case ViewportCoordinateSwizzleNV::ePositiveW : return "PositiveW";
+ case ViewportCoordinateSwizzleNV::eNegativeW : return "NegativeW";
+ default: return "invalid";
+ }
+ }
+
+ template<ObjectType value>
+ struct cpp_type
+ {
+ };
+
+ using AccessFlags = Flags<AccessFlagBits, VkAccessFlags>;
+
+ template <> struct FlagTraits<AccessFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(AccessFlagBits::eIndirectCommandRead) | VkFlags(AccessFlagBits::eIndexRead) | VkFlags(AccessFlagBits::eVertexAttributeRead) | VkFlags(AccessFlagBits::eUniformRead) | VkFlags(AccessFlagBits::eInputAttachmentRead) | VkFlags(AccessFlagBits::eShaderRead) | VkFlags(AccessFlagBits::eShaderWrite) | VkFlags(AccessFlagBits::eColorAttachmentRead) | VkFlags(AccessFlagBits::eColorAttachmentWrite) | VkFlags(AccessFlagBits::eDepthStencilAttachmentRead) | VkFlags(AccessFlagBits::eDepthStencilAttachmentWrite) | VkFlags(AccessFlagBits::eTransferRead) | VkFlags(AccessFlagBits::eTransferWrite) | VkFlags(AccessFlagBits::eHostRead) | VkFlags(AccessFlagBits::eHostWrite) | VkFlags(AccessFlagBits::eMemoryRead) | VkFlags(AccessFlagBits::eMemoryWrite) | VkFlags(AccessFlagBits::eTransformFeedbackWriteEXT) | VkFlags(AccessFlagBits::eTransformFeedbackCounterReadEXT) | VkFlags(AccessFlagBits::eTransformFeedbackCounterWriteEXT) | VkFlags(AccessFlagBits::eConditionalRenderingReadEXT) | VkFlags(AccessFlagBits::eCommandProcessReadNVX) | VkFlags(AccessFlagBits::eCommandProcessWriteNVX) | VkFlags(AccessFlagBits::eColorAttachmentReadNoncoherentEXT) | VkFlags(AccessFlagBits::eShadingRateImageReadNV) | VkFlags(AccessFlagBits::eAccelerationStructureReadNV) | VkFlags(AccessFlagBits::eAccelerationStructureWriteNV) | VkFlags(AccessFlagBits::eFragmentDensityMapReadEXT)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AccessFlags operator|( AccessFlagBits bit0, AccessFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return AccessFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AccessFlags operator&( AccessFlagBits bit0, AccessFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return AccessFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AccessFlags operator^( AccessFlagBits bit0, AccessFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return AccessFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AccessFlags operator~( AccessFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( AccessFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( AccessFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & AccessFlagBits::eIndirectCommandRead ) result += "IndirectCommandRead | ";
+ if ( value & AccessFlagBits::eIndexRead ) result += "IndexRead | ";
+ if ( value & AccessFlagBits::eVertexAttributeRead ) result += "VertexAttributeRead | ";
+ if ( value & AccessFlagBits::eUniformRead ) result += "UniformRead | ";
+ if ( value & AccessFlagBits::eInputAttachmentRead ) result += "InputAttachmentRead | ";
+ if ( value & AccessFlagBits::eShaderRead ) result += "ShaderRead | ";
+ if ( value & AccessFlagBits::eShaderWrite ) result += "ShaderWrite | ";
+ if ( value & AccessFlagBits::eColorAttachmentRead ) result += "ColorAttachmentRead | ";
+ if ( value & AccessFlagBits::eColorAttachmentWrite ) result += "ColorAttachmentWrite | ";
+ if ( value & AccessFlagBits::eDepthStencilAttachmentRead ) result += "DepthStencilAttachmentRead | ";
+ if ( value & AccessFlagBits::eDepthStencilAttachmentWrite ) result += "DepthStencilAttachmentWrite | ";
+ if ( value & AccessFlagBits::eTransferRead ) result += "TransferRead | ";
+ if ( value & AccessFlagBits::eTransferWrite ) result += "TransferWrite | ";
+ if ( value & AccessFlagBits::eHostRead ) result += "HostRead | ";
+ if ( value & AccessFlagBits::eHostWrite ) result += "HostWrite | ";
+ if ( value & AccessFlagBits::eMemoryRead ) result += "MemoryRead | ";
+ if ( value & AccessFlagBits::eMemoryWrite ) result += "MemoryWrite | ";
+ if ( value & AccessFlagBits::eTransformFeedbackWriteEXT ) result += "TransformFeedbackWriteEXT | ";
+ if ( value & AccessFlagBits::eTransformFeedbackCounterReadEXT ) result += "TransformFeedbackCounterReadEXT | ";
+ if ( value & AccessFlagBits::eTransformFeedbackCounterWriteEXT ) result += "TransformFeedbackCounterWriteEXT | ";
+ if ( value & AccessFlagBits::eConditionalRenderingReadEXT ) result += "ConditionalRenderingReadEXT | ";
+ if ( value & AccessFlagBits::eCommandProcessReadNVX ) result += "CommandProcessReadNVX | ";
+ if ( value & AccessFlagBits::eCommandProcessWriteNVX ) result += "CommandProcessWriteNVX | ";
+ if ( value & AccessFlagBits::eColorAttachmentReadNoncoherentEXT ) result += "ColorAttachmentReadNoncoherentEXT | ";
+ if ( value & AccessFlagBits::eShadingRateImageReadNV ) result += "ShadingRateImageReadNV | ";
+ if ( value & AccessFlagBits::eAccelerationStructureReadNV ) result += "AccelerationStructureReadNV | ";
+ if ( value & AccessFlagBits::eAccelerationStructureWriteNV ) result += "AccelerationStructureWriteNV | ";
+ if ( value & AccessFlagBits::eFragmentDensityMapReadEXT ) result += "FragmentDensityMapReadEXT | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using AcquireProfilingLockFlagsKHR = Flags<AcquireProfilingLockFlagBitsKHR, VkAcquireProfilingLockFlagsKHR>;
+
+ VULKAN_HPP_INLINE std::string to_string( AcquireProfilingLockFlagsKHR )
+ {
+ return "{}";
+ }
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ enum class AndroidSurfaceCreateFlagBitsKHR
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( AndroidSurfaceCreateFlagBitsKHR )
+ {
+ return "(void)";
+ }
+
+ using AndroidSurfaceCreateFlagsKHR = Flags<AndroidSurfaceCreateFlagBitsKHR, VkAndroidSurfaceCreateFlagsKHR>;
+
+ VULKAN_HPP_INLINE std::string to_string( AndroidSurfaceCreateFlagsKHR )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ using AttachmentDescriptionFlags = Flags<AttachmentDescriptionFlagBits, VkAttachmentDescriptionFlags>;
+
+ template <> struct FlagTraits<AttachmentDescriptionFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(AttachmentDescriptionFlagBits::eMayAlias)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AttachmentDescriptionFlags operator|( AttachmentDescriptionFlagBits bit0, AttachmentDescriptionFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return AttachmentDescriptionFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AttachmentDescriptionFlags operator&( AttachmentDescriptionFlagBits bit0, AttachmentDescriptionFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return AttachmentDescriptionFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AttachmentDescriptionFlags operator^( AttachmentDescriptionFlagBits bit0, AttachmentDescriptionFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return AttachmentDescriptionFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR AttachmentDescriptionFlags operator~( AttachmentDescriptionFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( AttachmentDescriptionFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( AttachmentDescriptionFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & AttachmentDescriptionFlagBits::eMayAlias ) result += "MayAlias | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using BufferCreateFlags = Flags<BufferCreateFlagBits, VkBufferCreateFlags>;
+
+ template <> struct FlagTraits<BufferCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(BufferCreateFlagBits::eSparseBinding) | VkFlags(BufferCreateFlagBits::eSparseResidency) | VkFlags(BufferCreateFlagBits::eSparseAliased) | VkFlags(BufferCreateFlagBits::eProtected) | VkFlags(BufferCreateFlagBits::eDeviceAddressCaptureReplay)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BufferCreateFlags operator|( BufferCreateFlagBits bit0, BufferCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return BufferCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BufferCreateFlags operator&( BufferCreateFlagBits bit0, BufferCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return BufferCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BufferCreateFlags operator^( BufferCreateFlagBits bit0, BufferCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return BufferCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BufferCreateFlags operator~( BufferCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( BufferCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( BufferCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & BufferCreateFlagBits::eSparseBinding ) result += "SparseBinding | ";
+ if ( value & BufferCreateFlagBits::eSparseResidency ) result += "SparseResidency | ";
+ if ( value & BufferCreateFlagBits::eSparseAliased ) result += "SparseAliased | ";
+ if ( value & BufferCreateFlagBits::eProtected ) result += "Protected | ";
+ if ( value & BufferCreateFlagBits::eDeviceAddressCaptureReplay ) result += "DeviceAddressCaptureReplay | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using BufferUsageFlags = Flags<BufferUsageFlagBits, VkBufferUsageFlags>;
+
+ template <> struct FlagTraits<BufferUsageFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(BufferUsageFlagBits::eTransferSrc) | VkFlags(BufferUsageFlagBits::eTransferDst) | VkFlags(BufferUsageFlagBits::eUniformTexelBuffer) | VkFlags(BufferUsageFlagBits::eStorageTexelBuffer) | VkFlags(BufferUsageFlagBits::eUniformBuffer) | VkFlags(BufferUsageFlagBits::eStorageBuffer) | VkFlags(BufferUsageFlagBits::eIndexBuffer) | VkFlags(BufferUsageFlagBits::eVertexBuffer) | VkFlags(BufferUsageFlagBits::eIndirectBuffer) | VkFlags(BufferUsageFlagBits::eShaderDeviceAddress) | VkFlags(BufferUsageFlagBits::eTransformFeedbackBufferEXT) | VkFlags(BufferUsageFlagBits::eTransformFeedbackCounterBufferEXT) | VkFlags(BufferUsageFlagBits::eConditionalRenderingEXT) | VkFlags(BufferUsageFlagBits::eRayTracingNV)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BufferUsageFlags operator|( BufferUsageFlagBits bit0, BufferUsageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return BufferUsageFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BufferUsageFlags operator&( BufferUsageFlagBits bit0, BufferUsageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return BufferUsageFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BufferUsageFlags operator^( BufferUsageFlagBits bit0, BufferUsageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return BufferUsageFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BufferUsageFlags operator~( BufferUsageFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( BufferUsageFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( BufferUsageFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & BufferUsageFlagBits::eTransferSrc ) result += "TransferSrc | ";
+ if ( value & BufferUsageFlagBits::eTransferDst ) result += "TransferDst | ";
+ if ( value & BufferUsageFlagBits::eUniformTexelBuffer ) result += "UniformTexelBuffer | ";
+ if ( value & BufferUsageFlagBits::eStorageTexelBuffer ) result += "StorageTexelBuffer | ";
+ if ( value & BufferUsageFlagBits::eUniformBuffer ) result += "UniformBuffer | ";
+ if ( value & BufferUsageFlagBits::eStorageBuffer ) result += "StorageBuffer | ";
+ if ( value & BufferUsageFlagBits::eIndexBuffer ) result += "IndexBuffer | ";
+ if ( value & BufferUsageFlagBits::eVertexBuffer ) result += "VertexBuffer | ";
+ if ( value & BufferUsageFlagBits::eIndirectBuffer ) result += "IndirectBuffer | ";
+ if ( value & BufferUsageFlagBits::eShaderDeviceAddress ) result += "ShaderDeviceAddress | ";
+ if ( value & BufferUsageFlagBits::eTransformFeedbackBufferEXT ) result += "TransformFeedbackBufferEXT | ";
+ if ( value & BufferUsageFlagBits::eTransformFeedbackCounterBufferEXT ) result += "TransformFeedbackCounterBufferEXT | ";
+ if ( value & BufferUsageFlagBits::eConditionalRenderingEXT ) result += "ConditionalRenderingEXT | ";
+ if ( value & BufferUsageFlagBits::eRayTracingNV ) result += "RayTracingNV | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using BufferViewCreateFlags = Flags<BufferViewCreateFlagBits, VkBufferViewCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( BufferViewCreateFlags )
+ {
+ return "{}";
+ }
+
+ using BuildAccelerationStructureFlagsNV = Flags<BuildAccelerationStructureFlagBitsNV, VkBuildAccelerationStructureFlagsNV>;
+
+ template <> struct FlagTraits<BuildAccelerationStructureFlagBitsNV>
+ {
+ enum
+ {
+ allFlags = VkFlags(BuildAccelerationStructureFlagBitsNV::eAllowUpdate) | VkFlags(BuildAccelerationStructureFlagBitsNV::eAllowCompaction) | VkFlags(BuildAccelerationStructureFlagBitsNV::ePreferFastTrace) | VkFlags(BuildAccelerationStructureFlagBitsNV::ePreferFastBuild) | VkFlags(BuildAccelerationStructureFlagBitsNV::eLowMemory)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsNV operator|( BuildAccelerationStructureFlagBitsNV bit0, BuildAccelerationStructureFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return BuildAccelerationStructureFlagsNV( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsNV operator&( BuildAccelerationStructureFlagBitsNV bit0, BuildAccelerationStructureFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return BuildAccelerationStructureFlagsNV( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsNV operator^( BuildAccelerationStructureFlagBitsNV bit0, BuildAccelerationStructureFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return BuildAccelerationStructureFlagsNV( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsNV operator~( BuildAccelerationStructureFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( BuildAccelerationStructureFlagsNV( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( BuildAccelerationStructureFlagsNV value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & BuildAccelerationStructureFlagBitsNV::eAllowUpdate ) result += "AllowUpdate | ";
+ if ( value & BuildAccelerationStructureFlagBitsNV::eAllowCompaction ) result += "AllowCompaction | ";
+ if ( value & BuildAccelerationStructureFlagBitsNV::ePreferFastTrace ) result += "PreferFastTrace | ";
+ if ( value & BuildAccelerationStructureFlagBitsNV::ePreferFastBuild ) result += "PreferFastBuild | ";
+ if ( value & BuildAccelerationStructureFlagBitsNV::eLowMemory ) result += "LowMemory | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ColorComponentFlags = Flags<ColorComponentFlagBits, VkColorComponentFlags>;
+
+ template <> struct FlagTraits<ColorComponentFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ColorComponentFlagBits::eR) | VkFlags(ColorComponentFlagBits::eG) | VkFlags(ColorComponentFlagBits::eB) | VkFlags(ColorComponentFlagBits::eA)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ColorComponentFlags operator|( ColorComponentFlagBits bit0, ColorComponentFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ColorComponentFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ColorComponentFlags operator&( ColorComponentFlagBits bit0, ColorComponentFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ColorComponentFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ColorComponentFlags operator^( ColorComponentFlagBits bit0, ColorComponentFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ColorComponentFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ColorComponentFlags operator~( ColorComponentFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ColorComponentFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ColorComponentFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ColorComponentFlagBits::eR ) result += "R | ";
+ if ( value & ColorComponentFlagBits::eG ) result += "G | ";
+ if ( value & ColorComponentFlagBits::eB ) result += "B | ";
+ if ( value & ColorComponentFlagBits::eA ) result += "A | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using CommandBufferResetFlags = Flags<CommandBufferResetFlagBits, VkCommandBufferResetFlags>;
+
+ template <> struct FlagTraits<CommandBufferResetFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(CommandBufferResetFlagBits::eReleaseResources)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandBufferResetFlags operator|( CommandBufferResetFlagBits bit0, CommandBufferResetFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandBufferResetFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandBufferResetFlags operator&( CommandBufferResetFlagBits bit0, CommandBufferResetFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandBufferResetFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandBufferResetFlags operator^( CommandBufferResetFlagBits bit0, CommandBufferResetFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandBufferResetFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandBufferResetFlags operator~( CommandBufferResetFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( CommandBufferResetFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( CommandBufferResetFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & CommandBufferResetFlagBits::eReleaseResources ) result += "ReleaseResources | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using CommandBufferUsageFlags = Flags<CommandBufferUsageFlagBits, VkCommandBufferUsageFlags>;
+
+ template <> struct FlagTraits<CommandBufferUsageFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(CommandBufferUsageFlagBits::eOneTimeSubmit) | VkFlags(CommandBufferUsageFlagBits::eRenderPassContinue) | VkFlags(CommandBufferUsageFlagBits::eSimultaneousUse)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandBufferUsageFlags operator|( CommandBufferUsageFlagBits bit0, CommandBufferUsageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandBufferUsageFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandBufferUsageFlags operator&( CommandBufferUsageFlagBits bit0, CommandBufferUsageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandBufferUsageFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandBufferUsageFlags operator^( CommandBufferUsageFlagBits bit0, CommandBufferUsageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandBufferUsageFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandBufferUsageFlags operator~( CommandBufferUsageFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( CommandBufferUsageFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( CommandBufferUsageFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & CommandBufferUsageFlagBits::eOneTimeSubmit ) result += "OneTimeSubmit | ";
+ if ( value & CommandBufferUsageFlagBits::eRenderPassContinue ) result += "RenderPassContinue | ";
+ if ( value & CommandBufferUsageFlagBits::eSimultaneousUse ) result += "SimultaneousUse | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using CommandPoolCreateFlags = Flags<CommandPoolCreateFlagBits, VkCommandPoolCreateFlags>;
+
+ template <> struct FlagTraits<CommandPoolCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(CommandPoolCreateFlagBits::eTransient) | VkFlags(CommandPoolCreateFlagBits::eResetCommandBuffer) | VkFlags(CommandPoolCreateFlagBits::eProtected)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandPoolCreateFlags operator|( CommandPoolCreateFlagBits bit0, CommandPoolCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandPoolCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandPoolCreateFlags operator&( CommandPoolCreateFlagBits bit0, CommandPoolCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandPoolCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandPoolCreateFlags operator^( CommandPoolCreateFlagBits bit0, CommandPoolCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandPoolCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandPoolCreateFlags operator~( CommandPoolCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( CommandPoolCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( CommandPoolCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & CommandPoolCreateFlagBits::eTransient ) result += "Transient | ";
+ if ( value & CommandPoolCreateFlagBits::eResetCommandBuffer ) result += "ResetCommandBuffer | ";
+ if ( value & CommandPoolCreateFlagBits::eProtected ) result += "Protected | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using CommandPoolResetFlags = Flags<CommandPoolResetFlagBits, VkCommandPoolResetFlags>;
+
+ template <> struct FlagTraits<CommandPoolResetFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(CommandPoolResetFlagBits::eReleaseResources)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandPoolResetFlags operator|( CommandPoolResetFlagBits bit0, CommandPoolResetFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandPoolResetFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandPoolResetFlags operator&( CommandPoolResetFlagBits bit0, CommandPoolResetFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandPoolResetFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandPoolResetFlags operator^( CommandPoolResetFlagBits bit0, CommandPoolResetFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CommandPoolResetFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CommandPoolResetFlags operator~( CommandPoolResetFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( CommandPoolResetFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( CommandPoolResetFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & CommandPoolResetFlagBits::eReleaseResources ) result += "ReleaseResources | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ enum class CommandPoolTrimFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( CommandPoolTrimFlagBits )
+ {
+ return "(void)";
+ }
+
+ using CommandPoolTrimFlags = Flags<CommandPoolTrimFlagBits, VkCommandPoolTrimFlags>;
+
+ using CommandPoolTrimFlagsKHR = CommandPoolTrimFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( CommandPoolTrimFlags )
+ {
+ return "{}";
+ }
+
+ using CompositeAlphaFlagsKHR = Flags<CompositeAlphaFlagBitsKHR, VkCompositeAlphaFlagsKHR>;
+
+ template <> struct FlagTraits<CompositeAlphaFlagBitsKHR>
+ {
+ enum
+ {
+ allFlags = VkFlags(CompositeAlphaFlagBitsKHR::eOpaque) | VkFlags(CompositeAlphaFlagBitsKHR::ePreMultiplied) | VkFlags(CompositeAlphaFlagBitsKHR::ePostMultiplied) | VkFlags(CompositeAlphaFlagBitsKHR::eInherit)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CompositeAlphaFlagsKHR operator|( CompositeAlphaFlagBitsKHR bit0, CompositeAlphaFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CompositeAlphaFlagsKHR( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CompositeAlphaFlagsKHR operator&( CompositeAlphaFlagBitsKHR bit0, CompositeAlphaFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CompositeAlphaFlagsKHR( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CompositeAlphaFlagsKHR operator^( CompositeAlphaFlagBitsKHR bit0, CompositeAlphaFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CompositeAlphaFlagsKHR( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CompositeAlphaFlagsKHR operator~( CompositeAlphaFlagBitsKHR bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( CompositeAlphaFlagsKHR( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( CompositeAlphaFlagsKHR value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & CompositeAlphaFlagBitsKHR::eOpaque ) result += "Opaque | ";
+ if ( value & CompositeAlphaFlagBitsKHR::ePreMultiplied ) result += "PreMultiplied | ";
+ if ( value & CompositeAlphaFlagBitsKHR::ePostMultiplied ) result += "PostMultiplied | ";
+ if ( value & CompositeAlphaFlagBitsKHR::eInherit ) result += "Inherit | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ConditionalRenderingFlagsEXT = Flags<ConditionalRenderingFlagBitsEXT, VkConditionalRenderingFlagsEXT>;
+
+ template <> struct FlagTraits<ConditionalRenderingFlagBitsEXT>
+ {
+ enum
+ {
+ allFlags = VkFlags(ConditionalRenderingFlagBitsEXT::eInverted)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ConditionalRenderingFlagsEXT operator|( ConditionalRenderingFlagBitsEXT bit0, ConditionalRenderingFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ConditionalRenderingFlagsEXT( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ConditionalRenderingFlagsEXT operator&( ConditionalRenderingFlagBitsEXT bit0, ConditionalRenderingFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ConditionalRenderingFlagsEXT( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ConditionalRenderingFlagsEXT operator^( ConditionalRenderingFlagBitsEXT bit0, ConditionalRenderingFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ConditionalRenderingFlagsEXT( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ConditionalRenderingFlagsEXT operator~( ConditionalRenderingFlagBitsEXT bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ConditionalRenderingFlagsEXT( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ConditionalRenderingFlagsEXT value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ConditionalRenderingFlagBitsEXT::eInverted ) result += "Inverted | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using CullModeFlags = Flags<CullModeFlagBits, VkCullModeFlags>;
+
+ template <> struct FlagTraits<CullModeFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(CullModeFlagBits::eNone) | VkFlags(CullModeFlagBits::eFront) | VkFlags(CullModeFlagBits::eBack) | VkFlags(CullModeFlagBits::eFrontAndBack)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CullModeFlags operator|( CullModeFlagBits bit0, CullModeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CullModeFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CullModeFlags operator&( CullModeFlagBits bit0, CullModeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CullModeFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CullModeFlags operator^( CullModeFlagBits bit0, CullModeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return CullModeFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR CullModeFlags operator~( CullModeFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( CullModeFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( CullModeFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & CullModeFlagBits::eFront ) result += "Front | ";
+ if ( value & CullModeFlagBits::eBack ) result += "Back | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using DebugReportFlagsEXT = Flags<DebugReportFlagBitsEXT, VkDebugReportFlagsEXT>;
+
+ template <> struct FlagTraits<DebugReportFlagBitsEXT>
+ {
+ enum
+ {
+ allFlags = VkFlags(DebugReportFlagBitsEXT::eInformation) | VkFlags(DebugReportFlagBitsEXT::eWarning) | VkFlags(DebugReportFlagBitsEXT::ePerformanceWarning) | VkFlags(DebugReportFlagBitsEXT::eError) | VkFlags(DebugReportFlagBitsEXT::eDebug)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugReportFlagsEXT operator|( DebugReportFlagBitsEXT bit0, DebugReportFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DebugReportFlagsEXT( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugReportFlagsEXT operator&( DebugReportFlagBitsEXT bit0, DebugReportFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DebugReportFlagsEXT( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugReportFlagsEXT operator^( DebugReportFlagBitsEXT bit0, DebugReportFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DebugReportFlagsEXT( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugReportFlagsEXT operator~( DebugReportFlagBitsEXT bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( DebugReportFlagsEXT( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( DebugReportFlagsEXT value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & DebugReportFlagBitsEXT::eInformation ) result += "Information | ";
+ if ( value & DebugReportFlagBitsEXT::eWarning ) result += "Warning | ";
+ if ( value & DebugReportFlagBitsEXT::ePerformanceWarning ) result += "PerformanceWarning | ";
+ if ( value & DebugReportFlagBitsEXT::eError ) result += "Error | ";
+ if ( value & DebugReportFlagBitsEXT::eDebug ) result += "Debug | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using DebugUtilsMessageSeverityFlagsEXT = Flags<DebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageSeverityFlagsEXT>;
+
+ template <> struct FlagTraits<DebugUtilsMessageSeverityFlagBitsEXT>
+ {
+ enum
+ {
+ allFlags = VkFlags(DebugUtilsMessageSeverityFlagBitsEXT::eVerbose) | VkFlags(DebugUtilsMessageSeverityFlagBitsEXT::eInfo) | VkFlags(DebugUtilsMessageSeverityFlagBitsEXT::eWarning) | VkFlags(DebugUtilsMessageSeverityFlagBitsEXT::eError)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugUtilsMessageSeverityFlagsEXT operator|( DebugUtilsMessageSeverityFlagBitsEXT bit0, DebugUtilsMessageSeverityFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DebugUtilsMessageSeverityFlagsEXT( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugUtilsMessageSeverityFlagsEXT operator&( DebugUtilsMessageSeverityFlagBitsEXT bit0, DebugUtilsMessageSeverityFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DebugUtilsMessageSeverityFlagsEXT( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugUtilsMessageSeverityFlagsEXT operator^( DebugUtilsMessageSeverityFlagBitsEXT bit0, DebugUtilsMessageSeverityFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DebugUtilsMessageSeverityFlagsEXT( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugUtilsMessageSeverityFlagsEXT operator~( DebugUtilsMessageSeverityFlagBitsEXT bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( DebugUtilsMessageSeverityFlagsEXT( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( DebugUtilsMessageSeverityFlagsEXT value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & DebugUtilsMessageSeverityFlagBitsEXT::eVerbose ) result += "Verbose | ";
+ if ( value & DebugUtilsMessageSeverityFlagBitsEXT::eInfo ) result += "Info | ";
+ if ( value & DebugUtilsMessageSeverityFlagBitsEXT::eWarning ) result += "Warning | ";
+ if ( value & DebugUtilsMessageSeverityFlagBitsEXT::eError ) result += "Error | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using DebugUtilsMessageTypeFlagsEXT = Flags<DebugUtilsMessageTypeFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT>;
+
+ template <> struct FlagTraits<DebugUtilsMessageTypeFlagBitsEXT>
+ {
+ enum
+ {
+ allFlags = VkFlags(DebugUtilsMessageTypeFlagBitsEXT::eGeneral) | VkFlags(DebugUtilsMessageTypeFlagBitsEXT::eValidation) | VkFlags(DebugUtilsMessageTypeFlagBitsEXT::ePerformance)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugUtilsMessageTypeFlagsEXT operator|( DebugUtilsMessageTypeFlagBitsEXT bit0, DebugUtilsMessageTypeFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DebugUtilsMessageTypeFlagsEXT( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugUtilsMessageTypeFlagsEXT operator&( DebugUtilsMessageTypeFlagBitsEXT bit0, DebugUtilsMessageTypeFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DebugUtilsMessageTypeFlagsEXT( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugUtilsMessageTypeFlagsEXT operator^( DebugUtilsMessageTypeFlagBitsEXT bit0, DebugUtilsMessageTypeFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DebugUtilsMessageTypeFlagsEXT( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DebugUtilsMessageTypeFlagsEXT operator~( DebugUtilsMessageTypeFlagBitsEXT bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( DebugUtilsMessageTypeFlagsEXT( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( DebugUtilsMessageTypeFlagsEXT value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & DebugUtilsMessageTypeFlagBitsEXT::eGeneral ) result += "General | ";
+ if ( value & DebugUtilsMessageTypeFlagBitsEXT::eValidation ) result += "Validation | ";
+ if ( value & DebugUtilsMessageTypeFlagBitsEXT::ePerformance ) result += "Performance | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ enum class DebugUtilsMessengerCallbackDataFlagBitsEXT
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( DebugUtilsMessengerCallbackDataFlagBitsEXT )
+ {
+ return "(void)";
+ }
+
+ using DebugUtilsMessengerCallbackDataFlagsEXT = Flags<DebugUtilsMessengerCallbackDataFlagBitsEXT, VkDebugUtilsMessengerCallbackDataFlagsEXT>;
+
+ VULKAN_HPP_INLINE std::string to_string( DebugUtilsMessengerCallbackDataFlagsEXT )
+ {
+ return "{}";
+ }
+
+ enum class DebugUtilsMessengerCreateFlagBitsEXT
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( DebugUtilsMessengerCreateFlagBitsEXT )
+ {
+ return "(void)";
+ }
+
+ using DebugUtilsMessengerCreateFlagsEXT = Flags<DebugUtilsMessengerCreateFlagBitsEXT, VkDebugUtilsMessengerCreateFlagsEXT>;
+
+ VULKAN_HPP_INLINE std::string to_string( DebugUtilsMessengerCreateFlagsEXT )
+ {
+ return "{}";
+ }
+
+ using DependencyFlags = Flags<DependencyFlagBits, VkDependencyFlags>;
+
+ template <> struct FlagTraits<DependencyFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(DependencyFlagBits::eByRegion) | VkFlags(DependencyFlagBits::eDeviceGroup) | VkFlags(DependencyFlagBits::eViewLocal)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DependencyFlags operator|( DependencyFlagBits bit0, DependencyFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DependencyFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DependencyFlags operator&( DependencyFlagBits bit0, DependencyFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DependencyFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DependencyFlags operator^( DependencyFlagBits bit0, DependencyFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DependencyFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DependencyFlags operator~( DependencyFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( DependencyFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( DependencyFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & DependencyFlagBits::eByRegion ) result += "ByRegion | ";
+ if ( value & DependencyFlagBits::eDeviceGroup ) result += "DeviceGroup | ";
+ if ( value & DependencyFlagBits::eViewLocal ) result += "ViewLocal | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using DescriptorBindingFlags = Flags<DescriptorBindingFlagBits, VkDescriptorBindingFlags>;
+
+ template <> struct FlagTraits<DescriptorBindingFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(DescriptorBindingFlagBits::eUpdateAfterBind) | VkFlags(DescriptorBindingFlagBits::eUpdateUnusedWhilePending) | VkFlags(DescriptorBindingFlagBits::ePartiallyBound) | VkFlags(DescriptorBindingFlagBits::eVariableDescriptorCount)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorBindingFlags operator|( DescriptorBindingFlagBits bit0, DescriptorBindingFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DescriptorBindingFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorBindingFlags operator&( DescriptorBindingFlagBits bit0, DescriptorBindingFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DescriptorBindingFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorBindingFlags operator^( DescriptorBindingFlagBits bit0, DescriptorBindingFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DescriptorBindingFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorBindingFlags operator~( DescriptorBindingFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( DescriptorBindingFlags( bits ) );
+ }
+
+ using DescriptorBindingFlagsEXT = DescriptorBindingFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorBindingFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & DescriptorBindingFlagBits::eUpdateAfterBind ) result += "UpdateAfterBind | ";
+ if ( value & DescriptorBindingFlagBits::eUpdateUnusedWhilePending ) result += "UpdateUnusedWhilePending | ";
+ if ( value & DescriptorBindingFlagBits::ePartiallyBound ) result += "PartiallyBound | ";
+ if ( value & DescriptorBindingFlagBits::eVariableDescriptorCount ) result += "VariableDescriptorCount | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using DescriptorPoolCreateFlags = Flags<DescriptorPoolCreateFlagBits, VkDescriptorPoolCreateFlags>;
+
+ template <> struct FlagTraits<DescriptorPoolCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(DescriptorPoolCreateFlagBits::eFreeDescriptorSet) | VkFlags(DescriptorPoolCreateFlagBits::eUpdateAfterBind)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorPoolCreateFlags operator|( DescriptorPoolCreateFlagBits bit0, DescriptorPoolCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DescriptorPoolCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorPoolCreateFlags operator&( DescriptorPoolCreateFlagBits bit0, DescriptorPoolCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DescriptorPoolCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorPoolCreateFlags operator^( DescriptorPoolCreateFlagBits bit0, DescriptorPoolCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DescriptorPoolCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorPoolCreateFlags operator~( DescriptorPoolCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( DescriptorPoolCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorPoolCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & DescriptorPoolCreateFlagBits::eFreeDescriptorSet ) result += "FreeDescriptorSet | ";
+ if ( value & DescriptorPoolCreateFlagBits::eUpdateAfterBind ) result += "UpdateAfterBind | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ enum class DescriptorPoolResetFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorPoolResetFlagBits )
+ {
+ return "(void)";
+ }
+
+ using DescriptorPoolResetFlags = Flags<DescriptorPoolResetFlagBits, VkDescriptorPoolResetFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorPoolResetFlags )
+ {
+ return "{}";
+ }
+
+ using DescriptorSetLayoutCreateFlags = Flags<DescriptorSetLayoutCreateFlagBits, VkDescriptorSetLayoutCreateFlags>;
+
+ template <> struct FlagTraits<DescriptorSetLayoutCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool) | VkFlags(DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorSetLayoutCreateFlags operator|( DescriptorSetLayoutCreateFlagBits bit0, DescriptorSetLayoutCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DescriptorSetLayoutCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorSetLayoutCreateFlags operator&( DescriptorSetLayoutCreateFlagBits bit0, DescriptorSetLayoutCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DescriptorSetLayoutCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorSetLayoutCreateFlags operator^( DescriptorSetLayoutCreateFlagBits bit0, DescriptorSetLayoutCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DescriptorSetLayoutCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DescriptorSetLayoutCreateFlags operator~( DescriptorSetLayoutCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( DescriptorSetLayoutCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorSetLayoutCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool ) result += "UpdateAfterBindPool | ";
+ if ( value & DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR ) result += "PushDescriptorKHR | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ enum class DescriptorUpdateTemplateCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorUpdateTemplateCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ using DescriptorUpdateTemplateCreateFlags = Flags<DescriptorUpdateTemplateCreateFlagBits, VkDescriptorUpdateTemplateCreateFlags>;
+
+ using DescriptorUpdateTemplateCreateFlagsKHR = DescriptorUpdateTemplateCreateFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( DescriptorUpdateTemplateCreateFlags )
+ {
+ return "{}";
+ }
+
+ using DeviceCreateFlags = Flags<DeviceCreateFlagBits, VkDeviceCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( DeviceCreateFlags )
+ {
+ return "{}";
+ }
+
+ using DeviceGroupPresentModeFlagsKHR = Flags<DeviceGroupPresentModeFlagBitsKHR, VkDeviceGroupPresentModeFlagsKHR>;
+
+ template <> struct FlagTraits<DeviceGroupPresentModeFlagBitsKHR>
+ {
+ enum
+ {
+ allFlags = VkFlags(DeviceGroupPresentModeFlagBitsKHR::eLocal) | VkFlags(DeviceGroupPresentModeFlagBitsKHR::eRemote) | VkFlags(DeviceGroupPresentModeFlagBitsKHR::eSum) | VkFlags(DeviceGroupPresentModeFlagBitsKHR::eLocalMultiDevice)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceGroupPresentModeFlagsKHR operator|( DeviceGroupPresentModeFlagBitsKHR bit0, DeviceGroupPresentModeFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DeviceGroupPresentModeFlagsKHR( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceGroupPresentModeFlagsKHR operator&( DeviceGroupPresentModeFlagBitsKHR bit0, DeviceGroupPresentModeFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DeviceGroupPresentModeFlagsKHR( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceGroupPresentModeFlagsKHR operator^( DeviceGroupPresentModeFlagBitsKHR bit0, DeviceGroupPresentModeFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DeviceGroupPresentModeFlagsKHR( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceGroupPresentModeFlagsKHR operator~( DeviceGroupPresentModeFlagBitsKHR bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( DeviceGroupPresentModeFlagsKHR( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( DeviceGroupPresentModeFlagsKHR value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & DeviceGroupPresentModeFlagBitsKHR::eLocal ) result += "Local | ";
+ if ( value & DeviceGroupPresentModeFlagBitsKHR::eRemote ) result += "Remote | ";
+ if ( value & DeviceGroupPresentModeFlagBitsKHR::eSum ) result += "Sum | ";
+ if ( value & DeviceGroupPresentModeFlagBitsKHR::eLocalMultiDevice ) result += "LocalMultiDevice | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using DeviceQueueCreateFlags = Flags<DeviceQueueCreateFlagBits, VkDeviceQueueCreateFlags>;
+
+ template <> struct FlagTraits<DeviceQueueCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(DeviceQueueCreateFlagBits::eProtected)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceQueueCreateFlags operator|( DeviceQueueCreateFlagBits bit0, DeviceQueueCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DeviceQueueCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceQueueCreateFlags operator&( DeviceQueueCreateFlagBits bit0, DeviceQueueCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DeviceQueueCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceQueueCreateFlags operator^( DeviceQueueCreateFlagBits bit0, DeviceQueueCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DeviceQueueCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceQueueCreateFlags operator~( DeviceQueueCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( DeviceQueueCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( DeviceQueueCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & DeviceQueueCreateFlagBits::eProtected ) result += "Protected | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ enum class DisplayModeCreateFlagBitsKHR
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( DisplayModeCreateFlagBitsKHR )
+ {
+ return "(void)";
+ }
+
+ using DisplayModeCreateFlagsKHR = Flags<DisplayModeCreateFlagBitsKHR, VkDisplayModeCreateFlagsKHR>;
+
+ VULKAN_HPP_INLINE std::string to_string( DisplayModeCreateFlagsKHR )
+ {
+ return "{}";
+ }
+
+ using DisplayPlaneAlphaFlagsKHR = Flags<DisplayPlaneAlphaFlagBitsKHR, VkDisplayPlaneAlphaFlagsKHR>;
+
+ template <> struct FlagTraits<DisplayPlaneAlphaFlagBitsKHR>
+ {
+ enum
+ {
+ allFlags = VkFlags(DisplayPlaneAlphaFlagBitsKHR::eOpaque) | VkFlags(DisplayPlaneAlphaFlagBitsKHR::eGlobal) | VkFlags(DisplayPlaneAlphaFlagBitsKHR::ePerPixel) | VkFlags(DisplayPlaneAlphaFlagBitsKHR::ePerPixelPremultiplied)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DisplayPlaneAlphaFlagsKHR operator|( DisplayPlaneAlphaFlagBitsKHR bit0, DisplayPlaneAlphaFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DisplayPlaneAlphaFlagsKHR( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DisplayPlaneAlphaFlagsKHR operator&( DisplayPlaneAlphaFlagBitsKHR bit0, DisplayPlaneAlphaFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DisplayPlaneAlphaFlagsKHR( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DisplayPlaneAlphaFlagsKHR operator^( DisplayPlaneAlphaFlagBitsKHR bit0, DisplayPlaneAlphaFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return DisplayPlaneAlphaFlagsKHR( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DisplayPlaneAlphaFlagsKHR operator~( DisplayPlaneAlphaFlagBitsKHR bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( DisplayPlaneAlphaFlagsKHR( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( DisplayPlaneAlphaFlagsKHR value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & DisplayPlaneAlphaFlagBitsKHR::eOpaque ) result += "Opaque | ";
+ if ( value & DisplayPlaneAlphaFlagBitsKHR::eGlobal ) result += "Global | ";
+ if ( value & DisplayPlaneAlphaFlagBitsKHR::ePerPixel ) result += "PerPixel | ";
+ if ( value & DisplayPlaneAlphaFlagBitsKHR::ePerPixelPremultiplied ) result += "PerPixelPremultiplied | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ enum class DisplaySurfaceCreateFlagBitsKHR
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( DisplaySurfaceCreateFlagBitsKHR )
+ {
+ return "(void)";
+ }
+
+ using DisplaySurfaceCreateFlagsKHR = Flags<DisplaySurfaceCreateFlagBitsKHR, VkDisplaySurfaceCreateFlagsKHR>;
+
+ VULKAN_HPP_INLINE std::string to_string( DisplaySurfaceCreateFlagsKHR )
+ {
+ return "{}";
+ }
+
+ enum class EventCreateFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( EventCreateFlagBits )
+ {
+ return "(void)";
+ }
+
+ using EventCreateFlags = Flags<EventCreateFlagBits, VkEventCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( EventCreateFlags )
+ {
+ return "{}";
+ }
+
+ using ExternalFenceFeatureFlags = Flags<ExternalFenceFeatureFlagBits, VkExternalFenceFeatureFlags>;
+
+ template <> struct FlagTraits<ExternalFenceFeatureFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ExternalFenceFeatureFlagBits::eExportable) | VkFlags(ExternalFenceFeatureFlagBits::eImportable)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalFenceFeatureFlags operator|( ExternalFenceFeatureFlagBits bit0, ExternalFenceFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalFenceFeatureFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalFenceFeatureFlags operator&( ExternalFenceFeatureFlagBits bit0, ExternalFenceFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalFenceFeatureFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalFenceFeatureFlags operator^( ExternalFenceFeatureFlagBits bit0, ExternalFenceFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalFenceFeatureFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalFenceFeatureFlags operator~( ExternalFenceFeatureFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ExternalFenceFeatureFlags( bits ) );
+ }
+
+ using ExternalFenceFeatureFlagsKHR = ExternalFenceFeatureFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalFenceFeatureFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ExternalFenceFeatureFlagBits::eExportable ) result += "Exportable | ";
+ if ( value & ExternalFenceFeatureFlagBits::eImportable ) result += "Importable | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ExternalFenceHandleTypeFlags = Flags<ExternalFenceHandleTypeFlagBits, VkExternalFenceHandleTypeFlags>;
+
+ template <> struct FlagTraits<ExternalFenceHandleTypeFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ExternalFenceHandleTypeFlagBits::eOpaqueFd) | VkFlags(ExternalFenceHandleTypeFlagBits::eOpaqueWin32) | VkFlags(ExternalFenceHandleTypeFlagBits::eOpaqueWin32Kmt) | VkFlags(ExternalFenceHandleTypeFlagBits::eSyncFd)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalFenceHandleTypeFlags operator|( ExternalFenceHandleTypeFlagBits bit0, ExternalFenceHandleTypeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalFenceHandleTypeFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalFenceHandleTypeFlags operator&( ExternalFenceHandleTypeFlagBits bit0, ExternalFenceHandleTypeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalFenceHandleTypeFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalFenceHandleTypeFlags operator^( ExternalFenceHandleTypeFlagBits bit0, ExternalFenceHandleTypeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalFenceHandleTypeFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalFenceHandleTypeFlags operator~( ExternalFenceHandleTypeFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ExternalFenceHandleTypeFlags( bits ) );
+ }
+
+ using ExternalFenceHandleTypeFlagsKHR = ExternalFenceHandleTypeFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalFenceHandleTypeFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ExternalFenceHandleTypeFlagBits::eOpaqueFd ) result += "OpaqueFd | ";
+ if ( value & ExternalFenceHandleTypeFlagBits::eOpaqueWin32 ) result += "OpaqueWin32 | ";
+ if ( value & ExternalFenceHandleTypeFlagBits::eOpaqueWin32Kmt ) result += "OpaqueWin32Kmt | ";
+ if ( value & ExternalFenceHandleTypeFlagBits::eSyncFd ) result += "SyncFd | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ExternalMemoryFeatureFlags = Flags<ExternalMemoryFeatureFlagBits, VkExternalMemoryFeatureFlags>;
+
+ template <> struct FlagTraits<ExternalMemoryFeatureFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ExternalMemoryFeatureFlagBits::eDedicatedOnly) | VkFlags(ExternalMemoryFeatureFlagBits::eExportable) | VkFlags(ExternalMemoryFeatureFlagBits::eImportable)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryFeatureFlags operator|( ExternalMemoryFeatureFlagBits bit0, ExternalMemoryFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryFeatureFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryFeatureFlags operator&( ExternalMemoryFeatureFlagBits bit0, ExternalMemoryFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryFeatureFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryFeatureFlags operator^( ExternalMemoryFeatureFlagBits bit0, ExternalMemoryFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryFeatureFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryFeatureFlags operator~( ExternalMemoryFeatureFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ExternalMemoryFeatureFlags( bits ) );
+ }
+
+ using ExternalMemoryFeatureFlagsKHR = ExternalMemoryFeatureFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalMemoryFeatureFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ExternalMemoryFeatureFlagBits::eDedicatedOnly ) result += "DedicatedOnly | ";
+ if ( value & ExternalMemoryFeatureFlagBits::eExportable ) result += "Exportable | ";
+ if ( value & ExternalMemoryFeatureFlagBits::eImportable ) result += "Importable | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ExternalMemoryFeatureFlagsNV = Flags<ExternalMemoryFeatureFlagBitsNV, VkExternalMemoryFeatureFlagsNV>;
+
+ template <> struct FlagTraits<ExternalMemoryFeatureFlagBitsNV>
+ {
+ enum
+ {
+ allFlags = VkFlags(ExternalMemoryFeatureFlagBitsNV::eDedicatedOnly) | VkFlags(ExternalMemoryFeatureFlagBitsNV::eExportable) | VkFlags(ExternalMemoryFeatureFlagBitsNV::eImportable)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryFeatureFlagsNV operator|( ExternalMemoryFeatureFlagBitsNV bit0, ExternalMemoryFeatureFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryFeatureFlagsNV( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryFeatureFlagsNV operator&( ExternalMemoryFeatureFlagBitsNV bit0, ExternalMemoryFeatureFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryFeatureFlagsNV( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryFeatureFlagsNV operator^( ExternalMemoryFeatureFlagBitsNV bit0, ExternalMemoryFeatureFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryFeatureFlagsNV( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryFeatureFlagsNV operator~( ExternalMemoryFeatureFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ExternalMemoryFeatureFlagsNV( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalMemoryFeatureFlagsNV value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ExternalMemoryFeatureFlagBitsNV::eDedicatedOnly ) result += "DedicatedOnly | ";
+ if ( value & ExternalMemoryFeatureFlagBitsNV::eExportable ) result += "Exportable | ";
+ if ( value & ExternalMemoryFeatureFlagBitsNV::eImportable ) result += "Importable | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ExternalMemoryHandleTypeFlags = Flags<ExternalMemoryHandleTypeFlagBits, VkExternalMemoryHandleTypeFlags>;
+
+ template <> struct FlagTraits<ExternalMemoryHandleTypeFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ExternalMemoryHandleTypeFlagBits::eOpaqueFd) | VkFlags(ExternalMemoryHandleTypeFlagBits::eOpaqueWin32) | VkFlags(ExternalMemoryHandleTypeFlagBits::eOpaqueWin32Kmt) | VkFlags(ExternalMemoryHandleTypeFlagBits::eD3D11Texture) | VkFlags(ExternalMemoryHandleTypeFlagBits::eD3D11TextureKmt) | VkFlags(ExternalMemoryHandleTypeFlagBits::eD3D12Heap) | VkFlags(ExternalMemoryHandleTypeFlagBits::eD3D12Resource) | VkFlags(ExternalMemoryHandleTypeFlagBits::eDmaBufEXT) | VkFlags(ExternalMemoryHandleTypeFlagBits::eAndroidHardwareBufferANDROID) | VkFlags(ExternalMemoryHandleTypeFlagBits::eHostAllocationEXT) | VkFlags(ExternalMemoryHandleTypeFlagBits::eHostMappedForeignMemoryEXT)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryHandleTypeFlags operator|( ExternalMemoryHandleTypeFlagBits bit0, ExternalMemoryHandleTypeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryHandleTypeFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryHandleTypeFlags operator&( ExternalMemoryHandleTypeFlagBits bit0, ExternalMemoryHandleTypeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryHandleTypeFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryHandleTypeFlags operator^( ExternalMemoryHandleTypeFlagBits bit0, ExternalMemoryHandleTypeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryHandleTypeFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryHandleTypeFlags operator~( ExternalMemoryHandleTypeFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ExternalMemoryHandleTypeFlags( bits ) );
+ }
+
+ using ExternalMemoryHandleTypeFlagsKHR = ExternalMemoryHandleTypeFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalMemoryHandleTypeFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ExternalMemoryHandleTypeFlagBits::eOpaqueFd ) result += "OpaqueFd | ";
+ if ( value & ExternalMemoryHandleTypeFlagBits::eOpaqueWin32 ) result += "OpaqueWin32 | ";
+ if ( value & ExternalMemoryHandleTypeFlagBits::eOpaqueWin32Kmt ) result += "OpaqueWin32Kmt | ";
+ if ( value & ExternalMemoryHandleTypeFlagBits::eD3D11Texture ) result += "D3D11Texture | ";
+ if ( value & ExternalMemoryHandleTypeFlagBits::eD3D11TextureKmt ) result += "D3D11TextureKmt | ";
+ if ( value & ExternalMemoryHandleTypeFlagBits::eD3D12Heap ) result += "D3D12Heap | ";
+ if ( value & ExternalMemoryHandleTypeFlagBits::eD3D12Resource ) result += "D3D12Resource | ";
+ if ( value & ExternalMemoryHandleTypeFlagBits::eDmaBufEXT ) result += "DmaBufEXT | ";
+ if ( value & ExternalMemoryHandleTypeFlagBits::eAndroidHardwareBufferANDROID ) result += "AndroidHardwareBufferANDROID | ";
+ if ( value & ExternalMemoryHandleTypeFlagBits::eHostAllocationEXT ) result += "HostAllocationEXT | ";
+ if ( value & ExternalMemoryHandleTypeFlagBits::eHostMappedForeignMemoryEXT ) result += "HostMappedForeignMemoryEXT | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ExternalMemoryHandleTypeFlagsNV = Flags<ExternalMemoryHandleTypeFlagBitsNV, VkExternalMemoryHandleTypeFlagsNV>;
+
+ template <> struct FlagTraits<ExternalMemoryHandleTypeFlagBitsNV>
+ {
+ enum
+ {
+ allFlags = VkFlags(ExternalMemoryHandleTypeFlagBitsNV::eOpaqueWin32) | VkFlags(ExternalMemoryHandleTypeFlagBitsNV::eOpaqueWin32Kmt) | VkFlags(ExternalMemoryHandleTypeFlagBitsNV::eD3D11Image) | VkFlags(ExternalMemoryHandleTypeFlagBitsNV::eD3D11ImageKmt)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryHandleTypeFlagsNV operator|( ExternalMemoryHandleTypeFlagBitsNV bit0, ExternalMemoryHandleTypeFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryHandleTypeFlagsNV( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryHandleTypeFlagsNV operator&( ExternalMemoryHandleTypeFlagBitsNV bit0, ExternalMemoryHandleTypeFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryHandleTypeFlagsNV( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryHandleTypeFlagsNV operator^( ExternalMemoryHandleTypeFlagBitsNV bit0, ExternalMemoryHandleTypeFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalMemoryHandleTypeFlagsNV( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalMemoryHandleTypeFlagsNV operator~( ExternalMemoryHandleTypeFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ExternalMemoryHandleTypeFlagsNV( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalMemoryHandleTypeFlagsNV value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ExternalMemoryHandleTypeFlagBitsNV::eOpaqueWin32 ) result += "OpaqueWin32 | ";
+ if ( value & ExternalMemoryHandleTypeFlagBitsNV::eOpaqueWin32Kmt ) result += "OpaqueWin32Kmt | ";
+ if ( value & ExternalMemoryHandleTypeFlagBitsNV::eD3D11Image ) result += "D3D11Image | ";
+ if ( value & ExternalMemoryHandleTypeFlagBitsNV::eD3D11ImageKmt ) result += "D3D11ImageKmt | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ExternalSemaphoreFeatureFlags = Flags<ExternalSemaphoreFeatureFlagBits, VkExternalSemaphoreFeatureFlags>;
+
+ template <> struct FlagTraits<ExternalSemaphoreFeatureFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ExternalSemaphoreFeatureFlagBits::eExportable) | VkFlags(ExternalSemaphoreFeatureFlagBits::eImportable)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalSemaphoreFeatureFlags operator|( ExternalSemaphoreFeatureFlagBits bit0, ExternalSemaphoreFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalSemaphoreFeatureFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalSemaphoreFeatureFlags operator&( ExternalSemaphoreFeatureFlagBits bit0, ExternalSemaphoreFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalSemaphoreFeatureFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalSemaphoreFeatureFlags operator^( ExternalSemaphoreFeatureFlagBits bit0, ExternalSemaphoreFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalSemaphoreFeatureFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalSemaphoreFeatureFlags operator~( ExternalSemaphoreFeatureFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ExternalSemaphoreFeatureFlags( bits ) );
+ }
+
+ using ExternalSemaphoreFeatureFlagsKHR = ExternalSemaphoreFeatureFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalSemaphoreFeatureFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ExternalSemaphoreFeatureFlagBits::eExportable ) result += "Exportable | ";
+ if ( value & ExternalSemaphoreFeatureFlagBits::eImportable ) result += "Importable | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ExternalSemaphoreHandleTypeFlags = Flags<ExternalSemaphoreHandleTypeFlagBits, VkExternalSemaphoreHandleTypeFlags>;
+
+ template <> struct FlagTraits<ExternalSemaphoreHandleTypeFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd) | VkFlags(ExternalSemaphoreHandleTypeFlagBits::eOpaqueWin32) | VkFlags(ExternalSemaphoreHandleTypeFlagBits::eOpaqueWin32Kmt) | VkFlags(ExternalSemaphoreHandleTypeFlagBits::eD3D12Fence) | VkFlags(ExternalSemaphoreHandleTypeFlagBits::eSyncFd)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalSemaphoreHandleTypeFlags operator|( ExternalSemaphoreHandleTypeFlagBits bit0, ExternalSemaphoreHandleTypeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalSemaphoreHandleTypeFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalSemaphoreHandleTypeFlags operator&( ExternalSemaphoreHandleTypeFlagBits bit0, ExternalSemaphoreHandleTypeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalSemaphoreHandleTypeFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalSemaphoreHandleTypeFlags operator^( ExternalSemaphoreHandleTypeFlagBits bit0, ExternalSemaphoreHandleTypeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ExternalSemaphoreHandleTypeFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ExternalSemaphoreHandleTypeFlags operator~( ExternalSemaphoreHandleTypeFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ExternalSemaphoreHandleTypeFlags( bits ) );
+ }
+
+ using ExternalSemaphoreHandleTypeFlagsKHR = ExternalSemaphoreHandleTypeFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( ExternalSemaphoreHandleTypeFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd ) result += "OpaqueFd | ";
+ if ( value & ExternalSemaphoreHandleTypeFlagBits::eOpaqueWin32 ) result += "OpaqueWin32 | ";
+ if ( value & ExternalSemaphoreHandleTypeFlagBits::eOpaqueWin32Kmt ) result += "OpaqueWin32Kmt | ";
+ if ( value & ExternalSemaphoreHandleTypeFlagBits::eD3D12Fence ) result += "D3D12Fence | ";
+ if ( value & ExternalSemaphoreHandleTypeFlagBits::eSyncFd ) result += "SyncFd | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using FenceCreateFlags = Flags<FenceCreateFlagBits, VkFenceCreateFlags>;
+
+ template <> struct FlagTraits<FenceCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(FenceCreateFlagBits::eSignaled)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FenceCreateFlags operator|( FenceCreateFlagBits bit0, FenceCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FenceCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FenceCreateFlags operator&( FenceCreateFlagBits bit0, FenceCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FenceCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FenceCreateFlags operator^( FenceCreateFlagBits bit0, FenceCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FenceCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FenceCreateFlags operator~( FenceCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( FenceCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( FenceCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & FenceCreateFlagBits::eSignaled ) result += "Signaled | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using FenceImportFlags = Flags<FenceImportFlagBits, VkFenceImportFlags>;
+
+ template <> struct FlagTraits<FenceImportFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(FenceImportFlagBits::eTemporary)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FenceImportFlags operator|( FenceImportFlagBits bit0, FenceImportFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FenceImportFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FenceImportFlags operator&( FenceImportFlagBits bit0, FenceImportFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FenceImportFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FenceImportFlags operator^( FenceImportFlagBits bit0, FenceImportFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FenceImportFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FenceImportFlags operator~( FenceImportFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( FenceImportFlags( bits ) );
+ }
+
+ using FenceImportFlagsKHR = FenceImportFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( FenceImportFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & FenceImportFlagBits::eTemporary ) result += "Temporary | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using FormatFeatureFlags = Flags<FormatFeatureFlagBits, VkFormatFeatureFlags>;
+
+ template <> struct FlagTraits<FormatFeatureFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(FormatFeatureFlagBits::eSampledImage) | VkFlags(FormatFeatureFlagBits::eStorageImage) | VkFlags(FormatFeatureFlagBits::eStorageImageAtomic) | VkFlags(FormatFeatureFlagBits::eUniformTexelBuffer) | VkFlags(FormatFeatureFlagBits::eStorageTexelBuffer) | VkFlags(FormatFeatureFlagBits::eStorageTexelBufferAtomic) | VkFlags(FormatFeatureFlagBits::eVertexBuffer) | VkFlags(FormatFeatureFlagBits::eColorAttachment) | VkFlags(FormatFeatureFlagBits::eColorAttachmentBlend) | VkFlags(FormatFeatureFlagBits::eDepthStencilAttachment) | VkFlags(FormatFeatureFlagBits::eBlitSrc) | VkFlags(FormatFeatureFlagBits::eBlitDst) | VkFlags(FormatFeatureFlagBits::eSampledImageFilterLinear) | VkFlags(FormatFeatureFlagBits::eTransferSrc) | VkFlags(FormatFeatureFlagBits::eTransferDst) | VkFlags(FormatFeatureFlagBits::eMidpointChromaSamples) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionLinearFilter) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionSeparateReconstructionFilter) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionChromaReconstructionExplicit) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionChromaReconstructionExplicitForceable) | VkFlags(FormatFeatureFlagBits::eDisjoint) | VkFlags(FormatFeatureFlagBits::eCositedChromaSamples) | VkFlags(FormatFeatureFlagBits::eSampledImageFilterMinmax) | VkFlags(FormatFeatureFlagBits::eSampledImageFilterCubicIMG) | VkFlags(FormatFeatureFlagBits::eFragmentDensityMapEXT)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FormatFeatureFlags operator|( FormatFeatureFlagBits bit0, FormatFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FormatFeatureFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FormatFeatureFlags operator&( FormatFeatureFlagBits bit0, FormatFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FormatFeatureFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FormatFeatureFlags operator^( FormatFeatureFlagBits bit0, FormatFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FormatFeatureFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FormatFeatureFlags operator~( FormatFeatureFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( FormatFeatureFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( FormatFeatureFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & FormatFeatureFlagBits::eSampledImage ) result += "SampledImage | ";
+ if ( value & FormatFeatureFlagBits::eStorageImage ) result += "StorageImage | ";
+ if ( value & FormatFeatureFlagBits::eStorageImageAtomic ) result += "StorageImageAtomic | ";
+ if ( value & FormatFeatureFlagBits::eUniformTexelBuffer ) result += "UniformTexelBuffer | ";
+ if ( value & FormatFeatureFlagBits::eStorageTexelBuffer ) result += "StorageTexelBuffer | ";
+ if ( value & FormatFeatureFlagBits::eStorageTexelBufferAtomic ) result += "StorageTexelBufferAtomic | ";
+ if ( value & FormatFeatureFlagBits::eVertexBuffer ) result += "VertexBuffer | ";
+ if ( value & FormatFeatureFlagBits::eColorAttachment ) result += "ColorAttachment | ";
+ if ( value & FormatFeatureFlagBits::eColorAttachmentBlend ) result += "ColorAttachmentBlend | ";
+ if ( value & FormatFeatureFlagBits::eDepthStencilAttachment ) result += "DepthStencilAttachment | ";
+ if ( value & FormatFeatureFlagBits::eBlitSrc ) result += "BlitSrc | ";
+ if ( value & FormatFeatureFlagBits::eBlitDst ) result += "BlitDst | ";
+ if ( value & FormatFeatureFlagBits::eSampledImageFilterLinear ) result += "SampledImageFilterLinear | ";
+ if ( value & FormatFeatureFlagBits::eTransferSrc ) result += "TransferSrc | ";
+ if ( value & FormatFeatureFlagBits::eTransferDst ) result += "TransferDst | ";
+ if ( value & FormatFeatureFlagBits::eMidpointChromaSamples ) result += "MidpointChromaSamples | ";
+ if ( value & FormatFeatureFlagBits::eSampledImageYcbcrConversionLinearFilter ) result += "SampledImageYcbcrConversionLinearFilter | ";
+ if ( value & FormatFeatureFlagBits::eSampledImageYcbcrConversionSeparateReconstructionFilter ) result += "SampledImageYcbcrConversionSeparateReconstructionFilter | ";
+ if ( value & FormatFeatureFlagBits::eSampledImageYcbcrConversionChromaReconstructionExplicit ) result += "SampledImageYcbcrConversionChromaReconstructionExplicit | ";
+ if ( value & FormatFeatureFlagBits::eSampledImageYcbcrConversionChromaReconstructionExplicitForceable ) result += "SampledImageYcbcrConversionChromaReconstructionExplicitForceable | ";
+ if ( value & FormatFeatureFlagBits::eDisjoint ) result += "Disjoint | ";
+ if ( value & FormatFeatureFlagBits::eCositedChromaSamples ) result += "CositedChromaSamples | ";
+ if ( value & FormatFeatureFlagBits::eSampledImageFilterMinmax ) result += "SampledImageFilterMinmax | ";
+ if ( value & FormatFeatureFlagBits::eSampledImageFilterCubicIMG ) result += "SampledImageFilterCubicIMG | ";
+ if ( value & FormatFeatureFlagBits::eFragmentDensityMapEXT ) result += "FragmentDensityMapEXT | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using FramebufferCreateFlags = Flags<FramebufferCreateFlagBits, VkFramebufferCreateFlags>;
+
+ template <> struct FlagTraits<FramebufferCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(FramebufferCreateFlagBits::eImageless)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FramebufferCreateFlags operator|( FramebufferCreateFlagBits bit0, FramebufferCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FramebufferCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FramebufferCreateFlags operator&( FramebufferCreateFlagBits bit0, FramebufferCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FramebufferCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FramebufferCreateFlags operator^( FramebufferCreateFlagBits bit0, FramebufferCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return FramebufferCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR FramebufferCreateFlags operator~( FramebufferCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( FramebufferCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( FramebufferCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & FramebufferCreateFlagBits::eImageless ) result += "Imageless | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using GeometryFlagsNV = Flags<GeometryFlagBitsNV, VkGeometryFlagsNV>;
+
+ template <> struct FlagTraits<GeometryFlagBitsNV>
+ {
+ enum
+ {
+ allFlags = VkFlags(GeometryFlagBitsNV::eOpaque) | VkFlags(GeometryFlagBitsNV::eNoDuplicateAnyHitInvocation)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsNV operator|( GeometryFlagBitsNV bit0, GeometryFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return GeometryFlagsNV( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsNV operator&( GeometryFlagBitsNV bit0, GeometryFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return GeometryFlagsNV( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsNV operator^( GeometryFlagBitsNV bit0, GeometryFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return GeometryFlagsNV( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsNV operator~( GeometryFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( GeometryFlagsNV( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( GeometryFlagsNV value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & GeometryFlagBitsNV::eOpaque ) result += "Opaque | ";
+ if ( value & GeometryFlagBitsNV::eNoDuplicateAnyHitInvocation ) result += "NoDuplicateAnyHitInvocation | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using GeometryInstanceFlagsNV = Flags<GeometryInstanceFlagBitsNV, VkGeometryInstanceFlagsNV>;
+
+ template <> struct FlagTraits<GeometryInstanceFlagBitsNV>
+ {
+ enum
+ {
+ allFlags = VkFlags(GeometryInstanceFlagBitsNV::eTriangleCullDisable) | VkFlags(GeometryInstanceFlagBitsNV::eTriangleFrontCounterclockwise) | VkFlags(GeometryInstanceFlagBitsNV::eForceOpaque) | VkFlags(GeometryInstanceFlagBitsNV::eForceNoOpaque)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsNV operator|( GeometryInstanceFlagBitsNV bit0, GeometryInstanceFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return GeometryInstanceFlagsNV( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsNV operator&( GeometryInstanceFlagBitsNV bit0, GeometryInstanceFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return GeometryInstanceFlagsNV( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsNV operator^( GeometryInstanceFlagBitsNV bit0, GeometryInstanceFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return GeometryInstanceFlagsNV( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsNV operator~( GeometryInstanceFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( GeometryInstanceFlagsNV( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( GeometryInstanceFlagsNV value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & GeometryInstanceFlagBitsNV::eTriangleCullDisable ) result += "TriangleCullDisable | ";
+ if ( value & GeometryInstanceFlagBitsNV::eTriangleFrontCounterclockwise ) result += "TriangleFrontCounterclockwise | ";
+ if ( value & GeometryInstanceFlagBitsNV::eForceOpaque ) result += "ForceOpaque | ";
+ if ( value & GeometryInstanceFlagBitsNV::eForceNoOpaque ) result += "ForceNoOpaque | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ enum class HeadlessSurfaceCreateFlagBitsEXT
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( HeadlessSurfaceCreateFlagBitsEXT )
+ {
+ return "(void)";
+ }
+
+ using HeadlessSurfaceCreateFlagsEXT = Flags<HeadlessSurfaceCreateFlagBitsEXT, VkHeadlessSurfaceCreateFlagsEXT>;
+
+ VULKAN_HPP_INLINE std::string to_string( HeadlessSurfaceCreateFlagsEXT )
+ {
+ return "{}";
+ }
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ enum class IOSSurfaceCreateFlagBitsMVK
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( IOSSurfaceCreateFlagBitsMVK )
+ {
+ return "(void)";
+ }
+
+ using IOSSurfaceCreateFlagsMVK = Flags<IOSSurfaceCreateFlagBitsMVK, VkIOSSurfaceCreateFlagsMVK>;
+
+ VULKAN_HPP_INLINE std::string to_string( IOSSurfaceCreateFlagsMVK )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_IOS_MVK*/
+
+ using ImageAspectFlags = Flags<ImageAspectFlagBits, VkImageAspectFlags>;
+
+ template <> struct FlagTraits<ImageAspectFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ImageAspectFlagBits::eColor) | VkFlags(ImageAspectFlagBits::eDepth) | VkFlags(ImageAspectFlagBits::eStencil) | VkFlags(ImageAspectFlagBits::eMetadata) | VkFlags(ImageAspectFlagBits::ePlane0) | VkFlags(ImageAspectFlagBits::ePlane1) | VkFlags(ImageAspectFlagBits::ePlane2) | VkFlags(ImageAspectFlagBits::eMemoryPlane0EXT) | VkFlags(ImageAspectFlagBits::eMemoryPlane1EXT) | VkFlags(ImageAspectFlagBits::eMemoryPlane2EXT) | VkFlags(ImageAspectFlagBits::eMemoryPlane3EXT)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageAspectFlags operator|( ImageAspectFlagBits bit0, ImageAspectFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageAspectFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageAspectFlags operator&( ImageAspectFlagBits bit0, ImageAspectFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageAspectFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageAspectFlags operator^( ImageAspectFlagBits bit0, ImageAspectFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageAspectFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageAspectFlags operator~( ImageAspectFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ImageAspectFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ImageAspectFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ImageAspectFlagBits::eColor ) result += "Color | ";
+ if ( value & ImageAspectFlagBits::eDepth ) result += "Depth | ";
+ if ( value & ImageAspectFlagBits::eStencil ) result += "Stencil | ";
+ if ( value & ImageAspectFlagBits::eMetadata ) result += "Metadata | ";
+ if ( value & ImageAspectFlagBits::ePlane0 ) result += "Plane0 | ";
+ if ( value & ImageAspectFlagBits::ePlane1 ) result += "Plane1 | ";
+ if ( value & ImageAspectFlagBits::ePlane2 ) result += "Plane2 | ";
+ if ( value & ImageAspectFlagBits::eMemoryPlane0EXT ) result += "MemoryPlane0EXT | ";
+ if ( value & ImageAspectFlagBits::eMemoryPlane1EXT ) result += "MemoryPlane1EXT | ";
+ if ( value & ImageAspectFlagBits::eMemoryPlane2EXT ) result += "MemoryPlane2EXT | ";
+ if ( value & ImageAspectFlagBits::eMemoryPlane3EXT ) result += "MemoryPlane3EXT | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ImageCreateFlags = Flags<ImageCreateFlagBits, VkImageCreateFlags>;
+
+ template <> struct FlagTraits<ImageCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ImageCreateFlagBits::eSparseBinding) | VkFlags(ImageCreateFlagBits::eSparseResidency) | VkFlags(ImageCreateFlagBits::eSparseAliased) | VkFlags(ImageCreateFlagBits::eMutableFormat) | VkFlags(ImageCreateFlagBits::eCubeCompatible) | VkFlags(ImageCreateFlagBits::eAlias) | VkFlags(ImageCreateFlagBits::eSplitInstanceBindRegions) | VkFlags(ImageCreateFlagBits::e2DArrayCompatible) | VkFlags(ImageCreateFlagBits::eBlockTexelViewCompatible) | VkFlags(ImageCreateFlagBits::eExtendedUsage) | VkFlags(ImageCreateFlagBits::eProtected) | VkFlags(ImageCreateFlagBits::eDisjoint) | VkFlags(ImageCreateFlagBits::eCornerSampledNV) | VkFlags(ImageCreateFlagBits::eSampleLocationsCompatibleDepthEXT) | VkFlags(ImageCreateFlagBits::eSubsampledEXT)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageCreateFlags operator|( ImageCreateFlagBits bit0, ImageCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageCreateFlags operator&( ImageCreateFlagBits bit0, ImageCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageCreateFlags operator^( ImageCreateFlagBits bit0, ImageCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageCreateFlags operator~( ImageCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ImageCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ImageCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ImageCreateFlagBits::eSparseBinding ) result += "SparseBinding | ";
+ if ( value & ImageCreateFlagBits::eSparseResidency ) result += "SparseResidency | ";
+ if ( value & ImageCreateFlagBits::eSparseAliased ) result += "SparseAliased | ";
+ if ( value & ImageCreateFlagBits::eMutableFormat ) result += "MutableFormat | ";
+ if ( value & ImageCreateFlagBits::eCubeCompatible ) result += "CubeCompatible | ";
+ if ( value & ImageCreateFlagBits::eAlias ) result += "Alias | ";
+ if ( value & ImageCreateFlagBits::eSplitInstanceBindRegions ) result += "SplitInstanceBindRegions | ";
+ if ( value & ImageCreateFlagBits::e2DArrayCompatible ) result += "2DArrayCompatible | ";
+ if ( value & ImageCreateFlagBits::eBlockTexelViewCompatible ) result += "BlockTexelViewCompatible | ";
+ if ( value & ImageCreateFlagBits::eExtendedUsage ) result += "ExtendedUsage | ";
+ if ( value & ImageCreateFlagBits::eProtected ) result += "Protected | ";
+ if ( value & ImageCreateFlagBits::eDisjoint ) result += "Disjoint | ";
+ if ( value & ImageCreateFlagBits::eCornerSampledNV ) result += "CornerSampledNV | ";
+ if ( value & ImageCreateFlagBits::eSampleLocationsCompatibleDepthEXT ) result += "SampleLocationsCompatibleDepthEXT | ";
+ if ( value & ImageCreateFlagBits::eSubsampledEXT ) result += "SubsampledEXT | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ enum class ImagePipeSurfaceCreateFlagBitsFUCHSIA
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( ImagePipeSurfaceCreateFlagBitsFUCHSIA )
+ {
+ return "(void)";
+ }
+
+ using ImagePipeSurfaceCreateFlagsFUCHSIA = Flags<ImagePipeSurfaceCreateFlagBitsFUCHSIA, VkImagePipeSurfaceCreateFlagsFUCHSIA>;
+
+ VULKAN_HPP_INLINE std::string to_string( ImagePipeSurfaceCreateFlagsFUCHSIA )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_FUCHSIA*/
+
+ using ImageUsageFlags = Flags<ImageUsageFlagBits, VkImageUsageFlags>;
+
+ template <> struct FlagTraits<ImageUsageFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ImageUsageFlagBits::eTransferSrc) | VkFlags(ImageUsageFlagBits::eTransferDst) | VkFlags(ImageUsageFlagBits::eSampled) | VkFlags(ImageUsageFlagBits::eStorage) | VkFlags(ImageUsageFlagBits::eColorAttachment) | VkFlags(ImageUsageFlagBits::eDepthStencilAttachment) | VkFlags(ImageUsageFlagBits::eTransientAttachment) | VkFlags(ImageUsageFlagBits::eInputAttachment) | VkFlags(ImageUsageFlagBits::eShadingRateImageNV) | VkFlags(ImageUsageFlagBits::eFragmentDensityMapEXT)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageUsageFlags operator|( ImageUsageFlagBits bit0, ImageUsageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageUsageFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageUsageFlags operator&( ImageUsageFlagBits bit0, ImageUsageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageUsageFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageUsageFlags operator^( ImageUsageFlagBits bit0, ImageUsageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageUsageFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageUsageFlags operator~( ImageUsageFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ImageUsageFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ImageUsageFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ImageUsageFlagBits::eTransferSrc ) result += "TransferSrc | ";
+ if ( value & ImageUsageFlagBits::eTransferDst ) result += "TransferDst | ";
+ if ( value & ImageUsageFlagBits::eSampled ) result += "Sampled | ";
+ if ( value & ImageUsageFlagBits::eStorage ) result += "Storage | ";
+ if ( value & ImageUsageFlagBits::eColorAttachment ) result += "ColorAttachment | ";
+ if ( value & ImageUsageFlagBits::eDepthStencilAttachment ) result += "DepthStencilAttachment | ";
+ if ( value & ImageUsageFlagBits::eTransientAttachment ) result += "TransientAttachment | ";
+ if ( value & ImageUsageFlagBits::eInputAttachment ) result += "InputAttachment | ";
+ if ( value & ImageUsageFlagBits::eShadingRateImageNV ) result += "ShadingRateImageNV | ";
+ if ( value & ImageUsageFlagBits::eFragmentDensityMapEXT ) result += "FragmentDensityMapEXT | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ImageViewCreateFlags = Flags<ImageViewCreateFlagBits, VkImageViewCreateFlags>;
+
+ template <> struct FlagTraits<ImageViewCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ImageViewCreateFlagBits::eFragmentDensityMapDynamicEXT)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageViewCreateFlags operator|( ImageViewCreateFlagBits bit0, ImageViewCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageViewCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageViewCreateFlags operator&( ImageViewCreateFlagBits bit0, ImageViewCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageViewCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageViewCreateFlags operator^( ImageViewCreateFlagBits bit0, ImageViewCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ImageViewCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ImageViewCreateFlags operator~( ImageViewCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ImageViewCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ImageViewCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ImageViewCreateFlagBits::eFragmentDensityMapDynamicEXT ) result += "FragmentDensityMapDynamicEXT | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using IndirectCommandsLayoutUsageFlagsNVX = Flags<IndirectCommandsLayoutUsageFlagBitsNVX, VkIndirectCommandsLayoutUsageFlagsNVX>;
+
+ template <> struct FlagTraits<IndirectCommandsLayoutUsageFlagBitsNVX>
+ {
+ enum
+ {
+ allFlags = VkFlags(IndirectCommandsLayoutUsageFlagBitsNVX::eUnorderedSequences) | VkFlags(IndirectCommandsLayoutUsageFlagBitsNVX::eSparseSequences) | VkFlags(IndirectCommandsLayoutUsageFlagBitsNVX::eEmptyExecutions) | VkFlags(IndirectCommandsLayoutUsageFlagBitsNVX::eIndexedSequences)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNVX operator|( IndirectCommandsLayoutUsageFlagBitsNVX bit0, IndirectCommandsLayoutUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return IndirectCommandsLayoutUsageFlagsNVX( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNVX operator&( IndirectCommandsLayoutUsageFlagBitsNVX bit0, IndirectCommandsLayoutUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return IndirectCommandsLayoutUsageFlagsNVX( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNVX operator^( IndirectCommandsLayoutUsageFlagBitsNVX bit0, IndirectCommandsLayoutUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return IndirectCommandsLayoutUsageFlagsNVX( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNVX operator~( IndirectCommandsLayoutUsageFlagBitsNVX bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( IndirectCommandsLayoutUsageFlagsNVX( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( IndirectCommandsLayoutUsageFlagsNVX value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & IndirectCommandsLayoutUsageFlagBitsNVX::eUnorderedSequences ) result += "UnorderedSequences | ";
+ if ( value & IndirectCommandsLayoutUsageFlagBitsNVX::eSparseSequences ) result += "SparseSequences | ";
+ if ( value & IndirectCommandsLayoutUsageFlagBitsNVX::eEmptyExecutions ) result += "EmptyExecutions | ";
+ if ( value & IndirectCommandsLayoutUsageFlagBitsNVX::eIndexedSequences ) result += "IndexedSequences | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using InstanceCreateFlags = Flags<InstanceCreateFlagBits, VkInstanceCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( InstanceCreateFlags )
+ {
+ return "{}";
+ }
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ enum class MacOSSurfaceCreateFlagBitsMVK
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( MacOSSurfaceCreateFlagBitsMVK )
+ {
+ return "(void)";
+ }
+
+ using MacOSSurfaceCreateFlagsMVK = Flags<MacOSSurfaceCreateFlagBitsMVK, VkMacOSSurfaceCreateFlagsMVK>;
+
+ VULKAN_HPP_INLINE std::string to_string( MacOSSurfaceCreateFlagsMVK )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_MACOS_MVK*/
+
+ using MemoryAllocateFlags = Flags<MemoryAllocateFlagBits, VkMemoryAllocateFlags>;
+
+ template <> struct FlagTraits<MemoryAllocateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(MemoryAllocateFlagBits::eDeviceMask) | VkFlags(MemoryAllocateFlagBits::eDeviceAddress) | VkFlags(MemoryAllocateFlagBits::eDeviceAddressCaptureReplay)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryAllocateFlags operator|( MemoryAllocateFlagBits bit0, MemoryAllocateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return MemoryAllocateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryAllocateFlags operator&( MemoryAllocateFlagBits bit0, MemoryAllocateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return MemoryAllocateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryAllocateFlags operator^( MemoryAllocateFlagBits bit0, MemoryAllocateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return MemoryAllocateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryAllocateFlags operator~( MemoryAllocateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( MemoryAllocateFlags( bits ) );
+ }
+
+ using MemoryAllocateFlagsKHR = MemoryAllocateFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( MemoryAllocateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & MemoryAllocateFlagBits::eDeviceMask ) result += "DeviceMask | ";
+ if ( value & MemoryAllocateFlagBits::eDeviceAddress ) result += "DeviceAddress | ";
+ if ( value & MemoryAllocateFlagBits::eDeviceAddressCaptureReplay ) result += "DeviceAddressCaptureReplay | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using MemoryHeapFlags = Flags<MemoryHeapFlagBits, VkMemoryHeapFlags>;
+
+ template <> struct FlagTraits<MemoryHeapFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(MemoryHeapFlagBits::eDeviceLocal) | VkFlags(MemoryHeapFlagBits::eMultiInstance)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryHeapFlags operator|( MemoryHeapFlagBits bit0, MemoryHeapFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return MemoryHeapFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryHeapFlags operator&( MemoryHeapFlagBits bit0, MemoryHeapFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return MemoryHeapFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryHeapFlags operator^( MemoryHeapFlagBits bit0, MemoryHeapFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return MemoryHeapFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryHeapFlags operator~( MemoryHeapFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( MemoryHeapFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( MemoryHeapFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & MemoryHeapFlagBits::eDeviceLocal ) result += "DeviceLocal | ";
+ if ( value & MemoryHeapFlagBits::eMultiInstance ) result += "MultiInstance | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ enum class MemoryMapFlagBits
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( MemoryMapFlagBits )
+ {
+ return "(void)";
+ }
+
+ using MemoryMapFlags = Flags<MemoryMapFlagBits, VkMemoryMapFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( MemoryMapFlags )
+ {
+ return "{}";
+ }
+
+ using MemoryPropertyFlags = Flags<MemoryPropertyFlagBits, VkMemoryPropertyFlags>;
+
+ template <> struct FlagTraits<MemoryPropertyFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(MemoryPropertyFlagBits::eDeviceLocal) | VkFlags(MemoryPropertyFlagBits::eHostVisible) | VkFlags(MemoryPropertyFlagBits::eHostCoherent) | VkFlags(MemoryPropertyFlagBits::eHostCached) | VkFlags(MemoryPropertyFlagBits::eLazilyAllocated) | VkFlags(MemoryPropertyFlagBits::eProtected) | VkFlags(MemoryPropertyFlagBits::eDeviceCoherentAMD) | VkFlags(MemoryPropertyFlagBits::eDeviceUncachedAMD)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryPropertyFlags operator|( MemoryPropertyFlagBits bit0, MemoryPropertyFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return MemoryPropertyFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryPropertyFlags operator&( MemoryPropertyFlagBits bit0, MemoryPropertyFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return MemoryPropertyFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryPropertyFlags operator^( MemoryPropertyFlagBits bit0, MemoryPropertyFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return MemoryPropertyFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR MemoryPropertyFlags operator~( MemoryPropertyFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( MemoryPropertyFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( MemoryPropertyFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & MemoryPropertyFlagBits::eDeviceLocal ) result += "DeviceLocal | ";
+ if ( value & MemoryPropertyFlagBits::eHostVisible ) result += "HostVisible | ";
+ if ( value & MemoryPropertyFlagBits::eHostCoherent ) result += "HostCoherent | ";
+ if ( value & MemoryPropertyFlagBits::eHostCached ) result += "HostCached | ";
+ if ( value & MemoryPropertyFlagBits::eLazilyAllocated ) result += "LazilyAllocated | ";
+ if ( value & MemoryPropertyFlagBits::eProtected ) result += "Protected | ";
+ if ( value & MemoryPropertyFlagBits::eDeviceCoherentAMD ) result += "DeviceCoherentAMD | ";
+ if ( value & MemoryPropertyFlagBits::eDeviceUncachedAMD ) result += "DeviceUncachedAMD | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ enum class MetalSurfaceCreateFlagBitsEXT
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( MetalSurfaceCreateFlagBitsEXT )
+ {
+ return "(void)";
+ }
+
+ using MetalSurfaceCreateFlagsEXT = Flags<MetalSurfaceCreateFlagBitsEXT, VkMetalSurfaceCreateFlagsEXT>;
+
+ VULKAN_HPP_INLINE std::string to_string( MetalSurfaceCreateFlagsEXT )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_METAL_EXT*/
+
+ using ObjectEntryUsageFlagsNVX = Flags<ObjectEntryUsageFlagBitsNVX, VkObjectEntryUsageFlagsNVX>;
+
+ template <> struct FlagTraits<ObjectEntryUsageFlagBitsNVX>
+ {
+ enum
+ {
+ allFlags = VkFlags(ObjectEntryUsageFlagBitsNVX::eGraphics) | VkFlags(ObjectEntryUsageFlagBitsNVX::eCompute)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ObjectEntryUsageFlagsNVX operator|( ObjectEntryUsageFlagBitsNVX bit0, ObjectEntryUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ObjectEntryUsageFlagsNVX( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ObjectEntryUsageFlagsNVX operator&( ObjectEntryUsageFlagBitsNVX bit0, ObjectEntryUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ObjectEntryUsageFlagsNVX( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ObjectEntryUsageFlagsNVX operator^( ObjectEntryUsageFlagBitsNVX bit0, ObjectEntryUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ObjectEntryUsageFlagsNVX( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ObjectEntryUsageFlagsNVX operator~( ObjectEntryUsageFlagBitsNVX bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ObjectEntryUsageFlagsNVX( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ObjectEntryUsageFlagsNVX value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ObjectEntryUsageFlagBitsNVX::eGraphics ) result += "Graphics | ";
+ if ( value & ObjectEntryUsageFlagBitsNVX::eCompute ) result += "Compute | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using PeerMemoryFeatureFlags = Flags<PeerMemoryFeatureFlagBits, VkPeerMemoryFeatureFlags>;
+
+ template <> struct FlagTraits<PeerMemoryFeatureFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(PeerMemoryFeatureFlagBits::eCopySrc) | VkFlags(PeerMemoryFeatureFlagBits::eCopyDst) | VkFlags(PeerMemoryFeatureFlagBits::eGenericSrc) | VkFlags(PeerMemoryFeatureFlagBits::eGenericDst)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PeerMemoryFeatureFlags operator|( PeerMemoryFeatureFlagBits bit0, PeerMemoryFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PeerMemoryFeatureFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PeerMemoryFeatureFlags operator&( PeerMemoryFeatureFlagBits bit0, PeerMemoryFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PeerMemoryFeatureFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PeerMemoryFeatureFlags operator^( PeerMemoryFeatureFlagBits bit0, PeerMemoryFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PeerMemoryFeatureFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PeerMemoryFeatureFlags operator~( PeerMemoryFeatureFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( PeerMemoryFeatureFlags( bits ) );
+ }
+
+ using PeerMemoryFeatureFlagsKHR = PeerMemoryFeatureFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( PeerMemoryFeatureFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & PeerMemoryFeatureFlagBits::eCopySrc ) result += "CopySrc | ";
+ if ( value & PeerMemoryFeatureFlagBits::eCopyDst ) result += "CopyDst | ";
+ if ( value & PeerMemoryFeatureFlagBits::eGenericSrc ) result += "GenericSrc | ";
+ if ( value & PeerMemoryFeatureFlagBits::eGenericDst ) result += "GenericDst | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using PerformanceCounterDescriptionFlagsKHR = Flags<PerformanceCounterDescriptionFlagBitsKHR, VkPerformanceCounterDescriptionFlagsKHR>;
+
+ template <> struct FlagTraits<PerformanceCounterDescriptionFlagBitsKHR>
+ {
+ enum
+ {
+ allFlags = VkFlags(PerformanceCounterDescriptionFlagBitsKHR::ePerformanceImpacting) | VkFlags(PerformanceCounterDescriptionFlagBitsKHR::eConcurrentlyImpacted)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PerformanceCounterDescriptionFlagsKHR operator|( PerformanceCounterDescriptionFlagBitsKHR bit0, PerformanceCounterDescriptionFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PerformanceCounterDescriptionFlagsKHR( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PerformanceCounterDescriptionFlagsKHR operator&( PerformanceCounterDescriptionFlagBitsKHR bit0, PerformanceCounterDescriptionFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PerformanceCounterDescriptionFlagsKHR( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PerformanceCounterDescriptionFlagsKHR operator^( PerformanceCounterDescriptionFlagBitsKHR bit0, PerformanceCounterDescriptionFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PerformanceCounterDescriptionFlagsKHR( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PerformanceCounterDescriptionFlagsKHR operator~( PerformanceCounterDescriptionFlagBitsKHR bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( PerformanceCounterDescriptionFlagsKHR( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( PerformanceCounterDescriptionFlagsKHR value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & PerformanceCounterDescriptionFlagBitsKHR::ePerformanceImpacting ) result += "PerformanceImpacting | ";
+ if ( value & PerformanceCounterDescriptionFlagBitsKHR::eConcurrentlyImpacted ) result += "ConcurrentlyImpacted | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using PipelineCacheCreateFlags = Flags<PipelineCacheCreateFlagBits, VkPipelineCacheCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCacheCreateFlags )
+ {
+ return "{}";
+ }
+
+ using PipelineColorBlendStateCreateFlags = Flags<PipelineColorBlendStateCreateFlagBits, VkPipelineColorBlendStateCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineColorBlendStateCreateFlags )
+ {
+ return "{}";
+ }
+
+ using PipelineCompilerControlFlagsAMD = Flags<PipelineCompilerControlFlagBitsAMD, VkPipelineCompilerControlFlagsAMD>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCompilerControlFlagsAMD )
+ {
+ return "{}";
+ }
+
+ enum class PipelineCoverageModulationStateCreateFlagBitsNV
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCoverageModulationStateCreateFlagBitsNV )
+ {
+ return "(void)";
+ }
+
+ using PipelineCoverageModulationStateCreateFlagsNV = Flags<PipelineCoverageModulationStateCreateFlagBitsNV, VkPipelineCoverageModulationStateCreateFlagsNV>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCoverageModulationStateCreateFlagsNV )
+ {
+ return "{}";
+ }
+
+ enum class PipelineCoverageReductionStateCreateFlagBitsNV
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCoverageReductionStateCreateFlagBitsNV )
+ {
+ return "(void)";
+ }
+
+ using PipelineCoverageReductionStateCreateFlagsNV = Flags<PipelineCoverageReductionStateCreateFlagBitsNV, VkPipelineCoverageReductionStateCreateFlagsNV>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCoverageReductionStateCreateFlagsNV )
+ {
+ return "{}";
+ }
+
+ enum class PipelineCoverageToColorStateCreateFlagBitsNV
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCoverageToColorStateCreateFlagBitsNV )
+ {
+ return "(void)";
+ }
+
+ using PipelineCoverageToColorStateCreateFlagsNV = Flags<PipelineCoverageToColorStateCreateFlagBitsNV, VkPipelineCoverageToColorStateCreateFlagsNV>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCoverageToColorStateCreateFlagsNV )
+ {
+ return "{}";
+ }
+
+ using PipelineCreateFlags = Flags<PipelineCreateFlagBits, VkPipelineCreateFlags>;
+
+ template <> struct FlagTraits<PipelineCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(PipelineCreateFlagBits::eDisableOptimization) | VkFlags(PipelineCreateFlagBits::eAllowDerivatives) | VkFlags(PipelineCreateFlagBits::eDerivative) | VkFlags(PipelineCreateFlagBits::eViewIndexFromDeviceIndex) | VkFlags(PipelineCreateFlagBits::eDispatchBase) | VkFlags(PipelineCreateFlagBits::eDeferCompileNV) | VkFlags(PipelineCreateFlagBits::eCaptureStatisticsKHR) | VkFlags(PipelineCreateFlagBits::eCaptureInternalRepresentationsKHR)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCreateFlags operator|( PipelineCreateFlagBits bit0, PipelineCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCreateFlags operator&( PipelineCreateFlagBits bit0, PipelineCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCreateFlags operator^( PipelineCreateFlagBits bit0, PipelineCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCreateFlags operator~( PipelineCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( PipelineCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & PipelineCreateFlagBits::eDisableOptimization ) result += "DisableOptimization | ";
+ if ( value & PipelineCreateFlagBits::eAllowDerivatives ) result += "AllowDerivatives | ";
+ if ( value & PipelineCreateFlagBits::eDerivative ) result += "Derivative | ";
+ if ( value & PipelineCreateFlagBits::eViewIndexFromDeviceIndex ) result += "ViewIndexFromDeviceIndex | ";
+ if ( value & PipelineCreateFlagBits::eDispatchBase ) result += "DispatchBase | ";
+ if ( value & PipelineCreateFlagBits::eDeferCompileNV ) result += "DeferCompileNV | ";
+ if ( value & PipelineCreateFlagBits::eCaptureStatisticsKHR ) result += "CaptureStatisticsKHR | ";
+ if ( value & PipelineCreateFlagBits::eCaptureInternalRepresentationsKHR ) result += "CaptureInternalRepresentationsKHR | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using PipelineCreationFeedbackFlagsEXT = Flags<PipelineCreationFeedbackFlagBitsEXT, VkPipelineCreationFeedbackFlagsEXT>;
+
+ template <> struct FlagTraits<PipelineCreationFeedbackFlagBitsEXT>
+ {
+ enum
+ {
+ allFlags = VkFlags(PipelineCreationFeedbackFlagBitsEXT::eValid) | VkFlags(PipelineCreationFeedbackFlagBitsEXT::eApplicationPipelineCacheHit) | VkFlags(PipelineCreationFeedbackFlagBitsEXT::eBasePipelineAcceleration)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCreationFeedbackFlagsEXT operator|( PipelineCreationFeedbackFlagBitsEXT bit0, PipelineCreationFeedbackFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineCreationFeedbackFlagsEXT( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCreationFeedbackFlagsEXT operator&( PipelineCreationFeedbackFlagBitsEXT bit0, PipelineCreationFeedbackFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineCreationFeedbackFlagsEXT( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCreationFeedbackFlagsEXT operator^( PipelineCreationFeedbackFlagBitsEXT bit0, PipelineCreationFeedbackFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineCreationFeedbackFlagsEXT( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCreationFeedbackFlagsEXT operator~( PipelineCreationFeedbackFlagBitsEXT bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( PipelineCreationFeedbackFlagsEXT( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineCreationFeedbackFlagsEXT value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & PipelineCreationFeedbackFlagBitsEXT::eValid ) result += "Valid | ";
+ if ( value & PipelineCreationFeedbackFlagBitsEXT::eApplicationPipelineCacheHit ) result += "ApplicationPipelineCacheHit | ";
+ if ( value & PipelineCreationFeedbackFlagBitsEXT::eBasePipelineAcceleration ) result += "BasePipelineAcceleration | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using PipelineDepthStencilStateCreateFlags = Flags<PipelineDepthStencilStateCreateFlagBits, VkPipelineDepthStencilStateCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineDepthStencilStateCreateFlags )
+ {
+ return "{}";
+ }
+
+ enum class PipelineDiscardRectangleStateCreateFlagBitsEXT
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineDiscardRectangleStateCreateFlagBitsEXT )
+ {
+ return "(void)";
+ }
+
+ using PipelineDiscardRectangleStateCreateFlagsEXT = Flags<PipelineDiscardRectangleStateCreateFlagBitsEXT, VkPipelineDiscardRectangleStateCreateFlagsEXT>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineDiscardRectangleStateCreateFlagsEXT )
+ {
+ return "{}";
+ }
+
+ using PipelineDynamicStateCreateFlags = Flags<PipelineDynamicStateCreateFlagBits, VkPipelineDynamicStateCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineDynamicStateCreateFlags )
+ {
+ return "{}";
+ }
+
+ using PipelineInputAssemblyStateCreateFlags = Flags<PipelineInputAssemblyStateCreateFlagBits, VkPipelineInputAssemblyStateCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineInputAssemblyStateCreateFlags )
+ {
+ return "{}";
+ }
+
+ using PipelineLayoutCreateFlags = Flags<PipelineLayoutCreateFlagBits, VkPipelineLayoutCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineLayoutCreateFlags )
+ {
+ return "{}";
+ }
+
+ using PipelineMultisampleStateCreateFlags = Flags<PipelineMultisampleStateCreateFlagBits, VkPipelineMultisampleStateCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineMultisampleStateCreateFlags )
+ {
+ return "{}";
+ }
+
+ enum class PipelineRasterizationConservativeStateCreateFlagBitsEXT
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineRasterizationConservativeStateCreateFlagBitsEXT )
+ {
+ return "(void)";
+ }
+
+ using PipelineRasterizationConservativeStateCreateFlagsEXT = Flags<PipelineRasterizationConservativeStateCreateFlagBitsEXT, VkPipelineRasterizationConservativeStateCreateFlagsEXT>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineRasterizationConservativeStateCreateFlagsEXT )
+ {
+ return "{}";
+ }
+
+ enum class PipelineRasterizationDepthClipStateCreateFlagBitsEXT
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineRasterizationDepthClipStateCreateFlagBitsEXT )
+ {
+ return "(void)";
+ }
+
+ using PipelineRasterizationDepthClipStateCreateFlagsEXT = Flags<PipelineRasterizationDepthClipStateCreateFlagBitsEXT, VkPipelineRasterizationDepthClipStateCreateFlagsEXT>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineRasterizationDepthClipStateCreateFlagsEXT )
+ {
+ return "{}";
+ }
+
+ using PipelineRasterizationStateCreateFlags = Flags<PipelineRasterizationStateCreateFlagBits, VkPipelineRasterizationStateCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineRasterizationStateCreateFlags )
+ {
+ return "{}";
+ }
+
+ enum class PipelineRasterizationStateStreamCreateFlagBitsEXT
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineRasterizationStateStreamCreateFlagBitsEXT )
+ {
+ return "(void)";
+ }
+
+ using PipelineRasterizationStateStreamCreateFlagsEXT = Flags<PipelineRasterizationStateStreamCreateFlagBitsEXT, VkPipelineRasterizationStateStreamCreateFlagsEXT>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineRasterizationStateStreamCreateFlagsEXT )
+ {
+ return "{}";
+ }
+
+ using PipelineShaderStageCreateFlags = Flags<PipelineShaderStageCreateFlagBits, VkPipelineShaderStageCreateFlags>;
+
+ template <> struct FlagTraits<PipelineShaderStageCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(PipelineShaderStageCreateFlagBits::eAllowVaryingSubgroupSizeEXT) | VkFlags(PipelineShaderStageCreateFlagBits::eRequireFullSubgroupsEXT)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineShaderStageCreateFlags operator|( PipelineShaderStageCreateFlagBits bit0, PipelineShaderStageCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineShaderStageCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineShaderStageCreateFlags operator&( PipelineShaderStageCreateFlagBits bit0, PipelineShaderStageCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineShaderStageCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineShaderStageCreateFlags operator^( PipelineShaderStageCreateFlagBits bit0, PipelineShaderStageCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineShaderStageCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineShaderStageCreateFlags operator~( PipelineShaderStageCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( PipelineShaderStageCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineShaderStageCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & PipelineShaderStageCreateFlagBits::eAllowVaryingSubgroupSizeEXT ) result += "AllowVaryingSubgroupSizeEXT | ";
+ if ( value & PipelineShaderStageCreateFlagBits::eRequireFullSubgroupsEXT ) result += "RequireFullSubgroupsEXT | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using PipelineStageFlags = Flags<PipelineStageFlagBits, VkPipelineStageFlags>;
+
+ template <> struct FlagTraits<PipelineStageFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(PipelineStageFlagBits::eTopOfPipe) | VkFlags(PipelineStageFlagBits::eDrawIndirect) | VkFlags(PipelineStageFlagBits::eVertexInput) | VkFlags(PipelineStageFlagBits::eVertexShader) | VkFlags(PipelineStageFlagBits::eTessellationControlShader) | VkFlags(PipelineStageFlagBits::eTessellationEvaluationShader) | VkFlags(PipelineStageFlagBits::eGeometryShader) | VkFlags(PipelineStageFlagBits::eFragmentShader) | VkFlags(PipelineStageFlagBits::eEarlyFragmentTests) | VkFlags(PipelineStageFlagBits::eLateFragmentTests) | VkFlags(PipelineStageFlagBits::eColorAttachmentOutput) | VkFlags(PipelineStageFlagBits::eComputeShader) | VkFlags(PipelineStageFlagBits::eTransfer) | VkFlags(PipelineStageFlagBits::eBottomOfPipe) | VkFlags(PipelineStageFlagBits::eHost) | VkFlags(PipelineStageFlagBits::eAllGraphics) | VkFlags(PipelineStageFlagBits::eAllCommands) | VkFlags(PipelineStageFlagBits::eTransformFeedbackEXT) | VkFlags(PipelineStageFlagBits::eConditionalRenderingEXT) | VkFlags(PipelineStageFlagBits::eCommandProcessNVX) | VkFlags(PipelineStageFlagBits::eShadingRateImageNV) | VkFlags(PipelineStageFlagBits::eRayTracingShaderNV) | VkFlags(PipelineStageFlagBits::eAccelerationStructureBuildNV) | VkFlags(PipelineStageFlagBits::eTaskShaderNV) | VkFlags(PipelineStageFlagBits::eMeshShaderNV) | VkFlags(PipelineStageFlagBits::eFragmentDensityProcessEXT)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineStageFlags operator|( PipelineStageFlagBits bit0, PipelineStageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineStageFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineStageFlags operator&( PipelineStageFlagBits bit0, PipelineStageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineStageFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineStageFlags operator^( PipelineStageFlagBits bit0, PipelineStageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return PipelineStageFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineStageFlags operator~( PipelineStageFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( PipelineStageFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineStageFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & PipelineStageFlagBits::eTopOfPipe ) result += "TopOfPipe | ";
+ if ( value & PipelineStageFlagBits::eDrawIndirect ) result += "DrawIndirect | ";
+ if ( value & PipelineStageFlagBits::eVertexInput ) result += "VertexInput | ";
+ if ( value & PipelineStageFlagBits::eVertexShader ) result += "VertexShader | ";
+ if ( value & PipelineStageFlagBits::eTessellationControlShader ) result += "TessellationControlShader | ";
+ if ( value & PipelineStageFlagBits::eTessellationEvaluationShader ) result += "TessellationEvaluationShader | ";
+ if ( value & PipelineStageFlagBits::eGeometryShader ) result += "GeometryShader | ";
+ if ( value & PipelineStageFlagBits::eFragmentShader ) result += "FragmentShader | ";
+ if ( value & PipelineStageFlagBits::eEarlyFragmentTests ) result += "EarlyFragmentTests | ";
+ if ( value & PipelineStageFlagBits::eLateFragmentTests ) result += "LateFragmentTests | ";
+ if ( value & PipelineStageFlagBits::eColorAttachmentOutput ) result += "ColorAttachmentOutput | ";
+ if ( value & PipelineStageFlagBits::eComputeShader ) result += "ComputeShader | ";
+ if ( value & PipelineStageFlagBits::eTransfer ) result += "Transfer | ";
+ if ( value & PipelineStageFlagBits::eBottomOfPipe ) result += "BottomOfPipe | ";
+ if ( value & PipelineStageFlagBits::eHost ) result += "Host | ";
+ if ( value & PipelineStageFlagBits::eAllGraphics ) result += "AllGraphics | ";
+ if ( value & PipelineStageFlagBits::eAllCommands ) result += "AllCommands | ";
+ if ( value & PipelineStageFlagBits::eTransformFeedbackEXT ) result += "TransformFeedbackEXT | ";
+ if ( value & PipelineStageFlagBits::eConditionalRenderingEXT ) result += "ConditionalRenderingEXT | ";
+ if ( value & PipelineStageFlagBits::eCommandProcessNVX ) result += "CommandProcessNVX | ";
+ if ( value & PipelineStageFlagBits::eShadingRateImageNV ) result += "ShadingRateImageNV | ";
+ if ( value & PipelineStageFlagBits::eRayTracingShaderNV ) result += "RayTracingShaderNV | ";
+ if ( value & PipelineStageFlagBits::eAccelerationStructureBuildNV ) result += "AccelerationStructureBuildNV | ";
+ if ( value & PipelineStageFlagBits::eTaskShaderNV ) result += "TaskShaderNV | ";
+ if ( value & PipelineStageFlagBits::eMeshShaderNV ) result += "MeshShaderNV | ";
+ if ( value & PipelineStageFlagBits::eFragmentDensityProcessEXT ) result += "FragmentDensityProcessEXT | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using PipelineTessellationStateCreateFlags = Flags<PipelineTessellationStateCreateFlagBits, VkPipelineTessellationStateCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineTessellationStateCreateFlags )
+ {
+ return "{}";
+ }
+
+ using PipelineVertexInputStateCreateFlags = Flags<PipelineVertexInputStateCreateFlagBits, VkPipelineVertexInputStateCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineVertexInputStateCreateFlags )
+ {
+ return "{}";
+ }
+
+ using PipelineViewportStateCreateFlags = Flags<PipelineViewportStateCreateFlagBits, VkPipelineViewportStateCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineViewportStateCreateFlags )
+ {
+ return "{}";
+ }
+
+ enum class PipelineViewportSwizzleStateCreateFlagBitsNV
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineViewportSwizzleStateCreateFlagBitsNV )
+ {
+ return "(void)";
+ }
+
+ using PipelineViewportSwizzleStateCreateFlagsNV = Flags<PipelineViewportSwizzleStateCreateFlagBitsNV, VkPipelineViewportSwizzleStateCreateFlagsNV>;
+
+ VULKAN_HPP_INLINE std::string to_string( PipelineViewportSwizzleStateCreateFlagsNV )
+ {
+ return "{}";
+ }
+
+ using QueryControlFlags = Flags<QueryControlFlagBits, VkQueryControlFlags>;
+
+ template <> struct FlagTraits<QueryControlFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(QueryControlFlagBits::ePrecise)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryControlFlags operator|( QueryControlFlagBits bit0, QueryControlFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueryControlFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryControlFlags operator&( QueryControlFlagBits bit0, QueryControlFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueryControlFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryControlFlags operator^( QueryControlFlagBits bit0, QueryControlFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueryControlFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryControlFlags operator~( QueryControlFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( QueryControlFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( QueryControlFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & QueryControlFlagBits::ePrecise ) result += "Precise | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using QueryPipelineStatisticFlags = Flags<QueryPipelineStatisticFlagBits, VkQueryPipelineStatisticFlags>;
+
+ template <> struct FlagTraits<QueryPipelineStatisticFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(QueryPipelineStatisticFlagBits::eInputAssemblyVertices) | VkFlags(QueryPipelineStatisticFlagBits::eInputAssemblyPrimitives) | VkFlags(QueryPipelineStatisticFlagBits::eVertexShaderInvocations) | VkFlags(QueryPipelineStatisticFlagBits::eGeometryShaderInvocations) | VkFlags(QueryPipelineStatisticFlagBits::eGeometryShaderPrimitives) | VkFlags(QueryPipelineStatisticFlagBits::eClippingInvocations) | VkFlags(QueryPipelineStatisticFlagBits::eClippingPrimitives) | VkFlags(QueryPipelineStatisticFlagBits::eFragmentShaderInvocations) | VkFlags(QueryPipelineStatisticFlagBits::eTessellationControlShaderPatches) | VkFlags(QueryPipelineStatisticFlagBits::eTessellationEvaluationShaderInvocations) | VkFlags(QueryPipelineStatisticFlagBits::eComputeShaderInvocations)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryPipelineStatisticFlags operator|( QueryPipelineStatisticFlagBits bit0, QueryPipelineStatisticFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueryPipelineStatisticFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryPipelineStatisticFlags operator&( QueryPipelineStatisticFlagBits bit0, QueryPipelineStatisticFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueryPipelineStatisticFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryPipelineStatisticFlags operator^( QueryPipelineStatisticFlagBits bit0, QueryPipelineStatisticFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueryPipelineStatisticFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryPipelineStatisticFlags operator~( QueryPipelineStatisticFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( QueryPipelineStatisticFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( QueryPipelineStatisticFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & QueryPipelineStatisticFlagBits::eInputAssemblyVertices ) result += "InputAssemblyVertices | ";
+ if ( value & QueryPipelineStatisticFlagBits::eInputAssemblyPrimitives ) result += "InputAssemblyPrimitives | ";
+ if ( value & QueryPipelineStatisticFlagBits::eVertexShaderInvocations ) result += "VertexShaderInvocations | ";
+ if ( value & QueryPipelineStatisticFlagBits::eGeometryShaderInvocations ) result += "GeometryShaderInvocations | ";
+ if ( value & QueryPipelineStatisticFlagBits::eGeometryShaderPrimitives ) result += "GeometryShaderPrimitives | ";
+ if ( value & QueryPipelineStatisticFlagBits::eClippingInvocations ) result += "ClippingInvocations | ";
+ if ( value & QueryPipelineStatisticFlagBits::eClippingPrimitives ) result += "ClippingPrimitives | ";
+ if ( value & QueryPipelineStatisticFlagBits::eFragmentShaderInvocations ) result += "FragmentShaderInvocations | ";
+ if ( value & QueryPipelineStatisticFlagBits::eTessellationControlShaderPatches ) result += "TessellationControlShaderPatches | ";
+ if ( value & QueryPipelineStatisticFlagBits::eTessellationEvaluationShaderInvocations ) result += "TessellationEvaluationShaderInvocations | ";
+ if ( value & QueryPipelineStatisticFlagBits::eComputeShaderInvocations ) result += "ComputeShaderInvocations | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using QueryPoolCreateFlags = Flags<QueryPoolCreateFlagBits, VkQueryPoolCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( QueryPoolCreateFlags )
+ {
+ return "{}";
+ }
+
+ using QueryResultFlags = Flags<QueryResultFlagBits, VkQueryResultFlags>;
+
+ template <> struct FlagTraits<QueryResultFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(QueryResultFlagBits::e64) | VkFlags(QueryResultFlagBits::eWait) | VkFlags(QueryResultFlagBits::eWithAvailability) | VkFlags(QueryResultFlagBits::ePartial)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryResultFlags operator|( QueryResultFlagBits bit0, QueryResultFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueryResultFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryResultFlags operator&( QueryResultFlagBits bit0, QueryResultFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueryResultFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryResultFlags operator^( QueryResultFlagBits bit0, QueryResultFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueryResultFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueryResultFlags operator~( QueryResultFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( QueryResultFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( QueryResultFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & QueryResultFlagBits::e64 ) result += "64 | ";
+ if ( value & QueryResultFlagBits::eWait ) result += "Wait | ";
+ if ( value & QueryResultFlagBits::eWithAvailability ) result += "WithAvailability | ";
+ if ( value & QueryResultFlagBits::ePartial ) result += "Partial | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using QueueFlags = Flags<QueueFlagBits, VkQueueFlags>;
+
+ template <> struct FlagTraits<QueueFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(QueueFlagBits::eGraphics) | VkFlags(QueueFlagBits::eCompute) | VkFlags(QueueFlagBits::eTransfer) | VkFlags(QueueFlagBits::eSparseBinding) | VkFlags(QueueFlagBits::eProtected)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueueFlags operator|( QueueFlagBits bit0, QueueFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueueFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueueFlags operator&( QueueFlagBits bit0, QueueFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueueFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueueFlags operator^( QueueFlagBits bit0, QueueFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return QueueFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR QueueFlags operator~( QueueFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( QueueFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( QueueFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & QueueFlagBits::eGraphics ) result += "Graphics | ";
+ if ( value & QueueFlagBits::eCompute ) result += "Compute | ";
+ if ( value & QueueFlagBits::eTransfer ) result += "Transfer | ";
+ if ( value & QueueFlagBits::eSparseBinding ) result += "SparseBinding | ";
+ if ( value & QueueFlagBits::eProtected ) result += "Protected | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using RenderPassCreateFlags = Flags<RenderPassCreateFlagBits, VkRenderPassCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( RenderPassCreateFlags )
+ {
+ return "{}";
+ }
+
+ using ResolveModeFlags = Flags<ResolveModeFlagBits, VkResolveModeFlags>;
+
+ template <> struct FlagTraits<ResolveModeFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ResolveModeFlagBits::eNone) | VkFlags(ResolveModeFlagBits::eSampleZero) | VkFlags(ResolveModeFlagBits::eAverage) | VkFlags(ResolveModeFlagBits::eMin) | VkFlags(ResolveModeFlagBits::eMax)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ResolveModeFlags operator|( ResolveModeFlagBits bit0, ResolveModeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ResolveModeFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ResolveModeFlags operator&( ResolveModeFlagBits bit0, ResolveModeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ResolveModeFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ResolveModeFlags operator^( ResolveModeFlagBits bit0, ResolveModeFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ResolveModeFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ResolveModeFlags operator~( ResolveModeFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ResolveModeFlags( bits ) );
+ }
+
+ using ResolveModeFlagsKHR = ResolveModeFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( ResolveModeFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ResolveModeFlagBits::eSampleZero ) result += "SampleZero | ";
+ if ( value & ResolveModeFlagBits::eAverage ) result += "Average | ";
+ if ( value & ResolveModeFlagBits::eMin ) result += "Min | ";
+ if ( value & ResolveModeFlagBits::eMax ) result += "Max | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using SampleCountFlags = Flags<SampleCountFlagBits, VkSampleCountFlags>;
+
+ template <> struct FlagTraits<SampleCountFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(SampleCountFlagBits::e1) | VkFlags(SampleCountFlagBits::e2) | VkFlags(SampleCountFlagBits::e4) | VkFlags(SampleCountFlagBits::e8) | VkFlags(SampleCountFlagBits::e16) | VkFlags(SampleCountFlagBits::e32) | VkFlags(SampleCountFlagBits::e64)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SampleCountFlags operator|( SampleCountFlagBits bit0, SampleCountFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SampleCountFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SampleCountFlags operator&( SampleCountFlagBits bit0, SampleCountFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SampleCountFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SampleCountFlags operator^( SampleCountFlagBits bit0, SampleCountFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SampleCountFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SampleCountFlags operator~( SampleCountFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SampleCountFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( SampleCountFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SampleCountFlagBits::e1 ) result += "1 | ";
+ if ( value & SampleCountFlagBits::e2 ) result += "2 | ";
+ if ( value & SampleCountFlagBits::e4 ) result += "4 | ";
+ if ( value & SampleCountFlagBits::e8 ) result += "8 | ";
+ if ( value & SampleCountFlagBits::e16 ) result += "16 | ";
+ if ( value & SampleCountFlagBits::e32 ) result += "32 | ";
+ if ( value & SampleCountFlagBits::e64 ) result += "64 | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using SamplerCreateFlags = Flags<SamplerCreateFlagBits, VkSamplerCreateFlags>;
+
+ template <> struct FlagTraits<SamplerCreateFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(SamplerCreateFlagBits::eSubsampledEXT) | VkFlags(SamplerCreateFlagBits::eSubsampledCoarseReconstructionEXT)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SamplerCreateFlags operator|( SamplerCreateFlagBits bit0, SamplerCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SamplerCreateFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SamplerCreateFlags operator&( SamplerCreateFlagBits bit0, SamplerCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SamplerCreateFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SamplerCreateFlags operator^( SamplerCreateFlagBits bit0, SamplerCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SamplerCreateFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SamplerCreateFlags operator~( SamplerCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SamplerCreateFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( SamplerCreateFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SamplerCreateFlagBits::eSubsampledEXT ) result += "SubsampledEXT | ";
+ if ( value & SamplerCreateFlagBits::eSubsampledCoarseReconstructionEXT ) result += "SubsampledCoarseReconstructionEXT | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using SemaphoreCreateFlags = Flags<SemaphoreCreateFlagBits, VkSemaphoreCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( SemaphoreCreateFlags )
+ {
+ return "{}";
+ }
+
+ using SemaphoreImportFlags = Flags<SemaphoreImportFlagBits, VkSemaphoreImportFlags>;
+
+ template <> struct FlagTraits<SemaphoreImportFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(SemaphoreImportFlagBits::eTemporary)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SemaphoreImportFlags operator|( SemaphoreImportFlagBits bit0, SemaphoreImportFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SemaphoreImportFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SemaphoreImportFlags operator&( SemaphoreImportFlagBits bit0, SemaphoreImportFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SemaphoreImportFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SemaphoreImportFlags operator^( SemaphoreImportFlagBits bit0, SemaphoreImportFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SemaphoreImportFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SemaphoreImportFlags operator~( SemaphoreImportFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SemaphoreImportFlags( bits ) );
+ }
+
+ using SemaphoreImportFlagsKHR = SemaphoreImportFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( SemaphoreImportFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SemaphoreImportFlagBits::eTemporary ) result += "Temporary | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using SemaphoreWaitFlags = Flags<SemaphoreWaitFlagBits, VkSemaphoreWaitFlags>;
+
+ template <> struct FlagTraits<SemaphoreWaitFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(SemaphoreWaitFlagBits::eAny)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SemaphoreWaitFlags operator|( SemaphoreWaitFlagBits bit0, SemaphoreWaitFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SemaphoreWaitFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SemaphoreWaitFlags operator&( SemaphoreWaitFlagBits bit0, SemaphoreWaitFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SemaphoreWaitFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SemaphoreWaitFlags operator^( SemaphoreWaitFlagBits bit0, SemaphoreWaitFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SemaphoreWaitFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SemaphoreWaitFlags operator~( SemaphoreWaitFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SemaphoreWaitFlags( bits ) );
+ }
+
+ using SemaphoreWaitFlagsKHR = SemaphoreWaitFlags;
+
+ VULKAN_HPP_INLINE std::string to_string( SemaphoreWaitFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SemaphoreWaitFlagBits::eAny ) result += "Any | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ShaderCorePropertiesFlagsAMD = Flags<ShaderCorePropertiesFlagBitsAMD, VkShaderCorePropertiesFlagsAMD>;
+
+ VULKAN_HPP_INLINE std::string to_string( ShaderCorePropertiesFlagsAMD )
+ {
+ return "{}";
+ }
+
+ using ShaderModuleCreateFlags = Flags<ShaderModuleCreateFlagBits, VkShaderModuleCreateFlags>;
+
+ VULKAN_HPP_INLINE std::string to_string( ShaderModuleCreateFlags )
+ {
+ return "{}";
+ }
+
+ using ShaderStageFlags = Flags<ShaderStageFlagBits, VkShaderStageFlags>;
+
+ template <> struct FlagTraits<ShaderStageFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(ShaderStageFlagBits::eVertex) | VkFlags(ShaderStageFlagBits::eTessellationControl) | VkFlags(ShaderStageFlagBits::eTessellationEvaluation) | VkFlags(ShaderStageFlagBits::eGeometry) | VkFlags(ShaderStageFlagBits::eFragment) | VkFlags(ShaderStageFlagBits::eCompute) | VkFlags(ShaderStageFlagBits::eAllGraphics) | VkFlags(ShaderStageFlagBits::eAll) | VkFlags(ShaderStageFlagBits::eRaygenNV) | VkFlags(ShaderStageFlagBits::eAnyHitNV) | VkFlags(ShaderStageFlagBits::eClosestHitNV) | VkFlags(ShaderStageFlagBits::eMissNV) | VkFlags(ShaderStageFlagBits::eIntersectionNV) | VkFlags(ShaderStageFlagBits::eCallableNV) | VkFlags(ShaderStageFlagBits::eTaskNV) | VkFlags(ShaderStageFlagBits::eMeshNV)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ShaderStageFlags operator|( ShaderStageFlagBits bit0, ShaderStageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ShaderStageFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ShaderStageFlags operator&( ShaderStageFlagBits bit0, ShaderStageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ShaderStageFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ShaderStageFlags operator^( ShaderStageFlagBits bit0, ShaderStageFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ShaderStageFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ShaderStageFlags operator~( ShaderStageFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ShaderStageFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ShaderStageFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ShaderStageFlagBits::eVertex ) result += "Vertex | ";
+ if ( value & ShaderStageFlagBits::eTessellationControl ) result += "TessellationControl | ";
+ if ( value & ShaderStageFlagBits::eTessellationEvaluation ) result += "TessellationEvaluation | ";
+ if ( value & ShaderStageFlagBits::eGeometry ) result += "Geometry | ";
+ if ( value & ShaderStageFlagBits::eFragment ) result += "Fragment | ";
+ if ( value & ShaderStageFlagBits::eCompute ) result += "Compute | ";
+ if ( value & ShaderStageFlagBits::eRaygenNV ) result += "RaygenNV | ";
+ if ( value & ShaderStageFlagBits::eAnyHitNV ) result += "AnyHitNV | ";
+ if ( value & ShaderStageFlagBits::eClosestHitNV ) result += "ClosestHitNV | ";
+ if ( value & ShaderStageFlagBits::eMissNV ) result += "MissNV | ";
+ if ( value & ShaderStageFlagBits::eIntersectionNV ) result += "IntersectionNV | ";
+ if ( value & ShaderStageFlagBits::eCallableNV ) result += "CallableNV | ";
+ if ( value & ShaderStageFlagBits::eTaskNV ) result += "TaskNV | ";
+ if ( value & ShaderStageFlagBits::eMeshNV ) result += "MeshNV | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using SparseImageFormatFlags = Flags<SparseImageFormatFlagBits, VkSparseImageFormatFlags>;
+
+ template <> struct FlagTraits<SparseImageFormatFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(SparseImageFormatFlagBits::eSingleMiptail) | VkFlags(SparseImageFormatFlagBits::eAlignedMipSize) | VkFlags(SparseImageFormatFlagBits::eNonstandardBlockSize)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SparseImageFormatFlags operator|( SparseImageFormatFlagBits bit0, SparseImageFormatFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SparseImageFormatFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SparseImageFormatFlags operator&( SparseImageFormatFlagBits bit0, SparseImageFormatFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SparseImageFormatFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SparseImageFormatFlags operator^( SparseImageFormatFlagBits bit0, SparseImageFormatFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SparseImageFormatFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SparseImageFormatFlags operator~( SparseImageFormatFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SparseImageFormatFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( SparseImageFormatFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SparseImageFormatFlagBits::eSingleMiptail ) result += "SingleMiptail | ";
+ if ( value & SparseImageFormatFlagBits::eAlignedMipSize ) result += "AlignedMipSize | ";
+ if ( value & SparseImageFormatFlagBits::eNonstandardBlockSize ) result += "NonstandardBlockSize | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using SparseMemoryBindFlags = Flags<SparseMemoryBindFlagBits, VkSparseMemoryBindFlags>;
+
+ template <> struct FlagTraits<SparseMemoryBindFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(SparseMemoryBindFlagBits::eMetadata)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SparseMemoryBindFlags operator|( SparseMemoryBindFlagBits bit0, SparseMemoryBindFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SparseMemoryBindFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SparseMemoryBindFlags operator&( SparseMemoryBindFlagBits bit0, SparseMemoryBindFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SparseMemoryBindFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SparseMemoryBindFlags operator^( SparseMemoryBindFlagBits bit0, SparseMemoryBindFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SparseMemoryBindFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SparseMemoryBindFlags operator~( SparseMemoryBindFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SparseMemoryBindFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( SparseMemoryBindFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SparseMemoryBindFlagBits::eMetadata ) result += "Metadata | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using StencilFaceFlags = Flags<StencilFaceFlagBits, VkStencilFaceFlags>;
+
+ template <> struct FlagTraits<StencilFaceFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(StencilFaceFlagBits::eFront) | VkFlags(StencilFaceFlagBits::eBack) | VkFlags(StencilFaceFlagBits::eFrontAndBack)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR StencilFaceFlags operator|( StencilFaceFlagBits bit0, StencilFaceFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return StencilFaceFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR StencilFaceFlags operator&( StencilFaceFlagBits bit0, StencilFaceFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return StencilFaceFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR StencilFaceFlags operator^( StencilFaceFlagBits bit0, StencilFaceFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return StencilFaceFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR StencilFaceFlags operator~( StencilFaceFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( StencilFaceFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( StencilFaceFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & StencilFaceFlagBits::eFront ) result += "Front | ";
+ if ( value & StencilFaceFlagBits::eBack ) result += "Back | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+#ifdef VK_USE_PLATFORM_GGP
+ enum class StreamDescriptorSurfaceCreateFlagBitsGGP
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( StreamDescriptorSurfaceCreateFlagBitsGGP )
+ {
+ return "(void)";
+ }
+
+ using StreamDescriptorSurfaceCreateFlagsGGP = Flags<StreamDescriptorSurfaceCreateFlagBitsGGP, VkStreamDescriptorSurfaceCreateFlagsGGP>;
+
+ VULKAN_HPP_INLINE std::string to_string( StreamDescriptorSurfaceCreateFlagsGGP )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_GGP*/
+
+ using SubgroupFeatureFlags = Flags<SubgroupFeatureFlagBits, VkSubgroupFeatureFlags>;
+
+ template <> struct FlagTraits<SubgroupFeatureFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(SubgroupFeatureFlagBits::eBasic) | VkFlags(SubgroupFeatureFlagBits::eVote) | VkFlags(SubgroupFeatureFlagBits::eArithmetic) | VkFlags(SubgroupFeatureFlagBits::eBallot) | VkFlags(SubgroupFeatureFlagBits::eShuffle) | VkFlags(SubgroupFeatureFlagBits::eShuffleRelative) | VkFlags(SubgroupFeatureFlagBits::eClustered) | VkFlags(SubgroupFeatureFlagBits::eQuad) | VkFlags(SubgroupFeatureFlagBits::ePartitionedNV)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SubgroupFeatureFlags operator|( SubgroupFeatureFlagBits bit0, SubgroupFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SubgroupFeatureFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SubgroupFeatureFlags operator&( SubgroupFeatureFlagBits bit0, SubgroupFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SubgroupFeatureFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SubgroupFeatureFlags operator^( SubgroupFeatureFlagBits bit0, SubgroupFeatureFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SubgroupFeatureFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SubgroupFeatureFlags operator~( SubgroupFeatureFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SubgroupFeatureFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( SubgroupFeatureFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SubgroupFeatureFlagBits::eBasic ) result += "Basic | ";
+ if ( value & SubgroupFeatureFlagBits::eVote ) result += "Vote | ";
+ if ( value & SubgroupFeatureFlagBits::eArithmetic ) result += "Arithmetic | ";
+ if ( value & SubgroupFeatureFlagBits::eBallot ) result += "Ballot | ";
+ if ( value & SubgroupFeatureFlagBits::eShuffle ) result += "Shuffle | ";
+ if ( value & SubgroupFeatureFlagBits::eShuffleRelative ) result += "ShuffleRelative | ";
+ if ( value & SubgroupFeatureFlagBits::eClustered ) result += "Clustered | ";
+ if ( value & SubgroupFeatureFlagBits::eQuad ) result += "Quad | ";
+ if ( value & SubgroupFeatureFlagBits::ePartitionedNV ) result += "PartitionedNV | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using SubpassDescriptionFlags = Flags<SubpassDescriptionFlagBits, VkSubpassDescriptionFlags>;
+
+ template <> struct FlagTraits<SubpassDescriptionFlagBits>
+ {
+ enum
+ {
+ allFlags = VkFlags(SubpassDescriptionFlagBits::ePerViewAttributesNVX) | VkFlags(SubpassDescriptionFlagBits::ePerViewPositionXOnlyNVX)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SubpassDescriptionFlags operator|( SubpassDescriptionFlagBits bit0, SubpassDescriptionFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SubpassDescriptionFlags( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SubpassDescriptionFlags operator&( SubpassDescriptionFlagBits bit0, SubpassDescriptionFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SubpassDescriptionFlags( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SubpassDescriptionFlags operator^( SubpassDescriptionFlagBits bit0, SubpassDescriptionFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SubpassDescriptionFlags( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SubpassDescriptionFlags operator~( SubpassDescriptionFlagBits bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SubpassDescriptionFlags( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( SubpassDescriptionFlags value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SubpassDescriptionFlagBits::ePerViewAttributesNVX ) result += "PerViewAttributesNVX | ";
+ if ( value & SubpassDescriptionFlagBits::ePerViewPositionXOnlyNVX ) result += "PerViewPositionXOnlyNVX | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using SurfaceCounterFlagsEXT = Flags<SurfaceCounterFlagBitsEXT, VkSurfaceCounterFlagsEXT>;
+
+ template <> struct FlagTraits<SurfaceCounterFlagBitsEXT>
+ {
+ enum
+ {
+ allFlags = VkFlags(SurfaceCounterFlagBitsEXT::eVblank)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SurfaceCounterFlagsEXT operator|( SurfaceCounterFlagBitsEXT bit0, SurfaceCounterFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SurfaceCounterFlagsEXT( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SurfaceCounterFlagsEXT operator&( SurfaceCounterFlagBitsEXT bit0, SurfaceCounterFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SurfaceCounterFlagsEXT( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SurfaceCounterFlagsEXT operator^( SurfaceCounterFlagBitsEXT bit0, SurfaceCounterFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SurfaceCounterFlagsEXT( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SurfaceCounterFlagsEXT operator~( SurfaceCounterFlagBitsEXT bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SurfaceCounterFlagsEXT( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( SurfaceCounterFlagsEXT value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SurfaceCounterFlagBitsEXT::eVblank ) result += "Vblank | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using SurfaceTransformFlagsKHR = Flags<SurfaceTransformFlagBitsKHR, VkSurfaceTransformFlagsKHR>;
+
+ template <> struct FlagTraits<SurfaceTransformFlagBitsKHR>
+ {
+ enum
+ {
+ allFlags = VkFlags(SurfaceTransformFlagBitsKHR::eIdentity) | VkFlags(SurfaceTransformFlagBitsKHR::eRotate90) | VkFlags(SurfaceTransformFlagBitsKHR::eRotate180) | VkFlags(SurfaceTransformFlagBitsKHR::eRotate270) | VkFlags(SurfaceTransformFlagBitsKHR::eHorizontalMirror) | VkFlags(SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate90) | VkFlags(SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate180) | VkFlags(SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate270) | VkFlags(SurfaceTransformFlagBitsKHR::eInherit)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SurfaceTransformFlagsKHR operator|( SurfaceTransformFlagBitsKHR bit0, SurfaceTransformFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SurfaceTransformFlagsKHR( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SurfaceTransformFlagsKHR operator&( SurfaceTransformFlagBitsKHR bit0, SurfaceTransformFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SurfaceTransformFlagsKHR( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SurfaceTransformFlagsKHR operator^( SurfaceTransformFlagBitsKHR bit0, SurfaceTransformFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SurfaceTransformFlagsKHR( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SurfaceTransformFlagsKHR operator~( SurfaceTransformFlagBitsKHR bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SurfaceTransformFlagsKHR( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( SurfaceTransformFlagsKHR value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SurfaceTransformFlagBitsKHR::eIdentity ) result += "Identity | ";
+ if ( value & SurfaceTransformFlagBitsKHR::eRotate90 ) result += "Rotate90 | ";
+ if ( value & SurfaceTransformFlagBitsKHR::eRotate180 ) result += "Rotate180 | ";
+ if ( value & SurfaceTransformFlagBitsKHR::eRotate270 ) result += "Rotate270 | ";
+ if ( value & SurfaceTransformFlagBitsKHR::eHorizontalMirror ) result += "HorizontalMirror | ";
+ if ( value & SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate90 ) result += "HorizontalMirrorRotate90 | ";
+ if ( value & SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate180 ) result += "HorizontalMirrorRotate180 | ";
+ if ( value & SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate270 ) result += "HorizontalMirrorRotate270 | ";
+ if ( value & SurfaceTransformFlagBitsKHR::eInherit ) result += "Inherit | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using SwapchainCreateFlagsKHR = Flags<SwapchainCreateFlagBitsKHR, VkSwapchainCreateFlagsKHR>;
+
+ template <> struct FlagTraits<SwapchainCreateFlagBitsKHR>
+ {
+ enum
+ {
+ allFlags = VkFlags(SwapchainCreateFlagBitsKHR::eSplitInstanceBindRegions) | VkFlags(SwapchainCreateFlagBitsKHR::eProtected) | VkFlags(SwapchainCreateFlagBitsKHR::eMutableFormat)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SwapchainCreateFlagsKHR operator|( SwapchainCreateFlagBitsKHR bit0, SwapchainCreateFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SwapchainCreateFlagsKHR( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SwapchainCreateFlagsKHR operator&( SwapchainCreateFlagBitsKHR bit0, SwapchainCreateFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SwapchainCreateFlagsKHR( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SwapchainCreateFlagsKHR operator^( SwapchainCreateFlagBitsKHR bit0, SwapchainCreateFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return SwapchainCreateFlagsKHR( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR SwapchainCreateFlagsKHR operator~( SwapchainCreateFlagBitsKHR bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( SwapchainCreateFlagsKHR( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( SwapchainCreateFlagsKHR value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & SwapchainCreateFlagBitsKHR::eSplitInstanceBindRegions ) result += "SplitInstanceBindRegions | ";
+ if ( value & SwapchainCreateFlagBitsKHR::eProtected ) result += "Protected | ";
+ if ( value & SwapchainCreateFlagBitsKHR::eMutableFormat ) result += "MutableFormat | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ using ToolPurposeFlagsEXT = Flags<ToolPurposeFlagBitsEXT, VkToolPurposeFlagsEXT>;
+
+ template <> struct FlagTraits<ToolPurposeFlagBitsEXT>
+ {
+ enum
+ {
+ allFlags = VkFlags(ToolPurposeFlagBitsEXT::eValidation) | VkFlags(ToolPurposeFlagBitsEXT::eProfiling) | VkFlags(ToolPurposeFlagBitsEXT::eTracing) | VkFlags(ToolPurposeFlagBitsEXT::eAdditionalFeatures) | VkFlags(ToolPurposeFlagBitsEXT::eModifyingFeatures) | VkFlags(ToolPurposeFlagBitsEXT::eDebugReporting) | VkFlags(ToolPurposeFlagBitsEXT::eDebugMarkers)
+ };
+ };
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ToolPurposeFlagsEXT operator|( ToolPurposeFlagBitsEXT bit0, ToolPurposeFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ToolPurposeFlagsEXT( bit0 ) | bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ToolPurposeFlagsEXT operator&( ToolPurposeFlagBitsEXT bit0, ToolPurposeFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ToolPurposeFlagsEXT( bit0 ) & bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ToolPurposeFlagsEXT operator^( ToolPurposeFlagBitsEXT bit0, ToolPurposeFlagBitsEXT bit1 ) VULKAN_HPP_NOEXCEPT
+ {
+ return ToolPurposeFlagsEXT( bit0 ) ^ bit1;
+ }
+
+ VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ToolPurposeFlagsEXT operator~( ToolPurposeFlagBitsEXT bits ) VULKAN_HPP_NOEXCEPT
+ {
+ return ~( ToolPurposeFlagsEXT( bits ) );
+ }
+
+ VULKAN_HPP_INLINE std::string to_string( ToolPurposeFlagsEXT value )
+ {
+ if ( !value ) return "{}";
+ std::string result;
+
+ if ( value & ToolPurposeFlagBitsEXT::eValidation ) result += "Validation | ";
+ if ( value & ToolPurposeFlagBitsEXT::eProfiling ) result += "Profiling | ";
+ if ( value & ToolPurposeFlagBitsEXT::eTracing ) result += "Tracing | ";
+ if ( value & ToolPurposeFlagBitsEXT::eAdditionalFeatures ) result += "AdditionalFeatures | ";
+ if ( value & ToolPurposeFlagBitsEXT::eModifyingFeatures ) result += "ModifyingFeatures | ";
+ if ( value & ToolPurposeFlagBitsEXT::eDebugReporting ) result += "DebugReporting | ";
+ if ( value & ToolPurposeFlagBitsEXT::eDebugMarkers ) result += "DebugMarkers | ";
+ return "{ " + result.substr(0, result.size() - 3) + " }";
+ }
+
+ enum class ValidationCacheCreateFlagBitsEXT
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( ValidationCacheCreateFlagBitsEXT )
+ {
+ return "(void)";
+ }
+
+ using ValidationCacheCreateFlagsEXT = Flags<ValidationCacheCreateFlagBitsEXT, VkValidationCacheCreateFlagsEXT>;
+
+ VULKAN_HPP_INLINE std::string to_string( ValidationCacheCreateFlagsEXT )
+ {
+ return "{}";
+ }
+
+#ifdef VK_USE_PLATFORM_VI_NN
+ enum class ViSurfaceCreateFlagBitsNN
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( ViSurfaceCreateFlagBitsNN )
+ {
+ return "(void)";
+ }
+
+ using ViSurfaceCreateFlagsNN = Flags<ViSurfaceCreateFlagBitsNN, VkViSurfaceCreateFlagsNN>;
+
+ VULKAN_HPP_INLINE std::string to_string( ViSurfaceCreateFlagsNN )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_VI_NN*/
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ enum class WaylandSurfaceCreateFlagBitsKHR
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( WaylandSurfaceCreateFlagBitsKHR )
+ {
+ return "(void)";
+ }
+
+ using WaylandSurfaceCreateFlagsKHR = Flags<WaylandSurfaceCreateFlagBitsKHR, VkWaylandSurfaceCreateFlagsKHR>;
+
+ VULKAN_HPP_INLINE std::string to_string( WaylandSurfaceCreateFlagsKHR )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ enum class Win32SurfaceCreateFlagBitsKHR
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( Win32SurfaceCreateFlagBitsKHR )
+ {
+ return "(void)";
+ }
+
+ using Win32SurfaceCreateFlagsKHR = Flags<Win32SurfaceCreateFlagBitsKHR, VkWin32SurfaceCreateFlagsKHR>;
+
+ VULKAN_HPP_INLINE std::string to_string( Win32SurfaceCreateFlagsKHR )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ enum class XcbSurfaceCreateFlagBitsKHR
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( XcbSurfaceCreateFlagBitsKHR )
+ {
+ return "(void)";
+ }
+
+ using XcbSurfaceCreateFlagsKHR = Flags<XcbSurfaceCreateFlagBitsKHR, VkXcbSurfaceCreateFlagsKHR>;
+
+ VULKAN_HPP_INLINE std::string to_string( XcbSurfaceCreateFlagsKHR )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ enum class XlibSurfaceCreateFlagBitsKHR
+ {};
+
+ VULKAN_HPP_INLINE std::string to_string( XlibSurfaceCreateFlagBitsKHR )
+ {
+ return "(void)";
+ }
+
+ using XlibSurfaceCreateFlagsKHR = Flags<XlibSurfaceCreateFlagBitsKHR, VkXlibSurfaceCreateFlagsKHR>;
+
+ VULKAN_HPP_INLINE std::string to_string( XlibSurfaceCreateFlagsKHR )
+ {
+ return "{}";
+ }
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+} // namespace VULKAN_HPP_NAMESPACE
+
+#ifndef VULKAN_HPP_NO_EXCEPTIONS
+namespace std
+{
+ template <>
+ struct is_error_code_enum<VULKAN_HPP_NAMESPACE::Result> : public true_type
+ {};
+}
+#endif
+
+namespace VULKAN_HPP_NAMESPACE
+{
+#ifndef VULKAN_HPP_NO_EXCEPTIONS
+ class ErrorCategoryImpl : public std::error_category
+ {
+ public:
+ virtual const char* name() const VULKAN_HPP_NOEXCEPT override { return VULKAN_HPP_NAMESPACE_STRING"::Result"; }
+ virtual std::string message(int ev) const override { return to_string(static_cast<Result>(ev)); }
+ };
+
+ class Error
+ {
+ public:
+ Error() VULKAN_HPP_NOEXCEPT = default;
+ Error(const Error&) VULKAN_HPP_NOEXCEPT = default;
+ virtual ~Error() VULKAN_HPP_NOEXCEPT = default;
+
+ virtual const char* what() const VULKAN_HPP_NOEXCEPT = 0;
+ };
+
+ class LogicError : public Error, public std::logic_error
+ {
+ public:
+ explicit LogicError( const std::string& what )
+ : Error(), std::logic_error(what) {}
+ explicit LogicError( char const * what )
+ : Error(), std::logic_error(what) {}
+
+ virtual const char* what() const VULKAN_HPP_NOEXCEPT { return std::logic_error::what(); }
+ };
+
+ class SystemError : public Error, public std::system_error
+ {
+ public:
+ SystemError( std::error_code ec )
+ : Error(), std::system_error(ec) {}
+ SystemError( std::error_code ec, std::string const& what )
+ : Error(), std::system_error(ec, what) {}
+ SystemError( std::error_code ec, char const * what )
+ : Error(), std::system_error(ec, what) {}
+ SystemError( int ev, std::error_category const& ecat )
+ : Error(), std::system_error(ev, ecat) {}
+ SystemError( int ev, std::error_category const& ecat, std::string const& what)
+ : Error(), std::system_error(ev, ecat, what) {}
+ SystemError( int ev, std::error_category const& ecat, char const * what)
+ : Error(), std::system_error(ev, ecat, what) {}
+
+ virtual const char* what() const VULKAN_HPP_NOEXCEPT { return std::system_error::what(); }
+ };
+
+ VULKAN_HPP_INLINE const std::error_category& errorCategory() VULKAN_HPP_NOEXCEPT
+ {
+ static ErrorCategoryImpl instance;
+ return instance;
+ }
+
+ VULKAN_HPP_INLINE std::error_code make_error_code(Result e) VULKAN_HPP_NOEXCEPT
+ {
+ return std::error_code(static_cast<int>(e), errorCategory());
+ }
+
+ VULKAN_HPP_INLINE std::error_condition make_error_condition(Result e) VULKAN_HPP_NOEXCEPT
+ {
+ return std::error_condition(static_cast<int>(e), errorCategory());
+ }
+
+ class OutOfHostMemoryError : public SystemError
+ {
+ public:
+ OutOfHostMemoryError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorOutOfHostMemory ), message ) {}
+ OutOfHostMemoryError( char const * message )
+ : SystemError( make_error_code( Result::eErrorOutOfHostMemory ), message ) {}
+ };
+
+ class OutOfDeviceMemoryError : public SystemError
+ {
+ public:
+ OutOfDeviceMemoryError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorOutOfDeviceMemory ), message ) {}
+ OutOfDeviceMemoryError( char const * message )
+ : SystemError( make_error_code( Result::eErrorOutOfDeviceMemory ), message ) {}
+ };
+
+ class InitializationFailedError : public SystemError
+ {
+ public:
+ InitializationFailedError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorInitializationFailed ), message ) {}
+ InitializationFailedError( char const * message )
+ : SystemError( make_error_code( Result::eErrorInitializationFailed ), message ) {}
+ };
+
+ class DeviceLostError : public SystemError
+ {
+ public:
+ DeviceLostError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorDeviceLost ), message ) {}
+ DeviceLostError( char const * message )
+ : SystemError( make_error_code( Result::eErrorDeviceLost ), message ) {}
+ };
+
+ class MemoryMapFailedError : public SystemError
+ {
+ public:
+ MemoryMapFailedError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorMemoryMapFailed ), message ) {}
+ MemoryMapFailedError( char const * message )
+ : SystemError( make_error_code( Result::eErrorMemoryMapFailed ), message ) {}
+ };
+
+ class LayerNotPresentError : public SystemError
+ {
+ public:
+ LayerNotPresentError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorLayerNotPresent ), message ) {}
+ LayerNotPresentError( char const * message )
+ : SystemError( make_error_code( Result::eErrorLayerNotPresent ), message ) {}
+ };
+
+ class ExtensionNotPresentError : public SystemError
+ {
+ public:
+ ExtensionNotPresentError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorExtensionNotPresent ), message ) {}
+ ExtensionNotPresentError( char const * message )
+ : SystemError( make_error_code( Result::eErrorExtensionNotPresent ), message ) {}
+ };
+
+ class FeatureNotPresentError : public SystemError
+ {
+ public:
+ FeatureNotPresentError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorFeatureNotPresent ), message ) {}
+ FeatureNotPresentError( char const * message )
+ : SystemError( make_error_code( Result::eErrorFeatureNotPresent ), message ) {}
+ };
+
+ class IncompatibleDriverError : public SystemError
+ {
+ public:
+ IncompatibleDriverError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorIncompatibleDriver ), message ) {}
+ IncompatibleDriverError( char const * message )
+ : SystemError( make_error_code( Result::eErrorIncompatibleDriver ), message ) {}
+ };
+
+ class TooManyObjectsError : public SystemError
+ {
+ public:
+ TooManyObjectsError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorTooManyObjects ), message ) {}
+ TooManyObjectsError( char const * message )
+ : SystemError( make_error_code( Result::eErrorTooManyObjects ), message ) {}
+ };
+
+ class FormatNotSupportedError : public SystemError
+ {
+ public:
+ FormatNotSupportedError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorFormatNotSupported ), message ) {}
+ FormatNotSupportedError( char const * message )
+ : SystemError( make_error_code( Result::eErrorFormatNotSupported ), message ) {}
+ };
+
+ class FragmentedPoolError : public SystemError
+ {
+ public:
+ FragmentedPoolError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorFragmentedPool ), message ) {}
+ FragmentedPoolError( char const * message )
+ : SystemError( make_error_code( Result::eErrorFragmentedPool ), message ) {}
+ };
+
+ class UnknownError : public SystemError
+ {
+ public:
+ UnknownError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorUnknown ), message ) {}
+ UnknownError( char const * message )
+ : SystemError( make_error_code( Result::eErrorUnknown ), message ) {}
+ };
+
+ class OutOfPoolMemoryError : public SystemError
+ {
+ public:
+ OutOfPoolMemoryError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorOutOfPoolMemory ), message ) {}
+ OutOfPoolMemoryError( char const * message )
+ : SystemError( make_error_code( Result::eErrorOutOfPoolMemory ), message ) {}
+ };
+
+ class InvalidExternalHandleError : public SystemError
+ {
+ public:
+ InvalidExternalHandleError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorInvalidExternalHandle ), message ) {}
+ InvalidExternalHandleError( char const * message )
+ : SystemError( make_error_code( Result::eErrorInvalidExternalHandle ), message ) {}
+ };
+
+ class FragmentationError : public SystemError
+ {
+ public:
+ FragmentationError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorFragmentation ), message ) {}
+ FragmentationError( char const * message )
+ : SystemError( make_error_code( Result::eErrorFragmentation ), message ) {}
+ };
+
+ class InvalidOpaqueCaptureAddressError : public SystemError
+ {
+ public:
+ InvalidOpaqueCaptureAddressError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorInvalidOpaqueCaptureAddress ), message ) {}
+ InvalidOpaqueCaptureAddressError( char const * message )
+ : SystemError( make_error_code( Result::eErrorInvalidOpaqueCaptureAddress ), message ) {}
+ };
+
+ class SurfaceLostKHRError : public SystemError
+ {
+ public:
+ SurfaceLostKHRError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorSurfaceLostKHR ), message ) {}
+ SurfaceLostKHRError( char const * message )
+ : SystemError( make_error_code( Result::eErrorSurfaceLostKHR ), message ) {}
+ };
+
+ class NativeWindowInUseKHRError : public SystemError
+ {
+ public:
+ NativeWindowInUseKHRError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorNativeWindowInUseKHR ), message ) {}
+ NativeWindowInUseKHRError( char const * message )
+ : SystemError( make_error_code( Result::eErrorNativeWindowInUseKHR ), message ) {}
+ };
+
+ class OutOfDateKHRError : public SystemError
+ {
+ public:
+ OutOfDateKHRError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorOutOfDateKHR ), message ) {}
+ OutOfDateKHRError( char const * message )
+ : SystemError( make_error_code( Result::eErrorOutOfDateKHR ), message ) {}
+ };
+
+ class IncompatibleDisplayKHRError : public SystemError
+ {
+ public:
+ IncompatibleDisplayKHRError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorIncompatibleDisplayKHR ), message ) {}
+ IncompatibleDisplayKHRError( char const * message )
+ : SystemError( make_error_code( Result::eErrorIncompatibleDisplayKHR ), message ) {}
+ };
+
+ class ValidationFailedEXTError : public SystemError
+ {
+ public:
+ ValidationFailedEXTError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorValidationFailedEXT ), message ) {}
+ ValidationFailedEXTError( char const * message )
+ : SystemError( make_error_code( Result::eErrorValidationFailedEXT ), message ) {}
+ };
+
+ class InvalidShaderNVError : public SystemError
+ {
+ public:
+ InvalidShaderNVError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorInvalidShaderNV ), message ) {}
+ InvalidShaderNVError( char const * message )
+ : SystemError( make_error_code( Result::eErrorInvalidShaderNV ), message ) {}
+ };
+
+ class InvalidDrmFormatModifierPlaneLayoutEXTError : public SystemError
+ {
+ public:
+ InvalidDrmFormatModifierPlaneLayoutEXTError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorInvalidDrmFormatModifierPlaneLayoutEXT ), message ) {}
+ InvalidDrmFormatModifierPlaneLayoutEXTError( char const * message )
+ : SystemError( make_error_code( Result::eErrorInvalidDrmFormatModifierPlaneLayoutEXT ), message ) {}
+ };
+
+ class NotPermittedEXTError : public SystemError
+ {
+ public:
+ NotPermittedEXTError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorNotPermittedEXT ), message ) {}
+ NotPermittedEXTError( char const * message )
+ : SystemError( make_error_code( Result::eErrorNotPermittedEXT ), message ) {}
+ };
+
+ class FullScreenExclusiveModeLostEXTError : public SystemError
+ {
+ public:
+ FullScreenExclusiveModeLostEXTError( std::string const& message )
+ : SystemError( make_error_code( Result::eErrorFullScreenExclusiveModeLostEXT ), message ) {}
+ FullScreenExclusiveModeLostEXTError( char const * message )
+ : SystemError( make_error_code( Result::eErrorFullScreenExclusiveModeLostEXT ), message ) {}
+ };
+
+ [[noreturn]] static void throwResultException( Result result, char const * message )
+ {
+ switch ( result )
+ {
+ case Result::eErrorOutOfHostMemory: throw OutOfHostMemoryError( message );
+ case Result::eErrorOutOfDeviceMemory: throw OutOfDeviceMemoryError( message );
+ case Result::eErrorInitializationFailed: throw InitializationFailedError( message );
+ case Result::eErrorDeviceLost: throw DeviceLostError( message );
+ case Result::eErrorMemoryMapFailed: throw MemoryMapFailedError( message );
+ case Result::eErrorLayerNotPresent: throw LayerNotPresentError( message );
+ case Result::eErrorExtensionNotPresent: throw ExtensionNotPresentError( message );
+ case Result::eErrorFeatureNotPresent: throw FeatureNotPresentError( message );
+ case Result::eErrorIncompatibleDriver: throw IncompatibleDriverError( message );
+ case Result::eErrorTooManyObjects: throw TooManyObjectsError( message );
+ case Result::eErrorFormatNotSupported: throw FormatNotSupportedError( message );
+ case Result::eErrorFragmentedPool: throw FragmentedPoolError( message );
+ case Result::eErrorUnknown: throw UnknownError( message );
+ case Result::eErrorOutOfPoolMemory: throw OutOfPoolMemoryError( message );
+ case Result::eErrorInvalidExternalHandle: throw InvalidExternalHandleError( message );
+ case Result::eErrorFragmentation: throw FragmentationError( message );
+ case Result::eErrorInvalidOpaqueCaptureAddress: throw InvalidOpaqueCaptureAddressError( message );
+ case Result::eErrorSurfaceLostKHR: throw SurfaceLostKHRError( message );
+ case Result::eErrorNativeWindowInUseKHR: throw NativeWindowInUseKHRError( message );
+ case Result::eErrorOutOfDateKHR: throw OutOfDateKHRError( message );
+ case Result::eErrorIncompatibleDisplayKHR: throw IncompatibleDisplayKHRError( message );
+ case Result::eErrorValidationFailedEXT: throw ValidationFailedEXTError( message );
+ case Result::eErrorInvalidShaderNV: throw InvalidShaderNVError( message );
+ case Result::eErrorInvalidDrmFormatModifierPlaneLayoutEXT: throw InvalidDrmFormatModifierPlaneLayoutEXTError( message );
+ case Result::eErrorNotPermittedEXT: throw NotPermittedEXTError( message );
+ case Result::eErrorFullScreenExclusiveModeLostEXT: throw FullScreenExclusiveModeLostEXTError( message );
+ default: throw SystemError( make_error_code( result ) );
+ }
+ }
+#endif
+
+ template <typename T> void ignore(T const&) VULKAN_HPP_NOEXCEPT {}
+
+ template <typename T>
+ struct ResultValue
+ {
+#ifdef VULKAN_HPP_HAS_NOEXCEPT
+ ResultValue( Result r, T & v ) VULKAN_HPP_NOEXCEPT(VULKAN_HPP_NOEXCEPT(T(v)))
+#else
+ ResultValue( Result r, T & v )
+#endif
+ : result( r )
+ , value( v )
+ {}
+
+#ifdef VULKAN_HPP_HAS_NOEXCEPT
+ ResultValue( Result r, T && v ) VULKAN_HPP_NOEXCEPT(VULKAN_HPP_NOEXCEPT(T(std::move(v))))
+#else
+ ResultValue( Result r, T && v )
+#endif
+ : result( r )
+ , value( std::move( v ) )
+ {}
+
+ Result result;
+ T value;
+
+ operator std::tuple<Result&, T&>() VULKAN_HPP_NOEXCEPT { return std::tuple<Result&, T&>(result, value); }
+ };
+
+ template <typename T>
+ struct ResultValueType
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ typedef ResultValue<T> type;
+#else
+ typedef T type;
+#endif
+ };
+
+ template <>
+ struct ResultValueType<void>
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ typedef Result type;
+#else
+ typedef void type;
+#endif
+ };
+
+ VULKAN_HPP_INLINE ResultValueType<void>::type createResultValue( Result result, char const * message )
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ ignore(message);
+ VULKAN_HPP_ASSERT( result == Result::eSuccess );
+ return result;
+#else
+ if ( result != Result::eSuccess )
+ {
+ throwResultException( result, message );
+ }
+#endif
+ }
+
+ template <typename T>
+ VULKAN_HPP_INLINE typename ResultValueType<T>::type createResultValue( Result result, T & data, char const * message )
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ ignore(message);
+ VULKAN_HPP_ASSERT( result == Result::eSuccess );
+ return ResultValue<T>( result, std::move( data ) );
+#else
+ if ( result != Result::eSuccess )
+ {
+ throwResultException( result, message );
+ }
+ return std::move( data );
+#endif
+ }
+
+ VULKAN_HPP_INLINE Result createResultValue( Result result, char const * message, std::initializer_list<Result> successCodes )
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ ignore(message);
+ VULKAN_HPP_ASSERT( std::find( successCodes.begin(), successCodes.end(), result ) != successCodes.end() );
+#else
+ if ( std::find( successCodes.begin(), successCodes.end(), result ) == successCodes.end() )
+ {
+ throwResultException( result, message );
+ }
+#endif
+ return result;
+ }
+
+ template <typename T>
+ VULKAN_HPP_INLINE ResultValue<T> createResultValue( Result result, T & data, char const * message, std::initializer_list<Result> successCodes )
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ ignore(message);
+ VULKAN_HPP_ASSERT( std::find( successCodes.begin(), successCodes.end(), result ) != successCodes.end() );
+#else
+ if ( std::find( successCodes.begin(), successCodes.end(), result ) == successCodes.end() )
+ {
+ throwResultException( result, message );
+ }
+#endif
+ return ResultValue<T>( result, data );
+ }
+
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template <typename T, typename D>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<T,D>>::type createResultValue( Result result, T & data, char const * message, typename UniqueHandleTraits<T,D>::deleter const& deleter )
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ ignore(message);
+ VULKAN_HPP_ASSERT( result == Result::eSuccess );
+ return ResultValue<UniqueHandle<T,D>>( result, UniqueHandle<T,D>(data, deleter) );
+#else
+ if ( result != Result::eSuccess )
+ {
+ throwResultException( result, message );
+ }
+ return UniqueHandle<T,D>(data, deleter);
+#endif
+ }
+#endif
+
+ struct AccelerationStructureCreateInfoNV;
+ struct AccelerationStructureInfoNV;
+ struct AccelerationStructureMemoryRequirementsInfoNV;
+ struct AcquireNextImageInfoKHR;
+ struct AcquireProfilingLockInfoKHR;
+ struct AllocationCallbacks;
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ struct AndroidHardwareBufferFormatPropertiesANDROID;
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ struct AndroidHardwareBufferPropertiesANDROID;
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ struct AndroidHardwareBufferUsageANDROID;
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ struct AndroidSurfaceCreateInfoKHR;
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ struct ApplicationInfo;
+ struct AttachmentDescription;
+ struct AttachmentDescription2;
+ using AttachmentDescription2KHR = AttachmentDescription2;
+ struct AttachmentDescriptionStencilLayout;
+ using AttachmentDescriptionStencilLayoutKHR = AttachmentDescriptionStencilLayout;
+ struct AttachmentReference;
+ struct AttachmentReference2;
+ using AttachmentReference2KHR = AttachmentReference2;
+ struct AttachmentReferenceStencilLayout;
+ using AttachmentReferenceStencilLayoutKHR = AttachmentReferenceStencilLayout;
+ struct AttachmentSampleLocationsEXT;
+ struct BaseInStructure;
+ struct BaseOutStructure;
+ struct BindAccelerationStructureMemoryInfoNV;
+ struct BindBufferMemoryDeviceGroupInfo;
+ using BindBufferMemoryDeviceGroupInfoKHR = BindBufferMemoryDeviceGroupInfo;
+ struct BindBufferMemoryInfo;
+ using BindBufferMemoryInfoKHR = BindBufferMemoryInfo;
+ struct BindImageMemoryDeviceGroupInfo;
+ using BindImageMemoryDeviceGroupInfoKHR = BindImageMemoryDeviceGroupInfo;
+ struct BindImageMemoryInfo;
+ using BindImageMemoryInfoKHR = BindImageMemoryInfo;
+ struct BindImageMemorySwapchainInfoKHR;
+ struct BindImagePlaneMemoryInfo;
+ using BindImagePlaneMemoryInfoKHR = BindImagePlaneMemoryInfo;
+ struct BindSparseInfo;
+ struct BufferCopy;
+ struct BufferCreateInfo;
+ struct BufferDeviceAddressCreateInfoEXT;
+ struct BufferDeviceAddressInfo;
+ using BufferDeviceAddressInfoKHR = BufferDeviceAddressInfo;
+ using BufferDeviceAddressInfoEXT = BufferDeviceAddressInfo;
+ struct BufferImageCopy;
+ struct BufferMemoryBarrier;
+ struct BufferMemoryRequirementsInfo2;
+ using BufferMemoryRequirementsInfo2KHR = BufferMemoryRequirementsInfo2;
+ struct BufferOpaqueCaptureAddressCreateInfo;
+ using BufferOpaqueCaptureAddressCreateInfoKHR = BufferOpaqueCaptureAddressCreateInfo;
+ struct BufferViewCreateInfo;
+ struct CalibratedTimestampInfoEXT;
+ struct CheckpointDataNV;
+ struct ClearAttachment;
+ union ClearColorValue;
+ struct ClearDepthStencilValue;
+ struct ClearRect;
+ union ClearValue;
+ struct CmdProcessCommandsInfoNVX;
+ struct CmdReserveSpaceForCommandsInfoNVX;
+ struct CoarseSampleLocationNV;
+ struct CoarseSampleOrderCustomNV;
+ struct CommandBufferAllocateInfo;
+ struct CommandBufferBeginInfo;
+ struct CommandBufferInheritanceConditionalRenderingInfoEXT;
+ struct CommandBufferInheritanceInfo;
+ struct CommandPoolCreateInfo;
+ struct ComponentMapping;
+ struct ComputePipelineCreateInfo;
+ struct ConditionalRenderingBeginInfoEXT;
+ struct ConformanceVersion;
+ using ConformanceVersionKHR = ConformanceVersion;
+ struct CooperativeMatrixPropertiesNV;
+ struct CopyDescriptorSet;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct D3D12FenceSubmitInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct DebugMarkerMarkerInfoEXT;
+ struct DebugMarkerObjectNameInfoEXT;
+ struct DebugMarkerObjectTagInfoEXT;
+ struct DebugReportCallbackCreateInfoEXT;
+ struct DebugUtilsLabelEXT;
+ struct DebugUtilsMessengerCallbackDataEXT;
+ struct DebugUtilsMessengerCreateInfoEXT;
+ struct DebugUtilsObjectNameInfoEXT;
+ struct DebugUtilsObjectTagInfoEXT;
+ struct DedicatedAllocationBufferCreateInfoNV;
+ struct DedicatedAllocationImageCreateInfoNV;
+ struct DedicatedAllocationMemoryAllocateInfoNV;
+ struct DescriptorBufferInfo;
+ struct DescriptorImageInfo;
+ struct DescriptorPoolCreateInfo;
+ struct DescriptorPoolInlineUniformBlockCreateInfoEXT;
+ struct DescriptorPoolSize;
+ struct DescriptorSetAllocateInfo;
+ struct DescriptorSetLayoutBinding;
+ struct DescriptorSetLayoutBindingFlagsCreateInfo;
+ using DescriptorSetLayoutBindingFlagsCreateInfoEXT = DescriptorSetLayoutBindingFlagsCreateInfo;
+ struct DescriptorSetLayoutCreateInfo;
+ struct DescriptorSetLayoutSupport;
+ using DescriptorSetLayoutSupportKHR = DescriptorSetLayoutSupport;
+ struct DescriptorSetVariableDescriptorCountAllocateInfo;
+ using DescriptorSetVariableDescriptorCountAllocateInfoEXT = DescriptorSetVariableDescriptorCountAllocateInfo;
+ struct DescriptorSetVariableDescriptorCountLayoutSupport;
+ using DescriptorSetVariableDescriptorCountLayoutSupportEXT = DescriptorSetVariableDescriptorCountLayoutSupport;
+ struct DescriptorUpdateTemplateCreateInfo;
+ using DescriptorUpdateTemplateCreateInfoKHR = DescriptorUpdateTemplateCreateInfo;
+ struct DescriptorUpdateTemplateEntry;
+ using DescriptorUpdateTemplateEntryKHR = DescriptorUpdateTemplateEntry;
+ struct DeviceCreateInfo;
+ struct DeviceEventInfoEXT;
+ struct DeviceGeneratedCommandsFeaturesNVX;
+ struct DeviceGeneratedCommandsLimitsNVX;
+ struct DeviceGroupBindSparseInfo;
+ using DeviceGroupBindSparseInfoKHR = DeviceGroupBindSparseInfo;
+ struct DeviceGroupCommandBufferBeginInfo;
+ using DeviceGroupCommandBufferBeginInfoKHR = DeviceGroupCommandBufferBeginInfo;
+ struct DeviceGroupDeviceCreateInfo;
+ using DeviceGroupDeviceCreateInfoKHR = DeviceGroupDeviceCreateInfo;
+ struct DeviceGroupPresentCapabilitiesKHR;
+ struct DeviceGroupPresentInfoKHR;
+ struct DeviceGroupRenderPassBeginInfo;
+ using DeviceGroupRenderPassBeginInfoKHR = DeviceGroupRenderPassBeginInfo;
+ struct DeviceGroupSubmitInfo;
+ using DeviceGroupSubmitInfoKHR = DeviceGroupSubmitInfo;
+ struct DeviceGroupSwapchainCreateInfoKHR;
+ struct DeviceMemoryOpaqueCaptureAddressInfo;
+ using DeviceMemoryOpaqueCaptureAddressInfoKHR = DeviceMemoryOpaqueCaptureAddressInfo;
+ struct DeviceMemoryOverallocationCreateInfoAMD;
+ struct DeviceQueueCreateInfo;
+ struct DeviceQueueGlobalPriorityCreateInfoEXT;
+ struct DeviceQueueInfo2;
+ struct DispatchIndirectCommand;
+ struct DisplayEventInfoEXT;
+ struct DisplayModeCreateInfoKHR;
+ struct DisplayModeParametersKHR;
+ struct DisplayModeProperties2KHR;
+ struct DisplayModePropertiesKHR;
+ struct DisplayNativeHdrSurfaceCapabilitiesAMD;
+ struct DisplayPlaneCapabilities2KHR;
+ struct DisplayPlaneCapabilitiesKHR;
+ struct DisplayPlaneInfo2KHR;
+ struct DisplayPlaneProperties2KHR;
+ struct DisplayPlanePropertiesKHR;
+ struct DisplayPowerInfoEXT;
+ struct DisplayPresentInfoKHR;
+ struct DisplayProperties2KHR;
+ struct DisplayPropertiesKHR;
+ struct DisplaySurfaceCreateInfoKHR;
+ struct DrawIndexedIndirectCommand;
+ struct DrawIndirectCommand;
+ struct DrawMeshTasksIndirectCommandNV;
+ struct DrmFormatModifierPropertiesEXT;
+ struct DrmFormatModifierPropertiesListEXT;
+ struct EventCreateInfo;
+ struct ExportFenceCreateInfo;
+ using ExportFenceCreateInfoKHR = ExportFenceCreateInfo;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct ExportFenceWin32HandleInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct ExportMemoryAllocateInfo;
+ using ExportMemoryAllocateInfoKHR = ExportMemoryAllocateInfo;
+ struct ExportMemoryAllocateInfoNV;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct ExportMemoryWin32HandleInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct ExportMemoryWin32HandleInfoNV;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct ExportSemaphoreCreateInfo;
+ using ExportSemaphoreCreateInfoKHR = ExportSemaphoreCreateInfo;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct ExportSemaphoreWin32HandleInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct ExtensionProperties;
+ struct Extent2D;
+ struct Extent3D;
+ struct ExternalBufferProperties;
+ using ExternalBufferPropertiesKHR = ExternalBufferProperties;
+ struct ExternalFenceProperties;
+ using ExternalFencePropertiesKHR = ExternalFenceProperties;
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ struct ExternalFormatANDROID;
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ struct ExternalImageFormatProperties;
+ using ExternalImageFormatPropertiesKHR = ExternalImageFormatProperties;
+ struct ExternalImageFormatPropertiesNV;
+ struct ExternalMemoryBufferCreateInfo;
+ using ExternalMemoryBufferCreateInfoKHR = ExternalMemoryBufferCreateInfo;
+ struct ExternalMemoryImageCreateInfo;
+ using ExternalMemoryImageCreateInfoKHR = ExternalMemoryImageCreateInfo;
+ struct ExternalMemoryImageCreateInfoNV;
+ struct ExternalMemoryProperties;
+ using ExternalMemoryPropertiesKHR = ExternalMemoryProperties;
+ struct ExternalSemaphoreProperties;
+ using ExternalSemaphorePropertiesKHR = ExternalSemaphoreProperties;
+ struct FenceCreateInfo;
+ struct FenceGetFdInfoKHR;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct FenceGetWin32HandleInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct FilterCubicImageViewImageFormatPropertiesEXT;
+ struct FormatProperties;
+ struct FormatProperties2;
+ using FormatProperties2KHR = FormatProperties2;
+ struct FramebufferAttachmentImageInfo;
+ using FramebufferAttachmentImageInfoKHR = FramebufferAttachmentImageInfo;
+ struct FramebufferAttachmentsCreateInfo;
+ using FramebufferAttachmentsCreateInfoKHR = FramebufferAttachmentsCreateInfo;
+ struct FramebufferCreateInfo;
+ struct FramebufferMixedSamplesCombinationNV;
+ struct GeometryAABBNV;
+ struct GeometryDataNV;
+ struct GeometryNV;
+ struct GeometryTrianglesNV;
+ struct GraphicsPipelineCreateInfo;
+ struct HdrMetadataEXT;
+ struct HeadlessSurfaceCreateInfoEXT;
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ struct IOSSurfaceCreateInfoMVK;
+#endif /*VK_USE_PLATFORM_IOS_MVK*/
+ struct ImageBlit;
+ struct ImageCopy;
+ struct ImageCreateInfo;
+ struct ImageDrmFormatModifierExplicitCreateInfoEXT;
+ struct ImageDrmFormatModifierListCreateInfoEXT;
+ struct ImageDrmFormatModifierPropertiesEXT;
+ struct ImageFormatListCreateInfo;
+ using ImageFormatListCreateInfoKHR = ImageFormatListCreateInfo;
+ struct ImageFormatProperties;
+ struct ImageFormatProperties2;
+ using ImageFormatProperties2KHR = ImageFormatProperties2;
+ struct ImageMemoryBarrier;
+ struct ImageMemoryRequirementsInfo2;
+ using ImageMemoryRequirementsInfo2KHR = ImageMemoryRequirementsInfo2;
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ struct ImagePipeSurfaceCreateInfoFUCHSIA;
+#endif /*VK_USE_PLATFORM_FUCHSIA*/
+ struct ImagePlaneMemoryRequirementsInfo;
+ using ImagePlaneMemoryRequirementsInfoKHR = ImagePlaneMemoryRequirementsInfo;
+ struct ImageResolve;
+ struct ImageSparseMemoryRequirementsInfo2;
+ using ImageSparseMemoryRequirementsInfo2KHR = ImageSparseMemoryRequirementsInfo2;
+ struct ImageStencilUsageCreateInfo;
+ using ImageStencilUsageCreateInfoEXT = ImageStencilUsageCreateInfo;
+ struct ImageSubresource;
+ struct ImageSubresourceLayers;
+ struct ImageSubresourceRange;
+ struct ImageSwapchainCreateInfoKHR;
+ struct ImageViewASTCDecodeModeEXT;
+ struct ImageViewCreateInfo;
+ struct ImageViewHandleInfoNVX;
+ struct ImageViewUsageCreateInfo;
+ using ImageViewUsageCreateInfoKHR = ImageViewUsageCreateInfo;
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ struct ImportAndroidHardwareBufferInfoANDROID;
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ struct ImportFenceFdInfoKHR;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct ImportFenceWin32HandleInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct ImportMemoryFdInfoKHR;
+ struct ImportMemoryHostPointerInfoEXT;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct ImportMemoryWin32HandleInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct ImportMemoryWin32HandleInfoNV;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct ImportSemaphoreFdInfoKHR;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct ImportSemaphoreWin32HandleInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct IndirectCommandsLayoutCreateInfoNVX;
+ struct IndirectCommandsLayoutTokenNVX;
+ struct IndirectCommandsTokenNVX;
+ struct InitializePerformanceApiInfoINTEL;
+ struct InputAttachmentAspectReference;
+ using InputAttachmentAspectReferenceKHR = InputAttachmentAspectReference;
+ struct InstanceCreateInfo;
+ struct LayerProperties;
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ struct MacOSSurfaceCreateInfoMVK;
+#endif /*VK_USE_PLATFORM_MACOS_MVK*/
+ struct MappedMemoryRange;
+ struct MemoryAllocateFlagsInfo;
+ using MemoryAllocateFlagsInfoKHR = MemoryAllocateFlagsInfo;
+ struct MemoryAllocateInfo;
+ struct MemoryBarrier;
+ struct MemoryDedicatedAllocateInfo;
+ using MemoryDedicatedAllocateInfoKHR = MemoryDedicatedAllocateInfo;
+ struct MemoryDedicatedRequirements;
+ using MemoryDedicatedRequirementsKHR = MemoryDedicatedRequirements;
+ struct MemoryFdPropertiesKHR;
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ struct MemoryGetAndroidHardwareBufferInfoANDROID;
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ struct MemoryGetFdInfoKHR;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct MemoryGetWin32HandleInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct MemoryHeap;
+ struct MemoryHostPointerPropertiesEXT;
+ struct MemoryOpaqueCaptureAddressAllocateInfo;
+ using MemoryOpaqueCaptureAddressAllocateInfoKHR = MemoryOpaqueCaptureAddressAllocateInfo;
+ struct MemoryPriorityAllocateInfoEXT;
+ struct MemoryRequirements;
+ struct MemoryRequirements2;
+ using MemoryRequirements2KHR = MemoryRequirements2;
+ struct MemoryType;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct MemoryWin32HandlePropertiesKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ struct MetalSurfaceCreateInfoEXT;
+#endif /*VK_USE_PLATFORM_METAL_EXT*/
+ struct MultisamplePropertiesEXT;
+ struct ObjectTableCreateInfoNVX;
+ struct ObjectTableDescriptorSetEntryNVX;
+ struct ObjectTableEntryNVX;
+ struct ObjectTableIndexBufferEntryNVX;
+ struct ObjectTablePipelineEntryNVX;
+ struct ObjectTablePushConstantEntryNVX;
+ struct ObjectTableVertexBufferEntryNVX;
+ struct Offset2D;
+ struct Offset3D;
+ struct PastPresentationTimingGOOGLE;
+ struct PerformanceConfigurationAcquireInfoINTEL;
+ struct PerformanceCounterDescriptionKHR;
+ struct PerformanceCounterKHR;
+ union PerformanceCounterResultKHR;
+ struct PerformanceMarkerInfoINTEL;
+ struct PerformanceOverrideInfoINTEL;
+ struct PerformanceQuerySubmitInfoKHR;
+ struct PerformanceStreamMarkerInfoINTEL;
+ union PerformanceValueDataINTEL;
+ struct PerformanceValueINTEL;
+ struct PhysicalDevice16BitStorageFeatures;
+ using PhysicalDevice16BitStorageFeaturesKHR = PhysicalDevice16BitStorageFeatures;
+ struct PhysicalDevice8BitStorageFeatures;
+ using PhysicalDevice8BitStorageFeaturesKHR = PhysicalDevice8BitStorageFeatures;
+ struct PhysicalDeviceASTCDecodeFeaturesEXT;
+ struct PhysicalDeviceBlendOperationAdvancedFeaturesEXT;
+ struct PhysicalDeviceBlendOperationAdvancedPropertiesEXT;
+ struct PhysicalDeviceBufferDeviceAddressFeatures;
+ using PhysicalDeviceBufferDeviceAddressFeaturesKHR = PhysicalDeviceBufferDeviceAddressFeatures;
+ struct PhysicalDeviceBufferDeviceAddressFeaturesEXT;
+ using PhysicalDeviceBufferAddressFeaturesEXT = PhysicalDeviceBufferDeviceAddressFeaturesEXT;
+ struct PhysicalDeviceCoherentMemoryFeaturesAMD;
+ struct PhysicalDeviceComputeShaderDerivativesFeaturesNV;
+ struct PhysicalDeviceConditionalRenderingFeaturesEXT;
+ struct PhysicalDeviceConservativeRasterizationPropertiesEXT;
+ struct PhysicalDeviceCooperativeMatrixFeaturesNV;
+ struct PhysicalDeviceCooperativeMatrixPropertiesNV;
+ struct PhysicalDeviceCornerSampledImageFeaturesNV;
+ struct PhysicalDeviceCoverageReductionModeFeaturesNV;
+ struct PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV;
+ struct PhysicalDeviceDepthClipEnableFeaturesEXT;
+ struct PhysicalDeviceDepthStencilResolveProperties;
+ using PhysicalDeviceDepthStencilResolvePropertiesKHR = PhysicalDeviceDepthStencilResolveProperties;
+ struct PhysicalDeviceDescriptorIndexingFeatures;
+ using PhysicalDeviceDescriptorIndexingFeaturesEXT = PhysicalDeviceDescriptorIndexingFeatures;
+ struct PhysicalDeviceDescriptorIndexingProperties;
+ using PhysicalDeviceDescriptorIndexingPropertiesEXT = PhysicalDeviceDescriptorIndexingProperties;
+ struct PhysicalDeviceDiscardRectanglePropertiesEXT;
+ struct PhysicalDeviceDriverProperties;
+ using PhysicalDeviceDriverPropertiesKHR = PhysicalDeviceDriverProperties;
+ struct PhysicalDeviceExclusiveScissorFeaturesNV;
+ struct PhysicalDeviceExternalBufferInfo;
+ using PhysicalDeviceExternalBufferInfoKHR = PhysicalDeviceExternalBufferInfo;
+ struct PhysicalDeviceExternalFenceInfo;
+ using PhysicalDeviceExternalFenceInfoKHR = PhysicalDeviceExternalFenceInfo;
+ struct PhysicalDeviceExternalImageFormatInfo;
+ using PhysicalDeviceExternalImageFormatInfoKHR = PhysicalDeviceExternalImageFormatInfo;
+ struct PhysicalDeviceExternalMemoryHostPropertiesEXT;
+ struct PhysicalDeviceExternalSemaphoreInfo;
+ using PhysicalDeviceExternalSemaphoreInfoKHR = PhysicalDeviceExternalSemaphoreInfo;
+ struct PhysicalDeviceFeatures;
+ struct PhysicalDeviceFeatures2;
+ using PhysicalDeviceFeatures2KHR = PhysicalDeviceFeatures2;
+ struct PhysicalDeviceFloatControlsProperties;
+ using PhysicalDeviceFloatControlsPropertiesKHR = PhysicalDeviceFloatControlsProperties;
+ struct PhysicalDeviceFragmentDensityMapFeaturesEXT;
+ struct PhysicalDeviceFragmentDensityMapPropertiesEXT;
+ struct PhysicalDeviceFragmentShaderBarycentricFeaturesNV;
+ struct PhysicalDeviceFragmentShaderInterlockFeaturesEXT;
+ struct PhysicalDeviceGroupProperties;
+ using PhysicalDeviceGroupPropertiesKHR = PhysicalDeviceGroupProperties;
+ struct PhysicalDeviceHostQueryResetFeatures;
+ using PhysicalDeviceHostQueryResetFeaturesEXT = PhysicalDeviceHostQueryResetFeatures;
+ struct PhysicalDeviceIDProperties;
+ using PhysicalDeviceIDPropertiesKHR = PhysicalDeviceIDProperties;
+ struct PhysicalDeviceImageDrmFormatModifierInfoEXT;
+ struct PhysicalDeviceImageFormatInfo2;
+ using PhysicalDeviceImageFormatInfo2KHR = PhysicalDeviceImageFormatInfo2;
+ struct PhysicalDeviceImageViewImageFormatInfoEXT;
+ struct PhysicalDeviceImagelessFramebufferFeatures;
+ using PhysicalDeviceImagelessFramebufferFeaturesKHR = PhysicalDeviceImagelessFramebufferFeatures;
+ struct PhysicalDeviceIndexTypeUint8FeaturesEXT;
+ struct PhysicalDeviceInlineUniformBlockFeaturesEXT;
+ struct PhysicalDeviceInlineUniformBlockPropertiesEXT;
+ struct PhysicalDeviceLimits;
+ struct PhysicalDeviceLineRasterizationFeaturesEXT;
+ struct PhysicalDeviceLineRasterizationPropertiesEXT;
+ struct PhysicalDeviceMaintenance3Properties;
+ using PhysicalDeviceMaintenance3PropertiesKHR = PhysicalDeviceMaintenance3Properties;
+ struct PhysicalDeviceMemoryBudgetPropertiesEXT;
+ struct PhysicalDeviceMemoryPriorityFeaturesEXT;
+ struct PhysicalDeviceMemoryProperties;
+ struct PhysicalDeviceMemoryProperties2;
+ using PhysicalDeviceMemoryProperties2KHR = PhysicalDeviceMemoryProperties2;
+ struct PhysicalDeviceMeshShaderFeaturesNV;
+ struct PhysicalDeviceMeshShaderPropertiesNV;
+ struct PhysicalDeviceMultiviewFeatures;
+ using PhysicalDeviceMultiviewFeaturesKHR = PhysicalDeviceMultiviewFeatures;
+ struct PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX;
+ struct PhysicalDeviceMultiviewProperties;
+ using PhysicalDeviceMultiviewPropertiesKHR = PhysicalDeviceMultiviewProperties;
+ struct PhysicalDevicePCIBusInfoPropertiesEXT;
+ struct PhysicalDevicePerformanceQueryFeaturesKHR;
+ struct PhysicalDevicePerformanceQueryPropertiesKHR;
+ struct PhysicalDevicePipelineExecutablePropertiesFeaturesKHR;
+ struct PhysicalDevicePointClippingProperties;
+ using PhysicalDevicePointClippingPropertiesKHR = PhysicalDevicePointClippingProperties;
+ struct PhysicalDeviceProperties;
+ struct PhysicalDeviceProperties2;
+ using PhysicalDeviceProperties2KHR = PhysicalDeviceProperties2;
+ struct PhysicalDeviceProtectedMemoryFeatures;
+ struct PhysicalDeviceProtectedMemoryProperties;
+ struct PhysicalDevicePushDescriptorPropertiesKHR;
+ struct PhysicalDeviceRayTracingPropertiesNV;
+ struct PhysicalDeviceRepresentativeFragmentTestFeaturesNV;
+ struct PhysicalDeviceSampleLocationsPropertiesEXT;
+ struct PhysicalDeviceSamplerFilterMinmaxProperties;
+ using PhysicalDeviceSamplerFilterMinmaxPropertiesEXT = PhysicalDeviceSamplerFilterMinmaxProperties;
+ struct PhysicalDeviceSamplerYcbcrConversionFeatures;
+ using PhysicalDeviceSamplerYcbcrConversionFeaturesKHR = PhysicalDeviceSamplerYcbcrConversionFeatures;
+ struct PhysicalDeviceScalarBlockLayoutFeatures;
+ using PhysicalDeviceScalarBlockLayoutFeaturesEXT = PhysicalDeviceScalarBlockLayoutFeatures;
+ struct PhysicalDeviceSeparateDepthStencilLayoutsFeatures;
+ using PhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR = PhysicalDeviceSeparateDepthStencilLayoutsFeatures;
+ struct PhysicalDeviceShaderAtomicInt64Features;
+ using PhysicalDeviceShaderAtomicInt64FeaturesKHR = PhysicalDeviceShaderAtomicInt64Features;
+ struct PhysicalDeviceShaderClockFeaturesKHR;
+ struct PhysicalDeviceShaderCoreProperties2AMD;
+ struct PhysicalDeviceShaderCorePropertiesAMD;
+ struct PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT;
+ struct PhysicalDeviceShaderDrawParametersFeatures;
+ using PhysicalDeviceShaderDrawParameterFeatures = PhysicalDeviceShaderDrawParametersFeatures;
+ struct PhysicalDeviceShaderFloat16Int8Features;
+ using PhysicalDeviceShaderFloat16Int8FeaturesKHR = PhysicalDeviceShaderFloat16Int8Features;
+ using PhysicalDeviceFloat16Int8FeaturesKHR = PhysicalDeviceShaderFloat16Int8Features;
+ struct PhysicalDeviceShaderImageFootprintFeaturesNV;
+ struct PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL;
+ struct PhysicalDeviceShaderSMBuiltinsFeaturesNV;
+ struct PhysicalDeviceShaderSMBuiltinsPropertiesNV;
+ struct PhysicalDeviceShaderSubgroupExtendedTypesFeatures;
+ using PhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR = PhysicalDeviceShaderSubgroupExtendedTypesFeatures;
+ struct PhysicalDeviceShadingRateImageFeaturesNV;
+ struct PhysicalDeviceShadingRateImagePropertiesNV;
+ struct PhysicalDeviceSparseImageFormatInfo2;
+ using PhysicalDeviceSparseImageFormatInfo2KHR = PhysicalDeviceSparseImageFormatInfo2;
+ struct PhysicalDeviceSparseProperties;
+ struct PhysicalDeviceSubgroupProperties;
+ struct PhysicalDeviceSubgroupSizeControlFeaturesEXT;
+ struct PhysicalDeviceSubgroupSizeControlPropertiesEXT;
+ struct PhysicalDeviceSurfaceInfo2KHR;
+ struct PhysicalDeviceTexelBufferAlignmentFeaturesEXT;
+ struct PhysicalDeviceTexelBufferAlignmentPropertiesEXT;
+ struct PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT;
+ struct PhysicalDeviceTimelineSemaphoreFeatures;
+ using PhysicalDeviceTimelineSemaphoreFeaturesKHR = PhysicalDeviceTimelineSemaphoreFeatures;
+ struct PhysicalDeviceTimelineSemaphoreProperties;
+ using PhysicalDeviceTimelineSemaphorePropertiesKHR = PhysicalDeviceTimelineSemaphoreProperties;
+ struct PhysicalDeviceToolPropertiesEXT;
+ struct PhysicalDeviceTransformFeedbackFeaturesEXT;
+ struct PhysicalDeviceTransformFeedbackPropertiesEXT;
+ struct PhysicalDeviceUniformBufferStandardLayoutFeatures;
+ using PhysicalDeviceUniformBufferStandardLayoutFeaturesKHR = PhysicalDeviceUniformBufferStandardLayoutFeatures;
+ struct PhysicalDeviceVariablePointersFeatures;
+ using PhysicalDeviceVariablePointersFeaturesKHR = PhysicalDeviceVariablePointersFeatures;
+ using PhysicalDeviceVariablePointerFeaturesKHR = PhysicalDeviceVariablePointersFeatures;
+ using PhysicalDeviceVariablePointerFeatures = PhysicalDeviceVariablePointersFeatures;
+ struct PhysicalDeviceVertexAttributeDivisorFeaturesEXT;
+ struct PhysicalDeviceVertexAttributeDivisorPropertiesEXT;
+ struct PhysicalDeviceVulkan11Features;
+ struct PhysicalDeviceVulkan11Properties;
+ struct PhysicalDeviceVulkan12Features;
+ struct PhysicalDeviceVulkan12Properties;
+ struct PhysicalDeviceVulkanMemoryModelFeatures;
+ using PhysicalDeviceVulkanMemoryModelFeaturesKHR = PhysicalDeviceVulkanMemoryModelFeatures;
+ struct PhysicalDeviceYcbcrImageArraysFeaturesEXT;
+ struct PipelineCacheCreateInfo;
+ struct PipelineColorBlendAdvancedStateCreateInfoEXT;
+ struct PipelineColorBlendAttachmentState;
+ struct PipelineColorBlendStateCreateInfo;
+ struct PipelineCompilerControlCreateInfoAMD;
+ struct PipelineCoverageModulationStateCreateInfoNV;
+ struct PipelineCoverageReductionStateCreateInfoNV;
+ struct PipelineCoverageToColorStateCreateInfoNV;
+ struct PipelineCreationFeedbackCreateInfoEXT;
+ struct PipelineCreationFeedbackEXT;
+ struct PipelineDepthStencilStateCreateInfo;
+ struct PipelineDiscardRectangleStateCreateInfoEXT;
+ struct PipelineDynamicStateCreateInfo;
+ struct PipelineExecutableInfoKHR;
+ struct PipelineExecutableInternalRepresentationKHR;
+ struct PipelineExecutablePropertiesKHR;
+ struct PipelineExecutableStatisticKHR;
+ union PipelineExecutableStatisticValueKHR;
+ struct PipelineInfoKHR;
+ struct PipelineInputAssemblyStateCreateInfo;
+ struct PipelineLayoutCreateInfo;
+ struct PipelineMultisampleStateCreateInfo;
+ struct PipelineRasterizationConservativeStateCreateInfoEXT;
+ struct PipelineRasterizationDepthClipStateCreateInfoEXT;
+ struct PipelineRasterizationLineStateCreateInfoEXT;
+ struct PipelineRasterizationStateCreateInfo;
+ struct PipelineRasterizationStateRasterizationOrderAMD;
+ struct PipelineRasterizationStateStreamCreateInfoEXT;
+ struct PipelineRepresentativeFragmentTestStateCreateInfoNV;
+ struct PipelineSampleLocationsStateCreateInfoEXT;
+ struct PipelineShaderStageCreateInfo;
+ struct PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT;
+ struct PipelineTessellationDomainOriginStateCreateInfo;
+ using PipelineTessellationDomainOriginStateCreateInfoKHR = PipelineTessellationDomainOriginStateCreateInfo;
+ struct PipelineTessellationStateCreateInfo;
+ struct PipelineVertexInputDivisorStateCreateInfoEXT;
+ struct PipelineVertexInputStateCreateInfo;
+ struct PipelineViewportCoarseSampleOrderStateCreateInfoNV;
+ struct PipelineViewportExclusiveScissorStateCreateInfoNV;
+ struct PipelineViewportShadingRateImageStateCreateInfoNV;
+ struct PipelineViewportStateCreateInfo;
+ struct PipelineViewportSwizzleStateCreateInfoNV;
+ struct PipelineViewportWScalingStateCreateInfoNV;
+#ifdef VK_USE_PLATFORM_GGP
+ struct PresentFrameTokenGGP;
+#endif /*VK_USE_PLATFORM_GGP*/
+ struct PresentInfoKHR;
+ struct PresentRegionKHR;
+ struct PresentRegionsKHR;
+ struct PresentTimeGOOGLE;
+ struct PresentTimesInfoGOOGLE;
+ struct ProtectedSubmitInfo;
+ struct PushConstantRange;
+ struct QueryPoolCreateInfo;
+ struct QueryPoolCreateInfoINTEL;
+ struct QueryPoolPerformanceCreateInfoKHR;
+ struct QueueFamilyCheckpointPropertiesNV;
+ struct QueueFamilyProperties;
+ struct QueueFamilyProperties2;
+ using QueueFamilyProperties2KHR = QueueFamilyProperties2;
+ struct RayTracingPipelineCreateInfoNV;
+ struct RayTracingShaderGroupCreateInfoNV;
+ struct Rect2D;
+ struct RectLayerKHR;
+ struct RefreshCycleDurationGOOGLE;
+ struct RenderPassAttachmentBeginInfo;
+ using RenderPassAttachmentBeginInfoKHR = RenderPassAttachmentBeginInfo;
+ struct RenderPassBeginInfo;
+ struct RenderPassCreateInfo;
+ struct RenderPassCreateInfo2;
+ using RenderPassCreateInfo2KHR = RenderPassCreateInfo2;
+ struct RenderPassFragmentDensityMapCreateInfoEXT;
+ struct RenderPassInputAttachmentAspectCreateInfo;
+ using RenderPassInputAttachmentAspectCreateInfoKHR = RenderPassInputAttachmentAspectCreateInfo;
+ struct RenderPassMultiviewCreateInfo;
+ using RenderPassMultiviewCreateInfoKHR = RenderPassMultiviewCreateInfo;
+ struct RenderPassSampleLocationsBeginInfoEXT;
+ struct SampleLocationEXT;
+ struct SampleLocationsInfoEXT;
+ struct SamplerCreateInfo;
+ struct SamplerReductionModeCreateInfo;
+ using SamplerReductionModeCreateInfoEXT = SamplerReductionModeCreateInfo;
+ struct SamplerYcbcrConversionCreateInfo;
+ using SamplerYcbcrConversionCreateInfoKHR = SamplerYcbcrConversionCreateInfo;
+ struct SamplerYcbcrConversionImageFormatProperties;
+ using SamplerYcbcrConversionImageFormatPropertiesKHR = SamplerYcbcrConversionImageFormatProperties;
+ struct SamplerYcbcrConversionInfo;
+ using SamplerYcbcrConversionInfoKHR = SamplerYcbcrConversionInfo;
+ struct SemaphoreCreateInfo;
+ struct SemaphoreGetFdInfoKHR;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct SemaphoreGetWin32HandleInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct SemaphoreSignalInfo;
+ using SemaphoreSignalInfoKHR = SemaphoreSignalInfo;
+ struct SemaphoreTypeCreateInfo;
+ using SemaphoreTypeCreateInfoKHR = SemaphoreTypeCreateInfo;
+ struct SemaphoreWaitInfo;
+ using SemaphoreWaitInfoKHR = SemaphoreWaitInfo;
+ struct ShaderModuleCreateInfo;
+ struct ShaderModuleValidationCacheCreateInfoEXT;
+ struct ShaderResourceUsageAMD;
+ struct ShaderStatisticsInfoAMD;
+ struct ShadingRatePaletteNV;
+ struct SharedPresentSurfaceCapabilitiesKHR;
+ struct SparseBufferMemoryBindInfo;
+ struct SparseImageFormatProperties;
+ struct SparseImageFormatProperties2;
+ using SparseImageFormatProperties2KHR = SparseImageFormatProperties2;
+ struct SparseImageMemoryBind;
+ struct SparseImageMemoryBindInfo;
+ struct SparseImageMemoryRequirements;
+ struct SparseImageMemoryRequirements2;
+ using SparseImageMemoryRequirements2KHR = SparseImageMemoryRequirements2;
+ struct SparseImageOpaqueMemoryBindInfo;
+ struct SparseMemoryBind;
+ struct SpecializationInfo;
+ struct SpecializationMapEntry;
+ struct StencilOpState;
+#ifdef VK_USE_PLATFORM_GGP
+ struct StreamDescriptorSurfaceCreateInfoGGP;
+#endif /*VK_USE_PLATFORM_GGP*/
+ struct SubmitInfo;
+ struct SubpassBeginInfo;
+ using SubpassBeginInfoKHR = SubpassBeginInfo;
+ struct SubpassDependency;
+ struct SubpassDependency2;
+ using SubpassDependency2KHR = SubpassDependency2;
+ struct SubpassDescription;
+ struct SubpassDescription2;
+ using SubpassDescription2KHR = SubpassDescription2;
+ struct SubpassDescriptionDepthStencilResolve;
+ using SubpassDescriptionDepthStencilResolveKHR = SubpassDescriptionDepthStencilResolve;
+ struct SubpassEndInfo;
+ using SubpassEndInfoKHR = SubpassEndInfo;
+ struct SubpassSampleLocationsEXT;
+ struct SubresourceLayout;
+ struct SurfaceCapabilities2EXT;
+ struct SurfaceCapabilities2KHR;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct SurfaceCapabilitiesFullScreenExclusiveEXT;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct SurfaceCapabilitiesKHR;
+ struct SurfaceFormat2KHR;
+ struct SurfaceFormatKHR;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct SurfaceFullScreenExclusiveInfoEXT;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct SurfaceFullScreenExclusiveWin32InfoEXT;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct SurfaceProtectedCapabilitiesKHR;
+ struct SwapchainCounterCreateInfoEXT;
+ struct SwapchainCreateInfoKHR;
+ struct SwapchainDisplayNativeHdrCreateInfoAMD;
+ struct TextureLODGatherFormatPropertiesAMD;
+ struct TimelineSemaphoreSubmitInfo;
+ using TimelineSemaphoreSubmitInfoKHR = TimelineSemaphoreSubmitInfo;
+ struct ValidationCacheCreateInfoEXT;
+ struct ValidationFeaturesEXT;
+ struct ValidationFlagsEXT;
+ struct VertexInputAttributeDescription;
+ struct VertexInputBindingDescription;
+ struct VertexInputBindingDivisorDescriptionEXT;
+#ifdef VK_USE_PLATFORM_VI_NN
+ struct ViSurfaceCreateInfoNN;
+#endif /*VK_USE_PLATFORM_VI_NN*/
+ struct Viewport;
+ struct ViewportSwizzleNV;
+ struct ViewportWScalingNV;
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ struct WaylandSurfaceCreateInfoKHR;
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct Win32KeyedMutexAcquireReleaseInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct Win32KeyedMutexAcquireReleaseInfoNV;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ struct Win32SurfaceCreateInfoKHR;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ struct WriteDescriptorSet;
+ struct WriteDescriptorSetAccelerationStructureNV;
+ struct WriteDescriptorSetInlineUniformBlockEXT;
+ struct XYColorEXT;
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ struct XcbSurfaceCreateInfoKHR;
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ struct XlibSurfaceCreateInfoKHR;
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+
+ class SurfaceKHR
+ {
+ public:
+ using CType = VkSurfaceKHR;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eSurfaceKHR;
+
+ public:
+ VULKAN_HPP_CONSTEXPR SurfaceKHR() VULKAN_HPP_NOEXCEPT
+ : m_surfaceKHR(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR SurfaceKHR( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_surfaceKHR(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT SurfaceKHR( VkSurfaceKHR surfaceKHR ) VULKAN_HPP_NOEXCEPT
+ : m_surfaceKHR( surfaceKHR )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ SurfaceKHR & operator=(VkSurfaceKHR surfaceKHR) VULKAN_HPP_NOEXCEPT
+ {
+ m_surfaceKHR = surfaceKHR;
+ return *this;
+ }
+#endif
+
+ SurfaceKHR & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_surfaceKHR = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( SurfaceKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_surfaceKHR == rhs.m_surfaceKHR;
+ }
+
+ bool operator!=(SurfaceKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_surfaceKHR != rhs.m_surfaceKHR;
+ }
+
+ bool operator<(SurfaceKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_surfaceKHR < rhs.m_surfaceKHR;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkSurfaceKHR() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_surfaceKHR;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_surfaceKHR != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_surfaceKHR == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkSurfaceKHR m_surfaceKHR;
+ };
+ static_assert( sizeof( SurfaceKHR ) == sizeof( VkSurfaceKHR ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eSurfaceKHR>
+ {
+ using type = SurfaceKHR;
+ };
+
+ class DebugReportCallbackEXT
+ {
+ public:
+ using CType = VkDebugReportCallbackEXT;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDebugReportCallbackEXT;
+
+ public:
+ VULKAN_HPP_CONSTEXPR DebugReportCallbackEXT() VULKAN_HPP_NOEXCEPT
+ : m_debugReportCallbackEXT(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR DebugReportCallbackEXT( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_debugReportCallbackEXT(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT DebugReportCallbackEXT( VkDebugReportCallbackEXT debugReportCallbackEXT ) VULKAN_HPP_NOEXCEPT
+ : m_debugReportCallbackEXT( debugReportCallbackEXT )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ DebugReportCallbackEXT & operator=(VkDebugReportCallbackEXT debugReportCallbackEXT) VULKAN_HPP_NOEXCEPT
+ {
+ m_debugReportCallbackEXT = debugReportCallbackEXT;
+ return *this;
+ }
+#endif
+
+ DebugReportCallbackEXT & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_debugReportCallbackEXT = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( DebugReportCallbackEXT const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugReportCallbackEXT == rhs.m_debugReportCallbackEXT;
+ }
+
+ bool operator!=(DebugReportCallbackEXT const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugReportCallbackEXT != rhs.m_debugReportCallbackEXT;
+ }
+
+ bool operator<(DebugReportCallbackEXT const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugReportCallbackEXT < rhs.m_debugReportCallbackEXT;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDebugReportCallbackEXT() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugReportCallbackEXT;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugReportCallbackEXT != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugReportCallbackEXT == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkDebugReportCallbackEXT m_debugReportCallbackEXT;
+ };
+ static_assert( sizeof( DebugReportCallbackEXT ) == sizeof( VkDebugReportCallbackEXT ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eDebugReportCallbackEXT>
+ {
+ using type = DebugReportCallbackEXT;
+ };
+
+ class DebugUtilsMessengerEXT
+ {
+ public:
+ using CType = VkDebugUtilsMessengerEXT;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDebugUtilsMessengerEXT;
+
+ public:
+ VULKAN_HPP_CONSTEXPR DebugUtilsMessengerEXT() VULKAN_HPP_NOEXCEPT
+ : m_debugUtilsMessengerEXT(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR DebugUtilsMessengerEXT( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_debugUtilsMessengerEXT(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT DebugUtilsMessengerEXT( VkDebugUtilsMessengerEXT debugUtilsMessengerEXT ) VULKAN_HPP_NOEXCEPT
+ : m_debugUtilsMessengerEXT( debugUtilsMessengerEXT )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ DebugUtilsMessengerEXT & operator=(VkDebugUtilsMessengerEXT debugUtilsMessengerEXT) VULKAN_HPP_NOEXCEPT
+ {
+ m_debugUtilsMessengerEXT = debugUtilsMessengerEXT;
+ return *this;
+ }
+#endif
+
+ DebugUtilsMessengerEXT & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_debugUtilsMessengerEXT = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( DebugUtilsMessengerEXT const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugUtilsMessengerEXT == rhs.m_debugUtilsMessengerEXT;
+ }
+
+ bool operator!=(DebugUtilsMessengerEXT const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugUtilsMessengerEXT != rhs.m_debugUtilsMessengerEXT;
+ }
+
+ bool operator<(DebugUtilsMessengerEXT const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugUtilsMessengerEXT < rhs.m_debugUtilsMessengerEXT;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDebugUtilsMessengerEXT() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugUtilsMessengerEXT;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugUtilsMessengerEXT != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_debugUtilsMessengerEXT == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkDebugUtilsMessengerEXT m_debugUtilsMessengerEXT;
+ };
+ static_assert( sizeof( DebugUtilsMessengerEXT ) == sizeof( VkDebugUtilsMessengerEXT ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eDebugUtilsMessengerEXT>
+ {
+ using type = DebugUtilsMessengerEXT;
+ };
+
+ class DisplayKHR
+ {
+ public:
+ using CType = VkDisplayKHR;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDisplayKHR;
+
+ public:
+ VULKAN_HPP_CONSTEXPR DisplayKHR() VULKAN_HPP_NOEXCEPT
+ : m_displayKHR(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR DisplayKHR( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_displayKHR(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT DisplayKHR( VkDisplayKHR displayKHR ) VULKAN_HPP_NOEXCEPT
+ : m_displayKHR( displayKHR )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ DisplayKHR & operator=(VkDisplayKHR displayKHR) VULKAN_HPP_NOEXCEPT
+ {
+ m_displayKHR = displayKHR;
+ return *this;
+ }
+#endif
+
+ DisplayKHR & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_displayKHR = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( DisplayKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayKHR == rhs.m_displayKHR;
+ }
+
+ bool operator!=(DisplayKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayKHR != rhs.m_displayKHR;
+ }
+
+ bool operator<(DisplayKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayKHR < rhs.m_displayKHR;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDisplayKHR() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayKHR;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayKHR != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayKHR == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkDisplayKHR m_displayKHR;
+ };
+ static_assert( sizeof( DisplayKHR ) == sizeof( VkDisplayKHR ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eDisplayKHR>
+ {
+ using type = DisplayKHR;
+ };
+
+ class SwapchainKHR
+ {
+ public:
+ using CType = VkSwapchainKHR;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eSwapchainKHR;
+
+ public:
+ VULKAN_HPP_CONSTEXPR SwapchainKHR() VULKAN_HPP_NOEXCEPT
+ : m_swapchainKHR(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR SwapchainKHR( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_swapchainKHR(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT SwapchainKHR( VkSwapchainKHR swapchainKHR ) VULKAN_HPP_NOEXCEPT
+ : m_swapchainKHR( swapchainKHR )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ SwapchainKHR & operator=(VkSwapchainKHR swapchainKHR) VULKAN_HPP_NOEXCEPT
+ {
+ m_swapchainKHR = swapchainKHR;
+ return *this;
+ }
+#endif
+
+ SwapchainKHR & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_swapchainKHR = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( SwapchainKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_swapchainKHR == rhs.m_swapchainKHR;
+ }
+
+ bool operator!=(SwapchainKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_swapchainKHR != rhs.m_swapchainKHR;
+ }
+
+ bool operator<(SwapchainKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_swapchainKHR < rhs.m_swapchainKHR;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkSwapchainKHR() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_swapchainKHR;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_swapchainKHR != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_swapchainKHR == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkSwapchainKHR m_swapchainKHR;
+ };
+ static_assert( sizeof( SwapchainKHR ) == sizeof( VkSwapchainKHR ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eSwapchainKHR>
+ {
+ using type = SwapchainKHR;
+ };
+
+ class Semaphore
+ {
+ public:
+ using CType = VkSemaphore;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eSemaphore;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Semaphore() VULKAN_HPP_NOEXCEPT
+ : m_semaphore(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Semaphore( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_semaphore(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Semaphore( VkSemaphore semaphore ) VULKAN_HPP_NOEXCEPT
+ : m_semaphore( semaphore )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Semaphore & operator=(VkSemaphore semaphore) VULKAN_HPP_NOEXCEPT
+ {
+ m_semaphore = semaphore;
+ return *this;
+ }
+#endif
+
+ Semaphore & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_semaphore = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Semaphore const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_semaphore == rhs.m_semaphore;
+ }
+
+ bool operator!=(Semaphore const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_semaphore != rhs.m_semaphore;
+ }
+
+ bool operator<(Semaphore const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_semaphore < rhs.m_semaphore;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkSemaphore() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_semaphore;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_semaphore != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_semaphore == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkSemaphore m_semaphore;
+ };
+ static_assert( sizeof( Semaphore ) == sizeof( VkSemaphore ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eSemaphore>
+ {
+ using type = Semaphore;
+ };
+
+ class Fence
+ {
+ public:
+ using CType = VkFence;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eFence;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Fence() VULKAN_HPP_NOEXCEPT
+ : m_fence(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Fence( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_fence(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Fence( VkFence fence ) VULKAN_HPP_NOEXCEPT
+ : m_fence( fence )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Fence & operator=(VkFence fence) VULKAN_HPP_NOEXCEPT
+ {
+ m_fence = fence;
+ return *this;
+ }
+#endif
+
+ Fence & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_fence = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Fence const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_fence == rhs.m_fence;
+ }
+
+ bool operator!=(Fence const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_fence != rhs.m_fence;
+ }
+
+ bool operator<(Fence const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_fence < rhs.m_fence;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkFence() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_fence;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_fence != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_fence == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkFence m_fence;
+ };
+ static_assert( sizeof( Fence ) == sizeof( VkFence ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eFence>
+ {
+ using type = Fence;
+ };
+
+ class PerformanceConfigurationINTEL
+ {
+ public:
+ using CType = VkPerformanceConfigurationINTEL;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::ePerformanceConfigurationINTEL;
+
+ public:
+ VULKAN_HPP_CONSTEXPR PerformanceConfigurationINTEL() VULKAN_HPP_NOEXCEPT
+ : m_performanceConfigurationINTEL(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR PerformanceConfigurationINTEL( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_performanceConfigurationINTEL(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT PerformanceConfigurationINTEL( VkPerformanceConfigurationINTEL performanceConfigurationINTEL ) VULKAN_HPP_NOEXCEPT
+ : m_performanceConfigurationINTEL( performanceConfigurationINTEL )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ PerformanceConfigurationINTEL & operator=(VkPerformanceConfigurationINTEL performanceConfigurationINTEL) VULKAN_HPP_NOEXCEPT
+ {
+ m_performanceConfigurationINTEL = performanceConfigurationINTEL;
+ return *this;
+ }
+#endif
+
+ PerformanceConfigurationINTEL & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_performanceConfigurationINTEL = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( PerformanceConfigurationINTEL const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_performanceConfigurationINTEL == rhs.m_performanceConfigurationINTEL;
+ }
+
+ bool operator!=(PerformanceConfigurationINTEL const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_performanceConfigurationINTEL != rhs.m_performanceConfigurationINTEL;
+ }
+
+ bool operator<(PerformanceConfigurationINTEL const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_performanceConfigurationINTEL < rhs.m_performanceConfigurationINTEL;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkPerformanceConfigurationINTEL() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_performanceConfigurationINTEL;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_performanceConfigurationINTEL != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_performanceConfigurationINTEL == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkPerformanceConfigurationINTEL m_performanceConfigurationINTEL;
+ };
+ static_assert( sizeof( PerformanceConfigurationINTEL ) == sizeof( VkPerformanceConfigurationINTEL ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::ePerformanceConfigurationINTEL>
+ {
+ using type = PerformanceConfigurationINTEL;
+ };
+
+ class QueryPool
+ {
+ public:
+ using CType = VkQueryPool;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eQueryPool;
+
+ public:
+ VULKAN_HPP_CONSTEXPR QueryPool() VULKAN_HPP_NOEXCEPT
+ : m_queryPool(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR QueryPool( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_queryPool(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT QueryPool( VkQueryPool queryPool ) VULKAN_HPP_NOEXCEPT
+ : m_queryPool( queryPool )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ QueryPool & operator=(VkQueryPool queryPool) VULKAN_HPP_NOEXCEPT
+ {
+ m_queryPool = queryPool;
+ return *this;
+ }
+#endif
+
+ QueryPool & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_queryPool = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( QueryPool const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queryPool == rhs.m_queryPool;
+ }
+
+ bool operator!=(QueryPool const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queryPool != rhs.m_queryPool;
+ }
+
+ bool operator<(QueryPool const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queryPool < rhs.m_queryPool;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkQueryPool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queryPool;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queryPool != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queryPool == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkQueryPool m_queryPool;
+ };
+ static_assert( sizeof( QueryPool ) == sizeof( VkQueryPool ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eQueryPool>
+ {
+ using type = QueryPool;
+ };
+
+ class Buffer
+ {
+ public:
+ using CType = VkBuffer;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eBuffer;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Buffer() VULKAN_HPP_NOEXCEPT
+ : m_buffer(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Buffer( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_buffer(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Buffer( VkBuffer buffer ) VULKAN_HPP_NOEXCEPT
+ : m_buffer( buffer )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Buffer & operator=(VkBuffer buffer) VULKAN_HPP_NOEXCEPT
+ {
+ m_buffer = buffer;
+ return *this;
+ }
+#endif
+
+ Buffer & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_buffer = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Buffer const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_buffer == rhs.m_buffer;
+ }
+
+ bool operator!=(Buffer const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_buffer != rhs.m_buffer;
+ }
+
+ bool operator<(Buffer const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_buffer < rhs.m_buffer;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkBuffer() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_buffer;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_buffer != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_buffer == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkBuffer m_buffer;
+ };
+ static_assert( sizeof( Buffer ) == sizeof( VkBuffer ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eBuffer>
+ {
+ using type = Buffer;
+ };
+
+ class PipelineLayout
+ {
+ public:
+ using CType = VkPipelineLayout;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::ePipelineLayout;
+
+ public:
+ VULKAN_HPP_CONSTEXPR PipelineLayout() VULKAN_HPP_NOEXCEPT
+ : m_pipelineLayout(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR PipelineLayout( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_pipelineLayout(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT PipelineLayout( VkPipelineLayout pipelineLayout ) VULKAN_HPP_NOEXCEPT
+ : m_pipelineLayout( pipelineLayout )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ PipelineLayout & operator=(VkPipelineLayout pipelineLayout) VULKAN_HPP_NOEXCEPT
+ {
+ m_pipelineLayout = pipelineLayout;
+ return *this;
+ }
+#endif
+
+ PipelineLayout & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_pipelineLayout = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( PipelineLayout const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineLayout == rhs.m_pipelineLayout;
+ }
+
+ bool operator!=(PipelineLayout const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineLayout != rhs.m_pipelineLayout;
+ }
+
+ bool operator<(PipelineLayout const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineLayout < rhs.m_pipelineLayout;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkPipelineLayout() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineLayout;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineLayout != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineLayout == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkPipelineLayout m_pipelineLayout;
+ };
+ static_assert( sizeof( PipelineLayout ) == sizeof( VkPipelineLayout ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::ePipelineLayout>
+ {
+ using type = PipelineLayout;
+ };
+
+ class DescriptorSet
+ {
+ public:
+ using CType = VkDescriptorSet;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDescriptorSet;
+
+ public:
+ VULKAN_HPP_CONSTEXPR DescriptorSet() VULKAN_HPP_NOEXCEPT
+ : m_descriptorSet(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR DescriptorSet( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_descriptorSet(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT DescriptorSet( VkDescriptorSet descriptorSet ) VULKAN_HPP_NOEXCEPT
+ : m_descriptorSet( descriptorSet )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ DescriptorSet & operator=(VkDescriptorSet descriptorSet) VULKAN_HPP_NOEXCEPT
+ {
+ m_descriptorSet = descriptorSet;
+ return *this;
+ }
+#endif
+
+ DescriptorSet & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_descriptorSet = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( DescriptorSet const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSet == rhs.m_descriptorSet;
+ }
+
+ bool operator!=(DescriptorSet const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSet != rhs.m_descriptorSet;
+ }
+
+ bool operator<(DescriptorSet const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSet < rhs.m_descriptorSet;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDescriptorSet() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSet;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSet != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSet == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkDescriptorSet m_descriptorSet;
+ };
+ static_assert( sizeof( DescriptorSet ) == sizeof( VkDescriptorSet ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eDescriptorSet>
+ {
+ using type = DescriptorSet;
+ };
+
+ class Pipeline
+ {
+ public:
+ using CType = VkPipeline;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::ePipeline;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Pipeline() VULKAN_HPP_NOEXCEPT
+ : m_pipeline(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Pipeline( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_pipeline(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Pipeline( VkPipeline pipeline ) VULKAN_HPP_NOEXCEPT
+ : m_pipeline( pipeline )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Pipeline & operator=(VkPipeline pipeline) VULKAN_HPP_NOEXCEPT
+ {
+ m_pipeline = pipeline;
+ return *this;
+ }
+#endif
+
+ Pipeline & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_pipeline = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Pipeline const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipeline == rhs.m_pipeline;
+ }
+
+ bool operator!=(Pipeline const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipeline != rhs.m_pipeline;
+ }
+
+ bool operator<(Pipeline const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipeline < rhs.m_pipeline;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkPipeline() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipeline;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipeline != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipeline == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkPipeline m_pipeline;
+ };
+ static_assert( sizeof( Pipeline ) == sizeof( VkPipeline ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::ePipeline>
+ {
+ using type = Pipeline;
+ };
+
+ class ImageView
+ {
+ public:
+ using CType = VkImageView;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eImageView;
+
+ public:
+ VULKAN_HPP_CONSTEXPR ImageView() VULKAN_HPP_NOEXCEPT
+ : m_imageView(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR ImageView( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_imageView(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT ImageView( VkImageView imageView ) VULKAN_HPP_NOEXCEPT
+ : m_imageView( imageView )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ ImageView & operator=(VkImageView imageView) VULKAN_HPP_NOEXCEPT
+ {
+ m_imageView = imageView;
+ return *this;
+ }
+#endif
+
+ ImageView & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_imageView = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( ImageView const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_imageView == rhs.m_imageView;
+ }
+
+ bool operator!=(ImageView const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_imageView != rhs.m_imageView;
+ }
+
+ bool operator<(ImageView const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_imageView < rhs.m_imageView;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkImageView() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_imageView;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_imageView != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_imageView == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkImageView m_imageView;
+ };
+ static_assert( sizeof( ImageView ) == sizeof( VkImageView ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eImageView>
+ {
+ using type = ImageView;
+ };
+
+ class Image
+ {
+ public:
+ using CType = VkImage;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eImage;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Image() VULKAN_HPP_NOEXCEPT
+ : m_image(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Image( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_image(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Image( VkImage image ) VULKAN_HPP_NOEXCEPT
+ : m_image( image )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Image & operator=(VkImage image) VULKAN_HPP_NOEXCEPT
+ {
+ m_image = image;
+ return *this;
+ }
+#endif
+
+ Image & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_image = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Image const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_image == rhs.m_image;
+ }
+
+ bool operator!=(Image const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_image != rhs.m_image;
+ }
+
+ bool operator<(Image const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_image < rhs.m_image;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkImage() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_image;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_image != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_image == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkImage m_image;
+ };
+ static_assert( sizeof( Image ) == sizeof( VkImage ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eImage>
+ {
+ using type = Image;
+ };
+
+ class AccelerationStructureNV
+ {
+ public:
+ using CType = VkAccelerationStructureNV;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eAccelerationStructureNV;
+
+ public:
+ VULKAN_HPP_CONSTEXPR AccelerationStructureNV() VULKAN_HPP_NOEXCEPT
+ : m_accelerationStructureNV(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR AccelerationStructureNV( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_accelerationStructureNV(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT AccelerationStructureNV( VkAccelerationStructureNV accelerationStructureNV ) VULKAN_HPP_NOEXCEPT
+ : m_accelerationStructureNV( accelerationStructureNV )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ AccelerationStructureNV & operator=(VkAccelerationStructureNV accelerationStructureNV) VULKAN_HPP_NOEXCEPT
+ {
+ m_accelerationStructureNV = accelerationStructureNV;
+ return *this;
+ }
+#endif
+
+ AccelerationStructureNV & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_accelerationStructureNV = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( AccelerationStructureNV const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_accelerationStructureNV == rhs.m_accelerationStructureNV;
+ }
+
+ bool operator!=(AccelerationStructureNV const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_accelerationStructureNV != rhs.m_accelerationStructureNV;
+ }
+
+ bool operator<(AccelerationStructureNV const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_accelerationStructureNV < rhs.m_accelerationStructureNV;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkAccelerationStructureNV() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_accelerationStructureNV;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_accelerationStructureNV != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_accelerationStructureNV == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkAccelerationStructureNV m_accelerationStructureNV;
+ };
+ static_assert( sizeof( AccelerationStructureNV ) == sizeof( VkAccelerationStructureNV ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eAccelerationStructureNV>
+ {
+ using type = AccelerationStructureNV;
+ };
+
+ class DescriptorUpdateTemplate
+ {
+ public:
+ using CType = VkDescriptorUpdateTemplate;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDescriptorUpdateTemplate;
+
+ public:
+ VULKAN_HPP_CONSTEXPR DescriptorUpdateTemplate() VULKAN_HPP_NOEXCEPT
+ : m_descriptorUpdateTemplate(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR DescriptorUpdateTemplate( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_descriptorUpdateTemplate(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT DescriptorUpdateTemplate( VkDescriptorUpdateTemplate descriptorUpdateTemplate ) VULKAN_HPP_NOEXCEPT
+ : m_descriptorUpdateTemplate( descriptorUpdateTemplate )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ DescriptorUpdateTemplate & operator=(VkDescriptorUpdateTemplate descriptorUpdateTemplate) VULKAN_HPP_NOEXCEPT
+ {
+ m_descriptorUpdateTemplate = descriptorUpdateTemplate;
+ return *this;
+ }
+#endif
+
+ DescriptorUpdateTemplate & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_descriptorUpdateTemplate = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( DescriptorUpdateTemplate const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorUpdateTemplate == rhs.m_descriptorUpdateTemplate;
+ }
+
+ bool operator!=(DescriptorUpdateTemplate const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorUpdateTemplate != rhs.m_descriptorUpdateTemplate;
+ }
+
+ bool operator<(DescriptorUpdateTemplate const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorUpdateTemplate < rhs.m_descriptorUpdateTemplate;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDescriptorUpdateTemplate() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorUpdateTemplate;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorUpdateTemplate != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorUpdateTemplate == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkDescriptorUpdateTemplate m_descriptorUpdateTemplate;
+ };
+ static_assert( sizeof( DescriptorUpdateTemplate ) == sizeof( VkDescriptorUpdateTemplate ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eDescriptorUpdateTemplate>
+ {
+ using type = DescriptorUpdateTemplate;
+ };
+ using DescriptorUpdateTemplateKHR = DescriptorUpdateTemplate;
+
+ class Event
+ {
+ public:
+ using CType = VkEvent;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eEvent;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Event() VULKAN_HPP_NOEXCEPT
+ : m_event(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Event( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_event(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Event( VkEvent event ) VULKAN_HPP_NOEXCEPT
+ : m_event( event )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Event & operator=(VkEvent event) VULKAN_HPP_NOEXCEPT
+ {
+ m_event = event;
+ return *this;
+ }
+#endif
+
+ Event & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_event = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Event const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_event == rhs.m_event;
+ }
+
+ bool operator!=(Event const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_event != rhs.m_event;
+ }
+
+ bool operator<(Event const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_event < rhs.m_event;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkEvent() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_event;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_event != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_event == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkEvent m_event;
+ };
+ static_assert( sizeof( Event ) == sizeof( VkEvent ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eEvent>
+ {
+ using type = Event;
+ };
+
+ class CommandBuffer
+ {
+ public:
+ using CType = VkCommandBuffer;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eCommandBuffer;
+
+ public:
+ VULKAN_HPP_CONSTEXPR CommandBuffer() VULKAN_HPP_NOEXCEPT
+ : m_commandBuffer(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR CommandBuffer( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_commandBuffer(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT CommandBuffer( VkCommandBuffer commandBuffer ) VULKAN_HPP_NOEXCEPT
+ : m_commandBuffer( commandBuffer )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ CommandBuffer & operator=(VkCommandBuffer commandBuffer) VULKAN_HPP_NOEXCEPT
+ {
+ m_commandBuffer = commandBuffer;
+ return *this;
+ }
+#endif
+
+ CommandBuffer & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_commandBuffer = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( CommandBuffer const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandBuffer == rhs.m_commandBuffer;
+ }
+
+ bool operator!=(CommandBuffer const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandBuffer != rhs.m_commandBuffer;
+ }
+
+ bool operator<(CommandBuffer const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandBuffer < rhs.m_commandBuffer;
+ }
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result begin( const VULKAN_HPP_NAMESPACE::CommandBufferBeginInfo* pBeginInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type begin( const CommandBufferBeginInfo & beginInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginConditionalRenderingEXT( const VULKAN_HPP_NAMESPACE::ConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginConditionalRenderingEXT( const ConditionalRenderingBeginInfoEXT & conditionalRenderingBegin, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginDebugUtilsLabelEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pLabelInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginDebugUtilsLabelEXT( const DebugUtilsLabelEXT & labelInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginQuery( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, VULKAN_HPP_NAMESPACE::QueryControlFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginQueryIndexedEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, VULKAN_HPP_NAMESPACE::QueryControlFlags flags, uint32_t index, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginRenderPass( const VULKAN_HPP_NAMESPACE::RenderPassBeginInfo* pRenderPassBegin, VULKAN_HPP_NAMESPACE::SubpassContents contents, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginRenderPass( const RenderPassBeginInfo & renderPassBegin, VULKAN_HPP_NAMESPACE::SubpassContents contents, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginRenderPass2( const VULKAN_HPP_NAMESPACE::RenderPassBeginInfo* pRenderPassBegin, const VULKAN_HPP_NAMESPACE::SubpassBeginInfo* pSubpassBeginInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginRenderPass2( const RenderPassBeginInfo & renderPassBegin, const SubpassBeginInfo & subpassBeginInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginRenderPass2KHR( const VULKAN_HPP_NAMESPACE::RenderPassBeginInfo* pRenderPassBegin, const VULKAN_HPP_NAMESPACE::SubpassBeginInfo* pSubpassBeginInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginRenderPass2KHR( const RenderPassBeginInfo & renderPassBegin, const SubpassBeginInfo & subpassBeginInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginTransformFeedbackEXT( uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VULKAN_HPP_NAMESPACE::Buffer* pCounterBuffers, const VULKAN_HPP_NAMESPACE::DeviceSize* pCounterBufferOffsets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginTransformFeedbackEXT( uint32_t firstCounterBuffer, ArrayProxy<const VULKAN_HPP_NAMESPACE::Buffer> counterBuffers, ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> counterBufferOffsets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void bindDescriptorSets( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VULKAN_HPP_NAMESPACE::DescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void bindDescriptorSets( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t firstSet, ArrayProxy<const VULKAN_HPP_NAMESPACE::DescriptorSet> descriptorSets, ArrayProxy<const uint32_t> dynamicOffsets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void bindIndexBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::IndexType indexType, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void bindPipeline( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::Pipeline pipeline, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void bindShadingRateImageNV( VULKAN_HPP_NAMESPACE::ImageView imageView, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void bindTransformFeedbackBuffersEXT( uint32_t firstBinding, uint32_t bindingCount, const VULKAN_HPP_NAMESPACE::Buffer* pBuffers, const VULKAN_HPP_NAMESPACE::DeviceSize* pOffsets, const VULKAN_HPP_NAMESPACE::DeviceSize* pSizes, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void bindTransformFeedbackBuffersEXT( uint32_t firstBinding, ArrayProxy<const VULKAN_HPP_NAMESPACE::Buffer> buffers, ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> offsets, ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> sizes, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void bindVertexBuffers( uint32_t firstBinding, uint32_t bindingCount, const VULKAN_HPP_NAMESPACE::Buffer* pBuffers, const VULKAN_HPP_NAMESPACE::DeviceSize* pOffsets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void bindVertexBuffers( uint32_t firstBinding, ArrayProxy<const VULKAN_HPP_NAMESPACE::Buffer> buffers, ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> offsets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void blitImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::ImageBlit* pRegions, VULKAN_HPP_NAMESPACE::Filter filter, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void blitImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageBlit> regions, VULKAN_HPP_NAMESPACE::Filter filter, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void buildAccelerationStructureNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV* pInfo, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void buildAccelerationStructureNV( const AccelerationStructureInfoNV & info, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void clearAttachments( uint32_t attachmentCount, const VULKAN_HPP_NAMESPACE::ClearAttachment* pAttachments, uint32_t rectCount, const VULKAN_HPP_NAMESPACE::ClearRect* pRects, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void clearAttachments( ArrayProxy<const VULKAN_HPP_NAMESPACE::ClearAttachment> attachments, ArrayProxy<const VULKAN_HPP_NAMESPACE::ClearRect> rects, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void clearColorImage( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, const VULKAN_HPP_NAMESPACE::ClearColorValue* pColor, uint32_t rangeCount, const VULKAN_HPP_NAMESPACE::ImageSubresourceRange* pRanges, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void clearColorImage( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, const ClearColorValue & color, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageSubresourceRange> ranges, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void clearDepthStencilImage( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, const VULKAN_HPP_NAMESPACE::ClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VULKAN_HPP_NAMESPACE::ImageSubresourceRange* pRanges, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void clearDepthStencilImage( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, const ClearDepthStencilValue & depthStencil, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageSubresourceRange> ranges, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void copyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeNV mode, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void copyBuffer( VULKAN_HPP_NAMESPACE::Buffer srcBuffer, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::BufferCopy* pRegions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void copyBuffer( VULKAN_HPP_NAMESPACE::Buffer srcBuffer, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferCopy> regions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void copyBufferToImage( VULKAN_HPP_NAMESPACE::Buffer srcBuffer, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::BufferImageCopy* pRegions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void copyBufferToImage( VULKAN_HPP_NAMESPACE::Buffer srcBuffer, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferImageCopy> regions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void copyImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::ImageCopy* pRegions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void copyImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageCopy> regions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void copyImageToBuffer( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::BufferImageCopy* pRegions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void copyImageToBuffer( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferImageCopy> regions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void copyQueryPoolResults( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize stride, VULKAN_HPP_NAMESPACE::QueryResultFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void debugMarkerBeginEXT( const VULKAN_HPP_NAMESPACE::DebugMarkerMarkerInfoEXT* pMarkerInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void debugMarkerBeginEXT( const DebugMarkerMarkerInfoEXT & markerInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void debugMarkerEndEXT(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void debugMarkerInsertEXT( const VULKAN_HPP_NAMESPACE::DebugMarkerMarkerInfoEXT* pMarkerInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void debugMarkerInsertEXT( const DebugMarkerMarkerInfoEXT & markerInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void dispatch( uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void dispatchBase( uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void dispatchBaseKHR( uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void dispatchIndirect( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void draw( uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawIndexed( uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawIndexedIndirect( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, uint32_t drawCount, uint32_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawIndexedIndirectCount( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawIndexedIndirectCountAMD( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawIndexedIndirectCountKHR( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawIndirect( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, uint32_t drawCount, uint32_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawIndirectByteCountEXT( uint32_t instanceCount, uint32_t firstInstance, VULKAN_HPP_NAMESPACE::Buffer counterBuffer, VULKAN_HPP_NAMESPACE::DeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawIndirectCount( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawIndirectCountAMD( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawIndirectCountKHR( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawMeshTasksIndirectCountNV( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawMeshTasksIndirectNV( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, uint32_t drawCount, uint32_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void drawMeshTasksNV( uint32_t taskCount, uint32_t firstTask, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endConditionalRenderingEXT(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endDebugUtilsLabelEXT(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endQuery( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endQueryIndexedEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, uint32_t index, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endRenderPass(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endRenderPass2( const VULKAN_HPP_NAMESPACE::SubpassEndInfo* pSubpassEndInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endRenderPass2( const SubpassEndInfo & subpassEndInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endRenderPass2KHR( const VULKAN_HPP_NAMESPACE::SubpassEndInfo* pSubpassEndInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endRenderPass2KHR( const SubpassEndInfo & subpassEndInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endTransformFeedbackEXT( uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VULKAN_HPP_NAMESPACE::Buffer* pCounterBuffers, const VULKAN_HPP_NAMESPACE::DeviceSize* pCounterBufferOffsets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endTransformFeedbackEXT( uint32_t firstCounterBuffer, ArrayProxy<const VULKAN_HPP_NAMESPACE::Buffer> counterBuffers, ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> counterBufferOffsets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void executeCommands( uint32_t commandBufferCount, const VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void executeCommands( ArrayProxy<const VULKAN_HPP_NAMESPACE::CommandBuffer> commandBuffers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void fillBuffer( VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize size, uint32_t data, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void insertDebugUtilsLabelEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pLabelInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void insertDebugUtilsLabelEXT( const DebugUtilsLabelEXT & labelInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void nextSubpass( VULKAN_HPP_NAMESPACE::SubpassContents contents, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void nextSubpass2( const VULKAN_HPP_NAMESPACE::SubpassBeginInfo* pSubpassBeginInfo, const VULKAN_HPP_NAMESPACE::SubpassEndInfo* pSubpassEndInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void nextSubpass2( const SubpassBeginInfo & subpassBeginInfo, const SubpassEndInfo & subpassEndInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void nextSubpass2KHR( const VULKAN_HPP_NAMESPACE::SubpassBeginInfo* pSubpassBeginInfo, const VULKAN_HPP_NAMESPACE::SubpassEndInfo* pSubpassEndInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void nextSubpass2KHR( const SubpassBeginInfo & subpassBeginInfo, const SubpassEndInfo & subpassEndInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void pipelineBarrier( VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask, VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask, VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VULKAN_HPP_NAMESPACE::MemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VULKAN_HPP_NAMESPACE::BufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VULKAN_HPP_NAMESPACE::ImageMemoryBarrier* pImageMemoryBarriers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void pipelineBarrier( VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask, VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask, VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags, ArrayProxy<const VULKAN_HPP_NAMESPACE::MemoryBarrier> memoryBarriers, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferMemoryBarrier> bufferMemoryBarriers, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageMemoryBarrier> imageMemoryBarriers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void processCommandsNVX( const VULKAN_HPP_NAMESPACE::CmdProcessCommandsInfoNVX* pProcessCommandsInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void processCommandsNVX( const CmdProcessCommandsInfoNVX & processCommandsInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void pushConstants( VULKAN_HPP_NAMESPACE::PipelineLayout layout, VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename T, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void pushConstants( VULKAN_HPP_NAMESPACE::PipelineLayout layout, VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags, uint32_t offset, ArrayProxy<const T> values, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void pushDescriptorSetKHR( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VULKAN_HPP_NAMESPACE::WriteDescriptorSet* pDescriptorWrites, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void pushDescriptorSetKHR( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t set, ArrayProxy<const VULKAN_HPP_NAMESPACE::WriteDescriptorSet> descriptorWrites, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void pushDescriptorSetWithTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t set, const void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void reserveSpaceForCommandsNVX( const VULKAN_HPP_NAMESPACE::CmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void reserveSpaceForCommandsNVX( const CmdReserveSpaceForCommandsInfoNVX & reserveSpaceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void resetEvent( VULKAN_HPP_NAMESPACE::Event event, VULKAN_HPP_NAMESPACE::PipelineStageFlags stageMask, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void resetQueryPool( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void resolveImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::ImageResolve* pRegions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void resolveImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageResolve> regions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setBlendConstants( const float blendConstants[4], Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setCheckpointNV( const void* pCheckpointMarker, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setCoarseSampleOrderNV( VULKAN_HPP_NAMESPACE::CoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VULKAN_HPP_NAMESPACE::CoarseSampleOrderCustomNV* pCustomSampleOrders, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setCoarseSampleOrderNV( VULKAN_HPP_NAMESPACE::CoarseSampleOrderTypeNV sampleOrderType, ArrayProxy<const VULKAN_HPP_NAMESPACE::CoarseSampleOrderCustomNV> customSampleOrders, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setDepthBias( float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setDepthBounds( float minDepthBounds, float maxDepthBounds, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setDeviceMask( uint32_t deviceMask, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setDeviceMaskKHR( uint32_t deviceMask, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setDiscardRectangleEXT( uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VULKAN_HPP_NAMESPACE::Rect2D* pDiscardRectangles, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setDiscardRectangleEXT( uint32_t firstDiscardRectangle, ArrayProxy<const VULKAN_HPP_NAMESPACE::Rect2D> discardRectangles, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setEvent( VULKAN_HPP_NAMESPACE::Event event, VULKAN_HPP_NAMESPACE::PipelineStageFlags stageMask, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setExclusiveScissorNV( uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VULKAN_HPP_NAMESPACE::Rect2D* pExclusiveScissors, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setExclusiveScissorNV( uint32_t firstExclusiveScissor, ArrayProxy<const VULKAN_HPP_NAMESPACE::Rect2D> exclusiveScissors, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setLineStippleEXT( uint32_t lineStippleFactor, uint16_t lineStipplePattern, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setLineWidth( float lineWidth, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result setPerformanceMarkerINTEL( const VULKAN_HPP_NAMESPACE::PerformanceMarkerInfoINTEL* pMarkerInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type setPerformanceMarkerINTEL( const PerformanceMarkerInfoINTEL & markerInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result setPerformanceOverrideINTEL( const VULKAN_HPP_NAMESPACE::PerformanceOverrideInfoINTEL* pOverrideInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type setPerformanceOverrideINTEL( const PerformanceOverrideInfoINTEL & overrideInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result setPerformanceStreamMarkerINTEL( const VULKAN_HPP_NAMESPACE::PerformanceStreamMarkerInfoINTEL* pMarkerInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type setPerformanceStreamMarkerINTEL( const PerformanceStreamMarkerInfoINTEL & markerInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setSampleLocationsEXT( const VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT* pSampleLocationsInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setSampleLocationsEXT( const SampleLocationsInfoEXT & sampleLocationsInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setScissor( uint32_t firstScissor, uint32_t scissorCount, const VULKAN_HPP_NAMESPACE::Rect2D* pScissors, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setScissor( uint32_t firstScissor, ArrayProxy<const VULKAN_HPP_NAMESPACE::Rect2D> scissors, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setStencilCompareMask( VULKAN_HPP_NAMESPACE::StencilFaceFlags faceMask, uint32_t compareMask, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setStencilReference( VULKAN_HPP_NAMESPACE::StencilFaceFlags faceMask, uint32_t reference, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setStencilWriteMask( VULKAN_HPP_NAMESPACE::StencilFaceFlags faceMask, uint32_t writeMask, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setViewport( uint32_t firstViewport, uint32_t viewportCount, const VULKAN_HPP_NAMESPACE::Viewport* pViewports, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setViewport( uint32_t firstViewport, ArrayProxy<const VULKAN_HPP_NAMESPACE::Viewport> viewports, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setViewportShadingRatePaletteNV( uint32_t firstViewport, uint32_t viewportCount, const VULKAN_HPP_NAMESPACE::ShadingRatePaletteNV* pShadingRatePalettes, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setViewportShadingRatePaletteNV( uint32_t firstViewport, ArrayProxy<const VULKAN_HPP_NAMESPACE::ShadingRatePaletteNV> shadingRatePalettes, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setViewportWScalingNV( uint32_t firstViewport, uint32_t viewportCount, const VULKAN_HPP_NAMESPACE::ViewportWScalingNV* pViewportWScalings, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setViewportWScalingNV( uint32_t firstViewport, ArrayProxy<const VULKAN_HPP_NAMESPACE::ViewportWScalingNV> viewportWScalings, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void traceRaysNV( VULKAN_HPP_NAMESPACE::Buffer raygenShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize raygenShaderBindingOffset, VULKAN_HPP_NAMESPACE::Buffer missShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize missShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize missShaderBindingStride, VULKAN_HPP_NAMESPACE::Buffer hitShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize hitShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize hitShaderBindingStride, VULKAN_HPP_NAMESPACE::Buffer callableShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize callableShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void updateBuffer( VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize dataSize, const void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename T, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void updateBuffer( VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, ArrayProxy<const T> data, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void waitEvents( uint32_t eventCount, const VULKAN_HPP_NAMESPACE::Event* pEvents, VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask, VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VULKAN_HPP_NAMESPACE::MemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VULKAN_HPP_NAMESPACE::BufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VULKAN_HPP_NAMESPACE::ImageMemoryBarrier* pImageMemoryBarriers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void waitEvents( ArrayProxy<const VULKAN_HPP_NAMESPACE::Event> events, VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask, VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask, ArrayProxy<const VULKAN_HPP_NAMESPACE::MemoryBarrier> memoryBarriers, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferMemoryBarrier> bufferMemoryBarriers, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageMemoryBarrier> imageMemoryBarriers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void writeAccelerationStructuresPropertiesNV( uint32_t accelerationStructureCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void writeAccelerationStructuresPropertiesNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureNV> accelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void writeBufferMarkerAMD( VULKAN_HPP_NAMESPACE::PipelineStageFlagBits pipelineStage, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, uint32_t marker, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void writeTimestamp( VULKAN_HPP_NAMESPACE::PipelineStageFlagBits pipelineStage, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result end(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type end(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result reset( VULKAN_HPP_NAMESPACE::CommandBufferResetFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type reset( VULKAN_HPP_NAMESPACE::CommandBufferResetFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkCommandBuffer() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandBuffer;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandBuffer != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandBuffer == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkCommandBuffer m_commandBuffer;
+ };
+ static_assert( sizeof( CommandBuffer ) == sizeof( VkCommandBuffer ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eCommandBuffer>
+ {
+ using type = CommandBuffer;
+ };
+
+ class DeviceMemory
+ {
+ public:
+ using CType = VkDeviceMemory;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDeviceMemory;
+
+ public:
+ VULKAN_HPP_CONSTEXPR DeviceMemory() VULKAN_HPP_NOEXCEPT
+ : m_deviceMemory(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR DeviceMemory( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_deviceMemory(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT DeviceMemory( VkDeviceMemory deviceMemory ) VULKAN_HPP_NOEXCEPT
+ : m_deviceMemory( deviceMemory )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ DeviceMemory & operator=(VkDeviceMemory deviceMemory) VULKAN_HPP_NOEXCEPT
+ {
+ m_deviceMemory = deviceMemory;
+ return *this;
+ }
+#endif
+
+ DeviceMemory & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_deviceMemory = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( DeviceMemory const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_deviceMemory == rhs.m_deviceMemory;
+ }
+
+ bool operator!=(DeviceMemory const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_deviceMemory != rhs.m_deviceMemory;
+ }
+
+ bool operator<(DeviceMemory const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_deviceMemory < rhs.m_deviceMemory;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDeviceMemory() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_deviceMemory;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_deviceMemory != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_deviceMemory == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkDeviceMemory m_deviceMemory;
+ };
+ static_assert( sizeof( DeviceMemory ) == sizeof( VkDeviceMemory ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eDeviceMemory>
+ {
+ using type = DeviceMemory;
+ };
+
+ class BufferView
+ {
+ public:
+ using CType = VkBufferView;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eBufferView;
+
+ public:
+ VULKAN_HPP_CONSTEXPR BufferView() VULKAN_HPP_NOEXCEPT
+ : m_bufferView(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR BufferView( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_bufferView(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT BufferView( VkBufferView bufferView ) VULKAN_HPP_NOEXCEPT
+ : m_bufferView( bufferView )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ BufferView & operator=(VkBufferView bufferView) VULKAN_HPP_NOEXCEPT
+ {
+ m_bufferView = bufferView;
+ return *this;
+ }
+#endif
+
+ BufferView & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_bufferView = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( BufferView const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_bufferView == rhs.m_bufferView;
+ }
+
+ bool operator!=(BufferView const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_bufferView != rhs.m_bufferView;
+ }
+
+ bool operator<(BufferView const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_bufferView < rhs.m_bufferView;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkBufferView() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_bufferView;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_bufferView != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_bufferView == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkBufferView m_bufferView;
+ };
+ static_assert( sizeof( BufferView ) == sizeof( VkBufferView ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eBufferView>
+ {
+ using type = BufferView;
+ };
+
+ class CommandPool
+ {
+ public:
+ using CType = VkCommandPool;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eCommandPool;
+
+ public:
+ VULKAN_HPP_CONSTEXPR CommandPool() VULKAN_HPP_NOEXCEPT
+ : m_commandPool(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR CommandPool( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_commandPool(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT CommandPool( VkCommandPool commandPool ) VULKAN_HPP_NOEXCEPT
+ : m_commandPool( commandPool )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ CommandPool & operator=(VkCommandPool commandPool) VULKAN_HPP_NOEXCEPT
+ {
+ m_commandPool = commandPool;
+ return *this;
+ }
+#endif
+
+ CommandPool & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_commandPool = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( CommandPool const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandPool == rhs.m_commandPool;
+ }
+
+ bool operator!=(CommandPool const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandPool != rhs.m_commandPool;
+ }
+
+ bool operator<(CommandPool const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandPool < rhs.m_commandPool;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkCommandPool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandPool;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandPool != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_commandPool == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkCommandPool m_commandPool;
+ };
+ static_assert( sizeof( CommandPool ) == sizeof( VkCommandPool ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eCommandPool>
+ {
+ using type = CommandPool;
+ };
+
+ class PipelineCache
+ {
+ public:
+ using CType = VkPipelineCache;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::ePipelineCache;
+
+ public:
+ VULKAN_HPP_CONSTEXPR PipelineCache() VULKAN_HPP_NOEXCEPT
+ : m_pipelineCache(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR PipelineCache( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_pipelineCache(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT PipelineCache( VkPipelineCache pipelineCache ) VULKAN_HPP_NOEXCEPT
+ : m_pipelineCache( pipelineCache )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ PipelineCache & operator=(VkPipelineCache pipelineCache) VULKAN_HPP_NOEXCEPT
+ {
+ m_pipelineCache = pipelineCache;
+ return *this;
+ }
+#endif
+
+ PipelineCache & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_pipelineCache = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( PipelineCache const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineCache == rhs.m_pipelineCache;
+ }
+
+ bool operator!=(PipelineCache const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineCache != rhs.m_pipelineCache;
+ }
+
+ bool operator<(PipelineCache const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineCache < rhs.m_pipelineCache;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkPipelineCache() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineCache;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineCache != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_pipelineCache == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkPipelineCache m_pipelineCache;
+ };
+ static_assert( sizeof( PipelineCache ) == sizeof( VkPipelineCache ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::ePipelineCache>
+ {
+ using type = PipelineCache;
+ };
+
+ class DescriptorPool
+ {
+ public:
+ using CType = VkDescriptorPool;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDescriptorPool;
+
+ public:
+ VULKAN_HPP_CONSTEXPR DescriptorPool() VULKAN_HPP_NOEXCEPT
+ : m_descriptorPool(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR DescriptorPool( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_descriptorPool(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT DescriptorPool( VkDescriptorPool descriptorPool ) VULKAN_HPP_NOEXCEPT
+ : m_descriptorPool( descriptorPool )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ DescriptorPool & operator=(VkDescriptorPool descriptorPool) VULKAN_HPP_NOEXCEPT
+ {
+ m_descriptorPool = descriptorPool;
+ return *this;
+ }
+#endif
+
+ DescriptorPool & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_descriptorPool = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( DescriptorPool const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorPool == rhs.m_descriptorPool;
+ }
+
+ bool operator!=(DescriptorPool const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorPool != rhs.m_descriptorPool;
+ }
+
+ bool operator<(DescriptorPool const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorPool < rhs.m_descriptorPool;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDescriptorPool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorPool;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorPool != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorPool == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkDescriptorPool m_descriptorPool;
+ };
+ static_assert( sizeof( DescriptorPool ) == sizeof( VkDescriptorPool ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eDescriptorPool>
+ {
+ using type = DescriptorPool;
+ };
+
+ class DescriptorSetLayout
+ {
+ public:
+ using CType = VkDescriptorSetLayout;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDescriptorSetLayout;
+
+ public:
+ VULKAN_HPP_CONSTEXPR DescriptorSetLayout() VULKAN_HPP_NOEXCEPT
+ : m_descriptorSetLayout(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR DescriptorSetLayout( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_descriptorSetLayout(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT DescriptorSetLayout( VkDescriptorSetLayout descriptorSetLayout ) VULKAN_HPP_NOEXCEPT
+ : m_descriptorSetLayout( descriptorSetLayout )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ DescriptorSetLayout & operator=(VkDescriptorSetLayout descriptorSetLayout) VULKAN_HPP_NOEXCEPT
+ {
+ m_descriptorSetLayout = descriptorSetLayout;
+ return *this;
+ }
+#endif
+
+ DescriptorSetLayout & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_descriptorSetLayout = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( DescriptorSetLayout const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSetLayout == rhs.m_descriptorSetLayout;
+ }
+
+ bool operator!=(DescriptorSetLayout const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSetLayout != rhs.m_descriptorSetLayout;
+ }
+
+ bool operator<(DescriptorSetLayout const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSetLayout < rhs.m_descriptorSetLayout;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDescriptorSetLayout() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSetLayout;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSetLayout != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_descriptorSetLayout == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkDescriptorSetLayout m_descriptorSetLayout;
+ };
+ static_assert( sizeof( DescriptorSetLayout ) == sizeof( VkDescriptorSetLayout ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eDescriptorSetLayout>
+ {
+ using type = DescriptorSetLayout;
+ };
+
+ class Framebuffer
+ {
+ public:
+ using CType = VkFramebuffer;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eFramebuffer;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Framebuffer() VULKAN_HPP_NOEXCEPT
+ : m_framebuffer(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Framebuffer( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_framebuffer(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Framebuffer( VkFramebuffer framebuffer ) VULKAN_HPP_NOEXCEPT
+ : m_framebuffer( framebuffer )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Framebuffer & operator=(VkFramebuffer framebuffer) VULKAN_HPP_NOEXCEPT
+ {
+ m_framebuffer = framebuffer;
+ return *this;
+ }
+#endif
+
+ Framebuffer & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_framebuffer = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Framebuffer const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_framebuffer == rhs.m_framebuffer;
+ }
+
+ bool operator!=(Framebuffer const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_framebuffer != rhs.m_framebuffer;
+ }
+
+ bool operator<(Framebuffer const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_framebuffer < rhs.m_framebuffer;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkFramebuffer() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_framebuffer;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_framebuffer != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_framebuffer == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkFramebuffer m_framebuffer;
+ };
+ static_assert( sizeof( Framebuffer ) == sizeof( VkFramebuffer ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eFramebuffer>
+ {
+ using type = Framebuffer;
+ };
+
+ class IndirectCommandsLayoutNVX
+ {
+ public:
+ using CType = VkIndirectCommandsLayoutNVX;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eIndirectCommandsLayoutNVX;
+
+ public:
+ VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutNVX() VULKAN_HPP_NOEXCEPT
+ : m_indirectCommandsLayoutNVX(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutNVX( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_indirectCommandsLayoutNVX(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT IndirectCommandsLayoutNVX( VkIndirectCommandsLayoutNVX indirectCommandsLayoutNVX ) VULKAN_HPP_NOEXCEPT
+ : m_indirectCommandsLayoutNVX( indirectCommandsLayoutNVX )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ IndirectCommandsLayoutNVX & operator=(VkIndirectCommandsLayoutNVX indirectCommandsLayoutNVX) VULKAN_HPP_NOEXCEPT
+ {
+ m_indirectCommandsLayoutNVX = indirectCommandsLayoutNVX;
+ return *this;
+ }
+#endif
+
+ IndirectCommandsLayoutNVX & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_indirectCommandsLayoutNVX = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( IndirectCommandsLayoutNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_indirectCommandsLayoutNVX == rhs.m_indirectCommandsLayoutNVX;
+ }
+
+ bool operator!=(IndirectCommandsLayoutNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_indirectCommandsLayoutNVX != rhs.m_indirectCommandsLayoutNVX;
+ }
+
+ bool operator<(IndirectCommandsLayoutNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_indirectCommandsLayoutNVX < rhs.m_indirectCommandsLayoutNVX;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkIndirectCommandsLayoutNVX() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_indirectCommandsLayoutNVX;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_indirectCommandsLayoutNVX != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_indirectCommandsLayoutNVX == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkIndirectCommandsLayoutNVX m_indirectCommandsLayoutNVX;
+ };
+ static_assert( sizeof( IndirectCommandsLayoutNVX ) == sizeof( VkIndirectCommandsLayoutNVX ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eIndirectCommandsLayoutNVX>
+ {
+ using type = IndirectCommandsLayoutNVX;
+ };
+
+ class ObjectTableNVX
+ {
+ public:
+ using CType = VkObjectTableNVX;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eObjectTableNVX;
+
+ public:
+ VULKAN_HPP_CONSTEXPR ObjectTableNVX() VULKAN_HPP_NOEXCEPT
+ : m_objectTableNVX(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR ObjectTableNVX( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_objectTableNVX(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT ObjectTableNVX( VkObjectTableNVX objectTableNVX ) VULKAN_HPP_NOEXCEPT
+ : m_objectTableNVX( objectTableNVX )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ ObjectTableNVX & operator=(VkObjectTableNVX objectTableNVX) VULKAN_HPP_NOEXCEPT
+ {
+ m_objectTableNVX = objectTableNVX;
+ return *this;
+ }
+#endif
+
+ ObjectTableNVX & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_objectTableNVX = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( ObjectTableNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_objectTableNVX == rhs.m_objectTableNVX;
+ }
+
+ bool operator!=(ObjectTableNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_objectTableNVX != rhs.m_objectTableNVX;
+ }
+
+ bool operator<(ObjectTableNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_objectTableNVX < rhs.m_objectTableNVX;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkObjectTableNVX() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_objectTableNVX;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_objectTableNVX != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_objectTableNVX == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkObjectTableNVX m_objectTableNVX;
+ };
+ static_assert( sizeof( ObjectTableNVX ) == sizeof( VkObjectTableNVX ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eObjectTableNVX>
+ {
+ using type = ObjectTableNVX;
+ };
+
+ class RenderPass
+ {
+ public:
+ using CType = VkRenderPass;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eRenderPass;
+
+ public:
+ VULKAN_HPP_CONSTEXPR RenderPass() VULKAN_HPP_NOEXCEPT
+ : m_renderPass(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR RenderPass( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_renderPass(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT RenderPass( VkRenderPass renderPass ) VULKAN_HPP_NOEXCEPT
+ : m_renderPass( renderPass )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ RenderPass & operator=(VkRenderPass renderPass) VULKAN_HPP_NOEXCEPT
+ {
+ m_renderPass = renderPass;
+ return *this;
+ }
+#endif
+
+ RenderPass & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_renderPass = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( RenderPass const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_renderPass == rhs.m_renderPass;
+ }
+
+ bool operator!=(RenderPass const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_renderPass != rhs.m_renderPass;
+ }
+
+ bool operator<(RenderPass const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_renderPass < rhs.m_renderPass;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkRenderPass() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_renderPass;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_renderPass != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_renderPass == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkRenderPass m_renderPass;
+ };
+ static_assert( sizeof( RenderPass ) == sizeof( VkRenderPass ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eRenderPass>
+ {
+ using type = RenderPass;
+ };
+
+ class Sampler
+ {
+ public:
+ using CType = VkSampler;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eSampler;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Sampler() VULKAN_HPP_NOEXCEPT
+ : m_sampler(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Sampler( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_sampler(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Sampler( VkSampler sampler ) VULKAN_HPP_NOEXCEPT
+ : m_sampler( sampler )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Sampler & operator=(VkSampler sampler) VULKAN_HPP_NOEXCEPT
+ {
+ m_sampler = sampler;
+ return *this;
+ }
+#endif
+
+ Sampler & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_sampler = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Sampler const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_sampler == rhs.m_sampler;
+ }
+
+ bool operator!=(Sampler const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_sampler != rhs.m_sampler;
+ }
+
+ bool operator<(Sampler const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_sampler < rhs.m_sampler;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkSampler() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_sampler;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_sampler != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_sampler == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkSampler m_sampler;
+ };
+ static_assert( sizeof( Sampler ) == sizeof( VkSampler ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eSampler>
+ {
+ using type = Sampler;
+ };
+
+ class SamplerYcbcrConversion
+ {
+ public:
+ using CType = VkSamplerYcbcrConversion;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eSamplerYcbcrConversion;
+
+ public:
+ VULKAN_HPP_CONSTEXPR SamplerYcbcrConversion() VULKAN_HPP_NOEXCEPT
+ : m_samplerYcbcrConversion(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR SamplerYcbcrConversion( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_samplerYcbcrConversion(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT SamplerYcbcrConversion( VkSamplerYcbcrConversion samplerYcbcrConversion ) VULKAN_HPP_NOEXCEPT
+ : m_samplerYcbcrConversion( samplerYcbcrConversion )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ SamplerYcbcrConversion & operator=(VkSamplerYcbcrConversion samplerYcbcrConversion) VULKAN_HPP_NOEXCEPT
+ {
+ m_samplerYcbcrConversion = samplerYcbcrConversion;
+ return *this;
+ }
+#endif
+
+ SamplerYcbcrConversion & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_samplerYcbcrConversion = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( SamplerYcbcrConversion const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_samplerYcbcrConversion == rhs.m_samplerYcbcrConversion;
+ }
+
+ bool operator!=(SamplerYcbcrConversion const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_samplerYcbcrConversion != rhs.m_samplerYcbcrConversion;
+ }
+
+ bool operator<(SamplerYcbcrConversion const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_samplerYcbcrConversion < rhs.m_samplerYcbcrConversion;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkSamplerYcbcrConversion() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_samplerYcbcrConversion;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_samplerYcbcrConversion != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_samplerYcbcrConversion == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkSamplerYcbcrConversion m_samplerYcbcrConversion;
+ };
+ static_assert( sizeof( SamplerYcbcrConversion ) == sizeof( VkSamplerYcbcrConversion ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eSamplerYcbcrConversion>
+ {
+ using type = SamplerYcbcrConversion;
+ };
+ using SamplerYcbcrConversionKHR = SamplerYcbcrConversion;
+
+ class ShaderModule
+ {
+ public:
+ using CType = VkShaderModule;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eShaderModule;
+
+ public:
+ VULKAN_HPP_CONSTEXPR ShaderModule() VULKAN_HPP_NOEXCEPT
+ : m_shaderModule(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR ShaderModule( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_shaderModule(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT ShaderModule( VkShaderModule shaderModule ) VULKAN_HPP_NOEXCEPT
+ : m_shaderModule( shaderModule )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ ShaderModule & operator=(VkShaderModule shaderModule) VULKAN_HPP_NOEXCEPT
+ {
+ m_shaderModule = shaderModule;
+ return *this;
+ }
+#endif
+
+ ShaderModule & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_shaderModule = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( ShaderModule const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_shaderModule == rhs.m_shaderModule;
+ }
+
+ bool operator!=(ShaderModule const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_shaderModule != rhs.m_shaderModule;
+ }
+
+ bool operator<(ShaderModule const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_shaderModule < rhs.m_shaderModule;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkShaderModule() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_shaderModule;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_shaderModule != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_shaderModule == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkShaderModule m_shaderModule;
+ };
+ static_assert( sizeof( ShaderModule ) == sizeof( VkShaderModule ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eShaderModule>
+ {
+ using type = ShaderModule;
+ };
+
+ class ValidationCacheEXT
+ {
+ public:
+ using CType = VkValidationCacheEXT;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eValidationCacheEXT;
+
+ public:
+ VULKAN_HPP_CONSTEXPR ValidationCacheEXT() VULKAN_HPP_NOEXCEPT
+ : m_validationCacheEXT(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR ValidationCacheEXT( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_validationCacheEXT(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT ValidationCacheEXT( VkValidationCacheEXT validationCacheEXT ) VULKAN_HPP_NOEXCEPT
+ : m_validationCacheEXT( validationCacheEXT )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ ValidationCacheEXT & operator=(VkValidationCacheEXT validationCacheEXT) VULKAN_HPP_NOEXCEPT
+ {
+ m_validationCacheEXT = validationCacheEXT;
+ return *this;
+ }
+#endif
+
+ ValidationCacheEXT & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_validationCacheEXT = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( ValidationCacheEXT const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_validationCacheEXT == rhs.m_validationCacheEXT;
+ }
+
+ bool operator!=(ValidationCacheEXT const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_validationCacheEXT != rhs.m_validationCacheEXT;
+ }
+
+ bool operator<(ValidationCacheEXT const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_validationCacheEXT < rhs.m_validationCacheEXT;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkValidationCacheEXT() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_validationCacheEXT;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_validationCacheEXT != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_validationCacheEXT == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkValidationCacheEXT m_validationCacheEXT;
+ };
+ static_assert( sizeof( ValidationCacheEXT ) == sizeof( VkValidationCacheEXT ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eValidationCacheEXT>
+ {
+ using type = ValidationCacheEXT;
+ };
+
+ class Queue
+ {
+ public:
+ using CType = VkQueue;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eQueue;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Queue() VULKAN_HPP_NOEXCEPT
+ : m_queue(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Queue( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_queue(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Queue( VkQueue queue ) VULKAN_HPP_NOEXCEPT
+ : m_queue( queue )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Queue & operator=(VkQueue queue) VULKAN_HPP_NOEXCEPT
+ {
+ m_queue = queue;
+ return *this;
+ }
+#endif
+
+ Queue & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_queue = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Queue const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queue == rhs.m_queue;
+ }
+
+ bool operator!=(Queue const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queue != rhs.m_queue;
+ }
+
+ bool operator<(Queue const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queue < rhs.m_queue;
+ }
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getCheckpointDataNV( uint32_t* pCheckpointDataCount, VULKAN_HPP_NAMESPACE::CheckpointDataNV* pCheckpointData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<CheckpointDataNV>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<CheckpointDataNV,Allocator> getCheckpointDataNV(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<CheckpointDataNV>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<CheckpointDataNV,Allocator> getCheckpointDataNV(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginDebugUtilsLabelEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pLabelInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void beginDebugUtilsLabelEXT( const DebugUtilsLabelEXT & labelInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result bindSparse( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindSparseInfo* pBindInfo, VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type bindSparse( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindSparseInfo> bindInfo, VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void endDebugUtilsLabelEXT(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void insertDebugUtilsLabelEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pLabelInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void insertDebugUtilsLabelEXT( const DebugUtilsLabelEXT & labelInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result presentKHR( const VULKAN_HPP_NAMESPACE::PresentInfoKHR* pPresentInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result presentKHR( const PresentInfoKHR & presentInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result setPerformanceConfigurationINTEL( VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL configuration, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type setPerformanceConfigurationINTEL( VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL configuration, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result submit( uint32_t submitCount, const VULKAN_HPP_NAMESPACE::SubmitInfo* pSubmits, VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type submit( ArrayProxy<const VULKAN_HPP_NAMESPACE::SubmitInfo> submits, VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result waitIdle(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type waitIdle(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkQueue() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queue;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queue != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_queue == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkQueue m_queue;
+ };
+ static_assert( sizeof( Queue ) == sizeof( VkQueue ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eQueue>
+ {
+ using type = Queue;
+ };
+
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ class Device;
+ template <typename Dispatch> class UniqueHandleTraits<AccelerationStructureNV, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueAccelerationStructureNV = UniqueHandle<AccelerationStructureNV, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<Buffer, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueBuffer = UniqueHandle<Buffer, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<BufferView, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueBufferView = UniqueHandle<BufferView, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<CommandBuffer, Dispatch> { public: using deleter = PoolFree<Device, CommandPool, Dispatch>; };
+ using UniqueCommandBuffer = UniqueHandle<CommandBuffer, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<CommandPool, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueCommandPool = UniqueHandle<CommandPool, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<DescriptorPool, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueDescriptorPool = UniqueHandle<DescriptorPool, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<DescriptorSet, Dispatch> { public: using deleter = PoolFree<Device, DescriptorPool, Dispatch>; };
+ using UniqueDescriptorSet = UniqueHandle<DescriptorSet, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<DescriptorSetLayout, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueDescriptorSetLayout = UniqueHandle<DescriptorSetLayout, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<DescriptorUpdateTemplate, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueDescriptorUpdateTemplate = UniqueHandle<DescriptorUpdateTemplate, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ using UniqueDescriptorUpdateTemplateKHR = UniqueHandle<DescriptorUpdateTemplate, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<DeviceMemory, Dispatch> { public: using deleter = ObjectFree<Device, Dispatch>; };
+ using UniqueDeviceMemory = UniqueHandle<DeviceMemory, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<Event, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueEvent = UniqueHandle<Event, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<Fence, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueFence = UniqueHandle<Fence, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<Framebuffer, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueFramebuffer = UniqueHandle<Framebuffer, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<Image, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueImage = UniqueHandle<Image, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<ImageView, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueImageView = UniqueHandle<ImageView, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<IndirectCommandsLayoutNVX, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueIndirectCommandsLayoutNVX = UniqueHandle<IndirectCommandsLayoutNVX, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<ObjectTableNVX, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueObjectTableNVX = UniqueHandle<ObjectTableNVX, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<Pipeline, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniquePipeline = UniqueHandle<Pipeline, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<PipelineCache, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniquePipelineCache = UniqueHandle<PipelineCache, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<PipelineLayout, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniquePipelineLayout = UniqueHandle<PipelineLayout, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<QueryPool, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueQueryPool = UniqueHandle<QueryPool, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<RenderPass, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueRenderPass = UniqueHandle<RenderPass, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<Sampler, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueSampler = UniqueHandle<Sampler, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<SamplerYcbcrConversion, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueSamplerYcbcrConversion = UniqueHandle<SamplerYcbcrConversion, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ using UniqueSamplerYcbcrConversionKHR = UniqueHandle<SamplerYcbcrConversion, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<Semaphore, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueSemaphore = UniqueHandle<Semaphore, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<ShaderModule, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueShaderModule = UniqueHandle<ShaderModule, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<SwapchainKHR, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueSwapchainKHR = UniqueHandle<SwapchainKHR, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<ValidationCacheEXT, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+ using UniqueValidationCacheEXT = UniqueHandle<ValidationCacheEXT, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+
+ class Device
+ {
+ public:
+ using CType = VkDevice;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDevice;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Device() VULKAN_HPP_NOEXCEPT
+ : m_device(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Device( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_device(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Device( VkDevice device ) VULKAN_HPP_NOEXCEPT
+ : m_device( device )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Device & operator=(VkDevice device) VULKAN_HPP_NOEXCEPT
+ {
+ m_device = device;
+ return *this;
+ }
+#endif
+
+ Device & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_device = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Device const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_device == rhs.m_device;
+ }
+
+ bool operator!=(Device const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_device != rhs.m_device;
+ }
+
+ bool operator<(Device const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_device < rhs.m_device;
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result acquireFullScreenExclusiveModeEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type acquireFullScreenExclusiveModeEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result acquireNextImage2KHR( const VULKAN_HPP_NAMESPACE::AcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ ResultValue<uint32_t> acquireNextImage2KHR( const AcquireNextImageInfoKHR & acquireInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result acquireNextImageKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, uint64_t timeout, VULKAN_HPP_NAMESPACE::Semaphore semaphore, VULKAN_HPP_NAMESPACE::Fence fence, uint32_t* pImageIndex, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ ResultValue<uint32_t> acquireNextImageKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, uint64_t timeout, VULKAN_HPP_NAMESPACE::Semaphore semaphore, VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result acquirePerformanceConfigurationINTEL( const VULKAN_HPP_NAMESPACE::PerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL* pConfiguration, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL>::type acquirePerformanceConfigurationINTEL( const PerformanceConfigurationAcquireInfoINTEL & acquireInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result acquireProfilingLockKHR( const VULKAN_HPP_NAMESPACE::AcquireProfilingLockInfoKHR* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type acquireProfilingLockKHR( const AcquireProfilingLockInfoKHR & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result allocateCommandBuffers( const VULKAN_HPP_NAMESPACE::CommandBufferAllocateInfo* pAllocateInfo, VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<CommandBuffer>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<CommandBuffer,Allocator>>::type allocateCommandBuffers( const CommandBufferAllocateInfo & allocateInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<CommandBuffer>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<CommandBuffer,Allocator>>::type allocateCommandBuffers( const CommandBufferAllocateInfo & allocateInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator = std::allocator<UniqueCommandBuffer>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<CommandBuffer,Dispatch>,Allocator>>::type allocateCommandBuffersUnique( const CommandBufferAllocateInfo & allocateInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<UniqueCommandBuffer>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<CommandBuffer,Dispatch>,Allocator>>::type allocateCommandBuffersUnique( const CommandBufferAllocateInfo & allocateInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result allocateDescriptorSets( const VULKAN_HPP_NAMESPACE::DescriptorSetAllocateInfo* pAllocateInfo, VULKAN_HPP_NAMESPACE::DescriptorSet* pDescriptorSets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<DescriptorSet>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DescriptorSet,Allocator>>::type allocateDescriptorSets( const DescriptorSetAllocateInfo & allocateInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<DescriptorSet>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DescriptorSet,Allocator>>::type allocateDescriptorSets( const DescriptorSetAllocateInfo & allocateInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator = std::allocator<UniqueDescriptorSet>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<DescriptorSet,Dispatch>,Allocator>>::type allocateDescriptorSetsUnique( const DescriptorSetAllocateInfo & allocateInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<UniqueDescriptorSet>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<DescriptorSet,Dispatch>,Allocator>>::type allocateDescriptorSetsUnique( const DescriptorSetAllocateInfo & allocateInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result allocateMemory( const VULKAN_HPP_NAMESPACE::MemoryAllocateInfo* pAllocateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DeviceMemory* pMemory, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DeviceMemory>::type allocateMemory( const MemoryAllocateInfo & allocateInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<DeviceMemory,Dispatch>>::type allocateMemoryUnique( const MemoryAllocateInfo & allocateInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result bindAccelerationStructureMemoryNV( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV* pBindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type bindAccelerationStructureMemoryNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV> bindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result bindBufferMemory( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type bindBufferMemory( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result bindBufferMemory2( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo* pBindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type bindBufferMemory2( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo> bindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result bindBufferMemory2KHR( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo* pBindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type bindBufferMemory2KHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo> bindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result bindImageMemory( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type bindImageMemory( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result bindImageMemory2( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo* pBindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type bindImageMemory2( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo> bindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result bindImageMemory2KHR( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo* pBindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type bindImageMemory2KHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo> bindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result compileDeferredNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t shader, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type compileDeferredNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t shader, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createAccelerationStructureNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoNV* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructure, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::AccelerationStructureNV>::type createAccelerationStructureNV( const AccelerationStructureCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<AccelerationStructureNV,Dispatch>>::type createAccelerationStructureNVUnique( const AccelerationStructureCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createBuffer( const VULKAN_HPP_NAMESPACE::BufferCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Buffer* pBuffer, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Buffer>::type createBuffer( const BufferCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Buffer,Dispatch>>::type createBufferUnique( const BufferCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createBufferView( const VULKAN_HPP_NAMESPACE::BufferViewCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::BufferView* pView, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::BufferView>::type createBufferView( const BufferViewCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<BufferView,Dispatch>>::type createBufferViewUnique( const BufferViewCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createCommandPool( const VULKAN_HPP_NAMESPACE::CommandPoolCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::CommandPool* pCommandPool, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::CommandPool>::type createCommandPool( const CommandPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<CommandPool,Dispatch>>::type createCommandPoolUnique( const CommandPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<Pipeline,Allocator>>::type createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<Pipeline,Allocator>>::type createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<Pipeline>::type createComputePipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type createComputePipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createDescriptorPool( const VULKAN_HPP_NAMESPACE::DescriptorPoolCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorPool* pDescriptorPool, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DescriptorPool>::type createDescriptorPool( const DescriptorPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<DescriptorPool,Dispatch>>::type createDescriptorPoolUnique( const DescriptorPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createDescriptorSetLayout( const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorSetLayout* pSetLayout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DescriptorSetLayout>::type createDescriptorSetLayout( const DescriptorSetLayoutCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<DescriptorSetLayout,Dispatch>>::type createDescriptorSetLayoutUnique( const DescriptorSetLayoutCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createDescriptorUpdateTemplate( const VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate* pDescriptorUpdateTemplate, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate>::type createDescriptorUpdateTemplate( const DescriptorUpdateTemplateCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<DescriptorUpdateTemplate,Dispatch>>::type createDescriptorUpdateTemplateUnique( const DescriptorUpdateTemplateCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createDescriptorUpdateTemplateKHR( const VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate* pDescriptorUpdateTemplate, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate>::type createDescriptorUpdateTemplateKHR( const DescriptorUpdateTemplateCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<DescriptorUpdateTemplate,Dispatch>>::type createDescriptorUpdateTemplateKHRUnique( const DescriptorUpdateTemplateCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createEvent( const VULKAN_HPP_NAMESPACE::EventCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Event* pEvent, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Event>::type createEvent( const EventCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Event,Dispatch>>::type createEventUnique( const EventCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createFence( const VULKAN_HPP_NAMESPACE::FenceCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Fence* pFence, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Fence>::type createFence( const FenceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Fence,Dispatch>>::type createFenceUnique( const FenceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createFramebuffer( const VULKAN_HPP_NAMESPACE::FramebufferCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Framebuffer* pFramebuffer, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Framebuffer>::type createFramebuffer( const FramebufferCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Framebuffer,Dispatch>>::type createFramebufferUnique( const FramebufferCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<Pipeline,Allocator>>::type createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<Pipeline,Allocator>>::type createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<Pipeline>::type createGraphicsPipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type createGraphicsPipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createImage( const VULKAN_HPP_NAMESPACE::ImageCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Image* pImage, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Image>::type createImage( const ImageCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Image,Dispatch>>::type createImageUnique( const ImageCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createImageView( const VULKAN_HPP_NAMESPACE::ImageViewCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::ImageView* pView, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageView>::type createImageView( const ImageViewCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<ImageView,Dispatch>>::type createImageViewUnique( const ImageViewCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createIndirectCommandsLayoutNVX( const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX* pIndirectCommandsLayout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX>::type createIndirectCommandsLayoutNVX( const IndirectCommandsLayoutCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<IndirectCommandsLayoutNVX,Dispatch>>::type createIndirectCommandsLayoutNVXUnique( const IndirectCommandsLayoutCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createObjectTableNVX( const VULKAN_HPP_NAMESPACE::ObjectTableCreateInfoNVX* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::ObjectTableNVX* pObjectTable, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::ObjectTableNVX>::type createObjectTableNVX( const ObjectTableCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<ObjectTableNVX,Dispatch>>::type createObjectTableNVXUnique( const ObjectTableCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createPipelineCache( const VULKAN_HPP_NAMESPACE::PipelineCacheCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::PipelineCache* pPipelineCache, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::PipelineCache>::type createPipelineCache( const PipelineCacheCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<PipelineCache,Dispatch>>::type createPipelineCacheUnique( const PipelineCacheCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createPipelineLayout( const VULKAN_HPP_NAMESPACE::PipelineLayoutCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::PipelineLayout* pPipelineLayout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::PipelineLayout>::type createPipelineLayout( const PipelineLayoutCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<PipelineLayout,Dispatch>>::type createPipelineLayoutUnique( const PipelineLayoutCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createQueryPool( const VULKAN_HPP_NAMESPACE::QueryPoolCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::QueryPool* pQueryPool, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::QueryPool>::type createQueryPool( const QueryPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<QueryPool,Dispatch>>::type createQueryPoolUnique( const QueryPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<Pipeline,Allocator>>::type createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<Pipeline,Allocator>>::type createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<Pipeline>::type createRayTracingPipelineNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type createRayTracingPipelineNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createRenderPass( const VULKAN_HPP_NAMESPACE::RenderPassCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::RenderPass* pRenderPass, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::RenderPass>::type createRenderPass( const RenderPassCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<RenderPass,Dispatch>>::type createRenderPassUnique( const RenderPassCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createRenderPass2( const VULKAN_HPP_NAMESPACE::RenderPassCreateInfo2* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::RenderPass* pRenderPass, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::RenderPass>::type createRenderPass2( const RenderPassCreateInfo2 & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<RenderPass,Dispatch>>::type createRenderPass2Unique( const RenderPassCreateInfo2 & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createRenderPass2KHR( const VULKAN_HPP_NAMESPACE::RenderPassCreateInfo2* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::RenderPass* pRenderPass, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::RenderPass>::type createRenderPass2KHR( const RenderPassCreateInfo2 & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<RenderPass,Dispatch>>::type createRenderPass2KHRUnique( const RenderPassCreateInfo2 & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createSampler( const VULKAN_HPP_NAMESPACE::SamplerCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Sampler* pSampler, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Sampler>::type createSampler( const SamplerCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Sampler,Dispatch>>::type createSamplerUnique( const SamplerCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createSamplerYcbcrConversion( const VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion* pYcbcrConversion, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion>::type createSamplerYcbcrConversion( const SamplerYcbcrConversionCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SamplerYcbcrConversion,Dispatch>>::type createSamplerYcbcrConversionUnique( const SamplerYcbcrConversionCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createSamplerYcbcrConversionKHR( const VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion* pYcbcrConversion, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion>::type createSamplerYcbcrConversionKHR( const SamplerYcbcrConversionCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SamplerYcbcrConversion,Dispatch>>::type createSamplerYcbcrConversionKHRUnique( const SamplerYcbcrConversionCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createSemaphore( const VULKAN_HPP_NAMESPACE::SemaphoreCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Semaphore* pSemaphore, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Semaphore>::type createSemaphore( const SemaphoreCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Semaphore,Dispatch>>::type createSemaphoreUnique( const SemaphoreCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createShaderModule( const VULKAN_HPP_NAMESPACE::ShaderModuleCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::ShaderModule* pShaderModule, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::ShaderModule>::type createShaderModule( const ShaderModuleCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<ShaderModule,Dispatch>>::type createShaderModuleUnique( const ShaderModuleCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createSharedSwapchainsKHR( uint32_t swapchainCount, const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SwapchainKHR* pSwapchains, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<SwapchainKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<SwapchainKHR,Allocator>>::type createSharedSwapchainsKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<SwapchainKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<SwapchainKHR,Allocator>>::type createSharedSwapchainsKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<SwapchainKHR>::type createSharedSwapchainKHR( const SwapchainCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator = std::allocator<UniqueSwapchainKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<SwapchainKHR,Dispatch>,Allocator>>::type createSharedSwapchainsKHRUnique( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<UniqueSwapchainKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<UniqueHandle<SwapchainKHR,Dispatch>,Allocator>>::type createSharedSwapchainsKHRUnique( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SwapchainKHR,Dispatch>>::type createSharedSwapchainKHRUnique( const SwapchainCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createSwapchainKHR( const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SwapchainKHR* pSwapchain, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SwapchainKHR>::type createSwapchainKHR( const SwapchainCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SwapchainKHR,Dispatch>>::type createSwapchainKHRUnique( const SwapchainCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createValidationCacheEXT( const VULKAN_HPP_NAMESPACE::ValidationCacheCreateInfoEXT* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::ValidationCacheEXT* pValidationCache, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::ValidationCacheEXT>::type createValidationCacheEXT( const ValidationCacheCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<ValidationCacheEXT,Dispatch>>::type createValidationCacheEXTUnique( const ValidationCacheCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result debugMarkerSetObjectNameEXT( const VULKAN_HPP_NAMESPACE::DebugMarkerObjectNameInfoEXT* pNameInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type debugMarkerSetObjectNameEXT( const DebugMarkerObjectNameInfoEXT & nameInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result debugMarkerSetObjectTagEXT( const VULKAN_HPP_NAMESPACE::DebugMarkerObjectTagInfoEXT* pTagInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type debugMarkerSetObjectTagEXT( const DebugMarkerObjectTagInfoEXT & tagInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Buffer buffer, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Buffer buffer, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyBufferView( VULKAN_HPP_NAMESPACE::BufferView bufferView, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyBufferView( VULKAN_HPP_NAMESPACE::BufferView bufferView, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::BufferView bufferView, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::BufferView bufferView, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::CommandPool commandPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::CommandPool commandPool, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDescriptorSetLayout( VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDescriptorSetLayout( VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDescriptorUpdateTemplate( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDescriptorUpdateTemplate( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDescriptorUpdateTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDescriptorUpdateTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyEvent( VULKAN_HPP_NAMESPACE::Event event, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyEvent( VULKAN_HPP_NAMESPACE::Event event, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Event event, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Event event, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyFence( VULKAN_HPP_NAMESPACE::Fence fence, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyFence( VULKAN_HPP_NAMESPACE::Fence fence, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Fence fence, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Fence fence, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyFramebuffer( VULKAN_HPP_NAMESPACE::Framebuffer framebuffer, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyFramebuffer( VULKAN_HPP_NAMESPACE::Framebuffer framebuffer, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Framebuffer framebuffer, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Framebuffer framebuffer, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyImage( VULKAN_HPP_NAMESPACE::Image image, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyImage( VULKAN_HPP_NAMESPACE::Image image, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Image image, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Image image, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyImageView( VULKAN_HPP_NAMESPACE::ImageView imageView, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyImageView( VULKAN_HPP_NAMESPACE::ImageView imageView, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::ImageView imageView, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::ImageView imageView, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyIndirectCommandsLayoutNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyIndirectCommandsLayoutNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyObjectTableNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyObjectTableNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyPipeline( VULKAN_HPP_NAMESPACE::Pipeline pipeline, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyPipeline( VULKAN_HPP_NAMESPACE::Pipeline pipeline, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Pipeline pipeline, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Pipeline pipeline, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyPipelineCache( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyPipelineCache( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyPipelineLayout( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyPipelineLayout( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyQueryPool( VULKAN_HPP_NAMESPACE::QueryPool queryPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyQueryPool( VULKAN_HPP_NAMESPACE::QueryPool queryPool, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::QueryPool queryPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::QueryPool queryPool, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyRenderPass( VULKAN_HPP_NAMESPACE::RenderPass renderPass, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyRenderPass( VULKAN_HPP_NAMESPACE::RenderPass renderPass, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::RenderPass renderPass, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::RenderPass renderPass, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySampler( VULKAN_HPP_NAMESPACE::Sampler sampler, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySampler( VULKAN_HPP_NAMESPACE::Sampler sampler, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Sampler sampler, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Sampler sampler, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySamplerYcbcrConversion( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySamplerYcbcrConversion( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySamplerYcbcrConversionKHR( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySamplerYcbcrConversionKHR( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySemaphore( VULKAN_HPP_NAMESPACE::Semaphore semaphore, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySemaphore( VULKAN_HPP_NAMESPACE::Semaphore semaphore, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Semaphore semaphore, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::Semaphore semaphore, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyShaderModule( VULKAN_HPP_NAMESPACE::ShaderModule shaderModule, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyShaderModule( VULKAN_HPP_NAMESPACE::ShaderModule shaderModule, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::ShaderModule shaderModule, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::ShaderModule shaderModule, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySwapchainKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySwapchainKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyValidationCacheEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyValidationCacheEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result waitIdle(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type waitIdle(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result displayPowerControlEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, const VULKAN_HPP_NAMESPACE::DisplayPowerInfoEXT* pDisplayPowerInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type displayPowerControlEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, const DisplayPowerInfoEXT & displayPowerInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result flushMappedMemoryRanges( uint32_t memoryRangeCount, const VULKAN_HPP_NAMESPACE::MappedMemoryRange* pMemoryRanges, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type flushMappedMemoryRanges( ArrayProxy<const VULKAN_HPP_NAMESPACE::MappedMemoryRange> memoryRanges, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void freeCommandBuffers( VULKAN_HPP_NAMESPACE::CommandPool commandPool, uint32_t commandBufferCount, const VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void freeCommandBuffers( VULKAN_HPP_NAMESPACE::CommandPool commandPool, ArrayProxy<const VULKAN_HPP_NAMESPACE::CommandBuffer> commandBuffers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void free( VULKAN_HPP_NAMESPACE::CommandPool commandPool, uint32_t commandBufferCount, const VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void free( VULKAN_HPP_NAMESPACE::CommandPool commandPool, ArrayProxy<const VULKAN_HPP_NAMESPACE::CommandBuffer> commandBuffers, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result freeDescriptorSets( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, uint32_t descriptorSetCount, const VULKAN_HPP_NAMESPACE::DescriptorSet* pDescriptorSets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type freeDescriptorSets( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, ArrayProxy<const VULKAN_HPP_NAMESPACE::DescriptorSet> descriptorSets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result free( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, uint32_t descriptorSetCount, const VULKAN_HPP_NAMESPACE::DescriptorSet* pDescriptorSets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type free( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, ArrayProxy<const VULKAN_HPP_NAMESPACE::DescriptorSet> descriptorSets, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void freeMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void freeMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void free( VULKAN_HPP_NAMESPACE::DeviceMemory memory, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void free( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, size_t dataSize, void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename T, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, ArrayProxy<T> data, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getAccelerationStructureMemoryRequirementsNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoNV* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2KHR* pMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2KHR getAccelerationStructureMemoryRequirementsNV( const AccelerationStructureMemoryRequirementsInfoNV & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getAccelerationStructureMemoryRequirementsNV( const AccelerationStructureMemoryRequirementsInfoNV & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getAndroidHardwareBufferPropertiesANDROID( const struct AHardwareBuffer* buffer, VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID>::type getAndroidHardwareBufferPropertiesANDROID( const struct AHardwareBuffer & buffer, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<StructureChain<X, Y, Z...>>::type getAndroidHardwareBufferPropertiesANDROID( const struct AHardwareBuffer & buffer, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ DeviceAddress getBufferAddress( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ DeviceAddress getBufferAddress( const BufferDeviceAddressInfo & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ DeviceAddress getBufferAddressEXT( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ DeviceAddress getBufferAddressEXT( const BufferDeviceAddressInfo & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ DeviceAddress getBufferAddressKHR( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ DeviceAddress getBufferAddressKHR( const BufferDeviceAddressInfo & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getBufferMemoryRequirements( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::MemoryRequirements* pMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::MemoryRequirements getBufferMemoryRequirements( VULKAN_HPP_NAMESPACE::Buffer buffer, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getBufferMemoryRequirements2( const VULKAN_HPP_NAMESPACE::BufferMemoryRequirementsInfo2* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2 getBufferMemoryRequirements2( const BufferMemoryRequirementsInfo2 & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getBufferMemoryRequirements2( const BufferMemoryRequirementsInfo2 & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getBufferMemoryRequirements2KHR( const VULKAN_HPP_NAMESPACE::BufferMemoryRequirementsInfo2* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2 getBufferMemoryRequirements2KHR( const BufferMemoryRequirementsInfo2 & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getBufferMemoryRequirements2KHR( const BufferMemoryRequirementsInfo2 & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint64_t getBufferOpaqueCaptureAddress( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint64_t getBufferOpaqueCaptureAddress( const BufferDeviceAddressInfo & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint64_t getBufferOpaqueCaptureAddressKHR( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint64_t getBufferOpaqueCaptureAddressKHR( const BufferDeviceAddressInfo & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getCalibratedTimestampsEXT( uint32_t timestampCount, const VULKAN_HPP_NAMESPACE::CalibratedTimestampInfoEXT* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<uint64_t>::type getCalibratedTimestampsEXT( ArrayProxy<const VULKAN_HPP_NAMESPACE::CalibratedTimestampInfoEXT> timestampInfos, ArrayProxy<uint64_t> timestamps, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getDescriptorSetLayoutSupport( const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo* pCreateInfo, VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport* pSupport, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport getDescriptorSetLayoutSupport( const DescriptorSetLayoutCreateInfo & createInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getDescriptorSetLayoutSupport( const DescriptorSetLayoutCreateInfo & createInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getDescriptorSetLayoutSupportKHR( const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo* pCreateInfo, VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport* pSupport, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport getDescriptorSetLayoutSupportKHR( const DescriptorSetLayoutCreateInfo & createInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getDescriptorSetLayoutSupportKHR( const DescriptorSetLayoutCreateInfo & createInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getGroupPeerMemoryFeatures( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags* pPeerMemoryFeatures, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags getGroupPeerMemoryFeatures( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getGroupPeerMemoryFeaturesKHR( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags* pPeerMemoryFeatures, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags getGroupPeerMemoryFeaturesKHR( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getGroupPresentCapabilitiesKHR( VULKAN_HPP_NAMESPACE::DeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DeviceGroupPresentCapabilitiesKHR>::type getGroupPresentCapabilitiesKHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getGroupSurfacePresentModes2EXT( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR* pModes, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR>::type getGroupSurfacePresentModes2EXT( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getGroupSurfacePresentModesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR* pModes, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR>::type getGroupSurfacePresentModesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getMemoryCommitment( VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize* pCommittedMemoryInBytes, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::DeviceSize getMemoryCommitment( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint64_t getMemoryOpaqueCaptureAddress( const VULKAN_HPP_NAMESPACE::DeviceMemoryOpaqueCaptureAddressInfo* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint64_t getMemoryOpaqueCaptureAddress( const DeviceMemoryOpaqueCaptureAddressInfo & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint64_t getMemoryOpaqueCaptureAddressKHR( const VULKAN_HPP_NAMESPACE::DeviceMemoryOpaqueCaptureAddressInfo* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint64_t getMemoryOpaqueCaptureAddressKHR( const DeviceMemoryOpaqueCaptureAddressInfo & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ PFN_vkVoidFunction getProcAddr( const char* pName, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ PFN_vkVoidFunction getProcAddr( const std::string & name, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getQueue( uint32_t queueFamilyIndex, uint32_t queueIndex, VULKAN_HPP_NAMESPACE::Queue* pQueue, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::Queue getQueue( uint32_t queueFamilyIndex, uint32_t queueIndex, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getQueue2( const VULKAN_HPP_NAMESPACE::DeviceQueueInfo2* pQueueInfo, VULKAN_HPP_NAMESPACE::Queue* pQueue, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::Queue getQueue2( const DeviceQueueInfo2 & queueInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getEventStatus( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getEventStatus( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getFenceFdKHR( const VULKAN_HPP_NAMESPACE::FenceGetFdInfoKHR* pGetFdInfo, int* pFd, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<int>::type getFenceFdKHR( const FenceGetFdInfoKHR & getFdInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getFenceStatus( VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getFenceStatus( VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getFenceWin32HandleKHR( const VULKAN_HPP_NAMESPACE::FenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<HANDLE>::type getFenceWin32HandleKHR( const FenceGetWin32HandleInfoKHR & getWin32HandleInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getImageDrmFormatModifierPropertiesEXT( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT>::type getImageDrmFormatModifierPropertiesEXT( VULKAN_HPP_NAMESPACE::Image image, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getImageMemoryRequirements( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::MemoryRequirements* pMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::MemoryRequirements getImageMemoryRequirements( VULKAN_HPP_NAMESPACE::Image image, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getImageMemoryRequirements2( const VULKAN_HPP_NAMESPACE::ImageMemoryRequirementsInfo2* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2 getImageMemoryRequirements2( const ImageMemoryRequirementsInfo2 & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getImageMemoryRequirements2( const ImageMemoryRequirementsInfo2 & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getImageMemoryRequirements2KHR( const VULKAN_HPP_NAMESPACE::ImageMemoryRequirementsInfo2* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2 getImageMemoryRequirements2KHR( const ImageMemoryRequirementsInfo2 & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getImageMemoryRequirements2KHR( const ImageMemoryRequirementsInfo2 & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getImageSparseMemoryRequirements( VULKAN_HPP_NAMESPACE::Image image, uint32_t* pSparseMemoryRequirementCount, VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements* pSparseMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<SparseImageMemoryRequirements>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageMemoryRequirements,Allocator> getImageSparseMemoryRequirements( VULKAN_HPP_NAMESPACE::Image image, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<SparseImageMemoryRequirements>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageMemoryRequirements,Allocator> getImageSparseMemoryRequirements( VULKAN_HPP_NAMESPACE::Image image, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getImageSparseMemoryRequirements2( const VULKAN_HPP_NAMESPACE::ImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements2* pSparseMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<SparseImageMemoryRequirements2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageMemoryRequirements2,Allocator> getImageSparseMemoryRequirements2( const ImageSparseMemoryRequirementsInfo2 & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<SparseImageMemoryRequirements2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageMemoryRequirements2,Allocator> getImageSparseMemoryRequirements2( const ImageSparseMemoryRequirementsInfo2 & info, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getImageSparseMemoryRequirements2KHR( const VULKAN_HPP_NAMESPACE::ImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements2* pSparseMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<SparseImageMemoryRequirements2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageMemoryRequirements2,Allocator> getImageSparseMemoryRequirements2KHR( const ImageSparseMemoryRequirementsInfo2 & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<SparseImageMemoryRequirements2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageMemoryRequirements2,Allocator> getImageSparseMemoryRequirements2KHR( const ImageSparseMemoryRequirementsInfo2 & info, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getImageSubresourceLayout( VULKAN_HPP_NAMESPACE::Image image, const VULKAN_HPP_NAMESPACE::ImageSubresource* pSubresource, VULKAN_HPP_NAMESPACE::SubresourceLayout* pLayout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::SubresourceLayout getImageSubresourceLayout( VULKAN_HPP_NAMESPACE::Image image, const ImageSubresource & subresource, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint32_t getImageViewHandleNVX( const VULKAN_HPP_NAMESPACE::ImageViewHandleInfoNVX* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint32_t getImageViewHandleNVX( const ImageViewHandleInfoNVX & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getMemoryAndroidHardwareBufferANDROID( const VULKAN_HPP_NAMESPACE::MemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<struct AHardwareBuffer*>::type getMemoryAndroidHardwareBufferANDROID( const MemoryGetAndroidHardwareBufferInfoANDROID & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getMemoryFdKHR( const VULKAN_HPP_NAMESPACE::MemoryGetFdInfoKHR* pGetFdInfo, int* pFd, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<int>::type getMemoryFdKHR( const MemoryGetFdInfoKHR & getFdInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getMemoryFdPropertiesKHR( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, int fd, VULKAN_HPP_NAMESPACE::MemoryFdPropertiesKHR* pMemoryFdProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::MemoryFdPropertiesKHR>::type getMemoryFdPropertiesKHR( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, int fd, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getMemoryHostPointerPropertiesEXT( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VULKAN_HPP_NAMESPACE::MemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::MemoryHostPointerPropertiesEXT>::type getMemoryHostPointerPropertiesEXT( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getMemoryWin32HandleKHR( const VULKAN_HPP_NAMESPACE::MemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<HANDLE>::type getMemoryWin32HandleKHR( const MemoryGetWin32HandleInfoKHR & getWin32HandleInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getMemoryWin32HandleNV( VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<HANDLE>::type getMemoryWin32HandleNV( VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleType, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getMemoryWin32HandlePropertiesKHR( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VULKAN_HPP_NAMESPACE::MemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::MemoryWin32HandlePropertiesKHR>::type getMemoryWin32HandlePropertiesKHR( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getPastPresentationTimingGOOGLE( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VULKAN_HPP_NAMESPACE::PastPresentationTimingGOOGLE* pPresentationTimings, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PastPresentationTimingGOOGLE>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PastPresentationTimingGOOGLE,Allocator>>::type getPastPresentationTimingGOOGLE( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PastPresentationTimingGOOGLE>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PastPresentationTimingGOOGLE,Allocator>>::type getPastPresentationTimingGOOGLE( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getPerformanceParameterINTEL( VULKAN_HPP_NAMESPACE::PerformanceParameterTypeINTEL parameter, VULKAN_HPP_NAMESPACE::PerformanceValueINTEL* pValue, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::PerformanceValueINTEL>::type getPerformanceParameterINTEL( VULKAN_HPP_NAMESPACE::PerformanceParameterTypeINTEL parameter, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getPipelineCacheData( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, size_t* pDataSize, void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<uint8_t>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<uint8_t,Allocator>>::type getPipelineCacheData( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<uint8_t>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<uint8_t,Allocator>>::type getPipelineCacheData( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getPipelineExecutableInternalRepresentationsKHR( const VULKAN_HPP_NAMESPACE::PipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VULKAN_HPP_NAMESPACE::PipelineExecutableInternalRepresentationKHR* pInternalRepresentations, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PipelineExecutableInternalRepresentationKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PipelineExecutableInternalRepresentationKHR,Allocator>>::type getPipelineExecutableInternalRepresentationsKHR( const PipelineExecutableInfoKHR & executableInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PipelineExecutableInternalRepresentationKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PipelineExecutableInternalRepresentationKHR,Allocator>>::type getPipelineExecutableInternalRepresentationsKHR( const PipelineExecutableInfoKHR & executableInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getPipelineExecutablePropertiesKHR( const VULKAN_HPP_NAMESPACE::PipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VULKAN_HPP_NAMESPACE::PipelineExecutablePropertiesKHR* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PipelineExecutablePropertiesKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PipelineExecutablePropertiesKHR,Allocator>>::type getPipelineExecutablePropertiesKHR( const PipelineInfoKHR & pipelineInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PipelineExecutablePropertiesKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PipelineExecutablePropertiesKHR,Allocator>>::type getPipelineExecutablePropertiesKHR( const PipelineInfoKHR & pipelineInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getPipelineExecutableStatisticsKHR( const VULKAN_HPP_NAMESPACE::PipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticKHR* pStatistics, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PipelineExecutableStatisticKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PipelineExecutableStatisticKHR,Allocator>>::type getPipelineExecutableStatisticsKHR( const PipelineExecutableInfoKHR & executableInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PipelineExecutableStatisticKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PipelineExecutableStatisticKHR,Allocator>>::type getPipelineExecutableStatisticsKHR( const PipelineExecutableInfoKHR & executableInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getQueryPoolResults( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VULKAN_HPP_NAMESPACE::DeviceSize stride, VULKAN_HPP_NAMESPACE::QueryResultFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename T, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getQueryPoolResults( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, ArrayProxy<T> data, VULKAN_HPP_NAMESPACE::DeviceSize stride, VULKAN_HPP_NAMESPACE::QueryResultFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getRayTracingShaderGroupHandlesNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename T, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type getRayTracingShaderGroupHandlesNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, ArrayProxy<T> data, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getRefreshCycleDurationGOOGLE( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, VULKAN_HPP_NAMESPACE::RefreshCycleDurationGOOGLE* pDisplayTimingProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::RefreshCycleDurationGOOGLE>::type getRefreshCycleDurationGOOGLE( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getRenderAreaGranularity( VULKAN_HPP_NAMESPACE::RenderPass renderPass, VULKAN_HPP_NAMESPACE::Extent2D* pGranularity, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::Extent2D getRenderAreaGranularity( VULKAN_HPP_NAMESPACE::RenderPass renderPass, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSemaphoreCounterValue( VULKAN_HPP_NAMESPACE::Semaphore semaphore, uint64_t* pValue, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<uint64_t>::type getSemaphoreCounterValue( VULKAN_HPP_NAMESPACE::Semaphore semaphore, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSemaphoreCounterValueKHR( VULKAN_HPP_NAMESPACE::Semaphore semaphore, uint64_t* pValue, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<uint64_t>::type getSemaphoreCounterValueKHR( VULKAN_HPP_NAMESPACE::Semaphore semaphore, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSemaphoreFdKHR( const VULKAN_HPP_NAMESPACE::SemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<int>::type getSemaphoreFdKHR( const SemaphoreGetFdInfoKHR & getFdInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSemaphoreWin32HandleKHR( const VULKAN_HPP_NAMESPACE::SemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<HANDLE>::type getSemaphoreWin32HandleKHR( const SemaphoreGetWin32HandleInfoKHR & getWin32HandleInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getShaderInfoAMD( VULKAN_HPP_NAMESPACE::Pipeline pipeline, VULKAN_HPP_NAMESPACE::ShaderStageFlagBits shaderStage, VULKAN_HPP_NAMESPACE::ShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<uint8_t>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<uint8_t,Allocator>>::type getShaderInfoAMD( VULKAN_HPP_NAMESPACE::Pipeline pipeline, VULKAN_HPP_NAMESPACE::ShaderStageFlagBits shaderStage, VULKAN_HPP_NAMESPACE::ShaderInfoTypeAMD infoType, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<uint8_t>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<uint8_t,Allocator>>::type getShaderInfoAMD( VULKAN_HPP_NAMESPACE::Pipeline pipeline, VULKAN_HPP_NAMESPACE::ShaderStageFlagBits shaderStage, VULKAN_HPP_NAMESPACE::ShaderInfoTypeAMD infoType, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSwapchainCounterEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, VULKAN_HPP_NAMESPACE::SurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<uint64_t>::type getSwapchainCounterEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, VULKAN_HPP_NAMESPACE::SurfaceCounterFlagBitsEXT counter, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSwapchainImagesKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VULKAN_HPP_NAMESPACE::Image* pSwapchainImages, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<Image>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<Image,Allocator>>::type getSwapchainImagesKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<Image>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<Image,Allocator>>::type getSwapchainImagesKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSwapchainStatusKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSwapchainStatusKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getValidationCacheDataEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, size_t* pDataSize, void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<uint8_t>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<uint8_t,Allocator>>::type getValidationCacheDataEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<uint8_t>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<uint8_t,Allocator>>::type getValidationCacheDataEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result importFenceFdKHR( const VULKAN_HPP_NAMESPACE::ImportFenceFdInfoKHR* pImportFenceFdInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type importFenceFdKHR( const ImportFenceFdInfoKHR & importFenceFdInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result importFenceWin32HandleKHR( const VULKAN_HPP_NAMESPACE::ImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type importFenceWin32HandleKHR( const ImportFenceWin32HandleInfoKHR & importFenceWin32HandleInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result importSemaphoreFdKHR( const VULKAN_HPP_NAMESPACE::ImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type importSemaphoreFdKHR( const ImportSemaphoreFdInfoKHR & importSemaphoreFdInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result importSemaphoreWin32HandleKHR( const VULKAN_HPP_NAMESPACE::ImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type importSemaphoreWin32HandleKHR( const ImportSemaphoreWin32HandleInfoKHR & importSemaphoreWin32HandleInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result initializePerformanceApiINTEL( const VULKAN_HPP_NAMESPACE::InitializePerformanceApiInfoINTEL* pInitializeInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type initializePerformanceApiINTEL( const InitializePerformanceApiInfoINTEL & initializeInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result invalidateMappedMemoryRanges( uint32_t memoryRangeCount, const VULKAN_HPP_NAMESPACE::MappedMemoryRange* pMemoryRanges, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type invalidateMappedMemoryRanges( ArrayProxy<const VULKAN_HPP_NAMESPACE::MappedMemoryRange> memoryRanges, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result mapMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::DeviceSize size, VULKAN_HPP_NAMESPACE::MemoryMapFlags flags, void** ppData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void*>::type mapMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::DeviceSize size, VULKAN_HPP_NAMESPACE::MemoryMapFlags flags = MemoryMapFlags(), Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result mergePipelineCaches( VULKAN_HPP_NAMESPACE::PipelineCache dstCache, uint32_t srcCacheCount, const VULKAN_HPP_NAMESPACE::PipelineCache* pSrcCaches, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type mergePipelineCaches( VULKAN_HPP_NAMESPACE::PipelineCache dstCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::PipelineCache> srcCaches, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result mergeValidationCachesEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT dstCache, uint32_t srcCacheCount, const VULKAN_HPP_NAMESPACE::ValidationCacheEXT* pSrcCaches, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type mergeValidationCachesEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT dstCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ValidationCacheEXT> srcCaches, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result registerEventEXT( const VULKAN_HPP_NAMESPACE::DeviceEventInfoEXT* pDeviceEventInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Fence* pFence, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Fence>::type registerEventEXT( const DeviceEventInfoEXT & deviceEventInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Fence,Dispatch>>::type registerEventEXTUnique( const DeviceEventInfoEXT & deviceEventInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result registerDisplayEventEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, const VULKAN_HPP_NAMESPACE::DisplayEventInfoEXT* pDisplayEventInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Fence* pFence, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Fence>::type registerDisplayEventEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, const DisplayEventInfoEXT & displayEventInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Fence,Dispatch>>::type registerDisplayEventEXTUnique( VULKAN_HPP_NAMESPACE::DisplayKHR display, const DisplayEventInfoEXT & displayEventInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result registerObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, uint32_t objectCount, const VULKAN_HPP_NAMESPACE::ObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type registerObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, ArrayProxy<const VULKAN_HPP_NAMESPACE::ObjectTableEntryNVX* const> pObjectTableEntries, ArrayProxy<const uint32_t> objectIndices, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result releaseFullScreenExclusiveModeEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type releaseFullScreenExclusiveModeEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result releasePerformanceConfigurationINTEL( VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL configuration, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type releasePerformanceConfigurationINTEL( VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL configuration, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void releaseProfilingLockKHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result resetCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolResetFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type resetCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolResetFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result resetDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, VULKAN_HPP_NAMESPACE::DescriptorPoolResetFlags flags = DescriptorPoolResetFlags(), Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type resetDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, VULKAN_HPP_NAMESPACE::DescriptorPoolResetFlags flags = DescriptorPoolResetFlags(), Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result resetEvent( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type resetEvent( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result resetFences( uint32_t fenceCount, const VULKAN_HPP_NAMESPACE::Fence* pFences, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type resetFences( ArrayProxy<const VULKAN_HPP_NAMESPACE::Fence> fences, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void resetQueryPool( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void resetQueryPoolEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result setDebugUtilsObjectNameEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsObjectNameInfoEXT* pNameInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type setDebugUtilsObjectNameEXT( const DebugUtilsObjectNameInfoEXT & nameInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result setDebugUtilsObjectTagEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsObjectTagInfoEXT* pTagInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type setDebugUtilsObjectTagEXT( const DebugUtilsObjectTagInfoEXT & tagInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result setEvent( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type setEvent( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setHdrMetadataEXT( uint32_t swapchainCount, const VULKAN_HPP_NAMESPACE::SwapchainKHR* pSwapchains, const VULKAN_HPP_NAMESPACE::HdrMetadataEXT* pMetadata, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setHdrMetadataEXT( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainKHR> swapchains, ArrayProxy<const VULKAN_HPP_NAMESPACE::HdrMetadataEXT> metadata, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void setLocalDimmingAMD( VULKAN_HPP_NAMESPACE::SwapchainKHR swapChain, VULKAN_HPP_NAMESPACE::Bool32 localDimmingEnable, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result signalSemaphore( const VULKAN_HPP_NAMESPACE::SemaphoreSignalInfo* pSignalInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type signalSemaphore( const SemaphoreSignalInfo & signalInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result signalSemaphoreKHR( const VULKAN_HPP_NAMESPACE::SemaphoreSignalInfo* pSignalInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type signalSemaphoreKHR( const SemaphoreSignalInfo & signalInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void trimCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolTrimFlags flags = CommandPoolTrimFlags(), Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void trimCommandPoolKHR( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolTrimFlags flags = CommandPoolTrimFlags(), Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void uninitializePerformanceApiINTEL(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void unmapMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result unregisterObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, uint32_t objectCount, const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type unregisterObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, ArrayProxy<const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX> objectEntryTypes, ArrayProxy<const uint32_t> objectIndices, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void updateDescriptorSetWithTemplate( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void updateDescriptorSetWithTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void updateDescriptorSets( uint32_t descriptorWriteCount, const VULKAN_HPP_NAMESPACE::WriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VULKAN_HPP_NAMESPACE::CopyDescriptorSet* pDescriptorCopies, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void updateDescriptorSets( ArrayProxy<const VULKAN_HPP_NAMESPACE::WriteDescriptorSet> descriptorWrites, ArrayProxy<const VULKAN_HPP_NAMESPACE::CopyDescriptorSet> descriptorCopies, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result waitForFences( uint32_t fenceCount, const VULKAN_HPP_NAMESPACE::Fence* pFences, VULKAN_HPP_NAMESPACE::Bool32 waitAll, uint64_t timeout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result waitForFences( ArrayProxy<const VULKAN_HPP_NAMESPACE::Fence> fences, VULKAN_HPP_NAMESPACE::Bool32 waitAll, uint64_t timeout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result waitSemaphores( const VULKAN_HPP_NAMESPACE::SemaphoreWaitInfo* pWaitInfo, uint64_t timeout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result waitSemaphores( const SemaphoreWaitInfo & waitInfo, uint64_t timeout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result waitSemaphoresKHR( const VULKAN_HPP_NAMESPACE::SemaphoreWaitInfo* pWaitInfo, uint64_t timeout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result waitSemaphoresKHR( const SemaphoreWaitInfo & waitInfo, uint64_t timeout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDevice() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_device;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_device != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_device == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkDevice m_device;
+ };
+ static_assert( sizeof( Device ) == sizeof( VkDevice ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eDevice>
+ {
+ using type = Device;
+ };
+
+ class DisplayModeKHR
+ {
+ public:
+ using CType = VkDisplayModeKHR;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDisplayModeKHR;
+
+ public:
+ VULKAN_HPP_CONSTEXPR DisplayModeKHR() VULKAN_HPP_NOEXCEPT
+ : m_displayModeKHR(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR DisplayModeKHR( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_displayModeKHR(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT DisplayModeKHR( VkDisplayModeKHR displayModeKHR ) VULKAN_HPP_NOEXCEPT
+ : m_displayModeKHR( displayModeKHR )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ DisplayModeKHR & operator=(VkDisplayModeKHR displayModeKHR) VULKAN_HPP_NOEXCEPT
+ {
+ m_displayModeKHR = displayModeKHR;
+ return *this;
+ }
+#endif
+
+ DisplayModeKHR & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_displayModeKHR = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( DisplayModeKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayModeKHR == rhs.m_displayModeKHR;
+ }
+
+ bool operator!=(DisplayModeKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayModeKHR != rhs.m_displayModeKHR;
+ }
+
+ bool operator<(DisplayModeKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayModeKHR < rhs.m_displayModeKHR;
+ }
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDisplayModeKHR() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayModeKHR;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayModeKHR != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_displayModeKHR == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkDisplayModeKHR m_displayModeKHR;
+ };
+ static_assert( sizeof( DisplayModeKHR ) == sizeof( VkDisplayModeKHR ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eDisplayModeKHR>
+ {
+ using type = DisplayModeKHR;
+ };
+
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template <typename Dispatch> class UniqueHandleTraits<Device, Dispatch> { public: using deleter = ObjectDestroy<NoParent, Dispatch>; };
+ using UniqueDevice = UniqueHandle<Device, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+
+ class PhysicalDevice
+ {
+ public:
+ using CType = VkPhysicalDevice;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::ePhysicalDevice;
+
+ public:
+ VULKAN_HPP_CONSTEXPR PhysicalDevice() VULKAN_HPP_NOEXCEPT
+ : m_physicalDevice(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR PhysicalDevice( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_physicalDevice(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT PhysicalDevice( VkPhysicalDevice physicalDevice ) VULKAN_HPP_NOEXCEPT
+ : m_physicalDevice( physicalDevice )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ PhysicalDevice & operator=(VkPhysicalDevice physicalDevice) VULKAN_HPP_NOEXCEPT
+ {
+ m_physicalDevice = physicalDevice;
+ return *this;
+ }
+#endif
+
+ PhysicalDevice & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_physicalDevice = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( PhysicalDevice const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_physicalDevice == rhs.m_physicalDevice;
+ }
+
+ bool operator!=(PhysicalDevice const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_physicalDevice != rhs.m_physicalDevice;
+ }
+
+ bool operator<(PhysicalDevice const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_physicalDevice < rhs.m_physicalDevice;
+ }
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result acquireXlibDisplayEXT( Display* dpy, VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<Display>::type acquireXlibDisplayEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XLIB_XRANDR_EXT*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createDevice( const VULKAN_HPP_NAMESPACE::DeviceCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Device* pDevice, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Device>::type createDevice( const DeviceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Device,Dispatch>>::type createDeviceUnique( const DeviceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createDisplayModeKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, const VULKAN_HPP_NAMESPACE::DisplayModeCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DisplayModeKHR* pMode, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DisplayModeKHR>::type createDisplayModeKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, const DisplayModeCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result enumerateDeviceExtensionProperties( const char* pLayerName, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::ExtensionProperties* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<ExtensionProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<ExtensionProperties,Allocator>>::type enumerateDeviceExtensionProperties( Optional<const std::string> layerName = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<ExtensionProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<ExtensionProperties,Allocator>>::type enumerateDeviceExtensionProperties( Optional<const std::string> layerName, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result enumerateDeviceLayerProperties( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::LayerProperties* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<LayerProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<LayerProperties,Allocator>>::type enumerateDeviceLayerProperties(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<LayerProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<LayerProperties,Allocator>>::type enumerateDeviceLayerProperties(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result enumerateQueueFamilyPerformanceQueryCountersKHR( uint32_t queueFamilyIndex, uint32_t* pCounterCount, VULKAN_HPP_NAMESPACE::PerformanceCounterKHR* pCounters, VULKAN_HPP_NAMESPACE::PerformanceCounterDescriptionKHR* pCounterDescriptions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PerformanceCounterDescriptionKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PerformanceCounterDescriptionKHR,Allocator>>::type enumerateQueueFamilyPerformanceQueryCountersKHR( uint32_t queueFamilyIndex, ArrayProxy<VULKAN_HPP_NAMESPACE::PerformanceCounterKHR> counters, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PerformanceCounterDescriptionKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PerformanceCounterDescriptionKHR,Allocator>>::type enumerateQueueFamilyPerformanceQueryCountersKHR( uint32_t queueFamilyIndex, ArrayProxy<VULKAN_HPP_NAMESPACE::PerformanceCounterKHR> counters, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getDisplayModeProperties2KHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayModeProperties2KHR* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<DisplayModeProperties2KHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayModeProperties2KHR,Allocator>>::type getDisplayModeProperties2KHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<DisplayModeProperties2KHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayModeProperties2KHR,Allocator>>::type getDisplayModeProperties2KHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getDisplayModePropertiesKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayModePropertiesKHR* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<DisplayModePropertiesKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayModePropertiesKHR,Allocator>>::type getDisplayModePropertiesKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<DisplayModePropertiesKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayModePropertiesKHR,Allocator>>::type getDisplayModePropertiesKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getDisplayPlaneCapabilities2KHR( const VULKAN_HPP_NAMESPACE::DisplayPlaneInfo2KHR* pDisplayPlaneInfo, VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilities2KHR* pCapabilities, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilities2KHR>::type getDisplayPlaneCapabilities2KHR( const DisplayPlaneInfo2KHR & displayPlaneInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getDisplayPlaneCapabilitiesKHR( VULKAN_HPP_NAMESPACE::DisplayModeKHR mode, uint32_t planeIndex, VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilitiesKHR* pCapabilities, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilitiesKHR>::type getDisplayPlaneCapabilitiesKHR( VULKAN_HPP_NAMESPACE::DisplayModeKHR mode, uint32_t planeIndex, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getDisplayPlaneSupportedDisplaysKHR( uint32_t planeIndex, uint32_t* pDisplayCount, VULKAN_HPP_NAMESPACE::DisplayKHR* pDisplays, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<DisplayKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayKHR,Allocator>>::type getDisplayPlaneSupportedDisplaysKHR( uint32_t planeIndex, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<DisplayKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayKHR,Allocator>>::type getDisplayPlaneSupportedDisplaysKHR( uint32_t planeIndex, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getCalibrateableTimeDomainsEXT( uint32_t* pTimeDomainCount, VULKAN_HPP_NAMESPACE::TimeDomainEXT* pTimeDomains, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<TimeDomainEXT>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<TimeDomainEXT,Allocator>>::type getCalibrateableTimeDomainsEXT(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<TimeDomainEXT>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<TimeDomainEXT,Allocator>>::type getCalibrateableTimeDomainsEXT(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getCooperativeMatrixPropertiesNV( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::CooperativeMatrixPropertiesNV* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<CooperativeMatrixPropertiesNV>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<CooperativeMatrixPropertiesNV,Allocator>>::type getCooperativeMatrixPropertiesNV(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<CooperativeMatrixPropertiesNV>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<CooperativeMatrixPropertiesNV,Allocator>>::type getCooperativeMatrixPropertiesNV(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getDisplayPlaneProperties2KHR( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayPlaneProperties2KHR* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<DisplayPlaneProperties2KHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayPlaneProperties2KHR,Allocator>>::type getDisplayPlaneProperties2KHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<DisplayPlaneProperties2KHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayPlaneProperties2KHR,Allocator>>::type getDisplayPlaneProperties2KHR(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getDisplayPlanePropertiesKHR( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayPlanePropertiesKHR* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<DisplayPlanePropertiesKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayPlanePropertiesKHR,Allocator>>::type getDisplayPlanePropertiesKHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<DisplayPlanePropertiesKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayPlanePropertiesKHR,Allocator>>::type getDisplayPlanePropertiesKHR(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getDisplayProperties2KHR( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayProperties2KHR* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<DisplayProperties2KHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayProperties2KHR,Allocator>>::type getDisplayProperties2KHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<DisplayProperties2KHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayProperties2KHR,Allocator>>::type getDisplayProperties2KHR(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getDisplayPropertiesKHR( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayPropertiesKHR* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<DisplayPropertiesKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayPropertiesKHR,Allocator>>::type getDisplayPropertiesKHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<DisplayPropertiesKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<DisplayPropertiesKHR,Allocator>>::type getDisplayPropertiesKHR(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getExternalBufferProperties( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VULKAN_HPP_NAMESPACE::ExternalBufferProperties* pExternalBufferProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::ExternalBufferProperties getExternalBufferProperties( const PhysicalDeviceExternalBufferInfo & externalBufferInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getExternalBufferPropertiesKHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VULKAN_HPP_NAMESPACE::ExternalBufferProperties* pExternalBufferProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::ExternalBufferProperties getExternalBufferPropertiesKHR( const PhysicalDeviceExternalBufferInfo & externalBufferInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getExternalFenceProperties( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VULKAN_HPP_NAMESPACE::ExternalFenceProperties* pExternalFenceProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::ExternalFenceProperties getExternalFenceProperties( const PhysicalDeviceExternalFenceInfo & externalFenceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getExternalFencePropertiesKHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VULKAN_HPP_NAMESPACE::ExternalFenceProperties* pExternalFenceProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::ExternalFenceProperties getExternalFencePropertiesKHR( const PhysicalDeviceExternalFenceInfo & externalFenceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getExternalImageFormatPropertiesNV( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::ImageTiling tiling, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageCreateFlags flags, VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV externalHandleType, VULKAN_HPP_NAMESPACE::ExternalImageFormatPropertiesNV* pExternalImageFormatProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::ExternalImageFormatPropertiesNV>::type getExternalImageFormatPropertiesNV( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::ImageTiling tiling, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageCreateFlags flags, VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV externalHandleType, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getExternalSemaphoreProperties( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties* pExternalSemaphoreProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties getExternalSemaphoreProperties( const PhysicalDeviceExternalSemaphoreInfo & externalSemaphoreInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getExternalSemaphorePropertiesKHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties* pExternalSemaphoreProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties getExternalSemaphorePropertiesKHR( const PhysicalDeviceExternalSemaphoreInfo & externalSemaphoreInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getFeatures( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures* pFeatures, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures getFeatures(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getFeatures2( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2* pFeatures, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 getFeatures2(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getFeatures2(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getFeatures2KHR( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2* pFeatures, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 getFeatures2KHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getFeatures2KHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::FormatProperties* pFormatProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::FormatProperties getFormatProperties( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getFormatProperties2( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::FormatProperties2* pFormatProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::FormatProperties2 getFormatProperties2( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getFormatProperties2( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getFormatProperties2KHR( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::FormatProperties2* pFormatProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::FormatProperties2 getFormatProperties2KHR( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getFormatProperties2KHR( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getGeneratedCommandsPropertiesNVX( VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsFeaturesNVX* pFeatures, VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX* pLimits, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX getGeneratedCommandsPropertiesNVX( DeviceGeneratedCommandsFeaturesNVX & features, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::ImageTiling tiling, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageCreateFlags flags, VULKAN_HPP_NAMESPACE::ImageFormatProperties* pImageFormatProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageFormatProperties>::type getImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::ImageTiling tiling, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageCreateFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getImageFormatProperties2( const VULKAN_HPP_NAMESPACE::PhysicalDeviceImageFormatInfo2* pImageFormatInfo, VULKAN_HPP_NAMESPACE::ImageFormatProperties2* pImageFormatProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageFormatProperties2>::type getImageFormatProperties2( const PhysicalDeviceImageFormatInfo2 & imageFormatInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<StructureChain<X, Y, Z...>>::type getImageFormatProperties2( const PhysicalDeviceImageFormatInfo2 & imageFormatInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getImageFormatProperties2KHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceImageFormatInfo2* pImageFormatInfo, VULKAN_HPP_NAMESPACE::ImageFormatProperties2* pImageFormatProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageFormatProperties2>::type getImageFormatProperties2KHR( const PhysicalDeviceImageFormatInfo2 & imageFormatInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<StructureChain<X, Y, Z...>>::type getImageFormatProperties2KHR( const PhysicalDeviceImageFormatInfo2 & imageFormatInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getMemoryProperties( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties* pMemoryProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties getMemoryProperties(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getMemoryProperties2( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2* pMemoryProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 getMemoryProperties2(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getMemoryProperties2(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getMemoryProperties2KHR( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2* pMemoryProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 getMemoryProperties2KHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getMemoryProperties2KHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getMultisamplePropertiesEXT( VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples, VULKAN_HPP_NAMESPACE::MultisamplePropertiesEXT* pMultisampleProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::MultisamplePropertiesEXT getMultisamplePropertiesEXT( VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getPresentRectanglesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, uint32_t* pRectCount, VULKAN_HPP_NAMESPACE::Rect2D* pRects, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<Rect2D>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<Rect2D,Allocator>>::type getPresentRectanglesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<Rect2D>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<Rect2D,Allocator>>::type getPresentRectanglesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getProperties( VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties getProperties(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getProperties2( VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 getProperties2(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getProperties2(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getProperties2KHR( VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 getProperties2KHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ StructureChain<X, Y, Z...> getProperties2KHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getQueueFamilyPerformanceQueryPassesKHR( const VULKAN_HPP_NAMESPACE::QueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ uint32_t getQueueFamilyPerformanceQueryPassesKHR( const QueryPoolPerformanceCreateInfoKHR & performanceQueryCreateInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getQueueFamilyProperties( uint32_t* pQueueFamilyPropertyCount, VULKAN_HPP_NAMESPACE::QueueFamilyProperties* pQueueFamilyProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<QueueFamilyProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<QueueFamilyProperties,Allocator> getQueueFamilyProperties(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<QueueFamilyProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<QueueFamilyProperties,Allocator> getQueueFamilyProperties(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getQueueFamilyProperties2( uint32_t* pQueueFamilyPropertyCount, VULKAN_HPP_NAMESPACE::QueueFamilyProperties2* pQueueFamilyProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<QueueFamilyProperties2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<QueueFamilyProperties2,Allocator> getQueueFamilyProperties2(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<QueueFamilyProperties2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<QueueFamilyProperties2,Allocator> getQueueFamilyProperties2(Allocator const& vectorAllocator, Dispatch const &d ) const;
+ template<typename StructureChain, typename Allocator = std::allocator<StructureChain>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<StructureChain,Allocator> getQueueFamilyProperties2(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename StructureChain, typename Allocator = std::allocator<StructureChain>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<StructureChain,Allocator> getQueueFamilyProperties2(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getQueueFamilyProperties2KHR( uint32_t* pQueueFamilyPropertyCount, VULKAN_HPP_NAMESPACE::QueueFamilyProperties2* pQueueFamilyProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<QueueFamilyProperties2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<QueueFamilyProperties2,Allocator> getQueueFamilyProperties2KHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<QueueFamilyProperties2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<QueueFamilyProperties2,Allocator> getQueueFamilyProperties2KHR(Allocator const& vectorAllocator, Dispatch const &d ) const;
+ template<typename StructureChain, typename Allocator = std::allocator<StructureChain>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<StructureChain,Allocator> getQueueFamilyProperties2KHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename StructureChain, typename Allocator = std::allocator<StructureChain>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<StructureChain,Allocator> getQueueFamilyProperties2KHR(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getSparseImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageTiling tiling, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::SparseImageFormatProperties* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<SparseImageFormatProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageFormatProperties,Allocator> getSparseImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageTiling tiling, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<SparseImageFormatProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageFormatProperties,Allocator> getSparseImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageTiling tiling, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getSparseImageFormatProperties2( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::SparseImageFormatProperties2* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<SparseImageFormatProperties2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageFormatProperties2,Allocator> getSparseImageFormatProperties2( const PhysicalDeviceSparseImageFormatInfo2 & formatInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<SparseImageFormatProperties2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageFormatProperties2,Allocator> getSparseImageFormatProperties2( const PhysicalDeviceSparseImageFormatInfo2 & formatInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void getSparseImageFormatProperties2KHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::SparseImageFormatProperties2* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<SparseImageFormatProperties2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageFormatProperties2,Allocator> getSparseImageFormatProperties2KHR( const PhysicalDeviceSparseImageFormatInfo2 & formatInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<SparseImageFormatProperties2>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ std::vector<SparseImageFormatProperties2,Allocator> getSparseImageFormatProperties2KHR( const PhysicalDeviceSparseImageFormatInfo2 & formatInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSupportedFramebufferMixedSamplesCombinationsNV( uint32_t* pCombinationCount, VULKAN_HPP_NAMESPACE::FramebufferMixedSamplesCombinationNV* pCombinations, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<FramebufferMixedSamplesCombinationNV>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<FramebufferMixedSamplesCombinationNV,Allocator>>::type getSupportedFramebufferMixedSamplesCombinationsNV(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<FramebufferMixedSamplesCombinationNV>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<FramebufferMixedSamplesCombinationNV,Allocator>>::type getSupportedFramebufferMixedSamplesCombinationsNV(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSurfaceCapabilities2EXT( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, VULKAN_HPP_NAMESPACE::SurfaceCapabilities2EXT* pSurfaceCapabilities, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceCapabilities2EXT>::type getSurfaceCapabilities2EXT( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSurfaceCapabilities2KHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR* pSurfaceCapabilities, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR>::type getSurfaceCapabilities2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<StructureChain<X, Y, Z...>>::type getSurfaceCapabilities2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSurfaceCapabilitiesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesKHR* pSurfaceCapabilities, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesKHR>::type getSurfaceCapabilitiesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSurfaceFormats2KHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VULKAN_HPP_NAMESPACE::SurfaceFormat2KHR* pSurfaceFormats, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<SurfaceFormat2KHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<SurfaceFormat2KHR,Allocator>>::type getSurfaceFormats2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<SurfaceFormat2KHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<SurfaceFormat2KHR,Allocator>>::type getSurfaceFormats2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSurfaceFormatsKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, uint32_t* pSurfaceFormatCount, VULKAN_HPP_NAMESPACE::SurfaceFormatKHR* pSurfaceFormats, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<SurfaceFormatKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<SurfaceFormatKHR,Allocator>>::type getSurfaceFormatsKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<SurfaceFormatKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<SurfaceFormatKHR,Allocator>>::type getSurfaceFormatsKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSurfacePresentModes2EXT( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pPresentModeCount, VULKAN_HPP_NAMESPACE::PresentModeKHR* pPresentModes, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PresentModeKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PresentModeKHR,Allocator>>::type getSurfacePresentModes2EXT( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PresentModeKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PresentModeKHR,Allocator>>::type getSurfacePresentModes2EXT( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSurfacePresentModesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, uint32_t* pPresentModeCount, VULKAN_HPP_NAMESPACE::PresentModeKHR* pPresentModes, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PresentModeKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PresentModeKHR,Allocator>>::type getSurfacePresentModesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PresentModeKHR>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PresentModeKHR,Allocator>>::type getSurfacePresentModesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getSurfaceSupportKHR( uint32_t queueFamilyIndex, VULKAN_HPP_NAMESPACE::SurfaceKHR surface, VULKAN_HPP_NAMESPACE::Bool32* pSupported, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Bool32>::type getSurfaceSupportKHR( uint32_t queueFamilyIndex, VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getToolPropertiesEXT( uint32_t* pToolCount, VULKAN_HPP_NAMESPACE::PhysicalDeviceToolPropertiesEXT* pToolProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PhysicalDeviceToolPropertiesEXT>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PhysicalDeviceToolPropertiesEXT,Allocator>>::type getToolPropertiesEXT(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PhysicalDeviceToolPropertiesEXT>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PhysicalDeviceToolPropertiesEXT,Allocator>>::type getToolPropertiesEXT(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Bool32 getWaylandPresentationSupportKHR( uint32_t queueFamilyIndex, struct wl_display* display, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Bool32 getWaylandPresentationSupportKHR( uint32_t queueFamilyIndex, struct wl_display & display, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Bool32 getWin32PresentationSupportKHR( uint32_t queueFamilyIndex, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Bool32 getXcbPresentationSupportKHR( uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Bool32 getXcbPresentationSupportKHR( uint32_t queueFamilyIndex, xcb_connection_t & connection, xcb_visualid_t visual_id, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Bool32 getXlibPresentationSupportKHR( uint32_t queueFamilyIndex, Display* dpy, VisualID visualID, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Bool32 getXlibPresentationSupportKHR( uint32_t queueFamilyIndex, Display & dpy, VisualID visualID, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result getRandROutputDisplayEXT( Display* dpy, RROutput rrOutput, VULKAN_HPP_NAMESPACE::DisplayKHR* pDisplay, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DisplayKHR>::type getRandROutputDisplayEXT( Display & dpy, RROutput rrOutput, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XLIB_XRANDR_EXT*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result releaseDisplayEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<void>::type releaseDisplayEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkPhysicalDevice() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_physicalDevice;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_physicalDevice != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_physicalDevice == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkPhysicalDevice m_physicalDevice;
+ };
+ static_assert( sizeof( PhysicalDevice ) == sizeof( VkPhysicalDevice ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::ePhysicalDevice>
+ {
+ using type = PhysicalDevice;
+ };
+
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ class Instance;
+ template <typename Dispatch> class UniqueHandleTraits<DebugReportCallbackEXT, Dispatch> { public: using deleter = ObjectDestroy<Instance, Dispatch>; };
+ using UniqueDebugReportCallbackEXT = UniqueHandle<DebugReportCallbackEXT, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<DebugUtilsMessengerEXT, Dispatch> { public: using deleter = ObjectDestroy<Instance, Dispatch>; };
+ using UniqueDebugUtilsMessengerEXT = UniqueHandle<DebugUtilsMessengerEXT, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+ template <typename Dispatch> class UniqueHandleTraits<SurfaceKHR, Dispatch> { public: using deleter = ObjectDestroy<Instance, Dispatch>; };
+ using UniqueSurfaceKHR = UniqueHandle<SurfaceKHR, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+
+ class Instance
+ {
+ public:
+ using CType = VkInstance;
+
+ static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eInstance;
+
+ public:
+ VULKAN_HPP_CONSTEXPR Instance() VULKAN_HPP_NOEXCEPT
+ : m_instance(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_CONSTEXPR Instance( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ : m_instance(VK_NULL_HANDLE)
+ {}
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT Instance( VkInstance instance ) VULKAN_HPP_NOEXCEPT
+ : m_instance( instance )
+ {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+ Instance & operator=(VkInstance instance) VULKAN_HPP_NOEXCEPT
+ {
+ m_instance = instance;
+ return *this;
+ }
+#endif
+
+ Instance & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+ {
+ m_instance = VK_NULL_HANDLE;
+ return *this;
+ }
+
+ bool operator==( Instance const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_instance == rhs.m_instance;
+ }
+
+ bool operator!=(Instance const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_instance != rhs.m_instance;
+ }
+
+ bool operator<(Instance const & rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return m_instance < rhs.m_instance;
+ }
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createAndroidSurfaceKHR( const VULKAN_HPP_NAMESPACE::AndroidSurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createAndroidSurfaceKHR( const AndroidSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createAndroidSurfaceKHRUnique( const AndroidSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createDebugReportCallbackEXT( const VULKAN_HPP_NAMESPACE::DebugReportCallbackCreateInfoEXT* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT* pCallback, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT>::type createDebugReportCallbackEXT( const DebugReportCallbackCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<DebugReportCallbackEXT,Dispatch>>::type createDebugReportCallbackEXTUnique( const DebugReportCallbackCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createDebugUtilsMessengerEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT* pMessenger, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT>::type createDebugUtilsMessengerEXT( const DebugUtilsMessengerCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<DebugUtilsMessengerEXT,Dispatch>>::type createDebugUtilsMessengerEXTUnique( const DebugUtilsMessengerCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createDisplayPlaneSurfaceKHR( const VULKAN_HPP_NAMESPACE::DisplaySurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createDisplayPlaneSurfaceKHR( const DisplaySurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createDisplayPlaneSurfaceKHRUnique( const DisplaySurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createHeadlessSurfaceEXT( const VULKAN_HPP_NAMESPACE::HeadlessSurfaceCreateInfoEXT* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createHeadlessSurfaceEXT( const HeadlessSurfaceCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createHeadlessSurfaceEXTUnique( const HeadlessSurfaceCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createIOSSurfaceMVK( const VULKAN_HPP_NAMESPACE::IOSSurfaceCreateInfoMVK* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createIOSSurfaceMVK( const IOSSurfaceCreateInfoMVK & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createIOSSurfaceMVKUnique( const IOSSurfaceCreateInfoMVK & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_IOS_MVK*/
+
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createImagePipeSurfaceFUCHSIA( const VULKAN_HPP_NAMESPACE::ImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createImagePipeSurfaceFUCHSIA( const ImagePipeSurfaceCreateInfoFUCHSIA & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createImagePipeSurfaceFUCHSIAUnique( const ImagePipeSurfaceCreateInfoFUCHSIA & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_FUCHSIA*/
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createMacOSSurfaceMVK( const VULKAN_HPP_NAMESPACE::MacOSSurfaceCreateInfoMVK* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createMacOSSurfaceMVK( const MacOSSurfaceCreateInfoMVK & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createMacOSSurfaceMVKUnique( const MacOSSurfaceCreateInfoMVK & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_MACOS_MVK*/
+
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createMetalSurfaceEXT( const VULKAN_HPP_NAMESPACE::MetalSurfaceCreateInfoEXT* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createMetalSurfaceEXT( const MetalSurfaceCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createMetalSurfaceEXTUnique( const MetalSurfaceCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_METAL_EXT*/
+
+#ifdef VK_USE_PLATFORM_GGP
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createStreamDescriptorSurfaceGGP( const VULKAN_HPP_NAMESPACE::StreamDescriptorSurfaceCreateInfoGGP* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createStreamDescriptorSurfaceGGP( const StreamDescriptorSurfaceCreateInfoGGP & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createStreamDescriptorSurfaceGGPUnique( const StreamDescriptorSurfaceCreateInfoGGP & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_GGP*/
+
+#ifdef VK_USE_PLATFORM_VI_NN
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createViSurfaceNN( const VULKAN_HPP_NAMESPACE::ViSurfaceCreateInfoNN* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createViSurfaceNN( const ViSurfaceCreateInfoNN & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createViSurfaceNNUnique( const ViSurfaceCreateInfoNN & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_VI_NN*/
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createWaylandSurfaceKHR( const VULKAN_HPP_NAMESPACE::WaylandSurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createWaylandSurfaceKHR( const WaylandSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createWaylandSurfaceKHRUnique( const WaylandSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createWin32SurfaceKHR( const VULKAN_HPP_NAMESPACE::Win32SurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createWin32SurfaceKHR( const Win32SurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createWin32SurfaceKHRUnique( const Win32SurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createXcbSurfaceKHR( const VULKAN_HPP_NAMESPACE::XcbSurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createXcbSurfaceKHR( const XcbSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createXcbSurfaceKHRUnique( const XcbSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createXlibSurfaceKHR( const VULKAN_HPP_NAMESPACE::XlibSurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type createXlibSurfaceKHR( const XlibSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type createXlibSurfaceKHRUnique( const XlibSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void debugReportMessageEXT( VULKAN_HPP_NAMESPACE::DebugReportFlagsEXT flags, VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void debugReportMessageEXT( VULKAN_HPP_NAMESPACE::DebugReportFlagsEXT flags, VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const std::string & layerPrefix, const std::string & message, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDebugReportCallbackEXT( VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT callback, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDebugReportCallbackEXT( VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT callback, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT callback, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT callback, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDebugUtilsMessengerEXT( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT messenger, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroyDebugUtilsMessengerEXT( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT messenger, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT messenger, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT messenger, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySurfaceKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroySurfaceKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void destroy( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result enumeratePhysicalDeviceGroups( uint32_t* pPhysicalDeviceGroupCount, VULKAN_HPP_NAMESPACE::PhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PhysicalDeviceGroupProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PhysicalDeviceGroupProperties,Allocator>>::type enumeratePhysicalDeviceGroups(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PhysicalDeviceGroupProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PhysicalDeviceGroupProperties,Allocator>>::type enumeratePhysicalDeviceGroups(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result enumeratePhysicalDeviceGroupsKHR( uint32_t* pPhysicalDeviceGroupCount, VULKAN_HPP_NAMESPACE::PhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PhysicalDeviceGroupProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PhysicalDeviceGroupProperties,Allocator>>::type enumeratePhysicalDeviceGroupsKHR(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PhysicalDeviceGroupProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PhysicalDeviceGroupProperties,Allocator>>::type enumeratePhysicalDeviceGroupsKHR(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result enumeratePhysicalDevices( uint32_t* pPhysicalDeviceCount, VULKAN_HPP_NAMESPACE::PhysicalDevice* pPhysicalDevices, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<PhysicalDevice>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PhysicalDevice,Allocator>>::type enumeratePhysicalDevices(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+ template<typename Allocator = std::allocator<PhysicalDevice>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<PhysicalDevice,Allocator>>::type enumeratePhysicalDevices(Allocator const& vectorAllocator, Dispatch const &d ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ PFN_vkVoidFunction getProcAddr( const char* pName, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ PFN_vkVoidFunction getProcAddr( const std::string & name, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void submitDebugUtilsMessageEXT( VULKAN_HPP_NAMESPACE::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VULKAN_HPP_NAMESPACE::DebugUtilsMessageTypeFlagsEXT messageTypes, const VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCallbackDataEXT* pCallbackData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ void submitDebugUtilsMessageEXT( VULKAN_HPP_NAMESPACE::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VULKAN_HPP_NAMESPACE::DebugUtilsMessageTypeFlagsEXT messageTypes, const DebugUtilsMessengerCallbackDataEXT & callbackData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ VULKAN_HPP_TYPESAFE_EXPLICIT operator VkInstance() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_instance;
+ }
+
+ explicit operator bool() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_instance != VK_NULL_HANDLE;
+ }
+
+ bool operator!() const VULKAN_HPP_NOEXCEPT
+ {
+ return m_instance == VK_NULL_HANDLE;
+ }
+
+ private:
+ VkInstance m_instance;
+ };
+ static_assert( sizeof( Instance ) == sizeof( VkInstance ), "handle and wrapper have different size!" );
+
+ template <>
+ struct cpp_type<ObjectType::eInstance>
+ {
+ using type = Instance;
+ };
+
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template <typename Dispatch> class UniqueHandleTraits<Instance, Dispatch> { public: using deleter = ObjectDestroy<NoParent, Dispatch>; };
+ using UniqueInstance = UniqueHandle<Instance, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result createInstance( const VULKAN_HPP_NAMESPACE::InstanceCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Instance* pInstance, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<VULKAN_HPP_NAMESPACE::Instance>::type createInstance( const InstanceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER );
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<UniqueHandle<Instance,Dispatch>>::type createInstanceUnique( const InstanceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER );
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result enumerateInstanceExtensionProperties( const char* pLayerName, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::ExtensionProperties* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<ExtensionProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<ExtensionProperties,Allocator>>::type enumerateInstanceExtensionProperties( Optional<const std::string> layerName = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER );
+ template<typename Allocator = std::allocator<ExtensionProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<ExtensionProperties,Allocator>>::type enumerateInstanceExtensionProperties( Optional<const std::string> layerName, Allocator const& vectorAllocator, Dispatch const &d );
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result enumerateInstanceLayerProperties( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::LayerProperties* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator = std::allocator<LayerProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<LayerProperties,Allocator>>::type enumerateInstanceLayerProperties(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER );
+ template<typename Allocator = std::allocator<LayerProperties>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<std::vector<LayerProperties,Allocator>>::type enumerateInstanceLayerProperties(Allocator const& vectorAllocator, Dispatch const &d );
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ Result enumerateInstanceVersion( uint32_t* pApiVersion, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+ typename ResultValueType<uint32_t>::type enumerateInstanceVersion(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER );
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ struct GeometryTrianglesNV
+ {
+ VULKAN_HPP_CONSTEXPR GeometryTrianglesNV( VULKAN_HPP_NAMESPACE::Buffer vertexData_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize vertexOffset_ = {},
+ uint32_t vertexCount_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize vertexStride_ = {},
+ VULKAN_HPP_NAMESPACE::Format vertexFormat_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::Buffer indexData_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize indexOffset_ = {},
+ uint32_t indexCount_ = {},
+ VULKAN_HPP_NAMESPACE::IndexType indexType_ = VULKAN_HPP_NAMESPACE::IndexType::eUint16,
+ VULKAN_HPP_NAMESPACE::Buffer transformData_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize transformOffset_ = {} ) VULKAN_HPP_NOEXCEPT
+ : vertexData( vertexData_ )
+ , vertexOffset( vertexOffset_ )
+ , vertexCount( vertexCount_ )
+ , vertexStride( vertexStride_ )
+ , vertexFormat( vertexFormat_ )
+ , indexData( indexData_ )
+ , indexOffset( indexOffset_ )
+ , indexCount( indexCount_ )
+ , indexType( indexType_ )
+ , transformData( transformData_ )
+ , transformOffset( transformOffset_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::GeometryTrianglesNV & operator=( VULKAN_HPP_NAMESPACE::GeometryTrianglesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::GeometryTrianglesNV ) - offsetof( GeometryTrianglesNV, pNext ) );
+ return *this;
+ }
+
+ GeometryTrianglesNV( VkGeometryTrianglesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ GeometryTrianglesNV& operator=( VkGeometryTrianglesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::GeometryTrianglesNV const *>(&rhs);
+ return *this;
+ }
+
+ GeometryTrianglesNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setVertexData( VULKAN_HPP_NAMESPACE::Buffer vertexData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexData = vertexData_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setVertexOffset( VULKAN_HPP_NAMESPACE::DeviceSize vertexOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexOffset = vertexOffset_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setVertexCount( uint32_t vertexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexCount = vertexCount_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setVertexStride( VULKAN_HPP_NAMESPACE::DeviceSize vertexStride_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexStride = vertexStride_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setVertexFormat( VULKAN_HPP_NAMESPACE::Format vertexFormat_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexFormat = vertexFormat_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setIndexData( VULKAN_HPP_NAMESPACE::Buffer indexData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ indexData = indexData_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setIndexOffset( VULKAN_HPP_NAMESPACE::DeviceSize indexOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ indexOffset = indexOffset_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setIndexCount( uint32_t indexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ indexCount = indexCount_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setIndexType( VULKAN_HPP_NAMESPACE::IndexType indexType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ indexType = indexType_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setTransformData( VULKAN_HPP_NAMESPACE::Buffer transformData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ transformData = transformData_;
+ return *this;
+ }
+
+ GeometryTrianglesNV & setTransformOffset( VULKAN_HPP_NAMESPACE::DeviceSize transformOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ transformOffset = transformOffset_;
+ return *this;
+ }
+
+ operator VkGeometryTrianglesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkGeometryTrianglesNV*>( this );
+ }
+
+ operator VkGeometryTrianglesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkGeometryTrianglesNV*>( this );
+ }
+
+ bool operator==( GeometryTrianglesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( vertexData == rhs.vertexData )
+ && ( vertexOffset == rhs.vertexOffset )
+ && ( vertexCount == rhs.vertexCount )
+ && ( vertexStride == rhs.vertexStride )
+ && ( vertexFormat == rhs.vertexFormat )
+ && ( indexData == rhs.indexData )
+ && ( indexOffset == rhs.indexOffset )
+ && ( indexCount == rhs.indexCount )
+ && ( indexType == rhs.indexType )
+ && ( transformData == rhs.transformData )
+ && ( transformOffset == rhs.transformOffset );
+ }
+
+ bool operator!=( GeometryTrianglesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eGeometryTrianglesNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Buffer vertexData = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize vertexOffset = {};
+ uint32_t vertexCount = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize vertexStride = {};
+ VULKAN_HPP_NAMESPACE::Format vertexFormat = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::Buffer indexData = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize indexOffset = {};
+ uint32_t indexCount = {};
+ VULKAN_HPP_NAMESPACE::IndexType indexType = VULKAN_HPP_NAMESPACE::IndexType::eUint16;
+ VULKAN_HPP_NAMESPACE::Buffer transformData = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize transformOffset = {};
+ };
+ static_assert( sizeof( GeometryTrianglesNV ) == sizeof( VkGeometryTrianglesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<GeometryTrianglesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct GeometryAABBNV
+ {
+ VULKAN_HPP_CONSTEXPR GeometryAABBNV( VULKAN_HPP_NAMESPACE::Buffer aabbData_ = {},
+ uint32_t numAABBs_ = {},
+ uint32_t stride_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {} ) VULKAN_HPP_NOEXCEPT
+ : aabbData( aabbData_ )
+ , numAABBs( numAABBs_ )
+ , stride( stride_ )
+ , offset( offset_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::GeometryAABBNV & operator=( VULKAN_HPP_NAMESPACE::GeometryAABBNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::GeometryAABBNV ) - offsetof( GeometryAABBNV, pNext ) );
+ return *this;
+ }
+
+ GeometryAABBNV( VkGeometryAABBNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ GeometryAABBNV& operator=( VkGeometryAABBNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::GeometryAABBNV const *>(&rhs);
+ return *this;
+ }
+
+ GeometryAABBNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ GeometryAABBNV & setAabbData( VULKAN_HPP_NAMESPACE::Buffer aabbData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ aabbData = aabbData_;
+ return *this;
+ }
+
+ GeometryAABBNV & setNumAABBs( uint32_t numAABBs_ ) VULKAN_HPP_NOEXCEPT
+ {
+ numAABBs = numAABBs_;
+ return *this;
+ }
+
+ GeometryAABBNV & setStride( uint32_t stride_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stride = stride_;
+ return *this;
+ }
+
+ GeometryAABBNV & setOffset( VULKAN_HPP_NAMESPACE::DeviceSize offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ operator VkGeometryAABBNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkGeometryAABBNV*>( this );
+ }
+
+ operator VkGeometryAABBNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkGeometryAABBNV*>( this );
+ }
+
+ bool operator==( GeometryAABBNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( aabbData == rhs.aabbData )
+ && ( numAABBs == rhs.numAABBs )
+ && ( stride == rhs.stride )
+ && ( offset == rhs.offset );
+ }
+
+ bool operator!=( GeometryAABBNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eGeometryAabbNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Buffer aabbData = {};
+ uint32_t numAABBs = {};
+ uint32_t stride = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
+ };
+ static_assert( sizeof( GeometryAABBNV ) == sizeof( VkGeometryAABBNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<GeometryAABBNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct GeometryDataNV
+ {
+ VULKAN_HPP_CONSTEXPR GeometryDataNV( VULKAN_HPP_NAMESPACE::GeometryTrianglesNV triangles_ = {},
+ VULKAN_HPP_NAMESPACE::GeometryAABBNV aabbs_ = {} ) VULKAN_HPP_NOEXCEPT
+ : triangles( triangles_ )
+ , aabbs( aabbs_ )
+ {}
+
+ GeometryDataNV( VkGeometryDataNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ GeometryDataNV& operator=( VkGeometryDataNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::GeometryDataNV const *>(&rhs);
+ return *this;
+ }
+
+ GeometryDataNV & setTriangles( VULKAN_HPP_NAMESPACE::GeometryTrianglesNV triangles_ ) VULKAN_HPP_NOEXCEPT
+ {
+ triangles = triangles_;
+ return *this;
+ }
+
+ GeometryDataNV & setAabbs( VULKAN_HPP_NAMESPACE::GeometryAABBNV aabbs_ ) VULKAN_HPP_NOEXCEPT
+ {
+ aabbs = aabbs_;
+ return *this;
+ }
+
+ operator VkGeometryDataNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkGeometryDataNV*>( this );
+ }
+
+ operator VkGeometryDataNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkGeometryDataNV*>( this );
+ }
+
+ bool operator==( GeometryDataNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( triangles == rhs.triangles )
+ && ( aabbs == rhs.aabbs );
+ }
+
+ bool operator!=( GeometryDataNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::GeometryTrianglesNV triangles = {};
+ VULKAN_HPP_NAMESPACE::GeometryAABBNV aabbs = {};
+ };
+ static_assert( sizeof( GeometryDataNV ) == sizeof( VkGeometryDataNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<GeometryDataNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct GeometryNV
+ {
+ VULKAN_HPP_CONSTEXPR GeometryNV( VULKAN_HPP_NAMESPACE::GeometryTypeNV geometryType_ = VULKAN_HPP_NAMESPACE::GeometryTypeNV::eTriangles,
+ VULKAN_HPP_NAMESPACE::GeometryDataNV geometry_ = {},
+ VULKAN_HPP_NAMESPACE::GeometryFlagsNV flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : geometryType( geometryType_ )
+ , geometry( geometry_ )
+ , flags( flags_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::GeometryNV & operator=( VULKAN_HPP_NAMESPACE::GeometryNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::GeometryNV ) - offsetof( GeometryNV, pNext ) );
+ return *this;
+ }
+
+ GeometryNV( VkGeometryNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ GeometryNV& operator=( VkGeometryNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::GeometryNV const *>(&rhs);
+ return *this;
+ }
+
+ GeometryNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ GeometryNV & setGeometryType( VULKAN_HPP_NAMESPACE::GeometryTypeNV geometryType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ geometryType = geometryType_;
+ return *this;
+ }
+
+ GeometryNV & setGeometry( VULKAN_HPP_NAMESPACE::GeometryDataNV geometry_ ) VULKAN_HPP_NOEXCEPT
+ {
+ geometry = geometry_;
+ return *this;
+ }
+
+ GeometryNV & setFlags( VULKAN_HPP_NAMESPACE::GeometryFlagsNV flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ operator VkGeometryNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkGeometryNV*>( this );
+ }
+
+ operator VkGeometryNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkGeometryNV*>( this );
+ }
+
+ bool operator==( GeometryNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( geometryType == rhs.geometryType )
+ && ( geometry == rhs.geometry )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( GeometryNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eGeometryNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::GeometryTypeNV geometryType = VULKAN_HPP_NAMESPACE::GeometryTypeNV::eTriangles;
+ VULKAN_HPP_NAMESPACE::GeometryDataNV geometry = {};
+ VULKAN_HPP_NAMESPACE::GeometryFlagsNV flags = {};
+ };
+ static_assert( sizeof( GeometryNV ) == sizeof( VkGeometryNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<GeometryNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct AccelerationStructureInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR AccelerationStructureInfoNV( VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV type_ = VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV::eTopLevel,
+ VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsNV flags_ = {},
+ uint32_t instanceCount_ = {},
+ uint32_t geometryCount_ = {},
+ const VULKAN_HPP_NAMESPACE::GeometryNV* pGeometries_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , flags( flags_ )
+ , instanceCount( instanceCount_ )
+ , geometryCount( geometryCount_ )
+ , pGeometries( pGeometries_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV & operator=( VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV ) - offsetof( AccelerationStructureInfoNV, pNext ) );
+ return *this;
+ }
+
+ AccelerationStructureInfoNV( VkAccelerationStructureInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AccelerationStructureInfoNV& operator=( VkAccelerationStructureInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ AccelerationStructureInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ AccelerationStructureInfoNV & setType( VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ AccelerationStructureInfoNV & setFlags( VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsNV flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ AccelerationStructureInfoNV & setInstanceCount( uint32_t instanceCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ instanceCount = instanceCount_;
+ return *this;
+ }
+
+ AccelerationStructureInfoNV & setGeometryCount( uint32_t geometryCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ geometryCount = geometryCount_;
+ return *this;
+ }
+
+ AccelerationStructureInfoNV & setPGeometries( const VULKAN_HPP_NAMESPACE::GeometryNV* pGeometries_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pGeometries = pGeometries_;
+ return *this;
+ }
+
+ operator VkAccelerationStructureInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAccelerationStructureInfoNV*>( this );
+ }
+
+ operator VkAccelerationStructureInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAccelerationStructureInfoNV*>( this );
+ }
+
+ bool operator==( AccelerationStructureInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( type == rhs.type )
+ && ( flags == rhs.flags )
+ && ( instanceCount == rhs.instanceCount )
+ && ( geometryCount == rhs.geometryCount )
+ && ( pGeometries == rhs.pGeometries );
+ }
+
+ bool operator!=( AccelerationStructureInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV type = VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV::eTopLevel;
+ VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsNV flags = {};
+ uint32_t instanceCount = {};
+ uint32_t geometryCount = {};
+ const VULKAN_HPP_NAMESPACE::GeometryNV* pGeometries = {};
+ };
+ static_assert( sizeof( AccelerationStructureInfoNV ) == sizeof( VkAccelerationStructureInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AccelerationStructureInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct AccelerationStructureCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR AccelerationStructureCreateInfoNV( VULKAN_HPP_NAMESPACE::DeviceSize compactedSize_ = {},
+ VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV info_ = {} ) VULKAN_HPP_NOEXCEPT
+ : compactedSize( compactedSize_ )
+ , info( info_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoNV ) - offsetof( AccelerationStructureCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ AccelerationStructureCreateInfoNV( VkAccelerationStructureCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AccelerationStructureCreateInfoNV& operator=( VkAccelerationStructureCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ AccelerationStructureCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ AccelerationStructureCreateInfoNV & setCompactedSize( VULKAN_HPP_NAMESPACE::DeviceSize compactedSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ compactedSize = compactedSize_;
+ return *this;
+ }
+
+ AccelerationStructureCreateInfoNV & setInfo( VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV info_ ) VULKAN_HPP_NOEXCEPT
+ {
+ info = info_;
+ return *this;
+ }
+
+ operator VkAccelerationStructureCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAccelerationStructureCreateInfoNV*>( this );
+ }
+
+ operator VkAccelerationStructureCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAccelerationStructureCreateInfoNV*>( this );
+ }
+
+ bool operator==( AccelerationStructureCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( compactedSize == rhs.compactedSize )
+ && ( info == rhs.info );
+ }
+
+ bool operator!=( AccelerationStructureCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize compactedSize = {};
+ VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV info = {};
+ };
+ static_assert( sizeof( AccelerationStructureCreateInfoNV ) == sizeof( VkAccelerationStructureCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AccelerationStructureCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct AccelerationStructureMemoryRequirementsInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR AccelerationStructureMemoryRequirementsInfoNV( VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV type_ = VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV::eObject,
+ VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , accelerationStructure( accelerationStructure_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoNV & operator=( VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoNV ) - offsetof( AccelerationStructureMemoryRequirementsInfoNV, pNext ) );
+ return *this;
+ }
+
+ AccelerationStructureMemoryRequirementsInfoNV( VkAccelerationStructureMemoryRequirementsInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AccelerationStructureMemoryRequirementsInfoNV& operator=( VkAccelerationStructureMemoryRequirementsInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ AccelerationStructureMemoryRequirementsInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ AccelerationStructureMemoryRequirementsInfoNV & setType( VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ AccelerationStructureMemoryRequirementsInfoNV & setAccelerationStructure( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure_ ) VULKAN_HPP_NOEXCEPT
+ {
+ accelerationStructure = accelerationStructure_;
+ return *this;
+ }
+
+ operator VkAccelerationStructureMemoryRequirementsInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAccelerationStructureMemoryRequirementsInfoNV*>( this );
+ }
+
+ operator VkAccelerationStructureMemoryRequirementsInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAccelerationStructureMemoryRequirementsInfoNV*>( this );
+ }
+
+ bool operator==( AccelerationStructureMemoryRequirementsInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( type == rhs.type )
+ && ( accelerationStructure == rhs.accelerationStructure );
+ }
+
+ bool operator!=( AccelerationStructureMemoryRequirementsInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureMemoryRequirementsInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV type = VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV::eObject;
+ VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure = {};
+ };
+ static_assert( sizeof( AccelerationStructureMemoryRequirementsInfoNV ) == sizeof( VkAccelerationStructureMemoryRequirementsInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AccelerationStructureMemoryRequirementsInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct AcquireNextImageInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR AcquireNextImageInfoKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain_ = {},
+ uint64_t timeout_ = {},
+ VULKAN_HPP_NAMESPACE::Semaphore semaphore_ = {},
+ VULKAN_HPP_NAMESPACE::Fence fence_ = {},
+ uint32_t deviceMask_ = {} ) VULKAN_HPP_NOEXCEPT
+ : swapchain( swapchain_ )
+ , timeout( timeout_ )
+ , semaphore( semaphore_ )
+ , fence( fence_ )
+ , deviceMask( deviceMask_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AcquireNextImageInfoKHR & operator=( VULKAN_HPP_NAMESPACE::AcquireNextImageInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AcquireNextImageInfoKHR ) - offsetof( AcquireNextImageInfoKHR, pNext ) );
+ return *this;
+ }
+
+ AcquireNextImageInfoKHR( VkAcquireNextImageInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AcquireNextImageInfoKHR& operator=( VkAcquireNextImageInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AcquireNextImageInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ AcquireNextImageInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ AcquireNextImageInfoKHR & setSwapchain( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain_ ) VULKAN_HPP_NOEXCEPT
+ {
+ swapchain = swapchain_;
+ return *this;
+ }
+
+ AcquireNextImageInfoKHR & setTimeout( uint64_t timeout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ timeout = timeout_;
+ return *this;
+ }
+
+ AcquireNextImageInfoKHR & setSemaphore( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ ) VULKAN_HPP_NOEXCEPT
+ {
+ semaphore = semaphore_;
+ return *this;
+ }
+
+ AcquireNextImageInfoKHR & setFence( VULKAN_HPP_NAMESPACE::Fence fence_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fence = fence_;
+ return *this;
+ }
+
+ AcquireNextImageInfoKHR & setDeviceMask( uint32_t deviceMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceMask = deviceMask_;
+ return *this;
+ }
+
+ operator VkAcquireNextImageInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAcquireNextImageInfoKHR*>( this );
+ }
+
+ operator VkAcquireNextImageInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAcquireNextImageInfoKHR*>( this );
+ }
+
+ bool operator==( AcquireNextImageInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( swapchain == rhs.swapchain )
+ && ( timeout == rhs.timeout )
+ && ( semaphore == rhs.semaphore )
+ && ( fence == rhs.fence )
+ && ( deviceMask == rhs.deviceMask );
+ }
+
+ bool operator!=( AcquireNextImageInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAcquireNextImageInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain = {};
+ uint64_t timeout = {};
+ VULKAN_HPP_NAMESPACE::Semaphore semaphore = {};
+ VULKAN_HPP_NAMESPACE::Fence fence = {};
+ uint32_t deviceMask = {};
+ };
+ static_assert( sizeof( AcquireNextImageInfoKHR ) == sizeof( VkAcquireNextImageInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AcquireNextImageInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct AcquireProfilingLockInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR AcquireProfilingLockInfoKHR( VULKAN_HPP_NAMESPACE::AcquireProfilingLockFlagsKHR flags_ = {},
+ uint64_t timeout_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , timeout( timeout_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AcquireProfilingLockInfoKHR & operator=( VULKAN_HPP_NAMESPACE::AcquireProfilingLockInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AcquireProfilingLockInfoKHR ) - offsetof( AcquireProfilingLockInfoKHR, pNext ) );
+ return *this;
+ }
+
+ AcquireProfilingLockInfoKHR( VkAcquireProfilingLockInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AcquireProfilingLockInfoKHR& operator=( VkAcquireProfilingLockInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AcquireProfilingLockInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ AcquireProfilingLockInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ AcquireProfilingLockInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::AcquireProfilingLockFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ AcquireProfilingLockInfoKHR & setTimeout( uint64_t timeout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ timeout = timeout_;
+ return *this;
+ }
+
+ operator VkAcquireProfilingLockInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAcquireProfilingLockInfoKHR*>( this );
+ }
+
+ operator VkAcquireProfilingLockInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAcquireProfilingLockInfoKHR*>( this );
+ }
+
+ bool operator==( AcquireProfilingLockInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( timeout == rhs.timeout );
+ }
+
+ bool operator!=( AcquireProfilingLockInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAcquireProfilingLockInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::AcquireProfilingLockFlagsKHR flags = {};
+ uint64_t timeout = {};
+ };
+ static_assert( sizeof( AcquireProfilingLockInfoKHR ) == sizeof( VkAcquireProfilingLockInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AcquireProfilingLockInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct AllocationCallbacks
+ {
+ VULKAN_HPP_CONSTEXPR AllocationCallbacks( void* pUserData_ = {},
+ PFN_vkAllocationFunction pfnAllocation_ = {},
+ PFN_vkReallocationFunction pfnReallocation_ = {},
+ PFN_vkFreeFunction pfnFree_ = {},
+ PFN_vkInternalAllocationNotification pfnInternalAllocation_ = {},
+ PFN_vkInternalFreeNotification pfnInternalFree_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pUserData( pUserData_ )
+ , pfnAllocation( pfnAllocation_ )
+ , pfnReallocation( pfnReallocation_ )
+ , pfnFree( pfnFree_ )
+ , pfnInternalAllocation( pfnInternalAllocation_ )
+ , pfnInternalFree( pfnInternalFree_ )
+ {}
+
+ AllocationCallbacks( VkAllocationCallbacks const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AllocationCallbacks& operator=( VkAllocationCallbacks const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AllocationCallbacks const *>(&rhs);
+ return *this;
+ }
+
+ AllocationCallbacks & setPUserData( void* pUserData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pUserData = pUserData_;
+ return *this;
+ }
+
+ AllocationCallbacks & setPfnAllocation( PFN_vkAllocationFunction pfnAllocation_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pfnAllocation = pfnAllocation_;
+ return *this;
+ }
+
+ AllocationCallbacks & setPfnReallocation( PFN_vkReallocationFunction pfnReallocation_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pfnReallocation = pfnReallocation_;
+ return *this;
+ }
+
+ AllocationCallbacks & setPfnFree( PFN_vkFreeFunction pfnFree_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pfnFree = pfnFree_;
+ return *this;
+ }
+
+ AllocationCallbacks & setPfnInternalAllocation( PFN_vkInternalAllocationNotification pfnInternalAllocation_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pfnInternalAllocation = pfnInternalAllocation_;
+ return *this;
+ }
+
+ AllocationCallbacks & setPfnInternalFree( PFN_vkInternalFreeNotification pfnInternalFree_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pfnInternalFree = pfnInternalFree_;
+ return *this;
+ }
+
+ operator VkAllocationCallbacks const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAllocationCallbacks*>( this );
+ }
+
+ operator VkAllocationCallbacks &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAllocationCallbacks*>( this );
+ }
+
+ bool operator==( AllocationCallbacks const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( pUserData == rhs.pUserData )
+ && ( pfnAllocation == rhs.pfnAllocation )
+ && ( pfnReallocation == rhs.pfnReallocation )
+ && ( pfnFree == rhs.pfnFree )
+ && ( pfnInternalAllocation == rhs.pfnInternalAllocation )
+ && ( pfnInternalFree == rhs.pfnInternalFree );
+ }
+
+ bool operator!=( AllocationCallbacks const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ void* pUserData = {};
+ PFN_vkAllocationFunction pfnAllocation = {};
+ PFN_vkReallocationFunction pfnReallocation = {};
+ PFN_vkFreeFunction pfnFree = {};
+ PFN_vkInternalAllocationNotification pfnInternalAllocation = {};
+ PFN_vkInternalFreeNotification pfnInternalFree = {};
+ };
+ static_assert( sizeof( AllocationCallbacks ) == sizeof( VkAllocationCallbacks ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AllocationCallbacks>::value, "struct wrapper is not a standard layout!" );
+
+ struct ComponentMapping
+ {
+ VULKAN_HPP_CONSTEXPR ComponentMapping( VULKAN_HPP_NAMESPACE::ComponentSwizzle r_ = VULKAN_HPP_NAMESPACE::ComponentSwizzle::eIdentity,
+ VULKAN_HPP_NAMESPACE::ComponentSwizzle g_ = VULKAN_HPP_NAMESPACE::ComponentSwizzle::eIdentity,
+ VULKAN_HPP_NAMESPACE::ComponentSwizzle b_ = VULKAN_HPP_NAMESPACE::ComponentSwizzle::eIdentity,
+ VULKAN_HPP_NAMESPACE::ComponentSwizzle a_ = VULKAN_HPP_NAMESPACE::ComponentSwizzle::eIdentity ) VULKAN_HPP_NOEXCEPT
+ : r( r_ )
+ , g( g_ )
+ , b( b_ )
+ , a( a_ )
+ {}
+
+ ComponentMapping( VkComponentMapping const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ComponentMapping& operator=( VkComponentMapping const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ComponentMapping const *>(&rhs);
+ return *this;
+ }
+
+ ComponentMapping & setR( VULKAN_HPP_NAMESPACE::ComponentSwizzle r_ ) VULKAN_HPP_NOEXCEPT
+ {
+ r = r_;
+ return *this;
+ }
+
+ ComponentMapping & setG( VULKAN_HPP_NAMESPACE::ComponentSwizzle g_ ) VULKAN_HPP_NOEXCEPT
+ {
+ g = g_;
+ return *this;
+ }
+
+ ComponentMapping & setB( VULKAN_HPP_NAMESPACE::ComponentSwizzle b_ ) VULKAN_HPP_NOEXCEPT
+ {
+ b = b_;
+ return *this;
+ }
+
+ ComponentMapping & setA( VULKAN_HPP_NAMESPACE::ComponentSwizzle a_ ) VULKAN_HPP_NOEXCEPT
+ {
+ a = a_;
+ return *this;
+ }
+
+ operator VkComponentMapping const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkComponentMapping*>( this );
+ }
+
+ operator VkComponentMapping &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkComponentMapping*>( this );
+ }
+
+ bool operator==( ComponentMapping const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( r == rhs.r )
+ && ( g == rhs.g )
+ && ( b == rhs.b )
+ && ( a == rhs.a );
+ }
+
+ bool operator!=( ComponentMapping const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ComponentSwizzle r = VULKAN_HPP_NAMESPACE::ComponentSwizzle::eIdentity;
+ VULKAN_HPP_NAMESPACE::ComponentSwizzle g = VULKAN_HPP_NAMESPACE::ComponentSwizzle::eIdentity;
+ VULKAN_HPP_NAMESPACE::ComponentSwizzle b = VULKAN_HPP_NAMESPACE::ComponentSwizzle::eIdentity;
+ VULKAN_HPP_NAMESPACE::ComponentSwizzle a = VULKAN_HPP_NAMESPACE::ComponentSwizzle::eIdentity;
+ };
+ static_assert( sizeof( ComponentMapping ) == sizeof( VkComponentMapping ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ComponentMapping>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+
+ struct AndroidHardwareBufferFormatPropertiesANDROID
+ {
+ AndroidHardwareBufferFormatPropertiesANDROID( VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ uint64_t externalFormat_ = {},
+ VULKAN_HPP_NAMESPACE::FormatFeatureFlags formatFeatures_ = {},
+ VULKAN_HPP_NAMESPACE::ComponentMapping samplerYcbcrConversionComponents_ = {},
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrModelConversion suggestedYcbcrModel_ = VULKAN_HPP_NAMESPACE::SamplerYcbcrModelConversion::eRgbIdentity,
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrRange suggestedYcbcrRange_ = VULKAN_HPP_NAMESPACE::SamplerYcbcrRange::eItuFull,
+ VULKAN_HPP_NAMESPACE::ChromaLocation suggestedXChromaOffset_ = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven,
+ VULKAN_HPP_NAMESPACE::ChromaLocation suggestedYChromaOffset_ = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven ) VULKAN_HPP_NOEXCEPT
+ : format( format_ )
+ , externalFormat( externalFormat_ )
+ , formatFeatures( formatFeatures_ )
+ , samplerYcbcrConversionComponents( samplerYcbcrConversionComponents_ )
+ , suggestedYcbcrModel( suggestedYcbcrModel_ )
+ , suggestedYcbcrRange( suggestedYcbcrRange_ )
+ , suggestedXChromaOffset( suggestedXChromaOffset_ )
+ , suggestedYChromaOffset( suggestedYChromaOffset_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatPropertiesANDROID & operator=( VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatPropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatPropertiesANDROID ) - offsetof( AndroidHardwareBufferFormatPropertiesANDROID, pNext ) );
+ return *this;
+ }
+
+ AndroidHardwareBufferFormatPropertiesANDROID( VkAndroidHardwareBufferFormatPropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AndroidHardwareBufferFormatPropertiesANDROID& operator=( VkAndroidHardwareBufferFormatPropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferFormatPropertiesANDROID const *>(&rhs);
+ return *this;
+ }
+
+ operator VkAndroidHardwareBufferFormatPropertiesANDROID const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAndroidHardwareBufferFormatPropertiesANDROID*>( this );
+ }
+
+ operator VkAndroidHardwareBufferFormatPropertiesANDROID &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAndroidHardwareBufferFormatPropertiesANDROID*>( this );
+ }
+
+ bool operator==( AndroidHardwareBufferFormatPropertiesANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( format == rhs.format )
+ && ( externalFormat == rhs.externalFormat )
+ && ( formatFeatures == rhs.formatFeatures )
+ && ( samplerYcbcrConversionComponents == rhs.samplerYcbcrConversionComponents )
+ && ( suggestedYcbcrModel == rhs.suggestedYcbcrModel )
+ && ( suggestedYcbcrRange == rhs.suggestedYcbcrRange )
+ && ( suggestedXChromaOffset == rhs.suggestedXChromaOffset )
+ && ( suggestedYChromaOffset == rhs.suggestedYChromaOffset );
+ }
+
+ bool operator!=( AndroidHardwareBufferFormatPropertiesANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAndroidHardwareBufferFormatPropertiesANDROID;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ uint64_t externalFormat = {};
+ VULKAN_HPP_NAMESPACE::FormatFeatureFlags formatFeatures = {};
+ VULKAN_HPP_NAMESPACE::ComponentMapping samplerYcbcrConversionComponents = {};
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrModelConversion suggestedYcbcrModel = VULKAN_HPP_NAMESPACE::SamplerYcbcrModelConversion::eRgbIdentity;
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrRange suggestedYcbcrRange = VULKAN_HPP_NAMESPACE::SamplerYcbcrRange::eItuFull;
+ VULKAN_HPP_NAMESPACE::ChromaLocation suggestedXChromaOffset = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven;
+ VULKAN_HPP_NAMESPACE::ChromaLocation suggestedYChromaOffset = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven;
+ };
+ static_assert( sizeof( AndroidHardwareBufferFormatPropertiesANDROID ) == sizeof( VkAndroidHardwareBufferFormatPropertiesANDROID ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AndroidHardwareBufferFormatPropertiesANDROID>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+
+ struct AndroidHardwareBufferPropertiesANDROID
+ {
+ AndroidHardwareBufferPropertiesANDROID( VULKAN_HPP_NAMESPACE::DeviceSize allocationSize_ = {},
+ uint32_t memoryTypeBits_ = {} ) VULKAN_HPP_NOEXCEPT
+ : allocationSize( allocationSize_ )
+ , memoryTypeBits( memoryTypeBits_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID & operator=( VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID ) - offsetof( AndroidHardwareBufferPropertiesANDROID, pNext ) );
+ return *this;
+ }
+
+ AndroidHardwareBufferPropertiesANDROID( VkAndroidHardwareBufferPropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AndroidHardwareBufferPropertiesANDROID& operator=( VkAndroidHardwareBufferPropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID const *>(&rhs);
+ return *this;
+ }
+
+ operator VkAndroidHardwareBufferPropertiesANDROID const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAndroidHardwareBufferPropertiesANDROID*>( this );
+ }
+
+ operator VkAndroidHardwareBufferPropertiesANDROID &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAndroidHardwareBufferPropertiesANDROID*>( this );
+ }
+
+ bool operator==( AndroidHardwareBufferPropertiesANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( allocationSize == rhs.allocationSize )
+ && ( memoryTypeBits == rhs.memoryTypeBits );
+ }
+
+ bool operator!=( AndroidHardwareBufferPropertiesANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAndroidHardwareBufferPropertiesANDROID;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize allocationSize = {};
+ uint32_t memoryTypeBits = {};
+ };
+ static_assert( sizeof( AndroidHardwareBufferPropertiesANDROID ) == sizeof( VkAndroidHardwareBufferPropertiesANDROID ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AndroidHardwareBufferPropertiesANDROID>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+
+ struct AndroidHardwareBufferUsageANDROID
+ {
+ AndroidHardwareBufferUsageANDROID( uint64_t androidHardwareBufferUsage_ = {} ) VULKAN_HPP_NOEXCEPT
+ : androidHardwareBufferUsage( androidHardwareBufferUsage_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AndroidHardwareBufferUsageANDROID & operator=( VULKAN_HPP_NAMESPACE::AndroidHardwareBufferUsageANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AndroidHardwareBufferUsageANDROID ) - offsetof( AndroidHardwareBufferUsageANDROID, pNext ) );
+ return *this;
+ }
+
+ AndroidHardwareBufferUsageANDROID( VkAndroidHardwareBufferUsageANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AndroidHardwareBufferUsageANDROID& operator=( VkAndroidHardwareBufferUsageANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferUsageANDROID const *>(&rhs);
+ return *this;
+ }
+
+ operator VkAndroidHardwareBufferUsageANDROID const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAndroidHardwareBufferUsageANDROID*>( this );
+ }
+
+ operator VkAndroidHardwareBufferUsageANDROID &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAndroidHardwareBufferUsageANDROID*>( this );
+ }
+
+ bool operator==( AndroidHardwareBufferUsageANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( androidHardwareBufferUsage == rhs.androidHardwareBufferUsage );
+ }
+
+ bool operator!=( AndroidHardwareBufferUsageANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAndroidHardwareBufferUsageANDROID;
+ void* pNext = {};
+ uint64_t androidHardwareBufferUsage = {};
+ };
+ static_assert( sizeof( AndroidHardwareBufferUsageANDROID ) == sizeof( VkAndroidHardwareBufferUsageANDROID ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AndroidHardwareBufferUsageANDROID>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+
+ struct AndroidSurfaceCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR AndroidSurfaceCreateInfoKHR( VULKAN_HPP_NAMESPACE::AndroidSurfaceCreateFlagsKHR flags_ = {},
+ struct ANativeWindow* window_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , window( window_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AndroidSurfaceCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::AndroidSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AndroidSurfaceCreateInfoKHR ) - offsetof( AndroidSurfaceCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ AndroidSurfaceCreateInfoKHR( VkAndroidSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AndroidSurfaceCreateInfoKHR& operator=( VkAndroidSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AndroidSurfaceCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ AndroidSurfaceCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ AndroidSurfaceCreateInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::AndroidSurfaceCreateFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ AndroidSurfaceCreateInfoKHR & setWindow( struct ANativeWindow* window_ ) VULKAN_HPP_NOEXCEPT
+ {
+ window = window_;
+ return *this;
+ }
+
+ operator VkAndroidSurfaceCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAndroidSurfaceCreateInfoKHR*>( this );
+ }
+
+ operator VkAndroidSurfaceCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAndroidSurfaceCreateInfoKHR*>( this );
+ }
+
+ bool operator==( AndroidSurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( window == rhs.window );
+ }
+
+ bool operator!=( AndroidSurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAndroidSurfaceCreateInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::AndroidSurfaceCreateFlagsKHR flags = {};
+ struct ANativeWindow* window = {};
+ };
+ static_assert( sizeof( AndroidSurfaceCreateInfoKHR ) == sizeof( VkAndroidSurfaceCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AndroidSurfaceCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ struct ApplicationInfo
+ {
+ VULKAN_HPP_CONSTEXPR ApplicationInfo( const char* pApplicationName_ = {},
+ uint32_t applicationVersion_ = {},
+ const char* pEngineName_ = {},
+ uint32_t engineVersion_ = {},
+ uint32_t apiVersion_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pApplicationName( pApplicationName_ )
+ , applicationVersion( applicationVersion_ )
+ , pEngineName( pEngineName_ )
+ , engineVersion( engineVersion_ )
+ , apiVersion( apiVersion_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ApplicationInfo & operator=( VULKAN_HPP_NAMESPACE::ApplicationInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ApplicationInfo ) - offsetof( ApplicationInfo, pNext ) );
+ return *this;
+ }
+
+ ApplicationInfo( VkApplicationInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ApplicationInfo& operator=( VkApplicationInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ApplicationInfo const *>(&rhs);
+ return *this;
+ }
+
+ ApplicationInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ApplicationInfo & setPApplicationName( const char* pApplicationName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pApplicationName = pApplicationName_;
+ return *this;
+ }
+
+ ApplicationInfo & setApplicationVersion( uint32_t applicationVersion_ ) VULKAN_HPP_NOEXCEPT
+ {
+ applicationVersion = applicationVersion_;
+ return *this;
+ }
+
+ ApplicationInfo & setPEngineName( const char* pEngineName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pEngineName = pEngineName_;
+ return *this;
+ }
+
+ ApplicationInfo & setEngineVersion( uint32_t engineVersion_ ) VULKAN_HPP_NOEXCEPT
+ {
+ engineVersion = engineVersion_;
+ return *this;
+ }
+
+ ApplicationInfo & setApiVersion( uint32_t apiVersion_ ) VULKAN_HPP_NOEXCEPT
+ {
+ apiVersion = apiVersion_;
+ return *this;
+ }
+
+ operator VkApplicationInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkApplicationInfo*>( this );
+ }
+
+ operator VkApplicationInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkApplicationInfo*>( this );
+ }
+
+ bool operator==( ApplicationInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pApplicationName == rhs.pApplicationName )
+ && ( applicationVersion == rhs.applicationVersion )
+ && ( pEngineName == rhs.pEngineName )
+ && ( engineVersion == rhs.engineVersion )
+ && ( apiVersion == rhs.apiVersion );
+ }
+
+ bool operator!=( ApplicationInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eApplicationInfo;
+ const void* pNext = {};
+ const char* pApplicationName = {};
+ uint32_t applicationVersion = {};
+ const char* pEngineName = {};
+ uint32_t engineVersion = {};
+ uint32_t apiVersion = {};
+ };
+ static_assert( sizeof( ApplicationInfo ) == sizeof( VkApplicationInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ApplicationInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct AttachmentDescription
+ {
+ VULKAN_HPP_CONSTEXPR AttachmentDescription( VULKAN_HPP_NAMESPACE::AttachmentDescriptionFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples_ = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1,
+ VULKAN_HPP_NAMESPACE::AttachmentLoadOp loadOp_ = VULKAN_HPP_NAMESPACE::AttachmentLoadOp::eLoad,
+ VULKAN_HPP_NAMESPACE::AttachmentStoreOp storeOp_ = VULKAN_HPP_NAMESPACE::AttachmentStoreOp::eStore,
+ VULKAN_HPP_NAMESPACE::AttachmentLoadOp stencilLoadOp_ = VULKAN_HPP_NAMESPACE::AttachmentLoadOp::eLoad,
+ VULKAN_HPP_NAMESPACE::AttachmentStoreOp stencilStoreOp_ = VULKAN_HPP_NAMESPACE::AttachmentStoreOp::eStore,
+ VULKAN_HPP_NAMESPACE::ImageLayout initialLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined,
+ VULKAN_HPP_NAMESPACE::ImageLayout finalLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , format( format_ )
+ , samples( samples_ )
+ , loadOp( loadOp_ )
+ , storeOp( storeOp_ )
+ , stencilLoadOp( stencilLoadOp_ )
+ , stencilStoreOp( stencilStoreOp_ )
+ , initialLayout( initialLayout_ )
+ , finalLayout( finalLayout_ )
+ {}
+
+ AttachmentDescription( VkAttachmentDescription const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AttachmentDescription& operator=( VkAttachmentDescription const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AttachmentDescription const *>(&rhs);
+ return *this;
+ }
+
+ AttachmentDescription & setFlags( VULKAN_HPP_NAMESPACE::AttachmentDescriptionFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ AttachmentDescription & setFormat( VULKAN_HPP_NAMESPACE::Format format_ ) VULKAN_HPP_NOEXCEPT
+ {
+ format = format_;
+ return *this;
+ }
+
+ AttachmentDescription & setSamples( VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples_ ) VULKAN_HPP_NOEXCEPT
+ {
+ samples = samples_;
+ return *this;
+ }
+
+ AttachmentDescription & setLoadOp( VULKAN_HPP_NAMESPACE::AttachmentLoadOp loadOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ loadOp = loadOp_;
+ return *this;
+ }
+
+ AttachmentDescription & setStoreOp( VULKAN_HPP_NAMESPACE::AttachmentStoreOp storeOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storeOp = storeOp_;
+ return *this;
+ }
+
+ AttachmentDescription & setStencilLoadOp( VULKAN_HPP_NAMESPACE::AttachmentLoadOp stencilLoadOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencilLoadOp = stencilLoadOp_;
+ return *this;
+ }
+
+ AttachmentDescription & setStencilStoreOp( VULKAN_HPP_NAMESPACE::AttachmentStoreOp stencilStoreOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencilStoreOp = stencilStoreOp_;
+ return *this;
+ }
+
+ AttachmentDescription & setInitialLayout( VULKAN_HPP_NAMESPACE::ImageLayout initialLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ initialLayout = initialLayout_;
+ return *this;
+ }
+
+ AttachmentDescription & setFinalLayout( VULKAN_HPP_NAMESPACE::ImageLayout finalLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ finalLayout = finalLayout_;
+ return *this;
+ }
+
+ operator VkAttachmentDescription const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAttachmentDescription*>( this );
+ }
+
+ operator VkAttachmentDescription &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAttachmentDescription*>( this );
+ }
+
+ bool operator==( AttachmentDescription const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( flags == rhs.flags )
+ && ( format == rhs.format )
+ && ( samples == rhs.samples )
+ && ( loadOp == rhs.loadOp )
+ && ( storeOp == rhs.storeOp )
+ && ( stencilLoadOp == rhs.stencilLoadOp )
+ && ( stencilStoreOp == rhs.stencilStoreOp )
+ && ( initialLayout == rhs.initialLayout )
+ && ( finalLayout == rhs.finalLayout );
+ }
+
+ bool operator!=( AttachmentDescription const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::AttachmentDescriptionFlags flags = {};
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1;
+ VULKAN_HPP_NAMESPACE::AttachmentLoadOp loadOp = VULKAN_HPP_NAMESPACE::AttachmentLoadOp::eLoad;
+ VULKAN_HPP_NAMESPACE::AttachmentStoreOp storeOp = VULKAN_HPP_NAMESPACE::AttachmentStoreOp::eStore;
+ VULKAN_HPP_NAMESPACE::AttachmentLoadOp stencilLoadOp = VULKAN_HPP_NAMESPACE::AttachmentLoadOp::eLoad;
+ VULKAN_HPP_NAMESPACE::AttachmentStoreOp stencilStoreOp = VULKAN_HPP_NAMESPACE::AttachmentStoreOp::eStore;
+ VULKAN_HPP_NAMESPACE::ImageLayout initialLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ VULKAN_HPP_NAMESPACE::ImageLayout finalLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ };
+ static_assert( sizeof( AttachmentDescription ) == sizeof( VkAttachmentDescription ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AttachmentDescription>::value, "struct wrapper is not a standard layout!" );
+
+ struct AttachmentDescription2
+ {
+ VULKAN_HPP_CONSTEXPR AttachmentDescription2( VULKAN_HPP_NAMESPACE::AttachmentDescriptionFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples_ = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1,
+ VULKAN_HPP_NAMESPACE::AttachmentLoadOp loadOp_ = VULKAN_HPP_NAMESPACE::AttachmentLoadOp::eLoad,
+ VULKAN_HPP_NAMESPACE::AttachmentStoreOp storeOp_ = VULKAN_HPP_NAMESPACE::AttachmentStoreOp::eStore,
+ VULKAN_HPP_NAMESPACE::AttachmentLoadOp stencilLoadOp_ = VULKAN_HPP_NAMESPACE::AttachmentLoadOp::eLoad,
+ VULKAN_HPP_NAMESPACE::AttachmentStoreOp stencilStoreOp_ = VULKAN_HPP_NAMESPACE::AttachmentStoreOp::eStore,
+ VULKAN_HPP_NAMESPACE::ImageLayout initialLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined,
+ VULKAN_HPP_NAMESPACE::ImageLayout finalLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , format( format_ )
+ , samples( samples_ )
+ , loadOp( loadOp_ )
+ , storeOp( storeOp_ )
+ , stencilLoadOp( stencilLoadOp_ )
+ , stencilStoreOp( stencilStoreOp_ )
+ , initialLayout( initialLayout_ )
+ , finalLayout( finalLayout_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AttachmentDescription2 & operator=( VULKAN_HPP_NAMESPACE::AttachmentDescription2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AttachmentDescription2 ) - offsetof( AttachmentDescription2, pNext ) );
+ return *this;
+ }
+
+ AttachmentDescription2( VkAttachmentDescription2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AttachmentDescription2& operator=( VkAttachmentDescription2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AttachmentDescription2 const *>(&rhs);
+ return *this;
+ }
+
+ AttachmentDescription2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ AttachmentDescription2 & setFlags( VULKAN_HPP_NAMESPACE::AttachmentDescriptionFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ AttachmentDescription2 & setFormat( VULKAN_HPP_NAMESPACE::Format format_ ) VULKAN_HPP_NOEXCEPT
+ {
+ format = format_;
+ return *this;
+ }
+
+ AttachmentDescription2 & setSamples( VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples_ ) VULKAN_HPP_NOEXCEPT
+ {
+ samples = samples_;
+ return *this;
+ }
+
+ AttachmentDescription2 & setLoadOp( VULKAN_HPP_NAMESPACE::AttachmentLoadOp loadOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ loadOp = loadOp_;
+ return *this;
+ }
+
+ AttachmentDescription2 & setStoreOp( VULKAN_HPP_NAMESPACE::AttachmentStoreOp storeOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storeOp = storeOp_;
+ return *this;
+ }
+
+ AttachmentDescription2 & setStencilLoadOp( VULKAN_HPP_NAMESPACE::AttachmentLoadOp stencilLoadOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencilLoadOp = stencilLoadOp_;
+ return *this;
+ }
+
+ AttachmentDescription2 & setStencilStoreOp( VULKAN_HPP_NAMESPACE::AttachmentStoreOp stencilStoreOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencilStoreOp = stencilStoreOp_;
+ return *this;
+ }
+
+ AttachmentDescription2 & setInitialLayout( VULKAN_HPP_NAMESPACE::ImageLayout initialLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ initialLayout = initialLayout_;
+ return *this;
+ }
+
+ AttachmentDescription2 & setFinalLayout( VULKAN_HPP_NAMESPACE::ImageLayout finalLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ finalLayout = finalLayout_;
+ return *this;
+ }
+
+ operator VkAttachmentDescription2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAttachmentDescription2*>( this );
+ }
+
+ operator VkAttachmentDescription2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAttachmentDescription2*>( this );
+ }
+
+ bool operator==( AttachmentDescription2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( format == rhs.format )
+ && ( samples == rhs.samples )
+ && ( loadOp == rhs.loadOp )
+ && ( storeOp == rhs.storeOp )
+ && ( stencilLoadOp == rhs.stencilLoadOp )
+ && ( stencilStoreOp == rhs.stencilStoreOp )
+ && ( initialLayout == rhs.initialLayout )
+ && ( finalLayout == rhs.finalLayout );
+ }
+
+ bool operator!=( AttachmentDescription2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAttachmentDescription2;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::AttachmentDescriptionFlags flags = {};
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1;
+ VULKAN_HPP_NAMESPACE::AttachmentLoadOp loadOp = VULKAN_HPP_NAMESPACE::AttachmentLoadOp::eLoad;
+ VULKAN_HPP_NAMESPACE::AttachmentStoreOp storeOp = VULKAN_HPP_NAMESPACE::AttachmentStoreOp::eStore;
+ VULKAN_HPP_NAMESPACE::AttachmentLoadOp stencilLoadOp = VULKAN_HPP_NAMESPACE::AttachmentLoadOp::eLoad;
+ VULKAN_HPP_NAMESPACE::AttachmentStoreOp stencilStoreOp = VULKAN_HPP_NAMESPACE::AttachmentStoreOp::eStore;
+ VULKAN_HPP_NAMESPACE::ImageLayout initialLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ VULKAN_HPP_NAMESPACE::ImageLayout finalLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ };
+ static_assert( sizeof( AttachmentDescription2 ) == sizeof( VkAttachmentDescription2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AttachmentDescription2>::value, "struct wrapper is not a standard layout!" );
+
+ struct AttachmentDescriptionStencilLayout
+ {
+ VULKAN_HPP_CONSTEXPR AttachmentDescriptionStencilLayout( VULKAN_HPP_NAMESPACE::ImageLayout stencilInitialLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined,
+ VULKAN_HPP_NAMESPACE::ImageLayout stencilFinalLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined ) VULKAN_HPP_NOEXCEPT
+ : stencilInitialLayout( stencilInitialLayout_ )
+ , stencilFinalLayout( stencilFinalLayout_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AttachmentDescriptionStencilLayout & operator=( VULKAN_HPP_NAMESPACE::AttachmentDescriptionStencilLayout const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AttachmentDescriptionStencilLayout ) - offsetof( AttachmentDescriptionStencilLayout, pNext ) );
+ return *this;
+ }
+
+ AttachmentDescriptionStencilLayout( VkAttachmentDescriptionStencilLayout const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AttachmentDescriptionStencilLayout& operator=( VkAttachmentDescriptionStencilLayout const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AttachmentDescriptionStencilLayout const *>(&rhs);
+ return *this;
+ }
+
+ AttachmentDescriptionStencilLayout & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ AttachmentDescriptionStencilLayout & setStencilInitialLayout( VULKAN_HPP_NAMESPACE::ImageLayout stencilInitialLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencilInitialLayout = stencilInitialLayout_;
+ return *this;
+ }
+
+ AttachmentDescriptionStencilLayout & setStencilFinalLayout( VULKAN_HPP_NAMESPACE::ImageLayout stencilFinalLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencilFinalLayout = stencilFinalLayout_;
+ return *this;
+ }
+
+ operator VkAttachmentDescriptionStencilLayout const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAttachmentDescriptionStencilLayout*>( this );
+ }
+
+ operator VkAttachmentDescriptionStencilLayout &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAttachmentDescriptionStencilLayout*>( this );
+ }
+
+ bool operator==( AttachmentDescriptionStencilLayout const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( stencilInitialLayout == rhs.stencilInitialLayout )
+ && ( stencilFinalLayout == rhs.stencilFinalLayout );
+ }
+
+ bool operator!=( AttachmentDescriptionStencilLayout const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAttachmentDescriptionStencilLayout;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageLayout stencilInitialLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ VULKAN_HPP_NAMESPACE::ImageLayout stencilFinalLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ };
+ static_assert( sizeof( AttachmentDescriptionStencilLayout ) == sizeof( VkAttachmentDescriptionStencilLayout ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AttachmentDescriptionStencilLayout>::value, "struct wrapper is not a standard layout!" );
+
+ struct AttachmentReference
+ {
+ VULKAN_HPP_CONSTEXPR AttachmentReference( uint32_t attachment_ = {},
+ VULKAN_HPP_NAMESPACE::ImageLayout layout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined ) VULKAN_HPP_NOEXCEPT
+ : attachment( attachment_ )
+ , layout( layout_ )
+ {}
+
+ AttachmentReference( VkAttachmentReference const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AttachmentReference& operator=( VkAttachmentReference const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AttachmentReference const *>(&rhs);
+ return *this;
+ }
+
+ AttachmentReference & setAttachment( uint32_t attachment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ attachment = attachment_;
+ return *this;
+ }
+
+ AttachmentReference & setLayout( VULKAN_HPP_NAMESPACE::ImageLayout layout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layout = layout_;
+ return *this;
+ }
+
+ operator VkAttachmentReference const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAttachmentReference*>( this );
+ }
+
+ operator VkAttachmentReference &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAttachmentReference*>( this );
+ }
+
+ bool operator==( AttachmentReference const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( attachment == rhs.attachment )
+ && ( layout == rhs.layout );
+ }
+
+ bool operator!=( AttachmentReference const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t attachment = {};
+ VULKAN_HPP_NAMESPACE::ImageLayout layout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ };
+ static_assert( sizeof( AttachmentReference ) == sizeof( VkAttachmentReference ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AttachmentReference>::value, "struct wrapper is not a standard layout!" );
+
+ struct AttachmentReference2
+ {
+ VULKAN_HPP_CONSTEXPR AttachmentReference2( uint32_t attachment_ = {},
+ VULKAN_HPP_NAMESPACE::ImageLayout layout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined,
+ VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ = {} ) VULKAN_HPP_NOEXCEPT
+ : attachment( attachment_ )
+ , layout( layout_ )
+ , aspectMask( aspectMask_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AttachmentReference2 & operator=( VULKAN_HPP_NAMESPACE::AttachmentReference2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AttachmentReference2 ) - offsetof( AttachmentReference2, pNext ) );
+ return *this;
+ }
+
+ AttachmentReference2( VkAttachmentReference2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AttachmentReference2& operator=( VkAttachmentReference2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AttachmentReference2 const *>(&rhs);
+ return *this;
+ }
+
+ AttachmentReference2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ AttachmentReference2 & setAttachment( uint32_t attachment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ attachment = attachment_;
+ return *this;
+ }
+
+ AttachmentReference2 & setLayout( VULKAN_HPP_NAMESPACE::ImageLayout layout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layout = layout_;
+ return *this;
+ }
+
+ AttachmentReference2 & setAspectMask( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ aspectMask = aspectMask_;
+ return *this;
+ }
+
+ operator VkAttachmentReference2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAttachmentReference2*>( this );
+ }
+
+ operator VkAttachmentReference2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAttachmentReference2*>( this );
+ }
+
+ bool operator==( AttachmentReference2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( attachment == rhs.attachment )
+ && ( layout == rhs.layout )
+ && ( aspectMask == rhs.aspectMask );
+ }
+
+ bool operator!=( AttachmentReference2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAttachmentReference2;
+ const void* pNext = {};
+ uint32_t attachment = {};
+ VULKAN_HPP_NAMESPACE::ImageLayout layout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask = {};
+ };
+ static_assert( sizeof( AttachmentReference2 ) == sizeof( VkAttachmentReference2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AttachmentReference2>::value, "struct wrapper is not a standard layout!" );
+
+ struct AttachmentReferenceStencilLayout
+ {
+ VULKAN_HPP_CONSTEXPR AttachmentReferenceStencilLayout( VULKAN_HPP_NAMESPACE::ImageLayout stencilLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined ) VULKAN_HPP_NOEXCEPT
+ : stencilLayout( stencilLayout_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::AttachmentReferenceStencilLayout & operator=( VULKAN_HPP_NAMESPACE::AttachmentReferenceStencilLayout const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::AttachmentReferenceStencilLayout ) - offsetof( AttachmentReferenceStencilLayout, pNext ) );
+ return *this;
+ }
+
+ AttachmentReferenceStencilLayout( VkAttachmentReferenceStencilLayout const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AttachmentReferenceStencilLayout& operator=( VkAttachmentReferenceStencilLayout const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AttachmentReferenceStencilLayout const *>(&rhs);
+ return *this;
+ }
+
+ AttachmentReferenceStencilLayout & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ AttachmentReferenceStencilLayout & setStencilLayout( VULKAN_HPP_NAMESPACE::ImageLayout stencilLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencilLayout = stencilLayout_;
+ return *this;
+ }
+
+ operator VkAttachmentReferenceStencilLayout const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAttachmentReferenceStencilLayout*>( this );
+ }
+
+ operator VkAttachmentReferenceStencilLayout &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAttachmentReferenceStencilLayout*>( this );
+ }
+
+ bool operator==( AttachmentReferenceStencilLayout const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( stencilLayout == rhs.stencilLayout );
+ }
+
+ bool operator!=( AttachmentReferenceStencilLayout const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAttachmentReferenceStencilLayout;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageLayout stencilLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ };
+ static_assert( sizeof( AttachmentReferenceStencilLayout ) == sizeof( VkAttachmentReferenceStencilLayout ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AttachmentReferenceStencilLayout>::value, "struct wrapper is not a standard layout!" );
+
+ struct Extent2D
+ {
+ VULKAN_HPP_CONSTEXPR Extent2D( uint32_t width_ = {},
+ uint32_t height_ = {} ) VULKAN_HPP_NOEXCEPT
+ : width( width_ )
+ , height( height_ )
+ {}
+
+ Extent2D( VkExtent2D const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ Extent2D& operator=( VkExtent2D const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::Extent2D const *>(&rhs);
+ return *this;
+ }
+
+ Extent2D & setWidth( uint32_t width_ ) VULKAN_HPP_NOEXCEPT
+ {
+ width = width_;
+ return *this;
+ }
+
+ Extent2D & setHeight( uint32_t height_ ) VULKAN_HPP_NOEXCEPT
+ {
+ height = height_;
+ return *this;
+ }
+
+ operator VkExtent2D const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExtent2D*>( this );
+ }
+
+ operator VkExtent2D &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExtent2D*>( this );
+ }
+
+ bool operator==( Extent2D const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( width == rhs.width )
+ && ( height == rhs.height );
+ }
+
+ bool operator!=( Extent2D const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t width = {};
+ uint32_t height = {};
+ };
+ static_assert( sizeof( Extent2D ) == sizeof( VkExtent2D ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<Extent2D>::value, "struct wrapper is not a standard layout!" );
+
+ struct SampleLocationEXT
+ {
+ VULKAN_HPP_CONSTEXPR SampleLocationEXT( float x_ = {},
+ float y_ = {} ) VULKAN_HPP_NOEXCEPT
+ : x( x_ )
+ , y( y_ )
+ {}
+
+ SampleLocationEXT( VkSampleLocationEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SampleLocationEXT& operator=( VkSampleLocationEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SampleLocationEXT const *>(&rhs);
+ return *this;
+ }
+
+ SampleLocationEXT & setX( float x_ ) VULKAN_HPP_NOEXCEPT
+ {
+ x = x_;
+ return *this;
+ }
+
+ SampleLocationEXT & setY( float y_ ) VULKAN_HPP_NOEXCEPT
+ {
+ y = y_;
+ return *this;
+ }
+
+ operator VkSampleLocationEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSampleLocationEXT*>( this );
+ }
+
+ operator VkSampleLocationEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSampleLocationEXT*>( this );
+ }
+
+ bool operator==( SampleLocationEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( x == rhs.x )
+ && ( y == rhs.y );
+ }
+
+ bool operator!=( SampleLocationEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ float x = {};
+ float y = {};
+ };
+ static_assert( sizeof( SampleLocationEXT ) == sizeof( VkSampleLocationEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SampleLocationEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct SampleLocationsInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR SampleLocationsInfoEXT( VULKAN_HPP_NAMESPACE::SampleCountFlagBits sampleLocationsPerPixel_ = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1,
+ VULKAN_HPP_NAMESPACE::Extent2D sampleLocationGridSize_ = {},
+ uint32_t sampleLocationsCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SampleLocationEXT* pSampleLocations_ = {} ) VULKAN_HPP_NOEXCEPT
+ : sampleLocationsPerPixel( sampleLocationsPerPixel_ )
+ , sampleLocationGridSize( sampleLocationGridSize_ )
+ , sampleLocationsCount( sampleLocationsCount_ )
+ , pSampleLocations( pSampleLocations_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT & operator=( VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT ) - offsetof( SampleLocationsInfoEXT, pNext ) );
+ return *this;
+ }
+
+ SampleLocationsInfoEXT( VkSampleLocationsInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SampleLocationsInfoEXT& operator=( VkSampleLocationsInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ SampleLocationsInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SampleLocationsInfoEXT & setSampleLocationsPerPixel( VULKAN_HPP_NAMESPACE::SampleCountFlagBits sampleLocationsPerPixel_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleLocationsPerPixel = sampleLocationsPerPixel_;
+ return *this;
+ }
+
+ SampleLocationsInfoEXT & setSampleLocationGridSize( VULKAN_HPP_NAMESPACE::Extent2D sampleLocationGridSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleLocationGridSize = sampleLocationGridSize_;
+ return *this;
+ }
+
+ SampleLocationsInfoEXT & setSampleLocationsCount( uint32_t sampleLocationsCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleLocationsCount = sampleLocationsCount_;
+ return *this;
+ }
+
+ SampleLocationsInfoEXT & setPSampleLocations( const VULKAN_HPP_NAMESPACE::SampleLocationEXT* pSampleLocations_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSampleLocations = pSampleLocations_;
+ return *this;
+ }
+
+ operator VkSampleLocationsInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSampleLocationsInfoEXT*>( this );
+ }
+
+ operator VkSampleLocationsInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSampleLocationsInfoEXT*>( this );
+ }
+
+ bool operator==( SampleLocationsInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( sampleLocationsPerPixel == rhs.sampleLocationsPerPixel )
+ && ( sampleLocationGridSize == rhs.sampleLocationGridSize )
+ && ( sampleLocationsCount == rhs.sampleLocationsCount )
+ && ( pSampleLocations == rhs.pSampleLocations );
+ }
+
+ bool operator!=( SampleLocationsInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSampleLocationsInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits sampleLocationsPerPixel = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1;
+ VULKAN_HPP_NAMESPACE::Extent2D sampleLocationGridSize = {};
+ uint32_t sampleLocationsCount = {};
+ const VULKAN_HPP_NAMESPACE::SampleLocationEXT* pSampleLocations = {};
+ };
+ static_assert( sizeof( SampleLocationsInfoEXT ) == sizeof( VkSampleLocationsInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SampleLocationsInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct AttachmentSampleLocationsEXT
+ {
+ VULKAN_HPP_CONSTEXPR AttachmentSampleLocationsEXT( uint32_t attachmentIndex_ = {},
+ VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT sampleLocationsInfo_ = {} ) VULKAN_HPP_NOEXCEPT
+ : attachmentIndex( attachmentIndex_ )
+ , sampleLocationsInfo( sampleLocationsInfo_ )
+ {}
+
+ AttachmentSampleLocationsEXT( VkAttachmentSampleLocationsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ AttachmentSampleLocationsEXT& operator=( VkAttachmentSampleLocationsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AttachmentSampleLocationsEXT const *>(&rhs);
+ return *this;
+ }
+
+ AttachmentSampleLocationsEXT & setAttachmentIndex( uint32_t attachmentIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ attachmentIndex = attachmentIndex_;
+ return *this;
+ }
+
+ AttachmentSampleLocationsEXT & setSampleLocationsInfo( VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT sampleLocationsInfo_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleLocationsInfo = sampleLocationsInfo_;
+ return *this;
+ }
+
+ operator VkAttachmentSampleLocationsEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkAttachmentSampleLocationsEXT*>( this );
+ }
+
+ operator VkAttachmentSampleLocationsEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkAttachmentSampleLocationsEXT*>( this );
+ }
+
+ bool operator==( AttachmentSampleLocationsEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( attachmentIndex == rhs.attachmentIndex )
+ && ( sampleLocationsInfo == rhs.sampleLocationsInfo );
+ }
+
+ bool operator!=( AttachmentSampleLocationsEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t attachmentIndex = {};
+ VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT sampleLocationsInfo = {};
+ };
+ static_assert( sizeof( AttachmentSampleLocationsEXT ) == sizeof( VkAttachmentSampleLocationsEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<AttachmentSampleLocationsEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct BaseInStructure
+ {
+ BaseInStructure() VULKAN_HPP_NOEXCEPT
+ {}
+
+ BaseInStructure( VkBaseInStructure const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BaseInStructure& operator=( VkBaseInStructure const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BaseInStructure const *>(&rhs);
+ return *this;
+ }
+
+ BaseInStructure & setPNext( const struct VULKAN_HPP_NAMESPACE::BaseInStructure* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ operator VkBaseInStructure const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBaseInStructure*>( this );
+ }
+
+ operator VkBaseInStructure &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBaseInStructure*>( this );
+ }
+
+ bool operator==( BaseInStructure const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext );
+ }
+
+ bool operator!=( BaseInStructure const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::StructureType sType = {};
+ const struct VULKAN_HPP_NAMESPACE::BaseInStructure* pNext = {};
+ };
+ static_assert( sizeof( BaseInStructure ) == sizeof( VkBaseInStructure ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BaseInStructure>::value, "struct wrapper is not a standard layout!" );
+
+ struct BaseOutStructure
+ {
+ BaseOutStructure() VULKAN_HPP_NOEXCEPT
+ {}
+
+ BaseOutStructure( VkBaseOutStructure const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BaseOutStructure& operator=( VkBaseOutStructure const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BaseOutStructure const *>(&rhs);
+ return *this;
+ }
+
+ BaseOutStructure & setPNext( struct VULKAN_HPP_NAMESPACE::BaseOutStructure* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ operator VkBaseOutStructure const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBaseOutStructure*>( this );
+ }
+
+ operator VkBaseOutStructure &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBaseOutStructure*>( this );
+ }
+
+ bool operator==( BaseOutStructure const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext );
+ }
+
+ bool operator!=( BaseOutStructure const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::StructureType sType = {};
+ struct VULKAN_HPP_NAMESPACE::BaseOutStructure* pNext = {};
+ };
+ static_assert( sizeof( BaseOutStructure ) == sizeof( VkBaseOutStructure ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BaseOutStructure>::value, "struct wrapper is not a standard layout!" );
+
+ struct BindAccelerationStructureMemoryInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR BindAccelerationStructureMemoryInfoNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ = {},
+ uint32_t deviceIndexCount_ = {},
+ const uint32_t* pDeviceIndices_ = {} ) VULKAN_HPP_NOEXCEPT
+ : accelerationStructure( accelerationStructure_ )
+ , memory( memory_ )
+ , memoryOffset( memoryOffset_ )
+ , deviceIndexCount( deviceIndexCount_ )
+ , pDeviceIndices( pDeviceIndices_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV & operator=( VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV ) - offsetof( BindAccelerationStructureMemoryInfoNV, pNext ) );
+ return *this;
+ }
+
+ BindAccelerationStructureMemoryInfoNV( VkBindAccelerationStructureMemoryInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BindAccelerationStructureMemoryInfoNV& operator=( VkBindAccelerationStructureMemoryInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ BindAccelerationStructureMemoryInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BindAccelerationStructureMemoryInfoNV & setAccelerationStructure( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure_ ) VULKAN_HPP_NOEXCEPT
+ {
+ accelerationStructure = accelerationStructure_;
+ return *this;
+ }
+
+ BindAccelerationStructureMemoryInfoNV & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memory = memory_;
+ return *this;
+ }
+
+ BindAccelerationStructureMemoryInfoNV & setMemoryOffset( VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memoryOffset = memoryOffset_;
+ return *this;
+ }
+
+ BindAccelerationStructureMemoryInfoNV & setDeviceIndexCount( uint32_t deviceIndexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceIndexCount = deviceIndexCount_;
+ return *this;
+ }
+
+ BindAccelerationStructureMemoryInfoNV & setPDeviceIndices( const uint32_t* pDeviceIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDeviceIndices = pDeviceIndices_;
+ return *this;
+ }
+
+ operator VkBindAccelerationStructureMemoryInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBindAccelerationStructureMemoryInfoNV*>( this );
+ }
+
+ operator VkBindAccelerationStructureMemoryInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBindAccelerationStructureMemoryInfoNV*>( this );
+ }
+
+ bool operator==( BindAccelerationStructureMemoryInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( accelerationStructure == rhs.accelerationStructure )
+ && ( memory == rhs.memory )
+ && ( memoryOffset == rhs.memoryOffset )
+ && ( deviceIndexCount == rhs.deviceIndexCount )
+ && ( pDeviceIndices == rhs.pDeviceIndices );
+ }
+
+ bool operator!=( BindAccelerationStructureMemoryInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBindAccelerationStructureMemoryInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure = {};
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset = {};
+ uint32_t deviceIndexCount = {};
+ const uint32_t* pDeviceIndices = {};
+ };
+ static_assert( sizeof( BindAccelerationStructureMemoryInfoNV ) == sizeof( VkBindAccelerationStructureMemoryInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BindAccelerationStructureMemoryInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct BindBufferMemoryDeviceGroupInfo
+ {
+ VULKAN_HPP_CONSTEXPR BindBufferMemoryDeviceGroupInfo( uint32_t deviceIndexCount_ = {},
+ const uint32_t* pDeviceIndices_ = {} ) VULKAN_HPP_NOEXCEPT
+ : deviceIndexCount( deviceIndexCount_ )
+ , pDeviceIndices( pDeviceIndices_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BindBufferMemoryDeviceGroupInfo & operator=( VULKAN_HPP_NAMESPACE::BindBufferMemoryDeviceGroupInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BindBufferMemoryDeviceGroupInfo ) - offsetof( BindBufferMemoryDeviceGroupInfo, pNext ) );
+ return *this;
+ }
+
+ BindBufferMemoryDeviceGroupInfo( VkBindBufferMemoryDeviceGroupInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BindBufferMemoryDeviceGroupInfo& operator=( VkBindBufferMemoryDeviceGroupInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindBufferMemoryDeviceGroupInfo const *>(&rhs);
+ return *this;
+ }
+
+ BindBufferMemoryDeviceGroupInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BindBufferMemoryDeviceGroupInfo & setDeviceIndexCount( uint32_t deviceIndexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceIndexCount = deviceIndexCount_;
+ return *this;
+ }
+
+ BindBufferMemoryDeviceGroupInfo & setPDeviceIndices( const uint32_t* pDeviceIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDeviceIndices = pDeviceIndices_;
+ return *this;
+ }
+
+ operator VkBindBufferMemoryDeviceGroupInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBindBufferMemoryDeviceGroupInfo*>( this );
+ }
+
+ operator VkBindBufferMemoryDeviceGroupInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBindBufferMemoryDeviceGroupInfo*>( this );
+ }
+
+ bool operator==( BindBufferMemoryDeviceGroupInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( deviceIndexCount == rhs.deviceIndexCount )
+ && ( pDeviceIndices == rhs.pDeviceIndices );
+ }
+
+ bool operator!=( BindBufferMemoryDeviceGroupInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBindBufferMemoryDeviceGroupInfo;
+ const void* pNext = {};
+ uint32_t deviceIndexCount = {};
+ const uint32_t* pDeviceIndices = {};
+ };
+ static_assert( sizeof( BindBufferMemoryDeviceGroupInfo ) == sizeof( VkBindBufferMemoryDeviceGroupInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BindBufferMemoryDeviceGroupInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct BindBufferMemoryInfo
+ {
+ VULKAN_HPP_CONSTEXPR BindBufferMemoryInfo( VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ = {} ) VULKAN_HPP_NOEXCEPT
+ : buffer( buffer_ )
+ , memory( memory_ )
+ , memoryOffset( memoryOffset_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo & operator=( VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo ) - offsetof( BindBufferMemoryInfo, pNext ) );
+ return *this;
+ }
+
+ BindBufferMemoryInfo( VkBindBufferMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BindBufferMemoryInfo& operator=( VkBindBufferMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo const *>(&rhs);
+ return *this;
+ }
+
+ BindBufferMemoryInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BindBufferMemoryInfo & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ BindBufferMemoryInfo & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memory = memory_;
+ return *this;
+ }
+
+ BindBufferMemoryInfo & setMemoryOffset( VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memoryOffset = memoryOffset_;
+ return *this;
+ }
+
+ operator VkBindBufferMemoryInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBindBufferMemoryInfo*>( this );
+ }
+
+ operator VkBindBufferMemoryInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBindBufferMemoryInfo*>( this );
+ }
+
+ bool operator==( BindBufferMemoryInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( buffer == rhs.buffer )
+ && ( memory == rhs.memory )
+ && ( memoryOffset == rhs.memoryOffset );
+ }
+
+ bool operator!=( BindBufferMemoryInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBindBufferMemoryInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset = {};
+ };
+ static_assert( sizeof( BindBufferMemoryInfo ) == sizeof( VkBindBufferMemoryInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BindBufferMemoryInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct Offset2D
+ {
+ VULKAN_HPP_CONSTEXPR Offset2D( int32_t x_ = {},
+ int32_t y_ = {} ) VULKAN_HPP_NOEXCEPT
+ : x( x_ )
+ , y( y_ )
+ {}
+
+ Offset2D( VkOffset2D const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ Offset2D& operator=( VkOffset2D const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::Offset2D const *>(&rhs);
+ return *this;
+ }
+
+ Offset2D & setX( int32_t x_ ) VULKAN_HPP_NOEXCEPT
+ {
+ x = x_;
+ return *this;
+ }
+
+ Offset2D & setY( int32_t y_ ) VULKAN_HPP_NOEXCEPT
+ {
+ y = y_;
+ return *this;
+ }
+
+ operator VkOffset2D const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkOffset2D*>( this );
+ }
+
+ operator VkOffset2D &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkOffset2D*>( this );
+ }
+
+ bool operator==( Offset2D const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( x == rhs.x )
+ && ( y == rhs.y );
+ }
+
+ bool operator!=( Offset2D const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ int32_t x = {};
+ int32_t y = {};
+ };
+ static_assert( sizeof( Offset2D ) == sizeof( VkOffset2D ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<Offset2D>::value, "struct wrapper is not a standard layout!" );
+
+ struct Rect2D
+ {
+ VULKAN_HPP_CONSTEXPR Rect2D( VULKAN_HPP_NAMESPACE::Offset2D offset_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D extent_ = {} ) VULKAN_HPP_NOEXCEPT
+ : offset( offset_ )
+ , extent( extent_ )
+ {}
+
+ Rect2D( VkRect2D const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ Rect2D& operator=( VkRect2D const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::Rect2D const *>(&rhs);
+ return *this;
+ }
+
+ Rect2D & setOffset( VULKAN_HPP_NAMESPACE::Offset2D offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ Rect2D & setExtent( VULKAN_HPP_NAMESPACE::Extent2D extent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ extent = extent_;
+ return *this;
+ }
+
+ operator VkRect2D const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRect2D*>( this );
+ }
+
+ operator VkRect2D &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRect2D*>( this );
+ }
+
+ bool operator==( Rect2D const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( offset == rhs.offset )
+ && ( extent == rhs.extent );
+ }
+
+ bool operator!=( Rect2D const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Offset2D offset = {};
+ VULKAN_HPP_NAMESPACE::Extent2D extent = {};
+ };
+ static_assert( sizeof( Rect2D ) == sizeof( VkRect2D ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<Rect2D>::value, "struct wrapper is not a standard layout!" );
+
+ struct BindImageMemoryDeviceGroupInfo
+ {
+ VULKAN_HPP_CONSTEXPR BindImageMemoryDeviceGroupInfo( uint32_t deviceIndexCount_ = {},
+ const uint32_t* pDeviceIndices_ = {},
+ uint32_t splitInstanceBindRegionCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Rect2D* pSplitInstanceBindRegions_ = {} ) VULKAN_HPP_NOEXCEPT
+ : deviceIndexCount( deviceIndexCount_ )
+ , pDeviceIndices( pDeviceIndices_ )
+ , splitInstanceBindRegionCount( splitInstanceBindRegionCount_ )
+ , pSplitInstanceBindRegions( pSplitInstanceBindRegions_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BindImageMemoryDeviceGroupInfo & operator=( VULKAN_HPP_NAMESPACE::BindImageMemoryDeviceGroupInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BindImageMemoryDeviceGroupInfo ) - offsetof( BindImageMemoryDeviceGroupInfo, pNext ) );
+ return *this;
+ }
+
+ BindImageMemoryDeviceGroupInfo( VkBindImageMemoryDeviceGroupInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BindImageMemoryDeviceGroupInfo& operator=( VkBindImageMemoryDeviceGroupInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindImageMemoryDeviceGroupInfo const *>(&rhs);
+ return *this;
+ }
+
+ BindImageMemoryDeviceGroupInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BindImageMemoryDeviceGroupInfo & setDeviceIndexCount( uint32_t deviceIndexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceIndexCount = deviceIndexCount_;
+ return *this;
+ }
+
+ BindImageMemoryDeviceGroupInfo & setPDeviceIndices( const uint32_t* pDeviceIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDeviceIndices = pDeviceIndices_;
+ return *this;
+ }
+
+ BindImageMemoryDeviceGroupInfo & setSplitInstanceBindRegionCount( uint32_t splitInstanceBindRegionCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ splitInstanceBindRegionCount = splitInstanceBindRegionCount_;
+ return *this;
+ }
+
+ BindImageMemoryDeviceGroupInfo & setPSplitInstanceBindRegions( const VULKAN_HPP_NAMESPACE::Rect2D* pSplitInstanceBindRegions_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSplitInstanceBindRegions = pSplitInstanceBindRegions_;
+ return *this;
+ }
+
+ operator VkBindImageMemoryDeviceGroupInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBindImageMemoryDeviceGroupInfo*>( this );
+ }
+
+ operator VkBindImageMemoryDeviceGroupInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBindImageMemoryDeviceGroupInfo*>( this );
+ }
+
+ bool operator==( BindImageMemoryDeviceGroupInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( deviceIndexCount == rhs.deviceIndexCount )
+ && ( pDeviceIndices == rhs.pDeviceIndices )
+ && ( splitInstanceBindRegionCount == rhs.splitInstanceBindRegionCount )
+ && ( pSplitInstanceBindRegions == rhs.pSplitInstanceBindRegions );
+ }
+
+ bool operator!=( BindImageMemoryDeviceGroupInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBindImageMemoryDeviceGroupInfo;
+ const void* pNext = {};
+ uint32_t deviceIndexCount = {};
+ const uint32_t* pDeviceIndices = {};
+ uint32_t splitInstanceBindRegionCount = {};
+ const VULKAN_HPP_NAMESPACE::Rect2D* pSplitInstanceBindRegions = {};
+ };
+ static_assert( sizeof( BindImageMemoryDeviceGroupInfo ) == sizeof( VkBindImageMemoryDeviceGroupInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BindImageMemoryDeviceGroupInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct BindImageMemoryInfo
+ {
+ VULKAN_HPP_CONSTEXPR BindImageMemoryInfo( VULKAN_HPP_NAMESPACE::Image image_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ = {} ) VULKAN_HPP_NOEXCEPT
+ : image( image_ )
+ , memory( memory_ )
+ , memoryOffset( memoryOffset_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BindImageMemoryInfo & operator=( VULKAN_HPP_NAMESPACE::BindImageMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BindImageMemoryInfo ) - offsetof( BindImageMemoryInfo, pNext ) );
+ return *this;
+ }
+
+ BindImageMemoryInfo( VkBindImageMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BindImageMemoryInfo& operator=( VkBindImageMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindImageMemoryInfo const *>(&rhs);
+ return *this;
+ }
+
+ BindImageMemoryInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BindImageMemoryInfo & setImage( VULKAN_HPP_NAMESPACE::Image image_ ) VULKAN_HPP_NOEXCEPT
+ {
+ image = image_;
+ return *this;
+ }
+
+ BindImageMemoryInfo & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memory = memory_;
+ return *this;
+ }
+
+ BindImageMemoryInfo & setMemoryOffset( VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memoryOffset = memoryOffset_;
+ return *this;
+ }
+
+ operator VkBindImageMemoryInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBindImageMemoryInfo*>( this );
+ }
+
+ operator VkBindImageMemoryInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBindImageMemoryInfo*>( this );
+ }
+
+ bool operator==( BindImageMemoryInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( image == rhs.image )
+ && ( memory == rhs.memory )
+ && ( memoryOffset == rhs.memoryOffset );
+ }
+
+ bool operator!=( BindImageMemoryInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBindImageMemoryInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Image image = {};
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset = {};
+ };
+ static_assert( sizeof( BindImageMemoryInfo ) == sizeof( VkBindImageMemoryInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BindImageMemoryInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct BindImageMemorySwapchainInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR BindImageMemorySwapchainInfoKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain_ = {},
+ uint32_t imageIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : swapchain( swapchain_ )
+ , imageIndex( imageIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BindImageMemorySwapchainInfoKHR & operator=( VULKAN_HPP_NAMESPACE::BindImageMemorySwapchainInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BindImageMemorySwapchainInfoKHR ) - offsetof( BindImageMemorySwapchainInfoKHR, pNext ) );
+ return *this;
+ }
+
+ BindImageMemorySwapchainInfoKHR( VkBindImageMemorySwapchainInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BindImageMemorySwapchainInfoKHR& operator=( VkBindImageMemorySwapchainInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindImageMemorySwapchainInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ BindImageMemorySwapchainInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BindImageMemorySwapchainInfoKHR & setSwapchain( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain_ ) VULKAN_HPP_NOEXCEPT
+ {
+ swapchain = swapchain_;
+ return *this;
+ }
+
+ BindImageMemorySwapchainInfoKHR & setImageIndex( uint32_t imageIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageIndex = imageIndex_;
+ return *this;
+ }
+
+ operator VkBindImageMemorySwapchainInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBindImageMemorySwapchainInfoKHR*>( this );
+ }
+
+ operator VkBindImageMemorySwapchainInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBindImageMemorySwapchainInfoKHR*>( this );
+ }
+
+ bool operator==( BindImageMemorySwapchainInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( swapchain == rhs.swapchain )
+ && ( imageIndex == rhs.imageIndex );
+ }
+
+ bool operator!=( BindImageMemorySwapchainInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBindImageMemorySwapchainInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain = {};
+ uint32_t imageIndex = {};
+ };
+ static_assert( sizeof( BindImageMemorySwapchainInfoKHR ) == sizeof( VkBindImageMemorySwapchainInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BindImageMemorySwapchainInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct BindImagePlaneMemoryInfo
+ {
+ VULKAN_HPP_CONSTEXPR BindImagePlaneMemoryInfo( VULKAN_HPP_NAMESPACE::ImageAspectFlagBits planeAspect_ = VULKAN_HPP_NAMESPACE::ImageAspectFlagBits::eColor ) VULKAN_HPP_NOEXCEPT
+ : planeAspect( planeAspect_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BindImagePlaneMemoryInfo & operator=( VULKAN_HPP_NAMESPACE::BindImagePlaneMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BindImagePlaneMemoryInfo ) - offsetof( BindImagePlaneMemoryInfo, pNext ) );
+ return *this;
+ }
+
+ BindImagePlaneMemoryInfo( VkBindImagePlaneMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BindImagePlaneMemoryInfo& operator=( VkBindImagePlaneMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindImagePlaneMemoryInfo const *>(&rhs);
+ return *this;
+ }
+
+ BindImagePlaneMemoryInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BindImagePlaneMemoryInfo & setPlaneAspect( VULKAN_HPP_NAMESPACE::ImageAspectFlagBits planeAspect_ ) VULKAN_HPP_NOEXCEPT
+ {
+ planeAspect = planeAspect_;
+ return *this;
+ }
+
+ operator VkBindImagePlaneMemoryInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBindImagePlaneMemoryInfo*>( this );
+ }
+
+ operator VkBindImagePlaneMemoryInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBindImagePlaneMemoryInfo*>( this );
+ }
+
+ bool operator==( BindImagePlaneMemoryInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( planeAspect == rhs.planeAspect );
+ }
+
+ bool operator!=( BindImagePlaneMemoryInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBindImagePlaneMemoryInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageAspectFlagBits planeAspect = VULKAN_HPP_NAMESPACE::ImageAspectFlagBits::eColor;
+ };
+ static_assert( sizeof( BindImagePlaneMemoryInfo ) == sizeof( VkBindImagePlaneMemoryInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BindImagePlaneMemoryInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SparseMemoryBind
+ {
+ VULKAN_HPP_CONSTEXPR SparseMemoryBind( VULKAN_HPP_NAMESPACE::DeviceSize resourceOffset_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize size_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ = {},
+ VULKAN_HPP_NAMESPACE::SparseMemoryBindFlags flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : resourceOffset( resourceOffset_ )
+ , size( size_ )
+ , memory( memory_ )
+ , memoryOffset( memoryOffset_ )
+ , flags( flags_ )
+ {}
+
+ SparseMemoryBind( VkSparseMemoryBind const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SparseMemoryBind& operator=( VkSparseMemoryBind const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SparseMemoryBind const *>(&rhs);
+ return *this;
+ }
+
+ SparseMemoryBind & setResourceOffset( VULKAN_HPP_NAMESPACE::DeviceSize resourceOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ resourceOffset = resourceOffset_;
+ return *this;
+ }
+
+ SparseMemoryBind & setSize( VULKAN_HPP_NAMESPACE::DeviceSize size_ ) VULKAN_HPP_NOEXCEPT
+ {
+ size = size_;
+ return *this;
+ }
+
+ SparseMemoryBind & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memory = memory_;
+ return *this;
+ }
+
+ SparseMemoryBind & setMemoryOffset( VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memoryOffset = memoryOffset_;
+ return *this;
+ }
+
+ SparseMemoryBind & setFlags( VULKAN_HPP_NAMESPACE::SparseMemoryBindFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ operator VkSparseMemoryBind const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSparseMemoryBind*>( this );
+ }
+
+ operator VkSparseMemoryBind &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSparseMemoryBind*>( this );
+ }
+
+ bool operator==( SparseMemoryBind const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( resourceOffset == rhs.resourceOffset )
+ && ( size == rhs.size )
+ && ( memory == rhs.memory )
+ && ( memoryOffset == rhs.memoryOffset )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( SparseMemoryBind const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DeviceSize resourceOffset = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize size = {};
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset = {};
+ VULKAN_HPP_NAMESPACE::SparseMemoryBindFlags flags = {};
+ };
+ static_assert( sizeof( SparseMemoryBind ) == sizeof( VkSparseMemoryBind ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SparseMemoryBind>::value, "struct wrapper is not a standard layout!" );
+
+ struct SparseBufferMemoryBindInfo
+ {
+ VULKAN_HPP_CONSTEXPR SparseBufferMemoryBindInfo( VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+ uint32_t bindCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SparseMemoryBind* pBinds_ = {} ) VULKAN_HPP_NOEXCEPT
+ : buffer( buffer_ )
+ , bindCount( bindCount_ )
+ , pBinds( pBinds_ )
+ {}
+
+ SparseBufferMemoryBindInfo( VkSparseBufferMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SparseBufferMemoryBindInfo& operator=( VkSparseBufferMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SparseBufferMemoryBindInfo const *>(&rhs);
+ return *this;
+ }
+
+ SparseBufferMemoryBindInfo & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ SparseBufferMemoryBindInfo & setBindCount( uint32_t bindCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bindCount = bindCount_;
+ return *this;
+ }
+
+ SparseBufferMemoryBindInfo & setPBinds( const VULKAN_HPP_NAMESPACE::SparseMemoryBind* pBinds_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pBinds = pBinds_;
+ return *this;
+ }
+
+ operator VkSparseBufferMemoryBindInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSparseBufferMemoryBindInfo*>( this );
+ }
+
+ operator VkSparseBufferMemoryBindInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSparseBufferMemoryBindInfo*>( this );
+ }
+
+ bool operator==( SparseBufferMemoryBindInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( buffer == rhs.buffer )
+ && ( bindCount == rhs.bindCount )
+ && ( pBinds == rhs.pBinds );
+ }
+
+ bool operator!=( SparseBufferMemoryBindInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ uint32_t bindCount = {};
+ const VULKAN_HPP_NAMESPACE::SparseMemoryBind* pBinds = {};
+ };
+ static_assert( sizeof( SparseBufferMemoryBindInfo ) == sizeof( VkSparseBufferMemoryBindInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SparseBufferMemoryBindInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SparseImageOpaqueMemoryBindInfo
+ {
+ VULKAN_HPP_CONSTEXPR SparseImageOpaqueMemoryBindInfo( VULKAN_HPP_NAMESPACE::Image image_ = {},
+ uint32_t bindCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SparseMemoryBind* pBinds_ = {} ) VULKAN_HPP_NOEXCEPT
+ : image( image_ )
+ , bindCount( bindCount_ )
+ , pBinds( pBinds_ )
+ {}
+
+ SparseImageOpaqueMemoryBindInfo( VkSparseImageOpaqueMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SparseImageOpaqueMemoryBindInfo& operator=( VkSparseImageOpaqueMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SparseImageOpaqueMemoryBindInfo const *>(&rhs);
+ return *this;
+ }
+
+ SparseImageOpaqueMemoryBindInfo & setImage( VULKAN_HPP_NAMESPACE::Image image_ ) VULKAN_HPP_NOEXCEPT
+ {
+ image = image_;
+ return *this;
+ }
+
+ SparseImageOpaqueMemoryBindInfo & setBindCount( uint32_t bindCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bindCount = bindCount_;
+ return *this;
+ }
+
+ SparseImageOpaqueMemoryBindInfo & setPBinds( const VULKAN_HPP_NAMESPACE::SparseMemoryBind* pBinds_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pBinds = pBinds_;
+ return *this;
+ }
+
+ operator VkSparseImageOpaqueMemoryBindInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSparseImageOpaqueMemoryBindInfo*>( this );
+ }
+
+ operator VkSparseImageOpaqueMemoryBindInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSparseImageOpaqueMemoryBindInfo*>( this );
+ }
+
+ bool operator==( SparseImageOpaqueMemoryBindInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( image == rhs.image )
+ && ( bindCount == rhs.bindCount )
+ && ( pBinds == rhs.pBinds );
+ }
+
+ bool operator!=( SparseImageOpaqueMemoryBindInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Image image = {};
+ uint32_t bindCount = {};
+ const VULKAN_HPP_NAMESPACE::SparseMemoryBind* pBinds = {};
+ };
+ static_assert( sizeof( SparseImageOpaqueMemoryBindInfo ) == sizeof( VkSparseImageOpaqueMemoryBindInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SparseImageOpaqueMemoryBindInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageSubresource
+ {
+ VULKAN_HPP_CONSTEXPR ImageSubresource( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ = {},
+ uint32_t mipLevel_ = {},
+ uint32_t arrayLayer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : aspectMask( aspectMask_ )
+ , mipLevel( mipLevel_ )
+ , arrayLayer( arrayLayer_ )
+ {}
+
+ ImageSubresource( VkImageSubresource const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageSubresource& operator=( VkImageSubresource const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageSubresource const *>(&rhs);
+ return *this;
+ }
+
+ ImageSubresource & setAspectMask( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ aspectMask = aspectMask_;
+ return *this;
+ }
+
+ ImageSubresource & setMipLevel( uint32_t mipLevel_ ) VULKAN_HPP_NOEXCEPT
+ {
+ mipLevel = mipLevel_;
+ return *this;
+ }
+
+ ImageSubresource & setArrayLayer( uint32_t arrayLayer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ arrayLayer = arrayLayer_;
+ return *this;
+ }
+
+ operator VkImageSubresource const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageSubresource*>( this );
+ }
+
+ operator VkImageSubresource &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageSubresource*>( this );
+ }
+
+ bool operator==( ImageSubresource const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( aspectMask == rhs.aspectMask )
+ && ( mipLevel == rhs.mipLevel )
+ && ( arrayLayer == rhs.arrayLayer );
+ }
+
+ bool operator!=( ImageSubresource const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask = {};
+ uint32_t mipLevel = {};
+ uint32_t arrayLayer = {};
+ };
+ static_assert( sizeof( ImageSubresource ) == sizeof( VkImageSubresource ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageSubresource>::value, "struct wrapper is not a standard layout!" );
+
+ struct Offset3D
+ {
+ VULKAN_HPP_CONSTEXPR Offset3D( int32_t x_ = {},
+ int32_t y_ = {},
+ int32_t z_ = {} ) VULKAN_HPP_NOEXCEPT
+ : x( x_ )
+ , y( y_ )
+ , z( z_ )
+ {}
+
+ explicit Offset3D( Offset2D const& offset2D,
+ int32_t z_ = {} )
+ : x( offset2D.x )
+ , y( offset2D.y )
+ , z( z_ )
+ {}
+
+ Offset3D( VkOffset3D const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ Offset3D& operator=( VkOffset3D const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::Offset3D const *>(&rhs);
+ return *this;
+ }
+
+ Offset3D & setX( int32_t x_ ) VULKAN_HPP_NOEXCEPT
+ {
+ x = x_;
+ return *this;
+ }
+
+ Offset3D & setY( int32_t y_ ) VULKAN_HPP_NOEXCEPT
+ {
+ y = y_;
+ return *this;
+ }
+
+ Offset3D & setZ( int32_t z_ ) VULKAN_HPP_NOEXCEPT
+ {
+ z = z_;
+ return *this;
+ }
+
+ operator VkOffset3D const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkOffset3D*>( this );
+ }
+
+ operator VkOffset3D &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkOffset3D*>( this );
+ }
+
+ bool operator==( Offset3D const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( x == rhs.x )
+ && ( y == rhs.y )
+ && ( z == rhs.z );
+ }
+
+ bool operator!=( Offset3D const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ int32_t x = {};
+ int32_t y = {};
+ int32_t z = {};
+ };
+ static_assert( sizeof( Offset3D ) == sizeof( VkOffset3D ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<Offset3D>::value, "struct wrapper is not a standard layout!" );
+
+ struct Extent3D
+ {
+ VULKAN_HPP_CONSTEXPR Extent3D( uint32_t width_ = {},
+ uint32_t height_ = {},
+ uint32_t depth_ = {} ) VULKAN_HPP_NOEXCEPT
+ : width( width_ )
+ , height( height_ )
+ , depth( depth_ )
+ {}
+
+ explicit Extent3D( Extent2D const& extent2D,
+ uint32_t depth_ = {} )
+ : width( extent2D.width )
+ , height( extent2D.height )
+ , depth( depth_ )
+ {}
+
+ Extent3D( VkExtent3D const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ Extent3D& operator=( VkExtent3D const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::Extent3D const *>(&rhs);
+ return *this;
+ }
+
+ Extent3D & setWidth( uint32_t width_ ) VULKAN_HPP_NOEXCEPT
+ {
+ width = width_;
+ return *this;
+ }
+
+ Extent3D & setHeight( uint32_t height_ ) VULKAN_HPP_NOEXCEPT
+ {
+ height = height_;
+ return *this;
+ }
+
+ Extent3D & setDepth( uint32_t depth_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depth = depth_;
+ return *this;
+ }
+
+ operator VkExtent3D const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExtent3D*>( this );
+ }
+
+ operator VkExtent3D &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExtent3D*>( this );
+ }
+
+ bool operator==( Extent3D const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( width == rhs.width )
+ && ( height == rhs.height )
+ && ( depth == rhs.depth );
+ }
+
+ bool operator!=( Extent3D const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t width = {};
+ uint32_t height = {};
+ uint32_t depth = {};
+ };
+ static_assert( sizeof( Extent3D ) == sizeof( VkExtent3D ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<Extent3D>::value, "struct wrapper is not a standard layout!" );
+
+ struct SparseImageMemoryBind
+ {
+ VULKAN_HPP_CONSTEXPR SparseImageMemoryBind( VULKAN_HPP_NAMESPACE::ImageSubresource subresource_ = {},
+ VULKAN_HPP_NAMESPACE::Offset3D offset_ = {},
+ VULKAN_HPP_NAMESPACE::Extent3D extent_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ = {},
+ VULKAN_HPP_NAMESPACE::SparseMemoryBindFlags flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : subresource( subresource_ )
+ , offset( offset_ )
+ , extent( extent_ )
+ , memory( memory_ )
+ , memoryOffset( memoryOffset_ )
+ , flags( flags_ )
+ {}
+
+ SparseImageMemoryBind( VkSparseImageMemoryBind const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SparseImageMemoryBind& operator=( VkSparseImageMemoryBind const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SparseImageMemoryBind const *>(&rhs);
+ return *this;
+ }
+
+ SparseImageMemoryBind & setSubresource( VULKAN_HPP_NAMESPACE::ImageSubresource subresource_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subresource = subresource_;
+ return *this;
+ }
+
+ SparseImageMemoryBind & setOffset( VULKAN_HPP_NAMESPACE::Offset3D offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ SparseImageMemoryBind & setExtent( VULKAN_HPP_NAMESPACE::Extent3D extent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ extent = extent_;
+ return *this;
+ }
+
+ SparseImageMemoryBind & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memory = memory_;
+ return *this;
+ }
+
+ SparseImageMemoryBind & setMemoryOffset( VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memoryOffset = memoryOffset_;
+ return *this;
+ }
+
+ SparseImageMemoryBind & setFlags( VULKAN_HPP_NAMESPACE::SparseMemoryBindFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ operator VkSparseImageMemoryBind const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSparseImageMemoryBind*>( this );
+ }
+
+ operator VkSparseImageMemoryBind &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSparseImageMemoryBind*>( this );
+ }
+
+ bool operator==( SparseImageMemoryBind const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( subresource == rhs.subresource )
+ && ( offset == rhs.offset )
+ && ( extent == rhs.extent )
+ && ( memory == rhs.memory )
+ && ( memoryOffset == rhs.memoryOffset )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( SparseImageMemoryBind const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ImageSubresource subresource = {};
+ VULKAN_HPP_NAMESPACE::Offset3D offset = {};
+ VULKAN_HPP_NAMESPACE::Extent3D extent = {};
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset = {};
+ VULKAN_HPP_NAMESPACE::SparseMemoryBindFlags flags = {};
+ };
+ static_assert( sizeof( SparseImageMemoryBind ) == sizeof( VkSparseImageMemoryBind ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SparseImageMemoryBind>::value, "struct wrapper is not a standard layout!" );
+
+ struct SparseImageMemoryBindInfo
+ {
+ VULKAN_HPP_CONSTEXPR SparseImageMemoryBindInfo( VULKAN_HPP_NAMESPACE::Image image_ = {},
+ uint32_t bindCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SparseImageMemoryBind* pBinds_ = {} ) VULKAN_HPP_NOEXCEPT
+ : image( image_ )
+ , bindCount( bindCount_ )
+ , pBinds( pBinds_ )
+ {}
+
+ SparseImageMemoryBindInfo( VkSparseImageMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SparseImageMemoryBindInfo& operator=( VkSparseImageMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SparseImageMemoryBindInfo const *>(&rhs);
+ return *this;
+ }
+
+ SparseImageMemoryBindInfo & setImage( VULKAN_HPP_NAMESPACE::Image image_ ) VULKAN_HPP_NOEXCEPT
+ {
+ image = image_;
+ return *this;
+ }
+
+ SparseImageMemoryBindInfo & setBindCount( uint32_t bindCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bindCount = bindCount_;
+ return *this;
+ }
+
+ SparseImageMemoryBindInfo & setPBinds( const VULKAN_HPP_NAMESPACE::SparseImageMemoryBind* pBinds_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pBinds = pBinds_;
+ return *this;
+ }
+
+ operator VkSparseImageMemoryBindInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSparseImageMemoryBindInfo*>( this );
+ }
+
+ operator VkSparseImageMemoryBindInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSparseImageMemoryBindInfo*>( this );
+ }
+
+ bool operator==( SparseImageMemoryBindInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( image == rhs.image )
+ && ( bindCount == rhs.bindCount )
+ && ( pBinds == rhs.pBinds );
+ }
+
+ bool operator!=( SparseImageMemoryBindInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Image image = {};
+ uint32_t bindCount = {};
+ const VULKAN_HPP_NAMESPACE::SparseImageMemoryBind* pBinds = {};
+ };
+ static_assert( sizeof( SparseImageMemoryBindInfo ) == sizeof( VkSparseImageMemoryBindInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SparseImageMemoryBindInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct BindSparseInfo
+ {
+ VULKAN_HPP_CONSTEXPR BindSparseInfo( uint32_t waitSemaphoreCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Semaphore* pWaitSemaphores_ = {},
+ uint32_t bufferBindCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SparseBufferMemoryBindInfo* pBufferBinds_ = {},
+ uint32_t imageOpaqueBindCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds_ = {},
+ uint32_t imageBindCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SparseImageMemoryBindInfo* pImageBinds_ = {},
+ uint32_t signalSemaphoreCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Semaphore* pSignalSemaphores_ = {} ) VULKAN_HPP_NOEXCEPT
+ : waitSemaphoreCount( waitSemaphoreCount_ )
+ , pWaitSemaphores( pWaitSemaphores_ )
+ , bufferBindCount( bufferBindCount_ )
+ , pBufferBinds( pBufferBinds_ )
+ , imageOpaqueBindCount( imageOpaqueBindCount_ )
+ , pImageOpaqueBinds( pImageOpaqueBinds_ )
+ , imageBindCount( imageBindCount_ )
+ , pImageBinds( pImageBinds_ )
+ , signalSemaphoreCount( signalSemaphoreCount_ )
+ , pSignalSemaphores( pSignalSemaphores_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BindSparseInfo & operator=( VULKAN_HPP_NAMESPACE::BindSparseInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BindSparseInfo ) - offsetof( BindSparseInfo, pNext ) );
+ return *this;
+ }
+
+ BindSparseInfo( VkBindSparseInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BindSparseInfo& operator=( VkBindSparseInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindSparseInfo const *>(&rhs);
+ return *this;
+ }
+
+ BindSparseInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BindSparseInfo & setWaitSemaphoreCount( uint32_t waitSemaphoreCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ waitSemaphoreCount = waitSemaphoreCount_;
+ return *this;
+ }
+
+ BindSparseInfo & setPWaitSemaphores( const VULKAN_HPP_NAMESPACE::Semaphore* pWaitSemaphores_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pWaitSemaphores = pWaitSemaphores_;
+ return *this;
+ }
+
+ BindSparseInfo & setBufferBindCount( uint32_t bufferBindCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferBindCount = bufferBindCount_;
+ return *this;
+ }
+
+ BindSparseInfo & setPBufferBinds( const VULKAN_HPP_NAMESPACE::SparseBufferMemoryBindInfo* pBufferBinds_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pBufferBinds = pBufferBinds_;
+ return *this;
+ }
+
+ BindSparseInfo & setImageOpaqueBindCount( uint32_t imageOpaqueBindCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageOpaqueBindCount = imageOpaqueBindCount_;
+ return *this;
+ }
+
+ BindSparseInfo & setPImageOpaqueBinds( const VULKAN_HPP_NAMESPACE::SparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pImageOpaqueBinds = pImageOpaqueBinds_;
+ return *this;
+ }
+
+ BindSparseInfo & setImageBindCount( uint32_t imageBindCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageBindCount = imageBindCount_;
+ return *this;
+ }
+
+ BindSparseInfo & setPImageBinds( const VULKAN_HPP_NAMESPACE::SparseImageMemoryBindInfo* pImageBinds_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pImageBinds = pImageBinds_;
+ return *this;
+ }
+
+ BindSparseInfo & setSignalSemaphoreCount( uint32_t signalSemaphoreCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ signalSemaphoreCount = signalSemaphoreCount_;
+ return *this;
+ }
+
+ BindSparseInfo & setPSignalSemaphores( const VULKAN_HPP_NAMESPACE::Semaphore* pSignalSemaphores_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSignalSemaphores = pSignalSemaphores_;
+ return *this;
+ }
+
+ operator VkBindSparseInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBindSparseInfo*>( this );
+ }
+
+ operator VkBindSparseInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBindSparseInfo*>( this );
+ }
+
+ bool operator==( BindSparseInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( waitSemaphoreCount == rhs.waitSemaphoreCount )
+ && ( pWaitSemaphores == rhs.pWaitSemaphores )
+ && ( bufferBindCount == rhs.bufferBindCount )
+ && ( pBufferBinds == rhs.pBufferBinds )
+ && ( imageOpaqueBindCount == rhs.imageOpaqueBindCount )
+ && ( pImageOpaqueBinds == rhs.pImageOpaqueBinds )
+ && ( imageBindCount == rhs.imageBindCount )
+ && ( pImageBinds == rhs.pImageBinds )
+ && ( signalSemaphoreCount == rhs.signalSemaphoreCount )
+ && ( pSignalSemaphores == rhs.pSignalSemaphores );
+ }
+
+ bool operator!=( BindSparseInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBindSparseInfo;
+ const void* pNext = {};
+ uint32_t waitSemaphoreCount = {};
+ const VULKAN_HPP_NAMESPACE::Semaphore* pWaitSemaphores = {};
+ uint32_t bufferBindCount = {};
+ const VULKAN_HPP_NAMESPACE::SparseBufferMemoryBindInfo* pBufferBinds = {};
+ uint32_t imageOpaqueBindCount = {};
+ const VULKAN_HPP_NAMESPACE::SparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds = {};
+ uint32_t imageBindCount = {};
+ const VULKAN_HPP_NAMESPACE::SparseImageMemoryBindInfo* pImageBinds = {};
+ uint32_t signalSemaphoreCount = {};
+ const VULKAN_HPP_NAMESPACE::Semaphore* pSignalSemaphores = {};
+ };
+ static_assert( sizeof( BindSparseInfo ) == sizeof( VkBindSparseInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BindSparseInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct BufferCopy
+ {
+ VULKAN_HPP_CONSTEXPR BufferCopy( VULKAN_HPP_NAMESPACE::DeviceSize srcOffset_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize dstOffset_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize size_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcOffset( srcOffset_ )
+ , dstOffset( dstOffset_ )
+ , size( size_ )
+ {}
+
+ BufferCopy( VkBufferCopy const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BufferCopy& operator=( VkBufferCopy const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BufferCopy const *>(&rhs);
+ return *this;
+ }
+
+ BufferCopy & setSrcOffset( VULKAN_HPP_NAMESPACE::DeviceSize srcOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcOffset = srcOffset_;
+ return *this;
+ }
+
+ BufferCopy & setDstOffset( VULKAN_HPP_NAMESPACE::DeviceSize dstOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstOffset = dstOffset_;
+ return *this;
+ }
+
+ BufferCopy & setSize( VULKAN_HPP_NAMESPACE::DeviceSize size_ ) VULKAN_HPP_NOEXCEPT
+ {
+ size = size_;
+ return *this;
+ }
+
+ operator VkBufferCopy const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBufferCopy*>( this );
+ }
+
+ operator VkBufferCopy &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBufferCopy*>( this );
+ }
+
+ bool operator==( BufferCopy const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( srcOffset == rhs.srcOffset )
+ && ( dstOffset == rhs.dstOffset )
+ && ( size == rhs.size );
+ }
+
+ bool operator!=( BufferCopy const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DeviceSize srcOffset = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize dstOffset = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize size = {};
+ };
+ static_assert( sizeof( BufferCopy ) == sizeof( VkBufferCopy ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BufferCopy>::value, "struct wrapper is not a standard layout!" );
+
+ struct BufferCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR BufferCreateInfo( VULKAN_HPP_NAMESPACE::BufferCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize size_ = {},
+ VULKAN_HPP_NAMESPACE::BufferUsageFlags usage_ = {},
+ VULKAN_HPP_NAMESPACE::SharingMode sharingMode_ = VULKAN_HPP_NAMESPACE::SharingMode::eExclusive,
+ uint32_t queueFamilyIndexCount_ = {},
+ const uint32_t* pQueueFamilyIndices_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , size( size_ )
+ , usage( usage_ )
+ , sharingMode( sharingMode_ )
+ , queueFamilyIndexCount( queueFamilyIndexCount_ )
+ , pQueueFamilyIndices( pQueueFamilyIndices_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BufferCreateInfo & operator=( VULKAN_HPP_NAMESPACE::BufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BufferCreateInfo ) - offsetof( BufferCreateInfo, pNext ) );
+ return *this;
+ }
+
+ BufferCreateInfo( VkBufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BufferCreateInfo& operator=( VkBufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BufferCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ BufferCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BufferCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::BufferCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ BufferCreateInfo & setSize( VULKAN_HPP_NAMESPACE::DeviceSize size_ ) VULKAN_HPP_NOEXCEPT
+ {
+ size = size_;
+ return *this;
+ }
+
+ BufferCreateInfo & setUsage( VULKAN_HPP_NAMESPACE::BufferUsageFlags usage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ usage = usage_;
+ return *this;
+ }
+
+ BufferCreateInfo & setSharingMode( VULKAN_HPP_NAMESPACE::SharingMode sharingMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sharingMode = sharingMode_;
+ return *this;
+ }
+
+ BufferCreateInfo & setQueueFamilyIndexCount( uint32_t queueFamilyIndexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueFamilyIndexCount = queueFamilyIndexCount_;
+ return *this;
+ }
+
+ BufferCreateInfo & setPQueueFamilyIndices( const uint32_t* pQueueFamilyIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pQueueFamilyIndices = pQueueFamilyIndices_;
+ return *this;
+ }
+
+ operator VkBufferCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBufferCreateInfo*>( this );
+ }
+
+ operator VkBufferCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBufferCreateInfo*>( this );
+ }
+
+ bool operator==( BufferCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( size == rhs.size )
+ && ( usage == rhs.usage )
+ && ( sharingMode == rhs.sharingMode )
+ && ( queueFamilyIndexCount == rhs.queueFamilyIndexCount )
+ && ( pQueueFamilyIndices == rhs.pQueueFamilyIndices );
+ }
+
+ bool operator!=( BufferCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBufferCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::BufferCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize size = {};
+ VULKAN_HPP_NAMESPACE::BufferUsageFlags usage = {};
+ VULKAN_HPP_NAMESPACE::SharingMode sharingMode = VULKAN_HPP_NAMESPACE::SharingMode::eExclusive;
+ uint32_t queueFamilyIndexCount = {};
+ const uint32_t* pQueueFamilyIndices = {};
+ };
+ static_assert( sizeof( BufferCreateInfo ) == sizeof( VkBufferCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BufferCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct BufferDeviceAddressCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR BufferDeviceAddressCreateInfoEXT( VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress_ = {} ) VULKAN_HPP_NOEXCEPT
+ : deviceAddress( deviceAddress_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BufferDeviceAddressCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::BufferDeviceAddressCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BufferDeviceAddressCreateInfoEXT ) - offsetof( BufferDeviceAddressCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ BufferDeviceAddressCreateInfoEXT( VkBufferDeviceAddressCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BufferDeviceAddressCreateInfoEXT& operator=( VkBufferDeviceAddressCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BufferDeviceAddressCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ BufferDeviceAddressCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BufferDeviceAddressCreateInfoEXT & setDeviceAddress( VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceAddress = deviceAddress_;
+ return *this;
+ }
+
+ operator VkBufferDeviceAddressCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBufferDeviceAddressCreateInfoEXT*>( this );
+ }
+
+ operator VkBufferDeviceAddressCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBufferDeviceAddressCreateInfoEXT*>( this );
+ }
+
+ bool operator==( BufferDeviceAddressCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( deviceAddress == rhs.deviceAddress );
+ }
+
+ bool operator!=( BufferDeviceAddressCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBufferDeviceAddressCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress = {};
+ };
+ static_assert( sizeof( BufferDeviceAddressCreateInfoEXT ) == sizeof( VkBufferDeviceAddressCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BufferDeviceAddressCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct BufferDeviceAddressInfo
+ {
+ VULKAN_HPP_CONSTEXPR BufferDeviceAddressInfo( VULKAN_HPP_NAMESPACE::Buffer buffer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : buffer( buffer_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo & operator=( VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo ) - offsetof( BufferDeviceAddressInfo, pNext ) );
+ return *this;
+ }
+
+ BufferDeviceAddressInfo( VkBufferDeviceAddressInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BufferDeviceAddressInfo& operator=( VkBufferDeviceAddressInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo const *>(&rhs);
+ return *this;
+ }
+
+ BufferDeviceAddressInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BufferDeviceAddressInfo & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ operator VkBufferDeviceAddressInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBufferDeviceAddressInfo*>( this );
+ }
+
+ operator VkBufferDeviceAddressInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBufferDeviceAddressInfo*>( this );
+ }
+
+ bool operator==( BufferDeviceAddressInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( buffer == rhs.buffer );
+ }
+
+ bool operator!=( BufferDeviceAddressInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBufferDeviceAddressInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ };
+ static_assert( sizeof( BufferDeviceAddressInfo ) == sizeof( VkBufferDeviceAddressInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BufferDeviceAddressInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageSubresourceLayers
+ {
+ VULKAN_HPP_CONSTEXPR ImageSubresourceLayers( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ = {},
+ uint32_t mipLevel_ = {},
+ uint32_t baseArrayLayer_ = {},
+ uint32_t layerCount_ = {} ) VULKAN_HPP_NOEXCEPT
+ : aspectMask( aspectMask_ )
+ , mipLevel( mipLevel_ )
+ , baseArrayLayer( baseArrayLayer_ )
+ , layerCount( layerCount_ )
+ {}
+
+ ImageSubresourceLayers( VkImageSubresourceLayers const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageSubresourceLayers& operator=( VkImageSubresourceLayers const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageSubresourceLayers const *>(&rhs);
+ return *this;
+ }
+
+ ImageSubresourceLayers & setAspectMask( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ aspectMask = aspectMask_;
+ return *this;
+ }
+
+ ImageSubresourceLayers & setMipLevel( uint32_t mipLevel_ ) VULKAN_HPP_NOEXCEPT
+ {
+ mipLevel = mipLevel_;
+ return *this;
+ }
+
+ ImageSubresourceLayers & setBaseArrayLayer( uint32_t baseArrayLayer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ baseArrayLayer = baseArrayLayer_;
+ return *this;
+ }
+
+ ImageSubresourceLayers & setLayerCount( uint32_t layerCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layerCount = layerCount_;
+ return *this;
+ }
+
+ operator VkImageSubresourceLayers const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageSubresourceLayers*>( this );
+ }
+
+ operator VkImageSubresourceLayers &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageSubresourceLayers*>( this );
+ }
+
+ bool operator==( ImageSubresourceLayers const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( aspectMask == rhs.aspectMask )
+ && ( mipLevel == rhs.mipLevel )
+ && ( baseArrayLayer == rhs.baseArrayLayer )
+ && ( layerCount == rhs.layerCount );
+ }
+
+ bool operator!=( ImageSubresourceLayers const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask = {};
+ uint32_t mipLevel = {};
+ uint32_t baseArrayLayer = {};
+ uint32_t layerCount = {};
+ };
+ static_assert( sizeof( ImageSubresourceLayers ) == sizeof( VkImageSubresourceLayers ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageSubresourceLayers>::value, "struct wrapper is not a standard layout!" );
+
+ struct BufferImageCopy
+ {
+ VULKAN_HPP_CONSTEXPR BufferImageCopy( VULKAN_HPP_NAMESPACE::DeviceSize bufferOffset_ = {},
+ uint32_t bufferRowLength_ = {},
+ uint32_t bufferImageHeight_ = {},
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers imageSubresource_ = {},
+ VULKAN_HPP_NAMESPACE::Offset3D imageOffset_ = {},
+ VULKAN_HPP_NAMESPACE::Extent3D imageExtent_ = {} ) VULKAN_HPP_NOEXCEPT
+ : bufferOffset( bufferOffset_ )
+ , bufferRowLength( bufferRowLength_ )
+ , bufferImageHeight( bufferImageHeight_ )
+ , imageSubresource( imageSubresource_ )
+ , imageOffset( imageOffset_ )
+ , imageExtent( imageExtent_ )
+ {}
+
+ BufferImageCopy( VkBufferImageCopy const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BufferImageCopy& operator=( VkBufferImageCopy const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BufferImageCopy const *>(&rhs);
+ return *this;
+ }
+
+ BufferImageCopy & setBufferOffset( VULKAN_HPP_NAMESPACE::DeviceSize bufferOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferOffset = bufferOffset_;
+ return *this;
+ }
+
+ BufferImageCopy & setBufferRowLength( uint32_t bufferRowLength_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferRowLength = bufferRowLength_;
+ return *this;
+ }
+
+ BufferImageCopy & setBufferImageHeight( uint32_t bufferImageHeight_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferImageHeight = bufferImageHeight_;
+ return *this;
+ }
+
+ BufferImageCopy & setImageSubresource( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers imageSubresource_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageSubresource = imageSubresource_;
+ return *this;
+ }
+
+ BufferImageCopy & setImageOffset( VULKAN_HPP_NAMESPACE::Offset3D imageOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageOffset = imageOffset_;
+ return *this;
+ }
+
+ BufferImageCopy & setImageExtent( VULKAN_HPP_NAMESPACE::Extent3D imageExtent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageExtent = imageExtent_;
+ return *this;
+ }
+
+ operator VkBufferImageCopy const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBufferImageCopy*>( this );
+ }
+
+ operator VkBufferImageCopy &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBufferImageCopy*>( this );
+ }
+
+ bool operator==( BufferImageCopy const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( bufferOffset == rhs.bufferOffset )
+ && ( bufferRowLength == rhs.bufferRowLength )
+ && ( bufferImageHeight == rhs.bufferImageHeight )
+ && ( imageSubresource == rhs.imageSubresource )
+ && ( imageOffset == rhs.imageOffset )
+ && ( imageExtent == rhs.imageExtent );
+ }
+
+ bool operator!=( BufferImageCopy const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DeviceSize bufferOffset = {};
+ uint32_t bufferRowLength = {};
+ uint32_t bufferImageHeight = {};
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers imageSubresource = {};
+ VULKAN_HPP_NAMESPACE::Offset3D imageOffset = {};
+ VULKAN_HPP_NAMESPACE::Extent3D imageExtent = {};
+ };
+ static_assert( sizeof( BufferImageCopy ) == sizeof( VkBufferImageCopy ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BufferImageCopy>::value, "struct wrapper is not a standard layout!" );
+
+ struct BufferMemoryBarrier
+ {
+ VULKAN_HPP_CONSTEXPR BufferMemoryBarrier( VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask_ = {},
+ VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask_ = {},
+ uint32_t srcQueueFamilyIndex_ = {},
+ uint32_t dstQueueFamilyIndex_ = {},
+ VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize size_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcAccessMask( srcAccessMask_ )
+ , dstAccessMask( dstAccessMask_ )
+ , srcQueueFamilyIndex( srcQueueFamilyIndex_ )
+ , dstQueueFamilyIndex( dstQueueFamilyIndex_ )
+ , buffer( buffer_ )
+ , offset( offset_ )
+ , size( size_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BufferMemoryBarrier & operator=( VULKAN_HPP_NAMESPACE::BufferMemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BufferMemoryBarrier ) - offsetof( BufferMemoryBarrier, pNext ) );
+ return *this;
+ }
+
+ BufferMemoryBarrier( VkBufferMemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BufferMemoryBarrier& operator=( VkBufferMemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BufferMemoryBarrier const *>(&rhs);
+ return *this;
+ }
+
+ BufferMemoryBarrier & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BufferMemoryBarrier & setSrcAccessMask( VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcAccessMask = srcAccessMask_;
+ return *this;
+ }
+
+ BufferMemoryBarrier & setDstAccessMask( VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstAccessMask = dstAccessMask_;
+ return *this;
+ }
+
+ BufferMemoryBarrier & setSrcQueueFamilyIndex( uint32_t srcQueueFamilyIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcQueueFamilyIndex = srcQueueFamilyIndex_;
+ return *this;
+ }
+
+ BufferMemoryBarrier & setDstQueueFamilyIndex( uint32_t dstQueueFamilyIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstQueueFamilyIndex = dstQueueFamilyIndex_;
+ return *this;
+ }
+
+ BufferMemoryBarrier & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ BufferMemoryBarrier & setOffset( VULKAN_HPP_NAMESPACE::DeviceSize offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ BufferMemoryBarrier & setSize( VULKAN_HPP_NAMESPACE::DeviceSize size_ ) VULKAN_HPP_NOEXCEPT
+ {
+ size = size_;
+ return *this;
+ }
+
+ operator VkBufferMemoryBarrier const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBufferMemoryBarrier*>( this );
+ }
+
+ operator VkBufferMemoryBarrier &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBufferMemoryBarrier*>( this );
+ }
+
+ bool operator==( BufferMemoryBarrier const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( srcAccessMask == rhs.srcAccessMask )
+ && ( dstAccessMask == rhs.dstAccessMask )
+ && ( srcQueueFamilyIndex == rhs.srcQueueFamilyIndex )
+ && ( dstQueueFamilyIndex == rhs.dstQueueFamilyIndex )
+ && ( buffer == rhs.buffer )
+ && ( offset == rhs.offset )
+ && ( size == rhs.size );
+ }
+
+ bool operator!=( BufferMemoryBarrier const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBufferMemoryBarrier;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask = {};
+ VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask = {};
+ uint32_t srcQueueFamilyIndex = {};
+ uint32_t dstQueueFamilyIndex = {};
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize size = {};
+ };
+ static_assert( sizeof( BufferMemoryBarrier ) == sizeof( VkBufferMemoryBarrier ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BufferMemoryBarrier>::value, "struct wrapper is not a standard layout!" );
+
+ struct BufferMemoryRequirementsInfo2
+ {
+ VULKAN_HPP_CONSTEXPR BufferMemoryRequirementsInfo2( VULKAN_HPP_NAMESPACE::Buffer buffer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : buffer( buffer_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BufferMemoryRequirementsInfo2 & operator=( VULKAN_HPP_NAMESPACE::BufferMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BufferMemoryRequirementsInfo2 ) - offsetof( BufferMemoryRequirementsInfo2, pNext ) );
+ return *this;
+ }
+
+ BufferMemoryRequirementsInfo2( VkBufferMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BufferMemoryRequirementsInfo2& operator=( VkBufferMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BufferMemoryRequirementsInfo2 const *>(&rhs);
+ return *this;
+ }
+
+ BufferMemoryRequirementsInfo2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BufferMemoryRequirementsInfo2 & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ operator VkBufferMemoryRequirementsInfo2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( this );
+ }
+
+ operator VkBufferMemoryRequirementsInfo2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBufferMemoryRequirementsInfo2*>( this );
+ }
+
+ bool operator==( BufferMemoryRequirementsInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( buffer == rhs.buffer );
+ }
+
+ bool operator!=( BufferMemoryRequirementsInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBufferMemoryRequirementsInfo2;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ };
+ static_assert( sizeof( BufferMemoryRequirementsInfo2 ) == sizeof( VkBufferMemoryRequirementsInfo2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BufferMemoryRequirementsInfo2>::value, "struct wrapper is not a standard layout!" );
+
+ struct BufferOpaqueCaptureAddressCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR BufferOpaqueCaptureAddressCreateInfo( uint64_t opaqueCaptureAddress_ = {} ) VULKAN_HPP_NOEXCEPT
+ : opaqueCaptureAddress( opaqueCaptureAddress_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BufferOpaqueCaptureAddressCreateInfo & operator=( VULKAN_HPP_NAMESPACE::BufferOpaqueCaptureAddressCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BufferOpaqueCaptureAddressCreateInfo ) - offsetof( BufferOpaqueCaptureAddressCreateInfo, pNext ) );
+ return *this;
+ }
+
+ BufferOpaqueCaptureAddressCreateInfo( VkBufferOpaqueCaptureAddressCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BufferOpaqueCaptureAddressCreateInfo& operator=( VkBufferOpaqueCaptureAddressCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BufferOpaqueCaptureAddressCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ BufferOpaqueCaptureAddressCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BufferOpaqueCaptureAddressCreateInfo & setOpaqueCaptureAddress( uint64_t opaqueCaptureAddress_ ) VULKAN_HPP_NOEXCEPT
+ {
+ opaqueCaptureAddress = opaqueCaptureAddress_;
+ return *this;
+ }
+
+ operator VkBufferOpaqueCaptureAddressCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBufferOpaqueCaptureAddressCreateInfo*>( this );
+ }
+
+ operator VkBufferOpaqueCaptureAddressCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBufferOpaqueCaptureAddressCreateInfo*>( this );
+ }
+
+ bool operator==( BufferOpaqueCaptureAddressCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( opaqueCaptureAddress == rhs.opaqueCaptureAddress );
+ }
+
+ bool operator!=( BufferOpaqueCaptureAddressCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBufferOpaqueCaptureAddressCreateInfo;
+ const void* pNext = {};
+ uint64_t opaqueCaptureAddress = {};
+ };
+ static_assert( sizeof( BufferOpaqueCaptureAddressCreateInfo ) == sizeof( VkBufferOpaqueCaptureAddressCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BufferOpaqueCaptureAddressCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct BufferViewCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR BufferViewCreateInfo( VULKAN_HPP_NAMESPACE::BufferViewCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+ VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize range_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , buffer( buffer_ )
+ , format( format_ )
+ , offset( offset_ )
+ , range( range_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::BufferViewCreateInfo & operator=( VULKAN_HPP_NAMESPACE::BufferViewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::BufferViewCreateInfo ) - offsetof( BufferViewCreateInfo, pNext ) );
+ return *this;
+ }
+
+ BufferViewCreateInfo( VkBufferViewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ BufferViewCreateInfo& operator=( VkBufferViewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BufferViewCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ BufferViewCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ BufferViewCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::BufferViewCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ BufferViewCreateInfo & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ BufferViewCreateInfo & setFormat( VULKAN_HPP_NAMESPACE::Format format_ ) VULKAN_HPP_NOEXCEPT
+ {
+ format = format_;
+ return *this;
+ }
+
+ BufferViewCreateInfo & setOffset( VULKAN_HPP_NAMESPACE::DeviceSize offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ BufferViewCreateInfo & setRange( VULKAN_HPP_NAMESPACE::DeviceSize range_ ) VULKAN_HPP_NOEXCEPT
+ {
+ range = range_;
+ return *this;
+ }
+
+ operator VkBufferViewCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkBufferViewCreateInfo*>( this );
+ }
+
+ operator VkBufferViewCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkBufferViewCreateInfo*>( this );
+ }
+
+ bool operator==( BufferViewCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( buffer == rhs.buffer )
+ && ( format == rhs.format )
+ && ( offset == rhs.offset )
+ && ( range == rhs.range );
+ }
+
+ bool operator!=( BufferViewCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBufferViewCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::BufferViewCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize range = {};
+ };
+ static_assert( sizeof( BufferViewCreateInfo ) == sizeof( VkBufferViewCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<BufferViewCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct CalibratedTimestampInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR CalibratedTimestampInfoEXT( VULKAN_HPP_NAMESPACE::TimeDomainEXT timeDomain_ = VULKAN_HPP_NAMESPACE::TimeDomainEXT::eDevice ) VULKAN_HPP_NOEXCEPT
+ : timeDomain( timeDomain_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CalibratedTimestampInfoEXT & operator=( VULKAN_HPP_NAMESPACE::CalibratedTimestampInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CalibratedTimestampInfoEXT ) - offsetof( CalibratedTimestampInfoEXT, pNext ) );
+ return *this;
+ }
+
+ CalibratedTimestampInfoEXT( VkCalibratedTimestampInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CalibratedTimestampInfoEXT& operator=( VkCalibratedTimestampInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CalibratedTimestampInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ CalibratedTimestampInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ CalibratedTimestampInfoEXT & setTimeDomain( VULKAN_HPP_NAMESPACE::TimeDomainEXT timeDomain_ ) VULKAN_HPP_NOEXCEPT
+ {
+ timeDomain = timeDomain_;
+ return *this;
+ }
+
+ operator VkCalibratedTimestampInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCalibratedTimestampInfoEXT*>( this );
+ }
+
+ operator VkCalibratedTimestampInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCalibratedTimestampInfoEXT*>( this );
+ }
+
+ bool operator==( CalibratedTimestampInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( timeDomain == rhs.timeDomain );
+ }
+
+ bool operator!=( CalibratedTimestampInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCalibratedTimestampInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::TimeDomainEXT timeDomain = VULKAN_HPP_NAMESPACE::TimeDomainEXT::eDevice;
+ };
+ static_assert( sizeof( CalibratedTimestampInfoEXT ) == sizeof( VkCalibratedTimestampInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CalibratedTimestampInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct CheckpointDataNV
+ {
+ CheckpointDataNV( VULKAN_HPP_NAMESPACE::PipelineStageFlagBits stage_ = VULKAN_HPP_NAMESPACE::PipelineStageFlagBits::eTopOfPipe,
+ void* pCheckpointMarker_ = {} ) VULKAN_HPP_NOEXCEPT
+ : stage( stage_ )
+ , pCheckpointMarker( pCheckpointMarker_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CheckpointDataNV & operator=( VULKAN_HPP_NAMESPACE::CheckpointDataNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CheckpointDataNV ) - offsetof( CheckpointDataNV, pNext ) );
+ return *this;
+ }
+
+ CheckpointDataNV( VkCheckpointDataNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CheckpointDataNV& operator=( VkCheckpointDataNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CheckpointDataNV const *>(&rhs);
+ return *this;
+ }
+
+ operator VkCheckpointDataNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCheckpointDataNV*>( this );
+ }
+
+ operator VkCheckpointDataNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCheckpointDataNV*>( this );
+ }
+
+ bool operator==( CheckpointDataNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( stage == rhs.stage )
+ && ( pCheckpointMarker == rhs.pCheckpointMarker );
+ }
+
+ bool operator!=( CheckpointDataNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCheckpointDataNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineStageFlagBits stage = VULKAN_HPP_NAMESPACE::PipelineStageFlagBits::eTopOfPipe;
+ void* pCheckpointMarker = {};
+ };
+ static_assert( sizeof( CheckpointDataNV ) == sizeof( VkCheckpointDataNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CheckpointDataNV>::value, "struct wrapper is not a standard layout!" );
+
+ union ClearColorValue
+ {
+ ClearColorValue( const std::array<float,4>& float32_ = {} )
+ {
+ memcpy( float32, float32_.data(), 4 * sizeof( float ) );
+ }
+
+ ClearColorValue( const std::array<int32_t,4>& int32_ )
+ {
+ memcpy( int32, int32_.data(), 4 * sizeof( int32_t ) );
+ }
+
+ ClearColorValue( const std::array<uint32_t,4>& uint32_ )
+ {
+ memcpy( uint32, uint32_.data(), 4 * sizeof( uint32_t ) );
+ }
+
+ ClearColorValue & setFloat32( std::array<float,4> float32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( float32, float32_.data(), 4 * sizeof( float ) );
+ return *this;
+ }
+
+ ClearColorValue & setInt32( std::array<int32_t,4> int32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( int32, int32_.data(), 4 * sizeof( int32_t ) );
+ return *this;
+ }
+
+ ClearColorValue & setUint32( std::array<uint32_t,4> uint32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( uint32, uint32_.data(), 4 * sizeof( uint32_t ) );
+ return *this;
+ }
+
+ VULKAN_HPP_NAMESPACE::ClearColorValue & operator=( VULKAN_HPP_NAMESPACE::ClearColorValue const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( this, &rhs, sizeof( VULKAN_HPP_NAMESPACE::ClearColorValue ) );
+ return *this;
+ }
+
+ operator VkClearColorValue const&() const
+ {
+ return *reinterpret_cast<const VkClearColorValue*>(this);
+ }
+
+ operator VkClearColorValue &()
+ {
+ return *reinterpret_cast<VkClearColorValue*>(this);
+ }
+
+ float float32[4];
+ int32_t int32[4];
+ uint32_t uint32[4];
+ };
+
+ struct ClearDepthStencilValue
+ {
+ VULKAN_HPP_CONSTEXPR ClearDepthStencilValue( float depth_ = {},
+ uint32_t stencil_ = {} ) VULKAN_HPP_NOEXCEPT
+ : depth( depth_ )
+ , stencil( stencil_ )
+ {}
+
+ ClearDepthStencilValue( VkClearDepthStencilValue const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ClearDepthStencilValue& operator=( VkClearDepthStencilValue const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ClearDepthStencilValue const *>(&rhs);
+ return *this;
+ }
+
+ ClearDepthStencilValue & setDepth( float depth_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depth = depth_;
+ return *this;
+ }
+
+ ClearDepthStencilValue & setStencil( uint32_t stencil_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencil = stencil_;
+ return *this;
+ }
+
+ operator VkClearDepthStencilValue const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkClearDepthStencilValue*>( this );
+ }
+
+ operator VkClearDepthStencilValue &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkClearDepthStencilValue*>( this );
+ }
+
+ bool operator==( ClearDepthStencilValue const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( depth == rhs.depth )
+ && ( stencil == rhs.stencil );
+ }
+
+ bool operator!=( ClearDepthStencilValue const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ float depth = {};
+ uint32_t stencil = {};
+ };
+ static_assert( sizeof( ClearDepthStencilValue ) == sizeof( VkClearDepthStencilValue ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ClearDepthStencilValue>::value, "struct wrapper is not a standard layout!" );
+
+ union ClearValue
+ {
+ ClearValue( VULKAN_HPP_NAMESPACE::ClearColorValue color_ = {} )
+ {
+ color = color_;
+ }
+
+ ClearValue( VULKAN_HPP_NAMESPACE::ClearDepthStencilValue depthStencil_ )
+ {
+ depthStencil = depthStencil_;
+ }
+
+ ClearValue & setColor( VULKAN_HPP_NAMESPACE::ClearColorValue color_ ) VULKAN_HPP_NOEXCEPT
+ {
+ color = color_;
+ return *this;
+ }
+
+ ClearValue & setDepthStencil( VULKAN_HPP_NAMESPACE::ClearDepthStencilValue depthStencil_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthStencil = depthStencil_;
+ return *this;
+ }
+
+ VULKAN_HPP_NAMESPACE::ClearValue & operator=( VULKAN_HPP_NAMESPACE::ClearValue const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( this, &rhs, sizeof( VULKAN_HPP_NAMESPACE::ClearValue ) );
+ return *this;
+ }
+
+ operator VkClearValue const&() const
+ {
+ return *reinterpret_cast<const VkClearValue*>(this);
+ }
+
+ operator VkClearValue &()
+ {
+ return *reinterpret_cast<VkClearValue*>(this);
+ }
+
+#ifdef VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
+ VULKAN_HPP_NAMESPACE::ClearColorValue color;
+ VULKAN_HPP_NAMESPACE::ClearDepthStencilValue depthStencil;
+#else
+ VkClearColorValue color;
+ VkClearDepthStencilValue depthStencil;
+#endif /*VULKAN_HPP_HAS_UNRESTRICTED_UNIONS*/
+ };
+
+ struct ClearAttachment
+ {
+ ClearAttachment( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ = {},
+ uint32_t colorAttachment_ = {},
+ VULKAN_HPP_NAMESPACE::ClearValue clearValue_ = {} ) VULKAN_HPP_NOEXCEPT
+ : aspectMask( aspectMask_ )
+ , colorAttachment( colorAttachment_ )
+ , clearValue( clearValue_ )
+ {}
+
+ ClearAttachment( VkClearAttachment const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ClearAttachment& operator=( VkClearAttachment const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ClearAttachment const *>(&rhs);
+ return *this;
+ }
+
+ ClearAttachment & setAspectMask( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ aspectMask = aspectMask_;
+ return *this;
+ }
+
+ ClearAttachment & setColorAttachment( uint32_t colorAttachment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ colorAttachment = colorAttachment_;
+ return *this;
+ }
+
+ ClearAttachment & setClearValue( VULKAN_HPP_NAMESPACE::ClearValue clearValue_ ) VULKAN_HPP_NOEXCEPT
+ {
+ clearValue = clearValue_;
+ return *this;
+ }
+
+ operator VkClearAttachment const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkClearAttachment*>( this );
+ }
+
+ operator VkClearAttachment &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkClearAttachment*>( this );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask = {};
+ uint32_t colorAttachment = {};
+ VULKAN_HPP_NAMESPACE::ClearValue clearValue = {};
+ };
+ static_assert( sizeof( ClearAttachment ) == sizeof( VkClearAttachment ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ClearAttachment>::value, "struct wrapper is not a standard layout!" );
+
+ struct ClearRect
+ {
+ VULKAN_HPP_CONSTEXPR ClearRect( VULKAN_HPP_NAMESPACE::Rect2D rect_ = {},
+ uint32_t baseArrayLayer_ = {},
+ uint32_t layerCount_ = {} ) VULKAN_HPP_NOEXCEPT
+ : rect( rect_ )
+ , baseArrayLayer( baseArrayLayer_ )
+ , layerCount( layerCount_ )
+ {}
+
+ ClearRect( VkClearRect const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ClearRect& operator=( VkClearRect const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ClearRect const *>(&rhs);
+ return *this;
+ }
+
+ ClearRect & setRect( VULKAN_HPP_NAMESPACE::Rect2D rect_ ) VULKAN_HPP_NOEXCEPT
+ {
+ rect = rect_;
+ return *this;
+ }
+
+ ClearRect & setBaseArrayLayer( uint32_t baseArrayLayer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ baseArrayLayer = baseArrayLayer_;
+ return *this;
+ }
+
+ ClearRect & setLayerCount( uint32_t layerCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layerCount = layerCount_;
+ return *this;
+ }
+
+ operator VkClearRect const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkClearRect*>( this );
+ }
+
+ operator VkClearRect &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkClearRect*>( this );
+ }
+
+ bool operator==( ClearRect const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( rect == rhs.rect )
+ && ( baseArrayLayer == rhs.baseArrayLayer )
+ && ( layerCount == rhs.layerCount );
+ }
+
+ bool operator!=( ClearRect const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Rect2D rect = {};
+ uint32_t baseArrayLayer = {};
+ uint32_t layerCount = {};
+ };
+ static_assert( sizeof( ClearRect ) == sizeof( VkClearRect ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ClearRect>::value, "struct wrapper is not a standard layout!" );
+
+ struct IndirectCommandsTokenNVX
+ {
+ VULKAN_HPP_CONSTEXPR IndirectCommandsTokenNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType_ = VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX::ePipeline,
+ VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {} ) VULKAN_HPP_NOEXCEPT
+ : tokenType( tokenType_ )
+ , buffer( buffer_ )
+ , offset( offset_ )
+ {}
+
+ IndirectCommandsTokenNVX( VkIndirectCommandsTokenNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ IndirectCommandsTokenNVX& operator=( VkIndirectCommandsTokenNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::IndirectCommandsTokenNVX const *>(&rhs);
+ return *this;
+ }
+
+ IndirectCommandsTokenNVX & setTokenType( VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tokenType = tokenType_;
+ return *this;
+ }
+
+ IndirectCommandsTokenNVX & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ IndirectCommandsTokenNVX & setOffset( VULKAN_HPP_NAMESPACE::DeviceSize offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ operator VkIndirectCommandsTokenNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkIndirectCommandsTokenNVX*>( this );
+ }
+
+ operator VkIndirectCommandsTokenNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkIndirectCommandsTokenNVX*>( this );
+ }
+
+ bool operator==( IndirectCommandsTokenNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( tokenType == rhs.tokenType )
+ && ( buffer == rhs.buffer )
+ && ( offset == rhs.offset );
+ }
+
+ bool operator!=( IndirectCommandsTokenNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType = VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX::ePipeline;
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
+ };
+ static_assert( sizeof( IndirectCommandsTokenNVX ) == sizeof( VkIndirectCommandsTokenNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<IndirectCommandsTokenNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct CmdProcessCommandsInfoNVX
+ {
+ VULKAN_HPP_CONSTEXPR CmdProcessCommandsInfoNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable_ = {},
+ VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout_ = {},
+ uint32_t indirectCommandsTokenCount_ = {},
+ const VULKAN_HPP_NAMESPACE::IndirectCommandsTokenNVX* pIndirectCommandsTokens_ = {},
+ uint32_t maxSequencesCount_ = {},
+ VULKAN_HPP_NAMESPACE::CommandBuffer targetCommandBuffer_ = {},
+ VULKAN_HPP_NAMESPACE::Buffer sequencesCountBuffer_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize sequencesCountOffset_ = {},
+ VULKAN_HPP_NAMESPACE::Buffer sequencesIndexBuffer_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize sequencesIndexOffset_ = {} ) VULKAN_HPP_NOEXCEPT
+ : objectTable( objectTable_ )
+ , indirectCommandsLayout( indirectCommandsLayout_ )
+ , indirectCommandsTokenCount( indirectCommandsTokenCount_ )
+ , pIndirectCommandsTokens( pIndirectCommandsTokens_ )
+ , maxSequencesCount( maxSequencesCount_ )
+ , targetCommandBuffer( targetCommandBuffer_ )
+ , sequencesCountBuffer( sequencesCountBuffer_ )
+ , sequencesCountOffset( sequencesCountOffset_ )
+ , sequencesIndexBuffer( sequencesIndexBuffer_ )
+ , sequencesIndexOffset( sequencesIndexOffset_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CmdProcessCommandsInfoNVX & operator=( VULKAN_HPP_NAMESPACE::CmdProcessCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CmdProcessCommandsInfoNVX ) - offsetof( CmdProcessCommandsInfoNVX, pNext ) );
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX( VkCmdProcessCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CmdProcessCommandsInfoNVX& operator=( VkCmdProcessCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CmdProcessCommandsInfoNVX const *>(&rhs);
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setObjectTable( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ objectTable = objectTable_;
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setIndirectCommandsLayout( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ indirectCommandsLayout = indirectCommandsLayout_;
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setIndirectCommandsTokenCount( uint32_t indirectCommandsTokenCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ indirectCommandsTokenCount = indirectCommandsTokenCount_;
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setPIndirectCommandsTokens( const VULKAN_HPP_NAMESPACE::IndirectCommandsTokenNVX* pIndirectCommandsTokens_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pIndirectCommandsTokens = pIndirectCommandsTokens_;
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setMaxSequencesCount( uint32_t maxSequencesCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxSequencesCount = maxSequencesCount_;
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setTargetCommandBuffer( VULKAN_HPP_NAMESPACE::CommandBuffer targetCommandBuffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ targetCommandBuffer = targetCommandBuffer_;
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setSequencesCountBuffer( VULKAN_HPP_NAMESPACE::Buffer sequencesCountBuffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sequencesCountBuffer = sequencesCountBuffer_;
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setSequencesCountOffset( VULKAN_HPP_NAMESPACE::DeviceSize sequencesCountOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sequencesCountOffset = sequencesCountOffset_;
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setSequencesIndexBuffer( VULKAN_HPP_NAMESPACE::Buffer sequencesIndexBuffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sequencesIndexBuffer = sequencesIndexBuffer_;
+ return *this;
+ }
+
+ CmdProcessCommandsInfoNVX & setSequencesIndexOffset( VULKAN_HPP_NAMESPACE::DeviceSize sequencesIndexOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sequencesIndexOffset = sequencesIndexOffset_;
+ return *this;
+ }
+
+ operator VkCmdProcessCommandsInfoNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCmdProcessCommandsInfoNVX*>( this );
+ }
+
+ operator VkCmdProcessCommandsInfoNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCmdProcessCommandsInfoNVX*>( this );
+ }
+
+ bool operator==( CmdProcessCommandsInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( objectTable == rhs.objectTable )
+ && ( indirectCommandsLayout == rhs.indirectCommandsLayout )
+ && ( indirectCommandsTokenCount == rhs.indirectCommandsTokenCount )
+ && ( pIndirectCommandsTokens == rhs.pIndirectCommandsTokens )
+ && ( maxSequencesCount == rhs.maxSequencesCount )
+ && ( targetCommandBuffer == rhs.targetCommandBuffer )
+ && ( sequencesCountBuffer == rhs.sequencesCountBuffer )
+ && ( sequencesCountOffset == rhs.sequencesCountOffset )
+ && ( sequencesIndexBuffer == rhs.sequencesIndexBuffer )
+ && ( sequencesIndexOffset == rhs.sequencesIndexOffset );
+ }
+
+ bool operator!=( CmdProcessCommandsInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCmdProcessCommandsInfoNVX;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable = {};
+ VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout = {};
+ uint32_t indirectCommandsTokenCount = {};
+ const VULKAN_HPP_NAMESPACE::IndirectCommandsTokenNVX* pIndirectCommandsTokens = {};
+ uint32_t maxSequencesCount = {};
+ VULKAN_HPP_NAMESPACE::CommandBuffer targetCommandBuffer = {};
+ VULKAN_HPP_NAMESPACE::Buffer sequencesCountBuffer = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize sequencesCountOffset = {};
+ VULKAN_HPP_NAMESPACE::Buffer sequencesIndexBuffer = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize sequencesIndexOffset = {};
+ };
+ static_assert( sizeof( CmdProcessCommandsInfoNVX ) == sizeof( VkCmdProcessCommandsInfoNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CmdProcessCommandsInfoNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct CmdReserveSpaceForCommandsInfoNVX
+ {
+ VULKAN_HPP_CONSTEXPR CmdReserveSpaceForCommandsInfoNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable_ = {},
+ VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout_ = {},
+ uint32_t maxSequencesCount_ = {} ) VULKAN_HPP_NOEXCEPT
+ : objectTable( objectTable_ )
+ , indirectCommandsLayout( indirectCommandsLayout_ )
+ , maxSequencesCount( maxSequencesCount_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CmdReserveSpaceForCommandsInfoNVX & operator=( VULKAN_HPP_NAMESPACE::CmdReserveSpaceForCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CmdReserveSpaceForCommandsInfoNVX ) - offsetof( CmdReserveSpaceForCommandsInfoNVX, pNext ) );
+ return *this;
+ }
+
+ CmdReserveSpaceForCommandsInfoNVX( VkCmdReserveSpaceForCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CmdReserveSpaceForCommandsInfoNVX& operator=( VkCmdReserveSpaceForCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CmdReserveSpaceForCommandsInfoNVX const *>(&rhs);
+ return *this;
+ }
+
+ CmdReserveSpaceForCommandsInfoNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ CmdReserveSpaceForCommandsInfoNVX & setObjectTable( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ objectTable = objectTable_;
+ return *this;
+ }
+
+ CmdReserveSpaceForCommandsInfoNVX & setIndirectCommandsLayout( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ indirectCommandsLayout = indirectCommandsLayout_;
+ return *this;
+ }
+
+ CmdReserveSpaceForCommandsInfoNVX & setMaxSequencesCount( uint32_t maxSequencesCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxSequencesCount = maxSequencesCount_;
+ return *this;
+ }
+
+ operator VkCmdReserveSpaceForCommandsInfoNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCmdReserveSpaceForCommandsInfoNVX*>( this );
+ }
+
+ operator VkCmdReserveSpaceForCommandsInfoNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCmdReserveSpaceForCommandsInfoNVX*>( this );
+ }
+
+ bool operator==( CmdReserveSpaceForCommandsInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( objectTable == rhs.objectTable )
+ && ( indirectCommandsLayout == rhs.indirectCommandsLayout )
+ && ( maxSequencesCount == rhs.maxSequencesCount );
+ }
+
+ bool operator!=( CmdReserveSpaceForCommandsInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCmdReserveSpaceForCommandsInfoNVX;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable = {};
+ VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout = {};
+ uint32_t maxSequencesCount = {};
+ };
+ static_assert( sizeof( CmdReserveSpaceForCommandsInfoNVX ) == sizeof( VkCmdReserveSpaceForCommandsInfoNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CmdReserveSpaceForCommandsInfoNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct CoarseSampleLocationNV
+ {
+ VULKAN_HPP_CONSTEXPR CoarseSampleLocationNV( uint32_t pixelX_ = {},
+ uint32_t pixelY_ = {},
+ uint32_t sample_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pixelX( pixelX_ )
+ , pixelY( pixelY_ )
+ , sample( sample_ )
+ {}
+
+ CoarseSampleLocationNV( VkCoarseSampleLocationNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CoarseSampleLocationNV& operator=( VkCoarseSampleLocationNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CoarseSampleLocationNV const *>(&rhs);
+ return *this;
+ }
+
+ CoarseSampleLocationNV & setPixelX( uint32_t pixelX_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pixelX = pixelX_;
+ return *this;
+ }
+
+ CoarseSampleLocationNV & setPixelY( uint32_t pixelY_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pixelY = pixelY_;
+ return *this;
+ }
+
+ CoarseSampleLocationNV & setSample( uint32_t sample_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sample = sample_;
+ return *this;
+ }
+
+ operator VkCoarseSampleLocationNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCoarseSampleLocationNV*>( this );
+ }
+
+ operator VkCoarseSampleLocationNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCoarseSampleLocationNV*>( this );
+ }
+
+ bool operator==( CoarseSampleLocationNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( pixelX == rhs.pixelX )
+ && ( pixelY == rhs.pixelY )
+ && ( sample == rhs.sample );
+ }
+
+ bool operator!=( CoarseSampleLocationNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t pixelX = {};
+ uint32_t pixelY = {};
+ uint32_t sample = {};
+ };
+ static_assert( sizeof( CoarseSampleLocationNV ) == sizeof( VkCoarseSampleLocationNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CoarseSampleLocationNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct CoarseSampleOrderCustomNV
+ {
+ VULKAN_HPP_CONSTEXPR CoarseSampleOrderCustomNV( VULKAN_HPP_NAMESPACE::ShadingRatePaletteEntryNV shadingRate_ = VULKAN_HPP_NAMESPACE::ShadingRatePaletteEntryNV::eNoInvocations,
+ uint32_t sampleCount_ = {},
+ uint32_t sampleLocationCount_ = {},
+ const VULKAN_HPP_NAMESPACE::CoarseSampleLocationNV* pSampleLocations_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shadingRate( shadingRate_ )
+ , sampleCount( sampleCount_ )
+ , sampleLocationCount( sampleLocationCount_ )
+ , pSampleLocations( pSampleLocations_ )
+ {}
+
+ CoarseSampleOrderCustomNV( VkCoarseSampleOrderCustomNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CoarseSampleOrderCustomNV& operator=( VkCoarseSampleOrderCustomNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CoarseSampleOrderCustomNV const *>(&rhs);
+ return *this;
+ }
+
+ CoarseSampleOrderCustomNV & setShadingRate( VULKAN_HPP_NAMESPACE::ShadingRatePaletteEntryNV shadingRate_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shadingRate = shadingRate_;
+ return *this;
+ }
+
+ CoarseSampleOrderCustomNV & setSampleCount( uint32_t sampleCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleCount = sampleCount_;
+ return *this;
+ }
+
+ CoarseSampleOrderCustomNV & setSampleLocationCount( uint32_t sampleLocationCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleLocationCount = sampleLocationCount_;
+ return *this;
+ }
+
+ CoarseSampleOrderCustomNV & setPSampleLocations( const VULKAN_HPP_NAMESPACE::CoarseSampleLocationNV* pSampleLocations_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSampleLocations = pSampleLocations_;
+ return *this;
+ }
+
+ operator VkCoarseSampleOrderCustomNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCoarseSampleOrderCustomNV*>( this );
+ }
+
+ operator VkCoarseSampleOrderCustomNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCoarseSampleOrderCustomNV*>( this );
+ }
+
+ bool operator==( CoarseSampleOrderCustomNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( shadingRate == rhs.shadingRate )
+ && ( sampleCount == rhs.sampleCount )
+ && ( sampleLocationCount == rhs.sampleLocationCount )
+ && ( pSampleLocations == rhs.pSampleLocations );
+ }
+
+ bool operator!=( CoarseSampleOrderCustomNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ShadingRatePaletteEntryNV shadingRate = VULKAN_HPP_NAMESPACE::ShadingRatePaletteEntryNV::eNoInvocations;
+ uint32_t sampleCount = {};
+ uint32_t sampleLocationCount = {};
+ const VULKAN_HPP_NAMESPACE::CoarseSampleLocationNV* pSampleLocations = {};
+ };
+ static_assert( sizeof( CoarseSampleOrderCustomNV ) == sizeof( VkCoarseSampleOrderCustomNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CoarseSampleOrderCustomNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct CommandBufferAllocateInfo
+ {
+ VULKAN_HPP_CONSTEXPR CommandBufferAllocateInfo( VULKAN_HPP_NAMESPACE::CommandPool commandPool_ = {},
+ VULKAN_HPP_NAMESPACE::CommandBufferLevel level_ = VULKAN_HPP_NAMESPACE::CommandBufferLevel::ePrimary,
+ uint32_t commandBufferCount_ = {} ) VULKAN_HPP_NOEXCEPT
+ : commandPool( commandPool_ )
+ , level( level_ )
+ , commandBufferCount( commandBufferCount_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CommandBufferAllocateInfo & operator=( VULKAN_HPP_NAMESPACE::CommandBufferAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CommandBufferAllocateInfo ) - offsetof( CommandBufferAllocateInfo, pNext ) );
+ return *this;
+ }
+
+ CommandBufferAllocateInfo( VkCommandBufferAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CommandBufferAllocateInfo& operator=( VkCommandBufferAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CommandBufferAllocateInfo const *>(&rhs);
+ return *this;
+ }
+
+ CommandBufferAllocateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ CommandBufferAllocateInfo & setCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool_ ) VULKAN_HPP_NOEXCEPT
+ {
+ commandPool = commandPool_;
+ return *this;
+ }
+
+ CommandBufferAllocateInfo & setLevel( VULKAN_HPP_NAMESPACE::CommandBufferLevel level_ ) VULKAN_HPP_NOEXCEPT
+ {
+ level = level_;
+ return *this;
+ }
+
+ CommandBufferAllocateInfo & setCommandBufferCount( uint32_t commandBufferCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ commandBufferCount = commandBufferCount_;
+ return *this;
+ }
+
+ operator VkCommandBufferAllocateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCommandBufferAllocateInfo*>( this );
+ }
+
+ operator VkCommandBufferAllocateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCommandBufferAllocateInfo*>( this );
+ }
+
+ bool operator==( CommandBufferAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( commandPool == rhs.commandPool )
+ && ( level == rhs.level )
+ && ( commandBufferCount == rhs.commandBufferCount );
+ }
+
+ bool operator!=( CommandBufferAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCommandBufferAllocateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::CommandPool commandPool = {};
+ VULKAN_HPP_NAMESPACE::CommandBufferLevel level = VULKAN_HPP_NAMESPACE::CommandBufferLevel::ePrimary;
+ uint32_t commandBufferCount = {};
+ };
+ static_assert( sizeof( CommandBufferAllocateInfo ) == sizeof( VkCommandBufferAllocateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CommandBufferAllocateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct CommandBufferInheritanceInfo
+ {
+ VULKAN_HPP_CONSTEXPR CommandBufferInheritanceInfo( VULKAN_HPP_NAMESPACE::RenderPass renderPass_ = {},
+ uint32_t subpass_ = {},
+ VULKAN_HPP_NAMESPACE::Framebuffer framebuffer_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 occlusionQueryEnable_ = {},
+ VULKAN_HPP_NAMESPACE::QueryControlFlags queryFlags_ = {},
+ VULKAN_HPP_NAMESPACE::QueryPipelineStatisticFlags pipelineStatistics_ = {} ) VULKAN_HPP_NOEXCEPT
+ : renderPass( renderPass_ )
+ , subpass( subpass_ )
+ , framebuffer( framebuffer_ )
+ , occlusionQueryEnable( occlusionQueryEnable_ )
+ , queryFlags( queryFlags_ )
+ , pipelineStatistics( pipelineStatistics_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CommandBufferInheritanceInfo & operator=( VULKAN_HPP_NAMESPACE::CommandBufferInheritanceInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CommandBufferInheritanceInfo ) - offsetof( CommandBufferInheritanceInfo, pNext ) );
+ return *this;
+ }
+
+ CommandBufferInheritanceInfo( VkCommandBufferInheritanceInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CommandBufferInheritanceInfo& operator=( VkCommandBufferInheritanceInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CommandBufferInheritanceInfo const *>(&rhs);
+ return *this;
+ }
+
+ CommandBufferInheritanceInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ CommandBufferInheritanceInfo & setRenderPass( VULKAN_HPP_NAMESPACE::RenderPass renderPass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ renderPass = renderPass_;
+ return *this;
+ }
+
+ CommandBufferInheritanceInfo & setSubpass( uint32_t subpass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subpass = subpass_;
+ return *this;
+ }
+
+ CommandBufferInheritanceInfo & setFramebuffer( VULKAN_HPP_NAMESPACE::Framebuffer framebuffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ framebuffer = framebuffer_;
+ return *this;
+ }
+
+ CommandBufferInheritanceInfo & setOcclusionQueryEnable( VULKAN_HPP_NAMESPACE::Bool32 occlusionQueryEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ occlusionQueryEnable = occlusionQueryEnable_;
+ return *this;
+ }
+
+ CommandBufferInheritanceInfo & setQueryFlags( VULKAN_HPP_NAMESPACE::QueryControlFlags queryFlags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queryFlags = queryFlags_;
+ return *this;
+ }
+
+ CommandBufferInheritanceInfo & setPipelineStatistics( VULKAN_HPP_NAMESPACE::QueryPipelineStatisticFlags pipelineStatistics_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineStatistics = pipelineStatistics_;
+ return *this;
+ }
+
+ operator VkCommandBufferInheritanceInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCommandBufferInheritanceInfo*>( this );
+ }
+
+ operator VkCommandBufferInheritanceInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCommandBufferInheritanceInfo*>( this );
+ }
+
+ bool operator==( CommandBufferInheritanceInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( renderPass == rhs.renderPass )
+ && ( subpass == rhs.subpass )
+ && ( framebuffer == rhs.framebuffer )
+ && ( occlusionQueryEnable == rhs.occlusionQueryEnable )
+ && ( queryFlags == rhs.queryFlags )
+ && ( pipelineStatistics == rhs.pipelineStatistics );
+ }
+
+ bool operator!=( CommandBufferInheritanceInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCommandBufferInheritanceInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass = {};
+ uint32_t subpass = {};
+ VULKAN_HPP_NAMESPACE::Framebuffer framebuffer = {};
+ VULKAN_HPP_NAMESPACE::Bool32 occlusionQueryEnable = {};
+ VULKAN_HPP_NAMESPACE::QueryControlFlags queryFlags = {};
+ VULKAN_HPP_NAMESPACE::QueryPipelineStatisticFlags pipelineStatistics = {};
+ };
+ static_assert( sizeof( CommandBufferInheritanceInfo ) == sizeof( VkCommandBufferInheritanceInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CommandBufferInheritanceInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct CommandBufferBeginInfo
+ {
+ VULKAN_HPP_CONSTEXPR CommandBufferBeginInfo( VULKAN_HPP_NAMESPACE::CommandBufferUsageFlags flags_ = {},
+ const VULKAN_HPP_NAMESPACE::CommandBufferInheritanceInfo* pInheritanceInfo_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , pInheritanceInfo( pInheritanceInfo_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CommandBufferBeginInfo & operator=( VULKAN_HPP_NAMESPACE::CommandBufferBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CommandBufferBeginInfo ) - offsetof( CommandBufferBeginInfo, pNext ) );
+ return *this;
+ }
+
+ CommandBufferBeginInfo( VkCommandBufferBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CommandBufferBeginInfo& operator=( VkCommandBufferBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CommandBufferBeginInfo const *>(&rhs);
+ return *this;
+ }
+
+ CommandBufferBeginInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ CommandBufferBeginInfo & setFlags( VULKAN_HPP_NAMESPACE::CommandBufferUsageFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ CommandBufferBeginInfo & setPInheritanceInfo( const VULKAN_HPP_NAMESPACE::CommandBufferInheritanceInfo* pInheritanceInfo_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pInheritanceInfo = pInheritanceInfo_;
+ return *this;
+ }
+
+ operator VkCommandBufferBeginInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCommandBufferBeginInfo*>( this );
+ }
+
+ operator VkCommandBufferBeginInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCommandBufferBeginInfo*>( this );
+ }
+
+ bool operator==( CommandBufferBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( pInheritanceInfo == rhs.pInheritanceInfo );
+ }
+
+ bool operator!=( CommandBufferBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCommandBufferBeginInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::CommandBufferUsageFlags flags = {};
+ const VULKAN_HPP_NAMESPACE::CommandBufferInheritanceInfo* pInheritanceInfo = {};
+ };
+ static_assert( sizeof( CommandBufferBeginInfo ) == sizeof( VkCommandBufferBeginInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CommandBufferBeginInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct CommandBufferInheritanceConditionalRenderingInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR CommandBufferInheritanceConditionalRenderingInfoEXT( VULKAN_HPP_NAMESPACE::Bool32 conditionalRenderingEnable_ = {} ) VULKAN_HPP_NOEXCEPT
+ : conditionalRenderingEnable( conditionalRenderingEnable_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CommandBufferInheritanceConditionalRenderingInfoEXT & operator=( VULKAN_HPP_NAMESPACE::CommandBufferInheritanceConditionalRenderingInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CommandBufferInheritanceConditionalRenderingInfoEXT ) - offsetof( CommandBufferInheritanceConditionalRenderingInfoEXT, pNext ) );
+ return *this;
+ }
+
+ CommandBufferInheritanceConditionalRenderingInfoEXT( VkCommandBufferInheritanceConditionalRenderingInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CommandBufferInheritanceConditionalRenderingInfoEXT& operator=( VkCommandBufferInheritanceConditionalRenderingInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CommandBufferInheritanceConditionalRenderingInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ CommandBufferInheritanceConditionalRenderingInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ CommandBufferInheritanceConditionalRenderingInfoEXT & setConditionalRenderingEnable( VULKAN_HPP_NAMESPACE::Bool32 conditionalRenderingEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ conditionalRenderingEnable = conditionalRenderingEnable_;
+ return *this;
+ }
+
+ operator VkCommandBufferInheritanceConditionalRenderingInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCommandBufferInheritanceConditionalRenderingInfoEXT*>( this );
+ }
+
+ operator VkCommandBufferInheritanceConditionalRenderingInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCommandBufferInheritanceConditionalRenderingInfoEXT*>( this );
+ }
+
+ bool operator==( CommandBufferInheritanceConditionalRenderingInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( conditionalRenderingEnable == rhs.conditionalRenderingEnable );
+ }
+
+ bool operator!=( CommandBufferInheritanceConditionalRenderingInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCommandBufferInheritanceConditionalRenderingInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 conditionalRenderingEnable = {};
+ };
+ static_assert( sizeof( CommandBufferInheritanceConditionalRenderingInfoEXT ) == sizeof( VkCommandBufferInheritanceConditionalRenderingInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CommandBufferInheritanceConditionalRenderingInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct CommandPoolCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR CommandPoolCreateInfo( VULKAN_HPP_NAMESPACE::CommandPoolCreateFlags flags_ = {},
+ uint32_t queueFamilyIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , queueFamilyIndex( queueFamilyIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CommandPoolCreateInfo & operator=( VULKAN_HPP_NAMESPACE::CommandPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CommandPoolCreateInfo ) - offsetof( CommandPoolCreateInfo, pNext ) );
+ return *this;
+ }
+
+ CommandPoolCreateInfo( VkCommandPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CommandPoolCreateInfo& operator=( VkCommandPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CommandPoolCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ CommandPoolCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ CommandPoolCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::CommandPoolCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ CommandPoolCreateInfo & setQueueFamilyIndex( uint32_t queueFamilyIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueFamilyIndex = queueFamilyIndex_;
+ return *this;
+ }
+
+ operator VkCommandPoolCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCommandPoolCreateInfo*>( this );
+ }
+
+ operator VkCommandPoolCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCommandPoolCreateInfo*>( this );
+ }
+
+ bool operator==( CommandPoolCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( queueFamilyIndex == rhs.queueFamilyIndex );
+ }
+
+ bool operator!=( CommandPoolCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCommandPoolCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::CommandPoolCreateFlags flags = {};
+ uint32_t queueFamilyIndex = {};
+ };
+ static_assert( sizeof( CommandPoolCreateInfo ) == sizeof( VkCommandPoolCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CommandPoolCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SpecializationMapEntry
+ {
+ VULKAN_HPP_CONSTEXPR SpecializationMapEntry( uint32_t constantID_ = {},
+ uint32_t offset_ = {},
+ size_t size_ = {} ) VULKAN_HPP_NOEXCEPT
+ : constantID( constantID_ )
+ , offset( offset_ )
+ , size( size_ )
+ {}
+
+ SpecializationMapEntry( VkSpecializationMapEntry const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SpecializationMapEntry& operator=( VkSpecializationMapEntry const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SpecializationMapEntry const *>(&rhs);
+ return *this;
+ }
+
+ SpecializationMapEntry & setConstantID( uint32_t constantID_ ) VULKAN_HPP_NOEXCEPT
+ {
+ constantID = constantID_;
+ return *this;
+ }
+
+ SpecializationMapEntry & setOffset( uint32_t offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ SpecializationMapEntry & setSize( size_t size_ ) VULKAN_HPP_NOEXCEPT
+ {
+ size = size_;
+ return *this;
+ }
+
+ operator VkSpecializationMapEntry const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSpecializationMapEntry*>( this );
+ }
+
+ operator VkSpecializationMapEntry &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSpecializationMapEntry*>( this );
+ }
+
+ bool operator==( SpecializationMapEntry const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( constantID == rhs.constantID )
+ && ( offset == rhs.offset )
+ && ( size == rhs.size );
+ }
+
+ bool operator!=( SpecializationMapEntry const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t constantID = {};
+ uint32_t offset = {};
+ size_t size = {};
+ };
+ static_assert( sizeof( SpecializationMapEntry ) == sizeof( VkSpecializationMapEntry ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SpecializationMapEntry>::value, "struct wrapper is not a standard layout!" );
+
+ struct SpecializationInfo
+ {
+ VULKAN_HPP_CONSTEXPR SpecializationInfo( uint32_t mapEntryCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SpecializationMapEntry* pMapEntries_ = {},
+ size_t dataSize_ = {},
+ const void* pData_ = {} ) VULKAN_HPP_NOEXCEPT
+ : mapEntryCount( mapEntryCount_ )
+ , pMapEntries( pMapEntries_ )
+ , dataSize( dataSize_ )
+ , pData( pData_ )
+ {}
+
+ SpecializationInfo( VkSpecializationInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SpecializationInfo& operator=( VkSpecializationInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SpecializationInfo const *>(&rhs);
+ return *this;
+ }
+
+ SpecializationInfo & setMapEntryCount( uint32_t mapEntryCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ mapEntryCount = mapEntryCount_;
+ return *this;
+ }
+
+ SpecializationInfo & setPMapEntries( const VULKAN_HPP_NAMESPACE::SpecializationMapEntry* pMapEntries_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pMapEntries = pMapEntries_;
+ return *this;
+ }
+
+ SpecializationInfo & setDataSize( size_t dataSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dataSize = dataSize_;
+ return *this;
+ }
+
+ SpecializationInfo & setPData( const void* pData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pData = pData_;
+ return *this;
+ }
+
+ operator VkSpecializationInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSpecializationInfo*>( this );
+ }
+
+ operator VkSpecializationInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSpecializationInfo*>( this );
+ }
+
+ bool operator==( SpecializationInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( mapEntryCount == rhs.mapEntryCount )
+ && ( pMapEntries == rhs.pMapEntries )
+ && ( dataSize == rhs.dataSize )
+ && ( pData == rhs.pData );
+ }
+
+ bool operator!=( SpecializationInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t mapEntryCount = {};
+ const VULKAN_HPP_NAMESPACE::SpecializationMapEntry* pMapEntries = {};
+ size_t dataSize = {};
+ const void* pData = {};
+ };
+ static_assert( sizeof( SpecializationInfo ) == sizeof( VkSpecializationInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SpecializationInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineShaderStageCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineShaderStageCreateInfo( VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::ShaderStageFlagBits stage_ = VULKAN_HPP_NAMESPACE::ShaderStageFlagBits::eVertex,
+ VULKAN_HPP_NAMESPACE::ShaderModule module_ = {},
+ const char* pName_ = {},
+ const VULKAN_HPP_NAMESPACE::SpecializationInfo* pSpecializationInfo_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , stage( stage_ )
+ , module( module_ )
+ , pName( pName_ )
+ , pSpecializationInfo( pSpecializationInfo_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo ) - offsetof( PipelineShaderStageCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineShaderStageCreateInfo( VkPipelineShaderStageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineShaderStageCreateInfo& operator=( VkPipelineShaderStageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineShaderStageCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineShaderStageCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineShaderStageCreateInfo & setStage( VULKAN_HPP_NAMESPACE::ShaderStageFlagBits stage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stage = stage_;
+ return *this;
+ }
+
+ PipelineShaderStageCreateInfo & setModule( VULKAN_HPP_NAMESPACE::ShaderModule module_ ) VULKAN_HPP_NOEXCEPT
+ {
+ module = module_;
+ return *this;
+ }
+
+ PipelineShaderStageCreateInfo & setPName( const char* pName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pName = pName_;
+ return *this;
+ }
+
+ PipelineShaderStageCreateInfo & setPSpecializationInfo( const VULKAN_HPP_NAMESPACE::SpecializationInfo* pSpecializationInfo_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSpecializationInfo = pSpecializationInfo_;
+ return *this;
+ }
+
+ operator VkPipelineShaderStageCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineShaderStageCreateInfo*>( this );
+ }
+
+ operator VkPipelineShaderStageCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineShaderStageCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineShaderStageCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( stage == rhs.stage )
+ && ( module == rhs.module )
+ && ( pName == rhs.pName )
+ && ( pSpecializationInfo == rhs.pSpecializationInfo );
+ }
+
+ bool operator!=( PipelineShaderStageCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineShaderStageCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::ShaderStageFlagBits stage = VULKAN_HPP_NAMESPACE::ShaderStageFlagBits::eVertex;
+ VULKAN_HPP_NAMESPACE::ShaderModule module = {};
+ const char* pName = {};
+ const VULKAN_HPP_NAMESPACE::SpecializationInfo* pSpecializationInfo = {};
+ };
+ static_assert( sizeof( PipelineShaderStageCreateInfo ) == sizeof( VkPipelineShaderStageCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineShaderStageCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ComputePipelineCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ComputePipelineCreateInfo( VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo stage_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineLayout layout_ = {},
+ VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle_ = {},
+ int32_t basePipelineIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , stage( stage_ )
+ , layout( layout_ )
+ , basePipelineHandle( basePipelineHandle_ )
+ , basePipelineIndex( basePipelineIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo ) - offsetof( ComputePipelineCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ComputePipelineCreateInfo( VkComputePipelineCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ComputePipelineCreateInfo& operator=( VkComputePipelineCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ComputePipelineCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ComputePipelineCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ComputePipelineCreateInfo & setStage( VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo stage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stage = stage_;
+ return *this;
+ }
+
+ ComputePipelineCreateInfo & setLayout( VULKAN_HPP_NAMESPACE::PipelineLayout layout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layout = layout_;
+ return *this;
+ }
+
+ ComputePipelineCreateInfo & setBasePipelineHandle( VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle_ ) VULKAN_HPP_NOEXCEPT
+ {
+ basePipelineHandle = basePipelineHandle_;
+ return *this;
+ }
+
+ ComputePipelineCreateInfo & setBasePipelineIndex( int32_t basePipelineIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ basePipelineIndex = basePipelineIndex_;
+ return *this;
+ }
+
+ operator VkComputePipelineCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkComputePipelineCreateInfo*>( this );
+ }
+
+ operator VkComputePipelineCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkComputePipelineCreateInfo*>( this );
+ }
+
+ bool operator==( ComputePipelineCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( stage == rhs.stage )
+ && ( layout == rhs.layout )
+ && ( basePipelineHandle == rhs.basePipelineHandle )
+ && ( basePipelineIndex == rhs.basePipelineIndex );
+ }
+
+ bool operator!=( ComputePipelineCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eComputePipelineCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo stage = {};
+ VULKAN_HPP_NAMESPACE::PipelineLayout layout = {};
+ VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle = {};
+ int32_t basePipelineIndex = {};
+ };
+ static_assert( sizeof( ComputePipelineCreateInfo ) == sizeof( VkComputePipelineCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ComputePipelineCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ConditionalRenderingBeginInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR ConditionalRenderingBeginInfoEXT( VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {},
+ VULKAN_HPP_NAMESPACE::ConditionalRenderingFlagsEXT flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : buffer( buffer_ )
+ , offset( offset_ )
+ , flags( flags_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ConditionalRenderingBeginInfoEXT & operator=( VULKAN_HPP_NAMESPACE::ConditionalRenderingBeginInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ConditionalRenderingBeginInfoEXT ) - offsetof( ConditionalRenderingBeginInfoEXT, pNext ) );
+ return *this;
+ }
+
+ ConditionalRenderingBeginInfoEXT( VkConditionalRenderingBeginInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ConditionalRenderingBeginInfoEXT& operator=( VkConditionalRenderingBeginInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ConditionalRenderingBeginInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ ConditionalRenderingBeginInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ConditionalRenderingBeginInfoEXT & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ ConditionalRenderingBeginInfoEXT & setOffset( VULKAN_HPP_NAMESPACE::DeviceSize offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ ConditionalRenderingBeginInfoEXT & setFlags( VULKAN_HPP_NAMESPACE::ConditionalRenderingFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ operator VkConditionalRenderingBeginInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkConditionalRenderingBeginInfoEXT*>( this );
+ }
+
+ operator VkConditionalRenderingBeginInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkConditionalRenderingBeginInfoEXT*>( this );
+ }
+
+ bool operator==( ConditionalRenderingBeginInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( buffer == rhs.buffer )
+ && ( offset == rhs.offset )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( ConditionalRenderingBeginInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eConditionalRenderingBeginInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
+ VULKAN_HPP_NAMESPACE::ConditionalRenderingFlagsEXT flags = {};
+ };
+ static_assert( sizeof( ConditionalRenderingBeginInfoEXT ) == sizeof( VkConditionalRenderingBeginInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ConditionalRenderingBeginInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct ConformanceVersion
+ {
+ VULKAN_HPP_CONSTEXPR ConformanceVersion( uint8_t major_ = {},
+ uint8_t minor_ = {},
+ uint8_t subminor_ = {},
+ uint8_t patch_ = {} ) VULKAN_HPP_NOEXCEPT
+ : major( major_ )
+ , minor( minor_ )
+ , subminor( subminor_ )
+ , patch( patch_ )
+ {}
+
+ ConformanceVersion( VkConformanceVersion const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ConformanceVersion& operator=( VkConformanceVersion const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ConformanceVersion const *>(&rhs);
+ return *this;
+ }
+
+ ConformanceVersion & setMajor( uint8_t major_ ) VULKAN_HPP_NOEXCEPT
+ {
+ major = major_;
+ return *this;
+ }
+
+ ConformanceVersion & setMinor( uint8_t minor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minor = minor_;
+ return *this;
+ }
+
+ ConformanceVersion & setSubminor( uint8_t subminor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subminor = subminor_;
+ return *this;
+ }
+
+ ConformanceVersion & setPatch( uint8_t patch_ ) VULKAN_HPP_NOEXCEPT
+ {
+ patch = patch_;
+ return *this;
+ }
+
+ operator VkConformanceVersion const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkConformanceVersion*>( this );
+ }
+
+ operator VkConformanceVersion &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkConformanceVersion*>( this );
+ }
+
+ bool operator==( ConformanceVersion const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( major == rhs.major )
+ && ( minor == rhs.minor )
+ && ( subminor == rhs.subminor )
+ && ( patch == rhs.patch );
+ }
+
+ bool operator!=( ConformanceVersion const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint8_t major = {};
+ uint8_t minor = {};
+ uint8_t subminor = {};
+ uint8_t patch = {};
+ };
+ static_assert( sizeof( ConformanceVersion ) == sizeof( VkConformanceVersion ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ConformanceVersion>::value, "struct wrapper is not a standard layout!" );
+
+ struct CooperativeMatrixPropertiesNV
+ {
+ VULKAN_HPP_CONSTEXPR CooperativeMatrixPropertiesNV( uint32_t MSize_ = {},
+ uint32_t NSize_ = {},
+ uint32_t KSize_ = {},
+ VULKAN_HPP_NAMESPACE::ComponentTypeNV AType_ = VULKAN_HPP_NAMESPACE::ComponentTypeNV::eFloat16,
+ VULKAN_HPP_NAMESPACE::ComponentTypeNV BType_ = VULKAN_HPP_NAMESPACE::ComponentTypeNV::eFloat16,
+ VULKAN_HPP_NAMESPACE::ComponentTypeNV CType_ = VULKAN_HPP_NAMESPACE::ComponentTypeNV::eFloat16,
+ VULKAN_HPP_NAMESPACE::ComponentTypeNV DType_ = VULKAN_HPP_NAMESPACE::ComponentTypeNV::eFloat16,
+ VULKAN_HPP_NAMESPACE::ScopeNV scope_ = VULKAN_HPP_NAMESPACE::ScopeNV::eDevice ) VULKAN_HPP_NOEXCEPT
+ : MSize( MSize_ )
+ , NSize( NSize_ )
+ , KSize( KSize_ )
+ , AType( AType_ )
+ , BType( BType_ )
+ , CType( CType_ )
+ , DType( DType_ )
+ , scope( scope_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CooperativeMatrixPropertiesNV & operator=( VULKAN_HPP_NAMESPACE::CooperativeMatrixPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CooperativeMatrixPropertiesNV ) - offsetof( CooperativeMatrixPropertiesNV, pNext ) );
+ return *this;
+ }
+
+ CooperativeMatrixPropertiesNV( VkCooperativeMatrixPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CooperativeMatrixPropertiesNV& operator=( VkCooperativeMatrixPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CooperativeMatrixPropertiesNV const *>(&rhs);
+ return *this;
+ }
+
+ CooperativeMatrixPropertiesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ CooperativeMatrixPropertiesNV & setMSize( uint32_t MSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ MSize = MSize_;
+ return *this;
+ }
+
+ CooperativeMatrixPropertiesNV & setNSize( uint32_t NSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ NSize = NSize_;
+ return *this;
+ }
+
+ CooperativeMatrixPropertiesNV & setKSize( uint32_t KSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ KSize = KSize_;
+ return *this;
+ }
+
+ CooperativeMatrixPropertiesNV & setAType( VULKAN_HPP_NAMESPACE::ComponentTypeNV AType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ AType = AType_;
+ return *this;
+ }
+
+ CooperativeMatrixPropertiesNV & setBType( VULKAN_HPP_NAMESPACE::ComponentTypeNV BType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ BType = BType_;
+ return *this;
+ }
+
+ CooperativeMatrixPropertiesNV & setCType( VULKAN_HPP_NAMESPACE::ComponentTypeNV CType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ CType = CType_;
+ return *this;
+ }
+
+ CooperativeMatrixPropertiesNV & setDType( VULKAN_HPP_NAMESPACE::ComponentTypeNV DType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ DType = DType_;
+ return *this;
+ }
+
+ CooperativeMatrixPropertiesNV & setScope( VULKAN_HPP_NAMESPACE::ScopeNV scope_ ) VULKAN_HPP_NOEXCEPT
+ {
+ scope = scope_;
+ return *this;
+ }
+
+ operator VkCooperativeMatrixPropertiesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCooperativeMatrixPropertiesNV*>( this );
+ }
+
+ operator VkCooperativeMatrixPropertiesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCooperativeMatrixPropertiesNV*>( this );
+ }
+
+ bool operator==( CooperativeMatrixPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( MSize == rhs.MSize )
+ && ( NSize == rhs.NSize )
+ && ( KSize == rhs.KSize )
+ && ( AType == rhs.AType )
+ && ( BType == rhs.BType )
+ && ( CType == rhs.CType )
+ && ( DType == rhs.DType )
+ && ( scope == rhs.scope );
+ }
+
+ bool operator!=( CooperativeMatrixPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCooperativeMatrixPropertiesNV;
+ void* pNext = {};
+ uint32_t MSize = {};
+ uint32_t NSize = {};
+ uint32_t KSize = {};
+ VULKAN_HPP_NAMESPACE::ComponentTypeNV AType = VULKAN_HPP_NAMESPACE::ComponentTypeNV::eFloat16;
+ VULKAN_HPP_NAMESPACE::ComponentTypeNV BType = VULKAN_HPP_NAMESPACE::ComponentTypeNV::eFloat16;
+ VULKAN_HPP_NAMESPACE::ComponentTypeNV CType = VULKAN_HPP_NAMESPACE::ComponentTypeNV::eFloat16;
+ VULKAN_HPP_NAMESPACE::ComponentTypeNV DType = VULKAN_HPP_NAMESPACE::ComponentTypeNV::eFloat16;
+ VULKAN_HPP_NAMESPACE::ScopeNV scope = VULKAN_HPP_NAMESPACE::ScopeNV::eDevice;
+ };
+ static_assert( sizeof( CooperativeMatrixPropertiesNV ) == sizeof( VkCooperativeMatrixPropertiesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CooperativeMatrixPropertiesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct CopyDescriptorSet
+ {
+ VULKAN_HPP_CONSTEXPR CopyDescriptorSet( VULKAN_HPP_NAMESPACE::DescriptorSet srcSet_ = {},
+ uint32_t srcBinding_ = {},
+ uint32_t srcArrayElement_ = {},
+ VULKAN_HPP_NAMESPACE::DescriptorSet dstSet_ = {},
+ uint32_t dstBinding_ = {},
+ uint32_t dstArrayElement_ = {},
+ uint32_t descriptorCount_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcSet( srcSet_ )
+ , srcBinding( srcBinding_ )
+ , srcArrayElement( srcArrayElement_ )
+ , dstSet( dstSet_ )
+ , dstBinding( dstBinding_ )
+ , dstArrayElement( dstArrayElement_ )
+ , descriptorCount( descriptorCount_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::CopyDescriptorSet & operator=( VULKAN_HPP_NAMESPACE::CopyDescriptorSet const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::CopyDescriptorSet ) - offsetof( CopyDescriptorSet, pNext ) );
+ return *this;
+ }
+
+ CopyDescriptorSet( VkCopyDescriptorSet const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ CopyDescriptorSet& operator=( VkCopyDescriptorSet const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CopyDescriptorSet const *>(&rhs);
+ return *this;
+ }
+
+ CopyDescriptorSet & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ CopyDescriptorSet & setSrcSet( VULKAN_HPP_NAMESPACE::DescriptorSet srcSet_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcSet = srcSet_;
+ return *this;
+ }
+
+ CopyDescriptorSet & setSrcBinding( uint32_t srcBinding_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcBinding = srcBinding_;
+ return *this;
+ }
+
+ CopyDescriptorSet & setSrcArrayElement( uint32_t srcArrayElement_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcArrayElement = srcArrayElement_;
+ return *this;
+ }
+
+ CopyDescriptorSet & setDstSet( VULKAN_HPP_NAMESPACE::DescriptorSet dstSet_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstSet = dstSet_;
+ return *this;
+ }
+
+ CopyDescriptorSet & setDstBinding( uint32_t dstBinding_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstBinding = dstBinding_;
+ return *this;
+ }
+
+ CopyDescriptorSet & setDstArrayElement( uint32_t dstArrayElement_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstArrayElement = dstArrayElement_;
+ return *this;
+ }
+
+ CopyDescriptorSet & setDescriptorCount( uint32_t descriptorCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorCount = descriptorCount_;
+ return *this;
+ }
+
+ operator VkCopyDescriptorSet const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkCopyDescriptorSet*>( this );
+ }
+
+ operator VkCopyDescriptorSet &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkCopyDescriptorSet*>( this );
+ }
+
+ bool operator==( CopyDescriptorSet const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( srcSet == rhs.srcSet )
+ && ( srcBinding == rhs.srcBinding )
+ && ( srcArrayElement == rhs.srcArrayElement )
+ && ( dstSet == rhs.dstSet )
+ && ( dstBinding == rhs.dstBinding )
+ && ( dstArrayElement == rhs.dstArrayElement )
+ && ( descriptorCount == rhs.descriptorCount );
+ }
+
+ bool operator!=( CopyDescriptorSet const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCopyDescriptorSet;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DescriptorSet srcSet = {};
+ uint32_t srcBinding = {};
+ uint32_t srcArrayElement = {};
+ VULKAN_HPP_NAMESPACE::DescriptorSet dstSet = {};
+ uint32_t dstBinding = {};
+ uint32_t dstArrayElement = {};
+ uint32_t descriptorCount = {};
+ };
+ static_assert( sizeof( CopyDescriptorSet ) == sizeof( VkCopyDescriptorSet ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<CopyDescriptorSet>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct D3D12FenceSubmitInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR D3D12FenceSubmitInfoKHR( uint32_t waitSemaphoreValuesCount_ = {},
+ const uint64_t* pWaitSemaphoreValues_ = {},
+ uint32_t signalSemaphoreValuesCount_ = {},
+ const uint64_t* pSignalSemaphoreValues_ = {} ) VULKAN_HPP_NOEXCEPT
+ : waitSemaphoreValuesCount( waitSemaphoreValuesCount_ )
+ , pWaitSemaphoreValues( pWaitSemaphoreValues_ )
+ , signalSemaphoreValuesCount( signalSemaphoreValuesCount_ )
+ , pSignalSemaphoreValues( pSignalSemaphoreValues_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::D3D12FenceSubmitInfoKHR & operator=( VULKAN_HPP_NAMESPACE::D3D12FenceSubmitInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::D3D12FenceSubmitInfoKHR ) - offsetof( D3D12FenceSubmitInfoKHR, pNext ) );
+ return *this;
+ }
+
+ D3D12FenceSubmitInfoKHR( VkD3D12FenceSubmitInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ D3D12FenceSubmitInfoKHR& operator=( VkD3D12FenceSubmitInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::D3D12FenceSubmitInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ D3D12FenceSubmitInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ D3D12FenceSubmitInfoKHR & setWaitSemaphoreValuesCount( uint32_t waitSemaphoreValuesCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ waitSemaphoreValuesCount = waitSemaphoreValuesCount_;
+ return *this;
+ }
+
+ D3D12FenceSubmitInfoKHR & setPWaitSemaphoreValues( const uint64_t* pWaitSemaphoreValues_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pWaitSemaphoreValues = pWaitSemaphoreValues_;
+ return *this;
+ }
+
+ D3D12FenceSubmitInfoKHR & setSignalSemaphoreValuesCount( uint32_t signalSemaphoreValuesCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ signalSemaphoreValuesCount = signalSemaphoreValuesCount_;
+ return *this;
+ }
+
+ D3D12FenceSubmitInfoKHR & setPSignalSemaphoreValues( const uint64_t* pSignalSemaphoreValues_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSignalSemaphoreValues = pSignalSemaphoreValues_;
+ return *this;
+ }
+
+ operator VkD3D12FenceSubmitInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkD3D12FenceSubmitInfoKHR*>( this );
+ }
+
+ operator VkD3D12FenceSubmitInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkD3D12FenceSubmitInfoKHR*>( this );
+ }
+
+ bool operator==( D3D12FenceSubmitInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( waitSemaphoreValuesCount == rhs.waitSemaphoreValuesCount )
+ && ( pWaitSemaphoreValues == rhs.pWaitSemaphoreValues )
+ && ( signalSemaphoreValuesCount == rhs.signalSemaphoreValuesCount )
+ && ( pSignalSemaphoreValues == rhs.pSignalSemaphoreValues );
+ }
+
+ bool operator!=( D3D12FenceSubmitInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eD3D12FenceSubmitInfoKHR;
+ const void* pNext = {};
+ uint32_t waitSemaphoreValuesCount = {};
+ const uint64_t* pWaitSemaphoreValues = {};
+ uint32_t signalSemaphoreValuesCount = {};
+ const uint64_t* pSignalSemaphoreValues = {};
+ };
+ static_assert( sizeof( D3D12FenceSubmitInfoKHR ) == sizeof( VkD3D12FenceSubmitInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<D3D12FenceSubmitInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct DebugMarkerMarkerInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR_14 DebugMarkerMarkerInfoEXT( const char* pMarkerName_ = {},
+ std::array<float,4> const& color_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pMarkerName( pMarkerName_ )
+ , color{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,4,4>::copy( color, color_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::DebugMarkerMarkerInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DebugMarkerMarkerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DebugMarkerMarkerInfoEXT ) - offsetof( DebugMarkerMarkerInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DebugMarkerMarkerInfoEXT( VkDebugMarkerMarkerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DebugMarkerMarkerInfoEXT& operator=( VkDebugMarkerMarkerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DebugMarkerMarkerInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DebugMarkerMarkerInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DebugMarkerMarkerInfoEXT & setPMarkerName( const char* pMarkerName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pMarkerName = pMarkerName_;
+ return *this;
+ }
+
+ DebugMarkerMarkerInfoEXT & setColor( std::array<float,4> color_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( color, color_.data(), 4 * sizeof( float ) );
+ return *this;
+ }
+
+ operator VkDebugMarkerMarkerInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDebugMarkerMarkerInfoEXT*>( this );
+ }
+
+ operator VkDebugMarkerMarkerInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDebugMarkerMarkerInfoEXT*>( this );
+ }
+
+ bool operator==( DebugMarkerMarkerInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pMarkerName == rhs.pMarkerName )
+ && ( memcmp( color, rhs.color, 4 * sizeof( float ) ) == 0 );
+ }
+
+ bool operator!=( DebugMarkerMarkerInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugMarkerMarkerInfoEXT;
+ const void* pNext = {};
+ const char* pMarkerName = {};
+ float color[4] = {};
+ };
+ static_assert( sizeof( DebugMarkerMarkerInfoEXT ) == sizeof( VkDebugMarkerMarkerInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DebugMarkerMarkerInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DebugMarkerObjectNameInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DebugMarkerObjectNameInfoEXT( VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT objectType_ = VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown,
+ uint64_t object_ = {},
+ const char* pObjectName_ = {} ) VULKAN_HPP_NOEXCEPT
+ : objectType( objectType_ )
+ , object( object_ )
+ , pObjectName( pObjectName_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DebugMarkerObjectNameInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DebugMarkerObjectNameInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DebugMarkerObjectNameInfoEXT ) - offsetof( DebugMarkerObjectNameInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DebugMarkerObjectNameInfoEXT( VkDebugMarkerObjectNameInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DebugMarkerObjectNameInfoEXT& operator=( VkDebugMarkerObjectNameInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DebugMarkerObjectNameInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DebugMarkerObjectNameInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DebugMarkerObjectNameInfoEXT & setObjectType( VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT objectType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ objectType = objectType_;
+ return *this;
+ }
+
+ DebugMarkerObjectNameInfoEXT & setObject( uint64_t object_ ) VULKAN_HPP_NOEXCEPT
+ {
+ object = object_;
+ return *this;
+ }
+
+ DebugMarkerObjectNameInfoEXT & setPObjectName( const char* pObjectName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pObjectName = pObjectName_;
+ return *this;
+ }
+
+ operator VkDebugMarkerObjectNameInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDebugMarkerObjectNameInfoEXT*>( this );
+ }
+
+ operator VkDebugMarkerObjectNameInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDebugMarkerObjectNameInfoEXT*>( this );
+ }
+
+ bool operator==( DebugMarkerObjectNameInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( objectType == rhs.objectType )
+ && ( object == rhs.object )
+ && ( pObjectName == rhs.pObjectName );
+ }
+
+ bool operator!=( DebugMarkerObjectNameInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugMarkerObjectNameInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT objectType = VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown;
+ uint64_t object = {};
+ const char* pObjectName = {};
+ };
+ static_assert( sizeof( DebugMarkerObjectNameInfoEXT ) == sizeof( VkDebugMarkerObjectNameInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DebugMarkerObjectNameInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DebugMarkerObjectTagInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DebugMarkerObjectTagInfoEXT( VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT objectType_ = VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown,
+ uint64_t object_ = {},
+ uint64_t tagName_ = {},
+ size_t tagSize_ = {},
+ const void* pTag_ = {} ) VULKAN_HPP_NOEXCEPT
+ : objectType( objectType_ )
+ , object( object_ )
+ , tagName( tagName_ )
+ , tagSize( tagSize_ )
+ , pTag( pTag_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DebugMarkerObjectTagInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DebugMarkerObjectTagInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DebugMarkerObjectTagInfoEXT ) - offsetof( DebugMarkerObjectTagInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DebugMarkerObjectTagInfoEXT( VkDebugMarkerObjectTagInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DebugMarkerObjectTagInfoEXT& operator=( VkDebugMarkerObjectTagInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DebugMarkerObjectTagInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DebugMarkerObjectTagInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DebugMarkerObjectTagInfoEXT & setObjectType( VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT objectType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ objectType = objectType_;
+ return *this;
+ }
+
+ DebugMarkerObjectTagInfoEXT & setObject( uint64_t object_ ) VULKAN_HPP_NOEXCEPT
+ {
+ object = object_;
+ return *this;
+ }
+
+ DebugMarkerObjectTagInfoEXT & setTagName( uint64_t tagName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tagName = tagName_;
+ return *this;
+ }
+
+ DebugMarkerObjectTagInfoEXT & setTagSize( size_t tagSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tagSize = tagSize_;
+ return *this;
+ }
+
+ DebugMarkerObjectTagInfoEXT & setPTag( const void* pTag_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pTag = pTag_;
+ return *this;
+ }
+
+ operator VkDebugMarkerObjectTagInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDebugMarkerObjectTagInfoEXT*>( this );
+ }
+
+ operator VkDebugMarkerObjectTagInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDebugMarkerObjectTagInfoEXT*>( this );
+ }
+
+ bool operator==( DebugMarkerObjectTagInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( objectType == rhs.objectType )
+ && ( object == rhs.object )
+ && ( tagName == rhs.tagName )
+ && ( tagSize == rhs.tagSize )
+ && ( pTag == rhs.pTag );
+ }
+
+ bool operator!=( DebugMarkerObjectTagInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugMarkerObjectTagInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT objectType = VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eUnknown;
+ uint64_t object = {};
+ uint64_t tagName = {};
+ size_t tagSize = {};
+ const void* pTag = {};
+ };
+ static_assert( sizeof( DebugMarkerObjectTagInfoEXT ) == sizeof( VkDebugMarkerObjectTagInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DebugMarkerObjectTagInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DebugReportCallbackCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DebugReportCallbackCreateInfoEXT( VULKAN_HPP_NAMESPACE::DebugReportFlagsEXT flags_ = {},
+ PFN_vkDebugReportCallbackEXT pfnCallback_ = {},
+ void* pUserData_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , pfnCallback( pfnCallback_ )
+ , pUserData( pUserData_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DebugReportCallbackCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DebugReportCallbackCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DebugReportCallbackCreateInfoEXT ) - offsetof( DebugReportCallbackCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DebugReportCallbackCreateInfoEXT( VkDebugReportCallbackCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DebugReportCallbackCreateInfoEXT& operator=( VkDebugReportCallbackCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DebugReportCallbackCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DebugReportCallbackCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DebugReportCallbackCreateInfoEXT & setFlags( VULKAN_HPP_NAMESPACE::DebugReportFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DebugReportCallbackCreateInfoEXT & setPfnCallback( PFN_vkDebugReportCallbackEXT pfnCallback_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pfnCallback = pfnCallback_;
+ return *this;
+ }
+
+ DebugReportCallbackCreateInfoEXT & setPUserData( void* pUserData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pUserData = pUserData_;
+ return *this;
+ }
+
+ operator VkDebugReportCallbackCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>( this );
+ }
+
+ operator VkDebugReportCallbackCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDebugReportCallbackCreateInfoEXT*>( this );
+ }
+
+ bool operator==( DebugReportCallbackCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( pfnCallback == rhs.pfnCallback )
+ && ( pUserData == rhs.pUserData );
+ }
+
+ bool operator!=( DebugReportCallbackCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugReportCallbackCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DebugReportFlagsEXT flags = {};
+ PFN_vkDebugReportCallbackEXT pfnCallback = {};
+ void* pUserData = {};
+ };
+ static_assert( sizeof( DebugReportCallbackCreateInfoEXT ) == sizeof( VkDebugReportCallbackCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DebugReportCallbackCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DebugUtilsLabelEXT
+ {
+ VULKAN_HPP_CONSTEXPR_14 DebugUtilsLabelEXT( const char* pLabelName_ = {},
+ std::array<float,4> const& color_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pLabelName( pLabelName_ )
+ , color{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,4,4>::copy( color, color_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT & operator=( VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT ) - offsetof( DebugUtilsLabelEXT, pNext ) );
+ return *this;
+ }
+
+ DebugUtilsLabelEXT( VkDebugUtilsLabelEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DebugUtilsLabelEXT& operator=( VkDebugUtilsLabelEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT const *>(&rhs);
+ return *this;
+ }
+
+ DebugUtilsLabelEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DebugUtilsLabelEXT & setPLabelName( const char* pLabelName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pLabelName = pLabelName_;
+ return *this;
+ }
+
+ DebugUtilsLabelEXT & setColor( std::array<float,4> color_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( color, color_.data(), 4 * sizeof( float ) );
+ return *this;
+ }
+
+ operator VkDebugUtilsLabelEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDebugUtilsLabelEXT*>( this );
+ }
+
+ operator VkDebugUtilsLabelEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDebugUtilsLabelEXT*>( this );
+ }
+
+ bool operator==( DebugUtilsLabelEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pLabelName == rhs.pLabelName )
+ && ( memcmp( color, rhs.color, 4 * sizeof( float ) ) == 0 );
+ }
+
+ bool operator!=( DebugUtilsLabelEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugUtilsLabelEXT;
+ const void* pNext = {};
+ const char* pLabelName = {};
+ float color[4] = {};
+ };
+ static_assert( sizeof( DebugUtilsLabelEXT ) == sizeof( VkDebugUtilsLabelEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DebugUtilsLabelEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DebugUtilsObjectNameInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DebugUtilsObjectNameInfoEXT( VULKAN_HPP_NAMESPACE::ObjectType objectType_ = VULKAN_HPP_NAMESPACE::ObjectType::eUnknown,
+ uint64_t objectHandle_ = {},
+ const char* pObjectName_ = {} ) VULKAN_HPP_NOEXCEPT
+ : objectType( objectType_ )
+ , objectHandle( objectHandle_ )
+ , pObjectName( pObjectName_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DebugUtilsObjectNameInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DebugUtilsObjectNameInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DebugUtilsObjectNameInfoEXT ) - offsetof( DebugUtilsObjectNameInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DebugUtilsObjectNameInfoEXT( VkDebugUtilsObjectNameInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DebugUtilsObjectNameInfoEXT& operator=( VkDebugUtilsObjectNameInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DebugUtilsObjectNameInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DebugUtilsObjectNameInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DebugUtilsObjectNameInfoEXT & setObjectType( VULKAN_HPP_NAMESPACE::ObjectType objectType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ objectType = objectType_;
+ return *this;
+ }
+
+ DebugUtilsObjectNameInfoEXT & setObjectHandle( uint64_t objectHandle_ ) VULKAN_HPP_NOEXCEPT
+ {
+ objectHandle = objectHandle_;
+ return *this;
+ }
+
+ DebugUtilsObjectNameInfoEXT & setPObjectName( const char* pObjectName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pObjectName = pObjectName_;
+ return *this;
+ }
+
+ operator VkDebugUtilsObjectNameInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDebugUtilsObjectNameInfoEXT*>( this );
+ }
+
+ operator VkDebugUtilsObjectNameInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDebugUtilsObjectNameInfoEXT*>( this );
+ }
+
+ bool operator==( DebugUtilsObjectNameInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( objectType == rhs.objectType )
+ && ( objectHandle == rhs.objectHandle )
+ && ( pObjectName == rhs.pObjectName );
+ }
+
+ bool operator!=( DebugUtilsObjectNameInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugUtilsObjectNameInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eUnknown;
+ uint64_t objectHandle = {};
+ const char* pObjectName = {};
+ };
+ static_assert( sizeof( DebugUtilsObjectNameInfoEXT ) == sizeof( VkDebugUtilsObjectNameInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DebugUtilsObjectNameInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DebugUtilsMessengerCallbackDataEXT
+ {
+ VULKAN_HPP_CONSTEXPR DebugUtilsMessengerCallbackDataEXT( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCallbackDataFlagsEXT flags_ = {},
+ const char* pMessageIdName_ = {},
+ int32_t messageIdNumber_ = {},
+ const char* pMessage_ = {},
+ uint32_t queueLabelCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pQueueLabels_ = {},
+ uint32_t cmdBufLabelCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pCmdBufLabels_ = {},
+ uint32_t objectCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DebugUtilsObjectNameInfoEXT* pObjects_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , pMessageIdName( pMessageIdName_ )
+ , messageIdNumber( messageIdNumber_ )
+ , pMessage( pMessage_ )
+ , queueLabelCount( queueLabelCount_ )
+ , pQueueLabels( pQueueLabels_ )
+ , cmdBufLabelCount( cmdBufLabelCount_ )
+ , pCmdBufLabels( pCmdBufLabels_ )
+ , objectCount( objectCount_ )
+ , pObjects( pObjects_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCallbackDataEXT & operator=( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCallbackDataEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCallbackDataEXT ) - offsetof( DebugUtilsMessengerCallbackDataEXT, pNext ) );
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT( VkDebugUtilsMessengerCallbackDataEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT& operator=( VkDebugUtilsMessengerCallbackDataEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCallbackDataEXT const *>(&rhs);
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setFlags( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCallbackDataFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setPMessageIdName( const char* pMessageIdName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pMessageIdName = pMessageIdName_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setMessageIdNumber( int32_t messageIdNumber_ ) VULKAN_HPP_NOEXCEPT
+ {
+ messageIdNumber = messageIdNumber_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setPMessage( const char* pMessage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pMessage = pMessage_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setQueueLabelCount( uint32_t queueLabelCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueLabelCount = queueLabelCount_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setPQueueLabels( const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pQueueLabels_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pQueueLabels = pQueueLabels_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setCmdBufLabelCount( uint32_t cmdBufLabelCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ cmdBufLabelCount = cmdBufLabelCount_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setPCmdBufLabels( const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pCmdBufLabels_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pCmdBufLabels = pCmdBufLabels_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setObjectCount( uint32_t objectCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ objectCount = objectCount_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCallbackDataEXT & setPObjects( const VULKAN_HPP_NAMESPACE::DebugUtilsObjectNameInfoEXT* pObjects_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pObjects = pObjects_;
+ return *this;
+ }
+
+ operator VkDebugUtilsMessengerCallbackDataEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDebugUtilsMessengerCallbackDataEXT*>( this );
+ }
+
+ operator VkDebugUtilsMessengerCallbackDataEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDebugUtilsMessengerCallbackDataEXT*>( this );
+ }
+
+ bool operator==( DebugUtilsMessengerCallbackDataEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( pMessageIdName == rhs.pMessageIdName )
+ && ( messageIdNumber == rhs.messageIdNumber )
+ && ( pMessage == rhs.pMessage )
+ && ( queueLabelCount == rhs.queueLabelCount )
+ && ( pQueueLabels == rhs.pQueueLabels )
+ && ( cmdBufLabelCount == rhs.cmdBufLabelCount )
+ && ( pCmdBufLabels == rhs.pCmdBufLabels )
+ && ( objectCount == rhs.objectCount )
+ && ( pObjects == rhs.pObjects );
+ }
+
+ bool operator!=( DebugUtilsMessengerCallbackDataEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugUtilsMessengerCallbackDataEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCallbackDataFlagsEXT flags = {};
+ const char* pMessageIdName = {};
+ int32_t messageIdNumber = {};
+ const char* pMessage = {};
+ uint32_t queueLabelCount = {};
+ const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pQueueLabels = {};
+ uint32_t cmdBufLabelCount = {};
+ const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pCmdBufLabels = {};
+ uint32_t objectCount = {};
+ const VULKAN_HPP_NAMESPACE::DebugUtilsObjectNameInfoEXT* pObjects = {};
+ };
+ static_assert( sizeof( DebugUtilsMessengerCallbackDataEXT ) == sizeof( VkDebugUtilsMessengerCallbackDataEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DebugUtilsMessengerCallbackDataEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DebugUtilsMessengerCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DebugUtilsMessengerCreateInfoEXT( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCreateFlagsEXT flags_ = {},
+ VULKAN_HPP_NAMESPACE::DebugUtilsMessageSeverityFlagsEXT messageSeverity_ = {},
+ VULKAN_HPP_NAMESPACE::DebugUtilsMessageTypeFlagsEXT messageType_ = {},
+ PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback_ = {},
+ void* pUserData_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , messageSeverity( messageSeverity_ )
+ , messageType( messageType_ )
+ , pfnUserCallback( pfnUserCallback_ )
+ , pUserData( pUserData_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCreateInfoEXT ) - offsetof( DebugUtilsMessengerCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DebugUtilsMessengerCreateInfoEXT( VkDebugUtilsMessengerCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DebugUtilsMessengerCreateInfoEXT& operator=( VkDebugUtilsMessengerCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DebugUtilsMessengerCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCreateInfoEXT & setFlags( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCreateFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCreateInfoEXT & setMessageSeverity( VULKAN_HPP_NAMESPACE::DebugUtilsMessageSeverityFlagsEXT messageSeverity_ ) VULKAN_HPP_NOEXCEPT
+ {
+ messageSeverity = messageSeverity_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCreateInfoEXT & setMessageType( VULKAN_HPP_NAMESPACE::DebugUtilsMessageTypeFlagsEXT messageType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ messageType = messageType_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCreateInfoEXT & setPfnUserCallback( PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pfnUserCallback = pfnUserCallback_;
+ return *this;
+ }
+
+ DebugUtilsMessengerCreateInfoEXT & setPUserData( void* pUserData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pUserData = pUserData_;
+ return *this;
+ }
+
+ operator VkDebugUtilsMessengerCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDebugUtilsMessengerCreateInfoEXT*>( this );
+ }
+
+ operator VkDebugUtilsMessengerCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDebugUtilsMessengerCreateInfoEXT*>( this );
+ }
+
+ bool operator==( DebugUtilsMessengerCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( messageSeverity == rhs.messageSeverity )
+ && ( messageType == rhs.messageType )
+ && ( pfnUserCallback == rhs.pfnUserCallback )
+ && ( pUserData == rhs.pUserData );
+ }
+
+ bool operator!=( DebugUtilsMessengerCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugUtilsMessengerCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCreateFlagsEXT flags = {};
+ VULKAN_HPP_NAMESPACE::DebugUtilsMessageSeverityFlagsEXT messageSeverity = {};
+ VULKAN_HPP_NAMESPACE::DebugUtilsMessageTypeFlagsEXT messageType = {};
+ PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback = {};
+ void* pUserData = {};
+ };
+ static_assert( sizeof( DebugUtilsMessengerCreateInfoEXT ) == sizeof( VkDebugUtilsMessengerCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DebugUtilsMessengerCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DebugUtilsObjectTagInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DebugUtilsObjectTagInfoEXT( VULKAN_HPP_NAMESPACE::ObjectType objectType_ = VULKAN_HPP_NAMESPACE::ObjectType::eUnknown,
+ uint64_t objectHandle_ = {},
+ uint64_t tagName_ = {},
+ size_t tagSize_ = {},
+ const void* pTag_ = {} ) VULKAN_HPP_NOEXCEPT
+ : objectType( objectType_ )
+ , objectHandle( objectHandle_ )
+ , tagName( tagName_ )
+ , tagSize( tagSize_ )
+ , pTag( pTag_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DebugUtilsObjectTagInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DebugUtilsObjectTagInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DebugUtilsObjectTagInfoEXT ) - offsetof( DebugUtilsObjectTagInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DebugUtilsObjectTagInfoEXT( VkDebugUtilsObjectTagInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DebugUtilsObjectTagInfoEXT& operator=( VkDebugUtilsObjectTagInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DebugUtilsObjectTagInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DebugUtilsObjectTagInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DebugUtilsObjectTagInfoEXT & setObjectType( VULKAN_HPP_NAMESPACE::ObjectType objectType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ objectType = objectType_;
+ return *this;
+ }
+
+ DebugUtilsObjectTagInfoEXT & setObjectHandle( uint64_t objectHandle_ ) VULKAN_HPP_NOEXCEPT
+ {
+ objectHandle = objectHandle_;
+ return *this;
+ }
+
+ DebugUtilsObjectTagInfoEXT & setTagName( uint64_t tagName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tagName = tagName_;
+ return *this;
+ }
+
+ DebugUtilsObjectTagInfoEXT & setTagSize( size_t tagSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tagSize = tagSize_;
+ return *this;
+ }
+
+ DebugUtilsObjectTagInfoEXT & setPTag( const void* pTag_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pTag = pTag_;
+ return *this;
+ }
+
+ operator VkDebugUtilsObjectTagInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDebugUtilsObjectTagInfoEXT*>( this );
+ }
+
+ operator VkDebugUtilsObjectTagInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDebugUtilsObjectTagInfoEXT*>( this );
+ }
+
+ bool operator==( DebugUtilsObjectTagInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( objectType == rhs.objectType )
+ && ( objectHandle == rhs.objectHandle )
+ && ( tagName == rhs.tagName )
+ && ( tagSize == rhs.tagSize )
+ && ( pTag == rhs.pTag );
+ }
+
+ bool operator!=( DebugUtilsObjectTagInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugUtilsObjectTagInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ObjectType objectType = VULKAN_HPP_NAMESPACE::ObjectType::eUnknown;
+ uint64_t objectHandle = {};
+ uint64_t tagName = {};
+ size_t tagSize = {};
+ const void* pTag = {};
+ };
+ static_assert( sizeof( DebugUtilsObjectTagInfoEXT ) == sizeof( VkDebugUtilsObjectTagInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DebugUtilsObjectTagInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DedicatedAllocationBufferCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR DedicatedAllocationBufferCreateInfoNV( VULKAN_HPP_NAMESPACE::Bool32 dedicatedAllocation_ = {} ) VULKAN_HPP_NOEXCEPT
+ : dedicatedAllocation( dedicatedAllocation_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DedicatedAllocationBufferCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::DedicatedAllocationBufferCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DedicatedAllocationBufferCreateInfoNV ) - offsetof( DedicatedAllocationBufferCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ DedicatedAllocationBufferCreateInfoNV( VkDedicatedAllocationBufferCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DedicatedAllocationBufferCreateInfoNV& operator=( VkDedicatedAllocationBufferCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DedicatedAllocationBufferCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ DedicatedAllocationBufferCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DedicatedAllocationBufferCreateInfoNV & setDedicatedAllocation( VULKAN_HPP_NAMESPACE::Bool32 dedicatedAllocation_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dedicatedAllocation = dedicatedAllocation_;
+ return *this;
+ }
+
+ operator VkDedicatedAllocationBufferCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDedicatedAllocationBufferCreateInfoNV*>( this );
+ }
+
+ operator VkDedicatedAllocationBufferCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDedicatedAllocationBufferCreateInfoNV*>( this );
+ }
+
+ bool operator==( DedicatedAllocationBufferCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( dedicatedAllocation == rhs.dedicatedAllocation );
+ }
+
+ bool operator!=( DedicatedAllocationBufferCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDedicatedAllocationBufferCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 dedicatedAllocation = {};
+ };
+ static_assert( sizeof( DedicatedAllocationBufferCreateInfoNV ) == sizeof( VkDedicatedAllocationBufferCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DedicatedAllocationBufferCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct DedicatedAllocationImageCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR DedicatedAllocationImageCreateInfoNV( VULKAN_HPP_NAMESPACE::Bool32 dedicatedAllocation_ = {} ) VULKAN_HPP_NOEXCEPT
+ : dedicatedAllocation( dedicatedAllocation_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DedicatedAllocationImageCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::DedicatedAllocationImageCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DedicatedAllocationImageCreateInfoNV ) - offsetof( DedicatedAllocationImageCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ DedicatedAllocationImageCreateInfoNV( VkDedicatedAllocationImageCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DedicatedAllocationImageCreateInfoNV& operator=( VkDedicatedAllocationImageCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DedicatedAllocationImageCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ DedicatedAllocationImageCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DedicatedAllocationImageCreateInfoNV & setDedicatedAllocation( VULKAN_HPP_NAMESPACE::Bool32 dedicatedAllocation_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dedicatedAllocation = dedicatedAllocation_;
+ return *this;
+ }
+
+ operator VkDedicatedAllocationImageCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDedicatedAllocationImageCreateInfoNV*>( this );
+ }
+
+ operator VkDedicatedAllocationImageCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDedicatedAllocationImageCreateInfoNV*>( this );
+ }
+
+ bool operator==( DedicatedAllocationImageCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( dedicatedAllocation == rhs.dedicatedAllocation );
+ }
+
+ bool operator!=( DedicatedAllocationImageCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDedicatedAllocationImageCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 dedicatedAllocation = {};
+ };
+ static_assert( sizeof( DedicatedAllocationImageCreateInfoNV ) == sizeof( VkDedicatedAllocationImageCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DedicatedAllocationImageCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct DedicatedAllocationMemoryAllocateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR DedicatedAllocationMemoryAllocateInfoNV( VULKAN_HPP_NAMESPACE::Image image_ = {},
+ VULKAN_HPP_NAMESPACE::Buffer buffer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : image( image_ )
+ , buffer( buffer_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DedicatedAllocationMemoryAllocateInfoNV & operator=( VULKAN_HPP_NAMESPACE::DedicatedAllocationMemoryAllocateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DedicatedAllocationMemoryAllocateInfoNV ) - offsetof( DedicatedAllocationMemoryAllocateInfoNV, pNext ) );
+ return *this;
+ }
+
+ DedicatedAllocationMemoryAllocateInfoNV( VkDedicatedAllocationMemoryAllocateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DedicatedAllocationMemoryAllocateInfoNV& operator=( VkDedicatedAllocationMemoryAllocateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DedicatedAllocationMemoryAllocateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ DedicatedAllocationMemoryAllocateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DedicatedAllocationMemoryAllocateInfoNV & setImage( VULKAN_HPP_NAMESPACE::Image image_ ) VULKAN_HPP_NOEXCEPT
+ {
+ image = image_;
+ return *this;
+ }
+
+ DedicatedAllocationMemoryAllocateInfoNV & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ operator VkDedicatedAllocationMemoryAllocateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDedicatedAllocationMemoryAllocateInfoNV*>( this );
+ }
+
+ operator VkDedicatedAllocationMemoryAllocateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDedicatedAllocationMemoryAllocateInfoNV*>( this );
+ }
+
+ bool operator==( DedicatedAllocationMemoryAllocateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( image == rhs.image )
+ && ( buffer == rhs.buffer );
+ }
+
+ bool operator!=( DedicatedAllocationMemoryAllocateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDedicatedAllocationMemoryAllocateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Image image = {};
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ };
+ static_assert( sizeof( DedicatedAllocationMemoryAllocateInfoNV ) == sizeof( VkDedicatedAllocationMemoryAllocateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DedicatedAllocationMemoryAllocateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorBufferInfo
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorBufferInfo( VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize range_ = {} ) VULKAN_HPP_NOEXCEPT
+ : buffer( buffer_ )
+ , offset( offset_ )
+ , range( range_ )
+ {}
+
+ DescriptorBufferInfo( VkDescriptorBufferInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorBufferInfo& operator=( VkDescriptorBufferInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorBufferInfo const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorBufferInfo & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ DescriptorBufferInfo & setOffset( VULKAN_HPP_NAMESPACE::DeviceSize offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ DescriptorBufferInfo & setRange( VULKAN_HPP_NAMESPACE::DeviceSize range_ ) VULKAN_HPP_NOEXCEPT
+ {
+ range = range_;
+ return *this;
+ }
+
+ operator VkDescriptorBufferInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorBufferInfo*>( this );
+ }
+
+ operator VkDescriptorBufferInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorBufferInfo*>( this );
+ }
+
+ bool operator==( DescriptorBufferInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( buffer == rhs.buffer )
+ && ( offset == rhs.offset )
+ && ( range == rhs.range );
+ }
+
+ bool operator!=( DescriptorBufferInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize range = {};
+ };
+ static_assert( sizeof( DescriptorBufferInfo ) == sizeof( VkDescriptorBufferInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorBufferInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorImageInfo
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorImageInfo( VULKAN_HPP_NAMESPACE::Sampler sampler_ = {},
+ VULKAN_HPP_NAMESPACE::ImageView imageView_ = {},
+ VULKAN_HPP_NAMESPACE::ImageLayout imageLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined ) VULKAN_HPP_NOEXCEPT
+ : sampler( sampler_ )
+ , imageView( imageView_ )
+ , imageLayout( imageLayout_ )
+ {}
+
+ DescriptorImageInfo( VkDescriptorImageInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorImageInfo& operator=( VkDescriptorImageInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorImageInfo const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorImageInfo & setSampler( VULKAN_HPP_NAMESPACE::Sampler sampler_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampler = sampler_;
+ return *this;
+ }
+
+ DescriptorImageInfo & setImageView( VULKAN_HPP_NAMESPACE::ImageView imageView_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageView = imageView_;
+ return *this;
+ }
+
+ DescriptorImageInfo & setImageLayout( VULKAN_HPP_NAMESPACE::ImageLayout imageLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageLayout = imageLayout_;
+ return *this;
+ }
+
+ operator VkDescriptorImageInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorImageInfo*>( this );
+ }
+
+ operator VkDescriptorImageInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorImageInfo*>( this );
+ }
+
+ bool operator==( DescriptorImageInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sampler == rhs.sampler )
+ && ( imageView == rhs.imageView )
+ && ( imageLayout == rhs.imageLayout );
+ }
+
+ bool operator!=( DescriptorImageInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Sampler sampler = {};
+ VULKAN_HPP_NAMESPACE::ImageView imageView = {};
+ VULKAN_HPP_NAMESPACE::ImageLayout imageLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ };
+ static_assert( sizeof( DescriptorImageInfo ) == sizeof( VkDescriptorImageInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorImageInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorPoolSize
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorPoolSize( VULKAN_HPP_NAMESPACE::DescriptorType type_ = VULKAN_HPP_NAMESPACE::DescriptorType::eSampler,
+ uint32_t descriptorCount_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , descriptorCount( descriptorCount_ )
+ {}
+
+ DescriptorPoolSize( VkDescriptorPoolSize const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorPoolSize& operator=( VkDescriptorPoolSize const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorPoolSize const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorPoolSize & setType( VULKAN_HPP_NAMESPACE::DescriptorType type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ DescriptorPoolSize & setDescriptorCount( uint32_t descriptorCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorCount = descriptorCount_;
+ return *this;
+ }
+
+ operator VkDescriptorPoolSize const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorPoolSize*>( this );
+ }
+
+ operator VkDescriptorPoolSize &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorPoolSize*>( this );
+ }
+
+ bool operator==( DescriptorPoolSize const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( type == rhs.type )
+ && ( descriptorCount == rhs.descriptorCount );
+ }
+
+ bool operator!=( DescriptorPoolSize const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DescriptorType type = VULKAN_HPP_NAMESPACE::DescriptorType::eSampler;
+ uint32_t descriptorCount = {};
+ };
+ static_assert( sizeof( DescriptorPoolSize ) == sizeof( VkDescriptorPoolSize ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorPoolSize>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorPoolCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorPoolCreateInfo( VULKAN_HPP_NAMESPACE::DescriptorPoolCreateFlags flags_ = {},
+ uint32_t maxSets_ = {},
+ uint32_t poolSizeCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DescriptorPoolSize* pPoolSizes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , maxSets( maxSets_ )
+ , poolSizeCount( poolSizeCount_ )
+ , pPoolSizes( pPoolSizes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DescriptorPoolCreateInfo & operator=( VULKAN_HPP_NAMESPACE::DescriptorPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DescriptorPoolCreateInfo ) - offsetof( DescriptorPoolCreateInfo, pNext ) );
+ return *this;
+ }
+
+ DescriptorPoolCreateInfo( VkDescriptorPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorPoolCreateInfo& operator=( VkDescriptorPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorPoolCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorPoolCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DescriptorPoolCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::DescriptorPoolCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DescriptorPoolCreateInfo & setMaxSets( uint32_t maxSets_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxSets = maxSets_;
+ return *this;
+ }
+
+ DescriptorPoolCreateInfo & setPoolSizeCount( uint32_t poolSizeCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ poolSizeCount = poolSizeCount_;
+ return *this;
+ }
+
+ DescriptorPoolCreateInfo & setPPoolSizes( const VULKAN_HPP_NAMESPACE::DescriptorPoolSize* pPoolSizes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pPoolSizes = pPoolSizes_;
+ return *this;
+ }
+
+ operator VkDescriptorPoolCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorPoolCreateInfo*>( this );
+ }
+
+ operator VkDescriptorPoolCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorPoolCreateInfo*>( this );
+ }
+
+ bool operator==( DescriptorPoolCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( maxSets == rhs.maxSets )
+ && ( poolSizeCount == rhs.poolSizeCount )
+ && ( pPoolSizes == rhs.pPoolSizes );
+ }
+
+ bool operator!=( DescriptorPoolCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDescriptorPoolCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DescriptorPoolCreateFlags flags = {};
+ uint32_t maxSets = {};
+ uint32_t poolSizeCount = {};
+ const VULKAN_HPP_NAMESPACE::DescriptorPoolSize* pPoolSizes = {};
+ };
+ static_assert( sizeof( DescriptorPoolCreateInfo ) == sizeof( VkDescriptorPoolCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorPoolCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorPoolInlineUniformBlockCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorPoolInlineUniformBlockCreateInfoEXT( uint32_t maxInlineUniformBlockBindings_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxInlineUniformBlockBindings( maxInlineUniformBlockBindings_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DescriptorPoolInlineUniformBlockCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DescriptorPoolInlineUniformBlockCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DescriptorPoolInlineUniformBlockCreateInfoEXT ) - offsetof( DescriptorPoolInlineUniformBlockCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DescriptorPoolInlineUniformBlockCreateInfoEXT( VkDescriptorPoolInlineUniformBlockCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorPoolInlineUniformBlockCreateInfoEXT& operator=( VkDescriptorPoolInlineUniformBlockCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorPoolInlineUniformBlockCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorPoolInlineUniformBlockCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DescriptorPoolInlineUniformBlockCreateInfoEXT & setMaxInlineUniformBlockBindings( uint32_t maxInlineUniformBlockBindings_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxInlineUniformBlockBindings = maxInlineUniformBlockBindings_;
+ return *this;
+ }
+
+ operator VkDescriptorPoolInlineUniformBlockCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorPoolInlineUniformBlockCreateInfoEXT*>( this );
+ }
+
+ operator VkDescriptorPoolInlineUniformBlockCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorPoolInlineUniformBlockCreateInfoEXT*>( this );
+ }
+
+ bool operator==( DescriptorPoolInlineUniformBlockCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxInlineUniformBlockBindings == rhs.maxInlineUniformBlockBindings );
+ }
+
+ bool operator!=( DescriptorPoolInlineUniformBlockCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDescriptorPoolInlineUniformBlockCreateInfoEXT;
+ const void* pNext = {};
+ uint32_t maxInlineUniformBlockBindings = {};
+ };
+ static_assert( sizeof( DescriptorPoolInlineUniformBlockCreateInfoEXT ) == sizeof( VkDescriptorPoolInlineUniformBlockCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorPoolInlineUniformBlockCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorSetAllocateInfo
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorSetAllocateInfo( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool_ = {},
+ uint32_t descriptorSetCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DescriptorSetLayout* pSetLayouts_ = {} ) VULKAN_HPP_NOEXCEPT
+ : descriptorPool( descriptorPool_ )
+ , descriptorSetCount( descriptorSetCount_ )
+ , pSetLayouts( pSetLayouts_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DescriptorSetAllocateInfo & operator=( VULKAN_HPP_NAMESPACE::DescriptorSetAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DescriptorSetAllocateInfo ) - offsetof( DescriptorSetAllocateInfo, pNext ) );
+ return *this;
+ }
+
+ DescriptorSetAllocateInfo( VkDescriptorSetAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorSetAllocateInfo& operator=( VkDescriptorSetAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorSetAllocateInfo const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorSetAllocateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DescriptorSetAllocateInfo & setDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorPool = descriptorPool_;
+ return *this;
+ }
+
+ DescriptorSetAllocateInfo & setDescriptorSetCount( uint32_t descriptorSetCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorSetCount = descriptorSetCount_;
+ return *this;
+ }
+
+ DescriptorSetAllocateInfo & setPSetLayouts( const VULKAN_HPP_NAMESPACE::DescriptorSetLayout* pSetLayouts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSetLayouts = pSetLayouts_;
+ return *this;
+ }
+
+ operator VkDescriptorSetAllocateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorSetAllocateInfo*>( this );
+ }
+
+ operator VkDescriptorSetAllocateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorSetAllocateInfo*>( this );
+ }
+
+ bool operator==( DescriptorSetAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( descriptorPool == rhs.descriptorPool )
+ && ( descriptorSetCount == rhs.descriptorSetCount )
+ && ( pSetLayouts == rhs.pSetLayouts );
+ }
+
+ bool operator!=( DescriptorSetAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDescriptorSetAllocateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool = {};
+ uint32_t descriptorSetCount = {};
+ const VULKAN_HPP_NAMESPACE::DescriptorSetLayout* pSetLayouts = {};
+ };
+ static_assert( sizeof( DescriptorSetAllocateInfo ) == sizeof( VkDescriptorSetAllocateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorSetAllocateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorSetLayoutBinding
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorSetLayoutBinding( uint32_t binding_ = {},
+ VULKAN_HPP_NAMESPACE::DescriptorType descriptorType_ = VULKAN_HPP_NAMESPACE::DescriptorType::eSampler,
+ uint32_t descriptorCount_ = {},
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags_ = {},
+ const VULKAN_HPP_NAMESPACE::Sampler* pImmutableSamplers_ = {} ) VULKAN_HPP_NOEXCEPT
+ : binding( binding_ )
+ , descriptorType( descriptorType_ )
+ , descriptorCount( descriptorCount_ )
+ , stageFlags( stageFlags_ )
+ , pImmutableSamplers( pImmutableSamplers_ )
+ {}
+
+ DescriptorSetLayoutBinding( VkDescriptorSetLayoutBinding const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorSetLayoutBinding& operator=( VkDescriptorSetLayoutBinding const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorSetLayoutBinding const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorSetLayoutBinding & setBinding( uint32_t binding_ ) VULKAN_HPP_NOEXCEPT
+ {
+ binding = binding_;
+ return *this;
+ }
+
+ DescriptorSetLayoutBinding & setDescriptorType( VULKAN_HPP_NAMESPACE::DescriptorType descriptorType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorType = descriptorType_;
+ return *this;
+ }
+
+ DescriptorSetLayoutBinding & setDescriptorCount( uint32_t descriptorCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorCount = descriptorCount_;
+ return *this;
+ }
+
+ DescriptorSetLayoutBinding & setStageFlags( VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stageFlags = stageFlags_;
+ return *this;
+ }
+
+ DescriptorSetLayoutBinding & setPImmutableSamplers( const VULKAN_HPP_NAMESPACE::Sampler* pImmutableSamplers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pImmutableSamplers = pImmutableSamplers_;
+ return *this;
+ }
+
+ operator VkDescriptorSetLayoutBinding const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorSetLayoutBinding*>( this );
+ }
+
+ operator VkDescriptorSetLayoutBinding &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorSetLayoutBinding*>( this );
+ }
+
+ bool operator==( DescriptorSetLayoutBinding const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( binding == rhs.binding )
+ && ( descriptorType == rhs.descriptorType )
+ && ( descriptorCount == rhs.descriptorCount )
+ && ( stageFlags == rhs.stageFlags )
+ && ( pImmutableSamplers == rhs.pImmutableSamplers );
+ }
+
+ bool operator!=( DescriptorSetLayoutBinding const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t binding = {};
+ VULKAN_HPP_NAMESPACE::DescriptorType descriptorType = VULKAN_HPP_NAMESPACE::DescriptorType::eSampler;
+ uint32_t descriptorCount = {};
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags = {};
+ const VULKAN_HPP_NAMESPACE::Sampler* pImmutableSamplers = {};
+ };
+ static_assert( sizeof( DescriptorSetLayoutBinding ) == sizeof( VkDescriptorSetLayoutBinding ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorSetLayoutBinding>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorSetLayoutBindingFlagsCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorSetLayoutBindingFlagsCreateInfo( uint32_t bindingCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DescriptorBindingFlags* pBindingFlags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : bindingCount( bindingCount_ )
+ , pBindingFlags( pBindingFlags_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayoutBindingFlagsCreateInfo & operator=( VULKAN_HPP_NAMESPACE::DescriptorSetLayoutBindingFlagsCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DescriptorSetLayoutBindingFlagsCreateInfo ) - offsetof( DescriptorSetLayoutBindingFlagsCreateInfo, pNext ) );
+ return *this;
+ }
+
+ DescriptorSetLayoutBindingFlagsCreateInfo( VkDescriptorSetLayoutBindingFlagsCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorSetLayoutBindingFlagsCreateInfo& operator=( VkDescriptorSetLayoutBindingFlagsCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorSetLayoutBindingFlagsCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorSetLayoutBindingFlagsCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DescriptorSetLayoutBindingFlagsCreateInfo & setBindingCount( uint32_t bindingCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bindingCount = bindingCount_;
+ return *this;
+ }
+
+ DescriptorSetLayoutBindingFlagsCreateInfo & setPBindingFlags( const VULKAN_HPP_NAMESPACE::DescriptorBindingFlags* pBindingFlags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pBindingFlags = pBindingFlags_;
+ return *this;
+ }
+
+ operator VkDescriptorSetLayoutBindingFlagsCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorSetLayoutBindingFlagsCreateInfo*>( this );
+ }
+
+ operator VkDescriptorSetLayoutBindingFlagsCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorSetLayoutBindingFlagsCreateInfo*>( this );
+ }
+
+ bool operator==( DescriptorSetLayoutBindingFlagsCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( bindingCount == rhs.bindingCount )
+ && ( pBindingFlags == rhs.pBindingFlags );
+ }
+
+ bool operator!=( DescriptorSetLayoutBindingFlagsCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDescriptorSetLayoutBindingFlagsCreateInfo;
+ const void* pNext = {};
+ uint32_t bindingCount = {};
+ const VULKAN_HPP_NAMESPACE::DescriptorBindingFlags* pBindingFlags = {};
+ };
+ static_assert( sizeof( DescriptorSetLayoutBindingFlagsCreateInfo ) == sizeof( VkDescriptorSetLayoutBindingFlagsCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorSetLayoutBindingFlagsCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorSetLayoutCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorSetLayoutCreateInfo( VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateFlags flags_ = {},
+ uint32_t bindingCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutBinding* pBindings_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , bindingCount( bindingCount_ )
+ , pBindings( pBindings_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo & operator=( VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo ) - offsetof( DescriptorSetLayoutCreateInfo, pNext ) );
+ return *this;
+ }
+
+ DescriptorSetLayoutCreateInfo( VkDescriptorSetLayoutCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorSetLayoutCreateInfo& operator=( VkDescriptorSetLayoutCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorSetLayoutCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DescriptorSetLayoutCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DescriptorSetLayoutCreateInfo & setBindingCount( uint32_t bindingCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bindingCount = bindingCount_;
+ return *this;
+ }
+
+ DescriptorSetLayoutCreateInfo & setPBindings( const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutBinding* pBindings_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pBindings = pBindings_;
+ return *this;
+ }
+
+ operator VkDescriptorSetLayoutCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( this );
+ }
+
+ operator VkDescriptorSetLayoutCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorSetLayoutCreateInfo*>( this );
+ }
+
+ bool operator==( DescriptorSetLayoutCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( bindingCount == rhs.bindingCount )
+ && ( pBindings == rhs.pBindings );
+ }
+
+ bool operator!=( DescriptorSetLayoutCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDescriptorSetLayoutCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateFlags flags = {};
+ uint32_t bindingCount = {};
+ const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutBinding* pBindings = {};
+ };
+ static_assert( sizeof( DescriptorSetLayoutCreateInfo ) == sizeof( VkDescriptorSetLayoutCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorSetLayoutCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorSetLayoutSupport
+ {
+ DescriptorSetLayoutSupport( VULKAN_HPP_NAMESPACE::Bool32 supported_ = {} ) VULKAN_HPP_NOEXCEPT
+ : supported( supported_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport & operator=( VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport ) - offsetof( DescriptorSetLayoutSupport, pNext ) );
+ return *this;
+ }
+
+ DescriptorSetLayoutSupport( VkDescriptorSetLayoutSupport const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorSetLayoutSupport& operator=( VkDescriptorSetLayoutSupport const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDescriptorSetLayoutSupport const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorSetLayoutSupport*>( this );
+ }
+
+ operator VkDescriptorSetLayoutSupport &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorSetLayoutSupport*>( this );
+ }
+
+ bool operator==( DescriptorSetLayoutSupport const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( supported == rhs.supported );
+ }
+
+ bool operator!=( DescriptorSetLayoutSupport const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDescriptorSetLayoutSupport;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 supported = {};
+ };
+ static_assert( sizeof( DescriptorSetLayoutSupport ) == sizeof( VkDescriptorSetLayoutSupport ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorSetLayoutSupport>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorSetVariableDescriptorCountAllocateInfo
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorSetVariableDescriptorCountAllocateInfo( uint32_t descriptorSetCount_ = {},
+ const uint32_t* pDescriptorCounts_ = {} ) VULKAN_HPP_NOEXCEPT
+ : descriptorSetCount( descriptorSetCount_ )
+ , pDescriptorCounts( pDescriptorCounts_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DescriptorSetVariableDescriptorCountAllocateInfo & operator=( VULKAN_HPP_NAMESPACE::DescriptorSetVariableDescriptorCountAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DescriptorSetVariableDescriptorCountAllocateInfo ) - offsetof( DescriptorSetVariableDescriptorCountAllocateInfo, pNext ) );
+ return *this;
+ }
+
+ DescriptorSetVariableDescriptorCountAllocateInfo( VkDescriptorSetVariableDescriptorCountAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorSetVariableDescriptorCountAllocateInfo& operator=( VkDescriptorSetVariableDescriptorCountAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorSetVariableDescriptorCountAllocateInfo const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorSetVariableDescriptorCountAllocateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DescriptorSetVariableDescriptorCountAllocateInfo & setDescriptorSetCount( uint32_t descriptorSetCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorSetCount = descriptorSetCount_;
+ return *this;
+ }
+
+ DescriptorSetVariableDescriptorCountAllocateInfo & setPDescriptorCounts( const uint32_t* pDescriptorCounts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDescriptorCounts = pDescriptorCounts_;
+ return *this;
+ }
+
+ operator VkDescriptorSetVariableDescriptorCountAllocateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorSetVariableDescriptorCountAllocateInfo*>( this );
+ }
+
+ operator VkDescriptorSetVariableDescriptorCountAllocateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorSetVariableDescriptorCountAllocateInfo*>( this );
+ }
+
+ bool operator==( DescriptorSetVariableDescriptorCountAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( descriptorSetCount == rhs.descriptorSetCount )
+ && ( pDescriptorCounts == rhs.pDescriptorCounts );
+ }
+
+ bool operator!=( DescriptorSetVariableDescriptorCountAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDescriptorSetVariableDescriptorCountAllocateInfo;
+ const void* pNext = {};
+ uint32_t descriptorSetCount = {};
+ const uint32_t* pDescriptorCounts = {};
+ };
+ static_assert( sizeof( DescriptorSetVariableDescriptorCountAllocateInfo ) == sizeof( VkDescriptorSetVariableDescriptorCountAllocateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorSetVariableDescriptorCountAllocateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorSetVariableDescriptorCountLayoutSupport
+ {
+ DescriptorSetVariableDescriptorCountLayoutSupport( uint32_t maxVariableDescriptorCount_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxVariableDescriptorCount( maxVariableDescriptorCount_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DescriptorSetVariableDescriptorCountLayoutSupport & operator=( VULKAN_HPP_NAMESPACE::DescriptorSetVariableDescriptorCountLayoutSupport const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DescriptorSetVariableDescriptorCountLayoutSupport ) - offsetof( DescriptorSetVariableDescriptorCountLayoutSupport, pNext ) );
+ return *this;
+ }
+
+ DescriptorSetVariableDescriptorCountLayoutSupport( VkDescriptorSetVariableDescriptorCountLayoutSupport const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorSetVariableDescriptorCountLayoutSupport& operator=( VkDescriptorSetVariableDescriptorCountLayoutSupport const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorSetVariableDescriptorCountLayoutSupport const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDescriptorSetVariableDescriptorCountLayoutSupport const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorSetVariableDescriptorCountLayoutSupport*>( this );
+ }
+
+ operator VkDescriptorSetVariableDescriptorCountLayoutSupport &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorSetVariableDescriptorCountLayoutSupport*>( this );
+ }
+
+ bool operator==( DescriptorSetVariableDescriptorCountLayoutSupport const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxVariableDescriptorCount == rhs.maxVariableDescriptorCount );
+ }
+
+ bool operator!=( DescriptorSetVariableDescriptorCountLayoutSupport const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDescriptorSetVariableDescriptorCountLayoutSupport;
+ void* pNext = {};
+ uint32_t maxVariableDescriptorCount = {};
+ };
+ static_assert( sizeof( DescriptorSetVariableDescriptorCountLayoutSupport ) == sizeof( VkDescriptorSetVariableDescriptorCountLayoutSupport ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorSetVariableDescriptorCountLayoutSupport>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorUpdateTemplateEntry
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorUpdateTemplateEntry( uint32_t dstBinding_ = {},
+ uint32_t dstArrayElement_ = {},
+ uint32_t descriptorCount_ = {},
+ VULKAN_HPP_NAMESPACE::DescriptorType descriptorType_ = VULKAN_HPP_NAMESPACE::DescriptorType::eSampler,
+ size_t offset_ = {},
+ size_t stride_ = {} ) VULKAN_HPP_NOEXCEPT
+ : dstBinding( dstBinding_ )
+ , dstArrayElement( dstArrayElement_ )
+ , descriptorCount( descriptorCount_ )
+ , descriptorType( descriptorType_ )
+ , offset( offset_ )
+ , stride( stride_ )
+ {}
+
+ DescriptorUpdateTemplateEntry( VkDescriptorUpdateTemplateEntry const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorUpdateTemplateEntry& operator=( VkDescriptorUpdateTemplateEntry const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateEntry const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorUpdateTemplateEntry & setDstBinding( uint32_t dstBinding_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstBinding = dstBinding_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateEntry & setDstArrayElement( uint32_t dstArrayElement_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstArrayElement = dstArrayElement_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateEntry & setDescriptorCount( uint32_t descriptorCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorCount = descriptorCount_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateEntry & setDescriptorType( VULKAN_HPP_NAMESPACE::DescriptorType descriptorType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorType = descriptorType_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateEntry & setOffset( size_t offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateEntry & setStride( size_t stride_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stride = stride_;
+ return *this;
+ }
+
+ operator VkDescriptorUpdateTemplateEntry const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorUpdateTemplateEntry*>( this );
+ }
+
+ operator VkDescriptorUpdateTemplateEntry &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorUpdateTemplateEntry*>( this );
+ }
+
+ bool operator==( DescriptorUpdateTemplateEntry const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( dstBinding == rhs.dstBinding )
+ && ( dstArrayElement == rhs.dstArrayElement )
+ && ( descriptorCount == rhs.descriptorCount )
+ && ( descriptorType == rhs.descriptorType )
+ && ( offset == rhs.offset )
+ && ( stride == rhs.stride );
+ }
+
+ bool operator!=( DescriptorUpdateTemplateEntry const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t dstBinding = {};
+ uint32_t dstArrayElement = {};
+ uint32_t descriptorCount = {};
+ VULKAN_HPP_NAMESPACE::DescriptorType descriptorType = VULKAN_HPP_NAMESPACE::DescriptorType::eSampler;
+ size_t offset = {};
+ size_t stride = {};
+ };
+ static_assert( sizeof( DescriptorUpdateTemplateEntry ) == sizeof( VkDescriptorUpdateTemplateEntry ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorUpdateTemplateEntry>::value, "struct wrapper is not a standard layout!" );
+
+ struct DescriptorUpdateTemplateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR DescriptorUpdateTemplateCreateInfo( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateFlags flags_ = {},
+ uint32_t descriptorUpdateEntryCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateEntry* pDescriptorUpdateEntries_ = {},
+ VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateType templateType_ = VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateType::eDescriptorSet,
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics,
+ VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ = {},
+ uint32_t set_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , descriptorUpdateEntryCount( descriptorUpdateEntryCount_ )
+ , pDescriptorUpdateEntries( pDescriptorUpdateEntries_ )
+ , templateType( templateType_ )
+ , descriptorSetLayout( descriptorSetLayout_ )
+ , pipelineBindPoint( pipelineBindPoint_ )
+ , pipelineLayout( pipelineLayout_ )
+ , set( set_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateInfo ) - offsetof( DescriptorUpdateTemplateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ DescriptorUpdateTemplateCreateInfo( VkDescriptorUpdateTemplateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DescriptorUpdateTemplateCreateInfo& operator=( VkDescriptorUpdateTemplateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ DescriptorUpdateTemplateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateCreateInfo & setDescriptorUpdateEntryCount( uint32_t descriptorUpdateEntryCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorUpdateEntryCount = descriptorUpdateEntryCount_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateCreateInfo & setPDescriptorUpdateEntries( const VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateEntry* pDescriptorUpdateEntries_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDescriptorUpdateEntries = pDescriptorUpdateEntries_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateCreateInfo & setTemplateType( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateType templateType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ templateType = templateType_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateCreateInfo & setDescriptorSetLayout( VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorSetLayout = descriptorSetLayout_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateCreateInfo & setPipelineBindPoint( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineBindPoint = pipelineBindPoint_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateCreateInfo & setPipelineLayout( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineLayout = pipelineLayout_;
+ return *this;
+ }
+
+ DescriptorUpdateTemplateCreateInfo & setSet( uint32_t set_ ) VULKAN_HPP_NOEXCEPT
+ {
+ set = set_;
+ return *this;
+ }
+
+ operator VkDescriptorUpdateTemplateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( this );
+ }
+
+ operator VkDescriptorUpdateTemplateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDescriptorUpdateTemplateCreateInfo*>( this );
+ }
+
+ bool operator==( DescriptorUpdateTemplateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( descriptorUpdateEntryCount == rhs.descriptorUpdateEntryCount )
+ && ( pDescriptorUpdateEntries == rhs.pDescriptorUpdateEntries )
+ && ( templateType == rhs.templateType )
+ && ( descriptorSetLayout == rhs.descriptorSetLayout )
+ && ( pipelineBindPoint == rhs.pipelineBindPoint )
+ && ( pipelineLayout == rhs.pipelineLayout )
+ && ( set == rhs.set );
+ }
+
+ bool operator!=( DescriptorUpdateTemplateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDescriptorUpdateTemplateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateFlags flags = {};
+ uint32_t descriptorUpdateEntryCount = {};
+ const VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateEntry* pDescriptorUpdateEntries = {};
+ VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateType templateType = VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateType::eDescriptorSet;
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout = {};
+ VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics;
+ VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout = {};
+ uint32_t set = {};
+ };
+ static_assert( sizeof( DescriptorUpdateTemplateCreateInfo ) == sizeof( VkDescriptorUpdateTemplateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DescriptorUpdateTemplateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceQueueCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR DeviceQueueCreateInfo( VULKAN_HPP_NAMESPACE::DeviceQueueCreateFlags flags_ = {},
+ uint32_t queueFamilyIndex_ = {},
+ uint32_t queueCount_ = {},
+ const float* pQueuePriorities_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , queueFamilyIndex( queueFamilyIndex_ )
+ , queueCount( queueCount_ )
+ , pQueuePriorities( pQueuePriorities_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceQueueCreateInfo & operator=( VULKAN_HPP_NAMESPACE::DeviceQueueCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceQueueCreateInfo ) - offsetof( DeviceQueueCreateInfo, pNext ) );
+ return *this;
+ }
+
+ DeviceQueueCreateInfo( VkDeviceQueueCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceQueueCreateInfo& operator=( VkDeviceQueueCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceQueueCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ DeviceQueueCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceQueueCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::DeviceQueueCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DeviceQueueCreateInfo & setQueueFamilyIndex( uint32_t queueFamilyIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueFamilyIndex = queueFamilyIndex_;
+ return *this;
+ }
+
+ DeviceQueueCreateInfo & setQueueCount( uint32_t queueCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueCount = queueCount_;
+ return *this;
+ }
+
+ DeviceQueueCreateInfo & setPQueuePriorities( const float* pQueuePriorities_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pQueuePriorities = pQueuePriorities_;
+ return *this;
+ }
+
+ operator VkDeviceQueueCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceQueueCreateInfo*>( this );
+ }
+
+ operator VkDeviceQueueCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceQueueCreateInfo*>( this );
+ }
+
+ bool operator==( DeviceQueueCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( queueFamilyIndex == rhs.queueFamilyIndex )
+ && ( queueCount == rhs.queueCount )
+ && ( pQueuePriorities == rhs.pQueuePriorities );
+ }
+
+ bool operator!=( DeviceQueueCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceQueueCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceQueueCreateFlags flags = {};
+ uint32_t queueFamilyIndex = {};
+ uint32_t queueCount = {};
+ const float* pQueuePriorities = {};
+ };
+ static_assert( sizeof( DeviceQueueCreateInfo ) == sizeof( VkDeviceQueueCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceQueueCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceFeatures( VULKAN_HPP_NAMESPACE::Bool32 robustBufferAccess_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 fullDrawIndexUint32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 imageCubeArray_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 independentBlend_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 geometryShader_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 tessellationShader_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 sampleRateShading_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 dualSrcBlend_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 logicOp_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 multiDrawIndirect_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 drawIndirectFirstInstance_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 depthClamp_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 depthBiasClamp_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 fillModeNonSolid_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 depthBounds_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 wideLines_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 largePoints_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 alphaToOne_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 multiViewport_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 samplerAnisotropy_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 textureCompressionETC2_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 textureCompressionASTC_LDR_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 textureCompressionBC_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 occlusionQueryPrecise_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 pipelineStatisticsQuery_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 vertexPipelineStoresAndAtomics_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentStoresAndAtomics_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderTessellationAndGeometryPointSize_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderImageGatherExtended_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageExtendedFormats_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageMultisample_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageReadWithoutFormat_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageWriteWithoutFormat_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayDynamicIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayDynamicIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayDynamicIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayDynamicIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderClipDistance_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderCullDistance_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderFloat64_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInt64_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInt16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderResourceResidency_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderResourceMinLod_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 sparseBinding_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyBuffer_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyImage2D_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyImage3D_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidency2Samples_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidency4Samples_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidency8Samples_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidency16Samples_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyAliased_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 variableMultisampleRate_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 inheritedQueries_ = {} ) VULKAN_HPP_NOEXCEPT
+ : robustBufferAccess( robustBufferAccess_ )
+ , fullDrawIndexUint32( fullDrawIndexUint32_ )
+ , imageCubeArray( imageCubeArray_ )
+ , independentBlend( independentBlend_ )
+ , geometryShader( geometryShader_ )
+ , tessellationShader( tessellationShader_ )
+ , sampleRateShading( sampleRateShading_ )
+ , dualSrcBlend( dualSrcBlend_ )
+ , logicOp( logicOp_ )
+ , multiDrawIndirect( multiDrawIndirect_ )
+ , drawIndirectFirstInstance( drawIndirectFirstInstance_ )
+ , depthClamp( depthClamp_ )
+ , depthBiasClamp( depthBiasClamp_ )
+ , fillModeNonSolid( fillModeNonSolid_ )
+ , depthBounds( depthBounds_ )
+ , wideLines( wideLines_ )
+ , largePoints( largePoints_ )
+ , alphaToOne( alphaToOne_ )
+ , multiViewport( multiViewport_ )
+ , samplerAnisotropy( samplerAnisotropy_ )
+ , textureCompressionETC2( textureCompressionETC2_ )
+ , textureCompressionASTC_LDR( textureCompressionASTC_LDR_ )
+ , textureCompressionBC( textureCompressionBC_ )
+ , occlusionQueryPrecise( occlusionQueryPrecise_ )
+ , pipelineStatisticsQuery( pipelineStatisticsQuery_ )
+ , vertexPipelineStoresAndAtomics( vertexPipelineStoresAndAtomics_ )
+ , fragmentStoresAndAtomics( fragmentStoresAndAtomics_ )
+ , shaderTessellationAndGeometryPointSize( shaderTessellationAndGeometryPointSize_ )
+ , shaderImageGatherExtended( shaderImageGatherExtended_ )
+ , shaderStorageImageExtendedFormats( shaderStorageImageExtendedFormats_ )
+ , shaderStorageImageMultisample( shaderStorageImageMultisample_ )
+ , shaderStorageImageReadWithoutFormat( shaderStorageImageReadWithoutFormat_ )
+ , shaderStorageImageWriteWithoutFormat( shaderStorageImageWriteWithoutFormat_ )
+ , shaderUniformBufferArrayDynamicIndexing( shaderUniformBufferArrayDynamicIndexing_ )
+ , shaderSampledImageArrayDynamicIndexing( shaderSampledImageArrayDynamicIndexing_ )
+ , shaderStorageBufferArrayDynamicIndexing( shaderStorageBufferArrayDynamicIndexing_ )
+ , shaderStorageImageArrayDynamicIndexing( shaderStorageImageArrayDynamicIndexing_ )
+ , shaderClipDistance( shaderClipDistance_ )
+ , shaderCullDistance( shaderCullDistance_ )
+ , shaderFloat64( shaderFloat64_ )
+ , shaderInt64( shaderInt64_ )
+ , shaderInt16( shaderInt16_ )
+ , shaderResourceResidency( shaderResourceResidency_ )
+ , shaderResourceMinLod( shaderResourceMinLod_ )
+ , sparseBinding( sparseBinding_ )
+ , sparseResidencyBuffer( sparseResidencyBuffer_ )
+ , sparseResidencyImage2D( sparseResidencyImage2D_ )
+ , sparseResidencyImage3D( sparseResidencyImage3D_ )
+ , sparseResidency2Samples( sparseResidency2Samples_ )
+ , sparseResidency4Samples( sparseResidency4Samples_ )
+ , sparseResidency8Samples( sparseResidency8Samples_ )
+ , sparseResidency16Samples( sparseResidency16Samples_ )
+ , sparseResidencyAliased( sparseResidencyAliased_ )
+ , variableMultisampleRate( variableMultisampleRate_ )
+ , inheritedQueries( inheritedQueries_ )
+ {}
+
+ PhysicalDeviceFeatures( VkPhysicalDeviceFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceFeatures& operator=( VkPhysicalDeviceFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setRobustBufferAccess( VULKAN_HPP_NAMESPACE::Bool32 robustBufferAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ robustBufferAccess = robustBufferAccess_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setFullDrawIndexUint32( VULKAN_HPP_NAMESPACE::Bool32 fullDrawIndexUint32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fullDrawIndexUint32 = fullDrawIndexUint32_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setImageCubeArray( VULKAN_HPP_NAMESPACE::Bool32 imageCubeArray_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageCubeArray = imageCubeArray_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setIndependentBlend( VULKAN_HPP_NAMESPACE::Bool32 independentBlend_ ) VULKAN_HPP_NOEXCEPT
+ {
+ independentBlend = independentBlend_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setGeometryShader( VULKAN_HPP_NAMESPACE::Bool32 geometryShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ geometryShader = geometryShader_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setTessellationShader( VULKAN_HPP_NAMESPACE::Bool32 tessellationShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tessellationShader = tessellationShader_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSampleRateShading( VULKAN_HPP_NAMESPACE::Bool32 sampleRateShading_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleRateShading = sampleRateShading_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setDualSrcBlend( VULKAN_HPP_NAMESPACE::Bool32 dualSrcBlend_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dualSrcBlend = dualSrcBlend_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setLogicOp( VULKAN_HPP_NAMESPACE::Bool32 logicOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ logicOp = logicOp_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setMultiDrawIndirect( VULKAN_HPP_NAMESPACE::Bool32 multiDrawIndirect_ ) VULKAN_HPP_NOEXCEPT
+ {
+ multiDrawIndirect = multiDrawIndirect_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setDrawIndirectFirstInstance( VULKAN_HPP_NAMESPACE::Bool32 drawIndirectFirstInstance_ ) VULKAN_HPP_NOEXCEPT
+ {
+ drawIndirectFirstInstance = drawIndirectFirstInstance_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setDepthClamp( VULKAN_HPP_NAMESPACE::Bool32 depthClamp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthClamp = depthClamp_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setDepthBiasClamp( VULKAN_HPP_NAMESPACE::Bool32 depthBiasClamp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthBiasClamp = depthBiasClamp_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setFillModeNonSolid( VULKAN_HPP_NAMESPACE::Bool32 fillModeNonSolid_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fillModeNonSolid = fillModeNonSolid_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setDepthBounds( VULKAN_HPP_NAMESPACE::Bool32 depthBounds_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthBounds = depthBounds_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setWideLines( VULKAN_HPP_NAMESPACE::Bool32 wideLines_ ) VULKAN_HPP_NOEXCEPT
+ {
+ wideLines = wideLines_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setLargePoints( VULKAN_HPP_NAMESPACE::Bool32 largePoints_ ) VULKAN_HPP_NOEXCEPT
+ {
+ largePoints = largePoints_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setAlphaToOne( VULKAN_HPP_NAMESPACE::Bool32 alphaToOne_ ) VULKAN_HPP_NOEXCEPT
+ {
+ alphaToOne = alphaToOne_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setMultiViewport( VULKAN_HPP_NAMESPACE::Bool32 multiViewport_ ) VULKAN_HPP_NOEXCEPT
+ {
+ multiViewport = multiViewport_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSamplerAnisotropy( VULKAN_HPP_NAMESPACE::Bool32 samplerAnisotropy_ ) VULKAN_HPP_NOEXCEPT
+ {
+ samplerAnisotropy = samplerAnisotropy_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setTextureCompressionETC2( VULKAN_HPP_NAMESPACE::Bool32 textureCompressionETC2_ ) VULKAN_HPP_NOEXCEPT
+ {
+ textureCompressionETC2 = textureCompressionETC2_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setTextureCompressionASTC_LDR( VULKAN_HPP_NAMESPACE::Bool32 textureCompressionASTC_LDR_ ) VULKAN_HPP_NOEXCEPT
+ {
+ textureCompressionASTC_LDR = textureCompressionASTC_LDR_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setTextureCompressionBC( VULKAN_HPP_NAMESPACE::Bool32 textureCompressionBC_ ) VULKAN_HPP_NOEXCEPT
+ {
+ textureCompressionBC = textureCompressionBC_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setOcclusionQueryPrecise( VULKAN_HPP_NAMESPACE::Bool32 occlusionQueryPrecise_ ) VULKAN_HPP_NOEXCEPT
+ {
+ occlusionQueryPrecise = occlusionQueryPrecise_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setPipelineStatisticsQuery( VULKAN_HPP_NAMESPACE::Bool32 pipelineStatisticsQuery_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineStatisticsQuery = pipelineStatisticsQuery_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setVertexPipelineStoresAndAtomics( VULKAN_HPP_NAMESPACE::Bool32 vertexPipelineStoresAndAtomics_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexPipelineStoresAndAtomics = vertexPipelineStoresAndAtomics_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setFragmentStoresAndAtomics( VULKAN_HPP_NAMESPACE::Bool32 fragmentStoresAndAtomics_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fragmentStoresAndAtomics = fragmentStoresAndAtomics_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderTessellationAndGeometryPointSize( VULKAN_HPP_NAMESPACE::Bool32 shaderTessellationAndGeometryPointSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderTessellationAndGeometryPointSize = shaderTessellationAndGeometryPointSize_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderImageGatherExtended( VULKAN_HPP_NAMESPACE::Bool32 shaderImageGatherExtended_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderImageGatherExtended = shaderImageGatherExtended_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderStorageImageExtendedFormats( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageExtendedFormats_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageImageExtendedFormats = shaderStorageImageExtendedFormats_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderStorageImageMultisample( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageMultisample_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageImageMultisample = shaderStorageImageMultisample_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderStorageImageReadWithoutFormat( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageReadWithoutFormat_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageImageReadWithoutFormat = shaderStorageImageReadWithoutFormat_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderStorageImageWriteWithoutFormat( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageWriteWithoutFormat_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageImageWriteWithoutFormat = shaderStorageImageWriteWithoutFormat_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderUniformBufferArrayDynamicIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayDynamicIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderUniformBufferArrayDynamicIndexing = shaderUniformBufferArrayDynamicIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderSampledImageArrayDynamicIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayDynamicIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSampledImageArrayDynamicIndexing = shaderSampledImageArrayDynamicIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderStorageBufferArrayDynamicIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayDynamicIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageBufferArrayDynamicIndexing = shaderStorageBufferArrayDynamicIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderStorageImageArrayDynamicIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayDynamicIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageImageArrayDynamicIndexing = shaderStorageImageArrayDynamicIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderClipDistance( VULKAN_HPP_NAMESPACE::Bool32 shaderClipDistance_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderClipDistance = shaderClipDistance_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderCullDistance( VULKAN_HPP_NAMESPACE::Bool32 shaderCullDistance_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderCullDistance = shaderCullDistance_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderFloat64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderFloat64 = shaderFloat64_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderInt64( VULKAN_HPP_NAMESPACE::Bool32 shaderInt64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderInt64 = shaderInt64_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderInt16( VULKAN_HPP_NAMESPACE::Bool32 shaderInt16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderInt16 = shaderInt16_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderResourceResidency( VULKAN_HPP_NAMESPACE::Bool32 shaderResourceResidency_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderResourceResidency = shaderResourceResidency_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setShaderResourceMinLod( VULKAN_HPP_NAMESPACE::Bool32 shaderResourceMinLod_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderResourceMinLod = shaderResourceMinLod_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSparseBinding( VULKAN_HPP_NAMESPACE::Bool32 sparseBinding_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sparseBinding = sparseBinding_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSparseResidencyBuffer( VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyBuffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sparseResidencyBuffer = sparseResidencyBuffer_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSparseResidencyImage2D( VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyImage2D_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sparseResidencyImage2D = sparseResidencyImage2D_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSparseResidencyImage3D( VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyImage3D_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sparseResidencyImage3D = sparseResidencyImage3D_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSparseResidency2Samples( VULKAN_HPP_NAMESPACE::Bool32 sparseResidency2Samples_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sparseResidency2Samples = sparseResidency2Samples_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSparseResidency4Samples( VULKAN_HPP_NAMESPACE::Bool32 sparseResidency4Samples_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sparseResidency4Samples = sparseResidency4Samples_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSparseResidency8Samples( VULKAN_HPP_NAMESPACE::Bool32 sparseResidency8Samples_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sparseResidency8Samples = sparseResidency8Samples_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSparseResidency16Samples( VULKAN_HPP_NAMESPACE::Bool32 sparseResidency16Samples_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sparseResidency16Samples = sparseResidency16Samples_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setSparseResidencyAliased( VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyAliased_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sparseResidencyAliased = sparseResidencyAliased_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setVariableMultisampleRate( VULKAN_HPP_NAMESPACE::Bool32 variableMultisampleRate_ ) VULKAN_HPP_NOEXCEPT
+ {
+ variableMultisampleRate = variableMultisampleRate_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures & setInheritedQueries( VULKAN_HPP_NAMESPACE::Bool32 inheritedQueries_ ) VULKAN_HPP_NOEXCEPT
+ {
+ inheritedQueries = inheritedQueries_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( robustBufferAccess == rhs.robustBufferAccess )
+ && ( fullDrawIndexUint32 == rhs.fullDrawIndexUint32 )
+ && ( imageCubeArray == rhs.imageCubeArray )
+ && ( independentBlend == rhs.independentBlend )
+ && ( geometryShader == rhs.geometryShader )
+ && ( tessellationShader == rhs.tessellationShader )
+ && ( sampleRateShading == rhs.sampleRateShading )
+ && ( dualSrcBlend == rhs.dualSrcBlend )
+ && ( logicOp == rhs.logicOp )
+ && ( multiDrawIndirect == rhs.multiDrawIndirect )
+ && ( drawIndirectFirstInstance == rhs.drawIndirectFirstInstance )
+ && ( depthClamp == rhs.depthClamp )
+ && ( depthBiasClamp == rhs.depthBiasClamp )
+ && ( fillModeNonSolid == rhs.fillModeNonSolid )
+ && ( depthBounds == rhs.depthBounds )
+ && ( wideLines == rhs.wideLines )
+ && ( largePoints == rhs.largePoints )
+ && ( alphaToOne == rhs.alphaToOne )
+ && ( multiViewport == rhs.multiViewport )
+ && ( samplerAnisotropy == rhs.samplerAnisotropy )
+ && ( textureCompressionETC2 == rhs.textureCompressionETC2 )
+ && ( textureCompressionASTC_LDR == rhs.textureCompressionASTC_LDR )
+ && ( textureCompressionBC == rhs.textureCompressionBC )
+ && ( occlusionQueryPrecise == rhs.occlusionQueryPrecise )
+ && ( pipelineStatisticsQuery == rhs.pipelineStatisticsQuery )
+ && ( vertexPipelineStoresAndAtomics == rhs.vertexPipelineStoresAndAtomics )
+ && ( fragmentStoresAndAtomics == rhs.fragmentStoresAndAtomics )
+ && ( shaderTessellationAndGeometryPointSize == rhs.shaderTessellationAndGeometryPointSize )
+ && ( shaderImageGatherExtended == rhs.shaderImageGatherExtended )
+ && ( shaderStorageImageExtendedFormats == rhs.shaderStorageImageExtendedFormats )
+ && ( shaderStorageImageMultisample == rhs.shaderStorageImageMultisample )
+ && ( shaderStorageImageReadWithoutFormat == rhs.shaderStorageImageReadWithoutFormat )
+ && ( shaderStorageImageWriteWithoutFormat == rhs.shaderStorageImageWriteWithoutFormat )
+ && ( shaderUniformBufferArrayDynamicIndexing == rhs.shaderUniformBufferArrayDynamicIndexing )
+ && ( shaderSampledImageArrayDynamicIndexing == rhs.shaderSampledImageArrayDynamicIndexing )
+ && ( shaderStorageBufferArrayDynamicIndexing == rhs.shaderStorageBufferArrayDynamicIndexing )
+ && ( shaderStorageImageArrayDynamicIndexing == rhs.shaderStorageImageArrayDynamicIndexing )
+ && ( shaderClipDistance == rhs.shaderClipDistance )
+ && ( shaderCullDistance == rhs.shaderCullDistance )
+ && ( shaderFloat64 == rhs.shaderFloat64 )
+ && ( shaderInt64 == rhs.shaderInt64 )
+ && ( shaderInt16 == rhs.shaderInt16 )
+ && ( shaderResourceResidency == rhs.shaderResourceResidency )
+ && ( shaderResourceMinLod == rhs.shaderResourceMinLod )
+ && ( sparseBinding == rhs.sparseBinding )
+ && ( sparseResidencyBuffer == rhs.sparseResidencyBuffer )
+ && ( sparseResidencyImage2D == rhs.sparseResidencyImage2D )
+ && ( sparseResidencyImage3D == rhs.sparseResidencyImage3D )
+ && ( sparseResidency2Samples == rhs.sparseResidency2Samples )
+ && ( sparseResidency4Samples == rhs.sparseResidency4Samples )
+ && ( sparseResidency8Samples == rhs.sparseResidency8Samples )
+ && ( sparseResidency16Samples == rhs.sparseResidency16Samples )
+ && ( sparseResidencyAliased == rhs.sparseResidencyAliased )
+ && ( variableMultisampleRate == rhs.variableMultisampleRate )
+ && ( inheritedQueries == rhs.inheritedQueries );
+ }
+
+ bool operator!=( PhysicalDeviceFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Bool32 robustBufferAccess = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fullDrawIndexUint32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 imageCubeArray = {};
+ VULKAN_HPP_NAMESPACE::Bool32 independentBlend = {};
+ VULKAN_HPP_NAMESPACE::Bool32 geometryShader = {};
+ VULKAN_HPP_NAMESPACE::Bool32 tessellationShader = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sampleRateShading = {};
+ VULKAN_HPP_NAMESPACE::Bool32 dualSrcBlend = {};
+ VULKAN_HPP_NAMESPACE::Bool32 logicOp = {};
+ VULKAN_HPP_NAMESPACE::Bool32 multiDrawIndirect = {};
+ VULKAN_HPP_NAMESPACE::Bool32 drawIndirectFirstInstance = {};
+ VULKAN_HPP_NAMESPACE::Bool32 depthClamp = {};
+ VULKAN_HPP_NAMESPACE::Bool32 depthBiasClamp = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fillModeNonSolid = {};
+ VULKAN_HPP_NAMESPACE::Bool32 depthBounds = {};
+ VULKAN_HPP_NAMESPACE::Bool32 wideLines = {};
+ VULKAN_HPP_NAMESPACE::Bool32 largePoints = {};
+ VULKAN_HPP_NAMESPACE::Bool32 alphaToOne = {};
+ VULKAN_HPP_NAMESPACE::Bool32 multiViewport = {};
+ VULKAN_HPP_NAMESPACE::Bool32 samplerAnisotropy = {};
+ VULKAN_HPP_NAMESPACE::Bool32 textureCompressionETC2 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 textureCompressionASTC_LDR = {};
+ VULKAN_HPP_NAMESPACE::Bool32 textureCompressionBC = {};
+ VULKAN_HPP_NAMESPACE::Bool32 occlusionQueryPrecise = {};
+ VULKAN_HPP_NAMESPACE::Bool32 pipelineStatisticsQuery = {};
+ VULKAN_HPP_NAMESPACE::Bool32 vertexPipelineStoresAndAtomics = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentStoresAndAtomics = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderTessellationAndGeometryPointSize = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderImageGatherExtended = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageExtendedFormats = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageMultisample = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageReadWithoutFormat = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageWriteWithoutFormat = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayDynamicIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayDynamicIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayDynamicIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayDynamicIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderClipDistance = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderCullDistance = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderFloat64 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInt64 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInt16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderResourceResidency = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderResourceMinLod = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sparseBinding = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyBuffer = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyImage2D = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyImage3D = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidency2Samples = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidency4Samples = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidency8Samples = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidency16Samples = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sparseResidencyAliased = {};
+ VULKAN_HPP_NAMESPACE::Bool32 variableMultisampleRate = {};
+ VULKAN_HPP_NAMESPACE::Bool32 inheritedQueries = {};
+ };
+ static_assert( sizeof( PhysicalDeviceFeatures ) == sizeof( VkPhysicalDeviceFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR DeviceCreateInfo( VULKAN_HPP_NAMESPACE::DeviceCreateFlags flags_ = {},
+ uint32_t queueCreateInfoCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DeviceQueueCreateInfo* pQueueCreateInfos_ = {},
+ uint32_t enabledLayerCount_ = {},
+ const char* const* ppEnabledLayerNames_ = {},
+ uint32_t enabledExtensionCount_ = {},
+ const char* const* ppEnabledExtensionNames_ = {},
+ const VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures* pEnabledFeatures_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , queueCreateInfoCount( queueCreateInfoCount_ )
+ , pQueueCreateInfos( pQueueCreateInfos_ )
+ , enabledLayerCount( enabledLayerCount_ )
+ , ppEnabledLayerNames( ppEnabledLayerNames_ )
+ , enabledExtensionCount( enabledExtensionCount_ )
+ , ppEnabledExtensionNames( ppEnabledExtensionNames_ )
+ , pEnabledFeatures( pEnabledFeatures_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceCreateInfo & operator=( VULKAN_HPP_NAMESPACE::DeviceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceCreateInfo ) - offsetof( DeviceCreateInfo, pNext ) );
+ return *this;
+ }
+
+ DeviceCreateInfo( VkDeviceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceCreateInfo& operator=( VkDeviceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ DeviceCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::DeviceCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DeviceCreateInfo & setQueueCreateInfoCount( uint32_t queueCreateInfoCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueCreateInfoCount = queueCreateInfoCount_;
+ return *this;
+ }
+
+ DeviceCreateInfo & setPQueueCreateInfos( const VULKAN_HPP_NAMESPACE::DeviceQueueCreateInfo* pQueueCreateInfos_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pQueueCreateInfos = pQueueCreateInfos_;
+ return *this;
+ }
+
+ DeviceCreateInfo & setEnabledLayerCount( uint32_t enabledLayerCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ enabledLayerCount = enabledLayerCount_;
+ return *this;
+ }
+
+ DeviceCreateInfo & setPpEnabledLayerNames( const char* const* ppEnabledLayerNames_ ) VULKAN_HPP_NOEXCEPT
+ {
+ ppEnabledLayerNames = ppEnabledLayerNames_;
+ return *this;
+ }
+
+ DeviceCreateInfo & setEnabledExtensionCount( uint32_t enabledExtensionCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ enabledExtensionCount = enabledExtensionCount_;
+ return *this;
+ }
+
+ DeviceCreateInfo & setPpEnabledExtensionNames( const char* const* ppEnabledExtensionNames_ ) VULKAN_HPP_NOEXCEPT
+ {
+ ppEnabledExtensionNames = ppEnabledExtensionNames_;
+ return *this;
+ }
+
+ DeviceCreateInfo & setPEnabledFeatures( const VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures* pEnabledFeatures_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pEnabledFeatures = pEnabledFeatures_;
+ return *this;
+ }
+
+ operator VkDeviceCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceCreateInfo*>( this );
+ }
+
+ operator VkDeviceCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceCreateInfo*>( this );
+ }
+
+ bool operator==( DeviceCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( queueCreateInfoCount == rhs.queueCreateInfoCount )
+ && ( pQueueCreateInfos == rhs.pQueueCreateInfos )
+ && ( enabledLayerCount == rhs.enabledLayerCount )
+ && ( ppEnabledLayerNames == rhs.ppEnabledLayerNames )
+ && ( enabledExtensionCount == rhs.enabledExtensionCount )
+ && ( ppEnabledExtensionNames == rhs.ppEnabledExtensionNames )
+ && ( pEnabledFeatures == rhs.pEnabledFeatures );
+ }
+
+ bool operator!=( DeviceCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceCreateFlags flags = {};
+ uint32_t queueCreateInfoCount = {};
+ const VULKAN_HPP_NAMESPACE::DeviceQueueCreateInfo* pQueueCreateInfos = {};
+ uint32_t enabledLayerCount = {};
+ const char* const* ppEnabledLayerNames = {};
+ uint32_t enabledExtensionCount = {};
+ const char* const* ppEnabledExtensionNames = {};
+ const VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures* pEnabledFeatures = {};
+ };
+ static_assert( sizeof( DeviceCreateInfo ) == sizeof( VkDeviceCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceEventInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DeviceEventInfoEXT( VULKAN_HPP_NAMESPACE::DeviceEventTypeEXT deviceEvent_ = VULKAN_HPP_NAMESPACE::DeviceEventTypeEXT::eDisplayHotplug ) VULKAN_HPP_NOEXCEPT
+ : deviceEvent( deviceEvent_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceEventInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DeviceEventInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceEventInfoEXT ) - offsetof( DeviceEventInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DeviceEventInfoEXT( VkDeviceEventInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceEventInfoEXT& operator=( VkDeviceEventInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceEventInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DeviceEventInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceEventInfoEXT & setDeviceEvent( VULKAN_HPP_NAMESPACE::DeviceEventTypeEXT deviceEvent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceEvent = deviceEvent_;
+ return *this;
+ }
+
+ operator VkDeviceEventInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceEventInfoEXT*>( this );
+ }
+
+ operator VkDeviceEventInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceEventInfoEXT*>( this );
+ }
+
+ bool operator==( DeviceEventInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( deviceEvent == rhs.deviceEvent );
+ }
+
+ bool operator!=( DeviceEventInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceEventInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceEventTypeEXT deviceEvent = VULKAN_HPP_NAMESPACE::DeviceEventTypeEXT::eDisplayHotplug;
+ };
+ static_assert( sizeof( DeviceEventInfoEXT ) == sizeof( VkDeviceEventInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceEventInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceGeneratedCommandsFeaturesNVX
+ {
+ VULKAN_HPP_CONSTEXPR DeviceGeneratedCommandsFeaturesNVX( VULKAN_HPP_NAMESPACE::Bool32 computeBindingPointSupport_ = {} ) VULKAN_HPP_NOEXCEPT
+ : computeBindingPointSupport( computeBindingPointSupport_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsFeaturesNVX & operator=( VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsFeaturesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsFeaturesNVX ) - offsetof( DeviceGeneratedCommandsFeaturesNVX, pNext ) );
+ return *this;
+ }
+
+ DeviceGeneratedCommandsFeaturesNVX( VkDeviceGeneratedCommandsFeaturesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceGeneratedCommandsFeaturesNVX& operator=( VkDeviceGeneratedCommandsFeaturesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsFeaturesNVX const *>(&rhs);
+ return *this;
+ }
+
+ DeviceGeneratedCommandsFeaturesNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceGeneratedCommandsFeaturesNVX & setComputeBindingPointSupport( VULKAN_HPP_NAMESPACE::Bool32 computeBindingPointSupport_ ) VULKAN_HPP_NOEXCEPT
+ {
+ computeBindingPointSupport = computeBindingPointSupport_;
+ return *this;
+ }
+
+ operator VkDeviceGeneratedCommandsFeaturesNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceGeneratedCommandsFeaturesNVX*>( this );
+ }
+
+ operator VkDeviceGeneratedCommandsFeaturesNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceGeneratedCommandsFeaturesNVX*>( this );
+ }
+
+ bool operator==( DeviceGeneratedCommandsFeaturesNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( computeBindingPointSupport == rhs.computeBindingPointSupport );
+ }
+
+ bool operator!=( DeviceGeneratedCommandsFeaturesNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGeneratedCommandsFeaturesNVX;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 computeBindingPointSupport = {};
+ };
+ static_assert( sizeof( DeviceGeneratedCommandsFeaturesNVX ) == sizeof( VkDeviceGeneratedCommandsFeaturesNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceGeneratedCommandsFeaturesNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceGeneratedCommandsLimitsNVX
+ {
+ VULKAN_HPP_CONSTEXPR DeviceGeneratedCommandsLimitsNVX( uint32_t maxIndirectCommandsLayoutTokenCount_ = {},
+ uint32_t maxObjectEntryCounts_ = {},
+ uint32_t minSequenceCountBufferOffsetAlignment_ = {},
+ uint32_t minSequenceIndexBufferOffsetAlignment_ = {},
+ uint32_t minCommandsTokenBufferOffsetAlignment_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxIndirectCommandsLayoutTokenCount( maxIndirectCommandsLayoutTokenCount_ )
+ , maxObjectEntryCounts( maxObjectEntryCounts_ )
+ , minSequenceCountBufferOffsetAlignment( minSequenceCountBufferOffsetAlignment_ )
+ , minSequenceIndexBufferOffsetAlignment( minSequenceIndexBufferOffsetAlignment_ )
+ , minCommandsTokenBufferOffsetAlignment( minCommandsTokenBufferOffsetAlignment_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX & operator=( VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX ) - offsetof( DeviceGeneratedCommandsLimitsNVX, pNext ) );
+ return *this;
+ }
+
+ DeviceGeneratedCommandsLimitsNVX( VkDeviceGeneratedCommandsLimitsNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceGeneratedCommandsLimitsNVX& operator=( VkDeviceGeneratedCommandsLimitsNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX const *>(&rhs);
+ return *this;
+ }
+
+ DeviceGeneratedCommandsLimitsNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceGeneratedCommandsLimitsNVX & setMaxIndirectCommandsLayoutTokenCount( uint32_t maxIndirectCommandsLayoutTokenCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxIndirectCommandsLayoutTokenCount = maxIndirectCommandsLayoutTokenCount_;
+ return *this;
+ }
+
+ DeviceGeneratedCommandsLimitsNVX & setMaxObjectEntryCounts( uint32_t maxObjectEntryCounts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxObjectEntryCounts = maxObjectEntryCounts_;
+ return *this;
+ }
+
+ DeviceGeneratedCommandsLimitsNVX & setMinSequenceCountBufferOffsetAlignment( uint32_t minSequenceCountBufferOffsetAlignment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minSequenceCountBufferOffsetAlignment = minSequenceCountBufferOffsetAlignment_;
+ return *this;
+ }
+
+ DeviceGeneratedCommandsLimitsNVX & setMinSequenceIndexBufferOffsetAlignment( uint32_t minSequenceIndexBufferOffsetAlignment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minSequenceIndexBufferOffsetAlignment = minSequenceIndexBufferOffsetAlignment_;
+ return *this;
+ }
+
+ DeviceGeneratedCommandsLimitsNVX & setMinCommandsTokenBufferOffsetAlignment( uint32_t minCommandsTokenBufferOffsetAlignment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minCommandsTokenBufferOffsetAlignment = minCommandsTokenBufferOffsetAlignment_;
+ return *this;
+ }
+
+ operator VkDeviceGeneratedCommandsLimitsNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceGeneratedCommandsLimitsNVX*>( this );
+ }
+
+ operator VkDeviceGeneratedCommandsLimitsNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceGeneratedCommandsLimitsNVX*>( this );
+ }
+
+ bool operator==( DeviceGeneratedCommandsLimitsNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxIndirectCommandsLayoutTokenCount == rhs.maxIndirectCommandsLayoutTokenCount )
+ && ( maxObjectEntryCounts == rhs.maxObjectEntryCounts )
+ && ( minSequenceCountBufferOffsetAlignment == rhs.minSequenceCountBufferOffsetAlignment )
+ && ( minSequenceIndexBufferOffsetAlignment == rhs.minSequenceIndexBufferOffsetAlignment )
+ && ( minCommandsTokenBufferOffsetAlignment == rhs.minCommandsTokenBufferOffsetAlignment );
+ }
+
+ bool operator!=( DeviceGeneratedCommandsLimitsNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGeneratedCommandsLimitsNVX;
+ const void* pNext = {};
+ uint32_t maxIndirectCommandsLayoutTokenCount = {};
+ uint32_t maxObjectEntryCounts = {};
+ uint32_t minSequenceCountBufferOffsetAlignment = {};
+ uint32_t minSequenceIndexBufferOffsetAlignment = {};
+ uint32_t minCommandsTokenBufferOffsetAlignment = {};
+ };
+ static_assert( sizeof( DeviceGeneratedCommandsLimitsNVX ) == sizeof( VkDeviceGeneratedCommandsLimitsNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceGeneratedCommandsLimitsNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceGroupBindSparseInfo
+ {
+ VULKAN_HPP_CONSTEXPR DeviceGroupBindSparseInfo( uint32_t resourceDeviceIndex_ = {},
+ uint32_t memoryDeviceIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : resourceDeviceIndex( resourceDeviceIndex_ )
+ , memoryDeviceIndex( memoryDeviceIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceGroupBindSparseInfo & operator=( VULKAN_HPP_NAMESPACE::DeviceGroupBindSparseInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceGroupBindSparseInfo ) - offsetof( DeviceGroupBindSparseInfo, pNext ) );
+ return *this;
+ }
+
+ DeviceGroupBindSparseInfo( VkDeviceGroupBindSparseInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceGroupBindSparseInfo& operator=( VkDeviceGroupBindSparseInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGroupBindSparseInfo const *>(&rhs);
+ return *this;
+ }
+
+ DeviceGroupBindSparseInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceGroupBindSparseInfo & setResourceDeviceIndex( uint32_t resourceDeviceIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ resourceDeviceIndex = resourceDeviceIndex_;
+ return *this;
+ }
+
+ DeviceGroupBindSparseInfo & setMemoryDeviceIndex( uint32_t memoryDeviceIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memoryDeviceIndex = memoryDeviceIndex_;
+ return *this;
+ }
+
+ operator VkDeviceGroupBindSparseInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceGroupBindSparseInfo*>( this );
+ }
+
+ operator VkDeviceGroupBindSparseInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceGroupBindSparseInfo*>( this );
+ }
+
+ bool operator==( DeviceGroupBindSparseInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( resourceDeviceIndex == rhs.resourceDeviceIndex )
+ && ( memoryDeviceIndex == rhs.memoryDeviceIndex );
+ }
+
+ bool operator!=( DeviceGroupBindSparseInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGroupBindSparseInfo;
+ const void* pNext = {};
+ uint32_t resourceDeviceIndex = {};
+ uint32_t memoryDeviceIndex = {};
+ };
+ static_assert( sizeof( DeviceGroupBindSparseInfo ) == sizeof( VkDeviceGroupBindSparseInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceGroupBindSparseInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceGroupCommandBufferBeginInfo
+ {
+ VULKAN_HPP_CONSTEXPR DeviceGroupCommandBufferBeginInfo( uint32_t deviceMask_ = {} ) VULKAN_HPP_NOEXCEPT
+ : deviceMask( deviceMask_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceGroupCommandBufferBeginInfo & operator=( VULKAN_HPP_NAMESPACE::DeviceGroupCommandBufferBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceGroupCommandBufferBeginInfo ) - offsetof( DeviceGroupCommandBufferBeginInfo, pNext ) );
+ return *this;
+ }
+
+ DeviceGroupCommandBufferBeginInfo( VkDeviceGroupCommandBufferBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceGroupCommandBufferBeginInfo& operator=( VkDeviceGroupCommandBufferBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGroupCommandBufferBeginInfo const *>(&rhs);
+ return *this;
+ }
+
+ DeviceGroupCommandBufferBeginInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceGroupCommandBufferBeginInfo & setDeviceMask( uint32_t deviceMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceMask = deviceMask_;
+ return *this;
+ }
+
+ operator VkDeviceGroupCommandBufferBeginInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceGroupCommandBufferBeginInfo*>( this );
+ }
+
+ operator VkDeviceGroupCommandBufferBeginInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceGroupCommandBufferBeginInfo*>( this );
+ }
+
+ bool operator==( DeviceGroupCommandBufferBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( deviceMask == rhs.deviceMask );
+ }
+
+ bool operator!=( DeviceGroupCommandBufferBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGroupCommandBufferBeginInfo;
+ const void* pNext = {};
+ uint32_t deviceMask = {};
+ };
+ static_assert( sizeof( DeviceGroupCommandBufferBeginInfo ) == sizeof( VkDeviceGroupCommandBufferBeginInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceGroupCommandBufferBeginInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceGroupDeviceCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR DeviceGroupDeviceCreateInfo( uint32_t physicalDeviceCount_ = {},
+ const VULKAN_HPP_NAMESPACE::PhysicalDevice* pPhysicalDevices_ = {} ) VULKAN_HPP_NOEXCEPT
+ : physicalDeviceCount( physicalDeviceCount_ )
+ , pPhysicalDevices( pPhysicalDevices_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceGroupDeviceCreateInfo & operator=( VULKAN_HPP_NAMESPACE::DeviceGroupDeviceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceGroupDeviceCreateInfo ) - offsetof( DeviceGroupDeviceCreateInfo, pNext ) );
+ return *this;
+ }
+
+ DeviceGroupDeviceCreateInfo( VkDeviceGroupDeviceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceGroupDeviceCreateInfo& operator=( VkDeviceGroupDeviceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGroupDeviceCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ DeviceGroupDeviceCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceGroupDeviceCreateInfo & setPhysicalDeviceCount( uint32_t physicalDeviceCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ physicalDeviceCount = physicalDeviceCount_;
+ return *this;
+ }
+
+ DeviceGroupDeviceCreateInfo & setPPhysicalDevices( const VULKAN_HPP_NAMESPACE::PhysicalDevice* pPhysicalDevices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pPhysicalDevices = pPhysicalDevices_;
+ return *this;
+ }
+
+ operator VkDeviceGroupDeviceCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceGroupDeviceCreateInfo*>( this );
+ }
+
+ operator VkDeviceGroupDeviceCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceGroupDeviceCreateInfo*>( this );
+ }
+
+ bool operator==( DeviceGroupDeviceCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( physicalDeviceCount == rhs.physicalDeviceCount )
+ && ( pPhysicalDevices == rhs.pPhysicalDevices );
+ }
+
+ bool operator!=( DeviceGroupDeviceCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGroupDeviceCreateInfo;
+ const void* pNext = {};
+ uint32_t physicalDeviceCount = {};
+ const VULKAN_HPP_NAMESPACE::PhysicalDevice* pPhysicalDevices = {};
+ };
+ static_assert( sizeof( DeviceGroupDeviceCreateInfo ) == sizeof( VkDeviceGroupDeviceCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceGroupDeviceCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceGroupPresentCapabilitiesKHR
+ {
+ DeviceGroupPresentCapabilitiesKHR( std::array<uint32_t,VK_MAX_DEVICE_GROUP_SIZE> const& presentMask_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR modes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : presentMask{}
+ , modes( modes_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,VK_MAX_DEVICE_GROUP_SIZE,VK_MAX_DEVICE_GROUP_SIZE>::copy( presentMask, presentMask_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::DeviceGroupPresentCapabilitiesKHR & operator=( VULKAN_HPP_NAMESPACE::DeviceGroupPresentCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceGroupPresentCapabilitiesKHR ) - offsetof( DeviceGroupPresentCapabilitiesKHR, pNext ) );
+ return *this;
+ }
+
+ DeviceGroupPresentCapabilitiesKHR( VkDeviceGroupPresentCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceGroupPresentCapabilitiesKHR& operator=( VkDeviceGroupPresentCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGroupPresentCapabilitiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDeviceGroupPresentCapabilitiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceGroupPresentCapabilitiesKHR*>( this );
+ }
+
+ operator VkDeviceGroupPresentCapabilitiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceGroupPresentCapabilitiesKHR*>( this );
+ }
+
+ bool operator==( DeviceGroupPresentCapabilitiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memcmp( presentMask, rhs.presentMask, VK_MAX_DEVICE_GROUP_SIZE * sizeof( uint32_t ) ) == 0 )
+ && ( modes == rhs.modes );
+ }
+
+ bool operator!=( DeviceGroupPresentCapabilitiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGroupPresentCapabilitiesKHR;
+ const void* pNext = {};
+ uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE] = {};
+ VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR modes = {};
+ };
+ static_assert( sizeof( DeviceGroupPresentCapabilitiesKHR ) == sizeof( VkDeviceGroupPresentCapabilitiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceGroupPresentCapabilitiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceGroupPresentInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR DeviceGroupPresentInfoKHR( uint32_t swapchainCount_ = {},
+ const uint32_t* pDeviceMasks_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagBitsKHR mode_ = VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagBitsKHR::eLocal ) VULKAN_HPP_NOEXCEPT
+ : swapchainCount( swapchainCount_ )
+ , pDeviceMasks( pDeviceMasks_ )
+ , mode( mode_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceGroupPresentInfoKHR & operator=( VULKAN_HPP_NAMESPACE::DeviceGroupPresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceGroupPresentInfoKHR ) - offsetof( DeviceGroupPresentInfoKHR, pNext ) );
+ return *this;
+ }
+
+ DeviceGroupPresentInfoKHR( VkDeviceGroupPresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceGroupPresentInfoKHR& operator=( VkDeviceGroupPresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGroupPresentInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ DeviceGroupPresentInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceGroupPresentInfoKHR & setSwapchainCount( uint32_t swapchainCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ swapchainCount = swapchainCount_;
+ return *this;
+ }
+
+ DeviceGroupPresentInfoKHR & setPDeviceMasks( const uint32_t* pDeviceMasks_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDeviceMasks = pDeviceMasks_;
+ return *this;
+ }
+
+ DeviceGroupPresentInfoKHR & setMode( VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagBitsKHR mode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ mode = mode_;
+ return *this;
+ }
+
+ operator VkDeviceGroupPresentInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceGroupPresentInfoKHR*>( this );
+ }
+
+ operator VkDeviceGroupPresentInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceGroupPresentInfoKHR*>( this );
+ }
+
+ bool operator==( DeviceGroupPresentInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( swapchainCount == rhs.swapchainCount )
+ && ( pDeviceMasks == rhs.pDeviceMasks )
+ && ( mode == rhs.mode );
+ }
+
+ bool operator!=( DeviceGroupPresentInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGroupPresentInfoKHR;
+ const void* pNext = {};
+ uint32_t swapchainCount = {};
+ const uint32_t* pDeviceMasks = {};
+ VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagBitsKHR mode = VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagBitsKHR::eLocal;
+ };
+ static_assert( sizeof( DeviceGroupPresentInfoKHR ) == sizeof( VkDeviceGroupPresentInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceGroupPresentInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceGroupRenderPassBeginInfo
+ {
+ VULKAN_HPP_CONSTEXPR DeviceGroupRenderPassBeginInfo( uint32_t deviceMask_ = {},
+ uint32_t deviceRenderAreaCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Rect2D* pDeviceRenderAreas_ = {} ) VULKAN_HPP_NOEXCEPT
+ : deviceMask( deviceMask_ )
+ , deviceRenderAreaCount( deviceRenderAreaCount_ )
+ , pDeviceRenderAreas( pDeviceRenderAreas_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceGroupRenderPassBeginInfo & operator=( VULKAN_HPP_NAMESPACE::DeviceGroupRenderPassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceGroupRenderPassBeginInfo ) - offsetof( DeviceGroupRenderPassBeginInfo, pNext ) );
+ return *this;
+ }
+
+ DeviceGroupRenderPassBeginInfo( VkDeviceGroupRenderPassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceGroupRenderPassBeginInfo& operator=( VkDeviceGroupRenderPassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGroupRenderPassBeginInfo const *>(&rhs);
+ return *this;
+ }
+
+ DeviceGroupRenderPassBeginInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceGroupRenderPassBeginInfo & setDeviceMask( uint32_t deviceMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceMask = deviceMask_;
+ return *this;
+ }
+
+ DeviceGroupRenderPassBeginInfo & setDeviceRenderAreaCount( uint32_t deviceRenderAreaCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceRenderAreaCount = deviceRenderAreaCount_;
+ return *this;
+ }
+
+ DeviceGroupRenderPassBeginInfo & setPDeviceRenderAreas( const VULKAN_HPP_NAMESPACE::Rect2D* pDeviceRenderAreas_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDeviceRenderAreas = pDeviceRenderAreas_;
+ return *this;
+ }
+
+ operator VkDeviceGroupRenderPassBeginInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceGroupRenderPassBeginInfo*>( this );
+ }
+
+ operator VkDeviceGroupRenderPassBeginInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceGroupRenderPassBeginInfo*>( this );
+ }
+
+ bool operator==( DeviceGroupRenderPassBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( deviceMask == rhs.deviceMask )
+ && ( deviceRenderAreaCount == rhs.deviceRenderAreaCount )
+ && ( pDeviceRenderAreas == rhs.pDeviceRenderAreas );
+ }
+
+ bool operator!=( DeviceGroupRenderPassBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGroupRenderPassBeginInfo;
+ const void* pNext = {};
+ uint32_t deviceMask = {};
+ uint32_t deviceRenderAreaCount = {};
+ const VULKAN_HPP_NAMESPACE::Rect2D* pDeviceRenderAreas = {};
+ };
+ static_assert( sizeof( DeviceGroupRenderPassBeginInfo ) == sizeof( VkDeviceGroupRenderPassBeginInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceGroupRenderPassBeginInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceGroupSubmitInfo
+ {
+ VULKAN_HPP_CONSTEXPR DeviceGroupSubmitInfo( uint32_t waitSemaphoreCount_ = {},
+ const uint32_t* pWaitSemaphoreDeviceIndices_ = {},
+ uint32_t commandBufferCount_ = {},
+ const uint32_t* pCommandBufferDeviceMasks_ = {},
+ uint32_t signalSemaphoreCount_ = {},
+ const uint32_t* pSignalSemaphoreDeviceIndices_ = {} ) VULKAN_HPP_NOEXCEPT
+ : waitSemaphoreCount( waitSemaphoreCount_ )
+ , pWaitSemaphoreDeviceIndices( pWaitSemaphoreDeviceIndices_ )
+ , commandBufferCount( commandBufferCount_ )
+ , pCommandBufferDeviceMasks( pCommandBufferDeviceMasks_ )
+ , signalSemaphoreCount( signalSemaphoreCount_ )
+ , pSignalSemaphoreDeviceIndices( pSignalSemaphoreDeviceIndices_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceGroupSubmitInfo & operator=( VULKAN_HPP_NAMESPACE::DeviceGroupSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceGroupSubmitInfo ) - offsetof( DeviceGroupSubmitInfo, pNext ) );
+ return *this;
+ }
+
+ DeviceGroupSubmitInfo( VkDeviceGroupSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceGroupSubmitInfo& operator=( VkDeviceGroupSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGroupSubmitInfo const *>(&rhs);
+ return *this;
+ }
+
+ DeviceGroupSubmitInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceGroupSubmitInfo & setWaitSemaphoreCount( uint32_t waitSemaphoreCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ waitSemaphoreCount = waitSemaphoreCount_;
+ return *this;
+ }
+
+ DeviceGroupSubmitInfo & setPWaitSemaphoreDeviceIndices( const uint32_t* pWaitSemaphoreDeviceIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pWaitSemaphoreDeviceIndices = pWaitSemaphoreDeviceIndices_;
+ return *this;
+ }
+
+ DeviceGroupSubmitInfo & setCommandBufferCount( uint32_t commandBufferCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ commandBufferCount = commandBufferCount_;
+ return *this;
+ }
+
+ DeviceGroupSubmitInfo & setPCommandBufferDeviceMasks( const uint32_t* pCommandBufferDeviceMasks_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pCommandBufferDeviceMasks = pCommandBufferDeviceMasks_;
+ return *this;
+ }
+
+ DeviceGroupSubmitInfo & setSignalSemaphoreCount( uint32_t signalSemaphoreCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ signalSemaphoreCount = signalSemaphoreCount_;
+ return *this;
+ }
+
+ DeviceGroupSubmitInfo & setPSignalSemaphoreDeviceIndices( const uint32_t* pSignalSemaphoreDeviceIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSignalSemaphoreDeviceIndices = pSignalSemaphoreDeviceIndices_;
+ return *this;
+ }
+
+ operator VkDeviceGroupSubmitInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceGroupSubmitInfo*>( this );
+ }
+
+ operator VkDeviceGroupSubmitInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceGroupSubmitInfo*>( this );
+ }
+
+ bool operator==( DeviceGroupSubmitInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( waitSemaphoreCount == rhs.waitSemaphoreCount )
+ && ( pWaitSemaphoreDeviceIndices == rhs.pWaitSemaphoreDeviceIndices )
+ && ( commandBufferCount == rhs.commandBufferCount )
+ && ( pCommandBufferDeviceMasks == rhs.pCommandBufferDeviceMasks )
+ && ( signalSemaphoreCount == rhs.signalSemaphoreCount )
+ && ( pSignalSemaphoreDeviceIndices == rhs.pSignalSemaphoreDeviceIndices );
+ }
+
+ bool operator!=( DeviceGroupSubmitInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGroupSubmitInfo;
+ const void* pNext = {};
+ uint32_t waitSemaphoreCount = {};
+ const uint32_t* pWaitSemaphoreDeviceIndices = {};
+ uint32_t commandBufferCount = {};
+ const uint32_t* pCommandBufferDeviceMasks = {};
+ uint32_t signalSemaphoreCount = {};
+ const uint32_t* pSignalSemaphoreDeviceIndices = {};
+ };
+ static_assert( sizeof( DeviceGroupSubmitInfo ) == sizeof( VkDeviceGroupSubmitInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceGroupSubmitInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceGroupSwapchainCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR DeviceGroupSwapchainCreateInfoKHR( VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR modes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : modes( modes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceGroupSwapchainCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::DeviceGroupSwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceGroupSwapchainCreateInfoKHR ) - offsetof( DeviceGroupSwapchainCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ DeviceGroupSwapchainCreateInfoKHR( VkDeviceGroupSwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceGroupSwapchainCreateInfoKHR& operator=( VkDeviceGroupSwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGroupSwapchainCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ DeviceGroupSwapchainCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceGroupSwapchainCreateInfoKHR & setModes( VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR modes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ modes = modes_;
+ return *this;
+ }
+
+ operator VkDeviceGroupSwapchainCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceGroupSwapchainCreateInfoKHR*>( this );
+ }
+
+ operator VkDeviceGroupSwapchainCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceGroupSwapchainCreateInfoKHR*>( this );
+ }
+
+ bool operator==( DeviceGroupSwapchainCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( modes == rhs.modes );
+ }
+
+ bool operator!=( DeviceGroupSwapchainCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGroupSwapchainCreateInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR modes = {};
+ };
+ static_assert( sizeof( DeviceGroupSwapchainCreateInfoKHR ) == sizeof( VkDeviceGroupSwapchainCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceGroupSwapchainCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceMemoryOpaqueCaptureAddressInfo
+ {
+ VULKAN_HPP_CONSTEXPR DeviceMemoryOpaqueCaptureAddressInfo( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memory( memory_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceMemoryOpaqueCaptureAddressInfo & operator=( VULKAN_HPP_NAMESPACE::DeviceMemoryOpaqueCaptureAddressInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceMemoryOpaqueCaptureAddressInfo ) - offsetof( DeviceMemoryOpaqueCaptureAddressInfo, pNext ) );
+ return *this;
+ }
+
+ DeviceMemoryOpaqueCaptureAddressInfo( VkDeviceMemoryOpaqueCaptureAddressInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceMemoryOpaqueCaptureAddressInfo& operator=( VkDeviceMemoryOpaqueCaptureAddressInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceMemoryOpaqueCaptureAddressInfo const *>(&rhs);
+ return *this;
+ }
+
+ DeviceMemoryOpaqueCaptureAddressInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceMemoryOpaqueCaptureAddressInfo & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memory = memory_;
+ return *this;
+ }
+
+ operator VkDeviceMemoryOpaqueCaptureAddressInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceMemoryOpaqueCaptureAddressInfo*>( this );
+ }
+
+ operator VkDeviceMemoryOpaqueCaptureAddressInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceMemoryOpaqueCaptureAddressInfo*>( this );
+ }
+
+ bool operator==( DeviceMemoryOpaqueCaptureAddressInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memory == rhs.memory );
+ }
+
+ bool operator!=( DeviceMemoryOpaqueCaptureAddressInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceMemoryOpaqueCaptureAddressInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
+ };
+ static_assert( sizeof( DeviceMemoryOpaqueCaptureAddressInfo ) == sizeof( VkDeviceMemoryOpaqueCaptureAddressInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceMemoryOpaqueCaptureAddressInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceMemoryOverallocationCreateInfoAMD
+ {
+ VULKAN_HPP_CONSTEXPR DeviceMemoryOverallocationCreateInfoAMD( VULKAN_HPP_NAMESPACE::MemoryOverallocationBehaviorAMD overallocationBehavior_ = VULKAN_HPP_NAMESPACE::MemoryOverallocationBehaviorAMD::eDefault ) VULKAN_HPP_NOEXCEPT
+ : overallocationBehavior( overallocationBehavior_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceMemoryOverallocationCreateInfoAMD & operator=( VULKAN_HPP_NAMESPACE::DeviceMemoryOverallocationCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceMemoryOverallocationCreateInfoAMD ) - offsetof( DeviceMemoryOverallocationCreateInfoAMD, pNext ) );
+ return *this;
+ }
+
+ DeviceMemoryOverallocationCreateInfoAMD( VkDeviceMemoryOverallocationCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceMemoryOverallocationCreateInfoAMD& operator=( VkDeviceMemoryOverallocationCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceMemoryOverallocationCreateInfoAMD const *>(&rhs);
+ return *this;
+ }
+
+ DeviceMemoryOverallocationCreateInfoAMD & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceMemoryOverallocationCreateInfoAMD & setOverallocationBehavior( VULKAN_HPP_NAMESPACE::MemoryOverallocationBehaviorAMD overallocationBehavior_ ) VULKAN_HPP_NOEXCEPT
+ {
+ overallocationBehavior = overallocationBehavior_;
+ return *this;
+ }
+
+ operator VkDeviceMemoryOverallocationCreateInfoAMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceMemoryOverallocationCreateInfoAMD*>( this );
+ }
+
+ operator VkDeviceMemoryOverallocationCreateInfoAMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceMemoryOverallocationCreateInfoAMD*>( this );
+ }
+
+ bool operator==( DeviceMemoryOverallocationCreateInfoAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( overallocationBehavior == rhs.overallocationBehavior );
+ }
+
+ bool operator!=( DeviceMemoryOverallocationCreateInfoAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceMemoryOverallocationCreateInfoAMD;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::MemoryOverallocationBehaviorAMD overallocationBehavior = VULKAN_HPP_NAMESPACE::MemoryOverallocationBehaviorAMD::eDefault;
+ };
+ static_assert( sizeof( DeviceMemoryOverallocationCreateInfoAMD ) == sizeof( VkDeviceMemoryOverallocationCreateInfoAMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceMemoryOverallocationCreateInfoAMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceQueueGlobalPriorityCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DeviceQueueGlobalPriorityCreateInfoEXT( VULKAN_HPP_NAMESPACE::QueueGlobalPriorityEXT globalPriority_ = VULKAN_HPP_NAMESPACE::QueueGlobalPriorityEXT::eLow ) VULKAN_HPP_NOEXCEPT
+ : globalPriority( globalPriority_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceQueueGlobalPriorityCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DeviceQueueGlobalPriorityCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceQueueGlobalPriorityCreateInfoEXT ) - offsetof( DeviceQueueGlobalPriorityCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DeviceQueueGlobalPriorityCreateInfoEXT( VkDeviceQueueGlobalPriorityCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceQueueGlobalPriorityCreateInfoEXT& operator=( VkDeviceQueueGlobalPriorityCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceQueueGlobalPriorityCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DeviceQueueGlobalPriorityCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceQueueGlobalPriorityCreateInfoEXT & setGlobalPriority( VULKAN_HPP_NAMESPACE::QueueGlobalPriorityEXT globalPriority_ ) VULKAN_HPP_NOEXCEPT
+ {
+ globalPriority = globalPriority_;
+ return *this;
+ }
+
+ operator VkDeviceQueueGlobalPriorityCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceQueueGlobalPriorityCreateInfoEXT*>( this );
+ }
+
+ operator VkDeviceQueueGlobalPriorityCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceQueueGlobalPriorityCreateInfoEXT*>( this );
+ }
+
+ bool operator==( DeviceQueueGlobalPriorityCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( globalPriority == rhs.globalPriority );
+ }
+
+ bool operator!=( DeviceQueueGlobalPriorityCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceQueueGlobalPriorityCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::QueueGlobalPriorityEXT globalPriority = VULKAN_HPP_NAMESPACE::QueueGlobalPriorityEXT::eLow;
+ };
+ static_assert( sizeof( DeviceQueueGlobalPriorityCreateInfoEXT ) == sizeof( VkDeviceQueueGlobalPriorityCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceQueueGlobalPriorityCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DeviceQueueInfo2
+ {
+ VULKAN_HPP_CONSTEXPR DeviceQueueInfo2( VULKAN_HPP_NAMESPACE::DeviceQueueCreateFlags flags_ = {},
+ uint32_t queueFamilyIndex_ = {},
+ uint32_t queueIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , queueFamilyIndex( queueFamilyIndex_ )
+ , queueIndex( queueIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DeviceQueueInfo2 & operator=( VULKAN_HPP_NAMESPACE::DeviceQueueInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DeviceQueueInfo2 ) - offsetof( DeviceQueueInfo2, pNext ) );
+ return *this;
+ }
+
+ DeviceQueueInfo2( VkDeviceQueueInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DeviceQueueInfo2& operator=( VkDeviceQueueInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceQueueInfo2 const *>(&rhs);
+ return *this;
+ }
+
+ DeviceQueueInfo2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DeviceQueueInfo2 & setFlags( VULKAN_HPP_NAMESPACE::DeviceQueueCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DeviceQueueInfo2 & setQueueFamilyIndex( uint32_t queueFamilyIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueFamilyIndex = queueFamilyIndex_;
+ return *this;
+ }
+
+ DeviceQueueInfo2 & setQueueIndex( uint32_t queueIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueIndex = queueIndex_;
+ return *this;
+ }
+
+ operator VkDeviceQueueInfo2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDeviceQueueInfo2*>( this );
+ }
+
+ operator VkDeviceQueueInfo2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDeviceQueueInfo2*>( this );
+ }
+
+ bool operator==( DeviceQueueInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( queueFamilyIndex == rhs.queueFamilyIndex )
+ && ( queueIndex == rhs.queueIndex );
+ }
+
+ bool operator!=( DeviceQueueInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceQueueInfo2;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceQueueCreateFlags flags = {};
+ uint32_t queueFamilyIndex = {};
+ uint32_t queueIndex = {};
+ };
+ static_assert( sizeof( DeviceQueueInfo2 ) == sizeof( VkDeviceQueueInfo2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DeviceQueueInfo2>::value, "struct wrapper is not a standard layout!" );
+
+ struct DispatchIndirectCommand
+ {
+ VULKAN_HPP_CONSTEXPR DispatchIndirectCommand( uint32_t x_ = {},
+ uint32_t y_ = {},
+ uint32_t z_ = {} ) VULKAN_HPP_NOEXCEPT
+ : x( x_ )
+ , y( y_ )
+ , z( z_ )
+ {}
+
+ DispatchIndirectCommand( VkDispatchIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DispatchIndirectCommand& operator=( VkDispatchIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DispatchIndirectCommand const *>(&rhs);
+ return *this;
+ }
+
+ DispatchIndirectCommand & setX( uint32_t x_ ) VULKAN_HPP_NOEXCEPT
+ {
+ x = x_;
+ return *this;
+ }
+
+ DispatchIndirectCommand & setY( uint32_t y_ ) VULKAN_HPP_NOEXCEPT
+ {
+ y = y_;
+ return *this;
+ }
+
+ DispatchIndirectCommand & setZ( uint32_t z_ ) VULKAN_HPP_NOEXCEPT
+ {
+ z = z_;
+ return *this;
+ }
+
+ operator VkDispatchIndirectCommand const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDispatchIndirectCommand*>( this );
+ }
+
+ operator VkDispatchIndirectCommand &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDispatchIndirectCommand*>( this );
+ }
+
+ bool operator==( DispatchIndirectCommand const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( x == rhs.x )
+ && ( y == rhs.y )
+ && ( z == rhs.z );
+ }
+
+ bool operator!=( DispatchIndirectCommand const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t x = {};
+ uint32_t y = {};
+ uint32_t z = {};
+ };
+ static_assert( sizeof( DispatchIndirectCommand ) == sizeof( VkDispatchIndirectCommand ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DispatchIndirectCommand>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayEventInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DisplayEventInfoEXT( VULKAN_HPP_NAMESPACE::DisplayEventTypeEXT displayEvent_ = VULKAN_HPP_NAMESPACE::DisplayEventTypeEXT::eFirstPixelOut ) VULKAN_HPP_NOEXCEPT
+ : displayEvent( displayEvent_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplayEventInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DisplayEventInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplayEventInfoEXT ) - offsetof( DisplayEventInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DisplayEventInfoEXT( VkDisplayEventInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayEventInfoEXT& operator=( VkDisplayEventInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayEventInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DisplayEventInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DisplayEventInfoEXT & setDisplayEvent( VULKAN_HPP_NAMESPACE::DisplayEventTypeEXT displayEvent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ displayEvent = displayEvent_;
+ return *this;
+ }
+
+ operator VkDisplayEventInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayEventInfoEXT*>( this );
+ }
+
+ operator VkDisplayEventInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayEventInfoEXT*>( this );
+ }
+
+ bool operator==( DisplayEventInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( displayEvent == rhs.displayEvent );
+ }
+
+ bool operator!=( DisplayEventInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplayEventInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DisplayEventTypeEXT displayEvent = VULKAN_HPP_NAMESPACE::DisplayEventTypeEXT::eFirstPixelOut;
+ };
+ static_assert( sizeof( DisplayEventInfoEXT ) == sizeof( VkDisplayEventInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayEventInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayModeParametersKHR
+ {
+ VULKAN_HPP_CONSTEXPR DisplayModeParametersKHR( VULKAN_HPP_NAMESPACE::Extent2D visibleRegion_ = {},
+ uint32_t refreshRate_ = {} ) VULKAN_HPP_NOEXCEPT
+ : visibleRegion( visibleRegion_ )
+ , refreshRate( refreshRate_ )
+ {}
+
+ DisplayModeParametersKHR( VkDisplayModeParametersKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayModeParametersKHR& operator=( VkDisplayModeParametersKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayModeParametersKHR const *>(&rhs);
+ return *this;
+ }
+
+ DisplayModeParametersKHR & setVisibleRegion( VULKAN_HPP_NAMESPACE::Extent2D visibleRegion_ ) VULKAN_HPP_NOEXCEPT
+ {
+ visibleRegion = visibleRegion_;
+ return *this;
+ }
+
+ DisplayModeParametersKHR & setRefreshRate( uint32_t refreshRate_ ) VULKAN_HPP_NOEXCEPT
+ {
+ refreshRate = refreshRate_;
+ return *this;
+ }
+
+ operator VkDisplayModeParametersKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayModeParametersKHR*>( this );
+ }
+
+ operator VkDisplayModeParametersKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayModeParametersKHR*>( this );
+ }
+
+ bool operator==( DisplayModeParametersKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( visibleRegion == rhs.visibleRegion )
+ && ( refreshRate == rhs.refreshRate );
+ }
+
+ bool operator!=( DisplayModeParametersKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Extent2D visibleRegion = {};
+ uint32_t refreshRate = {};
+ };
+ static_assert( sizeof( DisplayModeParametersKHR ) == sizeof( VkDisplayModeParametersKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayModeParametersKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayModeCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR DisplayModeCreateInfoKHR( VULKAN_HPP_NAMESPACE::DisplayModeCreateFlagsKHR flags_ = {},
+ VULKAN_HPP_NAMESPACE::DisplayModeParametersKHR parameters_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , parameters( parameters_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplayModeCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::DisplayModeCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplayModeCreateInfoKHR ) - offsetof( DisplayModeCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ DisplayModeCreateInfoKHR( VkDisplayModeCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayModeCreateInfoKHR& operator=( VkDisplayModeCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayModeCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ DisplayModeCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DisplayModeCreateInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::DisplayModeCreateFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DisplayModeCreateInfoKHR & setParameters( VULKAN_HPP_NAMESPACE::DisplayModeParametersKHR parameters_ ) VULKAN_HPP_NOEXCEPT
+ {
+ parameters = parameters_;
+ return *this;
+ }
+
+ operator VkDisplayModeCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayModeCreateInfoKHR*>( this );
+ }
+
+ operator VkDisplayModeCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayModeCreateInfoKHR*>( this );
+ }
+
+ bool operator==( DisplayModeCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( parameters == rhs.parameters );
+ }
+
+ bool operator!=( DisplayModeCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplayModeCreateInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DisplayModeCreateFlagsKHR flags = {};
+ VULKAN_HPP_NAMESPACE::DisplayModeParametersKHR parameters = {};
+ };
+ static_assert( sizeof( DisplayModeCreateInfoKHR ) == sizeof( VkDisplayModeCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayModeCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayModePropertiesKHR
+ {
+ DisplayModePropertiesKHR( VULKAN_HPP_NAMESPACE::DisplayModeKHR displayMode_ = {},
+ VULKAN_HPP_NAMESPACE::DisplayModeParametersKHR parameters_ = {} ) VULKAN_HPP_NOEXCEPT
+ : displayMode( displayMode_ )
+ , parameters( parameters_ )
+ {}
+
+ DisplayModePropertiesKHR( VkDisplayModePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayModePropertiesKHR& operator=( VkDisplayModePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayModePropertiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDisplayModePropertiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayModePropertiesKHR*>( this );
+ }
+
+ operator VkDisplayModePropertiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayModePropertiesKHR*>( this );
+ }
+
+ bool operator==( DisplayModePropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( displayMode == rhs.displayMode )
+ && ( parameters == rhs.parameters );
+ }
+
+ bool operator!=( DisplayModePropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DisplayModeKHR displayMode = {};
+ VULKAN_HPP_NAMESPACE::DisplayModeParametersKHR parameters = {};
+ };
+ static_assert( sizeof( DisplayModePropertiesKHR ) == sizeof( VkDisplayModePropertiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayModePropertiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayModeProperties2KHR
+ {
+ DisplayModeProperties2KHR( VULKAN_HPP_NAMESPACE::DisplayModePropertiesKHR displayModeProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : displayModeProperties( displayModeProperties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplayModeProperties2KHR & operator=( VULKAN_HPP_NAMESPACE::DisplayModeProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplayModeProperties2KHR ) - offsetof( DisplayModeProperties2KHR, pNext ) );
+ return *this;
+ }
+
+ DisplayModeProperties2KHR( VkDisplayModeProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayModeProperties2KHR& operator=( VkDisplayModeProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayModeProperties2KHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDisplayModeProperties2KHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayModeProperties2KHR*>( this );
+ }
+
+ operator VkDisplayModeProperties2KHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayModeProperties2KHR*>( this );
+ }
+
+ bool operator==( DisplayModeProperties2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( displayModeProperties == rhs.displayModeProperties );
+ }
+
+ bool operator!=( DisplayModeProperties2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplayModeProperties2KHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DisplayModePropertiesKHR displayModeProperties = {};
+ };
+ static_assert( sizeof( DisplayModeProperties2KHR ) == sizeof( VkDisplayModeProperties2KHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayModeProperties2KHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayNativeHdrSurfaceCapabilitiesAMD
+ {
+ DisplayNativeHdrSurfaceCapabilitiesAMD( VULKAN_HPP_NAMESPACE::Bool32 localDimmingSupport_ = {} ) VULKAN_HPP_NOEXCEPT
+ : localDimmingSupport( localDimmingSupport_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplayNativeHdrSurfaceCapabilitiesAMD & operator=( VULKAN_HPP_NAMESPACE::DisplayNativeHdrSurfaceCapabilitiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplayNativeHdrSurfaceCapabilitiesAMD ) - offsetof( DisplayNativeHdrSurfaceCapabilitiesAMD, pNext ) );
+ return *this;
+ }
+
+ DisplayNativeHdrSurfaceCapabilitiesAMD( VkDisplayNativeHdrSurfaceCapabilitiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayNativeHdrSurfaceCapabilitiesAMD& operator=( VkDisplayNativeHdrSurfaceCapabilitiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayNativeHdrSurfaceCapabilitiesAMD const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDisplayNativeHdrSurfaceCapabilitiesAMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayNativeHdrSurfaceCapabilitiesAMD*>( this );
+ }
+
+ operator VkDisplayNativeHdrSurfaceCapabilitiesAMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayNativeHdrSurfaceCapabilitiesAMD*>( this );
+ }
+
+ bool operator==( DisplayNativeHdrSurfaceCapabilitiesAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( localDimmingSupport == rhs.localDimmingSupport );
+ }
+
+ bool operator!=( DisplayNativeHdrSurfaceCapabilitiesAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplayNativeHdrSurfaceCapabilitiesAMD;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 localDimmingSupport = {};
+ };
+ static_assert( sizeof( DisplayNativeHdrSurfaceCapabilitiesAMD ) == sizeof( VkDisplayNativeHdrSurfaceCapabilitiesAMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayNativeHdrSurfaceCapabilitiesAMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayPlaneCapabilitiesKHR
+ {
+ DisplayPlaneCapabilitiesKHR( VULKAN_HPP_NAMESPACE::DisplayPlaneAlphaFlagsKHR supportedAlpha_ = {},
+ VULKAN_HPP_NAMESPACE::Offset2D minSrcPosition_ = {},
+ VULKAN_HPP_NAMESPACE::Offset2D maxSrcPosition_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D minSrcExtent_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D maxSrcExtent_ = {},
+ VULKAN_HPP_NAMESPACE::Offset2D minDstPosition_ = {},
+ VULKAN_HPP_NAMESPACE::Offset2D maxDstPosition_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D minDstExtent_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D maxDstExtent_ = {} ) VULKAN_HPP_NOEXCEPT
+ : supportedAlpha( supportedAlpha_ )
+ , minSrcPosition( minSrcPosition_ )
+ , maxSrcPosition( maxSrcPosition_ )
+ , minSrcExtent( minSrcExtent_ )
+ , maxSrcExtent( maxSrcExtent_ )
+ , minDstPosition( minDstPosition_ )
+ , maxDstPosition( maxDstPosition_ )
+ , minDstExtent( minDstExtent_ )
+ , maxDstExtent( maxDstExtent_ )
+ {}
+
+ DisplayPlaneCapabilitiesKHR( VkDisplayPlaneCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayPlaneCapabilitiesKHR& operator=( VkDisplayPlaneCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilitiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDisplayPlaneCapabilitiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayPlaneCapabilitiesKHR*>( this );
+ }
+
+ operator VkDisplayPlaneCapabilitiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayPlaneCapabilitiesKHR*>( this );
+ }
+
+ bool operator==( DisplayPlaneCapabilitiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( supportedAlpha == rhs.supportedAlpha )
+ && ( minSrcPosition == rhs.minSrcPosition )
+ && ( maxSrcPosition == rhs.maxSrcPosition )
+ && ( minSrcExtent == rhs.minSrcExtent )
+ && ( maxSrcExtent == rhs.maxSrcExtent )
+ && ( minDstPosition == rhs.minDstPosition )
+ && ( maxDstPosition == rhs.maxDstPosition )
+ && ( minDstExtent == rhs.minDstExtent )
+ && ( maxDstExtent == rhs.maxDstExtent );
+ }
+
+ bool operator!=( DisplayPlaneCapabilitiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DisplayPlaneAlphaFlagsKHR supportedAlpha = {};
+ VULKAN_HPP_NAMESPACE::Offset2D minSrcPosition = {};
+ VULKAN_HPP_NAMESPACE::Offset2D maxSrcPosition = {};
+ VULKAN_HPP_NAMESPACE::Extent2D minSrcExtent = {};
+ VULKAN_HPP_NAMESPACE::Extent2D maxSrcExtent = {};
+ VULKAN_HPP_NAMESPACE::Offset2D minDstPosition = {};
+ VULKAN_HPP_NAMESPACE::Offset2D maxDstPosition = {};
+ VULKAN_HPP_NAMESPACE::Extent2D minDstExtent = {};
+ VULKAN_HPP_NAMESPACE::Extent2D maxDstExtent = {};
+ };
+ static_assert( sizeof( DisplayPlaneCapabilitiesKHR ) == sizeof( VkDisplayPlaneCapabilitiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayPlaneCapabilitiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayPlaneCapabilities2KHR
+ {
+ DisplayPlaneCapabilities2KHR( VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilitiesKHR capabilities_ = {} ) VULKAN_HPP_NOEXCEPT
+ : capabilities( capabilities_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilities2KHR & operator=( VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilities2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilities2KHR ) - offsetof( DisplayPlaneCapabilities2KHR, pNext ) );
+ return *this;
+ }
+
+ DisplayPlaneCapabilities2KHR( VkDisplayPlaneCapabilities2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayPlaneCapabilities2KHR& operator=( VkDisplayPlaneCapabilities2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilities2KHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDisplayPlaneCapabilities2KHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayPlaneCapabilities2KHR*>( this );
+ }
+
+ operator VkDisplayPlaneCapabilities2KHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayPlaneCapabilities2KHR*>( this );
+ }
+
+ bool operator==( DisplayPlaneCapabilities2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( capabilities == rhs.capabilities );
+ }
+
+ bool operator!=( DisplayPlaneCapabilities2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplayPlaneCapabilities2KHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilitiesKHR capabilities = {};
+ };
+ static_assert( sizeof( DisplayPlaneCapabilities2KHR ) == sizeof( VkDisplayPlaneCapabilities2KHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayPlaneCapabilities2KHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayPlaneInfo2KHR
+ {
+ VULKAN_HPP_CONSTEXPR DisplayPlaneInfo2KHR( VULKAN_HPP_NAMESPACE::DisplayModeKHR mode_ = {},
+ uint32_t planeIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : mode( mode_ )
+ , planeIndex( planeIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplayPlaneInfo2KHR & operator=( VULKAN_HPP_NAMESPACE::DisplayPlaneInfo2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplayPlaneInfo2KHR ) - offsetof( DisplayPlaneInfo2KHR, pNext ) );
+ return *this;
+ }
+
+ DisplayPlaneInfo2KHR( VkDisplayPlaneInfo2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayPlaneInfo2KHR& operator=( VkDisplayPlaneInfo2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayPlaneInfo2KHR const *>(&rhs);
+ return *this;
+ }
+
+ DisplayPlaneInfo2KHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DisplayPlaneInfo2KHR & setMode( VULKAN_HPP_NAMESPACE::DisplayModeKHR mode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ mode = mode_;
+ return *this;
+ }
+
+ DisplayPlaneInfo2KHR & setPlaneIndex( uint32_t planeIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ planeIndex = planeIndex_;
+ return *this;
+ }
+
+ operator VkDisplayPlaneInfo2KHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayPlaneInfo2KHR*>( this );
+ }
+
+ operator VkDisplayPlaneInfo2KHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayPlaneInfo2KHR*>( this );
+ }
+
+ bool operator==( DisplayPlaneInfo2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( mode == rhs.mode )
+ && ( planeIndex == rhs.planeIndex );
+ }
+
+ bool operator!=( DisplayPlaneInfo2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplayPlaneInfo2KHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DisplayModeKHR mode = {};
+ uint32_t planeIndex = {};
+ };
+ static_assert( sizeof( DisplayPlaneInfo2KHR ) == sizeof( VkDisplayPlaneInfo2KHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayPlaneInfo2KHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayPlanePropertiesKHR
+ {
+ DisplayPlanePropertiesKHR( VULKAN_HPP_NAMESPACE::DisplayKHR currentDisplay_ = {},
+ uint32_t currentStackIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : currentDisplay( currentDisplay_ )
+ , currentStackIndex( currentStackIndex_ )
+ {}
+
+ DisplayPlanePropertiesKHR( VkDisplayPlanePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayPlanePropertiesKHR& operator=( VkDisplayPlanePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayPlanePropertiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDisplayPlanePropertiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayPlanePropertiesKHR*>( this );
+ }
+
+ operator VkDisplayPlanePropertiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayPlanePropertiesKHR*>( this );
+ }
+
+ bool operator==( DisplayPlanePropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( currentDisplay == rhs.currentDisplay )
+ && ( currentStackIndex == rhs.currentStackIndex );
+ }
+
+ bool operator!=( DisplayPlanePropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DisplayKHR currentDisplay = {};
+ uint32_t currentStackIndex = {};
+ };
+ static_assert( sizeof( DisplayPlanePropertiesKHR ) == sizeof( VkDisplayPlanePropertiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayPlanePropertiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayPlaneProperties2KHR
+ {
+ DisplayPlaneProperties2KHR( VULKAN_HPP_NAMESPACE::DisplayPlanePropertiesKHR displayPlaneProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : displayPlaneProperties( displayPlaneProperties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplayPlaneProperties2KHR & operator=( VULKAN_HPP_NAMESPACE::DisplayPlaneProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplayPlaneProperties2KHR ) - offsetof( DisplayPlaneProperties2KHR, pNext ) );
+ return *this;
+ }
+
+ DisplayPlaneProperties2KHR( VkDisplayPlaneProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayPlaneProperties2KHR& operator=( VkDisplayPlaneProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayPlaneProperties2KHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDisplayPlaneProperties2KHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayPlaneProperties2KHR*>( this );
+ }
+
+ operator VkDisplayPlaneProperties2KHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayPlaneProperties2KHR*>( this );
+ }
+
+ bool operator==( DisplayPlaneProperties2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( displayPlaneProperties == rhs.displayPlaneProperties );
+ }
+
+ bool operator!=( DisplayPlaneProperties2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplayPlaneProperties2KHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DisplayPlanePropertiesKHR displayPlaneProperties = {};
+ };
+ static_assert( sizeof( DisplayPlaneProperties2KHR ) == sizeof( VkDisplayPlaneProperties2KHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayPlaneProperties2KHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayPowerInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR DisplayPowerInfoEXT( VULKAN_HPP_NAMESPACE::DisplayPowerStateEXT powerState_ = VULKAN_HPP_NAMESPACE::DisplayPowerStateEXT::eOff ) VULKAN_HPP_NOEXCEPT
+ : powerState( powerState_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplayPowerInfoEXT & operator=( VULKAN_HPP_NAMESPACE::DisplayPowerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplayPowerInfoEXT ) - offsetof( DisplayPowerInfoEXT, pNext ) );
+ return *this;
+ }
+
+ DisplayPowerInfoEXT( VkDisplayPowerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayPowerInfoEXT& operator=( VkDisplayPowerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayPowerInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ DisplayPowerInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DisplayPowerInfoEXT & setPowerState( VULKAN_HPP_NAMESPACE::DisplayPowerStateEXT powerState_ ) VULKAN_HPP_NOEXCEPT
+ {
+ powerState = powerState_;
+ return *this;
+ }
+
+ operator VkDisplayPowerInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayPowerInfoEXT*>( this );
+ }
+
+ operator VkDisplayPowerInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayPowerInfoEXT*>( this );
+ }
+
+ bool operator==( DisplayPowerInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( powerState == rhs.powerState );
+ }
+
+ bool operator!=( DisplayPowerInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplayPowerInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DisplayPowerStateEXT powerState = VULKAN_HPP_NAMESPACE::DisplayPowerStateEXT::eOff;
+ };
+ static_assert( sizeof( DisplayPowerInfoEXT ) == sizeof( VkDisplayPowerInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayPowerInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayPresentInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR DisplayPresentInfoKHR( VULKAN_HPP_NAMESPACE::Rect2D srcRect_ = {},
+ VULKAN_HPP_NAMESPACE::Rect2D dstRect_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 persistent_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcRect( srcRect_ )
+ , dstRect( dstRect_ )
+ , persistent( persistent_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplayPresentInfoKHR & operator=( VULKAN_HPP_NAMESPACE::DisplayPresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplayPresentInfoKHR ) - offsetof( DisplayPresentInfoKHR, pNext ) );
+ return *this;
+ }
+
+ DisplayPresentInfoKHR( VkDisplayPresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayPresentInfoKHR& operator=( VkDisplayPresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayPresentInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ DisplayPresentInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DisplayPresentInfoKHR & setSrcRect( VULKAN_HPP_NAMESPACE::Rect2D srcRect_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcRect = srcRect_;
+ return *this;
+ }
+
+ DisplayPresentInfoKHR & setDstRect( VULKAN_HPP_NAMESPACE::Rect2D dstRect_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstRect = dstRect_;
+ return *this;
+ }
+
+ DisplayPresentInfoKHR & setPersistent( VULKAN_HPP_NAMESPACE::Bool32 persistent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ persistent = persistent_;
+ return *this;
+ }
+
+ operator VkDisplayPresentInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayPresentInfoKHR*>( this );
+ }
+
+ operator VkDisplayPresentInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayPresentInfoKHR*>( this );
+ }
+
+ bool operator==( DisplayPresentInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( srcRect == rhs.srcRect )
+ && ( dstRect == rhs.dstRect )
+ && ( persistent == rhs.persistent );
+ }
+
+ bool operator!=( DisplayPresentInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplayPresentInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Rect2D srcRect = {};
+ VULKAN_HPP_NAMESPACE::Rect2D dstRect = {};
+ VULKAN_HPP_NAMESPACE::Bool32 persistent = {};
+ };
+ static_assert( sizeof( DisplayPresentInfoKHR ) == sizeof( VkDisplayPresentInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayPresentInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayPropertiesKHR
+ {
+ DisplayPropertiesKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display_ = {},
+ const char* displayName_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D physicalDimensions_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D physicalResolution_ = {},
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagsKHR supportedTransforms_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 planeReorderPossible_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 persistentContent_ = {} ) VULKAN_HPP_NOEXCEPT
+ : display( display_ )
+ , displayName( displayName_ )
+ , physicalDimensions( physicalDimensions_ )
+ , physicalResolution( physicalResolution_ )
+ , supportedTransforms( supportedTransforms_ )
+ , planeReorderPossible( planeReorderPossible_ )
+ , persistentContent( persistentContent_ )
+ {}
+
+ DisplayPropertiesKHR( VkDisplayPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayPropertiesKHR& operator=( VkDisplayPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayPropertiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDisplayPropertiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayPropertiesKHR*>( this );
+ }
+
+ operator VkDisplayPropertiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayPropertiesKHR*>( this );
+ }
+
+ bool operator==( DisplayPropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( display == rhs.display )
+ && ( displayName == rhs.displayName )
+ && ( physicalDimensions == rhs.physicalDimensions )
+ && ( physicalResolution == rhs.physicalResolution )
+ && ( supportedTransforms == rhs.supportedTransforms )
+ && ( planeReorderPossible == rhs.planeReorderPossible )
+ && ( persistentContent == rhs.persistentContent );
+ }
+
+ bool operator!=( DisplayPropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DisplayKHR display = {};
+ const char* displayName = {};
+ VULKAN_HPP_NAMESPACE::Extent2D physicalDimensions = {};
+ VULKAN_HPP_NAMESPACE::Extent2D physicalResolution = {};
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagsKHR supportedTransforms = {};
+ VULKAN_HPP_NAMESPACE::Bool32 planeReorderPossible = {};
+ VULKAN_HPP_NAMESPACE::Bool32 persistentContent = {};
+ };
+ static_assert( sizeof( DisplayPropertiesKHR ) == sizeof( VkDisplayPropertiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayPropertiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplayProperties2KHR
+ {
+ DisplayProperties2KHR( VULKAN_HPP_NAMESPACE::DisplayPropertiesKHR displayProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : displayProperties( displayProperties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplayProperties2KHR & operator=( VULKAN_HPP_NAMESPACE::DisplayProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplayProperties2KHR ) - offsetof( DisplayProperties2KHR, pNext ) );
+ return *this;
+ }
+
+ DisplayProperties2KHR( VkDisplayProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplayProperties2KHR& operator=( VkDisplayProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplayProperties2KHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDisplayProperties2KHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplayProperties2KHR*>( this );
+ }
+
+ operator VkDisplayProperties2KHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplayProperties2KHR*>( this );
+ }
+
+ bool operator==( DisplayProperties2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( displayProperties == rhs.displayProperties );
+ }
+
+ bool operator!=( DisplayProperties2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplayProperties2KHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DisplayPropertiesKHR displayProperties = {};
+ };
+ static_assert( sizeof( DisplayProperties2KHR ) == sizeof( VkDisplayProperties2KHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplayProperties2KHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DisplaySurfaceCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR DisplaySurfaceCreateInfoKHR( VULKAN_HPP_NAMESPACE::DisplaySurfaceCreateFlagsKHR flags_ = {},
+ VULKAN_HPP_NAMESPACE::DisplayModeKHR displayMode_ = {},
+ uint32_t planeIndex_ = {},
+ uint32_t planeStackIndex_ = {},
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR transform_ = VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR::eIdentity,
+ float globalAlpha_ = {},
+ VULKAN_HPP_NAMESPACE::DisplayPlaneAlphaFlagBitsKHR alphaMode_ = VULKAN_HPP_NAMESPACE::DisplayPlaneAlphaFlagBitsKHR::eOpaque,
+ VULKAN_HPP_NAMESPACE::Extent2D imageExtent_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , displayMode( displayMode_ )
+ , planeIndex( planeIndex_ )
+ , planeStackIndex( planeStackIndex_ )
+ , transform( transform_ )
+ , globalAlpha( globalAlpha_ )
+ , alphaMode( alphaMode_ )
+ , imageExtent( imageExtent_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DisplaySurfaceCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::DisplaySurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DisplaySurfaceCreateInfoKHR ) - offsetof( DisplaySurfaceCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ DisplaySurfaceCreateInfoKHR( VkDisplaySurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DisplaySurfaceCreateInfoKHR& operator=( VkDisplaySurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DisplaySurfaceCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ DisplaySurfaceCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ DisplaySurfaceCreateInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::DisplaySurfaceCreateFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ DisplaySurfaceCreateInfoKHR & setDisplayMode( VULKAN_HPP_NAMESPACE::DisplayModeKHR displayMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ displayMode = displayMode_;
+ return *this;
+ }
+
+ DisplaySurfaceCreateInfoKHR & setPlaneIndex( uint32_t planeIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ planeIndex = planeIndex_;
+ return *this;
+ }
+
+ DisplaySurfaceCreateInfoKHR & setPlaneStackIndex( uint32_t planeStackIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ planeStackIndex = planeStackIndex_;
+ return *this;
+ }
+
+ DisplaySurfaceCreateInfoKHR & setTransform( VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR transform_ ) VULKAN_HPP_NOEXCEPT
+ {
+ transform = transform_;
+ return *this;
+ }
+
+ DisplaySurfaceCreateInfoKHR & setGlobalAlpha( float globalAlpha_ ) VULKAN_HPP_NOEXCEPT
+ {
+ globalAlpha = globalAlpha_;
+ return *this;
+ }
+
+ DisplaySurfaceCreateInfoKHR & setAlphaMode( VULKAN_HPP_NAMESPACE::DisplayPlaneAlphaFlagBitsKHR alphaMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ alphaMode = alphaMode_;
+ return *this;
+ }
+
+ DisplaySurfaceCreateInfoKHR & setImageExtent( VULKAN_HPP_NAMESPACE::Extent2D imageExtent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageExtent = imageExtent_;
+ return *this;
+ }
+
+ operator VkDisplaySurfaceCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDisplaySurfaceCreateInfoKHR*>( this );
+ }
+
+ operator VkDisplaySurfaceCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDisplaySurfaceCreateInfoKHR*>( this );
+ }
+
+ bool operator==( DisplaySurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( displayMode == rhs.displayMode )
+ && ( planeIndex == rhs.planeIndex )
+ && ( planeStackIndex == rhs.planeStackIndex )
+ && ( transform == rhs.transform )
+ && ( globalAlpha == rhs.globalAlpha )
+ && ( alphaMode == rhs.alphaMode )
+ && ( imageExtent == rhs.imageExtent );
+ }
+
+ bool operator!=( DisplaySurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDisplaySurfaceCreateInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DisplaySurfaceCreateFlagsKHR flags = {};
+ VULKAN_HPP_NAMESPACE::DisplayModeKHR displayMode = {};
+ uint32_t planeIndex = {};
+ uint32_t planeStackIndex = {};
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR transform = VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR::eIdentity;
+ float globalAlpha = {};
+ VULKAN_HPP_NAMESPACE::DisplayPlaneAlphaFlagBitsKHR alphaMode = VULKAN_HPP_NAMESPACE::DisplayPlaneAlphaFlagBitsKHR::eOpaque;
+ VULKAN_HPP_NAMESPACE::Extent2D imageExtent = {};
+ };
+ static_assert( sizeof( DisplaySurfaceCreateInfoKHR ) == sizeof( VkDisplaySurfaceCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DisplaySurfaceCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct DrawIndexedIndirectCommand
+ {
+ VULKAN_HPP_CONSTEXPR DrawIndexedIndirectCommand( uint32_t indexCount_ = {},
+ uint32_t instanceCount_ = {},
+ uint32_t firstIndex_ = {},
+ int32_t vertexOffset_ = {},
+ uint32_t firstInstance_ = {} ) VULKAN_HPP_NOEXCEPT
+ : indexCount( indexCount_ )
+ , instanceCount( instanceCount_ )
+ , firstIndex( firstIndex_ )
+ , vertexOffset( vertexOffset_ )
+ , firstInstance( firstInstance_ )
+ {}
+
+ DrawIndexedIndirectCommand( VkDrawIndexedIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DrawIndexedIndirectCommand& operator=( VkDrawIndexedIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DrawIndexedIndirectCommand const *>(&rhs);
+ return *this;
+ }
+
+ DrawIndexedIndirectCommand & setIndexCount( uint32_t indexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ indexCount = indexCount_;
+ return *this;
+ }
+
+ DrawIndexedIndirectCommand & setInstanceCount( uint32_t instanceCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ instanceCount = instanceCount_;
+ return *this;
+ }
+
+ DrawIndexedIndirectCommand & setFirstIndex( uint32_t firstIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ firstIndex = firstIndex_;
+ return *this;
+ }
+
+ DrawIndexedIndirectCommand & setVertexOffset( int32_t vertexOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexOffset = vertexOffset_;
+ return *this;
+ }
+
+ DrawIndexedIndirectCommand & setFirstInstance( uint32_t firstInstance_ ) VULKAN_HPP_NOEXCEPT
+ {
+ firstInstance = firstInstance_;
+ return *this;
+ }
+
+ operator VkDrawIndexedIndirectCommand const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDrawIndexedIndirectCommand*>( this );
+ }
+
+ operator VkDrawIndexedIndirectCommand &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDrawIndexedIndirectCommand*>( this );
+ }
+
+ bool operator==( DrawIndexedIndirectCommand const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( indexCount == rhs.indexCount )
+ && ( instanceCount == rhs.instanceCount )
+ && ( firstIndex == rhs.firstIndex )
+ && ( vertexOffset == rhs.vertexOffset )
+ && ( firstInstance == rhs.firstInstance );
+ }
+
+ bool operator!=( DrawIndexedIndirectCommand const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t indexCount = {};
+ uint32_t instanceCount = {};
+ uint32_t firstIndex = {};
+ int32_t vertexOffset = {};
+ uint32_t firstInstance = {};
+ };
+ static_assert( sizeof( DrawIndexedIndirectCommand ) == sizeof( VkDrawIndexedIndirectCommand ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DrawIndexedIndirectCommand>::value, "struct wrapper is not a standard layout!" );
+
+ struct DrawIndirectCommand
+ {
+ VULKAN_HPP_CONSTEXPR DrawIndirectCommand( uint32_t vertexCount_ = {},
+ uint32_t instanceCount_ = {},
+ uint32_t firstVertex_ = {},
+ uint32_t firstInstance_ = {} ) VULKAN_HPP_NOEXCEPT
+ : vertexCount( vertexCount_ )
+ , instanceCount( instanceCount_ )
+ , firstVertex( firstVertex_ )
+ , firstInstance( firstInstance_ )
+ {}
+
+ DrawIndirectCommand( VkDrawIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DrawIndirectCommand& operator=( VkDrawIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DrawIndirectCommand const *>(&rhs);
+ return *this;
+ }
+
+ DrawIndirectCommand & setVertexCount( uint32_t vertexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexCount = vertexCount_;
+ return *this;
+ }
+
+ DrawIndirectCommand & setInstanceCount( uint32_t instanceCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ instanceCount = instanceCount_;
+ return *this;
+ }
+
+ DrawIndirectCommand & setFirstVertex( uint32_t firstVertex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ firstVertex = firstVertex_;
+ return *this;
+ }
+
+ DrawIndirectCommand & setFirstInstance( uint32_t firstInstance_ ) VULKAN_HPP_NOEXCEPT
+ {
+ firstInstance = firstInstance_;
+ return *this;
+ }
+
+ operator VkDrawIndirectCommand const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDrawIndirectCommand*>( this );
+ }
+
+ operator VkDrawIndirectCommand &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDrawIndirectCommand*>( this );
+ }
+
+ bool operator==( DrawIndirectCommand const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( vertexCount == rhs.vertexCount )
+ && ( instanceCount == rhs.instanceCount )
+ && ( firstVertex == rhs.firstVertex )
+ && ( firstInstance == rhs.firstInstance );
+ }
+
+ bool operator!=( DrawIndirectCommand const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t vertexCount = {};
+ uint32_t instanceCount = {};
+ uint32_t firstVertex = {};
+ uint32_t firstInstance = {};
+ };
+ static_assert( sizeof( DrawIndirectCommand ) == sizeof( VkDrawIndirectCommand ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DrawIndirectCommand>::value, "struct wrapper is not a standard layout!" );
+
+ struct DrawMeshTasksIndirectCommandNV
+ {
+ VULKAN_HPP_CONSTEXPR DrawMeshTasksIndirectCommandNV( uint32_t taskCount_ = {},
+ uint32_t firstTask_ = {} ) VULKAN_HPP_NOEXCEPT
+ : taskCount( taskCount_ )
+ , firstTask( firstTask_ )
+ {}
+
+ DrawMeshTasksIndirectCommandNV( VkDrawMeshTasksIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DrawMeshTasksIndirectCommandNV& operator=( VkDrawMeshTasksIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DrawMeshTasksIndirectCommandNV const *>(&rhs);
+ return *this;
+ }
+
+ DrawMeshTasksIndirectCommandNV & setTaskCount( uint32_t taskCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ taskCount = taskCount_;
+ return *this;
+ }
+
+ DrawMeshTasksIndirectCommandNV & setFirstTask( uint32_t firstTask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ firstTask = firstTask_;
+ return *this;
+ }
+
+ operator VkDrawMeshTasksIndirectCommandNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDrawMeshTasksIndirectCommandNV*>( this );
+ }
+
+ operator VkDrawMeshTasksIndirectCommandNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDrawMeshTasksIndirectCommandNV*>( this );
+ }
+
+ bool operator==( DrawMeshTasksIndirectCommandNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( taskCount == rhs.taskCount )
+ && ( firstTask == rhs.firstTask );
+ }
+
+ bool operator!=( DrawMeshTasksIndirectCommandNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t taskCount = {};
+ uint32_t firstTask = {};
+ };
+ static_assert( sizeof( DrawMeshTasksIndirectCommandNV ) == sizeof( VkDrawMeshTasksIndirectCommandNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DrawMeshTasksIndirectCommandNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct DrmFormatModifierPropertiesEXT
+ {
+ DrmFormatModifierPropertiesEXT( uint64_t drmFormatModifier_ = {},
+ uint32_t drmFormatModifierPlaneCount_ = {},
+ VULKAN_HPP_NAMESPACE::FormatFeatureFlags drmFormatModifierTilingFeatures_ = {} ) VULKAN_HPP_NOEXCEPT
+ : drmFormatModifier( drmFormatModifier_ )
+ , drmFormatModifierPlaneCount( drmFormatModifierPlaneCount_ )
+ , drmFormatModifierTilingFeatures( drmFormatModifierTilingFeatures_ )
+ {}
+
+ DrmFormatModifierPropertiesEXT( VkDrmFormatModifierPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DrmFormatModifierPropertiesEXT& operator=( VkDrmFormatModifierPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DrmFormatModifierPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDrmFormatModifierPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDrmFormatModifierPropertiesEXT*>( this );
+ }
+
+ operator VkDrmFormatModifierPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDrmFormatModifierPropertiesEXT*>( this );
+ }
+
+ bool operator==( DrmFormatModifierPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( drmFormatModifier == rhs.drmFormatModifier )
+ && ( drmFormatModifierPlaneCount == rhs.drmFormatModifierPlaneCount )
+ && ( drmFormatModifierTilingFeatures == rhs.drmFormatModifierTilingFeatures );
+ }
+
+ bool operator!=( DrmFormatModifierPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint64_t drmFormatModifier = {};
+ uint32_t drmFormatModifierPlaneCount = {};
+ VULKAN_HPP_NAMESPACE::FormatFeatureFlags drmFormatModifierTilingFeatures = {};
+ };
+ static_assert( sizeof( DrmFormatModifierPropertiesEXT ) == sizeof( VkDrmFormatModifierPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DrmFormatModifierPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct DrmFormatModifierPropertiesListEXT
+ {
+ DrmFormatModifierPropertiesListEXT( uint32_t drmFormatModifierCount_ = {},
+ VULKAN_HPP_NAMESPACE::DrmFormatModifierPropertiesEXT* pDrmFormatModifierProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : drmFormatModifierCount( drmFormatModifierCount_ )
+ , pDrmFormatModifierProperties( pDrmFormatModifierProperties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::DrmFormatModifierPropertiesListEXT & operator=( VULKAN_HPP_NAMESPACE::DrmFormatModifierPropertiesListEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::DrmFormatModifierPropertiesListEXT ) - offsetof( DrmFormatModifierPropertiesListEXT, pNext ) );
+ return *this;
+ }
+
+ DrmFormatModifierPropertiesListEXT( VkDrmFormatModifierPropertiesListEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ DrmFormatModifierPropertiesListEXT& operator=( VkDrmFormatModifierPropertiesListEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DrmFormatModifierPropertiesListEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkDrmFormatModifierPropertiesListEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkDrmFormatModifierPropertiesListEXT*>( this );
+ }
+
+ operator VkDrmFormatModifierPropertiesListEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkDrmFormatModifierPropertiesListEXT*>( this );
+ }
+
+ bool operator==( DrmFormatModifierPropertiesListEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( drmFormatModifierCount == rhs.drmFormatModifierCount )
+ && ( pDrmFormatModifierProperties == rhs.pDrmFormatModifierProperties );
+ }
+
+ bool operator!=( DrmFormatModifierPropertiesListEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDrmFormatModifierPropertiesListEXT;
+ void* pNext = {};
+ uint32_t drmFormatModifierCount = {};
+ VULKAN_HPP_NAMESPACE::DrmFormatModifierPropertiesEXT* pDrmFormatModifierProperties = {};
+ };
+ static_assert( sizeof( DrmFormatModifierPropertiesListEXT ) == sizeof( VkDrmFormatModifierPropertiesListEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<DrmFormatModifierPropertiesListEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct EventCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR EventCreateInfo( VULKAN_HPP_NAMESPACE::EventCreateFlags flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::EventCreateInfo & operator=( VULKAN_HPP_NAMESPACE::EventCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::EventCreateInfo ) - offsetof( EventCreateInfo, pNext ) );
+ return *this;
+ }
+
+ EventCreateInfo( VkEventCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ EventCreateInfo& operator=( VkEventCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::EventCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ EventCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ EventCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::EventCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ operator VkEventCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkEventCreateInfo*>( this );
+ }
+
+ operator VkEventCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkEventCreateInfo*>( this );
+ }
+
+ bool operator==( EventCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( EventCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eEventCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::EventCreateFlags flags = {};
+ };
+ static_assert( sizeof( EventCreateInfo ) == sizeof( VkEventCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<EventCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ExportFenceCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ExportFenceCreateInfo( VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlags handleTypes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleTypes( handleTypes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExportFenceCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ExportFenceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExportFenceCreateInfo ) - offsetof( ExportFenceCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ExportFenceCreateInfo( VkExportFenceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExportFenceCreateInfo& operator=( VkExportFenceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExportFenceCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ExportFenceCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExportFenceCreateInfo & setHandleTypes( VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlags handleTypes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleTypes = handleTypes_;
+ return *this;
+ }
+
+ operator VkExportFenceCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExportFenceCreateInfo*>( this );
+ }
+
+ operator VkExportFenceCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExportFenceCreateInfo*>( this );
+ }
+
+ bool operator==( ExportFenceCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleTypes == rhs.handleTypes );
+ }
+
+ bool operator!=( ExportFenceCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExportFenceCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlags handleTypes = {};
+ };
+ static_assert( sizeof( ExportFenceCreateInfo ) == sizeof( VkExportFenceCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExportFenceCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct ExportFenceWin32HandleInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR ExportFenceWin32HandleInfoKHR( const SECURITY_ATTRIBUTES* pAttributes_ = {},
+ DWORD dwAccess_ = {},
+ LPCWSTR name_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pAttributes( pAttributes_ )
+ , dwAccess( dwAccess_ )
+ , name( name_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExportFenceWin32HandleInfoKHR & operator=( VULKAN_HPP_NAMESPACE::ExportFenceWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExportFenceWin32HandleInfoKHR ) - offsetof( ExportFenceWin32HandleInfoKHR, pNext ) );
+ return *this;
+ }
+
+ ExportFenceWin32HandleInfoKHR( VkExportFenceWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExportFenceWin32HandleInfoKHR& operator=( VkExportFenceWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExportFenceWin32HandleInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ ExportFenceWin32HandleInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExportFenceWin32HandleInfoKHR & setPAttributes( const SECURITY_ATTRIBUTES* pAttributes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttributes = pAttributes_;
+ return *this;
+ }
+
+ ExportFenceWin32HandleInfoKHR & setDwAccess( DWORD dwAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dwAccess = dwAccess_;
+ return *this;
+ }
+
+ ExportFenceWin32HandleInfoKHR & setName( LPCWSTR name_ ) VULKAN_HPP_NOEXCEPT
+ {
+ name = name_;
+ return *this;
+ }
+
+ operator VkExportFenceWin32HandleInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExportFenceWin32HandleInfoKHR*>( this );
+ }
+
+ operator VkExportFenceWin32HandleInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExportFenceWin32HandleInfoKHR*>( this );
+ }
+
+ bool operator==( ExportFenceWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pAttributes == rhs.pAttributes )
+ && ( dwAccess == rhs.dwAccess )
+ && ( name == rhs.name );
+ }
+
+ bool operator!=( ExportFenceWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExportFenceWin32HandleInfoKHR;
+ const void* pNext = {};
+ const SECURITY_ATTRIBUTES* pAttributes = {};
+ DWORD dwAccess = {};
+ LPCWSTR name = {};
+ };
+ static_assert( sizeof( ExportFenceWin32HandleInfoKHR ) == sizeof( VkExportFenceWin32HandleInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExportFenceWin32HandleInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct ExportMemoryAllocateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ExportMemoryAllocateInfo( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags handleTypes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleTypes( handleTypes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExportMemoryAllocateInfo & operator=( VULKAN_HPP_NAMESPACE::ExportMemoryAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExportMemoryAllocateInfo ) - offsetof( ExportMemoryAllocateInfo, pNext ) );
+ return *this;
+ }
+
+ ExportMemoryAllocateInfo( VkExportMemoryAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExportMemoryAllocateInfo& operator=( VkExportMemoryAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExportMemoryAllocateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ExportMemoryAllocateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExportMemoryAllocateInfo & setHandleTypes( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags handleTypes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleTypes = handleTypes_;
+ return *this;
+ }
+
+ operator VkExportMemoryAllocateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExportMemoryAllocateInfo*>( this );
+ }
+
+ operator VkExportMemoryAllocateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExportMemoryAllocateInfo*>( this );
+ }
+
+ bool operator==( ExportMemoryAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleTypes == rhs.handleTypes );
+ }
+
+ bool operator!=( ExportMemoryAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExportMemoryAllocateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags handleTypes = {};
+ };
+ static_assert( sizeof( ExportMemoryAllocateInfo ) == sizeof( VkExportMemoryAllocateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExportMemoryAllocateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ExportMemoryAllocateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR ExportMemoryAllocateInfoNV( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleTypes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleTypes( handleTypes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExportMemoryAllocateInfoNV & operator=( VULKAN_HPP_NAMESPACE::ExportMemoryAllocateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExportMemoryAllocateInfoNV ) - offsetof( ExportMemoryAllocateInfoNV, pNext ) );
+ return *this;
+ }
+
+ ExportMemoryAllocateInfoNV( VkExportMemoryAllocateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExportMemoryAllocateInfoNV& operator=( VkExportMemoryAllocateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExportMemoryAllocateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ ExportMemoryAllocateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExportMemoryAllocateInfoNV & setHandleTypes( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleTypes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleTypes = handleTypes_;
+ return *this;
+ }
+
+ operator VkExportMemoryAllocateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExportMemoryAllocateInfoNV*>( this );
+ }
+
+ operator VkExportMemoryAllocateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExportMemoryAllocateInfoNV*>( this );
+ }
+
+ bool operator==( ExportMemoryAllocateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleTypes == rhs.handleTypes );
+ }
+
+ bool operator!=( ExportMemoryAllocateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExportMemoryAllocateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleTypes = {};
+ };
+ static_assert( sizeof( ExportMemoryAllocateInfoNV ) == sizeof( VkExportMemoryAllocateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExportMemoryAllocateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct ExportMemoryWin32HandleInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR ExportMemoryWin32HandleInfoKHR( const SECURITY_ATTRIBUTES* pAttributes_ = {},
+ DWORD dwAccess_ = {},
+ LPCWSTR name_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pAttributes( pAttributes_ )
+ , dwAccess( dwAccess_ )
+ , name( name_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExportMemoryWin32HandleInfoKHR & operator=( VULKAN_HPP_NAMESPACE::ExportMemoryWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExportMemoryWin32HandleInfoKHR ) - offsetof( ExportMemoryWin32HandleInfoKHR, pNext ) );
+ return *this;
+ }
+
+ ExportMemoryWin32HandleInfoKHR( VkExportMemoryWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExportMemoryWin32HandleInfoKHR& operator=( VkExportMemoryWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExportMemoryWin32HandleInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ ExportMemoryWin32HandleInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExportMemoryWin32HandleInfoKHR & setPAttributes( const SECURITY_ATTRIBUTES* pAttributes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttributes = pAttributes_;
+ return *this;
+ }
+
+ ExportMemoryWin32HandleInfoKHR & setDwAccess( DWORD dwAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dwAccess = dwAccess_;
+ return *this;
+ }
+
+ ExportMemoryWin32HandleInfoKHR & setName( LPCWSTR name_ ) VULKAN_HPP_NOEXCEPT
+ {
+ name = name_;
+ return *this;
+ }
+
+ operator VkExportMemoryWin32HandleInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExportMemoryWin32HandleInfoKHR*>( this );
+ }
+
+ operator VkExportMemoryWin32HandleInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExportMemoryWin32HandleInfoKHR*>( this );
+ }
+
+ bool operator==( ExportMemoryWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pAttributes == rhs.pAttributes )
+ && ( dwAccess == rhs.dwAccess )
+ && ( name == rhs.name );
+ }
+
+ bool operator!=( ExportMemoryWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExportMemoryWin32HandleInfoKHR;
+ const void* pNext = {};
+ const SECURITY_ATTRIBUTES* pAttributes = {};
+ DWORD dwAccess = {};
+ LPCWSTR name = {};
+ };
+ static_assert( sizeof( ExportMemoryWin32HandleInfoKHR ) == sizeof( VkExportMemoryWin32HandleInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExportMemoryWin32HandleInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct ExportMemoryWin32HandleInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR ExportMemoryWin32HandleInfoNV( const SECURITY_ATTRIBUTES* pAttributes_ = {},
+ DWORD dwAccess_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pAttributes( pAttributes_ )
+ , dwAccess( dwAccess_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExportMemoryWin32HandleInfoNV & operator=( VULKAN_HPP_NAMESPACE::ExportMemoryWin32HandleInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExportMemoryWin32HandleInfoNV ) - offsetof( ExportMemoryWin32HandleInfoNV, pNext ) );
+ return *this;
+ }
+
+ ExportMemoryWin32HandleInfoNV( VkExportMemoryWin32HandleInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExportMemoryWin32HandleInfoNV& operator=( VkExportMemoryWin32HandleInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExportMemoryWin32HandleInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ ExportMemoryWin32HandleInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExportMemoryWin32HandleInfoNV & setPAttributes( const SECURITY_ATTRIBUTES* pAttributes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttributes = pAttributes_;
+ return *this;
+ }
+
+ ExportMemoryWin32HandleInfoNV & setDwAccess( DWORD dwAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dwAccess = dwAccess_;
+ return *this;
+ }
+
+ operator VkExportMemoryWin32HandleInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExportMemoryWin32HandleInfoNV*>( this );
+ }
+
+ operator VkExportMemoryWin32HandleInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExportMemoryWin32HandleInfoNV*>( this );
+ }
+
+ bool operator==( ExportMemoryWin32HandleInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pAttributes == rhs.pAttributes )
+ && ( dwAccess == rhs.dwAccess );
+ }
+
+ bool operator!=( ExportMemoryWin32HandleInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExportMemoryWin32HandleInfoNV;
+ const void* pNext = {};
+ const SECURITY_ATTRIBUTES* pAttributes = {};
+ DWORD dwAccess = {};
+ };
+ static_assert( sizeof( ExportMemoryWin32HandleInfoNV ) == sizeof( VkExportMemoryWin32HandleInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExportMemoryWin32HandleInfoNV>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct ExportSemaphoreCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ExportSemaphoreCreateInfo( VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlags handleTypes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleTypes( handleTypes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExportSemaphoreCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ExportSemaphoreCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExportSemaphoreCreateInfo ) - offsetof( ExportSemaphoreCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ExportSemaphoreCreateInfo( VkExportSemaphoreCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExportSemaphoreCreateInfo& operator=( VkExportSemaphoreCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExportSemaphoreCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ExportSemaphoreCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExportSemaphoreCreateInfo & setHandleTypes( VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlags handleTypes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleTypes = handleTypes_;
+ return *this;
+ }
+
+ operator VkExportSemaphoreCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExportSemaphoreCreateInfo*>( this );
+ }
+
+ operator VkExportSemaphoreCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExportSemaphoreCreateInfo*>( this );
+ }
+
+ bool operator==( ExportSemaphoreCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleTypes == rhs.handleTypes );
+ }
+
+ bool operator!=( ExportSemaphoreCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExportSemaphoreCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlags handleTypes = {};
+ };
+ static_assert( sizeof( ExportSemaphoreCreateInfo ) == sizeof( VkExportSemaphoreCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExportSemaphoreCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct ExportSemaphoreWin32HandleInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR ExportSemaphoreWin32HandleInfoKHR( const SECURITY_ATTRIBUTES* pAttributes_ = {},
+ DWORD dwAccess_ = {},
+ LPCWSTR name_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pAttributes( pAttributes_ )
+ , dwAccess( dwAccess_ )
+ , name( name_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExportSemaphoreWin32HandleInfoKHR & operator=( VULKAN_HPP_NAMESPACE::ExportSemaphoreWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExportSemaphoreWin32HandleInfoKHR ) - offsetof( ExportSemaphoreWin32HandleInfoKHR, pNext ) );
+ return *this;
+ }
+
+ ExportSemaphoreWin32HandleInfoKHR( VkExportSemaphoreWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExportSemaphoreWin32HandleInfoKHR& operator=( VkExportSemaphoreWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExportSemaphoreWin32HandleInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ ExportSemaphoreWin32HandleInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExportSemaphoreWin32HandleInfoKHR & setPAttributes( const SECURITY_ATTRIBUTES* pAttributes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttributes = pAttributes_;
+ return *this;
+ }
+
+ ExportSemaphoreWin32HandleInfoKHR & setDwAccess( DWORD dwAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dwAccess = dwAccess_;
+ return *this;
+ }
+
+ ExportSemaphoreWin32HandleInfoKHR & setName( LPCWSTR name_ ) VULKAN_HPP_NOEXCEPT
+ {
+ name = name_;
+ return *this;
+ }
+
+ operator VkExportSemaphoreWin32HandleInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExportSemaphoreWin32HandleInfoKHR*>( this );
+ }
+
+ operator VkExportSemaphoreWin32HandleInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExportSemaphoreWin32HandleInfoKHR*>( this );
+ }
+
+ bool operator==( ExportSemaphoreWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pAttributes == rhs.pAttributes )
+ && ( dwAccess == rhs.dwAccess )
+ && ( name == rhs.name );
+ }
+
+ bool operator!=( ExportSemaphoreWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExportSemaphoreWin32HandleInfoKHR;
+ const void* pNext = {};
+ const SECURITY_ATTRIBUTES* pAttributes = {};
+ DWORD dwAccess = {};
+ LPCWSTR name = {};
+ };
+ static_assert( sizeof( ExportSemaphoreWin32HandleInfoKHR ) == sizeof( VkExportSemaphoreWin32HandleInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExportSemaphoreWin32HandleInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct ExtensionProperties
+ {
+ ExtensionProperties( std::array<char,VK_MAX_EXTENSION_NAME_SIZE> const& extensionName_ = {},
+ uint32_t specVersion_ = {} ) VULKAN_HPP_NOEXCEPT
+ : extensionName{}
+ , specVersion( specVersion_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE,VK_MAX_EXTENSION_NAME_SIZE>::copy( extensionName, extensionName_ );
+ }
+
+ ExtensionProperties( VkExtensionProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExtensionProperties& operator=( VkExtensionProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExtensionProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkExtensionProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExtensionProperties*>( this );
+ }
+
+ operator VkExtensionProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExtensionProperties*>( this );
+ }
+
+ bool operator==( ExtensionProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( memcmp( extensionName, rhs.extensionName, VK_MAX_EXTENSION_NAME_SIZE * sizeof( char ) ) == 0 )
+ && ( specVersion == rhs.specVersion );
+ }
+
+ bool operator!=( ExtensionProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ char extensionName[VK_MAX_EXTENSION_NAME_SIZE] = {};
+ uint32_t specVersion = {};
+ };
+ static_assert( sizeof( ExtensionProperties ) == sizeof( VkExtensionProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExtensionProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct ExternalMemoryProperties
+ {
+ ExternalMemoryProperties( VULKAN_HPP_NAMESPACE::ExternalMemoryFeatureFlags externalMemoryFeatures_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags exportFromImportedHandleTypes_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags compatibleHandleTypes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : externalMemoryFeatures( externalMemoryFeatures_ )
+ , exportFromImportedHandleTypes( exportFromImportedHandleTypes_ )
+ , compatibleHandleTypes( compatibleHandleTypes_ )
+ {}
+
+ ExternalMemoryProperties( VkExternalMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExternalMemoryProperties& operator=( VkExternalMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExternalMemoryProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkExternalMemoryProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExternalMemoryProperties*>( this );
+ }
+
+ operator VkExternalMemoryProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExternalMemoryProperties*>( this );
+ }
+
+ bool operator==( ExternalMemoryProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( externalMemoryFeatures == rhs.externalMemoryFeatures )
+ && ( exportFromImportedHandleTypes == rhs.exportFromImportedHandleTypes )
+ && ( compatibleHandleTypes == rhs.compatibleHandleTypes );
+ }
+
+ bool operator!=( ExternalMemoryProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ExternalMemoryFeatureFlags externalMemoryFeatures = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags exportFromImportedHandleTypes = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags compatibleHandleTypes = {};
+ };
+ static_assert( sizeof( ExternalMemoryProperties ) == sizeof( VkExternalMemoryProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExternalMemoryProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct ExternalBufferProperties
+ {
+ ExternalBufferProperties( VULKAN_HPP_NAMESPACE::ExternalMemoryProperties externalMemoryProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : externalMemoryProperties( externalMemoryProperties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExternalBufferProperties & operator=( VULKAN_HPP_NAMESPACE::ExternalBufferProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExternalBufferProperties ) - offsetof( ExternalBufferProperties, pNext ) );
+ return *this;
+ }
+
+ ExternalBufferProperties( VkExternalBufferProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExternalBufferProperties& operator=( VkExternalBufferProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExternalBufferProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkExternalBufferProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExternalBufferProperties*>( this );
+ }
+
+ operator VkExternalBufferProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExternalBufferProperties*>( this );
+ }
+
+ bool operator==( ExternalBufferProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( externalMemoryProperties == rhs.externalMemoryProperties );
+ }
+
+ bool operator!=( ExternalBufferProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExternalBufferProperties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryProperties externalMemoryProperties = {};
+ };
+ static_assert( sizeof( ExternalBufferProperties ) == sizeof( VkExternalBufferProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExternalBufferProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct ExternalFenceProperties
+ {
+ ExternalFenceProperties( VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlags exportFromImportedHandleTypes_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlags compatibleHandleTypes_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalFenceFeatureFlags externalFenceFeatures_ = {} ) VULKAN_HPP_NOEXCEPT
+ : exportFromImportedHandleTypes( exportFromImportedHandleTypes_ )
+ , compatibleHandleTypes( compatibleHandleTypes_ )
+ , externalFenceFeatures( externalFenceFeatures_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExternalFenceProperties & operator=( VULKAN_HPP_NAMESPACE::ExternalFenceProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExternalFenceProperties ) - offsetof( ExternalFenceProperties, pNext ) );
+ return *this;
+ }
+
+ ExternalFenceProperties( VkExternalFenceProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExternalFenceProperties& operator=( VkExternalFenceProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExternalFenceProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkExternalFenceProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExternalFenceProperties*>( this );
+ }
+
+ operator VkExternalFenceProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExternalFenceProperties*>( this );
+ }
+
+ bool operator==( ExternalFenceProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( exportFromImportedHandleTypes == rhs.exportFromImportedHandleTypes )
+ && ( compatibleHandleTypes == rhs.compatibleHandleTypes )
+ && ( externalFenceFeatures == rhs.externalFenceFeatures );
+ }
+
+ bool operator!=( ExternalFenceProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExternalFenceProperties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlags exportFromImportedHandleTypes = {};
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlags compatibleHandleTypes = {};
+ VULKAN_HPP_NAMESPACE::ExternalFenceFeatureFlags externalFenceFeatures = {};
+ };
+ static_assert( sizeof( ExternalFenceProperties ) == sizeof( VkExternalFenceProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExternalFenceProperties>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+
+ struct ExternalFormatANDROID
+ {
+ VULKAN_HPP_CONSTEXPR ExternalFormatANDROID( uint64_t externalFormat_ = {} ) VULKAN_HPP_NOEXCEPT
+ : externalFormat( externalFormat_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExternalFormatANDROID & operator=( VULKAN_HPP_NAMESPACE::ExternalFormatANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExternalFormatANDROID ) - offsetof( ExternalFormatANDROID, pNext ) );
+ return *this;
+ }
+
+ ExternalFormatANDROID( VkExternalFormatANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExternalFormatANDROID& operator=( VkExternalFormatANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExternalFormatANDROID const *>(&rhs);
+ return *this;
+ }
+
+ ExternalFormatANDROID & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExternalFormatANDROID & setExternalFormat( uint64_t externalFormat_ ) VULKAN_HPP_NOEXCEPT
+ {
+ externalFormat = externalFormat_;
+ return *this;
+ }
+
+ operator VkExternalFormatANDROID const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExternalFormatANDROID*>( this );
+ }
+
+ operator VkExternalFormatANDROID &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExternalFormatANDROID*>( this );
+ }
+
+ bool operator==( ExternalFormatANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( externalFormat == rhs.externalFormat );
+ }
+
+ bool operator!=( ExternalFormatANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExternalFormatANDROID;
+ void* pNext = {};
+ uint64_t externalFormat = {};
+ };
+ static_assert( sizeof( ExternalFormatANDROID ) == sizeof( VkExternalFormatANDROID ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExternalFormatANDROID>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ struct ExternalImageFormatProperties
+ {
+ ExternalImageFormatProperties( VULKAN_HPP_NAMESPACE::ExternalMemoryProperties externalMemoryProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : externalMemoryProperties( externalMemoryProperties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExternalImageFormatProperties & operator=( VULKAN_HPP_NAMESPACE::ExternalImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExternalImageFormatProperties ) - offsetof( ExternalImageFormatProperties, pNext ) );
+ return *this;
+ }
+
+ ExternalImageFormatProperties( VkExternalImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExternalImageFormatProperties& operator=( VkExternalImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExternalImageFormatProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkExternalImageFormatProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExternalImageFormatProperties*>( this );
+ }
+
+ operator VkExternalImageFormatProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExternalImageFormatProperties*>( this );
+ }
+
+ bool operator==( ExternalImageFormatProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( externalMemoryProperties == rhs.externalMemoryProperties );
+ }
+
+ bool operator!=( ExternalImageFormatProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExternalImageFormatProperties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryProperties externalMemoryProperties = {};
+ };
+ static_assert( sizeof( ExternalImageFormatProperties ) == sizeof( VkExternalImageFormatProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExternalImageFormatProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageFormatProperties
+ {
+ ImageFormatProperties( VULKAN_HPP_NAMESPACE::Extent3D maxExtent_ = {},
+ uint32_t maxMipLevels_ = {},
+ uint32_t maxArrayLayers_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampleCounts_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize maxResourceSize_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxExtent( maxExtent_ )
+ , maxMipLevels( maxMipLevels_ )
+ , maxArrayLayers( maxArrayLayers_ )
+ , sampleCounts( sampleCounts_ )
+ , maxResourceSize( maxResourceSize_ )
+ {}
+
+ ImageFormatProperties( VkImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageFormatProperties& operator=( VkImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageFormatProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkImageFormatProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageFormatProperties*>( this );
+ }
+
+ operator VkImageFormatProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageFormatProperties*>( this );
+ }
+
+ bool operator==( ImageFormatProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( maxExtent == rhs.maxExtent )
+ && ( maxMipLevels == rhs.maxMipLevels )
+ && ( maxArrayLayers == rhs.maxArrayLayers )
+ && ( sampleCounts == rhs.sampleCounts )
+ && ( maxResourceSize == rhs.maxResourceSize );
+ }
+
+ bool operator!=( ImageFormatProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Extent3D maxExtent = {};
+ uint32_t maxMipLevels = {};
+ uint32_t maxArrayLayers = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampleCounts = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize maxResourceSize = {};
+ };
+ static_assert( sizeof( ImageFormatProperties ) == sizeof( VkImageFormatProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageFormatProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct ExternalImageFormatPropertiesNV
+ {
+ ExternalImageFormatPropertiesNV( VULKAN_HPP_NAMESPACE::ImageFormatProperties imageFormatProperties_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalMemoryFeatureFlagsNV externalMemoryFeatures_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV exportFromImportedHandleTypes_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV compatibleHandleTypes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : imageFormatProperties( imageFormatProperties_ )
+ , externalMemoryFeatures( externalMemoryFeatures_ )
+ , exportFromImportedHandleTypes( exportFromImportedHandleTypes_ )
+ , compatibleHandleTypes( compatibleHandleTypes_ )
+ {}
+
+ ExternalImageFormatPropertiesNV( VkExternalImageFormatPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExternalImageFormatPropertiesNV& operator=( VkExternalImageFormatPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExternalImageFormatPropertiesNV const *>(&rhs);
+ return *this;
+ }
+
+ operator VkExternalImageFormatPropertiesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExternalImageFormatPropertiesNV*>( this );
+ }
+
+ operator VkExternalImageFormatPropertiesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExternalImageFormatPropertiesNV*>( this );
+ }
+
+ bool operator==( ExternalImageFormatPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( imageFormatProperties == rhs.imageFormatProperties )
+ && ( externalMemoryFeatures == rhs.externalMemoryFeatures )
+ && ( exportFromImportedHandleTypes == rhs.exportFromImportedHandleTypes )
+ && ( compatibleHandleTypes == rhs.compatibleHandleTypes );
+ }
+
+ bool operator!=( ExternalImageFormatPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ImageFormatProperties imageFormatProperties = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryFeatureFlagsNV externalMemoryFeatures = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV exportFromImportedHandleTypes = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV compatibleHandleTypes = {};
+ };
+ static_assert( sizeof( ExternalImageFormatPropertiesNV ) == sizeof( VkExternalImageFormatPropertiesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExternalImageFormatPropertiesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct ExternalMemoryBufferCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ExternalMemoryBufferCreateInfo( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags handleTypes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleTypes( handleTypes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExternalMemoryBufferCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ExternalMemoryBufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExternalMemoryBufferCreateInfo ) - offsetof( ExternalMemoryBufferCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ExternalMemoryBufferCreateInfo( VkExternalMemoryBufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExternalMemoryBufferCreateInfo& operator=( VkExternalMemoryBufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExternalMemoryBufferCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ExternalMemoryBufferCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExternalMemoryBufferCreateInfo & setHandleTypes( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags handleTypes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleTypes = handleTypes_;
+ return *this;
+ }
+
+ operator VkExternalMemoryBufferCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExternalMemoryBufferCreateInfo*>( this );
+ }
+
+ operator VkExternalMemoryBufferCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExternalMemoryBufferCreateInfo*>( this );
+ }
+
+ bool operator==( ExternalMemoryBufferCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleTypes == rhs.handleTypes );
+ }
+
+ bool operator!=( ExternalMemoryBufferCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExternalMemoryBufferCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags handleTypes = {};
+ };
+ static_assert( sizeof( ExternalMemoryBufferCreateInfo ) == sizeof( VkExternalMemoryBufferCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExternalMemoryBufferCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ExternalMemoryImageCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ExternalMemoryImageCreateInfo( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags handleTypes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleTypes( handleTypes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExternalMemoryImageCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ExternalMemoryImageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExternalMemoryImageCreateInfo ) - offsetof( ExternalMemoryImageCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ExternalMemoryImageCreateInfo( VkExternalMemoryImageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExternalMemoryImageCreateInfo& operator=( VkExternalMemoryImageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExternalMemoryImageCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ExternalMemoryImageCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExternalMemoryImageCreateInfo & setHandleTypes( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags handleTypes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleTypes = handleTypes_;
+ return *this;
+ }
+
+ operator VkExternalMemoryImageCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExternalMemoryImageCreateInfo*>( this );
+ }
+
+ operator VkExternalMemoryImageCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExternalMemoryImageCreateInfo*>( this );
+ }
+
+ bool operator==( ExternalMemoryImageCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleTypes == rhs.handleTypes );
+ }
+
+ bool operator!=( ExternalMemoryImageCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExternalMemoryImageCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlags handleTypes = {};
+ };
+ static_assert( sizeof( ExternalMemoryImageCreateInfo ) == sizeof( VkExternalMemoryImageCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExternalMemoryImageCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ExternalMemoryImageCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR ExternalMemoryImageCreateInfoNV( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleTypes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleTypes( handleTypes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExternalMemoryImageCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::ExternalMemoryImageCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExternalMemoryImageCreateInfoNV ) - offsetof( ExternalMemoryImageCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ ExternalMemoryImageCreateInfoNV( VkExternalMemoryImageCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExternalMemoryImageCreateInfoNV& operator=( VkExternalMemoryImageCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExternalMemoryImageCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ ExternalMemoryImageCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ExternalMemoryImageCreateInfoNV & setHandleTypes( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleTypes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleTypes = handleTypes_;
+ return *this;
+ }
+
+ operator VkExternalMemoryImageCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExternalMemoryImageCreateInfoNV*>( this );
+ }
+
+ operator VkExternalMemoryImageCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExternalMemoryImageCreateInfoNV*>( this );
+ }
+
+ bool operator==( ExternalMemoryImageCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleTypes == rhs.handleTypes );
+ }
+
+ bool operator!=( ExternalMemoryImageCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExternalMemoryImageCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleTypes = {};
+ };
+ static_assert( sizeof( ExternalMemoryImageCreateInfoNV ) == sizeof( VkExternalMemoryImageCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExternalMemoryImageCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct ExternalSemaphoreProperties
+ {
+ ExternalSemaphoreProperties( VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlags exportFromImportedHandleTypes_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlags compatibleHandleTypes_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreFeatureFlags externalSemaphoreFeatures_ = {} ) VULKAN_HPP_NOEXCEPT
+ : exportFromImportedHandleTypes( exportFromImportedHandleTypes_ )
+ , compatibleHandleTypes( compatibleHandleTypes_ )
+ , externalSemaphoreFeatures( externalSemaphoreFeatures_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties & operator=( VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties ) - offsetof( ExternalSemaphoreProperties, pNext ) );
+ return *this;
+ }
+
+ ExternalSemaphoreProperties( VkExternalSemaphoreProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ExternalSemaphoreProperties& operator=( VkExternalSemaphoreProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkExternalSemaphoreProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkExternalSemaphoreProperties*>( this );
+ }
+
+ operator VkExternalSemaphoreProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkExternalSemaphoreProperties*>( this );
+ }
+
+ bool operator==( ExternalSemaphoreProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( exportFromImportedHandleTypes == rhs.exportFromImportedHandleTypes )
+ && ( compatibleHandleTypes == rhs.compatibleHandleTypes )
+ && ( externalSemaphoreFeatures == rhs.externalSemaphoreFeatures );
+ }
+
+ bool operator!=( ExternalSemaphoreProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eExternalSemaphoreProperties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlags exportFromImportedHandleTypes = {};
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlags compatibleHandleTypes = {};
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreFeatureFlags externalSemaphoreFeatures = {};
+ };
+ static_assert( sizeof( ExternalSemaphoreProperties ) == sizeof( VkExternalSemaphoreProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ExternalSemaphoreProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct FenceCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR FenceCreateInfo( VULKAN_HPP_NAMESPACE::FenceCreateFlags flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::FenceCreateInfo & operator=( VULKAN_HPP_NAMESPACE::FenceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::FenceCreateInfo ) - offsetof( FenceCreateInfo, pNext ) );
+ return *this;
+ }
+
+ FenceCreateInfo( VkFenceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ FenceCreateInfo& operator=( VkFenceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FenceCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ FenceCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ FenceCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::FenceCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ operator VkFenceCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkFenceCreateInfo*>( this );
+ }
+
+ operator VkFenceCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkFenceCreateInfo*>( this );
+ }
+
+ bool operator==( FenceCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( FenceCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eFenceCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::FenceCreateFlags flags = {};
+ };
+ static_assert( sizeof( FenceCreateInfo ) == sizeof( VkFenceCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<FenceCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct FenceGetFdInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR FenceGetFdInfoKHR( VULKAN_HPP_NAMESPACE::Fence fence_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits::eOpaqueFd ) VULKAN_HPP_NOEXCEPT
+ : fence( fence_ )
+ , handleType( handleType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::FenceGetFdInfoKHR & operator=( VULKAN_HPP_NAMESPACE::FenceGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::FenceGetFdInfoKHR ) - offsetof( FenceGetFdInfoKHR, pNext ) );
+ return *this;
+ }
+
+ FenceGetFdInfoKHR( VkFenceGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ FenceGetFdInfoKHR& operator=( VkFenceGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FenceGetFdInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ FenceGetFdInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ FenceGetFdInfoKHR & setFence( VULKAN_HPP_NAMESPACE::Fence fence_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fence = fence_;
+ return *this;
+ }
+
+ FenceGetFdInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ operator VkFenceGetFdInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkFenceGetFdInfoKHR*>( this );
+ }
+
+ operator VkFenceGetFdInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkFenceGetFdInfoKHR*>( this );
+ }
+
+ bool operator==( FenceGetFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( fence == rhs.fence )
+ && ( handleType == rhs.handleType );
+ }
+
+ bool operator!=( FenceGetFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eFenceGetFdInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Fence fence = {};
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits::eOpaqueFd;
+ };
+ static_assert( sizeof( FenceGetFdInfoKHR ) == sizeof( VkFenceGetFdInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<FenceGetFdInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct FenceGetWin32HandleInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR FenceGetWin32HandleInfoKHR( VULKAN_HPP_NAMESPACE::Fence fence_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits::eOpaqueFd ) VULKAN_HPP_NOEXCEPT
+ : fence( fence_ )
+ , handleType( handleType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::FenceGetWin32HandleInfoKHR & operator=( VULKAN_HPP_NAMESPACE::FenceGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::FenceGetWin32HandleInfoKHR ) - offsetof( FenceGetWin32HandleInfoKHR, pNext ) );
+ return *this;
+ }
+
+ FenceGetWin32HandleInfoKHR( VkFenceGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ FenceGetWin32HandleInfoKHR& operator=( VkFenceGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FenceGetWin32HandleInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ FenceGetWin32HandleInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ FenceGetWin32HandleInfoKHR & setFence( VULKAN_HPP_NAMESPACE::Fence fence_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fence = fence_;
+ return *this;
+ }
+
+ FenceGetWin32HandleInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ operator VkFenceGetWin32HandleInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkFenceGetWin32HandleInfoKHR*>( this );
+ }
+
+ operator VkFenceGetWin32HandleInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkFenceGetWin32HandleInfoKHR*>( this );
+ }
+
+ bool operator==( FenceGetWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( fence == rhs.fence )
+ && ( handleType == rhs.handleType );
+ }
+
+ bool operator!=( FenceGetWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eFenceGetWin32HandleInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Fence fence = {};
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits::eOpaqueFd;
+ };
+ static_assert( sizeof( FenceGetWin32HandleInfoKHR ) == sizeof( VkFenceGetWin32HandleInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<FenceGetWin32HandleInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct FilterCubicImageViewImageFormatPropertiesEXT
+ {
+ FilterCubicImageViewImageFormatPropertiesEXT( VULKAN_HPP_NAMESPACE::Bool32 filterCubic_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 filterCubicMinmax_ = {} ) VULKAN_HPP_NOEXCEPT
+ : filterCubic( filterCubic_ )
+ , filterCubicMinmax( filterCubicMinmax_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::FilterCubicImageViewImageFormatPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::FilterCubicImageViewImageFormatPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::FilterCubicImageViewImageFormatPropertiesEXT ) - offsetof( FilterCubicImageViewImageFormatPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ FilterCubicImageViewImageFormatPropertiesEXT( VkFilterCubicImageViewImageFormatPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ FilterCubicImageViewImageFormatPropertiesEXT& operator=( VkFilterCubicImageViewImageFormatPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FilterCubicImageViewImageFormatPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkFilterCubicImageViewImageFormatPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkFilterCubicImageViewImageFormatPropertiesEXT*>( this );
+ }
+
+ operator VkFilterCubicImageViewImageFormatPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkFilterCubicImageViewImageFormatPropertiesEXT*>( this );
+ }
+
+ bool operator==( FilterCubicImageViewImageFormatPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( filterCubic == rhs.filterCubic )
+ && ( filterCubicMinmax == rhs.filterCubicMinmax );
+ }
+
+ bool operator!=( FilterCubicImageViewImageFormatPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eFilterCubicImageViewImageFormatPropertiesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 filterCubic = {};
+ VULKAN_HPP_NAMESPACE::Bool32 filterCubicMinmax = {};
+ };
+ static_assert( sizeof( FilterCubicImageViewImageFormatPropertiesEXT ) == sizeof( VkFilterCubicImageViewImageFormatPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<FilterCubicImageViewImageFormatPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct FormatProperties
+ {
+ FormatProperties( VULKAN_HPP_NAMESPACE::FormatFeatureFlags linearTilingFeatures_ = {},
+ VULKAN_HPP_NAMESPACE::FormatFeatureFlags optimalTilingFeatures_ = {},
+ VULKAN_HPP_NAMESPACE::FormatFeatureFlags bufferFeatures_ = {} ) VULKAN_HPP_NOEXCEPT
+ : linearTilingFeatures( linearTilingFeatures_ )
+ , optimalTilingFeatures( optimalTilingFeatures_ )
+ , bufferFeatures( bufferFeatures_ )
+ {}
+
+ FormatProperties( VkFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ FormatProperties& operator=( VkFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FormatProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkFormatProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkFormatProperties*>( this );
+ }
+
+ operator VkFormatProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkFormatProperties*>( this );
+ }
+
+ bool operator==( FormatProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( linearTilingFeatures == rhs.linearTilingFeatures )
+ && ( optimalTilingFeatures == rhs.optimalTilingFeatures )
+ && ( bufferFeatures == rhs.bufferFeatures );
+ }
+
+ bool operator!=( FormatProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::FormatFeatureFlags linearTilingFeatures = {};
+ VULKAN_HPP_NAMESPACE::FormatFeatureFlags optimalTilingFeatures = {};
+ VULKAN_HPP_NAMESPACE::FormatFeatureFlags bufferFeatures = {};
+ };
+ static_assert( sizeof( FormatProperties ) == sizeof( VkFormatProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<FormatProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct FormatProperties2
+ {
+ FormatProperties2( VULKAN_HPP_NAMESPACE::FormatProperties formatProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : formatProperties( formatProperties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::FormatProperties2 & operator=( VULKAN_HPP_NAMESPACE::FormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::FormatProperties2 ) - offsetof( FormatProperties2, pNext ) );
+ return *this;
+ }
+
+ FormatProperties2( VkFormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ FormatProperties2& operator=( VkFormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FormatProperties2 const *>(&rhs);
+ return *this;
+ }
+
+ operator VkFormatProperties2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkFormatProperties2*>( this );
+ }
+
+ operator VkFormatProperties2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkFormatProperties2*>( this );
+ }
+
+ bool operator==( FormatProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( formatProperties == rhs.formatProperties );
+ }
+
+ bool operator!=( FormatProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eFormatProperties2;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::FormatProperties formatProperties = {};
+ };
+ static_assert( sizeof( FormatProperties2 ) == sizeof( VkFormatProperties2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<FormatProperties2>::value, "struct wrapper is not a standard layout!" );
+
+ struct FramebufferAttachmentImageInfo
+ {
+ VULKAN_HPP_CONSTEXPR FramebufferAttachmentImageInfo( VULKAN_HPP_NAMESPACE::ImageCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags usage_ = {},
+ uint32_t width_ = {},
+ uint32_t height_ = {},
+ uint32_t layerCount_ = {},
+ uint32_t viewFormatCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Format* pViewFormats_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , usage( usage_ )
+ , width( width_ )
+ , height( height_ )
+ , layerCount( layerCount_ )
+ , viewFormatCount( viewFormatCount_ )
+ , pViewFormats( pViewFormats_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::FramebufferAttachmentImageInfo & operator=( VULKAN_HPP_NAMESPACE::FramebufferAttachmentImageInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::FramebufferAttachmentImageInfo ) - offsetof( FramebufferAttachmentImageInfo, pNext ) );
+ return *this;
+ }
+
+ FramebufferAttachmentImageInfo( VkFramebufferAttachmentImageInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ FramebufferAttachmentImageInfo& operator=( VkFramebufferAttachmentImageInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FramebufferAttachmentImageInfo const *>(&rhs);
+ return *this;
+ }
+
+ FramebufferAttachmentImageInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ FramebufferAttachmentImageInfo & setFlags( VULKAN_HPP_NAMESPACE::ImageCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ FramebufferAttachmentImageInfo & setUsage( VULKAN_HPP_NAMESPACE::ImageUsageFlags usage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ usage = usage_;
+ return *this;
+ }
+
+ FramebufferAttachmentImageInfo & setWidth( uint32_t width_ ) VULKAN_HPP_NOEXCEPT
+ {
+ width = width_;
+ return *this;
+ }
+
+ FramebufferAttachmentImageInfo & setHeight( uint32_t height_ ) VULKAN_HPP_NOEXCEPT
+ {
+ height = height_;
+ return *this;
+ }
+
+ FramebufferAttachmentImageInfo & setLayerCount( uint32_t layerCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layerCount = layerCount_;
+ return *this;
+ }
+
+ FramebufferAttachmentImageInfo & setViewFormatCount( uint32_t viewFormatCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ viewFormatCount = viewFormatCount_;
+ return *this;
+ }
+
+ FramebufferAttachmentImageInfo & setPViewFormats( const VULKAN_HPP_NAMESPACE::Format* pViewFormats_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pViewFormats = pViewFormats_;
+ return *this;
+ }
+
+ operator VkFramebufferAttachmentImageInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkFramebufferAttachmentImageInfo*>( this );
+ }
+
+ operator VkFramebufferAttachmentImageInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkFramebufferAttachmentImageInfo*>( this );
+ }
+
+ bool operator==( FramebufferAttachmentImageInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( usage == rhs.usage )
+ && ( width == rhs.width )
+ && ( height == rhs.height )
+ && ( layerCount == rhs.layerCount )
+ && ( viewFormatCount == rhs.viewFormatCount )
+ && ( pViewFormats == rhs.pViewFormats );
+ }
+
+ bool operator!=( FramebufferAttachmentImageInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eFramebufferAttachmentImageInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags usage = {};
+ uint32_t width = {};
+ uint32_t height = {};
+ uint32_t layerCount = {};
+ uint32_t viewFormatCount = {};
+ const VULKAN_HPP_NAMESPACE::Format* pViewFormats = {};
+ };
+ static_assert( sizeof( FramebufferAttachmentImageInfo ) == sizeof( VkFramebufferAttachmentImageInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<FramebufferAttachmentImageInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct FramebufferAttachmentsCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR FramebufferAttachmentsCreateInfo( uint32_t attachmentImageInfoCount_ = {},
+ const VULKAN_HPP_NAMESPACE::FramebufferAttachmentImageInfo* pAttachmentImageInfos_ = {} ) VULKAN_HPP_NOEXCEPT
+ : attachmentImageInfoCount( attachmentImageInfoCount_ )
+ , pAttachmentImageInfos( pAttachmentImageInfos_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::FramebufferAttachmentsCreateInfo & operator=( VULKAN_HPP_NAMESPACE::FramebufferAttachmentsCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::FramebufferAttachmentsCreateInfo ) - offsetof( FramebufferAttachmentsCreateInfo, pNext ) );
+ return *this;
+ }
+
+ FramebufferAttachmentsCreateInfo( VkFramebufferAttachmentsCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ FramebufferAttachmentsCreateInfo& operator=( VkFramebufferAttachmentsCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FramebufferAttachmentsCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ FramebufferAttachmentsCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ FramebufferAttachmentsCreateInfo & setAttachmentImageInfoCount( uint32_t attachmentImageInfoCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ attachmentImageInfoCount = attachmentImageInfoCount_;
+ return *this;
+ }
+
+ FramebufferAttachmentsCreateInfo & setPAttachmentImageInfos( const VULKAN_HPP_NAMESPACE::FramebufferAttachmentImageInfo* pAttachmentImageInfos_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttachmentImageInfos = pAttachmentImageInfos_;
+ return *this;
+ }
+
+ operator VkFramebufferAttachmentsCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkFramebufferAttachmentsCreateInfo*>( this );
+ }
+
+ operator VkFramebufferAttachmentsCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkFramebufferAttachmentsCreateInfo*>( this );
+ }
+
+ bool operator==( FramebufferAttachmentsCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( attachmentImageInfoCount == rhs.attachmentImageInfoCount )
+ && ( pAttachmentImageInfos == rhs.pAttachmentImageInfos );
+ }
+
+ bool operator!=( FramebufferAttachmentsCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eFramebufferAttachmentsCreateInfo;
+ const void* pNext = {};
+ uint32_t attachmentImageInfoCount = {};
+ const VULKAN_HPP_NAMESPACE::FramebufferAttachmentImageInfo* pAttachmentImageInfos = {};
+ };
+ static_assert( sizeof( FramebufferAttachmentsCreateInfo ) == sizeof( VkFramebufferAttachmentsCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<FramebufferAttachmentsCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct FramebufferCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR FramebufferCreateInfo( VULKAN_HPP_NAMESPACE::FramebufferCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass_ = {},
+ uint32_t attachmentCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ImageView* pAttachments_ = {},
+ uint32_t width_ = {},
+ uint32_t height_ = {},
+ uint32_t layers_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , renderPass( renderPass_ )
+ , attachmentCount( attachmentCount_ )
+ , pAttachments( pAttachments_ )
+ , width( width_ )
+ , height( height_ )
+ , layers( layers_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::FramebufferCreateInfo & operator=( VULKAN_HPP_NAMESPACE::FramebufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::FramebufferCreateInfo ) - offsetof( FramebufferCreateInfo, pNext ) );
+ return *this;
+ }
+
+ FramebufferCreateInfo( VkFramebufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ FramebufferCreateInfo& operator=( VkFramebufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FramebufferCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ FramebufferCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ FramebufferCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::FramebufferCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ FramebufferCreateInfo & setRenderPass( VULKAN_HPP_NAMESPACE::RenderPass renderPass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ renderPass = renderPass_;
+ return *this;
+ }
+
+ FramebufferCreateInfo & setAttachmentCount( uint32_t attachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ attachmentCount = attachmentCount_;
+ return *this;
+ }
+
+ FramebufferCreateInfo & setPAttachments( const VULKAN_HPP_NAMESPACE::ImageView* pAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttachments = pAttachments_;
+ return *this;
+ }
+
+ FramebufferCreateInfo & setWidth( uint32_t width_ ) VULKAN_HPP_NOEXCEPT
+ {
+ width = width_;
+ return *this;
+ }
+
+ FramebufferCreateInfo & setHeight( uint32_t height_ ) VULKAN_HPP_NOEXCEPT
+ {
+ height = height_;
+ return *this;
+ }
+
+ FramebufferCreateInfo & setLayers( uint32_t layers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layers = layers_;
+ return *this;
+ }
+
+ operator VkFramebufferCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkFramebufferCreateInfo*>( this );
+ }
+
+ operator VkFramebufferCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkFramebufferCreateInfo*>( this );
+ }
+
+ bool operator==( FramebufferCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( renderPass == rhs.renderPass )
+ && ( attachmentCount == rhs.attachmentCount )
+ && ( pAttachments == rhs.pAttachments )
+ && ( width == rhs.width )
+ && ( height == rhs.height )
+ && ( layers == rhs.layers );
+ }
+
+ bool operator!=( FramebufferCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eFramebufferCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::FramebufferCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass = {};
+ uint32_t attachmentCount = {};
+ const VULKAN_HPP_NAMESPACE::ImageView* pAttachments = {};
+ uint32_t width = {};
+ uint32_t height = {};
+ uint32_t layers = {};
+ };
+ static_assert( sizeof( FramebufferCreateInfo ) == sizeof( VkFramebufferCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<FramebufferCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct FramebufferMixedSamplesCombinationNV
+ {
+ FramebufferMixedSamplesCombinationNV( VULKAN_HPP_NAMESPACE::CoverageReductionModeNV coverageReductionMode_ = VULKAN_HPP_NAMESPACE::CoverageReductionModeNV::eMerge,
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits rasterizationSamples_ = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1,
+ VULKAN_HPP_NAMESPACE::SampleCountFlags depthStencilSamples_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags colorSamples_ = {} ) VULKAN_HPP_NOEXCEPT
+ : coverageReductionMode( coverageReductionMode_ )
+ , rasterizationSamples( rasterizationSamples_ )
+ , depthStencilSamples( depthStencilSamples_ )
+ , colorSamples( colorSamples_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::FramebufferMixedSamplesCombinationNV & operator=( VULKAN_HPP_NAMESPACE::FramebufferMixedSamplesCombinationNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::FramebufferMixedSamplesCombinationNV ) - offsetof( FramebufferMixedSamplesCombinationNV, pNext ) );
+ return *this;
+ }
+
+ FramebufferMixedSamplesCombinationNV( VkFramebufferMixedSamplesCombinationNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ FramebufferMixedSamplesCombinationNV& operator=( VkFramebufferMixedSamplesCombinationNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::FramebufferMixedSamplesCombinationNV const *>(&rhs);
+ return *this;
+ }
+
+ operator VkFramebufferMixedSamplesCombinationNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkFramebufferMixedSamplesCombinationNV*>( this );
+ }
+
+ operator VkFramebufferMixedSamplesCombinationNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkFramebufferMixedSamplesCombinationNV*>( this );
+ }
+
+ bool operator==( FramebufferMixedSamplesCombinationNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( coverageReductionMode == rhs.coverageReductionMode )
+ && ( rasterizationSamples == rhs.rasterizationSamples )
+ && ( depthStencilSamples == rhs.depthStencilSamples )
+ && ( colorSamples == rhs.colorSamples );
+ }
+
+ bool operator!=( FramebufferMixedSamplesCombinationNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eFramebufferMixedSamplesCombinationNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::CoverageReductionModeNV coverageReductionMode = VULKAN_HPP_NAMESPACE::CoverageReductionModeNV::eMerge;
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits rasterizationSamples = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1;
+ VULKAN_HPP_NAMESPACE::SampleCountFlags depthStencilSamples = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags colorSamples = {};
+ };
+ static_assert( sizeof( FramebufferMixedSamplesCombinationNV ) == sizeof( VkFramebufferMixedSamplesCombinationNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<FramebufferMixedSamplesCombinationNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct VertexInputBindingDescription
+ {
+ VULKAN_HPP_CONSTEXPR VertexInputBindingDescription( uint32_t binding_ = {},
+ uint32_t stride_ = {},
+ VULKAN_HPP_NAMESPACE::VertexInputRate inputRate_ = VULKAN_HPP_NAMESPACE::VertexInputRate::eVertex ) VULKAN_HPP_NOEXCEPT
+ : binding( binding_ )
+ , stride( stride_ )
+ , inputRate( inputRate_ )
+ {}
+
+ VertexInputBindingDescription( VkVertexInputBindingDescription const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ VertexInputBindingDescription& operator=( VkVertexInputBindingDescription const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::VertexInputBindingDescription const *>(&rhs);
+ return *this;
+ }
+
+ VertexInputBindingDescription & setBinding( uint32_t binding_ ) VULKAN_HPP_NOEXCEPT
+ {
+ binding = binding_;
+ return *this;
+ }
+
+ VertexInputBindingDescription & setStride( uint32_t stride_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stride = stride_;
+ return *this;
+ }
+
+ VertexInputBindingDescription & setInputRate( VULKAN_HPP_NAMESPACE::VertexInputRate inputRate_ ) VULKAN_HPP_NOEXCEPT
+ {
+ inputRate = inputRate_;
+ return *this;
+ }
+
+ operator VkVertexInputBindingDescription const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkVertexInputBindingDescription*>( this );
+ }
+
+ operator VkVertexInputBindingDescription &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkVertexInputBindingDescription*>( this );
+ }
+
+ bool operator==( VertexInputBindingDescription const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( binding == rhs.binding )
+ && ( stride == rhs.stride )
+ && ( inputRate == rhs.inputRate );
+ }
+
+ bool operator!=( VertexInputBindingDescription const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t binding = {};
+ uint32_t stride = {};
+ VULKAN_HPP_NAMESPACE::VertexInputRate inputRate = VULKAN_HPP_NAMESPACE::VertexInputRate::eVertex;
+ };
+ static_assert( sizeof( VertexInputBindingDescription ) == sizeof( VkVertexInputBindingDescription ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<VertexInputBindingDescription>::value, "struct wrapper is not a standard layout!" );
+
+ struct VertexInputAttributeDescription
+ {
+ VULKAN_HPP_CONSTEXPR VertexInputAttributeDescription( uint32_t location_ = {},
+ uint32_t binding_ = {},
+ VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ uint32_t offset_ = {} ) VULKAN_HPP_NOEXCEPT
+ : location( location_ )
+ , binding( binding_ )
+ , format( format_ )
+ , offset( offset_ )
+ {}
+
+ VertexInputAttributeDescription( VkVertexInputAttributeDescription const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ VertexInputAttributeDescription& operator=( VkVertexInputAttributeDescription const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::VertexInputAttributeDescription const *>(&rhs);
+ return *this;
+ }
+
+ VertexInputAttributeDescription & setLocation( uint32_t location_ ) VULKAN_HPP_NOEXCEPT
+ {
+ location = location_;
+ return *this;
+ }
+
+ VertexInputAttributeDescription & setBinding( uint32_t binding_ ) VULKAN_HPP_NOEXCEPT
+ {
+ binding = binding_;
+ return *this;
+ }
+
+ VertexInputAttributeDescription & setFormat( VULKAN_HPP_NAMESPACE::Format format_ ) VULKAN_HPP_NOEXCEPT
+ {
+ format = format_;
+ return *this;
+ }
+
+ VertexInputAttributeDescription & setOffset( uint32_t offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ operator VkVertexInputAttributeDescription const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkVertexInputAttributeDescription*>( this );
+ }
+
+ operator VkVertexInputAttributeDescription &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkVertexInputAttributeDescription*>( this );
+ }
+
+ bool operator==( VertexInputAttributeDescription const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( location == rhs.location )
+ && ( binding == rhs.binding )
+ && ( format == rhs.format )
+ && ( offset == rhs.offset );
+ }
+
+ bool operator!=( VertexInputAttributeDescription const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t location = {};
+ uint32_t binding = {};
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ uint32_t offset = {};
+ };
+ static_assert( sizeof( VertexInputAttributeDescription ) == sizeof( VkVertexInputAttributeDescription ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<VertexInputAttributeDescription>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineVertexInputStateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineVertexInputStateCreateInfo( VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateFlags flags_ = {},
+ uint32_t vertexBindingDescriptionCount_ = {},
+ const VULKAN_HPP_NAMESPACE::VertexInputBindingDescription* pVertexBindingDescriptions_ = {},
+ uint32_t vertexAttributeDescriptionCount_ = {},
+ const VULKAN_HPP_NAMESPACE::VertexInputAttributeDescription* pVertexAttributeDescriptions_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , vertexBindingDescriptionCount( vertexBindingDescriptionCount_ )
+ , pVertexBindingDescriptions( pVertexBindingDescriptions_ )
+ , vertexAttributeDescriptionCount( vertexAttributeDescriptionCount_ )
+ , pVertexAttributeDescriptions( pVertexAttributeDescriptions_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateInfo ) - offsetof( PipelineVertexInputStateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineVertexInputStateCreateInfo( VkPipelineVertexInputStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineVertexInputStateCreateInfo& operator=( VkPipelineVertexInputStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineVertexInputStateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineVertexInputStateCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineVertexInputStateCreateInfo & setVertexBindingDescriptionCount( uint32_t vertexBindingDescriptionCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexBindingDescriptionCount = vertexBindingDescriptionCount_;
+ return *this;
+ }
+
+ PipelineVertexInputStateCreateInfo & setPVertexBindingDescriptions( const VULKAN_HPP_NAMESPACE::VertexInputBindingDescription* pVertexBindingDescriptions_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pVertexBindingDescriptions = pVertexBindingDescriptions_;
+ return *this;
+ }
+
+ PipelineVertexInputStateCreateInfo & setVertexAttributeDescriptionCount( uint32_t vertexAttributeDescriptionCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexAttributeDescriptionCount = vertexAttributeDescriptionCount_;
+ return *this;
+ }
+
+ PipelineVertexInputStateCreateInfo & setPVertexAttributeDescriptions( const VULKAN_HPP_NAMESPACE::VertexInputAttributeDescription* pVertexAttributeDescriptions_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pVertexAttributeDescriptions = pVertexAttributeDescriptions_;
+ return *this;
+ }
+
+ operator VkPipelineVertexInputStateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineVertexInputStateCreateInfo*>( this );
+ }
+
+ operator VkPipelineVertexInputStateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineVertexInputStateCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineVertexInputStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( vertexBindingDescriptionCount == rhs.vertexBindingDescriptionCount )
+ && ( pVertexBindingDescriptions == rhs.pVertexBindingDescriptions )
+ && ( vertexAttributeDescriptionCount == rhs.vertexAttributeDescriptionCount )
+ && ( pVertexAttributeDescriptions == rhs.pVertexAttributeDescriptions );
+ }
+
+ bool operator!=( PipelineVertexInputStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineVertexInputStateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateFlags flags = {};
+ uint32_t vertexBindingDescriptionCount = {};
+ const VULKAN_HPP_NAMESPACE::VertexInputBindingDescription* pVertexBindingDescriptions = {};
+ uint32_t vertexAttributeDescriptionCount = {};
+ const VULKAN_HPP_NAMESPACE::VertexInputAttributeDescription* pVertexAttributeDescriptions = {};
+ };
+ static_assert( sizeof( PipelineVertexInputStateCreateInfo ) == sizeof( VkPipelineVertexInputStateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineVertexInputStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineInputAssemblyStateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineInputAssemblyStateCreateInfo( VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::PrimitiveTopology topology_ = VULKAN_HPP_NAMESPACE::PrimitiveTopology::ePointList,
+ VULKAN_HPP_NAMESPACE::Bool32 primitiveRestartEnable_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , topology( topology_ )
+ , primitiveRestartEnable( primitiveRestartEnable_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateInfo ) - offsetof( PipelineInputAssemblyStateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineInputAssemblyStateCreateInfo( VkPipelineInputAssemblyStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineInputAssemblyStateCreateInfo& operator=( VkPipelineInputAssemblyStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineInputAssemblyStateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineInputAssemblyStateCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineInputAssemblyStateCreateInfo & setTopology( VULKAN_HPP_NAMESPACE::PrimitiveTopology topology_ ) VULKAN_HPP_NOEXCEPT
+ {
+ topology = topology_;
+ return *this;
+ }
+
+ PipelineInputAssemblyStateCreateInfo & setPrimitiveRestartEnable( VULKAN_HPP_NAMESPACE::Bool32 primitiveRestartEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ primitiveRestartEnable = primitiveRestartEnable_;
+ return *this;
+ }
+
+ operator VkPipelineInputAssemblyStateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineInputAssemblyStateCreateInfo*>( this );
+ }
+
+ operator VkPipelineInputAssemblyStateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineInputAssemblyStateCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineInputAssemblyStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( topology == rhs.topology )
+ && ( primitiveRestartEnable == rhs.primitiveRestartEnable );
+ }
+
+ bool operator!=( PipelineInputAssemblyStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineInputAssemblyStateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::PrimitiveTopology topology = VULKAN_HPP_NAMESPACE::PrimitiveTopology::ePointList;
+ VULKAN_HPP_NAMESPACE::Bool32 primitiveRestartEnable = {};
+ };
+ static_assert( sizeof( PipelineInputAssemblyStateCreateInfo ) == sizeof( VkPipelineInputAssemblyStateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineInputAssemblyStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineTessellationStateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineTessellationStateCreateInfo( VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateFlags flags_ = {},
+ uint32_t patchControlPoints_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , patchControlPoints( patchControlPoints_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateInfo ) - offsetof( PipelineTessellationStateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineTessellationStateCreateInfo( VkPipelineTessellationStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineTessellationStateCreateInfo& operator=( VkPipelineTessellationStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineTessellationStateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineTessellationStateCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineTessellationStateCreateInfo & setPatchControlPoints( uint32_t patchControlPoints_ ) VULKAN_HPP_NOEXCEPT
+ {
+ patchControlPoints = patchControlPoints_;
+ return *this;
+ }
+
+ operator VkPipelineTessellationStateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineTessellationStateCreateInfo*>( this );
+ }
+
+ operator VkPipelineTessellationStateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineTessellationStateCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineTessellationStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( patchControlPoints == rhs.patchControlPoints );
+ }
+
+ bool operator!=( PipelineTessellationStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineTessellationStateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateFlags flags = {};
+ uint32_t patchControlPoints = {};
+ };
+ static_assert( sizeof( PipelineTessellationStateCreateInfo ) == sizeof( VkPipelineTessellationStateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineTessellationStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct Viewport
+ {
+ VULKAN_HPP_CONSTEXPR Viewport( float x_ = {},
+ float y_ = {},
+ float width_ = {},
+ float height_ = {},
+ float minDepth_ = {},
+ float maxDepth_ = {} ) VULKAN_HPP_NOEXCEPT
+ : x( x_ )
+ , y( y_ )
+ , width( width_ )
+ , height( height_ )
+ , minDepth( minDepth_ )
+ , maxDepth( maxDepth_ )
+ {}
+
+ Viewport( VkViewport const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ Viewport& operator=( VkViewport const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::Viewport const *>(&rhs);
+ return *this;
+ }
+
+ Viewport & setX( float x_ ) VULKAN_HPP_NOEXCEPT
+ {
+ x = x_;
+ return *this;
+ }
+
+ Viewport & setY( float y_ ) VULKAN_HPP_NOEXCEPT
+ {
+ y = y_;
+ return *this;
+ }
+
+ Viewport & setWidth( float width_ ) VULKAN_HPP_NOEXCEPT
+ {
+ width = width_;
+ return *this;
+ }
+
+ Viewport & setHeight( float height_ ) VULKAN_HPP_NOEXCEPT
+ {
+ height = height_;
+ return *this;
+ }
+
+ Viewport & setMinDepth( float minDepth_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minDepth = minDepth_;
+ return *this;
+ }
+
+ Viewport & setMaxDepth( float maxDepth_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxDepth = maxDepth_;
+ return *this;
+ }
+
+ operator VkViewport const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkViewport*>( this );
+ }
+
+ operator VkViewport &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkViewport*>( this );
+ }
+
+ bool operator==( Viewport const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( x == rhs.x )
+ && ( y == rhs.y )
+ && ( width == rhs.width )
+ && ( height == rhs.height )
+ && ( minDepth == rhs.minDepth )
+ && ( maxDepth == rhs.maxDepth );
+ }
+
+ bool operator!=( Viewport const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ float x = {};
+ float y = {};
+ float width = {};
+ float height = {};
+ float minDepth = {};
+ float maxDepth = {};
+ };
+ static_assert( sizeof( Viewport ) == sizeof( VkViewport ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<Viewport>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineViewportStateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineViewportStateCreateInfo( VULKAN_HPP_NAMESPACE::PipelineViewportStateCreateFlags flags_ = {},
+ uint32_t viewportCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Viewport* pViewports_ = {},
+ uint32_t scissorCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Rect2D* pScissors_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , viewportCount( viewportCount_ )
+ , pViewports( pViewports_ )
+ , scissorCount( scissorCount_ )
+ , pScissors( pScissors_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineViewportStateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineViewportStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineViewportStateCreateInfo ) - offsetof( PipelineViewportStateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineViewportStateCreateInfo( VkPipelineViewportStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineViewportStateCreateInfo& operator=( VkPipelineViewportStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineViewportStateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineViewportStateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineViewportStateCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineViewportStateCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineViewportStateCreateInfo & setViewportCount( uint32_t viewportCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ viewportCount = viewportCount_;
+ return *this;
+ }
+
+ PipelineViewportStateCreateInfo & setPViewports( const VULKAN_HPP_NAMESPACE::Viewport* pViewports_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pViewports = pViewports_;
+ return *this;
+ }
+
+ PipelineViewportStateCreateInfo & setScissorCount( uint32_t scissorCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ scissorCount = scissorCount_;
+ return *this;
+ }
+
+ PipelineViewportStateCreateInfo & setPScissors( const VULKAN_HPP_NAMESPACE::Rect2D* pScissors_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pScissors = pScissors_;
+ return *this;
+ }
+
+ operator VkPipelineViewportStateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineViewportStateCreateInfo*>( this );
+ }
+
+ operator VkPipelineViewportStateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineViewportStateCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineViewportStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( viewportCount == rhs.viewportCount )
+ && ( pViewports == rhs.pViewports )
+ && ( scissorCount == rhs.scissorCount )
+ && ( pScissors == rhs.pScissors );
+ }
+
+ bool operator!=( PipelineViewportStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineViewportStateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineViewportStateCreateFlags flags = {};
+ uint32_t viewportCount = {};
+ const VULKAN_HPP_NAMESPACE::Viewport* pViewports = {};
+ uint32_t scissorCount = {};
+ const VULKAN_HPP_NAMESPACE::Rect2D* pScissors = {};
+ };
+ static_assert( sizeof( PipelineViewportStateCreateInfo ) == sizeof( VkPipelineViewportStateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineViewportStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineRasterizationStateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineRasterizationStateCreateInfo( VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 depthClampEnable_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 rasterizerDiscardEnable_ = {},
+ VULKAN_HPP_NAMESPACE::PolygonMode polygonMode_ = VULKAN_HPP_NAMESPACE::PolygonMode::eFill,
+ VULKAN_HPP_NAMESPACE::CullModeFlags cullMode_ = {},
+ VULKAN_HPP_NAMESPACE::FrontFace frontFace_ = VULKAN_HPP_NAMESPACE::FrontFace::eCounterClockwise,
+ VULKAN_HPP_NAMESPACE::Bool32 depthBiasEnable_ = {},
+ float depthBiasConstantFactor_ = {},
+ float depthBiasClamp_ = {},
+ float depthBiasSlopeFactor_ = {},
+ float lineWidth_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , depthClampEnable( depthClampEnable_ )
+ , rasterizerDiscardEnable( rasterizerDiscardEnable_ )
+ , polygonMode( polygonMode_ )
+ , cullMode( cullMode_ )
+ , frontFace( frontFace_ )
+ , depthBiasEnable( depthBiasEnable_ )
+ , depthBiasConstantFactor( depthBiasConstantFactor_ )
+ , depthBiasClamp( depthBiasClamp_ )
+ , depthBiasSlopeFactor( depthBiasSlopeFactor_ )
+ , lineWidth( lineWidth_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateInfo ) - offsetof( PipelineRasterizationStateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo( VkPipelineRasterizationStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineRasterizationStateCreateInfo& operator=( VkPipelineRasterizationStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setDepthClampEnable( VULKAN_HPP_NAMESPACE::Bool32 depthClampEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthClampEnable = depthClampEnable_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setRasterizerDiscardEnable( VULKAN_HPP_NAMESPACE::Bool32 rasterizerDiscardEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ rasterizerDiscardEnable = rasterizerDiscardEnable_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setPolygonMode( VULKAN_HPP_NAMESPACE::PolygonMode polygonMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ polygonMode = polygonMode_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setCullMode( VULKAN_HPP_NAMESPACE::CullModeFlags cullMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ cullMode = cullMode_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setFrontFace( VULKAN_HPP_NAMESPACE::FrontFace frontFace_ ) VULKAN_HPP_NOEXCEPT
+ {
+ frontFace = frontFace_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setDepthBiasEnable( VULKAN_HPP_NAMESPACE::Bool32 depthBiasEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthBiasEnable = depthBiasEnable_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setDepthBiasConstantFactor( float depthBiasConstantFactor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthBiasConstantFactor = depthBiasConstantFactor_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setDepthBiasClamp( float depthBiasClamp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthBiasClamp = depthBiasClamp_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setDepthBiasSlopeFactor( float depthBiasSlopeFactor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthBiasSlopeFactor = depthBiasSlopeFactor_;
+ return *this;
+ }
+
+ PipelineRasterizationStateCreateInfo & setLineWidth( float lineWidth_ ) VULKAN_HPP_NOEXCEPT
+ {
+ lineWidth = lineWidth_;
+ return *this;
+ }
+
+ operator VkPipelineRasterizationStateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineRasterizationStateCreateInfo*>( this );
+ }
+
+ operator VkPipelineRasterizationStateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineRasterizationStateCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineRasterizationStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( depthClampEnable == rhs.depthClampEnable )
+ && ( rasterizerDiscardEnable == rhs.rasterizerDiscardEnable )
+ && ( polygonMode == rhs.polygonMode )
+ && ( cullMode == rhs.cullMode )
+ && ( frontFace == rhs.frontFace )
+ && ( depthBiasEnable == rhs.depthBiasEnable )
+ && ( depthBiasConstantFactor == rhs.depthBiasConstantFactor )
+ && ( depthBiasClamp == rhs.depthBiasClamp )
+ && ( depthBiasSlopeFactor == rhs.depthBiasSlopeFactor )
+ && ( lineWidth == rhs.lineWidth );
+ }
+
+ bool operator!=( PipelineRasterizationStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineRasterizationStateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::Bool32 depthClampEnable = {};
+ VULKAN_HPP_NAMESPACE::Bool32 rasterizerDiscardEnable = {};
+ VULKAN_HPP_NAMESPACE::PolygonMode polygonMode = VULKAN_HPP_NAMESPACE::PolygonMode::eFill;
+ VULKAN_HPP_NAMESPACE::CullModeFlags cullMode = {};
+ VULKAN_HPP_NAMESPACE::FrontFace frontFace = VULKAN_HPP_NAMESPACE::FrontFace::eCounterClockwise;
+ VULKAN_HPP_NAMESPACE::Bool32 depthBiasEnable = {};
+ float depthBiasConstantFactor = {};
+ float depthBiasClamp = {};
+ float depthBiasSlopeFactor = {};
+ float lineWidth = {};
+ };
+ static_assert( sizeof( PipelineRasterizationStateCreateInfo ) == sizeof( VkPipelineRasterizationStateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineRasterizationStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineMultisampleStateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineMultisampleStateCreateInfo( VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits rasterizationSamples_ = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1,
+ VULKAN_HPP_NAMESPACE::Bool32 sampleShadingEnable_ = {},
+ float minSampleShading_ = {},
+ const VULKAN_HPP_NAMESPACE::SampleMask* pSampleMask_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 alphaToCoverageEnable_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 alphaToOneEnable_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , rasterizationSamples( rasterizationSamples_ )
+ , sampleShadingEnable( sampleShadingEnable_ )
+ , minSampleShading( minSampleShading_ )
+ , pSampleMask( pSampleMask_ )
+ , alphaToCoverageEnable( alphaToCoverageEnable_ )
+ , alphaToOneEnable( alphaToOneEnable_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateInfo ) - offsetof( PipelineMultisampleStateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineMultisampleStateCreateInfo( VkPipelineMultisampleStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineMultisampleStateCreateInfo& operator=( VkPipelineMultisampleStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineMultisampleStateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineMultisampleStateCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineMultisampleStateCreateInfo & setRasterizationSamples( VULKAN_HPP_NAMESPACE::SampleCountFlagBits rasterizationSamples_ ) VULKAN_HPP_NOEXCEPT
+ {
+ rasterizationSamples = rasterizationSamples_;
+ return *this;
+ }
+
+ PipelineMultisampleStateCreateInfo & setSampleShadingEnable( VULKAN_HPP_NAMESPACE::Bool32 sampleShadingEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleShadingEnable = sampleShadingEnable_;
+ return *this;
+ }
+
+ PipelineMultisampleStateCreateInfo & setMinSampleShading( float minSampleShading_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minSampleShading = minSampleShading_;
+ return *this;
+ }
+
+ PipelineMultisampleStateCreateInfo & setPSampleMask( const VULKAN_HPP_NAMESPACE::SampleMask* pSampleMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSampleMask = pSampleMask_;
+ return *this;
+ }
+
+ PipelineMultisampleStateCreateInfo & setAlphaToCoverageEnable( VULKAN_HPP_NAMESPACE::Bool32 alphaToCoverageEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ alphaToCoverageEnable = alphaToCoverageEnable_;
+ return *this;
+ }
+
+ PipelineMultisampleStateCreateInfo & setAlphaToOneEnable( VULKAN_HPP_NAMESPACE::Bool32 alphaToOneEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ alphaToOneEnable = alphaToOneEnable_;
+ return *this;
+ }
+
+ operator VkPipelineMultisampleStateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineMultisampleStateCreateInfo*>( this );
+ }
+
+ operator VkPipelineMultisampleStateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineMultisampleStateCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineMultisampleStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( rasterizationSamples == rhs.rasterizationSamples )
+ && ( sampleShadingEnable == rhs.sampleShadingEnable )
+ && ( minSampleShading == rhs.minSampleShading )
+ && ( pSampleMask == rhs.pSampleMask )
+ && ( alphaToCoverageEnable == rhs.alphaToCoverageEnable )
+ && ( alphaToOneEnable == rhs.alphaToOneEnable );
+ }
+
+ bool operator!=( PipelineMultisampleStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineMultisampleStateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits rasterizationSamples = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1;
+ VULKAN_HPP_NAMESPACE::Bool32 sampleShadingEnable = {};
+ float minSampleShading = {};
+ const VULKAN_HPP_NAMESPACE::SampleMask* pSampleMask = {};
+ VULKAN_HPP_NAMESPACE::Bool32 alphaToCoverageEnable = {};
+ VULKAN_HPP_NAMESPACE::Bool32 alphaToOneEnable = {};
+ };
+ static_assert( sizeof( PipelineMultisampleStateCreateInfo ) == sizeof( VkPipelineMultisampleStateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineMultisampleStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct StencilOpState
+ {
+ VULKAN_HPP_CONSTEXPR StencilOpState( VULKAN_HPP_NAMESPACE::StencilOp failOp_ = VULKAN_HPP_NAMESPACE::StencilOp::eKeep,
+ VULKAN_HPP_NAMESPACE::StencilOp passOp_ = VULKAN_HPP_NAMESPACE::StencilOp::eKeep,
+ VULKAN_HPP_NAMESPACE::StencilOp depthFailOp_ = VULKAN_HPP_NAMESPACE::StencilOp::eKeep,
+ VULKAN_HPP_NAMESPACE::CompareOp compareOp_ = VULKAN_HPP_NAMESPACE::CompareOp::eNever,
+ uint32_t compareMask_ = {},
+ uint32_t writeMask_ = {},
+ uint32_t reference_ = {} ) VULKAN_HPP_NOEXCEPT
+ : failOp( failOp_ )
+ , passOp( passOp_ )
+ , depthFailOp( depthFailOp_ )
+ , compareOp( compareOp_ )
+ , compareMask( compareMask_ )
+ , writeMask( writeMask_ )
+ , reference( reference_ )
+ {}
+
+ StencilOpState( VkStencilOpState const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ StencilOpState& operator=( VkStencilOpState const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::StencilOpState const *>(&rhs);
+ return *this;
+ }
+
+ StencilOpState & setFailOp( VULKAN_HPP_NAMESPACE::StencilOp failOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ failOp = failOp_;
+ return *this;
+ }
+
+ StencilOpState & setPassOp( VULKAN_HPP_NAMESPACE::StencilOp passOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ passOp = passOp_;
+ return *this;
+ }
+
+ StencilOpState & setDepthFailOp( VULKAN_HPP_NAMESPACE::StencilOp depthFailOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthFailOp = depthFailOp_;
+ return *this;
+ }
+
+ StencilOpState & setCompareOp( VULKAN_HPP_NAMESPACE::CompareOp compareOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ compareOp = compareOp_;
+ return *this;
+ }
+
+ StencilOpState & setCompareMask( uint32_t compareMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ compareMask = compareMask_;
+ return *this;
+ }
+
+ StencilOpState & setWriteMask( uint32_t writeMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ writeMask = writeMask_;
+ return *this;
+ }
+
+ StencilOpState & setReference( uint32_t reference_ ) VULKAN_HPP_NOEXCEPT
+ {
+ reference = reference_;
+ return *this;
+ }
+
+ operator VkStencilOpState const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkStencilOpState*>( this );
+ }
+
+ operator VkStencilOpState &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkStencilOpState*>( this );
+ }
+
+ bool operator==( StencilOpState const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( failOp == rhs.failOp )
+ && ( passOp == rhs.passOp )
+ && ( depthFailOp == rhs.depthFailOp )
+ && ( compareOp == rhs.compareOp )
+ && ( compareMask == rhs.compareMask )
+ && ( writeMask == rhs.writeMask )
+ && ( reference == rhs.reference );
+ }
+
+ bool operator!=( StencilOpState const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::StencilOp failOp = VULKAN_HPP_NAMESPACE::StencilOp::eKeep;
+ VULKAN_HPP_NAMESPACE::StencilOp passOp = VULKAN_HPP_NAMESPACE::StencilOp::eKeep;
+ VULKAN_HPP_NAMESPACE::StencilOp depthFailOp = VULKAN_HPP_NAMESPACE::StencilOp::eKeep;
+ VULKAN_HPP_NAMESPACE::CompareOp compareOp = VULKAN_HPP_NAMESPACE::CompareOp::eNever;
+ uint32_t compareMask = {};
+ uint32_t writeMask = {};
+ uint32_t reference = {};
+ };
+ static_assert( sizeof( StencilOpState ) == sizeof( VkStencilOpState ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<StencilOpState>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineDepthStencilStateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineDepthStencilStateCreateInfo( VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 depthTestEnable_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 depthWriteEnable_ = {},
+ VULKAN_HPP_NAMESPACE::CompareOp depthCompareOp_ = VULKAN_HPP_NAMESPACE::CompareOp::eNever,
+ VULKAN_HPP_NAMESPACE::Bool32 depthBoundsTestEnable_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 stencilTestEnable_ = {},
+ VULKAN_HPP_NAMESPACE::StencilOpState front_ = {},
+ VULKAN_HPP_NAMESPACE::StencilOpState back_ = {},
+ float minDepthBounds_ = {},
+ float maxDepthBounds_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , depthTestEnable( depthTestEnable_ )
+ , depthWriteEnable( depthWriteEnable_ )
+ , depthCompareOp( depthCompareOp_ )
+ , depthBoundsTestEnable( depthBoundsTestEnable_ )
+ , stencilTestEnable( stencilTestEnable_ )
+ , front( front_ )
+ , back( back_ )
+ , minDepthBounds( minDepthBounds_ )
+ , maxDepthBounds( maxDepthBounds_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateInfo ) - offsetof( PipelineDepthStencilStateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo( VkPipelineDepthStencilStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineDepthStencilStateCreateInfo& operator=( VkPipelineDepthStencilStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setDepthTestEnable( VULKAN_HPP_NAMESPACE::Bool32 depthTestEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthTestEnable = depthTestEnable_;
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setDepthWriteEnable( VULKAN_HPP_NAMESPACE::Bool32 depthWriteEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthWriteEnable = depthWriteEnable_;
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setDepthCompareOp( VULKAN_HPP_NAMESPACE::CompareOp depthCompareOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthCompareOp = depthCompareOp_;
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setDepthBoundsTestEnable( VULKAN_HPP_NAMESPACE::Bool32 depthBoundsTestEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthBoundsTestEnable = depthBoundsTestEnable_;
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setStencilTestEnable( VULKAN_HPP_NAMESPACE::Bool32 stencilTestEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencilTestEnable = stencilTestEnable_;
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setFront( VULKAN_HPP_NAMESPACE::StencilOpState front_ ) VULKAN_HPP_NOEXCEPT
+ {
+ front = front_;
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setBack( VULKAN_HPP_NAMESPACE::StencilOpState back_ ) VULKAN_HPP_NOEXCEPT
+ {
+ back = back_;
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setMinDepthBounds( float minDepthBounds_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minDepthBounds = minDepthBounds_;
+ return *this;
+ }
+
+ PipelineDepthStencilStateCreateInfo & setMaxDepthBounds( float maxDepthBounds_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxDepthBounds = maxDepthBounds_;
+ return *this;
+ }
+
+ operator VkPipelineDepthStencilStateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineDepthStencilStateCreateInfo*>( this );
+ }
+
+ operator VkPipelineDepthStencilStateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineDepthStencilStateCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineDepthStencilStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( depthTestEnable == rhs.depthTestEnable )
+ && ( depthWriteEnable == rhs.depthWriteEnable )
+ && ( depthCompareOp == rhs.depthCompareOp )
+ && ( depthBoundsTestEnable == rhs.depthBoundsTestEnable )
+ && ( stencilTestEnable == rhs.stencilTestEnable )
+ && ( front == rhs.front )
+ && ( back == rhs.back )
+ && ( minDepthBounds == rhs.minDepthBounds )
+ && ( maxDepthBounds == rhs.maxDepthBounds );
+ }
+
+ bool operator!=( PipelineDepthStencilStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineDepthStencilStateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::Bool32 depthTestEnable = {};
+ VULKAN_HPP_NAMESPACE::Bool32 depthWriteEnable = {};
+ VULKAN_HPP_NAMESPACE::CompareOp depthCompareOp = VULKAN_HPP_NAMESPACE::CompareOp::eNever;
+ VULKAN_HPP_NAMESPACE::Bool32 depthBoundsTestEnable = {};
+ VULKAN_HPP_NAMESPACE::Bool32 stencilTestEnable = {};
+ VULKAN_HPP_NAMESPACE::StencilOpState front = {};
+ VULKAN_HPP_NAMESPACE::StencilOpState back = {};
+ float minDepthBounds = {};
+ float maxDepthBounds = {};
+ };
+ static_assert( sizeof( PipelineDepthStencilStateCreateInfo ) == sizeof( VkPipelineDepthStencilStateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineDepthStencilStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineColorBlendAttachmentState
+ {
+ VULKAN_HPP_CONSTEXPR PipelineColorBlendAttachmentState( VULKAN_HPP_NAMESPACE::Bool32 blendEnable_ = {},
+ VULKAN_HPP_NAMESPACE::BlendFactor srcColorBlendFactor_ = VULKAN_HPP_NAMESPACE::BlendFactor::eZero,
+ VULKAN_HPP_NAMESPACE::BlendFactor dstColorBlendFactor_ = VULKAN_HPP_NAMESPACE::BlendFactor::eZero,
+ VULKAN_HPP_NAMESPACE::BlendOp colorBlendOp_ = VULKAN_HPP_NAMESPACE::BlendOp::eAdd,
+ VULKAN_HPP_NAMESPACE::BlendFactor srcAlphaBlendFactor_ = VULKAN_HPP_NAMESPACE::BlendFactor::eZero,
+ VULKAN_HPP_NAMESPACE::BlendFactor dstAlphaBlendFactor_ = VULKAN_HPP_NAMESPACE::BlendFactor::eZero,
+ VULKAN_HPP_NAMESPACE::BlendOp alphaBlendOp_ = VULKAN_HPP_NAMESPACE::BlendOp::eAdd,
+ VULKAN_HPP_NAMESPACE::ColorComponentFlags colorWriteMask_ = {} ) VULKAN_HPP_NOEXCEPT
+ : blendEnable( blendEnable_ )
+ , srcColorBlendFactor( srcColorBlendFactor_ )
+ , dstColorBlendFactor( dstColorBlendFactor_ )
+ , colorBlendOp( colorBlendOp_ )
+ , srcAlphaBlendFactor( srcAlphaBlendFactor_ )
+ , dstAlphaBlendFactor( dstAlphaBlendFactor_ )
+ , alphaBlendOp( alphaBlendOp_ )
+ , colorWriteMask( colorWriteMask_ )
+ {}
+
+ PipelineColorBlendAttachmentState( VkPipelineColorBlendAttachmentState const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineColorBlendAttachmentState& operator=( VkPipelineColorBlendAttachmentState const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineColorBlendAttachmentState const *>(&rhs);
+ return *this;
+ }
+
+ PipelineColorBlendAttachmentState & setBlendEnable( VULKAN_HPP_NAMESPACE::Bool32 blendEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ blendEnable = blendEnable_;
+ return *this;
+ }
+
+ PipelineColorBlendAttachmentState & setSrcColorBlendFactor( VULKAN_HPP_NAMESPACE::BlendFactor srcColorBlendFactor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcColorBlendFactor = srcColorBlendFactor_;
+ return *this;
+ }
+
+ PipelineColorBlendAttachmentState & setDstColorBlendFactor( VULKAN_HPP_NAMESPACE::BlendFactor dstColorBlendFactor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstColorBlendFactor = dstColorBlendFactor_;
+ return *this;
+ }
+
+ PipelineColorBlendAttachmentState & setColorBlendOp( VULKAN_HPP_NAMESPACE::BlendOp colorBlendOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ colorBlendOp = colorBlendOp_;
+ return *this;
+ }
+
+ PipelineColorBlendAttachmentState & setSrcAlphaBlendFactor( VULKAN_HPP_NAMESPACE::BlendFactor srcAlphaBlendFactor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcAlphaBlendFactor = srcAlphaBlendFactor_;
+ return *this;
+ }
+
+ PipelineColorBlendAttachmentState & setDstAlphaBlendFactor( VULKAN_HPP_NAMESPACE::BlendFactor dstAlphaBlendFactor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstAlphaBlendFactor = dstAlphaBlendFactor_;
+ return *this;
+ }
+
+ PipelineColorBlendAttachmentState & setAlphaBlendOp( VULKAN_HPP_NAMESPACE::BlendOp alphaBlendOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ alphaBlendOp = alphaBlendOp_;
+ return *this;
+ }
+
+ PipelineColorBlendAttachmentState & setColorWriteMask( VULKAN_HPP_NAMESPACE::ColorComponentFlags colorWriteMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ colorWriteMask = colorWriteMask_;
+ return *this;
+ }
+
+ operator VkPipelineColorBlendAttachmentState const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineColorBlendAttachmentState*>( this );
+ }
+
+ operator VkPipelineColorBlendAttachmentState &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineColorBlendAttachmentState*>( this );
+ }
+
+ bool operator==( PipelineColorBlendAttachmentState const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( blendEnable == rhs.blendEnable )
+ && ( srcColorBlendFactor == rhs.srcColorBlendFactor )
+ && ( dstColorBlendFactor == rhs.dstColorBlendFactor )
+ && ( colorBlendOp == rhs.colorBlendOp )
+ && ( srcAlphaBlendFactor == rhs.srcAlphaBlendFactor )
+ && ( dstAlphaBlendFactor == rhs.dstAlphaBlendFactor )
+ && ( alphaBlendOp == rhs.alphaBlendOp )
+ && ( colorWriteMask == rhs.colorWriteMask );
+ }
+
+ bool operator!=( PipelineColorBlendAttachmentState const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Bool32 blendEnable = {};
+ VULKAN_HPP_NAMESPACE::BlendFactor srcColorBlendFactor = VULKAN_HPP_NAMESPACE::BlendFactor::eZero;
+ VULKAN_HPP_NAMESPACE::BlendFactor dstColorBlendFactor = VULKAN_HPP_NAMESPACE::BlendFactor::eZero;
+ VULKAN_HPP_NAMESPACE::BlendOp colorBlendOp = VULKAN_HPP_NAMESPACE::BlendOp::eAdd;
+ VULKAN_HPP_NAMESPACE::BlendFactor srcAlphaBlendFactor = VULKAN_HPP_NAMESPACE::BlendFactor::eZero;
+ VULKAN_HPP_NAMESPACE::BlendFactor dstAlphaBlendFactor = VULKAN_HPP_NAMESPACE::BlendFactor::eZero;
+ VULKAN_HPP_NAMESPACE::BlendOp alphaBlendOp = VULKAN_HPP_NAMESPACE::BlendOp::eAdd;
+ VULKAN_HPP_NAMESPACE::ColorComponentFlags colorWriteMask = {};
+ };
+ static_assert( sizeof( PipelineColorBlendAttachmentState ) == sizeof( VkPipelineColorBlendAttachmentState ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineColorBlendAttachmentState>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineColorBlendStateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR_14 PipelineColorBlendStateCreateInfo( VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 logicOpEnable_ = {},
+ VULKAN_HPP_NAMESPACE::LogicOp logicOp_ = VULKAN_HPP_NAMESPACE::LogicOp::eClear,
+ uint32_t attachmentCount_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineColorBlendAttachmentState* pAttachments_ = {},
+ std::array<float,4> const& blendConstants_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , logicOpEnable( logicOpEnable_ )
+ , logicOp( logicOp_ )
+ , attachmentCount( attachmentCount_ )
+ , pAttachments( pAttachments_ )
+ , blendConstants{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,4,4>::copy( blendConstants, blendConstants_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateInfo ) - offsetof( PipelineColorBlendStateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineColorBlendStateCreateInfo( VkPipelineColorBlendStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineColorBlendStateCreateInfo& operator=( VkPipelineColorBlendStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineColorBlendStateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineColorBlendStateCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineColorBlendStateCreateInfo & setLogicOpEnable( VULKAN_HPP_NAMESPACE::Bool32 logicOpEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ logicOpEnable = logicOpEnable_;
+ return *this;
+ }
+
+ PipelineColorBlendStateCreateInfo & setLogicOp( VULKAN_HPP_NAMESPACE::LogicOp logicOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ logicOp = logicOp_;
+ return *this;
+ }
+
+ PipelineColorBlendStateCreateInfo & setAttachmentCount( uint32_t attachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ attachmentCount = attachmentCount_;
+ return *this;
+ }
+
+ PipelineColorBlendStateCreateInfo & setPAttachments( const VULKAN_HPP_NAMESPACE::PipelineColorBlendAttachmentState* pAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttachments = pAttachments_;
+ return *this;
+ }
+
+ PipelineColorBlendStateCreateInfo & setBlendConstants( std::array<float,4> blendConstants_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( blendConstants, blendConstants_.data(), 4 * sizeof( float ) );
+ return *this;
+ }
+
+ operator VkPipelineColorBlendStateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineColorBlendStateCreateInfo*>( this );
+ }
+
+ operator VkPipelineColorBlendStateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineColorBlendStateCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineColorBlendStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( logicOpEnable == rhs.logicOpEnable )
+ && ( logicOp == rhs.logicOp )
+ && ( attachmentCount == rhs.attachmentCount )
+ && ( pAttachments == rhs.pAttachments )
+ && ( memcmp( blendConstants, rhs.blendConstants, 4 * sizeof( float ) ) == 0 );
+ }
+
+ bool operator!=( PipelineColorBlendStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineColorBlendStateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::Bool32 logicOpEnable = {};
+ VULKAN_HPP_NAMESPACE::LogicOp logicOp = VULKAN_HPP_NAMESPACE::LogicOp::eClear;
+ uint32_t attachmentCount = {};
+ const VULKAN_HPP_NAMESPACE::PipelineColorBlendAttachmentState* pAttachments = {};
+ float blendConstants[4] = {};
+ };
+ static_assert( sizeof( PipelineColorBlendStateCreateInfo ) == sizeof( VkPipelineColorBlendStateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineColorBlendStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineDynamicStateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineDynamicStateCreateInfo( VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateFlags flags_ = {},
+ uint32_t dynamicStateCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DynamicState* pDynamicStates_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , dynamicStateCount( dynamicStateCount_ )
+ , pDynamicStates( pDynamicStates_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateInfo ) - offsetof( PipelineDynamicStateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineDynamicStateCreateInfo( VkPipelineDynamicStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineDynamicStateCreateInfo& operator=( VkPipelineDynamicStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineDynamicStateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineDynamicStateCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineDynamicStateCreateInfo & setDynamicStateCount( uint32_t dynamicStateCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dynamicStateCount = dynamicStateCount_;
+ return *this;
+ }
+
+ PipelineDynamicStateCreateInfo & setPDynamicStates( const VULKAN_HPP_NAMESPACE::DynamicState* pDynamicStates_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDynamicStates = pDynamicStates_;
+ return *this;
+ }
+
+ operator VkPipelineDynamicStateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineDynamicStateCreateInfo*>( this );
+ }
+
+ operator VkPipelineDynamicStateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineDynamicStateCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineDynamicStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( dynamicStateCount == rhs.dynamicStateCount )
+ && ( pDynamicStates == rhs.pDynamicStates );
+ }
+
+ bool operator!=( PipelineDynamicStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineDynamicStateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateFlags flags = {};
+ uint32_t dynamicStateCount = {};
+ const VULKAN_HPP_NAMESPACE::DynamicState* pDynamicStates = {};
+ };
+ static_assert( sizeof( PipelineDynamicStateCreateInfo ) == sizeof( VkPipelineDynamicStateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineDynamicStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct GraphicsPipelineCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR GraphicsPipelineCreateInfo( VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags_ = {},
+ uint32_t stageCount_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateInfo* pVertexInputState_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateInfo* pInputAssemblyState_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateInfo* pTessellationState_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineViewportStateCreateInfo* pViewportState_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateInfo* pRasterizationState_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateInfo* pMultisampleState_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateInfo* pDepthStencilState_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateInfo* pColorBlendState_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateInfo* pDynamicState_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineLayout layout_ = {},
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass_ = {},
+ uint32_t subpass_ = {},
+ VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle_ = {},
+ int32_t basePipelineIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , stageCount( stageCount_ )
+ , pStages( pStages_ )
+ , pVertexInputState( pVertexInputState_ )
+ , pInputAssemblyState( pInputAssemblyState_ )
+ , pTessellationState( pTessellationState_ )
+ , pViewportState( pViewportState_ )
+ , pRasterizationState( pRasterizationState_ )
+ , pMultisampleState( pMultisampleState_ )
+ , pDepthStencilState( pDepthStencilState_ )
+ , pColorBlendState( pColorBlendState_ )
+ , pDynamicState( pDynamicState_ )
+ , layout( layout_ )
+ , renderPass( renderPass_ )
+ , subpass( subpass_ )
+ , basePipelineHandle( basePipelineHandle_ )
+ , basePipelineIndex( basePipelineIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo & operator=( VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo ) - offsetof( GraphicsPipelineCreateInfo, pNext ) );
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo( VkGraphicsPipelineCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ GraphicsPipelineCreateInfo& operator=( VkGraphicsPipelineCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setStageCount( uint32_t stageCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stageCount = stageCount_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPStages( const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pStages = pStages_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPVertexInputState( const VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateInfo* pVertexInputState_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pVertexInputState = pVertexInputState_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPInputAssemblyState( const VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateInfo* pInputAssemblyState_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pInputAssemblyState = pInputAssemblyState_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPTessellationState( const VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateInfo* pTessellationState_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pTessellationState = pTessellationState_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPViewportState( const VULKAN_HPP_NAMESPACE::PipelineViewportStateCreateInfo* pViewportState_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pViewportState = pViewportState_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPRasterizationState( const VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateInfo* pRasterizationState_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pRasterizationState = pRasterizationState_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPMultisampleState( const VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateInfo* pMultisampleState_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pMultisampleState = pMultisampleState_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPDepthStencilState( const VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateInfo* pDepthStencilState_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDepthStencilState = pDepthStencilState_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPColorBlendState( const VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateInfo* pColorBlendState_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pColorBlendState = pColorBlendState_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setPDynamicState( const VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateInfo* pDynamicState_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDynamicState = pDynamicState_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setLayout( VULKAN_HPP_NAMESPACE::PipelineLayout layout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layout = layout_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setRenderPass( VULKAN_HPP_NAMESPACE::RenderPass renderPass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ renderPass = renderPass_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setSubpass( uint32_t subpass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subpass = subpass_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setBasePipelineHandle( VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle_ ) VULKAN_HPP_NOEXCEPT
+ {
+ basePipelineHandle = basePipelineHandle_;
+ return *this;
+ }
+
+ GraphicsPipelineCreateInfo & setBasePipelineIndex( int32_t basePipelineIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ basePipelineIndex = basePipelineIndex_;
+ return *this;
+ }
+
+ operator VkGraphicsPipelineCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( this );
+ }
+
+ operator VkGraphicsPipelineCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkGraphicsPipelineCreateInfo*>( this );
+ }
+
+ bool operator==( GraphicsPipelineCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( stageCount == rhs.stageCount )
+ && ( pStages == rhs.pStages )
+ && ( pVertexInputState == rhs.pVertexInputState )
+ && ( pInputAssemblyState == rhs.pInputAssemblyState )
+ && ( pTessellationState == rhs.pTessellationState )
+ && ( pViewportState == rhs.pViewportState )
+ && ( pRasterizationState == rhs.pRasterizationState )
+ && ( pMultisampleState == rhs.pMultisampleState )
+ && ( pDepthStencilState == rhs.pDepthStencilState )
+ && ( pColorBlendState == rhs.pColorBlendState )
+ && ( pDynamicState == rhs.pDynamicState )
+ && ( layout == rhs.layout )
+ && ( renderPass == rhs.renderPass )
+ && ( subpass == rhs.subpass )
+ && ( basePipelineHandle == rhs.basePipelineHandle )
+ && ( basePipelineIndex == rhs.basePipelineIndex );
+ }
+
+ bool operator!=( GraphicsPipelineCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eGraphicsPipelineCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags = {};
+ uint32_t stageCount = {};
+ const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages = {};
+ const VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateInfo* pVertexInputState = {};
+ const VULKAN_HPP_NAMESPACE::PipelineInputAssemblyStateCreateInfo* pInputAssemblyState = {};
+ const VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateInfo* pTessellationState = {};
+ const VULKAN_HPP_NAMESPACE::PipelineViewportStateCreateInfo* pViewportState = {};
+ const VULKAN_HPP_NAMESPACE::PipelineRasterizationStateCreateInfo* pRasterizationState = {};
+ const VULKAN_HPP_NAMESPACE::PipelineMultisampleStateCreateInfo* pMultisampleState = {};
+ const VULKAN_HPP_NAMESPACE::PipelineDepthStencilStateCreateInfo* pDepthStencilState = {};
+ const VULKAN_HPP_NAMESPACE::PipelineColorBlendStateCreateInfo* pColorBlendState = {};
+ const VULKAN_HPP_NAMESPACE::PipelineDynamicStateCreateInfo* pDynamicState = {};
+ VULKAN_HPP_NAMESPACE::PipelineLayout layout = {};
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass = {};
+ uint32_t subpass = {};
+ VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle = {};
+ int32_t basePipelineIndex = {};
+ };
+ static_assert( sizeof( GraphicsPipelineCreateInfo ) == sizeof( VkGraphicsPipelineCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<GraphicsPipelineCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct XYColorEXT
+ {
+ VULKAN_HPP_CONSTEXPR XYColorEXT( float x_ = {},
+ float y_ = {} ) VULKAN_HPP_NOEXCEPT
+ : x( x_ )
+ , y( y_ )
+ {}
+
+ XYColorEXT( VkXYColorEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ XYColorEXT& operator=( VkXYColorEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::XYColorEXT const *>(&rhs);
+ return *this;
+ }
+
+ XYColorEXT & setX( float x_ ) VULKAN_HPP_NOEXCEPT
+ {
+ x = x_;
+ return *this;
+ }
+
+ XYColorEXT & setY( float y_ ) VULKAN_HPP_NOEXCEPT
+ {
+ y = y_;
+ return *this;
+ }
+
+ operator VkXYColorEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkXYColorEXT*>( this );
+ }
+
+ operator VkXYColorEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkXYColorEXT*>( this );
+ }
+
+ bool operator==( XYColorEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( x == rhs.x )
+ && ( y == rhs.y );
+ }
+
+ bool operator!=( XYColorEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ float x = {};
+ float y = {};
+ };
+ static_assert( sizeof( XYColorEXT ) == sizeof( VkXYColorEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<XYColorEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct HdrMetadataEXT
+ {
+ VULKAN_HPP_CONSTEXPR HdrMetadataEXT( VULKAN_HPP_NAMESPACE::XYColorEXT displayPrimaryRed_ = {},
+ VULKAN_HPP_NAMESPACE::XYColorEXT displayPrimaryGreen_ = {},
+ VULKAN_HPP_NAMESPACE::XYColorEXT displayPrimaryBlue_ = {},
+ VULKAN_HPP_NAMESPACE::XYColorEXT whitePoint_ = {},
+ float maxLuminance_ = {},
+ float minLuminance_ = {},
+ float maxContentLightLevel_ = {},
+ float maxFrameAverageLightLevel_ = {} ) VULKAN_HPP_NOEXCEPT
+ : displayPrimaryRed( displayPrimaryRed_ )
+ , displayPrimaryGreen( displayPrimaryGreen_ )
+ , displayPrimaryBlue( displayPrimaryBlue_ )
+ , whitePoint( whitePoint_ )
+ , maxLuminance( maxLuminance_ )
+ , minLuminance( minLuminance_ )
+ , maxContentLightLevel( maxContentLightLevel_ )
+ , maxFrameAverageLightLevel( maxFrameAverageLightLevel_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::HdrMetadataEXT & operator=( VULKAN_HPP_NAMESPACE::HdrMetadataEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::HdrMetadataEXT ) - offsetof( HdrMetadataEXT, pNext ) );
+ return *this;
+ }
+
+ HdrMetadataEXT( VkHdrMetadataEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ HdrMetadataEXT& operator=( VkHdrMetadataEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::HdrMetadataEXT const *>(&rhs);
+ return *this;
+ }
+
+ HdrMetadataEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ HdrMetadataEXT & setDisplayPrimaryRed( VULKAN_HPP_NAMESPACE::XYColorEXT displayPrimaryRed_ ) VULKAN_HPP_NOEXCEPT
+ {
+ displayPrimaryRed = displayPrimaryRed_;
+ return *this;
+ }
+
+ HdrMetadataEXT & setDisplayPrimaryGreen( VULKAN_HPP_NAMESPACE::XYColorEXT displayPrimaryGreen_ ) VULKAN_HPP_NOEXCEPT
+ {
+ displayPrimaryGreen = displayPrimaryGreen_;
+ return *this;
+ }
+
+ HdrMetadataEXT & setDisplayPrimaryBlue( VULKAN_HPP_NAMESPACE::XYColorEXT displayPrimaryBlue_ ) VULKAN_HPP_NOEXCEPT
+ {
+ displayPrimaryBlue = displayPrimaryBlue_;
+ return *this;
+ }
+
+ HdrMetadataEXT & setWhitePoint( VULKAN_HPP_NAMESPACE::XYColorEXT whitePoint_ ) VULKAN_HPP_NOEXCEPT
+ {
+ whitePoint = whitePoint_;
+ return *this;
+ }
+
+ HdrMetadataEXT & setMaxLuminance( float maxLuminance_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxLuminance = maxLuminance_;
+ return *this;
+ }
+
+ HdrMetadataEXT & setMinLuminance( float minLuminance_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minLuminance = minLuminance_;
+ return *this;
+ }
+
+ HdrMetadataEXT & setMaxContentLightLevel( float maxContentLightLevel_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxContentLightLevel = maxContentLightLevel_;
+ return *this;
+ }
+
+ HdrMetadataEXT & setMaxFrameAverageLightLevel( float maxFrameAverageLightLevel_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxFrameAverageLightLevel = maxFrameAverageLightLevel_;
+ return *this;
+ }
+
+ operator VkHdrMetadataEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkHdrMetadataEXT*>( this );
+ }
+
+ operator VkHdrMetadataEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkHdrMetadataEXT*>( this );
+ }
+
+ bool operator==( HdrMetadataEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( displayPrimaryRed == rhs.displayPrimaryRed )
+ && ( displayPrimaryGreen == rhs.displayPrimaryGreen )
+ && ( displayPrimaryBlue == rhs.displayPrimaryBlue )
+ && ( whitePoint == rhs.whitePoint )
+ && ( maxLuminance == rhs.maxLuminance )
+ && ( minLuminance == rhs.minLuminance )
+ && ( maxContentLightLevel == rhs.maxContentLightLevel )
+ && ( maxFrameAverageLightLevel == rhs.maxFrameAverageLightLevel );
+ }
+
+ bool operator!=( HdrMetadataEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eHdrMetadataEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::XYColorEXT displayPrimaryRed = {};
+ VULKAN_HPP_NAMESPACE::XYColorEXT displayPrimaryGreen = {};
+ VULKAN_HPP_NAMESPACE::XYColorEXT displayPrimaryBlue = {};
+ VULKAN_HPP_NAMESPACE::XYColorEXT whitePoint = {};
+ float maxLuminance = {};
+ float minLuminance = {};
+ float maxContentLightLevel = {};
+ float maxFrameAverageLightLevel = {};
+ };
+ static_assert( sizeof( HdrMetadataEXT ) == sizeof( VkHdrMetadataEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<HdrMetadataEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct HeadlessSurfaceCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR HeadlessSurfaceCreateInfoEXT( VULKAN_HPP_NAMESPACE::HeadlessSurfaceCreateFlagsEXT flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::HeadlessSurfaceCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::HeadlessSurfaceCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::HeadlessSurfaceCreateInfoEXT ) - offsetof( HeadlessSurfaceCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ HeadlessSurfaceCreateInfoEXT( VkHeadlessSurfaceCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ HeadlessSurfaceCreateInfoEXT& operator=( VkHeadlessSurfaceCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::HeadlessSurfaceCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ HeadlessSurfaceCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ HeadlessSurfaceCreateInfoEXT & setFlags( VULKAN_HPP_NAMESPACE::HeadlessSurfaceCreateFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ operator VkHeadlessSurfaceCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkHeadlessSurfaceCreateInfoEXT*>( this );
+ }
+
+ operator VkHeadlessSurfaceCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkHeadlessSurfaceCreateInfoEXT*>( this );
+ }
+
+ bool operator==( HeadlessSurfaceCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( HeadlessSurfaceCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eHeadlessSurfaceCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::HeadlessSurfaceCreateFlagsEXT flags = {};
+ };
+ static_assert( sizeof( HeadlessSurfaceCreateInfoEXT ) == sizeof( VkHeadlessSurfaceCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<HeadlessSurfaceCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+
+ struct IOSSurfaceCreateInfoMVK
+ {
+ VULKAN_HPP_CONSTEXPR IOSSurfaceCreateInfoMVK( VULKAN_HPP_NAMESPACE::IOSSurfaceCreateFlagsMVK flags_ = {},
+ const void* pView_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , pView( pView_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::IOSSurfaceCreateInfoMVK & operator=( VULKAN_HPP_NAMESPACE::IOSSurfaceCreateInfoMVK const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::IOSSurfaceCreateInfoMVK ) - offsetof( IOSSurfaceCreateInfoMVK, pNext ) );
+ return *this;
+ }
+
+ IOSSurfaceCreateInfoMVK( VkIOSSurfaceCreateInfoMVK const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ IOSSurfaceCreateInfoMVK& operator=( VkIOSSurfaceCreateInfoMVK const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::IOSSurfaceCreateInfoMVK const *>(&rhs);
+ return *this;
+ }
+
+ IOSSurfaceCreateInfoMVK & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ IOSSurfaceCreateInfoMVK & setFlags( VULKAN_HPP_NAMESPACE::IOSSurfaceCreateFlagsMVK flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ IOSSurfaceCreateInfoMVK & setPView( const void* pView_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pView = pView_;
+ return *this;
+ }
+
+ operator VkIOSSurfaceCreateInfoMVK const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkIOSSurfaceCreateInfoMVK*>( this );
+ }
+
+ operator VkIOSSurfaceCreateInfoMVK &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkIOSSurfaceCreateInfoMVK*>( this );
+ }
+
+ bool operator==( IOSSurfaceCreateInfoMVK const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( pView == rhs.pView );
+ }
+
+ bool operator!=( IOSSurfaceCreateInfoMVK const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eIosSurfaceCreateInfoMVK;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::IOSSurfaceCreateFlagsMVK flags = {};
+ const void* pView = {};
+ };
+ static_assert( sizeof( IOSSurfaceCreateInfoMVK ) == sizeof( VkIOSSurfaceCreateInfoMVK ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<IOSSurfaceCreateInfoMVK>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_IOS_MVK*/
+
+ struct ImageBlit
+ {
+ VULKAN_HPP_CONSTEXPR_14 ImageBlit( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers srcSubresource_ = {},
+ std::array<VULKAN_HPP_NAMESPACE::Offset3D,2> const& srcOffsets_ = {},
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource_ = {},
+ std::array<VULKAN_HPP_NAMESPACE::Offset3D,2> const& dstOffsets_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcSubresource( srcSubresource_ )
+ , srcOffsets{}
+ , dstSubresource( dstSubresource_ )
+ , dstOffsets{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::Offset3D,2,2>::copy( srcOffsets, srcOffsets_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::Offset3D,2,2>::copy( dstOffsets, dstOffsets_ );
+ }
+
+ ImageBlit( VkImageBlit const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageBlit& operator=( VkImageBlit const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageBlit const *>(&rhs);
+ return *this;
+ }
+
+ ImageBlit & setSrcSubresource( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers srcSubresource_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcSubresource = srcSubresource_;
+ return *this;
+ }
+
+ ImageBlit & setSrcOffsets( std::array<VULKAN_HPP_NAMESPACE::Offset3D,2> srcOffsets_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( srcOffsets, srcOffsets_.data(), 2 * sizeof( VULKAN_HPP_NAMESPACE::Offset3D ) );
+ return *this;
+ }
+
+ ImageBlit & setDstSubresource( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstSubresource = dstSubresource_;
+ return *this;
+ }
+
+ ImageBlit & setDstOffsets( std::array<VULKAN_HPP_NAMESPACE::Offset3D,2> dstOffsets_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( dstOffsets, dstOffsets_.data(), 2 * sizeof( VULKAN_HPP_NAMESPACE::Offset3D ) );
+ return *this;
+ }
+
+ operator VkImageBlit const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageBlit*>( this );
+ }
+
+ operator VkImageBlit &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageBlit*>( this );
+ }
+
+ bool operator==( ImageBlit const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( srcSubresource == rhs.srcSubresource )
+ && ( memcmp( srcOffsets, rhs.srcOffsets, 2 * sizeof( VULKAN_HPP_NAMESPACE::Offset3D ) ) == 0 )
+ && ( dstSubresource == rhs.dstSubresource )
+ && ( memcmp( dstOffsets, rhs.dstOffsets, 2 * sizeof( VULKAN_HPP_NAMESPACE::Offset3D ) ) == 0 );
+ }
+
+ bool operator!=( ImageBlit const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers srcSubresource = {};
+ VULKAN_HPP_NAMESPACE::Offset3D srcOffsets[2] = {};
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource = {};
+ VULKAN_HPP_NAMESPACE::Offset3D dstOffsets[2] = {};
+ };
+ static_assert( sizeof( ImageBlit ) == sizeof( VkImageBlit ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageBlit>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageCopy
+ {
+ VULKAN_HPP_CONSTEXPR ImageCopy( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers srcSubresource_ = {},
+ VULKAN_HPP_NAMESPACE::Offset3D srcOffset_ = {},
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource_ = {},
+ VULKAN_HPP_NAMESPACE::Offset3D dstOffset_ = {},
+ VULKAN_HPP_NAMESPACE::Extent3D extent_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcSubresource( srcSubresource_ )
+ , srcOffset( srcOffset_ )
+ , dstSubresource( dstSubresource_ )
+ , dstOffset( dstOffset_ )
+ , extent( extent_ )
+ {}
+
+ ImageCopy( VkImageCopy const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageCopy& operator=( VkImageCopy const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageCopy const *>(&rhs);
+ return *this;
+ }
+
+ ImageCopy & setSrcSubresource( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers srcSubresource_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcSubresource = srcSubresource_;
+ return *this;
+ }
+
+ ImageCopy & setSrcOffset( VULKAN_HPP_NAMESPACE::Offset3D srcOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcOffset = srcOffset_;
+ return *this;
+ }
+
+ ImageCopy & setDstSubresource( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstSubresource = dstSubresource_;
+ return *this;
+ }
+
+ ImageCopy & setDstOffset( VULKAN_HPP_NAMESPACE::Offset3D dstOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstOffset = dstOffset_;
+ return *this;
+ }
+
+ ImageCopy & setExtent( VULKAN_HPP_NAMESPACE::Extent3D extent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ extent = extent_;
+ return *this;
+ }
+
+ operator VkImageCopy const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageCopy*>( this );
+ }
+
+ operator VkImageCopy &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageCopy*>( this );
+ }
+
+ bool operator==( ImageCopy const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( srcSubresource == rhs.srcSubresource )
+ && ( srcOffset == rhs.srcOffset )
+ && ( dstSubresource == rhs.dstSubresource )
+ && ( dstOffset == rhs.dstOffset )
+ && ( extent == rhs.extent );
+ }
+
+ bool operator!=( ImageCopy const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers srcSubresource = {};
+ VULKAN_HPP_NAMESPACE::Offset3D srcOffset = {};
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource = {};
+ VULKAN_HPP_NAMESPACE::Offset3D dstOffset = {};
+ VULKAN_HPP_NAMESPACE::Extent3D extent = {};
+ };
+ static_assert( sizeof( ImageCopy ) == sizeof( VkImageCopy ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageCopy>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ImageCreateInfo( VULKAN_HPP_NAMESPACE::ImageCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::ImageType imageType_ = VULKAN_HPP_NAMESPACE::ImageType::e1D,
+ VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::Extent3D extent_ = {},
+ uint32_t mipLevels_ = {},
+ uint32_t arrayLayers_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples_ = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1,
+ VULKAN_HPP_NAMESPACE::ImageTiling tiling_ = VULKAN_HPP_NAMESPACE::ImageTiling::eOptimal,
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags usage_ = {},
+ VULKAN_HPP_NAMESPACE::SharingMode sharingMode_ = VULKAN_HPP_NAMESPACE::SharingMode::eExclusive,
+ uint32_t queueFamilyIndexCount_ = {},
+ const uint32_t* pQueueFamilyIndices_ = {},
+ VULKAN_HPP_NAMESPACE::ImageLayout initialLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , imageType( imageType_ )
+ , format( format_ )
+ , extent( extent_ )
+ , mipLevels( mipLevels_ )
+ , arrayLayers( arrayLayers_ )
+ , samples( samples_ )
+ , tiling( tiling_ )
+ , usage( usage_ )
+ , sharingMode( sharingMode_ )
+ , queueFamilyIndexCount( queueFamilyIndexCount_ )
+ , pQueueFamilyIndices( pQueueFamilyIndices_ )
+ , initialLayout( initialLayout_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ImageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageCreateInfo ) - offsetof( ImageCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ImageCreateInfo( VkImageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageCreateInfo& operator=( VkImageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ImageCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::ImageCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ImageCreateInfo & setImageType( VULKAN_HPP_NAMESPACE::ImageType imageType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageType = imageType_;
+ return *this;
+ }
+
+ ImageCreateInfo & setFormat( VULKAN_HPP_NAMESPACE::Format format_ ) VULKAN_HPP_NOEXCEPT
+ {
+ format = format_;
+ return *this;
+ }
+
+ ImageCreateInfo & setExtent( VULKAN_HPP_NAMESPACE::Extent3D extent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ extent = extent_;
+ return *this;
+ }
+
+ ImageCreateInfo & setMipLevels( uint32_t mipLevels_ ) VULKAN_HPP_NOEXCEPT
+ {
+ mipLevels = mipLevels_;
+ return *this;
+ }
+
+ ImageCreateInfo & setArrayLayers( uint32_t arrayLayers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ arrayLayers = arrayLayers_;
+ return *this;
+ }
+
+ ImageCreateInfo & setSamples( VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples_ ) VULKAN_HPP_NOEXCEPT
+ {
+ samples = samples_;
+ return *this;
+ }
+
+ ImageCreateInfo & setTiling( VULKAN_HPP_NAMESPACE::ImageTiling tiling_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tiling = tiling_;
+ return *this;
+ }
+
+ ImageCreateInfo & setUsage( VULKAN_HPP_NAMESPACE::ImageUsageFlags usage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ usage = usage_;
+ return *this;
+ }
+
+ ImageCreateInfo & setSharingMode( VULKAN_HPP_NAMESPACE::SharingMode sharingMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sharingMode = sharingMode_;
+ return *this;
+ }
+
+ ImageCreateInfo & setQueueFamilyIndexCount( uint32_t queueFamilyIndexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueFamilyIndexCount = queueFamilyIndexCount_;
+ return *this;
+ }
+
+ ImageCreateInfo & setPQueueFamilyIndices( const uint32_t* pQueueFamilyIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pQueueFamilyIndices = pQueueFamilyIndices_;
+ return *this;
+ }
+
+ ImageCreateInfo & setInitialLayout( VULKAN_HPP_NAMESPACE::ImageLayout initialLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ initialLayout = initialLayout_;
+ return *this;
+ }
+
+ operator VkImageCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageCreateInfo*>( this );
+ }
+
+ operator VkImageCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageCreateInfo*>( this );
+ }
+
+ bool operator==( ImageCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( imageType == rhs.imageType )
+ && ( format == rhs.format )
+ && ( extent == rhs.extent )
+ && ( mipLevels == rhs.mipLevels )
+ && ( arrayLayers == rhs.arrayLayers )
+ && ( samples == rhs.samples )
+ && ( tiling == rhs.tiling )
+ && ( usage == rhs.usage )
+ && ( sharingMode == rhs.sharingMode )
+ && ( queueFamilyIndexCount == rhs.queueFamilyIndexCount )
+ && ( pQueueFamilyIndices == rhs.pQueueFamilyIndices )
+ && ( initialLayout == rhs.initialLayout );
+ }
+
+ bool operator!=( ImageCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::ImageType imageType = VULKAN_HPP_NAMESPACE::ImageType::e1D;
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::Extent3D extent = {};
+ uint32_t mipLevels = {};
+ uint32_t arrayLayers = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1;
+ VULKAN_HPP_NAMESPACE::ImageTiling tiling = VULKAN_HPP_NAMESPACE::ImageTiling::eOptimal;
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags usage = {};
+ VULKAN_HPP_NAMESPACE::SharingMode sharingMode = VULKAN_HPP_NAMESPACE::SharingMode::eExclusive;
+ uint32_t queueFamilyIndexCount = {};
+ const uint32_t* pQueueFamilyIndices = {};
+ VULKAN_HPP_NAMESPACE::ImageLayout initialLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ };
+ static_assert( sizeof( ImageCreateInfo ) == sizeof( VkImageCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SubresourceLayout
+ {
+ SubresourceLayout( VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize size_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize rowPitch_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize arrayPitch_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize depthPitch_ = {} ) VULKAN_HPP_NOEXCEPT
+ : offset( offset_ )
+ , size( size_ )
+ , rowPitch( rowPitch_ )
+ , arrayPitch( arrayPitch_ )
+ , depthPitch( depthPitch_ )
+ {}
+
+ SubresourceLayout( VkSubresourceLayout const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SubresourceLayout& operator=( VkSubresourceLayout const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SubresourceLayout const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSubresourceLayout const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSubresourceLayout*>( this );
+ }
+
+ operator VkSubresourceLayout &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSubresourceLayout*>( this );
+ }
+
+ bool operator==( SubresourceLayout const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( offset == rhs.offset )
+ && ( size == rhs.size )
+ && ( rowPitch == rhs.rowPitch )
+ && ( arrayPitch == rhs.arrayPitch )
+ && ( depthPitch == rhs.depthPitch );
+ }
+
+ bool operator!=( SubresourceLayout const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize size = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize rowPitch = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize arrayPitch = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize depthPitch = {};
+ };
+ static_assert( sizeof( SubresourceLayout ) == sizeof( VkSubresourceLayout ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SubresourceLayout>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageDrmFormatModifierExplicitCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR ImageDrmFormatModifierExplicitCreateInfoEXT( uint64_t drmFormatModifier_ = {},
+ uint32_t drmFormatModifierPlaneCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SubresourceLayout* pPlaneLayouts_ = {} ) VULKAN_HPP_NOEXCEPT
+ : drmFormatModifier( drmFormatModifier_ )
+ , drmFormatModifierPlaneCount( drmFormatModifierPlaneCount_ )
+ , pPlaneLayouts( pPlaneLayouts_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierExplicitCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierExplicitCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierExplicitCreateInfoEXT ) - offsetof( ImageDrmFormatModifierExplicitCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ ImageDrmFormatModifierExplicitCreateInfoEXT( VkImageDrmFormatModifierExplicitCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageDrmFormatModifierExplicitCreateInfoEXT& operator=( VkImageDrmFormatModifierExplicitCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierExplicitCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ ImageDrmFormatModifierExplicitCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageDrmFormatModifierExplicitCreateInfoEXT & setDrmFormatModifier( uint64_t drmFormatModifier_ ) VULKAN_HPP_NOEXCEPT
+ {
+ drmFormatModifier = drmFormatModifier_;
+ return *this;
+ }
+
+ ImageDrmFormatModifierExplicitCreateInfoEXT & setDrmFormatModifierPlaneCount( uint32_t drmFormatModifierPlaneCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ drmFormatModifierPlaneCount = drmFormatModifierPlaneCount_;
+ return *this;
+ }
+
+ ImageDrmFormatModifierExplicitCreateInfoEXT & setPPlaneLayouts( const VULKAN_HPP_NAMESPACE::SubresourceLayout* pPlaneLayouts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pPlaneLayouts = pPlaneLayouts_;
+ return *this;
+ }
+
+ operator VkImageDrmFormatModifierExplicitCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageDrmFormatModifierExplicitCreateInfoEXT*>( this );
+ }
+
+ operator VkImageDrmFormatModifierExplicitCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageDrmFormatModifierExplicitCreateInfoEXT*>( this );
+ }
+
+ bool operator==( ImageDrmFormatModifierExplicitCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( drmFormatModifier == rhs.drmFormatModifier )
+ && ( drmFormatModifierPlaneCount == rhs.drmFormatModifierPlaneCount )
+ && ( pPlaneLayouts == rhs.pPlaneLayouts );
+ }
+
+ bool operator!=( ImageDrmFormatModifierExplicitCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageDrmFormatModifierExplicitCreateInfoEXT;
+ const void* pNext = {};
+ uint64_t drmFormatModifier = {};
+ uint32_t drmFormatModifierPlaneCount = {};
+ const VULKAN_HPP_NAMESPACE::SubresourceLayout* pPlaneLayouts = {};
+ };
+ static_assert( sizeof( ImageDrmFormatModifierExplicitCreateInfoEXT ) == sizeof( VkImageDrmFormatModifierExplicitCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageDrmFormatModifierExplicitCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageDrmFormatModifierListCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR ImageDrmFormatModifierListCreateInfoEXT( uint32_t drmFormatModifierCount_ = {},
+ const uint64_t* pDrmFormatModifiers_ = {} ) VULKAN_HPP_NOEXCEPT
+ : drmFormatModifierCount( drmFormatModifierCount_ )
+ , pDrmFormatModifiers( pDrmFormatModifiers_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierListCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierListCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierListCreateInfoEXT ) - offsetof( ImageDrmFormatModifierListCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ ImageDrmFormatModifierListCreateInfoEXT( VkImageDrmFormatModifierListCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageDrmFormatModifierListCreateInfoEXT& operator=( VkImageDrmFormatModifierListCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierListCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ ImageDrmFormatModifierListCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageDrmFormatModifierListCreateInfoEXT & setDrmFormatModifierCount( uint32_t drmFormatModifierCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ drmFormatModifierCount = drmFormatModifierCount_;
+ return *this;
+ }
+
+ ImageDrmFormatModifierListCreateInfoEXT & setPDrmFormatModifiers( const uint64_t* pDrmFormatModifiers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDrmFormatModifiers = pDrmFormatModifiers_;
+ return *this;
+ }
+
+ operator VkImageDrmFormatModifierListCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageDrmFormatModifierListCreateInfoEXT*>( this );
+ }
+
+ operator VkImageDrmFormatModifierListCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageDrmFormatModifierListCreateInfoEXT*>( this );
+ }
+
+ bool operator==( ImageDrmFormatModifierListCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( drmFormatModifierCount == rhs.drmFormatModifierCount )
+ && ( pDrmFormatModifiers == rhs.pDrmFormatModifiers );
+ }
+
+ bool operator!=( ImageDrmFormatModifierListCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageDrmFormatModifierListCreateInfoEXT;
+ const void* pNext = {};
+ uint32_t drmFormatModifierCount = {};
+ const uint64_t* pDrmFormatModifiers = {};
+ };
+ static_assert( sizeof( ImageDrmFormatModifierListCreateInfoEXT ) == sizeof( VkImageDrmFormatModifierListCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageDrmFormatModifierListCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageDrmFormatModifierPropertiesEXT
+ {
+ ImageDrmFormatModifierPropertiesEXT( uint64_t drmFormatModifier_ = {} ) VULKAN_HPP_NOEXCEPT
+ : drmFormatModifier( drmFormatModifier_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT ) - offsetof( ImageDrmFormatModifierPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ ImageDrmFormatModifierPropertiesEXT( VkImageDrmFormatModifierPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageDrmFormatModifierPropertiesEXT& operator=( VkImageDrmFormatModifierPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkImageDrmFormatModifierPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageDrmFormatModifierPropertiesEXT*>( this );
+ }
+
+ operator VkImageDrmFormatModifierPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageDrmFormatModifierPropertiesEXT*>( this );
+ }
+
+ bool operator==( ImageDrmFormatModifierPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( drmFormatModifier == rhs.drmFormatModifier );
+ }
+
+ bool operator!=( ImageDrmFormatModifierPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageDrmFormatModifierPropertiesEXT;
+ void* pNext = {};
+ uint64_t drmFormatModifier = {};
+ };
+ static_assert( sizeof( ImageDrmFormatModifierPropertiesEXT ) == sizeof( VkImageDrmFormatModifierPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageDrmFormatModifierPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageFormatListCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ImageFormatListCreateInfo( uint32_t viewFormatCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Format* pViewFormats_ = {} ) VULKAN_HPP_NOEXCEPT
+ : viewFormatCount( viewFormatCount_ )
+ , pViewFormats( pViewFormats_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageFormatListCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ImageFormatListCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageFormatListCreateInfo ) - offsetof( ImageFormatListCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ImageFormatListCreateInfo( VkImageFormatListCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageFormatListCreateInfo& operator=( VkImageFormatListCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageFormatListCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ImageFormatListCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageFormatListCreateInfo & setViewFormatCount( uint32_t viewFormatCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ viewFormatCount = viewFormatCount_;
+ return *this;
+ }
+
+ ImageFormatListCreateInfo & setPViewFormats( const VULKAN_HPP_NAMESPACE::Format* pViewFormats_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pViewFormats = pViewFormats_;
+ return *this;
+ }
+
+ operator VkImageFormatListCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageFormatListCreateInfo*>( this );
+ }
+
+ operator VkImageFormatListCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageFormatListCreateInfo*>( this );
+ }
+
+ bool operator==( ImageFormatListCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( viewFormatCount == rhs.viewFormatCount )
+ && ( pViewFormats == rhs.pViewFormats );
+ }
+
+ bool operator!=( ImageFormatListCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageFormatListCreateInfo;
+ const void* pNext = {};
+ uint32_t viewFormatCount = {};
+ const VULKAN_HPP_NAMESPACE::Format* pViewFormats = {};
+ };
+ static_assert( sizeof( ImageFormatListCreateInfo ) == sizeof( VkImageFormatListCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageFormatListCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageFormatProperties2
+ {
+ ImageFormatProperties2( VULKAN_HPP_NAMESPACE::ImageFormatProperties imageFormatProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : imageFormatProperties( imageFormatProperties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageFormatProperties2 & operator=( VULKAN_HPP_NAMESPACE::ImageFormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageFormatProperties2 ) - offsetof( ImageFormatProperties2, pNext ) );
+ return *this;
+ }
+
+ ImageFormatProperties2( VkImageFormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageFormatProperties2& operator=( VkImageFormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageFormatProperties2 const *>(&rhs);
+ return *this;
+ }
+
+ operator VkImageFormatProperties2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageFormatProperties2*>( this );
+ }
+
+ operator VkImageFormatProperties2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageFormatProperties2*>( this );
+ }
+
+ bool operator==( ImageFormatProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( imageFormatProperties == rhs.imageFormatProperties );
+ }
+
+ bool operator!=( ImageFormatProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageFormatProperties2;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageFormatProperties imageFormatProperties = {};
+ };
+ static_assert( sizeof( ImageFormatProperties2 ) == sizeof( VkImageFormatProperties2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageFormatProperties2>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageSubresourceRange
+ {
+ VULKAN_HPP_CONSTEXPR ImageSubresourceRange( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ = {},
+ uint32_t baseMipLevel_ = {},
+ uint32_t levelCount_ = {},
+ uint32_t baseArrayLayer_ = {},
+ uint32_t layerCount_ = {} ) VULKAN_HPP_NOEXCEPT
+ : aspectMask( aspectMask_ )
+ , baseMipLevel( baseMipLevel_ )
+ , levelCount( levelCount_ )
+ , baseArrayLayer( baseArrayLayer_ )
+ , layerCount( layerCount_ )
+ {}
+
+ ImageSubresourceRange( VkImageSubresourceRange const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageSubresourceRange& operator=( VkImageSubresourceRange const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageSubresourceRange const *>(&rhs);
+ return *this;
+ }
+
+ ImageSubresourceRange & setAspectMask( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ aspectMask = aspectMask_;
+ return *this;
+ }
+
+ ImageSubresourceRange & setBaseMipLevel( uint32_t baseMipLevel_ ) VULKAN_HPP_NOEXCEPT
+ {
+ baseMipLevel = baseMipLevel_;
+ return *this;
+ }
+
+ ImageSubresourceRange & setLevelCount( uint32_t levelCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ levelCount = levelCount_;
+ return *this;
+ }
+
+ ImageSubresourceRange & setBaseArrayLayer( uint32_t baseArrayLayer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ baseArrayLayer = baseArrayLayer_;
+ return *this;
+ }
+
+ ImageSubresourceRange & setLayerCount( uint32_t layerCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layerCount = layerCount_;
+ return *this;
+ }
+
+ operator VkImageSubresourceRange const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageSubresourceRange*>( this );
+ }
+
+ operator VkImageSubresourceRange &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageSubresourceRange*>( this );
+ }
+
+ bool operator==( ImageSubresourceRange const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( aspectMask == rhs.aspectMask )
+ && ( baseMipLevel == rhs.baseMipLevel )
+ && ( levelCount == rhs.levelCount )
+ && ( baseArrayLayer == rhs.baseArrayLayer )
+ && ( layerCount == rhs.layerCount );
+ }
+
+ bool operator!=( ImageSubresourceRange const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask = {};
+ uint32_t baseMipLevel = {};
+ uint32_t levelCount = {};
+ uint32_t baseArrayLayer = {};
+ uint32_t layerCount = {};
+ };
+ static_assert( sizeof( ImageSubresourceRange ) == sizeof( VkImageSubresourceRange ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageSubresourceRange>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageMemoryBarrier
+ {
+ VULKAN_HPP_CONSTEXPR ImageMemoryBarrier( VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask_ = {},
+ VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask_ = {},
+ VULKAN_HPP_NAMESPACE::ImageLayout oldLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined,
+ VULKAN_HPP_NAMESPACE::ImageLayout newLayout_ = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined,
+ uint32_t srcQueueFamilyIndex_ = {},
+ uint32_t dstQueueFamilyIndex_ = {},
+ VULKAN_HPP_NAMESPACE::Image image_ = {},
+ VULKAN_HPP_NAMESPACE::ImageSubresourceRange subresourceRange_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcAccessMask( srcAccessMask_ )
+ , dstAccessMask( dstAccessMask_ )
+ , oldLayout( oldLayout_ )
+ , newLayout( newLayout_ )
+ , srcQueueFamilyIndex( srcQueueFamilyIndex_ )
+ , dstQueueFamilyIndex( dstQueueFamilyIndex_ )
+ , image( image_ )
+ , subresourceRange( subresourceRange_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageMemoryBarrier & operator=( VULKAN_HPP_NAMESPACE::ImageMemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageMemoryBarrier ) - offsetof( ImageMemoryBarrier, pNext ) );
+ return *this;
+ }
+
+ ImageMemoryBarrier( VkImageMemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageMemoryBarrier& operator=( VkImageMemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageMemoryBarrier const *>(&rhs);
+ return *this;
+ }
+
+ ImageMemoryBarrier & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageMemoryBarrier & setSrcAccessMask( VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcAccessMask = srcAccessMask_;
+ return *this;
+ }
+
+ ImageMemoryBarrier & setDstAccessMask( VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstAccessMask = dstAccessMask_;
+ return *this;
+ }
+
+ ImageMemoryBarrier & setOldLayout( VULKAN_HPP_NAMESPACE::ImageLayout oldLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ oldLayout = oldLayout_;
+ return *this;
+ }
+
+ ImageMemoryBarrier & setNewLayout( VULKAN_HPP_NAMESPACE::ImageLayout newLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ newLayout = newLayout_;
+ return *this;
+ }
+
+ ImageMemoryBarrier & setSrcQueueFamilyIndex( uint32_t srcQueueFamilyIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcQueueFamilyIndex = srcQueueFamilyIndex_;
+ return *this;
+ }
+
+ ImageMemoryBarrier & setDstQueueFamilyIndex( uint32_t dstQueueFamilyIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstQueueFamilyIndex = dstQueueFamilyIndex_;
+ return *this;
+ }
+
+ ImageMemoryBarrier & setImage( VULKAN_HPP_NAMESPACE::Image image_ ) VULKAN_HPP_NOEXCEPT
+ {
+ image = image_;
+ return *this;
+ }
+
+ ImageMemoryBarrier & setSubresourceRange( VULKAN_HPP_NAMESPACE::ImageSubresourceRange subresourceRange_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subresourceRange = subresourceRange_;
+ return *this;
+ }
+
+ operator VkImageMemoryBarrier const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageMemoryBarrier*>( this );
+ }
+
+ operator VkImageMemoryBarrier &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageMemoryBarrier*>( this );
+ }
+
+ bool operator==( ImageMemoryBarrier const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( srcAccessMask == rhs.srcAccessMask )
+ && ( dstAccessMask == rhs.dstAccessMask )
+ && ( oldLayout == rhs.oldLayout )
+ && ( newLayout == rhs.newLayout )
+ && ( srcQueueFamilyIndex == rhs.srcQueueFamilyIndex )
+ && ( dstQueueFamilyIndex == rhs.dstQueueFamilyIndex )
+ && ( image == rhs.image )
+ && ( subresourceRange == rhs.subresourceRange );
+ }
+
+ bool operator!=( ImageMemoryBarrier const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageMemoryBarrier;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask = {};
+ VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask = {};
+ VULKAN_HPP_NAMESPACE::ImageLayout oldLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ VULKAN_HPP_NAMESPACE::ImageLayout newLayout = VULKAN_HPP_NAMESPACE::ImageLayout::eUndefined;
+ uint32_t srcQueueFamilyIndex = {};
+ uint32_t dstQueueFamilyIndex = {};
+ VULKAN_HPP_NAMESPACE::Image image = {};
+ VULKAN_HPP_NAMESPACE::ImageSubresourceRange subresourceRange = {};
+ };
+ static_assert( sizeof( ImageMemoryBarrier ) == sizeof( VkImageMemoryBarrier ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageMemoryBarrier>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageMemoryRequirementsInfo2
+ {
+ VULKAN_HPP_CONSTEXPR ImageMemoryRequirementsInfo2( VULKAN_HPP_NAMESPACE::Image image_ = {} ) VULKAN_HPP_NOEXCEPT
+ : image( image_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageMemoryRequirementsInfo2 & operator=( VULKAN_HPP_NAMESPACE::ImageMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageMemoryRequirementsInfo2 ) - offsetof( ImageMemoryRequirementsInfo2, pNext ) );
+ return *this;
+ }
+
+ ImageMemoryRequirementsInfo2( VkImageMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageMemoryRequirementsInfo2& operator=( VkImageMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageMemoryRequirementsInfo2 const *>(&rhs);
+ return *this;
+ }
+
+ ImageMemoryRequirementsInfo2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageMemoryRequirementsInfo2 & setImage( VULKAN_HPP_NAMESPACE::Image image_ ) VULKAN_HPP_NOEXCEPT
+ {
+ image = image_;
+ return *this;
+ }
+
+ operator VkImageMemoryRequirementsInfo2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( this );
+ }
+
+ operator VkImageMemoryRequirementsInfo2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageMemoryRequirementsInfo2*>( this );
+ }
+
+ bool operator==( ImageMemoryRequirementsInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( image == rhs.image );
+ }
+
+ bool operator!=( ImageMemoryRequirementsInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageMemoryRequirementsInfo2;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Image image = {};
+ };
+ static_assert( sizeof( ImageMemoryRequirementsInfo2 ) == sizeof( VkImageMemoryRequirementsInfo2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageMemoryRequirementsInfo2>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_FUCHSIA
+
+ struct ImagePipeSurfaceCreateInfoFUCHSIA
+ {
+ VULKAN_HPP_CONSTEXPR ImagePipeSurfaceCreateInfoFUCHSIA( VULKAN_HPP_NAMESPACE::ImagePipeSurfaceCreateFlagsFUCHSIA flags_ = {},
+ zx_handle_t imagePipeHandle_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , imagePipeHandle( imagePipeHandle_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImagePipeSurfaceCreateInfoFUCHSIA & operator=( VULKAN_HPP_NAMESPACE::ImagePipeSurfaceCreateInfoFUCHSIA const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImagePipeSurfaceCreateInfoFUCHSIA ) - offsetof( ImagePipeSurfaceCreateInfoFUCHSIA, pNext ) );
+ return *this;
+ }
+
+ ImagePipeSurfaceCreateInfoFUCHSIA( VkImagePipeSurfaceCreateInfoFUCHSIA const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImagePipeSurfaceCreateInfoFUCHSIA& operator=( VkImagePipeSurfaceCreateInfoFUCHSIA const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImagePipeSurfaceCreateInfoFUCHSIA const *>(&rhs);
+ return *this;
+ }
+
+ ImagePipeSurfaceCreateInfoFUCHSIA & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImagePipeSurfaceCreateInfoFUCHSIA & setFlags( VULKAN_HPP_NAMESPACE::ImagePipeSurfaceCreateFlagsFUCHSIA flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ImagePipeSurfaceCreateInfoFUCHSIA & setImagePipeHandle( zx_handle_t imagePipeHandle_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imagePipeHandle = imagePipeHandle_;
+ return *this;
+ }
+
+ operator VkImagePipeSurfaceCreateInfoFUCHSIA const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImagePipeSurfaceCreateInfoFUCHSIA*>( this );
+ }
+
+ operator VkImagePipeSurfaceCreateInfoFUCHSIA &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImagePipeSurfaceCreateInfoFUCHSIA*>( this );
+ }
+
+ bool operator==( ImagePipeSurfaceCreateInfoFUCHSIA const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( imagePipeHandle == rhs.imagePipeHandle );
+ }
+
+ bool operator!=( ImagePipeSurfaceCreateInfoFUCHSIA const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImagepipeSurfaceCreateInfoFUCHSIA;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImagePipeSurfaceCreateFlagsFUCHSIA flags = {};
+ zx_handle_t imagePipeHandle = {};
+ };
+ static_assert( sizeof( ImagePipeSurfaceCreateInfoFUCHSIA ) == sizeof( VkImagePipeSurfaceCreateInfoFUCHSIA ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImagePipeSurfaceCreateInfoFUCHSIA>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_FUCHSIA*/
+
+ struct ImagePlaneMemoryRequirementsInfo
+ {
+ VULKAN_HPP_CONSTEXPR ImagePlaneMemoryRequirementsInfo( VULKAN_HPP_NAMESPACE::ImageAspectFlagBits planeAspect_ = VULKAN_HPP_NAMESPACE::ImageAspectFlagBits::eColor ) VULKAN_HPP_NOEXCEPT
+ : planeAspect( planeAspect_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImagePlaneMemoryRequirementsInfo & operator=( VULKAN_HPP_NAMESPACE::ImagePlaneMemoryRequirementsInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImagePlaneMemoryRequirementsInfo ) - offsetof( ImagePlaneMemoryRequirementsInfo, pNext ) );
+ return *this;
+ }
+
+ ImagePlaneMemoryRequirementsInfo( VkImagePlaneMemoryRequirementsInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImagePlaneMemoryRequirementsInfo& operator=( VkImagePlaneMemoryRequirementsInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImagePlaneMemoryRequirementsInfo const *>(&rhs);
+ return *this;
+ }
+
+ ImagePlaneMemoryRequirementsInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImagePlaneMemoryRequirementsInfo & setPlaneAspect( VULKAN_HPP_NAMESPACE::ImageAspectFlagBits planeAspect_ ) VULKAN_HPP_NOEXCEPT
+ {
+ planeAspect = planeAspect_;
+ return *this;
+ }
+
+ operator VkImagePlaneMemoryRequirementsInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImagePlaneMemoryRequirementsInfo*>( this );
+ }
+
+ operator VkImagePlaneMemoryRequirementsInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImagePlaneMemoryRequirementsInfo*>( this );
+ }
+
+ bool operator==( ImagePlaneMemoryRequirementsInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( planeAspect == rhs.planeAspect );
+ }
+
+ bool operator!=( ImagePlaneMemoryRequirementsInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImagePlaneMemoryRequirementsInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageAspectFlagBits planeAspect = VULKAN_HPP_NAMESPACE::ImageAspectFlagBits::eColor;
+ };
+ static_assert( sizeof( ImagePlaneMemoryRequirementsInfo ) == sizeof( VkImagePlaneMemoryRequirementsInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImagePlaneMemoryRequirementsInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageResolve
+ {
+ VULKAN_HPP_CONSTEXPR ImageResolve( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers srcSubresource_ = {},
+ VULKAN_HPP_NAMESPACE::Offset3D srcOffset_ = {},
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource_ = {},
+ VULKAN_HPP_NAMESPACE::Offset3D dstOffset_ = {},
+ VULKAN_HPP_NAMESPACE::Extent3D extent_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcSubresource( srcSubresource_ )
+ , srcOffset( srcOffset_ )
+ , dstSubresource( dstSubresource_ )
+ , dstOffset( dstOffset_ )
+ , extent( extent_ )
+ {}
+
+ ImageResolve( VkImageResolve const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageResolve& operator=( VkImageResolve const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageResolve const *>(&rhs);
+ return *this;
+ }
+
+ ImageResolve & setSrcSubresource( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers srcSubresource_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcSubresource = srcSubresource_;
+ return *this;
+ }
+
+ ImageResolve & setSrcOffset( VULKAN_HPP_NAMESPACE::Offset3D srcOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcOffset = srcOffset_;
+ return *this;
+ }
+
+ ImageResolve & setDstSubresource( VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstSubresource = dstSubresource_;
+ return *this;
+ }
+
+ ImageResolve & setDstOffset( VULKAN_HPP_NAMESPACE::Offset3D dstOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstOffset = dstOffset_;
+ return *this;
+ }
+
+ ImageResolve & setExtent( VULKAN_HPP_NAMESPACE::Extent3D extent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ extent = extent_;
+ return *this;
+ }
+
+ operator VkImageResolve const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageResolve*>( this );
+ }
+
+ operator VkImageResolve &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageResolve*>( this );
+ }
+
+ bool operator==( ImageResolve const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( srcSubresource == rhs.srcSubresource )
+ && ( srcOffset == rhs.srcOffset )
+ && ( dstSubresource == rhs.dstSubresource )
+ && ( dstOffset == rhs.dstOffset )
+ && ( extent == rhs.extent );
+ }
+
+ bool operator!=( ImageResolve const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers srcSubresource = {};
+ VULKAN_HPP_NAMESPACE::Offset3D srcOffset = {};
+ VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource = {};
+ VULKAN_HPP_NAMESPACE::Offset3D dstOffset = {};
+ VULKAN_HPP_NAMESPACE::Extent3D extent = {};
+ };
+ static_assert( sizeof( ImageResolve ) == sizeof( VkImageResolve ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageResolve>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageSparseMemoryRequirementsInfo2
+ {
+ VULKAN_HPP_CONSTEXPR ImageSparseMemoryRequirementsInfo2( VULKAN_HPP_NAMESPACE::Image image_ = {} ) VULKAN_HPP_NOEXCEPT
+ : image( image_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageSparseMemoryRequirementsInfo2 & operator=( VULKAN_HPP_NAMESPACE::ImageSparseMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageSparseMemoryRequirementsInfo2 ) - offsetof( ImageSparseMemoryRequirementsInfo2, pNext ) );
+ return *this;
+ }
+
+ ImageSparseMemoryRequirementsInfo2( VkImageSparseMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageSparseMemoryRequirementsInfo2& operator=( VkImageSparseMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageSparseMemoryRequirementsInfo2 const *>(&rhs);
+ return *this;
+ }
+
+ ImageSparseMemoryRequirementsInfo2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageSparseMemoryRequirementsInfo2 & setImage( VULKAN_HPP_NAMESPACE::Image image_ ) VULKAN_HPP_NOEXCEPT
+ {
+ image = image_;
+ return *this;
+ }
+
+ operator VkImageSparseMemoryRequirementsInfo2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( this );
+ }
+
+ operator VkImageSparseMemoryRequirementsInfo2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageSparseMemoryRequirementsInfo2*>( this );
+ }
+
+ bool operator==( ImageSparseMemoryRequirementsInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( image == rhs.image );
+ }
+
+ bool operator!=( ImageSparseMemoryRequirementsInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageSparseMemoryRequirementsInfo2;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Image image = {};
+ };
+ static_assert( sizeof( ImageSparseMemoryRequirementsInfo2 ) == sizeof( VkImageSparseMemoryRequirementsInfo2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageSparseMemoryRequirementsInfo2>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageStencilUsageCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ImageStencilUsageCreateInfo( VULKAN_HPP_NAMESPACE::ImageUsageFlags stencilUsage_ = {} ) VULKAN_HPP_NOEXCEPT
+ : stencilUsage( stencilUsage_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageStencilUsageCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ImageStencilUsageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageStencilUsageCreateInfo ) - offsetof( ImageStencilUsageCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ImageStencilUsageCreateInfo( VkImageStencilUsageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageStencilUsageCreateInfo& operator=( VkImageStencilUsageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageStencilUsageCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ImageStencilUsageCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageStencilUsageCreateInfo & setStencilUsage( VULKAN_HPP_NAMESPACE::ImageUsageFlags stencilUsage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencilUsage = stencilUsage_;
+ return *this;
+ }
+
+ operator VkImageStencilUsageCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageStencilUsageCreateInfo*>( this );
+ }
+
+ operator VkImageStencilUsageCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageStencilUsageCreateInfo*>( this );
+ }
+
+ bool operator==( ImageStencilUsageCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( stencilUsage == rhs.stencilUsage );
+ }
+
+ bool operator!=( ImageStencilUsageCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageStencilUsageCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags stencilUsage = {};
+ };
+ static_assert( sizeof( ImageStencilUsageCreateInfo ) == sizeof( VkImageStencilUsageCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageStencilUsageCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageSwapchainCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR ImageSwapchainCreateInfoKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain_ = {} ) VULKAN_HPP_NOEXCEPT
+ : swapchain( swapchain_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageSwapchainCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::ImageSwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageSwapchainCreateInfoKHR ) - offsetof( ImageSwapchainCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ ImageSwapchainCreateInfoKHR( VkImageSwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageSwapchainCreateInfoKHR& operator=( VkImageSwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageSwapchainCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ ImageSwapchainCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageSwapchainCreateInfoKHR & setSwapchain( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain_ ) VULKAN_HPP_NOEXCEPT
+ {
+ swapchain = swapchain_;
+ return *this;
+ }
+
+ operator VkImageSwapchainCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageSwapchainCreateInfoKHR*>( this );
+ }
+
+ operator VkImageSwapchainCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageSwapchainCreateInfoKHR*>( this );
+ }
+
+ bool operator==( ImageSwapchainCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( swapchain == rhs.swapchain );
+ }
+
+ bool operator!=( ImageSwapchainCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageSwapchainCreateInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain = {};
+ };
+ static_assert( sizeof( ImageSwapchainCreateInfoKHR ) == sizeof( VkImageSwapchainCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageSwapchainCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageViewASTCDecodeModeEXT
+ {
+ VULKAN_HPP_CONSTEXPR ImageViewASTCDecodeModeEXT( VULKAN_HPP_NAMESPACE::Format decodeMode_ = VULKAN_HPP_NAMESPACE::Format::eUndefined ) VULKAN_HPP_NOEXCEPT
+ : decodeMode( decodeMode_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageViewASTCDecodeModeEXT & operator=( VULKAN_HPP_NAMESPACE::ImageViewASTCDecodeModeEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageViewASTCDecodeModeEXT ) - offsetof( ImageViewASTCDecodeModeEXT, pNext ) );
+ return *this;
+ }
+
+ ImageViewASTCDecodeModeEXT( VkImageViewASTCDecodeModeEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageViewASTCDecodeModeEXT& operator=( VkImageViewASTCDecodeModeEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageViewASTCDecodeModeEXT const *>(&rhs);
+ return *this;
+ }
+
+ ImageViewASTCDecodeModeEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageViewASTCDecodeModeEXT & setDecodeMode( VULKAN_HPP_NAMESPACE::Format decodeMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ decodeMode = decodeMode_;
+ return *this;
+ }
+
+ operator VkImageViewASTCDecodeModeEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageViewASTCDecodeModeEXT*>( this );
+ }
+
+ operator VkImageViewASTCDecodeModeEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageViewASTCDecodeModeEXT*>( this );
+ }
+
+ bool operator==( ImageViewASTCDecodeModeEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( decodeMode == rhs.decodeMode );
+ }
+
+ bool operator!=( ImageViewASTCDecodeModeEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageViewAstcDecodeModeEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Format decodeMode = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ };
+ static_assert( sizeof( ImageViewASTCDecodeModeEXT ) == sizeof( VkImageViewASTCDecodeModeEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageViewASTCDecodeModeEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageViewCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ImageViewCreateInfo( VULKAN_HPP_NAMESPACE::ImageViewCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::Image image_ = {},
+ VULKAN_HPP_NAMESPACE::ImageViewType viewType_ = VULKAN_HPP_NAMESPACE::ImageViewType::e1D,
+ VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::ComponentMapping components_ = {},
+ VULKAN_HPP_NAMESPACE::ImageSubresourceRange subresourceRange_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , image( image_ )
+ , viewType( viewType_ )
+ , format( format_ )
+ , components( components_ )
+ , subresourceRange( subresourceRange_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageViewCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ImageViewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageViewCreateInfo ) - offsetof( ImageViewCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ImageViewCreateInfo( VkImageViewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageViewCreateInfo& operator=( VkImageViewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageViewCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ImageViewCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageViewCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::ImageViewCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ImageViewCreateInfo & setImage( VULKAN_HPP_NAMESPACE::Image image_ ) VULKAN_HPP_NOEXCEPT
+ {
+ image = image_;
+ return *this;
+ }
+
+ ImageViewCreateInfo & setViewType( VULKAN_HPP_NAMESPACE::ImageViewType viewType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ viewType = viewType_;
+ return *this;
+ }
+
+ ImageViewCreateInfo & setFormat( VULKAN_HPP_NAMESPACE::Format format_ ) VULKAN_HPP_NOEXCEPT
+ {
+ format = format_;
+ return *this;
+ }
+
+ ImageViewCreateInfo & setComponents( VULKAN_HPP_NAMESPACE::ComponentMapping components_ ) VULKAN_HPP_NOEXCEPT
+ {
+ components = components_;
+ return *this;
+ }
+
+ ImageViewCreateInfo & setSubresourceRange( VULKAN_HPP_NAMESPACE::ImageSubresourceRange subresourceRange_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subresourceRange = subresourceRange_;
+ return *this;
+ }
+
+ operator VkImageViewCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageViewCreateInfo*>( this );
+ }
+
+ operator VkImageViewCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageViewCreateInfo*>( this );
+ }
+
+ bool operator==( ImageViewCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( image == rhs.image )
+ && ( viewType == rhs.viewType )
+ && ( format == rhs.format )
+ && ( components == rhs.components )
+ && ( subresourceRange == rhs.subresourceRange );
+ }
+
+ bool operator!=( ImageViewCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageViewCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageViewCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::Image image = {};
+ VULKAN_HPP_NAMESPACE::ImageViewType viewType = VULKAN_HPP_NAMESPACE::ImageViewType::e1D;
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::ComponentMapping components = {};
+ VULKAN_HPP_NAMESPACE::ImageSubresourceRange subresourceRange = {};
+ };
+ static_assert( sizeof( ImageViewCreateInfo ) == sizeof( VkImageViewCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageViewCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageViewHandleInfoNVX
+ {
+ VULKAN_HPP_CONSTEXPR ImageViewHandleInfoNVX( VULKAN_HPP_NAMESPACE::ImageView imageView_ = {},
+ VULKAN_HPP_NAMESPACE::DescriptorType descriptorType_ = VULKAN_HPP_NAMESPACE::DescriptorType::eSampler,
+ VULKAN_HPP_NAMESPACE::Sampler sampler_ = {} ) VULKAN_HPP_NOEXCEPT
+ : imageView( imageView_ )
+ , descriptorType( descriptorType_ )
+ , sampler( sampler_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageViewHandleInfoNVX & operator=( VULKAN_HPP_NAMESPACE::ImageViewHandleInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageViewHandleInfoNVX ) - offsetof( ImageViewHandleInfoNVX, pNext ) );
+ return *this;
+ }
+
+ ImageViewHandleInfoNVX( VkImageViewHandleInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageViewHandleInfoNVX& operator=( VkImageViewHandleInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageViewHandleInfoNVX const *>(&rhs);
+ return *this;
+ }
+
+ ImageViewHandleInfoNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageViewHandleInfoNVX & setImageView( VULKAN_HPP_NAMESPACE::ImageView imageView_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageView = imageView_;
+ return *this;
+ }
+
+ ImageViewHandleInfoNVX & setDescriptorType( VULKAN_HPP_NAMESPACE::DescriptorType descriptorType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorType = descriptorType_;
+ return *this;
+ }
+
+ ImageViewHandleInfoNVX & setSampler( VULKAN_HPP_NAMESPACE::Sampler sampler_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampler = sampler_;
+ return *this;
+ }
+
+ operator VkImageViewHandleInfoNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageViewHandleInfoNVX*>( this );
+ }
+
+ operator VkImageViewHandleInfoNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageViewHandleInfoNVX*>( this );
+ }
+
+ bool operator==( ImageViewHandleInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( imageView == rhs.imageView )
+ && ( descriptorType == rhs.descriptorType )
+ && ( sampler == rhs.sampler );
+ }
+
+ bool operator!=( ImageViewHandleInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageViewHandleInfoNVX;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageView imageView = {};
+ VULKAN_HPP_NAMESPACE::DescriptorType descriptorType = VULKAN_HPP_NAMESPACE::DescriptorType::eSampler;
+ VULKAN_HPP_NAMESPACE::Sampler sampler = {};
+ };
+ static_assert( sizeof( ImageViewHandleInfoNVX ) == sizeof( VkImageViewHandleInfoNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageViewHandleInfoNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImageViewUsageCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ImageViewUsageCreateInfo( VULKAN_HPP_NAMESPACE::ImageUsageFlags usage_ = {} ) VULKAN_HPP_NOEXCEPT
+ : usage( usage_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImageViewUsageCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ImageViewUsageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImageViewUsageCreateInfo ) - offsetof( ImageViewUsageCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ImageViewUsageCreateInfo( VkImageViewUsageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImageViewUsageCreateInfo& operator=( VkImageViewUsageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageViewUsageCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ImageViewUsageCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImageViewUsageCreateInfo & setUsage( VULKAN_HPP_NAMESPACE::ImageUsageFlags usage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ usage = usage_;
+ return *this;
+ }
+
+ operator VkImageViewUsageCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImageViewUsageCreateInfo*>( this );
+ }
+
+ operator VkImageViewUsageCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImageViewUsageCreateInfo*>( this );
+ }
+
+ bool operator==( ImageViewUsageCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( usage == rhs.usage );
+ }
+
+ bool operator!=( ImageViewUsageCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageViewUsageCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags usage = {};
+ };
+ static_assert( sizeof( ImageViewUsageCreateInfo ) == sizeof( VkImageViewUsageCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImageViewUsageCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+
+ struct ImportAndroidHardwareBufferInfoANDROID
+ {
+ VULKAN_HPP_CONSTEXPR ImportAndroidHardwareBufferInfoANDROID( struct AHardwareBuffer* buffer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : buffer( buffer_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImportAndroidHardwareBufferInfoANDROID & operator=( VULKAN_HPP_NAMESPACE::ImportAndroidHardwareBufferInfoANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImportAndroidHardwareBufferInfoANDROID ) - offsetof( ImportAndroidHardwareBufferInfoANDROID, pNext ) );
+ return *this;
+ }
+
+ ImportAndroidHardwareBufferInfoANDROID( VkImportAndroidHardwareBufferInfoANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImportAndroidHardwareBufferInfoANDROID& operator=( VkImportAndroidHardwareBufferInfoANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImportAndroidHardwareBufferInfoANDROID const *>(&rhs);
+ return *this;
+ }
+
+ ImportAndroidHardwareBufferInfoANDROID & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImportAndroidHardwareBufferInfoANDROID & setBuffer( struct AHardwareBuffer* buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ operator VkImportAndroidHardwareBufferInfoANDROID const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImportAndroidHardwareBufferInfoANDROID*>( this );
+ }
+
+ operator VkImportAndroidHardwareBufferInfoANDROID &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImportAndroidHardwareBufferInfoANDROID*>( this );
+ }
+
+ bool operator==( ImportAndroidHardwareBufferInfoANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( buffer == rhs.buffer );
+ }
+
+ bool operator!=( ImportAndroidHardwareBufferInfoANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImportAndroidHardwareBufferInfoANDROID;
+ const void* pNext = {};
+ struct AHardwareBuffer* buffer = {};
+ };
+ static_assert( sizeof( ImportAndroidHardwareBufferInfoANDROID ) == sizeof( VkImportAndroidHardwareBufferInfoANDROID ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImportAndroidHardwareBufferInfoANDROID>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ struct ImportFenceFdInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR ImportFenceFdInfoKHR( VULKAN_HPP_NAMESPACE::Fence fence_ = {},
+ VULKAN_HPP_NAMESPACE::FenceImportFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits::eOpaqueFd,
+ int fd_ = {} ) VULKAN_HPP_NOEXCEPT
+ : fence( fence_ )
+ , flags( flags_ )
+ , handleType( handleType_ )
+ , fd( fd_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImportFenceFdInfoKHR & operator=( VULKAN_HPP_NAMESPACE::ImportFenceFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImportFenceFdInfoKHR ) - offsetof( ImportFenceFdInfoKHR, pNext ) );
+ return *this;
+ }
+
+ ImportFenceFdInfoKHR( VkImportFenceFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImportFenceFdInfoKHR& operator=( VkImportFenceFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImportFenceFdInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ ImportFenceFdInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImportFenceFdInfoKHR & setFence( VULKAN_HPP_NAMESPACE::Fence fence_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fence = fence_;
+ return *this;
+ }
+
+ ImportFenceFdInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::FenceImportFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ImportFenceFdInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ ImportFenceFdInfoKHR & setFd( int fd_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fd = fd_;
+ return *this;
+ }
+
+ operator VkImportFenceFdInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImportFenceFdInfoKHR*>( this );
+ }
+
+ operator VkImportFenceFdInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImportFenceFdInfoKHR*>( this );
+ }
+
+ bool operator==( ImportFenceFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( fence == rhs.fence )
+ && ( flags == rhs.flags )
+ && ( handleType == rhs.handleType )
+ && ( fd == rhs.fd );
+ }
+
+ bool operator!=( ImportFenceFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImportFenceFdInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Fence fence = {};
+ VULKAN_HPP_NAMESPACE::FenceImportFlags flags = {};
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits::eOpaqueFd;
+ int fd = {};
+ };
+ static_assert( sizeof( ImportFenceFdInfoKHR ) == sizeof( VkImportFenceFdInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImportFenceFdInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct ImportFenceWin32HandleInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR ImportFenceWin32HandleInfoKHR( VULKAN_HPP_NAMESPACE::Fence fence_ = {},
+ VULKAN_HPP_NAMESPACE::FenceImportFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits::eOpaqueFd,
+ HANDLE handle_ = {},
+ LPCWSTR name_ = {} ) VULKAN_HPP_NOEXCEPT
+ : fence( fence_ )
+ , flags( flags_ )
+ , handleType( handleType_ )
+ , handle( handle_ )
+ , name( name_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImportFenceWin32HandleInfoKHR & operator=( VULKAN_HPP_NAMESPACE::ImportFenceWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImportFenceWin32HandleInfoKHR ) - offsetof( ImportFenceWin32HandleInfoKHR, pNext ) );
+ return *this;
+ }
+
+ ImportFenceWin32HandleInfoKHR( VkImportFenceWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImportFenceWin32HandleInfoKHR& operator=( VkImportFenceWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImportFenceWin32HandleInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ ImportFenceWin32HandleInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImportFenceWin32HandleInfoKHR & setFence( VULKAN_HPP_NAMESPACE::Fence fence_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fence = fence_;
+ return *this;
+ }
+
+ ImportFenceWin32HandleInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::FenceImportFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ImportFenceWin32HandleInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ ImportFenceWin32HandleInfoKHR & setHandle( HANDLE handle_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handle = handle_;
+ return *this;
+ }
+
+ ImportFenceWin32HandleInfoKHR & setName( LPCWSTR name_ ) VULKAN_HPP_NOEXCEPT
+ {
+ name = name_;
+ return *this;
+ }
+
+ operator VkImportFenceWin32HandleInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImportFenceWin32HandleInfoKHR*>( this );
+ }
+
+ operator VkImportFenceWin32HandleInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImportFenceWin32HandleInfoKHR*>( this );
+ }
+
+ bool operator==( ImportFenceWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( fence == rhs.fence )
+ && ( flags == rhs.flags )
+ && ( handleType == rhs.handleType )
+ && ( handle == rhs.handle )
+ && ( name == rhs.name );
+ }
+
+ bool operator!=( ImportFenceWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImportFenceWin32HandleInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Fence fence = {};
+ VULKAN_HPP_NAMESPACE::FenceImportFlags flags = {};
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits::eOpaqueFd;
+ HANDLE handle = {};
+ LPCWSTR name = {};
+ };
+ static_assert( sizeof( ImportFenceWin32HandleInfoKHR ) == sizeof( VkImportFenceWin32HandleInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImportFenceWin32HandleInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct ImportMemoryFdInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR ImportMemoryFdInfoKHR( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd,
+ int fd_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleType( handleType_ )
+ , fd( fd_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImportMemoryFdInfoKHR & operator=( VULKAN_HPP_NAMESPACE::ImportMemoryFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImportMemoryFdInfoKHR ) - offsetof( ImportMemoryFdInfoKHR, pNext ) );
+ return *this;
+ }
+
+ ImportMemoryFdInfoKHR( VkImportMemoryFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImportMemoryFdInfoKHR& operator=( VkImportMemoryFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImportMemoryFdInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ ImportMemoryFdInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImportMemoryFdInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ ImportMemoryFdInfoKHR & setFd( int fd_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fd = fd_;
+ return *this;
+ }
+
+ operator VkImportMemoryFdInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImportMemoryFdInfoKHR*>( this );
+ }
+
+ operator VkImportMemoryFdInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImportMemoryFdInfoKHR*>( this );
+ }
+
+ bool operator==( ImportMemoryFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleType == rhs.handleType )
+ && ( fd == rhs.fd );
+ }
+
+ bool operator!=( ImportMemoryFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImportMemoryFdInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd;
+ int fd = {};
+ };
+ static_assert( sizeof( ImportMemoryFdInfoKHR ) == sizeof( VkImportMemoryFdInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImportMemoryFdInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct ImportMemoryHostPointerInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR ImportMemoryHostPointerInfoEXT( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd,
+ void* pHostPointer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleType( handleType_ )
+ , pHostPointer( pHostPointer_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImportMemoryHostPointerInfoEXT & operator=( VULKAN_HPP_NAMESPACE::ImportMemoryHostPointerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImportMemoryHostPointerInfoEXT ) - offsetof( ImportMemoryHostPointerInfoEXT, pNext ) );
+ return *this;
+ }
+
+ ImportMemoryHostPointerInfoEXT( VkImportMemoryHostPointerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImportMemoryHostPointerInfoEXT& operator=( VkImportMemoryHostPointerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImportMemoryHostPointerInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ ImportMemoryHostPointerInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImportMemoryHostPointerInfoEXT & setHandleType( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ ImportMemoryHostPointerInfoEXT & setPHostPointer( void* pHostPointer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pHostPointer = pHostPointer_;
+ return *this;
+ }
+
+ operator VkImportMemoryHostPointerInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImportMemoryHostPointerInfoEXT*>( this );
+ }
+
+ operator VkImportMemoryHostPointerInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImportMemoryHostPointerInfoEXT*>( this );
+ }
+
+ bool operator==( ImportMemoryHostPointerInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleType == rhs.handleType )
+ && ( pHostPointer == rhs.pHostPointer );
+ }
+
+ bool operator!=( ImportMemoryHostPointerInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImportMemoryHostPointerInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd;
+ void* pHostPointer = {};
+ };
+ static_assert( sizeof( ImportMemoryHostPointerInfoEXT ) == sizeof( VkImportMemoryHostPointerInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImportMemoryHostPointerInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct ImportMemoryWin32HandleInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR ImportMemoryWin32HandleInfoKHR( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd,
+ HANDLE handle_ = {},
+ LPCWSTR name_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleType( handleType_ )
+ , handle( handle_ )
+ , name( name_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImportMemoryWin32HandleInfoKHR & operator=( VULKAN_HPP_NAMESPACE::ImportMemoryWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImportMemoryWin32HandleInfoKHR ) - offsetof( ImportMemoryWin32HandleInfoKHR, pNext ) );
+ return *this;
+ }
+
+ ImportMemoryWin32HandleInfoKHR( VkImportMemoryWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImportMemoryWin32HandleInfoKHR& operator=( VkImportMemoryWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImportMemoryWin32HandleInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ ImportMemoryWin32HandleInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImportMemoryWin32HandleInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ ImportMemoryWin32HandleInfoKHR & setHandle( HANDLE handle_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handle = handle_;
+ return *this;
+ }
+
+ ImportMemoryWin32HandleInfoKHR & setName( LPCWSTR name_ ) VULKAN_HPP_NOEXCEPT
+ {
+ name = name_;
+ return *this;
+ }
+
+ operator VkImportMemoryWin32HandleInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImportMemoryWin32HandleInfoKHR*>( this );
+ }
+
+ operator VkImportMemoryWin32HandleInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImportMemoryWin32HandleInfoKHR*>( this );
+ }
+
+ bool operator==( ImportMemoryWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleType == rhs.handleType )
+ && ( handle == rhs.handle )
+ && ( name == rhs.name );
+ }
+
+ bool operator!=( ImportMemoryWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImportMemoryWin32HandleInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd;
+ HANDLE handle = {};
+ LPCWSTR name = {};
+ };
+ static_assert( sizeof( ImportMemoryWin32HandleInfoKHR ) == sizeof( VkImportMemoryWin32HandleInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImportMemoryWin32HandleInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct ImportMemoryWin32HandleInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR ImportMemoryWin32HandleInfoNV( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleType_ = {},
+ HANDLE handle_ = {} ) VULKAN_HPP_NOEXCEPT
+ : handleType( handleType_ )
+ , handle( handle_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImportMemoryWin32HandleInfoNV & operator=( VULKAN_HPP_NAMESPACE::ImportMemoryWin32HandleInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImportMemoryWin32HandleInfoNV ) - offsetof( ImportMemoryWin32HandleInfoNV, pNext ) );
+ return *this;
+ }
+
+ ImportMemoryWin32HandleInfoNV( VkImportMemoryWin32HandleInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImportMemoryWin32HandleInfoNV& operator=( VkImportMemoryWin32HandleInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImportMemoryWin32HandleInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ ImportMemoryWin32HandleInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImportMemoryWin32HandleInfoNV & setHandleType( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ ImportMemoryWin32HandleInfoNV & setHandle( HANDLE handle_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handle = handle_;
+ return *this;
+ }
+
+ operator VkImportMemoryWin32HandleInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImportMemoryWin32HandleInfoNV*>( this );
+ }
+
+ operator VkImportMemoryWin32HandleInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImportMemoryWin32HandleInfoNV*>( this );
+ }
+
+ bool operator==( ImportMemoryWin32HandleInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleType == rhs.handleType )
+ && ( handle == rhs.handle );
+ }
+
+ bool operator!=( ImportMemoryWin32HandleInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImportMemoryWin32HandleInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleType = {};
+ HANDLE handle = {};
+ };
+ static_assert( sizeof( ImportMemoryWin32HandleInfoNV ) == sizeof( VkImportMemoryWin32HandleInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImportMemoryWin32HandleInfoNV>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct ImportSemaphoreFdInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR ImportSemaphoreFdInfoKHR( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ = {},
+ VULKAN_HPP_NAMESPACE::SemaphoreImportFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd,
+ int fd_ = {} ) VULKAN_HPP_NOEXCEPT
+ : semaphore( semaphore_ )
+ , flags( flags_ )
+ , handleType( handleType_ )
+ , fd( fd_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImportSemaphoreFdInfoKHR & operator=( VULKAN_HPP_NAMESPACE::ImportSemaphoreFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImportSemaphoreFdInfoKHR ) - offsetof( ImportSemaphoreFdInfoKHR, pNext ) );
+ return *this;
+ }
+
+ ImportSemaphoreFdInfoKHR( VkImportSemaphoreFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImportSemaphoreFdInfoKHR& operator=( VkImportSemaphoreFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImportSemaphoreFdInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ ImportSemaphoreFdInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImportSemaphoreFdInfoKHR & setSemaphore( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ ) VULKAN_HPP_NOEXCEPT
+ {
+ semaphore = semaphore_;
+ return *this;
+ }
+
+ ImportSemaphoreFdInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::SemaphoreImportFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ImportSemaphoreFdInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ ImportSemaphoreFdInfoKHR & setFd( int fd_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fd = fd_;
+ return *this;
+ }
+
+ operator VkImportSemaphoreFdInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImportSemaphoreFdInfoKHR*>( this );
+ }
+
+ operator VkImportSemaphoreFdInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImportSemaphoreFdInfoKHR*>( this );
+ }
+
+ bool operator==( ImportSemaphoreFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( semaphore == rhs.semaphore )
+ && ( flags == rhs.flags )
+ && ( handleType == rhs.handleType )
+ && ( fd == rhs.fd );
+ }
+
+ bool operator!=( ImportSemaphoreFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImportSemaphoreFdInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Semaphore semaphore = {};
+ VULKAN_HPP_NAMESPACE::SemaphoreImportFlags flags = {};
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd;
+ int fd = {};
+ };
+ static_assert( sizeof( ImportSemaphoreFdInfoKHR ) == sizeof( VkImportSemaphoreFdInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImportSemaphoreFdInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct ImportSemaphoreWin32HandleInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR ImportSemaphoreWin32HandleInfoKHR( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ = {},
+ VULKAN_HPP_NAMESPACE::SemaphoreImportFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd,
+ HANDLE handle_ = {},
+ LPCWSTR name_ = {} ) VULKAN_HPP_NOEXCEPT
+ : semaphore( semaphore_ )
+ , flags( flags_ )
+ , handleType( handleType_ )
+ , handle( handle_ )
+ , name( name_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ImportSemaphoreWin32HandleInfoKHR & operator=( VULKAN_HPP_NAMESPACE::ImportSemaphoreWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ImportSemaphoreWin32HandleInfoKHR ) - offsetof( ImportSemaphoreWin32HandleInfoKHR, pNext ) );
+ return *this;
+ }
+
+ ImportSemaphoreWin32HandleInfoKHR( VkImportSemaphoreWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ImportSemaphoreWin32HandleInfoKHR& operator=( VkImportSemaphoreWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImportSemaphoreWin32HandleInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ ImportSemaphoreWin32HandleInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ImportSemaphoreWin32HandleInfoKHR & setSemaphore( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ ) VULKAN_HPP_NOEXCEPT
+ {
+ semaphore = semaphore_;
+ return *this;
+ }
+
+ ImportSemaphoreWin32HandleInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::SemaphoreImportFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ImportSemaphoreWin32HandleInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ ImportSemaphoreWin32HandleInfoKHR & setHandle( HANDLE handle_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handle = handle_;
+ return *this;
+ }
+
+ ImportSemaphoreWin32HandleInfoKHR & setName( LPCWSTR name_ ) VULKAN_HPP_NOEXCEPT
+ {
+ name = name_;
+ return *this;
+ }
+
+ operator VkImportSemaphoreWin32HandleInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkImportSemaphoreWin32HandleInfoKHR*>( this );
+ }
+
+ operator VkImportSemaphoreWin32HandleInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkImportSemaphoreWin32HandleInfoKHR*>( this );
+ }
+
+ bool operator==( ImportSemaphoreWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( semaphore == rhs.semaphore )
+ && ( flags == rhs.flags )
+ && ( handleType == rhs.handleType )
+ && ( handle == rhs.handle )
+ && ( name == rhs.name );
+ }
+
+ bool operator!=( ImportSemaphoreWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImportSemaphoreWin32HandleInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Semaphore semaphore = {};
+ VULKAN_HPP_NAMESPACE::SemaphoreImportFlags flags = {};
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd;
+ HANDLE handle = {};
+ LPCWSTR name = {};
+ };
+ static_assert( sizeof( ImportSemaphoreWin32HandleInfoKHR ) == sizeof( VkImportSemaphoreWin32HandleInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ImportSemaphoreWin32HandleInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct IndirectCommandsLayoutTokenNVX
+ {
+ VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutTokenNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType_ = VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX::ePipeline,
+ uint32_t bindingUnit_ = {},
+ uint32_t dynamicCount_ = {},
+ uint32_t divisor_ = {} ) VULKAN_HPP_NOEXCEPT
+ : tokenType( tokenType_ )
+ , bindingUnit( bindingUnit_ )
+ , dynamicCount( dynamicCount_ )
+ , divisor( divisor_ )
+ {}
+
+ IndirectCommandsLayoutTokenNVX( VkIndirectCommandsLayoutTokenNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ IndirectCommandsLayoutTokenNVX& operator=( VkIndirectCommandsLayoutTokenNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNVX const *>(&rhs);
+ return *this;
+ }
+
+ IndirectCommandsLayoutTokenNVX & setTokenType( VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tokenType = tokenType_;
+ return *this;
+ }
+
+ IndirectCommandsLayoutTokenNVX & setBindingUnit( uint32_t bindingUnit_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bindingUnit = bindingUnit_;
+ return *this;
+ }
+
+ IndirectCommandsLayoutTokenNVX & setDynamicCount( uint32_t dynamicCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dynamicCount = dynamicCount_;
+ return *this;
+ }
+
+ IndirectCommandsLayoutTokenNVX & setDivisor( uint32_t divisor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ divisor = divisor_;
+ return *this;
+ }
+
+ operator VkIndirectCommandsLayoutTokenNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkIndirectCommandsLayoutTokenNVX*>( this );
+ }
+
+ operator VkIndirectCommandsLayoutTokenNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkIndirectCommandsLayoutTokenNVX*>( this );
+ }
+
+ bool operator==( IndirectCommandsLayoutTokenNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( tokenType == rhs.tokenType )
+ && ( bindingUnit == rhs.bindingUnit )
+ && ( dynamicCount == rhs.dynamicCount )
+ && ( divisor == rhs.divisor );
+ }
+
+ bool operator!=( IndirectCommandsLayoutTokenNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType = VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX::ePipeline;
+ uint32_t bindingUnit = {};
+ uint32_t dynamicCount = {};
+ uint32_t divisor = {};
+ };
+ static_assert( sizeof( IndirectCommandsLayoutTokenNVX ) == sizeof( VkIndirectCommandsLayoutTokenNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<IndirectCommandsLayoutTokenNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct IndirectCommandsLayoutCreateInfoNVX
+ {
+ VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutCreateInfoNVX( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics,
+ VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutUsageFlagsNVX flags_ = {},
+ uint32_t tokenCount_ = {},
+ const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNVX* pTokens_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pipelineBindPoint( pipelineBindPoint_ )
+ , flags( flags_ )
+ , tokenCount( tokenCount_ )
+ , pTokens( pTokens_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNVX & operator=( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNVX ) - offsetof( IndirectCommandsLayoutCreateInfoNVX, pNext ) );
+ return *this;
+ }
+
+ IndirectCommandsLayoutCreateInfoNVX( VkIndirectCommandsLayoutCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ IndirectCommandsLayoutCreateInfoNVX& operator=( VkIndirectCommandsLayoutCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNVX const *>(&rhs);
+ return *this;
+ }
+
+ IndirectCommandsLayoutCreateInfoNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ IndirectCommandsLayoutCreateInfoNVX & setPipelineBindPoint( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineBindPoint = pipelineBindPoint_;
+ return *this;
+ }
+
+ IndirectCommandsLayoutCreateInfoNVX & setFlags( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ IndirectCommandsLayoutCreateInfoNVX & setTokenCount( uint32_t tokenCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tokenCount = tokenCount_;
+ return *this;
+ }
+
+ IndirectCommandsLayoutCreateInfoNVX & setPTokens( const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNVX* pTokens_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pTokens = pTokens_;
+ return *this;
+ }
+
+ operator VkIndirectCommandsLayoutCreateInfoNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNVX*>( this );
+ }
+
+ operator VkIndirectCommandsLayoutCreateInfoNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkIndirectCommandsLayoutCreateInfoNVX*>( this );
+ }
+
+ bool operator==( IndirectCommandsLayoutCreateInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pipelineBindPoint == rhs.pipelineBindPoint )
+ && ( flags == rhs.flags )
+ && ( tokenCount == rhs.tokenCount )
+ && ( pTokens == rhs.pTokens );
+ }
+
+ bool operator!=( IndirectCommandsLayoutCreateInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eIndirectCommandsLayoutCreateInfoNVX;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics;
+ VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutUsageFlagsNVX flags = {};
+ uint32_t tokenCount = {};
+ const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNVX* pTokens = {};
+ };
+ static_assert( sizeof( IndirectCommandsLayoutCreateInfoNVX ) == sizeof( VkIndirectCommandsLayoutCreateInfoNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<IndirectCommandsLayoutCreateInfoNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct InitializePerformanceApiInfoINTEL
+ {
+ VULKAN_HPP_CONSTEXPR InitializePerformanceApiInfoINTEL( void* pUserData_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pUserData( pUserData_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::InitializePerformanceApiInfoINTEL & operator=( VULKAN_HPP_NAMESPACE::InitializePerformanceApiInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::InitializePerformanceApiInfoINTEL ) - offsetof( InitializePerformanceApiInfoINTEL, pNext ) );
+ return *this;
+ }
+
+ InitializePerformanceApiInfoINTEL( VkInitializePerformanceApiInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ InitializePerformanceApiInfoINTEL& operator=( VkInitializePerformanceApiInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::InitializePerformanceApiInfoINTEL const *>(&rhs);
+ return *this;
+ }
+
+ InitializePerformanceApiInfoINTEL & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ InitializePerformanceApiInfoINTEL & setPUserData( void* pUserData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pUserData = pUserData_;
+ return *this;
+ }
+
+ operator VkInitializePerformanceApiInfoINTEL const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkInitializePerformanceApiInfoINTEL*>( this );
+ }
+
+ operator VkInitializePerformanceApiInfoINTEL &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkInitializePerformanceApiInfoINTEL*>( this );
+ }
+
+ bool operator==( InitializePerformanceApiInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pUserData == rhs.pUserData );
+ }
+
+ bool operator!=( InitializePerformanceApiInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eInitializePerformanceApiInfoINTEL;
+ const void* pNext = {};
+ void* pUserData = {};
+ };
+ static_assert( sizeof( InitializePerformanceApiInfoINTEL ) == sizeof( VkInitializePerformanceApiInfoINTEL ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<InitializePerformanceApiInfoINTEL>::value, "struct wrapper is not a standard layout!" );
+
+ struct InputAttachmentAspectReference
+ {
+ VULKAN_HPP_CONSTEXPR InputAttachmentAspectReference( uint32_t subpass_ = {},
+ uint32_t inputAttachmentIndex_ = {},
+ VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ = {} ) VULKAN_HPP_NOEXCEPT
+ : subpass( subpass_ )
+ , inputAttachmentIndex( inputAttachmentIndex_ )
+ , aspectMask( aspectMask_ )
+ {}
+
+ InputAttachmentAspectReference( VkInputAttachmentAspectReference const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ InputAttachmentAspectReference& operator=( VkInputAttachmentAspectReference const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::InputAttachmentAspectReference const *>(&rhs);
+ return *this;
+ }
+
+ InputAttachmentAspectReference & setSubpass( uint32_t subpass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subpass = subpass_;
+ return *this;
+ }
+
+ InputAttachmentAspectReference & setInputAttachmentIndex( uint32_t inputAttachmentIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ inputAttachmentIndex = inputAttachmentIndex_;
+ return *this;
+ }
+
+ InputAttachmentAspectReference & setAspectMask( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ aspectMask = aspectMask_;
+ return *this;
+ }
+
+ operator VkInputAttachmentAspectReference const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkInputAttachmentAspectReference*>( this );
+ }
+
+ operator VkInputAttachmentAspectReference &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkInputAttachmentAspectReference*>( this );
+ }
+
+ bool operator==( InputAttachmentAspectReference const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( subpass == rhs.subpass )
+ && ( inputAttachmentIndex == rhs.inputAttachmentIndex )
+ && ( aspectMask == rhs.aspectMask );
+ }
+
+ bool operator!=( InputAttachmentAspectReference const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t subpass = {};
+ uint32_t inputAttachmentIndex = {};
+ VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask = {};
+ };
+ static_assert( sizeof( InputAttachmentAspectReference ) == sizeof( VkInputAttachmentAspectReference ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<InputAttachmentAspectReference>::value, "struct wrapper is not a standard layout!" );
+
+ struct InstanceCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR InstanceCreateInfo( VULKAN_HPP_NAMESPACE::InstanceCreateFlags flags_ = {},
+ const VULKAN_HPP_NAMESPACE::ApplicationInfo* pApplicationInfo_ = {},
+ uint32_t enabledLayerCount_ = {},
+ const char* const* ppEnabledLayerNames_ = {},
+ uint32_t enabledExtensionCount_ = {},
+ const char* const* ppEnabledExtensionNames_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , pApplicationInfo( pApplicationInfo_ )
+ , enabledLayerCount( enabledLayerCount_ )
+ , ppEnabledLayerNames( ppEnabledLayerNames_ )
+ , enabledExtensionCount( enabledExtensionCount_ )
+ , ppEnabledExtensionNames( ppEnabledExtensionNames_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::InstanceCreateInfo & operator=( VULKAN_HPP_NAMESPACE::InstanceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::InstanceCreateInfo ) - offsetof( InstanceCreateInfo, pNext ) );
+ return *this;
+ }
+
+ InstanceCreateInfo( VkInstanceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ InstanceCreateInfo& operator=( VkInstanceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::InstanceCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ InstanceCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ InstanceCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::InstanceCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ InstanceCreateInfo & setPApplicationInfo( const VULKAN_HPP_NAMESPACE::ApplicationInfo* pApplicationInfo_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pApplicationInfo = pApplicationInfo_;
+ return *this;
+ }
+
+ InstanceCreateInfo & setEnabledLayerCount( uint32_t enabledLayerCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ enabledLayerCount = enabledLayerCount_;
+ return *this;
+ }
+
+ InstanceCreateInfo & setPpEnabledLayerNames( const char* const* ppEnabledLayerNames_ ) VULKAN_HPP_NOEXCEPT
+ {
+ ppEnabledLayerNames = ppEnabledLayerNames_;
+ return *this;
+ }
+
+ InstanceCreateInfo & setEnabledExtensionCount( uint32_t enabledExtensionCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ enabledExtensionCount = enabledExtensionCount_;
+ return *this;
+ }
+
+ InstanceCreateInfo & setPpEnabledExtensionNames( const char* const* ppEnabledExtensionNames_ ) VULKAN_HPP_NOEXCEPT
+ {
+ ppEnabledExtensionNames = ppEnabledExtensionNames_;
+ return *this;
+ }
+
+ operator VkInstanceCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkInstanceCreateInfo*>( this );
+ }
+
+ operator VkInstanceCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkInstanceCreateInfo*>( this );
+ }
+
+ bool operator==( InstanceCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( pApplicationInfo == rhs.pApplicationInfo )
+ && ( enabledLayerCount == rhs.enabledLayerCount )
+ && ( ppEnabledLayerNames == rhs.ppEnabledLayerNames )
+ && ( enabledExtensionCount == rhs.enabledExtensionCount )
+ && ( ppEnabledExtensionNames == rhs.ppEnabledExtensionNames );
+ }
+
+ bool operator!=( InstanceCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eInstanceCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::InstanceCreateFlags flags = {};
+ const VULKAN_HPP_NAMESPACE::ApplicationInfo* pApplicationInfo = {};
+ uint32_t enabledLayerCount = {};
+ const char* const* ppEnabledLayerNames = {};
+ uint32_t enabledExtensionCount = {};
+ const char* const* ppEnabledExtensionNames = {};
+ };
+ static_assert( sizeof( InstanceCreateInfo ) == sizeof( VkInstanceCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<InstanceCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct LayerProperties
+ {
+ LayerProperties( std::array<char,VK_MAX_EXTENSION_NAME_SIZE> const& layerName_ = {},
+ uint32_t specVersion_ = {},
+ uint32_t implementationVersion_ = {},
+ std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {} ) VULKAN_HPP_NOEXCEPT
+ : layerName{}
+ , specVersion( specVersion_ )
+ , implementationVersion( implementationVersion_ )
+ , description{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE,VK_MAX_EXTENSION_NAME_SIZE>::copy( layerName, layerName_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
+ }
+
+ LayerProperties( VkLayerProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ LayerProperties& operator=( VkLayerProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::LayerProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkLayerProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkLayerProperties*>( this );
+ }
+
+ operator VkLayerProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkLayerProperties*>( this );
+ }
+
+ bool operator==( LayerProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( memcmp( layerName, rhs.layerName, VK_MAX_EXTENSION_NAME_SIZE * sizeof( char ) ) == 0 )
+ && ( specVersion == rhs.specVersion )
+ && ( implementationVersion == rhs.implementationVersion )
+ && ( memcmp( description, rhs.description, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 );
+ }
+
+ bool operator!=( LayerProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ char layerName[VK_MAX_EXTENSION_NAME_SIZE] = {};
+ uint32_t specVersion = {};
+ uint32_t implementationVersion = {};
+ char description[VK_MAX_DESCRIPTION_SIZE] = {};
+ };
+ static_assert( sizeof( LayerProperties ) == sizeof( VkLayerProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<LayerProperties>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+
+ struct MacOSSurfaceCreateInfoMVK
+ {
+ VULKAN_HPP_CONSTEXPR MacOSSurfaceCreateInfoMVK( VULKAN_HPP_NAMESPACE::MacOSSurfaceCreateFlagsMVK flags_ = {},
+ const void* pView_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , pView( pView_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MacOSSurfaceCreateInfoMVK & operator=( VULKAN_HPP_NAMESPACE::MacOSSurfaceCreateInfoMVK const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MacOSSurfaceCreateInfoMVK ) - offsetof( MacOSSurfaceCreateInfoMVK, pNext ) );
+ return *this;
+ }
+
+ MacOSSurfaceCreateInfoMVK( VkMacOSSurfaceCreateInfoMVK const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MacOSSurfaceCreateInfoMVK& operator=( VkMacOSSurfaceCreateInfoMVK const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MacOSSurfaceCreateInfoMVK const *>(&rhs);
+ return *this;
+ }
+
+ MacOSSurfaceCreateInfoMVK & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MacOSSurfaceCreateInfoMVK & setFlags( VULKAN_HPP_NAMESPACE::MacOSSurfaceCreateFlagsMVK flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ MacOSSurfaceCreateInfoMVK & setPView( const void* pView_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pView = pView_;
+ return *this;
+ }
+
+ operator VkMacOSSurfaceCreateInfoMVK const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMacOSSurfaceCreateInfoMVK*>( this );
+ }
+
+ operator VkMacOSSurfaceCreateInfoMVK &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMacOSSurfaceCreateInfoMVK*>( this );
+ }
+
+ bool operator==( MacOSSurfaceCreateInfoMVK const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( pView == rhs.pView );
+ }
+
+ bool operator!=( MacOSSurfaceCreateInfoMVK const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMacosSurfaceCreateInfoMVK;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::MacOSSurfaceCreateFlagsMVK flags = {};
+ const void* pView = {};
+ };
+ static_assert( sizeof( MacOSSurfaceCreateInfoMVK ) == sizeof( VkMacOSSurfaceCreateInfoMVK ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MacOSSurfaceCreateInfoMVK>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_MACOS_MVK*/
+
+ struct MappedMemoryRange
+ {
+ VULKAN_HPP_CONSTEXPR MappedMemoryRange( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize size_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memory( memory_ )
+ , offset( offset_ )
+ , size( size_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MappedMemoryRange & operator=( VULKAN_HPP_NAMESPACE::MappedMemoryRange const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MappedMemoryRange ) - offsetof( MappedMemoryRange, pNext ) );
+ return *this;
+ }
+
+ MappedMemoryRange( VkMappedMemoryRange const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MappedMemoryRange& operator=( VkMappedMemoryRange const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MappedMemoryRange const *>(&rhs);
+ return *this;
+ }
+
+ MappedMemoryRange & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MappedMemoryRange & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memory = memory_;
+ return *this;
+ }
+
+ MappedMemoryRange & setOffset( VULKAN_HPP_NAMESPACE::DeviceSize offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ MappedMemoryRange & setSize( VULKAN_HPP_NAMESPACE::DeviceSize size_ ) VULKAN_HPP_NOEXCEPT
+ {
+ size = size_;
+ return *this;
+ }
+
+ operator VkMappedMemoryRange const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMappedMemoryRange*>( this );
+ }
+
+ operator VkMappedMemoryRange &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMappedMemoryRange*>( this );
+ }
+
+ bool operator==( MappedMemoryRange const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memory == rhs.memory )
+ && ( offset == rhs.offset )
+ && ( size == rhs.size );
+ }
+
+ bool operator!=( MappedMemoryRange const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMappedMemoryRange;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize size = {};
+ };
+ static_assert( sizeof( MappedMemoryRange ) == sizeof( VkMappedMemoryRange ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MappedMemoryRange>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryAllocateFlagsInfo
+ {
+ VULKAN_HPP_CONSTEXPR MemoryAllocateFlagsInfo( VULKAN_HPP_NAMESPACE::MemoryAllocateFlags flags_ = {},
+ uint32_t deviceMask_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , deviceMask( deviceMask_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryAllocateFlagsInfo & operator=( VULKAN_HPP_NAMESPACE::MemoryAllocateFlagsInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryAllocateFlagsInfo ) - offsetof( MemoryAllocateFlagsInfo, pNext ) );
+ return *this;
+ }
+
+ MemoryAllocateFlagsInfo( VkMemoryAllocateFlagsInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryAllocateFlagsInfo& operator=( VkMemoryAllocateFlagsInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryAllocateFlagsInfo const *>(&rhs);
+ return *this;
+ }
+
+ MemoryAllocateFlagsInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MemoryAllocateFlagsInfo & setFlags( VULKAN_HPP_NAMESPACE::MemoryAllocateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ MemoryAllocateFlagsInfo & setDeviceMask( uint32_t deviceMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceMask = deviceMask_;
+ return *this;
+ }
+
+ operator VkMemoryAllocateFlagsInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryAllocateFlagsInfo*>( this );
+ }
+
+ operator VkMemoryAllocateFlagsInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryAllocateFlagsInfo*>( this );
+ }
+
+ bool operator==( MemoryAllocateFlagsInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( deviceMask == rhs.deviceMask );
+ }
+
+ bool operator!=( MemoryAllocateFlagsInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryAllocateFlagsInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::MemoryAllocateFlags flags = {};
+ uint32_t deviceMask = {};
+ };
+ static_assert( sizeof( MemoryAllocateFlagsInfo ) == sizeof( VkMemoryAllocateFlagsInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryAllocateFlagsInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryAllocateInfo
+ {
+ VULKAN_HPP_CONSTEXPR MemoryAllocateInfo( VULKAN_HPP_NAMESPACE::DeviceSize allocationSize_ = {},
+ uint32_t memoryTypeIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : allocationSize( allocationSize_ )
+ , memoryTypeIndex( memoryTypeIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryAllocateInfo & operator=( VULKAN_HPP_NAMESPACE::MemoryAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryAllocateInfo ) - offsetof( MemoryAllocateInfo, pNext ) );
+ return *this;
+ }
+
+ MemoryAllocateInfo( VkMemoryAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryAllocateInfo& operator=( VkMemoryAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryAllocateInfo const *>(&rhs);
+ return *this;
+ }
+
+ MemoryAllocateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MemoryAllocateInfo & setAllocationSize( VULKAN_HPP_NAMESPACE::DeviceSize allocationSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ allocationSize = allocationSize_;
+ return *this;
+ }
+
+ MemoryAllocateInfo & setMemoryTypeIndex( uint32_t memoryTypeIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memoryTypeIndex = memoryTypeIndex_;
+ return *this;
+ }
+
+ operator VkMemoryAllocateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryAllocateInfo*>( this );
+ }
+
+ operator VkMemoryAllocateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryAllocateInfo*>( this );
+ }
+
+ bool operator==( MemoryAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( allocationSize == rhs.allocationSize )
+ && ( memoryTypeIndex == rhs.memoryTypeIndex );
+ }
+
+ bool operator!=( MemoryAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryAllocateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize allocationSize = {};
+ uint32_t memoryTypeIndex = {};
+ };
+ static_assert( sizeof( MemoryAllocateInfo ) == sizeof( VkMemoryAllocateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryAllocateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryBarrier
+ {
+ VULKAN_HPP_CONSTEXPR MemoryBarrier( VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask_ = {},
+ VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcAccessMask( srcAccessMask_ )
+ , dstAccessMask( dstAccessMask_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryBarrier & operator=( VULKAN_HPP_NAMESPACE::MemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryBarrier ) - offsetof( MemoryBarrier, pNext ) );
+ return *this;
+ }
+
+ MemoryBarrier( VkMemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryBarrier& operator=( VkMemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryBarrier const *>(&rhs);
+ return *this;
+ }
+
+ MemoryBarrier & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MemoryBarrier & setSrcAccessMask( VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcAccessMask = srcAccessMask_;
+ return *this;
+ }
+
+ MemoryBarrier & setDstAccessMask( VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstAccessMask = dstAccessMask_;
+ return *this;
+ }
+
+ operator VkMemoryBarrier const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryBarrier*>( this );
+ }
+
+ operator VkMemoryBarrier &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryBarrier*>( this );
+ }
+
+ bool operator==( MemoryBarrier const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( srcAccessMask == rhs.srcAccessMask )
+ && ( dstAccessMask == rhs.dstAccessMask );
+ }
+
+ bool operator!=( MemoryBarrier const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryBarrier;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask = {};
+ VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask = {};
+ };
+ static_assert( sizeof( MemoryBarrier ) == sizeof( VkMemoryBarrier ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryBarrier>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryDedicatedAllocateInfo
+ {
+ VULKAN_HPP_CONSTEXPR MemoryDedicatedAllocateInfo( VULKAN_HPP_NAMESPACE::Image image_ = {},
+ VULKAN_HPP_NAMESPACE::Buffer buffer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : image( image_ )
+ , buffer( buffer_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryDedicatedAllocateInfo & operator=( VULKAN_HPP_NAMESPACE::MemoryDedicatedAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryDedicatedAllocateInfo ) - offsetof( MemoryDedicatedAllocateInfo, pNext ) );
+ return *this;
+ }
+
+ MemoryDedicatedAllocateInfo( VkMemoryDedicatedAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryDedicatedAllocateInfo& operator=( VkMemoryDedicatedAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryDedicatedAllocateInfo const *>(&rhs);
+ return *this;
+ }
+
+ MemoryDedicatedAllocateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MemoryDedicatedAllocateInfo & setImage( VULKAN_HPP_NAMESPACE::Image image_ ) VULKAN_HPP_NOEXCEPT
+ {
+ image = image_;
+ return *this;
+ }
+
+ MemoryDedicatedAllocateInfo & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ operator VkMemoryDedicatedAllocateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryDedicatedAllocateInfo*>( this );
+ }
+
+ operator VkMemoryDedicatedAllocateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryDedicatedAllocateInfo*>( this );
+ }
+
+ bool operator==( MemoryDedicatedAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( image == rhs.image )
+ && ( buffer == rhs.buffer );
+ }
+
+ bool operator!=( MemoryDedicatedAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryDedicatedAllocateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Image image = {};
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ };
+ static_assert( sizeof( MemoryDedicatedAllocateInfo ) == sizeof( VkMemoryDedicatedAllocateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryDedicatedAllocateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryDedicatedRequirements
+ {
+ MemoryDedicatedRequirements( VULKAN_HPP_NAMESPACE::Bool32 prefersDedicatedAllocation_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 requiresDedicatedAllocation_ = {} ) VULKAN_HPP_NOEXCEPT
+ : prefersDedicatedAllocation( prefersDedicatedAllocation_ )
+ , requiresDedicatedAllocation( requiresDedicatedAllocation_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryDedicatedRequirements & operator=( VULKAN_HPP_NAMESPACE::MemoryDedicatedRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryDedicatedRequirements ) - offsetof( MemoryDedicatedRequirements, pNext ) );
+ return *this;
+ }
+
+ MemoryDedicatedRequirements( VkMemoryDedicatedRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryDedicatedRequirements& operator=( VkMemoryDedicatedRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryDedicatedRequirements const *>(&rhs);
+ return *this;
+ }
+
+ operator VkMemoryDedicatedRequirements const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryDedicatedRequirements*>( this );
+ }
+
+ operator VkMemoryDedicatedRequirements &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryDedicatedRequirements*>( this );
+ }
+
+ bool operator==( MemoryDedicatedRequirements const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( prefersDedicatedAllocation == rhs.prefersDedicatedAllocation )
+ && ( requiresDedicatedAllocation == rhs.requiresDedicatedAllocation );
+ }
+
+ bool operator!=( MemoryDedicatedRequirements const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryDedicatedRequirements;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 prefersDedicatedAllocation = {};
+ VULKAN_HPP_NAMESPACE::Bool32 requiresDedicatedAllocation = {};
+ };
+ static_assert( sizeof( MemoryDedicatedRequirements ) == sizeof( VkMemoryDedicatedRequirements ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryDedicatedRequirements>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryFdPropertiesKHR
+ {
+ MemoryFdPropertiesKHR( uint32_t memoryTypeBits_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memoryTypeBits( memoryTypeBits_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryFdPropertiesKHR & operator=( VULKAN_HPP_NAMESPACE::MemoryFdPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryFdPropertiesKHR ) - offsetof( MemoryFdPropertiesKHR, pNext ) );
+ return *this;
+ }
+
+ MemoryFdPropertiesKHR( VkMemoryFdPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryFdPropertiesKHR& operator=( VkMemoryFdPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryFdPropertiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkMemoryFdPropertiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryFdPropertiesKHR*>( this );
+ }
+
+ operator VkMemoryFdPropertiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryFdPropertiesKHR*>( this );
+ }
+
+ bool operator==( MemoryFdPropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memoryTypeBits == rhs.memoryTypeBits );
+ }
+
+ bool operator!=( MemoryFdPropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryFdPropertiesKHR;
+ void* pNext = {};
+ uint32_t memoryTypeBits = {};
+ };
+ static_assert( sizeof( MemoryFdPropertiesKHR ) == sizeof( VkMemoryFdPropertiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryFdPropertiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+
+ struct MemoryGetAndroidHardwareBufferInfoANDROID
+ {
+ VULKAN_HPP_CONSTEXPR MemoryGetAndroidHardwareBufferInfoANDROID( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memory( memory_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryGetAndroidHardwareBufferInfoANDROID & operator=( VULKAN_HPP_NAMESPACE::MemoryGetAndroidHardwareBufferInfoANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryGetAndroidHardwareBufferInfoANDROID ) - offsetof( MemoryGetAndroidHardwareBufferInfoANDROID, pNext ) );
+ return *this;
+ }
+
+ MemoryGetAndroidHardwareBufferInfoANDROID( VkMemoryGetAndroidHardwareBufferInfoANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryGetAndroidHardwareBufferInfoANDROID& operator=( VkMemoryGetAndroidHardwareBufferInfoANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryGetAndroidHardwareBufferInfoANDROID const *>(&rhs);
+ return *this;
+ }
+
+ MemoryGetAndroidHardwareBufferInfoANDROID & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MemoryGetAndroidHardwareBufferInfoANDROID & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memory = memory_;
+ return *this;
+ }
+
+ operator VkMemoryGetAndroidHardwareBufferInfoANDROID const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryGetAndroidHardwareBufferInfoANDROID*>( this );
+ }
+
+ operator VkMemoryGetAndroidHardwareBufferInfoANDROID &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryGetAndroidHardwareBufferInfoANDROID*>( this );
+ }
+
+ bool operator==( MemoryGetAndroidHardwareBufferInfoANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memory == rhs.memory );
+ }
+
+ bool operator!=( MemoryGetAndroidHardwareBufferInfoANDROID const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryGetAndroidHardwareBufferInfoANDROID;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
+ };
+ static_assert( sizeof( MemoryGetAndroidHardwareBufferInfoANDROID ) == sizeof( VkMemoryGetAndroidHardwareBufferInfoANDROID ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryGetAndroidHardwareBufferInfoANDROID>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ struct MemoryGetFdInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR MemoryGetFdInfoKHR( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd ) VULKAN_HPP_NOEXCEPT
+ : memory( memory_ )
+ , handleType( handleType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryGetFdInfoKHR & operator=( VULKAN_HPP_NAMESPACE::MemoryGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryGetFdInfoKHR ) - offsetof( MemoryGetFdInfoKHR, pNext ) );
+ return *this;
+ }
+
+ MemoryGetFdInfoKHR( VkMemoryGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryGetFdInfoKHR& operator=( VkMemoryGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryGetFdInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ MemoryGetFdInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MemoryGetFdInfoKHR & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memory = memory_;
+ return *this;
+ }
+
+ MemoryGetFdInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ operator VkMemoryGetFdInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryGetFdInfoKHR*>( this );
+ }
+
+ operator VkMemoryGetFdInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryGetFdInfoKHR*>( this );
+ }
+
+ bool operator==( MemoryGetFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memory == rhs.memory )
+ && ( handleType == rhs.handleType );
+ }
+
+ bool operator!=( MemoryGetFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryGetFdInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd;
+ };
+ static_assert( sizeof( MemoryGetFdInfoKHR ) == sizeof( VkMemoryGetFdInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryGetFdInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct MemoryGetWin32HandleInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR MemoryGetWin32HandleInfoKHR( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd ) VULKAN_HPP_NOEXCEPT
+ : memory( memory_ )
+ , handleType( handleType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryGetWin32HandleInfoKHR & operator=( VULKAN_HPP_NAMESPACE::MemoryGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryGetWin32HandleInfoKHR ) - offsetof( MemoryGetWin32HandleInfoKHR, pNext ) );
+ return *this;
+ }
+
+ MemoryGetWin32HandleInfoKHR( VkMemoryGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryGetWin32HandleInfoKHR& operator=( VkMemoryGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryGetWin32HandleInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ MemoryGetWin32HandleInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MemoryGetWin32HandleInfoKHR & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memory = memory_;
+ return *this;
+ }
+
+ MemoryGetWin32HandleInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ operator VkMemoryGetWin32HandleInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryGetWin32HandleInfoKHR*>( this );
+ }
+
+ operator VkMemoryGetWin32HandleInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryGetWin32HandleInfoKHR*>( this );
+ }
+
+ bool operator==( MemoryGetWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memory == rhs.memory )
+ && ( handleType == rhs.handleType );
+ }
+
+ bool operator!=( MemoryGetWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryGetWin32HandleInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd;
+ };
+ static_assert( sizeof( MemoryGetWin32HandleInfoKHR ) == sizeof( VkMemoryGetWin32HandleInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryGetWin32HandleInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct MemoryHeap
+ {
+ MemoryHeap( VULKAN_HPP_NAMESPACE::DeviceSize size_ = {},
+ VULKAN_HPP_NAMESPACE::MemoryHeapFlags flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : size( size_ )
+ , flags( flags_ )
+ {}
+
+ MemoryHeap( VkMemoryHeap const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryHeap& operator=( VkMemoryHeap const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryHeap const *>(&rhs);
+ return *this;
+ }
+
+ operator VkMemoryHeap const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryHeap*>( this );
+ }
+
+ operator VkMemoryHeap &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryHeap*>( this );
+ }
+
+ bool operator==( MemoryHeap const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( size == rhs.size )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( MemoryHeap const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DeviceSize size = {};
+ VULKAN_HPP_NAMESPACE::MemoryHeapFlags flags = {};
+ };
+ static_assert( sizeof( MemoryHeap ) == sizeof( VkMemoryHeap ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryHeap>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryHostPointerPropertiesEXT
+ {
+ MemoryHostPointerPropertiesEXT( uint32_t memoryTypeBits_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memoryTypeBits( memoryTypeBits_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryHostPointerPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::MemoryHostPointerPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryHostPointerPropertiesEXT ) - offsetof( MemoryHostPointerPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ MemoryHostPointerPropertiesEXT( VkMemoryHostPointerPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryHostPointerPropertiesEXT& operator=( VkMemoryHostPointerPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryHostPointerPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkMemoryHostPointerPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryHostPointerPropertiesEXT*>( this );
+ }
+
+ operator VkMemoryHostPointerPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryHostPointerPropertiesEXT*>( this );
+ }
+
+ bool operator==( MemoryHostPointerPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memoryTypeBits == rhs.memoryTypeBits );
+ }
+
+ bool operator!=( MemoryHostPointerPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryHostPointerPropertiesEXT;
+ void* pNext = {};
+ uint32_t memoryTypeBits = {};
+ };
+ static_assert( sizeof( MemoryHostPointerPropertiesEXT ) == sizeof( VkMemoryHostPointerPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryHostPointerPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryOpaqueCaptureAddressAllocateInfo
+ {
+ VULKAN_HPP_CONSTEXPR MemoryOpaqueCaptureAddressAllocateInfo( uint64_t opaqueCaptureAddress_ = {} ) VULKAN_HPP_NOEXCEPT
+ : opaqueCaptureAddress( opaqueCaptureAddress_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryOpaqueCaptureAddressAllocateInfo & operator=( VULKAN_HPP_NAMESPACE::MemoryOpaqueCaptureAddressAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryOpaqueCaptureAddressAllocateInfo ) - offsetof( MemoryOpaqueCaptureAddressAllocateInfo, pNext ) );
+ return *this;
+ }
+
+ MemoryOpaqueCaptureAddressAllocateInfo( VkMemoryOpaqueCaptureAddressAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryOpaqueCaptureAddressAllocateInfo& operator=( VkMemoryOpaqueCaptureAddressAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryOpaqueCaptureAddressAllocateInfo const *>(&rhs);
+ return *this;
+ }
+
+ MemoryOpaqueCaptureAddressAllocateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MemoryOpaqueCaptureAddressAllocateInfo & setOpaqueCaptureAddress( uint64_t opaqueCaptureAddress_ ) VULKAN_HPP_NOEXCEPT
+ {
+ opaqueCaptureAddress = opaqueCaptureAddress_;
+ return *this;
+ }
+
+ operator VkMemoryOpaqueCaptureAddressAllocateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryOpaqueCaptureAddressAllocateInfo*>( this );
+ }
+
+ operator VkMemoryOpaqueCaptureAddressAllocateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryOpaqueCaptureAddressAllocateInfo*>( this );
+ }
+
+ bool operator==( MemoryOpaqueCaptureAddressAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( opaqueCaptureAddress == rhs.opaqueCaptureAddress );
+ }
+
+ bool operator!=( MemoryOpaqueCaptureAddressAllocateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryOpaqueCaptureAddressAllocateInfo;
+ const void* pNext = {};
+ uint64_t opaqueCaptureAddress = {};
+ };
+ static_assert( sizeof( MemoryOpaqueCaptureAddressAllocateInfo ) == sizeof( VkMemoryOpaqueCaptureAddressAllocateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryOpaqueCaptureAddressAllocateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryPriorityAllocateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR MemoryPriorityAllocateInfoEXT( float priority_ = {} ) VULKAN_HPP_NOEXCEPT
+ : priority( priority_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryPriorityAllocateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::MemoryPriorityAllocateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryPriorityAllocateInfoEXT ) - offsetof( MemoryPriorityAllocateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ MemoryPriorityAllocateInfoEXT( VkMemoryPriorityAllocateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryPriorityAllocateInfoEXT& operator=( VkMemoryPriorityAllocateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryPriorityAllocateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ MemoryPriorityAllocateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MemoryPriorityAllocateInfoEXT & setPriority( float priority_ ) VULKAN_HPP_NOEXCEPT
+ {
+ priority = priority_;
+ return *this;
+ }
+
+ operator VkMemoryPriorityAllocateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryPriorityAllocateInfoEXT*>( this );
+ }
+
+ operator VkMemoryPriorityAllocateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryPriorityAllocateInfoEXT*>( this );
+ }
+
+ bool operator==( MemoryPriorityAllocateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( priority == rhs.priority );
+ }
+
+ bool operator!=( MemoryPriorityAllocateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryPriorityAllocateInfoEXT;
+ const void* pNext = {};
+ float priority = {};
+ };
+ static_assert( sizeof( MemoryPriorityAllocateInfoEXT ) == sizeof( VkMemoryPriorityAllocateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryPriorityAllocateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryRequirements
+ {
+ MemoryRequirements( VULKAN_HPP_NAMESPACE::DeviceSize size_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize alignment_ = {},
+ uint32_t memoryTypeBits_ = {} ) VULKAN_HPP_NOEXCEPT
+ : size( size_ )
+ , alignment( alignment_ )
+ , memoryTypeBits( memoryTypeBits_ )
+ {}
+
+ MemoryRequirements( VkMemoryRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryRequirements& operator=( VkMemoryRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryRequirements const *>(&rhs);
+ return *this;
+ }
+
+ operator VkMemoryRequirements const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryRequirements*>( this );
+ }
+
+ operator VkMemoryRequirements &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryRequirements*>( this );
+ }
+
+ bool operator==( MemoryRequirements const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( size == rhs.size )
+ && ( alignment == rhs.alignment )
+ && ( memoryTypeBits == rhs.memoryTypeBits );
+ }
+
+ bool operator!=( MemoryRequirements const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::DeviceSize size = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize alignment = {};
+ uint32_t memoryTypeBits = {};
+ };
+ static_assert( sizeof( MemoryRequirements ) == sizeof( VkMemoryRequirements ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryRequirements>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryRequirements2
+ {
+ MemoryRequirements2( VULKAN_HPP_NAMESPACE::MemoryRequirements memoryRequirements_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memoryRequirements( memoryRequirements_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2 & operator=( VULKAN_HPP_NAMESPACE::MemoryRequirements2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryRequirements2 ) - offsetof( MemoryRequirements2, pNext ) );
+ return *this;
+ }
+
+ MemoryRequirements2( VkMemoryRequirements2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryRequirements2& operator=( VkMemoryRequirements2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryRequirements2 const *>(&rhs);
+ return *this;
+ }
+
+ operator VkMemoryRequirements2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryRequirements2*>( this );
+ }
+
+ operator VkMemoryRequirements2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryRequirements2*>( this );
+ }
+
+ bool operator==( MemoryRequirements2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memoryRequirements == rhs.memoryRequirements );
+ }
+
+ bool operator!=( MemoryRequirements2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryRequirements2;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::MemoryRequirements memoryRequirements = {};
+ };
+ static_assert( sizeof( MemoryRequirements2 ) == sizeof( VkMemoryRequirements2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryRequirements2>::value, "struct wrapper is not a standard layout!" );
+
+ struct MemoryType
+ {
+ MemoryType( VULKAN_HPP_NAMESPACE::MemoryPropertyFlags propertyFlags_ = {},
+ uint32_t heapIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : propertyFlags( propertyFlags_ )
+ , heapIndex( heapIndex_ )
+ {}
+
+ MemoryType( VkMemoryType const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryType& operator=( VkMemoryType const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryType const *>(&rhs);
+ return *this;
+ }
+
+ operator VkMemoryType const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryType*>( this );
+ }
+
+ operator VkMemoryType &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryType*>( this );
+ }
+
+ bool operator==( MemoryType const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( propertyFlags == rhs.propertyFlags )
+ && ( heapIndex == rhs.heapIndex );
+ }
+
+ bool operator!=( MemoryType const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::MemoryPropertyFlags propertyFlags = {};
+ uint32_t heapIndex = {};
+ };
+ static_assert( sizeof( MemoryType ) == sizeof( VkMemoryType ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryType>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct MemoryWin32HandlePropertiesKHR
+ {
+ MemoryWin32HandlePropertiesKHR( uint32_t memoryTypeBits_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memoryTypeBits( memoryTypeBits_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MemoryWin32HandlePropertiesKHR & operator=( VULKAN_HPP_NAMESPACE::MemoryWin32HandlePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MemoryWin32HandlePropertiesKHR ) - offsetof( MemoryWin32HandlePropertiesKHR, pNext ) );
+ return *this;
+ }
+
+ MemoryWin32HandlePropertiesKHR( VkMemoryWin32HandlePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MemoryWin32HandlePropertiesKHR& operator=( VkMemoryWin32HandlePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MemoryWin32HandlePropertiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkMemoryWin32HandlePropertiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMemoryWin32HandlePropertiesKHR*>( this );
+ }
+
+ operator VkMemoryWin32HandlePropertiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMemoryWin32HandlePropertiesKHR*>( this );
+ }
+
+ bool operator==( MemoryWin32HandlePropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memoryTypeBits == rhs.memoryTypeBits );
+ }
+
+ bool operator!=( MemoryWin32HandlePropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMemoryWin32HandlePropertiesKHR;
+ void* pNext = {};
+ uint32_t memoryTypeBits = {};
+ };
+ static_assert( sizeof( MemoryWin32HandlePropertiesKHR ) == sizeof( VkMemoryWin32HandlePropertiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MemoryWin32HandlePropertiesKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_METAL_EXT
+
+ struct MetalSurfaceCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR MetalSurfaceCreateInfoEXT( VULKAN_HPP_NAMESPACE::MetalSurfaceCreateFlagsEXT flags_ = {},
+ const CAMetalLayer* pLayer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , pLayer( pLayer_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MetalSurfaceCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::MetalSurfaceCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MetalSurfaceCreateInfoEXT ) - offsetof( MetalSurfaceCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ MetalSurfaceCreateInfoEXT( VkMetalSurfaceCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MetalSurfaceCreateInfoEXT& operator=( VkMetalSurfaceCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MetalSurfaceCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ MetalSurfaceCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ MetalSurfaceCreateInfoEXT & setFlags( VULKAN_HPP_NAMESPACE::MetalSurfaceCreateFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ MetalSurfaceCreateInfoEXT & setPLayer( const CAMetalLayer* pLayer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pLayer = pLayer_;
+ return *this;
+ }
+
+ operator VkMetalSurfaceCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMetalSurfaceCreateInfoEXT*>( this );
+ }
+
+ operator VkMetalSurfaceCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMetalSurfaceCreateInfoEXT*>( this );
+ }
+
+ bool operator==( MetalSurfaceCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( pLayer == rhs.pLayer );
+ }
+
+ bool operator!=( MetalSurfaceCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMetalSurfaceCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::MetalSurfaceCreateFlagsEXT flags = {};
+ const CAMetalLayer* pLayer = {};
+ };
+ static_assert( sizeof( MetalSurfaceCreateInfoEXT ) == sizeof( VkMetalSurfaceCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MetalSurfaceCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_METAL_EXT*/
+
+ struct MultisamplePropertiesEXT
+ {
+ MultisamplePropertiesEXT( VULKAN_HPP_NAMESPACE::Extent2D maxSampleLocationGridSize_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxSampleLocationGridSize( maxSampleLocationGridSize_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::MultisamplePropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::MultisamplePropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::MultisamplePropertiesEXT ) - offsetof( MultisamplePropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ MultisamplePropertiesEXT( VkMultisamplePropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ MultisamplePropertiesEXT& operator=( VkMultisamplePropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::MultisamplePropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkMultisamplePropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkMultisamplePropertiesEXT*>( this );
+ }
+
+ operator VkMultisamplePropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkMultisamplePropertiesEXT*>( this );
+ }
+
+ bool operator==( MultisamplePropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxSampleLocationGridSize == rhs.maxSampleLocationGridSize );
+ }
+
+ bool operator!=( MultisamplePropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eMultisamplePropertiesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Extent2D maxSampleLocationGridSize = {};
+ };
+ static_assert( sizeof( MultisamplePropertiesEXT ) == sizeof( VkMultisamplePropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<MultisamplePropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct ObjectTableCreateInfoNVX
+ {
+ VULKAN_HPP_CONSTEXPR ObjectTableCreateInfoNVX( uint32_t objectCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX* pObjectEntryTypes_ = {},
+ const uint32_t* pObjectEntryCounts_ = {},
+ const VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags_ = {},
+ uint32_t maxUniformBuffersPerDescriptor_ = {},
+ uint32_t maxStorageBuffersPerDescriptor_ = {},
+ uint32_t maxStorageImagesPerDescriptor_ = {},
+ uint32_t maxSampledImagesPerDescriptor_ = {},
+ uint32_t maxPipelineLayouts_ = {} ) VULKAN_HPP_NOEXCEPT
+ : objectCount( objectCount_ )
+ , pObjectEntryTypes( pObjectEntryTypes_ )
+ , pObjectEntryCounts( pObjectEntryCounts_ )
+ , pObjectEntryUsageFlags( pObjectEntryUsageFlags_ )
+ , maxUniformBuffersPerDescriptor( maxUniformBuffersPerDescriptor_ )
+ , maxStorageBuffersPerDescriptor( maxStorageBuffersPerDescriptor_ )
+ , maxStorageImagesPerDescriptor( maxStorageImagesPerDescriptor_ )
+ , maxSampledImagesPerDescriptor( maxSampledImagesPerDescriptor_ )
+ , maxPipelineLayouts( maxPipelineLayouts_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ObjectTableCreateInfoNVX & operator=( VULKAN_HPP_NAMESPACE::ObjectTableCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ObjectTableCreateInfoNVX ) - offsetof( ObjectTableCreateInfoNVX, pNext ) );
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX( VkObjectTableCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ObjectTableCreateInfoNVX& operator=( VkObjectTableCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTableCreateInfoNVX const *>(&rhs);
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX & setObjectCount( uint32_t objectCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ objectCount = objectCount_;
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX & setPObjectEntryTypes( const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX* pObjectEntryTypes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pObjectEntryTypes = pObjectEntryTypes_;
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX & setPObjectEntryCounts( const uint32_t* pObjectEntryCounts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pObjectEntryCounts = pObjectEntryCounts_;
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX & setPObjectEntryUsageFlags( const VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pObjectEntryUsageFlags = pObjectEntryUsageFlags_;
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX & setMaxUniformBuffersPerDescriptor( uint32_t maxUniformBuffersPerDescriptor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxUniformBuffersPerDescriptor = maxUniformBuffersPerDescriptor_;
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX & setMaxStorageBuffersPerDescriptor( uint32_t maxStorageBuffersPerDescriptor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxStorageBuffersPerDescriptor = maxStorageBuffersPerDescriptor_;
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX & setMaxStorageImagesPerDescriptor( uint32_t maxStorageImagesPerDescriptor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxStorageImagesPerDescriptor = maxStorageImagesPerDescriptor_;
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX & setMaxSampledImagesPerDescriptor( uint32_t maxSampledImagesPerDescriptor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxSampledImagesPerDescriptor = maxSampledImagesPerDescriptor_;
+ return *this;
+ }
+
+ ObjectTableCreateInfoNVX & setMaxPipelineLayouts( uint32_t maxPipelineLayouts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxPipelineLayouts = maxPipelineLayouts_;
+ return *this;
+ }
+
+ operator VkObjectTableCreateInfoNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkObjectTableCreateInfoNVX*>( this );
+ }
+
+ operator VkObjectTableCreateInfoNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkObjectTableCreateInfoNVX*>( this );
+ }
+
+ bool operator==( ObjectTableCreateInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( objectCount == rhs.objectCount )
+ && ( pObjectEntryTypes == rhs.pObjectEntryTypes )
+ && ( pObjectEntryCounts == rhs.pObjectEntryCounts )
+ && ( pObjectEntryUsageFlags == rhs.pObjectEntryUsageFlags )
+ && ( maxUniformBuffersPerDescriptor == rhs.maxUniformBuffersPerDescriptor )
+ && ( maxStorageBuffersPerDescriptor == rhs.maxStorageBuffersPerDescriptor )
+ && ( maxStorageImagesPerDescriptor == rhs.maxStorageImagesPerDescriptor )
+ && ( maxSampledImagesPerDescriptor == rhs.maxSampledImagesPerDescriptor )
+ && ( maxPipelineLayouts == rhs.maxPipelineLayouts );
+ }
+
+ bool operator!=( ObjectTableCreateInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eObjectTableCreateInfoNVX;
+ const void* pNext = {};
+ uint32_t objectCount = {};
+ const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX* pObjectEntryTypes = {};
+ const uint32_t* pObjectEntryCounts = {};
+ const VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags = {};
+ uint32_t maxUniformBuffersPerDescriptor = {};
+ uint32_t maxStorageBuffersPerDescriptor = {};
+ uint32_t maxStorageImagesPerDescriptor = {};
+ uint32_t maxSampledImagesPerDescriptor = {};
+ uint32_t maxPipelineLayouts = {};
+ };
+ static_assert( sizeof( ObjectTableCreateInfoNVX ) == sizeof( VkObjectTableCreateInfoNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ObjectTableCreateInfoNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct ObjectTableEntryNVX
+ {
+ VULKAN_HPP_CONSTEXPR ObjectTableEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , flags( flags_ )
+ {}
+
+ ObjectTableEntryNVX( VkObjectTableEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ObjectTableEntryNVX& operator=( VkObjectTableEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTableEntryNVX const *>(&rhs);
+ return *this;
+ }
+
+ ObjectTableEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ ObjectTableEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ operator VkObjectTableEntryNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkObjectTableEntryNVX*>( this );
+ }
+
+ operator VkObjectTableEntryNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkObjectTableEntryNVX*>( this );
+ }
+
+ bool operator==( ObjectTableEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( type == rhs.type )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( ObjectTableEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
+ };
+ static_assert( sizeof( ObjectTableEntryNVX ) == sizeof( VkObjectTableEntryNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ObjectTableEntryNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct ObjectTableDescriptorSetEntryNVX
+ {
+ VULKAN_HPP_CONSTEXPR ObjectTableDescriptorSetEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ = {},
+ VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , flags( flags_ )
+ , pipelineLayout( pipelineLayout_ )
+ , descriptorSet( descriptorSet_ )
+ {}
+
+ explicit ObjectTableDescriptorSetEntryNVX( ObjectTableEntryNVX const& objectTableEntryNVX,
+ VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ = {},
+ VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet_ = {} )
+ : type( objectTableEntryNVX.type )
+ , flags( objectTableEntryNVX.flags )
+ , pipelineLayout( pipelineLayout_ )
+ , descriptorSet( descriptorSet_ )
+ {}
+
+ ObjectTableDescriptorSetEntryNVX( VkObjectTableDescriptorSetEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ObjectTableDescriptorSetEntryNVX& operator=( VkObjectTableDescriptorSetEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTableDescriptorSetEntryNVX const *>(&rhs);
+ return *this;
+ }
+
+ ObjectTableDescriptorSetEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ ObjectTableDescriptorSetEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ObjectTableDescriptorSetEntryNVX & setPipelineLayout( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineLayout = pipelineLayout_;
+ return *this;
+ }
+
+ ObjectTableDescriptorSetEntryNVX & setDescriptorSet( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorSet = descriptorSet_;
+ return *this;
+ }
+
+ operator VkObjectTableDescriptorSetEntryNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkObjectTableDescriptorSetEntryNVX*>( this );
+ }
+
+ operator VkObjectTableDescriptorSetEntryNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkObjectTableDescriptorSetEntryNVX*>( this );
+ }
+
+ bool operator==( ObjectTableDescriptorSetEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( type == rhs.type )
+ && ( flags == rhs.flags )
+ && ( pipelineLayout == rhs.pipelineLayout )
+ && ( descriptorSet == rhs.descriptorSet );
+ }
+
+ bool operator!=( ObjectTableDescriptorSetEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
+ VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout = {};
+ VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet = {};
+ };
+ static_assert( sizeof( ObjectTableDescriptorSetEntryNVX ) == sizeof( VkObjectTableDescriptorSetEntryNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ObjectTableDescriptorSetEntryNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct ObjectTableIndexBufferEntryNVX
+ {
+ VULKAN_HPP_CONSTEXPR ObjectTableIndexBufferEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {},
+ VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+ VULKAN_HPP_NAMESPACE::IndexType indexType_ = VULKAN_HPP_NAMESPACE::IndexType::eUint16 ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , flags( flags_ )
+ , buffer( buffer_ )
+ , indexType( indexType_ )
+ {}
+
+ explicit ObjectTableIndexBufferEntryNVX( ObjectTableEntryNVX const& objectTableEntryNVX,
+ VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+ VULKAN_HPP_NAMESPACE::IndexType indexType_ = VULKAN_HPP_NAMESPACE::IndexType::eUint16 )
+ : type( objectTableEntryNVX.type )
+ , flags( objectTableEntryNVX.flags )
+ , buffer( buffer_ )
+ , indexType( indexType_ )
+ {}
+
+ ObjectTableIndexBufferEntryNVX( VkObjectTableIndexBufferEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ObjectTableIndexBufferEntryNVX& operator=( VkObjectTableIndexBufferEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTableIndexBufferEntryNVX const *>(&rhs);
+ return *this;
+ }
+
+ ObjectTableIndexBufferEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ ObjectTableIndexBufferEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ObjectTableIndexBufferEntryNVX & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ ObjectTableIndexBufferEntryNVX & setIndexType( VULKAN_HPP_NAMESPACE::IndexType indexType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ indexType = indexType_;
+ return *this;
+ }
+
+ operator VkObjectTableIndexBufferEntryNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkObjectTableIndexBufferEntryNVX*>( this );
+ }
+
+ operator VkObjectTableIndexBufferEntryNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkObjectTableIndexBufferEntryNVX*>( this );
+ }
+
+ bool operator==( ObjectTableIndexBufferEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( type == rhs.type )
+ && ( flags == rhs.flags )
+ && ( buffer == rhs.buffer )
+ && ( indexType == rhs.indexType );
+ }
+
+ bool operator!=( ObjectTableIndexBufferEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ VULKAN_HPP_NAMESPACE::IndexType indexType = VULKAN_HPP_NAMESPACE::IndexType::eUint16;
+ };
+ static_assert( sizeof( ObjectTableIndexBufferEntryNVX ) == sizeof( VkObjectTableIndexBufferEntryNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ObjectTableIndexBufferEntryNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct ObjectTablePipelineEntryNVX
+ {
+ VULKAN_HPP_CONSTEXPR ObjectTablePipelineEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {},
+ VULKAN_HPP_NAMESPACE::Pipeline pipeline_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , flags( flags_ )
+ , pipeline( pipeline_ )
+ {}
+
+ explicit ObjectTablePipelineEntryNVX( ObjectTableEntryNVX const& objectTableEntryNVX,
+ VULKAN_HPP_NAMESPACE::Pipeline pipeline_ = {} )
+ : type( objectTableEntryNVX.type )
+ , flags( objectTableEntryNVX.flags )
+ , pipeline( pipeline_ )
+ {}
+
+ ObjectTablePipelineEntryNVX( VkObjectTablePipelineEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ObjectTablePipelineEntryNVX& operator=( VkObjectTablePipelineEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTablePipelineEntryNVX const *>(&rhs);
+ return *this;
+ }
+
+ ObjectTablePipelineEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ ObjectTablePipelineEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ObjectTablePipelineEntryNVX & setPipeline( VULKAN_HPP_NAMESPACE::Pipeline pipeline_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipeline = pipeline_;
+ return *this;
+ }
+
+ operator VkObjectTablePipelineEntryNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkObjectTablePipelineEntryNVX*>( this );
+ }
+
+ operator VkObjectTablePipelineEntryNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkObjectTablePipelineEntryNVX*>( this );
+ }
+
+ bool operator==( ObjectTablePipelineEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( type == rhs.type )
+ && ( flags == rhs.flags )
+ && ( pipeline == rhs.pipeline );
+ }
+
+ bool operator!=( ObjectTablePipelineEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
+ VULKAN_HPP_NAMESPACE::Pipeline pipeline = {};
+ };
+ static_assert( sizeof( ObjectTablePipelineEntryNVX ) == sizeof( VkObjectTablePipelineEntryNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ObjectTablePipelineEntryNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct ObjectTablePushConstantEntryNVX
+ {
+ VULKAN_HPP_CONSTEXPR ObjectTablePushConstantEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ = {},
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , flags( flags_ )
+ , pipelineLayout( pipelineLayout_ )
+ , stageFlags( stageFlags_ )
+ {}
+
+ explicit ObjectTablePushConstantEntryNVX( ObjectTableEntryNVX const& objectTableEntryNVX,
+ VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ = {},
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags_ = {} )
+ : type( objectTableEntryNVX.type )
+ , flags( objectTableEntryNVX.flags )
+ , pipelineLayout( pipelineLayout_ )
+ , stageFlags( stageFlags_ )
+ {}
+
+ ObjectTablePushConstantEntryNVX( VkObjectTablePushConstantEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ObjectTablePushConstantEntryNVX& operator=( VkObjectTablePushConstantEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTablePushConstantEntryNVX const *>(&rhs);
+ return *this;
+ }
+
+ ObjectTablePushConstantEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ ObjectTablePushConstantEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ObjectTablePushConstantEntryNVX & setPipelineLayout( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineLayout = pipelineLayout_;
+ return *this;
+ }
+
+ ObjectTablePushConstantEntryNVX & setStageFlags( VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stageFlags = stageFlags_;
+ return *this;
+ }
+
+ operator VkObjectTablePushConstantEntryNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkObjectTablePushConstantEntryNVX*>( this );
+ }
+
+ operator VkObjectTablePushConstantEntryNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkObjectTablePushConstantEntryNVX*>( this );
+ }
+
+ bool operator==( ObjectTablePushConstantEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( type == rhs.type )
+ && ( flags == rhs.flags )
+ && ( pipelineLayout == rhs.pipelineLayout )
+ && ( stageFlags == rhs.stageFlags );
+ }
+
+ bool operator!=( ObjectTablePushConstantEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
+ VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout = {};
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags = {};
+ };
+ static_assert( sizeof( ObjectTablePushConstantEntryNVX ) == sizeof( VkObjectTablePushConstantEntryNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ObjectTablePushConstantEntryNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct ObjectTableVertexBufferEntryNVX
+ {
+ VULKAN_HPP_CONSTEXPR ObjectTableVertexBufferEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {},
+ VULKAN_HPP_NAMESPACE::Buffer buffer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , flags( flags_ )
+ , buffer( buffer_ )
+ {}
+
+ explicit ObjectTableVertexBufferEntryNVX( ObjectTableEntryNVX const& objectTableEntryNVX,
+ VULKAN_HPP_NAMESPACE::Buffer buffer_ = {} )
+ : type( objectTableEntryNVX.type )
+ , flags( objectTableEntryNVX.flags )
+ , buffer( buffer_ )
+ {}
+
+ ObjectTableVertexBufferEntryNVX( VkObjectTableVertexBufferEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ObjectTableVertexBufferEntryNVX& operator=( VkObjectTableVertexBufferEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTableVertexBufferEntryNVX const *>(&rhs);
+ return *this;
+ }
+
+ ObjectTableVertexBufferEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ ObjectTableVertexBufferEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ObjectTableVertexBufferEntryNVX & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ buffer = buffer_;
+ return *this;
+ }
+
+ operator VkObjectTableVertexBufferEntryNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkObjectTableVertexBufferEntryNVX*>( this );
+ }
+
+ operator VkObjectTableVertexBufferEntryNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkObjectTableVertexBufferEntryNVX*>( this );
+ }
+
+ bool operator==( ObjectTableVertexBufferEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( type == rhs.type )
+ && ( flags == rhs.flags )
+ && ( buffer == rhs.buffer );
+ }
+
+ bool operator!=( ObjectTableVertexBufferEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
+ VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
+ VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+ };
+ static_assert( sizeof( ObjectTableVertexBufferEntryNVX ) == sizeof( VkObjectTableVertexBufferEntryNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ObjectTableVertexBufferEntryNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct PastPresentationTimingGOOGLE
+ {
+ PastPresentationTimingGOOGLE( uint32_t presentID_ = {},
+ uint64_t desiredPresentTime_ = {},
+ uint64_t actualPresentTime_ = {},
+ uint64_t earliestPresentTime_ = {},
+ uint64_t presentMargin_ = {} ) VULKAN_HPP_NOEXCEPT
+ : presentID( presentID_ )
+ , desiredPresentTime( desiredPresentTime_ )
+ , actualPresentTime( actualPresentTime_ )
+ , earliestPresentTime( earliestPresentTime_ )
+ , presentMargin( presentMargin_ )
+ {}
+
+ PastPresentationTimingGOOGLE( VkPastPresentationTimingGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PastPresentationTimingGOOGLE& operator=( VkPastPresentationTimingGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PastPresentationTimingGOOGLE const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPastPresentationTimingGOOGLE const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPastPresentationTimingGOOGLE*>( this );
+ }
+
+ operator VkPastPresentationTimingGOOGLE &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPastPresentationTimingGOOGLE*>( this );
+ }
+
+ bool operator==( PastPresentationTimingGOOGLE const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( presentID == rhs.presentID )
+ && ( desiredPresentTime == rhs.desiredPresentTime )
+ && ( actualPresentTime == rhs.actualPresentTime )
+ && ( earliestPresentTime == rhs.earliestPresentTime )
+ && ( presentMargin == rhs.presentMargin );
+ }
+
+ bool operator!=( PastPresentationTimingGOOGLE const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t presentID = {};
+ uint64_t desiredPresentTime = {};
+ uint64_t actualPresentTime = {};
+ uint64_t earliestPresentTime = {};
+ uint64_t presentMargin = {};
+ };
+ static_assert( sizeof( PastPresentationTimingGOOGLE ) == sizeof( VkPastPresentationTimingGOOGLE ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PastPresentationTimingGOOGLE>::value, "struct wrapper is not a standard layout!" );
+
+ struct PerformanceConfigurationAcquireInfoINTEL
+ {
+ VULKAN_HPP_CONSTEXPR PerformanceConfigurationAcquireInfoINTEL( VULKAN_HPP_NAMESPACE::PerformanceConfigurationTypeINTEL type_ = VULKAN_HPP_NAMESPACE::PerformanceConfigurationTypeINTEL::eCommandQueueMetricsDiscoveryActivated ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PerformanceConfigurationAcquireInfoINTEL & operator=( VULKAN_HPP_NAMESPACE::PerformanceConfigurationAcquireInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PerformanceConfigurationAcquireInfoINTEL ) - offsetof( PerformanceConfigurationAcquireInfoINTEL, pNext ) );
+ return *this;
+ }
+
+ PerformanceConfigurationAcquireInfoINTEL( VkPerformanceConfigurationAcquireInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PerformanceConfigurationAcquireInfoINTEL& operator=( VkPerformanceConfigurationAcquireInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PerformanceConfigurationAcquireInfoINTEL const *>(&rhs);
+ return *this;
+ }
+
+ PerformanceConfigurationAcquireInfoINTEL & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PerformanceConfigurationAcquireInfoINTEL & setType( VULKAN_HPP_NAMESPACE::PerformanceConfigurationTypeINTEL type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ operator VkPerformanceConfigurationAcquireInfoINTEL const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPerformanceConfigurationAcquireInfoINTEL*>( this );
+ }
+
+ operator VkPerformanceConfigurationAcquireInfoINTEL &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPerformanceConfigurationAcquireInfoINTEL*>( this );
+ }
+
+ bool operator==( PerformanceConfigurationAcquireInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( type == rhs.type );
+ }
+
+ bool operator!=( PerformanceConfigurationAcquireInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePerformanceConfigurationAcquireInfoINTEL;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PerformanceConfigurationTypeINTEL type = VULKAN_HPP_NAMESPACE::PerformanceConfigurationTypeINTEL::eCommandQueueMetricsDiscoveryActivated;
+ };
+ static_assert( sizeof( PerformanceConfigurationAcquireInfoINTEL ) == sizeof( VkPerformanceConfigurationAcquireInfoINTEL ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PerformanceConfigurationAcquireInfoINTEL>::value, "struct wrapper is not a standard layout!" );
+
+ struct PerformanceCounterDescriptionKHR
+ {
+ PerformanceCounterDescriptionKHR( VULKAN_HPP_NAMESPACE::PerformanceCounterDescriptionFlagsKHR flags_ = {},
+ std::array<char,VK_MAX_DESCRIPTION_SIZE> const& name_ = {},
+ std::array<char,VK_MAX_DESCRIPTION_SIZE> const& category_ = {},
+ std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , name{}
+ , category{}
+ , description{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( name, name_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( category, category_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PerformanceCounterDescriptionKHR & operator=( VULKAN_HPP_NAMESPACE::PerformanceCounterDescriptionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PerformanceCounterDescriptionKHR ) - offsetof( PerformanceCounterDescriptionKHR, pNext ) );
+ return *this;
+ }
+
+ PerformanceCounterDescriptionKHR( VkPerformanceCounterDescriptionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PerformanceCounterDescriptionKHR& operator=( VkPerformanceCounterDescriptionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PerformanceCounterDescriptionKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPerformanceCounterDescriptionKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPerformanceCounterDescriptionKHR*>( this );
+ }
+
+ operator VkPerformanceCounterDescriptionKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPerformanceCounterDescriptionKHR*>( this );
+ }
+
+ bool operator==( PerformanceCounterDescriptionKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( memcmp( name, rhs.name, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
+ && ( memcmp( category, rhs.category, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
+ && ( memcmp( description, rhs.description, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 );
+ }
+
+ bool operator!=( PerformanceCounterDescriptionKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePerformanceCounterDescriptionKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PerformanceCounterDescriptionFlagsKHR flags = {};
+ char name[VK_MAX_DESCRIPTION_SIZE] = {};
+ char category[VK_MAX_DESCRIPTION_SIZE] = {};
+ char description[VK_MAX_DESCRIPTION_SIZE] = {};
+ };
+ static_assert( sizeof( PerformanceCounterDescriptionKHR ) == sizeof( VkPerformanceCounterDescriptionKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PerformanceCounterDescriptionKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PerformanceCounterKHR
+ {
+ PerformanceCounterKHR( VULKAN_HPP_NAMESPACE::PerformanceCounterUnitKHR unit_ = VULKAN_HPP_NAMESPACE::PerformanceCounterUnitKHR::eGeneric,
+ VULKAN_HPP_NAMESPACE::PerformanceCounterScopeKHR scope_ = VULKAN_HPP_NAMESPACE::PerformanceCounterScopeKHR::eCommandBuffer,
+ VULKAN_HPP_NAMESPACE::PerformanceCounterStorageKHR storage_ = VULKAN_HPP_NAMESPACE::PerformanceCounterStorageKHR::eInt32,
+ std::array<uint8_t,VK_UUID_SIZE> const& uuid_ = {} ) VULKAN_HPP_NOEXCEPT
+ : unit( unit_ )
+ , scope( scope_ )
+ , storage( storage_ )
+ , uuid{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE,VK_UUID_SIZE>::copy( uuid, uuid_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PerformanceCounterKHR & operator=( VULKAN_HPP_NAMESPACE::PerformanceCounterKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PerformanceCounterKHR ) - offsetof( PerformanceCounterKHR, pNext ) );
+ return *this;
+ }
+
+ PerformanceCounterKHR( VkPerformanceCounterKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PerformanceCounterKHR& operator=( VkPerformanceCounterKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PerformanceCounterKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPerformanceCounterKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPerformanceCounterKHR*>( this );
+ }
+
+ operator VkPerformanceCounterKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPerformanceCounterKHR*>( this );
+ }
+
+ bool operator==( PerformanceCounterKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( unit == rhs.unit )
+ && ( scope == rhs.scope )
+ && ( storage == rhs.storage )
+ && ( memcmp( uuid, rhs.uuid, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 );
+ }
+
+ bool operator!=( PerformanceCounterKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePerformanceCounterKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PerformanceCounterUnitKHR unit = VULKAN_HPP_NAMESPACE::PerformanceCounterUnitKHR::eGeneric;
+ VULKAN_HPP_NAMESPACE::PerformanceCounterScopeKHR scope = VULKAN_HPP_NAMESPACE::PerformanceCounterScopeKHR::eCommandBuffer;
+ VULKAN_HPP_NAMESPACE::PerformanceCounterStorageKHR storage = VULKAN_HPP_NAMESPACE::PerformanceCounterStorageKHR::eInt32;
+ uint8_t uuid[VK_UUID_SIZE] = {};
+ };
+ static_assert( sizeof( PerformanceCounterKHR ) == sizeof( VkPerformanceCounterKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PerformanceCounterKHR>::value, "struct wrapper is not a standard layout!" );
+
+ union PerformanceCounterResultKHR
+ {
+ PerformanceCounterResultKHR( int32_t int32_ = {} )
+ {
+ int32 = int32_;
+ }
+
+ PerformanceCounterResultKHR( int64_t int64_ )
+ {
+ int64 = int64_;
+ }
+
+ PerformanceCounterResultKHR( uint32_t uint32_ )
+ {
+ uint32 = uint32_;
+ }
+
+ PerformanceCounterResultKHR( uint64_t uint64_ )
+ {
+ uint64 = uint64_;
+ }
+
+ PerformanceCounterResultKHR( float float32_ )
+ {
+ float32 = float32_;
+ }
+
+ PerformanceCounterResultKHR( double float64_ )
+ {
+ float64 = float64_;
+ }
+
+ PerformanceCounterResultKHR & setInt32( int32_t int32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ int32 = int32_;
+ return *this;
+ }
+
+ PerformanceCounterResultKHR & setInt64( int64_t int64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ int64 = int64_;
+ return *this;
+ }
+
+ PerformanceCounterResultKHR & setUint32( uint32_t uint32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ uint32 = uint32_;
+ return *this;
+ }
+
+ PerformanceCounterResultKHR & setUint64( uint64_t uint64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ uint64 = uint64_;
+ return *this;
+ }
+
+ PerformanceCounterResultKHR & setFloat32( float float32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ float32 = float32_;
+ return *this;
+ }
+
+ PerformanceCounterResultKHR & setFloat64( double float64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ float64 = float64_;
+ return *this;
+ }
+
+ VULKAN_HPP_NAMESPACE::PerformanceCounterResultKHR & operator=( VULKAN_HPP_NAMESPACE::PerformanceCounterResultKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( this, &rhs, sizeof( VULKAN_HPP_NAMESPACE::PerformanceCounterResultKHR ) );
+ return *this;
+ }
+
+ operator VkPerformanceCounterResultKHR const&() const
+ {
+ return *reinterpret_cast<const VkPerformanceCounterResultKHR*>(this);
+ }
+
+ operator VkPerformanceCounterResultKHR &()
+ {
+ return *reinterpret_cast<VkPerformanceCounterResultKHR*>(this);
+ }
+
+ int32_t int32;
+ int64_t int64;
+ uint32_t uint32;
+ uint64_t uint64;
+ float float32;
+ double float64;
+ };
+
+ struct PerformanceMarkerInfoINTEL
+ {
+ VULKAN_HPP_CONSTEXPR PerformanceMarkerInfoINTEL( uint64_t marker_ = {} ) VULKAN_HPP_NOEXCEPT
+ : marker( marker_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PerformanceMarkerInfoINTEL & operator=( VULKAN_HPP_NAMESPACE::PerformanceMarkerInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PerformanceMarkerInfoINTEL ) - offsetof( PerformanceMarkerInfoINTEL, pNext ) );
+ return *this;
+ }
+
+ PerformanceMarkerInfoINTEL( VkPerformanceMarkerInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PerformanceMarkerInfoINTEL& operator=( VkPerformanceMarkerInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PerformanceMarkerInfoINTEL const *>(&rhs);
+ return *this;
+ }
+
+ PerformanceMarkerInfoINTEL & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PerformanceMarkerInfoINTEL & setMarker( uint64_t marker_ ) VULKAN_HPP_NOEXCEPT
+ {
+ marker = marker_;
+ return *this;
+ }
+
+ operator VkPerformanceMarkerInfoINTEL const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPerformanceMarkerInfoINTEL*>( this );
+ }
+
+ operator VkPerformanceMarkerInfoINTEL &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPerformanceMarkerInfoINTEL*>( this );
+ }
+
+ bool operator==( PerformanceMarkerInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( marker == rhs.marker );
+ }
+
+ bool operator!=( PerformanceMarkerInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePerformanceMarkerInfoINTEL;
+ const void* pNext = {};
+ uint64_t marker = {};
+ };
+ static_assert( sizeof( PerformanceMarkerInfoINTEL ) == sizeof( VkPerformanceMarkerInfoINTEL ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PerformanceMarkerInfoINTEL>::value, "struct wrapper is not a standard layout!" );
+
+ struct PerformanceOverrideInfoINTEL
+ {
+ VULKAN_HPP_CONSTEXPR PerformanceOverrideInfoINTEL( VULKAN_HPP_NAMESPACE::PerformanceOverrideTypeINTEL type_ = VULKAN_HPP_NAMESPACE::PerformanceOverrideTypeINTEL::eNullHardware,
+ VULKAN_HPP_NAMESPACE::Bool32 enable_ = {},
+ uint64_t parameter_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , enable( enable_ )
+ , parameter( parameter_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PerformanceOverrideInfoINTEL & operator=( VULKAN_HPP_NAMESPACE::PerformanceOverrideInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PerformanceOverrideInfoINTEL ) - offsetof( PerformanceOverrideInfoINTEL, pNext ) );
+ return *this;
+ }
+
+ PerformanceOverrideInfoINTEL( VkPerformanceOverrideInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PerformanceOverrideInfoINTEL& operator=( VkPerformanceOverrideInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PerformanceOverrideInfoINTEL const *>(&rhs);
+ return *this;
+ }
+
+ PerformanceOverrideInfoINTEL & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PerformanceOverrideInfoINTEL & setType( VULKAN_HPP_NAMESPACE::PerformanceOverrideTypeINTEL type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ PerformanceOverrideInfoINTEL & setEnable( VULKAN_HPP_NAMESPACE::Bool32 enable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ enable = enable_;
+ return *this;
+ }
+
+ PerformanceOverrideInfoINTEL & setParameter( uint64_t parameter_ ) VULKAN_HPP_NOEXCEPT
+ {
+ parameter = parameter_;
+ return *this;
+ }
+
+ operator VkPerformanceOverrideInfoINTEL const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPerformanceOverrideInfoINTEL*>( this );
+ }
+
+ operator VkPerformanceOverrideInfoINTEL &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPerformanceOverrideInfoINTEL*>( this );
+ }
+
+ bool operator==( PerformanceOverrideInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( type == rhs.type )
+ && ( enable == rhs.enable )
+ && ( parameter == rhs.parameter );
+ }
+
+ bool operator!=( PerformanceOverrideInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePerformanceOverrideInfoINTEL;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PerformanceOverrideTypeINTEL type = VULKAN_HPP_NAMESPACE::PerformanceOverrideTypeINTEL::eNullHardware;
+ VULKAN_HPP_NAMESPACE::Bool32 enable = {};
+ uint64_t parameter = {};
+ };
+ static_assert( sizeof( PerformanceOverrideInfoINTEL ) == sizeof( VkPerformanceOverrideInfoINTEL ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PerformanceOverrideInfoINTEL>::value, "struct wrapper is not a standard layout!" );
+
+ struct PerformanceQuerySubmitInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR PerformanceQuerySubmitInfoKHR( uint32_t counterPassIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : counterPassIndex( counterPassIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PerformanceQuerySubmitInfoKHR & operator=( VULKAN_HPP_NAMESPACE::PerformanceQuerySubmitInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PerformanceQuerySubmitInfoKHR ) - offsetof( PerformanceQuerySubmitInfoKHR, pNext ) );
+ return *this;
+ }
+
+ PerformanceQuerySubmitInfoKHR( VkPerformanceQuerySubmitInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PerformanceQuerySubmitInfoKHR& operator=( VkPerformanceQuerySubmitInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PerformanceQuerySubmitInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ PerformanceQuerySubmitInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PerformanceQuerySubmitInfoKHR & setCounterPassIndex( uint32_t counterPassIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ counterPassIndex = counterPassIndex_;
+ return *this;
+ }
+
+ operator VkPerformanceQuerySubmitInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPerformanceQuerySubmitInfoKHR*>( this );
+ }
+
+ operator VkPerformanceQuerySubmitInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPerformanceQuerySubmitInfoKHR*>( this );
+ }
+
+ bool operator==( PerformanceQuerySubmitInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( counterPassIndex == rhs.counterPassIndex );
+ }
+
+ bool operator!=( PerformanceQuerySubmitInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePerformanceQuerySubmitInfoKHR;
+ const void* pNext = {};
+ uint32_t counterPassIndex = {};
+ };
+ static_assert( sizeof( PerformanceQuerySubmitInfoKHR ) == sizeof( VkPerformanceQuerySubmitInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PerformanceQuerySubmitInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PerformanceStreamMarkerInfoINTEL
+ {
+ VULKAN_HPP_CONSTEXPR PerformanceStreamMarkerInfoINTEL( uint32_t marker_ = {} ) VULKAN_HPP_NOEXCEPT
+ : marker( marker_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PerformanceStreamMarkerInfoINTEL & operator=( VULKAN_HPP_NAMESPACE::PerformanceStreamMarkerInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PerformanceStreamMarkerInfoINTEL ) - offsetof( PerformanceStreamMarkerInfoINTEL, pNext ) );
+ return *this;
+ }
+
+ PerformanceStreamMarkerInfoINTEL( VkPerformanceStreamMarkerInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PerformanceStreamMarkerInfoINTEL& operator=( VkPerformanceStreamMarkerInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PerformanceStreamMarkerInfoINTEL const *>(&rhs);
+ return *this;
+ }
+
+ PerformanceStreamMarkerInfoINTEL & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PerformanceStreamMarkerInfoINTEL & setMarker( uint32_t marker_ ) VULKAN_HPP_NOEXCEPT
+ {
+ marker = marker_;
+ return *this;
+ }
+
+ operator VkPerformanceStreamMarkerInfoINTEL const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPerformanceStreamMarkerInfoINTEL*>( this );
+ }
+
+ operator VkPerformanceStreamMarkerInfoINTEL &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPerformanceStreamMarkerInfoINTEL*>( this );
+ }
+
+ bool operator==( PerformanceStreamMarkerInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( marker == rhs.marker );
+ }
+
+ bool operator!=( PerformanceStreamMarkerInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePerformanceStreamMarkerInfoINTEL;
+ const void* pNext = {};
+ uint32_t marker = {};
+ };
+ static_assert( sizeof( PerformanceStreamMarkerInfoINTEL ) == sizeof( VkPerformanceStreamMarkerInfoINTEL ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PerformanceStreamMarkerInfoINTEL>::value, "struct wrapper is not a standard layout!" );
+
+ union PerformanceValueDataINTEL
+ {
+ PerformanceValueDataINTEL( uint32_t value32_ = {} )
+ {
+ value32 = value32_;
+ }
+
+ PerformanceValueDataINTEL( uint64_t value64_ )
+ {
+ value64 = value64_;
+ }
+
+ PerformanceValueDataINTEL( float valueFloat_ )
+ {
+ valueFloat = valueFloat_;
+ }
+
+ PerformanceValueDataINTEL( const char* valueString_ )
+ {
+ valueString = valueString_;
+ }
+
+ PerformanceValueDataINTEL & setValue32( uint32_t value32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ value32 = value32_;
+ return *this;
+ }
+
+ PerformanceValueDataINTEL & setValue64( uint64_t value64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ value64 = value64_;
+ return *this;
+ }
+
+ PerformanceValueDataINTEL & setValueFloat( float valueFloat_ ) VULKAN_HPP_NOEXCEPT
+ {
+ valueFloat = valueFloat_;
+ return *this;
+ }
+
+ PerformanceValueDataINTEL & setValueBool( VULKAN_HPP_NAMESPACE::Bool32 valueBool_ ) VULKAN_HPP_NOEXCEPT
+ {
+ valueBool = valueBool_;
+ return *this;
+ }
+
+ PerformanceValueDataINTEL & setValueString( const char* valueString_ ) VULKAN_HPP_NOEXCEPT
+ {
+ valueString = valueString_;
+ return *this;
+ }
+
+ VULKAN_HPP_NAMESPACE::PerformanceValueDataINTEL & operator=( VULKAN_HPP_NAMESPACE::PerformanceValueDataINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( this, &rhs, sizeof( VULKAN_HPP_NAMESPACE::PerformanceValueDataINTEL ) );
+ return *this;
+ }
+
+ operator VkPerformanceValueDataINTEL const&() const
+ {
+ return *reinterpret_cast<const VkPerformanceValueDataINTEL*>(this);
+ }
+
+ operator VkPerformanceValueDataINTEL &()
+ {
+ return *reinterpret_cast<VkPerformanceValueDataINTEL*>(this);
+ }
+
+#ifdef VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
+ uint32_t value32;
+ uint64_t value64;
+ float valueFloat;
+ VULKAN_HPP_NAMESPACE::Bool32 valueBool;
+ const char* valueString;
+#else
+ uint32_t value32;
+ uint64_t value64;
+ float valueFloat;
+ VkBool32 valueBool;
+ const char* valueString;
+#endif /*VULKAN_HPP_HAS_UNRESTRICTED_UNIONS*/
+ };
+
+ struct PerformanceValueINTEL
+ {
+ PerformanceValueINTEL( VULKAN_HPP_NAMESPACE::PerformanceValueTypeINTEL type_ = VULKAN_HPP_NAMESPACE::PerformanceValueTypeINTEL::eUint32,
+ VULKAN_HPP_NAMESPACE::PerformanceValueDataINTEL data_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , data( data_ )
+ {}
+
+ PerformanceValueINTEL( VkPerformanceValueINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PerformanceValueINTEL& operator=( VkPerformanceValueINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PerformanceValueINTEL const *>(&rhs);
+ return *this;
+ }
+
+ PerformanceValueINTEL & setType( VULKAN_HPP_NAMESPACE::PerformanceValueTypeINTEL type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ PerformanceValueINTEL & setData( VULKAN_HPP_NAMESPACE::PerformanceValueDataINTEL data_ ) VULKAN_HPP_NOEXCEPT
+ {
+ data = data_;
+ return *this;
+ }
+
+ operator VkPerformanceValueINTEL const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPerformanceValueINTEL*>( this );
+ }
+
+ operator VkPerformanceValueINTEL &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPerformanceValueINTEL*>( this );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::PerformanceValueTypeINTEL type = VULKAN_HPP_NAMESPACE::PerformanceValueTypeINTEL::eUint32;
+ VULKAN_HPP_NAMESPACE::PerformanceValueDataINTEL data = {};
+ };
+ static_assert( sizeof( PerformanceValueINTEL ) == sizeof( VkPerformanceValueINTEL ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PerformanceValueINTEL>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDevice16BitStorageFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDevice16BitStorageFeatures( VULKAN_HPP_NAMESPACE::Bool32 storageBuffer16BitAccess_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer16BitAccess_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 storageInputOutput16_ = {} ) VULKAN_HPP_NOEXCEPT
+ : storageBuffer16BitAccess( storageBuffer16BitAccess_ )
+ , uniformAndStorageBuffer16BitAccess( uniformAndStorageBuffer16BitAccess_ )
+ , storagePushConstant16( storagePushConstant16_ )
+ , storageInputOutput16( storageInputOutput16_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDevice16BitStorageFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDevice16BitStorageFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDevice16BitStorageFeatures ) - offsetof( PhysicalDevice16BitStorageFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDevice16BitStorageFeatures( VkPhysicalDevice16BitStorageFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDevice16BitStorageFeatures& operator=( VkPhysicalDevice16BitStorageFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDevice16BitStorageFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDevice16BitStorageFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDevice16BitStorageFeatures & setStorageBuffer16BitAccess( VULKAN_HPP_NAMESPACE::Bool32 storageBuffer16BitAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storageBuffer16BitAccess = storageBuffer16BitAccess_;
+ return *this;
+ }
+
+ PhysicalDevice16BitStorageFeatures & setUniformAndStorageBuffer16BitAccess( VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer16BitAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ uniformAndStorageBuffer16BitAccess = uniformAndStorageBuffer16BitAccess_;
+ return *this;
+ }
+
+ PhysicalDevice16BitStorageFeatures & setStoragePushConstant16( VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storagePushConstant16 = storagePushConstant16_;
+ return *this;
+ }
+
+ PhysicalDevice16BitStorageFeatures & setStorageInputOutput16( VULKAN_HPP_NAMESPACE::Bool32 storageInputOutput16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storageInputOutput16 = storageInputOutput16_;
+ return *this;
+ }
+
+ operator VkPhysicalDevice16BitStorageFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDevice16BitStorageFeatures*>( this );
+ }
+
+ operator VkPhysicalDevice16BitStorageFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDevice16BitStorageFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDevice16BitStorageFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( storageBuffer16BitAccess == rhs.storageBuffer16BitAccess )
+ && ( uniformAndStorageBuffer16BitAccess == rhs.uniformAndStorageBuffer16BitAccess )
+ && ( storagePushConstant16 == rhs.storagePushConstant16 )
+ && ( storageInputOutput16 == rhs.storageInputOutput16 );
+ }
+
+ bool operator!=( PhysicalDevice16BitStorageFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDevice16BitStorageFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storageBuffer16BitAccess = {};
+ VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer16BitAccess = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storageInputOutput16 = {};
+ };
+ static_assert( sizeof( PhysicalDevice16BitStorageFeatures ) == sizeof( VkPhysicalDevice16BitStorageFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDevice16BitStorageFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDevice8BitStorageFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDevice8BitStorageFeatures( VULKAN_HPP_NAMESPACE::Bool32 storageBuffer8BitAccess_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer8BitAccess_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant8_ = {} ) VULKAN_HPP_NOEXCEPT
+ : storageBuffer8BitAccess( storageBuffer8BitAccess_ )
+ , uniformAndStorageBuffer8BitAccess( uniformAndStorageBuffer8BitAccess_ )
+ , storagePushConstant8( storagePushConstant8_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDevice8BitStorageFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDevice8BitStorageFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDevice8BitStorageFeatures ) - offsetof( PhysicalDevice8BitStorageFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDevice8BitStorageFeatures( VkPhysicalDevice8BitStorageFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDevice8BitStorageFeatures& operator=( VkPhysicalDevice8BitStorageFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDevice8BitStorageFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDevice8BitStorageFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDevice8BitStorageFeatures & setStorageBuffer8BitAccess( VULKAN_HPP_NAMESPACE::Bool32 storageBuffer8BitAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storageBuffer8BitAccess = storageBuffer8BitAccess_;
+ return *this;
+ }
+
+ PhysicalDevice8BitStorageFeatures & setUniformAndStorageBuffer8BitAccess( VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer8BitAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ uniformAndStorageBuffer8BitAccess = uniformAndStorageBuffer8BitAccess_;
+ return *this;
+ }
+
+ PhysicalDevice8BitStorageFeatures & setStoragePushConstant8( VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant8_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storagePushConstant8 = storagePushConstant8_;
+ return *this;
+ }
+
+ operator VkPhysicalDevice8BitStorageFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDevice8BitStorageFeatures*>( this );
+ }
+
+ operator VkPhysicalDevice8BitStorageFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDevice8BitStorageFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDevice8BitStorageFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( storageBuffer8BitAccess == rhs.storageBuffer8BitAccess )
+ && ( uniformAndStorageBuffer8BitAccess == rhs.uniformAndStorageBuffer8BitAccess )
+ && ( storagePushConstant8 == rhs.storagePushConstant8 );
+ }
+
+ bool operator!=( PhysicalDevice8BitStorageFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDevice8BitStorageFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storageBuffer8BitAccess = {};
+ VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer8BitAccess = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant8 = {};
+ };
+ static_assert( sizeof( PhysicalDevice8BitStorageFeatures ) == sizeof( VkPhysicalDevice8BitStorageFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDevice8BitStorageFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceASTCDecodeFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceASTCDecodeFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 decodeModeSharedExponent_ = {} ) VULKAN_HPP_NOEXCEPT
+ : decodeModeSharedExponent( decodeModeSharedExponent_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceASTCDecodeFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceASTCDecodeFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceASTCDecodeFeaturesEXT ) - offsetof( PhysicalDeviceASTCDecodeFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceASTCDecodeFeaturesEXT( VkPhysicalDeviceASTCDecodeFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceASTCDecodeFeaturesEXT& operator=( VkPhysicalDeviceASTCDecodeFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceASTCDecodeFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceASTCDecodeFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceASTCDecodeFeaturesEXT & setDecodeModeSharedExponent( VULKAN_HPP_NAMESPACE::Bool32 decodeModeSharedExponent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ decodeModeSharedExponent = decodeModeSharedExponent_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceASTCDecodeFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceASTCDecodeFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceASTCDecodeFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceASTCDecodeFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceASTCDecodeFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( decodeModeSharedExponent == rhs.decodeModeSharedExponent );
+ }
+
+ bool operator!=( PhysicalDeviceASTCDecodeFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceAstcDecodeFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 decodeModeSharedExponent = {};
+ };
+ static_assert( sizeof( PhysicalDeviceASTCDecodeFeaturesEXT ) == sizeof( VkPhysicalDeviceASTCDecodeFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceASTCDecodeFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceBlendOperationAdvancedFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceBlendOperationAdvancedFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 advancedBlendCoherentOperations_ = {} ) VULKAN_HPP_NOEXCEPT
+ : advancedBlendCoherentOperations( advancedBlendCoherentOperations_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceBlendOperationAdvancedFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceBlendOperationAdvancedFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceBlendOperationAdvancedFeaturesEXT ) - offsetof( PhysicalDeviceBlendOperationAdvancedFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceBlendOperationAdvancedFeaturesEXT( VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceBlendOperationAdvancedFeaturesEXT& operator=( VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceBlendOperationAdvancedFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceBlendOperationAdvancedFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceBlendOperationAdvancedFeaturesEXT & setAdvancedBlendCoherentOperations( VULKAN_HPP_NAMESPACE::Bool32 advancedBlendCoherentOperations_ ) VULKAN_HPP_NOEXCEPT
+ {
+ advancedBlendCoherentOperations = advancedBlendCoherentOperations_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceBlendOperationAdvancedFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( advancedBlendCoherentOperations == rhs.advancedBlendCoherentOperations );
+ }
+
+ bool operator!=( PhysicalDeviceBlendOperationAdvancedFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceBlendOperationAdvancedFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendCoherentOperations = {};
+ };
+ static_assert( sizeof( PhysicalDeviceBlendOperationAdvancedFeaturesEXT ) == sizeof( VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceBlendOperationAdvancedFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceBlendOperationAdvancedPropertiesEXT
+ {
+ PhysicalDeviceBlendOperationAdvancedPropertiesEXT( uint32_t advancedBlendMaxColorAttachments_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendIndependentBlend_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendNonPremultipliedSrcColor_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendNonPremultipliedDstColor_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendCorrelatedOverlap_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendAllOperations_ = {} ) VULKAN_HPP_NOEXCEPT
+ : advancedBlendMaxColorAttachments( advancedBlendMaxColorAttachments_ )
+ , advancedBlendIndependentBlend( advancedBlendIndependentBlend_ )
+ , advancedBlendNonPremultipliedSrcColor( advancedBlendNonPremultipliedSrcColor_ )
+ , advancedBlendNonPremultipliedDstColor( advancedBlendNonPremultipliedDstColor_ )
+ , advancedBlendCorrelatedOverlap( advancedBlendCorrelatedOverlap_ )
+ , advancedBlendAllOperations( advancedBlendAllOperations_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceBlendOperationAdvancedPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceBlendOperationAdvancedPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceBlendOperationAdvancedPropertiesEXT ) - offsetof( PhysicalDeviceBlendOperationAdvancedPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceBlendOperationAdvancedPropertiesEXT( VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceBlendOperationAdvancedPropertiesEXT& operator=( VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceBlendOperationAdvancedPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceBlendOperationAdvancedPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( advancedBlendMaxColorAttachments == rhs.advancedBlendMaxColorAttachments )
+ && ( advancedBlendIndependentBlend == rhs.advancedBlendIndependentBlend )
+ && ( advancedBlendNonPremultipliedSrcColor == rhs.advancedBlendNonPremultipliedSrcColor )
+ && ( advancedBlendNonPremultipliedDstColor == rhs.advancedBlendNonPremultipliedDstColor )
+ && ( advancedBlendCorrelatedOverlap == rhs.advancedBlendCorrelatedOverlap )
+ && ( advancedBlendAllOperations == rhs.advancedBlendAllOperations );
+ }
+
+ bool operator!=( PhysicalDeviceBlendOperationAdvancedPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceBlendOperationAdvancedPropertiesEXT;
+ void* pNext = {};
+ uint32_t advancedBlendMaxColorAttachments = {};
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendIndependentBlend = {};
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendNonPremultipliedSrcColor = {};
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendNonPremultipliedDstColor = {};
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendCorrelatedOverlap = {};
+ VULKAN_HPP_NAMESPACE::Bool32 advancedBlendAllOperations = {};
+ };
+ static_assert( sizeof( PhysicalDeviceBlendOperationAdvancedPropertiesEXT ) == sizeof( VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceBlendOperationAdvancedPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceBufferDeviceAddressFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceBufferDeviceAddressFeatures( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddress_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressCaptureReplay_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressMultiDevice_ = {} ) VULKAN_HPP_NOEXCEPT
+ : bufferDeviceAddress( bufferDeviceAddress_ )
+ , bufferDeviceAddressCaptureReplay( bufferDeviceAddressCaptureReplay_ )
+ , bufferDeviceAddressMultiDevice( bufferDeviceAddressMultiDevice_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceBufferDeviceAddressFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceBufferDeviceAddressFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceBufferDeviceAddressFeatures ) - offsetof( PhysicalDeviceBufferDeviceAddressFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeatures( VkPhysicalDeviceBufferDeviceAddressFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeatures& operator=( VkPhysicalDeviceBufferDeviceAddressFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceBufferDeviceAddressFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeatures & setBufferDeviceAddress( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddress_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferDeviceAddress = bufferDeviceAddress_;
+ return *this;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeatures & setBufferDeviceAddressCaptureReplay( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressCaptureReplay_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferDeviceAddressCaptureReplay = bufferDeviceAddressCaptureReplay_;
+ return *this;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeatures & setBufferDeviceAddressMultiDevice( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressMultiDevice_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferDeviceAddressMultiDevice = bufferDeviceAddressMultiDevice_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceBufferDeviceAddressFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceBufferDeviceAddressFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceBufferDeviceAddressFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceBufferDeviceAddressFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceBufferDeviceAddressFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( bufferDeviceAddress == rhs.bufferDeviceAddress )
+ && ( bufferDeviceAddressCaptureReplay == rhs.bufferDeviceAddressCaptureReplay )
+ && ( bufferDeviceAddressMultiDevice == rhs.bufferDeviceAddressMultiDevice );
+ }
+
+ bool operator!=( PhysicalDeviceBufferDeviceAddressFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceBufferDeviceAddressFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddress = {};
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressCaptureReplay = {};
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressMultiDevice = {};
+ };
+ static_assert( sizeof( PhysicalDeviceBufferDeviceAddressFeatures ) == sizeof( VkPhysicalDeviceBufferDeviceAddressFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceBufferDeviceAddressFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceBufferDeviceAddressFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceBufferDeviceAddressFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddress_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressCaptureReplay_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressMultiDevice_ = {} ) VULKAN_HPP_NOEXCEPT
+ : bufferDeviceAddress( bufferDeviceAddress_ )
+ , bufferDeviceAddressCaptureReplay( bufferDeviceAddressCaptureReplay_ )
+ , bufferDeviceAddressMultiDevice( bufferDeviceAddressMultiDevice_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceBufferDeviceAddressFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceBufferDeviceAddressFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceBufferDeviceAddressFeaturesEXT ) - offsetof( PhysicalDeviceBufferDeviceAddressFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeaturesEXT( VkPhysicalDeviceBufferDeviceAddressFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeaturesEXT& operator=( VkPhysicalDeviceBufferDeviceAddressFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceBufferDeviceAddressFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeaturesEXT & setBufferDeviceAddress( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddress_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferDeviceAddress = bufferDeviceAddress_;
+ return *this;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeaturesEXT & setBufferDeviceAddressCaptureReplay( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressCaptureReplay_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferDeviceAddressCaptureReplay = bufferDeviceAddressCaptureReplay_;
+ return *this;
+ }
+
+ PhysicalDeviceBufferDeviceAddressFeaturesEXT & setBufferDeviceAddressMultiDevice( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressMultiDevice_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferDeviceAddressMultiDevice = bufferDeviceAddressMultiDevice_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceBufferDeviceAddressFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceBufferDeviceAddressFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceBufferDeviceAddressFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceBufferDeviceAddressFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceBufferDeviceAddressFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( bufferDeviceAddress == rhs.bufferDeviceAddress )
+ && ( bufferDeviceAddressCaptureReplay == rhs.bufferDeviceAddressCaptureReplay )
+ && ( bufferDeviceAddressMultiDevice == rhs.bufferDeviceAddressMultiDevice );
+ }
+
+ bool operator!=( PhysicalDeviceBufferDeviceAddressFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceBufferDeviceAddressFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddress = {};
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressCaptureReplay = {};
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressMultiDevice = {};
+ };
+ static_assert( sizeof( PhysicalDeviceBufferDeviceAddressFeaturesEXT ) == sizeof( VkPhysicalDeviceBufferDeviceAddressFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceBufferDeviceAddressFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceCoherentMemoryFeaturesAMD
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceCoherentMemoryFeaturesAMD( VULKAN_HPP_NAMESPACE::Bool32 deviceCoherentMemory_ = {} ) VULKAN_HPP_NOEXCEPT
+ : deviceCoherentMemory( deviceCoherentMemory_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceCoherentMemoryFeaturesAMD & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceCoherentMemoryFeaturesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceCoherentMemoryFeaturesAMD ) - offsetof( PhysicalDeviceCoherentMemoryFeaturesAMD, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceCoherentMemoryFeaturesAMD( VkPhysicalDeviceCoherentMemoryFeaturesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceCoherentMemoryFeaturesAMD& operator=( VkPhysicalDeviceCoherentMemoryFeaturesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceCoherentMemoryFeaturesAMD const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceCoherentMemoryFeaturesAMD & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceCoherentMemoryFeaturesAMD & setDeviceCoherentMemory( VULKAN_HPP_NAMESPACE::Bool32 deviceCoherentMemory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceCoherentMemory = deviceCoherentMemory_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceCoherentMemoryFeaturesAMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceCoherentMemoryFeaturesAMD*>( this );
+ }
+
+ operator VkPhysicalDeviceCoherentMemoryFeaturesAMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceCoherentMemoryFeaturesAMD*>( this );
+ }
+
+ bool operator==( PhysicalDeviceCoherentMemoryFeaturesAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( deviceCoherentMemory == rhs.deviceCoherentMemory );
+ }
+
+ bool operator!=( PhysicalDeviceCoherentMemoryFeaturesAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceCoherentMemoryFeaturesAMD;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 deviceCoherentMemory = {};
+ };
+ static_assert( sizeof( PhysicalDeviceCoherentMemoryFeaturesAMD ) == sizeof( VkPhysicalDeviceCoherentMemoryFeaturesAMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceCoherentMemoryFeaturesAMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceComputeShaderDerivativesFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceComputeShaderDerivativesFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 computeDerivativeGroupQuads_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 computeDerivativeGroupLinear_ = {} ) VULKAN_HPP_NOEXCEPT
+ : computeDerivativeGroupQuads( computeDerivativeGroupQuads_ )
+ , computeDerivativeGroupLinear( computeDerivativeGroupLinear_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceComputeShaderDerivativesFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceComputeShaderDerivativesFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceComputeShaderDerivativesFeaturesNV ) - offsetof( PhysicalDeviceComputeShaderDerivativesFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceComputeShaderDerivativesFeaturesNV( VkPhysicalDeviceComputeShaderDerivativesFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceComputeShaderDerivativesFeaturesNV& operator=( VkPhysicalDeviceComputeShaderDerivativesFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceComputeShaderDerivativesFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceComputeShaderDerivativesFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceComputeShaderDerivativesFeaturesNV & setComputeDerivativeGroupQuads( VULKAN_HPP_NAMESPACE::Bool32 computeDerivativeGroupQuads_ ) VULKAN_HPP_NOEXCEPT
+ {
+ computeDerivativeGroupQuads = computeDerivativeGroupQuads_;
+ return *this;
+ }
+
+ PhysicalDeviceComputeShaderDerivativesFeaturesNV & setComputeDerivativeGroupLinear( VULKAN_HPP_NAMESPACE::Bool32 computeDerivativeGroupLinear_ ) VULKAN_HPP_NOEXCEPT
+ {
+ computeDerivativeGroupLinear = computeDerivativeGroupLinear_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceComputeShaderDerivativesFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceComputeShaderDerivativesFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceComputeShaderDerivativesFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceComputeShaderDerivativesFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceComputeShaderDerivativesFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( computeDerivativeGroupQuads == rhs.computeDerivativeGroupQuads )
+ && ( computeDerivativeGroupLinear == rhs.computeDerivativeGroupLinear );
+ }
+
+ bool operator!=( PhysicalDeviceComputeShaderDerivativesFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceComputeShaderDerivativesFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 computeDerivativeGroupQuads = {};
+ VULKAN_HPP_NAMESPACE::Bool32 computeDerivativeGroupLinear = {};
+ };
+ static_assert( sizeof( PhysicalDeviceComputeShaderDerivativesFeaturesNV ) == sizeof( VkPhysicalDeviceComputeShaderDerivativesFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceComputeShaderDerivativesFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceConditionalRenderingFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceConditionalRenderingFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 conditionalRendering_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 inheritedConditionalRendering_ = {} ) VULKAN_HPP_NOEXCEPT
+ : conditionalRendering( conditionalRendering_ )
+ , inheritedConditionalRendering( inheritedConditionalRendering_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceConditionalRenderingFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceConditionalRenderingFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceConditionalRenderingFeaturesEXT ) - offsetof( PhysicalDeviceConditionalRenderingFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceConditionalRenderingFeaturesEXT( VkPhysicalDeviceConditionalRenderingFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceConditionalRenderingFeaturesEXT& operator=( VkPhysicalDeviceConditionalRenderingFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceConditionalRenderingFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceConditionalRenderingFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceConditionalRenderingFeaturesEXT & setConditionalRendering( VULKAN_HPP_NAMESPACE::Bool32 conditionalRendering_ ) VULKAN_HPP_NOEXCEPT
+ {
+ conditionalRendering = conditionalRendering_;
+ return *this;
+ }
+
+ PhysicalDeviceConditionalRenderingFeaturesEXT & setInheritedConditionalRendering( VULKAN_HPP_NAMESPACE::Bool32 inheritedConditionalRendering_ ) VULKAN_HPP_NOEXCEPT
+ {
+ inheritedConditionalRendering = inheritedConditionalRendering_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceConditionalRenderingFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceConditionalRenderingFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceConditionalRenderingFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceConditionalRenderingFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceConditionalRenderingFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( conditionalRendering == rhs.conditionalRendering )
+ && ( inheritedConditionalRendering == rhs.inheritedConditionalRendering );
+ }
+
+ bool operator!=( PhysicalDeviceConditionalRenderingFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceConditionalRenderingFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 conditionalRendering = {};
+ VULKAN_HPP_NAMESPACE::Bool32 inheritedConditionalRendering = {};
+ };
+ static_assert( sizeof( PhysicalDeviceConditionalRenderingFeaturesEXT ) == sizeof( VkPhysicalDeviceConditionalRenderingFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceConditionalRenderingFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceConservativeRasterizationPropertiesEXT
+ {
+ PhysicalDeviceConservativeRasterizationPropertiesEXT( float primitiveOverestimationSize_ = {},
+ float maxExtraPrimitiveOverestimationSize_ = {},
+ float extraPrimitiveOverestimationSizeGranularity_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 primitiveUnderestimation_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 conservativePointAndLineRasterization_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 degenerateTrianglesRasterized_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 degenerateLinesRasterized_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 fullyCoveredFragmentShaderInputVariable_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 conservativeRasterizationPostDepthCoverage_ = {} ) VULKAN_HPP_NOEXCEPT
+ : primitiveOverestimationSize( primitiveOverestimationSize_ )
+ , maxExtraPrimitiveOverestimationSize( maxExtraPrimitiveOverestimationSize_ )
+ , extraPrimitiveOverestimationSizeGranularity( extraPrimitiveOverestimationSizeGranularity_ )
+ , primitiveUnderestimation( primitiveUnderestimation_ )
+ , conservativePointAndLineRasterization( conservativePointAndLineRasterization_ )
+ , degenerateTrianglesRasterized( degenerateTrianglesRasterized_ )
+ , degenerateLinesRasterized( degenerateLinesRasterized_ )
+ , fullyCoveredFragmentShaderInputVariable( fullyCoveredFragmentShaderInputVariable_ )
+ , conservativeRasterizationPostDepthCoverage( conservativeRasterizationPostDepthCoverage_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceConservativeRasterizationPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceConservativeRasterizationPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceConservativeRasterizationPropertiesEXT ) - offsetof( PhysicalDeviceConservativeRasterizationPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceConservativeRasterizationPropertiesEXT( VkPhysicalDeviceConservativeRasterizationPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceConservativeRasterizationPropertiesEXT& operator=( VkPhysicalDeviceConservativeRasterizationPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceConservativeRasterizationPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceConservativeRasterizationPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceConservativeRasterizationPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceConservativeRasterizationPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceConservativeRasterizationPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceConservativeRasterizationPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( primitiveOverestimationSize == rhs.primitiveOverestimationSize )
+ && ( maxExtraPrimitiveOverestimationSize == rhs.maxExtraPrimitiveOverestimationSize )
+ && ( extraPrimitiveOverestimationSizeGranularity == rhs.extraPrimitiveOverestimationSizeGranularity )
+ && ( primitiveUnderestimation == rhs.primitiveUnderestimation )
+ && ( conservativePointAndLineRasterization == rhs.conservativePointAndLineRasterization )
+ && ( degenerateTrianglesRasterized == rhs.degenerateTrianglesRasterized )
+ && ( degenerateLinesRasterized == rhs.degenerateLinesRasterized )
+ && ( fullyCoveredFragmentShaderInputVariable == rhs.fullyCoveredFragmentShaderInputVariable )
+ && ( conservativeRasterizationPostDepthCoverage == rhs.conservativeRasterizationPostDepthCoverage );
+ }
+
+ bool operator!=( PhysicalDeviceConservativeRasterizationPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceConservativeRasterizationPropertiesEXT;
+ void* pNext = {};
+ float primitiveOverestimationSize = {};
+ float maxExtraPrimitiveOverestimationSize = {};
+ float extraPrimitiveOverestimationSizeGranularity = {};
+ VULKAN_HPP_NAMESPACE::Bool32 primitiveUnderestimation = {};
+ VULKAN_HPP_NAMESPACE::Bool32 conservativePointAndLineRasterization = {};
+ VULKAN_HPP_NAMESPACE::Bool32 degenerateTrianglesRasterized = {};
+ VULKAN_HPP_NAMESPACE::Bool32 degenerateLinesRasterized = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fullyCoveredFragmentShaderInputVariable = {};
+ VULKAN_HPP_NAMESPACE::Bool32 conservativeRasterizationPostDepthCoverage = {};
+ };
+ static_assert( sizeof( PhysicalDeviceConservativeRasterizationPropertiesEXT ) == sizeof( VkPhysicalDeviceConservativeRasterizationPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceConservativeRasterizationPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceCooperativeMatrixFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceCooperativeMatrixFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 cooperativeMatrix_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 cooperativeMatrixRobustBufferAccess_ = {} ) VULKAN_HPP_NOEXCEPT
+ : cooperativeMatrix( cooperativeMatrix_ )
+ , cooperativeMatrixRobustBufferAccess( cooperativeMatrixRobustBufferAccess_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceCooperativeMatrixFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceCooperativeMatrixFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceCooperativeMatrixFeaturesNV ) - offsetof( PhysicalDeviceCooperativeMatrixFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceCooperativeMatrixFeaturesNV( VkPhysicalDeviceCooperativeMatrixFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceCooperativeMatrixFeaturesNV& operator=( VkPhysicalDeviceCooperativeMatrixFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceCooperativeMatrixFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceCooperativeMatrixFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceCooperativeMatrixFeaturesNV & setCooperativeMatrix( VULKAN_HPP_NAMESPACE::Bool32 cooperativeMatrix_ ) VULKAN_HPP_NOEXCEPT
+ {
+ cooperativeMatrix = cooperativeMatrix_;
+ return *this;
+ }
+
+ PhysicalDeviceCooperativeMatrixFeaturesNV & setCooperativeMatrixRobustBufferAccess( VULKAN_HPP_NAMESPACE::Bool32 cooperativeMatrixRobustBufferAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ cooperativeMatrixRobustBufferAccess = cooperativeMatrixRobustBufferAccess_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceCooperativeMatrixFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceCooperativeMatrixFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceCooperativeMatrixFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceCooperativeMatrixFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceCooperativeMatrixFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( cooperativeMatrix == rhs.cooperativeMatrix )
+ && ( cooperativeMatrixRobustBufferAccess == rhs.cooperativeMatrixRobustBufferAccess );
+ }
+
+ bool operator!=( PhysicalDeviceCooperativeMatrixFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceCooperativeMatrixFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 cooperativeMatrix = {};
+ VULKAN_HPP_NAMESPACE::Bool32 cooperativeMatrixRobustBufferAccess = {};
+ };
+ static_assert( sizeof( PhysicalDeviceCooperativeMatrixFeaturesNV ) == sizeof( VkPhysicalDeviceCooperativeMatrixFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceCooperativeMatrixFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceCooperativeMatrixPropertiesNV
+ {
+ PhysicalDeviceCooperativeMatrixPropertiesNV( VULKAN_HPP_NAMESPACE::ShaderStageFlags cooperativeMatrixSupportedStages_ = {} ) VULKAN_HPP_NOEXCEPT
+ : cooperativeMatrixSupportedStages( cooperativeMatrixSupportedStages_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceCooperativeMatrixPropertiesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceCooperativeMatrixPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceCooperativeMatrixPropertiesNV ) - offsetof( PhysicalDeviceCooperativeMatrixPropertiesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceCooperativeMatrixPropertiesNV( VkPhysicalDeviceCooperativeMatrixPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceCooperativeMatrixPropertiesNV& operator=( VkPhysicalDeviceCooperativeMatrixPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceCooperativeMatrixPropertiesNV const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceCooperativeMatrixPropertiesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceCooperativeMatrixPropertiesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceCooperativeMatrixPropertiesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceCooperativeMatrixPropertiesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceCooperativeMatrixPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( cooperativeMatrixSupportedStages == rhs.cooperativeMatrixSupportedStages );
+ }
+
+ bool operator!=( PhysicalDeviceCooperativeMatrixPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceCooperativeMatrixPropertiesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags cooperativeMatrixSupportedStages = {};
+ };
+ static_assert( sizeof( PhysicalDeviceCooperativeMatrixPropertiesNV ) == sizeof( VkPhysicalDeviceCooperativeMatrixPropertiesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceCooperativeMatrixPropertiesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceCornerSampledImageFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceCornerSampledImageFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 cornerSampledImage_ = {} ) VULKAN_HPP_NOEXCEPT
+ : cornerSampledImage( cornerSampledImage_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceCornerSampledImageFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceCornerSampledImageFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceCornerSampledImageFeaturesNV ) - offsetof( PhysicalDeviceCornerSampledImageFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceCornerSampledImageFeaturesNV( VkPhysicalDeviceCornerSampledImageFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceCornerSampledImageFeaturesNV& operator=( VkPhysicalDeviceCornerSampledImageFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceCornerSampledImageFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceCornerSampledImageFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceCornerSampledImageFeaturesNV & setCornerSampledImage( VULKAN_HPP_NAMESPACE::Bool32 cornerSampledImage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ cornerSampledImage = cornerSampledImage_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceCornerSampledImageFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceCornerSampledImageFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceCornerSampledImageFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceCornerSampledImageFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceCornerSampledImageFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( cornerSampledImage == rhs.cornerSampledImage );
+ }
+
+ bool operator!=( PhysicalDeviceCornerSampledImageFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceCornerSampledImageFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 cornerSampledImage = {};
+ };
+ static_assert( sizeof( PhysicalDeviceCornerSampledImageFeaturesNV ) == sizeof( VkPhysicalDeviceCornerSampledImageFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceCornerSampledImageFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceCoverageReductionModeFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceCoverageReductionModeFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 coverageReductionMode_ = {} ) VULKAN_HPP_NOEXCEPT
+ : coverageReductionMode( coverageReductionMode_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceCoverageReductionModeFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceCoverageReductionModeFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceCoverageReductionModeFeaturesNV ) - offsetof( PhysicalDeviceCoverageReductionModeFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceCoverageReductionModeFeaturesNV( VkPhysicalDeviceCoverageReductionModeFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceCoverageReductionModeFeaturesNV& operator=( VkPhysicalDeviceCoverageReductionModeFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceCoverageReductionModeFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceCoverageReductionModeFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceCoverageReductionModeFeaturesNV & setCoverageReductionMode( VULKAN_HPP_NAMESPACE::Bool32 coverageReductionMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ coverageReductionMode = coverageReductionMode_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceCoverageReductionModeFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceCoverageReductionModeFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceCoverageReductionModeFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceCoverageReductionModeFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceCoverageReductionModeFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( coverageReductionMode == rhs.coverageReductionMode );
+ }
+
+ bool operator!=( PhysicalDeviceCoverageReductionModeFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceCoverageReductionModeFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 coverageReductionMode = {};
+ };
+ static_assert( sizeof( PhysicalDeviceCoverageReductionModeFeaturesNV ) == sizeof( VkPhysicalDeviceCoverageReductionModeFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceCoverageReductionModeFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 dedicatedAllocationImageAliasing_ = {} ) VULKAN_HPP_NOEXCEPT
+ : dedicatedAllocationImageAliasing( dedicatedAllocationImageAliasing_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV ) - offsetof( PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV( VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV& operator=( VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV & setDedicatedAllocationImageAliasing( VULKAN_HPP_NAMESPACE::Bool32 dedicatedAllocationImageAliasing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dedicatedAllocationImageAliasing = dedicatedAllocationImageAliasing_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( dedicatedAllocationImageAliasing == rhs.dedicatedAllocationImageAliasing );
+ }
+
+ bool operator!=( PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 dedicatedAllocationImageAliasing = {};
+ };
+ static_assert( sizeof( PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV ) == sizeof( VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceDepthClipEnableFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceDepthClipEnableFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 depthClipEnable_ = {} ) VULKAN_HPP_NOEXCEPT
+ : depthClipEnable( depthClipEnable_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceDepthClipEnableFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceDepthClipEnableFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceDepthClipEnableFeaturesEXT ) - offsetof( PhysicalDeviceDepthClipEnableFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceDepthClipEnableFeaturesEXT( VkPhysicalDeviceDepthClipEnableFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceDepthClipEnableFeaturesEXT& operator=( VkPhysicalDeviceDepthClipEnableFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDepthClipEnableFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceDepthClipEnableFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceDepthClipEnableFeaturesEXT & setDepthClipEnable( VULKAN_HPP_NAMESPACE::Bool32 depthClipEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthClipEnable = depthClipEnable_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceDepthClipEnableFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceDepthClipEnableFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceDepthClipEnableFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceDepthClipEnableFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceDepthClipEnableFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( depthClipEnable == rhs.depthClipEnable );
+ }
+
+ bool operator!=( PhysicalDeviceDepthClipEnableFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDepthClipEnableFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 depthClipEnable = {};
+ };
+ static_assert( sizeof( PhysicalDeviceDepthClipEnableFeaturesEXT ) == sizeof( VkPhysicalDeviceDepthClipEnableFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceDepthClipEnableFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceDepthStencilResolveProperties
+ {
+ PhysicalDeviceDepthStencilResolveProperties( VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedDepthResolveModes_ = {},
+ VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedStencilResolveModes_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 independentResolveNone_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 independentResolve_ = {} ) VULKAN_HPP_NOEXCEPT
+ : supportedDepthResolveModes( supportedDepthResolveModes_ )
+ , supportedStencilResolveModes( supportedStencilResolveModes_ )
+ , independentResolveNone( independentResolveNone_ )
+ , independentResolve( independentResolve_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceDepthStencilResolveProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceDepthStencilResolveProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceDepthStencilResolveProperties ) - offsetof( PhysicalDeviceDepthStencilResolveProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceDepthStencilResolveProperties( VkPhysicalDeviceDepthStencilResolveProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceDepthStencilResolveProperties& operator=( VkPhysicalDeviceDepthStencilResolveProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDepthStencilResolveProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceDepthStencilResolveProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceDepthStencilResolveProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceDepthStencilResolveProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceDepthStencilResolveProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceDepthStencilResolveProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( supportedDepthResolveModes == rhs.supportedDepthResolveModes )
+ && ( supportedStencilResolveModes == rhs.supportedStencilResolveModes )
+ && ( independentResolveNone == rhs.independentResolveNone )
+ && ( independentResolve == rhs.independentResolve );
+ }
+
+ bool operator!=( PhysicalDeviceDepthStencilResolveProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDepthStencilResolveProperties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedDepthResolveModes = {};
+ VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedStencilResolveModes = {};
+ VULKAN_HPP_NAMESPACE::Bool32 independentResolveNone = {};
+ VULKAN_HPP_NAMESPACE::Bool32 independentResolve = {};
+ };
+ static_assert( sizeof( PhysicalDeviceDepthStencilResolveProperties ) == sizeof( VkPhysicalDeviceDepthStencilResolveProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceDepthStencilResolveProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceDescriptorIndexingFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceDescriptorIndexingFeatures( VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayDynamicIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayDynamicIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayDynamicIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformBufferUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingSampledImageUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageImageUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageBufferUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformTexelBufferUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageTexelBufferUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUpdateUnusedWhilePending_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingPartiallyBound_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingVariableDescriptorCount_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 runtimeDescriptorArray_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderInputAttachmentArrayDynamicIndexing( shaderInputAttachmentArrayDynamicIndexing_ )
+ , shaderUniformTexelBufferArrayDynamicIndexing( shaderUniformTexelBufferArrayDynamicIndexing_ )
+ , shaderStorageTexelBufferArrayDynamicIndexing( shaderStorageTexelBufferArrayDynamicIndexing_ )
+ , shaderUniformBufferArrayNonUniformIndexing( shaderUniformBufferArrayNonUniformIndexing_ )
+ , shaderSampledImageArrayNonUniformIndexing( shaderSampledImageArrayNonUniformIndexing_ )
+ , shaderStorageBufferArrayNonUniformIndexing( shaderStorageBufferArrayNonUniformIndexing_ )
+ , shaderStorageImageArrayNonUniformIndexing( shaderStorageImageArrayNonUniformIndexing_ )
+ , shaderInputAttachmentArrayNonUniformIndexing( shaderInputAttachmentArrayNonUniformIndexing_ )
+ , shaderUniformTexelBufferArrayNonUniformIndexing( shaderUniformTexelBufferArrayNonUniformIndexing_ )
+ , shaderStorageTexelBufferArrayNonUniformIndexing( shaderStorageTexelBufferArrayNonUniformIndexing_ )
+ , descriptorBindingUniformBufferUpdateAfterBind( descriptorBindingUniformBufferUpdateAfterBind_ )
+ , descriptorBindingSampledImageUpdateAfterBind( descriptorBindingSampledImageUpdateAfterBind_ )
+ , descriptorBindingStorageImageUpdateAfterBind( descriptorBindingStorageImageUpdateAfterBind_ )
+ , descriptorBindingStorageBufferUpdateAfterBind( descriptorBindingStorageBufferUpdateAfterBind_ )
+ , descriptorBindingUniformTexelBufferUpdateAfterBind( descriptorBindingUniformTexelBufferUpdateAfterBind_ )
+ , descriptorBindingStorageTexelBufferUpdateAfterBind( descriptorBindingStorageTexelBufferUpdateAfterBind_ )
+ , descriptorBindingUpdateUnusedWhilePending( descriptorBindingUpdateUnusedWhilePending_ )
+ , descriptorBindingPartiallyBound( descriptorBindingPartiallyBound_ )
+ , descriptorBindingVariableDescriptorCount( descriptorBindingVariableDescriptorCount_ )
+ , runtimeDescriptorArray( runtimeDescriptorArray_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorIndexingFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorIndexingFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorIndexingFeatures ) - offsetof( PhysicalDeviceDescriptorIndexingFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures( VkPhysicalDeviceDescriptorIndexingFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures& operator=( VkPhysicalDeviceDescriptorIndexingFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorIndexingFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setShaderInputAttachmentArrayDynamicIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayDynamicIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderInputAttachmentArrayDynamicIndexing = shaderInputAttachmentArrayDynamicIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setShaderUniformTexelBufferArrayDynamicIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayDynamicIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderUniformTexelBufferArrayDynamicIndexing = shaderUniformTexelBufferArrayDynamicIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setShaderStorageTexelBufferArrayDynamicIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayDynamicIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageTexelBufferArrayDynamicIndexing = shaderStorageTexelBufferArrayDynamicIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setShaderUniformBufferArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderUniformBufferArrayNonUniformIndexing = shaderUniformBufferArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setShaderSampledImageArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSampledImageArrayNonUniformIndexing = shaderSampledImageArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setShaderStorageBufferArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageBufferArrayNonUniformIndexing = shaderStorageBufferArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setShaderStorageImageArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageImageArrayNonUniformIndexing = shaderStorageImageArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setShaderInputAttachmentArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderInputAttachmentArrayNonUniformIndexing = shaderInputAttachmentArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setShaderUniformTexelBufferArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderUniformTexelBufferArrayNonUniformIndexing = shaderUniformTexelBufferArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setShaderStorageTexelBufferArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageTexelBufferArrayNonUniformIndexing = shaderStorageTexelBufferArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setDescriptorBindingUniformBufferUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformBufferUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingUniformBufferUpdateAfterBind = descriptorBindingUniformBufferUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setDescriptorBindingSampledImageUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingSampledImageUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingSampledImageUpdateAfterBind = descriptorBindingSampledImageUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setDescriptorBindingStorageImageUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageImageUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingStorageImageUpdateAfterBind = descriptorBindingStorageImageUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setDescriptorBindingStorageBufferUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageBufferUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingStorageBufferUpdateAfterBind = descriptorBindingStorageBufferUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setDescriptorBindingUniformTexelBufferUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformTexelBufferUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingUniformTexelBufferUpdateAfterBind = descriptorBindingUniformTexelBufferUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setDescriptorBindingStorageTexelBufferUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageTexelBufferUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingStorageTexelBufferUpdateAfterBind = descriptorBindingStorageTexelBufferUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setDescriptorBindingUpdateUnusedWhilePending( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUpdateUnusedWhilePending_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingUpdateUnusedWhilePending = descriptorBindingUpdateUnusedWhilePending_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setDescriptorBindingPartiallyBound( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingPartiallyBound_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingPartiallyBound = descriptorBindingPartiallyBound_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setDescriptorBindingVariableDescriptorCount( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingVariableDescriptorCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingVariableDescriptorCount = descriptorBindingVariableDescriptorCount_;
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingFeatures & setRuntimeDescriptorArray( VULKAN_HPP_NAMESPACE::Bool32 runtimeDescriptorArray_ ) VULKAN_HPP_NOEXCEPT
+ {
+ runtimeDescriptorArray = runtimeDescriptorArray_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceDescriptorIndexingFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceDescriptorIndexingFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceDescriptorIndexingFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceDescriptorIndexingFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceDescriptorIndexingFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderInputAttachmentArrayDynamicIndexing == rhs.shaderInputAttachmentArrayDynamicIndexing )
+ && ( shaderUniformTexelBufferArrayDynamicIndexing == rhs.shaderUniformTexelBufferArrayDynamicIndexing )
+ && ( shaderStorageTexelBufferArrayDynamicIndexing == rhs.shaderStorageTexelBufferArrayDynamicIndexing )
+ && ( shaderUniformBufferArrayNonUniformIndexing == rhs.shaderUniformBufferArrayNonUniformIndexing )
+ && ( shaderSampledImageArrayNonUniformIndexing == rhs.shaderSampledImageArrayNonUniformIndexing )
+ && ( shaderStorageBufferArrayNonUniformIndexing == rhs.shaderStorageBufferArrayNonUniformIndexing )
+ && ( shaderStorageImageArrayNonUniformIndexing == rhs.shaderStorageImageArrayNonUniformIndexing )
+ && ( shaderInputAttachmentArrayNonUniformIndexing == rhs.shaderInputAttachmentArrayNonUniformIndexing )
+ && ( shaderUniformTexelBufferArrayNonUniformIndexing == rhs.shaderUniformTexelBufferArrayNonUniformIndexing )
+ && ( shaderStorageTexelBufferArrayNonUniformIndexing == rhs.shaderStorageTexelBufferArrayNonUniformIndexing )
+ && ( descriptorBindingUniformBufferUpdateAfterBind == rhs.descriptorBindingUniformBufferUpdateAfterBind )
+ && ( descriptorBindingSampledImageUpdateAfterBind == rhs.descriptorBindingSampledImageUpdateAfterBind )
+ && ( descriptorBindingStorageImageUpdateAfterBind == rhs.descriptorBindingStorageImageUpdateAfterBind )
+ && ( descriptorBindingStorageBufferUpdateAfterBind == rhs.descriptorBindingStorageBufferUpdateAfterBind )
+ && ( descriptorBindingUniformTexelBufferUpdateAfterBind == rhs.descriptorBindingUniformTexelBufferUpdateAfterBind )
+ && ( descriptorBindingStorageTexelBufferUpdateAfterBind == rhs.descriptorBindingStorageTexelBufferUpdateAfterBind )
+ && ( descriptorBindingUpdateUnusedWhilePending == rhs.descriptorBindingUpdateUnusedWhilePending )
+ && ( descriptorBindingPartiallyBound == rhs.descriptorBindingPartiallyBound )
+ && ( descriptorBindingVariableDescriptorCount == rhs.descriptorBindingVariableDescriptorCount )
+ && ( runtimeDescriptorArray == rhs.runtimeDescriptorArray );
+ }
+
+ bool operator!=( PhysicalDeviceDescriptorIndexingFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDescriptorIndexingFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayDynamicIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayDynamicIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayDynamicIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformBufferUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingSampledImageUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageImageUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageBufferUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformTexelBufferUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageTexelBufferUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUpdateUnusedWhilePending = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingPartiallyBound = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingVariableDescriptorCount = {};
+ VULKAN_HPP_NAMESPACE::Bool32 runtimeDescriptorArray = {};
+ };
+ static_assert( sizeof( PhysicalDeviceDescriptorIndexingFeatures ) == sizeof( VkPhysicalDeviceDescriptorIndexingFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceDescriptorIndexingFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceDescriptorIndexingProperties
+ {
+ PhysicalDeviceDescriptorIndexingProperties( uint32_t maxUpdateAfterBindDescriptorsInAllPools_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexingNative_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexingNative_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexingNative_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexingNative_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexingNative_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 robustBufferAccessUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 quadDivergentImplicitLod_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindSamplers_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments_ = {},
+ uint32_t maxPerStageUpdateAfterBindResources_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindSamplers_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindSampledImages_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindStorageImages_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindInputAttachments_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxUpdateAfterBindDescriptorsInAllPools( maxUpdateAfterBindDescriptorsInAllPools_ )
+ , shaderUniformBufferArrayNonUniformIndexingNative( shaderUniformBufferArrayNonUniformIndexingNative_ )
+ , shaderSampledImageArrayNonUniformIndexingNative( shaderSampledImageArrayNonUniformIndexingNative_ )
+ , shaderStorageBufferArrayNonUniformIndexingNative( shaderStorageBufferArrayNonUniformIndexingNative_ )
+ , shaderStorageImageArrayNonUniformIndexingNative( shaderStorageImageArrayNonUniformIndexingNative_ )
+ , shaderInputAttachmentArrayNonUniformIndexingNative( shaderInputAttachmentArrayNonUniformIndexingNative_ )
+ , robustBufferAccessUpdateAfterBind( robustBufferAccessUpdateAfterBind_ )
+ , quadDivergentImplicitLod( quadDivergentImplicitLod_ )
+ , maxPerStageDescriptorUpdateAfterBindSamplers( maxPerStageDescriptorUpdateAfterBindSamplers_ )
+ , maxPerStageDescriptorUpdateAfterBindUniformBuffers( maxPerStageDescriptorUpdateAfterBindUniformBuffers_ )
+ , maxPerStageDescriptorUpdateAfterBindStorageBuffers( maxPerStageDescriptorUpdateAfterBindStorageBuffers_ )
+ , maxPerStageDescriptorUpdateAfterBindSampledImages( maxPerStageDescriptorUpdateAfterBindSampledImages_ )
+ , maxPerStageDescriptorUpdateAfterBindStorageImages( maxPerStageDescriptorUpdateAfterBindStorageImages_ )
+ , maxPerStageDescriptorUpdateAfterBindInputAttachments( maxPerStageDescriptorUpdateAfterBindInputAttachments_ )
+ , maxPerStageUpdateAfterBindResources( maxPerStageUpdateAfterBindResources_ )
+ , maxDescriptorSetUpdateAfterBindSamplers( maxDescriptorSetUpdateAfterBindSamplers_ )
+ , maxDescriptorSetUpdateAfterBindUniformBuffers( maxDescriptorSetUpdateAfterBindUniformBuffers_ )
+ , maxDescriptorSetUpdateAfterBindUniformBuffersDynamic( maxDescriptorSetUpdateAfterBindUniformBuffersDynamic_ )
+ , maxDescriptorSetUpdateAfterBindStorageBuffers( maxDescriptorSetUpdateAfterBindStorageBuffers_ )
+ , maxDescriptorSetUpdateAfterBindStorageBuffersDynamic( maxDescriptorSetUpdateAfterBindStorageBuffersDynamic_ )
+ , maxDescriptorSetUpdateAfterBindSampledImages( maxDescriptorSetUpdateAfterBindSampledImages_ )
+ , maxDescriptorSetUpdateAfterBindStorageImages( maxDescriptorSetUpdateAfterBindStorageImages_ )
+ , maxDescriptorSetUpdateAfterBindInputAttachments( maxDescriptorSetUpdateAfterBindInputAttachments_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorIndexingProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorIndexingProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorIndexingProperties ) - offsetof( PhysicalDeviceDescriptorIndexingProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceDescriptorIndexingProperties( VkPhysicalDeviceDescriptorIndexingProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceDescriptorIndexingProperties& operator=( VkPhysicalDeviceDescriptorIndexingProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDescriptorIndexingProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceDescriptorIndexingProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceDescriptorIndexingProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceDescriptorIndexingProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceDescriptorIndexingProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceDescriptorIndexingProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxUpdateAfterBindDescriptorsInAllPools == rhs.maxUpdateAfterBindDescriptorsInAllPools )
+ && ( shaderUniformBufferArrayNonUniformIndexingNative == rhs.shaderUniformBufferArrayNonUniformIndexingNative )
+ && ( shaderSampledImageArrayNonUniformIndexingNative == rhs.shaderSampledImageArrayNonUniformIndexingNative )
+ && ( shaderStorageBufferArrayNonUniformIndexingNative == rhs.shaderStorageBufferArrayNonUniformIndexingNative )
+ && ( shaderStorageImageArrayNonUniformIndexingNative == rhs.shaderStorageImageArrayNonUniformIndexingNative )
+ && ( shaderInputAttachmentArrayNonUniformIndexingNative == rhs.shaderInputAttachmentArrayNonUniformIndexingNative )
+ && ( robustBufferAccessUpdateAfterBind == rhs.robustBufferAccessUpdateAfterBind )
+ && ( quadDivergentImplicitLod == rhs.quadDivergentImplicitLod )
+ && ( maxPerStageDescriptorUpdateAfterBindSamplers == rhs.maxPerStageDescriptorUpdateAfterBindSamplers )
+ && ( maxPerStageDescriptorUpdateAfterBindUniformBuffers == rhs.maxPerStageDescriptorUpdateAfterBindUniformBuffers )
+ && ( maxPerStageDescriptorUpdateAfterBindStorageBuffers == rhs.maxPerStageDescriptorUpdateAfterBindStorageBuffers )
+ && ( maxPerStageDescriptorUpdateAfterBindSampledImages == rhs.maxPerStageDescriptorUpdateAfterBindSampledImages )
+ && ( maxPerStageDescriptorUpdateAfterBindStorageImages == rhs.maxPerStageDescriptorUpdateAfterBindStorageImages )
+ && ( maxPerStageDescriptorUpdateAfterBindInputAttachments == rhs.maxPerStageDescriptorUpdateAfterBindInputAttachments )
+ && ( maxPerStageUpdateAfterBindResources == rhs.maxPerStageUpdateAfterBindResources )
+ && ( maxDescriptorSetUpdateAfterBindSamplers == rhs.maxDescriptorSetUpdateAfterBindSamplers )
+ && ( maxDescriptorSetUpdateAfterBindUniformBuffers == rhs.maxDescriptorSetUpdateAfterBindUniformBuffers )
+ && ( maxDescriptorSetUpdateAfterBindUniformBuffersDynamic == rhs.maxDescriptorSetUpdateAfterBindUniformBuffersDynamic )
+ && ( maxDescriptorSetUpdateAfterBindStorageBuffers == rhs.maxDescriptorSetUpdateAfterBindStorageBuffers )
+ && ( maxDescriptorSetUpdateAfterBindStorageBuffersDynamic == rhs.maxDescriptorSetUpdateAfterBindStorageBuffersDynamic )
+ && ( maxDescriptorSetUpdateAfterBindSampledImages == rhs.maxDescriptorSetUpdateAfterBindSampledImages )
+ && ( maxDescriptorSetUpdateAfterBindStorageImages == rhs.maxDescriptorSetUpdateAfterBindStorageImages )
+ && ( maxDescriptorSetUpdateAfterBindInputAttachments == rhs.maxDescriptorSetUpdateAfterBindInputAttachments );
+ }
+
+ bool operator!=( PhysicalDeviceDescriptorIndexingProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDescriptorIndexingProperties;
+ void* pNext = {};
+ uint32_t maxUpdateAfterBindDescriptorsInAllPools = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexingNative = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexingNative = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexingNative = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexingNative = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexingNative = {};
+ VULKAN_HPP_NAMESPACE::Bool32 robustBufferAccessUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 quadDivergentImplicitLod = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindSamplers = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments = {};
+ uint32_t maxPerStageUpdateAfterBindResources = {};
+ uint32_t maxDescriptorSetUpdateAfterBindSamplers = {};
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers = {};
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = {};
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers = {};
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = {};
+ uint32_t maxDescriptorSetUpdateAfterBindSampledImages = {};
+ uint32_t maxDescriptorSetUpdateAfterBindStorageImages = {};
+ uint32_t maxDescriptorSetUpdateAfterBindInputAttachments = {};
+ };
+ static_assert( sizeof( PhysicalDeviceDescriptorIndexingProperties ) == sizeof( VkPhysicalDeviceDescriptorIndexingProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceDescriptorIndexingProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceDiscardRectanglePropertiesEXT
+ {
+ PhysicalDeviceDiscardRectanglePropertiesEXT( uint32_t maxDiscardRectangles_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxDiscardRectangles( maxDiscardRectangles_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceDiscardRectanglePropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceDiscardRectanglePropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceDiscardRectanglePropertiesEXT ) - offsetof( PhysicalDeviceDiscardRectanglePropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceDiscardRectanglePropertiesEXT( VkPhysicalDeviceDiscardRectanglePropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceDiscardRectanglePropertiesEXT& operator=( VkPhysicalDeviceDiscardRectanglePropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDiscardRectanglePropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceDiscardRectanglePropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceDiscardRectanglePropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceDiscardRectanglePropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceDiscardRectanglePropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceDiscardRectanglePropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxDiscardRectangles == rhs.maxDiscardRectangles );
+ }
+
+ bool operator!=( PhysicalDeviceDiscardRectanglePropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDiscardRectanglePropertiesEXT;
+ void* pNext = {};
+ uint32_t maxDiscardRectangles = {};
+ };
+ static_assert( sizeof( PhysicalDeviceDiscardRectanglePropertiesEXT ) == sizeof( VkPhysicalDeviceDiscardRectanglePropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceDiscardRectanglePropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceDriverProperties
+ {
+ PhysicalDeviceDriverProperties( VULKAN_HPP_NAMESPACE::DriverId driverID_ = VULKAN_HPP_NAMESPACE::DriverId::eAmdProprietary,
+ std::array<char,VK_MAX_DRIVER_NAME_SIZE> const& driverName_ = {},
+ std::array<char,VK_MAX_DRIVER_INFO_SIZE> const& driverInfo_ = {},
+ VULKAN_HPP_NAMESPACE::ConformanceVersion conformanceVersion_ = {} ) VULKAN_HPP_NOEXCEPT
+ : driverID( driverID_ )
+ , driverName{}
+ , driverInfo{}
+ , conformanceVersion( conformanceVersion_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_NAME_SIZE,VK_MAX_DRIVER_NAME_SIZE>::copy( driverName, driverName_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_INFO_SIZE,VK_MAX_DRIVER_INFO_SIZE>::copy( driverInfo, driverInfo_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceDriverProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceDriverProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceDriverProperties ) - offsetof( PhysicalDeviceDriverProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceDriverProperties( VkPhysicalDeviceDriverProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceDriverProperties& operator=( VkPhysicalDeviceDriverProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDriverProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceDriverProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceDriverProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceDriverProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceDriverProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceDriverProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( driverID == rhs.driverID )
+ && ( memcmp( driverName, rhs.driverName, VK_MAX_DRIVER_NAME_SIZE * sizeof( char ) ) == 0 )
+ && ( memcmp( driverInfo, rhs.driverInfo, VK_MAX_DRIVER_INFO_SIZE * sizeof( char ) ) == 0 )
+ && ( conformanceVersion == rhs.conformanceVersion );
+ }
+
+ bool operator!=( PhysicalDeviceDriverProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDriverProperties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DriverId driverID = VULKAN_HPP_NAMESPACE::DriverId::eAmdProprietary;
+ char driverName[VK_MAX_DRIVER_NAME_SIZE] = {};
+ char driverInfo[VK_MAX_DRIVER_INFO_SIZE] = {};
+ VULKAN_HPP_NAMESPACE::ConformanceVersion conformanceVersion = {};
+ };
+ static_assert( sizeof( PhysicalDeviceDriverProperties ) == sizeof( VkPhysicalDeviceDriverProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceDriverProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceExclusiveScissorFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceExclusiveScissorFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 exclusiveScissor_ = {} ) VULKAN_HPP_NOEXCEPT
+ : exclusiveScissor( exclusiveScissor_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceExclusiveScissorFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceExclusiveScissorFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceExclusiveScissorFeaturesNV ) - offsetof( PhysicalDeviceExclusiveScissorFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceExclusiveScissorFeaturesNV( VkPhysicalDeviceExclusiveScissorFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceExclusiveScissorFeaturesNV& operator=( VkPhysicalDeviceExclusiveScissorFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceExclusiveScissorFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceExclusiveScissorFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceExclusiveScissorFeaturesNV & setExclusiveScissor( VULKAN_HPP_NAMESPACE::Bool32 exclusiveScissor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ exclusiveScissor = exclusiveScissor_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceExclusiveScissorFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceExclusiveScissorFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceExclusiveScissorFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceExclusiveScissorFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceExclusiveScissorFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( exclusiveScissor == rhs.exclusiveScissor );
+ }
+
+ bool operator!=( PhysicalDeviceExclusiveScissorFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceExclusiveScissorFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 exclusiveScissor = {};
+ };
+ static_assert( sizeof( PhysicalDeviceExclusiveScissorFeaturesNV ) == sizeof( VkPhysicalDeviceExclusiveScissorFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceExclusiveScissorFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceExternalBufferInfo
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalBufferInfo( VULKAN_HPP_NAMESPACE::BufferCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::BufferUsageFlags usage_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , usage( usage_ )
+ , handleType( handleType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo ) - offsetof( PhysicalDeviceExternalBufferInfo, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceExternalBufferInfo( VkPhysicalDeviceExternalBufferInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceExternalBufferInfo& operator=( VkPhysicalDeviceExternalBufferInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceExternalBufferInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceExternalBufferInfo & setFlags( VULKAN_HPP_NAMESPACE::BufferCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PhysicalDeviceExternalBufferInfo & setUsage( VULKAN_HPP_NAMESPACE::BufferUsageFlags usage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ usage = usage_;
+ return *this;
+ }
+
+ PhysicalDeviceExternalBufferInfo & setHandleType( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceExternalBufferInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceExternalBufferInfo*>( this );
+ }
+
+ operator VkPhysicalDeviceExternalBufferInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceExternalBufferInfo*>( this );
+ }
+
+ bool operator==( PhysicalDeviceExternalBufferInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( usage == rhs.usage )
+ && ( handleType == rhs.handleType );
+ }
+
+ bool operator!=( PhysicalDeviceExternalBufferInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceExternalBufferInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::BufferCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::BufferUsageFlags usage = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd;
+ };
+ static_assert( sizeof( PhysicalDeviceExternalBufferInfo ) == sizeof( VkPhysicalDeviceExternalBufferInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceExternalBufferInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceExternalFenceInfo
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalFenceInfo( VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits::eOpaqueFd ) VULKAN_HPP_NOEXCEPT
+ : handleType( handleType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFenceInfo & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFenceInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFenceInfo ) - offsetof( PhysicalDeviceExternalFenceInfo, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceExternalFenceInfo( VkPhysicalDeviceExternalFenceInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceExternalFenceInfo& operator=( VkPhysicalDeviceExternalFenceInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFenceInfo const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceExternalFenceInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceExternalFenceInfo & setHandleType( VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceExternalFenceInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceExternalFenceInfo*>( this );
+ }
+
+ operator VkPhysicalDeviceExternalFenceInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceExternalFenceInfo*>( this );
+ }
+
+ bool operator==( PhysicalDeviceExternalFenceInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleType == rhs.handleType );
+ }
+
+ bool operator!=( PhysicalDeviceExternalFenceInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceExternalFenceInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalFenceHandleTypeFlagBits::eOpaqueFd;
+ };
+ static_assert( sizeof( PhysicalDeviceExternalFenceInfo ) == sizeof( VkPhysicalDeviceExternalFenceInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceExternalFenceInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceExternalImageFormatInfo
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalImageFormatInfo( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd ) VULKAN_HPP_NOEXCEPT
+ : handleType( handleType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalImageFormatInfo & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalImageFormatInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalImageFormatInfo ) - offsetof( PhysicalDeviceExternalImageFormatInfo, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceExternalImageFormatInfo( VkPhysicalDeviceExternalImageFormatInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceExternalImageFormatInfo& operator=( VkPhysicalDeviceExternalImageFormatInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalImageFormatInfo const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceExternalImageFormatInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceExternalImageFormatInfo & setHandleType( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceExternalImageFormatInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceExternalImageFormatInfo*>( this );
+ }
+
+ operator VkPhysicalDeviceExternalImageFormatInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceExternalImageFormatInfo*>( this );
+ }
+
+ bool operator==( PhysicalDeviceExternalImageFormatInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleType == rhs.handleType );
+ }
+
+ bool operator!=( PhysicalDeviceExternalImageFormatInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceExternalImageFormatInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits::eOpaqueFd;
+ };
+ static_assert( sizeof( PhysicalDeviceExternalImageFormatInfo ) == sizeof( VkPhysicalDeviceExternalImageFormatInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceExternalImageFormatInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceExternalMemoryHostPropertiesEXT
+ {
+ PhysicalDeviceExternalMemoryHostPropertiesEXT( VULKAN_HPP_NAMESPACE::DeviceSize minImportedHostPointerAlignment_ = {} ) VULKAN_HPP_NOEXCEPT
+ : minImportedHostPointerAlignment( minImportedHostPointerAlignment_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalMemoryHostPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalMemoryHostPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalMemoryHostPropertiesEXT ) - offsetof( PhysicalDeviceExternalMemoryHostPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceExternalMemoryHostPropertiesEXT( VkPhysicalDeviceExternalMemoryHostPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceExternalMemoryHostPropertiesEXT& operator=( VkPhysicalDeviceExternalMemoryHostPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalMemoryHostPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceExternalMemoryHostPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceExternalMemoryHostPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceExternalMemoryHostPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceExternalMemoryHostPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceExternalMemoryHostPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( minImportedHostPointerAlignment == rhs.minImportedHostPointerAlignment );
+ }
+
+ bool operator!=( PhysicalDeviceExternalMemoryHostPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceExternalMemoryHostPropertiesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize minImportedHostPointerAlignment = {};
+ };
+ static_assert( sizeof( PhysicalDeviceExternalMemoryHostPropertiesEXT ) == sizeof( VkPhysicalDeviceExternalMemoryHostPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceExternalMemoryHostPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceExternalSemaphoreInfo
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalSemaphoreInfo( VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd ) VULKAN_HPP_NOEXCEPT
+ : handleType( handleType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalSemaphoreInfo & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalSemaphoreInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalSemaphoreInfo ) - offsetof( PhysicalDeviceExternalSemaphoreInfo, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceExternalSemaphoreInfo( VkPhysicalDeviceExternalSemaphoreInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceExternalSemaphoreInfo& operator=( VkPhysicalDeviceExternalSemaphoreInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalSemaphoreInfo const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceExternalSemaphoreInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceExternalSemaphoreInfo & setHandleType( VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceExternalSemaphoreInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceExternalSemaphoreInfo*>( this );
+ }
+
+ operator VkPhysicalDeviceExternalSemaphoreInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceExternalSemaphoreInfo*>( this );
+ }
+
+ bool operator==( PhysicalDeviceExternalSemaphoreInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( handleType == rhs.handleType );
+ }
+
+ bool operator!=( PhysicalDeviceExternalSemaphoreInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceExternalSemaphoreInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd;
+ };
+ static_assert( sizeof( PhysicalDeviceExternalSemaphoreInfo ) == sizeof( VkPhysicalDeviceExternalSemaphoreInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceExternalSemaphoreInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceFeatures2
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceFeatures2( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures features_ = {} ) VULKAN_HPP_NOEXCEPT
+ : features( features_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 ) - offsetof( PhysicalDeviceFeatures2, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceFeatures2( VkPhysicalDeviceFeatures2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceFeatures2& operator=( VkPhysicalDeviceFeatures2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceFeatures2 & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceFeatures2 & setFeatures( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures features_ ) VULKAN_HPP_NOEXCEPT
+ {
+ features = features_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceFeatures2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceFeatures2*>( this );
+ }
+
+ operator VkPhysicalDeviceFeatures2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceFeatures2*>( this );
+ }
+
+ bool operator==( PhysicalDeviceFeatures2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( features == rhs.features );
+ }
+
+ bool operator!=( PhysicalDeviceFeatures2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceFeatures2;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures features = {};
+ };
+ static_assert( sizeof( PhysicalDeviceFeatures2 ) == sizeof( VkPhysicalDeviceFeatures2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceFeatures2>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceFloatControlsProperties
+ {
+ PhysicalDeviceFloatControlsProperties( VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence denormBehaviorIndependence_ = VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence::e32BitOnly,
+ VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence roundingModeIndependence_ = VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence::e32BitOnly,
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat64_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat64_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat64_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat64_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat64_ = {} ) VULKAN_HPP_NOEXCEPT
+ : denormBehaviorIndependence( denormBehaviorIndependence_ )
+ , roundingModeIndependence( roundingModeIndependence_ )
+ , shaderSignedZeroInfNanPreserveFloat16( shaderSignedZeroInfNanPreserveFloat16_ )
+ , shaderSignedZeroInfNanPreserveFloat32( shaderSignedZeroInfNanPreserveFloat32_ )
+ , shaderSignedZeroInfNanPreserveFloat64( shaderSignedZeroInfNanPreserveFloat64_ )
+ , shaderDenormPreserveFloat16( shaderDenormPreserveFloat16_ )
+ , shaderDenormPreserveFloat32( shaderDenormPreserveFloat32_ )
+ , shaderDenormPreserveFloat64( shaderDenormPreserveFloat64_ )
+ , shaderDenormFlushToZeroFloat16( shaderDenormFlushToZeroFloat16_ )
+ , shaderDenormFlushToZeroFloat32( shaderDenormFlushToZeroFloat32_ )
+ , shaderDenormFlushToZeroFloat64( shaderDenormFlushToZeroFloat64_ )
+ , shaderRoundingModeRTEFloat16( shaderRoundingModeRTEFloat16_ )
+ , shaderRoundingModeRTEFloat32( shaderRoundingModeRTEFloat32_ )
+ , shaderRoundingModeRTEFloat64( shaderRoundingModeRTEFloat64_ )
+ , shaderRoundingModeRTZFloat16( shaderRoundingModeRTZFloat16_ )
+ , shaderRoundingModeRTZFloat32( shaderRoundingModeRTZFloat32_ )
+ , shaderRoundingModeRTZFloat64( shaderRoundingModeRTZFloat64_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFloatControlsProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceFloatControlsProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceFloatControlsProperties ) - offsetof( PhysicalDeviceFloatControlsProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceFloatControlsProperties( VkPhysicalDeviceFloatControlsProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceFloatControlsProperties& operator=( VkPhysicalDeviceFloatControlsProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceFloatControlsProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceFloatControlsProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceFloatControlsProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceFloatControlsProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceFloatControlsProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceFloatControlsProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( denormBehaviorIndependence == rhs.denormBehaviorIndependence )
+ && ( roundingModeIndependence == rhs.roundingModeIndependence )
+ && ( shaderSignedZeroInfNanPreserveFloat16 == rhs.shaderSignedZeroInfNanPreserveFloat16 )
+ && ( shaderSignedZeroInfNanPreserveFloat32 == rhs.shaderSignedZeroInfNanPreserveFloat32 )
+ && ( shaderSignedZeroInfNanPreserveFloat64 == rhs.shaderSignedZeroInfNanPreserveFloat64 )
+ && ( shaderDenormPreserveFloat16 == rhs.shaderDenormPreserveFloat16 )
+ && ( shaderDenormPreserveFloat32 == rhs.shaderDenormPreserveFloat32 )
+ && ( shaderDenormPreserveFloat64 == rhs.shaderDenormPreserveFloat64 )
+ && ( shaderDenormFlushToZeroFloat16 == rhs.shaderDenormFlushToZeroFloat16 )
+ && ( shaderDenormFlushToZeroFloat32 == rhs.shaderDenormFlushToZeroFloat32 )
+ && ( shaderDenormFlushToZeroFloat64 == rhs.shaderDenormFlushToZeroFloat64 )
+ && ( shaderRoundingModeRTEFloat16 == rhs.shaderRoundingModeRTEFloat16 )
+ && ( shaderRoundingModeRTEFloat32 == rhs.shaderRoundingModeRTEFloat32 )
+ && ( shaderRoundingModeRTEFloat64 == rhs.shaderRoundingModeRTEFloat64 )
+ && ( shaderRoundingModeRTZFloat16 == rhs.shaderRoundingModeRTZFloat16 )
+ && ( shaderRoundingModeRTZFloat32 == rhs.shaderRoundingModeRTZFloat32 )
+ && ( shaderRoundingModeRTZFloat64 == rhs.shaderRoundingModeRTZFloat64 );
+ }
+
+ bool operator!=( PhysicalDeviceFloatControlsProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceFloatControlsProperties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence denormBehaviorIndependence = VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence::e32BitOnly;
+ VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence roundingModeIndependence = VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence::e32BitOnly;
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat64 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat64 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat64 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat64 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat64 = {};
+ };
+ static_assert( sizeof( PhysicalDeviceFloatControlsProperties ) == sizeof( VkPhysicalDeviceFloatControlsProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceFloatControlsProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceFragmentDensityMapFeaturesEXT
+ {
+ PhysicalDeviceFragmentDensityMapFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 fragmentDensityMap_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentDensityMapDynamic_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentDensityMapNonSubsampledImages_ = {} ) VULKAN_HPP_NOEXCEPT
+ : fragmentDensityMap( fragmentDensityMap_ )
+ , fragmentDensityMapDynamic( fragmentDensityMapDynamic_ )
+ , fragmentDensityMapNonSubsampledImages( fragmentDensityMapNonSubsampledImages_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentDensityMapFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentDensityMapFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentDensityMapFeaturesEXT ) - offsetof( PhysicalDeviceFragmentDensityMapFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceFragmentDensityMapFeaturesEXT( VkPhysicalDeviceFragmentDensityMapFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceFragmentDensityMapFeaturesEXT& operator=( VkPhysicalDeviceFragmentDensityMapFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentDensityMapFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceFragmentDensityMapFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceFragmentDensityMapFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceFragmentDensityMapFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceFragmentDensityMapFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceFragmentDensityMapFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( fragmentDensityMap == rhs.fragmentDensityMap )
+ && ( fragmentDensityMapDynamic == rhs.fragmentDensityMapDynamic )
+ && ( fragmentDensityMapNonSubsampledImages == rhs.fragmentDensityMapNonSubsampledImages );
+ }
+
+ bool operator!=( PhysicalDeviceFragmentDensityMapFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceFragmentDensityMapFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentDensityMap = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentDensityMapDynamic = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentDensityMapNonSubsampledImages = {};
+ };
+ static_assert( sizeof( PhysicalDeviceFragmentDensityMapFeaturesEXT ) == sizeof( VkPhysicalDeviceFragmentDensityMapFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceFragmentDensityMapFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceFragmentDensityMapPropertiesEXT
+ {
+ PhysicalDeviceFragmentDensityMapPropertiesEXT( VULKAN_HPP_NAMESPACE::Extent2D minFragmentDensityTexelSize_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D maxFragmentDensityTexelSize_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentDensityInvocations_ = {} ) VULKAN_HPP_NOEXCEPT
+ : minFragmentDensityTexelSize( minFragmentDensityTexelSize_ )
+ , maxFragmentDensityTexelSize( maxFragmentDensityTexelSize_ )
+ , fragmentDensityInvocations( fragmentDensityInvocations_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentDensityMapPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentDensityMapPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentDensityMapPropertiesEXT ) - offsetof( PhysicalDeviceFragmentDensityMapPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceFragmentDensityMapPropertiesEXT( VkPhysicalDeviceFragmentDensityMapPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceFragmentDensityMapPropertiesEXT& operator=( VkPhysicalDeviceFragmentDensityMapPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentDensityMapPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceFragmentDensityMapPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceFragmentDensityMapPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceFragmentDensityMapPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceFragmentDensityMapPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceFragmentDensityMapPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( minFragmentDensityTexelSize == rhs.minFragmentDensityTexelSize )
+ && ( maxFragmentDensityTexelSize == rhs.maxFragmentDensityTexelSize )
+ && ( fragmentDensityInvocations == rhs.fragmentDensityInvocations );
+ }
+
+ bool operator!=( PhysicalDeviceFragmentDensityMapPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceFragmentDensityMapPropertiesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Extent2D minFragmentDensityTexelSize = {};
+ VULKAN_HPP_NAMESPACE::Extent2D maxFragmentDensityTexelSize = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentDensityInvocations = {};
+ };
+ static_assert( sizeof( PhysicalDeviceFragmentDensityMapPropertiesEXT ) == sizeof( VkPhysicalDeviceFragmentDensityMapPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceFragmentDensityMapPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceFragmentShaderBarycentricFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceFragmentShaderBarycentricFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderBarycentric_ = {} ) VULKAN_HPP_NOEXCEPT
+ : fragmentShaderBarycentric( fragmentShaderBarycentric_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentShaderBarycentricFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentShaderBarycentricFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentShaderBarycentricFeaturesNV ) - offsetof( PhysicalDeviceFragmentShaderBarycentricFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceFragmentShaderBarycentricFeaturesNV( VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceFragmentShaderBarycentricFeaturesNV& operator=( VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentShaderBarycentricFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceFragmentShaderBarycentricFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceFragmentShaderBarycentricFeaturesNV & setFragmentShaderBarycentric( VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderBarycentric_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fragmentShaderBarycentric = fragmentShaderBarycentric_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceFragmentShaderBarycentricFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( fragmentShaderBarycentric == rhs.fragmentShaderBarycentric );
+ }
+
+ bool operator!=( PhysicalDeviceFragmentShaderBarycentricFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceFragmentShaderBarycentricFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderBarycentric = {};
+ };
+ static_assert( sizeof( PhysicalDeviceFragmentShaderBarycentricFeaturesNV ) == sizeof( VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceFragmentShaderBarycentricFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceFragmentShaderInterlockFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceFragmentShaderInterlockFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderSampleInterlock_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderPixelInterlock_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderShadingRateInterlock_ = {} ) VULKAN_HPP_NOEXCEPT
+ : fragmentShaderSampleInterlock( fragmentShaderSampleInterlock_ )
+ , fragmentShaderPixelInterlock( fragmentShaderPixelInterlock_ )
+ , fragmentShaderShadingRateInterlock( fragmentShaderShadingRateInterlock_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentShaderInterlockFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentShaderInterlockFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentShaderInterlockFeaturesEXT ) - offsetof( PhysicalDeviceFragmentShaderInterlockFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceFragmentShaderInterlockFeaturesEXT( VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceFragmentShaderInterlockFeaturesEXT& operator=( VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceFragmentShaderInterlockFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceFragmentShaderInterlockFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceFragmentShaderInterlockFeaturesEXT & setFragmentShaderSampleInterlock( VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderSampleInterlock_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fragmentShaderSampleInterlock = fragmentShaderSampleInterlock_;
+ return *this;
+ }
+
+ PhysicalDeviceFragmentShaderInterlockFeaturesEXT & setFragmentShaderPixelInterlock( VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderPixelInterlock_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fragmentShaderPixelInterlock = fragmentShaderPixelInterlock_;
+ return *this;
+ }
+
+ PhysicalDeviceFragmentShaderInterlockFeaturesEXT & setFragmentShaderShadingRateInterlock( VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderShadingRateInterlock_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fragmentShaderShadingRateInterlock = fragmentShaderShadingRateInterlock_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceFragmentShaderInterlockFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( fragmentShaderSampleInterlock == rhs.fragmentShaderSampleInterlock )
+ && ( fragmentShaderPixelInterlock == rhs.fragmentShaderPixelInterlock )
+ && ( fragmentShaderShadingRateInterlock == rhs.fragmentShaderShadingRateInterlock );
+ }
+
+ bool operator!=( PhysicalDeviceFragmentShaderInterlockFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceFragmentShaderInterlockFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderSampleInterlock = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderPixelInterlock = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fragmentShaderShadingRateInterlock = {};
+ };
+ static_assert( sizeof( PhysicalDeviceFragmentShaderInterlockFeaturesEXT ) == sizeof( VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceFragmentShaderInterlockFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceGroupProperties
+ {
+ PhysicalDeviceGroupProperties( uint32_t physicalDeviceCount_ = {},
+ std::array<VULKAN_HPP_NAMESPACE::PhysicalDevice,VK_MAX_DEVICE_GROUP_SIZE> const& physicalDevices_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 subsetAllocation_ = {} ) VULKAN_HPP_NOEXCEPT
+ : physicalDeviceCount( physicalDeviceCount_ )
+ , physicalDevices{}
+ , subsetAllocation( subsetAllocation_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::PhysicalDevice,VK_MAX_DEVICE_GROUP_SIZE,VK_MAX_DEVICE_GROUP_SIZE>::copy( physicalDevices, physicalDevices_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceGroupProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceGroupProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceGroupProperties ) - offsetof( PhysicalDeviceGroupProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceGroupProperties( VkPhysicalDeviceGroupProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceGroupProperties& operator=( VkPhysicalDeviceGroupProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceGroupProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceGroupProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceGroupProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceGroupProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceGroupProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceGroupProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( physicalDeviceCount == rhs.physicalDeviceCount )
+ && ( memcmp( physicalDevices, rhs.physicalDevices, std::min<uint32_t>( VK_MAX_DEVICE_GROUP_SIZE, physicalDeviceCount ) * sizeof( VULKAN_HPP_NAMESPACE::PhysicalDevice ) ) == 0 )
+ && ( subsetAllocation == rhs.subsetAllocation );
+ }
+
+ bool operator!=( PhysicalDeviceGroupProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceGroupProperties;
+ void* pNext = {};
+ uint32_t physicalDeviceCount = {};
+ VULKAN_HPP_NAMESPACE::PhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE] = {};
+ VULKAN_HPP_NAMESPACE::Bool32 subsetAllocation = {};
+ };
+ static_assert( sizeof( PhysicalDeviceGroupProperties ) == sizeof( VkPhysicalDeviceGroupProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceGroupProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceHostQueryResetFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceHostQueryResetFeatures( VULKAN_HPP_NAMESPACE::Bool32 hostQueryReset_ = {} ) VULKAN_HPP_NOEXCEPT
+ : hostQueryReset( hostQueryReset_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceHostQueryResetFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceHostQueryResetFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceHostQueryResetFeatures ) - offsetof( PhysicalDeviceHostQueryResetFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceHostQueryResetFeatures( VkPhysicalDeviceHostQueryResetFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceHostQueryResetFeatures& operator=( VkPhysicalDeviceHostQueryResetFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceHostQueryResetFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceHostQueryResetFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceHostQueryResetFeatures & setHostQueryReset( VULKAN_HPP_NAMESPACE::Bool32 hostQueryReset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ hostQueryReset = hostQueryReset_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceHostQueryResetFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceHostQueryResetFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceHostQueryResetFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceHostQueryResetFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceHostQueryResetFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( hostQueryReset == rhs.hostQueryReset );
+ }
+
+ bool operator!=( PhysicalDeviceHostQueryResetFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceHostQueryResetFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 hostQueryReset = {};
+ };
+ static_assert( sizeof( PhysicalDeviceHostQueryResetFeatures ) == sizeof( VkPhysicalDeviceHostQueryResetFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceHostQueryResetFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceIDProperties
+ {
+ PhysicalDeviceIDProperties( std::array<uint8_t,VK_UUID_SIZE> const& deviceUUID_ = {},
+ std::array<uint8_t,VK_UUID_SIZE> const& driverUUID_ = {},
+ std::array<uint8_t,VK_LUID_SIZE> const& deviceLUID_ = {},
+ uint32_t deviceNodeMask_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 deviceLUIDValid_ = {} ) VULKAN_HPP_NOEXCEPT
+ : deviceUUID{}
+ , driverUUID{}
+ , deviceLUID{}
+ , deviceNodeMask( deviceNodeMask_ )
+ , deviceLUIDValid( deviceLUIDValid_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE,VK_UUID_SIZE>::copy( deviceUUID, deviceUUID_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE,VK_UUID_SIZE>::copy( driverUUID, driverUUID_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_LUID_SIZE,VK_LUID_SIZE>::copy( deviceLUID, deviceLUID_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceIDProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceIDProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceIDProperties ) - offsetof( PhysicalDeviceIDProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceIDProperties( VkPhysicalDeviceIDProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceIDProperties& operator=( VkPhysicalDeviceIDProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceIDProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceIDProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceIDProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceIDProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceIDProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceIDProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memcmp( deviceUUID, rhs.deviceUUID, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 )
+ && ( memcmp( driverUUID, rhs.driverUUID, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 )
+ && ( memcmp( deviceLUID, rhs.deviceLUID, VK_LUID_SIZE * sizeof( uint8_t ) ) == 0 )
+ && ( deviceNodeMask == rhs.deviceNodeMask )
+ && ( deviceLUIDValid == rhs.deviceLUIDValid );
+ }
+
+ bool operator!=( PhysicalDeviceIDProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceIdProperties;
+ void* pNext = {};
+ uint8_t deviceUUID[VK_UUID_SIZE] = {};
+ uint8_t driverUUID[VK_UUID_SIZE] = {};
+ uint8_t deviceLUID[VK_LUID_SIZE] = {};
+ uint32_t deviceNodeMask = {};
+ VULKAN_HPP_NAMESPACE::Bool32 deviceLUIDValid = {};
+ };
+ static_assert( sizeof( PhysicalDeviceIDProperties ) == sizeof( VkPhysicalDeviceIDProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceIDProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceImageDrmFormatModifierInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceImageDrmFormatModifierInfoEXT( uint64_t drmFormatModifier_ = {},
+ VULKAN_HPP_NAMESPACE::SharingMode sharingMode_ = VULKAN_HPP_NAMESPACE::SharingMode::eExclusive,
+ uint32_t queueFamilyIndexCount_ = {},
+ const uint32_t* pQueueFamilyIndices_ = {} ) VULKAN_HPP_NOEXCEPT
+ : drmFormatModifier( drmFormatModifier_ )
+ , sharingMode( sharingMode_ )
+ , queueFamilyIndexCount( queueFamilyIndexCount_ )
+ , pQueueFamilyIndices( pQueueFamilyIndices_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceImageDrmFormatModifierInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceImageDrmFormatModifierInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceImageDrmFormatModifierInfoEXT ) - offsetof( PhysicalDeviceImageDrmFormatModifierInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceImageDrmFormatModifierInfoEXT( VkPhysicalDeviceImageDrmFormatModifierInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceImageDrmFormatModifierInfoEXT& operator=( VkPhysicalDeviceImageDrmFormatModifierInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageDrmFormatModifierInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceImageDrmFormatModifierInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceImageDrmFormatModifierInfoEXT & setDrmFormatModifier( uint64_t drmFormatModifier_ ) VULKAN_HPP_NOEXCEPT
+ {
+ drmFormatModifier = drmFormatModifier_;
+ return *this;
+ }
+
+ PhysicalDeviceImageDrmFormatModifierInfoEXT & setSharingMode( VULKAN_HPP_NAMESPACE::SharingMode sharingMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sharingMode = sharingMode_;
+ return *this;
+ }
+
+ PhysicalDeviceImageDrmFormatModifierInfoEXT & setQueueFamilyIndexCount( uint32_t queueFamilyIndexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueFamilyIndexCount = queueFamilyIndexCount_;
+ return *this;
+ }
+
+ PhysicalDeviceImageDrmFormatModifierInfoEXT & setPQueueFamilyIndices( const uint32_t* pQueueFamilyIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pQueueFamilyIndices = pQueueFamilyIndices_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceImageDrmFormatModifierInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceImageDrmFormatModifierInfoEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceImageDrmFormatModifierInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceImageDrmFormatModifierInfoEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceImageDrmFormatModifierInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( drmFormatModifier == rhs.drmFormatModifier )
+ && ( sharingMode == rhs.sharingMode )
+ && ( queueFamilyIndexCount == rhs.queueFamilyIndexCount )
+ && ( pQueueFamilyIndices == rhs.pQueueFamilyIndices );
+ }
+
+ bool operator!=( PhysicalDeviceImageDrmFormatModifierInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceImageDrmFormatModifierInfoEXT;
+ const void* pNext = {};
+ uint64_t drmFormatModifier = {};
+ VULKAN_HPP_NAMESPACE::SharingMode sharingMode = VULKAN_HPP_NAMESPACE::SharingMode::eExclusive;
+ uint32_t queueFamilyIndexCount = {};
+ const uint32_t* pQueueFamilyIndices = {};
+ };
+ static_assert( sizeof( PhysicalDeviceImageDrmFormatModifierInfoEXT ) == sizeof( VkPhysicalDeviceImageDrmFormatModifierInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceImageDrmFormatModifierInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceImageFormatInfo2
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceImageFormatInfo2( VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::ImageType type_ = VULKAN_HPP_NAMESPACE::ImageType::e1D,
+ VULKAN_HPP_NAMESPACE::ImageTiling tiling_ = VULKAN_HPP_NAMESPACE::ImageTiling::eOptimal,
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags usage_ = {},
+ VULKAN_HPP_NAMESPACE::ImageCreateFlags flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : format( format_ )
+ , type( type_ )
+ , tiling( tiling_ )
+ , usage( usage_ )
+ , flags( flags_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceImageFormatInfo2 & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceImageFormatInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceImageFormatInfo2 ) - offsetof( PhysicalDeviceImageFormatInfo2, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceImageFormatInfo2( VkPhysicalDeviceImageFormatInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceImageFormatInfo2& operator=( VkPhysicalDeviceImageFormatInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageFormatInfo2 const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceImageFormatInfo2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceImageFormatInfo2 & setFormat( VULKAN_HPP_NAMESPACE::Format format_ ) VULKAN_HPP_NOEXCEPT
+ {
+ format = format_;
+ return *this;
+ }
+
+ PhysicalDeviceImageFormatInfo2 & setType( VULKAN_HPP_NAMESPACE::ImageType type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ PhysicalDeviceImageFormatInfo2 & setTiling( VULKAN_HPP_NAMESPACE::ImageTiling tiling_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tiling = tiling_;
+ return *this;
+ }
+
+ PhysicalDeviceImageFormatInfo2 & setUsage( VULKAN_HPP_NAMESPACE::ImageUsageFlags usage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ usage = usage_;
+ return *this;
+ }
+
+ PhysicalDeviceImageFormatInfo2 & setFlags( VULKAN_HPP_NAMESPACE::ImageCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceImageFormatInfo2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( this );
+ }
+
+ operator VkPhysicalDeviceImageFormatInfo2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceImageFormatInfo2*>( this );
+ }
+
+ bool operator==( PhysicalDeviceImageFormatInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( format == rhs.format )
+ && ( type == rhs.type )
+ && ( tiling == rhs.tiling )
+ && ( usage == rhs.usage )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( PhysicalDeviceImageFormatInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceImageFormatInfo2;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::ImageType type = VULKAN_HPP_NAMESPACE::ImageType::e1D;
+ VULKAN_HPP_NAMESPACE::ImageTiling tiling = VULKAN_HPP_NAMESPACE::ImageTiling::eOptimal;
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags usage = {};
+ VULKAN_HPP_NAMESPACE::ImageCreateFlags flags = {};
+ };
+ static_assert( sizeof( PhysicalDeviceImageFormatInfo2 ) == sizeof( VkPhysicalDeviceImageFormatInfo2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceImageFormatInfo2>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceImageViewImageFormatInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceImageViewImageFormatInfoEXT( VULKAN_HPP_NAMESPACE::ImageViewType imageViewType_ = VULKAN_HPP_NAMESPACE::ImageViewType::e1D ) VULKAN_HPP_NOEXCEPT
+ : imageViewType( imageViewType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceImageViewImageFormatInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceImageViewImageFormatInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceImageViewImageFormatInfoEXT ) - offsetof( PhysicalDeviceImageViewImageFormatInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceImageViewImageFormatInfoEXT( VkPhysicalDeviceImageViewImageFormatInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceImageViewImageFormatInfoEXT& operator=( VkPhysicalDeviceImageViewImageFormatInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceImageViewImageFormatInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceImageViewImageFormatInfoEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceImageViewImageFormatInfoEXT & setImageViewType( VULKAN_HPP_NAMESPACE::ImageViewType imageViewType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageViewType = imageViewType_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceImageViewImageFormatInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceImageViewImageFormatInfoEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceImageViewImageFormatInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceImageViewImageFormatInfoEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceImageViewImageFormatInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( imageViewType == rhs.imageViewType );
+ }
+
+ bool operator!=( PhysicalDeviceImageViewImageFormatInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceImageViewImageFormatInfoEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageViewType imageViewType = VULKAN_HPP_NAMESPACE::ImageViewType::e1D;
+ };
+ static_assert( sizeof( PhysicalDeviceImageViewImageFormatInfoEXT ) == sizeof( VkPhysicalDeviceImageViewImageFormatInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceImageViewImageFormatInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceImagelessFramebufferFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceImagelessFramebufferFeatures( VULKAN_HPP_NAMESPACE::Bool32 imagelessFramebuffer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : imagelessFramebuffer( imagelessFramebuffer_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceImagelessFramebufferFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceImagelessFramebufferFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceImagelessFramebufferFeatures ) - offsetof( PhysicalDeviceImagelessFramebufferFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceImagelessFramebufferFeatures( VkPhysicalDeviceImagelessFramebufferFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceImagelessFramebufferFeatures& operator=( VkPhysicalDeviceImagelessFramebufferFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceImagelessFramebufferFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceImagelessFramebufferFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceImagelessFramebufferFeatures & setImagelessFramebuffer( VULKAN_HPP_NAMESPACE::Bool32 imagelessFramebuffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imagelessFramebuffer = imagelessFramebuffer_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceImagelessFramebufferFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceImagelessFramebufferFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceImagelessFramebufferFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceImagelessFramebufferFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceImagelessFramebufferFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( imagelessFramebuffer == rhs.imagelessFramebuffer );
+ }
+
+ bool operator!=( PhysicalDeviceImagelessFramebufferFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceImagelessFramebufferFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 imagelessFramebuffer = {};
+ };
+ static_assert( sizeof( PhysicalDeviceImagelessFramebufferFeatures ) == sizeof( VkPhysicalDeviceImagelessFramebufferFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceImagelessFramebufferFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceIndexTypeUint8FeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceIndexTypeUint8FeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 indexTypeUint8_ = {} ) VULKAN_HPP_NOEXCEPT
+ : indexTypeUint8( indexTypeUint8_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceIndexTypeUint8FeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceIndexTypeUint8FeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceIndexTypeUint8FeaturesEXT ) - offsetof( PhysicalDeviceIndexTypeUint8FeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceIndexTypeUint8FeaturesEXT( VkPhysicalDeviceIndexTypeUint8FeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceIndexTypeUint8FeaturesEXT& operator=( VkPhysicalDeviceIndexTypeUint8FeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceIndexTypeUint8FeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceIndexTypeUint8FeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceIndexTypeUint8FeaturesEXT & setIndexTypeUint8( VULKAN_HPP_NAMESPACE::Bool32 indexTypeUint8_ ) VULKAN_HPP_NOEXCEPT
+ {
+ indexTypeUint8 = indexTypeUint8_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceIndexTypeUint8FeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceIndexTypeUint8FeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceIndexTypeUint8FeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceIndexTypeUint8FeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceIndexTypeUint8FeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( indexTypeUint8 == rhs.indexTypeUint8 );
+ }
+
+ bool operator!=( PhysicalDeviceIndexTypeUint8FeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceIndexTypeUint8FeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 indexTypeUint8 = {};
+ };
+ static_assert( sizeof( PhysicalDeviceIndexTypeUint8FeaturesEXT ) == sizeof( VkPhysicalDeviceIndexTypeUint8FeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceIndexTypeUint8FeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceInlineUniformBlockFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceInlineUniformBlockFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 inlineUniformBlock_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingInlineUniformBlockUpdateAfterBind_ = {} ) VULKAN_HPP_NOEXCEPT
+ : inlineUniformBlock( inlineUniformBlock_ )
+ , descriptorBindingInlineUniformBlockUpdateAfterBind( descriptorBindingInlineUniformBlockUpdateAfterBind_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceInlineUniformBlockFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceInlineUniformBlockFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceInlineUniformBlockFeaturesEXT ) - offsetof( PhysicalDeviceInlineUniformBlockFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceInlineUniformBlockFeaturesEXT( VkPhysicalDeviceInlineUniformBlockFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceInlineUniformBlockFeaturesEXT& operator=( VkPhysicalDeviceInlineUniformBlockFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceInlineUniformBlockFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceInlineUniformBlockFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceInlineUniformBlockFeaturesEXT & setInlineUniformBlock( VULKAN_HPP_NAMESPACE::Bool32 inlineUniformBlock_ ) VULKAN_HPP_NOEXCEPT
+ {
+ inlineUniformBlock = inlineUniformBlock_;
+ return *this;
+ }
+
+ PhysicalDeviceInlineUniformBlockFeaturesEXT & setDescriptorBindingInlineUniformBlockUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingInlineUniformBlockUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingInlineUniformBlockUpdateAfterBind = descriptorBindingInlineUniformBlockUpdateAfterBind_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceInlineUniformBlockFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceInlineUniformBlockFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceInlineUniformBlockFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceInlineUniformBlockFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceInlineUniformBlockFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( inlineUniformBlock == rhs.inlineUniformBlock )
+ && ( descriptorBindingInlineUniformBlockUpdateAfterBind == rhs.descriptorBindingInlineUniformBlockUpdateAfterBind );
+ }
+
+ bool operator!=( PhysicalDeviceInlineUniformBlockFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceInlineUniformBlockFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 inlineUniformBlock = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingInlineUniformBlockUpdateAfterBind = {};
+ };
+ static_assert( sizeof( PhysicalDeviceInlineUniformBlockFeaturesEXT ) == sizeof( VkPhysicalDeviceInlineUniformBlockFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceInlineUniformBlockFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceInlineUniformBlockPropertiesEXT
+ {
+ PhysicalDeviceInlineUniformBlockPropertiesEXT( uint32_t maxInlineUniformBlockSize_ = {},
+ uint32_t maxPerStageDescriptorInlineUniformBlocks_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks_ = {},
+ uint32_t maxDescriptorSetInlineUniformBlocks_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxInlineUniformBlockSize( maxInlineUniformBlockSize_ )
+ , maxPerStageDescriptorInlineUniformBlocks( maxPerStageDescriptorInlineUniformBlocks_ )
+ , maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks( maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks_ )
+ , maxDescriptorSetInlineUniformBlocks( maxDescriptorSetInlineUniformBlocks_ )
+ , maxDescriptorSetUpdateAfterBindInlineUniformBlocks( maxDescriptorSetUpdateAfterBindInlineUniformBlocks_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceInlineUniformBlockPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceInlineUniformBlockPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceInlineUniformBlockPropertiesEXT ) - offsetof( PhysicalDeviceInlineUniformBlockPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceInlineUniformBlockPropertiesEXT( VkPhysicalDeviceInlineUniformBlockPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceInlineUniformBlockPropertiesEXT& operator=( VkPhysicalDeviceInlineUniformBlockPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceInlineUniformBlockPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceInlineUniformBlockPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceInlineUniformBlockPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceInlineUniformBlockPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceInlineUniformBlockPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceInlineUniformBlockPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxInlineUniformBlockSize == rhs.maxInlineUniformBlockSize )
+ && ( maxPerStageDescriptorInlineUniformBlocks == rhs.maxPerStageDescriptorInlineUniformBlocks )
+ && ( maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks == rhs.maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks )
+ && ( maxDescriptorSetInlineUniformBlocks == rhs.maxDescriptorSetInlineUniformBlocks )
+ && ( maxDescriptorSetUpdateAfterBindInlineUniformBlocks == rhs.maxDescriptorSetUpdateAfterBindInlineUniformBlocks );
+ }
+
+ bool operator!=( PhysicalDeviceInlineUniformBlockPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceInlineUniformBlockPropertiesEXT;
+ void* pNext = {};
+ uint32_t maxInlineUniformBlockSize = {};
+ uint32_t maxPerStageDescriptorInlineUniformBlocks = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks = {};
+ uint32_t maxDescriptorSetInlineUniformBlocks = {};
+ uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks = {};
+ };
+ static_assert( sizeof( PhysicalDeviceInlineUniformBlockPropertiesEXT ) == sizeof( VkPhysicalDeviceInlineUniformBlockPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceInlineUniformBlockPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceLimits
+ {
+ PhysicalDeviceLimits( uint32_t maxImageDimension1D_ = {},
+ uint32_t maxImageDimension2D_ = {},
+ uint32_t maxImageDimension3D_ = {},
+ uint32_t maxImageDimensionCube_ = {},
+ uint32_t maxImageArrayLayers_ = {},
+ uint32_t maxTexelBufferElements_ = {},
+ uint32_t maxUniformBufferRange_ = {},
+ uint32_t maxStorageBufferRange_ = {},
+ uint32_t maxPushConstantsSize_ = {},
+ uint32_t maxMemoryAllocationCount_ = {},
+ uint32_t maxSamplerAllocationCount_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize bufferImageGranularity_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize sparseAddressSpaceSize_ = {},
+ uint32_t maxBoundDescriptorSets_ = {},
+ uint32_t maxPerStageDescriptorSamplers_ = {},
+ uint32_t maxPerStageDescriptorUniformBuffers_ = {},
+ uint32_t maxPerStageDescriptorStorageBuffers_ = {},
+ uint32_t maxPerStageDescriptorSampledImages_ = {},
+ uint32_t maxPerStageDescriptorStorageImages_ = {},
+ uint32_t maxPerStageDescriptorInputAttachments_ = {},
+ uint32_t maxPerStageResources_ = {},
+ uint32_t maxDescriptorSetSamplers_ = {},
+ uint32_t maxDescriptorSetUniformBuffers_ = {},
+ uint32_t maxDescriptorSetUniformBuffersDynamic_ = {},
+ uint32_t maxDescriptorSetStorageBuffers_ = {},
+ uint32_t maxDescriptorSetStorageBuffersDynamic_ = {},
+ uint32_t maxDescriptorSetSampledImages_ = {},
+ uint32_t maxDescriptorSetStorageImages_ = {},
+ uint32_t maxDescriptorSetInputAttachments_ = {},
+ uint32_t maxVertexInputAttributes_ = {},
+ uint32_t maxVertexInputBindings_ = {},
+ uint32_t maxVertexInputAttributeOffset_ = {},
+ uint32_t maxVertexInputBindingStride_ = {},
+ uint32_t maxVertexOutputComponents_ = {},
+ uint32_t maxTessellationGenerationLevel_ = {},
+ uint32_t maxTessellationPatchSize_ = {},
+ uint32_t maxTessellationControlPerVertexInputComponents_ = {},
+ uint32_t maxTessellationControlPerVertexOutputComponents_ = {},
+ uint32_t maxTessellationControlPerPatchOutputComponents_ = {},
+ uint32_t maxTessellationControlTotalOutputComponents_ = {},
+ uint32_t maxTessellationEvaluationInputComponents_ = {},
+ uint32_t maxTessellationEvaluationOutputComponents_ = {},
+ uint32_t maxGeometryShaderInvocations_ = {},
+ uint32_t maxGeometryInputComponents_ = {},
+ uint32_t maxGeometryOutputComponents_ = {},
+ uint32_t maxGeometryOutputVertices_ = {},
+ uint32_t maxGeometryTotalOutputComponents_ = {},
+ uint32_t maxFragmentInputComponents_ = {},
+ uint32_t maxFragmentOutputAttachments_ = {},
+ uint32_t maxFragmentDualSrcAttachments_ = {},
+ uint32_t maxFragmentCombinedOutputResources_ = {},
+ uint32_t maxComputeSharedMemorySize_ = {},
+ std::array<uint32_t,3> const& maxComputeWorkGroupCount_ = {},
+ uint32_t maxComputeWorkGroupInvocations_ = {},
+ std::array<uint32_t,3> const& maxComputeWorkGroupSize_ = {},
+ uint32_t subPixelPrecisionBits_ = {},
+ uint32_t subTexelPrecisionBits_ = {},
+ uint32_t mipmapPrecisionBits_ = {},
+ uint32_t maxDrawIndexedIndexValue_ = {},
+ uint32_t maxDrawIndirectCount_ = {},
+ float maxSamplerLodBias_ = {},
+ float maxSamplerAnisotropy_ = {},
+ uint32_t maxViewports_ = {},
+ std::array<uint32_t,2> const& maxViewportDimensions_ = {},
+ std::array<float,2> const& viewportBoundsRange_ = {},
+ uint32_t viewportSubPixelBits_ = {},
+ size_t minMemoryMapAlignment_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize minTexelBufferOffsetAlignment_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize minUniformBufferOffsetAlignment_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize minStorageBufferOffsetAlignment_ = {},
+ int32_t minTexelOffset_ = {},
+ uint32_t maxTexelOffset_ = {},
+ int32_t minTexelGatherOffset_ = {},
+ uint32_t maxTexelGatherOffset_ = {},
+ float minInterpolationOffset_ = {},
+ float maxInterpolationOffset_ = {},
+ uint32_t subPixelInterpolationOffsetBits_ = {},
+ uint32_t maxFramebufferWidth_ = {},
+ uint32_t maxFramebufferHeight_ = {},
+ uint32_t maxFramebufferLayers_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferColorSampleCounts_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferDepthSampleCounts_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferStencilSampleCounts_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferNoAttachmentsSampleCounts_ = {},
+ uint32_t maxColorAttachments_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampledImageColorSampleCounts_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampledImageIntegerSampleCounts_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampledImageDepthSampleCounts_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampledImageStencilSampleCounts_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags storageImageSampleCounts_ = {},
+ uint32_t maxSampleMaskWords_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 timestampComputeAndGraphics_ = {},
+ float timestampPeriod_ = {},
+ uint32_t maxClipDistances_ = {},
+ uint32_t maxCullDistances_ = {},
+ uint32_t maxCombinedClipAndCullDistances_ = {},
+ uint32_t discreteQueuePriorities_ = {},
+ std::array<float,2> const& pointSizeRange_ = {},
+ std::array<float,2> const& lineWidthRange_ = {},
+ float pointSizeGranularity_ = {},
+ float lineWidthGranularity_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 strictLines_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 standardSampleLocations_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize optimalBufferCopyOffsetAlignment_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize optimalBufferCopyRowPitchAlignment_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize nonCoherentAtomSize_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxImageDimension1D( maxImageDimension1D_ )
+ , maxImageDimension2D( maxImageDimension2D_ )
+ , maxImageDimension3D( maxImageDimension3D_ )
+ , maxImageDimensionCube( maxImageDimensionCube_ )
+ , maxImageArrayLayers( maxImageArrayLayers_ )
+ , maxTexelBufferElements( maxTexelBufferElements_ )
+ , maxUniformBufferRange( maxUniformBufferRange_ )
+ , maxStorageBufferRange( maxStorageBufferRange_ )
+ , maxPushConstantsSize( maxPushConstantsSize_ )
+ , maxMemoryAllocationCount( maxMemoryAllocationCount_ )
+ , maxSamplerAllocationCount( maxSamplerAllocationCount_ )
+ , bufferImageGranularity( bufferImageGranularity_ )
+ , sparseAddressSpaceSize( sparseAddressSpaceSize_ )
+ , maxBoundDescriptorSets( maxBoundDescriptorSets_ )
+ , maxPerStageDescriptorSamplers( maxPerStageDescriptorSamplers_ )
+ , maxPerStageDescriptorUniformBuffers( maxPerStageDescriptorUniformBuffers_ )
+ , maxPerStageDescriptorStorageBuffers( maxPerStageDescriptorStorageBuffers_ )
+ , maxPerStageDescriptorSampledImages( maxPerStageDescriptorSampledImages_ )
+ , maxPerStageDescriptorStorageImages( maxPerStageDescriptorStorageImages_ )
+ , maxPerStageDescriptorInputAttachments( maxPerStageDescriptorInputAttachments_ )
+ , maxPerStageResources( maxPerStageResources_ )
+ , maxDescriptorSetSamplers( maxDescriptorSetSamplers_ )
+ , maxDescriptorSetUniformBuffers( maxDescriptorSetUniformBuffers_ )
+ , maxDescriptorSetUniformBuffersDynamic( maxDescriptorSetUniformBuffersDynamic_ )
+ , maxDescriptorSetStorageBuffers( maxDescriptorSetStorageBuffers_ )
+ , maxDescriptorSetStorageBuffersDynamic( maxDescriptorSetStorageBuffersDynamic_ )
+ , maxDescriptorSetSampledImages( maxDescriptorSetSampledImages_ )
+ , maxDescriptorSetStorageImages( maxDescriptorSetStorageImages_ )
+ , maxDescriptorSetInputAttachments( maxDescriptorSetInputAttachments_ )
+ , maxVertexInputAttributes( maxVertexInputAttributes_ )
+ , maxVertexInputBindings( maxVertexInputBindings_ )
+ , maxVertexInputAttributeOffset( maxVertexInputAttributeOffset_ )
+ , maxVertexInputBindingStride( maxVertexInputBindingStride_ )
+ , maxVertexOutputComponents( maxVertexOutputComponents_ )
+ , maxTessellationGenerationLevel( maxTessellationGenerationLevel_ )
+ , maxTessellationPatchSize( maxTessellationPatchSize_ )
+ , maxTessellationControlPerVertexInputComponents( maxTessellationControlPerVertexInputComponents_ )
+ , maxTessellationControlPerVertexOutputComponents( maxTessellationControlPerVertexOutputComponents_ )
+ , maxTessellationControlPerPatchOutputComponents( maxTessellationControlPerPatchOutputComponents_ )
+ , maxTessellationControlTotalOutputComponents( maxTessellationControlTotalOutputComponents_ )
+ , maxTessellationEvaluationInputComponents( maxTessellationEvaluationInputComponents_ )
+ , maxTessellationEvaluationOutputComponents( maxTessellationEvaluationOutputComponents_ )
+ , maxGeometryShaderInvocations( maxGeometryShaderInvocations_ )
+ , maxGeometryInputComponents( maxGeometryInputComponents_ )
+ , maxGeometryOutputComponents( maxGeometryOutputComponents_ )
+ , maxGeometryOutputVertices( maxGeometryOutputVertices_ )
+ , maxGeometryTotalOutputComponents( maxGeometryTotalOutputComponents_ )
+ , maxFragmentInputComponents( maxFragmentInputComponents_ )
+ , maxFragmentOutputAttachments( maxFragmentOutputAttachments_ )
+ , maxFragmentDualSrcAttachments( maxFragmentDualSrcAttachments_ )
+ , maxFragmentCombinedOutputResources( maxFragmentCombinedOutputResources_ )
+ , maxComputeSharedMemorySize( maxComputeSharedMemorySize_ )
+ , maxComputeWorkGroupCount{}
+ , maxComputeWorkGroupInvocations( maxComputeWorkGroupInvocations_ )
+ , maxComputeWorkGroupSize{}
+ , subPixelPrecisionBits( subPixelPrecisionBits_ )
+ , subTexelPrecisionBits( subTexelPrecisionBits_ )
+ , mipmapPrecisionBits( mipmapPrecisionBits_ )
+ , maxDrawIndexedIndexValue( maxDrawIndexedIndexValue_ )
+ , maxDrawIndirectCount( maxDrawIndirectCount_ )
+ , maxSamplerLodBias( maxSamplerLodBias_ )
+ , maxSamplerAnisotropy( maxSamplerAnisotropy_ )
+ , maxViewports( maxViewports_ )
+ , maxViewportDimensions{}
+ , viewportBoundsRange{}
+ , viewportSubPixelBits( viewportSubPixelBits_ )
+ , minMemoryMapAlignment( minMemoryMapAlignment_ )
+ , minTexelBufferOffsetAlignment( minTexelBufferOffsetAlignment_ )
+ , minUniformBufferOffsetAlignment( minUniformBufferOffsetAlignment_ )
+ , minStorageBufferOffsetAlignment( minStorageBufferOffsetAlignment_ )
+ , minTexelOffset( minTexelOffset_ )
+ , maxTexelOffset( maxTexelOffset_ )
+ , minTexelGatherOffset( minTexelGatherOffset_ )
+ , maxTexelGatherOffset( maxTexelGatherOffset_ )
+ , minInterpolationOffset( minInterpolationOffset_ )
+ , maxInterpolationOffset( maxInterpolationOffset_ )
+ , subPixelInterpolationOffsetBits( subPixelInterpolationOffsetBits_ )
+ , maxFramebufferWidth( maxFramebufferWidth_ )
+ , maxFramebufferHeight( maxFramebufferHeight_ )
+ , maxFramebufferLayers( maxFramebufferLayers_ )
+ , framebufferColorSampleCounts( framebufferColorSampleCounts_ )
+ , framebufferDepthSampleCounts( framebufferDepthSampleCounts_ )
+ , framebufferStencilSampleCounts( framebufferStencilSampleCounts_ )
+ , framebufferNoAttachmentsSampleCounts( framebufferNoAttachmentsSampleCounts_ )
+ , maxColorAttachments( maxColorAttachments_ )
+ , sampledImageColorSampleCounts( sampledImageColorSampleCounts_ )
+ , sampledImageIntegerSampleCounts( sampledImageIntegerSampleCounts_ )
+ , sampledImageDepthSampleCounts( sampledImageDepthSampleCounts_ )
+ , sampledImageStencilSampleCounts( sampledImageStencilSampleCounts_ )
+ , storageImageSampleCounts( storageImageSampleCounts_ )
+ , maxSampleMaskWords( maxSampleMaskWords_ )
+ , timestampComputeAndGraphics( timestampComputeAndGraphics_ )
+ , timestampPeriod( timestampPeriod_ )
+ , maxClipDistances( maxClipDistances_ )
+ , maxCullDistances( maxCullDistances_ )
+ , maxCombinedClipAndCullDistances( maxCombinedClipAndCullDistances_ )
+ , discreteQueuePriorities( discreteQueuePriorities_ )
+ , pointSizeRange{}
+ , lineWidthRange{}
+ , pointSizeGranularity( pointSizeGranularity_ )
+ , lineWidthGranularity( lineWidthGranularity_ )
+ , strictLines( strictLines_ )
+ , standardSampleLocations( standardSampleLocations_ )
+ , optimalBufferCopyOffsetAlignment( optimalBufferCopyOffsetAlignment_ )
+ , optimalBufferCopyRowPitchAlignment( optimalBufferCopyRowPitchAlignment_ )
+ , nonCoherentAtomSize( nonCoherentAtomSize_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3,3>::copy( maxComputeWorkGroupCount, maxComputeWorkGroupCount_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3,3>::copy( maxComputeWorkGroupSize, maxComputeWorkGroupSize_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,2,2>::copy( maxViewportDimensions, maxViewportDimensions_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2,2>::copy( viewportBoundsRange, viewportBoundsRange_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2,2>::copy( pointSizeRange, pointSizeRange_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2,2>::copy( lineWidthRange, lineWidthRange_ );
+ }
+
+ PhysicalDeviceLimits( VkPhysicalDeviceLimits const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceLimits& operator=( VkPhysicalDeviceLimits const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceLimits const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceLimits const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceLimits*>( this );
+ }
+
+ operator VkPhysicalDeviceLimits &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceLimits*>( this );
+ }
+
+ bool operator==( PhysicalDeviceLimits const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( maxImageDimension1D == rhs.maxImageDimension1D )
+ && ( maxImageDimension2D == rhs.maxImageDimension2D )
+ && ( maxImageDimension3D == rhs.maxImageDimension3D )
+ && ( maxImageDimensionCube == rhs.maxImageDimensionCube )
+ && ( maxImageArrayLayers == rhs.maxImageArrayLayers )
+ && ( maxTexelBufferElements == rhs.maxTexelBufferElements )
+ && ( maxUniformBufferRange == rhs.maxUniformBufferRange )
+ && ( maxStorageBufferRange == rhs.maxStorageBufferRange )
+ && ( maxPushConstantsSize == rhs.maxPushConstantsSize )
+ && ( maxMemoryAllocationCount == rhs.maxMemoryAllocationCount )
+ && ( maxSamplerAllocationCount == rhs.maxSamplerAllocationCount )
+ && ( bufferImageGranularity == rhs.bufferImageGranularity )
+ && ( sparseAddressSpaceSize == rhs.sparseAddressSpaceSize )
+ && ( maxBoundDescriptorSets == rhs.maxBoundDescriptorSets )
+ && ( maxPerStageDescriptorSamplers == rhs.maxPerStageDescriptorSamplers )
+ && ( maxPerStageDescriptorUniformBuffers == rhs.maxPerStageDescriptorUniformBuffers )
+ && ( maxPerStageDescriptorStorageBuffers == rhs.maxPerStageDescriptorStorageBuffers )
+ && ( maxPerStageDescriptorSampledImages == rhs.maxPerStageDescriptorSampledImages )
+ && ( maxPerStageDescriptorStorageImages == rhs.maxPerStageDescriptorStorageImages )
+ && ( maxPerStageDescriptorInputAttachments == rhs.maxPerStageDescriptorInputAttachments )
+ && ( maxPerStageResources == rhs.maxPerStageResources )
+ && ( maxDescriptorSetSamplers == rhs.maxDescriptorSetSamplers )
+ && ( maxDescriptorSetUniformBuffers == rhs.maxDescriptorSetUniformBuffers )
+ && ( maxDescriptorSetUniformBuffersDynamic == rhs.maxDescriptorSetUniformBuffersDynamic )
+ && ( maxDescriptorSetStorageBuffers == rhs.maxDescriptorSetStorageBuffers )
+ && ( maxDescriptorSetStorageBuffersDynamic == rhs.maxDescriptorSetStorageBuffersDynamic )
+ && ( maxDescriptorSetSampledImages == rhs.maxDescriptorSetSampledImages )
+ && ( maxDescriptorSetStorageImages == rhs.maxDescriptorSetStorageImages )
+ && ( maxDescriptorSetInputAttachments == rhs.maxDescriptorSetInputAttachments )
+ && ( maxVertexInputAttributes == rhs.maxVertexInputAttributes )
+ && ( maxVertexInputBindings == rhs.maxVertexInputBindings )
+ && ( maxVertexInputAttributeOffset == rhs.maxVertexInputAttributeOffset )
+ && ( maxVertexInputBindingStride == rhs.maxVertexInputBindingStride )
+ && ( maxVertexOutputComponents == rhs.maxVertexOutputComponents )
+ && ( maxTessellationGenerationLevel == rhs.maxTessellationGenerationLevel )
+ && ( maxTessellationPatchSize == rhs.maxTessellationPatchSize )
+ && ( maxTessellationControlPerVertexInputComponents == rhs.maxTessellationControlPerVertexInputComponents )
+ && ( maxTessellationControlPerVertexOutputComponents == rhs.maxTessellationControlPerVertexOutputComponents )
+ && ( maxTessellationControlPerPatchOutputComponents == rhs.maxTessellationControlPerPatchOutputComponents )
+ && ( maxTessellationControlTotalOutputComponents == rhs.maxTessellationControlTotalOutputComponents )
+ && ( maxTessellationEvaluationInputComponents == rhs.maxTessellationEvaluationInputComponents )
+ && ( maxTessellationEvaluationOutputComponents == rhs.maxTessellationEvaluationOutputComponents )
+ && ( maxGeometryShaderInvocations == rhs.maxGeometryShaderInvocations )
+ && ( maxGeometryInputComponents == rhs.maxGeometryInputComponents )
+ && ( maxGeometryOutputComponents == rhs.maxGeometryOutputComponents )
+ && ( maxGeometryOutputVertices == rhs.maxGeometryOutputVertices )
+ && ( maxGeometryTotalOutputComponents == rhs.maxGeometryTotalOutputComponents )
+ && ( maxFragmentInputComponents == rhs.maxFragmentInputComponents )
+ && ( maxFragmentOutputAttachments == rhs.maxFragmentOutputAttachments )
+ && ( maxFragmentDualSrcAttachments == rhs.maxFragmentDualSrcAttachments )
+ && ( maxFragmentCombinedOutputResources == rhs.maxFragmentCombinedOutputResources )
+ && ( maxComputeSharedMemorySize == rhs.maxComputeSharedMemorySize )
+ && ( memcmp( maxComputeWorkGroupCount, rhs.maxComputeWorkGroupCount, 3 * sizeof( uint32_t ) ) == 0 )
+ && ( maxComputeWorkGroupInvocations == rhs.maxComputeWorkGroupInvocations )
+ && ( memcmp( maxComputeWorkGroupSize, rhs.maxComputeWorkGroupSize, 3 * sizeof( uint32_t ) ) == 0 )
+ && ( subPixelPrecisionBits == rhs.subPixelPrecisionBits )
+ && ( subTexelPrecisionBits == rhs.subTexelPrecisionBits )
+ && ( mipmapPrecisionBits == rhs.mipmapPrecisionBits )
+ && ( maxDrawIndexedIndexValue == rhs.maxDrawIndexedIndexValue )
+ && ( maxDrawIndirectCount == rhs.maxDrawIndirectCount )
+ && ( maxSamplerLodBias == rhs.maxSamplerLodBias )
+ && ( maxSamplerAnisotropy == rhs.maxSamplerAnisotropy )
+ && ( maxViewports == rhs.maxViewports )
+ && ( memcmp( maxViewportDimensions, rhs.maxViewportDimensions, 2 * sizeof( uint32_t ) ) == 0 )
+ && ( memcmp( viewportBoundsRange, rhs.viewportBoundsRange, 2 * sizeof( float ) ) == 0 )
+ && ( viewportSubPixelBits == rhs.viewportSubPixelBits )
+ && ( minMemoryMapAlignment == rhs.minMemoryMapAlignment )
+ && ( minTexelBufferOffsetAlignment == rhs.minTexelBufferOffsetAlignment )
+ && ( minUniformBufferOffsetAlignment == rhs.minUniformBufferOffsetAlignment )
+ && ( minStorageBufferOffsetAlignment == rhs.minStorageBufferOffsetAlignment )
+ && ( minTexelOffset == rhs.minTexelOffset )
+ && ( maxTexelOffset == rhs.maxTexelOffset )
+ && ( minTexelGatherOffset == rhs.minTexelGatherOffset )
+ && ( maxTexelGatherOffset == rhs.maxTexelGatherOffset )
+ && ( minInterpolationOffset == rhs.minInterpolationOffset )
+ && ( maxInterpolationOffset == rhs.maxInterpolationOffset )
+ && ( subPixelInterpolationOffsetBits == rhs.subPixelInterpolationOffsetBits )
+ && ( maxFramebufferWidth == rhs.maxFramebufferWidth )
+ && ( maxFramebufferHeight == rhs.maxFramebufferHeight )
+ && ( maxFramebufferLayers == rhs.maxFramebufferLayers )
+ && ( framebufferColorSampleCounts == rhs.framebufferColorSampleCounts )
+ && ( framebufferDepthSampleCounts == rhs.framebufferDepthSampleCounts )
+ && ( framebufferStencilSampleCounts == rhs.framebufferStencilSampleCounts )
+ && ( framebufferNoAttachmentsSampleCounts == rhs.framebufferNoAttachmentsSampleCounts )
+ && ( maxColorAttachments == rhs.maxColorAttachments )
+ && ( sampledImageColorSampleCounts == rhs.sampledImageColorSampleCounts )
+ && ( sampledImageIntegerSampleCounts == rhs.sampledImageIntegerSampleCounts )
+ && ( sampledImageDepthSampleCounts == rhs.sampledImageDepthSampleCounts )
+ && ( sampledImageStencilSampleCounts == rhs.sampledImageStencilSampleCounts )
+ && ( storageImageSampleCounts == rhs.storageImageSampleCounts )
+ && ( maxSampleMaskWords == rhs.maxSampleMaskWords )
+ && ( timestampComputeAndGraphics == rhs.timestampComputeAndGraphics )
+ && ( timestampPeriod == rhs.timestampPeriod )
+ && ( maxClipDistances == rhs.maxClipDistances )
+ && ( maxCullDistances == rhs.maxCullDistances )
+ && ( maxCombinedClipAndCullDistances == rhs.maxCombinedClipAndCullDistances )
+ && ( discreteQueuePriorities == rhs.discreteQueuePriorities )
+ && ( memcmp( pointSizeRange, rhs.pointSizeRange, 2 * sizeof( float ) ) == 0 )
+ && ( memcmp( lineWidthRange, rhs.lineWidthRange, 2 * sizeof( float ) ) == 0 )
+ && ( pointSizeGranularity == rhs.pointSizeGranularity )
+ && ( lineWidthGranularity == rhs.lineWidthGranularity )
+ && ( strictLines == rhs.strictLines )
+ && ( standardSampleLocations == rhs.standardSampleLocations )
+ && ( optimalBufferCopyOffsetAlignment == rhs.optimalBufferCopyOffsetAlignment )
+ && ( optimalBufferCopyRowPitchAlignment == rhs.optimalBufferCopyRowPitchAlignment )
+ && ( nonCoherentAtomSize == rhs.nonCoherentAtomSize );
+ }
+
+ bool operator!=( PhysicalDeviceLimits const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t maxImageDimension1D = {};
+ uint32_t maxImageDimension2D = {};
+ uint32_t maxImageDimension3D = {};
+ uint32_t maxImageDimensionCube = {};
+ uint32_t maxImageArrayLayers = {};
+ uint32_t maxTexelBufferElements = {};
+ uint32_t maxUniformBufferRange = {};
+ uint32_t maxStorageBufferRange = {};
+ uint32_t maxPushConstantsSize = {};
+ uint32_t maxMemoryAllocationCount = {};
+ uint32_t maxSamplerAllocationCount = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize bufferImageGranularity = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize sparseAddressSpaceSize = {};
+ uint32_t maxBoundDescriptorSets = {};
+ uint32_t maxPerStageDescriptorSamplers = {};
+ uint32_t maxPerStageDescriptorUniformBuffers = {};
+ uint32_t maxPerStageDescriptorStorageBuffers = {};
+ uint32_t maxPerStageDescriptorSampledImages = {};
+ uint32_t maxPerStageDescriptorStorageImages = {};
+ uint32_t maxPerStageDescriptorInputAttachments = {};
+ uint32_t maxPerStageResources = {};
+ uint32_t maxDescriptorSetSamplers = {};
+ uint32_t maxDescriptorSetUniformBuffers = {};
+ uint32_t maxDescriptorSetUniformBuffersDynamic = {};
+ uint32_t maxDescriptorSetStorageBuffers = {};
+ uint32_t maxDescriptorSetStorageBuffersDynamic = {};
+ uint32_t maxDescriptorSetSampledImages = {};
+ uint32_t maxDescriptorSetStorageImages = {};
+ uint32_t maxDescriptorSetInputAttachments = {};
+ uint32_t maxVertexInputAttributes = {};
+ uint32_t maxVertexInputBindings = {};
+ uint32_t maxVertexInputAttributeOffset = {};
+ uint32_t maxVertexInputBindingStride = {};
+ uint32_t maxVertexOutputComponents = {};
+ uint32_t maxTessellationGenerationLevel = {};
+ uint32_t maxTessellationPatchSize = {};
+ uint32_t maxTessellationControlPerVertexInputComponents = {};
+ uint32_t maxTessellationControlPerVertexOutputComponents = {};
+ uint32_t maxTessellationControlPerPatchOutputComponents = {};
+ uint32_t maxTessellationControlTotalOutputComponents = {};
+ uint32_t maxTessellationEvaluationInputComponents = {};
+ uint32_t maxTessellationEvaluationOutputComponents = {};
+ uint32_t maxGeometryShaderInvocations = {};
+ uint32_t maxGeometryInputComponents = {};
+ uint32_t maxGeometryOutputComponents = {};
+ uint32_t maxGeometryOutputVertices = {};
+ uint32_t maxGeometryTotalOutputComponents = {};
+ uint32_t maxFragmentInputComponents = {};
+ uint32_t maxFragmentOutputAttachments = {};
+ uint32_t maxFragmentDualSrcAttachments = {};
+ uint32_t maxFragmentCombinedOutputResources = {};
+ uint32_t maxComputeSharedMemorySize = {};
+ uint32_t maxComputeWorkGroupCount[3] = {};
+ uint32_t maxComputeWorkGroupInvocations = {};
+ uint32_t maxComputeWorkGroupSize[3] = {};
+ uint32_t subPixelPrecisionBits = {};
+ uint32_t subTexelPrecisionBits = {};
+ uint32_t mipmapPrecisionBits = {};
+ uint32_t maxDrawIndexedIndexValue = {};
+ uint32_t maxDrawIndirectCount = {};
+ float maxSamplerLodBias = {};
+ float maxSamplerAnisotropy = {};
+ uint32_t maxViewports = {};
+ uint32_t maxViewportDimensions[2] = {};
+ float viewportBoundsRange[2] = {};
+ uint32_t viewportSubPixelBits = {};
+ size_t minMemoryMapAlignment = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize minTexelBufferOffsetAlignment = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize minUniformBufferOffsetAlignment = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize minStorageBufferOffsetAlignment = {};
+ int32_t minTexelOffset = {};
+ uint32_t maxTexelOffset = {};
+ int32_t minTexelGatherOffset = {};
+ uint32_t maxTexelGatherOffset = {};
+ float minInterpolationOffset = {};
+ float maxInterpolationOffset = {};
+ uint32_t subPixelInterpolationOffsetBits = {};
+ uint32_t maxFramebufferWidth = {};
+ uint32_t maxFramebufferHeight = {};
+ uint32_t maxFramebufferLayers = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferColorSampleCounts = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferDepthSampleCounts = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferStencilSampleCounts = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferNoAttachmentsSampleCounts = {};
+ uint32_t maxColorAttachments = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampledImageColorSampleCounts = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampledImageIntegerSampleCounts = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampledImageDepthSampleCounts = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampledImageStencilSampleCounts = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags storageImageSampleCounts = {};
+ uint32_t maxSampleMaskWords = {};
+ VULKAN_HPP_NAMESPACE::Bool32 timestampComputeAndGraphics = {};
+ float timestampPeriod = {};
+ uint32_t maxClipDistances = {};
+ uint32_t maxCullDistances = {};
+ uint32_t maxCombinedClipAndCullDistances = {};
+ uint32_t discreteQueuePriorities = {};
+ float pointSizeRange[2] = {};
+ float lineWidthRange[2] = {};
+ float pointSizeGranularity = {};
+ float lineWidthGranularity = {};
+ VULKAN_HPP_NAMESPACE::Bool32 strictLines = {};
+ VULKAN_HPP_NAMESPACE::Bool32 standardSampleLocations = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize optimalBufferCopyOffsetAlignment = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize optimalBufferCopyRowPitchAlignment = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize nonCoherentAtomSize = {};
+ };
+ static_assert( sizeof( PhysicalDeviceLimits ) == sizeof( VkPhysicalDeviceLimits ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceLimits>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceLineRasterizationFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceLineRasterizationFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 rectangularLines_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 bresenhamLines_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 smoothLines_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 stippledRectangularLines_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 stippledBresenhamLines_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 stippledSmoothLines_ = {} ) VULKAN_HPP_NOEXCEPT
+ : rectangularLines( rectangularLines_ )
+ , bresenhamLines( bresenhamLines_ )
+ , smoothLines( smoothLines_ )
+ , stippledRectangularLines( stippledRectangularLines_ )
+ , stippledBresenhamLines( stippledBresenhamLines_ )
+ , stippledSmoothLines( stippledSmoothLines_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceLineRasterizationFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceLineRasterizationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceLineRasterizationFeaturesEXT ) - offsetof( PhysicalDeviceLineRasterizationFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceLineRasterizationFeaturesEXT( VkPhysicalDeviceLineRasterizationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceLineRasterizationFeaturesEXT& operator=( VkPhysicalDeviceLineRasterizationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceLineRasterizationFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceLineRasterizationFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceLineRasterizationFeaturesEXT & setRectangularLines( VULKAN_HPP_NAMESPACE::Bool32 rectangularLines_ ) VULKAN_HPP_NOEXCEPT
+ {
+ rectangularLines = rectangularLines_;
+ return *this;
+ }
+
+ PhysicalDeviceLineRasterizationFeaturesEXT & setBresenhamLines( VULKAN_HPP_NAMESPACE::Bool32 bresenhamLines_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bresenhamLines = bresenhamLines_;
+ return *this;
+ }
+
+ PhysicalDeviceLineRasterizationFeaturesEXT & setSmoothLines( VULKAN_HPP_NAMESPACE::Bool32 smoothLines_ ) VULKAN_HPP_NOEXCEPT
+ {
+ smoothLines = smoothLines_;
+ return *this;
+ }
+
+ PhysicalDeviceLineRasterizationFeaturesEXT & setStippledRectangularLines( VULKAN_HPP_NAMESPACE::Bool32 stippledRectangularLines_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stippledRectangularLines = stippledRectangularLines_;
+ return *this;
+ }
+
+ PhysicalDeviceLineRasterizationFeaturesEXT & setStippledBresenhamLines( VULKAN_HPP_NAMESPACE::Bool32 stippledBresenhamLines_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stippledBresenhamLines = stippledBresenhamLines_;
+ return *this;
+ }
+
+ PhysicalDeviceLineRasterizationFeaturesEXT & setStippledSmoothLines( VULKAN_HPP_NAMESPACE::Bool32 stippledSmoothLines_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stippledSmoothLines = stippledSmoothLines_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceLineRasterizationFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceLineRasterizationFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceLineRasterizationFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceLineRasterizationFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceLineRasterizationFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( rectangularLines == rhs.rectangularLines )
+ && ( bresenhamLines == rhs.bresenhamLines )
+ && ( smoothLines == rhs.smoothLines )
+ && ( stippledRectangularLines == rhs.stippledRectangularLines )
+ && ( stippledBresenhamLines == rhs.stippledBresenhamLines )
+ && ( stippledSmoothLines == rhs.stippledSmoothLines );
+ }
+
+ bool operator!=( PhysicalDeviceLineRasterizationFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceLineRasterizationFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 rectangularLines = {};
+ VULKAN_HPP_NAMESPACE::Bool32 bresenhamLines = {};
+ VULKAN_HPP_NAMESPACE::Bool32 smoothLines = {};
+ VULKAN_HPP_NAMESPACE::Bool32 stippledRectangularLines = {};
+ VULKAN_HPP_NAMESPACE::Bool32 stippledBresenhamLines = {};
+ VULKAN_HPP_NAMESPACE::Bool32 stippledSmoothLines = {};
+ };
+ static_assert( sizeof( PhysicalDeviceLineRasterizationFeaturesEXT ) == sizeof( VkPhysicalDeviceLineRasterizationFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceLineRasterizationFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceLineRasterizationPropertiesEXT
+ {
+ PhysicalDeviceLineRasterizationPropertiesEXT( uint32_t lineSubPixelPrecisionBits_ = {} ) VULKAN_HPP_NOEXCEPT
+ : lineSubPixelPrecisionBits( lineSubPixelPrecisionBits_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceLineRasterizationPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceLineRasterizationPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceLineRasterizationPropertiesEXT ) - offsetof( PhysicalDeviceLineRasterizationPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceLineRasterizationPropertiesEXT( VkPhysicalDeviceLineRasterizationPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceLineRasterizationPropertiesEXT& operator=( VkPhysicalDeviceLineRasterizationPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceLineRasterizationPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceLineRasterizationPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceLineRasterizationPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceLineRasterizationPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceLineRasterizationPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceLineRasterizationPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( lineSubPixelPrecisionBits == rhs.lineSubPixelPrecisionBits );
+ }
+
+ bool operator!=( PhysicalDeviceLineRasterizationPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceLineRasterizationPropertiesEXT;
+ void* pNext = {};
+ uint32_t lineSubPixelPrecisionBits = {};
+ };
+ static_assert( sizeof( PhysicalDeviceLineRasterizationPropertiesEXT ) == sizeof( VkPhysicalDeviceLineRasterizationPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceLineRasterizationPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceMaintenance3Properties
+ {
+ PhysicalDeviceMaintenance3Properties( uint32_t maxPerSetDescriptors_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize maxMemoryAllocationSize_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxPerSetDescriptors( maxPerSetDescriptors_ )
+ , maxMemoryAllocationSize( maxMemoryAllocationSize_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMaintenance3Properties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceMaintenance3Properties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMaintenance3Properties ) - offsetof( PhysicalDeviceMaintenance3Properties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceMaintenance3Properties( VkPhysicalDeviceMaintenance3Properties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceMaintenance3Properties& operator=( VkPhysicalDeviceMaintenance3Properties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceMaintenance3Properties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceMaintenance3Properties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceMaintenance3Properties*>( this );
+ }
+
+ operator VkPhysicalDeviceMaintenance3Properties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceMaintenance3Properties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceMaintenance3Properties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxPerSetDescriptors == rhs.maxPerSetDescriptors )
+ && ( maxMemoryAllocationSize == rhs.maxMemoryAllocationSize );
+ }
+
+ bool operator!=( PhysicalDeviceMaintenance3Properties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceMaintenance3Properties;
+ void* pNext = {};
+ uint32_t maxPerSetDescriptors = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize maxMemoryAllocationSize = {};
+ };
+ static_assert( sizeof( PhysicalDeviceMaintenance3Properties ) == sizeof( VkPhysicalDeviceMaintenance3Properties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceMaintenance3Properties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceMemoryBudgetPropertiesEXT
+ {
+ PhysicalDeviceMemoryBudgetPropertiesEXT( std::array<VULKAN_HPP_NAMESPACE::DeviceSize,VK_MAX_MEMORY_HEAPS> const& heapBudget_ = {},
+ std::array<VULKAN_HPP_NAMESPACE::DeviceSize,VK_MAX_MEMORY_HEAPS> const& heapUsage_ = {} ) VULKAN_HPP_NOEXCEPT
+ : heapBudget{}
+ , heapUsage{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::DeviceSize,VK_MAX_MEMORY_HEAPS,VK_MAX_MEMORY_HEAPS>::copy( heapBudget, heapBudget_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::DeviceSize,VK_MAX_MEMORY_HEAPS,VK_MAX_MEMORY_HEAPS>::copy( heapUsage, heapUsage_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryBudgetPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryBudgetPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryBudgetPropertiesEXT ) - offsetof( PhysicalDeviceMemoryBudgetPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceMemoryBudgetPropertiesEXT( VkPhysicalDeviceMemoryBudgetPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceMemoryBudgetPropertiesEXT& operator=( VkPhysicalDeviceMemoryBudgetPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryBudgetPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceMemoryBudgetPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceMemoryBudgetPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceMemoryBudgetPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceMemoryBudgetPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceMemoryBudgetPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memcmp( heapBudget, rhs.heapBudget, VK_MAX_MEMORY_HEAPS * sizeof( VULKAN_HPP_NAMESPACE::DeviceSize ) ) == 0 )
+ && ( memcmp( heapUsage, rhs.heapUsage, VK_MAX_MEMORY_HEAPS * sizeof( VULKAN_HPP_NAMESPACE::DeviceSize ) ) == 0 );
+ }
+
+ bool operator!=( PhysicalDeviceMemoryBudgetPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceMemoryBudgetPropertiesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize heapBudget[VK_MAX_MEMORY_HEAPS] = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize heapUsage[VK_MAX_MEMORY_HEAPS] = {};
+ };
+ static_assert( sizeof( PhysicalDeviceMemoryBudgetPropertiesEXT ) == sizeof( VkPhysicalDeviceMemoryBudgetPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceMemoryBudgetPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceMemoryPriorityFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceMemoryPriorityFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 memoryPriority_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memoryPriority( memoryPriority_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryPriorityFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryPriorityFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryPriorityFeaturesEXT ) - offsetof( PhysicalDeviceMemoryPriorityFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceMemoryPriorityFeaturesEXT( VkPhysicalDeviceMemoryPriorityFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceMemoryPriorityFeaturesEXT& operator=( VkPhysicalDeviceMemoryPriorityFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryPriorityFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceMemoryPriorityFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceMemoryPriorityFeaturesEXT & setMemoryPriority( VULKAN_HPP_NAMESPACE::Bool32 memoryPriority_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memoryPriority = memoryPriority_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceMemoryPriorityFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceMemoryPriorityFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceMemoryPriorityFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceMemoryPriorityFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceMemoryPriorityFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memoryPriority == rhs.memoryPriority );
+ }
+
+ bool operator!=( PhysicalDeviceMemoryPriorityFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceMemoryPriorityFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 memoryPriority = {};
+ };
+ static_assert( sizeof( PhysicalDeviceMemoryPriorityFeaturesEXT ) == sizeof( VkPhysicalDeviceMemoryPriorityFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceMemoryPriorityFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceMemoryProperties
+ {
+ PhysicalDeviceMemoryProperties( uint32_t memoryTypeCount_ = {},
+ std::array<VULKAN_HPP_NAMESPACE::MemoryType,VK_MAX_MEMORY_TYPES> const& memoryTypes_ = {},
+ uint32_t memoryHeapCount_ = {},
+ std::array<VULKAN_HPP_NAMESPACE::MemoryHeap,VK_MAX_MEMORY_HEAPS> const& memoryHeaps_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memoryTypeCount( memoryTypeCount_ )
+ , memoryTypes{}
+ , memoryHeapCount( memoryHeapCount_ )
+ , memoryHeaps{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::MemoryType,VK_MAX_MEMORY_TYPES,VK_MAX_MEMORY_TYPES>::copy( memoryTypes, memoryTypes_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::MemoryHeap,VK_MAX_MEMORY_HEAPS,VK_MAX_MEMORY_HEAPS>::copy( memoryHeaps, memoryHeaps_ );
+ }
+
+ PhysicalDeviceMemoryProperties( VkPhysicalDeviceMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceMemoryProperties& operator=( VkPhysicalDeviceMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceMemoryProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceMemoryProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceMemoryProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceMemoryProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceMemoryProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( memoryTypeCount == rhs.memoryTypeCount )
+ && ( memcmp( memoryTypes, rhs.memoryTypes, std::min<uint32_t>( VK_MAX_MEMORY_TYPES, memoryTypeCount ) * sizeof( VULKAN_HPP_NAMESPACE::MemoryType ) ) == 0 )
+ && ( memoryHeapCount == rhs.memoryHeapCount )
+ && ( memcmp( memoryHeaps, rhs.memoryHeaps, std::min<uint32_t>( VK_MAX_MEMORY_HEAPS, memoryHeapCount ) * sizeof( VULKAN_HPP_NAMESPACE::MemoryHeap ) ) == 0 );
+ }
+
+ bool operator!=( PhysicalDeviceMemoryProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t memoryTypeCount = {};
+ VULKAN_HPP_NAMESPACE::MemoryType memoryTypes[VK_MAX_MEMORY_TYPES] = {};
+ uint32_t memoryHeapCount = {};
+ VULKAN_HPP_NAMESPACE::MemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS] = {};
+ };
+ static_assert( sizeof( PhysicalDeviceMemoryProperties ) == sizeof( VkPhysicalDeviceMemoryProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceMemoryProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceMemoryProperties2
+ {
+ PhysicalDeviceMemoryProperties2( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties memoryProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memoryProperties( memoryProperties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 ) - offsetof( PhysicalDeviceMemoryProperties2, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceMemoryProperties2( VkPhysicalDeviceMemoryProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceMemoryProperties2& operator=( VkPhysicalDeviceMemoryProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceMemoryProperties2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceMemoryProperties2*>( this );
+ }
+
+ operator VkPhysicalDeviceMemoryProperties2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( this );
+ }
+
+ bool operator==( PhysicalDeviceMemoryProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memoryProperties == rhs.memoryProperties );
+ }
+
+ bool operator!=( PhysicalDeviceMemoryProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceMemoryProperties2;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties memoryProperties = {};
+ };
+ static_assert( sizeof( PhysicalDeviceMemoryProperties2 ) == sizeof( VkPhysicalDeviceMemoryProperties2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceMemoryProperties2>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceMeshShaderFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceMeshShaderFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 taskShader_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 meshShader_ = {} ) VULKAN_HPP_NOEXCEPT
+ : taskShader( taskShader_ )
+ , meshShader( meshShader_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMeshShaderFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceMeshShaderFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMeshShaderFeaturesNV ) - offsetof( PhysicalDeviceMeshShaderFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceMeshShaderFeaturesNV( VkPhysicalDeviceMeshShaderFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceMeshShaderFeaturesNV& operator=( VkPhysicalDeviceMeshShaderFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceMeshShaderFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceMeshShaderFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceMeshShaderFeaturesNV & setTaskShader( VULKAN_HPP_NAMESPACE::Bool32 taskShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ taskShader = taskShader_;
+ return *this;
+ }
+
+ PhysicalDeviceMeshShaderFeaturesNV & setMeshShader( VULKAN_HPP_NAMESPACE::Bool32 meshShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ meshShader = meshShader_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceMeshShaderFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceMeshShaderFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceMeshShaderFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceMeshShaderFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceMeshShaderFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( taskShader == rhs.taskShader )
+ && ( meshShader == rhs.meshShader );
+ }
+
+ bool operator!=( PhysicalDeviceMeshShaderFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceMeshShaderFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 taskShader = {};
+ VULKAN_HPP_NAMESPACE::Bool32 meshShader = {};
+ };
+ static_assert( sizeof( PhysicalDeviceMeshShaderFeaturesNV ) == sizeof( VkPhysicalDeviceMeshShaderFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceMeshShaderFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceMeshShaderPropertiesNV
+ {
+ PhysicalDeviceMeshShaderPropertiesNV( uint32_t maxDrawMeshTasksCount_ = {},
+ uint32_t maxTaskWorkGroupInvocations_ = {},
+ std::array<uint32_t,3> const& maxTaskWorkGroupSize_ = {},
+ uint32_t maxTaskTotalMemorySize_ = {},
+ uint32_t maxTaskOutputCount_ = {},
+ uint32_t maxMeshWorkGroupInvocations_ = {},
+ std::array<uint32_t,3> const& maxMeshWorkGroupSize_ = {},
+ uint32_t maxMeshTotalMemorySize_ = {},
+ uint32_t maxMeshOutputVertices_ = {},
+ uint32_t maxMeshOutputPrimitives_ = {},
+ uint32_t maxMeshMultiviewViewCount_ = {},
+ uint32_t meshOutputPerVertexGranularity_ = {},
+ uint32_t meshOutputPerPrimitiveGranularity_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxDrawMeshTasksCount( maxDrawMeshTasksCount_ )
+ , maxTaskWorkGroupInvocations( maxTaskWorkGroupInvocations_ )
+ , maxTaskWorkGroupSize{}
+ , maxTaskTotalMemorySize( maxTaskTotalMemorySize_ )
+ , maxTaskOutputCount( maxTaskOutputCount_ )
+ , maxMeshWorkGroupInvocations( maxMeshWorkGroupInvocations_ )
+ , maxMeshWorkGroupSize{}
+ , maxMeshTotalMemorySize( maxMeshTotalMemorySize_ )
+ , maxMeshOutputVertices( maxMeshOutputVertices_ )
+ , maxMeshOutputPrimitives( maxMeshOutputPrimitives_ )
+ , maxMeshMultiviewViewCount( maxMeshMultiviewViewCount_ )
+ , meshOutputPerVertexGranularity( meshOutputPerVertexGranularity_ )
+ , meshOutputPerPrimitiveGranularity( meshOutputPerPrimitiveGranularity_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3,3>::copy( maxTaskWorkGroupSize, maxTaskWorkGroupSize_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3,3>::copy( maxMeshWorkGroupSize, maxMeshWorkGroupSize_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMeshShaderPropertiesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceMeshShaderPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMeshShaderPropertiesNV ) - offsetof( PhysicalDeviceMeshShaderPropertiesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceMeshShaderPropertiesNV( VkPhysicalDeviceMeshShaderPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceMeshShaderPropertiesNV& operator=( VkPhysicalDeviceMeshShaderPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceMeshShaderPropertiesNV const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceMeshShaderPropertiesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceMeshShaderPropertiesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceMeshShaderPropertiesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceMeshShaderPropertiesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceMeshShaderPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxDrawMeshTasksCount == rhs.maxDrawMeshTasksCount )
+ && ( maxTaskWorkGroupInvocations == rhs.maxTaskWorkGroupInvocations )
+ && ( memcmp( maxTaskWorkGroupSize, rhs.maxTaskWorkGroupSize, 3 * sizeof( uint32_t ) ) == 0 )
+ && ( maxTaskTotalMemorySize == rhs.maxTaskTotalMemorySize )
+ && ( maxTaskOutputCount == rhs.maxTaskOutputCount )
+ && ( maxMeshWorkGroupInvocations == rhs.maxMeshWorkGroupInvocations )
+ && ( memcmp( maxMeshWorkGroupSize, rhs.maxMeshWorkGroupSize, 3 * sizeof( uint32_t ) ) == 0 )
+ && ( maxMeshTotalMemorySize == rhs.maxMeshTotalMemorySize )
+ && ( maxMeshOutputVertices == rhs.maxMeshOutputVertices )
+ && ( maxMeshOutputPrimitives == rhs.maxMeshOutputPrimitives )
+ && ( maxMeshMultiviewViewCount == rhs.maxMeshMultiviewViewCount )
+ && ( meshOutputPerVertexGranularity == rhs.meshOutputPerVertexGranularity )
+ && ( meshOutputPerPrimitiveGranularity == rhs.meshOutputPerPrimitiveGranularity );
+ }
+
+ bool operator!=( PhysicalDeviceMeshShaderPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceMeshShaderPropertiesNV;
+ void* pNext = {};
+ uint32_t maxDrawMeshTasksCount = {};
+ uint32_t maxTaskWorkGroupInvocations = {};
+ uint32_t maxTaskWorkGroupSize[3] = {};
+ uint32_t maxTaskTotalMemorySize = {};
+ uint32_t maxTaskOutputCount = {};
+ uint32_t maxMeshWorkGroupInvocations = {};
+ uint32_t maxMeshWorkGroupSize[3] = {};
+ uint32_t maxMeshTotalMemorySize = {};
+ uint32_t maxMeshOutputVertices = {};
+ uint32_t maxMeshOutputPrimitives = {};
+ uint32_t maxMeshMultiviewViewCount = {};
+ uint32_t meshOutputPerVertexGranularity = {};
+ uint32_t meshOutputPerPrimitiveGranularity = {};
+ };
+ static_assert( sizeof( PhysicalDeviceMeshShaderPropertiesNV ) == sizeof( VkPhysicalDeviceMeshShaderPropertiesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceMeshShaderPropertiesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceMultiviewFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceMultiviewFeatures( VULKAN_HPP_NAMESPACE::Bool32 multiview_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 multiviewGeometryShader_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 multiviewTessellationShader_ = {} ) VULKAN_HPP_NOEXCEPT
+ : multiview( multiview_ )
+ , multiviewGeometryShader( multiviewGeometryShader_ )
+ , multiviewTessellationShader( multiviewTessellationShader_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewFeatures ) - offsetof( PhysicalDeviceMultiviewFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceMultiviewFeatures( VkPhysicalDeviceMultiviewFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceMultiviewFeatures& operator=( VkPhysicalDeviceMultiviewFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceMultiviewFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceMultiviewFeatures & setMultiview( VULKAN_HPP_NAMESPACE::Bool32 multiview_ ) VULKAN_HPP_NOEXCEPT
+ {
+ multiview = multiview_;
+ return *this;
+ }
+
+ PhysicalDeviceMultiviewFeatures & setMultiviewGeometryShader( VULKAN_HPP_NAMESPACE::Bool32 multiviewGeometryShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ multiviewGeometryShader = multiviewGeometryShader_;
+ return *this;
+ }
+
+ PhysicalDeviceMultiviewFeatures & setMultiviewTessellationShader( VULKAN_HPP_NAMESPACE::Bool32 multiviewTessellationShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ multiviewTessellationShader = multiviewTessellationShader_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceMultiviewFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceMultiviewFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceMultiviewFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceMultiviewFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceMultiviewFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( multiview == rhs.multiview )
+ && ( multiviewGeometryShader == rhs.multiviewGeometryShader )
+ && ( multiviewTessellationShader == rhs.multiviewTessellationShader );
+ }
+
+ bool operator!=( PhysicalDeviceMultiviewFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceMultiviewFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 multiview = {};
+ VULKAN_HPP_NAMESPACE::Bool32 multiviewGeometryShader = {};
+ VULKAN_HPP_NAMESPACE::Bool32 multiviewTessellationShader = {};
+ };
+ static_assert( sizeof( PhysicalDeviceMultiviewFeatures ) == sizeof( VkPhysicalDeviceMultiviewFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceMultiviewFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX
+ {
+ PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX( VULKAN_HPP_NAMESPACE::Bool32 perViewPositionAllComponents_ = {} ) VULKAN_HPP_NOEXCEPT
+ : perViewPositionAllComponents( perViewPositionAllComponents_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX ) - offsetof( PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX( VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX& operator=( VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX*>( this );
+ }
+
+ operator VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX*>( this );
+ }
+
+ bool operator==( PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( perViewPositionAllComponents == rhs.perViewPositionAllComponents );
+ }
+
+ bool operator!=( PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceMultiviewPerViewAttributesPropertiesNVX;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 perViewPositionAllComponents = {};
+ };
+ static_assert( sizeof( PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX ) == sizeof( VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceMultiviewProperties
+ {
+ PhysicalDeviceMultiviewProperties( uint32_t maxMultiviewViewCount_ = {},
+ uint32_t maxMultiviewInstanceIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxMultiviewViewCount( maxMultiviewViewCount_ )
+ , maxMultiviewInstanceIndex( maxMultiviewInstanceIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewProperties ) - offsetof( PhysicalDeviceMultiviewProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceMultiviewProperties( VkPhysicalDeviceMultiviewProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceMultiviewProperties& operator=( VkPhysicalDeviceMultiviewProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceMultiviewProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceMultiviewProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceMultiviewProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceMultiviewProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceMultiviewProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceMultiviewProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxMultiviewViewCount == rhs.maxMultiviewViewCount )
+ && ( maxMultiviewInstanceIndex == rhs.maxMultiviewInstanceIndex );
+ }
+
+ bool operator!=( PhysicalDeviceMultiviewProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceMultiviewProperties;
+ void* pNext = {};
+ uint32_t maxMultiviewViewCount = {};
+ uint32_t maxMultiviewInstanceIndex = {};
+ };
+ static_assert( sizeof( PhysicalDeviceMultiviewProperties ) == sizeof( VkPhysicalDeviceMultiviewProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceMultiviewProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDevicePCIBusInfoPropertiesEXT
+ {
+ PhysicalDevicePCIBusInfoPropertiesEXT( uint32_t pciDomain_ = {},
+ uint32_t pciBus_ = {},
+ uint32_t pciDevice_ = {},
+ uint32_t pciFunction_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pciDomain( pciDomain_ )
+ , pciBus( pciBus_ )
+ , pciDevice( pciDevice_ )
+ , pciFunction( pciFunction_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDevicePCIBusInfoPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDevicePCIBusInfoPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDevicePCIBusInfoPropertiesEXT ) - offsetof( PhysicalDevicePCIBusInfoPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDevicePCIBusInfoPropertiesEXT( VkPhysicalDevicePCIBusInfoPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDevicePCIBusInfoPropertiesEXT& operator=( VkPhysicalDevicePCIBusInfoPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDevicePCIBusInfoPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDevicePCIBusInfoPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDevicePCIBusInfoPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDevicePCIBusInfoPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDevicePCIBusInfoPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDevicePCIBusInfoPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pciDomain == rhs.pciDomain )
+ && ( pciBus == rhs.pciBus )
+ && ( pciDevice == rhs.pciDevice )
+ && ( pciFunction == rhs.pciFunction );
+ }
+
+ bool operator!=( PhysicalDevicePCIBusInfoPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDevicePciBusInfoPropertiesEXT;
+ void* pNext = {};
+ uint32_t pciDomain = {};
+ uint32_t pciBus = {};
+ uint32_t pciDevice = {};
+ uint32_t pciFunction = {};
+ };
+ static_assert( sizeof( PhysicalDevicePCIBusInfoPropertiesEXT ) == sizeof( VkPhysicalDevicePCIBusInfoPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDevicePCIBusInfoPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDevicePerformanceQueryFeaturesKHR
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDevicePerformanceQueryFeaturesKHR( VULKAN_HPP_NAMESPACE::Bool32 performanceCounterQueryPools_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 performanceCounterMultipleQueryPools_ = {} ) VULKAN_HPP_NOEXCEPT
+ : performanceCounterQueryPools( performanceCounterQueryPools_ )
+ , performanceCounterMultipleQueryPools( performanceCounterMultipleQueryPools_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDevicePerformanceQueryFeaturesKHR & operator=( VULKAN_HPP_NAMESPACE::PhysicalDevicePerformanceQueryFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDevicePerformanceQueryFeaturesKHR ) - offsetof( PhysicalDevicePerformanceQueryFeaturesKHR, pNext ) );
+ return *this;
+ }
+
+ PhysicalDevicePerformanceQueryFeaturesKHR( VkPhysicalDevicePerformanceQueryFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDevicePerformanceQueryFeaturesKHR& operator=( VkPhysicalDevicePerformanceQueryFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDevicePerformanceQueryFeaturesKHR const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDevicePerformanceQueryFeaturesKHR & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDevicePerformanceQueryFeaturesKHR & setPerformanceCounterQueryPools( VULKAN_HPP_NAMESPACE::Bool32 performanceCounterQueryPools_ ) VULKAN_HPP_NOEXCEPT
+ {
+ performanceCounterQueryPools = performanceCounterQueryPools_;
+ return *this;
+ }
+
+ PhysicalDevicePerformanceQueryFeaturesKHR & setPerformanceCounterMultipleQueryPools( VULKAN_HPP_NAMESPACE::Bool32 performanceCounterMultipleQueryPools_ ) VULKAN_HPP_NOEXCEPT
+ {
+ performanceCounterMultipleQueryPools = performanceCounterMultipleQueryPools_;
+ return *this;
+ }
+
+ operator VkPhysicalDevicePerformanceQueryFeaturesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDevicePerformanceQueryFeaturesKHR*>( this );
+ }
+
+ operator VkPhysicalDevicePerformanceQueryFeaturesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDevicePerformanceQueryFeaturesKHR*>( this );
+ }
+
+ bool operator==( PhysicalDevicePerformanceQueryFeaturesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( performanceCounterQueryPools == rhs.performanceCounterQueryPools )
+ && ( performanceCounterMultipleQueryPools == rhs.performanceCounterMultipleQueryPools );
+ }
+
+ bool operator!=( PhysicalDevicePerformanceQueryFeaturesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDevicePerformanceQueryFeaturesKHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 performanceCounterQueryPools = {};
+ VULKAN_HPP_NAMESPACE::Bool32 performanceCounterMultipleQueryPools = {};
+ };
+ static_assert( sizeof( PhysicalDevicePerformanceQueryFeaturesKHR ) == sizeof( VkPhysicalDevicePerformanceQueryFeaturesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDevicePerformanceQueryFeaturesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDevicePerformanceQueryPropertiesKHR
+ {
+ PhysicalDevicePerformanceQueryPropertiesKHR( VULKAN_HPP_NAMESPACE::Bool32 allowCommandBufferQueryCopies_ = {} ) VULKAN_HPP_NOEXCEPT
+ : allowCommandBufferQueryCopies( allowCommandBufferQueryCopies_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDevicePerformanceQueryPropertiesKHR & operator=( VULKAN_HPP_NAMESPACE::PhysicalDevicePerformanceQueryPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDevicePerformanceQueryPropertiesKHR ) - offsetof( PhysicalDevicePerformanceQueryPropertiesKHR, pNext ) );
+ return *this;
+ }
+
+ PhysicalDevicePerformanceQueryPropertiesKHR( VkPhysicalDevicePerformanceQueryPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDevicePerformanceQueryPropertiesKHR& operator=( VkPhysicalDevicePerformanceQueryPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDevicePerformanceQueryPropertiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDevicePerformanceQueryPropertiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDevicePerformanceQueryPropertiesKHR*>( this );
+ }
+
+ operator VkPhysicalDevicePerformanceQueryPropertiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDevicePerformanceQueryPropertiesKHR*>( this );
+ }
+
+ bool operator==( PhysicalDevicePerformanceQueryPropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( allowCommandBufferQueryCopies == rhs.allowCommandBufferQueryCopies );
+ }
+
+ bool operator!=( PhysicalDevicePerformanceQueryPropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDevicePerformanceQueryPropertiesKHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 allowCommandBufferQueryCopies = {};
+ };
+ static_assert( sizeof( PhysicalDevicePerformanceQueryPropertiesKHR ) == sizeof( VkPhysicalDevicePerformanceQueryPropertiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDevicePerformanceQueryPropertiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDevicePipelineExecutablePropertiesFeaturesKHR
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDevicePipelineExecutablePropertiesFeaturesKHR( VULKAN_HPP_NAMESPACE::Bool32 pipelineExecutableInfo_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pipelineExecutableInfo( pipelineExecutableInfo_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDevicePipelineExecutablePropertiesFeaturesKHR & operator=( VULKAN_HPP_NAMESPACE::PhysicalDevicePipelineExecutablePropertiesFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDevicePipelineExecutablePropertiesFeaturesKHR ) - offsetof( PhysicalDevicePipelineExecutablePropertiesFeaturesKHR, pNext ) );
+ return *this;
+ }
+
+ PhysicalDevicePipelineExecutablePropertiesFeaturesKHR( VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDevicePipelineExecutablePropertiesFeaturesKHR& operator=( VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDevicePipelineExecutablePropertiesFeaturesKHR const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDevicePipelineExecutablePropertiesFeaturesKHR & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDevicePipelineExecutablePropertiesFeaturesKHR & setPipelineExecutableInfo( VULKAN_HPP_NAMESPACE::Bool32 pipelineExecutableInfo_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineExecutableInfo = pipelineExecutableInfo_;
+ return *this;
+ }
+
+ operator VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR*>( this );
+ }
+
+ operator VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR*>( this );
+ }
+
+ bool operator==( PhysicalDevicePipelineExecutablePropertiesFeaturesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pipelineExecutableInfo == rhs.pipelineExecutableInfo );
+ }
+
+ bool operator!=( PhysicalDevicePipelineExecutablePropertiesFeaturesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDevicePipelineExecutablePropertiesFeaturesKHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 pipelineExecutableInfo = {};
+ };
+ static_assert( sizeof( PhysicalDevicePipelineExecutablePropertiesFeaturesKHR ) == sizeof( VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDevicePipelineExecutablePropertiesFeaturesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDevicePointClippingProperties
+ {
+ PhysicalDevicePointClippingProperties( VULKAN_HPP_NAMESPACE::PointClippingBehavior pointClippingBehavior_ = VULKAN_HPP_NAMESPACE::PointClippingBehavior::eAllClipPlanes ) VULKAN_HPP_NOEXCEPT
+ : pointClippingBehavior( pointClippingBehavior_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDevicePointClippingProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDevicePointClippingProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDevicePointClippingProperties ) - offsetof( PhysicalDevicePointClippingProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDevicePointClippingProperties( VkPhysicalDevicePointClippingProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDevicePointClippingProperties& operator=( VkPhysicalDevicePointClippingProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDevicePointClippingProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDevicePointClippingProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDevicePointClippingProperties*>( this );
+ }
+
+ operator VkPhysicalDevicePointClippingProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDevicePointClippingProperties*>( this );
+ }
+
+ bool operator==( PhysicalDevicePointClippingProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pointClippingBehavior == rhs.pointClippingBehavior );
+ }
+
+ bool operator!=( PhysicalDevicePointClippingProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDevicePointClippingProperties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PointClippingBehavior pointClippingBehavior = VULKAN_HPP_NAMESPACE::PointClippingBehavior::eAllClipPlanes;
+ };
+ static_assert( sizeof( PhysicalDevicePointClippingProperties ) == sizeof( VkPhysicalDevicePointClippingProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDevicePointClippingProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceSparseProperties
+ {
+ PhysicalDeviceSparseProperties( VULKAN_HPP_NAMESPACE::Bool32 residencyStandard2DBlockShape_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 residencyStandard2DMultisampleBlockShape_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 residencyStandard3DBlockShape_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 residencyAlignedMipSize_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 residencyNonResidentStrict_ = {} ) VULKAN_HPP_NOEXCEPT
+ : residencyStandard2DBlockShape( residencyStandard2DBlockShape_ )
+ , residencyStandard2DMultisampleBlockShape( residencyStandard2DMultisampleBlockShape_ )
+ , residencyStandard3DBlockShape( residencyStandard3DBlockShape_ )
+ , residencyAlignedMipSize( residencyAlignedMipSize_ )
+ , residencyNonResidentStrict( residencyNonResidentStrict_ )
+ {}
+
+ PhysicalDeviceSparseProperties( VkPhysicalDeviceSparseProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceSparseProperties& operator=( VkPhysicalDeviceSparseProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceSparseProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceSparseProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceSparseProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceSparseProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceSparseProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( residencyStandard2DBlockShape == rhs.residencyStandard2DBlockShape )
+ && ( residencyStandard2DMultisampleBlockShape == rhs.residencyStandard2DMultisampleBlockShape )
+ && ( residencyStandard3DBlockShape == rhs.residencyStandard3DBlockShape )
+ && ( residencyAlignedMipSize == rhs.residencyAlignedMipSize )
+ && ( residencyNonResidentStrict == rhs.residencyNonResidentStrict );
+ }
+
+ bool operator!=( PhysicalDeviceSparseProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Bool32 residencyStandard2DBlockShape = {};
+ VULKAN_HPP_NAMESPACE::Bool32 residencyStandard2DMultisampleBlockShape = {};
+ VULKAN_HPP_NAMESPACE::Bool32 residencyStandard3DBlockShape = {};
+ VULKAN_HPP_NAMESPACE::Bool32 residencyAlignedMipSize = {};
+ VULKAN_HPP_NAMESPACE::Bool32 residencyNonResidentStrict = {};
+ };
+ static_assert( sizeof( PhysicalDeviceSparseProperties ) == sizeof( VkPhysicalDeviceSparseProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceSparseProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceProperties
+ {
+ PhysicalDeviceProperties( uint32_t apiVersion_ = {},
+ uint32_t driverVersion_ = {},
+ uint32_t vendorID_ = {},
+ uint32_t deviceID_ = {},
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceType deviceType_ = VULKAN_HPP_NAMESPACE::PhysicalDeviceType::eOther,
+ std::array<char,VK_MAX_PHYSICAL_DEVICE_NAME_SIZE> const& deviceName_ = {},
+ std::array<uint8_t,VK_UUID_SIZE> const& pipelineCacheUUID_ = {},
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceLimits limits_ = {},
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseProperties sparseProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : apiVersion( apiVersion_ )
+ , driverVersion( driverVersion_ )
+ , vendorID( vendorID_ )
+ , deviceID( deviceID_ )
+ , deviceType( deviceType_ )
+ , deviceName{}
+ , pipelineCacheUUID{}
+ , limits( limits_ )
+ , sparseProperties( sparseProperties_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_PHYSICAL_DEVICE_NAME_SIZE,VK_MAX_PHYSICAL_DEVICE_NAME_SIZE>::copy( deviceName, deviceName_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE,VK_UUID_SIZE>::copy( pipelineCacheUUID, pipelineCacheUUID_ );
+ }
+
+ PhysicalDeviceProperties( VkPhysicalDeviceProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceProperties& operator=( VkPhysicalDeviceProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( apiVersion == rhs.apiVersion )
+ && ( driverVersion == rhs.driverVersion )
+ && ( vendorID == rhs.vendorID )
+ && ( deviceID == rhs.deviceID )
+ && ( deviceType == rhs.deviceType )
+ && ( memcmp( deviceName, rhs.deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE * sizeof( char ) ) == 0 )
+ && ( memcmp( pipelineCacheUUID, rhs.pipelineCacheUUID, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 )
+ && ( limits == rhs.limits )
+ && ( sparseProperties == rhs.sparseProperties );
+ }
+
+ bool operator!=( PhysicalDeviceProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t apiVersion = {};
+ uint32_t driverVersion = {};
+ uint32_t vendorID = {};
+ uint32_t deviceID = {};
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceType deviceType = VULKAN_HPP_NAMESPACE::PhysicalDeviceType::eOther;
+ char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE] = {};
+ uint8_t pipelineCacheUUID[VK_UUID_SIZE] = {};
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceLimits limits = {};
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseProperties sparseProperties = {};
+ };
+ static_assert( sizeof( PhysicalDeviceProperties ) == sizeof( VkPhysicalDeviceProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceProperties2
+ {
+ PhysicalDeviceProperties2( VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties properties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : properties( properties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 ) - offsetof( PhysicalDeviceProperties2, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceProperties2( VkPhysicalDeviceProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceProperties2& operator=( VkPhysicalDeviceProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceProperties2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceProperties2*>( this );
+ }
+
+ operator VkPhysicalDeviceProperties2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceProperties2*>( this );
+ }
+
+ bool operator==( PhysicalDeviceProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( properties == rhs.properties );
+ }
+
+ bool operator!=( PhysicalDeviceProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceProperties2;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties properties = {};
+ };
+ static_assert( sizeof( PhysicalDeviceProperties2 ) == sizeof( VkPhysicalDeviceProperties2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceProperties2>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceProtectedMemoryFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceProtectedMemoryFeatures( VULKAN_HPP_NAMESPACE::Bool32 protectedMemory_ = {} ) VULKAN_HPP_NOEXCEPT
+ : protectedMemory( protectedMemory_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProtectedMemoryFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceProtectedMemoryFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceProtectedMemoryFeatures ) - offsetof( PhysicalDeviceProtectedMemoryFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceProtectedMemoryFeatures( VkPhysicalDeviceProtectedMemoryFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceProtectedMemoryFeatures& operator=( VkPhysicalDeviceProtectedMemoryFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceProtectedMemoryFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceProtectedMemoryFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceProtectedMemoryFeatures & setProtectedMemory( VULKAN_HPP_NAMESPACE::Bool32 protectedMemory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ protectedMemory = protectedMemory_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceProtectedMemoryFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceProtectedMemoryFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceProtectedMemoryFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceProtectedMemoryFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceProtectedMemoryFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( protectedMemory == rhs.protectedMemory );
+ }
+
+ bool operator!=( PhysicalDeviceProtectedMemoryFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceProtectedMemoryFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 protectedMemory = {};
+ };
+ static_assert( sizeof( PhysicalDeviceProtectedMemoryFeatures ) == sizeof( VkPhysicalDeviceProtectedMemoryFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceProtectedMemoryFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceProtectedMemoryProperties
+ {
+ PhysicalDeviceProtectedMemoryProperties( VULKAN_HPP_NAMESPACE::Bool32 protectedNoFault_ = {} ) VULKAN_HPP_NOEXCEPT
+ : protectedNoFault( protectedNoFault_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProtectedMemoryProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceProtectedMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceProtectedMemoryProperties ) - offsetof( PhysicalDeviceProtectedMemoryProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceProtectedMemoryProperties( VkPhysicalDeviceProtectedMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceProtectedMemoryProperties& operator=( VkPhysicalDeviceProtectedMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceProtectedMemoryProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceProtectedMemoryProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceProtectedMemoryProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceProtectedMemoryProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceProtectedMemoryProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceProtectedMemoryProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( protectedNoFault == rhs.protectedNoFault );
+ }
+
+ bool operator!=( PhysicalDeviceProtectedMemoryProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceProtectedMemoryProperties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 protectedNoFault = {};
+ };
+ static_assert( sizeof( PhysicalDeviceProtectedMemoryProperties ) == sizeof( VkPhysicalDeviceProtectedMemoryProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceProtectedMemoryProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDevicePushDescriptorPropertiesKHR
+ {
+ PhysicalDevicePushDescriptorPropertiesKHR( uint32_t maxPushDescriptors_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxPushDescriptors( maxPushDescriptors_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDevicePushDescriptorPropertiesKHR & operator=( VULKAN_HPP_NAMESPACE::PhysicalDevicePushDescriptorPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDevicePushDescriptorPropertiesKHR ) - offsetof( PhysicalDevicePushDescriptorPropertiesKHR, pNext ) );
+ return *this;
+ }
+
+ PhysicalDevicePushDescriptorPropertiesKHR( VkPhysicalDevicePushDescriptorPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDevicePushDescriptorPropertiesKHR& operator=( VkPhysicalDevicePushDescriptorPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDevicePushDescriptorPropertiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDevicePushDescriptorPropertiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDevicePushDescriptorPropertiesKHR*>( this );
+ }
+
+ operator VkPhysicalDevicePushDescriptorPropertiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDevicePushDescriptorPropertiesKHR*>( this );
+ }
+
+ bool operator==( PhysicalDevicePushDescriptorPropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxPushDescriptors == rhs.maxPushDescriptors );
+ }
+
+ bool operator!=( PhysicalDevicePushDescriptorPropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDevicePushDescriptorPropertiesKHR;
+ void* pNext = {};
+ uint32_t maxPushDescriptors = {};
+ };
+ static_assert( sizeof( PhysicalDevicePushDescriptorPropertiesKHR ) == sizeof( VkPhysicalDevicePushDescriptorPropertiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDevicePushDescriptorPropertiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceRayTracingPropertiesNV
+ {
+ PhysicalDeviceRayTracingPropertiesNV( uint32_t shaderGroupHandleSize_ = {},
+ uint32_t maxRecursionDepth_ = {},
+ uint32_t maxShaderGroupStride_ = {},
+ uint32_t shaderGroupBaseAlignment_ = {},
+ uint64_t maxGeometryCount_ = {},
+ uint64_t maxInstanceCount_ = {},
+ uint64_t maxTriangleCount_ = {},
+ uint32_t maxDescriptorSetAccelerationStructures_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderGroupHandleSize( shaderGroupHandleSize_ )
+ , maxRecursionDepth( maxRecursionDepth_ )
+ , maxShaderGroupStride( maxShaderGroupStride_ )
+ , shaderGroupBaseAlignment( shaderGroupBaseAlignment_ )
+ , maxGeometryCount( maxGeometryCount_ )
+ , maxInstanceCount( maxInstanceCount_ )
+ , maxTriangleCount( maxTriangleCount_ )
+ , maxDescriptorSetAccelerationStructures( maxDescriptorSetAccelerationStructures_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceRayTracingPropertiesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceRayTracingPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceRayTracingPropertiesNV ) - offsetof( PhysicalDeviceRayTracingPropertiesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceRayTracingPropertiesNV( VkPhysicalDeviceRayTracingPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceRayTracingPropertiesNV& operator=( VkPhysicalDeviceRayTracingPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceRayTracingPropertiesNV const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceRayTracingPropertiesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceRayTracingPropertiesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceRayTracingPropertiesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceRayTracingPropertiesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceRayTracingPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderGroupHandleSize == rhs.shaderGroupHandleSize )
+ && ( maxRecursionDepth == rhs.maxRecursionDepth )
+ && ( maxShaderGroupStride == rhs.maxShaderGroupStride )
+ && ( shaderGroupBaseAlignment == rhs.shaderGroupBaseAlignment )
+ && ( maxGeometryCount == rhs.maxGeometryCount )
+ && ( maxInstanceCount == rhs.maxInstanceCount )
+ && ( maxTriangleCount == rhs.maxTriangleCount )
+ && ( maxDescriptorSetAccelerationStructures == rhs.maxDescriptorSetAccelerationStructures );
+ }
+
+ bool operator!=( PhysicalDeviceRayTracingPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceRayTracingPropertiesNV;
+ void* pNext = {};
+ uint32_t shaderGroupHandleSize = {};
+ uint32_t maxRecursionDepth = {};
+ uint32_t maxShaderGroupStride = {};
+ uint32_t shaderGroupBaseAlignment = {};
+ uint64_t maxGeometryCount = {};
+ uint64_t maxInstanceCount = {};
+ uint64_t maxTriangleCount = {};
+ uint32_t maxDescriptorSetAccelerationStructures = {};
+ };
+ static_assert( sizeof( PhysicalDeviceRayTracingPropertiesNV ) == sizeof( VkPhysicalDeviceRayTracingPropertiesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceRayTracingPropertiesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceRepresentativeFragmentTestFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceRepresentativeFragmentTestFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 representativeFragmentTest_ = {} ) VULKAN_HPP_NOEXCEPT
+ : representativeFragmentTest( representativeFragmentTest_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceRepresentativeFragmentTestFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceRepresentativeFragmentTestFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceRepresentativeFragmentTestFeaturesNV ) - offsetof( PhysicalDeviceRepresentativeFragmentTestFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceRepresentativeFragmentTestFeaturesNV( VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceRepresentativeFragmentTestFeaturesNV& operator=( VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceRepresentativeFragmentTestFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceRepresentativeFragmentTestFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceRepresentativeFragmentTestFeaturesNV & setRepresentativeFragmentTest( VULKAN_HPP_NAMESPACE::Bool32 representativeFragmentTest_ ) VULKAN_HPP_NOEXCEPT
+ {
+ representativeFragmentTest = representativeFragmentTest_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceRepresentativeFragmentTestFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( representativeFragmentTest == rhs.representativeFragmentTest );
+ }
+
+ bool operator!=( PhysicalDeviceRepresentativeFragmentTestFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceRepresentativeFragmentTestFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 representativeFragmentTest = {};
+ };
+ static_assert( sizeof( PhysicalDeviceRepresentativeFragmentTestFeaturesNV ) == sizeof( VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceRepresentativeFragmentTestFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceSampleLocationsPropertiesEXT
+ {
+ PhysicalDeviceSampleLocationsPropertiesEXT( VULKAN_HPP_NAMESPACE::SampleCountFlags sampleLocationSampleCounts_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D maxSampleLocationGridSize_ = {},
+ std::array<float,2> const& sampleLocationCoordinateRange_ = {},
+ uint32_t sampleLocationSubPixelBits_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 variableSampleLocations_ = {} ) VULKAN_HPP_NOEXCEPT
+ : sampleLocationSampleCounts( sampleLocationSampleCounts_ )
+ , maxSampleLocationGridSize( maxSampleLocationGridSize_ )
+ , sampleLocationCoordinateRange{}
+ , sampleLocationSubPixelBits( sampleLocationSubPixelBits_ )
+ , variableSampleLocations( variableSampleLocations_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2,2>::copy( sampleLocationCoordinateRange, sampleLocationCoordinateRange_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSampleLocationsPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceSampleLocationsPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceSampleLocationsPropertiesEXT ) - offsetof( PhysicalDeviceSampleLocationsPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceSampleLocationsPropertiesEXT( VkPhysicalDeviceSampleLocationsPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceSampleLocationsPropertiesEXT& operator=( VkPhysicalDeviceSampleLocationsPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceSampleLocationsPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceSampleLocationsPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceSampleLocationsPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceSampleLocationsPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceSampleLocationsPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceSampleLocationsPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( sampleLocationSampleCounts == rhs.sampleLocationSampleCounts )
+ && ( maxSampleLocationGridSize == rhs.maxSampleLocationGridSize )
+ && ( memcmp( sampleLocationCoordinateRange, rhs.sampleLocationCoordinateRange, 2 * sizeof( float ) ) == 0 )
+ && ( sampleLocationSubPixelBits == rhs.sampleLocationSubPixelBits )
+ && ( variableSampleLocations == rhs.variableSampleLocations );
+ }
+
+ bool operator!=( PhysicalDeviceSampleLocationsPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceSampleLocationsPropertiesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags sampleLocationSampleCounts = {};
+ VULKAN_HPP_NAMESPACE::Extent2D maxSampleLocationGridSize = {};
+ float sampleLocationCoordinateRange[2] = {};
+ uint32_t sampleLocationSubPixelBits = {};
+ VULKAN_HPP_NAMESPACE::Bool32 variableSampleLocations = {};
+ };
+ static_assert( sizeof( PhysicalDeviceSampleLocationsPropertiesEXT ) == sizeof( VkPhysicalDeviceSampleLocationsPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceSampleLocationsPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceSamplerFilterMinmaxProperties
+ {
+ PhysicalDeviceSamplerFilterMinmaxProperties( VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxSingleComponentFormats_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxImageComponentMapping_ = {} ) VULKAN_HPP_NOEXCEPT
+ : filterMinmaxSingleComponentFormats( filterMinmaxSingleComponentFormats_ )
+ , filterMinmaxImageComponentMapping( filterMinmaxImageComponentMapping_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSamplerFilterMinmaxProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceSamplerFilterMinmaxProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceSamplerFilterMinmaxProperties ) - offsetof( PhysicalDeviceSamplerFilterMinmaxProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceSamplerFilterMinmaxProperties( VkPhysicalDeviceSamplerFilterMinmaxProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceSamplerFilterMinmaxProperties& operator=( VkPhysicalDeviceSamplerFilterMinmaxProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceSamplerFilterMinmaxProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceSamplerFilterMinmaxProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceSamplerFilterMinmaxProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceSamplerFilterMinmaxProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceSamplerFilterMinmaxProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceSamplerFilterMinmaxProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( filterMinmaxSingleComponentFormats == rhs.filterMinmaxSingleComponentFormats )
+ && ( filterMinmaxImageComponentMapping == rhs.filterMinmaxImageComponentMapping );
+ }
+
+ bool operator!=( PhysicalDeviceSamplerFilterMinmaxProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceSamplerFilterMinmaxProperties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxSingleComponentFormats = {};
+ VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxImageComponentMapping = {};
+ };
+ static_assert( sizeof( PhysicalDeviceSamplerFilterMinmaxProperties ) == sizeof( VkPhysicalDeviceSamplerFilterMinmaxProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceSamplerFilterMinmaxProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceSamplerYcbcrConversionFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceSamplerYcbcrConversionFeatures( VULKAN_HPP_NAMESPACE::Bool32 samplerYcbcrConversion_ = {} ) VULKAN_HPP_NOEXCEPT
+ : samplerYcbcrConversion( samplerYcbcrConversion_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSamplerYcbcrConversionFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceSamplerYcbcrConversionFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceSamplerYcbcrConversionFeatures ) - offsetof( PhysicalDeviceSamplerYcbcrConversionFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceSamplerYcbcrConversionFeatures( VkPhysicalDeviceSamplerYcbcrConversionFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceSamplerYcbcrConversionFeatures& operator=( VkPhysicalDeviceSamplerYcbcrConversionFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceSamplerYcbcrConversionFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceSamplerYcbcrConversionFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceSamplerYcbcrConversionFeatures & setSamplerYcbcrConversion( VULKAN_HPP_NAMESPACE::Bool32 samplerYcbcrConversion_ ) VULKAN_HPP_NOEXCEPT
+ {
+ samplerYcbcrConversion = samplerYcbcrConversion_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceSamplerYcbcrConversionFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceSamplerYcbcrConversionFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceSamplerYcbcrConversionFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceSamplerYcbcrConversionFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceSamplerYcbcrConversionFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( samplerYcbcrConversion == rhs.samplerYcbcrConversion );
+ }
+
+ bool operator!=( PhysicalDeviceSamplerYcbcrConversionFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceSamplerYcbcrConversionFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 samplerYcbcrConversion = {};
+ };
+ static_assert( sizeof( PhysicalDeviceSamplerYcbcrConversionFeatures ) == sizeof( VkPhysicalDeviceSamplerYcbcrConversionFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceSamplerYcbcrConversionFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceScalarBlockLayoutFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceScalarBlockLayoutFeatures( VULKAN_HPP_NAMESPACE::Bool32 scalarBlockLayout_ = {} ) VULKAN_HPP_NOEXCEPT
+ : scalarBlockLayout( scalarBlockLayout_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceScalarBlockLayoutFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceScalarBlockLayoutFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceScalarBlockLayoutFeatures ) - offsetof( PhysicalDeviceScalarBlockLayoutFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceScalarBlockLayoutFeatures( VkPhysicalDeviceScalarBlockLayoutFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceScalarBlockLayoutFeatures& operator=( VkPhysicalDeviceScalarBlockLayoutFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceScalarBlockLayoutFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceScalarBlockLayoutFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceScalarBlockLayoutFeatures & setScalarBlockLayout( VULKAN_HPP_NAMESPACE::Bool32 scalarBlockLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ scalarBlockLayout = scalarBlockLayout_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceScalarBlockLayoutFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceScalarBlockLayoutFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceScalarBlockLayoutFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceScalarBlockLayoutFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceScalarBlockLayoutFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( scalarBlockLayout == rhs.scalarBlockLayout );
+ }
+
+ bool operator!=( PhysicalDeviceScalarBlockLayoutFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceScalarBlockLayoutFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 scalarBlockLayout = {};
+ };
+ static_assert( sizeof( PhysicalDeviceScalarBlockLayoutFeatures ) == sizeof( VkPhysicalDeviceScalarBlockLayoutFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceScalarBlockLayoutFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceSeparateDepthStencilLayoutsFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceSeparateDepthStencilLayoutsFeatures( VULKAN_HPP_NAMESPACE::Bool32 separateDepthStencilLayouts_ = {} ) VULKAN_HPP_NOEXCEPT
+ : separateDepthStencilLayouts( separateDepthStencilLayouts_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSeparateDepthStencilLayoutsFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceSeparateDepthStencilLayoutsFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceSeparateDepthStencilLayoutsFeatures ) - offsetof( PhysicalDeviceSeparateDepthStencilLayoutsFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceSeparateDepthStencilLayoutsFeatures( VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceSeparateDepthStencilLayoutsFeatures& operator=( VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceSeparateDepthStencilLayoutsFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceSeparateDepthStencilLayoutsFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceSeparateDepthStencilLayoutsFeatures & setSeparateDepthStencilLayouts( VULKAN_HPP_NAMESPACE::Bool32 separateDepthStencilLayouts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ separateDepthStencilLayouts = separateDepthStencilLayouts_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceSeparateDepthStencilLayoutsFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( separateDepthStencilLayouts == rhs.separateDepthStencilLayouts );
+ }
+
+ bool operator!=( PhysicalDeviceSeparateDepthStencilLayoutsFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceSeparateDepthStencilLayoutsFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 separateDepthStencilLayouts = {};
+ };
+ static_assert( sizeof( PhysicalDeviceSeparateDepthStencilLayoutsFeatures ) == sizeof( VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceSeparateDepthStencilLayoutsFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderAtomicInt64Features
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderAtomicInt64Features( VULKAN_HPP_NAMESPACE::Bool32 shaderBufferInt64Atomics_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSharedInt64Atomics_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderBufferInt64Atomics( shaderBufferInt64Atomics_ )
+ , shaderSharedInt64Atomics( shaderSharedInt64Atomics_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderAtomicInt64Features & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderAtomicInt64Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderAtomicInt64Features ) - offsetof( PhysicalDeviceShaderAtomicInt64Features, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderAtomicInt64Features( VkPhysicalDeviceShaderAtomicInt64Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderAtomicInt64Features& operator=( VkPhysicalDeviceShaderAtomicInt64Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderAtomicInt64Features const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceShaderAtomicInt64Features & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderAtomicInt64Features & setShaderBufferInt64Atomics( VULKAN_HPP_NAMESPACE::Bool32 shaderBufferInt64Atomics_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderBufferInt64Atomics = shaderBufferInt64Atomics_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderAtomicInt64Features & setShaderSharedInt64Atomics( VULKAN_HPP_NAMESPACE::Bool32 shaderSharedInt64Atomics_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSharedInt64Atomics = shaderSharedInt64Atomics_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderAtomicInt64Features const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderAtomicInt64Features*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderAtomicInt64Features &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderAtomicInt64Features*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderAtomicInt64Features const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderBufferInt64Atomics == rhs.shaderBufferInt64Atomics )
+ && ( shaderSharedInt64Atomics == rhs.shaderSharedInt64Atomics );
+ }
+
+ bool operator!=( PhysicalDeviceShaderAtomicInt64Features const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderAtomicInt64Features;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderBufferInt64Atomics = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSharedInt64Atomics = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderAtomicInt64Features ) == sizeof( VkPhysicalDeviceShaderAtomicInt64Features ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderAtomicInt64Features>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderClockFeaturesKHR
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderClockFeaturesKHR( VULKAN_HPP_NAMESPACE::Bool32 shaderSubgroupClock_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDeviceClock_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderSubgroupClock( shaderSubgroupClock_ )
+ , shaderDeviceClock( shaderDeviceClock_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderClockFeaturesKHR & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderClockFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderClockFeaturesKHR ) - offsetof( PhysicalDeviceShaderClockFeaturesKHR, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderClockFeaturesKHR( VkPhysicalDeviceShaderClockFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderClockFeaturesKHR& operator=( VkPhysicalDeviceShaderClockFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderClockFeaturesKHR const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceShaderClockFeaturesKHR & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderClockFeaturesKHR & setShaderSubgroupClock( VULKAN_HPP_NAMESPACE::Bool32 shaderSubgroupClock_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSubgroupClock = shaderSubgroupClock_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderClockFeaturesKHR & setShaderDeviceClock( VULKAN_HPP_NAMESPACE::Bool32 shaderDeviceClock_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderDeviceClock = shaderDeviceClock_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderClockFeaturesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderClockFeaturesKHR*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderClockFeaturesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderClockFeaturesKHR*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderClockFeaturesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderSubgroupClock == rhs.shaderSubgroupClock )
+ && ( shaderDeviceClock == rhs.shaderDeviceClock );
+ }
+
+ bool operator!=( PhysicalDeviceShaderClockFeaturesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderClockFeaturesKHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSubgroupClock = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDeviceClock = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderClockFeaturesKHR ) == sizeof( VkPhysicalDeviceShaderClockFeaturesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderClockFeaturesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderCoreProperties2AMD
+ {
+ PhysicalDeviceShaderCoreProperties2AMD( VULKAN_HPP_NAMESPACE::ShaderCorePropertiesFlagsAMD shaderCoreFeatures_ = {},
+ uint32_t activeComputeUnitCount_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderCoreFeatures( shaderCoreFeatures_ )
+ , activeComputeUnitCount( activeComputeUnitCount_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderCoreProperties2AMD & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderCoreProperties2AMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderCoreProperties2AMD ) - offsetof( PhysicalDeviceShaderCoreProperties2AMD, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderCoreProperties2AMD( VkPhysicalDeviceShaderCoreProperties2AMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderCoreProperties2AMD& operator=( VkPhysicalDeviceShaderCoreProperties2AMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderCoreProperties2AMD const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderCoreProperties2AMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderCoreProperties2AMD*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderCoreProperties2AMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderCoreProperties2AMD*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderCoreProperties2AMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderCoreFeatures == rhs.shaderCoreFeatures )
+ && ( activeComputeUnitCount == rhs.activeComputeUnitCount );
+ }
+
+ bool operator!=( PhysicalDeviceShaderCoreProperties2AMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderCoreProperties2AMD;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ShaderCorePropertiesFlagsAMD shaderCoreFeatures = {};
+ uint32_t activeComputeUnitCount = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderCoreProperties2AMD ) == sizeof( VkPhysicalDeviceShaderCoreProperties2AMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderCoreProperties2AMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderCorePropertiesAMD
+ {
+ PhysicalDeviceShaderCorePropertiesAMD( uint32_t shaderEngineCount_ = {},
+ uint32_t shaderArraysPerEngineCount_ = {},
+ uint32_t computeUnitsPerShaderArray_ = {},
+ uint32_t simdPerComputeUnit_ = {},
+ uint32_t wavefrontsPerSimd_ = {},
+ uint32_t wavefrontSize_ = {},
+ uint32_t sgprsPerSimd_ = {},
+ uint32_t minSgprAllocation_ = {},
+ uint32_t maxSgprAllocation_ = {},
+ uint32_t sgprAllocationGranularity_ = {},
+ uint32_t vgprsPerSimd_ = {},
+ uint32_t minVgprAllocation_ = {},
+ uint32_t maxVgprAllocation_ = {},
+ uint32_t vgprAllocationGranularity_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderEngineCount( shaderEngineCount_ )
+ , shaderArraysPerEngineCount( shaderArraysPerEngineCount_ )
+ , computeUnitsPerShaderArray( computeUnitsPerShaderArray_ )
+ , simdPerComputeUnit( simdPerComputeUnit_ )
+ , wavefrontsPerSimd( wavefrontsPerSimd_ )
+ , wavefrontSize( wavefrontSize_ )
+ , sgprsPerSimd( sgprsPerSimd_ )
+ , minSgprAllocation( minSgprAllocation_ )
+ , maxSgprAllocation( maxSgprAllocation_ )
+ , sgprAllocationGranularity( sgprAllocationGranularity_ )
+ , vgprsPerSimd( vgprsPerSimd_ )
+ , minVgprAllocation( minVgprAllocation_ )
+ , maxVgprAllocation( maxVgprAllocation_ )
+ , vgprAllocationGranularity( vgprAllocationGranularity_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderCorePropertiesAMD & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderCorePropertiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderCorePropertiesAMD ) - offsetof( PhysicalDeviceShaderCorePropertiesAMD, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderCorePropertiesAMD( VkPhysicalDeviceShaderCorePropertiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderCorePropertiesAMD& operator=( VkPhysicalDeviceShaderCorePropertiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderCorePropertiesAMD const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderCorePropertiesAMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderCorePropertiesAMD*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderCorePropertiesAMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderCorePropertiesAMD*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderCorePropertiesAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderEngineCount == rhs.shaderEngineCount )
+ && ( shaderArraysPerEngineCount == rhs.shaderArraysPerEngineCount )
+ && ( computeUnitsPerShaderArray == rhs.computeUnitsPerShaderArray )
+ && ( simdPerComputeUnit == rhs.simdPerComputeUnit )
+ && ( wavefrontsPerSimd == rhs.wavefrontsPerSimd )
+ && ( wavefrontSize == rhs.wavefrontSize )
+ && ( sgprsPerSimd == rhs.sgprsPerSimd )
+ && ( minSgprAllocation == rhs.minSgprAllocation )
+ && ( maxSgprAllocation == rhs.maxSgprAllocation )
+ && ( sgprAllocationGranularity == rhs.sgprAllocationGranularity )
+ && ( vgprsPerSimd == rhs.vgprsPerSimd )
+ && ( minVgprAllocation == rhs.minVgprAllocation )
+ && ( maxVgprAllocation == rhs.maxVgprAllocation )
+ && ( vgprAllocationGranularity == rhs.vgprAllocationGranularity );
+ }
+
+ bool operator!=( PhysicalDeviceShaderCorePropertiesAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderCorePropertiesAMD;
+ void* pNext = {};
+ uint32_t shaderEngineCount = {};
+ uint32_t shaderArraysPerEngineCount = {};
+ uint32_t computeUnitsPerShaderArray = {};
+ uint32_t simdPerComputeUnit = {};
+ uint32_t wavefrontsPerSimd = {};
+ uint32_t wavefrontSize = {};
+ uint32_t sgprsPerSimd = {};
+ uint32_t minSgprAllocation = {};
+ uint32_t maxSgprAllocation = {};
+ uint32_t sgprAllocationGranularity = {};
+ uint32_t vgprsPerSimd = {};
+ uint32_t minVgprAllocation = {};
+ uint32_t maxVgprAllocation = {};
+ uint32_t vgprAllocationGranularity = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderCorePropertiesAMD ) == sizeof( VkPhysicalDeviceShaderCorePropertiesAMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderCorePropertiesAMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 shaderDemoteToHelperInvocation_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderDemoteToHelperInvocation( shaderDemoteToHelperInvocation_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT ) - offsetof( PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT( VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT& operator=( VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT & setShaderDemoteToHelperInvocation( VULKAN_HPP_NAMESPACE::Bool32 shaderDemoteToHelperInvocation_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderDemoteToHelperInvocation = shaderDemoteToHelperInvocation_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderDemoteToHelperInvocation == rhs.shaderDemoteToHelperInvocation );
+ }
+
+ bool operator!=( PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDemoteToHelperInvocation = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT ) == sizeof( VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderDrawParametersFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderDrawParametersFeatures( VULKAN_HPP_NAMESPACE::Bool32 shaderDrawParameters_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderDrawParameters( shaderDrawParameters_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderDrawParametersFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderDrawParametersFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderDrawParametersFeatures ) - offsetof( PhysicalDeviceShaderDrawParametersFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderDrawParametersFeatures( VkPhysicalDeviceShaderDrawParametersFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderDrawParametersFeatures& operator=( VkPhysicalDeviceShaderDrawParametersFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderDrawParametersFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceShaderDrawParametersFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderDrawParametersFeatures & setShaderDrawParameters( VULKAN_HPP_NAMESPACE::Bool32 shaderDrawParameters_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderDrawParameters = shaderDrawParameters_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderDrawParametersFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderDrawParametersFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderDrawParametersFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderDrawParametersFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderDrawParametersFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderDrawParameters == rhs.shaderDrawParameters );
+ }
+
+ bool operator!=( PhysicalDeviceShaderDrawParametersFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderDrawParametersFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDrawParameters = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderDrawParametersFeatures ) == sizeof( VkPhysicalDeviceShaderDrawParametersFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderDrawParametersFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderFloat16Int8Features
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderFloat16Int8Features( VULKAN_HPP_NAMESPACE::Bool32 shaderFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInt8_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderFloat16( shaderFloat16_ )
+ , shaderInt8( shaderInt8_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderFloat16Int8Features & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderFloat16Int8Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderFloat16Int8Features ) - offsetof( PhysicalDeviceShaderFloat16Int8Features, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderFloat16Int8Features( VkPhysicalDeviceShaderFloat16Int8Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderFloat16Int8Features& operator=( VkPhysicalDeviceShaderFloat16Int8Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderFloat16Int8Features const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceShaderFloat16Int8Features & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderFloat16Int8Features & setShaderFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderFloat16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderFloat16 = shaderFloat16_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderFloat16Int8Features & setShaderInt8( VULKAN_HPP_NAMESPACE::Bool32 shaderInt8_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderInt8 = shaderInt8_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderFloat16Int8Features const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderFloat16Int8Features*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderFloat16Int8Features &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderFloat16Int8Features*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderFloat16Int8Features const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderFloat16 == rhs.shaderFloat16 )
+ && ( shaderInt8 == rhs.shaderInt8 );
+ }
+
+ bool operator!=( PhysicalDeviceShaderFloat16Int8Features const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderFloat16Int8Features;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInt8 = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderFloat16Int8Features ) == sizeof( VkPhysicalDeviceShaderFloat16Int8Features ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderFloat16Int8Features>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderImageFootprintFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderImageFootprintFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 imageFootprint_ = {} ) VULKAN_HPP_NOEXCEPT
+ : imageFootprint( imageFootprint_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderImageFootprintFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderImageFootprintFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderImageFootprintFeaturesNV ) - offsetof( PhysicalDeviceShaderImageFootprintFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderImageFootprintFeaturesNV( VkPhysicalDeviceShaderImageFootprintFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderImageFootprintFeaturesNV& operator=( VkPhysicalDeviceShaderImageFootprintFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderImageFootprintFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceShaderImageFootprintFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderImageFootprintFeaturesNV & setImageFootprint( VULKAN_HPP_NAMESPACE::Bool32 imageFootprint_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageFootprint = imageFootprint_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderImageFootprintFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderImageFootprintFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderImageFootprintFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderImageFootprintFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderImageFootprintFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( imageFootprint == rhs.imageFootprint );
+ }
+
+ bool operator!=( PhysicalDeviceShaderImageFootprintFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderImageFootprintFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 imageFootprint = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderImageFootprintFeaturesNV ) == sizeof( VkPhysicalDeviceShaderImageFootprintFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderImageFootprintFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL( VULKAN_HPP_NAMESPACE::Bool32 shaderIntegerFunctions2_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderIntegerFunctions2( shaderIntegerFunctions2_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL ) - offsetof( PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL( VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL& operator=( VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL & setShaderIntegerFunctions2( VULKAN_HPP_NAMESPACE::Bool32 shaderIntegerFunctions2_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderIntegerFunctions2 = shaderIntegerFunctions2_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderIntegerFunctions2 == rhs.shaderIntegerFunctions2 );
+ }
+
+ bool operator!=( PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderIntegerFunctions2FeaturesINTEL;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderIntegerFunctions2 = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL ) == sizeof( VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderSMBuiltinsFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderSMBuiltinsFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 shaderSMBuiltins_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderSMBuiltins( shaderSMBuiltins_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSMBuiltinsFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSMBuiltinsFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSMBuiltinsFeaturesNV ) - offsetof( PhysicalDeviceShaderSMBuiltinsFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderSMBuiltinsFeaturesNV( VkPhysicalDeviceShaderSMBuiltinsFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderSMBuiltinsFeaturesNV& operator=( VkPhysicalDeviceShaderSMBuiltinsFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSMBuiltinsFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceShaderSMBuiltinsFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderSMBuiltinsFeaturesNV & setShaderSMBuiltins( VULKAN_HPP_NAMESPACE::Bool32 shaderSMBuiltins_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSMBuiltins = shaderSMBuiltins_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderSMBuiltinsFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderSMBuiltinsFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderSMBuiltinsFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderSMBuiltinsFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderSMBuiltinsFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderSMBuiltins == rhs.shaderSMBuiltins );
+ }
+
+ bool operator!=( PhysicalDeviceShaderSMBuiltinsFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderSmBuiltinsFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSMBuiltins = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderSMBuiltinsFeaturesNV ) == sizeof( VkPhysicalDeviceShaderSMBuiltinsFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderSMBuiltinsFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderSMBuiltinsPropertiesNV
+ {
+ PhysicalDeviceShaderSMBuiltinsPropertiesNV( uint32_t shaderSMCount_ = {},
+ uint32_t shaderWarpsPerSM_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderSMCount( shaderSMCount_ )
+ , shaderWarpsPerSM( shaderWarpsPerSM_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSMBuiltinsPropertiesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSMBuiltinsPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSMBuiltinsPropertiesNV ) - offsetof( PhysicalDeviceShaderSMBuiltinsPropertiesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderSMBuiltinsPropertiesNV( VkPhysicalDeviceShaderSMBuiltinsPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderSMBuiltinsPropertiesNV& operator=( VkPhysicalDeviceShaderSMBuiltinsPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSMBuiltinsPropertiesNV const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderSMBuiltinsPropertiesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderSMBuiltinsPropertiesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderSMBuiltinsPropertiesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderSMBuiltinsPropertiesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderSMBuiltinsPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderSMCount == rhs.shaderSMCount )
+ && ( shaderWarpsPerSM == rhs.shaderWarpsPerSM );
+ }
+
+ bool operator!=( PhysicalDeviceShaderSMBuiltinsPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderSmBuiltinsPropertiesNV;
+ void* pNext = {};
+ uint32_t shaderSMCount = {};
+ uint32_t shaderWarpsPerSM = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderSMBuiltinsPropertiesNV ) == sizeof( VkPhysicalDeviceShaderSMBuiltinsPropertiesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderSMBuiltinsPropertiesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShaderSubgroupExtendedTypesFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderSubgroupExtendedTypesFeatures( VULKAN_HPP_NAMESPACE::Bool32 shaderSubgroupExtendedTypes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderSubgroupExtendedTypes( shaderSubgroupExtendedTypes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSubgroupExtendedTypesFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSubgroupExtendedTypesFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSubgroupExtendedTypesFeatures ) - offsetof( PhysicalDeviceShaderSubgroupExtendedTypesFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShaderSubgroupExtendedTypesFeatures( VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShaderSubgroupExtendedTypesFeatures& operator=( VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShaderSubgroupExtendedTypesFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceShaderSubgroupExtendedTypesFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceShaderSubgroupExtendedTypesFeatures & setShaderSubgroupExtendedTypes( VULKAN_HPP_NAMESPACE::Bool32 shaderSubgroupExtendedTypes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSubgroupExtendedTypes = shaderSubgroupExtendedTypes_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShaderSubgroupExtendedTypesFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shaderSubgroupExtendedTypes == rhs.shaderSubgroupExtendedTypes );
+ }
+
+ bool operator!=( PhysicalDeviceShaderSubgroupExtendedTypesFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShaderSubgroupExtendedTypesFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSubgroupExtendedTypes = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShaderSubgroupExtendedTypesFeatures ) == sizeof( VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShaderSubgroupExtendedTypesFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShadingRateImageFeaturesNV
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceShadingRateImageFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 shadingRateImage_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shadingRateCoarseSampleOrder_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shadingRateImage( shadingRateImage_ )
+ , shadingRateCoarseSampleOrder( shadingRateCoarseSampleOrder_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShadingRateImageFeaturesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShadingRateImageFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShadingRateImageFeaturesNV ) - offsetof( PhysicalDeviceShadingRateImageFeaturesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShadingRateImageFeaturesNV( VkPhysicalDeviceShadingRateImageFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShadingRateImageFeaturesNV& operator=( VkPhysicalDeviceShadingRateImageFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShadingRateImageFeaturesNV const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceShadingRateImageFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceShadingRateImageFeaturesNV & setShadingRateImage( VULKAN_HPP_NAMESPACE::Bool32 shadingRateImage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shadingRateImage = shadingRateImage_;
+ return *this;
+ }
+
+ PhysicalDeviceShadingRateImageFeaturesNV & setShadingRateCoarseSampleOrder( VULKAN_HPP_NAMESPACE::Bool32 shadingRateCoarseSampleOrder_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shadingRateCoarseSampleOrder = shadingRateCoarseSampleOrder_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShadingRateImageFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShadingRateImageFeaturesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceShadingRateImageFeaturesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShadingRateImageFeaturesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShadingRateImageFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shadingRateImage == rhs.shadingRateImage )
+ && ( shadingRateCoarseSampleOrder == rhs.shadingRateCoarseSampleOrder );
+ }
+
+ bool operator!=( PhysicalDeviceShadingRateImageFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShadingRateImageFeaturesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shadingRateImage = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shadingRateCoarseSampleOrder = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShadingRateImageFeaturesNV ) == sizeof( VkPhysicalDeviceShadingRateImageFeaturesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShadingRateImageFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceShadingRateImagePropertiesNV
+ {
+ PhysicalDeviceShadingRateImagePropertiesNV( VULKAN_HPP_NAMESPACE::Extent2D shadingRateTexelSize_ = {},
+ uint32_t shadingRatePaletteSize_ = {},
+ uint32_t shadingRateMaxCoarseSamples_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shadingRateTexelSize( shadingRateTexelSize_ )
+ , shadingRatePaletteSize( shadingRatePaletteSize_ )
+ , shadingRateMaxCoarseSamples( shadingRateMaxCoarseSamples_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceShadingRateImagePropertiesNV & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceShadingRateImagePropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceShadingRateImagePropertiesNV ) - offsetof( PhysicalDeviceShadingRateImagePropertiesNV, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceShadingRateImagePropertiesNV( VkPhysicalDeviceShadingRateImagePropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceShadingRateImagePropertiesNV& operator=( VkPhysicalDeviceShadingRateImagePropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceShadingRateImagePropertiesNV const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceShadingRateImagePropertiesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceShadingRateImagePropertiesNV*>( this );
+ }
+
+ operator VkPhysicalDeviceShadingRateImagePropertiesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceShadingRateImagePropertiesNV*>( this );
+ }
+
+ bool operator==( PhysicalDeviceShadingRateImagePropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shadingRateTexelSize == rhs.shadingRateTexelSize )
+ && ( shadingRatePaletteSize == rhs.shadingRatePaletteSize )
+ && ( shadingRateMaxCoarseSamples == rhs.shadingRateMaxCoarseSamples );
+ }
+
+ bool operator!=( PhysicalDeviceShadingRateImagePropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceShadingRateImagePropertiesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Extent2D shadingRateTexelSize = {};
+ uint32_t shadingRatePaletteSize = {};
+ uint32_t shadingRateMaxCoarseSamples = {};
+ };
+ static_assert( sizeof( PhysicalDeviceShadingRateImagePropertiesNV ) == sizeof( VkPhysicalDeviceShadingRateImagePropertiesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceShadingRateImagePropertiesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceSparseImageFormatInfo2
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceSparseImageFormatInfo2( VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::ImageType type_ = VULKAN_HPP_NAMESPACE::ImageType::e1D,
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples_ = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1,
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags usage_ = {},
+ VULKAN_HPP_NAMESPACE::ImageTiling tiling_ = VULKAN_HPP_NAMESPACE::ImageTiling::eOptimal ) VULKAN_HPP_NOEXCEPT
+ : format( format_ )
+ , type( type_ )
+ , samples( samples_ )
+ , usage( usage_ )
+ , tiling( tiling_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseImageFormatInfo2 & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseImageFormatInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseImageFormatInfo2 ) - offsetof( PhysicalDeviceSparseImageFormatInfo2, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceSparseImageFormatInfo2( VkPhysicalDeviceSparseImageFormatInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceSparseImageFormatInfo2& operator=( VkPhysicalDeviceSparseImageFormatInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseImageFormatInfo2 const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceSparseImageFormatInfo2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceSparseImageFormatInfo2 & setFormat( VULKAN_HPP_NAMESPACE::Format format_ ) VULKAN_HPP_NOEXCEPT
+ {
+ format = format_;
+ return *this;
+ }
+
+ PhysicalDeviceSparseImageFormatInfo2 & setType( VULKAN_HPP_NAMESPACE::ImageType type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ PhysicalDeviceSparseImageFormatInfo2 & setSamples( VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples_ ) VULKAN_HPP_NOEXCEPT
+ {
+ samples = samples_;
+ return *this;
+ }
+
+ PhysicalDeviceSparseImageFormatInfo2 & setUsage( VULKAN_HPP_NAMESPACE::ImageUsageFlags usage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ usage = usage_;
+ return *this;
+ }
+
+ PhysicalDeviceSparseImageFormatInfo2 & setTiling( VULKAN_HPP_NAMESPACE::ImageTiling tiling_ ) VULKAN_HPP_NOEXCEPT
+ {
+ tiling = tiling_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceSparseImageFormatInfo2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( this );
+ }
+
+ operator VkPhysicalDeviceSparseImageFormatInfo2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceSparseImageFormatInfo2*>( this );
+ }
+
+ bool operator==( PhysicalDeviceSparseImageFormatInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( format == rhs.format )
+ && ( type == rhs.type )
+ && ( samples == rhs.samples )
+ && ( usage == rhs.usage )
+ && ( tiling == rhs.tiling );
+ }
+
+ bool operator!=( PhysicalDeviceSparseImageFormatInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceSparseImageFormatInfo2;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::ImageType type = VULKAN_HPP_NAMESPACE::ImageType::e1D;
+ VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples = VULKAN_HPP_NAMESPACE::SampleCountFlagBits::e1;
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags usage = {};
+ VULKAN_HPP_NAMESPACE::ImageTiling tiling = VULKAN_HPP_NAMESPACE::ImageTiling::eOptimal;
+ };
+ static_assert( sizeof( PhysicalDeviceSparseImageFormatInfo2 ) == sizeof( VkPhysicalDeviceSparseImageFormatInfo2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceSparseImageFormatInfo2>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceSubgroupProperties
+ {
+ PhysicalDeviceSubgroupProperties( uint32_t subgroupSize_ = {},
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags supportedStages_ = {},
+ VULKAN_HPP_NAMESPACE::SubgroupFeatureFlags supportedOperations_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 quadOperationsInAllStages_ = {} ) VULKAN_HPP_NOEXCEPT
+ : subgroupSize( subgroupSize_ )
+ , supportedStages( supportedStages_ )
+ , supportedOperations( supportedOperations_ )
+ , quadOperationsInAllStages( quadOperationsInAllStages_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupProperties ) - offsetof( PhysicalDeviceSubgroupProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceSubgroupProperties( VkPhysicalDeviceSubgroupProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceSubgroupProperties& operator=( VkPhysicalDeviceSubgroupProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceSubgroupProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceSubgroupProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceSubgroupProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceSubgroupProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceSubgroupProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( subgroupSize == rhs.subgroupSize )
+ && ( supportedStages == rhs.supportedStages )
+ && ( supportedOperations == rhs.supportedOperations )
+ && ( quadOperationsInAllStages == rhs.quadOperationsInAllStages );
+ }
+
+ bool operator!=( PhysicalDeviceSubgroupProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceSubgroupProperties;
+ void* pNext = {};
+ uint32_t subgroupSize = {};
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags supportedStages = {};
+ VULKAN_HPP_NAMESPACE::SubgroupFeatureFlags supportedOperations = {};
+ VULKAN_HPP_NAMESPACE::Bool32 quadOperationsInAllStages = {};
+ };
+ static_assert( sizeof( PhysicalDeviceSubgroupProperties ) == sizeof( VkPhysicalDeviceSubgroupProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceSubgroupProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceSubgroupSizeControlFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceSubgroupSizeControlFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 subgroupSizeControl_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 computeFullSubgroups_ = {} ) VULKAN_HPP_NOEXCEPT
+ : subgroupSizeControl( subgroupSizeControl_ )
+ , computeFullSubgroups( computeFullSubgroups_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupSizeControlFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupSizeControlFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupSizeControlFeaturesEXT ) - offsetof( PhysicalDeviceSubgroupSizeControlFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceSubgroupSizeControlFeaturesEXT( VkPhysicalDeviceSubgroupSizeControlFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceSubgroupSizeControlFeaturesEXT& operator=( VkPhysicalDeviceSubgroupSizeControlFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupSizeControlFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceSubgroupSizeControlFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceSubgroupSizeControlFeaturesEXT & setSubgroupSizeControl( VULKAN_HPP_NAMESPACE::Bool32 subgroupSizeControl_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subgroupSizeControl = subgroupSizeControl_;
+ return *this;
+ }
+
+ PhysicalDeviceSubgroupSizeControlFeaturesEXT & setComputeFullSubgroups( VULKAN_HPP_NAMESPACE::Bool32 computeFullSubgroups_ ) VULKAN_HPP_NOEXCEPT
+ {
+ computeFullSubgroups = computeFullSubgroups_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceSubgroupSizeControlFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceSubgroupSizeControlFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceSubgroupSizeControlFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceSubgroupSizeControlFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( subgroupSizeControl == rhs.subgroupSizeControl )
+ && ( computeFullSubgroups == rhs.computeFullSubgroups );
+ }
+
+ bool operator!=( PhysicalDeviceSubgroupSizeControlFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceSubgroupSizeControlFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 subgroupSizeControl = {};
+ VULKAN_HPP_NAMESPACE::Bool32 computeFullSubgroups = {};
+ };
+ static_assert( sizeof( PhysicalDeviceSubgroupSizeControlFeaturesEXT ) == sizeof( VkPhysicalDeviceSubgroupSizeControlFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceSubgroupSizeControlFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceSubgroupSizeControlPropertiesEXT
+ {
+ PhysicalDeviceSubgroupSizeControlPropertiesEXT( uint32_t minSubgroupSize_ = {},
+ uint32_t maxSubgroupSize_ = {},
+ uint32_t maxComputeWorkgroupSubgroups_ = {},
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags requiredSubgroupSizeStages_ = {} ) VULKAN_HPP_NOEXCEPT
+ : minSubgroupSize( minSubgroupSize_ )
+ , maxSubgroupSize( maxSubgroupSize_ )
+ , maxComputeWorkgroupSubgroups( maxComputeWorkgroupSubgroups_ )
+ , requiredSubgroupSizeStages( requiredSubgroupSizeStages_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupSizeControlPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupSizeControlPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupSizeControlPropertiesEXT ) - offsetof( PhysicalDeviceSubgroupSizeControlPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceSubgroupSizeControlPropertiesEXT( VkPhysicalDeviceSubgroupSizeControlPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceSubgroupSizeControlPropertiesEXT& operator=( VkPhysicalDeviceSubgroupSizeControlPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceSubgroupSizeControlPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceSubgroupSizeControlPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceSubgroupSizeControlPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceSubgroupSizeControlPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceSubgroupSizeControlPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( minSubgroupSize == rhs.minSubgroupSize )
+ && ( maxSubgroupSize == rhs.maxSubgroupSize )
+ && ( maxComputeWorkgroupSubgroups == rhs.maxComputeWorkgroupSubgroups )
+ && ( requiredSubgroupSizeStages == rhs.requiredSubgroupSizeStages );
+ }
+
+ bool operator!=( PhysicalDeviceSubgroupSizeControlPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceSubgroupSizeControlPropertiesEXT;
+ void* pNext = {};
+ uint32_t minSubgroupSize = {};
+ uint32_t maxSubgroupSize = {};
+ uint32_t maxComputeWorkgroupSubgroups = {};
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags requiredSubgroupSizeStages = {};
+ };
+ static_assert( sizeof( PhysicalDeviceSubgroupSizeControlPropertiesEXT ) == sizeof( VkPhysicalDeviceSubgroupSizeControlPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceSubgroupSizeControlPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceSurfaceInfo2KHR
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceSurfaceInfo2KHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface_ = {} ) VULKAN_HPP_NOEXCEPT
+ : surface( surface_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR ) - offsetof( PhysicalDeviceSurfaceInfo2KHR, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceSurfaceInfo2KHR( VkPhysicalDeviceSurfaceInfo2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceSurfaceInfo2KHR& operator=( VkPhysicalDeviceSurfaceInfo2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceSurfaceInfo2KHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceSurfaceInfo2KHR & setSurface( VULKAN_HPP_NAMESPACE::SurfaceKHR surface_ ) VULKAN_HPP_NOEXCEPT
+ {
+ surface = surface_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceSurfaceInfo2KHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( this );
+ }
+
+ operator VkPhysicalDeviceSurfaceInfo2KHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceSurfaceInfo2KHR*>( this );
+ }
+
+ bool operator==( PhysicalDeviceSurfaceInfo2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( surface == rhs.surface );
+ }
+
+ bool operator!=( PhysicalDeviceSurfaceInfo2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceSurfaceInfo2KHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface = {};
+ };
+ static_assert( sizeof( PhysicalDeviceSurfaceInfo2KHR ) == sizeof( VkPhysicalDeviceSurfaceInfo2KHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceSurfaceInfo2KHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceTexelBufferAlignmentFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceTexelBufferAlignmentFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 texelBufferAlignment_ = {} ) VULKAN_HPP_NOEXCEPT
+ : texelBufferAlignment( texelBufferAlignment_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceTexelBufferAlignmentFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceTexelBufferAlignmentFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceTexelBufferAlignmentFeaturesEXT ) - offsetof( PhysicalDeviceTexelBufferAlignmentFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceTexelBufferAlignmentFeaturesEXT( VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceTexelBufferAlignmentFeaturesEXT& operator=( VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceTexelBufferAlignmentFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceTexelBufferAlignmentFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceTexelBufferAlignmentFeaturesEXT & setTexelBufferAlignment( VULKAN_HPP_NAMESPACE::Bool32 texelBufferAlignment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ texelBufferAlignment = texelBufferAlignment_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceTexelBufferAlignmentFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( texelBufferAlignment == rhs.texelBufferAlignment );
+ }
+
+ bool operator!=( PhysicalDeviceTexelBufferAlignmentFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceTexelBufferAlignmentFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 texelBufferAlignment = {};
+ };
+ static_assert( sizeof( PhysicalDeviceTexelBufferAlignmentFeaturesEXT ) == sizeof( VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceTexelBufferAlignmentFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceTexelBufferAlignmentPropertiesEXT
+ {
+ PhysicalDeviceTexelBufferAlignmentPropertiesEXT( VULKAN_HPP_NAMESPACE::DeviceSize storageTexelBufferOffsetAlignmentBytes_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 storageTexelBufferOffsetSingleTexelAlignment_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize uniformTexelBufferOffsetAlignmentBytes_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 uniformTexelBufferOffsetSingleTexelAlignment_ = {} ) VULKAN_HPP_NOEXCEPT
+ : storageTexelBufferOffsetAlignmentBytes( storageTexelBufferOffsetAlignmentBytes_ )
+ , storageTexelBufferOffsetSingleTexelAlignment( storageTexelBufferOffsetSingleTexelAlignment_ )
+ , uniformTexelBufferOffsetAlignmentBytes( uniformTexelBufferOffsetAlignmentBytes_ )
+ , uniformTexelBufferOffsetSingleTexelAlignment( uniformTexelBufferOffsetSingleTexelAlignment_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceTexelBufferAlignmentPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceTexelBufferAlignmentPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceTexelBufferAlignmentPropertiesEXT ) - offsetof( PhysicalDeviceTexelBufferAlignmentPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceTexelBufferAlignmentPropertiesEXT( VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceTexelBufferAlignmentPropertiesEXT& operator=( VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceTexelBufferAlignmentPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceTexelBufferAlignmentPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( storageTexelBufferOffsetAlignmentBytes == rhs.storageTexelBufferOffsetAlignmentBytes )
+ && ( storageTexelBufferOffsetSingleTexelAlignment == rhs.storageTexelBufferOffsetSingleTexelAlignment )
+ && ( uniformTexelBufferOffsetAlignmentBytes == rhs.uniformTexelBufferOffsetAlignmentBytes )
+ && ( uniformTexelBufferOffsetSingleTexelAlignment == rhs.uniformTexelBufferOffsetSingleTexelAlignment );
+ }
+
+ bool operator!=( PhysicalDeviceTexelBufferAlignmentPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceTexelBufferAlignmentPropertiesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize storageTexelBufferOffsetAlignmentBytes = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storageTexelBufferOffsetSingleTexelAlignment = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize uniformTexelBufferOffsetAlignmentBytes = {};
+ VULKAN_HPP_NAMESPACE::Bool32 uniformTexelBufferOffsetSingleTexelAlignment = {};
+ };
+ static_assert( sizeof( PhysicalDeviceTexelBufferAlignmentPropertiesEXT ) == sizeof( VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceTexelBufferAlignmentPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 textureCompressionASTC_HDR_ = {} ) VULKAN_HPP_NOEXCEPT
+ : textureCompressionASTC_HDR( textureCompressionASTC_HDR_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT ) - offsetof( PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT( VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT& operator=( VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT & setTextureCompressionASTC_HDR( VULKAN_HPP_NAMESPACE::Bool32 textureCompressionASTC_HDR_ ) VULKAN_HPP_NOEXCEPT
+ {
+ textureCompressionASTC_HDR = textureCompressionASTC_HDR_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( textureCompressionASTC_HDR == rhs.textureCompressionASTC_HDR );
+ }
+
+ bool operator!=( PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceTextureCompressionAstcHdrFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 textureCompressionASTC_HDR = {};
+ };
+ static_assert( sizeof( PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT ) == sizeof( VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceTimelineSemaphoreFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceTimelineSemaphoreFeatures( VULKAN_HPP_NAMESPACE::Bool32 timelineSemaphore_ = {} ) VULKAN_HPP_NOEXCEPT
+ : timelineSemaphore( timelineSemaphore_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceTimelineSemaphoreFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceTimelineSemaphoreFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceTimelineSemaphoreFeatures ) - offsetof( PhysicalDeviceTimelineSemaphoreFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceTimelineSemaphoreFeatures( VkPhysicalDeviceTimelineSemaphoreFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceTimelineSemaphoreFeatures& operator=( VkPhysicalDeviceTimelineSemaphoreFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceTimelineSemaphoreFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceTimelineSemaphoreFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceTimelineSemaphoreFeatures & setTimelineSemaphore( VULKAN_HPP_NAMESPACE::Bool32 timelineSemaphore_ ) VULKAN_HPP_NOEXCEPT
+ {
+ timelineSemaphore = timelineSemaphore_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceTimelineSemaphoreFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceTimelineSemaphoreFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceTimelineSemaphoreFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceTimelineSemaphoreFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceTimelineSemaphoreFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( timelineSemaphore == rhs.timelineSemaphore );
+ }
+
+ bool operator!=( PhysicalDeviceTimelineSemaphoreFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceTimelineSemaphoreFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 timelineSemaphore = {};
+ };
+ static_assert( sizeof( PhysicalDeviceTimelineSemaphoreFeatures ) == sizeof( VkPhysicalDeviceTimelineSemaphoreFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceTimelineSemaphoreFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceTimelineSemaphoreProperties
+ {
+ PhysicalDeviceTimelineSemaphoreProperties( uint64_t maxTimelineSemaphoreValueDifference_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxTimelineSemaphoreValueDifference( maxTimelineSemaphoreValueDifference_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceTimelineSemaphoreProperties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceTimelineSemaphoreProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceTimelineSemaphoreProperties ) - offsetof( PhysicalDeviceTimelineSemaphoreProperties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceTimelineSemaphoreProperties( VkPhysicalDeviceTimelineSemaphoreProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceTimelineSemaphoreProperties& operator=( VkPhysicalDeviceTimelineSemaphoreProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceTimelineSemaphoreProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceTimelineSemaphoreProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceTimelineSemaphoreProperties*>( this );
+ }
+
+ operator VkPhysicalDeviceTimelineSemaphoreProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceTimelineSemaphoreProperties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceTimelineSemaphoreProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxTimelineSemaphoreValueDifference == rhs.maxTimelineSemaphoreValueDifference );
+ }
+
+ bool operator!=( PhysicalDeviceTimelineSemaphoreProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceTimelineSemaphoreProperties;
+ void* pNext = {};
+ uint64_t maxTimelineSemaphoreValueDifference = {};
+ };
+ static_assert( sizeof( PhysicalDeviceTimelineSemaphoreProperties ) == sizeof( VkPhysicalDeviceTimelineSemaphoreProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceTimelineSemaphoreProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceToolPropertiesEXT
+ {
+ PhysicalDeviceToolPropertiesEXT( std::array<char,VK_MAX_EXTENSION_NAME_SIZE> const& name_ = {},
+ std::array<char,VK_MAX_EXTENSION_NAME_SIZE> const& version_ = {},
+ VULKAN_HPP_NAMESPACE::ToolPurposeFlagsEXT purposes_ = {},
+ std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {},
+ std::array<char,VK_MAX_EXTENSION_NAME_SIZE> const& layer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : name{}
+ , version{}
+ , purposes( purposes_ )
+ , description{}
+ , layer{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE,VK_MAX_EXTENSION_NAME_SIZE>::copy( name, name_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE,VK_MAX_EXTENSION_NAME_SIZE>::copy( version, version_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE,VK_MAX_EXTENSION_NAME_SIZE>::copy( layer, layer_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceToolPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceToolPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceToolPropertiesEXT ) - offsetof( PhysicalDeviceToolPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceToolPropertiesEXT( VkPhysicalDeviceToolPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceToolPropertiesEXT& operator=( VkPhysicalDeviceToolPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceToolPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceToolPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceToolPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceToolPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceToolPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceToolPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memcmp( name, rhs.name, VK_MAX_EXTENSION_NAME_SIZE * sizeof( char ) ) == 0 )
+ && ( memcmp( version, rhs.version, VK_MAX_EXTENSION_NAME_SIZE * sizeof( char ) ) == 0 )
+ && ( purposes == rhs.purposes )
+ && ( memcmp( description, rhs.description, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
+ && ( memcmp( layer, rhs.layer, VK_MAX_EXTENSION_NAME_SIZE * sizeof( char ) ) == 0 );
+ }
+
+ bool operator!=( PhysicalDeviceToolPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceToolPropertiesEXT;
+ void* pNext = {};
+ char name[VK_MAX_EXTENSION_NAME_SIZE] = {};
+ char version[VK_MAX_EXTENSION_NAME_SIZE] = {};
+ VULKAN_HPP_NAMESPACE::ToolPurposeFlagsEXT purposes = {};
+ char description[VK_MAX_DESCRIPTION_SIZE] = {};
+ char layer[VK_MAX_EXTENSION_NAME_SIZE] = {};
+ };
+ static_assert( sizeof( PhysicalDeviceToolPropertiesEXT ) == sizeof( VkPhysicalDeviceToolPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceToolPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceTransformFeedbackFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceTransformFeedbackFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 transformFeedback_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 geometryStreams_ = {} ) VULKAN_HPP_NOEXCEPT
+ : transformFeedback( transformFeedback_ )
+ , geometryStreams( geometryStreams_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceTransformFeedbackFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceTransformFeedbackFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceTransformFeedbackFeaturesEXT ) - offsetof( PhysicalDeviceTransformFeedbackFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceTransformFeedbackFeaturesEXT( VkPhysicalDeviceTransformFeedbackFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceTransformFeedbackFeaturesEXT& operator=( VkPhysicalDeviceTransformFeedbackFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceTransformFeedbackFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceTransformFeedbackFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceTransformFeedbackFeaturesEXT & setTransformFeedback( VULKAN_HPP_NAMESPACE::Bool32 transformFeedback_ ) VULKAN_HPP_NOEXCEPT
+ {
+ transformFeedback = transformFeedback_;
+ return *this;
+ }
+
+ PhysicalDeviceTransformFeedbackFeaturesEXT & setGeometryStreams( VULKAN_HPP_NAMESPACE::Bool32 geometryStreams_ ) VULKAN_HPP_NOEXCEPT
+ {
+ geometryStreams = geometryStreams_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceTransformFeedbackFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceTransformFeedbackFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceTransformFeedbackFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceTransformFeedbackFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceTransformFeedbackFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( transformFeedback == rhs.transformFeedback )
+ && ( geometryStreams == rhs.geometryStreams );
+ }
+
+ bool operator!=( PhysicalDeviceTransformFeedbackFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceTransformFeedbackFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 transformFeedback = {};
+ VULKAN_HPP_NAMESPACE::Bool32 geometryStreams = {};
+ };
+ static_assert( sizeof( PhysicalDeviceTransformFeedbackFeaturesEXT ) == sizeof( VkPhysicalDeviceTransformFeedbackFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceTransformFeedbackFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceTransformFeedbackPropertiesEXT
+ {
+ PhysicalDeviceTransformFeedbackPropertiesEXT( uint32_t maxTransformFeedbackStreams_ = {},
+ uint32_t maxTransformFeedbackBuffers_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize maxTransformFeedbackBufferSize_ = {},
+ uint32_t maxTransformFeedbackStreamDataSize_ = {},
+ uint32_t maxTransformFeedbackBufferDataSize_ = {},
+ uint32_t maxTransformFeedbackBufferDataStride_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 transformFeedbackQueries_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 transformFeedbackStreamsLinesTriangles_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 transformFeedbackRasterizationStreamSelect_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 transformFeedbackDraw_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxTransformFeedbackStreams( maxTransformFeedbackStreams_ )
+ , maxTransformFeedbackBuffers( maxTransformFeedbackBuffers_ )
+ , maxTransformFeedbackBufferSize( maxTransformFeedbackBufferSize_ )
+ , maxTransformFeedbackStreamDataSize( maxTransformFeedbackStreamDataSize_ )
+ , maxTransformFeedbackBufferDataSize( maxTransformFeedbackBufferDataSize_ )
+ , maxTransformFeedbackBufferDataStride( maxTransformFeedbackBufferDataStride_ )
+ , transformFeedbackQueries( transformFeedbackQueries_ )
+ , transformFeedbackStreamsLinesTriangles( transformFeedbackStreamsLinesTriangles_ )
+ , transformFeedbackRasterizationStreamSelect( transformFeedbackRasterizationStreamSelect_ )
+ , transformFeedbackDraw( transformFeedbackDraw_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceTransformFeedbackPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceTransformFeedbackPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceTransformFeedbackPropertiesEXT ) - offsetof( PhysicalDeviceTransformFeedbackPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceTransformFeedbackPropertiesEXT( VkPhysicalDeviceTransformFeedbackPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceTransformFeedbackPropertiesEXT& operator=( VkPhysicalDeviceTransformFeedbackPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceTransformFeedbackPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceTransformFeedbackPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceTransformFeedbackPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceTransformFeedbackPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceTransformFeedbackPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceTransformFeedbackPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxTransformFeedbackStreams == rhs.maxTransformFeedbackStreams )
+ && ( maxTransformFeedbackBuffers == rhs.maxTransformFeedbackBuffers )
+ && ( maxTransformFeedbackBufferSize == rhs.maxTransformFeedbackBufferSize )
+ && ( maxTransformFeedbackStreamDataSize == rhs.maxTransformFeedbackStreamDataSize )
+ && ( maxTransformFeedbackBufferDataSize == rhs.maxTransformFeedbackBufferDataSize )
+ && ( maxTransformFeedbackBufferDataStride == rhs.maxTransformFeedbackBufferDataStride )
+ && ( transformFeedbackQueries == rhs.transformFeedbackQueries )
+ && ( transformFeedbackStreamsLinesTriangles == rhs.transformFeedbackStreamsLinesTriangles )
+ && ( transformFeedbackRasterizationStreamSelect == rhs.transformFeedbackRasterizationStreamSelect )
+ && ( transformFeedbackDraw == rhs.transformFeedbackDraw );
+ }
+
+ bool operator!=( PhysicalDeviceTransformFeedbackPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceTransformFeedbackPropertiesEXT;
+ void* pNext = {};
+ uint32_t maxTransformFeedbackStreams = {};
+ uint32_t maxTransformFeedbackBuffers = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize maxTransformFeedbackBufferSize = {};
+ uint32_t maxTransformFeedbackStreamDataSize = {};
+ uint32_t maxTransformFeedbackBufferDataSize = {};
+ uint32_t maxTransformFeedbackBufferDataStride = {};
+ VULKAN_HPP_NAMESPACE::Bool32 transformFeedbackQueries = {};
+ VULKAN_HPP_NAMESPACE::Bool32 transformFeedbackStreamsLinesTriangles = {};
+ VULKAN_HPP_NAMESPACE::Bool32 transformFeedbackRasterizationStreamSelect = {};
+ VULKAN_HPP_NAMESPACE::Bool32 transformFeedbackDraw = {};
+ };
+ static_assert( sizeof( PhysicalDeviceTransformFeedbackPropertiesEXT ) == sizeof( VkPhysicalDeviceTransformFeedbackPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceTransformFeedbackPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceUniformBufferStandardLayoutFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceUniformBufferStandardLayoutFeatures( VULKAN_HPP_NAMESPACE::Bool32 uniformBufferStandardLayout_ = {} ) VULKAN_HPP_NOEXCEPT
+ : uniformBufferStandardLayout( uniformBufferStandardLayout_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceUniformBufferStandardLayoutFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceUniformBufferStandardLayoutFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceUniformBufferStandardLayoutFeatures ) - offsetof( PhysicalDeviceUniformBufferStandardLayoutFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceUniformBufferStandardLayoutFeatures( VkPhysicalDeviceUniformBufferStandardLayoutFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceUniformBufferStandardLayoutFeatures& operator=( VkPhysicalDeviceUniformBufferStandardLayoutFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceUniformBufferStandardLayoutFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceUniformBufferStandardLayoutFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceUniformBufferStandardLayoutFeatures & setUniformBufferStandardLayout( VULKAN_HPP_NAMESPACE::Bool32 uniformBufferStandardLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ uniformBufferStandardLayout = uniformBufferStandardLayout_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceUniformBufferStandardLayoutFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceUniformBufferStandardLayoutFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceUniformBufferStandardLayoutFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceUniformBufferStandardLayoutFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceUniformBufferStandardLayoutFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( uniformBufferStandardLayout == rhs.uniformBufferStandardLayout );
+ }
+
+ bool operator!=( PhysicalDeviceUniformBufferStandardLayoutFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceUniformBufferStandardLayoutFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 uniformBufferStandardLayout = {};
+ };
+ static_assert( sizeof( PhysicalDeviceUniformBufferStandardLayoutFeatures ) == sizeof( VkPhysicalDeviceUniformBufferStandardLayoutFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceUniformBufferStandardLayoutFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceVariablePointersFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceVariablePointersFeatures( VULKAN_HPP_NAMESPACE::Bool32 variablePointersStorageBuffer_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 variablePointers_ = {} ) VULKAN_HPP_NOEXCEPT
+ : variablePointersStorageBuffer( variablePointersStorageBuffer_ )
+ , variablePointers( variablePointers_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceVariablePointersFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceVariablePointersFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceVariablePointersFeatures ) - offsetof( PhysicalDeviceVariablePointersFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceVariablePointersFeatures( VkPhysicalDeviceVariablePointersFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceVariablePointersFeatures& operator=( VkPhysicalDeviceVariablePointersFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceVariablePointersFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceVariablePointersFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceVariablePointersFeatures & setVariablePointersStorageBuffer( VULKAN_HPP_NAMESPACE::Bool32 variablePointersStorageBuffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ variablePointersStorageBuffer = variablePointersStorageBuffer_;
+ return *this;
+ }
+
+ PhysicalDeviceVariablePointersFeatures & setVariablePointers( VULKAN_HPP_NAMESPACE::Bool32 variablePointers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ variablePointers = variablePointers_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceVariablePointersFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceVariablePointersFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceVariablePointersFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceVariablePointersFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceVariablePointersFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( variablePointersStorageBuffer == rhs.variablePointersStorageBuffer )
+ && ( variablePointers == rhs.variablePointers );
+ }
+
+ bool operator!=( PhysicalDeviceVariablePointersFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceVariablePointersFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 variablePointersStorageBuffer = {};
+ VULKAN_HPP_NAMESPACE::Bool32 variablePointers = {};
+ };
+ static_assert( sizeof( PhysicalDeviceVariablePointersFeatures ) == sizeof( VkPhysicalDeviceVariablePointersFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceVariablePointersFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceVertexAttributeDivisorFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceVertexAttributeDivisorFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 vertexAttributeInstanceRateDivisor_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 vertexAttributeInstanceRateZeroDivisor_ = {} ) VULKAN_HPP_NOEXCEPT
+ : vertexAttributeInstanceRateDivisor( vertexAttributeInstanceRateDivisor_ )
+ , vertexAttributeInstanceRateZeroDivisor( vertexAttributeInstanceRateZeroDivisor_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceVertexAttributeDivisorFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceVertexAttributeDivisorFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceVertexAttributeDivisorFeaturesEXT ) - offsetof( PhysicalDeviceVertexAttributeDivisorFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceVertexAttributeDivisorFeaturesEXT( VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceVertexAttributeDivisorFeaturesEXT& operator=( VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceVertexAttributeDivisorFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceVertexAttributeDivisorFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceVertexAttributeDivisorFeaturesEXT & setVertexAttributeInstanceRateDivisor( VULKAN_HPP_NAMESPACE::Bool32 vertexAttributeInstanceRateDivisor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexAttributeInstanceRateDivisor = vertexAttributeInstanceRateDivisor_;
+ return *this;
+ }
+
+ PhysicalDeviceVertexAttributeDivisorFeaturesEXT & setVertexAttributeInstanceRateZeroDivisor( VULKAN_HPP_NAMESPACE::Bool32 vertexAttributeInstanceRateZeroDivisor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexAttributeInstanceRateZeroDivisor = vertexAttributeInstanceRateZeroDivisor_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceVertexAttributeDivisorFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( vertexAttributeInstanceRateDivisor == rhs.vertexAttributeInstanceRateDivisor )
+ && ( vertexAttributeInstanceRateZeroDivisor == rhs.vertexAttributeInstanceRateZeroDivisor );
+ }
+
+ bool operator!=( PhysicalDeviceVertexAttributeDivisorFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceVertexAttributeDivisorFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 vertexAttributeInstanceRateDivisor = {};
+ VULKAN_HPP_NAMESPACE::Bool32 vertexAttributeInstanceRateZeroDivisor = {};
+ };
+ static_assert( sizeof( PhysicalDeviceVertexAttributeDivisorFeaturesEXT ) == sizeof( VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceVertexAttributeDivisorFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceVertexAttributeDivisorPropertiesEXT
+ {
+ PhysicalDeviceVertexAttributeDivisorPropertiesEXT( uint32_t maxVertexAttribDivisor_ = {} ) VULKAN_HPP_NOEXCEPT
+ : maxVertexAttribDivisor( maxVertexAttribDivisor_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceVertexAttributeDivisorPropertiesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceVertexAttributeDivisorPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceVertexAttributeDivisorPropertiesEXT ) - offsetof( PhysicalDeviceVertexAttributeDivisorPropertiesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceVertexAttributeDivisorPropertiesEXT( VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceVertexAttributeDivisorPropertiesEXT& operator=( VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceVertexAttributeDivisorPropertiesEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceVertexAttributeDivisorPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( maxVertexAttribDivisor == rhs.maxVertexAttribDivisor );
+ }
+
+ bool operator!=( PhysicalDeviceVertexAttributeDivisorPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceVertexAttributeDivisorPropertiesEXT;
+ void* pNext = {};
+ uint32_t maxVertexAttribDivisor = {};
+ };
+ static_assert( sizeof( PhysicalDeviceVertexAttributeDivisorPropertiesEXT ) == sizeof( VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceVertexAttributeDivisorPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceVulkan11Features
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceVulkan11Features( VULKAN_HPP_NAMESPACE::Bool32 storageBuffer16BitAccess_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer16BitAccess_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 storageInputOutput16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 multiview_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 multiviewGeometryShader_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 multiviewTessellationShader_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 variablePointersStorageBuffer_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 variablePointers_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 protectedMemory_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 samplerYcbcrConversion_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDrawParameters_ = {} ) VULKAN_HPP_NOEXCEPT
+ : storageBuffer16BitAccess( storageBuffer16BitAccess_ )
+ , uniformAndStorageBuffer16BitAccess( uniformAndStorageBuffer16BitAccess_ )
+ , storagePushConstant16( storagePushConstant16_ )
+ , storageInputOutput16( storageInputOutput16_ )
+ , multiview( multiview_ )
+ , multiviewGeometryShader( multiviewGeometryShader_ )
+ , multiviewTessellationShader( multiviewTessellationShader_ )
+ , variablePointersStorageBuffer( variablePointersStorageBuffer_ )
+ , variablePointers( variablePointers_ )
+ , protectedMemory( protectedMemory_ )
+ , samplerYcbcrConversion( samplerYcbcrConversion_ )
+ , shaderDrawParameters( shaderDrawParameters_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan11Features & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan11Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan11Features ) - offsetof( PhysicalDeviceVulkan11Features, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features( VkPhysicalDeviceVulkan11Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceVulkan11Features& operator=( VkPhysicalDeviceVulkan11Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan11Features const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setStorageBuffer16BitAccess( VULKAN_HPP_NAMESPACE::Bool32 storageBuffer16BitAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storageBuffer16BitAccess = storageBuffer16BitAccess_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setUniformAndStorageBuffer16BitAccess( VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer16BitAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ uniformAndStorageBuffer16BitAccess = uniformAndStorageBuffer16BitAccess_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setStoragePushConstant16( VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storagePushConstant16 = storagePushConstant16_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setStorageInputOutput16( VULKAN_HPP_NAMESPACE::Bool32 storageInputOutput16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storageInputOutput16 = storageInputOutput16_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setMultiview( VULKAN_HPP_NAMESPACE::Bool32 multiview_ ) VULKAN_HPP_NOEXCEPT
+ {
+ multiview = multiview_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setMultiviewGeometryShader( VULKAN_HPP_NAMESPACE::Bool32 multiviewGeometryShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ multiviewGeometryShader = multiviewGeometryShader_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setMultiviewTessellationShader( VULKAN_HPP_NAMESPACE::Bool32 multiviewTessellationShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ multiviewTessellationShader = multiviewTessellationShader_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setVariablePointersStorageBuffer( VULKAN_HPP_NAMESPACE::Bool32 variablePointersStorageBuffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ variablePointersStorageBuffer = variablePointersStorageBuffer_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setVariablePointers( VULKAN_HPP_NAMESPACE::Bool32 variablePointers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ variablePointers = variablePointers_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setProtectedMemory( VULKAN_HPP_NAMESPACE::Bool32 protectedMemory_ ) VULKAN_HPP_NOEXCEPT
+ {
+ protectedMemory = protectedMemory_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setSamplerYcbcrConversion( VULKAN_HPP_NAMESPACE::Bool32 samplerYcbcrConversion_ ) VULKAN_HPP_NOEXCEPT
+ {
+ samplerYcbcrConversion = samplerYcbcrConversion_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Features & setShaderDrawParameters( VULKAN_HPP_NAMESPACE::Bool32 shaderDrawParameters_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderDrawParameters = shaderDrawParameters_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceVulkan11Features const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceVulkan11Features*>( this );
+ }
+
+ operator VkPhysicalDeviceVulkan11Features &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceVulkan11Features*>( this );
+ }
+
+ bool operator==( PhysicalDeviceVulkan11Features const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( storageBuffer16BitAccess == rhs.storageBuffer16BitAccess )
+ && ( uniformAndStorageBuffer16BitAccess == rhs.uniformAndStorageBuffer16BitAccess )
+ && ( storagePushConstant16 == rhs.storagePushConstant16 )
+ && ( storageInputOutput16 == rhs.storageInputOutput16 )
+ && ( multiview == rhs.multiview )
+ && ( multiviewGeometryShader == rhs.multiviewGeometryShader )
+ && ( multiviewTessellationShader == rhs.multiviewTessellationShader )
+ && ( variablePointersStorageBuffer == rhs.variablePointersStorageBuffer )
+ && ( variablePointers == rhs.variablePointers )
+ && ( protectedMemory == rhs.protectedMemory )
+ && ( samplerYcbcrConversion == rhs.samplerYcbcrConversion )
+ && ( shaderDrawParameters == rhs.shaderDrawParameters );
+ }
+
+ bool operator!=( PhysicalDeviceVulkan11Features const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceVulkan11Features;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storageBuffer16BitAccess = {};
+ VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer16BitAccess = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storageInputOutput16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 multiview = {};
+ VULKAN_HPP_NAMESPACE::Bool32 multiviewGeometryShader = {};
+ VULKAN_HPP_NAMESPACE::Bool32 multiviewTessellationShader = {};
+ VULKAN_HPP_NAMESPACE::Bool32 variablePointersStorageBuffer = {};
+ VULKAN_HPP_NAMESPACE::Bool32 variablePointers = {};
+ VULKAN_HPP_NAMESPACE::Bool32 protectedMemory = {};
+ VULKAN_HPP_NAMESPACE::Bool32 samplerYcbcrConversion = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDrawParameters = {};
+ };
+ static_assert( sizeof( PhysicalDeviceVulkan11Features ) == sizeof( VkPhysicalDeviceVulkan11Features ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceVulkan11Features>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceVulkan11Properties
+ {
+ VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceVulkan11Properties( std::array<uint8_t,VK_UUID_SIZE> const& deviceUUID_ = {},
+ std::array<uint8_t,VK_UUID_SIZE> const& driverUUID_ = {},
+ std::array<uint8_t,VK_LUID_SIZE> const& deviceLUID_ = {},
+ uint32_t deviceNodeMask_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 deviceLUIDValid_ = {},
+ uint32_t subgroupSize_ = {},
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags subgroupSupportedStages_ = {},
+ VULKAN_HPP_NAMESPACE::SubgroupFeatureFlags subgroupSupportedOperations_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 subgroupQuadOperationsInAllStages_ = {},
+ VULKAN_HPP_NAMESPACE::PointClippingBehavior pointClippingBehavior_ = VULKAN_HPP_NAMESPACE::PointClippingBehavior::eAllClipPlanes,
+ uint32_t maxMultiviewViewCount_ = {},
+ uint32_t maxMultiviewInstanceIndex_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 protectedNoFault_ = {},
+ uint32_t maxPerSetDescriptors_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize maxMemoryAllocationSize_ = {} ) VULKAN_HPP_NOEXCEPT
+ : deviceUUID{}
+ , driverUUID{}
+ , deviceLUID{}
+ , deviceNodeMask( deviceNodeMask_ )
+ , deviceLUIDValid( deviceLUIDValid_ )
+ , subgroupSize( subgroupSize_ )
+ , subgroupSupportedStages( subgroupSupportedStages_ )
+ , subgroupSupportedOperations( subgroupSupportedOperations_ )
+ , subgroupQuadOperationsInAllStages( subgroupQuadOperationsInAllStages_ )
+ , pointClippingBehavior( pointClippingBehavior_ )
+ , maxMultiviewViewCount( maxMultiviewViewCount_ )
+ , maxMultiviewInstanceIndex( maxMultiviewInstanceIndex_ )
+ , protectedNoFault( protectedNoFault_ )
+ , maxPerSetDescriptors( maxPerSetDescriptors_ )
+ , maxMemoryAllocationSize( maxMemoryAllocationSize_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE,VK_UUID_SIZE>::copy( deviceUUID, deviceUUID_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE,VK_UUID_SIZE>::copy( driverUUID, driverUUID_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_LUID_SIZE,VK_LUID_SIZE>::copy( deviceLUID, deviceLUID_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan11Properties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan11Properties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan11Properties ) - offsetof( PhysicalDeviceVulkan11Properties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties( VkPhysicalDeviceVulkan11Properties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceVulkan11Properties& operator=( VkPhysicalDeviceVulkan11Properties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan11Properties const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setDeviceUUID( std::array<uint8_t,VK_UUID_SIZE> deviceUUID_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( deviceUUID, deviceUUID_.data(), VK_UUID_SIZE * sizeof( uint8_t ) );
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setDriverUUID( std::array<uint8_t,VK_UUID_SIZE> driverUUID_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( driverUUID, driverUUID_.data(), VK_UUID_SIZE * sizeof( uint8_t ) );
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setDeviceLUID( std::array<uint8_t,VK_LUID_SIZE> deviceLUID_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( deviceLUID, deviceLUID_.data(), VK_LUID_SIZE * sizeof( uint8_t ) );
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setDeviceNodeMask( uint32_t deviceNodeMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceNodeMask = deviceNodeMask_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setDeviceLUIDValid( VULKAN_HPP_NAMESPACE::Bool32 deviceLUIDValid_ ) VULKAN_HPP_NOEXCEPT
+ {
+ deviceLUIDValid = deviceLUIDValid_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setSubgroupSize( uint32_t subgroupSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subgroupSize = subgroupSize_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setSubgroupSupportedStages( VULKAN_HPP_NAMESPACE::ShaderStageFlags subgroupSupportedStages_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subgroupSupportedStages = subgroupSupportedStages_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setSubgroupSupportedOperations( VULKAN_HPP_NAMESPACE::SubgroupFeatureFlags subgroupSupportedOperations_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subgroupSupportedOperations = subgroupSupportedOperations_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setSubgroupQuadOperationsInAllStages( VULKAN_HPP_NAMESPACE::Bool32 subgroupQuadOperationsInAllStages_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subgroupQuadOperationsInAllStages = subgroupQuadOperationsInAllStages_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setPointClippingBehavior( VULKAN_HPP_NAMESPACE::PointClippingBehavior pointClippingBehavior_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pointClippingBehavior = pointClippingBehavior_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setMaxMultiviewViewCount( uint32_t maxMultiviewViewCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxMultiviewViewCount = maxMultiviewViewCount_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setMaxMultiviewInstanceIndex( uint32_t maxMultiviewInstanceIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxMultiviewInstanceIndex = maxMultiviewInstanceIndex_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setProtectedNoFault( VULKAN_HPP_NAMESPACE::Bool32 protectedNoFault_ ) VULKAN_HPP_NOEXCEPT
+ {
+ protectedNoFault = protectedNoFault_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setMaxPerSetDescriptors( uint32_t maxPerSetDescriptors_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxPerSetDescriptors = maxPerSetDescriptors_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan11Properties & setMaxMemoryAllocationSize( VULKAN_HPP_NAMESPACE::DeviceSize maxMemoryAllocationSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxMemoryAllocationSize = maxMemoryAllocationSize_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceVulkan11Properties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceVulkan11Properties*>( this );
+ }
+
+ operator VkPhysicalDeviceVulkan11Properties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceVulkan11Properties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceVulkan11Properties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memcmp( deviceUUID, rhs.deviceUUID, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 )
+ && ( memcmp( driverUUID, rhs.driverUUID, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 )
+ && ( memcmp( deviceLUID, rhs.deviceLUID, VK_LUID_SIZE * sizeof( uint8_t ) ) == 0 )
+ && ( deviceNodeMask == rhs.deviceNodeMask )
+ && ( deviceLUIDValid == rhs.deviceLUIDValid )
+ && ( subgroupSize == rhs.subgroupSize )
+ && ( subgroupSupportedStages == rhs.subgroupSupportedStages )
+ && ( subgroupSupportedOperations == rhs.subgroupSupportedOperations )
+ && ( subgroupQuadOperationsInAllStages == rhs.subgroupQuadOperationsInAllStages )
+ && ( pointClippingBehavior == rhs.pointClippingBehavior )
+ && ( maxMultiviewViewCount == rhs.maxMultiviewViewCount )
+ && ( maxMultiviewInstanceIndex == rhs.maxMultiviewInstanceIndex )
+ && ( protectedNoFault == rhs.protectedNoFault )
+ && ( maxPerSetDescriptors == rhs.maxPerSetDescriptors )
+ && ( maxMemoryAllocationSize == rhs.maxMemoryAllocationSize );
+ }
+
+ bool operator!=( PhysicalDeviceVulkan11Properties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceVulkan11Properties;
+ void* pNext = {};
+ uint8_t deviceUUID[VK_UUID_SIZE] = {};
+ uint8_t driverUUID[VK_UUID_SIZE] = {};
+ uint8_t deviceLUID[VK_LUID_SIZE] = {};
+ uint32_t deviceNodeMask = {};
+ VULKAN_HPP_NAMESPACE::Bool32 deviceLUIDValid = {};
+ uint32_t subgroupSize = {};
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags subgroupSupportedStages = {};
+ VULKAN_HPP_NAMESPACE::SubgroupFeatureFlags subgroupSupportedOperations = {};
+ VULKAN_HPP_NAMESPACE::Bool32 subgroupQuadOperationsInAllStages = {};
+ VULKAN_HPP_NAMESPACE::PointClippingBehavior pointClippingBehavior = VULKAN_HPP_NAMESPACE::PointClippingBehavior::eAllClipPlanes;
+ uint32_t maxMultiviewViewCount = {};
+ uint32_t maxMultiviewInstanceIndex = {};
+ VULKAN_HPP_NAMESPACE::Bool32 protectedNoFault = {};
+ uint32_t maxPerSetDescriptors = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize maxMemoryAllocationSize = {};
+ };
+ static_assert( sizeof( PhysicalDeviceVulkan11Properties ) == sizeof( VkPhysicalDeviceVulkan11Properties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceVulkan11Properties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceVulkan12Features
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceVulkan12Features( VULKAN_HPP_NAMESPACE::Bool32 samplerMirrorClampToEdge_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 drawIndirectCount_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 storageBuffer8BitAccess_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer8BitAccess_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant8_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderBufferInt64Atomics_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSharedInt64Atomics_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInt8_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayDynamicIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayDynamicIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayDynamicIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayNonUniformIndexing_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformBufferUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingSampledImageUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageImageUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageBufferUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformTexelBufferUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageTexelBufferUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUpdateUnusedWhilePending_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingPartiallyBound_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingVariableDescriptorCount_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 runtimeDescriptorArray_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 samplerFilterMinmax_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 scalarBlockLayout_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 imagelessFramebuffer_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 uniformBufferStandardLayout_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSubgroupExtendedTypes_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 separateDepthStencilLayouts_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 hostQueryReset_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 timelineSemaphore_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddress_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressCaptureReplay_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressMultiDevice_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModel_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelDeviceScope_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelAvailabilityVisibilityChains_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderOutputViewportIndex_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderOutputLayer_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 subgroupBroadcastDynamicId_ = {} ) VULKAN_HPP_NOEXCEPT
+ : samplerMirrorClampToEdge( samplerMirrorClampToEdge_ )
+ , drawIndirectCount( drawIndirectCount_ )
+ , storageBuffer8BitAccess( storageBuffer8BitAccess_ )
+ , uniformAndStorageBuffer8BitAccess( uniformAndStorageBuffer8BitAccess_ )
+ , storagePushConstant8( storagePushConstant8_ )
+ , shaderBufferInt64Atomics( shaderBufferInt64Atomics_ )
+ , shaderSharedInt64Atomics( shaderSharedInt64Atomics_ )
+ , shaderFloat16( shaderFloat16_ )
+ , shaderInt8( shaderInt8_ )
+ , descriptorIndexing( descriptorIndexing_ )
+ , shaderInputAttachmentArrayDynamicIndexing( shaderInputAttachmentArrayDynamicIndexing_ )
+ , shaderUniformTexelBufferArrayDynamicIndexing( shaderUniformTexelBufferArrayDynamicIndexing_ )
+ , shaderStorageTexelBufferArrayDynamicIndexing( shaderStorageTexelBufferArrayDynamicIndexing_ )
+ , shaderUniformBufferArrayNonUniformIndexing( shaderUniformBufferArrayNonUniformIndexing_ )
+ , shaderSampledImageArrayNonUniformIndexing( shaderSampledImageArrayNonUniformIndexing_ )
+ , shaderStorageBufferArrayNonUniformIndexing( shaderStorageBufferArrayNonUniformIndexing_ )
+ , shaderStorageImageArrayNonUniformIndexing( shaderStorageImageArrayNonUniformIndexing_ )
+ , shaderInputAttachmentArrayNonUniformIndexing( shaderInputAttachmentArrayNonUniformIndexing_ )
+ , shaderUniformTexelBufferArrayNonUniformIndexing( shaderUniformTexelBufferArrayNonUniformIndexing_ )
+ , shaderStorageTexelBufferArrayNonUniformIndexing( shaderStorageTexelBufferArrayNonUniformIndexing_ )
+ , descriptorBindingUniformBufferUpdateAfterBind( descriptorBindingUniformBufferUpdateAfterBind_ )
+ , descriptorBindingSampledImageUpdateAfterBind( descriptorBindingSampledImageUpdateAfterBind_ )
+ , descriptorBindingStorageImageUpdateAfterBind( descriptorBindingStorageImageUpdateAfterBind_ )
+ , descriptorBindingStorageBufferUpdateAfterBind( descriptorBindingStorageBufferUpdateAfterBind_ )
+ , descriptorBindingUniformTexelBufferUpdateAfterBind( descriptorBindingUniformTexelBufferUpdateAfterBind_ )
+ , descriptorBindingStorageTexelBufferUpdateAfterBind( descriptorBindingStorageTexelBufferUpdateAfterBind_ )
+ , descriptorBindingUpdateUnusedWhilePending( descriptorBindingUpdateUnusedWhilePending_ )
+ , descriptorBindingPartiallyBound( descriptorBindingPartiallyBound_ )
+ , descriptorBindingVariableDescriptorCount( descriptorBindingVariableDescriptorCount_ )
+ , runtimeDescriptorArray( runtimeDescriptorArray_ )
+ , samplerFilterMinmax( samplerFilterMinmax_ )
+ , scalarBlockLayout( scalarBlockLayout_ )
+ , imagelessFramebuffer( imagelessFramebuffer_ )
+ , uniformBufferStandardLayout( uniformBufferStandardLayout_ )
+ , shaderSubgroupExtendedTypes( shaderSubgroupExtendedTypes_ )
+ , separateDepthStencilLayouts( separateDepthStencilLayouts_ )
+ , hostQueryReset( hostQueryReset_ )
+ , timelineSemaphore( timelineSemaphore_ )
+ , bufferDeviceAddress( bufferDeviceAddress_ )
+ , bufferDeviceAddressCaptureReplay( bufferDeviceAddressCaptureReplay_ )
+ , bufferDeviceAddressMultiDevice( bufferDeviceAddressMultiDevice_ )
+ , vulkanMemoryModel( vulkanMemoryModel_ )
+ , vulkanMemoryModelDeviceScope( vulkanMemoryModelDeviceScope_ )
+ , vulkanMemoryModelAvailabilityVisibilityChains( vulkanMemoryModelAvailabilityVisibilityChains_ )
+ , shaderOutputViewportIndex( shaderOutputViewportIndex_ )
+ , shaderOutputLayer( shaderOutputLayer_ )
+ , subgroupBroadcastDynamicId( subgroupBroadcastDynamicId_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan12Features & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan12Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan12Features ) - offsetof( PhysicalDeviceVulkan12Features, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features( VkPhysicalDeviceVulkan12Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceVulkan12Features& operator=( VkPhysicalDeviceVulkan12Features const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan12Features const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setSamplerMirrorClampToEdge( VULKAN_HPP_NAMESPACE::Bool32 samplerMirrorClampToEdge_ ) VULKAN_HPP_NOEXCEPT
+ {
+ samplerMirrorClampToEdge = samplerMirrorClampToEdge_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDrawIndirectCount( VULKAN_HPP_NAMESPACE::Bool32 drawIndirectCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ drawIndirectCount = drawIndirectCount_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setStorageBuffer8BitAccess( VULKAN_HPP_NAMESPACE::Bool32 storageBuffer8BitAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storageBuffer8BitAccess = storageBuffer8BitAccess_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setUniformAndStorageBuffer8BitAccess( VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer8BitAccess_ ) VULKAN_HPP_NOEXCEPT
+ {
+ uniformAndStorageBuffer8BitAccess = uniformAndStorageBuffer8BitAccess_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setStoragePushConstant8( VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant8_ ) VULKAN_HPP_NOEXCEPT
+ {
+ storagePushConstant8 = storagePushConstant8_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderBufferInt64Atomics( VULKAN_HPP_NAMESPACE::Bool32 shaderBufferInt64Atomics_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderBufferInt64Atomics = shaderBufferInt64Atomics_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderSharedInt64Atomics( VULKAN_HPP_NAMESPACE::Bool32 shaderSharedInt64Atomics_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSharedInt64Atomics = shaderSharedInt64Atomics_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderFloat16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderFloat16 = shaderFloat16_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderInt8( VULKAN_HPP_NAMESPACE::Bool32 shaderInt8_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderInt8 = shaderInt8_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDescriptorIndexing( VULKAN_HPP_NAMESPACE::Bool32 descriptorIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorIndexing = descriptorIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderInputAttachmentArrayDynamicIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayDynamicIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderInputAttachmentArrayDynamicIndexing = shaderInputAttachmentArrayDynamicIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderUniformTexelBufferArrayDynamicIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayDynamicIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderUniformTexelBufferArrayDynamicIndexing = shaderUniformTexelBufferArrayDynamicIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderStorageTexelBufferArrayDynamicIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayDynamicIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageTexelBufferArrayDynamicIndexing = shaderStorageTexelBufferArrayDynamicIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderUniformBufferArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderUniformBufferArrayNonUniformIndexing = shaderUniformBufferArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderSampledImageArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSampledImageArrayNonUniformIndexing = shaderSampledImageArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderStorageBufferArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageBufferArrayNonUniformIndexing = shaderStorageBufferArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderStorageImageArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageImageArrayNonUniformIndexing = shaderStorageImageArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderInputAttachmentArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderInputAttachmentArrayNonUniformIndexing = shaderInputAttachmentArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderUniformTexelBufferArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderUniformTexelBufferArrayNonUniformIndexing = shaderUniformTexelBufferArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderStorageTexelBufferArrayNonUniformIndexing( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayNonUniformIndexing_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageTexelBufferArrayNonUniformIndexing = shaderStorageTexelBufferArrayNonUniformIndexing_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDescriptorBindingUniformBufferUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformBufferUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingUniformBufferUpdateAfterBind = descriptorBindingUniformBufferUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDescriptorBindingSampledImageUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingSampledImageUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingSampledImageUpdateAfterBind = descriptorBindingSampledImageUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDescriptorBindingStorageImageUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageImageUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingStorageImageUpdateAfterBind = descriptorBindingStorageImageUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDescriptorBindingStorageBufferUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageBufferUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingStorageBufferUpdateAfterBind = descriptorBindingStorageBufferUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDescriptorBindingUniformTexelBufferUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformTexelBufferUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingUniformTexelBufferUpdateAfterBind = descriptorBindingUniformTexelBufferUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDescriptorBindingStorageTexelBufferUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageTexelBufferUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingStorageTexelBufferUpdateAfterBind = descriptorBindingStorageTexelBufferUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDescriptorBindingUpdateUnusedWhilePending( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUpdateUnusedWhilePending_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingUpdateUnusedWhilePending = descriptorBindingUpdateUnusedWhilePending_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDescriptorBindingPartiallyBound( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingPartiallyBound_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingPartiallyBound = descriptorBindingPartiallyBound_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setDescriptorBindingVariableDescriptorCount( VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingVariableDescriptorCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorBindingVariableDescriptorCount = descriptorBindingVariableDescriptorCount_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setRuntimeDescriptorArray( VULKAN_HPP_NAMESPACE::Bool32 runtimeDescriptorArray_ ) VULKAN_HPP_NOEXCEPT
+ {
+ runtimeDescriptorArray = runtimeDescriptorArray_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setSamplerFilterMinmax( VULKAN_HPP_NAMESPACE::Bool32 samplerFilterMinmax_ ) VULKAN_HPP_NOEXCEPT
+ {
+ samplerFilterMinmax = samplerFilterMinmax_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setScalarBlockLayout( VULKAN_HPP_NAMESPACE::Bool32 scalarBlockLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ scalarBlockLayout = scalarBlockLayout_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setImagelessFramebuffer( VULKAN_HPP_NAMESPACE::Bool32 imagelessFramebuffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imagelessFramebuffer = imagelessFramebuffer_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setUniformBufferStandardLayout( VULKAN_HPP_NAMESPACE::Bool32 uniformBufferStandardLayout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ uniformBufferStandardLayout = uniformBufferStandardLayout_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderSubgroupExtendedTypes( VULKAN_HPP_NAMESPACE::Bool32 shaderSubgroupExtendedTypes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSubgroupExtendedTypes = shaderSubgroupExtendedTypes_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setSeparateDepthStencilLayouts( VULKAN_HPP_NAMESPACE::Bool32 separateDepthStencilLayouts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ separateDepthStencilLayouts = separateDepthStencilLayouts_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setHostQueryReset( VULKAN_HPP_NAMESPACE::Bool32 hostQueryReset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ hostQueryReset = hostQueryReset_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setTimelineSemaphore( VULKAN_HPP_NAMESPACE::Bool32 timelineSemaphore_ ) VULKAN_HPP_NOEXCEPT
+ {
+ timelineSemaphore = timelineSemaphore_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setBufferDeviceAddress( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddress_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferDeviceAddress = bufferDeviceAddress_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setBufferDeviceAddressCaptureReplay( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressCaptureReplay_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferDeviceAddressCaptureReplay = bufferDeviceAddressCaptureReplay_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setBufferDeviceAddressMultiDevice( VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressMultiDevice_ ) VULKAN_HPP_NOEXCEPT
+ {
+ bufferDeviceAddressMultiDevice = bufferDeviceAddressMultiDevice_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setVulkanMemoryModel( VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModel_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vulkanMemoryModel = vulkanMemoryModel_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setVulkanMemoryModelDeviceScope( VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelDeviceScope_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vulkanMemoryModelDeviceScope = vulkanMemoryModelDeviceScope_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setVulkanMemoryModelAvailabilityVisibilityChains( VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelAvailabilityVisibilityChains_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vulkanMemoryModelAvailabilityVisibilityChains = vulkanMemoryModelAvailabilityVisibilityChains_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderOutputViewportIndex( VULKAN_HPP_NAMESPACE::Bool32 shaderOutputViewportIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderOutputViewportIndex = shaderOutputViewportIndex_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setShaderOutputLayer( VULKAN_HPP_NAMESPACE::Bool32 shaderOutputLayer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderOutputLayer = shaderOutputLayer_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Features & setSubgroupBroadcastDynamicId( VULKAN_HPP_NAMESPACE::Bool32 subgroupBroadcastDynamicId_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subgroupBroadcastDynamicId = subgroupBroadcastDynamicId_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceVulkan12Features const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceVulkan12Features*>( this );
+ }
+
+ operator VkPhysicalDeviceVulkan12Features &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceVulkan12Features*>( this );
+ }
+
+ bool operator==( PhysicalDeviceVulkan12Features const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( samplerMirrorClampToEdge == rhs.samplerMirrorClampToEdge )
+ && ( drawIndirectCount == rhs.drawIndirectCount )
+ && ( storageBuffer8BitAccess == rhs.storageBuffer8BitAccess )
+ && ( uniformAndStorageBuffer8BitAccess == rhs.uniformAndStorageBuffer8BitAccess )
+ && ( storagePushConstant8 == rhs.storagePushConstant8 )
+ && ( shaderBufferInt64Atomics == rhs.shaderBufferInt64Atomics )
+ && ( shaderSharedInt64Atomics == rhs.shaderSharedInt64Atomics )
+ && ( shaderFloat16 == rhs.shaderFloat16 )
+ && ( shaderInt8 == rhs.shaderInt8 )
+ && ( descriptorIndexing == rhs.descriptorIndexing )
+ && ( shaderInputAttachmentArrayDynamicIndexing == rhs.shaderInputAttachmentArrayDynamicIndexing )
+ && ( shaderUniformTexelBufferArrayDynamicIndexing == rhs.shaderUniformTexelBufferArrayDynamicIndexing )
+ && ( shaderStorageTexelBufferArrayDynamicIndexing == rhs.shaderStorageTexelBufferArrayDynamicIndexing )
+ && ( shaderUniformBufferArrayNonUniformIndexing == rhs.shaderUniformBufferArrayNonUniformIndexing )
+ && ( shaderSampledImageArrayNonUniformIndexing == rhs.shaderSampledImageArrayNonUniformIndexing )
+ && ( shaderStorageBufferArrayNonUniformIndexing == rhs.shaderStorageBufferArrayNonUniformIndexing )
+ && ( shaderStorageImageArrayNonUniformIndexing == rhs.shaderStorageImageArrayNonUniformIndexing )
+ && ( shaderInputAttachmentArrayNonUniformIndexing == rhs.shaderInputAttachmentArrayNonUniformIndexing )
+ && ( shaderUniformTexelBufferArrayNonUniformIndexing == rhs.shaderUniformTexelBufferArrayNonUniformIndexing )
+ && ( shaderStorageTexelBufferArrayNonUniformIndexing == rhs.shaderStorageTexelBufferArrayNonUniformIndexing )
+ && ( descriptorBindingUniformBufferUpdateAfterBind == rhs.descriptorBindingUniformBufferUpdateAfterBind )
+ && ( descriptorBindingSampledImageUpdateAfterBind == rhs.descriptorBindingSampledImageUpdateAfterBind )
+ && ( descriptorBindingStorageImageUpdateAfterBind == rhs.descriptorBindingStorageImageUpdateAfterBind )
+ && ( descriptorBindingStorageBufferUpdateAfterBind == rhs.descriptorBindingStorageBufferUpdateAfterBind )
+ && ( descriptorBindingUniformTexelBufferUpdateAfterBind == rhs.descriptorBindingUniformTexelBufferUpdateAfterBind )
+ && ( descriptorBindingStorageTexelBufferUpdateAfterBind == rhs.descriptorBindingStorageTexelBufferUpdateAfterBind )
+ && ( descriptorBindingUpdateUnusedWhilePending == rhs.descriptorBindingUpdateUnusedWhilePending )
+ && ( descriptorBindingPartiallyBound == rhs.descriptorBindingPartiallyBound )
+ && ( descriptorBindingVariableDescriptorCount == rhs.descriptorBindingVariableDescriptorCount )
+ && ( runtimeDescriptorArray == rhs.runtimeDescriptorArray )
+ && ( samplerFilterMinmax == rhs.samplerFilterMinmax )
+ && ( scalarBlockLayout == rhs.scalarBlockLayout )
+ && ( imagelessFramebuffer == rhs.imagelessFramebuffer )
+ && ( uniformBufferStandardLayout == rhs.uniformBufferStandardLayout )
+ && ( shaderSubgroupExtendedTypes == rhs.shaderSubgroupExtendedTypes )
+ && ( separateDepthStencilLayouts == rhs.separateDepthStencilLayouts )
+ && ( hostQueryReset == rhs.hostQueryReset )
+ && ( timelineSemaphore == rhs.timelineSemaphore )
+ && ( bufferDeviceAddress == rhs.bufferDeviceAddress )
+ && ( bufferDeviceAddressCaptureReplay == rhs.bufferDeviceAddressCaptureReplay )
+ && ( bufferDeviceAddressMultiDevice == rhs.bufferDeviceAddressMultiDevice )
+ && ( vulkanMemoryModel == rhs.vulkanMemoryModel )
+ && ( vulkanMemoryModelDeviceScope == rhs.vulkanMemoryModelDeviceScope )
+ && ( vulkanMemoryModelAvailabilityVisibilityChains == rhs.vulkanMemoryModelAvailabilityVisibilityChains )
+ && ( shaderOutputViewportIndex == rhs.shaderOutputViewportIndex )
+ && ( shaderOutputLayer == rhs.shaderOutputLayer )
+ && ( subgroupBroadcastDynamicId == rhs.subgroupBroadcastDynamicId );
+ }
+
+ bool operator!=( PhysicalDeviceVulkan12Features const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceVulkan12Features;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 samplerMirrorClampToEdge = {};
+ VULKAN_HPP_NAMESPACE::Bool32 drawIndirectCount = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storageBuffer8BitAccess = {};
+ VULKAN_HPP_NAMESPACE::Bool32 uniformAndStorageBuffer8BitAccess = {};
+ VULKAN_HPP_NAMESPACE::Bool32 storagePushConstant8 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderBufferInt64Atomics = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSharedInt64Atomics = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInt8 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayDynamicIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayDynamicIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayDynamicIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformTexelBufferArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageTexelBufferArrayNonUniformIndexing = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformBufferUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingSampledImageUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageImageUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageBufferUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUniformTexelBufferUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingStorageTexelBufferUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingUpdateUnusedWhilePending = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingPartiallyBound = {};
+ VULKAN_HPP_NAMESPACE::Bool32 descriptorBindingVariableDescriptorCount = {};
+ VULKAN_HPP_NAMESPACE::Bool32 runtimeDescriptorArray = {};
+ VULKAN_HPP_NAMESPACE::Bool32 samplerFilterMinmax = {};
+ VULKAN_HPP_NAMESPACE::Bool32 scalarBlockLayout = {};
+ VULKAN_HPP_NAMESPACE::Bool32 imagelessFramebuffer = {};
+ VULKAN_HPP_NAMESPACE::Bool32 uniformBufferStandardLayout = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSubgroupExtendedTypes = {};
+ VULKAN_HPP_NAMESPACE::Bool32 separateDepthStencilLayouts = {};
+ VULKAN_HPP_NAMESPACE::Bool32 hostQueryReset = {};
+ VULKAN_HPP_NAMESPACE::Bool32 timelineSemaphore = {};
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddress = {};
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressCaptureReplay = {};
+ VULKAN_HPP_NAMESPACE::Bool32 bufferDeviceAddressMultiDevice = {};
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModel = {};
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelDeviceScope = {};
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelAvailabilityVisibilityChains = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderOutputViewportIndex = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderOutputLayer = {};
+ VULKAN_HPP_NAMESPACE::Bool32 subgroupBroadcastDynamicId = {};
+ };
+ static_assert( sizeof( PhysicalDeviceVulkan12Features ) == sizeof( VkPhysicalDeviceVulkan12Features ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceVulkan12Features>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceVulkan12Properties
+ {
+ VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceVulkan12Properties( VULKAN_HPP_NAMESPACE::DriverId driverID_ = VULKAN_HPP_NAMESPACE::DriverId::eAmdProprietary,
+ std::array<char,VK_MAX_DRIVER_NAME_SIZE> const& driverName_ = {},
+ std::array<char,VK_MAX_DRIVER_INFO_SIZE> const& driverInfo_ = {},
+ VULKAN_HPP_NAMESPACE::ConformanceVersion conformanceVersion_ = {},
+ VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence denormBehaviorIndependence_ = VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence::e32BitOnly,
+ VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence roundingModeIndependence_ = VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence::e32BitOnly,
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat64_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat64_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat64_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat64_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat16_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat32_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat64_ = {},
+ uint32_t maxUpdateAfterBindDescriptorsInAllPools_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexingNative_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexingNative_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexingNative_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexingNative_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexingNative_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 robustBufferAccessUpdateAfterBind_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 quadDivergentImplicitLod_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindSamplers_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages_ = {},
+ uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments_ = {},
+ uint32_t maxPerStageUpdateAfterBindResources_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindSamplers_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindSampledImages_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindStorageImages_ = {},
+ uint32_t maxDescriptorSetUpdateAfterBindInputAttachments_ = {},
+ VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedDepthResolveModes_ = {},
+ VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedStencilResolveModes_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 independentResolveNone_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 independentResolve_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxSingleComponentFormats_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxImageComponentMapping_ = {},
+ uint64_t maxTimelineSemaphoreValueDifference_ = {},
+ VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferIntegerColorSampleCounts_ = {} ) VULKAN_HPP_NOEXCEPT
+ : driverID( driverID_ )
+ , driverName{}
+ , driverInfo{}
+ , conformanceVersion( conformanceVersion_ )
+ , denormBehaviorIndependence( denormBehaviorIndependence_ )
+ , roundingModeIndependence( roundingModeIndependence_ )
+ , shaderSignedZeroInfNanPreserveFloat16( shaderSignedZeroInfNanPreserveFloat16_ )
+ , shaderSignedZeroInfNanPreserveFloat32( shaderSignedZeroInfNanPreserveFloat32_ )
+ , shaderSignedZeroInfNanPreserveFloat64( shaderSignedZeroInfNanPreserveFloat64_ )
+ , shaderDenormPreserveFloat16( shaderDenormPreserveFloat16_ )
+ , shaderDenormPreserveFloat32( shaderDenormPreserveFloat32_ )
+ , shaderDenormPreserveFloat64( shaderDenormPreserveFloat64_ )
+ , shaderDenormFlushToZeroFloat16( shaderDenormFlushToZeroFloat16_ )
+ , shaderDenormFlushToZeroFloat32( shaderDenormFlushToZeroFloat32_ )
+ , shaderDenormFlushToZeroFloat64( shaderDenormFlushToZeroFloat64_ )
+ , shaderRoundingModeRTEFloat16( shaderRoundingModeRTEFloat16_ )
+ , shaderRoundingModeRTEFloat32( shaderRoundingModeRTEFloat32_ )
+ , shaderRoundingModeRTEFloat64( shaderRoundingModeRTEFloat64_ )
+ , shaderRoundingModeRTZFloat16( shaderRoundingModeRTZFloat16_ )
+ , shaderRoundingModeRTZFloat32( shaderRoundingModeRTZFloat32_ )
+ , shaderRoundingModeRTZFloat64( shaderRoundingModeRTZFloat64_ )
+ , maxUpdateAfterBindDescriptorsInAllPools( maxUpdateAfterBindDescriptorsInAllPools_ )
+ , shaderUniformBufferArrayNonUniformIndexingNative( shaderUniformBufferArrayNonUniformIndexingNative_ )
+ , shaderSampledImageArrayNonUniformIndexingNative( shaderSampledImageArrayNonUniformIndexingNative_ )
+ , shaderStorageBufferArrayNonUniformIndexingNative( shaderStorageBufferArrayNonUniformIndexingNative_ )
+ , shaderStorageImageArrayNonUniformIndexingNative( shaderStorageImageArrayNonUniformIndexingNative_ )
+ , shaderInputAttachmentArrayNonUniformIndexingNative( shaderInputAttachmentArrayNonUniformIndexingNative_ )
+ , robustBufferAccessUpdateAfterBind( robustBufferAccessUpdateAfterBind_ )
+ , quadDivergentImplicitLod( quadDivergentImplicitLod_ )
+ , maxPerStageDescriptorUpdateAfterBindSamplers( maxPerStageDescriptorUpdateAfterBindSamplers_ )
+ , maxPerStageDescriptorUpdateAfterBindUniformBuffers( maxPerStageDescriptorUpdateAfterBindUniformBuffers_ )
+ , maxPerStageDescriptorUpdateAfterBindStorageBuffers( maxPerStageDescriptorUpdateAfterBindStorageBuffers_ )
+ , maxPerStageDescriptorUpdateAfterBindSampledImages( maxPerStageDescriptorUpdateAfterBindSampledImages_ )
+ , maxPerStageDescriptorUpdateAfterBindStorageImages( maxPerStageDescriptorUpdateAfterBindStorageImages_ )
+ , maxPerStageDescriptorUpdateAfterBindInputAttachments( maxPerStageDescriptorUpdateAfterBindInputAttachments_ )
+ , maxPerStageUpdateAfterBindResources( maxPerStageUpdateAfterBindResources_ )
+ , maxDescriptorSetUpdateAfterBindSamplers( maxDescriptorSetUpdateAfterBindSamplers_ )
+ , maxDescriptorSetUpdateAfterBindUniformBuffers( maxDescriptorSetUpdateAfterBindUniformBuffers_ )
+ , maxDescriptorSetUpdateAfterBindUniformBuffersDynamic( maxDescriptorSetUpdateAfterBindUniformBuffersDynamic_ )
+ , maxDescriptorSetUpdateAfterBindStorageBuffers( maxDescriptorSetUpdateAfterBindStorageBuffers_ )
+ , maxDescriptorSetUpdateAfterBindStorageBuffersDynamic( maxDescriptorSetUpdateAfterBindStorageBuffersDynamic_ )
+ , maxDescriptorSetUpdateAfterBindSampledImages( maxDescriptorSetUpdateAfterBindSampledImages_ )
+ , maxDescriptorSetUpdateAfterBindStorageImages( maxDescriptorSetUpdateAfterBindStorageImages_ )
+ , maxDescriptorSetUpdateAfterBindInputAttachments( maxDescriptorSetUpdateAfterBindInputAttachments_ )
+ , supportedDepthResolveModes( supportedDepthResolveModes_ )
+ , supportedStencilResolveModes( supportedStencilResolveModes_ )
+ , independentResolveNone( independentResolveNone_ )
+ , independentResolve( independentResolve_ )
+ , filterMinmaxSingleComponentFormats( filterMinmaxSingleComponentFormats_ )
+ , filterMinmaxImageComponentMapping( filterMinmaxImageComponentMapping_ )
+ , maxTimelineSemaphoreValueDifference( maxTimelineSemaphoreValueDifference_ )
+ , framebufferIntegerColorSampleCounts( framebufferIntegerColorSampleCounts_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_NAME_SIZE,VK_MAX_DRIVER_NAME_SIZE>::copy( driverName, driverName_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_INFO_SIZE,VK_MAX_DRIVER_INFO_SIZE>::copy( driverInfo, driverInfo_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan12Properties & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan12Properties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan12Properties ) - offsetof( PhysicalDeviceVulkan12Properties, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties( VkPhysicalDeviceVulkan12Properties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceVulkan12Properties& operator=( VkPhysicalDeviceVulkan12Properties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkan12Properties const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setDriverID( VULKAN_HPP_NAMESPACE::DriverId driverID_ ) VULKAN_HPP_NOEXCEPT
+ {
+ driverID = driverID_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setDriverName( std::array<char,VK_MAX_DRIVER_NAME_SIZE> driverName_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( driverName, driverName_.data(), VK_MAX_DRIVER_NAME_SIZE * sizeof( char ) );
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setDriverInfo( std::array<char,VK_MAX_DRIVER_INFO_SIZE> driverInfo_ ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( driverInfo, driverInfo_.data(), VK_MAX_DRIVER_INFO_SIZE * sizeof( char ) );
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setConformanceVersion( VULKAN_HPP_NAMESPACE::ConformanceVersion conformanceVersion_ ) VULKAN_HPP_NOEXCEPT
+ {
+ conformanceVersion = conformanceVersion_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setDenormBehaviorIndependence( VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence denormBehaviorIndependence_ ) VULKAN_HPP_NOEXCEPT
+ {
+ denormBehaviorIndependence = denormBehaviorIndependence_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setRoundingModeIndependence( VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence roundingModeIndependence_ ) VULKAN_HPP_NOEXCEPT
+ {
+ roundingModeIndependence = roundingModeIndependence_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderSignedZeroInfNanPreserveFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSignedZeroInfNanPreserveFloat16 = shaderSignedZeroInfNanPreserveFloat16_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderSignedZeroInfNanPreserveFloat32( VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSignedZeroInfNanPreserveFloat32 = shaderSignedZeroInfNanPreserveFloat32_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderSignedZeroInfNanPreserveFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSignedZeroInfNanPreserveFloat64 = shaderSignedZeroInfNanPreserveFloat64_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderDenormPreserveFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderDenormPreserveFloat16 = shaderDenormPreserveFloat16_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderDenormPreserveFloat32( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderDenormPreserveFloat32 = shaderDenormPreserveFloat32_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderDenormPreserveFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderDenormPreserveFloat64 = shaderDenormPreserveFloat64_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderDenormFlushToZeroFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderDenormFlushToZeroFloat16 = shaderDenormFlushToZeroFloat16_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderDenormFlushToZeroFloat32( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderDenormFlushToZeroFloat32 = shaderDenormFlushToZeroFloat32_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderDenormFlushToZeroFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderDenormFlushToZeroFloat64 = shaderDenormFlushToZeroFloat64_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTEFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderRoundingModeRTEFloat16 = shaderRoundingModeRTEFloat16_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTEFloat32( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderRoundingModeRTEFloat32 = shaderRoundingModeRTEFloat32_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTEFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderRoundingModeRTEFloat64 = shaderRoundingModeRTEFloat64_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTZFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat16_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderRoundingModeRTZFloat16 = shaderRoundingModeRTZFloat16_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTZFloat32( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat32_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderRoundingModeRTZFloat32 = shaderRoundingModeRTZFloat32_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTZFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat64_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderRoundingModeRTZFloat64 = shaderRoundingModeRTZFloat64_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxUpdateAfterBindDescriptorsInAllPools( uint32_t maxUpdateAfterBindDescriptorsInAllPools_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxUpdateAfterBindDescriptorsInAllPools = maxUpdateAfterBindDescriptorsInAllPools_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderUniformBufferArrayNonUniformIndexingNative( VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexingNative_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderUniformBufferArrayNonUniformIndexingNative = shaderUniformBufferArrayNonUniformIndexingNative_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderSampledImageArrayNonUniformIndexingNative( VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexingNative_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderSampledImageArrayNonUniformIndexingNative = shaderSampledImageArrayNonUniformIndexingNative_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderStorageBufferArrayNonUniformIndexingNative( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexingNative_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageBufferArrayNonUniformIndexingNative = shaderStorageBufferArrayNonUniformIndexingNative_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderStorageImageArrayNonUniformIndexingNative( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexingNative_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderStorageImageArrayNonUniformIndexingNative = shaderStorageImageArrayNonUniformIndexingNative_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setShaderInputAttachmentArrayNonUniformIndexingNative( VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexingNative_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shaderInputAttachmentArrayNonUniformIndexingNative = shaderInputAttachmentArrayNonUniformIndexingNative_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setRobustBufferAccessUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 robustBufferAccessUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
+ {
+ robustBufferAccessUpdateAfterBind = robustBufferAccessUpdateAfterBind_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setQuadDivergentImplicitLod( VULKAN_HPP_NAMESPACE::Bool32 quadDivergentImplicitLod_ ) VULKAN_HPP_NOEXCEPT
+ {
+ quadDivergentImplicitLod = quadDivergentImplicitLod_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindSamplers( uint32_t maxPerStageDescriptorUpdateAfterBindSamplers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxPerStageDescriptorUpdateAfterBindSamplers = maxPerStageDescriptorUpdateAfterBindSamplers_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindUniformBuffers( uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxPerStageDescriptorUpdateAfterBindUniformBuffers = maxPerStageDescriptorUpdateAfterBindUniformBuffers_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindStorageBuffers( uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxPerStageDescriptorUpdateAfterBindStorageBuffers = maxPerStageDescriptorUpdateAfterBindStorageBuffers_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindSampledImages( uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxPerStageDescriptorUpdateAfterBindSampledImages = maxPerStageDescriptorUpdateAfterBindSampledImages_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindStorageImages( uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxPerStageDescriptorUpdateAfterBindStorageImages = maxPerStageDescriptorUpdateAfterBindStorageImages_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindInputAttachments( uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxPerStageDescriptorUpdateAfterBindInputAttachments = maxPerStageDescriptorUpdateAfterBindInputAttachments_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxPerStageUpdateAfterBindResources( uint32_t maxPerStageUpdateAfterBindResources_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxPerStageUpdateAfterBindResources = maxPerStageUpdateAfterBindResources_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindSamplers( uint32_t maxDescriptorSetUpdateAfterBindSamplers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxDescriptorSetUpdateAfterBindSamplers = maxDescriptorSetUpdateAfterBindSamplers_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindUniformBuffers( uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxDescriptorSetUpdateAfterBindUniformBuffers = maxDescriptorSetUpdateAfterBindUniformBuffers_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindUniformBuffersDynamic( uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = maxDescriptorSetUpdateAfterBindUniformBuffersDynamic_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindStorageBuffers( uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxDescriptorSetUpdateAfterBindStorageBuffers = maxDescriptorSetUpdateAfterBindStorageBuffers_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindStorageBuffersDynamic( uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = maxDescriptorSetUpdateAfterBindStorageBuffersDynamic_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindSampledImages( uint32_t maxDescriptorSetUpdateAfterBindSampledImages_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxDescriptorSetUpdateAfterBindSampledImages = maxDescriptorSetUpdateAfterBindSampledImages_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindStorageImages( uint32_t maxDescriptorSetUpdateAfterBindStorageImages_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxDescriptorSetUpdateAfterBindStorageImages = maxDescriptorSetUpdateAfterBindStorageImages_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindInputAttachments( uint32_t maxDescriptorSetUpdateAfterBindInputAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxDescriptorSetUpdateAfterBindInputAttachments = maxDescriptorSetUpdateAfterBindInputAttachments_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setSupportedDepthResolveModes( VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedDepthResolveModes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ supportedDepthResolveModes = supportedDepthResolveModes_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setSupportedStencilResolveModes( VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedStencilResolveModes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ supportedStencilResolveModes = supportedStencilResolveModes_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setIndependentResolveNone( VULKAN_HPP_NAMESPACE::Bool32 independentResolveNone_ ) VULKAN_HPP_NOEXCEPT
+ {
+ independentResolveNone = independentResolveNone_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setIndependentResolve( VULKAN_HPP_NAMESPACE::Bool32 independentResolve_ ) VULKAN_HPP_NOEXCEPT
+ {
+ independentResolve = independentResolve_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setFilterMinmaxSingleComponentFormats( VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxSingleComponentFormats_ ) VULKAN_HPP_NOEXCEPT
+ {
+ filterMinmaxSingleComponentFormats = filterMinmaxSingleComponentFormats_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setFilterMinmaxImageComponentMapping( VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxImageComponentMapping_ ) VULKAN_HPP_NOEXCEPT
+ {
+ filterMinmaxImageComponentMapping = filterMinmaxImageComponentMapping_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setMaxTimelineSemaphoreValueDifference( uint64_t maxTimelineSemaphoreValueDifference_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxTimelineSemaphoreValueDifference = maxTimelineSemaphoreValueDifference_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkan12Properties & setFramebufferIntegerColorSampleCounts( VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferIntegerColorSampleCounts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ framebufferIntegerColorSampleCounts = framebufferIntegerColorSampleCounts_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceVulkan12Properties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceVulkan12Properties*>( this );
+ }
+
+ operator VkPhysicalDeviceVulkan12Properties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceVulkan12Properties*>( this );
+ }
+
+ bool operator==( PhysicalDeviceVulkan12Properties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( driverID == rhs.driverID )
+ && ( memcmp( driverName, rhs.driverName, VK_MAX_DRIVER_NAME_SIZE * sizeof( char ) ) == 0 )
+ && ( memcmp( driverInfo, rhs.driverInfo, VK_MAX_DRIVER_INFO_SIZE * sizeof( char ) ) == 0 )
+ && ( conformanceVersion == rhs.conformanceVersion )
+ && ( denormBehaviorIndependence == rhs.denormBehaviorIndependence )
+ && ( roundingModeIndependence == rhs.roundingModeIndependence )
+ && ( shaderSignedZeroInfNanPreserveFloat16 == rhs.shaderSignedZeroInfNanPreserveFloat16 )
+ && ( shaderSignedZeroInfNanPreserveFloat32 == rhs.shaderSignedZeroInfNanPreserveFloat32 )
+ && ( shaderSignedZeroInfNanPreserveFloat64 == rhs.shaderSignedZeroInfNanPreserveFloat64 )
+ && ( shaderDenormPreserveFloat16 == rhs.shaderDenormPreserveFloat16 )
+ && ( shaderDenormPreserveFloat32 == rhs.shaderDenormPreserveFloat32 )
+ && ( shaderDenormPreserveFloat64 == rhs.shaderDenormPreserveFloat64 )
+ && ( shaderDenormFlushToZeroFloat16 == rhs.shaderDenormFlushToZeroFloat16 )
+ && ( shaderDenormFlushToZeroFloat32 == rhs.shaderDenormFlushToZeroFloat32 )
+ && ( shaderDenormFlushToZeroFloat64 == rhs.shaderDenormFlushToZeroFloat64 )
+ && ( shaderRoundingModeRTEFloat16 == rhs.shaderRoundingModeRTEFloat16 )
+ && ( shaderRoundingModeRTEFloat32 == rhs.shaderRoundingModeRTEFloat32 )
+ && ( shaderRoundingModeRTEFloat64 == rhs.shaderRoundingModeRTEFloat64 )
+ && ( shaderRoundingModeRTZFloat16 == rhs.shaderRoundingModeRTZFloat16 )
+ && ( shaderRoundingModeRTZFloat32 == rhs.shaderRoundingModeRTZFloat32 )
+ && ( shaderRoundingModeRTZFloat64 == rhs.shaderRoundingModeRTZFloat64 )
+ && ( maxUpdateAfterBindDescriptorsInAllPools == rhs.maxUpdateAfterBindDescriptorsInAllPools )
+ && ( shaderUniformBufferArrayNonUniformIndexingNative == rhs.shaderUniformBufferArrayNonUniformIndexingNative )
+ && ( shaderSampledImageArrayNonUniformIndexingNative == rhs.shaderSampledImageArrayNonUniformIndexingNative )
+ && ( shaderStorageBufferArrayNonUniformIndexingNative == rhs.shaderStorageBufferArrayNonUniformIndexingNative )
+ && ( shaderStorageImageArrayNonUniformIndexingNative == rhs.shaderStorageImageArrayNonUniformIndexingNative )
+ && ( shaderInputAttachmentArrayNonUniformIndexingNative == rhs.shaderInputAttachmentArrayNonUniformIndexingNative )
+ && ( robustBufferAccessUpdateAfterBind == rhs.robustBufferAccessUpdateAfterBind )
+ && ( quadDivergentImplicitLod == rhs.quadDivergentImplicitLod )
+ && ( maxPerStageDescriptorUpdateAfterBindSamplers == rhs.maxPerStageDescriptorUpdateAfterBindSamplers )
+ && ( maxPerStageDescriptorUpdateAfterBindUniformBuffers == rhs.maxPerStageDescriptorUpdateAfterBindUniformBuffers )
+ && ( maxPerStageDescriptorUpdateAfterBindStorageBuffers == rhs.maxPerStageDescriptorUpdateAfterBindStorageBuffers )
+ && ( maxPerStageDescriptorUpdateAfterBindSampledImages == rhs.maxPerStageDescriptorUpdateAfterBindSampledImages )
+ && ( maxPerStageDescriptorUpdateAfterBindStorageImages == rhs.maxPerStageDescriptorUpdateAfterBindStorageImages )
+ && ( maxPerStageDescriptorUpdateAfterBindInputAttachments == rhs.maxPerStageDescriptorUpdateAfterBindInputAttachments )
+ && ( maxPerStageUpdateAfterBindResources == rhs.maxPerStageUpdateAfterBindResources )
+ && ( maxDescriptorSetUpdateAfterBindSamplers == rhs.maxDescriptorSetUpdateAfterBindSamplers )
+ && ( maxDescriptorSetUpdateAfterBindUniformBuffers == rhs.maxDescriptorSetUpdateAfterBindUniformBuffers )
+ && ( maxDescriptorSetUpdateAfterBindUniformBuffersDynamic == rhs.maxDescriptorSetUpdateAfterBindUniformBuffersDynamic )
+ && ( maxDescriptorSetUpdateAfterBindStorageBuffers == rhs.maxDescriptorSetUpdateAfterBindStorageBuffers )
+ && ( maxDescriptorSetUpdateAfterBindStorageBuffersDynamic == rhs.maxDescriptorSetUpdateAfterBindStorageBuffersDynamic )
+ && ( maxDescriptorSetUpdateAfterBindSampledImages == rhs.maxDescriptorSetUpdateAfterBindSampledImages )
+ && ( maxDescriptorSetUpdateAfterBindStorageImages == rhs.maxDescriptorSetUpdateAfterBindStorageImages )
+ && ( maxDescriptorSetUpdateAfterBindInputAttachments == rhs.maxDescriptorSetUpdateAfterBindInputAttachments )
+ && ( supportedDepthResolveModes == rhs.supportedDepthResolveModes )
+ && ( supportedStencilResolveModes == rhs.supportedStencilResolveModes )
+ && ( independentResolveNone == rhs.independentResolveNone )
+ && ( independentResolve == rhs.independentResolve )
+ && ( filterMinmaxSingleComponentFormats == rhs.filterMinmaxSingleComponentFormats )
+ && ( filterMinmaxImageComponentMapping == rhs.filterMinmaxImageComponentMapping )
+ && ( maxTimelineSemaphoreValueDifference == rhs.maxTimelineSemaphoreValueDifference )
+ && ( framebufferIntegerColorSampleCounts == rhs.framebufferIntegerColorSampleCounts );
+ }
+
+ bool operator!=( PhysicalDeviceVulkan12Properties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceVulkan12Properties;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DriverId driverID = VULKAN_HPP_NAMESPACE::DriverId::eAmdProprietary;
+ char driverName[VK_MAX_DRIVER_NAME_SIZE] = {};
+ char driverInfo[VK_MAX_DRIVER_INFO_SIZE] = {};
+ VULKAN_HPP_NAMESPACE::ConformanceVersion conformanceVersion = {};
+ VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence denormBehaviorIndependence = VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence::e32BitOnly;
+ VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence roundingModeIndependence = VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence::e32BitOnly;
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat64 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat64 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat64 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat64 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat16 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat32 = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat64 = {};
+ uint32_t maxUpdateAfterBindDescriptorsInAllPools = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexingNative = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexingNative = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexingNative = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexingNative = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexingNative = {};
+ VULKAN_HPP_NAMESPACE::Bool32 robustBufferAccessUpdateAfterBind = {};
+ VULKAN_HPP_NAMESPACE::Bool32 quadDivergentImplicitLod = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindSamplers = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages = {};
+ uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments = {};
+ uint32_t maxPerStageUpdateAfterBindResources = {};
+ uint32_t maxDescriptorSetUpdateAfterBindSamplers = {};
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers = {};
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = {};
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers = {};
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = {};
+ uint32_t maxDescriptorSetUpdateAfterBindSampledImages = {};
+ uint32_t maxDescriptorSetUpdateAfterBindStorageImages = {};
+ uint32_t maxDescriptorSetUpdateAfterBindInputAttachments = {};
+ VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedDepthResolveModes = {};
+ VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedStencilResolveModes = {};
+ VULKAN_HPP_NAMESPACE::Bool32 independentResolveNone = {};
+ VULKAN_HPP_NAMESPACE::Bool32 independentResolve = {};
+ VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxSingleComponentFormats = {};
+ VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxImageComponentMapping = {};
+ uint64_t maxTimelineSemaphoreValueDifference = {};
+ VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferIntegerColorSampleCounts = {};
+ };
+ static_assert( sizeof( PhysicalDeviceVulkan12Properties ) == sizeof( VkPhysicalDeviceVulkan12Properties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceVulkan12Properties>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceVulkanMemoryModelFeatures
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceVulkanMemoryModelFeatures( VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModel_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelDeviceScope_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelAvailabilityVisibilityChains_ = {} ) VULKAN_HPP_NOEXCEPT
+ : vulkanMemoryModel( vulkanMemoryModel_ )
+ , vulkanMemoryModelDeviceScope( vulkanMemoryModelDeviceScope_ )
+ , vulkanMemoryModelAvailabilityVisibilityChains( vulkanMemoryModelAvailabilityVisibilityChains_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkanMemoryModelFeatures & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkanMemoryModelFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkanMemoryModelFeatures ) - offsetof( PhysicalDeviceVulkanMemoryModelFeatures, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceVulkanMemoryModelFeatures( VkPhysicalDeviceVulkanMemoryModelFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceVulkanMemoryModelFeatures& operator=( VkPhysicalDeviceVulkanMemoryModelFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceVulkanMemoryModelFeatures const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceVulkanMemoryModelFeatures & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkanMemoryModelFeatures & setVulkanMemoryModel( VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModel_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vulkanMemoryModel = vulkanMemoryModel_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkanMemoryModelFeatures & setVulkanMemoryModelDeviceScope( VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelDeviceScope_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vulkanMemoryModelDeviceScope = vulkanMemoryModelDeviceScope_;
+ return *this;
+ }
+
+ PhysicalDeviceVulkanMemoryModelFeatures & setVulkanMemoryModelAvailabilityVisibilityChains( VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelAvailabilityVisibilityChains_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vulkanMemoryModelAvailabilityVisibilityChains = vulkanMemoryModelAvailabilityVisibilityChains_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceVulkanMemoryModelFeatures const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceVulkanMemoryModelFeatures*>( this );
+ }
+
+ operator VkPhysicalDeviceVulkanMemoryModelFeatures &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceVulkanMemoryModelFeatures*>( this );
+ }
+
+ bool operator==( PhysicalDeviceVulkanMemoryModelFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( vulkanMemoryModel == rhs.vulkanMemoryModel )
+ && ( vulkanMemoryModelDeviceScope == rhs.vulkanMemoryModelDeviceScope )
+ && ( vulkanMemoryModelAvailabilityVisibilityChains == rhs.vulkanMemoryModelAvailabilityVisibilityChains );
+ }
+
+ bool operator!=( PhysicalDeviceVulkanMemoryModelFeatures const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceVulkanMemoryModelFeatures;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModel = {};
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelDeviceScope = {};
+ VULKAN_HPP_NAMESPACE::Bool32 vulkanMemoryModelAvailabilityVisibilityChains = {};
+ };
+ static_assert( sizeof( PhysicalDeviceVulkanMemoryModelFeatures ) == sizeof( VkPhysicalDeviceVulkanMemoryModelFeatures ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceVulkanMemoryModelFeatures>::value, "struct wrapper is not a standard layout!" );
+
+ struct PhysicalDeviceYcbcrImageArraysFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR PhysicalDeviceYcbcrImageArraysFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 ycbcrImageArrays_ = {} ) VULKAN_HPP_NOEXCEPT
+ : ycbcrImageArrays( ycbcrImageArrays_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrImageArraysFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrImageArraysFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrImageArraysFeaturesEXT ) - offsetof( PhysicalDeviceYcbcrImageArraysFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ PhysicalDeviceYcbcrImageArraysFeaturesEXT( VkPhysicalDeviceYcbcrImageArraysFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PhysicalDeviceYcbcrImageArraysFeaturesEXT& operator=( VkPhysicalDeviceYcbcrImageArraysFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceYcbcrImageArraysFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ PhysicalDeviceYcbcrImageArraysFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PhysicalDeviceYcbcrImageArraysFeaturesEXT & setYcbcrImageArrays( VULKAN_HPP_NAMESPACE::Bool32 ycbcrImageArrays_ ) VULKAN_HPP_NOEXCEPT
+ {
+ ycbcrImageArrays = ycbcrImageArrays_;
+ return *this;
+ }
+
+ operator VkPhysicalDeviceYcbcrImageArraysFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPhysicalDeviceYcbcrImageArraysFeaturesEXT*>( this );
+ }
+
+ operator VkPhysicalDeviceYcbcrImageArraysFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPhysicalDeviceYcbcrImageArraysFeaturesEXT*>( this );
+ }
+
+ bool operator==( PhysicalDeviceYcbcrImageArraysFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( ycbcrImageArrays == rhs.ycbcrImageArrays );
+ }
+
+ bool operator!=( PhysicalDeviceYcbcrImageArraysFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceYcbcrImageArraysFeaturesEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 ycbcrImageArrays = {};
+ };
+ static_assert( sizeof( PhysicalDeviceYcbcrImageArraysFeaturesEXT ) == sizeof( VkPhysicalDeviceYcbcrImageArraysFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PhysicalDeviceYcbcrImageArraysFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineCacheCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineCacheCreateInfo( VULKAN_HPP_NAMESPACE::PipelineCacheCreateFlags flags_ = {},
+ size_t initialDataSize_ = {},
+ const void* pInitialData_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , initialDataSize( initialDataSize_ )
+ , pInitialData( pInitialData_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineCacheCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineCacheCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineCacheCreateInfo ) - offsetof( PipelineCacheCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineCacheCreateInfo( VkPipelineCacheCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineCacheCreateInfo& operator=( VkPipelineCacheCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineCacheCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineCacheCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineCacheCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineCacheCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineCacheCreateInfo & setInitialDataSize( size_t initialDataSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ initialDataSize = initialDataSize_;
+ return *this;
+ }
+
+ PipelineCacheCreateInfo & setPInitialData( const void* pInitialData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pInitialData = pInitialData_;
+ return *this;
+ }
+
+ operator VkPipelineCacheCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineCacheCreateInfo*>( this );
+ }
+
+ operator VkPipelineCacheCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineCacheCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineCacheCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( initialDataSize == rhs.initialDataSize )
+ && ( pInitialData == rhs.pInitialData );
+ }
+
+ bool operator!=( PipelineCacheCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineCacheCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineCacheCreateFlags flags = {};
+ size_t initialDataSize = {};
+ const void* pInitialData = {};
+ };
+ static_assert( sizeof( PipelineCacheCreateInfo ) == sizeof( VkPipelineCacheCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineCacheCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineColorBlendAdvancedStateCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PipelineColorBlendAdvancedStateCreateInfoEXT( VULKAN_HPP_NAMESPACE::Bool32 srcPremultiplied_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 dstPremultiplied_ = {},
+ VULKAN_HPP_NAMESPACE::BlendOverlapEXT blendOverlap_ = VULKAN_HPP_NAMESPACE::BlendOverlapEXT::eUncorrelated ) VULKAN_HPP_NOEXCEPT
+ : srcPremultiplied( srcPremultiplied_ )
+ , dstPremultiplied( dstPremultiplied_ )
+ , blendOverlap( blendOverlap_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineColorBlendAdvancedStateCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PipelineColorBlendAdvancedStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineColorBlendAdvancedStateCreateInfoEXT ) - offsetof( PipelineColorBlendAdvancedStateCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PipelineColorBlendAdvancedStateCreateInfoEXT( VkPipelineColorBlendAdvancedStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineColorBlendAdvancedStateCreateInfoEXT& operator=( VkPipelineColorBlendAdvancedStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineColorBlendAdvancedStateCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PipelineColorBlendAdvancedStateCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineColorBlendAdvancedStateCreateInfoEXT & setSrcPremultiplied( VULKAN_HPP_NAMESPACE::Bool32 srcPremultiplied_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcPremultiplied = srcPremultiplied_;
+ return *this;
+ }
+
+ PipelineColorBlendAdvancedStateCreateInfoEXT & setDstPremultiplied( VULKAN_HPP_NAMESPACE::Bool32 dstPremultiplied_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstPremultiplied = dstPremultiplied_;
+ return *this;
+ }
+
+ PipelineColorBlendAdvancedStateCreateInfoEXT & setBlendOverlap( VULKAN_HPP_NAMESPACE::BlendOverlapEXT blendOverlap_ ) VULKAN_HPP_NOEXCEPT
+ {
+ blendOverlap = blendOverlap_;
+ return *this;
+ }
+
+ operator VkPipelineColorBlendAdvancedStateCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineColorBlendAdvancedStateCreateInfoEXT*>( this );
+ }
+
+ operator VkPipelineColorBlendAdvancedStateCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineColorBlendAdvancedStateCreateInfoEXT*>( this );
+ }
+
+ bool operator==( PipelineColorBlendAdvancedStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( srcPremultiplied == rhs.srcPremultiplied )
+ && ( dstPremultiplied == rhs.dstPremultiplied )
+ && ( blendOverlap == rhs.blendOverlap );
+ }
+
+ bool operator!=( PipelineColorBlendAdvancedStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineColorBlendAdvancedStateCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 srcPremultiplied = {};
+ VULKAN_HPP_NAMESPACE::Bool32 dstPremultiplied = {};
+ VULKAN_HPP_NAMESPACE::BlendOverlapEXT blendOverlap = VULKAN_HPP_NAMESPACE::BlendOverlapEXT::eUncorrelated;
+ };
+ static_assert( sizeof( PipelineColorBlendAdvancedStateCreateInfoEXT ) == sizeof( VkPipelineColorBlendAdvancedStateCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineColorBlendAdvancedStateCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineCompilerControlCreateInfoAMD
+ {
+ VULKAN_HPP_CONSTEXPR PipelineCompilerControlCreateInfoAMD( VULKAN_HPP_NAMESPACE::PipelineCompilerControlFlagsAMD compilerControlFlags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : compilerControlFlags( compilerControlFlags_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineCompilerControlCreateInfoAMD & operator=( VULKAN_HPP_NAMESPACE::PipelineCompilerControlCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineCompilerControlCreateInfoAMD ) - offsetof( PipelineCompilerControlCreateInfoAMD, pNext ) );
+ return *this;
+ }
+
+ PipelineCompilerControlCreateInfoAMD( VkPipelineCompilerControlCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineCompilerControlCreateInfoAMD& operator=( VkPipelineCompilerControlCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineCompilerControlCreateInfoAMD const *>(&rhs);
+ return *this;
+ }
+
+ PipelineCompilerControlCreateInfoAMD & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineCompilerControlCreateInfoAMD & setCompilerControlFlags( VULKAN_HPP_NAMESPACE::PipelineCompilerControlFlagsAMD compilerControlFlags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ compilerControlFlags = compilerControlFlags_;
+ return *this;
+ }
+
+ operator VkPipelineCompilerControlCreateInfoAMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineCompilerControlCreateInfoAMD*>( this );
+ }
+
+ operator VkPipelineCompilerControlCreateInfoAMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineCompilerControlCreateInfoAMD*>( this );
+ }
+
+ bool operator==( PipelineCompilerControlCreateInfoAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( compilerControlFlags == rhs.compilerControlFlags );
+ }
+
+ bool operator!=( PipelineCompilerControlCreateInfoAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineCompilerControlCreateInfoAMD;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineCompilerControlFlagsAMD compilerControlFlags = {};
+ };
+ static_assert( sizeof( PipelineCompilerControlCreateInfoAMD ) == sizeof( VkPipelineCompilerControlCreateInfoAMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineCompilerControlCreateInfoAMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineCoverageModulationStateCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR PipelineCoverageModulationStateCreateInfoNV( VULKAN_HPP_NAMESPACE::PipelineCoverageModulationStateCreateFlagsNV flags_ = {},
+ VULKAN_HPP_NAMESPACE::CoverageModulationModeNV coverageModulationMode_ = VULKAN_HPP_NAMESPACE::CoverageModulationModeNV::eNone,
+ VULKAN_HPP_NAMESPACE::Bool32 coverageModulationTableEnable_ = {},
+ uint32_t coverageModulationTableCount_ = {},
+ const float* pCoverageModulationTable_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , coverageModulationMode( coverageModulationMode_ )
+ , coverageModulationTableEnable( coverageModulationTableEnable_ )
+ , coverageModulationTableCount( coverageModulationTableCount_ )
+ , pCoverageModulationTable( pCoverageModulationTable_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineCoverageModulationStateCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::PipelineCoverageModulationStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineCoverageModulationStateCreateInfoNV ) - offsetof( PipelineCoverageModulationStateCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ PipelineCoverageModulationStateCreateInfoNV( VkPipelineCoverageModulationStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineCoverageModulationStateCreateInfoNV& operator=( VkPipelineCoverageModulationStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineCoverageModulationStateCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ PipelineCoverageModulationStateCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineCoverageModulationStateCreateInfoNV & setFlags( VULKAN_HPP_NAMESPACE::PipelineCoverageModulationStateCreateFlagsNV flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineCoverageModulationStateCreateInfoNV & setCoverageModulationMode( VULKAN_HPP_NAMESPACE::CoverageModulationModeNV coverageModulationMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ coverageModulationMode = coverageModulationMode_;
+ return *this;
+ }
+
+ PipelineCoverageModulationStateCreateInfoNV & setCoverageModulationTableEnable( VULKAN_HPP_NAMESPACE::Bool32 coverageModulationTableEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ coverageModulationTableEnable = coverageModulationTableEnable_;
+ return *this;
+ }
+
+ PipelineCoverageModulationStateCreateInfoNV & setCoverageModulationTableCount( uint32_t coverageModulationTableCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ coverageModulationTableCount = coverageModulationTableCount_;
+ return *this;
+ }
+
+ PipelineCoverageModulationStateCreateInfoNV & setPCoverageModulationTable( const float* pCoverageModulationTable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pCoverageModulationTable = pCoverageModulationTable_;
+ return *this;
+ }
+
+ operator VkPipelineCoverageModulationStateCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineCoverageModulationStateCreateInfoNV*>( this );
+ }
+
+ operator VkPipelineCoverageModulationStateCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineCoverageModulationStateCreateInfoNV*>( this );
+ }
+
+ bool operator==( PipelineCoverageModulationStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( coverageModulationMode == rhs.coverageModulationMode )
+ && ( coverageModulationTableEnable == rhs.coverageModulationTableEnable )
+ && ( coverageModulationTableCount == rhs.coverageModulationTableCount )
+ && ( pCoverageModulationTable == rhs.pCoverageModulationTable );
+ }
+
+ bool operator!=( PipelineCoverageModulationStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineCoverageModulationStateCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineCoverageModulationStateCreateFlagsNV flags = {};
+ VULKAN_HPP_NAMESPACE::CoverageModulationModeNV coverageModulationMode = VULKAN_HPP_NAMESPACE::CoverageModulationModeNV::eNone;
+ VULKAN_HPP_NAMESPACE::Bool32 coverageModulationTableEnable = {};
+ uint32_t coverageModulationTableCount = {};
+ const float* pCoverageModulationTable = {};
+ };
+ static_assert( sizeof( PipelineCoverageModulationStateCreateInfoNV ) == sizeof( VkPipelineCoverageModulationStateCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineCoverageModulationStateCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineCoverageReductionStateCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR PipelineCoverageReductionStateCreateInfoNV( VULKAN_HPP_NAMESPACE::PipelineCoverageReductionStateCreateFlagsNV flags_ = {},
+ VULKAN_HPP_NAMESPACE::CoverageReductionModeNV coverageReductionMode_ = VULKAN_HPP_NAMESPACE::CoverageReductionModeNV::eMerge ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , coverageReductionMode( coverageReductionMode_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineCoverageReductionStateCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::PipelineCoverageReductionStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineCoverageReductionStateCreateInfoNV ) - offsetof( PipelineCoverageReductionStateCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ PipelineCoverageReductionStateCreateInfoNV( VkPipelineCoverageReductionStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineCoverageReductionStateCreateInfoNV& operator=( VkPipelineCoverageReductionStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineCoverageReductionStateCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ PipelineCoverageReductionStateCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineCoverageReductionStateCreateInfoNV & setFlags( VULKAN_HPP_NAMESPACE::PipelineCoverageReductionStateCreateFlagsNV flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineCoverageReductionStateCreateInfoNV & setCoverageReductionMode( VULKAN_HPP_NAMESPACE::CoverageReductionModeNV coverageReductionMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ coverageReductionMode = coverageReductionMode_;
+ return *this;
+ }
+
+ operator VkPipelineCoverageReductionStateCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineCoverageReductionStateCreateInfoNV*>( this );
+ }
+
+ operator VkPipelineCoverageReductionStateCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineCoverageReductionStateCreateInfoNV*>( this );
+ }
+
+ bool operator==( PipelineCoverageReductionStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( coverageReductionMode == rhs.coverageReductionMode );
+ }
+
+ bool operator!=( PipelineCoverageReductionStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineCoverageReductionStateCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineCoverageReductionStateCreateFlagsNV flags = {};
+ VULKAN_HPP_NAMESPACE::CoverageReductionModeNV coverageReductionMode = VULKAN_HPP_NAMESPACE::CoverageReductionModeNV::eMerge;
+ };
+ static_assert( sizeof( PipelineCoverageReductionStateCreateInfoNV ) == sizeof( VkPipelineCoverageReductionStateCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineCoverageReductionStateCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineCoverageToColorStateCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR PipelineCoverageToColorStateCreateInfoNV( VULKAN_HPP_NAMESPACE::PipelineCoverageToColorStateCreateFlagsNV flags_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 coverageToColorEnable_ = {},
+ uint32_t coverageToColorLocation_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , coverageToColorEnable( coverageToColorEnable_ )
+ , coverageToColorLocation( coverageToColorLocation_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineCoverageToColorStateCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::PipelineCoverageToColorStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineCoverageToColorStateCreateInfoNV ) - offsetof( PipelineCoverageToColorStateCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ PipelineCoverageToColorStateCreateInfoNV( VkPipelineCoverageToColorStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineCoverageToColorStateCreateInfoNV& operator=( VkPipelineCoverageToColorStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineCoverageToColorStateCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ PipelineCoverageToColorStateCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineCoverageToColorStateCreateInfoNV & setFlags( VULKAN_HPP_NAMESPACE::PipelineCoverageToColorStateCreateFlagsNV flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineCoverageToColorStateCreateInfoNV & setCoverageToColorEnable( VULKAN_HPP_NAMESPACE::Bool32 coverageToColorEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ coverageToColorEnable = coverageToColorEnable_;
+ return *this;
+ }
+
+ PipelineCoverageToColorStateCreateInfoNV & setCoverageToColorLocation( uint32_t coverageToColorLocation_ ) VULKAN_HPP_NOEXCEPT
+ {
+ coverageToColorLocation = coverageToColorLocation_;
+ return *this;
+ }
+
+ operator VkPipelineCoverageToColorStateCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineCoverageToColorStateCreateInfoNV*>( this );
+ }
+
+ operator VkPipelineCoverageToColorStateCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineCoverageToColorStateCreateInfoNV*>( this );
+ }
+
+ bool operator==( PipelineCoverageToColorStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( coverageToColorEnable == rhs.coverageToColorEnable )
+ && ( coverageToColorLocation == rhs.coverageToColorLocation );
+ }
+
+ bool operator!=( PipelineCoverageToColorStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineCoverageToColorStateCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineCoverageToColorStateCreateFlagsNV flags = {};
+ VULKAN_HPP_NAMESPACE::Bool32 coverageToColorEnable = {};
+ uint32_t coverageToColorLocation = {};
+ };
+ static_assert( sizeof( PipelineCoverageToColorStateCreateInfoNV ) == sizeof( VkPipelineCoverageToColorStateCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineCoverageToColorStateCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineCreationFeedbackEXT
+ {
+ PipelineCreationFeedbackEXT( VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackFlagsEXT flags_ = {},
+ uint64_t duration_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , duration( duration_ )
+ {}
+
+ PipelineCreationFeedbackEXT( VkPipelineCreationFeedbackEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineCreationFeedbackEXT& operator=( VkPipelineCreationFeedbackEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPipelineCreationFeedbackEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineCreationFeedbackEXT*>( this );
+ }
+
+ operator VkPipelineCreationFeedbackEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineCreationFeedbackEXT*>( this );
+ }
+
+ bool operator==( PipelineCreationFeedbackEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( flags == rhs.flags )
+ && ( duration == rhs.duration );
+ }
+
+ bool operator!=( PipelineCreationFeedbackEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackFlagsEXT flags = {};
+ uint64_t duration = {};
+ };
+ static_assert( sizeof( PipelineCreationFeedbackEXT ) == sizeof( VkPipelineCreationFeedbackEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineCreationFeedbackEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineCreationFeedbackCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PipelineCreationFeedbackCreateInfoEXT( VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackEXT* pPipelineCreationFeedback_ = {},
+ uint32_t pipelineStageCreationFeedbackCount_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pPipelineCreationFeedback( pPipelineCreationFeedback_ )
+ , pipelineStageCreationFeedbackCount( pipelineStageCreationFeedbackCount_ )
+ , pPipelineStageCreationFeedbacks( pPipelineStageCreationFeedbacks_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackCreateInfoEXT ) - offsetof( PipelineCreationFeedbackCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PipelineCreationFeedbackCreateInfoEXT( VkPipelineCreationFeedbackCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineCreationFeedbackCreateInfoEXT& operator=( VkPipelineCreationFeedbackCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PipelineCreationFeedbackCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineCreationFeedbackCreateInfoEXT & setPPipelineCreationFeedback( VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackEXT* pPipelineCreationFeedback_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pPipelineCreationFeedback = pPipelineCreationFeedback_;
+ return *this;
+ }
+
+ PipelineCreationFeedbackCreateInfoEXT & setPipelineStageCreationFeedbackCount( uint32_t pipelineStageCreationFeedbackCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineStageCreationFeedbackCount = pipelineStageCreationFeedbackCount_;
+ return *this;
+ }
+
+ PipelineCreationFeedbackCreateInfoEXT & setPPipelineStageCreationFeedbacks( VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pPipelineStageCreationFeedbacks = pPipelineStageCreationFeedbacks_;
+ return *this;
+ }
+
+ operator VkPipelineCreationFeedbackCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineCreationFeedbackCreateInfoEXT*>( this );
+ }
+
+ operator VkPipelineCreationFeedbackCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineCreationFeedbackCreateInfoEXT*>( this );
+ }
+
+ bool operator==( PipelineCreationFeedbackCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pPipelineCreationFeedback == rhs.pPipelineCreationFeedback )
+ && ( pipelineStageCreationFeedbackCount == rhs.pipelineStageCreationFeedbackCount )
+ && ( pPipelineStageCreationFeedbacks == rhs.pPipelineStageCreationFeedbacks );
+ }
+
+ bool operator!=( PipelineCreationFeedbackCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineCreationFeedbackCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackEXT* pPipelineCreationFeedback = {};
+ uint32_t pipelineStageCreationFeedbackCount = {};
+ VULKAN_HPP_NAMESPACE::PipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks = {};
+ };
+ static_assert( sizeof( PipelineCreationFeedbackCreateInfoEXT ) == sizeof( VkPipelineCreationFeedbackCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineCreationFeedbackCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineDiscardRectangleStateCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PipelineDiscardRectangleStateCreateInfoEXT( VULKAN_HPP_NAMESPACE::PipelineDiscardRectangleStateCreateFlagsEXT flags_ = {},
+ VULKAN_HPP_NAMESPACE::DiscardRectangleModeEXT discardRectangleMode_ = VULKAN_HPP_NAMESPACE::DiscardRectangleModeEXT::eInclusive,
+ uint32_t discardRectangleCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Rect2D* pDiscardRectangles_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , discardRectangleMode( discardRectangleMode_ )
+ , discardRectangleCount( discardRectangleCount_ )
+ , pDiscardRectangles( pDiscardRectangles_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineDiscardRectangleStateCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PipelineDiscardRectangleStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineDiscardRectangleStateCreateInfoEXT ) - offsetof( PipelineDiscardRectangleStateCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PipelineDiscardRectangleStateCreateInfoEXT( VkPipelineDiscardRectangleStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineDiscardRectangleStateCreateInfoEXT& operator=( VkPipelineDiscardRectangleStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineDiscardRectangleStateCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PipelineDiscardRectangleStateCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineDiscardRectangleStateCreateInfoEXT & setFlags( VULKAN_HPP_NAMESPACE::PipelineDiscardRectangleStateCreateFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineDiscardRectangleStateCreateInfoEXT & setDiscardRectangleMode( VULKAN_HPP_NAMESPACE::DiscardRectangleModeEXT discardRectangleMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ discardRectangleMode = discardRectangleMode_;
+ return *this;
+ }
+
+ PipelineDiscardRectangleStateCreateInfoEXT & setDiscardRectangleCount( uint32_t discardRectangleCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ discardRectangleCount = discardRectangleCount_;
+ return *this;
+ }
+
+ PipelineDiscardRectangleStateCreateInfoEXT & setPDiscardRectangles( const VULKAN_HPP_NAMESPACE::Rect2D* pDiscardRectangles_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDiscardRectangles = pDiscardRectangles_;
+ return *this;
+ }
+
+ operator VkPipelineDiscardRectangleStateCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineDiscardRectangleStateCreateInfoEXT*>( this );
+ }
+
+ operator VkPipelineDiscardRectangleStateCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineDiscardRectangleStateCreateInfoEXT*>( this );
+ }
+
+ bool operator==( PipelineDiscardRectangleStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( discardRectangleMode == rhs.discardRectangleMode )
+ && ( discardRectangleCount == rhs.discardRectangleCount )
+ && ( pDiscardRectangles == rhs.pDiscardRectangles );
+ }
+
+ bool operator!=( PipelineDiscardRectangleStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineDiscardRectangleStateCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineDiscardRectangleStateCreateFlagsEXT flags = {};
+ VULKAN_HPP_NAMESPACE::DiscardRectangleModeEXT discardRectangleMode = VULKAN_HPP_NAMESPACE::DiscardRectangleModeEXT::eInclusive;
+ uint32_t discardRectangleCount = {};
+ const VULKAN_HPP_NAMESPACE::Rect2D* pDiscardRectangles = {};
+ };
+ static_assert( sizeof( PipelineDiscardRectangleStateCreateInfoEXT ) == sizeof( VkPipelineDiscardRectangleStateCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineDiscardRectangleStateCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineExecutableInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR PipelineExecutableInfoKHR( VULKAN_HPP_NAMESPACE::Pipeline pipeline_ = {},
+ uint32_t executableIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pipeline( pipeline_ )
+ , executableIndex( executableIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineExecutableInfoKHR & operator=( VULKAN_HPP_NAMESPACE::PipelineExecutableInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineExecutableInfoKHR ) - offsetof( PipelineExecutableInfoKHR, pNext ) );
+ return *this;
+ }
+
+ PipelineExecutableInfoKHR( VkPipelineExecutableInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineExecutableInfoKHR& operator=( VkPipelineExecutableInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineExecutableInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ PipelineExecutableInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineExecutableInfoKHR & setPipeline( VULKAN_HPP_NAMESPACE::Pipeline pipeline_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipeline = pipeline_;
+ return *this;
+ }
+
+ PipelineExecutableInfoKHR & setExecutableIndex( uint32_t executableIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ executableIndex = executableIndex_;
+ return *this;
+ }
+
+ operator VkPipelineExecutableInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineExecutableInfoKHR*>( this );
+ }
+
+ operator VkPipelineExecutableInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineExecutableInfoKHR*>( this );
+ }
+
+ bool operator==( PipelineExecutableInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pipeline == rhs.pipeline )
+ && ( executableIndex == rhs.executableIndex );
+ }
+
+ bool operator!=( PipelineExecutableInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineExecutableInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Pipeline pipeline = {};
+ uint32_t executableIndex = {};
+ };
+ static_assert( sizeof( PipelineExecutableInfoKHR ) == sizeof( VkPipelineExecutableInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineExecutableInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineExecutableInternalRepresentationKHR
+ {
+ PipelineExecutableInternalRepresentationKHR( std::array<char,VK_MAX_DESCRIPTION_SIZE> const& name_ = {},
+ std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 isText_ = {},
+ size_t dataSize_ = {},
+ void* pData_ = {} ) VULKAN_HPP_NOEXCEPT
+ : name{}
+ , description{}
+ , isText( isText_ )
+ , dataSize( dataSize_ )
+ , pData( pData_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( name, name_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PipelineExecutableInternalRepresentationKHR & operator=( VULKAN_HPP_NAMESPACE::PipelineExecutableInternalRepresentationKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineExecutableInternalRepresentationKHR ) - offsetof( PipelineExecutableInternalRepresentationKHR, pNext ) );
+ return *this;
+ }
+
+ PipelineExecutableInternalRepresentationKHR( VkPipelineExecutableInternalRepresentationKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineExecutableInternalRepresentationKHR& operator=( VkPipelineExecutableInternalRepresentationKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineExecutableInternalRepresentationKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPipelineExecutableInternalRepresentationKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineExecutableInternalRepresentationKHR*>( this );
+ }
+
+ operator VkPipelineExecutableInternalRepresentationKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineExecutableInternalRepresentationKHR*>( this );
+ }
+
+ bool operator==( PipelineExecutableInternalRepresentationKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memcmp( name, rhs.name, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
+ && ( memcmp( description, rhs.description, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
+ && ( isText == rhs.isText )
+ && ( dataSize == rhs.dataSize )
+ && ( pData == rhs.pData );
+ }
+
+ bool operator!=( PipelineExecutableInternalRepresentationKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineExecutableInternalRepresentationKHR;
+ void* pNext = {};
+ char name[VK_MAX_DESCRIPTION_SIZE] = {};
+ char description[VK_MAX_DESCRIPTION_SIZE] = {};
+ VULKAN_HPP_NAMESPACE::Bool32 isText = {};
+ size_t dataSize = {};
+ void* pData = {};
+ };
+ static_assert( sizeof( PipelineExecutableInternalRepresentationKHR ) == sizeof( VkPipelineExecutableInternalRepresentationKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineExecutableInternalRepresentationKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineExecutablePropertiesKHR
+ {
+ PipelineExecutablePropertiesKHR( VULKAN_HPP_NAMESPACE::ShaderStageFlags stages_ = {},
+ std::array<char,VK_MAX_DESCRIPTION_SIZE> const& name_ = {},
+ std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {},
+ uint32_t subgroupSize_ = {} ) VULKAN_HPP_NOEXCEPT
+ : stages( stages_ )
+ , name{}
+ , description{}
+ , subgroupSize( subgroupSize_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( name, name_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PipelineExecutablePropertiesKHR & operator=( VULKAN_HPP_NAMESPACE::PipelineExecutablePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineExecutablePropertiesKHR ) - offsetof( PipelineExecutablePropertiesKHR, pNext ) );
+ return *this;
+ }
+
+ PipelineExecutablePropertiesKHR( VkPipelineExecutablePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineExecutablePropertiesKHR& operator=( VkPipelineExecutablePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineExecutablePropertiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPipelineExecutablePropertiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineExecutablePropertiesKHR*>( this );
+ }
+
+ operator VkPipelineExecutablePropertiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineExecutablePropertiesKHR*>( this );
+ }
+
+ bool operator==( PipelineExecutablePropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( stages == rhs.stages )
+ && ( memcmp( name, rhs.name, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
+ && ( memcmp( description, rhs.description, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
+ && ( subgroupSize == rhs.subgroupSize );
+ }
+
+ bool operator!=( PipelineExecutablePropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineExecutablePropertiesKHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags stages = {};
+ char name[VK_MAX_DESCRIPTION_SIZE] = {};
+ char description[VK_MAX_DESCRIPTION_SIZE] = {};
+ uint32_t subgroupSize = {};
+ };
+ static_assert( sizeof( PipelineExecutablePropertiesKHR ) == sizeof( VkPipelineExecutablePropertiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineExecutablePropertiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ union PipelineExecutableStatisticValueKHR
+ {
+ VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticValueKHR & operator=( VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticValueKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( this, &rhs, sizeof( VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticValueKHR ) );
+ return *this;
+ }
+
+ operator VkPipelineExecutableStatisticValueKHR const&() const
+ {
+ return *reinterpret_cast<const VkPipelineExecutableStatisticValueKHR*>(this);
+ }
+
+ operator VkPipelineExecutableStatisticValueKHR &()
+ {
+ return *reinterpret_cast<VkPipelineExecutableStatisticValueKHR*>(this);
+ }
+
+#ifdef VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
+ VULKAN_HPP_NAMESPACE::Bool32 b32;
+ int64_t i64;
+ uint64_t u64;
+ double f64;
+#else
+ VkBool32 b32;
+ int64_t i64;
+ uint64_t u64;
+ double f64;
+#endif /*VULKAN_HPP_HAS_UNRESTRICTED_UNIONS*/
+ };
+
+ struct PipelineExecutableStatisticKHR
+ {
+ PipelineExecutableStatisticKHR( std::array<char,VK_MAX_DESCRIPTION_SIZE> const& name_ = {},
+ std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticFormatKHR format_ = VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticFormatKHR::eBool32,
+ VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticValueKHR value_ = {} ) VULKAN_HPP_NOEXCEPT
+ : name{}
+ , description{}
+ , format( format_ )
+ , value( value_ )
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( name, name_ );
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
+ }
+
+ VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticKHR & operator=( VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticKHR ) - offsetof( PipelineExecutableStatisticKHR, pNext ) );
+ return *this;
+ }
+
+ PipelineExecutableStatisticKHR( VkPipelineExecutableStatisticKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineExecutableStatisticKHR& operator=( VkPipelineExecutableStatisticKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPipelineExecutableStatisticKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineExecutableStatisticKHR*>( this );
+ }
+
+ operator VkPipelineExecutableStatisticKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineExecutableStatisticKHR*>( this );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineExecutableStatisticKHR;
+ void* pNext = {};
+ char name[VK_MAX_DESCRIPTION_SIZE] = {};
+ char description[VK_MAX_DESCRIPTION_SIZE] = {};
+ VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticFormatKHR format = VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticFormatKHR::eBool32;
+ VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticValueKHR value = {};
+ };
+ static_assert( sizeof( PipelineExecutableStatisticKHR ) == sizeof( VkPipelineExecutableStatisticKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineExecutableStatisticKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR PipelineInfoKHR( VULKAN_HPP_NAMESPACE::Pipeline pipeline_ = {} ) VULKAN_HPP_NOEXCEPT
+ : pipeline( pipeline_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineInfoKHR & operator=( VULKAN_HPP_NAMESPACE::PipelineInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineInfoKHR ) - offsetof( PipelineInfoKHR, pNext ) );
+ return *this;
+ }
+
+ PipelineInfoKHR( VkPipelineInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineInfoKHR& operator=( VkPipelineInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ PipelineInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineInfoKHR & setPipeline( VULKAN_HPP_NAMESPACE::Pipeline pipeline_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipeline = pipeline_;
+ return *this;
+ }
+
+ operator VkPipelineInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineInfoKHR*>( this );
+ }
+
+ operator VkPipelineInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineInfoKHR*>( this );
+ }
+
+ bool operator==( PipelineInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( pipeline == rhs.pipeline );
+ }
+
+ bool operator!=( PipelineInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Pipeline pipeline = {};
+ };
+ static_assert( sizeof( PipelineInfoKHR ) == sizeof( VkPipelineInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PushConstantRange
+ {
+ VULKAN_HPP_CONSTEXPR PushConstantRange( VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags_ = {},
+ uint32_t offset_ = {},
+ uint32_t size_ = {} ) VULKAN_HPP_NOEXCEPT
+ : stageFlags( stageFlags_ )
+ , offset( offset_ )
+ , size( size_ )
+ {}
+
+ PushConstantRange( VkPushConstantRange const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PushConstantRange& operator=( VkPushConstantRange const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PushConstantRange const *>(&rhs);
+ return *this;
+ }
+
+ PushConstantRange & setStageFlags( VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stageFlags = stageFlags_;
+ return *this;
+ }
+
+ PushConstantRange & setOffset( uint32_t offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ PushConstantRange & setSize( uint32_t size_ ) VULKAN_HPP_NOEXCEPT
+ {
+ size = size_;
+ return *this;
+ }
+
+ operator VkPushConstantRange const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPushConstantRange*>( this );
+ }
+
+ operator VkPushConstantRange &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPushConstantRange*>( this );
+ }
+
+ bool operator==( PushConstantRange const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( stageFlags == rhs.stageFlags )
+ && ( offset == rhs.offset )
+ && ( size == rhs.size );
+ }
+
+ bool operator!=( PushConstantRange const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags = {};
+ uint32_t offset = {};
+ uint32_t size = {};
+ };
+ static_assert( sizeof( PushConstantRange ) == sizeof( VkPushConstantRange ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PushConstantRange>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineLayoutCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineLayoutCreateInfo( VULKAN_HPP_NAMESPACE::PipelineLayoutCreateFlags flags_ = {},
+ uint32_t setLayoutCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DescriptorSetLayout* pSetLayouts_ = {},
+ uint32_t pushConstantRangeCount_ = {},
+ const VULKAN_HPP_NAMESPACE::PushConstantRange* pPushConstantRanges_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , setLayoutCount( setLayoutCount_ )
+ , pSetLayouts( pSetLayouts_ )
+ , pushConstantRangeCount( pushConstantRangeCount_ )
+ , pPushConstantRanges( pPushConstantRanges_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineLayoutCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineLayoutCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineLayoutCreateInfo ) - offsetof( PipelineLayoutCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineLayoutCreateInfo( VkPipelineLayoutCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineLayoutCreateInfo& operator=( VkPipelineLayoutCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineLayoutCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineLayoutCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineLayoutCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::PipelineLayoutCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineLayoutCreateInfo & setSetLayoutCount( uint32_t setLayoutCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ setLayoutCount = setLayoutCount_;
+ return *this;
+ }
+
+ PipelineLayoutCreateInfo & setPSetLayouts( const VULKAN_HPP_NAMESPACE::DescriptorSetLayout* pSetLayouts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSetLayouts = pSetLayouts_;
+ return *this;
+ }
+
+ PipelineLayoutCreateInfo & setPushConstantRangeCount( uint32_t pushConstantRangeCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pushConstantRangeCount = pushConstantRangeCount_;
+ return *this;
+ }
+
+ PipelineLayoutCreateInfo & setPPushConstantRanges( const VULKAN_HPP_NAMESPACE::PushConstantRange* pPushConstantRanges_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pPushConstantRanges = pPushConstantRanges_;
+ return *this;
+ }
+
+ operator VkPipelineLayoutCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineLayoutCreateInfo*>( this );
+ }
+
+ operator VkPipelineLayoutCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineLayoutCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineLayoutCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( setLayoutCount == rhs.setLayoutCount )
+ && ( pSetLayouts == rhs.pSetLayouts )
+ && ( pushConstantRangeCount == rhs.pushConstantRangeCount )
+ && ( pPushConstantRanges == rhs.pPushConstantRanges );
+ }
+
+ bool operator!=( PipelineLayoutCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineLayoutCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineLayoutCreateFlags flags = {};
+ uint32_t setLayoutCount = {};
+ const VULKAN_HPP_NAMESPACE::DescriptorSetLayout* pSetLayouts = {};
+ uint32_t pushConstantRangeCount = {};
+ const VULKAN_HPP_NAMESPACE::PushConstantRange* pPushConstantRanges = {};
+ };
+ static_assert( sizeof( PipelineLayoutCreateInfo ) == sizeof( VkPipelineLayoutCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineLayoutCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineRasterizationConservativeStateCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PipelineRasterizationConservativeStateCreateInfoEXT( VULKAN_HPP_NAMESPACE::PipelineRasterizationConservativeStateCreateFlagsEXT flags_ = {},
+ VULKAN_HPP_NAMESPACE::ConservativeRasterizationModeEXT conservativeRasterizationMode_ = VULKAN_HPP_NAMESPACE::ConservativeRasterizationModeEXT::eDisabled,
+ float extraPrimitiveOverestimationSize_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , conservativeRasterizationMode( conservativeRasterizationMode_ )
+ , extraPrimitiveOverestimationSize( extraPrimitiveOverestimationSize_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineRasterizationConservativeStateCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PipelineRasterizationConservativeStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineRasterizationConservativeStateCreateInfoEXT ) - offsetof( PipelineRasterizationConservativeStateCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PipelineRasterizationConservativeStateCreateInfoEXT( VkPipelineRasterizationConservativeStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineRasterizationConservativeStateCreateInfoEXT& operator=( VkPipelineRasterizationConservativeStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineRasterizationConservativeStateCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PipelineRasterizationConservativeStateCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineRasterizationConservativeStateCreateInfoEXT & setFlags( VULKAN_HPP_NAMESPACE::PipelineRasterizationConservativeStateCreateFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineRasterizationConservativeStateCreateInfoEXT & setConservativeRasterizationMode( VULKAN_HPP_NAMESPACE::ConservativeRasterizationModeEXT conservativeRasterizationMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ conservativeRasterizationMode = conservativeRasterizationMode_;
+ return *this;
+ }
+
+ PipelineRasterizationConservativeStateCreateInfoEXT & setExtraPrimitiveOverestimationSize( float extraPrimitiveOverestimationSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ extraPrimitiveOverestimationSize = extraPrimitiveOverestimationSize_;
+ return *this;
+ }
+
+ operator VkPipelineRasterizationConservativeStateCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineRasterizationConservativeStateCreateInfoEXT*>( this );
+ }
+
+ operator VkPipelineRasterizationConservativeStateCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineRasterizationConservativeStateCreateInfoEXT*>( this );
+ }
+
+ bool operator==( PipelineRasterizationConservativeStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( conservativeRasterizationMode == rhs.conservativeRasterizationMode )
+ && ( extraPrimitiveOverestimationSize == rhs.extraPrimitiveOverestimationSize );
+ }
+
+ bool operator!=( PipelineRasterizationConservativeStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineRasterizationConservativeStateCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineRasterizationConservativeStateCreateFlagsEXT flags = {};
+ VULKAN_HPP_NAMESPACE::ConservativeRasterizationModeEXT conservativeRasterizationMode = VULKAN_HPP_NAMESPACE::ConservativeRasterizationModeEXT::eDisabled;
+ float extraPrimitiveOverestimationSize = {};
+ };
+ static_assert( sizeof( PipelineRasterizationConservativeStateCreateInfoEXT ) == sizeof( VkPipelineRasterizationConservativeStateCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineRasterizationConservativeStateCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineRasterizationDepthClipStateCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PipelineRasterizationDepthClipStateCreateInfoEXT( VULKAN_HPP_NAMESPACE::PipelineRasterizationDepthClipStateCreateFlagsEXT flags_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 depthClipEnable_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , depthClipEnable( depthClipEnable_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineRasterizationDepthClipStateCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PipelineRasterizationDepthClipStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineRasterizationDepthClipStateCreateInfoEXT ) - offsetof( PipelineRasterizationDepthClipStateCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PipelineRasterizationDepthClipStateCreateInfoEXT( VkPipelineRasterizationDepthClipStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineRasterizationDepthClipStateCreateInfoEXT& operator=( VkPipelineRasterizationDepthClipStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineRasterizationDepthClipStateCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PipelineRasterizationDepthClipStateCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineRasterizationDepthClipStateCreateInfoEXT & setFlags( VULKAN_HPP_NAMESPACE::PipelineRasterizationDepthClipStateCreateFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineRasterizationDepthClipStateCreateInfoEXT & setDepthClipEnable( VULKAN_HPP_NAMESPACE::Bool32 depthClipEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthClipEnable = depthClipEnable_;
+ return *this;
+ }
+
+ operator VkPipelineRasterizationDepthClipStateCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineRasterizationDepthClipStateCreateInfoEXT*>( this );
+ }
+
+ operator VkPipelineRasterizationDepthClipStateCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineRasterizationDepthClipStateCreateInfoEXT*>( this );
+ }
+
+ bool operator==( PipelineRasterizationDepthClipStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( depthClipEnable == rhs.depthClipEnable );
+ }
+
+ bool operator!=( PipelineRasterizationDepthClipStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineRasterizationDepthClipStateCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineRasterizationDepthClipStateCreateFlagsEXT flags = {};
+ VULKAN_HPP_NAMESPACE::Bool32 depthClipEnable = {};
+ };
+ static_assert( sizeof( PipelineRasterizationDepthClipStateCreateInfoEXT ) == sizeof( VkPipelineRasterizationDepthClipStateCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineRasterizationDepthClipStateCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineRasterizationLineStateCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PipelineRasterizationLineStateCreateInfoEXT( VULKAN_HPP_NAMESPACE::LineRasterizationModeEXT lineRasterizationMode_ = VULKAN_HPP_NAMESPACE::LineRasterizationModeEXT::eDefault,
+ VULKAN_HPP_NAMESPACE::Bool32 stippledLineEnable_ = {},
+ uint32_t lineStippleFactor_ = {},
+ uint16_t lineStipplePattern_ = {} ) VULKAN_HPP_NOEXCEPT
+ : lineRasterizationMode( lineRasterizationMode_ )
+ , stippledLineEnable( stippledLineEnable_ )
+ , lineStippleFactor( lineStippleFactor_ )
+ , lineStipplePattern( lineStipplePattern_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineRasterizationLineStateCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PipelineRasterizationLineStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineRasterizationLineStateCreateInfoEXT ) - offsetof( PipelineRasterizationLineStateCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PipelineRasterizationLineStateCreateInfoEXT( VkPipelineRasterizationLineStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineRasterizationLineStateCreateInfoEXT& operator=( VkPipelineRasterizationLineStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineRasterizationLineStateCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PipelineRasterizationLineStateCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineRasterizationLineStateCreateInfoEXT & setLineRasterizationMode( VULKAN_HPP_NAMESPACE::LineRasterizationModeEXT lineRasterizationMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ lineRasterizationMode = lineRasterizationMode_;
+ return *this;
+ }
+
+ PipelineRasterizationLineStateCreateInfoEXT & setStippledLineEnable( VULKAN_HPP_NAMESPACE::Bool32 stippledLineEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stippledLineEnable = stippledLineEnable_;
+ return *this;
+ }
+
+ PipelineRasterizationLineStateCreateInfoEXT & setLineStippleFactor( uint32_t lineStippleFactor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ lineStippleFactor = lineStippleFactor_;
+ return *this;
+ }
+
+ PipelineRasterizationLineStateCreateInfoEXT & setLineStipplePattern( uint16_t lineStipplePattern_ ) VULKAN_HPP_NOEXCEPT
+ {
+ lineStipplePattern = lineStipplePattern_;
+ return *this;
+ }
+
+ operator VkPipelineRasterizationLineStateCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineRasterizationLineStateCreateInfoEXT*>( this );
+ }
+
+ operator VkPipelineRasterizationLineStateCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineRasterizationLineStateCreateInfoEXT*>( this );
+ }
+
+ bool operator==( PipelineRasterizationLineStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( lineRasterizationMode == rhs.lineRasterizationMode )
+ && ( stippledLineEnable == rhs.stippledLineEnable )
+ && ( lineStippleFactor == rhs.lineStippleFactor )
+ && ( lineStipplePattern == rhs.lineStipplePattern );
+ }
+
+ bool operator!=( PipelineRasterizationLineStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineRasterizationLineStateCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::LineRasterizationModeEXT lineRasterizationMode = VULKAN_HPP_NAMESPACE::LineRasterizationModeEXT::eDefault;
+ VULKAN_HPP_NAMESPACE::Bool32 stippledLineEnable = {};
+ uint32_t lineStippleFactor = {};
+ uint16_t lineStipplePattern = {};
+ };
+ static_assert( sizeof( PipelineRasterizationLineStateCreateInfoEXT ) == sizeof( VkPipelineRasterizationLineStateCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineRasterizationLineStateCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineRasterizationStateRasterizationOrderAMD
+ {
+ VULKAN_HPP_CONSTEXPR PipelineRasterizationStateRasterizationOrderAMD( VULKAN_HPP_NAMESPACE::RasterizationOrderAMD rasterizationOrder_ = VULKAN_HPP_NAMESPACE::RasterizationOrderAMD::eStrict ) VULKAN_HPP_NOEXCEPT
+ : rasterizationOrder( rasterizationOrder_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineRasterizationStateRasterizationOrderAMD & operator=( VULKAN_HPP_NAMESPACE::PipelineRasterizationStateRasterizationOrderAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineRasterizationStateRasterizationOrderAMD ) - offsetof( PipelineRasterizationStateRasterizationOrderAMD, pNext ) );
+ return *this;
+ }
+
+ PipelineRasterizationStateRasterizationOrderAMD( VkPipelineRasterizationStateRasterizationOrderAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineRasterizationStateRasterizationOrderAMD& operator=( VkPipelineRasterizationStateRasterizationOrderAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineRasterizationStateRasterizationOrderAMD const *>(&rhs);
+ return *this;
+ }
+
+ PipelineRasterizationStateRasterizationOrderAMD & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineRasterizationStateRasterizationOrderAMD & setRasterizationOrder( VULKAN_HPP_NAMESPACE::RasterizationOrderAMD rasterizationOrder_ ) VULKAN_HPP_NOEXCEPT
+ {
+ rasterizationOrder = rasterizationOrder_;
+ return *this;
+ }
+
+ operator VkPipelineRasterizationStateRasterizationOrderAMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineRasterizationStateRasterizationOrderAMD*>( this );
+ }
+
+ operator VkPipelineRasterizationStateRasterizationOrderAMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineRasterizationStateRasterizationOrderAMD*>( this );
+ }
+
+ bool operator==( PipelineRasterizationStateRasterizationOrderAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( rasterizationOrder == rhs.rasterizationOrder );
+ }
+
+ bool operator!=( PipelineRasterizationStateRasterizationOrderAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineRasterizationStateRasterizationOrderAMD;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::RasterizationOrderAMD rasterizationOrder = VULKAN_HPP_NAMESPACE::RasterizationOrderAMD::eStrict;
+ };
+ static_assert( sizeof( PipelineRasterizationStateRasterizationOrderAMD ) == sizeof( VkPipelineRasterizationStateRasterizationOrderAMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineRasterizationStateRasterizationOrderAMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineRasterizationStateStreamCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PipelineRasterizationStateStreamCreateInfoEXT( VULKAN_HPP_NAMESPACE::PipelineRasterizationStateStreamCreateFlagsEXT flags_ = {},
+ uint32_t rasterizationStream_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , rasterizationStream( rasterizationStream_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineRasterizationStateStreamCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PipelineRasterizationStateStreamCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineRasterizationStateStreamCreateInfoEXT ) - offsetof( PipelineRasterizationStateStreamCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PipelineRasterizationStateStreamCreateInfoEXT( VkPipelineRasterizationStateStreamCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineRasterizationStateStreamCreateInfoEXT& operator=( VkPipelineRasterizationStateStreamCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineRasterizationStateStreamCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PipelineRasterizationStateStreamCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineRasterizationStateStreamCreateInfoEXT & setFlags( VULKAN_HPP_NAMESPACE::PipelineRasterizationStateStreamCreateFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineRasterizationStateStreamCreateInfoEXT & setRasterizationStream( uint32_t rasterizationStream_ ) VULKAN_HPP_NOEXCEPT
+ {
+ rasterizationStream = rasterizationStream_;
+ return *this;
+ }
+
+ operator VkPipelineRasterizationStateStreamCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineRasterizationStateStreamCreateInfoEXT*>( this );
+ }
+
+ operator VkPipelineRasterizationStateStreamCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineRasterizationStateStreamCreateInfoEXT*>( this );
+ }
+
+ bool operator==( PipelineRasterizationStateStreamCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( rasterizationStream == rhs.rasterizationStream );
+ }
+
+ bool operator!=( PipelineRasterizationStateStreamCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineRasterizationStateStreamCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineRasterizationStateStreamCreateFlagsEXT flags = {};
+ uint32_t rasterizationStream = {};
+ };
+ static_assert( sizeof( PipelineRasterizationStateStreamCreateInfoEXT ) == sizeof( VkPipelineRasterizationStateStreamCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineRasterizationStateStreamCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineRepresentativeFragmentTestStateCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR PipelineRepresentativeFragmentTestStateCreateInfoNV( VULKAN_HPP_NAMESPACE::Bool32 representativeFragmentTestEnable_ = {} ) VULKAN_HPP_NOEXCEPT
+ : representativeFragmentTestEnable( representativeFragmentTestEnable_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineRepresentativeFragmentTestStateCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::PipelineRepresentativeFragmentTestStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineRepresentativeFragmentTestStateCreateInfoNV ) - offsetof( PipelineRepresentativeFragmentTestStateCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ PipelineRepresentativeFragmentTestStateCreateInfoNV( VkPipelineRepresentativeFragmentTestStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineRepresentativeFragmentTestStateCreateInfoNV& operator=( VkPipelineRepresentativeFragmentTestStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineRepresentativeFragmentTestStateCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ PipelineRepresentativeFragmentTestStateCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineRepresentativeFragmentTestStateCreateInfoNV & setRepresentativeFragmentTestEnable( VULKAN_HPP_NAMESPACE::Bool32 representativeFragmentTestEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ representativeFragmentTestEnable = representativeFragmentTestEnable_;
+ return *this;
+ }
+
+ operator VkPipelineRepresentativeFragmentTestStateCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineRepresentativeFragmentTestStateCreateInfoNV*>( this );
+ }
+
+ operator VkPipelineRepresentativeFragmentTestStateCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineRepresentativeFragmentTestStateCreateInfoNV*>( this );
+ }
+
+ bool operator==( PipelineRepresentativeFragmentTestStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( representativeFragmentTestEnable == rhs.representativeFragmentTestEnable );
+ }
+
+ bool operator!=( PipelineRepresentativeFragmentTestStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineRepresentativeFragmentTestStateCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 representativeFragmentTestEnable = {};
+ };
+ static_assert( sizeof( PipelineRepresentativeFragmentTestStateCreateInfoNV ) == sizeof( VkPipelineRepresentativeFragmentTestStateCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineRepresentativeFragmentTestStateCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineSampleLocationsStateCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PipelineSampleLocationsStateCreateInfoEXT( VULKAN_HPP_NAMESPACE::Bool32 sampleLocationsEnable_ = {},
+ VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT sampleLocationsInfo_ = {} ) VULKAN_HPP_NOEXCEPT
+ : sampleLocationsEnable( sampleLocationsEnable_ )
+ , sampleLocationsInfo( sampleLocationsInfo_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineSampleLocationsStateCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PipelineSampleLocationsStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineSampleLocationsStateCreateInfoEXT ) - offsetof( PipelineSampleLocationsStateCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PipelineSampleLocationsStateCreateInfoEXT( VkPipelineSampleLocationsStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineSampleLocationsStateCreateInfoEXT& operator=( VkPipelineSampleLocationsStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineSampleLocationsStateCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PipelineSampleLocationsStateCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineSampleLocationsStateCreateInfoEXT & setSampleLocationsEnable( VULKAN_HPP_NAMESPACE::Bool32 sampleLocationsEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleLocationsEnable = sampleLocationsEnable_;
+ return *this;
+ }
+
+ PipelineSampleLocationsStateCreateInfoEXT & setSampleLocationsInfo( VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT sampleLocationsInfo_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleLocationsInfo = sampleLocationsInfo_;
+ return *this;
+ }
+
+ operator VkPipelineSampleLocationsStateCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineSampleLocationsStateCreateInfoEXT*>( this );
+ }
+
+ operator VkPipelineSampleLocationsStateCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineSampleLocationsStateCreateInfoEXT*>( this );
+ }
+
+ bool operator==( PipelineSampleLocationsStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( sampleLocationsEnable == rhs.sampleLocationsEnable )
+ && ( sampleLocationsInfo == rhs.sampleLocationsInfo );
+ }
+
+ bool operator!=( PipelineSampleLocationsStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineSampleLocationsStateCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 sampleLocationsEnable = {};
+ VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT sampleLocationsInfo = {};
+ };
+ static_assert( sizeof( PipelineSampleLocationsStateCreateInfoEXT ) == sizeof( VkPipelineSampleLocationsStateCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineSampleLocationsStateCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT
+ {
+ PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT( uint32_t requiredSubgroupSize_ = {} ) VULKAN_HPP_NOEXCEPT
+ : requiredSubgroupSize( requiredSubgroupSize_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT ) - offsetof( PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT( VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT& operator=( VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT*>( this );
+ }
+
+ operator VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT*>( this );
+ }
+
+ bool operator==( PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( requiredSubgroupSize == rhs.requiredSubgroupSize );
+ }
+
+ bool operator!=( PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineShaderStageRequiredSubgroupSizeCreateInfoEXT;
+ void* pNext = {};
+ uint32_t requiredSubgroupSize = {};
+ };
+ static_assert( sizeof( PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT ) == sizeof( VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineTessellationDomainOriginStateCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR PipelineTessellationDomainOriginStateCreateInfo( VULKAN_HPP_NAMESPACE::TessellationDomainOrigin domainOrigin_ = VULKAN_HPP_NAMESPACE::TessellationDomainOrigin::eUpperLeft ) VULKAN_HPP_NOEXCEPT
+ : domainOrigin( domainOrigin_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineTessellationDomainOriginStateCreateInfo & operator=( VULKAN_HPP_NAMESPACE::PipelineTessellationDomainOriginStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineTessellationDomainOriginStateCreateInfo ) - offsetof( PipelineTessellationDomainOriginStateCreateInfo, pNext ) );
+ return *this;
+ }
+
+ PipelineTessellationDomainOriginStateCreateInfo( VkPipelineTessellationDomainOriginStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineTessellationDomainOriginStateCreateInfo& operator=( VkPipelineTessellationDomainOriginStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineTessellationDomainOriginStateCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ PipelineTessellationDomainOriginStateCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineTessellationDomainOriginStateCreateInfo & setDomainOrigin( VULKAN_HPP_NAMESPACE::TessellationDomainOrigin domainOrigin_ ) VULKAN_HPP_NOEXCEPT
+ {
+ domainOrigin = domainOrigin_;
+ return *this;
+ }
+
+ operator VkPipelineTessellationDomainOriginStateCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineTessellationDomainOriginStateCreateInfo*>( this );
+ }
+
+ operator VkPipelineTessellationDomainOriginStateCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineTessellationDomainOriginStateCreateInfo*>( this );
+ }
+
+ bool operator==( PipelineTessellationDomainOriginStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( domainOrigin == rhs.domainOrigin );
+ }
+
+ bool operator!=( PipelineTessellationDomainOriginStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineTessellationDomainOriginStateCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::TessellationDomainOrigin domainOrigin = VULKAN_HPP_NAMESPACE::TessellationDomainOrigin::eUpperLeft;
+ };
+ static_assert( sizeof( PipelineTessellationDomainOriginStateCreateInfo ) == sizeof( VkPipelineTessellationDomainOriginStateCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineTessellationDomainOriginStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct VertexInputBindingDivisorDescriptionEXT
+ {
+ VULKAN_HPP_CONSTEXPR VertexInputBindingDivisorDescriptionEXT( uint32_t binding_ = {},
+ uint32_t divisor_ = {} ) VULKAN_HPP_NOEXCEPT
+ : binding( binding_ )
+ , divisor( divisor_ )
+ {}
+
+ VertexInputBindingDivisorDescriptionEXT( VkVertexInputBindingDivisorDescriptionEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ VertexInputBindingDivisorDescriptionEXT& operator=( VkVertexInputBindingDivisorDescriptionEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::VertexInputBindingDivisorDescriptionEXT const *>(&rhs);
+ return *this;
+ }
+
+ VertexInputBindingDivisorDescriptionEXT & setBinding( uint32_t binding_ ) VULKAN_HPP_NOEXCEPT
+ {
+ binding = binding_;
+ return *this;
+ }
+
+ VertexInputBindingDivisorDescriptionEXT & setDivisor( uint32_t divisor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ divisor = divisor_;
+ return *this;
+ }
+
+ operator VkVertexInputBindingDivisorDescriptionEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkVertexInputBindingDivisorDescriptionEXT*>( this );
+ }
+
+ operator VkVertexInputBindingDivisorDescriptionEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkVertexInputBindingDivisorDescriptionEXT*>( this );
+ }
+
+ bool operator==( VertexInputBindingDivisorDescriptionEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( binding == rhs.binding )
+ && ( divisor == rhs.divisor );
+ }
+
+ bool operator!=( VertexInputBindingDivisorDescriptionEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t binding = {};
+ uint32_t divisor = {};
+ };
+ static_assert( sizeof( VertexInputBindingDivisorDescriptionEXT ) == sizeof( VkVertexInputBindingDivisorDescriptionEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<VertexInputBindingDivisorDescriptionEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineVertexInputDivisorStateCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR PipelineVertexInputDivisorStateCreateInfoEXT( uint32_t vertexBindingDivisorCount_ = {},
+ const VULKAN_HPP_NAMESPACE::VertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors_ = {} ) VULKAN_HPP_NOEXCEPT
+ : vertexBindingDivisorCount( vertexBindingDivisorCount_ )
+ , pVertexBindingDivisors( pVertexBindingDivisors_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineVertexInputDivisorStateCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::PipelineVertexInputDivisorStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineVertexInputDivisorStateCreateInfoEXT ) - offsetof( PipelineVertexInputDivisorStateCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ PipelineVertexInputDivisorStateCreateInfoEXT( VkPipelineVertexInputDivisorStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineVertexInputDivisorStateCreateInfoEXT& operator=( VkPipelineVertexInputDivisorStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineVertexInputDivisorStateCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ PipelineVertexInputDivisorStateCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineVertexInputDivisorStateCreateInfoEXT & setVertexBindingDivisorCount( uint32_t vertexBindingDivisorCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ vertexBindingDivisorCount = vertexBindingDivisorCount_;
+ return *this;
+ }
+
+ PipelineVertexInputDivisorStateCreateInfoEXT & setPVertexBindingDivisors( const VULKAN_HPP_NAMESPACE::VertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pVertexBindingDivisors = pVertexBindingDivisors_;
+ return *this;
+ }
+
+ operator VkPipelineVertexInputDivisorStateCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineVertexInputDivisorStateCreateInfoEXT*>( this );
+ }
+
+ operator VkPipelineVertexInputDivisorStateCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineVertexInputDivisorStateCreateInfoEXT*>( this );
+ }
+
+ bool operator==( PipelineVertexInputDivisorStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( vertexBindingDivisorCount == rhs.vertexBindingDivisorCount )
+ && ( pVertexBindingDivisors == rhs.pVertexBindingDivisors );
+ }
+
+ bool operator!=( PipelineVertexInputDivisorStateCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineVertexInputDivisorStateCreateInfoEXT;
+ const void* pNext = {};
+ uint32_t vertexBindingDivisorCount = {};
+ const VULKAN_HPP_NAMESPACE::VertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors = {};
+ };
+ static_assert( sizeof( PipelineVertexInputDivisorStateCreateInfoEXT ) == sizeof( VkPipelineVertexInputDivisorStateCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineVertexInputDivisorStateCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineViewportCoarseSampleOrderStateCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR PipelineViewportCoarseSampleOrderStateCreateInfoNV( VULKAN_HPP_NAMESPACE::CoarseSampleOrderTypeNV sampleOrderType_ = VULKAN_HPP_NAMESPACE::CoarseSampleOrderTypeNV::eDefault,
+ uint32_t customSampleOrderCount_ = {},
+ const VULKAN_HPP_NAMESPACE::CoarseSampleOrderCustomNV* pCustomSampleOrders_ = {} ) VULKAN_HPP_NOEXCEPT
+ : sampleOrderType( sampleOrderType_ )
+ , customSampleOrderCount( customSampleOrderCount_ )
+ , pCustomSampleOrders( pCustomSampleOrders_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineViewportCoarseSampleOrderStateCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::PipelineViewportCoarseSampleOrderStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineViewportCoarseSampleOrderStateCreateInfoNV ) - offsetof( PipelineViewportCoarseSampleOrderStateCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ PipelineViewportCoarseSampleOrderStateCreateInfoNV( VkPipelineViewportCoarseSampleOrderStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineViewportCoarseSampleOrderStateCreateInfoNV& operator=( VkPipelineViewportCoarseSampleOrderStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineViewportCoarseSampleOrderStateCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ PipelineViewportCoarseSampleOrderStateCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineViewportCoarseSampleOrderStateCreateInfoNV & setSampleOrderType( VULKAN_HPP_NAMESPACE::CoarseSampleOrderTypeNV sampleOrderType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleOrderType = sampleOrderType_;
+ return *this;
+ }
+
+ PipelineViewportCoarseSampleOrderStateCreateInfoNV & setCustomSampleOrderCount( uint32_t customSampleOrderCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ customSampleOrderCount = customSampleOrderCount_;
+ return *this;
+ }
+
+ PipelineViewportCoarseSampleOrderStateCreateInfoNV & setPCustomSampleOrders( const VULKAN_HPP_NAMESPACE::CoarseSampleOrderCustomNV* pCustomSampleOrders_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pCustomSampleOrders = pCustomSampleOrders_;
+ return *this;
+ }
+
+ operator VkPipelineViewportCoarseSampleOrderStateCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineViewportCoarseSampleOrderStateCreateInfoNV*>( this );
+ }
+
+ operator VkPipelineViewportCoarseSampleOrderStateCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineViewportCoarseSampleOrderStateCreateInfoNV*>( this );
+ }
+
+ bool operator==( PipelineViewportCoarseSampleOrderStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( sampleOrderType == rhs.sampleOrderType )
+ && ( customSampleOrderCount == rhs.customSampleOrderCount )
+ && ( pCustomSampleOrders == rhs.pCustomSampleOrders );
+ }
+
+ bool operator!=( PipelineViewportCoarseSampleOrderStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineViewportCoarseSampleOrderStateCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::CoarseSampleOrderTypeNV sampleOrderType = VULKAN_HPP_NAMESPACE::CoarseSampleOrderTypeNV::eDefault;
+ uint32_t customSampleOrderCount = {};
+ const VULKAN_HPP_NAMESPACE::CoarseSampleOrderCustomNV* pCustomSampleOrders = {};
+ };
+ static_assert( sizeof( PipelineViewportCoarseSampleOrderStateCreateInfoNV ) == sizeof( VkPipelineViewportCoarseSampleOrderStateCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineViewportCoarseSampleOrderStateCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineViewportExclusiveScissorStateCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR PipelineViewportExclusiveScissorStateCreateInfoNV( uint32_t exclusiveScissorCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Rect2D* pExclusiveScissors_ = {} ) VULKAN_HPP_NOEXCEPT
+ : exclusiveScissorCount( exclusiveScissorCount_ )
+ , pExclusiveScissors( pExclusiveScissors_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineViewportExclusiveScissorStateCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::PipelineViewportExclusiveScissorStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineViewportExclusiveScissorStateCreateInfoNV ) - offsetof( PipelineViewportExclusiveScissorStateCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ PipelineViewportExclusiveScissorStateCreateInfoNV( VkPipelineViewportExclusiveScissorStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineViewportExclusiveScissorStateCreateInfoNV& operator=( VkPipelineViewportExclusiveScissorStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineViewportExclusiveScissorStateCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ PipelineViewportExclusiveScissorStateCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineViewportExclusiveScissorStateCreateInfoNV & setExclusiveScissorCount( uint32_t exclusiveScissorCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ exclusiveScissorCount = exclusiveScissorCount_;
+ return *this;
+ }
+
+ PipelineViewportExclusiveScissorStateCreateInfoNV & setPExclusiveScissors( const VULKAN_HPP_NAMESPACE::Rect2D* pExclusiveScissors_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pExclusiveScissors = pExclusiveScissors_;
+ return *this;
+ }
+
+ operator VkPipelineViewportExclusiveScissorStateCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineViewportExclusiveScissorStateCreateInfoNV*>( this );
+ }
+
+ operator VkPipelineViewportExclusiveScissorStateCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineViewportExclusiveScissorStateCreateInfoNV*>( this );
+ }
+
+ bool operator==( PipelineViewportExclusiveScissorStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( exclusiveScissorCount == rhs.exclusiveScissorCount )
+ && ( pExclusiveScissors == rhs.pExclusiveScissors );
+ }
+
+ bool operator!=( PipelineViewportExclusiveScissorStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineViewportExclusiveScissorStateCreateInfoNV;
+ const void* pNext = {};
+ uint32_t exclusiveScissorCount = {};
+ const VULKAN_HPP_NAMESPACE::Rect2D* pExclusiveScissors = {};
+ };
+ static_assert( sizeof( PipelineViewportExclusiveScissorStateCreateInfoNV ) == sizeof( VkPipelineViewportExclusiveScissorStateCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineViewportExclusiveScissorStateCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct ShadingRatePaletteNV
+ {
+ VULKAN_HPP_CONSTEXPR ShadingRatePaletteNV( uint32_t shadingRatePaletteEntryCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ShadingRatePaletteEntryNV* pShadingRatePaletteEntries_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shadingRatePaletteEntryCount( shadingRatePaletteEntryCount_ )
+ , pShadingRatePaletteEntries( pShadingRatePaletteEntries_ )
+ {}
+
+ ShadingRatePaletteNV( VkShadingRatePaletteNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ShadingRatePaletteNV& operator=( VkShadingRatePaletteNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ShadingRatePaletteNV const *>(&rhs);
+ return *this;
+ }
+
+ ShadingRatePaletteNV & setShadingRatePaletteEntryCount( uint32_t shadingRatePaletteEntryCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shadingRatePaletteEntryCount = shadingRatePaletteEntryCount_;
+ return *this;
+ }
+
+ ShadingRatePaletteNV & setPShadingRatePaletteEntries( const VULKAN_HPP_NAMESPACE::ShadingRatePaletteEntryNV* pShadingRatePaletteEntries_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pShadingRatePaletteEntries = pShadingRatePaletteEntries_;
+ return *this;
+ }
+
+ operator VkShadingRatePaletteNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkShadingRatePaletteNV*>( this );
+ }
+
+ operator VkShadingRatePaletteNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkShadingRatePaletteNV*>( this );
+ }
+
+ bool operator==( ShadingRatePaletteNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( shadingRatePaletteEntryCount == rhs.shadingRatePaletteEntryCount )
+ && ( pShadingRatePaletteEntries == rhs.pShadingRatePaletteEntries );
+ }
+
+ bool operator!=( ShadingRatePaletteNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t shadingRatePaletteEntryCount = {};
+ const VULKAN_HPP_NAMESPACE::ShadingRatePaletteEntryNV* pShadingRatePaletteEntries = {};
+ };
+ static_assert( sizeof( ShadingRatePaletteNV ) == sizeof( VkShadingRatePaletteNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ShadingRatePaletteNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineViewportShadingRateImageStateCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR PipelineViewportShadingRateImageStateCreateInfoNV( VULKAN_HPP_NAMESPACE::Bool32 shadingRateImageEnable_ = {},
+ uint32_t viewportCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ShadingRatePaletteNV* pShadingRatePalettes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shadingRateImageEnable( shadingRateImageEnable_ )
+ , viewportCount( viewportCount_ )
+ , pShadingRatePalettes( pShadingRatePalettes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineViewportShadingRateImageStateCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::PipelineViewportShadingRateImageStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineViewportShadingRateImageStateCreateInfoNV ) - offsetof( PipelineViewportShadingRateImageStateCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ PipelineViewportShadingRateImageStateCreateInfoNV( VkPipelineViewportShadingRateImageStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineViewportShadingRateImageStateCreateInfoNV& operator=( VkPipelineViewportShadingRateImageStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineViewportShadingRateImageStateCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ PipelineViewportShadingRateImageStateCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineViewportShadingRateImageStateCreateInfoNV & setShadingRateImageEnable( VULKAN_HPP_NAMESPACE::Bool32 shadingRateImageEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ shadingRateImageEnable = shadingRateImageEnable_;
+ return *this;
+ }
+
+ PipelineViewportShadingRateImageStateCreateInfoNV & setViewportCount( uint32_t viewportCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ viewportCount = viewportCount_;
+ return *this;
+ }
+
+ PipelineViewportShadingRateImageStateCreateInfoNV & setPShadingRatePalettes( const VULKAN_HPP_NAMESPACE::ShadingRatePaletteNV* pShadingRatePalettes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pShadingRatePalettes = pShadingRatePalettes_;
+ return *this;
+ }
+
+ operator VkPipelineViewportShadingRateImageStateCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineViewportShadingRateImageStateCreateInfoNV*>( this );
+ }
+
+ operator VkPipelineViewportShadingRateImageStateCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineViewportShadingRateImageStateCreateInfoNV*>( this );
+ }
+
+ bool operator==( PipelineViewportShadingRateImageStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( shadingRateImageEnable == rhs.shadingRateImageEnable )
+ && ( viewportCount == rhs.viewportCount )
+ && ( pShadingRatePalettes == rhs.pShadingRatePalettes );
+ }
+
+ bool operator!=( PipelineViewportShadingRateImageStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineViewportShadingRateImageStateCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 shadingRateImageEnable = {};
+ uint32_t viewportCount = {};
+ const VULKAN_HPP_NAMESPACE::ShadingRatePaletteNV* pShadingRatePalettes = {};
+ };
+ static_assert( sizeof( PipelineViewportShadingRateImageStateCreateInfoNV ) == sizeof( VkPipelineViewportShadingRateImageStateCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineViewportShadingRateImageStateCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct ViewportSwizzleNV
+ {
+ VULKAN_HPP_CONSTEXPR ViewportSwizzleNV( VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV x_ = VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV::ePositiveX,
+ VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV y_ = VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV::ePositiveX,
+ VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV z_ = VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV::ePositiveX,
+ VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV w_ = VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV::ePositiveX ) VULKAN_HPP_NOEXCEPT
+ : x( x_ )
+ , y( y_ )
+ , z( z_ )
+ , w( w_ )
+ {}
+
+ ViewportSwizzleNV( VkViewportSwizzleNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ViewportSwizzleNV& operator=( VkViewportSwizzleNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ViewportSwizzleNV const *>(&rhs);
+ return *this;
+ }
+
+ ViewportSwizzleNV & setX( VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV x_ ) VULKAN_HPP_NOEXCEPT
+ {
+ x = x_;
+ return *this;
+ }
+
+ ViewportSwizzleNV & setY( VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV y_ ) VULKAN_HPP_NOEXCEPT
+ {
+ y = y_;
+ return *this;
+ }
+
+ ViewportSwizzleNV & setZ( VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV z_ ) VULKAN_HPP_NOEXCEPT
+ {
+ z = z_;
+ return *this;
+ }
+
+ ViewportSwizzleNV & setW( VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV w_ ) VULKAN_HPP_NOEXCEPT
+ {
+ w = w_;
+ return *this;
+ }
+
+ operator VkViewportSwizzleNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkViewportSwizzleNV*>( this );
+ }
+
+ operator VkViewportSwizzleNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkViewportSwizzleNV*>( this );
+ }
+
+ bool operator==( ViewportSwizzleNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( x == rhs.x )
+ && ( y == rhs.y )
+ && ( z == rhs.z )
+ && ( w == rhs.w );
+ }
+
+ bool operator!=( ViewportSwizzleNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV x = VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV::ePositiveX;
+ VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV y = VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV::ePositiveX;
+ VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV z = VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV::ePositiveX;
+ VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV w = VULKAN_HPP_NAMESPACE::ViewportCoordinateSwizzleNV::ePositiveX;
+ };
+ static_assert( sizeof( ViewportSwizzleNV ) == sizeof( VkViewportSwizzleNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ViewportSwizzleNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineViewportSwizzleStateCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR PipelineViewportSwizzleStateCreateInfoNV( VULKAN_HPP_NAMESPACE::PipelineViewportSwizzleStateCreateFlagsNV flags_ = {},
+ uint32_t viewportCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ViewportSwizzleNV* pViewportSwizzles_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , viewportCount( viewportCount_ )
+ , pViewportSwizzles( pViewportSwizzles_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineViewportSwizzleStateCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::PipelineViewportSwizzleStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineViewportSwizzleStateCreateInfoNV ) - offsetof( PipelineViewportSwizzleStateCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ PipelineViewportSwizzleStateCreateInfoNV( VkPipelineViewportSwizzleStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineViewportSwizzleStateCreateInfoNV& operator=( VkPipelineViewportSwizzleStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineViewportSwizzleStateCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ PipelineViewportSwizzleStateCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineViewportSwizzleStateCreateInfoNV & setFlags( VULKAN_HPP_NAMESPACE::PipelineViewportSwizzleStateCreateFlagsNV flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ PipelineViewportSwizzleStateCreateInfoNV & setViewportCount( uint32_t viewportCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ viewportCount = viewportCount_;
+ return *this;
+ }
+
+ PipelineViewportSwizzleStateCreateInfoNV & setPViewportSwizzles( const VULKAN_HPP_NAMESPACE::ViewportSwizzleNV* pViewportSwizzles_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pViewportSwizzles = pViewportSwizzles_;
+ return *this;
+ }
+
+ operator VkPipelineViewportSwizzleStateCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineViewportSwizzleStateCreateInfoNV*>( this );
+ }
+
+ operator VkPipelineViewportSwizzleStateCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineViewportSwizzleStateCreateInfoNV*>( this );
+ }
+
+ bool operator==( PipelineViewportSwizzleStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( viewportCount == rhs.viewportCount )
+ && ( pViewportSwizzles == rhs.pViewportSwizzles );
+ }
+
+ bool operator!=( PipelineViewportSwizzleStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineViewportSwizzleStateCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineViewportSwizzleStateCreateFlagsNV flags = {};
+ uint32_t viewportCount = {};
+ const VULKAN_HPP_NAMESPACE::ViewportSwizzleNV* pViewportSwizzles = {};
+ };
+ static_assert( sizeof( PipelineViewportSwizzleStateCreateInfoNV ) == sizeof( VkPipelineViewportSwizzleStateCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineViewportSwizzleStateCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct ViewportWScalingNV
+ {
+ VULKAN_HPP_CONSTEXPR ViewportWScalingNV( float xcoeff_ = {},
+ float ycoeff_ = {} ) VULKAN_HPP_NOEXCEPT
+ : xcoeff( xcoeff_ )
+ , ycoeff( ycoeff_ )
+ {}
+
+ ViewportWScalingNV( VkViewportWScalingNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ViewportWScalingNV& operator=( VkViewportWScalingNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ViewportWScalingNV const *>(&rhs);
+ return *this;
+ }
+
+ ViewportWScalingNV & setXcoeff( float xcoeff_ ) VULKAN_HPP_NOEXCEPT
+ {
+ xcoeff = xcoeff_;
+ return *this;
+ }
+
+ ViewportWScalingNV & setYcoeff( float ycoeff_ ) VULKAN_HPP_NOEXCEPT
+ {
+ ycoeff = ycoeff_;
+ return *this;
+ }
+
+ operator VkViewportWScalingNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkViewportWScalingNV*>( this );
+ }
+
+ operator VkViewportWScalingNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkViewportWScalingNV*>( this );
+ }
+
+ bool operator==( ViewportWScalingNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( xcoeff == rhs.xcoeff )
+ && ( ycoeff == rhs.ycoeff );
+ }
+
+ bool operator!=( ViewportWScalingNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ float xcoeff = {};
+ float ycoeff = {};
+ };
+ static_assert( sizeof( ViewportWScalingNV ) == sizeof( VkViewportWScalingNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ViewportWScalingNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct PipelineViewportWScalingStateCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR PipelineViewportWScalingStateCreateInfoNV( VULKAN_HPP_NAMESPACE::Bool32 viewportWScalingEnable_ = {},
+ uint32_t viewportCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ViewportWScalingNV* pViewportWScalings_ = {} ) VULKAN_HPP_NOEXCEPT
+ : viewportWScalingEnable( viewportWScalingEnable_ )
+ , viewportCount( viewportCount_ )
+ , pViewportWScalings( pViewportWScalings_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PipelineViewportWScalingStateCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::PipelineViewportWScalingStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PipelineViewportWScalingStateCreateInfoNV ) - offsetof( PipelineViewportWScalingStateCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ PipelineViewportWScalingStateCreateInfoNV( VkPipelineViewportWScalingStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PipelineViewportWScalingStateCreateInfoNV& operator=( VkPipelineViewportWScalingStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineViewportWScalingStateCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ PipelineViewportWScalingStateCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PipelineViewportWScalingStateCreateInfoNV & setViewportWScalingEnable( VULKAN_HPP_NAMESPACE::Bool32 viewportWScalingEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ viewportWScalingEnable = viewportWScalingEnable_;
+ return *this;
+ }
+
+ PipelineViewportWScalingStateCreateInfoNV & setViewportCount( uint32_t viewportCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ viewportCount = viewportCount_;
+ return *this;
+ }
+
+ PipelineViewportWScalingStateCreateInfoNV & setPViewportWScalings( const VULKAN_HPP_NAMESPACE::ViewportWScalingNV* pViewportWScalings_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pViewportWScalings = pViewportWScalings_;
+ return *this;
+ }
+
+ operator VkPipelineViewportWScalingStateCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPipelineViewportWScalingStateCreateInfoNV*>( this );
+ }
+
+ operator VkPipelineViewportWScalingStateCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPipelineViewportWScalingStateCreateInfoNV*>( this );
+ }
+
+ bool operator==( PipelineViewportWScalingStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( viewportWScalingEnable == rhs.viewportWScalingEnable )
+ && ( viewportCount == rhs.viewportCount )
+ && ( pViewportWScalings == rhs.pViewportWScalings );
+ }
+
+ bool operator!=( PipelineViewportWScalingStateCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineViewportWScalingStateCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 viewportWScalingEnable = {};
+ uint32_t viewportCount = {};
+ const VULKAN_HPP_NAMESPACE::ViewportWScalingNV* pViewportWScalings = {};
+ };
+ static_assert( sizeof( PipelineViewportWScalingStateCreateInfoNV ) == sizeof( VkPipelineViewportWScalingStateCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PipelineViewportWScalingStateCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_GGP
+
+ struct PresentFrameTokenGGP
+ {
+ VULKAN_HPP_CONSTEXPR PresentFrameTokenGGP( GgpFrameToken frameToken_ = {} ) VULKAN_HPP_NOEXCEPT
+ : frameToken( frameToken_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PresentFrameTokenGGP & operator=( VULKAN_HPP_NAMESPACE::PresentFrameTokenGGP const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PresentFrameTokenGGP ) - offsetof( PresentFrameTokenGGP, pNext ) );
+ return *this;
+ }
+
+ PresentFrameTokenGGP( VkPresentFrameTokenGGP const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PresentFrameTokenGGP& operator=( VkPresentFrameTokenGGP const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PresentFrameTokenGGP const *>(&rhs);
+ return *this;
+ }
+
+ PresentFrameTokenGGP & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PresentFrameTokenGGP & setFrameToken( GgpFrameToken frameToken_ ) VULKAN_HPP_NOEXCEPT
+ {
+ frameToken = frameToken_;
+ return *this;
+ }
+
+ operator VkPresentFrameTokenGGP const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPresentFrameTokenGGP*>( this );
+ }
+
+ operator VkPresentFrameTokenGGP &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPresentFrameTokenGGP*>( this );
+ }
+
+ bool operator==( PresentFrameTokenGGP const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( frameToken == rhs.frameToken );
+ }
+
+ bool operator!=( PresentFrameTokenGGP const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePresentFrameTokenGGP;
+ const void* pNext = {};
+ GgpFrameToken frameToken = {};
+ };
+ static_assert( sizeof( PresentFrameTokenGGP ) == sizeof( VkPresentFrameTokenGGP ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PresentFrameTokenGGP>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_GGP*/
+
+ struct PresentInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR PresentInfoKHR( uint32_t waitSemaphoreCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Semaphore* pWaitSemaphores_ = {},
+ uint32_t swapchainCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SwapchainKHR* pSwapchains_ = {},
+ const uint32_t* pImageIndices_ = {},
+ VULKAN_HPP_NAMESPACE::Result* pResults_ = {} ) VULKAN_HPP_NOEXCEPT
+ : waitSemaphoreCount( waitSemaphoreCount_ )
+ , pWaitSemaphores( pWaitSemaphores_ )
+ , swapchainCount( swapchainCount_ )
+ , pSwapchains( pSwapchains_ )
+ , pImageIndices( pImageIndices_ )
+ , pResults( pResults_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PresentInfoKHR & operator=( VULKAN_HPP_NAMESPACE::PresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PresentInfoKHR ) - offsetof( PresentInfoKHR, pNext ) );
+ return *this;
+ }
+
+ PresentInfoKHR( VkPresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PresentInfoKHR& operator=( VkPresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PresentInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ PresentInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PresentInfoKHR & setWaitSemaphoreCount( uint32_t waitSemaphoreCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ waitSemaphoreCount = waitSemaphoreCount_;
+ return *this;
+ }
+
+ PresentInfoKHR & setPWaitSemaphores( const VULKAN_HPP_NAMESPACE::Semaphore* pWaitSemaphores_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pWaitSemaphores = pWaitSemaphores_;
+ return *this;
+ }
+
+ PresentInfoKHR & setSwapchainCount( uint32_t swapchainCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ swapchainCount = swapchainCount_;
+ return *this;
+ }
+
+ PresentInfoKHR & setPSwapchains( const VULKAN_HPP_NAMESPACE::SwapchainKHR* pSwapchains_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSwapchains = pSwapchains_;
+ return *this;
+ }
+
+ PresentInfoKHR & setPImageIndices( const uint32_t* pImageIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pImageIndices = pImageIndices_;
+ return *this;
+ }
+
+ PresentInfoKHR & setPResults( VULKAN_HPP_NAMESPACE::Result* pResults_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pResults = pResults_;
+ return *this;
+ }
+
+ operator VkPresentInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPresentInfoKHR*>( this );
+ }
+
+ operator VkPresentInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPresentInfoKHR*>( this );
+ }
+
+ bool operator==( PresentInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( waitSemaphoreCount == rhs.waitSemaphoreCount )
+ && ( pWaitSemaphores == rhs.pWaitSemaphores )
+ && ( swapchainCount == rhs.swapchainCount )
+ && ( pSwapchains == rhs.pSwapchains )
+ && ( pImageIndices == rhs.pImageIndices )
+ && ( pResults == rhs.pResults );
+ }
+
+ bool operator!=( PresentInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePresentInfoKHR;
+ const void* pNext = {};
+ uint32_t waitSemaphoreCount = {};
+ const VULKAN_HPP_NAMESPACE::Semaphore* pWaitSemaphores = {};
+ uint32_t swapchainCount = {};
+ const VULKAN_HPP_NAMESPACE::SwapchainKHR* pSwapchains = {};
+ const uint32_t* pImageIndices = {};
+ VULKAN_HPP_NAMESPACE::Result* pResults = {};
+ };
+ static_assert( sizeof( PresentInfoKHR ) == sizeof( VkPresentInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PresentInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct RectLayerKHR
+ {
+ VULKAN_HPP_CONSTEXPR RectLayerKHR( VULKAN_HPP_NAMESPACE::Offset2D offset_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D extent_ = {},
+ uint32_t layer_ = {} ) VULKAN_HPP_NOEXCEPT
+ : offset( offset_ )
+ , extent( extent_ )
+ , layer( layer_ )
+ {}
+
+ explicit RectLayerKHR( Rect2D const& rect2D,
+ uint32_t layer_ = {} )
+ : offset( rect2D.offset )
+ , extent( rect2D.extent )
+ , layer( layer_ )
+ {}
+
+ RectLayerKHR( VkRectLayerKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RectLayerKHR& operator=( VkRectLayerKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RectLayerKHR const *>(&rhs);
+ return *this;
+ }
+
+ RectLayerKHR & setOffset( VULKAN_HPP_NAMESPACE::Offset2D offset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ offset = offset_;
+ return *this;
+ }
+
+ RectLayerKHR & setExtent( VULKAN_HPP_NAMESPACE::Extent2D extent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ extent = extent_;
+ return *this;
+ }
+
+ RectLayerKHR & setLayer( uint32_t layer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layer = layer_;
+ return *this;
+ }
+
+ operator VkRectLayerKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRectLayerKHR*>( this );
+ }
+
+ operator VkRectLayerKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRectLayerKHR*>( this );
+ }
+
+ bool operator==( RectLayerKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( offset == rhs.offset )
+ && ( extent == rhs.extent )
+ && ( layer == rhs.layer );
+ }
+
+ bool operator!=( RectLayerKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Offset2D offset = {};
+ VULKAN_HPP_NAMESPACE::Extent2D extent = {};
+ uint32_t layer = {};
+ };
+ static_assert( sizeof( RectLayerKHR ) == sizeof( VkRectLayerKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RectLayerKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PresentRegionKHR
+ {
+ VULKAN_HPP_CONSTEXPR PresentRegionKHR( uint32_t rectangleCount_ = {},
+ const VULKAN_HPP_NAMESPACE::RectLayerKHR* pRectangles_ = {} ) VULKAN_HPP_NOEXCEPT
+ : rectangleCount( rectangleCount_ )
+ , pRectangles( pRectangles_ )
+ {}
+
+ PresentRegionKHR( VkPresentRegionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PresentRegionKHR& operator=( VkPresentRegionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PresentRegionKHR const *>(&rhs);
+ return *this;
+ }
+
+ PresentRegionKHR & setRectangleCount( uint32_t rectangleCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ rectangleCount = rectangleCount_;
+ return *this;
+ }
+
+ PresentRegionKHR & setPRectangles( const VULKAN_HPP_NAMESPACE::RectLayerKHR* pRectangles_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pRectangles = pRectangles_;
+ return *this;
+ }
+
+ operator VkPresentRegionKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPresentRegionKHR*>( this );
+ }
+
+ operator VkPresentRegionKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPresentRegionKHR*>( this );
+ }
+
+ bool operator==( PresentRegionKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( rectangleCount == rhs.rectangleCount )
+ && ( pRectangles == rhs.pRectangles );
+ }
+
+ bool operator!=( PresentRegionKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t rectangleCount = {};
+ const VULKAN_HPP_NAMESPACE::RectLayerKHR* pRectangles = {};
+ };
+ static_assert( sizeof( PresentRegionKHR ) == sizeof( VkPresentRegionKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PresentRegionKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PresentRegionsKHR
+ {
+ VULKAN_HPP_CONSTEXPR PresentRegionsKHR( uint32_t swapchainCount_ = {},
+ const VULKAN_HPP_NAMESPACE::PresentRegionKHR* pRegions_ = {} ) VULKAN_HPP_NOEXCEPT
+ : swapchainCount( swapchainCount_ )
+ , pRegions( pRegions_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PresentRegionsKHR & operator=( VULKAN_HPP_NAMESPACE::PresentRegionsKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PresentRegionsKHR ) - offsetof( PresentRegionsKHR, pNext ) );
+ return *this;
+ }
+
+ PresentRegionsKHR( VkPresentRegionsKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PresentRegionsKHR& operator=( VkPresentRegionsKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PresentRegionsKHR const *>(&rhs);
+ return *this;
+ }
+
+ PresentRegionsKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PresentRegionsKHR & setSwapchainCount( uint32_t swapchainCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ swapchainCount = swapchainCount_;
+ return *this;
+ }
+
+ PresentRegionsKHR & setPRegions( const VULKAN_HPP_NAMESPACE::PresentRegionKHR* pRegions_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pRegions = pRegions_;
+ return *this;
+ }
+
+ operator VkPresentRegionsKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPresentRegionsKHR*>( this );
+ }
+
+ operator VkPresentRegionsKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPresentRegionsKHR*>( this );
+ }
+
+ bool operator==( PresentRegionsKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( swapchainCount == rhs.swapchainCount )
+ && ( pRegions == rhs.pRegions );
+ }
+
+ bool operator!=( PresentRegionsKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePresentRegionsKHR;
+ const void* pNext = {};
+ uint32_t swapchainCount = {};
+ const VULKAN_HPP_NAMESPACE::PresentRegionKHR* pRegions = {};
+ };
+ static_assert( sizeof( PresentRegionsKHR ) == sizeof( VkPresentRegionsKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PresentRegionsKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct PresentTimeGOOGLE
+ {
+ VULKAN_HPP_CONSTEXPR PresentTimeGOOGLE( uint32_t presentID_ = {},
+ uint64_t desiredPresentTime_ = {} ) VULKAN_HPP_NOEXCEPT
+ : presentID( presentID_ )
+ , desiredPresentTime( desiredPresentTime_ )
+ {}
+
+ PresentTimeGOOGLE( VkPresentTimeGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PresentTimeGOOGLE& operator=( VkPresentTimeGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PresentTimeGOOGLE const *>(&rhs);
+ return *this;
+ }
+
+ PresentTimeGOOGLE & setPresentID( uint32_t presentID_ ) VULKAN_HPP_NOEXCEPT
+ {
+ presentID = presentID_;
+ return *this;
+ }
+
+ PresentTimeGOOGLE & setDesiredPresentTime( uint64_t desiredPresentTime_ ) VULKAN_HPP_NOEXCEPT
+ {
+ desiredPresentTime = desiredPresentTime_;
+ return *this;
+ }
+
+ operator VkPresentTimeGOOGLE const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPresentTimeGOOGLE*>( this );
+ }
+
+ operator VkPresentTimeGOOGLE &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPresentTimeGOOGLE*>( this );
+ }
+
+ bool operator==( PresentTimeGOOGLE const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( presentID == rhs.presentID )
+ && ( desiredPresentTime == rhs.desiredPresentTime );
+ }
+
+ bool operator!=( PresentTimeGOOGLE const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t presentID = {};
+ uint64_t desiredPresentTime = {};
+ };
+ static_assert( sizeof( PresentTimeGOOGLE ) == sizeof( VkPresentTimeGOOGLE ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PresentTimeGOOGLE>::value, "struct wrapper is not a standard layout!" );
+
+ struct PresentTimesInfoGOOGLE
+ {
+ VULKAN_HPP_CONSTEXPR PresentTimesInfoGOOGLE( uint32_t swapchainCount_ = {},
+ const VULKAN_HPP_NAMESPACE::PresentTimeGOOGLE* pTimes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : swapchainCount( swapchainCount_ )
+ , pTimes( pTimes_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::PresentTimesInfoGOOGLE & operator=( VULKAN_HPP_NAMESPACE::PresentTimesInfoGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::PresentTimesInfoGOOGLE ) - offsetof( PresentTimesInfoGOOGLE, pNext ) );
+ return *this;
+ }
+
+ PresentTimesInfoGOOGLE( VkPresentTimesInfoGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ PresentTimesInfoGOOGLE& operator=( VkPresentTimesInfoGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PresentTimesInfoGOOGLE const *>(&rhs);
+ return *this;
+ }
+
+ PresentTimesInfoGOOGLE & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ PresentTimesInfoGOOGLE & setSwapchainCount( uint32_t swapchainCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ swapchainCount = swapchainCount_;
+ return *this;
+ }
+
+ PresentTimesInfoGOOGLE & setPTimes( const VULKAN_HPP_NAMESPACE::PresentTimeGOOGLE* pTimes_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pTimes = pTimes_;
+ return *this;
+ }
+
+ operator VkPresentTimesInfoGOOGLE const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkPresentTimesInfoGOOGLE*>( this );
+ }
+
+ operator VkPresentTimesInfoGOOGLE &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkPresentTimesInfoGOOGLE*>( this );
+ }
+
+ bool operator==( PresentTimesInfoGOOGLE const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( swapchainCount == rhs.swapchainCount )
+ && ( pTimes == rhs.pTimes );
+ }
+
+ bool operator!=( PresentTimesInfoGOOGLE const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePresentTimesInfoGOOGLE;
+ const void* pNext = {};
+ uint32_t swapchainCount = {};
+ const VULKAN_HPP_NAMESPACE::PresentTimeGOOGLE* pTimes = {};
+ };
+ static_assert( sizeof( PresentTimesInfoGOOGLE ) == sizeof( VkPresentTimesInfoGOOGLE ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<PresentTimesInfoGOOGLE>::value, "struct wrapper is not a standard layout!" );
+
+ struct ProtectedSubmitInfo
+ {
+ VULKAN_HPP_CONSTEXPR ProtectedSubmitInfo( VULKAN_HPP_NAMESPACE::Bool32 protectedSubmit_ = {} ) VULKAN_HPP_NOEXCEPT
+ : protectedSubmit( protectedSubmit_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ProtectedSubmitInfo & operator=( VULKAN_HPP_NAMESPACE::ProtectedSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ProtectedSubmitInfo ) - offsetof( ProtectedSubmitInfo, pNext ) );
+ return *this;
+ }
+
+ ProtectedSubmitInfo( VkProtectedSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ProtectedSubmitInfo& operator=( VkProtectedSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ProtectedSubmitInfo const *>(&rhs);
+ return *this;
+ }
+
+ ProtectedSubmitInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ProtectedSubmitInfo & setProtectedSubmit( VULKAN_HPP_NAMESPACE::Bool32 protectedSubmit_ ) VULKAN_HPP_NOEXCEPT
+ {
+ protectedSubmit = protectedSubmit_;
+ return *this;
+ }
+
+ operator VkProtectedSubmitInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkProtectedSubmitInfo*>( this );
+ }
+
+ operator VkProtectedSubmitInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkProtectedSubmitInfo*>( this );
+ }
+
+ bool operator==( ProtectedSubmitInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( protectedSubmit == rhs.protectedSubmit );
+ }
+
+ bool operator!=( ProtectedSubmitInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eProtectedSubmitInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 protectedSubmit = {};
+ };
+ static_assert( sizeof( ProtectedSubmitInfo ) == sizeof( VkProtectedSubmitInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ProtectedSubmitInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct QueryPoolCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR QueryPoolCreateInfo( VULKAN_HPP_NAMESPACE::QueryPoolCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::QueryType queryType_ = VULKAN_HPP_NAMESPACE::QueryType::eOcclusion,
+ uint32_t queryCount_ = {},
+ VULKAN_HPP_NAMESPACE::QueryPipelineStatisticFlags pipelineStatistics_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , queryType( queryType_ )
+ , queryCount( queryCount_ )
+ , pipelineStatistics( pipelineStatistics_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::QueryPoolCreateInfo & operator=( VULKAN_HPP_NAMESPACE::QueryPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::QueryPoolCreateInfo ) - offsetof( QueryPoolCreateInfo, pNext ) );
+ return *this;
+ }
+
+ QueryPoolCreateInfo( VkQueryPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ QueryPoolCreateInfo& operator=( VkQueryPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::QueryPoolCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ QueryPoolCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ QueryPoolCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::QueryPoolCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ QueryPoolCreateInfo & setQueryType( VULKAN_HPP_NAMESPACE::QueryType queryType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queryType = queryType_;
+ return *this;
+ }
+
+ QueryPoolCreateInfo & setQueryCount( uint32_t queryCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queryCount = queryCount_;
+ return *this;
+ }
+
+ QueryPoolCreateInfo & setPipelineStatistics( VULKAN_HPP_NAMESPACE::QueryPipelineStatisticFlags pipelineStatistics_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineStatistics = pipelineStatistics_;
+ return *this;
+ }
+
+ operator VkQueryPoolCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkQueryPoolCreateInfo*>( this );
+ }
+
+ operator VkQueryPoolCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkQueryPoolCreateInfo*>( this );
+ }
+
+ bool operator==( QueryPoolCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( queryType == rhs.queryType )
+ && ( queryCount == rhs.queryCount )
+ && ( pipelineStatistics == rhs.pipelineStatistics );
+ }
+
+ bool operator!=( QueryPoolCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eQueryPoolCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::QueryPoolCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::QueryType queryType = VULKAN_HPP_NAMESPACE::QueryType::eOcclusion;
+ uint32_t queryCount = {};
+ VULKAN_HPP_NAMESPACE::QueryPipelineStatisticFlags pipelineStatistics = {};
+ };
+ static_assert( sizeof( QueryPoolCreateInfo ) == sizeof( VkQueryPoolCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<QueryPoolCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct QueryPoolCreateInfoINTEL
+ {
+ VULKAN_HPP_CONSTEXPR QueryPoolCreateInfoINTEL( VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL performanceCountersSampling_ = VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL::eManual ) VULKAN_HPP_NOEXCEPT
+ : performanceCountersSampling( performanceCountersSampling_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::QueryPoolCreateInfoINTEL & operator=( VULKAN_HPP_NAMESPACE::QueryPoolCreateInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::QueryPoolCreateInfoINTEL ) - offsetof( QueryPoolCreateInfoINTEL, pNext ) );
+ return *this;
+ }
+
+ QueryPoolCreateInfoINTEL( VkQueryPoolCreateInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ QueryPoolCreateInfoINTEL& operator=( VkQueryPoolCreateInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::QueryPoolCreateInfoINTEL const *>(&rhs);
+ return *this;
+ }
+
+ QueryPoolCreateInfoINTEL & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ QueryPoolCreateInfoINTEL & setPerformanceCountersSampling( VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL performanceCountersSampling_ ) VULKAN_HPP_NOEXCEPT
+ {
+ performanceCountersSampling = performanceCountersSampling_;
+ return *this;
+ }
+
+ operator VkQueryPoolCreateInfoINTEL const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkQueryPoolCreateInfoINTEL*>( this );
+ }
+
+ operator VkQueryPoolCreateInfoINTEL &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkQueryPoolCreateInfoINTEL*>( this );
+ }
+
+ bool operator==( QueryPoolCreateInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( performanceCountersSampling == rhs.performanceCountersSampling );
+ }
+
+ bool operator!=( QueryPoolCreateInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eQueryPoolCreateInfoINTEL;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL performanceCountersSampling = VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL::eManual;
+ };
+ static_assert( sizeof( QueryPoolCreateInfoINTEL ) == sizeof( VkQueryPoolCreateInfoINTEL ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<QueryPoolCreateInfoINTEL>::value, "struct wrapper is not a standard layout!" );
+
+ struct QueryPoolPerformanceCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR QueryPoolPerformanceCreateInfoKHR( uint32_t queueFamilyIndex_ = {},
+ uint32_t counterIndexCount_ = {},
+ const uint32_t* pCounterIndices_ = {} ) VULKAN_HPP_NOEXCEPT
+ : queueFamilyIndex( queueFamilyIndex_ )
+ , counterIndexCount( counterIndexCount_ )
+ , pCounterIndices( pCounterIndices_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::QueryPoolPerformanceCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::QueryPoolPerformanceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::QueryPoolPerformanceCreateInfoKHR ) - offsetof( QueryPoolPerformanceCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ QueryPoolPerformanceCreateInfoKHR( VkQueryPoolPerformanceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ QueryPoolPerformanceCreateInfoKHR& operator=( VkQueryPoolPerformanceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::QueryPoolPerformanceCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ QueryPoolPerformanceCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ QueryPoolPerformanceCreateInfoKHR & setQueueFamilyIndex( uint32_t queueFamilyIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueFamilyIndex = queueFamilyIndex_;
+ return *this;
+ }
+
+ QueryPoolPerformanceCreateInfoKHR & setCounterIndexCount( uint32_t counterIndexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ counterIndexCount = counterIndexCount_;
+ return *this;
+ }
+
+ QueryPoolPerformanceCreateInfoKHR & setPCounterIndices( const uint32_t* pCounterIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pCounterIndices = pCounterIndices_;
+ return *this;
+ }
+
+ operator VkQueryPoolPerformanceCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkQueryPoolPerformanceCreateInfoKHR*>( this );
+ }
+
+ operator VkQueryPoolPerformanceCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkQueryPoolPerformanceCreateInfoKHR*>( this );
+ }
+
+ bool operator==( QueryPoolPerformanceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( queueFamilyIndex == rhs.queueFamilyIndex )
+ && ( counterIndexCount == rhs.counterIndexCount )
+ && ( pCounterIndices == rhs.pCounterIndices );
+ }
+
+ bool operator!=( QueryPoolPerformanceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eQueryPoolPerformanceCreateInfoKHR;
+ const void* pNext = {};
+ uint32_t queueFamilyIndex = {};
+ uint32_t counterIndexCount = {};
+ const uint32_t* pCounterIndices = {};
+ };
+ static_assert( sizeof( QueryPoolPerformanceCreateInfoKHR ) == sizeof( VkQueryPoolPerformanceCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<QueryPoolPerformanceCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct QueueFamilyCheckpointPropertiesNV
+ {
+ QueueFamilyCheckpointPropertiesNV( VULKAN_HPP_NAMESPACE::PipelineStageFlags checkpointExecutionStageMask_ = {} ) VULKAN_HPP_NOEXCEPT
+ : checkpointExecutionStageMask( checkpointExecutionStageMask_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::QueueFamilyCheckpointPropertiesNV & operator=( VULKAN_HPP_NAMESPACE::QueueFamilyCheckpointPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::QueueFamilyCheckpointPropertiesNV ) - offsetof( QueueFamilyCheckpointPropertiesNV, pNext ) );
+ return *this;
+ }
+
+ QueueFamilyCheckpointPropertiesNV( VkQueueFamilyCheckpointPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ QueueFamilyCheckpointPropertiesNV& operator=( VkQueueFamilyCheckpointPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::QueueFamilyCheckpointPropertiesNV const *>(&rhs);
+ return *this;
+ }
+
+ operator VkQueueFamilyCheckpointPropertiesNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkQueueFamilyCheckpointPropertiesNV*>( this );
+ }
+
+ operator VkQueueFamilyCheckpointPropertiesNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkQueueFamilyCheckpointPropertiesNV*>( this );
+ }
+
+ bool operator==( QueueFamilyCheckpointPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( checkpointExecutionStageMask == rhs.checkpointExecutionStageMask );
+ }
+
+ bool operator!=( QueueFamilyCheckpointPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eQueueFamilyCheckpointPropertiesNV;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineStageFlags checkpointExecutionStageMask = {};
+ };
+ static_assert( sizeof( QueueFamilyCheckpointPropertiesNV ) == sizeof( VkQueueFamilyCheckpointPropertiesNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<QueueFamilyCheckpointPropertiesNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct QueueFamilyProperties
+ {
+ QueueFamilyProperties( VULKAN_HPP_NAMESPACE::QueueFlags queueFlags_ = {},
+ uint32_t queueCount_ = {},
+ uint32_t timestampValidBits_ = {},
+ VULKAN_HPP_NAMESPACE::Extent3D minImageTransferGranularity_ = {} ) VULKAN_HPP_NOEXCEPT
+ : queueFlags( queueFlags_ )
+ , queueCount( queueCount_ )
+ , timestampValidBits( timestampValidBits_ )
+ , minImageTransferGranularity( minImageTransferGranularity_ )
+ {}
+
+ QueueFamilyProperties( VkQueueFamilyProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ QueueFamilyProperties& operator=( VkQueueFamilyProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::QueueFamilyProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkQueueFamilyProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkQueueFamilyProperties*>( this );
+ }
+
+ operator VkQueueFamilyProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkQueueFamilyProperties*>( this );
+ }
+
+ bool operator==( QueueFamilyProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( queueFlags == rhs.queueFlags )
+ && ( queueCount == rhs.queueCount )
+ && ( timestampValidBits == rhs.timestampValidBits )
+ && ( minImageTransferGranularity == rhs.minImageTransferGranularity );
+ }
+
+ bool operator!=( QueueFamilyProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::QueueFlags queueFlags = {};
+ uint32_t queueCount = {};
+ uint32_t timestampValidBits = {};
+ VULKAN_HPP_NAMESPACE::Extent3D minImageTransferGranularity = {};
+ };
+ static_assert( sizeof( QueueFamilyProperties ) == sizeof( VkQueueFamilyProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<QueueFamilyProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct QueueFamilyProperties2
+ {
+ QueueFamilyProperties2( VULKAN_HPP_NAMESPACE::QueueFamilyProperties queueFamilyProperties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : queueFamilyProperties( queueFamilyProperties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::QueueFamilyProperties2 & operator=( VULKAN_HPP_NAMESPACE::QueueFamilyProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::QueueFamilyProperties2 ) - offsetof( QueueFamilyProperties2, pNext ) );
+ return *this;
+ }
+
+ QueueFamilyProperties2( VkQueueFamilyProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ QueueFamilyProperties2& operator=( VkQueueFamilyProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2 const *>(&rhs);
+ return *this;
+ }
+
+ operator VkQueueFamilyProperties2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkQueueFamilyProperties2*>( this );
+ }
+
+ operator VkQueueFamilyProperties2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkQueueFamilyProperties2*>( this );
+ }
+
+ bool operator==( QueueFamilyProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( queueFamilyProperties == rhs.queueFamilyProperties );
+ }
+
+ bool operator!=( QueueFamilyProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eQueueFamilyProperties2;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::QueueFamilyProperties queueFamilyProperties = {};
+ };
+ static_assert( sizeof( QueueFamilyProperties2 ) == sizeof( VkQueueFamilyProperties2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<QueueFamilyProperties2>::value, "struct wrapper is not a standard layout!" );
+
+ struct RayTracingShaderGroupCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR RayTracingShaderGroupCreateInfoNV( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeNV type_ = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeNV::eGeneral,
+ uint32_t generalShader_ = {},
+ uint32_t closestHitShader_ = {},
+ uint32_t anyHitShader_ = {},
+ uint32_t intersectionShader_ = {} ) VULKAN_HPP_NOEXCEPT
+ : type( type_ )
+ , generalShader( generalShader_ )
+ , closestHitShader( closestHitShader_ )
+ , anyHitShader( anyHitShader_ )
+ , intersectionShader( intersectionShader_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoNV ) - offsetof( RayTracingShaderGroupCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ RayTracingShaderGroupCreateInfoNV( VkRayTracingShaderGroupCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RayTracingShaderGroupCreateInfoNV& operator=( VkRayTracingShaderGroupCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ RayTracingShaderGroupCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ RayTracingShaderGroupCreateInfoNV & setType( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeNV type_ ) VULKAN_HPP_NOEXCEPT
+ {
+ type = type_;
+ return *this;
+ }
+
+ RayTracingShaderGroupCreateInfoNV & setGeneralShader( uint32_t generalShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ generalShader = generalShader_;
+ return *this;
+ }
+
+ RayTracingShaderGroupCreateInfoNV & setClosestHitShader( uint32_t closestHitShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ closestHitShader = closestHitShader_;
+ return *this;
+ }
+
+ RayTracingShaderGroupCreateInfoNV & setAnyHitShader( uint32_t anyHitShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ anyHitShader = anyHitShader_;
+ return *this;
+ }
+
+ RayTracingShaderGroupCreateInfoNV & setIntersectionShader( uint32_t intersectionShader_ ) VULKAN_HPP_NOEXCEPT
+ {
+ intersectionShader = intersectionShader_;
+ return *this;
+ }
+
+ operator VkRayTracingShaderGroupCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRayTracingShaderGroupCreateInfoNV*>( this );
+ }
+
+ operator VkRayTracingShaderGroupCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRayTracingShaderGroupCreateInfoNV*>( this );
+ }
+
+ bool operator==( RayTracingShaderGroupCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( type == rhs.type )
+ && ( generalShader == rhs.generalShader )
+ && ( closestHitShader == rhs.closestHitShader )
+ && ( anyHitShader == rhs.anyHitShader )
+ && ( intersectionShader == rhs.intersectionShader );
+ }
+
+ bool operator!=( RayTracingShaderGroupCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRayTracingShaderGroupCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeNV type = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeNV::eGeneral;
+ uint32_t generalShader = {};
+ uint32_t closestHitShader = {};
+ uint32_t anyHitShader = {};
+ uint32_t intersectionShader = {};
+ };
+ static_assert( sizeof( RayTracingShaderGroupCreateInfoNV ) == sizeof( VkRayTracingShaderGroupCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RayTracingShaderGroupCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct RayTracingPipelineCreateInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR RayTracingPipelineCreateInfoNV( VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags_ = {},
+ uint32_t stageCount_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages_ = {},
+ uint32_t groupCount_ = {},
+ const VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoNV* pGroups_ = {},
+ uint32_t maxRecursionDepth_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineLayout layout_ = {},
+ VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle_ = {},
+ int32_t basePipelineIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , stageCount( stageCount_ )
+ , pStages( pStages_ )
+ , groupCount( groupCount_ )
+ , pGroups( pGroups_ )
+ , maxRecursionDepth( maxRecursionDepth_ )
+ , layout( layout_ )
+ , basePipelineHandle( basePipelineHandle_ )
+ , basePipelineIndex( basePipelineIndex_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV & operator=( VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV ) - offsetof( RayTracingPipelineCreateInfoNV, pNext ) );
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV( VkRayTracingPipelineCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RayTracingPipelineCreateInfoNV& operator=( VkRayTracingPipelineCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV & setFlags( VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV & setStageCount( uint32_t stageCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stageCount = stageCount_;
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV & setPStages( const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pStages = pStages_;
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV & setGroupCount( uint32_t groupCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ groupCount = groupCount_;
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV & setPGroups( const VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoNV* pGroups_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pGroups = pGroups_;
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV & setMaxRecursionDepth( uint32_t maxRecursionDepth_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxRecursionDepth = maxRecursionDepth_;
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV & setLayout( VULKAN_HPP_NAMESPACE::PipelineLayout layout_ ) VULKAN_HPP_NOEXCEPT
+ {
+ layout = layout_;
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV & setBasePipelineHandle( VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle_ ) VULKAN_HPP_NOEXCEPT
+ {
+ basePipelineHandle = basePipelineHandle_;
+ return *this;
+ }
+
+ RayTracingPipelineCreateInfoNV & setBasePipelineIndex( int32_t basePipelineIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ basePipelineIndex = basePipelineIndex_;
+ return *this;
+ }
+
+ operator VkRayTracingPipelineCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( this );
+ }
+
+ operator VkRayTracingPipelineCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRayTracingPipelineCreateInfoNV*>( this );
+ }
+
+ bool operator==( RayTracingPipelineCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( stageCount == rhs.stageCount )
+ && ( pStages == rhs.pStages )
+ && ( groupCount == rhs.groupCount )
+ && ( pGroups == rhs.pGroups )
+ && ( maxRecursionDepth == rhs.maxRecursionDepth )
+ && ( layout == rhs.layout )
+ && ( basePipelineHandle == rhs.basePipelineHandle )
+ && ( basePipelineIndex == rhs.basePipelineIndex );
+ }
+
+ bool operator!=( RayTracingPipelineCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRayTracingPipelineCreateInfoNV;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags = {};
+ uint32_t stageCount = {};
+ const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages = {};
+ uint32_t groupCount = {};
+ const VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoNV* pGroups = {};
+ uint32_t maxRecursionDepth = {};
+ VULKAN_HPP_NAMESPACE::PipelineLayout layout = {};
+ VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle = {};
+ int32_t basePipelineIndex = {};
+ };
+ static_assert( sizeof( RayTracingPipelineCreateInfoNV ) == sizeof( VkRayTracingPipelineCreateInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RayTracingPipelineCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct RefreshCycleDurationGOOGLE
+ {
+ RefreshCycleDurationGOOGLE( uint64_t refreshDuration_ = {} ) VULKAN_HPP_NOEXCEPT
+ : refreshDuration( refreshDuration_ )
+ {}
+
+ RefreshCycleDurationGOOGLE( VkRefreshCycleDurationGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RefreshCycleDurationGOOGLE& operator=( VkRefreshCycleDurationGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RefreshCycleDurationGOOGLE const *>(&rhs);
+ return *this;
+ }
+
+ operator VkRefreshCycleDurationGOOGLE const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRefreshCycleDurationGOOGLE*>( this );
+ }
+
+ operator VkRefreshCycleDurationGOOGLE &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRefreshCycleDurationGOOGLE*>( this );
+ }
+
+ bool operator==( RefreshCycleDurationGOOGLE const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( refreshDuration == rhs.refreshDuration );
+ }
+
+ bool operator!=( RefreshCycleDurationGOOGLE const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint64_t refreshDuration = {};
+ };
+ static_assert( sizeof( RefreshCycleDurationGOOGLE ) == sizeof( VkRefreshCycleDurationGOOGLE ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RefreshCycleDurationGOOGLE>::value, "struct wrapper is not a standard layout!" );
+
+ struct RenderPassAttachmentBeginInfo
+ {
+ VULKAN_HPP_CONSTEXPR RenderPassAttachmentBeginInfo( uint32_t attachmentCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ImageView* pAttachments_ = {} ) VULKAN_HPP_NOEXCEPT
+ : attachmentCount( attachmentCount_ )
+ , pAttachments( pAttachments_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::RenderPassAttachmentBeginInfo & operator=( VULKAN_HPP_NAMESPACE::RenderPassAttachmentBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::RenderPassAttachmentBeginInfo ) - offsetof( RenderPassAttachmentBeginInfo, pNext ) );
+ return *this;
+ }
+
+ RenderPassAttachmentBeginInfo( VkRenderPassAttachmentBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RenderPassAttachmentBeginInfo& operator=( VkRenderPassAttachmentBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RenderPassAttachmentBeginInfo const *>(&rhs);
+ return *this;
+ }
+
+ RenderPassAttachmentBeginInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ RenderPassAttachmentBeginInfo & setAttachmentCount( uint32_t attachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ attachmentCount = attachmentCount_;
+ return *this;
+ }
+
+ RenderPassAttachmentBeginInfo & setPAttachments( const VULKAN_HPP_NAMESPACE::ImageView* pAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttachments = pAttachments_;
+ return *this;
+ }
+
+ operator VkRenderPassAttachmentBeginInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRenderPassAttachmentBeginInfo*>( this );
+ }
+
+ operator VkRenderPassAttachmentBeginInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRenderPassAttachmentBeginInfo*>( this );
+ }
+
+ bool operator==( RenderPassAttachmentBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( attachmentCount == rhs.attachmentCount )
+ && ( pAttachments == rhs.pAttachments );
+ }
+
+ bool operator!=( RenderPassAttachmentBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRenderPassAttachmentBeginInfo;
+ const void* pNext = {};
+ uint32_t attachmentCount = {};
+ const VULKAN_HPP_NAMESPACE::ImageView* pAttachments = {};
+ };
+ static_assert( sizeof( RenderPassAttachmentBeginInfo ) == sizeof( VkRenderPassAttachmentBeginInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RenderPassAttachmentBeginInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct RenderPassBeginInfo
+ {
+ VULKAN_HPP_CONSTEXPR RenderPassBeginInfo( VULKAN_HPP_NAMESPACE::RenderPass renderPass_ = {},
+ VULKAN_HPP_NAMESPACE::Framebuffer framebuffer_ = {},
+ VULKAN_HPP_NAMESPACE::Rect2D renderArea_ = {},
+ uint32_t clearValueCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ClearValue* pClearValues_ = {} ) VULKAN_HPP_NOEXCEPT
+ : renderPass( renderPass_ )
+ , framebuffer( framebuffer_ )
+ , renderArea( renderArea_ )
+ , clearValueCount( clearValueCount_ )
+ , pClearValues( pClearValues_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::RenderPassBeginInfo & operator=( VULKAN_HPP_NAMESPACE::RenderPassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::RenderPassBeginInfo ) - offsetof( RenderPassBeginInfo, pNext ) );
+ return *this;
+ }
+
+ RenderPassBeginInfo( VkRenderPassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RenderPassBeginInfo& operator=( VkRenderPassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RenderPassBeginInfo const *>(&rhs);
+ return *this;
+ }
+
+ RenderPassBeginInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ RenderPassBeginInfo & setRenderPass( VULKAN_HPP_NAMESPACE::RenderPass renderPass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ renderPass = renderPass_;
+ return *this;
+ }
+
+ RenderPassBeginInfo & setFramebuffer( VULKAN_HPP_NAMESPACE::Framebuffer framebuffer_ ) VULKAN_HPP_NOEXCEPT
+ {
+ framebuffer = framebuffer_;
+ return *this;
+ }
+
+ RenderPassBeginInfo & setRenderArea( VULKAN_HPP_NAMESPACE::Rect2D renderArea_ ) VULKAN_HPP_NOEXCEPT
+ {
+ renderArea = renderArea_;
+ return *this;
+ }
+
+ RenderPassBeginInfo & setClearValueCount( uint32_t clearValueCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ clearValueCount = clearValueCount_;
+ return *this;
+ }
+
+ RenderPassBeginInfo & setPClearValues( const VULKAN_HPP_NAMESPACE::ClearValue* pClearValues_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pClearValues = pClearValues_;
+ return *this;
+ }
+
+ operator VkRenderPassBeginInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRenderPassBeginInfo*>( this );
+ }
+
+ operator VkRenderPassBeginInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRenderPassBeginInfo*>( this );
+ }
+
+ bool operator==( RenderPassBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( renderPass == rhs.renderPass )
+ && ( framebuffer == rhs.framebuffer )
+ && ( renderArea == rhs.renderArea )
+ && ( clearValueCount == rhs.clearValueCount )
+ && ( pClearValues == rhs.pClearValues );
+ }
+
+ bool operator!=( RenderPassBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRenderPassBeginInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass = {};
+ VULKAN_HPP_NAMESPACE::Framebuffer framebuffer = {};
+ VULKAN_HPP_NAMESPACE::Rect2D renderArea = {};
+ uint32_t clearValueCount = {};
+ const VULKAN_HPP_NAMESPACE::ClearValue* pClearValues = {};
+ };
+ static_assert( sizeof( RenderPassBeginInfo ) == sizeof( VkRenderPassBeginInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RenderPassBeginInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SubpassDescription
+ {
+ VULKAN_HPP_CONSTEXPR SubpassDescription( VULKAN_HPP_NAMESPACE::SubpassDescriptionFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics,
+ uint32_t inputAttachmentCount_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentReference* pInputAttachments_ = {},
+ uint32_t colorAttachmentCount_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentReference* pColorAttachments_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentReference* pResolveAttachments_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentReference* pDepthStencilAttachment_ = {},
+ uint32_t preserveAttachmentCount_ = {},
+ const uint32_t* pPreserveAttachments_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , pipelineBindPoint( pipelineBindPoint_ )
+ , inputAttachmentCount( inputAttachmentCount_ )
+ , pInputAttachments( pInputAttachments_ )
+ , colorAttachmentCount( colorAttachmentCount_ )
+ , pColorAttachments( pColorAttachments_ )
+ , pResolveAttachments( pResolveAttachments_ )
+ , pDepthStencilAttachment( pDepthStencilAttachment_ )
+ , preserveAttachmentCount( preserveAttachmentCount_ )
+ , pPreserveAttachments( pPreserveAttachments_ )
+ {}
+
+ SubpassDescription( VkSubpassDescription const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SubpassDescription& operator=( VkSubpassDescription const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SubpassDescription const *>(&rhs);
+ return *this;
+ }
+
+ SubpassDescription & setFlags( VULKAN_HPP_NAMESPACE::SubpassDescriptionFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ SubpassDescription & setPipelineBindPoint( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineBindPoint = pipelineBindPoint_;
+ return *this;
+ }
+
+ SubpassDescription & setInputAttachmentCount( uint32_t inputAttachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ inputAttachmentCount = inputAttachmentCount_;
+ return *this;
+ }
+
+ SubpassDescription & setPInputAttachments( const VULKAN_HPP_NAMESPACE::AttachmentReference* pInputAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pInputAttachments = pInputAttachments_;
+ return *this;
+ }
+
+ SubpassDescription & setColorAttachmentCount( uint32_t colorAttachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ colorAttachmentCount = colorAttachmentCount_;
+ return *this;
+ }
+
+ SubpassDescription & setPColorAttachments( const VULKAN_HPP_NAMESPACE::AttachmentReference* pColorAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pColorAttachments = pColorAttachments_;
+ return *this;
+ }
+
+ SubpassDescription & setPResolveAttachments( const VULKAN_HPP_NAMESPACE::AttachmentReference* pResolveAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pResolveAttachments = pResolveAttachments_;
+ return *this;
+ }
+
+ SubpassDescription & setPDepthStencilAttachment( const VULKAN_HPP_NAMESPACE::AttachmentReference* pDepthStencilAttachment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDepthStencilAttachment = pDepthStencilAttachment_;
+ return *this;
+ }
+
+ SubpassDescription & setPreserveAttachmentCount( uint32_t preserveAttachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ preserveAttachmentCount = preserveAttachmentCount_;
+ return *this;
+ }
+
+ SubpassDescription & setPPreserveAttachments( const uint32_t* pPreserveAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pPreserveAttachments = pPreserveAttachments_;
+ return *this;
+ }
+
+ operator VkSubpassDescription const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSubpassDescription*>( this );
+ }
+
+ operator VkSubpassDescription &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSubpassDescription*>( this );
+ }
+
+ bool operator==( SubpassDescription const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( flags == rhs.flags )
+ && ( pipelineBindPoint == rhs.pipelineBindPoint )
+ && ( inputAttachmentCount == rhs.inputAttachmentCount )
+ && ( pInputAttachments == rhs.pInputAttachments )
+ && ( colorAttachmentCount == rhs.colorAttachmentCount )
+ && ( pColorAttachments == rhs.pColorAttachments )
+ && ( pResolveAttachments == rhs.pResolveAttachments )
+ && ( pDepthStencilAttachment == rhs.pDepthStencilAttachment )
+ && ( preserveAttachmentCount == rhs.preserveAttachmentCount )
+ && ( pPreserveAttachments == rhs.pPreserveAttachments );
+ }
+
+ bool operator!=( SubpassDescription const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::SubpassDescriptionFlags flags = {};
+ VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics;
+ uint32_t inputAttachmentCount = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentReference* pInputAttachments = {};
+ uint32_t colorAttachmentCount = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentReference* pColorAttachments = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentReference* pResolveAttachments = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentReference* pDepthStencilAttachment = {};
+ uint32_t preserveAttachmentCount = {};
+ const uint32_t* pPreserveAttachments = {};
+ };
+ static_assert( sizeof( SubpassDescription ) == sizeof( VkSubpassDescription ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SubpassDescription>::value, "struct wrapper is not a standard layout!" );
+
+ struct SubpassDependency
+ {
+ VULKAN_HPP_CONSTEXPR SubpassDependency( uint32_t srcSubpass_ = {},
+ uint32_t dstSubpass_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask_ = {},
+ VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask_ = {},
+ VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask_ = {},
+ VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcSubpass( srcSubpass_ )
+ , dstSubpass( dstSubpass_ )
+ , srcStageMask( srcStageMask_ )
+ , dstStageMask( dstStageMask_ )
+ , srcAccessMask( srcAccessMask_ )
+ , dstAccessMask( dstAccessMask_ )
+ , dependencyFlags( dependencyFlags_ )
+ {}
+
+ SubpassDependency( VkSubpassDependency const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SubpassDependency& operator=( VkSubpassDependency const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SubpassDependency const *>(&rhs);
+ return *this;
+ }
+
+ SubpassDependency & setSrcSubpass( uint32_t srcSubpass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcSubpass = srcSubpass_;
+ return *this;
+ }
+
+ SubpassDependency & setDstSubpass( uint32_t dstSubpass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstSubpass = dstSubpass_;
+ return *this;
+ }
+
+ SubpassDependency & setSrcStageMask( VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcStageMask = srcStageMask_;
+ return *this;
+ }
+
+ SubpassDependency & setDstStageMask( VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstStageMask = dstStageMask_;
+ return *this;
+ }
+
+ SubpassDependency & setSrcAccessMask( VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcAccessMask = srcAccessMask_;
+ return *this;
+ }
+
+ SubpassDependency & setDstAccessMask( VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstAccessMask = dstAccessMask_;
+ return *this;
+ }
+
+ SubpassDependency & setDependencyFlags( VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dependencyFlags = dependencyFlags_;
+ return *this;
+ }
+
+ operator VkSubpassDependency const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSubpassDependency*>( this );
+ }
+
+ operator VkSubpassDependency &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSubpassDependency*>( this );
+ }
+
+ bool operator==( SubpassDependency const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( srcSubpass == rhs.srcSubpass )
+ && ( dstSubpass == rhs.dstSubpass )
+ && ( srcStageMask == rhs.srcStageMask )
+ && ( dstStageMask == rhs.dstStageMask )
+ && ( srcAccessMask == rhs.srcAccessMask )
+ && ( dstAccessMask == rhs.dstAccessMask )
+ && ( dependencyFlags == rhs.dependencyFlags );
+ }
+
+ bool operator!=( SubpassDependency const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t srcSubpass = {};
+ uint32_t dstSubpass = {};
+ VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask = {};
+ VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask = {};
+ VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask = {};
+ VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask = {};
+ VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags = {};
+ };
+ static_assert( sizeof( SubpassDependency ) == sizeof( VkSubpassDependency ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SubpassDependency>::value, "struct wrapper is not a standard layout!" );
+
+ struct RenderPassCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR RenderPassCreateInfo( VULKAN_HPP_NAMESPACE::RenderPassCreateFlags flags_ = {},
+ uint32_t attachmentCount_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentDescription* pAttachments_ = {},
+ uint32_t subpassCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SubpassDescription* pSubpasses_ = {},
+ uint32_t dependencyCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SubpassDependency* pDependencies_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , attachmentCount( attachmentCount_ )
+ , pAttachments( pAttachments_ )
+ , subpassCount( subpassCount_ )
+ , pSubpasses( pSubpasses_ )
+ , dependencyCount( dependencyCount_ )
+ , pDependencies( pDependencies_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::RenderPassCreateInfo & operator=( VULKAN_HPP_NAMESPACE::RenderPassCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::RenderPassCreateInfo ) - offsetof( RenderPassCreateInfo, pNext ) );
+ return *this;
+ }
+
+ RenderPassCreateInfo( VkRenderPassCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RenderPassCreateInfo& operator=( VkRenderPassCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RenderPassCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ RenderPassCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ RenderPassCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::RenderPassCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ RenderPassCreateInfo & setAttachmentCount( uint32_t attachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ attachmentCount = attachmentCount_;
+ return *this;
+ }
+
+ RenderPassCreateInfo & setPAttachments( const VULKAN_HPP_NAMESPACE::AttachmentDescription* pAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttachments = pAttachments_;
+ return *this;
+ }
+
+ RenderPassCreateInfo & setSubpassCount( uint32_t subpassCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subpassCount = subpassCount_;
+ return *this;
+ }
+
+ RenderPassCreateInfo & setPSubpasses( const VULKAN_HPP_NAMESPACE::SubpassDescription* pSubpasses_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSubpasses = pSubpasses_;
+ return *this;
+ }
+
+ RenderPassCreateInfo & setDependencyCount( uint32_t dependencyCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dependencyCount = dependencyCount_;
+ return *this;
+ }
+
+ RenderPassCreateInfo & setPDependencies( const VULKAN_HPP_NAMESPACE::SubpassDependency* pDependencies_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDependencies = pDependencies_;
+ return *this;
+ }
+
+ operator VkRenderPassCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRenderPassCreateInfo*>( this );
+ }
+
+ operator VkRenderPassCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRenderPassCreateInfo*>( this );
+ }
+
+ bool operator==( RenderPassCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( attachmentCount == rhs.attachmentCount )
+ && ( pAttachments == rhs.pAttachments )
+ && ( subpassCount == rhs.subpassCount )
+ && ( pSubpasses == rhs.pSubpasses )
+ && ( dependencyCount == rhs.dependencyCount )
+ && ( pDependencies == rhs.pDependencies );
+ }
+
+ bool operator!=( RenderPassCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRenderPassCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::RenderPassCreateFlags flags = {};
+ uint32_t attachmentCount = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentDescription* pAttachments = {};
+ uint32_t subpassCount = {};
+ const VULKAN_HPP_NAMESPACE::SubpassDescription* pSubpasses = {};
+ uint32_t dependencyCount = {};
+ const VULKAN_HPP_NAMESPACE::SubpassDependency* pDependencies = {};
+ };
+ static_assert( sizeof( RenderPassCreateInfo ) == sizeof( VkRenderPassCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RenderPassCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SubpassDescription2
+ {
+ VULKAN_HPP_CONSTEXPR SubpassDescription2( VULKAN_HPP_NAMESPACE::SubpassDescriptionFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics,
+ uint32_t viewMask_ = {},
+ uint32_t inputAttachmentCount_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentReference2* pInputAttachments_ = {},
+ uint32_t colorAttachmentCount_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentReference2* pColorAttachments_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentReference2* pResolveAttachments_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentReference2* pDepthStencilAttachment_ = {},
+ uint32_t preserveAttachmentCount_ = {},
+ const uint32_t* pPreserveAttachments_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , pipelineBindPoint( pipelineBindPoint_ )
+ , viewMask( viewMask_ )
+ , inputAttachmentCount( inputAttachmentCount_ )
+ , pInputAttachments( pInputAttachments_ )
+ , colorAttachmentCount( colorAttachmentCount_ )
+ , pColorAttachments( pColorAttachments_ )
+ , pResolveAttachments( pResolveAttachments_ )
+ , pDepthStencilAttachment( pDepthStencilAttachment_ )
+ , preserveAttachmentCount( preserveAttachmentCount_ )
+ , pPreserveAttachments( pPreserveAttachments_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SubpassDescription2 & operator=( VULKAN_HPP_NAMESPACE::SubpassDescription2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SubpassDescription2 ) - offsetof( SubpassDescription2, pNext ) );
+ return *this;
+ }
+
+ SubpassDescription2( VkSubpassDescription2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SubpassDescription2& operator=( VkSubpassDescription2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SubpassDescription2 const *>(&rhs);
+ return *this;
+ }
+
+ SubpassDescription2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SubpassDescription2 & setFlags( VULKAN_HPP_NAMESPACE::SubpassDescriptionFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ SubpassDescription2 & setPipelineBindPoint( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pipelineBindPoint = pipelineBindPoint_;
+ return *this;
+ }
+
+ SubpassDescription2 & setViewMask( uint32_t viewMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ viewMask = viewMask_;
+ return *this;
+ }
+
+ SubpassDescription2 & setInputAttachmentCount( uint32_t inputAttachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ inputAttachmentCount = inputAttachmentCount_;
+ return *this;
+ }
+
+ SubpassDescription2 & setPInputAttachments( const VULKAN_HPP_NAMESPACE::AttachmentReference2* pInputAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pInputAttachments = pInputAttachments_;
+ return *this;
+ }
+
+ SubpassDescription2 & setColorAttachmentCount( uint32_t colorAttachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ colorAttachmentCount = colorAttachmentCount_;
+ return *this;
+ }
+
+ SubpassDescription2 & setPColorAttachments( const VULKAN_HPP_NAMESPACE::AttachmentReference2* pColorAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pColorAttachments = pColorAttachments_;
+ return *this;
+ }
+
+ SubpassDescription2 & setPResolveAttachments( const VULKAN_HPP_NAMESPACE::AttachmentReference2* pResolveAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pResolveAttachments = pResolveAttachments_;
+ return *this;
+ }
+
+ SubpassDescription2 & setPDepthStencilAttachment( const VULKAN_HPP_NAMESPACE::AttachmentReference2* pDepthStencilAttachment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDepthStencilAttachment = pDepthStencilAttachment_;
+ return *this;
+ }
+
+ SubpassDescription2 & setPreserveAttachmentCount( uint32_t preserveAttachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ preserveAttachmentCount = preserveAttachmentCount_;
+ return *this;
+ }
+
+ SubpassDescription2 & setPPreserveAttachments( const uint32_t* pPreserveAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pPreserveAttachments = pPreserveAttachments_;
+ return *this;
+ }
+
+ operator VkSubpassDescription2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSubpassDescription2*>( this );
+ }
+
+ operator VkSubpassDescription2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSubpassDescription2*>( this );
+ }
+
+ bool operator==( SubpassDescription2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( pipelineBindPoint == rhs.pipelineBindPoint )
+ && ( viewMask == rhs.viewMask )
+ && ( inputAttachmentCount == rhs.inputAttachmentCount )
+ && ( pInputAttachments == rhs.pInputAttachments )
+ && ( colorAttachmentCount == rhs.colorAttachmentCount )
+ && ( pColorAttachments == rhs.pColorAttachments )
+ && ( pResolveAttachments == rhs.pResolveAttachments )
+ && ( pDepthStencilAttachment == rhs.pDepthStencilAttachment )
+ && ( preserveAttachmentCount == rhs.preserveAttachmentCount )
+ && ( pPreserveAttachments == rhs.pPreserveAttachments );
+ }
+
+ bool operator!=( SubpassDescription2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSubpassDescription2;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SubpassDescriptionFlags flags = {};
+ VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics;
+ uint32_t viewMask = {};
+ uint32_t inputAttachmentCount = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentReference2* pInputAttachments = {};
+ uint32_t colorAttachmentCount = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentReference2* pColorAttachments = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentReference2* pResolveAttachments = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentReference2* pDepthStencilAttachment = {};
+ uint32_t preserveAttachmentCount = {};
+ const uint32_t* pPreserveAttachments = {};
+ };
+ static_assert( sizeof( SubpassDescription2 ) == sizeof( VkSubpassDescription2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SubpassDescription2>::value, "struct wrapper is not a standard layout!" );
+
+ struct SubpassDependency2
+ {
+ VULKAN_HPP_CONSTEXPR SubpassDependency2( uint32_t srcSubpass_ = {},
+ uint32_t dstSubpass_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask_ = {},
+ VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask_ = {},
+ VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask_ = {},
+ VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask_ = {},
+ VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags_ = {},
+ int32_t viewOffset_ = {} ) VULKAN_HPP_NOEXCEPT
+ : srcSubpass( srcSubpass_ )
+ , dstSubpass( dstSubpass_ )
+ , srcStageMask( srcStageMask_ )
+ , dstStageMask( dstStageMask_ )
+ , srcAccessMask( srcAccessMask_ )
+ , dstAccessMask( dstAccessMask_ )
+ , dependencyFlags( dependencyFlags_ )
+ , viewOffset( viewOffset_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SubpassDependency2 & operator=( VULKAN_HPP_NAMESPACE::SubpassDependency2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SubpassDependency2 ) - offsetof( SubpassDependency2, pNext ) );
+ return *this;
+ }
+
+ SubpassDependency2( VkSubpassDependency2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SubpassDependency2& operator=( VkSubpassDependency2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SubpassDependency2 const *>(&rhs);
+ return *this;
+ }
+
+ SubpassDependency2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SubpassDependency2 & setSrcSubpass( uint32_t srcSubpass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcSubpass = srcSubpass_;
+ return *this;
+ }
+
+ SubpassDependency2 & setDstSubpass( uint32_t dstSubpass_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstSubpass = dstSubpass_;
+ return *this;
+ }
+
+ SubpassDependency2 & setSrcStageMask( VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcStageMask = srcStageMask_;
+ return *this;
+ }
+
+ SubpassDependency2 & setDstStageMask( VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstStageMask = dstStageMask_;
+ return *this;
+ }
+
+ SubpassDependency2 & setSrcAccessMask( VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ srcAccessMask = srcAccessMask_;
+ return *this;
+ }
+
+ SubpassDependency2 & setDstAccessMask( VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstAccessMask = dstAccessMask_;
+ return *this;
+ }
+
+ SubpassDependency2 & setDependencyFlags( VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dependencyFlags = dependencyFlags_;
+ return *this;
+ }
+
+ SubpassDependency2 & setViewOffset( int32_t viewOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ viewOffset = viewOffset_;
+ return *this;
+ }
+
+ operator VkSubpassDependency2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSubpassDependency2*>( this );
+ }
+
+ operator VkSubpassDependency2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSubpassDependency2*>( this );
+ }
+
+ bool operator==( SubpassDependency2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( srcSubpass == rhs.srcSubpass )
+ && ( dstSubpass == rhs.dstSubpass )
+ && ( srcStageMask == rhs.srcStageMask )
+ && ( dstStageMask == rhs.dstStageMask )
+ && ( srcAccessMask == rhs.srcAccessMask )
+ && ( dstAccessMask == rhs.dstAccessMask )
+ && ( dependencyFlags == rhs.dependencyFlags )
+ && ( viewOffset == rhs.viewOffset );
+ }
+
+ bool operator!=( SubpassDependency2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSubpassDependency2;
+ const void* pNext = {};
+ uint32_t srcSubpass = {};
+ uint32_t dstSubpass = {};
+ VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask = {};
+ VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask = {};
+ VULKAN_HPP_NAMESPACE::AccessFlags srcAccessMask = {};
+ VULKAN_HPP_NAMESPACE::AccessFlags dstAccessMask = {};
+ VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags = {};
+ int32_t viewOffset = {};
+ };
+ static_assert( sizeof( SubpassDependency2 ) == sizeof( VkSubpassDependency2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SubpassDependency2>::value, "struct wrapper is not a standard layout!" );
+
+ struct RenderPassCreateInfo2
+ {
+ VULKAN_HPP_CONSTEXPR RenderPassCreateInfo2( VULKAN_HPP_NAMESPACE::RenderPassCreateFlags flags_ = {},
+ uint32_t attachmentCount_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentDescription2* pAttachments_ = {},
+ uint32_t subpassCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SubpassDescription2* pSubpasses_ = {},
+ uint32_t dependencyCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SubpassDependency2* pDependencies_ = {},
+ uint32_t correlatedViewMaskCount_ = {},
+ const uint32_t* pCorrelatedViewMasks_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , attachmentCount( attachmentCount_ )
+ , pAttachments( pAttachments_ )
+ , subpassCount( subpassCount_ )
+ , pSubpasses( pSubpasses_ )
+ , dependencyCount( dependencyCount_ )
+ , pDependencies( pDependencies_ )
+ , correlatedViewMaskCount( correlatedViewMaskCount_ )
+ , pCorrelatedViewMasks( pCorrelatedViewMasks_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::RenderPassCreateInfo2 & operator=( VULKAN_HPP_NAMESPACE::RenderPassCreateInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::RenderPassCreateInfo2 ) - offsetof( RenderPassCreateInfo2, pNext ) );
+ return *this;
+ }
+
+ RenderPassCreateInfo2( VkRenderPassCreateInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RenderPassCreateInfo2& operator=( VkRenderPassCreateInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RenderPassCreateInfo2 const *>(&rhs);
+ return *this;
+ }
+
+ RenderPassCreateInfo2 & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ RenderPassCreateInfo2 & setFlags( VULKAN_HPP_NAMESPACE::RenderPassCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ RenderPassCreateInfo2 & setAttachmentCount( uint32_t attachmentCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ attachmentCount = attachmentCount_;
+ return *this;
+ }
+
+ RenderPassCreateInfo2 & setPAttachments( const VULKAN_HPP_NAMESPACE::AttachmentDescription2* pAttachments_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttachments = pAttachments_;
+ return *this;
+ }
+
+ RenderPassCreateInfo2 & setSubpassCount( uint32_t subpassCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subpassCount = subpassCount_;
+ return *this;
+ }
+
+ RenderPassCreateInfo2 & setPSubpasses( const VULKAN_HPP_NAMESPACE::SubpassDescription2* pSubpasses_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSubpasses = pSubpasses_;
+ return *this;
+ }
+
+ RenderPassCreateInfo2 & setDependencyCount( uint32_t dependencyCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dependencyCount = dependencyCount_;
+ return *this;
+ }
+
+ RenderPassCreateInfo2 & setPDependencies( const VULKAN_HPP_NAMESPACE::SubpassDependency2* pDependencies_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDependencies = pDependencies_;
+ return *this;
+ }
+
+ RenderPassCreateInfo2 & setCorrelatedViewMaskCount( uint32_t correlatedViewMaskCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ correlatedViewMaskCount = correlatedViewMaskCount_;
+ return *this;
+ }
+
+ RenderPassCreateInfo2 & setPCorrelatedViewMasks( const uint32_t* pCorrelatedViewMasks_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pCorrelatedViewMasks = pCorrelatedViewMasks_;
+ return *this;
+ }
+
+ operator VkRenderPassCreateInfo2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRenderPassCreateInfo2*>( this );
+ }
+
+ operator VkRenderPassCreateInfo2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRenderPassCreateInfo2*>( this );
+ }
+
+ bool operator==( RenderPassCreateInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( attachmentCount == rhs.attachmentCount )
+ && ( pAttachments == rhs.pAttachments )
+ && ( subpassCount == rhs.subpassCount )
+ && ( pSubpasses == rhs.pSubpasses )
+ && ( dependencyCount == rhs.dependencyCount )
+ && ( pDependencies == rhs.pDependencies )
+ && ( correlatedViewMaskCount == rhs.correlatedViewMaskCount )
+ && ( pCorrelatedViewMasks == rhs.pCorrelatedViewMasks );
+ }
+
+ bool operator!=( RenderPassCreateInfo2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRenderPassCreateInfo2;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::RenderPassCreateFlags flags = {};
+ uint32_t attachmentCount = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentDescription2* pAttachments = {};
+ uint32_t subpassCount = {};
+ const VULKAN_HPP_NAMESPACE::SubpassDescription2* pSubpasses = {};
+ uint32_t dependencyCount = {};
+ const VULKAN_HPP_NAMESPACE::SubpassDependency2* pDependencies = {};
+ uint32_t correlatedViewMaskCount = {};
+ const uint32_t* pCorrelatedViewMasks = {};
+ };
+ static_assert( sizeof( RenderPassCreateInfo2 ) == sizeof( VkRenderPassCreateInfo2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RenderPassCreateInfo2>::value, "struct wrapper is not a standard layout!" );
+
+ struct RenderPassFragmentDensityMapCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR RenderPassFragmentDensityMapCreateInfoEXT( VULKAN_HPP_NAMESPACE::AttachmentReference fragmentDensityMapAttachment_ = {} ) VULKAN_HPP_NOEXCEPT
+ : fragmentDensityMapAttachment( fragmentDensityMapAttachment_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::RenderPassFragmentDensityMapCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::RenderPassFragmentDensityMapCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::RenderPassFragmentDensityMapCreateInfoEXT ) - offsetof( RenderPassFragmentDensityMapCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ RenderPassFragmentDensityMapCreateInfoEXT( VkRenderPassFragmentDensityMapCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RenderPassFragmentDensityMapCreateInfoEXT& operator=( VkRenderPassFragmentDensityMapCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RenderPassFragmentDensityMapCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ RenderPassFragmentDensityMapCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ RenderPassFragmentDensityMapCreateInfoEXT & setFragmentDensityMapAttachment( VULKAN_HPP_NAMESPACE::AttachmentReference fragmentDensityMapAttachment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fragmentDensityMapAttachment = fragmentDensityMapAttachment_;
+ return *this;
+ }
+
+ operator VkRenderPassFragmentDensityMapCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRenderPassFragmentDensityMapCreateInfoEXT*>( this );
+ }
+
+ operator VkRenderPassFragmentDensityMapCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRenderPassFragmentDensityMapCreateInfoEXT*>( this );
+ }
+
+ bool operator==( RenderPassFragmentDensityMapCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( fragmentDensityMapAttachment == rhs.fragmentDensityMapAttachment );
+ }
+
+ bool operator!=( RenderPassFragmentDensityMapCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRenderPassFragmentDensityMapCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::AttachmentReference fragmentDensityMapAttachment = {};
+ };
+ static_assert( sizeof( RenderPassFragmentDensityMapCreateInfoEXT ) == sizeof( VkRenderPassFragmentDensityMapCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RenderPassFragmentDensityMapCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct RenderPassInputAttachmentAspectCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR RenderPassInputAttachmentAspectCreateInfo( uint32_t aspectReferenceCount_ = {},
+ const VULKAN_HPP_NAMESPACE::InputAttachmentAspectReference* pAspectReferences_ = {} ) VULKAN_HPP_NOEXCEPT
+ : aspectReferenceCount( aspectReferenceCount_ )
+ , pAspectReferences( pAspectReferences_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::RenderPassInputAttachmentAspectCreateInfo & operator=( VULKAN_HPP_NAMESPACE::RenderPassInputAttachmentAspectCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::RenderPassInputAttachmentAspectCreateInfo ) - offsetof( RenderPassInputAttachmentAspectCreateInfo, pNext ) );
+ return *this;
+ }
+
+ RenderPassInputAttachmentAspectCreateInfo( VkRenderPassInputAttachmentAspectCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RenderPassInputAttachmentAspectCreateInfo& operator=( VkRenderPassInputAttachmentAspectCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RenderPassInputAttachmentAspectCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ RenderPassInputAttachmentAspectCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ RenderPassInputAttachmentAspectCreateInfo & setAspectReferenceCount( uint32_t aspectReferenceCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ aspectReferenceCount = aspectReferenceCount_;
+ return *this;
+ }
+
+ RenderPassInputAttachmentAspectCreateInfo & setPAspectReferences( const VULKAN_HPP_NAMESPACE::InputAttachmentAspectReference* pAspectReferences_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAspectReferences = pAspectReferences_;
+ return *this;
+ }
+
+ operator VkRenderPassInputAttachmentAspectCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRenderPassInputAttachmentAspectCreateInfo*>( this );
+ }
+
+ operator VkRenderPassInputAttachmentAspectCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRenderPassInputAttachmentAspectCreateInfo*>( this );
+ }
+
+ bool operator==( RenderPassInputAttachmentAspectCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( aspectReferenceCount == rhs.aspectReferenceCount )
+ && ( pAspectReferences == rhs.pAspectReferences );
+ }
+
+ bool operator!=( RenderPassInputAttachmentAspectCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRenderPassInputAttachmentAspectCreateInfo;
+ const void* pNext = {};
+ uint32_t aspectReferenceCount = {};
+ const VULKAN_HPP_NAMESPACE::InputAttachmentAspectReference* pAspectReferences = {};
+ };
+ static_assert( sizeof( RenderPassInputAttachmentAspectCreateInfo ) == sizeof( VkRenderPassInputAttachmentAspectCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RenderPassInputAttachmentAspectCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct RenderPassMultiviewCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR RenderPassMultiviewCreateInfo( uint32_t subpassCount_ = {},
+ const uint32_t* pViewMasks_ = {},
+ uint32_t dependencyCount_ = {},
+ const int32_t* pViewOffsets_ = {},
+ uint32_t correlationMaskCount_ = {},
+ const uint32_t* pCorrelationMasks_ = {} ) VULKAN_HPP_NOEXCEPT
+ : subpassCount( subpassCount_ )
+ , pViewMasks( pViewMasks_ )
+ , dependencyCount( dependencyCount_ )
+ , pViewOffsets( pViewOffsets_ )
+ , correlationMaskCount( correlationMaskCount_ )
+ , pCorrelationMasks( pCorrelationMasks_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::RenderPassMultiviewCreateInfo & operator=( VULKAN_HPP_NAMESPACE::RenderPassMultiviewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::RenderPassMultiviewCreateInfo ) - offsetof( RenderPassMultiviewCreateInfo, pNext ) );
+ return *this;
+ }
+
+ RenderPassMultiviewCreateInfo( VkRenderPassMultiviewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RenderPassMultiviewCreateInfo& operator=( VkRenderPassMultiviewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RenderPassMultiviewCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ RenderPassMultiviewCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ RenderPassMultiviewCreateInfo & setSubpassCount( uint32_t subpassCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subpassCount = subpassCount_;
+ return *this;
+ }
+
+ RenderPassMultiviewCreateInfo & setPViewMasks( const uint32_t* pViewMasks_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pViewMasks = pViewMasks_;
+ return *this;
+ }
+
+ RenderPassMultiviewCreateInfo & setDependencyCount( uint32_t dependencyCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dependencyCount = dependencyCount_;
+ return *this;
+ }
+
+ RenderPassMultiviewCreateInfo & setPViewOffsets( const int32_t* pViewOffsets_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pViewOffsets = pViewOffsets_;
+ return *this;
+ }
+
+ RenderPassMultiviewCreateInfo & setCorrelationMaskCount( uint32_t correlationMaskCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ correlationMaskCount = correlationMaskCount_;
+ return *this;
+ }
+
+ RenderPassMultiviewCreateInfo & setPCorrelationMasks( const uint32_t* pCorrelationMasks_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pCorrelationMasks = pCorrelationMasks_;
+ return *this;
+ }
+
+ operator VkRenderPassMultiviewCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRenderPassMultiviewCreateInfo*>( this );
+ }
+
+ operator VkRenderPassMultiviewCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRenderPassMultiviewCreateInfo*>( this );
+ }
+
+ bool operator==( RenderPassMultiviewCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( subpassCount == rhs.subpassCount )
+ && ( pViewMasks == rhs.pViewMasks )
+ && ( dependencyCount == rhs.dependencyCount )
+ && ( pViewOffsets == rhs.pViewOffsets )
+ && ( correlationMaskCount == rhs.correlationMaskCount )
+ && ( pCorrelationMasks == rhs.pCorrelationMasks );
+ }
+
+ bool operator!=( RenderPassMultiviewCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRenderPassMultiviewCreateInfo;
+ const void* pNext = {};
+ uint32_t subpassCount = {};
+ const uint32_t* pViewMasks = {};
+ uint32_t dependencyCount = {};
+ const int32_t* pViewOffsets = {};
+ uint32_t correlationMaskCount = {};
+ const uint32_t* pCorrelationMasks = {};
+ };
+ static_assert( sizeof( RenderPassMultiviewCreateInfo ) == sizeof( VkRenderPassMultiviewCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RenderPassMultiviewCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SubpassSampleLocationsEXT
+ {
+ VULKAN_HPP_CONSTEXPR SubpassSampleLocationsEXT( uint32_t subpassIndex_ = {},
+ VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT sampleLocationsInfo_ = {} ) VULKAN_HPP_NOEXCEPT
+ : subpassIndex( subpassIndex_ )
+ , sampleLocationsInfo( sampleLocationsInfo_ )
+ {}
+
+ SubpassSampleLocationsEXT( VkSubpassSampleLocationsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SubpassSampleLocationsEXT& operator=( VkSubpassSampleLocationsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SubpassSampleLocationsEXT const *>(&rhs);
+ return *this;
+ }
+
+ SubpassSampleLocationsEXT & setSubpassIndex( uint32_t subpassIndex_ ) VULKAN_HPP_NOEXCEPT
+ {
+ subpassIndex = subpassIndex_;
+ return *this;
+ }
+
+ SubpassSampleLocationsEXT & setSampleLocationsInfo( VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT sampleLocationsInfo_ ) VULKAN_HPP_NOEXCEPT
+ {
+ sampleLocationsInfo = sampleLocationsInfo_;
+ return *this;
+ }
+
+ operator VkSubpassSampleLocationsEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSubpassSampleLocationsEXT*>( this );
+ }
+
+ operator VkSubpassSampleLocationsEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSubpassSampleLocationsEXT*>( this );
+ }
+
+ bool operator==( SubpassSampleLocationsEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( subpassIndex == rhs.subpassIndex )
+ && ( sampleLocationsInfo == rhs.sampleLocationsInfo );
+ }
+
+ bool operator!=( SubpassSampleLocationsEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t subpassIndex = {};
+ VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT sampleLocationsInfo = {};
+ };
+ static_assert( sizeof( SubpassSampleLocationsEXT ) == sizeof( VkSubpassSampleLocationsEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SubpassSampleLocationsEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct RenderPassSampleLocationsBeginInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR RenderPassSampleLocationsBeginInfoEXT( uint32_t attachmentInitialSampleLocationsCount_ = {},
+ const VULKAN_HPP_NAMESPACE::AttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations_ = {},
+ uint32_t postSubpassSampleLocationsCount_ = {},
+ const VULKAN_HPP_NAMESPACE::SubpassSampleLocationsEXT* pPostSubpassSampleLocations_ = {} ) VULKAN_HPP_NOEXCEPT
+ : attachmentInitialSampleLocationsCount( attachmentInitialSampleLocationsCount_ )
+ , pAttachmentInitialSampleLocations( pAttachmentInitialSampleLocations_ )
+ , postSubpassSampleLocationsCount( postSubpassSampleLocationsCount_ )
+ , pPostSubpassSampleLocations( pPostSubpassSampleLocations_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::RenderPassSampleLocationsBeginInfoEXT & operator=( VULKAN_HPP_NAMESPACE::RenderPassSampleLocationsBeginInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::RenderPassSampleLocationsBeginInfoEXT ) - offsetof( RenderPassSampleLocationsBeginInfoEXT, pNext ) );
+ return *this;
+ }
+
+ RenderPassSampleLocationsBeginInfoEXT( VkRenderPassSampleLocationsBeginInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ RenderPassSampleLocationsBeginInfoEXT& operator=( VkRenderPassSampleLocationsBeginInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RenderPassSampleLocationsBeginInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ RenderPassSampleLocationsBeginInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ RenderPassSampleLocationsBeginInfoEXT & setAttachmentInitialSampleLocationsCount( uint32_t attachmentInitialSampleLocationsCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ attachmentInitialSampleLocationsCount = attachmentInitialSampleLocationsCount_;
+ return *this;
+ }
+
+ RenderPassSampleLocationsBeginInfoEXT & setPAttachmentInitialSampleLocations( const VULKAN_HPP_NAMESPACE::AttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAttachmentInitialSampleLocations = pAttachmentInitialSampleLocations_;
+ return *this;
+ }
+
+ RenderPassSampleLocationsBeginInfoEXT & setPostSubpassSampleLocationsCount( uint32_t postSubpassSampleLocationsCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ postSubpassSampleLocationsCount = postSubpassSampleLocationsCount_;
+ return *this;
+ }
+
+ RenderPassSampleLocationsBeginInfoEXT & setPPostSubpassSampleLocations( const VULKAN_HPP_NAMESPACE::SubpassSampleLocationsEXT* pPostSubpassSampleLocations_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pPostSubpassSampleLocations = pPostSubpassSampleLocations_;
+ return *this;
+ }
+
+ operator VkRenderPassSampleLocationsBeginInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkRenderPassSampleLocationsBeginInfoEXT*>( this );
+ }
+
+ operator VkRenderPassSampleLocationsBeginInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkRenderPassSampleLocationsBeginInfoEXT*>( this );
+ }
+
+ bool operator==( RenderPassSampleLocationsBeginInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( attachmentInitialSampleLocationsCount == rhs.attachmentInitialSampleLocationsCount )
+ && ( pAttachmentInitialSampleLocations == rhs.pAttachmentInitialSampleLocations )
+ && ( postSubpassSampleLocationsCount == rhs.postSubpassSampleLocationsCount )
+ && ( pPostSubpassSampleLocations == rhs.pPostSubpassSampleLocations );
+ }
+
+ bool operator!=( RenderPassSampleLocationsBeginInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRenderPassSampleLocationsBeginInfoEXT;
+ const void* pNext = {};
+ uint32_t attachmentInitialSampleLocationsCount = {};
+ const VULKAN_HPP_NAMESPACE::AttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations = {};
+ uint32_t postSubpassSampleLocationsCount = {};
+ const VULKAN_HPP_NAMESPACE::SubpassSampleLocationsEXT* pPostSubpassSampleLocations = {};
+ };
+ static_assert( sizeof( RenderPassSampleLocationsBeginInfoEXT ) == sizeof( VkRenderPassSampleLocationsBeginInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<RenderPassSampleLocationsBeginInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct SamplerCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR SamplerCreateInfo( VULKAN_HPP_NAMESPACE::SamplerCreateFlags flags_ = {},
+ VULKAN_HPP_NAMESPACE::Filter magFilter_ = VULKAN_HPP_NAMESPACE::Filter::eNearest,
+ VULKAN_HPP_NAMESPACE::Filter minFilter_ = VULKAN_HPP_NAMESPACE::Filter::eNearest,
+ VULKAN_HPP_NAMESPACE::SamplerMipmapMode mipmapMode_ = VULKAN_HPP_NAMESPACE::SamplerMipmapMode::eNearest,
+ VULKAN_HPP_NAMESPACE::SamplerAddressMode addressModeU_ = VULKAN_HPP_NAMESPACE::SamplerAddressMode::eRepeat,
+ VULKAN_HPP_NAMESPACE::SamplerAddressMode addressModeV_ = VULKAN_HPP_NAMESPACE::SamplerAddressMode::eRepeat,
+ VULKAN_HPP_NAMESPACE::SamplerAddressMode addressModeW_ = VULKAN_HPP_NAMESPACE::SamplerAddressMode::eRepeat,
+ float mipLodBias_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 anisotropyEnable_ = {},
+ float maxAnisotropy_ = {},
+ VULKAN_HPP_NAMESPACE::Bool32 compareEnable_ = {},
+ VULKAN_HPP_NAMESPACE::CompareOp compareOp_ = VULKAN_HPP_NAMESPACE::CompareOp::eNever,
+ float minLod_ = {},
+ float maxLod_ = {},
+ VULKAN_HPP_NAMESPACE::BorderColor borderColor_ = VULKAN_HPP_NAMESPACE::BorderColor::eFloatTransparentBlack,
+ VULKAN_HPP_NAMESPACE::Bool32 unnormalizedCoordinates_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , magFilter( magFilter_ )
+ , minFilter( minFilter_ )
+ , mipmapMode( mipmapMode_ )
+ , addressModeU( addressModeU_ )
+ , addressModeV( addressModeV_ )
+ , addressModeW( addressModeW_ )
+ , mipLodBias( mipLodBias_ )
+ , anisotropyEnable( anisotropyEnable_ )
+ , maxAnisotropy( maxAnisotropy_ )
+ , compareEnable( compareEnable_ )
+ , compareOp( compareOp_ )
+ , minLod( minLod_ )
+ , maxLod( maxLod_ )
+ , borderColor( borderColor_ )
+ , unnormalizedCoordinates( unnormalizedCoordinates_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SamplerCreateInfo & operator=( VULKAN_HPP_NAMESPACE::SamplerCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SamplerCreateInfo ) - offsetof( SamplerCreateInfo, pNext ) );
+ return *this;
+ }
+
+ SamplerCreateInfo( VkSamplerCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SamplerCreateInfo& operator=( VkSamplerCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SamplerCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ SamplerCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::SamplerCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setMagFilter( VULKAN_HPP_NAMESPACE::Filter magFilter_ ) VULKAN_HPP_NOEXCEPT
+ {
+ magFilter = magFilter_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setMinFilter( VULKAN_HPP_NAMESPACE::Filter minFilter_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minFilter = minFilter_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setMipmapMode( VULKAN_HPP_NAMESPACE::SamplerMipmapMode mipmapMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ mipmapMode = mipmapMode_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setAddressModeU( VULKAN_HPP_NAMESPACE::SamplerAddressMode addressModeU_ ) VULKAN_HPP_NOEXCEPT
+ {
+ addressModeU = addressModeU_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setAddressModeV( VULKAN_HPP_NAMESPACE::SamplerAddressMode addressModeV_ ) VULKAN_HPP_NOEXCEPT
+ {
+ addressModeV = addressModeV_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setAddressModeW( VULKAN_HPP_NAMESPACE::SamplerAddressMode addressModeW_ ) VULKAN_HPP_NOEXCEPT
+ {
+ addressModeW = addressModeW_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setMipLodBias( float mipLodBias_ ) VULKAN_HPP_NOEXCEPT
+ {
+ mipLodBias = mipLodBias_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setAnisotropyEnable( VULKAN_HPP_NAMESPACE::Bool32 anisotropyEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ anisotropyEnable = anisotropyEnable_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setMaxAnisotropy( float maxAnisotropy_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxAnisotropy = maxAnisotropy_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setCompareEnable( VULKAN_HPP_NAMESPACE::Bool32 compareEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ compareEnable = compareEnable_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setCompareOp( VULKAN_HPP_NAMESPACE::CompareOp compareOp_ ) VULKAN_HPP_NOEXCEPT
+ {
+ compareOp = compareOp_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setMinLod( float minLod_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minLod = minLod_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setMaxLod( float maxLod_ ) VULKAN_HPP_NOEXCEPT
+ {
+ maxLod = maxLod_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setBorderColor( VULKAN_HPP_NAMESPACE::BorderColor borderColor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ borderColor = borderColor_;
+ return *this;
+ }
+
+ SamplerCreateInfo & setUnnormalizedCoordinates( VULKAN_HPP_NAMESPACE::Bool32 unnormalizedCoordinates_ ) VULKAN_HPP_NOEXCEPT
+ {
+ unnormalizedCoordinates = unnormalizedCoordinates_;
+ return *this;
+ }
+
+ operator VkSamplerCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSamplerCreateInfo*>( this );
+ }
+
+ operator VkSamplerCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSamplerCreateInfo*>( this );
+ }
+
+ bool operator==( SamplerCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( magFilter == rhs.magFilter )
+ && ( minFilter == rhs.minFilter )
+ && ( mipmapMode == rhs.mipmapMode )
+ && ( addressModeU == rhs.addressModeU )
+ && ( addressModeV == rhs.addressModeV )
+ && ( addressModeW == rhs.addressModeW )
+ && ( mipLodBias == rhs.mipLodBias )
+ && ( anisotropyEnable == rhs.anisotropyEnable )
+ && ( maxAnisotropy == rhs.maxAnisotropy )
+ && ( compareEnable == rhs.compareEnable )
+ && ( compareOp == rhs.compareOp )
+ && ( minLod == rhs.minLod )
+ && ( maxLod == rhs.maxLod )
+ && ( borderColor == rhs.borderColor )
+ && ( unnormalizedCoordinates == rhs.unnormalizedCoordinates );
+ }
+
+ bool operator!=( SamplerCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSamplerCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SamplerCreateFlags flags = {};
+ VULKAN_HPP_NAMESPACE::Filter magFilter = VULKAN_HPP_NAMESPACE::Filter::eNearest;
+ VULKAN_HPP_NAMESPACE::Filter minFilter = VULKAN_HPP_NAMESPACE::Filter::eNearest;
+ VULKAN_HPP_NAMESPACE::SamplerMipmapMode mipmapMode = VULKAN_HPP_NAMESPACE::SamplerMipmapMode::eNearest;
+ VULKAN_HPP_NAMESPACE::SamplerAddressMode addressModeU = VULKAN_HPP_NAMESPACE::SamplerAddressMode::eRepeat;
+ VULKAN_HPP_NAMESPACE::SamplerAddressMode addressModeV = VULKAN_HPP_NAMESPACE::SamplerAddressMode::eRepeat;
+ VULKAN_HPP_NAMESPACE::SamplerAddressMode addressModeW = VULKAN_HPP_NAMESPACE::SamplerAddressMode::eRepeat;
+ float mipLodBias = {};
+ VULKAN_HPP_NAMESPACE::Bool32 anisotropyEnable = {};
+ float maxAnisotropy = {};
+ VULKAN_HPP_NAMESPACE::Bool32 compareEnable = {};
+ VULKAN_HPP_NAMESPACE::CompareOp compareOp = VULKAN_HPP_NAMESPACE::CompareOp::eNever;
+ float minLod = {};
+ float maxLod = {};
+ VULKAN_HPP_NAMESPACE::BorderColor borderColor = VULKAN_HPP_NAMESPACE::BorderColor::eFloatTransparentBlack;
+ VULKAN_HPP_NAMESPACE::Bool32 unnormalizedCoordinates = {};
+ };
+ static_assert( sizeof( SamplerCreateInfo ) == sizeof( VkSamplerCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SamplerCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SamplerReductionModeCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR SamplerReductionModeCreateInfo( VULKAN_HPP_NAMESPACE::SamplerReductionMode reductionMode_ = VULKAN_HPP_NAMESPACE::SamplerReductionMode::eWeightedAverage ) VULKAN_HPP_NOEXCEPT
+ : reductionMode( reductionMode_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SamplerReductionModeCreateInfo & operator=( VULKAN_HPP_NAMESPACE::SamplerReductionModeCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SamplerReductionModeCreateInfo ) - offsetof( SamplerReductionModeCreateInfo, pNext ) );
+ return *this;
+ }
+
+ SamplerReductionModeCreateInfo( VkSamplerReductionModeCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SamplerReductionModeCreateInfo& operator=( VkSamplerReductionModeCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SamplerReductionModeCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ SamplerReductionModeCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SamplerReductionModeCreateInfo & setReductionMode( VULKAN_HPP_NAMESPACE::SamplerReductionMode reductionMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ reductionMode = reductionMode_;
+ return *this;
+ }
+
+ operator VkSamplerReductionModeCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSamplerReductionModeCreateInfo*>( this );
+ }
+
+ operator VkSamplerReductionModeCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSamplerReductionModeCreateInfo*>( this );
+ }
+
+ bool operator==( SamplerReductionModeCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( reductionMode == rhs.reductionMode );
+ }
+
+ bool operator!=( SamplerReductionModeCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSamplerReductionModeCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SamplerReductionMode reductionMode = VULKAN_HPP_NAMESPACE::SamplerReductionMode::eWeightedAverage;
+ };
+ static_assert( sizeof( SamplerReductionModeCreateInfo ) == sizeof( VkSamplerReductionModeCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SamplerReductionModeCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SamplerYcbcrConversionCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR SamplerYcbcrConversionCreateInfo( VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrModelConversion ycbcrModel_ = VULKAN_HPP_NAMESPACE::SamplerYcbcrModelConversion::eRgbIdentity,
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrRange ycbcrRange_ = VULKAN_HPP_NAMESPACE::SamplerYcbcrRange::eItuFull,
+ VULKAN_HPP_NAMESPACE::ComponentMapping components_ = {},
+ VULKAN_HPP_NAMESPACE::ChromaLocation xChromaOffset_ = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven,
+ VULKAN_HPP_NAMESPACE::ChromaLocation yChromaOffset_ = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven,
+ VULKAN_HPP_NAMESPACE::Filter chromaFilter_ = VULKAN_HPP_NAMESPACE::Filter::eNearest,
+ VULKAN_HPP_NAMESPACE::Bool32 forceExplicitReconstruction_ = {} ) VULKAN_HPP_NOEXCEPT
+ : format( format_ )
+ , ycbcrModel( ycbcrModel_ )
+ , ycbcrRange( ycbcrRange_ )
+ , components( components_ )
+ , xChromaOffset( xChromaOffset_ )
+ , yChromaOffset( yChromaOffset_ )
+ , chromaFilter( chromaFilter_ )
+ , forceExplicitReconstruction( forceExplicitReconstruction_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionCreateInfo & operator=( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionCreateInfo ) - offsetof( SamplerYcbcrConversionCreateInfo, pNext ) );
+ return *this;
+ }
+
+ SamplerYcbcrConversionCreateInfo( VkSamplerYcbcrConversionCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SamplerYcbcrConversionCreateInfo& operator=( VkSamplerYcbcrConversionCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ SamplerYcbcrConversionCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SamplerYcbcrConversionCreateInfo & setFormat( VULKAN_HPP_NAMESPACE::Format format_ ) VULKAN_HPP_NOEXCEPT
+ {
+ format = format_;
+ return *this;
+ }
+
+ SamplerYcbcrConversionCreateInfo & setYcbcrModel( VULKAN_HPP_NAMESPACE::SamplerYcbcrModelConversion ycbcrModel_ ) VULKAN_HPP_NOEXCEPT
+ {
+ ycbcrModel = ycbcrModel_;
+ return *this;
+ }
+
+ SamplerYcbcrConversionCreateInfo & setYcbcrRange( VULKAN_HPP_NAMESPACE::SamplerYcbcrRange ycbcrRange_ ) VULKAN_HPP_NOEXCEPT
+ {
+ ycbcrRange = ycbcrRange_;
+ return *this;
+ }
+
+ SamplerYcbcrConversionCreateInfo & setComponents( VULKAN_HPP_NAMESPACE::ComponentMapping components_ ) VULKAN_HPP_NOEXCEPT
+ {
+ components = components_;
+ return *this;
+ }
+
+ SamplerYcbcrConversionCreateInfo & setXChromaOffset( VULKAN_HPP_NAMESPACE::ChromaLocation xChromaOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ xChromaOffset = xChromaOffset_;
+ return *this;
+ }
+
+ SamplerYcbcrConversionCreateInfo & setYChromaOffset( VULKAN_HPP_NAMESPACE::ChromaLocation yChromaOffset_ ) VULKAN_HPP_NOEXCEPT
+ {
+ yChromaOffset = yChromaOffset_;
+ return *this;
+ }
+
+ SamplerYcbcrConversionCreateInfo & setChromaFilter( VULKAN_HPP_NAMESPACE::Filter chromaFilter_ ) VULKAN_HPP_NOEXCEPT
+ {
+ chromaFilter = chromaFilter_;
+ return *this;
+ }
+
+ SamplerYcbcrConversionCreateInfo & setForceExplicitReconstruction( VULKAN_HPP_NAMESPACE::Bool32 forceExplicitReconstruction_ ) VULKAN_HPP_NOEXCEPT
+ {
+ forceExplicitReconstruction = forceExplicitReconstruction_;
+ return *this;
+ }
+
+ operator VkSamplerYcbcrConversionCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( this );
+ }
+
+ operator VkSamplerYcbcrConversionCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSamplerYcbcrConversionCreateInfo*>( this );
+ }
+
+ bool operator==( SamplerYcbcrConversionCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( format == rhs.format )
+ && ( ycbcrModel == rhs.ycbcrModel )
+ && ( ycbcrRange == rhs.ycbcrRange )
+ && ( components == rhs.components )
+ && ( xChromaOffset == rhs.xChromaOffset )
+ && ( yChromaOffset == rhs.yChromaOffset )
+ && ( chromaFilter == rhs.chromaFilter )
+ && ( forceExplicitReconstruction == rhs.forceExplicitReconstruction );
+ }
+
+ bool operator!=( SamplerYcbcrConversionCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSamplerYcbcrConversionCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrModelConversion ycbcrModel = VULKAN_HPP_NAMESPACE::SamplerYcbcrModelConversion::eRgbIdentity;
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrRange ycbcrRange = VULKAN_HPP_NAMESPACE::SamplerYcbcrRange::eItuFull;
+ VULKAN_HPP_NAMESPACE::ComponentMapping components = {};
+ VULKAN_HPP_NAMESPACE::ChromaLocation xChromaOffset = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven;
+ VULKAN_HPP_NAMESPACE::ChromaLocation yChromaOffset = VULKAN_HPP_NAMESPACE::ChromaLocation::eCositedEven;
+ VULKAN_HPP_NAMESPACE::Filter chromaFilter = VULKAN_HPP_NAMESPACE::Filter::eNearest;
+ VULKAN_HPP_NAMESPACE::Bool32 forceExplicitReconstruction = {};
+ };
+ static_assert( sizeof( SamplerYcbcrConversionCreateInfo ) == sizeof( VkSamplerYcbcrConversionCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SamplerYcbcrConversionCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SamplerYcbcrConversionImageFormatProperties
+ {
+ SamplerYcbcrConversionImageFormatProperties( uint32_t combinedImageSamplerDescriptorCount_ = {} ) VULKAN_HPP_NOEXCEPT
+ : combinedImageSamplerDescriptorCount( combinedImageSamplerDescriptorCount_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionImageFormatProperties & operator=( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionImageFormatProperties ) - offsetof( SamplerYcbcrConversionImageFormatProperties, pNext ) );
+ return *this;
+ }
+
+ SamplerYcbcrConversionImageFormatProperties( VkSamplerYcbcrConversionImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SamplerYcbcrConversionImageFormatProperties& operator=( VkSamplerYcbcrConversionImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionImageFormatProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSamplerYcbcrConversionImageFormatProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSamplerYcbcrConversionImageFormatProperties*>( this );
+ }
+
+ operator VkSamplerYcbcrConversionImageFormatProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSamplerYcbcrConversionImageFormatProperties*>( this );
+ }
+
+ bool operator==( SamplerYcbcrConversionImageFormatProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( combinedImageSamplerDescriptorCount == rhs.combinedImageSamplerDescriptorCount );
+ }
+
+ bool operator!=( SamplerYcbcrConversionImageFormatProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSamplerYcbcrConversionImageFormatProperties;
+ void* pNext = {};
+ uint32_t combinedImageSamplerDescriptorCount = {};
+ };
+ static_assert( sizeof( SamplerYcbcrConversionImageFormatProperties ) == sizeof( VkSamplerYcbcrConversionImageFormatProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SamplerYcbcrConversionImageFormatProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct SamplerYcbcrConversionInfo
+ {
+ VULKAN_HPP_CONSTEXPR SamplerYcbcrConversionInfo( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion conversion_ = {} ) VULKAN_HPP_NOEXCEPT
+ : conversion( conversion_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionInfo & operator=( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionInfo ) - offsetof( SamplerYcbcrConversionInfo, pNext ) );
+ return *this;
+ }
+
+ SamplerYcbcrConversionInfo( VkSamplerYcbcrConversionInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SamplerYcbcrConversionInfo& operator=( VkSamplerYcbcrConversionInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionInfo const *>(&rhs);
+ return *this;
+ }
+
+ SamplerYcbcrConversionInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SamplerYcbcrConversionInfo & setConversion( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion conversion_ ) VULKAN_HPP_NOEXCEPT
+ {
+ conversion = conversion_;
+ return *this;
+ }
+
+ operator VkSamplerYcbcrConversionInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSamplerYcbcrConversionInfo*>( this );
+ }
+
+ operator VkSamplerYcbcrConversionInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSamplerYcbcrConversionInfo*>( this );
+ }
+
+ bool operator==( SamplerYcbcrConversionInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( conversion == rhs.conversion );
+ }
+
+ bool operator!=( SamplerYcbcrConversionInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSamplerYcbcrConversionInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion conversion = {};
+ };
+ static_assert( sizeof( SamplerYcbcrConversionInfo ) == sizeof( VkSamplerYcbcrConversionInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SamplerYcbcrConversionInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SemaphoreCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR SemaphoreCreateInfo( VULKAN_HPP_NAMESPACE::SemaphoreCreateFlags flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SemaphoreCreateInfo & operator=( VULKAN_HPP_NAMESPACE::SemaphoreCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SemaphoreCreateInfo ) - offsetof( SemaphoreCreateInfo, pNext ) );
+ return *this;
+ }
+
+ SemaphoreCreateInfo( VkSemaphoreCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SemaphoreCreateInfo& operator=( VkSemaphoreCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SemaphoreCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ SemaphoreCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SemaphoreCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::SemaphoreCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ operator VkSemaphoreCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSemaphoreCreateInfo*>( this );
+ }
+
+ operator VkSemaphoreCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSemaphoreCreateInfo*>( this );
+ }
+
+ bool operator==( SemaphoreCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( SemaphoreCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSemaphoreCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SemaphoreCreateFlags flags = {};
+ };
+ static_assert( sizeof( SemaphoreCreateInfo ) == sizeof( VkSemaphoreCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SemaphoreCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SemaphoreGetFdInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR SemaphoreGetFdInfoKHR( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd ) VULKAN_HPP_NOEXCEPT
+ : semaphore( semaphore_ )
+ , handleType( handleType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SemaphoreGetFdInfoKHR & operator=( VULKAN_HPP_NAMESPACE::SemaphoreGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SemaphoreGetFdInfoKHR ) - offsetof( SemaphoreGetFdInfoKHR, pNext ) );
+ return *this;
+ }
+
+ SemaphoreGetFdInfoKHR( VkSemaphoreGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SemaphoreGetFdInfoKHR& operator=( VkSemaphoreGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SemaphoreGetFdInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ SemaphoreGetFdInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SemaphoreGetFdInfoKHR & setSemaphore( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ ) VULKAN_HPP_NOEXCEPT
+ {
+ semaphore = semaphore_;
+ return *this;
+ }
+
+ SemaphoreGetFdInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ operator VkSemaphoreGetFdInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSemaphoreGetFdInfoKHR*>( this );
+ }
+
+ operator VkSemaphoreGetFdInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSemaphoreGetFdInfoKHR*>( this );
+ }
+
+ bool operator==( SemaphoreGetFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( semaphore == rhs.semaphore )
+ && ( handleType == rhs.handleType );
+ }
+
+ bool operator!=( SemaphoreGetFdInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSemaphoreGetFdInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Semaphore semaphore = {};
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd;
+ };
+ static_assert( sizeof( SemaphoreGetFdInfoKHR ) == sizeof( VkSemaphoreGetFdInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SemaphoreGetFdInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct SemaphoreGetWin32HandleInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR SemaphoreGetWin32HandleInfoKHR( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ = {},
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType_ = VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd ) VULKAN_HPP_NOEXCEPT
+ : semaphore( semaphore_ )
+ , handleType( handleType_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SemaphoreGetWin32HandleInfoKHR & operator=( VULKAN_HPP_NAMESPACE::SemaphoreGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SemaphoreGetWin32HandleInfoKHR ) - offsetof( SemaphoreGetWin32HandleInfoKHR, pNext ) );
+ return *this;
+ }
+
+ SemaphoreGetWin32HandleInfoKHR( VkSemaphoreGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SemaphoreGetWin32HandleInfoKHR& operator=( VkSemaphoreGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SemaphoreGetWin32HandleInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ SemaphoreGetWin32HandleInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SemaphoreGetWin32HandleInfoKHR & setSemaphore( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ ) VULKAN_HPP_NOEXCEPT
+ {
+ semaphore = semaphore_;
+ return *this;
+ }
+
+ SemaphoreGetWin32HandleInfoKHR & setHandleType( VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ handleType = handleType_;
+ return *this;
+ }
+
+ operator VkSemaphoreGetWin32HandleInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSemaphoreGetWin32HandleInfoKHR*>( this );
+ }
+
+ operator VkSemaphoreGetWin32HandleInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSemaphoreGetWin32HandleInfoKHR*>( this );
+ }
+
+ bool operator==( SemaphoreGetWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( semaphore == rhs.semaphore )
+ && ( handleType == rhs.handleType );
+ }
+
+ bool operator!=( SemaphoreGetWin32HandleInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSemaphoreGetWin32HandleInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Semaphore semaphore = {};
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits handleType = VULKAN_HPP_NAMESPACE::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd;
+ };
+ static_assert( sizeof( SemaphoreGetWin32HandleInfoKHR ) == sizeof( VkSemaphoreGetWin32HandleInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SemaphoreGetWin32HandleInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct SemaphoreSignalInfo
+ {
+ VULKAN_HPP_CONSTEXPR SemaphoreSignalInfo( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ = {},
+ uint64_t value_ = {} ) VULKAN_HPP_NOEXCEPT
+ : semaphore( semaphore_ )
+ , value( value_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SemaphoreSignalInfo & operator=( VULKAN_HPP_NAMESPACE::SemaphoreSignalInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SemaphoreSignalInfo ) - offsetof( SemaphoreSignalInfo, pNext ) );
+ return *this;
+ }
+
+ SemaphoreSignalInfo( VkSemaphoreSignalInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SemaphoreSignalInfo& operator=( VkSemaphoreSignalInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SemaphoreSignalInfo const *>(&rhs);
+ return *this;
+ }
+
+ SemaphoreSignalInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SemaphoreSignalInfo & setSemaphore( VULKAN_HPP_NAMESPACE::Semaphore semaphore_ ) VULKAN_HPP_NOEXCEPT
+ {
+ semaphore = semaphore_;
+ return *this;
+ }
+
+ SemaphoreSignalInfo & setValue( uint64_t value_ ) VULKAN_HPP_NOEXCEPT
+ {
+ value = value_;
+ return *this;
+ }
+
+ operator VkSemaphoreSignalInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSemaphoreSignalInfo*>( this );
+ }
+
+ operator VkSemaphoreSignalInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSemaphoreSignalInfo*>( this );
+ }
+
+ bool operator==( SemaphoreSignalInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( semaphore == rhs.semaphore )
+ && ( value == rhs.value );
+ }
+
+ bool operator!=( SemaphoreSignalInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSemaphoreSignalInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Semaphore semaphore = {};
+ uint64_t value = {};
+ };
+ static_assert( sizeof( SemaphoreSignalInfo ) == sizeof( VkSemaphoreSignalInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SemaphoreSignalInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SemaphoreTypeCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR SemaphoreTypeCreateInfo( VULKAN_HPP_NAMESPACE::SemaphoreType semaphoreType_ = VULKAN_HPP_NAMESPACE::SemaphoreType::eBinary,
+ uint64_t initialValue_ = {} ) VULKAN_HPP_NOEXCEPT
+ : semaphoreType( semaphoreType_ )
+ , initialValue( initialValue_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SemaphoreTypeCreateInfo & operator=( VULKAN_HPP_NAMESPACE::SemaphoreTypeCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SemaphoreTypeCreateInfo ) - offsetof( SemaphoreTypeCreateInfo, pNext ) );
+ return *this;
+ }
+
+ SemaphoreTypeCreateInfo( VkSemaphoreTypeCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SemaphoreTypeCreateInfo& operator=( VkSemaphoreTypeCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SemaphoreTypeCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ SemaphoreTypeCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SemaphoreTypeCreateInfo & setSemaphoreType( VULKAN_HPP_NAMESPACE::SemaphoreType semaphoreType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ semaphoreType = semaphoreType_;
+ return *this;
+ }
+
+ SemaphoreTypeCreateInfo & setInitialValue( uint64_t initialValue_ ) VULKAN_HPP_NOEXCEPT
+ {
+ initialValue = initialValue_;
+ return *this;
+ }
+
+ operator VkSemaphoreTypeCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSemaphoreTypeCreateInfo*>( this );
+ }
+
+ operator VkSemaphoreTypeCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSemaphoreTypeCreateInfo*>( this );
+ }
+
+ bool operator==( SemaphoreTypeCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( semaphoreType == rhs.semaphoreType )
+ && ( initialValue == rhs.initialValue );
+ }
+
+ bool operator!=( SemaphoreTypeCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSemaphoreTypeCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SemaphoreType semaphoreType = VULKAN_HPP_NAMESPACE::SemaphoreType::eBinary;
+ uint64_t initialValue = {};
+ };
+ static_assert( sizeof( SemaphoreTypeCreateInfo ) == sizeof( VkSemaphoreTypeCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SemaphoreTypeCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SemaphoreWaitInfo
+ {
+ VULKAN_HPP_CONSTEXPR SemaphoreWaitInfo( VULKAN_HPP_NAMESPACE::SemaphoreWaitFlags flags_ = {},
+ uint32_t semaphoreCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Semaphore* pSemaphores_ = {},
+ const uint64_t* pValues_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , semaphoreCount( semaphoreCount_ )
+ , pSemaphores( pSemaphores_ )
+ , pValues( pValues_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SemaphoreWaitInfo & operator=( VULKAN_HPP_NAMESPACE::SemaphoreWaitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SemaphoreWaitInfo ) - offsetof( SemaphoreWaitInfo, pNext ) );
+ return *this;
+ }
+
+ SemaphoreWaitInfo( VkSemaphoreWaitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SemaphoreWaitInfo& operator=( VkSemaphoreWaitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SemaphoreWaitInfo const *>(&rhs);
+ return *this;
+ }
+
+ SemaphoreWaitInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SemaphoreWaitInfo & setFlags( VULKAN_HPP_NAMESPACE::SemaphoreWaitFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ SemaphoreWaitInfo & setSemaphoreCount( uint32_t semaphoreCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ semaphoreCount = semaphoreCount_;
+ return *this;
+ }
+
+ SemaphoreWaitInfo & setPSemaphores( const VULKAN_HPP_NAMESPACE::Semaphore* pSemaphores_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSemaphores = pSemaphores_;
+ return *this;
+ }
+
+ SemaphoreWaitInfo & setPValues( const uint64_t* pValues_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pValues = pValues_;
+ return *this;
+ }
+
+ operator VkSemaphoreWaitInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSemaphoreWaitInfo*>( this );
+ }
+
+ operator VkSemaphoreWaitInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSemaphoreWaitInfo*>( this );
+ }
+
+ bool operator==( SemaphoreWaitInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( semaphoreCount == rhs.semaphoreCount )
+ && ( pSemaphores == rhs.pSemaphores )
+ && ( pValues == rhs.pValues );
+ }
+
+ bool operator!=( SemaphoreWaitInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSemaphoreWaitInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SemaphoreWaitFlags flags = {};
+ uint32_t semaphoreCount = {};
+ const VULKAN_HPP_NAMESPACE::Semaphore* pSemaphores = {};
+ const uint64_t* pValues = {};
+ };
+ static_assert( sizeof( SemaphoreWaitInfo ) == sizeof( VkSemaphoreWaitInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SemaphoreWaitInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ShaderModuleCreateInfo
+ {
+ VULKAN_HPP_CONSTEXPR ShaderModuleCreateInfo( VULKAN_HPP_NAMESPACE::ShaderModuleCreateFlags flags_ = {},
+ size_t codeSize_ = {},
+ const uint32_t* pCode_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , codeSize( codeSize_ )
+ , pCode( pCode_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ShaderModuleCreateInfo & operator=( VULKAN_HPP_NAMESPACE::ShaderModuleCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ShaderModuleCreateInfo ) - offsetof( ShaderModuleCreateInfo, pNext ) );
+ return *this;
+ }
+
+ ShaderModuleCreateInfo( VkShaderModuleCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ShaderModuleCreateInfo& operator=( VkShaderModuleCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ShaderModuleCreateInfo const *>(&rhs);
+ return *this;
+ }
+
+ ShaderModuleCreateInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ShaderModuleCreateInfo & setFlags( VULKAN_HPP_NAMESPACE::ShaderModuleCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ShaderModuleCreateInfo & setCodeSize( size_t codeSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ codeSize = codeSize_;
+ return *this;
+ }
+
+ ShaderModuleCreateInfo & setPCode( const uint32_t* pCode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pCode = pCode_;
+ return *this;
+ }
+
+ operator VkShaderModuleCreateInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkShaderModuleCreateInfo*>( this );
+ }
+
+ operator VkShaderModuleCreateInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkShaderModuleCreateInfo*>( this );
+ }
+
+ bool operator==( ShaderModuleCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( codeSize == rhs.codeSize )
+ && ( pCode == rhs.pCode );
+ }
+
+ bool operator!=( ShaderModuleCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eShaderModuleCreateInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ShaderModuleCreateFlags flags = {};
+ size_t codeSize = {};
+ const uint32_t* pCode = {};
+ };
+ static_assert( sizeof( ShaderModuleCreateInfo ) == sizeof( VkShaderModuleCreateInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ShaderModuleCreateInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ShaderModuleValidationCacheCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR ShaderModuleValidationCacheCreateInfoEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache_ = {} ) VULKAN_HPP_NOEXCEPT
+ : validationCache( validationCache_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ShaderModuleValidationCacheCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::ShaderModuleValidationCacheCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ShaderModuleValidationCacheCreateInfoEXT ) - offsetof( ShaderModuleValidationCacheCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ ShaderModuleValidationCacheCreateInfoEXT( VkShaderModuleValidationCacheCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ShaderModuleValidationCacheCreateInfoEXT& operator=( VkShaderModuleValidationCacheCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ShaderModuleValidationCacheCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ ShaderModuleValidationCacheCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ShaderModuleValidationCacheCreateInfoEXT & setValidationCache( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache_ ) VULKAN_HPP_NOEXCEPT
+ {
+ validationCache = validationCache_;
+ return *this;
+ }
+
+ operator VkShaderModuleValidationCacheCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkShaderModuleValidationCacheCreateInfoEXT*>( this );
+ }
+
+ operator VkShaderModuleValidationCacheCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkShaderModuleValidationCacheCreateInfoEXT*>( this );
+ }
+
+ bool operator==( ShaderModuleValidationCacheCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( validationCache == rhs.validationCache );
+ }
+
+ bool operator!=( ShaderModuleValidationCacheCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eShaderModuleValidationCacheCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache = {};
+ };
+ static_assert( sizeof( ShaderModuleValidationCacheCreateInfoEXT ) == sizeof( VkShaderModuleValidationCacheCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ShaderModuleValidationCacheCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct ShaderResourceUsageAMD
+ {
+ ShaderResourceUsageAMD( uint32_t numUsedVgprs_ = {},
+ uint32_t numUsedSgprs_ = {},
+ uint32_t ldsSizePerLocalWorkGroup_ = {},
+ size_t ldsUsageSizeInBytes_ = {},
+ size_t scratchMemUsageInBytes_ = {} ) VULKAN_HPP_NOEXCEPT
+ : numUsedVgprs( numUsedVgprs_ )
+ , numUsedSgprs( numUsedSgprs_ )
+ , ldsSizePerLocalWorkGroup( ldsSizePerLocalWorkGroup_ )
+ , ldsUsageSizeInBytes( ldsUsageSizeInBytes_ )
+ , scratchMemUsageInBytes( scratchMemUsageInBytes_ )
+ {}
+
+ ShaderResourceUsageAMD( VkShaderResourceUsageAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ShaderResourceUsageAMD& operator=( VkShaderResourceUsageAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ShaderResourceUsageAMD const *>(&rhs);
+ return *this;
+ }
+
+ operator VkShaderResourceUsageAMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkShaderResourceUsageAMD*>( this );
+ }
+
+ operator VkShaderResourceUsageAMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkShaderResourceUsageAMD*>( this );
+ }
+
+ bool operator==( ShaderResourceUsageAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( numUsedVgprs == rhs.numUsedVgprs )
+ && ( numUsedSgprs == rhs.numUsedSgprs )
+ && ( ldsSizePerLocalWorkGroup == rhs.ldsSizePerLocalWorkGroup )
+ && ( ldsUsageSizeInBytes == rhs.ldsUsageSizeInBytes )
+ && ( scratchMemUsageInBytes == rhs.scratchMemUsageInBytes );
+ }
+
+ bool operator!=( ShaderResourceUsageAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t numUsedVgprs = {};
+ uint32_t numUsedSgprs = {};
+ uint32_t ldsSizePerLocalWorkGroup = {};
+ size_t ldsUsageSizeInBytes = {};
+ size_t scratchMemUsageInBytes = {};
+ };
+ static_assert( sizeof( ShaderResourceUsageAMD ) == sizeof( VkShaderResourceUsageAMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ShaderResourceUsageAMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct ShaderStatisticsInfoAMD
+ {
+ ShaderStatisticsInfoAMD( VULKAN_HPP_NAMESPACE::ShaderStageFlags shaderStageMask_ = {},
+ VULKAN_HPP_NAMESPACE::ShaderResourceUsageAMD resourceUsage_ = {},
+ uint32_t numPhysicalVgprs_ = {},
+ uint32_t numPhysicalSgprs_ = {},
+ uint32_t numAvailableVgprs_ = {},
+ uint32_t numAvailableSgprs_ = {},
+ std::array<uint32_t,3> const& computeWorkGroupSize_ = {} ) VULKAN_HPP_NOEXCEPT
+ : shaderStageMask( shaderStageMask_ )
+ , resourceUsage( resourceUsage_ )
+ , numPhysicalVgprs( numPhysicalVgprs_ )
+ , numPhysicalSgprs( numPhysicalSgprs_ )
+ , numAvailableVgprs( numAvailableVgprs_ )
+ , numAvailableSgprs( numAvailableSgprs_ )
+ , computeWorkGroupSize{}
+ {
+ VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3,3>::copy( computeWorkGroupSize, computeWorkGroupSize_ );
+ }
+
+ ShaderStatisticsInfoAMD( VkShaderStatisticsInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ShaderStatisticsInfoAMD& operator=( VkShaderStatisticsInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ShaderStatisticsInfoAMD const *>(&rhs);
+ return *this;
+ }
+
+ operator VkShaderStatisticsInfoAMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkShaderStatisticsInfoAMD*>( this );
+ }
+
+ operator VkShaderStatisticsInfoAMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkShaderStatisticsInfoAMD*>( this );
+ }
+
+ bool operator==( ShaderStatisticsInfoAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( shaderStageMask == rhs.shaderStageMask )
+ && ( resourceUsage == rhs.resourceUsage )
+ && ( numPhysicalVgprs == rhs.numPhysicalVgprs )
+ && ( numPhysicalSgprs == rhs.numPhysicalSgprs )
+ && ( numAvailableVgprs == rhs.numAvailableVgprs )
+ && ( numAvailableSgprs == rhs.numAvailableSgprs )
+ && ( memcmp( computeWorkGroupSize, rhs.computeWorkGroupSize, 3 * sizeof( uint32_t ) ) == 0 );
+ }
+
+ bool operator!=( ShaderStatisticsInfoAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ShaderStageFlags shaderStageMask = {};
+ VULKAN_HPP_NAMESPACE::ShaderResourceUsageAMD resourceUsage = {};
+ uint32_t numPhysicalVgprs = {};
+ uint32_t numPhysicalSgprs = {};
+ uint32_t numAvailableVgprs = {};
+ uint32_t numAvailableSgprs = {};
+ uint32_t computeWorkGroupSize[3] = {};
+ };
+ static_assert( sizeof( ShaderStatisticsInfoAMD ) == sizeof( VkShaderStatisticsInfoAMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ShaderStatisticsInfoAMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct SharedPresentSurfaceCapabilitiesKHR
+ {
+ SharedPresentSurfaceCapabilitiesKHR( VULKAN_HPP_NAMESPACE::ImageUsageFlags sharedPresentSupportedUsageFlags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : sharedPresentSupportedUsageFlags( sharedPresentSupportedUsageFlags_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SharedPresentSurfaceCapabilitiesKHR & operator=( VULKAN_HPP_NAMESPACE::SharedPresentSurfaceCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SharedPresentSurfaceCapabilitiesKHR ) - offsetof( SharedPresentSurfaceCapabilitiesKHR, pNext ) );
+ return *this;
+ }
+
+ SharedPresentSurfaceCapabilitiesKHR( VkSharedPresentSurfaceCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SharedPresentSurfaceCapabilitiesKHR& operator=( VkSharedPresentSurfaceCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SharedPresentSurfaceCapabilitiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSharedPresentSurfaceCapabilitiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSharedPresentSurfaceCapabilitiesKHR*>( this );
+ }
+
+ operator VkSharedPresentSurfaceCapabilitiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSharedPresentSurfaceCapabilitiesKHR*>( this );
+ }
+
+ bool operator==( SharedPresentSurfaceCapabilitiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( sharedPresentSupportedUsageFlags == rhs.sharedPresentSupportedUsageFlags );
+ }
+
+ bool operator!=( SharedPresentSurfaceCapabilitiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSharedPresentSurfaceCapabilitiesKHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags sharedPresentSupportedUsageFlags = {};
+ };
+ static_assert( sizeof( SharedPresentSurfaceCapabilitiesKHR ) == sizeof( VkSharedPresentSurfaceCapabilitiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SharedPresentSurfaceCapabilitiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct SparseImageFormatProperties
+ {
+ SparseImageFormatProperties( VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask_ = {},
+ VULKAN_HPP_NAMESPACE::Extent3D imageGranularity_ = {},
+ VULKAN_HPP_NAMESPACE::SparseImageFormatFlags flags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : aspectMask( aspectMask_ )
+ , imageGranularity( imageGranularity_ )
+ , flags( flags_ )
+ {}
+
+ SparseImageFormatProperties( VkSparseImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SparseImageFormatProperties& operator=( VkSparseImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SparseImageFormatProperties const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSparseImageFormatProperties const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSparseImageFormatProperties*>( this );
+ }
+
+ operator VkSparseImageFormatProperties &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSparseImageFormatProperties*>( this );
+ }
+
+ bool operator==( SparseImageFormatProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( aspectMask == rhs.aspectMask )
+ && ( imageGranularity == rhs.imageGranularity )
+ && ( flags == rhs.flags );
+ }
+
+ bool operator!=( SparseImageFormatProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::ImageAspectFlags aspectMask = {};
+ VULKAN_HPP_NAMESPACE::Extent3D imageGranularity = {};
+ VULKAN_HPP_NAMESPACE::SparseImageFormatFlags flags = {};
+ };
+ static_assert( sizeof( SparseImageFormatProperties ) == sizeof( VkSparseImageFormatProperties ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SparseImageFormatProperties>::value, "struct wrapper is not a standard layout!" );
+
+ struct SparseImageFormatProperties2
+ {
+ SparseImageFormatProperties2( VULKAN_HPP_NAMESPACE::SparseImageFormatProperties properties_ = {} ) VULKAN_HPP_NOEXCEPT
+ : properties( properties_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SparseImageFormatProperties2 & operator=( VULKAN_HPP_NAMESPACE::SparseImageFormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SparseImageFormatProperties2 ) - offsetof( SparseImageFormatProperties2, pNext ) );
+ return *this;
+ }
+
+ SparseImageFormatProperties2( VkSparseImageFormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SparseImageFormatProperties2& operator=( VkSparseImageFormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SparseImageFormatProperties2 const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSparseImageFormatProperties2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSparseImageFormatProperties2*>( this );
+ }
+
+ operator VkSparseImageFormatProperties2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSparseImageFormatProperties2*>( this );
+ }
+
+ bool operator==( SparseImageFormatProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( properties == rhs.properties );
+ }
+
+ bool operator!=( SparseImageFormatProperties2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSparseImageFormatProperties2;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SparseImageFormatProperties properties = {};
+ };
+ static_assert( sizeof( SparseImageFormatProperties2 ) == sizeof( VkSparseImageFormatProperties2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SparseImageFormatProperties2>::value, "struct wrapper is not a standard layout!" );
+
+ struct SparseImageMemoryRequirements
+ {
+ SparseImageMemoryRequirements( VULKAN_HPP_NAMESPACE::SparseImageFormatProperties formatProperties_ = {},
+ uint32_t imageMipTailFirstLod_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize imageMipTailSize_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize imageMipTailOffset_ = {},
+ VULKAN_HPP_NAMESPACE::DeviceSize imageMipTailStride_ = {} ) VULKAN_HPP_NOEXCEPT
+ : formatProperties( formatProperties_ )
+ , imageMipTailFirstLod( imageMipTailFirstLod_ )
+ , imageMipTailSize( imageMipTailSize_ )
+ , imageMipTailOffset( imageMipTailOffset_ )
+ , imageMipTailStride( imageMipTailStride_ )
+ {}
+
+ SparseImageMemoryRequirements( VkSparseImageMemoryRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SparseImageMemoryRequirements& operator=( VkSparseImageMemoryRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSparseImageMemoryRequirements const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSparseImageMemoryRequirements*>( this );
+ }
+
+ operator VkSparseImageMemoryRequirements &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSparseImageMemoryRequirements*>( this );
+ }
+
+ bool operator==( SparseImageMemoryRequirements const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( formatProperties == rhs.formatProperties )
+ && ( imageMipTailFirstLod == rhs.imageMipTailFirstLod )
+ && ( imageMipTailSize == rhs.imageMipTailSize )
+ && ( imageMipTailOffset == rhs.imageMipTailOffset )
+ && ( imageMipTailStride == rhs.imageMipTailStride );
+ }
+
+ bool operator!=( SparseImageMemoryRequirements const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::SparseImageFormatProperties formatProperties = {};
+ uint32_t imageMipTailFirstLod = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize imageMipTailSize = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize imageMipTailOffset = {};
+ VULKAN_HPP_NAMESPACE::DeviceSize imageMipTailStride = {};
+ };
+ static_assert( sizeof( SparseImageMemoryRequirements ) == sizeof( VkSparseImageMemoryRequirements ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SparseImageMemoryRequirements>::value, "struct wrapper is not a standard layout!" );
+
+ struct SparseImageMemoryRequirements2
+ {
+ SparseImageMemoryRequirements2( VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements memoryRequirements_ = {} ) VULKAN_HPP_NOEXCEPT
+ : memoryRequirements( memoryRequirements_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements2 & operator=( VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements2 ) - offsetof( SparseImageMemoryRequirements2, pNext ) );
+ return *this;
+ }
+
+ SparseImageMemoryRequirements2( VkSparseImageMemoryRequirements2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SparseImageMemoryRequirements2& operator=( VkSparseImageMemoryRequirements2 const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements2 const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSparseImageMemoryRequirements2 const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSparseImageMemoryRequirements2*>( this );
+ }
+
+ operator VkSparseImageMemoryRequirements2 &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSparseImageMemoryRequirements2*>( this );
+ }
+
+ bool operator==( SparseImageMemoryRequirements2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( memoryRequirements == rhs.memoryRequirements );
+ }
+
+ bool operator!=( SparseImageMemoryRequirements2 const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSparseImageMemoryRequirements2;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements memoryRequirements = {};
+ };
+ static_assert( sizeof( SparseImageMemoryRequirements2 ) == sizeof( VkSparseImageMemoryRequirements2 ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SparseImageMemoryRequirements2>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_GGP
+
+ struct StreamDescriptorSurfaceCreateInfoGGP
+ {
+ VULKAN_HPP_CONSTEXPR StreamDescriptorSurfaceCreateInfoGGP( VULKAN_HPP_NAMESPACE::StreamDescriptorSurfaceCreateFlagsGGP flags_ = {},
+ GgpStreamDescriptor streamDescriptor_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , streamDescriptor( streamDescriptor_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::StreamDescriptorSurfaceCreateInfoGGP & operator=( VULKAN_HPP_NAMESPACE::StreamDescriptorSurfaceCreateInfoGGP const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::StreamDescriptorSurfaceCreateInfoGGP ) - offsetof( StreamDescriptorSurfaceCreateInfoGGP, pNext ) );
+ return *this;
+ }
+
+ StreamDescriptorSurfaceCreateInfoGGP( VkStreamDescriptorSurfaceCreateInfoGGP const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ StreamDescriptorSurfaceCreateInfoGGP& operator=( VkStreamDescriptorSurfaceCreateInfoGGP const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::StreamDescriptorSurfaceCreateInfoGGP const *>(&rhs);
+ return *this;
+ }
+
+ StreamDescriptorSurfaceCreateInfoGGP & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ StreamDescriptorSurfaceCreateInfoGGP & setFlags( VULKAN_HPP_NAMESPACE::StreamDescriptorSurfaceCreateFlagsGGP flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ StreamDescriptorSurfaceCreateInfoGGP & setStreamDescriptor( GgpStreamDescriptor streamDescriptor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ streamDescriptor = streamDescriptor_;
+ return *this;
+ }
+
+ operator VkStreamDescriptorSurfaceCreateInfoGGP const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkStreamDescriptorSurfaceCreateInfoGGP*>( this );
+ }
+
+ operator VkStreamDescriptorSurfaceCreateInfoGGP &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkStreamDescriptorSurfaceCreateInfoGGP*>( this );
+ }
+
+ bool operator==( StreamDescriptorSurfaceCreateInfoGGP const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( streamDescriptor == rhs.streamDescriptor );
+ }
+
+ bool operator!=( StreamDescriptorSurfaceCreateInfoGGP const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eStreamDescriptorSurfaceCreateInfoGGP;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::StreamDescriptorSurfaceCreateFlagsGGP flags = {};
+ GgpStreamDescriptor streamDescriptor = {};
+ };
+ static_assert( sizeof( StreamDescriptorSurfaceCreateInfoGGP ) == sizeof( VkStreamDescriptorSurfaceCreateInfoGGP ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<StreamDescriptorSurfaceCreateInfoGGP>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_GGP*/
+
+ struct SubmitInfo
+ {
+ VULKAN_HPP_CONSTEXPR SubmitInfo( uint32_t waitSemaphoreCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Semaphore* pWaitSemaphores_ = {},
+ const VULKAN_HPP_NAMESPACE::PipelineStageFlags* pWaitDstStageMask_ = {},
+ uint32_t commandBufferCount_ = {},
+ const VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers_ = {},
+ uint32_t signalSemaphoreCount_ = {},
+ const VULKAN_HPP_NAMESPACE::Semaphore* pSignalSemaphores_ = {} ) VULKAN_HPP_NOEXCEPT
+ : waitSemaphoreCount( waitSemaphoreCount_ )
+ , pWaitSemaphores( pWaitSemaphores_ )
+ , pWaitDstStageMask( pWaitDstStageMask_ )
+ , commandBufferCount( commandBufferCount_ )
+ , pCommandBuffers( pCommandBuffers_ )
+ , signalSemaphoreCount( signalSemaphoreCount_ )
+ , pSignalSemaphores( pSignalSemaphores_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SubmitInfo & operator=( VULKAN_HPP_NAMESPACE::SubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SubmitInfo ) - offsetof( SubmitInfo, pNext ) );
+ return *this;
+ }
+
+ SubmitInfo( VkSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SubmitInfo& operator=( VkSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SubmitInfo const *>(&rhs);
+ return *this;
+ }
+
+ SubmitInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SubmitInfo & setWaitSemaphoreCount( uint32_t waitSemaphoreCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ waitSemaphoreCount = waitSemaphoreCount_;
+ return *this;
+ }
+
+ SubmitInfo & setPWaitSemaphores( const VULKAN_HPP_NAMESPACE::Semaphore* pWaitSemaphores_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pWaitSemaphores = pWaitSemaphores_;
+ return *this;
+ }
+
+ SubmitInfo & setPWaitDstStageMask( const VULKAN_HPP_NAMESPACE::PipelineStageFlags* pWaitDstStageMask_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pWaitDstStageMask = pWaitDstStageMask_;
+ return *this;
+ }
+
+ SubmitInfo & setCommandBufferCount( uint32_t commandBufferCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ commandBufferCount = commandBufferCount_;
+ return *this;
+ }
+
+ SubmitInfo & setPCommandBuffers( const VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pCommandBuffers = pCommandBuffers_;
+ return *this;
+ }
+
+ SubmitInfo & setSignalSemaphoreCount( uint32_t signalSemaphoreCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ signalSemaphoreCount = signalSemaphoreCount_;
+ return *this;
+ }
+
+ SubmitInfo & setPSignalSemaphores( const VULKAN_HPP_NAMESPACE::Semaphore* pSignalSemaphores_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSignalSemaphores = pSignalSemaphores_;
+ return *this;
+ }
+
+ operator VkSubmitInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSubmitInfo*>( this );
+ }
+
+ operator VkSubmitInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSubmitInfo*>( this );
+ }
+
+ bool operator==( SubmitInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( waitSemaphoreCount == rhs.waitSemaphoreCount )
+ && ( pWaitSemaphores == rhs.pWaitSemaphores )
+ && ( pWaitDstStageMask == rhs.pWaitDstStageMask )
+ && ( commandBufferCount == rhs.commandBufferCount )
+ && ( pCommandBuffers == rhs.pCommandBuffers )
+ && ( signalSemaphoreCount == rhs.signalSemaphoreCount )
+ && ( pSignalSemaphores == rhs.pSignalSemaphores );
+ }
+
+ bool operator!=( SubmitInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSubmitInfo;
+ const void* pNext = {};
+ uint32_t waitSemaphoreCount = {};
+ const VULKAN_HPP_NAMESPACE::Semaphore* pWaitSemaphores = {};
+ const VULKAN_HPP_NAMESPACE::PipelineStageFlags* pWaitDstStageMask = {};
+ uint32_t commandBufferCount = {};
+ const VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers = {};
+ uint32_t signalSemaphoreCount = {};
+ const VULKAN_HPP_NAMESPACE::Semaphore* pSignalSemaphores = {};
+ };
+ static_assert( sizeof( SubmitInfo ) == sizeof( VkSubmitInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SubmitInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SubpassBeginInfo
+ {
+ VULKAN_HPP_CONSTEXPR SubpassBeginInfo( VULKAN_HPP_NAMESPACE::SubpassContents contents_ = VULKAN_HPP_NAMESPACE::SubpassContents::eInline ) VULKAN_HPP_NOEXCEPT
+ : contents( contents_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SubpassBeginInfo & operator=( VULKAN_HPP_NAMESPACE::SubpassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SubpassBeginInfo ) - offsetof( SubpassBeginInfo, pNext ) );
+ return *this;
+ }
+
+ SubpassBeginInfo( VkSubpassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SubpassBeginInfo& operator=( VkSubpassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SubpassBeginInfo const *>(&rhs);
+ return *this;
+ }
+
+ SubpassBeginInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SubpassBeginInfo & setContents( VULKAN_HPP_NAMESPACE::SubpassContents contents_ ) VULKAN_HPP_NOEXCEPT
+ {
+ contents = contents_;
+ return *this;
+ }
+
+ operator VkSubpassBeginInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSubpassBeginInfo*>( this );
+ }
+
+ operator VkSubpassBeginInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSubpassBeginInfo*>( this );
+ }
+
+ bool operator==( SubpassBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( contents == rhs.contents );
+ }
+
+ bool operator!=( SubpassBeginInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSubpassBeginInfo;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SubpassContents contents = VULKAN_HPP_NAMESPACE::SubpassContents::eInline;
+ };
+ static_assert( sizeof( SubpassBeginInfo ) == sizeof( VkSubpassBeginInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SubpassBeginInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SubpassDescriptionDepthStencilResolve
+ {
+ VULKAN_HPP_CONSTEXPR SubpassDescriptionDepthStencilResolve( VULKAN_HPP_NAMESPACE::ResolveModeFlagBits depthResolveMode_ = VULKAN_HPP_NAMESPACE::ResolveModeFlagBits::eNone,
+ VULKAN_HPP_NAMESPACE::ResolveModeFlagBits stencilResolveMode_ = VULKAN_HPP_NAMESPACE::ResolveModeFlagBits::eNone,
+ const VULKAN_HPP_NAMESPACE::AttachmentReference2* pDepthStencilResolveAttachment_ = {} ) VULKAN_HPP_NOEXCEPT
+ : depthResolveMode( depthResolveMode_ )
+ , stencilResolveMode( stencilResolveMode_ )
+ , pDepthStencilResolveAttachment( pDepthStencilResolveAttachment_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SubpassDescriptionDepthStencilResolve & operator=( VULKAN_HPP_NAMESPACE::SubpassDescriptionDepthStencilResolve const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SubpassDescriptionDepthStencilResolve ) - offsetof( SubpassDescriptionDepthStencilResolve, pNext ) );
+ return *this;
+ }
+
+ SubpassDescriptionDepthStencilResolve( VkSubpassDescriptionDepthStencilResolve const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SubpassDescriptionDepthStencilResolve& operator=( VkSubpassDescriptionDepthStencilResolve const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SubpassDescriptionDepthStencilResolve const *>(&rhs);
+ return *this;
+ }
+
+ SubpassDescriptionDepthStencilResolve & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SubpassDescriptionDepthStencilResolve & setDepthResolveMode( VULKAN_HPP_NAMESPACE::ResolveModeFlagBits depthResolveMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ depthResolveMode = depthResolveMode_;
+ return *this;
+ }
+
+ SubpassDescriptionDepthStencilResolve & setStencilResolveMode( VULKAN_HPP_NAMESPACE::ResolveModeFlagBits stencilResolveMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ stencilResolveMode = stencilResolveMode_;
+ return *this;
+ }
+
+ SubpassDescriptionDepthStencilResolve & setPDepthStencilResolveAttachment( const VULKAN_HPP_NAMESPACE::AttachmentReference2* pDepthStencilResolveAttachment_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDepthStencilResolveAttachment = pDepthStencilResolveAttachment_;
+ return *this;
+ }
+
+ operator VkSubpassDescriptionDepthStencilResolve const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSubpassDescriptionDepthStencilResolve*>( this );
+ }
+
+ operator VkSubpassDescriptionDepthStencilResolve &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSubpassDescriptionDepthStencilResolve*>( this );
+ }
+
+ bool operator==( SubpassDescriptionDepthStencilResolve const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( depthResolveMode == rhs.depthResolveMode )
+ && ( stencilResolveMode == rhs.stencilResolveMode )
+ && ( pDepthStencilResolveAttachment == rhs.pDepthStencilResolveAttachment );
+ }
+
+ bool operator!=( SubpassDescriptionDepthStencilResolve const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSubpassDescriptionDepthStencilResolve;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ResolveModeFlagBits depthResolveMode = VULKAN_HPP_NAMESPACE::ResolveModeFlagBits::eNone;
+ VULKAN_HPP_NAMESPACE::ResolveModeFlagBits stencilResolveMode = VULKAN_HPP_NAMESPACE::ResolveModeFlagBits::eNone;
+ const VULKAN_HPP_NAMESPACE::AttachmentReference2* pDepthStencilResolveAttachment = {};
+ };
+ static_assert( sizeof( SubpassDescriptionDepthStencilResolve ) == sizeof( VkSubpassDescriptionDepthStencilResolve ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SubpassDescriptionDepthStencilResolve>::value, "struct wrapper is not a standard layout!" );
+
+ struct SubpassEndInfo
+ {
+ VULKAN_HPP_CONSTEXPR SubpassEndInfo() VULKAN_HPP_NOEXCEPT
+ {}
+
+ VULKAN_HPP_NAMESPACE::SubpassEndInfo & operator=( VULKAN_HPP_NAMESPACE::SubpassEndInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SubpassEndInfo ) - offsetof( SubpassEndInfo, pNext ) );
+ return *this;
+ }
+
+ SubpassEndInfo( VkSubpassEndInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SubpassEndInfo& operator=( VkSubpassEndInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SubpassEndInfo const *>(&rhs);
+ return *this;
+ }
+
+ SubpassEndInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ operator VkSubpassEndInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSubpassEndInfo*>( this );
+ }
+
+ operator VkSubpassEndInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSubpassEndInfo*>( this );
+ }
+
+ bool operator==( SubpassEndInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext );
+ }
+
+ bool operator!=( SubpassEndInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSubpassEndInfo;
+ const void* pNext = {};
+ };
+ static_assert( sizeof( SubpassEndInfo ) == sizeof( VkSubpassEndInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SubpassEndInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct SurfaceCapabilities2EXT
+ {
+ SurfaceCapabilities2EXT( uint32_t minImageCount_ = {},
+ uint32_t maxImageCount_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D currentExtent_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D minImageExtent_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D maxImageExtent_ = {},
+ uint32_t maxImageArrayLayers_ = {},
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagsKHR supportedTransforms_ = {},
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR currentTransform_ = VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR::eIdentity,
+ VULKAN_HPP_NAMESPACE::CompositeAlphaFlagsKHR supportedCompositeAlpha_ = {},
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags supportedUsageFlags_ = {},
+ VULKAN_HPP_NAMESPACE::SurfaceCounterFlagsEXT supportedSurfaceCounters_ = {} ) VULKAN_HPP_NOEXCEPT
+ : minImageCount( minImageCount_ )
+ , maxImageCount( maxImageCount_ )
+ , currentExtent( currentExtent_ )
+ , minImageExtent( minImageExtent_ )
+ , maxImageExtent( maxImageExtent_ )
+ , maxImageArrayLayers( maxImageArrayLayers_ )
+ , supportedTransforms( supportedTransforms_ )
+ , currentTransform( currentTransform_ )
+ , supportedCompositeAlpha( supportedCompositeAlpha_ )
+ , supportedUsageFlags( supportedUsageFlags_ )
+ , supportedSurfaceCounters( supportedSurfaceCounters_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SurfaceCapabilities2EXT & operator=( VULKAN_HPP_NAMESPACE::SurfaceCapabilities2EXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SurfaceCapabilities2EXT ) - offsetof( SurfaceCapabilities2EXT, pNext ) );
+ return *this;
+ }
+
+ SurfaceCapabilities2EXT( VkSurfaceCapabilities2EXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SurfaceCapabilities2EXT& operator=( VkSurfaceCapabilities2EXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SurfaceCapabilities2EXT const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSurfaceCapabilities2EXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSurfaceCapabilities2EXT*>( this );
+ }
+
+ operator VkSurfaceCapabilities2EXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSurfaceCapabilities2EXT*>( this );
+ }
+
+ bool operator==( SurfaceCapabilities2EXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( minImageCount == rhs.minImageCount )
+ && ( maxImageCount == rhs.maxImageCount )
+ && ( currentExtent == rhs.currentExtent )
+ && ( minImageExtent == rhs.minImageExtent )
+ && ( maxImageExtent == rhs.maxImageExtent )
+ && ( maxImageArrayLayers == rhs.maxImageArrayLayers )
+ && ( supportedTransforms == rhs.supportedTransforms )
+ && ( currentTransform == rhs.currentTransform )
+ && ( supportedCompositeAlpha == rhs.supportedCompositeAlpha )
+ && ( supportedUsageFlags == rhs.supportedUsageFlags )
+ && ( supportedSurfaceCounters == rhs.supportedSurfaceCounters );
+ }
+
+ bool operator!=( SurfaceCapabilities2EXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSurfaceCapabilities2EXT;
+ void* pNext = {};
+ uint32_t minImageCount = {};
+ uint32_t maxImageCount = {};
+ VULKAN_HPP_NAMESPACE::Extent2D currentExtent = {};
+ VULKAN_HPP_NAMESPACE::Extent2D minImageExtent = {};
+ VULKAN_HPP_NAMESPACE::Extent2D maxImageExtent = {};
+ uint32_t maxImageArrayLayers = {};
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagsKHR supportedTransforms = {};
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR currentTransform = VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR::eIdentity;
+ VULKAN_HPP_NAMESPACE::CompositeAlphaFlagsKHR supportedCompositeAlpha = {};
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags supportedUsageFlags = {};
+ VULKAN_HPP_NAMESPACE::SurfaceCounterFlagsEXT supportedSurfaceCounters = {};
+ };
+ static_assert( sizeof( SurfaceCapabilities2EXT ) == sizeof( VkSurfaceCapabilities2EXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SurfaceCapabilities2EXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct SurfaceCapabilitiesKHR
+ {
+ SurfaceCapabilitiesKHR( uint32_t minImageCount_ = {},
+ uint32_t maxImageCount_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D currentExtent_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D minImageExtent_ = {},
+ VULKAN_HPP_NAMESPACE::Extent2D maxImageExtent_ = {},
+ uint32_t maxImageArrayLayers_ = {},
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagsKHR supportedTransforms_ = {},
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR currentTransform_ = VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR::eIdentity,
+ VULKAN_HPP_NAMESPACE::CompositeAlphaFlagsKHR supportedCompositeAlpha_ = {},
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags supportedUsageFlags_ = {} ) VULKAN_HPP_NOEXCEPT
+ : minImageCount( minImageCount_ )
+ , maxImageCount( maxImageCount_ )
+ , currentExtent( currentExtent_ )
+ , minImageExtent( minImageExtent_ )
+ , maxImageExtent( maxImageExtent_ )
+ , maxImageArrayLayers( maxImageArrayLayers_ )
+ , supportedTransforms( supportedTransforms_ )
+ , currentTransform( currentTransform_ )
+ , supportedCompositeAlpha( supportedCompositeAlpha_ )
+ , supportedUsageFlags( supportedUsageFlags_ )
+ {}
+
+ SurfaceCapabilitiesKHR( VkSurfaceCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SurfaceCapabilitiesKHR& operator=( VkSurfaceCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSurfaceCapabilitiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSurfaceCapabilitiesKHR*>( this );
+ }
+
+ operator VkSurfaceCapabilitiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSurfaceCapabilitiesKHR*>( this );
+ }
+
+ bool operator==( SurfaceCapabilitiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( minImageCount == rhs.minImageCount )
+ && ( maxImageCount == rhs.maxImageCount )
+ && ( currentExtent == rhs.currentExtent )
+ && ( minImageExtent == rhs.minImageExtent )
+ && ( maxImageExtent == rhs.maxImageExtent )
+ && ( maxImageArrayLayers == rhs.maxImageArrayLayers )
+ && ( supportedTransforms == rhs.supportedTransforms )
+ && ( currentTransform == rhs.currentTransform )
+ && ( supportedCompositeAlpha == rhs.supportedCompositeAlpha )
+ && ( supportedUsageFlags == rhs.supportedUsageFlags );
+ }
+
+ bool operator!=( SurfaceCapabilitiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ uint32_t minImageCount = {};
+ uint32_t maxImageCount = {};
+ VULKAN_HPP_NAMESPACE::Extent2D currentExtent = {};
+ VULKAN_HPP_NAMESPACE::Extent2D minImageExtent = {};
+ VULKAN_HPP_NAMESPACE::Extent2D maxImageExtent = {};
+ uint32_t maxImageArrayLayers = {};
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagsKHR supportedTransforms = {};
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR currentTransform = VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR::eIdentity;
+ VULKAN_HPP_NAMESPACE::CompositeAlphaFlagsKHR supportedCompositeAlpha = {};
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags supportedUsageFlags = {};
+ };
+ static_assert( sizeof( SurfaceCapabilitiesKHR ) == sizeof( VkSurfaceCapabilitiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SurfaceCapabilitiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct SurfaceCapabilities2KHR
+ {
+ SurfaceCapabilities2KHR( VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesKHR surfaceCapabilities_ = {} ) VULKAN_HPP_NOEXCEPT
+ : surfaceCapabilities( surfaceCapabilities_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR & operator=( VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR ) - offsetof( SurfaceCapabilities2KHR, pNext ) );
+ return *this;
+ }
+
+ SurfaceCapabilities2KHR( VkSurfaceCapabilities2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SurfaceCapabilities2KHR& operator=( VkSurfaceCapabilities2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSurfaceCapabilities2KHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSurfaceCapabilities2KHR*>( this );
+ }
+
+ operator VkSurfaceCapabilities2KHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSurfaceCapabilities2KHR*>( this );
+ }
+
+ bool operator==( SurfaceCapabilities2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( surfaceCapabilities == rhs.surfaceCapabilities );
+ }
+
+ bool operator!=( SurfaceCapabilities2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSurfaceCapabilities2KHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesKHR surfaceCapabilities = {};
+ };
+ static_assert( sizeof( SurfaceCapabilities2KHR ) == sizeof( VkSurfaceCapabilities2KHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SurfaceCapabilities2KHR>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct SurfaceCapabilitiesFullScreenExclusiveEXT
+ {
+ VULKAN_HPP_CONSTEXPR SurfaceCapabilitiesFullScreenExclusiveEXT( VULKAN_HPP_NAMESPACE::Bool32 fullScreenExclusiveSupported_ = {} ) VULKAN_HPP_NOEXCEPT
+ : fullScreenExclusiveSupported( fullScreenExclusiveSupported_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesFullScreenExclusiveEXT & operator=( VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesFullScreenExclusiveEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesFullScreenExclusiveEXT ) - offsetof( SurfaceCapabilitiesFullScreenExclusiveEXT, pNext ) );
+ return *this;
+ }
+
+ SurfaceCapabilitiesFullScreenExclusiveEXT( VkSurfaceCapabilitiesFullScreenExclusiveEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SurfaceCapabilitiesFullScreenExclusiveEXT& operator=( VkSurfaceCapabilitiesFullScreenExclusiveEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesFullScreenExclusiveEXT const *>(&rhs);
+ return *this;
+ }
+
+ SurfaceCapabilitiesFullScreenExclusiveEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SurfaceCapabilitiesFullScreenExclusiveEXT & setFullScreenExclusiveSupported( VULKAN_HPP_NAMESPACE::Bool32 fullScreenExclusiveSupported_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fullScreenExclusiveSupported = fullScreenExclusiveSupported_;
+ return *this;
+ }
+
+ operator VkSurfaceCapabilitiesFullScreenExclusiveEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSurfaceCapabilitiesFullScreenExclusiveEXT*>( this );
+ }
+
+ operator VkSurfaceCapabilitiesFullScreenExclusiveEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSurfaceCapabilitiesFullScreenExclusiveEXT*>( this );
+ }
+
+ bool operator==( SurfaceCapabilitiesFullScreenExclusiveEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( fullScreenExclusiveSupported == rhs.fullScreenExclusiveSupported );
+ }
+
+ bool operator!=( SurfaceCapabilitiesFullScreenExclusiveEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSurfaceCapabilitiesFullScreenExclusiveEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 fullScreenExclusiveSupported = {};
+ };
+ static_assert( sizeof( SurfaceCapabilitiesFullScreenExclusiveEXT ) == sizeof( VkSurfaceCapabilitiesFullScreenExclusiveEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SurfaceCapabilitiesFullScreenExclusiveEXT>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct SurfaceFormatKHR
+ {
+ SurfaceFormatKHR( VULKAN_HPP_NAMESPACE::Format format_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::ColorSpaceKHR colorSpace_ = VULKAN_HPP_NAMESPACE::ColorSpaceKHR::eSrgbNonlinear ) VULKAN_HPP_NOEXCEPT
+ : format( format_ )
+ , colorSpace( colorSpace_ )
+ {}
+
+ SurfaceFormatKHR( VkSurfaceFormatKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SurfaceFormatKHR& operator=( VkSurfaceFormatKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SurfaceFormatKHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSurfaceFormatKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSurfaceFormatKHR*>( this );
+ }
+
+ operator VkSurfaceFormatKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSurfaceFormatKHR*>( this );
+ }
+
+ bool operator==( SurfaceFormatKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( format == rhs.format )
+ && ( colorSpace == rhs.colorSpace );
+ }
+
+ bool operator!=( SurfaceFormatKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ VULKAN_HPP_NAMESPACE::Format format = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::ColorSpaceKHR colorSpace = VULKAN_HPP_NAMESPACE::ColorSpaceKHR::eSrgbNonlinear;
+ };
+ static_assert( sizeof( SurfaceFormatKHR ) == sizeof( VkSurfaceFormatKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SurfaceFormatKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct SurfaceFormat2KHR
+ {
+ SurfaceFormat2KHR( VULKAN_HPP_NAMESPACE::SurfaceFormatKHR surfaceFormat_ = {} ) VULKAN_HPP_NOEXCEPT
+ : surfaceFormat( surfaceFormat_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SurfaceFormat2KHR & operator=( VULKAN_HPP_NAMESPACE::SurfaceFormat2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SurfaceFormat2KHR ) - offsetof( SurfaceFormat2KHR, pNext ) );
+ return *this;
+ }
+
+ SurfaceFormat2KHR( VkSurfaceFormat2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SurfaceFormat2KHR& operator=( VkSurfaceFormat2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SurfaceFormat2KHR const *>(&rhs);
+ return *this;
+ }
+
+ operator VkSurfaceFormat2KHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSurfaceFormat2KHR*>( this );
+ }
+
+ operator VkSurfaceFormat2KHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSurfaceFormat2KHR*>( this );
+ }
+
+ bool operator==( SurfaceFormat2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( surfaceFormat == rhs.surfaceFormat );
+ }
+
+ bool operator!=( SurfaceFormat2KHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSurfaceFormat2KHR;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SurfaceFormatKHR surfaceFormat = {};
+ };
+ static_assert( sizeof( SurfaceFormat2KHR ) == sizeof( VkSurfaceFormat2KHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SurfaceFormat2KHR>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct SurfaceFullScreenExclusiveInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR SurfaceFullScreenExclusiveInfoEXT( VULKAN_HPP_NAMESPACE::FullScreenExclusiveEXT fullScreenExclusive_ = VULKAN_HPP_NAMESPACE::FullScreenExclusiveEXT::eDefault ) VULKAN_HPP_NOEXCEPT
+ : fullScreenExclusive( fullScreenExclusive_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SurfaceFullScreenExclusiveInfoEXT & operator=( VULKAN_HPP_NAMESPACE::SurfaceFullScreenExclusiveInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SurfaceFullScreenExclusiveInfoEXT ) - offsetof( SurfaceFullScreenExclusiveInfoEXT, pNext ) );
+ return *this;
+ }
+
+ SurfaceFullScreenExclusiveInfoEXT( VkSurfaceFullScreenExclusiveInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SurfaceFullScreenExclusiveInfoEXT& operator=( VkSurfaceFullScreenExclusiveInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SurfaceFullScreenExclusiveInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ SurfaceFullScreenExclusiveInfoEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SurfaceFullScreenExclusiveInfoEXT & setFullScreenExclusive( VULKAN_HPP_NAMESPACE::FullScreenExclusiveEXT fullScreenExclusive_ ) VULKAN_HPP_NOEXCEPT
+ {
+ fullScreenExclusive = fullScreenExclusive_;
+ return *this;
+ }
+
+ operator VkSurfaceFullScreenExclusiveInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSurfaceFullScreenExclusiveInfoEXT*>( this );
+ }
+
+ operator VkSurfaceFullScreenExclusiveInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSurfaceFullScreenExclusiveInfoEXT*>( this );
+ }
+
+ bool operator==( SurfaceFullScreenExclusiveInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( fullScreenExclusive == rhs.fullScreenExclusive );
+ }
+
+ bool operator!=( SurfaceFullScreenExclusiveInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSurfaceFullScreenExclusiveInfoEXT;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::FullScreenExclusiveEXT fullScreenExclusive = VULKAN_HPP_NAMESPACE::FullScreenExclusiveEXT::eDefault;
+ };
+ static_assert( sizeof( SurfaceFullScreenExclusiveInfoEXT ) == sizeof( VkSurfaceFullScreenExclusiveInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SurfaceFullScreenExclusiveInfoEXT>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct SurfaceFullScreenExclusiveWin32InfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR SurfaceFullScreenExclusiveWin32InfoEXT( HMONITOR hmonitor_ = {} ) VULKAN_HPP_NOEXCEPT
+ : hmonitor( hmonitor_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SurfaceFullScreenExclusiveWin32InfoEXT & operator=( VULKAN_HPP_NAMESPACE::SurfaceFullScreenExclusiveWin32InfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SurfaceFullScreenExclusiveWin32InfoEXT ) - offsetof( SurfaceFullScreenExclusiveWin32InfoEXT, pNext ) );
+ return *this;
+ }
+
+ SurfaceFullScreenExclusiveWin32InfoEXT( VkSurfaceFullScreenExclusiveWin32InfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SurfaceFullScreenExclusiveWin32InfoEXT& operator=( VkSurfaceFullScreenExclusiveWin32InfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SurfaceFullScreenExclusiveWin32InfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ SurfaceFullScreenExclusiveWin32InfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SurfaceFullScreenExclusiveWin32InfoEXT & setHmonitor( HMONITOR hmonitor_ ) VULKAN_HPP_NOEXCEPT
+ {
+ hmonitor = hmonitor_;
+ return *this;
+ }
+
+ operator VkSurfaceFullScreenExclusiveWin32InfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSurfaceFullScreenExclusiveWin32InfoEXT*>( this );
+ }
+
+ operator VkSurfaceFullScreenExclusiveWin32InfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSurfaceFullScreenExclusiveWin32InfoEXT*>( this );
+ }
+
+ bool operator==( SurfaceFullScreenExclusiveWin32InfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( hmonitor == rhs.hmonitor );
+ }
+
+ bool operator!=( SurfaceFullScreenExclusiveWin32InfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSurfaceFullScreenExclusiveWin32InfoEXT;
+ const void* pNext = {};
+ HMONITOR hmonitor = {};
+ };
+ static_assert( sizeof( SurfaceFullScreenExclusiveWin32InfoEXT ) == sizeof( VkSurfaceFullScreenExclusiveWin32InfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SurfaceFullScreenExclusiveWin32InfoEXT>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct SurfaceProtectedCapabilitiesKHR
+ {
+ VULKAN_HPP_CONSTEXPR SurfaceProtectedCapabilitiesKHR( VULKAN_HPP_NAMESPACE::Bool32 supportsProtected_ = {} ) VULKAN_HPP_NOEXCEPT
+ : supportsProtected( supportsProtected_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SurfaceProtectedCapabilitiesKHR & operator=( VULKAN_HPP_NAMESPACE::SurfaceProtectedCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SurfaceProtectedCapabilitiesKHR ) - offsetof( SurfaceProtectedCapabilitiesKHR, pNext ) );
+ return *this;
+ }
+
+ SurfaceProtectedCapabilitiesKHR( VkSurfaceProtectedCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SurfaceProtectedCapabilitiesKHR& operator=( VkSurfaceProtectedCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SurfaceProtectedCapabilitiesKHR const *>(&rhs);
+ return *this;
+ }
+
+ SurfaceProtectedCapabilitiesKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SurfaceProtectedCapabilitiesKHR & setSupportsProtected( VULKAN_HPP_NAMESPACE::Bool32 supportsProtected_ ) VULKAN_HPP_NOEXCEPT
+ {
+ supportsProtected = supportsProtected_;
+ return *this;
+ }
+
+ operator VkSurfaceProtectedCapabilitiesKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSurfaceProtectedCapabilitiesKHR*>( this );
+ }
+
+ operator VkSurfaceProtectedCapabilitiesKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSurfaceProtectedCapabilitiesKHR*>( this );
+ }
+
+ bool operator==( SurfaceProtectedCapabilitiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( supportsProtected == rhs.supportsProtected );
+ }
+
+ bool operator!=( SurfaceProtectedCapabilitiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSurfaceProtectedCapabilitiesKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 supportsProtected = {};
+ };
+ static_assert( sizeof( SurfaceProtectedCapabilitiesKHR ) == sizeof( VkSurfaceProtectedCapabilitiesKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SurfaceProtectedCapabilitiesKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct SwapchainCounterCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR SwapchainCounterCreateInfoEXT( VULKAN_HPP_NAMESPACE::SurfaceCounterFlagsEXT surfaceCounters_ = {} ) VULKAN_HPP_NOEXCEPT
+ : surfaceCounters( surfaceCounters_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SwapchainCounterCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::SwapchainCounterCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SwapchainCounterCreateInfoEXT ) - offsetof( SwapchainCounterCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ SwapchainCounterCreateInfoEXT( VkSwapchainCounterCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SwapchainCounterCreateInfoEXT& operator=( VkSwapchainCounterCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SwapchainCounterCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ SwapchainCounterCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SwapchainCounterCreateInfoEXT & setSurfaceCounters( VULKAN_HPP_NAMESPACE::SurfaceCounterFlagsEXT surfaceCounters_ ) VULKAN_HPP_NOEXCEPT
+ {
+ surfaceCounters = surfaceCounters_;
+ return *this;
+ }
+
+ operator VkSwapchainCounterCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSwapchainCounterCreateInfoEXT*>( this );
+ }
+
+ operator VkSwapchainCounterCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSwapchainCounterCreateInfoEXT*>( this );
+ }
+
+ bool operator==( SwapchainCounterCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( surfaceCounters == rhs.surfaceCounters );
+ }
+
+ bool operator!=( SwapchainCounterCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSwapchainCounterCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SurfaceCounterFlagsEXT surfaceCounters = {};
+ };
+ static_assert( sizeof( SwapchainCounterCreateInfoEXT ) == sizeof( VkSwapchainCounterCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SwapchainCounterCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct SwapchainCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR SwapchainCreateInfoKHR( VULKAN_HPP_NAMESPACE::SwapchainCreateFlagsKHR flags_ = {},
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface_ = {},
+ uint32_t minImageCount_ = {},
+ VULKAN_HPP_NAMESPACE::Format imageFormat_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+ VULKAN_HPP_NAMESPACE::ColorSpaceKHR imageColorSpace_ = VULKAN_HPP_NAMESPACE::ColorSpaceKHR::eSrgbNonlinear,
+ VULKAN_HPP_NAMESPACE::Extent2D imageExtent_ = {},
+ uint32_t imageArrayLayers_ = {},
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags imageUsage_ = {},
+ VULKAN_HPP_NAMESPACE::SharingMode imageSharingMode_ = VULKAN_HPP_NAMESPACE::SharingMode::eExclusive,
+ uint32_t queueFamilyIndexCount_ = {},
+ const uint32_t* pQueueFamilyIndices_ = {},
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR preTransform_ = VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR::eIdentity,
+ VULKAN_HPP_NAMESPACE::CompositeAlphaFlagBitsKHR compositeAlpha_ = VULKAN_HPP_NAMESPACE::CompositeAlphaFlagBitsKHR::eOpaque,
+ VULKAN_HPP_NAMESPACE::PresentModeKHR presentMode_ = VULKAN_HPP_NAMESPACE::PresentModeKHR::eImmediate,
+ VULKAN_HPP_NAMESPACE::Bool32 clipped_ = {},
+ VULKAN_HPP_NAMESPACE::SwapchainKHR oldSwapchain_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , surface( surface_ )
+ , minImageCount( minImageCount_ )
+ , imageFormat( imageFormat_ )
+ , imageColorSpace( imageColorSpace_ )
+ , imageExtent( imageExtent_ )
+ , imageArrayLayers( imageArrayLayers_ )
+ , imageUsage( imageUsage_ )
+ , imageSharingMode( imageSharingMode_ )
+ , queueFamilyIndexCount( queueFamilyIndexCount_ )
+ , pQueueFamilyIndices( pQueueFamilyIndices_ )
+ , preTransform( preTransform_ )
+ , compositeAlpha( compositeAlpha_ )
+ , presentMode( presentMode_ )
+ , clipped( clipped_ )
+ , oldSwapchain( oldSwapchain_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR ) - offsetof( SwapchainCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR( VkSwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SwapchainCreateInfoKHR& operator=( VkSwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::SwapchainCreateFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setSurface( VULKAN_HPP_NAMESPACE::SurfaceKHR surface_ ) VULKAN_HPP_NOEXCEPT
+ {
+ surface = surface_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setMinImageCount( uint32_t minImageCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ minImageCount = minImageCount_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setImageFormat( VULKAN_HPP_NAMESPACE::Format imageFormat_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageFormat = imageFormat_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setImageColorSpace( VULKAN_HPP_NAMESPACE::ColorSpaceKHR imageColorSpace_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageColorSpace = imageColorSpace_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setImageExtent( VULKAN_HPP_NAMESPACE::Extent2D imageExtent_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageExtent = imageExtent_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setImageArrayLayers( uint32_t imageArrayLayers_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageArrayLayers = imageArrayLayers_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setImageUsage( VULKAN_HPP_NAMESPACE::ImageUsageFlags imageUsage_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageUsage = imageUsage_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setImageSharingMode( VULKAN_HPP_NAMESPACE::SharingMode imageSharingMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ imageSharingMode = imageSharingMode_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setQueueFamilyIndexCount( uint32_t queueFamilyIndexCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ queueFamilyIndexCount = queueFamilyIndexCount_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setPQueueFamilyIndices( const uint32_t* pQueueFamilyIndices_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pQueueFamilyIndices = pQueueFamilyIndices_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setPreTransform( VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR preTransform_ ) VULKAN_HPP_NOEXCEPT
+ {
+ preTransform = preTransform_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setCompositeAlpha( VULKAN_HPP_NAMESPACE::CompositeAlphaFlagBitsKHR compositeAlpha_ ) VULKAN_HPP_NOEXCEPT
+ {
+ compositeAlpha = compositeAlpha_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setPresentMode( VULKAN_HPP_NAMESPACE::PresentModeKHR presentMode_ ) VULKAN_HPP_NOEXCEPT
+ {
+ presentMode = presentMode_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setClipped( VULKAN_HPP_NAMESPACE::Bool32 clipped_ ) VULKAN_HPP_NOEXCEPT
+ {
+ clipped = clipped_;
+ return *this;
+ }
+
+ SwapchainCreateInfoKHR & setOldSwapchain( VULKAN_HPP_NAMESPACE::SwapchainKHR oldSwapchain_ ) VULKAN_HPP_NOEXCEPT
+ {
+ oldSwapchain = oldSwapchain_;
+ return *this;
+ }
+
+ operator VkSwapchainCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSwapchainCreateInfoKHR*>( this );
+ }
+
+ operator VkSwapchainCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSwapchainCreateInfoKHR*>( this );
+ }
+
+ bool operator==( SwapchainCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( surface == rhs.surface )
+ && ( minImageCount == rhs.minImageCount )
+ && ( imageFormat == rhs.imageFormat )
+ && ( imageColorSpace == rhs.imageColorSpace )
+ && ( imageExtent == rhs.imageExtent )
+ && ( imageArrayLayers == rhs.imageArrayLayers )
+ && ( imageUsage == rhs.imageUsage )
+ && ( imageSharingMode == rhs.imageSharingMode )
+ && ( queueFamilyIndexCount == rhs.queueFamilyIndexCount )
+ && ( pQueueFamilyIndices == rhs.pQueueFamilyIndices )
+ && ( preTransform == rhs.preTransform )
+ && ( compositeAlpha == rhs.compositeAlpha )
+ && ( presentMode == rhs.presentMode )
+ && ( clipped == rhs.clipped )
+ && ( oldSwapchain == rhs.oldSwapchain );
+ }
+
+ bool operator!=( SwapchainCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSwapchainCreateInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::SwapchainCreateFlagsKHR flags = {};
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface = {};
+ uint32_t minImageCount = {};
+ VULKAN_HPP_NAMESPACE::Format imageFormat = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+ VULKAN_HPP_NAMESPACE::ColorSpaceKHR imageColorSpace = VULKAN_HPP_NAMESPACE::ColorSpaceKHR::eSrgbNonlinear;
+ VULKAN_HPP_NAMESPACE::Extent2D imageExtent = {};
+ uint32_t imageArrayLayers = {};
+ VULKAN_HPP_NAMESPACE::ImageUsageFlags imageUsage = {};
+ VULKAN_HPP_NAMESPACE::SharingMode imageSharingMode = VULKAN_HPP_NAMESPACE::SharingMode::eExclusive;
+ uint32_t queueFamilyIndexCount = {};
+ const uint32_t* pQueueFamilyIndices = {};
+ VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR preTransform = VULKAN_HPP_NAMESPACE::SurfaceTransformFlagBitsKHR::eIdentity;
+ VULKAN_HPP_NAMESPACE::CompositeAlphaFlagBitsKHR compositeAlpha = VULKAN_HPP_NAMESPACE::CompositeAlphaFlagBitsKHR::eOpaque;
+ VULKAN_HPP_NAMESPACE::PresentModeKHR presentMode = VULKAN_HPP_NAMESPACE::PresentModeKHR::eImmediate;
+ VULKAN_HPP_NAMESPACE::Bool32 clipped = {};
+ VULKAN_HPP_NAMESPACE::SwapchainKHR oldSwapchain = {};
+ };
+ static_assert( sizeof( SwapchainCreateInfoKHR ) == sizeof( VkSwapchainCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SwapchainCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+
+ struct SwapchainDisplayNativeHdrCreateInfoAMD
+ {
+ VULKAN_HPP_CONSTEXPR SwapchainDisplayNativeHdrCreateInfoAMD( VULKAN_HPP_NAMESPACE::Bool32 localDimmingEnable_ = {} ) VULKAN_HPP_NOEXCEPT
+ : localDimmingEnable( localDimmingEnable_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::SwapchainDisplayNativeHdrCreateInfoAMD & operator=( VULKAN_HPP_NAMESPACE::SwapchainDisplayNativeHdrCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::SwapchainDisplayNativeHdrCreateInfoAMD ) - offsetof( SwapchainDisplayNativeHdrCreateInfoAMD, pNext ) );
+ return *this;
+ }
+
+ SwapchainDisplayNativeHdrCreateInfoAMD( VkSwapchainDisplayNativeHdrCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ SwapchainDisplayNativeHdrCreateInfoAMD& operator=( VkSwapchainDisplayNativeHdrCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SwapchainDisplayNativeHdrCreateInfoAMD const *>(&rhs);
+ return *this;
+ }
+
+ SwapchainDisplayNativeHdrCreateInfoAMD & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ SwapchainDisplayNativeHdrCreateInfoAMD & setLocalDimmingEnable( VULKAN_HPP_NAMESPACE::Bool32 localDimmingEnable_ ) VULKAN_HPP_NOEXCEPT
+ {
+ localDimmingEnable = localDimmingEnable_;
+ return *this;
+ }
+
+ operator VkSwapchainDisplayNativeHdrCreateInfoAMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkSwapchainDisplayNativeHdrCreateInfoAMD*>( this );
+ }
+
+ operator VkSwapchainDisplayNativeHdrCreateInfoAMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkSwapchainDisplayNativeHdrCreateInfoAMD*>( this );
+ }
+
+ bool operator==( SwapchainDisplayNativeHdrCreateInfoAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( localDimmingEnable == rhs.localDimmingEnable );
+ }
+
+ bool operator!=( SwapchainDisplayNativeHdrCreateInfoAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eSwapchainDisplayNativeHdrCreateInfoAMD;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 localDimmingEnable = {};
+ };
+ static_assert( sizeof( SwapchainDisplayNativeHdrCreateInfoAMD ) == sizeof( VkSwapchainDisplayNativeHdrCreateInfoAMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<SwapchainDisplayNativeHdrCreateInfoAMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct TextureLODGatherFormatPropertiesAMD
+ {
+ TextureLODGatherFormatPropertiesAMD( VULKAN_HPP_NAMESPACE::Bool32 supportsTextureGatherLODBiasAMD_ = {} ) VULKAN_HPP_NOEXCEPT
+ : supportsTextureGatherLODBiasAMD( supportsTextureGatherLODBiasAMD_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::TextureLODGatherFormatPropertiesAMD & operator=( VULKAN_HPP_NAMESPACE::TextureLODGatherFormatPropertiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::TextureLODGatherFormatPropertiesAMD ) - offsetof( TextureLODGatherFormatPropertiesAMD, pNext ) );
+ return *this;
+ }
+
+ TextureLODGatherFormatPropertiesAMD( VkTextureLODGatherFormatPropertiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ TextureLODGatherFormatPropertiesAMD& operator=( VkTextureLODGatherFormatPropertiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::TextureLODGatherFormatPropertiesAMD const *>(&rhs);
+ return *this;
+ }
+
+ operator VkTextureLODGatherFormatPropertiesAMD const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkTextureLODGatherFormatPropertiesAMD*>( this );
+ }
+
+ operator VkTextureLODGatherFormatPropertiesAMD &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkTextureLODGatherFormatPropertiesAMD*>( this );
+ }
+
+ bool operator==( TextureLODGatherFormatPropertiesAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( supportsTextureGatherLODBiasAMD == rhs.supportsTextureGatherLODBiasAMD );
+ }
+
+ bool operator!=( TextureLODGatherFormatPropertiesAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eTextureLodGatherFormatPropertiesAMD;
+ void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Bool32 supportsTextureGatherLODBiasAMD = {};
+ };
+ static_assert( sizeof( TextureLODGatherFormatPropertiesAMD ) == sizeof( VkTextureLODGatherFormatPropertiesAMD ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<TextureLODGatherFormatPropertiesAMD>::value, "struct wrapper is not a standard layout!" );
+
+ struct TimelineSemaphoreSubmitInfo
+ {
+ VULKAN_HPP_CONSTEXPR TimelineSemaphoreSubmitInfo( uint32_t waitSemaphoreValueCount_ = {},
+ const uint64_t* pWaitSemaphoreValues_ = {},
+ uint32_t signalSemaphoreValueCount_ = {},
+ const uint64_t* pSignalSemaphoreValues_ = {} ) VULKAN_HPP_NOEXCEPT
+ : waitSemaphoreValueCount( waitSemaphoreValueCount_ )
+ , pWaitSemaphoreValues( pWaitSemaphoreValues_ )
+ , signalSemaphoreValueCount( signalSemaphoreValueCount_ )
+ , pSignalSemaphoreValues( pSignalSemaphoreValues_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::TimelineSemaphoreSubmitInfo & operator=( VULKAN_HPP_NAMESPACE::TimelineSemaphoreSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::TimelineSemaphoreSubmitInfo ) - offsetof( TimelineSemaphoreSubmitInfo, pNext ) );
+ return *this;
+ }
+
+ TimelineSemaphoreSubmitInfo( VkTimelineSemaphoreSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ TimelineSemaphoreSubmitInfo& operator=( VkTimelineSemaphoreSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::TimelineSemaphoreSubmitInfo const *>(&rhs);
+ return *this;
+ }
+
+ TimelineSemaphoreSubmitInfo & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ TimelineSemaphoreSubmitInfo & setWaitSemaphoreValueCount( uint32_t waitSemaphoreValueCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ waitSemaphoreValueCount = waitSemaphoreValueCount_;
+ return *this;
+ }
+
+ TimelineSemaphoreSubmitInfo & setPWaitSemaphoreValues( const uint64_t* pWaitSemaphoreValues_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pWaitSemaphoreValues = pWaitSemaphoreValues_;
+ return *this;
+ }
+
+ TimelineSemaphoreSubmitInfo & setSignalSemaphoreValueCount( uint32_t signalSemaphoreValueCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ signalSemaphoreValueCount = signalSemaphoreValueCount_;
+ return *this;
+ }
+
+ TimelineSemaphoreSubmitInfo & setPSignalSemaphoreValues( const uint64_t* pSignalSemaphoreValues_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pSignalSemaphoreValues = pSignalSemaphoreValues_;
+ return *this;
+ }
+
+ operator VkTimelineSemaphoreSubmitInfo const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkTimelineSemaphoreSubmitInfo*>( this );
+ }
+
+ operator VkTimelineSemaphoreSubmitInfo &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkTimelineSemaphoreSubmitInfo*>( this );
+ }
+
+ bool operator==( TimelineSemaphoreSubmitInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( waitSemaphoreValueCount == rhs.waitSemaphoreValueCount )
+ && ( pWaitSemaphoreValues == rhs.pWaitSemaphoreValues )
+ && ( signalSemaphoreValueCount == rhs.signalSemaphoreValueCount )
+ && ( pSignalSemaphoreValues == rhs.pSignalSemaphoreValues );
+ }
+
+ bool operator!=( TimelineSemaphoreSubmitInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eTimelineSemaphoreSubmitInfo;
+ const void* pNext = {};
+ uint32_t waitSemaphoreValueCount = {};
+ const uint64_t* pWaitSemaphoreValues = {};
+ uint32_t signalSemaphoreValueCount = {};
+ const uint64_t* pSignalSemaphoreValues = {};
+ };
+ static_assert( sizeof( TimelineSemaphoreSubmitInfo ) == sizeof( VkTimelineSemaphoreSubmitInfo ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<TimelineSemaphoreSubmitInfo>::value, "struct wrapper is not a standard layout!" );
+
+ struct ValidationCacheCreateInfoEXT
+ {
+ VULKAN_HPP_CONSTEXPR ValidationCacheCreateInfoEXT( VULKAN_HPP_NAMESPACE::ValidationCacheCreateFlagsEXT flags_ = {},
+ size_t initialDataSize_ = {},
+ const void* pInitialData_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , initialDataSize( initialDataSize_ )
+ , pInitialData( pInitialData_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ValidationCacheCreateInfoEXT & operator=( VULKAN_HPP_NAMESPACE::ValidationCacheCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ValidationCacheCreateInfoEXT ) - offsetof( ValidationCacheCreateInfoEXT, pNext ) );
+ return *this;
+ }
+
+ ValidationCacheCreateInfoEXT( VkValidationCacheCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ValidationCacheCreateInfoEXT& operator=( VkValidationCacheCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ValidationCacheCreateInfoEXT const *>(&rhs);
+ return *this;
+ }
+
+ ValidationCacheCreateInfoEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ValidationCacheCreateInfoEXT & setFlags( VULKAN_HPP_NAMESPACE::ValidationCacheCreateFlagsEXT flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ValidationCacheCreateInfoEXT & setInitialDataSize( size_t initialDataSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ initialDataSize = initialDataSize_;
+ return *this;
+ }
+
+ ValidationCacheCreateInfoEXT & setPInitialData( const void* pInitialData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pInitialData = pInitialData_;
+ return *this;
+ }
+
+ operator VkValidationCacheCreateInfoEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkValidationCacheCreateInfoEXT*>( this );
+ }
+
+ operator VkValidationCacheCreateInfoEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkValidationCacheCreateInfoEXT*>( this );
+ }
+
+ bool operator==( ValidationCacheCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( initialDataSize == rhs.initialDataSize )
+ && ( pInitialData == rhs.pInitialData );
+ }
+
+ bool operator!=( ValidationCacheCreateInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eValidationCacheCreateInfoEXT;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ValidationCacheCreateFlagsEXT flags = {};
+ size_t initialDataSize = {};
+ const void* pInitialData = {};
+ };
+ static_assert( sizeof( ValidationCacheCreateInfoEXT ) == sizeof( VkValidationCacheCreateInfoEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ValidationCacheCreateInfoEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct ValidationFeaturesEXT
+ {
+ VULKAN_HPP_CONSTEXPR ValidationFeaturesEXT( uint32_t enabledValidationFeatureCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ValidationFeatureEnableEXT* pEnabledValidationFeatures_ = {},
+ uint32_t disabledValidationFeatureCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ValidationFeatureDisableEXT* pDisabledValidationFeatures_ = {} ) VULKAN_HPP_NOEXCEPT
+ : enabledValidationFeatureCount( enabledValidationFeatureCount_ )
+ , pEnabledValidationFeatures( pEnabledValidationFeatures_ )
+ , disabledValidationFeatureCount( disabledValidationFeatureCount_ )
+ , pDisabledValidationFeatures( pDisabledValidationFeatures_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ValidationFeaturesEXT & operator=( VULKAN_HPP_NAMESPACE::ValidationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ValidationFeaturesEXT ) - offsetof( ValidationFeaturesEXT, pNext ) );
+ return *this;
+ }
+
+ ValidationFeaturesEXT( VkValidationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ValidationFeaturesEXT& operator=( VkValidationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ValidationFeaturesEXT const *>(&rhs);
+ return *this;
+ }
+
+ ValidationFeaturesEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ValidationFeaturesEXT & setEnabledValidationFeatureCount( uint32_t enabledValidationFeatureCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ enabledValidationFeatureCount = enabledValidationFeatureCount_;
+ return *this;
+ }
+
+ ValidationFeaturesEXT & setPEnabledValidationFeatures( const VULKAN_HPP_NAMESPACE::ValidationFeatureEnableEXT* pEnabledValidationFeatures_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pEnabledValidationFeatures = pEnabledValidationFeatures_;
+ return *this;
+ }
+
+ ValidationFeaturesEXT & setDisabledValidationFeatureCount( uint32_t disabledValidationFeatureCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ disabledValidationFeatureCount = disabledValidationFeatureCount_;
+ return *this;
+ }
+
+ ValidationFeaturesEXT & setPDisabledValidationFeatures( const VULKAN_HPP_NAMESPACE::ValidationFeatureDisableEXT* pDisabledValidationFeatures_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDisabledValidationFeatures = pDisabledValidationFeatures_;
+ return *this;
+ }
+
+ operator VkValidationFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkValidationFeaturesEXT*>( this );
+ }
+
+ operator VkValidationFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkValidationFeaturesEXT*>( this );
+ }
+
+ bool operator==( ValidationFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( enabledValidationFeatureCount == rhs.enabledValidationFeatureCount )
+ && ( pEnabledValidationFeatures == rhs.pEnabledValidationFeatures )
+ && ( disabledValidationFeatureCount == rhs.disabledValidationFeatureCount )
+ && ( pDisabledValidationFeatures == rhs.pDisabledValidationFeatures );
+ }
+
+ bool operator!=( ValidationFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eValidationFeaturesEXT;
+ const void* pNext = {};
+ uint32_t enabledValidationFeatureCount = {};
+ const VULKAN_HPP_NAMESPACE::ValidationFeatureEnableEXT* pEnabledValidationFeatures = {};
+ uint32_t disabledValidationFeatureCount = {};
+ const VULKAN_HPP_NAMESPACE::ValidationFeatureDisableEXT* pDisabledValidationFeatures = {};
+ };
+ static_assert( sizeof( ValidationFeaturesEXT ) == sizeof( VkValidationFeaturesEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ValidationFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
+ struct ValidationFlagsEXT
+ {
+ VULKAN_HPP_CONSTEXPR ValidationFlagsEXT( uint32_t disabledValidationCheckCount_ = {},
+ const VULKAN_HPP_NAMESPACE::ValidationCheckEXT* pDisabledValidationChecks_ = {} ) VULKAN_HPP_NOEXCEPT
+ : disabledValidationCheckCount( disabledValidationCheckCount_ )
+ , pDisabledValidationChecks( pDisabledValidationChecks_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ValidationFlagsEXT & operator=( VULKAN_HPP_NAMESPACE::ValidationFlagsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ValidationFlagsEXT ) - offsetof( ValidationFlagsEXT, pNext ) );
+ return *this;
+ }
+
+ ValidationFlagsEXT( VkValidationFlagsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ValidationFlagsEXT& operator=( VkValidationFlagsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ValidationFlagsEXT const *>(&rhs);
+ return *this;
+ }
+
+ ValidationFlagsEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ValidationFlagsEXT & setDisabledValidationCheckCount( uint32_t disabledValidationCheckCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ disabledValidationCheckCount = disabledValidationCheckCount_;
+ return *this;
+ }
+
+ ValidationFlagsEXT & setPDisabledValidationChecks( const VULKAN_HPP_NAMESPACE::ValidationCheckEXT* pDisabledValidationChecks_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pDisabledValidationChecks = pDisabledValidationChecks_;
+ return *this;
+ }
+
+ operator VkValidationFlagsEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkValidationFlagsEXT*>( this );
+ }
+
+ operator VkValidationFlagsEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkValidationFlagsEXT*>( this );
+ }
+
+ bool operator==( ValidationFlagsEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( disabledValidationCheckCount == rhs.disabledValidationCheckCount )
+ && ( pDisabledValidationChecks == rhs.pDisabledValidationChecks );
+ }
+
+ bool operator!=( ValidationFlagsEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eValidationFlagsEXT;
+ const void* pNext = {};
+ uint32_t disabledValidationCheckCount = {};
+ const VULKAN_HPP_NAMESPACE::ValidationCheckEXT* pDisabledValidationChecks = {};
+ };
+ static_assert( sizeof( ValidationFlagsEXT ) == sizeof( VkValidationFlagsEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ValidationFlagsEXT>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_VI_NN
+
+ struct ViSurfaceCreateInfoNN
+ {
+ VULKAN_HPP_CONSTEXPR ViSurfaceCreateInfoNN( VULKAN_HPP_NAMESPACE::ViSurfaceCreateFlagsNN flags_ = {},
+ void* window_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , window( window_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::ViSurfaceCreateInfoNN & operator=( VULKAN_HPP_NAMESPACE::ViSurfaceCreateInfoNN const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::ViSurfaceCreateInfoNN ) - offsetof( ViSurfaceCreateInfoNN, pNext ) );
+ return *this;
+ }
+
+ ViSurfaceCreateInfoNN( VkViSurfaceCreateInfoNN const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ ViSurfaceCreateInfoNN& operator=( VkViSurfaceCreateInfoNN const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ViSurfaceCreateInfoNN const *>(&rhs);
+ return *this;
+ }
+
+ ViSurfaceCreateInfoNN & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ ViSurfaceCreateInfoNN & setFlags( VULKAN_HPP_NAMESPACE::ViSurfaceCreateFlagsNN flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ ViSurfaceCreateInfoNN & setWindow( void* window_ ) VULKAN_HPP_NOEXCEPT
+ {
+ window = window_;
+ return *this;
+ }
+
+ operator VkViSurfaceCreateInfoNN const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkViSurfaceCreateInfoNN*>( this );
+ }
+
+ operator VkViSurfaceCreateInfoNN &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkViSurfaceCreateInfoNN*>( this );
+ }
+
+ bool operator==( ViSurfaceCreateInfoNN const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( window == rhs.window );
+ }
+
+ bool operator!=( ViSurfaceCreateInfoNN const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eViSurfaceCreateInfoNN;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::ViSurfaceCreateFlagsNN flags = {};
+ void* window = {};
+ };
+ static_assert( sizeof( ViSurfaceCreateInfoNN ) == sizeof( VkViSurfaceCreateInfoNN ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<ViSurfaceCreateInfoNN>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_VI_NN*/
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+
+ struct WaylandSurfaceCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR WaylandSurfaceCreateInfoKHR( VULKAN_HPP_NAMESPACE::WaylandSurfaceCreateFlagsKHR flags_ = {},
+ struct wl_display* display_ = {},
+ struct wl_surface* surface_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , display( display_ )
+ , surface( surface_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::WaylandSurfaceCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::WaylandSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::WaylandSurfaceCreateInfoKHR ) - offsetof( WaylandSurfaceCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ WaylandSurfaceCreateInfoKHR( VkWaylandSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ WaylandSurfaceCreateInfoKHR& operator=( VkWaylandSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::WaylandSurfaceCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ WaylandSurfaceCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ WaylandSurfaceCreateInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::WaylandSurfaceCreateFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ WaylandSurfaceCreateInfoKHR & setDisplay( struct wl_display* display_ ) VULKAN_HPP_NOEXCEPT
+ {
+ display = display_;
+ return *this;
+ }
+
+ WaylandSurfaceCreateInfoKHR & setSurface( struct wl_surface* surface_ ) VULKAN_HPP_NOEXCEPT
+ {
+ surface = surface_;
+ return *this;
+ }
+
+ operator VkWaylandSurfaceCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkWaylandSurfaceCreateInfoKHR*>( this );
+ }
+
+ operator VkWaylandSurfaceCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkWaylandSurfaceCreateInfoKHR*>( this );
+ }
+
+ bool operator==( WaylandSurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( display == rhs.display )
+ && ( surface == rhs.surface );
+ }
+
+ bool operator!=( WaylandSurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eWaylandSurfaceCreateInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::WaylandSurfaceCreateFlagsKHR flags = {};
+ struct wl_display* display = {};
+ struct wl_surface* surface = {};
+ };
+ static_assert( sizeof( WaylandSurfaceCreateInfoKHR ) == sizeof( VkWaylandSurfaceCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<WaylandSurfaceCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct Win32KeyedMutexAcquireReleaseInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR Win32KeyedMutexAcquireReleaseInfoKHR( uint32_t acquireCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DeviceMemory* pAcquireSyncs_ = {},
+ const uint64_t* pAcquireKeys_ = {},
+ const uint32_t* pAcquireTimeouts_ = {},
+ uint32_t releaseCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DeviceMemory* pReleaseSyncs_ = {},
+ const uint64_t* pReleaseKeys_ = {} ) VULKAN_HPP_NOEXCEPT
+ : acquireCount( acquireCount_ )
+ , pAcquireSyncs( pAcquireSyncs_ )
+ , pAcquireKeys( pAcquireKeys_ )
+ , pAcquireTimeouts( pAcquireTimeouts_ )
+ , releaseCount( releaseCount_ )
+ , pReleaseSyncs( pReleaseSyncs_ )
+ , pReleaseKeys( pReleaseKeys_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::Win32KeyedMutexAcquireReleaseInfoKHR & operator=( VULKAN_HPP_NAMESPACE::Win32KeyedMutexAcquireReleaseInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::Win32KeyedMutexAcquireReleaseInfoKHR ) - offsetof( Win32KeyedMutexAcquireReleaseInfoKHR, pNext ) );
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoKHR( VkWin32KeyedMutexAcquireReleaseInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoKHR& operator=( VkWin32KeyedMutexAcquireReleaseInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::Win32KeyedMutexAcquireReleaseInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoKHR & setAcquireCount( uint32_t acquireCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ acquireCount = acquireCount_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoKHR & setPAcquireSyncs( const VULKAN_HPP_NAMESPACE::DeviceMemory* pAcquireSyncs_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAcquireSyncs = pAcquireSyncs_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoKHR & setPAcquireKeys( const uint64_t* pAcquireKeys_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAcquireKeys = pAcquireKeys_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoKHR & setPAcquireTimeouts( const uint32_t* pAcquireTimeouts_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAcquireTimeouts = pAcquireTimeouts_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoKHR & setReleaseCount( uint32_t releaseCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ releaseCount = releaseCount_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoKHR & setPReleaseSyncs( const VULKAN_HPP_NAMESPACE::DeviceMemory* pReleaseSyncs_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pReleaseSyncs = pReleaseSyncs_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoKHR & setPReleaseKeys( const uint64_t* pReleaseKeys_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pReleaseKeys = pReleaseKeys_;
+ return *this;
+ }
+
+ operator VkWin32KeyedMutexAcquireReleaseInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkWin32KeyedMutexAcquireReleaseInfoKHR*>( this );
+ }
+
+ operator VkWin32KeyedMutexAcquireReleaseInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkWin32KeyedMutexAcquireReleaseInfoKHR*>( this );
+ }
+
+ bool operator==( Win32KeyedMutexAcquireReleaseInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( acquireCount == rhs.acquireCount )
+ && ( pAcquireSyncs == rhs.pAcquireSyncs )
+ && ( pAcquireKeys == rhs.pAcquireKeys )
+ && ( pAcquireTimeouts == rhs.pAcquireTimeouts )
+ && ( releaseCount == rhs.releaseCount )
+ && ( pReleaseSyncs == rhs.pReleaseSyncs )
+ && ( pReleaseKeys == rhs.pReleaseKeys );
+ }
+
+ bool operator!=( Win32KeyedMutexAcquireReleaseInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eWin32KeyedMutexAcquireReleaseInfoKHR;
+ const void* pNext = {};
+ uint32_t acquireCount = {};
+ const VULKAN_HPP_NAMESPACE::DeviceMemory* pAcquireSyncs = {};
+ const uint64_t* pAcquireKeys = {};
+ const uint32_t* pAcquireTimeouts = {};
+ uint32_t releaseCount = {};
+ const VULKAN_HPP_NAMESPACE::DeviceMemory* pReleaseSyncs = {};
+ const uint64_t* pReleaseKeys = {};
+ };
+ static_assert( sizeof( Win32KeyedMutexAcquireReleaseInfoKHR ) == sizeof( VkWin32KeyedMutexAcquireReleaseInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<Win32KeyedMutexAcquireReleaseInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct Win32KeyedMutexAcquireReleaseInfoNV
+ {
+ VULKAN_HPP_CONSTEXPR Win32KeyedMutexAcquireReleaseInfoNV( uint32_t acquireCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DeviceMemory* pAcquireSyncs_ = {},
+ const uint64_t* pAcquireKeys_ = {},
+ const uint32_t* pAcquireTimeoutMilliseconds_ = {},
+ uint32_t releaseCount_ = {},
+ const VULKAN_HPP_NAMESPACE::DeviceMemory* pReleaseSyncs_ = {},
+ const uint64_t* pReleaseKeys_ = {} ) VULKAN_HPP_NOEXCEPT
+ : acquireCount( acquireCount_ )
+ , pAcquireSyncs( pAcquireSyncs_ )
+ , pAcquireKeys( pAcquireKeys_ )
+ , pAcquireTimeoutMilliseconds( pAcquireTimeoutMilliseconds_ )
+ , releaseCount( releaseCount_ )
+ , pReleaseSyncs( pReleaseSyncs_ )
+ , pReleaseKeys( pReleaseKeys_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::Win32KeyedMutexAcquireReleaseInfoNV & operator=( VULKAN_HPP_NAMESPACE::Win32KeyedMutexAcquireReleaseInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::Win32KeyedMutexAcquireReleaseInfoNV ) - offsetof( Win32KeyedMutexAcquireReleaseInfoNV, pNext ) );
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoNV( VkWin32KeyedMutexAcquireReleaseInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoNV& operator=( VkWin32KeyedMutexAcquireReleaseInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::Win32KeyedMutexAcquireReleaseInfoNV const *>(&rhs);
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoNV & setAcquireCount( uint32_t acquireCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ acquireCount = acquireCount_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoNV & setPAcquireSyncs( const VULKAN_HPP_NAMESPACE::DeviceMemory* pAcquireSyncs_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAcquireSyncs = pAcquireSyncs_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoNV & setPAcquireKeys( const uint64_t* pAcquireKeys_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAcquireKeys = pAcquireKeys_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoNV & setPAcquireTimeoutMilliseconds( const uint32_t* pAcquireTimeoutMilliseconds_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAcquireTimeoutMilliseconds = pAcquireTimeoutMilliseconds_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoNV & setReleaseCount( uint32_t releaseCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ releaseCount = releaseCount_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoNV & setPReleaseSyncs( const VULKAN_HPP_NAMESPACE::DeviceMemory* pReleaseSyncs_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pReleaseSyncs = pReleaseSyncs_;
+ return *this;
+ }
+
+ Win32KeyedMutexAcquireReleaseInfoNV & setPReleaseKeys( const uint64_t* pReleaseKeys_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pReleaseKeys = pReleaseKeys_;
+ return *this;
+ }
+
+ operator VkWin32KeyedMutexAcquireReleaseInfoNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkWin32KeyedMutexAcquireReleaseInfoNV*>( this );
+ }
+
+ operator VkWin32KeyedMutexAcquireReleaseInfoNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkWin32KeyedMutexAcquireReleaseInfoNV*>( this );
+ }
+
+ bool operator==( Win32KeyedMutexAcquireReleaseInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( acquireCount == rhs.acquireCount )
+ && ( pAcquireSyncs == rhs.pAcquireSyncs )
+ && ( pAcquireKeys == rhs.pAcquireKeys )
+ && ( pAcquireTimeoutMilliseconds == rhs.pAcquireTimeoutMilliseconds )
+ && ( releaseCount == rhs.releaseCount )
+ && ( pReleaseSyncs == rhs.pReleaseSyncs )
+ && ( pReleaseKeys == rhs.pReleaseKeys );
+ }
+
+ bool operator!=( Win32KeyedMutexAcquireReleaseInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eWin32KeyedMutexAcquireReleaseInfoNV;
+ const void* pNext = {};
+ uint32_t acquireCount = {};
+ const VULKAN_HPP_NAMESPACE::DeviceMemory* pAcquireSyncs = {};
+ const uint64_t* pAcquireKeys = {};
+ const uint32_t* pAcquireTimeoutMilliseconds = {};
+ uint32_t releaseCount = {};
+ const VULKAN_HPP_NAMESPACE::DeviceMemory* pReleaseSyncs = {};
+ const uint64_t* pReleaseKeys = {};
+ };
+ static_assert( sizeof( Win32KeyedMutexAcquireReleaseInfoNV ) == sizeof( VkWin32KeyedMutexAcquireReleaseInfoNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<Win32KeyedMutexAcquireReleaseInfoNV>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ struct Win32SurfaceCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR Win32SurfaceCreateInfoKHR( VULKAN_HPP_NAMESPACE::Win32SurfaceCreateFlagsKHR flags_ = {},
+ HINSTANCE hinstance_ = {},
+ HWND hwnd_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , hinstance( hinstance_ )
+ , hwnd( hwnd_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::Win32SurfaceCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::Win32SurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::Win32SurfaceCreateInfoKHR ) - offsetof( Win32SurfaceCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ Win32SurfaceCreateInfoKHR( VkWin32SurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ Win32SurfaceCreateInfoKHR& operator=( VkWin32SurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::Win32SurfaceCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ Win32SurfaceCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ Win32SurfaceCreateInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::Win32SurfaceCreateFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ Win32SurfaceCreateInfoKHR & setHinstance( HINSTANCE hinstance_ ) VULKAN_HPP_NOEXCEPT
+ {
+ hinstance = hinstance_;
+ return *this;
+ }
+
+ Win32SurfaceCreateInfoKHR & setHwnd( HWND hwnd_ ) VULKAN_HPP_NOEXCEPT
+ {
+ hwnd = hwnd_;
+ return *this;
+ }
+
+ operator VkWin32SurfaceCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkWin32SurfaceCreateInfoKHR*>( this );
+ }
+
+ operator VkWin32SurfaceCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkWin32SurfaceCreateInfoKHR*>( this );
+ }
+
+ bool operator==( Win32SurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( hinstance == rhs.hinstance )
+ && ( hwnd == rhs.hwnd );
+ }
+
+ bool operator!=( Win32SurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eWin32SurfaceCreateInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::Win32SurfaceCreateFlagsKHR flags = {};
+ HINSTANCE hinstance = {};
+ HWND hwnd = {};
+ };
+ static_assert( sizeof( Win32SurfaceCreateInfoKHR ) == sizeof( VkWin32SurfaceCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<Win32SurfaceCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ struct WriteDescriptorSet
+ {
+ VULKAN_HPP_CONSTEXPR WriteDescriptorSet( VULKAN_HPP_NAMESPACE::DescriptorSet dstSet_ = {},
+ uint32_t dstBinding_ = {},
+ uint32_t dstArrayElement_ = {},
+ uint32_t descriptorCount_ = {},
+ VULKAN_HPP_NAMESPACE::DescriptorType descriptorType_ = VULKAN_HPP_NAMESPACE::DescriptorType::eSampler,
+ const VULKAN_HPP_NAMESPACE::DescriptorImageInfo* pImageInfo_ = {},
+ const VULKAN_HPP_NAMESPACE::DescriptorBufferInfo* pBufferInfo_ = {},
+ const VULKAN_HPP_NAMESPACE::BufferView* pTexelBufferView_ = {} ) VULKAN_HPP_NOEXCEPT
+ : dstSet( dstSet_ )
+ , dstBinding( dstBinding_ )
+ , dstArrayElement( dstArrayElement_ )
+ , descriptorCount( descriptorCount_ )
+ , descriptorType( descriptorType_ )
+ , pImageInfo( pImageInfo_ )
+ , pBufferInfo( pBufferInfo_ )
+ , pTexelBufferView( pTexelBufferView_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::WriteDescriptorSet & operator=( VULKAN_HPP_NAMESPACE::WriteDescriptorSet const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::WriteDescriptorSet ) - offsetof( WriteDescriptorSet, pNext ) );
+ return *this;
+ }
+
+ WriteDescriptorSet( VkWriteDescriptorSet const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ WriteDescriptorSet& operator=( VkWriteDescriptorSet const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::WriteDescriptorSet const *>(&rhs);
+ return *this;
+ }
+
+ WriteDescriptorSet & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ WriteDescriptorSet & setDstSet( VULKAN_HPP_NAMESPACE::DescriptorSet dstSet_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstSet = dstSet_;
+ return *this;
+ }
+
+ WriteDescriptorSet & setDstBinding( uint32_t dstBinding_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstBinding = dstBinding_;
+ return *this;
+ }
+
+ WriteDescriptorSet & setDstArrayElement( uint32_t dstArrayElement_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dstArrayElement = dstArrayElement_;
+ return *this;
+ }
+
+ WriteDescriptorSet & setDescriptorCount( uint32_t descriptorCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorCount = descriptorCount_;
+ return *this;
+ }
+
+ WriteDescriptorSet & setDescriptorType( VULKAN_HPP_NAMESPACE::DescriptorType descriptorType_ ) VULKAN_HPP_NOEXCEPT
+ {
+ descriptorType = descriptorType_;
+ return *this;
+ }
+
+ WriteDescriptorSet & setPImageInfo( const VULKAN_HPP_NAMESPACE::DescriptorImageInfo* pImageInfo_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pImageInfo = pImageInfo_;
+ return *this;
+ }
+
+ WriteDescriptorSet & setPBufferInfo( const VULKAN_HPP_NAMESPACE::DescriptorBufferInfo* pBufferInfo_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pBufferInfo = pBufferInfo_;
+ return *this;
+ }
+
+ WriteDescriptorSet & setPTexelBufferView( const VULKAN_HPP_NAMESPACE::BufferView* pTexelBufferView_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pTexelBufferView = pTexelBufferView_;
+ return *this;
+ }
+
+ operator VkWriteDescriptorSet const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkWriteDescriptorSet*>( this );
+ }
+
+ operator VkWriteDescriptorSet &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkWriteDescriptorSet*>( this );
+ }
+
+ bool operator==( WriteDescriptorSet const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( dstSet == rhs.dstSet )
+ && ( dstBinding == rhs.dstBinding )
+ && ( dstArrayElement == rhs.dstArrayElement )
+ && ( descriptorCount == rhs.descriptorCount )
+ && ( descriptorType == rhs.descriptorType )
+ && ( pImageInfo == rhs.pImageInfo )
+ && ( pBufferInfo == rhs.pBufferInfo )
+ && ( pTexelBufferView == rhs.pTexelBufferView );
+ }
+
+ bool operator!=( WriteDescriptorSet const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eWriteDescriptorSet;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::DescriptorSet dstSet = {};
+ uint32_t dstBinding = {};
+ uint32_t dstArrayElement = {};
+ uint32_t descriptorCount = {};
+ VULKAN_HPP_NAMESPACE::DescriptorType descriptorType = VULKAN_HPP_NAMESPACE::DescriptorType::eSampler;
+ const VULKAN_HPP_NAMESPACE::DescriptorImageInfo* pImageInfo = {};
+ const VULKAN_HPP_NAMESPACE::DescriptorBufferInfo* pBufferInfo = {};
+ const VULKAN_HPP_NAMESPACE::BufferView* pTexelBufferView = {};
+ };
+ static_assert( sizeof( WriteDescriptorSet ) == sizeof( VkWriteDescriptorSet ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<WriteDescriptorSet>::value, "struct wrapper is not a standard layout!" );
+
+ struct WriteDescriptorSetAccelerationStructureNV
+ {
+ VULKAN_HPP_CONSTEXPR WriteDescriptorSetAccelerationStructureNV( uint32_t accelerationStructureCount_ = {},
+ const VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructures_ = {} ) VULKAN_HPP_NOEXCEPT
+ : accelerationStructureCount( accelerationStructureCount_ )
+ , pAccelerationStructures( pAccelerationStructures_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::WriteDescriptorSetAccelerationStructureNV & operator=( VULKAN_HPP_NAMESPACE::WriteDescriptorSetAccelerationStructureNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::WriteDescriptorSetAccelerationStructureNV ) - offsetof( WriteDescriptorSetAccelerationStructureNV, pNext ) );
+ return *this;
+ }
+
+ WriteDescriptorSetAccelerationStructureNV( VkWriteDescriptorSetAccelerationStructureNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ WriteDescriptorSetAccelerationStructureNV& operator=( VkWriteDescriptorSetAccelerationStructureNV const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::WriteDescriptorSetAccelerationStructureNV const *>(&rhs);
+ return *this;
+ }
+
+ WriteDescriptorSetAccelerationStructureNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ WriteDescriptorSetAccelerationStructureNV & setAccelerationStructureCount( uint32_t accelerationStructureCount_ ) VULKAN_HPP_NOEXCEPT
+ {
+ accelerationStructureCount = accelerationStructureCount_;
+ return *this;
+ }
+
+ WriteDescriptorSetAccelerationStructureNV & setPAccelerationStructures( const VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructures_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pAccelerationStructures = pAccelerationStructures_;
+ return *this;
+ }
+
+ operator VkWriteDescriptorSetAccelerationStructureNV const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkWriteDescriptorSetAccelerationStructureNV*>( this );
+ }
+
+ operator VkWriteDescriptorSetAccelerationStructureNV &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkWriteDescriptorSetAccelerationStructureNV*>( this );
+ }
+
+ bool operator==( WriteDescriptorSetAccelerationStructureNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( accelerationStructureCount == rhs.accelerationStructureCount )
+ && ( pAccelerationStructures == rhs.pAccelerationStructures );
+ }
+
+ bool operator!=( WriteDescriptorSetAccelerationStructureNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eWriteDescriptorSetAccelerationStructureNV;
+ const void* pNext = {};
+ uint32_t accelerationStructureCount = {};
+ const VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructures = {};
+ };
+ static_assert( sizeof( WriteDescriptorSetAccelerationStructureNV ) == sizeof( VkWriteDescriptorSetAccelerationStructureNV ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<WriteDescriptorSetAccelerationStructureNV>::value, "struct wrapper is not a standard layout!" );
+
+ struct WriteDescriptorSetInlineUniformBlockEXT
+ {
+ VULKAN_HPP_CONSTEXPR WriteDescriptorSetInlineUniformBlockEXT( uint32_t dataSize_ = {},
+ const void* pData_ = {} ) VULKAN_HPP_NOEXCEPT
+ : dataSize( dataSize_ )
+ , pData( pData_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::WriteDescriptorSetInlineUniformBlockEXT & operator=( VULKAN_HPP_NAMESPACE::WriteDescriptorSetInlineUniformBlockEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::WriteDescriptorSetInlineUniformBlockEXT ) - offsetof( WriteDescriptorSetInlineUniformBlockEXT, pNext ) );
+ return *this;
+ }
+
+ WriteDescriptorSetInlineUniformBlockEXT( VkWriteDescriptorSetInlineUniformBlockEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ WriteDescriptorSetInlineUniformBlockEXT& operator=( VkWriteDescriptorSetInlineUniformBlockEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::WriteDescriptorSetInlineUniformBlockEXT const *>(&rhs);
+ return *this;
+ }
+
+ WriteDescriptorSetInlineUniformBlockEXT & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ WriteDescriptorSetInlineUniformBlockEXT & setDataSize( uint32_t dataSize_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dataSize = dataSize_;
+ return *this;
+ }
+
+ WriteDescriptorSetInlineUniformBlockEXT & setPData( const void* pData_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pData = pData_;
+ return *this;
+ }
+
+ operator VkWriteDescriptorSetInlineUniformBlockEXT const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkWriteDescriptorSetInlineUniformBlockEXT*>( this );
+ }
+
+ operator VkWriteDescriptorSetInlineUniformBlockEXT &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkWriteDescriptorSetInlineUniformBlockEXT*>( this );
+ }
+
+ bool operator==( WriteDescriptorSetInlineUniformBlockEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( dataSize == rhs.dataSize )
+ && ( pData == rhs.pData );
+ }
+
+ bool operator!=( WriteDescriptorSetInlineUniformBlockEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eWriteDescriptorSetInlineUniformBlockEXT;
+ const void* pNext = {};
+ uint32_t dataSize = {};
+ const void* pData = {};
+ };
+ static_assert( sizeof( WriteDescriptorSetInlineUniformBlockEXT ) == sizeof( VkWriteDescriptorSetInlineUniformBlockEXT ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<WriteDescriptorSetInlineUniformBlockEXT>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+
+ struct XcbSurfaceCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR XcbSurfaceCreateInfoKHR( VULKAN_HPP_NAMESPACE::XcbSurfaceCreateFlagsKHR flags_ = {},
+ xcb_connection_t* connection_ = {},
+ xcb_window_t window_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , connection( connection_ )
+ , window( window_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::XcbSurfaceCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::XcbSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::XcbSurfaceCreateInfoKHR ) - offsetof( XcbSurfaceCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ XcbSurfaceCreateInfoKHR( VkXcbSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ XcbSurfaceCreateInfoKHR& operator=( VkXcbSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::XcbSurfaceCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ XcbSurfaceCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ XcbSurfaceCreateInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::XcbSurfaceCreateFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ XcbSurfaceCreateInfoKHR & setConnection( xcb_connection_t* connection_ ) VULKAN_HPP_NOEXCEPT
+ {
+ connection = connection_;
+ return *this;
+ }
+
+ XcbSurfaceCreateInfoKHR & setWindow( xcb_window_t window_ ) VULKAN_HPP_NOEXCEPT
+ {
+ window = window_;
+ return *this;
+ }
+
+ operator VkXcbSurfaceCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkXcbSurfaceCreateInfoKHR*>( this );
+ }
+
+ operator VkXcbSurfaceCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkXcbSurfaceCreateInfoKHR*>( this );
+ }
+
+ bool operator==( XcbSurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( connection == rhs.connection )
+ && ( window == rhs.window );
+ }
+
+ bool operator!=( XcbSurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eXcbSurfaceCreateInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::XcbSurfaceCreateFlagsKHR flags = {};
+ xcb_connection_t* connection = {};
+ xcb_window_t window = {};
+ };
+ static_assert( sizeof( XcbSurfaceCreateInfoKHR ) == sizeof( VkXcbSurfaceCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<XcbSurfaceCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+
+ struct XlibSurfaceCreateInfoKHR
+ {
+ VULKAN_HPP_CONSTEXPR XlibSurfaceCreateInfoKHR( VULKAN_HPP_NAMESPACE::XlibSurfaceCreateFlagsKHR flags_ = {},
+ Display* dpy_ = {},
+ Window window_ = {} ) VULKAN_HPP_NOEXCEPT
+ : flags( flags_ )
+ , dpy( dpy_ )
+ , window( window_ )
+ {}
+
+ VULKAN_HPP_NAMESPACE::XlibSurfaceCreateInfoKHR & operator=( VULKAN_HPP_NAMESPACE::XlibSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ memcpy( &pNext, &rhs.pNext, sizeof( VULKAN_HPP_NAMESPACE::XlibSurfaceCreateInfoKHR ) - offsetof( XlibSurfaceCreateInfoKHR, pNext ) );
+ return *this;
+ }
+
+ XlibSurfaceCreateInfoKHR( VkXlibSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = rhs;
+ }
+
+ XlibSurfaceCreateInfoKHR& operator=( VkXlibSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+ {
+ *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::XlibSurfaceCreateInfoKHR const *>(&rhs);
+ return *this;
+ }
+
+ XlibSurfaceCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+ {
+ pNext = pNext_;
+ return *this;
+ }
+
+ XlibSurfaceCreateInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::XlibSurfaceCreateFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+ {
+ flags = flags_;
+ return *this;
+ }
+
+ XlibSurfaceCreateInfoKHR & setDpy( Display* dpy_ ) VULKAN_HPP_NOEXCEPT
+ {
+ dpy = dpy_;
+ return *this;
+ }
+
+ XlibSurfaceCreateInfoKHR & setWindow( Window window_ ) VULKAN_HPP_NOEXCEPT
+ {
+ window = window_;
+ return *this;
+ }
+
+ operator VkXlibSurfaceCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<const VkXlibSurfaceCreateInfoKHR*>( this );
+ }
+
+ operator VkXlibSurfaceCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+ {
+ return *reinterpret_cast<VkXlibSurfaceCreateInfoKHR*>( this );
+ }
+
+ bool operator==( XlibSurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return ( sType == rhs.sType )
+ && ( pNext == rhs.pNext )
+ && ( flags == rhs.flags )
+ && ( dpy == rhs.dpy )
+ && ( window == rhs.window );
+ }
+
+ bool operator!=( XlibSurfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+ {
+ return !operator==( rhs );
+ }
+
+ public:
+ const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eXlibSurfaceCreateInfoKHR;
+ const void* pNext = {};
+ VULKAN_HPP_NAMESPACE::XlibSurfaceCreateFlagsKHR flags = {};
+ Display* dpy = {};
+ Window window = {};
+ };
+ static_assert( sizeof( XlibSurfaceCreateInfoKHR ) == sizeof( VkXlibSurfaceCreateInfoKHR ), "struct and wrapper have different size!" );
+ static_assert( std::is_standard_layout<XlibSurfaceCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result createInstance( const VULKAN_HPP_NAMESPACE::InstanceCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Instance* pInstance, Dispatch const &d) VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateInstance( reinterpret_cast<const VkInstanceCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkInstance*>( pInstance ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Instance>::type createInstance( const InstanceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d )
+ {
+ VULKAN_HPP_NAMESPACE::Instance instance;
+ Result result = static_cast<Result>( d.vkCreateInstance( reinterpret_cast<const VkInstanceCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkInstance*>( &instance ) ) );
+ return createResultValue( result, instance, VULKAN_HPP_NAMESPACE_STRING"::createInstance" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Instance,Dispatch>>::type createInstanceUnique( const InstanceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d )
+ {
+ VULKAN_HPP_NAMESPACE::Instance instance;
+ Result result = static_cast<Result>( d.vkCreateInstance( reinterpret_cast<const VkInstanceCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkInstance*>( &instance ) ) );
+
+ ObjectDestroy<NoParent,Dispatch> deleter( allocator, d );
+ return createResultValue<Instance,Dispatch>( result, instance, VULKAN_HPP_NAMESPACE_STRING"::createInstanceUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result enumerateInstanceExtensionProperties( const char* pLayerName, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::ExtensionProperties* pProperties, Dispatch const &d) VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkEnumerateInstanceExtensionProperties( pLayerName, pPropertyCount, reinterpret_cast<VkExtensionProperties*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<ExtensionProperties,Allocator>>::type enumerateInstanceExtensionProperties( Optional<const std::string> layerName, Dispatch const &d )
+ {
+ std::vector<ExtensionProperties,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumerateInstanceExtensionProperties( layerName ? layerName->c_str() : nullptr, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkEnumerateInstanceExtensionProperties( layerName ? layerName->c_str() : nullptr, &propertyCount, reinterpret_cast<VkExtensionProperties*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::enumerateInstanceExtensionProperties" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<ExtensionProperties,Allocator>>::type enumerateInstanceExtensionProperties( Optional<const std::string> layerName, Allocator const& vectorAllocator, Dispatch const &d )
+ {
+ std::vector<ExtensionProperties,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumerateInstanceExtensionProperties( layerName ? layerName->c_str() : nullptr, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkEnumerateInstanceExtensionProperties( layerName ? layerName->c_str() : nullptr, &propertyCount, reinterpret_cast<VkExtensionProperties*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::enumerateInstanceExtensionProperties" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result enumerateInstanceLayerProperties( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::LayerProperties* pProperties, Dispatch const &d) VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkEnumerateInstanceLayerProperties( pPropertyCount, reinterpret_cast<VkLayerProperties*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<LayerProperties,Allocator>>::type enumerateInstanceLayerProperties(Dispatch const &d )
+ {
+ std::vector<LayerProperties,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumerateInstanceLayerProperties( &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkEnumerateInstanceLayerProperties( &propertyCount, reinterpret_cast<VkLayerProperties*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::enumerateInstanceLayerProperties" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<LayerProperties,Allocator>>::type enumerateInstanceLayerProperties(Allocator const& vectorAllocator, Dispatch const &d )
+ {
+ std::vector<LayerProperties,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumerateInstanceLayerProperties( &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkEnumerateInstanceLayerProperties( &propertyCount, reinterpret_cast<VkLayerProperties*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::enumerateInstanceLayerProperties" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result enumerateInstanceVersion( uint32_t* pApiVersion, Dispatch const &d) VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkEnumerateInstanceVersion( pApiVersion ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<uint32_t>::type enumerateInstanceVersion(Dispatch const &d )
+ {
+ uint32_t apiVersion;
+ Result result = static_cast<Result>( d.vkEnumerateInstanceVersion( &apiVersion ) );
+ return createResultValue( result, apiVersion, VULKAN_HPP_NAMESPACE_STRING"::enumerateInstanceVersion" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result CommandBuffer::begin( const VULKAN_HPP_NAMESPACE::CommandBufferBeginInfo* pBeginInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkBeginCommandBuffer( m_commandBuffer, reinterpret_cast<const VkCommandBufferBeginInfo*>( pBeginInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type CommandBuffer::begin( const CommandBufferBeginInfo & beginInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkBeginCommandBuffer( m_commandBuffer, reinterpret_cast<const VkCommandBufferBeginInfo*>( &beginInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::CommandBuffer::begin" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginConditionalRenderingEXT( const VULKAN_HPP_NAMESPACE::ConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginConditionalRenderingEXT( m_commandBuffer, reinterpret_cast<const VkConditionalRenderingBeginInfoEXT*>( pConditionalRenderingBegin ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginConditionalRenderingEXT( const ConditionalRenderingBeginInfoEXT & conditionalRenderingBegin, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginConditionalRenderingEXT( m_commandBuffer, reinterpret_cast<const VkConditionalRenderingBeginInfoEXT*>( &conditionalRenderingBegin ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginDebugUtilsLabelEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pLabelInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginDebugUtilsLabelEXT( m_commandBuffer, reinterpret_cast<const VkDebugUtilsLabelEXT*>( pLabelInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginDebugUtilsLabelEXT( const DebugUtilsLabelEXT & labelInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginDebugUtilsLabelEXT( m_commandBuffer, reinterpret_cast<const VkDebugUtilsLabelEXT*>( &labelInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginQuery( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, VULKAN_HPP_NAMESPACE::QueryControlFlags flags, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginQuery( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), query, static_cast<VkQueryControlFlags>( flags ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginQuery( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, VULKAN_HPP_NAMESPACE::QueryControlFlags flags, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginQuery( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), query, static_cast<VkQueryControlFlags>( flags ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginQueryIndexedEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, VULKAN_HPP_NAMESPACE::QueryControlFlags flags, uint32_t index, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginQueryIndexedEXT( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), query, static_cast<VkQueryControlFlags>( flags ), index );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginQueryIndexedEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, VULKAN_HPP_NAMESPACE::QueryControlFlags flags, uint32_t index, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginQueryIndexedEXT( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), query, static_cast<VkQueryControlFlags>( flags ), index );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginRenderPass( const VULKAN_HPP_NAMESPACE::RenderPassBeginInfo* pRenderPassBegin, VULKAN_HPP_NAMESPACE::SubpassContents contents, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginRenderPass( m_commandBuffer, reinterpret_cast<const VkRenderPassBeginInfo*>( pRenderPassBegin ), static_cast<VkSubpassContents>( contents ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginRenderPass( const RenderPassBeginInfo & renderPassBegin, VULKAN_HPP_NAMESPACE::SubpassContents contents, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginRenderPass( m_commandBuffer, reinterpret_cast<const VkRenderPassBeginInfo*>( &renderPassBegin ), static_cast<VkSubpassContents>( contents ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginRenderPass2( const VULKAN_HPP_NAMESPACE::RenderPassBeginInfo* pRenderPassBegin, const VULKAN_HPP_NAMESPACE::SubpassBeginInfo* pSubpassBeginInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginRenderPass2( m_commandBuffer, reinterpret_cast<const VkRenderPassBeginInfo*>( pRenderPassBegin ), reinterpret_cast<const VkSubpassBeginInfo*>( pSubpassBeginInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginRenderPass2( const RenderPassBeginInfo & renderPassBegin, const SubpassBeginInfo & subpassBeginInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginRenderPass2( m_commandBuffer, reinterpret_cast<const VkRenderPassBeginInfo*>( &renderPassBegin ), reinterpret_cast<const VkSubpassBeginInfo*>( &subpassBeginInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginRenderPass2KHR( const VULKAN_HPP_NAMESPACE::RenderPassBeginInfo* pRenderPassBegin, const VULKAN_HPP_NAMESPACE::SubpassBeginInfo* pSubpassBeginInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginRenderPass2KHR( m_commandBuffer, reinterpret_cast<const VkRenderPassBeginInfo*>( pRenderPassBegin ), reinterpret_cast<const VkSubpassBeginInfo*>( pSubpassBeginInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginRenderPass2KHR( const RenderPassBeginInfo & renderPassBegin, const SubpassBeginInfo & subpassBeginInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginRenderPass2KHR( m_commandBuffer, reinterpret_cast<const VkRenderPassBeginInfo*>( &renderPassBegin ), reinterpret_cast<const VkSubpassBeginInfo*>( &subpassBeginInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginTransformFeedbackEXT( uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VULKAN_HPP_NAMESPACE::Buffer* pCounterBuffers, const VULKAN_HPP_NAMESPACE::DeviceSize* pCounterBufferOffsets, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBeginTransformFeedbackEXT( m_commandBuffer, firstCounterBuffer, counterBufferCount, reinterpret_cast<const VkBuffer*>( pCounterBuffers ), reinterpret_cast<const VkDeviceSize*>( pCounterBufferOffsets ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::beginTransformFeedbackEXT( uint32_t firstCounterBuffer, ArrayProxy<const VULKAN_HPP_NAMESPACE::Buffer> counterBuffers, ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> counterBufferOffsets, Dispatch const &d ) const
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( counterBuffers.size() == counterBufferOffsets.size() );
+#else
+ if ( counterBuffers.size() != counterBufferOffsets.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkCommandBuffer::beginTransformFeedbackEXT: counterBuffers.size() != counterBufferOffsets.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+ d.vkCmdBeginTransformFeedbackEXT( m_commandBuffer, firstCounterBuffer, counterBuffers.size() , reinterpret_cast<const VkBuffer*>( counterBuffers.data() ), reinterpret_cast<const VkDeviceSize*>( counterBufferOffsets.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindDescriptorSets( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VULKAN_HPP_NAMESPACE::DescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBindDescriptorSets( m_commandBuffer, static_cast<VkPipelineBindPoint>( pipelineBindPoint ), static_cast<VkPipelineLayout>( layout ), firstSet, descriptorSetCount, reinterpret_cast<const VkDescriptorSet*>( pDescriptorSets ), dynamicOffsetCount, pDynamicOffsets );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindDescriptorSets( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t firstSet, ArrayProxy<const VULKAN_HPP_NAMESPACE::DescriptorSet> descriptorSets, ArrayProxy<const uint32_t> dynamicOffsets, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBindDescriptorSets( m_commandBuffer, static_cast<VkPipelineBindPoint>( pipelineBindPoint ), static_cast<VkPipelineLayout>( layout ), firstSet, descriptorSets.size() , reinterpret_cast<const VkDescriptorSet*>( descriptorSets.data() ), dynamicOffsets.size() , dynamicOffsets.data() );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindIndexBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::IndexType indexType, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBindIndexBuffer( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkIndexType>( indexType ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindIndexBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::IndexType indexType, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBindIndexBuffer( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkIndexType>( indexType ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindPipeline( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::Pipeline pipeline, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBindPipeline( m_commandBuffer, static_cast<VkPipelineBindPoint>( pipelineBindPoint ), static_cast<VkPipeline>( pipeline ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindPipeline( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::Pipeline pipeline, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBindPipeline( m_commandBuffer, static_cast<VkPipelineBindPoint>( pipelineBindPoint ), static_cast<VkPipeline>( pipeline ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindShadingRateImageNV( VULKAN_HPP_NAMESPACE::ImageView imageView, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBindShadingRateImageNV( m_commandBuffer, static_cast<VkImageView>( imageView ), static_cast<VkImageLayout>( imageLayout ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindShadingRateImageNV( VULKAN_HPP_NAMESPACE::ImageView imageView, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBindShadingRateImageNV( m_commandBuffer, static_cast<VkImageView>( imageView ), static_cast<VkImageLayout>( imageLayout ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindTransformFeedbackBuffersEXT( uint32_t firstBinding, uint32_t bindingCount, const VULKAN_HPP_NAMESPACE::Buffer* pBuffers, const VULKAN_HPP_NAMESPACE::DeviceSize* pOffsets, const VULKAN_HPP_NAMESPACE::DeviceSize* pSizes, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBindTransformFeedbackBuffersEXT( m_commandBuffer, firstBinding, bindingCount, reinterpret_cast<const VkBuffer*>( pBuffers ), reinterpret_cast<const VkDeviceSize*>( pOffsets ), reinterpret_cast<const VkDeviceSize*>( pSizes ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindTransformFeedbackBuffersEXT( uint32_t firstBinding, ArrayProxy<const VULKAN_HPP_NAMESPACE::Buffer> buffers, ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> offsets, ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> sizes, Dispatch const &d ) const
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( buffers.size() == offsets.size() );
+#else
+ if ( buffers.size() != offsets.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkCommandBuffer::bindTransformFeedbackBuffersEXT: buffers.size() != offsets.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( buffers.size() == sizes.size() );
+#else
+ if ( buffers.size() != sizes.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkCommandBuffer::bindTransformFeedbackBuffersEXT: buffers.size() != sizes.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( offsets.size() == sizes.size() );
+#else
+ if ( offsets.size() != sizes.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkCommandBuffer::bindTransformFeedbackBuffersEXT: offsets.size() != sizes.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+ d.vkCmdBindTransformFeedbackBuffersEXT( m_commandBuffer, firstBinding, buffers.size() , reinterpret_cast<const VkBuffer*>( buffers.data() ), reinterpret_cast<const VkDeviceSize*>( offsets.data() ), reinterpret_cast<const VkDeviceSize*>( sizes.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindVertexBuffers( uint32_t firstBinding, uint32_t bindingCount, const VULKAN_HPP_NAMESPACE::Buffer* pBuffers, const VULKAN_HPP_NAMESPACE::DeviceSize* pOffsets, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBindVertexBuffers( m_commandBuffer, firstBinding, bindingCount, reinterpret_cast<const VkBuffer*>( pBuffers ), reinterpret_cast<const VkDeviceSize*>( pOffsets ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::bindVertexBuffers( uint32_t firstBinding, ArrayProxy<const VULKAN_HPP_NAMESPACE::Buffer> buffers, ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> offsets, Dispatch const &d ) const
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( buffers.size() == offsets.size() );
+#else
+ if ( buffers.size() != offsets.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkCommandBuffer::bindVertexBuffers: buffers.size() != offsets.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+ d.vkCmdBindVertexBuffers( m_commandBuffer, firstBinding, buffers.size() , reinterpret_cast<const VkBuffer*>( buffers.data() ), reinterpret_cast<const VkDeviceSize*>( offsets.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::blitImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::ImageBlit* pRegions, VULKAN_HPP_NAMESPACE::Filter filter, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBlitImage( m_commandBuffer, static_cast<VkImage>( srcImage ), static_cast<VkImageLayout>( srcImageLayout ), static_cast<VkImage>( dstImage ), static_cast<VkImageLayout>( dstImageLayout ), regionCount, reinterpret_cast<const VkImageBlit*>( pRegions ), static_cast<VkFilter>( filter ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::blitImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageBlit> regions, VULKAN_HPP_NAMESPACE::Filter filter, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBlitImage( m_commandBuffer, static_cast<VkImage>( srcImage ), static_cast<VkImageLayout>( srcImageLayout ), static_cast<VkImage>( dstImage ), static_cast<VkImageLayout>( dstImageLayout ), regions.size() , reinterpret_cast<const VkImageBlit*>( regions.data() ), static_cast<VkFilter>( filter ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::buildAccelerationStructureNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV* pInfo, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBuildAccelerationStructureNV( m_commandBuffer, reinterpret_cast<const VkAccelerationStructureInfoNV*>( pInfo ), static_cast<VkBuffer>( instanceData ), static_cast<VkDeviceSize>( instanceOffset ), static_cast<VkBool32>( update ), static_cast<VkAccelerationStructureNV>( dst ), static_cast<VkAccelerationStructureNV>( src ), static_cast<VkBuffer>( scratch ), static_cast<VkDeviceSize>( scratchOffset ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::buildAccelerationStructureNV( const AccelerationStructureInfoNV & info, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdBuildAccelerationStructureNV( m_commandBuffer, reinterpret_cast<const VkAccelerationStructureInfoNV*>( &info ), static_cast<VkBuffer>( instanceData ), static_cast<VkDeviceSize>( instanceOffset ), static_cast<VkBool32>( update ), static_cast<VkAccelerationStructureNV>( dst ), static_cast<VkAccelerationStructureNV>( src ), static_cast<VkBuffer>( scratch ), static_cast<VkDeviceSize>( scratchOffset ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::clearAttachments( uint32_t attachmentCount, const VULKAN_HPP_NAMESPACE::ClearAttachment* pAttachments, uint32_t rectCount, const VULKAN_HPP_NAMESPACE::ClearRect* pRects, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdClearAttachments( m_commandBuffer, attachmentCount, reinterpret_cast<const VkClearAttachment*>( pAttachments ), rectCount, reinterpret_cast<const VkClearRect*>( pRects ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::clearAttachments( ArrayProxy<const VULKAN_HPP_NAMESPACE::ClearAttachment> attachments, ArrayProxy<const VULKAN_HPP_NAMESPACE::ClearRect> rects, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdClearAttachments( m_commandBuffer, attachments.size() , reinterpret_cast<const VkClearAttachment*>( attachments.data() ), rects.size() , reinterpret_cast<const VkClearRect*>( rects.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::clearColorImage( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, const VULKAN_HPP_NAMESPACE::ClearColorValue* pColor, uint32_t rangeCount, const VULKAN_HPP_NAMESPACE::ImageSubresourceRange* pRanges, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdClearColorImage( m_commandBuffer, static_cast<VkImage>( image ), static_cast<VkImageLayout>( imageLayout ), reinterpret_cast<const VkClearColorValue*>( pColor ), rangeCount, reinterpret_cast<const VkImageSubresourceRange*>( pRanges ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::clearColorImage( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, const ClearColorValue & color, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageSubresourceRange> ranges, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdClearColorImage( m_commandBuffer, static_cast<VkImage>( image ), static_cast<VkImageLayout>( imageLayout ), reinterpret_cast<const VkClearColorValue*>( &color ), ranges.size() , reinterpret_cast<const VkImageSubresourceRange*>( ranges.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::clearDepthStencilImage( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, const VULKAN_HPP_NAMESPACE::ClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VULKAN_HPP_NAMESPACE::ImageSubresourceRange* pRanges, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdClearDepthStencilImage( m_commandBuffer, static_cast<VkImage>( image ), static_cast<VkImageLayout>( imageLayout ), reinterpret_cast<const VkClearDepthStencilValue*>( pDepthStencil ), rangeCount, reinterpret_cast<const VkImageSubresourceRange*>( pRanges ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::clearDepthStencilImage( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, const ClearDepthStencilValue & depthStencil, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageSubresourceRange> ranges, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdClearDepthStencilImage( m_commandBuffer, static_cast<VkImage>( image ), static_cast<VkImageLayout>( imageLayout ), reinterpret_cast<const VkClearDepthStencilValue*>( &depthStencil ), ranges.size() , reinterpret_cast<const VkImageSubresourceRange*>( ranges.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeNV mode, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyAccelerationStructureNV( m_commandBuffer, static_cast<VkAccelerationStructureNV>( dst ), static_cast<VkAccelerationStructureNV>( src ), static_cast<VkCopyAccelerationStructureModeNV>( mode ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeNV mode, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyAccelerationStructureNV( m_commandBuffer, static_cast<VkAccelerationStructureNV>( dst ), static_cast<VkAccelerationStructureNV>( src ), static_cast<VkCopyAccelerationStructureModeNV>( mode ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyBuffer( VULKAN_HPP_NAMESPACE::Buffer srcBuffer, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::BufferCopy* pRegions, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyBuffer( m_commandBuffer, static_cast<VkBuffer>( srcBuffer ), static_cast<VkBuffer>( dstBuffer ), regionCount, reinterpret_cast<const VkBufferCopy*>( pRegions ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyBuffer( VULKAN_HPP_NAMESPACE::Buffer srcBuffer, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferCopy> regions, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyBuffer( m_commandBuffer, static_cast<VkBuffer>( srcBuffer ), static_cast<VkBuffer>( dstBuffer ), regions.size() , reinterpret_cast<const VkBufferCopy*>( regions.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyBufferToImage( VULKAN_HPP_NAMESPACE::Buffer srcBuffer, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::BufferImageCopy* pRegions, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyBufferToImage( m_commandBuffer, static_cast<VkBuffer>( srcBuffer ), static_cast<VkImage>( dstImage ), static_cast<VkImageLayout>( dstImageLayout ), regionCount, reinterpret_cast<const VkBufferImageCopy*>( pRegions ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyBufferToImage( VULKAN_HPP_NAMESPACE::Buffer srcBuffer, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferImageCopy> regions, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyBufferToImage( m_commandBuffer, static_cast<VkBuffer>( srcBuffer ), static_cast<VkImage>( dstImage ), static_cast<VkImageLayout>( dstImageLayout ), regions.size() , reinterpret_cast<const VkBufferImageCopy*>( regions.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::ImageCopy* pRegions, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyImage( m_commandBuffer, static_cast<VkImage>( srcImage ), static_cast<VkImageLayout>( srcImageLayout ), static_cast<VkImage>( dstImage ), static_cast<VkImageLayout>( dstImageLayout ), regionCount, reinterpret_cast<const VkImageCopy*>( pRegions ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageCopy> regions, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyImage( m_commandBuffer, static_cast<VkImage>( srcImage ), static_cast<VkImageLayout>( srcImageLayout ), static_cast<VkImage>( dstImage ), static_cast<VkImageLayout>( dstImageLayout ), regions.size() , reinterpret_cast<const VkImageCopy*>( regions.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyImageToBuffer( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::BufferImageCopy* pRegions, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyImageToBuffer( m_commandBuffer, static_cast<VkImage>( srcImage ), static_cast<VkImageLayout>( srcImageLayout ), static_cast<VkBuffer>( dstBuffer ), regionCount, reinterpret_cast<const VkBufferImageCopy*>( pRegions ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyImageToBuffer( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferImageCopy> regions, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyImageToBuffer( m_commandBuffer, static_cast<VkImage>( srcImage ), static_cast<VkImageLayout>( srcImageLayout ), static_cast<VkBuffer>( dstBuffer ), regions.size() , reinterpret_cast<const VkBufferImageCopy*>( regions.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyQueryPoolResults( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize stride, VULKAN_HPP_NAMESPACE::QueryResultFlags flags, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyQueryPoolResults( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount, static_cast<VkBuffer>( dstBuffer ), static_cast<VkDeviceSize>( dstOffset ), static_cast<VkDeviceSize>( stride ), static_cast<VkQueryResultFlags>( flags ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::copyQueryPoolResults( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize stride, VULKAN_HPP_NAMESPACE::QueryResultFlags flags, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdCopyQueryPoolResults( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount, static_cast<VkBuffer>( dstBuffer ), static_cast<VkDeviceSize>( dstOffset ), static_cast<VkDeviceSize>( stride ), static_cast<VkQueryResultFlags>( flags ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::debugMarkerBeginEXT( const VULKAN_HPP_NAMESPACE::DebugMarkerMarkerInfoEXT* pMarkerInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDebugMarkerBeginEXT( m_commandBuffer, reinterpret_cast<const VkDebugMarkerMarkerInfoEXT*>( pMarkerInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::debugMarkerBeginEXT( const DebugMarkerMarkerInfoEXT & markerInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDebugMarkerBeginEXT( m_commandBuffer, reinterpret_cast<const VkDebugMarkerMarkerInfoEXT*>( &markerInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::debugMarkerEndEXT(Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDebugMarkerEndEXT( m_commandBuffer );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::debugMarkerEndEXT(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDebugMarkerEndEXT( m_commandBuffer );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::debugMarkerInsertEXT( const VULKAN_HPP_NAMESPACE::DebugMarkerMarkerInfoEXT* pMarkerInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDebugMarkerInsertEXT( m_commandBuffer, reinterpret_cast<const VkDebugMarkerMarkerInfoEXT*>( pMarkerInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::debugMarkerInsertEXT( const DebugMarkerMarkerInfoEXT & markerInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDebugMarkerInsertEXT( m_commandBuffer, reinterpret_cast<const VkDebugMarkerMarkerInfoEXT*>( &markerInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::dispatch( uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDispatch( m_commandBuffer, groupCountX, groupCountY, groupCountZ );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::dispatch( uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDispatch( m_commandBuffer, groupCountX, groupCountY, groupCountZ );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::dispatchBase( uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDispatchBase( m_commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::dispatchBase( uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDispatchBase( m_commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::dispatchBaseKHR( uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDispatchBaseKHR( m_commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::dispatchBaseKHR( uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDispatchBaseKHR( m_commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::dispatchIndirect( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDispatchIndirect( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::dispatchIndirect( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDispatchIndirect( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::draw( uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDraw( m_commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::draw( uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDraw( m_commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndexed( uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndexed( m_commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndexed( uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndexed( m_commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirect( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, uint32_t drawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndexedIndirect( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), drawCount, stride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirect( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, uint32_t drawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndexedIndirect( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), drawCount, stride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirectCount( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndexedIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirectCount( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndexedIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirectCountAMD( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndexedIndirectCountAMD( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirectCountAMD( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndexedIndirectCountAMD( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirectCountKHR( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndexedIndirectCountKHR( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirectCountKHR( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndexedIndirectCountKHR( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndirect( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, uint32_t drawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndirect( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), drawCount, stride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndirect( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, uint32_t drawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndirect( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), drawCount, stride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndirectByteCountEXT( uint32_t instanceCount, uint32_t firstInstance, VULKAN_HPP_NAMESPACE::Buffer counterBuffer, VULKAN_HPP_NAMESPACE::DeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndirectByteCountEXT( m_commandBuffer, instanceCount, firstInstance, static_cast<VkBuffer>( counterBuffer ), static_cast<VkDeviceSize>( counterBufferOffset ), counterOffset, vertexStride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndirectByteCountEXT( uint32_t instanceCount, uint32_t firstInstance, VULKAN_HPP_NAMESPACE::Buffer counterBuffer, VULKAN_HPP_NAMESPACE::DeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndirectByteCountEXT( m_commandBuffer, instanceCount, firstInstance, static_cast<VkBuffer>( counterBuffer ), static_cast<VkDeviceSize>( counterBufferOffset ), counterOffset, vertexStride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndirectCount( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndirectCount( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndirectCountAMD( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndirectCountAMD( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndirectCountAMD( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndirectCountAMD( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndirectCountKHR( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndirectCountKHR( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawIndirectCountKHR( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawIndirectCountKHR( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawMeshTasksIndirectCountNV( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawMeshTasksIndirectCountNV( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawMeshTasksIndirectCountNV( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawMeshTasksIndirectCountNV( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawMeshTasksIndirectNV( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, uint32_t drawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawMeshTasksIndirectNV( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), drawCount, stride );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawMeshTasksIndirectNV( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, uint32_t drawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawMeshTasksIndirectNV( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), drawCount, stride );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawMeshTasksNV( uint32_t taskCount, uint32_t firstTask, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawMeshTasksNV( m_commandBuffer, taskCount, firstTask );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::drawMeshTasksNV( uint32_t taskCount, uint32_t firstTask, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdDrawMeshTasksNV( m_commandBuffer, taskCount, firstTask );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endConditionalRenderingEXT(Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndConditionalRenderingEXT( m_commandBuffer );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endConditionalRenderingEXT(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndConditionalRenderingEXT( m_commandBuffer );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endDebugUtilsLabelEXT(Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndDebugUtilsLabelEXT( m_commandBuffer );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endDebugUtilsLabelEXT(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndDebugUtilsLabelEXT( m_commandBuffer );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endQuery( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndQuery( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), query );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endQuery( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndQuery( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), query );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endQueryIndexedEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, uint32_t index, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndQueryIndexedEXT( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), query, index );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endQueryIndexedEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, uint32_t index, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndQueryIndexedEXT( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), query, index );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endRenderPass(Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndRenderPass( m_commandBuffer );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endRenderPass(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndRenderPass( m_commandBuffer );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endRenderPass2( const VULKAN_HPP_NAMESPACE::SubpassEndInfo* pSubpassEndInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndRenderPass2( m_commandBuffer, reinterpret_cast<const VkSubpassEndInfo*>( pSubpassEndInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endRenderPass2( const SubpassEndInfo & subpassEndInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndRenderPass2( m_commandBuffer, reinterpret_cast<const VkSubpassEndInfo*>( &subpassEndInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endRenderPass2KHR( const VULKAN_HPP_NAMESPACE::SubpassEndInfo* pSubpassEndInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndRenderPass2KHR( m_commandBuffer, reinterpret_cast<const VkSubpassEndInfo*>( pSubpassEndInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endRenderPass2KHR( const SubpassEndInfo & subpassEndInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndRenderPass2KHR( m_commandBuffer, reinterpret_cast<const VkSubpassEndInfo*>( &subpassEndInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endTransformFeedbackEXT( uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VULKAN_HPP_NAMESPACE::Buffer* pCounterBuffers, const VULKAN_HPP_NAMESPACE::DeviceSize* pCounterBufferOffsets, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdEndTransformFeedbackEXT( m_commandBuffer, firstCounterBuffer, counterBufferCount, reinterpret_cast<const VkBuffer*>( pCounterBuffers ), reinterpret_cast<const VkDeviceSize*>( pCounterBufferOffsets ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::endTransformFeedbackEXT( uint32_t firstCounterBuffer, ArrayProxy<const VULKAN_HPP_NAMESPACE::Buffer> counterBuffers, ArrayProxy<const VULKAN_HPP_NAMESPACE::DeviceSize> counterBufferOffsets, Dispatch const &d ) const
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( counterBuffers.size() == counterBufferOffsets.size() );
+#else
+ if ( counterBuffers.size() != counterBufferOffsets.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkCommandBuffer::endTransformFeedbackEXT: counterBuffers.size() != counterBufferOffsets.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+ d.vkCmdEndTransformFeedbackEXT( m_commandBuffer, firstCounterBuffer, counterBuffers.size() , reinterpret_cast<const VkBuffer*>( counterBuffers.data() ), reinterpret_cast<const VkDeviceSize*>( counterBufferOffsets.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::executeCommands( uint32_t commandBufferCount, const VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdExecuteCommands( m_commandBuffer, commandBufferCount, reinterpret_cast<const VkCommandBuffer*>( pCommandBuffers ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::executeCommands( ArrayProxy<const VULKAN_HPP_NAMESPACE::CommandBuffer> commandBuffers, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdExecuteCommands( m_commandBuffer, commandBuffers.size() , reinterpret_cast<const VkCommandBuffer*>( commandBuffers.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::fillBuffer( VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize size, uint32_t data, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdFillBuffer( m_commandBuffer, static_cast<VkBuffer>( dstBuffer ), static_cast<VkDeviceSize>( dstOffset ), static_cast<VkDeviceSize>( size ), data );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::fillBuffer( VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize size, uint32_t data, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdFillBuffer( m_commandBuffer, static_cast<VkBuffer>( dstBuffer ), static_cast<VkDeviceSize>( dstOffset ), static_cast<VkDeviceSize>( size ), data );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::insertDebugUtilsLabelEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pLabelInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdInsertDebugUtilsLabelEXT( m_commandBuffer, reinterpret_cast<const VkDebugUtilsLabelEXT*>( pLabelInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::insertDebugUtilsLabelEXT( const DebugUtilsLabelEXT & labelInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdInsertDebugUtilsLabelEXT( m_commandBuffer, reinterpret_cast<const VkDebugUtilsLabelEXT*>( &labelInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::nextSubpass( VULKAN_HPP_NAMESPACE::SubpassContents contents, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdNextSubpass( m_commandBuffer, static_cast<VkSubpassContents>( contents ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::nextSubpass( VULKAN_HPP_NAMESPACE::SubpassContents contents, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdNextSubpass( m_commandBuffer, static_cast<VkSubpassContents>( contents ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::nextSubpass2( const VULKAN_HPP_NAMESPACE::SubpassBeginInfo* pSubpassBeginInfo, const VULKAN_HPP_NAMESPACE::SubpassEndInfo* pSubpassEndInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdNextSubpass2( m_commandBuffer, reinterpret_cast<const VkSubpassBeginInfo*>( pSubpassBeginInfo ), reinterpret_cast<const VkSubpassEndInfo*>( pSubpassEndInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::nextSubpass2( const SubpassBeginInfo & subpassBeginInfo, const SubpassEndInfo & subpassEndInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdNextSubpass2( m_commandBuffer, reinterpret_cast<const VkSubpassBeginInfo*>( &subpassBeginInfo ), reinterpret_cast<const VkSubpassEndInfo*>( &subpassEndInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::nextSubpass2KHR( const VULKAN_HPP_NAMESPACE::SubpassBeginInfo* pSubpassBeginInfo, const VULKAN_HPP_NAMESPACE::SubpassEndInfo* pSubpassEndInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdNextSubpass2KHR( m_commandBuffer, reinterpret_cast<const VkSubpassBeginInfo*>( pSubpassBeginInfo ), reinterpret_cast<const VkSubpassEndInfo*>( pSubpassEndInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::nextSubpass2KHR( const SubpassBeginInfo & subpassBeginInfo, const SubpassEndInfo & subpassEndInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdNextSubpass2KHR( m_commandBuffer, reinterpret_cast<const VkSubpassBeginInfo*>( &subpassBeginInfo ), reinterpret_cast<const VkSubpassEndInfo*>( &subpassEndInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::pipelineBarrier( VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask, VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask, VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VULKAN_HPP_NAMESPACE::MemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VULKAN_HPP_NAMESPACE::BufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VULKAN_HPP_NAMESPACE::ImageMemoryBarrier* pImageMemoryBarriers, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdPipelineBarrier( m_commandBuffer, static_cast<VkPipelineStageFlags>( srcStageMask ), static_cast<VkPipelineStageFlags>( dstStageMask ), static_cast<VkDependencyFlags>( dependencyFlags ), memoryBarrierCount, reinterpret_cast<const VkMemoryBarrier*>( pMemoryBarriers ), bufferMemoryBarrierCount, reinterpret_cast<const VkBufferMemoryBarrier*>( pBufferMemoryBarriers ), imageMemoryBarrierCount, reinterpret_cast<const VkImageMemoryBarrier*>( pImageMemoryBarriers ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::pipelineBarrier( VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask, VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask, VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags, ArrayProxy<const VULKAN_HPP_NAMESPACE::MemoryBarrier> memoryBarriers, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferMemoryBarrier> bufferMemoryBarriers, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageMemoryBarrier> imageMemoryBarriers, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdPipelineBarrier( m_commandBuffer, static_cast<VkPipelineStageFlags>( srcStageMask ), static_cast<VkPipelineStageFlags>( dstStageMask ), static_cast<VkDependencyFlags>( dependencyFlags ), memoryBarriers.size() , reinterpret_cast<const VkMemoryBarrier*>( memoryBarriers.data() ), bufferMemoryBarriers.size() , reinterpret_cast<const VkBufferMemoryBarrier*>( bufferMemoryBarriers.data() ), imageMemoryBarriers.size() , reinterpret_cast<const VkImageMemoryBarrier*>( imageMemoryBarriers.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::processCommandsNVX( const VULKAN_HPP_NAMESPACE::CmdProcessCommandsInfoNVX* pProcessCommandsInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdProcessCommandsNVX( m_commandBuffer, reinterpret_cast<const VkCmdProcessCommandsInfoNVX*>( pProcessCommandsInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::processCommandsNVX( const CmdProcessCommandsInfoNVX & processCommandsInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdProcessCommandsNVX( m_commandBuffer, reinterpret_cast<const VkCmdProcessCommandsInfoNVX*>( &processCommandsInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::pushConstants( VULKAN_HPP_NAMESPACE::PipelineLayout layout, VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdPushConstants( m_commandBuffer, static_cast<VkPipelineLayout>( layout ), static_cast<VkShaderStageFlags>( stageFlags ), offset, size, pValues );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename T, typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::pushConstants( VULKAN_HPP_NAMESPACE::PipelineLayout layout, VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags, uint32_t offset, ArrayProxy<const T> values, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdPushConstants( m_commandBuffer, static_cast<VkPipelineLayout>( layout ), static_cast<VkShaderStageFlags>( stageFlags ), offset, values.size() * sizeof( T ) , reinterpret_cast<const void*>( values.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::pushDescriptorSetKHR( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VULKAN_HPP_NAMESPACE::WriteDescriptorSet* pDescriptorWrites, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdPushDescriptorSetKHR( m_commandBuffer, static_cast<VkPipelineBindPoint>( pipelineBindPoint ), static_cast<VkPipelineLayout>( layout ), set, descriptorWriteCount, reinterpret_cast<const VkWriteDescriptorSet*>( pDescriptorWrites ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::pushDescriptorSetKHR( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t set, ArrayProxy<const VULKAN_HPP_NAMESPACE::WriteDescriptorSet> descriptorWrites, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdPushDescriptorSetKHR( m_commandBuffer, static_cast<VkPipelineBindPoint>( pipelineBindPoint ), static_cast<VkPipelineLayout>( layout ), set, descriptorWrites.size() , reinterpret_cast<const VkWriteDescriptorSet*>( descriptorWrites.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::pushDescriptorSetWithTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t set, const void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdPushDescriptorSetWithTemplateKHR( m_commandBuffer, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), static_cast<VkPipelineLayout>( layout ), set, pData );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::pushDescriptorSetWithTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t set, const void* pData, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdPushDescriptorSetWithTemplateKHR( m_commandBuffer, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), static_cast<VkPipelineLayout>( layout ), set, pData );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::reserveSpaceForCommandsNVX( const VULKAN_HPP_NAMESPACE::CmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdReserveSpaceForCommandsNVX( m_commandBuffer, reinterpret_cast<const VkCmdReserveSpaceForCommandsInfoNVX*>( pReserveSpaceInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::reserveSpaceForCommandsNVX( const CmdReserveSpaceForCommandsInfoNVX & reserveSpaceInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdReserveSpaceForCommandsNVX( m_commandBuffer, reinterpret_cast<const VkCmdReserveSpaceForCommandsInfoNVX*>( &reserveSpaceInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::resetEvent( VULKAN_HPP_NAMESPACE::Event event, VULKAN_HPP_NAMESPACE::PipelineStageFlags stageMask, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdResetEvent( m_commandBuffer, static_cast<VkEvent>( event ), static_cast<VkPipelineStageFlags>( stageMask ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::resetEvent( VULKAN_HPP_NAMESPACE::Event event, VULKAN_HPP_NAMESPACE::PipelineStageFlags stageMask, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdResetEvent( m_commandBuffer, static_cast<VkEvent>( event ), static_cast<VkPipelineStageFlags>( stageMask ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::resetQueryPool( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdResetQueryPool( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::resetQueryPool( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdResetQueryPool( m_commandBuffer, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::resolveImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::ImageResolve* pRegions, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdResolveImage( m_commandBuffer, static_cast<VkImage>( srcImage ), static_cast<VkImageLayout>( srcImageLayout ), static_cast<VkImage>( dstImage ), static_cast<VkImageLayout>( dstImageLayout ), regionCount, reinterpret_cast<const VkImageResolve*>( pRegions ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::resolveImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageResolve> regions, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdResolveImage( m_commandBuffer, static_cast<VkImage>( srcImage ), static_cast<VkImageLayout>( srcImageLayout ), static_cast<VkImage>( dstImage ), static_cast<VkImageLayout>( dstImageLayout ), regions.size() , reinterpret_cast<const VkImageResolve*>( regions.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setBlendConstants( const float blendConstants[4], Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetBlendConstants( m_commandBuffer, blendConstants );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setBlendConstants( const float blendConstants[4], Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetBlendConstants( m_commandBuffer, blendConstants );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setCheckpointNV( const void* pCheckpointMarker, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetCheckpointNV( m_commandBuffer, pCheckpointMarker );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setCheckpointNV( const void* pCheckpointMarker, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetCheckpointNV( m_commandBuffer, pCheckpointMarker );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setCoarseSampleOrderNV( VULKAN_HPP_NAMESPACE::CoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VULKAN_HPP_NAMESPACE::CoarseSampleOrderCustomNV* pCustomSampleOrders, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetCoarseSampleOrderNV( m_commandBuffer, static_cast<VkCoarseSampleOrderTypeNV>( sampleOrderType ), customSampleOrderCount, reinterpret_cast<const VkCoarseSampleOrderCustomNV*>( pCustomSampleOrders ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setCoarseSampleOrderNV( VULKAN_HPP_NAMESPACE::CoarseSampleOrderTypeNV sampleOrderType, ArrayProxy<const VULKAN_HPP_NAMESPACE::CoarseSampleOrderCustomNV> customSampleOrders, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetCoarseSampleOrderNV( m_commandBuffer, static_cast<VkCoarseSampleOrderTypeNV>( sampleOrderType ), customSampleOrders.size() , reinterpret_cast<const VkCoarseSampleOrderCustomNV*>( customSampleOrders.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setDepthBias( float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetDepthBias( m_commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setDepthBias( float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetDepthBias( m_commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setDepthBounds( float minDepthBounds, float maxDepthBounds, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetDepthBounds( m_commandBuffer, minDepthBounds, maxDepthBounds );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setDepthBounds( float minDepthBounds, float maxDepthBounds, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetDepthBounds( m_commandBuffer, minDepthBounds, maxDepthBounds );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setDeviceMask( uint32_t deviceMask, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetDeviceMask( m_commandBuffer, deviceMask );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setDeviceMask( uint32_t deviceMask, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetDeviceMask( m_commandBuffer, deviceMask );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setDeviceMaskKHR( uint32_t deviceMask, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetDeviceMaskKHR( m_commandBuffer, deviceMask );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setDeviceMaskKHR( uint32_t deviceMask, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetDeviceMaskKHR( m_commandBuffer, deviceMask );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setDiscardRectangleEXT( uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VULKAN_HPP_NAMESPACE::Rect2D* pDiscardRectangles, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetDiscardRectangleEXT( m_commandBuffer, firstDiscardRectangle, discardRectangleCount, reinterpret_cast<const VkRect2D*>( pDiscardRectangles ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setDiscardRectangleEXT( uint32_t firstDiscardRectangle, ArrayProxy<const VULKAN_HPP_NAMESPACE::Rect2D> discardRectangles, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetDiscardRectangleEXT( m_commandBuffer, firstDiscardRectangle, discardRectangles.size() , reinterpret_cast<const VkRect2D*>( discardRectangles.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setEvent( VULKAN_HPP_NAMESPACE::Event event, VULKAN_HPP_NAMESPACE::PipelineStageFlags stageMask, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetEvent( m_commandBuffer, static_cast<VkEvent>( event ), static_cast<VkPipelineStageFlags>( stageMask ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setEvent( VULKAN_HPP_NAMESPACE::Event event, VULKAN_HPP_NAMESPACE::PipelineStageFlags stageMask, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetEvent( m_commandBuffer, static_cast<VkEvent>( event ), static_cast<VkPipelineStageFlags>( stageMask ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setExclusiveScissorNV( uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VULKAN_HPP_NAMESPACE::Rect2D* pExclusiveScissors, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetExclusiveScissorNV( m_commandBuffer, firstExclusiveScissor, exclusiveScissorCount, reinterpret_cast<const VkRect2D*>( pExclusiveScissors ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setExclusiveScissorNV( uint32_t firstExclusiveScissor, ArrayProxy<const VULKAN_HPP_NAMESPACE::Rect2D> exclusiveScissors, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetExclusiveScissorNV( m_commandBuffer, firstExclusiveScissor, exclusiveScissors.size() , reinterpret_cast<const VkRect2D*>( exclusiveScissors.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setLineStippleEXT( uint32_t lineStippleFactor, uint16_t lineStipplePattern, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetLineStippleEXT( m_commandBuffer, lineStippleFactor, lineStipplePattern );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setLineStippleEXT( uint32_t lineStippleFactor, uint16_t lineStipplePattern, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetLineStippleEXT( m_commandBuffer, lineStippleFactor, lineStipplePattern );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setLineWidth( float lineWidth, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetLineWidth( m_commandBuffer, lineWidth );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setLineWidth( float lineWidth, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetLineWidth( m_commandBuffer, lineWidth );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result CommandBuffer::setPerformanceMarkerINTEL( const VULKAN_HPP_NAMESPACE::PerformanceMarkerInfoINTEL* pMarkerInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCmdSetPerformanceMarkerINTEL( m_commandBuffer, reinterpret_cast<const VkPerformanceMarkerInfoINTEL*>( pMarkerInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type CommandBuffer::setPerformanceMarkerINTEL( const PerformanceMarkerInfoINTEL & markerInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkCmdSetPerformanceMarkerINTEL( m_commandBuffer, reinterpret_cast<const VkPerformanceMarkerInfoINTEL*>( &markerInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::CommandBuffer::setPerformanceMarkerINTEL" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result CommandBuffer::setPerformanceOverrideINTEL( const VULKAN_HPP_NAMESPACE::PerformanceOverrideInfoINTEL* pOverrideInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCmdSetPerformanceOverrideINTEL( m_commandBuffer, reinterpret_cast<const VkPerformanceOverrideInfoINTEL*>( pOverrideInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type CommandBuffer::setPerformanceOverrideINTEL( const PerformanceOverrideInfoINTEL & overrideInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkCmdSetPerformanceOverrideINTEL( m_commandBuffer, reinterpret_cast<const VkPerformanceOverrideInfoINTEL*>( &overrideInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::CommandBuffer::setPerformanceOverrideINTEL" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result CommandBuffer::setPerformanceStreamMarkerINTEL( const VULKAN_HPP_NAMESPACE::PerformanceStreamMarkerInfoINTEL* pMarkerInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCmdSetPerformanceStreamMarkerINTEL( m_commandBuffer, reinterpret_cast<const VkPerformanceStreamMarkerInfoINTEL*>( pMarkerInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type CommandBuffer::setPerformanceStreamMarkerINTEL( const PerformanceStreamMarkerInfoINTEL & markerInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkCmdSetPerformanceStreamMarkerINTEL( m_commandBuffer, reinterpret_cast<const VkPerformanceStreamMarkerInfoINTEL*>( &markerInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::CommandBuffer::setPerformanceStreamMarkerINTEL" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setSampleLocationsEXT( const VULKAN_HPP_NAMESPACE::SampleLocationsInfoEXT* pSampleLocationsInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetSampleLocationsEXT( m_commandBuffer, reinterpret_cast<const VkSampleLocationsInfoEXT*>( pSampleLocationsInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setSampleLocationsEXT( const SampleLocationsInfoEXT & sampleLocationsInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetSampleLocationsEXT( m_commandBuffer, reinterpret_cast<const VkSampleLocationsInfoEXT*>( &sampleLocationsInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setScissor( uint32_t firstScissor, uint32_t scissorCount, const VULKAN_HPP_NAMESPACE::Rect2D* pScissors, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetScissor( m_commandBuffer, firstScissor, scissorCount, reinterpret_cast<const VkRect2D*>( pScissors ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setScissor( uint32_t firstScissor, ArrayProxy<const VULKAN_HPP_NAMESPACE::Rect2D> scissors, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetScissor( m_commandBuffer, firstScissor, scissors.size() , reinterpret_cast<const VkRect2D*>( scissors.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setStencilCompareMask( VULKAN_HPP_NAMESPACE::StencilFaceFlags faceMask, uint32_t compareMask, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetStencilCompareMask( m_commandBuffer, static_cast<VkStencilFaceFlags>( faceMask ), compareMask );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setStencilCompareMask( VULKAN_HPP_NAMESPACE::StencilFaceFlags faceMask, uint32_t compareMask, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetStencilCompareMask( m_commandBuffer, static_cast<VkStencilFaceFlags>( faceMask ), compareMask );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setStencilReference( VULKAN_HPP_NAMESPACE::StencilFaceFlags faceMask, uint32_t reference, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetStencilReference( m_commandBuffer, static_cast<VkStencilFaceFlags>( faceMask ), reference );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setStencilReference( VULKAN_HPP_NAMESPACE::StencilFaceFlags faceMask, uint32_t reference, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetStencilReference( m_commandBuffer, static_cast<VkStencilFaceFlags>( faceMask ), reference );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setStencilWriteMask( VULKAN_HPP_NAMESPACE::StencilFaceFlags faceMask, uint32_t writeMask, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetStencilWriteMask( m_commandBuffer, static_cast<VkStencilFaceFlags>( faceMask ), writeMask );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setStencilWriteMask( VULKAN_HPP_NAMESPACE::StencilFaceFlags faceMask, uint32_t writeMask, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetStencilWriteMask( m_commandBuffer, static_cast<VkStencilFaceFlags>( faceMask ), writeMask );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setViewport( uint32_t firstViewport, uint32_t viewportCount, const VULKAN_HPP_NAMESPACE::Viewport* pViewports, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetViewport( m_commandBuffer, firstViewport, viewportCount, reinterpret_cast<const VkViewport*>( pViewports ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setViewport( uint32_t firstViewport, ArrayProxy<const VULKAN_HPP_NAMESPACE::Viewport> viewports, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetViewport( m_commandBuffer, firstViewport, viewports.size() , reinterpret_cast<const VkViewport*>( viewports.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setViewportShadingRatePaletteNV( uint32_t firstViewport, uint32_t viewportCount, const VULKAN_HPP_NAMESPACE::ShadingRatePaletteNV* pShadingRatePalettes, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetViewportShadingRatePaletteNV( m_commandBuffer, firstViewport, viewportCount, reinterpret_cast<const VkShadingRatePaletteNV*>( pShadingRatePalettes ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setViewportShadingRatePaletteNV( uint32_t firstViewport, ArrayProxy<const VULKAN_HPP_NAMESPACE::ShadingRatePaletteNV> shadingRatePalettes, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetViewportShadingRatePaletteNV( m_commandBuffer, firstViewport, shadingRatePalettes.size() , reinterpret_cast<const VkShadingRatePaletteNV*>( shadingRatePalettes.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setViewportWScalingNV( uint32_t firstViewport, uint32_t viewportCount, const VULKAN_HPP_NAMESPACE::ViewportWScalingNV* pViewportWScalings, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetViewportWScalingNV( m_commandBuffer, firstViewport, viewportCount, reinterpret_cast<const VkViewportWScalingNV*>( pViewportWScalings ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::setViewportWScalingNV( uint32_t firstViewport, ArrayProxy<const VULKAN_HPP_NAMESPACE::ViewportWScalingNV> viewportWScalings, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdSetViewportWScalingNV( m_commandBuffer, firstViewport, viewportWScalings.size() , reinterpret_cast<const VkViewportWScalingNV*>( viewportWScalings.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::traceRaysNV( VULKAN_HPP_NAMESPACE::Buffer raygenShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize raygenShaderBindingOffset, VULKAN_HPP_NAMESPACE::Buffer missShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize missShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize missShaderBindingStride, VULKAN_HPP_NAMESPACE::Buffer hitShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize hitShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize hitShaderBindingStride, VULKAN_HPP_NAMESPACE::Buffer callableShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize callableShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdTraceRaysNV( m_commandBuffer, static_cast<VkBuffer>( raygenShaderBindingTableBuffer ), static_cast<VkDeviceSize>( raygenShaderBindingOffset ), static_cast<VkBuffer>( missShaderBindingTableBuffer ), static_cast<VkDeviceSize>( missShaderBindingOffset ), static_cast<VkDeviceSize>( missShaderBindingStride ), static_cast<VkBuffer>( hitShaderBindingTableBuffer ), static_cast<VkDeviceSize>( hitShaderBindingOffset ), static_cast<VkDeviceSize>( hitShaderBindingStride ), static_cast<VkBuffer>( callableShaderBindingTableBuffer ), static_cast<VkDeviceSize>( callableShaderBindingOffset ), static_cast<VkDeviceSize>( callableShaderBindingStride ), width, height, depth );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::traceRaysNV( VULKAN_HPP_NAMESPACE::Buffer raygenShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize raygenShaderBindingOffset, VULKAN_HPP_NAMESPACE::Buffer missShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize missShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize missShaderBindingStride, VULKAN_HPP_NAMESPACE::Buffer hitShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize hitShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize hitShaderBindingStride, VULKAN_HPP_NAMESPACE::Buffer callableShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize callableShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdTraceRaysNV( m_commandBuffer, static_cast<VkBuffer>( raygenShaderBindingTableBuffer ), static_cast<VkDeviceSize>( raygenShaderBindingOffset ), static_cast<VkBuffer>( missShaderBindingTableBuffer ), static_cast<VkDeviceSize>( missShaderBindingOffset ), static_cast<VkDeviceSize>( missShaderBindingStride ), static_cast<VkBuffer>( hitShaderBindingTableBuffer ), static_cast<VkDeviceSize>( hitShaderBindingOffset ), static_cast<VkDeviceSize>( hitShaderBindingStride ), static_cast<VkBuffer>( callableShaderBindingTableBuffer ), static_cast<VkDeviceSize>( callableShaderBindingOffset ), static_cast<VkDeviceSize>( callableShaderBindingStride ), width, height, depth );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::updateBuffer( VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize dataSize, const void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdUpdateBuffer( m_commandBuffer, static_cast<VkBuffer>( dstBuffer ), static_cast<VkDeviceSize>( dstOffset ), static_cast<VkDeviceSize>( dataSize ), pData );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename T, typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::updateBuffer( VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, ArrayProxy<const T> data, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdUpdateBuffer( m_commandBuffer, static_cast<VkBuffer>( dstBuffer ), static_cast<VkDeviceSize>( dstOffset ), data.size() * sizeof( T ) , reinterpret_cast<const void*>( data.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::waitEvents( uint32_t eventCount, const VULKAN_HPP_NAMESPACE::Event* pEvents, VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask, VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VULKAN_HPP_NAMESPACE::MemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VULKAN_HPP_NAMESPACE::BufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VULKAN_HPP_NAMESPACE::ImageMemoryBarrier* pImageMemoryBarriers, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdWaitEvents( m_commandBuffer, eventCount, reinterpret_cast<const VkEvent*>( pEvents ), static_cast<VkPipelineStageFlags>( srcStageMask ), static_cast<VkPipelineStageFlags>( dstStageMask ), memoryBarrierCount, reinterpret_cast<const VkMemoryBarrier*>( pMemoryBarriers ), bufferMemoryBarrierCount, reinterpret_cast<const VkBufferMemoryBarrier*>( pBufferMemoryBarriers ), imageMemoryBarrierCount, reinterpret_cast<const VkImageMemoryBarrier*>( pImageMemoryBarriers ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::waitEvents( ArrayProxy<const VULKAN_HPP_NAMESPACE::Event> events, VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask, VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask, ArrayProxy<const VULKAN_HPP_NAMESPACE::MemoryBarrier> memoryBarriers, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferMemoryBarrier> bufferMemoryBarriers, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageMemoryBarrier> imageMemoryBarriers, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdWaitEvents( m_commandBuffer, events.size() , reinterpret_cast<const VkEvent*>( events.data() ), static_cast<VkPipelineStageFlags>( srcStageMask ), static_cast<VkPipelineStageFlags>( dstStageMask ), memoryBarriers.size() , reinterpret_cast<const VkMemoryBarrier*>( memoryBarriers.data() ), bufferMemoryBarriers.size() , reinterpret_cast<const VkBufferMemoryBarrier*>( bufferMemoryBarriers.data() ), imageMemoryBarriers.size() , reinterpret_cast<const VkImageMemoryBarrier*>( imageMemoryBarriers.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::writeAccelerationStructuresPropertiesNV( uint32_t accelerationStructureCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdWriteAccelerationStructuresPropertiesNV( m_commandBuffer, accelerationStructureCount, reinterpret_cast<const VkAccelerationStructureNV*>( pAccelerationStructures ), static_cast<VkQueryType>( queryType ), static_cast<VkQueryPool>( queryPool ), firstQuery );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::writeAccelerationStructuresPropertiesNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureNV> accelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdWriteAccelerationStructuresPropertiesNV( m_commandBuffer, accelerationStructures.size() , reinterpret_cast<const VkAccelerationStructureNV*>( accelerationStructures.data() ), static_cast<VkQueryType>( queryType ), static_cast<VkQueryPool>( queryPool ), firstQuery );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::writeBufferMarkerAMD( VULKAN_HPP_NAMESPACE::PipelineStageFlagBits pipelineStage, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, uint32_t marker, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdWriteBufferMarkerAMD( m_commandBuffer, static_cast<VkPipelineStageFlagBits>( pipelineStage ), static_cast<VkBuffer>( dstBuffer ), static_cast<VkDeviceSize>( dstOffset ), marker );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::writeBufferMarkerAMD( VULKAN_HPP_NAMESPACE::PipelineStageFlagBits pipelineStage, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, uint32_t marker, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdWriteBufferMarkerAMD( m_commandBuffer, static_cast<VkPipelineStageFlagBits>( pipelineStage ), static_cast<VkBuffer>( dstBuffer ), static_cast<VkDeviceSize>( dstOffset ), marker );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::writeTimestamp( VULKAN_HPP_NAMESPACE::PipelineStageFlagBits pipelineStage, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdWriteTimestamp( m_commandBuffer, static_cast<VkPipelineStageFlagBits>( pipelineStage ), static_cast<VkQueryPool>( queryPool ), query );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void CommandBuffer::writeTimestamp( VULKAN_HPP_NAMESPACE::PipelineStageFlagBits pipelineStage, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t query, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkCmdWriteTimestamp( m_commandBuffer, static_cast<VkPipelineStageFlagBits>( pipelineStage ), static_cast<VkQueryPool>( queryPool ), query );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result CommandBuffer::end(Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkEndCommandBuffer( m_commandBuffer ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type CommandBuffer::end(Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkEndCommandBuffer( m_commandBuffer ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::CommandBuffer::end" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result CommandBuffer::reset( VULKAN_HPP_NAMESPACE::CommandBufferResetFlags flags, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkResetCommandBuffer( m_commandBuffer, static_cast<VkCommandBufferResetFlags>( flags ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type CommandBuffer::reset( VULKAN_HPP_NAMESPACE::CommandBufferResetFlags flags, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkResetCommandBuffer( m_commandBuffer, static_cast<VkCommandBufferResetFlags>( flags ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::CommandBuffer::reset" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::acquireFullScreenExclusiveModeEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkAcquireFullScreenExclusiveModeEXT( m_device, static_cast<VkSwapchainKHR>( swapchain ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::acquireFullScreenExclusiveModeEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkAcquireFullScreenExclusiveModeEXT( m_device, static_cast<VkSwapchainKHR>( swapchain ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::acquireFullScreenExclusiveModeEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::acquireNextImage2KHR( const VULKAN_HPP_NAMESPACE::AcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkAcquireNextImage2KHR( m_device, reinterpret_cast<const VkAcquireNextImageInfoKHR*>( pAcquireInfo ), pImageIndex ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE ResultValue<uint32_t> Device::acquireNextImage2KHR( const AcquireNextImageInfoKHR & acquireInfo, Dispatch const &d ) const
+ {
+ uint32_t imageIndex;
+ Result result = static_cast<Result>( d.vkAcquireNextImage2KHR( m_device, reinterpret_cast<const VkAcquireNextImageInfoKHR*>( &acquireInfo ), &imageIndex ) );
+ return createResultValue( result, imageIndex, VULKAN_HPP_NAMESPACE_STRING"::Device::acquireNextImage2KHR", { Result::eSuccess, Result::eTimeout, Result::eNotReady, Result::eSuboptimalKHR } );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::acquireNextImageKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, uint64_t timeout, VULKAN_HPP_NAMESPACE::Semaphore semaphore, VULKAN_HPP_NAMESPACE::Fence fence, uint32_t* pImageIndex, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkAcquireNextImageKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), timeout, static_cast<VkSemaphore>( semaphore ), static_cast<VkFence>( fence ), pImageIndex ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE ResultValue<uint32_t> Device::acquireNextImageKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, uint64_t timeout, VULKAN_HPP_NAMESPACE::Semaphore semaphore, VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d ) const
+ {
+ uint32_t imageIndex;
+ Result result = static_cast<Result>( d.vkAcquireNextImageKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), timeout, static_cast<VkSemaphore>( semaphore ), static_cast<VkFence>( fence ), &imageIndex ) );
+ return createResultValue( result, imageIndex, VULKAN_HPP_NAMESPACE_STRING"::Device::acquireNextImageKHR", { Result::eSuccess, Result::eTimeout, Result::eNotReady, Result::eSuboptimalKHR } );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::acquirePerformanceConfigurationINTEL( const VULKAN_HPP_NAMESPACE::PerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL* pConfiguration, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkAcquirePerformanceConfigurationINTEL( m_device, reinterpret_cast<const VkPerformanceConfigurationAcquireInfoINTEL*>( pAcquireInfo ), reinterpret_cast<VkPerformanceConfigurationINTEL*>( pConfiguration ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL>::type Device::acquirePerformanceConfigurationINTEL( const PerformanceConfigurationAcquireInfoINTEL & acquireInfo, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL configuration;
+ Result result = static_cast<Result>( d.vkAcquirePerformanceConfigurationINTEL( m_device, reinterpret_cast<const VkPerformanceConfigurationAcquireInfoINTEL*>( &acquireInfo ), reinterpret_cast<VkPerformanceConfigurationINTEL*>( &configuration ) ) );
+ return createResultValue( result, configuration, VULKAN_HPP_NAMESPACE_STRING"::Device::acquirePerformanceConfigurationINTEL" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::acquireProfilingLockKHR( const VULKAN_HPP_NAMESPACE::AcquireProfilingLockInfoKHR* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkAcquireProfilingLockKHR( m_device, reinterpret_cast<const VkAcquireProfilingLockInfoKHR*>( pInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::acquireProfilingLockKHR( const AcquireProfilingLockInfoKHR & info, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkAcquireProfilingLockKHR( m_device, reinterpret_cast<const VkAcquireProfilingLockInfoKHR*>( &info ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::acquireProfilingLockKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::allocateCommandBuffers( const VULKAN_HPP_NAMESPACE::CommandBufferAllocateInfo* pAllocateInfo, VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkAllocateCommandBuffers( m_device, reinterpret_cast<const VkCommandBufferAllocateInfo*>( pAllocateInfo ), reinterpret_cast<VkCommandBuffer*>( pCommandBuffers ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<CommandBuffer,Allocator>>::type Device::allocateCommandBuffers( const CommandBufferAllocateInfo & allocateInfo, Dispatch const &d ) const
+ {
+ std::vector<CommandBuffer,Allocator> commandBuffers( allocateInfo.commandBufferCount );
+ Result result = static_cast<Result>( d.vkAllocateCommandBuffers( m_device, reinterpret_cast<const VkCommandBufferAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkCommandBuffer*>( commandBuffers.data() ) ) );
+ return createResultValue( result, commandBuffers, VULKAN_HPP_NAMESPACE_STRING"::Device::allocateCommandBuffers" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<CommandBuffer,Allocator>>::type Device::allocateCommandBuffers( const CommandBufferAllocateInfo & allocateInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<CommandBuffer,Allocator> commandBuffers( allocateInfo.commandBufferCount, vectorAllocator );
+ Result result = static_cast<Result>( d.vkAllocateCommandBuffers( m_device, reinterpret_cast<const VkCommandBufferAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkCommandBuffer*>( commandBuffers.data() ) ) );
+ return createResultValue( result, commandBuffers, VULKAN_HPP_NAMESPACE_STRING"::Device::allocateCommandBuffers" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<CommandBuffer,Dispatch>,Allocator>>::type Device::allocateCommandBuffersUnique( const CommandBufferAllocateInfo & allocateInfo, Dispatch const &d ) const
+ {
+ static_assert( sizeof( CommandBuffer ) <= sizeof( UniqueHandle<CommandBuffer, Dispatch> ), "CommandBuffer is greater than UniqueHandle<CommandBuffer, Dispatch>!" );
+ std::vector<UniqueHandle<CommandBuffer, Dispatch>, Allocator> commandBuffers;
+ commandBuffers.reserve( allocateInfo.commandBufferCount );
+ CommandBuffer* buffer = reinterpret_cast<CommandBuffer*>( reinterpret_cast<char*>( commandBuffers.data() ) + allocateInfo.commandBufferCount * ( sizeof( UniqueHandle<CommandBuffer, Dispatch> ) - sizeof( CommandBuffer ) ) );
+ Result result = static_cast<Result>(d.vkAllocateCommandBuffers( m_device, reinterpret_cast<const VkCommandBufferAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkCommandBuffer*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ PoolFree<Device,CommandPool,Dispatch> deleter( *this, allocateInfo.commandPool, d );
+ for ( size_t i=0 ; i<allocateInfo.commandBufferCount ; i++ )
+ {
+ commandBuffers.push_back( UniqueHandle<CommandBuffer, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, commandBuffers, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateCommandBuffersUnique" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<CommandBuffer,Dispatch>,Allocator>>::type Device::allocateCommandBuffersUnique( const CommandBufferAllocateInfo & allocateInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ static_assert( sizeof( CommandBuffer ) <= sizeof( UniqueHandle<CommandBuffer, Dispatch> ), "CommandBuffer is greater than UniqueHandle<CommandBuffer, Dispatch>!" );
+ std::vector<UniqueHandle<CommandBuffer, Dispatch>, Allocator> commandBuffers( vectorAllocator );
+ commandBuffers.reserve( allocateInfo.commandBufferCount );
+ CommandBuffer* buffer = reinterpret_cast<CommandBuffer*>( reinterpret_cast<char*>( commandBuffers.data() ) + allocateInfo.commandBufferCount * ( sizeof( UniqueHandle<CommandBuffer, Dispatch> ) - sizeof( CommandBuffer ) ) );
+ Result result = static_cast<Result>(d.vkAllocateCommandBuffers( m_device, reinterpret_cast<const VkCommandBufferAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkCommandBuffer*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ PoolFree<Device,CommandPool,Dispatch> deleter( *this, allocateInfo.commandPool, d );
+ for ( size_t i=0 ; i<allocateInfo.commandBufferCount ; i++ )
+ {
+ commandBuffers.push_back( UniqueHandle<CommandBuffer, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, commandBuffers, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateCommandBuffersUnique" );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::allocateDescriptorSets( const VULKAN_HPP_NAMESPACE::DescriptorSetAllocateInfo* pAllocateInfo, VULKAN_HPP_NAMESPACE::DescriptorSet* pDescriptorSets, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkAllocateDescriptorSets( m_device, reinterpret_cast<const VkDescriptorSetAllocateInfo*>( pAllocateInfo ), reinterpret_cast<VkDescriptorSet*>( pDescriptorSets ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DescriptorSet,Allocator>>::type Device::allocateDescriptorSets( const DescriptorSetAllocateInfo & allocateInfo, Dispatch const &d ) const
+ {
+ std::vector<DescriptorSet,Allocator> descriptorSets( allocateInfo.descriptorSetCount );
+ Result result = static_cast<Result>( d.vkAllocateDescriptorSets( m_device, reinterpret_cast<const VkDescriptorSetAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkDescriptorSet*>( descriptorSets.data() ) ) );
+ return createResultValue( result, descriptorSets, VULKAN_HPP_NAMESPACE_STRING"::Device::allocateDescriptorSets" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DescriptorSet,Allocator>>::type Device::allocateDescriptorSets( const DescriptorSetAllocateInfo & allocateInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<DescriptorSet,Allocator> descriptorSets( allocateInfo.descriptorSetCount, vectorAllocator );
+ Result result = static_cast<Result>( d.vkAllocateDescriptorSets( m_device, reinterpret_cast<const VkDescriptorSetAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkDescriptorSet*>( descriptorSets.data() ) ) );
+ return createResultValue( result, descriptorSets, VULKAN_HPP_NAMESPACE_STRING"::Device::allocateDescriptorSets" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<DescriptorSet,Dispatch>,Allocator>>::type Device::allocateDescriptorSetsUnique( const DescriptorSetAllocateInfo & allocateInfo, Dispatch const &d ) const
+ {
+ static_assert( sizeof( DescriptorSet ) <= sizeof( UniqueHandle<DescriptorSet, Dispatch> ), "DescriptorSet is greater than UniqueHandle<DescriptorSet, Dispatch>!" );
+ std::vector<UniqueHandle<DescriptorSet, Dispatch>, Allocator> descriptorSets;
+ descriptorSets.reserve( allocateInfo.descriptorSetCount );
+ DescriptorSet* buffer = reinterpret_cast<DescriptorSet*>( reinterpret_cast<char*>( descriptorSets.data() ) + allocateInfo.descriptorSetCount * ( sizeof( UniqueHandle<DescriptorSet, Dispatch> ) - sizeof( DescriptorSet ) ) );
+ Result result = static_cast<Result>(d.vkAllocateDescriptorSets( m_device, reinterpret_cast<const VkDescriptorSetAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkDescriptorSet*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ PoolFree<Device,DescriptorPool,Dispatch> deleter( *this, allocateInfo.descriptorPool, d );
+ for ( size_t i=0 ; i<allocateInfo.descriptorSetCount ; i++ )
+ {
+ descriptorSets.push_back( UniqueHandle<DescriptorSet, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, descriptorSets, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateDescriptorSetsUnique" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<DescriptorSet,Dispatch>,Allocator>>::type Device::allocateDescriptorSetsUnique( const DescriptorSetAllocateInfo & allocateInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ static_assert( sizeof( DescriptorSet ) <= sizeof( UniqueHandle<DescriptorSet, Dispatch> ), "DescriptorSet is greater than UniqueHandle<DescriptorSet, Dispatch>!" );
+ std::vector<UniqueHandle<DescriptorSet, Dispatch>, Allocator> descriptorSets( vectorAllocator );
+ descriptorSets.reserve( allocateInfo.descriptorSetCount );
+ DescriptorSet* buffer = reinterpret_cast<DescriptorSet*>( reinterpret_cast<char*>( descriptorSets.data() ) + allocateInfo.descriptorSetCount * ( sizeof( UniqueHandle<DescriptorSet, Dispatch> ) - sizeof( DescriptorSet ) ) );
+ Result result = static_cast<Result>(d.vkAllocateDescriptorSets( m_device, reinterpret_cast<const VkDescriptorSetAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkDescriptorSet*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ PoolFree<Device,DescriptorPool,Dispatch> deleter( *this, allocateInfo.descriptorPool, d );
+ for ( size_t i=0 ; i<allocateInfo.descriptorSetCount ; i++ )
+ {
+ descriptorSets.push_back( UniqueHandle<DescriptorSet, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, descriptorSets, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateDescriptorSetsUnique" );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::allocateMemory( const VULKAN_HPP_NAMESPACE::MemoryAllocateInfo* pAllocateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DeviceMemory* pMemory, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkAllocateMemory( m_device, reinterpret_cast<const VkMemoryAllocateInfo*>( pAllocateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDeviceMemory*>( pMemory ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DeviceMemory>::type Device::allocateMemory( const MemoryAllocateInfo & allocateInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory;
+ Result result = static_cast<Result>( d.vkAllocateMemory( m_device, reinterpret_cast<const VkMemoryAllocateInfo*>( &allocateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDeviceMemory*>( &memory ) ) );
+ return createResultValue( result, memory, VULKAN_HPP_NAMESPACE_STRING"::Device::allocateMemory" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<DeviceMemory,Dispatch>>::type Device::allocateMemoryUnique( const MemoryAllocateInfo & allocateInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DeviceMemory memory;
+ Result result = static_cast<Result>( d.vkAllocateMemory( m_device, reinterpret_cast<const VkMemoryAllocateInfo*>( &allocateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDeviceMemory*>( &memory ) ) );
+
+ ObjectFree<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<DeviceMemory,Dispatch>( result, memory, VULKAN_HPP_NAMESPACE_STRING"::Device::allocateMemoryUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::bindAccelerationStructureMemoryNV( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV* pBindInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkBindAccelerationStructureMemoryNV( m_device, bindInfoCount, reinterpret_cast<const VkBindAccelerationStructureMemoryInfoNV*>( pBindInfos ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindAccelerationStructureMemoryNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV> bindInfos, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkBindAccelerationStructureMemoryNV( m_device, bindInfos.size() , reinterpret_cast<const VkBindAccelerationStructureMemoryInfoNV*>( bindInfos.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindAccelerationStructureMemoryNV" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::bindBufferMemory( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkBindBufferMemory( m_device, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceMemory>( memory ), static_cast<VkDeviceSize>( memoryOffset ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindBufferMemory( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkBindBufferMemory( m_device, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceMemory>( memory ), static_cast<VkDeviceSize>( memoryOffset ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindBufferMemory" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::bindBufferMemory2( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo* pBindInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkBindBufferMemory2( m_device, bindInfoCount, reinterpret_cast<const VkBindBufferMemoryInfo*>( pBindInfos ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindBufferMemory2( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo> bindInfos, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkBindBufferMemory2( m_device, bindInfos.size() , reinterpret_cast<const VkBindBufferMemoryInfo*>( bindInfos.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindBufferMemory2" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::bindBufferMemory2KHR( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo* pBindInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkBindBufferMemory2KHR( m_device, bindInfoCount, reinterpret_cast<const VkBindBufferMemoryInfo*>( pBindInfos ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindBufferMemory2KHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo> bindInfos, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkBindBufferMemory2KHR( m_device, bindInfos.size() , reinterpret_cast<const VkBindBufferMemoryInfo*>( bindInfos.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindBufferMemory2KHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::bindImageMemory( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkBindImageMemory( m_device, static_cast<VkImage>( image ), static_cast<VkDeviceMemory>( memory ), static_cast<VkDeviceSize>( memoryOffset ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindImageMemory( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkBindImageMemory( m_device, static_cast<VkImage>( image ), static_cast<VkDeviceMemory>( memory ), static_cast<VkDeviceSize>( memoryOffset ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindImageMemory" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::bindImageMemory2( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo* pBindInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkBindImageMemory2( m_device, bindInfoCount, reinterpret_cast<const VkBindImageMemoryInfo*>( pBindInfos ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindImageMemory2( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo> bindInfos, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkBindImageMemory2( m_device, bindInfos.size() , reinterpret_cast<const VkBindImageMemoryInfo*>( bindInfos.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindImageMemory2" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::bindImageMemory2KHR( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo* pBindInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkBindImageMemory2KHR( m_device, bindInfoCount, reinterpret_cast<const VkBindImageMemoryInfo*>( pBindInfos ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindImageMemory2KHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo> bindInfos, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkBindImageMemory2KHR( m_device, bindInfos.size() , reinterpret_cast<const VkBindImageMemoryInfo*>( bindInfos.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindImageMemory2KHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::compileDeferredNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t shader, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCompileDeferredNV( m_device, static_cast<VkPipeline>( pipeline ), shader ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::compileDeferredNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t shader, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkCompileDeferredNV( m_device, static_cast<VkPipeline>( pipeline ), shader ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::compileDeferredNV" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createAccelerationStructureNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoNV* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructure, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateAccelerationStructureNV( m_device, reinterpret_cast<const VkAccelerationStructureCreateInfoNV*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkAccelerationStructureNV*>( pAccelerationStructure ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::AccelerationStructureNV>::type Device::createAccelerationStructureNV( const AccelerationStructureCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure;
+ Result result = static_cast<Result>( d.vkCreateAccelerationStructureNV( m_device, reinterpret_cast<const VkAccelerationStructureCreateInfoNV*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkAccelerationStructureNV*>( &accelerationStructure ) ) );
+ return createResultValue( result, accelerationStructure, VULKAN_HPP_NAMESPACE_STRING"::Device::createAccelerationStructureNV" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<AccelerationStructureNV,Dispatch>>::type Device::createAccelerationStructureNVUnique( const AccelerationStructureCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure;
+ Result result = static_cast<Result>( d.vkCreateAccelerationStructureNV( m_device, reinterpret_cast<const VkAccelerationStructureCreateInfoNV*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkAccelerationStructureNV*>( &accelerationStructure ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<AccelerationStructureNV,Dispatch>( result, accelerationStructure, VULKAN_HPP_NAMESPACE_STRING"::Device::createAccelerationStructureNVUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createBuffer( const VULKAN_HPP_NAMESPACE::BufferCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Buffer* pBuffer, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateBuffer( m_device, reinterpret_cast<const VkBufferCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkBuffer*>( pBuffer ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Buffer>::type Device::createBuffer( const BufferCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Buffer buffer;
+ Result result = static_cast<Result>( d.vkCreateBuffer( m_device, reinterpret_cast<const VkBufferCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkBuffer*>( &buffer ) ) );
+ return createResultValue( result, buffer, VULKAN_HPP_NAMESPACE_STRING"::Device::createBuffer" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Buffer,Dispatch>>::type Device::createBufferUnique( const BufferCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Buffer buffer;
+ Result result = static_cast<Result>( d.vkCreateBuffer( m_device, reinterpret_cast<const VkBufferCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkBuffer*>( &buffer ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Buffer,Dispatch>( result, buffer, VULKAN_HPP_NAMESPACE_STRING"::Device::createBufferUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createBufferView( const VULKAN_HPP_NAMESPACE::BufferViewCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::BufferView* pView, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateBufferView( m_device, reinterpret_cast<const VkBufferViewCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkBufferView*>( pView ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::BufferView>::type Device::createBufferView( const BufferViewCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::BufferView view;
+ Result result = static_cast<Result>( d.vkCreateBufferView( m_device, reinterpret_cast<const VkBufferViewCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkBufferView*>( &view ) ) );
+ return createResultValue( result, view, VULKAN_HPP_NAMESPACE_STRING"::Device::createBufferView" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<BufferView,Dispatch>>::type Device::createBufferViewUnique( const BufferViewCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::BufferView view;
+ Result result = static_cast<Result>( d.vkCreateBufferView( m_device, reinterpret_cast<const VkBufferViewCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkBufferView*>( &view ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<BufferView,Dispatch>( result, view, VULKAN_HPP_NAMESPACE_STRING"::Device::createBufferViewUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createCommandPool( const VULKAN_HPP_NAMESPACE::CommandPoolCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::CommandPool* pCommandPool, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateCommandPool( m_device, reinterpret_cast<const VkCommandPoolCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkCommandPool*>( pCommandPool ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::CommandPool>::type Device::createCommandPool( const CommandPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::CommandPool commandPool;
+ Result result = static_cast<Result>( d.vkCreateCommandPool( m_device, reinterpret_cast<const VkCommandPoolCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkCommandPool*>( &commandPool ) ) );
+ return createResultValue( result, commandPool, VULKAN_HPP_NAMESPACE_STRING"::Device::createCommandPool" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<CommandPool,Dispatch>>::type Device::createCommandPoolUnique( const CommandPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::CommandPool commandPool;
+ Result result = static_cast<Result>( d.vkCreateCommandPool( m_device, reinterpret_cast<const VkCommandPoolCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkCommandPool*>( &commandPool ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<CommandPool,Dispatch>( result, commandPool, VULKAN_HPP_NAMESPACE_STRING"::Device::createCommandPoolUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfoCount, reinterpret_cast<const VkComputePipelineCreateInfo*>( pCreateInfos ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkPipeline*>( pPipelines ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ std::vector<Pipeline,Allocator> pipelines( createInfos.size() );
+ Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkComputePipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipelines" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<Pipeline,Allocator> pipelines( createInfos.size(), vectorAllocator );
+ Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkComputePipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipelines" );
+ }
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<Pipeline>::type Device::createComputePipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ Pipeline pipeline;
+ Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkComputePipelineCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
+ return createResultValue( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipeline" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
+ std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines;
+ pipelines.reserve( createInfos.size() );
+ Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
+ Result result = static_cast<Result>(d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkComputePipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ for ( size_t i=0 ; i<createInfos.size() ; i++ )
+ {
+ pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createComputePipelinesUnique" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
+ std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines( vectorAllocator );
+ pipelines.reserve( createInfos.size() );
+ Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
+ Result result = static_cast<Result>(d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkComputePipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ for ( size_t i=0 ; i<createInfos.size() ; i++ )
+ {
+ pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createComputePipelinesUnique" );
+ }
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type Device::createComputePipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ Pipeline pipeline;
+ Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkComputePipelineCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipelineUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createDescriptorPool( const VULKAN_HPP_NAMESPACE::DescriptorPoolCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorPool* pDescriptorPool, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateDescriptorPool( m_device, reinterpret_cast<const VkDescriptorPoolCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDescriptorPool*>( pDescriptorPool ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DescriptorPool>::type Device::createDescriptorPool( const DescriptorPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool;
+ Result result = static_cast<Result>( d.vkCreateDescriptorPool( m_device, reinterpret_cast<const VkDescriptorPoolCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorPool*>( &descriptorPool ) ) );
+ return createResultValue( result, descriptorPool, VULKAN_HPP_NAMESPACE_STRING"::Device::createDescriptorPool" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<DescriptorPool,Dispatch>>::type Device::createDescriptorPoolUnique( const DescriptorPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool;
+ Result result = static_cast<Result>( d.vkCreateDescriptorPool( m_device, reinterpret_cast<const VkDescriptorPoolCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorPool*>( &descriptorPool ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<DescriptorPool,Dispatch>( result, descriptorPool, VULKAN_HPP_NAMESPACE_STRING"::Device::createDescriptorPoolUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createDescriptorSetLayout( const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorSetLayout* pSetLayout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateDescriptorSetLayout( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDescriptorSetLayout*>( pSetLayout ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DescriptorSetLayout>::type Device::createDescriptorSetLayout( const DescriptorSetLayoutCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayout setLayout;
+ Result result = static_cast<Result>( d.vkCreateDescriptorSetLayout( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorSetLayout*>( &setLayout ) ) );
+ return createResultValue( result, setLayout, VULKAN_HPP_NAMESPACE_STRING"::Device::createDescriptorSetLayout" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<DescriptorSetLayout,Dispatch>>::type Device::createDescriptorSetLayoutUnique( const DescriptorSetLayoutCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayout setLayout;
+ Result result = static_cast<Result>( d.vkCreateDescriptorSetLayout( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorSetLayout*>( &setLayout ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<DescriptorSetLayout,Dispatch>( result, setLayout, VULKAN_HPP_NAMESPACE_STRING"::Device::createDescriptorSetLayoutUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createDescriptorUpdateTemplate( const VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate* pDescriptorUpdateTemplate, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateDescriptorUpdateTemplate( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDescriptorUpdateTemplate*>( pDescriptorUpdateTemplate ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate>::type Device::createDescriptorUpdateTemplate( const DescriptorUpdateTemplateCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate;
+ Result result = static_cast<Result>( d.vkCreateDescriptorUpdateTemplate( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorUpdateTemplate*>( &descriptorUpdateTemplate ) ) );
+ return createResultValue( result, descriptorUpdateTemplate, VULKAN_HPP_NAMESPACE_STRING"::Device::createDescriptorUpdateTemplate" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<DescriptorUpdateTemplate,Dispatch>>::type Device::createDescriptorUpdateTemplateUnique( const DescriptorUpdateTemplateCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate;
+ Result result = static_cast<Result>( d.vkCreateDescriptorUpdateTemplate( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorUpdateTemplate*>( &descriptorUpdateTemplate ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<DescriptorUpdateTemplate,Dispatch>( result, descriptorUpdateTemplate, VULKAN_HPP_NAMESPACE_STRING"::Device::createDescriptorUpdateTemplateUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createDescriptorUpdateTemplateKHR( const VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate* pDescriptorUpdateTemplate, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateDescriptorUpdateTemplateKHR( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDescriptorUpdateTemplate*>( pDescriptorUpdateTemplate ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate>::type Device::createDescriptorUpdateTemplateKHR( const DescriptorUpdateTemplateCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate;
+ Result result = static_cast<Result>( d.vkCreateDescriptorUpdateTemplateKHR( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorUpdateTemplate*>( &descriptorUpdateTemplate ) ) );
+ return createResultValue( result, descriptorUpdateTemplate, VULKAN_HPP_NAMESPACE_STRING"::Device::createDescriptorUpdateTemplateKHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<DescriptorUpdateTemplate,Dispatch>>::type Device::createDescriptorUpdateTemplateKHRUnique( const DescriptorUpdateTemplateCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate;
+ Result result = static_cast<Result>( d.vkCreateDescriptorUpdateTemplateKHR( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorUpdateTemplate*>( &descriptorUpdateTemplate ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<DescriptorUpdateTemplate,Dispatch>( result, descriptorUpdateTemplate, VULKAN_HPP_NAMESPACE_STRING"::Device::createDescriptorUpdateTemplateKHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createEvent( const VULKAN_HPP_NAMESPACE::EventCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Event* pEvent, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateEvent( m_device, reinterpret_cast<const VkEventCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkEvent*>( pEvent ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Event>::type Device::createEvent( const EventCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Event event;
+ Result result = static_cast<Result>( d.vkCreateEvent( m_device, reinterpret_cast<const VkEventCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkEvent*>( &event ) ) );
+ return createResultValue( result, event, VULKAN_HPP_NAMESPACE_STRING"::Device::createEvent" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Event,Dispatch>>::type Device::createEventUnique( const EventCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Event event;
+ Result result = static_cast<Result>( d.vkCreateEvent( m_device, reinterpret_cast<const VkEventCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkEvent*>( &event ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Event,Dispatch>( result, event, VULKAN_HPP_NAMESPACE_STRING"::Device::createEventUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createFence( const VULKAN_HPP_NAMESPACE::FenceCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Fence* pFence, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateFence( m_device, reinterpret_cast<const VkFenceCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkFence*>( pFence ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Fence>::type Device::createFence( const FenceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Fence fence;
+ Result result = static_cast<Result>( d.vkCreateFence( m_device, reinterpret_cast<const VkFenceCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkFence*>( &fence ) ) );
+ return createResultValue( result, fence, VULKAN_HPP_NAMESPACE_STRING"::Device::createFence" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Fence,Dispatch>>::type Device::createFenceUnique( const FenceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Fence fence;
+ Result result = static_cast<Result>( d.vkCreateFence( m_device, reinterpret_cast<const VkFenceCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkFence*>( &fence ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Fence,Dispatch>( result, fence, VULKAN_HPP_NAMESPACE_STRING"::Device::createFenceUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createFramebuffer( const VULKAN_HPP_NAMESPACE::FramebufferCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Framebuffer* pFramebuffer, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateFramebuffer( m_device, reinterpret_cast<const VkFramebufferCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkFramebuffer*>( pFramebuffer ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Framebuffer>::type Device::createFramebuffer( const FramebufferCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Framebuffer framebuffer;
+ Result result = static_cast<Result>( d.vkCreateFramebuffer( m_device, reinterpret_cast<const VkFramebufferCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkFramebuffer*>( &framebuffer ) ) );
+ return createResultValue( result, framebuffer, VULKAN_HPP_NAMESPACE_STRING"::Device::createFramebuffer" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Framebuffer,Dispatch>>::type Device::createFramebufferUnique( const FramebufferCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Framebuffer framebuffer;
+ Result result = static_cast<Result>( d.vkCreateFramebuffer( m_device, reinterpret_cast<const VkFramebufferCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkFramebuffer*>( &framebuffer ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Framebuffer,Dispatch>( result, framebuffer, VULKAN_HPP_NAMESPACE_STRING"::Device::createFramebufferUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfoCount, reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( pCreateInfos ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkPipeline*>( pPipelines ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ std::vector<Pipeline,Allocator> pipelines( createInfos.size() );
+ Result result = static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipelines" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<Pipeline,Allocator> pipelines( createInfos.size(), vectorAllocator );
+ Result result = static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipelines" );
+ }
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<Pipeline>::type Device::createGraphicsPipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ Pipeline pipeline;
+ Result result = static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
+ return createResultValue( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipeline" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
+ std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines;
+ pipelines.reserve( createInfos.size() );
+ Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
+ Result result = static_cast<Result>(d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ for ( size_t i=0 ; i<createInfos.size() ; i++ )
+ {
+ pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createGraphicsPipelinesUnique" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
+ std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines( vectorAllocator );
+ pipelines.reserve( createInfos.size() );
+ Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
+ Result result = static_cast<Result>(d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ for ( size_t i=0 ; i<createInfos.size() ; i++ )
+ {
+ pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createGraphicsPipelinesUnique" );
+ }
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type Device::createGraphicsPipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ Pipeline pipeline;
+ Result result = static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipelineUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createImage( const VULKAN_HPP_NAMESPACE::ImageCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Image* pImage, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateImage( m_device, reinterpret_cast<const VkImageCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkImage*>( pImage ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Image>::type Device::createImage( const ImageCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Image image;
+ Result result = static_cast<Result>( d.vkCreateImage( m_device, reinterpret_cast<const VkImageCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkImage*>( &image ) ) );
+ return createResultValue( result, image, VULKAN_HPP_NAMESPACE_STRING"::Device::createImage" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Image,Dispatch>>::type Device::createImageUnique( const ImageCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Image image;
+ Result result = static_cast<Result>( d.vkCreateImage( m_device, reinterpret_cast<const VkImageCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkImage*>( &image ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Image,Dispatch>( result, image, VULKAN_HPP_NAMESPACE_STRING"::Device::createImageUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createImageView( const VULKAN_HPP_NAMESPACE::ImageViewCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::ImageView* pView, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateImageView( m_device, reinterpret_cast<const VkImageViewCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkImageView*>( pView ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageView>::type Device::createImageView( const ImageViewCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ImageView view;
+ Result result = static_cast<Result>( d.vkCreateImageView( m_device, reinterpret_cast<const VkImageViewCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkImageView*>( &view ) ) );
+ return createResultValue( result, view, VULKAN_HPP_NAMESPACE_STRING"::Device::createImageView" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<ImageView,Dispatch>>::type Device::createImageViewUnique( const ImageViewCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ImageView view;
+ Result result = static_cast<Result>( d.vkCreateImageView( m_device, reinterpret_cast<const VkImageViewCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkImageView*>( &view ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<ImageView,Dispatch>( result, view, VULKAN_HPP_NAMESPACE_STRING"::Device::createImageViewUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createIndirectCommandsLayoutNVX( const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX* pIndirectCommandsLayout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateIndirectCommandsLayoutNVX( m_device, reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNVX*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkIndirectCommandsLayoutNVX*>( pIndirectCommandsLayout ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX>::type Device::createIndirectCommandsLayoutNVX( const IndirectCommandsLayoutCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout;
+ Result result = static_cast<Result>( d.vkCreateIndirectCommandsLayoutNVX( m_device, reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNVX*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkIndirectCommandsLayoutNVX*>( &indirectCommandsLayout ) ) );
+ return createResultValue( result, indirectCommandsLayout, VULKAN_HPP_NAMESPACE_STRING"::Device::createIndirectCommandsLayoutNVX" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<IndirectCommandsLayoutNVX,Dispatch>>::type Device::createIndirectCommandsLayoutNVXUnique( const IndirectCommandsLayoutCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout;
+ Result result = static_cast<Result>( d.vkCreateIndirectCommandsLayoutNVX( m_device, reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNVX*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkIndirectCommandsLayoutNVX*>( &indirectCommandsLayout ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<IndirectCommandsLayoutNVX,Dispatch>( result, indirectCommandsLayout, VULKAN_HPP_NAMESPACE_STRING"::Device::createIndirectCommandsLayoutNVXUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createObjectTableNVX( const VULKAN_HPP_NAMESPACE::ObjectTableCreateInfoNVX* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::ObjectTableNVX* pObjectTable, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateObjectTableNVX( m_device, reinterpret_cast<const VkObjectTableCreateInfoNVX*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkObjectTableNVX*>( pObjectTable ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ObjectTableNVX>::type Device::createObjectTableNVX( const ObjectTableCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable;
+ Result result = static_cast<Result>( d.vkCreateObjectTableNVX( m_device, reinterpret_cast<const VkObjectTableCreateInfoNVX*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkObjectTableNVX*>( &objectTable ) ) );
+ return createResultValue( result, objectTable, VULKAN_HPP_NAMESPACE_STRING"::Device::createObjectTableNVX" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<ObjectTableNVX,Dispatch>>::type Device::createObjectTableNVXUnique( const ObjectTableCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable;
+ Result result = static_cast<Result>( d.vkCreateObjectTableNVX( m_device, reinterpret_cast<const VkObjectTableCreateInfoNVX*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkObjectTableNVX*>( &objectTable ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<ObjectTableNVX,Dispatch>( result, objectTable, VULKAN_HPP_NAMESPACE_STRING"::Device::createObjectTableNVXUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createPipelineCache( const VULKAN_HPP_NAMESPACE::PipelineCacheCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::PipelineCache* pPipelineCache, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreatePipelineCache( m_device, reinterpret_cast<const VkPipelineCacheCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkPipelineCache*>( pPipelineCache ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::PipelineCache>::type Device::createPipelineCache( const PipelineCacheCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache;
+ Result result = static_cast<Result>( d.vkCreatePipelineCache( m_device, reinterpret_cast<const VkPipelineCacheCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipelineCache*>( &pipelineCache ) ) );
+ return createResultValue( result, pipelineCache, VULKAN_HPP_NAMESPACE_STRING"::Device::createPipelineCache" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<PipelineCache,Dispatch>>::type Device::createPipelineCacheUnique( const PipelineCacheCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache;
+ Result result = static_cast<Result>( d.vkCreatePipelineCache( m_device, reinterpret_cast<const VkPipelineCacheCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipelineCache*>( &pipelineCache ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<PipelineCache,Dispatch>( result, pipelineCache, VULKAN_HPP_NAMESPACE_STRING"::Device::createPipelineCacheUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createPipelineLayout( const VULKAN_HPP_NAMESPACE::PipelineLayoutCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::PipelineLayout* pPipelineLayout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreatePipelineLayout( m_device, reinterpret_cast<const VkPipelineLayoutCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkPipelineLayout*>( pPipelineLayout ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::PipelineLayout>::type Device::createPipelineLayout( const PipelineLayoutCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout;
+ Result result = static_cast<Result>( d.vkCreatePipelineLayout( m_device, reinterpret_cast<const VkPipelineLayoutCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipelineLayout*>( &pipelineLayout ) ) );
+ return createResultValue( result, pipelineLayout, VULKAN_HPP_NAMESPACE_STRING"::Device::createPipelineLayout" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<PipelineLayout,Dispatch>>::type Device::createPipelineLayoutUnique( const PipelineLayoutCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout;
+ Result result = static_cast<Result>( d.vkCreatePipelineLayout( m_device, reinterpret_cast<const VkPipelineLayoutCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipelineLayout*>( &pipelineLayout ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<PipelineLayout,Dispatch>( result, pipelineLayout, VULKAN_HPP_NAMESPACE_STRING"::Device::createPipelineLayoutUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createQueryPool( const VULKAN_HPP_NAMESPACE::QueryPoolCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::QueryPool* pQueryPool, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateQueryPool( m_device, reinterpret_cast<const VkQueryPoolCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkQueryPool*>( pQueryPool ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::QueryPool>::type Device::createQueryPool( const QueryPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::QueryPool queryPool;
+ Result result = static_cast<Result>( d.vkCreateQueryPool( m_device, reinterpret_cast<const VkQueryPoolCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkQueryPool*>( &queryPool ) ) );
+ return createResultValue( result, queryPool, VULKAN_HPP_NAMESPACE_STRING"::Device::createQueryPool" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<QueryPool,Dispatch>>::type Device::createQueryPoolUnique( const QueryPoolCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::QueryPool queryPool;
+ Result result = static_cast<Result>( d.vkCreateQueryPool( m_device, reinterpret_cast<const VkQueryPoolCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkQueryPool*>( &queryPool ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<QueryPool,Dispatch>( result, queryPool, VULKAN_HPP_NAMESPACE_STRING"::Device::createQueryPoolUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfoCount, reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( pCreateInfos ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkPipeline*>( pPipelines ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ std::vector<Pipeline,Allocator> pipelines( createInfos.size() );
+ Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelinesNV" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<Pipeline,Allocator> pipelines( createInfos.size(), vectorAllocator );
+ Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelinesNV" );
+ }
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<Pipeline>::type Device::createRayTracingPipelineNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ Pipeline pipeline;
+ Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
+ return createResultValue( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelineNV" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
+ std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines;
+ pipelines.reserve( createInfos.size() );
+ Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
+ Result result = static_cast<Result>(d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ for ( size_t i=0 ; i<createInfos.size() ; i++ )
+ {
+ pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createRayTracingPipelinesNVUnique" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
+ std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines( vectorAllocator );
+ pipelines.reserve( createInfos.size() );
+ Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
+ Result result = static_cast<Result>(d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ for ( size_t i=0 ; i<createInfos.size() ; i++ )
+ {
+ pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createRayTracingPipelinesNVUnique" );
+ }
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type Device::createRayTracingPipelineNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ Pipeline pipeline;
+ Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelineNVUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createRenderPass( const VULKAN_HPP_NAMESPACE::RenderPassCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::RenderPass* pRenderPass, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateRenderPass( m_device, reinterpret_cast<const VkRenderPassCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkRenderPass*>( pRenderPass ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::RenderPass>::type Device::createRenderPass( const RenderPassCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass;
+ Result result = static_cast<Result>( d.vkCreateRenderPass( m_device, reinterpret_cast<const VkRenderPassCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkRenderPass*>( &renderPass ) ) );
+ return createResultValue( result, renderPass, VULKAN_HPP_NAMESPACE_STRING"::Device::createRenderPass" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<RenderPass,Dispatch>>::type Device::createRenderPassUnique( const RenderPassCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass;
+ Result result = static_cast<Result>( d.vkCreateRenderPass( m_device, reinterpret_cast<const VkRenderPassCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkRenderPass*>( &renderPass ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<RenderPass,Dispatch>( result, renderPass, VULKAN_HPP_NAMESPACE_STRING"::Device::createRenderPassUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createRenderPass2( const VULKAN_HPP_NAMESPACE::RenderPassCreateInfo2* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::RenderPass* pRenderPass, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateRenderPass2( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkRenderPass*>( pRenderPass ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::RenderPass>::type Device::createRenderPass2( const RenderPassCreateInfo2 & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass;
+ Result result = static_cast<Result>( d.vkCreateRenderPass2( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkRenderPass*>( &renderPass ) ) );
+ return createResultValue( result, renderPass, VULKAN_HPP_NAMESPACE_STRING"::Device::createRenderPass2" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<RenderPass,Dispatch>>::type Device::createRenderPass2Unique( const RenderPassCreateInfo2 & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass;
+ Result result = static_cast<Result>( d.vkCreateRenderPass2( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkRenderPass*>( &renderPass ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<RenderPass,Dispatch>( result, renderPass, VULKAN_HPP_NAMESPACE_STRING"::Device::createRenderPass2Unique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createRenderPass2KHR( const VULKAN_HPP_NAMESPACE::RenderPassCreateInfo2* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::RenderPass* pRenderPass, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateRenderPass2KHR( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkRenderPass*>( pRenderPass ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::RenderPass>::type Device::createRenderPass2KHR( const RenderPassCreateInfo2 & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass;
+ Result result = static_cast<Result>( d.vkCreateRenderPass2KHR( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkRenderPass*>( &renderPass ) ) );
+ return createResultValue( result, renderPass, VULKAN_HPP_NAMESPACE_STRING"::Device::createRenderPass2KHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<RenderPass,Dispatch>>::type Device::createRenderPass2KHRUnique( const RenderPassCreateInfo2 & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::RenderPass renderPass;
+ Result result = static_cast<Result>( d.vkCreateRenderPass2KHR( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkRenderPass*>( &renderPass ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<RenderPass,Dispatch>( result, renderPass, VULKAN_HPP_NAMESPACE_STRING"::Device::createRenderPass2KHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createSampler( const VULKAN_HPP_NAMESPACE::SamplerCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Sampler* pSampler, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateSampler( m_device, reinterpret_cast<const VkSamplerCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSampler*>( pSampler ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Sampler>::type Device::createSampler( const SamplerCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Sampler sampler;
+ Result result = static_cast<Result>( d.vkCreateSampler( m_device, reinterpret_cast<const VkSamplerCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSampler*>( &sampler ) ) );
+ return createResultValue( result, sampler, VULKAN_HPP_NAMESPACE_STRING"::Device::createSampler" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Sampler,Dispatch>>::type Device::createSamplerUnique( const SamplerCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Sampler sampler;
+ Result result = static_cast<Result>( d.vkCreateSampler( m_device, reinterpret_cast<const VkSamplerCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSampler*>( &sampler ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Sampler,Dispatch>( result, sampler, VULKAN_HPP_NAMESPACE_STRING"::Device::createSamplerUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createSamplerYcbcrConversion( const VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion* pYcbcrConversion, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateSamplerYcbcrConversion( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSamplerYcbcrConversion*>( pYcbcrConversion ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion>::type Device::createSamplerYcbcrConversion( const SamplerYcbcrConversionCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion;
+ Result result = static_cast<Result>( d.vkCreateSamplerYcbcrConversion( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSamplerYcbcrConversion*>( &ycbcrConversion ) ) );
+ return createResultValue( result, ycbcrConversion, VULKAN_HPP_NAMESPACE_STRING"::Device::createSamplerYcbcrConversion" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SamplerYcbcrConversion,Dispatch>>::type Device::createSamplerYcbcrConversionUnique( const SamplerYcbcrConversionCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion;
+ Result result = static_cast<Result>( d.vkCreateSamplerYcbcrConversion( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSamplerYcbcrConversion*>( &ycbcrConversion ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SamplerYcbcrConversion,Dispatch>( result, ycbcrConversion, VULKAN_HPP_NAMESPACE_STRING"::Device::createSamplerYcbcrConversionUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createSamplerYcbcrConversionKHR( const VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion* pYcbcrConversion, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateSamplerYcbcrConversionKHR( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSamplerYcbcrConversion*>( pYcbcrConversion ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion>::type Device::createSamplerYcbcrConversionKHR( const SamplerYcbcrConversionCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion;
+ Result result = static_cast<Result>( d.vkCreateSamplerYcbcrConversionKHR( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSamplerYcbcrConversion*>( &ycbcrConversion ) ) );
+ return createResultValue( result, ycbcrConversion, VULKAN_HPP_NAMESPACE_STRING"::Device::createSamplerYcbcrConversionKHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SamplerYcbcrConversion,Dispatch>>::type Device::createSamplerYcbcrConversionKHRUnique( const SamplerYcbcrConversionCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion;
+ Result result = static_cast<Result>( d.vkCreateSamplerYcbcrConversionKHR( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSamplerYcbcrConversion*>( &ycbcrConversion ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SamplerYcbcrConversion,Dispatch>( result, ycbcrConversion, VULKAN_HPP_NAMESPACE_STRING"::Device::createSamplerYcbcrConversionKHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createSemaphore( const VULKAN_HPP_NAMESPACE::SemaphoreCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Semaphore* pSemaphore, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateSemaphore( m_device, reinterpret_cast<const VkSemaphoreCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSemaphore*>( pSemaphore ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Semaphore>::type Device::createSemaphore( const SemaphoreCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Semaphore semaphore;
+ Result result = static_cast<Result>( d.vkCreateSemaphore( m_device, reinterpret_cast<const VkSemaphoreCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSemaphore*>( &semaphore ) ) );
+ return createResultValue( result, semaphore, VULKAN_HPP_NAMESPACE_STRING"::Device::createSemaphore" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Semaphore,Dispatch>>::type Device::createSemaphoreUnique( const SemaphoreCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Semaphore semaphore;
+ Result result = static_cast<Result>( d.vkCreateSemaphore( m_device, reinterpret_cast<const VkSemaphoreCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSemaphore*>( &semaphore ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Semaphore,Dispatch>( result, semaphore, VULKAN_HPP_NAMESPACE_STRING"::Device::createSemaphoreUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createShaderModule( const VULKAN_HPP_NAMESPACE::ShaderModuleCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::ShaderModule* pShaderModule, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateShaderModule( m_device, reinterpret_cast<const VkShaderModuleCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkShaderModule*>( pShaderModule ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ShaderModule>::type Device::createShaderModule( const ShaderModuleCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ShaderModule shaderModule;
+ Result result = static_cast<Result>( d.vkCreateShaderModule( m_device, reinterpret_cast<const VkShaderModuleCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkShaderModule*>( &shaderModule ) ) );
+ return createResultValue( result, shaderModule, VULKAN_HPP_NAMESPACE_STRING"::Device::createShaderModule" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<ShaderModule,Dispatch>>::type Device::createShaderModuleUnique( const ShaderModuleCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ShaderModule shaderModule;
+ Result result = static_cast<Result>( d.vkCreateShaderModule( m_device, reinterpret_cast<const VkShaderModuleCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkShaderModule*>( &shaderModule ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<ShaderModule,Dispatch>( result, shaderModule, VULKAN_HPP_NAMESPACE_STRING"::Device::createShaderModuleUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createSharedSwapchainsKHR( uint32_t swapchainCount, const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SwapchainKHR* pSwapchains, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateSharedSwapchainsKHR( m_device, swapchainCount, reinterpret_cast<const VkSwapchainCreateInfoKHR*>( pCreateInfos ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSwapchainKHR*>( pSwapchains ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<SwapchainKHR,Allocator>>::type Device::createSharedSwapchainsKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ std::vector<SwapchainKHR,Allocator> swapchains( createInfos.size() );
+ Result result = static_cast<Result>( d.vkCreateSharedSwapchainsKHR( m_device, createInfos.size() , reinterpret_cast<const VkSwapchainCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>( swapchains.data() ) ) );
+ return createResultValue( result, swapchains, VULKAN_HPP_NAMESPACE_STRING"::Device::createSharedSwapchainsKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<SwapchainKHR,Allocator>>::type Device::createSharedSwapchainsKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<SwapchainKHR,Allocator> swapchains( createInfos.size(), vectorAllocator );
+ Result result = static_cast<Result>( d.vkCreateSharedSwapchainsKHR( m_device, createInfos.size() , reinterpret_cast<const VkSwapchainCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>( swapchains.data() ) ) );
+ return createResultValue( result, swapchains, VULKAN_HPP_NAMESPACE_STRING"::Device::createSharedSwapchainsKHR" );
+ }
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<SwapchainKHR>::type Device::createSharedSwapchainKHR( const SwapchainCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ SwapchainKHR swapchain;
+ Result result = static_cast<Result>( d.vkCreateSharedSwapchainsKHR( m_device, 1 , reinterpret_cast<const VkSwapchainCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>( &swapchain ) ) );
+ return createResultValue( result, swapchain, VULKAN_HPP_NAMESPACE_STRING"::Device::createSharedSwapchainKHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<SwapchainKHR,Dispatch>,Allocator>>::type Device::createSharedSwapchainsKHRUnique( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ static_assert( sizeof( SwapchainKHR ) <= sizeof( UniqueHandle<SwapchainKHR, Dispatch> ), "SwapchainKHR is greater than UniqueHandle<SwapchainKHR, Dispatch>!" );
+ std::vector<UniqueHandle<SwapchainKHR, Dispatch>, Allocator> swapchainKHRs;
+ swapchainKHRs.reserve( createInfos.size() );
+ SwapchainKHR* buffer = reinterpret_cast<SwapchainKHR*>( reinterpret_cast<char*>( swapchainKHRs.data() ) + createInfos.size() * ( sizeof( UniqueHandle<SwapchainKHR, Dispatch> ) - sizeof( SwapchainKHR ) ) );
+ Result result = static_cast<Result>(d.vkCreateSharedSwapchainsKHR( m_device, createInfos.size() , reinterpret_cast<const VkSwapchainCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ for ( size_t i=0 ; i<createInfos.size() ; i++ )
+ {
+ swapchainKHRs.push_back( UniqueHandle<SwapchainKHR, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, swapchainKHRs, VULKAN_HPP_NAMESPACE_STRING "::Device::createSharedSwapchainsKHRUnique" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<SwapchainKHR,Dispatch>,Allocator>>::type Device::createSharedSwapchainsKHRUnique( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ static_assert( sizeof( SwapchainKHR ) <= sizeof( UniqueHandle<SwapchainKHR, Dispatch> ), "SwapchainKHR is greater than UniqueHandle<SwapchainKHR, Dispatch>!" );
+ std::vector<UniqueHandle<SwapchainKHR, Dispatch>, Allocator> swapchainKHRs( vectorAllocator );
+ swapchainKHRs.reserve( createInfos.size() );
+ SwapchainKHR* buffer = reinterpret_cast<SwapchainKHR*>( reinterpret_cast<char*>( swapchainKHRs.data() ) + createInfos.size() * ( sizeof( UniqueHandle<SwapchainKHR, Dispatch> ) - sizeof( SwapchainKHR ) ) );
+ Result result = static_cast<Result>(d.vkCreateSharedSwapchainsKHR( m_device, createInfos.size() , reinterpret_cast<const VkSwapchainCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>( buffer ) ) );
+ if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+ {
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ for ( size_t i=0 ; i<createInfos.size() ; i++ )
+ {
+ swapchainKHRs.push_back( UniqueHandle<SwapchainKHR, Dispatch>( buffer[i], deleter ) );
+ }
+ }
+
+ return createResultValue( result, swapchainKHRs, VULKAN_HPP_NAMESPACE_STRING "::Device::createSharedSwapchainsKHRUnique" );
+ }
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SwapchainKHR,Dispatch>>::type Device::createSharedSwapchainKHRUnique( const SwapchainCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ SwapchainKHR swapchain;
+ Result result = static_cast<Result>( d.vkCreateSharedSwapchainsKHR( m_device, 1 , reinterpret_cast<const VkSwapchainCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>( &swapchain ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SwapchainKHR,Dispatch>( result, swapchain, VULKAN_HPP_NAMESPACE_STRING"::Device::createSharedSwapchainKHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createSwapchainKHR( const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SwapchainKHR* pSwapchain, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateSwapchainKHR( m_device, reinterpret_cast<const VkSwapchainCreateInfoKHR*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSwapchainKHR*>( pSwapchain ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SwapchainKHR>::type Device::createSwapchainKHR( const SwapchainCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain;
+ Result result = static_cast<Result>( d.vkCreateSwapchainKHR( m_device, reinterpret_cast<const VkSwapchainCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>( &swapchain ) ) );
+ return createResultValue( result, swapchain, VULKAN_HPP_NAMESPACE_STRING"::Device::createSwapchainKHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SwapchainKHR,Dispatch>>::type Device::createSwapchainKHRUnique( const SwapchainCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain;
+ Result result = static_cast<Result>( d.vkCreateSwapchainKHR( m_device, reinterpret_cast<const VkSwapchainCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>( &swapchain ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SwapchainKHR,Dispatch>( result, swapchain, VULKAN_HPP_NAMESPACE_STRING"::Device::createSwapchainKHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::createValidationCacheEXT( const VULKAN_HPP_NAMESPACE::ValidationCacheCreateInfoEXT* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::ValidationCacheEXT* pValidationCache, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateValidationCacheEXT( m_device, reinterpret_cast<const VkValidationCacheCreateInfoEXT*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkValidationCacheEXT*>( pValidationCache ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ValidationCacheEXT>::type Device::createValidationCacheEXT( const ValidationCacheCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache;
+ Result result = static_cast<Result>( d.vkCreateValidationCacheEXT( m_device, reinterpret_cast<const VkValidationCacheCreateInfoEXT*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkValidationCacheEXT*>( &validationCache ) ) );
+ return createResultValue( result, validationCache, VULKAN_HPP_NAMESPACE_STRING"::Device::createValidationCacheEXT" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<ValidationCacheEXT,Dispatch>>::type Device::createValidationCacheEXTUnique( const ValidationCacheCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache;
+ Result result = static_cast<Result>( d.vkCreateValidationCacheEXT( m_device, reinterpret_cast<const VkValidationCacheCreateInfoEXT*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkValidationCacheEXT*>( &validationCache ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<ValidationCacheEXT,Dispatch>( result, validationCache, VULKAN_HPP_NAMESPACE_STRING"::Device::createValidationCacheEXTUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::debugMarkerSetObjectNameEXT( const VULKAN_HPP_NAMESPACE::DebugMarkerObjectNameInfoEXT* pNameInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkDebugMarkerSetObjectNameEXT( m_device, reinterpret_cast<const VkDebugMarkerObjectNameInfoEXT*>( pNameInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::debugMarkerSetObjectNameEXT( const DebugMarkerObjectNameInfoEXT & nameInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkDebugMarkerSetObjectNameEXT( m_device, reinterpret_cast<const VkDebugMarkerObjectNameInfoEXT*>( &nameInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::debugMarkerSetObjectNameEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::debugMarkerSetObjectTagEXT( const VULKAN_HPP_NAMESPACE::DebugMarkerObjectTagInfoEXT* pTagInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkDebugMarkerSetObjectTagEXT( m_device, reinterpret_cast<const VkDebugMarkerObjectTagInfoEXT*>( pTagInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::debugMarkerSetObjectTagEXT( const DebugMarkerObjectTagInfoEXT & tagInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkDebugMarkerSetObjectTagEXT( m_device, reinterpret_cast<const VkDebugMarkerObjectTagInfoEXT*>( &tagInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::debugMarkerSetObjectTagEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyAccelerationStructureNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyAccelerationStructureNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyAccelerationStructureNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyAccelerationStructureNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyBuffer( m_device, static_cast<VkBuffer>( buffer ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyBuffer( m_device, static_cast<VkBuffer>( buffer ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Buffer buffer, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyBuffer( m_device, static_cast<VkBuffer>( buffer ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Buffer buffer, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyBuffer( m_device, static_cast<VkBuffer>( buffer ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyBufferView( VULKAN_HPP_NAMESPACE::BufferView bufferView, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyBufferView( m_device, static_cast<VkBufferView>( bufferView ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyBufferView( VULKAN_HPP_NAMESPACE::BufferView bufferView, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyBufferView( m_device, static_cast<VkBufferView>( bufferView ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::BufferView bufferView, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyBufferView( m_device, static_cast<VkBufferView>( bufferView ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::BufferView bufferView, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyBufferView( m_device, static_cast<VkBufferView>( bufferView ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyCommandPool( m_device, static_cast<VkCommandPool>( commandPool ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyCommandPool( m_device, static_cast<VkCommandPool>( commandPool ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::CommandPool commandPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyCommandPool( m_device, static_cast<VkCommandPool>( commandPool ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::CommandPool commandPool, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyCommandPool( m_device, static_cast<VkCommandPool>( commandPool ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorPool( m_device, static_cast<VkDescriptorPool>( descriptorPool ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorPool( m_device, static_cast<VkDescriptorPool>( descriptorPool ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorPool( m_device, static_cast<VkDescriptorPool>( descriptorPool ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorPool( m_device, static_cast<VkDescriptorPool>( descriptorPool ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyDescriptorSetLayout( VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorSetLayout( m_device, static_cast<VkDescriptorSetLayout>( descriptorSetLayout ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyDescriptorSetLayout( VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorSetLayout( m_device, static_cast<VkDescriptorSetLayout>( descriptorSetLayout ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorSetLayout( m_device, static_cast<VkDescriptorSetLayout>( descriptorSetLayout ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::DescriptorSetLayout descriptorSetLayout, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorSetLayout( m_device, static_cast<VkDescriptorSetLayout>( descriptorSetLayout ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyDescriptorUpdateTemplate( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorUpdateTemplate( m_device, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyDescriptorUpdateTemplate( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorUpdateTemplate( m_device, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorUpdateTemplate( m_device, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorUpdateTemplate( m_device, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyDescriptorUpdateTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorUpdateTemplateKHR( m_device, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyDescriptorUpdateTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDescriptorUpdateTemplateKHR( m_device, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDevice( m_device, reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDevice( m_device, reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyEvent( VULKAN_HPP_NAMESPACE::Event event, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyEvent( m_device, static_cast<VkEvent>( event ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyEvent( VULKAN_HPP_NAMESPACE::Event event, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyEvent( m_device, static_cast<VkEvent>( event ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Event event, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyEvent( m_device, static_cast<VkEvent>( event ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Event event, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyEvent( m_device, static_cast<VkEvent>( event ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyFence( VULKAN_HPP_NAMESPACE::Fence fence, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyFence( m_device, static_cast<VkFence>( fence ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyFence( VULKAN_HPP_NAMESPACE::Fence fence, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyFence( m_device, static_cast<VkFence>( fence ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Fence fence, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyFence( m_device, static_cast<VkFence>( fence ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Fence fence, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyFence( m_device, static_cast<VkFence>( fence ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyFramebuffer( VULKAN_HPP_NAMESPACE::Framebuffer framebuffer, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyFramebuffer( m_device, static_cast<VkFramebuffer>( framebuffer ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyFramebuffer( VULKAN_HPP_NAMESPACE::Framebuffer framebuffer, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyFramebuffer( m_device, static_cast<VkFramebuffer>( framebuffer ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Framebuffer framebuffer, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyFramebuffer( m_device, static_cast<VkFramebuffer>( framebuffer ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Framebuffer framebuffer, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyFramebuffer( m_device, static_cast<VkFramebuffer>( framebuffer ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyImage( VULKAN_HPP_NAMESPACE::Image image, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyImage( m_device, static_cast<VkImage>( image ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyImage( VULKAN_HPP_NAMESPACE::Image image, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyImage( m_device, static_cast<VkImage>( image ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Image image, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyImage( m_device, static_cast<VkImage>( image ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Image image, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyImage( m_device, static_cast<VkImage>( image ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyImageView( VULKAN_HPP_NAMESPACE::ImageView imageView, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyImageView( m_device, static_cast<VkImageView>( imageView ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyImageView( VULKAN_HPP_NAMESPACE::ImageView imageView, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyImageView( m_device, static_cast<VkImageView>( imageView ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::ImageView imageView, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyImageView( m_device, static_cast<VkImageView>( imageView ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::ImageView imageView, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyImageView( m_device, static_cast<VkImageView>( imageView ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyIndirectCommandsLayoutNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyIndirectCommandsLayoutNVX( m_device, static_cast<VkIndirectCommandsLayoutNVX>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyIndirectCommandsLayoutNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyIndirectCommandsLayoutNVX( m_device, static_cast<VkIndirectCommandsLayoutNVX>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyIndirectCommandsLayoutNVX( m_device, static_cast<VkIndirectCommandsLayoutNVX>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyIndirectCommandsLayoutNVX( m_device, static_cast<VkIndirectCommandsLayoutNVX>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyObjectTableNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyObjectTableNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyObjectTableNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyObjectTableNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyObjectTableNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyObjectTableNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyPipeline( VULKAN_HPP_NAMESPACE::Pipeline pipeline, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipeline( m_device, static_cast<VkPipeline>( pipeline ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyPipeline( VULKAN_HPP_NAMESPACE::Pipeline pipeline, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipeline( m_device, static_cast<VkPipeline>( pipeline ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Pipeline pipeline, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipeline( m_device, static_cast<VkPipeline>( pipeline ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Pipeline pipeline, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipeline( m_device, static_cast<VkPipeline>( pipeline ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyPipelineCache( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipelineCache( m_device, static_cast<VkPipelineCache>( pipelineCache ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyPipelineCache( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipelineCache( m_device, static_cast<VkPipelineCache>( pipelineCache ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipelineCache( m_device, static_cast<VkPipelineCache>( pipelineCache ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipelineCache( m_device, static_cast<VkPipelineCache>( pipelineCache ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyPipelineLayout( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipelineLayout( m_device, static_cast<VkPipelineLayout>( pipelineLayout ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyPipelineLayout( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipelineLayout( m_device, static_cast<VkPipelineLayout>( pipelineLayout ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipelineLayout( m_device, static_cast<VkPipelineLayout>( pipelineLayout ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyPipelineLayout( m_device, static_cast<VkPipelineLayout>( pipelineLayout ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyQueryPool( VULKAN_HPP_NAMESPACE::QueryPool queryPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyQueryPool( m_device, static_cast<VkQueryPool>( queryPool ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyQueryPool( VULKAN_HPP_NAMESPACE::QueryPool queryPool, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyQueryPool( m_device, static_cast<VkQueryPool>( queryPool ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::QueryPool queryPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyQueryPool( m_device, static_cast<VkQueryPool>( queryPool ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::QueryPool queryPool, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyQueryPool( m_device, static_cast<VkQueryPool>( queryPool ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyRenderPass( VULKAN_HPP_NAMESPACE::RenderPass renderPass, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyRenderPass( m_device, static_cast<VkRenderPass>( renderPass ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyRenderPass( VULKAN_HPP_NAMESPACE::RenderPass renderPass, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyRenderPass( m_device, static_cast<VkRenderPass>( renderPass ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::RenderPass renderPass, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyRenderPass( m_device, static_cast<VkRenderPass>( renderPass ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::RenderPass renderPass, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyRenderPass( m_device, static_cast<VkRenderPass>( renderPass ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroySampler( VULKAN_HPP_NAMESPACE::Sampler sampler, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySampler( m_device, static_cast<VkSampler>( sampler ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroySampler( VULKAN_HPP_NAMESPACE::Sampler sampler, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySampler( m_device, static_cast<VkSampler>( sampler ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Sampler sampler, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySampler( m_device, static_cast<VkSampler>( sampler ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Sampler sampler, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySampler( m_device, static_cast<VkSampler>( sampler ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroySamplerYcbcrConversion( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySamplerYcbcrConversion( m_device, static_cast<VkSamplerYcbcrConversion>( ycbcrConversion ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroySamplerYcbcrConversion( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySamplerYcbcrConversion( m_device, static_cast<VkSamplerYcbcrConversion>( ycbcrConversion ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySamplerYcbcrConversion( m_device, static_cast<VkSamplerYcbcrConversion>( ycbcrConversion ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySamplerYcbcrConversion( m_device, static_cast<VkSamplerYcbcrConversion>( ycbcrConversion ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroySamplerYcbcrConversionKHR( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySamplerYcbcrConversionKHR( m_device, static_cast<VkSamplerYcbcrConversion>( ycbcrConversion ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroySamplerYcbcrConversionKHR( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySamplerYcbcrConversionKHR( m_device, static_cast<VkSamplerYcbcrConversion>( ycbcrConversion ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroySemaphore( VULKAN_HPP_NAMESPACE::Semaphore semaphore, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySemaphore( m_device, static_cast<VkSemaphore>( semaphore ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroySemaphore( VULKAN_HPP_NAMESPACE::Semaphore semaphore, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySemaphore( m_device, static_cast<VkSemaphore>( semaphore ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Semaphore semaphore, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySemaphore( m_device, static_cast<VkSemaphore>( semaphore ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::Semaphore semaphore, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySemaphore( m_device, static_cast<VkSemaphore>( semaphore ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyShaderModule( VULKAN_HPP_NAMESPACE::ShaderModule shaderModule, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyShaderModule( m_device, static_cast<VkShaderModule>( shaderModule ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyShaderModule( VULKAN_HPP_NAMESPACE::ShaderModule shaderModule, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyShaderModule( m_device, static_cast<VkShaderModule>( shaderModule ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::ShaderModule shaderModule, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyShaderModule( m_device, static_cast<VkShaderModule>( shaderModule ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::ShaderModule shaderModule, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyShaderModule( m_device, static_cast<VkShaderModule>( shaderModule ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroySwapchainKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySwapchainKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroySwapchainKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySwapchainKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySwapchainKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySwapchainKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyValidationCacheEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyValidationCacheEXT( m_device, static_cast<VkValidationCacheEXT>( validationCache ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroyValidationCacheEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyValidationCacheEXT( m_device, static_cast<VkValidationCacheEXT>( validationCache ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyValidationCacheEXT( m_device, static_cast<VkValidationCacheEXT>( validationCache ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyValidationCacheEXT( m_device, static_cast<VkValidationCacheEXT>( validationCache ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::waitIdle(Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkDeviceWaitIdle( m_device ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::waitIdle(Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkDeviceWaitIdle( m_device ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::waitIdle" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::displayPowerControlEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, const VULKAN_HPP_NAMESPACE::DisplayPowerInfoEXT* pDisplayPowerInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkDisplayPowerControlEXT( m_device, static_cast<VkDisplayKHR>( display ), reinterpret_cast<const VkDisplayPowerInfoEXT*>( pDisplayPowerInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::displayPowerControlEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, const DisplayPowerInfoEXT & displayPowerInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkDisplayPowerControlEXT( m_device, static_cast<VkDisplayKHR>( display ), reinterpret_cast<const VkDisplayPowerInfoEXT*>( &displayPowerInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::displayPowerControlEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::flushMappedMemoryRanges( uint32_t memoryRangeCount, const VULKAN_HPP_NAMESPACE::MappedMemoryRange* pMemoryRanges, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkFlushMappedMemoryRanges( m_device, memoryRangeCount, reinterpret_cast<const VkMappedMemoryRange*>( pMemoryRanges ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::flushMappedMemoryRanges( ArrayProxy<const VULKAN_HPP_NAMESPACE::MappedMemoryRange> memoryRanges, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkFlushMappedMemoryRanges( m_device, memoryRanges.size() , reinterpret_cast<const VkMappedMemoryRange*>( memoryRanges.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::flushMappedMemoryRanges" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::freeCommandBuffers( VULKAN_HPP_NAMESPACE::CommandPool commandPool, uint32_t commandBufferCount, const VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkFreeCommandBuffers( m_device, static_cast<VkCommandPool>( commandPool ), commandBufferCount, reinterpret_cast<const VkCommandBuffer*>( pCommandBuffers ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::freeCommandBuffers( VULKAN_HPP_NAMESPACE::CommandPool commandPool, ArrayProxy<const VULKAN_HPP_NAMESPACE::CommandBuffer> commandBuffers, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkFreeCommandBuffers( m_device, static_cast<VkCommandPool>( commandPool ), commandBuffers.size() , reinterpret_cast<const VkCommandBuffer*>( commandBuffers.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::free( VULKAN_HPP_NAMESPACE::CommandPool commandPool, uint32_t commandBufferCount, const VULKAN_HPP_NAMESPACE::CommandBuffer* pCommandBuffers, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkFreeCommandBuffers( m_device, static_cast<VkCommandPool>( commandPool ), commandBufferCount, reinterpret_cast<const VkCommandBuffer*>( pCommandBuffers ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::free( VULKAN_HPP_NAMESPACE::CommandPool commandPool, ArrayProxy<const VULKAN_HPP_NAMESPACE::CommandBuffer> commandBuffers, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkFreeCommandBuffers( m_device, static_cast<VkCommandPool>( commandPool ), commandBuffers.size() , reinterpret_cast<const VkCommandBuffer*>( commandBuffers.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::freeDescriptorSets( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, uint32_t descriptorSetCount, const VULKAN_HPP_NAMESPACE::DescriptorSet* pDescriptorSets, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkFreeDescriptorSets( m_device, static_cast<VkDescriptorPool>( descriptorPool ), descriptorSetCount, reinterpret_cast<const VkDescriptorSet*>( pDescriptorSets ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::freeDescriptorSets( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, ArrayProxy<const VULKAN_HPP_NAMESPACE::DescriptorSet> descriptorSets, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkFreeDescriptorSets( m_device, static_cast<VkDescriptorPool>( descriptorPool ), descriptorSets.size() , reinterpret_cast<const VkDescriptorSet*>( descriptorSets.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::freeDescriptorSets" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::free( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, uint32_t descriptorSetCount, const VULKAN_HPP_NAMESPACE::DescriptorSet* pDescriptorSets, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkFreeDescriptorSets( m_device, static_cast<VkDescriptorPool>( descriptorPool ), descriptorSetCount, reinterpret_cast<const VkDescriptorSet*>( pDescriptorSets ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::free( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, ArrayProxy<const VULKAN_HPP_NAMESPACE::DescriptorSet> descriptorSets, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkFreeDescriptorSets( m_device, static_cast<VkDescriptorPool>( descriptorPool ), descriptorSets.size() , reinterpret_cast<const VkDescriptorSet*>( descriptorSets.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::free" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::freeMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkFreeMemory( m_device, static_cast<VkDeviceMemory>( memory ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::freeMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkFreeMemory( m_device, static_cast<VkDeviceMemory>( memory ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::free( VULKAN_HPP_NAMESPACE::DeviceMemory memory, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkFreeMemory( m_device, static_cast<VkDeviceMemory>( memory ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::free( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkFreeMemory( m_device, static_cast<VkDeviceMemory>( memory ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, size_t dataSize, void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetAccelerationStructureHandleNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), dataSize, pData ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename T, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, ArrayProxy<T> data, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkGetAccelerationStructureHandleNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), data.size() * sizeof( T ) , reinterpret_cast<void*>( data.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getAccelerationStructureHandleNV" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getAccelerationStructureMemoryRequirementsNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoNV* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2KHR* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetAccelerationStructureMemoryRequirementsNV( m_device, reinterpret_cast<const VkAccelerationStructureMemoryRequirementsInfoNV*>( pInfo ), reinterpret_cast<VkMemoryRequirements2KHR*>( pMemoryRequirements ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements2KHR Device::getAccelerationStructureMemoryRequirementsNV( const AccelerationStructureMemoryRequirementsInfoNV & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2KHR memoryRequirements;
+ d.vkGetAccelerationStructureMemoryRequirementsNV( m_device, reinterpret_cast<const VkAccelerationStructureMemoryRequirementsInfoNV*>( &info ), reinterpret_cast<VkMemoryRequirements2KHR*>( &memoryRequirements ) );
+ return memoryRequirements;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> Device::getAccelerationStructureMemoryRequirementsNV( const AccelerationStructureMemoryRequirementsInfoNV & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2KHR& memoryRequirements = structureChain.template get<VULKAN_HPP_NAMESPACE::MemoryRequirements2KHR>();
+ d.vkGetAccelerationStructureMemoryRequirementsNV( m_device, reinterpret_cast<const VkAccelerationStructureMemoryRequirementsInfoNV*>( &info ), reinterpret_cast<VkMemoryRequirements2KHR*>( &memoryRequirements ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getAndroidHardwareBufferPropertiesANDROID( const struct AHardwareBuffer* buffer, VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetAndroidHardwareBufferPropertiesANDROID( m_device, buffer, reinterpret_cast<VkAndroidHardwareBufferPropertiesANDROID*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID>::type Device::getAndroidHardwareBufferPropertiesANDROID( const struct AHardwareBuffer & buffer, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID properties;
+ Result result = static_cast<Result>( d.vkGetAndroidHardwareBufferPropertiesANDROID( m_device, buffer, reinterpret_cast<VkAndroidHardwareBufferPropertiesANDROID*>( &properties ) ) );
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::Device::getAndroidHardwareBufferPropertiesANDROID" );
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<StructureChain<X, Y, Z...>>::type Device::getAndroidHardwareBufferPropertiesANDROID( const struct AHardwareBuffer & buffer, Dispatch const &d ) const
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID& properties = structureChain.template get<VULKAN_HPP_NAMESPACE::AndroidHardwareBufferPropertiesANDROID>();
+ Result result = static_cast<Result>( d.vkGetAndroidHardwareBufferPropertiesANDROID( m_device, buffer, reinterpret_cast<VkAndroidHardwareBufferPropertiesANDROID*>( &properties ) ) );
+ return createResultValue( result, structureChain, VULKAN_HPP_NAMESPACE_STRING"::Device::getAndroidHardwareBufferPropertiesANDROID" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE DeviceAddress Device::getBufferAddress( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<DeviceAddress>( d.vkGetBufferDeviceAddress( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE DeviceAddress Device::getBufferAddress( const BufferDeviceAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetBufferDeviceAddress( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE DeviceAddress Device::getBufferAddressEXT( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<DeviceAddress>( d.vkGetBufferDeviceAddressEXT( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE DeviceAddress Device::getBufferAddressEXT( const BufferDeviceAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetBufferDeviceAddressEXT( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE DeviceAddress Device::getBufferAddressKHR( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<DeviceAddress>( d.vkGetBufferDeviceAddressKHR( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE DeviceAddress Device::getBufferAddressKHR( const BufferDeviceAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetBufferDeviceAddressKHR( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getBufferMemoryRequirements( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::MemoryRequirements* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetBufferMemoryRequirements( m_device, static_cast<VkBuffer>( buffer ), reinterpret_cast<VkMemoryRequirements*>( pMemoryRequirements ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements Device::getBufferMemoryRequirements( VULKAN_HPP_NAMESPACE::Buffer buffer, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::MemoryRequirements memoryRequirements;
+ d.vkGetBufferMemoryRequirements( m_device, static_cast<VkBuffer>( buffer ), reinterpret_cast<VkMemoryRequirements*>( &memoryRequirements ) );
+ return memoryRequirements;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getBufferMemoryRequirements2( const VULKAN_HPP_NAMESPACE::BufferMemoryRequirementsInfo2* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetBufferMemoryRequirements2( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( pInfo ), reinterpret_cast<VkMemoryRequirements2*>( pMemoryRequirements ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements2 Device::getBufferMemoryRequirements2( const BufferMemoryRequirementsInfo2 & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2 memoryRequirements;
+ d.vkGetBufferMemoryRequirements2( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+ return memoryRequirements;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> Device::getBufferMemoryRequirements2( const BufferMemoryRequirementsInfo2 & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2& memoryRequirements = structureChain.template get<VULKAN_HPP_NAMESPACE::MemoryRequirements2>();
+ d.vkGetBufferMemoryRequirements2( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getBufferMemoryRequirements2KHR( const VULKAN_HPP_NAMESPACE::BufferMemoryRequirementsInfo2* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetBufferMemoryRequirements2KHR( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( pInfo ), reinterpret_cast<VkMemoryRequirements2*>( pMemoryRequirements ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements2 Device::getBufferMemoryRequirements2KHR( const BufferMemoryRequirementsInfo2 & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2 memoryRequirements;
+ d.vkGetBufferMemoryRequirements2KHR( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+ return memoryRequirements;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> Device::getBufferMemoryRequirements2KHR( const BufferMemoryRequirementsInfo2 & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2& memoryRequirements = structureChain.template get<VULKAN_HPP_NAMESPACE::MemoryRequirements2>();
+ d.vkGetBufferMemoryRequirements2KHR( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint64_t Device::getBufferOpaqueCaptureAddress( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetBufferOpaqueCaptureAddress( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint64_t Device::getBufferOpaqueCaptureAddress( const BufferDeviceAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetBufferOpaqueCaptureAddress( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint64_t Device::getBufferOpaqueCaptureAddressKHR( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetBufferOpaqueCaptureAddressKHR( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint64_t Device::getBufferOpaqueCaptureAddressKHR( const BufferDeviceAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetBufferOpaqueCaptureAddressKHR( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getCalibratedTimestampsEXT( uint32_t timestampCount, const VULKAN_HPP_NAMESPACE::CalibratedTimestampInfoEXT* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetCalibratedTimestampsEXT( m_device, timestampCount, reinterpret_cast<const VkCalibratedTimestampInfoEXT*>( pTimestampInfos ), pTimestamps, pMaxDeviation ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<uint64_t>::type Device::getCalibratedTimestampsEXT( ArrayProxy<const VULKAN_HPP_NAMESPACE::CalibratedTimestampInfoEXT> timestampInfos, ArrayProxy<uint64_t> timestamps, Dispatch const &d ) const
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( timestampInfos.size() == timestamps.size() );
+#else
+ if ( timestampInfos.size() != timestamps.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkDevice::getCalibratedTimestampsEXT: timestampInfos.size() != timestamps.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+ uint64_t maxDeviation;
+ Result result = static_cast<Result>( d.vkGetCalibratedTimestampsEXT( m_device, timestampInfos.size() , reinterpret_cast<const VkCalibratedTimestampInfoEXT*>( timestampInfos.data() ), timestamps.data(), &maxDeviation ) );
+ return createResultValue( result, maxDeviation, VULKAN_HPP_NAMESPACE_STRING"::Device::getCalibratedTimestampsEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getDescriptorSetLayoutSupport( const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo* pCreateInfo, VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport* pSupport, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetDescriptorSetLayoutSupport( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( pCreateInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( pSupport ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport Device::getDescriptorSetLayoutSupport( const DescriptorSetLayoutCreateInfo & createInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport support;
+ d.vkGetDescriptorSetLayoutSupport( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( &createInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( &support ) );
+ return support;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> Device::getDescriptorSetLayoutSupport( const DescriptorSetLayoutCreateInfo & createInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport& support = structureChain.template get<VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport>();
+ d.vkGetDescriptorSetLayoutSupport( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( &createInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( &support ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getDescriptorSetLayoutSupportKHR( const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo* pCreateInfo, VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport* pSupport, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetDescriptorSetLayoutSupportKHR( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( pCreateInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( pSupport ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport Device::getDescriptorSetLayoutSupportKHR( const DescriptorSetLayoutCreateInfo & createInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport support;
+ d.vkGetDescriptorSetLayoutSupportKHR( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( &createInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( &support ) );
+ return support;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> Device::getDescriptorSetLayoutSupportKHR( const DescriptorSetLayoutCreateInfo & createInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport& support = structureChain.template get<VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport>();
+ d.vkGetDescriptorSetLayoutSupportKHR( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( &createInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( &support ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getGroupPeerMemoryFeatures( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags* pPeerMemoryFeatures, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetDeviceGroupPeerMemoryFeatures( m_device, heapIndex, localDeviceIndex, remoteDeviceIndex, reinterpret_cast<VkPeerMemoryFeatureFlags*>( pPeerMemoryFeatures ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags Device::getGroupPeerMemoryFeatures( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags peerMemoryFeatures;
+ d.vkGetDeviceGroupPeerMemoryFeatures( m_device, heapIndex, localDeviceIndex, remoteDeviceIndex, reinterpret_cast<VkPeerMemoryFeatureFlags*>( &peerMemoryFeatures ) );
+ return peerMemoryFeatures;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getGroupPeerMemoryFeaturesKHR( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags* pPeerMemoryFeatures, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetDeviceGroupPeerMemoryFeaturesKHR( m_device, heapIndex, localDeviceIndex, remoteDeviceIndex, reinterpret_cast<VkPeerMemoryFeatureFlags*>( pPeerMemoryFeatures ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags Device::getGroupPeerMemoryFeaturesKHR( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags peerMemoryFeatures;
+ d.vkGetDeviceGroupPeerMemoryFeaturesKHR( m_device, heapIndex, localDeviceIndex, remoteDeviceIndex, reinterpret_cast<VkPeerMemoryFeatureFlags*>( &peerMemoryFeatures ) );
+ return peerMemoryFeatures;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getGroupPresentCapabilitiesKHR( VULKAN_HPP_NAMESPACE::DeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetDeviceGroupPresentCapabilitiesKHR( m_device, reinterpret_cast<VkDeviceGroupPresentCapabilitiesKHR*>( pDeviceGroupPresentCapabilities ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DeviceGroupPresentCapabilitiesKHR>::type Device::getGroupPresentCapabilitiesKHR(Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DeviceGroupPresentCapabilitiesKHR deviceGroupPresentCapabilities;
+ Result result = static_cast<Result>( d.vkGetDeviceGroupPresentCapabilitiesKHR( m_device, reinterpret_cast<VkDeviceGroupPresentCapabilitiesKHR*>( &deviceGroupPresentCapabilities ) ) );
+ return createResultValue( result, deviceGroupPresentCapabilities, VULKAN_HPP_NAMESPACE_STRING"::Device::getGroupPresentCapabilitiesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getGroupSurfacePresentModes2EXT( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR* pModes, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetDeviceGroupSurfacePresentModes2EXT( m_device, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( pSurfaceInfo ), reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR*>( pModes ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR>::type Device::getGroupSurfacePresentModes2EXT( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR modes;
+ Result result = static_cast<Result>( d.vkGetDeviceGroupSurfacePresentModes2EXT( m_device, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR*>( &modes ) ) );
+ return createResultValue( result, modes, VULKAN_HPP_NAMESPACE_STRING"::Device::getGroupSurfacePresentModes2EXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getGroupSurfacePresentModesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR* pModes, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetDeviceGroupSurfacePresentModesKHR( m_device, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR*>( pModes ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR>::type Device::getGroupSurfacePresentModesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR modes;
+ Result result = static_cast<Result>( d.vkGetDeviceGroupSurfacePresentModesKHR( m_device, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR*>( &modes ) ) );
+ return createResultValue( result, modes, VULKAN_HPP_NAMESPACE_STRING"::Device::getGroupSurfacePresentModesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getMemoryCommitment( VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize* pCommittedMemoryInBytes, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetDeviceMemoryCommitment( m_device, static_cast<VkDeviceMemory>( memory ), reinterpret_cast<VkDeviceSize*>( pCommittedMemoryInBytes ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::DeviceSize Device::getMemoryCommitment( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::DeviceSize committedMemoryInBytes;
+ d.vkGetDeviceMemoryCommitment( m_device, static_cast<VkDeviceMemory>( memory ), reinterpret_cast<VkDeviceSize*>( &committedMemoryInBytes ) );
+ return committedMemoryInBytes;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint64_t Device::getMemoryOpaqueCaptureAddress( const VULKAN_HPP_NAMESPACE::DeviceMemoryOpaqueCaptureAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetDeviceMemoryOpaqueCaptureAddress( m_device, reinterpret_cast<const VkDeviceMemoryOpaqueCaptureAddressInfo*>( pInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint64_t Device::getMemoryOpaqueCaptureAddress( const DeviceMemoryOpaqueCaptureAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetDeviceMemoryOpaqueCaptureAddress( m_device, reinterpret_cast<const VkDeviceMemoryOpaqueCaptureAddressInfo*>( &info ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint64_t Device::getMemoryOpaqueCaptureAddressKHR( const VULKAN_HPP_NAMESPACE::DeviceMemoryOpaqueCaptureAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetDeviceMemoryOpaqueCaptureAddressKHR( m_device, reinterpret_cast<const VkDeviceMemoryOpaqueCaptureAddressInfo*>( pInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint64_t Device::getMemoryOpaqueCaptureAddressKHR( const DeviceMemoryOpaqueCaptureAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetDeviceMemoryOpaqueCaptureAddressKHR( m_device, reinterpret_cast<const VkDeviceMemoryOpaqueCaptureAddressInfo*>( &info ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE PFN_vkVoidFunction Device::getProcAddr( const char* pName, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetDeviceProcAddr( m_device, pName );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE PFN_vkVoidFunction Device::getProcAddr( const std::string & name, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetDeviceProcAddr( m_device, name.c_str() );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getQueue( uint32_t queueFamilyIndex, uint32_t queueIndex, VULKAN_HPP_NAMESPACE::Queue* pQueue, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetDeviceQueue( m_device, queueFamilyIndex, queueIndex, reinterpret_cast<VkQueue*>( pQueue ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::Queue Device::getQueue( uint32_t queueFamilyIndex, uint32_t queueIndex, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::Queue queue;
+ d.vkGetDeviceQueue( m_device, queueFamilyIndex, queueIndex, reinterpret_cast<VkQueue*>( &queue ) );
+ return queue;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getQueue2( const VULKAN_HPP_NAMESPACE::DeviceQueueInfo2* pQueueInfo, VULKAN_HPP_NAMESPACE::Queue* pQueue, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetDeviceQueue2( m_device, reinterpret_cast<const VkDeviceQueueInfo2*>( pQueueInfo ), reinterpret_cast<VkQueue*>( pQueue ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::Queue Device::getQueue2( const DeviceQueueInfo2 & queueInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::Queue queue;
+ d.vkGetDeviceQueue2( m_device, reinterpret_cast<const VkDeviceQueueInfo2*>( &queueInfo ), reinterpret_cast<VkQueue*>( &queue ) );
+ return queue;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getEventStatus( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetEventStatus( m_device, static_cast<VkEvent>( event ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getEventStatus( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkGetEventStatus( m_device, static_cast<VkEvent>( event ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getEventStatus", { Result::eEventSet, Result::eEventReset } );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getFenceFdKHR( const VULKAN_HPP_NAMESPACE::FenceGetFdInfoKHR* pGetFdInfo, int* pFd, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetFenceFdKHR( m_device, reinterpret_cast<const VkFenceGetFdInfoKHR*>( pGetFdInfo ), pFd ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<int>::type Device::getFenceFdKHR( const FenceGetFdInfoKHR & getFdInfo, Dispatch const &d ) const
+ {
+ int fd;
+ Result result = static_cast<Result>( d.vkGetFenceFdKHR( m_device, reinterpret_cast<const VkFenceGetFdInfoKHR*>( &getFdInfo ), &fd ) );
+ return createResultValue( result, fd, VULKAN_HPP_NAMESPACE_STRING"::Device::getFenceFdKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getFenceStatus( VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetFenceStatus( m_device, static_cast<VkFence>( fence ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getFenceStatus( VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkGetFenceStatus( m_device, static_cast<VkFence>( fence ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getFenceStatus", { Result::eSuccess, Result::eNotReady } );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getFenceWin32HandleKHR( const VULKAN_HPP_NAMESPACE::FenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetFenceWin32HandleKHR( m_device, reinterpret_cast<const VkFenceGetWin32HandleInfoKHR*>( pGetWin32HandleInfo ), pHandle ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<HANDLE>::type Device::getFenceWin32HandleKHR( const FenceGetWin32HandleInfoKHR & getWin32HandleInfo, Dispatch const &d ) const
+ {
+ HANDLE handle;
+ Result result = static_cast<Result>( d.vkGetFenceWin32HandleKHR( m_device, reinterpret_cast<const VkFenceGetWin32HandleInfoKHR*>( &getWin32HandleInfo ), &handle ) );
+ return createResultValue( result, handle, VULKAN_HPP_NAMESPACE_STRING"::Device::getFenceWin32HandleKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getImageDrmFormatModifierPropertiesEXT( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetImageDrmFormatModifierPropertiesEXT( m_device, static_cast<VkImage>( image ), reinterpret_cast<VkImageDrmFormatModifierPropertiesEXT*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT>::type Device::getImageDrmFormatModifierPropertiesEXT( VULKAN_HPP_NAMESPACE::Image image, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT properties;
+ Result result = static_cast<Result>( d.vkGetImageDrmFormatModifierPropertiesEXT( m_device, static_cast<VkImage>( image ), reinterpret_cast<VkImageDrmFormatModifierPropertiesEXT*>( &properties ) ) );
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::Device::getImageDrmFormatModifierPropertiesEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getImageMemoryRequirements( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::MemoryRequirements* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetImageMemoryRequirements( m_device, static_cast<VkImage>( image ), reinterpret_cast<VkMemoryRequirements*>( pMemoryRequirements ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements Device::getImageMemoryRequirements( VULKAN_HPP_NAMESPACE::Image image, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::MemoryRequirements memoryRequirements;
+ d.vkGetImageMemoryRequirements( m_device, static_cast<VkImage>( image ), reinterpret_cast<VkMemoryRequirements*>( &memoryRequirements ) );
+ return memoryRequirements;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getImageMemoryRequirements2( const VULKAN_HPP_NAMESPACE::ImageMemoryRequirementsInfo2* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetImageMemoryRequirements2( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( pInfo ), reinterpret_cast<VkMemoryRequirements2*>( pMemoryRequirements ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements2 Device::getImageMemoryRequirements2( const ImageMemoryRequirementsInfo2 & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2 memoryRequirements;
+ d.vkGetImageMemoryRequirements2( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+ return memoryRequirements;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> Device::getImageMemoryRequirements2( const ImageMemoryRequirementsInfo2 & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2& memoryRequirements = structureChain.template get<VULKAN_HPP_NAMESPACE::MemoryRequirements2>();
+ d.vkGetImageMemoryRequirements2( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getImageMemoryRequirements2KHR( const VULKAN_HPP_NAMESPACE::ImageMemoryRequirementsInfo2* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetImageMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( pInfo ), reinterpret_cast<VkMemoryRequirements2*>( pMemoryRequirements ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements2 Device::getImageMemoryRequirements2KHR( const ImageMemoryRequirementsInfo2 & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2 memoryRequirements;
+ d.vkGetImageMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+ return memoryRequirements;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> Device::getImageMemoryRequirements2KHR( const ImageMemoryRequirementsInfo2 & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::MemoryRequirements2& memoryRequirements = structureChain.template get<VULKAN_HPP_NAMESPACE::MemoryRequirements2>();
+ d.vkGetImageMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getImageSparseMemoryRequirements( VULKAN_HPP_NAMESPACE::Image image, uint32_t* pSparseMemoryRequirementCount, VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements* pSparseMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetImageSparseMemoryRequirements( m_device, static_cast<VkImage>( image ), pSparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements*>( pSparseMemoryRequirements ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageMemoryRequirements,Allocator> Device::getImageSparseMemoryRequirements( VULKAN_HPP_NAMESPACE::Image image, Dispatch const &d ) const
+ {
+ std::vector<SparseImageMemoryRequirements,Allocator> sparseMemoryRequirements;
+ uint32_t sparseMemoryRequirementCount;
+ d.vkGetImageSparseMemoryRequirements( m_device, static_cast<VkImage>( image ), &sparseMemoryRequirementCount, nullptr );
+ sparseMemoryRequirements.resize( sparseMemoryRequirementCount );
+ d.vkGetImageSparseMemoryRequirements( m_device, static_cast<VkImage>( image ), &sparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements*>( sparseMemoryRequirements.data() ) );
+ return sparseMemoryRequirements;
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageMemoryRequirements,Allocator> Device::getImageSparseMemoryRequirements( VULKAN_HPP_NAMESPACE::Image image, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<SparseImageMemoryRequirements,Allocator> sparseMemoryRequirements( vectorAllocator );
+ uint32_t sparseMemoryRequirementCount;
+ d.vkGetImageSparseMemoryRequirements( m_device, static_cast<VkImage>( image ), &sparseMemoryRequirementCount, nullptr );
+ sparseMemoryRequirements.resize( sparseMemoryRequirementCount );
+ d.vkGetImageSparseMemoryRequirements( m_device, static_cast<VkImage>( image ), &sparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements*>( sparseMemoryRequirements.data() ) );
+ return sparseMemoryRequirements;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getImageSparseMemoryRequirements2( const VULKAN_HPP_NAMESPACE::ImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements2* pSparseMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetImageSparseMemoryRequirements2( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( pInfo ), pSparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( pSparseMemoryRequirements ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageMemoryRequirements2,Allocator> Device::getImageSparseMemoryRequirements2( const ImageSparseMemoryRequirementsInfo2 & info, Dispatch const &d ) const
+ {
+ std::vector<SparseImageMemoryRequirements2,Allocator> sparseMemoryRequirements;
+ uint32_t sparseMemoryRequirementCount;
+ d.vkGetImageSparseMemoryRequirements2( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, nullptr );
+ sparseMemoryRequirements.resize( sparseMemoryRequirementCount );
+ d.vkGetImageSparseMemoryRequirements2( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( sparseMemoryRequirements.data() ) );
+ return sparseMemoryRequirements;
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageMemoryRequirements2,Allocator> Device::getImageSparseMemoryRequirements2( const ImageSparseMemoryRequirementsInfo2 & info, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<SparseImageMemoryRequirements2,Allocator> sparseMemoryRequirements( vectorAllocator );
+ uint32_t sparseMemoryRequirementCount;
+ d.vkGetImageSparseMemoryRequirements2( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, nullptr );
+ sparseMemoryRequirements.resize( sparseMemoryRequirementCount );
+ d.vkGetImageSparseMemoryRequirements2( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( sparseMemoryRequirements.data() ) );
+ return sparseMemoryRequirements;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getImageSparseMemoryRequirements2KHR( const VULKAN_HPP_NAMESPACE::ImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements2* pSparseMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetImageSparseMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( pInfo ), pSparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( pSparseMemoryRequirements ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageMemoryRequirements2,Allocator> Device::getImageSparseMemoryRequirements2KHR( const ImageSparseMemoryRequirementsInfo2 & info, Dispatch const &d ) const
+ {
+ std::vector<SparseImageMemoryRequirements2,Allocator> sparseMemoryRequirements;
+ uint32_t sparseMemoryRequirementCount;
+ d.vkGetImageSparseMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, nullptr );
+ sparseMemoryRequirements.resize( sparseMemoryRequirementCount );
+ d.vkGetImageSparseMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( sparseMemoryRequirements.data() ) );
+ return sparseMemoryRequirements;
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageMemoryRequirements2,Allocator> Device::getImageSparseMemoryRequirements2KHR( const ImageSparseMemoryRequirementsInfo2 & info, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<SparseImageMemoryRequirements2,Allocator> sparseMemoryRequirements( vectorAllocator );
+ uint32_t sparseMemoryRequirementCount;
+ d.vkGetImageSparseMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, nullptr );
+ sparseMemoryRequirements.resize( sparseMemoryRequirementCount );
+ d.vkGetImageSparseMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( sparseMemoryRequirements.data() ) );
+ return sparseMemoryRequirements;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getImageSubresourceLayout( VULKAN_HPP_NAMESPACE::Image image, const VULKAN_HPP_NAMESPACE::ImageSubresource* pSubresource, VULKAN_HPP_NAMESPACE::SubresourceLayout* pLayout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetImageSubresourceLayout( m_device, static_cast<VkImage>( image ), reinterpret_cast<const VkImageSubresource*>( pSubresource ), reinterpret_cast<VkSubresourceLayout*>( pLayout ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::SubresourceLayout Device::getImageSubresourceLayout( VULKAN_HPP_NAMESPACE::Image image, const ImageSubresource & subresource, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::SubresourceLayout layout;
+ d.vkGetImageSubresourceLayout( m_device, static_cast<VkImage>( image ), reinterpret_cast<const VkImageSubresource*>( &subresource ), reinterpret_cast<VkSubresourceLayout*>( &layout ) );
+ return layout;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint32_t Device::getImageViewHandleNVX( const VULKAN_HPP_NAMESPACE::ImageViewHandleInfoNVX* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetImageViewHandleNVX( m_device, reinterpret_cast<const VkImageViewHandleInfoNVX*>( pInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint32_t Device::getImageViewHandleNVX( const ImageViewHandleInfoNVX & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetImageViewHandleNVX( m_device, reinterpret_cast<const VkImageViewHandleInfoNVX*>( &info ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getMemoryAndroidHardwareBufferANDROID( const VULKAN_HPP_NAMESPACE::MemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetMemoryAndroidHardwareBufferANDROID( m_device, reinterpret_cast<const VkMemoryGetAndroidHardwareBufferInfoANDROID*>( pInfo ), pBuffer ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<struct AHardwareBuffer*>::type Device::getMemoryAndroidHardwareBufferANDROID( const MemoryGetAndroidHardwareBufferInfoANDROID & info, Dispatch const &d ) const
+ {
+ struct AHardwareBuffer* buffer;
+ Result result = static_cast<Result>( d.vkGetMemoryAndroidHardwareBufferANDROID( m_device, reinterpret_cast<const VkMemoryGetAndroidHardwareBufferInfoANDROID*>( &info ), &buffer ) );
+ return createResultValue( result, buffer, VULKAN_HPP_NAMESPACE_STRING"::Device::getMemoryAndroidHardwareBufferANDROID" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getMemoryFdKHR( const VULKAN_HPP_NAMESPACE::MemoryGetFdInfoKHR* pGetFdInfo, int* pFd, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetMemoryFdKHR( m_device, reinterpret_cast<const VkMemoryGetFdInfoKHR*>( pGetFdInfo ), pFd ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<int>::type Device::getMemoryFdKHR( const MemoryGetFdInfoKHR & getFdInfo, Dispatch const &d ) const
+ {
+ int fd;
+ Result result = static_cast<Result>( d.vkGetMemoryFdKHR( m_device, reinterpret_cast<const VkMemoryGetFdInfoKHR*>( &getFdInfo ), &fd ) );
+ return createResultValue( result, fd, VULKAN_HPP_NAMESPACE_STRING"::Device::getMemoryFdKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getMemoryFdPropertiesKHR( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, int fd, VULKAN_HPP_NAMESPACE::MemoryFdPropertiesKHR* pMemoryFdProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetMemoryFdPropertiesKHR( m_device, static_cast<VkExternalMemoryHandleTypeFlagBits>( handleType ), fd, reinterpret_cast<VkMemoryFdPropertiesKHR*>( pMemoryFdProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::MemoryFdPropertiesKHR>::type Device::getMemoryFdPropertiesKHR( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, int fd, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::MemoryFdPropertiesKHR memoryFdProperties;
+ Result result = static_cast<Result>( d.vkGetMemoryFdPropertiesKHR( m_device, static_cast<VkExternalMemoryHandleTypeFlagBits>( handleType ), fd, reinterpret_cast<VkMemoryFdPropertiesKHR*>( &memoryFdProperties ) ) );
+ return createResultValue( result, memoryFdProperties, VULKAN_HPP_NAMESPACE_STRING"::Device::getMemoryFdPropertiesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getMemoryHostPointerPropertiesEXT( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VULKAN_HPP_NAMESPACE::MemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetMemoryHostPointerPropertiesEXT( m_device, static_cast<VkExternalMemoryHandleTypeFlagBits>( handleType ), pHostPointer, reinterpret_cast<VkMemoryHostPointerPropertiesEXT*>( pMemoryHostPointerProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::MemoryHostPointerPropertiesEXT>::type Device::getMemoryHostPointerPropertiesEXT( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::MemoryHostPointerPropertiesEXT memoryHostPointerProperties;
+ Result result = static_cast<Result>( d.vkGetMemoryHostPointerPropertiesEXT( m_device, static_cast<VkExternalMemoryHandleTypeFlagBits>( handleType ), pHostPointer, reinterpret_cast<VkMemoryHostPointerPropertiesEXT*>( &memoryHostPointerProperties ) ) );
+ return createResultValue( result, memoryHostPointerProperties, VULKAN_HPP_NAMESPACE_STRING"::Device::getMemoryHostPointerPropertiesEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getMemoryWin32HandleKHR( const VULKAN_HPP_NAMESPACE::MemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetMemoryWin32HandleKHR( m_device, reinterpret_cast<const VkMemoryGetWin32HandleInfoKHR*>( pGetWin32HandleInfo ), pHandle ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<HANDLE>::type Device::getMemoryWin32HandleKHR( const MemoryGetWin32HandleInfoKHR & getWin32HandleInfo, Dispatch const &d ) const
+ {
+ HANDLE handle;
+ Result result = static_cast<Result>( d.vkGetMemoryWin32HandleKHR( m_device, reinterpret_cast<const VkMemoryGetWin32HandleInfoKHR*>( &getWin32HandleInfo ), &handle ) );
+ return createResultValue( result, handle, VULKAN_HPP_NAMESPACE_STRING"::Device::getMemoryWin32HandleKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getMemoryWin32HandleNV( VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetMemoryWin32HandleNV( m_device, static_cast<VkDeviceMemory>( memory ), static_cast<VkExternalMemoryHandleTypeFlagsNV>( handleType ), pHandle ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<HANDLE>::type Device::getMemoryWin32HandleNV( VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV handleType, Dispatch const &d ) const
+ {
+ HANDLE handle;
+ Result result = static_cast<Result>( d.vkGetMemoryWin32HandleNV( m_device, static_cast<VkDeviceMemory>( memory ), static_cast<VkExternalMemoryHandleTypeFlagsNV>( handleType ), &handle ) );
+ return createResultValue( result, handle, VULKAN_HPP_NAMESPACE_STRING"::Device::getMemoryWin32HandleNV" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getMemoryWin32HandlePropertiesKHR( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VULKAN_HPP_NAMESPACE::MemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetMemoryWin32HandlePropertiesKHR( m_device, static_cast<VkExternalMemoryHandleTypeFlagBits>( handleType ), handle, reinterpret_cast<VkMemoryWin32HandlePropertiesKHR*>( pMemoryWin32HandleProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::MemoryWin32HandlePropertiesKHR>::type Device::getMemoryWin32HandlePropertiesKHR( VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::MemoryWin32HandlePropertiesKHR memoryWin32HandleProperties;
+ Result result = static_cast<Result>( d.vkGetMemoryWin32HandlePropertiesKHR( m_device, static_cast<VkExternalMemoryHandleTypeFlagBits>( handleType ), handle, reinterpret_cast<VkMemoryWin32HandlePropertiesKHR*>( &memoryWin32HandleProperties ) ) );
+ return createResultValue( result, memoryWin32HandleProperties, VULKAN_HPP_NAMESPACE_STRING"::Device::getMemoryWin32HandlePropertiesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getPastPresentationTimingGOOGLE( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VULKAN_HPP_NAMESPACE::PastPresentationTimingGOOGLE* pPresentationTimings, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPastPresentationTimingGOOGLE( m_device, static_cast<VkSwapchainKHR>( swapchain ), pPresentationTimingCount, reinterpret_cast<VkPastPresentationTimingGOOGLE*>( pPresentationTimings ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PastPresentationTimingGOOGLE,Allocator>>::type Device::getPastPresentationTimingGOOGLE( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d ) const
+ {
+ std::vector<PastPresentationTimingGOOGLE,Allocator> presentationTimings;
+ uint32_t presentationTimingCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPastPresentationTimingGOOGLE( m_device, static_cast<VkSwapchainKHR>( swapchain ), &presentationTimingCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && presentationTimingCount )
+ {
+ presentationTimings.resize( presentationTimingCount );
+ result = static_cast<Result>( d.vkGetPastPresentationTimingGOOGLE( m_device, static_cast<VkSwapchainKHR>( swapchain ), &presentationTimingCount, reinterpret_cast<VkPastPresentationTimingGOOGLE*>( presentationTimings.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( presentationTimingCount <= presentationTimings.size() );
+ presentationTimings.resize( presentationTimingCount );
+ }
+ return createResultValue( result, presentationTimings, VULKAN_HPP_NAMESPACE_STRING"::Device::getPastPresentationTimingGOOGLE" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PastPresentationTimingGOOGLE,Allocator>>::type Device::getPastPresentationTimingGOOGLE( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PastPresentationTimingGOOGLE,Allocator> presentationTimings( vectorAllocator );
+ uint32_t presentationTimingCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPastPresentationTimingGOOGLE( m_device, static_cast<VkSwapchainKHR>( swapchain ), &presentationTimingCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && presentationTimingCount )
+ {
+ presentationTimings.resize( presentationTimingCount );
+ result = static_cast<Result>( d.vkGetPastPresentationTimingGOOGLE( m_device, static_cast<VkSwapchainKHR>( swapchain ), &presentationTimingCount, reinterpret_cast<VkPastPresentationTimingGOOGLE*>( presentationTimings.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( presentationTimingCount <= presentationTimings.size() );
+ presentationTimings.resize( presentationTimingCount );
+ }
+ return createResultValue( result, presentationTimings, VULKAN_HPP_NAMESPACE_STRING"::Device::getPastPresentationTimingGOOGLE" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getPerformanceParameterINTEL( VULKAN_HPP_NAMESPACE::PerformanceParameterTypeINTEL parameter, VULKAN_HPP_NAMESPACE::PerformanceValueINTEL* pValue, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPerformanceParameterINTEL( m_device, static_cast<VkPerformanceParameterTypeINTEL>( parameter ), reinterpret_cast<VkPerformanceValueINTEL*>( pValue ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::PerformanceValueINTEL>::type Device::getPerformanceParameterINTEL( VULKAN_HPP_NAMESPACE::PerformanceParameterTypeINTEL parameter, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::PerformanceValueINTEL value;
+ Result result = static_cast<Result>( d.vkGetPerformanceParameterINTEL( m_device, static_cast<VkPerformanceParameterTypeINTEL>( parameter ), reinterpret_cast<VkPerformanceValueINTEL*>( &value ) ) );
+ return createResultValue( result, value, VULKAN_HPP_NAMESPACE_STRING"::Device::getPerformanceParameterINTEL" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getPipelineCacheData( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, size_t* pDataSize, void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPipelineCacheData( m_device, static_cast<VkPipelineCache>( pipelineCache ), pDataSize, pData ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<uint8_t,Allocator>>::type Device::getPipelineCacheData( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, Dispatch const &d ) const
+ {
+ std::vector<uint8_t,Allocator> data;
+ size_t dataSize;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPipelineCacheData( m_device, static_cast<VkPipelineCache>( pipelineCache ), &dataSize, nullptr ) );
+ if ( ( result == Result::eSuccess ) && dataSize )
+ {
+ data.resize( dataSize );
+ result = static_cast<Result>( d.vkGetPipelineCacheData( m_device, static_cast<VkPipelineCache>( pipelineCache ), &dataSize, reinterpret_cast<void*>( data.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( dataSize <= data.size() );
+ data.resize( dataSize );
+ }
+ return createResultValue( result, data, VULKAN_HPP_NAMESPACE_STRING"::Device::getPipelineCacheData" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<uint8_t,Allocator>>::type Device::getPipelineCacheData( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<uint8_t,Allocator> data( vectorAllocator );
+ size_t dataSize;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPipelineCacheData( m_device, static_cast<VkPipelineCache>( pipelineCache ), &dataSize, nullptr ) );
+ if ( ( result == Result::eSuccess ) && dataSize )
+ {
+ data.resize( dataSize );
+ result = static_cast<Result>( d.vkGetPipelineCacheData( m_device, static_cast<VkPipelineCache>( pipelineCache ), &dataSize, reinterpret_cast<void*>( data.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( dataSize <= data.size() );
+ data.resize( dataSize );
+ }
+ return createResultValue( result, data, VULKAN_HPP_NAMESPACE_STRING"::Device::getPipelineCacheData" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getPipelineExecutableInternalRepresentationsKHR( const VULKAN_HPP_NAMESPACE::PipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VULKAN_HPP_NAMESPACE::PipelineExecutableInternalRepresentationKHR* pInternalRepresentations, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPipelineExecutableInternalRepresentationsKHR( m_device, reinterpret_cast<const VkPipelineExecutableInfoKHR*>( pExecutableInfo ), pInternalRepresentationCount, reinterpret_cast<VkPipelineExecutableInternalRepresentationKHR*>( pInternalRepresentations ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PipelineExecutableInternalRepresentationKHR,Allocator>>::type Device::getPipelineExecutableInternalRepresentationsKHR( const PipelineExecutableInfoKHR & executableInfo, Dispatch const &d ) const
+ {
+ std::vector<PipelineExecutableInternalRepresentationKHR,Allocator> internalRepresentations;
+ uint32_t internalRepresentationCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPipelineExecutableInternalRepresentationsKHR( m_device, reinterpret_cast<const VkPipelineExecutableInfoKHR*>( &executableInfo ), &internalRepresentationCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && internalRepresentationCount )
+ {
+ internalRepresentations.resize( internalRepresentationCount );
+ result = static_cast<Result>( d.vkGetPipelineExecutableInternalRepresentationsKHR( m_device, reinterpret_cast<const VkPipelineExecutableInfoKHR*>( &executableInfo ), &internalRepresentationCount, reinterpret_cast<VkPipelineExecutableInternalRepresentationKHR*>( internalRepresentations.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( internalRepresentationCount <= internalRepresentations.size() );
+ internalRepresentations.resize( internalRepresentationCount );
+ }
+ return createResultValue( result, internalRepresentations, VULKAN_HPP_NAMESPACE_STRING"::Device::getPipelineExecutableInternalRepresentationsKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PipelineExecutableInternalRepresentationKHR,Allocator>>::type Device::getPipelineExecutableInternalRepresentationsKHR( const PipelineExecutableInfoKHR & executableInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PipelineExecutableInternalRepresentationKHR,Allocator> internalRepresentations( vectorAllocator );
+ uint32_t internalRepresentationCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPipelineExecutableInternalRepresentationsKHR( m_device, reinterpret_cast<const VkPipelineExecutableInfoKHR*>( &executableInfo ), &internalRepresentationCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && internalRepresentationCount )
+ {
+ internalRepresentations.resize( internalRepresentationCount );
+ result = static_cast<Result>( d.vkGetPipelineExecutableInternalRepresentationsKHR( m_device, reinterpret_cast<const VkPipelineExecutableInfoKHR*>( &executableInfo ), &internalRepresentationCount, reinterpret_cast<VkPipelineExecutableInternalRepresentationKHR*>( internalRepresentations.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( internalRepresentationCount <= internalRepresentations.size() );
+ internalRepresentations.resize( internalRepresentationCount );
+ }
+ return createResultValue( result, internalRepresentations, VULKAN_HPP_NAMESPACE_STRING"::Device::getPipelineExecutableInternalRepresentationsKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getPipelineExecutablePropertiesKHR( const VULKAN_HPP_NAMESPACE::PipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VULKAN_HPP_NAMESPACE::PipelineExecutablePropertiesKHR* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPipelineExecutablePropertiesKHR( m_device, reinterpret_cast<const VkPipelineInfoKHR*>( pPipelineInfo ), pExecutableCount, reinterpret_cast<VkPipelineExecutablePropertiesKHR*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PipelineExecutablePropertiesKHR,Allocator>>::type Device::getPipelineExecutablePropertiesKHR( const PipelineInfoKHR & pipelineInfo, Dispatch const &d ) const
+ {
+ std::vector<PipelineExecutablePropertiesKHR,Allocator> properties;
+ uint32_t executableCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPipelineExecutablePropertiesKHR( m_device, reinterpret_cast<const VkPipelineInfoKHR*>( &pipelineInfo ), &executableCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && executableCount )
+ {
+ properties.resize( executableCount );
+ result = static_cast<Result>( d.vkGetPipelineExecutablePropertiesKHR( m_device, reinterpret_cast<const VkPipelineInfoKHR*>( &pipelineInfo ), &executableCount, reinterpret_cast<VkPipelineExecutablePropertiesKHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( executableCount <= properties.size() );
+ properties.resize( executableCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::Device::getPipelineExecutablePropertiesKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PipelineExecutablePropertiesKHR,Allocator>>::type Device::getPipelineExecutablePropertiesKHR( const PipelineInfoKHR & pipelineInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PipelineExecutablePropertiesKHR,Allocator> properties( vectorAllocator );
+ uint32_t executableCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPipelineExecutablePropertiesKHR( m_device, reinterpret_cast<const VkPipelineInfoKHR*>( &pipelineInfo ), &executableCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && executableCount )
+ {
+ properties.resize( executableCount );
+ result = static_cast<Result>( d.vkGetPipelineExecutablePropertiesKHR( m_device, reinterpret_cast<const VkPipelineInfoKHR*>( &pipelineInfo ), &executableCount, reinterpret_cast<VkPipelineExecutablePropertiesKHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( executableCount <= properties.size() );
+ properties.resize( executableCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::Device::getPipelineExecutablePropertiesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getPipelineExecutableStatisticsKHR( const VULKAN_HPP_NAMESPACE::PipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticKHR* pStatistics, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPipelineExecutableStatisticsKHR( m_device, reinterpret_cast<const VkPipelineExecutableInfoKHR*>( pExecutableInfo ), pStatisticCount, reinterpret_cast<VkPipelineExecutableStatisticKHR*>( pStatistics ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PipelineExecutableStatisticKHR,Allocator>>::type Device::getPipelineExecutableStatisticsKHR( const PipelineExecutableInfoKHR & executableInfo, Dispatch const &d ) const
+ {
+ std::vector<PipelineExecutableStatisticKHR,Allocator> statistics;
+ uint32_t statisticCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPipelineExecutableStatisticsKHR( m_device, reinterpret_cast<const VkPipelineExecutableInfoKHR*>( &executableInfo ), &statisticCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && statisticCount )
+ {
+ statistics.resize( statisticCount );
+ result = static_cast<Result>( d.vkGetPipelineExecutableStatisticsKHR( m_device, reinterpret_cast<const VkPipelineExecutableInfoKHR*>( &executableInfo ), &statisticCount, reinterpret_cast<VkPipelineExecutableStatisticKHR*>( statistics.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( statisticCount <= statistics.size() );
+ statistics.resize( statisticCount );
+ }
+ return createResultValue( result, statistics, VULKAN_HPP_NAMESPACE_STRING"::Device::getPipelineExecutableStatisticsKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PipelineExecutableStatisticKHR,Allocator>>::type Device::getPipelineExecutableStatisticsKHR( const PipelineExecutableInfoKHR & executableInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PipelineExecutableStatisticKHR,Allocator> statistics( vectorAllocator );
+ uint32_t statisticCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPipelineExecutableStatisticsKHR( m_device, reinterpret_cast<const VkPipelineExecutableInfoKHR*>( &executableInfo ), &statisticCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && statisticCount )
+ {
+ statistics.resize( statisticCount );
+ result = static_cast<Result>( d.vkGetPipelineExecutableStatisticsKHR( m_device, reinterpret_cast<const VkPipelineExecutableInfoKHR*>( &executableInfo ), &statisticCount, reinterpret_cast<VkPipelineExecutableStatisticKHR*>( statistics.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( statisticCount <= statistics.size() );
+ statistics.resize( statisticCount );
+ }
+ return createResultValue( result, statistics, VULKAN_HPP_NAMESPACE_STRING"::Device::getPipelineExecutableStatisticsKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getQueryPoolResults( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VULKAN_HPP_NAMESPACE::DeviceSize stride, VULKAN_HPP_NAMESPACE::QueryResultFlags flags, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetQueryPoolResults( m_device, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount, dataSize, pData, static_cast<VkDeviceSize>( stride ), static_cast<VkQueryResultFlags>( flags ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename T, typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getQueryPoolResults( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, ArrayProxy<T> data, VULKAN_HPP_NAMESPACE::DeviceSize stride, VULKAN_HPP_NAMESPACE::QueryResultFlags flags, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkGetQueryPoolResults( m_device, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount, data.size() * sizeof( T ) , reinterpret_cast<void*>( data.data() ), static_cast<VkDeviceSize>( stride ), static_cast<VkQueryResultFlags>( flags ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getQueryPoolResults", { Result::eSuccess, Result::eNotReady } );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getRayTracingShaderGroupHandlesNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetRayTracingShaderGroupHandlesNV( m_device, static_cast<VkPipeline>( pipeline ), firstGroup, groupCount, dataSize, pData ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename T, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::getRayTracingShaderGroupHandlesNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, ArrayProxy<T> data, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkGetRayTracingShaderGroupHandlesNV( m_device, static_cast<VkPipeline>( pipeline ), firstGroup, groupCount, data.size() * sizeof( T ) , reinterpret_cast<void*>( data.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getRayTracingShaderGroupHandlesNV" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getRefreshCycleDurationGOOGLE( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, VULKAN_HPP_NAMESPACE::RefreshCycleDurationGOOGLE* pDisplayTimingProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetRefreshCycleDurationGOOGLE( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<VkRefreshCycleDurationGOOGLE*>( pDisplayTimingProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::RefreshCycleDurationGOOGLE>::type Device::getRefreshCycleDurationGOOGLE( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::RefreshCycleDurationGOOGLE displayTimingProperties;
+ Result result = static_cast<Result>( d.vkGetRefreshCycleDurationGOOGLE( m_device, static_cast<VkSwapchainKHR>( swapchain ), reinterpret_cast<VkRefreshCycleDurationGOOGLE*>( &displayTimingProperties ) ) );
+ return createResultValue( result, displayTimingProperties, VULKAN_HPP_NAMESPACE_STRING"::Device::getRefreshCycleDurationGOOGLE" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::getRenderAreaGranularity( VULKAN_HPP_NAMESPACE::RenderPass renderPass, VULKAN_HPP_NAMESPACE::Extent2D* pGranularity, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetRenderAreaGranularity( m_device, static_cast<VkRenderPass>( renderPass ), reinterpret_cast<VkExtent2D*>( pGranularity ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::Extent2D Device::getRenderAreaGranularity( VULKAN_HPP_NAMESPACE::RenderPass renderPass, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::Extent2D granularity;
+ d.vkGetRenderAreaGranularity( m_device, static_cast<VkRenderPass>( renderPass ), reinterpret_cast<VkExtent2D*>( &granularity ) );
+ return granularity;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getSemaphoreCounterValue( VULKAN_HPP_NAMESPACE::Semaphore semaphore, uint64_t* pValue, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetSemaphoreCounterValue( m_device, static_cast<VkSemaphore>( semaphore ), pValue ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<uint64_t>::type Device::getSemaphoreCounterValue( VULKAN_HPP_NAMESPACE::Semaphore semaphore, Dispatch const &d ) const
+ {
+ uint64_t value;
+ Result result = static_cast<Result>( d.vkGetSemaphoreCounterValue( m_device, static_cast<VkSemaphore>( semaphore ), &value ) );
+ return createResultValue( result, value, VULKAN_HPP_NAMESPACE_STRING"::Device::getSemaphoreCounterValue" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getSemaphoreCounterValueKHR( VULKAN_HPP_NAMESPACE::Semaphore semaphore, uint64_t* pValue, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetSemaphoreCounterValueKHR( m_device, static_cast<VkSemaphore>( semaphore ), pValue ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<uint64_t>::type Device::getSemaphoreCounterValueKHR( VULKAN_HPP_NAMESPACE::Semaphore semaphore, Dispatch const &d ) const
+ {
+ uint64_t value;
+ Result result = static_cast<Result>( d.vkGetSemaphoreCounterValueKHR( m_device, static_cast<VkSemaphore>( semaphore ), &value ) );
+ return createResultValue( result, value, VULKAN_HPP_NAMESPACE_STRING"::Device::getSemaphoreCounterValueKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getSemaphoreFdKHR( const VULKAN_HPP_NAMESPACE::SemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetSemaphoreFdKHR( m_device, reinterpret_cast<const VkSemaphoreGetFdInfoKHR*>( pGetFdInfo ), pFd ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<int>::type Device::getSemaphoreFdKHR( const SemaphoreGetFdInfoKHR & getFdInfo, Dispatch const &d ) const
+ {
+ int fd;
+ Result result = static_cast<Result>( d.vkGetSemaphoreFdKHR( m_device, reinterpret_cast<const VkSemaphoreGetFdInfoKHR*>( &getFdInfo ), &fd ) );
+ return createResultValue( result, fd, VULKAN_HPP_NAMESPACE_STRING"::Device::getSemaphoreFdKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getSemaphoreWin32HandleKHR( const VULKAN_HPP_NAMESPACE::SemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetSemaphoreWin32HandleKHR( m_device, reinterpret_cast<const VkSemaphoreGetWin32HandleInfoKHR*>( pGetWin32HandleInfo ), pHandle ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<HANDLE>::type Device::getSemaphoreWin32HandleKHR( const SemaphoreGetWin32HandleInfoKHR & getWin32HandleInfo, Dispatch const &d ) const
+ {
+ HANDLE handle;
+ Result result = static_cast<Result>( d.vkGetSemaphoreWin32HandleKHR( m_device, reinterpret_cast<const VkSemaphoreGetWin32HandleInfoKHR*>( &getWin32HandleInfo ), &handle ) );
+ return createResultValue( result, handle, VULKAN_HPP_NAMESPACE_STRING"::Device::getSemaphoreWin32HandleKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getShaderInfoAMD( VULKAN_HPP_NAMESPACE::Pipeline pipeline, VULKAN_HPP_NAMESPACE::ShaderStageFlagBits shaderStage, VULKAN_HPP_NAMESPACE::ShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetShaderInfoAMD( m_device, static_cast<VkPipeline>( pipeline ), static_cast<VkShaderStageFlagBits>( shaderStage ), static_cast<VkShaderInfoTypeAMD>( infoType ), pInfoSize, pInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<uint8_t,Allocator>>::type Device::getShaderInfoAMD( VULKAN_HPP_NAMESPACE::Pipeline pipeline, VULKAN_HPP_NAMESPACE::ShaderStageFlagBits shaderStage, VULKAN_HPP_NAMESPACE::ShaderInfoTypeAMD infoType, Dispatch const &d ) const
+ {
+ std::vector<uint8_t,Allocator> info;
+ size_t infoSize;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetShaderInfoAMD( m_device, static_cast<VkPipeline>( pipeline ), static_cast<VkShaderStageFlagBits>( shaderStage ), static_cast<VkShaderInfoTypeAMD>( infoType ), &infoSize, nullptr ) );
+ if ( ( result == Result::eSuccess ) && infoSize )
+ {
+ info.resize( infoSize );
+ result = static_cast<Result>( d.vkGetShaderInfoAMD( m_device, static_cast<VkPipeline>( pipeline ), static_cast<VkShaderStageFlagBits>( shaderStage ), static_cast<VkShaderInfoTypeAMD>( infoType ), &infoSize, reinterpret_cast<void*>( info.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( infoSize <= info.size() );
+ info.resize( infoSize );
+ }
+ return createResultValue( result, info, VULKAN_HPP_NAMESPACE_STRING"::Device::getShaderInfoAMD" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<uint8_t,Allocator>>::type Device::getShaderInfoAMD( VULKAN_HPP_NAMESPACE::Pipeline pipeline, VULKAN_HPP_NAMESPACE::ShaderStageFlagBits shaderStage, VULKAN_HPP_NAMESPACE::ShaderInfoTypeAMD infoType, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<uint8_t,Allocator> info( vectorAllocator );
+ size_t infoSize;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetShaderInfoAMD( m_device, static_cast<VkPipeline>( pipeline ), static_cast<VkShaderStageFlagBits>( shaderStage ), static_cast<VkShaderInfoTypeAMD>( infoType ), &infoSize, nullptr ) );
+ if ( ( result == Result::eSuccess ) && infoSize )
+ {
+ info.resize( infoSize );
+ result = static_cast<Result>( d.vkGetShaderInfoAMD( m_device, static_cast<VkPipeline>( pipeline ), static_cast<VkShaderStageFlagBits>( shaderStage ), static_cast<VkShaderInfoTypeAMD>( infoType ), &infoSize, reinterpret_cast<void*>( info.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( infoSize <= info.size() );
+ info.resize( infoSize );
+ }
+ return createResultValue( result, info, VULKAN_HPP_NAMESPACE_STRING"::Device::getShaderInfoAMD" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getSwapchainCounterEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, VULKAN_HPP_NAMESPACE::SurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetSwapchainCounterEXT( m_device, static_cast<VkSwapchainKHR>( swapchain ), static_cast<VkSurfaceCounterFlagBitsEXT>( counter ), pCounterValue ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<uint64_t>::type Device::getSwapchainCounterEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, VULKAN_HPP_NAMESPACE::SurfaceCounterFlagBitsEXT counter, Dispatch const &d ) const
+ {
+ uint64_t counterValue;
+ Result result = static_cast<Result>( d.vkGetSwapchainCounterEXT( m_device, static_cast<VkSwapchainKHR>( swapchain ), static_cast<VkSurfaceCounterFlagBitsEXT>( counter ), &counterValue ) );
+ return createResultValue( result, counterValue, VULKAN_HPP_NAMESPACE_STRING"::Device::getSwapchainCounterEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getSwapchainImagesKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VULKAN_HPP_NAMESPACE::Image* pSwapchainImages, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetSwapchainImagesKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), pSwapchainImageCount, reinterpret_cast<VkImage*>( pSwapchainImages ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<Image,Allocator>>::type Device::getSwapchainImagesKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d ) const
+ {
+ std::vector<Image,Allocator> swapchainImages;
+ uint32_t swapchainImageCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetSwapchainImagesKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), &swapchainImageCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && swapchainImageCount )
+ {
+ swapchainImages.resize( swapchainImageCount );
+ result = static_cast<Result>( d.vkGetSwapchainImagesKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), &swapchainImageCount, reinterpret_cast<VkImage*>( swapchainImages.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( swapchainImageCount <= swapchainImages.size() );
+ swapchainImages.resize( swapchainImageCount );
+ }
+ return createResultValue( result, swapchainImages, VULKAN_HPP_NAMESPACE_STRING"::Device::getSwapchainImagesKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<Image,Allocator>>::type Device::getSwapchainImagesKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<Image,Allocator> swapchainImages( vectorAllocator );
+ uint32_t swapchainImageCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetSwapchainImagesKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), &swapchainImageCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && swapchainImageCount )
+ {
+ swapchainImages.resize( swapchainImageCount );
+ result = static_cast<Result>( d.vkGetSwapchainImagesKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ), &swapchainImageCount, reinterpret_cast<VkImage*>( swapchainImages.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( swapchainImageCount <= swapchainImages.size() );
+ swapchainImages.resize( swapchainImageCount );
+ }
+ return createResultValue( result, swapchainImages, VULKAN_HPP_NAMESPACE_STRING"::Device::getSwapchainImagesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getSwapchainStatusKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetSwapchainStatusKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getSwapchainStatusKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkGetSwapchainStatusKHR( m_device, static_cast<VkSwapchainKHR>( swapchain ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getSwapchainStatusKHR", { Result::eSuccess, Result::eSuboptimalKHR } );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::getValidationCacheDataEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, size_t* pDataSize, void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetValidationCacheDataEXT( m_device, static_cast<VkValidationCacheEXT>( validationCache ), pDataSize, pData ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<uint8_t,Allocator>>::type Device::getValidationCacheDataEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, Dispatch const &d ) const
+ {
+ std::vector<uint8_t,Allocator> data;
+ size_t dataSize;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetValidationCacheDataEXT( m_device, static_cast<VkValidationCacheEXT>( validationCache ), &dataSize, nullptr ) );
+ if ( ( result == Result::eSuccess ) && dataSize )
+ {
+ data.resize( dataSize );
+ result = static_cast<Result>( d.vkGetValidationCacheDataEXT( m_device, static_cast<VkValidationCacheEXT>( validationCache ), &dataSize, reinterpret_cast<void*>( data.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( dataSize <= data.size() );
+ data.resize( dataSize );
+ }
+ return createResultValue( result, data, VULKAN_HPP_NAMESPACE_STRING"::Device::getValidationCacheDataEXT" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<uint8_t,Allocator>>::type Device::getValidationCacheDataEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT validationCache, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<uint8_t,Allocator> data( vectorAllocator );
+ size_t dataSize;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetValidationCacheDataEXT( m_device, static_cast<VkValidationCacheEXT>( validationCache ), &dataSize, nullptr ) );
+ if ( ( result == Result::eSuccess ) && dataSize )
+ {
+ data.resize( dataSize );
+ result = static_cast<Result>( d.vkGetValidationCacheDataEXT( m_device, static_cast<VkValidationCacheEXT>( validationCache ), &dataSize, reinterpret_cast<void*>( data.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( dataSize <= data.size() );
+ data.resize( dataSize );
+ }
+ return createResultValue( result, data, VULKAN_HPP_NAMESPACE_STRING"::Device::getValidationCacheDataEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::importFenceFdKHR( const VULKAN_HPP_NAMESPACE::ImportFenceFdInfoKHR* pImportFenceFdInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkImportFenceFdKHR( m_device, reinterpret_cast<const VkImportFenceFdInfoKHR*>( pImportFenceFdInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::importFenceFdKHR( const ImportFenceFdInfoKHR & importFenceFdInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkImportFenceFdKHR( m_device, reinterpret_cast<const VkImportFenceFdInfoKHR*>( &importFenceFdInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::importFenceFdKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::importFenceWin32HandleKHR( const VULKAN_HPP_NAMESPACE::ImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkImportFenceWin32HandleKHR( m_device, reinterpret_cast<const VkImportFenceWin32HandleInfoKHR*>( pImportFenceWin32HandleInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::importFenceWin32HandleKHR( const ImportFenceWin32HandleInfoKHR & importFenceWin32HandleInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkImportFenceWin32HandleKHR( m_device, reinterpret_cast<const VkImportFenceWin32HandleInfoKHR*>( &importFenceWin32HandleInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::importFenceWin32HandleKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::importSemaphoreFdKHR( const VULKAN_HPP_NAMESPACE::ImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkImportSemaphoreFdKHR( m_device, reinterpret_cast<const VkImportSemaphoreFdInfoKHR*>( pImportSemaphoreFdInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::importSemaphoreFdKHR( const ImportSemaphoreFdInfoKHR & importSemaphoreFdInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkImportSemaphoreFdKHR( m_device, reinterpret_cast<const VkImportSemaphoreFdInfoKHR*>( &importSemaphoreFdInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::importSemaphoreFdKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::importSemaphoreWin32HandleKHR( const VULKAN_HPP_NAMESPACE::ImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkImportSemaphoreWin32HandleKHR( m_device, reinterpret_cast<const VkImportSemaphoreWin32HandleInfoKHR*>( pImportSemaphoreWin32HandleInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::importSemaphoreWin32HandleKHR( const ImportSemaphoreWin32HandleInfoKHR & importSemaphoreWin32HandleInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkImportSemaphoreWin32HandleKHR( m_device, reinterpret_cast<const VkImportSemaphoreWin32HandleInfoKHR*>( &importSemaphoreWin32HandleInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::importSemaphoreWin32HandleKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::initializePerformanceApiINTEL( const VULKAN_HPP_NAMESPACE::InitializePerformanceApiInfoINTEL* pInitializeInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkInitializePerformanceApiINTEL( m_device, reinterpret_cast<const VkInitializePerformanceApiInfoINTEL*>( pInitializeInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::initializePerformanceApiINTEL( const InitializePerformanceApiInfoINTEL & initializeInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkInitializePerformanceApiINTEL( m_device, reinterpret_cast<const VkInitializePerformanceApiInfoINTEL*>( &initializeInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::initializePerformanceApiINTEL" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::invalidateMappedMemoryRanges( uint32_t memoryRangeCount, const VULKAN_HPP_NAMESPACE::MappedMemoryRange* pMemoryRanges, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkInvalidateMappedMemoryRanges( m_device, memoryRangeCount, reinterpret_cast<const VkMappedMemoryRange*>( pMemoryRanges ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::invalidateMappedMemoryRanges( ArrayProxy<const VULKAN_HPP_NAMESPACE::MappedMemoryRange> memoryRanges, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkInvalidateMappedMemoryRanges( m_device, memoryRanges.size() , reinterpret_cast<const VkMappedMemoryRange*>( memoryRanges.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::invalidateMappedMemoryRanges" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::mapMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::DeviceSize size, VULKAN_HPP_NAMESPACE::MemoryMapFlags flags, void** ppData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkMapMemory( m_device, static_cast<VkDeviceMemory>( memory ), static_cast<VkDeviceSize>( offset ), static_cast<VkDeviceSize>( size ), static_cast<VkMemoryMapFlags>( flags ), ppData ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void*>::type Device::mapMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::DeviceSize size, VULKAN_HPP_NAMESPACE::MemoryMapFlags flags, Dispatch const &d ) const
+ {
+ void* pData;
+ Result result = static_cast<Result>( d.vkMapMemory( m_device, static_cast<VkDeviceMemory>( memory ), static_cast<VkDeviceSize>( offset ), static_cast<VkDeviceSize>( size ), static_cast<VkMemoryMapFlags>( flags ), &pData ) );
+ return createResultValue( result, pData, VULKAN_HPP_NAMESPACE_STRING"::Device::mapMemory" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::mergePipelineCaches( VULKAN_HPP_NAMESPACE::PipelineCache dstCache, uint32_t srcCacheCount, const VULKAN_HPP_NAMESPACE::PipelineCache* pSrcCaches, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkMergePipelineCaches( m_device, static_cast<VkPipelineCache>( dstCache ), srcCacheCount, reinterpret_cast<const VkPipelineCache*>( pSrcCaches ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::mergePipelineCaches( VULKAN_HPP_NAMESPACE::PipelineCache dstCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::PipelineCache> srcCaches, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkMergePipelineCaches( m_device, static_cast<VkPipelineCache>( dstCache ), srcCaches.size() , reinterpret_cast<const VkPipelineCache*>( srcCaches.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::mergePipelineCaches" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::mergeValidationCachesEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT dstCache, uint32_t srcCacheCount, const VULKAN_HPP_NAMESPACE::ValidationCacheEXT* pSrcCaches, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkMergeValidationCachesEXT( m_device, static_cast<VkValidationCacheEXT>( dstCache ), srcCacheCount, reinterpret_cast<const VkValidationCacheEXT*>( pSrcCaches ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::mergeValidationCachesEXT( VULKAN_HPP_NAMESPACE::ValidationCacheEXT dstCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ValidationCacheEXT> srcCaches, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkMergeValidationCachesEXT( m_device, static_cast<VkValidationCacheEXT>( dstCache ), srcCaches.size() , reinterpret_cast<const VkValidationCacheEXT*>( srcCaches.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::mergeValidationCachesEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::registerEventEXT( const VULKAN_HPP_NAMESPACE::DeviceEventInfoEXT* pDeviceEventInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Fence* pFence, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkRegisterDeviceEventEXT( m_device, reinterpret_cast<const VkDeviceEventInfoEXT*>( pDeviceEventInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkFence*>( pFence ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Fence>::type Device::registerEventEXT( const DeviceEventInfoEXT & deviceEventInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Fence fence;
+ Result result = static_cast<Result>( d.vkRegisterDeviceEventEXT( m_device, reinterpret_cast<const VkDeviceEventInfoEXT*>( &deviceEventInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkFence*>( &fence ) ) );
+ return createResultValue( result, fence, VULKAN_HPP_NAMESPACE_STRING"::Device::registerEventEXT" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Fence,Dispatch>>::type Device::registerEventEXTUnique( const DeviceEventInfoEXT & deviceEventInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Fence fence;
+ Result result = static_cast<Result>( d.vkRegisterDeviceEventEXT( m_device, reinterpret_cast<const VkDeviceEventInfoEXT*>( &deviceEventInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkFence*>( &fence ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Fence,Dispatch>( result, fence, VULKAN_HPP_NAMESPACE_STRING"::Device::registerEventEXTUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::registerDisplayEventEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, const VULKAN_HPP_NAMESPACE::DisplayEventInfoEXT* pDisplayEventInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Fence* pFence, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkRegisterDisplayEventEXT( m_device, static_cast<VkDisplayKHR>( display ), reinterpret_cast<const VkDisplayEventInfoEXT*>( pDisplayEventInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkFence*>( pFence ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Fence>::type Device::registerDisplayEventEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, const DisplayEventInfoEXT & displayEventInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Fence fence;
+ Result result = static_cast<Result>( d.vkRegisterDisplayEventEXT( m_device, static_cast<VkDisplayKHR>( display ), reinterpret_cast<const VkDisplayEventInfoEXT*>( &displayEventInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkFence*>( &fence ) ) );
+ return createResultValue( result, fence, VULKAN_HPP_NAMESPACE_STRING"::Device::registerDisplayEventEXT" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Fence,Dispatch>>::type Device::registerDisplayEventEXTUnique( VULKAN_HPP_NAMESPACE::DisplayKHR display, const DisplayEventInfoEXT & displayEventInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Fence fence;
+ Result result = static_cast<Result>( d.vkRegisterDisplayEventEXT( m_device, static_cast<VkDisplayKHR>( display ), reinterpret_cast<const VkDisplayEventInfoEXT*>( &displayEventInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkFence*>( &fence ) ) );
+
+ ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<Fence,Dispatch>( result, fence, VULKAN_HPP_NAMESPACE_STRING"::Device::registerDisplayEventEXTUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::registerObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, uint32_t objectCount, const VULKAN_HPP_NAMESPACE::ObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkRegisterObjectsNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), objectCount, reinterpret_cast<const VkObjectTableEntryNVX* const*>( ppObjectTableEntries ), pObjectIndices ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::registerObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, ArrayProxy<const VULKAN_HPP_NAMESPACE::ObjectTableEntryNVX* const> pObjectTableEntries, ArrayProxy<const uint32_t> objectIndices, Dispatch const &d ) const
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( pObjectTableEntries.size() == objectIndices.size() );
+#else
+ if ( pObjectTableEntries.size() != objectIndices.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkDevice::registerObjectsNVX: pObjectTableEntries.size() != objectIndices.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+ Result result = static_cast<Result>( d.vkRegisterObjectsNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), pObjectTableEntries.size() , reinterpret_cast<const VkObjectTableEntryNVX* const*>( pObjectTableEntries.data() ), objectIndices.data() ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::registerObjectsNVX" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::releaseFullScreenExclusiveModeEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkReleaseFullScreenExclusiveModeEXT( m_device, static_cast<VkSwapchainKHR>( swapchain ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::releaseFullScreenExclusiveModeEXT( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkReleaseFullScreenExclusiveModeEXT( m_device, static_cast<VkSwapchainKHR>( swapchain ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::releaseFullScreenExclusiveModeEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::releasePerformanceConfigurationINTEL( VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL configuration, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkReleasePerformanceConfigurationINTEL( m_device, static_cast<VkPerformanceConfigurationINTEL>( configuration ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::releasePerformanceConfigurationINTEL( VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL configuration, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkReleasePerformanceConfigurationINTEL( m_device, static_cast<VkPerformanceConfigurationINTEL>( configuration ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::releasePerformanceConfigurationINTEL" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::releaseProfilingLockKHR(Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkReleaseProfilingLockKHR( m_device );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::releaseProfilingLockKHR(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkReleaseProfilingLockKHR( m_device );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::resetCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolResetFlags flags, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkResetCommandPool( m_device, static_cast<VkCommandPool>( commandPool ), static_cast<VkCommandPoolResetFlags>( flags ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::resetCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolResetFlags flags, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkResetCommandPool( m_device, static_cast<VkCommandPool>( commandPool ), static_cast<VkCommandPoolResetFlags>( flags ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::resetCommandPool" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::resetDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, VULKAN_HPP_NAMESPACE::DescriptorPoolResetFlags flags, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkResetDescriptorPool( m_device, static_cast<VkDescriptorPool>( descriptorPool ), static_cast<VkDescriptorPoolResetFlags>( flags ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::resetDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, VULKAN_HPP_NAMESPACE::DescriptorPoolResetFlags flags, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkResetDescriptorPool( m_device, static_cast<VkDescriptorPool>( descriptorPool ), static_cast<VkDescriptorPoolResetFlags>( flags ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::resetDescriptorPool" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::resetEvent( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkResetEvent( m_device, static_cast<VkEvent>( event ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::resetEvent( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkResetEvent( m_device, static_cast<VkEvent>( event ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::resetEvent" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::resetFences( uint32_t fenceCount, const VULKAN_HPP_NAMESPACE::Fence* pFences, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkResetFences( m_device, fenceCount, reinterpret_cast<const VkFence*>( pFences ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::resetFences( ArrayProxy<const VULKAN_HPP_NAMESPACE::Fence> fences, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkResetFences( m_device, fences.size() , reinterpret_cast<const VkFence*>( fences.data() ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::resetFences" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::resetQueryPool( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkResetQueryPool( m_device, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::resetQueryPool( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkResetQueryPool( m_device, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::resetQueryPoolEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkResetQueryPoolEXT( m_device, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::resetQueryPoolEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkResetQueryPoolEXT( m_device, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::setDebugUtilsObjectNameEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsObjectNameInfoEXT* pNameInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkSetDebugUtilsObjectNameEXT( m_device, reinterpret_cast<const VkDebugUtilsObjectNameInfoEXT*>( pNameInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::setDebugUtilsObjectNameEXT( const DebugUtilsObjectNameInfoEXT & nameInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkSetDebugUtilsObjectNameEXT( m_device, reinterpret_cast<const VkDebugUtilsObjectNameInfoEXT*>( &nameInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::setDebugUtilsObjectNameEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::setDebugUtilsObjectTagEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsObjectTagInfoEXT* pTagInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkSetDebugUtilsObjectTagEXT( m_device, reinterpret_cast<const VkDebugUtilsObjectTagInfoEXT*>( pTagInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::setDebugUtilsObjectTagEXT( const DebugUtilsObjectTagInfoEXT & tagInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkSetDebugUtilsObjectTagEXT( m_device, reinterpret_cast<const VkDebugUtilsObjectTagInfoEXT*>( &tagInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::setDebugUtilsObjectTagEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::setEvent( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkSetEvent( m_device, static_cast<VkEvent>( event ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::setEvent( VULKAN_HPP_NAMESPACE::Event event, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkSetEvent( m_device, static_cast<VkEvent>( event ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::setEvent" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::setHdrMetadataEXT( uint32_t swapchainCount, const VULKAN_HPP_NAMESPACE::SwapchainKHR* pSwapchains, const VULKAN_HPP_NAMESPACE::HdrMetadataEXT* pMetadata, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkSetHdrMetadataEXT( m_device, swapchainCount, reinterpret_cast<const VkSwapchainKHR*>( pSwapchains ), reinterpret_cast<const VkHdrMetadataEXT*>( pMetadata ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::setHdrMetadataEXT( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainKHR> swapchains, ArrayProxy<const VULKAN_HPP_NAMESPACE::HdrMetadataEXT> metadata, Dispatch const &d ) const
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( swapchains.size() == metadata.size() );
+#else
+ if ( swapchains.size() != metadata.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkDevice::setHdrMetadataEXT: swapchains.size() != metadata.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+ d.vkSetHdrMetadataEXT( m_device, swapchains.size() , reinterpret_cast<const VkSwapchainKHR*>( swapchains.data() ), reinterpret_cast<const VkHdrMetadataEXT*>( metadata.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::setLocalDimmingAMD( VULKAN_HPP_NAMESPACE::SwapchainKHR swapChain, VULKAN_HPP_NAMESPACE::Bool32 localDimmingEnable, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkSetLocalDimmingAMD( m_device, static_cast<VkSwapchainKHR>( swapChain ), static_cast<VkBool32>( localDimmingEnable ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::setLocalDimmingAMD( VULKAN_HPP_NAMESPACE::SwapchainKHR swapChain, VULKAN_HPP_NAMESPACE::Bool32 localDimmingEnable, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkSetLocalDimmingAMD( m_device, static_cast<VkSwapchainKHR>( swapChain ), static_cast<VkBool32>( localDimmingEnable ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::signalSemaphore( const VULKAN_HPP_NAMESPACE::SemaphoreSignalInfo* pSignalInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkSignalSemaphore( m_device, reinterpret_cast<const VkSemaphoreSignalInfo*>( pSignalInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::signalSemaphore( const SemaphoreSignalInfo & signalInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkSignalSemaphore( m_device, reinterpret_cast<const VkSemaphoreSignalInfo*>( &signalInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::signalSemaphore" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::signalSemaphoreKHR( const VULKAN_HPP_NAMESPACE::SemaphoreSignalInfo* pSignalInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkSignalSemaphoreKHR( m_device, reinterpret_cast<const VkSemaphoreSignalInfo*>( pSignalInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::signalSemaphoreKHR( const SemaphoreSignalInfo & signalInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkSignalSemaphoreKHR( m_device, reinterpret_cast<const VkSemaphoreSignalInfo*>( &signalInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::signalSemaphoreKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::trimCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolTrimFlags flags, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkTrimCommandPool( m_device, static_cast<VkCommandPool>( commandPool ), static_cast<VkCommandPoolTrimFlags>( flags ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::trimCommandPool( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolTrimFlags flags, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkTrimCommandPool( m_device, static_cast<VkCommandPool>( commandPool ), static_cast<VkCommandPoolTrimFlags>( flags ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::trimCommandPoolKHR( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolTrimFlags flags, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkTrimCommandPoolKHR( m_device, static_cast<VkCommandPool>( commandPool ), static_cast<VkCommandPoolTrimFlags>( flags ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::trimCommandPoolKHR( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolTrimFlags flags, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkTrimCommandPoolKHR( m_device, static_cast<VkCommandPool>( commandPool ), static_cast<VkCommandPoolTrimFlags>( flags ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::uninitializePerformanceApiINTEL(Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkUninitializePerformanceApiINTEL( m_device );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::uninitializePerformanceApiINTEL(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkUninitializePerformanceApiINTEL( m_device );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::unmapMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkUnmapMemory( m_device, static_cast<VkDeviceMemory>( memory ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::unmapMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkUnmapMemory( m_device, static_cast<VkDeviceMemory>( memory ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::unregisterObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, uint32_t objectCount, const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkUnregisterObjectsNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), objectCount, reinterpret_cast<const VkObjectEntryTypeNVX*>( pObjectEntryTypes ), pObjectIndices ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::unregisterObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, ArrayProxy<const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX> objectEntryTypes, ArrayProxy<const uint32_t> objectIndices, Dispatch const &d ) const
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( objectEntryTypes.size() == objectIndices.size() );
+#else
+ if ( objectEntryTypes.size() != objectIndices.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkDevice::unregisterObjectsNVX: objectEntryTypes.size() != objectIndices.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+ Result result = static_cast<Result>( d.vkUnregisterObjectsNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), objectEntryTypes.size() , reinterpret_cast<const VkObjectEntryTypeNVX*>( objectEntryTypes.data() ), objectIndices.data() ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::unregisterObjectsNVX" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::updateDescriptorSetWithTemplate( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkUpdateDescriptorSetWithTemplate( m_device, static_cast<VkDescriptorSet>( descriptorSet ), static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), pData );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::updateDescriptorSetWithTemplate( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkUpdateDescriptorSetWithTemplate( m_device, static_cast<VkDescriptorSet>( descriptorSet ), static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), pData );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::updateDescriptorSetWithTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkUpdateDescriptorSetWithTemplateKHR( m_device, static_cast<VkDescriptorSet>( descriptorSet ), static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), pData );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::updateDescriptorSetWithTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkUpdateDescriptorSetWithTemplateKHR( m_device, static_cast<VkDescriptorSet>( descriptorSet ), static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), pData );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::updateDescriptorSets( uint32_t descriptorWriteCount, const VULKAN_HPP_NAMESPACE::WriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VULKAN_HPP_NAMESPACE::CopyDescriptorSet* pDescriptorCopies, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkUpdateDescriptorSets( m_device, descriptorWriteCount, reinterpret_cast<const VkWriteDescriptorSet*>( pDescriptorWrites ), descriptorCopyCount, reinterpret_cast<const VkCopyDescriptorSet*>( pDescriptorCopies ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Device::updateDescriptorSets( ArrayProxy<const VULKAN_HPP_NAMESPACE::WriteDescriptorSet> descriptorWrites, ArrayProxy<const VULKAN_HPP_NAMESPACE::CopyDescriptorSet> descriptorCopies, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkUpdateDescriptorSets( m_device, descriptorWrites.size() , reinterpret_cast<const VkWriteDescriptorSet*>( descriptorWrites.data() ), descriptorCopies.size() , reinterpret_cast<const VkCopyDescriptorSet*>( descriptorCopies.data() ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::waitForFences( uint32_t fenceCount, const VULKAN_HPP_NAMESPACE::Fence* pFences, VULKAN_HPP_NAMESPACE::Bool32 waitAll, uint64_t timeout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkWaitForFences( m_device, fenceCount, reinterpret_cast<const VkFence*>( pFences ), static_cast<VkBool32>( waitAll ), timeout ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::waitForFences( ArrayProxy<const VULKAN_HPP_NAMESPACE::Fence> fences, VULKAN_HPP_NAMESPACE::Bool32 waitAll, uint64_t timeout, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkWaitForFences( m_device, fences.size() , reinterpret_cast<const VkFence*>( fences.data() ), static_cast<VkBool32>( waitAll ), timeout ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::waitForFences", { Result::eSuccess, Result::eTimeout } );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::waitSemaphores( const VULKAN_HPP_NAMESPACE::SemaphoreWaitInfo* pWaitInfo, uint64_t timeout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkWaitSemaphores( m_device, reinterpret_cast<const VkSemaphoreWaitInfo*>( pWaitInfo ), timeout ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::waitSemaphores( const SemaphoreWaitInfo & waitInfo, uint64_t timeout, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkWaitSemaphores( m_device, reinterpret_cast<const VkSemaphoreWaitInfo*>( &waitInfo ), timeout ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::waitSemaphores", { Result::eSuccess, Result::eTimeout } );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::waitSemaphoresKHR( const VULKAN_HPP_NAMESPACE::SemaphoreWaitInfo* pWaitInfo, uint64_t timeout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkWaitSemaphoresKHR( m_device, reinterpret_cast<const VkSemaphoreWaitInfo*>( pWaitInfo ), timeout ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Device::waitSemaphoresKHR( const SemaphoreWaitInfo & waitInfo, uint64_t timeout, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkWaitSemaphoresKHR( m_device, reinterpret_cast<const VkSemaphoreWaitInfo*>( &waitInfo ), timeout ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::waitSemaphoresKHR", { Result::eSuccess, Result::eTimeout } );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createAndroidSurfaceKHR( const VULKAN_HPP_NAMESPACE::AndroidSurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateAndroidSurfaceKHR( m_instance, reinterpret_cast<const VkAndroidSurfaceCreateInfoKHR*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createAndroidSurfaceKHR( const AndroidSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateAndroidSurfaceKHR( m_instance, reinterpret_cast<const VkAndroidSurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createAndroidSurfaceKHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createAndroidSurfaceKHRUnique( const AndroidSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateAndroidSurfaceKHR( m_instance, reinterpret_cast<const VkAndroidSurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createAndroidSurfaceKHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createDebugReportCallbackEXT( const VULKAN_HPP_NAMESPACE::DebugReportCallbackCreateInfoEXT* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT* pCallback, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateDebugReportCallbackEXT( m_instance, reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDebugReportCallbackEXT*>( pCallback ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT>::type Instance::createDebugReportCallbackEXT( const DebugReportCallbackCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT callback;
+ Result result = static_cast<Result>( d.vkCreateDebugReportCallbackEXT( m_instance, reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDebugReportCallbackEXT*>( &callback ) ) );
+ return createResultValue( result, callback, VULKAN_HPP_NAMESPACE_STRING"::Instance::createDebugReportCallbackEXT" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<DebugReportCallbackEXT,Dispatch>>::type Instance::createDebugReportCallbackEXTUnique( const DebugReportCallbackCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT callback;
+ Result result = static_cast<Result>( d.vkCreateDebugReportCallbackEXT( m_instance, reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDebugReportCallbackEXT*>( &callback ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<DebugReportCallbackEXT,Dispatch>( result, callback, VULKAN_HPP_NAMESPACE_STRING"::Instance::createDebugReportCallbackEXTUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createDebugUtilsMessengerEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT* pMessenger, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateDebugUtilsMessengerEXT( m_instance, reinterpret_cast<const VkDebugUtilsMessengerCreateInfoEXT*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDebugUtilsMessengerEXT*>( pMessenger ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT>::type Instance::createDebugUtilsMessengerEXT( const DebugUtilsMessengerCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT messenger;
+ Result result = static_cast<Result>( d.vkCreateDebugUtilsMessengerEXT( m_instance, reinterpret_cast<const VkDebugUtilsMessengerCreateInfoEXT*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDebugUtilsMessengerEXT*>( &messenger ) ) );
+ return createResultValue( result, messenger, VULKAN_HPP_NAMESPACE_STRING"::Instance::createDebugUtilsMessengerEXT" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<DebugUtilsMessengerEXT,Dispatch>>::type Instance::createDebugUtilsMessengerEXTUnique( const DebugUtilsMessengerCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT messenger;
+ Result result = static_cast<Result>( d.vkCreateDebugUtilsMessengerEXT( m_instance, reinterpret_cast<const VkDebugUtilsMessengerCreateInfoEXT*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDebugUtilsMessengerEXT*>( &messenger ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<DebugUtilsMessengerEXT,Dispatch>( result, messenger, VULKAN_HPP_NAMESPACE_STRING"::Instance::createDebugUtilsMessengerEXTUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createDisplayPlaneSurfaceKHR( const VULKAN_HPP_NAMESPACE::DisplaySurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateDisplayPlaneSurfaceKHR( m_instance, reinterpret_cast<const VkDisplaySurfaceCreateInfoKHR*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createDisplayPlaneSurfaceKHR( const DisplaySurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateDisplayPlaneSurfaceKHR( m_instance, reinterpret_cast<const VkDisplaySurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createDisplayPlaneSurfaceKHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createDisplayPlaneSurfaceKHRUnique( const DisplaySurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateDisplayPlaneSurfaceKHR( m_instance, reinterpret_cast<const VkDisplaySurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createDisplayPlaneSurfaceKHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createHeadlessSurfaceEXT( const VULKAN_HPP_NAMESPACE::HeadlessSurfaceCreateInfoEXT* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateHeadlessSurfaceEXT( m_instance, reinterpret_cast<const VkHeadlessSurfaceCreateInfoEXT*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createHeadlessSurfaceEXT( const HeadlessSurfaceCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateHeadlessSurfaceEXT( m_instance, reinterpret_cast<const VkHeadlessSurfaceCreateInfoEXT*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createHeadlessSurfaceEXT" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createHeadlessSurfaceEXTUnique( const HeadlessSurfaceCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateHeadlessSurfaceEXT( m_instance, reinterpret_cast<const VkHeadlessSurfaceCreateInfoEXT*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createHeadlessSurfaceEXTUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createIOSSurfaceMVK( const VULKAN_HPP_NAMESPACE::IOSSurfaceCreateInfoMVK* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateIOSSurfaceMVK( m_instance, reinterpret_cast<const VkIOSSurfaceCreateInfoMVK*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createIOSSurfaceMVK( const IOSSurfaceCreateInfoMVK & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateIOSSurfaceMVK( m_instance, reinterpret_cast<const VkIOSSurfaceCreateInfoMVK*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createIOSSurfaceMVK" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createIOSSurfaceMVKUnique( const IOSSurfaceCreateInfoMVK & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateIOSSurfaceMVK( m_instance, reinterpret_cast<const VkIOSSurfaceCreateInfoMVK*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createIOSSurfaceMVKUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_IOS_MVK*/
+
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createImagePipeSurfaceFUCHSIA( const VULKAN_HPP_NAMESPACE::ImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateImagePipeSurfaceFUCHSIA( m_instance, reinterpret_cast<const VkImagePipeSurfaceCreateInfoFUCHSIA*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createImagePipeSurfaceFUCHSIA( const ImagePipeSurfaceCreateInfoFUCHSIA & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateImagePipeSurfaceFUCHSIA( m_instance, reinterpret_cast<const VkImagePipeSurfaceCreateInfoFUCHSIA*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createImagePipeSurfaceFUCHSIA" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createImagePipeSurfaceFUCHSIAUnique( const ImagePipeSurfaceCreateInfoFUCHSIA & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateImagePipeSurfaceFUCHSIA( m_instance, reinterpret_cast<const VkImagePipeSurfaceCreateInfoFUCHSIA*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createImagePipeSurfaceFUCHSIAUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_FUCHSIA*/
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createMacOSSurfaceMVK( const VULKAN_HPP_NAMESPACE::MacOSSurfaceCreateInfoMVK* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateMacOSSurfaceMVK( m_instance, reinterpret_cast<const VkMacOSSurfaceCreateInfoMVK*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createMacOSSurfaceMVK( const MacOSSurfaceCreateInfoMVK & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateMacOSSurfaceMVK( m_instance, reinterpret_cast<const VkMacOSSurfaceCreateInfoMVK*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createMacOSSurfaceMVK" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createMacOSSurfaceMVKUnique( const MacOSSurfaceCreateInfoMVK & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateMacOSSurfaceMVK( m_instance, reinterpret_cast<const VkMacOSSurfaceCreateInfoMVK*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createMacOSSurfaceMVKUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_MACOS_MVK*/
+
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createMetalSurfaceEXT( const VULKAN_HPP_NAMESPACE::MetalSurfaceCreateInfoEXT* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateMetalSurfaceEXT( m_instance, reinterpret_cast<const VkMetalSurfaceCreateInfoEXT*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createMetalSurfaceEXT( const MetalSurfaceCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateMetalSurfaceEXT( m_instance, reinterpret_cast<const VkMetalSurfaceCreateInfoEXT*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createMetalSurfaceEXT" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createMetalSurfaceEXTUnique( const MetalSurfaceCreateInfoEXT & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateMetalSurfaceEXT( m_instance, reinterpret_cast<const VkMetalSurfaceCreateInfoEXT*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createMetalSurfaceEXTUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_METAL_EXT*/
+
+#ifdef VK_USE_PLATFORM_GGP
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createStreamDescriptorSurfaceGGP( const VULKAN_HPP_NAMESPACE::StreamDescriptorSurfaceCreateInfoGGP* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateStreamDescriptorSurfaceGGP( m_instance, reinterpret_cast<const VkStreamDescriptorSurfaceCreateInfoGGP*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createStreamDescriptorSurfaceGGP( const StreamDescriptorSurfaceCreateInfoGGP & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateStreamDescriptorSurfaceGGP( m_instance, reinterpret_cast<const VkStreamDescriptorSurfaceCreateInfoGGP*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createStreamDescriptorSurfaceGGP" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createStreamDescriptorSurfaceGGPUnique( const StreamDescriptorSurfaceCreateInfoGGP & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateStreamDescriptorSurfaceGGP( m_instance, reinterpret_cast<const VkStreamDescriptorSurfaceCreateInfoGGP*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createStreamDescriptorSurfaceGGPUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_GGP*/
+
+#ifdef VK_USE_PLATFORM_VI_NN
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createViSurfaceNN( const VULKAN_HPP_NAMESPACE::ViSurfaceCreateInfoNN* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateViSurfaceNN( m_instance, reinterpret_cast<const VkViSurfaceCreateInfoNN*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createViSurfaceNN( const ViSurfaceCreateInfoNN & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateViSurfaceNN( m_instance, reinterpret_cast<const VkViSurfaceCreateInfoNN*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createViSurfaceNN" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createViSurfaceNNUnique( const ViSurfaceCreateInfoNN & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateViSurfaceNN( m_instance, reinterpret_cast<const VkViSurfaceCreateInfoNN*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createViSurfaceNNUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_VI_NN*/
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createWaylandSurfaceKHR( const VULKAN_HPP_NAMESPACE::WaylandSurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateWaylandSurfaceKHR( m_instance, reinterpret_cast<const VkWaylandSurfaceCreateInfoKHR*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createWaylandSurfaceKHR( const WaylandSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateWaylandSurfaceKHR( m_instance, reinterpret_cast<const VkWaylandSurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createWaylandSurfaceKHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createWaylandSurfaceKHRUnique( const WaylandSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateWaylandSurfaceKHR( m_instance, reinterpret_cast<const VkWaylandSurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createWaylandSurfaceKHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createWin32SurfaceKHR( const VULKAN_HPP_NAMESPACE::Win32SurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateWin32SurfaceKHR( m_instance, reinterpret_cast<const VkWin32SurfaceCreateInfoKHR*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createWin32SurfaceKHR( const Win32SurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateWin32SurfaceKHR( m_instance, reinterpret_cast<const VkWin32SurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createWin32SurfaceKHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createWin32SurfaceKHRUnique( const Win32SurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateWin32SurfaceKHR( m_instance, reinterpret_cast<const VkWin32SurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createWin32SurfaceKHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createXcbSurfaceKHR( const VULKAN_HPP_NAMESPACE::XcbSurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateXcbSurfaceKHR( m_instance, reinterpret_cast<const VkXcbSurfaceCreateInfoKHR*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createXcbSurfaceKHR( const XcbSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateXcbSurfaceKHR( m_instance, reinterpret_cast<const VkXcbSurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createXcbSurfaceKHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createXcbSurfaceKHRUnique( const XcbSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateXcbSurfaceKHR( m_instance, reinterpret_cast<const VkXcbSurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createXcbSurfaceKHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::createXlibSurfaceKHR( const VULKAN_HPP_NAMESPACE::XlibSurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateXlibSurfaceKHR( m_instance, reinterpret_cast<const VkXlibSurfaceCreateInfoKHR*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSurfaceKHR*>( pSurface ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceKHR>::type Instance::createXlibSurfaceKHR( const XlibSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateXlibSurfaceKHR( m_instance, reinterpret_cast<const VkXlibSurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+ return createResultValue( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createXlibSurfaceKHR" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SurfaceKHR,Dispatch>>::type Instance::createXlibSurfaceKHRUnique( const XlibSurfaceCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceKHR surface;
+ Result result = static_cast<Result>( d.vkCreateXlibSurfaceKHR( m_instance, reinterpret_cast<const VkXlibSurfaceCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSurfaceKHR*>( &surface ) ) );
+
+ ObjectDestroy<Instance,Dispatch> deleter( *this, allocator, d );
+ return createResultValue<SurfaceKHR,Dispatch>( result, surface, VULKAN_HPP_NAMESPACE_STRING"::Instance::createXlibSurfaceKHRUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::debugReportMessageEXT( VULKAN_HPP_NAMESPACE::DebugReportFlagsEXT flags, VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDebugReportMessageEXT( m_instance, static_cast<VkDebugReportFlagsEXT>( flags ), static_cast<VkDebugReportObjectTypeEXT>( objectType ), object, location, messageCode, pLayerPrefix, pMessage );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::debugReportMessageEXT( VULKAN_HPP_NAMESPACE::DebugReportFlagsEXT flags, VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const std::string & layerPrefix, const std::string & message, Dispatch const &d ) const
+ {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ VULKAN_HPP_ASSERT( layerPrefix.size() == message.size() );
+#else
+ if ( layerPrefix.size() != message.size() )
+ {
+ throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkInstance::debugReportMessageEXT: layerPrefix.size() != message.size()" );
+ }
+#endif /*VULKAN_HPP_NO_EXCEPTIONS*/
+ d.vkDebugReportMessageEXT( m_instance, static_cast<VkDebugReportFlagsEXT>( flags ), static_cast<VkDebugReportObjectTypeEXT>( objectType ), object, location, messageCode, layerPrefix.c_str(), message.c_str() );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroyDebugReportCallbackEXT( VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT callback, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDebugReportCallbackEXT( m_instance, static_cast<VkDebugReportCallbackEXT>( callback ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroyDebugReportCallbackEXT( VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT callback, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDebugReportCallbackEXT( m_instance, static_cast<VkDebugReportCallbackEXT>( callback ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroy( VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT callback, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDebugReportCallbackEXT( m_instance, static_cast<VkDebugReportCallbackEXT>( callback ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroy( VULKAN_HPP_NAMESPACE::DebugReportCallbackEXT callback, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDebugReportCallbackEXT( m_instance, static_cast<VkDebugReportCallbackEXT>( callback ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroyDebugUtilsMessengerEXT( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT messenger, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDebugUtilsMessengerEXT( m_instance, static_cast<VkDebugUtilsMessengerEXT>( messenger ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroyDebugUtilsMessengerEXT( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT messenger, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDebugUtilsMessengerEXT( m_instance, static_cast<VkDebugUtilsMessengerEXT>( messenger ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroy( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT messenger, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDebugUtilsMessengerEXT( m_instance, static_cast<VkDebugUtilsMessengerEXT>( messenger ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroy( VULKAN_HPP_NAMESPACE::DebugUtilsMessengerEXT messenger, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyDebugUtilsMessengerEXT( m_instance, static_cast<VkDebugUtilsMessengerEXT>( messenger ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroy( const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyInstance( m_instance, reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroy( Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroyInstance( m_instance, reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroySurfaceKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySurfaceKHR( m_instance, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroySurfaceKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySurfaceKHR( m_instance, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroy( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySurfaceKHR( m_instance, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::destroy( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkDestroySurfaceKHR( m_instance, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::enumeratePhysicalDeviceGroups( uint32_t* pPhysicalDeviceGroupCount, VULKAN_HPP_NAMESPACE::PhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkEnumeratePhysicalDeviceGroups( m_instance, pPhysicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( pPhysicalDeviceGroupProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PhysicalDeviceGroupProperties,Allocator>>::type Instance::enumeratePhysicalDeviceGroups(Dispatch const &d ) const
+ {
+ std::vector<PhysicalDeviceGroupProperties,Allocator> physicalDeviceGroupProperties;
+ uint32_t physicalDeviceGroupCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroups( m_instance, &physicalDeviceGroupCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && physicalDeviceGroupCount )
+ {
+ physicalDeviceGroupProperties.resize( physicalDeviceGroupCount );
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroups( m_instance, &physicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( physicalDeviceGroupProperties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( physicalDeviceGroupCount <= physicalDeviceGroupProperties.size() );
+ physicalDeviceGroupProperties.resize( physicalDeviceGroupCount );
+ }
+ return createResultValue( result, physicalDeviceGroupProperties, VULKAN_HPP_NAMESPACE_STRING"::Instance::enumeratePhysicalDeviceGroups" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PhysicalDeviceGroupProperties,Allocator>>::type Instance::enumeratePhysicalDeviceGroups(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PhysicalDeviceGroupProperties,Allocator> physicalDeviceGroupProperties( vectorAllocator );
+ uint32_t physicalDeviceGroupCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroups( m_instance, &physicalDeviceGroupCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && physicalDeviceGroupCount )
+ {
+ physicalDeviceGroupProperties.resize( physicalDeviceGroupCount );
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroups( m_instance, &physicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( physicalDeviceGroupProperties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( physicalDeviceGroupCount <= physicalDeviceGroupProperties.size() );
+ physicalDeviceGroupProperties.resize( physicalDeviceGroupCount );
+ }
+ return createResultValue( result, physicalDeviceGroupProperties, VULKAN_HPP_NAMESPACE_STRING"::Instance::enumeratePhysicalDeviceGroups" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::enumeratePhysicalDeviceGroupsKHR( uint32_t* pPhysicalDeviceGroupCount, VULKAN_HPP_NAMESPACE::PhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkEnumeratePhysicalDeviceGroupsKHR( m_instance, pPhysicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( pPhysicalDeviceGroupProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PhysicalDeviceGroupProperties,Allocator>>::type Instance::enumeratePhysicalDeviceGroupsKHR(Dispatch const &d ) const
+ {
+ std::vector<PhysicalDeviceGroupProperties,Allocator> physicalDeviceGroupProperties;
+ uint32_t physicalDeviceGroupCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroupsKHR( m_instance, &physicalDeviceGroupCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && physicalDeviceGroupCount )
+ {
+ physicalDeviceGroupProperties.resize( physicalDeviceGroupCount );
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroupsKHR( m_instance, &physicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( physicalDeviceGroupProperties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( physicalDeviceGroupCount <= physicalDeviceGroupProperties.size() );
+ physicalDeviceGroupProperties.resize( physicalDeviceGroupCount );
+ }
+ return createResultValue( result, physicalDeviceGroupProperties, VULKAN_HPP_NAMESPACE_STRING"::Instance::enumeratePhysicalDeviceGroupsKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PhysicalDeviceGroupProperties,Allocator>>::type Instance::enumeratePhysicalDeviceGroupsKHR(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PhysicalDeviceGroupProperties,Allocator> physicalDeviceGroupProperties( vectorAllocator );
+ uint32_t physicalDeviceGroupCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroupsKHR( m_instance, &physicalDeviceGroupCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && physicalDeviceGroupCount )
+ {
+ physicalDeviceGroupProperties.resize( physicalDeviceGroupCount );
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroupsKHR( m_instance, &physicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( physicalDeviceGroupProperties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( physicalDeviceGroupCount <= physicalDeviceGroupProperties.size() );
+ physicalDeviceGroupProperties.resize( physicalDeviceGroupCount );
+ }
+ return createResultValue( result, physicalDeviceGroupProperties, VULKAN_HPP_NAMESPACE_STRING"::Instance::enumeratePhysicalDeviceGroupsKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Instance::enumeratePhysicalDevices( uint32_t* pPhysicalDeviceCount, VULKAN_HPP_NAMESPACE::PhysicalDevice* pPhysicalDevices, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkEnumeratePhysicalDevices( m_instance, pPhysicalDeviceCount, reinterpret_cast<VkPhysicalDevice*>( pPhysicalDevices ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PhysicalDevice,Allocator>>::type Instance::enumeratePhysicalDevices(Dispatch const &d ) const
+ {
+ std::vector<PhysicalDevice,Allocator> physicalDevices;
+ uint32_t physicalDeviceCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumeratePhysicalDevices( m_instance, &physicalDeviceCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && physicalDeviceCount )
+ {
+ physicalDevices.resize( physicalDeviceCount );
+ result = static_cast<Result>( d.vkEnumeratePhysicalDevices( m_instance, &physicalDeviceCount, reinterpret_cast<VkPhysicalDevice*>( physicalDevices.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( physicalDeviceCount <= physicalDevices.size() );
+ physicalDevices.resize( physicalDeviceCount );
+ }
+ return createResultValue( result, physicalDevices, VULKAN_HPP_NAMESPACE_STRING"::Instance::enumeratePhysicalDevices" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PhysicalDevice,Allocator>>::type Instance::enumeratePhysicalDevices(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PhysicalDevice,Allocator> physicalDevices( vectorAllocator );
+ uint32_t physicalDeviceCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumeratePhysicalDevices( m_instance, &physicalDeviceCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && physicalDeviceCount )
+ {
+ physicalDevices.resize( physicalDeviceCount );
+ result = static_cast<Result>( d.vkEnumeratePhysicalDevices( m_instance, &physicalDeviceCount, reinterpret_cast<VkPhysicalDevice*>( physicalDevices.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( physicalDeviceCount <= physicalDevices.size() );
+ physicalDevices.resize( physicalDeviceCount );
+ }
+ return createResultValue( result, physicalDevices, VULKAN_HPP_NAMESPACE_STRING"::Instance::enumeratePhysicalDevices" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE PFN_vkVoidFunction Instance::getProcAddr( const char* pName, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetInstanceProcAddr( m_instance, pName );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE PFN_vkVoidFunction Instance::getProcAddr( const std::string & name, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetInstanceProcAddr( m_instance, name.c_str() );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::submitDebugUtilsMessageEXT( VULKAN_HPP_NAMESPACE::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VULKAN_HPP_NAMESPACE::DebugUtilsMessageTypeFlagsEXT messageTypes, const VULKAN_HPP_NAMESPACE::DebugUtilsMessengerCallbackDataEXT* pCallbackData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkSubmitDebugUtilsMessageEXT( m_instance, static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>( messageSeverity ), static_cast<VkDebugUtilsMessageTypeFlagsEXT>( messageTypes ), reinterpret_cast<const VkDebugUtilsMessengerCallbackDataEXT*>( pCallbackData ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Instance::submitDebugUtilsMessageEXT( VULKAN_HPP_NAMESPACE::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VULKAN_HPP_NAMESPACE::DebugUtilsMessageTypeFlagsEXT messageTypes, const DebugUtilsMessengerCallbackDataEXT & callbackData, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkSubmitDebugUtilsMessageEXT( m_instance, static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>( messageSeverity ), static_cast<VkDebugUtilsMessageTypeFlagsEXT>( messageTypes ), reinterpret_cast<const VkDebugUtilsMessengerCallbackDataEXT*>( &callbackData ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::acquireXlibDisplayEXT( Display* dpy, VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkAcquireXlibDisplayEXT( m_physicalDevice, dpy, static_cast<VkDisplayKHR>( display ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<Display>::type PhysicalDevice::acquireXlibDisplayEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d ) const
+ {
+ Display dpy;
+ Result result = static_cast<Result>( d.vkAcquireXlibDisplayEXT( m_physicalDevice, &dpy, static_cast<VkDisplayKHR>( display ) ) );
+ return createResultValue( result, dpy, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::acquireXlibDisplayEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XLIB_XRANDR_EXT*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::createDevice( const VULKAN_HPP_NAMESPACE::DeviceCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Device* pDevice, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateDevice( m_physicalDevice, reinterpret_cast<const VkDeviceCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDevice*>( pDevice ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Device>::type PhysicalDevice::createDevice( const DeviceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Device device;
+ Result result = static_cast<Result>( d.vkCreateDevice( m_physicalDevice, reinterpret_cast<const VkDeviceCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDevice*>( &device ) ) );
+ return createResultValue( result, device, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::createDevice" );
+ }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Device,Dispatch>>::type PhysicalDevice::createDeviceUnique( const DeviceCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Device device;
+ Result result = static_cast<Result>( d.vkCreateDevice( m_physicalDevice, reinterpret_cast<const VkDeviceCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDevice*>( &device ) ) );
+
+ ObjectDestroy<NoParent,Dispatch> deleter( allocator, d );
+ return createResultValue<Device,Dispatch>( result, device, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::createDeviceUnique", deleter );
+ }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::createDisplayModeKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, const VULKAN_HPP_NAMESPACE::DisplayModeCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DisplayModeKHR* pMode, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkCreateDisplayModeKHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), reinterpret_cast<const VkDisplayModeCreateInfoKHR*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDisplayModeKHR*>( pMode ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DisplayModeKHR>::type PhysicalDevice::createDisplayModeKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, const DisplayModeCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DisplayModeKHR mode;
+ Result result = static_cast<Result>( d.vkCreateDisplayModeKHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), reinterpret_cast<const VkDisplayModeCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDisplayModeKHR*>( &mode ) ) );
+ return createResultValue( result, mode, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::createDisplayModeKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::enumerateDeviceExtensionProperties( const char* pLayerName, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::ExtensionProperties* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkEnumerateDeviceExtensionProperties( m_physicalDevice, pLayerName, pPropertyCount, reinterpret_cast<VkExtensionProperties*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<ExtensionProperties,Allocator>>::type PhysicalDevice::enumerateDeviceExtensionProperties( Optional<const std::string> layerName, Dispatch const &d ) const
+ {
+ std::vector<ExtensionProperties,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumerateDeviceExtensionProperties( m_physicalDevice, layerName ? layerName->c_str() : nullptr, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkEnumerateDeviceExtensionProperties( m_physicalDevice, layerName ? layerName->c_str() : nullptr, &propertyCount, reinterpret_cast<VkExtensionProperties*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::enumerateDeviceExtensionProperties" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<ExtensionProperties,Allocator>>::type PhysicalDevice::enumerateDeviceExtensionProperties( Optional<const std::string> layerName, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<ExtensionProperties,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumerateDeviceExtensionProperties( m_physicalDevice, layerName ? layerName->c_str() : nullptr, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkEnumerateDeviceExtensionProperties( m_physicalDevice, layerName ? layerName->c_str() : nullptr, &propertyCount, reinterpret_cast<VkExtensionProperties*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::enumerateDeviceExtensionProperties" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::enumerateDeviceLayerProperties( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::LayerProperties* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkEnumerateDeviceLayerProperties( m_physicalDevice, pPropertyCount, reinterpret_cast<VkLayerProperties*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<LayerProperties,Allocator>>::type PhysicalDevice::enumerateDeviceLayerProperties(Dispatch const &d ) const
+ {
+ std::vector<LayerProperties,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkEnumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, reinterpret_cast<VkLayerProperties*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::enumerateDeviceLayerProperties" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<LayerProperties,Allocator>>::type PhysicalDevice::enumerateDeviceLayerProperties(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<LayerProperties,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkEnumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, reinterpret_cast<VkLayerProperties*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::enumerateDeviceLayerProperties" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::enumerateQueueFamilyPerformanceQueryCountersKHR( uint32_t queueFamilyIndex, uint32_t* pCounterCount, VULKAN_HPP_NAMESPACE::PerformanceCounterKHR* pCounters, VULKAN_HPP_NAMESPACE::PerformanceCounterDescriptionKHR* pCounterDescriptions, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( m_physicalDevice, queueFamilyIndex, pCounterCount, reinterpret_cast<VkPerformanceCounterKHR*>( pCounters ), reinterpret_cast<VkPerformanceCounterDescriptionKHR*>( pCounterDescriptions ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PerformanceCounterDescriptionKHR,Allocator>>::type PhysicalDevice::enumerateQueueFamilyPerformanceQueryCountersKHR( uint32_t queueFamilyIndex, ArrayProxy<VULKAN_HPP_NAMESPACE::PerformanceCounterKHR> counters, Dispatch const &d ) const
+ {
+ std::vector<PerformanceCounterDescriptionKHR,Allocator> counterDescriptions;
+ uint32_t counterCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( m_physicalDevice, queueFamilyIndex, counters.size() , reinterpret_cast<VkPerformanceCounterKHR*>( counters.data() ), nullptr ) );
+ if ( ( result == Result::eSuccess ) && counterCount )
+ {
+ counterDescriptions.resize( counterCount );
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( m_physicalDevice, queueFamilyIndex, counters.size() , reinterpret_cast<VkPerformanceCounterKHR*>( counters.data() ), reinterpret_cast<VkPerformanceCounterDescriptionKHR*>( counterDescriptions.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( counterCount <= counterDescriptions.size() );
+ counterDescriptions.resize( counterCount );
+ }
+ return createResultValue( result, counterDescriptions, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::enumerateQueueFamilyPerformanceQueryCountersKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PerformanceCounterDescriptionKHR,Allocator>>::type PhysicalDevice::enumerateQueueFamilyPerformanceQueryCountersKHR( uint32_t queueFamilyIndex, ArrayProxy<VULKAN_HPP_NAMESPACE::PerformanceCounterKHR> counters, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PerformanceCounterDescriptionKHR,Allocator> counterDescriptions( vectorAllocator );
+ uint32_t counterCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( m_physicalDevice, queueFamilyIndex, counters.size() , reinterpret_cast<VkPerformanceCounterKHR*>( counters.data() ), nullptr ) );
+ if ( ( result == Result::eSuccess ) && counterCount )
+ {
+ counterDescriptions.resize( counterCount );
+ result = static_cast<Result>( d.vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( m_physicalDevice, queueFamilyIndex, counters.size() , reinterpret_cast<VkPerformanceCounterKHR*>( counters.data() ), reinterpret_cast<VkPerformanceCounterDescriptionKHR*>( counterDescriptions.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( counterCount <= counterDescriptions.size() );
+ counterDescriptions.resize( counterCount );
+ }
+ return createResultValue( result, counterDescriptions, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::enumerateQueueFamilyPerformanceQueryCountersKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getDisplayModeProperties2KHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayModeProperties2KHR* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetDisplayModeProperties2KHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), pPropertyCount, reinterpret_cast<VkDisplayModeProperties2KHR*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayModeProperties2KHR,Allocator>>::type PhysicalDevice::getDisplayModeProperties2KHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d ) const
+ {
+ std::vector<DisplayModeProperties2KHR,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetDisplayModeProperties2KHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetDisplayModeProperties2KHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), &propertyCount, reinterpret_cast<VkDisplayModeProperties2KHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayModeProperties2KHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayModeProperties2KHR,Allocator>>::type PhysicalDevice::getDisplayModeProperties2KHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<DisplayModeProperties2KHR,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetDisplayModeProperties2KHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetDisplayModeProperties2KHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), &propertyCount, reinterpret_cast<VkDisplayModeProperties2KHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayModeProperties2KHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getDisplayModePropertiesKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayModePropertiesKHR* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetDisplayModePropertiesKHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), pPropertyCount, reinterpret_cast<VkDisplayModePropertiesKHR*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayModePropertiesKHR,Allocator>>::type PhysicalDevice::getDisplayModePropertiesKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d ) const
+ {
+ std::vector<DisplayModePropertiesKHR,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetDisplayModePropertiesKHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetDisplayModePropertiesKHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), &propertyCount, reinterpret_cast<VkDisplayModePropertiesKHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayModePropertiesKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayModePropertiesKHR,Allocator>>::type PhysicalDevice::getDisplayModePropertiesKHR( VULKAN_HPP_NAMESPACE::DisplayKHR display, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<DisplayModePropertiesKHR,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetDisplayModePropertiesKHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetDisplayModePropertiesKHR( m_physicalDevice, static_cast<VkDisplayKHR>( display ), &propertyCount, reinterpret_cast<VkDisplayModePropertiesKHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayModePropertiesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getDisplayPlaneCapabilities2KHR( const VULKAN_HPP_NAMESPACE::DisplayPlaneInfo2KHR* pDisplayPlaneInfo, VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilities2KHR* pCapabilities, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetDisplayPlaneCapabilities2KHR( m_physicalDevice, reinterpret_cast<const VkDisplayPlaneInfo2KHR*>( pDisplayPlaneInfo ), reinterpret_cast<VkDisplayPlaneCapabilities2KHR*>( pCapabilities ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilities2KHR>::type PhysicalDevice::getDisplayPlaneCapabilities2KHR( const DisplayPlaneInfo2KHR & displayPlaneInfo, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilities2KHR capabilities;
+ Result result = static_cast<Result>( d.vkGetDisplayPlaneCapabilities2KHR( m_physicalDevice, reinterpret_cast<const VkDisplayPlaneInfo2KHR*>( &displayPlaneInfo ), reinterpret_cast<VkDisplayPlaneCapabilities2KHR*>( &capabilities ) ) );
+ return createResultValue( result, capabilities, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayPlaneCapabilities2KHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getDisplayPlaneCapabilitiesKHR( VULKAN_HPP_NAMESPACE::DisplayModeKHR mode, uint32_t planeIndex, VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilitiesKHR* pCapabilities, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetDisplayPlaneCapabilitiesKHR( m_physicalDevice, static_cast<VkDisplayModeKHR>( mode ), planeIndex, reinterpret_cast<VkDisplayPlaneCapabilitiesKHR*>( pCapabilities ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilitiesKHR>::type PhysicalDevice::getDisplayPlaneCapabilitiesKHR( VULKAN_HPP_NAMESPACE::DisplayModeKHR mode, uint32_t planeIndex, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DisplayPlaneCapabilitiesKHR capabilities;
+ Result result = static_cast<Result>( d.vkGetDisplayPlaneCapabilitiesKHR( m_physicalDevice, static_cast<VkDisplayModeKHR>( mode ), planeIndex, reinterpret_cast<VkDisplayPlaneCapabilitiesKHR*>( &capabilities ) ) );
+ return createResultValue( result, capabilities, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayPlaneCapabilitiesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getDisplayPlaneSupportedDisplaysKHR( uint32_t planeIndex, uint32_t* pDisplayCount, VULKAN_HPP_NAMESPACE::DisplayKHR* pDisplays, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetDisplayPlaneSupportedDisplaysKHR( m_physicalDevice, planeIndex, pDisplayCount, reinterpret_cast<VkDisplayKHR*>( pDisplays ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayKHR,Allocator>>::type PhysicalDevice::getDisplayPlaneSupportedDisplaysKHR( uint32_t planeIndex, Dispatch const &d ) const
+ {
+ std::vector<DisplayKHR,Allocator> displays;
+ uint32_t displayCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetDisplayPlaneSupportedDisplaysKHR( m_physicalDevice, planeIndex, &displayCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && displayCount )
+ {
+ displays.resize( displayCount );
+ result = static_cast<Result>( d.vkGetDisplayPlaneSupportedDisplaysKHR( m_physicalDevice, planeIndex, &displayCount, reinterpret_cast<VkDisplayKHR*>( displays.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( displayCount <= displays.size() );
+ displays.resize( displayCount );
+ }
+ return createResultValue( result, displays, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayPlaneSupportedDisplaysKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayKHR,Allocator>>::type PhysicalDevice::getDisplayPlaneSupportedDisplaysKHR( uint32_t planeIndex, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<DisplayKHR,Allocator> displays( vectorAllocator );
+ uint32_t displayCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetDisplayPlaneSupportedDisplaysKHR( m_physicalDevice, planeIndex, &displayCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && displayCount )
+ {
+ displays.resize( displayCount );
+ result = static_cast<Result>( d.vkGetDisplayPlaneSupportedDisplaysKHR( m_physicalDevice, planeIndex, &displayCount, reinterpret_cast<VkDisplayKHR*>( displays.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( displayCount <= displays.size() );
+ displays.resize( displayCount );
+ }
+ return createResultValue( result, displays, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayPlaneSupportedDisplaysKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getCalibrateableTimeDomainsEXT( uint32_t* pTimeDomainCount, VULKAN_HPP_NAMESPACE::TimeDomainEXT* pTimeDomains, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( m_physicalDevice, pTimeDomainCount, reinterpret_cast<VkTimeDomainEXT*>( pTimeDomains ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<TimeDomainEXT,Allocator>>::type PhysicalDevice::getCalibrateableTimeDomainsEXT(Dispatch const &d ) const
+ {
+ std::vector<TimeDomainEXT,Allocator> timeDomains;
+ uint32_t timeDomainCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( m_physicalDevice, &timeDomainCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && timeDomainCount )
+ {
+ timeDomains.resize( timeDomainCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( m_physicalDevice, &timeDomainCount, reinterpret_cast<VkTimeDomainEXT*>( timeDomains.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( timeDomainCount <= timeDomains.size() );
+ timeDomains.resize( timeDomainCount );
+ }
+ return createResultValue( result, timeDomains, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getCalibrateableTimeDomainsEXT" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<TimeDomainEXT,Allocator>>::type PhysicalDevice::getCalibrateableTimeDomainsEXT(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<TimeDomainEXT,Allocator> timeDomains( vectorAllocator );
+ uint32_t timeDomainCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( m_physicalDevice, &timeDomainCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && timeDomainCount )
+ {
+ timeDomains.resize( timeDomainCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( m_physicalDevice, &timeDomainCount, reinterpret_cast<VkTimeDomainEXT*>( timeDomains.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( timeDomainCount <= timeDomains.size() );
+ timeDomains.resize( timeDomainCount );
+ }
+ return createResultValue( result, timeDomains, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getCalibrateableTimeDomainsEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getCooperativeMatrixPropertiesNV( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::CooperativeMatrixPropertiesNV* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( m_physicalDevice, pPropertyCount, reinterpret_cast<VkCooperativeMatrixPropertiesNV*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<CooperativeMatrixPropertiesNV,Allocator>>::type PhysicalDevice::getCooperativeMatrixPropertiesNV(Dispatch const &d ) const
+ {
+ std::vector<CooperativeMatrixPropertiesNV,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( m_physicalDevice, &propertyCount, reinterpret_cast<VkCooperativeMatrixPropertiesNV*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getCooperativeMatrixPropertiesNV" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<CooperativeMatrixPropertiesNV,Allocator>>::type PhysicalDevice::getCooperativeMatrixPropertiesNV(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<CooperativeMatrixPropertiesNV,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( m_physicalDevice, &propertyCount, reinterpret_cast<VkCooperativeMatrixPropertiesNV*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getCooperativeMatrixPropertiesNV" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getDisplayPlaneProperties2KHR( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayPlaneProperties2KHR* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceDisplayPlaneProperties2KHR( m_physicalDevice, pPropertyCount, reinterpret_cast<VkDisplayPlaneProperties2KHR*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayPlaneProperties2KHR,Allocator>>::type PhysicalDevice::getDisplayPlaneProperties2KHR(Dispatch const &d ) const
+ {
+ std::vector<DisplayPlaneProperties2KHR,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPlaneProperties2KHR( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPlaneProperties2KHR( m_physicalDevice, &propertyCount, reinterpret_cast<VkDisplayPlaneProperties2KHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayPlaneProperties2KHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayPlaneProperties2KHR,Allocator>>::type PhysicalDevice::getDisplayPlaneProperties2KHR(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<DisplayPlaneProperties2KHR,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPlaneProperties2KHR( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPlaneProperties2KHR( m_physicalDevice, &propertyCount, reinterpret_cast<VkDisplayPlaneProperties2KHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayPlaneProperties2KHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getDisplayPlanePropertiesKHR( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayPlanePropertiesKHR* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceDisplayPlanePropertiesKHR( m_physicalDevice, pPropertyCount, reinterpret_cast<VkDisplayPlanePropertiesKHR*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayPlanePropertiesKHR,Allocator>>::type PhysicalDevice::getDisplayPlanePropertiesKHR(Dispatch const &d ) const
+ {
+ std::vector<DisplayPlanePropertiesKHR,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPlanePropertiesKHR( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPlanePropertiesKHR( m_physicalDevice, &propertyCount, reinterpret_cast<VkDisplayPlanePropertiesKHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayPlanePropertiesKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayPlanePropertiesKHR,Allocator>>::type PhysicalDevice::getDisplayPlanePropertiesKHR(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<DisplayPlanePropertiesKHR,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPlanePropertiesKHR( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPlanePropertiesKHR( m_physicalDevice, &propertyCount, reinterpret_cast<VkDisplayPlanePropertiesKHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayPlanePropertiesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getDisplayProperties2KHR( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayProperties2KHR* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceDisplayProperties2KHR( m_physicalDevice, pPropertyCount, reinterpret_cast<VkDisplayProperties2KHR*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayProperties2KHR,Allocator>>::type PhysicalDevice::getDisplayProperties2KHR(Dispatch const &d ) const
+ {
+ std::vector<DisplayProperties2KHR,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayProperties2KHR( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayProperties2KHR( m_physicalDevice, &propertyCount, reinterpret_cast<VkDisplayProperties2KHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayProperties2KHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayProperties2KHR,Allocator>>::type PhysicalDevice::getDisplayProperties2KHR(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<DisplayProperties2KHR,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayProperties2KHR( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayProperties2KHR( m_physicalDevice, &propertyCount, reinterpret_cast<VkDisplayProperties2KHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayProperties2KHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getDisplayPropertiesKHR( uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::DisplayPropertiesKHR* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceDisplayPropertiesKHR( m_physicalDevice, pPropertyCount, reinterpret_cast<VkDisplayPropertiesKHR*>( pProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayPropertiesKHR,Allocator>>::type PhysicalDevice::getDisplayPropertiesKHR(Dispatch const &d ) const
+ {
+ std::vector<DisplayPropertiesKHR,Allocator> properties;
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPropertiesKHR( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPropertiesKHR( m_physicalDevice, &propertyCount, reinterpret_cast<VkDisplayPropertiesKHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayPropertiesKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<DisplayPropertiesKHR,Allocator>>::type PhysicalDevice::getDisplayPropertiesKHR(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<DisplayPropertiesKHR,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPropertiesKHR( m_physicalDevice, &propertyCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && propertyCount )
+ {
+ properties.resize( propertyCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceDisplayPropertiesKHR( m_physicalDevice, &propertyCount, reinterpret_cast<VkDisplayPropertiesKHR*>( properties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( propertyCount <= properties.size() );
+ properties.resize( propertyCount );
+ }
+ return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getDisplayPropertiesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getExternalBufferProperties( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VULKAN_HPP_NAMESPACE::ExternalBufferProperties* pExternalBufferProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceExternalBufferProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalBufferInfo*>( pExternalBufferInfo ), reinterpret_cast<VkExternalBufferProperties*>( pExternalBufferProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::ExternalBufferProperties PhysicalDevice::getExternalBufferProperties( const PhysicalDeviceExternalBufferInfo & externalBufferInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::ExternalBufferProperties externalBufferProperties;
+ d.vkGetPhysicalDeviceExternalBufferProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalBufferInfo*>( &externalBufferInfo ), reinterpret_cast<VkExternalBufferProperties*>( &externalBufferProperties ) );
+ return externalBufferProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getExternalBufferPropertiesKHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VULKAN_HPP_NAMESPACE::ExternalBufferProperties* pExternalBufferProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceExternalBufferPropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalBufferInfo*>( pExternalBufferInfo ), reinterpret_cast<VkExternalBufferProperties*>( pExternalBufferProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::ExternalBufferProperties PhysicalDevice::getExternalBufferPropertiesKHR( const PhysicalDeviceExternalBufferInfo & externalBufferInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::ExternalBufferProperties externalBufferProperties;
+ d.vkGetPhysicalDeviceExternalBufferPropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalBufferInfo*>( &externalBufferInfo ), reinterpret_cast<VkExternalBufferProperties*>( &externalBufferProperties ) );
+ return externalBufferProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getExternalFenceProperties( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VULKAN_HPP_NAMESPACE::ExternalFenceProperties* pExternalFenceProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceExternalFenceProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalFenceInfo*>( pExternalFenceInfo ), reinterpret_cast<VkExternalFenceProperties*>( pExternalFenceProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::ExternalFenceProperties PhysicalDevice::getExternalFenceProperties( const PhysicalDeviceExternalFenceInfo & externalFenceInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::ExternalFenceProperties externalFenceProperties;
+ d.vkGetPhysicalDeviceExternalFenceProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalFenceInfo*>( &externalFenceInfo ), reinterpret_cast<VkExternalFenceProperties*>( &externalFenceProperties ) );
+ return externalFenceProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getExternalFencePropertiesKHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VULKAN_HPP_NAMESPACE::ExternalFenceProperties* pExternalFenceProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceExternalFencePropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalFenceInfo*>( pExternalFenceInfo ), reinterpret_cast<VkExternalFenceProperties*>( pExternalFenceProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::ExternalFenceProperties PhysicalDevice::getExternalFencePropertiesKHR( const PhysicalDeviceExternalFenceInfo & externalFenceInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::ExternalFenceProperties externalFenceProperties;
+ d.vkGetPhysicalDeviceExternalFencePropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalFenceInfo*>( &externalFenceInfo ), reinterpret_cast<VkExternalFenceProperties*>( &externalFenceProperties ) );
+ return externalFenceProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getExternalImageFormatPropertiesNV( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::ImageTiling tiling, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageCreateFlags flags, VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV externalHandleType, VULKAN_HPP_NAMESPACE::ExternalImageFormatPropertiesNV* pExternalImageFormatProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceExternalImageFormatPropertiesNV( m_physicalDevice, static_cast<VkFormat>( format ), static_cast<VkImageType>( type ), static_cast<VkImageTiling>( tiling ), static_cast<VkImageUsageFlags>( usage ), static_cast<VkImageCreateFlags>( flags ), static_cast<VkExternalMemoryHandleTypeFlagsNV>( externalHandleType ), reinterpret_cast<VkExternalImageFormatPropertiesNV*>( pExternalImageFormatProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ExternalImageFormatPropertiesNV>::type PhysicalDevice::getExternalImageFormatPropertiesNV( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::ImageTiling tiling, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageCreateFlags flags, VULKAN_HPP_NAMESPACE::ExternalMemoryHandleTypeFlagsNV externalHandleType, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ExternalImageFormatPropertiesNV externalImageFormatProperties;
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceExternalImageFormatPropertiesNV( m_physicalDevice, static_cast<VkFormat>( format ), static_cast<VkImageType>( type ), static_cast<VkImageTiling>( tiling ), static_cast<VkImageUsageFlags>( usage ), static_cast<VkImageCreateFlags>( flags ), static_cast<VkExternalMemoryHandleTypeFlagsNV>( externalHandleType ), reinterpret_cast<VkExternalImageFormatPropertiesNV*>( &externalImageFormatProperties ) ) );
+ return createResultValue( result, externalImageFormatProperties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getExternalImageFormatPropertiesNV" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getExternalSemaphoreProperties( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties* pExternalSemaphoreProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceExternalSemaphoreProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalSemaphoreInfo*>( pExternalSemaphoreInfo ), reinterpret_cast<VkExternalSemaphoreProperties*>( pExternalSemaphoreProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties PhysicalDevice::getExternalSemaphoreProperties( const PhysicalDeviceExternalSemaphoreInfo & externalSemaphoreInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties externalSemaphoreProperties;
+ d.vkGetPhysicalDeviceExternalSemaphoreProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalSemaphoreInfo*>( &externalSemaphoreInfo ), reinterpret_cast<VkExternalSemaphoreProperties*>( &externalSemaphoreProperties ) );
+ return externalSemaphoreProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getExternalSemaphorePropertiesKHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties* pExternalSemaphoreProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalSemaphoreInfo*>( pExternalSemaphoreInfo ), reinterpret_cast<VkExternalSemaphoreProperties*>( pExternalSemaphoreProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties PhysicalDevice::getExternalSemaphorePropertiesKHR( const PhysicalDeviceExternalSemaphoreInfo & externalSemaphoreInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties externalSemaphoreProperties;
+ d.vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalSemaphoreInfo*>( &externalSemaphoreInfo ), reinterpret_cast<VkExternalSemaphoreProperties*>( &externalSemaphoreProperties ) );
+ return externalSemaphoreProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getFeatures( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures* pFeatures, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceFeatures( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures*>( pFeatures ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures PhysicalDevice::getFeatures(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures features;
+ d.vkGetPhysicalDeviceFeatures( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures*>( &features ) );
+ return features;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getFeatures2( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2* pFeatures, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceFeatures2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( pFeatures ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 PhysicalDevice::getFeatures2(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 features;
+ d.vkGetPhysicalDeviceFeatures2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( &features ) );
+ return features;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> PhysicalDevice::getFeatures2(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2& features = structureChain.template get<VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2>();
+ d.vkGetPhysicalDeviceFeatures2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( &features ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getFeatures2KHR( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2* pFeatures, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceFeatures2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( pFeatures ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 PhysicalDevice::getFeatures2KHR(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 features;
+ d.vkGetPhysicalDeviceFeatures2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( &features ) );
+ return features;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> PhysicalDevice::getFeatures2KHR(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2& features = structureChain.template get<VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2>();
+ d.vkGetPhysicalDeviceFeatures2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( &features ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::FormatProperties* pFormatProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceFormatProperties( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties*>( pFormatProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::FormatProperties PhysicalDevice::getFormatProperties( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::FormatProperties formatProperties;
+ d.vkGetPhysicalDeviceFormatProperties( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties*>( &formatProperties ) );
+ return formatProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getFormatProperties2( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::FormatProperties2* pFormatProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceFormatProperties2( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( pFormatProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::FormatProperties2 PhysicalDevice::getFormatProperties2( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::FormatProperties2 formatProperties;
+ d.vkGetPhysicalDeviceFormatProperties2( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( &formatProperties ) );
+ return formatProperties;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> PhysicalDevice::getFormatProperties2( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::FormatProperties2& formatProperties = structureChain.template get<VULKAN_HPP_NAMESPACE::FormatProperties2>();
+ d.vkGetPhysicalDeviceFormatProperties2( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( &formatProperties ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getFormatProperties2KHR( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::FormatProperties2* pFormatProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceFormatProperties2KHR( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( pFormatProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::FormatProperties2 PhysicalDevice::getFormatProperties2KHR( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::FormatProperties2 formatProperties;
+ d.vkGetPhysicalDeviceFormatProperties2KHR( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( &formatProperties ) );
+ return formatProperties;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> PhysicalDevice::getFormatProperties2KHR( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::FormatProperties2& formatProperties = structureChain.template get<VULKAN_HPP_NAMESPACE::FormatProperties2>();
+ d.vkGetPhysicalDeviceFormatProperties2KHR( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( &formatProperties ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getGeneratedCommandsPropertiesNVX( VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsFeaturesNVX* pFeatures, VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX* pLimits, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( m_physicalDevice, reinterpret_cast<VkDeviceGeneratedCommandsFeaturesNVX*>( pFeatures ), reinterpret_cast<VkDeviceGeneratedCommandsLimitsNVX*>( pLimits ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX PhysicalDevice::getGeneratedCommandsPropertiesNVX( DeviceGeneratedCommandsFeaturesNVX & features, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX limits;
+ d.vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( m_physicalDevice, reinterpret_cast<VkDeviceGeneratedCommandsFeaturesNVX*>( &features ), reinterpret_cast<VkDeviceGeneratedCommandsLimitsNVX*>( &limits ) );
+ return limits;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::ImageTiling tiling, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageCreateFlags flags, VULKAN_HPP_NAMESPACE::ImageFormatProperties* pImageFormatProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties( m_physicalDevice, static_cast<VkFormat>( format ), static_cast<VkImageType>( type ), static_cast<VkImageTiling>( tiling ), static_cast<VkImageUsageFlags>( usage ), static_cast<VkImageCreateFlags>( flags ), reinterpret_cast<VkImageFormatProperties*>( pImageFormatProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageFormatProperties>::type PhysicalDevice::getImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::ImageTiling tiling, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageCreateFlags flags, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ImageFormatProperties imageFormatProperties;
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties( m_physicalDevice, static_cast<VkFormat>( format ), static_cast<VkImageType>( type ), static_cast<VkImageTiling>( tiling ), static_cast<VkImageUsageFlags>( usage ), static_cast<VkImageCreateFlags>( flags ), reinterpret_cast<VkImageFormatProperties*>( &imageFormatProperties ) ) );
+ return createResultValue( result, imageFormatProperties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getImageFormatProperties" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getImageFormatProperties2( const VULKAN_HPP_NAMESPACE::PhysicalDeviceImageFormatInfo2* pImageFormatInfo, VULKAN_HPP_NAMESPACE::ImageFormatProperties2* pImageFormatProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( pImageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( pImageFormatProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageFormatProperties2>::type PhysicalDevice::getImageFormatProperties2( const PhysicalDeviceImageFormatInfo2 & imageFormatInfo, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ImageFormatProperties2 imageFormatProperties;
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( &imageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( &imageFormatProperties ) ) );
+ return createResultValue( result, imageFormatProperties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getImageFormatProperties2" );
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<StructureChain<X, Y, Z...>>::type PhysicalDevice::getImageFormatProperties2( const PhysicalDeviceImageFormatInfo2 & imageFormatInfo, Dispatch const &d ) const
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::ImageFormatProperties2& imageFormatProperties = structureChain.template get<VULKAN_HPP_NAMESPACE::ImageFormatProperties2>();
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( &imageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( &imageFormatProperties ) ) );
+ return createResultValue( result, structureChain, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getImageFormatProperties2" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getImageFormatProperties2KHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceImageFormatInfo2* pImageFormatInfo, VULKAN_HPP_NAMESPACE::ImageFormatProperties2* pImageFormatProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( pImageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( pImageFormatProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageFormatProperties2>::type PhysicalDevice::getImageFormatProperties2KHR( const PhysicalDeviceImageFormatInfo2 & imageFormatInfo, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::ImageFormatProperties2 imageFormatProperties;
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( &imageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( &imageFormatProperties ) ) );
+ return createResultValue( result, imageFormatProperties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getImageFormatProperties2KHR" );
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<StructureChain<X, Y, Z...>>::type PhysicalDevice::getImageFormatProperties2KHR( const PhysicalDeviceImageFormatInfo2 & imageFormatInfo, Dispatch const &d ) const
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::ImageFormatProperties2& imageFormatProperties = structureChain.template get<VULKAN_HPP_NAMESPACE::ImageFormatProperties2>();
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( &imageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( &imageFormatProperties ) ) );
+ return createResultValue( result, structureChain, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getImageFormatProperties2KHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getMemoryProperties( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties* pMemoryProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceMemoryProperties( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties*>( pMemoryProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties PhysicalDevice::getMemoryProperties(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties memoryProperties;
+ d.vkGetPhysicalDeviceMemoryProperties( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties*>( &memoryProperties ) );
+ return memoryProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getMemoryProperties2( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2* pMemoryProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceMemoryProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( pMemoryProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 PhysicalDevice::getMemoryProperties2(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 memoryProperties;
+ d.vkGetPhysicalDeviceMemoryProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( &memoryProperties ) );
+ return memoryProperties;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> PhysicalDevice::getMemoryProperties2(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2& memoryProperties = structureChain.template get<VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2>();
+ d.vkGetPhysicalDeviceMemoryProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( &memoryProperties ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getMemoryProperties2KHR( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2* pMemoryProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceMemoryProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( pMemoryProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 PhysicalDevice::getMemoryProperties2KHR(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 memoryProperties;
+ d.vkGetPhysicalDeviceMemoryProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( &memoryProperties ) );
+ return memoryProperties;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> PhysicalDevice::getMemoryProperties2KHR(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2& memoryProperties = structureChain.template get<VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2>();
+ d.vkGetPhysicalDeviceMemoryProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( &memoryProperties ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getMultisamplePropertiesEXT( VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples, VULKAN_HPP_NAMESPACE::MultisamplePropertiesEXT* pMultisampleProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceMultisamplePropertiesEXT( m_physicalDevice, static_cast<VkSampleCountFlagBits>( samples ), reinterpret_cast<VkMultisamplePropertiesEXT*>( pMultisampleProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MultisamplePropertiesEXT PhysicalDevice::getMultisamplePropertiesEXT( VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::MultisamplePropertiesEXT multisampleProperties;
+ d.vkGetPhysicalDeviceMultisamplePropertiesEXT( m_physicalDevice, static_cast<VkSampleCountFlagBits>( samples ), reinterpret_cast<VkMultisamplePropertiesEXT*>( &multisampleProperties ) );
+ return multisampleProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getPresentRectanglesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, uint32_t* pRectCount, VULKAN_HPP_NAMESPACE::Rect2D* pRects, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDevicePresentRectanglesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), pRectCount, reinterpret_cast<VkRect2D*>( pRects ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<Rect2D,Allocator>>::type PhysicalDevice::getPresentRectanglesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d ) const
+ {
+ std::vector<Rect2D,Allocator> rects;
+ uint32_t rectCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDevicePresentRectanglesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &rectCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && rectCount )
+ {
+ rects.resize( rectCount );
+ result = static_cast<Result>( d.vkGetPhysicalDevicePresentRectanglesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &rectCount, reinterpret_cast<VkRect2D*>( rects.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( rectCount <= rects.size() );
+ rects.resize( rectCount );
+ }
+ return createResultValue( result, rects, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getPresentRectanglesKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<Rect2D,Allocator>>::type PhysicalDevice::getPresentRectanglesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<Rect2D,Allocator> rects( vectorAllocator );
+ uint32_t rectCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDevicePresentRectanglesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &rectCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && rectCount )
+ {
+ rects.resize( rectCount );
+ result = static_cast<Result>( d.vkGetPhysicalDevicePresentRectanglesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &rectCount, reinterpret_cast<VkRect2D*>( rects.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( rectCount <= rects.size() );
+ rects.resize( rectCount );
+ }
+ return createResultValue( result, rects, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getPresentRectanglesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getProperties( VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceProperties( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties*>( pProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties PhysicalDevice::getProperties(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties properties;
+ d.vkGetPhysicalDeviceProperties( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties*>( &properties ) );
+ return properties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getProperties2( VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( pProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 PhysicalDevice::getProperties2(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 properties;
+ d.vkGetPhysicalDeviceProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( &properties ) );
+ return properties;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> PhysicalDevice::getProperties2(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2& properties = structureChain.template get<VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2>();
+ d.vkGetPhysicalDeviceProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( &properties ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getProperties2KHR( VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( pProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 PhysicalDevice::getProperties2KHR(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 properties;
+ d.vkGetPhysicalDeviceProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( &properties ) );
+ return properties;
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE StructureChain<X, Y, Z...> PhysicalDevice::getProperties2KHR(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2& properties = structureChain.template get<VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2>();
+ d.vkGetPhysicalDeviceProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( &properties ) );
+ return structureChain;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getQueueFamilyPerformanceQueryPassesKHR( const VULKAN_HPP_NAMESPACE::QueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( m_physicalDevice, reinterpret_cast<const VkQueryPoolPerformanceCreateInfoKHR*>( pPerformanceQueryCreateInfo ), pNumPasses );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE uint32_t PhysicalDevice::getQueueFamilyPerformanceQueryPassesKHR( const QueryPoolPerformanceCreateInfoKHR & performanceQueryCreateInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ uint32_t numPasses;
+ d.vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( m_physicalDevice, reinterpret_cast<const VkQueryPoolPerformanceCreateInfoKHR*>( &performanceQueryCreateInfo ), &numPasses );
+ return numPasses;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getQueueFamilyProperties( uint32_t* pQueueFamilyPropertyCount, VULKAN_HPP_NAMESPACE::QueueFamilyProperties* pQueueFamilyProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceQueueFamilyProperties( m_physicalDevice, pQueueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties*>( pQueueFamilyProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<QueueFamilyProperties,Allocator> PhysicalDevice::getQueueFamilyProperties(Dispatch const &d ) const
+ {
+ std::vector<QueueFamilyProperties,Allocator> queueFamilyProperties;
+ uint32_t queueFamilyPropertyCount;
+ d.vkGetPhysicalDeviceQueueFamilyProperties( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+ queueFamilyProperties.resize( queueFamilyPropertyCount );
+ d.vkGetPhysicalDeviceQueueFamilyProperties( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties*>( queueFamilyProperties.data() ) );
+ return queueFamilyProperties;
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<QueueFamilyProperties,Allocator> PhysicalDevice::getQueueFamilyProperties(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<QueueFamilyProperties,Allocator> queueFamilyProperties( vectorAllocator );
+ uint32_t queueFamilyPropertyCount;
+ d.vkGetPhysicalDeviceQueueFamilyProperties( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+ queueFamilyProperties.resize( queueFamilyPropertyCount );
+ d.vkGetPhysicalDeviceQueueFamilyProperties( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties*>( queueFamilyProperties.data() ) );
+ return queueFamilyProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getQueueFamilyProperties2( uint32_t* pQueueFamilyPropertyCount, VULKAN_HPP_NAMESPACE::QueueFamilyProperties2* pQueueFamilyProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, pQueueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( pQueueFamilyProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<QueueFamilyProperties2,Allocator> PhysicalDevice::getQueueFamilyProperties2(Dispatch const &d ) const
+ {
+ std::vector<QueueFamilyProperties2,Allocator> queueFamilyProperties;
+ uint32_t queueFamilyPropertyCount;
+ d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+ queueFamilyProperties.resize( queueFamilyPropertyCount );
+ d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( queueFamilyProperties.data() ) );
+ return queueFamilyProperties;
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<QueueFamilyProperties2,Allocator> PhysicalDevice::getQueueFamilyProperties2(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<QueueFamilyProperties2,Allocator> queueFamilyProperties( vectorAllocator );
+ uint32_t queueFamilyPropertyCount;
+ d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+ queueFamilyProperties.resize( queueFamilyPropertyCount );
+ d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( queueFamilyProperties.data() ) );
+ return queueFamilyProperties;
+ }
+ template<typename StructureChain, typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<StructureChain,Allocator> PhysicalDevice::getQueueFamilyProperties2(Dispatch const &d ) const
+ {
+ std::vector<StructureChain,Allocator> queueFamilyProperties;
+ uint32_t queueFamilyPropertyCount;
+ d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+ queueFamilyProperties.resize( queueFamilyPropertyCount );
+ std::vector<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2> localVector( queueFamilyPropertyCount );
+ for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
+ {
+ localVector[i].pNext = queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>().pNext;
+ }
+ d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( localVector.data() ) );
+ for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
+ {
+ queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>() = localVector[i];
+ }
+ return queueFamilyProperties;
+ }
+ template<typename StructureChain, typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<StructureChain,Allocator> PhysicalDevice::getQueueFamilyProperties2(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<StructureChain,Allocator> queueFamilyProperties( vectorAllocator );
+ uint32_t queueFamilyPropertyCount;
+ d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+ queueFamilyProperties.resize( queueFamilyPropertyCount );
+ std::vector<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2> localVector( queueFamilyPropertyCount );
+ for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
+ {
+ localVector[i].pNext = queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>().pNext;
+ }
+ d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( localVector.data() ) );
+ for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
+ {
+ queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>() = localVector[i];
+ }
+ return queueFamilyProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getQueueFamilyProperties2KHR( uint32_t* pQueueFamilyPropertyCount, VULKAN_HPP_NAMESPACE::QueueFamilyProperties2* pQueueFamilyProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, pQueueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( pQueueFamilyProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<QueueFamilyProperties2,Allocator> PhysicalDevice::getQueueFamilyProperties2KHR(Dispatch const &d ) const
+ {
+ std::vector<QueueFamilyProperties2,Allocator> queueFamilyProperties;
+ uint32_t queueFamilyPropertyCount;
+ d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+ queueFamilyProperties.resize( queueFamilyPropertyCount );
+ d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( queueFamilyProperties.data() ) );
+ return queueFamilyProperties;
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<QueueFamilyProperties2,Allocator> PhysicalDevice::getQueueFamilyProperties2KHR(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<QueueFamilyProperties2,Allocator> queueFamilyProperties( vectorAllocator );
+ uint32_t queueFamilyPropertyCount;
+ d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+ queueFamilyProperties.resize( queueFamilyPropertyCount );
+ d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( queueFamilyProperties.data() ) );
+ return queueFamilyProperties;
+ }
+ template<typename StructureChain, typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<StructureChain,Allocator> PhysicalDevice::getQueueFamilyProperties2KHR(Dispatch const &d ) const
+ {
+ std::vector<StructureChain,Allocator> queueFamilyProperties;
+ uint32_t queueFamilyPropertyCount;
+ d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+ queueFamilyProperties.resize( queueFamilyPropertyCount );
+ std::vector<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2> localVector( queueFamilyPropertyCount );
+ for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
+ {
+ localVector[i].pNext = queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>().pNext;
+ }
+ d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( localVector.data() ) );
+ for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
+ {
+ queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>() = localVector[i];
+ }
+ return queueFamilyProperties;
+ }
+ template<typename StructureChain, typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<StructureChain,Allocator> PhysicalDevice::getQueueFamilyProperties2KHR(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<StructureChain,Allocator> queueFamilyProperties( vectorAllocator );
+ uint32_t queueFamilyPropertyCount;
+ d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+ queueFamilyProperties.resize( queueFamilyPropertyCount );
+ std::vector<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2> localVector( queueFamilyPropertyCount );
+ for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
+ {
+ localVector[i].pNext = queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>().pNext;
+ }
+ d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( localVector.data() ) );
+ for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
+ {
+ queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>() = localVector[i];
+ }
+ return queueFamilyProperties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getSparseImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageTiling tiling, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::SparseImageFormatProperties* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceSparseImageFormatProperties( m_physicalDevice, static_cast<VkFormat>( format ), static_cast<VkImageType>( type ), static_cast<VkSampleCountFlagBits>( samples ), static_cast<VkImageUsageFlags>( usage ), static_cast<VkImageTiling>( tiling ), pPropertyCount, reinterpret_cast<VkSparseImageFormatProperties*>( pProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageFormatProperties,Allocator> PhysicalDevice::getSparseImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageTiling tiling, Dispatch const &d ) const
+ {
+ std::vector<SparseImageFormatProperties,Allocator> properties;
+ uint32_t propertyCount;
+ d.vkGetPhysicalDeviceSparseImageFormatProperties( m_physicalDevice, static_cast<VkFormat>( format ), static_cast<VkImageType>( type ), static_cast<VkSampleCountFlagBits>( samples ), static_cast<VkImageUsageFlags>( usage ), static_cast<VkImageTiling>( tiling ), &propertyCount, nullptr );
+ properties.resize( propertyCount );
+ d.vkGetPhysicalDeviceSparseImageFormatProperties( m_physicalDevice, static_cast<VkFormat>( format ), static_cast<VkImageType>( type ), static_cast<VkSampleCountFlagBits>( samples ), static_cast<VkImageUsageFlags>( usage ), static_cast<VkImageTiling>( tiling ), &propertyCount, reinterpret_cast<VkSparseImageFormatProperties*>( properties.data() ) );
+ return properties;
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageFormatProperties,Allocator> PhysicalDevice::getSparseImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::SampleCountFlagBits samples, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageTiling tiling, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<SparseImageFormatProperties,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ d.vkGetPhysicalDeviceSparseImageFormatProperties( m_physicalDevice, static_cast<VkFormat>( format ), static_cast<VkImageType>( type ), static_cast<VkSampleCountFlagBits>( samples ), static_cast<VkImageUsageFlags>( usage ), static_cast<VkImageTiling>( tiling ), &propertyCount, nullptr );
+ properties.resize( propertyCount );
+ d.vkGetPhysicalDeviceSparseImageFormatProperties( m_physicalDevice, static_cast<VkFormat>( format ), static_cast<VkImageType>( type ), static_cast<VkSampleCountFlagBits>( samples ), static_cast<VkImageUsageFlags>( usage ), static_cast<VkImageTiling>( tiling ), &propertyCount, reinterpret_cast<VkSparseImageFormatProperties*>( properties.data() ) );
+ return properties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getSparseImageFormatProperties2( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::SparseImageFormatProperties2* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceSparseImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( pFormatInfo ), pPropertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( pProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageFormatProperties2,Allocator> PhysicalDevice::getSparseImageFormatProperties2( const PhysicalDeviceSparseImageFormatInfo2 & formatInfo, Dispatch const &d ) const
+ {
+ std::vector<SparseImageFormatProperties2,Allocator> properties;
+ uint32_t propertyCount;
+ d.vkGetPhysicalDeviceSparseImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, nullptr );
+ properties.resize( propertyCount );
+ d.vkGetPhysicalDeviceSparseImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( properties.data() ) );
+ return properties;
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageFormatProperties2,Allocator> PhysicalDevice::getSparseImageFormatProperties2( const PhysicalDeviceSparseImageFormatInfo2 & formatInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<SparseImageFormatProperties2,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ d.vkGetPhysicalDeviceSparseImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, nullptr );
+ properties.resize( propertyCount );
+ d.vkGetPhysicalDeviceSparseImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( properties.data() ) );
+ return properties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void PhysicalDevice::getSparseImageFormatProperties2KHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::SparseImageFormatProperties2* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetPhysicalDeviceSparseImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( pFormatInfo ), pPropertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( pProperties ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageFormatProperties2,Allocator> PhysicalDevice::getSparseImageFormatProperties2KHR( const PhysicalDeviceSparseImageFormatInfo2 & formatInfo, Dispatch const &d ) const
+ {
+ std::vector<SparseImageFormatProperties2,Allocator> properties;
+ uint32_t propertyCount;
+ d.vkGetPhysicalDeviceSparseImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, nullptr );
+ properties.resize( propertyCount );
+ d.vkGetPhysicalDeviceSparseImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( properties.data() ) );
+ return properties;
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<SparseImageFormatProperties2,Allocator> PhysicalDevice::getSparseImageFormatProperties2KHR( const PhysicalDeviceSparseImageFormatInfo2 & formatInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<SparseImageFormatProperties2,Allocator> properties( vectorAllocator );
+ uint32_t propertyCount;
+ d.vkGetPhysicalDeviceSparseImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, nullptr );
+ properties.resize( propertyCount );
+ d.vkGetPhysicalDeviceSparseImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( properties.data() ) );
+ return properties;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getSupportedFramebufferMixedSamplesCombinationsNV( uint32_t* pCombinationCount, VULKAN_HPP_NAMESPACE::FramebufferMixedSamplesCombinationNV* pCombinations, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( m_physicalDevice, pCombinationCount, reinterpret_cast<VkFramebufferMixedSamplesCombinationNV*>( pCombinations ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<FramebufferMixedSamplesCombinationNV,Allocator>>::type PhysicalDevice::getSupportedFramebufferMixedSamplesCombinationsNV(Dispatch const &d ) const
+ {
+ std::vector<FramebufferMixedSamplesCombinationNV,Allocator> combinations;
+ uint32_t combinationCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( m_physicalDevice, &combinationCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && combinationCount )
+ {
+ combinations.resize( combinationCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( m_physicalDevice, &combinationCount, reinterpret_cast<VkFramebufferMixedSamplesCombinationNV*>( combinations.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( combinationCount <= combinations.size() );
+ combinations.resize( combinationCount );
+ }
+ return createResultValue( result, combinations, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSupportedFramebufferMixedSamplesCombinationsNV" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<FramebufferMixedSamplesCombinationNV,Allocator>>::type PhysicalDevice::getSupportedFramebufferMixedSamplesCombinationsNV(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<FramebufferMixedSamplesCombinationNV,Allocator> combinations( vectorAllocator );
+ uint32_t combinationCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( m_physicalDevice, &combinationCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && combinationCount )
+ {
+ combinations.resize( combinationCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( m_physicalDevice, &combinationCount, reinterpret_cast<VkFramebufferMixedSamplesCombinationNV*>( combinations.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( combinationCount <= combinations.size() );
+ combinations.resize( combinationCount );
+ }
+ return createResultValue( result, combinations, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSupportedFramebufferMixedSamplesCombinationsNV" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getSurfaceCapabilities2EXT( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, VULKAN_HPP_NAMESPACE::SurfaceCapabilities2EXT* pSurfaceCapabilities, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceSurfaceCapabilities2EXT( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<VkSurfaceCapabilities2EXT*>( pSurfaceCapabilities ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceCapabilities2EXT>::type PhysicalDevice::getSurfaceCapabilities2EXT( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceCapabilities2EXT surfaceCapabilities;
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceCapabilities2EXT( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<VkSurfaceCapabilities2EXT*>( &surfaceCapabilities ) ) );
+ return createResultValue( result, surfaceCapabilities, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfaceCapabilities2EXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getSurfaceCapabilities2KHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR* pSurfaceCapabilities, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceSurfaceCapabilities2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( pSurfaceInfo ), reinterpret_cast<VkSurfaceCapabilities2KHR*>( pSurfaceCapabilities ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR>::type PhysicalDevice::getSurfaceCapabilities2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR surfaceCapabilities;
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceCapabilities2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), reinterpret_cast<VkSurfaceCapabilities2KHR*>( &surfaceCapabilities ) ) );
+ return createResultValue( result, surfaceCapabilities, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfaceCapabilities2KHR" );
+ }
+ template<typename X, typename Y, typename ...Z, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<StructureChain<X, Y, Z...>>::type PhysicalDevice::getSurfaceCapabilities2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Dispatch const &d ) const
+ {
+ StructureChain<X, Y, Z...> structureChain;
+ VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR& surfaceCapabilities = structureChain.template get<VULKAN_HPP_NAMESPACE::SurfaceCapabilities2KHR>();
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceCapabilities2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), reinterpret_cast<VkSurfaceCapabilities2KHR*>( &surfaceCapabilities ) ) );
+ return createResultValue( result, structureChain, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfaceCapabilities2KHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getSurfaceCapabilitiesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesKHR* pSurfaceCapabilities, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceSurfaceCapabilitiesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<VkSurfaceCapabilitiesKHR*>( pSurfaceCapabilities ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesKHR>::type PhysicalDevice::getSurfaceCapabilitiesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::SurfaceCapabilitiesKHR surfaceCapabilities;
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceCapabilitiesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<VkSurfaceCapabilitiesKHR*>( &surfaceCapabilities ) ) );
+ return createResultValue( result, surfaceCapabilities, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfaceCapabilitiesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getSurfaceFormats2KHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VULKAN_HPP_NAMESPACE::SurfaceFormat2KHR* pSurfaceFormats, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceSurfaceFormats2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( pSurfaceInfo ), pSurfaceFormatCount, reinterpret_cast<VkSurfaceFormat2KHR*>( pSurfaceFormats ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<SurfaceFormat2KHR,Allocator>>::type PhysicalDevice::getSurfaceFormats2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Dispatch const &d ) const
+ {
+ std::vector<SurfaceFormat2KHR,Allocator> surfaceFormats;
+ uint32_t surfaceFormatCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceFormats2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), &surfaceFormatCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && surfaceFormatCount )
+ {
+ surfaceFormats.resize( surfaceFormatCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceFormats2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), &surfaceFormatCount, reinterpret_cast<VkSurfaceFormat2KHR*>( surfaceFormats.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( surfaceFormatCount <= surfaceFormats.size() );
+ surfaceFormats.resize( surfaceFormatCount );
+ }
+ return createResultValue( result, surfaceFormats, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfaceFormats2KHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<SurfaceFormat2KHR,Allocator>>::type PhysicalDevice::getSurfaceFormats2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<SurfaceFormat2KHR,Allocator> surfaceFormats( vectorAllocator );
+ uint32_t surfaceFormatCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceFormats2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), &surfaceFormatCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && surfaceFormatCount )
+ {
+ surfaceFormats.resize( surfaceFormatCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceFormats2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), &surfaceFormatCount, reinterpret_cast<VkSurfaceFormat2KHR*>( surfaceFormats.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( surfaceFormatCount <= surfaceFormats.size() );
+ surfaceFormats.resize( surfaceFormatCount );
+ }
+ return createResultValue( result, surfaceFormats, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfaceFormats2KHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getSurfaceFormatsKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, uint32_t* pSurfaceFormatCount, VULKAN_HPP_NAMESPACE::SurfaceFormatKHR* pSurfaceFormats, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceSurfaceFormatsKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), pSurfaceFormatCount, reinterpret_cast<VkSurfaceFormatKHR*>( pSurfaceFormats ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<SurfaceFormatKHR,Allocator>>::type PhysicalDevice::getSurfaceFormatsKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d ) const
+ {
+ std::vector<SurfaceFormatKHR,Allocator> surfaceFormats;
+ uint32_t surfaceFormatCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceFormatsKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &surfaceFormatCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && surfaceFormatCount )
+ {
+ surfaceFormats.resize( surfaceFormatCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceFormatsKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &surfaceFormatCount, reinterpret_cast<VkSurfaceFormatKHR*>( surfaceFormats.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( surfaceFormatCount <= surfaceFormats.size() );
+ surfaceFormats.resize( surfaceFormatCount );
+ }
+ return createResultValue( result, surfaceFormats, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfaceFormatsKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<SurfaceFormatKHR,Allocator>>::type PhysicalDevice::getSurfaceFormatsKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<SurfaceFormatKHR,Allocator> surfaceFormats( vectorAllocator );
+ uint32_t surfaceFormatCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceFormatsKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &surfaceFormatCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && surfaceFormatCount )
+ {
+ surfaceFormats.resize( surfaceFormatCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceFormatsKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &surfaceFormatCount, reinterpret_cast<VkSurfaceFormatKHR*>( surfaceFormats.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( surfaceFormatCount <= surfaceFormats.size() );
+ surfaceFormats.resize( surfaceFormatCount );
+ }
+ return createResultValue( result, surfaceFormats, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfaceFormatsKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getSurfacePresentModes2EXT( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pPresentModeCount, VULKAN_HPP_NAMESPACE::PresentModeKHR* pPresentModes, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceSurfacePresentModes2EXT( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( pSurfaceInfo ), pPresentModeCount, reinterpret_cast<VkPresentModeKHR*>( pPresentModes ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PresentModeKHR,Allocator>>::type PhysicalDevice::getSurfacePresentModes2EXT( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Dispatch const &d ) const
+ {
+ std::vector<PresentModeKHR,Allocator> presentModes;
+ uint32_t presentModeCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfacePresentModes2EXT( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), &presentModeCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && presentModeCount )
+ {
+ presentModes.resize( presentModeCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfacePresentModes2EXT( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), &presentModeCount, reinterpret_cast<VkPresentModeKHR*>( presentModes.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( presentModeCount <= presentModes.size() );
+ presentModes.resize( presentModeCount );
+ }
+ return createResultValue( result, presentModes, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfacePresentModes2EXT" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PresentModeKHR,Allocator>>::type PhysicalDevice::getSurfacePresentModes2EXT( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PresentModeKHR,Allocator> presentModes( vectorAllocator );
+ uint32_t presentModeCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfacePresentModes2EXT( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), &presentModeCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && presentModeCount )
+ {
+ presentModes.resize( presentModeCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfacePresentModes2EXT( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), &presentModeCount, reinterpret_cast<VkPresentModeKHR*>( presentModes.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( presentModeCount <= presentModes.size() );
+ presentModes.resize( presentModeCount );
+ }
+ return createResultValue( result, presentModes, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfacePresentModes2EXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getSurfacePresentModesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, uint32_t* pPresentModeCount, VULKAN_HPP_NAMESPACE::PresentModeKHR* pPresentModes, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceSurfacePresentModesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), pPresentModeCount, reinterpret_cast<VkPresentModeKHR*>( pPresentModes ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PresentModeKHR,Allocator>>::type PhysicalDevice::getSurfacePresentModesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d ) const
+ {
+ std::vector<PresentModeKHR,Allocator> presentModes;
+ uint32_t presentModeCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfacePresentModesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &presentModeCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && presentModeCount )
+ {
+ presentModes.resize( presentModeCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfacePresentModesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &presentModeCount, reinterpret_cast<VkPresentModeKHR*>( presentModes.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( presentModeCount <= presentModes.size() );
+ presentModes.resize( presentModeCount );
+ }
+ return createResultValue( result, presentModes, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfacePresentModesKHR" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PresentModeKHR,Allocator>>::type PhysicalDevice::getSurfacePresentModesKHR( VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PresentModeKHR,Allocator> presentModes( vectorAllocator );
+ uint32_t presentModeCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfacePresentModesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &presentModeCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && presentModeCount )
+ {
+ presentModes.resize( presentModeCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceSurfacePresentModesKHR( m_physicalDevice, static_cast<VkSurfaceKHR>( surface ), &presentModeCount, reinterpret_cast<VkPresentModeKHR*>( presentModes.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( presentModeCount <= presentModes.size() );
+ presentModes.resize( presentModeCount );
+ }
+ return createResultValue( result, presentModes, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfacePresentModesKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getSurfaceSupportKHR( uint32_t queueFamilyIndex, VULKAN_HPP_NAMESPACE::SurfaceKHR surface, VULKAN_HPP_NAMESPACE::Bool32* pSupported, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceSurfaceSupportKHR( m_physicalDevice, queueFamilyIndex, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<VkBool32*>( pSupported ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::Bool32>::type PhysicalDevice::getSurfaceSupportKHR( uint32_t queueFamilyIndex, VULKAN_HPP_NAMESPACE::SurfaceKHR surface, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::Bool32 supported;
+ Result result = static_cast<Result>( d.vkGetPhysicalDeviceSurfaceSupportKHR( m_physicalDevice, queueFamilyIndex, static_cast<VkSurfaceKHR>( surface ), reinterpret_cast<VkBool32*>( &supported ) ) );
+ return createResultValue( result, supported, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getSurfaceSupportKHR" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getToolPropertiesEXT( uint32_t* pToolCount, VULKAN_HPP_NAMESPACE::PhysicalDeviceToolPropertiesEXT* pToolProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetPhysicalDeviceToolPropertiesEXT( m_physicalDevice, pToolCount, reinterpret_cast<VkPhysicalDeviceToolPropertiesEXT*>( pToolProperties ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PhysicalDeviceToolPropertiesEXT,Allocator>>::type PhysicalDevice::getToolPropertiesEXT(Dispatch const &d ) const
+ {
+ std::vector<PhysicalDeviceToolPropertiesEXT,Allocator> toolProperties;
+ uint32_t toolCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceToolPropertiesEXT( m_physicalDevice, &toolCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && toolCount )
+ {
+ toolProperties.resize( toolCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceToolPropertiesEXT( m_physicalDevice, &toolCount, reinterpret_cast<VkPhysicalDeviceToolPropertiesEXT*>( toolProperties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( toolCount <= toolProperties.size() );
+ toolProperties.resize( toolCount );
+ }
+ return createResultValue( result, toolProperties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getToolPropertiesEXT" );
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<std::vector<PhysicalDeviceToolPropertiesEXT,Allocator>>::type PhysicalDevice::getToolPropertiesEXT(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<PhysicalDeviceToolPropertiesEXT,Allocator> toolProperties( vectorAllocator );
+ uint32_t toolCount;
+ Result result;
+ do
+ {
+ result = static_cast<Result>( d.vkGetPhysicalDeviceToolPropertiesEXT( m_physicalDevice, &toolCount, nullptr ) );
+ if ( ( result == Result::eSuccess ) && toolCount )
+ {
+ toolProperties.resize( toolCount );
+ result = static_cast<Result>( d.vkGetPhysicalDeviceToolPropertiesEXT( m_physicalDevice, &toolCount, reinterpret_cast<VkPhysicalDeviceToolPropertiesEXT*>( toolProperties.data() ) ) );
+ }
+ } while ( result == Result::eIncomplete );
+ if ( result == Result::eSuccess )
+ {
+ VULKAN_HPP_ASSERT( toolCount <= toolProperties.size() );
+ toolProperties.resize( toolCount );
+ }
+ return createResultValue( result, toolProperties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getToolPropertiesEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Bool32 PhysicalDevice::getWaylandPresentationSupportKHR( uint32_t queueFamilyIndex, struct wl_display* display, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Bool32>( d.vkGetPhysicalDeviceWaylandPresentationSupportKHR( m_physicalDevice, queueFamilyIndex, display ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Bool32 PhysicalDevice::getWaylandPresentationSupportKHR( uint32_t queueFamilyIndex, struct wl_display & display, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetPhysicalDeviceWaylandPresentationSupportKHR( m_physicalDevice, queueFamilyIndex, &display );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Bool32 PhysicalDevice::getWin32PresentationSupportKHR( uint32_t queueFamilyIndex, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Bool32>( d.vkGetPhysicalDeviceWin32PresentationSupportKHR( m_physicalDevice, queueFamilyIndex ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Bool32 PhysicalDevice::getWin32PresentationSupportKHR( uint32_t queueFamilyIndex, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetPhysicalDeviceWin32PresentationSupportKHR( m_physicalDevice, queueFamilyIndex );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Bool32 PhysicalDevice::getXcbPresentationSupportKHR( uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Bool32>( d.vkGetPhysicalDeviceXcbPresentationSupportKHR( m_physicalDevice, queueFamilyIndex, connection, visual_id ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Bool32 PhysicalDevice::getXcbPresentationSupportKHR( uint32_t queueFamilyIndex, xcb_connection_t & connection, xcb_visualid_t visual_id, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetPhysicalDeviceXcbPresentationSupportKHR( m_physicalDevice, queueFamilyIndex, &connection, visual_id );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Bool32 PhysicalDevice::getXlibPresentationSupportKHR( uint32_t queueFamilyIndex, Display* dpy, VisualID visualID, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Bool32>( d.vkGetPhysicalDeviceXlibPresentationSupportKHR( m_physicalDevice, queueFamilyIndex, dpy, visualID ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Bool32 PhysicalDevice::getXlibPresentationSupportKHR( uint32_t queueFamilyIndex, Display & dpy, VisualID visualID, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ return d.vkGetPhysicalDeviceXlibPresentationSupportKHR( m_physicalDevice, queueFamilyIndex, &dpy, visualID );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::getRandROutputDisplayEXT( Display* dpy, RROutput rrOutput, VULKAN_HPP_NAMESPACE::DisplayKHR* pDisplay, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkGetRandROutputDisplayEXT( m_physicalDevice, dpy, rrOutput, reinterpret_cast<VkDisplayKHR*>( pDisplay ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DisplayKHR>::type PhysicalDevice::getRandROutputDisplayEXT( Display & dpy, RROutput rrOutput, Dispatch const &d ) const
+ {
+ VULKAN_HPP_NAMESPACE::DisplayKHR display;
+ Result result = static_cast<Result>( d.vkGetRandROutputDisplayEXT( m_physicalDevice, &dpy, rrOutput, reinterpret_cast<VkDisplayKHR*>( &display ) ) );
+ return createResultValue( result, display, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getRandROutputDisplayEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_USE_PLATFORM_XLIB_XRANDR_EXT*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result PhysicalDevice::releaseDisplayEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkReleaseDisplayEXT( m_physicalDevice, static_cast<VkDisplayKHR>( display ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type PhysicalDevice::releaseDisplayEXT( VULKAN_HPP_NAMESPACE::DisplayKHR display, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkReleaseDisplayEXT( m_physicalDevice, static_cast<VkDisplayKHR>( display ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::releaseDisplayEXT" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Queue::getCheckpointDataNV( uint32_t* pCheckpointDataCount, VULKAN_HPP_NAMESPACE::CheckpointDataNV* pCheckpointData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkGetQueueCheckpointDataNV( m_queue, pCheckpointDataCount, reinterpret_cast<VkCheckpointDataNV*>( pCheckpointData ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<CheckpointDataNV,Allocator> Queue::getCheckpointDataNV(Dispatch const &d ) const
+ {
+ std::vector<CheckpointDataNV,Allocator> checkpointData;
+ uint32_t checkpointDataCount;
+ d.vkGetQueueCheckpointDataNV( m_queue, &checkpointDataCount, nullptr );
+ checkpointData.resize( checkpointDataCount );
+ d.vkGetQueueCheckpointDataNV( m_queue, &checkpointDataCount, reinterpret_cast<VkCheckpointDataNV*>( checkpointData.data() ) );
+ return checkpointData;
+ }
+ template<typename Allocator, typename Dispatch>
+ VULKAN_HPP_INLINE std::vector<CheckpointDataNV,Allocator> Queue::getCheckpointDataNV(Allocator const& vectorAllocator, Dispatch const &d ) const
+ {
+ std::vector<CheckpointDataNV,Allocator> checkpointData( vectorAllocator );
+ uint32_t checkpointDataCount;
+ d.vkGetQueueCheckpointDataNV( m_queue, &checkpointDataCount, nullptr );
+ checkpointData.resize( checkpointDataCount );
+ d.vkGetQueueCheckpointDataNV( m_queue, &checkpointDataCount, reinterpret_cast<VkCheckpointDataNV*>( checkpointData.data() ) );
+ return checkpointData;
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Queue::beginDebugUtilsLabelEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pLabelInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkQueueBeginDebugUtilsLabelEXT( m_queue, reinterpret_cast<const VkDebugUtilsLabelEXT*>( pLabelInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Queue::beginDebugUtilsLabelEXT( const DebugUtilsLabelEXT & labelInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkQueueBeginDebugUtilsLabelEXT( m_queue, reinterpret_cast<const VkDebugUtilsLabelEXT*>( &labelInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Queue::bindSparse( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindSparseInfo* pBindInfo, VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkQueueBindSparse( m_queue, bindInfoCount, reinterpret_cast<const VkBindSparseInfo*>( pBindInfo ), static_cast<VkFence>( fence ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Queue::bindSparse( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindSparseInfo> bindInfo, VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkQueueBindSparse( m_queue, bindInfo.size() , reinterpret_cast<const VkBindSparseInfo*>( bindInfo.data() ), static_cast<VkFence>( fence ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Queue::bindSparse" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Queue::endDebugUtilsLabelEXT(Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkQueueEndDebugUtilsLabelEXT( m_queue );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Queue::endDebugUtilsLabelEXT(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkQueueEndDebugUtilsLabelEXT( m_queue );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Queue::insertDebugUtilsLabelEXT( const VULKAN_HPP_NAMESPACE::DebugUtilsLabelEXT* pLabelInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkQueueInsertDebugUtilsLabelEXT( m_queue, reinterpret_cast<const VkDebugUtilsLabelEXT*>( pLabelInfo ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE void Queue::insertDebugUtilsLabelEXT( const DebugUtilsLabelEXT & labelInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+ {
+ d.vkQueueInsertDebugUtilsLabelEXT( m_queue, reinterpret_cast<const VkDebugUtilsLabelEXT*>( &labelInfo ) );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Queue::presentKHR( const VULKAN_HPP_NAMESPACE::PresentInfoKHR* pPresentInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkQueuePresentKHR( m_queue, reinterpret_cast<const VkPresentInfoKHR*>( pPresentInfo ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Queue::presentKHR( const PresentInfoKHR & presentInfo, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkQueuePresentKHR( m_queue, reinterpret_cast<const VkPresentInfoKHR*>( &presentInfo ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Queue::presentKHR", { Result::eSuccess, Result::eSuboptimalKHR } );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Queue::setPerformanceConfigurationINTEL( VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL configuration, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkQueueSetPerformanceConfigurationINTEL( m_queue, static_cast<VkPerformanceConfigurationINTEL>( configuration ) ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Queue::setPerformanceConfigurationINTEL( VULKAN_HPP_NAMESPACE::PerformanceConfigurationINTEL configuration, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkQueueSetPerformanceConfigurationINTEL( m_queue, static_cast<VkPerformanceConfigurationINTEL>( configuration ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Queue::setPerformanceConfigurationINTEL" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Queue::submit( uint32_t submitCount, const VULKAN_HPP_NAMESPACE::SubmitInfo* pSubmits, VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkQueueSubmit( m_queue, submitCount, reinterpret_cast<const VkSubmitInfo*>( pSubmits ), static_cast<VkFence>( fence ) ) );
+ }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Queue::submit( ArrayProxy<const VULKAN_HPP_NAMESPACE::SubmitInfo> submits, VULKAN_HPP_NAMESPACE::Fence fence, Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkQueueSubmit( m_queue, submits.size() , reinterpret_cast<const VkSubmitInfo*>( submits.data() ), static_cast<VkFence>( fence ) ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Queue::submit" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE Result Queue::waitIdle(Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+ {
+ return static_cast<Result>( d.vkQueueWaitIdle( m_queue ) );
+ }
+#else
+ template<typename Dispatch>
+ VULKAN_HPP_INLINE typename ResultValueType<void>::type Queue::waitIdle(Dispatch const &d ) const
+ {
+ Result result = static_cast<Result>( d.vkQueueWaitIdle( m_queue ) );
+ return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Queue::waitIdle" );
+ }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ template <> struct isStructureChainValid<AndroidHardwareBufferPropertiesANDROID, AndroidHardwareBufferFormatPropertiesANDROID>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ template <> struct isStructureChainValid<ImageFormatProperties2, AndroidHardwareBufferUsageANDROID>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ template <> struct isStructureChainValid<AttachmentDescription2, AttachmentDescriptionStencilLayout>{ enum { value = true }; };
+ template <> struct isStructureChainValid<AttachmentReference2, AttachmentReferenceStencilLayout>{ enum { value = true }; };
+ template <> struct isStructureChainValid<BindBufferMemoryInfo, BindBufferMemoryDeviceGroupInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<BindImageMemoryInfo, BindImageMemoryDeviceGroupInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<BindImageMemoryInfo, BindImageMemorySwapchainInfoKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<BindImageMemoryInfo, BindImagePlaneMemoryInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<BufferCreateInfo, BufferDeviceAddressCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<BufferCreateInfo, BufferOpaqueCaptureAddressCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<CommandBufferInheritanceInfo, CommandBufferInheritanceConditionalRenderingInfoEXT>{ enum { value = true }; };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<SubmitInfo, D3D12FenceSubmitInfoKHR>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ template <> struct isStructureChainValid<InstanceCreateInfo, DebugReportCallbackCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<InstanceCreateInfo, DebugUtilsMessengerCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<BufferCreateInfo, DedicatedAllocationBufferCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageCreateInfo, DedicatedAllocationImageCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<MemoryAllocateInfo, DedicatedAllocationMemoryAllocateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DescriptorPoolCreateInfo, DescriptorPoolInlineUniformBlockCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DescriptorSetLayoutCreateInfo, DescriptorSetLayoutBindingFlagsCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DescriptorSetAllocateInfo, DescriptorSetVariableDescriptorCountAllocateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DescriptorSetLayoutSupport, DescriptorSetVariableDescriptorCountLayoutSupport>{ enum { value = true }; };
+ template <> struct isStructureChainValid<BindSparseInfo, DeviceGroupBindSparseInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<CommandBufferBeginInfo, DeviceGroupCommandBufferBeginInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, DeviceGroupDeviceCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PresentInfoKHR, DeviceGroupPresentInfoKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<RenderPassBeginInfo, DeviceGroupRenderPassBeginInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SubmitInfo, DeviceGroupSubmitInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SwapchainCreateInfoKHR, DeviceGroupSwapchainCreateInfoKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, DeviceMemoryOverallocationCreateInfoAMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceQueueCreateInfo, DeviceQueueGlobalPriorityCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SurfaceCapabilities2KHR, DisplayNativeHdrSurfaceCapabilitiesAMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PresentInfoKHR, DisplayPresentInfoKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<FormatProperties2, DrmFormatModifierPropertiesListEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<FenceCreateInfo, ExportFenceCreateInfo>{ enum { value = true }; };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<FenceCreateInfo, ExportFenceWin32HandleInfoKHR>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ template <> struct isStructureChainValid<MemoryAllocateInfo, ExportMemoryAllocateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<MemoryAllocateInfo, ExportMemoryAllocateInfoNV>{ enum { value = true }; };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<MemoryAllocateInfo, ExportMemoryWin32HandleInfoKHR>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<MemoryAllocateInfo, ExportMemoryWin32HandleInfoNV>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ template <> struct isStructureChainValid<SemaphoreCreateInfo, ExportSemaphoreCreateInfo>{ enum { value = true }; };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<SemaphoreCreateInfo, ExportSemaphoreWin32HandleInfoKHR>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ template <> struct isStructureChainValid<ImageCreateInfo, ExternalFormatANDROID>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SamplerYcbcrConversionCreateInfo, ExternalFormatANDROID>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ template <> struct isStructureChainValid<ImageFormatProperties2, ExternalImageFormatProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<BufferCreateInfo, ExternalMemoryBufferCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageCreateInfo, ExternalMemoryImageCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageCreateInfo, ExternalMemoryImageCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageFormatProperties2, FilterCubicImageViewImageFormatPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<FramebufferCreateInfo, FramebufferAttachmentsCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageCreateInfo, ImageDrmFormatModifierExplicitCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageCreateInfo, ImageDrmFormatModifierListCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageCreateInfo, ImageFormatListCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SwapchainCreateInfoKHR, ImageFormatListCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceImageFormatInfo2, ImageFormatListCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageMemoryRequirementsInfo2, ImagePlaneMemoryRequirementsInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageCreateInfo, ImageStencilUsageCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceImageFormatInfo2, ImageStencilUsageCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageCreateInfo, ImageSwapchainCreateInfoKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageViewCreateInfo, ImageViewASTCDecodeModeEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageViewCreateInfo, ImageViewUsageCreateInfo>{ enum { value = true }; };
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ template <> struct isStructureChainValid<MemoryAllocateInfo, ImportAndroidHardwareBufferInfoANDROID>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ template <> struct isStructureChainValid<MemoryAllocateInfo, ImportMemoryFdInfoKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<MemoryAllocateInfo, ImportMemoryHostPointerInfoEXT>{ enum { value = true }; };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<MemoryAllocateInfo, ImportMemoryWin32HandleInfoKHR>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<MemoryAllocateInfo, ImportMemoryWin32HandleInfoNV>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ template <> struct isStructureChainValid<MemoryAllocateInfo, MemoryAllocateFlagsInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<MemoryAllocateInfo, MemoryDedicatedAllocateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<MemoryRequirements2, MemoryDedicatedRequirements>{ enum { value = true }; };
+ template <> struct isStructureChainValid<MemoryAllocateInfo, MemoryOpaqueCaptureAddressAllocateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<MemoryAllocateInfo, MemoryPriorityAllocateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SubmitInfo, PerformanceQuerySubmitInfoKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDevice16BitStorageFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDevice16BitStorageFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDevice8BitStorageFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDevice8BitStorageFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceASTCDecodeFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceASTCDecodeFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceBlendOperationAdvancedFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceBlendOperationAdvancedFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceBlendOperationAdvancedPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceBufferDeviceAddressFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceBufferDeviceAddressFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceBufferDeviceAddressFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceBufferDeviceAddressFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceCoherentMemoryFeaturesAMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceCoherentMemoryFeaturesAMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceComputeShaderDerivativesFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceComputeShaderDerivativesFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceConditionalRenderingFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceConditionalRenderingFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceConservativeRasterizationPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceCooperativeMatrixFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceCooperativeMatrixFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceCooperativeMatrixPropertiesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceCornerSampledImageFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceCornerSampledImageFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceCoverageReductionModeFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceCoverageReductionModeFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceDepthClipEnableFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceDepthClipEnableFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceDepthStencilResolveProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceDescriptorIndexingFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceDescriptorIndexingFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceDescriptorIndexingProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceDiscardRectanglePropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceDriverProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceExclusiveScissorFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceExclusiveScissorFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceImageFormatInfo2, PhysicalDeviceExternalImageFormatInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceExternalMemoryHostPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceFeatures2>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceFloatControlsProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceFragmentDensityMapFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceFragmentDensityMapFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceFragmentDensityMapPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceFragmentShaderBarycentricFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceFragmentShaderBarycentricFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceFragmentShaderInterlockFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceFragmentShaderInterlockFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceHostQueryResetFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceHostQueryResetFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceIDProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceImageFormatInfo2, PhysicalDeviceImageDrmFormatModifierInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceImageFormatInfo2, PhysicalDeviceImageViewImageFormatInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceImagelessFramebufferFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceImagelessFramebufferFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceIndexTypeUint8FeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceIndexTypeUint8FeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceInlineUniformBlockFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceInlineUniformBlockFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceInlineUniformBlockPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceLineRasterizationFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceLineRasterizationFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceLineRasterizationPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceMaintenance3Properties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceMemoryProperties2, PhysicalDeviceMemoryBudgetPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceMemoryPriorityFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceMemoryPriorityFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceMeshShaderFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceMeshShaderFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceMeshShaderPropertiesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceMultiviewFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceMultiviewFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceMultiviewProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDevicePCIBusInfoPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDevicePerformanceQueryFeaturesKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDevicePerformanceQueryFeaturesKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDevicePerformanceQueryPropertiesKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDevicePipelineExecutablePropertiesFeaturesKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDevicePipelineExecutablePropertiesFeaturesKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDevicePointClippingProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceProtectedMemoryFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceProtectedMemoryFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceProtectedMemoryProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDevicePushDescriptorPropertiesKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceRayTracingPropertiesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceRepresentativeFragmentTestFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceRepresentativeFragmentTestFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceSampleLocationsPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceSamplerFilterMinmaxProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceSamplerYcbcrConversionFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceSamplerYcbcrConversionFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceScalarBlockLayoutFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceScalarBlockLayoutFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceSeparateDepthStencilLayoutsFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceSeparateDepthStencilLayoutsFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceShaderAtomicInt64Features>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceShaderAtomicInt64Features>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceShaderClockFeaturesKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceShaderClockFeaturesKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceShaderCoreProperties2AMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceShaderCorePropertiesAMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceShaderDrawParametersFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceShaderDrawParametersFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceShaderFloat16Int8Features>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceShaderFloat16Int8Features>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceShaderImageFootprintFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceShaderImageFootprintFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceShaderSMBuiltinsFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceShaderSMBuiltinsFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceShaderSMBuiltinsPropertiesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceShaderSubgroupExtendedTypesFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceShaderSubgroupExtendedTypesFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceShadingRateImageFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceShadingRateImageFeaturesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceShadingRateImagePropertiesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceSubgroupProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceSubgroupSizeControlFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceSubgroupSizeControlFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceSubgroupSizeControlPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceTexelBufferAlignmentFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceTexelBufferAlignmentFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceTexelBufferAlignmentPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceTimelineSemaphoreFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceTimelineSemaphoreFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceTimelineSemaphoreProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceTransformFeedbackFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceTransformFeedbackFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceTransformFeedbackPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceUniformBufferStandardLayoutFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceUniformBufferStandardLayoutFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceVariablePointersFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceVariablePointersFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceVertexAttributeDivisorFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceVertexAttributeDivisorFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceVertexAttributeDivisorPropertiesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceVulkan11Features>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceVulkan11Features>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceVulkan11Properties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceVulkan12Features>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceVulkan12Features>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceVulkan12Properties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceVulkanMemoryModelFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceVulkanMemoryModelFeatures>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceYcbcrImageArraysFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceYcbcrImageArraysFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineColorBlendStateCreateInfo, PipelineColorBlendAdvancedStateCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<GraphicsPipelineCreateInfo, PipelineCompilerControlCreateInfoAMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ComputePipelineCreateInfo, PipelineCompilerControlCreateInfoAMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineMultisampleStateCreateInfo, PipelineCoverageModulationStateCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineMultisampleStateCreateInfo, PipelineCoverageReductionStateCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineMultisampleStateCreateInfo, PipelineCoverageToColorStateCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<GraphicsPipelineCreateInfo, PipelineCreationFeedbackCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ComputePipelineCreateInfo, PipelineCreationFeedbackCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<RayTracingPipelineCreateInfoNV, PipelineCreationFeedbackCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<GraphicsPipelineCreateInfo, PipelineDiscardRectangleStateCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineRasterizationStateCreateInfo, PipelineRasterizationConservativeStateCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineRasterizationStateCreateInfo, PipelineRasterizationDepthClipStateCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineRasterizationStateCreateInfo, PipelineRasterizationLineStateCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineRasterizationStateCreateInfo, PipelineRasterizationStateRasterizationOrderAMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineRasterizationStateCreateInfo, PipelineRasterizationStateStreamCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<GraphicsPipelineCreateInfo, PipelineRepresentativeFragmentTestStateCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineMultisampleStateCreateInfo, PipelineSampleLocationsStateCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineShaderStageCreateInfo, PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineTessellationStateCreateInfo, PipelineTessellationDomainOriginStateCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineVertexInputStateCreateInfo, PipelineVertexInputDivisorStateCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineViewportStateCreateInfo, PipelineViewportCoarseSampleOrderStateCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineViewportStateCreateInfo, PipelineViewportExclusiveScissorStateCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineViewportStateCreateInfo, PipelineViewportShadingRateImageStateCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineViewportStateCreateInfo, PipelineViewportSwizzleStateCreateInfoNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PipelineViewportStateCreateInfo, PipelineViewportWScalingStateCreateInfoNV>{ enum { value = true }; };
+#ifdef VK_USE_PLATFORM_GGP
+ template <> struct isStructureChainValid<PresentInfoKHR, PresentFrameTokenGGP>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_GGP*/
+ template <> struct isStructureChainValid<PresentInfoKHR, PresentRegionsKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PresentInfoKHR, PresentTimesInfoGOOGLE>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SubmitInfo, ProtectedSubmitInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<QueryPoolCreateInfo, QueryPoolPerformanceCreateInfoKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<QueueFamilyProperties2, QueueFamilyCheckpointPropertiesNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<RenderPassBeginInfo, RenderPassAttachmentBeginInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<RenderPassCreateInfo, RenderPassFragmentDensityMapCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<RenderPassCreateInfo2, RenderPassFragmentDensityMapCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<RenderPassCreateInfo, RenderPassInputAttachmentAspectCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<RenderPassCreateInfo, RenderPassMultiviewCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<RenderPassBeginInfo, RenderPassSampleLocationsBeginInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageMemoryBarrier, SampleLocationsInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SamplerCreateInfo, SamplerReductionModeCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageFormatProperties2, SamplerYcbcrConversionImageFormatProperties>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SamplerCreateInfo, SamplerYcbcrConversionInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageViewCreateInfo, SamplerYcbcrConversionInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SemaphoreCreateInfo, SemaphoreTypeCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<PhysicalDeviceExternalSemaphoreInfo, SemaphoreTypeCreateInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ShaderModuleCreateInfo, ShaderModuleValidationCacheCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SurfaceCapabilities2KHR, SharedPresentSurfaceCapabilitiesKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SubpassDescription2, SubpassDescriptionDepthStencilResolve>{ enum { value = true }; };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<SurfaceCapabilities2KHR, SurfaceCapabilitiesFullScreenExclusiveEXT>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<PhysicalDeviceSurfaceInfo2KHR, SurfaceFullScreenExclusiveInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SwapchainCreateInfoKHR, SurfaceFullScreenExclusiveInfoEXT>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<PhysicalDeviceSurfaceInfo2KHR, SurfaceFullScreenExclusiveWin32InfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SwapchainCreateInfoKHR, SurfaceFullScreenExclusiveWin32InfoEXT>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ template <> struct isStructureChainValid<SurfaceCapabilities2KHR, SurfaceProtectedCapabilitiesKHR>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SwapchainCreateInfoKHR, SwapchainCounterCreateInfoEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SwapchainCreateInfoKHR, SwapchainDisplayNativeHdrCreateInfoAMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<ImageFormatProperties2, TextureLODGatherFormatPropertiesAMD>{ enum { value = true }; };
+ template <> struct isStructureChainValid<SubmitInfo, TimelineSemaphoreSubmitInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<BindSparseInfo, TimelineSemaphoreSubmitInfo>{ enum { value = true }; };
+ template <> struct isStructureChainValid<InstanceCreateInfo, ValidationFeaturesEXT>{ enum { value = true }; };
+ template <> struct isStructureChainValid<InstanceCreateInfo, ValidationFlagsEXT>{ enum { value = true }; };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<SubmitInfo, Win32KeyedMutexAcquireReleaseInfoKHR>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ template <> struct isStructureChainValid<SubmitInfo, Win32KeyedMutexAcquireReleaseInfoNV>{ enum { value = true }; };
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ template <> struct isStructureChainValid<WriteDescriptorSet, WriteDescriptorSetAccelerationStructureNV>{ enum { value = true }; };
+ template <> struct isStructureChainValid<WriteDescriptorSet, WriteDescriptorSetInlineUniformBlockEXT>{ enum { value = true }; };
+
+#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL
+ class DynamicLoader
+ {
+ public:
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+ DynamicLoader() VULKAN_HPP_NOEXCEPT : m_success( false )
+#else
+ DynamicLoader() : m_success( false )
+#endif
+ {
+#if defined(__linux__)
+ m_library = dlopen( "libvulkan.so", RTLD_NOW | RTLD_LOCAL );
+#elif defined(__APPLE__)
+ m_library = dlopen( "libvulkan.dylib", RTLD_NOW | RTLD_LOCAL );
+#elif defined(_WIN32)
+ m_library = LoadLibrary( TEXT( "vulkan-1.dll" ) );
+#else
+ assert( false && "unsupported platform" );
+#endif
+
+ m_success = m_library != 0;
+#ifndef VULKAN_HPP_NO_EXCEPTIONS
+ if ( !m_success )
+ {
+ // NOTE there should be an InitializationFailedError, but msvc insists on the symbol does not exist within the scope of this function.
+ throw std::runtime_error( "Failed to load vulkan library!" );
+ }
+#endif
+ }
+
+ ~DynamicLoader() VULKAN_HPP_NOEXCEPT
+ {
+ if ( m_library )
+ {
+#if defined(__linux__) || defined(__APPLE__)
+ dlclose( m_library );
+#elif defined(_WIN32)
+ FreeLibrary( m_library );
+#endif
+ }
+ }
+
+ template <typename T>
+ T getProcAddress( const char* function ) const VULKAN_HPP_NOEXCEPT
+ {
+#if defined(__linux__) || defined(__APPLE__)
+ return (T)dlsym( m_library, function );
+#elif defined(_WIN32)
+ return (T)GetProcAddress( m_library, function );
+#endif
+ }
+
+ bool success() const VULKAN_HPP_NOEXCEPT { return m_success; }
+
+ private:
+ bool m_success;
+#if defined(__linux__) || defined(__APPLE__)
+ void *m_library;
+#elif defined(_WIN32)
+ HMODULE m_library;
+#else
+#error unsupported platform
+#endif
+ };
+#endif
+
+ class DispatchLoaderDynamic
+ {
+ public:
+ PFN_vkCreateInstance vkCreateInstance = 0;
+ PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties = 0;
+ PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties = 0;
+ PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion = 0;
+ PFN_vkBeginCommandBuffer vkBeginCommandBuffer = 0;
+ PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT = 0;
+ PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT = 0;
+ PFN_vkCmdBeginQuery vkCmdBeginQuery = 0;
+ PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT = 0;
+ PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass = 0;
+ PFN_vkCmdBeginRenderPass2 vkCmdBeginRenderPass2 = 0;
+ PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR = 0;
+ PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT = 0;
+ PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = 0;
+ PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer = 0;
+ PFN_vkCmdBindPipeline vkCmdBindPipeline = 0;
+ PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV = 0;
+ PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT = 0;
+ PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers = 0;
+ PFN_vkCmdBlitImage vkCmdBlitImage = 0;
+ PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV = 0;
+ PFN_vkCmdClearAttachments vkCmdClearAttachments = 0;
+ PFN_vkCmdClearColorImage vkCmdClearColorImage = 0;
+ PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage = 0;
+ PFN_vkCmdCopyAccelerationStructureNV vkCmdCopyAccelerationStructureNV = 0;
+ PFN_vkCmdCopyBuffer vkCmdCopyBuffer = 0;
+ PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = 0;
+ PFN_vkCmdCopyImage vkCmdCopyImage = 0;
+ PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer = 0;
+ PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults = 0;
+ PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBeginEXT = 0;
+ PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEndEXT = 0;
+ PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsertEXT = 0;
+ PFN_vkCmdDispatch vkCmdDispatch = 0;
+ PFN_vkCmdDispatchBase vkCmdDispatchBase = 0;
+ PFN_vkCmdDispatchBaseKHR vkCmdDispatchBaseKHR = 0;
+ PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect = 0;
+ PFN_vkCmdDraw vkCmdDraw = 0;
+ PFN_vkCmdDrawIndexed vkCmdDrawIndexed = 0;
+ PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect = 0;
+ PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount = 0;
+ PFN_vkCmdDrawIndexedIndirectCountAMD vkCmdDrawIndexedIndirectCountAMD = 0;
+ PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR = 0;
+ PFN_vkCmdDrawIndirect vkCmdDrawIndirect = 0;
+ PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT = 0;
+ PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount = 0;
+ PFN_vkCmdDrawIndirectCountAMD vkCmdDrawIndirectCountAMD = 0;
+ PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR = 0;
+ PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV = 0;
+ PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV = 0;
+ PFN_vkCmdDrawMeshTasksNV vkCmdDrawMeshTasksNV = 0;
+ PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT = 0;
+ PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT = 0;
+ PFN_vkCmdEndQuery vkCmdEndQuery = 0;
+ PFN_vkCmdEndQueryIndexedEXT vkCmdEndQueryIndexedEXT = 0;
+ PFN_vkCmdEndRenderPass vkCmdEndRenderPass = 0;
+ PFN_vkCmdEndRenderPass2 vkCmdEndRenderPass2 = 0;
+ PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR = 0;
+ PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT = 0;
+ PFN_vkCmdExecuteCommands vkCmdExecuteCommands = 0;
+ PFN_vkCmdFillBuffer vkCmdFillBuffer = 0;
+ PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT = 0;
+ PFN_vkCmdNextSubpass vkCmdNextSubpass = 0;
+ PFN_vkCmdNextSubpass2 vkCmdNextSubpass2 = 0;
+ PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR = 0;
+ PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier = 0;
+ PFN_vkCmdProcessCommandsNVX vkCmdProcessCommandsNVX = 0;
+ PFN_vkCmdPushConstants vkCmdPushConstants = 0;
+ PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR = 0;
+ PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR = 0;
+ PFN_vkCmdReserveSpaceForCommandsNVX vkCmdReserveSpaceForCommandsNVX = 0;
+ PFN_vkCmdResetEvent vkCmdResetEvent = 0;
+ PFN_vkCmdResetQueryPool vkCmdResetQueryPool = 0;
+ PFN_vkCmdResolveImage vkCmdResolveImage = 0;
+ PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants = 0;
+ PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV = 0;
+ PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV = 0;
+ PFN_vkCmdSetDepthBias vkCmdSetDepthBias = 0;
+ PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds = 0;
+ PFN_vkCmdSetDeviceMask vkCmdSetDeviceMask = 0;
+ PFN_vkCmdSetDeviceMaskKHR vkCmdSetDeviceMaskKHR = 0;
+ PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT = 0;
+ PFN_vkCmdSetEvent vkCmdSetEvent = 0;
+ PFN_vkCmdSetExclusiveScissorNV vkCmdSetExclusiveScissorNV = 0;
+ PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT = 0;
+ PFN_vkCmdSetLineWidth vkCmdSetLineWidth = 0;
+ PFN_vkCmdSetPerformanceMarkerINTEL vkCmdSetPerformanceMarkerINTEL = 0;
+ PFN_vkCmdSetPerformanceOverrideINTEL vkCmdSetPerformanceOverrideINTEL = 0;
+ PFN_vkCmdSetPerformanceStreamMarkerINTEL vkCmdSetPerformanceStreamMarkerINTEL = 0;
+ PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT = 0;
+ PFN_vkCmdSetScissor vkCmdSetScissor = 0;
+ PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask = 0;
+ PFN_vkCmdSetStencilReference vkCmdSetStencilReference = 0;
+ PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask = 0;
+ PFN_vkCmdSetViewport vkCmdSetViewport = 0;
+ PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV = 0;
+ PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV = 0;
+ PFN_vkCmdTraceRaysNV vkCmdTraceRaysNV = 0;
+ PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer = 0;
+ PFN_vkCmdWaitEvents vkCmdWaitEvents = 0;
+ PFN_vkCmdWriteAccelerationStructuresPropertiesNV vkCmdWriteAccelerationStructuresPropertiesNV = 0;
+ PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD = 0;
+ PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp = 0;
+ PFN_vkEndCommandBuffer vkEndCommandBuffer = 0;
+ PFN_vkResetCommandBuffer vkResetCommandBuffer = 0;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR = 0;
+ PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR = 0;
+ PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL = 0;
+ PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR = 0;
+ PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = 0;
+ PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets = 0;
+ PFN_vkAllocateMemory vkAllocateMemory = 0;
+ PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV = 0;
+ PFN_vkBindBufferMemory vkBindBufferMemory = 0;
+ PFN_vkBindBufferMemory2 vkBindBufferMemory2 = 0;
+ PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR = 0;
+ PFN_vkBindImageMemory vkBindImageMemory = 0;
+ PFN_vkBindImageMemory2 vkBindImageMemory2 = 0;
+ PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR = 0;
+ PFN_vkCompileDeferredNV vkCompileDeferredNV = 0;
+ PFN_vkCreateAccelerationStructureNV vkCreateAccelerationStructureNV = 0;
+ PFN_vkCreateBuffer vkCreateBuffer = 0;
+ PFN_vkCreateBufferView vkCreateBufferView = 0;
+ PFN_vkCreateCommandPool vkCreateCommandPool = 0;
+ PFN_vkCreateComputePipelines vkCreateComputePipelines = 0;
+ PFN_vkCreateDescriptorPool vkCreateDescriptorPool = 0;
+ PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout = 0;
+ PFN_vkCreateDescriptorUpdateTemplate vkCreateDescriptorUpdateTemplate = 0;
+ PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR = 0;
+ PFN_vkCreateEvent vkCreateEvent = 0;
+ PFN_vkCreateFence vkCreateFence = 0;
+ PFN_vkCreateFramebuffer vkCreateFramebuffer = 0;
+ PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines = 0;
+ PFN_vkCreateImage vkCreateImage = 0;
+ PFN_vkCreateImageView vkCreateImageView = 0;
+ PFN_vkCreateIndirectCommandsLayoutNVX vkCreateIndirectCommandsLayoutNVX = 0;
+ PFN_vkCreateObjectTableNVX vkCreateObjectTableNVX = 0;
+ PFN_vkCreatePipelineCache vkCreatePipelineCache = 0;
+ PFN_vkCreatePipelineLayout vkCreatePipelineLayout = 0;
+ PFN_vkCreateQueryPool vkCreateQueryPool = 0;
+ PFN_vkCreateRayTracingPipelinesNV vkCreateRayTracingPipelinesNV = 0;
+ PFN_vkCreateRenderPass vkCreateRenderPass = 0;
+ PFN_vkCreateRenderPass2 vkCreateRenderPass2 = 0;
+ PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR = 0;
+ PFN_vkCreateSampler vkCreateSampler = 0;
+ PFN_vkCreateSamplerYcbcrConversion vkCreateSamplerYcbcrConversion = 0;
+ PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR = 0;
+ PFN_vkCreateSemaphore vkCreateSemaphore = 0;
+ PFN_vkCreateShaderModule vkCreateShaderModule = 0;
+ PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR = 0;
+ PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = 0;
+ PFN_vkCreateValidationCacheEXT vkCreateValidationCacheEXT = 0;
+ PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectNameEXT = 0;
+ PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTagEXT = 0;
+ PFN_vkDestroyAccelerationStructureNV vkDestroyAccelerationStructureNV = 0;
+ PFN_vkDestroyBuffer vkDestroyBuffer = 0;
+ PFN_vkDestroyBufferView vkDestroyBufferView = 0;
+ PFN_vkDestroyCommandPool vkDestroyCommandPool = 0;
+ PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool = 0;
+ PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout = 0;
+ PFN_vkDestroyDescriptorUpdateTemplate vkDestroyDescriptorUpdateTemplate = 0;
+ PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR = 0;
+ PFN_vkDestroyDevice vkDestroyDevice = 0;
+ PFN_vkDestroyEvent vkDestroyEvent = 0;
+ PFN_vkDestroyFence vkDestroyFence = 0;
+ PFN_vkDestroyFramebuffer vkDestroyFramebuffer = 0;
+ PFN_vkDestroyImage vkDestroyImage = 0;
+ PFN_vkDestroyImageView vkDestroyImageView = 0;
+ PFN_vkDestroyIndirectCommandsLayoutNVX vkDestroyIndirectCommandsLayoutNVX = 0;
+ PFN_vkDestroyObjectTableNVX vkDestroyObjectTableNVX = 0;
+ PFN_vkDestroyPipeline vkDestroyPipeline = 0;
+ PFN_vkDestroyPipelineCache vkDestroyPipelineCache = 0;
+ PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout = 0;
+ PFN_vkDestroyQueryPool vkDestroyQueryPool = 0;
+ PFN_vkDestroyRenderPass vkDestroyRenderPass = 0;
+ PFN_vkDestroySampler vkDestroySampler = 0;
+ PFN_vkDestroySamplerYcbcrConversion vkDestroySamplerYcbcrConversion = 0;
+ PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR = 0;
+ PFN_vkDestroySemaphore vkDestroySemaphore = 0;
+ PFN_vkDestroyShaderModule vkDestroyShaderModule = 0;
+ PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = 0;
+ PFN_vkDestroyValidationCacheEXT vkDestroyValidationCacheEXT = 0;
+ PFN_vkDeviceWaitIdle vkDeviceWaitIdle = 0;
+ PFN_vkDisplayPowerControlEXT vkDisplayPowerControlEXT = 0;
+ PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges = 0;
+ PFN_vkFreeCommandBuffers vkFreeCommandBuffers = 0;
+ PFN_vkFreeDescriptorSets vkFreeDescriptorSets = 0;
+ PFN_vkFreeMemory vkFreeMemory = 0;
+ PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV = 0;
+ PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV = 0;
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID = 0;
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress = 0;
+ PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT = 0;
+ PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR = 0;
+ PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements = 0;
+ PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2 = 0;
+ PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR = 0;
+ PFN_vkGetBufferOpaqueCaptureAddress vkGetBufferOpaqueCaptureAddress = 0;
+ PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR = 0;
+ PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT = 0;
+ PFN_vkGetDescriptorSetLayoutSupport vkGetDescriptorSetLayoutSupport = 0;
+ PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR = 0;
+ PFN_vkGetDeviceGroupPeerMemoryFeatures vkGetDeviceGroupPeerMemoryFeatures = 0;
+ PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR vkGetDeviceGroupPeerMemoryFeaturesKHR = 0;
+ PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR = 0;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR = 0;
+ PFN_vkGetDeviceMemoryCommitment vkGetDeviceMemoryCommitment = 0;
+ PFN_vkGetDeviceMemoryOpaqueCaptureAddress vkGetDeviceMemoryOpaqueCaptureAddress = 0;
+ PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR = 0;
+ PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = 0;
+ PFN_vkGetDeviceQueue vkGetDeviceQueue = 0;
+ PFN_vkGetDeviceQueue2 vkGetDeviceQueue2 = 0;
+ PFN_vkGetEventStatus vkGetEventStatus = 0;
+ PFN_vkGetFenceFdKHR vkGetFenceFdKHR = 0;
+ PFN_vkGetFenceStatus vkGetFenceStatus = 0;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetFenceWin32HandleKHR vkGetFenceWin32HandleKHR = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT = 0;
+ PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements = 0;
+ PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2 = 0;
+ PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR = 0;
+ PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements = 0;
+ PFN_vkGetImageSparseMemoryRequirements2 vkGetImageSparseMemoryRequirements2 = 0;
+ PFN_vkGetImageSparseMemoryRequirements2KHR vkGetImageSparseMemoryRequirements2KHR = 0;
+ PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout = 0;
+ PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX = 0;
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID = 0;
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR = 0;
+ PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHR = 0;
+ PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT = 0;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetMemoryWin32HandlePropertiesKHR vkGetMemoryWin32HandlePropertiesKHR = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE = 0;
+ PFN_vkGetPerformanceParameterINTEL vkGetPerformanceParameterINTEL = 0;
+ PFN_vkGetPipelineCacheData vkGetPipelineCacheData = 0;
+ PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR = 0;
+ PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR = 0;
+ PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR = 0;
+ PFN_vkGetQueryPoolResults vkGetQueryPoolResults = 0;
+ PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV = 0;
+ PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE = 0;
+ PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity = 0;
+ PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue = 0;
+ PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR = 0;
+ PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR = 0;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD = 0;
+ PFN_vkGetSwapchainCounterEXT vkGetSwapchainCounterEXT = 0;
+ PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = 0;
+ PFN_vkGetSwapchainStatusKHR vkGetSwapchainStatusKHR = 0;
+ PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT = 0;
+ PFN_vkImportFenceFdKHR vkImportFenceFdKHR = 0;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkImportFenceWin32HandleKHR vkImportFenceWin32HandleKHR = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR = 0;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ PFN_vkInitializePerformanceApiINTEL vkInitializePerformanceApiINTEL = 0;
+ PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges = 0;
+ PFN_vkMapMemory vkMapMemory = 0;
+ PFN_vkMergePipelineCaches vkMergePipelineCaches = 0;
+ PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT = 0;
+ PFN_vkRegisterDeviceEventEXT vkRegisterDeviceEventEXT = 0;
+ PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT = 0;
+ PFN_vkRegisterObjectsNVX vkRegisterObjectsNVX = 0;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ PFN_vkReleasePerformanceConfigurationINTEL vkReleasePerformanceConfigurationINTEL = 0;
+ PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR = 0;
+ PFN_vkResetCommandPool vkResetCommandPool = 0;
+ PFN_vkResetDescriptorPool vkResetDescriptorPool = 0;
+ PFN_vkResetEvent vkResetEvent = 0;
+ PFN_vkResetFences vkResetFences = 0;
+ PFN_vkResetQueryPool vkResetQueryPool = 0;
+ PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT = 0;
+ PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = 0;
+ PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT = 0;
+ PFN_vkSetEvent vkSetEvent = 0;
+ PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT = 0;
+ PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD = 0;
+ PFN_vkSignalSemaphore vkSignalSemaphore = 0;
+ PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR = 0;
+ PFN_vkTrimCommandPool vkTrimCommandPool = 0;
+ PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR = 0;
+ PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL = 0;
+ PFN_vkUnmapMemory vkUnmapMemory = 0;
+ PFN_vkUnregisterObjectsNVX vkUnregisterObjectsNVX = 0;
+ PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate = 0;
+ PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR = 0;
+ PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = 0;
+ PFN_vkWaitForFences vkWaitForFences = 0;
+ PFN_vkWaitSemaphores vkWaitSemaphores = 0;
+ PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR = 0;
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR = 0;
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = 0;
+ PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = 0;
+ PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR = 0;
+ PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT = 0;
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK = 0;
+#endif /*VK_USE_PLATFORM_IOS_MVK*/
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA = 0;
+#endif /*VK_USE_PLATFORM_FUCHSIA*/
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK = 0;
+#endif /*VK_USE_PLATFORM_MACOS_MVK*/
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT = 0;
+#endif /*VK_USE_PLATFORM_METAL_EXT*/
+#ifdef VK_USE_PLATFORM_GGP
+ PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP = 0;
+#endif /*VK_USE_PLATFORM_GGP*/
+#ifdef VK_USE_PLATFORM_VI_NN
+ PFN_vkCreateViSurfaceNN vkCreateViSurfaceNN = 0;
+#endif /*VK_USE_PLATFORM_VI_NN*/
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR = 0;
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR = 0;
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR = 0;
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+ PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT = 0;
+ PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = 0;
+ PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = 0;
+ PFN_vkDestroyInstance vkDestroyInstance = 0;
+ PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = 0;
+ PFN_vkEnumeratePhysicalDeviceGroups vkEnumeratePhysicalDeviceGroups = 0;
+ PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR = 0;
+ PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = 0;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = 0;
+ PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT = 0;
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT = 0;
+#endif /*VK_USE_PLATFORM_XLIB_XRANDR_EXT*/
+ PFN_vkCreateDevice vkCreateDevice = 0;
+ PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR = 0;
+ PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties = 0;
+ PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties = 0;
+ PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = 0;
+ PFN_vkGetDisplayModeProperties2KHR vkGetDisplayModeProperties2KHR = 0;
+ PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR = 0;
+ PFN_vkGetDisplayPlaneCapabilities2KHR vkGetDisplayPlaneCapabilities2KHR = 0;
+ PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR = 0;
+ PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR = 0;
+ PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT = 0;
+ PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV = 0;
+ PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR vkGetPhysicalDeviceDisplayPlaneProperties2KHR = 0;
+ PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR = 0;
+ PFN_vkGetPhysicalDeviceDisplayProperties2KHR vkGetPhysicalDeviceDisplayProperties2KHR = 0;
+ PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR = 0;
+ PFN_vkGetPhysicalDeviceExternalBufferProperties vkGetPhysicalDeviceExternalBufferProperties = 0;
+ PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR vkGetPhysicalDeviceExternalBufferPropertiesKHR = 0;
+ PFN_vkGetPhysicalDeviceExternalFenceProperties vkGetPhysicalDeviceExternalFenceProperties = 0;
+ PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR = 0;
+ PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV = 0;
+ PFN_vkGetPhysicalDeviceExternalSemaphoreProperties vkGetPhysicalDeviceExternalSemaphoreProperties = 0;
+ PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = 0;
+ PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures = 0;
+ PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2 = 0;
+ PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = 0;
+ PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties = 0;
+ PFN_vkGetPhysicalDeviceFormatProperties2 vkGetPhysicalDeviceFormatProperties2 = 0;
+ PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR = 0;
+ PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX = 0;
+ PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties = 0;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2 = 0;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2KHR vkGetPhysicalDeviceImageFormatProperties2KHR = 0;
+ PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties = 0;
+ PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2 = 0;
+ PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR = 0;
+ PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT = 0;
+ PFN_vkGetPhysicalDevicePresentRectanglesKHR vkGetPhysicalDevicePresentRectanglesKHR = 0;
+ PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = 0;
+ PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2 = 0;
+ PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = 0;
+ PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = 0;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties = 0;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2 vkGetPhysicalDeviceQueueFamilyProperties2 = 0;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR = 0;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties = 0;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 vkGetPhysicalDeviceSparseImageFormatProperties2 = 0;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR vkGetPhysicalDeviceSparseImageFormatProperties2KHR = 0;
+ PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = 0;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT = 0;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR = 0;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = 0;
+ PFN_vkGetPhysicalDeviceSurfaceFormats2KHR vkGetPhysicalDeviceSurfaceFormats2KHR = 0;
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR = 0;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT vkGetPhysicalDeviceSurfacePresentModes2EXT = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR = 0;
+ PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = 0;
+ PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT = 0;
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR = 0;
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR = 0;
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR = 0;
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR = 0;
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT = 0;
+#endif /*VK_USE_PLATFORM_XLIB_XRANDR_EXT*/
+ PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT = 0;
+ PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV = 0;
+ PFN_vkQueueBeginDebugUtilsLabelEXT vkQueueBeginDebugUtilsLabelEXT = 0;
+ PFN_vkQueueBindSparse vkQueueBindSparse = 0;
+ PFN_vkQueueEndDebugUtilsLabelEXT vkQueueEndDebugUtilsLabelEXT = 0;
+ PFN_vkQueueInsertDebugUtilsLabelEXT vkQueueInsertDebugUtilsLabelEXT = 0;
+ PFN_vkQueuePresentKHR vkQueuePresentKHR = 0;
+ PFN_vkQueueSetPerformanceConfigurationINTEL vkQueueSetPerformanceConfigurationINTEL = 0;
+ PFN_vkQueueSubmit vkQueueSubmit = 0;
+ PFN_vkQueueWaitIdle vkQueueWaitIdle = 0;
+
+ public:
+ DispatchLoaderDynamic() VULKAN_HPP_NOEXCEPT = default;
+
+#if !defined(VK_NO_PROTOTYPES)
+ // This interface is designed to be used for per-device function pointers in combination with a linked vulkan library.
+ DispatchLoaderDynamic(VULKAN_HPP_NAMESPACE::Instance const& instance, VULKAN_HPP_NAMESPACE::Device const& device) VULKAN_HPP_NOEXCEPT
+ {
+ init(instance, device);
+ }
+
+ // This interface is designed to be used for per-device function pointers in combination with a linked vulkan library.
+ void init(VULKAN_HPP_NAMESPACE::Instance const& instance, VULKAN_HPP_NAMESPACE::Device const& device) VULKAN_HPP_NOEXCEPT
+ {
+ static vk::DynamicLoader dl;
+ PFN_vkGetInstanceProcAddr getInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
+ PFN_vkGetDeviceProcAddr getDeviceProcAddr = dl.getProcAddress<PFN_vkGetDeviceProcAddr>("vkGetDeviceProcAddr");
+ init(static_cast<VkInstance>(instance), getInstanceProcAddr, static_cast<VkDevice>(device), device ? getDeviceProcAddr : nullptr);
+ }
+#endif // !defined(VK_NO_PROTOTYPES)
+
+ DispatchLoaderDynamic(PFN_vkGetInstanceProcAddr getInstanceProcAddr) VULKAN_HPP_NOEXCEPT
+ {
+ init(getInstanceProcAddr);
+ }
+
+ void init( PFN_vkGetInstanceProcAddr getInstanceProcAddr ) VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_ASSERT(getInstanceProcAddr);
+
+ vkGetInstanceProcAddr = getInstanceProcAddr;
+ vkCreateInstance = PFN_vkCreateInstance( vkGetInstanceProcAddr( NULL, "vkCreateInstance" ) );
+ vkEnumerateInstanceExtensionProperties = PFN_vkEnumerateInstanceExtensionProperties( vkGetInstanceProcAddr( NULL, "vkEnumerateInstanceExtensionProperties" ) );
+ vkEnumerateInstanceLayerProperties = PFN_vkEnumerateInstanceLayerProperties( vkGetInstanceProcAddr( NULL, "vkEnumerateInstanceLayerProperties" ) );
+ vkEnumerateInstanceVersion = PFN_vkEnumerateInstanceVersion( vkGetInstanceProcAddr( NULL, "vkEnumerateInstanceVersion" ) );
+ }
+
+ // This interface does not require a linked vulkan library.
+ DispatchLoaderDynamic( VkInstance instance, PFN_vkGetInstanceProcAddr getInstanceProcAddr, VkDevice device = VK_NULL_HANDLE, PFN_vkGetDeviceProcAddr getDeviceProcAddr = nullptr ) VULKAN_HPP_NOEXCEPT
+ {
+ init( instance, getInstanceProcAddr, device, getDeviceProcAddr );
+ }
+
+ // This interface does not require a linked vulkan library.
+ void init( VkInstance instance, PFN_vkGetInstanceProcAddr getInstanceProcAddr, VkDevice device = VK_NULL_HANDLE, PFN_vkGetDeviceProcAddr /*getDeviceProcAddr*/ = nullptr ) VULKAN_HPP_NOEXCEPT
+ {
+ VULKAN_HPP_ASSERT(instance && getInstanceProcAddr);
+ vkGetInstanceProcAddr = getInstanceProcAddr;
+ init( VULKAN_HPP_NAMESPACE::Instance(instance) );
+ if (device) {
+ init( VULKAN_HPP_NAMESPACE::Device(device) );
+ }
+ }
+
+ void init( VULKAN_HPP_NAMESPACE::Instance instanceCpp ) VULKAN_HPP_NOEXCEPT
+ {
+ VkInstance instance = static_cast<VkInstance>(instanceCpp);
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ vkCreateAndroidSurfaceKHR = PFN_vkCreateAndroidSurfaceKHR( vkGetInstanceProcAddr( instance, "vkCreateAndroidSurfaceKHR" ) );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ vkCreateDebugReportCallbackEXT = PFN_vkCreateDebugReportCallbackEXT( vkGetInstanceProcAddr( instance, "vkCreateDebugReportCallbackEXT" ) );
+ vkCreateDebugUtilsMessengerEXT = PFN_vkCreateDebugUtilsMessengerEXT( vkGetInstanceProcAddr( instance, "vkCreateDebugUtilsMessengerEXT" ) );
+ vkCreateDisplayPlaneSurfaceKHR = PFN_vkCreateDisplayPlaneSurfaceKHR( vkGetInstanceProcAddr( instance, "vkCreateDisplayPlaneSurfaceKHR" ) );
+ vkCreateHeadlessSurfaceEXT = PFN_vkCreateHeadlessSurfaceEXT( vkGetInstanceProcAddr( instance, "vkCreateHeadlessSurfaceEXT" ) );
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ vkCreateIOSSurfaceMVK = PFN_vkCreateIOSSurfaceMVK( vkGetInstanceProcAddr( instance, "vkCreateIOSSurfaceMVK" ) );
+#endif /*VK_USE_PLATFORM_IOS_MVK*/
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ vkCreateImagePipeSurfaceFUCHSIA = PFN_vkCreateImagePipeSurfaceFUCHSIA( vkGetInstanceProcAddr( instance, "vkCreateImagePipeSurfaceFUCHSIA" ) );
+#endif /*VK_USE_PLATFORM_FUCHSIA*/
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ vkCreateMacOSSurfaceMVK = PFN_vkCreateMacOSSurfaceMVK( vkGetInstanceProcAddr( instance, "vkCreateMacOSSurfaceMVK" ) );
+#endif /*VK_USE_PLATFORM_MACOS_MVK*/
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ vkCreateMetalSurfaceEXT = PFN_vkCreateMetalSurfaceEXT( vkGetInstanceProcAddr( instance, "vkCreateMetalSurfaceEXT" ) );
+#endif /*VK_USE_PLATFORM_METAL_EXT*/
+#ifdef VK_USE_PLATFORM_GGP
+ vkCreateStreamDescriptorSurfaceGGP = PFN_vkCreateStreamDescriptorSurfaceGGP( vkGetInstanceProcAddr( instance, "vkCreateStreamDescriptorSurfaceGGP" ) );
+#endif /*VK_USE_PLATFORM_GGP*/
+#ifdef VK_USE_PLATFORM_VI_NN
+ vkCreateViSurfaceNN = PFN_vkCreateViSurfaceNN( vkGetInstanceProcAddr( instance, "vkCreateViSurfaceNN" ) );
+#endif /*VK_USE_PLATFORM_VI_NN*/
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ vkCreateWaylandSurfaceKHR = PFN_vkCreateWaylandSurfaceKHR( vkGetInstanceProcAddr( instance, "vkCreateWaylandSurfaceKHR" ) );
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkCreateWin32SurfaceKHR = PFN_vkCreateWin32SurfaceKHR( vkGetInstanceProcAddr( instance, "vkCreateWin32SurfaceKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ vkCreateXcbSurfaceKHR = PFN_vkCreateXcbSurfaceKHR( vkGetInstanceProcAddr( instance, "vkCreateXcbSurfaceKHR" ) );
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ vkCreateXlibSurfaceKHR = PFN_vkCreateXlibSurfaceKHR( vkGetInstanceProcAddr( instance, "vkCreateXlibSurfaceKHR" ) );
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+ vkDebugReportMessageEXT = PFN_vkDebugReportMessageEXT( vkGetInstanceProcAddr( instance, "vkDebugReportMessageEXT" ) );
+ vkDestroyDebugReportCallbackEXT = PFN_vkDestroyDebugReportCallbackEXT( vkGetInstanceProcAddr( instance, "vkDestroyDebugReportCallbackEXT" ) );
+ vkDestroyDebugUtilsMessengerEXT = PFN_vkDestroyDebugUtilsMessengerEXT( vkGetInstanceProcAddr( instance, "vkDestroyDebugUtilsMessengerEXT" ) );
+ vkDestroyInstance = PFN_vkDestroyInstance( vkGetInstanceProcAddr( instance, "vkDestroyInstance" ) );
+ vkDestroySurfaceKHR = PFN_vkDestroySurfaceKHR( vkGetInstanceProcAddr( instance, "vkDestroySurfaceKHR" ) );
+ vkEnumeratePhysicalDeviceGroups = PFN_vkEnumeratePhysicalDeviceGroups( vkGetInstanceProcAddr( instance, "vkEnumeratePhysicalDeviceGroups" ) );
+ vkEnumeratePhysicalDeviceGroupsKHR = PFN_vkEnumeratePhysicalDeviceGroupsKHR( vkGetInstanceProcAddr( instance, "vkEnumeratePhysicalDeviceGroupsKHR" ) );
+ vkEnumeratePhysicalDevices = PFN_vkEnumeratePhysicalDevices( vkGetInstanceProcAddr( instance, "vkEnumeratePhysicalDevices" ) );
+ vkSubmitDebugUtilsMessageEXT = PFN_vkSubmitDebugUtilsMessageEXT( vkGetInstanceProcAddr( instance, "vkSubmitDebugUtilsMessageEXT" ) );
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ vkAcquireXlibDisplayEXT = PFN_vkAcquireXlibDisplayEXT( vkGetInstanceProcAddr( instance, "vkAcquireXlibDisplayEXT" ) );
+#endif /*VK_USE_PLATFORM_XLIB_XRANDR_EXT*/
+ vkCreateDevice = PFN_vkCreateDevice( vkGetInstanceProcAddr( instance, "vkCreateDevice" ) );
+ vkCreateDisplayModeKHR = PFN_vkCreateDisplayModeKHR( vkGetInstanceProcAddr( instance, "vkCreateDisplayModeKHR" ) );
+ vkEnumerateDeviceExtensionProperties = PFN_vkEnumerateDeviceExtensionProperties( vkGetInstanceProcAddr( instance, "vkEnumerateDeviceExtensionProperties" ) );
+ vkEnumerateDeviceLayerProperties = PFN_vkEnumerateDeviceLayerProperties( vkGetInstanceProcAddr( instance, "vkEnumerateDeviceLayerProperties" ) );
+ vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( vkGetInstanceProcAddr( instance, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR" ) );
+ vkGetDisplayModeProperties2KHR = PFN_vkGetDisplayModeProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetDisplayModeProperties2KHR" ) );
+ vkGetDisplayModePropertiesKHR = PFN_vkGetDisplayModePropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetDisplayModePropertiesKHR" ) );
+ vkGetDisplayPlaneCapabilities2KHR = PFN_vkGetDisplayPlaneCapabilities2KHR( vkGetInstanceProcAddr( instance, "vkGetDisplayPlaneCapabilities2KHR" ) );
+ vkGetDisplayPlaneCapabilitiesKHR = PFN_vkGetDisplayPlaneCapabilitiesKHR( vkGetInstanceProcAddr( instance, "vkGetDisplayPlaneCapabilitiesKHR" ) );
+ vkGetDisplayPlaneSupportedDisplaysKHR = PFN_vkGetDisplayPlaneSupportedDisplaysKHR( vkGetInstanceProcAddr( instance, "vkGetDisplayPlaneSupportedDisplaysKHR" ) );
+ vkGetPhysicalDeviceCalibrateableTimeDomainsEXT = PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT" ) );
+ vkGetPhysicalDeviceCooperativeMatrixPropertiesNV = PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV" ) );
+ vkGetPhysicalDeviceDisplayPlaneProperties2KHR = PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR" ) );
+ vkGetPhysicalDeviceDisplayPlanePropertiesKHR = PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR" ) );
+ vkGetPhysicalDeviceDisplayProperties2KHR = PFN_vkGetPhysicalDeviceDisplayProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceDisplayProperties2KHR" ) );
+ vkGetPhysicalDeviceDisplayPropertiesKHR = PFN_vkGetPhysicalDeviceDisplayPropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceDisplayPropertiesKHR" ) );
+ vkGetPhysicalDeviceExternalBufferProperties = PFN_vkGetPhysicalDeviceExternalBufferProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceExternalBufferProperties" ) );
+ vkGetPhysicalDeviceExternalBufferPropertiesKHR = PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceExternalBufferPropertiesKHR" ) );
+ vkGetPhysicalDeviceExternalFenceProperties = PFN_vkGetPhysicalDeviceExternalFenceProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceExternalFenceProperties" ) );
+ vkGetPhysicalDeviceExternalFencePropertiesKHR = PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceExternalFencePropertiesKHR" ) );
+ vkGetPhysicalDeviceExternalImageFormatPropertiesNV = PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV" ) );
+ vkGetPhysicalDeviceExternalSemaphoreProperties = PFN_vkGetPhysicalDeviceExternalSemaphoreProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceExternalSemaphoreProperties" ) );
+ vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR" ) );
+ vkGetPhysicalDeviceFeatures = PFN_vkGetPhysicalDeviceFeatures( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceFeatures" ) );
+ vkGetPhysicalDeviceFeatures2 = PFN_vkGetPhysicalDeviceFeatures2( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceFeatures2" ) );
+ vkGetPhysicalDeviceFeatures2KHR = PFN_vkGetPhysicalDeviceFeatures2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceFeatures2KHR" ) );
+ vkGetPhysicalDeviceFormatProperties = PFN_vkGetPhysicalDeviceFormatProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceFormatProperties" ) );
+ vkGetPhysicalDeviceFormatProperties2 = PFN_vkGetPhysicalDeviceFormatProperties2( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceFormatProperties2" ) );
+ vkGetPhysicalDeviceFormatProperties2KHR = PFN_vkGetPhysicalDeviceFormatProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceFormatProperties2KHR" ) );
+ vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX = PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX" ) );
+ vkGetPhysicalDeviceImageFormatProperties = PFN_vkGetPhysicalDeviceImageFormatProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceImageFormatProperties" ) );
+ vkGetPhysicalDeviceImageFormatProperties2 = PFN_vkGetPhysicalDeviceImageFormatProperties2( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceImageFormatProperties2" ) );
+ vkGetPhysicalDeviceImageFormatProperties2KHR = PFN_vkGetPhysicalDeviceImageFormatProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceImageFormatProperties2KHR" ) );
+ vkGetPhysicalDeviceMemoryProperties = PFN_vkGetPhysicalDeviceMemoryProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceMemoryProperties" ) );
+ vkGetPhysicalDeviceMemoryProperties2 = PFN_vkGetPhysicalDeviceMemoryProperties2( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceMemoryProperties2" ) );
+ vkGetPhysicalDeviceMemoryProperties2KHR = PFN_vkGetPhysicalDeviceMemoryProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceMemoryProperties2KHR" ) );
+ vkGetPhysicalDeviceMultisamplePropertiesEXT = PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceMultisamplePropertiesEXT" ) );
+ vkGetPhysicalDevicePresentRectanglesKHR = PFN_vkGetPhysicalDevicePresentRectanglesKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDevicePresentRectanglesKHR" ) );
+ vkGetPhysicalDeviceProperties = PFN_vkGetPhysicalDeviceProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceProperties" ) );
+ vkGetPhysicalDeviceProperties2 = PFN_vkGetPhysicalDeviceProperties2( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceProperties2" ) );
+ vkGetPhysicalDeviceProperties2KHR = PFN_vkGetPhysicalDeviceProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceProperties2KHR" ) );
+ vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR" ) );
+ vkGetPhysicalDeviceQueueFamilyProperties = PFN_vkGetPhysicalDeviceQueueFamilyProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceQueueFamilyProperties" ) );
+ vkGetPhysicalDeviceQueueFamilyProperties2 = PFN_vkGetPhysicalDeviceQueueFamilyProperties2( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceQueueFamilyProperties2" ) );
+ vkGetPhysicalDeviceQueueFamilyProperties2KHR = PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR" ) );
+ vkGetPhysicalDeviceSparseImageFormatProperties = PFN_vkGetPhysicalDeviceSparseImageFormatProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSparseImageFormatProperties" ) );
+ vkGetPhysicalDeviceSparseImageFormatProperties2 = PFN_vkGetPhysicalDeviceSparseImageFormatProperties2( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSparseImageFormatProperties2" ) );
+ vkGetPhysicalDeviceSparseImageFormatProperties2KHR = PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR" ) );
+ vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV" ) );
+ vkGetPhysicalDeviceSurfaceCapabilities2EXT = PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSurfaceCapabilities2EXT" ) );
+ vkGetPhysicalDeviceSurfaceCapabilities2KHR = PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR" ) );
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR = PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR" ) );
+ vkGetPhysicalDeviceSurfaceFormats2KHR = PFN_vkGetPhysicalDeviceSurfaceFormats2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSurfaceFormats2KHR" ) );
+ vkGetPhysicalDeviceSurfaceFormatsKHR = PFN_vkGetPhysicalDeviceSurfaceFormatsKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSurfaceFormatsKHR" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetPhysicalDeviceSurfacePresentModes2EXT = PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSurfacePresentModes2EXT" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkGetPhysicalDeviceSurfacePresentModesKHR = PFN_vkGetPhysicalDeviceSurfacePresentModesKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSurfacePresentModesKHR" ) );
+ vkGetPhysicalDeviceSurfaceSupportKHR = PFN_vkGetPhysicalDeviceSurfaceSupportKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceSurfaceSupportKHR" ) );
+ vkGetPhysicalDeviceToolPropertiesEXT = PFN_vkGetPhysicalDeviceToolPropertiesEXT( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceToolPropertiesEXT" ) );
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ vkGetPhysicalDeviceWaylandPresentationSupportKHR = PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR" ) );
+#endif /*VK_USE_PLATFORM_WAYLAND_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetPhysicalDeviceWin32PresentationSupportKHR = PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ vkGetPhysicalDeviceXcbPresentationSupportKHR = PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR" ) );
+#endif /*VK_USE_PLATFORM_XCB_KHR*/
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ vkGetPhysicalDeviceXlibPresentationSupportKHR = PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR" ) );
+#endif /*VK_USE_PLATFORM_XLIB_KHR*/
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ vkGetRandROutputDisplayEXT = PFN_vkGetRandROutputDisplayEXT( vkGetInstanceProcAddr( instance, "vkGetRandROutputDisplayEXT" ) );
+#endif /*VK_USE_PLATFORM_XLIB_XRANDR_EXT*/
+ vkReleaseDisplayEXT = PFN_vkReleaseDisplayEXT( vkGetInstanceProcAddr( instance, "vkReleaseDisplayEXT" ) );
+ vkBeginCommandBuffer = PFN_vkBeginCommandBuffer( vkGetInstanceProcAddr( instance, "vkBeginCommandBuffer" ) );
+ vkCmdBeginConditionalRenderingEXT = PFN_vkCmdBeginConditionalRenderingEXT( vkGetInstanceProcAddr( instance, "vkCmdBeginConditionalRenderingEXT" ) );
+ vkCmdBeginDebugUtilsLabelEXT = PFN_vkCmdBeginDebugUtilsLabelEXT( vkGetInstanceProcAddr( instance, "vkCmdBeginDebugUtilsLabelEXT" ) );
+ vkCmdBeginQuery = PFN_vkCmdBeginQuery( vkGetInstanceProcAddr( instance, "vkCmdBeginQuery" ) );
+ vkCmdBeginQueryIndexedEXT = PFN_vkCmdBeginQueryIndexedEXT( vkGetInstanceProcAddr( instance, "vkCmdBeginQueryIndexedEXT" ) );
+ vkCmdBeginRenderPass = PFN_vkCmdBeginRenderPass( vkGetInstanceProcAddr( instance, "vkCmdBeginRenderPass" ) );
+ vkCmdBeginRenderPass2 = PFN_vkCmdBeginRenderPass2( vkGetInstanceProcAddr( instance, "vkCmdBeginRenderPass2" ) );
+ vkCmdBeginRenderPass2KHR = PFN_vkCmdBeginRenderPass2KHR( vkGetInstanceProcAddr( instance, "vkCmdBeginRenderPass2KHR" ) );
+ vkCmdBeginTransformFeedbackEXT = PFN_vkCmdBeginTransformFeedbackEXT( vkGetInstanceProcAddr( instance, "vkCmdBeginTransformFeedbackEXT" ) );
+ vkCmdBindDescriptorSets = PFN_vkCmdBindDescriptorSets( vkGetInstanceProcAddr( instance, "vkCmdBindDescriptorSets" ) );
+ vkCmdBindIndexBuffer = PFN_vkCmdBindIndexBuffer( vkGetInstanceProcAddr( instance, "vkCmdBindIndexBuffer" ) );
+ vkCmdBindPipeline = PFN_vkCmdBindPipeline( vkGetInstanceProcAddr( instance, "vkCmdBindPipeline" ) );
+ vkCmdBindShadingRateImageNV = PFN_vkCmdBindShadingRateImageNV( vkGetInstanceProcAddr( instance, "vkCmdBindShadingRateImageNV" ) );
+ vkCmdBindTransformFeedbackBuffersEXT = PFN_vkCmdBindTransformFeedbackBuffersEXT( vkGetInstanceProcAddr( instance, "vkCmdBindTransformFeedbackBuffersEXT" ) );
+ vkCmdBindVertexBuffers = PFN_vkCmdBindVertexBuffers( vkGetInstanceProcAddr( instance, "vkCmdBindVertexBuffers" ) );
+ vkCmdBlitImage = PFN_vkCmdBlitImage( vkGetInstanceProcAddr( instance, "vkCmdBlitImage" ) );
+ vkCmdBuildAccelerationStructureNV = PFN_vkCmdBuildAccelerationStructureNV( vkGetInstanceProcAddr( instance, "vkCmdBuildAccelerationStructureNV" ) );
+ vkCmdClearAttachments = PFN_vkCmdClearAttachments( vkGetInstanceProcAddr( instance, "vkCmdClearAttachments" ) );
+ vkCmdClearColorImage = PFN_vkCmdClearColorImage( vkGetInstanceProcAddr( instance, "vkCmdClearColorImage" ) );
+ vkCmdClearDepthStencilImage = PFN_vkCmdClearDepthStencilImage( vkGetInstanceProcAddr( instance, "vkCmdClearDepthStencilImage" ) );
+ vkCmdCopyAccelerationStructureNV = PFN_vkCmdCopyAccelerationStructureNV( vkGetInstanceProcAddr( instance, "vkCmdCopyAccelerationStructureNV" ) );
+ vkCmdCopyBuffer = PFN_vkCmdCopyBuffer( vkGetInstanceProcAddr( instance, "vkCmdCopyBuffer" ) );
+ vkCmdCopyBufferToImage = PFN_vkCmdCopyBufferToImage( vkGetInstanceProcAddr( instance, "vkCmdCopyBufferToImage" ) );
+ vkCmdCopyImage = PFN_vkCmdCopyImage( vkGetInstanceProcAddr( instance, "vkCmdCopyImage" ) );
+ vkCmdCopyImageToBuffer = PFN_vkCmdCopyImageToBuffer( vkGetInstanceProcAddr( instance, "vkCmdCopyImageToBuffer" ) );
+ vkCmdCopyQueryPoolResults = PFN_vkCmdCopyQueryPoolResults( vkGetInstanceProcAddr( instance, "vkCmdCopyQueryPoolResults" ) );
+ vkCmdDebugMarkerBeginEXT = PFN_vkCmdDebugMarkerBeginEXT( vkGetInstanceProcAddr( instance, "vkCmdDebugMarkerBeginEXT" ) );
+ vkCmdDebugMarkerEndEXT = PFN_vkCmdDebugMarkerEndEXT( vkGetInstanceProcAddr( instance, "vkCmdDebugMarkerEndEXT" ) );
+ vkCmdDebugMarkerInsertEXT = PFN_vkCmdDebugMarkerInsertEXT( vkGetInstanceProcAddr( instance, "vkCmdDebugMarkerInsertEXT" ) );
+ vkCmdDispatch = PFN_vkCmdDispatch( vkGetInstanceProcAddr( instance, "vkCmdDispatch" ) );
+ vkCmdDispatchBase = PFN_vkCmdDispatchBase( vkGetInstanceProcAddr( instance, "vkCmdDispatchBase" ) );
+ vkCmdDispatchBaseKHR = PFN_vkCmdDispatchBaseKHR( vkGetInstanceProcAddr( instance, "vkCmdDispatchBaseKHR" ) );
+ vkCmdDispatchIndirect = PFN_vkCmdDispatchIndirect( vkGetInstanceProcAddr( instance, "vkCmdDispatchIndirect" ) );
+ vkCmdDraw = PFN_vkCmdDraw( vkGetInstanceProcAddr( instance, "vkCmdDraw" ) );
+ vkCmdDrawIndexed = PFN_vkCmdDrawIndexed( vkGetInstanceProcAddr( instance, "vkCmdDrawIndexed" ) );
+ vkCmdDrawIndexedIndirect = PFN_vkCmdDrawIndexedIndirect( vkGetInstanceProcAddr( instance, "vkCmdDrawIndexedIndirect" ) );
+ vkCmdDrawIndexedIndirectCount = PFN_vkCmdDrawIndexedIndirectCount( vkGetInstanceProcAddr( instance, "vkCmdDrawIndexedIndirectCount" ) );
+ vkCmdDrawIndexedIndirectCountAMD = PFN_vkCmdDrawIndexedIndirectCountAMD( vkGetInstanceProcAddr( instance, "vkCmdDrawIndexedIndirectCountAMD" ) );
+ vkCmdDrawIndexedIndirectCountKHR = PFN_vkCmdDrawIndexedIndirectCountKHR( vkGetInstanceProcAddr( instance, "vkCmdDrawIndexedIndirectCountKHR" ) );
+ vkCmdDrawIndirect = PFN_vkCmdDrawIndirect( vkGetInstanceProcAddr( instance, "vkCmdDrawIndirect" ) );
+ vkCmdDrawIndirectByteCountEXT = PFN_vkCmdDrawIndirectByteCountEXT( vkGetInstanceProcAddr( instance, "vkCmdDrawIndirectByteCountEXT" ) );
+ vkCmdDrawIndirectCount = PFN_vkCmdDrawIndirectCount( vkGetInstanceProcAddr( instance, "vkCmdDrawIndirectCount" ) );
+ vkCmdDrawIndirectCountAMD = PFN_vkCmdDrawIndirectCountAMD( vkGetInstanceProcAddr( instance, "vkCmdDrawIndirectCountAMD" ) );
+ vkCmdDrawIndirectCountKHR = PFN_vkCmdDrawIndirectCountKHR( vkGetInstanceProcAddr( instance, "vkCmdDrawIndirectCountKHR" ) );
+ vkCmdDrawMeshTasksIndirectCountNV = PFN_vkCmdDrawMeshTasksIndirectCountNV( vkGetInstanceProcAddr( instance, "vkCmdDrawMeshTasksIndirectCountNV" ) );
+ vkCmdDrawMeshTasksIndirectNV = PFN_vkCmdDrawMeshTasksIndirectNV( vkGetInstanceProcAddr( instance, "vkCmdDrawMeshTasksIndirectNV" ) );
+ vkCmdDrawMeshTasksNV = PFN_vkCmdDrawMeshTasksNV( vkGetInstanceProcAddr( instance, "vkCmdDrawMeshTasksNV" ) );
+ vkCmdEndConditionalRenderingEXT = PFN_vkCmdEndConditionalRenderingEXT( vkGetInstanceProcAddr( instance, "vkCmdEndConditionalRenderingEXT" ) );
+ vkCmdEndDebugUtilsLabelEXT = PFN_vkCmdEndDebugUtilsLabelEXT( vkGetInstanceProcAddr( instance, "vkCmdEndDebugUtilsLabelEXT" ) );
+ vkCmdEndQuery = PFN_vkCmdEndQuery( vkGetInstanceProcAddr( instance, "vkCmdEndQuery" ) );
+ vkCmdEndQueryIndexedEXT = PFN_vkCmdEndQueryIndexedEXT( vkGetInstanceProcAddr( instance, "vkCmdEndQueryIndexedEXT" ) );
+ vkCmdEndRenderPass = PFN_vkCmdEndRenderPass( vkGetInstanceProcAddr( instance, "vkCmdEndRenderPass" ) );
+ vkCmdEndRenderPass2 = PFN_vkCmdEndRenderPass2( vkGetInstanceProcAddr( instance, "vkCmdEndRenderPass2" ) );
+ vkCmdEndRenderPass2KHR = PFN_vkCmdEndRenderPass2KHR( vkGetInstanceProcAddr( instance, "vkCmdEndRenderPass2KHR" ) );
+ vkCmdEndTransformFeedbackEXT = PFN_vkCmdEndTransformFeedbackEXT( vkGetInstanceProcAddr( instance, "vkCmdEndTransformFeedbackEXT" ) );
+ vkCmdExecuteCommands = PFN_vkCmdExecuteCommands( vkGetInstanceProcAddr( instance, "vkCmdExecuteCommands" ) );
+ vkCmdFillBuffer = PFN_vkCmdFillBuffer( vkGetInstanceProcAddr( instance, "vkCmdFillBuffer" ) );
+ vkCmdInsertDebugUtilsLabelEXT = PFN_vkCmdInsertDebugUtilsLabelEXT( vkGetInstanceProcAddr( instance, "vkCmdInsertDebugUtilsLabelEXT" ) );
+ vkCmdNextSubpass = PFN_vkCmdNextSubpass( vkGetInstanceProcAddr( instance, "vkCmdNextSubpass" ) );
+ vkCmdNextSubpass2 = PFN_vkCmdNextSubpass2( vkGetInstanceProcAddr( instance, "vkCmdNextSubpass2" ) );
+ vkCmdNextSubpass2KHR = PFN_vkCmdNextSubpass2KHR( vkGetInstanceProcAddr( instance, "vkCmdNextSubpass2KHR" ) );
+ vkCmdPipelineBarrier = PFN_vkCmdPipelineBarrier( vkGetInstanceProcAddr( instance, "vkCmdPipelineBarrier" ) );
+ vkCmdProcessCommandsNVX = PFN_vkCmdProcessCommandsNVX( vkGetInstanceProcAddr( instance, "vkCmdProcessCommandsNVX" ) );
+ vkCmdPushConstants = PFN_vkCmdPushConstants( vkGetInstanceProcAddr( instance, "vkCmdPushConstants" ) );
+ vkCmdPushDescriptorSetKHR = PFN_vkCmdPushDescriptorSetKHR( vkGetInstanceProcAddr( instance, "vkCmdPushDescriptorSetKHR" ) );
+ vkCmdPushDescriptorSetWithTemplateKHR = PFN_vkCmdPushDescriptorSetWithTemplateKHR( vkGetInstanceProcAddr( instance, "vkCmdPushDescriptorSetWithTemplateKHR" ) );
+ vkCmdReserveSpaceForCommandsNVX = PFN_vkCmdReserveSpaceForCommandsNVX( vkGetInstanceProcAddr( instance, "vkCmdReserveSpaceForCommandsNVX" ) );
+ vkCmdResetEvent = PFN_vkCmdResetEvent( vkGetInstanceProcAddr( instance, "vkCmdResetEvent" ) );
+ vkCmdResetQueryPool = PFN_vkCmdResetQueryPool( vkGetInstanceProcAddr( instance, "vkCmdResetQueryPool" ) );
+ vkCmdResolveImage = PFN_vkCmdResolveImage( vkGetInstanceProcAddr( instance, "vkCmdResolveImage" ) );
+ vkCmdSetBlendConstants = PFN_vkCmdSetBlendConstants( vkGetInstanceProcAddr( instance, "vkCmdSetBlendConstants" ) );
+ vkCmdSetCheckpointNV = PFN_vkCmdSetCheckpointNV( vkGetInstanceProcAddr( instance, "vkCmdSetCheckpointNV" ) );
+ vkCmdSetCoarseSampleOrderNV = PFN_vkCmdSetCoarseSampleOrderNV( vkGetInstanceProcAddr( instance, "vkCmdSetCoarseSampleOrderNV" ) );
+ vkCmdSetDepthBias = PFN_vkCmdSetDepthBias( vkGetInstanceProcAddr( instance, "vkCmdSetDepthBias" ) );
+ vkCmdSetDepthBounds = PFN_vkCmdSetDepthBounds( vkGetInstanceProcAddr( instance, "vkCmdSetDepthBounds" ) );
+ vkCmdSetDeviceMask = PFN_vkCmdSetDeviceMask( vkGetInstanceProcAddr( instance, "vkCmdSetDeviceMask" ) );
+ vkCmdSetDeviceMaskKHR = PFN_vkCmdSetDeviceMaskKHR( vkGetInstanceProcAddr( instance, "vkCmdSetDeviceMaskKHR" ) );
+ vkCmdSetDiscardRectangleEXT = PFN_vkCmdSetDiscardRectangleEXT( vkGetInstanceProcAddr( instance, "vkCmdSetDiscardRectangleEXT" ) );
+ vkCmdSetEvent = PFN_vkCmdSetEvent( vkGetInstanceProcAddr( instance, "vkCmdSetEvent" ) );
+ vkCmdSetExclusiveScissorNV = PFN_vkCmdSetExclusiveScissorNV( vkGetInstanceProcAddr( instance, "vkCmdSetExclusiveScissorNV" ) );
+ vkCmdSetLineStippleEXT = PFN_vkCmdSetLineStippleEXT( vkGetInstanceProcAddr( instance, "vkCmdSetLineStippleEXT" ) );
+ vkCmdSetLineWidth = PFN_vkCmdSetLineWidth( vkGetInstanceProcAddr( instance, "vkCmdSetLineWidth" ) );
+ vkCmdSetPerformanceMarkerINTEL = PFN_vkCmdSetPerformanceMarkerINTEL( vkGetInstanceProcAddr( instance, "vkCmdSetPerformanceMarkerINTEL" ) );
+ vkCmdSetPerformanceOverrideINTEL = PFN_vkCmdSetPerformanceOverrideINTEL( vkGetInstanceProcAddr( instance, "vkCmdSetPerformanceOverrideINTEL" ) );
+ vkCmdSetPerformanceStreamMarkerINTEL = PFN_vkCmdSetPerformanceStreamMarkerINTEL( vkGetInstanceProcAddr( instance, "vkCmdSetPerformanceStreamMarkerINTEL" ) );
+ vkCmdSetSampleLocationsEXT = PFN_vkCmdSetSampleLocationsEXT( vkGetInstanceProcAddr( instance, "vkCmdSetSampleLocationsEXT" ) );
+ vkCmdSetScissor = PFN_vkCmdSetScissor( vkGetInstanceProcAddr( instance, "vkCmdSetScissor" ) );
+ vkCmdSetStencilCompareMask = PFN_vkCmdSetStencilCompareMask( vkGetInstanceProcAddr( instance, "vkCmdSetStencilCompareMask" ) );
+ vkCmdSetStencilReference = PFN_vkCmdSetStencilReference( vkGetInstanceProcAddr( instance, "vkCmdSetStencilReference" ) );
+ vkCmdSetStencilWriteMask = PFN_vkCmdSetStencilWriteMask( vkGetInstanceProcAddr( instance, "vkCmdSetStencilWriteMask" ) );
+ vkCmdSetViewport = PFN_vkCmdSetViewport( vkGetInstanceProcAddr( instance, "vkCmdSetViewport" ) );
+ vkCmdSetViewportShadingRatePaletteNV = PFN_vkCmdSetViewportShadingRatePaletteNV( vkGetInstanceProcAddr( instance, "vkCmdSetViewportShadingRatePaletteNV" ) );
+ vkCmdSetViewportWScalingNV = PFN_vkCmdSetViewportWScalingNV( vkGetInstanceProcAddr( instance, "vkCmdSetViewportWScalingNV" ) );
+ vkCmdTraceRaysNV = PFN_vkCmdTraceRaysNV( vkGetInstanceProcAddr( instance, "vkCmdTraceRaysNV" ) );
+ vkCmdUpdateBuffer = PFN_vkCmdUpdateBuffer( vkGetInstanceProcAddr( instance, "vkCmdUpdateBuffer" ) );
+ vkCmdWaitEvents = PFN_vkCmdWaitEvents( vkGetInstanceProcAddr( instance, "vkCmdWaitEvents" ) );
+ vkCmdWriteAccelerationStructuresPropertiesNV = PFN_vkCmdWriteAccelerationStructuresPropertiesNV( vkGetInstanceProcAddr( instance, "vkCmdWriteAccelerationStructuresPropertiesNV" ) );
+ vkCmdWriteBufferMarkerAMD = PFN_vkCmdWriteBufferMarkerAMD( vkGetInstanceProcAddr( instance, "vkCmdWriteBufferMarkerAMD" ) );
+ vkCmdWriteTimestamp = PFN_vkCmdWriteTimestamp( vkGetInstanceProcAddr( instance, "vkCmdWriteTimestamp" ) );
+ vkEndCommandBuffer = PFN_vkEndCommandBuffer( vkGetInstanceProcAddr( instance, "vkEndCommandBuffer" ) );
+ vkResetCommandBuffer = PFN_vkResetCommandBuffer( vkGetInstanceProcAddr( instance, "vkResetCommandBuffer" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkAcquireFullScreenExclusiveModeEXT = PFN_vkAcquireFullScreenExclusiveModeEXT( vkGetInstanceProcAddr( instance, "vkAcquireFullScreenExclusiveModeEXT" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkAcquireNextImage2KHR = PFN_vkAcquireNextImage2KHR( vkGetInstanceProcAddr( instance, "vkAcquireNextImage2KHR" ) );
+ vkAcquireNextImageKHR = PFN_vkAcquireNextImageKHR( vkGetInstanceProcAddr( instance, "vkAcquireNextImageKHR" ) );
+ vkAcquirePerformanceConfigurationINTEL = PFN_vkAcquirePerformanceConfigurationINTEL( vkGetInstanceProcAddr( instance, "vkAcquirePerformanceConfigurationINTEL" ) );
+ vkAcquireProfilingLockKHR = PFN_vkAcquireProfilingLockKHR( vkGetInstanceProcAddr( instance, "vkAcquireProfilingLockKHR" ) );
+ vkAllocateCommandBuffers = PFN_vkAllocateCommandBuffers( vkGetInstanceProcAddr( instance, "vkAllocateCommandBuffers" ) );
+ vkAllocateDescriptorSets = PFN_vkAllocateDescriptorSets( vkGetInstanceProcAddr( instance, "vkAllocateDescriptorSets" ) );
+ vkAllocateMemory = PFN_vkAllocateMemory( vkGetInstanceProcAddr( instance, "vkAllocateMemory" ) );
+ vkBindAccelerationStructureMemoryNV = PFN_vkBindAccelerationStructureMemoryNV( vkGetInstanceProcAddr( instance, "vkBindAccelerationStructureMemoryNV" ) );
+ vkBindBufferMemory = PFN_vkBindBufferMemory( vkGetInstanceProcAddr( instance, "vkBindBufferMemory" ) );
+ vkBindBufferMemory2 = PFN_vkBindBufferMemory2( vkGetInstanceProcAddr( instance, "vkBindBufferMemory2" ) );
+ vkBindBufferMemory2KHR = PFN_vkBindBufferMemory2KHR( vkGetInstanceProcAddr( instance, "vkBindBufferMemory2KHR" ) );
+ vkBindImageMemory = PFN_vkBindImageMemory( vkGetInstanceProcAddr( instance, "vkBindImageMemory" ) );
+ vkBindImageMemory2 = PFN_vkBindImageMemory2( vkGetInstanceProcAddr( instance, "vkBindImageMemory2" ) );
+ vkBindImageMemory2KHR = PFN_vkBindImageMemory2KHR( vkGetInstanceProcAddr( instance, "vkBindImageMemory2KHR" ) );
+ vkCompileDeferredNV = PFN_vkCompileDeferredNV( vkGetInstanceProcAddr( instance, "vkCompileDeferredNV" ) );
+ vkCreateAccelerationStructureNV = PFN_vkCreateAccelerationStructureNV( vkGetInstanceProcAddr( instance, "vkCreateAccelerationStructureNV" ) );
+ vkCreateBuffer = PFN_vkCreateBuffer( vkGetInstanceProcAddr( instance, "vkCreateBuffer" ) );
+ vkCreateBufferView = PFN_vkCreateBufferView( vkGetInstanceProcAddr( instance, "vkCreateBufferView" ) );
+ vkCreateCommandPool = PFN_vkCreateCommandPool( vkGetInstanceProcAddr( instance, "vkCreateCommandPool" ) );
+ vkCreateComputePipelines = PFN_vkCreateComputePipelines( vkGetInstanceProcAddr( instance, "vkCreateComputePipelines" ) );
+ vkCreateDescriptorPool = PFN_vkCreateDescriptorPool( vkGetInstanceProcAddr( instance, "vkCreateDescriptorPool" ) );
+ vkCreateDescriptorSetLayout = PFN_vkCreateDescriptorSetLayout( vkGetInstanceProcAddr( instance, "vkCreateDescriptorSetLayout" ) );
+ vkCreateDescriptorUpdateTemplate = PFN_vkCreateDescriptorUpdateTemplate( vkGetInstanceProcAddr( instance, "vkCreateDescriptorUpdateTemplate" ) );
+ vkCreateDescriptorUpdateTemplateKHR = PFN_vkCreateDescriptorUpdateTemplateKHR( vkGetInstanceProcAddr( instance, "vkCreateDescriptorUpdateTemplateKHR" ) );
+ vkCreateEvent = PFN_vkCreateEvent( vkGetInstanceProcAddr( instance, "vkCreateEvent" ) );
+ vkCreateFence = PFN_vkCreateFence( vkGetInstanceProcAddr( instance, "vkCreateFence" ) );
+ vkCreateFramebuffer = PFN_vkCreateFramebuffer( vkGetInstanceProcAddr( instance, "vkCreateFramebuffer" ) );
+ vkCreateGraphicsPipelines = PFN_vkCreateGraphicsPipelines( vkGetInstanceProcAddr( instance, "vkCreateGraphicsPipelines" ) );
+ vkCreateImage = PFN_vkCreateImage( vkGetInstanceProcAddr( instance, "vkCreateImage" ) );
+ vkCreateImageView = PFN_vkCreateImageView( vkGetInstanceProcAddr( instance, "vkCreateImageView" ) );
+ vkCreateIndirectCommandsLayoutNVX = PFN_vkCreateIndirectCommandsLayoutNVX( vkGetInstanceProcAddr( instance, "vkCreateIndirectCommandsLayoutNVX" ) );
+ vkCreateObjectTableNVX = PFN_vkCreateObjectTableNVX( vkGetInstanceProcAddr( instance, "vkCreateObjectTableNVX" ) );
+ vkCreatePipelineCache = PFN_vkCreatePipelineCache( vkGetInstanceProcAddr( instance, "vkCreatePipelineCache" ) );
+ vkCreatePipelineLayout = PFN_vkCreatePipelineLayout( vkGetInstanceProcAddr( instance, "vkCreatePipelineLayout" ) );
+ vkCreateQueryPool = PFN_vkCreateQueryPool( vkGetInstanceProcAddr( instance, "vkCreateQueryPool" ) );
+ vkCreateRayTracingPipelinesNV = PFN_vkCreateRayTracingPipelinesNV( vkGetInstanceProcAddr( instance, "vkCreateRayTracingPipelinesNV" ) );
+ vkCreateRenderPass = PFN_vkCreateRenderPass( vkGetInstanceProcAddr( instance, "vkCreateRenderPass" ) );
+ vkCreateRenderPass2 = PFN_vkCreateRenderPass2( vkGetInstanceProcAddr( instance, "vkCreateRenderPass2" ) );
+ vkCreateRenderPass2KHR = PFN_vkCreateRenderPass2KHR( vkGetInstanceProcAddr( instance, "vkCreateRenderPass2KHR" ) );
+ vkCreateSampler = PFN_vkCreateSampler( vkGetInstanceProcAddr( instance, "vkCreateSampler" ) );
+ vkCreateSamplerYcbcrConversion = PFN_vkCreateSamplerYcbcrConversion( vkGetInstanceProcAddr( instance, "vkCreateSamplerYcbcrConversion" ) );
+ vkCreateSamplerYcbcrConversionKHR = PFN_vkCreateSamplerYcbcrConversionKHR( vkGetInstanceProcAddr( instance, "vkCreateSamplerYcbcrConversionKHR" ) );
+ vkCreateSemaphore = PFN_vkCreateSemaphore( vkGetInstanceProcAddr( instance, "vkCreateSemaphore" ) );
+ vkCreateShaderModule = PFN_vkCreateShaderModule( vkGetInstanceProcAddr( instance, "vkCreateShaderModule" ) );
+ vkCreateSharedSwapchainsKHR = PFN_vkCreateSharedSwapchainsKHR( vkGetInstanceProcAddr( instance, "vkCreateSharedSwapchainsKHR" ) );
+ vkCreateSwapchainKHR = PFN_vkCreateSwapchainKHR( vkGetInstanceProcAddr( instance, "vkCreateSwapchainKHR" ) );
+ vkCreateValidationCacheEXT = PFN_vkCreateValidationCacheEXT( vkGetInstanceProcAddr( instance, "vkCreateValidationCacheEXT" ) );
+ vkDebugMarkerSetObjectNameEXT = PFN_vkDebugMarkerSetObjectNameEXT( vkGetInstanceProcAddr( instance, "vkDebugMarkerSetObjectNameEXT" ) );
+ vkDebugMarkerSetObjectTagEXT = PFN_vkDebugMarkerSetObjectTagEXT( vkGetInstanceProcAddr( instance, "vkDebugMarkerSetObjectTagEXT" ) );
+ vkDestroyAccelerationStructureNV = PFN_vkDestroyAccelerationStructureNV( vkGetInstanceProcAddr( instance, "vkDestroyAccelerationStructureNV" ) );
+ vkDestroyBuffer = PFN_vkDestroyBuffer( vkGetInstanceProcAddr( instance, "vkDestroyBuffer" ) );
+ vkDestroyBufferView = PFN_vkDestroyBufferView( vkGetInstanceProcAddr( instance, "vkDestroyBufferView" ) );
+ vkDestroyCommandPool = PFN_vkDestroyCommandPool( vkGetInstanceProcAddr( instance, "vkDestroyCommandPool" ) );
+ vkDestroyDescriptorPool = PFN_vkDestroyDescriptorPool( vkGetInstanceProcAddr( instance, "vkDestroyDescriptorPool" ) );
+ vkDestroyDescriptorSetLayout = PFN_vkDestroyDescriptorSetLayout( vkGetInstanceProcAddr( instance, "vkDestroyDescriptorSetLayout" ) );
+ vkDestroyDescriptorUpdateTemplate = PFN_vkDestroyDescriptorUpdateTemplate( vkGetInstanceProcAddr( instance, "vkDestroyDescriptorUpdateTemplate" ) );
+ vkDestroyDescriptorUpdateTemplateKHR = PFN_vkDestroyDescriptorUpdateTemplateKHR( vkGetInstanceProcAddr( instance, "vkDestroyDescriptorUpdateTemplateKHR" ) );
+ vkDestroyDevice = PFN_vkDestroyDevice( vkGetInstanceProcAddr( instance, "vkDestroyDevice" ) );
+ vkDestroyEvent = PFN_vkDestroyEvent( vkGetInstanceProcAddr( instance, "vkDestroyEvent" ) );
+ vkDestroyFence = PFN_vkDestroyFence( vkGetInstanceProcAddr( instance, "vkDestroyFence" ) );
+ vkDestroyFramebuffer = PFN_vkDestroyFramebuffer( vkGetInstanceProcAddr( instance, "vkDestroyFramebuffer" ) );
+ vkDestroyImage = PFN_vkDestroyImage( vkGetInstanceProcAddr( instance, "vkDestroyImage" ) );
+ vkDestroyImageView = PFN_vkDestroyImageView( vkGetInstanceProcAddr( instance, "vkDestroyImageView" ) );
+ vkDestroyIndirectCommandsLayoutNVX = PFN_vkDestroyIndirectCommandsLayoutNVX( vkGetInstanceProcAddr( instance, "vkDestroyIndirectCommandsLayoutNVX" ) );
+ vkDestroyObjectTableNVX = PFN_vkDestroyObjectTableNVX( vkGetInstanceProcAddr( instance, "vkDestroyObjectTableNVX" ) );
+ vkDestroyPipeline = PFN_vkDestroyPipeline( vkGetInstanceProcAddr( instance, "vkDestroyPipeline" ) );
+ vkDestroyPipelineCache = PFN_vkDestroyPipelineCache( vkGetInstanceProcAddr( instance, "vkDestroyPipelineCache" ) );
+ vkDestroyPipelineLayout = PFN_vkDestroyPipelineLayout( vkGetInstanceProcAddr( instance, "vkDestroyPipelineLayout" ) );
+ vkDestroyQueryPool = PFN_vkDestroyQueryPool( vkGetInstanceProcAddr( instance, "vkDestroyQueryPool" ) );
+ vkDestroyRenderPass = PFN_vkDestroyRenderPass( vkGetInstanceProcAddr( instance, "vkDestroyRenderPass" ) );
+ vkDestroySampler = PFN_vkDestroySampler( vkGetInstanceProcAddr( instance, "vkDestroySampler" ) );
+ vkDestroySamplerYcbcrConversion = PFN_vkDestroySamplerYcbcrConversion( vkGetInstanceProcAddr( instance, "vkDestroySamplerYcbcrConversion" ) );
+ vkDestroySamplerYcbcrConversionKHR = PFN_vkDestroySamplerYcbcrConversionKHR( vkGetInstanceProcAddr( instance, "vkDestroySamplerYcbcrConversionKHR" ) );
+ vkDestroySemaphore = PFN_vkDestroySemaphore( vkGetInstanceProcAddr( instance, "vkDestroySemaphore" ) );
+ vkDestroyShaderModule = PFN_vkDestroyShaderModule( vkGetInstanceProcAddr( instance, "vkDestroyShaderModule" ) );
+ vkDestroySwapchainKHR = PFN_vkDestroySwapchainKHR( vkGetInstanceProcAddr( instance, "vkDestroySwapchainKHR" ) );
+ vkDestroyValidationCacheEXT = PFN_vkDestroyValidationCacheEXT( vkGetInstanceProcAddr( instance, "vkDestroyValidationCacheEXT" ) );
+ vkDeviceWaitIdle = PFN_vkDeviceWaitIdle( vkGetInstanceProcAddr( instance, "vkDeviceWaitIdle" ) );
+ vkDisplayPowerControlEXT = PFN_vkDisplayPowerControlEXT( vkGetInstanceProcAddr( instance, "vkDisplayPowerControlEXT" ) );
+ vkFlushMappedMemoryRanges = PFN_vkFlushMappedMemoryRanges( vkGetInstanceProcAddr( instance, "vkFlushMappedMemoryRanges" ) );
+ vkFreeCommandBuffers = PFN_vkFreeCommandBuffers( vkGetInstanceProcAddr( instance, "vkFreeCommandBuffers" ) );
+ vkFreeDescriptorSets = PFN_vkFreeDescriptorSets( vkGetInstanceProcAddr( instance, "vkFreeDescriptorSets" ) );
+ vkFreeMemory = PFN_vkFreeMemory( vkGetInstanceProcAddr( instance, "vkFreeMemory" ) );
+ vkGetAccelerationStructureHandleNV = PFN_vkGetAccelerationStructureHandleNV( vkGetInstanceProcAddr( instance, "vkGetAccelerationStructureHandleNV" ) );
+ vkGetAccelerationStructureMemoryRequirementsNV = PFN_vkGetAccelerationStructureMemoryRequirementsNV( vkGetInstanceProcAddr( instance, "vkGetAccelerationStructureMemoryRequirementsNV" ) );
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ vkGetAndroidHardwareBufferPropertiesANDROID = PFN_vkGetAndroidHardwareBufferPropertiesANDROID( vkGetInstanceProcAddr( instance, "vkGetAndroidHardwareBufferPropertiesANDROID" ) );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ vkGetBufferDeviceAddress = PFN_vkGetBufferDeviceAddress( vkGetInstanceProcAddr( instance, "vkGetBufferDeviceAddress" ) );
+ vkGetBufferDeviceAddressEXT = PFN_vkGetBufferDeviceAddressEXT( vkGetInstanceProcAddr( instance, "vkGetBufferDeviceAddressEXT" ) );
+ vkGetBufferDeviceAddressKHR = PFN_vkGetBufferDeviceAddressKHR( vkGetInstanceProcAddr( instance, "vkGetBufferDeviceAddressKHR" ) );
+ vkGetBufferMemoryRequirements = PFN_vkGetBufferMemoryRequirements( vkGetInstanceProcAddr( instance, "vkGetBufferMemoryRequirements" ) );
+ vkGetBufferMemoryRequirements2 = PFN_vkGetBufferMemoryRequirements2( vkGetInstanceProcAddr( instance, "vkGetBufferMemoryRequirements2" ) );
+ vkGetBufferMemoryRequirements2KHR = PFN_vkGetBufferMemoryRequirements2KHR( vkGetInstanceProcAddr( instance, "vkGetBufferMemoryRequirements2KHR" ) );
+ vkGetBufferOpaqueCaptureAddress = PFN_vkGetBufferOpaqueCaptureAddress( vkGetInstanceProcAddr( instance, "vkGetBufferOpaqueCaptureAddress" ) );
+ vkGetBufferOpaqueCaptureAddressKHR = PFN_vkGetBufferOpaqueCaptureAddressKHR( vkGetInstanceProcAddr( instance, "vkGetBufferOpaqueCaptureAddressKHR" ) );
+ vkGetCalibratedTimestampsEXT = PFN_vkGetCalibratedTimestampsEXT( vkGetInstanceProcAddr( instance, "vkGetCalibratedTimestampsEXT" ) );
+ vkGetDescriptorSetLayoutSupport = PFN_vkGetDescriptorSetLayoutSupport( vkGetInstanceProcAddr( instance, "vkGetDescriptorSetLayoutSupport" ) );
+ vkGetDescriptorSetLayoutSupportKHR = PFN_vkGetDescriptorSetLayoutSupportKHR( vkGetInstanceProcAddr( instance, "vkGetDescriptorSetLayoutSupportKHR" ) );
+ vkGetDeviceGroupPeerMemoryFeatures = PFN_vkGetDeviceGroupPeerMemoryFeatures( vkGetInstanceProcAddr( instance, "vkGetDeviceGroupPeerMemoryFeatures" ) );
+ vkGetDeviceGroupPeerMemoryFeaturesKHR = PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR( vkGetInstanceProcAddr( instance, "vkGetDeviceGroupPeerMemoryFeaturesKHR" ) );
+ vkGetDeviceGroupPresentCapabilitiesKHR = PFN_vkGetDeviceGroupPresentCapabilitiesKHR( vkGetInstanceProcAddr( instance, "vkGetDeviceGroupPresentCapabilitiesKHR" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetDeviceGroupSurfacePresentModes2EXT = PFN_vkGetDeviceGroupSurfacePresentModes2EXT( vkGetInstanceProcAddr( instance, "vkGetDeviceGroupSurfacePresentModes2EXT" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkGetDeviceGroupSurfacePresentModesKHR = PFN_vkGetDeviceGroupSurfacePresentModesKHR( vkGetInstanceProcAddr( instance, "vkGetDeviceGroupSurfacePresentModesKHR" ) );
+ vkGetDeviceMemoryCommitment = PFN_vkGetDeviceMemoryCommitment( vkGetInstanceProcAddr( instance, "vkGetDeviceMemoryCommitment" ) );
+ vkGetDeviceMemoryOpaqueCaptureAddress = PFN_vkGetDeviceMemoryOpaqueCaptureAddress( vkGetInstanceProcAddr( instance, "vkGetDeviceMemoryOpaqueCaptureAddress" ) );
+ vkGetDeviceMemoryOpaqueCaptureAddressKHR = PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR( vkGetInstanceProcAddr( instance, "vkGetDeviceMemoryOpaqueCaptureAddressKHR" ) );
+ vkGetDeviceProcAddr = PFN_vkGetDeviceProcAddr( vkGetInstanceProcAddr( instance, "vkGetDeviceProcAddr" ) );
+ vkGetDeviceQueue = PFN_vkGetDeviceQueue( vkGetInstanceProcAddr( instance, "vkGetDeviceQueue" ) );
+ vkGetDeviceQueue2 = PFN_vkGetDeviceQueue2( vkGetInstanceProcAddr( instance, "vkGetDeviceQueue2" ) );
+ vkGetEventStatus = PFN_vkGetEventStatus( vkGetInstanceProcAddr( instance, "vkGetEventStatus" ) );
+ vkGetFenceFdKHR = PFN_vkGetFenceFdKHR( vkGetInstanceProcAddr( instance, "vkGetFenceFdKHR" ) );
+ vkGetFenceStatus = PFN_vkGetFenceStatus( vkGetInstanceProcAddr( instance, "vkGetFenceStatus" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetFenceWin32HandleKHR = PFN_vkGetFenceWin32HandleKHR( vkGetInstanceProcAddr( instance, "vkGetFenceWin32HandleKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkGetImageDrmFormatModifierPropertiesEXT = PFN_vkGetImageDrmFormatModifierPropertiesEXT( vkGetInstanceProcAddr( instance, "vkGetImageDrmFormatModifierPropertiesEXT" ) );
+ vkGetImageMemoryRequirements = PFN_vkGetImageMemoryRequirements( vkGetInstanceProcAddr( instance, "vkGetImageMemoryRequirements" ) );
+ vkGetImageMemoryRequirements2 = PFN_vkGetImageMemoryRequirements2( vkGetInstanceProcAddr( instance, "vkGetImageMemoryRequirements2" ) );
+ vkGetImageMemoryRequirements2KHR = PFN_vkGetImageMemoryRequirements2KHR( vkGetInstanceProcAddr( instance, "vkGetImageMemoryRequirements2KHR" ) );
+ vkGetImageSparseMemoryRequirements = PFN_vkGetImageSparseMemoryRequirements( vkGetInstanceProcAddr( instance, "vkGetImageSparseMemoryRequirements" ) );
+ vkGetImageSparseMemoryRequirements2 = PFN_vkGetImageSparseMemoryRequirements2( vkGetInstanceProcAddr( instance, "vkGetImageSparseMemoryRequirements2" ) );
+ vkGetImageSparseMemoryRequirements2KHR = PFN_vkGetImageSparseMemoryRequirements2KHR( vkGetInstanceProcAddr( instance, "vkGetImageSparseMemoryRequirements2KHR" ) );
+ vkGetImageSubresourceLayout = PFN_vkGetImageSubresourceLayout( vkGetInstanceProcAddr( instance, "vkGetImageSubresourceLayout" ) );
+ vkGetImageViewHandleNVX = PFN_vkGetImageViewHandleNVX( vkGetInstanceProcAddr( instance, "vkGetImageViewHandleNVX" ) );
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ vkGetMemoryAndroidHardwareBufferANDROID = PFN_vkGetMemoryAndroidHardwareBufferANDROID( vkGetInstanceProcAddr( instance, "vkGetMemoryAndroidHardwareBufferANDROID" ) );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ vkGetMemoryFdKHR = PFN_vkGetMemoryFdKHR( vkGetInstanceProcAddr( instance, "vkGetMemoryFdKHR" ) );
+ vkGetMemoryFdPropertiesKHR = PFN_vkGetMemoryFdPropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetMemoryFdPropertiesKHR" ) );
+ vkGetMemoryHostPointerPropertiesEXT = PFN_vkGetMemoryHostPointerPropertiesEXT( vkGetInstanceProcAddr( instance, "vkGetMemoryHostPointerPropertiesEXT" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetMemoryWin32HandleKHR = PFN_vkGetMemoryWin32HandleKHR( vkGetInstanceProcAddr( instance, "vkGetMemoryWin32HandleKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetMemoryWin32HandleNV = PFN_vkGetMemoryWin32HandleNV( vkGetInstanceProcAddr( instance, "vkGetMemoryWin32HandleNV" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetMemoryWin32HandlePropertiesKHR = PFN_vkGetMemoryWin32HandlePropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetMemoryWin32HandlePropertiesKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkGetPastPresentationTimingGOOGLE = PFN_vkGetPastPresentationTimingGOOGLE( vkGetInstanceProcAddr( instance, "vkGetPastPresentationTimingGOOGLE" ) );
+ vkGetPerformanceParameterINTEL = PFN_vkGetPerformanceParameterINTEL( vkGetInstanceProcAddr( instance, "vkGetPerformanceParameterINTEL" ) );
+ vkGetPipelineCacheData = PFN_vkGetPipelineCacheData( vkGetInstanceProcAddr( instance, "vkGetPipelineCacheData" ) );
+ vkGetPipelineExecutableInternalRepresentationsKHR = PFN_vkGetPipelineExecutableInternalRepresentationsKHR( vkGetInstanceProcAddr( instance, "vkGetPipelineExecutableInternalRepresentationsKHR" ) );
+ vkGetPipelineExecutablePropertiesKHR = PFN_vkGetPipelineExecutablePropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetPipelineExecutablePropertiesKHR" ) );
+ vkGetPipelineExecutableStatisticsKHR = PFN_vkGetPipelineExecutableStatisticsKHR( vkGetInstanceProcAddr( instance, "vkGetPipelineExecutableStatisticsKHR" ) );
+ vkGetQueryPoolResults = PFN_vkGetQueryPoolResults( vkGetInstanceProcAddr( instance, "vkGetQueryPoolResults" ) );
+ vkGetRayTracingShaderGroupHandlesNV = PFN_vkGetRayTracingShaderGroupHandlesNV( vkGetInstanceProcAddr( instance, "vkGetRayTracingShaderGroupHandlesNV" ) );
+ vkGetRefreshCycleDurationGOOGLE = PFN_vkGetRefreshCycleDurationGOOGLE( vkGetInstanceProcAddr( instance, "vkGetRefreshCycleDurationGOOGLE" ) );
+ vkGetRenderAreaGranularity = PFN_vkGetRenderAreaGranularity( vkGetInstanceProcAddr( instance, "vkGetRenderAreaGranularity" ) );
+ vkGetSemaphoreCounterValue = PFN_vkGetSemaphoreCounterValue( vkGetInstanceProcAddr( instance, "vkGetSemaphoreCounterValue" ) );
+ vkGetSemaphoreCounterValueKHR = PFN_vkGetSemaphoreCounterValueKHR( vkGetInstanceProcAddr( instance, "vkGetSemaphoreCounterValueKHR" ) );
+ vkGetSemaphoreFdKHR = PFN_vkGetSemaphoreFdKHR( vkGetInstanceProcAddr( instance, "vkGetSemaphoreFdKHR" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetSemaphoreWin32HandleKHR = PFN_vkGetSemaphoreWin32HandleKHR( vkGetInstanceProcAddr( instance, "vkGetSemaphoreWin32HandleKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkGetShaderInfoAMD = PFN_vkGetShaderInfoAMD( vkGetInstanceProcAddr( instance, "vkGetShaderInfoAMD" ) );
+ vkGetSwapchainCounterEXT = PFN_vkGetSwapchainCounterEXT( vkGetInstanceProcAddr( instance, "vkGetSwapchainCounterEXT" ) );
+ vkGetSwapchainImagesKHR = PFN_vkGetSwapchainImagesKHR( vkGetInstanceProcAddr( instance, "vkGetSwapchainImagesKHR" ) );
+ vkGetSwapchainStatusKHR = PFN_vkGetSwapchainStatusKHR( vkGetInstanceProcAddr( instance, "vkGetSwapchainStatusKHR" ) );
+ vkGetValidationCacheDataEXT = PFN_vkGetValidationCacheDataEXT( vkGetInstanceProcAddr( instance, "vkGetValidationCacheDataEXT" ) );
+ vkImportFenceFdKHR = PFN_vkImportFenceFdKHR( vkGetInstanceProcAddr( instance, "vkImportFenceFdKHR" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkImportFenceWin32HandleKHR = PFN_vkImportFenceWin32HandleKHR( vkGetInstanceProcAddr( instance, "vkImportFenceWin32HandleKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkImportSemaphoreFdKHR = PFN_vkImportSemaphoreFdKHR( vkGetInstanceProcAddr( instance, "vkImportSemaphoreFdKHR" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkImportSemaphoreWin32HandleKHR = PFN_vkImportSemaphoreWin32HandleKHR( vkGetInstanceProcAddr( instance, "vkImportSemaphoreWin32HandleKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkInitializePerformanceApiINTEL = PFN_vkInitializePerformanceApiINTEL( vkGetInstanceProcAddr( instance, "vkInitializePerformanceApiINTEL" ) );
+ vkInvalidateMappedMemoryRanges = PFN_vkInvalidateMappedMemoryRanges( vkGetInstanceProcAddr( instance, "vkInvalidateMappedMemoryRanges" ) );
+ vkMapMemory = PFN_vkMapMemory( vkGetInstanceProcAddr( instance, "vkMapMemory" ) );
+ vkMergePipelineCaches = PFN_vkMergePipelineCaches( vkGetInstanceProcAddr( instance, "vkMergePipelineCaches" ) );
+ vkMergeValidationCachesEXT = PFN_vkMergeValidationCachesEXT( vkGetInstanceProcAddr( instance, "vkMergeValidationCachesEXT" ) );
+ vkRegisterDeviceEventEXT = PFN_vkRegisterDeviceEventEXT( vkGetInstanceProcAddr( instance, "vkRegisterDeviceEventEXT" ) );
+ vkRegisterDisplayEventEXT = PFN_vkRegisterDisplayEventEXT( vkGetInstanceProcAddr( instance, "vkRegisterDisplayEventEXT" ) );
+ vkRegisterObjectsNVX = PFN_vkRegisterObjectsNVX( vkGetInstanceProcAddr( instance, "vkRegisterObjectsNVX" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkReleaseFullScreenExclusiveModeEXT = PFN_vkReleaseFullScreenExclusiveModeEXT( vkGetInstanceProcAddr( instance, "vkReleaseFullScreenExclusiveModeEXT" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkReleasePerformanceConfigurationINTEL = PFN_vkReleasePerformanceConfigurationINTEL( vkGetInstanceProcAddr( instance, "vkReleasePerformanceConfigurationINTEL" ) );
+ vkReleaseProfilingLockKHR = PFN_vkReleaseProfilingLockKHR( vkGetInstanceProcAddr( instance, "vkReleaseProfilingLockKHR" ) );
+ vkResetCommandPool = PFN_vkResetCommandPool( vkGetInstanceProcAddr( instance, "vkResetCommandPool" ) );
+ vkResetDescriptorPool = PFN_vkResetDescriptorPool( vkGetInstanceProcAddr( instance, "vkResetDescriptorPool" ) );
+ vkResetEvent = PFN_vkResetEvent( vkGetInstanceProcAddr( instance, "vkResetEvent" ) );
+ vkResetFences = PFN_vkResetFences( vkGetInstanceProcAddr( instance, "vkResetFences" ) );
+ vkResetQueryPool = PFN_vkResetQueryPool( vkGetInstanceProcAddr( instance, "vkResetQueryPool" ) );
+ vkResetQueryPoolEXT = PFN_vkResetQueryPoolEXT( vkGetInstanceProcAddr( instance, "vkResetQueryPoolEXT" ) );
+ vkSetDebugUtilsObjectNameEXT = PFN_vkSetDebugUtilsObjectNameEXT( vkGetInstanceProcAddr( instance, "vkSetDebugUtilsObjectNameEXT" ) );
+ vkSetDebugUtilsObjectTagEXT = PFN_vkSetDebugUtilsObjectTagEXT( vkGetInstanceProcAddr( instance, "vkSetDebugUtilsObjectTagEXT" ) );
+ vkSetEvent = PFN_vkSetEvent( vkGetInstanceProcAddr( instance, "vkSetEvent" ) );
+ vkSetHdrMetadataEXT = PFN_vkSetHdrMetadataEXT( vkGetInstanceProcAddr( instance, "vkSetHdrMetadataEXT" ) );
+ vkSetLocalDimmingAMD = PFN_vkSetLocalDimmingAMD( vkGetInstanceProcAddr( instance, "vkSetLocalDimmingAMD" ) );
+ vkSignalSemaphore = PFN_vkSignalSemaphore( vkGetInstanceProcAddr( instance, "vkSignalSemaphore" ) );
+ vkSignalSemaphoreKHR = PFN_vkSignalSemaphoreKHR( vkGetInstanceProcAddr( instance, "vkSignalSemaphoreKHR" ) );
+ vkTrimCommandPool = PFN_vkTrimCommandPool( vkGetInstanceProcAddr( instance, "vkTrimCommandPool" ) );
+ vkTrimCommandPoolKHR = PFN_vkTrimCommandPoolKHR( vkGetInstanceProcAddr( instance, "vkTrimCommandPoolKHR" ) );
+ vkUninitializePerformanceApiINTEL = PFN_vkUninitializePerformanceApiINTEL( vkGetInstanceProcAddr( instance, "vkUninitializePerformanceApiINTEL" ) );
+ vkUnmapMemory = PFN_vkUnmapMemory( vkGetInstanceProcAddr( instance, "vkUnmapMemory" ) );
+ vkUnregisterObjectsNVX = PFN_vkUnregisterObjectsNVX( vkGetInstanceProcAddr( instance, "vkUnregisterObjectsNVX" ) );
+ vkUpdateDescriptorSetWithTemplate = PFN_vkUpdateDescriptorSetWithTemplate( vkGetInstanceProcAddr( instance, "vkUpdateDescriptorSetWithTemplate" ) );
+ vkUpdateDescriptorSetWithTemplateKHR = PFN_vkUpdateDescriptorSetWithTemplateKHR( vkGetInstanceProcAddr( instance, "vkUpdateDescriptorSetWithTemplateKHR" ) );
+ vkUpdateDescriptorSets = PFN_vkUpdateDescriptorSets( vkGetInstanceProcAddr( instance, "vkUpdateDescriptorSets" ) );
+ vkWaitForFences = PFN_vkWaitForFences( vkGetInstanceProcAddr( instance, "vkWaitForFences" ) );
+ vkWaitSemaphores = PFN_vkWaitSemaphores( vkGetInstanceProcAddr( instance, "vkWaitSemaphores" ) );
+ vkWaitSemaphoresKHR = PFN_vkWaitSemaphoresKHR( vkGetInstanceProcAddr( instance, "vkWaitSemaphoresKHR" ) );
+ vkGetQueueCheckpointDataNV = PFN_vkGetQueueCheckpointDataNV( vkGetInstanceProcAddr( instance, "vkGetQueueCheckpointDataNV" ) );
+ vkQueueBeginDebugUtilsLabelEXT = PFN_vkQueueBeginDebugUtilsLabelEXT( vkGetInstanceProcAddr( instance, "vkQueueBeginDebugUtilsLabelEXT" ) );
+ vkQueueBindSparse = PFN_vkQueueBindSparse( vkGetInstanceProcAddr( instance, "vkQueueBindSparse" ) );
+ vkQueueEndDebugUtilsLabelEXT = PFN_vkQueueEndDebugUtilsLabelEXT( vkGetInstanceProcAddr( instance, "vkQueueEndDebugUtilsLabelEXT" ) );
+ vkQueueInsertDebugUtilsLabelEXT = PFN_vkQueueInsertDebugUtilsLabelEXT( vkGetInstanceProcAddr( instance, "vkQueueInsertDebugUtilsLabelEXT" ) );
+ vkQueuePresentKHR = PFN_vkQueuePresentKHR( vkGetInstanceProcAddr( instance, "vkQueuePresentKHR" ) );
+ vkQueueSetPerformanceConfigurationINTEL = PFN_vkQueueSetPerformanceConfigurationINTEL( vkGetInstanceProcAddr( instance, "vkQueueSetPerformanceConfigurationINTEL" ) );
+ vkQueueSubmit = PFN_vkQueueSubmit( vkGetInstanceProcAddr( instance, "vkQueueSubmit" ) );
+ vkQueueWaitIdle = PFN_vkQueueWaitIdle( vkGetInstanceProcAddr( instance, "vkQueueWaitIdle" ) );
+ }
+
+ void init( VULKAN_HPP_NAMESPACE::Device deviceCpp ) VULKAN_HPP_NOEXCEPT
+ {
+ VkDevice device = static_cast<VkDevice>(deviceCpp);
+ vkBeginCommandBuffer = PFN_vkBeginCommandBuffer( vkGetDeviceProcAddr( device, "vkBeginCommandBuffer" ) );
+ vkCmdBeginConditionalRenderingEXT = PFN_vkCmdBeginConditionalRenderingEXT( vkGetDeviceProcAddr( device, "vkCmdBeginConditionalRenderingEXT" ) );
+ vkCmdBeginDebugUtilsLabelEXT = PFN_vkCmdBeginDebugUtilsLabelEXT( vkGetDeviceProcAddr( device, "vkCmdBeginDebugUtilsLabelEXT" ) );
+ vkCmdBeginQuery = PFN_vkCmdBeginQuery( vkGetDeviceProcAddr( device, "vkCmdBeginQuery" ) );
+ vkCmdBeginQueryIndexedEXT = PFN_vkCmdBeginQueryIndexedEXT( vkGetDeviceProcAddr( device, "vkCmdBeginQueryIndexedEXT" ) );
+ vkCmdBeginRenderPass = PFN_vkCmdBeginRenderPass( vkGetDeviceProcAddr( device, "vkCmdBeginRenderPass" ) );
+ vkCmdBeginRenderPass2 = PFN_vkCmdBeginRenderPass2( vkGetDeviceProcAddr( device, "vkCmdBeginRenderPass2" ) );
+ vkCmdBeginRenderPass2KHR = PFN_vkCmdBeginRenderPass2KHR( vkGetDeviceProcAddr( device, "vkCmdBeginRenderPass2KHR" ) );
+ vkCmdBeginTransformFeedbackEXT = PFN_vkCmdBeginTransformFeedbackEXT( vkGetDeviceProcAddr( device, "vkCmdBeginTransformFeedbackEXT" ) );
+ vkCmdBindDescriptorSets = PFN_vkCmdBindDescriptorSets( vkGetDeviceProcAddr( device, "vkCmdBindDescriptorSets" ) );
+ vkCmdBindIndexBuffer = PFN_vkCmdBindIndexBuffer( vkGetDeviceProcAddr( device, "vkCmdBindIndexBuffer" ) );
+ vkCmdBindPipeline = PFN_vkCmdBindPipeline( vkGetDeviceProcAddr( device, "vkCmdBindPipeline" ) );
+ vkCmdBindShadingRateImageNV = PFN_vkCmdBindShadingRateImageNV( vkGetDeviceProcAddr( device, "vkCmdBindShadingRateImageNV" ) );
+ vkCmdBindTransformFeedbackBuffersEXT = PFN_vkCmdBindTransformFeedbackBuffersEXT( vkGetDeviceProcAddr( device, "vkCmdBindTransformFeedbackBuffersEXT" ) );
+ vkCmdBindVertexBuffers = PFN_vkCmdBindVertexBuffers( vkGetDeviceProcAddr( device, "vkCmdBindVertexBuffers" ) );
+ vkCmdBlitImage = PFN_vkCmdBlitImage( vkGetDeviceProcAddr( device, "vkCmdBlitImage" ) );
+ vkCmdBuildAccelerationStructureNV = PFN_vkCmdBuildAccelerationStructureNV( vkGetDeviceProcAddr( device, "vkCmdBuildAccelerationStructureNV" ) );
+ vkCmdClearAttachments = PFN_vkCmdClearAttachments( vkGetDeviceProcAddr( device, "vkCmdClearAttachments" ) );
+ vkCmdClearColorImage = PFN_vkCmdClearColorImage( vkGetDeviceProcAddr( device, "vkCmdClearColorImage" ) );
+ vkCmdClearDepthStencilImage = PFN_vkCmdClearDepthStencilImage( vkGetDeviceProcAddr( device, "vkCmdClearDepthStencilImage" ) );
+ vkCmdCopyAccelerationStructureNV = PFN_vkCmdCopyAccelerationStructureNV( vkGetDeviceProcAddr( device, "vkCmdCopyAccelerationStructureNV" ) );
+ vkCmdCopyBuffer = PFN_vkCmdCopyBuffer( vkGetDeviceProcAddr( device, "vkCmdCopyBuffer" ) );
+ vkCmdCopyBufferToImage = PFN_vkCmdCopyBufferToImage( vkGetDeviceProcAddr( device, "vkCmdCopyBufferToImage" ) );
+ vkCmdCopyImage = PFN_vkCmdCopyImage( vkGetDeviceProcAddr( device, "vkCmdCopyImage" ) );
+ vkCmdCopyImageToBuffer = PFN_vkCmdCopyImageToBuffer( vkGetDeviceProcAddr( device, "vkCmdCopyImageToBuffer" ) );
+ vkCmdCopyQueryPoolResults = PFN_vkCmdCopyQueryPoolResults( vkGetDeviceProcAddr( device, "vkCmdCopyQueryPoolResults" ) );
+ vkCmdDebugMarkerBeginEXT = PFN_vkCmdDebugMarkerBeginEXT( vkGetDeviceProcAddr( device, "vkCmdDebugMarkerBeginEXT" ) );
+ vkCmdDebugMarkerEndEXT = PFN_vkCmdDebugMarkerEndEXT( vkGetDeviceProcAddr( device, "vkCmdDebugMarkerEndEXT" ) );
+ vkCmdDebugMarkerInsertEXT = PFN_vkCmdDebugMarkerInsertEXT( vkGetDeviceProcAddr( device, "vkCmdDebugMarkerInsertEXT" ) );
+ vkCmdDispatch = PFN_vkCmdDispatch( vkGetDeviceProcAddr( device, "vkCmdDispatch" ) );
+ vkCmdDispatchBase = PFN_vkCmdDispatchBase( vkGetDeviceProcAddr( device, "vkCmdDispatchBase" ) );
+ vkCmdDispatchBaseKHR = PFN_vkCmdDispatchBaseKHR( vkGetDeviceProcAddr( device, "vkCmdDispatchBaseKHR" ) );
+ vkCmdDispatchIndirect = PFN_vkCmdDispatchIndirect( vkGetDeviceProcAddr( device, "vkCmdDispatchIndirect" ) );
+ vkCmdDraw = PFN_vkCmdDraw( vkGetDeviceProcAddr( device, "vkCmdDraw" ) );
+ vkCmdDrawIndexed = PFN_vkCmdDrawIndexed( vkGetDeviceProcAddr( device, "vkCmdDrawIndexed" ) );
+ vkCmdDrawIndexedIndirect = PFN_vkCmdDrawIndexedIndirect( vkGetDeviceProcAddr( device, "vkCmdDrawIndexedIndirect" ) );
+ vkCmdDrawIndexedIndirectCount = PFN_vkCmdDrawIndexedIndirectCount( vkGetDeviceProcAddr( device, "vkCmdDrawIndexedIndirectCount" ) );
+ vkCmdDrawIndexedIndirectCountAMD = PFN_vkCmdDrawIndexedIndirectCountAMD( vkGetDeviceProcAddr( device, "vkCmdDrawIndexedIndirectCountAMD" ) );
+ vkCmdDrawIndexedIndirectCountKHR = PFN_vkCmdDrawIndexedIndirectCountKHR( vkGetDeviceProcAddr( device, "vkCmdDrawIndexedIndirectCountKHR" ) );
+ vkCmdDrawIndirect = PFN_vkCmdDrawIndirect( vkGetDeviceProcAddr( device, "vkCmdDrawIndirect" ) );
+ vkCmdDrawIndirectByteCountEXT = PFN_vkCmdDrawIndirectByteCountEXT( vkGetDeviceProcAddr( device, "vkCmdDrawIndirectByteCountEXT" ) );
+ vkCmdDrawIndirectCount = PFN_vkCmdDrawIndirectCount( vkGetDeviceProcAddr( device, "vkCmdDrawIndirectCount" ) );
+ vkCmdDrawIndirectCountAMD = PFN_vkCmdDrawIndirectCountAMD( vkGetDeviceProcAddr( device, "vkCmdDrawIndirectCountAMD" ) );
+ vkCmdDrawIndirectCountKHR = PFN_vkCmdDrawIndirectCountKHR( vkGetDeviceProcAddr( device, "vkCmdDrawIndirectCountKHR" ) );
+ vkCmdDrawMeshTasksIndirectCountNV = PFN_vkCmdDrawMeshTasksIndirectCountNV( vkGetDeviceProcAddr( device, "vkCmdDrawMeshTasksIndirectCountNV" ) );
+ vkCmdDrawMeshTasksIndirectNV = PFN_vkCmdDrawMeshTasksIndirectNV( vkGetDeviceProcAddr( device, "vkCmdDrawMeshTasksIndirectNV" ) );
+ vkCmdDrawMeshTasksNV = PFN_vkCmdDrawMeshTasksNV( vkGetDeviceProcAddr( device, "vkCmdDrawMeshTasksNV" ) );
+ vkCmdEndConditionalRenderingEXT = PFN_vkCmdEndConditionalRenderingEXT( vkGetDeviceProcAddr( device, "vkCmdEndConditionalRenderingEXT" ) );
+ vkCmdEndDebugUtilsLabelEXT = PFN_vkCmdEndDebugUtilsLabelEXT( vkGetDeviceProcAddr( device, "vkCmdEndDebugUtilsLabelEXT" ) );
+ vkCmdEndQuery = PFN_vkCmdEndQuery( vkGetDeviceProcAddr( device, "vkCmdEndQuery" ) );
+ vkCmdEndQueryIndexedEXT = PFN_vkCmdEndQueryIndexedEXT( vkGetDeviceProcAddr( device, "vkCmdEndQueryIndexedEXT" ) );
+ vkCmdEndRenderPass = PFN_vkCmdEndRenderPass( vkGetDeviceProcAddr( device, "vkCmdEndRenderPass" ) );
+ vkCmdEndRenderPass2 = PFN_vkCmdEndRenderPass2( vkGetDeviceProcAddr( device, "vkCmdEndRenderPass2" ) );
+ vkCmdEndRenderPass2KHR = PFN_vkCmdEndRenderPass2KHR( vkGetDeviceProcAddr( device, "vkCmdEndRenderPass2KHR" ) );
+ vkCmdEndTransformFeedbackEXT = PFN_vkCmdEndTransformFeedbackEXT( vkGetDeviceProcAddr( device, "vkCmdEndTransformFeedbackEXT" ) );
+ vkCmdExecuteCommands = PFN_vkCmdExecuteCommands( vkGetDeviceProcAddr( device, "vkCmdExecuteCommands" ) );
+ vkCmdFillBuffer = PFN_vkCmdFillBuffer( vkGetDeviceProcAddr( device, "vkCmdFillBuffer" ) );
+ vkCmdInsertDebugUtilsLabelEXT = PFN_vkCmdInsertDebugUtilsLabelEXT( vkGetDeviceProcAddr( device, "vkCmdInsertDebugUtilsLabelEXT" ) );
+ vkCmdNextSubpass = PFN_vkCmdNextSubpass( vkGetDeviceProcAddr( device, "vkCmdNextSubpass" ) );
+ vkCmdNextSubpass2 = PFN_vkCmdNextSubpass2( vkGetDeviceProcAddr( device, "vkCmdNextSubpass2" ) );
+ vkCmdNextSubpass2KHR = PFN_vkCmdNextSubpass2KHR( vkGetDeviceProcAddr( device, "vkCmdNextSubpass2KHR" ) );
+ vkCmdPipelineBarrier = PFN_vkCmdPipelineBarrier( vkGetDeviceProcAddr( device, "vkCmdPipelineBarrier" ) );
+ vkCmdProcessCommandsNVX = PFN_vkCmdProcessCommandsNVX( vkGetDeviceProcAddr( device, "vkCmdProcessCommandsNVX" ) );
+ vkCmdPushConstants = PFN_vkCmdPushConstants( vkGetDeviceProcAddr( device, "vkCmdPushConstants" ) );
+ vkCmdPushDescriptorSetKHR = PFN_vkCmdPushDescriptorSetKHR( vkGetDeviceProcAddr( device, "vkCmdPushDescriptorSetKHR" ) );
+ vkCmdPushDescriptorSetWithTemplateKHR = PFN_vkCmdPushDescriptorSetWithTemplateKHR( vkGetDeviceProcAddr( device, "vkCmdPushDescriptorSetWithTemplateKHR" ) );
+ vkCmdReserveSpaceForCommandsNVX = PFN_vkCmdReserveSpaceForCommandsNVX( vkGetDeviceProcAddr( device, "vkCmdReserveSpaceForCommandsNVX" ) );
+ vkCmdResetEvent = PFN_vkCmdResetEvent( vkGetDeviceProcAddr( device, "vkCmdResetEvent" ) );
+ vkCmdResetQueryPool = PFN_vkCmdResetQueryPool( vkGetDeviceProcAddr( device, "vkCmdResetQueryPool" ) );
+ vkCmdResolveImage = PFN_vkCmdResolveImage( vkGetDeviceProcAddr( device, "vkCmdResolveImage" ) );
+ vkCmdSetBlendConstants = PFN_vkCmdSetBlendConstants( vkGetDeviceProcAddr( device, "vkCmdSetBlendConstants" ) );
+ vkCmdSetCheckpointNV = PFN_vkCmdSetCheckpointNV( vkGetDeviceProcAddr( device, "vkCmdSetCheckpointNV" ) );
+ vkCmdSetCoarseSampleOrderNV = PFN_vkCmdSetCoarseSampleOrderNV( vkGetDeviceProcAddr( device, "vkCmdSetCoarseSampleOrderNV" ) );
+ vkCmdSetDepthBias = PFN_vkCmdSetDepthBias( vkGetDeviceProcAddr( device, "vkCmdSetDepthBias" ) );
+ vkCmdSetDepthBounds = PFN_vkCmdSetDepthBounds( vkGetDeviceProcAddr( device, "vkCmdSetDepthBounds" ) );
+ vkCmdSetDeviceMask = PFN_vkCmdSetDeviceMask( vkGetDeviceProcAddr( device, "vkCmdSetDeviceMask" ) );
+ vkCmdSetDeviceMaskKHR = PFN_vkCmdSetDeviceMaskKHR( vkGetDeviceProcAddr( device, "vkCmdSetDeviceMaskKHR" ) );
+ vkCmdSetDiscardRectangleEXT = PFN_vkCmdSetDiscardRectangleEXT( vkGetDeviceProcAddr( device, "vkCmdSetDiscardRectangleEXT" ) );
+ vkCmdSetEvent = PFN_vkCmdSetEvent( vkGetDeviceProcAddr( device, "vkCmdSetEvent" ) );
+ vkCmdSetExclusiveScissorNV = PFN_vkCmdSetExclusiveScissorNV( vkGetDeviceProcAddr( device, "vkCmdSetExclusiveScissorNV" ) );
+ vkCmdSetLineStippleEXT = PFN_vkCmdSetLineStippleEXT( vkGetDeviceProcAddr( device, "vkCmdSetLineStippleEXT" ) );
+ vkCmdSetLineWidth = PFN_vkCmdSetLineWidth( vkGetDeviceProcAddr( device, "vkCmdSetLineWidth" ) );
+ vkCmdSetPerformanceMarkerINTEL = PFN_vkCmdSetPerformanceMarkerINTEL( vkGetDeviceProcAddr( device, "vkCmdSetPerformanceMarkerINTEL" ) );
+ vkCmdSetPerformanceOverrideINTEL = PFN_vkCmdSetPerformanceOverrideINTEL( vkGetDeviceProcAddr( device, "vkCmdSetPerformanceOverrideINTEL" ) );
+ vkCmdSetPerformanceStreamMarkerINTEL = PFN_vkCmdSetPerformanceStreamMarkerINTEL( vkGetDeviceProcAddr( device, "vkCmdSetPerformanceStreamMarkerINTEL" ) );
+ vkCmdSetSampleLocationsEXT = PFN_vkCmdSetSampleLocationsEXT( vkGetDeviceProcAddr( device, "vkCmdSetSampleLocationsEXT" ) );
+ vkCmdSetScissor = PFN_vkCmdSetScissor( vkGetDeviceProcAddr( device, "vkCmdSetScissor" ) );
+ vkCmdSetStencilCompareMask = PFN_vkCmdSetStencilCompareMask( vkGetDeviceProcAddr( device, "vkCmdSetStencilCompareMask" ) );
+ vkCmdSetStencilReference = PFN_vkCmdSetStencilReference( vkGetDeviceProcAddr( device, "vkCmdSetStencilReference" ) );
+ vkCmdSetStencilWriteMask = PFN_vkCmdSetStencilWriteMask( vkGetDeviceProcAddr( device, "vkCmdSetStencilWriteMask" ) );
+ vkCmdSetViewport = PFN_vkCmdSetViewport( vkGetDeviceProcAddr( device, "vkCmdSetViewport" ) );
+ vkCmdSetViewportShadingRatePaletteNV = PFN_vkCmdSetViewportShadingRatePaletteNV( vkGetDeviceProcAddr( device, "vkCmdSetViewportShadingRatePaletteNV" ) );
+ vkCmdSetViewportWScalingNV = PFN_vkCmdSetViewportWScalingNV( vkGetDeviceProcAddr( device, "vkCmdSetViewportWScalingNV" ) );
+ vkCmdTraceRaysNV = PFN_vkCmdTraceRaysNV( vkGetDeviceProcAddr( device, "vkCmdTraceRaysNV" ) );
+ vkCmdUpdateBuffer = PFN_vkCmdUpdateBuffer( vkGetDeviceProcAddr( device, "vkCmdUpdateBuffer" ) );
+ vkCmdWaitEvents = PFN_vkCmdWaitEvents( vkGetDeviceProcAddr( device, "vkCmdWaitEvents" ) );
+ vkCmdWriteAccelerationStructuresPropertiesNV = PFN_vkCmdWriteAccelerationStructuresPropertiesNV( vkGetDeviceProcAddr( device, "vkCmdWriteAccelerationStructuresPropertiesNV" ) );
+ vkCmdWriteBufferMarkerAMD = PFN_vkCmdWriteBufferMarkerAMD( vkGetDeviceProcAddr( device, "vkCmdWriteBufferMarkerAMD" ) );
+ vkCmdWriteTimestamp = PFN_vkCmdWriteTimestamp( vkGetDeviceProcAddr( device, "vkCmdWriteTimestamp" ) );
+ vkEndCommandBuffer = PFN_vkEndCommandBuffer( vkGetDeviceProcAddr( device, "vkEndCommandBuffer" ) );
+ vkResetCommandBuffer = PFN_vkResetCommandBuffer( vkGetDeviceProcAddr( device, "vkResetCommandBuffer" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkAcquireFullScreenExclusiveModeEXT = PFN_vkAcquireFullScreenExclusiveModeEXT( vkGetDeviceProcAddr( device, "vkAcquireFullScreenExclusiveModeEXT" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkAcquireNextImage2KHR = PFN_vkAcquireNextImage2KHR( vkGetDeviceProcAddr( device, "vkAcquireNextImage2KHR" ) );
+ vkAcquireNextImageKHR = PFN_vkAcquireNextImageKHR( vkGetDeviceProcAddr( device, "vkAcquireNextImageKHR" ) );
+ vkAcquirePerformanceConfigurationINTEL = PFN_vkAcquirePerformanceConfigurationINTEL( vkGetDeviceProcAddr( device, "vkAcquirePerformanceConfigurationINTEL" ) );
+ vkAcquireProfilingLockKHR = PFN_vkAcquireProfilingLockKHR( vkGetDeviceProcAddr( device, "vkAcquireProfilingLockKHR" ) );
+ vkAllocateCommandBuffers = PFN_vkAllocateCommandBuffers( vkGetDeviceProcAddr( device, "vkAllocateCommandBuffers" ) );
+ vkAllocateDescriptorSets = PFN_vkAllocateDescriptorSets( vkGetDeviceProcAddr( device, "vkAllocateDescriptorSets" ) );
+ vkAllocateMemory = PFN_vkAllocateMemory( vkGetDeviceProcAddr( device, "vkAllocateMemory" ) );
+ vkBindAccelerationStructureMemoryNV = PFN_vkBindAccelerationStructureMemoryNV( vkGetDeviceProcAddr( device, "vkBindAccelerationStructureMemoryNV" ) );
+ vkBindBufferMemory = PFN_vkBindBufferMemory( vkGetDeviceProcAddr( device, "vkBindBufferMemory" ) );
+ vkBindBufferMemory2 = PFN_vkBindBufferMemory2( vkGetDeviceProcAddr( device, "vkBindBufferMemory2" ) );
+ vkBindBufferMemory2KHR = PFN_vkBindBufferMemory2KHR( vkGetDeviceProcAddr( device, "vkBindBufferMemory2KHR" ) );
+ vkBindImageMemory = PFN_vkBindImageMemory( vkGetDeviceProcAddr( device, "vkBindImageMemory" ) );
+ vkBindImageMemory2 = PFN_vkBindImageMemory2( vkGetDeviceProcAddr( device, "vkBindImageMemory2" ) );
+ vkBindImageMemory2KHR = PFN_vkBindImageMemory2KHR( vkGetDeviceProcAddr( device, "vkBindImageMemory2KHR" ) );
+ vkCompileDeferredNV = PFN_vkCompileDeferredNV( vkGetDeviceProcAddr( device, "vkCompileDeferredNV" ) );
+ vkCreateAccelerationStructureNV = PFN_vkCreateAccelerationStructureNV( vkGetDeviceProcAddr( device, "vkCreateAccelerationStructureNV" ) );
+ vkCreateBuffer = PFN_vkCreateBuffer( vkGetDeviceProcAddr( device, "vkCreateBuffer" ) );
+ vkCreateBufferView = PFN_vkCreateBufferView( vkGetDeviceProcAddr( device, "vkCreateBufferView" ) );
+ vkCreateCommandPool = PFN_vkCreateCommandPool( vkGetDeviceProcAddr( device, "vkCreateCommandPool" ) );
+ vkCreateComputePipelines = PFN_vkCreateComputePipelines( vkGetDeviceProcAddr( device, "vkCreateComputePipelines" ) );
+ vkCreateDescriptorPool = PFN_vkCreateDescriptorPool( vkGetDeviceProcAddr( device, "vkCreateDescriptorPool" ) );
+ vkCreateDescriptorSetLayout = PFN_vkCreateDescriptorSetLayout( vkGetDeviceProcAddr( device, "vkCreateDescriptorSetLayout" ) );
+ vkCreateDescriptorUpdateTemplate = PFN_vkCreateDescriptorUpdateTemplate( vkGetDeviceProcAddr( device, "vkCreateDescriptorUpdateTemplate" ) );
+ vkCreateDescriptorUpdateTemplateKHR = PFN_vkCreateDescriptorUpdateTemplateKHR( vkGetDeviceProcAddr( device, "vkCreateDescriptorUpdateTemplateKHR" ) );
+ vkCreateEvent = PFN_vkCreateEvent( vkGetDeviceProcAddr( device, "vkCreateEvent" ) );
+ vkCreateFence = PFN_vkCreateFence( vkGetDeviceProcAddr( device, "vkCreateFence" ) );
+ vkCreateFramebuffer = PFN_vkCreateFramebuffer( vkGetDeviceProcAddr( device, "vkCreateFramebuffer" ) );
+ vkCreateGraphicsPipelines = PFN_vkCreateGraphicsPipelines( vkGetDeviceProcAddr( device, "vkCreateGraphicsPipelines" ) );
+ vkCreateImage = PFN_vkCreateImage( vkGetDeviceProcAddr( device, "vkCreateImage" ) );
+ vkCreateImageView = PFN_vkCreateImageView( vkGetDeviceProcAddr( device, "vkCreateImageView" ) );
+ vkCreateIndirectCommandsLayoutNVX = PFN_vkCreateIndirectCommandsLayoutNVX( vkGetDeviceProcAddr( device, "vkCreateIndirectCommandsLayoutNVX" ) );
+ vkCreateObjectTableNVX = PFN_vkCreateObjectTableNVX( vkGetDeviceProcAddr( device, "vkCreateObjectTableNVX" ) );
+ vkCreatePipelineCache = PFN_vkCreatePipelineCache( vkGetDeviceProcAddr( device, "vkCreatePipelineCache" ) );
+ vkCreatePipelineLayout = PFN_vkCreatePipelineLayout( vkGetDeviceProcAddr( device, "vkCreatePipelineLayout" ) );
+ vkCreateQueryPool = PFN_vkCreateQueryPool( vkGetDeviceProcAddr( device, "vkCreateQueryPool" ) );
+ vkCreateRayTracingPipelinesNV = PFN_vkCreateRayTracingPipelinesNV( vkGetDeviceProcAddr( device, "vkCreateRayTracingPipelinesNV" ) );
+ vkCreateRenderPass = PFN_vkCreateRenderPass( vkGetDeviceProcAddr( device, "vkCreateRenderPass" ) );
+ vkCreateRenderPass2 = PFN_vkCreateRenderPass2( vkGetDeviceProcAddr( device, "vkCreateRenderPass2" ) );
+ vkCreateRenderPass2KHR = PFN_vkCreateRenderPass2KHR( vkGetDeviceProcAddr( device, "vkCreateRenderPass2KHR" ) );
+ vkCreateSampler = PFN_vkCreateSampler( vkGetDeviceProcAddr( device, "vkCreateSampler" ) );
+ vkCreateSamplerYcbcrConversion = PFN_vkCreateSamplerYcbcrConversion( vkGetDeviceProcAddr( device, "vkCreateSamplerYcbcrConversion" ) );
+ vkCreateSamplerYcbcrConversionKHR = PFN_vkCreateSamplerYcbcrConversionKHR( vkGetDeviceProcAddr( device, "vkCreateSamplerYcbcrConversionKHR" ) );
+ vkCreateSemaphore = PFN_vkCreateSemaphore( vkGetDeviceProcAddr( device, "vkCreateSemaphore" ) );
+ vkCreateShaderModule = PFN_vkCreateShaderModule( vkGetDeviceProcAddr( device, "vkCreateShaderModule" ) );
+ vkCreateSharedSwapchainsKHR = PFN_vkCreateSharedSwapchainsKHR( vkGetDeviceProcAddr( device, "vkCreateSharedSwapchainsKHR" ) );
+ vkCreateSwapchainKHR = PFN_vkCreateSwapchainKHR( vkGetDeviceProcAddr( device, "vkCreateSwapchainKHR" ) );
+ vkCreateValidationCacheEXT = PFN_vkCreateValidationCacheEXT( vkGetDeviceProcAddr( device, "vkCreateValidationCacheEXT" ) );
+ vkDebugMarkerSetObjectNameEXT = PFN_vkDebugMarkerSetObjectNameEXT( vkGetDeviceProcAddr( device, "vkDebugMarkerSetObjectNameEXT" ) );
+ vkDebugMarkerSetObjectTagEXT = PFN_vkDebugMarkerSetObjectTagEXT( vkGetDeviceProcAddr( device, "vkDebugMarkerSetObjectTagEXT" ) );
+ vkDestroyAccelerationStructureNV = PFN_vkDestroyAccelerationStructureNV( vkGetDeviceProcAddr( device, "vkDestroyAccelerationStructureNV" ) );
+ vkDestroyBuffer = PFN_vkDestroyBuffer( vkGetDeviceProcAddr( device, "vkDestroyBuffer" ) );
+ vkDestroyBufferView = PFN_vkDestroyBufferView( vkGetDeviceProcAddr( device, "vkDestroyBufferView" ) );
+ vkDestroyCommandPool = PFN_vkDestroyCommandPool( vkGetDeviceProcAddr( device, "vkDestroyCommandPool" ) );
+ vkDestroyDescriptorPool = PFN_vkDestroyDescriptorPool( vkGetDeviceProcAddr( device, "vkDestroyDescriptorPool" ) );
+ vkDestroyDescriptorSetLayout = PFN_vkDestroyDescriptorSetLayout( vkGetDeviceProcAddr( device, "vkDestroyDescriptorSetLayout" ) );
+ vkDestroyDescriptorUpdateTemplate = PFN_vkDestroyDescriptorUpdateTemplate( vkGetDeviceProcAddr( device, "vkDestroyDescriptorUpdateTemplate" ) );
+ vkDestroyDescriptorUpdateTemplateKHR = PFN_vkDestroyDescriptorUpdateTemplateKHR( vkGetDeviceProcAddr( device, "vkDestroyDescriptorUpdateTemplateKHR" ) );
+ vkDestroyDevice = PFN_vkDestroyDevice( vkGetDeviceProcAddr( device, "vkDestroyDevice" ) );
+ vkDestroyEvent = PFN_vkDestroyEvent( vkGetDeviceProcAddr( device, "vkDestroyEvent" ) );
+ vkDestroyFence = PFN_vkDestroyFence( vkGetDeviceProcAddr( device, "vkDestroyFence" ) );
+ vkDestroyFramebuffer = PFN_vkDestroyFramebuffer( vkGetDeviceProcAddr( device, "vkDestroyFramebuffer" ) );
+ vkDestroyImage = PFN_vkDestroyImage( vkGetDeviceProcAddr( device, "vkDestroyImage" ) );
+ vkDestroyImageView = PFN_vkDestroyImageView( vkGetDeviceProcAddr( device, "vkDestroyImageView" ) );
+ vkDestroyIndirectCommandsLayoutNVX = PFN_vkDestroyIndirectCommandsLayoutNVX( vkGetDeviceProcAddr( device, "vkDestroyIndirectCommandsLayoutNVX" ) );
+ vkDestroyObjectTableNVX = PFN_vkDestroyObjectTableNVX( vkGetDeviceProcAddr( device, "vkDestroyObjectTableNVX" ) );
+ vkDestroyPipeline = PFN_vkDestroyPipeline( vkGetDeviceProcAddr( device, "vkDestroyPipeline" ) );
+ vkDestroyPipelineCache = PFN_vkDestroyPipelineCache( vkGetDeviceProcAddr( device, "vkDestroyPipelineCache" ) );
+ vkDestroyPipelineLayout = PFN_vkDestroyPipelineLayout( vkGetDeviceProcAddr( device, "vkDestroyPipelineLayout" ) );
+ vkDestroyQueryPool = PFN_vkDestroyQueryPool( vkGetDeviceProcAddr( device, "vkDestroyQueryPool" ) );
+ vkDestroyRenderPass = PFN_vkDestroyRenderPass( vkGetDeviceProcAddr( device, "vkDestroyRenderPass" ) );
+ vkDestroySampler = PFN_vkDestroySampler( vkGetDeviceProcAddr( device, "vkDestroySampler" ) );
+ vkDestroySamplerYcbcrConversion = PFN_vkDestroySamplerYcbcrConversion( vkGetDeviceProcAddr( device, "vkDestroySamplerYcbcrConversion" ) );
+ vkDestroySamplerYcbcrConversionKHR = PFN_vkDestroySamplerYcbcrConversionKHR( vkGetDeviceProcAddr( device, "vkDestroySamplerYcbcrConversionKHR" ) );
+ vkDestroySemaphore = PFN_vkDestroySemaphore( vkGetDeviceProcAddr( device, "vkDestroySemaphore" ) );
+ vkDestroyShaderModule = PFN_vkDestroyShaderModule( vkGetDeviceProcAddr( device, "vkDestroyShaderModule" ) );
+ vkDestroySwapchainKHR = PFN_vkDestroySwapchainKHR( vkGetDeviceProcAddr( device, "vkDestroySwapchainKHR" ) );
+ vkDestroyValidationCacheEXT = PFN_vkDestroyValidationCacheEXT( vkGetDeviceProcAddr( device, "vkDestroyValidationCacheEXT" ) );
+ vkDeviceWaitIdle = PFN_vkDeviceWaitIdle( vkGetDeviceProcAddr( device, "vkDeviceWaitIdle" ) );
+ vkDisplayPowerControlEXT = PFN_vkDisplayPowerControlEXT( vkGetDeviceProcAddr( device, "vkDisplayPowerControlEXT" ) );
+ vkFlushMappedMemoryRanges = PFN_vkFlushMappedMemoryRanges( vkGetDeviceProcAddr( device, "vkFlushMappedMemoryRanges" ) );
+ vkFreeCommandBuffers = PFN_vkFreeCommandBuffers( vkGetDeviceProcAddr( device, "vkFreeCommandBuffers" ) );
+ vkFreeDescriptorSets = PFN_vkFreeDescriptorSets( vkGetDeviceProcAddr( device, "vkFreeDescriptorSets" ) );
+ vkFreeMemory = PFN_vkFreeMemory( vkGetDeviceProcAddr( device, "vkFreeMemory" ) );
+ vkGetAccelerationStructureHandleNV = PFN_vkGetAccelerationStructureHandleNV( vkGetDeviceProcAddr( device, "vkGetAccelerationStructureHandleNV" ) );
+ vkGetAccelerationStructureMemoryRequirementsNV = PFN_vkGetAccelerationStructureMemoryRequirementsNV( vkGetDeviceProcAddr( device, "vkGetAccelerationStructureMemoryRequirementsNV" ) );
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ vkGetAndroidHardwareBufferPropertiesANDROID = PFN_vkGetAndroidHardwareBufferPropertiesANDROID( vkGetDeviceProcAddr( device, "vkGetAndroidHardwareBufferPropertiesANDROID" ) );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ vkGetBufferDeviceAddress = PFN_vkGetBufferDeviceAddress( vkGetDeviceProcAddr( device, "vkGetBufferDeviceAddress" ) );
+ vkGetBufferDeviceAddressEXT = PFN_vkGetBufferDeviceAddressEXT( vkGetDeviceProcAddr( device, "vkGetBufferDeviceAddressEXT" ) );
+ vkGetBufferDeviceAddressKHR = PFN_vkGetBufferDeviceAddressKHR( vkGetDeviceProcAddr( device, "vkGetBufferDeviceAddressKHR" ) );
+ vkGetBufferMemoryRequirements = PFN_vkGetBufferMemoryRequirements( vkGetDeviceProcAddr( device, "vkGetBufferMemoryRequirements" ) );
+ vkGetBufferMemoryRequirements2 = PFN_vkGetBufferMemoryRequirements2( vkGetDeviceProcAddr( device, "vkGetBufferMemoryRequirements2" ) );
+ vkGetBufferMemoryRequirements2KHR = PFN_vkGetBufferMemoryRequirements2KHR( vkGetDeviceProcAddr( device, "vkGetBufferMemoryRequirements2KHR" ) );
+ vkGetBufferOpaqueCaptureAddress = PFN_vkGetBufferOpaqueCaptureAddress( vkGetDeviceProcAddr( device, "vkGetBufferOpaqueCaptureAddress" ) );
+ vkGetBufferOpaqueCaptureAddressKHR = PFN_vkGetBufferOpaqueCaptureAddressKHR( vkGetDeviceProcAddr( device, "vkGetBufferOpaqueCaptureAddressKHR" ) );
+ vkGetCalibratedTimestampsEXT = PFN_vkGetCalibratedTimestampsEXT( vkGetDeviceProcAddr( device, "vkGetCalibratedTimestampsEXT" ) );
+ vkGetDescriptorSetLayoutSupport = PFN_vkGetDescriptorSetLayoutSupport( vkGetDeviceProcAddr( device, "vkGetDescriptorSetLayoutSupport" ) );
+ vkGetDescriptorSetLayoutSupportKHR = PFN_vkGetDescriptorSetLayoutSupportKHR( vkGetDeviceProcAddr( device, "vkGetDescriptorSetLayoutSupportKHR" ) );
+ vkGetDeviceGroupPeerMemoryFeatures = PFN_vkGetDeviceGroupPeerMemoryFeatures( vkGetDeviceProcAddr( device, "vkGetDeviceGroupPeerMemoryFeatures" ) );
+ vkGetDeviceGroupPeerMemoryFeaturesKHR = PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR( vkGetDeviceProcAddr( device, "vkGetDeviceGroupPeerMemoryFeaturesKHR" ) );
+ vkGetDeviceGroupPresentCapabilitiesKHR = PFN_vkGetDeviceGroupPresentCapabilitiesKHR( vkGetDeviceProcAddr( device, "vkGetDeviceGroupPresentCapabilitiesKHR" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetDeviceGroupSurfacePresentModes2EXT = PFN_vkGetDeviceGroupSurfacePresentModes2EXT( vkGetDeviceProcAddr( device, "vkGetDeviceGroupSurfacePresentModes2EXT" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkGetDeviceGroupSurfacePresentModesKHR = PFN_vkGetDeviceGroupSurfacePresentModesKHR( vkGetDeviceProcAddr( device, "vkGetDeviceGroupSurfacePresentModesKHR" ) );
+ vkGetDeviceMemoryCommitment = PFN_vkGetDeviceMemoryCommitment( vkGetDeviceProcAddr( device, "vkGetDeviceMemoryCommitment" ) );
+ vkGetDeviceMemoryOpaqueCaptureAddress = PFN_vkGetDeviceMemoryOpaqueCaptureAddress( vkGetDeviceProcAddr( device, "vkGetDeviceMemoryOpaqueCaptureAddress" ) );
+ vkGetDeviceMemoryOpaqueCaptureAddressKHR = PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR( vkGetDeviceProcAddr( device, "vkGetDeviceMemoryOpaqueCaptureAddressKHR" ) );
+ vkGetDeviceProcAddr = PFN_vkGetDeviceProcAddr( vkGetDeviceProcAddr( device, "vkGetDeviceProcAddr" ) );
+ vkGetDeviceQueue = PFN_vkGetDeviceQueue( vkGetDeviceProcAddr( device, "vkGetDeviceQueue" ) );
+ vkGetDeviceQueue2 = PFN_vkGetDeviceQueue2( vkGetDeviceProcAddr( device, "vkGetDeviceQueue2" ) );
+ vkGetEventStatus = PFN_vkGetEventStatus( vkGetDeviceProcAddr( device, "vkGetEventStatus" ) );
+ vkGetFenceFdKHR = PFN_vkGetFenceFdKHR( vkGetDeviceProcAddr( device, "vkGetFenceFdKHR" ) );
+ vkGetFenceStatus = PFN_vkGetFenceStatus( vkGetDeviceProcAddr( device, "vkGetFenceStatus" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetFenceWin32HandleKHR = PFN_vkGetFenceWin32HandleKHR( vkGetDeviceProcAddr( device, "vkGetFenceWin32HandleKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkGetImageDrmFormatModifierPropertiesEXT = PFN_vkGetImageDrmFormatModifierPropertiesEXT( vkGetDeviceProcAddr( device, "vkGetImageDrmFormatModifierPropertiesEXT" ) );
+ vkGetImageMemoryRequirements = PFN_vkGetImageMemoryRequirements( vkGetDeviceProcAddr( device, "vkGetImageMemoryRequirements" ) );
+ vkGetImageMemoryRequirements2 = PFN_vkGetImageMemoryRequirements2( vkGetDeviceProcAddr( device, "vkGetImageMemoryRequirements2" ) );
+ vkGetImageMemoryRequirements2KHR = PFN_vkGetImageMemoryRequirements2KHR( vkGetDeviceProcAddr( device, "vkGetImageMemoryRequirements2KHR" ) );
+ vkGetImageSparseMemoryRequirements = PFN_vkGetImageSparseMemoryRequirements( vkGetDeviceProcAddr( device, "vkGetImageSparseMemoryRequirements" ) );
+ vkGetImageSparseMemoryRequirements2 = PFN_vkGetImageSparseMemoryRequirements2( vkGetDeviceProcAddr( device, "vkGetImageSparseMemoryRequirements2" ) );
+ vkGetImageSparseMemoryRequirements2KHR = PFN_vkGetImageSparseMemoryRequirements2KHR( vkGetDeviceProcAddr( device, "vkGetImageSparseMemoryRequirements2KHR" ) );
+ vkGetImageSubresourceLayout = PFN_vkGetImageSubresourceLayout( vkGetDeviceProcAddr( device, "vkGetImageSubresourceLayout" ) );
+ vkGetImageViewHandleNVX = PFN_vkGetImageViewHandleNVX( vkGetDeviceProcAddr( device, "vkGetImageViewHandleNVX" ) );
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ vkGetMemoryAndroidHardwareBufferANDROID = PFN_vkGetMemoryAndroidHardwareBufferANDROID( vkGetDeviceProcAddr( device, "vkGetMemoryAndroidHardwareBufferANDROID" ) );
+#endif /*VK_USE_PLATFORM_ANDROID_KHR*/
+ vkGetMemoryFdKHR = PFN_vkGetMemoryFdKHR( vkGetDeviceProcAddr( device, "vkGetMemoryFdKHR" ) );
+ vkGetMemoryFdPropertiesKHR = PFN_vkGetMemoryFdPropertiesKHR( vkGetDeviceProcAddr( device, "vkGetMemoryFdPropertiesKHR" ) );
+ vkGetMemoryHostPointerPropertiesEXT = PFN_vkGetMemoryHostPointerPropertiesEXT( vkGetDeviceProcAddr( device, "vkGetMemoryHostPointerPropertiesEXT" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetMemoryWin32HandleKHR = PFN_vkGetMemoryWin32HandleKHR( vkGetDeviceProcAddr( device, "vkGetMemoryWin32HandleKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetMemoryWin32HandleNV = PFN_vkGetMemoryWin32HandleNV( vkGetDeviceProcAddr( device, "vkGetMemoryWin32HandleNV" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetMemoryWin32HandlePropertiesKHR = PFN_vkGetMemoryWin32HandlePropertiesKHR( vkGetDeviceProcAddr( device, "vkGetMemoryWin32HandlePropertiesKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkGetPastPresentationTimingGOOGLE = PFN_vkGetPastPresentationTimingGOOGLE( vkGetDeviceProcAddr( device, "vkGetPastPresentationTimingGOOGLE" ) );
+ vkGetPerformanceParameterINTEL = PFN_vkGetPerformanceParameterINTEL( vkGetDeviceProcAddr( device, "vkGetPerformanceParameterINTEL" ) );
+ vkGetPipelineCacheData = PFN_vkGetPipelineCacheData( vkGetDeviceProcAddr( device, "vkGetPipelineCacheData" ) );
+ vkGetPipelineExecutableInternalRepresentationsKHR = PFN_vkGetPipelineExecutableInternalRepresentationsKHR( vkGetDeviceProcAddr( device, "vkGetPipelineExecutableInternalRepresentationsKHR" ) );
+ vkGetPipelineExecutablePropertiesKHR = PFN_vkGetPipelineExecutablePropertiesKHR( vkGetDeviceProcAddr( device, "vkGetPipelineExecutablePropertiesKHR" ) );
+ vkGetPipelineExecutableStatisticsKHR = PFN_vkGetPipelineExecutableStatisticsKHR( vkGetDeviceProcAddr( device, "vkGetPipelineExecutableStatisticsKHR" ) );
+ vkGetQueryPoolResults = PFN_vkGetQueryPoolResults( vkGetDeviceProcAddr( device, "vkGetQueryPoolResults" ) );
+ vkGetRayTracingShaderGroupHandlesNV = PFN_vkGetRayTracingShaderGroupHandlesNV( vkGetDeviceProcAddr( device, "vkGetRayTracingShaderGroupHandlesNV" ) );
+ vkGetRefreshCycleDurationGOOGLE = PFN_vkGetRefreshCycleDurationGOOGLE( vkGetDeviceProcAddr( device, "vkGetRefreshCycleDurationGOOGLE" ) );
+ vkGetRenderAreaGranularity = PFN_vkGetRenderAreaGranularity( vkGetDeviceProcAddr( device, "vkGetRenderAreaGranularity" ) );
+ vkGetSemaphoreCounterValue = PFN_vkGetSemaphoreCounterValue( vkGetDeviceProcAddr( device, "vkGetSemaphoreCounterValue" ) );
+ vkGetSemaphoreCounterValueKHR = PFN_vkGetSemaphoreCounterValueKHR( vkGetDeviceProcAddr( device, "vkGetSemaphoreCounterValueKHR" ) );
+ vkGetSemaphoreFdKHR = PFN_vkGetSemaphoreFdKHR( vkGetDeviceProcAddr( device, "vkGetSemaphoreFdKHR" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkGetSemaphoreWin32HandleKHR = PFN_vkGetSemaphoreWin32HandleKHR( vkGetDeviceProcAddr( device, "vkGetSemaphoreWin32HandleKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkGetShaderInfoAMD = PFN_vkGetShaderInfoAMD( vkGetDeviceProcAddr( device, "vkGetShaderInfoAMD" ) );
+ vkGetSwapchainCounterEXT = PFN_vkGetSwapchainCounterEXT( vkGetDeviceProcAddr( device, "vkGetSwapchainCounterEXT" ) );
+ vkGetSwapchainImagesKHR = PFN_vkGetSwapchainImagesKHR( vkGetDeviceProcAddr( device, "vkGetSwapchainImagesKHR" ) );
+ vkGetSwapchainStatusKHR = PFN_vkGetSwapchainStatusKHR( vkGetDeviceProcAddr( device, "vkGetSwapchainStatusKHR" ) );
+ vkGetValidationCacheDataEXT = PFN_vkGetValidationCacheDataEXT( vkGetDeviceProcAddr( device, "vkGetValidationCacheDataEXT" ) );
+ vkImportFenceFdKHR = PFN_vkImportFenceFdKHR( vkGetDeviceProcAddr( device, "vkImportFenceFdKHR" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkImportFenceWin32HandleKHR = PFN_vkImportFenceWin32HandleKHR( vkGetDeviceProcAddr( device, "vkImportFenceWin32HandleKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkImportSemaphoreFdKHR = PFN_vkImportSemaphoreFdKHR( vkGetDeviceProcAddr( device, "vkImportSemaphoreFdKHR" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkImportSemaphoreWin32HandleKHR = PFN_vkImportSemaphoreWin32HandleKHR( vkGetDeviceProcAddr( device, "vkImportSemaphoreWin32HandleKHR" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkInitializePerformanceApiINTEL = PFN_vkInitializePerformanceApiINTEL( vkGetDeviceProcAddr( device, "vkInitializePerformanceApiINTEL" ) );
+ vkInvalidateMappedMemoryRanges = PFN_vkInvalidateMappedMemoryRanges( vkGetDeviceProcAddr( device, "vkInvalidateMappedMemoryRanges" ) );
+ vkMapMemory = PFN_vkMapMemory( vkGetDeviceProcAddr( device, "vkMapMemory" ) );
+ vkMergePipelineCaches = PFN_vkMergePipelineCaches( vkGetDeviceProcAddr( device, "vkMergePipelineCaches" ) );
+ vkMergeValidationCachesEXT = PFN_vkMergeValidationCachesEXT( vkGetDeviceProcAddr( device, "vkMergeValidationCachesEXT" ) );
+ vkRegisterDeviceEventEXT = PFN_vkRegisterDeviceEventEXT( vkGetDeviceProcAddr( device, "vkRegisterDeviceEventEXT" ) );
+ vkRegisterDisplayEventEXT = PFN_vkRegisterDisplayEventEXT( vkGetDeviceProcAddr( device, "vkRegisterDisplayEventEXT" ) );
+ vkRegisterObjectsNVX = PFN_vkRegisterObjectsNVX( vkGetDeviceProcAddr( device, "vkRegisterObjectsNVX" ) );
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ vkReleaseFullScreenExclusiveModeEXT = PFN_vkReleaseFullScreenExclusiveModeEXT( vkGetDeviceProcAddr( device, "vkReleaseFullScreenExclusiveModeEXT" ) );
+#endif /*VK_USE_PLATFORM_WIN32_KHR*/
+ vkReleasePerformanceConfigurationINTEL = PFN_vkReleasePerformanceConfigurationINTEL( vkGetDeviceProcAddr( device, "vkReleasePerformanceConfigurationINTEL" ) );
+ vkReleaseProfilingLockKHR = PFN_vkReleaseProfilingLockKHR( vkGetDeviceProcAddr( device, "vkReleaseProfilingLockKHR" ) );
+ vkResetCommandPool = PFN_vkResetCommandPool( vkGetDeviceProcAddr( device, "vkResetCommandPool" ) );
+ vkResetDescriptorPool = PFN_vkResetDescriptorPool( vkGetDeviceProcAddr( device, "vkResetDescriptorPool" ) );
+ vkResetEvent = PFN_vkResetEvent( vkGetDeviceProcAddr( device, "vkResetEvent" ) );
+ vkResetFences = PFN_vkResetFences( vkGetDeviceProcAddr( device, "vkResetFences" ) );
+ vkResetQueryPool = PFN_vkResetQueryPool( vkGetDeviceProcAddr( device, "vkResetQueryPool" ) );
+ vkResetQueryPoolEXT = PFN_vkResetQueryPoolEXT( vkGetDeviceProcAddr( device, "vkResetQueryPoolEXT" ) );
+ vkSetDebugUtilsObjectNameEXT = PFN_vkSetDebugUtilsObjectNameEXT( vkGetDeviceProcAddr( device, "vkSetDebugUtilsObjectNameEXT" ) );
+ vkSetDebugUtilsObjectTagEXT = PFN_vkSetDebugUtilsObjectTagEXT( vkGetDeviceProcAddr( device, "vkSetDebugUtilsObjectTagEXT" ) );
+ vkSetEvent = PFN_vkSetEvent( vkGetDeviceProcAddr( device, "vkSetEvent" ) );
+ vkSetHdrMetadataEXT = PFN_vkSetHdrMetadataEXT( vkGetDeviceProcAddr( device, "vkSetHdrMetadataEXT" ) );
+ vkSetLocalDimmingAMD = PFN_vkSetLocalDimmingAMD( vkGetDeviceProcAddr( device, "vkSetLocalDimmingAMD" ) );
+ vkSignalSemaphore = PFN_vkSignalSemaphore( vkGetDeviceProcAddr( device, "vkSignalSemaphore" ) );
+ vkSignalSemaphoreKHR = PFN_vkSignalSemaphoreKHR( vkGetDeviceProcAddr( device, "vkSignalSemaphoreKHR" ) );
+ vkTrimCommandPool = PFN_vkTrimCommandPool( vkGetDeviceProcAddr( device, "vkTrimCommandPool" ) );
+ vkTrimCommandPoolKHR = PFN_vkTrimCommandPoolKHR( vkGetDeviceProcAddr( device, "vkTrimCommandPoolKHR" ) );
+ vkUninitializePerformanceApiINTEL = PFN_vkUninitializePerformanceApiINTEL( vkGetDeviceProcAddr( device, "vkUninitializePerformanceApiINTEL" ) );
+ vkUnmapMemory = PFN_vkUnmapMemory( vkGetDeviceProcAddr( device, "vkUnmapMemory" ) );
+ vkUnregisterObjectsNVX = PFN_vkUnregisterObjectsNVX( vkGetDeviceProcAddr( device, "vkUnregisterObjectsNVX" ) );
+ vkUpdateDescriptorSetWithTemplate = PFN_vkUpdateDescriptorSetWithTemplate( vkGetDeviceProcAddr( device, "vkUpdateDescriptorSetWithTemplate" ) );
+ vkUpdateDescriptorSetWithTemplateKHR = PFN_vkUpdateDescriptorSetWithTemplateKHR( vkGetDeviceProcAddr( device, "vkUpdateDescriptorSetWithTemplateKHR" ) );
+ vkUpdateDescriptorSets = PFN_vkUpdateDescriptorSets( vkGetDeviceProcAddr( device, "vkUpdateDescriptorSets" ) );
+ vkWaitForFences = PFN_vkWaitForFences( vkGetDeviceProcAddr( device, "vkWaitForFences" ) );
+ vkWaitSemaphores = PFN_vkWaitSemaphores( vkGetDeviceProcAddr( device, "vkWaitSemaphores" ) );
+ vkWaitSemaphoresKHR = PFN_vkWaitSemaphoresKHR( vkGetDeviceProcAddr( device, "vkWaitSemaphoresKHR" ) );
+ vkGetQueueCheckpointDataNV = PFN_vkGetQueueCheckpointDataNV( vkGetDeviceProcAddr( device, "vkGetQueueCheckpointDataNV" ) );
+ vkQueueBeginDebugUtilsLabelEXT = PFN_vkQueueBeginDebugUtilsLabelEXT( vkGetDeviceProcAddr( device, "vkQueueBeginDebugUtilsLabelEXT" ) );
+ vkQueueBindSparse = PFN_vkQueueBindSparse( vkGetDeviceProcAddr( device, "vkQueueBindSparse" ) );
+ vkQueueEndDebugUtilsLabelEXT = PFN_vkQueueEndDebugUtilsLabelEXT( vkGetDeviceProcAddr( device, "vkQueueEndDebugUtilsLabelEXT" ) );
+ vkQueueInsertDebugUtilsLabelEXT = PFN_vkQueueInsertDebugUtilsLabelEXT( vkGetDeviceProcAddr( device, "vkQueueInsertDebugUtilsLabelEXT" ) );
+ vkQueuePresentKHR = PFN_vkQueuePresentKHR( vkGetDeviceProcAddr( device, "vkQueuePresentKHR" ) );
+ vkQueueSetPerformanceConfigurationINTEL = PFN_vkQueueSetPerformanceConfigurationINTEL( vkGetDeviceProcAddr( device, "vkQueueSetPerformanceConfigurationINTEL" ) );
+ vkQueueSubmit = PFN_vkQueueSubmit( vkGetDeviceProcAddr( device, "vkQueueSubmit" ) );
+ vkQueueWaitIdle = PFN_vkQueueWaitIdle( vkGetDeviceProcAddr( device, "vkQueueWaitIdle" ) );
+ }
+ };
+
+} // namespace VULKAN_HPP_NAMESPACE
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_android.h b/thirdparty/vulkan/include/vulkan/vulkan_android.h
new file mode 100644
index 0000000000..9b8d3e276f
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_android.h
@@ -0,0 +1,122 @@
+#ifndef VULKAN_ANDROID_H_
+#define VULKAN_ANDROID_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_KHR_android_surface 1
+struct ANativeWindow;
+#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6
+#define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface"
+typedef VkFlags VkAndroidSurfaceCreateFlagsKHR;
+typedef struct VkAndroidSurfaceCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkAndroidSurfaceCreateFlagsKHR flags;
+ struct ANativeWindow* window;
+} VkAndroidSurfaceCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateAndroidSurfaceKHR)(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
+ VkInstance instance,
+ const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+
+
+#define VK_ANDROID_external_memory_android_hardware_buffer 1
+struct AHardwareBuffer;
+#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 3
+#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer"
+typedef struct VkAndroidHardwareBufferUsageANDROID {
+ VkStructureType sType;
+ void* pNext;
+ uint64_t androidHardwareBufferUsage;
+} VkAndroidHardwareBufferUsageANDROID;
+
+typedef struct VkAndroidHardwareBufferPropertiesANDROID {
+ VkStructureType sType;
+ void* pNext;
+ VkDeviceSize allocationSize;
+ uint32_t memoryTypeBits;
+} VkAndroidHardwareBufferPropertiesANDROID;
+
+typedef struct VkAndroidHardwareBufferFormatPropertiesANDROID {
+ VkStructureType sType;
+ void* pNext;
+ VkFormat format;
+ uint64_t externalFormat;
+ VkFormatFeatureFlags formatFeatures;
+ VkComponentMapping samplerYcbcrConversionComponents;
+ VkSamplerYcbcrModelConversion suggestedYcbcrModel;
+ VkSamplerYcbcrRange suggestedYcbcrRange;
+ VkChromaLocation suggestedXChromaOffset;
+ VkChromaLocation suggestedYChromaOffset;
+} VkAndroidHardwareBufferFormatPropertiesANDROID;
+
+typedef struct VkImportAndroidHardwareBufferInfoANDROID {
+ VkStructureType sType;
+ const void* pNext;
+ struct AHardwareBuffer* buffer;
+} VkImportAndroidHardwareBufferInfoANDROID;
+
+typedef struct VkMemoryGetAndroidHardwareBufferInfoANDROID {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceMemory memory;
+} VkMemoryGetAndroidHardwareBufferInfoANDROID;
+
+typedef struct VkExternalFormatANDROID {
+ VkStructureType sType;
+ void* pNext;
+ uint64_t externalFormat;
+} VkExternalFormatANDROID;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetAndroidHardwareBufferPropertiesANDROID)(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryAndroidHardwareBufferANDROID)(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetAndroidHardwareBufferPropertiesANDROID(
+ VkDevice device,
+ const struct AHardwareBuffer* buffer,
+ VkAndroidHardwareBufferPropertiesANDROID* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryAndroidHardwareBufferANDROID(
+ VkDevice device,
+ const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo,
+ struct AHardwareBuffer** pBuffer);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_core.h b/thirdparty/vulkan/include/vulkan/vulkan_core.h
new file mode 100644
index 0000000000..ea96fc43ed
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_core.h
@@ -0,0 +1,10722 @@
+#ifndef VULKAN_CORE_H_
+#define VULKAN_CORE_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_VERSION_1_0 1
+#include "vk_platform.h"
+#define VK_MAKE_VERSION(major, minor, patch) \
+ (((major) << 22) | ((minor) << 12) | (patch))
+
+// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead.
+//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0
+
+// Vulkan 1.0 version number
+#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)// Patch version should always be set to 0
+
+#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
+#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
+#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
+// Version of this file
+#define VK_HEADER_VERSION 131
+
+
+#define VK_NULL_HANDLE 0
+
+
+#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
+
+
+#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE)
+#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+ #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
+#else
+ #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+#endif
+#endif
+
+typedef uint32_t VkFlags;
+typedef uint32_t VkBool32;
+typedef uint64_t VkDeviceSize;
+typedef uint32_t VkSampleMask;
+VK_DEFINE_HANDLE(VkInstance)
+VK_DEFINE_HANDLE(VkPhysicalDevice)
+VK_DEFINE_HANDLE(VkDevice)
+VK_DEFINE_HANDLE(VkQueue)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore)
+VK_DEFINE_HANDLE(VkCommandBuffer)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool)
+#define VK_LOD_CLAMP_NONE 1000.0f
+#define VK_REMAINING_MIP_LEVELS (~0U)
+#define VK_REMAINING_ARRAY_LAYERS (~0U)
+#define VK_WHOLE_SIZE (~0ULL)
+#define VK_ATTACHMENT_UNUSED (~0U)
+#define VK_TRUE 1
+#define VK_FALSE 0
+#define VK_QUEUE_FAMILY_IGNORED (~0U)
+#define VK_SUBPASS_EXTERNAL (~0U)
+#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
+#define VK_UUID_SIZE 16
+#define VK_MAX_MEMORY_TYPES 32
+#define VK_MAX_MEMORY_HEAPS 16
+#define VK_MAX_EXTENSION_NAME_SIZE 256
+#define VK_MAX_DESCRIPTION_SIZE 256
+
+typedef enum VkPipelineCacheHeaderVersion {
+ VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1,
+ VK_PIPELINE_CACHE_HEADER_VERSION_BEGIN_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE,
+ VK_PIPELINE_CACHE_HEADER_VERSION_END_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE,
+ VK_PIPELINE_CACHE_HEADER_VERSION_RANGE_SIZE = (VK_PIPELINE_CACHE_HEADER_VERSION_ONE - VK_PIPELINE_CACHE_HEADER_VERSION_ONE + 1),
+ VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineCacheHeaderVersion;
+
+typedef enum VkResult {
+ VK_SUCCESS = 0,
+ VK_NOT_READY = 1,
+ VK_TIMEOUT = 2,
+ VK_EVENT_SET = 3,
+ VK_EVENT_RESET = 4,
+ VK_INCOMPLETE = 5,
+ VK_ERROR_OUT_OF_HOST_MEMORY = -1,
+ VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
+ VK_ERROR_INITIALIZATION_FAILED = -3,
+ VK_ERROR_DEVICE_LOST = -4,
+ VK_ERROR_MEMORY_MAP_FAILED = -5,
+ VK_ERROR_LAYER_NOT_PRESENT = -6,
+ VK_ERROR_EXTENSION_NOT_PRESENT = -7,
+ VK_ERROR_FEATURE_NOT_PRESENT = -8,
+ VK_ERROR_INCOMPATIBLE_DRIVER = -9,
+ VK_ERROR_TOO_MANY_OBJECTS = -10,
+ VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
+ VK_ERROR_FRAGMENTED_POOL = -12,
+ VK_ERROR_UNKNOWN = -13,
+ VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000,
+ VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003,
+ VK_ERROR_FRAGMENTATION = -1000161000,
+ VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000,
+ VK_ERROR_SURFACE_LOST_KHR = -1000000000,
+ VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
+ VK_SUBOPTIMAL_KHR = 1000001003,
+ VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
+ VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
+ VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
+ VK_ERROR_INVALID_SHADER_NV = -1000012000,
+ VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000,
+ VK_ERROR_NOT_PERMITTED_EXT = -1000174001,
+ VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000,
+ VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY,
+ VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE,
+ VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION,
+ VK_ERROR_INVALID_DEVICE_ADDRESS_EXT = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS,
+ VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS,
+ VK_RESULT_BEGIN_RANGE = VK_ERROR_UNKNOWN,
+ VK_RESULT_END_RANGE = VK_INCOMPLETE,
+ VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_UNKNOWN + 1),
+ VK_RESULT_MAX_ENUM = 0x7FFFFFFF
+} VkResult;
+
+typedef enum VkStructureType {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO = 0,
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1,
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO = 2,
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 3,
+ VK_STRUCTURE_TYPE_SUBMIT_INFO = 4,
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 5,
+ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE = 6,
+ VK_STRUCTURE_TYPE_BIND_SPARSE_INFO = 7,
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO = 8,
+ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO = 9,
+ VK_STRUCTURE_TYPE_EVENT_CREATE_INFO = 10,
+ VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO = 11,
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 12,
+ VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO = 13,
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 14,
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO = 15,
+ VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO = 16,
+ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO = 17,
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO = 18,
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19,
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20,
+ VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22,
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23,
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24,
+ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25,
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26,
+ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27,
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO = 28,
+ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO = 29,
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO = 30,
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO = 31,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO = 33,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO = 34,
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET = 35,
+ VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET = 36,
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO = 37,
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO = 38,
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO = 39,
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO = 40,
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO = 41,
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO = 42,
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO = 43,
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER = 44,
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 45,
+ VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46,
+ VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47,
+ VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000,
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO = 1000157000,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO = 1000157001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000,
+ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000,
+ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001,
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO = 1000060000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO = 1000060005,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006,
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001,
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 = 1000146000,
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 = 1000146001,
+ VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 = 1000146002,
+ VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 = 1000146003,
+ VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 = 1000146004,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 = 1000059000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001,
+ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 = 1000059002,
+ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 = 1000059003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004,
+ VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 = 1000059005,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006,
+ VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000,
+ VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001,
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002,
+ VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003,
+ VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000,
+ VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO = 1000145000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002,
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 = 1000145003,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO = 1000156001,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002,
+ VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000,
+ VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002,
+ VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES = 1000071003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO = 1000072000,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO = 1000072001,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO = 1000072002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000,
+ VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES = 1000112001,
+ VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO = 1000113000,
+ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO = 1000077000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000,
+ VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES = 50,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES = 51,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES = 52,
+ VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000,
+ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 = 1000109000,
+ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2 = 1000109001,
+ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2 = 1000109002,
+ VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 = 1000109003,
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2 = 1000109004,
+ VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO = 1000109005,
+ VK_STRUCTURE_TYPE_SUBPASS_END_INFO = 1000109006,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000,
+ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000,
+ VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000,
+ VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000,
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001,
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002,
+ VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000,
+ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001,
+ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES = 1000207000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES = 1000207001,
+ VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO = 1000207002,
+ VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO = 1000207003,
+ VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO = 1000207004,
+ VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO = 1000207005,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES = 1000257000,
+ VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO = 1000244001,
+ VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002,
+ VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003,
+ VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004,
+ VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000,
+ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007,
+ VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR = 1000060008,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR = 1000060009,
+ VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR = 1000060010,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012,
+ VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000,
+ VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001,
+ VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR = 1000003000,
+ VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
+ VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
+ VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
+ VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000,
+ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
+ VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000,
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000,
+ VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000,
+ VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001,
+ VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002,
+ VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000,
+ VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
+ VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001,
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002,
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000,
+ VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000,
+ VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001,
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001,
+ VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
+ VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
+ VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT = 1000066000,
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001,
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001,
+ VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002,
+ VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR = 1000073003,
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR = 1000074000,
+ VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR = 1000074001,
+ VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR = 1000074002,
+ VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR = 1000075000,
+ VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000,
+ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001,
+ VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002,
+ VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR = 1000078003,
+ VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000,
+ VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR = 1000079001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000,
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001,
+ VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002,
+ VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
+ VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
+ VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
+ VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002,
+ VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003,
+ VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004,
+ VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000,
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000,
+ VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000,
+ VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT = 1000091001,
+ VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT = 1000091002,
+ VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003,
+ VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000,
+ VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000,
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT = 1000102000,
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT = 1000102001,
+ VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
+ VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000,
+ VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000,
+ VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001,
+ VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002,
+ VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR = 1000115000,
+ VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR = 1000115001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR = 1000116000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR = 1000116001,
+ VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR = 1000116002,
+ VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR = 1000116003,
+ VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR = 1000116004,
+ VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR = 1000116005,
+ VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR = 1000116006,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000,
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
+ VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
+ VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR = 1000121000,
+ VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR = 1000121001,
+ VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR = 1000121002,
+ VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR = 1000121003,
+ VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR = 1000121004,
+ VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
+ VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
+ VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000,
+ VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT = 1000128001,
+ VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT = 1000128002,
+ VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000128003,
+ VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004,
+ VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID = 1000129000,
+ VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID = 1000129001,
+ VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID = 1000129002,
+ VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003,
+ VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004,
+ VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = 1000138000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = 1000138001,
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = 1000138002,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = 1000138003,
+ VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000,
+ VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001,
+ VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003,
+ VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT = 1000143004,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001,
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002,
+ VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000,
+ VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001,
+ VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT = 1000158000,
+ VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT = 1000158002,
+ VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003,
+ VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004,
+ VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005,
+ VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000,
+ VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005,
+ VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001,
+ VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003,
+ VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004,
+ VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005,
+ VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006,
+ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009,
+ VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011,
+ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV = 1000165012,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000,
+ VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT = 1000170000,
+ VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT = 1000170001,
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = 1000174000,
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000,
+ VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR = 1000181000,
+ VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD = 1000183000,
+ VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT = 1000184000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
+ VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000,
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002,
+ VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP = 1000191000,
+ VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000192000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = 1000203000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002,
+ VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000,
+ VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL = 1000209000,
+ VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL = 1000210000,
+ VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL = 1000210001,
+ VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL = 1000210002,
+ VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL = 1000210003,
+ VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL = 1000210004,
+ VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL = 1000210005,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000,
+ VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD = 1000213000,
+ VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD = 1000213001,
+ VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000,
+ VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001,
+ VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT = 1000225000,
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = 1000225001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT = 1000225002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD = 1000227000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD = 1000229000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT = 1000237000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT = 1000238000,
+ VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT = 1000238001,
+ VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR = 1000239000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV = 1000240000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT = 1000244000,
+ VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT = 1000244002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT = 1000245000,
+ VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT = 1000247000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV = 1000249000,
+ VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV = 1000250000,
+ VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV = 1000250001,
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV = 1000250002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT = 1000251000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT = 1000252000,
+ VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT = 1000255000,
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT = 1000255002,
+ VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT = 1000255001,
+ VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT = 1000259000,
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = 1000259001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = 1000259002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = 1000265000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000,
+ VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR = 1000269001,
+ VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002,
+ VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR = 1000269003,
+ VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004,
+ VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = 1000276000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = 1000281001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES,
+ VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
+ VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
+ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
+ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+ VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2,
+ VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2,
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO,
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
+ VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
+ VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
+ VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
+ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES,
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO,
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO_KHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,
+ VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO,
+ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
+ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
+ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
+ VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
+ VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
+ VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
+ VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
+ VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES,
+ VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO,
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES,
+ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
+ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES,
+ VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
+ VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2,
+ VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
+ VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2,
+ VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO,
+ VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES,
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES,
+ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES,
+ VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
+ VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+ VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES,
+ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT,
+ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT,
+ VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_EXT = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
+ VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES,
+ VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
+ VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO,
+ VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO,
+ VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES,
+ VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
+ VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
+ VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkStructureType;
+
+typedef enum VkSystemAllocationScope {
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1,
+ VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2,
+ VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4,
+ VK_SYSTEM_ALLOCATION_SCOPE_BEGIN_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_COMMAND,
+ VK_SYSTEM_ALLOCATION_SCOPE_END_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE,
+ VK_SYSTEM_ALLOCATION_SCOPE_RANGE_SIZE = (VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND + 1),
+ VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF
+} VkSystemAllocationScope;
+
+typedef enum VkInternalAllocationType {
+ VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0,
+ VK_INTERNAL_ALLOCATION_TYPE_BEGIN_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE,
+ VK_INTERNAL_ALLOCATION_TYPE_END_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE,
+ VK_INTERNAL_ALLOCATION_TYPE_RANGE_SIZE = (VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE - VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE + 1),
+ VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkInternalAllocationType;
+
+typedef enum VkFormat {
+ VK_FORMAT_UNDEFINED = 0,
+ VK_FORMAT_R4G4_UNORM_PACK8 = 1,
+ VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2,
+ VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3,
+ VK_FORMAT_R5G6B5_UNORM_PACK16 = 4,
+ VK_FORMAT_B5G6R5_UNORM_PACK16 = 5,
+ VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6,
+ VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7,
+ VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8,
+ VK_FORMAT_R8_UNORM = 9,
+ VK_FORMAT_R8_SNORM = 10,
+ VK_FORMAT_R8_USCALED = 11,
+ VK_FORMAT_R8_SSCALED = 12,
+ VK_FORMAT_R8_UINT = 13,
+ VK_FORMAT_R8_SINT = 14,
+ VK_FORMAT_R8_SRGB = 15,
+ VK_FORMAT_R8G8_UNORM = 16,
+ VK_FORMAT_R8G8_SNORM = 17,
+ VK_FORMAT_R8G8_USCALED = 18,
+ VK_FORMAT_R8G8_SSCALED = 19,
+ VK_FORMAT_R8G8_UINT = 20,
+ VK_FORMAT_R8G8_SINT = 21,
+ VK_FORMAT_R8G8_SRGB = 22,
+ VK_FORMAT_R8G8B8_UNORM = 23,
+ VK_FORMAT_R8G8B8_SNORM = 24,
+ VK_FORMAT_R8G8B8_USCALED = 25,
+ VK_FORMAT_R8G8B8_SSCALED = 26,
+ VK_FORMAT_R8G8B8_UINT = 27,
+ VK_FORMAT_R8G8B8_SINT = 28,
+ VK_FORMAT_R8G8B8_SRGB = 29,
+ VK_FORMAT_B8G8R8_UNORM = 30,
+ VK_FORMAT_B8G8R8_SNORM = 31,
+ VK_FORMAT_B8G8R8_USCALED = 32,
+ VK_FORMAT_B8G8R8_SSCALED = 33,
+ VK_FORMAT_B8G8R8_UINT = 34,
+ VK_FORMAT_B8G8R8_SINT = 35,
+ VK_FORMAT_B8G8R8_SRGB = 36,
+ VK_FORMAT_R8G8B8A8_UNORM = 37,
+ VK_FORMAT_R8G8B8A8_SNORM = 38,
+ VK_FORMAT_R8G8B8A8_USCALED = 39,
+ VK_FORMAT_R8G8B8A8_SSCALED = 40,
+ VK_FORMAT_R8G8B8A8_UINT = 41,
+ VK_FORMAT_R8G8B8A8_SINT = 42,
+ VK_FORMAT_R8G8B8A8_SRGB = 43,
+ VK_FORMAT_B8G8R8A8_UNORM = 44,
+ VK_FORMAT_B8G8R8A8_SNORM = 45,
+ VK_FORMAT_B8G8R8A8_USCALED = 46,
+ VK_FORMAT_B8G8R8A8_SSCALED = 47,
+ VK_FORMAT_B8G8R8A8_UINT = 48,
+ VK_FORMAT_B8G8R8A8_SINT = 49,
+ VK_FORMAT_B8G8R8A8_SRGB = 50,
+ VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51,
+ VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52,
+ VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53,
+ VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54,
+ VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55,
+ VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56,
+ VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57,
+ VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58,
+ VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59,
+ VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60,
+ VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61,
+ VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62,
+ VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63,
+ VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64,
+ VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65,
+ VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66,
+ VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67,
+ VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68,
+ VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69,
+ VK_FORMAT_R16_UNORM = 70,
+ VK_FORMAT_R16_SNORM = 71,
+ VK_FORMAT_R16_USCALED = 72,
+ VK_FORMAT_R16_SSCALED = 73,
+ VK_FORMAT_R16_UINT = 74,
+ VK_FORMAT_R16_SINT = 75,
+ VK_FORMAT_R16_SFLOAT = 76,
+ VK_FORMAT_R16G16_UNORM = 77,
+ VK_FORMAT_R16G16_SNORM = 78,
+ VK_FORMAT_R16G16_USCALED = 79,
+ VK_FORMAT_R16G16_SSCALED = 80,
+ VK_FORMAT_R16G16_UINT = 81,
+ VK_FORMAT_R16G16_SINT = 82,
+ VK_FORMAT_R16G16_SFLOAT = 83,
+ VK_FORMAT_R16G16B16_UNORM = 84,
+ VK_FORMAT_R16G16B16_SNORM = 85,
+ VK_FORMAT_R16G16B16_USCALED = 86,
+ VK_FORMAT_R16G16B16_SSCALED = 87,
+ VK_FORMAT_R16G16B16_UINT = 88,
+ VK_FORMAT_R16G16B16_SINT = 89,
+ VK_FORMAT_R16G16B16_SFLOAT = 90,
+ VK_FORMAT_R16G16B16A16_UNORM = 91,
+ VK_FORMAT_R16G16B16A16_SNORM = 92,
+ VK_FORMAT_R16G16B16A16_USCALED = 93,
+ VK_FORMAT_R16G16B16A16_SSCALED = 94,
+ VK_FORMAT_R16G16B16A16_UINT = 95,
+ VK_FORMAT_R16G16B16A16_SINT = 96,
+ VK_FORMAT_R16G16B16A16_SFLOAT = 97,
+ VK_FORMAT_R32_UINT = 98,
+ VK_FORMAT_R32_SINT = 99,
+ VK_FORMAT_R32_SFLOAT = 100,
+ VK_FORMAT_R32G32_UINT = 101,
+ VK_FORMAT_R32G32_SINT = 102,
+ VK_FORMAT_R32G32_SFLOAT = 103,
+ VK_FORMAT_R32G32B32_UINT = 104,
+ VK_FORMAT_R32G32B32_SINT = 105,
+ VK_FORMAT_R32G32B32_SFLOAT = 106,
+ VK_FORMAT_R32G32B32A32_UINT = 107,
+ VK_FORMAT_R32G32B32A32_SINT = 108,
+ VK_FORMAT_R32G32B32A32_SFLOAT = 109,
+ VK_FORMAT_R64_UINT = 110,
+ VK_FORMAT_R64_SINT = 111,
+ VK_FORMAT_R64_SFLOAT = 112,
+ VK_FORMAT_R64G64_UINT = 113,
+ VK_FORMAT_R64G64_SINT = 114,
+ VK_FORMAT_R64G64_SFLOAT = 115,
+ VK_FORMAT_R64G64B64_UINT = 116,
+ VK_FORMAT_R64G64B64_SINT = 117,
+ VK_FORMAT_R64G64B64_SFLOAT = 118,
+ VK_FORMAT_R64G64B64A64_UINT = 119,
+ VK_FORMAT_R64G64B64A64_SINT = 120,
+ VK_FORMAT_R64G64B64A64_SFLOAT = 121,
+ VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122,
+ VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123,
+ VK_FORMAT_D16_UNORM = 124,
+ VK_FORMAT_X8_D24_UNORM_PACK32 = 125,
+ VK_FORMAT_D32_SFLOAT = 126,
+ VK_FORMAT_S8_UINT = 127,
+ VK_FORMAT_D16_UNORM_S8_UINT = 128,
+ VK_FORMAT_D24_UNORM_S8_UINT = 129,
+ VK_FORMAT_D32_SFLOAT_S8_UINT = 130,
+ VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131,
+ VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132,
+ VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133,
+ VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134,
+ VK_FORMAT_BC2_UNORM_BLOCK = 135,
+ VK_FORMAT_BC2_SRGB_BLOCK = 136,
+ VK_FORMAT_BC3_UNORM_BLOCK = 137,
+ VK_FORMAT_BC3_SRGB_BLOCK = 138,
+ VK_FORMAT_BC4_UNORM_BLOCK = 139,
+ VK_FORMAT_BC4_SNORM_BLOCK = 140,
+ VK_FORMAT_BC5_UNORM_BLOCK = 141,
+ VK_FORMAT_BC5_SNORM_BLOCK = 142,
+ VK_FORMAT_BC6H_UFLOAT_BLOCK = 143,
+ VK_FORMAT_BC6H_SFLOAT_BLOCK = 144,
+ VK_FORMAT_BC7_UNORM_BLOCK = 145,
+ VK_FORMAT_BC7_SRGB_BLOCK = 146,
+ VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147,
+ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148,
+ VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149,
+ VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150,
+ VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151,
+ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152,
+ VK_FORMAT_EAC_R11_UNORM_BLOCK = 153,
+ VK_FORMAT_EAC_R11_SNORM_BLOCK = 154,
+ VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155,
+ VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156,
+ VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157,
+ VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158,
+ VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159,
+ VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160,
+ VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161,
+ VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162,
+ VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163,
+ VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164,
+ VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165,
+ VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166,
+ VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167,
+ VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168,
+ VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169,
+ VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170,
+ VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171,
+ VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172,
+ VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173,
+ VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174,
+ VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175,
+ VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176,
+ VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177,
+ VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178,
+ VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179,
+ VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180,
+ VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181,
+ VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182,
+ VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183,
+ VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184,
+ VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000,
+ VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001,
+ VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002,
+ VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003,
+ VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004,
+ VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005,
+ VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006,
+ VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007,
+ VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008,
+ VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009,
+ VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010,
+ VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012,
+ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014,
+ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016,
+ VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017,
+ VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018,
+ VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019,
+ VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020,
+ VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022,
+ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024,
+ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026,
+ VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027,
+ VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028,
+ VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029,
+ VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030,
+ VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031,
+ VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032,
+ VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033,
+ VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000,
+ VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001,
+ VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002,
+ VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003,
+ VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004,
+ VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005,
+ VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006,
+ VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007,
+ VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT = 1000066000,
+ VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT = 1000066001,
+ VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT = 1000066002,
+ VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT = 1000066003,
+ VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT = 1000066004,
+ VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT = 1000066005,
+ VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT = 1000066006,
+ VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT = 1000066007,
+ VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT = 1000066008,
+ VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT = 1000066009,
+ VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT = 1000066010,
+ VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT = 1000066011,
+ VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT = 1000066012,
+ VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT = 1000066013,
+ VK_FORMAT_G8B8G8R8_422_UNORM_KHR = VK_FORMAT_G8B8G8R8_422_UNORM,
+ VK_FORMAT_B8G8R8G8_422_UNORM_KHR = VK_FORMAT_B8G8R8G8_422_UNORM,
+ VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
+ VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
+ VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
+ VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
+ VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
+ VK_FORMAT_R10X6_UNORM_PACK16_KHR = VK_FORMAT_R10X6_UNORM_PACK16,
+ VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR = VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
+ VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
+ VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR = VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
+ VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
+ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
+ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
+ VK_FORMAT_R12X4_UNORM_PACK16_KHR = VK_FORMAT_R12X4_UNORM_PACK16,
+ VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR = VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
+ VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR = VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
+ VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR = VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
+ VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR = VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
+ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
+ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
+ VK_FORMAT_G16B16G16R16_422_UNORM_KHR = VK_FORMAT_G16B16G16R16_422_UNORM,
+ VK_FORMAT_B16G16R16G16_422_UNORM_KHR = VK_FORMAT_B16G16R16G16_422_UNORM,
+ VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
+ VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
+ VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
+ VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
+ VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
+ VK_FORMAT_BEGIN_RANGE = VK_FORMAT_UNDEFINED,
+ VK_FORMAT_END_RANGE = VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
+ VK_FORMAT_RANGE_SIZE = (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1),
+ VK_FORMAT_MAX_ENUM = 0x7FFFFFFF
+} VkFormat;
+
+typedef enum VkImageType {
+ VK_IMAGE_TYPE_1D = 0,
+ VK_IMAGE_TYPE_2D = 1,
+ VK_IMAGE_TYPE_3D = 2,
+ VK_IMAGE_TYPE_BEGIN_RANGE = VK_IMAGE_TYPE_1D,
+ VK_IMAGE_TYPE_END_RANGE = VK_IMAGE_TYPE_3D,
+ VK_IMAGE_TYPE_RANGE_SIZE = (VK_IMAGE_TYPE_3D - VK_IMAGE_TYPE_1D + 1),
+ VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkImageType;
+
+typedef enum VkImageTiling {
+ VK_IMAGE_TILING_OPTIMAL = 0,
+ VK_IMAGE_TILING_LINEAR = 1,
+ VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT = 1000158000,
+ VK_IMAGE_TILING_BEGIN_RANGE = VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_TILING_END_RANGE = VK_IMAGE_TILING_LINEAR,
+ VK_IMAGE_TILING_RANGE_SIZE = (VK_IMAGE_TILING_LINEAR - VK_IMAGE_TILING_OPTIMAL + 1),
+ VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF
+} VkImageTiling;
+
+typedef enum VkPhysicalDeviceType {
+ VK_PHYSICAL_DEVICE_TYPE_OTHER = 0,
+ VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1,
+ VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2,
+ VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3,
+ VK_PHYSICAL_DEVICE_TYPE_CPU = 4,
+ VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE = VK_PHYSICAL_DEVICE_TYPE_OTHER,
+ VK_PHYSICAL_DEVICE_TYPE_END_RANGE = VK_PHYSICAL_DEVICE_TYPE_CPU,
+ VK_PHYSICAL_DEVICE_TYPE_RANGE_SIZE = (VK_PHYSICAL_DEVICE_TYPE_CPU - VK_PHYSICAL_DEVICE_TYPE_OTHER + 1),
+ VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkPhysicalDeviceType;
+
+typedef enum VkQueryType {
+ VK_QUERY_TYPE_OCCLUSION = 0,
+ VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
+ VK_QUERY_TYPE_TIMESTAMP = 2,
+ VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004,
+ VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR = 1000116000,
+ VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000,
+ VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000,
+ VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION,
+ VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP,
+ VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1),
+ VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkQueryType;
+
+typedef enum VkSharingMode {
+ VK_SHARING_MODE_EXCLUSIVE = 0,
+ VK_SHARING_MODE_CONCURRENT = 1,
+ VK_SHARING_MODE_BEGIN_RANGE = VK_SHARING_MODE_EXCLUSIVE,
+ VK_SHARING_MODE_END_RANGE = VK_SHARING_MODE_CONCURRENT,
+ VK_SHARING_MODE_RANGE_SIZE = (VK_SHARING_MODE_CONCURRENT - VK_SHARING_MODE_EXCLUSIVE + 1),
+ VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkSharingMode;
+
+typedef enum VkImageLayout {
+ VK_IMAGE_LAYOUT_UNDEFINED = 0,
+ VK_IMAGE_LAYOUT_GENERAL = 1,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7,
+ VK_IMAGE_LAYOUT_PREINITIALIZED = 8,
+ VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000,
+ VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001,
+ VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000,
+ VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001,
+ VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002,
+ VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003,
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
+ VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000,
+ VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = 1000164003,
+ VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000,
+ VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_END_RANGE = VK_IMAGE_LAYOUT_PREINITIALIZED,
+ VK_IMAGE_LAYOUT_RANGE_SIZE = (VK_IMAGE_LAYOUT_PREINITIALIZED - VK_IMAGE_LAYOUT_UNDEFINED + 1),
+ VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF
+} VkImageLayout;
+
+typedef enum VkImageViewType {
+ VK_IMAGE_VIEW_TYPE_1D = 0,
+ VK_IMAGE_VIEW_TYPE_2D = 1,
+ VK_IMAGE_VIEW_TYPE_3D = 2,
+ VK_IMAGE_VIEW_TYPE_CUBE = 3,
+ VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4,
+ VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5,
+ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6,
+ VK_IMAGE_VIEW_TYPE_BEGIN_RANGE = VK_IMAGE_VIEW_TYPE_1D,
+ VK_IMAGE_VIEW_TYPE_END_RANGE = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,
+ VK_IMAGE_VIEW_TYPE_RANGE_SIZE = (VK_IMAGE_VIEW_TYPE_CUBE_ARRAY - VK_IMAGE_VIEW_TYPE_1D + 1),
+ VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkImageViewType;
+
+typedef enum VkComponentSwizzle {
+ VK_COMPONENT_SWIZZLE_IDENTITY = 0,
+ VK_COMPONENT_SWIZZLE_ZERO = 1,
+ VK_COMPONENT_SWIZZLE_ONE = 2,
+ VK_COMPONENT_SWIZZLE_R = 3,
+ VK_COMPONENT_SWIZZLE_G = 4,
+ VK_COMPONENT_SWIZZLE_B = 5,
+ VK_COMPONENT_SWIZZLE_A = 6,
+ VK_COMPONENT_SWIZZLE_BEGIN_RANGE = VK_COMPONENT_SWIZZLE_IDENTITY,
+ VK_COMPONENT_SWIZZLE_END_RANGE = VK_COMPONENT_SWIZZLE_A,
+ VK_COMPONENT_SWIZZLE_RANGE_SIZE = (VK_COMPONENT_SWIZZLE_A - VK_COMPONENT_SWIZZLE_IDENTITY + 1),
+ VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF
+} VkComponentSwizzle;
+
+typedef enum VkVertexInputRate {
+ VK_VERTEX_INPUT_RATE_VERTEX = 0,
+ VK_VERTEX_INPUT_RATE_INSTANCE = 1,
+ VK_VERTEX_INPUT_RATE_BEGIN_RANGE = VK_VERTEX_INPUT_RATE_VERTEX,
+ VK_VERTEX_INPUT_RATE_END_RANGE = VK_VERTEX_INPUT_RATE_INSTANCE,
+ VK_VERTEX_INPUT_RATE_RANGE_SIZE = (VK_VERTEX_INPUT_RATE_INSTANCE - VK_VERTEX_INPUT_RATE_VERTEX + 1),
+ VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF
+} VkVertexInputRate;
+
+typedef enum VkPrimitiveTopology {
+ VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0,
+ VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1,
+ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5,
+ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6,
+ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9,
+ VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10,
+ VK_PRIMITIVE_TOPOLOGY_BEGIN_RANGE = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
+ VK_PRIMITIVE_TOPOLOGY_END_RANGE = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
+ VK_PRIMITIVE_TOPOLOGY_RANGE_SIZE = (VK_PRIMITIVE_TOPOLOGY_PATCH_LIST - VK_PRIMITIVE_TOPOLOGY_POINT_LIST + 1),
+ VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF
+} VkPrimitiveTopology;
+
+typedef enum VkPolygonMode {
+ VK_POLYGON_MODE_FILL = 0,
+ VK_POLYGON_MODE_LINE = 1,
+ VK_POLYGON_MODE_POINT = 2,
+ VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000,
+ VK_POLYGON_MODE_BEGIN_RANGE = VK_POLYGON_MODE_FILL,
+ VK_POLYGON_MODE_END_RANGE = VK_POLYGON_MODE_POINT,
+ VK_POLYGON_MODE_RANGE_SIZE = (VK_POLYGON_MODE_POINT - VK_POLYGON_MODE_FILL + 1),
+ VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkPolygonMode;
+
+typedef enum VkFrontFace {
+ VK_FRONT_FACE_COUNTER_CLOCKWISE = 0,
+ VK_FRONT_FACE_CLOCKWISE = 1,
+ VK_FRONT_FACE_BEGIN_RANGE = VK_FRONT_FACE_COUNTER_CLOCKWISE,
+ VK_FRONT_FACE_END_RANGE = VK_FRONT_FACE_CLOCKWISE,
+ VK_FRONT_FACE_RANGE_SIZE = (VK_FRONT_FACE_CLOCKWISE - VK_FRONT_FACE_COUNTER_CLOCKWISE + 1),
+ VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF
+} VkFrontFace;
+
+typedef enum VkCompareOp {
+ VK_COMPARE_OP_NEVER = 0,
+ VK_COMPARE_OP_LESS = 1,
+ VK_COMPARE_OP_EQUAL = 2,
+ VK_COMPARE_OP_LESS_OR_EQUAL = 3,
+ VK_COMPARE_OP_GREATER = 4,
+ VK_COMPARE_OP_NOT_EQUAL = 5,
+ VK_COMPARE_OP_GREATER_OR_EQUAL = 6,
+ VK_COMPARE_OP_ALWAYS = 7,
+ VK_COMPARE_OP_BEGIN_RANGE = VK_COMPARE_OP_NEVER,
+ VK_COMPARE_OP_END_RANGE = VK_COMPARE_OP_ALWAYS,
+ VK_COMPARE_OP_RANGE_SIZE = (VK_COMPARE_OP_ALWAYS - VK_COMPARE_OP_NEVER + 1),
+ VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF
+} VkCompareOp;
+
+typedef enum VkStencilOp {
+ VK_STENCIL_OP_KEEP = 0,
+ VK_STENCIL_OP_ZERO = 1,
+ VK_STENCIL_OP_REPLACE = 2,
+ VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3,
+ VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4,
+ VK_STENCIL_OP_INVERT = 5,
+ VK_STENCIL_OP_INCREMENT_AND_WRAP = 6,
+ VK_STENCIL_OP_DECREMENT_AND_WRAP = 7,
+ VK_STENCIL_OP_BEGIN_RANGE = VK_STENCIL_OP_KEEP,
+ VK_STENCIL_OP_END_RANGE = VK_STENCIL_OP_DECREMENT_AND_WRAP,
+ VK_STENCIL_OP_RANGE_SIZE = (VK_STENCIL_OP_DECREMENT_AND_WRAP - VK_STENCIL_OP_KEEP + 1),
+ VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF
+} VkStencilOp;
+
+typedef enum VkLogicOp {
+ VK_LOGIC_OP_CLEAR = 0,
+ VK_LOGIC_OP_AND = 1,
+ VK_LOGIC_OP_AND_REVERSE = 2,
+ VK_LOGIC_OP_COPY = 3,
+ VK_LOGIC_OP_AND_INVERTED = 4,
+ VK_LOGIC_OP_NO_OP = 5,
+ VK_LOGIC_OP_XOR = 6,
+ VK_LOGIC_OP_OR = 7,
+ VK_LOGIC_OP_NOR = 8,
+ VK_LOGIC_OP_EQUIVALENT = 9,
+ VK_LOGIC_OP_INVERT = 10,
+ VK_LOGIC_OP_OR_REVERSE = 11,
+ VK_LOGIC_OP_COPY_INVERTED = 12,
+ VK_LOGIC_OP_OR_INVERTED = 13,
+ VK_LOGIC_OP_NAND = 14,
+ VK_LOGIC_OP_SET = 15,
+ VK_LOGIC_OP_BEGIN_RANGE = VK_LOGIC_OP_CLEAR,
+ VK_LOGIC_OP_END_RANGE = VK_LOGIC_OP_SET,
+ VK_LOGIC_OP_RANGE_SIZE = (VK_LOGIC_OP_SET - VK_LOGIC_OP_CLEAR + 1),
+ VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF
+} VkLogicOp;
+
+typedef enum VkBlendFactor {
+ VK_BLEND_FACTOR_ZERO = 0,
+ VK_BLEND_FACTOR_ONE = 1,
+ VK_BLEND_FACTOR_SRC_COLOR = 2,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3,
+ VK_BLEND_FACTOR_DST_COLOR = 4,
+ VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5,
+ VK_BLEND_FACTOR_SRC_ALPHA = 6,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7,
+ VK_BLEND_FACTOR_DST_ALPHA = 8,
+ VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9,
+ VK_BLEND_FACTOR_CONSTANT_COLOR = 10,
+ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11,
+ VK_BLEND_FACTOR_CONSTANT_ALPHA = 12,
+ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13,
+ VK_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14,
+ VK_BLEND_FACTOR_SRC1_COLOR = 15,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16,
+ VK_BLEND_FACTOR_SRC1_ALPHA = 17,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18,
+ VK_BLEND_FACTOR_BEGIN_RANGE = VK_BLEND_FACTOR_ZERO,
+ VK_BLEND_FACTOR_END_RANGE = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
+ VK_BLEND_FACTOR_RANGE_SIZE = (VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA - VK_BLEND_FACTOR_ZERO + 1),
+ VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF
+} VkBlendFactor;
+
+typedef enum VkBlendOp {
+ VK_BLEND_OP_ADD = 0,
+ VK_BLEND_OP_SUBTRACT = 1,
+ VK_BLEND_OP_REVERSE_SUBTRACT = 2,
+ VK_BLEND_OP_MIN = 3,
+ VK_BLEND_OP_MAX = 4,
+ VK_BLEND_OP_ZERO_EXT = 1000148000,
+ VK_BLEND_OP_SRC_EXT = 1000148001,
+ VK_BLEND_OP_DST_EXT = 1000148002,
+ VK_BLEND_OP_SRC_OVER_EXT = 1000148003,
+ VK_BLEND_OP_DST_OVER_EXT = 1000148004,
+ VK_BLEND_OP_SRC_IN_EXT = 1000148005,
+ VK_BLEND_OP_DST_IN_EXT = 1000148006,
+ VK_BLEND_OP_SRC_OUT_EXT = 1000148007,
+ VK_BLEND_OP_DST_OUT_EXT = 1000148008,
+ VK_BLEND_OP_SRC_ATOP_EXT = 1000148009,
+ VK_BLEND_OP_DST_ATOP_EXT = 1000148010,
+ VK_BLEND_OP_XOR_EXT = 1000148011,
+ VK_BLEND_OP_MULTIPLY_EXT = 1000148012,
+ VK_BLEND_OP_SCREEN_EXT = 1000148013,
+ VK_BLEND_OP_OVERLAY_EXT = 1000148014,
+ VK_BLEND_OP_DARKEN_EXT = 1000148015,
+ VK_BLEND_OP_LIGHTEN_EXT = 1000148016,
+ VK_BLEND_OP_COLORDODGE_EXT = 1000148017,
+ VK_BLEND_OP_COLORBURN_EXT = 1000148018,
+ VK_BLEND_OP_HARDLIGHT_EXT = 1000148019,
+ VK_BLEND_OP_SOFTLIGHT_EXT = 1000148020,
+ VK_BLEND_OP_DIFFERENCE_EXT = 1000148021,
+ VK_BLEND_OP_EXCLUSION_EXT = 1000148022,
+ VK_BLEND_OP_INVERT_EXT = 1000148023,
+ VK_BLEND_OP_INVERT_RGB_EXT = 1000148024,
+ VK_BLEND_OP_LINEARDODGE_EXT = 1000148025,
+ VK_BLEND_OP_LINEARBURN_EXT = 1000148026,
+ VK_BLEND_OP_VIVIDLIGHT_EXT = 1000148027,
+ VK_BLEND_OP_LINEARLIGHT_EXT = 1000148028,
+ VK_BLEND_OP_PINLIGHT_EXT = 1000148029,
+ VK_BLEND_OP_HARDMIX_EXT = 1000148030,
+ VK_BLEND_OP_HSL_HUE_EXT = 1000148031,
+ VK_BLEND_OP_HSL_SATURATION_EXT = 1000148032,
+ VK_BLEND_OP_HSL_COLOR_EXT = 1000148033,
+ VK_BLEND_OP_HSL_LUMINOSITY_EXT = 1000148034,
+ VK_BLEND_OP_PLUS_EXT = 1000148035,
+ VK_BLEND_OP_PLUS_CLAMPED_EXT = 1000148036,
+ VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT = 1000148037,
+ VK_BLEND_OP_PLUS_DARKER_EXT = 1000148038,
+ VK_BLEND_OP_MINUS_EXT = 1000148039,
+ VK_BLEND_OP_MINUS_CLAMPED_EXT = 1000148040,
+ VK_BLEND_OP_CONTRAST_EXT = 1000148041,
+ VK_BLEND_OP_INVERT_OVG_EXT = 1000148042,
+ VK_BLEND_OP_RED_EXT = 1000148043,
+ VK_BLEND_OP_GREEN_EXT = 1000148044,
+ VK_BLEND_OP_BLUE_EXT = 1000148045,
+ VK_BLEND_OP_BEGIN_RANGE = VK_BLEND_OP_ADD,
+ VK_BLEND_OP_END_RANGE = VK_BLEND_OP_MAX,
+ VK_BLEND_OP_RANGE_SIZE = (VK_BLEND_OP_MAX - VK_BLEND_OP_ADD + 1),
+ VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF
+} VkBlendOp;
+
+typedef enum VkDynamicState {
+ VK_DYNAMIC_STATE_VIEWPORT = 0,
+ VK_DYNAMIC_STATE_SCISSOR = 1,
+ VK_DYNAMIC_STATE_LINE_WIDTH = 2,
+ VK_DYNAMIC_STATE_DEPTH_BIAS = 3,
+ VK_DYNAMIC_STATE_BLEND_CONSTANTS = 4,
+ VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5,
+ VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6,
+ VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7,
+ VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8,
+ VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000,
+ VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000,
+ VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000,
+ VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004,
+ VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006,
+ VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001,
+ VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000,
+ VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE,
+ VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1),
+ VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF
+} VkDynamicState;
+
+typedef enum VkFilter {
+ VK_FILTER_NEAREST = 0,
+ VK_FILTER_LINEAR = 1,
+ VK_FILTER_CUBIC_IMG = 1000015000,
+ VK_FILTER_CUBIC_EXT = VK_FILTER_CUBIC_IMG,
+ VK_FILTER_BEGIN_RANGE = VK_FILTER_NEAREST,
+ VK_FILTER_END_RANGE = VK_FILTER_LINEAR,
+ VK_FILTER_RANGE_SIZE = (VK_FILTER_LINEAR - VK_FILTER_NEAREST + 1),
+ VK_FILTER_MAX_ENUM = 0x7FFFFFFF
+} VkFilter;
+
+typedef enum VkSamplerMipmapMode {
+ VK_SAMPLER_MIPMAP_MODE_NEAREST = 0,
+ VK_SAMPLER_MIPMAP_MODE_LINEAR = 1,
+ VK_SAMPLER_MIPMAP_MODE_BEGIN_RANGE = VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_MIPMAP_MODE_END_RANGE = VK_SAMPLER_MIPMAP_MODE_LINEAR,
+ VK_SAMPLER_MIPMAP_MODE_RANGE_SIZE = (VK_SAMPLER_MIPMAP_MODE_LINEAR - VK_SAMPLER_MIPMAP_MODE_NEAREST + 1),
+ VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerMipmapMode;
+
+typedef enum VkSamplerAddressMode {
+ VK_SAMPLER_ADDRESS_MODE_REPEAT = 0,
+ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3,
+ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4,
+ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
+ VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+ VK_SAMPLER_ADDRESS_MODE_END_RANGE = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
+ VK_SAMPLER_ADDRESS_MODE_RANGE_SIZE = (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER - VK_SAMPLER_ADDRESS_MODE_REPEAT + 1),
+ VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerAddressMode;
+
+typedef enum VkBorderColor {
+ VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0,
+ VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1,
+ VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2,
+ VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3,
+ VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4,
+ VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5,
+ VK_BORDER_COLOR_BEGIN_RANGE = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
+ VK_BORDER_COLOR_END_RANGE = VK_BORDER_COLOR_INT_OPAQUE_WHITE,
+ VK_BORDER_COLOR_RANGE_SIZE = (VK_BORDER_COLOR_INT_OPAQUE_WHITE - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK + 1),
+ VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF
+} VkBorderColor;
+
+typedef enum VkDescriptorType {
+ VK_DESCRIPTOR_TYPE_SAMPLER = 0,
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1,
+ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2,
+ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3,
+ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4,
+ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6,
+ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
+ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
+ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
+ VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
+ VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
+ VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER,
+ VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1),
+ VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorType;
+
+typedef enum VkAttachmentLoadOp {
+ VK_ATTACHMENT_LOAD_OP_LOAD = 0,
+ VK_ATTACHMENT_LOAD_OP_CLEAR = 1,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2,
+ VK_ATTACHMENT_LOAD_OP_BEGIN_RANGE = VK_ATTACHMENT_LOAD_OP_LOAD,
+ VK_ATTACHMENT_LOAD_OP_END_RANGE = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_LOAD_OP_RANGE_SIZE = (VK_ATTACHMENT_LOAD_OP_DONT_CARE - VK_ATTACHMENT_LOAD_OP_LOAD + 1),
+ VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF
+} VkAttachmentLoadOp;
+
+typedef enum VkAttachmentStoreOp {
+ VK_ATTACHMENT_STORE_OP_STORE = 0,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE = 1,
+ VK_ATTACHMENT_STORE_OP_BEGIN_RANGE = VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_STORE_OP_END_RANGE = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_RANGE_SIZE = (VK_ATTACHMENT_STORE_OP_DONT_CARE - VK_ATTACHMENT_STORE_OP_STORE + 1),
+ VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF
+} VkAttachmentStoreOp;
+
+typedef enum VkPipelineBindPoint {
+ VK_PIPELINE_BIND_POINT_GRAPHICS = 0,
+ VK_PIPELINE_BIND_POINT_COMPUTE = 1,
+ VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = 1000165000,
+ VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS,
+ VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE,
+ VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1),
+ VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineBindPoint;
+
+typedef enum VkCommandBufferLevel {
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0,
+ VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1,
+ VK_COMMAND_BUFFER_LEVEL_BEGIN_RANGE = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ VK_COMMAND_BUFFER_LEVEL_END_RANGE = VK_COMMAND_BUFFER_LEVEL_SECONDARY,
+ VK_COMMAND_BUFFER_LEVEL_RANGE_SIZE = (VK_COMMAND_BUFFER_LEVEL_SECONDARY - VK_COMMAND_BUFFER_LEVEL_PRIMARY + 1),
+ VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF
+} VkCommandBufferLevel;
+
+typedef enum VkIndexType {
+ VK_INDEX_TYPE_UINT16 = 0,
+ VK_INDEX_TYPE_UINT32 = 1,
+ VK_INDEX_TYPE_NONE_NV = 1000165000,
+ VK_INDEX_TYPE_UINT8_EXT = 1000265000,
+ VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16,
+ VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32,
+ VK_INDEX_TYPE_RANGE_SIZE = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1),
+ VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkIndexType;
+
+typedef enum VkSubpassContents {
+ VK_SUBPASS_CONTENTS_INLINE = 0,
+ VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1,
+ VK_SUBPASS_CONTENTS_BEGIN_RANGE = VK_SUBPASS_CONTENTS_INLINE,
+ VK_SUBPASS_CONTENTS_END_RANGE = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS,
+ VK_SUBPASS_CONTENTS_RANGE_SIZE = (VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS - VK_SUBPASS_CONTENTS_INLINE + 1),
+ VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF
+} VkSubpassContents;
+
+typedef enum VkObjectType {
+ VK_OBJECT_TYPE_UNKNOWN = 0,
+ VK_OBJECT_TYPE_INSTANCE = 1,
+ VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2,
+ VK_OBJECT_TYPE_DEVICE = 3,
+ VK_OBJECT_TYPE_QUEUE = 4,
+ VK_OBJECT_TYPE_SEMAPHORE = 5,
+ VK_OBJECT_TYPE_COMMAND_BUFFER = 6,
+ VK_OBJECT_TYPE_FENCE = 7,
+ VK_OBJECT_TYPE_DEVICE_MEMORY = 8,
+ VK_OBJECT_TYPE_BUFFER = 9,
+ VK_OBJECT_TYPE_IMAGE = 10,
+ VK_OBJECT_TYPE_EVENT = 11,
+ VK_OBJECT_TYPE_QUERY_POOL = 12,
+ VK_OBJECT_TYPE_BUFFER_VIEW = 13,
+ VK_OBJECT_TYPE_IMAGE_VIEW = 14,
+ VK_OBJECT_TYPE_SHADER_MODULE = 15,
+ VK_OBJECT_TYPE_PIPELINE_CACHE = 16,
+ VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17,
+ VK_OBJECT_TYPE_RENDER_PASS = 18,
+ VK_OBJECT_TYPE_PIPELINE = 19,
+ VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20,
+ VK_OBJECT_TYPE_SAMPLER = 21,
+ VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22,
+ VK_OBJECT_TYPE_DESCRIPTOR_SET = 23,
+ VK_OBJECT_TYPE_FRAMEBUFFER = 24,
+ VK_OBJECT_TYPE_COMMAND_POOL = 25,
+ VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000,
+ VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000,
+ VK_OBJECT_TYPE_SURFACE_KHR = 1000000000,
+ VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000,
+ VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000,
+ VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001,
+ VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000,
+ VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000,
+ VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
+ VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000,
+ VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
+ VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
+ VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000,
+ VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE,
+ VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
+ VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN,
+ VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL,
+ VK_OBJECT_TYPE_RANGE_SIZE = (VK_OBJECT_TYPE_COMMAND_POOL - VK_OBJECT_TYPE_UNKNOWN + 1),
+ VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkObjectType;
+
+typedef enum VkVendorId {
+ VK_VENDOR_ID_VIV = 0x10001,
+ VK_VENDOR_ID_VSI = 0x10002,
+ VK_VENDOR_ID_KAZAN = 0x10003,
+ VK_VENDOR_ID_BEGIN_RANGE = VK_VENDOR_ID_VIV,
+ VK_VENDOR_ID_END_RANGE = VK_VENDOR_ID_KAZAN,
+ VK_VENDOR_ID_RANGE_SIZE = (VK_VENDOR_ID_KAZAN - VK_VENDOR_ID_VIV + 1),
+ VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF
+} VkVendorId;
+typedef VkFlags VkInstanceCreateFlags;
+
+typedef enum VkFormatFeatureFlagBits {
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001,
+ VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002,
+ VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004,
+ VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008,
+ VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0x00000010,
+ VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020,
+ VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0x00000040,
+ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0x00000080,
+ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100,
+ VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200,
+ VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400,
+ VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
+ VK_FORMAT_FEATURE_TRANSFER_SRC_BIT = 0x00004000,
+ VK_FORMAT_FEATURE_TRANSFER_DST_BIT = 0x00008000,
+ VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT = 0x00020000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0x00040000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0x00080000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0x00100000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000,
+ VK_FORMAT_FEATURE_DISJOINT_BIT = 0x00400000,
+ VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
+ VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000,
+ VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT,
+ VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT,
+ VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT,
+ VK_FORMAT_FEATURE_DISJOINT_BIT_KHR = VK_FORMAT_FEATURE_DISJOINT_BIT,
+ VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG,
+ VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkFormatFeatureFlagBits;
+typedef VkFlags VkFormatFeatureFlags;
+
+typedef enum VkImageUsageFlagBits {
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001,
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002,
+ VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004,
+ VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020,
+ VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,
+ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,
+ VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100,
+ VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200,
+ VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkImageUsageFlagBits;
+typedef VkFlags VkImageUsageFlags;
+
+typedef enum VkImageCreateFlagBits {
+ VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001,
+ VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
+ VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+ VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
+ VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
+ VK_IMAGE_CREATE_ALIAS_BIT = 0x00000400,
+ VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT = 0x00000040,
+ VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT = 0x00000020,
+ VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 0x00000080,
+ VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100,
+ VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800,
+ VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200,
+ VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000,
+ VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
+ VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT = 0x00004000,
+ VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT,
+ VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT,
+ VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT,
+ VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR = VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
+ VK_IMAGE_CREATE_DISJOINT_BIT_KHR = VK_IMAGE_CREATE_DISJOINT_BIT,
+ VK_IMAGE_CREATE_ALIAS_BIT_KHR = VK_IMAGE_CREATE_ALIAS_BIT,
+ VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkImageCreateFlagBits;
+typedef VkFlags VkImageCreateFlags;
+
+typedef enum VkSampleCountFlagBits {
+ VK_SAMPLE_COUNT_1_BIT = 0x00000001,
+ VK_SAMPLE_COUNT_2_BIT = 0x00000002,
+ VK_SAMPLE_COUNT_4_BIT = 0x00000004,
+ VK_SAMPLE_COUNT_8_BIT = 0x00000008,
+ VK_SAMPLE_COUNT_16_BIT = 0x00000010,
+ VK_SAMPLE_COUNT_32_BIT = 0x00000020,
+ VK_SAMPLE_COUNT_64_BIT = 0x00000040,
+ VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSampleCountFlagBits;
+typedef VkFlags VkSampleCountFlags;
+
+typedef enum VkQueueFlagBits {
+ VK_QUEUE_GRAPHICS_BIT = 0x00000001,
+ VK_QUEUE_COMPUTE_BIT = 0x00000002,
+ VK_QUEUE_TRANSFER_BIT = 0x00000004,
+ VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008,
+ VK_QUEUE_PROTECTED_BIT = 0x00000010,
+ VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkQueueFlagBits;
+typedef VkFlags VkQueueFlags;
+
+typedef enum VkMemoryPropertyFlagBits {
+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002,
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
+ VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
+ VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
+ VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020,
+ VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD = 0x00000040,
+ VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD = 0x00000080,
+ VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkMemoryPropertyFlagBits;
+typedef VkFlags VkMemoryPropertyFlags;
+
+typedef enum VkMemoryHeapFlagBits {
+ VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
+ VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002,
+ VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT,
+ VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkMemoryHeapFlagBits;
+typedef VkFlags VkMemoryHeapFlags;
+typedef VkFlags VkDeviceCreateFlags;
+
+typedef enum VkDeviceQueueCreateFlagBits {
+ VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 0x00000001,
+ VK_DEVICE_QUEUE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkDeviceQueueCreateFlagBits;
+typedef VkFlags VkDeviceQueueCreateFlags;
+
+typedef enum VkPipelineStageFlagBits {
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001,
+ VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002,
+ VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004,
+ VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008,
+ VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010,
+ VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020,
+ VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080,
+ VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100,
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400,
+ VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800,
+ VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000,
+ VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
+ VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000,
+ VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000,
+ VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000,
+ VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000,
+ VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = 0x00200000,
+ VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000,
+ VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000,
+ VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000,
+ VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000,
+ VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineStageFlagBits;
+typedef VkFlags VkPipelineStageFlags;
+typedef VkFlags VkMemoryMapFlags;
+
+typedef enum VkImageAspectFlagBits {
+ VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001,
+ VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002,
+ VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004,
+ VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008,
+ VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010,
+ VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020,
+ VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040,
+ VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0x00000080,
+ VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0x00000100,
+ VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0x00000200,
+ VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0x00000400,
+ VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT,
+ VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT,
+ VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT,
+ VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkImageAspectFlagBits;
+typedef VkFlags VkImageAspectFlags;
+
+typedef enum VkSparseImageFormatFlagBits {
+ VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001,
+ VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0x00000002,
+ VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0x00000004,
+ VK_SPARSE_IMAGE_FORMAT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSparseImageFormatFlagBits;
+typedef VkFlags VkSparseImageFormatFlags;
+
+typedef enum VkSparseMemoryBindFlagBits {
+ VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001,
+ VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSparseMemoryBindFlagBits;
+typedef VkFlags VkSparseMemoryBindFlags;
+
+typedef enum VkFenceCreateFlagBits {
+ VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001,
+ VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkFenceCreateFlagBits;
+typedef VkFlags VkFenceCreateFlags;
+typedef VkFlags VkSemaphoreCreateFlags;
+typedef VkFlags VkEventCreateFlags;
+typedef VkFlags VkQueryPoolCreateFlags;
+
+typedef enum VkQueryPipelineStatisticFlagBits {
+ VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001,
+ VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0x00000002,
+ VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0x00000004,
+ VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0x00000008,
+ VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0x00000010,
+ VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0x00000020,
+ VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0x00000040,
+ VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0x00000080,
+ VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100,
+ VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200,
+ VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400,
+ VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkQueryPipelineStatisticFlagBits;
+typedef VkFlags VkQueryPipelineStatisticFlags;
+
+typedef enum VkQueryResultFlagBits {
+ VK_QUERY_RESULT_64_BIT = 0x00000001,
+ VK_QUERY_RESULT_WAIT_BIT = 0x00000002,
+ VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004,
+ VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008,
+ VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkQueryResultFlagBits;
+typedef VkFlags VkQueryResultFlags;
+
+typedef enum VkBufferCreateFlagBits {
+ VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001,
+ VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
+ VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+ VK_BUFFER_CREATE_PROTECTED_BIT = 0x00000008,
+ VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000010,
+ VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT,
+ VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT,
+ VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkBufferCreateFlagBits;
+typedef VkFlags VkBufferCreateFlags;
+
+typedef enum VkBufferUsageFlagBits {
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 0x00000001,
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT = 0x00000002,
+ VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004,
+ VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008,
+ VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010,
+ VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020,
+ VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040,
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080,
+ VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100,
+ VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT = 0x00020000,
+ VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800,
+ VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000,
+ VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200,
+ VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = 0x00000400,
+ VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+ VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+ VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkBufferUsageFlagBits;
+typedef VkFlags VkBufferUsageFlags;
+typedef VkFlags VkBufferViewCreateFlags;
+
+typedef enum VkImageViewCreateFlagBits {
+ VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0x00000001,
+ VK_IMAGE_VIEW_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkImageViewCreateFlagBits;
+typedef VkFlags VkImageViewCreateFlags;
+
+typedef enum VkShaderModuleCreateFlagBits {
+ VK_SHADER_MODULE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkShaderModuleCreateFlagBits;
+typedef VkFlags VkShaderModuleCreateFlags;
+typedef VkFlags VkPipelineCacheCreateFlags;
+
+typedef enum VkPipelineCreateFlagBits {
+ VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001,
+ VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
+ VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
+ VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008,
+ VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010,
+ VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020,
+ VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR = 0x00000040,
+ VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080,
+ VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT,
+ VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT,
+ VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE,
+ VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineCreateFlagBits;
+typedef VkFlags VkPipelineCreateFlags;
+
+typedef enum VkPipelineShaderStageCreateFlagBits {
+ VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = 0x00000001,
+ VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = 0x00000002,
+ VK_PIPELINE_SHADER_STAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineShaderStageCreateFlagBits;
+typedef VkFlags VkPipelineShaderStageCreateFlags;
+
+typedef enum VkShaderStageFlagBits {
+ VK_SHADER_STAGE_VERTEX_BIT = 0x00000001,
+ VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002,
+ VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004,
+ VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008,
+ VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010,
+ VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020,
+ VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F,
+ VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
+ VK_SHADER_STAGE_RAYGEN_BIT_NV = 0x00000100,
+ VK_SHADER_STAGE_ANY_HIT_BIT_NV = 0x00000200,
+ VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = 0x00000400,
+ VK_SHADER_STAGE_MISS_BIT_NV = 0x00000800,
+ VK_SHADER_STAGE_INTERSECTION_BIT_NV = 0x00001000,
+ VK_SHADER_STAGE_CALLABLE_BIT_NV = 0x00002000,
+ VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040,
+ VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080,
+ VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkShaderStageFlagBits;
+typedef VkFlags VkPipelineVertexInputStateCreateFlags;
+typedef VkFlags VkPipelineInputAssemblyStateCreateFlags;
+typedef VkFlags VkPipelineTessellationStateCreateFlags;
+typedef VkFlags VkPipelineViewportStateCreateFlags;
+typedef VkFlags VkPipelineRasterizationStateCreateFlags;
+
+typedef enum VkCullModeFlagBits {
+ VK_CULL_MODE_NONE = 0,
+ VK_CULL_MODE_FRONT_BIT = 0x00000001,
+ VK_CULL_MODE_BACK_BIT = 0x00000002,
+ VK_CULL_MODE_FRONT_AND_BACK = 0x00000003,
+ VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkCullModeFlagBits;
+typedef VkFlags VkCullModeFlags;
+typedef VkFlags VkPipelineMultisampleStateCreateFlags;
+typedef VkFlags VkPipelineDepthStencilStateCreateFlags;
+typedef VkFlags VkPipelineColorBlendStateCreateFlags;
+
+typedef enum VkColorComponentFlagBits {
+ VK_COLOR_COMPONENT_R_BIT = 0x00000001,
+ VK_COLOR_COMPONENT_G_BIT = 0x00000002,
+ VK_COLOR_COMPONENT_B_BIT = 0x00000004,
+ VK_COLOR_COMPONENT_A_BIT = 0x00000008,
+ VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkColorComponentFlagBits;
+typedef VkFlags VkColorComponentFlags;
+typedef VkFlags VkPipelineDynamicStateCreateFlags;
+typedef VkFlags VkPipelineLayoutCreateFlags;
+typedef VkFlags VkShaderStageFlags;
+
+typedef enum VkSamplerCreateFlagBits {
+ VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0x00000001,
+ VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0x00000002,
+ VK_SAMPLER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerCreateFlagBits;
+typedef VkFlags VkSamplerCreateFlags;
+
+typedef enum VkDescriptorSetLayoutCreateFlagBits {
+ VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0x00000002,
+ VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001,
+ VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
+ VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorSetLayoutCreateFlagBits;
+typedef VkFlags VkDescriptorSetLayoutCreateFlags;
+
+typedef enum VkDescriptorPoolCreateFlagBits {
+ VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001,
+ VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0x00000002,
+ VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
+ VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorPoolCreateFlagBits;
+typedef VkFlags VkDescriptorPoolCreateFlags;
+typedef VkFlags VkDescriptorPoolResetFlags;
+
+typedef enum VkFramebufferCreateFlagBits {
+ VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 0x00000001,
+ VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT,
+ VK_FRAMEBUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkFramebufferCreateFlagBits;
+typedef VkFlags VkFramebufferCreateFlags;
+
+typedef enum VkRenderPassCreateFlagBits {
+ VK_RENDER_PASS_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkRenderPassCreateFlagBits;
+typedef VkFlags VkRenderPassCreateFlags;
+
+typedef enum VkAttachmentDescriptionFlagBits {
+ VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001,
+ VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkAttachmentDescriptionFlagBits;
+typedef VkFlags VkAttachmentDescriptionFlags;
+
+typedef enum VkSubpassDescriptionFlagBits {
+ VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001,
+ VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002,
+ VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSubpassDescriptionFlagBits;
+typedef VkFlags VkSubpassDescriptionFlags;
+
+typedef enum VkAccessFlagBits {
+ VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001,
+ VK_ACCESS_INDEX_READ_BIT = 0x00000002,
+ VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004,
+ VK_ACCESS_UNIFORM_READ_BIT = 0x00000008,
+ VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010,
+ VK_ACCESS_SHADER_READ_BIT = 0x00000020,
+ VK_ACCESS_SHADER_WRITE_BIT = 0x00000040,
+ VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080,
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100,
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200,
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400,
+ VK_ACCESS_TRANSFER_READ_BIT = 0x00000800,
+ VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000,
+ VK_ACCESS_HOST_READ_BIT = 0x00002000,
+ VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
+ VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
+ VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
+ VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000,
+ VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000,
+ VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000,
+ VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000,
+ VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000,
+ VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000,
+ VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000,
+ VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000,
+ VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000,
+ VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000,
+ VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000,
+ VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkAccessFlagBits;
+typedef VkFlags VkAccessFlags;
+
+typedef enum VkDependencyFlagBits {
+ VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
+ VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004,
+ VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002,
+ VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = VK_DEPENDENCY_VIEW_LOCAL_BIT,
+ VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = VK_DEPENDENCY_DEVICE_GROUP_BIT,
+ VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkDependencyFlagBits;
+typedef VkFlags VkDependencyFlags;
+
+typedef enum VkCommandPoolCreateFlagBits {
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001,
+ VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,
+ VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004,
+ VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkCommandPoolCreateFlagBits;
+typedef VkFlags VkCommandPoolCreateFlags;
+
+typedef enum VkCommandPoolResetFlagBits {
+ VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
+ VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkCommandPoolResetFlagBits;
+typedef VkFlags VkCommandPoolResetFlags;
+
+typedef enum VkCommandBufferUsageFlagBits {
+ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001,
+ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002,
+ VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004,
+ VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkCommandBufferUsageFlagBits;
+typedef VkFlags VkCommandBufferUsageFlags;
+
+typedef enum VkQueryControlFlagBits {
+ VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001,
+ VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkQueryControlFlagBits;
+typedef VkFlags VkQueryControlFlags;
+
+typedef enum VkCommandBufferResetFlagBits {
+ VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
+ VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkCommandBufferResetFlagBits;
+typedef VkFlags VkCommandBufferResetFlags;
+
+typedef enum VkStencilFaceFlagBits {
+ VK_STENCIL_FACE_FRONT_BIT = 0x00000001,
+ VK_STENCIL_FACE_BACK_BIT = 0x00000002,
+ VK_STENCIL_FACE_FRONT_AND_BACK = 0x00000003,
+ VK_STENCIL_FRONT_AND_BACK = VK_STENCIL_FACE_FRONT_AND_BACK,
+ VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkStencilFaceFlagBits;
+typedef VkFlags VkStencilFaceFlags;
+typedef struct VkApplicationInfo {
+ VkStructureType sType;
+ const void* pNext;
+ const char* pApplicationName;
+ uint32_t applicationVersion;
+ const char* pEngineName;
+ uint32_t engineVersion;
+ uint32_t apiVersion;
+} VkApplicationInfo;
+
+typedef struct VkInstanceCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkInstanceCreateFlags flags;
+ const VkApplicationInfo* pApplicationInfo;
+ uint32_t enabledLayerCount;
+ const char* const* ppEnabledLayerNames;
+ uint32_t enabledExtensionCount;
+ const char* const* ppEnabledExtensionNames;
+} VkInstanceCreateInfo;
+
+typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)(
+ void* pUserData,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope allocationScope);
+
+typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)(
+ void* pUserData,
+ void* pOriginal,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope allocationScope);
+
+typedef void (VKAPI_PTR *PFN_vkFreeFunction)(
+ void* pUserData,
+ void* pMemory);
+
+typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)(
+ void* pUserData,
+ size_t size,
+ VkInternalAllocationType allocationType,
+ VkSystemAllocationScope allocationScope);
+
+typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)(
+ void* pUserData,
+ size_t size,
+ VkInternalAllocationType allocationType,
+ VkSystemAllocationScope allocationScope);
+
+typedef struct VkAllocationCallbacks {
+ void* pUserData;
+ PFN_vkAllocationFunction pfnAllocation;
+ PFN_vkReallocationFunction pfnReallocation;
+ PFN_vkFreeFunction pfnFree;
+ PFN_vkInternalAllocationNotification pfnInternalAllocation;
+ PFN_vkInternalFreeNotification pfnInternalFree;
+} VkAllocationCallbacks;
+
+typedef struct VkPhysicalDeviceFeatures {
+ VkBool32 robustBufferAccess;
+ VkBool32 fullDrawIndexUint32;
+ VkBool32 imageCubeArray;
+ VkBool32 independentBlend;
+ VkBool32 geometryShader;
+ VkBool32 tessellationShader;
+ VkBool32 sampleRateShading;
+ VkBool32 dualSrcBlend;
+ VkBool32 logicOp;
+ VkBool32 multiDrawIndirect;
+ VkBool32 drawIndirectFirstInstance;
+ VkBool32 depthClamp;
+ VkBool32 depthBiasClamp;
+ VkBool32 fillModeNonSolid;
+ VkBool32 depthBounds;
+ VkBool32 wideLines;
+ VkBool32 largePoints;
+ VkBool32 alphaToOne;
+ VkBool32 multiViewport;
+ VkBool32 samplerAnisotropy;
+ VkBool32 textureCompressionETC2;
+ VkBool32 textureCompressionASTC_LDR;
+ VkBool32 textureCompressionBC;
+ VkBool32 occlusionQueryPrecise;
+ VkBool32 pipelineStatisticsQuery;
+ VkBool32 vertexPipelineStoresAndAtomics;
+ VkBool32 fragmentStoresAndAtomics;
+ VkBool32 shaderTessellationAndGeometryPointSize;
+ VkBool32 shaderImageGatherExtended;
+ VkBool32 shaderStorageImageExtendedFormats;
+ VkBool32 shaderStorageImageMultisample;
+ VkBool32 shaderStorageImageReadWithoutFormat;
+ VkBool32 shaderStorageImageWriteWithoutFormat;
+ VkBool32 shaderUniformBufferArrayDynamicIndexing;
+ VkBool32 shaderSampledImageArrayDynamicIndexing;
+ VkBool32 shaderStorageBufferArrayDynamicIndexing;
+ VkBool32 shaderStorageImageArrayDynamicIndexing;
+ VkBool32 shaderClipDistance;
+ VkBool32 shaderCullDistance;
+ VkBool32 shaderFloat64;
+ VkBool32 shaderInt64;
+ VkBool32 shaderInt16;
+ VkBool32 shaderResourceResidency;
+ VkBool32 shaderResourceMinLod;
+ VkBool32 sparseBinding;
+ VkBool32 sparseResidencyBuffer;
+ VkBool32 sparseResidencyImage2D;
+ VkBool32 sparseResidencyImage3D;
+ VkBool32 sparseResidency2Samples;
+ VkBool32 sparseResidency4Samples;
+ VkBool32 sparseResidency8Samples;
+ VkBool32 sparseResidency16Samples;
+ VkBool32 sparseResidencyAliased;
+ VkBool32 variableMultisampleRate;
+ VkBool32 inheritedQueries;
+} VkPhysicalDeviceFeatures;
+
+typedef struct VkFormatProperties {
+ VkFormatFeatureFlags linearTilingFeatures;
+ VkFormatFeatureFlags optimalTilingFeatures;
+ VkFormatFeatureFlags bufferFeatures;
+} VkFormatProperties;
+
+typedef struct VkExtent3D {
+ uint32_t width;
+ uint32_t height;
+ uint32_t depth;
+} VkExtent3D;
+
+typedef struct VkImageFormatProperties {
+ VkExtent3D maxExtent;
+ uint32_t maxMipLevels;
+ uint32_t maxArrayLayers;
+ VkSampleCountFlags sampleCounts;
+ VkDeviceSize maxResourceSize;
+} VkImageFormatProperties;
+
+typedef struct VkPhysicalDeviceLimits {
+ uint32_t maxImageDimension1D;
+ uint32_t maxImageDimension2D;
+ uint32_t maxImageDimension3D;
+ uint32_t maxImageDimensionCube;
+ uint32_t maxImageArrayLayers;
+ uint32_t maxTexelBufferElements;
+ uint32_t maxUniformBufferRange;
+ uint32_t maxStorageBufferRange;
+ uint32_t maxPushConstantsSize;
+ uint32_t maxMemoryAllocationCount;
+ uint32_t maxSamplerAllocationCount;
+ VkDeviceSize bufferImageGranularity;
+ VkDeviceSize sparseAddressSpaceSize;
+ uint32_t maxBoundDescriptorSets;
+ uint32_t maxPerStageDescriptorSamplers;
+ uint32_t maxPerStageDescriptorUniformBuffers;
+ uint32_t maxPerStageDescriptorStorageBuffers;
+ uint32_t maxPerStageDescriptorSampledImages;
+ uint32_t maxPerStageDescriptorStorageImages;
+ uint32_t maxPerStageDescriptorInputAttachments;
+ uint32_t maxPerStageResources;
+ uint32_t maxDescriptorSetSamplers;
+ uint32_t maxDescriptorSetUniformBuffers;
+ uint32_t maxDescriptorSetUniformBuffersDynamic;
+ uint32_t maxDescriptorSetStorageBuffers;
+ uint32_t maxDescriptorSetStorageBuffersDynamic;
+ uint32_t maxDescriptorSetSampledImages;
+ uint32_t maxDescriptorSetStorageImages;
+ uint32_t maxDescriptorSetInputAttachments;
+ uint32_t maxVertexInputAttributes;
+ uint32_t maxVertexInputBindings;
+ uint32_t maxVertexInputAttributeOffset;
+ uint32_t maxVertexInputBindingStride;
+ uint32_t maxVertexOutputComponents;
+ uint32_t maxTessellationGenerationLevel;
+ uint32_t maxTessellationPatchSize;
+ uint32_t maxTessellationControlPerVertexInputComponents;
+ uint32_t maxTessellationControlPerVertexOutputComponents;
+ uint32_t maxTessellationControlPerPatchOutputComponents;
+ uint32_t maxTessellationControlTotalOutputComponents;
+ uint32_t maxTessellationEvaluationInputComponents;
+ uint32_t maxTessellationEvaluationOutputComponents;
+ uint32_t maxGeometryShaderInvocations;
+ uint32_t maxGeometryInputComponents;
+ uint32_t maxGeometryOutputComponents;
+ uint32_t maxGeometryOutputVertices;
+ uint32_t maxGeometryTotalOutputComponents;
+ uint32_t maxFragmentInputComponents;
+ uint32_t maxFragmentOutputAttachments;
+ uint32_t maxFragmentDualSrcAttachments;
+ uint32_t maxFragmentCombinedOutputResources;
+ uint32_t maxComputeSharedMemorySize;
+ uint32_t maxComputeWorkGroupCount[3];
+ uint32_t maxComputeWorkGroupInvocations;
+ uint32_t maxComputeWorkGroupSize[3];
+ uint32_t subPixelPrecisionBits;
+ uint32_t subTexelPrecisionBits;
+ uint32_t mipmapPrecisionBits;
+ uint32_t maxDrawIndexedIndexValue;
+ uint32_t maxDrawIndirectCount;
+ float maxSamplerLodBias;
+ float maxSamplerAnisotropy;
+ uint32_t maxViewports;
+ uint32_t maxViewportDimensions[2];
+ float viewportBoundsRange[2];
+ uint32_t viewportSubPixelBits;
+ size_t minMemoryMapAlignment;
+ VkDeviceSize minTexelBufferOffsetAlignment;
+ VkDeviceSize minUniformBufferOffsetAlignment;
+ VkDeviceSize minStorageBufferOffsetAlignment;
+ int32_t minTexelOffset;
+ uint32_t maxTexelOffset;
+ int32_t minTexelGatherOffset;
+ uint32_t maxTexelGatherOffset;
+ float minInterpolationOffset;
+ float maxInterpolationOffset;
+ uint32_t subPixelInterpolationOffsetBits;
+ uint32_t maxFramebufferWidth;
+ uint32_t maxFramebufferHeight;
+ uint32_t maxFramebufferLayers;
+ VkSampleCountFlags framebufferColorSampleCounts;
+ VkSampleCountFlags framebufferDepthSampleCounts;
+ VkSampleCountFlags framebufferStencilSampleCounts;
+ VkSampleCountFlags framebufferNoAttachmentsSampleCounts;
+ uint32_t maxColorAttachments;
+ VkSampleCountFlags sampledImageColorSampleCounts;
+ VkSampleCountFlags sampledImageIntegerSampleCounts;
+ VkSampleCountFlags sampledImageDepthSampleCounts;
+ VkSampleCountFlags sampledImageStencilSampleCounts;
+ VkSampleCountFlags storageImageSampleCounts;
+ uint32_t maxSampleMaskWords;
+ VkBool32 timestampComputeAndGraphics;
+ float timestampPeriod;
+ uint32_t maxClipDistances;
+ uint32_t maxCullDistances;
+ uint32_t maxCombinedClipAndCullDistances;
+ uint32_t discreteQueuePriorities;
+ float pointSizeRange[2];
+ float lineWidthRange[2];
+ float pointSizeGranularity;
+ float lineWidthGranularity;
+ VkBool32 strictLines;
+ VkBool32 standardSampleLocations;
+ VkDeviceSize optimalBufferCopyOffsetAlignment;
+ VkDeviceSize optimalBufferCopyRowPitchAlignment;
+ VkDeviceSize nonCoherentAtomSize;
+} VkPhysicalDeviceLimits;
+
+typedef struct VkPhysicalDeviceSparseProperties {
+ VkBool32 residencyStandard2DBlockShape;
+ VkBool32 residencyStandard2DMultisampleBlockShape;
+ VkBool32 residencyStandard3DBlockShape;
+ VkBool32 residencyAlignedMipSize;
+ VkBool32 residencyNonResidentStrict;
+} VkPhysicalDeviceSparseProperties;
+
+typedef struct VkPhysicalDeviceProperties {
+ uint32_t apiVersion;
+ uint32_t driverVersion;
+ uint32_t vendorID;
+ uint32_t deviceID;
+ VkPhysicalDeviceType deviceType;
+ char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
+ uint8_t pipelineCacheUUID[VK_UUID_SIZE];
+ VkPhysicalDeviceLimits limits;
+ VkPhysicalDeviceSparseProperties sparseProperties;
+} VkPhysicalDeviceProperties;
+
+typedef struct VkQueueFamilyProperties {
+ VkQueueFlags queueFlags;
+ uint32_t queueCount;
+ uint32_t timestampValidBits;
+ VkExtent3D minImageTransferGranularity;
+} VkQueueFamilyProperties;
+
+typedef struct VkMemoryType {
+ VkMemoryPropertyFlags propertyFlags;
+ uint32_t heapIndex;
+} VkMemoryType;
+
+typedef struct VkMemoryHeap {
+ VkDeviceSize size;
+ VkMemoryHeapFlags flags;
+} VkMemoryHeap;
+
+typedef struct VkPhysicalDeviceMemoryProperties {
+ uint32_t memoryTypeCount;
+ VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES];
+ uint32_t memoryHeapCount;
+ VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS];
+} VkPhysicalDeviceMemoryProperties;
+
+typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void);
+typedef struct VkDeviceQueueCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceQueueCreateFlags flags;
+ uint32_t queueFamilyIndex;
+ uint32_t queueCount;
+ const float* pQueuePriorities;
+} VkDeviceQueueCreateInfo;
+
+typedef struct VkDeviceCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceCreateFlags flags;
+ uint32_t queueCreateInfoCount;
+ const VkDeviceQueueCreateInfo* pQueueCreateInfos;
+ uint32_t enabledLayerCount;
+ const char* const* ppEnabledLayerNames;
+ uint32_t enabledExtensionCount;
+ const char* const* ppEnabledExtensionNames;
+ const VkPhysicalDeviceFeatures* pEnabledFeatures;
+} VkDeviceCreateInfo;
+
+typedef struct VkExtensionProperties {
+ char extensionName[VK_MAX_EXTENSION_NAME_SIZE];
+ uint32_t specVersion;
+} VkExtensionProperties;
+
+typedef struct VkLayerProperties {
+ char layerName[VK_MAX_EXTENSION_NAME_SIZE];
+ uint32_t specVersion;
+ uint32_t implementationVersion;
+ char description[VK_MAX_DESCRIPTION_SIZE];
+} VkLayerProperties;
+
+typedef struct VkSubmitInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t waitSemaphoreCount;
+ const VkSemaphore* pWaitSemaphores;
+ const VkPipelineStageFlags* pWaitDstStageMask;
+ uint32_t commandBufferCount;
+ const VkCommandBuffer* pCommandBuffers;
+ uint32_t signalSemaphoreCount;
+ const VkSemaphore* pSignalSemaphores;
+} VkSubmitInfo;
+
+typedef struct VkMemoryAllocateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceSize allocationSize;
+ uint32_t memoryTypeIndex;
+} VkMemoryAllocateInfo;
+
+typedef struct VkMappedMemoryRange {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceMemory memory;
+ VkDeviceSize offset;
+ VkDeviceSize size;
+} VkMappedMemoryRange;
+
+typedef struct VkMemoryRequirements {
+ VkDeviceSize size;
+ VkDeviceSize alignment;
+ uint32_t memoryTypeBits;
+} VkMemoryRequirements;
+
+typedef struct VkSparseImageFormatProperties {
+ VkImageAspectFlags aspectMask;
+ VkExtent3D imageGranularity;
+ VkSparseImageFormatFlags flags;
+} VkSparseImageFormatProperties;
+
+typedef struct VkSparseImageMemoryRequirements {
+ VkSparseImageFormatProperties formatProperties;
+ uint32_t imageMipTailFirstLod;
+ VkDeviceSize imageMipTailSize;
+ VkDeviceSize imageMipTailOffset;
+ VkDeviceSize imageMipTailStride;
+} VkSparseImageMemoryRequirements;
+
+typedef struct VkSparseMemoryBind {
+ VkDeviceSize resourceOffset;
+ VkDeviceSize size;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+ VkSparseMemoryBindFlags flags;
+} VkSparseMemoryBind;
+
+typedef struct VkSparseBufferMemoryBindInfo {
+ VkBuffer buffer;
+ uint32_t bindCount;
+ const VkSparseMemoryBind* pBinds;
+} VkSparseBufferMemoryBindInfo;
+
+typedef struct VkSparseImageOpaqueMemoryBindInfo {
+ VkImage image;
+ uint32_t bindCount;
+ const VkSparseMemoryBind* pBinds;
+} VkSparseImageOpaqueMemoryBindInfo;
+
+typedef struct VkImageSubresource {
+ VkImageAspectFlags aspectMask;
+ uint32_t mipLevel;
+ uint32_t arrayLayer;
+} VkImageSubresource;
+
+typedef struct VkOffset3D {
+ int32_t x;
+ int32_t y;
+ int32_t z;
+} VkOffset3D;
+
+typedef struct VkSparseImageMemoryBind {
+ VkImageSubresource subresource;
+ VkOffset3D offset;
+ VkExtent3D extent;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+ VkSparseMemoryBindFlags flags;
+} VkSparseImageMemoryBind;
+
+typedef struct VkSparseImageMemoryBindInfo {
+ VkImage image;
+ uint32_t bindCount;
+ const VkSparseImageMemoryBind* pBinds;
+} VkSparseImageMemoryBindInfo;
+
+typedef struct VkBindSparseInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t waitSemaphoreCount;
+ const VkSemaphore* pWaitSemaphores;
+ uint32_t bufferBindCount;
+ const VkSparseBufferMemoryBindInfo* pBufferBinds;
+ uint32_t imageOpaqueBindCount;
+ const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds;
+ uint32_t imageBindCount;
+ const VkSparseImageMemoryBindInfo* pImageBinds;
+ uint32_t signalSemaphoreCount;
+ const VkSemaphore* pSignalSemaphores;
+} VkBindSparseInfo;
+
+typedef struct VkFenceCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkFenceCreateFlags flags;
+} VkFenceCreateInfo;
+
+typedef struct VkSemaphoreCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphoreCreateFlags flags;
+} VkSemaphoreCreateInfo;
+
+typedef struct VkEventCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkEventCreateFlags flags;
+} VkEventCreateInfo;
+
+typedef struct VkQueryPoolCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkQueryPoolCreateFlags flags;
+ VkQueryType queryType;
+ uint32_t queryCount;
+ VkQueryPipelineStatisticFlags pipelineStatistics;
+} VkQueryPoolCreateInfo;
+
+typedef struct VkBufferCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkBufferCreateFlags flags;
+ VkDeviceSize size;
+ VkBufferUsageFlags usage;
+ VkSharingMode sharingMode;
+ uint32_t queueFamilyIndexCount;
+ const uint32_t* pQueueFamilyIndices;
+} VkBufferCreateInfo;
+
+typedef struct VkBufferViewCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkBufferViewCreateFlags flags;
+ VkBuffer buffer;
+ VkFormat format;
+ VkDeviceSize offset;
+ VkDeviceSize range;
+} VkBufferViewCreateInfo;
+
+typedef struct VkImageCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageCreateFlags flags;
+ VkImageType imageType;
+ VkFormat format;
+ VkExtent3D extent;
+ uint32_t mipLevels;
+ uint32_t arrayLayers;
+ VkSampleCountFlagBits samples;
+ VkImageTiling tiling;
+ VkImageUsageFlags usage;
+ VkSharingMode sharingMode;
+ uint32_t queueFamilyIndexCount;
+ const uint32_t* pQueueFamilyIndices;
+ VkImageLayout initialLayout;
+} VkImageCreateInfo;
+
+typedef struct VkSubresourceLayout {
+ VkDeviceSize offset;
+ VkDeviceSize size;
+ VkDeviceSize rowPitch;
+ VkDeviceSize arrayPitch;
+ VkDeviceSize depthPitch;
+} VkSubresourceLayout;
+
+typedef struct VkComponentMapping {
+ VkComponentSwizzle r;
+ VkComponentSwizzle g;
+ VkComponentSwizzle b;
+ VkComponentSwizzle a;
+} VkComponentMapping;
+
+typedef struct VkImageSubresourceRange {
+ VkImageAspectFlags aspectMask;
+ uint32_t baseMipLevel;
+ uint32_t levelCount;
+ uint32_t baseArrayLayer;
+ uint32_t layerCount;
+} VkImageSubresourceRange;
+
+typedef struct VkImageViewCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageViewCreateFlags flags;
+ VkImage image;
+ VkImageViewType viewType;
+ VkFormat format;
+ VkComponentMapping components;
+ VkImageSubresourceRange subresourceRange;
+} VkImageViewCreateInfo;
+
+typedef struct VkShaderModuleCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkShaderModuleCreateFlags flags;
+ size_t codeSize;
+ const uint32_t* pCode;
+} VkShaderModuleCreateInfo;
+
+typedef struct VkPipelineCacheCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCacheCreateFlags flags;
+ size_t initialDataSize;
+ const void* pInitialData;
+} VkPipelineCacheCreateInfo;
+
+typedef struct VkSpecializationMapEntry {
+ uint32_t constantID;
+ uint32_t offset;
+ size_t size;
+} VkSpecializationMapEntry;
+
+typedef struct VkSpecializationInfo {
+ uint32_t mapEntryCount;
+ const VkSpecializationMapEntry* pMapEntries;
+ size_t dataSize;
+ const void* pData;
+} VkSpecializationInfo;
+
+typedef struct VkPipelineShaderStageCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineShaderStageCreateFlags flags;
+ VkShaderStageFlagBits stage;
+ VkShaderModule module;
+ const char* pName;
+ const VkSpecializationInfo* pSpecializationInfo;
+} VkPipelineShaderStageCreateInfo;
+
+typedef struct VkVertexInputBindingDescription {
+ uint32_t binding;
+ uint32_t stride;
+ VkVertexInputRate inputRate;
+} VkVertexInputBindingDescription;
+
+typedef struct VkVertexInputAttributeDescription {
+ uint32_t location;
+ uint32_t binding;
+ VkFormat format;
+ uint32_t offset;
+} VkVertexInputAttributeDescription;
+
+typedef struct VkPipelineVertexInputStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineVertexInputStateCreateFlags flags;
+ uint32_t vertexBindingDescriptionCount;
+ const VkVertexInputBindingDescription* pVertexBindingDescriptions;
+ uint32_t vertexAttributeDescriptionCount;
+ const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+} VkPipelineVertexInputStateCreateInfo;
+
+typedef struct VkPipelineInputAssemblyStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineInputAssemblyStateCreateFlags flags;
+ VkPrimitiveTopology topology;
+ VkBool32 primitiveRestartEnable;
+} VkPipelineInputAssemblyStateCreateInfo;
+
+typedef struct VkPipelineTessellationStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineTessellationStateCreateFlags flags;
+ uint32_t patchControlPoints;
+} VkPipelineTessellationStateCreateInfo;
+
+typedef struct VkViewport {
+ float x;
+ float y;
+ float width;
+ float height;
+ float minDepth;
+ float maxDepth;
+} VkViewport;
+
+typedef struct VkOffset2D {
+ int32_t x;
+ int32_t y;
+} VkOffset2D;
+
+typedef struct VkExtent2D {
+ uint32_t width;
+ uint32_t height;
+} VkExtent2D;
+
+typedef struct VkRect2D {
+ VkOffset2D offset;
+ VkExtent2D extent;
+} VkRect2D;
+
+typedef struct VkPipelineViewportStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineViewportStateCreateFlags flags;
+ uint32_t viewportCount;
+ const VkViewport* pViewports;
+ uint32_t scissorCount;
+ const VkRect2D* pScissors;
+} VkPipelineViewportStateCreateInfo;
+
+typedef struct VkPipelineRasterizationStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineRasterizationStateCreateFlags flags;
+ VkBool32 depthClampEnable;
+ VkBool32 rasterizerDiscardEnable;
+ VkPolygonMode polygonMode;
+ VkCullModeFlags cullMode;
+ VkFrontFace frontFace;
+ VkBool32 depthBiasEnable;
+ float depthBiasConstantFactor;
+ float depthBiasClamp;
+ float depthBiasSlopeFactor;
+ float lineWidth;
+} VkPipelineRasterizationStateCreateInfo;
+
+typedef struct VkPipelineMultisampleStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineMultisampleStateCreateFlags flags;
+ VkSampleCountFlagBits rasterizationSamples;
+ VkBool32 sampleShadingEnable;
+ float minSampleShading;
+ const VkSampleMask* pSampleMask;
+ VkBool32 alphaToCoverageEnable;
+ VkBool32 alphaToOneEnable;
+} VkPipelineMultisampleStateCreateInfo;
+
+typedef struct VkStencilOpState {
+ VkStencilOp failOp;
+ VkStencilOp passOp;
+ VkStencilOp depthFailOp;
+ VkCompareOp compareOp;
+ uint32_t compareMask;
+ uint32_t writeMask;
+ uint32_t reference;
+} VkStencilOpState;
+
+typedef struct VkPipelineDepthStencilStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineDepthStencilStateCreateFlags flags;
+ VkBool32 depthTestEnable;
+ VkBool32 depthWriteEnable;
+ VkCompareOp depthCompareOp;
+ VkBool32 depthBoundsTestEnable;
+ VkBool32 stencilTestEnable;
+ VkStencilOpState front;
+ VkStencilOpState back;
+ float minDepthBounds;
+ float maxDepthBounds;
+} VkPipelineDepthStencilStateCreateInfo;
+
+typedef struct VkPipelineColorBlendAttachmentState {
+ VkBool32 blendEnable;
+ VkBlendFactor srcColorBlendFactor;
+ VkBlendFactor dstColorBlendFactor;
+ VkBlendOp colorBlendOp;
+ VkBlendFactor srcAlphaBlendFactor;
+ VkBlendFactor dstAlphaBlendFactor;
+ VkBlendOp alphaBlendOp;
+ VkColorComponentFlags colorWriteMask;
+} VkPipelineColorBlendAttachmentState;
+
+typedef struct VkPipelineColorBlendStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineColorBlendStateCreateFlags flags;
+ VkBool32 logicOpEnable;
+ VkLogicOp logicOp;
+ uint32_t attachmentCount;
+ const VkPipelineColorBlendAttachmentState* pAttachments;
+ float blendConstants[4];
+} VkPipelineColorBlendStateCreateInfo;
+
+typedef struct VkPipelineDynamicStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineDynamicStateCreateFlags flags;
+ uint32_t dynamicStateCount;
+ const VkDynamicState* pDynamicStates;
+} VkPipelineDynamicStateCreateInfo;
+
+typedef struct VkGraphicsPipelineCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCreateFlags flags;
+ uint32_t stageCount;
+ const VkPipelineShaderStageCreateInfo* pStages;
+ const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+ const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+ const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ const VkPipelineViewportStateCreateInfo* pViewportState;
+ const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
+ const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+ const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+ const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
+ const VkPipelineDynamicStateCreateInfo* pDynamicState;
+ VkPipelineLayout layout;
+ VkRenderPass renderPass;
+ uint32_t subpass;
+ VkPipeline basePipelineHandle;
+ int32_t basePipelineIndex;
+} VkGraphicsPipelineCreateInfo;
+
+typedef struct VkComputePipelineCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCreateFlags flags;
+ VkPipelineShaderStageCreateInfo stage;
+ VkPipelineLayout layout;
+ VkPipeline basePipelineHandle;
+ int32_t basePipelineIndex;
+} VkComputePipelineCreateInfo;
+
+typedef struct VkPushConstantRange {
+ VkShaderStageFlags stageFlags;
+ uint32_t offset;
+ uint32_t size;
+} VkPushConstantRange;
+
+typedef struct VkPipelineLayoutCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineLayoutCreateFlags flags;
+ uint32_t setLayoutCount;
+ const VkDescriptorSetLayout* pSetLayouts;
+ uint32_t pushConstantRangeCount;
+ const VkPushConstantRange* pPushConstantRanges;
+} VkPipelineLayoutCreateInfo;
+
+typedef struct VkSamplerCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkSamplerCreateFlags flags;
+ VkFilter magFilter;
+ VkFilter minFilter;
+ VkSamplerMipmapMode mipmapMode;
+ VkSamplerAddressMode addressModeU;
+ VkSamplerAddressMode addressModeV;
+ VkSamplerAddressMode addressModeW;
+ float mipLodBias;
+ VkBool32 anisotropyEnable;
+ float maxAnisotropy;
+ VkBool32 compareEnable;
+ VkCompareOp compareOp;
+ float minLod;
+ float maxLod;
+ VkBorderColor borderColor;
+ VkBool32 unnormalizedCoordinates;
+} VkSamplerCreateInfo;
+
+typedef struct VkDescriptorSetLayoutBinding {
+ uint32_t binding;
+ VkDescriptorType descriptorType;
+ uint32_t descriptorCount;
+ VkShaderStageFlags stageFlags;
+ const VkSampler* pImmutableSamplers;
+} VkDescriptorSetLayoutBinding;
+
+typedef struct VkDescriptorSetLayoutCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorSetLayoutCreateFlags flags;
+ uint32_t bindingCount;
+ const VkDescriptorSetLayoutBinding* pBindings;
+} VkDescriptorSetLayoutCreateInfo;
+
+typedef struct VkDescriptorPoolSize {
+ VkDescriptorType type;
+ uint32_t descriptorCount;
+} VkDescriptorPoolSize;
+
+typedef struct VkDescriptorPoolCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorPoolCreateFlags flags;
+ uint32_t maxSets;
+ uint32_t poolSizeCount;
+ const VkDescriptorPoolSize* pPoolSizes;
+} VkDescriptorPoolCreateInfo;
+
+typedef struct VkDescriptorSetAllocateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorPool descriptorPool;
+ uint32_t descriptorSetCount;
+ const VkDescriptorSetLayout* pSetLayouts;
+} VkDescriptorSetAllocateInfo;
+
+typedef struct VkDescriptorImageInfo {
+ VkSampler sampler;
+ VkImageView imageView;
+ VkImageLayout imageLayout;
+} VkDescriptorImageInfo;
+
+typedef struct VkDescriptorBufferInfo {
+ VkBuffer buffer;
+ VkDeviceSize offset;
+ VkDeviceSize range;
+} VkDescriptorBufferInfo;
+
+typedef struct VkWriteDescriptorSet {
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorSet dstSet;
+ uint32_t dstBinding;
+ uint32_t dstArrayElement;
+ uint32_t descriptorCount;
+ VkDescriptorType descriptorType;
+ const VkDescriptorImageInfo* pImageInfo;
+ const VkDescriptorBufferInfo* pBufferInfo;
+ const VkBufferView* pTexelBufferView;
+} VkWriteDescriptorSet;
+
+typedef struct VkCopyDescriptorSet {
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorSet srcSet;
+ uint32_t srcBinding;
+ uint32_t srcArrayElement;
+ VkDescriptorSet dstSet;
+ uint32_t dstBinding;
+ uint32_t dstArrayElement;
+ uint32_t descriptorCount;
+} VkCopyDescriptorSet;
+
+typedef struct VkFramebufferCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkFramebufferCreateFlags flags;
+ VkRenderPass renderPass;
+ uint32_t attachmentCount;
+ const VkImageView* pAttachments;
+ uint32_t width;
+ uint32_t height;
+ uint32_t layers;
+} VkFramebufferCreateInfo;
+
+typedef struct VkAttachmentDescription {
+ VkAttachmentDescriptionFlags flags;
+ VkFormat format;
+ VkSampleCountFlagBits samples;
+ VkAttachmentLoadOp loadOp;
+ VkAttachmentStoreOp storeOp;
+ VkAttachmentLoadOp stencilLoadOp;
+ VkAttachmentStoreOp stencilStoreOp;
+ VkImageLayout initialLayout;
+ VkImageLayout finalLayout;
+} VkAttachmentDescription;
+
+typedef struct VkAttachmentReference {
+ uint32_t attachment;
+ VkImageLayout layout;
+} VkAttachmentReference;
+
+typedef struct VkSubpassDescription {
+ VkSubpassDescriptionFlags flags;
+ VkPipelineBindPoint pipelineBindPoint;
+ uint32_t inputAttachmentCount;
+ const VkAttachmentReference* pInputAttachments;
+ uint32_t colorAttachmentCount;
+ const VkAttachmentReference* pColorAttachments;
+ const VkAttachmentReference* pResolveAttachments;
+ const VkAttachmentReference* pDepthStencilAttachment;
+ uint32_t preserveAttachmentCount;
+ const uint32_t* pPreserveAttachments;
+} VkSubpassDescription;
+
+typedef struct VkSubpassDependency {
+ uint32_t srcSubpass;
+ uint32_t dstSubpass;
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
+ VkAccessFlags srcAccessMask;
+ VkAccessFlags dstAccessMask;
+ VkDependencyFlags dependencyFlags;
+} VkSubpassDependency;
+
+typedef struct VkRenderPassCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkRenderPassCreateFlags flags;
+ uint32_t attachmentCount;
+ const VkAttachmentDescription* pAttachments;
+ uint32_t subpassCount;
+ const VkSubpassDescription* pSubpasses;
+ uint32_t dependencyCount;
+ const VkSubpassDependency* pDependencies;
+} VkRenderPassCreateInfo;
+
+typedef struct VkCommandPoolCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkCommandPoolCreateFlags flags;
+ uint32_t queueFamilyIndex;
+} VkCommandPoolCreateInfo;
+
+typedef struct VkCommandBufferAllocateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkCommandPool commandPool;
+ VkCommandBufferLevel level;
+ uint32_t commandBufferCount;
+} VkCommandBufferAllocateInfo;
+
+typedef struct VkCommandBufferInheritanceInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkRenderPass renderPass;
+ uint32_t subpass;
+ VkFramebuffer framebuffer;
+ VkBool32 occlusionQueryEnable;
+ VkQueryControlFlags queryFlags;
+ VkQueryPipelineStatisticFlags pipelineStatistics;
+} VkCommandBufferInheritanceInfo;
+
+typedef struct VkCommandBufferBeginInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkCommandBufferUsageFlags flags;
+ const VkCommandBufferInheritanceInfo* pInheritanceInfo;
+} VkCommandBufferBeginInfo;
+
+typedef struct VkBufferCopy {
+ VkDeviceSize srcOffset;
+ VkDeviceSize dstOffset;
+ VkDeviceSize size;
+} VkBufferCopy;
+
+typedef struct VkImageSubresourceLayers {
+ VkImageAspectFlags aspectMask;
+ uint32_t mipLevel;
+ uint32_t baseArrayLayer;
+ uint32_t layerCount;
+} VkImageSubresourceLayers;
+
+typedef struct VkImageCopy {
+ VkImageSubresourceLayers srcSubresource;
+ VkOffset3D srcOffset;
+ VkImageSubresourceLayers dstSubresource;
+ VkOffset3D dstOffset;
+ VkExtent3D extent;
+} VkImageCopy;
+
+typedef struct VkImageBlit {
+ VkImageSubresourceLayers srcSubresource;
+ VkOffset3D srcOffsets[2];
+ VkImageSubresourceLayers dstSubresource;
+ VkOffset3D dstOffsets[2];
+} VkImageBlit;
+
+typedef struct VkBufferImageCopy {
+ VkDeviceSize bufferOffset;
+ uint32_t bufferRowLength;
+ uint32_t bufferImageHeight;
+ VkImageSubresourceLayers imageSubresource;
+ VkOffset3D imageOffset;
+ VkExtent3D imageExtent;
+} VkBufferImageCopy;
+
+typedef union VkClearColorValue {
+ float float32[4];
+ int32_t int32[4];
+ uint32_t uint32[4];
+} VkClearColorValue;
+
+typedef struct VkClearDepthStencilValue {
+ float depth;
+ uint32_t stencil;
+} VkClearDepthStencilValue;
+
+typedef union VkClearValue {
+ VkClearColorValue color;
+ VkClearDepthStencilValue depthStencil;
+} VkClearValue;
+
+typedef struct VkClearAttachment {
+ VkImageAspectFlags aspectMask;
+ uint32_t colorAttachment;
+ VkClearValue clearValue;
+} VkClearAttachment;
+
+typedef struct VkClearRect {
+ VkRect2D rect;
+ uint32_t baseArrayLayer;
+ uint32_t layerCount;
+} VkClearRect;
+
+typedef struct VkImageResolve {
+ VkImageSubresourceLayers srcSubresource;
+ VkOffset3D srcOffset;
+ VkImageSubresourceLayers dstSubresource;
+ VkOffset3D dstOffset;
+ VkExtent3D extent;
+} VkImageResolve;
+
+typedef struct VkMemoryBarrier {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccessFlags srcAccessMask;
+ VkAccessFlags dstAccessMask;
+} VkMemoryBarrier;
+
+typedef struct VkBufferMemoryBarrier {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccessFlags srcAccessMask;
+ VkAccessFlags dstAccessMask;
+ uint32_t srcQueueFamilyIndex;
+ uint32_t dstQueueFamilyIndex;
+ VkBuffer buffer;
+ VkDeviceSize offset;
+ VkDeviceSize size;
+} VkBufferMemoryBarrier;
+
+typedef struct VkImageMemoryBarrier {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccessFlags srcAccessMask;
+ VkAccessFlags dstAccessMask;
+ VkImageLayout oldLayout;
+ VkImageLayout newLayout;
+ uint32_t srcQueueFamilyIndex;
+ uint32_t dstQueueFamilyIndex;
+ VkImage image;
+ VkImageSubresourceRange subresourceRange;
+} VkImageMemoryBarrier;
+
+typedef struct VkRenderPassBeginInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkRenderPass renderPass;
+ VkFramebuffer framebuffer;
+ VkRect2D renderArea;
+ uint32_t clearValueCount;
+ const VkClearValue* pClearValues;
+} VkRenderPassBeginInfo;
+
+typedef struct VkDispatchIndirectCommand {
+ uint32_t x;
+ uint32_t y;
+ uint32_t z;
+} VkDispatchIndirectCommand;
+
+typedef struct VkDrawIndexedIndirectCommand {
+ uint32_t indexCount;
+ uint32_t instanceCount;
+ uint32_t firstIndex;
+ int32_t vertexOffset;
+ uint32_t firstInstance;
+} VkDrawIndexedIndirectCommand;
+
+typedef struct VkDrawIndirectCommand {
+ uint32_t vertexCount;
+ uint32_t instanceCount;
+ uint32_t firstVertex;
+ uint32_t firstInstance;
+} VkDrawIndirectCommand;
+
+typedef struct VkBaseOutStructure {
+ VkStructureType sType;
+ struct VkBaseOutStructure* pNext;
+} VkBaseOutStructure;
+
+typedef struct VkBaseInStructure {
+ VkStructureType sType;
+ const struct VkBaseInStructure* pNext;
+} VkBaseInStructure;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
+typedef void (VKAPI_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties);
+typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char* pName);
+typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetDeviceProcAddr)(VkDevice device, const char* pName);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDevice)(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
+typedef void (VKAPI_PTR *PFN_vkDestroyDevice)(VkDevice device, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceExtensionProperties)(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceExtensionProperties)(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceLayerProperties)(uint32_t* pPropertyCount, VkLayerProperties* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceLayerProperties)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue)(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence);
+typedef VkResult (VKAPI_PTR *PFN_vkQueueWaitIdle)(VkQueue queue);
+typedef VkResult (VKAPI_PTR *PFN_vkDeviceWaitIdle)(VkDevice device);
+typedef VkResult (VKAPI_PTR *PFN_vkAllocateMemory)(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory);
+typedef void (VKAPI_PTR *PFN_vkFreeMemory)(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkMapMemory)(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData);
+typedef void (VKAPI_PTR *PFN_vkUnmapMemory)(VkDevice device, VkDeviceMemory memory);
+typedef VkResult (VKAPI_PTR *PFN_vkFlushMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges);
+typedef VkResult (VKAPI_PTR *PFN_vkInvalidateMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceMemoryCommitment)(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes);
+typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory)(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset);
+typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory)(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset);
+typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements)(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements)(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements)(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkQueueBindSparse)(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateFence)(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
+typedef void (VKAPI_PTR *PFN_vkDestroyFence)(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences);
+typedef VkResult (VKAPI_PTR *PFN_vkGetFenceStatus)(VkDevice device, VkFence fence);
+typedef VkResult (VKAPI_PTR *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore);
+typedef void (VKAPI_PTR *PFN_vkDestroySemaphore)(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent);
+typedef void (VKAPI_PTR *PFN_vkDestroyEvent)(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetEventStatus)(VkDevice device, VkEvent event);
+typedef VkResult (VKAPI_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event);
+typedef VkResult (VKAPI_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool);
+typedef void (VKAPI_PTR *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer);
+typedef void (VKAPI_PTR *PFN_vkDestroyBuffer)(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView);
+typedef void (VKAPI_PTR *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage);
+typedef void (VKAPI_PTR *PFN_vkDestroyImage)(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateImageView)(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView);
+typedef void (VKAPI_PTR *PFN_vkDestroyImageView)(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateShaderModule)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule);
+typedef void (VKAPI_PTR *PFN_vkDestroyShaderModule)(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache);
+typedef void (VKAPI_PTR *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData);
+typedef VkResult (VKAPI_PTR *PFN_vkMergePipelineCaches)(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateComputePipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef void (VKAPI_PTR *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout);
+typedef void (VKAPI_PTR *PFN_vkDestroyPipelineLayout)(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSampler)(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler);
+typedef void (VKAPI_PTR *PFN_vkDestroySampler)(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorSetLayout)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorSetLayout)(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorPool)(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags);
+typedef VkResult (VKAPI_PTR *PFN_vkAllocateDescriptorSets)(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets);
+typedef VkResult (VKAPI_PTR *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets);
+typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateFramebuffer)(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer);
+typedef void (VKAPI_PTR *PFN_vkDestroyFramebuffer)(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
+typedef void (VKAPI_PTR *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool);
+typedef void (VKAPI_PTR *PFN_vkDestroyCommandPool)(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags);
+typedef VkResult (VKAPI_PTR *PFN_vkAllocateCommandBuffers)(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
+typedef void (VKAPI_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+typedef VkResult (VKAPI_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer commandBuffer);
+typedef VkResult (VKAPI_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags);
+typedef void (VKAPI_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline);
+typedef void (VKAPI_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports);
+typedef void (VKAPI_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors);
+typedef void (VKAPI_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer commandBuffer, float lineWidth);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias)(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor);
+typedef void (VKAPI_PTR *PFN_vkCmdSetBlendConstants)(VkCommandBuffer commandBuffer, const float blendConstants[4]);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds);
+typedef void (VKAPI_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask);
+typedef void (VKAPI_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask);
+typedef void (VKAPI_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference);
+typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets);
+typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType);
+typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets);
+typedef void (VKAPI_PTR *PFN_vkCmdDraw)(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions);
+typedef void (VKAPI_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions);
+typedef void (VKAPI_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData);
+typedef void (VKAPI_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data);
+typedef void (VKAPI_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
+typedef void (VKAPI_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
+typedef void (VKAPI_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects);
+typedef void (VKAPI_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions);
+typedef void (VKAPI_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+typedef void (VKAPI_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers);
+typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers);
+typedef void (VKAPI_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags);
+typedef void (VKAPI_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query);
+typedef void (VKAPI_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
+typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags);
+typedef void (VKAPI_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues);
+typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents);
+typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer commandBuffer, VkSubpassContents contents);
+typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer commandBuffer);
+typedef void (VKAPI_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
+ const VkInstanceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkInstance* pInstance);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(
+ VkInstance instance,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceCount,
+ VkPhysicalDevice* pPhysicalDevices);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures* pFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties* pFormatProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ VkImageTiling tiling,
+ VkImageUsageFlags usage,
+ VkImageCreateFlags flags,
+ VkImageFormatProperties* pImageFormatProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties* pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties* pQueueFamilyProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties* pMemoryProperties);
+
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(
+ VkInstance instance,
+ const char* pName);
+
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(
+ VkDevice device,
+ const char* pName);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(
+ VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(
+ VkDevice device,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(
+ VkPhysicalDevice physicalDevice,
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
+ uint32_t* pPropertyCount,
+ VkLayerProperties* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkLayerProperties* pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(
+ VkDevice device,
+ uint32_t queueFamilyIndex,
+ uint32_t queueIndex,
+ VkQueue* pQueue);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit(
+ VkQueue queue,
+ uint32_t submitCount,
+ const VkSubmitInfo* pSubmits,
+ VkFence fence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(
+ VkQueue queue);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(
+ VkDevice device);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(
+ VkDevice device,
+ const VkMemoryAllocateInfo* pAllocateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDeviceMemory* pMemory);
+
+VKAPI_ATTR void VKAPI_CALL vkFreeMemory(
+ VkDevice device,
+ VkDeviceMemory memory,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory(
+ VkDevice device,
+ VkDeviceMemory memory,
+ VkDeviceSize offset,
+ VkDeviceSize size,
+ VkMemoryMapFlags flags,
+ void** ppData);
+
+VKAPI_ATTR void VKAPI_CALL vkUnmapMemory(
+ VkDevice device,
+ VkDeviceMemory memory);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkFlushMappedMemoryRanges(
+ VkDevice device,
+ uint32_t memoryRangeCount,
+ const VkMappedMemoryRange* pMemoryRanges);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkInvalidateMappedMemoryRanges(
+ VkDevice device,
+ uint32_t memoryRangeCount,
+ const VkMappedMemoryRange* pMemoryRanges);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceMemoryCommitment(
+ VkDevice device,
+ VkDeviceMemory memory,
+ VkDeviceSize* pCommittedMemoryInBytes);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory(
+ VkDevice device,
+ VkBuffer buffer,
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(
+ VkDevice device,
+ VkImage image,
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset);
+
+VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements(
+ VkDevice device,
+ VkBuffer buffer,
+ VkMemoryRequirements* pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements(
+ VkDevice device,
+ VkImage image,
+ VkMemoryRequirements* pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements(
+ VkDevice device,
+ VkImage image,
+ uint32_t* pSparseMemoryRequirementCount,
+ VkSparseImageMemoryRequirements* pSparseMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ VkSampleCountFlagBits samples,
+ VkImageUsageFlags usage,
+ VkImageTiling tiling,
+ uint32_t* pPropertyCount,
+ VkSparseImageFormatProperties* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse(
+ VkQueue queue,
+ uint32_t bindInfoCount,
+ const VkBindSparseInfo* pBindInfo,
+ VkFence fence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateFence(
+ VkDevice device,
+ const VkFenceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyFence(
+ VkDevice device,
+ VkFence fence,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(
+ VkDevice device,
+ uint32_t fenceCount,
+ const VkFence* pFences);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(
+ VkDevice device,
+ VkFence fence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences(
+ VkDevice device,
+ uint32_t fenceCount,
+ const VkFence* pFences,
+ VkBool32 waitAll,
+ uint64_t timeout);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore(
+ VkDevice device,
+ const VkSemaphoreCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSemaphore* pSemaphore);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore(
+ VkDevice device,
+ VkSemaphore semaphore,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent(
+ VkDevice device,
+ const VkEventCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkEvent* pEvent);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyEvent(
+ VkDevice device,
+ VkEvent event,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus(
+ VkDevice device,
+ VkEvent event);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(
+ VkDevice device,
+ VkEvent event);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent(
+ VkDevice device,
+ VkEvent event);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool(
+ VkDevice device,
+ const VkQueryPoolCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkQueryPool* pQueryPool);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyQueryPool(
+ VkDevice device,
+ VkQueryPool queryPool,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults(
+ VkDevice device,
+ VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount,
+ size_t dataSize,
+ void* pData,
+ VkDeviceSize stride,
+ VkQueryResultFlags flags);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer(
+ VkDevice device,
+ const VkBufferCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkBuffer* pBuffer);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer(
+ VkDevice device,
+ VkBuffer buffer,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView(
+ VkDevice device,
+ const VkBufferViewCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkBufferView* pView);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView(
+ VkDevice device,
+ VkBufferView bufferView,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(
+ VkDevice device,
+ const VkImageCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkImage* pImage);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyImage(
+ VkDevice device,
+ VkImage image,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout(
+ VkDevice device,
+ VkImage image,
+ const VkImageSubresource* pSubresource,
+ VkSubresourceLayout* pLayout);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView(
+ VkDevice device,
+ const VkImageViewCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkImageView* pView);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyImageView(
+ VkDevice device,
+ VkImageView imageView,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule(
+ VkDevice device,
+ const VkShaderModuleCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkShaderModule* pShaderModule);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyShaderModule(
+ VkDevice device,
+ VkShaderModule shaderModule,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache(
+ VkDevice device,
+ const VkPipelineCacheCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipelineCache* pPipelineCache);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineCache(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ size_t* pDataSize,
+ void* pData);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches(
+ VkDevice device,
+ VkPipelineCache dstCache,
+ uint32_t srcCacheCount,
+ const VkPipelineCache* pSrcCaches);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ uint32_t createInfoCount,
+ const VkGraphicsPipelineCreateInfo* pCreateInfos,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipeline* pPipelines);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ uint32_t createInfoCount,
+ const VkComputePipelineCreateInfo* pCreateInfos,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipeline* pPipelines);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline(
+ VkDevice device,
+ VkPipeline pipeline,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineLayout(
+ VkDevice device,
+ const VkPipelineLayoutCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipelineLayout* pPipelineLayout);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout(
+ VkDevice device,
+ VkPipelineLayout pipelineLayout,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(
+ VkDevice device,
+ const VkSamplerCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSampler* pSampler);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroySampler(
+ VkDevice device,
+ VkSampler sampler,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout(
+ VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDescriptorSetLayout* pSetLayout);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorSetLayout(
+ VkDevice device,
+ VkDescriptorSetLayout descriptorSetLayout,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorPool(
+ VkDevice device,
+ const VkDescriptorPoolCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDescriptorPool* pDescriptorPool);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorPool(
+ VkDevice device,
+ VkDescriptorPool descriptorPool,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkResetDescriptorPool(
+ VkDevice device,
+ VkDescriptorPool descriptorPool,
+ VkDescriptorPoolResetFlags flags);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAllocateDescriptorSets(
+ VkDevice device,
+ const VkDescriptorSetAllocateInfo* pAllocateInfo,
+ VkDescriptorSet* pDescriptorSets);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets(
+ VkDevice device,
+ VkDescriptorPool descriptorPool,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet* pDescriptorSets);
+
+VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets(
+ VkDevice device,
+ uint32_t descriptorWriteCount,
+ const VkWriteDescriptorSet* pDescriptorWrites,
+ uint32_t descriptorCopyCount,
+ const VkCopyDescriptorSet* pDescriptorCopies);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer(
+ VkDevice device,
+ const VkFramebufferCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFramebuffer* pFramebuffer);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyFramebuffer(
+ VkDevice device,
+ VkFramebuffer framebuffer,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(
+ VkDevice device,
+ const VkRenderPassCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkRenderPass* pRenderPass);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass(
+ VkDevice device,
+ VkRenderPass renderPass,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkGetRenderAreaGranularity(
+ VkDevice device,
+ VkRenderPass renderPass,
+ VkExtent2D* pGranularity);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(
+ VkDevice device,
+ const VkCommandPoolCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkCommandPool* pCommandPool);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool(
+ VkDevice device,
+ VkCommandPool commandPool,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool(
+ VkDevice device,
+ VkCommandPool commandPool,
+ VkCommandPoolResetFlags flags);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers(
+ VkDevice device,
+ const VkCommandBufferAllocateInfo* pAllocateInfo,
+ VkCommandBuffer* pCommandBuffers);
+
+VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(
+ VkDevice device,
+ VkCommandPool commandPool,
+ uint32_t commandBufferCount,
+ const VkCommandBuffer* pCommandBuffers);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer(
+ VkCommandBuffer commandBuffer,
+ const VkCommandBufferBeginInfo* pBeginInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer(
+ VkCommandBuffer commandBuffer);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer(
+ VkCommandBuffer commandBuffer,
+ VkCommandBufferResetFlags flags);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline(
+ VkCommandBuffer commandBuffer,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipeline pipeline);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkViewport* pViewports);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetScissor(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstScissor,
+ uint32_t scissorCount,
+ const VkRect2D* pScissors);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth(
+ VkCommandBuffer commandBuffer,
+ float lineWidth);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias(
+ VkCommandBuffer commandBuffer,
+ float depthBiasConstantFactor,
+ float depthBiasClamp,
+ float depthBiasSlopeFactor);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants(
+ VkCommandBuffer commandBuffer,
+ const float blendConstants[4]);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBounds(
+ VkCommandBuffer commandBuffer,
+ float minDepthBounds,
+ float maxDepthBounds);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilCompareMask(
+ VkCommandBuffer commandBuffer,
+ VkStencilFaceFlags faceMask,
+ uint32_t compareMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilWriteMask(
+ VkCommandBuffer commandBuffer,
+ VkStencilFaceFlags faceMask,
+ uint32_t writeMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference(
+ VkCommandBuffer commandBuffer,
+ VkStencilFaceFlags faceMask,
+ uint32_t reference);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets(
+ VkCommandBuffer commandBuffer,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ uint32_t firstSet,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet* pDescriptorSets,
+ uint32_t dynamicOffsetCount,
+ const uint32_t* pDynamicOffsets);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkIndexType indexType);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstBinding,
+ uint32_t bindingCount,
+ const VkBuffer* pBuffers,
+ const VkDeviceSize* pOffsets);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDraw(
+ VkCommandBuffer commandBuffer,
+ uint32_t vertexCount,
+ uint32_t instanceCount,
+ uint32_t firstVertex,
+ uint32_t firstInstance);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed(
+ VkCommandBuffer commandBuffer,
+ uint32_t indexCount,
+ uint32_t instanceCount,
+ uint32_t firstIndex,
+ int32_t vertexOffset,
+ uint32_t firstInstance);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ uint32_t drawCount,
+ uint32_t stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ uint32_t drawCount,
+ uint32_t stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatch(
+ VkCommandBuffer commandBuffer,
+ uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer(
+ VkCommandBuffer commandBuffer,
+ VkBuffer srcBuffer,
+ VkBuffer dstBuffer,
+ uint32_t regionCount,
+ const VkBufferCopy* pRegions);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage(
+ VkCommandBuffer commandBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageCopy* pRegions);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage(
+ VkCommandBuffer commandBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageBlit* pRegions,
+ VkFilter filter);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(
+ VkCommandBuffer commandBuffer,
+ VkBuffer srcBuffer,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkBufferImageCopy* pRegions);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(
+ VkCommandBuffer commandBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkBuffer dstBuffer,
+ uint32_t regionCount,
+ const VkBufferImageCopy* pRegions);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer(
+ VkCommandBuffer commandBuffer,
+ VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize dataSize,
+ const void* pData);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer(
+ VkCommandBuffer commandBuffer,
+ VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize size,
+ uint32_t data);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(
+ VkCommandBuffer commandBuffer,
+ VkImage image,
+ VkImageLayout imageLayout,
+ const VkClearColorValue* pColor,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange* pRanges);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage(
+ VkCommandBuffer commandBuffer,
+ VkImage image,
+ VkImageLayout imageLayout,
+ const VkClearDepthStencilValue* pDepthStencil,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange* pRanges);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(
+ VkCommandBuffer commandBuffer,
+ uint32_t attachmentCount,
+ const VkClearAttachment* pAttachments,
+ uint32_t rectCount,
+ const VkClearRect* pRects);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage(
+ VkCommandBuffer commandBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageResolve* pRegions);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent(
+ VkCommandBuffer commandBuffer,
+ VkEvent event,
+ VkPipelineStageFlags stageMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent(
+ VkCommandBuffer commandBuffer,
+ VkEvent event,
+ VkPipelineStageFlags stageMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents(
+ VkCommandBuffer commandBuffer,
+ uint32_t eventCount,
+ const VkEvent* pEvents,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier* pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier* pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier* pImageMemoryBarriers);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier(
+ VkCommandBuffer commandBuffer,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ VkDependencyFlags dependencyFlags,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier* pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier* pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier* pImageMemoryBarriers);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery(
+ VkCommandBuffer commandBuffer,
+ VkQueryPool queryPool,
+ uint32_t query,
+ VkQueryControlFlags flags);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery(
+ VkCommandBuffer commandBuffer,
+ VkQueryPool queryPool,
+ uint32_t query);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool(
+ VkCommandBuffer commandBuffer,
+ VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp(
+ VkCommandBuffer commandBuffer,
+ VkPipelineStageFlagBits pipelineStage,
+ VkQueryPool queryPool,
+ uint32_t query);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults(
+ VkCommandBuffer commandBuffer,
+ VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount,
+ VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize stride,
+ VkQueryResultFlags flags);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants(
+ VkCommandBuffer commandBuffer,
+ VkPipelineLayout layout,
+ VkShaderStageFlags stageFlags,
+ uint32_t offset,
+ uint32_t size,
+ const void* pValues);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass(
+ VkCommandBuffer commandBuffer,
+ const VkRenderPassBeginInfo* pRenderPassBegin,
+ VkSubpassContents contents);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(
+ VkCommandBuffer commandBuffer,
+ VkSubpassContents contents);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass(
+ VkCommandBuffer commandBuffer);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(
+ VkCommandBuffer commandBuffer,
+ uint32_t commandBufferCount,
+ const VkCommandBuffer* pCommandBuffers);
+#endif
+
+
+#define VK_VERSION_1_1 1
+// Vulkan 1.1 version number
+#define VK_API_VERSION_1_1 VK_MAKE_VERSION(1, 1, 0)// Patch version should always be set to 0
+
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate)
+#define VK_MAX_DEVICE_GROUP_SIZE 32
+#define VK_LUID_SIZE 8
+#define VK_QUEUE_FAMILY_EXTERNAL (~0U-1)
+
+typedef enum VkPointClippingBehavior {
+ VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0,
+ VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1,
+ VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES,
+ VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY,
+ VK_POINT_CLIPPING_BEHAVIOR_BEGIN_RANGE = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES,
+ VK_POINT_CLIPPING_BEHAVIOR_END_RANGE = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY,
+ VK_POINT_CLIPPING_BEHAVIOR_RANGE_SIZE = (VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES + 1),
+ VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF
+} VkPointClippingBehavior;
+
+typedef enum VkTessellationDomainOrigin {
+ VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0,
+ VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1,
+ VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT,
+ VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT,
+ VK_TESSELLATION_DOMAIN_ORIGIN_BEGIN_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT,
+ VK_TESSELLATION_DOMAIN_ORIGIN_END_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT,
+ VK_TESSELLATION_DOMAIN_ORIGIN_RANGE_SIZE = (VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT + 1),
+ VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF
+} VkTessellationDomainOrigin;
+
+typedef enum VkSamplerYcbcrModelConversion {
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_BEGIN_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_END_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_RANGE_SIZE = (VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + 1),
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerYcbcrModelConversion;
+
+typedef enum VkSamplerYcbcrRange {
+ VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0,
+ VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1,
+ VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
+ VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
+ VK_SAMPLER_YCBCR_RANGE_BEGIN_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
+ VK_SAMPLER_YCBCR_RANGE_END_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
+ VK_SAMPLER_YCBCR_RANGE_RANGE_SIZE = (VK_SAMPLER_YCBCR_RANGE_ITU_NARROW - VK_SAMPLER_YCBCR_RANGE_ITU_FULL + 1),
+ VK_SAMPLER_YCBCR_RANGE_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerYcbcrRange;
+
+typedef enum VkChromaLocation {
+ VK_CHROMA_LOCATION_COSITED_EVEN = 0,
+ VK_CHROMA_LOCATION_MIDPOINT = 1,
+ VK_CHROMA_LOCATION_COSITED_EVEN_KHR = VK_CHROMA_LOCATION_COSITED_EVEN,
+ VK_CHROMA_LOCATION_MIDPOINT_KHR = VK_CHROMA_LOCATION_MIDPOINT,
+ VK_CHROMA_LOCATION_BEGIN_RANGE = VK_CHROMA_LOCATION_COSITED_EVEN,
+ VK_CHROMA_LOCATION_END_RANGE = VK_CHROMA_LOCATION_MIDPOINT,
+ VK_CHROMA_LOCATION_RANGE_SIZE = (VK_CHROMA_LOCATION_MIDPOINT - VK_CHROMA_LOCATION_COSITED_EVEN + 1),
+ VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF
+} VkChromaLocation;
+
+typedef enum VkDescriptorUpdateTemplateType {
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_END_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET + 1),
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorUpdateTemplateType;
+
+typedef enum VkSubgroupFeatureFlagBits {
+ VK_SUBGROUP_FEATURE_BASIC_BIT = 0x00000001,
+ VK_SUBGROUP_FEATURE_VOTE_BIT = 0x00000002,
+ VK_SUBGROUP_FEATURE_ARITHMETIC_BIT = 0x00000004,
+ VK_SUBGROUP_FEATURE_BALLOT_BIT = 0x00000008,
+ VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 0x00000010,
+ VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0x00000020,
+ VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0x00000040,
+ VK_SUBGROUP_FEATURE_QUAD_BIT = 0x00000080,
+ VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV = 0x00000100,
+ VK_SUBGROUP_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSubgroupFeatureFlagBits;
+typedef VkFlags VkSubgroupFeatureFlags;
+
+typedef enum VkPeerMemoryFeatureFlagBits {
+ VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0x00000001,
+ VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0x00000002,
+ VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0x00000004,
+ VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0x00000008,
+ VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT,
+ VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_DST_BIT,
+ VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT,
+ VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT,
+ VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkPeerMemoryFeatureFlagBits;
+typedef VkFlags VkPeerMemoryFeatureFlags;
+
+typedef enum VkMemoryAllocateFlagBits {
+ VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001,
+ VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 0x00000002,
+ VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000004,
+ VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT,
+ VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
+ VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT,
+ VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkMemoryAllocateFlagBits;
+typedef VkFlags VkMemoryAllocateFlags;
+typedef VkFlags VkCommandPoolTrimFlags;
+typedef VkFlags VkDescriptorUpdateTemplateCreateFlags;
+
+typedef enum VkExternalMemoryHandleTypeFlagBits {
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 0x00000008,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 0x00000010,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 0x00000020,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 0x00000040,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT = 0x00000200,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID = 0x00000400,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT = 0x00000080,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0x00000100,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalMemoryHandleTypeFlagBits;
+typedef VkFlags VkExternalMemoryHandleTypeFlags;
+
+typedef enum VkExternalMemoryFeatureFlagBits {
+ VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 0x00000001,
+ VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 0x00000002,
+ VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 0x00000004,
+ VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT,
+ VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT,
+ VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
+ VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalMemoryFeatureFlagBits;
+typedef VkFlags VkExternalMemoryFeatureFlags;
+
+typedef enum VkExternalFenceHandleTypeFlagBits {
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000008,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalFenceHandleTypeFlagBits;
+typedef VkFlags VkExternalFenceHandleTypeFlags;
+
+typedef enum VkExternalFenceFeatureFlagBits {
+ VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 0x00000001,
+ VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 0x00000002,
+ VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT,
+ VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT,
+ VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalFenceFeatureFlagBits;
+typedef VkFlags VkExternalFenceFeatureFlags;
+
+typedef enum VkFenceImportFlagBits {
+ VK_FENCE_IMPORT_TEMPORARY_BIT = 0x00000001,
+ VK_FENCE_IMPORT_TEMPORARY_BIT_KHR = VK_FENCE_IMPORT_TEMPORARY_BIT,
+ VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkFenceImportFlagBits;
+typedef VkFlags VkFenceImportFlags;
+
+typedef enum VkSemaphoreImportFlagBits {
+ VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0x00000001,
+ VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
+ VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSemaphoreImportFlagBits;
+typedef VkFlags VkSemaphoreImportFlags;
+
+typedef enum VkExternalSemaphoreHandleTypeFlagBits {
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalSemaphoreHandleTypeFlagBits;
+typedef VkFlags VkExternalSemaphoreHandleTypeFlags;
+
+typedef enum VkExternalSemaphoreFeatureFlagBits {
+ VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 0x00000001,
+ VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 0x00000002,
+ VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT,
+ VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR = VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT,
+ VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalSemaphoreFeatureFlagBits;
+typedef VkFlags VkExternalSemaphoreFeatureFlags;
+typedef struct VkPhysicalDeviceSubgroupProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t subgroupSize;
+ VkShaderStageFlags supportedStages;
+ VkSubgroupFeatureFlags supportedOperations;
+ VkBool32 quadOperationsInAllStages;
+} VkPhysicalDeviceSubgroupProperties;
+
+typedef struct VkBindBufferMemoryInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer buffer;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+} VkBindBufferMemoryInfo;
+
+typedef struct VkBindImageMemoryInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+} VkBindImageMemoryInfo;
+
+typedef struct VkPhysicalDevice16BitStorageFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 storageBuffer16BitAccess;
+ VkBool32 uniformAndStorageBuffer16BitAccess;
+ VkBool32 storagePushConstant16;
+ VkBool32 storageInputOutput16;
+} VkPhysicalDevice16BitStorageFeatures;
+
+typedef struct VkMemoryDedicatedRequirements {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 prefersDedicatedAllocation;
+ VkBool32 requiresDedicatedAllocation;
+} VkMemoryDedicatedRequirements;
+
+typedef struct VkMemoryDedicatedAllocateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+ VkBuffer buffer;
+} VkMemoryDedicatedAllocateInfo;
+
+typedef struct VkMemoryAllocateFlagsInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkMemoryAllocateFlags flags;
+ uint32_t deviceMask;
+} VkMemoryAllocateFlagsInfo;
+
+typedef struct VkDeviceGroupRenderPassBeginInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t deviceMask;
+ uint32_t deviceRenderAreaCount;
+ const VkRect2D* pDeviceRenderAreas;
+} VkDeviceGroupRenderPassBeginInfo;
+
+typedef struct VkDeviceGroupCommandBufferBeginInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t deviceMask;
+} VkDeviceGroupCommandBufferBeginInfo;
+
+typedef struct VkDeviceGroupSubmitInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t waitSemaphoreCount;
+ const uint32_t* pWaitSemaphoreDeviceIndices;
+ uint32_t commandBufferCount;
+ const uint32_t* pCommandBufferDeviceMasks;
+ uint32_t signalSemaphoreCount;
+ const uint32_t* pSignalSemaphoreDeviceIndices;
+} VkDeviceGroupSubmitInfo;
+
+typedef struct VkDeviceGroupBindSparseInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t resourceDeviceIndex;
+ uint32_t memoryDeviceIndex;
+} VkDeviceGroupBindSparseInfo;
+
+typedef struct VkBindBufferMemoryDeviceGroupInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t deviceIndexCount;
+ const uint32_t* pDeviceIndices;
+} VkBindBufferMemoryDeviceGroupInfo;
+
+typedef struct VkBindImageMemoryDeviceGroupInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t deviceIndexCount;
+ const uint32_t* pDeviceIndices;
+ uint32_t splitInstanceBindRegionCount;
+ const VkRect2D* pSplitInstanceBindRegions;
+} VkBindImageMemoryDeviceGroupInfo;
+
+typedef struct VkPhysicalDeviceGroupProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t physicalDeviceCount;
+ VkPhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE];
+ VkBool32 subsetAllocation;
+} VkPhysicalDeviceGroupProperties;
+
+typedef struct VkDeviceGroupDeviceCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t physicalDeviceCount;
+ const VkPhysicalDevice* pPhysicalDevices;
+} VkDeviceGroupDeviceCreateInfo;
+
+typedef struct VkBufferMemoryRequirementsInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer buffer;
+} VkBufferMemoryRequirementsInfo2;
+
+typedef struct VkImageMemoryRequirementsInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+} VkImageMemoryRequirementsInfo2;
+
+typedef struct VkImageSparseMemoryRequirementsInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+} VkImageSparseMemoryRequirementsInfo2;
+
+typedef struct VkMemoryRequirements2 {
+ VkStructureType sType;
+ void* pNext;
+ VkMemoryRequirements memoryRequirements;
+} VkMemoryRequirements2;
+
+typedef VkMemoryRequirements2 VkMemoryRequirements2KHR;
+
+typedef struct VkSparseImageMemoryRequirements2 {
+ VkStructureType sType;
+ void* pNext;
+ VkSparseImageMemoryRequirements memoryRequirements;
+} VkSparseImageMemoryRequirements2;
+
+typedef struct VkPhysicalDeviceFeatures2 {
+ VkStructureType sType;
+ void* pNext;
+ VkPhysicalDeviceFeatures features;
+} VkPhysicalDeviceFeatures2;
+
+typedef struct VkPhysicalDeviceProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkPhysicalDeviceProperties properties;
+} VkPhysicalDeviceProperties2;
+
+typedef struct VkFormatProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkFormatProperties formatProperties;
+} VkFormatProperties2;
+
+typedef struct VkImageFormatProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkImageFormatProperties imageFormatProperties;
+} VkImageFormatProperties2;
+
+typedef struct VkPhysicalDeviceImageFormatInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkFormat format;
+ VkImageType type;
+ VkImageTiling tiling;
+ VkImageUsageFlags usage;
+ VkImageCreateFlags flags;
+} VkPhysicalDeviceImageFormatInfo2;
+
+typedef struct VkQueueFamilyProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkQueueFamilyProperties queueFamilyProperties;
+} VkQueueFamilyProperties2;
+
+typedef struct VkPhysicalDeviceMemoryProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkPhysicalDeviceMemoryProperties memoryProperties;
+} VkPhysicalDeviceMemoryProperties2;
+
+typedef struct VkSparseImageFormatProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkSparseImageFormatProperties properties;
+} VkSparseImageFormatProperties2;
+
+typedef struct VkPhysicalDeviceSparseImageFormatInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkFormat format;
+ VkImageType type;
+ VkSampleCountFlagBits samples;
+ VkImageUsageFlags usage;
+ VkImageTiling tiling;
+} VkPhysicalDeviceSparseImageFormatInfo2;
+
+typedef struct VkPhysicalDevicePointClippingProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkPointClippingBehavior pointClippingBehavior;
+} VkPhysicalDevicePointClippingProperties;
+
+typedef struct VkInputAttachmentAspectReference {
+ uint32_t subpass;
+ uint32_t inputAttachmentIndex;
+ VkImageAspectFlags aspectMask;
+} VkInputAttachmentAspectReference;
+
+typedef struct VkRenderPassInputAttachmentAspectCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t aspectReferenceCount;
+ const VkInputAttachmentAspectReference* pAspectReferences;
+} VkRenderPassInputAttachmentAspectCreateInfo;
+
+typedef struct VkImageViewUsageCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageUsageFlags usage;
+} VkImageViewUsageCreateInfo;
+
+typedef struct VkPipelineTessellationDomainOriginStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkTessellationDomainOrigin domainOrigin;
+} VkPipelineTessellationDomainOriginStateCreateInfo;
+
+typedef struct VkRenderPassMultiviewCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t subpassCount;
+ const uint32_t* pViewMasks;
+ uint32_t dependencyCount;
+ const int32_t* pViewOffsets;
+ uint32_t correlationMaskCount;
+ const uint32_t* pCorrelationMasks;
+} VkRenderPassMultiviewCreateInfo;
+
+typedef struct VkPhysicalDeviceMultiviewFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 multiview;
+ VkBool32 multiviewGeometryShader;
+ VkBool32 multiviewTessellationShader;
+} VkPhysicalDeviceMultiviewFeatures;
+
+typedef struct VkPhysicalDeviceMultiviewProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxMultiviewViewCount;
+ uint32_t maxMultiviewInstanceIndex;
+} VkPhysicalDeviceMultiviewProperties;
+
+typedef struct VkPhysicalDeviceVariablePointersFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 variablePointersStorageBuffer;
+ VkBool32 variablePointers;
+} VkPhysicalDeviceVariablePointersFeatures;
+
+typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeatures;
+
+typedef struct VkPhysicalDeviceProtectedMemoryFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 protectedMemory;
+} VkPhysicalDeviceProtectedMemoryFeatures;
+
+typedef struct VkPhysicalDeviceProtectedMemoryProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 protectedNoFault;
+} VkPhysicalDeviceProtectedMemoryProperties;
+
+typedef struct VkDeviceQueueInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceQueueCreateFlags flags;
+ uint32_t queueFamilyIndex;
+ uint32_t queueIndex;
+} VkDeviceQueueInfo2;
+
+typedef struct VkProtectedSubmitInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 protectedSubmit;
+} VkProtectedSubmitInfo;
+
+typedef struct VkSamplerYcbcrConversionCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkFormat format;
+ VkSamplerYcbcrModelConversion ycbcrModel;
+ VkSamplerYcbcrRange ycbcrRange;
+ VkComponentMapping components;
+ VkChromaLocation xChromaOffset;
+ VkChromaLocation yChromaOffset;
+ VkFilter chromaFilter;
+ VkBool32 forceExplicitReconstruction;
+} VkSamplerYcbcrConversionCreateInfo;
+
+typedef struct VkSamplerYcbcrConversionInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkSamplerYcbcrConversion conversion;
+} VkSamplerYcbcrConversionInfo;
+
+typedef struct VkBindImagePlaneMemoryInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageAspectFlagBits planeAspect;
+} VkBindImagePlaneMemoryInfo;
+
+typedef struct VkImagePlaneMemoryRequirementsInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageAspectFlagBits planeAspect;
+} VkImagePlaneMemoryRequirementsInfo;
+
+typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 samplerYcbcrConversion;
+} VkPhysicalDeviceSamplerYcbcrConversionFeatures;
+
+typedef struct VkSamplerYcbcrConversionImageFormatProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t combinedImageSamplerDescriptorCount;
+} VkSamplerYcbcrConversionImageFormatProperties;
+
+typedef struct VkDescriptorUpdateTemplateEntry {
+ uint32_t dstBinding;
+ uint32_t dstArrayElement;
+ uint32_t descriptorCount;
+ VkDescriptorType descriptorType;
+ size_t offset;
+ size_t stride;
+} VkDescriptorUpdateTemplateEntry;
+
+typedef struct VkDescriptorUpdateTemplateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkDescriptorUpdateTemplateCreateFlags flags;
+ uint32_t descriptorUpdateEntryCount;
+ const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries;
+ VkDescriptorUpdateTemplateType templateType;
+ VkDescriptorSetLayout descriptorSetLayout;
+ VkPipelineBindPoint pipelineBindPoint;
+ VkPipelineLayout pipelineLayout;
+ uint32_t set;
+} VkDescriptorUpdateTemplateCreateInfo;
+
+typedef struct VkExternalMemoryProperties {
+ VkExternalMemoryFeatureFlags externalMemoryFeatures;
+ VkExternalMemoryHandleTypeFlags exportFromImportedHandleTypes;
+ VkExternalMemoryHandleTypeFlags compatibleHandleTypes;
+} VkExternalMemoryProperties;
+
+typedef struct VkPhysicalDeviceExternalImageFormatInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+} VkPhysicalDeviceExternalImageFormatInfo;
+
+typedef struct VkExternalImageFormatProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalMemoryProperties externalMemoryProperties;
+} VkExternalImageFormatProperties;
+
+typedef struct VkPhysicalDeviceExternalBufferInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkBufferCreateFlags flags;
+ VkBufferUsageFlags usage;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+} VkPhysicalDeviceExternalBufferInfo;
+
+typedef struct VkExternalBufferProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalMemoryProperties externalMemoryProperties;
+} VkExternalBufferProperties;
+
+typedef struct VkPhysicalDeviceIDProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint8_t deviceUUID[VK_UUID_SIZE];
+ uint8_t driverUUID[VK_UUID_SIZE];
+ uint8_t deviceLUID[VK_LUID_SIZE];
+ uint32_t deviceNodeMask;
+ VkBool32 deviceLUIDValid;
+} VkPhysicalDeviceIDProperties;
+
+typedef struct VkExternalMemoryImageCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlags handleTypes;
+} VkExternalMemoryImageCreateInfo;
+
+typedef struct VkExternalMemoryBufferCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlags handleTypes;
+} VkExternalMemoryBufferCreateInfo;
+
+typedef struct VkExportMemoryAllocateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlags handleTypes;
+} VkExportMemoryAllocateInfo;
+
+typedef struct VkPhysicalDeviceExternalFenceInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalFenceHandleTypeFlagBits handleType;
+} VkPhysicalDeviceExternalFenceInfo;
+
+typedef struct VkExternalFenceProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalFenceHandleTypeFlags exportFromImportedHandleTypes;
+ VkExternalFenceHandleTypeFlags compatibleHandleTypes;
+ VkExternalFenceFeatureFlags externalFenceFeatures;
+} VkExternalFenceProperties;
+
+typedef struct VkExportFenceCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalFenceHandleTypeFlags handleTypes;
+} VkExportFenceCreateInfo;
+
+typedef struct VkExportSemaphoreCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalSemaphoreHandleTypeFlags handleTypes;
+} VkExportSemaphoreCreateInfo;
+
+typedef struct VkPhysicalDeviceExternalSemaphoreInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalSemaphoreHandleTypeFlagBits handleType;
+} VkPhysicalDeviceExternalSemaphoreInfo;
+
+typedef struct VkExternalSemaphoreProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalSemaphoreHandleTypeFlags exportFromImportedHandleTypes;
+ VkExternalSemaphoreHandleTypeFlags compatibleHandleTypes;
+ VkExternalSemaphoreFeatureFlags externalSemaphoreFeatures;
+} VkExternalSemaphoreProperties;
+
+typedef struct VkPhysicalDeviceMaintenance3Properties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxPerSetDescriptors;
+ VkDeviceSize maxMemoryAllocationSize;
+} VkPhysicalDeviceMaintenance3Properties;
+
+typedef struct VkDescriptorSetLayoutSupport {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 supported;
+} VkDescriptorSetLayoutSupport;
+
+typedef struct VkPhysicalDeviceShaderDrawParametersFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderDrawParameters;
+} VkPhysicalDeviceShaderDrawParametersFeatures;
+
+typedef VkPhysicalDeviceShaderDrawParametersFeatures VkPhysicalDeviceShaderDrawParameterFeatures;
+
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceVersion)(uint32_t* pApiVersion);
+typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeatures)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMask)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+typedef void (VKAPI_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroups)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+typedef void (VKAPI_PTR *PFN_vkTrimCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue2)(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversion)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplate)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplate)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFenceProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupport)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion(
+ uint32_t* pApiVersion);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindBufferMemoryInfo* pBindInfos);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindImageMemoryInfo* pBindInfos);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeatures(
+ VkDevice device,
+ uint32_t heapIndex,
+ uint32_t localDeviceIndex,
+ uint32_t remoteDeviceIndex,
+ VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMask(
+ VkCommandBuffer commandBuffer,
+ uint32_t deviceMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBase(
+ VkCommandBuffer commandBuffer,
+ uint32_t baseGroupX,
+ uint32_t baseGroupY,
+ uint32_t baseGroupZ,
+ uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2(
+ VkDevice device,
+ const VkImageMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2(
+ VkDevice device,
+ const VkBufferMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2(
+ VkDevice device,
+ const VkImageSparseMemoryRequirementsInfo2* pInfo,
+ uint32_t* pSparseMemoryRequirementCount,
+ VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures2* pFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2* pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties2* pFormatProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
+ VkImageFormatProperties2* pImageFormatProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2* pQueueFamilyProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
+ uint32_t* pPropertyCount,
+ VkSparseImageFormatProperties2* pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkTrimCommandPool(
+ VkDevice device,
+ VkCommandPool commandPool,
+ VkCommandPoolTrimFlags flags);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue2(
+ VkDevice device,
+ const VkDeviceQueueInfo2* pQueueInfo,
+ VkQueue* pQueue);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion(
+ VkDevice device,
+ const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSamplerYcbcrConversion* pYcbcrConversion);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion(
+ VkDevice device,
+ VkSamplerYcbcrConversion ycbcrConversion,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplate(
+ VkDevice device,
+ const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplate(
+ VkDevice device,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplate(
+ VkDevice device,
+ VkDescriptorSet descriptorSet,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const void* pData);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
+ VkExternalFenceProperties* pExternalFenceProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+ VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport(
+ VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ VkDescriptorSetLayoutSupport* pSupport);
+#endif
+
+
+#define VK_VERSION_1_2 1
+// Vulkan 1.2 version number
+#define VK_API_VERSION_1_2 VK_MAKE_VERSION(1, 2, 0)// Patch version should always be set to 0
+
+typedef uint64_t VkDeviceAddress;
+#define VK_MAX_DRIVER_NAME_SIZE 256
+#define VK_MAX_DRIVER_INFO_SIZE 256
+
+typedef enum VkDriverId {
+ VK_DRIVER_ID_AMD_PROPRIETARY = 1,
+ VK_DRIVER_ID_AMD_OPEN_SOURCE = 2,
+ VK_DRIVER_ID_MESA_RADV = 3,
+ VK_DRIVER_ID_NVIDIA_PROPRIETARY = 4,
+ VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS = 5,
+ VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA = 6,
+ VK_DRIVER_ID_IMAGINATION_PROPRIETARY = 7,
+ VK_DRIVER_ID_QUALCOMM_PROPRIETARY = 8,
+ VK_DRIVER_ID_ARM_PROPRIETARY = 9,
+ VK_DRIVER_ID_GOOGLE_SWIFTSHADER = 10,
+ VK_DRIVER_ID_GGP_PROPRIETARY = 11,
+ VK_DRIVER_ID_BROADCOM_PROPRIETARY = 12,
+ VK_DRIVER_ID_AMD_PROPRIETARY_KHR = VK_DRIVER_ID_AMD_PROPRIETARY,
+ VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = VK_DRIVER_ID_AMD_OPEN_SOURCE,
+ VK_DRIVER_ID_MESA_RADV_KHR = VK_DRIVER_ID_MESA_RADV,
+ VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = VK_DRIVER_ID_NVIDIA_PROPRIETARY,
+ VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS,
+ VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA,
+ VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = VK_DRIVER_ID_IMAGINATION_PROPRIETARY,
+ VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = VK_DRIVER_ID_QUALCOMM_PROPRIETARY,
+ VK_DRIVER_ID_ARM_PROPRIETARY_KHR = VK_DRIVER_ID_ARM_PROPRIETARY,
+ VK_DRIVER_ID_GOOGLE_SWIFTSHADER_KHR = VK_DRIVER_ID_GOOGLE_SWIFTSHADER,
+ VK_DRIVER_ID_GGP_PROPRIETARY_KHR = VK_DRIVER_ID_GGP_PROPRIETARY,
+ VK_DRIVER_ID_BROADCOM_PROPRIETARY_KHR = VK_DRIVER_ID_BROADCOM_PROPRIETARY,
+ VK_DRIVER_ID_BEGIN_RANGE = VK_DRIVER_ID_AMD_PROPRIETARY,
+ VK_DRIVER_ID_END_RANGE = VK_DRIVER_ID_BROADCOM_PROPRIETARY,
+ VK_DRIVER_ID_RANGE_SIZE = (VK_DRIVER_ID_BROADCOM_PROPRIETARY - VK_DRIVER_ID_AMD_PROPRIETARY + 1),
+ VK_DRIVER_ID_MAX_ENUM = 0x7FFFFFFF
+} VkDriverId;
+
+typedef enum VkShaderFloatControlsIndependence {
+ VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY = 0,
+ VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL = 1,
+ VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE = 2,
+ VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY,
+ VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL,
+ VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE,
+ VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_BEGIN_RANGE = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY,
+ VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_END_RANGE = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE,
+ VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_RANGE_SIZE = (VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE - VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY + 1),
+ VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_MAX_ENUM = 0x7FFFFFFF
+} VkShaderFloatControlsIndependence;
+
+typedef enum VkSamplerReductionMode {
+ VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0,
+ VK_SAMPLER_REDUCTION_MODE_MIN = 1,
+ VK_SAMPLER_REDUCTION_MODE_MAX = 2,
+ VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE,
+ VK_SAMPLER_REDUCTION_MODE_MIN_EXT = VK_SAMPLER_REDUCTION_MODE_MIN,
+ VK_SAMPLER_REDUCTION_MODE_MAX_EXT = VK_SAMPLER_REDUCTION_MODE_MAX,
+ VK_SAMPLER_REDUCTION_MODE_BEGIN_RANGE = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE,
+ VK_SAMPLER_REDUCTION_MODE_END_RANGE = VK_SAMPLER_REDUCTION_MODE_MAX,
+ VK_SAMPLER_REDUCTION_MODE_RANGE_SIZE = (VK_SAMPLER_REDUCTION_MODE_MAX - VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE + 1),
+ VK_SAMPLER_REDUCTION_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerReductionMode;
+
+typedef enum VkSemaphoreType {
+ VK_SEMAPHORE_TYPE_BINARY = 0,
+ VK_SEMAPHORE_TYPE_TIMELINE = 1,
+ VK_SEMAPHORE_TYPE_BINARY_KHR = VK_SEMAPHORE_TYPE_BINARY,
+ VK_SEMAPHORE_TYPE_TIMELINE_KHR = VK_SEMAPHORE_TYPE_TIMELINE,
+ VK_SEMAPHORE_TYPE_BEGIN_RANGE = VK_SEMAPHORE_TYPE_BINARY,
+ VK_SEMAPHORE_TYPE_END_RANGE = VK_SEMAPHORE_TYPE_TIMELINE,
+ VK_SEMAPHORE_TYPE_RANGE_SIZE = (VK_SEMAPHORE_TYPE_TIMELINE - VK_SEMAPHORE_TYPE_BINARY + 1),
+ VK_SEMAPHORE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkSemaphoreType;
+
+typedef enum VkResolveModeFlagBits {
+ VK_RESOLVE_MODE_NONE = 0,
+ VK_RESOLVE_MODE_SAMPLE_ZERO_BIT = 0x00000001,
+ VK_RESOLVE_MODE_AVERAGE_BIT = 0x00000002,
+ VK_RESOLVE_MODE_MIN_BIT = 0x00000004,
+ VK_RESOLVE_MODE_MAX_BIT = 0x00000008,
+ VK_RESOLVE_MODE_NONE_KHR = VK_RESOLVE_MODE_NONE,
+ VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
+ VK_RESOLVE_MODE_AVERAGE_BIT_KHR = VK_RESOLVE_MODE_AVERAGE_BIT,
+ VK_RESOLVE_MODE_MIN_BIT_KHR = VK_RESOLVE_MODE_MIN_BIT,
+ VK_RESOLVE_MODE_MAX_BIT_KHR = VK_RESOLVE_MODE_MAX_BIT,
+ VK_RESOLVE_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkResolveModeFlagBits;
+typedef VkFlags VkResolveModeFlags;
+
+typedef enum VkDescriptorBindingFlagBits {
+ VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 0x00000001,
+ VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0x00000002,
+ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0x00000004,
+ VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0x00000008,
+ VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
+ VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
+ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT,
+ VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT,
+ VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorBindingFlagBits;
+typedef VkFlags VkDescriptorBindingFlags;
+
+typedef enum VkSemaphoreWaitFlagBits {
+ VK_SEMAPHORE_WAIT_ANY_BIT = 0x00000001,
+ VK_SEMAPHORE_WAIT_ANY_BIT_KHR = VK_SEMAPHORE_WAIT_ANY_BIT,
+ VK_SEMAPHORE_WAIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSemaphoreWaitFlagBits;
+typedef VkFlags VkSemaphoreWaitFlags;
+typedef struct VkPhysicalDeviceVulkan11Features {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 storageBuffer16BitAccess;
+ VkBool32 uniformAndStorageBuffer16BitAccess;
+ VkBool32 storagePushConstant16;
+ VkBool32 storageInputOutput16;
+ VkBool32 multiview;
+ VkBool32 multiviewGeometryShader;
+ VkBool32 multiviewTessellationShader;
+ VkBool32 variablePointersStorageBuffer;
+ VkBool32 variablePointers;
+ VkBool32 protectedMemory;
+ VkBool32 samplerYcbcrConversion;
+ VkBool32 shaderDrawParameters;
+} VkPhysicalDeviceVulkan11Features;
+
+typedef struct VkPhysicalDeviceVulkan11Properties {
+ VkStructureType sType;
+ void* pNext;
+ uint8_t deviceUUID[VK_UUID_SIZE];
+ uint8_t driverUUID[VK_UUID_SIZE];
+ uint8_t deviceLUID[VK_LUID_SIZE];
+ uint32_t deviceNodeMask;
+ VkBool32 deviceLUIDValid;
+ uint32_t subgroupSize;
+ VkShaderStageFlags subgroupSupportedStages;
+ VkSubgroupFeatureFlags subgroupSupportedOperations;
+ VkBool32 subgroupQuadOperationsInAllStages;
+ VkPointClippingBehavior pointClippingBehavior;
+ uint32_t maxMultiviewViewCount;
+ uint32_t maxMultiviewInstanceIndex;
+ VkBool32 protectedNoFault;
+ uint32_t maxPerSetDescriptors;
+ VkDeviceSize maxMemoryAllocationSize;
+} VkPhysicalDeviceVulkan11Properties;
+
+typedef struct VkPhysicalDeviceVulkan12Features {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 samplerMirrorClampToEdge;
+ VkBool32 drawIndirectCount;
+ VkBool32 storageBuffer8BitAccess;
+ VkBool32 uniformAndStorageBuffer8BitAccess;
+ VkBool32 storagePushConstant8;
+ VkBool32 shaderBufferInt64Atomics;
+ VkBool32 shaderSharedInt64Atomics;
+ VkBool32 shaderFloat16;
+ VkBool32 shaderInt8;
+ VkBool32 descriptorIndexing;
+ VkBool32 shaderInputAttachmentArrayDynamicIndexing;
+ VkBool32 shaderUniformTexelBufferArrayDynamicIndexing;
+ VkBool32 shaderStorageTexelBufferArrayDynamicIndexing;
+ VkBool32 shaderUniformBufferArrayNonUniformIndexing;
+ VkBool32 shaderSampledImageArrayNonUniformIndexing;
+ VkBool32 shaderStorageBufferArrayNonUniformIndexing;
+ VkBool32 shaderStorageImageArrayNonUniformIndexing;
+ VkBool32 shaderInputAttachmentArrayNonUniformIndexing;
+ VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing;
+ VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing;
+ VkBool32 descriptorBindingUniformBufferUpdateAfterBind;
+ VkBool32 descriptorBindingSampledImageUpdateAfterBind;
+ VkBool32 descriptorBindingStorageImageUpdateAfterBind;
+ VkBool32 descriptorBindingStorageBufferUpdateAfterBind;
+ VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind;
+ VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind;
+ VkBool32 descriptorBindingUpdateUnusedWhilePending;
+ VkBool32 descriptorBindingPartiallyBound;
+ VkBool32 descriptorBindingVariableDescriptorCount;
+ VkBool32 runtimeDescriptorArray;
+ VkBool32 samplerFilterMinmax;
+ VkBool32 scalarBlockLayout;
+ VkBool32 imagelessFramebuffer;
+ VkBool32 uniformBufferStandardLayout;
+ VkBool32 shaderSubgroupExtendedTypes;
+ VkBool32 separateDepthStencilLayouts;
+ VkBool32 hostQueryReset;
+ VkBool32 timelineSemaphore;
+ VkBool32 bufferDeviceAddress;
+ VkBool32 bufferDeviceAddressCaptureReplay;
+ VkBool32 bufferDeviceAddressMultiDevice;
+ VkBool32 vulkanMemoryModel;
+ VkBool32 vulkanMemoryModelDeviceScope;
+ VkBool32 vulkanMemoryModelAvailabilityVisibilityChains;
+ VkBool32 shaderOutputViewportIndex;
+ VkBool32 shaderOutputLayer;
+ VkBool32 subgroupBroadcastDynamicId;
+} VkPhysicalDeviceVulkan12Features;
+
+typedef struct VkConformanceVersion {
+ uint8_t major;
+ uint8_t minor;
+ uint8_t subminor;
+ uint8_t patch;
+} VkConformanceVersion;
+
+typedef struct VkPhysicalDeviceVulkan12Properties {
+ VkStructureType sType;
+ void* pNext;
+ VkDriverId driverID;
+ char driverName[VK_MAX_DRIVER_NAME_SIZE];
+ char driverInfo[VK_MAX_DRIVER_INFO_SIZE];
+ VkConformanceVersion conformanceVersion;
+ VkShaderFloatControlsIndependence denormBehaviorIndependence;
+ VkShaderFloatControlsIndependence roundingModeIndependence;
+ VkBool32 shaderSignedZeroInfNanPreserveFloat16;
+ VkBool32 shaderSignedZeroInfNanPreserveFloat32;
+ VkBool32 shaderSignedZeroInfNanPreserveFloat64;
+ VkBool32 shaderDenormPreserveFloat16;
+ VkBool32 shaderDenormPreserveFloat32;
+ VkBool32 shaderDenormPreserveFloat64;
+ VkBool32 shaderDenormFlushToZeroFloat16;
+ VkBool32 shaderDenormFlushToZeroFloat32;
+ VkBool32 shaderDenormFlushToZeroFloat64;
+ VkBool32 shaderRoundingModeRTEFloat16;
+ VkBool32 shaderRoundingModeRTEFloat32;
+ VkBool32 shaderRoundingModeRTEFloat64;
+ VkBool32 shaderRoundingModeRTZFloat16;
+ VkBool32 shaderRoundingModeRTZFloat32;
+ VkBool32 shaderRoundingModeRTZFloat64;
+ uint32_t maxUpdateAfterBindDescriptorsInAllPools;
+ VkBool32 shaderUniformBufferArrayNonUniformIndexingNative;
+ VkBool32 shaderSampledImageArrayNonUniformIndexingNative;
+ VkBool32 shaderStorageBufferArrayNonUniformIndexingNative;
+ VkBool32 shaderStorageImageArrayNonUniformIndexingNative;
+ VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative;
+ VkBool32 robustBufferAccessUpdateAfterBind;
+ VkBool32 quadDivergentImplicitLod;
+ uint32_t maxPerStageDescriptorUpdateAfterBindSamplers;
+ uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers;
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers;
+ uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages;
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages;
+ uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments;
+ uint32_t maxPerStageUpdateAfterBindResources;
+ uint32_t maxDescriptorSetUpdateAfterBindSamplers;
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers;
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic;
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers;
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic;
+ uint32_t maxDescriptorSetUpdateAfterBindSampledImages;
+ uint32_t maxDescriptorSetUpdateAfterBindStorageImages;
+ uint32_t maxDescriptorSetUpdateAfterBindInputAttachments;
+ VkResolveModeFlags supportedDepthResolveModes;
+ VkResolveModeFlags supportedStencilResolveModes;
+ VkBool32 independentResolveNone;
+ VkBool32 independentResolve;
+ VkBool32 filterMinmaxSingleComponentFormats;
+ VkBool32 filterMinmaxImageComponentMapping;
+ uint64_t maxTimelineSemaphoreValueDifference;
+ VkSampleCountFlags framebufferIntegerColorSampleCounts;
+} VkPhysicalDeviceVulkan12Properties;
+
+typedef struct VkImageFormatListCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t viewFormatCount;
+ const VkFormat* pViewFormats;
+} VkImageFormatListCreateInfo;
+
+typedef struct VkAttachmentDescription2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkAttachmentDescriptionFlags flags;
+ VkFormat format;
+ VkSampleCountFlagBits samples;
+ VkAttachmentLoadOp loadOp;
+ VkAttachmentStoreOp storeOp;
+ VkAttachmentLoadOp stencilLoadOp;
+ VkAttachmentStoreOp stencilStoreOp;
+ VkImageLayout initialLayout;
+ VkImageLayout finalLayout;
+} VkAttachmentDescription2;
+
+typedef struct VkAttachmentReference2 {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t attachment;
+ VkImageLayout layout;
+ VkImageAspectFlags aspectMask;
+} VkAttachmentReference2;
+
+typedef struct VkSubpassDescription2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkSubpassDescriptionFlags flags;
+ VkPipelineBindPoint pipelineBindPoint;
+ uint32_t viewMask;
+ uint32_t inputAttachmentCount;
+ const VkAttachmentReference2* pInputAttachments;
+ uint32_t colorAttachmentCount;
+ const VkAttachmentReference2* pColorAttachments;
+ const VkAttachmentReference2* pResolveAttachments;
+ const VkAttachmentReference2* pDepthStencilAttachment;
+ uint32_t preserveAttachmentCount;
+ const uint32_t* pPreserveAttachments;
+} VkSubpassDescription2;
+
+typedef struct VkSubpassDependency2 {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t srcSubpass;
+ uint32_t dstSubpass;
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
+ VkAccessFlags srcAccessMask;
+ VkAccessFlags dstAccessMask;
+ VkDependencyFlags dependencyFlags;
+ int32_t viewOffset;
+} VkSubpassDependency2;
+
+typedef struct VkRenderPassCreateInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkRenderPassCreateFlags flags;
+ uint32_t attachmentCount;
+ const VkAttachmentDescription2* pAttachments;
+ uint32_t subpassCount;
+ const VkSubpassDescription2* pSubpasses;
+ uint32_t dependencyCount;
+ const VkSubpassDependency2* pDependencies;
+ uint32_t correlatedViewMaskCount;
+ const uint32_t* pCorrelatedViewMasks;
+} VkRenderPassCreateInfo2;
+
+typedef struct VkSubpassBeginInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkSubpassContents contents;
+} VkSubpassBeginInfo;
+
+typedef struct VkSubpassEndInfo {
+ VkStructureType sType;
+ const void* pNext;
+} VkSubpassEndInfo;
+
+typedef struct VkPhysicalDevice8BitStorageFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 storageBuffer8BitAccess;
+ VkBool32 uniformAndStorageBuffer8BitAccess;
+ VkBool32 storagePushConstant8;
+} VkPhysicalDevice8BitStorageFeatures;
+
+typedef struct VkPhysicalDeviceDriverProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkDriverId driverID;
+ char driverName[VK_MAX_DRIVER_NAME_SIZE];
+ char driverInfo[VK_MAX_DRIVER_INFO_SIZE];
+ VkConformanceVersion conformanceVersion;
+} VkPhysicalDeviceDriverProperties;
+
+typedef struct VkPhysicalDeviceShaderAtomicInt64Features {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderBufferInt64Atomics;
+ VkBool32 shaderSharedInt64Atomics;
+} VkPhysicalDeviceShaderAtomicInt64Features;
+
+typedef struct VkPhysicalDeviceShaderFloat16Int8Features {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderFloat16;
+ VkBool32 shaderInt8;
+} VkPhysicalDeviceShaderFloat16Int8Features;
+
+typedef struct VkPhysicalDeviceFloatControlsProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkShaderFloatControlsIndependence denormBehaviorIndependence;
+ VkShaderFloatControlsIndependence roundingModeIndependence;
+ VkBool32 shaderSignedZeroInfNanPreserveFloat16;
+ VkBool32 shaderSignedZeroInfNanPreserveFloat32;
+ VkBool32 shaderSignedZeroInfNanPreserveFloat64;
+ VkBool32 shaderDenormPreserveFloat16;
+ VkBool32 shaderDenormPreserveFloat32;
+ VkBool32 shaderDenormPreserveFloat64;
+ VkBool32 shaderDenormFlushToZeroFloat16;
+ VkBool32 shaderDenormFlushToZeroFloat32;
+ VkBool32 shaderDenormFlushToZeroFloat64;
+ VkBool32 shaderRoundingModeRTEFloat16;
+ VkBool32 shaderRoundingModeRTEFloat32;
+ VkBool32 shaderRoundingModeRTEFloat64;
+ VkBool32 shaderRoundingModeRTZFloat16;
+ VkBool32 shaderRoundingModeRTZFloat32;
+ VkBool32 shaderRoundingModeRTZFloat64;
+} VkPhysicalDeviceFloatControlsProperties;
+
+typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t bindingCount;
+ const VkDescriptorBindingFlags* pBindingFlags;
+} VkDescriptorSetLayoutBindingFlagsCreateInfo;
+
+typedef struct VkPhysicalDeviceDescriptorIndexingFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderInputAttachmentArrayDynamicIndexing;
+ VkBool32 shaderUniformTexelBufferArrayDynamicIndexing;
+ VkBool32 shaderStorageTexelBufferArrayDynamicIndexing;
+ VkBool32 shaderUniformBufferArrayNonUniformIndexing;
+ VkBool32 shaderSampledImageArrayNonUniformIndexing;
+ VkBool32 shaderStorageBufferArrayNonUniformIndexing;
+ VkBool32 shaderStorageImageArrayNonUniformIndexing;
+ VkBool32 shaderInputAttachmentArrayNonUniformIndexing;
+ VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing;
+ VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing;
+ VkBool32 descriptorBindingUniformBufferUpdateAfterBind;
+ VkBool32 descriptorBindingSampledImageUpdateAfterBind;
+ VkBool32 descriptorBindingStorageImageUpdateAfterBind;
+ VkBool32 descriptorBindingStorageBufferUpdateAfterBind;
+ VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind;
+ VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind;
+ VkBool32 descriptorBindingUpdateUnusedWhilePending;
+ VkBool32 descriptorBindingPartiallyBound;
+ VkBool32 descriptorBindingVariableDescriptorCount;
+ VkBool32 runtimeDescriptorArray;
+} VkPhysicalDeviceDescriptorIndexingFeatures;
+
+typedef struct VkPhysicalDeviceDescriptorIndexingProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxUpdateAfterBindDescriptorsInAllPools;
+ VkBool32 shaderUniformBufferArrayNonUniformIndexingNative;
+ VkBool32 shaderSampledImageArrayNonUniformIndexingNative;
+ VkBool32 shaderStorageBufferArrayNonUniformIndexingNative;
+ VkBool32 shaderStorageImageArrayNonUniformIndexingNative;
+ VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative;
+ VkBool32 robustBufferAccessUpdateAfterBind;
+ VkBool32 quadDivergentImplicitLod;
+ uint32_t maxPerStageDescriptorUpdateAfterBindSamplers;
+ uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers;
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers;
+ uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages;
+ uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages;
+ uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments;
+ uint32_t maxPerStageUpdateAfterBindResources;
+ uint32_t maxDescriptorSetUpdateAfterBindSamplers;
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers;
+ uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic;
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers;
+ uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic;
+ uint32_t maxDescriptorSetUpdateAfterBindSampledImages;
+ uint32_t maxDescriptorSetUpdateAfterBindStorageImages;
+ uint32_t maxDescriptorSetUpdateAfterBindInputAttachments;
+} VkPhysicalDeviceDescriptorIndexingProperties;
+
+typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t descriptorSetCount;
+ const uint32_t* pDescriptorCounts;
+} VkDescriptorSetVariableDescriptorCountAllocateInfo;
+
+typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupport {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxVariableDescriptorCount;
+} VkDescriptorSetVariableDescriptorCountLayoutSupport;
+
+typedef struct VkSubpassDescriptionDepthStencilResolve {
+ VkStructureType sType;
+ const void* pNext;
+ VkResolveModeFlagBits depthResolveMode;
+ VkResolveModeFlagBits stencilResolveMode;
+ const VkAttachmentReference2* pDepthStencilResolveAttachment;
+} VkSubpassDescriptionDepthStencilResolve;
+
+typedef struct VkPhysicalDeviceDepthStencilResolveProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkResolveModeFlags supportedDepthResolveModes;
+ VkResolveModeFlags supportedStencilResolveModes;
+ VkBool32 independentResolveNone;
+ VkBool32 independentResolve;
+} VkPhysicalDeviceDepthStencilResolveProperties;
+
+typedef struct VkPhysicalDeviceScalarBlockLayoutFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 scalarBlockLayout;
+} VkPhysicalDeviceScalarBlockLayoutFeatures;
+
+typedef struct VkImageStencilUsageCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageUsageFlags stencilUsage;
+} VkImageStencilUsageCreateInfo;
+
+typedef struct VkSamplerReductionModeCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkSamplerReductionMode reductionMode;
+} VkSamplerReductionModeCreateInfo;
+
+typedef struct VkPhysicalDeviceSamplerFilterMinmaxProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 filterMinmaxSingleComponentFormats;
+ VkBool32 filterMinmaxImageComponentMapping;
+} VkPhysicalDeviceSamplerFilterMinmaxProperties;
+
+typedef struct VkPhysicalDeviceVulkanMemoryModelFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 vulkanMemoryModel;
+ VkBool32 vulkanMemoryModelDeviceScope;
+ VkBool32 vulkanMemoryModelAvailabilityVisibilityChains;
+} VkPhysicalDeviceVulkanMemoryModelFeatures;
+
+typedef struct VkPhysicalDeviceImagelessFramebufferFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 imagelessFramebuffer;
+} VkPhysicalDeviceImagelessFramebufferFeatures;
+
+typedef struct VkFramebufferAttachmentImageInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageCreateFlags flags;
+ VkImageUsageFlags usage;
+ uint32_t width;
+ uint32_t height;
+ uint32_t layerCount;
+ uint32_t viewFormatCount;
+ const VkFormat* pViewFormats;
+} VkFramebufferAttachmentImageInfo;
+
+typedef struct VkFramebufferAttachmentsCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t attachmentImageInfoCount;
+ const VkFramebufferAttachmentImageInfo* pAttachmentImageInfos;
+} VkFramebufferAttachmentsCreateInfo;
+
+typedef struct VkRenderPassAttachmentBeginInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t attachmentCount;
+ const VkImageView* pAttachments;
+} VkRenderPassAttachmentBeginInfo;
+
+typedef struct VkPhysicalDeviceUniformBufferStandardLayoutFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 uniformBufferStandardLayout;
+} VkPhysicalDeviceUniformBufferStandardLayoutFeatures;
+
+typedef struct VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderSubgroupExtendedTypes;
+} VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures;
+
+typedef struct VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 separateDepthStencilLayouts;
+} VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures;
+
+typedef struct VkAttachmentReferenceStencilLayout {
+ VkStructureType sType;
+ void* pNext;
+ VkImageLayout stencilLayout;
+} VkAttachmentReferenceStencilLayout;
+
+typedef struct VkAttachmentDescriptionStencilLayout {
+ VkStructureType sType;
+ void* pNext;
+ VkImageLayout stencilInitialLayout;
+ VkImageLayout stencilFinalLayout;
+} VkAttachmentDescriptionStencilLayout;
+
+typedef struct VkPhysicalDeviceHostQueryResetFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 hostQueryReset;
+} VkPhysicalDeviceHostQueryResetFeatures;
+
+typedef struct VkPhysicalDeviceTimelineSemaphoreFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 timelineSemaphore;
+} VkPhysicalDeviceTimelineSemaphoreFeatures;
+
+typedef struct VkPhysicalDeviceTimelineSemaphoreProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint64_t maxTimelineSemaphoreValueDifference;
+} VkPhysicalDeviceTimelineSemaphoreProperties;
+
+typedef struct VkSemaphoreTypeCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphoreType semaphoreType;
+ uint64_t initialValue;
+} VkSemaphoreTypeCreateInfo;
+
+typedef struct VkTimelineSemaphoreSubmitInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t waitSemaphoreValueCount;
+ const uint64_t* pWaitSemaphoreValues;
+ uint32_t signalSemaphoreValueCount;
+ const uint64_t* pSignalSemaphoreValues;
+} VkTimelineSemaphoreSubmitInfo;
+
+typedef struct VkSemaphoreWaitInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphoreWaitFlags flags;
+ uint32_t semaphoreCount;
+ const VkSemaphore* pSemaphores;
+ const uint64_t* pValues;
+} VkSemaphoreWaitInfo;
+
+typedef struct VkSemaphoreSignalInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ uint64_t value;
+} VkSemaphoreSignalInfo;
+
+typedef struct VkPhysicalDeviceBufferDeviceAddressFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 bufferDeviceAddress;
+ VkBool32 bufferDeviceAddressCaptureReplay;
+ VkBool32 bufferDeviceAddressMultiDevice;
+} VkPhysicalDeviceBufferDeviceAddressFeatures;
+
+typedef struct VkBufferDeviceAddressInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer buffer;
+} VkBufferDeviceAddressInfo;
+
+typedef struct VkBufferOpaqueCaptureAddressCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint64_t opaqueCaptureAddress;
+} VkBufferOpaqueCaptureAddressCreateInfo;
+
+typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint64_t opaqueCaptureAddress;
+} VkMemoryOpaqueCaptureAddressAllocateInfo;
+
+typedef struct VkDeviceMemoryOpaqueCaptureAddressInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceMemory memory;
+} VkDeviceMemoryOpaqueCaptureAddressInfo;
+
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
+typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo);
+typedef void (VKAPI_PTR *PFN_vkResetQueryPool)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValue)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue);
+typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphores)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout);
+typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphore)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo);
+typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddress)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo);
+typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddress)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo);
+typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddress)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCount(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCount(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2(
+ VkDevice device,
+ const VkRenderPassCreateInfo2* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkRenderPass* pRenderPass);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2(
+ VkCommandBuffer commandBuffer,
+ const VkRenderPassBeginInfo* pRenderPassBegin,
+ const VkSubpassBeginInfo* pSubpassBeginInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2(
+ VkCommandBuffer commandBuffer,
+ const VkSubpassBeginInfo* pSubpassBeginInfo,
+ const VkSubpassEndInfo* pSubpassEndInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2(
+ VkCommandBuffer commandBuffer,
+ const VkSubpassEndInfo* pSubpassEndInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkResetQueryPool(
+ VkDevice device,
+ VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValue(
+ VkDevice device,
+ VkSemaphore semaphore,
+ uint64_t* pValue);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphores(
+ VkDevice device,
+ const VkSemaphoreWaitInfo* pWaitInfo,
+ uint64_t timeout);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphore(
+ VkDevice device,
+ const VkSemaphoreSignalInfo* pSignalInfo);
+
+VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddress(
+ VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo);
+
+VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddress(
+ VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo);
+
+VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddress(
+ VkDevice device,
+ const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo);
+#endif
+
+
+#define VK_KHR_surface 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
+#define VK_KHR_SURFACE_SPEC_VERSION 25
+#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface"
+
+typedef enum VkColorSpaceKHR {
+ VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,
+ VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001,
+ VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002,
+ VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104003,
+ VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004,
+ VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005,
+ VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006,
+ VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007,
+ VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008,
+ VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009,
+ VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010,
+ VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011,
+ VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
+ VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
+ VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014,
+ VK_COLOR_SPACE_DISPLAY_NATIVE_AMD = 1000213000,
+ VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT,
+ VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1),
+ VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkColorSpaceKHR;
+
+typedef enum VkPresentModeKHR {
+ VK_PRESENT_MODE_IMMEDIATE_KHR = 0,
+ VK_PRESENT_MODE_MAILBOX_KHR = 1,
+ VK_PRESENT_MODE_FIFO_KHR = 2,
+ VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3,
+ VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000,
+ VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001,
+ VK_PRESENT_MODE_BEGIN_RANGE_KHR = VK_PRESENT_MODE_IMMEDIATE_KHR,
+ VK_PRESENT_MODE_END_RANGE_KHR = VK_PRESENT_MODE_FIFO_RELAXED_KHR,
+ VK_PRESENT_MODE_RANGE_SIZE_KHR = (VK_PRESENT_MODE_FIFO_RELAXED_KHR - VK_PRESENT_MODE_IMMEDIATE_KHR + 1),
+ VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkPresentModeKHR;
+
+typedef enum VkSurfaceTransformFlagBitsKHR {
+ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001,
+ VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002,
+ VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004,
+ VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008,
+ VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010,
+ VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020,
+ VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040,
+ VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080,
+ VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100,
+ VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkSurfaceTransformFlagBitsKHR;
+typedef VkFlags VkSurfaceTransformFlagsKHR;
+
+typedef enum VkCompositeAlphaFlagBitsKHR {
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
+ VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002,
+ VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004,
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008,
+ VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkCompositeAlphaFlagBitsKHR;
+typedef VkFlags VkCompositeAlphaFlagsKHR;
+typedef struct VkSurfaceCapabilitiesKHR {
+ uint32_t minImageCount;
+ uint32_t maxImageCount;
+ VkExtent2D currentExtent;
+ VkExtent2D minImageExtent;
+ VkExtent2D maxImageExtent;
+ uint32_t maxImageArrayLayers;
+ VkSurfaceTransformFlagsKHR supportedTransforms;
+ VkSurfaceTransformFlagBitsKHR currentTransform;
+ VkCompositeAlphaFlagsKHR supportedCompositeAlpha;
+ VkImageUsageFlags supportedUsageFlags;
+} VkSurfaceCapabilitiesKHR;
+
+typedef struct VkSurfaceFormatKHR {
+ VkFormat format;
+ VkColorSpaceKHR colorSpace;
+} VkSurfaceFormatKHR;
+
+typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(
+ VkInstance instance,
+ VkSurfaceKHR surface,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ VkSurfaceKHR surface,
+ VkBool32* pSupported);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ VkSurfaceCapabilitiesKHR* pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pSurfaceFormatCount,
+ VkSurfaceFormatKHR* pSurfaceFormats);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pPresentModeCount,
+ VkPresentModeKHR* pPresentModes);
+#endif
+
+
+#define VK_KHR_swapchain 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR)
+#define VK_KHR_SWAPCHAIN_SPEC_VERSION 70
+#define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain"
+
+typedef enum VkSwapchainCreateFlagBitsKHR {
+ VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001,
+ VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002,
+ VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0x00000004,
+ VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkSwapchainCreateFlagBitsKHR;
+typedef VkFlags VkSwapchainCreateFlagsKHR;
+
+typedef enum VkDeviceGroupPresentModeFlagBitsKHR {
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0x00000001,
+ VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0x00000002,
+ VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0x00000004,
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008,
+ VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkDeviceGroupPresentModeFlagBitsKHR;
+typedef VkFlags VkDeviceGroupPresentModeFlagsKHR;
+typedef struct VkSwapchainCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainCreateFlagsKHR flags;
+ VkSurfaceKHR surface;
+ uint32_t minImageCount;
+ VkFormat imageFormat;
+ VkColorSpaceKHR imageColorSpace;
+ VkExtent2D imageExtent;
+ uint32_t imageArrayLayers;
+ VkImageUsageFlags imageUsage;
+ VkSharingMode imageSharingMode;
+ uint32_t queueFamilyIndexCount;
+ const uint32_t* pQueueFamilyIndices;
+ VkSurfaceTransformFlagBitsKHR preTransform;
+ VkCompositeAlphaFlagBitsKHR compositeAlpha;
+ VkPresentModeKHR presentMode;
+ VkBool32 clipped;
+ VkSwapchainKHR oldSwapchain;
+} VkSwapchainCreateInfoKHR;
+
+typedef struct VkPresentInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t waitSemaphoreCount;
+ const VkSemaphore* pWaitSemaphores;
+ uint32_t swapchainCount;
+ const VkSwapchainKHR* pSwapchains;
+ const uint32_t* pImageIndices;
+ VkResult* pResults;
+} VkPresentInfoKHR;
+
+typedef struct VkImageSwapchainCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainKHR swapchain;
+} VkImageSwapchainCreateInfoKHR;
+
+typedef struct VkBindImageMemorySwapchainInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainKHR swapchain;
+ uint32_t imageIndex;
+} VkBindImageMemorySwapchainInfoKHR;
+
+typedef struct VkAcquireNextImageInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainKHR swapchain;
+ uint64_t timeout;
+ VkSemaphore semaphore;
+ VkFence fence;
+ uint32_t deviceMask;
+} VkAcquireNextImageInfoKHR;
+
+typedef struct VkDeviceGroupPresentCapabilitiesKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE];
+ VkDeviceGroupPresentModeFlagsKHR modes;
+} VkDeviceGroupPresentCapabilitiesKHR;
+
+typedef struct VkDeviceGroupPresentInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t swapchainCount;
+ const uint32_t* pDeviceMasks;
+ VkDeviceGroupPresentModeFlagBitsKHR mode;
+} VkDeviceGroupPresentInfoKHR;
+
+typedef struct VkDeviceGroupSwapchainCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceGroupPresentModeFlagsKHR modes;
+} VkDeviceGroupSwapchainCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain);
+typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages);
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
+typedef VkResult (VKAPI_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR* pPresentInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
+ VkDevice device,
+ const VkSwapchainCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSwapchainKHR* pSwapchain);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ uint32_t* pSwapchainImageCount,
+ VkImage* pSwapchainImages);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ uint64_t timeout,
+ VkSemaphore semaphore,
+ VkFence fence,
+ uint32_t* pImageIndex);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
+ VkQueue queue,
+ const VkPresentInfoKHR* pPresentInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR(
+ VkDevice device,
+ VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR(
+ VkDevice device,
+ VkSurfaceKHR surface,
+ VkDeviceGroupPresentModeFlagsKHR* pModes);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR(
+ VkDevice device,
+ const VkAcquireNextImageInfoKHR* pAcquireInfo,
+ uint32_t* pImageIndex);
+#endif
+
+
+#define VK_KHR_display 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR)
+#define VK_KHR_DISPLAY_SPEC_VERSION 23
+#define VK_KHR_DISPLAY_EXTENSION_NAME "VK_KHR_display"
+
+typedef enum VkDisplayPlaneAlphaFlagBitsKHR {
+ VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
+ VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002,
+ VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004,
+ VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008,
+ VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkDisplayPlaneAlphaFlagBitsKHR;
+typedef VkFlags VkDisplayPlaneAlphaFlagsKHR;
+typedef VkFlags VkDisplayModeCreateFlagsKHR;
+typedef VkFlags VkDisplaySurfaceCreateFlagsKHR;
+typedef struct VkDisplayPropertiesKHR {
+ VkDisplayKHR display;
+ const char* displayName;
+ VkExtent2D physicalDimensions;
+ VkExtent2D physicalResolution;
+ VkSurfaceTransformFlagsKHR supportedTransforms;
+ VkBool32 planeReorderPossible;
+ VkBool32 persistentContent;
+} VkDisplayPropertiesKHR;
+
+typedef struct VkDisplayModeParametersKHR {
+ VkExtent2D visibleRegion;
+ uint32_t refreshRate;
+} VkDisplayModeParametersKHR;
+
+typedef struct VkDisplayModePropertiesKHR {
+ VkDisplayModeKHR displayMode;
+ VkDisplayModeParametersKHR parameters;
+} VkDisplayModePropertiesKHR;
+
+typedef struct VkDisplayModeCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkDisplayModeCreateFlagsKHR flags;
+ VkDisplayModeParametersKHR parameters;
+} VkDisplayModeCreateInfoKHR;
+
+typedef struct VkDisplayPlaneCapabilitiesKHR {
+ VkDisplayPlaneAlphaFlagsKHR supportedAlpha;
+ VkOffset2D minSrcPosition;
+ VkOffset2D maxSrcPosition;
+ VkExtent2D minSrcExtent;
+ VkExtent2D maxSrcExtent;
+ VkOffset2D minDstPosition;
+ VkOffset2D maxDstPosition;
+ VkExtent2D minDstExtent;
+ VkExtent2D maxDstExtent;
+} VkDisplayPlaneCapabilitiesKHR;
+
+typedef struct VkDisplayPlanePropertiesKHR {
+ VkDisplayKHR currentDisplay;
+ uint32_t currentStackIndex;
+} VkDisplayPlanePropertiesKHR;
+
+typedef struct VkDisplaySurfaceCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkDisplaySurfaceCreateFlagsKHR flags;
+ VkDisplayModeKHR displayMode;
+ uint32_t planeIndex;
+ uint32_t planeStackIndex;
+ VkSurfaceTransformFlagBitsKHR transform;
+ float globalAlpha;
+ VkDisplayPlaneAlphaFlagBitsKHR alphaMode;
+ VkExtent2D imageExtent;
+} VkDisplaySurfaceCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkDisplayPropertiesKHR* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkDisplayPlanePropertiesKHR* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t planeIndex,
+ uint32_t* pDisplayCount,
+ VkDisplayKHR* pDisplays);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display,
+ uint32_t* pPropertyCount,
+ VkDisplayModePropertiesKHR* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR(
+ VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display,
+ const VkDisplayModeCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDisplayModeKHR* pMode);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkDisplayModeKHR mode,
+ uint32_t planeIndex,
+ VkDisplayPlaneCapabilitiesKHR* pCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR(
+ VkInstance instance,
+ const VkDisplaySurfaceCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+
+
+#define VK_KHR_display_swapchain 1
+#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 10
+#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain"
+typedef struct VkDisplayPresentInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkRect2D srcRect;
+ VkRect2D dstRect;
+ VkBool32 persistent;
+} VkDisplayPresentInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR(
+ VkDevice device,
+ uint32_t swapchainCount,
+ const VkSwapchainCreateInfoKHR* pCreateInfos,
+ const VkAllocationCallbacks* pAllocator,
+ VkSwapchainKHR* pSwapchains);
+#endif
+
+
+#define VK_KHR_sampler_mirror_clamp_to_edge 1
+#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 3
+#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge"
+
+
+#define VK_KHR_multiview 1
+#define VK_KHR_MULTIVIEW_SPEC_VERSION 1
+#define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview"
+typedef VkRenderPassMultiviewCreateInfo VkRenderPassMultiviewCreateInfoKHR;
+
+typedef VkPhysicalDeviceMultiviewFeatures VkPhysicalDeviceMultiviewFeaturesKHR;
+
+typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesKHR;
+
+
+
+#define VK_KHR_get_physical_device_properties2 1
+#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 2
+#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2"
+typedef VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR;
+
+typedef VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR;
+
+typedef VkFormatProperties2 VkFormatProperties2KHR;
+
+typedef VkImageFormatProperties2 VkImageFormatProperties2KHR;
+
+typedef VkPhysicalDeviceImageFormatInfo2 VkPhysicalDeviceImageFormatInfo2KHR;
+
+typedef VkQueueFamilyProperties2 VkQueueFamilyProperties2KHR;
+
+typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR;
+
+typedef VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR;
+
+typedef VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR;
+
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures2* pFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2* pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties2* pFormatProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
+ VkImageFormatProperties2* pImageFormatProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2* pQueueFamilyProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
+ uint32_t* pPropertyCount,
+ VkSparseImageFormatProperties2* pProperties);
+#endif
+
+
+#define VK_KHR_device_group 1
+#define VK_KHR_DEVICE_GROUP_SPEC_VERSION 4
+#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group"
+typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR;
+
+typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR;
+
+typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR;
+
+typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR;
+
+typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR;
+
+typedef VkDeviceGroupRenderPassBeginInfo VkDeviceGroupRenderPassBeginInfoKHR;
+
+typedef VkDeviceGroupCommandBufferBeginInfo VkDeviceGroupCommandBufferBeginInfoKHR;
+
+typedef VkDeviceGroupSubmitInfo VkDeviceGroupSubmitInfoKHR;
+
+typedef VkDeviceGroupBindSparseInfo VkDeviceGroupBindSparseInfoKHR;
+
+typedef VkBindBufferMemoryDeviceGroupInfo VkBindBufferMemoryDeviceGroupInfoKHR;
+
+typedef VkBindImageMemoryDeviceGroupInfo VkBindImageMemoryDeviceGroupInfoKHR;
+
+typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHR)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHR(
+ VkDevice device,
+ uint32_t heapIndex,
+ uint32_t localDeviceIndex,
+ uint32_t remoteDeviceIndex,
+ VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHR(
+ VkCommandBuffer commandBuffer,
+ uint32_t deviceMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR(
+ VkCommandBuffer commandBuffer,
+ uint32_t baseGroupX,
+ uint32_t baseGroupY,
+ uint32_t baseGroupZ,
+ uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ);
+#endif
+
+
+#define VK_KHR_shader_draw_parameters 1
+#define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1
+#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters"
+
+
+#define VK_KHR_maintenance1 1
+#define VK_KHR_MAINTENANCE1_SPEC_VERSION 2
+#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
+typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR;
+
+typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR(
+ VkDevice device,
+ VkCommandPool commandPool,
+ VkCommandPoolTrimFlags flags);
+#endif
+
+
+#define VK_KHR_device_group_creation 1
+#define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1
+#define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation"
+#define VK_MAX_DEVICE_GROUP_SIZE_KHR VK_MAX_DEVICE_GROUP_SIZE
+typedef VkPhysicalDeviceGroupProperties VkPhysicalDeviceGroupPropertiesKHR;
+
+typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHR)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+#endif
+
+
+#define VK_KHR_external_memory_capabilities 1
+#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities"
+#define VK_LUID_SIZE_KHR VK_LUID_SIZE
+typedef VkExternalMemoryHandleTypeFlags VkExternalMemoryHandleTypeFlagsKHR;
+
+typedef VkExternalMemoryHandleTypeFlagBits VkExternalMemoryHandleTypeFlagBitsKHR;
+
+typedef VkExternalMemoryFeatureFlags VkExternalMemoryFeatureFlagsKHR;
+
+typedef VkExternalMemoryFeatureFlagBits VkExternalMemoryFeatureFlagBitsKHR;
+
+typedef VkExternalMemoryProperties VkExternalMemoryPropertiesKHR;
+
+typedef VkPhysicalDeviceExternalImageFormatInfo VkPhysicalDeviceExternalImageFormatInfoKHR;
+
+typedef VkExternalImageFormatProperties VkExternalImageFormatPropertiesKHR;
+
+typedef VkPhysicalDeviceExternalBufferInfo VkPhysicalDeviceExternalBufferInfoKHR;
+
+typedef VkExternalBufferProperties VkExternalBufferPropertiesKHR;
+
+typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR;
+
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties);
+#endif
+
+
+#define VK_KHR_external_memory 1
+#define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory"
+#define VK_QUEUE_FAMILY_EXTERNAL_KHR VK_QUEUE_FAMILY_EXTERNAL
+typedef VkExternalMemoryImageCreateInfo VkExternalMemoryImageCreateInfoKHR;
+
+typedef VkExternalMemoryBufferCreateInfo VkExternalMemoryBufferCreateInfoKHR;
+
+typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR;
+
+
+
+#define VK_KHR_external_memory_fd 1
+#define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd"
+typedef struct VkImportMemoryFdInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+ int fd;
+} VkImportMemoryFdInfoKHR;
+
+typedef struct VkMemoryFdPropertiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t memoryTypeBits;
+} VkMemoryFdPropertiesKHR;
+
+typedef struct VkMemoryGetFdInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceMemory memory;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+} VkMemoryGetFdInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR(
+ VkDevice device,
+ const VkMemoryGetFdInfoKHR* pGetFdInfo,
+ int* pFd);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBits handleType,
+ int fd,
+ VkMemoryFdPropertiesKHR* pMemoryFdProperties);
+#endif
+
+
+#define VK_KHR_external_semaphore_capabilities 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities"
+typedef VkExternalSemaphoreHandleTypeFlags VkExternalSemaphoreHandleTypeFlagsKHR;
+
+typedef VkExternalSemaphoreHandleTypeFlagBits VkExternalSemaphoreHandleTypeFlagBitsKHR;
+
+typedef VkExternalSemaphoreFeatureFlags VkExternalSemaphoreFeatureFlagsKHR;
+
+typedef VkExternalSemaphoreFeatureFlagBits VkExternalSemaphoreFeatureFlagBitsKHR;
+
+typedef VkPhysicalDeviceExternalSemaphoreInfo VkPhysicalDeviceExternalSemaphoreInfoKHR;
+
+typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR;
+
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+ VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+#endif
+
+
+#define VK_KHR_external_semaphore 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore"
+typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR;
+
+typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR;
+
+typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR;
+
+
+
+#define VK_KHR_external_semaphore_fd 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd"
+typedef struct VkImportSemaphoreFdInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkSemaphoreImportFlags flags;
+ VkExternalSemaphoreHandleTypeFlagBits handleType;
+ int fd;
+} VkImportSemaphoreFdInfoKHR;
+
+typedef struct VkSemaphoreGetFdInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkExternalSemaphoreHandleTypeFlagBits handleType;
+} VkSemaphoreGetFdInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHR)(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHR)(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHR(
+ VkDevice device,
+ const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR(
+ VkDevice device,
+ const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
+ int* pFd);
+#endif
+
+
+#define VK_KHR_push_descriptor 1
+#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2
+#define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
+typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxPushDescriptors;
+} VkPhysicalDevicePushDescriptorPropertiesKHR;
+
+typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites);
+typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR(
+ VkCommandBuffer commandBuffer,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ uint32_t set,
+ uint32_t descriptorWriteCount,
+ const VkWriteDescriptorSet* pDescriptorWrites);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR(
+ VkCommandBuffer commandBuffer,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ VkPipelineLayout layout,
+ uint32_t set,
+ const void* pData);
+#endif
+
+
+#define VK_KHR_shader_float16_int8 1
+#define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1
+#define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8"
+typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceShaderFloat16Int8FeaturesKHR;
+
+typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceFloat16Int8FeaturesKHR;
+
+
+
+#define VK_KHR_16bit_storage 1
+#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1
+#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage"
+typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeaturesKHR;
+
+
+
+#define VK_KHR_incremental_present 1
+#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
+#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
+typedef struct VkRectLayerKHR {
+ VkOffset2D offset;
+ VkExtent2D extent;
+ uint32_t layer;
+} VkRectLayerKHR;
+
+typedef struct VkPresentRegionKHR {
+ uint32_t rectangleCount;
+ const VkRectLayerKHR* pRectangles;
+} VkPresentRegionKHR;
+
+typedef struct VkPresentRegionsKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t swapchainCount;
+ const VkPresentRegionKHR* pRegions;
+} VkPresentRegionsKHR;
+
+
+
+#define VK_KHR_descriptor_update_template 1
+typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR;
+
+#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
+#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template"
+typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR;
+
+typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR;
+
+typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR;
+
+typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR(
+ VkDevice device,
+ const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR(
+ VkDevice device,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR(
+ VkDevice device,
+ VkDescriptorSet descriptorSet,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const void* pData);
+#endif
+
+
+#define VK_KHR_imageless_framebuffer 1
+#define VK_KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION 1
+#define VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME "VK_KHR_imageless_framebuffer"
+typedef VkPhysicalDeviceImagelessFramebufferFeatures VkPhysicalDeviceImagelessFramebufferFeaturesKHR;
+
+typedef VkFramebufferAttachmentsCreateInfo VkFramebufferAttachmentsCreateInfoKHR;
+
+typedef VkFramebufferAttachmentImageInfo VkFramebufferAttachmentImageInfoKHR;
+
+typedef VkRenderPassAttachmentBeginInfo VkRenderPassAttachmentBeginInfoKHR;
+
+
+
+#define VK_KHR_create_renderpass2 1
+#define VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION 1
+#define VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME "VK_KHR_create_renderpass2"
+typedef VkRenderPassCreateInfo2 VkRenderPassCreateInfo2KHR;
+
+typedef VkAttachmentDescription2 VkAttachmentDescription2KHR;
+
+typedef VkAttachmentReference2 VkAttachmentReference2KHR;
+
+typedef VkSubpassDescription2 VkSubpassDescription2KHR;
+
+typedef VkSubpassDependency2 VkSubpassDependency2KHR;
+
+typedef VkSubpassBeginInfo VkSubpassBeginInfoKHR;
+
+typedef VkSubpassEndInfo VkSubpassEndInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2KHR)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
+typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR(
+ VkDevice device,
+ const VkRenderPassCreateInfo2* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkRenderPass* pRenderPass);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkRenderPassBeginInfo* pRenderPassBegin,
+ const VkSubpassBeginInfo* pSubpassBeginInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkSubpassBeginInfo* pSubpassBeginInfo,
+ const VkSubpassEndInfo* pSubpassEndInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkSubpassEndInfo* pSubpassEndInfo);
+#endif
+
+
+#define VK_KHR_shared_presentable_image 1
+#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
+#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
+typedef struct VkSharedPresentSurfaceCapabilitiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkImageUsageFlags sharedPresentSupportedUsageFlags;
+} VkSharedPresentSurfaceCapabilitiesKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR(
+ VkDevice device,
+ VkSwapchainKHR swapchain);
+#endif
+
+
+#define VK_KHR_external_fence_capabilities 1
+#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities"
+typedef VkExternalFenceHandleTypeFlags VkExternalFenceHandleTypeFlagsKHR;
+
+typedef VkExternalFenceHandleTypeFlagBits VkExternalFenceHandleTypeFlagBitsKHR;
+
+typedef VkExternalFenceFeatureFlags VkExternalFenceFeatureFlagsKHR;
+
+typedef VkExternalFenceFeatureFlagBits VkExternalFenceFeatureFlagBitsKHR;
+
+typedef VkPhysicalDeviceExternalFenceInfo VkPhysicalDeviceExternalFenceInfoKHR;
+
+typedef VkExternalFenceProperties VkExternalFencePropertiesKHR;
+
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
+ VkExternalFenceProperties* pExternalFenceProperties);
+#endif
+
+
+#define VK_KHR_external_fence 1
+#define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence"
+typedef VkFenceImportFlags VkFenceImportFlagsKHR;
+
+typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR;
+
+typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR;
+
+
+
+#define VK_KHR_external_fence_fd 1
+#define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd"
+typedef struct VkImportFenceFdInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkFence fence;
+ VkFenceImportFlags flags;
+ VkExternalFenceHandleTypeFlagBits handleType;
+ int fd;
+} VkImportFenceFdInfoKHR;
+
+typedef struct VkFenceGetFdInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkFence fence;
+ VkExternalFenceHandleTypeFlagBits handleType;
+} VkFenceGetFdInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkImportFenceFdKHR)(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetFenceFdKHR)(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceFdKHR(
+ VkDevice device,
+ const VkImportFenceFdInfoKHR* pImportFenceFdInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR(
+ VkDevice device,
+ const VkFenceGetFdInfoKHR* pGetFdInfo,
+ int* pFd);
+#endif
+
+
+#define VK_KHR_performance_query 1
+#define VK_KHR_PERFORMANCE_QUERY_SPEC_VERSION 1
+#define VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME "VK_KHR_performance_query"
+
+typedef enum VkPerformanceCounterUnitKHR {
+ VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR = 0,
+ VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR = 1,
+ VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR = 2,
+ VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR = 3,
+ VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR = 4,
+ VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR = 5,
+ VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR = 6,
+ VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR = 7,
+ VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR = 8,
+ VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR = 9,
+ VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR = 10,
+ VK_PERFORMANCE_COUNTER_UNIT_BEGIN_RANGE_KHR = VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR,
+ VK_PERFORMANCE_COUNTER_UNIT_END_RANGE_KHR = VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR,
+ VK_PERFORMANCE_COUNTER_UNIT_RANGE_SIZE_KHR = (VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR - VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR + 1),
+ VK_PERFORMANCE_COUNTER_UNIT_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkPerformanceCounterUnitKHR;
+
+typedef enum VkPerformanceCounterScopeKHR {
+ VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR = 0,
+ VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR = 1,
+ VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR = 2,
+ VK_QUERY_SCOPE_COMMAND_BUFFER_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR,
+ VK_QUERY_SCOPE_RENDER_PASS_KHR = VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR,
+ VK_QUERY_SCOPE_COMMAND_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR,
+ VK_PERFORMANCE_COUNTER_SCOPE_BEGIN_RANGE_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR,
+ VK_PERFORMANCE_COUNTER_SCOPE_END_RANGE_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR,
+ VK_PERFORMANCE_COUNTER_SCOPE_RANGE_SIZE_KHR = (VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR - VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR + 1),
+ VK_PERFORMANCE_COUNTER_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkPerformanceCounterScopeKHR;
+
+typedef enum VkPerformanceCounterStorageKHR {
+ VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR = 0,
+ VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR = 1,
+ VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR = 2,
+ VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR = 3,
+ VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR = 4,
+ VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR = 5,
+ VK_PERFORMANCE_COUNTER_STORAGE_BEGIN_RANGE_KHR = VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR,
+ VK_PERFORMANCE_COUNTER_STORAGE_END_RANGE_KHR = VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR,
+ VK_PERFORMANCE_COUNTER_STORAGE_RANGE_SIZE_KHR = (VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR - VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR + 1),
+ VK_PERFORMANCE_COUNTER_STORAGE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkPerformanceCounterStorageKHR;
+
+typedef enum VkPerformanceCounterDescriptionFlagBitsKHR {
+ VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = 0x00000001,
+ VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = 0x00000002,
+ VK_PERFORMANCE_COUNTER_DESCRIPTION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkPerformanceCounterDescriptionFlagBitsKHR;
+typedef VkFlags VkPerformanceCounterDescriptionFlagsKHR;
+
+typedef enum VkAcquireProfilingLockFlagBitsKHR {
+ VK_ACQUIRE_PROFILING_LOCK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkAcquireProfilingLockFlagBitsKHR;
+typedef VkFlags VkAcquireProfilingLockFlagsKHR;
+typedef struct VkPhysicalDevicePerformanceQueryFeaturesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 performanceCounterQueryPools;
+ VkBool32 performanceCounterMultipleQueryPools;
+} VkPhysicalDevicePerformanceQueryFeaturesKHR;
+
+typedef struct VkPhysicalDevicePerformanceQueryPropertiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 allowCommandBufferQueryCopies;
+} VkPhysicalDevicePerformanceQueryPropertiesKHR;
+
+typedef struct VkPerformanceCounterKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkPerformanceCounterUnitKHR unit;
+ VkPerformanceCounterScopeKHR scope;
+ VkPerformanceCounterStorageKHR storage;
+ uint8_t uuid[VK_UUID_SIZE];
+} VkPerformanceCounterKHR;
+
+typedef struct VkPerformanceCounterDescriptionKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkPerformanceCounterDescriptionFlagsKHR flags;
+ char name[VK_MAX_DESCRIPTION_SIZE];
+ char category[VK_MAX_DESCRIPTION_SIZE];
+ char description[VK_MAX_DESCRIPTION_SIZE];
+} VkPerformanceCounterDescriptionKHR;
+
+typedef struct VkQueryPoolPerformanceCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t queueFamilyIndex;
+ uint32_t counterIndexCount;
+ const uint32_t* pCounterIndices;
+} VkQueryPoolPerformanceCreateInfoKHR;
+
+typedef union VkPerformanceCounterResultKHR {
+ int32_t int32;
+ int64_t int64;
+ uint32_t uint32;
+ uint64_t uint64;
+ float float32;
+ double float64;
+} VkPerformanceCounterResultKHR;
+
+typedef struct VkAcquireProfilingLockInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkAcquireProfilingLockFlagsKHR flags;
+ uint64_t timeout;
+} VkAcquireProfilingLockInfoKHR;
+
+typedef struct VkPerformanceQuerySubmitInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t counterPassIndex;
+} VkPerformanceQuerySubmitInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterKHR* pCounters, VkPerformanceCounterDescriptionKHR* pCounterDescriptions);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR)(VkPhysicalDevice physicalDevice, const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses);
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireProfilingLockKHR)(VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo);
+typedef void (VKAPI_PTR *PFN_vkReleaseProfilingLockKHR)(VkDevice device);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ uint32_t* pCounterCount,
+ VkPerformanceCounterKHR* pCounters,
+ VkPerformanceCounterDescriptionKHR* pCounterDescriptions);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(
+ VkPhysicalDevice physicalDevice,
+ const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo,
+ uint32_t* pNumPasses);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireProfilingLockKHR(
+ VkDevice device,
+ const VkAcquireProfilingLockInfoKHR* pInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkReleaseProfilingLockKHR(
+ VkDevice device);
+#endif
+
+
+#define VK_KHR_maintenance2 1
+#define VK_KHR_MAINTENANCE2_SPEC_VERSION 1
+#define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2"
+typedef VkPointClippingBehavior VkPointClippingBehaviorKHR;
+
+typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR;
+
+typedef VkPhysicalDevicePointClippingProperties VkPhysicalDevicePointClippingPropertiesKHR;
+
+typedef VkRenderPassInputAttachmentAspectCreateInfo VkRenderPassInputAttachmentAspectCreateInfoKHR;
+
+typedef VkInputAttachmentAspectReference VkInputAttachmentAspectReferenceKHR;
+
+typedef VkImageViewUsageCreateInfo VkImageViewUsageCreateInfoKHR;
+
+typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellationDomainOriginStateCreateInfoKHR;
+
+
+
+#define VK_KHR_get_surface_capabilities2 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
+typedef struct VkPhysicalDeviceSurfaceInfo2KHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSurfaceKHR surface;
+} VkPhysicalDeviceSurfaceInfo2KHR;
+
+typedef struct VkSurfaceCapabilities2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkSurfaceCapabilitiesKHR surfaceCapabilities;
+} VkSurfaceCapabilities2KHR;
+
+typedef struct VkSurfaceFormat2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkSurfaceFormatKHR surfaceFormat;
+} VkSurfaceFormat2KHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pSurfaceFormatCount,
+ VkSurfaceFormat2KHR* pSurfaceFormats);
+#endif
+
+
+#define VK_KHR_variable_pointers 1
+#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1
+#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers"
+typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeaturesKHR;
+
+typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointersFeaturesKHR;
+
+
+
+#define VK_KHR_get_display_properties2 1
+#define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1
+#define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2"
+typedef struct VkDisplayProperties2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkDisplayPropertiesKHR displayProperties;
+} VkDisplayProperties2KHR;
+
+typedef struct VkDisplayPlaneProperties2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkDisplayPlanePropertiesKHR displayPlaneProperties;
+} VkDisplayPlaneProperties2KHR;
+
+typedef struct VkDisplayModeProperties2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkDisplayModePropertiesKHR displayModeProperties;
+} VkDisplayModeProperties2KHR;
+
+typedef struct VkDisplayPlaneInfo2KHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkDisplayModeKHR mode;
+ uint32_t planeIndex;
+} VkDisplayPlaneInfo2KHR;
+
+typedef struct VkDisplayPlaneCapabilities2KHR {
+ VkStructureType sType;
+ void* pNext;
+ VkDisplayPlaneCapabilitiesKHR capabilities;
+} VkDisplayPlaneCapabilities2KHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayProperties2KHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlaneProperties2KHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModeProperties2KHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModeProperties2KHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkDisplayProperties2KHR* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkDisplayPlaneProperties2KHR* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display,
+ uint32_t* pPropertyCount,
+ VkDisplayModeProperties2KHR* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo,
+ VkDisplayPlaneCapabilities2KHR* pCapabilities);
+#endif
+
+
+#define VK_KHR_dedicated_allocation 1
+#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3
+#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation"
+typedef VkMemoryDedicatedRequirements VkMemoryDedicatedRequirementsKHR;
+
+typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR;
+
+
+
+#define VK_KHR_storage_buffer_storage_class 1
+#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION 1
+#define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class"
+
+
+#define VK_KHR_relaxed_block_layout 1
+#define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1
+#define VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME "VK_KHR_relaxed_block_layout"
+
+
+#define VK_KHR_get_memory_requirements2 1
+#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1
+#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2"
+typedef VkBufferMemoryRequirementsInfo2 VkBufferMemoryRequirementsInfo2KHR;
+
+typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR;
+
+typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR;
+
+typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR;
+
+typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR(
+ VkDevice device,
+ const VkImageMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR(
+ VkDevice device,
+ const VkBufferMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR(
+ VkDevice device,
+ const VkImageSparseMemoryRequirementsInfo2* pInfo,
+ uint32_t* pSparseMemoryRequirementCount,
+ VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+#endif
+
+
+#define VK_KHR_image_format_list 1
+#define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1
+#define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list"
+typedef VkImageFormatListCreateInfo VkImageFormatListCreateInfoKHR;
+
+
+
+#define VK_KHR_sampler_ycbcr_conversion 1
+typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR;
+
+#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 14
+#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion"
+typedef VkSamplerYcbcrModelConversion VkSamplerYcbcrModelConversionKHR;
+
+typedef VkSamplerYcbcrRange VkSamplerYcbcrRangeKHR;
+
+typedef VkChromaLocation VkChromaLocationKHR;
+
+typedef VkSamplerYcbcrConversionCreateInfo VkSamplerYcbcrConversionCreateInfoKHR;
+
+typedef VkSamplerYcbcrConversionInfo VkSamplerYcbcrConversionInfoKHR;
+
+typedef VkBindImagePlaneMemoryInfo VkBindImagePlaneMemoryInfoKHR;
+
+typedef VkImagePlaneMemoryRequirementsInfo VkImagePlaneMemoryRequirementsInfoKHR;
+
+typedef VkPhysicalDeviceSamplerYcbcrConversionFeatures VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR;
+
+typedef VkSamplerYcbcrConversionImageFormatProperties VkSamplerYcbcrConversionImageFormatPropertiesKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversionKHR(
+ VkDevice device,
+ const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSamplerYcbcrConversion* pYcbcrConversion);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR(
+ VkDevice device,
+ VkSamplerYcbcrConversion ycbcrConversion,
+ const VkAllocationCallbacks* pAllocator);
+#endif
+
+
+#define VK_KHR_bind_memory2 1
+#define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1
+#define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2"
+typedef VkBindBufferMemoryInfo VkBindBufferMemoryInfoKHR;
+
+typedef VkBindImageMemoryInfo VkBindImageMemoryInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindBufferMemoryInfo* pBindInfos);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindImageMemoryInfo* pBindInfos);
+#endif
+
+
+#define VK_KHR_maintenance3 1
+#define VK_KHR_MAINTENANCE3_SPEC_VERSION 1
+#define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3"
+typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR;
+
+typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR;
+
+typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupportKHR)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR(
+ VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ VkDescriptorSetLayoutSupport* pSupport);
+#endif
+
+
+#define VK_KHR_draw_indirect_count 1
+#define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
+#define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count"
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride);
+#endif
+
+
+#define VK_KHR_shader_subgroup_extended_types 1
+#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_SPEC_VERSION 1
+#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME "VK_KHR_shader_subgroup_extended_types"
+typedef VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR;
+
+
+
+#define VK_KHR_8bit_storage 1
+#define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1
+#define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage"
+typedef VkPhysicalDevice8BitStorageFeatures VkPhysicalDevice8BitStorageFeaturesKHR;
+
+
+
+#define VK_KHR_shader_atomic_int64 1
+#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1
+#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64"
+typedef VkPhysicalDeviceShaderAtomicInt64Features VkPhysicalDeviceShaderAtomicInt64FeaturesKHR;
+
+
+
+#define VK_KHR_shader_clock 1
+#define VK_KHR_SHADER_CLOCK_SPEC_VERSION 1
+#define VK_KHR_SHADER_CLOCK_EXTENSION_NAME "VK_KHR_shader_clock"
+typedef struct VkPhysicalDeviceShaderClockFeaturesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderSubgroupClock;
+ VkBool32 shaderDeviceClock;
+} VkPhysicalDeviceShaderClockFeaturesKHR;
+
+
+
+#define VK_KHR_driver_properties 1
+#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
+#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
+#define VK_MAX_DRIVER_NAME_SIZE_KHR VK_MAX_DRIVER_NAME_SIZE
+#define VK_MAX_DRIVER_INFO_SIZE_KHR VK_MAX_DRIVER_INFO_SIZE
+typedef VkDriverId VkDriverIdKHR;
+
+typedef VkConformanceVersion VkConformanceVersionKHR;
+
+typedef VkPhysicalDeviceDriverProperties VkPhysicalDeviceDriverPropertiesKHR;
+
+
+
+#define VK_KHR_shader_float_controls 1
+#define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 4
+#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls"
+typedef VkShaderFloatControlsIndependence VkShaderFloatControlsIndependenceKHR;
+
+typedef VkPhysicalDeviceFloatControlsProperties VkPhysicalDeviceFloatControlsPropertiesKHR;
+
+
+
+#define VK_KHR_depth_stencil_resolve 1
+#define VK_KHR_DEPTH_STENCIL_RESOLVE_SPEC_VERSION 1
+#define VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME "VK_KHR_depth_stencil_resolve"
+typedef VkResolveModeFlagBits VkResolveModeFlagBitsKHR;
+
+typedef VkResolveModeFlags VkResolveModeFlagsKHR;
+
+typedef VkSubpassDescriptionDepthStencilResolve VkSubpassDescriptionDepthStencilResolveKHR;
+
+typedef VkPhysicalDeviceDepthStencilResolveProperties VkPhysicalDeviceDepthStencilResolvePropertiesKHR;
+
+
+
+#define VK_KHR_swapchain_mutable_format 1
+#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1
+#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format"
+
+
+#define VK_KHR_timeline_semaphore 1
+#define VK_KHR_TIMELINE_SEMAPHORE_SPEC_VERSION 2
+#define VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME "VK_KHR_timeline_semaphore"
+typedef VkSemaphoreType VkSemaphoreTypeKHR;
+
+typedef VkSemaphoreWaitFlagBits VkSemaphoreWaitFlagBitsKHR;
+
+typedef VkSemaphoreWaitFlags VkSemaphoreWaitFlagsKHR;
+
+typedef VkPhysicalDeviceTimelineSemaphoreFeatures VkPhysicalDeviceTimelineSemaphoreFeaturesKHR;
+
+typedef VkPhysicalDeviceTimelineSemaphoreProperties VkPhysicalDeviceTimelineSemaphorePropertiesKHR;
+
+typedef VkSemaphoreTypeCreateInfo VkSemaphoreTypeCreateInfoKHR;
+
+typedef VkTimelineSemaphoreSubmitInfo VkTimelineSemaphoreSubmitInfoKHR;
+
+typedef VkSemaphoreWaitInfo VkSemaphoreWaitInfoKHR;
+
+typedef VkSemaphoreSignalInfo VkSemaphoreSignalInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValueKHR)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue);
+typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphoresKHR)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout);
+typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphoreKHR)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValueKHR(
+ VkDevice device,
+ VkSemaphore semaphore,
+ uint64_t* pValue);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphoresKHR(
+ VkDevice device,
+ const VkSemaphoreWaitInfo* pWaitInfo,
+ uint64_t timeout);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphoreKHR(
+ VkDevice device,
+ const VkSemaphoreSignalInfo* pSignalInfo);
+#endif
+
+
+#define VK_KHR_vulkan_memory_model 1
+#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 3
+#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
+typedef VkPhysicalDeviceVulkanMemoryModelFeatures VkPhysicalDeviceVulkanMemoryModelFeaturesKHR;
+
+
+
+#define VK_KHR_spirv_1_4 1
+#define VK_KHR_SPIRV_1_4_SPEC_VERSION 1
+#define VK_KHR_SPIRV_1_4_EXTENSION_NAME "VK_KHR_spirv_1_4"
+
+
+#define VK_KHR_surface_protected_capabilities 1
+#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION 1
+#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME "VK_KHR_surface_protected_capabilities"
+typedef struct VkSurfaceProtectedCapabilitiesKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 supportsProtected;
+} VkSurfaceProtectedCapabilitiesKHR;
+
+
+
+#define VK_KHR_separate_depth_stencil_layouts 1
+#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_SPEC_VERSION 1
+#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME "VK_KHR_separate_depth_stencil_layouts"
+typedef VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR;
+
+typedef VkAttachmentReferenceStencilLayout VkAttachmentReferenceStencilLayoutKHR;
+
+typedef VkAttachmentDescriptionStencilLayout VkAttachmentDescriptionStencilLayoutKHR;
+
+
+
+#define VK_KHR_uniform_buffer_standard_layout 1
+#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1
+#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME "VK_KHR_uniform_buffer_standard_layout"
+typedef VkPhysicalDeviceUniformBufferStandardLayoutFeatures VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR;
+
+
+
+#define VK_KHR_buffer_device_address 1
+#define VK_KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 1
+#define VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_KHR_buffer_device_address"
+typedef VkPhysicalDeviceBufferDeviceAddressFeatures VkPhysicalDeviceBufferDeviceAddressFeaturesKHR;
+
+typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoKHR;
+
+typedef VkBufferOpaqueCaptureAddressCreateInfo VkBufferOpaqueCaptureAddressCreateInfoKHR;
+
+typedef VkMemoryOpaqueCaptureAddressAllocateInfo VkMemoryOpaqueCaptureAddressAllocateInfoKHR;
+
+typedef VkDeviceMemoryOpaqueCaptureAddressInfo VkDeviceMemoryOpaqueCaptureAddressInfoKHR;
+
+typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo);
+typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo);
+typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressKHR(
+ VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo);
+
+VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddressKHR(
+ VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo);
+
+VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddressKHR(
+ VkDevice device,
+ const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo);
+#endif
+
+
+#define VK_KHR_pipeline_executable_properties 1
+#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION 1
+#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME "VK_KHR_pipeline_executable_properties"
+
+typedef enum VkPipelineExecutableStatisticFormatKHR {
+ VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR = 0,
+ VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR = 1,
+ VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR = 2,
+ VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR = 3,
+ VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BEGIN_RANGE_KHR = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR,
+ VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_END_RANGE_KHR = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR,
+ VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_RANGE_SIZE_KHR = (VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR - VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR + 1),
+ VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkPipelineExecutableStatisticFormatKHR;
+typedef struct VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 pipelineExecutableInfo;
+} VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR;
+
+typedef struct VkPipelineInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipeline pipeline;
+} VkPipelineInfoKHR;
+
+typedef struct VkPipelineExecutablePropertiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkShaderStageFlags stages;
+ char name[VK_MAX_DESCRIPTION_SIZE];
+ char description[VK_MAX_DESCRIPTION_SIZE];
+ uint32_t subgroupSize;
+} VkPipelineExecutablePropertiesKHR;
+
+typedef struct VkPipelineExecutableInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipeline pipeline;
+ uint32_t executableIndex;
+} VkPipelineExecutableInfoKHR;
+
+typedef union VkPipelineExecutableStatisticValueKHR {
+ VkBool32 b32;
+ int64_t i64;
+ uint64_t u64;
+ double f64;
+} VkPipelineExecutableStatisticValueKHR;
+
+typedef struct VkPipelineExecutableStatisticKHR {
+ VkStructureType sType;
+ void* pNext;
+ char name[VK_MAX_DESCRIPTION_SIZE];
+ char description[VK_MAX_DESCRIPTION_SIZE];
+ VkPipelineExecutableStatisticFormatKHR format;
+ VkPipelineExecutableStatisticValueKHR value;
+} VkPipelineExecutableStatisticKHR;
+
+typedef struct VkPipelineExecutableInternalRepresentationKHR {
+ VkStructureType sType;
+ void* pNext;
+ char name[VK_MAX_DESCRIPTION_SIZE];
+ char description[VK_MAX_DESCRIPTION_SIZE];
+ VkBool32 isText;
+ size_t dataSize;
+ void* pData;
+} VkPipelineExecutableInternalRepresentationKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutablePropertiesKHR)(VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VkPipelineExecutablePropertiesKHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableStatisticsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VkPipelineExecutableStatisticKHR* pStatistics);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableInternalRepresentationsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutablePropertiesKHR(
+ VkDevice device,
+ const VkPipelineInfoKHR* pPipelineInfo,
+ uint32_t* pExecutableCount,
+ VkPipelineExecutablePropertiesKHR* pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableStatisticsKHR(
+ VkDevice device,
+ const VkPipelineExecutableInfoKHR* pExecutableInfo,
+ uint32_t* pStatisticCount,
+ VkPipelineExecutableStatisticKHR* pStatistics);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR(
+ VkDevice device,
+ const VkPipelineExecutableInfoKHR* pExecutableInfo,
+ uint32_t* pInternalRepresentationCount,
+ VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations);
+#endif
+
+
+#define VK_EXT_debug_report 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9
+#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
+
+typedef enum VkDebugReportObjectTypeEXT {
+ VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0,
+ VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1,
+ VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT = 2,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT = 3,
+ VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT = 4,
+ VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT = 5,
+ VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT = 6,
+ VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT = 7,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT = 8,
+ VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT = 9,
+ VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT = 10,
+ VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT = 11,
+ VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT = 12,
+ VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT = 13,
+ VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT = 14,
+ VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT = 15,
+ VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT = 16,
+ VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT = 17,
+ VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT = 18,
+ VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT = 19,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT = 20,
+ VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT = 21,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT = 22,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT = 23,
+ VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT = 24,
+ VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT = 25,
+ VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26,
+ VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30,
+ VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
+ VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
+ VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33,
+ VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000,
+ VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT,
+ VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT,
+ VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT,
+ VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
+ VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
+ VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
+ VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDebugReportObjectTypeEXT;
+
+typedef enum VkDebugReportFlagBitsEXT {
+ VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001,
+ VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002,
+ VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004,
+ VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008,
+ VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010,
+ VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDebugReportFlagBitsEXT;
+typedef VkFlags VkDebugReportFlagsEXT;
+typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)(
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objectType,
+ uint64_t object,
+ size_t location,
+ int32_t messageCode,
+ const char* pLayerPrefix,
+ const char* pMessage,
+ void* pUserData);
+
+typedef struct VkDebugReportCallbackCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDebugReportFlagsEXT flags;
+ PFN_vkDebugReportCallbackEXT pfnCallback;
+ void* pUserData;
+} VkDebugReportCallbackCreateInfoEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
+typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
+ VkInstance instance,
+ const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDebugReportCallbackEXT* pCallback);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(
+ VkInstance instance,
+ VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
+ VkInstance instance,
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objectType,
+ uint64_t object,
+ size_t location,
+ int32_t messageCode,
+ const char* pLayerPrefix,
+ const char* pMessage);
+#endif
+
+
+#define VK_NV_glsl_shader 1
+#define VK_NV_GLSL_SHADER_SPEC_VERSION 1
+#define VK_NV_GLSL_SHADER_EXTENSION_NAME "VK_NV_glsl_shader"
+
+
+#define VK_EXT_depth_range_unrestricted 1
+#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION 1
+#define VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME "VK_EXT_depth_range_unrestricted"
+
+
+#define VK_IMG_filter_cubic 1
+#define VK_IMG_FILTER_CUBIC_SPEC_VERSION 1
+#define VK_IMG_FILTER_CUBIC_EXTENSION_NAME "VK_IMG_filter_cubic"
+
+
+#define VK_AMD_rasterization_order 1
+#define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION 1
+#define VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME "VK_AMD_rasterization_order"
+
+typedef enum VkRasterizationOrderAMD {
+ VK_RASTERIZATION_ORDER_STRICT_AMD = 0,
+ VK_RASTERIZATION_ORDER_RELAXED_AMD = 1,
+ VK_RASTERIZATION_ORDER_BEGIN_RANGE_AMD = VK_RASTERIZATION_ORDER_STRICT_AMD,
+ VK_RASTERIZATION_ORDER_END_RANGE_AMD = VK_RASTERIZATION_ORDER_RELAXED_AMD,
+ VK_RASTERIZATION_ORDER_RANGE_SIZE_AMD = (VK_RASTERIZATION_ORDER_RELAXED_AMD - VK_RASTERIZATION_ORDER_STRICT_AMD + 1),
+ VK_RASTERIZATION_ORDER_MAX_ENUM_AMD = 0x7FFFFFFF
+} VkRasterizationOrderAMD;
+typedef struct VkPipelineRasterizationStateRasterizationOrderAMD {
+ VkStructureType sType;
+ const void* pNext;
+ VkRasterizationOrderAMD rasterizationOrder;
+} VkPipelineRasterizationStateRasterizationOrderAMD;
+
+
+
+#define VK_AMD_shader_trinary_minmax 1
+#define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1
+#define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax"
+
+
+#define VK_AMD_shader_explicit_vertex_parameter 1
+#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1
+#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter"
+
+
+#define VK_EXT_debug_marker 1
+#define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4
+#define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker"
+typedef struct VkDebugMarkerObjectNameInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDebugReportObjectTypeEXT objectType;
+ uint64_t object;
+ const char* pObjectName;
+} VkDebugMarkerObjectNameInfoEXT;
+
+typedef struct VkDebugMarkerObjectTagInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDebugReportObjectTypeEXT objectType;
+ uint64_t object;
+ uint64_t tagName;
+ size_t tagSize;
+ const void* pTag;
+} VkDebugMarkerObjectTagInfoEXT;
+
+typedef struct VkDebugMarkerMarkerInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ const char* pMarkerName;
+ float color[4];
+} VkDebugMarkerMarkerInfoEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectTagEXT)(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectNameEXT)(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerBeginEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerEndEXT)(VkCommandBuffer commandBuffer);
+typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerInsertEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectTagEXT(
+ VkDevice device,
+ const VkDebugMarkerObjectTagInfoEXT* pTagInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectNameEXT(
+ VkDevice device,
+ const VkDebugMarkerObjectNameInfoEXT* pNameInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerBeginEXT(
+ VkCommandBuffer commandBuffer,
+ const VkDebugMarkerMarkerInfoEXT* pMarkerInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerEndEXT(
+ VkCommandBuffer commandBuffer);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT(
+ VkCommandBuffer commandBuffer,
+ const VkDebugMarkerMarkerInfoEXT* pMarkerInfo);
+#endif
+
+
+#define VK_AMD_gcn_shader 1
+#define VK_AMD_GCN_SHADER_SPEC_VERSION 1
+#define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader"
+
+
+#define VK_NV_dedicated_allocation 1
+#define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1
+#define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation"
+typedef struct VkDedicatedAllocationImageCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 dedicatedAllocation;
+} VkDedicatedAllocationImageCreateInfoNV;
+
+typedef struct VkDedicatedAllocationBufferCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 dedicatedAllocation;
+} VkDedicatedAllocationBufferCreateInfoNV;
+
+typedef struct VkDedicatedAllocationMemoryAllocateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+ VkBuffer buffer;
+} VkDedicatedAllocationMemoryAllocateInfoNV;
+
+
+
+#define VK_EXT_transform_feedback 1
+#define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1
+#define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback"
+typedef VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT;
+typedef struct VkPhysicalDeviceTransformFeedbackFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 transformFeedback;
+ VkBool32 geometryStreams;
+} VkPhysicalDeviceTransformFeedbackFeaturesEXT;
+
+typedef struct VkPhysicalDeviceTransformFeedbackPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxTransformFeedbackStreams;
+ uint32_t maxTransformFeedbackBuffers;
+ VkDeviceSize maxTransformFeedbackBufferSize;
+ uint32_t maxTransformFeedbackStreamDataSize;
+ uint32_t maxTransformFeedbackBufferDataSize;
+ uint32_t maxTransformFeedbackBufferDataStride;
+ VkBool32 transformFeedbackQueries;
+ VkBool32 transformFeedbackStreamsLinesTriangles;
+ VkBool32 transformFeedbackRasterizationStreamSelect;
+ VkBool32 transformFeedbackDraw;
+} VkPhysicalDeviceTransformFeedbackPropertiesEXT;
+
+typedef struct VkPipelineRasterizationStateStreamCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineRasterizationStateStreamCreateFlagsEXT flags;
+ uint32_t rasterizationStream;
+} VkPipelineRasterizationStateStreamCreateInfoEXT;
+
+typedef void (VKAPI_PTR *PFN_vkCmdBindTransformFeedbackBuffersEXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes);
+typedef void (VKAPI_PTR *PFN_vkCmdBeginTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets);
+typedef void (VKAPI_PTR *PFN_vkCmdEndTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets);
+typedef void (VKAPI_PTR *PFN_vkCmdBeginQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index);
+typedef void (VKAPI_PTR *PFN_vkCmdEndQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCountEXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffersEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstBinding,
+ uint32_t bindingCount,
+ const VkBuffer* pBuffers,
+ const VkDeviceSize* pOffsets,
+ const VkDeviceSize* pSizes);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedbackEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstCounterBuffer,
+ uint32_t counterBufferCount,
+ const VkBuffer* pCounterBuffers,
+ const VkDeviceSize* pCounterBufferOffsets);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedbackEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstCounterBuffer,
+ uint32_t counterBufferCount,
+ const VkBuffer* pCounterBuffers,
+ const VkDeviceSize* pCounterBufferOffsets);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginQueryIndexedEXT(
+ VkCommandBuffer commandBuffer,
+ VkQueryPool queryPool,
+ uint32_t query,
+ VkQueryControlFlags flags,
+ uint32_t index);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndQueryIndexedEXT(
+ VkCommandBuffer commandBuffer,
+ VkQueryPool queryPool,
+ uint32_t query,
+ uint32_t index);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t instanceCount,
+ uint32_t firstInstance,
+ VkBuffer counterBuffer,
+ VkDeviceSize counterBufferOffset,
+ uint32_t counterOffset,
+ uint32_t vertexStride);
+#endif
+
+
+#define VK_NVX_image_view_handle 1
+#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 1
+#define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle"
+typedef struct VkImageViewHandleInfoNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageView imageView;
+ VkDescriptorType descriptorType;
+ VkSampler sampler;
+} VkImageViewHandleInfoNVX;
+
+typedef uint32_t (VKAPI_PTR *PFN_vkGetImageViewHandleNVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR uint32_t VKAPI_CALL vkGetImageViewHandleNVX(
+ VkDevice device,
+ const VkImageViewHandleInfoNVX* pInfo);
+#endif
+
+
+#define VK_AMD_draw_indirect_count 1
+#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 2
+#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count"
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride);
+#endif
+
+
+#define VK_AMD_negative_viewport_height 1
+#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1
+#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height"
+
+
+#define VK_AMD_gpu_shader_half_float 1
+#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 2
+#define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float"
+
+
+#define VK_AMD_shader_ballot 1
+#define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1
+#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot"
+
+
+#define VK_AMD_texture_gather_bias_lod 1
+#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1
+#define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod"
+typedef struct VkTextureLODGatherFormatPropertiesAMD {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 supportsTextureGatherLODBiasAMD;
+} VkTextureLODGatherFormatPropertiesAMD;
+
+
+
+#define VK_AMD_shader_info 1
+#define VK_AMD_SHADER_INFO_SPEC_VERSION 1
+#define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info"
+
+typedef enum VkShaderInfoTypeAMD {
+ VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0,
+ VK_SHADER_INFO_TYPE_BINARY_AMD = 1,
+ VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2,
+ VK_SHADER_INFO_TYPE_BEGIN_RANGE_AMD = VK_SHADER_INFO_TYPE_STATISTICS_AMD,
+ VK_SHADER_INFO_TYPE_END_RANGE_AMD = VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD,
+ VK_SHADER_INFO_TYPE_RANGE_SIZE_AMD = (VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD - VK_SHADER_INFO_TYPE_STATISTICS_AMD + 1),
+ VK_SHADER_INFO_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF
+} VkShaderInfoTypeAMD;
+typedef struct VkShaderResourceUsageAMD {
+ uint32_t numUsedVgprs;
+ uint32_t numUsedSgprs;
+ uint32_t ldsSizePerLocalWorkGroup;
+ size_t ldsUsageSizeInBytes;
+ size_t scratchMemUsageInBytes;
+} VkShaderResourceUsageAMD;
+
+typedef struct VkShaderStatisticsInfoAMD {
+ VkShaderStageFlags shaderStageMask;
+ VkShaderResourceUsageAMD resourceUsage;
+ uint32_t numPhysicalVgprs;
+ uint32_t numPhysicalSgprs;
+ uint32_t numAvailableVgprs;
+ uint32_t numAvailableSgprs;
+ uint32_t computeWorkGroupSize[3];
+} VkShaderStatisticsInfoAMD;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInfoAMD)(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD(
+ VkDevice device,
+ VkPipeline pipeline,
+ VkShaderStageFlagBits shaderStage,
+ VkShaderInfoTypeAMD infoType,
+ size_t* pInfoSize,
+ void* pInfo);
+#endif
+
+
+#define VK_AMD_shader_image_load_store_lod 1
+#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1
+#define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod"
+
+
+#define VK_NV_corner_sampled_image 1
+#define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2
+#define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image"
+typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 cornerSampledImage;
+} VkPhysicalDeviceCornerSampledImageFeaturesNV;
+
+
+
+#define VK_IMG_format_pvrtc 1
+#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1
+#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
+
+
+#define VK_NV_external_memory_capabilities 1
+#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
+#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities"
+
+typedef enum VkExternalMemoryHandleTypeFlagBitsNV {
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkExternalMemoryHandleTypeFlagBitsNV;
+typedef VkFlags VkExternalMemoryHandleTypeFlagsNV;
+
+typedef enum VkExternalMemoryFeatureFlagBitsNV {
+ VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001,
+ VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002,
+ VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004,
+ VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkExternalMemoryFeatureFlagBitsNV;
+typedef VkFlags VkExternalMemoryFeatureFlagsNV;
+typedef struct VkExternalImageFormatPropertiesNV {
+ VkImageFormatProperties imageFormatProperties;
+ VkExternalMemoryFeatureFlagsNV externalMemoryFeatures;
+ VkExternalMemoryHandleTypeFlagsNV exportFromImportedHandleTypes;
+ VkExternalMemoryHandleTypeFlagsNV compatibleHandleTypes;
+} VkExternalImageFormatPropertiesNV;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ VkImageTiling tiling,
+ VkImageUsageFlags usage,
+ VkImageCreateFlags flags,
+ VkExternalMemoryHandleTypeFlagsNV externalHandleType,
+ VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties);
+#endif
+
+
+#define VK_NV_external_memory 1
+#define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1
+#define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory"
+typedef struct VkExternalMemoryImageCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagsNV handleTypes;
+} VkExternalMemoryImageCreateInfoNV;
+
+typedef struct VkExportMemoryAllocateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagsNV handleTypes;
+} VkExportMemoryAllocateInfoNV;
+
+
+
+#define VK_EXT_validation_flags 1
+#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 2
+#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags"
+
+typedef enum VkValidationCheckEXT {
+ VK_VALIDATION_CHECK_ALL_EXT = 0,
+ VK_VALIDATION_CHECK_SHADERS_EXT = 1,
+ VK_VALIDATION_CHECK_BEGIN_RANGE_EXT = VK_VALIDATION_CHECK_ALL_EXT,
+ VK_VALIDATION_CHECK_END_RANGE_EXT = VK_VALIDATION_CHECK_SHADERS_EXT,
+ VK_VALIDATION_CHECK_RANGE_SIZE_EXT = (VK_VALIDATION_CHECK_SHADERS_EXT - VK_VALIDATION_CHECK_ALL_EXT + 1),
+ VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkValidationCheckEXT;
+typedef struct VkValidationFlagsEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t disabledValidationCheckCount;
+ const VkValidationCheckEXT* pDisabledValidationChecks;
+} VkValidationFlagsEXT;
+
+
+
+#define VK_EXT_shader_subgroup_ballot 1
+#define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1
+#define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot"
+
+
+#define VK_EXT_shader_subgroup_vote 1
+#define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1
+#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
+
+
+#define VK_EXT_texture_compression_astc_hdr 1
+#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION 1
+#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME "VK_EXT_texture_compression_astc_hdr"
+typedef struct VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 textureCompressionASTC_HDR;
+} VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT;
+
+
+
+#define VK_EXT_astc_decode_mode 1
+#define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1
+#define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode"
+typedef struct VkImageViewASTCDecodeModeEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkFormat decodeMode;
+} VkImageViewASTCDecodeModeEXT;
+
+typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 decodeModeSharedExponent;
+} VkPhysicalDeviceASTCDecodeFeaturesEXT;
+
+
+
+#define VK_EXT_conditional_rendering 1
+#define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 2
+#define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering"
+
+typedef enum VkConditionalRenderingFlagBitsEXT {
+ VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001,
+ VK_CONDITIONAL_RENDERING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkConditionalRenderingFlagBitsEXT;
+typedef VkFlags VkConditionalRenderingFlagsEXT;
+typedef struct VkConditionalRenderingBeginInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer buffer;
+ VkDeviceSize offset;
+ VkConditionalRenderingFlagsEXT flags;
+} VkConditionalRenderingBeginInfoEXT;
+
+typedef struct VkPhysicalDeviceConditionalRenderingFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 conditionalRendering;
+ VkBool32 inheritedConditionalRendering;
+} VkPhysicalDeviceConditionalRenderingFeaturesEXT;
+
+typedef struct VkCommandBufferInheritanceConditionalRenderingInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 conditionalRenderingEnable;
+} VkCommandBufferInheritanceConditionalRenderingInfoEXT;
+
+typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRenderingEXT)(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin);
+typedef void (VKAPI_PTR *PFN_vkCmdEndConditionalRenderingEXT)(VkCommandBuffer commandBuffer);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRenderingEXT(
+ VkCommandBuffer commandBuffer,
+ const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT(
+ VkCommandBuffer commandBuffer);
+#endif
+
+
+#define VK_NVX_device_generated_commands 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
+#define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3
+#define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands"
+
+typedef enum VkIndirectCommandsTokenTypeNVX {
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX = 0,
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX = 1,
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX = 2,
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX = 3,
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX = 4,
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX = 5,
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX = 6,
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX = 7,
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX,
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX,
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX + 1),
+ VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkIndirectCommandsTokenTypeNVX;
+
+typedef enum VkObjectEntryTypeNVX {
+ VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX = 0,
+ VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX = 1,
+ VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX = 2,
+ VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX = 3,
+ VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX = 4,
+ VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX,
+ VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX,
+ VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX + 1),
+ VK_OBJECT_ENTRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkObjectEntryTypeNVX;
+
+typedef enum VkIndirectCommandsLayoutUsageFlagBitsNVX {
+ VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001,
+ VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002,
+ VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004,
+ VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008,
+ VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkIndirectCommandsLayoutUsageFlagBitsNVX;
+typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNVX;
+
+typedef enum VkObjectEntryUsageFlagBitsNVX {
+ VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001,
+ VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002,
+ VK_OBJECT_ENTRY_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkObjectEntryUsageFlagBitsNVX;
+typedef VkFlags VkObjectEntryUsageFlagsNVX;
+typedef struct VkDeviceGeneratedCommandsFeaturesNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 computeBindingPointSupport;
+} VkDeviceGeneratedCommandsFeaturesNVX;
+
+typedef struct VkDeviceGeneratedCommandsLimitsNVX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t maxIndirectCommandsLayoutTokenCount;
+ uint32_t maxObjectEntryCounts;
+ uint32_t minSequenceCountBufferOffsetAlignment;
+ uint32_t minSequenceIndexBufferOffsetAlignment;
+ uint32_t minCommandsTokenBufferOffsetAlignment;
+} VkDeviceGeneratedCommandsLimitsNVX;
+
+typedef struct VkIndirectCommandsTokenNVX {
+ VkIndirectCommandsTokenTypeNVX tokenType;
+ VkBuffer buffer;
+ VkDeviceSize offset;
+} VkIndirectCommandsTokenNVX;
+
+typedef struct VkIndirectCommandsLayoutTokenNVX {
+ VkIndirectCommandsTokenTypeNVX tokenType;
+ uint32_t bindingUnit;
+ uint32_t dynamicCount;
+ uint32_t divisor;
+} VkIndirectCommandsLayoutTokenNVX;
+
+typedef struct VkIndirectCommandsLayoutCreateInfoNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineBindPoint pipelineBindPoint;
+ VkIndirectCommandsLayoutUsageFlagsNVX flags;
+ uint32_t tokenCount;
+ const VkIndirectCommandsLayoutTokenNVX* pTokens;
+} VkIndirectCommandsLayoutCreateInfoNVX;
+
+typedef struct VkCmdProcessCommandsInfoNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkObjectTableNVX objectTable;
+ VkIndirectCommandsLayoutNVX indirectCommandsLayout;
+ uint32_t indirectCommandsTokenCount;
+ const VkIndirectCommandsTokenNVX* pIndirectCommandsTokens;
+ uint32_t maxSequencesCount;
+ VkCommandBuffer targetCommandBuffer;
+ VkBuffer sequencesCountBuffer;
+ VkDeviceSize sequencesCountOffset;
+ VkBuffer sequencesIndexBuffer;
+ VkDeviceSize sequencesIndexOffset;
+} VkCmdProcessCommandsInfoNVX;
+
+typedef struct VkCmdReserveSpaceForCommandsInfoNVX {
+ VkStructureType sType;
+ const void* pNext;
+ VkObjectTableNVX objectTable;
+ VkIndirectCommandsLayoutNVX indirectCommandsLayout;
+ uint32_t maxSequencesCount;
+} VkCmdReserveSpaceForCommandsInfoNVX;
+
+typedef struct VkObjectTableCreateInfoNVX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t objectCount;
+ const VkObjectEntryTypeNVX* pObjectEntryTypes;
+ const uint32_t* pObjectEntryCounts;
+ const VkObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags;
+ uint32_t maxUniformBuffersPerDescriptor;
+ uint32_t maxStorageBuffersPerDescriptor;
+ uint32_t maxStorageImagesPerDescriptor;
+ uint32_t maxSampledImagesPerDescriptor;
+ uint32_t maxPipelineLayouts;
+} VkObjectTableCreateInfoNVX;
+
+typedef struct VkObjectTableEntryNVX {
+ VkObjectEntryTypeNVX type;
+ VkObjectEntryUsageFlagsNVX flags;
+} VkObjectTableEntryNVX;
+
+typedef struct VkObjectTablePipelineEntryNVX {
+ VkObjectEntryTypeNVX type;
+ VkObjectEntryUsageFlagsNVX flags;
+ VkPipeline pipeline;
+} VkObjectTablePipelineEntryNVX;
+
+typedef struct VkObjectTableDescriptorSetEntryNVX {
+ VkObjectEntryTypeNVX type;
+ VkObjectEntryUsageFlagsNVX flags;
+ VkPipelineLayout pipelineLayout;
+ VkDescriptorSet descriptorSet;
+} VkObjectTableDescriptorSetEntryNVX;
+
+typedef struct VkObjectTableVertexBufferEntryNVX {
+ VkObjectEntryTypeNVX type;
+ VkObjectEntryUsageFlagsNVX flags;
+ VkBuffer buffer;
+} VkObjectTableVertexBufferEntryNVX;
+
+typedef struct VkObjectTableIndexBufferEntryNVX {
+ VkObjectEntryTypeNVX type;
+ VkObjectEntryUsageFlagsNVX flags;
+ VkBuffer buffer;
+ VkIndexType indexType;
+} VkObjectTableIndexBufferEntryNVX;
+
+typedef struct VkObjectTablePushConstantEntryNVX {
+ VkObjectEntryTypeNVX type;
+ VkObjectEntryUsageFlagsNVX flags;
+ VkPipelineLayout pipelineLayout;
+ VkShaderStageFlags stageFlags;
+} VkObjectTablePushConstantEntryNVX;
+
+typedef void (VKAPI_PTR *PFN_vkCmdProcessCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdReserveSpaceForCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNVX)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout);
+typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNVX)(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateObjectTableNVX)(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable);
+typedef void (VKAPI_PTR *PFN_vkDestroyObjectTableNVX)(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkRegisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices);
+typedef VkResult (VKAPI_PTR *PFN_vkUnregisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)(VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdProcessCommandsNVX(
+ VkCommandBuffer commandBuffer,
+ const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdReserveSpaceForCommandsNVX(
+ VkCommandBuffer commandBuffer,
+ const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNVX(
+ VkDevice device,
+ const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNVX(
+ VkDevice device,
+ VkIndirectCommandsLayoutNVX indirectCommandsLayout,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateObjectTableNVX(
+ VkDevice device,
+ const VkObjectTableCreateInfoNVX* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkObjectTableNVX* pObjectTable);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyObjectTableNVX(
+ VkDevice device,
+ VkObjectTableNVX objectTable,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkRegisterObjectsNVX(
+ VkDevice device,
+ VkObjectTableNVX objectTable,
+ uint32_t objectCount,
+ const VkObjectTableEntryNVX* const* ppObjectTableEntries,
+ const uint32_t* pObjectIndices);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkUnregisterObjectsNVX(
+ VkDevice device,
+ VkObjectTableNVX objectTable,
+ uint32_t objectCount,
+ const VkObjectEntryTypeNVX* pObjectEntryTypes,
+ const uint32_t* pObjectIndices);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX(
+ VkPhysicalDevice physicalDevice,
+ VkDeviceGeneratedCommandsFeaturesNVX* pFeatures,
+ VkDeviceGeneratedCommandsLimitsNVX* pLimits);
+#endif
+
+
+#define VK_NV_clip_space_w_scaling 1
+#define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1
+#define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling"
+typedef struct VkViewportWScalingNV {
+ float xcoeff;
+ float ycoeff;
+} VkViewportWScalingNV;
+
+typedef struct VkPipelineViewportWScalingStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 viewportWScalingEnable;
+ uint32_t viewportCount;
+ const VkViewportWScalingNV* pViewportWScalings;
+} VkPipelineViewportWScalingStateCreateInfoNV;
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkViewportWScalingNV* pViewportWScalings);
+#endif
+
+
+#define VK_EXT_direct_mode_display 1
+#define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1
+#define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display"
+typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT(
+ VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display);
+#endif
+
+
+#define VK_EXT_display_surface_counter 1
+#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1
+#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter"
+
+typedef enum VkSurfaceCounterFlagBitsEXT {
+ VK_SURFACE_COUNTER_VBLANK_EXT = 0x00000001,
+ VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkSurfaceCounterFlagBitsEXT;
+typedef VkFlags VkSurfaceCounterFlagsEXT;
+typedef struct VkSurfaceCapabilities2EXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t minImageCount;
+ uint32_t maxImageCount;
+ VkExtent2D currentExtent;
+ VkExtent2D minImageExtent;
+ VkExtent2D maxImageExtent;
+ uint32_t maxImageArrayLayers;
+ VkSurfaceTransformFlagsKHR supportedTransforms;
+ VkSurfaceTransformFlagBitsKHR currentTransform;
+ VkCompositeAlphaFlagsKHR supportedCompositeAlpha;
+ VkImageUsageFlags supportedUsageFlags;
+ VkSurfaceCounterFlagsEXT supportedSurfaceCounters;
+} VkSurfaceCapabilities2EXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ VkSurfaceCapabilities2EXT* pSurfaceCapabilities);
+#endif
+
+
+#define VK_EXT_display_control 1
+#define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1
+#define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control"
+
+typedef enum VkDisplayPowerStateEXT {
+ VK_DISPLAY_POWER_STATE_OFF_EXT = 0,
+ VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1,
+ VK_DISPLAY_POWER_STATE_ON_EXT = 2,
+ VK_DISPLAY_POWER_STATE_BEGIN_RANGE_EXT = VK_DISPLAY_POWER_STATE_OFF_EXT,
+ VK_DISPLAY_POWER_STATE_END_RANGE_EXT = VK_DISPLAY_POWER_STATE_ON_EXT,
+ VK_DISPLAY_POWER_STATE_RANGE_SIZE_EXT = (VK_DISPLAY_POWER_STATE_ON_EXT - VK_DISPLAY_POWER_STATE_OFF_EXT + 1),
+ VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDisplayPowerStateEXT;
+
+typedef enum VkDeviceEventTypeEXT {
+ VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0,
+ VK_DEVICE_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT,
+ VK_DEVICE_EVENT_TYPE_END_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT,
+ VK_DEVICE_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT + 1),
+ VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDeviceEventTypeEXT;
+
+typedef enum VkDisplayEventTypeEXT {
+ VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0,
+ VK_DISPLAY_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT,
+ VK_DISPLAY_EVENT_TYPE_END_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT,
+ VK_DISPLAY_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT + 1),
+ VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDisplayEventTypeEXT;
+typedef struct VkDisplayPowerInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDisplayPowerStateEXT powerState;
+} VkDisplayPowerInfoEXT;
+
+typedef struct VkDeviceEventInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceEventTypeEXT deviceEvent;
+} VkDeviceEventInfoEXT;
+
+typedef struct VkDisplayEventInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDisplayEventTypeEXT displayEvent;
+} VkDisplayEventInfoEXT;
+
+typedef struct VkSwapchainCounterCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkSurfaceCounterFlagsEXT surfaceCounters;
+} VkSwapchainCounterCreateInfoEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
+typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT(
+ VkDevice device,
+ VkDisplayKHR display,
+ const VkDisplayPowerInfoEXT* pDisplayPowerInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT(
+ VkDevice device,
+ const VkDeviceEventInfoEXT* pDeviceEventInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT(
+ VkDevice device,
+ VkDisplayKHR display,
+ const VkDisplayEventInfoEXT* pDisplayEventInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ VkSurfaceCounterFlagBitsEXT counter,
+ uint64_t* pCounterValue);
+#endif
+
+
+#define VK_GOOGLE_display_timing 1
+#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1
+#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing"
+typedef struct VkRefreshCycleDurationGOOGLE {
+ uint64_t refreshDuration;
+} VkRefreshCycleDurationGOOGLE;
+
+typedef struct VkPastPresentationTimingGOOGLE {
+ uint32_t presentID;
+ uint64_t desiredPresentTime;
+ uint64_t actualPresentTime;
+ uint64_t earliestPresentTime;
+ uint64_t presentMargin;
+} VkPastPresentationTimingGOOGLE;
+
+typedef struct VkPresentTimeGOOGLE {
+ uint32_t presentID;
+ uint64_t desiredPresentTime;
+} VkPresentTimeGOOGLE;
+
+typedef struct VkPresentTimesInfoGOOGLE {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t swapchainCount;
+ const VkPresentTimeGOOGLE* pTimes;
+} VkPresentTimesInfoGOOGLE;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ uint32_t* pPresentationTimingCount,
+ VkPastPresentationTimingGOOGLE* pPresentationTimings);
+#endif
+
+
+#define VK_NV_sample_mask_override_coverage 1
+#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1
+#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage"
+
+
+#define VK_NV_geometry_shader_passthrough 1
+#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1
+#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough"
+
+
+#define VK_NV_viewport_array2 1
+#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1
+#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2"
+
+
+#define VK_NVX_multiview_per_view_attributes 1
+#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1
+#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes"
+typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 perViewPositionAllComponents;
+} VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX;
+
+
+
+#define VK_NV_viewport_swizzle 1
+#define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1
+#define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle"
+
+typedef enum VkViewportCoordinateSwizzleNV {
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_BEGIN_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_END_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_RANGE_SIZE_NV = (VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV + 1),
+ VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkViewportCoordinateSwizzleNV;
+typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV;
+typedef struct VkViewportSwizzleNV {
+ VkViewportCoordinateSwizzleNV x;
+ VkViewportCoordinateSwizzleNV y;
+ VkViewportCoordinateSwizzleNV z;
+ VkViewportCoordinateSwizzleNV w;
+} VkViewportSwizzleNV;
+
+typedef struct VkPipelineViewportSwizzleStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineViewportSwizzleStateCreateFlagsNV flags;
+ uint32_t viewportCount;
+ const VkViewportSwizzleNV* pViewportSwizzles;
+} VkPipelineViewportSwizzleStateCreateInfoNV;
+
+
+
+#define VK_EXT_discard_rectangles 1
+#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1
+#define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles"
+
+typedef enum VkDiscardRectangleModeEXT {
+ VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0,
+ VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1,
+ VK_DISCARD_RECTANGLE_MODE_BEGIN_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT,
+ VK_DISCARD_RECTANGLE_MODE_END_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT,
+ VK_DISCARD_RECTANGLE_MODE_RANGE_SIZE_EXT = (VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT - VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT + 1),
+ VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDiscardRectangleModeEXT;
+typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT;
+typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxDiscardRectangles;
+} VkPhysicalDeviceDiscardRectanglePropertiesEXT;
+
+typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineDiscardRectangleStateCreateFlagsEXT flags;
+ VkDiscardRectangleModeEXT discardRectangleMode;
+ uint32_t discardRectangleCount;
+ const VkRect2D* pDiscardRectangles;
+} VkPipelineDiscardRectangleStateCreateInfoEXT;
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstDiscardRectangle,
+ uint32_t discardRectangleCount,
+ const VkRect2D* pDiscardRectangles);
+#endif
+
+
+#define VK_EXT_conservative_rasterization 1
+#define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1
+#define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization"
+
+typedef enum VkConservativeRasterizationModeEXT {
+ VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0,
+ VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1,
+ VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2,
+ VK_CONSERVATIVE_RASTERIZATION_MODE_BEGIN_RANGE_EXT = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT,
+ VK_CONSERVATIVE_RASTERIZATION_MODE_END_RANGE_EXT = VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT,
+ VK_CONSERVATIVE_RASTERIZATION_MODE_RANGE_SIZE_EXT = (VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT - VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT + 1),
+ VK_CONSERVATIVE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkConservativeRasterizationModeEXT;
+typedef VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT;
+typedef struct VkPhysicalDeviceConservativeRasterizationPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ float primitiveOverestimationSize;
+ float maxExtraPrimitiveOverestimationSize;
+ float extraPrimitiveOverestimationSizeGranularity;
+ VkBool32 primitiveUnderestimation;
+ VkBool32 conservativePointAndLineRasterization;
+ VkBool32 degenerateTrianglesRasterized;
+ VkBool32 degenerateLinesRasterized;
+ VkBool32 fullyCoveredFragmentShaderInputVariable;
+ VkBool32 conservativeRasterizationPostDepthCoverage;
+} VkPhysicalDeviceConservativeRasterizationPropertiesEXT;
+
+typedef struct VkPipelineRasterizationConservativeStateCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineRasterizationConservativeStateCreateFlagsEXT flags;
+ VkConservativeRasterizationModeEXT conservativeRasterizationMode;
+ float extraPrimitiveOverestimationSize;
+} VkPipelineRasterizationConservativeStateCreateInfoEXT;
+
+
+
+#define VK_EXT_depth_clip_enable 1
+#define VK_EXT_DEPTH_CLIP_ENABLE_SPEC_VERSION 1
+#define VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME "VK_EXT_depth_clip_enable"
+typedef VkFlags VkPipelineRasterizationDepthClipStateCreateFlagsEXT;
+typedef struct VkPhysicalDeviceDepthClipEnableFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 depthClipEnable;
+} VkPhysicalDeviceDepthClipEnableFeaturesEXT;
+
+typedef struct VkPipelineRasterizationDepthClipStateCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineRasterizationDepthClipStateCreateFlagsEXT flags;
+ VkBool32 depthClipEnable;
+} VkPipelineRasterizationDepthClipStateCreateInfoEXT;
+
+
+
+#define VK_EXT_swapchain_colorspace 1
+#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 4
+#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
+
+
+#define VK_EXT_hdr_metadata 1
+#define VK_EXT_HDR_METADATA_SPEC_VERSION 2
+#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
+typedef struct VkXYColorEXT {
+ float x;
+ float y;
+} VkXYColorEXT;
+
+typedef struct VkHdrMetadataEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkXYColorEXT displayPrimaryRed;
+ VkXYColorEXT displayPrimaryGreen;
+ VkXYColorEXT displayPrimaryBlue;
+ VkXYColorEXT whitePoint;
+ float maxLuminance;
+ float minLuminance;
+ float maxContentLightLevel;
+ float maxFrameAverageLightLevel;
+} VkHdrMetadataEXT;
+
+typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT(
+ VkDevice device,
+ uint32_t swapchainCount,
+ const VkSwapchainKHR* pSwapchains,
+ const VkHdrMetadataEXT* pMetadata);
+#endif
+
+
+#define VK_EXT_external_memory_dma_buf 1
+#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1
+#define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf"
+
+
+#define VK_EXT_queue_family_foreign 1
+#define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1
+#define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign"
+#define VK_QUEUE_FAMILY_FOREIGN_EXT (~0U-2)
+
+
+#define VK_EXT_debug_utils 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT)
+#define VK_EXT_DEBUG_UTILS_SPEC_VERSION 1
+#define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils"
+typedef VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT;
+typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT;
+
+typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT {
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001,
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010,
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100,
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000,
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDebugUtilsMessageSeverityFlagBitsEXT;
+typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT;
+
+typedef enum VkDebugUtilsMessageTypeFlagBitsEXT {
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDebugUtilsMessageTypeFlagBitsEXT;
+typedef VkFlags VkDebugUtilsMessageTypeFlagsEXT;
+typedef struct VkDebugUtilsObjectNameInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkObjectType objectType;
+ uint64_t objectHandle;
+ const char* pObjectName;
+} VkDebugUtilsObjectNameInfoEXT;
+
+typedef struct VkDebugUtilsObjectTagInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkObjectType objectType;
+ uint64_t objectHandle;
+ uint64_t tagName;
+ size_t tagSize;
+ const void* pTag;
+} VkDebugUtilsObjectTagInfoEXT;
+
+typedef struct VkDebugUtilsLabelEXT {
+ VkStructureType sType;
+ const void* pNext;
+ const char* pLabelName;
+ float color[4];
+} VkDebugUtilsLabelEXT;
+
+typedef struct VkDebugUtilsMessengerCallbackDataEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDebugUtilsMessengerCallbackDataFlagsEXT flags;
+ const char* pMessageIdName;
+ int32_t messageIdNumber;
+ const char* pMessage;
+ uint32_t queueLabelCount;
+ const VkDebugUtilsLabelEXT* pQueueLabels;
+ uint32_t cmdBufLabelCount;
+ const VkDebugUtilsLabelEXT* pCmdBufLabels;
+ uint32_t objectCount;
+ const VkDebugUtilsObjectNameInfoEXT* pObjects;
+} VkDebugUtilsMessengerCallbackDataEXT;
+
+typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)(
+ VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
+ void* pUserData);
+
+typedef struct VkDebugUtilsMessengerCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDebugUtilsMessengerCreateFlagsEXT flags;
+ VkDebugUtilsMessageSeverityFlagsEXT messageSeverity;
+ VkDebugUtilsMessageTypeFlagsEXT messageType;
+ PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback;
+ void* pUserData;
+} VkDebugUtilsMessengerCreateInfoEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectNameEXT)(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectTagEXT)(VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo);
+typedef void (VKAPI_PTR *PFN_vkQueueBeginDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo);
+typedef void (VKAPI_PTR *PFN_vkQueueEndDebugUtilsLabelEXT)(VkQueue queue);
+typedef void (VKAPI_PTR *PFN_vkQueueInsertDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdBeginDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdEndDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer);
+typedef void (VKAPI_PTR *PFN_vkCmdInsertDebugUtilsLabelEXT)(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugUtilsMessengerEXT)(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger);
+typedef void (VKAPI_PTR *PFN_vkDestroyDebugUtilsMessengerEXT)(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkSubmitDebugUtilsMessageEXT)(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectNameEXT(
+ VkDevice device,
+ const VkDebugUtilsObjectNameInfoEXT* pNameInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectTagEXT(
+ VkDevice device,
+ const VkDebugUtilsObjectTagInfoEXT* pTagInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkQueueBeginDebugUtilsLabelEXT(
+ VkQueue queue,
+ const VkDebugUtilsLabelEXT* pLabelInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkQueueEndDebugUtilsLabelEXT(
+ VkQueue queue);
+
+VKAPI_ATTR void VKAPI_CALL vkQueueInsertDebugUtilsLabelEXT(
+ VkQueue queue,
+ const VkDebugUtilsLabelEXT* pLabelInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginDebugUtilsLabelEXT(
+ VkCommandBuffer commandBuffer,
+ const VkDebugUtilsLabelEXT* pLabelInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndDebugUtilsLabelEXT(
+ VkCommandBuffer commandBuffer);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdInsertDebugUtilsLabelEXT(
+ VkCommandBuffer commandBuffer,
+ const VkDebugUtilsLabelEXT* pLabelInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT(
+ VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDebugUtilsMessengerEXT* pMessenger);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT(
+ VkInstance instance,
+ VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT(
+ VkInstance instance,
+ VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData);
+#endif
+
+
+#define VK_EXT_sampler_filter_minmax 1
+#define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 2
+#define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax"
+typedef VkSamplerReductionMode VkSamplerReductionModeEXT;
+
+typedef VkSamplerReductionModeCreateInfo VkSamplerReductionModeCreateInfoEXT;
+
+typedef VkPhysicalDeviceSamplerFilterMinmaxProperties VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT;
+
+
+
+#define VK_AMD_gpu_shader_int16 1
+#define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 2
+#define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16"
+
+
+#define VK_AMD_mixed_attachment_samples 1
+#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1
+#define VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME "VK_AMD_mixed_attachment_samples"
+
+
+#define VK_AMD_shader_fragment_mask 1
+#define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1
+#define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask"
+
+
+#define VK_EXT_inline_uniform_block 1
+#define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1
+#define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block"
+typedef struct VkPhysicalDeviceInlineUniformBlockFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 inlineUniformBlock;
+ VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind;
+} VkPhysicalDeviceInlineUniformBlockFeaturesEXT;
+
+typedef struct VkPhysicalDeviceInlineUniformBlockPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxInlineUniformBlockSize;
+ uint32_t maxPerStageDescriptorInlineUniformBlocks;
+ uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks;
+ uint32_t maxDescriptorSetInlineUniformBlocks;
+ uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks;
+} VkPhysicalDeviceInlineUniformBlockPropertiesEXT;
+
+typedef struct VkWriteDescriptorSetInlineUniformBlockEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t dataSize;
+ const void* pData;
+} VkWriteDescriptorSetInlineUniformBlockEXT;
+
+typedef struct VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t maxInlineUniformBlockBindings;
+} VkDescriptorPoolInlineUniformBlockCreateInfoEXT;
+
+
+
+#define VK_EXT_shader_stencil_export 1
+#define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1
+#define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export"
+
+
+#define VK_EXT_sample_locations 1
+#define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1
+#define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations"
+typedef struct VkSampleLocationEXT {
+ float x;
+ float y;
+} VkSampleLocationEXT;
+
+typedef struct VkSampleLocationsInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkSampleCountFlagBits sampleLocationsPerPixel;
+ VkExtent2D sampleLocationGridSize;
+ uint32_t sampleLocationsCount;
+ const VkSampleLocationEXT* pSampleLocations;
+} VkSampleLocationsInfoEXT;
+
+typedef struct VkAttachmentSampleLocationsEXT {
+ uint32_t attachmentIndex;
+ VkSampleLocationsInfoEXT sampleLocationsInfo;
+} VkAttachmentSampleLocationsEXT;
+
+typedef struct VkSubpassSampleLocationsEXT {
+ uint32_t subpassIndex;
+ VkSampleLocationsInfoEXT sampleLocationsInfo;
+} VkSubpassSampleLocationsEXT;
+
+typedef struct VkRenderPassSampleLocationsBeginInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t attachmentInitialSampleLocationsCount;
+ const VkAttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations;
+ uint32_t postSubpassSampleLocationsCount;
+ const VkSubpassSampleLocationsEXT* pPostSubpassSampleLocations;
+} VkRenderPassSampleLocationsBeginInfoEXT;
+
+typedef struct VkPipelineSampleLocationsStateCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 sampleLocationsEnable;
+ VkSampleLocationsInfoEXT sampleLocationsInfo;
+} VkPipelineSampleLocationsStateCreateInfoEXT;
+
+typedef struct VkPhysicalDeviceSampleLocationsPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkSampleCountFlags sampleLocationSampleCounts;
+ VkExtent2D maxSampleLocationGridSize;
+ float sampleLocationCoordinateRange[2];
+ uint32_t sampleLocationSubPixelBits;
+ VkBool32 variableSampleLocations;
+} VkPhysicalDeviceSampleLocationsPropertiesEXT;
+
+typedef struct VkMultisamplePropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkExtent2D maxSampleLocationGridSize;
+} VkMultisamplePropertiesEXT;
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEXT)(VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEXT(
+ VkCommandBuffer commandBuffer,
+ const VkSampleLocationsInfoEXT* pSampleLocationsInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT(
+ VkPhysicalDevice physicalDevice,
+ VkSampleCountFlagBits samples,
+ VkMultisamplePropertiesEXT* pMultisampleProperties);
+#endif
+
+
+#define VK_EXT_blend_operation_advanced 1
+#define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2
+#define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced"
+
+typedef enum VkBlendOverlapEXT {
+ VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0,
+ VK_BLEND_OVERLAP_DISJOINT_EXT = 1,
+ VK_BLEND_OVERLAP_CONJOINT_EXT = 2,
+ VK_BLEND_OVERLAP_BEGIN_RANGE_EXT = VK_BLEND_OVERLAP_UNCORRELATED_EXT,
+ VK_BLEND_OVERLAP_END_RANGE_EXT = VK_BLEND_OVERLAP_CONJOINT_EXT,
+ VK_BLEND_OVERLAP_RANGE_SIZE_EXT = (VK_BLEND_OVERLAP_CONJOINT_EXT - VK_BLEND_OVERLAP_UNCORRELATED_EXT + 1),
+ VK_BLEND_OVERLAP_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkBlendOverlapEXT;
+typedef struct VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 advancedBlendCoherentOperations;
+} VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT;
+
+typedef struct VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t advancedBlendMaxColorAttachments;
+ VkBool32 advancedBlendIndependentBlend;
+ VkBool32 advancedBlendNonPremultipliedSrcColor;
+ VkBool32 advancedBlendNonPremultipliedDstColor;
+ VkBool32 advancedBlendCorrelatedOverlap;
+ VkBool32 advancedBlendAllOperations;
+} VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT;
+
+typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 srcPremultiplied;
+ VkBool32 dstPremultiplied;
+ VkBlendOverlapEXT blendOverlap;
+} VkPipelineColorBlendAdvancedStateCreateInfoEXT;
+
+
+
+#define VK_NV_fragment_coverage_to_color 1
+#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1
+#define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color"
+typedef VkFlags VkPipelineCoverageToColorStateCreateFlagsNV;
+typedef struct VkPipelineCoverageToColorStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCoverageToColorStateCreateFlagsNV flags;
+ VkBool32 coverageToColorEnable;
+ uint32_t coverageToColorLocation;
+} VkPipelineCoverageToColorStateCreateInfoNV;
+
+
+
+#define VK_NV_framebuffer_mixed_samples 1
+#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1
+#define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples"
+
+typedef enum VkCoverageModulationModeNV {
+ VK_COVERAGE_MODULATION_MODE_NONE_NV = 0,
+ VK_COVERAGE_MODULATION_MODE_RGB_NV = 1,
+ VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2,
+ VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3,
+ VK_COVERAGE_MODULATION_MODE_BEGIN_RANGE_NV = VK_COVERAGE_MODULATION_MODE_NONE_NV,
+ VK_COVERAGE_MODULATION_MODE_END_RANGE_NV = VK_COVERAGE_MODULATION_MODE_RGBA_NV,
+ VK_COVERAGE_MODULATION_MODE_RANGE_SIZE_NV = (VK_COVERAGE_MODULATION_MODE_RGBA_NV - VK_COVERAGE_MODULATION_MODE_NONE_NV + 1),
+ VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkCoverageModulationModeNV;
+typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV;
+typedef struct VkPipelineCoverageModulationStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCoverageModulationStateCreateFlagsNV flags;
+ VkCoverageModulationModeNV coverageModulationMode;
+ VkBool32 coverageModulationTableEnable;
+ uint32_t coverageModulationTableCount;
+ const float* pCoverageModulationTable;
+} VkPipelineCoverageModulationStateCreateInfoNV;
+
+
+
+#define VK_NV_fill_rectangle 1
+#define VK_NV_FILL_RECTANGLE_SPEC_VERSION 1
+#define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle"
+
+
+#define VK_NV_shader_sm_builtins 1
+#define VK_NV_SHADER_SM_BUILTINS_SPEC_VERSION 1
+#define VK_NV_SHADER_SM_BUILTINS_EXTENSION_NAME "VK_NV_shader_sm_builtins"
+typedef struct VkPhysicalDeviceShaderSMBuiltinsPropertiesNV {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t shaderSMCount;
+ uint32_t shaderWarpsPerSM;
+} VkPhysicalDeviceShaderSMBuiltinsPropertiesNV;
+
+typedef struct VkPhysicalDeviceShaderSMBuiltinsFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderSMBuiltins;
+} VkPhysicalDeviceShaderSMBuiltinsFeaturesNV;
+
+
+
+#define VK_EXT_post_depth_coverage 1
+#define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1
+#define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage"
+
+
+#define VK_EXT_image_drm_format_modifier 1
+#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 1
+#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier"
+typedef struct VkDrmFormatModifierPropertiesEXT {
+ uint64_t drmFormatModifier;
+ uint32_t drmFormatModifierPlaneCount;
+ VkFormatFeatureFlags drmFormatModifierTilingFeatures;
+} VkDrmFormatModifierPropertiesEXT;
+
+typedef struct VkDrmFormatModifierPropertiesListEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t drmFormatModifierCount;
+ VkDrmFormatModifierPropertiesEXT* pDrmFormatModifierProperties;
+} VkDrmFormatModifierPropertiesListEXT;
+
+typedef struct VkPhysicalDeviceImageDrmFormatModifierInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint64_t drmFormatModifier;
+ VkSharingMode sharingMode;
+ uint32_t queueFamilyIndexCount;
+ const uint32_t* pQueueFamilyIndices;
+} VkPhysicalDeviceImageDrmFormatModifierInfoEXT;
+
+typedef struct VkImageDrmFormatModifierListCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t drmFormatModifierCount;
+ const uint64_t* pDrmFormatModifiers;
+} VkImageDrmFormatModifierListCreateInfoEXT;
+
+typedef struct VkImageDrmFormatModifierExplicitCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint64_t drmFormatModifier;
+ uint32_t drmFormatModifierPlaneCount;
+ const VkSubresourceLayout* pPlaneLayouts;
+} VkImageDrmFormatModifierExplicitCreateInfoEXT;
+
+typedef struct VkImageDrmFormatModifierPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint64_t drmFormatModifier;
+} VkImageDrmFormatModifierPropertiesEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetImageDrmFormatModifierPropertiesEXT)(VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetImageDrmFormatModifierPropertiesEXT(
+ VkDevice device,
+ VkImage image,
+ VkImageDrmFormatModifierPropertiesEXT* pProperties);
+#endif
+
+
+#define VK_EXT_validation_cache 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT)
+#define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1
+#define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache"
+
+typedef enum VkValidationCacheHeaderVersionEXT {
+ VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1,
+ VK_VALIDATION_CACHE_HEADER_VERSION_BEGIN_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT,
+ VK_VALIDATION_CACHE_HEADER_VERSION_END_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT,
+ VK_VALIDATION_CACHE_HEADER_VERSION_RANGE_SIZE_EXT = (VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT - VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT + 1),
+ VK_VALIDATION_CACHE_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkValidationCacheHeaderVersionEXT;
+typedef VkFlags VkValidationCacheCreateFlagsEXT;
+typedef struct VkValidationCacheCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkValidationCacheCreateFlagsEXT flags;
+ size_t initialDataSize;
+ const void* pInitialData;
+} VkValidationCacheCreateInfoEXT;
+
+typedef struct VkShaderModuleValidationCacheCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkValidationCacheEXT validationCache;
+} VkShaderModuleValidationCacheCreateInfoEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateValidationCacheEXT)(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache);
+typedef void (VKAPI_PTR *PFN_vkDestroyValidationCacheEXT)(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkMergeValidationCachesEXT)(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches);
+typedef VkResult (VKAPI_PTR *PFN_vkGetValidationCacheDataEXT)(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateValidationCacheEXT(
+ VkDevice device,
+ const VkValidationCacheCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkValidationCacheEXT* pValidationCache);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyValidationCacheEXT(
+ VkDevice device,
+ VkValidationCacheEXT validationCache,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkMergeValidationCachesEXT(
+ VkDevice device,
+ VkValidationCacheEXT dstCache,
+ uint32_t srcCacheCount,
+ const VkValidationCacheEXT* pSrcCaches);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT(
+ VkDevice device,
+ VkValidationCacheEXT validationCache,
+ size_t* pDataSize,
+ void* pData);
+#endif
+
+
+#define VK_EXT_descriptor_indexing 1
+#define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2
+#define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing"
+typedef VkDescriptorBindingFlagBits VkDescriptorBindingFlagBitsEXT;
+
+typedef VkDescriptorBindingFlags VkDescriptorBindingFlagsEXT;
+
+typedef VkDescriptorSetLayoutBindingFlagsCreateInfo VkDescriptorSetLayoutBindingFlagsCreateInfoEXT;
+
+typedef VkPhysicalDeviceDescriptorIndexingFeatures VkPhysicalDeviceDescriptorIndexingFeaturesEXT;
+
+typedef VkPhysicalDeviceDescriptorIndexingProperties VkPhysicalDeviceDescriptorIndexingPropertiesEXT;
+
+typedef VkDescriptorSetVariableDescriptorCountAllocateInfo VkDescriptorSetVariableDescriptorCountAllocateInfoEXT;
+
+typedef VkDescriptorSetVariableDescriptorCountLayoutSupport VkDescriptorSetVariableDescriptorCountLayoutSupportEXT;
+
+
+
+#define VK_EXT_shader_viewport_index_layer 1
+#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1
+#define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer"
+
+
+#define VK_NV_shading_rate_image 1
+#define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3
+#define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image"
+
+typedef enum VkShadingRatePaletteEntryNV {
+ VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0,
+ VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1,
+ VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2,
+ VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3,
+ VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10,
+ VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11,
+ VK_SHADING_RATE_PALETTE_ENTRY_BEGIN_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV,
+ VK_SHADING_RATE_PALETTE_ENTRY_END_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV,
+ VK_SHADING_RATE_PALETTE_ENTRY_RANGE_SIZE_NV = (VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV - VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV + 1),
+ VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF
+} VkShadingRatePaletteEntryNV;
+
+typedef enum VkCoarseSampleOrderTypeNV {
+ VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0,
+ VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1,
+ VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2,
+ VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3,
+ VK_COARSE_SAMPLE_ORDER_TYPE_BEGIN_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV,
+ VK_COARSE_SAMPLE_ORDER_TYPE_END_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV,
+ VK_COARSE_SAMPLE_ORDER_TYPE_RANGE_SIZE_NV = (VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV - VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV + 1),
+ VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkCoarseSampleOrderTypeNV;
+typedef struct VkShadingRatePaletteNV {
+ uint32_t shadingRatePaletteEntryCount;
+ const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries;
+} VkShadingRatePaletteNV;
+
+typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 shadingRateImageEnable;
+ uint32_t viewportCount;
+ const VkShadingRatePaletteNV* pShadingRatePalettes;
+} VkPipelineViewportShadingRateImageStateCreateInfoNV;
+
+typedef struct VkPhysicalDeviceShadingRateImageFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shadingRateImage;
+ VkBool32 shadingRateCoarseSampleOrder;
+} VkPhysicalDeviceShadingRateImageFeaturesNV;
+
+typedef struct VkPhysicalDeviceShadingRateImagePropertiesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkExtent2D shadingRateTexelSize;
+ uint32_t shadingRatePaletteSize;
+ uint32_t shadingRateMaxCoarseSamples;
+} VkPhysicalDeviceShadingRateImagePropertiesNV;
+
+typedef struct VkCoarseSampleLocationNV {
+ uint32_t pixelX;
+ uint32_t pixelY;
+ uint32_t sample;
+} VkCoarseSampleLocationNV;
+
+typedef struct VkCoarseSampleOrderCustomNV {
+ VkShadingRatePaletteEntryNV shadingRate;
+ uint32_t sampleCount;
+ uint32_t sampleLocationCount;
+ const VkCoarseSampleLocationNV* pSampleLocations;
+} VkCoarseSampleOrderCustomNV;
+
+typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkCoarseSampleOrderTypeNV sampleOrderType;
+ uint32_t customSampleOrderCount;
+ const VkCoarseSampleOrderCustomNV* pCustomSampleOrders;
+} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV;
+
+typedef void (VKAPI_PTR *PFN_vkCmdBindShadingRateImageNV)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout);
+typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes);
+typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV(
+ VkCommandBuffer commandBuffer,
+ VkImageView imageView,
+ VkImageLayout imageLayout);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkShadingRatePaletteNV* pShadingRatePalettes);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV(
+ VkCommandBuffer commandBuffer,
+ VkCoarseSampleOrderTypeNV sampleOrderType,
+ uint32_t customSampleOrderCount,
+ const VkCoarseSampleOrderCustomNV* pCustomSampleOrders);
+#endif
+
+
+#define VK_NV_ray_tracing 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV)
+#define VK_NV_RAY_TRACING_SPEC_VERSION 3
+#define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing"
+#define VK_SHADER_UNUSED_NV (~0U)
+
+typedef enum VkAccelerationStructureTypeNV {
+ VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = 0,
+ VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = 1,
+ VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV,
+ VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV,
+ VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV + 1),
+ VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkAccelerationStructureTypeNV;
+
+typedef enum VkRayTracingShaderGroupTypeNV {
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = 0,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = 1,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = 2,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_BEGIN_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_END_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV,
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_RANGE_SIZE_NV = (VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV + 1),
+ VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkRayTracingShaderGroupTypeNV;
+
+typedef enum VkGeometryTypeNV {
+ VK_GEOMETRY_TYPE_TRIANGLES_NV = 0,
+ VK_GEOMETRY_TYPE_AABBS_NV = 1,
+ VK_GEOMETRY_TYPE_BEGIN_RANGE_NV = VK_GEOMETRY_TYPE_TRIANGLES_NV,
+ VK_GEOMETRY_TYPE_END_RANGE_NV = VK_GEOMETRY_TYPE_AABBS_NV,
+ VK_GEOMETRY_TYPE_RANGE_SIZE_NV = (VK_GEOMETRY_TYPE_AABBS_NV - VK_GEOMETRY_TYPE_TRIANGLES_NV + 1),
+ VK_GEOMETRY_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkGeometryTypeNV;
+
+typedef enum VkCopyAccelerationStructureModeNV {
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = 0,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = 1,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV,
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_NV = (VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV + 1),
+ VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkCopyAccelerationStructureModeNV;
+
+typedef enum VkAccelerationStructureMemoryRequirementsTypeNV {
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV,
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV + 1),
+ VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkAccelerationStructureMemoryRequirementsTypeNV;
+
+typedef enum VkGeometryFlagBitsNV {
+ VK_GEOMETRY_OPAQUE_BIT_NV = 0x00000001,
+ VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = 0x00000002,
+ VK_GEOMETRY_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkGeometryFlagBitsNV;
+typedef VkFlags VkGeometryFlagsNV;
+
+typedef enum VkGeometryInstanceFlagBitsNV {
+ VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = 0x00000001,
+ VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = 0x00000002,
+ VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = 0x00000004,
+ VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = 0x00000008,
+ VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkGeometryInstanceFlagBitsNV;
+typedef VkFlags VkGeometryInstanceFlagsNV;
+
+typedef enum VkBuildAccelerationStructureFlagBitsNV {
+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = 0x00000001,
+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = 0x00000002,
+ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = 0x00000004,
+ VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = 0x00000008,
+ VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = 0x00000010,
+ VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkBuildAccelerationStructureFlagBitsNV;
+typedef VkFlags VkBuildAccelerationStructureFlagsNV;
+typedef struct VkRayTracingShaderGroupCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkRayTracingShaderGroupTypeNV type;
+ uint32_t generalShader;
+ uint32_t closestHitShader;
+ uint32_t anyHitShader;
+ uint32_t intersectionShader;
+} VkRayTracingShaderGroupCreateInfoNV;
+
+typedef struct VkRayTracingPipelineCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCreateFlags flags;
+ uint32_t stageCount;
+ const VkPipelineShaderStageCreateInfo* pStages;
+ uint32_t groupCount;
+ const VkRayTracingShaderGroupCreateInfoNV* pGroups;
+ uint32_t maxRecursionDepth;
+ VkPipelineLayout layout;
+ VkPipeline basePipelineHandle;
+ int32_t basePipelineIndex;
+} VkRayTracingPipelineCreateInfoNV;
+
+typedef struct VkGeometryTrianglesNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer vertexData;
+ VkDeviceSize vertexOffset;
+ uint32_t vertexCount;
+ VkDeviceSize vertexStride;
+ VkFormat vertexFormat;
+ VkBuffer indexData;
+ VkDeviceSize indexOffset;
+ uint32_t indexCount;
+ VkIndexType indexType;
+ VkBuffer transformData;
+ VkDeviceSize transformOffset;
+} VkGeometryTrianglesNV;
+
+typedef struct VkGeometryAABBNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer aabbData;
+ uint32_t numAABBs;
+ uint32_t stride;
+ VkDeviceSize offset;
+} VkGeometryAABBNV;
+
+typedef struct VkGeometryDataNV {
+ VkGeometryTrianglesNV triangles;
+ VkGeometryAABBNV aabbs;
+} VkGeometryDataNV;
+
+typedef struct VkGeometryNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkGeometryTypeNV geometryType;
+ VkGeometryDataNV geometry;
+ VkGeometryFlagsNV flags;
+} VkGeometryNV;
+
+typedef struct VkAccelerationStructureInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccelerationStructureTypeNV type;
+ VkBuildAccelerationStructureFlagsNV flags;
+ uint32_t instanceCount;
+ uint32_t geometryCount;
+ const VkGeometryNV* pGeometries;
+} VkAccelerationStructureInfoNV;
+
+typedef struct VkAccelerationStructureCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceSize compactedSize;
+ VkAccelerationStructureInfoNV info;
+} VkAccelerationStructureCreateInfoNV;
+
+typedef struct VkBindAccelerationStructureMemoryInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccelerationStructureNV accelerationStructure;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+ uint32_t deviceIndexCount;
+ const uint32_t* pDeviceIndices;
+} VkBindAccelerationStructureMemoryInfoNV;
+
+typedef struct VkWriteDescriptorSetAccelerationStructureNV {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t accelerationStructureCount;
+ const VkAccelerationStructureNV* pAccelerationStructures;
+} VkWriteDescriptorSetAccelerationStructureNV;
+
+typedef struct VkAccelerationStructureMemoryRequirementsInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkAccelerationStructureMemoryRequirementsTypeNV type;
+ VkAccelerationStructureNV accelerationStructure;
+} VkAccelerationStructureMemoryRequirementsInfoNV;
+
+typedef struct VkPhysicalDeviceRayTracingPropertiesNV {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t shaderGroupHandleSize;
+ uint32_t maxRecursionDepth;
+ uint32_t maxShaderGroupStride;
+ uint32_t shaderGroupBaseAlignment;
+ uint64_t maxGeometryCount;
+ uint64_t maxInstanceCount;
+ uint64_t maxTriangleCount;
+ uint32_t maxDescriptorSetAccelerationStructures;
+} VkPhysicalDeviceRayTracingPropertiesNV;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure);
+typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
+typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos);
+typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeNV mode);
+typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData);
+typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData);
+typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery);
+typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV(
+ VkDevice device,
+ const VkAccelerationStructureCreateInfoNV* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkAccelerationStructureNV* pAccelerationStructure);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV(
+ VkDevice device,
+ VkAccelerationStructureNV accelerationStructure,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV(
+ VkDevice device,
+ const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo,
+ VkMemoryRequirements2KHR* pMemoryRequirements);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindAccelerationStructureMemoryInfoNV* pBindInfos);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV(
+ VkCommandBuffer commandBuffer,
+ const VkAccelerationStructureInfoNV* pInfo,
+ VkBuffer instanceData,
+ VkDeviceSize instanceOffset,
+ VkBool32 update,
+ VkAccelerationStructureNV dst,
+ VkAccelerationStructureNV src,
+ VkBuffer scratch,
+ VkDeviceSize scratchOffset);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV(
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureNV dst,
+ VkAccelerationStructureNV src,
+ VkCopyAccelerationStructureModeNV mode);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV(
+ VkCommandBuffer commandBuffer,
+ VkBuffer raygenShaderBindingTableBuffer,
+ VkDeviceSize raygenShaderBindingOffset,
+ VkBuffer missShaderBindingTableBuffer,
+ VkDeviceSize missShaderBindingOffset,
+ VkDeviceSize missShaderBindingStride,
+ VkBuffer hitShaderBindingTableBuffer,
+ VkDeviceSize hitShaderBindingOffset,
+ VkDeviceSize hitShaderBindingStride,
+ VkBuffer callableShaderBindingTableBuffer,
+ VkDeviceSize callableShaderBindingOffset,
+ VkDeviceSize callableShaderBindingStride,
+ uint32_t width,
+ uint32_t height,
+ uint32_t depth);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ uint32_t createInfoCount,
+ const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipeline* pPipelines);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV(
+ VkDevice device,
+ VkPipeline pipeline,
+ uint32_t firstGroup,
+ uint32_t groupCount,
+ size_t dataSize,
+ void* pData);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV(
+ VkDevice device,
+ VkAccelerationStructureNV accelerationStructure,
+ size_t dataSize,
+ void* pData);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t accelerationStructureCount,
+ const VkAccelerationStructureNV* pAccelerationStructures,
+ VkQueryType queryType,
+ VkQueryPool queryPool,
+ uint32_t firstQuery);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNV(
+ VkDevice device,
+ VkPipeline pipeline,
+ uint32_t shader);
+#endif
+
+
+#define VK_NV_representative_fragment_test 1
+#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 2
+#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test"
+typedef struct VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 representativeFragmentTest;
+} VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV;
+
+typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 representativeFragmentTestEnable;
+} VkPipelineRepresentativeFragmentTestStateCreateInfoNV;
+
+
+
+#define VK_EXT_filter_cubic 1
+#define VK_EXT_FILTER_CUBIC_SPEC_VERSION 3
+#define VK_EXT_FILTER_CUBIC_EXTENSION_NAME "VK_EXT_filter_cubic"
+typedef struct VkPhysicalDeviceImageViewImageFormatInfoEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkImageViewType imageViewType;
+} VkPhysicalDeviceImageViewImageFormatInfoEXT;
+
+typedef struct VkFilterCubicImageViewImageFormatPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 filterCubic;
+ VkBool32 filterCubicMinmax;
+} VkFilterCubicImageViewImageFormatPropertiesEXT;
+
+
+
+#define VK_EXT_global_priority 1
+#define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2
+#define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority"
+
+typedef enum VkQueueGlobalPriorityEXT {
+ VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT = 128,
+ VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT = 256,
+ VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT = 512,
+ VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = 1024,
+ VK_QUEUE_GLOBAL_PRIORITY_BEGIN_RANGE_EXT = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT,
+ VK_QUEUE_GLOBAL_PRIORITY_END_RANGE_EXT = VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT,
+ VK_QUEUE_GLOBAL_PRIORITY_RANGE_SIZE_EXT = (VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT - VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT + 1),
+ VK_QUEUE_GLOBAL_PRIORITY_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkQueueGlobalPriorityEXT;
+typedef struct VkDeviceQueueGlobalPriorityCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkQueueGlobalPriorityEXT globalPriority;
+} VkDeviceQueueGlobalPriorityCreateInfoEXT;
+
+
+
+#define VK_EXT_external_memory_host 1
+#define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1
+#define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host"
+typedef struct VkImportMemoryHostPointerInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+ void* pHostPointer;
+} VkImportMemoryHostPointerInfoEXT;
+
+typedef struct VkMemoryHostPointerPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t memoryTypeBits;
+} VkMemoryHostPointerPropertiesEXT;
+
+typedef struct VkPhysicalDeviceExternalMemoryHostPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkDeviceSize minImportedHostPointerAlignment;
+} VkPhysicalDeviceExternalMemoryHostPropertiesEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostPointerPropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBits handleType,
+ const void* pHostPointer,
+ VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties);
+#endif
+
+
+#define VK_AMD_buffer_marker 1
+#define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1
+#define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker"
+typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarkerAMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD(
+ VkCommandBuffer commandBuffer,
+ VkPipelineStageFlagBits pipelineStage,
+ VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ uint32_t marker);
+#endif
+
+
+#define VK_AMD_pipeline_compiler_control 1
+#define VK_AMD_PIPELINE_COMPILER_CONTROL_SPEC_VERSION 1
+#define VK_AMD_PIPELINE_COMPILER_CONTROL_EXTENSION_NAME "VK_AMD_pipeline_compiler_control"
+
+typedef enum VkPipelineCompilerControlFlagBitsAMD {
+ VK_PIPELINE_COMPILER_CONTROL_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF
+} VkPipelineCompilerControlFlagBitsAMD;
+typedef VkFlags VkPipelineCompilerControlFlagsAMD;
+typedef struct VkPipelineCompilerControlCreateInfoAMD {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCompilerControlFlagsAMD compilerControlFlags;
+} VkPipelineCompilerControlCreateInfoAMD;
+
+
+
+#define VK_EXT_calibrated_timestamps 1
+#define VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION 1
+#define VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME "VK_EXT_calibrated_timestamps"
+
+typedef enum VkTimeDomainEXT {
+ VK_TIME_DOMAIN_DEVICE_EXT = 0,
+ VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = 1,
+ VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = 2,
+ VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = 3,
+ VK_TIME_DOMAIN_BEGIN_RANGE_EXT = VK_TIME_DOMAIN_DEVICE_EXT,
+ VK_TIME_DOMAIN_END_RANGE_EXT = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT,
+ VK_TIME_DOMAIN_RANGE_SIZE_EXT = (VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT - VK_TIME_DOMAIN_DEVICE_EXT + 1),
+ VK_TIME_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkTimeDomainEXT;
+typedef struct VkCalibratedTimestampInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkTimeDomainEXT timeDomain;
+} VkCalibratedTimestampInfoEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)(VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainEXT* pTimeDomains);
+typedef VkResult (VKAPI_PTR *PFN_vkGetCalibratedTimestampsEXT)(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoEXT* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pTimeDomainCount,
+ VkTimeDomainEXT* pTimeDomains);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsEXT(
+ VkDevice device,
+ uint32_t timestampCount,
+ const VkCalibratedTimestampInfoEXT* pTimestampInfos,
+ uint64_t* pTimestamps,
+ uint64_t* pMaxDeviation);
+#endif
+
+
+#define VK_AMD_shader_core_properties 1
+#define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 2
+#define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties"
+typedef struct VkPhysicalDeviceShaderCorePropertiesAMD {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t shaderEngineCount;
+ uint32_t shaderArraysPerEngineCount;
+ uint32_t computeUnitsPerShaderArray;
+ uint32_t simdPerComputeUnit;
+ uint32_t wavefrontsPerSimd;
+ uint32_t wavefrontSize;
+ uint32_t sgprsPerSimd;
+ uint32_t minSgprAllocation;
+ uint32_t maxSgprAllocation;
+ uint32_t sgprAllocationGranularity;
+ uint32_t vgprsPerSimd;
+ uint32_t minVgprAllocation;
+ uint32_t maxVgprAllocation;
+ uint32_t vgprAllocationGranularity;
+} VkPhysicalDeviceShaderCorePropertiesAMD;
+
+
+
+#define VK_AMD_memory_overallocation_behavior 1
+#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1
+#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior"
+
+typedef enum VkMemoryOverallocationBehaviorAMD {
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_BEGIN_RANGE_AMD = VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_END_RANGE_AMD = VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD,
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_RANGE_SIZE_AMD = (VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD - VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD + 1),
+ VK_MEMORY_OVERALLOCATION_BEHAVIOR_MAX_ENUM_AMD = 0x7FFFFFFF
+} VkMemoryOverallocationBehaviorAMD;
+typedef struct VkDeviceMemoryOverallocationCreateInfoAMD {
+ VkStructureType sType;
+ const void* pNext;
+ VkMemoryOverallocationBehaviorAMD overallocationBehavior;
+} VkDeviceMemoryOverallocationCreateInfoAMD;
+
+
+
+#define VK_EXT_vertex_attribute_divisor 1
+#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3
+#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
+typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxVertexAttribDivisor;
+} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT;
+
+typedef struct VkVertexInputBindingDivisorDescriptionEXT {
+ uint32_t binding;
+ uint32_t divisor;
+} VkVertexInputBindingDivisorDescriptionEXT;
+
+typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t vertexBindingDivisorCount;
+ const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors;
+} VkPipelineVertexInputDivisorStateCreateInfoEXT;
+
+typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 vertexAttributeInstanceRateDivisor;
+ VkBool32 vertexAttributeInstanceRateZeroDivisor;
+} VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT;
+
+
+
+#define VK_EXT_pipeline_creation_feedback 1
+#define VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION 1
+#define VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME "VK_EXT_pipeline_creation_feedback"
+
+typedef enum VkPipelineCreationFeedbackFlagBitsEXT {
+ VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = 0x00000001,
+ VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = 0x00000002,
+ VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = 0x00000004,
+ VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkPipelineCreationFeedbackFlagBitsEXT;
+typedef VkFlags VkPipelineCreationFeedbackFlagsEXT;
+typedef struct VkPipelineCreationFeedbackEXT {
+ VkPipelineCreationFeedbackFlagsEXT flags;
+ uint64_t duration;
+} VkPipelineCreationFeedbackEXT;
+
+typedef struct VkPipelineCreationFeedbackCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCreationFeedbackEXT* pPipelineCreationFeedback;
+ uint32_t pipelineStageCreationFeedbackCount;
+ VkPipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks;
+} VkPipelineCreationFeedbackCreateInfoEXT;
+
+
+
+#define VK_NV_shader_subgroup_partitioned 1
+#define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
+#define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned"
+
+
+#define VK_NV_compute_shader_derivatives 1
+#define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1
+#define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives"
+typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 computeDerivativeGroupQuads;
+ VkBool32 computeDerivativeGroupLinear;
+} VkPhysicalDeviceComputeShaderDerivativesFeaturesNV;
+
+
+
+#define VK_NV_mesh_shader 1
+#define VK_NV_MESH_SHADER_SPEC_VERSION 1
+#define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader"
+typedef struct VkPhysicalDeviceMeshShaderFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 taskShader;
+ VkBool32 meshShader;
+} VkPhysicalDeviceMeshShaderFeaturesNV;
+
+typedef struct VkPhysicalDeviceMeshShaderPropertiesNV {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxDrawMeshTasksCount;
+ uint32_t maxTaskWorkGroupInvocations;
+ uint32_t maxTaskWorkGroupSize[3];
+ uint32_t maxTaskTotalMemorySize;
+ uint32_t maxTaskOutputCount;
+ uint32_t maxMeshWorkGroupInvocations;
+ uint32_t maxMeshWorkGroupSize[3];
+ uint32_t maxMeshTotalMemorySize;
+ uint32_t maxMeshOutputVertices;
+ uint32_t maxMeshOutputPrimitives;
+ uint32_t maxMeshMultiviewViewCount;
+ uint32_t meshOutputPerVertexGranularity;
+ uint32_t meshOutputPerPrimitiveGranularity;
+} VkPhysicalDeviceMeshShaderPropertiesNV;
+
+typedef struct VkDrawMeshTasksIndirectCommandNV {
+ uint32_t taskCount;
+ uint32_t firstTask;
+} VkDrawMeshTasksIndirectCommandNV;
+
+typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksNV)(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t taskCount,
+ uint32_t firstTask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ uint32_t drawCount,
+ uint32_t stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride);
+#endif
+
+
+#define VK_NV_fragment_shader_barycentric 1
+#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1
+#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric"
+typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 fragmentShaderBarycentric;
+} VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV;
+
+
+
+#define VK_NV_shader_image_footprint 1
+#define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 2
+#define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint"
+typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 imageFootprint;
+} VkPhysicalDeviceShaderImageFootprintFeaturesNV;
+
+
+
+#define VK_NV_scissor_exclusive 1
+#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1
+#define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive"
+typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t exclusiveScissorCount;
+ const VkRect2D* pExclusiveScissors;
+} VkPipelineViewportExclusiveScissorStateCreateInfoNV;
+
+typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 exclusiveScissor;
+} VkPhysicalDeviceExclusiveScissorFeaturesNV;
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstExclusiveScissor,
+ uint32_t exclusiveScissorCount,
+ const VkRect2D* pExclusiveScissors);
+#endif
+
+
+#define VK_NV_device_diagnostic_checkpoints 1
+#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2
+#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints"
+typedef struct VkQueueFamilyCheckpointPropertiesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkPipelineStageFlags checkpointExecutionStageMask;
+} VkQueueFamilyCheckpointPropertiesNV;
+
+typedef struct VkCheckpointDataNV {
+ VkStructureType sType;
+ void* pNext;
+ VkPipelineStageFlagBits stage;
+ void* pCheckpointMarker;
+} VkCheckpointDataNV;
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetCheckpointNV)(VkCommandBuffer commandBuffer, const void* pCheckpointMarker);
+typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointDataNV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetCheckpointNV(
+ VkCommandBuffer commandBuffer,
+ const void* pCheckpointMarker);
+
+VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointDataNV(
+ VkQueue queue,
+ uint32_t* pCheckpointDataCount,
+ VkCheckpointDataNV* pCheckpointData);
+#endif
+
+
+#define VK_INTEL_shader_integer_functions2 1
+#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_SPEC_VERSION 1
+#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME "VK_INTEL_shader_integer_functions2"
+typedef struct VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderIntegerFunctions2;
+} VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL;
+
+
+
+#define VK_INTEL_performance_query 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPerformanceConfigurationINTEL)
+#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 1
+#define VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME "VK_INTEL_performance_query"
+
+typedef enum VkPerformanceConfigurationTypeINTEL {
+ VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL = 0,
+ VK_PERFORMANCE_CONFIGURATION_TYPE_BEGIN_RANGE_INTEL = VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL,
+ VK_PERFORMANCE_CONFIGURATION_TYPE_END_RANGE_INTEL = VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL,
+ VK_PERFORMANCE_CONFIGURATION_TYPE_RANGE_SIZE_INTEL = (VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL - VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL + 1),
+ VK_PERFORMANCE_CONFIGURATION_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF
+} VkPerformanceConfigurationTypeINTEL;
+
+typedef enum VkQueryPoolSamplingModeINTEL {
+ VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL = 0,
+ VK_QUERY_POOL_SAMPLING_MODE_BEGIN_RANGE_INTEL = VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL,
+ VK_QUERY_POOL_SAMPLING_MODE_END_RANGE_INTEL = VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL,
+ VK_QUERY_POOL_SAMPLING_MODE_RANGE_SIZE_INTEL = (VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL - VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL + 1),
+ VK_QUERY_POOL_SAMPLING_MODE_MAX_ENUM_INTEL = 0x7FFFFFFF
+} VkQueryPoolSamplingModeINTEL;
+
+typedef enum VkPerformanceOverrideTypeINTEL {
+ VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL = 0,
+ VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL = 1,
+ VK_PERFORMANCE_OVERRIDE_TYPE_BEGIN_RANGE_INTEL = VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL,
+ VK_PERFORMANCE_OVERRIDE_TYPE_END_RANGE_INTEL = VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL,
+ VK_PERFORMANCE_OVERRIDE_TYPE_RANGE_SIZE_INTEL = (VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL - VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL + 1),
+ VK_PERFORMANCE_OVERRIDE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF
+} VkPerformanceOverrideTypeINTEL;
+
+typedef enum VkPerformanceParameterTypeINTEL {
+ VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL = 0,
+ VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL = 1,
+ VK_PERFORMANCE_PARAMETER_TYPE_BEGIN_RANGE_INTEL = VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL,
+ VK_PERFORMANCE_PARAMETER_TYPE_END_RANGE_INTEL = VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL,
+ VK_PERFORMANCE_PARAMETER_TYPE_RANGE_SIZE_INTEL = (VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL - VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL + 1),
+ VK_PERFORMANCE_PARAMETER_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF
+} VkPerformanceParameterTypeINTEL;
+
+typedef enum VkPerformanceValueTypeINTEL {
+ VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL = 0,
+ VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL = 1,
+ VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL = 2,
+ VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL = 3,
+ VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL = 4,
+ VK_PERFORMANCE_VALUE_TYPE_BEGIN_RANGE_INTEL = VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL,
+ VK_PERFORMANCE_VALUE_TYPE_END_RANGE_INTEL = VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL,
+ VK_PERFORMANCE_VALUE_TYPE_RANGE_SIZE_INTEL = (VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL - VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL + 1),
+ VK_PERFORMANCE_VALUE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF
+} VkPerformanceValueTypeINTEL;
+typedef union VkPerformanceValueDataINTEL {
+ uint32_t value32;
+ uint64_t value64;
+ float valueFloat;
+ VkBool32 valueBool;
+ const char* valueString;
+} VkPerformanceValueDataINTEL;
+
+typedef struct VkPerformanceValueINTEL {
+ VkPerformanceValueTypeINTEL type;
+ VkPerformanceValueDataINTEL data;
+} VkPerformanceValueINTEL;
+
+typedef struct VkInitializePerformanceApiInfoINTEL {
+ VkStructureType sType;
+ const void* pNext;
+ void* pUserData;
+} VkInitializePerformanceApiInfoINTEL;
+
+typedef struct VkQueryPoolCreateInfoINTEL {
+ VkStructureType sType;
+ const void* pNext;
+ VkQueryPoolSamplingModeINTEL performanceCountersSampling;
+} VkQueryPoolCreateInfoINTEL;
+
+typedef struct VkPerformanceMarkerInfoINTEL {
+ VkStructureType sType;
+ const void* pNext;
+ uint64_t marker;
+} VkPerformanceMarkerInfoINTEL;
+
+typedef struct VkPerformanceStreamMarkerInfoINTEL {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t marker;
+} VkPerformanceStreamMarkerInfoINTEL;
+
+typedef struct VkPerformanceOverrideInfoINTEL {
+ VkStructureType sType;
+ const void* pNext;
+ VkPerformanceOverrideTypeINTEL type;
+ VkBool32 enable;
+ uint64_t parameter;
+} VkPerformanceOverrideInfoINTEL;
+
+typedef struct VkPerformanceConfigurationAcquireInfoINTEL {
+ VkStructureType sType;
+ const void* pNext;
+ VkPerformanceConfigurationTypeINTEL type;
+} VkPerformanceConfigurationAcquireInfoINTEL;
+
+typedef VkResult (VKAPI_PTR *PFN_vkInitializePerformanceApiINTEL)(VkDevice device, const VkInitializePerformanceApiInfoINTEL* pInitializeInfo);
+typedef void (VKAPI_PTR *PFN_vkUninitializePerformanceApiINTEL)(VkDevice device);
+typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceMarkerInfoINTEL* pMarkerInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceStreamMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceOverrideINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceOverrideInfoINTEL* pOverrideInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkAcquirePerformanceConfigurationINTEL)(VkDevice device, const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VkPerformanceConfigurationINTEL* pConfiguration);
+typedef VkResult (VKAPI_PTR *PFN_vkReleasePerformanceConfigurationINTEL)(VkDevice device, VkPerformanceConfigurationINTEL configuration);
+typedef VkResult (VKAPI_PTR *PFN_vkQueueSetPerformanceConfigurationINTEL)(VkQueue queue, VkPerformanceConfigurationINTEL configuration);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPerformanceParameterINTEL)(VkDevice device, VkPerformanceParameterTypeINTEL parameter, VkPerformanceValueINTEL* pValue);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkInitializePerformanceApiINTEL(
+ VkDevice device,
+ const VkInitializePerformanceApiInfoINTEL* pInitializeInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkUninitializePerformanceApiINTEL(
+ VkDevice device);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceMarkerINTEL(
+ VkCommandBuffer commandBuffer,
+ const VkPerformanceMarkerInfoINTEL* pMarkerInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceStreamMarkerINTEL(
+ VkCommandBuffer commandBuffer,
+ const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceOverrideINTEL(
+ VkCommandBuffer commandBuffer,
+ const VkPerformanceOverrideInfoINTEL* pOverrideInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquirePerformanceConfigurationINTEL(
+ VkDevice device,
+ const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo,
+ VkPerformanceConfigurationINTEL* pConfiguration);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkReleasePerformanceConfigurationINTEL(
+ VkDevice device,
+ VkPerformanceConfigurationINTEL configuration);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkQueueSetPerformanceConfigurationINTEL(
+ VkQueue queue,
+ VkPerformanceConfigurationINTEL configuration);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPerformanceParameterINTEL(
+ VkDevice device,
+ VkPerformanceParameterTypeINTEL parameter,
+ VkPerformanceValueINTEL* pValue);
+#endif
+
+
+#define VK_EXT_pci_bus_info 1
+#define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2
+#define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info"
+typedef struct VkPhysicalDevicePCIBusInfoPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t pciDomain;
+ uint32_t pciBus;
+ uint32_t pciDevice;
+ uint32_t pciFunction;
+} VkPhysicalDevicePCIBusInfoPropertiesEXT;
+
+
+
+#define VK_AMD_display_native_hdr 1
+#define VK_AMD_DISPLAY_NATIVE_HDR_SPEC_VERSION 1
+#define VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME "VK_AMD_display_native_hdr"
+typedef struct VkDisplayNativeHdrSurfaceCapabilitiesAMD {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 localDimmingSupport;
+} VkDisplayNativeHdrSurfaceCapabilitiesAMD;
+
+typedef struct VkSwapchainDisplayNativeHdrCreateInfoAMD {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 localDimmingEnable;
+} VkSwapchainDisplayNativeHdrCreateInfoAMD;
+
+typedef void (VKAPI_PTR *PFN_vkSetLocalDimmingAMD)(VkDevice device, VkSwapchainKHR swapChain, VkBool32 localDimmingEnable);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkSetLocalDimmingAMD(
+ VkDevice device,
+ VkSwapchainKHR swapChain,
+ VkBool32 localDimmingEnable);
+#endif
+
+
+#define VK_EXT_fragment_density_map 1
+#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 1
+#define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map"
+typedef struct VkPhysicalDeviceFragmentDensityMapFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 fragmentDensityMap;
+ VkBool32 fragmentDensityMapDynamic;
+ VkBool32 fragmentDensityMapNonSubsampledImages;
+} VkPhysicalDeviceFragmentDensityMapFeaturesEXT;
+
+typedef struct VkPhysicalDeviceFragmentDensityMapPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkExtent2D minFragmentDensityTexelSize;
+ VkExtent2D maxFragmentDensityTexelSize;
+ VkBool32 fragmentDensityInvocations;
+} VkPhysicalDeviceFragmentDensityMapPropertiesEXT;
+
+typedef struct VkRenderPassFragmentDensityMapCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkAttachmentReference fragmentDensityMapAttachment;
+} VkRenderPassFragmentDensityMapCreateInfoEXT;
+
+
+
+#define VK_EXT_scalar_block_layout 1
+#define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1
+#define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout"
+typedef VkPhysicalDeviceScalarBlockLayoutFeatures VkPhysicalDeviceScalarBlockLayoutFeaturesEXT;
+
+
+
+#define VK_GOOGLE_hlsl_functionality1 1
+#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION 1
+#define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1"
+
+
+#define VK_GOOGLE_decorate_string 1
+#define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1
+#define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string"
+
+
+#define VK_EXT_subgroup_size_control 1
+#define VK_EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION 2
+#define VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME "VK_EXT_subgroup_size_control"
+typedef struct VkPhysicalDeviceSubgroupSizeControlFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 subgroupSizeControl;
+ VkBool32 computeFullSubgroups;
+} VkPhysicalDeviceSubgroupSizeControlFeaturesEXT;
+
+typedef struct VkPhysicalDeviceSubgroupSizeControlPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t minSubgroupSize;
+ uint32_t maxSubgroupSize;
+ uint32_t maxComputeWorkgroupSubgroups;
+ VkShaderStageFlags requiredSubgroupSizeStages;
+} VkPhysicalDeviceSubgroupSizeControlPropertiesEXT;
+
+typedef struct VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t requiredSubgroupSize;
+} VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT;
+
+
+
+#define VK_AMD_shader_core_properties2 1
+#define VK_AMD_SHADER_CORE_PROPERTIES_2_SPEC_VERSION 1
+#define VK_AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME "VK_AMD_shader_core_properties2"
+
+typedef enum VkShaderCorePropertiesFlagBitsAMD {
+ VK_SHADER_CORE_PROPERTIES_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF
+} VkShaderCorePropertiesFlagBitsAMD;
+typedef VkFlags VkShaderCorePropertiesFlagsAMD;
+typedef struct VkPhysicalDeviceShaderCoreProperties2AMD {
+ VkStructureType sType;
+ void* pNext;
+ VkShaderCorePropertiesFlagsAMD shaderCoreFeatures;
+ uint32_t activeComputeUnitCount;
+} VkPhysicalDeviceShaderCoreProperties2AMD;
+
+
+
+#define VK_AMD_device_coherent_memory 1
+#define VK_AMD_DEVICE_COHERENT_MEMORY_SPEC_VERSION 1
+#define VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME "VK_AMD_device_coherent_memory"
+typedef struct VkPhysicalDeviceCoherentMemoryFeaturesAMD {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 deviceCoherentMemory;
+} VkPhysicalDeviceCoherentMemoryFeaturesAMD;
+
+
+
+#define VK_EXT_memory_budget 1
+#define VK_EXT_MEMORY_BUDGET_SPEC_VERSION 1
+#define VK_EXT_MEMORY_BUDGET_EXTENSION_NAME "VK_EXT_memory_budget"
+typedef struct VkPhysicalDeviceMemoryBudgetPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkDeviceSize heapBudget[VK_MAX_MEMORY_HEAPS];
+ VkDeviceSize heapUsage[VK_MAX_MEMORY_HEAPS];
+} VkPhysicalDeviceMemoryBudgetPropertiesEXT;
+
+
+
+#define VK_EXT_memory_priority 1
+#define VK_EXT_MEMORY_PRIORITY_SPEC_VERSION 1
+#define VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME "VK_EXT_memory_priority"
+typedef struct VkPhysicalDeviceMemoryPriorityFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 memoryPriority;
+} VkPhysicalDeviceMemoryPriorityFeaturesEXT;
+
+typedef struct VkMemoryPriorityAllocateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ float priority;
+} VkMemoryPriorityAllocateInfoEXT;
+
+
+
+#define VK_NV_dedicated_allocation_image_aliasing 1
+#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_SPEC_VERSION 1
+#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME "VK_NV_dedicated_allocation_image_aliasing"
+typedef struct VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 dedicatedAllocationImageAliasing;
+} VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV;
+
+
+
+#define VK_EXT_buffer_device_address 1
+#define VK_EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 2
+#define VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_EXT_buffer_device_address"
+typedef struct VkPhysicalDeviceBufferDeviceAddressFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 bufferDeviceAddress;
+ VkBool32 bufferDeviceAddressCaptureReplay;
+ VkBool32 bufferDeviceAddressMultiDevice;
+} VkPhysicalDeviceBufferDeviceAddressFeaturesEXT;
+
+typedef VkPhysicalDeviceBufferDeviceAddressFeaturesEXT VkPhysicalDeviceBufferAddressFeaturesEXT;
+
+typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoEXT;
+
+typedef struct VkBufferDeviceAddressCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceAddress deviceAddress;
+} VkBufferDeviceAddressCreateInfoEXT;
+
+typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressEXT)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressEXT(
+ VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo);
+#endif
+
+
+#define VK_EXT_tooling_info 1
+#define VK_EXT_TOOLING_INFO_SPEC_VERSION 1
+#define VK_EXT_TOOLING_INFO_EXTENSION_NAME "VK_EXT_tooling_info"
+
+typedef enum VkToolPurposeFlagBitsEXT {
+ VK_TOOL_PURPOSE_VALIDATION_BIT_EXT = 0x00000001,
+ VK_TOOL_PURPOSE_PROFILING_BIT_EXT = 0x00000002,
+ VK_TOOL_PURPOSE_TRACING_BIT_EXT = 0x00000004,
+ VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT = 0x00000008,
+ VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT = 0x00000010,
+ VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT = 0x00000020,
+ VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT = 0x00000040,
+ VK_TOOL_PURPOSE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkToolPurposeFlagBitsEXT;
+typedef VkFlags VkToolPurposeFlagsEXT;
+typedef struct VkPhysicalDeviceToolPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ char name[VK_MAX_EXTENSION_NAME_SIZE];
+ char version[VK_MAX_EXTENSION_NAME_SIZE];
+ VkToolPurposeFlagsEXT purposes;
+ char description[VK_MAX_DESCRIPTION_SIZE];
+ char layer[VK_MAX_EXTENSION_NAME_SIZE];
+} VkPhysicalDeviceToolPropertiesEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolPropertiesEXT)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolPropertiesEXT* pToolProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolPropertiesEXT(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pToolCount,
+ VkPhysicalDeviceToolPropertiesEXT* pToolProperties);
+#endif
+
+
+#define VK_EXT_separate_stencil_usage 1
+#define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1
+#define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage"
+typedef VkImageStencilUsageCreateInfo VkImageStencilUsageCreateInfoEXT;
+
+
+
+#define VK_EXT_validation_features 1
+#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 2
+#define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features"
+
+typedef enum VkValidationFeatureEnableEXT {
+ VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0,
+ VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1,
+ VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2,
+ VK_VALIDATION_FEATURE_ENABLE_BEGIN_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
+ VK_VALIDATION_FEATURE_ENABLE_END_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
+ VK_VALIDATION_FEATURE_ENABLE_RANGE_SIZE_EXT = (VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT + 1),
+ VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkValidationFeatureEnableEXT;
+
+typedef enum VkValidationFeatureDisableEXT {
+ VK_VALIDATION_FEATURE_DISABLE_ALL_EXT = 0,
+ VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT = 1,
+ VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT = 2,
+ VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT = 3,
+ VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4,
+ VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5,
+ VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6,
+ VK_VALIDATION_FEATURE_DISABLE_BEGIN_RANGE_EXT = VK_VALIDATION_FEATURE_DISABLE_ALL_EXT,
+ VK_VALIDATION_FEATURE_DISABLE_END_RANGE_EXT = VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT,
+ VK_VALIDATION_FEATURE_DISABLE_RANGE_SIZE_EXT = (VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT - VK_VALIDATION_FEATURE_DISABLE_ALL_EXT + 1),
+ VK_VALIDATION_FEATURE_DISABLE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkValidationFeatureDisableEXT;
+typedef struct VkValidationFeaturesEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t enabledValidationFeatureCount;
+ const VkValidationFeatureEnableEXT* pEnabledValidationFeatures;
+ uint32_t disabledValidationFeatureCount;
+ const VkValidationFeatureDisableEXT* pDisabledValidationFeatures;
+} VkValidationFeaturesEXT;
+
+
+
+#define VK_NV_cooperative_matrix 1
+#define VK_NV_COOPERATIVE_MATRIX_SPEC_VERSION 1
+#define VK_NV_COOPERATIVE_MATRIX_EXTENSION_NAME "VK_NV_cooperative_matrix"
+
+typedef enum VkComponentTypeNV {
+ VK_COMPONENT_TYPE_FLOAT16_NV = 0,
+ VK_COMPONENT_TYPE_FLOAT32_NV = 1,
+ VK_COMPONENT_TYPE_FLOAT64_NV = 2,
+ VK_COMPONENT_TYPE_SINT8_NV = 3,
+ VK_COMPONENT_TYPE_SINT16_NV = 4,
+ VK_COMPONENT_TYPE_SINT32_NV = 5,
+ VK_COMPONENT_TYPE_SINT64_NV = 6,
+ VK_COMPONENT_TYPE_UINT8_NV = 7,
+ VK_COMPONENT_TYPE_UINT16_NV = 8,
+ VK_COMPONENT_TYPE_UINT32_NV = 9,
+ VK_COMPONENT_TYPE_UINT64_NV = 10,
+ VK_COMPONENT_TYPE_BEGIN_RANGE_NV = VK_COMPONENT_TYPE_FLOAT16_NV,
+ VK_COMPONENT_TYPE_END_RANGE_NV = VK_COMPONENT_TYPE_UINT64_NV,
+ VK_COMPONENT_TYPE_RANGE_SIZE_NV = (VK_COMPONENT_TYPE_UINT64_NV - VK_COMPONENT_TYPE_FLOAT16_NV + 1),
+ VK_COMPONENT_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkComponentTypeNV;
+
+typedef enum VkScopeNV {
+ VK_SCOPE_DEVICE_NV = 1,
+ VK_SCOPE_WORKGROUP_NV = 2,
+ VK_SCOPE_SUBGROUP_NV = 3,
+ VK_SCOPE_QUEUE_FAMILY_NV = 5,
+ VK_SCOPE_BEGIN_RANGE_NV = VK_SCOPE_DEVICE_NV,
+ VK_SCOPE_END_RANGE_NV = VK_SCOPE_QUEUE_FAMILY_NV,
+ VK_SCOPE_RANGE_SIZE_NV = (VK_SCOPE_QUEUE_FAMILY_NV - VK_SCOPE_DEVICE_NV + 1),
+ VK_SCOPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkScopeNV;
+typedef struct VkCooperativeMatrixPropertiesNV {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t MSize;
+ uint32_t NSize;
+ uint32_t KSize;
+ VkComponentTypeNV AType;
+ VkComponentTypeNV BType;
+ VkComponentTypeNV CType;
+ VkComponentTypeNV DType;
+ VkScopeNV scope;
+} VkCooperativeMatrixPropertiesNV;
+
+typedef struct VkPhysicalDeviceCooperativeMatrixFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 cooperativeMatrix;
+ VkBool32 cooperativeMatrixRobustBufferAccess;
+} VkPhysicalDeviceCooperativeMatrixFeaturesNV;
+
+typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkShaderStageFlags cooperativeMatrixSupportedStages;
+} VkPhysicalDeviceCooperativeMatrixPropertiesNV;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesNV* pProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesNV(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkCooperativeMatrixPropertiesNV* pProperties);
+#endif
+
+
+#define VK_NV_coverage_reduction_mode 1
+#define VK_NV_COVERAGE_REDUCTION_MODE_SPEC_VERSION 1
+#define VK_NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME "VK_NV_coverage_reduction_mode"
+
+typedef enum VkCoverageReductionModeNV {
+ VK_COVERAGE_REDUCTION_MODE_MERGE_NV = 0,
+ VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV = 1,
+ VK_COVERAGE_REDUCTION_MODE_BEGIN_RANGE_NV = VK_COVERAGE_REDUCTION_MODE_MERGE_NV,
+ VK_COVERAGE_REDUCTION_MODE_END_RANGE_NV = VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV,
+ VK_COVERAGE_REDUCTION_MODE_RANGE_SIZE_NV = (VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV - VK_COVERAGE_REDUCTION_MODE_MERGE_NV + 1),
+ VK_COVERAGE_REDUCTION_MODE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkCoverageReductionModeNV;
+typedef VkFlags VkPipelineCoverageReductionStateCreateFlagsNV;
+typedef struct VkPhysicalDeviceCoverageReductionModeFeaturesNV {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 coverageReductionMode;
+} VkPhysicalDeviceCoverageReductionModeFeaturesNV;
+
+typedef struct VkPipelineCoverageReductionStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineCoverageReductionStateCreateFlagsNV flags;
+ VkCoverageReductionModeNV coverageReductionMode;
+} VkPipelineCoverageReductionStateCreateInfoNV;
+
+typedef struct VkFramebufferMixedSamplesCombinationNV {
+ VkStructureType sType;
+ void* pNext;
+ VkCoverageReductionModeNV coverageReductionMode;
+ VkSampleCountFlagBits rasterizationSamples;
+ VkSampleCountFlags depthStencilSamples;
+ VkSampleCountFlags colorSamples;
+} VkFramebufferMixedSamplesCombinationNV;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)(VkPhysicalDevice physicalDevice, uint32_t* pCombinationCount, VkFramebufferMixedSamplesCombinationNV* pCombinations);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pCombinationCount,
+ VkFramebufferMixedSamplesCombinationNV* pCombinations);
+#endif
+
+
+#define VK_EXT_fragment_shader_interlock 1
+#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION 1
+#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME "VK_EXT_fragment_shader_interlock"
+typedef struct VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 fragmentShaderSampleInterlock;
+ VkBool32 fragmentShaderPixelInterlock;
+ VkBool32 fragmentShaderShadingRateInterlock;
+} VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT;
+
+
+
+#define VK_EXT_ycbcr_image_arrays 1
+#define VK_EXT_YCBCR_IMAGE_ARRAYS_SPEC_VERSION 1
+#define VK_EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME "VK_EXT_ycbcr_image_arrays"
+typedef struct VkPhysicalDeviceYcbcrImageArraysFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 ycbcrImageArrays;
+} VkPhysicalDeviceYcbcrImageArraysFeaturesEXT;
+
+
+
+#define VK_EXT_headless_surface 1
+#define VK_EXT_HEADLESS_SURFACE_SPEC_VERSION 1
+#define VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME "VK_EXT_headless_surface"
+typedef VkFlags VkHeadlessSurfaceCreateFlagsEXT;
+typedef struct VkHeadlessSurfaceCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkHeadlessSurfaceCreateFlagsEXT flags;
+} VkHeadlessSurfaceCreateInfoEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT(
+ VkInstance instance,
+ const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+
+
+#define VK_EXT_line_rasterization 1
+#define VK_EXT_LINE_RASTERIZATION_SPEC_VERSION 1
+#define VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME "VK_EXT_line_rasterization"
+
+typedef enum VkLineRasterizationModeEXT {
+ VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT = 0,
+ VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT = 1,
+ VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT = 2,
+ VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT = 3,
+ VK_LINE_RASTERIZATION_MODE_BEGIN_RANGE_EXT = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT,
+ VK_LINE_RASTERIZATION_MODE_END_RANGE_EXT = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT,
+ VK_LINE_RASTERIZATION_MODE_RANGE_SIZE_EXT = (VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT - VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT + 1),
+ VK_LINE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkLineRasterizationModeEXT;
+typedef struct VkPhysicalDeviceLineRasterizationFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 rectangularLines;
+ VkBool32 bresenhamLines;
+ VkBool32 smoothLines;
+ VkBool32 stippledRectangularLines;
+ VkBool32 stippledBresenhamLines;
+ VkBool32 stippledSmoothLines;
+} VkPhysicalDeviceLineRasterizationFeaturesEXT;
+
+typedef struct VkPhysicalDeviceLineRasterizationPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t lineSubPixelPrecisionBits;
+} VkPhysicalDeviceLineRasterizationPropertiesEXT;
+
+typedef struct VkPipelineRasterizationLineStateCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkLineRasterizationModeEXT lineRasterizationMode;
+ VkBool32 stippledLineEnable;
+ uint32_t lineStippleFactor;
+ uint16_t lineStipplePattern;
+} VkPipelineRasterizationLineStateCreateInfoEXT;
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleEXT)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t lineStippleFactor,
+ uint16_t lineStipplePattern);
+#endif
+
+
+#define VK_EXT_host_query_reset 1
+#define VK_EXT_HOST_QUERY_RESET_SPEC_VERSION 1
+#define VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME "VK_EXT_host_query_reset"
+typedef VkPhysicalDeviceHostQueryResetFeatures VkPhysicalDeviceHostQueryResetFeaturesEXT;
+
+typedef void (VKAPI_PTR *PFN_vkResetQueryPoolEXT)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkResetQueryPoolEXT(
+ VkDevice device,
+ VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount);
+#endif
+
+
+#define VK_EXT_index_type_uint8 1
+#define VK_EXT_INDEX_TYPE_UINT8_SPEC_VERSION 1
+#define VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME "VK_EXT_index_type_uint8"
+typedef struct VkPhysicalDeviceIndexTypeUint8FeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 indexTypeUint8;
+} VkPhysicalDeviceIndexTypeUint8FeaturesEXT;
+
+
+
+#define VK_EXT_shader_demote_to_helper_invocation 1
+#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION 1
+#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME "VK_EXT_shader_demote_to_helper_invocation"
+typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderDemoteToHelperInvocation;
+} VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT;
+
+
+
+#define VK_EXT_texel_buffer_alignment 1
+#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1
+#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment"
+typedef struct VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 texelBufferAlignment;
+} VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT;
+
+typedef struct VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkDeviceSize storageTexelBufferOffsetAlignmentBytes;
+ VkBool32 storageTexelBufferOffsetSingleTexelAlignment;
+ VkDeviceSize uniformTexelBufferOffsetAlignmentBytes;
+ VkBool32 uniformTexelBufferOffsetSingleTexelAlignment;
+} VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT;
+
+
+
+#define VK_GOOGLE_user_type 1
+#define VK_GOOGLE_USER_TYPE_SPEC_VERSION 1
+#define VK_GOOGLE_USER_TYPE_EXTENSION_NAME "VK_GOOGLE_user_type"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_fuchsia.h b/thirdparty/vulkan/include/vulkan/vulkan_fuchsia.h
new file mode 100644
index 0000000000..81ebe55d31
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_fuchsia.h
@@ -0,0 +1,57 @@
+#ifndef VULKAN_FUCHSIA_H_
+#define VULKAN_FUCHSIA_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_FUCHSIA_imagepipe_surface 1
+#define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1
+#define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface"
+typedef VkFlags VkImagePipeSurfaceCreateFlagsFUCHSIA;
+typedef struct VkImagePipeSurfaceCreateInfoFUCHSIA {
+ VkStructureType sType;
+ const void* pNext;
+ VkImagePipeSurfaceCreateFlagsFUCHSIA flags;
+ zx_handle_t imagePipeHandle;
+} VkImagePipeSurfaceCreateInfoFUCHSIA;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateImagePipeSurfaceFUCHSIA)(VkInstance instance, const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateImagePipeSurfaceFUCHSIA(
+ VkInstance instance,
+ const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_ggp.h b/thirdparty/vulkan/include/vulkan/vulkan_ggp.h
new file mode 100644
index 0000000000..fd306131c3
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_ggp.h
@@ -0,0 +1,68 @@
+#ifndef VULKAN_GGP_H_
+#define VULKAN_GGP_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_GGP_stream_descriptor_surface 1
+#define VK_GGP_STREAM_DESCRIPTOR_SURFACE_SPEC_VERSION 1
+#define VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME "VK_GGP_stream_descriptor_surface"
+typedef VkFlags VkStreamDescriptorSurfaceCreateFlagsGGP;
+typedef struct VkStreamDescriptorSurfaceCreateInfoGGP {
+ VkStructureType sType;
+ const void* pNext;
+ VkStreamDescriptorSurfaceCreateFlagsGGP flags;
+ GgpStreamDescriptor streamDescriptor;
+} VkStreamDescriptorSurfaceCreateInfoGGP;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateStreamDescriptorSurfaceGGP)(VkInstance instance, const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateStreamDescriptorSurfaceGGP(
+ VkInstance instance,
+ const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+
+
+#define VK_GGP_frame_token 1
+#define VK_GGP_FRAME_TOKEN_SPEC_VERSION 1
+#define VK_GGP_FRAME_TOKEN_EXTENSION_NAME "VK_GGP_frame_token"
+typedef struct VkPresentFrameTokenGGP {
+ VkStructureType sType;
+ const void* pNext;
+ GgpFrameToken frameToken;
+} VkPresentFrameTokenGGP;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_ios.h b/thirdparty/vulkan/include/vulkan/vulkan_ios.h
new file mode 100644
index 0000000000..72ef1a8a82
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_ios.h
@@ -0,0 +1,57 @@
+#ifndef VULKAN_IOS_H_
+#define VULKAN_IOS_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_MVK_ios_surface 1
+#define VK_MVK_IOS_SURFACE_SPEC_VERSION 2
+#define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface"
+typedef VkFlags VkIOSSurfaceCreateFlagsMVK;
+typedef struct VkIOSSurfaceCreateInfoMVK {
+ VkStructureType sType;
+ const void* pNext;
+ VkIOSSurfaceCreateFlagsMVK flags;
+ const void* pView;
+} VkIOSSurfaceCreateInfoMVK;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateIOSSurfaceMVK)(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK(
+ VkInstance instance,
+ const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_macos.h b/thirdparty/vulkan/include/vulkan/vulkan_macos.h
new file mode 100644
index 0000000000..e6e5deaa36
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_macos.h
@@ -0,0 +1,57 @@
+#ifndef VULKAN_MACOS_H_
+#define VULKAN_MACOS_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_MVK_macos_surface 1
+#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 2
+#define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface"
+typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
+typedef struct VkMacOSSurfaceCreateInfoMVK {
+ VkStructureType sType;
+ const void* pNext;
+ VkMacOSSurfaceCreateFlagsMVK flags;
+ const void* pView;
+} VkMacOSSurfaceCreateInfoMVK;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateMacOSSurfaceMVK)(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(
+ VkInstance instance,
+ const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_metal.h b/thirdparty/vulkan/include/vulkan/vulkan_metal.h
new file mode 100644
index 0000000000..3dec68c771
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_metal.h
@@ -0,0 +1,64 @@
+#ifndef VULKAN_METAL_H_
+#define VULKAN_METAL_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_EXT_metal_surface 1
+
+#ifdef __OBJC__
+@class CAMetalLayer;
+#else
+typedef void CAMetalLayer;
+#endif
+
+#define VK_EXT_METAL_SURFACE_SPEC_VERSION 1
+#define VK_EXT_METAL_SURFACE_EXTENSION_NAME "VK_EXT_metal_surface"
+typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
+typedef struct VkMetalSurfaceCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkMetalSurfaceCreateFlagsEXT flags;
+ const CAMetalLayer* pLayer;
+} VkMetalSurfaceCreateInfoEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateMetalSurfaceEXT)(VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT(
+ VkInstance instance,
+ const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_vi.h b/thirdparty/vulkan/include/vulkan/vulkan_vi.h
new file mode 100644
index 0000000000..6fb66f9dd2
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_vi.h
@@ -0,0 +1,57 @@
+#ifndef VULKAN_VI_H_
+#define VULKAN_VI_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_NN_vi_surface 1
+#define VK_NN_VI_SURFACE_SPEC_VERSION 1
+#define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface"
+typedef VkFlags VkViSurfaceCreateFlagsNN;
+typedef struct VkViSurfaceCreateInfoNN {
+ VkStructureType sType;
+ const void* pNext;
+ VkViSurfaceCreateFlagsNN flags;
+ void* window;
+} VkViSurfaceCreateInfoNN;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateViSurfaceNN)(VkInstance instance, const VkViSurfaceCreateInfoNN* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN(
+ VkInstance instance,
+ const VkViSurfaceCreateInfoNN* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_wayland.h b/thirdparty/vulkan/include/vulkan/vulkan_wayland.h
new file mode 100644
index 0000000000..599d05b24a
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_wayland.h
@@ -0,0 +1,64 @@
+#ifndef VULKAN_WAYLAND_H_
+#define VULKAN_WAYLAND_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_KHR_wayland_surface 1
+#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6
+#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface"
+typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
+typedef struct VkWaylandSurfaceCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkWaylandSurfaceCreateFlagsKHR flags;
+ struct wl_display* display;
+ struct wl_surface* surface;
+} VkWaylandSurfaceCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateWaylandSurfaceKHR)(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
+ VkInstance instance,
+ const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ struct wl_display* display);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_win32.h b/thirdparty/vulkan/include/vulkan/vulkan_win32.h
new file mode 100644
index 0000000000..20a1dc0e58
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_win32.h
@@ -0,0 +1,328 @@
+#ifndef VULKAN_WIN32_H_
+#define VULKAN_WIN32_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_KHR_win32_surface 1
+#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6
+#define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface"
+typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
+typedef struct VkWin32SurfaceCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkWin32SurfaceCreateFlagsKHR flags;
+ HINSTANCE hinstance;
+ HWND hwnd;
+} VkWin32SurfaceCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
+ VkInstance instance,
+ const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex);
+#endif
+
+
+#define VK_KHR_external_memory_win32 1
+#define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32"
+typedef struct VkImportMemoryWin32HandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+ HANDLE handle;
+ LPCWSTR name;
+} VkImportMemoryWin32HandleInfoKHR;
+
+typedef struct VkExportMemoryWin32HandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ const SECURITY_ATTRIBUTES* pAttributes;
+ DWORD dwAccess;
+ LPCWSTR name;
+} VkExportMemoryWin32HandleInfoKHR;
+
+typedef struct VkMemoryWin32HandlePropertiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t memoryTypeBits;
+} VkMemoryWin32HandlePropertiesKHR;
+
+typedef struct VkMemoryGetWin32HandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceMemory memory;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+} VkMemoryGetWin32HandleInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR(
+ VkDevice device,
+ const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo,
+ HANDLE* pHandle);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBits handleType,
+ HANDLE handle,
+ VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
+#endif
+
+
+#define VK_KHR_win32_keyed_mutex 1
+#define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1
+#define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex"
+typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t acquireCount;
+ const VkDeviceMemory* pAcquireSyncs;
+ const uint64_t* pAcquireKeys;
+ const uint32_t* pAcquireTimeouts;
+ uint32_t releaseCount;
+ const VkDeviceMemory* pReleaseSyncs;
+ const uint64_t* pReleaseKeys;
+} VkWin32KeyedMutexAcquireReleaseInfoKHR;
+
+
+
+#define VK_KHR_external_semaphore_win32 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32"
+typedef struct VkImportSemaphoreWin32HandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkSemaphoreImportFlags flags;
+ VkExternalSemaphoreHandleTypeFlagBits handleType;
+ HANDLE handle;
+ LPCWSTR name;
+} VkImportSemaphoreWin32HandleInfoKHR;
+
+typedef struct VkExportSemaphoreWin32HandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ const SECURITY_ATTRIBUTES* pAttributes;
+ DWORD dwAccess;
+ LPCWSTR name;
+} VkExportSemaphoreWin32HandleInfoKHR;
+
+typedef struct VkD3D12FenceSubmitInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t waitSemaphoreValuesCount;
+ const uint64_t* pWaitSemaphoreValues;
+ uint32_t signalSemaphoreValuesCount;
+ const uint64_t* pSignalSemaphoreValues;
+} VkD3D12FenceSubmitInfoKHR;
+
+typedef struct VkSemaphoreGetWin32HandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkExternalSemaphoreHandleTypeFlagBits handleType;
+} VkSemaphoreGetWin32HandleInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHR(
+ VkDevice device,
+ const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR(
+ VkDevice device,
+ const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo,
+ HANDLE* pHandle);
+#endif
+
+
+#define VK_KHR_external_fence_win32 1
+#define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32"
+typedef struct VkImportFenceWin32HandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkFence fence;
+ VkFenceImportFlags flags;
+ VkExternalFenceHandleTypeFlagBits handleType;
+ HANDLE handle;
+ LPCWSTR name;
+} VkImportFenceWin32HandleInfoKHR;
+
+typedef struct VkExportFenceWin32HandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ const SECURITY_ATTRIBUTES* pAttributes;
+ DWORD dwAccess;
+ LPCWSTR name;
+} VkExportFenceWin32HandleInfoKHR;
+
+typedef struct VkFenceGetWin32HandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkFence fence;
+ VkExternalFenceHandleTypeFlagBits handleType;
+} VkFenceGetWin32HandleInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceWin32HandleKHR(
+ VkDevice device,
+ const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR(
+ VkDevice device,
+ const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo,
+ HANDLE* pHandle);
+#endif
+
+
+#define VK_NV_external_memory_win32 1
+#define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
+#define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32"
+typedef struct VkImportMemoryWin32HandleInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagsNV handleType;
+ HANDLE handle;
+} VkImportMemoryWin32HandleInfoNV;
+
+typedef struct VkExportMemoryWin32HandleInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ const SECURITY_ATTRIBUTES* pAttributes;
+ DWORD dwAccess;
+} VkExportMemoryWin32HandleInfoNV;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV(
+ VkDevice device,
+ VkDeviceMemory memory,
+ VkExternalMemoryHandleTypeFlagsNV handleType,
+ HANDLE* pHandle);
+#endif
+
+
+#define VK_NV_win32_keyed_mutex 1
+#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 2
+#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex"
+typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t acquireCount;
+ const VkDeviceMemory* pAcquireSyncs;
+ const uint64_t* pAcquireKeys;
+ const uint32_t* pAcquireTimeoutMilliseconds;
+ uint32_t releaseCount;
+ const VkDeviceMemory* pReleaseSyncs;
+ const uint64_t* pReleaseKeys;
+} VkWin32KeyedMutexAcquireReleaseInfoNV;
+
+
+
+#define VK_EXT_full_screen_exclusive 1
+#define VK_EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION 4
+#define VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME "VK_EXT_full_screen_exclusive"
+
+typedef enum VkFullScreenExclusiveEXT {
+ VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT = 0,
+ VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT = 1,
+ VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT = 2,
+ VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT = 3,
+ VK_FULL_SCREEN_EXCLUSIVE_BEGIN_RANGE_EXT = VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT,
+ VK_FULL_SCREEN_EXCLUSIVE_END_RANGE_EXT = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT,
+ VK_FULL_SCREEN_EXCLUSIVE_RANGE_SIZE_EXT = (VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT - VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT + 1),
+ VK_FULL_SCREEN_EXCLUSIVE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkFullScreenExclusiveEXT;
+typedef struct VkSurfaceFullScreenExclusiveInfoEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkFullScreenExclusiveEXT fullScreenExclusive;
+} VkSurfaceFullScreenExclusiveInfoEXT;
+
+typedef struct VkSurfaceCapabilitiesFullScreenExclusiveEXT {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 fullScreenExclusiveSupported;
+} VkSurfaceCapabilitiesFullScreenExclusiveEXT;
+
+typedef struct VkSurfaceFullScreenExclusiveWin32InfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ HMONITOR hmonitor;
+} VkSurfaceFullScreenExclusiveWin32InfoEXT;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes);
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain);
+typedef VkResult (VKAPI_PTR *PFN_vkReleaseFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModes2EXT)(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModes2EXT(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pPresentModeCount,
+ VkPresentModeKHR* pPresentModes);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireFullScreenExclusiveModeEXT(
+ VkDevice device,
+ VkSwapchainKHR swapchain);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkReleaseFullScreenExclusiveModeEXT(
+ VkDevice device,
+ VkSwapchainKHR swapchain);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModes2EXT(
+ VkDevice device,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkDeviceGroupPresentModeFlagsKHR* pModes);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_xcb.h b/thirdparty/vulkan/include/vulkan/vulkan_xcb.h
new file mode 100644
index 0000000000..4cc0bc0cec
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_xcb.h
@@ -0,0 +1,65 @@
+#ifndef VULKAN_XCB_H_
+#define VULKAN_XCB_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_KHR_xcb_surface 1
+#define VK_KHR_XCB_SURFACE_SPEC_VERSION 6
+#define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface"
+typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
+typedef struct VkXcbSurfaceCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkXcbSurfaceCreateFlagsKHR flags;
+ xcb_connection_t* connection;
+ xcb_window_t window;
+} VkXcbSurfaceCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
+ VkInstance instance,
+ const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ xcb_connection_t* connection,
+ xcb_visualid_t visual_id);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_xlib.h b/thirdparty/vulkan/include/vulkan/vulkan_xlib.h
new file mode 100644
index 0000000000..ee2b48accb
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_xlib.h
@@ -0,0 +1,65 @@
+#ifndef VULKAN_XLIB_H_
+#define VULKAN_XLIB_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_KHR_xlib_surface 1
+#define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6
+#define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface"
+typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
+typedef struct VkXlibSurfaceCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkXlibSurfaceCreateFlagsKHR flags;
+ Display* dpy;
+ Window window;
+} VkXlibSurfaceCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
+ VkInstance instance,
+ const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ Display* dpy,
+ VisualID visualID);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/include/vulkan/vulkan_xlib_xrandr.h b/thirdparty/vulkan/include/vulkan/vulkan_xlib_xrandr.h
new file mode 100644
index 0000000000..08c4fd729c
--- /dev/null
+++ b/thirdparty/vulkan/include/vulkan/vulkan_xlib_xrandr.h
@@ -0,0 +1,55 @@
+#ifndef VULKAN_XLIB_XRANDR_H_
+#define VULKAN_XLIB_XRANDR_H_ 1
+
+/*
+** Copyright (c) 2015-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_EXT_acquire_xlib_display 1
+#define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1
+#define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display"
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireXlibDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display);
+typedef VkResult (VKAPI_PTR *PFN_vkGetRandROutputDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput, VkDisplayKHR* pDisplay);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireXlibDisplayEXT(
+ VkPhysicalDevice physicalDevice,
+ Display* dpy,
+ VkDisplayKHR display);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRandROutputDisplayEXT(
+ VkPhysicalDevice physicalDevice,
+ Display* dpy,
+ RROutput rrOutput,
+ VkDisplayKHR* pDisplay);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/loader/adapters.h b/thirdparty/vulkan/loader/adapters.h
new file mode 100644
index 0000000000..ef97d66573
--- /dev/null
+++ b/thirdparty/vulkan/loader/adapters.h
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2019 The Khronos Group Inc.
+* Copyright (c) 2019 Valve Corporation
+* Copyright (c) 2019 LunarG, Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+* Author: Lenny Komow <lenny@lunarg.com>
+*/
+
+typedef struct LoaderEnumAdapters2 {
+ ULONG adapter_count;
+ struct {
+ UINT handle;
+ LUID luid;
+ ULONG source_count;
+ BOOL present_move_regions_preferred;
+ } * adapters;
+} LoaderEnumAdapters2;
+
+typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderEnumAdapters2)(const LoaderEnumAdapters2 *);
+
+typedef enum AdapterInfoType {
+ LOADER_QUERY_TYPE_REGISTRY = 48,
+} AdapterInfoType;
+
+typedef struct LoaderQueryAdapterInfo {
+ UINT handle;
+ AdapterInfoType type;
+ VOID *private_data;
+ UINT private_data_size;
+} LoaderQueryAdapterInfo;
+
+typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderQueryAdapterInfo)(const LoaderQueryAdapterInfo *);
+
+typedef enum LoaderQueryRegistryType {
+ LOADER_QUERY_REGISTRY_ADAPTER_KEY = 1,
+} LoaderQueryRegistryType;
+
+typedef enum LoaderQueryRegistryStatus {
+ LOADER_QUERY_REGISTRY_STATUS_SUCCESS = 0,
+ LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW = 1,
+} LoaderQueryRegistryStatus;
+
+typedef struct LoaderQueryRegistryFlags {
+ union {
+ struct {
+ UINT translate_path : 1;
+ UINT mutable_value : 1;
+ UINT reserved : 30;
+ };
+ UINT value;
+ };
+} LoaderQueryRegistryFlags;
+
+typedef struct LoaderQueryRegistryInfo {
+ LoaderQueryRegistryType query_type;
+ LoaderQueryRegistryFlags query_flags;
+ WCHAR value_name[MAX_PATH];
+ ULONG value_type;
+ ULONG physical_adapter_index;
+ ULONG output_value_size;
+ LoaderQueryRegistryStatus status;
+ union {
+ DWORD output_dword;
+ UINT64 output_qword;
+ WCHAR output_string[1];
+ BYTE output_binary[1];
+ };
+} LoaderQueryRegistryInfo;
diff --git a/thirdparty/vulkan/loader/asm_offset.c b/thirdparty/vulkan/loader/asm_offset.c
new file mode 100644
index 0000000000..97832afa03
--- /dev/null
+++ b/thirdparty/vulkan/loader/asm_offset.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017-2018 The Khronos Group Inc.
+ * Copyright (c) 2017-2018 Valve Corporation
+ * Copyright (c) 2017-2018 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Lenny Komow <lenny@lunarg.com>
+ */
+
+// This code generates an assembly file which provides offsets to get struct members from assembly code.
+
+#include <stdio.h>
+#include "loader.h"
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+#define SIZE_T_FMT "%-8zu"
+#else
+#define SIZE_T_FMT "%-8lu"
+#endif
+
+struct ValueInfo
+{
+ const char *name;
+ size_t value;
+ const char *comment;
+};
+
+int main(int argc, char **argv) {
+ const char *assembler = NULL;
+ for (int i = 0; i < argc; ++i) {
+ if (!strcmp(argv[i], "MASM")) {
+ assembler = "MASM";
+ } else if (!strcmp(argv[i], "GAS")) {
+ assembler = "GAS";
+ }
+ }
+ if (assembler == NULL) {
+ return 1;
+ }
+
+ struct ValueInfo values[] = {
+ { .name = "VK_DEBUG_REPORT_ERROR_BIT_EXT", .value = (size_t) VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ .comment = "The numerical value of the enum value 'VK_DEBUG_REPORT_ERROR_BIT_EXT'" },
+ { .name = "PTR_SIZE", .value = sizeof(void*),
+ .comment = "The size of a pointer" },
+ { .name = "HASH_SIZE", .value = sizeof(struct loader_dispatch_hash_entry),
+ .comment = "The size of a 'loader_dispatch_hash_entry' struct" },
+ { .name = "HASH_OFFSET_INSTANCE", .value = offsetof(struct loader_instance, phys_dev_ext_disp_hash),
+ .comment = "The offset of 'phys_dev_ext_disp_hash' within a 'loader_instance' struct" },
+ { .name = "PHYS_DEV_OFFSET_INST_DISPATCH", .value = offsetof(struct loader_instance_dispatch_table, phys_dev_ext),
+ .comment = "The offset of 'phys_dev_ext' within in 'loader_instance_dispatch_table' struct" },
+ { .name = "PHYS_DEV_OFFSET_PHYS_DEV_TRAMP", .value = offsetof(struct loader_physical_device_tramp, phys_dev),
+ .comment = "The offset of 'phys_dev' within a 'loader_physical_device_tramp' struct" },
+ { .name = "ICD_TERM_OFFSET_PHYS_DEV_TERM", .value = offsetof(struct loader_physical_device_term, this_icd_term),
+ .comment = "The offset of 'this_icd_term' within a 'loader_physical_device_term' struct" },
+ { .name = "PHYS_DEV_OFFSET_PHYS_DEV_TERM", .value = offsetof(struct loader_physical_device_term, phys_dev),
+ .comment = "The offset of 'phys_dev' within a 'loader_physical_device_term' struct" },
+ { .name = "INSTANCE_OFFSET_ICD_TERM", .value = offsetof(struct loader_icd_term, this_instance),
+ .comment = "The offset of 'this_instance' within a 'loader_icd_term' struct" },
+ { .name = "DISPATCH_OFFSET_ICD_TERM", .value = offsetof(struct loader_icd_term, phys_dev_ext),
+ .comment = "The offset of 'phys_dev_ext' within a 'loader_icd_term' struct" },
+ { .name = "FUNC_NAME_OFFSET_HASH", .value = offsetof(struct loader_dispatch_hash_entry, func_name),
+ .comment = "The offset of 'func_name' within a 'loader_dispatch_hash_entry' struct" },
+ { .name = "EXT_OFFSET_DEVICE_DISPATCH", .value = offsetof(struct loader_dev_dispatch_table, ext_dispatch),
+ .comment = "The offset of 'ext_dispatch' within a 'loader_dev_dispatch_table' struct" },
+ };
+
+ FILE *file = fopen("gen_defines.asm", "w");
+ fprintf(file, "\n");
+ if (!strcmp(assembler, "MASM")) {
+ for (size_t i = 0; i < sizeof(values)/sizeof(values[0]); ++i) {
+ fprintf(file, "%-32s equ " SIZE_T_FMT "; %s\n", values[i].name, values[i].value, values[i].comment);
+ }
+ } else if (!strcmp(assembler, "GAS")) {
+#ifdef __x86_64__
+ fprintf(file, ".set X86_64, 1\n");
+#endif // __x86_64__
+ for (size_t i = 0; i < sizeof(values)/sizeof(values[0]); ++i) {
+ fprintf(file, ".set %-32s, " SIZE_T_FMT "# %s\n", values[i].name, values[i].value, values[i].comment);
+ }
+ }
+ return fclose(file);
+}
diff --git a/thirdparty/vulkan/loader/cJSON.c b/thirdparty/vulkan/loader/cJSON.c
new file mode 100644
index 0000000000..8da6d83c32
--- /dev/null
+++ b/thirdparty/vulkan/loader/cJSON.c
@@ -0,0 +1,1215 @@
+/*
+ Copyright (c) 2009 Dave Gamble
+ Copyright (c) 2015-2016 The Khronos Group Inc.
+ Copyright (c) 2015-2016 Valve Corporation
+ Copyright (c) 2015-2016 LunarG, Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <limits.h>
+#include <ctype.h>
+#include "cJSON.h"
+
+static const char *ep;
+
+const char *cJSON_GetErrorPtr(void) { return ep; }
+
+static void *(*cJSON_malloc)(size_t sz) = malloc;
+static void (*cJSON_free)(void *ptr) = free;
+
+static char *cJSON_strdup(const char *str) {
+ size_t len;
+ char *copy;
+
+ len = strlen(str) + 1;
+ if (!(copy = (char *)cJSON_malloc(len))) return 0;
+ memcpy(copy, str, len);
+ return copy;
+}
+
+void cJSON_InitHooks(cJSON_Hooks *hooks) {
+ if (!hooks) { /* Reset hooks */
+ cJSON_malloc = malloc;
+ cJSON_free = free;
+ return;
+ }
+
+ cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
+ cJSON_free = (hooks->free_fn) ? hooks->free_fn : free;
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(void) {
+ cJSON *node = (cJSON *)cJSON_malloc(sizeof(cJSON));
+ if (node) memset(node, 0, sizeof(cJSON));
+ return node;
+}
+
+/* Delete a cJSON structure. */
+void cJSON_Delete(cJSON *c) {
+ cJSON *next;
+ while (c) {
+ next = c->next;
+ if (!(c->type & cJSON_IsReference) && c->child) cJSON_Delete(c->child);
+ if (!(c->type & cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
+ if (!(c->type & cJSON_StringIsConst) && c->string) cJSON_free(c->string);
+ cJSON_free(c);
+ c = next;
+ }
+}
+
+void cJSON_Free(void *p) { cJSON_free(p); }
+
+/* Parse the input text to generate a number, and populate the result into item.
+ */
+static const char *parse_number(cJSON *item, const char *num) {
+ double n = 0, sign = 1, scale = 0;
+ int subscale = 0, signsubscale = 1;
+
+ if (*num == '-') sign = -1, num++; /* Has sign? */
+ if (*num == '0') num++; /* is zero */
+ if (*num >= '1' && *num <= '9') do
+ n = (n * 10.0) + (*num++ - '0');
+ while (*num >= '0' && *num <= '9'); /* Number? */
+ if (*num == '.' && num[1] >= '0' && num[1] <= '9') {
+ num++;
+ do
+ n = (n * 10.0) + (*num++ - '0'), scale--;
+ while (*num >= '0' && *num <= '9');
+ } /* Fractional part? */
+ if (*num == 'e' || *num == 'E') /* Exponent? */
+ {
+ num++;
+ if (*num == '+')
+ num++;
+ else if (*num == '-')
+ signsubscale = -1, num++; /* With sign? */
+ while (*num >= '0' && *num <= '9') subscale = (subscale * 10) + (*num++ - '0'); /* Number? */
+ }
+
+ n = sign * n * pow(10.0, (scale + subscale * signsubscale)); /* number = +/-
+ number.fraction *
+ 10^+/- exponent */
+
+ item->valuedouble = n;
+ item->valueint = (int)n;
+ item->type = cJSON_Number;
+ return num;
+}
+
+static size_t pow2gt(size_t x) {
+ --x;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return x + 1;
+}
+
+typedef struct {
+ char *buffer;
+ size_t length;
+ size_t offset;
+} printbuffer;
+
+static char *ensure(printbuffer *p, size_t needed) {
+ char *newbuffer;
+ size_t newsize;
+ if (!p || !p->buffer) return 0;
+ needed += p->offset;
+ if (needed <= p->length) return p->buffer + p->offset;
+
+ newsize = pow2gt(needed);
+ newbuffer = (char *)cJSON_malloc(newsize);
+ if (!newbuffer) {
+ cJSON_free(p->buffer);
+ p->length = 0, p->buffer = 0;
+ return 0;
+ }
+ if (newbuffer) memcpy(newbuffer, p->buffer, p->length);
+ cJSON_free(p->buffer);
+ p->length = newsize;
+ p->buffer = newbuffer;
+ return newbuffer + p->offset;
+}
+
+static size_t update(printbuffer *p) {
+ char *str;
+ if (!p || !p->buffer) return 0;
+ str = p->buffer + p->offset;
+ return p->offset + strlen(str);
+}
+
+/* Render the number nicely from the given item into a string. */
+static char *print_number(cJSON *item, printbuffer *p) {
+ char *str = 0;
+ double d = item->valuedouble;
+ if (d == 0) {
+ if (p)
+ str = ensure(p, 2);
+ else
+ str = (char *)cJSON_malloc(2); /* special case for 0. */
+ if (str) strcpy(str, "0");
+ } else if (fabs(((double)item->valueint) - d) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN) {
+ if (p)
+ str = ensure(p, 21);
+ else
+ str = (char *)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
+ if (str) sprintf(str, "%d", item->valueint);
+ } else {
+ if (p)
+ str = ensure(p, 64);
+ else
+ str = (char *)cJSON_malloc(64); /* This is a nice tradeoff. */
+ if (str) {
+ if (fabs(floor(d) - d) <= DBL_EPSILON && fabs(d) < 1.0e60)
+ sprintf(str, "%.0f", d);
+ else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9)
+ sprintf(str, "%e", d);
+ else
+ sprintf(str, "%f", d);
+ }
+ }
+ return str;
+}
+
+static unsigned parse_hex4(const char *str) {
+ unsigned h = 0;
+ if (*str >= '0' && *str <= '9')
+ h += (*str) - '0';
+ else if (*str >= 'A' && *str <= 'F')
+ h += 10 + (*str) - 'A';
+ else if (*str >= 'a' && *str <= 'f')
+ h += 10 + (*str) - 'a';
+ else
+ return 0;
+ h = h << 4;
+ str++;
+ if (*str >= '0' && *str <= '9')
+ h += (*str) - '0';
+ else if (*str >= 'A' && *str <= 'F')
+ h += 10 + (*str) - 'A';
+ else if (*str >= 'a' && *str <= 'f')
+ h += 10 + (*str) - 'a';
+ else
+ return 0;
+ h = h << 4;
+ str++;
+ if (*str >= '0' && *str <= '9')
+ h += (*str) - '0';
+ else if (*str >= 'A' && *str <= 'F')
+ h += 10 + (*str) - 'A';
+ else if (*str >= 'a' && *str <= 'f')
+ h += 10 + (*str) - 'a';
+ else
+ return 0;
+ h = h << 4;
+ str++;
+ if (*str >= '0' && *str <= '9')
+ h += (*str) - '0';
+ else if (*str >= 'A' && *str <= 'F')
+ h += 10 + (*str) - 'A';
+ else if (*str >= 'a' && *str <= 'f')
+ h += 10 + (*str) - 'a';
+ else
+ return 0;
+ return h;
+}
+
+/* Parse the input text into an unescaped cstring, and populate item. */
+static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
+static const char *parse_string(cJSON *item, const char *str) {
+ const char *ptr = str + 1;
+ char *ptr2;
+ char *out;
+ int len = 0;
+ unsigned uc, uc2;
+ if (*str != '\"') {
+ ep = str;
+ return 0;
+ } /* not a string! */
+
+ while (*ptr != '\"' && *ptr && ++len)
+ if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
+
+ out = (char *)cJSON_malloc(len + 1); /* This is how long we need for the string, roughly. */
+ if (!out) return 0;
+
+ ptr = str + 1;
+ ptr2 = out;
+ while (*ptr != '\"' && *ptr) {
+ if (*ptr != '\\')
+ *ptr2++ = *ptr++;
+ else {
+ ptr++;
+ switch (*ptr) {
+ case 'b':
+ *ptr2++ = '\b';
+ break;
+ case 'f':
+ *ptr2++ = '\f';
+ break;
+ case 'n':
+ *ptr2++ = '\n';
+ break;
+ case 'r':
+ *ptr2++ = '\r';
+ break;
+ case 't':
+ *ptr2++ = '\t';
+ break;
+ case 'u': /* transcode utf16 to utf8. */
+ uc = parse_hex4(ptr + 1);
+ ptr += 4; /* get the unicode char. */
+
+ if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) break; /* check for invalid. */
+
+ if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */
+ {
+ if (ptr[1] != '\\' || ptr[2] != 'u') break; /* missing second-half of surrogate. */
+ uc2 = parse_hex4(ptr + 3);
+ ptr += 6;
+ if (uc2 < 0xDC00 || uc2 > 0xDFFF) break; /* invalid second-half of surrogate. */
+ uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
+ }
+
+ len = 4;
+ if (uc < 0x80)
+ len = 1;
+ else if (uc < 0x800)
+ len = 2;
+ else if (uc < 0x10000)
+ len = 3;
+ ptr2 += len;
+
+ switch (len) {
+ case 4:
+ *--ptr2 = ((uc | 0x80) & 0xBF);
+ uc >>= 6;
+ // fall through
+ case 3:
+ *--ptr2 = ((uc | 0x80) & 0xBF);
+ uc >>= 6;
+ // fall through
+ case 2:
+ *--ptr2 = ((uc | 0x80) & 0xBF);
+ uc >>= 6;
+ // fall through
+ case 1:
+ *--ptr2 = ((unsigned char)uc | firstByteMark[len]);
+ }
+ ptr2 += len;
+ break;
+ default:
+ *ptr2++ = *ptr;
+ break;
+ }
+ ptr++;
+ }
+ }
+ *ptr2 = 0;
+ if (*ptr == '\"') ptr++;
+ item->valuestring = out;
+ item->type = cJSON_String;
+ return ptr;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static char *print_string_ptr(const char *str, printbuffer *p) {
+ const char *ptr;
+ char *ptr2;
+ char *out;
+ size_t len = 0, flag = 0;
+ unsigned char token;
+
+ for (ptr = str; *ptr; ptr++) flag |= ((*ptr > 0 && *ptr < 32) || (*ptr == '\"') || (*ptr == '\\')) ? 1 : 0;
+ if (!flag) {
+ len = ptr - str;
+ if (p)
+ out = ensure(p, len + 3);
+ else
+ out = (char *)cJSON_malloc(len + 3);
+ if (!out) return 0;
+ ptr2 = out;
+ *ptr2++ = '\"';
+ strcpy(ptr2, str);
+ ptr2[len] = '\"';
+ ptr2[len + 1] = 0;
+ return out;
+ }
+
+ if (!str) {
+ if (p)
+ out = ensure(p, 3);
+ else
+ out = (char *)cJSON_malloc(3);
+ if (!out) return 0;
+ strcpy(out, "\"\"");
+ return out;
+ }
+ ptr = str;
+ while ((token = *ptr) && ++len) {
+ if (strchr("\"\\\b\f\n\r\t", token))
+ len++;
+ else if (token < 32)
+ len += 5;
+ ptr++;
+ }
+
+ if (p)
+ out = ensure(p, len + 3);
+ else
+ out = (char *)cJSON_malloc(len + 3);
+ if (!out) return 0;
+
+ ptr2 = out;
+ ptr = str;
+ *ptr2++ = '\"';
+ while (*ptr) {
+ if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
+ *ptr2++ = *ptr++;
+ else {
+ switch (token = *ptr++) {
+ case '\\':
+ *ptr2++ = '\\';
+ break;
+ case '\"':
+ *ptr2++ = '\"';
+ break;
+ case '\b':
+ *ptr2++ = '\b';
+ break;
+ case '\f':
+ *ptr2++ = '\f';
+ break;
+ case '\n':
+ *ptr2++ = '\n';
+ break;
+ case '\r':
+ *ptr2++ = '\r';
+ break;
+ case '\t':
+ *ptr2++ = '\t';
+ break;
+ default:
+ sprintf(ptr2, "u%04x", token);
+ ptr2 += 5;
+ break; /* escape and print */
+ }
+ }
+ }
+ *ptr2++ = '\"';
+ *ptr2++ = 0;
+ return out;
+}
+/* Invote print_string_ptr (which is useful) on an item. */
+static char *print_string(cJSON *item, printbuffer *p) { return print_string_ptr(item->valuestring, p); }
+
+/* Predeclare these prototypes. */
+static const char *parse_value(cJSON *item, const char *value);
+static char *print_value(cJSON *item, int depth, int fmt, printbuffer *p);
+static const char *parse_array(cJSON *item, const char *value);
+static char *print_array(cJSON *item, int depth, int fmt, printbuffer *p);
+static const char *parse_object(cJSON *item, const char *value);
+static char *print_object(cJSON *item, int depth, int fmt, printbuffer *p);
+
+/* Utility to jump whitespace and cr/lf */
+static const char *skip(const char *in) {
+ while (in && *in && (unsigned char)*in <= 32) in++;
+ return in;
+}
+
+/* Parse an object - create a new root, and populate. */
+cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated) {
+ const char *end = 0;
+ cJSON *c = cJSON_New_Item();
+ ep = 0;
+ if (!c) return 0; /* memory fail */
+
+ end = parse_value(c, skip(value));
+ if (!end) {
+ cJSON_Delete(c);
+ return 0;
+ } /* parse failure. ep is set. */
+
+ /* if we require null-terminated JSON without appended garbage, skip and
+ * then check for a null terminator */
+ if (require_null_terminated) {
+ end = skip(end);
+ if (*end) {
+ cJSON_Delete(c);
+ ep = end;
+ return 0;
+ }
+ }
+ if (return_parse_end) *return_parse_end = end;
+ return c;
+}
+/* Default options for cJSON_Parse */
+cJSON *cJSON_Parse(const char *value) { return cJSON_ParseWithOpts(value, 0, 0); }
+
+/* Render a cJSON item/entity/structure to text. */
+char *cJSON_Print(cJSON *item) { return print_value(item, 0, 1, 0); }
+char *cJSON_PrintUnformatted(cJSON *item) { return print_value(item, 0, 0, 0); }
+
+char *cJSON_PrintBuffered(cJSON *item, int prebuffer, int fmt) {
+ printbuffer p;
+ p.buffer = (char *)cJSON_malloc(prebuffer);
+ p.length = prebuffer;
+ p.offset = 0;
+ return print_value(item, 0, fmt, &p);
+}
+
+/* Parser core - when encountering text, process appropriately. */
+static const char *parse_value(cJSON *item, const char *value) {
+ if (!value) return 0; /* Fail on null. */
+ if (!strncmp(value, "null", 4)) {
+ item->type = cJSON_NULL;
+ return value + 4;
+ }
+ if (!strncmp(value, "false", 5)) {
+ item->type = cJSON_False;
+ return value + 5;
+ }
+ if (!strncmp(value, "true", 4)) {
+ item->type = cJSON_True;
+ item->valueint = 1;
+ return value + 4;
+ }
+ if (*value == '\"') {
+ return parse_string(item, value);
+ }
+ if (*value == '-' || (*value >= '0' && *value <= '9')) {
+ return parse_number(item, value);
+ }
+ if (*value == '[') {
+ return parse_array(item, value);
+ }
+ if (*value == '{') {
+ return parse_object(item, value);
+ }
+
+ ep = value;
+ return 0; /* failure. */
+}
+
+/* Render a value to text. */
+static char *print_value(cJSON *item, int depth, int fmt, printbuffer *p) {
+ char *out = 0;
+ if (!item) return 0;
+ if (p) {
+ switch ((item->type) & 255) {
+ case cJSON_NULL: {
+ out = ensure(p, 5);
+ if (out) strcpy(out, "null");
+ break;
+ }
+ case cJSON_False: {
+ out = ensure(p, 6);
+ if (out) strcpy(out, "false");
+ break;
+ }
+ case cJSON_True: {
+ out = ensure(p, 5);
+ if (out) strcpy(out, "true");
+ break;
+ }
+ case cJSON_Number:
+ out = print_number(item, p);
+ break;
+ case cJSON_String:
+ out = print_string(item, p);
+ break;
+ case cJSON_Array:
+ out = print_array(item, depth, fmt, p);
+ break;
+ case cJSON_Object:
+ out = print_object(item, depth, fmt, p);
+ break;
+ }
+ } else {
+ switch ((item->type) & 255) {
+ case cJSON_NULL:
+ out = cJSON_strdup("null");
+ break;
+ case cJSON_False:
+ out = cJSON_strdup("false");
+ break;
+ case cJSON_True:
+ out = cJSON_strdup("true");
+ break;
+ case cJSON_Number:
+ out = print_number(item, 0);
+ break;
+ case cJSON_String:
+ out = print_string(item, 0);
+ break;
+ case cJSON_Array:
+ out = print_array(item, depth, fmt, 0);
+ break;
+ case cJSON_Object:
+ out = print_object(item, depth, fmt, 0);
+ break;
+ }
+ }
+ return out;
+}
+
+/* Build an array from input text. */
+static const char *parse_array(cJSON *item, const char *value) {
+ cJSON *child;
+ if (*value != '[') {
+ ep = value;
+ return 0;
+ } /* not an array! */
+
+ item->type = cJSON_Array;
+ value = skip(value + 1);
+ if (*value == ']') return value + 1; /* empty array. */
+
+ item->child = child = cJSON_New_Item();
+ if (!item->child) return 0; /* memory fail */
+ value = skip(parse_value(child, skip(value))); /* skip any spacing, get the value. */
+ if (!value) return 0;
+
+ while (*value == ',') {
+ cJSON *new_item;
+ if (!(new_item = cJSON_New_Item())) return 0; /* memory fail */
+ child->next = new_item;
+ new_item->prev = child;
+ child = new_item;
+ value = skip(parse_value(child, skip(value + 1)));
+ if (!value) return 0; /* memory fail */
+ }
+
+ if (*value == ']') return value + 1; /* end of array */
+ ep = value;
+ return 0; /* malformed. */
+}
+
+/* Render an array to text */
+static char *print_array(cJSON *item, int depth, int fmt, printbuffer *p) {
+ char **entries;
+ char *out = 0, *ptr, *ret;
+ size_t len = 5;
+ cJSON *child = item->child;
+ int numentries = 0, fail = 0, j = 0;
+ size_t tmplen = 0, i = 0;
+
+ /* How many entries in the array? */
+ while (child) numentries++, child = child->next;
+ /* Explicitly handle numentries==0 */
+ if (!numentries) {
+ if (p)
+ out = ensure(p, 3);
+ else
+ out = (char *)cJSON_malloc(3);
+ if (out) strcpy(out, "[]");
+ return out;
+ }
+
+ if (p) {
+ /* Compose the output array. */
+ i = p->offset;
+ ptr = ensure(p, 1);
+ if (!ptr) return 0;
+ *ptr = '[';
+ p->offset++;
+ child = item->child;
+ while (child && !fail) {
+ print_value(child, depth + 1, fmt, p);
+ p->offset = update(p);
+ if (child->next) {
+ len = fmt ? 2 : 1;
+ ptr = ensure(p, len + 1);
+ if (!ptr) return 0;
+ *ptr++ = ',';
+ if (fmt) *ptr++ = ' ';
+ *ptr = 0;
+ p->offset += len;
+ }
+ child = child->next;
+ }
+ ptr = ensure(p, 2);
+ if (!ptr) return 0;
+ *ptr++ = ']';
+ *ptr = 0;
+ out = (p->buffer) + i;
+ } else {
+ /* Allocate an array to hold the values for each */
+ entries = (char **)cJSON_malloc(numentries * sizeof(char *));
+ if (!entries) return 0;
+ memset(entries, 0, numentries * sizeof(char *));
+ /* Retrieve all the results: */
+ child = item->child;
+ while (child && !fail) {
+ ret = print_value(child, depth + 1, fmt, 0);
+ entries[i++] = ret;
+ if (ret)
+ len += strlen(ret) + 2 + (fmt ? 1 : 0);
+ else
+ fail = 1;
+ child = child->next;
+ }
+
+ /* If we didn't fail, try to malloc the output string */
+ if (!fail) out = (char *)cJSON_malloc(len);
+ /* If that fails, we fail. */
+ if (!out) fail = 1;
+
+ /* Handle failure. */
+ if (fail) {
+ for (j = 0; j < numentries; j++)
+ if (entries[j]) cJSON_free(entries[j]);
+ cJSON_free(entries);
+ return 0;
+ }
+
+ /* Compose the output array. */
+ *out = '[';
+ ptr = out + 1;
+ *ptr = 0;
+ for (j = 0; j < numentries; j++) {
+ tmplen = strlen(entries[j]);
+ memcpy(ptr, entries[j], tmplen);
+ ptr += tmplen;
+ if (j != numentries - 1) {
+ *ptr++ = ',';
+ if (fmt) *ptr++ = ' ';
+ *ptr = 0;
+ }
+ cJSON_free(entries[j]);
+ }
+ cJSON_free(entries);
+ *ptr++ = ']';
+ *ptr++ = 0;
+ }
+ return out;
+}
+
+/* Build an object from the text. */
+static const char *parse_object(cJSON *item, const char *value) {
+ cJSON *child;
+ if (*value != '{') {
+ ep = value;
+ return 0;
+ } /* not an object! */
+
+ item->type = cJSON_Object;
+ value = skip(value + 1);
+ if (*value == '}') return value + 1; /* empty array. */
+
+ item->child = child = cJSON_New_Item();
+ if (!item->child) return 0;
+ value = skip(parse_string(child, skip(value)));
+ if (!value) return 0;
+ child->string = child->valuestring;
+ child->valuestring = 0;
+ if (*value != ':') {
+ ep = value;
+ return 0;
+ } /* fail! */
+ value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
+ if (!value) return 0;
+
+ while (*value == ',') {
+ cJSON *new_item;
+ if (!(new_item = cJSON_New_Item())) return 0; /* memory fail */
+ child->next = new_item;
+ new_item->prev = child;
+ child = new_item;
+ value = skip(parse_string(child, skip(value + 1)));
+ if (!value) return 0;
+ child->string = child->valuestring;
+ child->valuestring = 0;
+ if (*value != ':') {
+ ep = value;
+ return 0;
+ } /* fail! */
+ value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
+ if (!value) return 0;
+ }
+
+ if (*value == '}') return value + 1; /* end of array */
+ ep = value;
+ return 0; /* malformed. */
+}
+
+/* Render an object to text. */
+static char *print_object(cJSON *item, int depth, int fmt, printbuffer *p) {
+ char **entries = 0, **names = 0;
+ char *out = 0, *ptr, *ret, *str;
+ int j;
+ cJSON *child = item->child;
+ int numentries = 0, fail = 0, k;
+ size_t tmplen = 0, i = 0, len = 7;
+ /* Count the number of entries. */
+ while (child) numentries++, child = child->next;
+ /* Explicitly handle empty object case */
+ if (!numentries) {
+ if (p)
+ out = ensure(p, fmt ? depth + 4 : 3);
+ else
+ out = (char *)cJSON_malloc(fmt ? depth + 4 : 3);
+ if (!out) return 0;
+ ptr = out;
+ *ptr++ = '{';
+ if (fmt) {
+ *ptr++ = '\n';
+ for (j = 0; j < depth - 1; j++) *ptr++ = '\t';
+ }
+ *ptr++ = '}';
+ *ptr++ = 0;
+ return out;
+ }
+ if (p) {
+ /* Compose the output: */
+ i = p->offset;
+ len = fmt ? 2 : 1;
+ ptr = ensure(p, len + 1);
+ if (!ptr) return 0;
+ *ptr++ = '{';
+ if (fmt) *ptr++ = '\n';
+ *ptr = 0;
+ p->offset += len;
+ child = item->child;
+ depth++;
+ while (child) {
+ if (fmt) {
+ ptr = ensure(p, depth);
+ if (!ptr) return 0;
+ for (j = 0; j < depth; j++) *ptr++ = '\t';
+ p->offset += depth;
+ }
+ print_string_ptr(child->string, p);
+ p->offset = update(p);
+
+ len = fmt ? 2 : 1;
+ ptr = ensure(p, len);
+ if (!ptr) return 0;
+ *ptr++ = ':';
+ if (fmt) *ptr++ = '\t';
+ p->offset += len;
+
+ print_value(child, depth, fmt, p);
+ p->offset = update(p);
+
+ len = (fmt ? 1 : 0) + (child->next ? 1 : 0);
+ ptr = ensure(p, len + 1);
+ if (!ptr) return 0;
+ if (child->next) *ptr++ = ',';
+ if (fmt) *ptr++ = '\n';
+ *ptr = 0;
+ p->offset += len;
+ child = child->next;
+ }
+ ptr = ensure(p, fmt ? (depth + 1) : 2);
+ if (!ptr) return 0;
+ if (fmt)
+ for (j = 0; j < depth - 1; j++) *ptr++ = '\t';
+ *ptr++ = '}';
+ *ptr = 0;
+ out = (p->buffer) + i;
+ } else {
+ /* Allocate space for the names and the objects */
+ entries = (char **)cJSON_malloc(numentries * sizeof(char *));
+ if (!entries) return 0;
+ names = (char **)cJSON_malloc(numentries * sizeof(char *));
+ if (!names) {
+ cJSON_free(entries);
+ return 0;
+ }
+ memset(entries, 0, sizeof(char *) * numentries);
+ memset(names, 0, sizeof(char *) * numentries);
+
+ /* Collect all the results into our arrays: */
+ child = item->child;
+ depth++;
+ if (fmt) len += depth;
+ while (child) {
+ names[i] = str = print_string_ptr(child->string, 0);
+ entries[i++] = ret = print_value(child, depth, fmt, 0);
+ if (str && ret)
+ len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
+ else
+ fail = 1;
+ child = child->next;
+ }
+
+ /* Try to allocate the output string */
+ if (!fail) out = (char *)cJSON_malloc(len);
+ if (!out) fail = 1;
+
+ /* Handle failure */
+ if (fail) {
+ for (j = 0; j < numentries; j++) {
+ if (names[i]) cJSON_free(names[j]);
+ if (entries[j]) cJSON_free(entries[j]);
+ }
+ cJSON_free(names);
+ cJSON_free(entries);
+ return 0;
+ }
+
+ /* Compose the output: */
+ *out = '{';
+ ptr = out + 1;
+ if (fmt) *ptr++ = '\n';
+ *ptr = 0;
+ for (j = 0; j < numentries; j++) {
+ if (fmt)
+ for (k = 0; k < depth; k++) *ptr++ = '\t';
+ tmplen = strlen(names[j]);
+ memcpy(ptr, names[j], tmplen);
+ ptr += tmplen;
+ *ptr++ = ':';
+ if (fmt) *ptr++ = '\t';
+ strcpy(ptr, entries[j]);
+ ptr += strlen(entries[j]);
+ if (j != numentries - 1) *ptr++ = ',';
+ if (fmt) *ptr++ = '\n';
+ *ptr = 0;
+ cJSON_free(names[j]);
+ cJSON_free(entries[j]);
+ }
+
+ cJSON_free(names);
+ cJSON_free(entries);
+ if (fmt)
+ for (j = 0; j < depth - 1; j++) *ptr++ = '\t';
+ *ptr++ = '}';
+ *ptr++ = 0;
+ }
+ return out;
+}
+
+/* Get Array size/item / object item. */
+int cJSON_GetArraySize(cJSON *array) {
+ cJSON *c = array->child;
+ int i = 0;
+ while (c) i++, c = c->next;
+ return i;
+}
+cJSON *cJSON_GetArrayItem(cJSON *array, int item) {
+ cJSON *c = array->child;
+ while (c && item > 0) item--, c = c->next;
+ return c;
+}
+cJSON *cJSON_GetObjectItem(cJSON *object, const char *string) {
+ cJSON *c = object->child;
+ while (c && strcmp(c->string, string)) c = c->next;
+ return c;
+}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev, cJSON *item) {
+ prev->next = item;
+ item->prev = prev;
+}
+/* Utility for handling references. */
+static cJSON *create_reference(cJSON *item) {
+ cJSON *ref = cJSON_New_Item();
+ if (!ref) return 0;
+ memcpy(ref, item, sizeof(cJSON));
+ ref->string = 0;
+ ref->type |= cJSON_IsReference;
+ ref->next = ref->prev = 0;
+ return ref;
+}
+
+/* Add item to array/object. */
+void cJSON_AddItemToArray(cJSON *array, cJSON *item) {
+ cJSON *c = array->child;
+ if (!item) return;
+ if (!c) {
+ array->child = item;
+ } else {
+ while (c && c->next) c = c->next;
+ suffix_object(c, item);
+ }
+}
+void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) {
+ if (!item) return;
+ if (item->string) cJSON_free(item->string);
+ item->string = cJSON_strdup(string);
+ cJSON_AddItemToArray(object, item);
+}
+void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) {
+ if (!item) return;
+ if (!(item->type & cJSON_StringIsConst) && item->string) cJSON_free(item->string);
+ item->string = (char *)string;
+ item->type |= cJSON_StringIsConst;
+ cJSON_AddItemToArray(object, item);
+}
+void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) { cJSON_AddItemToArray(array, create_reference(item)); }
+void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) {
+ cJSON_AddItemToObject(object, string, create_reference(item));
+}
+
+cJSON *cJSON_DetachItemFromArray(cJSON *array, int which) {
+ cJSON *c = array->child;
+ while (c && which > 0) c = c->next, which--;
+ if (!c) return 0;
+ if (c->prev) c->prev->next = c->next;
+ if (c->next) c->next->prev = c->prev;
+ if (c == array->child) array->child = c->next;
+ c->prev = c->next = 0;
+ return c;
+}
+void cJSON_DeleteItemFromArray(cJSON *array, int which) { cJSON_Delete(cJSON_DetachItemFromArray(array, which)); }
+cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string) {
+ int i = 0;
+ cJSON *c = object->child;
+ while (c && strcmp(c->string, string)) i++, c = c->next;
+ if (c) return cJSON_DetachItemFromArray(object, i);
+ return 0;
+}
+void cJSON_DeleteItemFromObject(cJSON *object, const char *string) { cJSON_Delete(cJSON_DetachItemFromObject(object, string)); }
+
+/* Replace array/object items with new ones. */
+void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) {
+ cJSON *c = array->child;
+ while (c && which > 0) c = c->next, which--;
+ if (!c) {
+ cJSON_AddItemToArray(array, newitem);
+ return;
+ }
+ newitem->next = c;
+ newitem->prev = c->prev;
+ c->prev = newitem;
+ if (c == array->child)
+ array->child = newitem;
+ else
+ newitem->prev->next = newitem;
+}
+void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) {
+ cJSON *c = array->child;
+ while (c && which > 0) c = c->next, which--;
+ if (!c) return;
+ newitem->next = c->next;
+ newitem->prev = c->prev;
+ if (newitem->next) newitem->next->prev = newitem;
+ if (c == array->child)
+ array->child = newitem;
+ else
+ newitem->prev->next = newitem;
+ c->next = c->prev = 0;
+ cJSON_Delete(c);
+}
+void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) {
+ int i = 0;
+ cJSON *c = object->child;
+ while (c && strcmp(c->string, string)) i++, c = c->next;
+ if (c) {
+ newitem->string = cJSON_strdup(string);
+ cJSON_ReplaceItemInArray(object, i, newitem);
+ }
+}
+
+/* Create basic types: */
+cJSON *cJSON_CreateNull(void) {
+ cJSON *item = cJSON_New_Item();
+ if (item) item->type = cJSON_NULL;
+ return item;
+}
+cJSON *cJSON_CreateTrue(void) {
+ cJSON *item = cJSON_New_Item();
+ if (item) item->type = cJSON_True;
+ return item;
+}
+cJSON *cJSON_CreateFalse(void) {
+ cJSON *item = cJSON_New_Item();
+ if (item) item->type = cJSON_False;
+ return item;
+}
+cJSON *cJSON_CreateBool(int b) {
+ cJSON *item = cJSON_New_Item();
+ if (item) item->type = b ? cJSON_True : cJSON_False;
+ return item;
+}
+cJSON *cJSON_CreateNumber(double num) {
+ cJSON *item = cJSON_New_Item();
+ if (item) {
+ item->type = cJSON_Number;
+ item->valuedouble = num;
+ item->valueint = (int)num;
+ }
+ return item;
+}
+cJSON *cJSON_CreateString(const char *string) {
+ cJSON *item = cJSON_New_Item();
+ if (item) {
+ item->type = cJSON_String;
+ item->valuestring = cJSON_strdup(string);
+ }
+ return item;
+}
+cJSON *cJSON_CreateArray(void) {
+ cJSON *item = cJSON_New_Item();
+ if (item) item->type = cJSON_Array;
+ return item;
+}
+cJSON *cJSON_CreateObject(void) {
+ cJSON *item = cJSON_New_Item();
+ if (item) item->type = cJSON_Object;
+ return item;
+}
+
+/* Create Arrays: */
+cJSON *cJSON_CreateIntArray(const int *numbers, int count) {
+ int i;
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+ for (i = 0; a && i < count; i++) {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!i)
+ a->child = n;
+ else
+ suffix_object(p, n);
+ p = n;
+ }
+ return a;
+}
+cJSON *cJSON_CreateFloatArray(const float *numbers, int count) {
+ int i;
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+ for (i = 0; a && i < count; i++) {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!i)
+ a->child = n;
+ else
+ suffix_object(p, n);
+ p = n;
+ }
+ return a;
+}
+cJSON *cJSON_CreateDoubleArray(const double *numbers, int count) {
+ int i;
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+ for (i = 0; a && i < count; i++) {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!i)
+ a->child = n;
+ else
+ suffix_object(p, n);
+ p = n;
+ }
+ return a;
+}
+cJSON *cJSON_CreateStringArray(const char **strings, int count) {
+ int i;
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+ for (i = 0; a && i < count; i++) {
+ n = cJSON_CreateString(strings[i]);
+ if (!i)
+ a->child = n;
+ else
+ suffix_object(p, n);
+ p = n;
+ }
+ return a;
+}
+
+/* Duplication */
+cJSON *cJSON_Duplicate(cJSON *item, int recurse) {
+ cJSON *newitem, *cptr, *nptr = 0, *newchild;
+ /* Bail on bad ptr */
+ if (!item) return 0;
+ /* Create new item */
+ newitem = cJSON_New_Item();
+ if (!newitem) return 0;
+ /* Copy over all vars */
+ newitem->type = item->type & (~cJSON_IsReference), newitem->valueint = item->valueint, newitem->valuedouble = item->valuedouble;
+ if (item->valuestring) {
+ newitem->valuestring = cJSON_strdup(item->valuestring);
+ if (!newitem->valuestring) {
+ cJSON_Delete(newitem);
+ return 0;
+ }
+ }
+ if (item->string) {
+ newitem->string = cJSON_strdup(item->string);
+ if (!newitem->string) {
+ cJSON_Delete(newitem);
+ return 0;
+ }
+ }
+ /* If non-recursive, then we're done! */
+ if (!recurse) return newitem;
+ /* Walk the ->next chain for the child. */
+ cptr = item->child;
+ while (cptr) {
+ newchild = cJSON_Duplicate(cptr, 1); /* Duplicate (with recurse) each item in the ->next chain */
+ if (!newchild) {
+ cJSON_Delete(newitem);
+ return 0;
+ }
+ if (nptr) {
+ nptr->next = newchild, newchild->prev = nptr;
+ nptr = newchild;
+ } /* If newitem->child already set, then crosswire ->prev and ->next and
+ move on */
+ else {
+ newitem->child = newchild;
+ nptr = newchild;
+ } /* Set newitem->child and move to it */
+ cptr = cptr->next;
+ }
+ return newitem;
+}
+
+void cJSON_Minify(char *json) {
+ char *into = json;
+ while (*json) {
+ if (*json == ' ')
+ json++;
+ else if (*json == '\t')
+ json++; /* Whitespace characters. */
+ else if (*json == '\r')
+ json++;
+ else if (*json == '\n')
+ json++;
+ else if (*json == '/' && json[1] == '/')
+ while (*json && *json != '\n') json++; /* double-slash comments, to end of line. */
+ else if (*json == '/' && json[1] == '*') {
+ while (*json && !(*json == '*' && json[1] == '/')) json++;
+ json += 2;
+ } /* multiline comments. */
+ else if (*json == '\"') {
+ *into++ = *json++;
+ while (*json && *json != '\"') {
+ if (*json == '\\') *into++ = *json++;
+ *into++ = *json++;
+ }
+ *into++ = *json++;
+ } /* string literals, which are \" sensitive. */
+ else
+ *into++ = *json++; /* All other characters. */
+ }
+ *into = 0; /* and null-terminate. */
+}
diff --git a/thirdparty/vulkan/loader/cJSON.h b/thirdparty/vulkan/loader/cJSON.h
new file mode 100644
index 0000000000..f0059abdcb
--- /dev/null
+++ b/thirdparty/vulkan/loader/cJSON.h
@@ -0,0 +1,174 @@
+/*
+ Copyright (c) 2009 Dave Gamble
+ Copyright (c) 2015-2016 The Khronos Group Inc.
+ Copyright (c) 2015-2016 Valve Corporation
+ Copyright (c) 2015-2016 LunarG, Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* cJSON Types: */
+#define cJSON_False 0
+#define cJSON_True 1
+#define cJSON_NULL 2
+#define cJSON_Number 3
+#define cJSON_String 4
+#define cJSON_Array 5
+#define cJSON_Object 6
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+/* The cJSON structure: */
+typedef struct cJSON {
+ struct cJSON *next, *prev; /* next/prev allow you to walk array/object
+ chains. Alternatively, use
+ GetArraySize/GetArrayItem/GetObjectItem */
+ struct cJSON *child; /* An array or object item will have a child pointer
+ pointing to a chain of the items in the
+ array/object. */
+
+ int type; /* The type of the item, as above. */
+
+ char *valuestring; /* The item's string, if type==cJSON_String */
+ int valueint; /* The item's number, if type==cJSON_Number */
+ double valuedouble; /* The item's number, if type==cJSON_Number */
+
+ char *string; /* The item's name string, if this item is the child of, or is
+ in the list of subitems of an object. */
+} cJSON;
+
+typedef struct cJSON_Hooks {
+ void *(*malloc_fn)(size_t sz);
+ void (*free_fn)(void *ptr);
+} cJSON_Hooks;
+
+/* Supply malloc, realloc and free functions to cJSON */
+extern void cJSON_InitHooks(cJSON_Hooks *hooks);
+
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate.
+ * Call cJSON_Delete when finished. */
+extern cJSON *cJSON_Parse(const char *value);
+/* Render a cJSON entity to text for transfer/storage. Free the char* when
+ * finished. */
+extern char *cJSON_Print(cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting.
+ * Free the char* when finished. */
+extern char *cJSON_PrintUnformatted(cJSON *item);
+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess
+ * at the final size. guessing well reduces reallocation. fmt=0 gives
+ * unformatted, =1 gives formatted */
+extern char *cJSON_PrintBuffered(cJSON *item, int prebuffer, int fmt);
+/* Delete a cJSON entity and all subentities. */
+extern void cJSON_Delete(cJSON *c);
+/* Delete an item allocated inside the JSON parser*/
+extern void cJSON_Free(void *p);
+
+/* Returns the number of items in an array (or object). */
+extern int cJSON_GetArraySize(cJSON *array);
+/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful.
+ */
+extern cJSON *cJSON_GetArrayItem(cJSON *array, int item);
+/* Get item "string" from object. Case insensitive. */
+extern cJSON *cJSON_GetObjectItem(cJSON *object, const char *string);
+
+/* For analysing failed parses. This returns a pointer to the parse error.
+ * You'll probably need to look a few chars back to make sense of it. Defined
+ * when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+extern const char *cJSON_GetErrorPtr(void);
+
+/* These calls create a cJSON item of the appropriate type. */
+extern cJSON *cJSON_CreateNull(void);
+extern cJSON *cJSON_CreateTrue(void);
+extern cJSON *cJSON_CreateFalse(void);
+extern cJSON *cJSON_CreateBool(int b);
+extern cJSON *cJSON_CreateNumber(double num);
+extern cJSON *cJSON_CreateString(const char *string);
+extern cJSON *cJSON_CreateArray(void);
+extern cJSON *cJSON_CreateObject(void);
+
+/* These utilities create an Array of count items. */
+extern cJSON *cJSON_CreateIntArray(const int *numbers, int count);
+extern cJSON *cJSON_CreateFloatArray(const float *numbers, int count);
+extern cJSON *cJSON_CreateDoubleArray(const double *numbers, int count);
+extern cJSON *cJSON_CreateStringArray(const char **strings, int count);
+
+/* Append item to the specified array/object. */
+extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
+extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+extern void cJSON_AddItemToObjectCS(cJSON *object, const char *string,
+ cJSON *item); /* Use this when string is definitely const (i.e. a literal,
+ or as good as), and will definitely survive the cJSON
+ object */
+/* Append reference to item to the specified array/object. Use this when you
+ * want to add an existing cJSON to a new cJSON, but don't want to corrupt your
+ * existing cJSON. */
+extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+/* Remove/Detatch items from Arrays/Objects. */
+extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which);
+extern void cJSON_DeleteItemFromArray(cJSON *array, int which);
+extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string);
+extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+
+/* Update array items. */
+extern void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
+extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+extern void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem);
+
+/* Duplicate a cJSON item */
+extern cJSON *cJSON_Duplicate(cJSON *item, int recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new
+memory that will
+need to be released. With recurse!=0, it will duplicate any children connected
+to the item.
+The item->next and ->prev pointers are always zero on return from Duplicate. */
+
+/* ParseWithOpts allows you to require (and check) that the JSON is null
+ * terminated, and to retrieve the pointer to the final byte parsed. */
+extern cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated);
+
+extern void cJSON_Minify(char *json);
+
+/* Macros for creating things quickly. */
+#define cJSON_AddNullToObject(object, name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
+#define cJSON_AddTrueToObject(object, name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
+#define cJSON_AddFalseToObject(object, name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
+#define cJSON_AddBoolToObject(object, name, b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
+#define cJSON_AddNumberToObject(object, name, n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
+#define cJSON_AddStringToObject(object, name, s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
+
+/* When assigning an integer value, it needs to be propagated to valuedouble
+ * too. */
+#define cJSON_SetIntValue(object, val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val))
+#define cJSON_SetNumberValue(object, val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/loader/debug_utils.c b/thirdparty/vulkan/loader/debug_utils.c
new file mode 100644
index 0000000000..10701e7991
--- /dev/null
+++ b/thirdparty/vulkan/loader/debug_utils.c
@@ -0,0 +1,996 @@
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ * Copyright (C) 2015-2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Jon Ashburn <jon@LunarG.com>
+ * Author: Mark Young <marky@lunarg.com>
+ *
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#ifndef WIN32
+#include <signal.h>
+#else
+#endif
+#include "vk_loader_platform.h"
+#include "debug_utils.h"
+#include "vulkan/vk_layer.h"
+#include "vk_object_types.h"
+
+// VK_EXT_debug_report related items
+
+VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger) {
+ VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+ sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ } else {
+#endif
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ }
+ if (!pNewDbgFuncNode) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+ pNewDbgFuncNode->is_messenger = true;
+ pNewDbgFuncNode->messenger.messenger = messenger;
+ pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
+ pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity;
+ pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType;
+ pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+ pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+ inst->DbgFunctionHead = pNewDbgFuncNode;
+
+ return VK_SUCCESS;
+}
+
+static VKAPI_ATTR VkResult VKAPI_CALL
+debug_utils_CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ loader_platform_thread_lock_mutex(&loader_lock);
+ VkResult result = inst->disp->layer_inst_disp.CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return result;
+}
+
+VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+ VkBool32 bail = false;
+
+ if (NULL != pCallbackData) {
+ VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+ VkDebugReportObjectTypeEXT object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
+ VkDebugReportFlagsEXT object_flags = 0;
+ uint64_t object_handle = 0;
+
+ debug_utils_AnnotFlagsToReportFlags(messageSeverity, messageTypes, &object_flags);
+ if (0 < pCallbackData->objectCount) {
+ debug_utils_AnnotObjectToDebugReportObject(pCallbackData->pObjects, &object_type, &object_handle);
+ }
+
+ while (pTrav) {
+ if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & messageSeverity) &&
+ (pTrav->messenger.messageType & messageTypes)) {
+ if (pTrav->messenger.pfnUserCallback(messageSeverity, messageTypes, pCallbackData, pTrav->pUserData)) {
+ bail = true;
+ }
+ }
+ if (!pTrav->is_messenger && pTrav->report.msgFlags & object_flags) {
+ if (pTrav->report.pfnMsgCallback(object_flags, object_type, object_handle, 0, pCallbackData->messageIdNumber,
+ pCallbackData->pMessageIdName, pCallbackData->pMessage, pTrav->pUserData)) {
+ bail = true;
+ }
+ }
+
+ pTrav = pTrav->pNext;
+ }
+ }
+
+ return bail;
+}
+
+void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+ VkLayerDbgFunctionNode *pPrev = pTrav;
+
+ while (pTrav) {
+ if (pTrav->is_messenger && pTrav->messenger.messenger == messenger) {
+ pPrev->pNext = pTrav->pNext;
+ if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, pTrav);
+ } else {
+#endif
+ loader_instance_heap_free(inst, pTrav);
+ }
+ break;
+ }
+ pPrev = pTrav;
+ pTrav = pTrav->pNext;
+ }
+}
+
+// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It
+// counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It
+// then allocates array that can hold that many structs, as well as that many
+// VkDebugUtilsMessengerEXT handles. It then copies each
+// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
+VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator,
+ uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos,
+ VkDebugUtilsMessengerEXT **messengers) {
+ uint32_t n = *num_messengers = 0;
+ VkDebugUtilsMessengerCreateInfoEXT *pInfos = NULL;
+ VkDebugUtilsMessengerEXT *pMessengers = NULL;
+
+ const void *pNext = pChain;
+ while (pNext) {
+ // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
+ if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ n++;
+ }
+ pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
+ }
+ if (n == 0) {
+ return VK_SUCCESS;
+ }
+
+// 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pInfos = *infos = ((VkDebugUtilsMessengerCreateInfoEXT *)pAllocator->pfnAllocation(
+ pAllocator->pUserData, n * sizeof(VkDebugUtilsMessengerCreateInfoEXT), sizeof(void *),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ } else {
+#endif
+ pInfos = *infos = ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
+ }
+ if (!pInfos) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+// 3rd, allocate memory for a unique handle for each callback:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)pAllocator->pfnAllocation(
+ pAllocator->pUserData, n * sizeof(VkDebugUtilsMessengerEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ if (NULL == pMessengers) {
+ pAllocator->pfnFree(pAllocator->pUserData, pInfos);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ } else {
+#endif
+ pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
+ if (NULL == pMessengers) {
+ free(pInfos);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ }
+ // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
+ // vkDestroyInstance, and assign a unique handle to each messenger (just
+ // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
+ pNext = pChain;
+ while (pNext) {
+ if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
+ *pMessengers++ = (VkDebugUtilsMessengerEXT)(uintptr_t)pInfos++;
+ }
+ pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
+ }
+
+ *num_messengers = n;
+ return VK_SUCCESS;
+}
+
+void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos,
+ VkDebugUtilsMessengerEXT *messengers) {
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, infos);
+ pAllocator->pfnFree(pAllocator->pUserData, messengers);
+ } else {
+#endif
+ free(infos);
+ free(messengers);
+ }
+}
+
+VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos,
+ VkDebugUtilsMessengerEXT *messengers) {
+ VkResult rtn = VK_SUCCESS;
+ for (uint32_t i = 0; i < num_messengers; i++) {
+ rtn = util_CreateDebugUtilsMessenger(inst, &infos[i], pAllocator, messengers[i]);
+ if (rtn != VK_SUCCESS) {
+ for (uint32_t j = 0; j < i; j++) {
+ util_DestroyDebugUtilsMessenger(inst, messengers[j], pAllocator);
+ }
+ return rtn;
+ }
+ }
+ return rtn;
+}
+
+void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers) {
+ for (uint32_t i = 0; i < num_messengers; i++) {
+ util_DestroyDebugUtilsMessenger(inst, messengers[i], pAllocator);
+ }
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_SubmitDebugUtilsMessageEXT(
+ VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+ struct loader_instance *inst = loader_get_instance(instance);
+
+ inst->disp->layer_inst_disp.SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData);
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ loader_platform_thread_lock_mutex(&loader_lock);
+
+ inst->disp->layer_inst_disp.DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+// This is the instance chain terminator function for CreateDebugUtilsMessenger
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger) {
+ VkDebugUtilsMessengerEXT *icd_info = NULL;
+ const struct loader_icd_term *icd_term;
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ VkResult res = VK_SUCCESS;
+ uint32_t storage_idx;
+ VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ icd_info = ((VkDebugUtilsMessengerEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
+ inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT),
+ sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ if (icd_info) {
+ memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT));
+ }
+ } else {
+#endif
+ icd_info = calloc(sizeof(VkDebugUtilsMessengerEXT), inst->total_icd_count);
+ }
+ if (!icd_info) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (!icd_term->dispatch.CreateDebugUtilsMessengerEXT) {
+ continue;
+ }
+
+ res = icd_term->dispatch.CreateDebugUtilsMessengerEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
+
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+ storage_idx++;
+ }
+
+// Setup the debug report callback in the terminator since a layer may want
+// to grab the information itself (RenderDoc) and then return back to the
+// user callback a sub-set of the messages.
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
+ if (pAllocator != NULL) {
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+ sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ } else {
+#else
+ {
+#endif
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ }
+ if (!pNewDbgFuncNode) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+ pNewDbgFuncNode->is_messenger = true;
+ pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
+ pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity;
+ pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType;
+ pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+ pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+ inst->DbgFunctionHead = pNewDbgFuncNode;
+
+ *(VkDebugUtilsMessengerEXT **)pMessenger = icd_info;
+ pNewDbgFuncNode->messenger.messenger = *pMessenger;
+
+out:
+
+ // Roll back on errors
+ if (VK_SUCCESS != res) {
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
+ continue;
+ }
+
+ if (icd_info && icd_info[storage_idx]) {
+ icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+ }
+ storage_idx++;
+ }
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ if (NULL != pNewDbgFuncNode) {
+ pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
+ }
+ if (NULL != icd_info) {
+ pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+ }
+ } else {
+#endif
+ if (NULL != pNewDbgFuncNode) {
+ free(pNewDbgFuncNode);
+ }
+ if (NULL != icd_info) {
+ free(icd_info);
+ }
+ }
+ }
+
+ return res;
+}
+
+// This is the instance chain terminator function for DestroyDebugUtilsMessenger
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ uint32_t storage_idx;
+ VkDebugUtilsMessengerEXT *icd_info;
+ const struct loader_icd_term *icd_term;
+
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ icd_info = *(VkDebugUtilsMessengerEXT **)&messenger;
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
+ continue;
+ }
+
+ if (icd_info[storage_idx]) {
+ icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+ }
+ storage_idx++;
+ }
+
+ util_DestroyDebugUtilsMessenger(inst, messenger, pAllocator);
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+ } else {
+#endif
+ free(icd_info);
+ }
+}
+
+// This is the instance chain terminator function for SubmitDebugUtilsMessageEXT
+VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance instance,
+ VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+ loader_platform_thread_lock_mutex(&loader_lock);
+ // NOTE: Just make the callback ourselves because there could be one or more ICDs that support this extension
+ // and each one will trigger the callback to the user. This would result in multiple callback triggers
+ // per message. Instead, if we get a messaged up to here, then just trigger the message ourselves and
+ // return. This would still allow the ICDs to trigger their own messages, but won't get any external ones.
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ util_SubmitDebugUtilsMessageEXT(inst, messageSeverity, messageTypes, pCallbackData);
+ loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+// VK_EXT_debug_report related items
+
+VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) {
+ VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+ sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ } else {
+#endif
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ }
+ if (!pNewDbgFuncNode) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+ pNewDbgFuncNode->is_messenger = false;
+ pNewDbgFuncNode->report.msgCallback = callback;
+ pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback;
+ pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags;
+ pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+ pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+ inst->DbgFunctionHead = pNewDbgFuncNode;
+
+ return VK_SUCCESS;
+}
+
+static VKAPI_ATTR VkResult VKAPI_CALL
+debug_utils_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ loader_platform_thread_lock_mutex(&loader_lock);
+ VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return result;
+}
+
+// Utility function to handle reporting
+VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
+ uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
+ VkBool32 bail = false;
+ VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+ VkDebugUtilsMessageSeverityFlagBitsEXT severity;
+ VkDebugUtilsMessageTypeFlagsEXT types;
+ VkDebugUtilsMessengerCallbackDataEXT callback_data;
+ VkDebugUtilsObjectNameInfoEXT object_name;
+
+ debug_utils_ReportFlagsToAnnotFlags(msgFlags, false, &severity, &types);
+ debug_utils_ReportObjectToAnnotObject(objectType, srcObject, &object_name);
+
+ callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+ callback_data.pNext = NULL;
+ callback_data.flags = 0;
+ callback_data.pMessageIdName = pLayerPrefix;
+ callback_data.messageIdNumber = msgCode;
+ callback_data.pMessage = pMsg;
+ callback_data.cmdBufLabelCount = 0;
+ callback_data.pCmdBufLabels = NULL;
+ callback_data.queueLabelCount = 0;
+ callback_data.pQueueLabels = NULL;
+ callback_data.objectCount = 1;
+ callback_data.pObjects = &object_name;
+
+ while (pTrav) {
+ if (!pTrav->is_messenger && pTrav->report.msgFlags & msgFlags) {
+ if (pTrav->report.pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg,
+ pTrav->pUserData)) {
+ bail = true;
+ }
+ }
+ if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & severity) && (pTrav->messenger.messageType & types)) {
+ if (pTrav->messenger.pfnUserCallback(severity, types, &callback_data, pTrav->pUserData)) {
+ bail = true;
+ }
+ }
+
+ pTrav = pTrav->pNext;
+ }
+
+ return bail;
+}
+
+void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator) {
+ VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+ VkLayerDbgFunctionNode *pPrev = pTrav;
+
+ while (pTrav) {
+ if (!pTrav->is_messenger && pTrav->report.msgCallback == callback) {
+ pPrev->pNext = pTrav->pNext;
+ if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, pTrav);
+ } else {
+#endif
+ loader_instance_heap_free(inst, pTrav);
+ }
+ break;
+ }
+ pPrev = pTrav;
+ pTrav = pTrav->pNext;
+ }
+}
+
+// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It
+// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
+// then allocates array that can hold that many structs, as well as that many
+// VkDebugReportCallbackEXT handles. It then copies each
+// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
+VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
+ VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) {
+ uint32_t n = *num_callbacks = 0;
+ VkDebugReportCallbackCreateInfoEXT *pInfos = NULL;
+ VkDebugReportCallbackEXT *pCallbacks = NULL;
+
+ const void *pNext = pChain;
+ while (pNext) {
+ // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
+ if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
+ n++;
+ }
+ pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
+ }
+ if (n == 0) {
+ return VK_SUCCESS;
+ }
+
+// 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)pAllocator->pfnAllocation(
+ pAllocator->pUserData, n * sizeof(VkDebugReportCallbackCreateInfoEXT), sizeof(void *),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ } else {
+#endif
+ pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
+ }
+ if (!pInfos) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+// 3rd, allocate memory for a unique handle for each callback:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(
+ pAllocator->pUserData, n * sizeof(VkDebugReportCallbackEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ if (!pCallbacks) {
+ pAllocator->pfnFree(pAllocator->pUserData, pInfos);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ } else {
+#endif
+ pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
+ if (!pCallbacks) {
+ free(pInfos);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ }
+ // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
+ // vkDestroyInstance, and assign a unique handle to each callback (just
+ // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
+ pNext = pChain;
+ while (pNext) {
+ if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
+ memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
+ *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++;
+ }
+ pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
+ }
+
+ *num_callbacks = n;
+ return VK_SUCCESS;
+}
+
+void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
+ VkDebugReportCallbackEXT *callbacks) {
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, infos);
+ pAllocator->pfnFree(pAllocator->pUserData, callbacks);
+ } else {
+#endif
+ free(infos);
+ free(callbacks);
+ }
+}
+
+VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
+ VkDebugReportCallbackEXT *callbacks) {
+ VkResult rtn = VK_SUCCESS;
+ for (uint32_t i = 0; i < num_callbacks; i++) {
+ rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator, callbacks[i]);
+ if (rtn != VK_SUCCESS) {
+ for (uint32_t j = 0; j < i; j++) {
+ util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator);
+ }
+ return rtn;
+ }
+ }
+ return rtn;
+}
+
+void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
+ VkDebugReportCallbackEXT *callbacks) {
+ for (uint32_t i = 0; i < num_callbacks; i++) {
+ util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator);
+ }
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ loader_platform_thread_lock_mutex(&loader_lock);
+
+ inst->disp->layer_inst_disp.DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objType, uint64_t object,
+ size_t location, int32_t msgCode, const char *pLayerPrefix,
+ const char *pMsg) {
+ struct loader_instance *inst = loader_get_instance(instance);
+
+ inst->disp->layer_inst_disp.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
+}
+
+// This is the instance chain terminator function
+// for CreateDebugReportCallback
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
+ const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugReportCallbackEXT *pCallback) {
+ VkDebugReportCallbackEXT *icd_info = NULL;
+ const struct loader_icd_term *icd_term;
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ VkResult res = VK_SUCCESS;
+ uint32_t storage_idx;
+ VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
+ inst->total_icd_count * sizeof(VkDebugReportCallbackEXT),
+ sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ if (icd_info) {
+ memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT));
+ }
+ } else {
+#endif
+ icd_info = calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count);
+ }
+ if (!icd_info) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (!icd_term->dispatch.CreateDebugReportCallbackEXT) {
+ continue;
+ }
+
+ res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
+
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+ storage_idx++;
+ }
+
+// Setup the debug report callback in the terminator since a layer may want
+// to grab the information itself (RenderDoc) and then return back to the
+// user callback a sub-set of the messages.
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
+ if (pAllocator != NULL) {
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+ sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ } else {
+#else
+ {
+#endif
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ }
+ if (!pNewDbgFuncNode) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+ pNewDbgFuncNode->is_messenger = false;
+ pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback;
+ pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags;
+ pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+ pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+ inst->DbgFunctionHead = pNewDbgFuncNode;
+
+ *(VkDebugReportCallbackEXT **)pCallback = icd_info;
+ pNewDbgFuncNode->report.msgCallback = *pCallback;
+
+out:
+
+ // Roll back on errors
+ if (VK_SUCCESS != res) {
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
+ continue;
+ }
+
+ if (icd_info && icd_info[storage_idx]) {
+ icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+ }
+ storage_idx++;
+ }
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ if (NULL != pNewDbgFuncNode) {
+ pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
+ }
+ if (NULL != icd_info) {
+ pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+ }
+ } else {
+#endif
+ if (NULL != pNewDbgFuncNode) {
+ free(pNewDbgFuncNode);
+ }
+ if (NULL != icd_info) {
+ free(icd_info);
+ }
+ }
+ }
+
+ return res;
+}
+
+// This is the instance chain terminator function for DestroyDebugReportCallback
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator) {
+ uint32_t storage_idx;
+ VkDebugReportCallbackEXT *icd_info;
+ const struct loader_icd_term *icd_term;
+
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ icd_info = *(VkDebugReportCallbackEXT **)&callback;
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
+ continue;
+ }
+
+ if (icd_info[storage_idx]) {
+ icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+ }
+ storage_idx++;
+ }
+
+ util_DestroyDebugReportCallback(inst, callback, pAllocator);
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+ } else {
+#endif
+ free(icd_info);
+ }
+}
+
+// This is the instance chain terminator function for DebugReportMessage
+VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
+ int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
+ const struct loader_icd_term *icd_term;
+
+ struct loader_instance *inst = (struct loader_instance *)instance;
+
+ loader_platform_thread_lock_mutex(&loader_lock);
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (icd_term->dispatch.DebugReportMessageEXT != NULL) {
+ icd_term->dispatch.DebugReportMessageEXT(icd_term->instance, flags, objType, object, location, msgCode, pLayerPrefix,
+ pMsg);
+ }
+ }
+
+ // Now that all ICDs have seen the message, call the necessary callbacks. Ignoring "bail" return value
+ // as there is nothing to bail from at this point.
+
+ util_DebugReportMessage(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+// General utilities
+
+static const VkExtensionProperties debug_utils_extension_info[] = {
+ {VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
+ {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION},
+};
+
+void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
+ loader_add_to_ext_list(inst, ext_list, sizeof(debug_utils_extension_info) / sizeof(VkExtensionProperties),
+ debug_utils_extension_info);
+}
+
+void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
+ ptr_instance->enabled_known_extensions.ext_debug_report = 0;
+ ptr_instance->enabled_known_extensions.ext_debug_utils = 0;
+
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
+ ptr_instance->enabled_known_extensions.ext_debug_report = 1;
+ } else if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
+ ptr_instance->enabled_known_extensions.ext_debug_utils = 1;
+ }
+ }
+}
+
+bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
+ bool ret_type = false;
+
+ *addr = NULL;
+
+ if (!strcmp("vkCreateDebugReportCallbackEXT", name)) {
+ *addr = ptr_instance->enabled_known_extensions.ext_debug_report == 1 ? (void *)debug_utils_CreateDebugReportCallbackEXT : NULL;
+ ret_type = true;
+ } else if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) {
+ *addr = ptr_instance->enabled_known_extensions.ext_debug_report == 1 ? (void *)debug_utils_DestroyDebugReportCallbackEXT : NULL;
+ ret_type = true;
+ } else if (!strcmp("vkDebugReportMessageEXT", name)) {
+ *addr = ptr_instance->enabled_known_extensions.ext_debug_report == 1 ? (void *)debug_utils_DebugReportMessageEXT : NULL;
+ return true;
+ }
+ if (!strcmp("vkCreateDebugUtilsMessengerEXT", name)) {
+ *addr = ptr_instance->enabled_known_extensions.ext_debug_utils == 1 ? (void *)debug_utils_CreateDebugUtilsMessengerEXT : NULL;
+ ret_type = true;
+ } else if (!strcmp("vkDestroyDebugUtilsMessengerEXT", name)) {
+ *addr = ptr_instance->enabled_known_extensions.ext_debug_utils == 1 ? (void *)debug_utils_DestroyDebugUtilsMessengerEXT : NULL;
+ ret_type = true;
+ } else if (!strcmp("vkSubmitDebugUtilsMessageEXT", name)) {
+ *addr = ptr_instance->enabled_known_extensions.ext_debug_utils == 1 ? (void *)debug_utils_SubmitDebugUtilsMessageEXT : NULL;
+ ret_type = true;
+ }
+
+ return ret_type;
+}
+
+bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
+ VkDebugUtilsMessageSeverityFlagBitsEXT *da_severity,
+ VkDebugUtilsMessageTypeFlagsEXT *da_type) {
+ bool type_set = false;
+ if (NULL == da_severity || NULL == da_type) {
+ return false;
+ }
+ *da_type = 0;
+ *da_severity = 0;
+
+ if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
+ *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ type_set = true;
+ } else if ((dr_flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)) != 0) {
+ *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ } else if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
+ *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ } else if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
+ *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ type_set = true;
+ }
+
+ if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ } else if (!type_set) {
+ if (default_flag_is_spec) {
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+ } else {
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ }
+ }
+
+ return true;
+}
+
+bool debug_utils_AnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
+ VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
+ if (NULL == dr_flags) {
+ return false;
+ }
+
+ *dr_flags = 0;
+
+ if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
+ } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
+ if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+ } else {
+ *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
+ }
+ } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+ } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+ }
+
+ return true;
+}
+
+bool debug_utils_ReportObjectToAnnotObject(VkDebugReportObjectTypeEXT dr_object_type, uint64_t object_handle,
+ VkDebugUtilsObjectNameInfoEXT *da_object_name_info) {
+ if (NULL == da_object_name_info) {
+ return false;
+ }
+ da_object_name_info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ da_object_name_info->pNext = NULL;
+ da_object_name_info->objectHandle = (uint64_t)(uintptr_t)object_handle;
+ da_object_name_info->pObjectName = NULL;
+ da_object_name_info->objectType = convertDebugReportObjectToCoreObject(dr_object_type);
+ return true;
+}
+
+bool debug_utils_AnnotObjectToDebugReportObject(const VkDebugUtilsObjectNameInfoEXT *da_object_name_info,
+ VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle) {
+ if (NULL == da_object_name_info || NULL == dr_object_type || NULL == dr_object_handle) {
+ return false;
+ }
+ *dr_object_type = convertCoreObjectToDebugReportObject(da_object_name_info->objectType);
+ *dr_object_handle = da_object_name_info->objectHandle;
+ return true;
+}
diff --git a/thirdparty/vulkan/loader/debug_utils.h b/thirdparty/vulkan/loader/debug_utils.h
new file mode 100644
index 0000000000..c33a6fcee6
--- /dev/null
+++ b/thirdparty/vulkan/loader/debug_utils.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ * Copyright (C) 2015-2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Mark Young <markyk@lunarg.com>
+ *
+ */
+
+#include "vk_loader_platform.h"
+#include "loader.h"
+
+// General utilities
+
+void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list);
+void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);
+bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr);
+bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
+ VkDebugUtilsMessageSeverityFlagBitsEXT *da_severity,
+ VkDebugUtilsMessageTypeFlagsEXT *da_type);
+bool debug_utils_AnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
+ VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags);
+bool debug_utils_ReportObjectToAnnotObject(VkDebugReportObjectTypeEXT dr_object_type, uint64_t object_handle,
+ VkDebugUtilsObjectNameInfoEXT *da_object_name_info);
+bool debug_utils_AnnotObjectToDebugReportObject(const VkDebugUtilsObjectNameInfoEXT *da_object_name_info,
+ VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle);
+
+// VK_EXT_debug_utils related items
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger);
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator);
+VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance instance,
+ VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData);
+VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger);
+VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos,
+ VkDebugUtilsMessengerEXT *messengers);
+VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData);
+VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator,
+ uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos,
+ VkDebugUtilsMessengerEXT **messengers);
+void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator);
+void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers);
+void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos,
+ VkDebugUtilsMessengerEXT *messengers);
+
+// VK_EXT_debug_report related items
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
+ const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugReportCallbackEXT *pCallback);
+
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
+ int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
+
+VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback);
+VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
+ VkDebugReportCallbackEXT *callbacks);
+VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
+ uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
+VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
+ VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks);
+void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator);
+void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
+ VkDebugReportCallbackEXT *callbacks);
+void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
+ VkDebugReportCallbackEXT *callbacks);
diff --git a/thirdparty/vulkan/loader/dev_ext_trampoline.c b/thirdparty/vulkan/loader/dev_ext_trampoline.c
new file mode 100644
index 0000000000..55eee0c25f
--- /dev/null
+++ b/thirdparty/vulkan/loader/dev_ext_trampoline.c
@@ -0,0 +1,538 @@
+/*
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Lenny Komow <lenny@lunarg.com>
+ */
+
+#include "vk_loader_platform.h"
+#include "loader.h"
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC optimize(3) // force gcc to use tail-calls
+#endif
+
+// Clang-format does not understand macros.
+// clang-format off
+
+VKAPI_ATTR void VKAPI_CALL vkdev_ext0(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext1(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext2(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext3(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext4(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext5(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext6(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext7(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext8(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext9(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext10(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext11(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext12(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext13(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext14(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext15(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext16(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext17(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext18(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext19(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext20(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext21(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext22(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext23(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext24(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext25(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext26(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext27(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext28(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext29(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext30(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext31(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext32(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext33(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext34(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext35(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext36(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext37(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext38(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext39(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext40(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext41(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext42(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext43(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext44(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext45(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext46(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext47(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext48(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext49(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext50(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext51(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext52(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext53(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext54(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext55(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext56(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext57(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext58(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext59(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext60(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext61(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext62(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext63(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext64(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext65(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext66(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext67(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext68(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext69(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext70(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext71(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext72(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext73(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext74(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext75(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext76(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext77(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext78(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext79(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext80(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext81(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext82(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext83(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext84(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext85(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext86(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext87(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext88(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext89(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext90(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext91(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext92(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext93(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext94(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext95(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext96(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext97(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext98(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext99(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext100(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext101(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext102(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext103(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext104(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext105(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext106(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext107(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext108(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext109(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext110(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext111(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext112(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext113(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext114(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext115(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext116(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext117(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext118(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext119(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext120(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext121(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext122(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext123(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext124(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext125(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext126(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext127(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext128(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext129(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext130(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext131(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext132(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext133(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext134(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext135(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext136(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext137(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext138(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext139(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext140(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext141(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext142(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext143(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext144(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext145(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext146(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext147(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext148(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext149(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext150(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext151(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext152(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext153(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext154(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext155(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext156(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext157(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext158(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext159(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext160(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext161(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext162(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext163(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext164(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext165(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext166(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext167(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext168(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext169(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext170(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext171(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext172(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext173(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext174(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext175(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext176(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext177(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext178(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext179(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext180(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext181(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext182(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext183(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext184(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext185(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext186(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext187(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext188(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext189(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext190(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext191(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext192(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext193(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext194(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext195(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext196(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext197(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext198(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext199(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext200(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext201(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext202(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext203(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext204(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext205(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext206(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext207(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext208(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext209(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext210(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext211(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext212(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext213(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext214(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext215(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext216(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext217(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext218(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext219(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext220(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext221(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext222(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext223(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext224(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext225(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext226(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext227(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext228(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext229(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext230(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext231(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext232(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext233(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext234(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext235(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext236(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext237(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext238(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext239(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext240(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext241(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext242(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext243(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext244(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext245(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext246(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext247(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext248(VkDevice device);
+VKAPI_ATTR void VKAPI_CALL vkdev_ext249(VkDevice device);
+
+void *loader_get_dev_ext_trampoline(uint32_t index) {
+ switch (index) {
+#define CASE_HANDLE(num) case num: return vkdev_ext##num
+ CASE_HANDLE(0);
+ CASE_HANDLE(1);
+ CASE_HANDLE(2);
+ CASE_HANDLE(3);
+ CASE_HANDLE(4);
+ CASE_HANDLE(5);
+ CASE_HANDLE(6);
+ CASE_HANDLE(7);
+ CASE_HANDLE(8);
+ CASE_HANDLE(9);
+ CASE_HANDLE(10);
+ CASE_HANDLE(11);
+ CASE_HANDLE(12);
+ CASE_HANDLE(13);
+ CASE_HANDLE(14);
+ CASE_HANDLE(15);
+ CASE_HANDLE(16);
+ CASE_HANDLE(17);
+ CASE_HANDLE(18);
+ CASE_HANDLE(19);
+ CASE_HANDLE(20);
+ CASE_HANDLE(21);
+ CASE_HANDLE(22);
+ CASE_HANDLE(23);
+ CASE_HANDLE(24);
+ CASE_HANDLE(25);
+ CASE_HANDLE(26);
+ CASE_HANDLE(27);
+ CASE_HANDLE(28);
+ CASE_HANDLE(29);
+ CASE_HANDLE(30);
+ CASE_HANDLE(31);
+ CASE_HANDLE(32);
+ CASE_HANDLE(33);
+ CASE_HANDLE(34);
+ CASE_HANDLE(35);
+ CASE_HANDLE(36);
+ CASE_HANDLE(37);
+ CASE_HANDLE(38);
+ CASE_HANDLE(39);
+ CASE_HANDLE(40);
+ CASE_HANDLE(41);
+ CASE_HANDLE(42);
+ CASE_HANDLE(43);
+ CASE_HANDLE(44);
+ CASE_HANDLE(45);
+ CASE_HANDLE(46);
+ CASE_HANDLE(47);
+ CASE_HANDLE(48);
+ CASE_HANDLE(49);
+ CASE_HANDLE(50);
+ CASE_HANDLE(51);
+ CASE_HANDLE(52);
+ CASE_HANDLE(53);
+ CASE_HANDLE(54);
+ CASE_HANDLE(55);
+ CASE_HANDLE(56);
+ CASE_HANDLE(57);
+ CASE_HANDLE(58);
+ CASE_HANDLE(59);
+ CASE_HANDLE(60);
+ CASE_HANDLE(61);
+ CASE_HANDLE(62);
+ CASE_HANDLE(63);
+ CASE_HANDLE(64);
+ CASE_HANDLE(65);
+ CASE_HANDLE(66);
+ CASE_HANDLE(67);
+ CASE_HANDLE(68);
+ CASE_HANDLE(69);
+ CASE_HANDLE(70);
+ CASE_HANDLE(71);
+ CASE_HANDLE(72);
+ CASE_HANDLE(73);
+ CASE_HANDLE(74);
+ CASE_HANDLE(75);
+ CASE_HANDLE(76);
+ CASE_HANDLE(77);
+ CASE_HANDLE(78);
+ CASE_HANDLE(79);
+ CASE_HANDLE(80);
+ CASE_HANDLE(81);
+ CASE_HANDLE(82);
+ CASE_HANDLE(83);
+ CASE_HANDLE(84);
+ CASE_HANDLE(85);
+ CASE_HANDLE(86);
+ CASE_HANDLE(87);
+ CASE_HANDLE(88);
+ CASE_HANDLE(89);
+ CASE_HANDLE(90);
+ CASE_HANDLE(91);
+ CASE_HANDLE(92);
+ CASE_HANDLE(93);
+ CASE_HANDLE(94);
+ CASE_HANDLE(95);
+ CASE_HANDLE(96);
+ CASE_HANDLE(97);
+ CASE_HANDLE(98);
+ CASE_HANDLE(99);
+ CASE_HANDLE(100);
+ CASE_HANDLE(101);
+ CASE_HANDLE(102);
+ CASE_HANDLE(103);
+ CASE_HANDLE(104);
+ CASE_HANDLE(105);
+ CASE_HANDLE(106);
+ CASE_HANDLE(107);
+ CASE_HANDLE(108);
+ CASE_HANDLE(109);
+ CASE_HANDLE(110);
+ CASE_HANDLE(111);
+ CASE_HANDLE(112);
+ CASE_HANDLE(113);
+ CASE_HANDLE(114);
+ CASE_HANDLE(115);
+ CASE_HANDLE(116);
+ CASE_HANDLE(117);
+ CASE_HANDLE(118);
+ CASE_HANDLE(119);
+ CASE_HANDLE(120);
+ CASE_HANDLE(121);
+ CASE_HANDLE(122);
+ CASE_HANDLE(123);
+ CASE_HANDLE(124);
+ CASE_HANDLE(125);
+ CASE_HANDLE(126);
+ CASE_HANDLE(127);
+ CASE_HANDLE(128);
+ CASE_HANDLE(129);
+ CASE_HANDLE(130);
+ CASE_HANDLE(131);
+ CASE_HANDLE(132);
+ CASE_HANDLE(133);
+ CASE_HANDLE(134);
+ CASE_HANDLE(135);
+ CASE_HANDLE(136);
+ CASE_HANDLE(137);
+ CASE_HANDLE(138);
+ CASE_HANDLE(139);
+ CASE_HANDLE(140);
+ CASE_HANDLE(141);
+ CASE_HANDLE(142);
+ CASE_HANDLE(143);
+ CASE_HANDLE(144);
+ CASE_HANDLE(145);
+ CASE_HANDLE(146);
+ CASE_HANDLE(147);
+ CASE_HANDLE(148);
+ CASE_HANDLE(149);
+ CASE_HANDLE(150);
+ CASE_HANDLE(151);
+ CASE_HANDLE(152);
+ CASE_HANDLE(153);
+ CASE_HANDLE(154);
+ CASE_HANDLE(155);
+ CASE_HANDLE(156);
+ CASE_HANDLE(157);
+ CASE_HANDLE(158);
+ CASE_HANDLE(159);
+ CASE_HANDLE(160);
+ CASE_HANDLE(161);
+ CASE_HANDLE(162);
+ CASE_HANDLE(163);
+ CASE_HANDLE(164);
+ CASE_HANDLE(165);
+ CASE_HANDLE(166);
+ CASE_HANDLE(167);
+ CASE_HANDLE(168);
+ CASE_HANDLE(169);
+ CASE_HANDLE(170);
+ CASE_HANDLE(171);
+ CASE_HANDLE(172);
+ CASE_HANDLE(173);
+ CASE_HANDLE(174);
+ CASE_HANDLE(175);
+ CASE_HANDLE(176);
+ CASE_HANDLE(177);
+ CASE_HANDLE(178);
+ CASE_HANDLE(179);
+ CASE_HANDLE(180);
+ CASE_HANDLE(181);
+ CASE_HANDLE(182);
+ CASE_HANDLE(183);
+ CASE_HANDLE(184);
+ CASE_HANDLE(185);
+ CASE_HANDLE(186);
+ CASE_HANDLE(187);
+ CASE_HANDLE(188);
+ CASE_HANDLE(189);
+ CASE_HANDLE(190);
+ CASE_HANDLE(191);
+ CASE_HANDLE(192);
+ CASE_HANDLE(193);
+ CASE_HANDLE(194);
+ CASE_HANDLE(195);
+ CASE_HANDLE(196);
+ CASE_HANDLE(197);
+ CASE_HANDLE(198);
+ CASE_HANDLE(199);
+ CASE_HANDLE(200);
+ CASE_HANDLE(201);
+ CASE_HANDLE(202);
+ CASE_HANDLE(203);
+ CASE_HANDLE(204);
+ CASE_HANDLE(205);
+ CASE_HANDLE(206);
+ CASE_HANDLE(207);
+ CASE_HANDLE(208);
+ CASE_HANDLE(209);
+ CASE_HANDLE(210);
+ CASE_HANDLE(211);
+ CASE_HANDLE(212);
+ CASE_HANDLE(213);
+ CASE_HANDLE(214);
+ CASE_HANDLE(215);
+ CASE_HANDLE(216);
+ CASE_HANDLE(217);
+ CASE_HANDLE(218);
+ CASE_HANDLE(219);
+ CASE_HANDLE(220);
+ CASE_HANDLE(221);
+ CASE_HANDLE(222);
+ CASE_HANDLE(223);
+ CASE_HANDLE(224);
+ CASE_HANDLE(225);
+ CASE_HANDLE(226);
+ CASE_HANDLE(227);
+ CASE_HANDLE(228);
+ CASE_HANDLE(229);
+ CASE_HANDLE(230);
+ CASE_HANDLE(231);
+ CASE_HANDLE(232);
+ CASE_HANDLE(233);
+ CASE_HANDLE(234);
+ CASE_HANDLE(235);
+ CASE_HANDLE(236);
+ CASE_HANDLE(237);
+ CASE_HANDLE(238);
+ CASE_HANDLE(239);
+ CASE_HANDLE(240);
+ CASE_HANDLE(241);
+ CASE_HANDLE(242);
+ CASE_HANDLE(243);
+ CASE_HANDLE(244);
+ CASE_HANDLE(245);
+ CASE_HANDLE(246);
+ CASE_HANDLE(247);
+ CASE_HANDLE(248);
+ CASE_HANDLE(249);
+ }
+
+ return NULL;
+}
diff --git a/thirdparty/vulkan/loader/dirent_on_windows.c b/thirdparty/vulkan/loader/dirent_on_windows.c
new file mode 100644
index 0000000000..16318cc70d
--- /dev/null
+++ b/thirdparty/vulkan/loader/dirent_on_windows.c
@@ -0,0 +1,128 @@
+/*
+
+ Implementation of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003 and July 2012.
+ Rights: See end of file.
+
+*/
+#include "dirent_on_windows.h"
+#include <errno.h>
+#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
+#include <stdlib.h>
+#include <string.h>
+#include "vk_loader_platform.h"
+#include "loader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
+
+struct DIR {
+ handle_type handle; /* -1 for failed rewind */
+ struct _finddata_t info;
+ struct dirent result; /* d_name null iff first time */
+ char *name; /* null-terminated char string */
+};
+
+DIR *opendir(const char *name) {
+ DIR *dir = 0;
+
+ if (name && name[0]) {
+ size_t base_length = strlen(name);
+ const char *all = /* search pattern must end with suitable wildcard */
+ strchr("/\\", name[base_length - 1]) ? "*" : "/*";
+
+ if ((dir = (DIR *)loader_instance_tls_heap_alloc(sizeof *dir)) != 0 &&
+ (dir->name = (char *)loader_instance_tls_heap_alloc(base_length + strlen(all) + 1)) != 0) {
+ strcat(strcpy(dir->name, name), all);
+
+ if ((dir->handle = (handle_type)_findfirst(dir->name, &dir->info)) != -1) {
+ dir->result.d_name = 0;
+ } else /* rollback */
+ {
+ loader_instance_tls_heap_free(dir->name);
+ loader_instance_tls_heap_free(dir);
+ dir = 0;
+ }
+ } else /* rollback */
+ {
+ loader_instance_tls_heap_free(dir);
+ dir = 0;
+ errno = ENOMEM;
+ }
+ } else {
+ errno = EINVAL;
+ }
+
+ return dir;
+}
+
+int closedir(DIR *dir) {
+ int result = -1;
+
+ if (dir) {
+ if (dir->handle != -1) {
+ result = _findclose(dir->handle);
+ }
+
+ loader_instance_tls_heap_free(dir->name);
+ loader_instance_tls_heap_free(dir);
+ }
+
+ if (result == -1) /* map all errors to EBADF */
+ {
+ errno = EBADF;
+ }
+
+ return result;
+}
+
+struct dirent *readdir(DIR *dir) {
+ struct dirent *result = 0;
+
+ if (dir && dir->handle != -1) {
+ if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) {
+ result = &dir->result;
+ result->d_name = dir->info.name;
+ }
+ } else {
+ errno = EBADF;
+ }
+
+ return result;
+}
+
+void rewinddir(DIR *dir) {
+ if (dir && dir->handle != -1) {
+ _findclose(dir->handle);
+ dir->handle = (handle_type)_findfirst(dir->name, &dir->info);
+ dir->result.d_name = 0;
+ } else {
+ errno = EBADF;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+
+ Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved.
+ Copyright (c) 2015 The Khronos Group Inc.
+ Copyright (c) 2015 Valve Corporation
+ Copyright (c) 2015 LunarG, Inc.
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+
+*/
diff --git a/thirdparty/vulkan/loader/dirent_on_windows.h b/thirdparty/vulkan/loader/dirent_on_windows.h
new file mode 100644
index 0000000000..8600f8ef04
--- /dev/null
+++ b/thirdparty/vulkan/loader/dirent_on_windows.h
@@ -0,0 +1,51 @@
+#ifndef DIRENT_INCLUDED
+#define DIRENT_INCLUDED
+
+/*
+
+ Declaration of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003.
+ Rights: See end of file.
+
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct DIR DIR;
+
+struct dirent {
+ char *d_name;
+};
+
+DIR *opendir(const char *);
+int closedir(DIR *);
+struct dirent *readdir(DIR *);
+void rewinddir(DIR *);
+
+/*
+
+ Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+ Copyright (c) 2015 The Khronos Group Inc.
+ Copyright (c) 2015 Valve Corporation
+ Copyright (c) 2015 LunarG, Inc.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/loader/dxgi_loader.c b/thirdparty/vulkan/loader/dxgi_loader.c
new file mode 100644
index 0000000000..c2a3fa5638
--- /dev/null
+++ b/thirdparty/vulkan/loader/dxgi_loader.c
@@ -0,0 +1,23 @@
+#include "dxgi_loader.h"
+
+#include <strsafe.h>
+
+static HMODULE load_dxgi_module() {
+ TCHAR systemPath[MAX_PATH] = "";
+ GetSystemDirectory(systemPath, MAX_PATH);
+ StringCchCat(systemPath, MAX_PATH, TEXT("\\dxgi.dll"));
+
+ return LoadLibrary(systemPath);
+}
+
+typedef HRESULT (APIENTRY *PFN_CreateDXGIFactory1)(REFIID riid, void **ppFactory);
+
+HRESULT dyn_CreateDXGIFactory1(REFIID riid, void **ppFactory) {
+ PFN_CreateDXGIFactory1 fpCreateDXGIFactory1 =
+ (PFN_CreateDXGIFactory1)GetProcAddress(load_dxgi_module(), "CreateDXGIFactory1");
+
+ if (fpCreateDXGIFactory1 != NULL)
+ return fpCreateDXGIFactory1(riid, ppFactory);
+
+ return DXGI_ERROR_NOT_FOUND;
+} \ No newline at end of file
diff --git a/thirdparty/vulkan/loader/dxgi_loader.h b/thirdparty/vulkan/loader/dxgi_loader.h
new file mode 100644
index 0000000000..00daf08ed2
--- /dev/null
+++ b/thirdparty/vulkan/loader/dxgi_loader.h
@@ -0,0 +1,8 @@
+#ifndef DXGI_LOADER_H
+#define DXGI_LOADER_H
+
+#include <dxgi1_2.h>
+
+HRESULT dyn_CreateDXGIFactory1(REFIID riid, void **ppFactory);
+
+#endif \ No newline at end of file
diff --git a/thirdparty/vulkan/loader/extension_manual.c b/thirdparty/vulkan/loader/extension_manual.c
new file mode 100644
index 0000000000..b8118fdc8a
--- /dev/null
+++ b/thirdparty/vulkan/loader/extension_manual.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Mark Young <marky@lunarg.com>
+ * Author: Lenny Komow <lenny@lunarg.com>
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "vk_loader_platform.h"
+#include "loader.h"
+#include "vk_loader_extensions.h"
+#include <vulkan/vk_icd.h>
+#include "wsi.h"
+#include "debug_utils.h"
+
+// ---- Manually added trampoline/terminator functions
+
+// These functions, for whatever reason, require more complex changes than
+// can easily be automatically generated.
+
+// ---- VK_KHR_device_group extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
+ VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceSurfaceCapabilities2KHR(unwrapped_phys_dev, pSurfaceInfo, pSurfaceCapabilities);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2KHR(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
+ VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(pSurfaceInfo->surface);
+ uint8_t icd_index = phys_dev_term->icd_index;
+
+ if (icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR != NULL) {
+ VkBaseOutStructure *pNext = (VkBaseOutStructure *)pSurfaceCapabilities->pNext;
+ while (pNext != NULL) {
+ if ((int)pNext->sType == VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR) {
+ // Not all ICDs may be supporting VK_KHR_surface_protected_capabilities
+ // Initialize VkSurfaceProtectedCapabilitiesKHR.supportsProtected to false and
+ // if an ICD supports protected surfaces, it will reset it to true accordingly.
+ ((VkSurfaceProtectedCapabilitiesKHR *)pNext)->supportsProtected = VK_FALSE;
+ }
+ pNext = (VkBaseOutStructure *)pNext->pNext;
+ }
+
+ // Pass the call to the driver, possibly unwrapping the ICD surface
+ if (icd_surface->real_icd_surfaces != NULL && (void *)icd_surface->real_icd_surfaces[icd_index] != NULL) {
+ VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;
+ info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev_term->phys_dev, &info_copy,
+ pSurfaceCapabilities);
+ } else {
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev_term->phys_dev, pSurfaceInfo,
+ pSurfaceCapabilities);
+ }
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSurfaceCapabilities2KHR: Emulating call in ICD \"%s\" using "
+ "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
+ icd_term->scanned_icd->lib_name);
+
+ if (pSurfaceInfo->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSurfaceCapabilities2KHR: Emulation found unrecognized structure type in "
+ "pSurfaceInfo->pNext - this struct will be ignored");
+ }
+
+ // Write to the VkSurfaceCapabilities2KHR struct
+ VkSurfaceKHR surface = pSurfaceInfo->surface;
+ if (icd_surface->real_icd_surfaces != NULL && (void *)icd_surface->real_icd_surfaces[icd_index] != NULL) {
+ surface = icd_surface->real_icd_surfaces[icd_index];
+ }
+ VkResult res = icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, surface,
+ &pSurfaceCapabilities->surfaceCapabilities);
+
+ if (pSurfaceCapabilities->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSurfaceCapabilities2KHR: Emulation found unrecognized structure type in "
+ "pSurfaceCapabilities->pNext - this struct will be ignored");
+ }
+ return res;
+ }
+}
+
+// ---- VK_NV_external_memory_capabilities extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL
+GetPhysicalDeviceExternalImageFormatPropertiesNV(
+ VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
+ VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
+ VkExternalMemoryHandleTypeFlagsNV externalHandleType,
+ VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+
+ return disp->GetPhysicalDeviceExternalImageFormatPropertiesNV(
+ unwrapped_phys_dev, format, type, tiling, usage, flags,
+ externalHandleType, pExternalImageFormatProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV(
+ VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
+ VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
+ VkExternalMemoryHandleTypeFlagsNV externalHandleType,
+ VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ if (!icd_term->dispatch.GetPhysicalDeviceExternalImageFormatPropertiesNV) {
+ if (externalHandleType) {
+ return VK_ERROR_FORMAT_NOT_SUPPORTED;
+ }
+
+ if (!icd_term->dispatch.GetPhysicalDeviceImageFormatProperties) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ pExternalImageFormatProperties->externalMemoryFeatures = 0;
+ pExternalImageFormatProperties->exportFromImportedHandleTypes = 0;
+ pExternalImageFormatProperties->compatibleHandleTypes = 0;
+
+ return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(
+ phys_dev_term->phys_dev, format, type, tiling, usage, flags,
+ &pExternalImageFormatProperties->imageFormatProperties);
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceExternalImageFormatPropertiesNV(
+ phys_dev_term->phys_dev, format, type, tiling, usage, flags,
+ externalHandleType, pExternalImageFormatProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
+ uint32_t *pSurfaceFormatCount,
+ VkSurfaceFormat2KHR *pSurfaceFormats) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceSurfaceFormats2KHR(unwrapped_phys_dev, pSurfaceInfo, pSurfaceFormatCount, pSurfaceFormats);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
+ uint32_t *pSurfaceFormatCount,
+ VkSurfaceFormat2KHR *pSurfaceFormats) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(pSurfaceInfo->surface);
+ uint8_t icd_index = phys_dev_term->icd_index;
+
+ if (icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR != NULL) {
+ // Pass the call to the driver, possibly unwrapping the ICD surface
+ if (icd_surface->real_icd_surfaces != NULL && (void *)icd_surface->real_icd_surfaces[icd_index] != NULL) {
+ VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;
+ info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR(phys_dev_term->phys_dev, &info_copy, pSurfaceFormatCount,
+ pSurfaceFormats);
+ } else {
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR(phys_dev_term->phys_dev, pSurfaceInfo,
+ pSurfaceFormatCount, pSurfaceFormats);
+ }
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSurfaceFormats2KHR: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceSurfaceFormatsKHR",
+ icd_term->scanned_icd->lib_name);
+
+ if (pSurfaceInfo->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSurfaceFormats2KHR: Emulation found unrecognized structure type in pSurfaceInfo->pNext "
+ "- this struct will be ignored");
+ }
+
+ VkSurfaceKHR surface = pSurfaceInfo->surface;
+ if (icd_surface->real_icd_surfaces != NULL && (void *)icd_surface->real_icd_surfaces[icd_index] != NULL) {
+ surface = icd_surface->real_icd_surfaces[icd_index];
+ }
+
+ if (*pSurfaceFormatCount == 0 || pSurfaceFormats == NULL) {
+ // Write to pSurfaceFormatCount
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface, pSurfaceFormatCount,
+ NULL);
+ } else {
+ // Allocate a temporary array for the output of the old function
+ VkSurfaceFormatKHR *formats = loader_stack_alloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
+ if (formats == NULL) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ VkResult res = icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface,
+ pSurfaceFormatCount, formats);
+ for (uint32_t i = 0; i < *pSurfaceFormatCount; ++i) {
+ pSurfaceFormats[i].surfaceFormat = formats[i];
+ if (pSurfaceFormats[i].pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSurfaceFormats2KHR: Emulation found unrecognized structure type in "
+ "pSurfaceFormats[%d].pNext - this struct will be ignored",
+ i);
+ }
+ }
+ return res;
+ }
+ }
+}
+
+// ---- VK_EXT_display_surface_counter extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
+ VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceSurfaceCapabilities2EXT(unwrapped_phys_dev, surface, pSurfaceCapabilities);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2EXT(
+ VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(surface);
+ uint8_t icd_index = phys_dev_term->icd_index;
+
+ // Unwrap the surface if needed
+ VkSurfaceKHR unwrapped_surface = surface;
+ if (icd_surface->real_icd_surfaces != NULL && (void *)icd_surface->real_icd_surfaces[icd_index] != NULL) {
+ unwrapped_surface = icd_surface->real_icd_surfaces[icd_index];
+ }
+
+ if (icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT != NULL) {
+ // Pass the call to the driver
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT(phys_dev_term->phys_dev, unwrapped_surface,
+ pSurfaceCapabilities);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSurfaceCapabilities2EXT: Emulating call in ICD \"%s\" using "
+ "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
+ icd_term->scanned_icd->lib_name);
+
+ VkSurfaceCapabilitiesKHR surface_caps;
+ VkResult res =
+ icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, unwrapped_surface, &surface_caps);
+ pSurfaceCapabilities->minImageCount = surface_caps.minImageCount;
+ pSurfaceCapabilities->maxImageCount = surface_caps.maxImageCount;
+ pSurfaceCapabilities->currentExtent = surface_caps.currentExtent;
+ pSurfaceCapabilities->minImageExtent = surface_caps.minImageExtent;
+ pSurfaceCapabilities->maxImageExtent = surface_caps.maxImageExtent;
+ pSurfaceCapabilities->maxImageArrayLayers = surface_caps.maxImageArrayLayers;
+ pSurfaceCapabilities->supportedTransforms = surface_caps.supportedTransforms;
+ pSurfaceCapabilities->currentTransform = surface_caps.currentTransform;
+ pSurfaceCapabilities->supportedCompositeAlpha = surface_caps.supportedCompositeAlpha;
+ pSurfaceCapabilities->supportedUsageFlags = surface_caps.supportedUsageFlags;
+ pSurfaceCapabilities->supportedSurfaceCounters = 0;
+
+ if (pSurfaceCapabilities->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSurfaceCapabilities2EXT: Emulation found unrecognized structure type in "
+ "pSurfaceCapabilities->pNext - this struct will be ignored");
+ }
+
+ return res;
+ }
+}
+
+// ---- VK_EXT_direct_mode_display extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->ReleaseDisplayEXT(unwrapped_phys_dev, display);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ if (icd_term->dispatch.ReleaseDisplayEXT == NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD \"%s\" associated with VkPhysicalDevice does not support vkReleaseDisplayEXT - Consequently, the call is "
+ "invalid because it should not be possible to acquire a display on this device",
+ icd_term->scanned_icd->lib_name);
+ }
+ return icd_term->dispatch.ReleaseDisplayEXT(phys_dev_term->phys_dev, display);
+}
+
+// ---- VK_EXT_acquire_xlib_display extension trampoline/terminators
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+VKAPI_ATTR VkResult VKAPI_CALL AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, VkDisplayKHR display) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->AcquireXlibDisplayEXT(unwrapped_phys_dev, dpy, display);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy,
+ VkDisplayKHR display) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ if (icd_term->dispatch.AcquireXlibDisplayEXT != NULL) {
+ // Pass the call to the driver
+ return icd_term->dispatch.AcquireXlibDisplayEXT(phys_dev_term->phys_dev, dpy, display);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkAcquireXLibDisplayEXT: Emulating call in ICD \"%s\" by returning error", icd_term->scanned_icd->lib_name);
+
+ // Fail for the unsupported command
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, RROutput rrOutput,
+ VkDisplayKHR *pDisplay) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetRandROutputDisplayEXT(unwrapped_phys_dev, dpy, rrOutput, pDisplay);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, RROutput rrOutput,
+ VkDisplayKHR *pDisplay) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ if (icd_term->dispatch.GetRandROutputDisplayEXT != NULL) {
+ // Pass the call to the driver
+ return icd_term->dispatch.GetRandROutputDisplayEXT(phys_dev_term->phys_dev, dpy, rrOutput, pDisplay);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetRandROutputDisplayEXT: Emulating call in ICD \"%s\" by returning null display",
+ icd_term->scanned_icd->lib_name);
+
+ // Return a null handle to indicate this can't be done
+ *pDisplay = VK_NULL_HANDLE;
+ return VK_SUCCESS;
+ }
+}
+
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModes2EXT(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pPresentModeCount,
+ VkPresentModeKHR* pPresentModes) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceSurfacePresentModes2EXT(unwrapped_phys_dev, pSurfaceInfo, pPresentModeCount, pPresentModes);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModes2EXT(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pPresentModeCount,
+ VkPresentModeKHR* pPresentModes) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceSurfacePresentModes2EXT");
+ }
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(pSurfaceInfo->surface);
+ uint8_t icd_index = phys_dev_term->icd_index;
+ if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)icd_surface->real_icd_surfaces[icd_index]) {
+ const VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy = {
+ .sType = pSurfaceInfo->sType,
+ .pNext = pSurfaceInfo->pNext,
+ .surface = icd_surface->real_icd_surfaces[icd_index],
+ };
+ return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, &surface_info_copy, pPresentModeCount, pPresentModes);
+ }
+ return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, pSurfaceInfo, pPresentModeCount, pPresentModes);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetDeviceGroupSurfacePresentModes2EXT(
+ VkDevice device,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkDeviceGroupPresentModeFlagsKHR* pModes) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT(
+ VkDevice device,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkDeviceGroupPresentModeFlagsKHR* pModes) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.GetDeviceGroupSurfacePresentModes2EXT) {
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface;
+ if (NULL != icd_surface->real_icd_surfaces && (VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[icd_index]) {
+ const VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy = {
+ .sType = pSurfaceInfo->sType,
+ .pNext = pSurfaceInfo->pNext,
+ .surface = icd_surface->real_icd_surfaces[icd_index],
+ };
+ return icd_term->dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, &surface_info_copy, pModes);
+ }
+ return icd_term->dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes);
+ }
+ return VK_SUCCESS;
+}
+
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+// ---- VK_EXT_tooling_info extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceToolPropertiesEXT(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pToolCount,
+ VkPhysicalDeviceToolPropertiesEXT* pToolProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceToolPropertiesEXT(unwrapped_phys_dev, pToolCount, pToolProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceToolPropertiesEXT(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pToolCount,
+ VkPhysicalDeviceToolPropertiesEXT* pToolProperties) {
+ return VK_SUCCESS;
+}
diff --git a/thirdparty/vulkan/loader/extension_manual.h b/thirdparty/vulkan/loader/extension_manual.h
new file mode 100644
index 0000000000..fe4287effb
--- /dev/null
+++ b/thirdparty/vulkan/loader/extension_manual.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Mark Young <marky@lunarg.com>
+ */
+
+#pragma once
+
+// ---- Manually added trampoline/terminator functions
+
+// These functions, for whatever reason, require more complex changes than
+// can easily be automatically generated.
+
+VKAPI_ATTR VkResult VKAPI_CALL
+GetPhysicalDeviceExternalImageFormatPropertiesNV(
+ VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
+ VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
+ VkExternalMemoryHandleTypeFlagsNV externalHandleType,
+ VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL
+terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV(
+ VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
+ VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
+ VkExternalMemoryHandleTypeFlagsNV externalHandleType,
+ VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2KHR(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pSurfaceFormatCount,
+ VkSurfaceFormat2KHR* pSurfaceFormats);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pSurfaceFormatCount,
+ VkSurfaceFormat2KHR* pSurfaceFormats);
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
+ VkSurfaceCapabilities2EXT* pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ VkSurfaceCapabilities2EXT* pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display);
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+VKAPI_ATTR VkResult VKAPI_CALL AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display* dpy,
+ VkDisplayKHR display);
+
+VKAPI_ATTR VkResult VKAPI_CALL GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput,
+ VkDisplayKHR* pDisplay);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput,
+ VkDisplayKHR* pDisplay);
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModes2EXT(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pPresentModeCount,
+ VkPresentModeKHR* pPresentModes);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModes2EXT(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pPresentModeCount,
+ VkPresentModeKHR* pPresentModes);
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+VKAPI_ATTR VkResult VKAPI_CALL GetDeviceGroupSurfacePresentModes2EXT(
+ VkDevice device,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkDeviceGroupPresentModeFlagsKHR* pModes);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT(
+ VkDevice device,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkDeviceGroupPresentModeFlagsKHR* pModes);
+
+// ---- VK_EXT_tooling_info extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceToolPropertiesEXT(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pToolCount,
+ VkPhysicalDeviceToolPropertiesEXT* pToolProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceToolPropertiesEXT(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pToolCount,
+ VkPhysicalDeviceToolPropertiesEXT* pToolProperties);
diff --git a/thirdparty/vulkan/loader/gpa_helper.h b/thirdparty/vulkan/loader/gpa_helper.h
new file mode 100644
index 0000000000..832b68c3ef
--- /dev/null
+++ b/thirdparty/vulkan/loader/gpa_helper.h
@@ -0,0 +1,248 @@
+/*
+ *
+ * Copyright (c) 2015-18, 2020 The Khronos Group Inc.
+ * Copyright (c) 2015-18, 2020 Valve Corporation
+ * Copyright (c) 2015-18, 2020 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Jon Ashburn <jon@lunarg.com>
+ */
+
+#include <string.h>
+#include "debug_utils.h"
+#include "wsi.h"
+
+static inline void *trampolineGetProcAddr(struct loader_instance *inst, const char *funcName) {
+ // Don't include or check global functions
+ if (!strcmp(funcName, "vkGetInstanceProcAddr")) return vkGetInstanceProcAddr;
+ if (!strcmp(funcName, "vkDestroyInstance")) return vkDestroyInstance;
+ if (!strcmp(funcName, "vkEnumeratePhysicalDevices")) return vkEnumeratePhysicalDevices;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceFeatures")) return vkGetPhysicalDeviceFeatures;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceFormatProperties")) return vkGetPhysicalDeviceFormatProperties;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceImageFormatProperties")) return vkGetPhysicalDeviceImageFormatProperties;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceSparseImageFormatProperties")) return vkGetPhysicalDeviceSparseImageFormatProperties;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceProperties")) return vkGetPhysicalDeviceProperties;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceQueueFamilyProperties")) return vkGetPhysicalDeviceQueueFamilyProperties;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceMemoryProperties")) return vkGetPhysicalDeviceMemoryProperties;
+ if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties")) return vkEnumerateDeviceLayerProperties;
+ if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties")) return vkEnumerateDeviceExtensionProperties;
+ if (!strcmp(funcName, "vkCreateDevice")) return vkCreateDevice;
+ if (!strcmp(funcName, "vkGetDeviceProcAddr")) return vkGetDeviceProcAddr;
+ if (!strcmp(funcName, "vkDestroyDevice")) return vkDestroyDevice;
+ if (!strcmp(funcName, "vkGetDeviceQueue")) return vkGetDeviceQueue;
+ if (!strcmp(funcName, "vkQueueSubmit")) return vkQueueSubmit;
+ if (!strcmp(funcName, "vkQueueWaitIdle")) return vkQueueWaitIdle;
+ if (!strcmp(funcName, "vkDeviceWaitIdle")) return vkDeviceWaitIdle;
+ if (!strcmp(funcName, "vkAllocateMemory")) return vkAllocateMemory;
+ if (!strcmp(funcName, "vkFreeMemory")) return vkFreeMemory;
+ if (!strcmp(funcName, "vkMapMemory")) return vkMapMemory;
+ if (!strcmp(funcName, "vkUnmapMemory")) return vkUnmapMemory;
+ if (!strcmp(funcName, "vkFlushMappedMemoryRanges")) return vkFlushMappedMemoryRanges;
+ if (!strcmp(funcName, "vkInvalidateMappedMemoryRanges")) return vkInvalidateMappedMemoryRanges;
+ if (!strcmp(funcName, "vkGetDeviceMemoryCommitment")) return vkGetDeviceMemoryCommitment;
+ if (!strcmp(funcName, "vkGetImageSparseMemoryRequirements")) return vkGetImageSparseMemoryRequirements;
+ if (!strcmp(funcName, "vkGetImageMemoryRequirements")) return vkGetImageMemoryRequirements;
+ if (!strcmp(funcName, "vkGetBufferMemoryRequirements")) return vkGetBufferMemoryRequirements;
+ if (!strcmp(funcName, "vkBindImageMemory")) return vkBindImageMemory;
+ if (!strcmp(funcName, "vkBindBufferMemory")) return vkBindBufferMemory;
+ if (!strcmp(funcName, "vkQueueBindSparse")) return vkQueueBindSparse;
+ if (!strcmp(funcName, "vkCreateFence")) return vkCreateFence;
+ if (!strcmp(funcName, "vkDestroyFence")) return vkDestroyFence;
+ if (!strcmp(funcName, "vkGetFenceStatus")) return vkGetFenceStatus;
+ if (!strcmp(funcName, "vkResetFences")) return vkResetFences;
+ if (!strcmp(funcName, "vkWaitForFences")) return vkWaitForFences;
+ if (!strcmp(funcName, "vkCreateSemaphore")) return vkCreateSemaphore;
+ if (!strcmp(funcName, "vkDestroySemaphore")) return vkDestroySemaphore;
+ if (!strcmp(funcName, "vkCreateEvent")) return vkCreateEvent;
+ if (!strcmp(funcName, "vkDestroyEvent")) return vkDestroyEvent;
+ if (!strcmp(funcName, "vkGetEventStatus")) return vkGetEventStatus;
+ if (!strcmp(funcName, "vkSetEvent")) return vkSetEvent;
+ if (!strcmp(funcName, "vkResetEvent")) return vkResetEvent;
+ if (!strcmp(funcName, "vkCreateQueryPool")) return vkCreateQueryPool;
+ if (!strcmp(funcName, "vkDestroyQueryPool")) return vkDestroyQueryPool;
+ if (!strcmp(funcName, "vkGetQueryPoolResults")) return vkGetQueryPoolResults;
+ if (!strcmp(funcName, "vkCreateBuffer")) return vkCreateBuffer;
+ if (!strcmp(funcName, "vkDestroyBuffer")) return vkDestroyBuffer;
+ if (!strcmp(funcName, "vkCreateBufferView")) return vkCreateBufferView;
+ if (!strcmp(funcName, "vkDestroyBufferView")) return vkDestroyBufferView;
+ if (!strcmp(funcName, "vkCreateImage")) return vkCreateImage;
+ if (!strcmp(funcName, "vkDestroyImage")) return vkDestroyImage;
+ if (!strcmp(funcName, "vkGetImageSubresourceLayout")) return vkGetImageSubresourceLayout;
+ if (!strcmp(funcName, "vkCreateImageView")) return vkCreateImageView;
+ if (!strcmp(funcName, "vkDestroyImageView")) return vkDestroyImageView;
+ if (!strcmp(funcName, "vkCreateShaderModule")) return vkCreateShaderModule;
+ if (!strcmp(funcName, "vkDestroyShaderModule")) return vkDestroyShaderModule;
+ if (!strcmp(funcName, "vkCreatePipelineCache")) return vkCreatePipelineCache;
+ if (!strcmp(funcName, "vkDestroyPipelineCache")) return vkDestroyPipelineCache;
+ if (!strcmp(funcName, "vkGetPipelineCacheData")) return vkGetPipelineCacheData;
+ if (!strcmp(funcName, "vkMergePipelineCaches")) return vkMergePipelineCaches;
+ if (!strcmp(funcName, "vkCreateGraphicsPipelines")) return vkCreateGraphicsPipelines;
+ if (!strcmp(funcName, "vkCreateComputePipelines")) return vkCreateComputePipelines;
+ if (!strcmp(funcName, "vkDestroyPipeline")) return vkDestroyPipeline;
+ if (!strcmp(funcName, "vkCreatePipelineLayout")) return vkCreatePipelineLayout;
+ if (!strcmp(funcName, "vkDestroyPipelineLayout")) return vkDestroyPipelineLayout;
+ if (!strcmp(funcName, "vkCreateSampler")) return vkCreateSampler;
+ if (!strcmp(funcName, "vkDestroySampler")) return vkDestroySampler;
+ if (!strcmp(funcName, "vkCreateDescriptorSetLayout")) return vkCreateDescriptorSetLayout;
+ if (!strcmp(funcName, "vkDestroyDescriptorSetLayout")) return vkDestroyDescriptorSetLayout;
+ if (!strcmp(funcName, "vkCreateDescriptorPool")) return vkCreateDescriptorPool;
+ if (!strcmp(funcName, "vkDestroyDescriptorPool")) return vkDestroyDescriptorPool;
+ if (!strcmp(funcName, "vkResetDescriptorPool")) return vkResetDescriptorPool;
+ if (!strcmp(funcName, "vkAllocateDescriptorSets")) return vkAllocateDescriptorSets;
+ if (!strcmp(funcName, "vkFreeDescriptorSets")) return vkFreeDescriptorSets;
+ if (!strcmp(funcName, "vkUpdateDescriptorSets")) return vkUpdateDescriptorSets;
+ if (!strcmp(funcName, "vkCreateFramebuffer")) return vkCreateFramebuffer;
+ if (!strcmp(funcName, "vkDestroyFramebuffer")) return vkDestroyFramebuffer;
+ if (!strcmp(funcName, "vkCreateRenderPass")) return vkCreateRenderPass;
+ if (!strcmp(funcName, "vkDestroyRenderPass")) return vkDestroyRenderPass;
+ if (!strcmp(funcName, "vkGetRenderAreaGranularity")) return vkGetRenderAreaGranularity;
+ if (!strcmp(funcName, "vkCreateCommandPool")) return vkCreateCommandPool;
+ if (!strcmp(funcName, "vkDestroyCommandPool")) return vkDestroyCommandPool;
+ if (!strcmp(funcName, "vkResetCommandPool")) return vkResetCommandPool;
+ if (!strcmp(funcName, "vkAllocateCommandBuffers")) return vkAllocateCommandBuffers;
+ if (!strcmp(funcName, "vkFreeCommandBuffers")) return vkFreeCommandBuffers;
+ if (!strcmp(funcName, "vkBeginCommandBuffer")) return vkBeginCommandBuffer;
+ if (!strcmp(funcName, "vkEndCommandBuffer")) return vkEndCommandBuffer;
+ if (!strcmp(funcName, "vkResetCommandBuffer")) return vkResetCommandBuffer;
+ if (!strcmp(funcName, "vkCmdBindPipeline")) return vkCmdBindPipeline;
+ if (!strcmp(funcName, "vkCmdBindDescriptorSets")) return vkCmdBindDescriptorSets;
+ if (!strcmp(funcName, "vkCmdBindVertexBuffers")) return vkCmdBindVertexBuffers;
+ if (!strcmp(funcName, "vkCmdBindIndexBuffer")) return vkCmdBindIndexBuffer;
+ if (!strcmp(funcName, "vkCmdSetViewport")) return vkCmdSetViewport;
+ if (!strcmp(funcName, "vkCmdSetScissor")) return vkCmdSetScissor;
+ if (!strcmp(funcName, "vkCmdSetLineWidth")) return vkCmdSetLineWidth;
+ if (!strcmp(funcName, "vkCmdSetDepthBias")) return vkCmdSetDepthBias;
+ if (!strcmp(funcName, "vkCmdSetBlendConstants")) return vkCmdSetBlendConstants;
+ if (!strcmp(funcName, "vkCmdSetDepthBounds")) return vkCmdSetDepthBounds;
+ if (!strcmp(funcName, "vkCmdSetStencilCompareMask")) return vkCmdSetStencilCompareMask;
+ if (!strcmp(funcName, "vkCmdSetStencilWriteMask")) return vkCmdSetStencilWriteMask;
+ if (!strcmp(funcName, "vkCmdSetStencilReference")) return vkCmdSetStencilReference;
+ if (!strcmp(funcName, "vkCmdDraw")) return vkCmdDraw;
+ if (!strcmp(funcName, "vkCmdDrawIndexed")) return vkCmdDrawIndexed;
+ if (!strcmp(funcName, "vkCmdDrawIndirect")) return vkCmdDrawIndirect;
+ if (!strcmp(funcName, "vkCmdDrawIndexedIndirect")) return vkCmdDrawIndexedIndirect;
+ if (!strcmp(funcName, "vkCmdDispatch")) return vkCmdDispatch;
+ if (!strcmp(funcName, "vkCmdDispatchIndirect")) return vkCmdDispatchIndirect;
+ if (!strcmp(funcName, "vkCmdCopyBuffer")) return vkCmdCopyBuffer;
+ if (!strcmp(funcName, "vkCmdCopyImage")) return vkCmdCopyImage;
+ if (!strcmp(funcName, "vkCmdBlitImage")) return vkCmdBlitImage;
+ if (!strcmp(funcName, "vkCmdCopyBufferToImage")) return vkCmdCopyBufferToImage;
+ if (!strcmp(funcName, "vkCmdCopyImageToBuffer")) return vkCmdCopyImageToBuffer;
+ if (!strcmp(funcName, "vkCmdUpdateBuffer")) return vkCmdUpdateBuffer;
+ if (!strcmp(funcName, "vkCmdFillBuffer")) return vkCmdFillBuffer;
+ if (!strcmp(funcName, "vkCmdClearColorImage")) return vkCmdClearColorImage;
+ if (!strcmp(funcName, "vkCmdClearDepthStencilImage")) return vkCmdClearDepthStencilImage;
+ if (!strcmp(funcName, "vkCmdClearAttachments")) return vkCmdClearAttachments;
+ if (!strcmp(funcName, "vkCmdResolveImage")) return vkCmdResolveImage;
+ if (!strcmp(funcName, "vkCmdSetEvent")) return vkCmdSetEvent;
+ if (!strcmp(funcName, "vkCmdResetEvent")) return vkCmdResetEvent;
+ if (!strcmp(funcName, "vkCmdWaitEvents")) return vkCmdWaitEvents;
+ if (!strcmp(funcName, "vkCmdPipelineBarrier")) return vkCmdPipelineBarrier;
+ if (!strcmp(funcName, "vkCmdBeginQuery")) return vkCmdBeginQuery;
+ if (!strcmp(funcName, "vkCmdEndQuery")) return vkCmdEndQuery;
+ if (!strcmp(funcName, "vkCmdResetQueryPool")) return vkCmdResetQueryPool;
+ if (!strcmp(funcName, "vkCmdWriteTimestamp")) return vkCmdWriteTimestamp;
+ if (!strcmp(funcName, "vkCmdCopyQueryPoolResults")) return vkCmdCopyQueryPoolResults;
+ if (!strcmp(funcName, "vkCmdPushConstants")) return vkCmdPushConstants;
+ if (!strcmp(funcName, "vkCmdBeginRenderPass")) return vkCmdBeginRenderPass;
+ if (!strcmp(funcName, "vkCmdNextSubpass")) return vkCmdNextSubpass;
+ if (!strcmp(funcName, "vkCmdEndRenderPass")) return vkCmdEndRenderPass;
+ if (!strcmp(funcName, "vkCmdExecuteCommands")) return vkCmdExecuteCommands;
+
+ // Core 1.1 functions
+ if (!strcmp(funcName, "vkEnumeratePhysicalDeviceGroups")) return vkEnumeratePhysicalDeviceGroups;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceFeatures2")) return vkGetPhysicalDeviceFeatures2;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceProperties2")) return vkGetPhysicalDeviceProperties2;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceFormatProperties2")) return vkGetPhysicalDeviceFormatProperties2;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceImageFormatProperties2")) return vkGetPhysicalDeviceImageFormatProperties2;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceQueueFamilyProperties2")) return vkGetPhysicalDeviceQueueFamilyProperties2;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceMemoryProperties2")) return vkGetPhysicalDeviceMemoryProperties2;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceSparseImageFormatProperties2"))
+ return vkGetPhysicalDeviceSparseImageFormatProperties2;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceExternalBufferProperties")) return vkGetPhysicalDeviceExternalBufferProperties;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceExternalSemaphoreProperties")) return vkGetPhysicalDeviceExternalSemaphoreProperties;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceExternalFenceProperties")) return vkGetPhysicalDeviceExternalFenceProperties;
+ if (!strcmp(funcName, "vkBindBufferMemory2")) return vkBindBufferMemory2;
+ if (!strcmp(funcName, "vkBindImageMemory2")) return vkBindImageMemory2;
+ if (!strcmp(funcName, "vkGetDeviceGroupPeerMemoryFeatures")) return vkGetDeviceGroupPeerMemoryFeatures;
+ if (!strcmp(funcName, "vkCmdSetDeviceMask")) return vkCmdSetDeviceMask;
+ if (!strcmp(funcName, "vkCmdDispatchBase")) return vkCmdDispatchBase;
+ if (!strcmp(funcName, "vkGetImageMemoryRequirements2")) return vkGetImageMemoryRequirements2;
+ if (!strcmp(funcName, "vkTrimCommandPool")) return vkTrimCommandPool;
+ if (!strcmp(funcName, "vkGetDeviceQueue2")) return vkGetDeviceQueue2;
+ if (!strcmp(funcName, "vkCreateSamplerYcbcrConversion")) return vkCreateSamplerYcbcrConversion;
+ if (!strcmp(funcName, "vkDestroySamplerYcbcrConversion")) return vkDestroySamplerYcbcrConversion;
+ if (!strcmp(funcName, "vkGetDescriptorSetLayoutSupport")) return vkGetDescriptorSetLayoutSupport;
+ if (!strcmp(funcName, "vkCreateDescriptorUpdateTemplate")) return vkCreateDescriptorUpdateTemplate;
+ if (!strcmp(funcName, "vkDestroyDescriptorUpdateTemplate")) return vkDestroyDescriptorUpdateTemplate;
+ if (!strcmp(funcName, "vkUpdateDescriptorSetWithTemplate")) return vkUpdateDescriptorSetWithTemplate;
+ if (!strcmp(funcName, "vkGetImageSparseMemoryRequirements2")) return vkGetImageSparseMemoryRequirements2;
+ if (!strcmp(funcName, "vkGetBufferMemoryRequirements2")) return vkGetBufferMemoryRequirements2;
+
+ // Core 1.2 functions
+ if (!strcmp(funcName, "vkCreateRenderPass2")) return vkCreateRenderPass2;
+ if (!strcmp(funcName, "vkCmdBeginRenderPass2")) return vkCmdBeginRenderPass2;
+ if (!strcmp(funcName, "vkCmdNextSubpass2")) return vkCmdNextSubpass2;
+ if (!strcmp(funcName, "vkCmdEndRenderPass2")) return vkCmdEndRenderPass2;
+ if (!strcmp(funcName, "vkCmdDrawIndirectCount")) return vkCmdDrawIndirectCount;
+ if (!strcmp(funcName, "vkCmdDrawIndexedIndirectCount")) return vkCmdDrawIndexedIndirectCount;
+ if (!strcmp(funcName, "vkGetSemaphoreCounterValue")) return vkGetSemaphoreCounterValue;
+ if (!strcmp(funcName, "vkWaitSemaphores")) return vkWaitSemaphores;
+ if (!strcmp(funcName, "vkSignalSemaphore")) return vkSignalSemaphore;
+ if (!strcmp(funcName, "vkGetBufferDeviceAddress")) return vkGetBufferDeviceAddress;
+ if (!strcmp(funcName, "vkGetBufferOpaqueCaptureAddress")) return vkGetBufferOpaqueCaptureAddress;
+ if (!strcmp(funcName, "vkGetDeviceMemoryOpaqueCaptureAddress")) return vkGetDeviceMemoryOpaqueCaptureAddress;
+ if (!strcmp(funcName, "vkResetQueryPool")) return vkResetQueryPool;
+
+ // Instance extensions
+ void *addr;
+ if (debug_utils_InstanceGpa(inst, funcName, &addr)) return addr;
+
+ if (wsi_swapchain_instance_gpa(inst, funcName, &addr)) return addr;
+
+ if (extension_instance_gpa(inst, funcName, &addr)) return addr;
+
+ // Unknown physical device extensions
+ if (loader_phys_dev_ext_gpa(inst, funcName, true, &addr, NULL)) return addr;
+
+ // Unknown device extensions
+ addr = loader_dev_ext_gpa(inst, funcName);
+ return addr;
+}
+
+static inline void *globalGetProcAddr(const char *name) {
+ if (!name || name[0] != 'v' || name[1] != 'k') return NULL;
+
+ name += 2;
+ if (!strcmp(name, "CreateInstance")) return vkCreateInstance;
+ if (!strcmp(name, "EnumerateInstanceExtensionProperties")) return vkEnumerateInstanceExtensionProperties;
+ if (!strcmp(name, "EnumerateInstanceLayerProperties")) return vkEnumerateInstanceLayerProperties;
+ if (!strcmp(name, "EnumerateInstanceVersion")) return vkEnumerateInstanceVersion;
+
+ return NULL;
+}
+
+static inline void *loader_non_passthrough_gdpa(const char *name) {
+ if (!name || name[0] != 'v' || name[1] != 'k') return NULL;
+
+ name += 2;
+
+ if (!strcmp(name, "GetDeviceProcAddr")) return vkGetDeviceProcAddr;
+ if (!strcmp(name, "DestroyDevice")) return vkDestroyDevice;
+ if (!strcmp(name, "GetDeviceQueue")) return vkGetDeviceQueue;
+ if (!strcmp(name, "GetDeviceQueue2")) return vkGetDeviceQueue2;
+ if (!strcmp(name, "AllocateCommandBuffers")) return vkAllocateCommandBuffers;
+
+ return NULL;
+}
diff --git a/thirdparty/vulkan/loader/loader.c b/thirdparty/vulkan/loader/loader.c
new file mode 100644
index 0000000000..c7cdb47122
--- /dev/null
+++ b/thirdparty/vulkan/loader/loader.c
@@ -0,0 +1,8100 @@
+/*
+ *
+ * Copyright (c) 2014-2020 The Khronos Group Inc.
+ * Copyright (c) 2014-2020 Valve Corporation
+ * Copyright (c) 2014-2020 LunarG, Inc.
+ * Copyright (C) 2015 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ *
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Mark Young <marky@lunarg.com>
+ * Author: Lenny Komow <lenny@lunarg.com>
+ *
+ */
+
+// This needs to be defined first, or else we'll get redefinitions on NTSTATUS values
+#ifdef _WIN32
+#define UMDF_USING_NTSTATUS
+#include <ntstatus.h>
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stddef.h>
+
+#if defined(__APPLE__)
+#include <CoreFoundation/CoreFoundation.h>
+#include <sys/param.h>
+#endif
+
+// Time related functions
+#include <time.h>
+
+#include <sys/types.h>
+#if defined(_WIN32)
+#include "dirent_on_windows.h"
+#else // _WIN32
+#include <dirent.h>
+#endif // _WIN32
+#include "vk_loader_platform.h"
+#include "loader.h"
+#include "gpa_helper.h"
+#include "debug_utils.h"
+#include "wsi.h"
+#include "vulkan/vk_icd.h"
+#include "cJSON.h"
+#include "murmurhash.h"
+
+#if defined(_WIN32)
+#include <cfgmgr32.h>
+#include <initguid.h>
+#include <devpkey.h>
+#include <winternl.h>
+#include "adapters.h"
+#include "dxgi_loader.h"
+#endif
+
+// This is a CMake generated file with #defines for any functions/includes
+// that it found present. This is currently necessary to properly determine
+// if secure_getenv or __secure_getenv are present
+#if !defined(VULKAN_NON_CMAKE_BUILD)
+#include "loader_cmake_config.h"
+#endif // !defined(VULKAN_NON_CMAKE_BUILD)
+
+// Generated file containing all the extension data
+#include "vk_loader_extensions.c"
+
+// Override layer information
+#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
+
+struct loader_struct loader = {0};
+// TLS for instance for alloc/free callbacks
+THREAD_LOCAL_DECL struct loader_instance *tls_instance;
+
+static size_t loader_platform_combine_path(char *dest, size_t len, ...);
+
+struct loader_phys_dev_per_icd {
+ uint32_t count;
+ VkPhysicalDevice *phys_devs;
+ struct loader_icd_term *this_icd_term;
+};
+
+enum loader_debug {
+ LOADER_INFO_BIT = 0x01,
+ LOADER_WARN_BIT = 0x02,
+ LOADER_PERF_BIT = 0x04,
+ LOADER_ERROR_BIT = 0x08,
+ LOADER_DEBUG_BIT = 0x10,
+};
+
+uint32_t g_loader_debug = 0;
+uint32_t g_loader_log_msgs = 0;
+
+enum loader_data_files_type {
+ LOADER_DATA_FILE_MANIFEST_ICD = 0,
+ LOADER_DATA_FILE_MANIFEST_LAYER,
+ LOADER_DATA_FILE_NUM_TYPES // Not a real field, used for possible loop terminator
+};
+
+// thread safety lock for accessing global data structures such as "loader"
+// all entrypoints on the instance chain need to be locked except GPA
+// additionally CreateDevice and DestroyDevice needs to be locked
+loader_platform_thread_mutex loader_lock;
+loader_platform_thread_mutex loader_json_lock;
+
+LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
+
+// This loader supports Vulkan API version 1.1
+uint32_t loader_major_version = 1;
+uint32_t loader_minor_version = 2;
+
+void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope alloc_scope) {
+ void *pMemory = NULL;
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (instance && instance->alloc_callbacks.pfnAllocation) {
+ // These are internal structures, so it's best to align everything to
+ // the largest unit size which is the size of a uint64_t.
+ pMemory = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, sizeof(uint64_t), alloc_scope);
+ } else {
+#endif
+ pMemory = malloc(size);
+ }
+
+ return pMemory;
+}
+
+void loader_instance_heap_free(const struct loader_instance *instance, void *pMemory) {
+ if (pMemory != NULL) {
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (instance && instance->alloc_callbacks.pfnFree) {
+ instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
+ } else {
+#endif
+ free(pMemory);
+ }
+ }
+}
+
+void *loader_instance_heap_realloc(const struct loader_instance *instance, void *pMemory, size_t orig_size, size_t size,
+ VkSystemAllocationScope alloc_scope) {
+ void *pNewMem = NULL;
+ if (pMemory == NULL || orig_size == 0) {
+ pNewMem = loader_instance_heap_alloc(instance, size, alloc_scope);
+ } else if (size == 0) {
+ loader_instance_heap_free(instance, pMemory);
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+#else
+ } else if (instance && instance->alloc_callbacks.pfnReallocation) {
+ // These are internal structures, so it's best to align everything to
+ // the largest unit size which is the size of a uint64_t.
+ pNewMem = instance->alloc_callbacks.pfnReallocation(instance->alloc_callbacks.pUserData, pMemory, size, sizeof(uint64_t),
+ alloc_scope);
+#endif
+ } else {
+ pNewMem = realloc(pMemory, size);
+ }
+ return pNewMem;
+}
+
+void *loader_instance_tls_heap_alloc(size_t size) {
+ return loader_instance_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+}
+
+void loader_instance_tls_heap_free(void *pMemory) { loader_instance_heap_free(tls_instance, pMemory); }
+
+void *loader_device_heap_alloc(const struct loader_device *device, size_t size, VkSystemAllocationScope alloc_scope) {
+ void *pMemory = NULL;
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (device && device->alloc_callbacks.pfnAllocation) {
+ // These are internal structures, so it's best to align everything to
+ // the largest unit size which is the size of a uint64_t.
+ pMemory = device->alloc_callbacks.pfnAllocation(device->alloc_callbacks.pUserData, size, sizeof(uint64_t), alloc_scope);
+ } else {
+#endif
+ pMemory = malloc(size);
+ }
+ return pMemory;
+}
+
+void loader_device_heap_free(const struct loader_device *device, void *pMemory) {
+ if (pMemory != NULL) {
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (device && device->alloc_callbacks.pfnFree) {
+ device->alloc_callbacks.pfnFree(device->alloc_callbacks.pUserData, pMemory);
+ } else {
+#endif
+ free(pMemory);
+ }
+ }
+}
+
+void *loader_device_heap_realloc(const struct loader_device *device, void *pMemory, size_t orig_size, size_t size,
+ VkSystemAllocationScope alloc_scope) {
+ void *pNewMem = NULL;
+ if (pMemory == NULL || orig_size == 0) {
+ pNewMem = loader_device_heap_alloc(device, size, alloc_scope);
+ } else if (size == 0) {
+ loader_device_heap_free(device, pMemory);
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+#else
+ } else if (device && device->alloc_callbacks.pfnReallocation) {
+ // These are internal structures, so it's best to align everything to
+ // the largest unit size which is the size of a uint64_t.
+ pNewMem = device->alloc_callbacks.pfnReallocation(device->alloc_callbacks.pUserData, pMemory, size, sizeof(uint64_t),
+ alloc_scope);
+#endif
+ } else {
+ pNewMem = realloc(pMemory, size);
+ }
+ return pNewMem;
+}
+
+// Environment variables
+#if defined(__linux__) || defined(__APPLE__)
+
+static inline bool IsHighIntegrity() {
+ return geteuid() != getuid() || getegid() != getgid();
+}
+
+static inline char *loader_getenv(const char *name, const struct loader_instance *inst) {
+ // No allocation of memory necessary for Linux, but we should at least touch
+ // the inst pointer to get rid of compiler warnings.
+ (void)inst;
+ return getenv(name);
+}
+
+static inline char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
+ char *out;
+#if defined(__APPLE__)
+ // Apple does not appear to have a secure getenv implementation.
+ // The main difference between secure getenv and getenv is that secure getenv
+ // returns NULL if the process is being run with elevated privileges by a normal user.
+ // The idea is to prevent the reading of malicious environment variables by a process
+ // that can do damage.
+ // This algorithm is derived from glibc code that sets an internal
+ // variable (__libc_enable_secure) if the process is running under setuid or setgid.
+ return IsHighIntegrity() ? NULL : loader_getenv(name, inst);
+#else
+// Linux
+#if defined(HAVE_SECURE_GETENV) && !defined(USE_UNSAFE_FILE_SEARCH)
+ (void)inst;
+ out = secure_getenv(name);
+#elif defined(HAVE___SECURE_GETENV) && !defined(USE_UNSAFE_FILE_SEARCH)
+ (void)inst;
+ out = __secure_getenv(name);
+#else
+ out = loader_getenv(name, inst);
+#endif
+#endif
+ if (out == NULL) {
+ loader_log(inst, LOADER_INFO_BIT, 0,
+ "Loader is running with elevated permissions. Environment variable %s will be ignored.", name);
+ }
+ return out;
+}
+
+static inline void loader_free_getenv(char *val, const struct loader_instance *inst) {
+ // No freeing of memory necessary for Linux, but we should at least touch
+ // the val and inst pointers to get rid of compiler warnings.
+ (void)val;
+ (void)inst;
+}
+
+#elif defined(WIN32)
+
+static inline bool IsHighIntegrity() {
+ HANDLE process_token;
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) {
+ // Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD.
+ uint8_t mandatory_label_buffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)];
+ DWORD buffer_size;
+ if (GetTokenInformation(process_token, TokenIntegrityLevel, mandatory_label_buffer, sizeof(mandatory_label_buffer),
+ &buffer_size) != 0) {
+ const TOKEN_MANDATORY_LABEL *mandatory_label = (const TOKEN_MANDATORY_LABEL *)mandatory_label_buffer;
+ const DWORD sub_authority_count = *GetSidSubAuthorityCount(mandatory_label->Label.Sid);
+ const DWORD integrity_level = *GetSidSubAuthority(mandatory_label->Label.Sid, sub_authority_count - 1);
+
+ CloseHandle(process_token);
+ return integrity_level > SECURITY_MANDATORY_MEDIUM_RID;
+ }
+
+ CloseHandle(process_token);
+ }
+
+ return false;
+}
+
+static inline char *loader_getenv(const char *name, const struct loader_instance *inst) {
+ char *retVal;
+ DWORD valSize;
+
+ valSize = GetEnvironmentVariableA(name, NULL, 0);
+
+ // valSize DOES include the null terminator, so for any set variable
+ // will always be at least 1. If it's 0, the variable wasn't set.
+ if (valSize == 0) return NULL;
+
+ // Allocate the space necessary for the registry entry
+ if (NULL != inst && NULL != inst->alloc_callbacks.pfnAllocation) {
+ retVal = (char *)inst->alloc_callbacks.pfnAllocation(inst->alloc_callbacks.pUserData, valSize, sizeof(char *),
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ } else {
+ retVal = (char *)malloc(valSize);
+ }
+
+ if (NULL != retVal) {
+ GetEnvironmentVariableA(name, retVal, valSize);
+ }
+
+ return retVal;
+}
+
+static inline char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
+#if !defined(USE_UNSAFE_FILE_SEARCH)
+ if (IsHighIntegrity()) {
+ loader_log(inst, LOADER_INFO_BIT, 0,
+ "Loader is running with elevated permissions. Environment variable %s will be ignored.", name);
+ return NULL;
+ }
+#endif
+
+ return loader_getenv(name, inst);
+}
+
+static inline void loader_free_getenv(char *val, const struct loader_instance *inst) {
+ if (NULL != inst && NULL != inst->alloc_callbacks.pfnFree) {
+ inst->alloc_callbacks.pfnFree(inst->alloc_callbacks.pUserData, val);
+ } else {
+ free((void *)val);
+ }
+}
+
+#else
+
+static inline char *loader_getenv(const char *name, const struct loader_instance *inst) {
+ // stub func
+ (void)inst;
+ (void)name;
+ return NULL;
+}
+static inline void loader_free_getenv(char *val, const struct loader_instance *inst) {
+ // stub func
+ (void)val;
+ (void)inst;
+}
+
+#endif
+
+void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...) {
+ char msg[512];
+ char cmd_line_msg[512];
+ size_t cmd_line_size = sizeof(cmd_line_msg);
+ va_list ap;
+ int ret;
+
+ va_start(ap, format);
+ ret = vsnprintf(msg, sizeof(msg), format, ap);
+ if ((ret >= (int)sizeof(msg)) || ret < 0) {
+ msg[sizeof(msg) - 1] = '\0';
+ }
+ va_end(ap);
+
+ if (inst) {
+ VkDebugUtilsMessageSeverityFlagBitsEXT severity = 0;
+ VkDebugUtilsMessageTypeFlagsEXT type;
+ VkDebugUtilsMessengerCallbackDataEXT callback_data;
+ VkDebugUtilsObjectNameInfoEXT object_name;
+
+ if ((msg_type & LOADER_INFO_BIT) != 0) {
+ severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ } else if ((msg_type & LOADER_WARN_BIT) != 0) {
+ severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ } else if ((msg_type & LOADER_ERROR_BIT) != 0) {
+ severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ } else if ((msg_type & LOADER_DEBUG_BIT) != 0) {
+ severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ }
+
+ if ((msg_type & LOADER_PERF_BIT) != 0) {
+ type = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ } else {
+ type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ }
+
+ callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+ callback_data.pNext = NULL;
+ callback_data.flags = 0;
+ callback_data.pMessageIdName = "Loader Message";
+ callback_data.messageIdNumber = 0;
+ callback_data.pMessage = msg;
+ callback_data.queueLabelCount = 0;
+ callback_data.pQueueLabels = NULL;
+ callback_data.cmdBufLabelCount = 0;
+ callback_data.pCmdBufLabels = NULL;
+ callback_data.objectCount = 1;
+ callback_data.pObjects = &object_name;
+ object_name.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ object_name.pNext = NULL;
+ object_name.objectType = VK_OBJECT_TYPE_INSTANCE;
+ object_name.objectHandle = (uint64_t)(uintptr_t)inst;
+ object_name.pObjectName = NULL;
+
+ util_SubmitDebugUtilsMessageEXT(inst, severity, type, &callback_data);
+ }
+
+ if (!(msg_type & g_loader_log_msgs)) {
+ return;
+ }
+
+ cmd_line_msg[0] = '\0';
+ cmd_line_size -= 1;
+ size_t original_size = cmd_line_size;
+
+ if ((msg_type & LOADER_INFO_BIT) != 0) {
+ strncat(cmd_line_msg, "INFO", cmd_line_size);
+ cmd_line_size -= 4;
+ }
+ if ((msg_type & LOADER_WARN_BIT) != 0) {
+ if (cmd_line_size != original_size) {
+ strncat(cmd_line_msg, " | ", cmd_line_size);
+ cmd_line_size -= 3;
+ }
+ strncat(cmd_line_msg, "WARNING", cmd_line_size);
+ cmd_line_size -= 7;
+ }
+ if ((msg_type & LOADER_PERF_BIT) != 0) {
+ if (cmd_line_size != original_size) {
+ strncat(cmd_line_msg, " | ", cmd_line_size);
+ cmd_line_size -= 3;
+ }
+ strncat(cmd_line_msg, "PERF", cmd_line_size);
+ cmd_line_size -= 4;
+ }
+ if ((msg_type & LOADER_ERROR_BIT) != 0) {
+ if (cmd_line_size != original_size) {
+ strncat(cmd_line_msg, " | ", cmd_line_size);
+ cmd_line_size -= 3;
+ }
+ strncat(cmd_line_msg, "ERROR", cmd_line_size);
+ cmd_line_size -= 5;
+ }
+ if ((msg_type & LOADER_DEBUG_BIT) != 0) {
+ if (cmd_line_size != original_size) {
+ strncat(cmd_line_msg, " | ", cmd_line_size);
+ cmd_line_size -= 3;
+ }
+ strncat(cmd_line_msg, "DEBUG", cmd_line_size);
+ cmd_line_size -= 5;
+ }
+ if (cmd_line_size != original_size) {
+ strncat(cmd_line_msg, ": ", cmd_line_size);
+ cmd_line_size -= 2;
+ }
+
+ if (0 < cmd_line_size) {
+ // If the message is too long, trim it down
+ if (strlen(msg) > cmd_line_size) {
+ msg[cmd_line_size - 1] = '\0';
+ }
+ strncat(cmd_line_msg, msg, cmd_line_size);
+ } else {
+ // Shouldn't get here, but check to make sure if we've already overrun
+ // the string boundary
+ assert(false);
+ }
+
+#if defined(WIN32)
+ OutputDebugString(cmd_line_msg);
+ OutputDebugString("\n");
+#endif
+
+ fputs(cmd_line_msg, stderr);
+ fputc('\n', stderr);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL vkSetInstanceDispatch(VkInstance instance, void *object) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ if (!inst) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "vkSetInstanceDispatch: Can not retrieve Instance "
+ "dispatch table.");
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ loader_set_dispatch(object, inst->disp);
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL vkSetDeviceDispatch(VkDevice device, void *object) {
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL);
+
+ if (NULL == icd_term) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ loader_set_dispatch(object, &dev->loader_dispatch);
+ return VK_SUCCESS;
+}
+
+#if defined(_WIN32)
+
+// Append the JSON path data to the list and allocate/grow the list if it's not large enough.
+// Function returns true if filename was appended to reg_data list.
+// Caller should free reg_data.
+static bool loaderAddJsonEntry(const struct loader_instance *inst,
+ char **reg_data, // list of JSON files
+ PDWORD total_size, // size of reg_data
+ LPCSTR key_name, // key name - used for debug prints - i.e. VulkanDriverName
+ DWORD key_type, // key data type
+ LPSTR json_path, // JSON string to add to the list reg_data
+ DWORD json_size, // size in bytes of json_path
+ VkResult *result) {
+ // Check for and ignore duplicates.
+ if (*reg_data && strstr(*reg_data, json_path)) {
+ // Success. The json_path is already in the list.
+ return true;
+ }
+
+ if (NULL == *reg_data) {
+ *reg_data = loader_instance_heap_alloc(inst, *total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == *reg_data) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderAddJsonEntry: Failed to allocate space for registry data for key %s", json_path);
+ *result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ return false;
+ }
+ *reg_data[0] = '\0';
+ } else if (strlen(*reg_data) + json_size + 1 > *total_size) {
+ void *new_ptr =
+ loader_instance_heap_realloc(inst, *reg_data, *total_size, *total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_ptr) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderAddJsonEntry: Failed to reallocate space for registry value of size %d for key %s", *total_size * 2,
+ json_path);
+ *result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ return false;
+ }
+ *reg_data = new_ptr;
+ *total_size *= 2;
+ }
+
+ for (char *curr_filename = json_path; curr_filename[0] != '\0'; curr_filename += strlen(curr_filename) + 1) {
+ if (strlen(*reg_data) == 0) {
+ (void)snprintf(*reg_data, json_size + 1, "%s", curr_filename);
+ } else {
+ (void)snprintf(*reg_data + strlen(*reg_data), json_size + 2, "%c%s", PATH_SEPARATOR, curr_filename);
+ }
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "%s: Located json file \"%s\" from PnP registry: %s", __FUNCTION__,
+ curr_filename, key_name);
+
+ if (key_type == REG_SZ) {
+ break;
+ }
+ }
+ return true;
+}
+
+// Find the list of registry files (names VulkanDriverName/VulkanDriverNameWow) in hkr.
+//
+// This function looks for filename in given device handle, filename is then added to return list
+// function return true if filename was appended to reg_data list
+// If error occurs result is updated with failure reason
+bool loaderGetDeviceRegistryEntry(const struct loader_instance *inst, char **reg_data, PDWORD total_size, DEVINST dev_id,
+ LPCSTR value_name, VkResult *result) {
+ HKEY hkrKey = INVALID_HANDLE_VALUE;
+ DWORD requiredSize, data_type;
+ char *manifest_path = NULL;
+ bool found = false;
+
+ if (NULL == total_size || NULL == reg_data) {
+ *result = VK_ERROR_INITIALIZATION_FAILED;
+ return false;
+ }
+
+ CONFIGRET status = CM_Open_DevNode_Key(dev_id, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &hkrKey, CM_REGISTRY_SOFTWARE);
+ if (status != CR_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loaderGetDeviceRegistryEntry: Failed to open registry key for DeviceID(%d)", dev_id);
+ *result = VK_ERROR_INITIALIZATION_FAILED;
+ return false;
+ }
+
+ // query value
+ LSTATUS ret = RegQueryValueEx(
+ hkrKey,
+ value_name,
+ NULL,
+ NULL,
+ NULL,
+ &requiredSize);
+
+ if (ret != ERROR_SUCCESS) {
+ if (ret == ERROR_FILE_NOT_FOUND) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "loaderGetDeviceRegistryEntry: Device ID(%d) Does not contain a value for \"%s\"", dev_id, value_name);
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "loaderGetDeviceRegistryEntry: DeviceID(%d) Failed to obtain %s size", dev_id, value_name);
+ }
+ goto out;
+ }
+
+ manifest_path = loader_instance_heap_alloc(inst, requiredSize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (manifest_path == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderGetDeviceRegistryEntry: Failed to allocate space for DriverName.");
+ *result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ ret = RegQueryValueEx(
+ hkrKey,
+ value_name,
+ NULL,
+ &data_type,
+ (BYTE *)manifest_path,
+ &requiredSize
+ );
+
+ if (ret != ERROR_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderGetDeviceRegistryEntry: DeviceID(%d) Failed to obtain %s", value_name);
+
+ *result = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ if (data_type != REG_SZ && data_type != REG_MULTI_SZ) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderGetDeviceRegistryEntry: Invalid %s data type. Expected REG_SZ or REG_MULTI_SZ.", value_name);
+ *result = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ found = loaderAddJsonEntry(inst, reg_data, total_size, value_name, data_type, manifest_path, requiredSize, result);
+
+out:
+ if (manifest_path != NULL) {
+ loader_instance_heap_free(inst, manifest_path);
+ }
+ RegCloseKey(hkrKey);
+ return found;
+}
+
+// Find the list of registry files (names VulkanDriverName/VulkanDriverNameWow) in hkr .
+//
+// This function looks for display devices and childish software components
+// for a list of files which are added to a returned list (function return
+// value).
+// Function return is a string with a ';' separated list of filenames.
+// Function return is NULL if no valid name/value pairs are found in the key,
+// or the key is not found.
+//
+// *reg_data contains a string list of filenames as pointer.
+// When done using the returned string list, the caller should free the pointer.
+VkResult loaderGetDeviceRegistryFiles(const struct loader_instance *inst, char **reg_data, PDWORD reg_data_size,
+ LPCSTR value_name) {
+ static const wchar_t *softwareComponentGUID = L"{5c4c3332-344d-483c-8739-259e934c9cc8}";
+ static const wchar_t *displayGUID = L"{4d36e968-e325-11ce-bfc1-08002be10318}";
+ const ULONG flags = CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT;
+
+ wchar_t childGuid[MAX_GUID_STRING_LEN + 2]; // +2 for brackets {}
+ ULONG childGuidSize = sizeof(childGuid);
+
+ DEVINST devID = 0, childID = 0;
+ wchar_t *pDeviceNames = NULL;
+ ULONG deviceNamesSize = 0;
+ VkResult result = VK_SUCCESS;
+ bool found = false;
+
+ if (NULL == reg_data) {
+ result = VK_ERROR_INITIALIZATION_FAILED;
+ return result;
+ }
+
+ // if after obtaining the DeviceNameSize, new device is added start over
+ do {
+ CM_Get_Device_ID_List_SizeW(&deviceNamesSize, displayGUID, flags);
+
+ if (pDeviceNames != NULL) {
+ loader_instance_heap_free(inst, pDeviceNames);
+ }
+
+ pDeviceNames = loader_instance_heap_alloc(inst, deviceNamesSize * sizeof(wchar_t), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (pDeviceNames == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderGetDeviceRegistryFiles: Failed to allocate space for display device names.");
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ return result;
+ }
+ } while (CM_Get_Device_ID_ListW(displayGUID, pDeviceNames, deviceNamesSize, flags) == CR_BUFFER_SMALL);
+
+ if (pDeviceNames) {
+ for (wchar_t *deviceName = pDeviceNames; *deviceName; deviceName += wcslen(deviceName) + 1) {
+ CONFIGRET status = CM_Locate_DevNodeW(&devID, deviceName, CM_LOCATE_DEVNODE_NORMAL);
+ if (CR_SUCCESS != status) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: failed to open DevNode %ls",
+ deviceName);
+ continue;
+ }
+ ULONG ulStatus, ulProblem;
+ status = CM_Get_DevNode_Status(&ulStatus, &ulProblem, devID, 0);
+
+ if (CR_SUCCESS != status)
+ {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: failed to probe device status %ls",
+ deviceName);
+ continue;
+ }
+ if ((ulStatus & DN_HAS_PROBLEM) && (ulProblem == CM_PROB_NEED_RESTART || ulProblem == DN_NEED_RESTART)) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "loaderGetDeviceRegistryFiles: device %ls is pending reboot, skipping ...", deviceName);
+ continue;
+ }
+
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: opening device %ls", deviceName);
+
+ if (loaderGetDeviceRegistryEntry(inst, reg_data, reg_data_size, devID, value_name, &result)) {
+ found = true;
+ continue;
+ }
+ else if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
+ break;
+ }
+
+ status = CM_Get_Child(&childID, devID, 0);
+ if (status != CR_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "loaderGetDeviceRegistryFiles: unable to open child-device error:%d", status);
+ continue;
+ }
+
+ do {
+ wchar_t buffer[MAX_DEVICE_ID_LEN];
+ CM_Get_Device_IDW(childID, buffer, MAX_DEVICE_ID_LEN, 0);
+
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "loaderGetDeviceRegistryFiles: Opening child device %d - %ls", childID, buffer);
+
+ status = CM_Get_DevNode_Registry_PropertyW(childID, CM_DRP_CLASSGUID, NULL, &childGuid, &childGuidSize, 0);
+ if (status != CR_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderGetDeviceRegistryFiles: unable to obtain GUID for:%d error:%d", childID, status);
+
+ result = VK_ERROR_INITIALIZATION_FAILED;
+ continue;
+ }
+
+ if (wcscmp(childGuid, softwareComponentGUID) != 0) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
+ "loaderGetDeviceRegistryFiles: GUID for %d is not SoftwareComponent skipping", childID);
+ continue;
+ }
+
+ if (loaderGetDeviceRegistryEntry(inst, reg_data, reg_data_size, childID, value_name, &result)) {
+ found = true;
+ break; // check next-display-device
+ }
+
+ } while (CM_Get_Sibling(&childID, childID, 0) == CR_SUCCESS);
+ }
+
+ loader_instance_heap_free(inst, pDeviceNames);
+ }
+
+ if (!found && result != VK_ERROR_OUT_OF_HOST_MEMORY) {
+ result = VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ return result;
+}
+
+static char *loader_get_next_path(char *path);
+
+// Find the list of registry files (names within a key) in key "location".
+//
+// This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as
+// given in "location"
+// for a list or name/values which are added to a returned list (function return
+// value).
+// The DWORD values within the key must be 0 or they are skipped.
+// Function return is a string with a ';' separated list of filenames.
+// Function return is NULL if no valid name/value pairs are found in the key,
+// or the key is not found.
+//
+// *reg_data contains a string list of filenames as pointer.
+// When done using the returned string list, the caller should free the pointer.
+VkResult loaderGetRegistryFiles(const struct loader_instance *inst, char *location, bool use_secondary_hive, char **reg_data,
+ PDWORD reg_data_size) {
+ // This list contains all of the allowed ICDs. This allows us to verify that a device is actually present from the vendor
+ // specified. This does disallow other vendors, but any new driver should use the device-specific registries anyway.
+ static const struct {
+ const char *filename;
+ int vendor_id;
+ } known_drivers[] = {
+#if defined(_WIN64)
+ {
+ .filename = "igvk64.json",
+ .vendor_id = 0x8086,
+ },
+ {
+ .filename = "nv-vk64.json",
+ .vendor_id = 0x10de,
+ },
+ {
+ .filename = "amd-vulkan64.json",
+ .vendor_id = 0x1002,
+ },
+ {
+ .filename = "amdvlk64.json",
+ .vendor_id = 0x1002,
+ },
+#else
+ {
+ .filename = "igvk32.json",
+ .vendor_id = 0x8086,
+ },
+ {
+ .filename = "nv-vk32.json",
+ .vendor_id = 0x10de,
+ },
+ {
+ .filename = "amd-vulkan32.json",
+ .vendor_id = 0x1002,
+ },
+ {
+ .filename = "amdvlk32.json",
+ .vendor_id = 0x1002,
+ },
+#endif
+ };
+
+ LONG rtn_value;
+ HKEY hive = DEFAULT_VK_REGISTRY_HIVE, key;
+ DWORD access_flags;
+ char name[2048];
+ char *loc = location;
+ char *next;
+ DWORD name_size = sizeof(name);
+ DWORD value;
+ DWORD value_size = sizeof(value);
+ VkResult result = VK_SUCCESS;
+ bool found = false;
+ IDXGIFactory1 *dxgi_factory = NULL;
+ bool is_driver = !strcmp(location, VK_DRIVERS_INFO_REGISTRY_LOC);
+
+ if (NULL == reg_data) {
+ result = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ if (is_driver) {
+ HRESULT hres = dyn_CreateDXGIFactory1(&IID_IDXGIFactory1, &dxgi_factory);
+ if (hres != S_OK) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loaderGetRegistryFiles: Failed to create dxgi factory for ICD registry verification. No ICDs will be added from "
+ "legacy registry locations");
+ goto out;
+ }
+ }
+
+ while (*loc) {
+ next = loader_get_next_path(loc);
+ access_flags = KEY_QUERY_VALUE;
+ rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
+ if (ERROR_SUCCESS == rtn_value) {
+ for (DWORD idx = 0;
+ (rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE)&value, &value_size)) == ERROR_SUCCESS;
+ name_size = sizeof(name), value_size = sizeof(value)) {
+ if (value_size == sizeof(value) && value == 0) {
+ if (NULL == *reg_data) {
+ *reg_data = loader_instance_heap_alloc(inst, *reg_data_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == *reg_data) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderGetRegistryFiles: Failed to allocate space for registry data for key %s", name);
+ RegCloseKey(key);
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ *reg_data[0] = '\0';
+ } else if (strlen(*reg_data) + name_size + 1 > *reg_data_size) {
+ void *new_ptr = loader_instance_heap_realloc(inst, *reg_data, *reg_data_size, *reg_data_size * 2,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_ptr) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderGetRegistryFiles: Failed to reallocate space for registry value of size %d for key %s",
+ *reg_data_size * 2, name);
+ RegCloseKey(key);
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ *reg_data = new_ptr;
+ *reg_data_size *= 2;
+ }
+
+ // We've now found a json file. If this is an ICD, we still need to check if there is actually a device
+ // that matches this ICD
+ loader_log(
+ inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Located json file \"%s\" from registry \"%s\\%s\"", name,
+ hive == DEFAULT_VK_REGISTRY_HIVE ? DEFAULT_VK_REGISTRY_HIVE_STR : SECONDARY_VK_REGISTRY_HIVE_STR, location);
+ if (is_driver) {
+ int i;
+ for (i = 0; i < sizeof(known_drivers) / sizeof(known_drivers[0]); ++i) {
+ if (!strcmp(name + strlen(name) - strlen(known_drivers[i].filename), known_drivers[i].filename)) {
+ break;
+ }
+ }
+ if (i == sizeof(known_drivers) / sizeof(known_drivers[0])) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "Driver %s is not recognized as a known driver. It will be assumed to be active", name);
+ } else {
+ bool found_gpu = false;
+ for (int j = 0;; ++j) {
+ IDXGIAdapter1 *adapter;
+ HRESULT hres = dxgi_factory->lpVtbl->EnumAdapters1(dxgi_factory, j, &adapter);
+ if (hres == DXGI_ERROR_NOT_FOUND) {
+ break;
+ } else if (hres != S_OK) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Failed to enumerate DXGI adapters at index %d. As a result, drivers may be skipped", j);
+ continue;
+ }
+
+ DXGI_ADAPTER_DESC1 description;
+ hres = adapter->lpVtbl->GetDesc1(adapter, &description);
+ if (hres != S_OK) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "Failed to get DXGI adapter information at index %d. As a result, drivers may be skipped", j);
+ continue;
+ }
+
+ if (description.VendorId == known_drivers[i].vendor_id) {
+ found_gpu = true;
+ break;
+ }
+ }
+
+ if (!found_gpu) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "Dropping driver %s as no corresponding DXGI adapter was found", name);
+ continue;
+ }
+ }
+ }
+
+ if (strlen(*reg_data) == 0) {
+ // The list is emtpy. Add the first entry.
+ (void)snprintf(*reg_data, name_size + 1, "%s", name);
+ found = true;
+ } else {
+ // At this point the reg_data variable contains other JSON paths, likely from the PNP/device section
+ // of the registry that we want to have precedence over this non-device specific section of the registry.
+ // To make sure we avoid enumerating old JSON files/drivers that might be present in the non-device specific
+ // area of the registry when a newer device specific JSON file is present, do a check before adding.
+ // Find the file name, without path, of the JSON file found in the non-device specific registry location.
+ // If the same JSON file name is already found in the list, don't add it again.
+ bool foundDuplicate = false;
+ char *pLastSlashName = strrchr(name, '\\');
+ if (pLastSlashName != NULL) {
+ char *foundMatch = strstr(*reg_data, pLastSlashName + 1);
+ if (foundMatch != NULL) {
+ foundDuplicate = true;
+ }
+ }
+
+ if (foundDuplicate == false) {
+ // Add the new entry to the list.
+ (void)snprintf(*reg_data + strlen(*reg_data), name_size + 2, "%c%s", PATH_SEPARATOR, name);
+ found = true;
+ } else {
+ loader_log(
+ inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "Skipping adding of json file \"%s\" from registry \"%s\\%s\" to the list due to duplication", name,
+ hive == DEFAULT_VK_REGISTRY_HIVE ? DEFAULT_VK_REGISTRY_HIVE_STR : SECONDARY_VK_REGISTRY_HIVE_STR,
+ location);
+ }
+ }
+ }
+ }
+ RegCloseKey(key);
+ }
+
+ // Advance the location - if the next location is in the secondary hive, then reset the locations and advance the hive
+ if (use_secondary_hive && (hive == DEFAULT_VK_REGISTRY_HIVE) && (*next == '\0')) {
+ loc = location;
+ hive = SECONDARY_VK_REGISTRY_HIVE;
+ } else {
+ loc = next;
+ }
+ }
+
+ if (!found && result != VK_ERROR_OUT_OF_HOST_MEMORY) {
+ result = VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+out:
+ if (is_driver && dxgi_factory != NULL) {
+ dxgi_factory->lpVtbl->Release(dxgi_factory);
+ }
+
+ return result;
+}
+
+#endif // WIN32
+
+// Combine path elements, separating each element with the platform-specific
+// directory separator, and save the combined string to a destination buffer,
+// not exceeding the given length. Path elements are given as variable args,
+// with a NULL element terminating the list.
+//
+// \returns the total length of the combined string, not including an ASCII
+// NUL termination character. This length may exceed the available storage:
+// in this case, the written string will be truncated to avoid a buffer
+// overrun, and the return value will greater than or equal to the storage
+// size. A NULL argument may be provided as the destination buffer in order
+// to determine the required string length without actually writing a string.
+static size_t loader_platform_combine_path(char *dest, size_t len, ...) {
+ size_t required_len = 0;
+ va_list ap;
+ const char *component;
+
+ va_start(ap, len);
+
+ while ((component = va_arg(ap, const char *))) {
+ if (required_len > 0) {
+ // This path element is not the first non-empty element; prepend
+ // a directory separator if space allows
+ if (dest && required_len + 1 < len) {
+ (void)snprintf(dest + required_len, len - required_len, "%c", DIRECTORY_SYMBOL);
+ }
+ required_len++;
+ }
+
+ if (dest && required_len < len) {
+ strncpy(dest + required_len, component, len - required_len);
+ }
+ required_len += strlen(component);
+ }
+
+ va_end(ap);
+
+ // strncpy(3) won't add a NUL terminating byte in the event of truncation.
+ if (dest && required_len >= len) {
+ dest[len - 1] = '\0';
+ }
+
+ return required_len;
+}
+
+// Given string of three part form "maj.min.pat" convert to a vulkan version number.
+static uint32_t loader_make_version(char *vers_str) {
+ uint32_t vers = 0, major = 0, minor = 0, patch = 0;
+ char *vers_tok;
+
+ if (!vers_str) {
+ return vers;
+ }
+
+ vers_tok = strtok(vers_str, ".\"\n\r");
+ if (NULL != vers_tok) {
+ major = (uint16_t)atoi(vers_tok);
+ vers_tok = strtok(NULL, ".\"\n\r");
+ if (NULL != vers_tok) {
+ minor = (uint16_t)atoi(vers_tok);
+ vers_tok = strtok(NULL, ".\"\n\r");
+ if (NULL != vers_tok) {
+ patch = (uint16_t)atoi(vers_tok);
+ }
+ }
+ }
+
+ return VK_MAKE_VERSION(major, minor, patch);
+}
+
+bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) {
+ return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
+}
+
+// Search the given ext_array for an extension matching the given vk_ext_prop
+bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, const uint32_t count,
+ const VkExtensionProperties *ext_array) {
+ for (uint32_t i = 0; i < count; i++) {
+ if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i])) return true;
+ }
+ return false;
+}
+
+// Search the given ext_list for an extension matching the given vk_ext_prop
+bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list) {
+ for (uint32_t i = 0; i < ext_list->count; i++) {
+ if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) return true;
+ }
+ return false;
+}
+
+// Search the given ext_list for a device extension matching the given ext_prop
+bool has_vk_dev_ext_property(const VkExtensionProperties *ext_prop, const struct loader_device_extension_list *ext_list) {
+ for (uint32_t i = 0; i < ext_list->count; i++) {
+ if (compare_vk_extension_properties(&ext_list->list[i].props, ext_prop)) return true;
+ }
+ return false;
+}
+
+// Get the next unused layer property in the list. Init the property to zero.
+static struct loader_layer_properties *loaderGetNextLayerPropertySlot(const struct loader_instance *inst,
+ struct loader_layer_list *layer_list) {
+ if (layer_list->capacity == 0) {
+ layer_list->list =
+ loader_instance_heap_alloc(inst, sizeof(struct loader_layer_properties) * 64, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (layer_list->list == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderGetNextLayerPropertySlot: Out of memory can "
+ "not add any layer properties to list");
+ return NULL;
+ }
+ memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
+ layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
+ }
+
+ // Ensure enough room to add an entry
+ if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > layer_list->capacity) {
+ void *new_ptr = loader_instance_heap_realloc(inst, layer_list->list, layer_list->capacity, layer_list->capacity * 2,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_ptr) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetNextLayerPropertySlot: realloc failed for layer list");
+ return NULL;
+ }
+ layer_list->list = new_ptr;
+ memset((uint8_t *)layer_list->list + layer_list->capacity, 0, layer_list->capacity);
+ layer_list->capacity *= 2;
+ }
+
+ layer_list->count++;
+ return &(layer_list->list[layer_list->count - 1]);
+}
+
+// Search the given layer list for a layer property matching the given layer name
+static struct loader_layer_properties *loaderFindLayerProperty(const char *name, const struct loader_layer_list *layer_list) {
+ for (uint32_t i = 0; i < layer_list->count; i++) {
+ const VkLayerProperties *item = &layer_list->list[i].info;
+ if (strcmp(name, item->layerName) == 0) return &layer_list->list[i];
+ }
+ return NULL;
+}
+
+// Search the given layer list for a layer matching the given layer name
+static bool loaderFindLayerNameInList(const char *name, const struct loader_layer_list *layer_list) {
+ if (NULL == layer_list) {
+ return false;
+ }
+ if (NULL != loaderFindLayerProperty(name, layer_list)) {
+ return true;
+ }
+ return false;
+}
+
+// Search the given meta-layer's component list for a layer matching the given layer name
+static bool loaderFindLayerNameInMetaLayer(const struct loader_instance *inst, const char *layer_name,
+ struct loader_layer_list *layer_list, struct loader_layer_properties *meta_layer_props) {
+ for (uint32_t comp_layer = 0; comp_layer < meta_layer_props->num_component_layers; comp_layer++) {
+ if (!strcmp(meta_layer_props->component_layer_names[comp_layer], layer_name)) {
+ return true;
+ }
+ struct loader_layer_properties *comp_layer_props =
+ loaderFindLayerProperty(meta_layer_props->component_layer_names[comp_layer], layer_list);
+ if (comp_layer_props->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
+ return loaderFindLayerNameInMetaLayer(inst, layer_name, layer_list, comp_layer_props);
+ }
+ }
+ return false;
+}
+
+// Search the override layer's blacklist for a layer matching the given layer name
+static bool loaderFindLayerNameInBlacklist(const struct loader_instance *inst, const char *layer_name,
+ struct loader_layer_list *layer_list, struct loader_layer_properties *meta_layer_props) {
+ for (uint32_t black_layer = 0; black_layer < meta_layer_props->num_blacklist_layers; ++black_layer) {
+ if (!strcmp(meta_layer_props->blacklist_layer_names[black_layer], layer_name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Remove all layer properties entries from the list
+void loaderDeleteLayerListAndProperties(const struct loader_instance *inst, struct loader_layer_list *layer_list) {
+ uint32_t i, j, k;
+ struct loader_device_extension_list *dev_ext_list;
+ struct loader_dev_ext_props *ext_props;
+ if (!layer_list) return;
+
+ for (i = 0; i < layer_list->count; i++) {
+ if (NULL != layer_list->list[i].blacklist_layer_names) {
+ loader_instance_heap_free(inst, layer_list->list[i].blacklist_layer_names);
+ layer_list->list[i].blacklist_layer_names = NULL;
+ }
+ if (NULL != layer_list->list[i].component_layer_names) {
+ loader_instance_heap_free(inst, layer_list->list[i].component_layer_names);
+ layer_list->list[i].component_layer_names = NULL;
+ }
+ if (NULL != layer_list->list[i].override_paths) {
+ loader_instance_heap_free(inst, layer_list->list[i].override_paths);
+ layer_list->list[i].override_paths = NULL;
+ }
+ loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_list->list[i].instance_extension_list);
+ dev_ext_list = &layer_list->list[i].device_extension_list;
+ if (dev_ext_list->capacity > 0 && NULL != dev_ext_list->list) {
+ for (j = 0; j < dev_ext_list->count; j++) {
+ ext_props = &dev_ext_list->list[j];
+ if (ext_props->entrypoint_count > 0) {
+ for (k = 0; k < ext_props->entrypoint_count; k++) {
+ loader_instance_heap_free(inst, ext_props->entrypoints[k]);
+ }
+ loader_instance_heap_free(inst, ext_props->entrypoints);
+ }
+ }
+ }
+ loader_destroy_generic_list(inst, (struct loader_generic_list *)dev_ext_list);
+ }
+ layer_list->count = 0;
+
+ if (layer_list->capacity > 0) {
+ layer_list->capacity = 0;
+ loader_instance_heap_free(inst, layer_list->list);
+ }
+}
+
+// Remove all layers in the layer list that are blacklisted by the override layer.
+// NOTE: This should only be called if an override layer is found and not expired.
+void loaderRemoveLayersInBlacklist(const struct loader_instance *inst, struct loader_layer_list *layer_list) {
+ struct loader_layer_properties *override_prop = loaderFindLayerProperty(VK_OVERRIDE_LAYER_NAME, layer_list);
+ if (NULL == override_prop) {
+ return;
+ }
+
+ for (int32_t j = 0; j < (int32_t)(layer_list->count); j++) {
+ struct loader_layer_properties cur_layer_prop = layer_list->list[j];
+ const char *cur_layer_name = &cur_layer_prop.info.layerName[0];
+
+ // Skip the override layer itself.
+ if (!strcmp(VK_OVERRIDE_LAYER_NAME, cur_layer_name)) {
+ continue;
+ }
+
+ // If found in the override layer's blacklist, remove it
+ if (loaderFindLayerNameInBlacklist(inst, cur_layer_name, layer_list, override_prop)) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
+ "loaderRemoveLayersInBlacklist: Override layer is active and layer %s is in the blacklist"
+ " inside of it. Removing that layer from current layer list.",
+ cur_layer_name);
+
+ if (cur_layer_prop.type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
+ // Delete the component layers
+ loader_instance_heap_free(inst, cur_layer_prop.component_layer_names);
+ loader_instance_heap_free(inst, cur_layer_prop.override_paths);
+ // Never need to free the blacklist, since it can only exist in the override layer
+ }
+
+ // Remove the current invalid meta-layer from the layer list. Use memmove since we are
+ // overlapping the source and destination addresses.
+ memmove(&layer_list->list[j], &layer_list->list[j + 1],
+ sizeof(struct loader_layer_properties) * (layer_list->count - 1 - j));
+
+ // Decrement the count (because we now have one less) and decrement the loop index since we need to
+ // re-check this index.
+ layer_list->count--;
+ j--;
+
+ // Re-do the query for the override layer
+ override_prop = loaderFindLayerProperty(VK_OVERRIDE_LAYER_NAME, layer_list);
+ }
+ }
+}
+
+// Remove all layers in the layer list that are not found inside any implicit meta-layers.
+void loaderRemoveLayersNotInImplicitMetaLayers(const struct loader_instance *inst, struct loader_layer_list *layer_list) {
+ int32_t i;
+ int32_t j;
+ int32_t layer_count = (int32_t)(layer_list->count);
+
+ for (i = 0; i < layer_count; i++) {
+ layer_list->list[i].keep = false;
+ }
+
+ for (i = 0; i < layer_count; i++) {
+ struct loader_layer_properties cur_layer_prop = layer_list->list[i];
+
+ if (0 == (cur_layer_prop.type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
+ cur_layer_prop.keep = true;
+ } else {
+ continue;
+ }
+
+ if (cur_layer_prop.type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
+ for (j = 0; j < layer_count; j++) {
+ struct loader_layer_properties layer_to_check = layer_list->list[j];
+
+ if (i == j) {
+ continue;
+ }
+
+ // For all layers found in this meta layer, we want to keep them as well.
+ if (loaderFindLayerNameInMetaLayer(inst, layer_to_check.info.layerName, layer_list, &cur_layer_prop)) {
+ cur_layer_prop.keep = true;
+ }
+ }
+ }
+ }
+
+ // Remove any layers we don't want to keep (Don't use layer_count here as we need it to be
+ // dynamically updated if we delete a layer property in the list).
+ for (i = 0; i < (int32_t)(layer_list->count); i++) {
+ struct loader_layer_properties cur_layer_prop = layer_list->list[i];
+ if (!cur_layer_prop.keep) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
+ "loaderRemoveLayersNotInImplicitMetaLayers : Implicit meta-layers are active, and layer %s is not list"
+ " inside of any. So removing layer from current layer list.",
+ cur_layer_prop.info.layerName);
+
+ if (cur_layer_prop.type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
+ // Delete the component layers
+ loader_instance_heap_free(inst, cur_layer_prop.component_layer_names);
+ loader_instance_heap_free(inst, cur_layer_prop.override_paths);
+ }
+
+ // Remove the current invalid meta-layer from the layer list. Use memmove since we are
+ // overlapping the source and destination addresses.
+ memmove(&layer_list->list[i], &layer_list->list[i + 1],
+ sizeof(struct loader_layer_properties) * (layer_list->count - 1 - i));
+
+ // Decrement the count (because we now have one less) and decrement the loop index since we need to
+ // re-check this index.
+ layer_list->count--;
+ i--;
+ }
+ }
+}
+
+static VkResult loader_add_instance_extensions(const struct loader_instance *inst,
+ const PFN_vkEnumerateInstanceExtensionProperties fp_get_props, const char *lib_name,
+ struct loader_extension_list *ext_list) {
+ uint32_t i, count = 0;
+ VkExtensionProperties *ext_props;
+ VkResult res = VK_SUCCESS;
+
+ if (!fp_get_props) {
+ // No EnumerateInstanceExtensionProperties defined
+ goto out;
+ }
+
+ res = fp_get_props(NULL, &count, NULL);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_instance_extensions: Error getting Instance "
+ "extension count from %s",
+ lib_name);
+ goto out;
+ }
+
+ if (count == 0) {
+ // No ExtensionProperties to report
+ goto out;
+ }
+
+ ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
+ if (NULL == ext_props) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ res = fp_get_props(NULL, &count, ext_props);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_instance_extensions: Error getting Instance "
+ "extensions from %s",
+ lib_name);
+ goto out;
+ }
+
+ for (i = 0; i < count; i++) {
+ char spec_version[64];
+
+ bool ext_unsupported = wsi_unsupported_instance_extension(&ext_props[i]);
+ if (!ext_unsupported) {
+ (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion),
+ VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion));
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Instance Extension: %s (%s) version %s", ext_props[i].extensionName,
+ lib_name, spec_version);
+
+ res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_instance_extensions: Failed to add %s "
+ "to Instance extension list",
+ lib_name);
+ goto out;
+ }
+ }
+ }
+
+out:
+ return res;
+}
+
+// Initialize ext_list with the physical device extensions.
+// The extension properties are passed as inputs in count and ext_props.
+static VkResult loader_init_device_extensions(const struct loader_instance *inst, struct loader_physical_device_term *phys_dev_term,
+ uint32_t count, VkExtensionProperties *ext_props,
+ struct loader_extension_list *ext_list) {
+ VkResult res;
+ uint32_t i;
+
+ res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties));
+ if (VK_SUCCESS != res) {
+ return res;
+ }
+
+ for (i = 0; i < count; i++) {
+ char spec_version[64];
+ (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion),
+ VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion));
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Device Extension: %s (%s) version %s", ext_props[i].extensionName,
+ phys_dev_term->this_icd_term->scanned_icd->lib_name, spec_version);
+ res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
+ if (res != VK_SUCCESS) return res;
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult loader_add_device_extensions(const struct loader_instance *inst,
+ PFN_vkEnumerateDeviceExtensionProperties fpEnumerateDeviceExtensionProperties,
+ VkPhysicalDevice physical_device, const char *lib_name,
+ struct loader_extension_list *ext_list) {
+ uint32_t i, count;
+ VkResult res;
+ VkExtensionProperties *ext_props;
+
+ res = fpEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL);
+ if (res == VK_SUCCESS && count > 0) {
+ ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
+ if (!ext_props) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_device_extensions: Failed to allocate space"
+ " for device extension properties.");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ res = fpEnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props);
+ if (res != VK_SUCCESS) {
+ return res;
+ }
+ for (i = 0; i < count; i++) {
+ char spec_version[64];
+ (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion),
+ VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion));
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Device Extension: %s (%s) version %s", ext_props[i].extensionName,
+ lib_name, spec_version);
+ res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
+ if (res != VK_SUCCESS) {
+ return res;
+ }
+ }
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_device_extensions: Error getting physical "
+ "device extension info count from library %s",
+ lib_name);
+ return res;
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size) {
+ size_t capacity = 32 * element_size;
+ list_info->count = 0;
+ list_info->capacity = 0;
+ list_info->list = loader_instance_heap_alloc(inst, capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (list_info->list == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_init_generic_list: Failed to allocate space "
+ "for generic list");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memset(list_info->list, 0, capacity);
+ list_info->capacity = capacity;
+ return VK_SUCCESS;
+}
+
+void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list) {
+ loader_instance_heap_free(inst, list->list);
+ list->count = 0;
+ list->capacity = 0;
+}
+
+// Append non-duplicate extension properties defined in props to the given ext_list.
+// Return - Vk_SUCCESS on success
+VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list,
+ uint32_t prop_list_count, const VkExtensionProperties *props) {
+ uint32_t i;
+ const VkExtensionProperties *cur_ext;
+
+ if (ext_list->list == NULL || ext_list->capacity == 0) {
+ VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties));
+ if (VK_SUCCESS != res) {
+ return res;
+ }
+ }
+
+ for (i = 0; i < prop_list_count; i++) {
+ cur_ext = &props[i];
+
+ // look for duplicates
+ if (has_vk_extension_property(cur_ext, ext_list)) {
+ continue;
+ }
+
+ // add to list at end
+ // check for enough capacity
+ if (ext_list->count * sizeof(VkExtensionProperties) >= ext_list->capacity) {
+ void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (new_ptr == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_to_ext_list: Failed to reallocate "
+ "space for extension list");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ ext_list->list = new_ptr;
+
+ // double capacity
+ ext_list->capacity *= 2;
+ }
+
+ memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
+ ext_list->count++;
+ }
+ return VK_SUCCESS;
+}
+
+// Append one extension property defined in props with entrypoints defined in entries to the given
+// ext_list. Do not append if a duplicate.
+// Return - Vk_SUCCESS on success
+VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct loader_device_extension_list *ext_list,
+ const VkExtensionProperties *props, uint32_t entry_count, char **entrys) {
+ uint32_t idx;
+ if (ext_list->list == NULL || ext_list->capacity == 0) {
+ VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(struct loader_dev_ext_props));
+ if (VK_SUCCESS != res) {
+ return res;
+ }
+ }
+
+ // look for duplicates
+ if (has_vk_dev_ext_property(props, ext_list)) {
+ return VK_SUCCESS;
+ }
+
+ idx = ext_list->count;
+ // add to list at end
+ // check for enough capacity
+ if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) {
+ void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+
+ if (NULL == new_ptr) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_to_dev_ext_list: Failed to reallocate space for device extension list");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ ext_list->list = new_ptr;
+
+ // double capacity
+ ext_list->capacity *= 2;
+ }
+
+ memcpy(&ext_list->list[idx].props, props, sizeof(*props));
+ ext_list->list[idx].entrypoint_count = entry_count;
+ if (entry_count == 0) {
+ ext_list->list[idx].entrypoints = NULL;
+ } else {
+ ext_list->list[idx].entrypoints =
+ loader_instance_heap_alloc(inst, sizeof(char *) * entry_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (ext_list->list[idx].entrypoints == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_to_dev_ext_list: Failed to allocate space "
+ "for device extension entrypoint list in list %d",
+ idx);
+ ext_list->list[idx].entrypoint_count = 0;
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ for (uint32_t i = 0; i < entry_count; i++) {
+ ext_list->list[idx].entrypoints[i] =
+ loader_instance_heap_alloc(inst, strlen(entrys[i]) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (ext_list->list[idx].entrypoints[i] == NULL) {
+ for (uint32_t j = 0; j < i; j++) {
+ loader_instance_heap_free(inst, ext_list->list[idx].entrypoints[j]);
+ }
+ loader_instance_heap_free(inst, ext_list->list[idx].entrypoints);
+ ext_list->list[idx].entrypoint_count = 0;
+ ext_list->list[idx].entrypoints = NULL;
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_to_dev_ext_list: Failed to allocate space "
+ "for device extension entrypoint %d name",
+ i);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ strcpy(ext_list->list[idx].entrypoints[i], entrys[i]);
+ }
+ }
+ ext_list->count++;
+
+ return VK_SUCCESS;
+}
+
+// Prototypes needed.
+bool loaderAddMetaLayer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
+ struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
+ const struct loader_layer_list *source_list);
+
+// Manage lists of VkLayerProperties
+static bool loaderInitLayerList(const struct loader_instance *inst, struct loader_layer_list *list) {
+ list->capacity = 32 * sizeof(struct loader_layer_properties);
+ list->list = loader_instance_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (list->list == NULL) {
+ return false;
+ }
+ memset(list->list, 0, list->capacity);
+ list->count = 0;
+ return true;
+}
+
+// Search the given layer list for a list matching the given VkLayerProperties
+bool loaderListHasLayerProperty(const VkLayerProperties *vk_layer_prop, const struct loader_layer_list *list) {
+ for (uint32_t i = 0; i < list->count; i++) {
+ if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0) return true;
+ }
+ return false;
+}
+
+void loaderDestroyLayerList(const struct loader_instance *inst, struct loader_device *device,
+ struct loader_layer_list *layer_list) {
+ if (device) {
+ loader_device_heap_free(device, layer_list->list);
+ } else {
+ loader_instance_heap_free(inst, layer_list->list);
+ }
+ layer_list->count = 0;
+ layer_list->capacity = 0;
+}
+
+// Append non-duplicate layer properties defined in prop_list to the given layer_info list
+VkResult loaderAddLayerPropertiesToList(const struct loader_instance *inst, struct loader_layer_list *list,
+ uint32_t prop_list_count, const struct loader_layer_properties *props) {
+ uint32_t i;
+ struct loader_layer_properties *layer;
+
+ if (list->list == NULL || list->capacity == 0) {
+ if (!loaderInitLayerList(inst, list)) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ }
+
+ if (list->list == NULL) return VK_SUCCESS;
+
+ for (i = 0; i < prop_list_count; i++) {
+ layer = (struct loader_layer_properties *)&props[i];
+
+ // Look for duplicates, and skip
+ if (loaderListHasLayerProperty(&layer->info, list)) {
+ continue;
+ }
+
+ // Check for enough capacity
+ if (((list->count + 1) * sizeof(struct loader_layer_properties)) >= list->capacity) {
+ size_t new_capacity = list->capacity * 2;
+ void *new_ptr =
+ loader_instance_heap_realloc(inst, list->list, list->capacity, new_capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_ptr) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderAddLayerPropertiesToList: Realloc failed for when attempting to add new layer");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ list->list = new_ptr;
+ list->capacity = new_capacity;
+ }
+
+ memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
+ list->count++;
+ }
+
+ return VK_SUCCESS;
+}
+
+// Search the given search_list for any layers in the props list. Add these to the
+// output layer_list. Don't add duplicates to the output layer_list.
+static VkResult loaderAddLayerNamesToList(const struct loader_instance *inst, struct loader_layer_list *output_list,
+ struct loader_layer_list *expanded_output_list, uint32_t name_count,
+ const char *const *names, const struct loader_layer_list *source_list) {
+ struct loader_layer_properties *layer_prop;
+ VkResult err = VK_SUCCESS;
+
+ for (uint32_t i = 0; i < name_count; i++) {
+ const char *source_name = names[i];
+ layer_prop = loaderFindLayerProperty(source_name, source_list);
+ if (NULL == layer_prop) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderAddLayerNamesToList: Unable to find layer %s", source_name);
+ err = VK_ERROR_LAYER_NOT_PRESENT;
+ continue;
+ }
+
+ // If not a meta-layer, simply add it.
+ if (0 == (layer_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
+ if (!loaderListHasLayerProperty(&layer_prop->info, output_list)) {
+ loaderAddLayerPropertiesToList(inst, output_list, 1, layer_prop);
+ }
+ if (!loaderListHasLayerProperty(&layer_prop->info, expanded_output_list)) {
+ loaderAddLayerPropertiesToList(inst, expanded_output_list, 1, layer_prop);
+ }
+ } else {
+ if (!loaderListHasLayerProperty(&layer_prop->info, output_list) ||
+ !loaderListHasLayerProperty(&layer_prop->info, expanded_output_list)) {
+ loaderAddMetaLayer(inst, layer_prop, output_list, expanded_output_list, source_list);
+ }
+ }
+ }
+
+ return err;
+}
+
+static bool checkExpiration(const struct loader_instance *inst, const struct loader_layer_properties *prop) {
+ time_t current = time(NULL);
+ struct tm tm_current = *localtime(&current);
+
+ struct tm tm_expiration = {
+ .tm_sec = 0,
+ .tm_min = prop->expiration.minute,
+ .tm_hour = prop->expiration.hour,
+ .tm_mday = prop->expiration.day,
+ .tm_mon = prop->expiration.month - 1,
+ .tm_year = prop->expiration.year - 1900,
+ .tm_isdst = tm_current.tm_isdst,
+ // wday and yday are ignored by mktime
+ };
+ time_t expiration = mktime(&tm_expiration);
+
+ return current < expiration;
+}
+
+// Determine if the provided implicit layer should be enabled by querying the appropriate environmental variables.
+// For an implicit layer, at least a disable environment variable is required.
+bool loaderImplicitLayerIsEnabled(const struct loader_instance *inst, const struct loader_layer_properties *prop) {
+ bool enable = false;
+ char *env_value = NULL;
+
+ // If no enable_environment variable is specified, this implicit layer is always be enabled by default.
+ if (prop->enable_env_var.name[0] == 0) {
+ enable = true;
+ } else {
+ // Otherwise, only enable this layer if the enable environment variable is defined
+ env_value = loader_getenv(prop->enable_env_var.name, inst);
+ if (env_value && !strcmp(prop->enable_env_var.value, env_value)) {
+ enable = true;
+ }
+ loader_free_getenv(env_value, inst);
+ }
+
+ // The disable_environment has priority over everything else. If it is defined, the layer is always
+ // disabled.
+ env_value = loader_getenv(prop->disable_env_var.name, inst);
+ if (env_value) {
+ enable = false;
+ }
+ loader_free_getenv(env_value, inst);
+
+ // If this layer has an expiration, check it to determine if this layer has expired.
+ if (prop->has_expiration) {
+ enable = checkExpiration(inst, prop);
+ }
+
+ // Enable this layer if it is included in the override layer
+ if (inst != NULL && inst->override_layer_present) {
+ struct loader_layer_properties *override = NULL;
+ for (uint32_t i = 0; i < inst->instance_layer_list.count; ++i) {
+ if (strcmp(inst->instance_layer_list.list[i].info.layerName, VK_OVERRIDE_LAYER_NAME) == 0) {
+ override = &inst->instance_layer_list.list[i];
+ break;
+ }
+ }
+ if (override != NULL) {
+ for (uint32_t i = 0; i < override->num_component_layers; ++i) {
+ if (strcmp(override->component_layer_names[i], prop->info.layerName) == 0) {
+ enable = true;
+ break;
+ }
+ }
+ }
+ }
+
+ return enable;
+}
+
+// Check the individual implicit layer for the enable/disable environment variable settings. Only add it after
+// every check has passed indicating it should be used.
+static void loaderAddImplicitLayer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
+ struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
+ const struct loader_layer_list *source_list) {
+ bool enable = loaderImplicitLayerIsEnabled(inst, prop);
+
+ // If the implicit layer is supposed to be enable, make sure the layer supports at least the same API version
+ // that the application is asking (i.e. layer's API >= app's API). If it's not, disable this layer.
+ if (enable) {
+ uint16_t layer_api_major_version = VK_VERSION_MAJOR(prop->info.specVersion);
+ uint16_t layer_api_minor_version = VK_VERSION_MINOR(prop->info.specVersion);
+ if (inst->app_api_major_version > layer_api_major_version ||
+ (inst->app_api_major_version == layer_api_major_version && inst->app_api_minor_version > layer_api_minor_version)) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "loader_add_implicit_layer: Disabling implicit layer %s for using an old API version %d.%d versus "
+ "application requested %d.%d",
+ prop->info.layerName, layer_api_major_version, layer_api_minor_version, inst->app_api_major_version,
+ inst->app_api_minor_version);
+ enable = false;
+ }
+ }
+
+ if (enable) {
+ if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
+ if (!loaderListHasLayerProperty(&prop->info, target_list)) {
+ loaderAddLayerPropertiesToList(inst, target_list, 1, prop);
+ }
+ if (NULL != expanded_target_list && !loaderListHasLayerProperty(&prop->info, expanded_target_list)) {
+ loaderAddLayerPropertiesToList(inst, expanded_target_list, 1, prop);
+ }
+ } else {
+ if (!loaderListHasLayerProperty(&prop->info, target_list) ||
+ (NULL != expanded_target_list && !loaderListHasLayerProperty(&prop->info, expanded_target_list))) {
+ loaderAddMetaLayer(inst, prop, target_list, expanded_target_list, source_list);
+ }
+ }
+ }
+}
+
+// Add the component layers of a meta-layer to the active list of layers
+bool loaderAddMetaLayer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
+ struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
+ const struct loader_layer_list *source_list) {
+ bool found = true;
+
+ // If the meta-layer isn't present in the unexpanded list, add it.
+ if (!loaderListHasLayerProperty(&prop->info, target_list)) {
+ loaderAddLayerPropertiesToList(inst, target_list, 1, prop);
+ }
+
+ // We need to add all the individual component layers
+ for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) {
+ bool found_comp = false;
+ const struct loader_layer_properties *search_prop =
+ loaderFindLayerProperty(prop->component_layer_names[comp_layer], source_list);
+ if (search_prop != NULL) {
+ found_comp = true;
+
+ // If the component layer is itself an implicit layer, we need to do the implicit layer enable
+ // checks
+ if (0 == (search_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
+ loaderAddImplicitLayer(inst, search_prop, target_list, expanded_target_list, source_list);
+ } else {
+ if (0 != (search_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
+ found = loaderAddMetaLayer(inst, search_prop, target_list, expanded_target_list, source_list);
+ } else {
+ // Otherwise, just make sure it hasn't already been added to either list before we add it
+ if (!loaderListHasLayerProperty(&search_prop->info, target_list)) {
+ loaderAddLayerPropertiesToList(inst, target_list, 1, search_prop);
+ }
+ if (NULL != expanded_target_list && !loaderListHasLayerProperty(&search_prop->info, expanded_target_list)) {
+ loaderAddLayerPropertiesToList(inst, expanded_target_list, 1, search_prop);
+ }
+ }
+ }
+ }
+ if (!found_comp) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loaderAddMetaLayer: Failed to find layer name %s component layer "
+ "%s to activate",
+ search_prop->info.layerName, prop->component_layer_names[comp_layer]);
+ found = false;
+ }
+ }
+
+ // Add this layer to the overall target list (not the expanded one)
+ if (found && !loaderListHasLayerProperty(&prop->info, target_list)) {
+ loaderAddLayerPropertiesToList(inst, target_list, 1, prop);
+ }
+
+ return found;
+}
+
+// Search the source_list for any layer with a name that matches the given name and a type
+// that matches the given type. Add all matching layers to the target_list.
+// Do not add if found loader_layer_properties is already on the target_list.
+void loaderAddLayerNameToList(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags,
+ const struct loader_layer_list *source_list, struct loader_layer_list *target_list,
+ struct loader_layer_list *expanded_target_list) {
+ bool found = false;
+ for (uint32_t i = 0; i < source_list->count; i++) {
+ struct loader_layer_properties *source_prop = &source_list->list[i];
+ if (0 == strcmp(source_prop->info.layerName, name) && (source_prop->type_flags & type_flags) == type_flags) {
+ // If not a meta-layer, simply add it.
+ if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
+ if (!loaderListHasLayerProperty(&source_prop->info, target_list) &&
+ VK_SUCCESS == loaderAddLayerPropertiesToList(inst, target_list, 1, source_prop)) {
+ found = true;
+ }
+ if (!loaderListHasLayerProperty(&source_prop->info, expanded_target_list) &&
+ VK_SUCCESS == loaderAddLayerPropertiesToList(inst, expanded_target_list, 1, source_prop)) {
+ found = true;
+ }
+ } else {
+ found = loaderAddMetaLayer(inst, source_prop, target_list, expanded_target_list, source_list);
+ }
+ }
+ }
+ if (!found) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loaderAddLayerNameToList: Failed to find layer name %s to activate",
+ name);
+ }
+}
+
+static VkExtensionProperties *get_extension_property(const char *name, const struct loader_extension_list *list) {
+ for (uint32_t i = 0; i < list->count; i++) {
+ if (strcmp(name, list->list[i].extensionName) == 0) return &list->list[i];
+ }
+ return NULL;
+}
+
+static VkExtensionProperties *get_dev_extension_property(const char *name, const struct loader_device_extension_list *list) {
+ for (uint32_t i = 0; i < list->count; i++) {
+ if (strcmp(name, list->list[i].props.extensionName) == 0) return &list->list[i].props;
+ }
+ return NULL;
+}
+
+// For Instance extensions implemented within the loader (i.e. DEBUG_REPORT
+// the extension must provide two entry points for the loader to use:
+// - "trampoline" entry point - this is the address returned by GetProcAddr
+// and will always do what's necessary to support a
+// global call.
+// - "terminator" function - this function will be put at the end of the
+// instance chain and will contain the necessary logic
+// to call / process the extension for the appropriate
+// ICDs that are available.
+// There is no generic mechanism for including these functions, the references
+// must be placed into the appropriate loader entry points.
+// GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr
+// requests
+// loader_coalesce_extensions(void) - add extension records to the list of global
+// extension available to the app.
+// instance_disp - add function pointer for terminator function
+// to this array.
+// The extension itself should be in a separate file that will be linked directly
+// with the loader.
+VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
+ struct loader_extension_list *inst_exts) {
+ struct loader_extension_list icd_exts;
+ VkResult res = VK_SUCCESS;
+ char *env_value;
+ bool filter_extensions = true;
+
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
+
+ // Check if a user wants to disable the instance extension filtering behavior
+ env_value = loader_getenv("VK_LOADER_DISABLE_INST_EXT_FILTER", inst);
+ if (NULL != env_value && atoi(env_value) != 0) {
+ filter_extensions = false;
+ }
+ loader_free_getenv(env_value, inst);
+
+ // traverse scanned icd list adding non-duplicate extensions to the list
+ for (uint32_t i = 0; i < icd_tramp_list->count; i++) {
+ res = loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties));
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ res = loader_add_instance_extensions(inst, icd_tramp_list->scanned_list[i].EnumerateInstanceExtensionProperties,
+ icd_tramp_list->scanned_list[i].lib_name, &icd_exts);
+ if (VK_SUCCESS == res) {
+ if (filter_extensions) {
+ // Remove any extensions not recognized by the loader
+ for (int32_t j = 0; j < (int32_t)icd_exts.count; j++) {
+ // See if the extension is in the list of supported extensions
+ bool found = false;
+ for (uint32_t k = 0; LOADER_INSTANCE_EXTENSIONS[k] != NULL; k++) {
+ if (strcmp(icd_exts.list[j].extensionName, LOADER_INSTANCE_EXTENSIONS[k]) == 0) {
+ found = true;
+ break;
+ }
+ }
+
+ // If it isn't in the list, remove it
+ if (!found) {
+ for (uint32_t k = j + 1; k < icd_exts.count; k++) {
+ icd_exts.list[k - 1] = icd_exts.list[k];
+ }
+ --icd_exts.count;
+ --j;
+ }
+ }
+ }
+
+ res = loader_add_to_ext_list(inst, inst_exts, icd_exts.count, icd_exts.list);
+ }
+ loader_destroy_generic_list(inst, (struct loader_generic_list *)&icd_exts);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ };
+
+ // Traverse loader's extensions, adding non-duplicate extensions to the list
+ debug_utils_AddInstanceExtensions(inst, inst_exts);
+
+out:
+ return res;
+}
+
+struct loader_icd_term *loader_get_icd_and_device(const void *device, struct loader_device **found_dev, uint32_t *icd_index) {
+ *found_dev = NULL;
+ for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
+ uint32_t index = 0;
+ for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ for (struct loader_device *dev = icd_term->logical_device_list; dev; dev = dev->next)
+ // Value comparison of device prevents object wrapping by layers
+ if (loader_get_dispatch(dev->icd_device) == loader_get_dispatch(device) ||
+ (dev->chain_device != VK_NULL_HANDLE &&
+ loader_get_dispatch(dev->chain_device) == loader_get_dispatch(device))) {
+ *found_dev = dev;
+ if (NULL != icd_index) {
+ *icd_index = index;
+ }
+ return icd_term;
+ }
+ index++;
+ }
+ }
+ return NULL;
+}
+
+void loader_destroy_logical_device(const struct loader_instance *inst, struct loader_device *dev,
+ const VkAllocationCallbacks *pAllocator) {
+ if (pAllocator) {
+ dev->alloc_callbacks = *pAllocator;
+ }
+ if (NULL != dev->expanded_activated_layer_list.list) {
+ loaderDeactivateLayers(inst, dev, &dev->expanded_activated_layer_list);
+ }
+ if (NULL != dev->app_activated_layer_list.list) {
+ loaderDestroyLayerList(inst, dev, &dev->app_activated_layer_list);
+ }
+ loader_device_heap_free(dev, dev);
+}
+
+struct loader_device *loader_create_logical_device(const struct loader_instance *inst, const VkAllocationCallbacks *pAllocator) {
+ struct loader_device *new_dev;
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator) {
+ new_dev = (struct loader_device *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(struct loader_device),
+ sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+ } else {
+#endif
+ new_dev = (struct loader_device *)malloc(sizeof(struct loader_device));
+ }
+
+ if (!new_dev) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_create_logical_device: Failed to alloc struct "
+ "loader_device");
+ return NULL;
+ }
+
+ memset(new_dev, 0, sizeof(struct loader_device));
+ if (pAllocator) {
+ new_dev->alloc_callbacks = *pAllocator;
+ }
+
+ return new_dev;
+}
+
+void loader_add_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term, struct loader_device *dev) {
+ dev->next = icd_term->logical_device_list;
+ icd_term->logical_device_list = dev;
+}
+
+void loader_remove_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term,
+ struct loader_device *found_dev, const VkAllocationCallbacks *pAllocator) {
+ struct loader_device *dev, *prev_dev;
+
+ if (!icd_term || !found_dev) return;
+
+ prev_dev = NULL;
+ dev = icd_term->logical_device_list;
+ while (dev && dev != found_dev) {
+ prev_dev = dev;
+ dev = dev->next;
+ }
+
+ if (prev_dev)
+ prev_dev->next = found_dev->next;
+ else
+ icd_term->logical_device_list = found_dev->next;
+ loader_destroy_logical_device(inst, found_dev, pAllocator);
+}
+
+static void loader_icd_destroy(struct loader_instance *ptr_inst, struct loader_icd_term *icd_term,
+ const VkAllocationCallbacks *pAllocator) {
+ ptr_inst->total_icd_count--;
+ for (struct loader_device *dev = icd_term->logical_device_list; dev;) {
+ struct loader_device *next_dev = dev->next;
+ loader_destroy_logical_device(ptr_inst, dev, pAllocator);
+ dev = next_dev;
+ }
+
+ loader_instance_heap_free(ptr_inst, icd_term);
+}
+
+static struct loader_icd_term *loader_icd_create(const struct loader_instance *inst) {
+ struct loader_icd_term *icd_term;
+
+ icd_term = loader_instance_heap_alloc(inst, sizeof(struct loader_icd_term), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (!icd_term) {
+ return NULL;
+ }
+
+ memset(icd_term, 0, sizeof(struct loader_icd_term));
+
+ return icd_term;
+}
+
+static struct loader_icd_term *loader_icd_add(struct loader_instance *ptr_inst, const struct loader_scanned_icd *scanned_icd) {
+ struct loader_icd_term *icd_term;
+
+ icd_term = loader_icd_create(ptr_inst);
+ if (!icd_term) {
+ return NULL;
+ }
+
+ icd_term->scanned_icd = scanned_icd;
+ icd_term->this_instance = ptr_inst;
+
+ // Prepend to the list
+ icd_term->next = ptr_inst->icd_terms;
+ ptr_inst->icd_terms = icd_term;
+ ptr_inst->total_icd_count++;
+
+ return icd_term;
+}
+
+// Determine the ICD interface version to use.
+// @param icd
+// @param pVersion Output parameter indicating which version to use or 0 if
+// the negotiation API is not supported by the ICD
+// @return bool indicating true if the selected interface version is supported
+// by the loader, false indicates the version is not supported
+bool loader_get_icd_interface_version(PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version, uint32_t *pVersion) {
+ if (fp_negotiate_icd_version == NULL) {
+ // ICD does not support the negotiation API, it supports version 0 or 1
+ // calling code must determine if it is version 0 or 1
+ *pVersion = 0;
+ } else {
+ // ICD supports the negotiation API, so call it with the loader's
+ // latest version supported
+ *pVersion = CURRENT_LOADER_ICD_INTERFACE_VERSION;
+ VkResult result = fp_negotiate_icd_version(pVersion);
+
+ if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
+ // ICD no longer supports the loader's latest interface version so
+ // fail loading the ICD
+ return false;
+ }
+ }
+
+#if MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION > 0
+ if (*pVersion < MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION) {
+ // Loader no longer supports the ICD's latest interface version so fail
+ // loading the ICD
+ return false;
+ }
+#endif
+ return true;
+}
+
+void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
+ if (0 != icd_tramp_list->capacity) {
+ for (uint32_t i = 0; i < icd_tramp_list->count; i++) {
+ loader_platform_close_library(icd_tramp_list->scanned_list[i].handle);
+ loader_instance_heap_free(inst, icd_tramp_list->scanned_list[i].lib_name);
+ }
+ loader_instance_heap_free(inst, icd_tramp_list->scanned_list);
+ icd_tramp_list->capacity = 0;
+ icd_tramp_list->count = 0;
+ icd_tramp_list->scanned_list = NULL;
+ }
+}
+
+static VkResult loader_scanned_icd_init(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
+ VkResult err = VK_SUCCESS;
+ loader_scanned_icd_clear(inst, icd_tramp_list);
+ icd_tramp_list->capacity = 8 * sizeof(struct loader_scanned_icd);
+ icd_tramp_list->scanned_list = loader_instance_heap_alloc(inst, icd_tramp_list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == icd_tramp_list->scanned_list) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_scanned_icd_init: Realloc failed for layer list when "
+ "attempting to add new layer");
+ err = VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ return err;
+}
+
+static VkResult loader_scanned_icd_add(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
+ const char *filename, uint32_t api_version) {
+ loader_platform_dl_handle handle;
+ PFN_vkCreateInstance fp_create_inst;
+ PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
+ PFN_vkGetInstanceProcAddr fp_get_proc_addr;
+ PFN_GetPhysicalDeviceProcAddr fp_get_phys_dev_proc_addr = NULL;
+ PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version;
+ struct loader_scanned_icd *new_scanned_icd;
+ uint32_t interface_vers;
+ VkResult res = VK_SUCCESS;
+
+ // TODO implement smarter opening/closing of libraries. For now this
+ // function leaves libraries open and the scanned_icd_clear closes them
+ handle = loader_platform_open_library(filename);
+ if (NULL == handle) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, loader_platform_open_library_error(filename));
+ goto out;
+ }
+
+ // Get and settle on an ICD interface version
+ fp_negotiate_icd_version = loader_platform_get_proc_address(handle, "vk_icdNegotiateLoaderICDInterfaceVersion");
+
+ if (!loader_get_icd_interface_version(fp_negotiate_icd_version, &interface_vers)) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_scanned_icd_add: ICD %s doesn't support interface"
+ " version compatible with loader, skip this ICD.",
+ filename);
+ goto out;
+ }
+
+ fp_get_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr");
+ if (NULL == fp_get_proc_addr) {
+ assert(interface_vers == 0);
+ // Use deprecated interface from version 0
+ fp_get_proc_addr = loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr");
+ if (NULL == fp_get_proc_addr) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_scanned_icd_add: Attempt to retrieve either "
+ "\'vkGetInstanceProcAddr\' or "
+ "\'vk_icdGetInstanceProcAddr\' from ICD %s failed.",
+ filename);
+ goto out;
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_scanned_icd_add: Using deprecated ICD "
+ "interface of \'vkGetInstanceProcAddr\' instead of "
+ "\'vk_icdGetInstanceProcAddr\' for ICD %s",
+ filename);
+ }
+ fp_create_inst = loader_platform_get_proc_address(handle, "vkCreateInstance");
+ if (NULL == fp_create_inst) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_scanned_icd_add: Failed querying "
+ "\'vkCreateInstance\' via dlsym/loadlibrary for "
+ "ICD %s",
+ filename);
+ goto out;
+ }
+ fp_get_inst_ext_props = loader_platform_get_proc_address(handle, "vkEnumerateInstanceExtensionProperties");
+ if (NULL == fp_get_inst_ext_props) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_scanned_icd_add: Could not get \'vkEnumerate"
+ "InstanceExtensionProperties\' via dlsym/loadlibrary "
+ "for ICD %s",
+ filename);
+ goto out;
+ }
+ } else {
+ // Use newer interface version 1 or later
+ if (interface_vers == 0) {
+ interface_vers = 1;
+ }
+
+ fp_create_inst = (PFN_vkCreateInstance)fp_get_proc_addr(NULL, "vkCreateInstance");
+ if (NULL == fp_create_inst) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_scanned_icd_add: Could not get "
+ "\'vkCreateInstance\' via \'vk_icdGetInstanceProcAddr\'"
+ " for ICD %s",
+ filename);
+ goto out;
+ }
+ fp_get_inst_ext_props =
+ (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(NULL, "vkEnumerateInstanceExtensionProperties");
+ if (NULL == fp_get_inst_ext_props) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_scanned_icd_add: Could not get \'vkEnumerate"
+ "InstanceExtensionProperties\' via "
+ "\'vk_icdGetInstanceProcAddr\' for ICD %s",
+ filename);
+ goto out;
+ }
+ fp_get_phys_dev_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetPhysicalDeviceProcAddr");
+ }
+
+ // check for enough capacity
+ if ((icd_tramp_list->count * sizeof(struct loader_scanned_icd)) >= icd_tramp_list->capacity) {
+ void *new_ptr = loader_instance_heap_realloc(inst, icd_tramp_list->scanned_list, icd_tramp_list->capacity,
+ icd_tramp_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_ptr) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_scanned_icd_add: Realloc failed on icd library list for ICD %s", filename);
+ goto out;
+ }
+ icd_tramp_list->scanned_list = new_ptr;
+
+ // double capacity
+ icd_tramp_list->capacity *= 2;
+ }
+
+ new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]);
+ new_scanned_icd->handle = handle;
+ new_scanned_icd->api_version = api_version;
+ new_scanned_icd->GetInstanceProcAddr = fp_get_proc_addr;
+ new_scanned_icd->GetPhysicalDeviceProcAddr = fp_get_phys_dev_proc_addr;
+ new_scanned_icd->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props;
+ new_scanned_icd->CreateInstance = fp_create_inst;
+ new_scanned_icd->interface_version = interface_vers;
+
+ new_scanned_icd->lib_name = (char *)loader_instance_heap_alloc(inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_scanned_icd->lib_name) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_scanned_icd_add: Out of memory can't add ICD %s", filename);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ strcpy(new_scanned_icd->lib_name, filename);
+ icd_tramp_list->count++;
+
+out:
+
+ return res;
+}
+
+static void loader_debug_init(void) {
+ char *env, *orig;
+
+ if (g_loader_debug > 0) return;
+
+ g_loader_debug = 0;
+
+ // Parse comma-separated debug options
+ orig = env = loader_getenv("VK_LOADER_DEBUG", NULL);
+ while (env) {
+ char *p = strchr(env, ',');
+ size_t len;
+
+ if (p)
+ len = p - env;
+ else
+ len = strlen(env);
+
+ if (len > 0) {
+ if (strncmp(env, "all", len) == 0) {
+ g_loader_debug = ~0u;
+ g_loader_log_msgs = ~0u;
+ } else if (strncmp(env, "warn", len) == 0) {
+ g_loader_debug |= LOADER_WARN_BIT;
+ g_loader_log_msgs |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
+ } else if (strncmp(env, "info", len) == 0) {
+ g_loader_debug |= LOADER_INFO_BIT;
+ g_loader_log_msgs |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+ } else if (strncmp(env, "perf", len) == 0) {
+ g_loader_debug |= LOADER_PERF_BIT;
+ g_loader_log_msgs |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+ } else if (strncmp(env, "error", len) == 0) {
+ g_loader_debug |= LOADER_ERROR_BIT;
+ g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
+ } else if (strncmp(env, "debug", len) == 0) {
+ g_loader_debug |= LOADER_DEBUG_BIT;
+ g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+ }
+ }
+
+ if (!p) break;
+
+ env = p + 1;
+ }
+
+ loader_free_getenv(orig, NULL);
+}
+
+void loader_initialize(void) {
+ // initialize mutexes
+ loader_platform_thread_create_mutex(&loader_lock);
+ loader_platform_thread_create_mutex(&loader_json_lock);
+
+ // initialize logging
+ loader_debug_init();
+
+ // initial cJSON to use alloc callbacks
+ cJSON_Hooks alloc_fns = {
+ .malloc_fn = loader_instance_tls_heap_alloc, .free_fn = loader_instance_tls_heap_free,
+ };
+ cJSON_InitHooks(&alloc_fns);
+
+#if defined(_WIN32)
+ // This is needed to ensure that newer APIs are available right away
+ // and not after the first call that has been statically linked
+ LoadLibrary("gdi32.dll");
+#endif
+}
+
+struct loader_data_files {
+ uint32_t count;
+ uint32_t alloc_count;
+ char **filename_list;
+};
+
+void loader_release() {
+ // release mutexes
+ loader_platform_thread_delete_mutex(&loader_lock);
+ loader_platform_thread_delete_mutex(&loader_json_lock);
+}
+
+// Get next file or dirname given a string list or registry key path
+//
+// \returns
+// A pointer to first char in the next path.
+// The next path (or NULL) in the list is returned in next_path.
+// Note: input string is modified in some cases. PASS IN A COPY!
+static char *loader_get_next_path(char *path) {
+ uint32_t len;
+ char *next;
+
+ if (path == NULL) return NULL;
+ next = strchr(path, PATH_SEPARATOR);
+ if (next == NULL) {
+ len = (uint32_t)strlen(path);
+ next = path + len;
+ } else {
+ *next = '\0';
+ next++;
+ }
+
+ return next;
+}
+
+// Given a path which is absolute or relative, expand the path if relative or
+// leave the path unmodified if absolute. The base path to prepend to relative
+// paths is given in rel_base.
+//
+// @return - A string in out_fullpath of the full absolute path
+static void loader_expand_path(const char *path, const char *rel_base, size_t out_size, char *out_fullpath) {
+ if (loader_platform_is_path_absolute(path)) {
+ // do not prepend a base to an absolute path
+ rel_base = "";
+ }
+
+ loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
+}
+
+// Given a filename (file) and a list of paths (dir), try to find an existing
+// file in the paths. If filename already is a path then no searching in the given paths.
+//
+// @return - A string in out_fullpath of either the full path or file.
+static void loader_get_fullpath(const char *file, const char *dirs, size_t out_size, char *out_fullpath) {
+ if (!loader_platform_is_path(file) && *dirs) {
+ char *dirs_copy, *dir, *next_dir;
+
+ dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
+ strcpy(dirs_copy, dirs);
+
+ // find if file exists after prepending paths in given list
+ for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir)); dir = next_dir) {
+ loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
+ if (loader_platform_file_exists(out_fullpath)) {
+ return;
+ }
+ }
+ }
+
+ (void)snprintf(out_fullpath, out_size, "%s", file);
+}
+
+// Read a JSON file into a buffer.
+//
+// @return - A pointer to a cJSON object representing the JSON parse tree.
+// This returned buffer should be freed by caller.
+static VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
+ FILE *file = NULL;
+ char *json_buf;
+ size_t len;
+ VkResult res = VK_SUCCESS;
+
+ if (NULL == json) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_json: Received invalid JSON file");
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ *json = NULL;
+
+ file = fopen(filename, "rb");
+ if (!file) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_json: Failed to open JSON file %s", filename);
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+ fseek(file, 0, SEEK_END);
+ len = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ json_buf = (char *)loader_stack_alloc(len + 1);
+ if (json_buf == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_get_json: Failed to allocate space for "
+ "JSON file %s buffer of length %d",
+ filename, len);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ if (fread(json_buf, sizeof(char), len, file) != len) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_json: Failed to read JSON file %s.", filename);
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+ json_buf[len] = '\0';
+
+ // Parse text from file
+ *json = cJSON_Parse(json_buf);
+ if (*json == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_get_json: Failed to parse JSON file %s, "
+ "this is usually because something ran out of "
+ "memory.",
+ filename);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+out:
+ if (NULL != file) {
+ fclose(file);
+ }
+
+ return res;
+}
+
+// Verify that all component layers in a meta-layer are valid.
+static bool verifyMetaLayerComponentLayers(const struct loader_instance *inst, struct loader_layer_properties *prop,
+ struct loader_layer_list *instance_layers) {
+ bool success = true;
+ const uint32_t expected_major = VK_VERSION_MAJOR(prop->info.specVersion);
+ const uint32_t expected_minor = VK_VERSION_MINOR(prop->info.specVersion);
+
+ for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) {
+ if (!loaderFindLayerNameInList(prop->component_layer_names[comp_layer], instance_layers)) {
+ if (NULL != inst) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "verifyMetaLayerComponentLayers: Meta-layer %s can't find component layer %s at index %d."
+ " Skipping this layer.",
+ prop->info.layerName, prop->component_layer_names[comp_layer], comp_layer);
+ }
+ success = false;
+ break;
+ } else {
+ struct loader_layer_properties *comp_prop =
+ loaderFindLayerProperty(prop->component_layer_names[comp_layer], instance_layers);
+ if (comp_prop == NULL) {
+ if (NULL != inst) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "verifyMetaLayerComponentLayers: Meta-layer %s can't find property for component layer "
+ "%s at index %d. Skipping this layer.",
+ prop->info.layerName, prop->component_layer_names[comp_layer], comp_layer);
+ }
+ success = false;
+ break;
+ }
+
+ // Check the version of each layer, they need to at least match MAJOR and MINOR
+ uint32_t cur_major = VK_VERSION_MAJOR(comp_prop->info.specVersion);
+ uint32_t cur_minor = VK_VERSION_MINOR(comp_prop->info.specVersion);
+ if (cur_major != expected_major || cur_minor != expected_minor) {
+ if (NULL != inst) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "verifyMetaLayerComponentLayers: Meta-layer uses API version %d.%d, but component "
+ "layer %d uses API version %d.%d. Skipping this layer.",
+ expected_major, expected_minor, comp_layer, cur_major, cur_minor);
+ }
+ success = false;
+ break;
+ }
+
+ // Make sure the layer isn't using it's own name
+ if (!strcmp(prop->info.layerName, prop->component_layer_names[comp_layer])) {
+ if (NULL != inst) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "verifyMetaLayerComponentLayers: Meta-layer %s lists itself in its component layer "
+ "list at index %d. Skipping this layer.",
+ prop->info.layerName, comp_layer);
+ }
+ success = false;
+ break;
+ }
+ if (comp_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
+ if (NULL != inst) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "verifyMetaLayerComponentLayers: Adding meta-layer %s which also contains meta-layer %s",
+ prop->info.layerName, comp_prop->info.layerName);
+ }
+
+ // Make sure if the layer is using a meta-layer in its component list that we also verify that.
+ if (!verifyMetaLayerComponentLayers(inst, comp_prop, instance_layers)) {
+ if (NULL != inst) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Meta-layer %s component layer %s can not find all component layers."
+ " Skipping this layer.",
+ prop->info.layerName, prop->component_layer_names[comp_layer]);
+ }
+ success = false;
+ break;
+ }
+ }
+
+ // Add any instance and device extensions from component layers to this layer
+ // list, so that anyone querying extensions will only need to look at the meta-layer
+ for (uint32_t ext = 0; ext < comp_prop->instance_extension_list.count; ext++) {
+ if (NULL != inst) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
+ "Meta-layer %s component layer %s adding instance extension %s", prop->info.layerName,
+ prop->component_layer_names[comp_layer], comp_prop->instance_extension_list.list[ext].extensionName);
+ }
+ if (!has_vk_extension_property(&comp_prop->instance_extension_list.list[ext], &prop->instance_extension_list)) {
+ loader_add_to_ext_list(inst, &prop->instance_extension_list, 1, &comp_prop->instance_extension_list.list[ext]);
+ }
+ }
+
+ for (uint32_t ext = 0; ext < comp_prop->device_extension_list.count; ext++) {
+ if (NULL != inst) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
+ "Meta-layer %s component layer %s adding device extension %s", prop->info.layerName,
+ prop->component_layer_names[comp_layer],
+ comp_prop->device_extension_list.list[ext].props.extensionName);
+ }
+ if (!has_vk_dev_ext_property(&comp_prop->device_extension_list.list[ext].props, &prop->device_extension_list)) {
+ loader_add_to_dev_ext_list(inst, &prop->device_extension_list,
+ &comp_prop->device_extension_list.list[ext].props, 0, NULL);
+ }
+ }
+ }
+ }
+ if (success) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Meta-layer %s all %d component layers appear to be valid.",
+ prop->info.layerName, prop->num_component_layers);
+ }
+ return success;
+}
+
+// Verify that all meta-layers in a layer list are valid.
+static void VerifyAllMetaLayers(struct loader_instance *inst, struct loader_layer_list *instance_layers,
+ bool *override_layer_present) {
+ *override_layer_present = false;
+ for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) {
+ struct loader_layer_properties *prop = &instance_layers->list[i];
+
+ // If this is a meta-layer, make sure it is valid
+ if ((prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) && !verifyMetaLayerComponentLayers(inst, prop, instance_layers)) {
+ if (NULL != inst) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
+ "Removing meta-layer %s from instance layer list since it appears invalid.", prop->info.layerName);
+ }
+
+ // Delete the component layers
+ loader_instance_heap_free(inst, prop->component_layer_names);
+ if (prop->blacklist_layer_names != NULL) {
+ loader_instance_heap_free(inst, prop->blacklist_layer_names);
+ }
+
+ // Remove the current invalid meta-layer from the layer list. Use memmove since we are
+ // overlapping the source and destination addresses.
+ memmove(&instance_layers->list[i], &instance_layers->list[i + 1],
+ sizeof(struct loader_layer_properties) * (instance_layers->count - 1 - i));
+
+ // Decrement the count (because we now have one less) and decrement the loop index since we need to
+ // re-check this index.
+ instance_layers->count--;
+ i--;
+ } else if (prop->is_override && loaderImplicitLayerIsEnabled(inst, prop)) {
+ *override_layer_present = true;
+ }
+ }
+}
+
+// This structure is used to store the json file version
+// in a more manageable way.
+typedef struct {
+ uint16_t major;
+ uint16_t minor;
+ uint16_t patch;
+} layer_json_version;
+
+static inline bool layer_json_supports_pre_instance_tag(const layer_json_version *layer_json) {
+ // Supported versions started in 1.1.2, so anything newer
+ return layer_json->major > 1 || layer_json->minor > 1 || (layer_json->minor == 1 && layer_json->patch > 1);
+}
+
+static VkResult loaderReadLayerJson(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list,
+ cJSON *layer_node, layer_json_version version, cJSON *item, cJSON *disable_environment,
+ bool is_implicit, char *filename) {
+ char *temp;
+ char *name, *type, *library_path_str, *api_version;
+ char *implementation_version, *description;
+ cJSON *ext_item;
+ cJSON *library_path;
+ cJSON *component_layers;
+ cJSON *override_paths;
+ cJSON *blacklisted_layers;
+ VkExtensionProperties ext_prop;
+ VkResult result = VK_ERROR_INITIALIZATION_FAILED;
+ struct loader_layer_properties *props = NULL;
+ int i, j;
+
+// The following are required in the "layer" object:
+// (required) "name"
+// (required) "type"
+// (required) "library_path"
+// (required) "api_version"
+// (required) "implementation_version"
+// (required) "description"
+// (required for implicit layers) "disable_environment"
+#define GET_JSON_OBJECT(node, var) \
+ { \
+ var = cJSON_GetObjectItem(node, #var); \
+ if (var == NULL) { \
+ layer_node = layer_node->next; \
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \
+ "Didn't find required layer object %s in manifest " \
+ "JSON file, skipping this layer", \
+ #var); \
+ goto out; \
+ } \
+ }
+#define GET_JSON_ITEM(node, var) \
+ { \
+ item = cJSON_GetObjectItem(node, #var); \
+ if (item == NULL) { \
+ layer_node = layer_node->next; \
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \
+ "Didn't find required layer value %s in manifest JSON " \
+ "file, skipping this layer", \
+ #var); \
+ goto out; \
+ } \
+ temp = cJSON_Print(item); \
+ if (temp == NULL) { \
+ layer_node = layer_node->next; \
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \
+ "Problem accessing layer value %s in manifest JSON " \
+ "file, skipping this layer", \
+ #var); \
+ result = VK_ERROR_OUT_OF_HOST_MEMORY; \
+ goto out; \
+ } \
+ temp[strlen(temp) - 1] = '\0'; \
+ var = loader_stack_alloc(strlen(temp) + 1); \
+ strcpy(var, &temp[1]); \
+ cJSON_Free(temp); \
+ }
+ GET_JSON_ITEM(layer_node, name)
+ GET_JSON_ITEM(layer_node, type)
+ GET_JSON_ITEM(layer_node, api_version)
+ GET_JSON_ITEM(layer_node, implementation_version)
+ GET_JSON_ITEM(layer_node, description)
+
+ // Add list entry
+ if (!strcmp(type, "DEVICE")) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "Device layers are deprecated skipping this layer");
+ layer_node = layer_node->next;
+ goto out;
+ }
+
+ // Allow either GLOBAL or INSTANCE type interchangeably to handle
+ // layers that must work with older loaders
+ if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) {
+ if (layer_instance_list == NULL) {
+ layer_node = layer_node->next;
+ goto out;
+ }
+ props = loaderGetNextLayerPropertySlot(inst, layer_instance_list);
+ if (NULL == props) {
+ // Error already triggered in loaderGetNextLayerPropertySlot.
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ props->type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER;
+ if (!is_implicit) {
+ props->type_flags |= VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER;
+ }
+ } else {
+ layer_node = layer_node->next;
+ goto out;
+ }
+
+ // Expiration date for override layer. Field starte with JSON file 1.1.2 and
+ // is completely optional. So, no check put in place.
+ if (!strcmp(name, VK_OVERRIDE_LAYER_NAME)) {
+ cJSON *expiration;
+
+ if (version.major < 1 && version.minor < 1 && version.patch < 2) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Override layer expiration date not added until version 1.1.2. Please update JSON file version appropriately.");
+ }
+
+ props->is_override = true;
+ expiration = cJSON_GetObjectItem(layer_node, "expiration_date");
+ if (NULL != expiration) {
+ char date_copy[32];
+ uint8_t cur_item = 0;
+
+ // Get the string for the current item
+ temp = cJSON_Print(expiration);
+ if (temp == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Problem accessing layer value 'expiration_date' in manifest JSON file, skipping this layer");
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ temp[strlen(temp) - 1] = '\0';
+ strcpy(date_copy, &temp[1]);
+ cJSON_Free(temp);
+
+ if (strlen(date_copy) == 16) {
+ char *cur_start = &date_copy[0];
+ char *next_dash = strchr(date_copy, '-');
+ if (NULL != next_dash) {
+ while (cur_item < 5 && strlen(cur_start)) {
+ if (next_dash != NULL) {
+ *next_dash = '\0';
+ }
+ switch (cur_item) {
+ case 0: // Year
+ props->expiration.year = atoi(cur_start);
+ break;
+ case 1: // Month
+ props->expiration.month = atoi(cur_start);
+ break;
+ case 2: // Day
+ props->expiration.day = atoi(cur_start);
+ break;
+ case 3: // Hour
+ props->expiration.hour = atoi(cur_start);
+ break;
+ case 4: // Minute
+ props->expiration.minute = atoi(cur_start);
+ props->has_expiration = true;
+ break;
+ default: // Ignore
+ break;
+ }
+ if (next_dash != NULL) {
+ cur_start = next_dash + 1;
+ next_dash = strchr(cur_start, '-');
+ }
+ cur_item++;
+ }
+ }
+ }
+ }
+ }
+
+ // Library path no longer required unless component_layers is also not defined
+ library_path = cJSON_GetObjectItem(layer_node, "library_path");
+ component_layers = cJSON_GetObjectItem(layer_node, "component_layers");
+ if (NULL != library_path) {
+ if (NULL != component_layers) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Indicating meta-layer-specific component_layers, but also "
+ "defining layer library path. Both are not compatible, so "
+ "skipping this layer");
+ goto out;
+ }
+ props->num_component_layers = 0;
+ props->component_layer_names = NULL;
+
+ temp = cJSON_Print(library_path);
+ if (NULL == temp) {
+ layer_node = layer_node->next;
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Problem accessing layer value library_path in manifest JSON "
+ "file, skipping this layer");
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ temp[strlen(temp) - 1] = '\0';
+ library_path_str = loader_stack_alloc(strlen(temp) + 1);
+ strcpy(library_path_str, &temp[1]);
+ cJSON_Free(temp);
+
+ char *fullpath = props->lib_name;
+ char *rel_base;
+ if (NULL != library_path_str) {
+ if (loader_platform_is_path(library_path_str)) {
+ // A relative or absolute path
+ char *name_copy = loader_stack_alloc(strlen(filename) + 1);
+ strcpy(name_copy, filename);
+ rel_base = loader_platform_dirname(name_copy);
+ loader_expand_path(library_path_str, rel_base, MAX_STRING_SIZE, fullpath);
+ } else {
+// A filename which is assumed in a system directory
+#if defined(DEFAULT_VK_LAYERS_PATH)
+ loader_get_fullpath(library_path_str, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
+#else
+ loader_get_fullpath(library_path_str, "", MAX_STRING_SIZE, fullpath);
+#endif
+ }
+ }
+ } else if (NULL != component_layers) {
+ if (version.major == 1 && (version.minor < 1 || version.patch < 1)) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Indicating meta-layer-specific component_layers, but using older "
+ "JSON file version.");
+ }
+ int count = cJSON_GetArraySize(component_layers);
+ props->num_component_layers = count;
+
+ // Allocate buffer for layer names
+ props->component_layer_names =
+ loader_instance_heap_alloc(inst, sizeof(char[MAX_STRING_SIZE]) * count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == props->component_layer_names) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ // Copy the component layers into the array
+ for (i = 0; i < count; i++) {
+ cJSON *comp_layer = cJSON_GetArrayItem(component_layers, i);
+ if (NULL != comp_layer) {
+ temp = cJSON_Print(comp_layer);
+ if (NULL == temp) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ temp[strlen(temp) - 1] = '\0';
+ strncpy(props->component_layer_names[i], temp + 1, MAX_STRING_SIZE - 1);
+ props->component_layer_names[i][MAX_STRING_SIZE - 1] = '\0';
+ cJSON_Free(temp);
+ }
+ }
+
+ // This is now, officially, a meta-layer
+ props->type_flags |= VK_LAYER_TYPE_FLAG_META_LAYER;
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Encountered meta-layer %s", name);
+
+ // Make sure we set up other things so we head down the correct branches below
+ library_path_str = NULL;
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Layer missing both library_path and component_layers fields. One or the "
+ "other MUST be defined. Skipping this layer");
+ goto out;
+ }
+
+ props->num_blacklist_layers = 0;
+ props->blacklist_layer_names = NULL;
+ blacklisted_layers = cJSON_GetObjectItem(layer_node, "blacklisted_layers");
+ if (blacklisted_layers != NULL) {
+ if (strcmp(name, VK_OVERRIDE_LAYER_NAME)) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Layer %s contains a blacklist, but a blacklist can only be provided by the override metalayer. "
+ "This blacklist will be ignored.",
+ name);
+ } else {
+ props->num_blacklist_layers = cJSON_GetArraySize(blacklisted_layers);
+
+ // Allocate the blacklist array
+ props->blacklist_layer_names = loader_instance_heap_alloc(
+ inst, sizeof(char[MAX_STRING_SIZE]) * props->num_blacklist_layers, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (props->blacklist_layer_names == NULL) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ // Copy the blacklisted layers into the array
+ for (i = 0; i < (int)props->num_blacklist_layers; ++i) {
+ cJSON *black_layer = cJSON_GetArrayItem(blacklisted_layers, i);
+ if (black_layer == NULL) {
+ continue;
+ }
+ temp = cJSON_Print(black_layer);
+ if (temp == NULL) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ temp[strlen(temp) - 1] = '\0';
+ strncpy(props->blacklist_layer_names[i], temp + 1, MAX_STRING_SIZE - 1);
+ props->blacklist_layer_names[i][MAX_STRING_SIZE - 1] = '\0';
+ cJSON_Free(temp);
+ }
+ }
+ }
+
+ override_paths = cJSON_GetObjectItem(layer_node, "override_paths");
+ if (NULL != override_paths) {
+ if (version.major == 1 && (version.minor < 1 || version.patch < 1)) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Indicating meta-layer-specific override paths, but using older "
+ "JSON file version.");
+ }
+ int count = cJSON_GetArraySize(override_paths);
+ props->num_override_paths = count;
+
+ // Allocate buffer for override paths
+ props->override_paths =
+ loader_instance_heap_alloc(inst, sizeof(char[MAX_STRING_SIZE]) * count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == props->override_paths) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ // Copy the override paths into the array
+ for (i = 0; i < count; i++) {
+ cJSON *override_path = cJSON_GetArrayItem(override_paths, i);
+ if (NULL != override_path) {
+ temp = cJSON_Print(override_path);
+ if (NULL == temp) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ temp[strlen(temp) - 1] = '\0';
+ strncpy(props->override_paths[i], temp + 1, MAX_STRING_SIZE - 1);
+ props->override_paths[i][MAX_STRING_SIZE - 1] = '\0';
+ cJSON_Free(temp);
+ }
+ }
+ }
+
+ if (is_implicit) {
+ GET_JSON_OBJECT(layer_node, disable_environment)
+ }
+#undef GET_JSON_ITEM
+#undef GET_JSON_OBJECT
+
+ strncpy(props->info.layerName, name, sizeof(props->info.layerName));
+ props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
+ props->info.specVersion = loader_make_version(api_version);
+ props->info.implementationVersion = atoi(implementation_version);
+ strncpy((char *)props->info.description, description, sizeof(props->info.description));
+ props->info.description[sizeof(props->info.description) - 1] = '\0';
+ if (is_implicit) {
+ if (!disable_environment || !disable_environment->child) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Didn't find required layer child value disable_environment"
+ "in manifest JSON file, skipping this layer");
+ layer_node = layer_node->next;
+ goto out;
+ }
+ strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof(props->disable_env_var.name));
+ props->disable_env_var.name[sizeof(props->disable_env_var.name) - 1] = '\0';
+ strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof(props->disable_env_var.value));
+ props->disable_env_var.value[sizeof(props->disable_env_var.value) - 1] = '\0';
+ }
+
+// Now get all optional items and objects and put in list:
+// functions
+// instance_extensions
+// device_extensions
+// enable_environment (implicit layers only)
+#define GET_JSON_OBJECT(node, var) \
+ { var = cJSON_GetObjectItem(node, #var); }
+#define GET_JSON_ITEM(node, var) \
+ { \
+ item = cJSON_GetObjectItem(node, #var); \
+ if (item != NULL) { \
+ temp = cJSON_Print(item); \
+ if (temp != NULL) { \
+ temp[strlen(temp) - 1] = '\0'; \
+ var = loader_stack_alloc(strlen(temp) + 1); \
+ strcpy(var, &temp[1]); \
+ cJSON_Free(temp); \
+ } else { \
+ result = VK_ERROR_OUT_OF_HOST_MEMORY; \
+ goto out; \
+ } \
+ } \
+ }
+
+ cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
+ cJSON *entrypoints = NULL;
+ char *vkGetInstanceProcAddr = NULL;
+ char *vkGetDeviceProcAddr = NULL;
+ char *vkNegotiateLoaderLayerInterfaceVersion = NULL;
+ char *spec_version = NULL;
+ char **entry_array = NULL;
+
+ // Layer interface functions
+ // vkGetInstanceProcAddr
+ // vkGetDeviceProcAddr
+ // vkNegotiateLoaderLayerInterfaceVersion (starting with JSON file 1.1.0)
+ GET_JSON_OBJECT(layer_node, functions)
+ if (functions != NULL) {
+ if (version.major > 1 || version.minor >= 1) {
+ GET_JSON_ITEM(functions, vkNegotiateLoaderLayerInterfaceVersion)
+ if (vkNegotiateLoaderLayerInterfaceVersion != NULL)
+ strncpy(props->functions.str_negotiate_interface, vkNegotiateLoaderLayerInterfaceVersion,
+ sizeof(props->functions.str_negotiate_interface));
+ props->functions.str_negotiate_interface[sizeof(props->functions.str_negotiate_interface) - 1] = '\0';
+ } else {
+ props->functions.str_negotiate_interface[0] = '\0';
+ }
+ GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
+ GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
+ if (vkGetInstanceProcAddr != NULL) {
+ strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof(props->functions.str_gipa));
+ if (version.major > 1 || version.minor >= 1) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "Layer \"%s\" using deprecated \'vkGetInstanceProcAddr\' tag which was deprecated starting with JSON "
+ "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
+ "compatibility reasons it may be desirable to continue using the deprecated tag.",
+ name);
+ }
+ }
+ props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] = '\0';
+ if (vkGetDeviceProcAddr != NULL) {
+ strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof(props->functions.str_gdpa));
+ if (version.major > 1 || version.minor >= 1) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "Layer \"%s\" using deprecated \'vkGetDeviceProcAddr\' tag which was deprecated starting with JSON "
+ "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
+ "compatibility reasons it may be desirable to continue using the deprecated tag.",
+ name);
+ }
+ }
+ props->functions.str_gdpa[sizeof(props->functions.str_gdpa) - 1] = '\0';
+ }
+
+ // instance_extensions
+ // array of {
+ // name
+ // spec_version
+ // }
+ GET_JSON_OBJECT(layer_node, instance_extensions)
+ if (instance_extensions != NULL) {
+ int count = cJSON_GetArraySize(instance_extensions);
+ for (i = 0; i < count; i++) {
+ ext_item = cJSON_GetArrayItem(instance_extensions, i);
+ GET_JSON_ITEM(ext_item, name)
+ if (name != NULL) {
+ strncpy(ext_prop.extensionName, name, sizeof(ext_prop.extensionName));
+ ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] = '\0';
+ }
+ GET_JSON_ITEM(ext_item, spec_version)
+ if (NULL != spec_version) {
+ ext_prop.specVersion = atoi(spec_version);
+ } else {
+ ext_prop.specVersion = 0;
+ }
+ bool ext_unsupported = wsi_unsupported_instance_extension(&ext_prop);
+ if (!ext_unsupported) {
+ loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
+ }
+ }
+ }
+
+ // device_extensions
+ // array of {
+ // name
+ // spec_version
+ // entrypoints
+ // }
+ GET_JSON_OBJECT(layer_node, device_extensions)
+ if (device_extensions != NULL) {
+ int count = cJSON_GetArraySize(device_extensions);
+ for (i = 0; i < count; i++) {
+ ext_item = cJSON_GetArrayItem(device_extensions, i);
+ GET_JSON_ITEM(ext_item, name)
+ GET_JSON_ITEM(ext_item, spec_version)
+ if (name != NULL) {
+ strncpy(ext_prop.extensionName, name, sizeof(ext_prop.extensionName));
+ ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] = '\0';
+ }
+ if (NULL != spec_version) {
+ ext_prop.specVersion = atoi(spec_version);
+ } else {
+ ext_prop.specVersion = 0;
+ }
+ // entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
+ GET_JSON_OBJECT(ext_item, entrypoints)
+ int entry_count;
+ if (entrypoints == NULL) {
+ loader_add_to_dev_ext_list(inst, &props->device_extension_list, &ext_prop, 0, NULL);
+ continue;
+ }
+ entry_count = cJSON_GetArraySize(entrypoints);
+ if (entry_count) {
+ entry_array = (char **)loader_stack_alloc(sizeof(char *) * entry_count);
+ }
+ for (j = 0; j < entry_count; j++) {
+ ext_item = cJSON_GetArrayItem(entrypoints, j);
+ if (ext_item != NULL) {
+ temp = cJSON_Print(ext_item);
+ if (NULL == temp) {
+ entry_array[j] = NULL;
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ temp[strlen(temp) - 1] = '\0';
+ entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
+ strcpy(entry_array[j], &temp[1]);
+ cJSON_Free(temp);
+ }
+ }
+ loader_add_to_dev_ext_list(inst, &props->device_extension_list, &ext_prop, entry_count, entry_array);
+ }
+ }
+ if (is_implicit) {
+ GET_JSON_OBJECT(layer_node, enable_environment)
+
+ // enable_environment is optional
+ if (enable_environment) {
+ strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof(props->enable_env_var.name));
+ props->enable_env_var.name[sizeof(props->enable_env_var.name) - 1] = '\0';
+ strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof(props->enable_env_var.value));
+ props->enable_env_var.value[sizeof(props->enable_env_var.value) - 1] = '\0';
+ }
+ }
+
+ // Read in the pre-instance stuff
+ cJSON *pre_instance = cJSON_GetObjectItem(layer_node, "pre_instance_functions");
+ if (pre_instance) {
+ if (!layer_json_supports_pre_instance_tag(&version)) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "Found pre_instance_functions section in layer from \"%s\". "
+ "This section is only valid in manifest version 1.1.2 or later. The section will be ignored",
+ filename);
+ } else if (!is_implicit) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Found pre_instance_functions section in explicit layer from "
+ "\"%s\". This section is only valid in implicit layers. The section will be ignored",
+ filename);
+ } else {
+ cJSON *inst_ext_json = cJSON_GetObjectItem(pre_instance, "vkEnumerateInstanceExtensionProperties");
+ if (inst_ext_json) {
+ char *inst_ext_name = cJSON_Print(inst_ext_json);
+ if (inst_ext_name == NULL) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ size_t len = strlen(inst_ext_name) >= MAX_STRING_SIZE ? MAX_STRING_SIZE - 3 : strlen(inst_ext_name) - 2;
+ strncpy(props->pre_instance_functions.enumerate_instance_extension_properties, inst_ext_name + 1, len);
+ props->pre_instance_functions.enumerate_instance_extension_properties[len] = '\0';
+ cJSON_Free(inst_ext_name);
+ }
+
+ cJSON *inst_layer_json = cJSON_GetObjectItem(pre_instance, "vkEnumerateInstanceLayerProperties");
+ if (inst_layer_json) {
+ char *inst_layer_name = cJSON_Print(inst_layer_json);
+ if (inst_layer_name == NULL) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ size_t len = strlen(inst_layer_name) >= MAX_STRING_SIZE ? MAX_STRING_SIZE - 3 : strlen(inst_layer_name) - 2;
+ strncpy(props->pre_instance_functions.enumerate_instance_layer_properties, inst_layer_name + 1, len);
+ props->pre_instance_functions.enumerate_instance_layer_properties[len] = '\0';
+ cJSON_Free(inst_layer_name);
+ }
+
+ cJSON *inst_version_json = cJSON_GetObjectItem(pre_instance, "vkEnumerateInstanceVersion");
+ if (inst_version_json) {
+ char *inst_version_name = cJSON_Print(inst_version_json);
+ if (inst_version_json) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ size_t len = strlen(inst_version_name) >= MAX_STRING_SIZE ? MAX_STRING_SIZE - 3 : strlen(inst_version_name) - 2;
+ strncpy(props->pre_instance_functions.enumerate_instance_version, inst_version_name + 1, len);
+ props->pre_instance_functions.enumerate_instance_version[len] = '\0';
+ cJSON_Free(inst_version_name);
+ }
+ }
+ }
+
+ result = VK_SUCCESS;
+
+out:
+#undef GET_JSON_ITEM
+#undef GET_JSON_OBJECT
+
+ if (VK_SUCCESS != result && NULL != props) {
+ if (NULL != props->blacklist_layer_names) {
+ loader_instance_heap_free(inst, props->blacklist_layer_names);
+ }
+ if (NULL != props->component_layer_names) {
+ loader_instance_heap_free(inst, props->component_layer_names);
+ }
+ if (NULL != props->override_paths) {
+ loader_instance_heap_free(inst, props->override_paths);
+ }
+ props->num_blacklist_layers = 0;
+ props->blacklist_layer_names = NULL;
+ props->num_component_layers = 0;
+ props->component_layer_names = NULL;
+ props->num_override_paths = 0;
+ props->override_paths = NULL;
+ }
+
+ return result;
+}
+
+static inline bool isValidLayerJsonVersion(const layer_json_version *layer_json) {
+ // Supported versions are: 1.0.0, 1.0.1, and 1.1.0 - 1.1.2.
+ if ((layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch < 3) ||
+ (layer_json->major == 1 && layer_json->minor == 0 && layer_json->patch < 2)) {
+ return true;
+ }
+ return false;
+}
+
+static inline bool layerJsonSupportsMultipleLayers(const layer_json_version *layer_json) {
+ // Supported versions started in 1.0.1, so anything newer
+ if ((layer_json->major > 1 || layer_json->minor > 0 || layer_json->patch > 1)) {
+ return true;
+ }
+ return false;
+}
+
+// Given a cJSON struct (json) of the top level JSON object from layer manifest
+// file, add entry to the layer_list. Fill out the layer_properties in this list
+// entry from the input cJSON object.
+//
+// \returns
+// void
+// layer_list has a new entry and initialized accordingly.
+// If the json input object does not have all the required fields no entry
+// is added to the list.
+static VkResult loaderAddLayerProperties(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list,
+ cJSON *json, bool is_implicit, char *filename) {
+ // The following Fields in layer manifest file that are required:
+ // - "file_format_version"
+ // - If more than one "layer" object are used, then the "layers" array is
+ // required
+ VkResult result = VK_ERROR_INITIALIZATION_FAILED;
+ cJSON *item, *layers_node, *layer_node;
+ layer_json_version json_version = {0, 0, 0};
+ char *vers_tok;
+ cJSON *disable_environment = NULL;
+ item = cJSON_GetObjectItem(json, "file_format_version");
+ if (item == NULL) {
+ goto out;
+ }
+ char *file_vers = cJSON_PrintUnformatted(item);
+ if (NULL == file_vers) {
+ goto out;
+ }
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Found manifest file %s, version %s", filename, file_vers);
+ // Get the major/minor/and patch as integers for easier comparison
+ vers_tok = strtok(file_vers, ".\"\n\r");
+ if (NULL != vers_tok) {
+ json_version.major = (uint16_t)atoi(vers_tok);
+ vers_tok = strtok(NULL, ".\"\n\r");
+ if (NULL != vers_tok) {
+ json_version.minor = (uint16_t)atoi(vers_tok);
+ vers_tok = strtok(NULL, ".\"\n\r");
+ if (NULL != vers_tok) {
+ json_version.patch = (uint16_t)atoi(vers_tok);
+ }
+ }
+ }
+
+ if (!isValidLayerJsonVersion(&json_version)) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loaderAddLayerProperties: %s invalid layer manifest file version %d.%d.%d. May cause errors.", filename,
+ json_version.major, json_version.minor, json_version.patch);
+ }
+ cJSON_Free(file_vers);
+
+ // If "layers" is present, read in the array of layer objects
+ layers_node = cJSON_GetObjectItem(json, "layers");
+ if (layers_node != NULL) {
+ int numItems = cJSON_GetArraySize(layers_node);
+ if (!layerJsonSupportsMultipleLayers(&json_version)) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loaderAddLayerProperties: \'layers\' tag not supported until file version 1.0.1, but %s is reporting version %s",
+ filename, file_vers);
+ }
+ for (int curLayer = 0; curLayer < numItems; curLayer++) {
+ layer_node = cJSON_GetArrayItem(layers_node, curLayer);
+ if (layer_node == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loaderAddLayerProperties: Can not find 'layers' array element %d object in manifest JSON file %s. "
+ "Skipping this file",
+ curLayer, filename);
+ goto out;
+ }
+ result = loaderReadLayerJson(inst, layer_instance_list, layer_node, json_version, item, disable_environment,
+ is_implicit, filename);
+ }
+ } else {
+ // Otherwise, try to read in individual layers
+ layer_node = cJSON_GetObjectItem(json, "layer");
+ if (layer_node == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loaderAddLayerProperties: Can not find 'layer' object in manifest JSON file %s. Skipping this file.",
+ filename);
+ goto out;
+ }
+ // Loop through all "layer" objects in the file to get a count of them
+ // first.
+ uint16_t layer_count = 0;
+ cJSON *tempNode = layer_node;
+ do {
+ tempNode = tempNode->next;
+ layer_count++;
+ } while (tempNode != NULL);
+
+ // Throw a warning if we encounter multiple "layer" objects in file
+ // versions newer than 1.0.0. Having multiple objects with the same
+ // name at the same level is actually a JSON standard violation.
+ if (layer_count > 1 && layerJsonSupportsMultipleLayers(&json_version)) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderAddLayerProperties: Multiple 'layer' nodes are deprecated starting in file version \"1.0.1\". "
+ "Please use 'layers' : [] array instead in %s.",
+ filename);
+ } else {
+ do {
+ result = loaderReadLayerJson(inst, layer_instance_list, layer_node, json_version, item, disable_environment,
+ is_implicit, filename);
+ layer_node = layer_node->next;
+ } while (layer_node != NULL);
+ }
+ }
+
+out:
+
+ return result;
+}
+
+static inline size_t DetermineDataFilePathSize(const char *cur_path, size_t relative_path_size) {
+ size_t path_size = 0;
+
+ if (NULL != cur_path) {
+ // For each folder in cur_path, (detected by finding additional
+ // path separators in the string) we need to add the relative path on
+ // the end. Plus, leave an additional two slots on the end to add an
+ // additional directory slash and path separator if needed
+ path_size += strlen(cur_path) + relative_path_size + 2;
+ for (const char *x = cur_path; *x; ++x) {
+ if (*x == PATH_SEPARATOR) {
+ path_size += relative_path_size + 2;
+ }
+ }
+ }
+
+ return path_size;
+}
+
+static inline void CopyDataFilePath(const char *cur_path, const char *relative_path, size_t relative_path_size,
+ char **output_path) {
+ if (NULL != cur_path) {
+ uint32_t start = 0;
+ uint32_t stop = 0;
+ char *cur_write = *output_path;
+
+ while (cur_path[start] != '\0') {
+ while (cur_path[start] == PATH_SEPARATOR) {
+ start++;
+ }
+ stop = start;
+ while (cur_path[stop] != PATH_SEPARATOR && cur_path[stop] != '\0') {
+ stop++;
+ }
+ const size_t s = stop - start;
+ if (s) {
+ memcpy(cur_write, &cur_path[start], s);
+ cur_write += s;
+
+ // If last symbol written was not a directory symbol, add it.
+ if (*(cur_write - 1) != DIRECTORY_SYMBOL) {
+ *cur_write++ = DIRECTORY_SYMBOL;
+ }
+
+ if (relative_path_size > 0) {
+ memcpy(cur_write, relative_path, relative_path_size);
+ cur_write += relative_path_size;
+ }
+ *cur_write++ = PATH_SEPARATOR;
+ start = stop;
+ }
+ }
+ *output_path = cur_write;
+ }
+}
+
+// Check to see if there's enough space in the data file list. If not, add some.
+static inline VkResult CheckAndAdjustDataFileList(const struct loader_instance *inst, struct loader_data_files *out_files) {
+ if (out_files->count == 0) {
+ out_files->filename_list = loader_instance_heap_alloc(inst, 64 * sizeof(char *), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (NULL == out_files->filename_list) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "CheckAndAdjustDataFileList: Failed to allocate space for manifest file name list");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ out_files->alloc_count = 64;
+ } else if (out_files->count == out_files->alloc_count) {
+ size_t new_size = out_files->alloc_count * sizeof(char *) * 2;
+ void *new_ptr = loader_instance_heap_realloc(inst, out_files->filename_list, out_files->alloc_count * sizeof(char *),
+ new_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (NULL == new_ptr) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "CheckAndAdjustDataFileList: Failed to reallocate space for manifest file name list");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ out_files->filename_list = new_ptr;
+ out_files->alloc_count *= 2;
+ }
+
+ return VK_SUCCESS;
+}
+
+// If the file found is a manifest file name, add it to the out_files manifest list.
+static VkResult AddIfManifestFile(const struct loader_instance *inst, const char *file_name, struct loader_data_files *out_files) {
+ VkResult vk_result = VK_SUCCESS;
+
+ if (NULL == file_name || NULL == out_files) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "AddIfManfistFile: Received NULL pointer");
+ vk_result = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ // Look for files ending with ".json" suffix
+ size_t name_len = strlen(file_name);
+ const char *name_suffix = file_name + name_len - 5;
+ if ((name_len < 5) || 0 != strncmp(name_suffix, ".json", 5)) {
+ // Use incomplete to indicate invalid name, but to keep going.
+ vk_result = VK_INCOMPLETE;
+ goto out;
+ }
+
+ // Check and allocate space in the manifest list if necessary
+ vk_result = CheckAndAdjustDataFileList(inst, out_files);
+ if (VK_SUCCESS != vk_result) {
+ goto out;
+ }
+
+ out_files->filename_list[out_files->count] =
+ loader_instance_heap_alloc(inst, strlen(file_name) + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (out_files->filename_list[out_files->count] == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "AddIfManfistFile: Failed to allocate space for manifest file %d list",
+ out_files->count);
+ vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ strcpy(out_files->filename_list[out_files->count++], file_name);
+
+out:
+
+ return vk_result;
+}
+
+static VkResult AddDataFilesInPath(const struct loader_instance *inst, char *search_path, bool is_directory_list,
+ struct loader_data_files *out_files) {
+ VkResult vk_result = VK_SUCCESS;
+ DIR *dir_stream = NULL;
+ struct dirent *dir_entry;
+ char *cur_file;
+ char *next_file;
+ char *name;
+ char full_path[2048];
+#ifndef _WIN32
+ char temp_path[2048];
+#endif
+
+ // Now, parse the paths
+ next_file = search_path;
+ while (NULL != next_file && *next_file != '\0') {
+ name = NULL;
+ cur_file = next_file;
+ next_file = loader_get_next_path(cur_file);
+
+ // Get the next name in the list and verify it's valid
+ if (is_directory_list) {
+ dir_stream = opendir(cur_file);
+ if (NULL == dir_stream) {
+ continue;
+ }
+ while (1) {
+ dir_entry = readdir(dir_stream);
+ if (NULL == dir_entry) {
+ break;
+ }
+
+ name = &(dir_entry->d_name[0]);
+ loader_get_fullpath(name, cur_file, sizeof(full_path), full_path);
+ name = full_path;
+
+ VkResult local_res;
+ local_res = AddIfManifestFile(inst, name, out_files);
+
+ // Incomplete means this was not a valid data file.
+ if (local_res == VK_INCOMPLETE) {
+ continue;
+ } else if (local_res != VK_SUCCESS) {
+ vk_result = local_res;
+ break;
+ }
+ }
+ closedir(dir_stream);
+ if (vk_result != VK_SUCCESS) {
+ goto out;
+ }
+ } else {
+#ifdef _WIN32
+ name = cur_file;
+#else
+ // Only Linux has relative paths, make a copy of location so it isn't modified
+ size_t str_len;
+ if (NULL != next_file) {
+ str_len = next_file - cur_file + 1;
+ } else {
+ str_len = strlen(cur_file) + 1;
+ }
+ if (str_len > sizeof(temp_path)) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "AddDataFilesInPath: Path to %s too long\n", cur_file);
+ continue;
+ }
+ strcpy(temp_path, cur_file);
+ name = temp_path;
+#endif
+ loader_get_fullpath(cur_file, name, sizeof(full_path), full_path);
+ name = full_path;
+
+ VkResult local_res;
+ local_res = AddIfManifestFile(inst, name, out_files);
+
+ // Incomplete means this was not a valid data file.
+ if (local_res == VK_INCOMPLETE) {
+ continue;
+ } else if (local_res != VK_SUCCESS) {
+ vk_result = local_res;
+ break;
+ }
+ }
+ }
+
+out:
+
+ return vk_result;
+}
+
+// Look for data files in the provided paths, but first check the environment override to determine if we should use that
+// instead.
+static VkResult ReadDataFilesInSearchPaths(const struct loader_instance *inst, enum loader_data_files_type data_file_type,
+ const char *env_override, const char *path_override, const char *relative_location,
+ bool *override_active, struct loader_data_files *out_files) {
+ VkResult vk_result = VK_SUCCESS;
+ bool is_directory_list = true;
+ bool is_icd = (data_file_type == LOADER_DATA_FILE_MANIFEST_ICD);
+ char *override_env = NULL;
+ const char *override_path = NULL;
+ size_t search_path_size = 0;
+ char *search_path = NULL;
+ char *cur_path_ptr = NULL;
+ size_t rel_size = 0;
+#ifndef _WIN32
+ bool xdgconfig_alloc = true;
+ bool xdgdata_alloc = true;
+#endif
+
+#ifndef _WIN32
+ // Determine how much space is needed to generate the full search path
+ // for the current manifest files.
+ char *xdgconfdirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
+ char *xdgdatadirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
+ char *xdgdatahome = loader_secure_getenv("XDG_DATA_HOME", inst);
+ char *home = NULL;
+ char* home_root = NULL;
+
+ if (xdgconfdirs == NULL) {
+ xdgconfig_alloc = false;
+ }
+ if (xdgdatadirs == NULL) {
+ xdgdata_alloc = false;
+ }
+ if (xdgconfdirs == NULL || xdgconfdirs[0] == '\0') {
+ xdgconfdirs = FALLBACK_CONFIG_DIRS;
+ }
+ if (xdgdatadirs == NULL || xdgdatadirs[0] == '\0') {
+ xdgdatadirs = FALLBACK_DATA_DIRS;
+ }
+
+ // Only use HOME if XDG_DATA_HOME is not present on the system
+ if (NULL == xdgdatahome) {
+ home = loader_secure_getenv("HOME", inst);
+ if (home != NULL) {
+ home_root = loader_instance_heap_alloc(inst, strlen(home) + 14, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (home_root == NULL) {
+ vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ strcpy(home_root, home);
+ strcat(home_root, "/.local/share");
+ }
+ }
+#endif
+
+ if (path_override != NULL) {
+ override_path = path_override;
+ } else if (env_override != NULL) {
+#ifndef _WIN32
+ if (geteuid() != getuid() || getegid() != getgid()) {
+ // Don't allow setuid apps to use the env var:
+ env_override = NULL;
+ } else
+#endif
+ {
+ override_env = loader_secure_getenv(env_override, inst);
+
+ // The ICD override is actually a specific list of filenames, not directories
+ if (is_icd && NULL != override_env) {
+ is_directory_list = false;
+ }
+ override_path = override_env;
+ }
+ }
+
+ // Add two by default for NULL terminator and one path separator on end (just in case)
+ search_path_size = 2;
+
+ // If there's an override, use that (and the local folder if required) and nothing else
+ if (NULL != override_path) {
+ // Local folder and null terminator
+ search_path_size += strlen(override_path) + 1;
+ } else if (NULL == relative_location) {
+ // If there's no override, and no relative location, bail out. This is usually
+ // the case when we're on Windows and the default path is to use the registry.
+ goto out;
+ } else {
+ // Add the general search folders (with the appropriate relative folder added)
+ rel_size = strlen(relative_location);
+ if (rel_size == 0) {
+ goto out;
+ } else {
+#if defined(__APPLE__)
+ search_path_size += MAXPATHLEN;
+#endif
+#ifndef _WIN32
+ search_path_size += DetermineDataFilePathSize(xdgconfdirs, rel_size);
+ search_path_size += DetermineDataFilePathSize(xdgdatadirs, rel_size);
+ search_path_size += DetermineDataFilePathSize(SYSCONFDIR, rel_size);
+#if defined(EXTRASYSCONFDIR)
+ search_path_size += DetermineDataFilePathSize(EXTRASYSCONFDIR, rel_size);
+#endif
+ if (is_directory_list) {
+ if (!IsHighIntegrity()) {
+ search_path_size += DetermineDataFilePathSize(xdgdatahome, rel_size);
+ search_path_size += DetermineDataFilePathSize(home_root, rel_size);
+ }
+ }
+#endif
+ }
+ }
+
+ // Allocate the required space
+ search_path = loader_instance_heap_alloc(inst, search_path_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (NULL == search_path) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ReadDataFilesInSearchPaths: Failed to allocate space for search path of length %d", (uint32_t)search_path_size);
+ vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ cur_path_ptr = search_path;
+
+ // Add the remaining paths to the list
+ if (NULL != override_path) {
+ strcpy(cur_path_ptr, override_path);
+ } else {
+#ifndef _WIN32
+ if (rel_size > 0) {
+#if defined(__APPLE__)
+ // Add the bundle's Resources dir to the beginning of the search path.
+ // Looks for manifests in the bundle first, before any system directories.
+ CFBundleRef main_bundle = CFBundleGetMainBundle();
+ if (NULL != main_bundle) {
+ CFURLRef ref = CFBundleCopyResourcesDirectoryURL(main_bundle);
+ if (NULL != ref) {
+ if (CFURLGetFileSystemRepresentation(ref, TRUE, (UInt8 *)cur_path_ptr, search_path_size)) {
+ cur_path_ptr += strlen(cur_path_ptr);
+ *cur_path_ptr++ = DIRECTORY_SYMBOL;
+ memcpy(cur_path_ptr, relative_location, rel_size);
+ cur_path_ptr += rel_size;
+ *cur_path_ptr++ = PATH_SEPARATOR;
+ }
+ CFRelease(ref);
+ }
+ }
+#endif
+ CopyDataFilePath(xdgconfdirs, relative_location, rel_size, &cur_path_ptr);
+ CopyDataFilePath(SYSCONFDIR, relative_location, rel_size, &cur_path_ptr);
+#if defined(EXTRASYSCONFDIR)
+ CopyDataFilePath(EXTRASYSCONFDIR, relative_location, rel_size, &cur_path_ptr);
+#endif
+ CopyDataFilePath(xdgdatadirs, relative_location, rel_size, &cur_path_ptr);
+ if (is_directory_list) {
+ CopyDataFilePath(xdgdatahome, relative_location, rel_size, &cur_path_ptr);
+ CopyDataFilePath(home_root, relative_location, rel_size, &cur_path_ptr);
+ }
+ }
+
+ // Remove the last path separator
+ --cur_path_ptr;
+
+ assert(cur_path_ptr - search_path < (ptrdiff_t)search_path_size);
+ *cur_path_ptr = '\0';
+#endif
+ }
+
+ // Print out the paths being searched if debugging is enabled
+ if (search_path_size > 0) {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
+ "ReadDataFilesInSearchPaths: Searching the following paths for manifest files: %s\n", search_path);
+ }
+
+ // Now, parse the paths and add any manifest files found in them.
+ vk_result = AddDataFilesInPath(inst, search_path, is_directory_list, out_files);
+
+ if (NULL != override_path) {
+ *override_active = true;
+ } else {
+ *override_active = false;
+ }
+
+out:
+
+ if (NULL != override_env) {
+ loader_free_getenv(override_env, inst);
+ }
+#ifndef _WIN32
+ if (xdgconfig_alloc) {
+ loader_free_getenv(xdgconfdirs, inst);
+ }
+ if (xdgdata_alloc) {
+ loader_free_getenv(xdgdatadirs, inst);
+ }
+ if (NULL != xdgdatahome) {
+ loader_free_getenv(xdgdatahome, inst);
+ }
+ if (NULL != home) {
+ loader_free_getenv(home, inst);
+ }
+ if (NULL != home_root) {
+ loader_instance_heap_free(inst, home_root);
+ }
+#endif
+
+ if (NULL != search_path) {
+ loader_instance_heap_free(inst, search_path);
+ }
+
+ return vk_result;
+}
+
+#ifdef _WIN32
+// Read manifest JSON files using the Windows driver interface
+static VkResult ReadManifestsFromD3DAdapters(const struct loader_instance *inst, char **reg_data, PDWORD reg_data_size,
+ const wchar_t *value_name) {
+ VkResult result = VK_INCOMPLETE;
+ LoaderEnumAdapters2 adapters = {.adapter_count = 0, .adapters = NULL};
+ LoaderQueryRegistryInfo *full_info = NULL;
+ size_t full_info_size = 0;
+ char *json_path = NULL;
+ size_t json_path_size = 0;
+
+ PFN_LoaderEnumAdapters2 fpLoaderEnumAdapters2 =
+ (PFN_LoaderEnumAdapters2)GetProcAddress(GetModuleHandle("gdi32.dll"), "D3DKMTEnumAdapters2");
+ PFN_LoaderQueryAdapterInfo fpLoaderQueryAdapterInfo =
+ (PFN_LoaderQueryAdapterInfo)GetProcAddress(GetModuleHandle("gdi32.dll"), "D3DKMTQueryAdapterInfo");
+ if (fpLoaderEnumAdapters2 == NULL || fpLoaderQueryAdapterInfo == NULL) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ // Get all of the adapters
+ NTSTATUS status = fpLoaderEnumAdapters2(&adapters);
+ if (status == STATUS_SUCCESS && adapters.adapter_count > 0) {
+ adapters.adapters = loader_instance_heap_alloc(inst, sizeof(*adapters.adapters) * adapters.adapter_count,
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (adapters.adapters == NULL) {
+ goto out;
+ }
+ status = fpLoaderEnumAdapters2(&adapters);
+ }
+ if (status != STATUS_SUCCESS) {
+ goto out;
+ }
+
+ // If that worked, we need to get the manifest file(s) for each adapter
+ for (ULONG i = 0; i < adapters.adapter_count; ++i) {
+ // The first query should just check if the field exists and how big it is
+ LoaderQueryRegistryInfo filename_info = {
+ .query_type = LOADER_QUERY_REGISTRY_ADAPTER_KEY,
+ .query_flags =
+ {
+ .translate_path = true,
+ },
+ .value_type = REG_MULTI_SZ,
+ .physical_adapter_index = 0,
+ };
+ wcsncpy(filename_info.value_name, value_name, sizeof(filename_info.value_name) / sizeof(WCHAR));
+ LoaderQueryAdapterInfo query_info = {
+ .handle = adapters.adapters[i].handle,
+ .type = LOADER_QUERY_TYPE_REGISTRY,
+ .private_data = &filename_info,
+ .private_data_size = sizeof(filename_info),
+ };
+ status = fpLoaderQueryAdapterInfo(&query_info);
+
+ // This error indicates that the type didn't match, so we'll try a REG_SZ
+ if (status != STATUS_SUCCESS) {
+ filename_info.value_type = REG_SZ;
+ status = fpLoaderQueryAdapterInfo(&query_info);
+ }
+
+ if (status != STATUS_SUCCESS || filename_info.status != LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW) {
+ continue;
+ }
+
+ while (status == STATUS_SUCCESS &&
+ ((LoaderQueryRegistryInfo *)query_info.private_data)->status == LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW) {
+ bool needs_copy = (full_info == NULL);
+ size_t full_size = sizeof(LoaderQueryRegistryInfo) + filename_info.output_value_size;
+ void *buffer =
+ loader_instance_heap_realloc(inst, full_info, full_info_size, full_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (buffer == NULL) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ full_info = buffer;
+ full_info_size = full_size;
+
+ if (needs_copy) {
+ memcpy(full_info, &filename_info, sizeof(LoaderQueryRegistryInfo));
+ }
+ query_info.private_data = full_info;
+ query_info.private_data_size = (UINT)full_info_size;
+ status = fpLoaderQueryAdapterInfo(&query_info);
+ }
+
+ if (status != STATUS_SUCCESS || full_info->status != LOADER_QUERY_REGISTRY_STATUS_SUCCESS) {
+ goto out;
+ }
+
+ // Convert the wide string to a narrow string
+ void *buffer = loader_instance_heap_realloc(inst, json_path, json_path_size, full_info->output_value_size,
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (buffer == NULL) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ json_path = buffer;
+ json_path_size = full_info->output_value_size;
+
+ // Iterate over each component string
+ for (const wchar_t *curr_path = full_info->output_string; curr_path[0] != '\0'; curr_path += wcslen(curr_path) + 1) {
+ WideCharToMultiByte(CP_UTF8, 0, curr_path, -1, json_path, (int)json_path_size, NULL, NULL);
+
+ // Add the string to the output list
+ result = VK_SUCCESS;
+ loaderAddJsonEntry(inst, reg_data, reg_data_size, (LPCTSTR)L"EnumAdapters", REG_SZ, json_path,
+ (DWORD)strlen(json_path) + 1, &result);
+ if (result != VK_SUCCESS) {
+ goto out;
+ }
+
+ // If this is a string and not a multi-string, we don't want to go throught the loop more than once
+ if (full_info->value_type == REG_SZ) {
+ break;
+ }
+ }
+ }
+
+out:
+ if (json_path != NULL) {
+ loader_instance_heap_free(inst, json_path);
+ }
+ if (full_info != NULL) {
+ loader_instance_heap_free(inst, full_info);
+ }
+ if (adapters.adapters != NULL) {
+ loader_instance_heap_free(inst, adapters.adapters);
+ }
+
+ return result;
+}
+
+// Look for data files in the registry.
+static VkResult ReadDataFilesInRegistry(const struct loader_instance *inst, enum loader_data_files_type data_file_type,
+ bool warn_if_not_present, char *registry_location, struct loader_data_files *out_files) {
+ VkResult vk_result = VK_SUCCESS;
+ bool is_icd = (data_file_type == LOADER_DATA_FILE_MANIFEST_ICD);
+ char *search_path = NULL;
+
+ // These calls look at the PNP/Device section of the registry.
+ VkResult regHKR_result = VK_SUCCESS;
+ DWORD reg_size = 4096;
+ if (!strncmp(registry_location, VK_DRIVERS_INFO_REGISTRY_LOC, sizeof(VK_DRIVERS_INFO_REGISTRY_LOC))) {
+ // If we're looking for drivers we need to try enumerating adapters
+ regHKR_result = ReadManifestsFromD3DAdapters(inst, &search_path, &reg_size, LoaderPnpDriverRegistryWide());
+ if (regHKR_result == VK_INCOMPLETE) {
+ regHKR_result = loaderGetDeviceRegistryFiles(inst, &search_path, &reg_size, LoaderPnpDriverRegistry());
+ }
+ } else if (!strncmp(registry_location, VK_ELAYERS_INFO_REGISTRY_LOC, sizeof(VK_ELAYERS_INFO_REGISTRY_LOC))) {
+ regHKR_result = ReadManifestsFromD3DAdapters(inst, &search_path, &reg_size, LoaderPnpELayerRegistryWide());
+ if (regHKR_result == VK_INCOMPLETE) {
+ regHKR_result = loaderGetDeviceRegistryFiles(inst, &search_path, &reg_size, LoaderPnpELayerRegistry());
+ }
+ } else if (!strncmp(registry_location, VK_ILAYERS_INFO_REGISTRY_LOC, sizeof(VK_ILAYERS_INFO_REGISTRY_LOC))) {
+ regHKR_result = ReadManifestsFromD3DAdapters(inst, &search_path, &reg_size, LoaderPnpILayerRegistryWide());
+ if (regHKR_result == VK_INCOMPLETE) {
+ regHKR_result = loaderGetDeviceRegistryFiles(inst, &search_path, &reg_size, LoaderPnpILayerRegistry());
+ }
+ }
+
+ // This call looks into the Khronos non-device specific section of the registry.
+ bool use_secondary_hive = (data_file_type == LOADER_DATA_FILE_MANIFEST_LAYER) && (!IsHighIntegrity());
+ VkResult reg_result = loaderGetRegistryFiles(inst, registry_location, use_secondary_hive, &search_path, &reg_size);
+
+ if ((VK_SUCCESS != reg_result && VK_SUCCESS != regHKR_result) || NULL == search_path) {
+ if (data_file_type == LOADER_DATA_FILE_MANIFEST_ICD) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ReadDataFilesInRegistry: Registry lookup failed to get ICD manifest files. Possibly missing Vulkan driver?");
+ if (VK_SUCCESS == reg_result || VK_ERROR_OUT_OF_HOST_MEMORY == reg_result) {
+ vk_result = reg_result;
+ } else {
+ vk_result = regHKR_result;
+ }
+ } else {
+ if (warn_if_not_present) {
+ if (data_file_type == LOADER_DATA_FILE_MANIFEST_LAYER) {
+ // This is only a warning for layers
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "ReadDataFilesInRegistry: Registry lookup failed to get layer manifest files.");
+ } else {
+ // This is only a warning for general data files
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "ReadDataFilesInRegistry: Registry lookup failed to get data files.");
+ }
+ }
+ if (reg_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
+ vk_result = reg_result;
+ } else {
+ // Return success for now since it's not critical for layers
+ vk_result = VK_SUCCESS;
+ }
+ }
+ goto out;
+ }
+
+ // Now, parse the paths and add any manifest files found in them.
+ vk_result = AddDataFilesInPath(inst, search_path, false, out_files);
+
+out:
+
+ if (NULL != search_path) {
+ loader_instance_heap_free(inst, search_path);
+ }
+
+ return vk_result;
+}
+#endif // _WIN32
+
+// Find the Vulkan library manifest files.
+//
+// This function scans the "location" or "env_override" directories/files
+// for a list of JSON manifest files. If env_override is non-NULL
+// and has a valid value. Then the location is ignored. Otherwise
+// location is used to look for manifest files. The location
+// is interpreted as Registry path on Windows and a directory path(s)
+// on Linux. "home_location" is an additional directory in the users home
+// directory to look at. It is expanded into the dir path
+// $XDG_DATA_HOME/home_location or $HOME/.local/share/home_location depending
+// on environment variables. This "home_location" is only used on Linux.
+//
+// \returns
+// VKResult
+// A string list of manifest files to be opened in out_files param.
+// List has a pointer to string for each manifest filename.
+// When done using the list in out_files, pointers should be freed.
+// Location or override string lists can be either files or directories as
+// follows:
+// | location | override
+// --------------------------------
+// Win ICD | files | files
+// Win Layer | files | dirs
+// Linux ICD | dirs | files
+// Linux Layer| dirs | dirs
+static VkResult loaderGetDataFiles(const struct loader_instance *inst, enum loader_data_files_type data_file_type,
+ bool warn_if_not_present, const char *env_override, const char *path_override,
+ char *registry_location, const char *relative_location, struct loader_data_files *out_files) {
+ VkResult res = VK_SUCCESS;
+ bool override_active = false;
+
+ // Free and init the out_files information so there's no false data left from uninitialized variables.
+ if (out_files->filename_list != NULL) {
+ for (uint32_t i = 0; i < out_files->count; i++) {
+ if (NULL != out_files->filename_list[i]) {
+ loader_instance_heap_free(inst, out_files->filename_list[i]);
+ out_files->filename_list[i] = NULL;
+ }
+ }
+ loader_instance_heap_free(inst, out_files->filename_list);
+ }
+ out_files->count = 0;
+ out_files->alloc_count = 0;
+ out_files->filename_list = NULL;
+
+ res = ReadDataFilesInSearchPaths(inst, data_file_type, env_override, path_override, relative_location, &override_active,
+ out_files);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
+#ifdef _WIN32
+ // Read the registry if the override wasn't active.
+ if (!override_active) {
+ res = ReadDataFilesInRegistry(inst, data_file_type, warn_if_not_present, registry_location, out_files);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ }
+#endif
+
+out:
+
+ if (VK_SUCCESS != res && NULL != out_files->filename_list) {
+ for (uint32_t remove = 0; remove < out_files->count; remove++) {
+ loader_instance_heap_free(inst, out_files->filename_list[remove]);
+ }
+ loader_instance_heap_free(inst, out_files->filename_list);
+ out_files->count = 0;
+ out_files->alloc_count = 0;
+ out_files->filename_list = NULL;
+ }
+
+ return res;
+}
+
+void loader_init_icd_lib_list() {}
+
+void loader_destroy_icd_lib_list() {}
+
+// Try to find the Vulkan ICD driver(s).
+//
+// This function scans the default system loader path(s) or path
+// specified by the \c VK_ICD_FILENAMES environment variable in
+// order to find loadable VK ICDs manifest files. From these
+// manifest files it finds the ICD libraries.
+//
+// \returns
+// Vulkan result
+// (on result == VK_SUCCESS) a list of icds that were discovered
+VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
+ char *file_str;
+ uint16_t file_major_vers = 0;
+ uint16_t file_minor_vers = 0;
+ uint16_t file_patch_vers = 0;
+ char *vers_tok;
+ struct loader_data_files manifest_files;
+ VkResult res = VK_SUCCESS;
+ bool lockedMutex = false;
+ cJSON *json = NULL;
+ uint32_t num_good_icds = 0;
+
+ memset(&manifest_files, 0, sizeof(struct loader_data_files));
+
+ res = loader_scanned_icd_init(inst, icd_tramp_list);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
+ // Get a list of manifest files for ICDs
+ res = loaderGetDataFiles(inst, LOADER_DATA_FILE_MANIFEST_ICD, true, "VK_ICD_FILENAMES", NULL, VK_DRIVERS_INFO_REGISTRY_LOC,
+ VK_DRIVERS_INFO_RELATIVE_DIR, &manifest_files);
+ if (VK_SUCCESS != res || manifest_files.count == 0) {
+ goto out;
+ }
+
+ loader_platform_thread_lock_mutex(&loader_json_lock);
+ lockedMutex = true;
+ for (uint32_t i = 0; i < manifest_files.count; i++) {
+ file_str = manifest_files.filename_list[i];
+ if (file_str == NULL) {
+ continue;
+ }
+
+ VkResult temp_res = loader_get_json(inst, file_str, &json);
+ if (NULL == json || temp_res != VK_SUCCESS) {
+ if (NULL != json) {
+ cJSON_Delete(json);
+ json = NULL;
+ }
+ // If we haven't already found an ICD, copy this result to
+ // the returned result.
+ if (num_good_icds == 0) {
+ res = temp_res;
+ }
+ if (temp_res == VK_ERROR_OUT_OF_HOST_MEMORY) {
+ break;
+ } else {
+ continue;
+ }
+ }
+ res = temp_res;
+
+ cJSON *item, *itemICD;
+ item = cJSON_GetObjectItem(json, "file_format_version");
+ if (item == NULL) {
+ if (num_good_icds == 0) {
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ }
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_icd_scan: ICD JSON %s does not have a"
+ " \'file_format_version\' field. Skipping ICD JSON.",
+ file_str);
+ cJSON_Delete(json);
+ json = NULL;
+ continue;
+ }
+
+ char *file_vers = cJSON_Print(item);
+ if (NULL == file_vers) {
+ // Only reason the print can fail is if there was an allocation issue
+ if (num_good_icds == 0) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_icd_scan: Failed retrieving ICD JSON %s"
+ " \'file_format_version\' field. Skipping ICD JSON",
+ file_str);
+ cJSON_Delete(json);
+ json = NULL;
+ continue;
+ }
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Found ICD manifest file %s, version %s", file_str, file_vers);
+
+ // Get the major/minor/and patch as integers for easier comparison
+ vers_tok = strtok(file_vers, ".\"\n\r");
+ if (NULL != vers_tok) {
+ file_major_vers = (uint16_t)atoi(vers_tok);
+ vers_tok = strtok(NULL, ".\"\n\r");
+ if (NULL != vers_tok) {
+ file_minor_vers = (uint16_t)atoi(vers_tok);
+ vers_tok = strtok(NULL, ".\"\n\r");
+ if (NULL != vers_tok) {
+ file_patch_vers = (uint16_t)atoi(vers_tok);
+ }
+ }
+ }
+
+ if (file_major_vers != 1 || file_minor_vers != 0 || file_patch_vers > 1) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_icd_scan: Unexpected manifest file version "
+ "(expected 1.0.0 or 1.0.1), may cause errors");
+ }
+ cJSON_Free(file_vers);
+
+ itemICD = cJSON_GetObjectItem(json, "ICD");
+ if (itemICD != NULL) {
+ item = cJSON_GetObjectItem(itemICD, "library_path");
+ if (item != NULL) {
+ char *temp = cJSON_Print(item);
+ if (!temp || strlen(temp) == 0) {
+ if (num_good_icds == 0) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_icd_scan: Failed retrieving ICD JSON %s"
+ " \'library_path\' field. Skipping ICD JSON.",
+ file_str);
+ cJSON_Free(temp);
+ cJSON_Delete(json);
+ json = NULL;
+ continue;
+ }
+ // strip out extra quotes
+ temp[strlen(temp) - 1] = '\0';
+ char *library_path = loader_stack_alloc(strlen(temp) + 1);
+ if (NULL == library_path) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_icd_scan: Failed to allocate space for "
+ "ICD JSON %s \'library_path\' value. Skipping "
+ "ICD JSON.",
+ file_str);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ cJSON_Free(temp);
+ cJSON_Delete(json);
+ json = NULL;
+ goto out;
+ }
+ strcpy(library_path, &temp[1]);
+ cJSON_Free(temp);
+ if (strlen(library_path) == 0) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_icd_scan: ICD JSON %s \'library_path\'"
+ " field is empty. Skipping ICD JSON.",
+ file_str);
+ cJSON_Delete(json);
+ json = NULL;
+ continue;
+ }
+ char fullpath[MAX_STRING_SIZE];
+ // Print out the paths being searched if debugging is enabled
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching for ICD drivers named %s", library_path);
+ if (loader_platform_is_path(library_path)) {
+ // a relative or absolute path
+ char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
+ char *rel_base;
+ strcpy(name_copy, file_str);
+ rel_base = loader_platform_dirname(name_copy);
+ loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
+ } else {
+// a filename which is assumed in a system directory
+#if defined(DEFAULT_VK_DRIVERS_PATH)
+ loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
+#else
+ loader_get_fullpath(library_path, "", sizeof(fullpath), fullpath);
+#endif
+ }
+
+ uint32_t vers = 0;
+ item = cJSON_GetObjectItem(itemICD, "api_version");
+ if (item != NULL) {
+ temp = cJSON_Print(item);
+ if (NULL == temp) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_icd_scan: Failed retrieving ICD JSON %s"
+ " \'api_version\' field. Skipping ICD JSON.",
+ file_str);
+
+ // Only reason the print can fail is if there was an
+ // allocation issue
+ if (num_good_icds == 0) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ cJSON_Free(temp);
+ cJSON_Delete(json);
+ json = NULL;
+ continue;
+ }
+ vers = loader_make_version(temp);
+ cJSON_Free(temp);
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_icd_scan: ICD JSON %s does not have an"
+ " \'api_version\' field.",
+ file_str);
+ }
+
+ res = loader_scanned_icd_add(inst, icd_tramp_list, fullpath, vers);
+ if (VK_SUCCESS != res) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_icd_scan: Failed to add ICD JSON %s. "
+ " Skipping ICD JSON.",
+ fullpath);
+ cJSON_Delete(json);
+ json = NULL;
+ continue;
+ }
+ num_good_icds++;
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_icd_scan: Failed to find \'library_path\' "
+ "object in ICD JSON file %s. Skipping ICD JSON.",
+ file_str);
+ }
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_icd_scan: Can not find \'ICD\' object in ICD JSON "
+ "file %s. Skipping ICD JSON",
+ file_str);
+ }
+
+ cJSON_Delete(json);
+ json = NULL;
+ }
+
+out:
+
+ if (NULL != json) {
+ cJSON_Delete(json);
+ }
+
+ if (NULL != manifest_files.filename_list) {
+ for (uint32_t i = 0; i < manifest_files.count; i++) {
+ if (NULL != manifest_files.filename_list[i]) {
+ loader_instance_heap_free(inst, manifest_files.filename_list[i]);
+ }
+ }
+ loader_instance_heap_free(inst, manifest_files.filename_list);
+ }
+ if (lockedMutex) {
+ loader_platform_thread_unlock_mutex(&loader_json_lock);
+ }
+
+ return res;
+}
+
+void loaderScanForLayers(struct loader_instance *inst, struct loader_layer_list *instance_layers) {
+ char *file_str;
+ struct loader_data_files manifest_files;
+ cJSON *json;
+ bool override_layer_valid = false;
+ char *override_paths = NULL;
+ uint32_t total_count = 0;
+
+ memset(&manifest_files, 0, sizeof(struct loader_data_files));
+
+ // Cleanup any previously scanned libraries
+ loaderDeleteLayerListAndProperties(inst, instance_layers);
+
+ loader_platform_thread_lock_mutex(&loader_json_lock);
+
+ // Get a list of manifest files for any implicit layers
+ // Pass NULL for environment variable override - implicit layers are not overridden by LAYERS_PATH_ENV
+ if (VK_SUCCESS != loaderGetDataFiles(inst, LOADER_DATA_FILE_MANIFEST_LAYER, false, NULL, NULL, VK_ILAYERS_INFO_REGISTRY_LOC,
+ VK_ILAYERS_INFO_RELATIVE_DIR, &manifest_files)) {
+ goto out;
+ }
+
+ if (manifest_files.count != 0) {
+ total_count += manifest_files.count;
+ for (uint32_t i = 0; i < manifest_files.count; i++) {
+ file_str = manifest_files.filename_list[i];
+ if (file_str == NULL) {
+ continue;
+ }
+
+ // Parse file into JSON struct
+ VkResult res = loader_get_json(inst, file_str, &json);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ goto out;
+ } else if (VK_SUCCESS != res || NULL == json) {
+ continue;
+ }
+
+ VkResult local_res = loaderAddLayerProperties(inst, instance_layers, json, true, file_str);
+ cJSON_Delete(json);
+
+ if (VK_SUCCESS != local_res) {
+ goto out;
+ }
+ }
+ }
+
+ // Check to see if the override layer is present, and use it's override paths.
+ for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) {
+ struct loader_layer_properties *prop = &instance_layers->list[i];
+ if (prop->is_override && loaderImplicitLayerIsEnabled(inst, prop) && prop->num_override_paths > 0) {
+ char *cur_write_ptr = NULL;
+ size_t override_path_size = 0;
+ for (uint32_t j = 0; j < prop->num_override_paths; j++) {
+ override_path_size += DetermineDataFilePathSize(prop->override_paths[j], 0);
+ }
+ override_paths = loader_instance_heap_alloc(inst, override_path_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (override_paths == NULL) {
+ goto out;
+ }
+ cur_write_ptr = &override_paths[0];
+ for (uint32_t j = 0; j < prop->num_override_paths; j++) {
+ CopyDataFilePath(prop->override_paths[j], NULL, 0, &cur_write_ptr);
+ }
+ // Remove the last path separator
+ --cur_write_ptr;
+ assert(cur_write_ptr - override_paths < (ptrdiff_t)override_path_size);
+ *cur_write_ptr = '\0';
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loaderScanForLayers: Override layer has override paths set to %s",
+ override_paths);
+ }
+ }
+
+ // Get a list of manifest files for explicit layers
+ if (VK_SUCCESS != loaderGetDataFiles(inst, LOADER_DATA_FILE_MANIFEST_LAYER, true, "VK_LAYER_PATH", override_paths,
+ VK_ELAYERS_INFO_REGISTRY_LOC, VK_ELAYERS_INFO_RELATIVE_DIR, &manifest_files)) {
+ goto out;
+ }
+
+ // Make sure we have at least one layer, if not, go ahead and return
+ if (manifest_files.count == 0 && total_count == 0) {
+ goto out;
+ } else {
+ total_count += manifest_files.count;
+ for (uint32_t i = 0; i < manifest_files.count; i++) {
+ file_str = manifest_files.filename_list[i];
+ if (file_str == NULL) {
+ continue;
+ }
+
+ // Parse file into JSON struct
+ VkResult res = loader_get_json(inst, file_str, &json);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ goto out;
+ } else if (VK_SUCCESS != res || NULL == json) {
+ continue;
+ }
+
+ VkResult local_res = loaderAddLayerProperties(inst, instance_layers, json, false, file_str);
+ cJSON_Delete(json);
+
+ // If the error is anything other than out of memory we still want to try to load the other layers
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
+ goto out;
+ }
+ }
+ }
+
+ // Verify any meta-layers in the list are valid and all the component layers are
+ // actually present in the available layer list
+ VerifyAllMetaLayers(inst, instance_layers, &override_layer_valid);
+
+ if (override_layer_valid) {
+ loaderRemoveLayersInBlacklist(inst, instance_layers);
+ if (NULL != inst) {
+ inst->override_layer_present = true;
+ }
+ }
+
+out:
+
+ if (NULL != override_paths) {
+ loader_instance_heap_free(inst, override_paths);
+ }
+ if (NULL != manifest_files.filename_list) {
+ for (uint32_t i = 0; i < manifest_files.count; i++) {
+ if (NULL != manifest_files.filename_list[i]) {
+ loader_instance_heap_free(inst, manifest_files.filename_list[i]);
+ }
+ }
+ loader_instance_heap_free(inst, manifest_files.filename_list);
+ }
+ loader_platform_thread_unlock_mutex(&loader_json_lock);
+}
+
+void loaderScanForImplicitLayers(struct loader_instance *inst, struct loader_layer_list *instance_layers) {
+ char *file_str;
+ struct loader_data_files manifest_files;
+ cJSON *json;
+ bool override_layer_valid = false;
+ char *override_paths = NULL;
+ bool implicit_metalayer_present = false;
+ bool have_json_lock = false;
+
+ // Before we begin anything, init manifest_files to avoid a delete of garbage memory if
+ // a failure occurs before allocating the manifest filename_list.
+ memset(&manifest_files, 0, sizeof(struct loader_data_files));
+
+ // Pass NULL for environment variable override - implicit layers are not overridden by LAYERS_PATH_ENV
+ VkResult res = loaderGetDataFiles(inst, LOADER_DATA_FILE_MANIFEST_LAYER, false, NULL, NULL, VK_ILAYERS_INFO_REGISTRY_LOC,
+ VK_ILAYERS_INFO_RELATIVE_DIR, &manifest_files);
+ if (VK_SUCCESS != res || manifest_files.count == 0) {
+ goto out;
+ }
+
+ // Cleanup any previously scanned libraries
+ loaderDeleteLayerListAndProperties(inst, instance_layers);
+
+ loader_platform_thread_lock_mutex(&loader_json_lock);
+ have_json_lock = true;
+
+ for (uint32_t i = 0; i < manifest_files.count; i++) {
+ file_str = manifest_files.filename_list[i];
+ if (file_str == NULL) {
+ continue;
+ }
+
+ // parse file into JSON struct
+ res = loader_get_json(inst, file_str, &json);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ goto out;
+ } else if (VK_SUCCESS != res || NULL == json) {
+ continue;
+ }
+
+ res = loaderAddLayerProperties(inst, instance_layers, json, true, file_str);
+
+ loader_instance_heap_free(inst, file_str);
+ manifest_files.filename_list[i] = NULL;
+ cJSON_Delete(json);
+
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ goto out;
+ }
+ }
+
+ // Check to see if either the override layer is present, or another implicit meta-layer.
+ // Each of these may require explicit layers to be enabled at this time.
+ for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) {
+ struct loader_layer_properties *prop = &instance_layers->list[i];
+ if (prop->is_override && loaderImplicitLayerIsEnabled(inst, prop)) {
+ override_layer_valid = true;
+ if (prop->num_override_paths > 0) {
+ char *cur_write_ptr = NULL;
+ size_t override_path_size = 0;
+ for (uint32_t j = 0; j < prop->num_override_paths; j++) {
+ override_path_size += DetermineDataFilePathSize(prop->override_paths[j], 0);
+ }
+ override_paths = loader_instance_heap_alloc(inst, override_path_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (override_paths == NULL) {
+ goto out;
+ }
+ cur_write_ptr = &override_paths[0];
+ for (uint32_t j = 0; j < prop->num_override_paths; j++) {
+ CopyDataFilePath(prop->override_paths[j], NULL, 0, &cur_write_ptr);
+ }
+ // Remove the last path separator
+ --cur_write_ptr;
+ assert(cur_write_ptr - override_paths < (ptrdiff_t)override_path_size);
+ *cur_write_ptr = '\0';
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loaderScanForImplicitLayers: Override layer has override paths set to %s", override_paths);
+ }
+ } else if (!prop->is_override && prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
+ implicit_metalayer_present = true;
+ }
+ }
+
+ // If either the override layer or an implicit meta-layer are present, we need to add
+ // explicit layer info as well. Not to worry, though, all explicit layers not included
+ // in the override layer will be removed below in loaderRemoveLayersInBlacklist().
+ if (override_layer_valid || implicit_metalayer_present) {
+ if (VK_SUCCESS != loaderGetDataFiles(inst, LOADER_DATA_FILE_MANIFEST_LAYER, true, "VK_LAYER_PATH", override_paths,
+ VK_ELAYERS_INFO_REGISTRY_LOC, VK_ELAYERS_INFO_RELATIVE_DIR, &manifest_files)) {
+ goto out;
+ }
+
+ for (uint32_t i = 0; i < manifest_files.count; i++) {
+ file_str = manifest_files.filename_list[i];
+ if (file_str == NULL) {
+ continue;
+ }
+
+ // parse file into JSON struct
+ res = loader_get_json(inst, file_str, &json);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ goto out;
+ } else if (VK_SUCCESS != res || NULL == json) {
+ continue;
+ }
+
+ res = loaderAddLayerProperties(inst, instance_layers, json, true, file_str);
+
+ loader_instance_heap_free(inst, file_str);
+ cJSON_Delete(json);
+
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ goto out;
+ }
+ }
+ }
+
+ // Verify any meta-layers in the list are valid and all the component layers are
+ // actually present in the available layer list
+ VerifyAllMetaLayers(inst, instance_layers, &override_layer_valid);
+
+ if (override_layer_valid || implicit_metalayer_present) {
+ loaderRemoveLayersNotInImplicitMetaLayers(inst, instance_layers);
+ if (override_layer_valid && inst != NULL) {
+ inst->override_layer_present = true;
+ }
+ }
+
+out:
+
+ if (NULL != override_paths) {
+ loader_instance_heap_free(inst, override_paths);
+ }
+ if (NULL != manifest_files.filename_list) {
+ loader_instance_heap_free(inst, manifest_files.filename_list);
+ }
+
+ if (have_json_lock) {
+ loader_platform_thread_unlock_mutex(&loader_json_lock);
+ }
+}
+
+static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpdpa_instance_internal(VkInstance inst, const char *pName) {
+ // inst is not wrapped
+ if (inst == VK_NULL_HANDLE) {
+ return NULL;
+ }
+ VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst;
+ void *addr;
+
+ if (disp_table == NULL) return NULL;
+
+ bool found_name;
+ addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name);
+ if (found_name) {
+ return addr;
+ }
+
+ if (loader_phys_dev_ext_gpa(loader_get_instance(inst), pName, true, NULL, &addr)) return addr;
+
+ // Don't call down the chain, this would be an infinite loop
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loader_gpdpa_instance_internal() unrecognized name %s", pName);
+ return NULL;
+}
+
+static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpdpa_instance_terminator(VkInstance inst, const char *pName) {
+ // inst is not wrapped
+ if (inst == VK_NULL_HANDLE) {
+ return NULL;
+ }
+ VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst;
+ void *addr;
+
+ if (disp_table == NULL) return NULL;
+
+ bool found_name;
+ addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name);
+ if (found_name) {
+ return addr;
+ }
+
+ // Get the terminator, but don't perform checking since it should already
+ // have been setup if we get here.
+ if (loader_phys_dev_ext_gpa(loader_get_instance(inst), pName, false, NULL, &addr)) {
+ return addr;
+ }
+
+ // Don't call down the chain, this would be an infinite loop
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loader_gpdpa_instance_terminator() unrecognized name %s", pName);
+ return NULL;
+}
+
+static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char *pName) {
+ if (!strcmp(pName, "vkGetInstanceProcAddr")) {
+ return (PFN_vkVoidFunction)loader_gpa_instance_internal;
+ }
+ if (!strcmp(pName, "vk_layerGetPhysicalDeviceProcAddr")) {
+ return (PFN_vkVoidFunction)loader_gpdpa_instance_terminator;
+ }
+ if (!strcmp(pName, "vkCreateInstance")) {
+ return (PFN_vkVoidFunction)terminator_CreateInstance;
+ }
+ if (!strcmp(pName, "vkCreateDevice")) {
+ return (PFN_vkVoidFunction)terminator_CreateDevice;
+ }
+
+ // The VK_EXT_debug_utils functions need a special case here so the terminators can still be found from vkGetInstanceProcAddr
+ if (!strcmp(pName, "vkSetDebugUtilsObjectNameEXT")) {
+ return (PFN_vkVoidFunction)terminator_SetDebugUtilsObjectNameEXT;
+ }
+ if (!strcmp(pName, "vkSetDebugUtilsObjectTagEXT")) {
+ return (PFN_vkVoidFunction)terminator_SetDebugUtilsObjectTagEXT;
+ }
+ if (!strcmp(pName, "vkQueueBeginDebugUtilsLabelEXT")) {
+ return (PFN_vkVoidFunction)terminator_QueueBeginDebugUtilsLabelEXT;
+ }
+ if (!strcmp(pName, "vkQueueEndDebugUtilsLabelEXT")) {
+ return (PFN_vkVoidFunction)terminator_QueueEndDebugUtilsLabelEXT;
+ }
+ if (!strcmp(pName, "vkQueueInsertDebugUtilsLabelEXT")) {
+ return (PFN_vkVoidFunction)terminator_QueueInsertDebugUtilsLabelEXT;
+ }
+ if (!strcmp(pName, "vkCmdBeginDebugUtilsLabelEXT")) {
+ return (PFN_vkVoidFunction)terminator_CmdBeginDebugUtilsLabelEXT;
+ }
+ if (!strcmp(pName, "vkCmdEndDebugUtilsLabelEXT")) {
+ return (PFN_vkVoidFunction)terminator_CmdEndDebugUtilsLabelEXT;
+ }
+ if (!strcmp(pName, "vkCmdInsertDebugUtilsLabelEXT")) {
+ return (PFN_vkVoidFunction)terminator_CmdInsertDebugUtilsLabelEXT;
+ }
+
+ // inst is not wrapped
+ if (inst == VK_NULL_HANDLE) {
+ return NULL;
+ }
+ VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst;
+ void *addr;
+
+ if (disp_table == NULL) return NULL;
+
+ bool found_name;
+ addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name);
+ if (found_name) {
+ return addr;
+ }
+
+ // Don't call down the chain, this would be an infinite loop
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loader_gpa_instance_internal() unrecognized name %s", pName);
+ return NULL;
+}
+
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_device_internal(VkDevice device, const char *pName) {
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL);
+
+ // Return this function if a layer above here is asking for the vkGetDeviceProcAddr.
+ // This is so we can properly intercept any device commands needing a terminator.
+ if (!strcmp(pName, "vkGetDeviceProcAddr")) {
+ return (PFN_vkVoidFunction)loader_gpa_device_internal;
+ }
+
+ // NOTE: Device Funcs needing Trampoline/Terminator.
+ // Overrides for device functions needing a trampoline and
+ // a terminator because certain device entry-points still need to go
+ // through a terminator before hitting the ICD. This could be for
+ // several reasons, but the main one is currently unwrapping an
+ // object before passing the appropriate info along to the ICD.
+ // This is why we also have to override the direct ICD call to
+ // vkGetDeviceProcAddr to intercept those calls.
+ PFN_vkVoidFunction addr = get_extension_device_proc_terminator(dev, pName);
+ if (NULL != addr) {
+ return addr;
+ }
+
+ return icd_term->dispatch.GetDeviceProcAddr(device, pName);
+}
+
+// Initialize device_ext dispatch table entry as follows:
+// If dev == NULL find all logical devices created within this instance and
+// init the entry (given by idx) in the ext dispatch table.
+// If dev != NULL only initialize the entry in the given dev's dispatch table.
+// The initialization value is gotten by calling down the device chain with
+// GDPA.
+// If GDPA returns NULL then don't initialize the dispatch table entry.
+static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst, struct loader_device *dev, uint32_t idx,
+ const char *funcName)
+
+{
+ void *gdpa_value;
+ if (dev != NULL) {
+ gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(dev->chain_device, funcName);
+ if (gdpa_value != NULL) dev->loader_dispatch.ext_dispatch.dev_ext[idx] = (PFN_vkDevExt)gdpa_value;
+ } else {
+ for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
+ struct loader_device *ldev = icd_term->logical_device_list;
+ while (ldev) {
+ gdpa_value = ldev->loader_dispatch.core_dispatch.GetDeviceProcAddr(ldev->chain_device, funcName);
+ if (gdpa_value != NULL) ldev->loader_dispatch.ext_dispatch.dev_ext[idx] = (PFN_vkDevExt)gdpa_value;
+ ldev = ldev->next;
+ }
+ }
+ }
+}
+
+// Find all dev extension in the hash table and initialize the dispatch table
+// for dev for each of those extension entrypoints found in hash table.
+void loader_init_dispatch_dev_ext(struct loader_instance *inst, struct loader_device *dev) {
+ for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) {
+ if (inst->dev_ext_disp_hash[i].func_name != NULL)
+ loader_init_dispatch_dev_ext_entry(inst, dev, i, inst->dev_ext_disp_hash[i].func_name);
+ }
+}
+
+static bool loader_check_icds_for_dev_ext_address(struct loader_instance *inst, const char *funcName) {
+ struct loader_icd_term *icd_term;
+ icd_term = inst->icd_terms;
+ while (NULL != icd_term) {
+ if (icd_term->scanned_icd->GetInstanceProcAddr(icd_term->instance, funcName))
+ // this icd supports funcName
+ return true;
+ icd_term = icd_term->next;
+ }
+
+ return false;
+}
+
+static bool loader_check_layer_list_for_dev_ext_address(const struct loader_layer_list *const layers, const char *funcName) {
+ // Iterate over the layers.
+ for (uint32_t layer = 0; layer < layers->count; ++layer) {
+ // Iterate over the extensions.
+ const struct loader_device_extension_list *const extensions = &(layers->list[layer].device_extension_list);
+ for (uint32_t extension = 0; extension < extensions->count; ++extension) {
+ // Iterate over the entry points.
+ const struct loader_dev_ext_props *const property = &(extensions->list[extension]);
+ for (uint32_t entry = 0; entry < property->entrypoint_count; ++entry) {
+ if (strcmp(property->entrypoints[entry], funcName) == 0) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static void loader_free_dev_ext_table(struct loader_instance *inst) {
+ for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) {
+ loader_instance_heap_free(inst, inst->dev_ext_disp_hash[i].func_name);
+ loader_instance_heap_free(inst, inst->dev_ext_disp_hash[i].list.index);
+ }
+ memset(inst->dev_ext_disp_hash, 0, sizeof(inst->dev_ext_disp_hash));
+}
+
+static bool loader_add_dev_ext_table(struct loader_instance *inst, uint32_t *ptr_idx, const char *funcName) {
+ uint32_t i;
+ uint32_t idx = *ptr_idx;
+ struct loader_dispatch_hash_list *list = &inst->dev_ext_disp_hash[idx].list;
+
+ if (!inst->dev_ext_disp_hash[idx].func_name) {
+ // no entry here at this idx, so use it
+ assert(list->capacity == 0);
+ inst->dev_ext_disp_hash[idx].func_name =
+ (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (inst->dev_ext_disp_hash[idx].func_name == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_dev_ext_table: Failed to allocate memory "
+ "for func_name %s",
+ funcName);
+ return false;
+ }
+ strncpy(inst->dev_ext_disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
+ return true;
+ }
+
+ // check for enough capacity
+ if (list->capacity == 0) {
+ list->index = loader_instance_heap_alloc(inst, 8 * sizeof(*(list->index)), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (list->index == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_dev_ext_table: Failed to allocate memory for list index of function %s", funcName);
+ return false;
+ }
+ list->capacity = 8 * sizeof(*(list->index));
+ } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
+ void *new_ptr = loader_instance_heap_realloc(inst, list->index, list->capacity, list->capacity * 2,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_ptr) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_dev_ext_table: Failed to reallocate memory for list index of function %s", funcName);
+ return false;
+ }
+ list->index = new_ptr;
+ list->capacity *= 2;
+ }
+
+ // find an unused index in the hash table and use it
+ i = (idx + 1) % MAX_NUM_UNKNOWN_EXTS;
+ do {
+ if (!inst->dev_ext_disp_hash[i].func_name) {
+ assert(inst->dev_ext_disp_hash[i].list.capacity == 0);
+ inst->dev_ext_disp_hash[i].func_name =
+ (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (inst->dev_ext_disp_hash[i].func_name == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_dev_ext_table: Failed to allocate memory "
+ "for func_name %s",
+ funcName);
+ return false;
+ }
+ strncpy(inst->dev_ext_disp_hash[i].func_name, funcName, strlen(funcName) + 1);
+ list->index[list->count] = i;
+ list->count++;
+ *ptr_idx = i;
+ return true;
+ }
+ i = (i + 1) % MAX_NUM_UNKNOWN_EXTS;
+ } while (i != idx);
+
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_dev_ext_table: Could not insert into hash table; is "
+ "it full?");
+
+ return false;
+}
+
+static bool loader_name_in_dev_ext_table(struct loader_instance *inst, uint32_t *idx, const char *funcName) {
+ uint32_t alt_idx;
+ if (inst->dev_ext_disp_hash[*idx].func_name && !strcmp(inst->dev_ext_disp_hash[*idx].func_name, funcName)) return true;
+
+ // funcName wasn't at the primary spot in the hash table
+ // search the list of secondary locations (shallow search, not deep search)
+ for (uint32_t i = 0; i < inst->dev_ext_disp_hash[*idx].list.count; i++) {
+ alt_idx = inst->dev_ext_disp_hash[*idx].list.index[i];
+ if (!strcmp(inst->dev_ext_disp_hash[*idx].func_name, funcName)) {
+ *idx = alt_idx;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// This function returns generic trampoline code address for unknown entry
+// points.
+// Presumably, these unknown entry points (as given by funcName) are device
+// extension entrypoints. A hash table is used to keep a list of unknown entry
+// points and their mapping to the device extension dispatch table
+// (struct loader_dev_ext_dispatch_table).
+// \returns
+// For a given entry point string (funcName), if an existing mapping is found
+// the
+// trampoline address for that mapping is returned. Otherwise, this unknown
+// entry point
+// has not been seen yet. Next check if a layer or ICD supports it. If so then
+// a
+// new entry in the hash table is initialized and that trampoline address for
+// the new entry is returned. Null is returned if the hash table is full or
+// if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
+void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) {
+ uint32_t idx;
+ uint32_t seed = 0;
+
+ idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_UNKNOWN_EXTS;
+
+ if (loader_name_in_dev_ext_table(inst, &idx, funcName))
+ // found funcName already in hash
+ return loader_get_dev_ext_trampoline(idx);
+
+ // Check if funcName is supported in either ICDs or a layer library
+ if (!loader_check_icds_for_dev_ext_address(inst, funcName) &&
+ !loader_check_layer_list_for_dev_ext_address(&inst->app_activated_layer_list, funcName)) {
+ // if support found in layers continue on
+ return NULL;
+ }
+
+ if (loader_add_dev_ext_table(inst, &idx, funcName)) {
+ // successfully added new table entry
+ // init any dev dispatch table entries as needed
+ loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
+ return loader_get_dev_ext_trampoline(idx);
+ }
+
+ return NULL;
+}
+
+static bool loader_check_icds_for_phys_dev_ext_address(struct loader_instance *inst, const char *funcName) {
+ struct loader_icd_term *icd_term;
+ icd_term = inst->icd_terms;
+ while (NULL != icd_term) {
+ if (icd_term->scanned_icd->interface_version >= MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION &&
+ icd_term->scanned_icd->GetPhysicalDeviceProcAddr(icd_term->instance, funcName))
+ // this icd supports funcName
+ return true;
+ icd_term = icd_term->next;
+ }
+
+ return false;
+}
+
+static bool loader_check_layer_list_for_phys_dev_ext_address(struct loader_instance *inst, const char *funcName) {
+ struct loader_layer_properties *layer_prop_list = inst->expanded_activated_layer_list.list;
+ for (uint32_t layer = 0; layer < inst->expanded_activated_layer_list.count; ++layer) {
+ // If this layer supports the vk_layerGetPhysicalDeviceProcAddr, then call
+ // it and see if it returns a valid pointer for this function name.
+ if (layer_prop_list[layer].interface_version > 1) {
+ const struct loader_layer_functions *const functions = &(layer_prop_list[layer].functions);
+ if (NULL != functions->get_physical_device_proc_addr &&
+ NULL != functions->get_physical_device_proc_addr((VkInstance)inst->instance, funcName)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static void loader_free_phys_dev_ext_table(struct loader_instance *inst) {
+ for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) {
+ loader_instance_heap_free(inst, inst->phys_dev_ext_disp_hash[i].func_name);
+ loader_instance_heap_free(inst, inst->phys_dev_ext_disp_hash[i].list.index);
+ }
+ memset(inst->phys_dev_ext_disp_hash, 0, sizeof(inst->phys_dev_ext_disp_hash));
+}
+
+static bool loader_add_phys_dev_ext_table(struct loader_instance *inst, uint32_t *ptr_idx, const char *funcName) {
+ uint32_t i;
+ uint32_t idx = *ptr_idx;
+ struct loader_dispatch_hash_list *list = &inst->phys_dev_ext_disp_hash[idx].list;
+
+ if (!inst->phys_dev_ext_disp_hash[idx].func_name) {
+ // no entry here at this idx, so use it
+ assert(list->capacity == 0);
+ inst->phys_dev_ext_disp_hash[idx].func_name =
+ (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (inst->phys_dev_ext_disp_hash[idx].func_name == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_phys_dev_ext_table() can't allocate memory for "
+ "func_name");
+ return false;
+ }
+ strncpy(inst->phys_dev_ext_disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
+ return true;
+ }
+
+ // check for enough capacity
+ if (list->capacity == 0) {
+ list->index = loader_instance_heap_alloc(inst, 8 * sizeof(*(list->index)), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (list->index == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_add_phys_dev_ext_table() can't allocate list memory");
+ return false;
+ }
+ list->capacity = 8 * sizeof(*(list->index));
+ } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
+ void *new_ptr = loader_instance_heap_realloc(inst, list->index, list->capacity, list->capacity * 2,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_ptr) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_add_phys_dev_ext_table() can't reallocate list memory");
+ return false;
+ }
+ list->index = new_ptr;
+ list->capacity *= 2;
+ }
+
+ // find an unused index in the hash table and use it
+ i = (idx + 1) % MAX_NUM_UNKNOWN_EXTS;
+ do {
+ if (!inst->phys_dev_ext_disp_hash[i].func_name) {
+ assert(inst->phys_dev_ext_disp_hash[i].list.capacity == 0);
+ inst->phys_dev_ext_disp_hash[i].func_name =
+ (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (inst->phys_dev_ext_disp_hash[i].func_name == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_dev_ext_table() can't reallocate "
+ "func_name memory");
+ return false;
+ }
+ strncpy(inst->phys_dev_ext_disp_hash[i].func_name, funcName, strlen(funcName) + 1);
+ list->index[list->count] = i;
+ list->count++;
+ *ptr_idx = i;
+ return true;
+ }
+ i = (i + 1) % MAX_NUM_UNKNOWN_EXTS;
+ } while (i != idx);
+
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_phys_dev_ext_table() couldn't insert into hash table; is "
+ "it full?");
+ return false;
+}
+
+static bool loader_name_in_phys_dev_ext_table(struct loader_instance *inst, uint32_t *idx, const char *funcName) {
+ uint32_t alt_idx;
+ if (inst->phys_dev_ext_disp_hash[*idx].func_name && !strcmp(inst->phys_dev_ext_disp_hash[*idx].func_name, funcName))
+ return true;
+
+ // funcName wasn't at the primary spot in the hash table
+ // search the list of secondary locations (shallow search, not deep search)
+ for (uint32_t i = 0; i < inst->phys_dev_ext_disp_hash[*idx].list.count; i++) {
+ alt_idx = inst->phys_dev_ext_disp_hash[*idx].list.index[i];
+ if (!strcmp(inst->phys_dev_ext_disp_hash[*idx].func_name, funcName)) {
+ *idx = alt_idx;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// This function returns a generic trampoline and/or terminator function
+// address for any unknown physical device extension commands. A hash
+// table is used to keep a list of unknown entry points and their
+// mapping to the physical device extension dispatch table (struct
+// loader_phys_dev_ext_dispatch_table).
+// For a given entry point string (funcName), if an existing mapping is
+// found, then the trampoline address for that mapping is returned in
+// tramp_addr (if it is not NULL) and the terminator address for that
+// mapping is returned in term_addr (if it is not NULL). Otherwise,
+// this unknown entry point has not been seen yet.
+// If it has not been seen before, and perform_checking is 'true',
+// check if a layer or and ICD supports it. If so then a new entry in
+// the hash table is initialized and the trampoline and/or terminator
+// addresses are returned.
+// Null is returned if the hash table is full or if no discovered layer or
+// ICD returns a non-NULL GetProcAddr for it.
+bool loader_phys_dev_ext_gpa(struct loader_instance *inst, const char *funcName, bool perform_checking, void **tramp_addr,
+ void **term_addr) {
+ uint32_t idx;
+ uint32_t seed = 0;
+ bool success = false;
+
+ if (inst == NULL) {
+ goto out;
+ }
+
+ if (NULL != tramp_addr) {
+ *tramp_addr = NULL;
+ }
+ if (NULL != term_addr) {
+ *term_addr = NULL;
+ }
+
+ // We should always check to see if any ICD supports it.
+ if (!loader_check_icds_for_phys_dev_ext_address(inst, funcName)) {
+ // If we're not checking layers, or we are and it's not in a layer, just
+ // return
+ if (!perform_checking || !loader_check_layer_list_for_phys_dev_ext_address(inst, funcName)) {
+ goto out;
+ }
+ }
+
+ idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_UNKNOWN_EXTS;
+ if (perform_checking && !loader_name_in_phys_dev_ext_table(inst, &idx, funcName)) {
+ uint32_t i;
+ bool added = false;
+
+ // Only need to add first one to get index in Instance. Others will use
+ // the same index.
+ if (!added && loader_add_phys_dev_ext_table(inst, &idx, funcName)) {
+ added = true;
+ }
+
+ // Setup the ICD function pointers
+ struct loader_icd_term *icd_term = inst->icd_terms;
+ while (NULL != icd_term) {
+ if (MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION <= icd_term->scanned_icd->interface_version &&
+ NULL != icd_term->scanned_icd->GetPhysicalDeviceProcAddr) {
+ icd_term->phys_dev_ext[idx] =
+ (PFN_PhysDevExt)icd_term->scanned_icd->GetPhysicalDeviceProcAddr(icd_term->instance, funcName);
+
+ // Make sure we set the instance dispatch to point to the
+ // loader's terminator now since we can at least handle it
+ // in one ICD.
+ inst->disp->phys_dev_ext[idx] = loader_get_phys_dev_ext_termin(idx);
+ } else {
+ icd_term->phys_dev_ext[idx] = NULL;
+ }
+
+ icd_term = icd_term->next;
+ }
+
+ // Now, search for the first layer attached and query using it to get
+ // the first entry point.
+ for (i = 0; i < inst->expanded_activated_layer_list.count; i++) {
+ struct loader_layer_properties *layer_prop = &inst->expanded_activated_layer_list.list[i];
+ if (layer_prop->interface_version > 1 && NULL != layer_prop->functions.get_physical_device_proc_addr) {
+ inst->disp->phys_dev_ext[idx] =
+ (PFN_PhysDevExt)layer_prop->functions.get_physical_device_proc_addr((VkInstance)inst->instance, funcName);
+ if (NULL != inst->disp->phys_dev_ext[idx]) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (NULL != tramp_addr) {
+ *tramp_addr = loader_get_phys_dev_ext_tramp(idx);
+ }
+
+ if (NULL != term_addr) {
+ *term_addr = loader_get_phys_dev_ext_termin(idx);
+ }
+
+ success = true;
+
+out:
+ return success;
+}
+
+struct loader_instance *loader_get_instance(const VkInstance instance) {
+ // look up the loader_instance in our list by comparing dispatch tables, as
+ // there is no guarantee the instance is still a loader_instance* after any
+ // layers which wrap the instance object.
+ const VkLayerInstanceDispatchTable *disp;
+ struct loader_instance *ptr_instance = NULL;
+ disp = loader_get_instance_layer_dispatch(instance);
+ for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
+ if (&inst->disp->layer_inst_disp == disp) {
+ ptr_instance = inst;
+ break;
+ }
+ }
+ return ptr_instance;
+}
+
+static loader_platform_dl_handle loaderOpenLayerFile(const struct loader_instance *inst, const char *chain_type,
+ struct loader_layer_properties *prop) {
+ if ((prop->lib_handle = loader_platform_open_library(prop->lib_name)) == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, loader_platform_open_library_error(prop->lib_name));
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Loading layer library %s", prop->lib_name);
+ }
+
+ return prop->lib_handle;
+}
+
+static void loaderCloseLayerFile(const struct loader_instance *inst, struct loader_layer_properties *prop) {
+ if (prop->lib_handle) {
+ loader_platform_close_library(prop->lib_handle);
+ loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Unloading layer library %s", prop->lib_name);
+ prop->lib_handle = NULL;
+ }
+}
+
+void loaderDeactivateLayers(const struct loader_instance *instance, struct loader_device *device, struct loader_layer_list *list) {
+ // Delete instance list of enabled layers and close any layer libraries
+ for (uint32_t i = 0; i < list->count; i++) {
+ struct loader_layer_properties *layer_prop = &list->list[i];
+
+ loaderCloseLayerFile(instance, layer_prop);
+ }
+ loaderDestroyLayerList(instance, device, list);
+}
+
+// Go through the search_list and find any layers which match type. If layer
+// type match is found in then add it to ext_list.
+static void loaderAddImplicitLayers(const struct loader_instance *inst, struct loader_layer_list *target_list,
+ struct loader_layer_list *expanded_target_list, const struct loader_layer_list *source_list) {
+ for (uint32_t src_layer = 0; src_layer < source_list->count; src_layer++) {
+ const struct loader_layer_properties *prop = &source_list->list[src_layer];
+ if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
+ loaderAddImplicitLayer(inst, prop, target_list, expanded_target_list, source_list);
+ }
+ }
+}
+
+// Get the layer name(s) from the env_name environment variable. If layer is found in
+// search_list then add it to layer_list. But only add it to layer_list if type_flags matches.
+static void loaderAddEnvironmentLayers(struct loader_instance *inst, const enum layer_type_flags type_flags, const char *env_name,
+ struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
+ const struct loader_layer_list *source_list) {
+ char *next, *name;
+ char *layer_env = loader_getenv(env_name, inst);
+ if (layer_env == NULL) {
+ goto out;
+ }
+ name = loader_stack_alloc(strlen(layer_env) + 1);
+ if (name == NULL) {
+ goto out;
+ }
+ strcpy(name, layer_env);
+
+ while (name && *name) {
+ next = loader_get_next_path(name);
+ loaderAddLayerNameToList(inst, name, type_flags, source_list, target_list, expanded_target_list);
+ name = next;
+ }
+
+out:
+
+ if (layer_env != NULL) {
+ loader_free_getenv(layer_env, inst);
+ }
+
+ return;
+}
+
+VkResult loaderEnableInstanceLayers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo,
+ const struct loader_layer_list *instance_layers) {
+ VkResult err = VK_SUCCESS;
+ uint16_t layer_api_major_version;
+ uint16_t layer_api_minor_version;
+ uint32_t i;
+ struct loader_layer_properties *prop;
+
+ assert(inst && "Cannot have null instance");
+
+ if (!loaderInitLayerList(inst, &inst->app_activated_layer_list)) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderEnableInstanceLayers: Failed to initialize application version of the layer list");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ if (!loaderInitLayerList(inst, &inst->expanded_activated_layer_list)) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderEnableInstanceLayers: Failed to initialize expanded version of the layer list");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ // Add any implicit layers first
+ loaderAddImplicitLayers(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, instance_layers);
+
+ // Add any layers specified via environment variable next
+ loaderAddEnvironmentLayers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, "VK_INSTANCE_LAYERS", &inst->app_activated_layer_list,
+ &inst->expanded_activated_layer_list, instance_layers);
+
+ // Add layers specified by the application
+ err = loaderAddLayerNamesToList(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list,
+ pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames, instance_layers);
+
+ for (i = 0; i < inst->expanded_activated_layer_list.count; i++) {
+ // Verify that the layer api version is at least that of the application's request, if not, throw a warning since
+ // undefined behavior could occur.
+ prop = inst->expanded_activated_layer_list.list + i;
+ layer_api_major_version = VK_VERSION_MAJOR(prop->info.specVersion);
+ layer_api_minor_version = VK_VERSION_MINOR(prop->info.specVersion);
+ if (inst->app_api_major_version > layer_api_major_version ||
+ (inst->app_api_major_version == layer_api_major_version && inst->app_api_minor_version > layer_api_minor_version)) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_add_to_layer_list: Explicit layer %s is using an old API version %" PRIu16 ".%" PRIu16
+ " versus application requested %" PRIu16 ".%" PRIu16,
+ prop->info.layerName, layer_api_major_version, layer_api_minor_version, inst->app_api_major_version,
+ inst->app_api_minor_version);
+ }
+ }
+
+ return err;
+}
+
+// Determine the layer interface version to use.
+bool loaderGetLayerInterfaceVersion(PFN_vkNegotiateLoaderLayerInterfaceVersion fp_negotiate_layer_version,
+ VkNegotiateLayerInterface *interface_struct) {
+ memset(interface_struct, 0, sizeof(VkNegotiateLayerInterface));
+ interface_struct->sType = LAYER_NEGOTIATE_INTERFACE_STRUCT;
+ interface_struct->loaderLayerInterfaceVersion = 1;
+ interface_struct->pNext = NULL;
+
+ if (fp_negotiate_layer_version != NULL) {
+ // Layer supports the negotiation API, so call it with the loader's
+ // latest version supported
+ interface_struct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
+ VkResult result = fp_negotiate_layer_version(interface_struct);
+
+ if (result != VK_SUCCESS) {
+ // Layer no longer supports the loader's latest interface version so
+ // fail loading the Layer
+ return false;
+ }
+ }
+
+ if (interface_struct->loaderLayerInterfaceVersion < MIN_SUPPORTED_LOADER_LAYER_INTERFACE_VERSION) {
+ // Loader no longer supports the layer's latest interface version so
+ // fail loading the layer
+ return false;
+ }
+
+ return true;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL loader_layer_create_device(VkInstance instance, VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
+ PFN_vkGetInstanceProcAddr layerGIPA, PFN_vkGetDeviceProcAddr *nextGDPA) {
+ VkResult res;
+ VkPhysicalDevice internal_device = VK_NULL_HANDLE;
+ struct loader_device *dev = NULL;
+ struct loader_instance *inst = NULL;
+
+ if (instance != NULL) {
+ inst = loader_get_instance(instance);
+ internal_device = physicalDevice;
+ } else {
+ struct loader_physical_device_tramp *phys_dev = (struct loader_physical_device_tramp *)physicalDevice;
+ internal_device = phys_dev->phys_dev;
+ inst = (struct loader_instance *)phys_dev->this_instance;
+ }
+
+ // Get the physical device (ICD) extensions
+ struct loader_extension_list icd_exts;
+ icd_exts.list = NULL;
+ res = loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties));
+ if (VK_SUCCESS != res) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "vkCreateDevice: Failed to create ICD extension list");
+ goto out;
+ }
+
+ PFN_vkEnumerateDeviceExtensionProperties enumDeviceExtensionProperties = NULL;
+ if (layerGIPA != NULL) {
+ enumDeviceExtensionProperties =
+ (PFN_vkEnumerateDeviceExtensionProperties)layerGIPA(instance, "vkEnumerateDeviceExtensionProperties");
+ } else {
+ enumDeviceExtensionProperties = inst->disp->layer_inst_disp.EnumerateDeviceExtensionProperties;
+ }
+ res = loader_add_device_extensions(inst, enumDeviceExtensionProperties, internal_device, "Unknown", &icd_exts);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "vkCreateDevice: Failed to add extensions to list");
+ goto out;
+ }
+
+ // Make sure requested extensions to be enabled are supported
+ res = loader_validate_device_extensions(inst, &inst->expanded_activated_layer_list, &icd_exts, pCreateInfo);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "vkCreateDevice: Failed to validate extensions in list");
+ goto out;
+ }
+
+ dev = loader_create_logical_device(inst, pAllocator);
+ if (dev == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ // Copy the application enabled instance layer list into the device
+ if (NULL != inst->app_activated_layer_list.list) {
+ dev->app_activated_layer_list.capacity = inst->app_activated_layer_list.capacity;
+ dev->app_activated_layer_list.count = inst->app_activated_layer_list.count;
+ dev->app_activated_layer_list.list =
+ loader_device_heap_alloc(dev, inst->app_activated_layer_list.capacity, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+ if (dev->app_activated_layer_list.list == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "vkCreateDevice: Failed to allocate application activated layer list of size %d.",
+ inst->app_activated_layer_list.capacity);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memcpy(dev->app_activated_layer_list.list, inst->app_activated_layer_list.list,
+ sizeof(*dev->app_activated_layer_list.list) * dev->app_activated_layer_list.count);
+ } else {
+ dev->app_activated_layer_list.capacity = 0;
+ dev->app_activated_layer_list.count = 0;
+ dev->app_activated_layer_list.list = NULL;
+ }
+
+ // Copy the expanded enabled instance layer list into the device
+ if (NULL != inst->expanded_activated_layer_list.list) {
+ dev->expanded_activated_layer_list.capacity = inst->expanded_activated_layer_list.capacity;
+ dev->expanded_activated_layer_list.count = inst->expanded_activated_layer_list.count;
+ dev->expanded_activated_layer_list.list =
+ loader_device_heap_alloc(dev, inst->expanded_activated_layer_list.capacity, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+ if (dev->expanded_activated_layer_list.list == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "vkCreateDevice: Failed to allocate expanded activated layer list of size %d.",
+ inst->expanded_activated_layer_list.capacity);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memcpy(dev->expanded_activated_layer_list.list, inst->expanded_activated_layer_list.list,
+ sizeof(*dev->expanded_activated_layer_list.list) * dev->expanded_activated_layer_list.count);
+ } else {
+ dev->expanded_activated_layer_list.capacity = 0;
+ dev->expanded_activated_layer_list.count = 0;
+ dev->expanded_activated_layer_list.list = NULL;
+ }
+
+ res = loader_create_device_chain(internal_device, pCreateInfo, pAllocator, inst, dev, layerGIPA, nextGDPA);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "vkCreateDevice: Failed to create device chain.");
+ goto out;
+ }
+
+ *pDevice = dev->chain_device;
+
+ // Initialize any device extension dispatch entry's from the instance list
+ loader_init_dispatch_dev_ext(inst, dev);
+
+ // Initialize WSI device extensions as part of core dispatch since loader
+ // has dedicated trampoline code for these
+ loader_init_device_extension_dispatch_table(&dev->loader_dispatch, inst->disp->layer_inst_disp.GetInstanceProcAddr,
+ dev->loader_dispatch.core_dispatch.GetDeviceProcAddr, inst->instance, *pDevice);
+
+out:
+
+ // Failure cleanup
+ if (VK_SUCCESS != res) {
+ if (NULL != dev) {
+ loader_destroy_logical_device(inst, dev, pAllocator);
+ }
+ }
+
+ if (NULL != icd_exts.list) {
+ loader_destroy_generic_list(inst, (struct loader_generic_list *)&icd_exts);
+ }
+ return res;
+}
+
+VKAPI_ATTR void VKAPI_CALL loader_layer_destroy_device(VkDevice device, const VkAllocationCallbacks *pAllocator,
+ PFN_vkDestroyDevice destroyFunction) {
+ struct loader_device *dev;
+
+ if (device == VK_NULL_HANDLE) {
+ return;
+ }
+
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL);
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ destroyFunction(device, pAllocator);
+ dev->chain_device = NULL;
+ dev->icd_device = NULL;
+ loader_remove_logical_device(inst, icd_term, dev, pAllocator);
+}
+
+// Given the list of layers to activate in the loader_instance
+// structure. This function will add a VkLayerInstanceCreateInfo
+// structure to the VkInstanceCreateInfo.pNext pointer.
+// Each activated layer will have it's own VkLayerInstanceLink
+// structure that tells the layer what Get*ProcAddr to call to
+// get function pointers to the next layer down.
+// Once the chain info has been created this function will
+// execute the CreateInstance call chain. Each layer will
+// then have an opportunity in it's CreateInstance function
+// to setup it's dispatch table when the lower layer returns
+// successfully.
+// Each layer can wrap or not-wrap the returned VkInstance object
+// as it sees fit.
+// The instance chain is terminated by a loader function
+// that will call CreateInstance on all available ICD's and
+// cache those VkInstance objects for future use.
+VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
+ struct loader_instance *inst, VkInstance *created_instance) {
+ uint32_t activated_layers = 0;
+ VkLayerInstanceCreateInfo chain_info;
+ VkLayerInstanceLink *layer_instance_link_info = NULL;
+ VkInstanceCreateInfo loader_create_info;
+ VkResult res;
+
+ PFN_vkGetInstanceProcAddr next_gipa = loader_gpa_instance_internal;
+ PFN_vkGetInstanceProcAddr cur_gipa = loader_gpa_instance_internal;
+ PFN_vkGetDeviceProcAddr cur_gdpa = loader_gpa_device_internal;
+ PFN_GetPhysicalDeviceProcAddr next_gpdpa = loader_gpdpa_instance_internal;
+ PFN_GetPhysicalDeviceProcAddr cur_gpdpa = loader_gpdpa_instance_internal;
+
+ memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo));
+
+ if (inst->expanded_activated_layer_list.count > 0) {
+ chain_info.u.pLayerInfo = NULL;
+ chain_info.pNext = pCreateInfo->pNext;
+ chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+ chain_info.function = VK_LAYER_LINK_INFO;
+ loader_create_info.pNext = &chain_info;
+
+ layer_instance_link_info = loader_stack_alloc(sizeof(VkLayerInstanceLink) * inst->expanded_activated_layer_list.count);
+ if (!layer_instance_link_info) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_create_instance_chain: Failed to alloc Instance"
+ " objects for layer");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ // Create instance chain of enabled layers
+ for (int32_t i = inst->expanded_activated_layer_list.count - 1; i >= 0; i--) {
+ struct loader_layer_properties *layer_prop = &inst->expanded_activated_layer_list.list[i];
+ loader_platform_dl_handle lib_handle;
+
+ lib_handle = loaderOpenLayerFile(inst, "instance", layer_prop);
+ if (!lib_handle) {
+ continue;
+ }
+
+ if (NULL == layer_prop->functions.negotiate_layer_interface) {
+ PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_interface = NULL;
+ bool functions_in_interface = false;
+ if (strlen(layer_prop->functions.str_negotiate_interface) == 0) {
+ negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address(
+ lib_handle, "vkNegotiateLoaderLayerInterfaceVersion");
+ } else {
+ negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address(
+ lib_handle, layer_prop->functions.str_negotiate_interface);
+ }
+
+ // If we can negotiate an interface version, then we can also
+ // get everything we need from the one function call, so try
+ // that first, and see if we can get all the function pointers
+ // necessary from that one call.
+ if (NULL != negotiate_interface) {
+ layer_prop->functions.negotiate_layer_interface = negotiate_interface;
+
+ VkNegotiateLayerInterface interface_struct;
+
+ if (loaderGetLayerInterfaceVersion(negotiate_interface, &interface_struct)) {
+ // Go ahead and set the properties version to the
+ // correct value.
+ layer_prop->interface_version = interface_struct.loaderLayerInterfaceVersion;
+
+ // If the interface is 2 or newer, we have access to the
+ // new GetPhysicalDeviceProcAddr function, so grab it,
+ // and the other necessary functions, from the
+ // structure.
+ if (interface_struct.loaderLayerInterfaceVersion > 1) {
+ cur_gipa = interface_struct.pfnGetInstanceProcAddr;
+ cur_gdpa = interface_struct.pfnGetDeviceProcAddr;
+ cur_gpdpa = interface_struct.pfnGetPhysicalDeviceProcAddr;
+ if (cur_gipa != NULL) {
+ // We've set the functions, so make sure we
+ // don't do the unnecessary calls later.
+ functions_in_interface = true;
+ }
+ }
+ }
+ }
+
+ if (!functions_in_interface) {
+ if ((cur_gipa = layer_prop->functions.get_instance_proc_addr) == NULL) {
+ if (strlen(layer_prop->functions.str_gipa) == 0) {
+ cur_gipa =
+ (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
+ layer_prop->functions.get_instance_proc_addr = cur_gipa;
+ } else {
+ cur_gipa = (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle,
+ layer_prop->functions.str_gipa);
+ }
+
+ if (NULL == cur_gipa) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_create_instance_chain: Failed to"
+ " find \'vkGetInstanceProcAddr\' in "
+ "layer %s",
+ layer_prop->lib_name);
+ continue;
+ }
+ }
+ }
+ }
+
+ layer_instance_link_info[activated_layers].pNext = chain_info.u.pLayerInfo;
+ layer_instance_link_info[activated_layers].pfnNextGetInstanceProcAddr = next_gipa;
+ layer_instance_link_info[activated_layers].pfnNextGetPhysicalDeviceProcAddr = next_gpdpa;
+ next_gipa = cur_gipa;
+ if (layer_prop->interface_version > 1 && cur_gpdpa != NULL) {
+ layer_prop->functions.get_physical_device_proc_addr = cur_gpdpa;
+ next_gpdpa = cur_gpdpa;
+ }
+ if (layer_prop->interface_version > 1 && cur_gipa != NULL) {
+ layer_prop->functions.get_instance_proc_addr = cur_gipa;
+ }
+ if (layer_prop->interface_version > 1 && cur_gdpa != NULL) {
+ layer_prop->functions.get_device_proc_addr = cur_gdpa;
+ }
+
+ chain_info.u.pLayerInfo = &layer_instance_link_info[activated_layers];
+
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Insert instance layer %s (%s)", layer_prop->info.layerName,
+ layer_prop->lib_name);
+
+ activated_layers++;
+ }
+ }
+
+ PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)next_gipa(*created_instance, "vkCreateInstance");
+ if (fpCreateInstance) {
+ VkLayerInstanceCreateInfo create_info_disp;
+
+ create_info_disp.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+ create_info_disp.function = VK_LOADER_DATA_CALLBACK;
+
+ create_info_disp.u.pfnSetInstanceLoaderData = vkSetInstanceDispatch;
+
+ create_info_disp.pNext = loader_create_info.pNext;
+ loader_create_info.pNext = &create_info_disp;
+
+ VkLayerInstanceCreateInfo create_info_disp2;
+
+ create_info_disp2.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+ create_info_disp2.function = VK_LOADER_LAYER_CREATE_DEVICE_CALLBACK;
+
+ create_info_disp2.u.layerDevice.pfnLayerCreateDevice = loader_layer_create_device;
+ create_info_disp2.u.layerDevice.pfnLayerDestroyDevice = loader_layer_destroy_device;
+
+ create_info_disp2.pNext = loader_create_info.pNext;
+ loader_create_info.pNext = &create_info_disp2;
+
+ res = fpCreateInstance(&loader_create_info, pAllocator, created_instance);
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_create_instance_chain: Failed to find "
+ "\'vkCreateInstance\'");
+ // Couldn't find CreateInstance function!
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (res == VK_SUCCESS) {
+ loader_init_instance_core_dispatch_table(&inst->disp->layer_inst_disp, next_gipa, *created_instance);
+ inst->instance = *created_instance;
+ }
+
+ return res;
+}
+
+void loaderActivateInstanceLayerExtensions(struct loader_instance *inst, VkInstance created_inst) {
+ loader_init_instance_extension_dispatch_table(&inst->disp->layer_inst_disp, inst->disp->layer_inst_disp.GetInstanceProcAddr,
+ created_inst);
+}
+
+VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, const struct loader_instance *inst,
+ struct loader_device *dev, PFN_vkGetInstanceProcAddr callingLayer,
+ PFN_vkGetDeviceProcAddr *layerNextGDPA) {
+ uint32_t activated_layers = 0;
+ VkLayerDeviceLink *layer_device_link_info;
+ VkLayerDeviceCreateInfo chain_info;
+ VkDeviceCreateInfo loader_create_info;
+ VkResult res;
+
+ PFN_vkGetDeviceProcAddr fpGDPA = NULL, nextGDPA = loader_gpa_device_internal;
+ PFN_vkGetInstanceProcAddr fpGIPA = NULL, nextGIPA = loader_gpa_instance_internal;
+
+ memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
+
+ // Before we continue, we need to find out if the KHR_device_group extension is in the enabled list. If it is, we then
+ // need to look for the corresponding VkDeviceGroupDeviceCreateInfoKHR struct in the device list. This is because we
+ // need to replace all the incoming physical device values (which are really loader trampoline physical device values)
+ // with the layer/ICD version.
+ {
+ VkBaseOutStructure *pNext = (VkBaseOutStructure *)loader_create_info.pNext;
+ VkBaseOutStructure *pPrev = (VkBaseOutStructure *)&loader_create_info;
+ while (NULL != pNext) {
+ if (VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO == pNext->sType) {
+ VkDeviceGroupDeviceCreateInfoKHR *cur_struct = (VkDeviceGroupDeviceCreateInfoKHR *)pNext;
+ if (0 < cur_struct->physicalDeviceCount && NULL != cur_struct->pPhysicalDevices) {
+ VkDeviceGroupDeviceCreateInfoKHR *temp_struct = loader_stack_alloc(sizeof(VkDeviceGroupDeviceCreateInfoKHR));
+ VkPhysicalDevice *phys_dev_array = NULL;
+ if (NULL == temp_struct) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memcpy(temp_struct, cur_struct, sizeof(VkDeviceGroupDeviceCreateInfoKHR));
+ phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * cur_struct->physicalDeviceCount);
+ if (NULL == phys_dev_array) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ // Before calling down, replace the incoming physical device values (which are really loader trampoline
+ // physical devices) with the next layer (or possibly even the terminator) physical device values.
+ struct loader_physical_device_tramp *cur_tramp;
+ for (uint32_t phys_dev = 0; phys_dev < cur_struct->physicalDeviceCount; phys_dev++) {
+ cur_tramp = (struct loader_physical_device_tramp *)cur_struct->pPhysicalDevices[phys_dev];
+ phys_dev_array[phys_dev] = cur_tramp->phys_dev;
+ }
+ temp_struct->pPhysicalDevices = phys_dev_array;
+
+ // Replace the old struct in the pNext chain with this one.
+ pPrev->pNext = (VkBaseOutStructure *)temp_struct;
+ pNext = (VkBaseOutStructure *)temp_struct;
+ }
+ break;
+ }
+
+ pPrev = pNext;
+ pNext = pNext->pNext;
+ }
+ }
+
+ layer_device_link_info = loader_stack_alloc(sizeof(VkLayerDeviceLink) * dev->expanded_activated_layer_list.count);
+ if (!layer_device_link_info) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_create_device_chain: Failed to alloc Device objects"
+ " for layer. Skipping Layer.");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ if (dev->expanded_activated_layer_list.count > 0) {
+ chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+ chain_info.function = VK_LAYER_LINK_INFO;
+ chain_info.u.pLayerInfo = NULL;
+ chain_info.pNext = loader_create_info.pNext;
+ loader_create_info.pNext = &chain_info;
+
+ bool done = false;
+
+ // Create instance chain of enabled layers
+ for (int32_t i = dev->expanded_activated_layer_list.count - 1; i >= 0; i--) {
+ struct loader_layer_properties *layer_prop = &dev->expanded_activated_layer_list.list[i];
+ loader_platform_dl_handle lib_handle;
+
+ lib_handle = loaderOpenLayerFile(inst, "device", layer_prop);
+ if (!lib_handle || done) {
+ continue;
+ }
+
+ // The Get*ProcAddr pointers will already be filled in if they were received from either the json file or the
+ // version negotiation
+ if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
+ if (strlen(layer_prop->functions.str_gipa) == 0) {
+ fpGIPA = (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
+ layer_prop->functions.get_instance_proc_addr = fpGIPA;
+ } else
+ fpGIPA =
+ (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
+ if (!fpGIPA) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_create_device_chain: Failed to find "
+ "\'vkGetInstanceProcAddr\' in layer %s. Skipping"
+ " layer.",
+ layer_prop->lib_name);
+ continue;
+ }
+ }
+
+ if (fpGIPA == callingLayer) {
+ if (layerNextGDPA != NULL) {
+ *layerNextGDPA = nextGDPA;
+ }
+ done = true;
+ continue;
+ }
+
+ if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) {
+ if (strlen(layer_prop->functions.str_gdpa) == 0) {
+ fpGDPA = (PFN_vkGetDeviceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
+ layer_prop->functions.get_device_proc_addr = fpGDPA;
+ } else
+ fpGDPA =
+ (PFN_vkGetDeviceProcAddr)loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
+ if (!fpGDPA) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Failed to find vkGetDeviceProcAddr in layer %s",
+ layer_prop->lib_name);
+ continue;
+ }
+ }
+
+ layer_device_link_info[activated_layers].pNext = chain_info.u.pLayerInfo;
+ layer_device_link_info[activated_layers].pfnNextGetInstanceProcAddr = nextGIPA;
+ layer_device_link_info[activated_layers].pfnNextGetDeviceProcAddr = nextGDPA;
+ chain_info.u.pLayerInfo = &layer_device_link_info[activated_layers];
+ nextGIPA = fpGIPA;
+ nextGDPA = fpGDPA;
+
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Inserted device layer %s (%s)", layer_prop->info.layerName,
+ layer_prop->lib_name);
+
+ activated_layers++;
+ }
+ }
+
+ VkDevice created_device = (VkDevice)dev;
+ PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)nextGIPA(inst->instance, "vkCreateDevice");
+ if (fpCreateDevice) {
+ VkLayerDeviceCreateInfo create_info_disp;
+
+ create_info_disp.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+ create_info_disp.function = VK_LOADER_DATA_CALLBACK;
+
+ create_info_disp.u.pfnSetDeviceLoaderData = vkSetDeviceDispatch;
+
+ create_info_disp.pNext = loader_create_info.pNext;
+ loader_create_info.pNext = &create_info_disp;
+ res = fpCreateDevice(pd, &loader_create_info, pAllocator, &created_device);
+ if (res != VK_SUCCESS) {
+ return res;
+ }
+ dev->chain_device = created_device;
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_create_device_chain: Failed to find \'vkCreateDevice\' "
+ "in layers or ICD");
+ // Couldn't find CreateDevice function!
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ // Initialize device dispatch table
+ loader_init_device_dispatch_table(&dev->loader_dispatch, nextGDPA, dev->chain_device);
+
+ return res;
+}
+
+VkResult loaderValidateLayers(const struct loader_instance *inst, const uint32_t layer_count,
+ const char *const *ppEnabledLayerNames, const struct loader_layer_list *list) {
+ struct loader_layer_properties *prop;
+
+ for (uint32_t i = 0; i < layer_count; i++) {
+ VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]);
+ if (result != VK_STRING_ERROR_NONE) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderValidateLayers: Device ppEnabledLayerNames "
+ "contains string that is too long or is badly formed");
+ return VK_ERROR_LAYER_NOT_PRESENT;
+ }
+
+ prop = loaderFindLayerProperty(ppEnabledLayerNames[i], list);
+ if (NULL == prop) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loaderValidateLayers: Layer %d does not exist in the list of available layers", i);
+ return VK_ERROR_LAYER_NOT_PRESENT;
+ }
+ }
+ return VK_SUCCESS;
+}
+
+VkResult loader_validate_instance_extensions(struct loader_instance *inst, const struct loader_extension_list *icd_exts,
+ const struct loader_layer_list *instance_layers,
+ const VkInstanceCreateInfo *pCreateInfo) {
+ VkExtensionProperties *extension_prop;
+ char *env_value;
+ bool check_if_known = true;
+ VkResult res = VK_SUCCESS;
+
+ struct loader_layer_list active_layers;
+ struct loader_layer_list expanded_layers;
+ memset(&active_layers, 0, sizeof(active_layers));
+ memset(&expanded_layers, 0, sizeof(expanded_layers));
+ if (!loaderInitLayerList(inst, &active_layers)) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ if (!loaderInitLayerList(inst, &expanded_layers)) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ // Build the lists of active layers (including metalayers) and expanded layers (with metalayers resolved to their components)
+ loaderAddImplicitLayers(inst, &active_layers, &expanded_layers, instance_layers);
+ loaderAddEnvironmentLayers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, ENABLED_LAYERS_ENV, &active_layers, &expanded_layers,
+ instance_layers);
+ res = loaderAddLayerNamesToList(inst, &active_layers, &expanded_layers, pCreateInfo->enabledLayerCount,
+ pCreateInfo->ppEnabledLayerNames, instance_layers);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]);
+ if (result != VK_STRING_ERROR_NONE) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_validate_instance_extensions: Instance ppEnabledExtensionNames contains "
+ "string that is too long or is badly formed");
+ res = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+
+ // Check if a user wants to disable the instance extension filtering behavior
+ env_value = loader_getenv("VK_LOADER_DISABLE_INST_EXT_FILTER", inst);
+ if (NULL != env_value && atoi(env_value) != 0) {
+ check_if_known = false;
+ }
+ loader_free_getenv(env_value, inst);
+
+ if (check_if_known) {
+ // See if the extension is in the list of supported extensions
+ bool found = false;
+ for (uint32_t j = 0; LOADER_INSTANCE_EXTENSIONS[j] != NULL; j++) {
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], LOADER_INSTANCE_EXTENSIONS[j]) == 0) {
+ found = true;
+ break;
+ }
+ }
+
+ // If it isn't in the list, return an error
+ if (!found) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_validate_instance_extensions: Extension %s not found in list of known instance extensions.",
+ pCreateInfo->ppEnabledExtensionNames[i]);
+ res = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+ }
+
+ extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], icd_exts);
+
+ if (extension_prop) {
+ continue;
+ }
+
+ extension_prop = NULL;
+
+ // Not in global list, search layer extension lists
+ struct loader_layer_properties *layer_prop = NULL;
+ for (uint32_t j = 0; NULL == extension_prop && j < expanded_layers.count; ++j) {
+ extension_prop =
+ get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], &expanded_layers.list[j].instance_extension_list);
+ if (extension_prop) {
+ // Found the extension in one of the layers enabled by the app.
+ break;
+ }
+
+ layer_prop = loaderFindLayerProperty(expanded_layers.list[j].info.layerName, instance_layers);
+ if (NULL == layer_prop) {
+ // Should NOT get here, loaderValidateLayers should have already filtered this case out.
+ continue;
+ }
+ }
+
+ if (!extension_prop) {
+ // Didn't find extension name in any of the global layers, error out
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_validate_instance_extensions: Instance extension %s not supported by available ICDs or enabled "
+ "layers.",
+ pCreateInfo->ppEnabledExtensionNames[i]);
+ res = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+ }
+
+out:
+ loaderDestroyLayerList(inst, NULL, &active_layers);
+ loaderDestroyLayerList(inst, NULL, &expanded_layers);
+ return res;
+}
+
+VkResult loader_validate_device_extensions(struct loader_instance *this_instance,
+ const struct loader_layer_list *activated_device_layers,
+ const struct loader_extension_list *icd_exts, const VkDeviceCreateInfo *pCreateInfo) {
+ VkExtensionProperties *extension_prop;
+ struct loader_layer_properties *layer_prop;
+
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]);
+ if (result != VK_STRING_ERROR_NONE) {
+ loader_log(this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_validate_device_extensions: Device ppEnabledExtensionNames contains "
+ "string that is too long or is badly formed");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
+ extension_prop = get_extension_property(extension_name, icd_exts);
+
+ if (extension_prop) {
+ continue;
+ }
+
+ // Not in global list, search activated layer extension lists
+ for (uint32_t j = 0; j < activated_device_layers->count; j++) {
+ layer_prop = &activated_device_layers->list[j];
+
+ extension_prop = get_dev_extension_property(extension_name, &layer_prop->device_extension_list);
+ if (extension_prop) {
+ // Found the extension in one of the layers enabled by the app.
+ break;
+ }
+ }
+
+ if (!extension_prop) {
+ // Didn't find extension name in any of the device layers, error out
+ loader_log(this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_validate_device_extensions: Device extension %s not supported by selected physical device "
+ "or enabled layers.",
+ pCreateInfo->ppEnabledExtensionNames[i]);
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+ }
+ return VK_SUCCESS;
+}
+
+// Terminator functions for the Instance chain
+// All named terminator_<Vulkan API name>
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
+ struct loader_icd_term *icd_term;
+ VkExtensionProperties *prop;
+ char **filtered_extension_names = NULL;
+ VkInstanceCreateInfo icd_create_info;
+ VkResult res = VK_SUCCESS;
+ bool one_icd_successful = false;
+
+ struct loader_instance *ptr_instance = (struct loader_instance *)*pInstance;
+ memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
+
+ icd_create_info.enabledLayerCount = 0;
+ icd_create_info.ppEnabledLayerNames = NULL;
+
+ // NOTE: Need to filter the extensions to only those supported by the ICD.
+ // No ICD will advertise support for layers. An ICD library could
+ // support a layer, but it would be independent of the actual ICD,
+ // just in the same library.
+ filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
+ if (!filtered_extension_names) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "terminator_CreateInstance: Failed create extension name array for %d extensions",
+ pCreateInfo->enabledExtensionCount);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ icd_create_info.ppEnabledExtensionNames = (const char *const *)filtered_extension_names;
+
+ for (uint32_t i = 0; i < ptr_instance->icd_tramp_list.count; i++) {
+ icd_term = loader_icd_add(ptr_instance, &ptr_instance->icd_tramp_list.scanned_list[i]);
+ if (NULL == icd_term) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "terminator_CreateInstance: Failed to add ICD %d to ICD trampoline list.", i);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ // If any error happens after here, we need to remove the ICD from the list,
+ // because we've already added it, but haven't validated it
+
+ // Make sure that we reset the pApplicationInfo so we don't get an old pointer
+ icd_create_info.pApplicationInfo = pCreateInfo->pApplicationInfo;
+ icd_create_info.enabledExtensionCount = 0;
+ struct loader_extension_list icd_exts;
+
+ loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
+ // traverse scanned icd list adding non-duplicate extensions to the list
+ res = loader_init_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties));
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ // If out of memory, bail immediately.
+ goto out;
+ } else if (VK_SUCCESS != res) {
+ // Something bad happened with this ICD, so free it and try the
+ // next.
+ ptr_instance->icd_terms = icd_term->next;
+ icd_term->next = NULL;
+ loader_icd_destroy(ptr_instance, icd_term, pAllocator);
+ continue;
+ }
+
+ res = loader_add_instance_extensions(ptr_instance, icd_term->scanned_icd->EnumerateInstanceExtensionProperties,
+ icd_term->scanned_icd->lib_name, &icd_exts);
+ if (VK_SUCCESS != res) {
+ loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ // If out of memory, bail immediately.
+ goto out;
+ } else {
+ // Something bad happened with this ICD, so free it and try the next.
+ ptr_instance->icd_terms = icd_term->next;
+ icd_term->next = NULL;
+ loader_icd_destroy(ptr_instance, icd_term, pAllocator);
+ continue;
+ }
+ }
+
+ for (uint32_t j = 0; j < pCreateInfo->enabledExtensionCount; j++) {
+ prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[j], &icd_exts);
+ if (prop) {
+ filtered_extension_names[icd_create_info.enabledExtensionCount] = (char *)pCreateInfo->ppEnabledExtensionNames[j];
+ icd_create_info.enabledExtensionCount++;
+ }
+ }
+
+ loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts);
+
+ // Get the driver version from vkEnumerateInstanceVersion
+ uint32_t icd_version = VK_API_VERSION_1_0;
+ VkResult icd_result = VK_SUCCESS;
+ if (icd_term->scanned_icd->api_version >= VK_API_VERSION_1_1) {
+ PFN_vkEnumerateInstanceVersion icd_enumerate_instance_version = (PFN_vkEnumerateInstanceVersion)
+ icd_term->scanned_icd->GetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion");
+ if (icd_enumerate_instance_version != NULL) {
+ icd_result = icd_enumerate_instance_version(&icd_version);
+ if (icd_result != VK_SUCCESS) {
+ icd_version = VK_API_VERSION_1_0;
+ loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "terminator_CreateInstance: ICD \"%s\" "
+ "vkEnumerateInstanceVersion returned error. The ICD will be treated as a 1.0 ICD",
+ icd_term->scanned_icd->lib_name);
+ }
+ }
+ }
+
+ // Create an instance, substituting the version to 1.0 if necessary
+ VkApplicationInfo icd_app_info;
+ uint32_t icd_version_nopatch = VK_MAKE_VERSION(VK_VERSION_MAJOR(icd_version), VK_VERSION_MINOR(icd_version), 0);
+ uint32_t requested_version = pCreateInfo == NULL || pCreateInfo->pApplicationInfo == NULL ? VK_API_VERSION_1_0 : pCreateInfo->pApplicationInfo->apiVersion;
+ if ((requested_version != 0) && (icd_version_nopatch == VK_API_VERSION_1_0)) {
+ if (icd_create_info.pApplicationInfo == NULL) {
+ memset(&icd_app_info, 0, sizeof(icd_app_info));
+ } else {
+ memcpy(&icd_app_info, icd_create_info.pApplicationInfo, sizeof(icd_app_info));
+ }
+ icd_app_info.apiVersion = icd_version;
+ icd_create_info.pApplicationInfo = &icd_app_info;
+ }
+ icd_result = ptr_instance->icd_tramp_list.scanned_list[i].CreateInstance(&icd_create_info, pAllocator, &(icd_term->instance));
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_result) {
+ // If out of memory, bail immediately.
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ } else if (VK_SUCCESS != icd_result) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "terminator_CreateInstance: Failed to CreateInstance in "
+ "ICD %d. Skipping ICD.",
+ i);
+ ptr_instance->icd_terms = icd_term->next;
+ icd_term->next = NULL;
+ loader_icd_destroy(ptr_instance, icd_term, pAllocator);
+ continue;
+ }
+
+ if (!loader_icd_init_entries(icd_term, icd_term->instance,
+ ptr_instance->icd_tramp_list.scanned_list[i].GetInstanceProcAddr)) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "terminator_CreateInstance: Failed to CreateInstance and find "
+ "entrypoints with ICD. Skipping ICD.");
+ ptr_instance->icd_terms = icd_term->next;
+ icd_term->next = NULL;
+ loader_icd_destroy(ptr_instance, icd_term, pAllocator);
+ continue;
+ }
+
+ // If we made it this far, at least one ICD was successful
+ one_icd_successful = true;
+ }
+
+ // If no ICDs were added to instance list and res is unchanged from it's initial value, the loader was unable to
+ // find a suitable ICD.
+ if (VK_SUCCESS == res && (ptr_instance->icd_terms == NULL || !one_icd_successful)) {
+ res = VK_ERROR_INCOMPATIBLE_DRIVER;
+ }
+
+out:
+
+ if (VK_SUCCESS != res) {
+ while (NULL != ptr_instance->icd_terms) {
+ icd_term = ptr_instance->icd_terms;
+ ptr_instance->icd_terms = icd_term->next;
+ if (NULL != icd_term->instance) {
+ icd_term->dispatch.DestroyInstance(icd_term->instance, pAllocator);
+ }
+ loader_icd_destroy(ptr_instance, icd_term, pAllocator);
+ }
+ }
+
+ return res;
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
+ struct loader_instance *ptr_instance = loader_instance(instance);
+ if (NULL == ptr_instance) {
+ return;
+ }
+ struct loader_icd_term *icd_terms = ptr_instance->icd_terms;
+ struct loader_icd_term *next_icd_term;
+
+ // Remove this instance from the list of instances:
+ struct loader_instance *prev = NULL;
+ struct loader_instance *next = loader.instances;
+ while (next != NULL) {
+ if (next == ptr_instance) {
+ // Remove this instance from the list:
+ if (prev)
+ prev->next = next->next;
+ else
+ loader.instances = next->next;
+ break;
+ }
+ prev = next;
+ next = next->next;
+ }
+
+ while (NULL != icd_terms) {
+ if (icd_terms->instance) {
+ icd_terms->dispatch.DestroyInstance(icd_terms->instance, pAllocator);
+ }
+ next_icd_term = icd_terms->next;
+ icd_terms->instance = VK_NULL_HANDLE;
+ loader_icd_destroy(ptr_instance, icd_terms, pAllocator);
+
+ icd_terms = next_icd_term;
+ }
+
+ loaderDeleteLayerListAndProperties(ptr_instance, &ptr_instance->instance_layer_list);
+ loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_tramp_list);
+ loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list);
+ if (NULL != ptr_instance->phys_devs_term) {
+ for (uint32_t i = 0; i < ptr_instance->phys_dev_count_term; i++) {
+ loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_term[i]);
+ }
+ loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_term);
+ }
+ if (NULL != ptr_instance->phys_dev_groups_term) {
+ for (uint32_t i = 0; i < ptr_instance->phys_dev_group_count_term; i++) {
+ loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_term[i]);
+ }
+ loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_term);
+ }
+ loader_free_dev_ext_table(ptr_instance);
+ loader_free_phys_dev_ext_table(ptr_instance);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
+ VkResult res = VK_SUCCESS;
+ struct loader_physical_device_term *phys_dev_term;
+ phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ struct loader_device *dev = (struct loader_device *)*pDevice;
+ PFN_vkCreateDevice fpCreateDevice = icd_term->dispatch.CreateDevice;
+ struct loader_extension_list icd_exts;
+
+ VkBaseOutStructure *caller_dgci_container = NULL;
+ VkDeviceGroupDeviceCreateInfoKHR *caller_dgci = NULL;
+
+ dev->phys_dev_term = phys_dev_term;
+
+ icd_exts.list = NULL;
+
+ if (fpCreateDevice == NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "terminator_CreateDevice: No vkCreateDevice command exposed "
+ "by ICD %s",
+ icd_term->scanned_icd->lib_name);
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ VkDeviceCreateInfo localCreateInfo;
+ memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo));
+
+ // NOTE: Need to filter the extensions to only those supported by the ICD.
+ // No ICD will advertise support for layers. An ICD library could support a layer,
+ // but it would be independent of the actual ICD, just in the same library.
+ char **filtered_extension_names = NULL;
+ if (0 < pCreateInfo->enabledExtensionCount) {
+ filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
+ if (NULL == filtered_extension_names) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "terminator_CreateDevice: Failed to create extension name "
+ "storage for %d extensions",
+ pCreateInfo->enabledExtensionCount);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ }
+
+ localCreateInfo.enabledLayerCount = 0;
+ localCreateInfo.ppEnabledLayerNames = NULL;
+
+ localCreateInfo.enabledExtensionCount = 0;
+ localCreateInfo.ppEnabledExtensionNames = (const char *const *)filtered_extension_names;
+
+ // Get the physical device (ICD) extensions
+ res = loader_init_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties));
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
+ res = loader_add_device_extensions(icd_term->this_instance, icd_term->dispatch.EnumerateDeviceExtensionProperties,
+ phys_dev_term->phys_dev, icd_term->scanned_icd->lib_name, &icd_exts);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
+ VkExtensionProperties *prop = get_extension_property(extension_name, &icd_exts);
+ if (prop) {
+ filtered_extension_names[localCreateInfo.enabledExtensionCount] = (char *)extension_name;
+ localCreateInfo.enabledExtensionCount++;
+ } else {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
+ "vkCreateDevice extension %s not available for "
+ "devices associated with ICD %s",
+ extension_name, icd_term->scanned_icd->lib_name);
+ }
+ }
+
+ // Before we continue, If KHX_device_group is the list of enabled and viable extensions, then we then need to look for the
+ // corresponding VkDeviceGroupDeviceCreateInfo struct in the device list and replace all the physical device values (which
+ // are really loader physical device terminator values) with the ICD versions.
+ //if (icd_term->this_instance->enabled_known_extensions.khr_device_group_creation == 1) {
+ {
+ VkBaseOutStructure *pNext = (VkBaseOutStructure *)localCreateInfo.pNext;
+ VkBaseOutStructure *pPrev = (VkBaseOutStructure *)&localCreateInfo;
+ while (NULL != pNext) {
+ if (VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO == pNext->sType) {
+ VkDeviceGroupDeviceCreateInfo *cur_struct = (VkDeviceGroupDeviceCreateInfo *)pNext;
+ if (0 < cur_struct->physicalDeviceCount && NULL != cur_struct->pPhysicalDevices) {
+ VkDeviceGroupDeviceCreateInfo *temp_struct = loader_stack_alloc(sizeof(VkDeviceGroupDeviceCreateInfo));
+ VkPhysicalDevice *phys_dev_array = NULL;
+ if (NULL == temp_struct) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memcpy(temp_struct, cur_struct, sizeof(VkDeviceGroupDeviceCreateInfo));
+ phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * cur_struct->physicalDeviceCount);
+ if (NULL == phys_dev_array) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ // Before calling down, replace the incoming physical device values (which are really loader terminator
+ // physical devices) with the ICDs physical device values.
+ struct loader_physical_device_term *cur_term;
+ for (uint32_t phys_dev = 0; phys_dev < cur_struct->physicalDeviceCount; phys_dev++) {
+ cur_term = (struct loader_physical_device_term *)cur_struct->pPhysicalDevices[phys_dev];
+ phys_dev_array[phys_dev] = cur_term->phys_dev;
+ }
+ temp_struct->pPhysicalDevices = phys_dev_array;
+
+ // Keep track of pointers to restore pNext chain before returning
+ caller_dgci_container = pPrev;
+ caller_dgci = cur_struct;
+
+ // Replace the old struct in the pNext chain with this one.
+ pPrev->pNext = (VkBaseOutStructure *)temp_struct;
+ pNext = (VkBaseOutStructure *)temp_struct;
+ }
+ break;
+ }
+
+ pPrev = pNext;
+ pNext = pNext->pNext;
+ }
+ }
+
+ // Handle loader emulation for structs that are not supported by the ICD:
+ // Presently, the emulation leaves the pNext chain alone. This means that the ICD will receive items in the chain which
+ // are not recognized by the ICD. If this causes the ICD to fail, then the items would have to be removed here. The current
+ // implementation does not remove them because copying the pNext chain would be impossible if the loader does not recognize
+ // the any of the struct types, as the loader would not know the size to allocate and copy.
+ //if (icd_term->dispatch.GetPhysicalDeviceFeatures2 == NULL && icd_term->dispatch.GetPhysicalDeviceFeatures2KHR == NULL) {
+ {
+ const void *pNext = localCreateInfo.pNext;
+ while (pNext != NULL) {
+ switch (*(VkStructureType *)pNext) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: {
+ const VkPhysicalDeviceFeatures2KHR *features = pNext;
+
+ if (icd_term->dispatch.GetPhysicalDeviceFeatures2 == NULL && icd_term->dispatch.GetPhysicalDeviceFeatures2KHR == NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkCreateDevice: Emulating handling of VkPhysicalDeviceFeatures2 in pNext chain for ICD \"%s\"",
+ icd_term->scanned_icd->lib_name);
+
+ // Verify that VK_KHR_get_physical_device_properties2 is enabled
+ if (icd_term->this_instance->enabled_known_extensions.khr_get_physical_device_properties2) {
+ localCreateInfo.pEnabledFeatures = &features->features;
+ }
+ }
+
+ // Leave this item in the pNext chain for now
+
+ pNext = features->pNext;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO: {
+ const VkDeviceGroupDeviceCreateInfoKHR *group_info = pNext;
+
+ if (icd_term->dispatch.EnumeratePhysicalDeviceGroups == NULL && icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHR == NULL) {
+ loader_log(
+ icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkCreateDevice: Emulating handling of VkPhysicalDeviceGroupProperties in pNext chain for ICD \"%s\"",
+ icd_term->scanned_icd->lib_name);
+
+ // The group must contain only this one device, since physical device groups aren't actually supported
+ if (group_info->physicalDeviceCount != 1) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "vkCreateDevice: Emulation failed to create device from device group info");
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+ }
+
+ // Nothing needs to be done here because we're leaving the item in the pNext chain and because the spec states
+ // that the physicalDevice argument must be included in the device group, and we've already checked that it is
+
+ pNext = group_info->pNext;
+ break;
+ }
+
+ // Multiview properties are also allowed, but since VK_KHX_multiview is a device extension, we'll just let the ICD
+ // handle that error when the user enables the extension here
+ default: {
+ const VkBaseInStructure *header = pNext;
+ pNext = header->pNext;
+ break;
+ }
+ }
+ }
+ }
+
+ // Every extension that has a loader-defined terminator needs to be marked as enabled or disabled so that we know whether or
+ // not to return that terminator when vkGetDeviceProcAddr is called
+ for (uint32_t i = 0; i < localCreateInfo.enabledExtensionCount; ++i) {
+ if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
+ dev->extensions.khr_swapchain_enabled = true;
+ } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME)) {
+ dev->extensions.khr_display_swapchain_enabled = true;
+ } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_KHR_DEVICE_GROUP_EXTENSION_NAME)) {
+ dev->extensions.khr_device_group_enabled = true;
+ } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
+ dev->extensions.ext_debug_marker_enabled = true;
+ } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], "VK_EXT_full_screen_exclusive")) {
+ dev->extensions.ext_full_screen_exclusive_enabled = true;
+ }
+ }
+ dev->extensions.ext_debug_utils_enabled = icd_term->this_instance->enabled_known_extensions.ext_debug_utils;
+
+ if (!dev->extensions.khr_device_group_enabled) {
+ VkPhysicalDeviceProperties properties;
+ icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, &properties);
+ if (properties.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
+ dev->extensions.khr_device_group_enabled = true;
+ }
+ }
+
+ res = fpCreateDevice(phys_dev_term->phys_dev, &localCreateInfo, pAllocator, &dev->icd_device);
+ if (res != VK_SUCCESS) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "terminator_CreateDevice: Failed in ICD %s vkCreateDevice"
+ "call",
+ icd_term->scanned_icd->lib_name);
+ goto out;
+ }
+
+ *pDevice = dev->icd_device;
+ loader_add_logical_device(icd_term->this_instance, icd_term, dev);
+
+ // Init dispatch pointer in new device object
+ loader_init_dispatch(*pDevice, &dev->loader_dispatch);
+
+out:
+ if (NULL != icd_exts.list) {
+ loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts);
+ }
+
+ // Restore pNext pointer to old VkDeviceGroupDeviceCreateInfoKHX
+ // in the chain to maintain consistency for the caller.
+ if (caller_dgci_container != NULL) {
+ caller_dgci_container->pNext = (VkBaseOutStructure *)caller_dgci;
+ }
+
+ return res;
+}
+
+VkResult setupLoaderTrampPhysDevs(VkInstance instance) {
+ VkResult res = VK_SUCCESS;
+ VkPhysicalDevice *local_phys_devs = NULL;
+ struct loader_instance *inst;
+ uint32_t total_count = 0;
+ struct loader_physical_device_tramp **new_phys_devs = NULL;
+
+ inst = loader_get_instance(instance);
+ if (NULL == inst) {
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ // Query how many GPUs there
+ res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(instance, &total_count, NULL);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevs: Failed during dispatch call "
+ "of \'vkEnumeratePhysicalDevices\' to lower layers or "
+ "loader to get count.");
+ goto out;
+ }
+
+ // Really use what the total GPU count is since Optimus and other layers may mess
+ // the count up.
+ total_count = inst->total_gpu_count;
+
+ // Create an array for the new physical devices, which will be stored
+ // in the instance for the trampoline code.
+ new_phys_devs = (struct loader_physical_device_tramp **)loader_instance_heap_alloc(
+ inst, total_count * sizeof(struct loader_physical_device_tramp *), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_phys_devs) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevs: Failed to allocate new physical device"
+ " array of size %d",
+ total_count);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memset(new_phys_devs, 0, total_count * sizeof(struct loader_physical_device_tramp *));
+
+ // Create a temporary array (on the stack) to keep track of the
+ // returned VkPhysicalDevice values.
+ local_phys_devs = loader_stack_alloc(sizeof(VkPhysicalDevice) * total_count);
+ if (NULL == local_phys_devs) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevs: Failed to allocate local "
+ "physical device array of size %d",
+ total_count);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memset(local_phys_devs, 0, sizeof(VkPhysicalDevice) * total_count);
+
+ res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(instance, &total_count, local_phys_devs);
+ if (VK_SUCCESS != res) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevs: Failed during dispatch call "
+ "of \'vkEnumeratePhysicalDevices\' to lower layers or "
+ "loader to get content.");
+ goto out;
+ }
+
+ // Copy or create everything to fill the new array of physical devices
+ for (uint32_t new_idx = 0; new_idx < total_count; new_idx++) {
+ // Check if this physical device is already in the old buffer
+ for (uint32_t old_idx = 0; old_idx < inst->phys_dev_count_tramp; old_idx++) {
+ if (local_phys_devs[new_idx] == inst->phys_devs_tramp[old_idx]->phys_dev) {
+ new_phys_devs[new_idx] = inst->phys_devs_tramp[old_idx];
+ break;
+ }
+ }
+
+ // If this physical device isn't in the old buffer, create it
+ if (NULL == new_phys_devs[new_idx]) {
+ new_phys_devs[new_idx] = (struct loader_physical_device_tramp *)loader_instance_heap_alloc(
+ inst, sizeof(struct loader_physical_device_tramp), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_phys_devs[new_idx]) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevs: Failed to allocate "
+ "physical device trampoline object %d",
+ new_idx);
+ total_count = new_idx;
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ // Initialize the new physicalDevice object
+ loader_set_dispatch((void *)new_phys_devs[new_idx], inst->disp);
+ new_phys_devs[new_idx]->this_instance = inst;
+ new_phys_devs[new_idx]->phys_dev = local_phys_devs[new_idx];
+ }
+ }
+
+out:
+
+ if (VK_SUCCESS != res) {
+ if (NULL != new_phys_devs) {
+ for (uint32_t i = 0; i < total_count; i++) {
+ loader_instance_heap_free(inst, new_phys_devs[i]);
+ }
+ loader_instance_heap_free(inst, new_phys_devs);
+ }
+ total_count = 0;
+ } else {
+ // Free everything that didn't carry over to the new array of
+ // physical devices
+ if (NULL != inst->phys_devs_tramp) {
+ for (uint32_t i = 0; i < inst->phys_dev_count_tramp; i++) {
+ bool found = false;
+ for (uint32_t j = 0; j < total_count; j++) {
+ if (inst->phys_devs_tramp[i] == new_phys_devs[j]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ loader_instance_heap_free(inst, inst->phys_devs_tramp[i]);
+ }
+ }
+ loader_instance_heap_free(inst, inst->phys_devs_tramp);
+ }
+
+ // Swap in the new physical device list
+ inst->phys_dev_count_tramp = total_count;
+ inst->phys_devs_tramp = new_phys_devs;
+ }
+
+ return res;
+}
+
+VkResult setupLoaderTermPhysDevs(struct loader_instance *inst) {
+ VkResult res = VK_SUCCESS;
+ struct loader_icd_term *icd_term;
+ struct loader_phys_dev_per_icd *icd_phys_dev_array = NULL;
+ struct loader_physical_device_term **new_phys_devs = NULL;
+
+ inst->total_gpu_count = 0;
+
+ // Allocate something to store the physical device characteristics
+ // that we read from each ICD.
+ icd_phys_dev_array =
+ (struct loader_phys_dev_per_icd *)loader_stack_alloc(sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count);
+ if (NULL == icd_phys_dev_array) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevs: Failed to allocate temporary "
+ "ICD Physical device info array of size %d",
+ inst->total_gpu_count);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memset(icd_phys_dev_array, 0, sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count);
+ icd_term = inst->icd_terms;
+
+ // For each ICD, query the number of physical devices, and then get an
+ // internal value for those physical devices.
+ for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) {
+ res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &icd_phys_dev_array[icd_idx].count, NULL);
+ if (VK_SUCCESS != res) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevs: Call to "
+ "ICD %d's \'vkEnumeratePhysicalDevices\' failed with"
+ " error 0x%08x",
+ icd_idx, res);
+ goto out;
+ }
+
+ icd_phys_dev_array[icd_idx].phys_devs =
+ (VkPhysicalDevice *)loader_stack_alloc(icd_phys_dev_array[icd_idx].count * sizeof(VkPhysicalDevice));
+ if (NULL == icd_phys_dev_array[icd_idx].phys_devs) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevs: Failed to allocate temporary "
+ "ICD Physical device array for ICD %d of size %d",
+ icd_idx, inst->total_gpu_count);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &(icd_phys_dev_array[icd_idx].count),
+ icd_phys_dev_array[icd_idx].phys_devs);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ inst->total_gpu_count += icd_phys_dev_array[icd_idx].count;
+ icd_phys_dev_array[icd_idx].this_icd_term = icd_term;
+ }
+
+ if (0 == inst->total_gpu_count) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevs: Failed to detect any valid"
+ " GPUs in the current config");
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ new_phys_devs = loader_instance_heap_alloc(inst, sizeof(struct loader_physical_device_term *) * inst->total_gpu_count,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_phys_devs) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevs: Failed to allocate new physical"
+ " device array of size %d",
+ inst->total_gpu_count);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memset(new_phys_devs, 0, sizeof(struct loader_physical_device_term *) * inst->total_gpu_count);
+
+ // Copy or create everything to fill the new array of physical devices
+ uint32_t idx = 0;
+ for (uint32_t icd_idx = 0; icd_idx < inst->total_icd_count; icd_idx++) {
+ for (uint32_t pd_idx = 0; pd_idx < icd_phys_dev_array[icd_idx].count; pd_idx++) {
+ // Check if this physical device is already in the old buffer
+ if (NULL != inst->phys_devs_term) {
+ for (uint32_t old_idx = 0; old_idx < inst->phys_dev_count_term; old_idx++) {
+ if (icd_phys_dev_array[icd_idx].phys_devs[pd_idx] == inst->phys_devs_term[old_idx]->phys_dev) {
+ new_phys_devs[idx] = inst->phys_devs_term[old_idx];
+ break;
+ }
+ }
+ }
+ // If this physical device isn't in the old buffer, then we
+ // need to create it.
+ if (NULL == new_phys_devs[idx]) {
+ new_phys_devs[idx] = loader_instance_heap_alloc(inst, sizeof(struct loader_physical_device_term),
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_phys_devs[idx]) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevs: Failed to allocate "
+ "physical device terminator object %d",
+ idx);
+ inst->total_gpu_count = idx;
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ loader_set_dispatch((void *)new_phys_devs[idx], inst->disp);
+ new_phys_devs[idx]->this_icd_term = icd_phys_dev_array[icd_idx].this_icd_term;
+ new_phys_devs[idx]->icd_index = (uint8_t)(icd_idx);
+ new_phys_devs[idx]->phys_dev = icd_phys_dev_array[icd_idx].phys_devs[pd_idx];
+ }
+ idx++;
+ }
+ }
+
+out:
+
+ if (VK_SUCCESS != res) {
+ if (NULL != new_phys_devs) {
+ // We've encountered an error, so we should free the new buffers.
+ for (uint32_t i = 0; i < inst->total_gpu_count; i++) {
+ loader_instance_heap_free(inst, new_phys_devs[i]);
+ }
+ loader_instance_heap_free(inst, new_phys_devs);
+ }
+ inst->total_gpu_count = 0;
+ } else {
+ // Free everything that didn't carry over to the new array of
+ // physical devices. Everything else will have been copied over
+ // to the new array.
+ if (NULL != inst->phys_devs_term) {
+ for (uint32_t cur_pd = 0; cur_pd < inst->phys_dev_count_term; cur_pd++) {
+ bool found = false;
+ for (uint32_t new_pd_idx = 0; new_pd_idx < inst->total_gpu_count; new_pd_idx++) {
+ if (inst->phys_devs_term[cur_pd] == new_phys_devs[new_pd_idx]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ loader_instance_heap_free(inst, inst->phys_devs_term[cur_pd]);
+ }
+ }
+ loader_instance_heap_free(inst, inst->phys_devs_term);
+ }
+
+ // Swap out old and new devices list
+ inst->phys_dev_count_term = inst->total_gpu_count;
+ inst->phys_devs_term = new_phys_devs;
+ }
+
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
+ VkPhysicalDevice *pPhysicalDevices) {
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ VkResult res = VK_SUCCESS;
+
+ // Always call the setup loader terminator physical devices because they may
+ // have changed at any point.
+ res = setupLoaderTermPhysDevs(inst);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
+ uint32_t copy_count = inst->total_gpu_count;
+ if (NULL != pPhysicalDevices) {
+ if (copy_count > *pPhysicalDeviceCount) {
+ copy_count = *pPhysicalDeviceCount;
+ res = VK_INCOMPLETE;
+ }
+
+ for (uint32_t i = 0; i < copy_count; i++) {
+ pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_term[i];
+ }
+ }
+
+ *pPhysicalDeviceCount = copy_count;
+
+out:
+
+ return res;
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties *pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL != icd_term->dispatch.GetPhysicalDeviceProperties) {
+ icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, pProperties);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
+ uint32_t *pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties *pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL != icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties) {
+ icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties(phys_dev_term->phys_dev, pQueueFamilyPropertyCount, pProperties);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties *pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL != icd_term->dispatch.GetPhysicalDeviceMemoryProperties) {
+ icd_term->dispatch.GetPhysicalDeviceMemoryProperties(phys_dev_term->phys_dev, pProperties);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures *pFeatures) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL != icd_term->dispatch.GetPhysicalDeviceFeatures) {
+ icd_term->dispatch.GetPhysicalDeviceFeatures(phys_dev_term->phys_dev, pFeatures);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
+ VkFormatProperties *pFormatInfo) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL != icd_term->dispatch.GetPhysicalDeviceFormatProperties) {
+ icd_term->dispatch.GetPhysicalDeviceFormatProperties(phys_dev_term->phys_dev, format, pFormatInfo);
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
+ VkImageType type, VkImageTiling tiling,
+ VkImageUsageFlags usage, VkImageCreateFlags flags,
+ VkImageFormatProperties *pImageFormatProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceImageFormatProperties) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "Encountered the vkEnumerateDeviceLayerProperties "
+ "terminator. This means a layer improperly continued.");
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(phys_dev_term->phys_dev, format, type, tiling, usage, flags,
+ pImageFormatProperties);
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
+ VkImageType type, VkSampleCountFlagBits samples,
+ VkImageUsageFlags usage, VkImageTiling tiling,
+ uint32_t *pNumProperties,
+ VkSparseImageFormatProperties *pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL != icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties) {
+ icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties(phys_dev_term->phys_dev, format, type, samples, usage,
+ tiling, pNumProperties, pProperties);
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
+ const char *pLayerName, uint32_t *pPropertyCount,
+ VkExtensionProperties *pProperties) {
+ struct loader_physical_device_term *phys_dev_term;
+
+ struct loader_layer_list implicit_layer_list = {0};
+ struct loader_extension_list all_exts = {0};
+ struct loader_extension_list icd_exts = {0};
+
+ // Any layer or trampoline wrapping should be removed at this point in time can just cast to the expected
+ // type for VkPhysicalDevice.
+ phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+
+ // if we got here with a non-empty pLayerName, look up the extensions
+ // from the json
+ if (pLayerName != NULL && strlen(pLayerName) > 0) {
+ uint32_t count;
+ uint32_t copy_size;
+ const struct loader_instance *inst = phys_dev_term->this_icd_term->this_instance;
+ struct loader_device_extension_list *dev_ext_list = NULL;
+ struct loader_device_extension_list local_ext_list;
+ memset(&local_ext_list, 0, sizeof(local_ext_list));
+ if (vk_string_validate(MaxLoaderStringLength, pLayerName) == VK_STRING_ERROR_NONE) {
+ for (uint32_t i = 0; i < inst->instance_layer_list.count; i++) {
+ struct loader_layer_properties *props = &inst->instance_layer_list.list[i];
+ if (strcmp(props->info.layerName, pLayerName) == 0) {
+ dev_ext_list = &props->device_extension_list;
+ }
+ }
+
+ count = (dev_ext_list == NULL) ? 0 : dev_ext_list->count;
+ if (pProperties == NULL) {
+ *pPropertyCount = count;
+ loader_destroy_generic_list(inst, (struct loader_generic_list *)&local_ext_list);
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return VK_SUCCESS;
+ }
+
+ copy_size = *pPropertyCount < count ? *pPropertyCount : count;
+ for (uint32_t i = 0; i < copy_size; i++) {
+ memcpy(&pProperties[i], &dev_ext_list->list[i].props, sizeof(VkExtensionProperties));
+ }
+ *pPropertyCount = copy_size;
+
+ loader_destroy_generic_list(inst, (struct loader_generic_list *)&local_ext_list);
+ if (copy_size < count) {
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return VK_INCOMPLETE;
+ }
+ } else {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "vkEnumerateDeviceExtensionProperties: pLayerName "
+ "is too long or is badly formed");
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ return VK_SUCCESS;
+ }
+
+ // This case is during the call down the instance chain with pLayerName == NULL
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ uint32_t icd_ext_count = *pPropertyCount;
+ VkResult res;
+
+ // Get the available device extensions
+ res = icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &icd_ext_count, pProperties);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+
+ if (!loaderInitLayerList(icd_term->this_instance, &implicit_layer_list)) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ loaderAddImplicitLayers(icd_term->this_instance, &implicit_layer_list, NULL, &icd_term->this_instance->instance_layer_list);
+ // We need to determine which implicit layers are active, and then add their extensions. This can't be cached as
+ // it depends on results of environment variables (which can change).
+ if (pProperties != NULL) {
+ // Initialize dev_extension list within the physicalDevice object
+ res = loader_init_device_extensions(icd_term->this_instance, phys_dev_term, icd_ext_count, pProperties, &icd_exts);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+
+ // We need to determine which implicit layers are active, and then add their extensions. This can't be cached as
+ // it depends on results of environment variables (which can change).
+ res = loader_add_to_ext_list(icd_term->this_instance, &all_exts, icd_exts.count, icd_exts.list);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+
+ loaderAddImplicitLayers(icd_term->this_instance, &implicit_layer_list, NULL, &icd_term->this_instance->instance_layer_list);
+
+ for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
+ for (uint32_t j = 0; j < implicit_layer_list.list[i].device_extension_list.count; j++) {
+ res = loader_add_to_ext_list(icd_term->this_instance, &all_exts, 1,
+ &implicit_layer_list.list[i].device_extension_list.list[j].props);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+ }
+ }
+ uint32_t capacity = *pPropertyCount;
+ VkExtensionProperties *props = pProperties;
+
+ for (uint32_t i = 0; i < all_exts.count && i < capacity; i++) {
+ props[i] = all_exts.list[i];
+ }
+
+ // Wasn't enough space for the extensions, we did partial copy now return VK_INCOMPLETE
+ if (capacity < all_exts.count) {
+ res = VK_INCOMPLETE;
+ } else {
+ *pPropertyCount = all_exts.count;
+ }
+ } else {
+ // Just return the count; need to add in the count of implicit layer extensions
+ // don't worry about duplicates being added in the count
+ *pPropertyCount = icd_ext_count;
+
+ for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
+ *pPropertyCount += implicit_layer_list.list[i].device_extension_list.count;
+ }
+ res = VK_SUCCESS;
+ }
+
+out:
+
+ if (NULL != implicit_layer_list.list) {
+ loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&implicit_layer_list);
+ }
+ if (NULL != all_exts.list) {
+ loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&all_exts);
+ }
+ if (NULL != icd_exts.list) {
+ loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts);
+ }
+
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
+ VkLayerProperties *pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "Encountered the vkEnumerateDeviceLayerProperties "
+ "terminator. This means a layer improperly continued.");
+ // Should never get here this call isn't dispatched down the chain
+ return VK_ERROR_INITIALIZATION_FAILED;
+}
+
+VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) {
+ VkStringErrorFlags result = VK_STRING_ERROR_NONE;
+ int num_char_bytes = 0;
+ int i, j;
+
+ if (utf8 == NULL) {
+ return VK_STRING_ERROR_NULL_PTR;
+ }
+
+ for (i = 0; i <= max_length; i++) {
+ if (utf8[i] == 0) {
+ break;
+ } else if (i == max_length) {
+ result |= VK_STRING_ERROR_LENGTH;
+ break;
+ } else if ((utf8[i] >= 0x20) && (utf8[i] < 0x7f)) {
+ num_char_bytes = 0;
+ } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) {
+ num_char_bytes = 1;
+ } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) {
+ num_char_bytes = 2;
+ } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) {
+ num_char_bytes = 3;
+ } else {
+ result = VK_STRING_ERROR_BAD_DATA;
+ }
+
+ // Validate the following num_char_bytes of data
+ for (j = 0; (j < num_char_bytes) && (i < max_length); j++) {
+ if (++i == max_length) {
+ result |= VK_STRING_ERROR_LENGTH;
+ break;
+ }
+ if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) {
+ result |= VK_STRING_ERROR_BAD_DATA;
+ }
+ }
+ }
+ return result;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+terminator_EnumerateInstanceVersion(const VkEnumerateInstanceVersionChain *chain, uint32_t* pApiVersion) {
+ // NOTE: The Vulkan WG doesn't want us checking pApiVersion for NULL, but instead
+ // prefers us crashing.
+ *pApiVersion = VK_MAKE_VERSION(loader_major_version, loader_minor_version, VK_HEADER_VERSION);
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+terminator_EnumerateInstanceExtensionProperties(const VkEnumerateInstanceExtensionPropertiesChain *chain, const char *pLayerName,
+ uint32_t *pPropertyCount, VkExtensionProperties *pProperties) {
+ struct loader_extension_list *global_ext_list = NULL;
+ struct loader_layer_list instance_layers;
+ struct loader_extension_list local_ext_list;
+ struct loader_icd_tramp_list icd_tramp_list;
+ uint32_t copy_size;
+ VkResult res = VK_SUCCESS;
+
+ // tls_instance = NULL;
+ memset(&local_ext_list, 0, sizeof(local_ext_list));
+ memset(&instance_layers, 0, sizeof(instance_layers));
+
+ // Get layer libraries if needed
+ if (pLayerName && strlen(pLayerName) != 0) {
+ if (vk_string_validate(MaxLoaderStringLength, pLayerName) != VK_STRING_ERROR_NONE) {
+ assert(VK_FALSE &&
+ "vkEnumerateInstanceExtensionProperties: "
+ "pLayerName is too long or is badly formed");
+ res = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+
+ loaderScanForLayers(NULL, &instance_layers);
+ for (uint32_t i = 0; i < instance_layers.count; i++) {
+ struct loader_layer_properties *props = &instance_layers.list[i];
+ if (strcmp(props->info.layerName, pLayerName) == 0) {
+ global_ext_list = &props->instance_extension_list;
+ break;
+ }
+ }
+ } else {
+ // Scan/discover all ICD libraries
+ memset(&icd_tramp_list, 0, sizeof(icd_tramp_list));
+ res = loader_icd_scan(NULL, &icd_tramp_list);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ // Get extensions from all ICD's, merge so no duplicates
+ res = loader_get_icd_loader_instance_extensions(NULL, &icd_tramp_list, &local_ext_list);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ loader_scanned_icd_clear(NULL, &icd_tramp_list);
+
+ // Append enabled implicit layers.
+ loaderScanForImplicitLayers(NULL, &instance_layers);
+ for (uint32_t i = 0; i < instance_layers.count; i++) {
+ if (!loaderImplicitLayerIsEnabled(NULL, &instance_layers.list[i])) {
+ continue;
+ }
+ struct loader_extension_list *ext_list = &instance_layers.list[i].instance_extension_list;
+ loader_add_to_ext_list(NULL, &local_ext_list, ext_list->count, ext_list->list);
+ }
+
+ global_ext_list = &local_ext_list;
+ }
+
+ if (global_ext_list == NULL) {
+ res = VK_ERROR_LAYER_NOT_PRESENT;
+ goto out;
+ }
+
+ if (pProperties == NULL) {
+ *pPropertyCount = global_ext_list->count;
+ goto out;
+ }
+
+ copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
+ for (uint32_t i = 0; i < copy_size; i++) {
+ memcpy(&pProperties[i], &global_ext_list->list[i], sizeof(VkExtensionProperties));
+ }
+ *pPropertyCount = copy_size;
+
+ if (copy_size < global_ext_list->count) {
+ res = VK_INCOMPLETE;
+ goto out;
+ }
+
+out:
+
+ loader_destroy_generic_list(NULL, (struct loader_generic_list *)&local_ext_list);
+ loaderDeleteLayerListAndProperties(NULL, &instance_layers);
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(const VkEnumerateInstanceLayerPropertiesChain *chain,
+ uint32_t *pPropertyCount,
+ VkLayerProperties *pProperties) {
+ VkResult result = VK_SUCCESS;
+ struct loader_layer_list instance_layer_list;
+ tls_instance = NULL;
+
+ LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
+
+ uint32_t copy_size;
+
+ // Get layer libraries
+ memset(&instance_layer_list, 0, sizeof(instance_layer_list));
+ loaderScanForLayers(NULL, &instance_layer_list);
+
+ if (pProperties == NULL) {
+ *pPropertyCount = instance_layer_list.count;
+ goto out;
+ }
+
+ copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
+ for (uint32_t i = 0; i < copy_size; i++) {
+ memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
+ }
+
+ *pPropertyCount = copy_size;
+
+ if (copy_size < instance_layer_list.count) {
+ result = VK_INCOMPLETE;
+ goto out;
+ }
+
+out:
+
+ loaderDeleteLayerListAndProperties(NULL, &instance_layer_list);
+ return result;
+}
+
+#if defined(_WIN32) && defined(LOADER_DYNAMIC_LIB)
+BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ loader_initialize();
+ break;
+ case DLL_PROCESS_DETACH:
+ if (NULL == reserved) {
+ loader_release();
+ }
+ break;
+ default:
+ // Do nothing
+ break;
+ }
+ return TRUE;
+}
+#elif !defined(_WIN32)
+__attribute__((constructor)) void loader_init_library() { loader_initialize(); }
+
+__attribute__((destructor)) void loader_free_library() { loader_release(); }
+#endif
+
+// ---- Vulkan Core 1.1 terminators
+
+VkResult setupLoaderTermPhysDevGroups(struct loader_instance *inst) {
+ VkResult res = VK_SUCCESS;
+ struct loader_icd_term *icd_term;
+ uint32_t total_count = 0;
+ uint32_t cur_icd_group_count = 0;
+ VkPhysicalDeviceGroupPropertiesKHR **new_phys_dev_groups = NULL;
+ VkPhysicalDeviceGroupPropertiesKHR *local_phys_dev_groups = NULL;
+ PFN_vkEnumeratePhysicalDeviceGroups fpEnumeratePhysicalDeviceGroups = NULL;
+
+ if (0 == inst->phys_dev_count_term) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevGroups: Loader failed to setup physical "
+ "device terminator info before calling \'EnumeratePhysicalDeviceGroups\'.");
+ assert(false);
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ // For each ICD, query the number of physical device groups, and then get an
+ // internal value for those physical devices.
+ icd_term = inst->icd_terms;
+ for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) {
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ if (inst->enabled_known_extensions.khr_device_group_creation) {
+ fpEnumeratePhysicalDeviceGroups = icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHR;
+ } else {
+ fpEnumeratePhysicalDeviceGroups = icd_term->dispatch.EnumeratePhysicalDeviceGroups;
+ }
+
+ cur_icd_group_count = 0;
+ if (NULL == fpEnumeratePhysicalDeviceGroups) {
+ // Treat each ICD's GPU as it's own group if the extension isn't supported
+ res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &cur_icd_group_count, NULL);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevGroups: Failed during dispatch call of "
+ "\'EnumeratePhysicalDevices\' to ICD %d to get plain phys dev count.",
+ icd_idx);
+ goto out;
+ }
+ } else {
+ // Query the actual group info
+ res = fpEnumeratePhysicalDeviceGroups(icd_term->instance, &cur_icd_group_count, NULL);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevGroups: Failed during dispatch call of "
+ "\'EnumeratePhysicalDeviceGroups\' to ICD %d to get count.",
+ icd_idx);
+ goto out;
+ }
+ }
+ total_count += cur_icd_group_count;
+ }
+
+ // Create an array for the new physical device groups, which will be stored
+ // in the instance for the Terminator code.
+ new_phys_dev_groups = (VkPhysicalDeviceGroupProperties **)loader_instance_heap_alloc(
+ inst, total_count * sizeof(VkPhysicalDeviceGroupProperties *), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_phys_dev_groups) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevGroups: Failed to allocate new physical device"
+ " group array of size %d",
+ total_count);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memset(new_phys_dev_groups, 0, total_count * sizeof(VkPhysicalDeviceGroupProperties *));
+
+ // Create a temporary array (on the stack) to keep track of the
+ // returned VkPhysicalDevice values.
+ local_phys_dev_groups = loader_stack_alloc(sizeof(VkPhysicalDeviceGroupProperties) * total_count);
+ if (NULL == local_phys_dev_groups) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevGroups: Failed to allocate local "
+ "physical device group array of size %d",
+ total_count);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ // Initialize the memory to something valid
+ memset(local_phys_dev_groups, 0, sizeof(VkPhysicalDeviceGroupProperties) * total_count);
+ for (uint32_t group = 0; group < total_count; group++) {
+ local_phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR;
+ local_phys_dev_groups[group].pNext = NULL;
+ local_phys_dev_groups[group].subsetAllocation = false;
+ }
+
+ cur_icd_group_count = 0;
+ icd_term = inst->icd_terms;
+ for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) {
+ uint32_t count_this_time = total_count - cur_icd_group_count;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ if (inst->enabled_known_extensions.khr_device_group_creation) {
+ fpEnumeratePhysicalDeviceGroups = icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHR;
+ } else {
+ fpEnumeratePhysicalDeviceGroups = icd_term->dispatch.EnumeratePhysicalDeviceGroups;
+ }
+
+ if (NULL == fpEnumeratePhysicalDeviceGroups) {
+ VkPhysicalDevice* phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * count_this_time);
+ if (NULL == phys_dev_array) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevGroups: Failed to allocate local "
+ "physical device array of size %d",
+ count_this_time);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &count_this_time, phys_dev_array);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevGroups: Failed during dispatch call of "
+ "\'EnumeratePhysicalDevices\' to ICD %d to get plain phys dev count.",
+ icd_idx);
+ goto out;
+ }
+
+ // Add each GPU as it's own group
+ for (uint32_t indiv_gpu = 0; indiv_gpu < count_this_time; indiv_gpu++) {
+ local_phys_dev_groups[indiv_gpu + cur_icd_group_count].physicalDeviceCount = 1;
+ local_phys_dev_groups[indiv_gpu + cur_icd_group_count].physicalDevices[0] = phys_dev_array[indiv_gpu];
+ }
+
+ } else {
+ res = fpEnumeratePhysicalDeviceGroups(icd_term->instance, &count_this_time, &local_phys_dev_groups[cur_icd_group_count]);
+ if (VK_SUCCESS != res) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevGroups: Failed during dispatch call of "
+ "\'EnumeratePhysicalDeviceGroups\' to ICD %d to get content.",
+ icd_idx);
+ goto out;
+ }
+ }
+
+ cur_icd_group_count += count_this_time;
+ }
+
+ // Replace all the physical device IDs with the proper loader values
+ for (uint32_t group = 0; group < total_count; group++) {
+ for (uint32_t group_gpu = 0; group_gpu < local_phys_dev_groups[group].physicalDeviceCount; group_gpu++) {
+ bool found = false;
+ for (uint32_t term_gpu = 0; term_gpu < inst->phys_dev_count_term; term_gpu++) {
+ if (local_phys_dev_groups[group].physicalDevices[group_gpu] == inst->phys_devs_term[term_gpu]->phys_dev) {
+ local_phys_dev_groups[group].physicalDevices[group_gpu] = (VkPhysicalDevice)inst->phys_devs_term[term_gpu];
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevGroups: Failed to find GPU %d in group %d"
+ " returned by \'EnumeratePhysicalDeviceGroups\' in list returned"
+ " by \'EnumeratePhysicalDevices\'", group_gpu, group);
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+ }
+ }
+
+ // Copy or create everything to fill the new array of physical device groups
+ for (uint32_t new_idx = 0; new_idx < total_count; new_idx++) {
+ // Check if this physical device group with the same contents is already in the old buffer
+ for (uint32_t old_idx = 0; old_idx < inst->phys_dev_group_count_term; old_idx++) {
+ if (local_phys_dev_groups[new_idx].physicalDeviceCount == inst->phys_dev_groups_term[old_idx]->physicalDeviceCount) {
+ bool found_all_gpus = true;
+ for (uint32_t old_gpu = 0; old_gpu < inst->phys_dev_groups_term[old_idx]->physicalDeviceCount; old_gpu++) {
+ bool found_gpu = false;
+ for (uint32_t new_gpu = 0; new_gpu < local_phys_dev_groups[new_idx].physicalDeviceCount; new_gpu++) {
+ if (local_phys_dev_groups[new_idx].physicalDevices[new_gpu] == inst->phys_dev_groups_term[old_idx]->physicalDevices[old_gpu]) {
+ found_gpu = true;
+ break;
+ }
+ }
+
+ if (!found_gpu) {
+ found_all_gpus = false;
+ break;
+ }
+ }
+ if (!found_all_gpus) {
+ continue;
+ } else {
+ new_phys_dev_groups[new_idx] = inst->phys_dev_groups_term[old_idx];
+ break;
+ }
+ }
+ }
+
+ // If this physical device group isn't in the old buffer, create it
+ if (NULL == new_phys_dev_groups[new_idx]) {
+ new_phys_dev_groups[new_idx] = (VkPhysicalDeviceGroupPropertiesKHR *)loader_instance_heap_alloc(
+ inst, sizeof(VkPhysicalDeviceGroupPropertiesKHR), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_phys_dev_groups[new_idx]) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTermPhysDevGroups: Failed to allocate "
+ "physical device group Terminator object %d",
+ new_idx);
+ total_count = new_idx;
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memcpy(new_phys_dev_groups[new_idx], &local_phys_dev_groups[new_idx],
+ sizeof(VkPhysicalDeviceGroupPropertiesKHR));
+ }
+ }
+
+out:
+
+ if (VK_SUCCESS != res) {
+ if (NULL != new_phys_dev_groups) {
+ for (uint32_t i = 0; i < total_count; i++) {
+ loader_instance_heap_free(inst, new_phys_dev_groups[i]);
+ }
+ loader_instance_heap_free(inst, new_phys_dev_groups);
+ }
+ total_count = 0;
+ } else {
+ // Free everything that didn't carry over to the new array of
+ // physical device groups
+ if (NULL != inst->phys_dev_groups_term) {
+ for (uint32_t i = 0; i < inst->phys_dev_group_count_term; i++) {
+ bool found = false;
+ for (uint32_t j = 0; j < total_count; j++) {
+ if (inst->phys_dev_groups_term[i] == new_phys_dev_groups[j]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ loader_instance_heap_free(inst, inst->phys_dev_groups_term[i]);
+ }
+ }
+ loader_instance_heap_free(inst, inst->phys_dev_groups_term);
+ }
+
+ // Swap in the new physical device group list
+ inst->phys_dev_group_count_term = total_count;
+ inst->phys_dev_groups_term = new_phys_dev_groups;
+ }
+
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups(
+ VkInstance instance, uint32_t *pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties) {
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ VkResult res = VK_SUCCESS;
+
+ // Always call the setup loader terminator physical device groups because they may
+ // have changed at any point.
+ res = setupLoaderTermPhysDevGroups(inst);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
+ uint32_t copy_count = inst->phys_dev_group_count_term;
+ if (NULL != pPhysicalDeviceGroupProperties) {
+ if (copy_count > *pPhysicalDeviceGroupCount) {
+ copy_count = *pPhysicalDeviceGroupCount;
+ res = VK_INCOMPLETE;
+ }
+
+ for (uint32_t i = 0; i < copy_count; i++) {
+ memcpy(&pPhysicalDeviceGroupProperties[i], inst->phys_dev_groups_term[i],
+ sizeof(VkPhysicalDeviceGroupPropertiesKHR));
+ }
+ }
+
+ *pPhysicalDeviceGroupCount = copy_count;
+
+out:
+
+ return res;
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures2 *pFeatures) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ PFN_vkGetPhysicalDeviceFeatures2 fpGetPhysicalDeviceFeatures2 = NULL;
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ fpGetPhysicalDeviceFeatures2 = icd_term->dispatch.GetPhysicalDeviceFeatures2KHR;
+ } else {
+ fpGetPhysicalDeviceFeatures2 = icd_term->dispatch.GetPhysicalDeviceFeatures2;
+ }
+
+ if (fpGetPhysicalDeviceFeatures2 != NULL || !inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ // Pass the call to the driver
+ fpGetPhysicalDeviceFeatures2(phys_dev_term->phys_dev, pFeatures);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceFeatures2: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceFeatures",
+ icd_term->scanned_icd->lib_name);
+
+ // Write to the VkPhysicalDeviceFeatures2 struct
+ icd_term->dispatch.GetPhysicalDeviceFeatures(phys_dev_term->phys_dev, &pFeatures->features);
+
+ const VkBaseInStructure *pNext = pFeatures->pNext;
+ while (pNext != NULL) {
+ switch (pNext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
+ // Skip the check if VK_KHR_multiview is enabled because it's a device extension
+ // Write to the VkPhysicalDeviceMultiviewFeaturesKHR struct
+ VkPhysicalDeviceMultiviewFeaturesKHR *multiview_features = (VkPhysicalDeviceMultiviewFeaturesKHR *)pNext;
+ multiview_features->multiview = VK_FALSE;
+ multiview_features->multiviewGeometryShader = VK_FALSE;
+ multiview_features->multiviewTessellationShader = VK_FALSE;
+
+ pNext = multiview_features->pNext;
+ break;
+ }
+ default: {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceFeatures2: Emulation found unrecognized structure type in pFeatures->pNext - "
+ "this struct will be ignored");
+
+ pNext = pNext->pNext;
+ break;
+ }
+ }
+ }
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2 *pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ PFN_vkGetPhysicalDeviceProperties2 fpGetPhysicalDeviceProperties2 = NULL;
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ fpGetPhysicalDeviceProperties2 = icd_term->dispatch.GetPhysicalDeviceProperties2KHR;
+ } else {
+ fpGetPhysicalDeviceProperties2 = icd_term->dispatch.GetPhysicalDeviceProperties2;
+ }
+
+ if (fpGetPhysicalDeviceProperties2 != NULL || !inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ // Pass the call to the driver
+ fpGetPhysicalDeviceProperties2(phys_dev_term->phys_dev, pProperties);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceProperties2: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceProperties",
+ icd_term->scanned_icd->lib_name);
+
+ // Write to the VkPhysicalDeviceProperties2 struct
+ icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, &pProperties->properties);
+
+ const VkBaseInStructure *pNext = pProperties->pNext;
+ while (pNext != NULL) {
+ switch (pNext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
+ VkPhysicalDeviceIDPropertiesKHR *id_properties = (VkPhysicalDeviceIDPropertiesKHR *)pNext;
+
+ // Verify that "VK_KHR_external_memory_capabilities" is enabled
+ if (icd_term->this_instance->enabled_known_extensions.khr_external_memory_capabilities) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceProperties2: Emulation cannot generate unique IDs for struct "
+ "VkPhysicalDeviceIDProperties - setting IDs to zero instead");
+
+ // Write to the VkPhysicalDeviceIDPropertiesKHR struct
+ memset(id_properties->deviceUUID, 0, VK_UUID_SIZE);
+ memset(id_properties->driverUUID, 0, VK_UUID_SIZE);
+ id_properties->deviceLUIDValid = VK_FALSE;
+ }
+
+ pNext = id_properties->pNext;
+ break;
+ }
+ default: {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceProperties2KHR: Emulation found unrecognized structure type in "
+ "pProperties->pNext - this struct will be ignored");
+
+ pNext = pNext->pNext;
+ break;
+ }
+ }
+ }
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format,
+ VkFormatProperties2 *pFormatProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ PFN_vkGetPhysicalDeviceFormatProperties2 fpGetPhysicalDeviceFormatProperties2 = NULL;
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ fpGetPhysicalDeviceFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceFormatProperties2KHR;
+ } else {
+ fpGetPhysicalDeviceFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceFormatProperties2;
+ }
+
+ if (fpGetPhysicalDeviceFormatProperties2 != NULL || !inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ // Pass the call to the driver
+ fpGetPhysicalDeviceFormatProperties2(phys_dev_term->phys_dev, format, pFormatProperties);
+ } else {
+ // Emulate the call
+ loader_log(
+ icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceFormatProperties2: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceFormatProperties",
+ icd_term->scanned_icd->lib_name);
+
+ // Write to the VkFormatProperties2 struct
+ icd_term->dispatch.GetPhysicalDeviceFormatProperties(phys_dev_term->phys_dev, format, &pFormatProperties->formatProperties);
+
+ if (pFormatProperties->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceFormatProperties2: Emulation found unrecognized structure type in "
+ "pFormatProperties->pNext - this struct will be ignored");
+ }
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties2(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
+ VkImageFormatProperties2KHR *pImageFormatProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ PFN_vkGetPhysicalDeviceImageFormatProperties2 fpGetPhysicalDeviceImageFormatProperties2 = NULL;
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ fpGetPhysicalDeviceImageFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceImageFormatProperties2KHR;
+ } else {
+ fpGetPhysicalDeviceImageFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceImageFormatProperties2;
+ }
+
+ if (fpGetPhysicalDeviceImageFormatProperties2 != NULL || !inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ // Pass the call to the driver
+ return fpGetPhysicalDeviceImageFormatProperties2(phys_dev_term->phys_dev, pImageFormatInfo, pImageFormatProperties);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceImageFormatProperties2: Emulating call in ICD \"%s\" using "
+ "vkGetPhysicalDeviceImageFormatProperties",
+ icd_term->scanned_icd->lib_name);
+
+ // If there is more info in either pNext, then this is unsupported
+ if (pImageFormatInfo->pNext != NULL || pImageFormatProperties->pNext != NULL) {
+ return VK_ERROR_FORMAT_NOT_SUPPORTED;
+ }
+
+ // Write to the VkImageFormatProperties2KHR struct
+ return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(
+ phys_dev_term->phys_dev, pImageFormatInfo->format, pImageFormatInfo->type, pImageFormatInfo->tiling,
+ pImageFormatInfo->usage, pImageFormatInfo->flags, &pImageFormatProperties->imageFormatProperties);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties2(
+ VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2 fpGetPhysicalDeviceQueueFamilyProperties2 = NULL;
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ fpGetPhysicalDeviceQueueFamilyProperties2 = icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties2KHR;
+ } else {
+ fpGetPhysicalDeviceQueueFamilyProperties2 = icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties2;
+ }
+
+ if (fpGetPhysicalDeviceQueueFamilyProperties2 != NULL || !inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ // Pass the call to the driver
+ fpGetPhysicalDeviceQueueFamilyProperties2(phys_dev_term->phys_dev, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceQueueFamilyProperties2: Emulating call in ICD \"%s\" using "
+ "vkGetPhysicalDeviceQueueFamilyProperties",
+ icd_term->scanned_icd->lib_name);
+
+ if (pQueueFamilyProperties == NULL || *pQueueFamilyPropertyCount == 0) {
+ // Write to pQueueFamilyPropertyCount
+ icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties(phys_dev_term->phys_dev, pQueueFamilyPropertyCount, NULL);
+ } else {
+ // Allocate a temporary array for the output of the old function
+ VkQueueFamilyProperties *properties = loader_stack_alloc(*pQueueFamilyPropertyCount * sizeof(VkQueueFamilyProperties));
+ if (properties == NULL) {
+ *pQueueFamilyPropertyCount = 0;
+ loader_log(
+ icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "vkGetPhysicalDeviceQueueFamilyProperties2: Out of memory - Failed to allocate array for loader emulation.");
+ return;
+ }
+
+ icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties(phys_dev_term->phys_dev, pQueueFamilyPropertyCount,
+ properties);
+ for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; ++i) {
+ // Write to the VkQueueFamilyProperties2KHR struct
+ memcpy(&pQueueFamilyProperties[i].queueFamilyProperties, &properties[i], sizeof(VkQueueFamilyProperties));
+
+ if (pQueueFamilyProperties[i].pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceQueueFamilyProperties2: Emulation found unrecognized structure type in "
+ "pQueueFamilyProperties[%d].pNext - this struct will be ignored",
+ i);
+ }
+ }
+ }
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties2(
+ VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2 *pMemoryProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ PFN_vkGetPhysicalDeviceMemoryProperties2 fpGetPhysicalDeviceMemoryProperties2 = NULL;
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ fpGetPhysicalDeviceMemoryProperties2 = icd_term->dispatch.GetPhysicalDeviceMemoryProperties2KHR;
+ } else {
+ fpGetPhysicalDeviceMemoryProperties2 = icd_term->dispatch.GetPhysicalDeviceMemoryProperties2;
+ }
+
+ if (fpGetPhysicalDeviceMemoryProperties2 != NULL || !inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ // Pass the call to the driver
+ fpGetPhysicalDeviceMemoryProperties2(phys_dev_term->phys_dev, pMemoryProperties);
+ } else {
+ // Emulate the call
+ loader_log(
+ icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceMemoryProperties2: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceMemoryProperties",
+ icd_term->scanned_icd->lib_name);
+
+ // Write to the VkPhysicalDeviceMemoryProperties2 struct
+ icd_term->dispatch.GetPhysicalDeviceMemoryProperties(phys_dev_term->phys_dev, &pMemoryProperties->memoryProperties);
+
+ if (pMemoryProperties->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceMemoryProperties2: Emulation found unrecognized structure type in "
+ "pMemoryProperties->pNext - this struct will be ignored");
+ }
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperties2(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR *pFormatInfo, uint32_t *pPropertyCount,
+ VkSparseImageFormatProperties2KHR *pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 fpGetPhysicalDeviceSparseImageFormatProperties2 = NULL;
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ fpGetPhysicalDeviceSparseImageFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties2KHR;
+ } else {
+ fpGetPhysicalDeviceSparseImageFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties2;
+ }
+
+ if (fpGetPhysicalDeviceSparseImageFormatProperties2 != NULL || !inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ // Pass the call to the driver
+ fpGetPhysicalDeviceSparseImageFormatProperties2(phys_dev_term->phys_dev, pFormatInfo, pPropertyCount, pProperties);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSparseImageFormatProperties2: Emulating call in ICD \"%s\" using "
+ "vkGetPhysicalDeviceSparseImageFormatProperties",
+ icd_term->scanned_icd->lib_name);
+
+ if (pFormatInfo->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSparseImageFormatProperties2: Emulation found unrecognized structure type in "
+ "pFormatInfo->pNext - this struct will be ignored");
+ }
+
+ if (pProperties == NULL || *pPropertyCount == 0) {
+ // Write to pPropertyCount
+ icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties(
+ phys_dev_term->phys_dev, pFormatInfo->format, pFormatInfo->type, pFormatInfo->samples, pFormatInfo->usage,
+ pFormatInfo->tiling, pPropertyCount, NULL);
+ } else {
+ // Allocate a temporary array for the output of the old function
+ VkSparseImageFormatProperties *properties =
+ loader_stack_alloc(*pPropertyCount * sizeof(VkSparseImageMemoryRequirements));
+ if (properties == NULL) {
+ *pPropertyCount = 0;
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSparseImageFormatProperties2: Out of memory - Failed to allocate array for "
+ "loader emulation.");
+ return;
+ }
+
+ icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties(
+ phys_dev_term->phys_dev, pFormatInfo->format, pFormatInfo->type, pFormatInfo->samples, pFormatInfo->usage,
+ pFormatInfo->tiling, pPropertyCount, properties);
+ for (uint32_t i = 0; i < *pPropertyCount; ++i) {
+ // Write to the VkSparseImageFormatProperties2KHR struct
+ memcpy(&pProperties[i].properties, &properties[i], sizeof(VkSparseImageFormatProperties));
+
+ if (pProperties[i].pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceSparseImageFormatProperties2: Emulation found unrecognized structure type in "
+ "pProperties[%d].pNext - this struct will be ignored",
+ i);
+ }
+ }
+ }
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalBufferProperties(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
+ VkExternalBufferProperties *pExternalBufferProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ PFN_vkGetPhysicalDeviceExternalBufferProperties fpGetPhysicalDeviceExternalBufferProperties = NULL;
+ if (inst != NULL && inst->enabled_known_extensions.khr_external_memory_capabilities) {
+ fpGetPhysicalDeviceExternalBufferProperties = icd_term->dispatch.GetPhysicalDeviceExternalBufferPropertiesKHR;
+ } else {
+ fpGetPhysicalDeviceExternalBufferProperties = icd_term->dispatch.GetPhysicalDeviceExternalBufferProperties;
+ }
+
+ if (fpGetPhysicalDeviceExternalBufferProperties || !inst->enabled_known_extensions.khr_external_memory_capabilities) {
+ // Pass the call to the driver
+ fpGetPhysicalDeviceExternalBufferProperties(phys_dev_term->phys_dev, pExternalBufferInfo, pExternalBufferProperties);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceExternalBufferProperties: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
+
+ if (pExternalBufferInfo->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceExternalBufferProperties: Emulation found unrecognized structure type in "
+ "pExternalBufferInfo->pNext - this struct will be ignored");
+ }
+
+ // Fill in everything being unsupported
+ memset(&pExternalBufferProperties->externalMemoryProperties, 0, sizeof(VkExternalMemoryPropertiesKHR));
+
+ if (pExternalBufferProperties->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceExternalBufferProperties: Emulation found unrecognized structure type in "
+ "pExternalBufferProperties->pNext - this struct will be ignored");
+ }
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalSemaphoreProperties(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo,
+ VkExternalSemaphoreProperties *pExternalSemaphoreProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ PFN_vkGetPhysicalDeviceExternalSemaphoreProperties fpGetPhysicalDeviceExternalSemaphoreProperties = NULL;
+ if (inst != NULL && inst->enabled_known_extensions.khr_external_semaphore_capabilities) {
+ fpGetPhysicalDeviceExternalSemaphoreProperties = icd_term->dispatch.GetPhysicalDeviceExternalSemaphorePropertiesKHR;
+ } else {
+ fpGetPhysicalDeviceExternalSemaphoreProperties = icd_term->dispatch.GetPhysicalDeviceExternalSemaphoreProperties;
+ }
+
+ if (fpGetPhysicalDeviceExternalSemaphoreProperties != NULL || !inst->enabled_known_extensions.khr_external_semaphore_capabilities) {
+ // Pass the call to the driver
+ fpGetPhysicalDeviceExternalSemaphoreProperties(phys_dev_term->phys_dev, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceExternalSemaphoreProperties: Emulating call in ICD \"%s\"",
+ icd_term->scanned_icd->lib_name);
+
+ if (pExternalSemaphoreInfo->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceExternalSemaphoreProperties: Emulation found unrecognized structure type in "
+ "pExternalSemaphoreInfo->pNext - this struct will be ignored");
+ }
+
+ // Fill in everything being unsupported
+ pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
+ pExternalSemaphoreProperties->compatibleHandleTypes = 0;
+ pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
+
+ if (pExternalSemaphoreProperties->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceExternalSemaphoreProperties: Emulation found unrecognized structure type in "
+ "pExternalSemaphoreProperties->pNext - this struct will be ignored");
+ }
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalFenceProperties(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
+ VkExternalFenceProperties *pExternalFenceProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ const struct loader_instance *inst = icd_term->this_instance;
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ PFN_vkGetPhysicalDeviceExternalFenceProperties fpGetPhysicalDeviceExternalFenceProperties = NULL;
+ if (inst != NULL && inst->enabled_known_extensions.khr_external_fence_capabilities) {
+ fpGetPhysicalDeviceExternalFenceProperties = icd_term->dispatch.GetPhysicalDeviceExternalFencePropertiesKHR;
+ } else {
+ fpGetPhysicalDeviceExternalFenceProperties = icd_term->dispatch.GetPhysicalDeviceExternalFenceProperties;
+ }
+
+ if (fpGetPhysicalDeviceExternalFenceProperties != NULL || !inst->enabled_known_extensions.khr_external_fence_capabilities) {
+ // Pass the call to the driver
+ fpGetPhysicalDeviceExternalFenceProperties(phys_dev_term->phys_dev, pExternalFenceInfo, pExternalFenceProperties);
+ } else {
+ // Emulate the call
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceExternalFenceProperties: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
+
+ if (pExternalFenceInfo->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceExternalFenceProperties: Emulation found unrecognized structure type in "
+ "pExternalFenceInfo->pNext - this struct will be ignored");
+ }
+
+ // Fill in everything being unsupported
+ pExternalFenceProperties->exportFromImportedHandleTypes = 0;
+ pExternalFenceProperties->compatibleHandleTypes = 0;
+ pExternalFenceProperties->externalFenceFeatures = 0;
+
+ if (pExternalFenceProperties->pNext != NULL) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "vkGetPhysicalDeviceExternalFenceProperties: Emulation found unrecognized structure type in "
+ "pExternalFenceProperties->pNext - this struct will be ignored");
+ }
+ }
+}
diff --git a/thirdparty/vulkan/loader/loader.h b/thirdparty/vulkan/loader/loader.h
new file mode 100644
index 0000000000..56745a968d
--- /dev/null
+++ b/thirdparty/vulkan/loader/loader.h
@@ -0,0 +1,533 @@
+/*
+ *
+ * Copyright (c) 2014-2019 The Khronos Group Inc.
+ * Copyright (c) 2014-2019 Valve Corporation
+ * Copyright (c) 2014-2019 LunarG, Inc.
+ * Copyright (C) 2015 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Chia-I Wu <olvaffe@gmail.com>
+ * Author: Chia-I Wu <olv@lunarg.com>
+ * Author: Mark Lobodzinski <mark@LunarG.com>
+ * Author: Lenny Komow <lenny@lunarg.com>
+ *
+ */
+
+#ifndef LOADER_H
+#define LOADER_H
+
+#include <vulkan/vulkan.h>
+#include "vk_loader_platform.h"
+#include "vk_loader_layer.h"
+#include <vulkan/vk_layer.h>
+#include <vulkan/vk_icd.h>
+#include <assert.h>
+#include "vk_layer_dispatch_table.h"
+#include "vk_loader_extensions.h"
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define LOADER_EXPORT __attribute__((visibility("default")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
+#define LOADER_EXPORT __attribute__((visibility("default")))
+#else
+#define LOADER_EXPORT
+#endif
+
+// A debug option to disable allocators at compile time to investigate future issues.
+#define DEBUG_DISABLE_APP_ALLOCATORS 0
+
+#define MAX_STRING_SIZE 1024
+
+// This is defined in vk_layer.h, but if there's problems we need to create the define
+// here.
+#ifndef MAX_NUM_UNKNOWN_EXTS
+#define MAX_NUM_UNKNOWN_EXTS 250
+#endif
+
+enum layer_type_flags {
+ VK_LAYER_TYPE_FLAG_INSTANCE_LAYER = 0x1, // If not set, indicates Device layer
+ VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER = 0x2, // If not set, indicates Implicit layer
+ VK_LAYER_TYPE_FLAG_META_LAYER = 0x4, // If not set, indicates standard layer
+};
+
+typedef enum VkStringErrorFlagBits {
+ VK_STRING_ERROR_NONE = 0x00000000,
+ VK_STRING_ERROR_LENGTH = 0x00000001,
+ VK_STRING_ERROR_BAD_DATA = 0x00000002,
+ VK_STRING_ERROR_NULL_PTR = 0x00000004,
+} VkStringErrorFlagBits;
+typedef VkFlags VkStringErrorFlags;
+
+static const int MaxLoaderStringLength = 256;
+static const char UTF8_ONE_BYTE_CODE = 0xC0;
+static const char UTF8_ONE_BYTE_MASK = 0xE0;
+static const char UTF8_TWO_BYTE_CODE = 0xE0;
+static const char UTF8_TWO_BYTE_MASK = 0xF0;
+static const char UTF8_THREE_BYTE_CODE = 0xF0;
+static const char UTF8_THREE_BYTE_MASK = 0xF8;
+static const char UTF8_DATA_BYTE_CODE = 0x80;
+static const char UTF8_DATA_BYTE_MASK = 0xC0;
+
+// form of all dynamic lists/arrays
+// only the list element should be changed
+struct loader_generic_list {
+ size_t capacity;
+ uint32_t count;
+ void *list;
+};
+
+struct loader_extension_list {
+ size_t capacity;
+ uint32_t count;
+ VkExtensionProperties *list;
+};
+
+struct loader_dev_ext_props {
+ VkExtensionProperties props;
+ uint32_t entrypoint_count;
+ char **entrypoints;
+};
+
+struct loader_device_extension_list {
+ size_t capacity;
+ uint32_t count;
+ struct loader_dev_ext_props *list;
+};
+
+struct loader_name_value {
+ char name[MAX_STRING_SIZE];
+ char value[MAX_STRING_SIZE];
+};
+
+struct loader_layer_functions {
+ char str_gipa[MAX_STRING_SIZE];
+ char str_gdpa[MAX_STRING_SIZE];
+ char str_negotiate_interface[MAX_STRING_SIZE];
+ PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_layer_interface;
+ PFN_vkGetInstanceProcAddr get_instance_proc_addr;
+ PFN_vkGetDeviceProcAddr get_device_proc_addr;
+ PFN_GetPhysicalDeviceProcAddr get_physical_device_proc_addr;
+};
+
+struct loader_override_expiration {
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+};
+
+struct loader_layer_properties {
+ VkLayerProperties info;
+ enum layer_type_flags type_flags;
+ uint32_t interface_version; // PFN_vkNegotiateLoaderLayerInterfaceVersion
+ char lib_name[MAX_STRING_SIZE];
+ loader_platform_dl_handle lib_handle;
+ struct loader_layer_functions functions;
+ struct loader_extension_list instance_extension_list;
+ struct loader_device_extension_list device_extension_list;
+ struct loader_name_value disable_env_var;
+ struct loader_name_value enable_env_var;
+ uint32_t num_component_layers;
+ char (*component_layer_names)[MAX_STRING_SIZE];
+ struct {
+ char enumerate_instance_extension_properties[MAX_STRING_SIZE];
+ char enumerate_instance_layer_properties[MAX_STRING_SIZE];
+ char enumerate_instance_version[MAX_STRING_SIZE];
+ } pre_instance_functions;
+ uint32_t num_override_paths;
+ char (*override_paths)[MAX_STRING_SIZE];
+ bool is_override;
+ bool has_expiration;
+ struct loader_override_expiration expiration;
+ bool keep;
+ uint32_t num_blacklist_layers;
+ char (*blacklist_layer_names)[MAX_STRING_SIZE];
+};
+
+struct loader_layer_list {
+ size_t capacity;
+ uint32_t count;
+ struct loader_layer_properties *list;
+};
+
+struct loader_dispatch_hash_list {
+ size_t capacity;
+ uint32_t count;
+ uint32_t *index; // index into the dev_ext dispatch table
+};
+
+// loader_dispatch_hash_entry and loader_dev_ext_dispatch_table.dev_ext have
+// one to one correspondence; one loader_dispatch_hash_entry for one dev_ext
+// dispatch entry.
+// Also have a one to one correspondence with functions in dev_ext_trampoline.c
+struct loader_dispatch_hash_entry {
+ char *func_name;
+ struct loader_dispatch_hash_list list; // to handle hashing collisions
+};
+
+typedef VkResult(VKAPI_PTR *PFN_vkDevExt)(VkDevice device);
+struct loader_dev_ext_dispatch_table {
+ PFN_vkDevExt dev_ext[MAX_NUM_UNKNOWN_EXTS];
+};
+
+struct loader_dev_dispatch_table {
+ VkLayerDispatchTable core_dispatch;
+ struct loader_dev_ext_dispatch_table ext_dispatch;
+};
+
+// per CreateDevice structure
+struct loader_device {
+ struct loader_dev_dispatch_table loader_dispatch;
+ VkDevice chain_device; // device object from the dispatch chain
+ VkDevice icd_device; // device object from the icd
+ struct loader_physical_device_term *phys_dev_term;
+
+ // List of activated layers.
+ // app_ is the version based on exactly what the application asked for.
+ // This is what must be returned to the application on Enumerate calls.
+ // expanded_ is the version based on expanding meta-layers into their
+ // individual component layers. This is what is used internally.
+ struct loader_layer_list app_activated_layer_list;
+ struct loader_layer_list expanded_activated_layer_list;
+
+ VkAllocationCallbacks alloc_callbacks;
+
+ // List of activated device extensions that have terminators implemented in the loader
+ struct {
+ bool khr_swapchain_enabled;
+ bool khr_display_swapchain_enabled;
+ bool khr_device_group_enabled;
+ bool ext_debug_marker_enabled;
+ bool ext_debug_utils_enabled;
+ bool ext_full_screen_exclusive_enabled;
+ } extensions;
+
+ struct loader_device *next;
+};
+
+// Per ICD information
+
+// Per ICD structure
+struct loader_icd_term {
+ // pointers to find other structs
+ const struct loader_scanned_icd *scanned_icd;
+ const struct loader_instance *this_instance;
+ struct loader_device *logical_device_list;
+ VkInstance instance; // instance object from the icd
+ struct loader_icd_term_dispatch dispatch;
+
+ struct loader_icd_term *next;
+
+ PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS];
+};
+
+// Per ICD library structure
+struct loader_icd_tramp_list {
+ size_t capacity;
+ uint32_t count;
+ struct loader_scanned_icd *scanned_list;
+};
+
+struct loader_instance_dispatch_table {
+ VkLayerInstanceDispatchTable layer_inst_disp; // must be first entry in structure
+
+ // Physical device functions unknown to the loader
+ PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS];
+};
+
+// Per instance structure
+struct loader_instance {
+ struct loader_instance_dispatch_table *disp; // must be first entry in structure
+
+ // Vulkan API version the app is intending to use.
+ uint16_t app_api_major_version;
+ uint16_t app_api_minor_version;
+
+ // We need to manually track physical devices over time. If the user
+ // re-queries the information, we don't want to delete old data or
+ // create new data unless necessary.
+ uint32_t total_gpu_count;
+ uint32_t phys_dev_count_term;
+ struct loader_physical_device_term **phys_devs_term;
+ uint32_t phys_dev_count_tramp;
+ struct loader_physical_device_tramp **phys_devs_tramp;
+
+ // We also need to manually track physical device groups, but we don't need
+ // loader specific structures since we have that content in the physical
+ // device stored internal to the public structures.
+ uint32_t phys_dev_group_count_term;
+ struct VkPhysicalDeviceGroupProperties **phys_dev_groups_term;
+ uint32_t phys_dev_group_count_tramp;
+ struct VkPhysicalDeviceGroupProperties **phys_dev_groups_tramp;
+
+ struct loader_instance *next;
+
+ uint32_t total_icd_count;
+ struct loader_icd_term *icd_terms;
+ struct loader_icd_tramp_list icd_tramp_list;
+
+ struct loader_dispatch_hash_entry dev_ext_disp_hash[MAX_NUM_UNKNOWN_EXTS];
+ struct loader_dispatch_hash_entry phys_dev_ext_disp_hash[MAX_NUM_UNKNOWN_EXTS];
+
+ struct loader_msg_callback_map_entry *icd_msg_callback_map;
+
+ struct loader_layer_list instance_layer_list;
+ bool override_layer_present;
+
+ // List of activated layers.
+ // app_ is the version based on exactly what the application asked for.
+ // This is what must be returned to the application on Enumerate calls.
+ // expanded_ is the version based on expanding meta-layers into their
+ // individual component layers. This is what is used internally.
+ struct loader_layer_list app_activated_layer_list;
+ struct loader_layer_list expanded_activated_layer_list;
+
+ VkInstance instance; // layers/ICD instance returned to trampoline
+
+ struct loader_extension_list ext_list; // icds and loaders extensions
+ union loader_instance_extension_enables enabled_known_extensions;
+
+ VkLayerDbgFunctionNode *DbgFunctionHead;
+ uint32_t num_tmp_report_callbacks;
+ VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos;
+ VkDebugReportCallbackEXT *tmp_report_callbacks;
+ uint32_t num_tmp_messengers;
+ VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos;
+ VkDebugUtilsMessengerEXT *tmp_messengers;
+
+ VkAllocationCallbacks alloc_callbacks;
+
+ bool wsi_surface_enabled;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ bool wsi_win32_surface_enabled;
+#endif
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ bool wsi_wayland_surface_enabled;
+#endif
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ bool wsi_xcb_surface_enabled;
+#endif
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ bool wsi_xlib_surface_enabled;
+#endif
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ bool wsi_android_surface_enabled;
+#endif
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ bool wsi_macos_surface_enabled;
+#endif
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ bool wsi_ios_surface_enabled;
+#endif
+ bool wsi_headless_surface_enabled;
+#if defined(VK_USE_PLATFORM_METAL_EXT)
+ bool wsi_metal_surface_enabled;
+#endif
+ bool wsi_display_enabled;
+ bool wsi_display_props2_enabled;
+};
+
+// VkPhysicalDevice requires special treatment by loader. Firstly, terminator
+// code must be able to get the struct loader_icd_term to call into the proper
+// driver (multiple ICD/gpu case). This can be accomplished by wrapping the
+// created VkPhysicalDevice in loader terminate_EnumeratePhysicalDevices().
+// Secondly, the loader must be able to handle wrapped by layer VkPhysicalDevice
+// in trampoline code. This implies, that the loader trampoline code must also
+// wrap the VkPhysicalDevice object in trampoline code. Thus, loader has to
+// wrap the VkPhysicalDevice created object twice. In trampoline code it can't
+// rely on the terminator object wrapping since a layer may also wrap. Since
+// trampoline code wraps the VkPhysicalDevice this means all loader trampoline
+// code that passes a VkPhysicalDevice should unwrap it.
+
+// Per enumerated PhysicalDevice structure, used to wrap in trampoline code and
+// also same structure used to wrap in terminator code
+struct loader_physical_device_tramp {
+ struct loader_instance_dispatch_table *disp; // must be first entry in structure
+ struct loader_instance *this_instance;
+ VkPhysicalDevice phys_dev; // object from layers/loader terminator
+};
+
+// Per enumerated PhysicalDevice structure, used to wrap in terminator code
+struct loader_physical_device_term {
+ struct loader_instance_dispatch_table *disp; // must be first entry in structure
+ struct loader_icd_term *this_icd_term;
+ uint8_t icd_index;
+ VkPhysicalDevice phys_dev; // object from ICD
+};
+
+struct loader_struct {
+ struct loader_instance *instances;
+};
+
+struct loader_scanned_icd {
+ char *lib_name;
+ loader_platform_dl_handle handle;
+ uint32_t api_version;
+ uint32_t interface_version;
+ PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+ PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr;
+ PFN_vkCreateInstance CreateInstance;
+ PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+};
+
+static inline struct loader_instance *loader_instance(VkInstance instance) { return (struct loader_instance *)instance; }
+
+static inline VkPhysicalDevice loader_unwrap_physical_device(VkPhysicalDevice physicalDevice) {
+ struct loader_physical_device_tramp *phys_dev = (struct loader_physical_device_tramp *)physicalDevice;
+ return phys_dev->phys_dev;
+}
+
+static inline void loader_set_dispatch(void *obj, const void *data) { *((const void **)obj) = data; }
+
+static inline VkLayerDispatchTable *loader_get_dispatch(const void *obj) { return *((VkLayerDispatchTable **)obj); }
+
+static inline struct loader_dev_dispatch_table *loader_get_dev_dispatch(const void *obj) {
+ return *((struct loader_dev_dispatch_table **)obj);
+}
+
+static inline VkLayerInstanceDispatchTable *loader_get_instance_layer_dispatch(const void *obj) {
+ return *((VkLayerInstanceDispatchTable **)obj);
+}
+
+static inline struct loader_instance_dispatch_table *loader_get_instance_dispatch(const void *obj) {
+ return *((struct loader_instance_dispatch_table **)obj);
+}
+
+static inline void loader_init_dispatch(void *obj, const void *data) {
+#ifdef DEBUG
+ assert(valid_loader_magic_value(obj) &&
+ "Incompatible ICD, first dword must be initialized to "
+ "ICD_LOADER_MAGIC. See loader/README.md for details.");
+#endif
+
+ loader_set_dispatch(obj, data);
+}
+
+// Global variables used across files
+extern struct loader_struct loader;
+extern THREAD_LOCAL_DECL struct loader_instance *tls_instance;
+#if defined(_WIN32) && !defined(LOADER_DYNAMIC_LIB)
+extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_init);
+#endif
+extern loader_platform_thread_mutex loader_lock;
+extern loader_platform_thread_mutex loader_json_lock;
+
+struct loader_msg_callback_map_entry {
+ VkDebugReportCallbackEXT icd_obj;
+ VkDebugReportCallbackEXT loader_obj;
+};
+
+// Helper function definitions
+void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope allocationScope);
+void loader_instance_heap_free(const struct loader_instance *instance, void *pMemory);
+void *loader_instance_heap_realloc(const struct loader_instance *instance, void *pMemory, size_t orig_size, size_t size,
+ VkSystemAllocationScope alloc_scope);
+void *loader_instance_tls_heap_alloc(size_t size);
+void loader_instance_tls_heap_free(void *pMemory);
+void *loader_device_heap_alloc(const struct loader_device *device, size_t size, VkSystemAllocationScope allocationScope);
+void loader_device_heap_free(const struct loader_device *device, void *pMemory);
+void *loader_device_heap_realloc(const struct loader_device *device, void *pMemory, size_t orig_size, size_t size,
+ VkSystemAllocationScope alloc_scope);
+
+void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...);
+
+bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2);
+
+VkResult loaderValidateLayers(const struct loader_instance *inst, const uint32_t layer_count,
+ const char *const *ppEnabledLayerNames, const struct loader_layer_list *list);
+
+VkResult loader_validate_instance_extensions(struct loader_instance *inst, const struct loader_extension_list *icd_exts,
+ const struct loader_layer_list *instance_layer,
+ const VkInstanceCreateInfo *pCreateInfo);
+
+void loader_initialize(void);
+bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, const uint32_t count,
+ const VkExtensionProperties *ext_array);
+bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list);
+
+VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list,
+ uint32_t prop_list_count, const VkExtensionProperties *props);
+VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct loader_device_extension_list *ext_list,
+ const VkExtensionProperties *props, uint32_t entry_count, char **entrys);
+VkResult loader_add_device_extensions(const struct loader_instance *inst,
+ PFN_vkEnumerateDeviceExtensionProperties fpEnumerateDeviceExtensionProperties,
+ VkPhysicalDevice physical_device, const char *lib_name,
+ struct loader_extension_list *ext_list);
+VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size);
+void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list);
+void loaderDestroyLayerList(const struct loader_instance *inst, struct loader_device *device, struct loader_layer_list *layer_list);
+void loaderDeleteLayerListAndProperties(const struct loader_instance *inst, struct loader_layer_list *layer_list);
+void loaderAddLayerNameToList(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags,
+ const struct loader_layer_list *source_list, struct loader_layer_list *target_list,
+ struct loader_layer_list *expanded_target_list);
+void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list);
+VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list);
+void loaderScanForLayers(struct loader_instance *inst, struct loader_layer_list *instance_layers);
+void loaderScanForImplicitLayers(struct loader_instance *inst, struct loader_layer_list *instance_layers);
+bool loaderImplicitLayerIsEnabled(const struct loader_instance *inst, const struct loader_layer_properties *prop);
+VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
+ struct loader_extension_list *inst_exts);
+struct loader_icd_term *loader_get_icd_and_device(const void *device, struct loader_device **found_dev, uint32_t *icd_index);
+void loader_init_dispatch_dev_ext(struct loader_instance *inst, struct loader_device *dev);
+void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName);
+void *loader_get_dev_ext_trampoline(uint32_t index);
+bool loader_phys_dev_ext_gpa(struct loader_instance *inst, const char *funcName, bool perform_checking, void **tramp_addr,
+ void **term_addr);
+void *loader_get_phys_dev_ext_tramp(uint32_t index);
+void *loader_get_phys_dev_ext_termin(uint32_t index);
+struct loader_instance *loader_get_instance(const VkInstance instance);
+void loaderDeactivateLayers(const struct loader_instance *instance, struct loader_device *device, struct loader_layer_list *list);
+struct loader_device *loader_create_logical_device(const struct loader_instance *inst, const VkAllocationCallbacks *pAllocator);
+void loader_add_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term,
+ struct loader_device *found_dev);
+void loader_remove_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term,
+ struct loader_device *found_dev, const VkAllocationCallbacks *pAllocator);
+// NOTE: Outside of loader, this entry-point is only provided for error
+// cleanup.
+void loader_destroy_logical_device(const struct loader_instance *inst, struct loader_device *dev,
+ const VkAllocationCallbacks *pAllocator);
+
+VkResult loaderEnableInstanceLayers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo,
+ const struct loader_layer_list *instance_layers);
+
+VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
+ struct loader_instance *inst, VkInstance *created_instance);
+
+void loaderActivateInstanceLayerExtensions(struct loader_instance *inst, VkInstance created_inst);
+
+VKAPI_ATTR VkResult VKAPI_CALL loader_layer_create_device(VkInstance instance, VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
+ PFN_vkGetInstanceProcAddr layerGIPA, PFN_vkGetDeviceProcAddr *nextGDPA);
+VKAPI_ATTR void VKAPI_CALL loader_layer_destroy_device(VkDevice device, const VkAllocationCallbacks *pAllocator,
+ PFN_vkDestroyDevice destroyFunction);
+
+VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, const struct loader_instance *inst,
+ struct loader_device *dev, PFN_vkGetInstanceProcAddr callingLayer,
+ PFN_vkGetDeviceProcAddr *layerNextGDPA);
+
+VkResult loader_validate_device_extensions(struct loader_instance *this_instance,
+ const struct loader_layer_list *activated_device_layers,
+ const struct loader_extension_list *icd_exts, const VkDeviceCreateInfo *pCreateInfo);
+
+VkResult setupLoaderTrampPhysDevs(VkInstance instance);
+VkResult setupLoaderTermPhysDevs(struct loader_instance *inst);
+
+VkStringErrorFlags vk_string_validate(const int max_length, const char *char_array);
+
+#endif // LOADER_H
diff --git a/thirdparty/vulkan/loader/murmurhash.c b/thirdparty/vulkan/loader/murmurhash.c
new file mode 100644
index 0000000000..40f0d5e975
--- /dev/null
+++ b/thirdparty/vulkan/loader/murmurhash.c
@@ -0,0 +1,98 @@
+
+/**
+ * `murmurhash.h' - murmurhash
+ *
+ * copyright (c) 2014 joseph werle <joseph.werle@gmail.com>
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and/or associated documentation files (the "Materials"), to
+ * deal in the Materials without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Materials, and to permit persons to whom the Materials are
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included in
+ * all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
+ * USE OR OTHER DEALINGS IN THE MATERIALS.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "murmurhash.h"
+
+uint32_t murmurhash(const char *key, size_t len, uint32_t seed) {
+ uint32_t c1 = 0xcc9e2d51;
+ uint32_t c2 = 0x1b873593;
+ uint32_t r1 = 15;
+ uint32_t r2 = 13;
+ uint32_t m = 5;
+ uint32_t n = 0xe6546b64;
+ uint32_t h = 0;
+ uint32_t k = 0;
+ uint8_t *d = (uint8_t *)key; // 32 bit extract from `key'
+ const uint32_t *chunks = NULL;
+ const uint8_t *tail = NULL; // tail - last 8 bytes
+ int i = 0;
+ int l = (int)len / 4; // chunk length
+
+ h = seed;
+
+ chunks = (const uint32_t *)(d + l * 4); // body
+ tail = (const uint8_t *)(d + l * 4); // last 8 byte chunk of `key'
+
+ // for each 4 byte chunk of `key'
+ for (i = -l; i != 0; ++i) {
+ // next 4 byte chunk of `key'
+ k = chunks[i];
+
+ // encode next 4 byte chunk of `key'
+ k *= c1;
+ k = (k << r1) | (k >> (32 - r1));
+ k *= c2;
+
+ // append to hash
+ h ^= k;
+ h = (h << r2) | (h >> (32 - r2));
+ h = h * m + n;
+ }
+
+ k = 0;
+
+ // remainder
+ switch (len & 3) { // `len % 4'
+ case 3:
+ k ^= (tail[2] << 16);
+ // fall through
+ case 2:
+ k ^= (tail[1] << 8);
+ // fall through
+ case 1:
+ k ^= tail[0];
+ k *= c1;
+ k = (k << r1) | (k >> (32 - r1));
+ k *= c2;
+ h ^= k;
+ }
+
+ h ^= len;
+
+ h ^= (h >> 16);
+ h *= 0x85ebca6b;
+ h ^= (h >> 13);
+ h *= 0xc2b2ae35;
+ h ^= (h >> 16);
+
+ return h;
+}
diff --git a/thirdparty/vulkan/loader/murmurhash.h b/thirdparty/vulkan/loader/murmurhash.h
new file mode 100644
index 0000000000..775532e8b8
--- /dev/null
+++ b/thirdparty/vulkan/loader/murmurhash.h
@@ -0,0 +1,52 @@
+
+/**
+ * `murmurhash.h' - murmurhash
+ *
+ * copyright (c) 2014 joseph werle <joseph.werle@gmail.com>
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and/or associated documentation files (the "Materials"), to
+ * deal in the Materials without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Materials, and to permit persons to whom the Materials are
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included in
+ * all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
+ * USE OR OTHER DEALINGS IN THE MATERIALS.
+ */
+
+#ifndef MURMURHASH_H
+#define MURMURHASH_H 1
+
+#include <stdint.h>
+
+#define MURMURHASH_VERSION "0.0.3"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Returns a murmur hash of `key' based on `seed'
+ * using the MurmurHash3 algorithm
+ */
+
+uint32_t murmurhash(const char *key, size_t len, uint32_t seed);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/vulkan/loader/phys_dev_ext.c b/thirdparty/vulkan/loader/phys_dev_ext.c
new file mode 100644
index 0000000000..91e0ef8f67
--- /dev/null
+++ b/thirdparty/vulkan/loader/phys_dev_ext.c
@@ -0,0 +1,1056 @@
+/*
+ *
+ * Copyright (c) 2016-17 The Khronos Group Inc.
+ * Copyright (c) 2016-17 Valve Corporation
+ * Copyright (c) 2016-17 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Mark Young <marky@lunarg.com>
+ * Author: Lenny Komow <lenny@lunarg.com>
+ *
+ */
+
+// This code is used to enable generic instance extensions which use a physical device
+// as the first parameter. If the extension is already known by the loader, it will
+// not use this code, but instead use the more direct route. However, if it is
+// unknown to the loader, it will use this code. Technically, this is not trampoline
+// code since we don't want to optimize it out.
+
+#include "vk_loader_platform.h"
+#include "loader.h"
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC optimize(3) // force gcc to use tail-calls
+#endif
+
+// Declarations for the trampoline
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp0(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp1(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp2(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp3(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp4(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp5(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp6(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp7(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp8(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp9(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp10(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp11(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp12(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp13(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp14(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp15(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp16(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp17(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp18(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp19(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp20(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp21(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp22(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp23(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp24(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp25(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp26(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp27(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp28(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp29(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp30(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp31(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp32(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp33(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp34(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp35(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp36(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp37(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp38(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp39(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp40(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp41(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp42(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp43(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp44(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp45(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp46(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp47(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp48(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp49(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp50(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp51(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp52(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp53(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp54(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp55(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp56(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp57(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp58(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp59(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp60(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp61(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp62(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp63(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp64(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp65(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp66(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp67(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp68(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp69(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp70(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp71(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp72(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp73(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp74(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp75(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp76(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp77(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp78(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp79(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp80(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp81(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp82(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp83(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp84(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp85(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp86(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp87(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp88(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp89(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp90(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp91(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp92(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp93(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp94(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp95(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp96(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp97(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp98(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp99(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp100(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp101(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp102(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp103(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp104(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp105(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp106(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp107(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp108(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp109(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp110(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp111(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp112(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp113(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp114(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp115(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp116(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp117(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp118(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp119(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp120(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp121(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp122(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp123(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp124(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp125(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp126(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp127(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp128(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp129(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp130(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp131(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp132(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp133(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp134(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp135(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp136(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp137(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp138(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp139(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp140(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp141(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp142(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp143(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp144(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp145(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp146(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp147(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp148(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp149(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp150(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp151(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp152(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp153(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp154(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp155(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp156(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp157(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp158(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp159(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp160(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp161(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp162(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp163(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp164(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp165(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp166(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp167(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp168(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp169(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp170(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp171(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp172(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp173(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp174(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp175(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp176(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp177(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp178(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp179(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp180(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp181(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp182(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp183(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp184(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp185(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp186(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp187(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp188(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp189(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp190(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp191(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp192(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp193(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp194(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp195(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp196(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp197(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp198(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp199(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp200(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp201(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp202(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp203(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp204(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp205(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp206(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp207(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp208(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp209(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp210(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp211(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp212(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp213(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp214(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp215(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp216(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp217(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp218(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp219(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp220(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp221(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp222(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp223(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp224(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp225(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp226(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp227(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp228(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp229(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp230(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp231(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp232(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp233(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp234(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp235(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp236(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp237(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp238(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp239(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp240(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp241(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp242(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp243(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp244(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp245(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp246(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp247(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp248(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp249(VkPhysicalDevice);
+
+// Disable clang-format for lists of macros
+// clang-format off
+
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin0(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin1(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin2(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin3(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin4(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin5(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin6(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin7(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin8(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin9(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin10(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin11(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin12(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin13(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin14(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin15(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin16(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin17(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin18(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin19(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin20(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin21(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin22(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin23(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin24(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin25(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin26(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin27(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin28(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin29(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin30(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin31(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin32(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin33(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin34(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin35(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin36(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin37(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin38(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin39(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin40(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin41(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin42(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin43(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin44(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin45(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin46(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin47(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin48(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin49(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin50(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin51(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin52(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin53(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin54(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin55(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin56(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin57(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin58(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin59(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin60(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin61(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin62(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin63(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin64(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin65(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin66(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin67(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin68(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin69(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin70(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin71(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin72(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin73(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin74(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin75(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin76(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin77(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin78(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin79(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin80(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin81(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin82(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin83(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin84(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin85(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin86(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin87(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin88(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin89(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin90(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin91(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin92(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin93(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin94(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin95(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin96(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin97(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin98(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin99(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin100(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin101(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin102(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin103(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin104(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin105(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin106(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin107(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin108(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin109(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin110(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin111(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin112(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin113(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin114(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin115(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin116(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin117(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin118(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin119(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin120(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin121(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin122(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin123(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin124(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin125(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin126(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin127(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin128(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin129(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin130(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin131(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin132(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin133(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin134(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin135(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin136(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin137(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin138(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin139(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin140(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin141(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin142(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin143(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin144(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin145(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin146(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin147(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin148(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin149(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin150(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin151(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin152(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin153(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin154(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin155(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin156(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin157(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin158(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin159(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin160(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin161(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin162(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin163(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin164(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin165(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin166(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin167(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin168(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin169(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin170(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin171(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin172(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin173(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin174(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin175(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin176(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin177(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin178(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin179(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin180(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin181(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin182(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin183(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin184(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin185(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin186(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin187(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin188(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin189(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin190(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin191(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin192(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin193(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin194(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin195(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin196(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin197(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin198(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin199(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin200(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin201(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin202(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin203(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin204(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin205(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin206(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin207(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin208(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin209(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin210(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin211(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin212(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin213(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin214(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin215(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin216(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin217(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin218(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin219(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin220(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin221(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin222(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin223(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin224(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin225(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin226(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin227(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin228(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin229(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin230(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin231(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin232(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin233(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin234(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin235(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin236(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin237(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin238(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin239(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin240(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin241(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin242(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin243(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin244(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin245(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin246(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin247(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin248(VkPhysicalDevice);
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin249(VkPhysicalDevice);
+
+
+void *loader_get_phys_dev_ext_tramp(uint32_t index) {
+ switch (index) {
+#define TRAMP_CASE_HANDLE(num) case num: return vkPhysDevExtTramp##num
+ TRAMP_CASE_HANDLE(0);
+ TRAMP_CASE_HANDLE(1);
+ TRAMP_CASE_HANDLE(2);
+ TRAMP_CASE_HANDLE(3);
+ TRAMP_CASE_HANDLE(4);
+ TRAMP_CASE_HANDLE(5);
+ TRAMP_CASE_HANDLE(6);
+ TRAMP_CASE_HANDLE(7);
+ TRAMP_CASE_HANDLE(8);
+ TRAMP_CASE_HANDLE(9);
+ TRAMP_CASE_HANDLE(10);
+ TRAMP_CASE_HANDLE(11);
+ TRAMP_CASE_HANDLE(12);
+ TRAMP_CASE_HANDLE(13);
+ TRAMP_CASE_HANDLE(14);
+ TRAMP_CASE_HANDLE(15);
+ TRAMP_CASE_HANDLE(16);
+ TRAMP_CASE_HANDLE(17);
+ TRAMP_CASE_HANDLE(18);
+ TRAMP_CASE_HANDLE(19);
+ TRAMP_CASE_HANDLE(20);
+ TRAMP_CASE_HANDLE(21);
+ TRAMP_CASE_HANDLE(22);
+ TRAMP_CASE_HANDLE(23);
+ TRAMP_CASE_HANDLE(24);
+ TRAMP_CASE_HANDLE(25);
+ TRAMP_CASE_HANDLE(26);
+ TRAMP_CASE_HANDLE(27);
+ TRAMP_CASE_HANDLE(28);
+ TRAMP_CASE_HANDLE(29);
+ TRAMP_CASE_HANDLE(30);
+ TRAMP_CASE_HANDLE(31);
+ TRAMP_CASE_HANDLE(32);
+ TRAMP_CASE_HANDLE(33);
+ TRAMP_CASE_HANDLE(34);
+ TRAMP_CASE_HANDLE(35);
+ TRAMP_CASE_HANDLE(36);
+ TRAMP_CASE_HANDLE(37);
+ TRAMP_CASE_HANDLE(38);
+ TRAMP_CASE_HANDLE(39);
+ TRAMP_CASE_HANDLE(40);
+ TRAMP_CASE_HANDLE(41);
+ TRAMP_CASE_HANDLE(42);
+ TRAMP_CASE_HANDLE(43);
+ TRAMP_CASE_HANDLE(44);
+ TRAMP_CASE_HANDLE(45);
+ TRAMP_CASE_HANDLE(46);
+ TRAMP_CASE_HANDLE(47);
+ TRAMP_CASE_HANDLE(48);
+ TRAMP_CASE_HANDLE(49);
+ TRAMP_CASE_HANDLE(50);
+ TRAMP_CASE_HANDLE(51);
+ TRAMP_CASE_HANDLE(52);
+ TRAMP_CASE_HANDLE(53);
+ TRAMP_CASE_HANDLE(54);
+ TRAMP_CASE_HANDLE(55);
+ TRAMP_CASE_HANDLE(56);
+ TRAMP_CASE_HANDLE(57);
+ TRAMP_CASE_HANDLE(58);
+ TRAMP_CASE_HANDLE(59);
+ TRAMP_CASE_HANDLE(60);
+ TRAMP_CASE_HANDLE(61);
+ TRAMP_CASE_HANDLE(62);
+ TRAMP_CASE_HANDLE(63);
+ TRAMP_CASE_HANDLE(64);
+ TRAMP_CASE_HANDLE(65);
+ TRAMP_CASE_HANDLE(66);
+ TRAMP_CASE_HANDLE(67);
+ TRAMP_CASE_HANDLE(68);
+ TRAMP_CASE_HANDLE(69);
+ TRAMP_CASE_HANDLE(70);
+ TRAMP_CASE_HANDLE(71);
+ TRAMP_CASE_HANDLE(72);
+ TRAMP_CASE_HANDLE(73);
+ TRAMP_CASE_HANDLE(74);
+ TRAMP_CASE_HANDLE(75);
+ TRAMP_CASE_HANDLE(76);
+ TRAMP_CASE_HANDLE(77);
+ TRAMP_CASE_HANDLE(78);
+ TRAMP_CASE_HANDLE(79);
+ TRAMP_CASE_HANDLE(80);
+ TRAMP_CASE_HANDLE(81);
+ TRAMP_CASE_HANDLE(82);
+ TRAMP_CASE_HANDLE(83);
+ TRAMP_CASE_HANDLE(84);
+ TRAMP_CASE_HANDLE(85);
+ TRAMP_CASE_HANDLE(86);
+ TRAMP_CASE_HANDLE(87);
+ TRAMP_CASE_HANDLE(88);
+ TRAMP_CASE_HANDLE(89);
+ TRAMP_CASE_HANDLE(90);
+ TRAMP_CASE_HANDLE(91);
+ TRAMP_CASE_HANDLE(92);
+ TRAMP_CASE_HANDLE(93);
+ TRAMP_CASE_HANDLE(94);
+ TRAMP_CASE_HANDLE(95);
+ TRAMP_CASE_HANDLE(96);
+ TRAMP_CASE_HANDLE(97);
+ TRAMP_CASE_HANDLE(98);
+ TRAMP_CASE_HANDLE(99);
+ TRAMP_CASE_HANDLE(100);
+ TRAMP_CASE_HANDLE(101);
+ TRAMP_CASE_HANDLE(102);
+ TRAMP_CASE_HANDLE(103);
+ TRAMP_CASE_HANDLE(104);
+ TRAMP_CASE_HANDLE(105);
+ TRAMP_CASE_HANDLE(106);
+ TRAMP_CASE_HANDLE(107);
+ TRAMP_CASE_HANDLE(108);
+ TRAMP_CASE_HANDLE(109);
+ TRAMP_CASE_HANDLE(110);
+ TRAMP_CASE_HANDLE(111);
+ TRAMP_CASE_HANDLE(112);
+ TRAMP_CASE_HANDLE(113);
+ TRAMP_CASE_HANDLE(114);
+ TRAMP_CASE_HANDLE(115);
+ TRAMP_CASE_HANDLE(116);
+ TRAMP_CASE_HANDLE(117);
+ TRAMP_CASE_HANDLE(118);
+ TRAMP_CASE_HANDLE(119);
+ TRAMP_CASE_HANDLE(120);
+ TRAMP_CASE_HANDLE(121);
+ TRAMP_CASE_HANDLE(122);
+ TRAMP_CASE_HANDLE(123);
+ TRAMP_CASE_HANDLE(124);
+ TRAMP_CASE_HANDLE(125);
+ TRAMP_CASE_HANDLE(126);
+ TRAMP_CASE_HANDLE(127);
+ TRAMP_CASE_HANDLE(128);
+ TRAMP_CASE_HANDLE(129);
+ TRAMP_CASE_HANDLE(130);
+ TRAMP_CASE_HANDLE(131);
+ TRAMP_CASE_HANDLE(132);
+ TRAMP_CASE_HANDLE(133);
+ TRAMP_CASE_HANDLE(134);
+ TRAMP_CASE_HANDLE(135);
+ TRAMP_CASE_HANDLE(136);
+ TRAMP_CASE_HANDLE(137);
+ TRAMP_CASE_HANDLE(138);
+ TRAMP_CASE_HANDLE(139);
+ TRAMP_CASE_HANDLE(140);
+ TRAMP_CASE_HANDLE(141);
+ TRAMP_CASE_HANDLE(142);
+ TRAMP_CASE_HANDLE(143);
+ TRAMP_CASE_HANDLE(144);
+ TRAMP_CASE_HANDLE(145);
+ TRAMP_CASE_HANDLE(146);
+ TRAMP_CASE_HANDLE(147);
+ TRAMP_CASE_HANDLE(148);
+ TRAMP_CASE_HANDLE(149);
+ TRAMP_CASE_HANDLE(150);
+ TRAMP_CASE_HANDLE(151);
+ TRAMP_CASE_HANDLE(152);
+ TRAMP_CASE_HANDLE(153);
+ TRAMP_CASE_HANDLE(154);
+ TRAMP_CASE_HANDLE(155);
+ TRAMP_CASE_HANDLE(156);
+ TRAMP_CASE_HANDLE(157);
+ TRAMP_CASE_HANDLE(158);
+ TRAMP_CASE_HANDLE(159);
+ TRAMP_CASE_HANDLE(160);
+ TRAMP_CASE_HANDLE(161);
+ TRAMP_CASE_HANDLE(162);
+ TRAMP_CASE_HANDLE(163);
+ TRAMP_CASE_HANDLE(164);
+ TRAMP_CASE_HANDLE(165);
+ TRAMP_CASE_HANDLE(166);
+ TRAMP_CASE_HANDLE(167);
+ TRAMP_CASE_HANDLE(168);
+ TRAMP_CASE_HANDLE(169);
+ TRAMP_CASE_HANDLE(170);
+ TRAMP_CASE_HANDLE(171);
+ TRAMP_CASE_HANDLE(172);
+ TRAMP_CASE_HANDLE(173);
+ TRAMP_CASE_HANDLE(174);
+ TRAMP_CASE_HANDLE(175);
+ TRAMP_CASE_HANDLE(176);
+ TRAMP_CASE_HANDLE(177);
+ TRAMP_CASE_HANDLE(178);
+ TRAMP_CASE_HANDLE(179);
+ TRAMP_CASE_HANDLE(180);
+ TRAMP_CASE_HANDLE(181);
+ TRAMP_CASE_HANDLE(182);
+ TRAMP_CASE_HANDLE(183);
+ TRAMP_CASE_HANDLE(184);
+ TRAMP_CASE_HANDLE(185);
+ TRAMP_CASE_HANDLE(186);
+ TRAMP_CASE_HANDLE(187);
+ TRAMP_CASE_HANDLE(188);
+ TRAMP_CASE_HANDLE(189);
+ TRAMP_CASE_HANDLE(190);
+ TRAMP_CASE_HANDLE(191);
+ TRAMP_CASE_HANDLE(192);
+ TRAMP_CASE_HANDLE(193);
+ TRAMP_CASE_HANDLE(194);
+ TRAMP_CASE_HANDLE(195);
+ TRAMP_CASE_HANDLE(196);
+ TRAMP_CASE_HANDLE(197);
+ TRAMP_CASE_HANDLE(198);
+ TRAMP_CASE_HANDLE(199);
+ TRAMP_CASE_HANDLE(200);
+ TRAMP_CASE_HANDLE(201);
+ TRAMP_CASE_HANDLE(202);
+ TRAMP_CASE_HANDLE(203);
+ TRAMP_CASE_HANDLE(204);
+ TRAMP_CASE_HANDLE(205);
+ TRAMP_CASE_HANDLE(206);
+ TRAMP_CASE_HANDLE(207);
+ TRAMP_CASE_HANDLE(208);
+ TRAMP_CASE_HANDLE(209);
+ TRAMP_CASE_HANDLE(210);
+ TRAMP_CASE_HANDLE(211);
+ TRAMP_CASE_HANDLE(212);
+ TRAMP_CASE_HANDLE(213);
+ TRAMP_CASE_HANDLE(214);
+ TRAMP_CASE_HANDLE(215);
+ TRAMP_CASE_HANDLE(216);
+ TRAMP_CASE_HANDLE(217);
+ TRAMP_CASE_HANDLE(218);
+ TRAMP_CASE_HANDLE(219);
+ TRAMP_CASE_HANDLE(220);
+ TRAMP_CASE_HANDLE(221);
+ TRAMP_CASE_HANDLE(222);
+ TRAMP_CASE_HANDLE(223);
+ TRAMP_CASE_HANDLE(224);
+ TRAMP_CASE_HANDLE(225);
+ TRAMP_CASE_HANDLE(226);
+ TRAMP_CASE_HANDLE(227);
+ TRAMP_CASE_HANDLE(228);
+ TRAMP_CASE_HANDLE(229);
+ TRAMP_CASE_HANDLE(230);
+ TRAMP_CASE_HANDLE(231);
+ TRAMP_CASE_HANDLE(232);
+ TRAMP_CASE_HANDLE(233);
+ TRAMP_CASE_HANDLE(234);
+ TRAMP_CASE_HANDLE(235);
+ TRAMP_CASE_HANDLE(236);
+ TRAMP_CASE_HANDLE(237);
+ TRAMP_CASE_HANDLE(238);
+ TRAMP_CASE_HANDLE(239);
+ TRAMP_CASE_HANDLE(240);
+ TRAMP_CASE_HANDLE(241);
+ TRAMP_CASE_HANDLE(242);
+ TRAMP_CASE_HANDLE(243);
+ TRAMP_CASE_HANDLE(244);
+ TRAMP_CASE_HANDLE(245);
+ TRAMP_CASE_HANDLE(246);
+ TRAMP_CASE_HANDLE(247);
+ TRAMP_CASE_HANDLE(248);
+ TRAMP_CASE_HANDLE(249);
+ }
+ return NULL;
+}
+
+void *loader_get_phys_dev_ext_termin(uint32_t index) {
+ switch (index) {
+#define TERM_CASE_HANDLE(num) case num: return vkPhysDevExtTermin##num
+ TERM_CASE_HANDLE(0);
+ TERM_CASE_HANDLE(1);
+ TERM_CASE_HANDLE(2);
+ TERM_CASE_HANDLE(3);
+ TERM_CASE_HANDLE(4);
+ TERM_CASE_HANDLE(5);
+ TERM_CASE_HANDLE(6);
+ TERM_CASE_HANDLE(7);
+ TERM_CASE_HANDLE(8);
+ TERM_CASE_HANDLE(9);
+ TERM_CASE_HANDLE(10);
+ TERM_CASE_HANDLE(11);
+ TERM_CASE_HANDLE(12);
+ TERM_CASE_HANDLE(13);
+ TERM_CASE_HANDLE(14);
+ TERM_CASE_HANDLE(15);
+ TERM_CASE_HANDLE(16);
+ TERM_CASE_HANDLE(17);
+ TERM_CASE_HANDLE(18);
+ TERM_CASE_HANDLE(19);
+ TERM_CASE_HANDLE(20);
+ TERM_CASE_HANDLE(21);
+ TERM_CASE_HANDLE(22);
+ TERM_CASE_HANDLE(23);
+ TERM_CASE_HANDLE(24);
+ TERM_CASE_HANDLE(25);
+ TERM_CASE_HANDLE(26);
+ TERM_CASE_HANDLE(27);
+ TERM_CASE_HANDLE(28);
+ TERM_CASE_HANDLE(29);
+ TERM_CASE_HANDLE(30);
+ TERM_CASE_HANDLE(31);
+ TERM_CASE_HANDLE(32);
+ TERM_CASE_HANDLE(33);
+ TERM_CASE_HANDLE(34);
+ TERM_CASE_HANDLE(35);
+ TERM_CASE_HANDLE(36);
+ TERM_CASE_HANDLE(37);
+ TERM_CASE_HANDLE(38);
+ TERM_CASE_HANDLE(39);
+ TERM_CASE_HANDLE(40);
+ TERM_CASE_HANDLE(41);
+ TERM_CASE_HANDLE(42);
+ TERM_CASE_HANDLE(43);
+ TERM_CASE_HANDLE(44);
+ TERM_CASE_HANDLE(45);
+ TERM_CASE_HANDLE(46);
+ TERM_CASE_HANDLE(47);
+ TERM_CASE_HANDLE(48);
+ TERM_CASE_HANDLE(49);
+ TERM_CASE_HANDLE(50);
+ TERM_CASE_HANDLE(51);
+ TERM_CASE_HANDLE(52);
+ TERM_CASE_HANDLE(53);
+ TERM_CASE_HANDLE(54);
+ TERM_CASE_HANDLE(55);
+ TERM_CASE_HANDLE(56);
+ TERM_CASE_HANDLE(57);
+ TERM_CASE_HANDLE(58);
+ TERM_CASE_HANDLE(59);
+ TERM_CASE_HANDLE(60);
+ TERM_CASE_HANDLE(61);
+ TERM_CASE_HANDLE(62);
+ TERM_CASE_HANDLE(63);
+ TERM_CASE_HANDLE(64);
+ TERM_CASE_HANDLE(65);
+ TERM_CASE_HANDLE(66);
+ TERM_CASE_HANDLE(67);
+ TERM_CASE_HANDLE(68);
+ TERM_CASE_HANDLE(69);
+ TERM_CASE_HANDLE(70);
+ TERM_CASE_HANDLE(71);
+ TERM_CASE_HANDLE(72);
+ TERM_CASE_HANDLE(73);
+ TERM_CASE_HANDLE(74);
+ TERM_CASE_HANDLE(75);
+ TERM_CASE_HANDLE(76);
+ TERM_CASE_HANDLE(77);
+ TERM_CASE_HANDLE(78);
+ TERM_CASE_HANDLE(79);
+ TERM_CASE_HANDLE(80);
+ TERM_CASE_HANDLE(81);
+ TERM_CASE_HANDLE(82);
+ TERM_CASE_HANDLE(83);
+ TERM_CASE_HANDLE(84);
+ TERM_CASE_HANDLE(85);
+ TERM_CASE_HANDLE(86);
+ TERM_CASE_HANDLE(87);
+ TERM_CASE_HANDLE(88);
+ TERM_CASE_HANDLE(89);
+ TERM_CASE_HANDLE(90);
+ TERM_CASE_HANDLE(91);
+ TERM_CASE_HANDLE(92);
+ TERM_CASE_HANDLE(93);
+ TERM_CASE_HANDLE(94);
+ TERM_CASE_HANDLE(95);
+ TERM_CASE_HANDLE(96);
+ TERM_CASE_HANDLE(97);
+ TERM_CASE_HANDLE(98);
+ TERM_CASE_HANDLE(99);
+ TERM_CASE_HANDLE(100);
+ TERM_CASE_HANDLE(101);
+ TERM_CASE_HANDLE(102);
+ TERM_CASE_HANDLE(103);
+ TERM_CASE_HANDLE(104);
+ TERM_CASE_HANDLE(105);
+ TERM_CASE_HANDLE(106);
+ TERM_CASE_HANDLE(107);
+ TERM_CASE_HANDLE(108);
+ TERM_CASE_HANDLE(109);
+ TERM_CASE_HANDLE(110);
+ TERM_CASE_HANDLE(111);
+ TERM_CASE_HANDLE(112);
+ TERM_CASE_HANDLE(113);
+ TERM_CASE_HANDLE(114);
+ TERM_CASE_HANDLE(115);
+ TERM_CASE_HANDLE(116);
+ TERM_CASE_HANDLE(117);
+ TERM_CASE_HANDLE(118);
+ TERM_CASE_HANDLE(119);
+ TERM_CASE_HANDLE(120);
+ TERM_CASE_HANDLE(121);
+ TERM_CASE_HANDLE(122);
+ TERM_CASE_HANDLE(123);
+ TERM_CASE_HANDLE(124);
+ TERM_CASE_HANDLE(125);
+ TERM_CASE_HANDLE(126);
+ TERM_CASE_HANDLE(127);
+ TERM_CASE_HANDLE(128);
+ TERM_CASE_HANDLE(129);
+ TERM_CASE_HANDLE(130);
+ TERM_CASE_HANDLE(131);
+ TERM_CASE_HANDLE(132);
+ TERM_CASE_HANDLE(133);
+ TERM_CASE_HANDLE(134);
+ TERM_CASE_HANDLE(135);
+ TERM_CASE_HANDLE(136);
+ TERM_CASE_HANDLE(137);
+ TERM_CASE_HANDLE(138);
+ TERM_CASE_HANDLE(139);
+ TERM_CASE_HANDLE(140);
+ TERM_CASE_HANDLE(141);
+ TERM_CASE_HANDLE(142);
+ TERM_CASE_HANDLE(143);
+ TERM_CASE_HANDLE(144);
+ TERM_CASE_HANDLE(145);
+ TERM_CASE_HANDLE(146);
+ TERM_CASE_HANDLE(147);
+ TERM_CASE_HANDLE(148);
+ TERM_CASE_HANDLE(149);
+ TERM_CASE_HANDLE(150);
+ TERM_CASE_HANDLE(151);
+ TERM_CASE_HANDLE(152);
+ TERM_CASE_HANDLE(153);
+ TERM_CASE_HANDLE(154);
+ TERM_CASE_HANDLE(155);
+ TERM_CASE_HANDLE(156);
+ TERM_CASE_HANDLE(157);
+ TERM_CASE_HANDLE(158);
+ TERM_CASE_HANDLE(159);
+ TERM_CASE_HANDLE(160);
+ TERM_CASE_HANDLE(161);
+ TERM_CASE_HANDLE(162);
+ TERM_CASE_HANDLE(163);
+ TERM_CASE_HANDLE(164);
+ TERM_CASE_HANDLE(165);
+ TERM_CASE_HANDLE(166);
+ TERM_CASE_HANDLE(167);
+ TERM_CASE_HANDLE(168);
+ TERM_CASE_HANDLE(169);
+ TERM_CASE_HANDLE(170);
+ TERM_CASE_HANDLE(171);
+ TERM_CASE_HANDLE(172);
+ TERM_CASE_HANDLE(173);
+ TERM_CASE_HANDLE(174);
+ TERM_CASE_HANDLE(175);
+ TERM_CASE_HANDLE(176);
+ TERM_CASE_HANDLE(177);
+ TERM_CASE_HANDLE(178);
+ TERM_CASE_HANDLE(179);
+ TERM_CASE_HANDLE(180);
+ TERM_CASE_HANDLE(181);
+ TERM_CASE_HANDLE(182);
+ TERM_CASE_HANDLE(183);
+ TERM_CASE_HANDLE(184);
+ TERM_CASE_HANDLE(185);
+ TERM_CASE_HANDLE(186);
+ TERM_CASE_HANDLE(187);
+ TERM_CASE_HANDLE(188);
+ TERM_CASE_HANDLE(189);
+ TERM_CASE_HANDLE(190);
+ TERM_CASE_HANDLE(191);
+ TERM_CASE_HANDLE(192);
+ TERM_CASE_HANDLE(193);
+ TERM_CASE_HANDLE(194);
+ TERM_CASE_HANDLE(195);
+ TERM_CASE_HANDLE(196);
+ TERM_CASE_HANDLE(197);
+ TERM_CASE_HANDLE(198);
+ TERM_CASE_HANDLE(199);
+ TERM_CASE_HANDLE(200);
+ TERM_CASE_HANDLE(201);
+ TERM_CASE_HANDLE(202);
+ TERM_CASE_HANDLE(203);
+ TERM_CASE_HANDLE(204);
+ TERM_CASE_HANDLE(205);
+ TERM_CASE_HANDLE(206);
+ TERM_CASE_HANDLE(207);
+ TERM_CASE_HANDLE(208);
+ TERM_CASE_HANDLE(209);
+ TERM_CASE_HANDLE(210);
+ TERM_CASE_HANDLE(211);
+ TERM_CASE_HANDLE(212);
+ TERM_CASE_HANDLE(213);
+ TERM_CASE_HANDLE(214);
+ TERM_CASE_HANDLE(215);
+ TERM_CASE_HANDLE(216);
+ TERM_CASE_HANDLE(217);
+ TERM_CASE_HANDLE(218);
+ TERM_CASE_HANDLE(219);
+ TERM_CASE_HANDLE(220);
+ TERM_CASE_HANDLE(221);
+ TERM_CASE_HANDLE(222);
+ TERM_CASE_HANDLE(223);
+ TERM_CASE_HANDLE(224);
+ TERM_CASE_HANDLE(225);
+ TERM_CASE_HANDLE(226);
+ TERM_CASE_HANDLE(227);
+ TERM_CASE_HANDLE(228);
+ TERM_CASE_HANDLE(229);
+ TERM_CASE_HANDLE(230);
+ TERM_CASE_HANDLE(231);
+ TERM_CASE_HANDLE(232);
+ TERM_CASE_HANDLE(233);
+ TERM_CASE_HANDLE(234);
+ TERM_CASE_HANDLE(235);
+ TERM_CASE_HANDLE(236);
+ TERM_CASE_HANDLE(237);
+ TERM_CASE_HANDLE(238);
+ TERM_CASE_HANDLE(239);
+ TERM_CASE_HANDLE(240);
+ TERM_CASE_HANDLE(241);
+ TERM_CASE_HANDLE(242);
+ TERM_CASE_HANDLE(243);
+ TERM_CASE_HANDLE(244);
+ TERM_CASE_HANDLE(245);
+ TERM_CASE_HANDLE(246);
+ TERM_CASE_HANDLE(247);
+ TERM_CASE_HANDLE(248);
+ TERM_CASE_HANDLE(249);
+ }
+ return NULL;
+}
diff --git a/thirdparty/vulkan/loader/trampoline.c b/thirdparty/vulkan/loader/trampoline.c
new file mode 100644
index 0000000000..a6a37f0fce
--- /dev/null
+++ b/thirdparty/vulkan/loader/trampoline.c
@@ -0,0 +1,2593 @@
+/*
+ *
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ * Copyright (C) 2015 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Courtney Goeltzenleuchter <courtney@lunarg.com>
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Tony Barbour <tony@LunarG.com>
+ * Author: Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "vk_loader_platform.h"
+#include "loader.h"
+#include "debug_utils.h"
+#include "wsi.h"
+#include "vk_loader_extensions.h"
+#include "gpa_helper.h"
+
+
+// Trampoline entrypoints are in this file for core Vulkan commands
+
+// Get an instance level or global level entry point address.
+// @param instance
+// @param pName
+// @return
+// If instance == NULL returns a global level functions only
+// If instance is valid returns a trampoline entry point for all dispatchable Vulkan
+// functions both core and extensions.
+LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *pName) {
+ void *addr;
+
+ addr = globalGetProcAddr(pName);
+ if (instance == VK_NULL_HANDLE || addr != NULL) {
+ return addr;
+ }
+
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (ptr_instance == NULL) return NULL;
+ // Return trampoline code for non-global entrypoints including any extensions.
+ // Device extensions are returned if a layer or ICD supports the extension.
+ // Instance extensions are returned if the extension is enabled and the
+ // loader or someone else supports the extension
+ return trampolineGetProcAddr(ptr_instance, pName);
+}
+
+// Get a device level or global level entry point address.
+// @param device
+// @param pName
+// @return
+// If device is valid, returns a device relative entry point for device level
+// entry points both core and extensions.
+// Device relative means call down the device chain.
+LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *pName) {
+ void *addr;
+
+ // For entrypoints that loader must handle (ie non-dispatchable or create object)
+ // make sure the loader entrypoint is returned
+ addr = loader_non_passthrough_gdpa(pName);
+ if (addr) {
+ return addr;
+ }
+
+ // Although CreateDevice is on device chain it's dispatchable object isn't
+ // a VkDevice or child of VkDevice so return NULL.
+ if (!strcmp(pName, "CreateDevice")) return NULL;
+
+ // Return the dispatch table entrypoint for the fastest case
+ const VkLayerDispatchTable *disp_table = *(VkLayerDispatchTable **)device;
+ if (disp_table == NULL) return NULL;
+
+ addr = loader_lookup_device_dispatch_table(disp_table, pName);
+ if (addr) return addr;
+
+ if (disp_table->GetDeviceProcAddr == NULL) return NULL;
+ return disp_table->GetDeviceProcAddr(device, pName);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName,
+ uint32_t *pPropertyCount,
+ VkExtensionProperties *pProperties) {
+ tls_instance = NULL;
+ LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
+
+ // We know we need to call at least the terminator
+ VkResult res = VK_SUCCESS;
+ VkEnumerateInstanceExtensionPropertiesChain chain_tail = {
+ .header =
+ {
+ .type = VK_CHAIN_TYPE_ENUMERATE_INSTANCE_EXTENSION_PROPERTIES,
+ .version = VK_CURRENT_CHAIN_VERSION,
+ .size = sizeof(chain_tail),
+ },
+ .pfnNextLayer = &terminator_EnumerateInstanceExtensionProperties,
+ .pNextLink = NULL,
+ };
+ VkEnumerateInstanceExtensionPropertiesChain *chain_head = &chain_tail;
+
+ // Get the implicit layers
+ struct loader_layer_list layers;
+ memset(&layers, 0, sizeof(layers));
+ loaderScanForImplicitLayers(NULL, &layers);
+
+ // We'll need to save the dl handles so we can close them later
+ loader_platform_dl_handle *libs = malloc(sizeof(loader_platform_dl_handle) * layers.count);
+ if (libs == NULL) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ size_t lib_count = 0;
+
+ // Prepend layers onto the chain if they implment this entry point
+ for (uint32_t i = 0; i < layers.count; ++i) {
+ if (!loaderImplicitLayerIsEnabled(NULL, layers.list + i) ||
+ layers.list[i].pre_instance_functions.enumerate_instance_extension_properties[0] == '\0') {
+ continue;
+ }
+
+ loader_platform_dl_handle layer_lib = loader_platform_open_library(layers.list[i].lib_name);
+ if (layer_lib == NULL) {
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "%s: Unable to load implicit layer library \"%s\"", __FUNCTION__,
+ layers.list[i].lib_name);
+ continue;
+ }
+
+ libs[lib_count++] = layer_lib;
+ void *pfn = loader_platform_get_proc_address(layer_lib,
+ layers.list[i].pre_instance_functions.enumerate_instance_extension_properties);
+ if (pfn == NULL) {
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "%s: Unable to resolve symbol \"%s\" in implicit layer library \"%s\"", __FUNCTION__,
+ layers.list[i].pre_instance_functions.enumerate_instance_extension_properties, layers.list[i].lib_name);
+ continue;
+ }
+
+ VkEnumerateInstanceExtensionPropertiesChain *chain_link = malloc(sizeof(VkEnumerateInstanceExtensionPropertiesChain));
+ if (chain_link == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ break;
+ }
+
+ chain_link->header.type = VK_CHAIN_TYPE_ENUMERATE_INSTANCE_EXTENSION_PROPERTIES;
+ chain_link->header.version = VK_CURRENT_CHAIN_VERSION;
+ chain_link->header.size = sizeof(*chain_link);
+ chain_link->pfnNextLayer = pfn;
+ chain_link->pNextLink = chain_head;
+
+ chain_head = chain_link;
+ }
+
+ // Call down the chain
+ if (res == VK_SUCCESS) {
+ res = chain_head->pfnNextLayer(chain_head->pNextLink, pLayerName, pPropertyCount, pProperties);
+ }
+
+ // Free up the layers
+ loaderDeleteLayerListAndProperties(NULL, &layers);
+
+ // Tear down the chain
+ while (chain_head != &chain_tail) {
+ VkEnumerateInstanceExtensionPropertiesChain *holder = chain_head;
+ chain_head = (VkEnumerateInstanceExtensionPropertiesChain *)chain_head->pNextLink;
+ free(holder);
+ }
+
+ // Close the dl handles
+ for (size_t i = 0; i < lib_count; ++i) {
+ loader_platform_close_library(libs[i]);
+ }
+ free(libs);
+
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
+ VkLayerProperties *pProperties) {
+ tls_instance = NULL;
+ LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
+
+ // We know we need to call at least the terminator
+ VkResult res = VK_SUCCESS;
+ VkEnumerateInstanceLayerPropertiesChain chain_tail = {
+ .header =
+ {
+ .type = VK_CHAIN_TYPE_ENUMERATE_INSTANCE_LAYER_PROPERTIES,
+ .version = VK_CURRENT_CHAIN_VERSION,
+ .size = sizeof(chain_tail),
+ },
+ .pfnNextLayer = &terminator_EnumerateInstanceLayerProperties,
+ .pNextLink = NULL,
+ };
+ VkEnumerateInstanceLayerPropertiesChain *chain_head = &chain_tail;
+
+ // Get the implicit layers
+ struct loader_layer_list layers;
+ memset(&layers, 0, sizeof(layers));
+ loaderScanForImplicitLayers(NULL, &layers);
+
+ // We'll need to save the dl handles so we can close them later
+ loader_platform_dl_handle *libs = malloc(sizeof(loader_platform_dl_handle) * layers.count);
+ if (libs == NULL) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ size_t lib_count = 0;
+
+ // Prepend layers onto the chain if they implment this entry point
+ for (uint32_t i = 0; i < layers.count; ++i) {
+ if (!loaderImplicitLayerIsEnabled(NULL, layers.list + i) ||
+ layers.list[i].pre_instance_functions.enumerate_instance_layer_properties[0] == '\0') {
+ continue;
+ }
+
+ loader_platform_dl_handle layer_lib = loader_platform_open_library(layers.list[i].lib_name);
+ if (layer_lib == NULL) {
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "%s: Unable to load implicit layer library \"%s\"", __FUNCTION__,
+ layers.list[i].lib_name);
+ continue;
+ }
+
+ libs[lib_count++] = layer_lib;
+ void *pfn =
+ loader_platform_get_proc_address(layer_lib, layers.list[i].pre_instance_functions.enumerate_instance_layer_properties);
+ if (pfn == NULL) {
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "%s: Unable to resolve symbol \"%s\" in implicit layer library \"%s\"", __FUNCTION__,
+ layers.list[i].pre_instance_functions.enumerate_instance_layer_properties, layers.list[i].lib_name);
+ continue;
+ }
+
+ VkEnumerateInstanceLayerPropertiesChain *chain_link = malloc(sizeof(VkEnumerateInstanceLayerPropertiesChain));
+ if (chain_link == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ break;
+ }
+
+ chain_link->header.type = VK_CHAIN_TYPE_ENUMERATE_INSTANCE_LAYER_PROPERTIES;
+ chain_link->header.version = VK_CURRENT_CHAIN_VERSION;
+ chain_link->header.size = sizeof(*chain_link);
+ chain_link->pfnNextLayer = pfn;
+ chain_link->pNextLink = chain_head;
+
+ chain_head = chain_link;
+ }
+
+ // Call down the chain
+ if (res == VK_SUCCESS) {
+ res = chain_head->pfnNextLayer(chain_head->pNextLink, pPropertyCount, pProperties);
+ }
+
+ // Free up the layers
+ loaderDeleteLayerListAndProperties(NULL, &layers);
+
+ // Tear down the chain
+ while (chain_head != &chain_tail) {
+ VkEnumerateInstanceLayerPropertiesChain *holder = chain_head;
+ chain_head = (VkEnumerateInstanceLayerPropertiesChain *)chain_head->pNextLink;
+ free(holder);
+ }
+
+ // Close the dl handles
+ for (size_t i = 0; i < lib_count; ++i) {
+ loader_platform_close_library(libs[i]);
+ }
+ free(libs);
+
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion(uint32_t* pApiVersion) {
+
+ tls_instance = NULL;
+ LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
+
+ // We know we need to call at least the terminator
+ VkResult res = VK_SUCCESS;
+ VkEnumerateInstanceVersionChain chain_tail = {
+ .header =
+ {
+ .type = VK_CHAIN_TYPE_ENUMERATE_INSTANCE_VERSION,
+ .version = VK_CURRENT_CHAIN_VERSION,
+ .size = sizeof(chain_tail),
+ },
+ .pfnNextLayer = &terminator_EnumerateInstanceVersion,
+ .pNextLink = NULL,
+ };
+ VkEnumerateInstanceVersionChain *chain_head = &chain_tail;
+
+ // Get the implicit layers
+ struct loader_layer_list layers;
+ memset(&layers, 0, sizeof(layers));
+ loaderScanForImplicitLayers(NULL, &layers);
+
+ // We'll need to save the dl handles so we can close them later
+ loader_platform_dl_handle *libs = malloc(sizeof(loader_platform_dl_handle) * layers.count);
+ if (libs == NULL) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ size_t lib_count = 0;
+
+ // Prepend layers onto the chain if they implment this entry point
+ for (uint32_t i = 0; i < layers.count; ++i) {
+ if (!loaderImplicitLayerIsEnabled(NULL, layers.list + i) ||
+ layers.list[i].pre_instance_functions.enumerate_instance_version[0] == '\0') {
+ continue;
+ }
+
+ loader_platform_dl_handle layer_lib = loader_platform_open_library(layers.list[i].lib_name);
+ if (layer_lib == NULL) {
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "%s: Unable to load implicit layer library \"%s\"", __FUNCTION__,
+ layers.list[i].lib_name);
+ continue;
+ }
+
+ libs[lib_count++] = layer_lib;
+ void *pfn = loader_platform_get_proc_address(layer_lib,
+ layers.list[i].pre_instance_functions.enumerate_instance_version);
+ if (pfn == NULL) {
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "%s: Unable to resolve symbol \"%s\" in implicit layer library \"%s\"", __FUNCTION__,
+ layers.list[i].pre_instance_functions.enumerate_instance_version, layers.list[i].lib_name);
+ continue;
+ }
+
+ VkEnumerateInstanceVersionChain *chain_link = malloc(sizeof(VkEnumerateInstanceVersionChain));
+ if (chain_link == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ break;
+ }
+
+ chain_link->header.type = VK_CHAIN_TYPE_ENUMERATE_INSTANCE_VERSION;
+ chain_link->header.version = VK_CURRENT_CHAIN_VERSION;
+ chain_link->header.size = sizeof(*chain_link);
+ chain_link->pfnNextLayer = pfn;
+ chain_link->pNextLink = chain_head;
+
+ chain_head = chain_link;
+ }
+
+ // Call down the chain
+ if (res == VK_SUCCESS) {
+ res = chain_head->pfnNextLayer(chain_head->pNextLink, pApiVersion);
+ }
+
+ // Free up the layers
+ loaderDeleteLayerListAndProperties(NULL, &layers);
+
+ // Tear down the chain
+ while (chain_head != &chain_tail) {
+ VkEnumerateInstanceVersionChain *holder = chain_head;
+ chain_head = (VkEnumerateInstanceVersionChain *)chain_head->pNextLink;
+ free(holder);
+ }
+
+ // Close the dl handles
+ for (size_t i = 0; i < lib_count; ++i) {
+ loader_platform_close_library(libs[i]);
+ }
+ free(libs);
+
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
+ struct loader_instance *ptr_instance = NULL;
+ VkInstance created_instance = VK_NULL_HANDLE;
+ bool loaderLocked = false;
+ VkResult res = VK_ERROR_INITIALIZATION_FAILED;
+
+ LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator) {
+ ptr_instance = (struct loader_instance *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(struct loader_instance),
+ sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ } else {
+#endif
+ ptr_instance = (struct loader_instance *)malloc(sizeof(struct loader_instance));
+ }
+
+ VkInstanceCreateInfo ici = *pCreateInfo;
+
+ if (ptr_instance == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ tls_instance = ptr_instance;
+ loader_platform_thread_lock_mutex(&loader_lock);
+ loaderLocked = true;
+ memset(ptr_instance, 0, sizeof(struct loader_instance));
+ if (pAllocator) {
+ ptr_instance->alloc_callbacks = *pAllocator;
+ }
+
+ // Save the application version
+ if (NULL == pCreateInfo || NULL == pCreateInfo->pApplicationInfo || 0 == pCreateInfo->pApplicationInfo->apiVersion)
+{
+ ptr_instance->app_api_major_version = 1;
+ ptr_instance->app_api_minor_version = 0;
+ } else {
+ ptr_instance->app_api_major_version = VK_VERSION_MAJOR(pCreateInfo->pApplicationInfo->apiVersion);
+ ptr_instance->app_api_minor_version = VK_VERSION_MINOR(pCreateInfo->pApplicationInfo->apiVersion);
+ }
+
+ // Look for one or more VK_EXT_debug_report or VK_EXT_debug_utils create info structures
+ // and setup a callback(s) for each one found.
+ ptr_instance->num_tmp_report_callbacks = 0;
+ ptr_instance->tmp_report_create_infos = NULL;
+ ptr_instance->tmp_report_callbacks = NULL;
+ ptr_instance->num_tmp_messengers = 0;
+ ptr_instance->tmp_messenger_create_infos = NULL;
+ ptr_instance->tmp_messengers = NULL;
+
+ // Handle cases of VK_EXT_debug_utils
+ if (util_CopyDebugUtilsMessengerCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_messengers,
+ &ptr_instance->tmp_messenger_create_infos, &ptr_instance->tmp_messengers)) {
+ // One or more were found, but allocation failed. Therefore, clean up and fail this function:
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ } else if (ptr_instance->num_tmp_messengers > 0) {
+ // Setup the temporary messenger(s) here to catch early issues:
+ if (util_CreateDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+ ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers)) {
+ // Failure of setting up one or more of the messenger. Therefore, clean up and fail this function:
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ }
+
+ // Handle cases of VK_EXT_debug_report
+ if (util_CopyDebugReportCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_report_callbacks,
+ &ptr_instance->tmp_report_create_infos, &ptr_instance->tmp_report_callbacks)) {
+ // One or more were found, but allocation failed. Therefore, clean up and fail this function:
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ } else if (ptr_instance->num_tmp_report_callbacks > 0) {
+ // Setup the temporary callback(s) here to catch early issues:
+ if (util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+ ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks)) {
+ // Failure of setting up one or more of the callback. Therefore, clean up and fail this function:
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ }
+
+ // Due to implicit layers need to get layer list even if
+ // enabledLayerCount == 0 and VK_INSTANCE_LAYERS is unset. For now always
+ // get layer list via loaderScanForLayers().
+ memset(&ptr_instance->instance_layer_list, 0, sizeof(ptr_instance->instance_layer_list));
+ loaderScanForLayers(ptr_instance, &ptr_instance->instance_layer_list);
+
+ // Validate the app requested layers to be enabled
+ if (pCreateInfo->enabledLayerCount > 0) {
+ res = loaderValidateLayers(ptr_instance, pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames,
+ &ptr_instance->instance_layer_list);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+ }
+
+ // Scan/discover all ICD libraries
+ memset(&ptr_instance->icd_tramp_list, 0, sizeof(ptr_instance->icd_tramp_list));
+ res = loader_icd_scan(ptr_instance, &ptr_instance->icd_tramp_list);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+
+ // Get extensions from all ICD's, merge so no duplicates, then validate
+ res = loader_get_icd_loader_instance_extensions(ptr_instance, &ptr_instance->icd_tramp_list, &ptr_instance->ext_list);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+ res = loader_validate_instance_extensions(ptr_instance, &ptr_instance->ext_list, &ptr_instance->instance_layer_list, &ici);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+
+ ptr_instance->disp = loader_instance_heap_alloc(ptr_instance, sizeof(struct loader_instance_dispatch_table),
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (ptr_instance->disp == NULL) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "vkCreateInstance: Failed to allocate Loader's full Instance dispatch table.");
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memcpy(&ptr_instance->disp->layer_inst_disp, &instance_disp, sizeof(instance_disp));
+
+ ptr_instance->next = loader.instances;
+ loader.instances = ptr_instance;
+
+ // Activate any layers on instance chain
+ res = loaderEnableInstanceLayers(ptr_instance, &ici, &ptr_instance->instance_layer_list);
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+
+ created_instance = (VkInstance)ptr_instance;
+ res = loader_create_instance_chain(&ici, pAllocator, ptr_instance, &created_instance);
+
+ if (res == VK_SUCCESS) {
+ memset(ptr_instance->enabled_known_extensions.padding, 0, sizeof(uint64_t) * 4);
+
+ wsi_create_instance(ptr_instance, &ici);
+ debug_utils_CreateInstance(ptr_instance, &ici);
+ extensions_create_instance(ptr_instance, &ici);
+
+ *pInstance = created_instance;
+
+ // Finally have the layers in place and everyone has seen
+ // the CreateInstance command go by. This allows the layer's
+ // GetInstanceProcAddr functions to return valid extension functions
+ // if enabled.
+ loaderActivateInstanceLayerExtensions(ptr_instance, *pInstance);
+ }
+
+out:
+
+ if (NULL != ptr_instance) {
+ if (res != VK_SUCCESS) {
+ if (NULL != ptr_instance->next) {
+ loader.instances = ptr_instance->next;
+ }
+ if (NULL != ptr_instance->disp) {
+ loader_instance_heap_free(ptr_instance, ptr_instance->disp);
+ }
+ if (ptr_instance->num_tmp_report_callbacks > 0) {
+ // Remove temporary VK_EXT_debug_report items
+ util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+ ptr_instance->tmp_report_callbacks);
+ util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_report_create_infos,
+ ptr_instance->tmp_report_callbacks);
+ }
+ if (ptr_instance->num_tmp_messengers > 0) {
+ // Remove temporary VK_EXT_debug_utils items
+ util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+ ptr_instance->tmp_messengers);
+ util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos,
+ ptr_instance->tmp_messengers);
+ }
+
+ if (NULL != ptr_instance->expanded_activated_layer_list.list) {
+ loaderDeactivateLayers(ptr_instance, NULL, &ptr_instance->expanded_activated_layer_list);
+ }
+ if (NULL != ptr_instance->app_activated_layer_list.list) {
+ loaderDestroyLayerList(ptr_instance, NULL, &ptr_instance->app_activated_layer_list);
+ }
+
+ loaderDeleteLayerListAndProperties(ptr_instance, &ptr_instance->instance_layer_list);
+ loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_tramp_list);
+ loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list);
+
+ loader_instance_heap_free(ptr_instance, ptr_instance);
+ } else {
+ // Remove temporary VK_EXT_debug_report or VK_EXT_debug_utils items
+ util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+ ptr_instance->tmp_messengers);
+ util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+ ptr_instance->tmp_report_callbacks);
+ }
+
+ if (loaderLocked) {
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ }
+ }
+
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
+ const VkLayerInstanceDispatchTable *disp;
+ struct loader_instance *ptr_instance = NULL;
+ bool callback_setup = false;
+ bool messenger_setup = false;
+
+ if (instance == VK_NULL_HANDLE) {
+ return;
+ }
+
+ disp = loader_get_instance_layer_dispatch(instance);
+
+ loader_platform_thread_lock_mutex(&loader_lock);
+
+ ptr_instance = loader_get_instance(instance);
+
+ if (pAllocator) {
+ ptr_instance->alloc_callbacks = *pAllocator;
+ }
+
+ if (ptr_instance->num_tmp_messengers > 0) {
+ // Setup the temporary VK_EXT_debug_utils messenger(s) here to catch cleanup issues:
+ if (!util_CreateDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+ ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers)) {
+ messenger_setup = true;
+ }
+ }
+
+ if (ptr_instance->num_tmp_report_callbacks > 0) {
+ // Setup the temporary VK_EXT_debug_report callback(s) here to catch cleanup issues:
+ if (!util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+ ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks)) {
+ callback_setup = true;
+ }
+ }
+
+ disp->DestroyInstance(instance, pAllocator);
+
+ if (NULL != ptr_instance->expanded_activated_layer_list.list) {
+ loaderDeactivateLayers(ptr_instance, NULL, &ptr_instance->expanded_activated_layer_list);
+ }
+ if (NULL != ptr_instance->app_activated_layer_list.list) {
+ loaderDestroyLayerList(ptr_instance, NULL, &ptr_instance->app_activated_layer_list);
+ }
+
+ if (ptr_instance->phys_devs_tramp) {
+ for (uint32_t i = 0; i < ptr_instance->phys_dev_count_tramp; i++) {
+ loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_tramp[i]);
+ }
+ loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_tramp);
+ }
+
+ if (ptr_instance->phys_dev_groups_tramp) {
+ for (uint32_t i = 0; i < ptr_instance->phys_dev_group_count_tramp; i++) {
+ loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_tramp[i]);
+ }
+ loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_tramp);
+ }
+
+ if (messenger_setup) {
+ util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers, ptr_instance->tmp_messengers);
+ util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers);
+ }
+
+ if (callback_setup) {
+ util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+ ptr_instance->tmp_report_callbacks);
+ util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks);
+ }
+ loader_instance_heap_free(ptr_instance, ptr_instance->disp);
+ loader_instance_heap_free(ptr_instance, ptr_instance);
+ loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
+ VkPhysicalDevice *pPhysicalDevices) {
+ VkResult res = VK_SUCCESS;
+ uint32_t count;
+ uint32_t i;
+ struct loader_instance *inst;
+
+ loader_platform_thread_lock_mutex(&loader_lock);
+
+ inst = loader_get_instance(instance);
+ if (NULL == inst) {
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ if (NULL == pPhysicalDeviceCount) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "vkEnumeratePhysicalDevices: Received NULL pointer for physical device count return value.");
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ // Setup the trampoline loader physical devices. This will actually
+ // call down and setup the terminator loader physical devices during the
+ // process.
+ VkResult setup_res = setupLoaderTrampPhysDevs(instance);
+ if (setup_res != VK_SUCCESS && setup_res != VK_INCOMPLETE) {
+ res = setup_res;
+ goto out;
+ }
+
+ count = inst->phys_dev_count_tramp;
+
+ // Wrap the PhysDev object for loader usage, return wrapped objects
+ if (NULL != pPhysicalDevices) {
+ if (inst->phys_dev_count_tramp > *pPhysicalDeviceCount) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkEnumeratePhysicalDevices: Trimming device count down"
+ " by application request from %d to %d physical devices",
+ inst->phys_dev_count_tramp, *pPhysicalDeviceCount);
+ count = *pPhysicalDeviceCount;
+ res = VK_INCOMPLETE;
+ }
+ for (i = 0; i < count; i++) {
+ pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_tramp[i];
+ }
+ }
+
+ *pPhysicalDeviceCount = count;
+
+out:
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures *pFeatures) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceFeatures(unwrapped_phys_dev, pFeatures);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
+ VkFormatProperties *pFormatInfo) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_pd = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceFormatProperties(unwrapped_pd, format, pFormatInfo);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties(
+ VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage,
+ VkImageCreateFlags flags, VkImageFormatProperties *pImageFormatProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceImageFormatProperties(unwrapped_phys_dev, format, type, tiling, usage, flags,
+ pImageFormatProperties);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties *pProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceProperties(unwrapped_phys_dev, pProperties);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
+ uint32_t *pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties *pQueueProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceQueueFamilyProperties(unwrapped_phys_dev, pQueueFamilyPropertyCount, pQueueProperties);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceMemoryProperties(unwrapped_phys_dev, pMemoryProperties);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
+ loader_platform_thread_lock_mutex(&loader_lock);
+ VkResult res = loader_layer_create_device(NULL, physicalDevice, pCreateInfo, pAllocator, pDevice, NULL, NULL);
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ if (device == VK_NULL_HANDLE) {
+ return;
+ }
+ disp = loader_get_dispatch(device);
+
+ loader_platform_thread_lock_mutex(&loader_lock);
+
+ loader_layer_destroy_device(device, pAllocator, disp->DestroyDevice);
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
+ const char *pLayerName, uint32_t *pPropertyCount,
+ VkExtensionProperties *pProperties) {
+ VkResult res = VK_SUCCESS;
+ struct loader_physical_device_tramp *phys_dev;
+ const VkLayerInstanceDispatchTable *disp;
+ phys_dev = (struct loader_physical_device_tramp *)physicalDevice;
+
+ loader_platform_thread_lock_mutex(&loader_lock);
+
+ // always pass this call down the instance chain which will terminate
+ // in the ICD. This allows layers to filter the extensions coming back
+ // up the chain. In the terminator we look up layer extensions from the
+ // manifest file if it wasn't provided by the layer itself.
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ res = disp->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, pLayerName, pPropertyCount, pProperties);
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkLayerProperties *pProperties) {
+ uint32_t copy_size;
+ struct loader_physical_device_tramp *phys_dev;
+ struct loader_layer_list *enabled_layers, layers_list;
+ memset(&layers_list, 0, sizeof(layers_list));
+ loader_platform_thread_lock_mutex(&loader_lock);
+
+ // Don't dispatch this call down the instance chain, want all device layers
+ // enumerated and instance chain may not contain all device layers
+ // TODO re-evaluate the above statement we maybe able to start calling
+ // down the chain
+
+ phys_dev = (struct loader_physical_device_tramp *)physicalDevice;
+ const struct loader_instance *inst = phys_dev->this_instance;
+
+ uint32_t count = inst->app_activated_layer_list.count;
+ if (count == 0 || pProperties == NULL) {
+ *pPropertyCount = count;
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return VK_SUCCESS;
+ }
+ enabled_layers = (struct loader_layer_list *)&inst->app_activated_layer_list;
+
+ copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
+ for (uint32_t i = 0; i < copy_size; i++) {
+ memcpy(&pProperties[i], &(enabled_layers->list[i].info), sizeof(VkLayerProperties));
+ }
+ *pPropertyCount = copy_size;
+
+ if (copy_size < count) {
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return VK_INCOMPLETE;
+ }
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return VK_SUCCESS;
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(VkDevice device, uint32_t queueNodeIndex, uint32_t queueIndex,
+ VkQueue *pQueue) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue);
+ loader_set_dispatch(*pQueue, disp);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits,
+ VkFence fence) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(queue);
+
+ return disp->QueueSubmit(queue, submitCount, pSubmits, fence);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(VkQueue queue) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(queue);
+
+ return disp->QueueWaitIdle(queue);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->DeviceWaitIdle(device);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->AllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkFreeMemory(VkDevice device, VkDeviceMemory mem,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->FreeMemory(device, mem, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset,
+ VkDeviceSize size, VkFlags flags, void **ppData) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->MapMemory(device, mem, offset, size, flags, ppData);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkUnmapMemory(VkDevice device, VkDeviceMemory mem) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->UnmapMemory(device, mem);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
+ const VkMappedMemoryRange *pMemoryRanges) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->FlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
+ const VkMappedMemoryRange *pMemoryRanges) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->InvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory,
+ VkDeviceSize *pCommittedMemoryInBytes) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->GetDeviceMemoryCommitment(device, memory, pCommittedMemoryInBytes);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem,
+ VkDeviceSize offset) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->BindBufferMemory(device, buffer, mem, offset);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem,
+ VkDeviceSize offset) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->BindImageMemory(device, image, mem, offset);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer,
+ VkMemoryRequirements *pMemoryRequirements) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->GetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements(VkDevice device, VkImage image,
+ VkMemoryRequirements *pMemoryRequirements) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->GetImageMemoryRequirements(device, image, pMemoryRequirements);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
+vkGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t *pSparseMemoryRequirementCount,
+ VkSparseImageMemoryRequirements *pSparseMemoryRequirements) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->GetImageSparseMemoryRequirements(device, image, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties(
+ VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage,
+ VkImageTiling tiling, uint32_t *pPropertyCount, VkSparseImageFormatProperties *pProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+
+ disp->GetPhysicalDeviceSparseImageFormatProperties(unwrapped_phys_dev, format, type, samples, usage, tiling, pPropertyCount,
+ pProperties);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount,
+ const VkBindSparseInfo *pBindInfo, VkFence fence) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(queue);
+
+ return disp->QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkFence *pFence) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateFence(device, pCreateInfo, pAllocator, pFence);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyFence(device, fence, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->ResetFences(device, fenceCount, pFences);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(VkDevice device, VkFence fence) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->GetFenceStatus(device, fence);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences,
+ VkBool32 waitAll, uint64_t timeout) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->WaitForFences(device, fenceCount, pFences, waitAll, timeout);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore(VkDevice device, VkSemaphore semaphore,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroySemaphore(device, semaphore, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateEvent(device, pCreateInfo, pAllocator, pEvent);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyEvent(device, event, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus(VkDevice device, VkEvent event) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->GetEventStatus(device, event);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(VkDevice device, VkEvent event) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->SetEvent(device, event);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent(VkDevice device, VkEvent event) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->ResetEvent(device, event);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyQueryPool(device, queryPool, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery,
+ uint32_t queryCount, size_t dataSize, void *pData,
+ VkDeviceSize stride, VkQueryResultFlags flags) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer(VkDevice device, VkBuffer buffer,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyBuffer(device, buffer, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkBufferView *pView) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateBufferView(device, pCreateInfo, pAllocator, pView);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView(VkDevice device, VkBufferView bufferView,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyBufferView(device, bufferView, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateImage(device, pCreateInfo, pAllocator, pImage);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyImage(device, image, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout(VkDevice device, VkImage image,
+ const VkImageSubresource *pSubresource,
+ VkSubresourceLayout *pLayout) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->GetImageSubresourceLayout(device, image, pSubresource, pLayout);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateImageView(device, pCreateInfo, pAllocator, pView);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyImageView(VkDevice device, VkImageView imageView,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyImageView(device, imageView, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkShaderModule *pShader) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateShaderModule(device, pCreateInfo, pAllocator, pShader);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyShaderModule(device, shaderModule, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkPipelineCache *pPipelineCache) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyPipelineCache(device, pipelineCache, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache,
+ size_t *pDataSize, void *pData) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache,
+ uint32_t srcCacheCount, const VkPipelineCache *pSrcCaches) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache,
+ uint32_t createInfoCount,
+ const VkGraphicsPipelineCreateInfo *pCreateInfos,
+ const VkAllocationCallbacks *pAllocator,
+ VkPipeline *pPipelines) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache,
+ uint32_t createInfoCount,
+ const VkComputePipelineCreateInfo *pCreateInfos,
+ const VkAllocationCallbacks *pAllocator,
+ VkPipeline *pPipelines) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline(VkDevice device, VkPipeline pipeline,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyPipeline(device, pipeline, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkPipelineLayout *pPipelineLayout) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyPipelineLayout(device, pipelineLayout, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateSampler(device, pCreateInfo, pAllocator, pSampler);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySampler(VkDevice device, VkSampler sampler,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroySampler(device, sampler, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout(VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDescriptorSetLayout *pSetLayout) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDescriptorPool *pDescriptorPool) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyDescriptorPool(device, descriptorPool, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
+ VkDescriptorPoolResetFlags flags) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->ResetDescriptorPool(device, descriptorPool, flags);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAllocateDescriptorSets(VkDevice device,
+ const VkDescriptorSetAllocateInfo *pAllocateInfo,
+ VkDescriptorSet *pDescriptorSets) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet *pDescriptorSets) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->FreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
+ const VkWriteDescriptorSet *pDescriptorWrites,
+ uint32_t descriptorCopyCount,
+ const VkCopyDescriptorSet *pDescriptorCopies) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkFramebuffer *pFramebuffer) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyFramebuffer(device, framebuffer, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkRenderPass *pRenderPass) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyRenderPass(device, renderPass, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass,
+ VkExtent2D *pGranularity) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->GetRenderAreaGranularity(device, renderPass, pGranularity);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkCommandPool *pCommandPool) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->DestroyCommandPool(device, commandPool, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool(VkDevice device, VkCommandPool commandPool,
+ VkCommandPoolResetFlags flags) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ return disp->ResetCommandPool(device, commandPool, flags);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers(VkDevice device,
+ const VkCommandBufferAllocateInfo *pAllocateInfo,
+ VkCommandBuffer *pCommandBuffers) {
+ const VkLayerDispatchTable *disp;
+ VkResult res;
+
+ disp = loader_get_dispatch(device);
+
+ res = disp->AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers);
+ if (res == VK_SUCCESS) {
+ for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
+ if (pCommandBuffers[i]) {
+ loader_init_dispatch(pCommandBuffers[i], disp);
+ }
+ }
+ }
+
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
+ uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(device);
+
+ disp->FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer(VkCommandBuffer commandBuffer,
+ const VkCommandBufferBeginInfo *pBeginInfo) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ return disp->BeginCommandBuffer(commandBuffer, pBeginInfo);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ return disp->EndCommandBuffer(commandBuffer);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ return disp->ResetCommandBuffer(commandBuffer, flags);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
+ VkPipeline pipeline) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport,
+ uint32_t viewportCount, const VkViewport *pViewports) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor,
+ uint32_t scissorCount, const VkRect2D *pScissors) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdSetLineWidth(commandBuffer, lineWidth);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor,
+ float depthBiasClamp, float depthBiasSlopeFactor) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdSetBlendConstants(commandBuffer, blendConstants);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds,
+ float maxDepthBounds) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
+ uint32_t compareMask) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
+ uint32_t writeMask) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
+ uint32_t reference) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdSetStencilReference(commandBuffer, faceMask, reference);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer,
+ VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
+ uint32_t firstSet, uint32_t descriptorSetCount,
+ const VkDescriptorSet *pDescriptorSets,
+ uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets,
+ dynamicOffsetCount, pDynamicOffsets);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
+ VkIndexType indexType) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding,
+ uint32_t bindingCount, const VkBuffer *pBuffers,
+ const VkDeviceSize *pOffsets) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
+ uint32_t firstVertex, uint32_t firstInstance) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount,
+ uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
+ uint32_t firstInstance) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
+ uint32_t drawCount, uint32_t stride) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
+ VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdDispatch(commandBuffer, x, y, z);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
+ VkDeviceSize offset) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdDispatchIndirect(commandBuffer, buffer, offset);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
+ uint32_t regionCount, const VkBufferCopy *pRegions) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage,
+ VkImageLayout srcImageLayout, VkImage dstImage,
+ VkImageLayout dstImageLayout, uint32_t regionCount,
+ const VkImageCopy *pRegions) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage,
+ VkImageLayout srcImageLayout, VkImage dstImage,
+ VkImageLayout dstImageLayout, uint32_t regionCount,
+ const VkImageBlit *pRegions, VkFilter filter) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
+ VkImageLayout dstImageLayout, uint32_t regionCount,
+ const VkBufferImageCopy *pRegions) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
+ VkImageLayout srcImageLayout, VkBuffer dstBuffer,
+ uint32_t regionCount, const VkBufferImageCopy *pRegions) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
+ VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
+ VkDeviceSize size, uint32_t data) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
+ VkImageLayout imageLayout, const VkClearColorValue *pColor,
+ uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image,
+ VkImageLayout imageLayout,
+ const VkClearDepthStencilValue *pDepthStencil,
+ uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
+ const VkClearAttachment *pAttachments, uint32_t rectCount,
+ const VkClearRect *pRects) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage,
+ VkImageLayout srcImageLayout, VkImage dstImage,
+ VkImageLayout dstImageLayout, uint32_t regionCount,
+ const VkImageResolve *pRegions) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event,
+ VkPipelineStageFlags stageMask) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdSetEvent(commandBuffer, event, stageMask);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event,
+ VkPipelineStageFlags stageMask) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdResetEvent(commandBuffer, event, stageMask);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
+ VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask,
+ uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier *pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *pImageMemoryBarriers) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers,
+ bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
+ uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier *pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *pImageMemoryBarriers) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers,
+ bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot,
+ VkFlags flags) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdBeginQuery(commandBuffer, queryPool, slot, flags);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdEndQuery(commandBuffer, queryPool, slot);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
+ uint32_t firstQuery, uint32_t queryCount) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage,
+ VkQueryPool queryPool, uint32_t slot) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
+ uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer,
+ VkDeviceSize dstOffset, VkDeviceSize stride, VkFlags flags) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout,
+ VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size,
+ const void *pValues) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass(VkCommandBuffer commandBuffer,
+ const VkRenderPassBeginInfo *pRenderPassBegin,
+ VkSubpassContents contents) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdNextSubpass(commandBuffer, contents);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass(VkCommandBuffer commandBuffer) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdEndRenderPass(commandBuffer);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount,
+ const VkCommandBuffer *pCommandBuffers) {
+ const VkLayerDispatchTable *disp;
+
+ disp = loader_get_dispatch(commandBuffer);
+
+ disp->CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers);
+}
+
+// ---- Vulkan core 1.1 trampolines
+
+VkResult setupLoaderTrampPhysDevGroups(VkInstance instance) {
+ VkResult res = VK_SUCCESS;
+ struct loader_instance *inst;
+ uint32_t total_count = 0;
+ VkPhysicalDeviceGroupPropertiesKHR **new_phys_dev_groups = NULL;
+ VkPhysicalDeviceGroupPropertiesKHR *local_phys_dev_groups = NULL;
+ PFN_vkEnumeratePhysicalDeviceGroups fpEnumeratePhysicalDeviceGroups = NULL;
+
+ inst = loader_get_instance(instance);
+ if (NULL == inst) {
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ // Get the function pointer to use to call into the ICD. This could be the core or KHR version
+ if (inst->enabled_known_extensions.khr_device_group_creation) {
+ fpEnumeratePhysicalDeviceGroups = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroupsKHR;
+ } else {
+ fpEnumeratePhysicalDeviceGroups = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroups;
+ }
+
+ // Setup the trampoline loader physical devices. This will actually
+ // call down and setup the terminator loader physical devices during the
+ // process.
+ VkResult setup_res = setupLoaderTrampPhysDevs(instance);
+ if (setup_res != VK_SUCCESS && setup_res != VK_INCOMPLETE) {
+ res = setup_res;
+ goto out;
+ }
+
+ // Query how many physical device groups there
+ res = fpEnumeratePhysicalDeviceGroups(instance, &total_count, NULL);
+ if (res != VK_SUCCESS) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevGroups: Failed during dispatch call of "
+ "\'EnumeratePhysicalDeviceGroupsKHR\' to lower layers or "
+ "loader to get count.");
+ goto out;
+ }
+
+ // Create an array for the new physical device groups, which will be stored
+ // in the instance for the trampoline code.
+ new_phys_dev_groups = (VkPhysicalDeviceGroupPropertiesKHR **)loader_instance_heap_alloc(
+ inst, total_count * sizeof(VkPhysicalDeviceGroupPropertiesKHR *), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_phys_dev_groups) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevGroups: Failed to allocate new physical device"
+ " group array of size %d",
+ total_count);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memset(new_phys_dev_groups, 0, total_count * sizeof(VkPhysicalDeviceGroupPropertiesKHR *));
+
+ // Create a temporary array (on the stack) to keep track of the
+ // returned VkPhysicalDevice values.
+ local_phys_dev_groups = loader_stack_alloc(sizeof(VkPhysicalDeviceGroupPropertiesKHR) * total_count);
+ if (NULL == local_phys_dev_groups) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevGroups: Failed to allocate local "
+ "physical device group array of size %d",
+ total_count);
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ // Initialize the memory to something valid
+ memset(local_phys_dev_groups, 0, sizeof(VkPhysicalDeviceGroupPropertiesKHR) * total_count);
+ for (uint32_t group = 0; group < total_count; group++) {
+ local_phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR;
+ local_phys_dev_groups[group].pNext = NULL;
+ local_phys_dev_groups[group].subsetAllocation = false;
+ }
+
+ // Call down and get the content
+ fpEnumeratePhysicalDeviceGroups(instance, &total_count, local_phys_dev_groups);
+ if (VK_SUCCESS != res) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevGroups: Failed during dispatch call of "
+ "\'EnumeratePhysicalDeviceGroupsKHR\' to lower layers or "
+ "loader to get content.");
+ goto out;
+ }
+
+ // Replace all the physical device IDs with the proper loader values
+ for (uint32_t group = 0; group < total_count; group++) {
+ for (uint32_t group_gpu = 0; group_gpu < local_phys_dev_groups[group].physicalDeviceCount; group_gpu++) {
+ bool found = false;
+ for (uint32_t tramp_gpu = 0; tramp_gpu < inst->phys_dev_count_tramp; tramp_gpu++) {
+ if (local_phys_dev_groups[group].physicalDevices[group_gpu] == inst->phys_devs_tramp[tramp_gpu]->phys_dev) {
+ local_phys_dev_groups[group].physicalDevices[group_gpu] = (VkPhysicalDevice)inst->phys_devs_tramp[tramp_gpu];
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevGroups: Failed to find GPU %d in group %d"
+ " returned by \'EnumeratePhysicalDeviceGroupsKHR\' in list returned"
+ " by \'EnumeratePhysicalDevices\'", group_gpu, group);
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+ }
+ }
+
+ // Copy or create everything to fill the new array of physical device groups
+ for (uint32_t new_idx = 0; new_idx < total_count; new_idx++) {
+ // Check if this physical device group with the same contents is already in the old buffer
+ for (uint32_t old_idx = 0; old_idx < inst->phys_dev_group_count_tramp; old_idx++) {
+ if (local_phys_dev_groups[new_idx].physicalDeviceCount == inst->phys_dev_groups_tramp[old_idx]->physicalDeviceCount) {
+ bool found_all_gpus = true;
+ for (uint32_t old_gpu = 0; old_gpu < inst->phys_dev_groups_tramp[old_idx]->physicalDeviceCount; old_gpu++) {
+ bool found_gpu = false;
+ for (uint32_t new_gpu = 0; new_gpu < local_phys_dev_groups[new_idx].physicalDeviceCount; new_gpu++) {
+ if (local_phys_dev_groups[new_idx].physicalDevices[new_gpu] == inst->phys_dev_groups_tramp[old_idx]->physicalDevices[old_gpu]) {
+ found_gpu = true;
+ break;
+ }
+ }
+
+ if (!found_gpu) {
+ found_all_gpus = false;
+ break;
+ }
+ }
+ if (!found_all_gpus) {
+ continue;
+ } else {
+ new_phys_dev_groups[new_idx] = inst->phys_dev_groups_tramp[old_idx];
+ break;
+ }
+ }
+ }
+
+ // If this physical device group isn't in the old buffer, create it
+ if (NULL == new_phys_dev_groups[new_idx]) {
+ new_phys_dev_groups[new_idx] = (VkPhysicalDeviceGroupPropertiesKHR *)loader_instance_heap_alloc(
+ inst, sizeof(VkPhysicalDeviceGroupPropertiesKHR), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_phys_dev_groups[new_idx]) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "setupLoaderTrampPhysDevGroups: Failed to allocate "
+ "physical device group trampoline object %d",
+ new_idx);
+ total_count = new_idx;
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memcpy(new_phys_dev_groups[new_idx], &local_phys_dev_groups[new_idx],
+ sizeof(VkPhysicalDeviceGroupPropertiesKHR));
+ }
+ }
+
+out:
+
+ if (VK_SUCCESS != res) {
+ if (NULL != new_phys_dev_groups) {
+ for (uint32_t i = 0; i < total_count; i++) {
+ loader_instance_heap_free(inst, new_phys_dev_groups[i]);
+ }
+ loader_instance_heap_free(inst, new_phys_dev_groups);
+ }
+ total_count = 0;
+ } else {
+ // Free everything that didn't carry over to the new array of
+ // physical device groups
+ if (NULL != inst->phys_dev_groups_tramp) {
+ for (uint32_t i = 0; i < inst->phys_dev_group_count_tramp; i++) {
+ bool found = false;
+ for (uint32_t j = 0; j < total_count; j++) {
+ if (inst->phys_dev_groups_tramp[i] == new_phys_dev_groups[j]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ loader_instance_heap_free(inst, inst->phys_dev_groups_tramp[i]);
+ }
+ }
+ loader_instance_heap_free(inst, inst->phys_dev_groups_tramp);
+ }
+
+ // Swap in the new physical device group list
+ inst->phys_dev_group_count_tramp = total_count;
+ inst->phys_dev_groups_tramp = new_phys_dev_groups;
+ }
+
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups(
+ VkInstance instance, uint32_t *pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties) {
+ VkResult res = VK_SUCCESS;
+ uint32_t count;
+ uint32_t i;
+ struct loader_instance *inst = NULL;
+
+ loader_platform_thread_lock_mutex(&loader_lock);
+
+ inst = loader_get_instance(instance);
+ if (NULL == inst) {
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ if (NULL == pPhysicalDeviceGroupCount) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "vkEnumeratePhysicalDeviceGroupsKHR: Received NULL pointer for physical "
+ "device group count return value.");
+ res = VK_ERROR_INITIALIZATION_FAILED;
+ goto out;
+ }
+
+ VkResult setup_res = setupLoaderTrampPhysDevGroups(instance);
+ if (VK_SUCCESS != setup_res) {
+ res = setup_res;
+ goto out;
+ }
+
+ count = inst->phys_dev_group_count_tramp;
+
+ // Wrap the PhysDev object for loader usage, return wrapped objects
+ if (NULL != pPhysicalDeviceGroupProperties) {
+ if (inst->phys_dev_group_count_tramp > *pPhysicalDeviceGroupCount) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkEnumeratePhysicalDeviceGroupsKHR: Trimming device group count down"
+ " by application request from %d to %d physical device groups",
+ inst->phys_dev_group_count_tramp, *pPhysicalDeviceGroupCount);
+ count = *pPhysicalDeviceGroupCount;
+ res = VK_INCOMPLETE;
+ }
+ for (i = 0; i < count; i++) {
+ memcpy(&pPhysicalDeviceGroupProperties[i], inst->phys_dev_groups_tramp[i],
+ sizeof(VkPhysicalDeviceGroupPropertiesKHR));
+ }
+ }
+
+ *pPhysicalDeviceGroupCount = count;
+
+out:
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2 *pFeatures) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
+ const struct loader_instance *inst = ((struct loader_physical_device_tramp*) physicalDevice)->this_instance;
+
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ disp->GetPhysicalDeviceFeatures2KHR(unwrapped_phys_dev, pFeatures);
+ } else {
+ disp->GetPhysicalDeviceFeatures2(unwrapped_phys_dev, pFeatures);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2 *pProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
+ const struct loader_instance *inst = ((struct loader_physical_device_tramp*) physicalDevice)->this_instance;
+
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ disp->GetPhysicalDeviceProperties2KHR(unwrapped_phys_dev, pProperties);
+ } else {
+ disp->GetPhysicalDeviceProperties2(unwrapped_phys_dev, pProperties);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format,
+ VkFormatProperties2 *pFormatProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
+ const struct loader_instance *inst = ((struct loader_physical_device_tramp*) physicalDevice)->this_instance;
+
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ disp->GetPhysicalDeviceFormatProperties2KHR(unwrapped_phys_dev, format, pFormatProperties);
+ } else {
+ disp->GetPhysicalDeviceFormatProperties2(unwrapped_phys_dev, format, pFormatProperties);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
+ VkImageFormatProperties2 *pImageFormatProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
+ const struct loader_instance *inst = ((struct loader_physical_device_tramp*) physicalDevice)->this_instance;
+
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ return disp->GetPhysicalDeviceImageFormatProperties2KHR(unwrapped_phys_dev, pImageFormatInfo, pImageFormatProperties);
+ } else {
+ return disp->GetPhysicalDeviceImageFormatProperties2(unwrapped_phys_dev, pImageFormatInfo, pImageFormatProperties);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
+ uint32_t *pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2 *pQueueFamilyProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
+ const struct loader_instance *inst = ((struct loader_physical_device_tramp*) physicalDevice)->this_instance;
+
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ disp->GetPhysicalDeviceQueueFamilyProperties2KHR(unwrapped_phys_dev, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+ } else {
+ disp->GetPhysicalDeviceQueueFamilyProperties2(unwrapped_phys_dev, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2 *pMemoryProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
+ const struct loader_instance *inst = ((struct loader_physical_device_tramp*) physicalDevice)->this_instance;
+
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ disp->GetPhysicalDeviceMemoryProperties2KHR(unwrapped_phys_dev, pMemoryProperties);
+ } else {
+ disp->GetPhysicalDeviceMemoryProperties2(unwrapped_phys_dev, pMemoryProperties);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo, uint32_t *pPropertyCount,
+ VkSparseImageFormatProperties2 *pProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
+ const struct loader_instance *inst = ((struct loader_physical_device_tramp*) physicalDevice)->this_instance;
+
+ if (inst != NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
+ disp->GetPhysicalDeviceSparseImageFormatProperties2KHR(unwrapped_phys_dev, pFormatInfo, pPropertyCount, pProperties);
+ } else {
+ disp->GetPhysicalDeviceSparseImageFormatProperties2(unwrapped_phys_dev, pFormatInfo, pPropertyCount, pProperties);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferProperties(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
+ VkExternalBufferProperties *pExternalBufferProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
+ const struct loader_instance *inst = ((struct loader_physical_device_tramp*) physicalDevice)->this_instance;
+
+ if (inst != NULL && inst->enabled_known_extensions.khr_external_memory_capabilities){
+ disp->GetPhysicalDeviceExternalBufferPropertiesKHR(unwrapped_phys_dev, pExternalBufferInfo, pExternalBufferProperties);
+ } else {
+ disp->GetPhysicalDeviceExternalBufferProperties(unwrapped_phys_dev, pExternalBufferInfo, pExternalBufferProperties);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfoKHR *pExternalSemaphoreInfo,
+ VkExternalSemaphoreProperties *pExternalSemaphoreProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
+ const struct loader_instance *inst = ((struct loader_physical_device_tramp*) physicalDevice)->this_instance;
+
+ if (inst != NULL && inst->enabled_known_extensions.khr_external_semaphore_capabilities) {
+ disp->GetPhysicalDeviceExternalSemaphorePropertiesKHR(unwrapped_phys_dev, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+ } else {
+ disp->GetPhysicalDeviceExternalSemaphoreProperties(unwrapped_phys_dev, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties(
+ VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
+ VkExternalFenceProperties *pExternalFenceProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
+ const struct loader_instance *inst = ((struct loader_physical_device_tramp*) physicalDevice)->this_instance;
+
+ if (inst != NULL && inst->enabled_known_extensions.khr_external_fence_capabilities) {
+ disp->GetPhysicalDeviceExternalFencePropertiesKHR(unwrapped_phys_dev, pExternalFenceInfo, pExternalFenceProperties);
+ } else {
+ disp->GetPhysicalDeviceExternalFenceProperties(unwrapped_phys_dev, pExternalFenceInfo, pExternalFenceProperties);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindBufferMemoryInfo* pBindInfos) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->BindBufferMemory2(device, bindInfoCount, pBindInfos);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindImageMemoryInfo* pBindInfos) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->BindImageMemory2(device, bindInfoCount, pBindInfos);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeatures(
+ VkDevice device,
+ uint32_t heapIndex,
+ uint32_t localDeviceIndex,
+ uint32_t remoteDeviceIndex,
+ VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetDeviceGroupPeerMemoryFeatures(device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMask(
+ VkCommandBuffer commandBuffer,
+ uint32_t deviceMask) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdSetDeviceMask(commandBuffer, deviceMask);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBase(
+ VkCommandBuffer commandBuffer,
+ uint32_t baseGroupX,
+ uint32_t baseGroupY,
+ uint32_t baseGroupZ,
+ uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2(
+ VkDevice device,
+ const VkImageMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetImageMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2(
+ VkDevice device,
+ const VkBufferMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2(
+ VkDevice device,
+ const VkImageSparseMemoryRequirementsInfo2* pInfo,
+ uint32_t* pSparseMemoryRequirementCount,
+ VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetImageSparseMemoryRequirements2(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkTrimCommandPool(
+ VkDevice device,
+ VkCommandPool commandPool,
+ VkCommandPoolTrimFlags flags) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->TrimCommandPool(device, commandPool, flags);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2 *pQueueInfo, VkQueue *pQueue) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetDeviceQueue2(device, pQueueInfo, pQueue);
+ if (*pQueue != VK_NULL_HANDLE)
+ {
+ loader_set_dispatch(*pQueue, disp);
+ }
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion(
+ VkDevice device,
+ const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSamplerYcbcrConversion* pYcbcrConversion) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion(
+ VkDevice device,
+ VkSamplerYcbcrConversion ycbcrConversion,
+ const VkAllocationCallbacks* pAllocator) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->DestroySamplerYcbcrConversion(device, ycbcrConversion, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport(
+ VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ VkDescriptorSetLayoutSupport* pSupport) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
+vkCreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateDescriptorUpdateTemplate(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplate(VkDevice device,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const void *pData) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
+}
+
+// ---- Vulkan core 1.2 trampolines
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateRenderPass2(device, pCreateInfo, pAllocator, pRenderPass);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2(VkCommandBuffer commandBuffer,
+ const VkRenderPassBeginInfo* pRenderPassBegin,
+ const VkSubpassBeginInfo* pSubpassBeginInfo)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdBeginRenderPass2(commandBuffer, pRenderPassBegin, pSubpassBeginInfo);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2(VkCommandBuffer commandBuffer,
+ const VkSubpassBeginInfo* pSubpassBeginInfo,
+ const VkSubpassEndInfo* pSubpassEndInfo)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdNextSubpass2(commandBuffer, pSubpassBeginInfo, pSubpassEndInfo);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdEndRenderPass2(commandBuffer, pSubpassEndInfo);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
+ VkBuffer countBuffer, VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount, uint32_t stride)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer,
+ VkDeviceSize offset, VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
+ uint32_t stride)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValue(VkDevice device, VkSemaphore semaphore, uint64_t* pValue)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetSemaphoreCounterValue(device, semaphore, pValue);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphores(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo,
+ uint64_t timeout)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->WaitSemaphores(device, pWaitInfo, timeout);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphore(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->SignalSemaphore(device, pSignalInfo);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddress(VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetBufferDeviceAddress(device, pInfo);
+}
+
+LOADER_EXPORT VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddress(VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetBufferOpaqueCaptureAddress(device, pInfo);
+}
+
+LOADER_EXPORT VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddress(VkDevice device,
+ const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetDeviceMemoryOpaqueCaptureAddress(device, pInfo);
+}
+
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkResetQueryPool(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery,
+ uint32_t queryCount)
+{
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->ResetQueryPool(device, queryPool, firstQuery, queryCount);
+}
diff --git a/thirdparty/vulkan/loader/unknown_ext_chain.c b/thirdparty/vulkan/loader/unknown_ext_chain.c
new file mode 100644
index 0000000000..1c8560dd61
--- /dev/null
+++ b/thirdparty/vulkan/loader/unknown_ext_chain.c
@@ -0,0 +1,819 @@
+/*
+ * Copyright (c) 2017 The Khronos Group Inc.
+ * Copyright (c) 2017 Valve Corporation
+ * Copyright (c) 2017 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author Jon Ashburn <jon@lunarg.com>
+ * Author: Lenny Komow <lenny@lunarg.com>
+ */
+
+ // This code is used to pass on physical device extensions through the call chain. It must do this without creating a stack frame,
+ // because the actual parameters of the call are not known. Since the first parameter is known to be a VkPhysicalDevice, it can
+// unwrap the physical device, overwriting the wrapped device, and then jump to the next function in the call chain. This code
+// attempts to accomplish this by relying on tail-call optimizations, but there is no guarantee that this will work. As a result,
+// this code is only compiled on systems where an assembly alternative has not been written.
+
+ #include "vk_loader_platform.h"
+ #include "loader.h"
+
+ #if defined(__GNUC__) && !defined(__clang__)
+ #pragma GCC optimize(3) // force gcc to use tail-calls
+ #endif
+
+ // Trampoline function macro for unknown physical device extension command.
+ #define PhysDevExtTramp(num) \
+ VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp##num(VkPhysicalDevice physical_device) { \
+ const struct loader_instance_dispatch_table *disp; \
+ disp = loader_get_instance_dispatch(physical_device); \
+ disp->phys_dev_ext[num](loader_unwrap_physical_device(physical_device)); \
+ }
+
+// Terminator function macro for unknown physical device extension command.
+#define PhysDevExtTermin(num) \
+ VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin##num(VkPhysicalDevice physical_device) { \
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physical_device; \
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; \
+ struct loader_instance *inst = (struct loader_instance *)icd_term->this_instance; \
+ if (NULL == icd_term->phys_dev_ext[num]) { \
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Extension %s not supported for this physical device", \
+ inst->phys_dev_ext_disp_hash[num].func_name); \
+ } \
+ icd_term->phys_dev_ext[num](phys_dev_term->phys_dev); \
+ }
+
+// Trampoline function macro for unknown physical device extension command.
+#define DevExtTramp(num) \
+ VKAPI_ATTR void VKAPI_CALL vkdev_ext##num(VkDevice device) { \
+ const struct loader_dev_dispatch_table *disp; \
+ disp = loader_get_dev_dispatch(device); \
+ disp->ext_dispatch.dev_ext[num](device); \
+ }
+
+
+// Instantiations of the trampoline
+PhysDevExtTramp(0)
+PhysDevExtTramp(1)
+PhysDevExtTramp(2)
+PhysDevExtTramp(3)
+PhysDevExtTramp(4)
+PhysDevExtTramp(5)
+PhysDevExtTramp(6)
+PhysDevExtTramp(7)
+PhysDevExtTramp(8)
+PhysDevExtTramp(9)
+PhysDevExtTramp(10)
+PhysDevExtTramp(11)
+PhysDevExtTramp(12)
+PhysDevExtTramp(13)
+PhysDevExtTramp(14)
+PhysDevExtTramp(15)
+PhysDevExtTramp(16)
+PhysDevExtTramp(17)
+PhysDevExtTramp(18)
+PhysDevExtTramp(19)
+PhysDevExtTramp(20)
+PhysDevExtTramp(21)
+PhysDevExtTramp(22)
+PhysDevExtTramp(23)
+PhysDevExtTramp(24)
+PhysDevExtTramp(25)
+PhysDevExtTramp(26)
+PhysDevExtTramp(27)
+PhysDevExtTramp(28)
+PhysDevExtTramp(29)
+PhysDevExtTramp(30)
+PhysDevExtTramp(31)
+PhysDevExtTramp(32)
+PhysDevExtTramp(33)
+PhysDevExtTramp(34)
+PhysDevExtTramp(35)
+PhysDevExtTramp(36)
+PhysDevExtTramp(37)
+PhysDevExtTramp(38)
+PhysDevExtTramp(39)
+PhysDevExtTramp(40)
+PhysDevExtTramp(41)
+PhysDevExtTramp(42)
+PhysDevExtTramp(43)
+PhysDevExtTramp(44)
+PhysDevExtTramp(45)
+PhysDevExtTramp(46)
+PhysDevExtTramp(47)
+PhysDevExtTramp(48)
+PhysDevExtTramp(49)
+PhysDevExtTramp(50)
+PhysDevExtTramp(51)
+PhysDevExtTramp(52)
+PhysDevExtTramp(53)
+PhysDevExtTramp(54)
+PhysDevExtTramp(55)
+PhysDevExtTramp(56)
+PhysDevExtTramp(57)
+PhysDevExtTramp(58)
+PhysDevExtTramp(59)
+PhysDevExtTramp(60)
+PhysDevExtTramp(61)
+PhysDevExtTramp(62)
+PhysDevExtTramp(63)
+PhysDevExtTramp(64)
+PhysDevExtTramp(65)
+PhysDevExtTramp(66)
+PhysDevExtTramp(67)
+PhysDevExtTramp(68)
+PhysDevExtTramp(69)
+PhysDevExtTramp(70)
+PhysDevExtTramp(71)
+PhysDevExtTramp(72)
+PhysDevExtTramp(73)
+PhysDevExtTramp(74)
+PhysDevExtTramp(75)
+PhysDevExtTramp(76)
+PhysDevExtTramp(77)
+PhysDevExtTramp(78)
+PhysDevExtTramp(79)
+PhysDevExtTramp(80)
+PhysDevExtTramp(81)
+PhysDevExtTramp(82)
+PhysDevExtTramp(83)
+PhysDevExtTramp(84)
+PhysDevExtTramp(85)
+PhysDevExtTramp(86)
+PhysDevExtTramp(87)
+PhysDevExtTramp(88)
+PhysDevExtTramp(89)
+PhysDevExtTramp(90)
+PhysDevExtTramp(91)
+PhysDevExtTramp(92)
+PhysDevExtTramp(93)
+PhysDevExtTramp(94)
+PhysDevExtTramp(95)
+PhysDevExtTramp(96)
+PhysDevExtTramp(97)
+PhysDevExtTramp(98)
+PhysDevExtTramp(99)
+PhysDevExtTramp(100)
+PhysDevExtTramp(101)
+PhysDevExtTramp(102)
+PhysDevExtTramp(103)
+PhysDevExtTramp(104)
+PhysDevExtTramp(105)
+PhysDevExtTramp(106)
+PhysDevExtTramp(107)
+PhysDevExtTramp(108)
+PhysDevExtTramp(109)
+PhysDevExtTramp(110)
+PhysDevExtTramp(111)
+PhysDevExtTramp(112)
+PhysDevExtTramp(113)
+PhysDevExtTramp(114)
+PhysDevExtTramp(115)
+PhysDevExtTramp(116)
+PhysDevExtTramp(117)
+PhysDevExtTramp(118)
+PhysDevExtTramp(119)
+PhysDevExtTramp(120)
+PhysDevExtTramp(121)
+PhysDevExtTramp(122)
+PhysDevExtTramp(123)
+PhysDevExtTramp(124)
+PhysDevExtTramp(125)
+PhysDevExtTramp(126)
+PhysDevExtTramp(127)
+PhysDevExtTramp(128)
+PhysDevExtTramp(129)
+PhysDevExtTramp(130)
+PhysDevExtTramp(131)
+PhysDevExtTramp(132)
+PhysDevExtTramp(133)
+PhysDevExtTramp(134)
+PhysDevExtTramp(135)
+PhysDevExtTramp(136)
+PhysDevExtTramp(137)
+PhysDevExtTramp(138)
+PhysDevExtTramp(139)
+PhysDevExtTramp(140)
+PhysDevExtTramp(141)
+PhysDevExtTramp(142)
+PhysDevExtTramp(143)
+PhysDevExtTramp(144)
+PhysDevExtTramp(145)
+PhysDevExtTramp(146)
+PhysDevExtTramp(147)
+PhysDevExtTramp(148)
+PhysDevExtTramp(149)
+PhysDevExtTramp(150)
+PhysDevExtTramp(151)
+PhysDevExtTramp(152)
+PhysDevExtTramp(153)
+PhysDevExtTramp(154)
+PhysDevExtTramp(155)
+PhysDevExtTramp(156)
+PhysDevExtTramp(157)
+PhysDevExtTramp(158)
+PhysDevExtTramp(159)
+PhysDevExtTramp(160)
+PhysDevExtTramp(161)
+PhysDevExtTramp(162)
+PhysDevExtTramp(163)
+PhysDevExtTramp(164)
+PhysDevExtTramp(165)
+PhysDevExtTramp(166)
+PhysDevExtTramp(167)
+PhysDevExtTramp(168)
+PhysDevExtTramp(169)
+PhysDevExtTramp(170)
+PhysDevExtTramp(171)
+PhysDevExtTramp(172)
+PhysDevExtTramp(173)
+PhysDevExtTramp(174)
+PhysDevExtTramp(175)
+PhysDevExtTramp(176)
+PhysDevExtTramp(177)
+PhysDevExtTramp(178)
+PhysDevExtTramp(179)
+PhysDevExtTramp(180)
+PhysDevExtTramp(181)
+PhysDevExtTramp(182)
+PhysDevExtTramp(183)
+PhysDevExtTramp(184)
+PhysDevExtTramp(185)
+PhysDevExtTramp(186)
+PhysDevExtTramp(187)
+PhysDevExtTramp(188)
+PhysDevExtTramp(189)
+PhysDevExtTramp(190)
+PhysDevExtTramp(191)
+PhysDevExtTramp(192)
+PhysDevExtTramp(193)
+PhysDevExtTramp(194)
+PhysDevExtTramp(195)
+PhysDevExtTramp(196)
+PhysDevExtTramp(197)
+PhysDevExtTramp(198)
+PhysDevExtTramp(199)
+PhysDevExtTramp(200)
+PhysDevExtTramp(201)
+PhysDevExtTramp(202)
+PhysDevExtTramp(203)
+PhysDevExtTramp(204)
+PhysDevExtTramp(205)
+PhysDevExtTramp(206)
+PhysDevExtTramp(207)
+PhysDevExtTramp(208)
+PhysDevExtTramp(209)
+PhysDevExtTramp(210)
+PhysDevExtTramp(211)
+PhysDevExtTramp(212)
+PhysDevExtTramp(213)
+PhysDevExtTramp(214)
+PhysDevExtTramp(215)
+PhysDevExtTramp(216)
+PhysDevExtTramp(217)
+PhysDevExtTramp(218)
+PhysDevExtTramp(219)
+PhysDevExtTramp(220)
+PhysDevExtTramp(221)
+PhysDevExtTramp(222)
+PhysDevExtTramp(223)
+PhysDevExtTramp(224)
+PhysDevExtTramp(225)
+PhysDevExtTramp(226)
+PhysDevExtTramp(227)
+PhysDevExtTramp(228)
+PhysDevExtTramp(229)
+PhysDevExtTramp(230)
+PhysDevExtTramp(231)
+PhysDevExtTramp(232)
+PhysDevExtTramp(233)
+PhysDevExtTramp(234)
+PhysDevExtTramp(235)
+PhysDevExtTramp(236)
+PhysDevExtTramp(237)
+PhysDevExtTramp(238)
+PhysDevExtTramp(239)
+PhysDevExtTramp(240)
+PhysDevExtTramp(241)
+PhysDevExtTramp(242)
+PhysDevExtTramp(243)
+PhysDevExtTramp(244)
+PhysDevExtTramp(245)
+PhysDevExtTramp(246)
+PhysDevExtTramp(247)
+PhysDevExtTramp(248)
+PhysDevExtTramp(249)
+
+// Instantiations of the terminator
+PhysDevExtTermin(0)
+PhysDevExtTermin(1)
+PhysDevExtTermin(2)
+PhysDevExtTermin(3)
+PhysDevExtTermin(4)
+PhysDevExtTermin(5)
+PhysDevExtTermin(6)
+PhysDevExtTermin(7)
+PhysDevExtTermin(8)
+PhysDevExtTermin(9)
+PhysDevExtTermin(10)
+PhysDevExtTermin(11)
+PhysDevExtTermin(12)
+PhysDevExtTermin(13)
+PhysDevExtTermin(14)
+PhysDevExtTermin(15)
+PhysDevExtTermin(16)
+PhysDevExtTermin(17)
+PhysDevExtTermin(18)
+PhysDevExtTermin(19)
+PhysDevExtTermin(20)
+PhysDevExtTermin(21)
+PhysDevExtTermin(22)
+PhysDevExtTermin(23)
+PhysDevExtTermin(24)
+PhysDevExtTermin(25)
+PhysDevExtTermin(26)
+PhysDevExtTermin(27)
+PhysDevExtTermin(28)
+PhysDevExtTermin(29)
+PhysDevExtTermin(30)
+PhysDevExtTermin(31)
+PhysDevExtTermin(32)
+PhysDevExtTermin(33)
+PhysDevExtTermin(34)
+PhysDevExtTermin(35)
+PhysDevExtTermin(36)
+PhysDevExtTermin(37)
+PhysDevExtTermin(38)
+PhysDevExtTermin(39)
+PhysDevExtTermin(40)
+PhysDevExtTermin(41)
+PhysDevExtTermin(42)
+PhysDevExtTermin(43)
+PhysDevExtTermin(44)
+PhysDevExtTermin(45)
+PhysDevExtTermin(46)
+PhysDevExtTermin(47)
+PhysDevExtTermin(48)
+PhysDevExtTermin(49)
+PhysDevExtTermin(50)
+PhysDevExtTermin(51)
+PhysDevExtTermin(52)
+PhysDevExtTermin(53)
+PhysDevExtTermin(54)
+PhysDevExtTermin(55)
+PhysDevExtTermin(56)
+PhysDevExtTermin(57)
+PhysDevExtTermin(58)
+PhysDevExtTermin(59)
+PhysDevExtTermin(60)
+PhysDevExtTermin(61)
+PhysDevExtTermin(62)
+PhysDevExtTermin(63)
+PhysDevExtTermin(64)
+PhysDevExtTermin(65)
+PhysDevExtTermin(66)
+PhysDevExtTermin(67)
+PhysDevExtTermin(68)
+PhysDevExtTermin(69)
+PhysDevExtTermin(70)
+PhysDevExtTermin(71)
+PhysDevExtTermin(72)
+PhysDevExtTermin(73)
+PhysDevExtTermin(74)
+PhysDevExtTermin(75)
+PhysDevExtTermin(76)
+PhysDevExtTermin(77)
+PhysDevExtTermin(78)
+PhysDevExtTermin(79)
+PhysDevExtTermin(80)
+PhysDevExtTermin(81)
+PhysDevExtTermin(82)
+PhysDevExtTermin(83)
+PhysDevExtTermin(84)
+PhysDevExtTermin(85)
+PhysDevExtTermin(86)
+PhysDevExtTermin(87)
+PhysDevExtTermin(88)
+PhysDevExtTermin(89)
+PhysDevExtTermin(90)
+PhysDevExtTermin(91)
+PhysDevExtTermin(92)
+PhysDevExtTermin(93)
+PhysDevExtTermin(94)
+PhysDevExtTermin(95)
+PhysDevExtTermin(96)
+PhysDevExtTermin(97)
+PhysDevExtTermin(98)
+PhysDevExtTermin(99)
+PhysDevExtTermin(100)
+PhysDevExtTermin(101)
+PhysDevExtTermin(102)
+PhysDevExtTermin(103)
+PhysDevExtTermin(104)
+PhysDevExtTermin(105)
+PhysDevExtTermin(106)
+PhysDevExtTermin(107)
+PhysDevExtTermin(108)
+PhysDevExtTermin(109)
+PhysDevExtTermin(110)
+PhysDevExtTermin(111)
+PhysDevExtTermin(112)
+PhysDevExtTermin(113)
+PhysDevExtTermin(114)
+PhysDevExtTermin(115)
+PhysDevExtTermin(116)
+PhysDevExtTermin(117)
+PhysDevExtTermin(118)
+PhysDevExtTermin(119)
+PhysDevExtTermin(120)
+PhysDevExtTermin(121)
+PhysDevExtTermin(122)
+PhysDevExtTermin(123)
+PhysDevExtTermin(124)
+PhysDevExtTermin(125)
+PhysDevExtTermin(126)
+PhysDevExtTermin(127)
+PhysDevExtTermin(128)
+PhysDevExtTermin(129)
+PhysDevExtTermin(130)
+PhysDevExtTermin(131)
+PhysDevExtTermin(132)
+PhysDevExtTermin(133)
+PhysDevExtTermin(134)
+PhysDevExtTermin(135)
+PhysDevExtTermin(136)
+PhysDevExtTermin(137)
+PhysDevExtTermin(138)
+PhysDevExtTermin(139)
+PhysDevExtTermin(140)
+PhysDevExtTermin(141)
+PhysDevExtTermin(142)
+PhysDevExtTermin(143)
+PhysDevExtTermin(144)
+PhysDevExtTermin(145)
+PhysDevExtTermin(146)
+PhysDevExtTermin(147)
+PhysDevExtTermin(148)
+PhysDevExtTermin(149)
+PhysDevExtTermin(150)
+PhysDevExtTermin(151)
+PhysDevExtTermin(152)
+PhysDevExtTermin(153)
+PhysDevExtTermin(154)
+PhysDevExtTermin(155)
+PhysDevExtTermin(156)
+PhysDevExtTermin(157)
+PhysDevExtTermin(158)
+PhysDevExtTermin(159)
+PhysDevExtTermin(160)
+PhysDevExtTermin(161)
+PhysDevExtTermin(162)
+PhysDevExtTermin(163)
+PhysDevExtTermin(164)
+PhysDevExtTermin(165)
+PhysDevExtTermin(166)
+PhysDevExtTermin(167)
+PhysDevExtTermin(168)
+PhysDevExtTermin(169)
+PhysDevExtTermin(170)
+PhysDevExtTermin(171)
+PhysDevExtTermin(172)
+PhysDevExtTermin(173)
+PhysDevExtTermin(174)
+PhysDevExtTermin(175)
+PhysDevExtTermin(176)
+PhysDevExtTermin(177)
+PhysDevExtTermin(178)
+PhysDevExtTermin(179)
+PhysDevExtTermin(180)
+PhysDevExtTermin(181)
+PhysDevExtTermin(182)
+PhysDevExtTermin(183)
+PhysDevExtTermin(184)
+PhysDevExtTermin(185)
+PhysDevExtTermin(186)
+PhysDevExtTermin(187)
+PhysDevExtTermin(188)
+PhysDevExtTermin(189)
+PhysDevExtTermin(190)
+PhysDevExtTermin(191)
+PhysDevExtTermin(192)
+PhysDevExtTermin(193)
+PhysDevExtTermin(194)
+PhysDevExtTermin(195)
+PhysDevExtTermin(196)
+PhysDevExtTermin(197)
+PhysDevExtTermin(198)
+PhysDevExtTermin(199)
+PhysDevExtTermin(200)
+PhysDevExtTermin(201)
+PhysDevExtTermin(202)
+PhysDevExtTermin(203)
+PhysDevExtTermin(204)
+PhysDevExtTermin(205)
+PhysDevExtTermin(206)
+PhysDevExtTermin(207)
+PhysDevExtTermin(208)
+PhysDevExtTermin(209)
+PhysDevExtTermin(210)
+PhysDevExtTermin(211)
+PhysDevExtTermin(212)
+PhysDevExtTermin(213)
+PhysDevExtTermin(214)
+PhysDevExtTermin(215)
+PhysDevExtTermin(216)
+PhysDevExtTermin(217)
+PhysDevExtTermin(218)
+PhysDevExtTermin(219)
+PhysDevExtTermin(220)
+PhysDevExtTermin(221)
+PhysDevExtTermin(222)
+PhysDevExtTermin(223)
+PhysDevExtTermin(224)
+PhysDevExtTermin(225)
+PhysDevExtTermin(226)
+PhysDevExtTermin(227)
+PhysDevExtTermin(228)
+PhysDevExtTermin(229)
+PhysDevExtTermin(230)
+PhysDevExtTermin(231)
+PhysDevExtTermin(232)
+PhysDevExtTermin(233)
+PhysDevExtTermin(234)
+PhysDevExtTermin(235)
+PhysDevExtTermin(236)
+PhysDevExtTermin(237)
+PhysDevExtTermin(238)
+PhysDevExtTermin(239)
+PhysDevExtTermin(240)
+PhysDevExtTermin(241)
+PhysDevExtTermin(242)
+PhysDevExtTermin(243)
+PhysDevExtTermin(244)
+PhysDevExtTermin(245)
+PhysDevExtTermin(246)
+PhysDevExtTermin(247)
+PhysDevExtTermin(248)
+PhysDevExtTermin(249)
+
+// Instantiations of the device trampoline
+DevExtTramp(0)
+DevExtTramp(1)
+DevExtTramp(2)
+DevExtTramp(3)
+DevExtTramp(4)
+DevExtTramp(5)
+DevExtTramp(6)
+DevExtTramp(7)
+DevExtTramp(8)
+DevExtTramp(9)
+DevExtTramp(10)
+DevExtTramp(11)
+DevExtTramp(12)
+DevExtTramp(13)
+DevExtTramp(14)
+DevExtTramp(15)
+DevExtTramp(16)
+DevExtTramp(17)
+DevExtTramp(18)
+DevExtTramp(19)
+DevExtTramp(20)
+DevExtTramp(21)
+DevExtTramp(22)
+DevExtTramp(23)
+DevExtTramp(24)
+DevExtTramp(25)
+DevExtTramp(26)
+DevExtTramp(27)
+DevExtTramp(28)
+DevExtTramp(29)
+DevExtTramp(30)
+DevExtTramp(31)
+DevExtTramp(32)
+DevExtTramp(33)
+DevExtTramp(34)
+DevExtTramp(35)
+DevExtTramp(36)
+DevExtTramp(37)
+DevExtTramp(38)
+DevExtTramp(39)
+DevExtTramp(40)
+DevExtTramp(41)
+DevExtTramp(42)
+DevExtTramp(43)
+DevExtTramp(44)
+DevExtTramp(45)
+DevExtTramp(46)
+DevExtTramp(47)
+DevExtTramp(48)
+DevExtTramp(49)
+DevExtTramp(50)
+DevExtTramp(51)
+DevExtTramp(52)
+DevExtTramp(53)
+DevExtTramp(54)
+DevExtTramp(55)
+DevExtTramp(56)
+DevExtTramp(57)
+DevExtTramp(58)
+DevExtTramp(59)
+DevExtTramp(60)
+DevExtTramp(61)
+DevExtTramp(62)
+DevExtTramp(63)
+DevExtTramp(64)
+DevExtTramp(65)
+DevExtTramp(66)
+DevExtTramp(67)
+DevExtTramp(68)
+DevExtTramp(69)
+DevExtTramp(70)
+DevExtTramp(71)
+DevExtTramp(72)
+DevExtTramp(73)
+DevExtTramp(74)
+DevExtTramp(75)
+DevExtTramp(76)
+DevExtTramp(77)
+DevExtTramp(78)
+DevExtTramp(79)
+DevExtTramp(80)
+DevExtTramp(81)
+DevExtTramp(82)
+DevExtTramp(83)
+DevExtTramp(84)
+DevExtTramp(85)
+DevExtTramp(86)
+DevExtTramp(87)
+DevExtTramp(88)
+DevExtTramp(89)
+DevExtTramp(90)
+DevExtTramp(91)
+DevExtTramp(92)
+DevExtTramp(93)
+DevExtTramp(94)
+DevExtTramp(95)
+DevExtTramp(96)
+DevExtTramp(97)
+DevExtTramp(98)
+DevExtTramp(99)
+DevExtTramp(100)
+DevExtTramp(101)
+DevExtTramp(102)
+DevExtTramp(103)
+DevExtTramp(104)
+DevExtTramp(105)
+DevExtTramp(106)
+DevExtTramp(107)
+DevExtTramp(108)
+DevExtTramp(109)
+DevExtTramp(110)
+DevExtTramp(111)
+DevExtTramp(112)
+DevExtTramp(113)
+DevExtTramp(114)
+DevExtTramp(115)
+DevExtTramp(116)
+DevExtTramp(117)
+DevExtTramp(118)
+DevExtTramp(119)
+DevExtTramp(120)
+DevExtTramp(121)
+DevExtTramp(122)
+DevExtTramp(123)
+DevExtTramp(124)
+DevExtTramp(125)
+DevExtTramp(126)
+DevExtTramp(127)
+DevExtTramp(128)
+DevExtTramp(129)
+DevExtTramp(130)
+DevExtTramp(131)
+DevExtTramp(132)
+DevExtTramp(133)
+DevExtTramp(134)
+DevExtTramp(135)
+DevExtTramp(136)
+DevExtTramp(137)
+DevExtTramp(138)
+DevExtTramp(139)
+DevExtTramp(140)
+DevExtTramp(141)
+DevExtTramp(142)
+DevExtTramp(143)
+DevExtTramp(144)
+DevExtTramp(145)
+DevExtTramp(146)
+DevExtTramp(147)
+DevExtTramp(148)
+DevExtTramp(149)
+DevExtTramp(150)
+DevExtTramp(151)
+DevExtTramp(152)
+DevExtTramp(153)
+DevExtTramp(154)
+DevExtTramp(155)
+DevExtTramp(156)
+DevExtTramp(157)
+DevExtTramp(158)
+DevExtTramp(159)
+DevExtTramp(160)
+DevExtTramp(161)
+DevExtTramp(162)
+DevExtTramp(163)
+DevExtTramp(164)
+DevExtTramp(165)
+DevExtTramp(166)
+DevExtTramp(167)
+DevExtTramp(168)
+DevExtTramp(169)
+DevExtTramp(170)
+DevExtTramp(171)
+DevExtTramp(172)
+DevExtTramp(173)
+DevExtTramp(174)
+DevExtTramp(175)
+DevExtTramp(176)
+DevExtTramp(177)
+DevExtTramp(178)
+DevExtTramp(179)
+DevExtTramp(180)
+DevExtTramp(181)
+DevExtTramp(182)
+DevExtTramp(183)
+DevExtTramp(184)
+DevExtTramp(185)
+DevExtTramp(186)
+DevExtTramp(187)
+DevExtTramp(188)
+DevExtTramp(189)
+DevExtTramp(190)
+DevExtTramp(191)
+DevExtTramp(192)
+DevExtTramp(193)
+DevExtTramp(194)
+DevExtTramp(195)
+DevExtTramp(196)
+DevExtTramp(197)
+DevExtTramp(198)
+DevExtTramp(199)
+DevExtTramp(200)
+DevExtTramp(201)
+DevExtTramp(202)
+DevExtTramp(203)
+DevExtTramp(204)
+DevExtTramp(205)
+DevExtTramp(206)
+DevExtTramp(207)
+DevExtTramp(208)
+DevExtTramp(209)
+DevExtTramp(210)
+DevExtTramp(211)
+DevExtTramp(212)
+DevExtTramp(213)
+DevExtTramp(214)
+DevExtTramp(215)
+DevExtTramp(216)
+DevExtTramp(217)
+DevExtTramp(218)
+DevExtTramp(219)
+DevExtTramp(220)
+DevExtTramp(221)
+DevExtTramp(222)
+DevExtTramp(223)
+DevExtTramp(224)
+DevExtTramp(225)
+DevExtTramp(226)
+DevExtTramp(227)
+DevExtTramp(228)
+DevExtTramp(229)
+DevExtTramp(230)
+DevExtTramp(231)
+DevExtTramp(232)
+DevExtTramp(233)
+DevExtTramp(234)
+DevExtTramp(235)
+DevExtTramp(236)
+DevExtTramp(237)
+DevExtTramp(238)
+DevExtTramp(239)
+DevExtTramp(240)
+DevExtTramp(241)
+DevExtTramp(242)
+DevExtTramp(243)
+DevExtTramp(244)
+DevExtTramp(245)
+DevExtTramp(246)
+DevExtTramp(247)
+DevExtTramp(248)
+DevExtTramp(249)
diff --git a/thirdparty/vulkan/loader/vk_dispatch_table_helper.h b/thirdparty/vulkan/loader/vk_dispatch_table_helper.h
new file mode 100644
index 0000000000..386745a1e7
--- /dev/null
+++ b/thirdparty/vulkan/loader/vk_dispatch_table_helper.h
@@ -0,0 +1,792 @@
+#pragma once
+// *** THIS FILE IS GENERATED - DO NOT EDIT ***
+// See dispatch_helper_generator.py for modifications
+
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Mark Lobodzinski <mark@lunarg.com>
+ */
+
+#include <vulkan/vulkan.h>
+#include <vulkan/vk_layer.h>
+#include <string.h>
+#include "vk_layer_dispatch_table.h"
+
+static VKAPI_ATTR VkResult VKAPI_CALL StubCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubGetDeviceGroupPeerMemoryFeaturesKHR(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdSetDeviceMaskKHR(VkCommandBuffer commandBuffer, uint32_t deviceMask) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) { };
+static VKAPI_ATTR void VKAPI_CALL StubTrimCommandPoolKHR(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) { };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetMemoryWin32HandleKHR(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetMemoryWin32HandlePropertiesKHR(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetMemoryFdKHR(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetMemoryFdPropertiesKHR(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties) { return VK_SUCCESS; };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubImportSemaphoreWin32HandleKHR(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetSemaphoreWin32HandleKHR(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubImportSemaphoreFdKHR(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetSemaphoreFdKHR(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubCmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCreateDescriptorUpdateTemplateKHR(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubDestroyDescriptorUpdateTemplateKHR(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) { };
+static VKAPI_ATTR void VKAPI_CALL StubUpdateDescriptorSetWithTemplateKHR(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdNextSubpass2KHR(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdEndRenderPass2KHR(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain) { return VK_SUCCESS; };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubImportFenceWin32HandleKHR(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetFenceWin32HandleKHR(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubImportFenceFdKHR(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetFenceFdKHR(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubAcquireProfilingLockKHR(VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubReleaseProfilingLockKHR(VkDevice device) { };
+static VKAPI_ATTR void VKAPI_CALL StubGetImageMemoryRequirements2KHR(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) { };
+static VKAPI_ATTR void VKAPI_CALL StubGetBufferMemoryRequirements2KHR(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) { };
+static VKAPI_ATTR void VKAPI_CALL StubGetImageSparseMemoryRequirements2KHR(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCreateSamplerYcbcrConversionKHR(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubDestroySamplerYcbcrConversionKHR(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubBindBufferMemory2KHR(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubBindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubGetDescriptorSetLayoutSupportKHR(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetSemaphoreCounterValueKHR(VkDevice device, VkSemaphore semaphore, uint64_t* pValue) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubWaitSemaphoresKHR(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubSignalSemaphoreKHR(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubGetBufferDeviceAddressKHR(VkDevice device, const VkBufferDeviceAddressInfo* pInfo) { };
+static VKAPI_ATTR void VKAPI_CALL StubGetBufferOpaqueCaptureAddressKHR(VkDevice device, const VkBufferDeviceAddressInfo* pInfo) { };
+static VKAPI_ATTR void VKAPI_CALL StubGetDeviceMemoryOpaqueCaptureAddressKHR(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetPipelineExecutablePropertiesKHR(VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VkPipelineExecutablePropertiesKHR* pProperties) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetPipelineExecutableStatisticsKHR(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VkPipelineExecutableStatisticKHR* pStatistics) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetPipelineExecutableInternalRepresentationsKHR(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubDebugMarkerSetObjectTagEXT(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubDebugMarkerSetObjectNameEXT(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDebugMarkerBeginEXT(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDebugMarkerEndEXT(VkCommandBuffer commandBuffer) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDebugMarkerInsertEXT(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdEndTransformFeedbackEXT(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdBeginQueryIndexedEXT(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdEndQueryIndexedEXT(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride) { };
+static VKAPI_ATTR void VKAPI_CALL StubGetImageViewHandleNVX(VkDevice device, const VkImageViewHandleInfoNVX* pInfo) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDrawIndirectCountAMD(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDrawIndexedIndirectCountAMD(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetShaderInfoAMD(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo) { return VK_SUCCESS; };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetMemoryWin32HandleNV(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR void VKAPI_CALL StubCmdBeginConditionalRenderingEXT(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdEndConditionalRenderingEXT(VkCommandBuffer commandBuffer) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdProcessCommandsNVX(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdReserveSpaceForCommandsNVX(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCreateIndirectCommandsLayoutNVX(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubDestroyIndirectCommandsLayoutNVX(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCreateObjectTableNVX(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubDestroyObjectTableNVX(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubRegisterObjectsNVX(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubUnregisterObjectsNVX(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubCmdSetViewportWScalingNV(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubDisplayPowerControlEXT(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubRegisterDeviceEventEXT(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubRegisterDisplayEventEXT(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetSwapchainCounterEXT(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubCmdSetDiscardRectangleEXT(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles) { };
+static VKAPI_ATTR void VKAPI_CALL StubSetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata) { };
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetAndroidHardwareBufferPropertiesANDROID(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetMemoryAndroidHardwareBufferANDROID(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+static VKAPI_ATTR void VKAPI_CALL StubCmdSetSampleLocationsEXT(VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetImageDrmFormatModifierPropertiesEXT(VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubCmdBindShadingRateImageNV(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdSetViewportShadingRatePaletteNV(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdSetCoarseSampleOrderNV(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCreateAccelerationStructureNV(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubDestroyAccelerationStructureNV(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator) { };
+static VKAPI_ATTR void VKAPI_CALL StubGetAccelerationStructureMemoryRequirementsNV(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdCopyAccelerationStructureNV(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeNV mode) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetRayTracingShaderGroupHandlesNV(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetAccelerationStructureHandleNV(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubCmdWriteAccelerationStructuresPropertiesNV(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCompileDeferredNV(VkDevice device, VkPipeline pipeline, uint32_t shader) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetMemoryHostPointerPropertiesEXT(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubCmdWriteBufferMarkerAMD(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetCalibratedTimestampsEXT(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoEXT* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdSetExclusiveScissorNV(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors) { };
+static VKAPI_ATTR void VKAPI_CALL StubCmdSetCheckpointNV(VkCommandBuffer commandBuffer, const void* pCheckpointMarker) { };
+static VKAPI_ATTR void VKAPI_CALL StubGetQueueCheckpointDataNV(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubInitializePerformanceApiINTEL(VkDevice device, const VkInitializePerformanceApiInfoINTEL* pInitializeInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubUninitializePerformanceApiINTEL(VkDevice device) { };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCmdSetPerformanceMarkerINTEL(VkCommandBuffer commandBuffer, const VkPerformanceMarkerInfoINTEL* pMarkerInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCmdSetPerformanceStreamMarkerINTEL(VkCommandBuffer commandBuffer, const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubCmdSetPerformanceOverrideINTEL(VkCommandBuffer commandBuffer, const VkPerformanceOverrideInfoINTEL* pOverrideInfo) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubAcquirePerformanceConfigurationINTEL(VkDevice device, const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VkPerformanceConfigurationINTEL* pConfiguration) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubReleasePerformanceConfigurationINTEL(VkDevice device, VkPerformanceConfigurationINTEL configuration) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubQueueSetPerformanceConfigurationINTEL(VkQueue queue, VkPerformanceConfigurationINTEL configuration) { return VK_SUCCESS; };
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetPerformanceParameterINTEL(VkDevice device, VkPerformanceParameterTypeINTEL parameter, VkPerformanceValueINTEL* pValue) { return VK_SUCCESS; };
+static VKAPI_ATTR void VKAPI_CALL StubSetLocalDimmingAMD(VkDevice device, VkSwapchainKHR swapChain, VkBool32 localDimmingEnable) { };
+static VKAPI_ATTR void VKAPI_CALL StubGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfo* pInfo) { };
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubAcquireFullScreenExclusiveModeEXT(VkDevice device, VkSwapchainKHR swapchain) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubReleaseFullScreenExclusiveModeEXT(VkDevice device, VkSwapchainKHR swapchain) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR VkResult VKAPI_CALL StubGetDeviceGroupSurfacePresentModes2EXT(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes) { return VK_SUCCESS; };
+#endif // VK_USE_PLATFORM_WIN32_KHR
+static VKAPI_ATTR void VKAPI_CALL StubCmdSetLineStippleEXT(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern) { };
+static VKAPI_ATTR void VKAPI_CALL StubResetQueryPoolEXT(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) { };
+
+
+
+static inline void layer_init_device_dispatch_table(VkDevice device, VkLayerDispatchTable *table, PFN_vkGetDeviceProcAddr gpa) {
+ memset(table, 0, sizeof(*table));
+ // Device function pointers
+ table->GetDeviceProcAddr = gpa;
+ table->DestroyDevice = (PFN_vkDestroyDevice) gpa(device, "vkDestroyDevice");
+ table->GetDeviceQueue = (PFN_vkGetDeviceQueue) gpa(device, "vkGetDeviceQueue");
+ table->QueueSubmit = (PFN_vkQueueSubmit) gpa(device, "vkQueueSubmit");
+ table->QueueWaitIdle = (PFN_vkQueueWaitIdle) gpa(device, "vkQueueWaitIdle");
+ table->DeviceWaitIdle = (PFN_vkDeviceWaitIdle) gpa(device, "vkDeviceWaitIdle");
+ table->AllocateMemory = (PFN_vkAllocateMemory) gpa(device, "vkAllocateMemory");
+ table->FreeMemory = (PFN_vkFreeMemory) gpa(device, "vkFreeMemory");
+ table->MapMemory = (PFN_vkMapMemory) gpa(device, "vkMapMemory");
+ table->UnmapMemory = (PFN_vkUnmapMemory) gpa(device, "vkUnmapMemory");
+ table->FlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges) gpa(device, "vkFlushMappedMemoryRanges");
+ table->InvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges) gpa(device, "vkInvalidateMappedMemoryRanges");
+ table->GetDeviceMemoryCommitment = (PFN_vkGetDeviceMemoryCommitment) gpa(device, "vkGetDeviceMemoryCommitment");
+ table->BindBufferMemory = (PFN_vkBindBufferMemory) gpa(device, "vkBindBufferMemory");
+ table->BindImageMemory = (PFN_vkBindImageMemory) gpa(device, "vkBindImageMemory");
+ table->GetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements) gpa(device, "vkGetBufferMemoryRequirements");
+ table->GetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements) gpa(device, "vkGetImageMemoryRequirements");
+ table->GetImageSparseMemoryRequirements = (PFN_vkGetImageSparseMemoryRequirements) gpa(device, "vkGetImageSparseMemoryRequirements");
+ table->QueueBindSparse = (PFN_vkQueueBindSparse) gpa(device, "vkQueueBindSparse");
+ table->CreateFence = (PFN_vkCreateFence) gpa(device, "vkCreateFence");
+ table->DestroyFence = (PFN_vkDestroyFence) gpa(device, "vkDestroyFence");
+ table->ResetFences = (PFN_vkResetFences) gpa(device, "vkResetFences");
+ table->GetFenceStatus = (PFN_vkGetFenceStatus) gpa(device, "vkGetFenceStatus");
+ table->WaitForFences = (PFN_vkWaitForFences) gpa(device, "vkWaitForFences");
+ table->CreateSemaphore = (PFN_vkCreateSemaphore) gpa(device, "vkCreateSemaphore");
+ table->DestroySemaphore = (PFN_vkDestroySemaphore) gpa(device, "vkDestroySemaphore");
+ table->CreateEvent = (PFN_vkCreateEvent) gpa(device, "vkCreateEvent");
+ table->DestroyEvent = (PFN_vkDestroyEvent) gpa(device, "vkDestroyEvent");
+ table->GetEventStatus = (PFN_vkGetEventStatus) gpa(device, "vkGetEventStatus");
+ table->SetEvent = (PFN_vkSetEvent) gpa(device, "vkSetEvent");
+ table->ResetEvent = (PFN_vkResetEvent) gpa(device, "vkResetEvent");
+ table->CreateQueryPool = (PFN_vkCreateQueryPool) gpa(device, "vkCreateQueryPool");
+ table->DestroyQueryPool = (PFN_vkDestroyQueryPool) gpa(device, "vkDestroyQueryPool");
+ table->GetQueryPoolResults = (PFN_vkGetQueryPoolResults) gpa(device, "vkGetQueryPoolResults");
+ table->CreateBuffer = (PFN_vkCreateBuffer) gpa(device, "vkCreateBuffer");
+ table->DestroyBuffer = (PFN_vkDestroyBuffer) gpa(device, "vkDestroyBuffer");
+ table->CreateBufferView = (PFN_vkCreateBufferView) gpa(device, "vkCreateBufferView");
+ table->DestroyBufferView = (PFN_vkDestroyBufferView) gpa(device, "vkDestroyBufferView");
+ table->CreateImage = (PFN_vkCreateImage) gpa(device, "vkCreateImage");
+ table->DestroyImage = (PFN_vkDestroyImage) gpa(device, "vkDestroyImage");
+ table->GetImageSubresourceLayout = (PFN_vkGetImageSubresourceLayout) gpa(device, "vkGetImageSubresourceLayout");
+ table->CreateImageView = (PFN_vkCreateImageView) gpa(device, "vkCreateImageView");
+ table->DestroyImageView = (PFN_vkDestroyImageView) gpa(device, "vkDestroyImageView");
+ table->CreateShaderModule = (PFN_vkCreateShaderModule) gpa(device, "vkCreateShaderModule");
+ table->DestroyShaderModule = (PFN_vkDestroyShaderModule) gpa(device, "vkDestroyShaderModule");
+ table->CreatePipelineCache = (PFN_vkCreatePipelineCache) gpa(device, "vkCreatePipelineCache");
+ table->DestroyPipelineCache = (PFN_vkDestroyPipelineCache) gpa(device, "vkDestroyPipelineCache");
+ table->GetPipelineCacheData = (PFN_vkGetPipelineCacheData) gpa(device, "vkGetPipelineCacheData");
+ table->MergePipelineCaches = (PFN_vkMergePipelineCaches) gpa(device, "vkMergePipelineCaches");
+ table->CreateGraphicsPipelines = (PFN_vkCreateGraphicsPipelines) gpa(device, "vkCreateGraphicsPipelines");
+ table->CreateComputePipelines = (PFN_vkCreateComputePipelines) gpa(device, "vkCreateComputePipelines");
+ table->DestroyPipeline = (PFN_vkDestroyPipeline) gpa(device, "vkDestroyPipeline");
+ table->CreatePipelineLayout = (PFN_vkCreatePipelineLayout) gpa(device, "vkCreatePipelineLayout");
+ table->DestroyPipelineLayout = (PFN_vkDestroyPipelineLayout) gpa(device, "vkDestroyPipelineLayout");
+ table->CreateSampler = (PFN_vkCreateSampler) gpa(device, "vkCreateSampler");
+ table->DestroySampler = (PFN_vkDestroySampler) gpa(device, "vkDestroySampler");
+ table->CreateDescriptorSetLayout = (PFN_vkCreateDescriptorSetLayout) gpa(device, "vkCreateDescriptorSetLayout");
+ table->DestroyDescriptorSetLayout = (PFN_vkDestroyDescriptorSetLayout) gpa(device, "vkDestroyDescriptorSetLayout");
+ table->CreateDescriptorPool = (PFN_vkCreateDescriptorPool) gpa(device, "vkCreateDescriptorPool");
+ table->DestroyDescriptorPool = (PFN_vkDestroyDescriptorPool) gpa(device, "vkDestroyDescriptorPool");
+ table->ResetDescriptorPool = (PFN_vkResetDescriptorPool) gpa(device, "vkResetDescriptorPool");
+ table->AllocateDescriptorSets = (PFN_vkAllocateDescriptorSets) gpa(device, "vkAllocateDescriptorSets");
+ table->FreeDescriptorSets = (PFN_vkFreeDescriptorSets) gpa(device, "vkFreeDescriptorSets");
+ table->UpdateDescriptorSets = (PFN_vkUpdateDescriptorSets) gpa(device, "vkUpdateDescriptorSets");
+ table->CreateFramebuffer = (PFN_vkCreateFramebuffer) gpa(device, "vkCreateFramebuffer");
+ table->DestroyFramebuffer = (PFN_vkDestroyFramebuffer) gpa(device, "vkDestroyFramebuffer");
+ table->CreateRenderPass = (PFN_vkCreateRenderPass) gpa(device, "vkCreateRenderPass");
+ table->DestroyRenderPass = (PFN_vkDestroyRenderPass) gpa(device, "vkDestroyRenderPass");
+ table->GetRenderAreaGranularity = (PFN_vkGetRenderAreaGranularity) gpa(device, "vkGetRenderAreaGranularity");
+ table->CreateCommandPool = (PFN_vkCreateCommandPool) gpa(device, "vkCreateCommandPool");
+ table->DestroyCommandPool = (PFN_vkDestroyCommandPool) gpa(device, "vkDestroyCommandPool");
+ table->ResetCommandPool = (PFN_vkResetCommandPool) gpa(device, "vkResetCommandPool");
+ table->AllocateCommandBuffers = (PFN_vkAllocateCommandBuffers) gpa(device, "vkAllocateCommandBuffers");
+ table->FreeCommandBuffers = (PFN_vkFreeCommandBuffers) gpa(device, "vkFreeCommandBuffers");
+ table->BeginCommandBuffer = (PFN_vkBeginCommandBuffer) gpa(device, "vkBeginCommandBuffer");
+ table->EndCommandBuffer = (PFN_vkEndCommandBuffer) gpa(device, "vkEndCommandBuffer");
+ table->ResetCommandBuffer = (PFN_vkResetCommandBuffer) gpa(device, "vkResetCommandBuffer");
+ table->CmdBindPipeline = (PFN_vkCmdBindPipeline) gpa(device, "vkCmdBindPipeline");
+ table->CmdSetViewport = (PFN_vkCmdSetViewport) gpa(device, "vkCmdSetViewport");
+ table->CmdSetScissor = (PFN_vkCmdSetScissor) gpa(device, "vkCmdSetScissor");
+ table->CmdSetLineWidth = (PFN_vkCmdSetLineWidth) gpa(device, "vkCmdSetLineWidth");
+ table->CmdSetDepthBias = (PFN_vkCmdSetDepthBias) gpa(device, "vkCmdSetDepthBias");
+ table->CmdSetBlendConstants = (PFN_vkCmdSetBlendConstants) gpa(device, "vkCmdSetBlendConstants");
+ table->CmdSetDepthBounds = (PFN_vkCmdSetDepthBounds) gpa(device, "vkCmdSetDepthBounds");
+ table->CmdSetStencilCompareMask = (PFN_vkCmdSetStencilCompareMask) gpa(device, "vkCmdSetStencilCompareMask");
+ table->CmdSetStencilWriteMask = (PFN_vkCmdSetStencilWriteMask) gpa(device, "vkCmdSetStencilWriteMask");
+ table->CmdSetStencilReference = (PFN_vkCmdSetStencilReference) gpa(device, "vkCmdSetStencilReference");
+ table->CmdBindDescriptorSets = (PFN_vkCmdBindDescriptorSets) gpa(device, "vkCmdBindDescriptorSets");
+ table->CmdBindIndexBuffer = (PFN_vkCmdBindIndexBuffer) gpa(device, "vkCmdBindIndexBuffer");
+ table->CmdBindVertexBuffers = (PFN_vkCmdBindVertexBuffers) gpa(device, "vkCmdBindVertexBuffers");
+ table->CmdDraw = (PFN_vkCmdDraw) gpa(device, "vkCmdDraw");
+ table->CmdDrawIndexed = (PFN_vkCmdDrawIndexed) gpa(device, "vkCmdDrawIndexed");
+ table->CmdDrawIndirect = (PFN_vkCmdDrawIndirect) gpa(device, "vkCmdDrawIndirect");
+ table->CmdDrawIndexedIndirect = (PFN_vkCmdDrawIndexedIndirect) gpa(device, "vkCmdDrawIndexedIndirect");
+ table->CmdDispatch = (PFN_vkCmdDispatch) gpa(device, "vkCmdDispatch");
+ table->CmdDispatchIndirect = (PFN_vkCmdDispatchIndirect) gpa(device, "vkCmdDispatchIndirect");
+ table->CmdCopyBuffer = (PFN_vkCmdCopyBuffer) gpa(device, "vkCmdCopyBuffer");
+ table->CmdCopyImage = (PFN_vkCmdCopyImage) gpa(device, "vkCmdCopyImage");
+ table->CmdBlitImage = (PFN_vkCmdBlitImage) gpa(device, "vkCmdBlitImage");
+ table->CmdCopyBufferToImage = (PFN_vkCmdCopyBufferToImage) gpa(device, "vkCmdCopyBufferToImage");
+ table->CmdCopyImageToBuffer = (PFN_vkCmdCopyImageToBuffer) gpa(device, "vkCmdCopyImageToBuffer");
+ table->CmdUpdateBuffer = (PFN_vkCmdUpdateBuffer) gpa(device, "vkCmdUpdateBuffer");
+ table->CmdFillBuffer = (PFN_vkCmdFillBuffer) gpa(device, "vkCmdFillBuffer");
+ table->CmdClearColorImage = (PFN_vkCmdClearColorImage) gpa(device, "vkCmdClearColorImage");
+ table->CmdClearDepthStencilImage = (PFN_vkCmdClearDepthStencilImage) gpa(device, "vkCmdClearDepthStencilImage");
+ table->CmdClearAttachments = (PFN_vkCmdClearAttachments) gpa(device, "vkCmdClearAttachments");
+ table->CmdResolveImage = (PFN_vkCmdResolveImage) gpa(device, "vkCmdResolveImage");
+ table->CmdSetEvent = (PFN_vkCmdSetEvent) gpa(device, "vkCmdSetEvent");
+ table->CmdResetEvent = (PFN_vkCmdResetEvent) gpa(device, "vkCmdResetEvent");
+ table->CmdWaitEvents = (PFN_vkCmdWaitEvents) gpa(device, "vkCmdWaitEvents");
+ table->CmdPipelineBarrier = (PFN_vkCmdPipelineBarrier) gpa(device, "vkCmdPipelineBarrier");
+ table->CmdBeginQuery = (PFN_vkCmdBeginQuery) gpa(device, "vkCmdBeginQuery");
+ table->CmdEndQuery = (PFN_vkCmdEndQuery) gpa(device, "vkCmdEndQuery");
+ table->CmdResetQueryPool = (PFN_vkCmdResetQueryPool) gpa(device, "vkCmdResetQueryPool");
+ table->CmdWriteTimestamp = (PFN_vkCmdWriteTimestamp) gpa(device, "vkCmdWriteTimestamp");
+ table->CmdCopyQueryPoolResults = (PFN_vkCmdCopyQueryPoolResults) gpa(device, "vkCmdCopyQueryPoolResults");
+ table->CmdPushConstants = (PFN_vkCmdPushConstants) gpa(device, "vkCmdPushConstants");
+ table->CmdBeginRenderPass = (PFN_vkCmdBeginRenderPass) gpa(device, "vkCmdBeginRenderPass");
+ table->CmdNextSubpass = (PFN_vkCmdNextSubpass) gpa(device, "vkCmdNextSubpass");
+ table->CmdEndRenderPass = (PFN_vkCmdEndRenderPass) gpa(device, "vkCmdEndRenderPass");
+ table->CmdExecuteCommands = (PFN_vkCmdExecuteCommands) gpa(device, "vkCmdExecuteCommands");
+ table->BindBufferMemory2 = (PFN_vkBindBufferMemory2) gpa(device, "vkBindBufferMemory2");
+ table->BindImageMemory2 = (PFN_vkBindImageMemory2) gpa(device, "vkBindImageMemory2");
+ table->GetDeviceGroupPeerMemoryFeatures = (PFN_vkGetDeviceGroupPeerMemoryFeatures) gpa(device, "vkGetDeviceGroupPeerMemoryFeatures");
+ table->CmdSetDeviceMask = (PFN_vkCmdSetDeviceMask) gpa(device, "vkCmdSetDeviceMask");
+ table->CmdDispatchBase = (PFN_vkCmdDispatchBase) gpa(device, "vkCmdDispatchBase");
+ table->GetImageMemoryRequirements2 = (PFN_vkGetImageMemoryRequirements2) gpa(device, "vkGetImageMemoryRequirements2");
+ table->GetBufferMemoryRequirements2 = (PFN_vkGetBufferMemoryRequirements2) gpa(device, "vkGetBufferMemoryRequirements2");
+ table->GetImageSparseMemoryRequirements2 = (PFN_vkGetImageSparseMemoryRequirements2) gpa(device, "vkGetImageSparseMemoryRequirements2");
+ table->TrimCommandPool = (PFN_vkTrimCommandPool) gpa(device, "vkTrimCommandPool");
+ table->GetDeviceQueue2 = (PFN_vkGetDeviceQueue2) gpa(device, "vkGetDeviceQueue2");
+ table->CreateSamplerYcbcrConversion = (PFN_vkCreateSamplerYcbcrConversion) gpa(device, "vkCreateSamplerYcbcrConversion");
+ table->DestroySamplerYcbcrConversion = (PFN_vkDestroySamplerYcbcrConversion) gpa(device, "vkDestroySamplerYcbcrConversion");
+ table->CreateDescriptorUpdateTemplate = (PFN_vkCreateDescriptorUpdateTemplate) gpa(device, "vkCreateDescriptorUpdateTemplate");
+ table->DestroyDescriptorUpdateTemplate = (PFN_vkDestroyDescriptorUpdateTemplate) gpa(device, "vkDestroyDescriptorUpdateTemplate");
+ table->UpdateDescriptorSetWithTemplate = (PFN_vkUpdateDescriptorSetWithTemplate) gpa(device, "vkUpdateDescriptorSetWithTemplate");
+ table->GetDescriptorSetLayoutSupport = (PFN_vkGetDescriptorSetLayoutSupport) gpa(device, "vkGetDescriptorSetLayoutSupport");
+ table->CmdDrawIndirectCount = (PFN_vkCmdDrawIndirectCount) gpa(device, "vkCmdDrawIndirectCount");
+ table->CmdDrawIndexedIndirectCount = (PFN_vkCmdDrawIndexedIndirectCount) gpa(device, "vkCmdDrawIndexedIndirectCount");
+ table->CreateRenderPass2 = (PFN_vkCreateRenderPass2) gpa(device, "vkCreateRenderPass2");
+ table->CmdBeginRenderPass2 = (PFN_vkCmdBeginRenderPass2) gpa(device, "vkCmdBeginRenderPass2");
+ table->CmdNextSubpass2 = (PFN_vkCmdNextSubpass2) gpa(device, "vkCmdNextSubpass2");
+ table->CmdEndRenderPass2 = (PFN_vkCmdEndRenderPass2) gpa(device, "vkCmdEndRenderPass2");
+ table->ResetQueryPool = (PFN_vkResetQueryPool) gpa(device, "vkResetQueryPool");
+ table->GetSemaphoreCounterValue = (PFN_vkGetSemaphoreCounterValue) gpa(device, "vkGetSemaphoreCounterValue");
+ table->WaitSemaphores = (PFN_vkWaitSemaphores) gpa(device, "vkWaitSemaphores");
+ table->SignalSemaphore = (PFN_vkSignalSemaphore) gpa(device, "vkSignalSemaphore");
+ table->GetBufferDeviceAddress = (PFN_vkGetBufferDeviceAddress) gpa(device, "vkGetBufferDeviceAddress");
+ table->GetBufferOpaqueCaptureAddress = (PFN_vkGetBufferOpaqueCaptureAddress) gpa(device, "vkGetBufferOpaqueCaptureAddress");
+ table->GetDeviceMemoryOpaqueCaptureAddress = (PFN_vkGetDeviceMemoryOpaqueCaptureAddress) gpa(device, "vkGetDeviceMemoryOpaqueCaptureAddress");
+ table->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
+ if (table->CreateSwapchainKHR == nullptr) { table->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)StubCreateSwapchainKHR; }
+ table->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) gpa(device, "vkDestroySwapchainKHR");
+ if (table->DestroySwapchainKHR == nullptr) { table->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)StubDestroySwapchainKHR; }
+ table->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
+ if (table->GetSwapchainImagesKHR == nullptr) { table->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)StubGetSwapchainImagesKHR; }
+ table->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
+ if (table->AcquireNextImageKHR == nullptr) { table->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)StubAcquireNextImageKHR; }
+ table->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
+ if (table->QueuePresentKHR == nullptr) { table->QueuePresentKHR = (PFN_vkQueuePresentKHR)StubQueuePresentKHR; }
+ table->GetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR) gpa(device, "vkGetDeviceGroupPresentCapabilitiesKHR");
+ if (table->GetDeviceGroupPresentCapabilitiesKHR == nullptr) { table->GetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR)StubGetDeviceGroupPresentCapabilitiesKHR; }
+ table->GetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR) gpa(device, "vkGetDeviceGroupSurfacePresentModesKHR");
+ if (table->GetDeviceGroupSurfacePresentModesKHR == nullptr) { table->GetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR)StubGetDeviceGroupSurfacePresentModesKHR; }
+ table->AcquireNextImage2KHR = (PFN_vkAcquireNextImage2KHR) gpa(device, "vkAcquireNextImage2KHR");
+ if (table->AcquireNextImage2KHR == nullptr) { table->AcquireNextImage2KHR = (PFN_vkAcquireNextImage2KHR)StubAcquireNextImage2KHR; }
+ table->CreateSharedSwapchainsKHR = (PFN_vkCreateSharedSwapchainsKHR) gpa(device, "vkCreateSharedSwapchainsKHR");
+ if (table->CreateSharedSwapchainsKHR == nullptr) { table->CreateSharedSwapchainsKHR = (PFN_vkCreateSharedSwapchainsKHR)StubCreateSharedSwapchainsKHR; }
+ table->GetDeviceGroupPeerMemoryFeaturesKHR = (PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR) gpa(device, "vkGetDeviceGroupPeerMemoryFeaturesKHR");
+ if (table->GetDeviceGroupPeerMemoryFeaturesKHR == nullptr) { table->GetDeviceGroupPeerMemoryFeaturesKHR = (PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)StubGetDeviceGroupPeerMemoryFeaturesKHR; }
+ table->CmdSetDeviceMaskKHR = (PFN_vkCmdSetDeviceMaskKHR) gpa(device, "vkCmdSetDeviceMaskKHR");
+ if (table->CmdSetDeviceMaskKHR == nullptr) { table->CmdSetDeviceMaskKHR = (PFN_vkCmdSetDeviceMaskKHR)StubCmdSetDeviceMaskKHR; }
+ table->CmdDispatchBaseKHR = (PFN_vkCmdDispatchBaseKHR) gpa(device, "vkCmdDispatchBaseKHR");
+ if (table->CmdDispatchBaseKHR == nullptr) { table->CmdDispatchBaseKHR = (PFN_vkCmdDispatchBaseKHR)StubCmdDispatchBaseKHR; }
+ table->TrimCommandPoolKHR = (PFN_vkTrimCommandPoolKHR) gpa(device, "vkTrimCommandPoolKHR");
+ if (table->TrimCommandPoolKHR == nullptr) { table->TrimCommandPoolKHR = (PFN_vkTrimCommandPoolKHR)StubTrimCommandPoolKHR; }
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetMemoryWin32HandleKHR = (PFN_vkGetMemoryWin32HandleKHR) gpa(device, "vkGetMemoryWin32HandleKHR");
+ if (table->GetMemoryWin32HandleKHR == nullptr) { table->GetMemoryWin32HandleKHR = (PFN_vkGetMemoryWin32HandleKHR)StubGetMemoryWin32HandleKHR; }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetMemoryWin32HandlePropertiesKHR = (PFN_vkGetMemoryWin32HandlePropertiesKHR) gpa(device, "vkGetMemoryWin32HandlePropertiesKHR");
+ if (table->GetMemoryWin32HandlePropertiesKHR == nullptr) { table->GetMemoryWin32HandlePropertiesKHR = (PFN_vkGetMemoryWin32HandlePropertiesKHR)StubGetMemoryWin32HandlePropertiesKHR; }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+ table->GetMemoryFdKHR = (PFN_vkGetMemoryFdKHR) gpa(device, "vkGetMemoryFdKHR");
+ if (table->GetMemoryFdKHR == nullptr) { table->GetMemoryFdKHR = (PFN_vkGetMemoryFdKHR)StubGetMemoryFdKHR; }
+ table->GetMemoryFdPropertiesKHR = (PFN_vkGetMemoryFdPropertiesKHR) gpa(device, "vkGetMemoryFdPropertiesKHR");
+ if (table->GetMemoryFdPropertiesKHR == nullptr) { table->GetMemoryFdPropertiesKHR = (PFN_vkGetMemoryFdPropertiesKHR)StubGetMemoryFdPropertiesKHR; }
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->ImportSemaphoreWin32HandleKHR = (PFN_vkImportSemaphoreWin32HandleKHR) gpa(device, "vkImportSemaphoreWin32HandleKHR");
+ if (table->ImportSemaphoreWin32HandleKHR == nullptr) { table->ImportSemaphoreWin32HandleKHR = (PFN_vkImportSemaphoreWin32HandleKHR)StubImportSemaphoreWin32HandleKHR; }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetSemaphoreWin32HandleKHR = (PFN_vkGetSemaphoreWin32HandleKHR) gpa(device, "vkGetSemaphoreWin32HandleKHR");
+ if (table->GetSemaphoreWin32HandleKHR == nullptr) { table->GetSemaphoreWin32HandleKHR = (PFN_vkGetSemaphoreWin32HandleKHR)StubGetSemaphoreWin32HandleKHR; }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+ table->ImportSemaphoreFdKHR = (PFN_vkImportSemaphoreFdKHR) gpa(device, "vkImportSemaphoreFdKHR");
+ if (table->ImportSemaphoreFdKHR == nullptr) { table->ImportSemaphoreFdKHR = (PFN_vkImportSemaphoreFdKHR)StubImportSemaphoreFdKHR; }
+ table->GetSemaphoreFdKHR = (PFN_vkGetSemaphoreFdKHR) gpa(device, "vkGetSemaphoreFdKHR");
+ if (table->GetSemaphoreFdKHR == nullptr) { table->GetSemaphoreFdKHR = (PFN_vkGetSemaphoreFdKHR)StubGetSemaphoreFdKHR; }
+ table->CmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR) gpa(device, "vkCmdPushDescriptorSetKHR");
+ if (table->CmdPushDescriptorSetKHR == nullptr) { table->CmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)StubCmdPushDescriptorSetKHR; }
+ table->CmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR) gpa(device, "vkCmdPushDescriptorSetWithTemplateKHR");
+ if (table->CmdPushDescriptorSetWithTemplateKHR == nullptr) { table->CmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)StubCmdPushDescriptorSetWithTemplateKHR; }
+ table->CreateDescriptorUpdateTemplateKHR = (PFN_vkCreateDescriptorUpdateTemplateKHR) gpa(device, "vkCreateDescriptorUpdateTemplateKHR");
+ if (table->CreateDescriptorUpdateTemplateKHR == nullptr) { table->CreateDescriptorUpdateTemplateKHR = (PFN_vkCreateDescriptorUpdateTemplateKHR)StubCreateDescriptorUpdateTemplateKHR; }
+ table->DestroyDescriptorUpdateTemplateKHR = (PFN_vkDestroyDescriptorUpdateTemplateKHR) gpa(device, "vkDestroyDescriptorUpdateTemplateKHR");
+ if (table->DestroyDescriptorUpdateTemplateKHR == nullptr) { table->DestroyDescriptorUpdateTemplateKHR = (PFN_vkDestroyDescriptorUpdateTemplateKHR)StubDestroyDescriptorUpdateTemplateKHR; }
+ table->UpdateDescriptorSetWithTemplateKHR = (PFN_vkUpdateDescriptorSetWithTemplateKHR) gpa(device, "vkUpdateDescriptorSetWithTemplateKHR");
+ if (table->UpdateDescriptorSetWithTemplateKHR == nullptr) { table->UpdateDescriptorSetWithTemplateKHR = (PFN_vkUpdateDescriptorSetWithTemplateKHR)StubUpdateDescriptorSetWithTemplateKHR; }
+ table->CreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR) gpa(device, "vkCreateRenderPass2KHR");
+ if (table->CreateRenderPass2KHR == nullptr) { table->CreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)StubCreateRenderPass2KHR; }
+ table->CmdBeginRenderPass2KHR = (PFN_vkCmdBeginRenderPass2KHR) gpa(device, "vkCmdBeginRenderPass2KHR");
+ if (table->CmdBeginRenderPass2KHR == nullptr) { table->CmdBeginRenderPass2KHR = (PFN_vkCmdBeginRenderPass2KHR)StubCmdBeginRenderPass2KHR; }
+ table->CmdNextSubpass2KHR = (PFN_vkCmdNextSubpass2KHR) gpa(device, "vkCmdNextSubpass2KHR");
+ if (table->CmdNextSubpass2KHR == nullptr) { table->CmdNextSubpass2KHR = (PFN_vkCmdNextSubpass2KHR)StubCmdNextSubpass2KHR; }
+ table->CmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR) gpa(device, "vkCmdEndRenderPass2KHR");
+ if (table->CmdEndRenderPass2KHR == nullptr) { table->CmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR)StubCmdEndRenderPass2KHR; }
+ table->GetSwapchainStatusKHR = (PFN_vkGetSwapchainStatusKHR) gpa(device, "vkGetSwapchainStatusKHR");
+ if (table->GetSwapchainStatusKHR == nullptr) { table->GetSwapchainStatusKHR = (PFN_vkGetSwapchainStatusKHR)StubGetSwapchainStatusKHR; }
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->ImportFenceWin32HandleKHR = (PFN_vkImportFenceWin32HandleKHR) gpa(device, "vkImportFenceWin32HandleKHR");
+ if (table->ImportFenceWin32HandleKHR == nullptr) { table->ImportFenceWin32HandleKHR = (PFN_vkImportFenceWin32HandleKHR)StubImportFenceWin32HandleKHR; }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetFenceWin32HandleKHR = (PFN_vkGetFenceWin32HandleKHR) gpa(device, "vkGetFenceWin32HandleKHR");
+ if (table->GetFenceWin32HandleKHR == nullptr) { table->GetFenceWin32HandleKHR = (PFN_vkGetFenceWin32HandleKHR)StubGetFenceWin32HandleKHR; }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+ table->ImportFenceFdKHR = (PFN_vkImportFenceFdKHR) gpa(device, "vkImportFenceFdKHR");
+ if (table->ImportFenceFdKHR == nullptr) { table->ImportFenceFdKHR = (PFN_vkImportFenceFdKHR)StubImportFenceFdKHR; }
+ table->GetFenceFdKHR = (PFN_vkGetFenceFdKHR) gpa(device, "vkGetFenceFdKHR");
+ if (table->GetFenceFdKHR == nullptr) { table->GetFenceFdKHR = (PFN_vkGetFenceFdKHR)StubGetFenceFdKHR; }
+ table->AcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR) gpa(device, "vkAcquireProfilingLockKHR");
+ if (table->AcquireProfilingLockKHR == nullptr) { table->AcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)StubAcquireProfilingLockKHR; }
+ table->ReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR) gpa(device, "vkReleaseProfilingLockKHR");
+ if (table->ReleaseProfilingLockKHR == nullptr) { table->ReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)StubReleaseProfilingLockKHR; }
+ table->GetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2KHR) gpa(device, "vkGetImageMemoryRequirements2KHR");
+ if (table->GetImageMemoryRequirements2KHR == nullptr) { table->GetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2KHR)StubGetImageMemoryRequirements2KHR; }
+ table->GetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2KHR) gpa(device, "vkGetBufferMemoryRequirements2KHR");
+ if (table->GetBufferMemoryRequirements2KHR == nullptr) { table->GetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2KHR)StubGetBufferMemoryRequirements2KHR; }
+ table->GetImageSparseMemoryRequirements2KHR = (PFN_vkGetImageSparseMemoryRequirements2KHR) gpa(device, "vkGetImageSparseMemoryRequirements2KHR");
+ if (table->GetImageSparseMemoryRequirements2KHR == nullptr) { table->GetImageSparseMemoryRequirements2KHR = (PFN_vkGetImageSparseMemoryRequirements2KHR)StubGetImageSparseMemoryRequirements2KHR; }
+ table->CreateSamplerYcbcrConversionKHR = (PFN_vkCreateSamplerYcbcrConversionKHR) gpa(device, "vkCreateSamplerYcbcrConversionKHR");
+ if (table->CreateSamplerYcbcrConversionKHR == nullptr) { table->CreateSamplerYcbcrConversionKHR = (PFN_vkCreateSamplerYcbcrConversionKHR)StubCreateSamplerYcbcrConversionKHR; }
+ table->DestroySamplerYcbcrConversionKHR = (PFN_vkDestroySamplerYcbcrConversionKHR) gpa(device, "vkDestroySamplerYcbcrConversionKHR");
+ if (table->DestroySamplerYcbcrConversionKHR == nullptr) { table->DestroySamplerYcbcrConversionKHR = (PFN_vkDestroySamplerYcbcrConversionKHR)StubDestroySamplerYcbcrConversionKHR; }
+ table->BindBufferMemory2KHR = (PFN_vkBindBufferMemory2KHR) gpa(device, "vkBindBufferMemory2KHR");
+ if (table->BindBufferMemory2KHR == nullptr) { table->BindBufferMemory2KHR = (PFN_vkBindBufferMemory2KHR)StubBindBufferMemory2KHR; }
+ table->BindImageMemory2KHR = (PFN_vkBindImageMemory2KHR) gpa(device, "vkBindImageMemory2KHR");
+ if (table->BindImageMemory2KHR == nullptr) { table->BindImageMemory2KHR = (PFN_vkBindImageMemory2KHR)StubBindImageMemory2KHR; }
+ table->GetDescriptorSetLayoutSupportKHR = (PFN_vkGetDescriptorSetLayoutSupportKHR) gpa(device, "vkGetDescriptorSetLayoutSupportKHR");
+ if (table->GetDescriptorSetLayoutSupportKHR == nullptr) { table->GetDescriptorSetLayoutSupportKHR = (PFN_vkGetDescriptorSetLayoutSupportKHR)StubGetDescriptorSetLayoutSupportKHR; }
+ table->CmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR) gpa(device, "vkCmdDrawIndirectCountKHR");
+ if (table->CmdDrawIndirectCountKHR == nullptr) { table->CmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)StubCmdDrawIndirectCountKHR; }
+ table->CmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR) gpa(device, "vkCmdDrawIndexedIndirectCountKHR");
+ if (table->CmdDrawIndexedIndirectCountKHR == nullptr) { table->CmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)StubCmdDrawIndexedIndirectCountKHR; }
+ table->GetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR) gpa(device, "vkGetSemaphoreCounterValueKHR");
+ if (table->GetSemaphoreCounterValueKHR == nullptr) { table->GetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR)StubGetSemaphoreCounterValueKHR; }
+ table->WaitSemaphoresKHR = (PFN_vkWaitSemaphoresKHR) gpa(device, "vkWaitSemaphoresKHR");
+ if (table->WaitSemaphoresKHR == nullptr) { table->WaitSemaphoresKHR = (PFN_vkWaitSemaphoresKHR)StubWaitSemaphoresKHR; }
+ table->SignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR) gpa(device, "vkSignalSemaphoreKHR");
+ if (table->SignalSemaphoreKHR == nullptr) { table->SignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR)StubSignalSemaphoreKHR; }
+ table->GetBufferDeviceAddressKHR = (PFN_vkGetBufferDeviceAddressKHR) gpa(device, "vkGetBufferDeviceAddressKHR");
+ if (table->GetBufferDeviceAddressKHR == nullptr) { table->GetBufferDeviceAddressKHR = (PFN_vkGetBufferDeviceAddressKHR)StubGetBufferDeviceAddressKHR; }
+ table->GetBufferOpaqueCaptureAddressKHR = (PFN_vkGetBufferOpaqueCaptureAddressKHR) gpa(device, "vkGetBufferOpaqueCaptureAddressKHR");
+ if (table->GetBufferOpaqueCaptureAddressKHR == nullptr) { table->GetBufferOpaqueCaptureAddressKHR = (PFN_vkGetBufferOpaqueCaptureAddressKHR)StubGetBufferOpaqueCaptureAddressKHR; }
+ table->GetDeviceMemoryOpaqueCaptureAddressKHR = (PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR) gpa(device, "vkGetDeviceMemoryOpaqueCaptureAddressKHR");
+ if (table->GetDeviceMemoryOpaqueCaptureAddressKHR == nullptr) { table->GetDeviceMemoryOpaqueCaptureAddressKHR = (PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)StubGetDeviceMemoryOpaqueCaptureAddressKHR; }
+ table->GetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR) gpa(device, "vkGetPipelineExecutablePropertiesKHR");
+ if (table->GetPipelineExecutablePropertiesKHR == nullptr) { table->GetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR)StubGetPipelineExecutablePropertiesKHR; }
+ table->GetPipelineExecutableStatisticsKHR = (PFN_vkGetPipelineExecutableStatisticsKHR) gpa(device, "vkGetPipelineExecutableStatisticsKHR");
+ if (table->GetPipelineExecutableStatisticsKHR == nullptr) { table->GetPipelineExecutableStatisticsKHR = (PFN_vkGetPipelineExecutableStatisticsKHR)StubGetPipelineExecutableStatisticsKHR; }
+ table->GetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR) gpa(device, "vkGetPipelineExecutableInternalRepresentationsKHR");
+ if (table->GetPipelineExecutableInternalRepresentationsKHR == nullptr) { table->GetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR)StubGetPipelineExecutableInternalRepresentationsKHR; }
+ table->DebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT) gpa(device, "vkDebugMarkerSetObjectTagEXT");
+ if (table->DebugMarkerSetObjectTagEXT == nullptr) { table->DebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT)StubDebugMarkerSetObjectTagEXT; }
+ table->DebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT) gpa(device, "vkDebugMarkerSetObjectNameEXT");
+ if (table->DebugMarkerSetObjectNameEXT == nullptr) { table->DebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)StubDebugMarkerSetObjectNameEXT; }
+ table->CmdDebugMarkerBeginEXT = (PFN_vkCmdDebugMarkerBeginEXT) gpa(device, "vkCmdDebugMarkerBeginEXT");
+ if (table->CmdDebugMarkerBeginEXT == nullptr) { table->CmdDebugMarkerBeginEXT = (PFN_vkCmdDebugMarkerBeginEXT)StubCmdDebugMarkerBeginEXT; }
+ table->CmdDebugMarkerEndEXT = (PFN_vkCmdDebugMarkerEndEXT) gpa(device, "vkCmdDebugMarkerEndEXT");
+ if (table->CmdDebugMarkerEndEXT == nullptr) { table->CmdDebugMarkerEndEXT = (PFN_vkCmdDebugMarkerEndEXT)StubCmdDebugMarkerEndEXT; }
+ table->CmdDebugMarkerInsertEXT = (PFN_vkCmdDebugMarkerInsertEXT) gpa(device, "vkCmdDebugMarkerInsertEXT");
+ if (table->CmdDebugMarkerInsertEXT == nullptr) { table->CmdDebugMarkerInsertEXT = (PFN_vkCmdDebugMarkerInsertEXT)StubCmdDebugMarkerInsertEXT; }
+ table->CmdBindTransformFeedbackBuffersEXT = (PFN_vkCmdBindTransformFeedbackBuffersEXT) gpa(device, "vkCmdBindTransformFeedbackBuffersEXT");
+ if (table->CmdBindTransformFeedbackBuffersEXT == nullptr) { table->CmdBindTransformFeedbackBuffersEXT = (PFN_vkCmdBindTransformFeedbackBuffersEXT)StubCmdBindTransformFeedbackBuffersEXT; }
+ table->CmdBeginTransformFeedbackEXT = (PFN_vkCmdBeginTransformFeedbackEXT) gpa(device, "vkCmdBeginTransformFeedbackEXT");
+ if (table->CmdBeginTransformFeedbackEXT == nullptr) { table->CmdBeginTransformFeedbackEXT = (PFN_vkCmdBeginTransformFeedbackEXT)StubCmdBeginTransformFeedbackEXT; }
+ table->CmdEndTransformFeedbackEXT = (PFN_vkCmdEndTransformFeedbackEXT) gpa(device, "vkCmdEndTransformFeedbackEXT");
+ if (table->CmdEndTransformFeedbackEXT == nullptr) { table->CmdEndTransformFeedbackEXT = (PFN_vkCmdEndTransformFeedbackEXT)StubCmdEndTransformFeedbackEXT; }
+ table->CmdBeginQueryIndexedEXT = (PFN_vkCmdBeginQueryIndexedEXT) gpa(device, "vkCmdBeginQueryIndexedEXT");
+ if (table->CmdBeginQueryIndexedEXT == nullptr) { table->CmdBeginQueryIndexedEXT = (PFN_vkCmdBeginQueryIndexedEXT)StubCmdBeginQueryIndexedEXT; }
+ table->CmdEndQueryIndexedEXT = (PFN_vkCmdEndQueryIndexedEXT) gpa(device, "vkCmdEndQueryIndexedEXT");
+ if (table->CmdEndQueryIndexedEXT == nullptr) { table->CmdEndQueryIndexedEXT = (PFN_vkCmdEndQueryIndexedEXT)StubCmdEndQueryIndexedEXT; }
+ table->CmdDrawIndirectByteCountEXT = (PFN_vkCmdDrawIndirectByteCountEXT) gpa(device, "vkCmdDrawIndirectByteCountEXT");
+ if (table->CmdDrawIndirectByteCountEXT == nullptr) { table->CmdDrawIndirectByteCountEXT = (PFN_vkCmdDrawIndirectByteCountEXT)StubCmdDrawIndirectByteCountEXT; }
+ table->GetImageViewHandleNVX = (PFN_vkGetImageViewHandleNVX) gpa(device, "vkGetImageViewHandleNVX");
+ if (table->GetImageViewHandleNVX == nullptr) { table->GetImageViewHandleNVX = (PFN_vkGetImageViewHandleNVX)StubGetImageViewHandleNVX; }
+ table->CmdDrawIndirectCountAMD = (PFN_vkCmdDrawIndirectCountAMD) gpa(device, "vkCmdDrawIndirectCountAMD");
+ if (table->CmdDrawIndirectCountAMD == nullptr) { table->CmdDrawIndirectCountAMD = (PFN_vkCmdDrawIndirectCountAMD)StubCmdDrawIndirectCountAMD; }
+ table->CmdDrawIndexedIndirectCountAMD = (PFN_vkCmdDrawIndexedIndirectCountAMD) gpa(device, "vkCmdDrawIndexedIndirectCountAMD");
+ if (table->CmdDrawIndexedIndirectCountAMD == nullptr) { table->CmdDrawIndexedIndirectCountAMD = (PFN_vkCmdDrawIndexedIndirectCountAMD)StubCmdDrawIndexedIndirectCountAMD; }
+ table->GetShaderInfoAMD = (PFN_vkGetShaderInfoAMD) gpa(device, "vkGetShaderInfoAMD");
+ if (table->GetShaderInfoAMD == nullptr) { table->GetShaderInfoAMD = (PFN_vkGetShaderInfoAMD)StubGetShaderInfoAMD; }
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetMemoryWin32HandleNV = (PFN_vkGetMemoryWin32HandleNV) gpa(device, "vkGetMemoryWin32HandleNV");
+ if (table->GetMemoryWin32HandleNV == nullptr) { table->GetMemoryWin32HandleNV = (PFN_vkGetMemoryWin32HandleNV)StubGetMemoryWin32HandleNV; }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+ table->CmdBeginConditionalRenderingEXT = (PFN_vkCmdBeginConditionalRenderingEXT) gpa(device, "vkCmdBeginConditionalRenderingEXT");
+ if (table->CmdBeginConditionalRenderingEXT == nullptr) { table->CmdBeginConditionalRenderingEXT = (PFN_vkCmdBeginConditionalRenderingEXT)StubCmdBeginConditionalRenderingEXT; }
+ table->CmdEndConditionalRenderingEXT = (PFN_vkCmdEndConditionalRenderingEXT) gpa(device, "vkCmdEndConditionalRenderingEXT");
+ if (table->CmdEndConditionalRenderingEXT == nullptr) { table->CmdEndConditionalRenderingEXT = (PFN_vkCmdEndConditionalRenderingEXT)StubCmdEndConditionalRenderingEXT; }
+ table->CmdProcessCommandsNVX = (PFN_vkCmdProcessCommandsNVX) gpa(device, "vkCmdProcessCommandsNVX");
+ if (table->CmdProcessCommandsNVX == nullptr) { table->CmdProcessCommandsNVX = (PFN_vkCmdProcessCommandsNVX)StubCmdProcessCommandsNVX; }
+ table->CmdReserveSpaceForCommandsNVX = (PFN_vkCmdReserveSpaceForCommandsNVX) gpa(device, "vkCmdReserveSpaceForCommandsNVX");
+ if (table->CmdReserveSpaceForCommandsNVX == nullptr) { table->CmdReserveSpaceForCommandsNVX = (PFN_vkCmdReserveSpaceForCommandsNVX)StubCmdReserveSpaceForCommandsNVX; }
+ table->CreateIndirectCommandsLayoutNVX = (PFN_vkCreateIndirectCommandsLayoutNVX) gpa(device, "vkCreateIndirectCommandsLayoutNVX");
+ if (table->CreateIndirectCommandsLayoutNVX == nullptr) { table->CreateIndirectCommandsLayoutNVX = (PFN_vkCreateIndirectCommandsLayoutNVX)StubCreateIndirectCommandsLayoutNVX; }
+ table->DestroyIndirectCommandsLayoutNVX = (PFN_vkDestroyIndirectCommandsLayoutNVX) gpa(device, "vkDestroyIndirectCommandsLayoutNVX");
+ if (table->DestroyIndirectCommandsLayoutNVX == nullptr) { table->DestroyIndirectCommandsLayoutNVX = (PFN_vkDestroyIndirectCommandsLayoutNVX)StubDestroyIndirectCommandsLayoutNVX; }
+ table->CreateObjectTableNVX = (PFN_vkCreateObjectTableNVX) gpa(device, "vkCreateObjectTableNVX");
+ if (table->CreateObjectTableNVX == nullptr) { table->CreateObjectTableNVX = (PFN_vkCreateObjectTableNVX)StubCreateObjectTableNVX; }
+ table->DestroyObjectTableNVX = (PFN_vkDestroyObjectTableNVX) gpa(device, "vkDestroyObjectTableNVX");
+ if (table->DestroyObjectTableNVX == nullptr) { table->DestroyObjectTableNVX = (PFN_vkDestroyObjectTableNVX)StubDestroyObjectTableNVX; }
+ table->RegisterObjectsNVX = (PFN_vkRegisterObjectsNVX) gpa(device, "vkRegisterObjectsNVX");
+ if (table->RegisterObjectsNVX == nullptr) { table->RegisterObjectsNVX = (PFN_vkRegisterObjectsNVX)StubRegisterObjectsNVX; }
+ table->UnregisterObjectsNVX = (PFN_vkUnregisterObjectsNVX) gpa(device, "vkUnregisterObjectsNVX");
+ if (table->UnregisterObjectsNVX == nullptr) { table->UnregisterObjectsNVX = (PFN_vkUnregisterObjectsNVX)StubUnregisterObjectsNVX; }
+ table->CmdSetViewportWScalingNV = (PFN_vkCmdSetViewportWScalingNV) gpa(device, "vkCmdSetViewportWScalingNV");
+ if (table->CmdSetViewportWScalingNV == nullptr) { table->CmdSetViewportWScalingNV = (PFN_vkCmdSetViewportWScalingNV)StubCmdSetViewportWScalingNV; }
+ table->DisplayPowerControlEXT = (PFN_vkDisplayPowerControlEXT) gpa(device, "vkDisplayPowerControlEXT");
+ if (table->DisplayPowerControlEXT == nullptr) { table->DisplayPowerControlEXT = (PFN_vkDisplayPowerControlEXT)StubDisplayPowerControlEXT; }
+ table->RegisterDeviceEventEXT = (PFN_vkRegisterDeviceEventEXT) gpa(device, "vkRegisterDeviceEventEXT");
+ if (table->RegisterDeviceEventEXT == nullptr) { table->RegisterDeviceEventEXT = (PFN_vkRegisterDeviceEventEXT)StubRegisterDeviceEventEXT; }
+ table->RegisterDisplayEventEXT = (PFN_vkRegisterDisplayEventEXT) gpa(device, "vkRegisterDisplayEventEXT");
+ if (table->RegisterDisplayEventEXT == nullptr) { table->RegisterDisplayEventEXT = (PFN_vkRegisterDisplayEventEXT)StubRegisterDisplayEventEXT; }
+ table->GetSwapchainCounterEXT = (PFN_vkGetSwapchainCounterEXT) gpa(device, "vkGetSwapchainCounterEXT");
+ if (table->GetSwapchainCounterEXT == nullptr) { table->GetSwapchainCounterEXT = (PFN_vkGetSwapchainCounterEXT)StubGetSwapchainCounterEXT; }
+ table->GetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE) gpa(device, "vkGetRefreshCycleDurationGOOGLE");
+ if (table->GetRefreshCycleDurationGOOGLE == nullptr) { table->GetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE)StubGetRefreshCycleDurationGOOGLE; }
+ table->GetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE) gpa(device, "vkGetPastPresentationTimingGOOGLE");
+ if (table->GetPastPresentationTimingGOOGLE == nullptr) { table->GetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE)StubGetPastPresentationTimingGOOGLE; }
+ table->CmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT) gpa(device, "vkCmdSetDiscardRectangleEXT");
+ if (table->CmdSetDiscardRectangleEXT == nullptr) { table->CmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)StubCmdSetDiscardRectangleEXT; }
+ table->SetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT) gpa(device, "vkSetHdrMetadataEXT");
+ if (table->SetHdrMetadataEXT == nullptr) { table->SetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT)StubSetHdrMetadataEXT; }
+ table->SetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT) gpa(device, "vkSetDebugUtilsObjectNameEXT");
+ table->SetDebugUtilsObjectTagEXT = (PFN_vkSetDebugUtilsObjectTagEXT) gpa(device, "vkSetDebugUtilsObjectTagEXT");
+ table->QueueBeginDebugUtilsLabelEXT = (PFN_vkQueueBeginDebugUtilsLabelEXT) gpa(device, "vkQueueBeginDebugUtilsLabelEXT");
+ table->QueueEndDebugUtilsLabelEXT = (PFN_vkQueueEndDebugUtilsLabelEXT) gpa(device, "vkQueueEndDebugUtilsLabelEXT");
+ table->QueueInsertDebugUtilsLabelEXT = (PFN_vkQueueInsertDebugUtilsLabelEXT) gpa(device, "vkQueueInsertDebugUtilsLabelEXT");
+ table->CmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT) gpa(device, "vkCmdBeginDebugUtilsLabelEXT");
+ table->CmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT) gpa(device, "vkCmdEndDebugUtilsLabelEXT");
+ table->CmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT) gpa(device, "vkCmdInsertDebugUtilsLabelEXT");
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ table->GetAndroidHardwareBufferPropertiesANDROID = (PFN_vkGetAndroidHardwareBufferPropertiesANDROID) gpa(device, "vkGetAndroidHardwareBufferPropertiesANDROID");
+ if (table->GetAndroidHardwareBufferPropertiesANDROID == nullptr) { table->GetAndroidHardwareBufferPropertiesANDROID = (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)StubGetAndroidHardwareBufferPropertiesANDROID; }
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ table->GetMemoryAndroidHardwareBufferANDROID = (PFN_vkGetMemoryAndroidHardwareBufferANDROID) gpa(device, "vkGetMemoryAndroidHardwareBufferANDROID");
+ if (table->GetMemoryAndroidHardwareBufferANDROID == nullptr) { table->GetMemoryAndroidHardwareBufferANDROID = (PFN_vkGetMemoryAndroidHardwareBufferANDROID)StubGetMemoryAndroidHardwareBufferANDROID; }
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+ table->CmdSetSampleLocationsEXT = (PFN_vkCmdSetSampleLocationsEXT) gpa(device, "vkCmdSetSampleLocationsEXT");
+ if (table->CmdSetSampleLocationsEXT == nullptr) { table->CmdSetSampleLocationsEXT = (PFN_vkCmdSetSampleLocationsEXT)StubCmdSetSampleLocationsEXT; }
+ table->GetImageDrmFormatModifierPropertiesEXT = (PFN_vkGetImageDrmFormatModifierPropertiesEXT) gpa(device, "vkGetImageDrmFormatModifierPropertiesEXT");
+ if (table->GetImageDrmFormatModifierPropertiesEXT == nullptr) { table->GetImageDrmFormatModifierPropertiesEXT = (PFN_vkGetImageDrmFormatModifierPropertiesEXT)StubGetImageDrmFormatModifierPropertiesEXT; }
+ table->CreateValidationCacheEXT = (PFN_vkCreateValidationCacheEXT) gpa(device, "vkCreateValidationCacheEXT");
+ if (table->CreateValidationCacheEXT == nullptr) { table->CreateValidationCacheEXT = (PFN_vkCreateValidationCacheEXT)StubCreateValidationCacheEXT; }
+ table->DestroyValidationCacheEXT = (PFN_vkDestroyValidationCacheEXT) gpa(device, "vkDestroyValidationCacheEXT");
+ if (table->DestroyValidationCacheEXT == nullptr) { table->DestroyValidationCacheEXT = (PFN_vkDestroyValidationCacheEXT)StubDestroyValidationCacheEXT; }
+ table->MergeValidationCachesEXT = (PFN_vkMergeValidationCachesEXT) gpa(device, "vkMergeValidationCachesEXT");
+ if (table->MergeValidationCachesEXT == nullptr) { table->MergeValidationCachesEXT = (PFN_vkMergeValidationCachesEXT)StubMergeValidationCachesEXT; }
+ table->GetValidationCacheDataEXT = (PFN_vkGetValidationCacheDataEXT) gpa(device, "vkGetValidationCacheDataEXT");
+ if (table->GetValidationCacheDataEXT == nullptr) { table->GetValidationCacheDataEXT = (PFN_vkGetValidationCacheDataEXT)StubGetValidationCacheDataEXT; }
+ table->CmdBindShadingRateImageNV = (PFN_vkCmdBindShadingRateImageNV) gpa(device, "vkCmdBindShadingRateImageNV");
+ if (table->CmdBindShadingRateImageNV == nullptr) { table->CmdBindShadingRateImageNV = (PFN_vkCmdBindShadingRateImageNV)StubCmdBindShadingRateImageNV; }
+ table->CmdSetViewportShadingRatePaletteNV = (PFN_vkCmdSetViewportShadingRatePaletteNV) gpa(device, "vkCmdSetViewportShadingRatePaletteNV");
+ if (table->CmdSetViewportShadingRatePaletteNV == nullptr) { table->CmdSetViewportShadingRatePaletteNV = (PFN_vkCmdSetViewportShadingRatePaletteNV)StubCmdSetViewportShadingRatePaletteNV; }
+ table->CmdSetCoarseSampleOrderNV = (PFN_vkCmdSetCoarseSampleOrderNV) gpa(device, "vkCmdSetCoarseSampleOrderNV");
+ if (table->CmdSetCoarseSampleOrderNV == nullptr) { table->CmdSetCoarseSampleOrderNV = (PFN_vkCmdSetCoarseSampleOrderNV)StubCmdSetCoarseSampleOrderNV; }
+ table->CreateAccelerationStructureNV = (PFN_vkCreateAccelerationStructureNV) gpa(device, "vkCreateAccelerationStructureNV");
+ if (table->CreateAccelerationStructureNV == nullptr) { table->CreateAccelerationStructureNV = (PFN_vkCreateAccelerationStructureNV)StubCreateAccelerationStructureNV; }
+ table->DestroyAccelerationStructureNV = (PFN_vkDestroyAccelerationStructureNV) gpa(device, "vkDestroyAccelerationStructureNV");
+ if (table->DestroyAccelerationStructureNV == nullptr) { table->DestroyAccelerationStructureNV = (PFN_vkDestroyAccelerationStructureNV)StubDestroyAccelerationStructureNV; }
+ table->GetAccelerationStructureMemoryRequirementsNV = (PFN_vkGetAccelerationStructureMemoryRequirementsNV) gpa(device, "vkGetAccelerationStructureMemoryRequirementsNV");
+ if (table->GetAccelerationStructureMemoryRequirementsNV == nullptr) { table->GetAccelerationStructureMemoryRequirementsNV = (PFN_vkGetAccelerationStructureMemoryRequirementsNV)StubGetAccelerationStructureMemoryRequirementsNV; }
+ table->BindAccelerationStructureMemoryNV = (PFN_vkBindAccelerationStructureMemoryNV) gpa(device, "vkBindAccelerationStructureMemoryNV");
+ if (table->BindAccelerationStructureMemoryNV == nullptr) { table->BindAccelerationStructureMemoryNV = (PFN_vkBindAccelerationStructureMemoryNV)StubBindAccelerationStructureMemoryNV; }
+ table->CmdBuildAccelerationStructureNV = (PFN_vkCmdBuildAccelerationStructureNV) gpa(device, "vkCmdBuildAccelerationStructureNV");
+ if (table->CmdBuildAccelerationStructureNV == nullptr) { table->CmdBuildAccelerationStructureNV = (PFN_vkCmdBuildAccelerationStructureNV)StubCmdBuildAccelerationStructureNV; }
+ table->CmdCopyAccelerationStructureNV = (PFN_vkCmdCopyAccelerationStructureNV) gpa(device, "vkCmdCopyAccelerationStructureNV");
+ if (table->CmdCopyAccelerationStructureNV == nullptr) { table->CmdCopyAccelerationStructureNV = (PFN_vkCmdCopyAccelerationStructureNV)StubCmdCopyAccelerationStructureNV; }
+ table->CmdTraceRaysNV = (PFN_vkCmdTraceRaysNV) gpa(device, "vkCmdTraceRaysNV");
+ if (table->CmdTraceRaysNV == nullptr) { table->CmdTraceRaysNV = (PFN_vkCmdTraceRaysNV)StubCmdTraceRaysNV; }
+ table->CreateRayTracingPipelinesNV = (PFN_vkCreateRayTracingPipelinesNV) gpa(device, "vkCreateRayTracingPipelinesNV");
+ if (table->CreateRayTracingPipelinesNV == nullptr) { table->CreateRayTracingPipelinesNV = (PFN_vkCreateRayTracingPipelinesNV)StubCreateRayTracingPipelinesNV; }
+ table->GetRayTracingShaderGroupHandlesNV = (PFN_vkGetRayTracingShaderGroupHandlesNV) gpa(device, "vkGetRayTracingShaderGroupHandlesNV");
+ if (table->GetRayTracingShaderGroupHandlesNV == nullptr) { table->GetRayTracingShaderGroupHandlesNV = (PFN_vkGetRayTracingShaderGroupHandlesNV)StubGetRayTracingShaderGroupHandlesNV; }
+ table->GetAccelerationStructureHandleNV = (PFN_vkGetAccelerationStructureHandleNV) gpa(device, "vkGetAccelerationStructureHandleNV");
+ if (table->GetAccelerationStructureHandleNV == nullptr) { table->GetAccelerationStructureHandleNV = (PFN_vkGetAccelerationStructureHandleNV)StubGetAccelerationStructureHandleNV; }
+ table->CmdWriteAccelerationStructuresPropertiesNV = (PFN_vkCmdWriteAccelerationStructuresPropertiesNV) gpa(device, "vkCmdWriteAccelerationStructuresPropertiesNV");
+ if (table->CmdWriteAccelerationStructuresPropertiesNV == nullptr) { table->CmdWriteAccelerationStructuresPropertiesNV = (PFN_vkCmdWriteAccelerationStructuresPropertiesNV)StubCmdWriteAccelerationStructuresPropertiesNV; }
+ table->CompileDeferredNV = (PFN_vkCompileDeferredNV) gpa(device, "vkCompileDeferredNV");
+ if (table->CompileDeferredNV == nullptr) { table->CompileDeferredNV = (PFN_vkCompileDeferredNV)StubCompileDeferredNV; }
+ table->GetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT) gpa(device, "vkGetMemoryHostPointerPropertiesEXT");
+ if (table->GetMemoryHostPointerPropertiesEXT == nullptr) { table->GetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT)StubGetMemoryHostPointerPropertiesEXT; }
+ table->CmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD) gpa(device, "vkCmdWriteBufferMarkerAMD");
+ if (table->CmdWriteBufferMarkerAMD == nullptr) { table->CmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)StubCmdWriteBufferMarkerAMD; }
+ table->GetCalibratedTimestampsEXT = (PFN_vkGetCalibratedTimestampsEXT) gpa(device, "vkGetCalibratedTimestampsEXT");
+ if (table->GetCalibratedTimestampsEXT == nullptr) { table->GetCalibratedTimestampsEXT = (PFN_vkGetCalibratedTimestampsEXT)StubGetCalibratedTimestampsEXT; }
+ table->CmdDrawMeshTasksNV = (PFN_vkCmdDrawMeshTasksNV) gpa(device, "vkCmdDrawMeshTasksNV");
+ if (table->CmdDrawMeshTasksNV == nullptr) { table->CmdDrawMeshTasksNV = (PFN_vkCmdDrawMeshTasksNV)StubCmdDrawMeshTasksNV; }
+ table->CmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV) gpa(device, "vkCmdDrawMeshTasksIndirectNV");
+ if (table->CmdDrawMeshTasksIndirectNV == nullptr) { table->CmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)StubCmdDrawMeshTasksIndirectNV; }
+ table->CmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV) gpa(device, "vkCmdDrawMeshTasksIndirectCountNV");
+ if (table->CmdDrawMeshTasksIndirectCountNV == nullptr) { table->CmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)StubCmdDrawMeshTasksIndirectCountNV; }
+ table->CmdSetExclusiveScissorNV = (PFN_vkCmdSetExclusiveScissorNV) gpa(device, "vkCmdSetExclusiveScissorNV");
+ if (table->CmdSetExclusiveScissorNV == nullptr) { table->CmdSetExclusiveScissorNV = (PFN_vkCmdSetExclusiveScissorNV)StubCmdSetExclusiveScissorNV; }
+ table->CmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV) gpa(device, "vkCmdSetCheckpointNV");
+ if (table->CmdSetCheckpointNV == nullptr) { table->CmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)StubCmdSetCheckpointNV; }
+ table->GetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV) gpa(device, "vkGetQueueCheckpointDataNV");
+ if (table->GetQueueCheckpointDataNV == nullptr) { table->GetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)StubGetQueueCheckpointDataNV; }
+ table->InitializePerformanceApiINTEL = (PFN_vkInitializePerformanceApiINTEL) gpa(device, "vkInitializePerformanceApiINTEL");
+ if (table->InitializePerformanceApiINTEL == nullptr) { table->InitializePerformanceApiINTEL = (PFN_vkInitializePerformanceApiINTEL)StubInitializePerformanceApiINTEL; }
+ table->UninitializePerformanceApiINTEL = (PFN_vkUninitializePerformanceApiINTEL) gpa(device, "vkUninitializePerformanceApiINTEL");
+ if (table->UninitializePerformanceApiINTEL == nullptr) { table->UninitializePerformanceApiINTEL = (PFN_vkUninitializePerformanceApiINTEL)StubUninitializePerformanceApiINTEL; }
+ table->CmdSetPerformanceMarkerINTEL = (PFN_vkCmdSetPerformanceMarkerINTEL) gpa(device, "vkCmdSetPerformanceMarkerINTEL");
+ if (table->CmdSetPerformanceMarkerINTEL == nullptr) { table->CmdSetPerformanceMarkerINTEL = (PFN_vkCmdSetPerformanceMarkerINTEL)StubCmdSetPerformanceMarkerINTEL; }
+ table->CmdSetPerformanceStreamMarkerINTEL = (PFN_vkCmdSetPerformanceStreamMarkerINTEL) gpa(device, "vkCmdSetPerformanceStreamMarkerINTEL");
+ if (table->CmdSetPerformanceStreamMarkerINTEL == nullptr) { table->CmdSetPerformanceStreamMarkerINTEL = (PFN_vkCmdSetPerformanceStreamMarkerINTEL)StubCmdSetPerformanceStreamMarkerINTEL; }
+ table->CmdSetPerformanceOverrideINTEL = (PFN_vkCmdSetPerformanceOverrideINTEL) gpa(device, "vkCmdSetPerformanceOverrideINTEL");
+ if (table->CmdSetPerformanceOverrideINTEL == nullptr) { table->CmdSetPerformanceOverrideINTEL = (PFN_vkCmdSetPerformanceOverrideINTEL)StubCmdSetPerformanceOverrideINTEL; }
+ table->AcquirePerformanceConfigurationINTEL = (PFN_vkAcquirePerformanceConfigurationINTEL) gpa(device, "vkAcquirePerformanceConfigurationINTEL");
+ if (table->AcquirePerformanceConfigurationINTEL == nullptr) { table->AcquirePerformanceConfigurationINTEL = (PFN_vkAcquirePerformanceConfigurationINTEL)StubAcquirePerformanceConfigurationINTEL; }
+ table->ReleasePerformanceConfigurationINTEL = (PFN_vkReleasePerformanceConfigurationINTEL) gpa(device, "vkReleasePerformanceConfigurationINTEL");
+ if (table->ReleasePerformanceConfigurationINTEL == nullptr) { table->ReleasePerformanceConfigurationINTEL = (PFN_vkReleasePerformanceConfigurationINTEL)StubReleasePerformanceConfigurationINTEL; }
+ table->QueueSetPerformanceConfigurationINTEL = (PFN_vkQueueSetPerformanceConfigurationINTEL) gpa(device, "vkQueueSetPerformanceConfigurationINTEL");
+ if (table->QueueSetPerformanceConfigurationINTEL == nullptr) { table->QueueSetPerformanceConfigurationINTEL = (PFN_vkQueueSetPerformanceConfigurationINTEL)StubQueueSetPerformanceConfigurationINTEL; }
+ table->GetPerformanceParameterINTEL = (PFN_vkGetPerformanceParameterINTEL) gpa(device, "vkGetPerformanceParameterINTEL");
+ if (table->GetPerformanceParameterINTEL == nullptr) { table->GetPerformanceParameterINTEL = (PFN_vkGetPerformanceParameterINTEL)StubGetPerformanceParameterINTEL; }
+ table->SetLocalDimmingAMD = (PFN_vkSetLocalDimmingAMD) gpa(device, "vkSetLocalDimmingAMD");
+ if (table->SetLocalDimmingAMD == nullptr) { table->SetLocalDimmingAMD = (PFN_vkSetLocalDimmingAMD)StubSetLocalDimmingAMD; }
+ table->GetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT) gpa(device, "vkGetBufferDeviceAddressEXT");
+ if (table->GetBufferDeviceAddressEXT == nullptr) { table->GetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)StubGetBufferDeviceAddressEXT; }
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->AcquireFullScreenExclusiveModeEXT = (PFN_vkAcquireFullScreenExclusiveModeEXT) gpa(device, "vkAcquireFullScreenExclusiveModeEXT");
+ if (table->AcquireFullScreenExclusiveModeEXT == nullptr) { table->AcquireFullScreenExclusiveModeEXT = (PFN_vkAcquireFullScreenExclusiveModeEXT)StubAcquireFullScreenExclusiveModeEXT; }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->ReleaseFullScreenExclusiveModeEXT = (PFN_vkReleaseFullScreenExclusiveModeEXT) gpa(device, "vkReleaseFullScreenExclusiveModeEXT");
+ if (table->ReleaseFullScreenExclusiveModeEXT == nullptr) { table->ReleaseFullScreenExclusiveModeEXT = (PFN_vkReleaseFullScreenExclusiveModeEXT)StubReleaseFullScreenExclusiveModeEXT; }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT) gpa(device, "vkGetDeviceGroupSurfacePresentModes2EXT");
+ if (table->GetDeviceGroupSurfacePresentModes2EXT == nullptr) { table->GetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)StubGetDeviceGroupSurfacePresentModes2EXT; }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+ table->CmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT) gpa(device, "vkCmdSetLineStippleEXT");
+ if (table->CmdSetLineStippleEXT == nullptr) { table->CmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT)StubCmdSetLineStippleEXT; }
+ table->ResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT) gpa(device, "vkResetQueryPoolEXT");
+ if (table->ResetQueryPoolEXT == nullptr) { table->ResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT)StubResetQueryPoolEXT; }
+}
+
+
+static inline void layer_init_instance_dispatch_table(VkInstance instance, VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa) {
+ memset(table, 0, sizeof(*table));
+ // Instance function pointers
+ table->DestroyInstance = (PFN_vkDestroyInstance) gpa(instance, "vkDestroyInstance");
+ table->EnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) gpa(instance, "vkEnumeratePhysicalDevices");
+ table->GetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures) gpa(instance, "vkGetPhysicalDeviceFeatures");
+ table->GetPhysicalDeviceFormatProperties = (PFN_vkGetPhysicalDeviceFormatProperties) gpa(instance, "vkGetPhysicalDeviceFormatProperties");
+ table->GetPhysicalDeviceImageFormatProperties = (PFN_vkGetPhysicalDeviceImageFormatProperties) gpa(instance, "vkGetPhysicalDeviceImageFormatProperties");
+ table->GetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties) gpa(instance, "vkGetPhysicalDeviceProperties");
+ table->GetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties) gpa(instance, "vkGetPhysicalDeviceQueueFamilyProperties");
+ table->GetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties) gpa(instance, "vkGetPhysicalDeviceMemoryProperties");
+ table->GetInstanceProcAddr = gpa;
+ table->EnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties) gpa(instance, "vkEnumerateDeviceExtensionProperties");
+ table->EnumerateDeviceLayerProperties = (PFN_vkEnumerateDeviceLayerProperties) gpa(instance, "vkEnumerateDeviceLayerProperties");
+ table->GetPhysicalDeviceSparseImageFormatProperties = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties) gpa(instance, "vkGetPhysicalDeviceSparseImageFormatProperties");
+ table->EnumeratePhysicalDeviceGroups = (PFN_vkEnumeratePhysicalDeviceGroups) gpa(instance, "vkEnumeratePhysicalDeviceGroups");
+ table->GetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2) gpa(instance, "vkGetPhysicalDeviceFeatures2");
+ table->GetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) gpa(instance, "vkGetPhysicalDeviceProperties2");
+ table->GetPhysicalDeviceFormatProperties2 = (PFN_vkGetPhysicalDeviceFormatProperties2) gpa(instance, "vkGetPhysicalDeviceFormatProperties2");
+ table->GetPhysicalDeviceImageFormatProperties2 = (PFN_vkGetPhysicalDeviceImageFormatProperties2) gpa(instance, "vkGetPhysicalDeviceImageFormatProperties2");
+ table->GetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2) gpa(instance, "vkGetPhysicalDeviceQueueFamilyProperties2");
+ table->GetPhysicalDeviceMemoryProperties2 = (PFN_vkGetPhysicalDeviceMemoryProperties2) gpa(instance, "vkGetPhysicalDeviceMemoryProperties2");
+ table->GetPhysicalDeviceSparseImageFormatProperties2 = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2) gpa(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2");
+ table->GetPhysicalDeviceExternalBufferProperties = (PFN_vkGetPhysicalDeviceExternalBufferProperties) gpa(instance, "vkGetPhysicalDeviceExternalBufferProperties");
+ table->GetPhysicalDeviceExternalFenceProperties = (PFN_vkGetPhysicalDeviceExternalFenceProperties) gpa(instance, "vkGetPhysicalDeviceExternalFenceProperties");
+ table->GetPhysicalDeviceExternalSemaphoreProperties = (PFN_vkGetPhysicalDeviceExternalSemaphoreProperties) gpa(instance, "vkGetPhysicalDeviceExternalSemaphoreProperties");
+ table->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR) gpa(instance, "vkDestroySurfaceKHR");
+ table->GetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
+ table->GetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
+ table->GetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
+ table->GetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
+ table->GetPhysicalDevicePresentRectanglesKHR = (PFN_vkGetPhysicalDevicePresentRectanglesKHR) gpa(instance, "vkGetPhysicalDevicePresentRectanglesKHR");
+ table->GetPhysicalDeviceDisplayPropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR) gpa(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR");
+ table->GetPhysicalDeviceDisplayPlanePropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR) gpa(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
+ table->GetDisplayPlaneSupportedDisplaysKHR = (PFN_vkGetDisplayPlaneSupportedDisplaysKHR) gpa(instance, "vkGetDisplayPlaneSupportedDisplaysKHR");
+ table->GetDisplayModePropertiesKHR = (PFN_vkGetDisplayModePropertiesKHR) gpa(instance, "vkGetDisplayModePropertiesKHR");
+ table->CreateDisplayModeKHR = (PFN_vkCreateDisplayModeKHR) gpa(instance, "vkCreateDisplayModeKHR");
+ table->GetDisplayPlaneCapabilitiesKHR = (PFN_vkGetDisplayPlaneCapabilitiesKHR) gpa(instance, "vkGetDisplayPlaneCapabilitiesKHR");
+ table->CreateDisplayPlaneSurfaceKHR = (PFN_vkCreateDisplayPlaneSurfaceKHR) gpa(instance, "vkCreateDisplayPlaneSurfaceKHR");
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ table->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR) gpa(instance, "vkCreateXlibSurfaceKHR");
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ table->GetPhysicalDeviceXlibPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ table->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR) gpa(instance, "vkCreateXcbSurfaceKHR");
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ table->GetPhysicalDeviceXcbPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ table->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR) gpa(instance, "vkCreateWaylandSurfaceKHR");
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ table->GetPhysicalDeviceWaylandPresentationSupportKHR = (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ table->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR) gpa(instance, "vkCreateAndroidSurfaceKHR");
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR) gpa(instance, "vkCreateWin32SurfaceKHR");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetPhysicalDeviceWin32PresentationSupportKHR = (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+ table->GetPhysicalDeviceFeatures2KHR = (PFN_vkGetPhysicalDeviceFeatures2KHR) gpa(instance, "vkGetPhysicalDeviceFeatures2KHR");
+ table->GetPhysicalDeviceProperties2KHR = (PFN_vkGetPhysicalDeviceProperties2KHR) gpa(instance, "vkGetPhysicalDeviceProperties2KHR");
+ table->GetPhysicalDeviceFormatProperties2KHR = (PFN_vkGetPhysicalDeviceFormatProperties2KHR) gpa(instance, "vkGetPhysicalDeviceFormatProperties2KHR");
+ table->GetPhysicalDeviceImageFormatProperties2KHR = (PFN_vkGetPhysicalDeviceImageFormatProperties2KHR) gpa(instance, "vkGetPhysicalDeviceImageFormatProperties2KHR");
+ table->GetPhysicalDeviceQueueFamilyProperties2KHR = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR) gpa(instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR");
+ table->GetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2KHR) gpa(instance, "vkGetPhysicalDeviceMemoryProperties2KHR");
+ table->GetPhysicalDeviceSparseImageFormatProperties2KHR = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR) gpa(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
+ table->EnumeratePhysicalDeviceGroupsKHR = (PFN_vkEnumeratePhysicalDeviceGroupsKHR) gpa(instance, "vkEnumeratePhysicalDeviceGroupsKHR");
+ table->GetPhysicalDeviceExternalBufferPropertiesKHR = (PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR) gpa(instance, "vkGetPhysicalDeviceExternalBufferPropertiesKHR");
+ table->GetPhysicalDeviceExternalSemaphorePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR) gpa(instance, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR");
+ table->GetPhysicalDeviceExternalFencePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR) gpa(instance, "vkGetPhysicalDeviceExternalFencePropertiesKHR");
+ table->EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = (PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR) gpa(instance, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR");
+ table->GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = (PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR) gpa(instance, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR");
+ table->GetPhysicalDeviceSurfaceCapabilities2KHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR) gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR");
+ table->GetPhysicalDeviceSurfaceFormats2KHR = (PFN_vkGetPhysicalDeviceSurfaceFormats2KHR) gpa(instance, "vkGetPhysicalDeviceSurfaceFormats2KHR");
+ table->GetPhysicalDeviceDisplayProperties2KHR = (PFN_vkGetPhysicalDeviceDisplayProperties2KHR) gpa(instance, "vkGetPhysicalDeviceDisplayProperties2KHR");
+ table->GetPhysicalDeviceDisplayPlaneProperties2KHR = (PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR) gpa(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR");
+ table->GetDisplayModeProperties2KHR = (PFN_vkGetDisplayModeProperties2KHR) gpa(instance, "vkGetDisplayModeProperties2KHR");
+ table->GetDisplayPlaneCapabilities2KHR = (PFN_vkGetDisplayPlaneCapabilities2KHR) gpa(instance, "vkGetDisplayPlaneCapabilities2KHR");
+ table->CreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT) gpa(instance, "vkCreateDebugReportCallbackEXT");
+ table->DestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT) gpa(instance, "vkDestroyDebugReportCallbackEXT");
+ table->DebugReportMessageEXT = (PFN_vkDebugReportMessageEXT) gpa(instance, "vkDebugReportMessageEXT");
+#ifdef VK_USE_PLATFORM_GGP
+ table->CreateStreamDescriptorSurfaceGGP = (PFN_vkCreateStreamDescriptorSurfaceGGP) gpa(instance, "vkCreateStreamDescriptorSurfaceGGP");
+#endif // VK_USE_PLATFORM_GGP
+ table->GetPhysicalDeviceExternalImageFormatPropertiesNV = (PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV) gpa(instance, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV");
+#ifdef VK_USE_PLATFORM_VI_NN
+ table->CreateViSurfaceNN = (PFN_vkCreateViSurfaceNN) gpa(instance, "vkCreateViSurfaceNN");
+#endif // VK_USE_PLATFORM_VI_NN
+ table->GetPhysicalDeviceGeneratedCommandsPropertiesNVX = (PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX) gpa(instance, "vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX");
+ table->ReleaseDisplayEXT = (PFN_vkReleaseDisplayEXT) gpa(instance, "vkReleaseDisplayEXT");
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ table->AcquireXlibDisplayEXT = (PFN_vkAcquireXlibDisplayEXT) gpa(instance, "vkAcquireXlibDisplayEXT");
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ table->GetRandROutputDisplayEXT = (PFN_vkGetRandROutputDisplayEXT) gpa(instance, "vkGetRandROutputDisplayEXT");
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ table->GetPhysicalDeviceSurfaceCapabilities2EXT = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT) gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilities2EXT");
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ table->CreateIOSSurfaceMVK = (PFN_vkCreateIOSSurfaceMVK) gpa(instance, "vkCreateIOSSurfaceMVK");
+#endif // VK_USE_PLATFORM_IOS_MVK
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ table->CreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK) gpa(instance, "vkCreateMacOSSurfaceMVK");
+#endif // VK_USE_PLATFORM_MACOS_MVK
+ table->CreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT) gpa(instance, "vkCreateDebugUtilsMessengerEXT");
+ table->DestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT) gpa(instance, "vkDestroyDebugUtilsMessengerEXT");
+ table->SubmitDebugUtilsMessageEXT = (PFN_vkSubmitDebugUtilsMessageEXT) gpa(instance, "vkSubmitDebugUtilsMessageEXT");
+ table->GetPhysicalDeviceMultisamplePropertiesEXT = (PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT) gpa(instance, "vkGetPhysicalDeviceMultisamplePropertiesEXT");
+ table->GetPhysicalDeviceCalibrateableTimeDomainsEXT = (PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT) gpa(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT");
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ table->CreateImagePipeSurfaceFUCHSIA = (PFN_vkCreateImagePipeSurfaceFUCHSIA) gpa(instance, "vkCreateImagePipeSurfaceFUCHSIA");
+#endif // VK_USE_PLATFORM_FUCHSIA
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ table->CreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT) gpa(instance, "vkCreateMetalSurfaceEXT");
+#endif // VK_USE_PLATFORM_METAL_EXT
+ table->GetPhysicalDeviceToolPropertiesEXT = (PFN_vkGetPhysicalDeviceToolPropertiesEXT) gpa(instance, "vkGetPhysicalDeviceToolPropertiesEXT");
+ table->GetPhysicalDeviceCooperativeMatrixPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV) gpa(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV");
+ table->GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = (PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV) gpa(instance, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV");
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetPhysicalDeviceSurfacePresentModes2EXT = (PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT) gpa(instance, "vkGetPhysicalDeviceSurfacePresentModes2EXT");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+ table->CreateHeadlessSurfaceEXT = (PFN_vkCreateHeadlessSurfaceEXT) gpa(instance, "vkCreateHeadlessSurfaceEXT");
+}
diff --git a/thirdparty/vulkan/loader/vk_layer_dispatch_table.h b/thirdparty/vulkan/loader/vk_layer_dispatch_table.h
new file mode 100644
index 0000000000..b919447e55
--- /dev/null
+++ b/thirdparty/vulkan/loader/vk_layer_dispatch_table.h
@@ -0,0 +1,682 @@
+// *** THIS FILE IS GENERATED - DO NOT EDIT ***
+// See loader_extension_generator.py for modifications
+
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Mark Lobodzinski <mark@lunarg.com>
+ * Author: Mark Young <marky@lunarg.com>
+ */
+
+#pragma once
+
+typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName);
+
+// Instance function pointer dispatch table
+typedef struct VkLayerInstanceDispatchTable_ {
+ // Manually add in GetPhysicalDeviceProcAddr entry
+ PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr;
+
+ // ---- Core 1_0 commands
+ PFN_vkCreateInstance CreateInstance;
+ PFN_vkDestroyInstance DestroyInstance;
+ PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+ PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
+ PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
+ PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
+ PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties;
+ PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties;
+ PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+ PFN_vkCreateDevice CreateDevice;
+ PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+ PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+ PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties;
+ PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
+
+ // ---- Core 1_1 commands
+ PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion;
+ PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
+ PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
+ PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
+ PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysicalDeviceImageFormatProperties2;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysicalDeviceQueueFamilyProperties2;
+ PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysicalDeviceMemoryProperties2;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysicalDeviceSparseImageFormatProperties2;
+ PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties;
+ PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties;
+ PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties;
+
+ // ---- VK_KHR_surface extension commands
+ PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
+ PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
+ PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
+
+ // ---- VK_KHR_swapchain extension commands
+ PFN_vkGetPhysicalDevicePresentRectanglesKHR GetPhysicalDevicePresentRectanglesKHR;
+
+ // ---- VK_KHR_display extension commands
+ PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR;
+ PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR;
+ PFN_vkGetDisplayPlaneSupportedDisplaysKHR GetDisplayPlaneSupportedDisplaysKHR;
+ PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR;
+ PFN_vkCreateDisplayModeKHR CreateDisplayModeKHR;
+ PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR;
+ PFN_vkCreateDisplayPlaneSurfaceKHR CreateDisplayPlaneSurfaceKHR;
+
+ // ---- VK_KHR_xlib_surface extension commands
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR GetPhysicalDeviceXlibPresentationSupportKHR;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+
+ // ---- VK_KHR_xcb_surface extension commands
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ PFN_vkCreateXcbSurfaceKHR CreateXcbSurfaceKHR;
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR GetPhysicalDeviceXcbPresentationSupportKHR;
+#endif // VK_USE_PLATFORM_XCB_KHR
+
+ // ---- VK_KHR_wayland_surface extension commands
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ PFN_vkCreateWaylandSurfaceKHR CreateWaylandSurfaceKHR;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR GetPhysicalDeviceWaylandPresentationSupportKHR;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+
+ // ---- VK_KHR_android_surface extension commands
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+ // ---- VK_KHR_win32_surface extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkCreateWin32SurfaceKHR CreateWin32SurfaceKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR GetPhysicalDeviceWin32PresentationSupportKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_get_physical_device_properties2 extension commands
+ PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysicalDeviceFeatures2KHR;
+ PFN_vkGetPhysicalDeviceProperties2KHR GetPhysicalDeviceProperties2KHR;
+ PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysicalDeviceFormatProperties2KHR;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysicalDeviceImageFormatProperties2KHR;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysicalDeviceQueueFamilyProperties2KHR;
+ PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysicalDeviceMemoryProperties2KHR;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysicalDeviceSparseImageFormatProperties2KHR;
+
+ // ---- VK_KHR_device_group_creation extension commands
+ PFN_vkEnumeratePhysicalDeviceGroupsKHR EnumeratePhysicalDeviceGroupsKHR;
+
+ // ---- VK_KHR_external_memory_capabilities extension commands
+ PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR;
+
+ // ---- VK_KHR_external_semaphore_capabilities extension commands
+ PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR GetPhysicalDeviceExternalSemaphorePropertiesKHR;
+
+ // ---- VK_KHR_external_fence_capabilities extension commands
+ PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR GetPhysicalDeviceExternalFencePropertiesKHR;
+
+ // ---- VK_KHR_performance_query extension commands
+ PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR;
+ PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR;
+
+ // ---- VK_KHR_get_surface_capabilities2 extension commands
+ PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR GetPhysicalDeviceSurfaceCapabilities2KHR;
+ PFN_vkGetPhysicalDeviceSurfaceFormats2KHR GetPhysicalDeviceSurfaceFormats2KHR;
+
+ // ---- VK_KHR_get_display_properties2 extension commands
+ PFN_vkGetPhysicalDeviceDisplayProperties2KHR GetPhysicalDeviceDisplayProperties2KHR;
+ PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR GetPhysicalDeviceDisplayPlaneProperties2KHR;
+ PFN_vkGetDisplayModeProperties2KHR GetDisplayModeProperties2KHR;
+ PFN_vkGetDisplayPlaneCapabilities2KHR GetDisplayPlaneCapabilities2KHR;
+
+ // ---- VK_EXT_debug_report extension commands
+ PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
+ PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
+ PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+
+ // ---- VK_GGP_stream_descriptor_surface extension commands
+#ifdef VK_USE_PLATFORM_GGP
+ PFN_vkCreateStreamDescriptorSurfaceGGP CreateStreamDescriptorSurfaceGGP;
+#endif // VK_USE_PLATFORM_GGP
+
+ // ---- VK_NV_external_memory_capabilities extension commands
+ PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV GetPhysicalDeviceExternalImageFormatPropertiesNV;
+
+ // ---- VK_NN_vi_surface extension commands
+#ifdef VK_USE_PLATFORM_VI_NN
+ PFN_vkCreateViSurfaceNN CreateViSurfaceNN;
+#endif // VK_USE_PLATFORM_VI_NN
+
+ // ---- VK_NVX_device_generated_commands extension commands
+ PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX GetPhysicalDeviceGeneratedCommandsPropertiesNVX;
+
+ // ---- VK_EXT_direct_mode_display extension commands
+ PFN_vkReleaseDisplayEXT ReleaseDisplayEXT;
+
+ // ---- VK_EXT_acquire_xlib_display extension commands
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ PFN_vkAcquireXlibDisplayEXT AcquireXlibDisplayEXT;
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ PFN_vkGetRandROutputDisplayEXT GetRandROutputDisplayEXT;
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
+ // ---- VK_EXT_display_surface_counter extension commands
+ PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT GetPhysicalDeviceSurfaceCapabilities2EXT;
+
+ // ---- VK_MVK_ios_surface extension commands
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ PFN_vkCreateIOSSurfaceMVK CreateIOSSurfaceMVK;
+#endif // VK_USE_PLATFORM_IOS_MVK
+
+ // ---- VK_MVK_macos_surface extension commands
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ PFN_vkCreateMacOSSurfaceMVK CreateMacOSSurfaceMVK;
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
+ // ---- VK_EXT_debug_utils extension commands
+ PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT;
+ PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT;
+ PFN_vkSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT;
+
+ // ---- VK_EXT_sample_locations extension commands
+ PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT GetPhysicalDeviceMultisamplePropertiesEXT;
+
+ // ---- VK_EXT_calibrated_timestamps extension commands
+ PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT GetPhysicalDeviceCalibrateableTimeDomainsEXT;
+
+ // ---- VK_FUCHSIA_imagepipe_surface extension commands
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ PFN_vkCreateImagePipeSurfaceFUCHSIA CreateImagePipeSurfaceFUCHSIA;
+#endif // VK_USE_PLATFORM_FUCHSIA
+
+ // ---- VK_EXT_metal_surface extension commands
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ PFN_vkCreateMetalSurfaceEXT CreateMetalSurfaceEXT;
+#endif // VK_USE_PLATFORM_METAL_EXT
+
+ // ---- VK_EXT_tooling_info extension commands
+ PFN_vkGetPhysicalDeviceToolPropertiesEXT GetPhysicalDeviceToolPropertiesEXT;
+
+ // ---- VK_NV_cooperative_matrix extension commands
+ PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV GetPhysicalDeviceCooperativeMatrixPropertiesNV;
+
+ // ---- VK_NV_coverage_reduction_mode extension commands
+ PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV;
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT GetPhysicalDeviceSurfacePresentModes2EXT;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_headless_surface extension commands
+ PFN_vkCreateHeadlessSurfaceEXT CreateHeadlessSurfaceEXT;
+} VkLayerInstanceDispatchTable;
+
+// Device function pointer dispatch table
+typedef struct VkLayerDispatchTable_ {
+
+ // ---- Core 1_0 commands
+ PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+ PFN_vkDestroyDevice DestroyDevice;
+ PFN_vkGetDeviceQueue GetDeviceQueue;
+ PFN_vkQueueSubmit QueueSubmit;
+ PFN_vkQueueWaitIdle QueueWaitIdle;
+ PFN_vkDeviceWaitIdle DeviceWaitIdle;
+ PFN_vkAllocateMemory AllocateMemory;
+ PFN_vkFreeMemory FreeMemory;
+ PFN_vkMapMemory MapMemory;
+ PFN_vkUnmapMemory UnmapMemory;
+ PFN_vkFlushMappedMemoryRanges FlushMappedMemoryRanges;
+ PFN_vkInvalidateMappedMemoryRanges InvalidateMappedMemoryRanges;
+ PFN_vkGetDeviceMemoryCommitment GetDeviceMemoryCommitment;
+ PFN_vkBindBufferMemory BindBufferMemory;
+ PFN_vkBindImageMemory BindImageMemory;
+ PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements;
+ PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements;
+ PFN_vkGetImageSparseMemoryRequirements GetImageSparseMemoryRequirements;
+ PFN_vkQueueBindSparse QueueBindSparse;
+ PFN_vkCreateFence CreateFence;
+ PFN_vkDestroyFence DestroyFence;
+ PFN_vkResetFences ResetFences;
+ PFN_vkGetFenceStatus GetFenceStatus;
+ PFN_vkWaitForFences WaitForFences;
+ PFN_vkCreateSemaphore CreateSemaphore;
+ PFN_vkDestroySemaphore DestroySemaphore;
+ PFN_vkCreateEvent CreateEvent;
+ PFN_vkDestroyEvent DestroyEvent;
+ PFN_vkGetEventStatus GetEventStatus;
+ PFN_vkSetEvent SetEvent;
+ PFN_vkResetEvent ResetEvent;
+ PFN_vkCreateQueryPool CreateQueryPool;
+ PFN_vkDestroyQueryPool DestroyQueryPool;
+ PFN_vkGetQueryPoolResults GetQueryPoolResults;
+ PFN_vkCreateBuffer CreateBuffer;
+ PFN_vkDestroyBuffer DestroyBuffer;
+ PFN_vkCreateBufferView CreateBufferView;
+ PFN_vkDestroyBufferView DestroyBufferView;
+ PFN_vkCreateImage CreateImage;
+ PFN_vkDestroyImage DestroyImage;
+ PFN_vkGetImageSubresourceLayout GetImageSubresourceLayout;
+ PFN_vkCreateImageView CreateImageView;
+ PFN_vkDestroyImageView DestroyImageView;
+ PFN_vkCreateShaderModule CreateShaderModule;
+ PFN_vkDestroyShaderModule DestroyShaderModule;
+ PFN_vkCreatePipelineCache CreatePipelineCache;
+ PFN_vkDestroyPipelineCache DestroyPipelineCache;
+ PFN_vkGetPipelineCacheData GetPipelineCacheData;
+ PFN_vkMergePipelineCaches MergePipelineCaches;
+ PFN_vkCreateGraphicsPipelines CreateGraphicsPipelines;
+ PFN_vkCreateComputePipelines CreateComputePipelines;
+ PFN_vkDestroyPipeline DestroyPipeline;
+ PFN_vkCreatePipelineLayout CreatePipelineLayout;
+ PFN_vkDestroyPipelineLayout DestroyPipelineLayout;
+ PFN_vkCreateSampler CreateSampler;
+ PFN_vkDestroySampler DestroySampler;
+ PFN_vkCreateDescriptorSetLayout CreateDescriptorSetLayout;
+ PFN_vkDestroyDescriptorSetLayout DestroyDescriptorSetLayout;
+ PFN_vkCreateDescriptorPool CreateDescriptorPool;
+ PFN_vkDestroyDescriptorPool DestroyDescriptorPool;
+ PFN_vkResetDescriptorPool ResetDescriptorPool;
+ PFN_vkAllocateDescriptorSets AllocateDescriptorSets;
+ PFN_vkFreeDescriptorSets FreeDescriptorSets;
+ PFN_vkUpdateDescriptorSets UpdateDescriptorSets;
+ PFN_vkCreateFramebuffer CreateFramebuffer;
+ PFN_vkDestroyFramebuffer DestroyFramebuffer;
+ PFN_vkCreateRenderPass CreateRenderPass;
+ PFN_vkDestroyRenderPass DestroyRenderPass;
+ PFN_vkGetRenderAreaGranularity GetRenderAreaGranularity;
+ PFN_vkCreateCommandPool CreateCommandPool;
+ PFN_vkDestroyCommandPool DestroyCommandPool;
+ PFN_vkResetCommandPool ResetCommandPool;
+ PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+ PFN_vkFreeCommandBuffers FreeCommandBuffers;
+ PFN_vkBeginCommandBuffer BeginCommandBuffer;
+ PFN_vkEndCommandBuffer EndCommandBuffer;
+ PFN_vkResetCommandBuffer ResetCommandBuffer;
+ PFN_vkCmdBindPipeline CmdBindPipeline;
+ PFN_vkCmdSetViewport CmdSetViewport;
+ PFN_vkCmdSetScissor CmdSetScissor;
+ PFN_vkCmdSetLineWidth CmdSetLineWidth;
+ PFN_vkCmdSetDepthBias CmdSetDepthBias;
+ PFN_vkCmdSetBlendConstants CmdSetBlendConstants;
+ PFN_vkCmdSetDepthBounds CmdSetDepthBounds;
+ PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask;
+ PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask;
+ PFN_vkCmdSetStencilReference CmdSetStencilReference;
+ PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
+ PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
+ PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
+ PFN_vkCmdDraw CmdDraw;
+ PFN_vkCmdDrawIndexed CmdDrawIndexed;
+ PFN_vkCmdDrawIndirect CmdDrawIndirect;
+ PFN_vkCmdDrawIndexedIndirect CmdDrawIndexedIndirect;
+ PFN_vkCmdDispatch CmdDispatch;
+ PFN_vkCmdDispatchIndirect CmdDispatchIndirect;
+ PFN_vkCmdCopyBuffer CmdCopyBuffer;
+ PFN_vkCmdCopyImage CmdCopyImage;
+ PFN_vkCmdBlitImage CmdBlitImage;
+ PFN_vkCmdCopyBufferToImage CmdCopyBufferToImage;
+ PFN_vkCmdCopyImageToBuffer CmdCopyImageToBuffer;
+ PFN_vkCmdUpdateBuffer CmdUpdateBuffer;
+ PFN_vkCmdFillBuffer CmdFillBuffer;
+ PFN_vkCmdClearColorImage CmdClearColorImage;
+ PFN_vkCmdClearDepthStencilImage CmdClearDepthStencilImage;
+ PFN_vkCmdClearAttachments CmdClearAttachments;
+ PFN_vkCmdResolveImage CmdResolveImage;
+ PFN_vkCmdSetEvent CmdSetEvent;
+ PFN_vkCmdResetEvent CmdResetEvent;
+ PFN_vkCmdWaitEvents CmdWaitEvents;
+ PFN_vkCmdPipelineBarrier CmdPipelineBarrier;
+ PFN_vkCmdBeginQuery CmdBeginQuery;
+ PFN_vkCmdEndQuery CmdEndQuery;
+ PFN_vkCmdResetQueryPool CmdResetQueryPool;
+ PFN_vkCmdWriteTimestamp CmdWriteTimestamp;
+ PFN_vkCmdCopyQueryPoolResults CmdCopyQueryPoolResults;
+ PFN_vkCmdPushConstants CmdPushConstants;
+ PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
+ PFN_vkCmdNextSubpass CmdNextSubpass;
+ PFN_vkCmdEndRenderPass CmdEndRenderPass;
+ PFN_vkCmdExecuteCommands CmdExecuteCommands;
+
+ // ---- Core 1_1 commands
+ PFN_vkBindBufferMemory2 BindBufferMemory2;
+ PFN_vkBindImageMemory2 BindImageMemory2;
+ PFN_vkGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeatures;
+ PFN_vkCmdSetDeviceMask CmdSetDeviceMask;
+ PFN_vkCmdDispatchBase CmdDispatchBase;
+ PFN_vkGetImageMemoryRequirements2 GetImageMemoryRequirements2;
+ PFN_vkGetBufferMemoryRequirements2 GetBufferMemoryRequirements2;
+ PFN_vkGetImageSparseMemoryRequirements2 GetImageSparseMemoryRequirements2;
+ PFN_vkTrimCommandPool TrimCommandPool;
+ PFN_vkGetDeviceQueue2 GetDeviceQueue2;
+ PFN_vkCreateSamplerYcbcrConversion CreateSamplerYcbcrConversion;
+ PFN_vkDestroySamplerYcbcrConversion DestroySamplerYcbcrConversion;
+ PFN_vkCreateDescriptorUpdateTemplate CreateDescriptorUpdateTemplate;
+ PFN_vkDestroyDescriptorUpdateTemplate DestroyDescriptorUpdateTemplate;
+ PFN_vkUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplate;
+ PFN_vkGetDescriptorSetLayoutSupport GetDescriptorSetLayoutSupport;
+
+ // ---- Core 1_2 commands
+ PFN_vkCmdDrawIndirectCount CmdDrawIndirectCount;
+ PFN_vkCmdDrawIndexedIndirectCount CmdDrawIndexedIndirectCount;
+ PFN_vkCreateRenderPass2 CreateRenderPass2;
+ PFN_vkCmdBeginRenderPass2 CmdBeginRenderPass2;
+ PFN_vkCmdNextSubpass2 CmdNextSubpass2;
+ PFN_vkCmdEndRenderPass2 CmdEndRenderPass2;
+ PFN_vkResetQueryPool ResetQueryPool;
+ PFN_vkGetSemaphoreCounterValue GetSemaphoreCounterValue;
+ PFN_vkWaitSemaphores WaitSemaphores;
+ PFN_vkSignalSemaphore SignalSemaphore;
+ PFN_vkGetBufferDeviceAddress GetBufferDeviceAddress;
+ PFN_vkGetBufferOpaqueCaptureAddress GetBufferOpaqueCaptureAddress;
+ PFN_vkGetDeviceMemoryOpaqueCaptureAddress GetDeviceMemoryOpaqueCaptureAddress;
+
+ // ---- VK_KHR_swapchain extension commands
+ PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
+ PFN_vkDestroySwapchainKHR DestroySwapchainKHR;
+ PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
+ PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
+ PFN_vkQueuePresentKHR QueuePresentKHR;
+ PFN_vkGetDeviceGroupPresentCapabilitiesKHR GetDeviceGroupPresentCapabilitiesKHR;
+ PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR;
+ PFN_vkAcquireNextImage2KHR AcquireNextImage2KHR;
+
+ // ---- VK_KHR_display_swapchain extension commands
+ PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR;
+
+ // ---- VK_KHR_device_group extension commands
+ PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR GetDeviceGroupPeerMemoryFeaturesKHR;
+ PFN_vkCmdSetDeviceMaskKHR CmdSetDeviceMaskKHR;
+ PFN_vkCmdDispatchBaseKHR CmdDispatchBaseKHR;
+
+ // ---- VK_KHR_maintenance1 extension commands
+ PFN_vkTrimCommandPoolKHR TrimCommandPoolKHR;
+
+ // ---- VK_KHR_external_memory_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetMemoryWin32HandleKHR GetMemoryWin32HandleKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetMemoryWin32HandlePropertiesKHR GetMemoryWin32HandlePropertiesKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_memory_fd extension commands
+ PFN_vkGetMemoryFdKHR GetMemoryFdKHR;
+ PFN_vkGetMemoryFdPropertiesKHR GetMemoryFdPropertiesKHR;
+
+ // ---- VK_KHR_external_semaphore_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkImportSemaphoreWin32HandleKHR ImportSemaphoreWin32HandleKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetSemaphoreWin32HandleKHR GetSemaphoreWin32HandleKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_semaphore_fd extension commands
+ PFN_vkImportSemaphoreFdKHR ImportSemaphoreFdKHR;
+ PFN_vkGetSemaphoreFdKHR GetSemaphoreFdKHR;
+
+ // ---- VK_KHR_push_descriptor extension commands
+ PFN_vkCmdPushDescriptorSetKHR CmdPushDescriptorSetKHR;
+ PFN_vkCmdPushDescriptorSetWithTemplateKHR CmdPushDescriptorSetWithTemplateKHR;
+
+ // ---- VK_KHR_descriptor_update_template extension commands
+ PFN_vkCreateDescriptorUpdateTemplateKHR CreateDescriptorUpdateTemplateKHR;
+ PFN_vkDestroyDescriptorUpdateTemplateKHR DestroyDescriptorUpdateTemplateKHR;
+ PFN_vkUpdateDescriptorSetWithTemplateKHR UpdateDescriptorSetWithTemplateKHR;
+
+ // ---- VK_KHR_create_renderpass2 extension commands
+ PFN_vkCreateRenderPass2KHR CreateRenderPass2KHR;
+ PFN_vkCmdBeginRenderPass2KHR CmdBeginRenderPass2KHR;
+ PFN_vkCmdNextSubpass2KHR CmdNextSubpass2KHR;
+ PFN_vkCmdEndRenderPass2KHR CmdEndRenderPass2KHR;
+
+ // ---- VK_KHR_shared_presentable_image extension commands
+ PFN_vkGetSwapchainStatusKHR GetSwapchainStatusKHR;
+
+ // ---- VK_KHR_external_fence_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkImportFenceWin32HandleKHR ImportFenceWin32HandleKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetFenceWin32HandleKHR GetFenceWin32HandleKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_fence_fd extension commands
+ PFN_vkImportFenceFdKHR ImportFenceFdKHR;
+ PFN_vkGetFenceFdKHR GetFenceFdKHR;
+
+ // ---- VK_KHR_performance_query extension commands
+ PFN_vkAcquireProfilingLockKHR AcquireProfilingLockKHR;
+ PFN_vkReleaseProfilingLockKHR ReleaseProfilingLockKHR;
+
+ // ---- VK_KHR_get_memory_requirements2 extension commands
+ PFN_vkGetImageMemoryRequirements2KHR GetImageMemoryRequirements2KHR;
+ PFN_vkGetBufferMemoryRequirements2KHR GetBufferMemoryRequirements2KHR;
+ PFN_vkGetImageSparseMemoryRequirements2KHR GetImageSparseMemoryRequirements2KHR;
+
+ // ---- VK_KHR_sampler_ycbcr_conversion extension commands
+ PFN_vkCreateSamplerYcbcrConversionKHR CreateSamplerYcbcrConversionKHR;
+ PFN_vkDestroySamplerYcbcrConversionKHR DestroySamplerYcbcrConversionKHR;
+
+ // ---- VK_KHR_bind_memory2 extension commands
+ PFN_vkBindBufferMemory2KHR BindBufferMemory2KHR;
+ PFN_vkBindImageMemory2KHR BindImageMemory2KHR;
+
+ // ---- VK_KHR_maintenance3 extension commands
+ PFN_vkGetDescriptorSetLayoutSupportKHR GetDescriptorSetLayoutSupportKHR;
+
+ // ---- VK_KHR_draw_indirect_count extension commands
+ PFN_vkCmdDrawIndirectCountKHR CmdDrawIndirectCountKHR;
+ PFN_vkCmdDrawIndexedIndirectCountKHR CmdDrawIndexedIndirectCountKHR;
+
+ // ---- VK_KHR_timeline_semaphore extension commands
+ PFN_vkGetSemaphoreCounterValueKHR GetSemaphoreCounterValueKHR;
+ PFN_vkWaitSemaphoresKHR WaitSemaphoresKHR;
+ PFN_vkSignalSemaphoreKHR SignalSemaphoreKHR;
+
+ // ---- VK_KHR_buffer_device_address extension commands
+ PFN_vkGetBufferDeviceAddressKHR GetBufferDeviceAddressKHR;
+ PFN_vkGetBufferOpaqueCaptureAddressKHR GetBufferOpaqueCaptureAddressKHR;
+ PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR GetDeviceMemoryOpaqueCaptureAddressKHR;
+
+ // ---- VK_KHR_pipeline_executable_properties extension commands
+ PFN_vkGetPipelineExecutablePropertiesKHR GetPipelineExecutablePropertiesKHR;
+ PFN_vkGetPipelineExecutableStatisticsKHR GetPipelineExecutableStatisticsKHR;
+ PFN_vkGetPipelineExecutableInternalRepresentationsKHR GetPipelineExecutableInternalRepresentationsKHR;
+
+ // ---- VK_EXT_debug_marker extension commands
+ PFN_vkDebugMarkerSetObjectTagEXT DebugMarkerSetObjectTagEXT;
+ PFN_vkDebugMarkerSetObjectNameEXT DebugMarkerSetObjectNameEXT;
+ PFN_vkCmdDebugMarkerBeginEXT CmdDebugMarkerBeginEXT;
+ PFN_vkCmdDebugMarkerEndEXT CmdDebugMarkerEndEXT;
+ PFN_vkCmdDebugMarkerInsertEXT CmdDebugMarkerInsertEXT;
+
+ // ---- VK_EXT_transform_feedback extension commands
+ PFN_vkCmdBindTransformFeedbackBuffersEXT CmdBindTransformFeedbackBuffersEXT;
+ PFN_vkCmdBeginTransformFeedbackEXT CmdBeginTransformFeedbackEXT;
+ PFN_vkCmdEndTransformFeedbackEXT CmdEndTransformFeedbackEXT;
+ PFN_vkCmdBeginQueryIndexedEXT CmdBeginQueryIndexedEXT;
+ PFN_vkCmdEndQueryIndexedEXT CmdEndQueryIndexedEXT;
+ PFN_vkCmdDrawIndirectByteCountEXT CmdDrawIndirectByteCountEXT;
+
+ // ---- VK_NVX_image_view_handle extension commands
+ PFN_vkGetImageViewHandleNVX GetImageViewHandleNVX;
+
+ // ---- VK_AMD_draw_indirect_count extension commands
+ PFN_vkCmdDrawIndirectCountAMD CmdDrawIndirectCountAMD;
+ PFN_vkCmdDrawIndexedIndirectCountAMD CmdDrawIndexedIndirectCountAMD;
+
+ // ---- VK_AMD_shader_info extension commands
+ PFN_vkGetShaderInfoAMD GetShaderInfoAMD;
+
+ // ---- VK_NV_external_memory_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetMemoryWin32HandleNV GetMemoryWin32HandleNV;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_conditional_rendering extension commands
+ PFN_vkCmdBeginConditionalRenderingEXT CmdBeginConditionalRenderingEXT;
+ PFN_vkCmdEndConditionalRenderingEXT CmdEndConditionalRenderingEXT;
+
+ // ---- VK_NVX_device_generated_commands extension commands
+ PFN_vkCmdProcessCommandsNVX CmdProcessCommandsNVX;
+ PFN_vkCmdReserveSpaceForCommandsNVX CmdReserveSpaceForCommandsNVX;
+ PFN_vkCreateIndirectCommandsLayoutNVX CreateIndirectCommandsLayoutNVX;
+ PFN_vkDestroyIndirectCommandsLayoutNVX DestroyIndirectCommandsLayoutNVX;
+ PFN_vkCreateObjectTableNVX CreateObjectTableNVX;
+ PFN_vkDestroyObjectTableNVX DestroyObjectTableNVX;
+ PFN_vkRegisterObjectsNVX RegisterObjectsNVX;
+ PFN_vkUnregisterObjectsNVX UnregisterObjectsNVX;
+
+ // ---- VK_NV_clip_space_w_scaling extension commands
+ PFN_vkCmdSetViewportWScalingNV CmdSetViewportWScalingNV;
+
+ // ---- VK_EXT_display_control extension commands
+ PFN_vkDisplayPowerControlEXT DisplayPowerControlEXT;
+ PFN_vkRegisterDeviceEventEXT RegisterDeviceEventEXT;
+ PFN_vkRegisterDisplayEventEXT RegisterDisplayEventEXT;
+ PFN_vkGetSwapchainCounterEXT GetSwapchainCounterEXT;
+
+ // ---- VK_GOOGLE_display_timing extension commands
+ PFN_vkGetRefreshCycleDurationGOOGLE GetRefreshCycleDurationGOOGLE;
+ PFN_vkGetPastPresentationTimingGOOGLE GetPastPresentationTimingGOOGLE;
+
+ // ---- VK_EXT_discard_rectangles extension commands
+ PFN_vkCmdSetDiscardRectangleEXT CmdSetDiscardRectangleEXT;
+
+ // ---- VK_EXT_hdr_metadata extension commands
+ PFN_vkSetHdrMetadataEXT SetHdrMetadataEXT;
+
+ // ---- VK_EXT_debug_utils extension commands
+ PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT;
+ PFN_vkSetDebugUtilsObjectTagEXT SetDebugUtilsObjectTagEXT;
+ PFN_vkQueueBeginDebugUtilsLabelEXT QueueBeginDebugUtilsLabelEXT;
+ PFN_vkQueueEndDebugUtilsLabelEXT QueueEndDebugUtilsLabelEXT;
+ PFN_vkQueueInsertDebugUtilsLabelEXT QueueInsertDebugUtilsLabelEXT;
+ PFN_vkCmdBeginDebugUtilsLabelEXT CmdBeginDebugUtilsLabelEXT;
+ PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT;
+ PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT;
+
+ // ---- VK_ANDROID_external_memory_android_hardware_buffer extension commands
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ PFN_vkGetAndroidHardwareBufferPropertiesANDROID GetAndroidHardwareBufferPropertiesANDROID;
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ PFN_vkGetMemoryAndroidHardwareBufferANDROID GetMemoryAndroidHardwareBufferANDROID;
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+ // ---- VK_EXT_sample_locations extension commands
+ PFN_vkCmdSetSampleLocationsEXT CmdSetSampleLocationsEXT;
+
+ // ---- VK_EXT_image_drm_format_modifier extension commands
+ PFN_vkGetImageDrmFormatModifierPropertiesEXT GetImageDrmFormatModifierPropertiesEXT;
+
+ // ---- VK_EXT_validation_cache extension commands
+ PFN_vkCreateValidationCacheEXT CreateValidationCacheEXT;
+ PFN_vkDestroyValidationCacheEXT DestroyValidationCacheEXT;
+ PFN_vkMergeValidationCachesEXT MergeValidationCachesEXT;
+ PFN_vkGetValidationCacheDataEXT GetValidationCacheDataEXT;
+
+ // ---- VK_NV_shading_rate_image extension commands
+ PFN_vkCmdBindShadingRateImageNV CmdBindShadingRateImageNV;
+ PFN_vkCmdSetViewportShadingRatePaletteNV CmdSetViewportShadingRatePaletteNV;
+ PFN_vkCmdSetCoarseSampleOrderNV CmdSetCoarseSampleOrderNV;
+
+ // ---- VK_NV_ray_tracing extension commands
+ PFN_vkCreateAccelerationStructureNV CreateAccelerationStructureNV;
+ PFN_vkDestroyAccelerationStructureNV DestroyAccelerationStructureNV;
+ PFN_vkGetAccelerationStructureMemoryRequirementsNV GetAccelerationStructureMemoryRequirementsNV;
+ PFN_vkBindAccelerationStructureMemoryNV BindAccelerationStructureMemoryNV;
+ PFN_vkCmdBuildAccelerationStructureNV CmdBuildAccelerationStructureNV;
+ PFN_vkCmdCopyAccelerationStructureNV CmdCopyAccelerationStructureNV;
+ PFN_vkCmdTraceRaysNV CmdTraceRaysNV;
+ PFN_vkCreateRayTracingPipelinesNV CreateRayTracingPipelinesNV;
+ PFN_vkGetRayTracingShaderGroupHandlesNV GetRayTracingShaderGroupHandlesNV;
+ PFN_vkGetAccelerationStructureHandleNV GetAccelerationStructureHandleNV;
+ PFN_vkCmdWriteAccelerationStructuresPropertiesNV CmdWriteAccelerationStructuresPropertiesNV;
+ PFN_vkCompileDeferredNV CompileDeferredNV;
+
+ // ---- VK_EXT_external_memory_host extension commands
+ PFN_vkGetMemoryHostPointerPropertiesEXT GetMemoryHostPointerPropertiesEXT;
+
+ // ---- VK_AMD_buffer_marker extension commands
+ PFN_vkCmdWriteBufferMarkerAMD CmdWriteBufferMarkerAMD;
+
+ // ---- VK_EXT_calibrated_timestamps extension commands
+ PFN_vkGetCalibratedTimestampsEXT GetCalibratedTimestampsEXT;
+
+ // ---- VK_NV_mesh_shader extension commands
+ PFN_vkCmdDrawMeshTasksNV CmdDrawMeshTasksNV;
+ PFN_vkCmdDrawMeshTasksIndirectNV CmdDrawMeshTasksIndirectNV;
+ PFN_vkCmdDrawMeshTasksIndirectCountNV CmdDrawMeshTasksIndirectCountNV;
+
+ // ---- VK_NV_scissor_exclusive extension commands
+ PFN_vkCmdSetExclusiveScissorNV CmdSetExclusiveScissorNV;
+
+ // ---- VK_NV_device_diagnostic_checkpoints extension commands
+ PFN_vkCmdSetCheckpointNV CmdSetCheckpointNV;
+ PFN_vkGetQueueCheckpointDataNV GetQueueCheckpointDataNV;
+
+ // ---- VK_INTEL_performance_query extension commands
+ PFN_vkInitializePerformanceApiINTEL InitializePerformanceApiINTEL;
+ PFN_vkUninitializePerformanceApiINTEL UninitializePerformanceApiINTEL;
+ PFN_vkCmdSetPerformanceMarkerINTEL CmdSetPerformanceMarkerINTEL;
+ PFN_vkCmdSetPerformanceStreamMarkerINTEL CmdSetPerformanceStreamMarkerINTEL;
+ PFN_vkCmdSetPerformanceOverrideINTEL CmdSetPerformanceOverrideINTEL;
+ PFN_vkAcquirePerformanceConfigurationINTEL AcquirePerformanceConfigurationINTEL;
+ PFN_vkReleasePerformanceConfigurationINTEL ReleasePerformanceConfigurationINTEL;
+ PFN_vkQueueSetPerformanceConfigurationINTEL QueueSetPerformanceConfigurationINTEL;
+ PFN_vkGetPerformanceParameterINTEL GetPerformanceParameterINTEL;
+
+ // ---- VK_AMD_display_native_hdr extension commands
+ PFN_vkSetLocalDimmingAMD SetLocalDimmingAMD;
+
+ // ---- VK_EXT_buffer_device_address extension commands
+ PFN_vkGetBufferDeviceAddressEXT GetBufferDeviceAddressEXT;
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkAcquireFullScreenExclusiveModeEXT AcquireFullScreenExclusiveModeEXT;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkReleaseFullScreenExclusiveModeEXT ReleaseFullScreenExclusiveModeEXT;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetDeviceGroupSurfacePresentModes2EXT GetDeviceGroupSurfacePresentModes2EXT;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_line_rasterization extension commands
+ PFN_vkCmdSetLineStippleEXT CmdSetLineStippleEXT;
+
+ // ---- VK_EXT_host_query_reset extension commands
+ PFN_vkResetQueryPoolEXT ResetQueryPoolEXT;
+} VkLayerDispatchTable;
+
+
diff --git a/thirdparty/vulkan/loader/vk_loader_extensions.c b/thirdparty/vulkan/loader/vk_loader_extensions.c
new file mode 100644
index 0000000000..542b8b4af4
--- /dev/null
+++ b/thirdparty/vulkan/loader/vk_loader_extensions.c
@@ -0,0 +1,4734 @@
+// *** THIS FILE IS GENERATED - DO NOT EDIT ***
+// See loader_extension_generator.py for modifications
+
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Mark Lobodzinski <mark@lunarg.com>
+ * Author: Mark Young <marky@lunarg.com>
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "vk_loader_platform.h"
+#include "loader.h"
+#include "vk_loader_extensions.h"
+#include <vulkan/vk_icd.h>
+#include "wsi.h"
+#include "debug_utils.h"
+#include "extension_manual.h"
+
+// Device extension error function
+VKAPI_ATTR VkResult VKAPI_CALL vkDevExtError(VkDevice dev) {
+ struct loader_device *found_dev;
+ // The device going in is a trampoline device
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(dev, &found_dev, NULL);
+
+ if (icd_term)
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "Bad destination in loader trampoline dispatch,"
+ "Are layers and extensions that you are calling enabled?");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+}
+
+VKAPI_ATTR bool VKAPI_CALL loader_icd_init_entries(struct loader_icd_term *icd_term, VkInstance inst,
+ const PFN_vkGetInstanceProcAddr fp_gipa) {
+
+#define LOOKUP_GIPA(func, required) \
+ do { \
+ icd_term->dispatch.func = (PFN_vk##func)fp_gipa(inst, "vk" #func); \
+ if (!icd_term->dispatch.func && required) { \
+ loader_log((struct loader_instance *)inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \
+ loader_platform_get_proc_address_error("vk" #func)); \
+ return false; \
+ } \
+ } while (0)
+
+
+ // ---- Core 1_0
+ LOOKUP_GIPA(DestroyInstance, true);
+ LOOKUP_GIPA(EnumeratePhysicalDevices, true);
+ LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
+ LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
+ LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
+ LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
+ LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
+ LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
+ LOOKUP_GIPA(GetDeviceProcAddr, true);
+ LOOKUP_GIPA(CreateDevice, true);
+ LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
+ LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
+
+ // ---- Core 1_1
+ LOOKUP_GIPA(EnumeratePhysicalDeviceGroups, false);
+ LOOKUP_GIPA(GetPhysicalDeviceFeatures2, false);
+ LOOKUP_GIPA(GetPhysicalDeviceProperties2, false);
+ LOOKUP_GIPA(GetPhysicalDeviceFormatProperties2, false);
+ LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties2, false);
+ LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties2, false);
+ LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties2, false);
+ LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties2, false);
+ LOOKUP_GIPA(GetPhysicalDeviceExternalBufferProperties, false);
+ LOOKUP_GIPA(GetPhysicalDeviceExternalFenceProperties, false);
+ LOOKUP_GIPA(GetPhysicalDeviceExternalSemaphoreProperties, false);
+
+ // ---- VK_KHR_surface extension commands
+ LOOKUP_GIPA(DestroySurfaceKHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false);
+
+ // ---- VK_KHR_swapchain extension commands
+ LOOKUP_GIPA(CreateSwapchainKHR, false);
+ LOOKUP_GIPA(GetDeviceGroupSurfacePresentModesKHR, false);
+ LOOKUP_GIPA(GetPhysicalDevicePresentRectanglesKHR, false);
+
+ // ---- VK_KHR_display extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceDisplayPropertiesKHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceDisplayPlanePropertiesKHR, false);
+ LOOKUP_GIPA(GetDisplayPlaneSupportedDisplaysKHR, false);
+ LOOKUP_GIPA(GetDisplayModePropertiesKHR, false);
+ LOOKUP_GIPA(CreateDisplayModeKHR, false);
+ LOOKUP_GIPA(GetDisplayPlaneCapabilitiesKHR, false);
+ LOOKUP_GIPA(CreateDisplayPlaneSurfaceKHR, false);
+
+ // ---- VK_KHR_display_swapchain extension commands
+ LOOKUP_GIPA(CreateSharedSwapchainsKHR, false);
+
+ // ---- VK_KHR_xlib_surface extension commands
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ LOOKUP_GIPA(CreateXlibSurfaceKHR, false);
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ LOOKUP_GIPA(GetPhysicalDeviceXlibPresentationSupportKHR, false);
+#endif // VK_USE_PLATFORM_XLIB_KHR
+
+ // ---- VK_KHR_xcb_surface extension commands
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ LOOKUP_GIPA(CreateXcbSurfaceKHR, false);
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
+#endif // VK_USE_PLATFORM_XCB_KHR
+
+ // ---- VK_KHR_wayland_surface extension commands
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ LOOKUP_GIPA(CreateWaylandSurfaceKHR, false);
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ LOOKUP_GIPA(GetPhysicalDeviceWaylandPresentationSupportKHR, false);
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+
+ // ---- VK_KHR_android_surface extension commands
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ LOOKUP_GIPA(CreateAndroidSurfaceKHR, false);
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+ // ---- VK_KHR_win32_surface extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ LOOKUP_GIPA(CreateWin32SurfaceKHR, false);
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_get_physical_device_properties2 extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceFeatures2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceFormatProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties2KHR, false);
+
+ // ---- VK_KHR_device_group_creation extension commands
+ LOOKUP_GIPA(EnumeratePhysicalDeviceGroupsKHR, false);
+
+ // ---- VK_KHR_external_memory_capabilities extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceExternalBufferPropertiesKHR, false);
+
+ // ---- VK_KHR_external_semaphore_capabilities extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceExternalSemaphorePropertiesKHR, false);
+
+ // ---- VK_KHR_external_fence_capabilities extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceExternalFencePropertiesKHR, false);
+
+ // ---- VK_KHR_performance_query extension commands
+ LOOKUP_GIPA(EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR, false);
+
+ // ---- VK_KHR_get_surface_capabilities2 extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilities2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormats2KHR, false);
+
+ // ---- VK_KHR_get_display_properties2 extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceDisplayProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceDisplayPlaneProperties2KHR, false);
+ LOOKUP_GIPA(GetDisplayModeProperties2KHR, false);
+ LOOKUP_GIPA(GetDisplayPlaneCapabilities2KHR, false);
+
+ // ---- VK_EXT_debug_report extension commands
+ LOOKUP_GIPA(CreateDebugReportCallbackEXT, false);
+ LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false);
+ LOOKUP_GIPA(DebugReportMessageEXT, false);
+
+ // ---- VK_EXT_debug_marker extension commands
+ LOOKUP_GIPA(DebugMarkerSetObjectTagEXT, false);
+ LOOKUP_GIPA(DebugMarkerSetObjectNameEXT, false);
+
+ // ---- VK_GGP_stream_descriptor_surface extension commands
+#ifdef VK_USE_PLATFORM_GGP
+ LOOKUP_GIPA(CreateStreamDescriptorSurfaceGGP, false);
+#endif // VK_USE_PLATFORM_GGP
+
+ // ---- VK_NV_external_memory_capabilities extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceExternalImageFormatPropertiesNV, false);
+
+ // ---- VK_NN_vi_surface extension commands
+#ifdef VK_USE_PLATFORM_VI_NN
+ LOOKUP_GIPA(CreateViSurfaceNN, false);
+#endif // VK_USE_PLATFORM_VI_NN
+
+ // ---- VK_NVX_device_generated_commands extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceGeneratedCommandsPropertiesNVX, false);
+
+ // ---- VK_EXT_direct_mode_display extension commands
+ LOOKUP_GIPA(ReleaseDisplayEXT, false);
+
+ // ---- VK_EXT_acquire_xlib_display extension commands
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ LOOKUP_GIPA(AcquireXlibDisplayEXT, false);
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ LOOKUP_GIPA(GetRandROutputDisplayEXT, false);
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
+ // ---- VK_EXT_display_surface_counter extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilities2EXT, false);
+
+ // ---- VK_MVK_ios_surface extension commands
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ LOOKUP_GIPA(CreateIOSSurfaceMVK, false);
+#endif // VK_USE_PLATFORM_IOS_MVK
+
+ // ---- VK_MVK_macos_surface extension commands
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ LOOKUP_GIPA(CreateMacOSSurfaceMVK, false);
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
+ // ---- VK_EXT_debug_utils extension commands
+ LOOKUP_GIPA(SetDebugUtilsObjectNameEXT, false);
+ LOOKUP_GIPA(SetDebugUtilsObjectTagEXT, false);
+ LOOKUP_GIPA(QueueBeginDebugUtilsLabelEXT, false);
+ LOOKUP_GIPA(QueueEndDebugUtilsLabelEXT, false);
+ LOOKUP_GIPA(QueueInsertDebugUtilsLabelEXT, false);
+ LOOKUP_GIPA(CmdBeginDebugUtilsLabelEXT, false);
+ LOOKUP_GIPA(CmdEndDebugUtilsLabelEXT, false);
+ LOOKUP_GIPA(CmdInsertDebugUtilsLabelEXT, false);
+ LOOKUP_GIPA(CreateDebugUtilsMessengerEXT, false);
+ LOOKUP_GIPA(DestroyDebugUtilsMessengerEXT, false);
+ LOOKUP_GIPA(SubmitDebugUtilsMessageEXT, false);
+
+ // ---- VK_EXT_sample_locations extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceMultisamplePropertiesEXT, false);
+
+ // ---- VK_EXT_calibrated_timestamps extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceCalibrateableTimeDomainsEXT, false);
+
+ // ---- VK_FUCHSIA_imagepipe_surface extension commands
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ LOOKUP_GIPA(CreateImagePipeSurfaceFUCHSIA, false);
+#endif // VK_USE_PLATFORM_FUCHSIA
+
+ // ---- VK_EXT_metal_surface extension commands
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ LOOKUP_GIPA(CreateMetalSurfaceEXT, false);
+#endif // VK_USE_PLATFORM_METAL_EXT
+
+ // ---- VK_EXT_tooling_info extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceToolPropertiesEXT, false);
+
+ // ---- VK_NV_cooperative_matrix extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceCooperativeMatrixPropertiesNV, false);
+
+ // ---- VK_NV_coverage_reduction_mode extension commands
+ LOOKUP_GIPA(GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV, false);
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModes2EXT, false);
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ LOOKUP_GIPA(GetDeviceGroupSurfacePresentModes2EXT, false);
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_headless_surface extension commands
+ LOOKUP_GIPA(CreateHeadlessSurfaceEXT, false);
+
+#undef LOOKUP_GIPA
+
+ return true;
+};
+
+// Init Device function pointer dispatch table with core commands
+VKAPI_ATTR void VKAPI_CALL loader_init_device_dispatch_table(struct loader_dev_dispatch_table *dev_table, PFN_vkGetDeviceProcAddr gpa,
+ VkDevice dev) {
+ VkLayerDispatchTable *table = &dev_table->core_dispatch;
+ for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) dev_table->ext_dispatch.dev_ext[i] = (PFN_vkDevExt)vkDevExtError;
+
+ // ---- Core 1_0 commands
+ table->GetDeviceProcAddr = gpa;
+ table->DestroyDevice = (PFN_vkDestroyDevice)gpa(dev, "vkDestroyDevice");
+ table->GetDeviceQueue = (PFN_vkGetDeviceQueue)gpa(dev, "vkGetDeviceQueue");
+ table->QueueSubmit = (PFN_vkQueueSubmit)gpa(dev, "vkQueueSubmit");
+ table->QueueWaitIdle = (PFN_vkQueueWaitIdle)gpa(dev, "vkQueueWaitIdle");
+ table->DeviceWaitIdle = (PFN_vkDeviceWaitIdle)gpa(dev, "vkDeviceWaitIdle");
+ table->AllocateMemory = (PFN_vkAllocateMemory)gpa(dev, "vkAllocateMemory");
+ table->FreeMemory = (PFN_vkFreeMemory)gpa(dev, "vkFreeMemory");
+ table->MapMemory = (PFN_vkMapMemory)gpa(dev, "vkMapMemory");
+ table->UnmapMemory = (PFN_vkUnmapMemory)gpa(dev, "vkUnmapMemory");
+ table->FlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)gpa(dev, "vkFlushMappedMemoryRanges");
+ table->InvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)gpa(dev, "vkInvalidateMappedMemoryRanges");
+ table->GetDeviceMemoryCommitment = (PFN_vkGetDeviceMemoryCommitment)gpa(dev, "vkGetDeviceMemoryCommitment");
+ table->BindBufferMemory = (PFN_vkBindBufferMemory)gpa(dev, "vkBindBufferMemory");
+ table->BindImageMemory = (PFN_vkBindImageMemory)gpa(dev, "vkBindImageMemory");
+ table->GetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)gpa(dev, "vkGetBufferMemoryRequirements");
+ table->GetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)gpa(dev, "vkGetImageMemoryRequirements");
+ table->GetImageSparseMemoryRequirements = (PFN_vkGetImageSparseMemoryRequirements)gpa(dev, "vkGetImageSparseMemoryRequirements");
+ table->QueueBindSparse = (PFN_vkQueueBindSparse)gpa(dev, "vkQueueBindSparse");
+ table->CreateFence = (PFN_vkCreateFence)gpa(dev, "vkCreateFence");
+ table->DestroyFence = (PFN_vkDestroyFence)gpa(dev, "vkDestroyFence");
+ table->ResetFences = (PFN_vkResetFences)gpa(dev, "vkResetFences");
+ table->GetFenceStatus = (PFN_vkGetFenceStatus)gpa(dev, "vkGetFenceStatus");
+ table->WaitForFences = (PFN_vkWaitForFences)gpa(dev, "vkWaitForFences");
+ table->CreateSemaphore = (PFN_vkCreateSemaphore)gpa(dev, "vkCreateSemaphore");
+ table->DestroySemaphore = (PFN_vkDestroySemaphore)gpa(dev, "vkDestroySemaphore");
+ table->CreateEvent = (PFN_vkCreateEvent)gpa(dev, "vkCreateEvent");
+ table->DestroyEvent = (PFN_vkDestroyEvent)gpa(dev, "vkDestroyEvent");
+ table->GetEventStatus = (PFN_vkGetEventStatus)gpa(dev, "vkGetEventStatus");
+ table->SetEvent = (PFN_vkSetEvent)gpa(dev, "vkSetEvent");
+ table->ResetEvent = (PFN_vkResetEvent)gpa(dev, "vkResetEvent");
+ table->CreateQueryPool = (PFN_vkCreateQueryPool)gpa(dev, "vkCreateQueryPool");
+ table->DestroyQueryPool = (PFN_vkDestroyQueryPool)gpa(dev, "vkDestroyQueryPool");
+ table->GetQueryPoolResults = (PFN_vkGetQueryPoolResults)gpa(dev, "vkGetQueryPoolResults");
+ table->CreateBuffer = (PFN_vkCreateBuffer)gpa(dev, "vkCreateBuffer");
+ table->DestroyBuffer = (PFN_vkDestroyBuffer)gpa(dev, "vkDestroyBuffer");
+ table->CreateBufferView = (PFN_vkCreateBufferView)gpa(dev, "vkCreateBufferView");
+ table->DestroyBufferView = (PFN_vkDestroyBufferView)gpa(dev, "vkDestroyBufferView");
+ table->CreateImage = (PFN_vkCreateImage)gpa(dev, "vkCreateImage");
+ table->DestroyImage = (PFN_vkDestroyImage)gpa(dev, "vkDestroyImage");
+ table->GetImageSubresourceLayout = (PFN_vkGetImageSubresourceLayout)gpa(dev, "vkGetImageSubresourceLayout");
+ table->CreateImageView = (PFN_vkCreateImageView)gpa(dev, "vkCreateImageView");
+ table->DestroyImageView = (PFN_vkDestroyImageView)gpa(dev, "vkDestroyImageView");
+ table->CreateShaderModule = (PFN_vkCreateShaderModule)gpa(dev, "vkCreateShaderModule");
+ table->DestroyShaderModule = (PFN_vkDestroyShaderModule)gpa(dev, "vkDestroyShaderModule");
+ table->CreatePipelineCache = (PFN_vkCreatePipelineCache)gpa(dev, "vkCreatePipelineCache");
+ table->DestroyPipelineCache = (PFN_vkDestroyPipelineCache)gpa(dev, "vkDestroyPipelineCache");
+ table->GetPipelineCacheData = (PFN_vkGetPipelineCacheData)gpa(dev, "vkGetPipelineCacheData");
+ table->MergePipelineCaches = (PFN_vkMergePipelineCaches)gpa(dev, "vkMergePipelineCaches");
+ table->CreateGraphicsPipelines = (PFN_vkCreateGraphicsPipelines)gpa(dev, "vkCreateGraphicsPipelines");
+ table->CreateComputePipelines = (PFN_vkCreateComputePipelines)gpa(dev, "vkCreateComputePipelines");
+ table->DestroyPipeline = (PFN_vkDestroyPipeline)gpa(dev, "vkDestroyPipeline");
+ table->CreatePipelineLayout = (PFN_vkCreatePipelineLayout)gpa(dev, "vkCreatePipelineLayout");
+ table->DestroyPipelineLayout = (PFN_vkDestroyPipelineLayout)gpa(dev, "vkDestroyPipelineLayout");
+ table->CreateSampler = (PFN_vkCreateSampler)gpa(dev, "vkCreateSampler");
+ table->DestroySampler = (PFN_vkDestroySampler)gpa(dev, "vkDestroySampler");
+ table->CreateDescriptorSetLayout = (PFN_vkCreateDescriptorSetLayout)gpa(dev, "vkCreateDescriptorSetLayout");
+ table->DestroyDescriptorSetLayout = (PFN_vkDestroyDescriptorSetLayout)gpa(dev, "vkDestroyDescriptorSetLayout");
+ table->CreateDescriptorPool = (PFN_vkCreateDescriptorPool)gpa(dev, "vkCreateDescriptorPool");
+ table->DestroyDescriptorPool = (PFN_vkDestroyDescriptorPool)gpa(dev, "vkDestroyDescriptorPool");
+ table->ResetDescriptorPool = (PFN_vkResetDescriptorPool)gpa(dev, "vkResetDescriptorPool");
+ table->AllocateDescriptorSets = (PFN_vkAllocateDescriptorSets)gpa(dev, "vkAllocateDescriptorSets");
+ table->FreeDescriptorSets = (PFN_vkFreeDescriptorSets)gpa(dev, "vkFreeDescriptorSets");
+ table->UpdateDescriptorSets = (PFN_vkUpdateDescriptorSets)gpa(dev, "vkUpdateDescriptorSets");
+ table->CreateFramebuffer = (PFN_vkCreateFramebuffer)gpa(dev, "vkCreateFramebuffer");
+ table->DestroyFramebuffer = (PFN_vkDestroyFramebuffer)gpa(dev, "vkDestroyFramebuffer");
+ table->CreateRenderPass = (PFN_vkCreateRenderPass)gpa(dev, "vkCreateRenderPass");
+ table->DestroyRenderPass = (PFN_vkDestroyRenderPass)gpa(dev, "vkDestroyRenderPass");
+ table->GetRenderAreaGranularity = (PFN_vkGetRenderAreaGranularity)gpa(dev, "vkGetRenderAreaGranularity");
+ table->CreateCommandPool = (PFN_vkCreateCommandPool)gpa(dev, "vkCreateCommandPool");
+ table->DestroyCommandPool = (PFN_vkDestroyCommandPool)gpa(dev, "vkDestroyCommandPool");
+ table->ResetCommandPool = (PFN_vkResetCommandPool)gpa(dev, "vkResetCommandPool");
+ table->AllocateCommandBuffers = (PFN_vkAllocateCommandBuffers)gpa(dev, "vkAllocateCommandBuffers");
+ table->FreeCommandBuffers = (PFN_vkFreeCommandBuffers)gpa(dev, "vkFreeCommandBuffers");
+ table->BeginCommandBuffer = (PFN_vkBeginCommandBuffer)gpa(dev, "vkBeginCommandBuffer");
+ table->EndCommandBuffer = (PFN_vkEndCommandBuffer)gpa(dev, "vkEndCommandBuffer");
+ table->ResetCommandBuffer = (PFN_vkResetCommandBuffer)gpa(dev, "vkResetCommandBuffer");
+ table->CmdBindPipeline = (PFN_vkCmdBindPipeline)gpa(dev, "vkCmdBindPipeline");
+ table->CmdSetViewport = (PFN_vkCmdSetViewport)gpa(dev, "vkCmdSetViewport");
+ table->CmdSetScissor = (PFN_vkCmdSetScissor)gpa(dev, "vkCmdSetScissor");
+ table->CmdSetLineWidth = (PFN_vkCmdSetLineWidth)gpa(dev, "vkCmdSetLineWidth");
+ table->CmdSetDepthBias = (PFN_vkCmdSetDepthBias)gpa(dev, "vkCmdSetDepthBias");
+ table->CmdSetBlendConstants = (PFN_vkCmdSetBlendConstants)gpa(dev, "vkCmdSetBlendConstants");
+ table->CmdSetDepthBounds = (PFN_vkCmdSetDepthBounds)gpa(dev, "vkCmdSetDepthBounds");
+ table->CmdSetStencilCompareMask = (PFN_vkCmdSetStencilCompareMask)gpa(dev, "vkCmdSetStencilCompareMask");
+ table->CmdSetStencilWriteMask = (PFN_vkCmdSetStencilWriteMask)gpa(dev, "vkCmdSetStencilWriteMask");
+ table->CmdSetStencilReference = (PFN_vkCmdSetStencilReference)gpa(dev, "vkCmdSetStencilReference");
+ table->CmdBindDescriptorSets = (PFN_vkCmdBindDescriptorSets)gpa(dev, "vkCmdBindDescriptorSets");
+ table->CmdBindIndexBuffer = (PFN_vkCmdBindIndexBuffer)gpa(dev, "vkCmdBindIndexBuffer");
+ table->CmdBindVertexBuffers = (PFN_vkCmdBindVertexBuffers)gpa(dev, "vkCmdBindVertexBuffers");
+ table->CmdDraw = (PFN_vkCmdDraw)gpa(dev, "vkCmdDraw");
+ table->CmdDrawIndexed = (PFN_vkCmdDrawIndexed)gpa(dev, "vkCmdDrawIndexed");
+ table->CmdDrawIndirect = (PFN_vkCmdDrawIndirect)gpa(dev, "vkCmdDrawIndirect");
+ table->CmdDrawIndexedIndirect = (PFN_vkCmdDrawIndexedIndirect)gpa(dev, "vkCmdDrawIndexedIndirect");
+ table->CmdDispatch = (PFN_vkCmdDispatch)gpa(dev, "vkCmdDispatch");
+ table->CmdDispatchIndirect = (PFN_vkCmdDispatchIndirect)gpa(dev, "vkCmdDispatchIndirect");
+ table->CmdCopyBuffer = (PFN_vkCmdCopyBuffer)gpa(dev, "vkCmdCopyBuffer");
+ table->CmdCopyImage = (PFN_vkCmdCopyImage)gpa(dev, "vkCmdCopyImage");
+ table->CmdBlitImage = (PFN_vkCmdBlitImage)gpa(dev, "vkCmdBlitImage");
+ table->CmdCopyBufferToImage = (PFN_vkCmdCopyBufferToImage)gpa(dev, "vkCmdCopyBufferToImage");
+ table->CmdCopyImageToBuffer = (PFN_vkCmdCopyImageToBuffer)gpa(dev, "vkCmdCopyImageToBuffer");
+ table->CmdUpdateBuffer = (PFN_vkCmdUpdateBuffer)gpa(dev, "vkCmdUpdateBuffer");
+ table->CmdFillBuffer = (PFN_vkCmdFillBuffer)gpa(dev, "vkCmdFillBuffer");
+ table->CmdClearColorImage = (PFN_vkCmdClearColorImage)gpa(dev, "vkCmdClearColorImage");
+ table->CmdClearDepthStencilImage = (PFN_vkCmdClearDepthStencilImage)gpa(dev, "vkCmdClearDepthStencilImage");
+ table->CmdClearAttachments = (PFN_vkCmdClearAttachments)gpa(dev, "vkCmdClearAttachments");
+ table->CmdResolveImage = (PFN_vkCmdResolveImage)gpa(dev, "vkCmdResolveImage");
+ table->CmdSetEvent = (PFN_vkCmdSetEvent)gpa(dev, "vkCmdSetEvent");
+ table->CmdResetEvent = (PFN_vkCmdResetEvent)gpa(dev, "vkCmdResetEvent");
+ table->CmdWaitEvents = (PFN_vkCmdWaitEvents)gpa(dev, "vkCmdWaitEvents");
+ table->CmdPipelineBarrier = (PFN_vkCmdPipelineBarrier)gpa(dev, "vkCmdPipelineBarrier");
+ table->CmdBeginQuery = (PFN_vkCmdBeginQuery)gpa(dev, "vkCmdBeginQuery");
+ table->CmdEndQuery = (PFN_vkCmdEndQuery)gpa(dev, "vkCmdEndQuery");
+ table->CmdResetQueryPool = (PFN_vkCmdResetQueryPool)gpa(dev, "vkCmdResetQueryPool");
+ table->CmdWriteTimestamp = (PFN_vkCmdWriteTimestamp)gpa(dev, "vkCmdWriteTimestamp");
+ table->CmdCopyQueryPoolResults = (PFN_vkCmdCopyQueryPoolResults)gpa(dev, "vkCmdCopyQueryPoolResults");
+ table->CmdPushConstants = (PFN_vkCmdPushConstants)gpa(dev, "vkCmdPushConstants");
+ table->CmdBeginRenderPass = (PFN_vkCmdBeginRenderPass)gpa(dev, "vkCmdBeginRenderPass");
+ table->CmdNextSubpass = (PFN_vkCmdNextSubpass)gpa(dev, "vkCmdNextSubpass");
+ table->CmdEndRenderPass = (PFN_vkCmdEndRenderPass)gpa(dev, "vkCmdEndRenderPass");
+ table->CmdExecuteCommands = (PFN_vkCmdExecuteCommands)gpa(dev, "vkCmdExecuteCommands");
+
+ // ---- Core 1_1 commands
+ table->BindBufferMemory2 = (PFN_vkBindBufferMemory2)gpa(dev, "vkBindBufferMemory2");
+ table->BindImageMemory2 = (PFN_vkBindImageMemory2)gpa(dev, "vkBindImageMemory2");
+ table->GetDeviceGroupPeerMemoryFeatures = (PFN_vkGetDeviceGroupPeerMemoryFeatures)gpa(dev, "vkGetDeviceGroupPeerMemoryFeatures");
+ table->CmdSetDeviceMask = (PFN_vkCmdSetDeviceMask)gpa(dev, "vkCmdSetDeviceMask");
+ table->CmdDispatchBase = (PFN_vkCmdDispatchBase)gpa(dev, "vkCmdDispatchBase");
+ table->GetImageMemoryRequirements2 = (PFN_vkGetImageMemoryRequirements2)gpa(dev, "vkGetImageMemoryRequirements2");
+ table->GetBufferMemoryRequirements2 = (PFN_vkGetBufferMemoryRequirements2)gpa(dev, "vkGetBufferMemoryRequirements2");
+ table->GetImageSparseMemoryRequirements2 = (PFN_vkGetImageSparseMemoryRequirements2)gpa(dev, "vkGetImageSparseMemoryRequirements2");
+ table->TrimCommandPool = (PFN_vkTrimCommandPool)gpa(dev, "vkTrimCommandPool");
+ table->GetDeviceQueue2 = (PFN_vkGetDeviceQueue2)gpa(dev, "vkGetDeviceQueue2");
+ table->CreateSamplerYcbcrConversion = (PFN_vkCreateSamplerYcbcrConversion)gpa(dev, "vkCreateSamplerYcbcrConversion");
+ table->DestroySamplerYcbcrConversion = (PFN_vkDestroySamplerYcbcrConversion)gpa(dev, "vkDestroySamplerYcbcrConversion");
+ table->CreateDescriptorUpdateTemplate = (PFN_vkCreateDescriptorUpdateTemplate)gpa(dev, "vkCreateDescriptorUpdateTemplate");
+ table->DestroyDescriptorUpdateTemplate = (PFN_vkDestroyDescriptorUpdateTemplate)gpa(dev, "vkDestroyDescriptorUpdateTemplate");
+ table->UpdateDescriptorSetWithTemplate = (PFN_vkUpdateDescriptorSetWithTemplate)gpa(dev, "vkUpdateDescriptorSetWithTemplate");
+ table->GetDescriptorSetLayoutSupport = (PFN_vkGetDescriptorSetLayoutSupport)gpa(dev, "vkGetDescriptorSetLayoutSupport");
+
+ // ---- Core 1_2 commands
+ table->CmdDrawIndirectCount = (PFN_vkCmdDrawIndirectCount)gpa(dev, "vkCmdDrawIndirectCount");
+ table->CmdDrawIndexedIndirectCount = (PFN_vkCmdDrawIndexedIndirectCount)gpa(dev, "vkCmdDrawIndexedIndirectCount");
+ table->CreateRenderPass2 = (PFN_vkCreateRenderPass2)gpa(dev, "vkCreateRenderPass2");
+ table->CmdBeginRenderPass2 = (PFN_vkCmdBeginRenderPass2)gpa(dev, "vkCmdBeginRenderPass2");
+ table->CmdNextSubpass2 = (PFN_vkCmdNextSubpass2)gpa(dev, "vkCmdNextSubpass2");
+ table->CmdEndRenderPass2 = (PFN_vkCmdEndRenderPass2)gpa(dev, "vkCmdEndRenderPass2");
+ table->ResetQueryPool = (PFN_vkResetQueryPool)gpa(dev, "vkResetQueryPool");
+ table->GetSemaphoreCounterValue = (PFN_vkGetSemaphoreCounterValue)gpa(dev, "vkGetSemaphoreCounterValue");
+ table->WaitSemaphores = (PFN_vkWaitSemaphores)gpa(dev, "vkWaitSemaphores");
+ table->SignalSemaphore = (PFN_vkSignalSemaphore)gpa(dev, "vkSignalSemaphore");
+ table->GetBufferDeviceAddress = (PFN_vkGetBufferDeviceAddress)gpa(dev, "vkGetBufferDeviceAddress");
+ table->GetBufferOpaqueCaptureAddress = (PFN_vkGetBufferOpaqueCaptureAddress)gpa(dev, "vkGetBufferOpaqueCaptureAddress");
+ table->GetDeviceMemoryOpaqueCaptureAddress = (PFN_vkGetDeviceMemoryOpaqueCaptureAddress)gpa(dev, "vkGetDeviceMemoryOpaqueCaptureAddress");
+}
+
+// Init Device function pointer dispatch table with extension commands
+VKAPI_ATTR void VKAPI_CALL loader_init_device_extension_dispatch_table(struct loader_dev_dispatch_table *dev_table,
+ PFN_vkGetInstanceProcAddr gipa,
+ PFN_vkGetDeviceProcAddr gdpa,
+ VkInstance inst,
+ VkDevice dev) {
+ VkLayerDispatchTable *table = &dev_table->core_dispatch;
+
+ // ---- VK_KHR_swapchain extension commands
+ table->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)gdpa(dev, "vkCreateSwapchainKHR");
+ table->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)gdpa(dev, "vkDestroySwapchainKHR");
+ table->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)gdpa(dev, "vkGetSwapchainImagesKHR");
+ table->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)gdpa(dev, "vkAcquireNextImageKHR");
+ table->QueuePresentKHR = (PFN_vkQueuePresentKHR)gdpa(dev, "vkQueuePresentKHR");
+ table->GetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR)gdpa(dev, "vkGetDeviceGroupPresentCapabilitiesKHR");
+ table->GetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR)gdpa(dev, "vkGetDeviceGroupSurfacePresentModesKHR");
+ table->AcquireNextImage2KHR = (PFN_vkAcquireNextImage2KHR)gdpa(dev, "vkAcquireNextImage2KHR");
+
+ // ---- VK_KHR_display_swapchain extension commands
+ table->CreateSharedSwapchainsKHR = (PFN_vkCreateSharedSwapchainsKHR)gdpa(dev, "vkCreateSharedSwapchainsKHR");
+
+ // ---- VK_KHR_device_group extension commands
+ table->GetDeviceGroupPeerMemoryFeaturesKHR = (PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)gdpa(dev, "vkGetDeviceGroupPeerMemoryFeaturesKHR");
+ table->CmdSetDeviceMaskKHR = (PFN_vkCmdSetDeviceMaskKHR)gdpa(dev, "vkCmdSetDeviceMaskKHR");
+ table->CmdDispatchBaseKHR = (PFN_vkCmdDispatchBaseKHR)gdpa(dev, "vkCmdDispatchBaseKHR");
+
+ // ---- VK_KHR_maintenance1 extension commands
+ table->TrimCommandPoolKHR = (PFN_vkTrimCommandPoolKHR)gdpa(dev, "vkTrimCommandPoolKHR");
+
+ // ---- VK_KHR_external_memory_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetMemoryWin32HandleKHR = (PFN_vkGetMemoryWin32HandleKHR)gdpa(dev, "vkGetMemoryWin32HandleKHR");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetMemoryWin32HandlePropertiesKHR = (PFN_vkGetMemoryWin32HandlePropertiesKHR)gdpa(dev, "vkGetMemoryWin32HandlePropertiesKHR");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_memory_fd extension commands
+ table->GetMemoryFdKHR = (PFN_vkGetMemoryFdKHR)gdpa(dev, "vkGetMemoryFdKHR");
+ table->GetMemoryFdPropertiesKHR = (PFN_vkGetMemoryFdPropertiesKHR)gdpa(dev, "vkGetMemoryFdPropertiesKHR");
+
+ // ---- VK_KHR_external_semaphore_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->ImportSemaphoreWin32HandleKHR = (PFN_vkImportSemaphoreWin32HandleKHR)gdpa(dev, "vkImportSemaphoreWin32HandleKHR");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetSemaphoreWin32HandleKHR = (PFN_vkGetSemaphoreWin32HandleKHR)gdpa(dev, "vkGetSemaphoreWin32HandleKHR");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_semaphore_fd extension commands
+ table->ImportSemaphoreFdKHR = (PFN_vkImportSemaphoreFdKHR)gdpa(dev, "vkImportSemaphoreFdKHR");
+ table->GetSemaphoreFdKHR = (PFN_vkGetSemaphoreFdKHR)gdpa(dev, "vkGetSemaphoreFdKHR");
+
+ // ---- VK_KHR_push_descriptor extension commands
+ table->CmdPushDescriptorSetKHR = (PFN_vkCmdPushDescriptorSetKHR)gdpa(dev, "vkCmdPushDescriptorSetKHR");
+ table->CmdPushDescriptorSetWithTemplateKHR = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)gdpa(dev, "vkCmdPushDescriptorSetWithTemplateKHR");
+
+ // ---- VK_KHR_descriptor_update_template extension commands
+ table->CreateDescriptorUpdateTemplateKHR = (PFN_vkCreateDescriptorUpdateTemplateKHR)gdpa(dev, "vkCreateDescriptorUpdateTemplateKHR");
+ table->DestroyDescriptorUpdateTemplateKHR = (PFN_vkDestroyDescriptorUpdateTemplateKHR)gdpa(dev, "vkDestroyDescriptorUpdateTemplateKHR");
+ table->UpdateDescriptorSetWithTemplateKHR = (PFN_vkUpdateDescriptorSetWithTemplateKHR)gdpa(dev, "vkUpdateDescriptorSetWithTemplateKHR");
+
+ // ---- VK_KHR_create_renderpass2 extension commands
+ table->CreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)gdpa(dev, "vkCreateRenderPass2KHR");
+ table->CmdBeginRenderPass2KHR = (PFN_vkCmdBeginRenderPass2KHR)gdpa(dev, "vkCmdBeginRenderPass2KHR");
+ table->CmdNextSubpass2KHR = (PFN_vkCmdNextSubpass2KHR)gdpa(dev, "vkCmdNextSubpass2KHR");
+ table->CmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR)gdpa(dev, "vkCmdEndRenderPass2KHR");
+
+ // ---- VK_KHR_shared_presentable_image extension commands
+ table->GetSwapchainStatusKHR = (PFN_vkGetSwapchainStatusKHR)gdpa(dev, "vkGetSwapchainStatusKHR");
+
+ // ---- VK_KHR_external_fence_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->ImportFenceWin32HandleKHR = (PFN_vkImportFenceWin32HandleKHR)gdpa(dev, "vkImportFenceWin32HandleKHR");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetFenceWin32HandleKHR = (PFN_vkGetFenceWin32HandleKHR)gdpa(dev, "vkGetFenceWin32HandleKHR");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_fence_fd extension commands
+ table->ImportFenceFdKHR = (PFN_vkImportFenceFdKHR)gdpa(dev, "vkImportFenceFdKHR");
+ table->GetFenceFdKHR = (PFN_vkGetFenceFdKHR)gdpa(dev, "vkGetFenceFdKHR");
+
+ // ---- VK_KHR_performance_query extension commands
+ table->AcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)gdpa(dev, "vkAcquireProfilingLockKHR");
+ table->ReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)gdpa(dev, "vkReleaseProfilingLockKHR");
+
+ // ---- VK_KHR_get_memory_requirements2 extension commands
+ table->GetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2KHR)gdpa(dev, "vkGetImageMemoryRequirements2KHR");
+ table->GetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2KHR)gdpa(dev, "vkGetBufferMemoryRequirements2KHR");
+ table->GetImageSparseMemoryRequirements2KHR = (PFN_vkGetImageSparseMemoryRequirements2KHR)gdpa(dev, "vkGetImageSparseMemoryRequirements2KHR");
+
+ // ---- VK_KHR_sampler_ycbcr_conversion extension commands
+ table->CreateSamplerYcbcrConversionKHR = (PFN_vkCreateSamplerYcbcrConversionKHR)gdpa(dev, "vkCreateSamplerYcbcrConversionKHR");
+ table->DestroySamplerYcbcrConversionKHR = (PFN_vkDestroySamplerYcbcrConversionKHR)gdpa(dev, "vkDestroySamplerYcbcrConversionKHR");
+
+ // ---- VK_KHR_bind_memory2 extension commands
+ table->BindBufferMemory2KHR = (PFN_vkBindBufferMemory2KHR)gdpa(dev, "vkBindBufferMemory2KHR");
+ table->BindImageMemory2KHR = (PFN_vkBindImageMemory2KHR)gdpa(dev, "vkBindImageMemory2KHR");
+
+ // ---- VK_KHR_maintenance3 extension commands
+ table->GetDescriptorSetLayoutSupportKHR = (PFN_vkGetDescriptorSetLayoutSupportKHR)gdpa(dev, "vkGetDescriptorSetLayoutSupportKHR");
+
+ // ---- VK_KHR_draw_indirect_count extension commands
+ table->CmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)gdpa(dev, "vkCmdDrawIndirectCountKHR");
+ table->CmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)gdpa(dev, "vkCmdDrawIndexedIndirectCountKHR");
+
+ // ---- VK_KHR_timeline_semaphore extension commands
+ table->GetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR)gdpa(dev, "vkGetSemaphoreCounterValueKHR");
+ table->WaitSemaphoresKHR = (PFN_vkWaitSemaphoresKHR)gdpa(dev, "vkWaitSemaphoresKHR");
+ table->SignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR)gdpa(dev, "vkSignalSemaphoreKHR");
+
+ // ---- VK_KHR_buffer_device_address extension commands
+ table->GetBufferDeviceAddressKHR = (PFN_vkGetBufferDeviceAddressKHR)gdpa(dev, "vkGetBufferDeviceAddressKHR");
+ table->GetBufferOpaqueCaptureAddressKHR = (PFN_vkGetBufferOpaqueCaptureAddressKHR)gdpa(dev, "vkGetBufferOpaqueCaptureAddressKHR");
+ table->GetDeviceMemoryOpaqueCaptureAddressKHR = (PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)gdpa(dev, "vkGetDeviceMemoryOpaqueCaptureAddressKHR");
+
+ // ---- VK_KHR_pipeline_executable_properties extension commands
+ table->GetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR)gdpa(dev, "vkGetPipelineExecutablePropertiesKHR");
+ table->GetPipelineExecutableStatisticsKHR = (PFN_vkGetPipelineExecutableStatisticsKHR)gdpa(dev, "vkGetPipelineExecutableStatisticsKHR");
+ table->GetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR)gdpa(dev, "vkGetPipelineExecutableInternalRepresentationsKHR");
+
+ // ---- VK_EXT_debug_marker extension commands
+ table->DebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT)gdpa(dev, "vkDebugMarkerSetObjectTagEXT");
+ table->DebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)gdpa(dev, "vkDebugMarkerSetObjectNameEXT");
+ table->CmdDebugMarkerBeginEXT = (PFN_vkCmdDebugMarkerBeginEXT)gdpa(dev, "vkCmdDebugMarkerBeginEXT");
+ table->CmdDebugMarkerEndEXT = (PFN_vkCmdDebugMarkerEndEXT)gdpa(dev, "vkCmdDebugMarkerEndEXT");
+ table->CmdDebugMarkerInsertEXT = (PFN_vkCmdDebugMarkerInsertEXT)gdpa(dev, "vkCmdDebugMarkerInsertEXT");
+
+ // ---- VK_EXT_transform_feedback extension commands
+ table->CmdBindTransformFeedbackBuffersEXT = (PFN_vkCmdBindTransformFeedbackBuffersEXT)gdpa(dev, "vkCmdBindTransformFeedbackBuffersEXT");
+ table->CmdBeginTransformFeedbackEXT = (PFN_vkCmdBeginTransformFeedbackEXT)gdpa(dev, "vkCmdBeginTransformFeedbackEXT");
+ table->CmdEndTransformFeedbackEXT = (PFN_vkCmdEndTransformFeedbackEXT)gdpa(dev, "vkCmdEndTransformFeedbackEXT");
+ table->CmdBeginQueryIndexedEXT = (PFN_vkCmdBeginQueryIndexedEXT)gdpa(dev, "vkCmdBeginQueryIndexedEXT");
+ table->CmdEndQueryIndexedEXT = (PFN_vkCmdEndQueryIndexedEXT)gdpa(dev, "vkCmdEndQueryIndexedEXT");
+ table->CmdDrawIndirectByteCountEXT = (PFN_vkCmdDrawIndirectByteCountEXT)gdpa(dev, "vkCmdDrawIndirectByteCountEXT");
+
+ // ---- VK_NVX_image_view_handle extension commands
+ table->GetImageViewHandleNVX = (PFN_vkGetImageViewHandleNVX)gdpa(dev, "vkGetImageViewHandleNVX");
+
+ // ---- VK_AMD_draw_indirect_count extension commands
+ table->CmdDrawIndirectCountAMD = (PFN_vkCmdDrawIndirectCountAMD)gdpa(dev, "vkCmdDrawIndirectCountAMD");
+ table->CmdDrawIndexedIndirectCountAMD = (PFN_vkCmdDrawIndexedIndirectCountAMD)gdpa(dev, "vkCmdDrawIndexedIndirectCountAMD");
+
+ // ---- VK_AMD_shader_info extension commands
+ table->GetShaderInfoAMD = (PFN_vkGetShaderInfoAMD)gdpa(dev, "vkGetShaderInfoAMD");
+
+ // ---- VK_NV_external_memory_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetMemoryWin32HandleNV = (PFN_vkGetMemoryWin32HandleNV)gdpa(dev, "vkGetMemoryWin32HandleNV");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_conditional_rendering extension commands
+ table->CmdBeginConditionalRenderingEXT = (PFN_vkCmdBeginConditionalRenderingEXT)gdpa(dev, "vkCmdBeginConditionalRenderingEXT");
+ table->CmdEndConditionalRenderingEXT = (PFN_vkCmdEndConditionalRenderingEXT)gdpa(dev, "vkCmdEndConditionalRenderingEXT");
+
+ // ---- VK_NVX_device_generated_commands extension commands
+ table->CmdProcessCommandsNVX = (PFN_vkCmdProcessCommandsNVX)gdpa(dev, "vkCmdProcessCommandsNVX");
+ table->CmdReserveSpaceForCommandsNVX = (PFN_vkCmdReserveSpaceForCommandsNVX)gdpa(dev, "vkCmdReserveSpaceForCommandsNVX");
+ table->CreateIndirectCommandsLayoutNVX = (PFN_vkCreateIndirectCommandsLayoutNVX)gdpa(dev, "vkCreateIndirectCommandsLayoutNVX");
+ table->DestroyIndirectCommandsLayoutNVX = (PFN_vkDestroyIndirectCommandsLayoutNVX)gdpa(dev, "vkDestroyIndirectCommandsLayoutNVX");
+ table->CreateObjectTableNVX = (PFN_vkCreateObjectTableNVX)gdpa(dev, "vkCreateObjectTableNVX");
+ table->DestroyObjectTableNVX = (PFN_vkDestroyObjectTableNVX)gdpa(dev, "vkDestroyObjectTableNVX");
+ table->RegisterObjectsNVX = (PFN_vkRegisterObjectsNVX)gdpa(dev, "vkRegisterObjectsNVX");
+ table->UnregisterObjectsNVX = (PFN_vkUnregisterObjectsNVX)gdpa(dev, "vkUnregisterObjectsNVX");
+
+ // ---- VK_NV_clip_space_w_scaling extension commands
+ table->CmdSetViewportWScalingNV = (PFN_vkCmdSetViewportWScalingNV)gdpa(dev, "vkCmdSetViewportWScalingNV");
+
+ // ---- VK_EXT_display_control extension commands
+ table->DisplayPowerControlEXT = (PFN_vkDisplayPowerControlEXT)gdpa(dev, "vkDisplayPowerControlEXT");
+ table->RegisterDeviceEventEXT = (PFN_vkRegisterDeviceEventEXT)gdpa(dev, "vkRegisterDeviceEventEXT");
+ table->RegisterDisplayEventEXT = (PFN_vkRegisterDisplayEventEXT)gdpa(dev, "vkRegisterDisplayEventEXT");
+ table->GetSwapchainCounterEXT = (PFN_vkGetSwapchainCounterEXT)gdpa(dev, "vkGetSwapchainCounterEXT");
+
+ // ---- VK_GOOGLE_display_timing extension commands
+ table->GetRefreshCycleDurationGOOGLE = (PFN_vkGetRefreshCycleDurationGOOGLE)gdpa(dev, "vkGetRefreshCycleDurationGOOGLE");
+ table->GetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE)gdpa(dev, "vkGetPastPresentationTimingGOOGLE");
+
+ // ---- VK_EXT_discard_rectangles extension commands
+ table->CmdSetDiscardRectangleEXT = (PFN_vkCmdSetDiscardRectangleEXT)gdpa(dev, "vkCmdSetDiscardRectangleEXT");
+
+ // ---- VK_EXT_hdr_metadata extension commands
+ table->SetHdrMetadataEXT = (PFN_vkSetHdrMetadataEXT)gdpa(dev, "vkSetHdrMetadataEXT");
+
+ // ---- VK_EXT_debug_utils extension commands
+ table->SetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)gipa(inst, "vkSetDebugUtilsObjectNameEXT");
+ table->SetDebugUtilsObjectTagEXT = (PFN_vkSetDebugUtilsObjectTagEXT)gipa(inst, "vkSetDebugUtilsObjectTagEXT");
+ table->QueueBeginDebugUtilsLabelEXT = (PFN_vkQueueBeginDebugUtilsLabelEXT)gipa(inst, "vkQueueBeginDebugUtilsLabelEXT");
+ table->QueueEndDebugUtilsLabelEXT = (PFN_vkQueueEndDebugUtilsLabelEXT)gipa(inst, "vkQueueEndDebugUtilsLabelEXT");
+ table->QueueInsertDebugUtilsLabelEXT = (PFN_vkQueueInsertDebugUtilsLabelEXT)gipa(inst, "vkQueueInsertDebugUtilsLabelEXT");
+ table->CmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)gipa(inst, "vkCmdBeginDebugUtilsLabelEXT");
+ table->CmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)gipa(inst, "vkCmdEndDebugUtilsLabelEXT");
+ table->CmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)gipa(inst, "vkCmdInsertDebugUtilsLabelEXT");
+
+ // ---- VK_ANDROID_external_memory_android_hardware_buffer extension commands
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ table->GetAndroidHardwareBufferPropertiesANDROID = (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)gdpa(dev, "vkGetAndroidHardwareBufferPropertiesANDROID");
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ table->GetMemoryAndroidHardwareBufferANDROID = (PFN_vkGetMemoryAndroidHardwareBufferANDROID)gdpa(dev, "vkGetMemoryAndroidHardwareBufferANDROID");
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+ // ---- VK_EXT_sample_locations extension commands
+ table->CmdSetSampleLocationsEXT = (PFN_vkCmdSetSampleLocationsEXT)gdpa(dev, "vkCmdSetSampleLocationsEXT");
+
+ // ---- VK_EXT_image_drm_format_modifier extension commands
+ table->GetImageDrmFormatModifierPropertiesEXT = (PFN_vkGetImageDrmFormatModifierPropertiesEXT)gdpa(dev, "vkGetImageDrmFormatModifierPropertiesEXT");
+
+ // ---- VK_EXT_validation_cache extension commands
+ table->CreateValidationCacheEXT = (PFN_vkCreateValidationCacheEXT)gdpa(dev, "vkCreateValidationCacheEXT");
+ table->DestroyValidationCacheEXT = (PFN_vkDestroyValidationCacheEXT)gdpa(dev, "vkDestroyValidationCacheEXT");
+ table->MergeValidationCachesEXT = (PFN_vkMergeValidationCachesEXT)gdpa(dev, "vkMergeValidationCachesEXT");
+ table->GetValidationCacheDataEXT = (PFN_vkGetValidationCacheDataEXT)gdpa(dev, "vkGetValidationCacheDataEXT");
+
+ // ---- VK_NV_shading_rate_image extension commands
+ table->CmdBindShadingRateImageNV = (PFN_vkCmdBindShadingRateImageNV)gdpa(dev, "vkCmdBindShadingRateImageNV");
+ table->CmdSetViewportShadingRatePaletteNV = (PFN_vkCmdSetViewportShadingRatePaletteNV)gdpa(dev, "vkCmdSetViewportShadingRatePaletteNV");
+ table->CmdSetCoarseSampleOrderNV = (PFN_vkCmdSetCoarseSampleOrderNV)gdpa(dev, "vkCmdSetCoarseSampleOrderNV");
+
+ // ---- VK_NV_ray_tracing extension commands
+ table->CreateAccelerationStructureNV = (PFN_vkCreateAccelerationStructureNV)gdpa(dev, "vkCreateAccelerationStructureNV");
+ table->DestroyAccelerationStructureNV = (PFN_vkDestroyAccelerationStructureNV)gdpa(dev, "vkDestroyAccelerationStructureNV");
+ table->GetAccelerationStructureMemoryRequirementsNV = (PFN_vkGetAccelerationStructureMemoryRequirementsNV)gdpa(dev, "vkGetAccelerationStructureMemoryRequirementsNV");
+ table->BindAccelerationStructureMemoryNV = (PFN_vkBindAccelerationStructureMemoryNV)gdpa(dev, "vkBindAccelerationStructureMemoryNV");
+ table->CmdBuildAccelerationStructureNV = (PFN_vkCmdBuildAccelerationStructureNV)gdpa(dev, "vkCmdBuildAccelerationStructureNV");
+ table->CmdCopyAccelerationStructureNV = (PFN_vkCmdCopyAccelerationStructureNV)gdpa(dev, "vkCmdCopyAccelerationStructureNV");
+ table->CmdTraceRaysNV = (PFN_vkCmdTraceRaysNV)gdpa(dev, "vkCmdTraceRaysNV");
+ table->CreateRayTracingPipelinesNV = (PFN_vkCreateRayTracingPipelinesNV)gdpa(dev, "vkCreateRayTracingPipelinesNV");
+ table->GetRayTracingShaderGroupHandlesNV = (PFN_vkGetRayTracingShaderGroupHandlesNV)gdpa(dev, "vkGetRayTracingShaderGroupHandlesNV");
+ table->GetAccelerationStructureHandleNV = (PFN_vkGetAccelerationStructureHandleNV)gdpa(dev, "vkGetAccelerationStructureHandleNV");
+ table->CmdWriteAccelerationStructuresPropertiesNV = (PFN_vkCmdWriteAccelerationStructuresPropertiesNV)gdpa(dev, "vkCmdWriteAccelerationStructuresPropertiesNV");
+ table->CompileDeferredNV = (PFN_vkCompileDeferredNV)gdpa(dev, "vkCompileDeferredNV");
+
+ // ---- VK_EXT_external_memory_host extension commands
+ table->GetMemoryHostPointerPropertiesEXT = (PFN_vkGetMemoryHostPointerPropertiesEXT)gdpa(dev, "vkGetMemoryHostPointerPropertiesEXT");
+
+ // ---- VK_AMD_buffer_marker extension commands
+ table->CmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)gdpa(dev, "vkCmdWriteBufferMarkerAMD");
+
+ // ---- VK_EXT_calibrated_timestamps extension commands
+ table->GetCalibratedTimestampsEXT = (PFN_vkGetCalibratedTimestampsEXT)gdpa(dev, "vkGetCalibratedTimestampsEXT");
+
+ // ---- VK_NV_mesh_shader extension commands
+ table->CmdDrawMeshTasksNV = (PFN_vkCmdDrawMeshTasksNV)gdpa(dev, "vkCmdDrawMeshTasksNV");
+ table->CmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)gdpa(dev, "vkCmdDrawMeshTasksIndirectNV");
+ table->CmdDrawMeshTasksIndirectCountNV = (PFN_vkCmdDrawMeshTasksIndirectCountNV)gdpa(dev, "vkCmdDrawMeshTasksIndirectCountNV");
+
+ // ---- VK_NV_scissor_exclusive extension commands
+ table->CmdSetExclusiveScissorNV = (PFN_vkCmdSetExclusiveScissorNV)gdpa(dev, "vkCmdSetExclusiveScissorNV");
+
+ // ---- VK_NV_device_diagnostic_checkpoints extension commands
+ table->CmdSetCheckpointNV = (PFN_vkCmdSetCheckpointNV)gdpa(dev, "vkCmdSetCheckpointNV");
+ table->GetQueueCheckpointDataNV = (PFN_vkGetQueueCheckpointDataNV)gdpa(dev, "vkGetQueueCheckpointDataNV");
+
+ // ---- VK_INTEL_performance_query extension commands
+ table->InitializePerformanceApiINTEL = (PFN_vkInitializePerformanceApiINTEL)gdpa(dev, "vkInitializePerformanceApiINTEL");
+ table->UninitializePerformanceApiINTEL = (PFN_vkUninitializePerformanceApiINTEL)gdpa(dev, "vkUninitializePerformanceApiINTEL");
+ table->CmdSetPerformanceMarkerINTEL = (PFN_vkCmdSetPerformanceMarkerINTEL)gdpa(dev, "vkCmdSetPerformanceMarkerINTEL");
+ table->CmdSetPerformanceStreamMarkerINTEL = (PFN_vkCmdSetPerformanceStreamMarkerINTEL)gdpa(dev, "vkCmdSetPerformanceStreamMarkerINTEL");
+ table->CmdSetPerformanceOverrideINTEL = (PFN_vkCmdSetPerformanceOverrideINTEL)gdpa(dev, "vkCmdSetPerformanceOverrideINTEL");
+ table->AcquirePerformanceConfigurationINTEL = (PFN_vkAcquirePerformanceConfigurationINTEL)gdpa(dev, "vkAcquirePerformanceConfigurationINTEL");
+ table->ReleasePerformanceConfigurationINTEL = (PFN_vkReleasePerformanceConfigurationINTEL)gdpa(dev, "vkReleasePerformanceConfigurationINTEL");
+ table->QueueSetPerformanceConfigurationINTEL = (PFN_vkQueueSetPerformanceConfigurationINTEL)gdpa(dev, "vkQueueSetPerformanceConfigurationINTEL");
+ table->GetPerformanceParameterINTEL = (PFN_vkGetPerformanceParameterINTEL)gdpa(dev, "vkGetPerformanceParameterINTEL");
+
+ // ---- VK_AMD_display_native_hdr extension commands
+ table->SetLocalDimmingAMD = (PFN_vkSetLocalDimmingAMD)gdpa(dev, "vkSetLocalDimmingAMD");
+
+ // ---- VK_EXT_buffer_device_address extension commands
+ table->GetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)gdpa(dev, "vkGetBufferDeviceAddressEXT");
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->AcquireFullScreenExclusiveModeEXT = (PFN_vkAcquireFullScreenExclusiveModeEXT)gdpa(dev, "vkAcquireFullScreenExclusiveModeEXT");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->ReleaseFullScreenExclusiveModeEXT = (PFN_vkReleaseFullScreenExclusiveModeEXT)gdpa(dev, "vkReleaseFullScreenExclusiveModeEXT");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)gdpa(dev, "vkGetDeviceGroupSurfacePresentModes2EXT");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_line_rasterization extension commands
+ table->CmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT)gdpa(dev, "vkCmdSetLineStippleEXT");
+
+ // ---- VK_EXT_host_query_reset extension commands
+ table->ResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT)gdpa(dev, "vkResetQueryPoolEXT");
+}
+
+// Init Instance function pointer dispatch table with core commands
+VKAPI_ATTR void VKAPI_CALL loader_init_instance_core_dispatch_table(VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa,
+ VkInstance inst) {
+
+ // ---- Core 1_0 commands
+ table->DestroyInstance = (PFN_vkDestroyInstance)gpa(inst, "vkDestroyInstance");
+ table->EnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)gpa(inst, "vkEnumeratePhysicalDevices");
+ table->GetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures)gpa(inst, "vkGetPhysicalDeviceFeatures");
+ table->GetPhysicalDeviceFormatProperties = (PFN_vkGetPhysicalDeviceFormatProperties)gpa(inst, "vkGetPhysicalDeviceFormatProperties");
+ table->GetPhysicalDeviceImageFormatProperties = (PFN_vkGetPhysicalDeviceImageFormatProperties)gpa(inst, "vkGetPhysicalDeviceImageFormatProperties");
+ table->GetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)gpa(inst, "vkGetPhysicalDeviceProperties");
+ table->GetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties)gpa(inst, "vkGetPhysicalDeviceQueueFamilyProperties");
+ table->GetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)gpa(inst, "vkGetPhysicalDeviceMemoryProperties");
+ table->GetInstanceProcAddr = gpa;
+ table->EnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties)gpa(inst, "vkEnumerateDeviceExtensionProperties");
+ table->EnumerateDeviceLayerProperties = (PFN_vkEnumerateDeviceLayerProperties)gpa(inst, "vkEnumerateDeviceLayerProperties");
+ table->GetPhysicalDeviceSparseImageFormatProperties = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties)gpa(inst, "vkGetPhysicalDeviceSparseImageFormatProperties");
+
+ // ---- Core 1_1 commands
+ table->EnumeratePhysicalDeviceGroups = (PFN_vkEnumeratePhysicalDeviceGroups)gpa(inst, "vkEnumeratePhysicalDeviceGroups");
+ table->GetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2)gpa(inst, "vkGetPhysicalDeviceFeatures2");
+ table->GetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2)gpa(inst, "vkGetPhysicalDeviceProperties2");
+ table->GetPhysicalDeviceFormatProperties2 = (PFN_vkGetPhysicalDeviceFormatProperties2)gpa(inst, "vkGetPhysicalDeviceFormatProperties2");
+ table->GetPhysicalDeviceImageFormatProperties2 = (PFN_vkGetPhysicalDeviceImageFormatProperties2)gpa(inst, "vkGetPhysicalDeviceImageFormatProperties2");
+ table->GetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2)gpa(inst, "vkGetPhysicalDeviceQueueFamilyProperties2");
+ table->GetPhysicalDeviceMemoryProperties2 = (PFN_vkGetPhysicalDeviceMemoryProperties2)gpa(inst, "vkGetPhysicalDeviceMemoryProperties2");
+ table->GetPhysicalDeviceSparseImageFormatProperties2 = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)gpa(inst, "vkGetPhysicalDeviceSparseImageFormatProperties2");
+ table->GetPhysicalDeviceExternalBufferProperties = (PFN_vkGetPhysicalDeviceExternalBufferProperties)gpa(inst, "vkGetPhysicalDeviceExternalBufferProperties");
+ table->GetPhysicalDeviceExternalFenceProperties = (PFN_vkGetPhysicalDeviceExternalFenceProperties)gpa(inst, "vkGetPhysicalDeviceExternalFenceProperties");
+ table->GetPhysicalDeviceExternalSemaphoreProperties = (PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)gpa(inst, "vkGetPhysicalDeviceExternalSemaphoreProperties");
+}
+
+// Init Instance function pointer dispatch table with core commands
+VKAPI_ATTR void VKAPI_CALL loader_init_instance_extension_dispatch_table(VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa,
+ VkInstance inst) {
+
+ // ---- VK_KHR_surface extension commands
+ table->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)gpa(inst, "vkDestroySurfaceKHR");
+ table->GetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)gpa(inst, "vkGetPhysicalDeviceSurfaceSupportKHR");
+ table->GetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)gpa(inst, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
+ table->GetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)gpa(inst, "vkGetPhysicalDeviceSurfaceFormatsKHR");
+ table->GetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)gpa(inst, "vkGetPhysicalDeviceSurfacePresentModesKHR");
+
+ // ---- VK_KHR_swapchain extension commands
+ table->GetPhysicalDevicePresentRectanglesKHR = (PFN_vkGetPhysicalDevicePresentRectanglesKHR)gpa(inst, "vkGetPhysicalDevicePresentRectanglesKHR");
+
+ // ---- VK_KHR_display extension commands
+ table->GetPhysicalDeviceDisplayPropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)gpa(inst, "vkGetPhysicalDeviceDisplayPropertiesKHR");
+ table->GetPhysicalDeviceDisplayPlanePropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)gpa(inst, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
+ table->GetDisplayPlaneSupportedDisplaysKHR = (PFN_vkGetDisplayPlaneSupportedDisplaysKHR)gpa(inst, "vkGetDisplayPlaneSupportedDisplaysKHR");
+ table->GetDisplayModePropertiesKHR = (PFN_vkGetDisplayModePropertiesKHR)gpa(inst, "vkGetDisplayModePropertiesKHR");
+ table->CreateDisplayModeKHR = (PFN_vkCreateDisplayModeKHR)gpa(inst, "vkCreateDisplayModeKHR");
+ table->GetDisplayPlaneCapabilitiesKHR = (PFN_vkGetDisplayPlaneCapabilitiesKHR)gpa(inst, "vkGetDisplayPlaneCapabilitiesKHR");
+ table->CreateDisplayPlaneSurfaceKHR = (PFN_vkCreateDisplayPlaneSurfaceKHR)gpa(inst, "vkCreateDisplayPlaneSurfaceKHR");
+
+ // ---- VK_KHR_xlib_surface extension commands
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ table->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)gpa(inst, "vkCreateXlibSurfaceKHR");
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ table->GetPhysicalDeviceXlibPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)gpa(inst, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
+#endif // VK_USE_PLATFORM_XLIB_KHR
+
+ // ---- VK_KHR_xcb_surface extension commands
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ table->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)gpa(inst, "vkCreateXcbSurfaceKHR");
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ table->GetPhysicalDeviceXcbPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)gpa(inst, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
+#endif // VK_USE_PLATFORM_XCB_KHR
+
+ // ---- VK_KHR_wayland_surface extension commands
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ table->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)gpa(inst, "vkCreateWaylandSurfaceKHR");
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ table->GetPhysicalDeviceWaylandPresentationSupportKHR = (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)gpa(inst, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+
+ // ---- VK_KHR_android_surface extension commands
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ table->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)gpa(inst, "vkCreateAndroidSurfaceKHR");
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+ // ---- VK_KHR_win32_surface extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)gpa(inst, "vkCreateWin32SurfaceKHR");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetPhysicalDeviceWin32PresentationSupportKHR = (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)gpa(inst, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_get_physical_device_properties2 extension commands
+ table->GetPhysicalDeviceFeatures2KHR = (PFN_vkGetPhysicalDeviceFeatures2KHR)gpa(inst, "vkGetPhysicalDeviceFeatures2KHR");
+ table->GetPhysicalDeviceProperties2KHR = (PFN_vkGetPhysicalDeviceProperties2KHR)gpa(inst, "vkGetPhysicalDeviceProperties2KHR");
+ table->GetPhysicalDeviceFormatProperties2KHR = (PFN_vkGetPhysicalDeviceFormatProperties2KHR)gpa(inst, "vkGetPhysicalDeviceFormatProperties2KHR");
+ table->GetPhysicalDeviceImageFormatProperties2KHR = (PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)gpa(inst, "vkGetPhysicalDeviceImageFormatProperties2KHR");
+ table->GetPhysicalDeviceQueueFamilyProperties2KHR = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)gpa(inst, "vkGetPhysicalDeviceQueueFamilyProperties2KHR");
+ table->GetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2KHR)gpa(inst, "vkGetPhysicalDeviceMemoryProperties2KHR");
+ table->GetPhysicalDeviceSparseImageFormatProperties2KHR = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)gpa(inst, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
+
+ // ---- VK_KHR_device_group_creation extension commands
+ table->EnumeratePhysicalDeviceGroupsKHR = (PFN_vkEnumeratePhysicalDeviceGroupsKHR)gpa(inst, "vkEnumeratePhysicalDeviceGroupsKHR");
+
+ // ---- VK_KHR_external_memory_capabilities extension commands
+ table->GetPhysicalDeviceExternalBufferPropertiesKHR = (PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)gpa(inst, "vkGetPhysicalDeviceExternalBufferPropertiesKHR");
+
+ // ---- VK_KHR_external_semaphore_capabilities extension commands
+ table->GetPhysicalDeviceExternalSemaphorePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)gpa(inst, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR");
+
+ // ---- VK_KHR_external_fence_capabilities extension commands
+ table->GetPhysicalDeviceExternalFencePropertiesKHR = (PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)gpa(inst, "vkGetPhysicalDeviceExternalFencePropertiesKHR");
+
+ // ---- VK_KHR_performance_query extension commands
+ table->EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = (PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR)gpa(inst, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR");
+ table->GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = (PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR)gpa(inst, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR");
+
+ // ---- VK_KHR_get_surface_capabilities2 extension commands
+ table->GetPhysicalDeviceSurfaceCapabilities2KHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)gpa(inst, "vkGetPhysicalDeviceSurfaceCapabilities2KHR");
+ table->GetPhysicalDeviceSurfaceFormats2KHR = (PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)gpa(inst, "vkGetPhysicalDeviceSurfaceFormats2KHR");
+
+ // ---- VK_KHR_get_display_properties2 extension commands
+ table->GetPhysicalDeviceDisplayProperties2KHR = (PFN_vkGetPhysicalDeviceDisplayProperties2KHR)gpa(inst, "vkGetPhysicalDeviceDisplayProperties2KHR");
+ table->GetPhysicalDeviceDisplayPlaneProperties2KHR = (PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)gpa(inst, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR");
+ table->GetDisplayModeProperties2KHR = (PFN_vkGetDisplayModeProperties2KHR)gpa(inst, "vkGetDisplayModeProperties2KHR");
+ table->GetDisplayPlaneCapabilities2KHR = (PFN_vkGetDisplayPlaneCapabilities2KHR)gpa(inst, "vkGetDisplayPlaneCapabilities2KHR");
+
+ // ---- VK_EXT_debug_report extension commands
+ table->CreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)gpa(inst, "vkCreateDebugReportCallbackEXT");
+ table->DestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)gpa(inst, "vkDestroyDebugReportCallbackEXT");
+ table->DebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)gpa(inst, "vkDebugReportMessageEXT");
+
+ // ---- VK_GGP_stream_descriptor_surface extension commands
+#ifdef VK_USE_PLATFORM_GGP
+ table->CreateStreamDescriptorSurfaceGGP = (PFN_vkCreateStreamDescriptorSurfaceGGP)gpa(inst, "vkCreateStreamDescriptorSurfaceGGP");
+#endif // VK_USE_PLATFORM_GGP
+
+ // ---- VK_NV_external_memory_capabilities extension commands
+ table->GetPhysicalDeviceExternalImageFormatPropertiesNV = (PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)gpa(inst, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV");
+
+ // ---- VK_NN_vi_surface extension commands
+#ifdef VK_USE_PLATFORM_VI_NN
+ table->CreateViSurfaceNN = (PFN_vkCreateViSurfaceNN)gpa(inst, "vkCreateViSurfaceNN");
+#endif // VK_USE_PLATFORM_VI_NN
+
+ // ---- VK_NVX_device_generated_commands extension commands
+ table->GetPhysicalDeviceGeneratedCommandsPropertiesNVX = (PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)gpa(inst, "vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX");
+
+ // ---- VK_EXT_direct_mode_display extension commands
+ table->ReleaseDisplayEXT = (PFN_vkReleaseDisplayEXT)gpa(inst, "vkReleaseDisplayEXT");
+
+ // ---- VK_EXT_acquire_xlib_display extension commands
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ table->AcquireXlibDisplayEXT = (PFN_vkAcquireXlibDisplayEXT)gpa(inst, "vkAcquireXlibDisplayEXT");
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ table->GetRandROutputDisplayEXT = (PFN_vkGetRandROutputDisplayEXT)gpa(inst, "vkGetRandROutputDisplayEXT");
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
+ // ---- VK_EXT_display_surface_counter extension commands
+ table->GetPhysicalDeviceSurfaceCapabilities2EXT = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)gpa(inst, "vkGetPhysicalDeviceSurfaceCapabilities2EXT");
+
+ // ---- VK_MVK_ios_surface extension commands
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ table->CreateIOSSurfaceMVK = (PFN_vkCreateIOSSurfaceMVK)gpa(inst, "vkCreateIOSSurfaceMVK");
+#endif // VK_USE_PLATFORM_IOS_MVK
+
+ // ---- VK_MVK_macos_surface extension commands
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ table->CreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)gpa(inst, "vkCreateMacOSSurfaceMVK");
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
+ // ---- VK_EXT_debug_utils extension commands
+ table->CreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)gpa(inst, "vkCreateDebugUtilsMessengerEXT");
+ table->DestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)gpa(inst, "vkDestroyDebugUtilsMessengerEXT");
+ table->SubmitDebugUtilsMessageEXT = (PFN_vkSubmitDebugUtilsMessageEXT)gpa(inst, "vkSubmitDebugUtilsMessageEXT");
+
+ // ---- VK_EXT_sample_locations extension commands
+ table->GetPhysicalDeviceMultisamplePropertiesEXT = (PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)gpa(inst, "vkGetPhysicalDeviceMultisamplePropertiesEXT");
+
+ // ---- VK_EXT_calibrated_timestamps extension commands
+ table->GetPhysicalDeviceCalibrateableTimeDomainsEXT = (PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)gpa(inst, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT");
+
+ // ---- VK_FUCHSIA_imagepipe_surface extension commands
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ table->CreateImagePipeSurfaceFUCHSIA = (PFN_vkCreateImagePipeSurfaceFUCHSIA)gpa(inst, "vkCreateImagePipeSurfaceFUCHSIA");
+#endif // VK_USE_PLATFORM_FUCHSIA
+
+ // ---- VK_EXT_metal_surface extension commands
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ table->CreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT)gpa(inst, "vkCreateMetalSurfaceEXT");
+#endif // VK_USE_PLATFORM_METAL_EXT
+
+ // ---- VK_EXT_tooling_info extension commands
+ table->GetPhysicalDeviceToolPropertiesEXT = (PFN_vkGetPhysicalDeviceToolPropertiesEXT)gpa(inst, "vkGetPhysicalDeviceToolPropertiesEXT");
+
+ // ---- VK_NV_cooperative_matrix extension commands
+ table->GetPhysicalDeviceCooperativeMatrixPropertiesNV = (PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)gpa(inst, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV");
+
+ // ---- VK_NV_coverage_reduction_mode extension commands
+ table->GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = (PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)gpa(inst, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV");
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ table->GetPhysicalDeviceSurfacePresentModes2EXT = (PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT)gpa(inst, "vkGetPhysicalDeviceSurfacePresentModes2EXT");
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_headless_surface extension commands
+ table->CreateHeadlessSurfaceEXT = (PFN_vkCreateHeadlessSurfaceEXT)gpa(inst, "vkCreateHeadlessSurfaceEXT");
+}
+
+// Device command lookup function
+VKAPI_ATTR void* VKAPI_CALL loader_lookup_device_dispatch_table(const VkLayerDispatchTable *table, const char *name) {
+ if (!name || name[0] != 'v' || name[1] != 'k') return NULL;
+
+ name += 2;
+
+ // ---- Core 1_0 commands
+ if (!strcmp(name, "GetDeviceProcAddr")) return (void *)table->GetDeviceProcAddr;
+ if (!strcmp(name, "DestroyDevice")) return (void *)table->DestroyDevice;
+ if (!strcmp(name, "GetDeviceQueue")) return (void *)table->GetDeviceQueue;
+ if (!strcmp(name, "QueueSubmit")) return (void *)table->QueueSubmit;
+ if (!strcmp(name, "QueueWaitIdle")) return (void *)table->QueueWaitIdle;
+ if (!strcmp(name, "DeviceWaitIdle")) return (void *)table->DeviceWaitIdle;
+ if (!strcmp(name, "AllocateMemory")) return (void *)table->AllocateMemory;
+ if (!strcmp(name, "FreeMemory")) return (void *)table->FreeMemory;
+ if (!strcmp(name, "MapMemory")) return (void *)table->MapMemory;
+ if (!strcmp(name, "UnmapMemory")) return (void *)table->UnmapMemory;
+ if (!strcmp(name, "FlushMappedMemoryRanges")) return (void *)table->FlushMappedMemoryRanges;
+ if (!strcmp(name, "InvalidateMappedMemoryRanges")) return (void *)table->InvalidateMappedMemoryRanges;
+ if (!strcmp(name, "GetDeviceMemoryCommitment")) return (void *)table->GetDeviceMemoryCommitment;
+ if (!strcmp(name, "BindBufferMemory")) return (void *)table->BindBufferMemory;
+ if (!strcmp(name, "BindImageMemory")) return (void *)table->BindImageMemory;
+ if (!strcmp(name, "GetBufferMemoryRequirements")) return (void *)table->GetBufferMemoryRequirements;
+ if (!strcmp(name, "GetImageMemoryRequirements")) return (void *)table->GetImageMemoryRequirements;
+ if (!strcmp(name, "GetImageSparseMemoryRequirements")) return (void *)table->GetImageSparseMemoryRequirements;
+ if (!strcmp(name, "QueueBindSparse")) return (void *)table->QueueBindSparse;
+ if (!strcmp(name, "CreateFence")) return (void *)table->CreateFence;
+ if (!strcmp(name, "DestroyFence")) return (void *)table->DestroyFence;
+ if (!strcmp(name, "ResetFences")) return (void *)table->ResetFences;
+ if (!strcmp(name, "GetFenceStatus")) return (void *)table->GetFenceStatus;
+ if (!strcmp(name, "WaitForFences")) return (void *)table->WaitForFences;
+ if (!strcmp(name, "CreateSemaphore")) return (void *)table->CreateSemaphore;
+ if (!strcmp(name, "DestroySemaphore")) return (void *)table->DestroySemaphore;
+ if (!strcmp(name, "CreateEvent")) return (void *)table->CreateEvent;
+ if (!strcmp(name, "DestroyEvent")) return (void *)table->DestroyEvent;
+ if (!strcmp(name, "GetEventStatus")) return (void *)table->GetEventStatus;
+ if (!strcmp(name, "SetEvent")) return (void *)table->SetEvent;
+ if (!strcmp(name, "ResetEvent")) return (void *)table->ResetEvent;
+ if (!strcmp(name, "CreateQueryPool")) return (void *)table->CreateQueryPool;
+ if (!strcmp(name, "DestroyQueryPool")) return (void *)table->DestroyQueryPool;
+ if (!strcmp(name, "GetQueryPoolResults")) return (void *)table->GetQueryPoolResults;
+ if (!strcmp(name, "CreateBuffer")) return (void *)table->CreateBuffer;
+ if (!strcmp(name, "DestroyBuffer")) return (void *)table->DestroyBuffer;
+ if (!strcmp(name, "CreateBufferView")) return (void *)table->CreateBufferView;
+ if (!strcmp(name, "DestroyBufferView")) return (void *)table->DestroyBufferView;
+ if (!strcmp(name, "CreateImage")) return (void *)table->CreateImage;
+ if (!strcmp(name, "DestroyImage")) return (void *)table->DestroyImage;
+ if (!strcmp(name, "GetImageSubresourceLayout")) return (void *)table->GetImageSubresourceLayout;
+ if (!strcmp(name, "CreateImageView")) return (void *)table->CreateImageView;
+ if (!strcmp(name, "DestroyImageView")) return (void *)table->DestroyImageView;
+ if (!strcmp(name, "CreateShaderModule")) return (void *)table->CreateShaderModule;
+ if (!strcmp(name, "DestroyShaderModule")) return (void *)table->DestroyShaderModule;
+ if (!strcmp(name, "CreatePipelineCache")) return (void *)table->CreatePipelineCache;
+ if (!strcmp(name, "DestroyPipelineCache")) return (void *)table->DestroyPipelineCache;
+ if (!strcmp(name, "GetPipelineCacheData")) return (void *)table->GetPipelineCacheData;
+ if (!strcmp(name, "MergePipelineCaches")) return (void *)table->MergePipelineCaches;
+ if (!strcmp(name, "CreateGraphicsPipelines")) return (void *)table->CreateGraphicsPipelines;
+ if (!strcmp(name, "CreateComputePipelines")) return (void *)table->CreateComputePipelines;
+ if (!strcmp(name, "DestroyPipeline")) return (void *)table->DestroyPipeline;
+ if (!strcmp(name, "CreatePipelineLayout")) return (void *)table->CreatePipelineLayout;
+ if (!strcmp(name, "DestroyPipelineLayout")) return (void *)table->DestroyPipelineLayout;
+ if (!strcmp(name, "CreateSampler")) return (void *)table->CreateSampler;
+ if (!strcmp(name, "DestroySampler")) return (void *)table->DestroySampler;
+ if (!strcmp(name, "CreateDescriptorSetLayout")) return (void *)table->CreateDescriptorSetLayout;
+ if (!strcmp(name, "DestroyDescriptorSetLayout")) return (void *)table->DestroyDescriptorSetLayout;
+ if (!strcmp(name, "CreateDescriptorPool")) return (void *)table->CreateDescriptorPool;
+ if (!strcmp(name, "DestroyDescriptorPool")) return (void *)table->DestroyDescriptorPool;
+ if (!strcmp(name, "ResetDescriptorPool")) return (void *)table->ResetDescriptorPool;
+ if (!strcmp(name, "AllocateDescriptorSets")) return (void *)table->AllocateDescriptorSets;
+ if (!strcmp(name, "FreeDescriptorSets")) return (void *)table->FreeDescriptorSets;
+ if (!strcmp(name, "UpdateDescriptorSets")) return (void *)table->UpdateDescriptorSets;
+ if (!strcmp(name, "CreateFramebuffer")) return (void *)table->CreateFramebuffer;
+ if (!strcmp(name, "DestroyFramebuffer")) return (void *)table->DestroyFramebuffer;
+ if (!strcmp(name, "CreateRenderPass")) return (void *)table->CreateRenderPass;
+ if (!strcmp(name, "DestroyRenderPass")) return (void *)table->DestroyRenderPass;
+ if (!strcmp(name, "GetRenderAreaGranularity")) return (void *)table->GetRenderAreaGranularity;
+ if (!strcmp(name, "CreateCommandPool")) return (void *)table->CreateCommandPool;
+ if (!strcmp(name, "DestroyCommandPool")) return (void *)table->DestroyCommandPool;
+ if (!strcmp(name, "ResetCommandPool")) return (void *)table->ResetCommandPool;
+ if (!strcmp(name, "AllocateCommandBuffers")) return (void *)table->AllocateCommandBuffers;
+ if (!strcmp(name, "FreeCommandBuffers")) return (void *)table->FreeCommandBuffers;
+ if (!strcmp(name, "BeginCommandBuffer")) return (void *)table->BeginCommandBuffer;
+ if (!strcmp(name, "EndCommandBuffer")) return (void *)table->EndCommandBuffer;
+ if (!strcmp(name, "ResetCommandBuffer")) return (void *)table->ResetCommandBuffer;
+ if (!strcmp(name, "CmdBindPipeline")) return (void *)table->CmdBindPipeline;
+ if (!strcmp(name, "CmdSetViewport")) return (void *)table->CmdSetViewport;
+ if (!strcmp(name, "CmdSetScissor")) return (void *)table->CmdSetScissor;
+ if (!strcmp(name, "CmdSetLineWidth")) return (void *)table->CmdSetLineWidth;
+ if (!strcmp(name, "CmdSetDepthBias")) return (void *)table->CmdSetDepthBias;
+ if (!strcmp(name, "CmdSetBlendConstants")) return (void *)table->CmdSetBlendConstants;
+ if (!strcmp(name, "CmdSetDepthBounds")) return (void *)table->CmdSetDepthBounds;
+ if (!strcmp(name, "CmdSetStencilCompareMask")) return (void *)table->CmdSetStencilCompareMask;
+ if (!strcmp(name, "CmdSetStencilWriteMask")) return (void *)table->CmdSetStencilWriteMask;
+ if (!strcmp(name, "CmdSetStencilReference")) return (void *)table->CmdSetStencilReference;
+ if (!strcmp(name, "CmdBindDescriptorSets")) return (void *)table->CmdBindDescriptorSets;
+ if (!strcmp(name, "CmdBindIndexBuffer")) return (void *)table->CmdBindIndexBuffer;
+ if (!strcmp(name, "CmdBindVertexBuffers")) return (void *)table->CmdBindVertexBuffers;
+ if (!strcmp(name, "CmdDraw")) return (void *)table->CmdDraw;
+ if (!strcmp(name, "CmdDrawIndexed")) return (void *)table->CmdDrawIndexed;
+ if (!strcmp(name, "CmdDrawIndirect")) return (void *)table->CmdDrawIndirect;
+ if (!strcmp(name, "CmdDrawIndexedIndirect")) return (void *)table->CmdDrawIndexedIndirect;
+ if (!strcmp(name, "CmdDispatch")) return (void *)table->CmdDispatch;
+ if (!strcmp(name, "CmdDispatchIndirect")) return (void *)table->CmdDispatchIndirect;
+ if (!strcmp(name, "CmdCopyBuffer")) return (void *)table->CmdCopyBuffer;
+ if (!strcmp(name, "CmdCopyImage")) return (void *)table->CmdCopyImage;
+ if (!strcmp(name, "CmdBlitImage")) return (void *)table->CmdBlitImage;
+ if (!strcmp(name, "CmdCopyBufferToImage")) return (void *)table->CmdCopyBufferToImage;
+ if (!strcmp(name, "CmdCopyImageToBuffer")) return (void *)table->CmdCopyImageToBuffer;
+ if (!strcmp(name, "CmdUpdateBuffer")) return (void *)table->CmdUpdateBuffer;
+ if (!strcmp(name, "CmdFillBuffer")) return (void *)table->CmdFillBuffer;
+ if (!strcmp(name, "CmdClearColorImage")) return (void *)table->CmdClearColorImage;
+ if (!strcmp(name, "CmdClearDepthStencilImage")) return (void *)table->CmdClearDepthStencilImage;
+ if (!strcmp(name, "CmdClearAttachments")) return (void *)table->CmdClearAttachments;
+ if (!strcmp(name, "CmdResolveImage")) return (void *)table->CmdResolveImage;
+ if (!strcmp(name, "CmdSetEvent")) return (void *)table->CmdSetEvent;
+ if (!strcmp(name, "CmdResetEvent")) return (void *)table->CmdResetEvent;
+ if (!strcmp(name, "CmdWaitEvents")) return (void *)table->CmdWaitEvents;
+ if (!strcmp(name, "CmdPipelineBarrier")) return (void *)table->CmdPipelineBarrier;
+ if (!strcmp(name, "CmdBeginQuery")) return (void *)table->CmdBeginQuery;
+ if (!strcmp(name, "CmdEndQuery")) return (void *)table->CmdEndQuery;
+ if (!strcmp(name, "CmdResetQueryPool")) return (void *)table->CmdResetQueryPool;
+ if (!strcmp(name, "CmdWriteTimestamp")) return (void *)table->CmdWriteTimestamp;
+ if (!strcmp(name, "CmdCopyQueryPoolResults")) return (void *)table->CmdCopyQueryPoolResults;
+ if (!strcmp(name, "CmdPushConstants")) return (void *)table->CmdPushConstants;
+ if (!strcmp(name, "CmdBeginRenderPass")) return (void *)table->CmdBeginRenderPass;
+ if (!strcmp(name, "CmdNextSubpass")) return (void *)table->CmdNextSubpass;
+ if (!strcmp(name, "CmdEndRenderPass")) return (void *)table->CmdEndRenderPass;
+ if (!strcmp(name, "CmdExecuteCommands")) return (void *)table->CmdExecuteCommands;
+
+ // ---- Core 1_1 commands
+ if (!strcmp(name, "BindBufferMemory2")) return (void *)table->BindBufferMemory2;
+ if (!strcmp(name, "BindImageMemory2")) return (void *)table->BindImageMemory2;
+ if (!strcmp(name, "GetDeviceGroupPeerMemoryFeatures")) return (void *)table->GetDeviceGroupPeerMemoryFeatures;
+ if (!strcmp(name, "CmdSetDeviceMask")) return (void *)table->CmdSetDeviceMask;
+ if (!strcmp(name, "CmdDispatchBase")) return (void *)table->CmdDispatchBase;
+ if (!strcmp(name, "GetImageMemoryRequirements2")) return (void *)table->GetImageMemoryRequirements2;
+ if (!strcmp(name, "GetBufferMemoryRequirements2")) return (void *)table->GetBufferMemoryRequirements2;
+ if (!strcmp(name, "GetImageSparseMemoryRequirements2")) return (void *)table->GetImageSparseMemoryRequirements2;
+ if (!strcmp(name, "TrimCommandPool")) return (void *)table->TrimCommandPool;
+ if (!strcmp(name, "GetDeviceQueue2")) return (void *)table->GetDeviceQueue2;
+ if (!strcmp(name, "CreateSamplerYcbcrConversion")) return (void *)table->CreateSamplerYcbcrConversion;
+ if (!strcmp(name, "DestroySamplerYcbcrConversion")) return (void *)table->DestroySamplerYcbcrConversion;
+ if (!strcmp(name, "CreateDescriptorUpdateTemplate")) return (void *)table->CreateDescriptorUpdateTemplate;
+ if (!strcmp(name, "DestroyDescriptorUpdateTemplate")) return (void *)table->DestroyDescriptorUpdateTemplate;
+ if (!strcmp(name, "UpdateDescriptorSetWithTemplate")) return (void *)table->UpdateDescriptorSetWithTemplate;
+ if (!strcmp(name, "GetDescriptorSetLayoutSupport")) return (void *)table->GetDescriptorSetLayoutSupport;
+
+ // ---- Core 1_2 commands
+ if (!strcmp(name, "CmdDrawIndirectCount")) return (void *)table->CmdDrawIndirectCount;
+ if (!strcmp(name, "CmdDrawIndexedIndirectCount")) return (void *)table->CmdDrawIndexedIndirectCount;
+ if (!strcmp(name, "CreateRenderPass2")) return (void *)table->CreateRenderPass2;
+ if (!strcmp(name, "CmdBeginRenderPass2")) return (void *)table->CmdBeginRenderPass2;
+ if (!strcmp(name, "CmdNextSubpass2")) return (void *)table->CmdNextSubpass2;
+ if (!strcmp(name, "CmdEndRenderPass2")) return (void *)table->CmdEndRenderPass2;
+ if (!strcmp(name, "ResetQueryPool")) return (void *)table->ResetQueryPool;
+ if (!strcmp(name, "GetSemaphoreCounterValue")) return (void *)table->GetSemaphoreCounterValue;
+ if (!strcmp(name, "WaitSemaphores")) return (void *)table->WaitSemaphores;
+ if (!strcmp(name, "SignalSemaphore")) return (void *)table->SignalSemaphore;
+ if (!strcmp(name, "GetBufferDeviceAddress")) return (void *)table->GetBufferDeviceAddress;
+ if (!strcmp(name, "GetBufferOpaqueCaptureAddress")) return (void *)table->GetBufferOpaqueCaptureAddress;
+ if (!strcmp(name, "GetDeviceMemoryOpaqueCaptureAddress")) return (void *)table->GetDeviceMemoryOpaqueCaptureAddress;
+
+ // ---- VK_KHR_swapchain extension commands
+ if (!strcmp(name, "CreateSwapchainKHR")) return (void *)table->CreateSwapchainKHR;
+ if (!strcmp(name, "DestroySwapchainKHR")) return (void *)table->DestroySwapchainKHR;
+ if (!strcmp(name, "GetSwapchainImagesKHR")) return (void *)table->GetSwapchainImagesKHR;
+ if (!strcmp(name, "AcquireNextImageKHR")) return (void *)table->AcquireNextImageKHR;
+ if (!strcmp(name, "QueuePresentKHR")) return (void *)table->QueuePresentKHR;
+ if (!strcmp(name, "GetDeviceGroupPresentCapabilitiesKHR")) return (void *)table->GetDeviceGroupPresentCapabilitiesKHR;
+ if (!strcmp(name, "GetDeviceGroupSurfacePresentModesKHR")) return (void *)table->GetDeviceGroupSurfacePresentModesKHR;
+ if (!strcmp(name, "AcquireNextImage2KHR")) return (void *)table->AcquireNextImage2KHR;
+
+ // ---- VK_KHR_display_swapchain extension commands
+ if (!strcmp(name, "CreateSharedSwapchainsKHR")) return (void *)table->CreateSharedSwapchainsKHR;
+
+ // ---- VK_KHR_device_group extension commands
+ if (!strcmp(name, "GetDeviceGroupPeerMemoryFeaturesKHR")) return (void *)table->GetDeviceGroupPeerMemoryFeaturesKHR;
+ if (!strcmp(name, "CmdSetDeviceMaskKHR")) return (void *)table->CmdSetDeviceMaskKHR;
+ if (!strcmp(name, "CmdDispatchBaseKHR")) return (void *)table->CmdDispatchBaseKHR;
+
+ // ---- VK_KHR_maintenance1 extension commands
+ if (!strcmp(name, "TrimCommandPoolKHR")) return (void *)table->TrimCommandPoolKHR;
+
+ // ---- VK_KHR_external_memory_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "GetMemoryWin32HandleKHR")) return (void *)table->GetMemoryWin32HandleKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "GetMemoryWin32HandlePropertiesKHR")) return (void *)table->GetMemoryWin32HandlePropertiesKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_memory_fd extension commands
+ if (!strcmp(name, "GetMemoryFdKHR")) return (void *)table->GetMemoryFdKHR;
+ if (!strcmp(name, "GetMemoryFdPropertiesKHR")) return (void *)table->GetMemoryFdPropertiesKHR;
+
+ // ---- VK_KHR_external_semaphore_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "ImportSemaphoreWin32HandleKHR")) return (void *)table->ImportSemaphoreWin32HandleKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "GetSemaphoreWin32HandleKHR")) return (void *)table->GetSemaphoreWin32HandleKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_semaphore_fd extension commands
+ if (!strcmp(name, "ImportSemaphoreFdKHR")) return (void *)table->ImportSemaphoreFdKHR;
+ if (!strcmp(name, "GetSemaphoreFdKHR")) return (void *)table->GetSemaphoreFdKHR;
+
+ // ---- VK_KHR_push_descriptor extension commands
+ if (!strcmp(name, "CmdPushDescriptorSetKHR")) return (void *)table->CmdPushDescriptorSetKHR;
+ if (!strcmp(name, "CmdPushDescriptorSetWithTemplateKHR")) return (void *)table->CmdPushDescriptorSetWithTemplateKHR;
+
+ // ---- VK_KHR_descriptor_update_template extension commands
+ if (!strcmp(name, "CreateDescriptorUpdateTemplateKHR")) return (void *)table->CreateDescriptorUpdateTemplateKHR;
+ if (!strcmp(name, "DestroyDescriptorUpdateTemplateKHR")) return (void *)table->DestroyDescriptorUpdateTemplateKHR;
+ if (!strcmp(name, "UpdateDescriptorSetWithTemplateKHR")) return (void *)table->UpdateDescriptorSetWithTemplateKHR;
+
+ // ---- VK_KHR_create_renderpass2 extension commands
+ if (!strcmp(name, "CreateRenderPass2KHR")) return (void *)table->CreateRenderPass2KHR;
+ if (!strcmp(name, "CmdBeginRenderPass2KHR")) return (void *)table->CmdBeginRenderPass2KHR;
+ if (!strcmp(name, "CmdNextSubpass2KHR")) return (void *)table->CmdNextSubpass2KHR;
+ if (!strcmp(name, "CmdEndRenderPass2KHR")) return (void *)table->CmdEndRenderPass2KHR;
+
+ // ---- VK_KHR_shared_presentable_image extension commands
+ if (!strcmp(name, "GetSwapchainStatusKHR")) return (void *)table->GetSwapchainStatusKHR;
+
+ // ---- VK_KHR_external_fence_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "ImportFenceWin32HandleKHR")) return (void *)table->ImportFenceWin32HandleKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "GetFenceWin32HandleKHR")) return (void *)table->GetFenceWin32HandleKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_fence_fd extension commands
+ if (!strcmp(name, "ImportFenceFdKHR")) return (void *)table->ImportFenceFdKHR;
+ if (!strcmp(name, "GetFenceFdKHR")) return (void *)table->GetFenceFdKHR;
+
+ // ---- VK_KHR_performance_query extension commands
+ if (!strcmp(name, "AcquireProfilingLockKHR")) return (void *)table->AcquireProfilingLockKHR;
+ if (!strcmp(name, "ReleaseProfilingLockKHR")) return (void *)table->ReleaseProfilingLockKHR;
+
+ // ---- VK_KHR_get_memory_requirements2 extension commands
+ if (!strcmp(name, "GetImageMemoryRequirements2KHR")) return (void *)table->GetImageMemoryRequirements2KHR;
+ if (!strcmp(name, "GetBufferMemoryRequirements2KHR")) return (void *)table->GetBufferMemoryRequirements2KHR;
+ if (!strcmp(name, "GetImageSparseMemoryRequirements2KHR")) return (void *)table->GetImageSparseMemoryRequirements2KHR;
+
+ // ---- VK_KHR_sampler_ycbcr_conversion extension commands
+ if (!strcmp(name, "CreateSamplerYcbcrConversionKHR")) return (void *)table->CreateSamplerYcbcrConversionKHR;
+ if (!strcmp(name, "DestroySamplerYcbcrConversionKHR")) return (void *)table->DestroySamplerYcbcrConversionKHR;
+
+ // ---- VK_KHR_bind_memory2 extension commands
+ if (!strcmp(name, "BindBufferMemory2KHR")) return (void *)table->BindBufferMemory2KHR;
+ if (!strcmp(name, "BindImageMemory2KHR")) return (void *)table->BindImageMemory2KHR;
+
+ // ---- VK_KHR_maintenance3 extension commands
+ if (!strcmp(name, "GetDescriptorSetLayoutSupportKHR")) return (void *)table->GetDescriptorSetLayoutSupportKHR;
+
+ // ---- VK_KHR_draw_indirect_count extension commands
+ if (!strcmp(name, "CmdDrawIndirectCountKHR")) return (void *)table->CmdDrawIndirectCountKHR;
+ if (!strcmp(name, "CmdDrawIndexedIndirectCountKHR")) return (void *)table->CmdDrawIndexedIndirectCountKHR;
+
+ // ---- VK_KHR_timeline_semaphore extension commands
+ if (!strcmp(name, "GetSemaphoreCounterValueKHR")) return (void *)table->GetSemaphoreCounterValueKHR;
+ if (!strcmp(name, "WaitSemaphoresKHR")) return (void *)table->WaitSemaphoresKHR;
+ if (!strcmp(name, "SignalSemaphoreKHR")) return (void *)table->SignalSemaphoreKHR;
+
+ // ---- VK_KHR_buffer_device_address extension commands
+ if (!strcmp(name, "GetBufferDeviceAddressKHR")) return (void *)table->GetBufferDeviceAddressKHR;
+ if (!strcmp(name, "GetBufferOpaqueCaptureAddressKHR")) return (void *)table->GetBufferOpaqueCaptureAddressKHR;
+ if (!strcmp(name, "GetDeviceMemoryOpaqueCaptureAddressKHR")) return (void *)table->GetDeviceMemoryOpaqueCaptureAddressKHR;
+
+ // ---- VK_KHR_pipeline_executable_properties extension commands
+ if (!strcmp(name, "GetPipelineExecutablePropertiesKHR")) return (void *)table->GetPipelineExecutablePropertiesKHR;
+ if (!strcmp(name, "GetPipelineExecutableStatisticsKHR")) return (void *)table->GetPipelineExecutableStatisticsKHR;
+ if (!strcmp(name, "GetPipelineExecutableInternalRepresentationsKHR")) return (void *)table->GetPipelineExecutableInternalRepresentationsKHR;
+
+ // ---- VK_EXT_debug_marker extension commands
+ if (!strcmp(name, "DebugMarkerSetObjectTagEXT")) return (void *)table->DebugMarkerSetObjectTagEXT;
+ if (!strcmp(name, "DebugMarkerSetObjectNameEXT")) return (void *)table->DebugMarkerSetObjectNameEXT;
+ if (!strcmp(name, "CmdDebugMarkerBeginEXT")) return (void *)table->CmdDebugMarkerBeginEXT;
+ if (!strcmp(name, "CmdDebugMarkerEndEXT")) return (void *)table->CmdDebugMarkerEndEXT;
+ if (!strcmp(name, "CmdDebugMarkerInsertEXT")) return (void *)table->CmdDebugMarkerInsertEXT;
+
+ // ---- VK_EXT_transform_feedback extension commands
+ if (!strcmp(name, "CmdBindTransformFeedbackBuffersEXT")) return (void *)table->CmdBindTransformFeedbackBuffersEXT;
+ if (!strcmp(name, "CmdBeginTransformFeedbackEXT")) return (void *)table->CmdBeginTransformFeedbackEXT;
+ if (!strcmp(name, "CmdEndTransformFeedbackEXT")) return (void *)table->CmdEndTransformFeedbackEXT;
+ if (!strcmp(name, "CmdBeginQueryIndexedEXT")) return (void *)table->CmdBeginQueryIndexedEXT;
+ if (!strcmp(name, "CmdEndQueryIndexedEXT")) return (void *)table->CmdEndQueryIndexedEXT;
+ if (!strcmp(name, "CmdDrawIndirectByteCountEXT")) return (void *)table->CmdDrawIndirectByteCountEXT;
+
+ // ---- VK_NVX_image_view_handle extension commands
+ if (!strcmp(name, "GetImageViewHandleNVX")) return (void *)table->GetImageViewHandleNVX;
+
+ // ---- VK_AMD_draw_indirect_count extension commands
+ if (!strcmp(name, "CmdDrawIndirectCountAMD")) return (void *)table->CmdDrawIndirectCountAMD;
+ if (!strcmp(name, "CmdDrawIndexedIndirectCountAMD")) return (void *)table->CmdDrawIndexedIndirectCountAMD;
+
+ // ---- VK_AMD_shader_info extension commands
+ if (!strcmp(name, "GetShaderInfoAMD")) return (void *)table->GetShaderInfoAMD;
+
+ // ---- VK_NV_external_memory_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "GetMemoryWin32HandleNV")) return (void *)table->GetMemoryWin32HandleNV;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_conditional_rendering extension commands
+ if (!strcmp(name, "CmdBeginConditionalRenderingEXT")) return (void *)table->CmdBeginConditionalRenderingEXT;
+ if (!strcmp(name, "CmdEndConditionalRenderingEXT")) return (void *)table->CmdEndConditionalRenderingEXT;
+
+ // ---- VK_NVX_device_generated_commands extension commands
+ if (!strcmp(name, "CmdProcessCommandsNVX")) return (void *)table->CmdProcessCommandsNVX;
+ if (!strcmp(name, "CmdReserveSpaceForCommandsNVX")) return (void *)table->CmdReserveSpaceForCommandsNVX;
+ if (!strcmp(name, "CreateIndirectCommandsLayoutNVX")) return (void *)table->CreateIndirectCommandsLayoutNVX;
+ if (!strcmp(name, "DestroyIndirectCommandsLayoutNVX")) return (void *)table->DestroyIndirectCommandsLayoutNVX;
+ if (!strcmp(name, "CreateObjectTableNVX")) return (void *)table->CreateObjectTableNVX;
+ if (!strcmp(name, "DestroyObjectTableNVX")) return (void *)table->DestroyObjectTableNVX;
+ if (!strcmp(name, "RegisterObjectsNVX")) return (void *)table->RegisterObjectsNVX;
+ if (!strcmp(name, "UnregisterObjectsNVX")) return (void *)table->UnregisterObjectsNVX;
+
+ // ---- VK_NV_clip_space_w_scaling extension commands
+ if (!strcmp(name, "CmdSetViewportWScalingNV")) return (void *)table->CmdSetViewportWScalingNV;
+
+ // ---- VK_EXT_display_control extension commands
+ if (!strcmp(name, "DisplayPowerControlEXT")) return (void *)table->DisplayPowerControlEXT;
+ if (!strcmp(name, "RegisterDeviceEventEXT")) return (void *)table->RegisterDeviceEventEXT;
+ if (!strcmp(name, "RegisterDisplayEventEXT")) return (void *)table->RegisterDisplayEventEXT;
+ if (!strcmp(name, "GetSwapchainCounterEXT")) return (void *)table->GetSwapchainCounterEXT;
+
+ // ---- VK_GOOGLE_display_timing extension commands
+ if (!strcmp(name, "GetRefreshCycleDurationGOOGLE")) return (void *)table->GetRefreshCycleDurationGOOGLE;
+ if (!strcmp(name, "GetPastPresentationTimingGOOGLE")) return (void *)table->GetPastPresentationTimingGOOGLE;
+
+ // ---- VK_EXT_discard_rectangles extension commands
+ if (!strcmp(name, "CmdSetDiscardRectangleEXT")) return (void *)table->CmdSetDiscardRectangleEXT;
+
+ // ---- VK_EXT_hdr_metadata extension commands
+ if (!strcmp(name, "SetHdrMetadataEXT")) return (void *)table->SetHdrMetadataEXT;
+
+ // ---- VK_EXT_debug_utils extension commands
+ if (!strcmp(name, "SetDebugUtilsObjectNameEXT")) return (void *)table->SetDebugUtilsObjectNameEXT;
+ if (!strcmp(name, "SetDebugUtilsObjectTagEXT")) return (void *)table->SetDebugUtilsObjectTagEXT;
+ if (!strcmp(name, "QueueBeginDebugUtilsLabelEXT")) return (void *)table->QueueBeginDebugUtilsLabelEXT;
+ if (!strcmp(name, "QueueEndDebugUtilsLabelEXT")) return (void *)table->QueueEndDebugUtilsLabelEXT;
+ if (!strcmp(name, "QueueInsertDebugUtilsLabelEXT")) return (void *)table->QueueInsertDebugUtilsLabelEXT;
+ if (!strcmp(name, "CmdBeginDebugUtilsLabelEXT")) return (void *)table->CmdBeginDebugUtilsLabelEXT;
+ if (!strcmp(name, "CmdEndDebugUtilsLabelEXT")) return (void *)table->CmdEndDebugUtilsLabelEXT;
+ if (!strcmp(name, "CmdInsertDebugUtilsLabelEXT")) return (void *)table->CmdInsertDebugUtilsLabelEXT;
+
+ // ---- VK_ANDROID_external_memory_android_hardware_buffer extension commands
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ if (!strcmp(name, "GetAndroidHardwareBufferPropertiesANDROID")) return (void *)table->GetAndroidHardwareBufferPropertiesANDROID;
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ if (!strcmp(name, "GetMemoryAndroidHardwareBufferANDROID")) return (void *)table->GetMemoryAndroidHardwareBufferANDROID;
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+ // ---- VK_EXT_sample_locations extension commands
+ if (!strcmp(name, "CmdSetSampleLocationsEXT")) return (void *)table->CmdSetSampleLocationsEXT;
+
+ // ---- VK_EXT_image_drm_format_modifier extension commands
+ if (!strcmp(name, "GetImageDrmFormatModifierPropertiesEXT")) return (void *)table->GetImageDrmFormatModifierPropertiesEXT;
+
+ // ---- VK_EXT_validation_cache extension commands
+ if (!strcmp(name, "CreateValidationCacheEXT")) return (void *)table->CreateValidationCacheEXT;
+ if (!strcmp(name, "DestroyValidationCacheEXT")) return (void *)table->DestroyValidationCacheEXT;
+ if (!strcmp(name, "MergeValidationCachesEXT")) return (void *)table->MergeValidationCachesEXT;
+ if (!strcmp(name, "GetValidationCacheDataEXT")) return (void *)table->GetValidationCacheDataEXT;
+
+ // ---- VK_NV_shading_rate_image extension commands
+ if (!strcmp(name, "CmdBindShadingRateImageNV")) return (void *)table->CmdBindShadingRateImageNV;
+ if (!strcmp(name, "CmdSetViewportShadingRatePaletteNV")) return (void *)table->CmdSetViewportShadingRatePaletteNV;
+ if (!strcmp(name, "CmdSetCoarseSampleOrderNV")) return (void *)table->CmdSetCoarseSampleOrderNV;
+
+ // ---- VK_NV_ray_tracing extension commands
+ if (!strcmp(name, "CreateAccelerationStructureNV")) return (void *)table->CreateAccelerationStructureNV;
+ if (!strcmp(name, "DestroyAccelerationStructureNV")) return (void *)table->DestroyAccelerationStructureNV;
+ if (!strcmp(name, "GetAccelerationStructureMemoryRequirementsNV")) return (void *)table->GetAccelerationStructureMemoryRequirementsNV;
+ if (!strcmp(name, "BindAccelerationStructureMemoryNV")) return (void *)table->BindAccelerationStructureMemoryNV;
+ if (!strcmp(name, "CmdBuildAccelerationStructureNV")) return (void *)table->CmdBuildAccelerationStructureNV;
+ if (!strcmp(name, "CmdCopyAccelerationStructureNV")) return (void *)table->CmdCopyAccelerationStructureNV;
+ if (!strcmp(name, "CmdTraceRaysNV")) return (void *)table->CmdTraceRaysNV;
+ if (!strcmp(name, "CreateRayTracingPipelinesNV")) return (void *)table->CreateRayTracingPipelinesNV;
+ if (!strcmp(name, "GetRayTracingShaderGroupHandlesNV")) return (void *)table->GetRayTracingShaderGroupHandlesNV;
+ if (!strcmp(name, "GetAccelerationStructureHandleNV")) return (void *)table->GetAccelerationStructureHandleNV;
+ if (!strcmp(name, "CmdWriteAccelerationStructuresPropertiesNV")) return (void *)table->CmdWriteAccelerationStructuresPropertiesNV;
+ if (!strcmp(name, "CompileDeferredNV")) return (void *)table->CompileDeferredNV;
+
+ // ---- VK_EXT_external_memory_host extension commands
+ if (!strcmp(name, "GetMemoryHostPointerPropertiesEXT")) return (void *)table->GetMemoryHostPointerPropertiesEXT;
+
+ // ---- VK_AMD_buffer_marker extension commands
+ if (!strcmp(name, "CmdWriteBufferMarkerAMD")) return (void *)table->CmdWriteBufferMarkerAMD;
+
+ // ---- VK_EXT_calibrated_timestamps extension commands
+ if (!strcmp(name, "GetCalibratedTimestampsEXT")) return (void *)table->GetCalibratedTimestampsEXT;
+
+ // ---- VK_NV_mesh_shader extension commands
+ if (!strcmp(name, "CmdDrawMeshTasksNV")) return (void *)table->CmdDrawMeshTasksNV;
+ if (!strcmp(name, "CmdDrawMeshTasksIndirectNV")) return (void *)table->CmdDrawMeshTasksIndirectNV;
+ if (!strcmp(name, "CmdDrawMeshTasksIndirectCountNV")) return (void *)table->CmdDrawMeshTasksIndirectCountNV;
+
+ // ---- VK_NV_scissor_exclusive extension commands
+ if (!strcmp(name, "CmdSetExclusiveScissorNV")) return (void *)table->CmdSetExclusiveScissorNV;
+
+ // ---- VK_NV_device_diagnostic_checkpoints extension commands
+ if (!strcmp(name, "CmdSetCheckpointNV")) return (void *)table->CmdSetCheckpointNV;
+ if (!strcmp(name, "GetQueueCheckpointDataNV")) return (void *)table->GetQueueCheckpointDataNV;
+
+ // ---- VK_INTEL_performance_query extension commands
+ if (!strcmp(name, "InitializePerformanceApiINTEL")) return (void *)table->InitializePerformanceApiINTEL;
+ if (!strcmp(name, "UninitializePerformanceApiINTEL")) return (void *)table->UninitializePerformanceApiINTEL;
+ if (!strcmp(name, "CmdSetPerformanceMarkerINTEL")) return (void *)table->CmdSetPerformanceMarkerINTEL;
+ if (!strcmp(name, "CmdSetPerformanceStreamMarkerINTEL")) return (void *)table->CmdSetPerformanceStreamMarkerINTEL;
+ if (!strcmp(name, "CmdSetPerformanceOverrideINTEL")) return (void *)table->CmdSetPerformanceOverrideINTEL;
+ if (!strcmp(name, "AcquirePerformanceConfigurationINTEL")) return (void *)table->AcquirePerformanceConfigurationINTEL;
+ if (!strcmp(name, "ReleasePerformanceConfigurationINTEL")) return (void *)table->ReleasePerformanceConfigurationINTEL;
+ if (!strcmp(name, "QueueSetPerformanceConfigurationINTEL")) return (void *)table->QueueSetPerformanceConfigurationINTEL;
+ if (!strcmp(name, "GetPerformanceParameterINTEL")) return (void *)table->GetPerformanceParameterINTEL;
+
+ // ---- VK_AMD_display_native_hdr extension commands
+ if (!strcmp(name, "SetLocalDimmingAMD")) return (void *)table->SetLocalDimmingAMD;
+
+ // ---- VK_EXT_buffer_device_address extension commands
+ if (!strcmp(name, "GetBufferDeviceAddressEXT")) return (void *)table->GetBufferDeviceAddressEXT;
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "AcquireFullScreenExclusiveModeEXT")) return (void *)table->AcquireFullScreenExclusiveModeEXT;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "ReleaseFullScreenExclusiveModeEXT")) return (void *)table->ReleaseFullScreenExclusiveModeEXT;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "GetDeviceGroupSurfacePresentModes2EXT")) return (void *)table->GetDeviceGroupSurfacePresentModes2EXT;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_line_rasterization extension commands
+ if (!strcmp(name, "CmdSetLineStippleEXT")) return (void *)table->CmdSetLineStippleEXT;
+
+ // ---- VK_EXT_host_query_reset extension commands
+ if (!strcmp(name, "ResetQueryPoolEXT")) return (void *)table->ResetQueryPoolEXT;
+
+ return NULL;
+}
+
+// Instance command lookup function
+VKAPI_ATTR void* VKAPI_CALL loader_lookup_instance_dispatch_table(const VkLayerInstanceDispatchTable *table, const char *name,
+ bool *found_name) {
+ if (!name || name[0] != 'v' || name[1] != 'k') {
+ *found_name = false;
+ return NULL;
+ }
+
+ *found_name = true;
+ name += 2;
+
+ // ---- Core 1_0 commands
+ if (!strcmp(name, "DestroyInstance")) return (void *)table->DestroyInstance;
+ if (!strcmp(name, "EnumeratePhysicalDevices")) return (void *)table->EnumeratePhysicalDevices;
+ if (!strcmp(name, "GetPhysicalDeviceFeatures")) return (void *)table->GetPhysicalDeviceFeatures;
+ if (!strcmp(name, "GetPhysicalDeviceFormatProperties")) return (void *)table->GetPhysicalDeviceFormatProperties;
+ if (!strcmp(name, "GetPhysicalDeviceImageFormatProperties")) return (void *)table->GetPhysicalDeviceImageFormatProperties;
+ if (!strcmp(name, "GetPhysicalDeviceProperties")) return (void *)table->GetPhysicalDeviceProperties;
+ if (!strcmp(name, "GetPhysicalDeviceQueueFamilyProperties")) return (void *)table->GetPhysicalDeviceQueueFamilyProperties;
+ if (!strcmp(name, "GetPhysicalDeviceMemoryProperties")) return (void *)table->GetPhysicalDeviceMemoryProperties;
+ if (!strcmp(name, "GetInstanceProcAddr")) return (void *)table->GetInstanceProcAddr;
+ if (!strcmp(name, "EnumerateDeviceExtensionProperties")) return (void *)table->EnumerateDeviceExtensionProperties;
+ if (!strcmp(name, "EnumerateDeviceLayerProperties")) return (void *)table->EnumerateDeviceLayerProperties;
+ if (!strcmp(name, "GetPhysicalDeviceSparseImageFormatProperties")) return (void *)table->GetPhysicalDeviceSparseImageFormatProperties;
+
+ // ---- Core 1_1 commands
+ if (!strcmp(name, "EnumeratePhysicalDeviceGroups")) return (void *)table->EnumeratePhysicalDeviceGroups;
+ if (!strcmp(name, "GetPhysicalDeviceFeatures2")) return (void *)table->GetPhysicalDeviceFeatures2;
+ if (!strcmp(name, "GetPhysicalDeviceProperties2")) return (void *)table->GetPhysicalDeviceProperties2;
+ if (!strcmp(name, "GetPhysicalDeviceFormatProperties2")) return (void *)table->GetPhysicalDeviceFormatProperties2;
+ if (!strcmp(name, "GetPhysicalDeviceImageFormatProperties2")) return (void *)table->GetPhysicalDeviceImageFormatProperties2;
+ if (!strcmp(name, "GetPhysicalDeviceQueueFamilyProperties2")) return (void *)table->GetPhysicalDeviceQueueFamilyProperties2;
+ if (!strcmp(name, "GetPhysicalDeviceMemoryProperties2")) return (void *)table->GetPhysicalDeviceMemoryProperties2;
+ if (!strcmp(name, "GetPhysicalDeviceSparseImageFormatProperties2")) return (void *)table->GetPhysicalDeviceSparseImageFormatProperties2;
+ if (!strcmp(name, "GetPhysicalDeviceExternalBufferProperties")) return (void *)table->GetPhysicalDeviceExternalBufferProperties;
+ if (!strcmp(name, "GetPhysicalDeviceExternalFenceProperties")) return (void *)table->GetPhysicalDeviceExternalFenceProperties;
+ if (!strcmp(name, "GetPhysicalDeviceExternalSemaphoreProperties")) return (void *)table->GetPhysicalDeviceExternalSemaphoreProperties;
+
+ // ---- VK_KHR_surface extension commands
+ if (!strcmp(name, "DestroySurfaceKHR")) return (void *)table->DestroySurfaceKHR;
+ if (!strcmp(name, "GetPhysicalDeviceSurfaceSupportKHR")) return (void *)table->GetPhysicalDeviceSurfaceSupportKHR;
+ if (!strcmp(name, "GetPhysicalDeviceSurfaceCapabilitiesKHR")) return (void *)table->GetPhysicalDeviceSurfaceCapabilitiesKHR;
+ if (!strcmp(name, "GetPhysicalDeviceSurfaceFormatsKHR")) return (void *)table->GetPhysicalDeviceSurfaceFormatsKHR;
+ if (!strcmp(name, "GetPhysicalDeviceSurfacePresentModesKHR")) return (void *)table->GetPhysicalDeviceSurfacePresentModesKHR;
+
+ // ---- VK_KHR_swapchain extension commands
+ if (!strcmp(name, "GetPhysicalDevicePresentRectanglesKHR")) return (void *)table->GetPhysicalDevicePresentRectanglesKHR;
+
+ // ---- VK_KHR_display extension commands
+ if (!strcmp(name, "GetPhysicalDeviceDisplayPropertiesKHR")) return (void *)table->GetPhysicalDeviceDisplayPropertiesKHR;
+ if (!strcmp(name, "GetPhysicalDeviceDisplayPlanePropertiesKHR")) return (void *)table->GetPhysicalDeviceDisplayPlanePropertiesKHR;
+ if (!strcmp(name, "GetDisplayPlaneSupportedDisplaysKHR")) return (void *)table->GetDisplayPlaneSupportedDisplaysKHR;
+ if (!strcmp(name, "GetDisplayModePropertiesKHR")) return (void *)table->GetDisplayModePropertiesKHR;
+ if (!strcmp(name, "CreateDisplayModeKHR")) return (void *)table->CreateDisplayModeKHR;
+ if (!strcmp(name, "GetDisplayPlaneCapabilitiesKHR")) return (void *)table->GetDisplayPlaneCapabilitiesKHR;
+ if (!strcmp(name, "CreateDisplayPlaneSurfaceKHR")) return (void *)table->CreateDisplayPlaneSurfaceKHR;
+
+ // ---- VK_KHR_xlib_surface extension commands
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ if (!strcmp(name, "CreateXlibSurfaceKHR")) return (void *)table->CreateXlibSurfaceKHR;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ if (!strcmp(name, "GetPhysicalDeviceXlibPresentationSupportKHR")) return (void *)table->GetPhysicalDeviceXlibPresentationSupportKHR;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+
+ // ---- VK_KHR_xcb_surface extension commands
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ if (!strcmp(name, "CreateXcbSurfaceKHR")) return (void *)table->CreateXcbSurfaceKHR;
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ if (!strcmp(name, "GetPhysicalDeviceXcbPresentationSupportKHR")) return (void *)table->GetPhysicalDeviceXcbPresentationSupportKHR;
+#endif // VK_USE_PLATFORM_XCB_KHR
+
+ // ---- VK_KHR_wayland_surface extension commands
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ if (!strcmp(name, "CreateWaylandSurfaceKHR")) return (void *)table->CreateWaylandSurfaceKHR;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ if (!strcmp(name, "GetPhysicalDeviceWaylandPresentationSupportKHR")) return (void *)table->GetPhysicalDeviceWaylandPresentationSupportKHR;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+
+ // ---- VK_KHR_android_surface extension commands
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ if (!strcmp(name, "CreateAndroidSurfaceKHR")) return (void *)table->CreateAndroidSurfaceKHR;
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+ // ---- VK_KHR_win32_surface extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "CreateWin32SurfaceKHR")) return (void *)table->CreateWin32SurfaceKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "GetPhysicalDeviceWin32PresentationSupportKHR")) return (void *)table->GetPhysicalDeviceWin32PresentationSupportKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_get_physical_device_properties2 extension commands
+ if (!strcmp(name, "GetPhysicalDeviceFeatures2KHR")) return (void *)table->GetPhysicalDeviceFeatures2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceProperties2KHR")) return (void *)table->GetPhysicalDeviceProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceFormatProperties2KHR")) return (void *)table->GetPhysicalDeviceFormatProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceImageFormatProperties2KHR")) return (void *)table->GetPhysicalDeviceImageFormatProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceQueueFamilyProperties2KHR")) return (void *)table->GetPhysicalDeviceQueueFamilyProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceMemoryProperties2KHR")) return (void *)table->GetPhysicalDeviceMemoryProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceSparseImageFormatProperties2KHR")) return (void *)table->GetPhysicalDeviceSparseImageFormatProperties2KHR;
+
+ // ---- VK_KHR_device_group_creation extension commands
+ if (!strcmp(name, "EnumeratePhysicalDeviceGroupsKHR")) return (void *)table->EnumeratePhysicalDeviceGroupsKHR;
+
+ // ---- VK_KHR_external_memory_capabilities extension commands
+ if (!strcmp(name, "GetPhysicalDeviceExternalBufferPropertiesKHR")) return (void *)table->GetPhysicalDeviceExternalBufferPropertiesKHR;
+
+ // ---- VK_KHR_external_semaphore_capabilities extension commands
+ if (!strcmp(name, "GetPhysicalDeviceExternalSemaphorePropertiesKHR")) return (void *)table->GetPhysicalDeviceExternalSemaphorePropertiesKHR;
+
+ // ---- VK_KHR_external_fence_capabilities extension commands
+ if (!strcmp(name, "GetPhysicalDeviceExternalFencePropertiesKHR")) return (void *)table->GetPhysicalDeviceExternalFencePropertiesKHR;
+
+ // ---- VK_KHR_performance_query extension commands
+ if (!strcmp(name, "EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR")) return (void *)table->EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR;
+ if (!strcmp(name, "GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR")) return (void *)table->GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR;
+
+ // ---- VK_KHR_get_surface_capabilities2 extension commands
+ if (!strcmp(name, "GetPhysicalDeviceSurfaceCapabilities2KHR")) return (void *)table->GetPhysicalDeviceSurfaceCapabilities2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceSurfaceFormats2KHR")) return (void *)table->GetPhysicalDeviceSurfaceFormats2KHR;
+
+ // ---- VK_KHR_get_display_properties2 extension commands
+ if (!strcmp(name, "GetPhysicalDeviceDisplayProperties2KHR")) return (void *)table->GetPhysicalDeviceDisplayProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceDisplayPlaneProperties2KHR")) return (void *)table->GetPhysicalDeviceDisplayPlaneProperties2KHR;
+ if (!strcmp(name, "GetDisplayModeProperties2KHR")) return (void *)table->GetDisplayModeProperties2KHR;
+ if (!strcmp(name, "GetDisplayPlaneCapabilities2KHR")) return (void *)table->GetDisplayPlaneCapabilities2KHR;
+
+ // ---- VK_EXT_debug_report extension commands
+ if (!strcmp(name, "CreateDebugReportCallbackEXT")) return (void *)table->CreateDebugReportCallbackEXT;
+ if (!strcmp(name, "DestroyDebugReportCallbackEXT")) return (void *)table->DestroyDebugReportCallbackEXT;
+ if (!strcmp(name, "DebugReportMessageEXT")) return (void *)table->DebugReportMessageEXT;
+
+ // ---- VK_GGP_stream_descriptor_surface extension commands
+#ifdef VK_USE_PLATFORM_GGP
+ if (!strcmp(name, "CreateStreamDescriptorSurfaceGGP")) return (void *)table->CreateStreamDescriptorSurfaceGGP;
+#endif // VK_USE_PLATFORM_GGP
+
+ // ---- VK_NV_external_memory_capabilities extension commands
+ if (!strcmp(name, "GetPhysicalDeviceExternalImageFormatPropertiesNV")) return (void *)table->GetPhysicalDeviceExternalImageFormatPropertiesNV;
+
+ // ---- VK_NN_vi_surface extension commands
+#ifdef VK_USE_PLATFORM_VI_NN
+ if (!strcmp(name, "CreateViSurfaceNN")) return (void *)table->CreateViSurfaceNN;
+#endif // VK_USE_PLATFORM_VI_NN
+
+ // ---- VK_NVX_device_generated_commands extension commands
+ if (!strcmp(name, "GetPhysicalDeviceGeneratedCommandsPropertiesNVX")) return (void *)table->GetPhysicalDeviceGeneratedCommandsPropertiesNVX;
+
+ // ---- VK_EXT_direct_mode_display extension commands
+ if (!strcmp(name, "ReleaseDisplayEXT")) return (void *)table->ReleaseDisplayEXT;
+
+ // ---- VK_EXT_acquire_xlib_display extension commands
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ if (!strcmp(name, "AcquireXlibDisplayEXT")) return (void *)table->AcquireXlibDisplayEXT;
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ if (!strcmp(name, "GetRandROutputDisplayEXT")) return (void *)table->GetRandROutputDisplayEXT;
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
+ // ---- VK_EXT_display_surface_counter extension commands
+ if (!strcmp(name, "GetPhysicalDeviceSurfaceCapabilities2EXT")) return (void *)table->GetPhysicalDeviceSurfaceCapabilities2EXT;
+
+ // ---- VK_MVK_ios_surface extension commands
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ if (!strcmp(name, "CreateIOSSurfaceMVK")) return (void *)table->CreateIOSSurfaceMVK;
+#endif // VK_USE_PLATFORM_IOS_MVK
+
+ // ---- VK_MVK_macos_surface extension commands
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ if (!strcmp(name, "CreateMacOSSurfaceMVK")) return (void *)table->CreateMacOSSurfaceMVK;
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
+ // ---- VK_EXT_debug_utils extension commands
+ if (!strcmp(name, "CreateDebugUtilsMessengerEXT")) return (void *)table->CreateDebugUtilsMessengerEXT;
+ if (!strcmp(name, "DestroyDebugUtilsMessengerEXT")) return (void *)table->DestroyDebugUtilsMessengerEXT;
+ if (!strcmp(name, "SubmitDebugUtilsMessageEXT")) return (void *)table->SubmitDebugUtilsMessageEXT;
+
+ // ---- VK_EXT_sample_locations extension commands
+ if (!strcmp(name, "GetPhysicalDeviceMultisamplePropertiesEXT")) return (void *)table->GetPhysicalDeviceMultisamplePropertiesEXT;
+
+ // ---- VK_EXT_calibrated_timestamps extension commands
+ if (!strcmp(name, "GetPhysicalDeviceCalibrateableTimeDomainsEXT")) return (void *)table->GetPhysicalDeviceCalibrateableTimeDomainsEXT;
+
+ // ---- VK_FUCHSIA_imagepipe_surface extension commands
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ if (!strcmp(name, "CreateImagePipeSurfaceFUCHSIA")) return (void *)table->CreateImagePipeSurfaceFUCHSIA;
+#endif // VK_USE_PLATFORM_FUCHSIA
+
+ // ---- VK_EXT_metal_surface extension commands
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ if (!strcmp(name, "CreateMetalSurfaceEXT")) return (void *)table->CreateMetalSurfaceEXT;
+#endif // VK_USE_PLATFORM_METAL_EXT
+
+ // ---- VK_EXT_tooling_info extension commands
+ if (!strcmp(name, "GetPhysicalDeviceToolPropertiesEXT")) return (void *)table->GetPhysicalDeviceToolPropertiesEXT;
+
+ // ---- VK_NV_cooperative_matrix extension commands
+ if (!strcmp(name, "GetPhysicalDeviceCooperativeMatrixPropertiesNV")) return (void *)table->GetPhysicalDeviceCooperativeMatrixPropertiesNV;
+
+ // ---- VK_NV_coverage_reduction_mode extension commands
+ if (!strcmp(name, "GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV")) return (void *)table->GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV;
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(name, "GetPhysicalDeviceSurfacePresentModes2EXT")) return (void *)table->GetPhysicalDeviceSurfacePresentModes2EXT;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_headless_surface extension commands
+ if (!strcmp(name, "CreateHeadlessSurfaceEXT")) return (void *)table->CreateHeadlessSurfaceEXT;
+
+ *found_name = false;
+ return NULL;
+}
+
+
+// ---- VK_KHR_device_group extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL GetDeviceGroupPeerMemoryFeaturesKHR(
+ VkDevice device,
+ uint32_t heapIndex,
+ uint32_t localDeviceIndex,
+ uint32_t remoteDeviceIndex,
+ VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetDeviceGroupPeerMemoryFeaturesKHR(device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdSetDeviceMaskKHR(
+ VkCommandBuffer commandBuffer,
+ uint32_t deviceMask) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdSetDeviceMaskKHR(commandBuffer, deviceMask);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdDispatchBaseKHR(
+ VkCommandBuffer commandBuffer,
+ uint32_t baseGroupX,
+ uint32_t baseGroupY,
+ uint32_t baseGroupZ,
+ uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDispatchBaseKHR(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
+}
+
+
+// ---- VK_KHR_maintenance1 extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL TrimCommandPoolKHR(
+ VkDevice device,
+ VkCommandPool commandPool,
+ VkCommandPoolTrimFlags flags) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->TrimCommandPoolKHR(device, commandPool, flags);
+}
+
+
+// ---- VK_KHR_external_memory_win32 extension trampoline/terminators
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL GetMemoryWin32HandleKHR(
+ VkDevice device,
+ const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo,
+ HANDLE* pHandle) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetMemoryWin32HandleKHR(device, pGetWin32HandleInfo, pHandle);
+}
+
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL GetMemoryWin32HandlePropertiesKHR(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBits handleType,
+ HANDLE handle,
+ VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetMemoryWin32HandlePropertiesKHR(device, handleType, handle, pMemoryWin32HandleProperties);
+}
+
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+// ---- VK_KHR_external_memory_fd extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetMemoryFdKHR(
+ VkDevice device,
+ const VkMemoryGetFdInfoKHR* pGetFdInfo,
+ int* pFd) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetMemoryFdKHR(device, pGetFdInfo, pFd);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetMemoryFdPropertiesKHR(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBits handleType,
+ int fd,
+ VkMemoryFdPropertiesKHR* pMemoryFdProperties) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetMemoryFdPropertiesKHR(device, handleType, fd, pMemoryFdProperties);
+}
+
+
+// ---- VK_KHR_external_semaphore_win32 extension trampoline/terminators
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL ImportSemaphoreWin32HandleKHR(
+ VkDevice device,
+ const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->ImportSemaphoreWin32HandleKHR(device, pImportSemaphoreWin32HandleInfo);
+}
+
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL GetSemaphoreWin32HandleKHR(
+ VkDevice device,
+ const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo,
+ HANDLE* pHandle) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetSemaphoreWin32HandleKHR(device, pGetWin32HandleInfo, pHandle);
+}
+
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+// ---- VK_KHR_external_semaphore_fd extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL ImportSemaphoreFdKHR(
+ VkDevice device,
+ const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->ImportSemaphoreFdKHR(device, pImportSemaphoreFdInfo);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetSemaphoreFdKHR(
+ VkDevice device,
+ const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
+ int* pFd) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetSemaphoreFdKHR(device, pGetFdInfo, pFd);
+}
+
+
+// ---- VK_KHR_push_descriptor extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdPushDescriptorSetKHR(
+ VkCommandBuffer commandBuffer,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ uint32_t set,
+ uint32_t descriptorWriteCount,
+ const VkWriteDescriptorSet* pDescriptorWrites) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdPushDescriptorSetKHR(commandBuffer, pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdPushDescriptorSetWithTemplateKHR(
+ VkCommandBuffer commandBuffer,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ VkPipelineLayout layout,
+ uint32_t set,
+ const void* pData) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdPushDescriptorSetWithTemplateKHR(commandBuffer, descriptorUpdateTemplate, layout, set, pData);
+}
+
+
+// ---- VK_KHR_descriptor_update_template extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorUpdateTemplateKHR(
+ VkDevice device,
+ const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateDescriptorUpdateTemplateKHR(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+}
+
+VKAPI_ATTR void VKAPI_CALL DestroyDescriptorUpdateTemplateKHR(
+ VkDevice device,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const VkAllocationCallbacks* pAllocator) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->DestroyDescriptorUpdateTemplateKHR(device, descriptorUpdateTemplate, pAllocator);
+}
+
+VKAPI_ATTR void VKAPI_CALL UpdateDescriptorSetWithTemplateKHR(
+ VkDevice device,
+ VkDescriptorSet descriptorSet,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const void* pData) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->UpdateDescriptorSetWithTemplateKHR(device, descriptorSet, descriptorUpdateTemplate, pData);
+}
+
+
+// ---- VK_KHR_create_renderpass2 extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass2KHR(
+ VkDevice device,
+ const VkRenderPassCreateInfo2* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkRenderPass* pRenderPass) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateRenderPass2KHR(device, pCreateInfo, pAllocator, pRenderPass);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdBeginRenderPass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkRenderPassBeginInfo* pRenderPassBegin,
+ const VkSubpassBeginInfo* pSubpassBeginInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdBeginRenderPass2KHR(commandBuffer, pRenderPassBegin, pSubpassBeginInfo);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdNextSubpass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkSubpassBeginInfo* pSubpassBeginInfo,
+ const VkSubpassEndInfo* pSubpassEndInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdNextSubpass2KHR(commandBuffer, pSubpassBeginInfo, pSubpassEndInfo);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdEndRenderPass2KHR(
+ VkCommandBuffer commandBuffer,
+ const VkSubpassEndInfo* pSubpassEndInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdEndRenderPass2KHR(commandBuffer, pSubpassEndInfo);
+}
+
+
+// ---- VK_KHR_shared_presentable_image extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetSwapchainStatusKHR(
+ VkDevice device,
+ VkSwapchainKHR swapchain) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetSwapchainStatusKHR(device, swapchain);
+}
+
+
+// ---- VK_KHR_external_fence_win32 extension trampoline/terminators
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL ImportFenceWin32HandleKHR(
+ VkDevice device,
+ const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->ImportFenceWin32HandleKHR(device, pImportFenceWin32HandleInfo);
+}
+
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL GetFenceWin32HandleKHR(
+ VkDevice device,
+ const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo,
+ HANDLE* pHandle) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetFenceWin32HandleKHR(device, pGetWin32HandleInfo, pHandle);
+}
+
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+// ---- VK_KHR_external_fence_fd extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL ImportFenceFdKHR(
+ VkDevice device,
+ const VkImportFenceFdInfoKHR* pImportFenceFdInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->ImportFenceFdKHR(device, pImportFenceFdInfo);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetFenceFdKHR(
+ VkDevice device,
+ const VkFenceGetFdInfoKHR* pGetFdInfo,
+ int* pFd) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetFenceFdKHR(device, pGetFdInfo, pFd);
+}
+
+
+// ---- VK_KHR_performance_query extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ uint32_t* pCounterCount,
+ VkPerformanceCounterKHR* pCounters,
+ VkPerformanceCounterDescriptionKHR* pCounterDescriptions) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(unwrapped_phys_dev, queueFamilyIndex, pCounterCount, pCounters, pCounterDescriptions);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ uint32_t* pCounterCount,
+ VkPerformanceCounterKHR* pCounters,
+ VkPerformanceCounterDescriptionKHR* pCounterDescriptions) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->dispatch.EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR");
+ }
+ return icd_term->dispatch.EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(phys_dev_term->phys_dev, queueFamilyIndex, pCounterCount, pCounters, pCounterDescriptions);
+}
+
+VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(
+ VkPhysicalDevice physicalDevice,
+ const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo,
+ uint32_t* pNumPasses) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(unwrapped_phys_dev, pPerformanceQueryCreateInfo, pNumPasses);
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(
+ VkPhysicalDevice physicalDevice,
+ const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo,
+ uint32_t* pNumPasses) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR");
+ }
+ icd_term->dispatch.GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(phys_dev_term->phys_dev, pPerformanceQueryCreateInfo, pNumPasses);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL AcquireProfilingLockKHR(
+ VkDevice device,
+ const VkAcquireProfilingLockInfoKHR* pInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->AcquireProfilingLockKHR(device, pInfo);
+}
+
+VKAPI_ATTR void VKAPI_CALL ReleaseProfilingLockKHR(
+ VkDevice device) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->ReleaseProfilingLockKHR(device);
+}
+
+
+// ---- VK_KHR_get_memory_requirements2 extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL GetImageMemoryRequirements2KHR(
+ VkDevice device,
+ const VkImageMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetImageMemoryRequirements2KHR(device, pInfo, pMemoryRequirements);
+}
+
+VKAPI_ATTR void VKAPI_CALL GetBufferMemoryRequirements2KHR(
+ VkDevice device,
+ const VkBufferMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetBufferMemoryRequirements2KHR(device, pInfo, pMemoryRequirements);
+}
+
+VKAPI_ATTR void VKAPI_CALL GetImageSparseMemoryRequirements2KHR(
+ VkDevice device,
+ const VkImageSparseMemoryRequirementsInfo2* pInfo,
+ uint32_t* pSparseMemoryRequirementCount,
+ VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetImageSparseMemoryRequirements2KHR(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+
+// ---- VK_KHR_sampler_ycbcr_conversion extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateSamplerYcbcrConversionKHR(
+ VkDevice device,
+ const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSamplerYcbcrConversion* pYcbcrConversion) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateSamplerYcbcrConversionKHR(device, pCreateInfo, pAllocator, pYcbcrConversion);
+}
+
+VKAPI_ATTR void VKAPI_CALL DestroySamplerYcbcrConversionKHR(
+ VkDevice device,
+ VkSamplerYcbcrConversion ycbcrConversion,
+ const VkAllocationCallbacks* pAllocator) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->DestroySamplerYcbcrConversionKHR(device, ycbcrConversion, pAllocator);
+}
+
+
+// ---- VK_KHR_bind_memory2 extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory2KHR(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindBufferMemoryInfo* pBindInfos) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->BindBufferMemory2KHR(device, bindInfoCount, pBindInfos);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory2KHR(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindImageMemoryInfo* pBindInfos) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->BindImageMemory2KHR(device, bindInfoCount, pBindInfos);
+}
+
+
+// ---- VK_KHR_maintenance3 extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL GetDescriptorSetLayoutSupportKHR(
+ VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ VkDescriptorSetLayoutSupport* pSupport) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetDescriptorSetLayoutSupportKHR(device, pCreateInfo, pSupport);
+}
+
+
+// ---- VK_KHR_draw_indirect_count extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdDrawIndirectCountKHR(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirectCountKHR(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
+}
+
+
+// ---- VK_KHR_timeline_semaphore extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetSemaphoreCounterValueKHR(
+ VkDevice device,
+ VkSemaphore semaphore,
+ uint64_t* pValue) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetSemaphoreCounterValueKHR(device, semaphore, pValue);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL WaitSemaphoresKHR(
+ VkDevice device,
+ const VkSemaphoreWaitInfo* pWaitInfo,
+ uint64_t timeout) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->WaitSemaphoresKHR(device, pWaitInfo, timeout);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL SignalSemaphoreKHR(
+ VkDevice device,
+ const VkSemaphoreSignalInfo* pSignalInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->SignalSemaphoreKHR(device, pSignalInfo);
+}
+
+
+// ---- VK_KHR_buffer_device_address extension trampoline/terminators
+
+VKAPI_ATTR VkDeviceAddress VKAPI_CALL GetBufferDeviceAddressKHR(
+ VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetBufferDeviceAddressKHR(device, pInfo);
+}
+
+VKAPI_ATTR uint64_t VKAPI_CALL GetBufferOpaqueCaptureAddressKHR(
+ VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetBufferOpaqueCaptureAddressKHR(device, pInfo);
+}
+
+VKAPI_ATTR uint64_t VKAPI_CALL GetDeviceMemoryOpaqueCaptureAddressKHR(
+ VkDevice device,
+ const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetDeviceMemoryOpaqueCaptureAddressKHR(device, pInfo);
+}
+
+
+// ---- VK_KHR_pipeline_executable_properties extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPipelineExecutablePropertiesKHR(
+ VkDevice device,
+ const VkPipelineInfoKHR* pPipelineInfo,
+ uint32_t* pExecutableCount,
+ VkPipelineExecutablePropertiesKHR* pProperties) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetPipelineExecutablePropertiesKHR(device, pPipelineInfo, pExecutableCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPipelineExecutableStatisticsKHR(
+ VkDevice device,
+ const VkPipelineExecutableInfoKHR* pExecutableInfo,
+ uint32_t* pStatisticCount,
+ VkPipelineExecutableStatisticKHR* pStatistics) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetPipelineExecutableStatisticsKHR(device, pExecutableInfo, pStatisticCount, pStatistics);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPipelineExecutableInternalRepresentationsKHR(
+ VkDevice device,
+ const VkPipelineExecutableInfoKHR* pExecutableInfo,
+ uint32_t* pInternalRepresentationCount,
+ VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetPipelineExecutableInternalRepresentationsKHR(device, pExecutableInfo, pInternalRepresentationCount, pInternalRepresentations);
+}
+
+
+// ---- VK_EXT_debug_marker extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectTagEXT(
+ VkDevice device,
+ const VkDebugMarkerObjectTagInfoEXT* pTagInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ VkDebugMarkerObjectTagInfoEXT local_tag_info;
+ memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugMarkerObjectTagInfoEXT));
+ // If this is a physical device, we have to replace it with the proper one for the next call.
+ if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {
+ struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pTagInfo->object;
+ local_tag_info.object = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;
+ }
+ return disp->DebugMarkerSetObjectTagEXT(device, &local_tag_info);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectTagEXT(
+ VkDevice device,
+ const VkDebugMarkerObjectTagInfoEXT* pTagInfo) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.DebugMarkerSetObjectTagEXT) {
+ VkDebugMarkerObjectTagInfoEXT local_tag_info;
+ memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugMarkerObjectTagInfoEXT));
+ // If this is a physical device, we have to replace it with the proper one for the next call.
+ if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pTagInfo->object;
+ local_tag_info.object = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;
+ // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.
+ } else if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {
+ if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->object;
+ if (NULL != icd_surface->real_icd_surfaces) {
+ local_tag_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];
+ }
+ }
+ }
+ return icd_term->dispatch.DebugMarkerSetObjectTagEXT(device, &local_tag_info);
+ } else {
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectNameEXT(
+ VkDevice device,
+ const VkDebugMarkerObjectNameInfoEXT* pNameInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ VkDebugMarkerObjectNameInfoEXT local_name_info;
+ memcpy(&local_name_info, pNameInfo, sizeof(VkDebugMarkerObjectNameInfoEXT));
+ // If this is a physical device, we have to replace it with the proper one for the next call.
+ if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {
+ struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pNameInfo->object;
+ local_name_info.object = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;
+ }
+ return disp->DebugMarkerSetObjectNameEXT(device, &local_name_info);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectNameEXT(
+ VkDevice device,
+ const VkDebugMarkerObjectNameInfoEXT* pNameInfo) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.DebugMarkerSetObjectNameEXT) {
+ VkDebugMarkerObjectNameInfoEXT local_name_info;
+ memcpy(&local_name_info, pNameInfo, sizeof(VkDebugMarkerObjectNameInfoEXT));
+ // If this is a physical device, we have to replace it with the proper one for the next call.
+ if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pNameInfo->object;
+ local_name_info.object = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;
+ // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.
+ } else if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {
+ if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->object;
+ if (NULL != icd_surface->real_icd_surfaces) {
+ local_name_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];
+ }
+ }
+ }
+ return icd_term->dispatch.DebugMarkerSetObjectNameEXT(device, &local_name_info);
+ } else {
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdDebugMarkerBeginEXT(
+ VkCommandBuffer commandBuffer,
+ const VkDebugMarkerMarkerInfoEXT* pMarkerInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDebugMarkerBeginEXT(commandBuffer, pMarkerInfo);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdDebugMarkerEndEXT(
+ VkCommandBuffer commandBuffer) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDebugMarkerEndEXT(commandBuffer);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdDebugMarkerInsertEXT(
+ VkCommandBuffer commandBuffer,
+ const VkDebugMarkerMarkerInfoEXT* pMarkerInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDebugMarkerInsertEXT(commandBuffer, pMarkerInfo);
+}
+
+
+// ---- VK_EXT_transform_feedback extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdBindTransformFeedbackBuffersEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstBinding,
+ uint32_t bindingCount,
+ const VkBuffer* pBuffers,
+ const VkDeviceSize* pOffsets,
+ const VkDeviceSize* pSizes) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdBindTransformFeedbackBuffersEXT(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets, pSizes);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdBeginTransformFeedbackEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstCounterBuffer,
+ uint32_t counterBufferCount,
+ const VkBuffer* pCounterBuffers,
+ const VkDeviceSize* pCounterBufferOffsets) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdBeginTransformFeedbackEXT(commandBuffer, firstCounterBuffer, counterBufferCount, pCounterBuffers, pCounterBufferOffsets);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdEndTransformFeedbackEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstCounterBuffer,
+ uint32_t counterBufferCount,
+ const VkBuffer* pCounterBuffers,
+ const VkDeviceSize* pCounterBufferOffsets) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdEndTransformFeedbackEXT(commandBuffer, firstCounterBuffer, counterBufferCount, pCounterBuffers, pCounterBufferOffsets);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdBeginQueryIndexedEXT(
+ VkCommandBuffer commandBuffer,
+ VkQueryPool queryPool,
+ uint32_t query,
+ VkQueryControlFlags flags,
+ uint32_t index) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdBeginQueryIndexedEXT(commandBuffer, queryPool, query, flags, index);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdEndQueryIndexedEXT(
+ VkCommandBuffer commandBuffer,
+ VkQueryPool queryPool,
+ uint32_t query,
+ uint32_t index) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdEndQueryIndexedEXT(commandBuffer, queryPool, query, index);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdDrawIndirectByteCountEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t instanceCount,
+ uint32_t firstInstance,
+ VkBuffer counterBuffer,
+ VkDeviceSize counterBufferOffset,
+ uint32_t counterOffset,
+ uint32_t vertexStride) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer, counterBufferOffset, counterOffset, vertexStride);
+}
+
+
+// ---- VK_NVX_image_view_handle extension trampoline/terminators
+
+VKAPI_ATTR uint32_t VKAPI_CALL GetImageViewHandleNVX(
+ VkDevice device,
+ const VkImageViewHandleInfoNVX* pInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetImageViewHandleNVX(device, pInfo);
+}
+
+
+// ---- VK_AMD_draw_indirect_count extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdDrawIndirectCountAMD(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawIndirectCountAMD(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirectCountAMD(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawIndexedIndirectCountAMD(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
+}
+
+
+// ---- VK_AMD_shader_info extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetShaderInfoAMD(
+ VkDevice device,
+ VkPipeline pipeline,
+ VkShaderStageFlagBits shaderStage,
+ VkShaderInfoTypeAMD infoType,
+ size_t* pInfoSize,
+ void* pInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetShaderInfoAMD(device, pipeline, shaderStage, infoType, pInfoSize, pInfo);
+}
+
+
+// ---- VK_GGP_stream_descriptor_surface extension trampoline/terminators
+
+#ifdef VK_USE_PLATFORM_GGP
+VKAPI_ATTR VkResult VKAPI_CALL CreateStreamDescriptorSurfaceGGP(
+ VkInstance instance,
+ const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface) {
+#error("Not implemented. Likely needs to be manually generated!");
+ return disp->CreateStreamDescriptorSurfaceGGP(instance, pCreateInfo, pAllocator, pSurface);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateStreamDescriptorSurfaceGGP(
+ VkInstance instance,
+ const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface) {
+#error("Not implemented. Likely needs to be manually generated!");
+}
+
+#endif // VK_USE_PLATFORM_GGP
+
+// ---- VK_NV_external_memory_win32 extension trampoline/terminators
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL GetMemoryWin32HandleNV(
+ VkDevice device,
+ VkDeviceMemory memory,
+ VkExternalMemoryHandleTypeFlagsNV handleType,
+ HANDLE* pHandle) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetMemoryWin32HandleNV(device, memory, handleType, pHandle);
+}
+
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+// ---- VK_NN_vi_surface extension trampoline/terminators
+
+#ifdef VK_USE_PLATFORM_VI_NN
+VKAPI_ATTR VkResult VKAPI_CALL CreateViSurfaceNN(
+ VkInstance instance,
+ const VkViSurfaceCreateInfoNN* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface) {
+#error("Not implemented. Likely needs to be manually generated!");
+ return disp->CreateViSurfaceNN(instance, pCreateInfo, pAllocator, pSurface);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateViSurfaceNN(
+ VkInstance instance,
+ const VkViSurfaceCreateInfoNN* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface) {
+#error("Not implemented. Likely needs to be manually generated!");
+}
+
+#endif // VK_USE_PLATFORM_VI_NN
+
+// ---- VK_EXT_conditional_rendering extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdBeginConditionalRenderingEXT(
+ VkCommandBuffer commandBuffer,
+ const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdBeginConditionalRenderingEXT(commandBuffer, pConditionalRenderingBegin);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdEndConditionalRenderingEXT(
+ VkCommandBuffer commandBuffer) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdEndConditionalRenderingEXT(commandBuffer);
+}
+
+
+// ---- VK_NVX_device_generated_commands extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdProcessCommandsNVX(
+ VkCommandBuffer commandBuffer,
+ const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdProcessCommandsNVX(commandBuffer, pProcessCommandsInfo);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdReserveSpaceForCommandsNVX(
+ VkCommandBuffer commandBuffer,
+ const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdReserveSpaceForCommandsNVX(commandBuffer, pReserveSpaceInfo);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateIndirectCommandsLayoutNVX(
+ VkDevice device,
+ const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateIndirectCommandsLayoutNVX(device, pCreateInfo, pAllocator, pIndirectCommandsLayout);
+}
+
+VKAPI_ATTR void VKAPI_CALL DestroyIndirectCommandsLayoutNVX(
+ VkDevice device,
+ VkIndirectCommandsLayoutNVX indirectCommandsLayout,
+ const VkAllocationCallbacks* pAllocator) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->DestroyIndirectCommandsLayoutNVX(device, indirectCommandsLayout, pAllocator);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateObjectTableNVX(
+ VkDevice device,
+ const VkObjectTableCreateInfoNVX* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkObjectTableNVX* pObjectTable) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateObjectTableNVX(device, pCreateInfo, pAllocator, pObjectTable);
+}
+
+VKAPI_ATTR void VKAPI_CALL DestroyObjectTableNVX(
+ VkDevice device,
+ VkObjectTableNVX objectTable,
+ const VkAllocationCallbacks* pAllocator) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->DestroyObjectTableNVX(device, objectTable, pAllocator);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL RegisterObjectsNVX(
+ VkDevice device,
+ VkObjectTableNVX objectTable,
+ uint32_t objectCount,
+ const VkObjectTableEntryNVX* const* ppObjectTableEntries,
+ const uint32_t* pObjectIndices) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->RegisterObjectsNVX(device, objectTable, objectCount, ppObjectTableEntries, pObjectIndices);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL UnregisterObjectsNVX(
+ VkDevice device,
+ VkObjectTableNVX objectTable,
+ uint32_t objectCount,
+ const VkObjectEntryTypeNVX* pObjectEntryTypes,
+ const uint32_t* pObjectIndices) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->UnregisterObjectsNVX(device, objectTable, objectCount, pObjectEntryTypes, pObjectIndices);
+}
+
+VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceGeneratedCommandsPropertiesNVX(
+ VkPhysicalDevice physicalDevice,
+ VkDeviceGeneratedCommandsFeaturesNVX* pFeatures,
+ VkDeviceGeneratedCommandsLimitsNVX* pLimits) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceGeneratedCommandsPropertiesNVX(unwrapped_phys_dev, pFeatures, pLimits);
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceGeneratedCommandsPropertiesNVX(
+ VkPhysicalDevice physicalDevice,
+ VkDeviceGeneratedCommandsFeaturesNVX* pFeatures,
+ VkDeviceGeneratedCommandsLimitsNVX* pLimits) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceGeneratedCommandsPropertiesNVX) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceGeneratedCommandsPropertiesNVX");
+ }
+ icd_term->dispatch.GetPhysicalDeviceGeneratedCommandsPropertiesNVX(phys_dev_term->phys_dev, pFeatures, pLimits);
+}
+
+
+// ---- VK_NV_clip_space_w_scaling extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdSetViewportWScalingNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkViewportWScalingNV* pViewportWScalings) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdSetViewportWScalingNV(commandBuffer, firstViewport, viewportCount, pViewportWScalings);
+}
+
+
+// ---- VK_EXT_display_control extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL DisplayPowerControlEXT(
+ VkDevice device,
+ VkDisplayKHR display,
+ const VkDisplayPowerInfoEXT* pDisplayPowerInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->DisplayPowerControlEXT(device, display, pDisplayPowerInfo);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL RegisterDeviceEventEXT(
+ VkDevice device,
+ const VkDeviceEventInfoEXT* pDeviceEventInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->RegisterDeviceEventEXT(device, pDeviceEventInfo, pAllocator, pFence);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL RegisterDisplayEventEXT(
+ VkDevice device,
+ VkDisplayKHR display,
+ const VkDisplayEventInfoEXT* pDisplayEventInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->RegisterDisplayEventEXT(device, display, pDisplayEventInfo, pAllocator, pFence);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetSwapchainCounterEXT(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ VkSurfaceCounterFlagBitsEXT counter,
+ uint64_t* pCounterValue) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetSwapchainCounterEXT(device, swapchain, counter, pCounterValue);
+}
+
+
+// ---- VK_GOOGLE_display_timing extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetRefreshCycleDurationGOOGLE(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetRefreshCycleDurationGOOGLE(device, swapchain, pDisplayTimingProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPastPresentationTimingGOOGLE(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ uint32_t* pPresentationTimingCount,
+ VkPastPresentationTimingGOOGLE* pPresentationTimings) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetPastPresentationTimingGOOGLE(device, swapchain, pPresentationTimingCount, pPresentationTimings);
+}
+
+
+// ---- VK_EXT_discard_rectangles extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdSetDiscardRectangleEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstDiscardRectangle,
+ uint32_t discardRectangleCount,
+ const VkRect2D* pDiscardRectangles) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdSetDiscardRectangleEXT(commandBuffer, firstDiscardRectangle, discardRectangleCount, pDiscardRectangles);
+}
+
+
+// ---- VK_EXT_hdr_metadata extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL SetHdrMetadataEXT(
+ VkDevice device,
+ uint32_t swapchainCount,
+ const VkSwapchainKHR* pSwapchains,
+ const VkHdrMetadataEXT* pMetadata) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->SetHdrMetadataEXT(device, swapchainCount, pSwapchains, pMetadata);
+}
+
+
+// ---- VK_EXT_debug_utils extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectNameEXT(
+ VkDevice device,
+ const VkDebugUtilsObjectNameInfoEXT* pNameInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ VkDebugUtilsObjectNameInfoEXT local_name_info;
+ memcpy(&local_name_info, pNameInfo, sizeof(VkDebugUtilsObjectNameInfoEXT));
+ // If this is a physical device, we have to replace it with the proper one for the next call.
+ if (pNameInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {
+ struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pNameInfo->objectHandle;
+ local_name_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;
+ }
+ if (disp->SetDebugUtilsObjectNameEXT != NULL) {
+ return disp->SetDebugUtilsObjectNameEXT(device, &local_name_info);
+ } else {
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_SetDebugUtilsObjectNameEXT(
+ VkDevice device,
+ const VkDebugUtilsObjectNameInfoEXT* pNameInfo) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.SetDebugUtilsObjectNameEXT) {
+ VkDebugUtilsObjectNameInfoEXT local_name_info;
+ memcpy(&local_name_info, pNameInfo, sizeof(VkDebugUtilsObjectNameInfoEXT));
+ // If this is a physical device, we have to replace it with the proper one for the next call.
+ if (pNameInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pNameInfo->objectHandle;
+ local_name_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;
+ // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.
+ } else if (pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
+ if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->objectHandle;
+ if (NULL != icd_surface->real_icd_surfaces) {
+ local_name_info.objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];
+ }
+ }
+ }
+ return icd_term->dispatch.SetDebugUtilsObjectNameEXT(device, &local_name_info);
+ } else {
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectTagEXT(
+ VkDevice device,
+ const VkDebugUtilsObjectTagInfoEXT* pTagInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ VkDebugUtilsObjectTagInfoEXT local_tag_info;
+ memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugUtilsObjectTagInfoEXT));
+ // If this is a physical device, we have to replace it with the proper one for the next call.
+ if (pTagInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {
+ struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pTagInfo->objectHandle;
+ local_tag_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;
+ }
+ if (disp->SetDebugUtilsObjectTagEXT != NULL) {
+ return disp->SetDebugUtilsObjectTagEXT(device, &local_tag_info);
+ } else {
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_SetDebugUtilsObjectTagEXT(
+ VkDevice device,
+ const VkDebugUtilsObjectTagInfoEXT* pTagInfo) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.SetDebugUtilsObjectTagEXT) {
+ VkDebugUtilsObjectTagInfoEXT local_tag_info;
+ memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugUtilsObjectTagInfoEXT));
+ // If this is a physical device, we have to replace it with the proper one for the next call.
+ if (pTagInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pTagInfo->objectHandle;
+ local_tag_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;
+ // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.
+ } else if (pTagInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
+ if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->objectHandle;
+ if (NULL != icd_surface->real_icd_surfaces) {
+ local_tag_info.objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];
+ }
+ }
+ }
+ return icd_term->dispatch.SetDebugUtilsObjectTagEXT(device, &local_tag_info);
+ } else {
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL QueueBeginDebugUtilsLabelEXT(
+ VkQueue queue,
+ const VkDebugUtilsLabelEXT* pLabelInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(queue);
+ if (disp->QueueBeginDebugUtilsLabelEXT != NULL) {
+ disp->QueueBeginDebugUtilsLabelEXT(queue, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_QueueBeginDebugUtilsLabelEXT(
+ VkQueue queue,
+ const VkDebugUtilsLabelEXT* pLabelInfo) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(queue, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.QueueBeginDebugUtilsLabelEXT) {
+ icd_term->dispatch.QueueBeginDebugUtilsLabelEXT(queue, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL QueueEndDebugUtilsLabelEXT(
+ VkQueue queue) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(queue);
+ if (disp->QueueEndDebugUtilsLabelEXT != NULL) {
+ disp->QueueEndDebugUtilsLabelEXT(queue);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_QueueEndDebugUtilsLabelEXT(
+ VkQueue queue) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(queue, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.QueueEndDebugUtilsLabelEXT) {
+ icd_term->dispatch.QueueEndDebugUtilsLabelEXT(queue);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL QueueInsertDebugUtilsLabelEXT(
+ VkQueue queue,
+ const VkDebugUtilsLabelEXT* pLabelInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(queue);
+ if (disp->QueueInsertDebugUtilsLabelEXT != NULL) {
+ disp->QueueInsertDebugUtilsLabelEXT(queue, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_QueueInsertDebugUtilsLabelEXT(
+ VkQueue queue,
+ const VkDebugUtilsLabelEXT* pLabelInfo) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(queue, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.QueueInsertDebugUtilsLabelEXT) {
+ icd_term->dispatch.QueueInsertDebugUtilsLabelEXT(queue, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdBeginDebugUtilsLabelEXT(
+ VkCommandBuffer commandBuffer,
+ const VkDebugUtilsLabelEXT* pLabelInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ if (disp->CmdBeginDebugUtilsLabelEXT != NULL) {
+ disp->CmdBeginDebugUtilsLabelEXT(commandBuffer, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_CmdBeginDebugUtilsLabelEXT(
+ VkCommandBuffer commandBuffer,
+ const VkDebugUtilsLabelEXT* pLabelInfo) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(commandBuffer, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.CmdBeginDebugUtilsLabelEXT) {
+ icd_term->dispatch.CmdBeginDebugUtilsLabelEXT(commandBuffer, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdEndDebugUtilsLabelEXT(
+ VkCommandBuffer commandBuffer) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ if (disp->CmdEndDebugUtilsLabelEXT != NULL) {
+ disp->CmdEndDebugUtilsLabelEXT(commandBuffer);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_CmdEndDebugUtilsLabelEXT(
+ VkCommandBuffer commandBuffer) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(commandBuffer, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.CmdEndDebugUtilsLabelEXT) {
+ icd_term->dispatch.CmdEndDebugUtilsLabelEXT(commandBuffer);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdInsertDebugUtilsLabelEXT(
+ VkCommandBuffer commandBuffer,
+ const VkDebugUtilsLabelEXT* pLabelInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ if (disp->CmdInsertDebugUtilsLabelEXT != NULL) {
+ disp->CmdInsertDebugUtilsLabelEXT(commandBuffer, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_CmdInsertDebugUtilsLabelEXT(
+ VkCommandBuffer commandBuffer,
+ const VkDebugUtilsLabelEXT* pLabelInfo) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(commandBuffer, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.CmdInsertDebugUtilsLabelEXT) {
+ icd_term->dispatch.CmdInsertDebugUtilsLabelEXT(commandBuffer, pLabelInfo);
+ }
+}
+
+
+// ---- VK_ANDROID_external_memory_android_hardware_buffer extension trampoline/terminators
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+VKAPI_ATTR VkResult VKAPI_CALL GetAndroidHardwareBufferPropertiesANDROID(
+ VkDevice device,
+ const struct AHardwareBuffer* buffer,
+ VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetAndroidHardwareBufferPropertiesANDROID(device, buffer, pProperties);
+}
+
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+VKAPI_ATTR VkResult VKAPI_CALL GetMemoryAndroidHardwareBufferANDROID(
+ VkDevice device,
+ const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo,
+ struct AHardwareBuffer** pBuffer) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetMemoryAndroidHardwareBufferANDROID(device, pInfo, pBuffer);
+}
+
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+// ---- VK_EXT_sample_locations extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdSetSampleLocationsEXT(
+ VkCommandBuffer commandBuffer,
+ const VkSampleLocationsInfoEXT* pSampleLocationsInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdSetSampleLocationsEXT(commandBuffer, pSampleLocationsInfo);
+}
+
+VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceMultisamplePropertiesEXT(
+ VkPhysicalDevice physicalDevice,
+ VkSampleCountFlagBits samples,
+ VkMultisamplePropertiesEXT* pMultisampleProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceMultisamplePropertiesEXT(unwrapped_phys_dev, samples, pMultisampleProperties);
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMultisamplePropertiesEXT(
+ VkPhysicalDevice physicalDevice,
+ VkSampleCountFlagBits samples,
+ VkMultisamplePropertiesEXT* pMultisampleProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceMultisamplePropertiesEXT) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceMultisamplePropertiesEXT");
+ }
+ icd_term->dispatch.GetPhysicalDeviceMultisamplePropertiesEXT(phys_dev_term->phys_dev, samples, pMultisampleProperties);
+}
+
+
+// ---- VK_EXT_image_drm_format_modifier extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetImageDrmFormatModifierPropertiesEXT(
+ VkDevice device,
+ VkImage image,
+ VkImageDrmFormatModifierPropertiesEXT* pProperties) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetImageDrmFormatModifierPropertiesEXT(device, image, pProperties);
+}
+
+
+// ---- VK_EXT_validation_cache extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(
+ VkDevice device,
+ const VkValidationCacheCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkValidationCacheEXT* pValidationCache) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateValidationCacheEXT(device, pCreateInfo, pAllocator, pValidationCache);
+}
+
+VKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(
+ VkDevice device,
+ VkValidationCacheEXT validationCache,
+ const VkAllocationCallbacks* pAllocator) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->DestroyValidationCacheEXT(device, validationCache, pAllocator);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(
+ VkDevice device,
+ VkValidationCacheEXT dstCache,
+ uint32_t srcCacheCount,
+ const VkValidationCacheEXT* pSrcCaches) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->MergeValidationCachesEXT(device, dstCache, srcCacheCount, pSrcCaches);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(
+ VkDevice device,
+ VkValidationCacheEXT validationCache,
+ size_t* pDataSize,
+ void* pData) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetValidationCacheDataEXT(device, validationCache, pDataSize, pData);
+}
+
+
+// ---- VK_NV_shading_rate_image extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdBindShadingRateImageNV(
+ VkCommandBuffer commandBuffer,
+ VkImageView imageView,
+ VkImageLayout imageLayout) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdBindShadingRateImageNV(commandBuffer, imageView, imageLayout);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdSetViewportShadingRatePaletteNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkShadingRatePaletteNV* pShadingRatePalettes) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdSetViewportShadingRatePaletteNV(commandBuffer, firstViewport, viewportCount, pShadingRatePalettes);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdSetCoarseSampleOrderNV(
+ VkCommandBuffer commandBuffer,
+ VkCoarseSampleOrderTypeNV sampleOrderType,
+ uint32_t customSampleOrderCount,
+ const VkCoarseSampleOrderCustomNV* pCustomSampleOrders) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdSetCoarseSampleOrderNV(commandBuffer, sampleOrderType, customSampleOrderCount, pCustomSampleOrders);
+}
+
+
+// ---- VK_NV_ray_tracing extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateAccelerationStructureNV(
+ VkDevice device,
+ const VkAccelerationStructureCreateInfoNV* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkAccelerationStructureNV* pAccelerationStructure) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateAccelerationStructureNV(device, pCreateInfo, pAllocator, pAccelerationStructure);
+}
+
+VKAPI_ATTR void VKAPI_CALL DestroyAccelerationStructureNV(
+ VkDevice device,
+ VkAccelerationStructureNV accelerationStructure,
+ const VkAllocationCallbacks* pAllocator) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->DestroyAccelerationStructureNV(device, accelerationStructure, pAllocator);
+}
+
+VKAPI_ATTR void VKAPI_CALL GetAccelerationStructureMemoryRequirementsNV(
+ VkDevice device,
+ const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo,
+ VkMemoryRequirements2KHR* pMemoryRequirements) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->GetAccelerationStructureMemoryRequirementsNV(device, pInfo, pMemoryRequirements);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL BindAccelerationStructureMemoryNV(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindAccelerationStructureMemoryInfoNV* pBindInfos) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->BindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdBuildAccelerationStructureNV(
+ VkCommandBuffer commandBuffer,
+ const VkAccelerationStructureInfoNV* pInfo,
+ VkBuffer instanceData,
+ VkDeviceSize instanceOffset,
+ VkBool32 update,
+ VkAccelerationStructureNV dst,
+ VkAccelerationStructureNV src,
+ VkBuffer scratch,
+ VkDeviceSize scratchOffset) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdBuildAccelerationStructureNV(commandBuffer, pInfo, instanceData, instanceOffset, update, dst, src, scratch, scratchOffset);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdCopyAccelerationStructureNV(
+ VkCommandBuffer commandBuffer,
+ VkAccelerationStructureNV dst,
+ VkAccelerationStructureNV src,
+ VkCopyAccelerationStructureModeNV mode) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdCopyAccelerationStructureNV(commandBuffer, dst, src, mode);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdTraceRaysNV(
+ VkCommandBuffer commandBuffer,
+ VkBuffer raygenShaderBindingTableBuffer,
+ VkDeviceSize raygenShaderBindingOffset,
+ VkBuffer missShaderBindingTableBuffer,
+ VkDeviceSize missShaderBindingOffset,
+ VkDeviceSize missShaderBindingStride,
+ VkBuffer hitShaderBindingTableBuffer,
+ VkDeviceSize hitShaderBindingOffset,
+ VkDeviceSize hitShaderBindingStride,
+ VkBuffer callableShaderBindingTableBuffer,
+ VkDeviceSize callableShaderBindingOffset,
+ VkDeviceSize callableShaderBindingStride,
+ uint32_t width,
+ uint32_t height,
+ uint32_t depth) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdTraceRaysNV(commandBuffer, raygenShaderBindingTableBuffer, raygenShaderBindingOffset, missShaderBindingTableBuffer, missShaderBindingOffset, missShaderBindingStride, hitShaderBindingTableBuffer, hitShaderBindingOffset, hitShaderBindingStride, callableShaderBindingTableBuffer, callableShaderBindingOffset, callableShaderBindingStride, width, height, depth);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateRayTracingPipelinesNV(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ uint32_t createInfoCount,
+ const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipeline* pPipelines) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetRayTracingShaderGroupHandlesNV(
+ VkDevice device,
+ VkPipeline pipeline,
+ uint32_t firstGroup,
+ uint32_t groupCount,
+ size_t dataSize,
+ void* pData) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetRayTracingShaderGroupHandlesNV(device, pipeline, firstGroup, groupCount, dataSize, pData);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetAccelerationStructureHandleNV(
+ VkDevice device,
+ VkAccelerationStructureNV accelerationStructure,
+ size_t dataSize,
+ void* pData) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetAccelerationStructureHandleNV(device, accelerationStructure, dataSize, pData);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdWriteAccelerationStructuresPropertiesNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t accelerationStructureCount,
+ const VkAccelerationStructureNV* pAccelerationStructures,
+ VkQueryType queryType,
+ VkQueryPool queryPool,
+ uint32_t firstQuery) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdWriteAccelerationStructuresPropertiesNV(commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL CompileDeferredNV(
+ VkDevice device,
+ VkPipeline pipeline,
+ uint32_t shader) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->CompileDeferredNV(device, pipeline, shader);
+}
+
+
+// ---- VK_EXT_external_memory_host extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetMemoryHostPointerPropertiesEXT(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBits handleType,
+ const void* pHostPointer,
+ VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetMemoryHostPointerPropertiesEXT(device, handleType, pHostPointer, pMemoryHostPointerProperties);
+}
+
+
+// ---- VK_AMD_buffer_marker extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdWriteBufferMarkerAMD(
+ VkCommandBuffer commandBuffer,
+ VkPipelineStageFlagBits pipelineStage,
+ VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ uint32_t marker) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdWriteBufferMarkerAMD(commandBuffer, pipelineStage, dstBuffer, dstOffset, marker);
+}
+
+
+// ---- VK_EXT_calibrated_timestamps extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceCalibrateableTimeDomainsEXT(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pTimeDomainCount,
+ VkTimeDomainEXT* pTimeDomains) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceCalibrateableTimeDomainsEXT(unwrapped_phys_dev, pTimeDomainCount, pTimeDomains);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceCalibrateableTimeDomainsEXT(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pTimeDomainCount,
+ VkTimeDomainEXT* pTimeDomains) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceCalibrateableTimeDomainsEXT) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceCalibrateableTimeDomainsEXT");
+ }
+ return icd_term->dispatch.GetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev_term->phys_dev, pTimeDomainCount, pTimeDomains);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetCalibratedTimestampsEXT(
+ VkDevice device,
+ uint32_t timestampCount,
+ const VkCalibratedTimestampInfoEXT* pTimestampInfos,
+ uint64_t* pTimestamps,
+ uint64_t* pMaxDeviation) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetCalibratedTimestampsEXT(device, timestampCount, pTimestampInfos, pTimestamps, pMaxDeviation);
+}
+
+
+// ---- VK_NV_mesh_shader extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdDrawMeshTasksNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t taskCount,
+ uint32_t firstTask) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdDrawMeshTasksIndirectNV(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ uint32_t drawCount,
+ uint32_t stride) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdDrawMeshTasksIndirectCountNV(
+ VkCommandBuffer commandBuffer,
+ VkBuffer buffer,
+ VkDeviceSize offset,
+ VkBuffer countBuffer,
+ VkDeviceSize countBufferOffset,
+ uint32_t maxDrawCount,
+ uint32_t stride) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
+}
+
+
+// ---- VK_NV_scissor_exclusive extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdSetExclusiveScissorNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstExclusiveScissor,
+ uint32_t exclusiveScissorCount,
+ const VkRect2D* pExclusiveScissors) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdSetExclusiveScissorNV(commandBuffer, firstExclusiveScissor, exclusiveScissorCount, pExclusiveScissors);
+}
+
+
+// ---- VK_NV_device_diagnostic_checkpoints extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdSetCheckpointNV(
+ VkCommandBuffer commandBuffer,
+ const void* pCheckpointMarker) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdSetCheckpointNV(commandBuffer, pCheckpointMarker);
+}
+
+VKAPI_ATTR void VKAPI_CALL GetQueueCheckpointDataNV(
+ VkQueue queue,
+ uint32_t* pCheckpointDataCount,
+ VkCheckpointDataNV* pCheckpointData) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(queue);
+ disp->GetQueueCheckpointDataNV(queue, pCheckpointDataCount, pCheckpointData);
+}
+
+
+// ---- VK_INTEL_performance_query extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL InitializePerformanceApiINTEL(
+ VkDevice device,
+ const VkInitializePerformanceApiInfoINTEL* pInitializeInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->InitializePerformanceApiINTEL(device, pInitializeInfo);
+}
+
+VKAPI_ATTR void VKAPI_CALL UninitializePerformanceApiINTEL(
+ VkDevice device) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->UninitializePerformanceApiINTEL(device);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL CmdSetPerformanceMarkerINTEL(
+ VkCommandBuffer commandBuffer,
+ const VkPerformanceMarkerInfoINTEL* pMarkerInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ return disp->CmdSetPerformanceMarkerINTEL(commandBuffer, pMarkerInfo);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL CmdSetPerformanceStreamMarkerINTEL(
+ VkCommandBuffer commandBuffer,
+ const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ return disp->CmdSetPerformanceStreamMarkerINTEL(commandBuffer, pMarkerInfo);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL CmdSetPerformanceOverrideINTEL(
+ VkCommandBuffer commandBuffer,
+ const VkPerformanceOverrideInfoINTEL* pOverrideInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ return disp->CmdSetPerformanceOverrideINTEL(commandBuffer, pOverrideInfo);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL AcquirePerformanceConfigurationINTEL(
+ VkDevice device,
+ const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo,
+ VkPerformanceConfigurationINTEL* pConfiguration) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->AcquirePerformanceConfigurationINTEL(device, pAcquireInfo, pConfiguration);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL ReleasePerformanceConfigurationINTEL(
+ VkDevice device,
+ VkPerformanceConfigurationINTEL configuration) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->ReleasePerformanceConfigurationINTEL(device, configuration);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL QueueSetPerformanceConfigurationINTEL(
+ VkQueue queue,
+ VkPerformanceConfigurationINTEL configuration) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(queue);
+ return disp->QueueSetPerformanceConfigurationINTEL(queue, configuration);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPerformanceParameterINTEL(
+ VkDevice device,
+ VkPerformanceParameterTypeINTEL parameter,
+ VkPerformanceValueINTEL* pValue) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetPerformanceParameterINTEL(device, parameter, pValue);
+}
+
+
+// ---- VK_AMD_display_native_hdr extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL SetLocalDimmingAMD(
+ VkDevice device,
+ VkSwapchainKHR swapChain,
+ VkBool32 localDimmingEnable) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->SetLocalDimmingAMD(device, swapChain, localDimmingEnable);
+}
+
+
+// ---- VK_FUCHSIA_imagepipe_surface extension trampoline/terminators
+
+#ifdef VK_USE_PLATFORM_FUCHSIA
+VKAPI_ATTR VkResult VKAPI_CALL CreateImagePipeSurfaceFUCHSIA(
+ VkInstance instance,
+ const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface) {
+#error("Not implemented. Likely needs to be manually generated!");
+ return disp->CreateImagePipeSurfaceFUCHSIA(instance, pCreateInfo, pAllocator, pSurface);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateImagePipeSurfaceFUCHSIA(
+ VkInstance instance,
+ const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface) {
+#error("Not implemented. Likely needs to be manually generated!");
+}
+
+#endif // VK_USE_PLATFORM_FUCHSIA
+
+// ---- VK_EXT_buffer_device_address extension trampoline/terminators
+
+VKAPI_ATTR VkDeviceAddress VKAPI_CALL GetBufferDeviceAddressEXT(
+ VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetBufferDeviceAddressEXT(device, pInfo);
+}
+
+
+// ---- VK_NV_cooperative_matrix extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceCooperativeMatrixPropertiesNV(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkCooperativeMatrixPropertiesNV* pProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceCooperativeMatrixPropertiesNV(unwrapped_phys_dev, pPropertyCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceCooperativeMatrixPropertiesNV(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkCooperativeMatrixPropertiesNV* pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceCooperativeMatrixPropertiesNV) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceCooperativeMatrixPropertiesNV");
+ }
+ return icd_term->dispatch.GetPhysicalDeviceCooperativeMatrixPropertiesNV(phys_dev_term->phys_dev, pPropertyCount, pProperties);
+}
+
+
+// ---- VK_NV_coverage_reduction_mode extension trampoline/terminators
+
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pCombinationCount,
+ VkFramebufferMixedSamplesCombinationNV* pCombinations) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(unwrapped_phys_dev, pCombinationCount, pCombinations);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pCombinationCount,
+ VkFramebufferMixedSamplesCombinationNV* pCombinations) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV");
+ }
+ return icd_term->dispatch.GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(phys_dev_term->phys_dev, pCombinationCount, pCombinations);
+}
+
+
+// ---- VK_EXT_full_screen_exclusive extension trampoline/terminators
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL AcquireFullScreenExclusiveModeEXT(
+ VkDevice device,
+ VkSwapchainKHR swapchain) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->AcquireFullScreenExclusiveModeEXT(device, swapchain);
+}
+
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL ReleaseFullScreenExclusiveModeEXT(
+ VkDevice device,
+ VkSwapchainKHR swapchain) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->ReleaseFullScreenExclusiveModeEXT(device, swapchain);
+}
+
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+// ---- VK_EXT_line_rasterization extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL CmdSetLineStippleEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t lineStippleFactor,
+ uint16_t lineStipplePattern) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdSetLineStippleEXT(commandBuffer, lineStippleFactor, lineStipplePattern);
+}
+
+
+// ---- VK_EXT_host_query_reset extension trampoline/terminators
+
+VKAPI_ATTR void VKAPI_CALL ResetQueryPoolEXT(
+ VkDevice device,
+ VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->ResetQueryPoolEXT(device, queryPool, firstQuery, queryCount);
+}
+
+// GPA helpers for extensions
+bool extension_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
+ *addr = NULL;
+
+
+ // ---- VK_KHR_get_physical_device_properties2 extension commands
+ if (!strcmp("vkGetPhysicalDeviceFeatures2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceFeatures2
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceProperties2
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceFormatProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceFormatProperties2
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceImageFormatProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceImageFormatProperties2
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceQueueFamilyProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceQueueFamilyProperties2
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceMemoryProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceMemoryProperties2
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceSparseImageFormatProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceSparseImageFormatProperties2
+ : NULL;
+ return true;
+ }
+
+ // ---- VK_KHR_device_group extension commands
+ if (!strcmp("vkGetDeviceGroupPeerMemoryFeaturesKHR", name)) {
+ *addr = (void *)GetDeviceGroupPeerMemoryFeaturesKHR;
+ return true;
+ }
+ if (!strcmp("vkCmdSetDeviceMaskKHR", name)) {
+ *addr = (void *)CmdSetDeviceMaskKHR;
+ return true;
+ }
+ if (!strcmp("vkCmdDispatchBaseKHR", name)) {
+ *addr = (void *)CmdDispatchBaseKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_maintenance1 extension commands
+ if (!strcmp("vkTrimCommandPoolKHR", name)) {
+ *addr = (void *)TrimCommandPoolKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_device_group_creation extension commands
+ if (!strcmp("vkEnumeratePhysicalDeviceGroupsKHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_device_group_creation == 1)
+ ? (void *)vkEnumeratePhysicalDeviceGroups
+ : NULL;
+ return true;
+ }
+
+ // ---- VK_KHR_external_memory_capabilities extension commands
+ if (!strcmp("vkGetPhysicalDeviceExternalBufferPropertiesKHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_external_memory_capabilities == 1)
+ ? (void *)vkGetPhysicalDeviceExternalBufferProperties
+ : NULL;
+ return true;
+ }
+
+ // ---- VK_KHR_external_memory_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkGetMemoryWin32HandleKHR", name)) {
+ *addr = (void *)GetMemoryWin32HandleKHR;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkGetMemoryWin32HandlePropertiesKHR", name)) {
+ *addr = (void *)GetMemoryWin32HandlePropertiesKHR;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_memory_fd extension commands
+ if (!strcmp("vkGetMemoryFdKHR", name)) {
+ *addr = (void *)GetMemoryFdKHR;
+ return true;
+ }
+ if (!strcmp("vkGetMemoryFdPropertiesKHR", name)) {
+ *addr = (void *)GetMemoryFdPropertiesKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_external_semaphore_capabilities extension commands
+ if (!strcmp("vkGetPhysicalDeviceExternalSemaphorePropertiesKHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_external_semaphore_capabilities == 1)
+ ? (void *)vkGetPhysicalDeviceExternalSemaphoreProperties
+ : NULL;
+ return true;
+ }
+
+ // ---- VK_KHR_external_semaphore_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkImportSemaphoreWin32HandleKHR", name)) {
+ *addr = (void *)ImportSemaphoreWin32HandleKHR;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkGetSemaphoreWin32HandleKHR", name)) {
+ *addr = (void *)GetSemaphoreWin32HandleKHR;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_semaphore_fd extension commands
+ if (!strcmp("vkImportSemaphoreFdKHR", name)) {
+ *addr = (void *)ImportSemaphoreFdKHR;
+ return true;
+ }
+ if (!strcmp("vkGetSemaphoreFdKHR", name)) {
+ *addr = (void *)GetSemaphoreFdKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_push_descriptor extension commands
+ if (!strcmp("vkCmdPushDescriptorSetKHR", name)) {
+ *addr = (void *)CmdPushDescriptorSetKHR;
+ return true;
+ }
+ if (!strcmp("vkCmdPushDescriptorSetWithTemplateKHR", name)) {
+ *addr = (void *)CmdPushDescriptorSetWithTemplateKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_descriptor_update_template extension commands
+ if (!strcmp("vkCreateDescriptorUpdateTemplateKHR", name)) {
+ *addr = (void *)CreateDescriptorUpdateTemplateKHR;
+ return true;
+ }
+ if (!strcmp("vkDestroyDescriptorUpdateTemplateKHR", name)) {
+ *addr = (void *)DestroyDescriptorUpdateTemplateKHR;
+ return true;
+ }
+ if (!strcmp("vkUpdateDescriptorSetWithTemplateKHR", name)) {
+ *addr = (void *)UpdateDescriptorSetWithTemplateKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_create_renderpass2 extension commands
+ if (!strcmp("vkCreateRenderPass2KHR", name)) {
+ *addr = (void *)CreateRenderPass2KHR;
+ return true;
+ }
+ if (!strcmp("vkCmdBeginRenderPass2KHR", name)) {
+ *addr = (void *)CmdBeginRenderPass2KHR;
+ return true;
+ }
+ if (!strcmp("vkCmdNextSubpass2KHR", name)) {
+ *addr = (void *)CmdNextSubpass2KHR;
+ return true;
+ }
+ if (!strcmp("vkCmdEndRenderPass2KHR", name)) {
+ *addr = (void *)CmdEndRenderPass2KHR;
+ return true;
+ }
+
+ // ---- VK_KHR_shared_presentable_image extension commands
+ if (!strcmp("vkGetSwapchainStatusKHR", name)) {
+ *addr = (void *)GetSwapchainStatusKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_external_fence_capabilities extension commands
+ if (!strcmp("vkGetPhysicalDeviceExternalFencePropertiesKHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_external_fence_capabilities == 1)
+ ? (void *)vkGetPhysicalDeviceExternalFenceProperties
+ : NULL;
+ return true;
+ }
+
+ // ---- VK_KHR_external_fence_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkImportFenceWin32HandleKHR", name)) {
+ *addr = (void *)ImportFenceWin32HandleKHR;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkGetFenceWin32HandleKHR", name)) {
+ *addr = (void *)GetFenceWin32HandleKHR;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_external_fence_fd extension commands
+ if (!strcmp("vkImportFenceFdKHR", name)) {
+ *addr = (void *)ImportFenceFdKHR;
+ return true;
+ }
+ if (!strcmp("vkGetFenceFdKHR", name)) {
+ *addr = (void *)GetFenceFdKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_performance_query extension commands
+ if (!strcmp("vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR", name)) {
+ *addr = (void *)EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR", name)) {
+ *addr = (void *)GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR;
+ return true;
+ }
+ if (!strcmp("vkAcquireProfilingLockKHR", name)) {
+ *addr = (void *)AcquireProfilingLockKHR;
+ return true;
+ }
+ if (!strcmp("vkReleaseProfilingLockKHR", name)) {
+ *addr = (void *)ReleaseProfilingLockKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_get_surface_capabilities2 extension commands
+ if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilities2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_get_surface_capabilities2 == 1)
+ ? (void *)GetPhysicalDeviceSurfaceCapabilities2KHR
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceSurfaceFormats2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.khr_get_surface_capabilities2 == 1)
+ ? (void *)GetPhysicalDeviceSurfaceFormats2KHR
+ : NULL;
+ return true;
+ }
+
+ // ---- VK_KHR_get_memory_requirements2 extension commands
+ if (!strcmp("vkGetImageMemoryRequirements2KHR", name)) {
+ *addr = (void *)GetImageMemoryRequirements2KHR;
+ return true;
+ }
+ if (!strcmp("vkGetBufferMemoryRequirements2KHR", name)) {
+ *addr = (void *)GetBufferMemoryRequirements2KHR;
+ return true;
+ }
+ if (!strcmp("vkGetImageSparseMemoryRequirements2KHR", name)) {
+ *addr = (void *)GetImageSparseMemoryRequirements2KHR;
+ return true;
+ }
+
+ // ---- VK_KHR_sampler_ycbcr_conversion extension commands
+ if (!strcmp("vkCreateSamplerYcbcrConversionKHR", name)) {
+ *addr = (void *)CreateSamplerYcbcrConversionKHR;
+ return true;
+ }
+ if (!strcmp("vkDestroySamplerYcbcrConversionKHR", name)) {
+ *addr = (void *)DestroySamplerYcbcrConversionKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_bind_memory2 extension commands
+ if (!strcmp("vkBindBufferMemory2KHR", name)) {
+ *addr = (void *)BindBufferMemory2KHR;
+ return true;
+ }
+ if (!strcmp("vkBindImageMemory2KHR", name)) {
+ *addr = (void *)BindImageMemory2KHR;
+ return true;
+ }
+
+ // ---- VK_KHR_maintenance3 extension commands
+ if (!strcmp("vkGetDescriptorSetLayoutSupportKHR", name)) {
+ *addr = (void *)GetDescriptorSetLayoutSupportKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_draw_indirect_count extension commands
+ if (!strcmp("vkCmdDrawIndirectCountKHR", name)) {
+ *addr = (void *)CmdDrawIndirectCountKHR;
+ return true;
+ }
+ if (!strcmp("vkCmdDrawIndexedIndirectCountKHR", name)) {
+ *addr = (void *)CmdDrawIndexedIndirectCountKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_timeline_semaphore extension commands
+ if (!strcmp("vkGetSemaphoreCounterValueKHR", name)) {
+ *addr = (void *)GetSemaphoreCounterValueKHR;
+ return true;
+ }
+ if (!strcmp("vkWaitSemaphoresKHR", name)) {
+ *addr = (void *)WaitSemaphoresKHR;
+ return true;
+ }
+ if (!strcmp("vkSignalSemaphoreKHR", name)) {
+ *addr = (void *)SignalSemaphoreKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_buffer_device_address extension commands
+ if (!strcmp("vkGetBufferDeviceAddressKHR", name)) {
+ *addr = (void *)GetBufferDeviceAddressKHR;
+ return true;
+ }
+ if (!strcmp("vkGetBufferOpaqueCaptureAddressKHR", name)) {
+ *addr = (void *)GetBufferOpaqueCaptureAddressKHR;
+ return true;
+ }
+ if (!strcmp("vkGetDeviceMemoryOpaqueCaptureAddressKHR", name)) {
+ *addr = (void *)GetDeviceMemoryOpaqueCaptureAddressKHR;
+ return true;
+ }
+
+ // ---- VK_KHR_pipeline_executable_properties extension commands
+ if (!strcmp("vkGetPipelineExecutablePropertiesKHR", name)) {
+ *addr = (void *)GetPipelineExecutablePropertiesKHR;
+ return true;
+ }
+ if (!strcmp("vkGetPipelineExecutableStatisticsKHR", name)) {
+ *addr = (void *)GetPipelineExecutableStatisticsKHR;
+ return true;
+ }
+ if (!strcmp("vkGetPipelineExecutableInternalRepresentationsKHR", name)) {
+ *addr = (void *)GetPipelineExecutableInternalRepresentationsKHR;
+ return true;
+ }
+
+ // ---- VK_EXT_debug_marker extension commands
+ if (!strcmp("vkDebugMarkerSetObjectTagEXT", name)) {
+ *addr = (void *)DebugMarkerSetObjectTagEXT;
+ return true;
+ }
+ if (!strcmp("vkDebugMarkerSetObjectNameEXT", name)) {
+ *addr = (void *)DebugMarkerSetObjectNameEXT;
+ return true;
+ }
+ if (!strcmp("vkCmdDebugMarkerBeginEXT", name)) {
+ *addr = (void *)CmdDebugMarkerBeginEXT;
+ return true;
+ }
+ if (!strcmp("vkCmdDebugMarkerEndEXT", name)) {
+ *addr = (void *)CmdDebugMarkerEndEXT;
+ return true;
+ }
+ if (!strcmp("vkCmdDebugMarkerInsertEXT", name)) {
+ *addr = (void *)CmdDebugMarkerInsertEXT;
+ return true;
+ }
+
+ // ---- VK_EXT_transform_feedback extension commands
+ if (!strcmp("vkCmdBindTransformFeedbackBuffersEXT", name)) {
+ *addr = (void *)CmdBindTransformFeedbackBuffersEXT;
+ return true;
+ }
+ if (!strcmp("vkCmdBeginTransformFeedbackEXT", name)) {
+ *addr = (void *)CmdBeginTransformFeedbackEXT;
+ return true;
+ }
+ if (!strcmp("vkCmdEndTransformFeedbackEXT", name)) {
+ *addr = (void *)CmdEndTransformFeedbackEXT;
+ return true;
+ }
+ if (!strcmp("vkCmdBeginQueryIndexedEXT", name)) {
+ *addr = (void *)CmdBeginQueryIndexedEXT;
+ return true;
+ }
+ if (!strcmp("vkCmdEndQueryIndexedEXT", name)) {
+ *addr = (void *)CmdEndQueryIndexedEXT;
+ return true;
+ }
+ if (!strcmp("vkCmdDrawIndirectByteCountEXT", name)) {
+ *addr = (void *)CmdDrawIndirectByteCountEXT;
+ return true;
+ }
+
+ // ---- VK_NVX_image_view_handle extension commands
+ if (!strcmp("vkGetImageViewHandleNVX", name)) {
+ *addr = (void *)GetImageViewHandleNVX;
+ return true;
+ }
+
+ // ---- VK_AMD_draw_indirect_count extension commands
+ if (!strcmp("vkCmdDrawIndirectCountAMD", name)) {
+ *addr = (void *)CmdDrawIndirectCountAMD;
+ return true;
+ }
+ if (!strcmp("vkCmdDrawIndexedIndirectCountAMD", name)) {
+ *addr = (void *)CmdDrawIndexedIndirectCountAMD;
+ return true;
+ }
+
+ // ---- VK_AMD_shader_info extension commands
+ if (!strcmp("vkGetShaderInfoAMD", name)) {
+ *addr = (void *)GetShaderInfoAMD;
+ return true;
+ }
+
+ // ---- VK_GGP_stream_descriptor_surface extension commands
+#ifdef VK_USE_PLATFORM_GGP
+ if (!strcmp("vkCreateStreamDescriptorSurfaceGGP", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ggp_stream_descriptor_surface == 1)
+ ? (void *)CreateStreamDescriptorSurfaceGGP
+ : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_GGP
+
+ // ---- VK_NV_external_memory_capabilities extension commands
+ if (!strcmp("vkGetPhysicalDeviceExternalImageFormatPropertiesNV", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.nv_external_memory_capabilities == 1)
+ ? (void *)GetPhysicalDeviceExternalImageFormatPropertiesNV
+ : NULL;
+ return true;
+ }
+
+ // ---- VK_NV_external_memory_win32 extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkGetMemoryWin32HandleNV", name)) {
+ *addr = (void *)GetMemoryWin32HandleNV;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_NN_vi_surface extension commands
+#ifdef VK_USE_PLATFORM_VI_NN
+ if (!strcmp("vkCreateViSurfaceNN", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.nn_vi_surface == 1)
+ ? (void *)CreateViSurfaceNN
+ : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_VI_NN
+
+ // ---- VK_EXT_conditional_rendering extension commands
+ if (!strcmp("vkCmdBeginConditionalRenderingEXT", name)) {
+ *addr = (void *)CmdBeginConditionalRenderingEXT;
+ return true;
+ }
+ if (!strcmp("vkCmdEndConditionalRenderingEXT", name)) {
+ *addr = (void *)CmdEndConditionalRenderingEXT;
+ return true;
+ }
+
+ // ---- VK_NVX_device_generated_commands extension commands
+ if (!strcmp("vkCmdProcessCommandsNVX", name)) {
+ *addr = (void *)CmdProcessCommandsNVX;
+ return true;
+ }
+ if (!strcmp("vkCmdReserveSpaceForCommandsNVX", name)) {
+ *addr = (void *)CmdReserveSpaceForCommandsNVX;
+ return true;
+ }
+ if (!strcmp("vkCreateIndirectCommandsLayoutNVX", name)) {
+ *addr = (void *)CreateIndirectCommandsLayoutNVX;
+ return true;
+ }
+ if (!strcmp("vkDestroyIndirectCommandsLayoutNVX", name)) {
+ *addr = (void *)DestroyIndirectCommandsLayoutNVX;
+ return true;
+ }
+ if (!strcmp("vkCreateObjectTableNVX", name)) {
+ *addr = (void *)CreateObjectTableNVX;
+ return true;
+ }
+ if (!strcmp("vkDestroyObjectTableNVX", name)) {
+ *addr = (void *)DestroyObjectTableNVX;
+ return true;
+ }
+ if (!strcmp("vkRegisterObjectsNVX", name)) {
+ *addr = (void *)RegisterObjectsNVX;
+ return true;
+ }
+ if (!strcmp("vkUnregisterObjectsNVX", name)) {
+ *addr = (void *)UnregisterObjectsNVX;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX", name)) {
+ *addr = (void *)GetPhysicalDeviceGeneratedCommandsPropertiesNVX;
+ return true;
+ }
+
+ // ---- VK_NV_clip_space_w_scaling extension commands
+ if (!strcmp("vkCmdSetViewportWScalingNV", name)) {
+ *addr = (void *)CmdSetViewportWScalingNV;
+ return true;
+ }
+
+ // ---- VK_EXT_direct_mode_display extension commands
+ if (!strcmp("vkReleaseDisplayEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_direct_mode_display == 1)
+ ? (void *)ReleaseDisplayEXT
+ : NULL;
+ return true;
+ }
+
+ // ---- VK_EXT_acquire_xlib_display extension commands
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ if (!strcmp("vkAcquireXlibDisplayEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_acquire_xlib_display == 1)
+ ? (void *)AcquireXlibDisplayEXT
+ : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ if (!strcmp("vkGetRandROutputDisplayEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_acquire_xlib_display == 1)
+ ? (void *)GetRandROutputDisplayEXT
+ : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
+ // ---- VK_EXT_display_surface_counter extension commands
+ if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilities2EXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_display_surface_counter == 1)
+ ? (void *)GetPhysicalDeviceSurfaceCapabilities2EXT
+ : NULL;
+ return true;
+ }
+
+ // ---- VK_EXT_display_control extension commands
+ if (!strcmp("vkDisplayPowerControlEXT", name)) {
+ *addr = (void *)DisplayPowerControlEXT;
+ return true;
+ }
+ if (!strcmp("vkRegisterDeviceEventEXT", name)) {
+ *addr = (void *)RegisterDeviceEventEXT;
+ return true;
+ }
+ if (!strcmp("vkRegisterDisplayEventEXT", name)) {
+ *addr = (void *)RegisterDisplayEventEXT;
+ return true;
+ }
+ if (!strcmp("vkGetSwapchainCounterEXT", name)) {
+ *addr = (void *)GetSwapchainCounterEXT;
+ return true;
+ }
+
+ // ---- VK_GOOGLE_display_timing extension commands
+ if (!strcmp("vkGetRefreshCycleDurationGOOGLE", name)) {
+ *addr = (void *)GetRefreshCycleDurationGOOGLE;
+ return true;
+ }
+ if (!strcmp("vkGetPastPresentationTimingGOOGLE", name)) {
+ *addr = (void *)GetPastPresentationTimingGOOGLE;
+ return true;
+ }
+
+ // ---- VK_EXT_discard_rectangles extension commands
+ if (!strcmp("vkCmdSetDiscardRectangleEXT", name)) {
+ *addr = (void *)CmdSetDiscardRectangleEXT;
+ return true;
+ }
+
+ // ---- VK_EXT_hdr_metadata extension commands
+ if (!strcmp("vkSetHdrMetadataEXT", name)) {
+ *addr = (void *)SetHdrMetadataEXT;
+ return true;
+ }
+
+ // ---- VK_EXT_debug_utils extension commands
+ if (!strcmp("vkSetDebugUtilsObjectNameEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_debug_utils == 1)
+ ? (void *)SetDebugUtilsObjectNameEXT
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkSetDebugUtilsObjectTagEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_debug_utils == 1)
+ ? (void *)SetDebugUtilsObjectTagEXT
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkQueueBeginDebugUtilsLabelEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_debug_utils == 1)
+ ? (void *)QueueBeginDebugUtilsLabelEXT
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkQueueEndDebugUtilsLabelEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_debug_utils == 1)
+ ? (void *)QueueEndDebugUtilsLabelEXT
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkQueueInsertDebugUtilsLabelEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_debug_utils == 1)
+ ? (void *)QueueInsertDebugUtilsLabelEXT
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkCmdBeginDebugUtilsLabelEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_debug_utils == 1)
+ ? (void *)CmdBeginDebugUtilsLabelEXT
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkCmdEndDebugUtilsLabelEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_debug_utils == 1)
+ ? (void *)CmdEndDebugUtilsLabelEXT
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkCmdInsertDebugUtilsLabelEXT", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.ext_debug_utils == 1)
+ ? (void *)CmdInsertDebugUtilsLabelEXT
+ : NULL;
+ return true;
+ }
+
+ // ---- VK_ANDROID_external_memory_android_hardware_buffer extension commands
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ if (!strcmp("vkGetAndroidHardwareBufferPropertiesANDROID", name)) {
+ *addr = (void *)GetAndroidHardwareBufferPropertiesANDROID;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ if (!strcmp("vkGetMemoryAndroidHardwareBufferANDROID", name)) {
+ *addr = (void *)GetMemoryAndroidHardwareBufferANDROID;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+ // ---- VK_EXT_sample_locations extension commands
+ if (!strcmp("vkCmdSetSampleLocationsEXT", name)) {
+ *addr = (void *)CmdSetSampleLocationsEXT;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceMultisamplePropertiesEXT", name)) {
+ *addr = (void *)GetPhysicalDeviceMultisamplePropertiesEXT;
+ return true;
+ }
+
+ // ---- VK_EXT_image_drm_format_modifier extension commands
+ if (!strcmp("vkGetImageDrmFormatModifierPropertiesEXT", name)) {
+ *addr = (void *)GetImageDrmFormatModifierPropertiesEXT;
+ return true;
+ }
+
+ // ---- VK_EXT_validation_cache extension commands
+ if (!strcmp("vkCreateValidationCacheEXT", name)) {
+ *addr = (void *)CreateValidationCacheEXT;
+ return true;
+ }
+ if (!strcmp("vkDestroyValidationCacheEXT", name)) {
+ *addr = (void *)DestroyValidationCacheEXT;
+ return true;
+ }
+ if (!strcmp("vkMergeValidationCachesEXT", name)) {
+ *addr = (void *)MergeValidationCachesEXT;
+ return true;
+ }
+ if (!strcmp("vkGetValidationCacheDataEXT", name)) {
+ *addr = (void *)GetValidationCacheDataEXT;
+ return true;
+ }
+
+ // ---- VK_NV_shading_rate_image extension commands
+ if (!strcmp("vkCmdBindShadingRateImageNV", name)) {
+ *addr = (void *)CmdBindShadingRateImageNV;
+ return true;
+ }
+ if (!strcmp("vkCmdSetViewportShadingRatePaletteNV", name)) {
+ *addr = (void *)CmdSetViewportShadingRatePaletteNV;
+ return true;
+ }
+ if (!strcmp("vkCmdSetCoarseSampleOrderNV", name)) {
+ *addr = (void *)CmdSetCoarseSampleOrderNV;
+ return true;
+ }
+
+ // ---- VK_NV_ray_tracing extension commands
+ if (!strcmp("vkCreateAccelerationStructureNV", name)) {
+ *addr = (void *)CreateAccelerationStructureNV;
+ return true;
+ }
+ if (!strcmp("vkDestroyAccelerationStructureNV", name)) {
+ *addr = (void *)DestroyAccelerationStructureNV;
+ return true;
+ }
+ if (!strcmp("vkGetAccelerationStructureMemoryRequirementsNV", name)) {
+ *addr = (void *)GetAccelerationStructureMemoryRequirementsNV;
+ return true;
+ }
+ if (!strcmp("vkBindAccelerationStructureMemoryNV", name)) {
+ *addr = (void *)BindAccelerationStructureMemoryNV;
+ return true;
+ }
+ if (!strcmp("vkCmdBuildAccelerationStructureNV", name)) {
+ *addr = (void *)CmdBuildAccelerationStructureNV;
+ return true;
+ }
+ if (!strcmp("vkCmdCopyAccelerationStructureNV", name)) {
+ *addr = (void *)CmdCopyAccelerationStructureNV;
+ return true;
+ }
+ if (!strcmp("vkCmdTraceRaysNV", name)) {
+ *addr = (void *)CmdTraceRaysNV;
+ return true;
+ }
+ if (!strcmp("vkCreateRayTracingPipelinesNV", name)) {
+ *addr = (void *)CreateRayTracingPipelinesNV;
+ return true;
+ }
+ if (!strcmp("vkGetRayTracingShaderGroupHandlesNV", name)) {
+ *addr = (void *)GetRayTracingShaderGroupHandlesNV;
+ return true;
+ }
+ if (!strcmp("vkGetAccelerationStructureHandleNV", name)) {
+ *addr = (void *)GetAccelerationStructureHandleNV;
+ return true;
+ }
+ if (!strcmp("vkCmdWriteAccelerationStructuresPropertiesNV", name)) {
+ *addr = (void *)CmdWriteAccelerationStructuresPropertiesNV;
+ return true;
+ }
+ if (!strcmp("vkCompileDeferredNV", name)) {
+ *addr = (void *)CompileDeferredNV;
+ return true;
+ }
+
+ // ---- VK_EXT_external_memory_host extension commands
+ if (!strcmp("vkGetMemoryHostPointerPropertiesEXT", name)) {
+ *addr = (void *)GetMemoryHostPointerPropertiesEXT;
+ return true;
+ }
+
+ // ---- VK_AMD_buffer_marker extension commands
+ if (!strcmp("vkCmdWriteBufferMarkerAMD", name)) {
+ *addr = (void *)CmdWriteBufferMarkerAMD;
+ return true;
+ }
+
+ // ---- VK_EXT_calibrated_timestamps extension commands
+ if (!strcmp("vkGetPhysicalDeviceCalibrateableTimeDomainsEXT", name)) {
+ *addr = (void *)GetPhysicalDeviceCalibrateableTimeDomainsEXT;
+ return true;
+ }
+ if (!strcmp("vkGetCalibratedTimestampsEXT", name)) {
+ *addr = (void *)GetCalibratedTimestampsEXT;
+ return true;
+ }
+
+ // ---- VK_NV_mesh_shader extension commands
+ if (!strcmp("vkCmdDrawMeshTasksNV", name)) {
+ *addr = (void *)CmdDrawMeshTasksNV;
+ return true;
+ }
+ if (!strcmp("vkCmdDrawMeshTasksIndirectNV", name)) {
+ *addr = (void *)CmdDrawMeshTasksIndirectNV;
+ return true;
+ }
+ if (!strcmp("vkCmdDrawMeshTasksIndirectCountNV", name)) {
+ *addr = (void *)CmdDrawMeshTasksIndirectCountNV;
+ return true;
+ }
+
+ // ---- VK_NV_scissor_exclusive extension commands
+ if (!strcmp("vkCmdSetExclusiveScissorNV", name)) {
+ *addr = (void *)CmdSetExclusiveScissorNV;
+ return true;
+ }
+
+ // ---- VK_NV_device_diagnostic_checkpoints extension commands
+ if (!strcmp("vkCmdSetCheckpointNV", name)) {
+ *addr = (void *)CmdSetCheckpointNV;
+ return true;
+ }
+ if (!strcmp("vkGetQueueCheckpointDataNV", name)) {
+ *addr = (void *)GetQueueCheckpointDataNV;
+ return true;
+ }
+
+ // ---- VK_INTEL_performance_query extension commands
+ if (!strcmp("vkInitializePerformanceApiINTEL", name)) {
+ *addr = (void *)InitializePerformanceApiINTEL;
+ return true;
+ }
+ if (!strcmp("vkUninitializePerformanceApiINTEL", name)) {
+ *addr = (void *)UninitializePerformanceApiINTEL;
+ return true;
+ }
+ if (!strcmp("vkCmdSetPerformanceMarkerINTEL", name)) {
+ *addr = (void *)CmdSetPerformanceMarkerINTEL;
+ return true;
+ }
+ if (!strcmp("vkCmdSetPerformanceStreamMarkerINTEL", name)) {
+ *addr = (void *)CmdSetPerformanceStreamMarkerINTEL;
+ return true;
+ }
+ if (!strcmp("vkCmdSetPerformanceOverrideINTEL", name)) {
+ *addr = (void *)CmdSetPerformanceOverrideINTEL;
+ return true;
+ }
+ if (!strcmp("vkAcquirePerformanceConfigurationINTEL", name)) {
+ *addr = (void *)AcquirePerformanceConfigurationINTEL;
+ return true;
+ }
+ if (!strcmp("vkReleasePerformanceConfigurationINTEL", name)) {
+ *addr = (void *)ReleasePerformanceConfigurationINTEL;
+ return true;
+ }
+ if (!strcmp("vkQueueSetPerformanceConfigurationINTEL", name)) {
+ *addr = (void *)QueueSetPerformanceConfigurationINTEL;
+ return true;
+ }
+ if (!strcmp("vkGetPerformanceParameterINTEL", name)) {
+ *addr = (void *)GetPerformanceParameterINTEL;
+ return true;
+ }
+
+ // ---- VK_AMD_display_native_hdr extension commands
+ if (!strcmp("vkSetLocalDimmingAMD", name)) {
+ *addr = (void *)SetLocalDimmingAMD;
+ return true;
+ }
+
+ // ---- VK_FUCHSIA_imagepipe_surface extension commands
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ if (!strcmp("vkCreateImagePipeSurfaceFUCHSIA", name)) {
+ *addr = (ptr_instance->enabled_known_extensions.fuchsia_imagepipe_surface == 1)
+ ? (void *)CreateImagePipeSurfaceFUCHSIA
+ : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_FUCHSIA
+
+ // ---- VK_EXT_buffer_device_address extension commands
+ if (!strcmp("vkGetBufferDeviceAddressEXT", name)) {
+ *addr = (void *)GetBufferDeviceAddressEXT;
+ return true;
+ }
+
+ // ---- VK_EXT_tooling_info extension commands
+ if (!strcmp("vkGetPhysicalDeviceToolPropertiesEXT", name)) {
+ *addr = (void *)GetPhysicalDeviceToolPropertiesEXT;
+ return true;
+ }
+
+ // ---- VK_NV_cooperative_matrix extension commands
+ if (!strcmp("vkGetPhysicalDeviceCooperativeMatrixPropertiesNV", name)) {
+ *addr = (void *)GetPhysicalDeviceCooperativeMatrixPropertiesNV;
+ return true;
+ }
+
+ // ---- VK_NV_coverage_reduction_mode extension commands
+ if (!strcmp("vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV", name)) {
+ *addr = (void *)GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV;
+ return true;
+ }
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkGetPhysicalDeviceSurfacePresentModes2EXT", name)) {
+ *addr = (void *)GetPhysicalDeviceSurfacePresentModes2EXT;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkAcquireFullScreenExclusiveModeEXT", name)) {
+ *addr = (void *)AcquireFullScreenExclusiveModeEXT;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkReleaseFullScreenExclusiveModeEXT", name)) {
+ *addr = (void *)ReleaseFullScreenExclusiveModeEXT;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp("vkGetDeviceGroupSurfacePresentModes2EXT", name)) {
+ *addr = (void *)GetDeviceGroupSurfacePresentModes2EXT;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_line_rasterization extension commands
+ if (!strcmp("vkCmdSetLineStippleEXT", name)) {
+ *addr = (void *)CmdSetLineStippleEXT;
+ return true;
+ }
+
+ // ---- VK_EXT_host_query_reset extension commands
+ if (!strcmp("vkResetQueryPoolEXT", name)) {
+ *addr = (void *)ResetQueryPoolEXT;
+ return true;
+ }
+ return false;
+}
+
+// A function that can be used to query enabled extensions during a vkCreateInstance call
+void extensions_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+
+ // ---- VK_KHR_get_physical_device_properties2 extension commands
+ if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.khr_get_physical_device_properties2 = 1;
+
+ // ---- VK_KHR_device_group_creation extension commands
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.khr_device_group_creation = 1;
+
+ // ---- VK_KHR_external_memory_capabilities extension commands
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.khr_external_memory_capabilities = 1;
+
+ // ---- VK_KHR_external_semaphore_capabilities extension commands
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.khr_external_semaphore_capabilities = 1;
+
+ // ---- VK_KHR_external_fence_capabilities extension commands
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.khr_external_fence_capabilities = 1;
+
+ // ---- VK_KHR_get_surface_capabilities2 extension commands
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.khr_get_surface_capabilities2 = 1;
+
+ // ---- VK_GGP_stream_descriptor_surface extension commands
+#ifdef VK_USE_PLATFORM_GGP
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.ggp_stream_descriptor_surface = 1;
+#endif // VK_USE_PLATFORM_GGP
+
+ // ---- VK_NV_external_memory_capabilities extension commands
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.nv_external_memory_capabilities = 1;
+
+ // ---- VK_NN_vi_surface extension commands
+#ifdef VK_USE_PLATFORM_VI_NN
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NN_VI_SURFACE_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.nn_vi_surface = 1;
+#endif // VK_USE_PLATFORM_VI_NN
+
+ // ---- VK_EXT_direct_mode_display extension commands
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.ext_direct_mode_display = 1;
+
+ // ---- VK_EXT_acquire_xlib_display extension commands
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.ext_acquire_xlib_display = 1;
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
+ // ---- VK_EXT_display_surface_counter extension commands
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.ext_display_surface_counter = 1;
+
+ // ---- VK_EXT_debug_utils extension commands
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.ext_debug_utils = 1;
+
+ // ---- VK_FUCHSIA_imagepipe_surface extension commands
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.fuchsia_imagepipe_surface = 1;
+#endif // VK_USE_PLATFORM_FUCHSIA
+ }
+ }
+}
+
+// Some device commands still need a terminator because the loader needs to unwrap something about them.
+// In many cases, the item needing unwrapping is a VkPhysicalDevice or VkSurfaceKHR object. But there may be other items
+// in the future.
+PFN_vkVoidFunction get_extension_device_proc_terminator(struct loader_device *dev, const char *pName) {
+ PFN_vkVoidFunction addr = NULL;
+
+ // ---- VK_KHR_swapchain extension commands
+ if (dev->extensions.khr_swapchain_enabled) {
+ if(!strcmp(pName, "vkCreateSwapchainKHR")) {
+ addr = (PFN_vkVoidFunction)terminator_CreateSwapchainKHR;
+ } else if(!strcmp(pName, "vkGetDeviceGroupSurfacePresentModesKHR")) {
+ addr = (PFN_vkVoidFunction)terminator_GetDeviceGroupSurfacePresentModesKHR;
+ }
+ }
+
+ // ---- VK_KHR_display_swapchain extension commands
+ if (dev->extensions.khr_display_swapchain_enabled) {
+ if(!strcmp(pName, "vkCreateSharedSwapchainsKHR")) {
+ addr = (PFN_vkVoidFunction)terminator_CreateSharedSwapchainsKHR;
+ }
+ }
+
+ // ---- VK_EXT_debug_marker extension commands
+ if (dev->extensions.ext_debug_marker_enabled) {
+ if(!strcmp(pName, "vkDebugMarkerSetObjectTagEXT")) {
+ addr = (PFN_vkVoidFunction)terminator_DebugMarkerSetObjectTagEXT;
+ } else if(!strcmp(pName, "vkDebugMarkerSetObjectNameEXT")) {
+ addr = (PFN_vkVoidFunction)terminator_DebugMarkerSetObjectNameEXT;
+ }
+ }
+
+ // ---- VK_EXT_debug_utils extension commands
+ if (dev->extensions.ext_debug_utils_enabled) {
+ if(!strcmp(pName, "vkSetDebugUtilsObjectNameEXT")) {
+ addr = (PFN_vkVoidFunction)terminator_SetDebugUtilsObjectNameEXT;
+ } else if(!strcmp(pName, "vkSetDebugUtilsObjectTagEXT")) {
+ addr = (PFN_vkVoidFunction)terminator_SetDebugUtilsObjectTagEXT;
+ } else if(!strcmp(pName, "vkQueueBeginDebugUtilsLabelEXT")) {
+ addr = (PFN_vkVoidFunction)terminator_QueueBeginDebugUtilsLabelEXT;
+ } else if(!strcmp(pName, "vkQueueEndDebugUtilsLabelEXT")) {
+ addr = (PFN_vkVoidFunction)terminator_QueueEndDebugUtilsLabelEXT;
+ } else if(!strcmp(pName, "vkQueueInsertDebugUtilsLabelEXT")) {
+ addr = (PFN_vkVoidFunction)terminator_QueueInsertDebugUtilsLabelEXT;
+ } else if(!strcmp(pName, "vkCmdBeginDebugUtilsLabelEXT")) {
+ addr = (PFN_vkVoidFunction)terminator_CmdBeginDebugUtilsLabelEXT;
+ } else if(!strcmp(pName, "vkCmdEndDebugUtilsLabelEXT")) {
+ addr = (PFN_vkVoidFunction)terminator_CmdEndDebugUtilsLabelEXT;
+ } else if(!strcmp(pName, "vkCmdInsertDebugUtilsLabelEXT")) {
+ addr = (PFN_vkVoidFunction)terminator_CmdInsertDebugUtilsLabelEXT;
+ }
+ }
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+ if (dev->extensions.ext_full_screen_exclusive_enabled && dev->extensions.khr_device_group_enabled) {
+ if(!strcmp(pName, "vkGetDeviceGroupSurfacePresentModes2EXT")) {
+ addr = (PFN_vkVoidFunction)terminator_GetDeviceGroupSurfacePresentModes2EXT;
+ }
+ }
+#endif // None
+ return addr;
+}
+
+// This table contains the loader's instance dispatch table, which contains
+// default functions if no instance layers are activated. This contains
+// pointers to "terminator functions".
+const VkLayerInstanceDispatchTable instance_disp = {
+
+ // ---- Core 1_0 commands
+ .DestroyInstance = terminator_DestroyInstance,
+ .EnumeratePhysicalDevices = terminator_EnumeratePhysicalDevices,
+ .GetPhysicalDeviceFeatures = terminator_GetPhysicalDeviceFeatures,
+ .GetPhysicalDeviceFormatProperties = terminator_GetPhysicalDeviceFormatProperties,
+ .GetPhysicalDeviceImageFormatProperties = terminator_GetPhysicalDeviceImageFormatProperties,
+ .GetPhysicalDeviceProperties = terminator_GetPhysicalDeviceProperties,
+ .GetPhysicalDeviceQueueFamilyProperties = terminator_GetPhysicalDeviceQueueFamilyProperties,
+ .GetPhysicalDeviceMemoryProperties = terminator_GetPhysicalDeviceMemoryProperties,
+ .GetInstanceProcAddr = vkGetInstanceProcAddr,
+ .EnumerateDeviceExtensionProperties = terminator_EnumerateDeviceExtensionProperties,
+ .EnumerateDeviceLayerProperties = terminator_EnumerateDeviceLayerProperties,
+ .GetPhysicalDeviceSparseImageFormatProperties = terminator_GetPhysicalDeviceSparseImageFormatProperties,
+
+ // ---- Core 1_1 commands
+ .EnumeratePhysicalDeviceGroups = terminator_EnumeratePhysicalDeviceGroups,
+ .GetPhysicalDeviceFeatures2 = terminator_GetPhysicalDeviceFeatures2,
+ .GetPhysicalDeviceProperties2 = terminator_GetPhysicalDeviceProperties2,
+ .GetPhysicalDeviceFormatProperties2 = terminator_GetPhysicalDeviceFormatProperties2,
+ .GetPhysicalDeviceImageFormatProperties2 = terminator_GetPhysicalDeviceImageFormatProperties2,
+ .GetPhysicalDeviceQueueFamilyProperties2 = terminator_GetPhysicalDeviceQueueFamilyProperties2,
+ .GetPhysicalDeviceMemoryProperties2 = terminator_GetPhysicalDeviceMemoryProperties2,
+ .GetPhysicalDeviceSparseImageFormatProperties2 = terminator_GetPhysicalDeviceSparseImageFormatProperties2,
+ .GetPhysicalDeviceExternalBufferProperties = terminator_GetPhysicalDeviceExternalBufferProperties,
+ .GetPhysicalDeviceExternalFenceProperties = terminator_GetPhysicalDeviceExternalFenceProperties,
+ .GetPhysicalDeviceExternalSemaphoreProperties = terminator_GetPhysicalDeviceExternalSemaphoreProperties,
+
+ // ---- VK_KHR_surface extension commands
+ .DestroySurfaceKHR = terminator_DestroySurfaceKHR,
+ .GetPhysicalDeviceSurfaceSupportKHR = terminator_GetPhysicalDeviceSurfaceSupportKHR,
+ .GetPhysicalDeviceSurfaceCapabilitiesKHR = terminator_GetPhysicalDeviceSurfaceCapabilitiesKHR,
+ .GetPhysicalDeviceSurfaceFormatsKHR = terminator_GetPhysicalDeviceSurfaceFormatsKHR,
+ .GetPhysicalDeviceSurfacePresentModesKHR = terminator_GetPhysicalDeviceSurfacePresentModesKHR,
+
+ // ---- VK_KHR_swapchain extension commands
+ .GetPhysicalDevicePresentRectanglesKHR = terminator_GetPhysicalDevicePresentRectanglesKHR,
+
+ // ---- VK_KHR_display extension commands
+ .GetPhysicalDeviceDisplayPropertiesKHR = terminator_GetPhysicalDeviceDisplayPropertiesKHR,
+ .GetPhysicalDeviceDisplayPlanePropertiesKHR = terminator_GetPhysicalDeviceDisplayPlanePropertiesKHR,
+ .GetDisplayPlaneSupportedDisplaysKHR = terminator_GetDisplayPlaneSupportedDisplaysKHR,
+ .GetDisplayModePropertiesKHR = terminator_GetDisplayModePropertiesKHR,
+ .CreateDisplayModeKHR = terminator_CreateDisplayModeKHR,
+ .GetDisplayPlaneCapabilitiesKHR = terminator_GetDisplayPlaneCapabilitiesKHR,
+ .CreateDisplayPlaneSurfaceKHR = terminator_CreateDisplayPlaneSurfaceKHR,
+
+ // ---- VK_KHR_xlib_surface extension commands
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ .CreateXlibSurfaceKHR = terminator_CreateXlibSurfaceKHR,
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ .GetPhysicalDeviceXlibPresentationSupportKHR = terminator_GetPhysicalDeviceXlibPresentationSupportKHR,
+#endif // VK_USE_PLATFORM_XLIB_KHR
+
+ // ---- VK_KHR_xcb_surface extension commands
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ .CreateXcbSurfaceKHR = terminator_CreateXcbSurfaceKHR,
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ .GetPhysicalDeviceXcbPresentationSupportKHR = terminator_GetPhysicalDeviceXcbPresentationSupportKHR,
+#endif // VK_USE_PLATFORM_XCB_KHR
+
+ // ---- VK_KHR_wayland_surface extension commands
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ .CreateWaylandSurfaceKHR = terminator_CreateWaylandSurfaceKHR,
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ .GetPhysicalDeviceWaylandPresentationSupportKHR = terminator_GetPhysicalDeviceWaylandPresentationSupportKHR,
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+
+ // ---- VK_KHR_android_surface extension commands
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ .CreateAndroidSurfaceKHR = terminator_CreateAndroidSurfaceKHR,
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+ // ---- VK_KHR_win32_surface extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ .CreateWin32SurfaceKHR = terminator_CreateWin32SurfaceKHR,
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ .GetPhysicalDeviceWin32PresentationSupportKHR = terminator_GetPhysicalDeviceWin32PresentationSupportKHR,
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_get_physical_device_properties2 extension commands
+ .GetPhysicalDeviceFeatures2KHR = terminator_GetPhysicalDeviceFeatures2,
+ .GetPhysicalDeviceProperties2KHR = terminator_GetPhysicalDeviceProperties2,
+ .GetPhysicalDeviceFormatProperties2KHR = terminator_GetPhysicalDeviceFormatProperties2,
+ .GetPhysicalDeviceImageFormatProperties2KHR = terminator_GetPhysicalDeviceImageFormatProperties2,
+ .GetPhysicalDeviceQueueFamilyProperties2KHR = terminator_GetPhysicalDeviceQueueFamilyProperties2,
+ .GetPhysicalDeviceMemoryProperties2KHR = terminator_GetPhysicalDeviceMemoryProperties2,
+ .GetPhysicalDeviceSparseImageFormatProperties2KHR = terminator_GetPhysicalDeviceSparseImageFormatProperties2,
+
+ // ---- VK_KHR_device_group_creation extension commands
+ .EnumeratePhysicalDeviceGroupsKHR = terminator_EnumeratePhysicalDeviceGroups,
+
+ // ---- VK_KHR_external_memory_capabilities extension commands
+ .GetPhysicalDeviceExternalBufferPropertiesKHR = terminator_GetPhysicalDeviceExternalBufferProperties,
+
+ // ---- VK_KHR_external_semaphore_capabilities extension commands
+ .GetPhysicalDeviceExternalSemaphorePropertiesKHR = terminator_GetPhysicalDeviceExternalSemaphoreProperties,
+
+ // ---- VK_KHR_external_fence_capabilities extension commands
+ .GetPhysicalDeviceExternalFencePropertiesKHR = terminator_GetPhysicalDeviceExternalFenceProperties,
+
+ // ---- VK_KHR_performance_query extension commands
+ .EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = terminator_EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR,
+ .GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = terminator_GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR,
+
+ // ---- VK_KHR_get_surface_capabilities2 extension commands
+ .GetPhysicalDeviceSurfaceCapabilities2KHR = terminator_GetPhysicalDeviceSurfaceCapabilities2KHR,
+ .GetPhysicalDeviceSurfaceFormats2KHR = terminator_GetPhysicalDeviceSurfaceFormats2KHR,
+
+ // ---- VK_KHR_get_display_properties2 extension commands
+ .GetPhysicalDeviceDisplayProperties2KHR = terminator_GetPhysicalDeviceDisplayProperties2KHR,
+ .GetPhysicalDeviceDisplayPlaneProperties2KHR = terminator_GetPhysicalDeviceDisplayPlaneProperties2KHR,
+ .GetDisplayModeProperties2KHR = terminator_GetDisplayModeProperties2KHR,
+ .GetDisplayPlaneCapabilities2KHR = terminator_GetDisplayPlaneCapabilities2KHR,
+
+ // ---- VK_EXT_debug_report extension commands
+ .CreateDebugReportCallbackEXT = terminator_CreateDebugReportCallbackEXT,
+ .DestroyDebugReportCallbackEXT = terminator_DestroyDebugReportCallbackEXT,
+ .DebugReportMessageEXT = terminator_DebugReportMessageEXT,
+
+ // ---- VK_GGP_stream_descriptor_surface extension commands
+#ifdef VK_USE_PLATFORM_GGP
+ .CreateStreamDescriptorSurfaceGGP = terminator_CreateStreamDescriptorSurfaceGGP,
+#endif // VK_USE_PLATFORM_GGP
+
+ // ---- VK_NV_external_memory_capabilities extension commands
+ .GetPhysicalDeviceExternalImageFormatPropertiesNV = terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV,
+
+ // ---- VK_NN_vi_surface extension commands
+#ifdef VK_USE_PLATFORM_VI_NN
+ .CreateViSurfaceNN = terminator_CreateViSurfaceNN,
+#endif // VK_USE_PLATFORM_VI_NN
+
+ // ---- VK_NVX_device_generated_commands extension commands
+ .GetPhysicalDeviceGeneratedCommandsPropertiesNVX = terminator_GetPhysicalDeviceGeneratedCommandsPropertiesNVX,
+
+ // ---- VK_EXT_direct_mode_display extension commands
+ .ReleaseDisplayEXT = terminator_ReleaseDisplayEXT,
+
+ // ---- VK_EXT_acquire_xlib_display extension commands
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ .AcquireXlibDisplayEXT = terminator_AcquireXlibDisplayEXT,
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ .GetRandROutputDisplayEXT = terminator_GetRandROutputDisplayEXT,
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
+ // ---- VK_EXT_display_surface_counter extension commands
+ .GetPhysicalDeviceSurfaceCapabilities2EXT = terminator_GetPhysicalDeviceSurfaceCapabilities2EXT,
+
+ // ---- VK_MVK_ios_surface extension commands
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ .CreateIOSSurfaceMVK = terminator_CreateIOSSurfaceMVK,
+#endif // VK_USE_PLATFORM_IOS_MVK
+
+ // ---- VK_MVK_macos_surface extension commands
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ .CreateMacOSSurfaceMVK = terminator_CreateMacOSSurfaceMVK,
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
+ // ---- VK_EXT_debug_utils extension commands
+ .CreateDebugUtilsMessengerEXT = terminator_CreateDebugUtilsMessengerEXT,
+ .DestroyDebugUtilsMessengerEXT = terminator_DestroyDebugUtilsMessengerEXT,
+ .SubmitDebugUtilsMessageEXT = terminator_SubmitDebugUtilsMessageEXT,
+
+ // ---- VK_EXT_sample_locations extension commands
+ .GetPhysicalDeviceMultisamplePropertiesEXT = terminator_GetPhysicalDeviceMultisamplePropertiesEXT,
+
+ // ---- VK_EXT_calibrated_timestamps extension commands
+ .GetPhysicalDeviceCalibrateableTimeDomainsEXT = terminator_GetPhysicalDeviceCalibrateableTimeDomainsEXT,
+
+ // ---- VK_FUCHSIA_imagepipe_surface extension commands
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ .CreateImagePipeSurfaceFUCHSIA = terminator_CreateImagePipeSurfaceFUCHSIA,
+#endif // VK_USE_PLATFORM_FUCHSIA
+
+ // ---- VK_EXT_metal_surface extension commands
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ .CreateMetalSurfaceEXT = terminator_CreateMetalSurfaceEXT,
+#endif // VK_USE_PLATFORM_METAL_EXT
+
+ // ---- VK_EXT_tooling_info extension commands
+ .GetPhysicalDeviceToolPropertiesEXT = terminator_GetPhysicalDeviceToolPropertiesEXT,
+
+ // ---- VK_NV_cooperative_matrix extension commands
+ .GetPhysicalDeviceCooperativeMatrixPropertiesNV = terminator_GetPhysicalDeviceCooperativeMatrixPropertiesNV,
+
+ // ---- VK_NV_coverage_reduction_mode extension commands
+ .GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = terminator_GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV,
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ .GetPhysicalDeviceSurfacePresentModes2EXT = terminator_GetPhysicalDeviceSurfacePresentModes2EXT,
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_headless_surface extension commands
+ .CreateHeadlessSurfaceEXT = terminator_CreateHeadlessSurfaceEXT,
+};
+
+// A null-terminated list of all of the instance extensions supported by the loader.
+// If an instance extension name is not in this list, but it is exported by one or more of the
+// ICDs detected by the loader, then the extension name not in the list will be filtered out
+// before passing the list of extensions to the application.
+const char *const LOADER_INSTANCE_EXTENSIONS[] = {
+ VK_KHR_SURFACE_EXTENSION_NAME,
+ VK_KHR_DISPLAY_EXTENSION_NAME,
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ VK_KHR_XCB_SURFACE_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_WIN32_KHR
+ VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
+ VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME,
+ VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
+ VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME,
+ VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME,
+ VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
+#ifdef VK_USE_PLATFORM_GGP
+ VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_GGP
+ VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
+ VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME,
+#ifdef VK_USE_PLATFORM_VI_NN
+ VK_NN_VI_SURFACE_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_VI_NN
+ VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME,
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME,
+ VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ VK_MVK_IOS_SURFACE_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_IOS_MVK
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ VK_MVK_MACOS_SURFACE_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_MACOS_MVK
+ VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_FUCHSIA
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ VK_EXT_METAL_SURFACE_EXTENSION_NAME,
+#endif // VK_USE_PLATFORM_METAL_EXT
+ VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME,
+ VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME,
+ NULL };
+
diff --git a/thirdparty/vulkan/loader/vk_loader_extensions.h b/thirdparty/vulkan/loader/vk_loader_extensions.h
new file mode 100644
index 0000000000..a50f3cdd32
--- /dev/null
+++ b/thirdparty/vulkan/loader/vk_loader_extensions.h
@@ -0,0 +1,457 @@
+// *** THIS FILE IS GENERATED - DO NOT EDIT ***
+// See loader_extension_generator.py for modifications
+
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Mark Lobodzinski <mark@lunarg.com>
+ * Author: Mark Young <marky@lunarg.com>
+ */
+
+#pragma once
+
+// Structures defined externally, but used here
+struct loader_instance;
+struct loader_device;
+struct loader_icd_term;
+struct loader_dev_dispatch_table;
+
+// Device extension error function
+VKAPI_ATTR VkResult VKAPI_CALL vkDevExtError(VkDevice dev);
+
+// Extension interception for vkGetInstanceProcAddr function, so we can return
+// the appropriate information for any instance extensions we know about.
+bool extension_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr);
+
+// Extension interception for vkCreateInstance function, so we can properly
+// detect and enable any instance extension information for extensions we know
+// about.
+void extensions_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);
+
+// Extension interception for vkGetDeviceProcAddr function, so we can return
+// an appropriate terminator if this is one of those few device commands requiring
+// a terminator.
+PFN_vkVoidFunction get_extension_device_proc_terminator(struct loader_device *dev, const char *pName);
+
+// Dispatch table properly filled in with appropriate terminators for the
+// supported extensions.
+extern const VkLayerInstanceDispatchTable instance_disp;
+
+// Array of extension strings for instance extensions we support.
+extern const char *const LOADER_INSTANCE_EXTENSIONS[];
+
+VKAPI_ATTR bool VKAPI_CALL loader_icd_init_entries(struct loader_icd_term *icd_term, VkInstance inst,
+ const PFN_vkGetInstanceProcAddr fp_gipa);
+
+// Init Device function pointer dispatch table with core commands
+VKAPI_ATTR void VKAPI_CALL loader_init_device_dispatch_table(struct loader_dev_dispatch_table *dev_table, PFN_vkGetDeviceProcAddr gpa,
+ VkDevice dev);
+
+// Init Device function pointer dispatch table with extension commands
+VKAPI_ATTR void VKAPI_CALL loader_init_device_extension_dispatch_table(struct loader_dev_dispatch_table *dev_table,
+ PFN_vkGetInstanceProcAddr gipa,
+ PFN_vkGetDeviceProcAddr gdpa,
+ VkInstance inst,
+ VkDevice dev);
+
+// Init Instance function pointer dispatch table with core commands
+VKAPI_ATTR void VKAPI_CALL loader_init_instance_core_dispatch_table(VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa,
+ VkInstance inst);
+
+// Init Instance function pointer dispatch table with core commands
+VKAPI_ATTR void VKAPI_CALL loader_init_instance_extension_dispatch_table(VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa,
+ VkInstance inst);
+
+// Device command lookup function
+VKAPI_ATTR void* VKAPI_CALL loader_lookup_device_dispatch_table(const VkLayerDispatchTable *table, const char *name);
+
+// Instance command lookup function
+VKAPI_ATTR void* VKAPI_CALL loader_lookup_instance_dispatch_table(const VkLayerInstanceDispatchTable *table, const char *name,
+ bool *found_name);
+
+VKAPI_ATTR bool VKAPI_CALL loader_icd_init_entries(struct loader_icd_term *icd_term, VkInstance inst,
+ const PFN_vkGetInstanceProcAddr fp_gipa);
+
+// Loader core instance terminators
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(
+ const VkInstanceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkInstance* pInstance);
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyInstance(
+ VkInstance instance,
+ const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceCount,
+ VkPhysicalDevice* pPhysicalDevices);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures* pFeatures);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties* pFormatProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ VkImageTiling tiling,
+ VkImageUsageFlags usage,
+ VkImageCreateFlags flags,
+ VkImageFormatProperties* pImageFormatProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties* pProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties* pQueueFamilyProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties* pMemoryProperties);
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL terminator_GetInstanceProcAddr(
+ VkInstance instance,
+ const char* pName);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(
+ VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceExtensionProperties(
+ const VkEnumerateInstanceExtensionPropertiesChain* chain,
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(
+ VkPhysicalDevice physicalDevice,
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(
+ const VkEnumerateInstanceLayerPropertiesChain* chain,
+ uint32_t* pPropertyCount,
+ VkLayerProperties* pProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceLayerProperties(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pPropertyCount,
+ VkLayerProperties* pProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ VkSampleCountFlagBits samples,
+ VkImageUsageFlags usage,
+ VkImageTiling tiling,
+ uint32_t* pPropertyCount,
+ VkSparseImageFormatProperties* pProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceVersion(
+ const VkEnumerateInstanceVersionChain* chain,
+ uint32_t* pApiVersion);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
+ VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties2(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
+ uint32_t* pPropertyCount,
+ VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalBufferProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalFenceProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
+ VkExternalFenceProperties* pExternalFenceProperties);
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalSemaphoreProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+ VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+
+// ICD function pointer dispatch table
+struct loader_icd_term_dispatch {
+
+ // ---- Core 1_0 commands
+ PFN_vkCreateInstance CreateInstance;
+ PFN_vkDestroyInstance DestroyInstance;
+ PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+ PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
+ PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
+ PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
+ PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties;
+ PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties;
+ PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+ PFN_vkCreateDevice CreateDevice;
+ PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+ PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+ PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
+
+ // ---- Core 1_1 commands
+ PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion;
+ PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
+ PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
+ PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
+ PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysicalDeviceImageFormatProperties2;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysicalDeviceQueueFamilyProperties2;
+ PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysicalDeviceMemoryProperties2;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysicalDeviceSparseImageFormatProperties2;
+ PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties;
+ PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties;
+ PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties;
+
+ // ---- VK_KHR_surface extension commands
+ PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
+ PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
+ PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
+
+ // ---- VK_KHR_swapchain extension commands
+ PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
+ PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR;
+ PFN_vkGetPhysicalDevicePresentRectanglesKHR GetPhysicalDevicePresentRectanglesKHR;
+
+ // ---- VK_KHR_display extension commands
+ PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR;
+ PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR;
+ PFN_vkGetDisplayPlaneSupportedDisplaysKHR GetDisplayPlaneSupportedDisplaysKHR;
+ PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR;
+ PFN_vkCreateDisplayModeKHR CreateDisplayModeKHR;
+ PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR;
+ PFN_vkCreateDisplayPlaneSurfaceKHR CreateDisplayPlaneSurfaceKHR;
+
+ // ---- VK_KHR_display_swapchain extension commands
+ PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR;
+
+ // ---- VK_KHR_xlib_surface extension commands
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR GetPhysicalDeviceXlibPresentationSupportKHR;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+
+ // ---- VK_KHR_xcb_surface extension commands
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ PFN_vkCreateXcbSurfaceKHR CreateXcbSurfaceKHR;
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR GetPhysicalDeviceXcbPresentationSupportKHR;
+#endif // VK_USE_PLATFORM_XCB_KHR
+
+ // ---- VK_KHR_wayland_surface extension commands
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ PFN_vkCreateWaylandSurfaceKHR CreateWaylandSurfaceKHR;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR GetPhysicalDeviceWaylandPresentationSupportKHR;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+
+ // ---- VK_KHR_android_surface extension commands
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+ // ---- VK_KHR_win32_surface extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkCreateWin32SurfaceKHR CreateWin32SurfaceKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR GetPhysicalDeviceWin32PresentationSupportKHR;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_KHR_get_physical_device_properties2 extension commands
+ PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysicalDeviceFeatures2KHR;
+ PFN_vkGetPhysicalDeviceProperties2KHR GetPhysicalDeviceProperties2KHR;
+ PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysicalDeviceFormatProperties2KHR;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysicalDeviceImageFormatProperties2KHR;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysicalDeviceQueueFamilyProperties2KHR;
+ PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysicalDeviceMemoryProperties2KHR;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysicalDeviceSparseImageFormatProperties2KHR;
+
+ // ---- VK_KHR_device_group_creation extension commands
+ PFN_vkEnumeratePhysicalDeviceGroupsKHR EnumeratePhysicalDeviceGroupsKHR;
+
+ // ---- VK_KHR_external_memory_capabilities extension commands
+ PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR;
+
+ // ---- VK_KHR_external_semaphore_capabilities extension commands
+ PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR GetPhysicalDeviceExternalSemaphorePropertiesKHR;
+
+ // ---- VK_KHR_external_fence_capabilities extension commands
+ PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR GetPhysicalDeviceExternalFencePropertiesKHR;
+
+ // ---- VK_KHR_performance_query extension commands
+ PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR;
+ PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR;
+
+ // ---- VK_KHR_get_surface_capabilities2 extension commands
+ PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR GetPhysicalDeviceSurfaceCapabilities2KHR;
+ PFN_vkGetPhysicalDeviceSurfaceFormats2KHR GetPhysicalDeviceSurfaceFormats2KHR;
+
+ // ---- VK_KHR_get_display_properties2 extension commands
+ PFN_vkGetPhysicalDeviceDisplayProperties2KHR GetPhysicalDeviceDisplayProperties2KHR;
+ PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR GetPhysicalDeviceDisplayPlaneProperties2KHR;
+ PFN_vkGetDisplayModeProperties2KHR GetDisplayModeProperties2KHR;
+ PFN_vkGetDisplayPlaneCapabilities2KHR GetDisplayPlaneCapabilities2KHR;
+
+ // ---- VK_EXT_debug_report extension commands
+ PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
+ PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
+ PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+
+ // ---- VK_EXT_debug_marker extension commands
+ PFN_vkDebugMarkerSetObjectTagEXT DebugMarkerSetObjectTagEXT;
+ PFN_vkDebugMarkerSetObjectNameEXT DebugMarkerSetObjectNameEXT;
+
+ // ---- VK_GGP_stream_descriptor_surface extension commands
+#ifdef VK_USE_PLATFORM_GGP
+ PFN_vkCreateStreamDescriptorSurfaceGGP CreateStreamDescriptorSurfaceGGP;
+#endif // VK_USE_PLATFORM_GGP
+
+ // ---- VK_NV_external_memory_capabilities extension commands
+ PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV GetPhysicalDeviceExternalImageFormatPropertiesNV;
+
+ // ---- VK_NN_vi_surface extension commands
+#ifdef VK_USE_PLATFORM_VI_NN
+ PFN_vkCreateViSurfaceNN CreateViSurfaceNN;
+#endif // VK_USE_PLATFORM_VI_NN
+
+ // ---- VK_NVX_device_generated_commands extension commands
+ PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX GetPhysicalDeviceGeneratedCommandsPropertiesNVX;
+
+ // ---- VK_EXT_direct_mode_display extension commands
+ PFN_vkReleaseDisplayEXT ReleaseDisplayEXT;
+
+ // ---- VK_EXT_acquire_xlib_display extension commands
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ PFN_vkAcquireXlibDisplayEXT AcquireXlibDisplayEXT;
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ PFN_vkGetRandROutputDisplayEXT GetRandROutputDisplayEXT;
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
+ // ---- VK_EXT_display_surface_counter extension commands
+ PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT GetPhysicalDeviceSurfaceCapabilities2EXT;
+
+ // ---- VK_MVK_ios_surface extension commands
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ PFN_vkCreateIOSSurfaceMVK CreateIOSSurfaceMVK;
+#endif // VK_USE_PLATFORM_IOS_MVK
+
+ // ---- VK_MVK_macos_surface extension commands
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ PFN_vkCreateMacOSSurfaceMVK CreateMacOSSurfaceMVK;
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
+ // ---- VK_EXT_debug_utils extension commands
+ PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT;
+ PFN_vkSetDebugUtilsObjectTagEXT SetDebugUtilsObjectTagEXT;
+ PFN_vkQueueBeginDebugUtilsLabelEXT QueueBeginDebugUtilsLabelEXT;
+ PFN_vkQueueEndDebugUtilsLabelEXT QueueEndDebugUtilsLabelEXT;
+ PFN_vkQueueInsertDebugUtilsLabelEXT QueueInsertDebugUtilsLabelEXT;
+ PFN_vkCmdBeginDebugUtilsLabelEXT CmdBeginDebugUtilsLabelEXT;
+ PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT;
+ PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT;
+ PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT;
+ PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT;
+ PFN_vkSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT;
+
+ // ---- VK_EXT_sample_locations extension commands
+ PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT GetPhysicalDeviceMultisamplePropertiesEXT;
+
+ // ---- VK_EXT_calibrated_timestamps extension commands
+ PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT GetPhysicalDeviceCalibrateableTimeDomainsEXT;
+
+ // ---- VK_FUCHSIA_imagepipe_surface extension commands
+#ifdef VK_USE_PLATFORM_FUCHSIA
+ PFN_vkCreateImagePipeSurfaceFUCHSIA CreateImagePipeSurfaceFUCHSIA;
+#endif // VK_USE_PLATFORM_FUCHSIA
+
+ // ---- VK_EXT_metal_surface extension commands
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ PFN_vkCreateMetalSurfaceEXT CreateMetalSurfaceEXT;
+#endif // VK_USE_PLATFORM_METAL_EXT
+
+ // ---- VK_EXT_tooling_info extension commands
+ PFN_vkGetPhysicalDeviceToolPropertiesEXT GetPhysicalDeviceToolPropertiesEXT;
+
+ // ---- VK_NV_cooperative_matrix extension commands
+ PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV GetPhysicalDeviceCooperativeMatrixPropertiesNV;
+
+ // ---- VK_NV_coverage_reduction_mode extension commands
+ PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV;
+
+ // ---- VK_EXT_full_screen_exclusive extension commands
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT GetPhysicalDeviceSurfacePresentModes2EXT;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ PFN_vkGetDeviceGroupSurfacePresentModes2EXT GetDeviceGroupSurfacePresentModes2EXT;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+ // ---- VK_EXT_headless_surface extension commands
+ PFN_vkCreateHeadlessSurfaceEXT CreateHeadlessSurfaceEXT;
+};
+
+union loader_instance_extension_enables {
+ struct {
+ uint8_t khr_get_physical_device_properties2 : 1;
+ uint8_t khr_device_group_creation : 1;
+ uint8_t khr_external_memory_capabilities : 1;
+ uint8_t khr_external_semaphore_capabilities : 1;
+ uint8_t khr_external_fence_capabilities : 1;
+ uint8_t khr_get_surface_capabilities2 : 1;
+ uint8_t ext_debug_report : 1;
+ uint8_t ggp_stream_descriptor_surface : 1;
+ uint8_t nv_external_memory_capabilities : 1;
+ uint8_t nn_vi_surface : 1;
+ uint8_t ext_direct_mode_display : 1;
+ uint8_t ext_acquire_xlib_display : 1;
+ uint8_t ext_display_surface_counter : 1;
+ uint8_t ext_debug_utils : 1;
+ uint8_t fuchsia_imagepipe_surface : 1;
+ };
+ uint64_t padding[4];
+};
+
+
diff --git a/thirdparty/vulkan/loader/vk_loader_layer.h b/thirdparty/vulkan/loader/vk_loader_layer.h
new file mode 100644
index 0000000000..dfcf5b2a46
--- /dev/null
+++ b/thirdparty/vulkan/loader/vk_loader_layer.h
@@ -0,0 +1,46 @@
+/*
+*
+* Copyright (c) 2016 The Khronos Group Inc.
+* Copyright (c) 2016 Valve Corporation
+* Copyright (c) 2016 LunarG, Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+* Author: Mark Lobodzinski <mark@lunarg.com>
+*
+*/
+#pragma once
+
+// Linked list node for tree of debug callbacks
+typedef struct VkDebugReportContent {
+ VkDebugReportCallbackEXT msgCallback;
+ PFN_vkDebugReportCallbackEXT pfnMsgCallback;
+ VkFlags msgFlags;
+} VkDebugReportContent;
+
+typedef struct VkDebugUtilsMessengerContent {
+ VkDebugUtilsMessengerEXT messenger;
+ VkDebugUtilsMessageSeverityFlagsEXT messageSeverity;
+ VkDebugUtilsMessageTypeFlagsEXT messageType;
+ PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback;
+} VkDebugUtilsMessengerContent;
+
+typedef struct VkLayerDbgFunctionNode_ {
+ bool is_messenger;
+ union {
+ VkDebugReportContent report;
+ VkDebugUtilsMessengerContent messenger;
+ };
+ void *pUserData;
+ struct VkLayerDbgFunctionNode_ *pNext;
+} VkLayerDbgFunctionNode;
diff --git a/thirdparty/vulkan/loader/vk_loader_platform.h b/thirdparty/vulkan/loader/vk_loader_platform.h
new file mode 100644
index 0000000000..62e8e3ae09
--- /dev/null
+++ b/thirdparty/vulkan/loader/vk_loader_platform.h
@@ -0,0 +1,386 @@
+/*
+ *
+ * Copyright (c) 2015-2018 The Khronos Group Inc.
+ * Copyright (c) 2015-2018 Valve Corporation
+ * Copyright (c) 2015-2018 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Ian Elliot <ian@lunarg.com>
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Lenny Komow <lenny@lunarg.com>
+ *
+ */
+#pragma once
+
+#if defined(_WIN32)
+// WinSock2.h must be included *BEFORE* windows.h
+#include <winsock2.h>
+#endif // _WIN32
+
+#include "vulkan/vk_platform.h"
+#include "vulkan/vk_sdk_platform.h"
+
+#if defined(__linux__) || defined(__APPLE__)
+/* Linux-specific common code: */
+
+// Headers:
+//#ifndef _GNU_SOURCE
+//#define _GNU_SOURCE 1
+//#endif
+// TBD: Are the contents of the following file used?
+#include <unistd.h>
+// Note: The following file is for dynamic loading:
+#include <dlfcn.h>
+#include <pthread.h>
+#include <assert.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <libgen.h>
+
+// VK Library Filenames, Paths, etc.:
+#define PATH_SEPARATOR ':'
+#define DIRECTORY_SYMBOL '/'
+
+#define VULKAN_DIR "vulkan/"
+#define VULKAN_ICDCONF_DIR "icd.d"
+#define VULKAN_ICD_DIR "icd"
+#define VULKAN_SETTINGSCONF_DIR "settings.d"
+#define VULKAN_ELAYERCONF_DIR "explicit_layer.d"
+#define VULKAN_ILAYERCONF_DIR "implicit_layer.d"
+#define VULKAN_LAYER_DIR "layer"
+
+#define VK_DRIVERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ICDCONF_DIR
+#define VK_SETTINGS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_SETTINGSCONF_DIR
+#define VK_ELAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
+#define VK_ILAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
+
+#define VK_DRIVERS_INFO_REGISTRY_LOC ""
+#define VK_SETTINGS_INFO_REGISTRY_LOC ""
+#define VK_ELAYERS_INFO_REGISTRY_LOC ""
+#define VK_ILAYERS_INFO_REGISTRY_LOC ""
+
+#if !defined(DEFAULT_VK_LAYERS_PATH)
+#define DEFAULT_VK_LAYERS_PATH ""
+#endif
+#if !defined(LAYERS_SOURCE_PATH)
+#define LAYERS_SOURCE_PATH NULL
+#endif
+#define LAYERS_PATH_ENV "VK_LAYER_PATH"
+#define ENABLED_LAYERS_ENV "VK_INSTANCE_LAYERS"
+
+// C99:
+#define PRINTF_SIZE_T_SPECIFIER "%zu"
+
+// File IO
+static inline bool loader_platform_file_exists(const char *path) {
+ if (access(path, F_OK))
+ return false;
+ else
+ return true;
+}
+
+static inline bool loader_platform_is_path_absolute(const char *path) {
+ if (path[0] == '/')
+ return true;
+ else
+ return false;
+}
+
+static inline char *loader_platform_dirname(char *path) { return dirname(path); }
+
+// Dynamic Loading of libraries:
+typedef void *loader_platform_dl_handle;
+static inline loader_platform_dl_handle loader_platform_open_library(const char *libPath) {
+ // When loading the library, we use RTLD_LAZY so that not all symbols have to be
+ // resolved at this time (which improves performance). Note that if not all symbols
+ // can be resolved, this could cause crashes later. Use the LD_BIND_NOW environment
+ // variable to force all symbols to be resolved here.
+ return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
+}
+static inline const char *loader_platform_open_library_error(const char *libPath) { return dlerror(); }
+static inline void loader_platform_close_library(loader_platform_dl_handle library) { dlclose(library); }
+static inline void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
+ assert(library);
+ assert(name);
+ return dlsym(library, name);
+}
+static inline const char *loader_platform_get_proc_address_error(const char *name) { return dlerror(); }
+
+// Threads:
+typedef pthread_t loader_platform_thread;
+#define THREAD_LOCAL_DECL __thread
+
+// The once init functionality is not used on Linux
+#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var)
+#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var)
+#define LOADER_PLATFORM_THREAD_ONCE(ctl, func)
+
+// Thread IDs:
+typedef pthread_t loader_platform_thread_id;
+static inline loader_platform_thread_id loader_platform_get_thread_id() { return pthread_self(); }
+
+// Thread mutex:
+typedef pthread_mutex_t loader_platform_thread_mutex;
+static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_init(pMutex, NULL); }
+static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_lock(pMutex); }
+static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
+static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_destroy(pMutex); }
+typedef pthread_cond_t loader_platform_thread_cond;
+static inline void loader_platform_thread_init_cond(loader_platform_thread_cond *pCond) { pthread_cond_init(pCond, NULL); }
+static inline void loader_platform_thread_cond_wait(loader_platform_thread_cond *pCond, loader_platform_thread_mutex *pMutex) {
+ pthread_cond_wait(pCond, pMutex);
+}
+static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_cond *pCond) { pthread_cond_broadcast(pCond); }
+
+#define loader_stack_alloc(size) alloca(size)
+
+#elif defined(_WIN32) // defined(__linux__)
+/* Windows-specific common code: */
+// WinBase.h defines CreateSemaphore and synchapi.h defines CreateEvent
+// undefine them to avoid conflicts with VkLayerDispatchTable struct members.
+#ifdef CreateSemaphore
+#undef CreateSemaphore
+#endif
+#ifdef CreateEvent
+#undef CreateEvent
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <io.h>
+#include <stdbool.h>
+#include <shlwapi.h>
+#ifdef __cplusplus
+#include <iostream>
+#include <string>
+#endif // __cplusplus
+
+// VK Library Filenames, Paths, etc.:
+#define PATH_SEPARATOR ';'
+#define DIRECTORY_SYMBOL '\\'
+#define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
+#define DEFAULT_VK_REGISTRY_HIVE_STR "HKEY_LOCAL_MACHINE"
+#define SECONDARY_VK_REGISTRY_HIVE HKEY_CURRENT_USER
+#define SECONDARY_VK_REGISTRY_HIVE_STR "HKEY_CURRENT_USER"
+
+#define VK_DRIVERS_INFO_RELATIVE_DIR ""
+#define VK_SETTINGS_INFO_RELATIVE_DIR ""
+#define VK_ELAYERS_INFO_RELATIVE_DIR ""
+#define VK_ILAYERS_INFO_RELATIVE_DIR ""
+
+#ifdef _WIN64
+#define HKR_VK_DRIVER_NAME API_NAME "DriverName"
+#else
+#define HKR_VK_DRIVER_NAME API_NAME "DriverNameWow"
+#endif
+#define VK_DRIVERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\" API_NAME "\\Drivers"
+#define VK_SETTINGS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\" API_NAME "\\Settings"
+#define VK_ELAYERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\" API_NAME "\\ExplicitLayers"
+#define VK_ILAYERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\" API_NAME "\\ImplicitLayers"
+
+#if !defined(DEFAULT_VK_LAYERS_PATH)
+#define DEFAULT_VK_LAYERS_PATH ""
+#endif
+#if !defined(LAYERS_SOURCE_PATH)
+#define LAYERS_SOURCE_PATH NULL
+#endif
+#define LAYERS_PATH_ENV "VK_LAYER_PATH"
+#define ENABLED_LAYERS_ENV "VK_INSTANCE_LAYERS"
+
+#define PRINTF_SIZE_T_SPECIFIER "%Iu"
+
+#if defined(_WIN32)
+// Get the key for the plug n play driver registry
+// The string returned by this function should NOT be freed
+static inline const char *LoaderPnpDriverRegistry() {
+ BOOL is_wow;
+ IsWow64Process(GetCurrentProcess(), &is_wow);
+ return is_wow ? "VulkanDriverNameWow" : "VulkanDriverName";
+}
+static inline const wchar_t *LoaderPnpDriverRegistryWide() {
+ BOOL is_wow;
+ IsWow64Process(GetCurrentProcess(), &is_wow);
+ return is_wow ? L"VulkanDriverNameWow" : L"VulkanDriverName";
+}
+
+// Get the key for the plug 'n play explicit layer registry
+// The string returned by this function should NOT be freed
+static inline const char *LoaderPnpELayerRegistry() {
+ BOOL is_wow;
+ IsWow64Process(GetCurrentProcess(), &is_wow);
+ return is_wow ? "VulkanExplicitLayersWow" : "VulkanExplicitLayers";
+}
+static inline const wchar_t *LoaderPnpELayerRegistryWide() {
+ BOOL is_wow;
+ IsWow64Process(GetCurrentProcess(), &is_wow);
+ return is_wow ? L"VulkanExplicitLayersWow" : L"VulkanExplicitLayers";
+}
+
+// Get the key for the plug 'n play implicit layer registry
+// The string returned by this function should NOT be freed
+static inline const char *LoaderPnpILayerRegistry() {
+ BOOL is_wow;
+ IsWow64Process(GetCurrentProcess(), &is_wow);
+ return is_wow ? "VulkanImplicitLayersWow" : "VulkanImplicitLayers";
+}
+static inline const wchar_t *LoaderPnpILayerRegistryWide() {
+ BOOL is_wow;
+ IsWow64Process(GetCurrentProcess(), &is_wow);
+ return is_wow ? L"VulkanImplicitLayersWow" : L"VulkanImplicitLayers";
+}
+#endif
+
+// File IO
+static bool loader_platform_file_exists(const char *path) {
+ if ((_access(path, 0)) == -1)
+ return false;
+ else
+ return true;
+}
+
+static bool loader_platform_is_path_absolute(const char *path) {
+ if (!path || !*path) {
+ return false;
+ }
+ if (*path == DIRECTORY_SYMBOL || path[1] == ':') {
+ return true;
+ }
+ return false;
+}
+
+// WIN32 runtime doesn't have dirname().
+static inline char *loader_platform_dirname(char *path) {
+ char *current, *next;
+
+ // TODO/TBD: Do we need to deal with the Windows's ":" character?
+
+ for (current = path; *current != '\0'; current = next) {
+ next = strchr(current, DIRECTORY_SYMBOL);
+ if (next == NULL) {
+ if (current != path) *(current - 1) = '\0';
+ return path;
+ } else {
+ // Point one character past the DIRECTORY_SYMBOL:
+ next++;
+ }
+ }
+ return path;
+}
+
+// Dynamic Loading:
+typedef HMODULE loader_platform_dl_handle;
+static loader_platform_dl_handle loader_platform_open_library(const char *lib_path) {
+ // Try loading the library the original way first.
+ loader_platform_dl_handle lib_handle = LoadLibrary(lib_path);
+ if (lib_handle == NULL && GetLastError() == ERROR_MOD_NOT_FOUND) {
+ // If that failed, then try loading it with broader search folders.
+ lib_handle = LoadLibraryEx(lib_path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
+ }
+ return lib_handle;
+}
+static char *loader_platform_open_library_error(const char *libPath) {
+ static char errorMsg[164];
+ (void)snprintf(errorMsg, 163, "Failed to open dynamic library \"%s\" with error %lu", libPath, GetLastError());
+ return errorMsg;
+}
+static void loader_platform_close_library(loader_platform_dl_handle library) { FreeLibrary(library); }
+static void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
+ assert(library);
+ assert(name);
+ return (void *)GetProcAddress(library, name);
+}
+static char *loader_platform_get_proc_address_error(const char *name) {
+ static char errorMsg[120];
+ (void)snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
+ return errorMsg;
+}
+
+// Threads:
+typedef HANDLE loader_platform_thread;
+
+// __declspec(thread) is not supported by MinGW compiler (ignored with warning or
+// cause error depending on compiler switches)
+//
+// __thread should be used instead
+//
+// __MINGW32__ defined for both 32 and 64 bit MinGW compilers, so it is enough to
+// detect any (32 or 64) flavor of MinGW compiler.
+//
+// @note __GNUC__ could be used as a more generic way to detect _any_
+// GCC[-compatible] compiler on Windows, but this fix was tested
+// only with MinGW, so keep it explicit at the moment.
+#if defined(__MINGW32__)
+#define THREAD_LOCAL_DECL __thread
+#else
+#define THREAD_LOCAL_DECL __declspec(thread)
+#endif
+
+// The once init functionality is not used when building a DLL on Windows. This is because there is no way to clean up the
+// resources allocated by anything allocated by once init. This isn't a problem for static libraries, but it is for dynamic
+// ones. When building a DLL, we use DllMain() instead to allow properly cleaning up resources.
+#if defined(LOADER_DYNAMIC_LIB)
+#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var)
+#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var)
+#define LOADER_PLATFORM_THREAD_ONCE(ctl, func)
+#else
+#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) INIT_ONCE var = INIT_ONCE_STATIC_INIT;
+#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) INIT_ONCE var;
+#define LOADER_PLATFORM_THREAD_ONCE(ctl, func) loader_platform_thread_once_fn(ctl, func)
+static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) {
+ void (*func)(void) = (void (*)(void))Parameter;
+ func();
+ return TRUE;
+}
+static void loader_platform_thread_once_fn(void *ctl, void (*func)(void)) {
+ assert(func != NULL);
+ assert(ctl != NULL);
+ InitOnceExecuteOnce((PINIT_ONCE)ctl, InitFuncWrapper, (void *)func, NULL);
+}
+#endif
+
+// Thread IDs:
+typedef DWORD loader_platform_thread_id;
+static loader_platform_thread_id loader_platform_get_thread_id() { return GetCurrentThreadId(); }
+
+// Thread mutex:
+typedef CRITICAL_SECTION loader_platform_thread_mutex;
+static void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) { InitializeCriticalSection(pMutex); }
+static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { EnterCriticalSection(pMutex); }
+static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { LeaveCriticalSection(pMutex); }
+static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { DeleteCriticalSection(pMutex); }
+typedef CONDITION_VARIABLE loader_platform_thread_cond;
+static void loader_platform_thread_init_cond(loader_platform_thread_cond *pCond) { InitializeConditionVariable(pCond); }
+static void loader_platform_thread_cond_wait(loader_platform_thread_cond *pCond, loader_platform_thread_mutex *pMutex) {
+ SleepConditionVariableCS(pCond, pMutex, INFINITE);
+}
+static void loader_platform_thread_cond_broadcast(loader_platform_thread_cond *pCond) { WakeAllConditionVariable(pCond); }
+
+#define loader_stack_alloc(size) _alloca(size)
+#else // defined(_WIN32)
+
+#error The "loader_platform.h" file must be modified for this OS.
+
+// NOTE: In order to support another OS, an #elif needs to be added (above the
+// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
+// contents of this file must be created.
+
+// NOTE: Other OS-specific changes are also needed for this OS. Search for
+// files with "WIN32" in it, as a quick way to find files that must be changed.
+
+#endif // defined(_WIN32)
+
+// returns true if the given string appears to be a relative or absolute
+// path, as opposed to a bare filename.
+static inline bool loader_platform_is_path(const char *path) { return strchr(path, DIRECTORY_SYMBOL) != NULL; }
diff --git a/thirdparty/vulkan/loader/vk_object_types.h b/thirdparty/vulkan/loader/vk_object_types.h
new file mode 100644
index 0000000000..7fdf77aa6a
--- /dev/null
+++ b/thirdparty/vulkan/loader/vk_object_types.h
@@ -0,0 +1,383 @@
+// *** THIS FILE IS GENERATED - DO NOT EDIT ***
+// See helper_file_generator.py for modifications
+
+
+/***************************************************************************
+ *
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ * Copyright (c) 2015-2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Mark Lobodzinski <mark@lunarg.com>
+ * Author: Courtney Goeltzenleuchter <courtneygo@google.com>
+ * Author: Tobin Ehlis <tobine@google.com>
+ * Author: Chris Forbes <chrisforbes@google.com>
+ * Author: John Zulauf<jzulauf@lunarg.com>
+ *
+ ****************************************************************************/
+
+
+#pragma once
+
+#include <vulkan/vulkan.h>
+
+// Object Type enum for validation layer internal object handling
+typedef enum VulkanObjectType {
+ kVulkanObjectTypeUnknown = 0,
+ kVulkanObjectTypeInstance = 1,
+ kVulkanObjectTypePhysicalDevice = 2,
+ kVulkanObjectTypeDevice = 3,
+ kVulkanObjectTypeQueue = 4,
+ kVulkanObjectTypeSemaphore = 5,
+ kVulkanObjectTypeCommandBuffer = 6,
+ kVulkanObjectTypeFence = 7,
+ kVulkanObjectTypeDeviceMemory = 8,
+ kVulkanObjectTypeBuffer = 9,
+ kVulkanObjectTypeImage = 10,
+ kVulkanObjectTypeEvent = 11,
+ kVulkanObjectTypeQueryPool = 12,
+ kVulkanObjectTypeBufferView = 13,
+ kVulkanObjectTypeImageView = 14,
+ kVulkanObjectTypeShaderModule = 15,
+ kVulkanObjectTypePipelineCache = 16,
+ kVulkanObjectTypePipelineLayout = 17,
+ kVulkanObjectTypeRenderPass = 18,
+ kVulkanObjectTypePipeline = 19,
+ kVulkanObjectTypeDescriptorSetLayout = 20,
+ kVulkanObjectTypeSampler = 21,
+ kVulkanObjectTypeDescriptorPool = 22,
+ kVulkanObjectTypeDescriptorSet = 23,
+ kVulkanObjectTypeFramebuffer = 24,
+ kVulkanObjectTypeCommandPool = 25,
+ kVulkanObjectTypeSamplerYcbcrConversion = 26,
+ kVulkanObjectTypeDescriptorUpdateTemplate = 27,
+ kVulkanObjectTypeSurfaceKHR = 28,
+ kVulkanObjectTypeSwapchainKHR = 29,
+ kVulkanObjectTypeDisplayKHR = 30,
+ kVulkanObjectTypeDisplayModeKHR = 31,
+ kVulkanObjectTypeDebugReportCallbackEXT = 32,
+ kVulkanObjectTypeObjectTableNVX = 33,
+ kVulkanObjectTypeIndirectCommandsLayoutNVX = 34,
+ kVulkanObjectTypeDebugUtilsMessengerEXT = 35,
+ kVulkanObjectTypeValidationCacheEXT = 36,
+ kVulkanObjectTypeAccelerationStructureNV = 37,
+ kVulkanObjectTypePerformanceConfigurationINTEL = 38,
+ kVulkanObjectTypeMax = 39,
+ // Aliases for backwards compatibilty of "promoted" types
+ kVulkanObjectTypeDescriptorUpdateTemplateKHR = kVulkanObjectTypeDescriptorUpdateTemplate,
+ kVulkanObjectTypeSamplerYcbcrConversionKHR = kVulkanObjectTypeSamplerYcbcrConversion,
+} VulkanObjectType;
+
+// Array of object name strings for OBJECT_TYPE enum conversion
+static const char * const object_string[kVulkanObjectTypeMax] = {
+ "Unknown",
+ "Instance",
+ "PhysicalDevice",
+ "Device",
+ "Queue",
+ "Semaphore",
+ "CommandBuffer",
+ "Fence",
+ "DeviceMemory",
+ "Buffer",
+ "Image",
+ "Event",
+ "QueryPool",
+ "BufferView",
+ "ImageView",
+ "ShaderModule",
+ "PipelineCache",
+ "PipelineLayout",
+ "RenderPass",
+ "Pipeline",
+ "DescriptorSetLayout",
+ "Sampler",
+ "DescriptorPool",
+ "DescriptorSet",
+ "Framebuffer",
+ "CommandPool",
+ "SamplerYcbcrConversion",
+ "DescriptorUpdateTemplate",
+ "SurfaceKHR",
+ "SwapchainKHR",
+ "DisplayKHR",
+ "DisplayModeKHR",
+ "DebugReportCallbackEXT",
+ "ObjectTableNVX",
+ "IndirectCommandsLayoutNVX",
+ "DebugUtilsMessengerEXT",
+ "ValidationCacheEXT",
+ "AccelerationStructureNV",
+ "PerformanceConfigurationINTEL",
+};
+
+// Helper array to get Vulkan VK_EXT_debug_report object type enum from the internal layers version
+const VkDebugReportObjectTypeEXT get_debug_report_enum[] = {
+ VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeUnknown
+ VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, // kVulkanObjectTypeInstance
+ VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, // kVulkanObjectTypePhysicalDevice
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, // kVulkanObjectTypeDevice
+ VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, // kVulkanObjectTypeQueue
+ VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, // kVulkanObjectTypeSemaphore
+ VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, // kVulkanObjectTypeCommandBuffer
+ VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, // kVulkanObjectTypeFence
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, // kVulkanObjectTypeDeviceMemory
+ VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, // kVulkanObjectTypeBuffer
+ VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, // kVulkanObjectTypeImage
+ VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, // kVulkanObjectTypeEvent
+ VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, // kVulkanObjectTypeQueryPool
+ VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT, // kVulkanObjectTypeBufferView
+ VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT, // kVulkanObjectTypeImageView
+ VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, // kVulkanObjectTypeShaderModule
+ VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT, // kVulkanObjectTypePipelineCache
+ VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT, // kVulkanObjectTypePipelineLayout
+ VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, // kVulkanObjectTypeRenderPass
+ VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, // kVulkanObjectTypePipeline
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, // kVulkanObjectTypeDescriptorSetLayout
+ VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, // kVulkanObjectTypeSampler
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, // kVulkanObjectTypeDescriptorPool
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, // kVulkanObjectTypeDescriptorSet
+ VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, // kVulkanObjectTypeFramebuffer
+ VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, // kVulkanObjectTypeCommandPool
+ VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, // kVulkanObjectTypeSamplerYcbcrConversion
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, // kVulkanObjectTypeDescriptorUpdateTemplate
+ VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT, // kVulkanObjectTypeSurfaceKHR
+ VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, // kVulkanObjectTypeSwapchainKHR
+ VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT, // kVulkanObjectTypeDisplayKHR
+ VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT, // kVulkanObjectTypeDisplayModeKHR
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, // kVulkanObjectTypeDebugReportCallbackEXT
+ VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT, // kVulkanObjectTypeObjectTableNVX
+ VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT, // kVulkanObjectTypeIndirectCommandsLayoutNVX
+ VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeDebugUtilsMessengerEXT
+ VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, // kVulkanObjectTypeValidationCacheEXT
+ VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT, // kVulkanObjectTypeAccelerationStructureNV
+ VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypePerformanceConfigurationINTEL
+};
+
+// Helper array to get Official Vulkan VkObjectType enum from the internal layers version
+const VkObjectType get_object_type_enum[] = {
+ VK_OBJECT_TYPE_UNKNOWN, // kVulkanObjectTypeUnknown
+ VK_OBJECT_TYPE_INSTANCE, // kVulkanObjectTypeInstance
+ VK_OBJECT_TYPE_PHYSICAL_DEVICE, // kVulkanObjectTypePhysicalDevice
+ VK_OBJECT_TYPE_DEVICE, // kVulkanObjectTypeDevice
+ VK_OBJECT_TYPE_QUEUE, // kVulkanObjectTypeQueue
+ VK_OBJECT_TYPE_SEMAPHORE, // kVulkanObjectTypeSemaphore
+ VK_OBJECT_TYPE_COMMAND_BUFFER, // kVulkanObjectTypeCommandBuffer
+ VK_OBJECT_TYPE_FENCE, // kVulkanObjectTypeFence
+ VK_OBJECT_TYPE_DEVICE_MEMORY, // kVulkanObjectTypeDeviceMemory
+ VK_OBJECT_TYPE_BUFFER, // kVulkanObjectTypeBuffer
+ VK_OBJECT_TYPE_IMAGE, // kVulkanObjectTypeImage
+ VK_OBJECT_TYPE_EVENT, // kVulkanObjectTypeEvent
+ VK_OBJECT_TYPE_QUERY_POOL, // kVulkanObjectTypeQueryPool
+ VK_OBJECT_TYPE_BUFFER_VIEW, // kVulkanObjectTypeBufferView
+ VK_OBJECT_TYPE_IMAGE_VIEW, // kVulkanObjectTypeImageView
+ VK_OBJECT_TYPE_SHADER_MODULE, // kVulkanObjectTypeShaderModule
+ VK_OBJECT_TYPE_PIPELINE_CACHE, // kVulkanObjectTypePipelineCache
+ VK_OBJECT_TYPE_PIPELINE_LAYOUT, // kVulkanObjectTypePipelineLayout
+ VK_OBJECT_TYPE_RENDER_PASS, // kVulkanObjectTypeRenderPass
+ VK_OBJECT_TYPE_PIPELINE, // kVulkanObjectTypePipeline
+ VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, // kVulkanObjectTypeDescriptorSetLayout
+ VK_OBJECT_TYPE_SAMPLER, // kVulkanObjectTypeSampler
+ VK_OBJECT_TYPE_DESCRIPTOR_POOL, // kVulkanObjectTypeDescriptorPool
+ VK_OBJECT_TYPE_DESCRIPTOR_SET, // kVulkanObjectTypeDescriptorSet
+ VK_OBJECT_TYPE_FRAMEBUFFER, // kVulkanObjectTypeFramebuffer
+ VK_OBJECT_TYPE_COMMAND_POOL, // kVulkanObjectTypeCommandPool
+ VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, // kVulkanObjectTypeSamplerYcbcrConversion
+ VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, // kVulkanObjectTypeDescriptorUpdateTemplate
+ VK_OBJECT_TYPE_SURFACE_KHR, // kVulkanObjectTypeSurfaceKHR
+ VK_OBJECT_TYPE_SWAPCHAIN_KHR, // kVulkanObjectTypeSwapchainKHR
+ VK_OBJECT_TYPE_DISPLAY_KHR, // kVulkanObjectTypeDisplayKHR
+ VK_OBJECT_TYPE_DISPLAY_MODE_KHR, // kVulkanObjectTypeDisplayModeKHR
+ VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT, // kVulkanObjectTypeDebugReportCallbackEXT
+ VK_OBJECT_TYPE_OBJECT_TABLE_NVX, // kVulkanObjectTypeObjectTableNVX
+ VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX, // kVulkanObjectTypeIndirectCommandsLayoutNVX
+ VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT, // kVulkanObjectTypeDebugUtilsMessengerEXT
+ VK_OBJECT_TYPE_VALIDATION_CACHE_EXT, // kVulkanObjectTypeValidationCacheEXT
+ VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV, // kVulkanObjectTypeAccelerationStructureNV
+ VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL, // kVulkanObjectTypePerformanceConfigurationINTEL
+};
+
+// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType
+static inline VkObjectType convertDebugReportObjectToCoreObject(VkDebugReportObjectTypeEXT debug_report_obj){
+ if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT) {
+ return VK_OBJECT_TYPE_UNKNOWN;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT) {
+ return VK_OBJECT_TYPE_UNKNOWN;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT) {
+ return VK_OBJECT_TYPE_INSTANCE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {
+ return VK_OBJECT_TYPE_PHYSICAL_DEVICE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT) {
+ return VK_OBJECT_TYPE_DEVICE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT) {
+ return VK_OBJECT_TYPE_QUEUE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT) {
+ return VK_OBJECT_TYPE_SEMAPHORE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT) {
+ return VK_OBJECT_TYPE_COMMAND_BUFFER;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT) {
+ return VK_OBJECT_TYPE_FENCE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT) {
+ return VK_OBJECT_TYPE_DEVICE_MEMORY;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT) {
+ return VK_OBJECT_TYPE_BUFFER;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT) {
+ return VK_OBJECT_TYPE_IMAGE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT) {
+ return VK_OBJECT_TYPE_EVENT;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT) {
+ return VK_OBJECT_TYPE_QUERY_POOL;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT) {
+ return VK_OBJECT_TYPE_BUFFER_VIEW;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT) {
+ return VK_OBJECT_TYPE_IMAGE_VIEW;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT) {
+ return VK_OBJECT_TYPE_SHADER_MODULE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT) {
+ return VK_OBJECT_TYPE_PIPELINE_CACHE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT) {
+ return VK_OBJECT_TYPE_PIPELINE_LAYOUT;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT) {
+ return VK_OBJECT_TYPE_RENDER_PASS;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT) {
+ return VK_OBJECT_TYPE_PIPELINE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT) {
+ return VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT) {
+ return VK_OBJECT_TYPE_SAMPLER;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT) {
+ return VK_OBJECT_TYPE_DESCRIPTOR_POOL;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT) {
+ return VK_OBJECT_TYPE_DESCRIPTOR_SET;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT) {
+ return VK_OBJECT_TYPE_FRAMEBUFFER;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT) {
+ return VK_OBJECT_TYPE_COMMAND_POOL;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT) {
+ return VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT) {
+ return VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {
+ return VK_OBJECT_TYPE_SURFACE_KHR;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT) {
+ return VK_OBJECT_TYPE_SWAPCHAIN_KHR;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT) {
+ return VK_OBJECT_TYPE_DISPLAY_KHR;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT) {
+ return VK_OBJECT_TYPE_DISPLAY_MODE_KHR;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT) {
+ return VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT) {
+ return VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT) {
+ return VK_OBJECT_TYPE_OBJECT_TABLE_NVX;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT) {
+ return VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT) {
+ return VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT) {
+ return VK_OBJECT_TYPE_VALIDATION_CACHE_EXT;
+ } else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT) {
+ return VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV;
+ }
+ return VK_OBJECT_TYPE_UNKNOWN;
+}
+
+// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType
+static inline VkDebugReportObjectTypeEXT convertCoreObjectToDebugReportObject(VkObjectType core_report_obj){
+ if (core_report_obj == VK_OBJECT_TYPE_UNKNOWN) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_UNKNOWN) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_INSTANCE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_DEVICE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_QUEUE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_SEMAPHORE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_COMMAND_BUFFER) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_FENCE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_DEVICE_MEMORY) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_BUFFER) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_IMAGE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_EVENT) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_QUERY_POOL) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_BUFFER_VIEW) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_IMAGE_VIEW) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_SHADER_MODULE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_PIPELINE_CACHE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_PIPELINE_LAYOUT) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_RENDER_PASS) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_PIPELINE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_SAMPLER) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_DESCRIPTOR_POOL) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_DESCRIPTOR_SET) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_FRAMEBUFFER) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_COMMAND_POOL) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_SURFACE_KHR) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_SWAPCHAIN_KHR) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_DISPLAY_KHR) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_DISPLAY_MODE_KHR) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_OBJECT_TABLE_NVX) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_VALIDATION_CACHE_EXT) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT;
+ } else if (core_report_obj == VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV) {
+ return VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT;
+ }
+ return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
+}
diff --git a/thirdparty/vulkan/loader/wsi.c b/thirdparty/vulkan/loader/wsi.c
new file mode 100644
index 0000000000..f8d8e5374c
--- /dev/null
+++ b/thirdparty/vulkan/loader/wsi.c
@@ -0,0 +1,2023 @@
+/*
+ * Copyright (c) 2015-2016, 2019 The Khronos Group Inc.
+ * Copyright (c) 2015-2016, 2019 Valve Corporation
+ * Copyright (c) 2015-2016, 2019 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Ian Elliott <ian@lunarg.com>
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Ian Elliott <ianelliott@google.com>
+ * Author: Mark Lobodzinski <mark@lunarg.com>
+ * Author: Lenny Komow <lenny@lunarg.com>
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "vk_loader_platform.h"
+#include "loader.h"
+#include "wsi.h"
+#include <vulkan/vk_icd.h>
+
+// The first ICD/Loader interface that support querying the SurfaceKHR from
+// the ICDs.
+#define ICD_VER_SUPPORTS_ICD_SURFACE_KHR 3
+
+void wsi_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
+ ptr_instance->wsi_surface_enabled = false;
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ ptr_instance->wsi_win32_surface_enabled = false;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ ptr_instance->wsi_wayland_surface_enabled = false;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ ptr_instance->wsi_xcb_surface_enabled = false;
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ ptr_instance->wsi_xlib_surface_enabled = false;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ ptr_instance->wsi_android_surface_enabled = false;
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ ptr_instance->wsi_macos_surface_enabled = false;
+#endif // VK_USE_PLATFORM_MACOS_MVK
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ ptr_instance->wsi_ios_surface_enabled = false;
+#endif // VK_USE_PLATFORM_IOS_MVK
+ ptr_instance->wsi_display_enabled = false;
+ ptr_instance->wsi_display_props2_enabled = false;
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ ptr_instance->wsi_metal_surface_enabled = false;
+#endif // VK_USE_PLATFORM_METAL_EXT
+
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_surface_enabled = true;
+ continue;
+ }
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_win32_surface_enabled = true;
+ continue;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_wayland_surface_enabled = true;
+ continue;
+ }
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_xcb_surface_enabled = true;
+ continue;
+ }
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_xlib_surface_enabled = true;
+ continue;
+ }
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_android_surface_enabled = true;
+ continue;
+ }
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_MVK_MACOS_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_macos_surface_enabled = true;
+ continue;
+ }
+#endif // VK_USE_PLATFORM_MACOS_MVK
+#ifdef VK_USE_PLATFORM_IOS_MVK
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_MVK_IOS_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_ios_surface_enabled = true;
+ continue;
+ }
+#endif // VK_USE_PLATFORM_IOS_MVK
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_headless_surface_enabled = true;
+ continue;
+ }
+#if defined(VK_USE_PLATFORM_METAL_EXT)
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_METAL_SURFACE_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_metal_surface_enabled = true;
+ continue;
+ }
+#endif
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_display_enabled = true;
+ continue;
+ }
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME) == 0) {
+ ptr_instance->wsi_display_props2_enabled = true;
+ continue;
+ }
+ }
+}
+
+// Linux WSI surface extensions are not always compiled into the loader. (Assume
+// for Windows the KHR_win32_surface is always compiled into loader). A given
+// Linux build environment might not have the headers required for building one
+// of the three extensions (Xlib, Xcb, Wayland). Thus, need to check if
+// the built loader actually supports the particular Linux surface extension.
+// If not supported by the built loader it will not be included in the list of
+// enumerated instance extensions. This solves the issue where an ICD or layer
+// advertises support for a given Linux surface extension but the loader was not
+// built to support the extension.
+bool wsi_unsupported_instance_extension(const VkExtensionProperties *ext_prop) {
+#ifndef VK_USE_PLATFORM_WAYLAND_KHR
+ if (!strcmp(ext_prop->extensionName, "VK_KHR_wayland_surface")) return true;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifndef VK_USE_PLATFORM_XCB_KHR
+ if (!strcmp(ext_prop->extensionName, "VK_KHR_xcb_surface")) return true;
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifndef VK_USE_PLATFORM_XLIB_KHR
+ if (!strcmp(ext_prop->extensionName, "VK_KHR_xlib_surface")) return true;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+
+ return false;
+}
+
+// Functions for the VK_KHR_surface extension:
+
+// This is the trampoline entrypoint for DestroySurfaceKHR
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ disp->DestroySurfaceKHR(instance, surface, pAllocator);
+}
+
+// TODO probably need to lock around all the loader_get_instance() calls.
+
+// This is the instance chain terminator function for DestroySurfaceKHR
+VKAPI_ATTR void VKAPI_CALL terminator_DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
+ const VkAllocationCallbacks *pAllocator) {
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
+ if (NULL != icd_surface) {
+ if (NULL != icd_surface->real_icd_surfaces) {
+ uint32_t i = 0;
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+ if (NULL != icd_term->dispatch.DestroySurfaceKHR && (VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[i]) {
+ icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, icd_surface->real_icd_surfaces[i], pAllocator);
+ icd_surface->real_icd_surfaces[i] = (VkSurfaceKHR)NULL;
+ }
+ } else {
+ // The real_icd_surface for any ICD not supporting the
+ // proper interface version should be NULL. If not, then
+ // we have a problem.
+ assert((VkSurfaceKHR)NULL == icd_surface->real_icd_surfaces[i]);
+ }
+ }
+ loader_instance_heap_free(ptr_instance, icd_surface->real_icd_surfaces);
+ }
+
+ loader_instance_heap_free(ptr_instance, (void *)(uintptr_t)surface);
+ }
+}
+
+// This is the trampoline entrypoint for GetPhysicalDeviceSurfaceSupportKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex, VkSurfaceKHR surface,
+ VkBool32 *pSupported) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkResult res = disp->GetPhysicalDeviceSurfaceSupportKHR(unwrapped_phys_dev, queueFamilyIndex, surface, pSupported);
+ return res;
+}
+
+// This is the instance chain terminator function for
+// GetPhysicalDeviceSurfaceSupportKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex, VkSurfaceKHR surface,
+ VkBool32 *pSupported) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_surface extension not enabled. vkGetPhysicalDeviceSurfaceSupportKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == pSupported) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "NULL pointer passed into vkGetPhysicalDeviceSurfaceSupportKHR for pSupported!\n");
+ assert(false && "GetPhysicalDeviceSurfaceSupportKHR: Error, null pSupported");
+ }
+ *pSupported = false;
+
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfaceSupportKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetPhysicalDeviceSurfaceSupportKHR!\n");
+ assert(false && "loader: null GetPhysicalDeviceSurfaceSupportKHR ICD pointer");
+ }
+
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
+ if (NULL != icd_surface->real_icd_surfaces && (VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[phys_dev_term->icd_index]) {
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceSupportKHR(
+ phys_dev_term->phys_dev, queueFamilyIndex, icd_surface->real_icd_surfaces[phys_dev_term->icd_index], pSupported);
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex, surface, pSupported);
+}
+
+// This is the trampoline entrypoint for GetPhysicalDeviceSurfaceCapabilitiesKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
+ VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkResult res = disp->GetPhysicalDeviceSurfaceCapabilitiesKHR(unwrapped_phys_dev, surface, pSurfaceCapabilities);
+ return res;
+}
+
+// This is the instance chain terminator function for
+// GetPhysicalDeviceSurfaceCapabilitiesKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_surface extension not enabled. vkGetPhysicalDeviceSurfaceCapabilitiesKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == pSurfaceCapabilities) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "NULL pointer passed into vkGetPhysicalDeviceSurfaceCapabilitiesKHR for pSurfaceCapabilities!\n");
+ assert(false && "GetPhysicalDeviceSurfaceCapabilitiesKHR: Error, null pSurfaceCapabilities");
+ }
+
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetPhysicalDeviceSurfaceCapabilitiesKHR!\n");
+ assert(false && "loader: null GetPhysicalDeviceSurfaceCapabilitiesKHR ICD pointer");
+ }
+
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
+ if (NULL != icd_surface->real_icd_surfaces && (VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[phys_dev_term->icd_index]) {
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(
+ phys_dev_term->phys_dev, icd_surface->real_icd_surfaces[phys_dev_term->icd_index], pSurfaceCapabilities);
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, surface, pSurfaceCapabilities);
+}
+
+// This is the trampoline entrypoint for GetPhysicalDeviceSurfaceFormatsKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t *pSurfaceFormatCount,
+ VkSurfaceFormatKHR *pSurfaceFormats) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkResult res = disp->GetPhysicalDeviceSurfaceFormatsKHR(unwrapped_phys_dev, surface, pSurfaceFormatCount, pSurfaceFormats);
+ return res;
+}
+
+// This is the instance chain terminator function for
+// GetPhysicalDeviceSurfaceFormatsKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
+ uint32_t *pSurfaceFormatCount,
+ VkSurfaceFormatKHR *pSurfaceFormats) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_surface extension not enabled. vkGetPhysicalDeviceSurfaceFormatsKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == pSurfaceFormatCount) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "NULL pointer passed into vkGetPhysicalDeviceSurfaceFormatsKHR for pSurfaceFormatCount!\n");
+ assert(false && "GetPhysicalDeviceSurfaceFormatsKHR(: Error, null pSurfaceFormatCount");
+ }
+
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetPhysicalDeviceSurfaceCapabilitiesKHR!\n");
+ assert(false && "loader: null GetPhysicalDeviceSurfaceFormatsKHR ICD pointer");
+ }
+
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
+ if (NULL != icd_surface->real_icd_surfaces && (VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[phys_dev_term->icd_index]) {
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev,
+ icd_surface->real_icd_surfaces[phys_dev_term->icd_index],
+ pSurfaceFormatCount, pSurfaceFormats);
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface, pSurfaceFormatCount,
+ pSurfaceFormats);
+}
+
+// This is the trampoline entrypoint for GetPhysicalDeviceSurfacePresentModesKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t *pPresentModeCount,
+ VkPresentModeKHR *pPresentModes) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkResult res = disp->GetPhysicalDeviceSurfacePresentModesKHR(unwrapped_phys_dev, surface, pPresentModeCount, pPresentModes);
+ return res;
+}
+
+// This is the instance chain terminator function for
+// GetPhysicalDeviceSurfacePresentModesKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface, uint32_t *pPresentModeCount,
+ VkPresentModeKHR *pPresentModes) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_surface extension not enabled. vkGetPhysicalDeviceSurfacePresentModesKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == pPresentModeCount) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "NULL pointer passed into vkGetPhysicalDeviceSurfacePresentModesKHR for pPresentModeCount!\n");
+ assert(false && "GetPhysicalDeviceSurfacePresentModesKHR(: Error, null pPresentModeCount");
+ }
+
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetPhysicalDeviceSurfacePresentModesKHR!\n");
+ assert(false && "loader: null GetPhysicalDeviceSurfacePresentModesKHR ICD pointer");
+ }
+
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
+ if (NULL != icd_surface->real_icd_surfaces && (VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[phys_dev_term->icd_index]) {
+ return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(
+ phys_dev_term->phys_dev, icd_surface->real_icd_surfaces[phys_dev_term->icd_index], pPresentModeCount, pPresentModes);
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(phys_dev_term->phys_dev, surface, pPresentModeCount,
+ pPresentModes);
+}
+
+// Functions for the VK_KHR_swapchain extension:
+
+// This is the trampoline entrypoint for CreateSwapchainKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSwapchainKHR *pSwapchain) {
+ const VkLayerDispatchTable *disp;
+ disp = loader_get_dispatch(device);
+ return disp->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pCreateInfo->surface;
+ if (NULL != icd_surface->real_icd_surfaces) {
+ if ((VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[icd_index]) {
+ // We found the ICD, and there is an ICD KHR surface
+ // associated with it, so copy the CreateInfo struct
+ // and point it at the ICD's surface.
+ VkSwapchainCreateInfoKHR *pCreateCopy = loader_stack_alloc(sizeof(VkSwapchainCreateInfoKHR));
+ if (NULL == pCreateCopy) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memcpy(pCreateCopy, pCreateInfo, sizeof(VkSwapchainCreateInfoKHR));
+ pCreateCopy->surface = icd_surface->real_icd_surfaces[icd_index];
+ return icd_term->dispatch.CreateSwapchainKHR(device, pCreateCopy, pAllocator, pSwapchain);
+ }
+ }
+ return icd_term->dispatch.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
+ }
+ return VK_SUCCESS;
+}
+
+// This is the trampoline entrypoint for DestroySwapchainKHR
+LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
+ const VkAllocationCallbacks *pAllocator) {
+ const VkLayerDispatchTable *disp;
+ disp = loader_get_dispatch(device);
+ disp->DestroySwapchainKHR(device, swapchain, pAllocator);
+}
+
+// This is the trampoline entrypoint for GetSwapchainImagesKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain,
+ uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
+ const VkLayerDispatchTable *disp;
+ disp = loader_get_dispatch(device);
+ return disp->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
+}
+
+// This is the trampoline entrypoint for AcquireNextImageKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
+ VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
+ const VkLayerDispatchTable *disp;
+ disp = loader_get_dispatch(device);
+ return disp->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
+}
+
+// This is the trampoline entrypoint for QueuePresentKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
+ const VkLayerDispatchTable *disp;
+ disp = loader_get_dispatch(queue);
+ return disp->QueuePresentKHR(queue, pPresentInfo);
+}
+
+static VkIcdSurface *AllocateIcdSurfaceStruct(struct loader_instance *instance, size_t base_size, size_t platform_size) {
+ // Next, if so, proceed with the implementation of this function:
+ VkIcdSurface *pIcdSurface = loader_instance_heap_alloc(instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (pIcdSurface != NULL) {
+ // Setup the new sizes and offsets so we can grow the structures in the
+ // future without having problems
+ pIcdSurface->base_size = (uint32_t)base_size;
+ pIcdSurface->platform_size = (uint32_t)platform_size;
+ pIcdSurface->non_platform_offset = (uint32_t)((uint8_t *)(&pIcdSurface->base_size) - (uint8_t *)pIcdSurface);
+ pIcdSurface->entire_size = sizeof(VkIcdSurface);
+
+ pIcdSurface->real_icd_surfaces = loader_instance_heap_alloc(instance, sizeof(VkSurfaceKHR) * instance->total_icd_count,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (pIcdSurface->real_icd_surfaces == NULL) {
+ loader_instance_heap_free(instance, pIcdSurface);
+ pIcdSurface = NULL;
+ } else {
+ memset(pIcdSurface->real_icd_surfaces, 0, sizeof(VkSurfaceKHR) * instance->total_icd_count);
+ }
+ }
+ return pIcdSurface;
+}
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+// Functions for the VK_KHR_win32_surface extension:
+
+// This is the trampoline entrypoint for CreateWin32SurfaceKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(VkInstance instance,
+ const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+ return res;
+}
+
+// This is the instance chain terminator function for CreateWin32SurfaceKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ VkResult vkRes = VK_SUCCESS;
+ VkIcdSurface *pIcdSurface = NULL;
+ uint32_t i = 0;
+
+ // Initialize pSurface to NULL just to be safe.
+ *pSurface = VK_NULL_HANDLE;
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (!ptr_instance->wsi_win32_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_win32_surface extension not enabled. vkCreateWin32SurfaceKHR not executed!\n");
+ vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ pIcdSurface = AllocateIcdSurfaceStruct(ptr_instance, sizeof(pIcdSurface->win_surf.base), sizeof(pIcdSurface->win_surf));
+ if (pIcdSurface == NULL) {
+ vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ pIcdSurface->win_surf.base.platform = VK_ICD_WSI_PLATFORM_WIN32;
+ pIcdSurface->win_surf.hinstance = pCreateInfo->hinstance;
+ pIcdSurface->win_surf.hwnd = pCreateInfo->hwnd;
+
+ // Loop through each ICD and determine if they need to create a surface
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+ if (NULL != icd_term->dispatch.CreateWin32SurfaceKHR) {
+ vkRes = icd_term->dispatch.CreateWin32SurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
+ &pIcdSurface->real_icd_surfaces[i]);
+ if (VK_SUCCESS != vkRes) {
+ goto out;
+ }
+ }
+ }
+ }
+
+ *pSurface = (VkSurfaceKHR)(pIcdSurface);
+
+out:
+
+ if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+ if (NULL != pIcdSurface->real_icd_surfaces) {
+ i = 0;
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if ((VkSurfaceKHR)NULL != pIcdSurface->real_icd_surfaces[i] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
+ icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+ }
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface);
+ }
+
+ return vkRes;
+}
+
+// This is the trampoline entrypoint for
+// GetPhysicalDeviceWin32PresentationSupportKHR
+LOADER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkBool32 res = disp->GetPhysicalDeviceWin32PresentationSupportKHR(unwrapped_phys_dev, queueFamilyIndex);
+ return res;
+}
+
+// This is the instance chain terminator function for
+// GetPhysicalDeviceWin32PresentationSupportKHR
+VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_win32_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_win32_surface extension not enabled. vkGetPhysicalDeviceWin32PresentationSupportKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceWin32PresentationSupportKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetPhysicalDeviceWin32PresentationSupportKHR!\n");
+ assert(false && "loader: null GetPhysicalDeviceWin32PresentationSupportKHR ICD pointer");
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceWin32PresentationSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex);
+}
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+
+// This is the trampoline entrypoint for CreateWaylandSurfaceKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(VkInstance instance,
+ const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+ return res;
+}
+
+// This is the instance chain terminator function for CreateWaylandSurfaceKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWaylandSurfaceKHR(VkInstance instance,
+ const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ VkResult vkRes = VK_SUCCESS;
+ VkIcdSurface *pIcdSurface = NULL;
+ uint32_t i = 0;
+
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (!ptr_instance->wsi_wayland_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_wayland_surface extension not enabled. vkCreateWaylandSurfaceKHR not executed!\n");
+ vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ pIcdSurface = AllocateIcdSurfaceStruct(ptr_instance, sizeof(pIcdSurface->wayland_surf.base), sizeof(pIcdSurface->wayland_surf));
+ if (pIcdSurface == NULL) {
+ vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ pIcdSurface->wayland_surf.base.platform = VK_ICD_WSI_PLATFORM_WAYLAND;
+ pIcdSurface->wayland_surf.display = pCreateInfo->display;
+ pIcdSurface->wayland_surf.surface = pCreateInfo->surface;
+
+ // Loop through each ICD and determine if they need to create a surface
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+ if (NULL != icd_term->dispatch.CreateWaylandSurfaceKHR) {
+ vkRes = icd_term->dispatch.CreateWaylandSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
+ &pIcdSurface->real_icd_surfaces[i]);
+ if (VK_SUCCESS != vkRes) {
+ goto out;
+ }
+ }
+ }
+ }
+
+ *pSurface = (VkSurfaceKHR)pIcdSurface;
+
+out:
+
+ if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+ if (NULL != pIcdSurface->real_icd_surfaces) {
+ i = 0;
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if ((VkSurfaceKHR)NULL != pIcdSurface->real_icd_surfaces[i] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
+ icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+ }
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface);
+ }
+
+ return vkRes;
+}
+
+// This is the trampoline entrypoint for
+// GetPhysicalDeviceWaylandPresentationSupportKHR
+LOADER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ struct wl_display *display) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkBool32 res = disp->GetPhysicalDeviceWaylandPresentationSupportKHR(unwrapped_phys_dev, queueFamilyIndex, display);
+ return res;
+}
+
+// This is the instance chain terminator function for
+// GetPhysicalDeviceWaylandPresentationSupportKHR
+VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ struct wl_display *display) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_wayland_surface_enabled) {
+ loader_log(
+ ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_wayland_surface extension not enabled. vkGetPhysicalDeviceWaylandPresentationSupportKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceWaylandPresentationSupportKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetPhysicalDeviceWaylandPresentationSupportKHR!\n");
+ assert(false && "loader: null GetPhysicalDeviceWaylandPresentationSupportKHR ICD pointer");
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceWaylandPresentationSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex, display);
+}
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+
+// Functions for the VK_KHR_xcb_surface extension:
+
+// This is the trampoline entrypoint for CreateXcbSurfaceKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(VkInstance instance,
+ const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+ return res;
+}
+
+// This is the instance chain terminator function for CreateXcbSurfaceKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ VkResult vkRes = VK_SUCCESS;
+ VkIcdSurface *pIcdSurface = NULL;
+ uint32_t i = 0;
+
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (!ptr_instance->wsi_xcb_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_xcb_surface extension not enabled. vkCreateXcbSurfaceKHR not executed!\n");
+ vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ pIcdSurface = AllocateIcdSurfaceStruct(ptr_instance, sizeof(pIcdSurface->xcb_surf.base), sizeof(pIcdSurface->xcb_surf));
+ if (pIcdSurface == NULL) {
+ vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ pIcdSurface->xcb_surf.base.platform = VK_ICD_WSI_PLATFORM_XCB;
+ pIcdSurface->xcb_surf.connection = pCreateInfo->connection;
+ pIcdSurface->xcb_surf.window = pCreateInfo->window;
+
+ // Loop through each ICD and determine if they need to create a surface
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+ if (NULL != icd_term->dispatch.CreateXcbSurfaceKHR) {
+ vkRes = icd_term->dispatch.CreateXcbSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
+ &pIcdSurface->real_icd_surfaces[i]);
+ if (VK_SUCCESS != vkRes) {
+ goto out;
+ }
+ }
+ }
+ }
+
+ *pSurface = (VkSurfaceKHR)pIcdSurface;
+
+out:
+
+ if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+ if (NULL != pIcdSurface->real_icd_surfaces) {
+ i = 0;
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if ((VkSurfaceKHR)NULL != pIcdSurface->real_icd_surfaces[i] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
+ icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+ }
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface);
+ }
+
+ return vkRes;
+}
+
+// This is the trampoline entrypoint for
+// GetPhysicalDeviceXcbPresentationSupportKHR
+LOADER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ xcb_connection_t *connection,
+ xcb_visualid_t visual_id) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkBool32 res = disp->GetPhysicalDeviceXcbPresentationSupportKHR(unwrapped_phys_dev, queueFamilyIndex, connection, visual_id);
+ return res;
+}
+
+// This is the instance chain terminator function for
+// GetPhysicalDeviceXcbPresentationSupportKHR
+VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ xcb_connection_t *connection,
+ xcb_visualid_t visual_id) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_xcb_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_xcb_surface extension not enabled. vkGetPhysicalDeviceXcbPresentationSupportKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceXcbPresentationSupportKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetPhysicalDeviceXcbPresentationSupportKHR!\n");
+ assert(false && "loader: null GetPhysicalDeviceXcbPresentationSupportKHR ICD pointer");
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceXcbPresentationSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex, connection,
+ visual_id);
+}
+#endif // VK_USE_PLATFORM_XCB_KHR
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+
+// Functions for the VK_KHR_xlib_surface extension:
+
+// This is the trampoline entrypoint for CreateXlibSurfaceKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(VkInstance instance,
+ const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+ return res;
+}
+
+// This is the instance chain terminator function for CreateXlibSurfaceKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ VkResult vkRes = VK_SUCCESS;
+ VkIcdSurface *pIcdSurface = NULL;
+ uint32_t i = 0;
+
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (!ptr_instance->wsi_xlib_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_xlib_surface extension not enabled. vkCreateXlibSurfaceKHR not executed!\n");
+ vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ pIcdSurface = AllocateIcdSurfaceStruct(ptr_instance, sizeof(pIcdSurface->xlib_surf.base), sizeof(pIcdSurface->xlib_surf));
+ if (pIcdSurface == NULL) {
+ vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ pIcdSurface->xlib_surf.base.platform = VK_ICD_WSI_PLATFORM_XLIB;
+ pIcdSurface->xlib_surf.dpy = pCreateInfo->dpy;
+ pIcdSurface->xlib_surf.window = pCreateInfo->window;
+
+ // Loop through each ICD and determine if they need to create a surface
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+ if (NULL != icd_term->dispatch.CreateXlibSurfaceKHR) {
+ vkRes = icd_term->dispatch.CreateXlibSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
+ &pIcdSurface->real_icd_surfaces[i]);
+ if (VK_SUCCESS != vkRes) {
+ goto out;
+ }
+ }
+ }
+ }
+
+ *pSurface = (VkSurfaceKHR)pIcdSurface;
+
+out:
+
+ if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+ if (NULL != pIcdSurface->real_icd_surfaces) {
+ i = 0;
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if ((VkSurfaceKHR)NULL != pIcdSurface->real_icd_surfaces[i] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
+ icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+ }
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface);
+ }
+
+ return vkRes;
+}
+
+// This is the trampoline entrypoint for
+// GetPhysicalDeviceXlibPresentationSupportKHR
+LOADER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex, Display *dpy,
+ VisualID visualID) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkBool32 res = disp->GetPhysicalDeviceXlibPresentationSupportKHR(unwrapped_phys_dev, queueFamilyIndex, dpy, visualID);
+ return res;
+}
+
+// This is the instance chain terminator function for
+// GetPhysicalDeviceXlibPresentationSupportKHR
+VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex, Display *dpy,
+ VisualID visualID) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_xlib_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_xlib_surface extension not enabled. vkGetPhysicalDeviceXlibPresentationSupportKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceXlibPresentationSupportKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetPhysicalDeviceXlibPresentationSupportKHR!\n");
+ assert(false && "loader: null GetPhysicalDeviceXlibPresentationSupportKHR ICD pointer");
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceXlibPresentationSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex, dpy, visualID);
+}
+#endif // VK_USE_PLATFORM_XLIB_KHR
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+
+// Functions for the VK_KHR_android_surface extension:
+
+// This is the trampoline entrypoint for CreateAndroidSurfaceKHR
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(VkInstance instance, ANativeWindow *window,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateAndroidSurfaceKHR(instance, window, pAllocator, pSurface);
+ return res;
+}
+
+// This is the instance chain terminator function for CreateAndroidSurfaceKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateAndroidSurfaceKHR(VkInstance instance, Window window,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (!ptr_instance->wsi_display_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_display extension not enabled. vkCreateAndroidSurfaceKHR not executed!\n");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ VkIcdSurfaceAndroid *pIcdSurface =
+ loader_instance_heap_alloc(ptr_instance, sizeof(VkIcdSurfaceAndroid), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (pIcdSurface == NULL) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_ANDROID;
+ pIcdSurface->window = window;
+
+ *pSurface = (VkSurfaceKHR)pIcdSurface;
+
+ return VK_SUCCESS;
+}
+
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+// Functions for the VK_EXT_headless_surface extension:
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateHeadlessSurfaceEXT(instance, pCreateInfo, pAllocator, pSurface);
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateHeadlessSurfaceEXT(VkInstance instance,
+ const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ VkIcdSurface *pIcdSurface = NULL;
+ VkResult vkRes = VK_SUCCESS;
+ uint32_t i = 0;
+
+ if (!inst->wsi_headless_surface_enabled) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_EXT_headless_surface extension not enabled. "
+ "vkCreateHeadlessSurfaceEXT not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ pIcdSurface = AllocateIcdSurfaceStruct(inst, sizeof(pIcdSurface->headless_surf.base), sizeof(pIcdSurface->headless_surf));
+ if (pIcdSurface == NULL) {
+ vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ pIcdSurface->headless_surf.base.platform = VK_ICD_WSI_PLATFORM_HEADLESS;
+ // Loop through each ICD and determine if they need to create a surface
+ for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+ if (NULL != icd_term->dispatch.CreateHeadlessSurfaceEXT) {
+ vkRes = icd_term->dispatch.CreateHeadlessSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator,
+ &pIcdSurface->real_icd_surfaces[i]);
+ if (VK_SUCCESS != vkRes) {
+ goto out;
+ }
+ }
+ }
+ }
+
+ *pSurface = (VkSurfaceKHR)pIcdSurface;
+
+out:
+
+ if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+ if (NULL != pIcdSurface->real_icd_surfaces) {
+ i = 0;
+ for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if ((VkSurfaceKHR)NULL != pIcdSurface->real_icd_surfaces[i] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
+ icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+ }
+ }
+ loader_instance_heap_free(inst, pIcdSurface->real_icd_surfaces);
+ }
+ loader_instance_heap_free(inst, pIcdSurface);
+ }
+
+ return vkRes;
+}
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+
+// Functions for the VK_MVK_macos_surface extension:
+
+// This is the trampoline entrypoint for CreateMacOSSurfaceMVK
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(VkInstance instance,
+ const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateMacOSSurfaceMVK(instance, pCreateInfo, pAllocator, pSurface);
+ return res;
+}
+
+// This is the instance chain terminator function for CreateMacOSSurfaceKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ VkResult vkRes = VK_SUCCESS;
+ VkIcdSurface *pIcdSurface = NULL;
+ uint32_t i = 0;
+
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (!ptr_instance->wsi_macos_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_MVK_macos_surface extension not enabled. vkCreateMacOSSurfaceMVK not executed!\n");
+ vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ pIcdSurface = AllocateIcdSurfaceStruct(ptr_instance, sizeof(pIcdSurface->macos_surf.base), sizeof(pIcdSurface->macos_surf));
+ if (pIcdSurface == NULL) {
+ vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ pIcdSurface->macos_surf.base.platform = VK_ICD_WSI_PLATFORM_MACOS;
+ pIcdSurface->macos_surf.pView = pCreateInfo->pView;
+
+ // Loop through each ICD and determine if they need to create a surface
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+ if (NULL != icd_term->dispatch.CreateMacOSSurfaceMVK) {
+ vkRes = icd_term->dispatch.CreateMacOSSurfaceMVK(icd_term->instance, pCreateInfo, pAllocator,
+ &pIcdSurface->real_icd_surfaces[i]);
+ if (VK_SUCCESS != vkRes) {
+ goto out;
+ }
+ }
+ }
+ }
+
+ *pSurface = (VkSurfaceKHR)pIcdSurface;
+
+out:
+
+ if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+ if (NULL != pIcdSurface->real_icd_surfaces) {
+ i = 0;
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if ((VkSurfaceKHR)NULL != pIcdSurface->real_icd_surfaces[i] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
+ icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+ }
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface->real_icd_surfaces);
+ }
+ loader_instance_heap_free(ptr_instance, pIcdSurface);
+ }
+
+ return vkRes;
+}
+
+#endif // VK_USE_PLATFORM_MACOS_MVK
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+
+// Functions for the VK_MVK_ios_surface extension:
+
+// This is the trampoline entrypoint for CreateIOSSurfaceMVK
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK(VkInstance instance,
+ const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateIOSSurfaceMVK(instance, pCreateInfo, pAllocator, pSurface);
+ return res;
+}
+
+// This is the instance chain terminator function for CreateIOSSurfaceKHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (!ptr_instance->wsi_ios_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_MVK_ios_surface extension not enabled. vkCreateIOSSurfaceMVK not executed!\n");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ VkIcdSurfaceIOS *pIcdSurface =
+ loader_instance_heap_alloc(ptr_instance, sizeof(VkIcdSurfaceIOS), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (pIcdSurface == NULL) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_IOS;
+ pIcdSurface->pView = pCreateInfo->pView;
+
+ *pSurface = (VkSurfaceKHR)pIcdSurface;
+
+ return VK_SUCCESS;
+}
+
+#endif // VK_USE_PLATFORM_IOS_MVK
+
+#if defined(VK_USE_PLATFORM_METAL_EXT)
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT(VkInstance instance,
+ const VkMetalSurfaceCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(instance);
+ return disp->CreateMetalSurfaceEXT(instance, pCreateInfo, pAllocator, pSurface);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance instance, const VkMetalSurfaceCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ VkResult result = VK_SUCCESS;
+ VkIcdSurface *icd_surface = NULL;
+ uint32_t i;
+
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_instance *ptr_instance = loader_get_instance(instance);
+ if (!ptr_instance->wsi_metal_surface_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_EXT_metal_surface extension not enabled. vkCreateMetalSurfaceEXT will not be executed.\n");
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ icd_surface = AllocateIcdSurfaceStruct(ptr_instance, sizeof(icd_surface->metal_surf.base), sizeof(icd_surface->metal_surf));
+ if (icd_surface == NULL) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ icd_surface->metal_surf.base.platform = VK_ICD_WSI_PLATFORM_METAL;
+ icd_surface->metal_surf.pLayer = pCreateInfo->pLayer;
+
+ // Loop through each ICD and determine if they need to create a surface
+ i = 0;
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, ++i) {
+ if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+ if (icd_term->dispatch.CreateMetalSurfaceEXT != NULL) {
+ result = icd_term->dispatch.CreateMetalSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator,
+ &icd_surface->real_icd_surfaces[i]);
+ if (result != VK_SUCCESS) {
+ goto out;
+ }
+ }
+ }
+ }
+ *pSurface = (VkSurfaceKHR)icd_surface;
+
+out:
+ if (result != VK_SUCCESS && icd_surface != NULL) {
+ if (icd_surface->real_icd_surfaces != NULL) {
+ i = 0;
+ for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, ++i) {
+ if (icd_surface->real_icd_surfaces[i] == VK_NULL_HANDLE && icd_term->dispatch.DestroySurfaceKHR != NULL) {
+ icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, icd_surface->real_icd_surfaces[i], pAllocator);
+ }
+ }
+ loader_instance_heap_free(ptr_instance, icd_surface->real_icd_surfaces);
+ }
+ loader_instance_heap_free(ptr_instance, icd_surface);
+ }
+ return result;
+}
+
+#endif
+
+// Functions for the VK_KHR_display instance extension:
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPropertiesKHR *pProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkResult res = disp->GetPhysicalDeviceDisplayPropertiesKHR(unwrapped_phys_dev, pPropertyCount, pProperties);
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPropertiesKHR *pProperties) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_display_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_display extension not enabled. vkGetPhysicalDeviceDisplayPropertiesKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceDisplayPropertiesKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetPhysicalDeviceDisplayPropertiesKHR!\n");
+ assert(false && "loader: null GetPhysicalDeviceDisplayPropertiesKHR ICD pointer");
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceDisplayPropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, pProperties);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR(
+ VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPlanePropertiesKHR *pProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkResult res = disp->GetPhysicalDeviceDisplayPlanePropertiesKHR(unwrapped_phys_dev, pPropertyCount, pProperties);
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPlanePropertiesKHR *pProperties) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_display_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_display extension not enabled. vkGetPhysicalDeviceDisplayPlanePropertiesKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetPhysicalDeviceDisplayPlanePropertiesKHR!\n");
+ assert(false && "loader: null GetPhysicalDeviceDisplayPlanePropertiesKHR ICD pointer");
+ }
+
+ return icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, pProperties);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,
+ uint32_t planeIndex, uint32_t *pDisplayCount,
+ VkDisplayKHR *pDisplays) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkResult res = disp->GetDisplayPlaneSupportedDisplaysKHR(unwrapped_phys_dev, planeIndex, pDisplayCount, pDisplays);
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex,
+ uint32_t *pDisplayCount, VkDisplayKHR *pDisplays) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_display_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_display extension not enabled. vkGetDisplayPlaneSupportedDisplaysKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == icd_term->dispatch.GetDisplayPlaneSupportedDisplaysKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetDisplayPlaneSupportedDisplaysKHR!\n");
+ assert(false && "loader: null GetDisplayPlaneSupportedDisplaysKHR ICD pointer");
+ }
+
+ return icd_term->dispatch.GetDisplayPlaneSupportedDisplaysKHR(phys_dev_term->phys_dev, planeIndex, pDisplayCount, pDisplays);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+ uint32_t *pPropertyCount,
+ VkDisplayModePropertiesKHR *pProperties) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkResult res = disp->GetDisplayModePropertiesKHR(unwrapped_phys_dev, display, pPropertyCount, pProperties);
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+ uint32_t *pPropertyCount,
+ VkDisplayModePropertiesKHR *pProperties) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_display_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_display extension not enabled. vkGetDisplayModePropertiesKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == icd_term->dispatch.GetDisplayModePropertiesKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetDisplayModePropertiesKHR!\n");
+ assert(false && "loader: null GetDisplayModePropertiesKHR ICD pointer");
+ }
+
+ return icd_term->dispatch.GetDisplayModePropertiesKHR(phys_dev_term->phys_dev, display, pPropertyCount, pProperties);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+ const VkDisplayModeCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDisplayModeKHR *pMode) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkResult res = disp->CreateDisplayModeKHR(unwrapped_phys_dev, display, pCreateInfo, pAllocator, pMode);
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+ const VkDisplayModeCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDisplayModeKHR *pMode) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_display_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_display extension not enabled. vkCreateDisplayModeKHR not executed!\n");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ if (NULL == icd_term->dispatch.CreateDisplayModeKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkCreateDisplayModeKHR!\n");
+ assert(false && "loader: null CreateDisplayModeKHR ICD pointer");
+ }
+
+ return icd_term->dispatch.CreateDisplayModeKHR(phys_dev_term->phys_dev, display, pCreateInfo, pAllocator, pMode);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice,
+ VkDisplayModeKHR mode, uint32_t planeIndex,
+ VkDisplayPlaneCapabilitiesKHR *pCapabilities) {
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ VkResult res = disp->GetDisplayPlaneCapabilitiesKHR(unwrapped_phys_dev, mode, planeIndex, pCapabilities);
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode,
+ uint32_t planeIndex,
+ VkDisplayPlaneCapabilitiesKHR *pCapabilities) {
+ // First, check to ensure the appropriate extension was enabled:
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ struct loader_instance *ptr_instance = (struct loader_instance *)icd_term->this_instance;
+ if (!ptr_instance->wsi_display_enabled) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_display extension not enabled. vkGetDisplayPlaneCapabilitiesKHR not executed!\n");
+ return VK_SUCCESS;
+ }
+
+ if (NULL == icd_term->dispatch.GetDisplayPlaneCapabilitiesKHR) {
+ loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD for selected physical device is not exporting vkGetDisplayPlaneCapabilitiesKHR!\n");
+ assert(false && "loader: null GetDisplayPlaneCapabilitiesKHR ICD pointer");
+ }
+
+ return icd_term->dispatch.GetDisplayPlaneCapabilitiesKHR(phys_dev_term->phys_dev, mode, planeIndex, pCapabilities);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR(VkInstance instance,
+ const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ const VkLayerInstanceDispatchTable *disp;
+ disp = loader_get_instance_layer_dispatch(instance);
+ VkResult res;
+
+ res = disp->CreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+ return res;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayPlaneSurfaceKHR(VkInstance instance,
+ const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ VkIcdSurface *pIcdSurface = NULL;
+ VkResult vkRes = VK_SUCCESS;
+ uint32_t i = 0;
+
+ if (!inst->wsi_display_enabled) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "VK_KHR_surface extension not enabled. vkCreateDisplayPlaneSurfaceKHR not executed!\n");
+ vkRes = VK_ERROR_EXTENSION_NOT_PRESENT;
+ goto out;
+ }
+
+ // Next, if so, proceed with the implementation of this function:
+ pIcdSurface = AllocateIcdSurfaceStruct(inst, sizeof(pIcdSurface->display_surf.base), sizeof(pIcdSurface->display_surf));
+ if (pIcdSurface == NULL) {
+ vkRes = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ pIcdSurface->display_surf.base.platform = VK_ICD_WSI_PLATFORM_DISPLAY;
+ pIcdSurface->display_surf.displayMode = pCreateInfo->displayMode;
+ pIcdSurface->display_surf.planeIndex = pCreateInfo->planeIndex;
+ pIcdSurface->display_surf.planeStackIndex = pCreateInfo->planeStackIndex;
+ pIcdSurface->display_surf.transform = pCreateInfo->transform;
+ pIcdSurface->display_surf.globalAlpha = pCreateInfo->globalAlpha;
+ pIcdSurface->display_surf.alphaMode = pCreateInfo->alphaMode;
+ pIcdSurface->display_surf.imageExtent = pCreateInfo->imageExtent;
+
+ // Loop through each ICD and determine if they need to create a surface
+ for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
+ if (NULL != icd_term->dispatch.CreateDisplayPlaneSurfaceKHR) {
+ vkRes = icd_term->dispatch.CreateDisplayPlaneSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
+ &pIcdSurface->real_icd_surfaces[i]);
+ if (VK_SUCCESS != vkRes) {
+ goto out;
+ }
+ }
+ }
+ }
+
+ *pSurface = (VkSurfaceKHR)pIcdSurface;
+
+out:
+
+ if (VK_SUCCESS != vkRes && NULL != pIcdSurface) {
+ if (NULL != pIcdSurface->real_icd_surfaces) {
+ i = 0;
+ for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next, i++) {
+ if ((VkSurfaceKHR)NULL != pIcdSurface->real_icd_surfaces[i] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
+ icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, pIcdSurface->real_icd_surfaces[i], pAllocator);
+ }
+ }
+ loader_instance_heap_free(inst, pIcdSurface->real_icd_surfaces);
+ }
+ loader_instance_heap_free(inst, pIcdSurface);
+ }
+
+ return vkRes;
+}
+
+// EXT_display_swapchain Extension command
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
+ const VkSwapchainCreateInfoKHR *pCreateInfos,
+ const VkAllocationCallbacks *pAllocator,
+ VkSwapchainKHR *pSwapchains) {
+ const VkLayerDispatchTable *disp;
+ disp = loader_get_dispatch(device);
+ return disp->CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
+ const VkSwapchainCreateInfoKHR *pCreateInfos,
+ const VkAllocationCallbacks *pAllocator,
+ VkSwapchainKHR *pSwapchains) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.CreateSharedSwapchainsKHR) {
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pCreateInfos->surface;
+ if (NULL != icd_surface->real_icd_surfaces) {
+ if ((VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[icd_index]) {
+ // We found the ICD, and there is an ICD KHR surface
+ // associated with it, so copy the CreateInfo struct
+ // and point it at the ICD's surface.
+ VkSwapchainCreateInfoKHR *pCreateCopy = loader_stack_alloc(sizeof(VkSwapchainCreateInfoKHR) * swapchainCount);
+ if (NULL == pCreateCopy) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memcpy(pCreateCopy, pCreateInfos, sizeof(VkSwapchainCreateInfoKHR) * swapchainCount);
+ for (uint32_t sc = 0; sc < swapchainCount; sc++) {
+ pCreateCopy[sc].surface = icd_surface->real_icd_surfaces[icd_index];
+ }
+ return icd_term->dispatch.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateCopy, pAllocator, pSwapchains);
+ }
+ }
+ return icd_term->dispatch.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains);
+ }
+ return VK_SUCCESS;
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR(
+ VkDevice device,
+ VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR(
+ VkDevice device,
+ VkSurfaceKHR surface,
+ VkDeviceGroupPresentModeFlagsKHR* pModes) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModesKHR(
+ VkDevice device,
+ VkSurfaceKHR surface,
+ VkDeviceGroupPresentModeFlagsKHR* pModes) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->dispatch.GetDeviceGroupSurfacePresentModesKHR) {
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
+ if (NULL != icd_surface->real_icd_surfaces && (VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[icd_index]) {
+ return icd_term->dispatch.GetDeviceGroupSurfacePresentModesKHR(device, icd_surface->real_icd_surfaces[icd_index], pModes);
+ }
+ return icd_term->dispatch.GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
+ }
+ return VK_SUCCESS;
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDevicePresentRectanglesKHR(unwrapped_phys_dev, surface, pRectCount, pRects);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDevicePresentRectanglesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->dispatch.GetPhysicalDevicePresentRectanglesKHR) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support GetPhysicalDevicePresentRectanglesKHX");
+ }
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(surface);
+ uint8_t icd_index = phys_dev_term->icd_index;
+ if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)icd_surface->real_icd_surfaces[icd_index]) {
+ return icd_term->dispatch.GetPhysicalDevicePresentRectanglesKHR(phys_dev_term->phys_dev, icd_surface->real_icd_surfaces[icd_index], pRectCount, pRects);
+ }
+ return icd_term->dispatch.GetPhysicalDevicePresentRectanglesKHR(phys_dev_term->phys_dev, surface, pRectCount, pRects);
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR(
+ VkDevice device,
+ const VkAcquireNextImageInfoKHR* pAcquireInfo,
+ uint32_t* pImageIndex) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ return disp->AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex);
+}
+
+// ---- VK_KHR_get_display_properties2 extension trampoline/terminators
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayProperties2KHR *pProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceDisplayProperties2KHR(unwrapped_phys_dev, pPropertyCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayProperties2KHR *pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ // If the function is available in the driver, just call into it
+ if (icd_term->dispatch.GetPhysicalDeviceDisplayProperties2KHR != NULL) {
+ return icd_term->dispatch.GetPhysicalDeviceDisplayProperties2KHR(phys_dev_term->phys_dev, pPropertyCount, pProperties);
+ }
+
+ // We have to emulate the function.
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceDisplayProperties2KHR: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
+
+ // If the icd doesn't support VK_KHR_display, then no properties are available
+ if (icd_term->dispatch.GetPhysicalDeviceDisplayPropertiesKHR == NULL) {
+ *pPropertyCount = 0;
+ return VK_SUCCESS;
+ }
+
+ // If we aren't writing to pProperties, then emulation is straightforward
+ if (pProperties == NULL || *pPropertyCount == 0) {
+ return icd_term->dispatch.GetPhysicalDeviceDisplayPropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, NULL);
+ }
+
+ // If we do have to write to pProperties, then we need to write to a temporary array of VkDisplayPropertiesKHR and copy it
+ VkDisplayPropertiesKHR *properties = loader_stack_alloc(*pPropertyCount * sizeof(VkDisplayPropertiesKHR));
+ if (properties == NULL) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ VkResult res = icd_term->dispatch.GetPhysicalDeviceDisplayPropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, properties);
+ if (res < 0) {
+ return res;
+ }
+ for (uint32_t i = 0; i < *pPropertyCount; ++i) {
+ memcpy(&pProperties[i].displayProperties, &properties[i], sizeof(VkDisplayPropertiesKHR));
+ }
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR(
+ VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPlaneProperties2KHR *pProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceDisplayPlaneProperties2KHR(unwrapped_phys_dev, pPropertyCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPlaneProperties2KHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPlaneProperties2KHR *pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ // If the function is available in the driver, just call into it
+ if (icd_term->dispatch.GetPhysicalDeviceDisplayPlaneProperties2KHR != NULL) {
+ return icd_term->dispatch.GetPhysicalDeviceDisplayPlaneProperties2KHR(phys_dev_term->phys_dev, pPropertyCount, pProperties);
+ }
+
+ // We have to emulate the function.
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetPhysicalDeviceDisplayPlaneProperties2KHR: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
+
+ // If the icd doesn't support VK_KHR_display, then no properties are available
+ if (icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR == NULL) {
+ *pPropertyCount = 0;
+ return VK_SUCCESS;
+ }
+
+ // If we aren't writing to pProperties, then emulation is straightforward
+ if (pProperties == NULL || *pPropertyCount == 0) {
+ return icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, NULL);
+ }
+
+ // If we do have to write to pProperties, then we need to write to a temporary array of VkDisplayPlanePropertiesKHR and copy it
+ VkDisplayPlanePropertiesKHR *properties = loader_stack_alloc(*pPropertyCount * sizeof(VkDisplayPlanePropertiesKHR));
+ if (properties == NULL) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ VkResult res =
+ icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, properties);
+ if (res < 0) {
+ return res;
+ }
+ for (uint32_t i = 0; i < *pPropertyCount; ++i) {
+ memcpy(&pProperties[i].displayPlaneProperties, &properties[i], sizeof(VkDisplayPlanePropertiesKHR));
+ }
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+ uint32_t *pPropertyCount,
+ VkDisplayModeProperties2KHR *pProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetDisplayModeProperties2KHR(unwrapped_phys_dev, display, pPropertyCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+ uint32_t *pPropertyCount,
+ VkDisplayModeProperties2KHR *pProperties) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ // If the function is available in the driver, just call into it
+ if (icd_term->dispatch.GetDisplayModeProperties2KHR != NULL) {
+ return icd_term->dispatch.GetDisplayModeProperties2KHR(phys_dev_term->phys_dev, display, pPropertyCount, pProperties);
+ }
+
+ // We have to emulate the function.
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetDisplayModeProperties2KHR: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
+
+ // If the icd doesn't support VK_KHR_display, then no properties are available
+ if (icd_term->dispatch.GetDisplayModePropertiesKHR == NULL) {
+ *pPropertyCount = 0;
+ return VK_SUCCESS;
+ }
+
+ // If we aren't writing to pProperties, then emulation is straightforward
+ if (pProperties == NULL || *pPropertyCount == 0) {
+ return icd_term->dispatch.GetDisplayModePropertiesKHR(phys_dev_term->phys_dev, display, pPropertyCount, NULL);
+ }
+
+ // If we do have to write to pProperties, then we need to write to a temporary array of VkDisplayModePropertiesKHR and copy it
+ VkDisplayModePropertiesKHR *properties = loader_stack_alloc(*pPropertyCount * sizeof(VkDisplayModePropertiesKHR));
+ if (properties == NULL) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ VkResult res = icd_term->dispatch.GetDisplayModePropertiesKHR(phys_dev_term->phys_dev, display, pPropertyCount, properties);
+ if (res < 0) {
+ return res;
+ }
+ for (uint32_t i = 0; i < *pPropertyCount; ++i) {
+ memcpy(&pProperties[i].displayModeProperties, &properties[i], sizeof(VkDisplayModePropertiesKHR));
+ }
+ return res;
+}
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physicalDevice,
+ const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
+ VkDisplayPlaneCapabilities2KHR *pCapabilities) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetDisplayPlaneCapabilities2KHR(unwrapped_phys_dev, pDisplayPlaneInfo, pCapabilities);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physicalDevice,
+ const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
+ VkDisplayPlaneCapabilities2KHR *pCapabilities) {
+ struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+
+ // If the function is abailable in the driver, just call into it
+ if (icd_term->dispatch.GetDisplayPlaneCapabilities2KHR != NULL) {
+ return icd_term->dispatch.GetDisplayPlaneCapabilities2KHR(phys_dev_term->phys_dev, pDisplayPlaneInfo, pCapabilities);
+ }
+
+ // We have to emulate the function.
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "vkGetDisplayPlaneCapabilities2KHR: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
+
+ // Just call into the old version of the function.
+ // If the icd doesn't support VK_KHR_display, there are zero planes and this call is invalid (and will crash)
+ return icd_term->dispatch.GetDisplayPlaneCapabilitiesKHR(phys_dev_term->phys_dev, pDisplayPlaneInfo->mode,
+ pDisplayPlaneInfo->planeIndex, &pCapabilities->capabilities);
+}
+
+bool wsi_swapchain_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
+ *addr = NULL;
+
+ // Functions for the VK_KHR_surface extension:
+ if (!strcmp("vkDestroySurfaceKHR", name)) {
+ *addr = ptr_instance->wsi_surface_enabled ? (void *)vkDestroySurfaceKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", name)) {
+ *addr = ptr_instance->wsi_surface_enabled ? (void *)vkGetPhysicalDeviceSurfaceSupportKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", name)) {
+ *addr = ptr_instance->wsi_surface_enabled ? (void *)vkGetPhysicalDeviceSurfaceCapabilitiesKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", name)) {
+ *addr = ptr_instance->wsi_surface_enabled ? (void *)vkGetPhysicalDeviceSurfaceFormatsKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", name)) {
+ *addr = ptr_instance->wsi_surface_enabled ? (void *)vkGetPhysicalDeviceSurfacePresentModesKHR : NULL;
+ return true;
+ }
+
+ if (!strcmp("vkGetDeviceGroupPresentCapabilitiesKHR", name)) {
+ *addr = ptr_instance->wsi_surface_enabled ? (void *)vkGetDeviceGroupPresentCapabilitiesKHR : NULL;
+ return true;
+ }
+
+ if (!strcmp("vkGetDeviceGroupSurfacePresentModesKHR", name)) {
+ *addr = ptr_instance->wsi_surface_enabled ? (void *)vkGetDeviceGroupSurfacePresentModesKHR : NULL;
+ return true;
+ }
+
+ if (!strcmp("vkGetPhysicalDevicePresentRectanglesKHR", name)) {
+ *addr = ptr_instance->wsi_surface_enabled ? (void *)vkGetPhysicalDevicePresentRectanglesKHR : NULL;
+ return true;
+ }
+
+ // Functions for the VK_KHR_swapchain extension:
+
+ // Note: This is a device extension, and its functions are statically
+ // exported from the loader. Per Khronos decisions, the loader's GIPA
+ // function will return the trampoline function for such device-extension
+ // functions, regardless of whether the extension has been enabled.
+ if (!strcmp("vkCreateSwapchainKHR", name)) {
+ *addr = (void *)vkCreateSwapchainKHR;
+ return true;
+ }
+ if (!strcmp("vkDestroySwapchainKHR", name)) {
+ *addr = (void *)vkDestroySwapchainKHR;
+ return true;
+ }
+ if (!strcmp("vkGetSwapchainImagesKHR", name)) {
+ *addr = (void *)vkGetSwapchainImagesKHR;
+ return true;
+ }
+ if (!strcmp("vkAcquireNextImageKHR", name)) {
+ *addr = (void *)vkAcquireNextImageKHR;
+ return true;
+ }
+ if (!strcmp("vkQueuePresentKHR", name)) {
+ *addr = (void *)vkQueuePresentKHR;
+ return true;
+ }
+ if (!strcmp("vkAcquireNextImage2KHR", name)) {
+ *addr = (void *)vkAcquireNextImage2KHR;
+ return true;
+ }
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+ // Functions for the VK_KHR_win32_surface extension:
+ if (!strcmp("vkCreateWin32SurfaceKHR", name)) {
+ *addr = ptr_instance->wsi_win32_surface_enabled ? (void *)vkCreateWin32SurfaceKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceWin32PresentationSupportKHR", name)) {
+ *addr = ptr_instance->wsi_win32_surface_enabled ? (void *)vkGetPhysicalDeviceWin32PresentationSupportKHR : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+
+ // Functions for the VK_KHR_wayland_surface extension:
+ if (!strcmp("vkCreateWaylandSurfaceKHR", name)) {
+ *addr = ptr_instance->wsi_wayland_surface_enabled ? (void *)vkCreateWaylandSurfaceKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceWaylandPresentationSupportKHR", name)) {
+ *addr = ptr_instance->wsi_wayland_surface_enabled ? (void *)vkGetPhysicalDeviceWaylandPresentationSupportKHR : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+
+ // Functions for the VK_KHR_xcb_surface extension:
+ if (!strcmp("vkCreateXcbSurfaceKHR", name)) {
+ *addr = ptr_instance->wsi_xcb_surface_enabled ? (void *)vkCreateXcbSurfaceKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceXcbPresentationSupportKHR", name)) {
+ *addr = ptr_instance->wsi_xcb_surface_enabled ? (void *)vkGetPhysicalDeviceXcbPresentationSupportKHR : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+
+ // Functions for the VK_KHR_xlib_surface extension:
+ if (!strcmp("vkCreateXlibSurfaceKHR", name)) {
+ *addr = ptr_instance->wsi_xlib_surface_enabled ? (void *)vkCreateXlibSurfaceKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceXlibPresentationSupportKHR", name)) {
+ *addr = ptr_instance->wsi_xlib_surface_enabled ? (void *)vkGetPhysicalDeviceXlibPresentationSupportKHR : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+
+ // Functions for the VK_KHR_android_surface extension:
+ if (!strcmp("vkCreateAndroidSurfaceKHR", name)) {
+ *addr = ptr_instance->wsi_android_surface_enabled ? (void *)vkCreateAndroidSurfaceKHR : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+
+ // Functions for the VK_MVK_macos_surface extension:
+ if (!strcmp("vkCreateMacOSSurfaceMVK", name)) {
+ *addr = ptr_instance->wsi_macos_surface_enabled ? (void *)vkCreateMacOSSurfaceMVK : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_MACOS_MVK
+#ifdef VK_USE_PLATFORM_IOS_MVK
+
+ // Functions for the VK_MVK_ios_surface extension:
+ if (!strcmp("vkCreateIOSSurfaceMVK", name)) {
+ *addr = ptr_instance->wsi_ios_surface_enabled ? (void *)vkCreateIOSSurfaceMVK : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_IOS_MVK
+
+ // Functions for the VK_EXT_headless_surface extension:
+ if (!strcmp("vkCreateHeadlessSurfaceEXT", name)) {
+ *addr = ptr_instance->wsi_headless_surface_enabled ? (void *)vkCreateHeadlessSurfaceEXT : NULL;
+ return true;
+ }
+
+#if defined(VK_USE_PLATFORM_METAL_EXT)
+ // Functions for the VK_MVK_macos_surface extension:
+ if (!strcmp("vkCreateMetalSurfaceEXT", name)) {
+ *addr = ptr_instance->wsi_metal_surface_enabled ? (void *)vkCreateMetalSurfaceEXT : NULL;
+ return true;
+ }
+#endif // VK_USE_PLATFORM_METAL_EXT
+
+ // Functions for VK_KHR_display extension:
+ if (!strcmp("vkGetPhysicalDeviceDisplayPropertiesKHR", name)) {
+ *addr = ptr_instance->wsi_display_enabled ? (void *)vkGetPhysicalDeviceDisplayPropertiesKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceDisplayPlanePropertiesKHR", name)) {
+ *addr = ptr_instance->wsi_display_enabled ? (void *)vkGetPhysicalDeviceDisplayPlanePropertiesKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetDisplayPlaneSupportedDisplaysKHR", name)) {
+ *addr = ptr_instance->wsi_display_enabled ? (void *)vkGetDisplayPlaneSupportedDisplaysKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetDisplayModePropertiesKHR", name)) {
+ *addr = ptr_instance->wsi_display_enabled ? (void *)vkGetDisplayModePropertiesKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkCreateDisplayModeKHR", name)) {
+ *addr = ptr_instance->wsi_display_enabled ? (void *)vkCreateDisplayModeKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetDisplayPlaneCapabilitiesKHR", name)) {
+ *addr = ptr_instance->wsi_display_enabled ? (void *)vkGetDisplayPlaneCapabilitiesKHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkCreateDisplayPlaneSurfaceKHR", name)) {
+ *addr = ptr_instance->wsi_display_enabled ? (void *)vkCreateDisplayPlaneSurfaceKHR : NULL;
+ return true;
+ }
+
+ // Functions for KHR_display_swapchain extension:
+ if (!strcmp("vkCreateSharedSwapchainsKHR", name)) {
+ *addr = (void *)vkCreateSharedSwapchainsKHR;
+ return true;
+ }
+
+ // Functions for KHR_get_display_properties2
+ if (!strcmp("vkGetPhysicalDeviceDisplayProperties2KHR", name)) {
+ *addr = ptr_instance->wsi_display_props2_enabled ? (void *)vkGetPhysicalDeviceDisplayProperties2KHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceDisplayPlaneProperties2KHR", name)) {
+ *addr = ptr_instance->wsi_display_props2_enabled ? (void *)vkGetPhysicalDeviceDisplayPlaneProperties2KHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetDisplayModeProperties2KHR", name)) {
+ *addr = ptr_instance->wsi_display_props2_enabled ? (void *)vkGetDisplayModeProperties2KHR : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetDisplayPlaneCapabilities2KHR", name)) {
+ *addr = ptr_instance->wsi_display_props2_enabled ? (void *)vkGetDisplayPlaneCapabilities2KHR : NULL;
+ return true;
+ }
+
+ return false;
+}
diff --git a/thirdparty/vulkan/loader/wsi.h b/thirdparty/vulkan/loader/wsi.h
new file mode 100644
index 0000000000..3e44efa9e9
--- /dev/null
+++ b/thirdparty/vulkan/loader/wsi.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Ian Elliott <ian@lunarg.com>
+ *
+ */
+
+#ifndef WSI_H
+#define WSI_H
+
+#include "vk_loader_platform.h"
+#include "loader.h"
+
+typedef struct {
+ union {
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ VkIcdSurfaceWayland wayland_surf;
+#endif // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ VkIcdSurfaceWin32 win_surf;
+#endif // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ VkIcdSurfaceXcb xcb_surf;
+#endif // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ VkIcdSurfaceXlib xlib_surf;
+#endif // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+ VkIcdSurfaceMacOS macos_surf;
+#endif // VK_USE_PLATFORM_MACOS_MVK
+#ifdef VK_USE_PLATFORM_METAL_EXT
+ VkIcdSurfaceMetal metal_surf;
+#endif // VK_USE_PLATFORM_METAL_EXT
+ VkIcdSurfaceDisplay display_surf;
+ VkIcdSurfaceHeadless headless_surf;
+ };
+ uint32_t base_size; // Size of VkIcdSurfaceBase
+ uint32_t platform_size; // Size of corresponding VkIcdSurfaceXXX
+ uint32_t non_platform_offset; // Start offset to base_size
+ uint32_t entire_size; // Size of entire VkIcdSurface
+ VkSurfaceKHR *real_icd_surfaces;
+} VkIcdSurface;
+
+bool wsi_swapchain_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr);
+
+void wsi_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);
+bool wsi_unsupported_instance_extension(const VkExtensionProperties *ext_prop);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateHeadlessSurfaceEXT(VkInstance instance,
+ const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain);
+
+VKAPI_ATTR void VKAPI_CALL terminator_DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
+ const VkAllocationCallbacks *pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex, VkSurfaceKHR surface,
+ VkBool32 *pSupported);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ VkSurfaceCapabilitiesKHR *pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
+ uint32_t *pSurfaceFormatCount,
+ VkSurfaceFormatKHR *pSurfaceFormats);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface, uint32_t *pPresentModeCount,
+ VkPresentModeKHR *pPresentModes);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModesKHR(
+ VkDevice device,
+ VkSurfaceKHR surface,
+ VkDeviceGroupPresentModeFlagsKHR* pModes);
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex);
+#endif
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWaylandSurfaceKHR(VkInstance instance,
+ const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ struct wl_display *display);
+#endif
+#ifdef VK_USE_PLATFORM_XCB_KHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ xcb_connection_t *connection,
+ xcb_visualid_t visual_id);
+#endif
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex, Display *dpy,
+ VisualID visualID);
+#endif
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+#endif
+#ifdef VK_USE_PLATFORM_IOS_MVK
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+#endif
+#if defined(VK_USE_PLATFORM_METAL_EXT)
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance instance, const VkMetalSurfaceCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+#endif
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPropertiesKHR *pProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPlanePropertiesKHR *pProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex,
+ uint32_t *pDisplayCount, VkDisplayKHR *pDisplays);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+ uint32_t *pPropertyCount,
+ VkDisplayModePropertiesKHR *pProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+ const VkDisplayModeCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDisplayModeKHR *pMode);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode,
+ uint32_t planeIndex,
+ VkDisplayPlaneCapabilitiesKHR *pCapabilities);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayPlaneSurfaceKHR(VkInstance instance,
+ const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
+ const VkSwapchainCreateInfoKHR *pCreateInfos,
+ const VkAllocationCallbacks *pAllocator,
+ VkSwapchainKHR *pSwapchains);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayProperties2KHR *pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPlaneProperties2KHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPlaneProperties2KHR *pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+ uint32_t *pPropertyCount,
+ VkDisplayModeProperties2KHR *pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physicalDevice,
+ const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
+ VkDisplayPlaneCapabilities2KHR *pCapabilities);
+
+#endif // WSI_H
diff --git a/thirdparty/vulkan/patches/Vulkan-Loader-revert-pr260.patch b/thirdparty/vulkan/patches/Vulkan-Loader-revert-pr260.patch
new file mode 100644
index 0000000000..1267e560df
--- /dev/null
+++ b/thirdparty/vulkan/patches/Vulkan-Loader-revert-pr260.patch
@@ -0,0 +1,57 @@
+diff --git a/thirdparty/vulkan/loader/loader.c b/thirdparty/vulkan/loader/loader.c
+index 87d08d5116..c7cdb47122 100644
+--- a/thirdparty/vulkan/loader/loader.c
++++ b/thirdparty/vulkan/loader/loader.c
+@@ -7330,7 +7330,7 @@ out:
+ return result;
+ }
+
+-#if defined(_WIN32)
++#if defined(_WIN32) && defined(LOADER_DYNAMIC_LIB)
+ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+diff --git a/thirdparty/vulkan/loader/loader.h b/thirdparty/vulkan/loader/loader.h
+index 5e9495521b..56745a968d 100644
+--- a/thirdparty/vulkan/loader/loader.h
++++ b/thirdparty/vulkan/loader/loader.h
+@@ -420,6 +420,9 @@ static inline void loader_init_dispatch(void *obj, const void *data) {
+ // Global variables used across files
+ extern struct loader_struct loader;
+ extern THREAD_LOCAL_DECL struct loader_instance *tls_instance;
++#if defined(_WIN32) && !defined(LOADER_DYNAMIC_LIB)
++extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_init);
++#endif
+ extern loader_platform_thread_mutex loader_lock;
+ extern loader_platform_thread_mutex loader_json_lock;
+
+diff --git a/thirdparty/vulkan/loader/vk_loader_platform.h b/thirdparty/vulkan/loader/vk_loader_platform.h
+index 7824e35d6b..62e8e3ae09 100644
+--- a/thirdparty/vulkan/loader/vk_loader_platform.h
++++ b/thirdparty/vulkan/loader/vk_loader_platform.h
+@@ -330,9 +330,25 @@ typedef HANDLE loader_platform_thread;
+ // The once init functionality is not used when building a DLL on Windows. This is because there is no way to clean up the
+ // resources allocated by anything allocated by once init. This isn't a problem for static libraries, but it is for dynamic
+ // ones. When building a DLL, we use DllMain() instead to allow properly cleaning up resources.
++#if defined(LOADER_DYNAMIC_LIB)
+ #define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var)
+ #define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var)
+ #define LOADER_PLATFORM_THREAD_ONCE(ctl, func)
++#else
++#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) INIT_ONCE var = INIT_ONCE_STATIC_INIT;
++#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) INIT_ONCE var;
++#define LOADER_PLATFORM_THREAD_ONCE(ctl, func) loader_platform_thread_once_fn(ctl, func)
++static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) {
++ void (*func)(void) = (void (*)(void))Parameter;
++ func();
++ return TRUE;
++}
++static void loader_platform_thread_once_fn(void *ctl, void (*func)(void)) {
++ assert(func != NULL);
++ assert(ctl != NULL);
++ InitOnceExecuteOnce((PINIT_ONCE)ctl, InitFuncWrapper, (void *)func, NULL);
++}
++#endif
+
+ // Thread IDs:
+ typedef DWORD loader_platform_thread_id;
diff --git a/thirdparty/vulkan/vk_enum_string_helper.h b/thirdparty/vulkan/vk_enum_string_helper.h
new file mode 100644
index 0000000000..1c99b31270
--- /dev/null
+++ b/thirdparty/vulkan/vk_enum_string_helper.h
@@ -0,0 +1,6414 @@
+// *** THIS FILE IS GENERATED - DO NOT EDIT ***
+// See helper_file_generator.py for modifications
+
+
+/***************************************************************************
+ *
+ * Copyright (c) 2015-2020 The Khronos Group Inc.
+ * Copyright (c) 2015-2020 Valve Corporation
+ * Copyright (c) 2015-2020 LunarG, Inc.
+ * Copyright (c) 2015-2020 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Mark Lobodzinski <mark@lunarg.com>
+ * Author: Courtney Goeltzenleuchter <courtneygo@google.com>
+ * Author: Tobin Ehlis <tobine@google.com>
+ * Author: Chris Forbes <chrisforbes@google.com>
+ * Author: John Zulauf<jzulauf@lunarg.com>
+ *
+ ****************************************************************************/
+
+
+#pragma once
+#ifdef _MSC_VER
+#pragma warning( disable : 4065 )
+#endif
+
+#include <string>
+#include <vulkan/vulkan.h>
+
+
+static inline const char* string_VkPipelineCacheHeaderVersion(VkPipelineCacheHeaderVersion input_value)
+{
+ switch ((VkPipelineCacheHeaderVersion)input_value)
+ {
+ case VK_PIPELINE_CACHE_HEADER_VERSION_ONE:
+ return "VK_PIPELINE_CACHE_HEADER_VERSION_ONE";
+ default:
+ return "Unhandled VkPipelineCacheHeaderVersion";
+ }
+}
+
+static inline const char* string_VkResult(VkResult input_value)
+{
+ switch ((VkResult)input_value)
+ {
+ case VK_ERROR_DEVICE_LOST:
+ return "VK_ERROR_DEVICE_LOST";
+ case VK_ERROR_EXTENSION_NOT_PRESENT:
+ return "VK_ERROR_EXTENSION_NOT_PRESENT";
+ case VK_ERROR_FEATURE_NOT_PRESENT:
+ return "VK_ERROR_FEATURE_NOT_PRESENT";
+ case VK_ERROR_FORMAT_NOT_SUPPORTED:
+ return "VK_ERROR_FORMAT_NOT_SUPPORTED";
+ case VK_ERROR_FRAGMENTATION:
+ return "VK_ERROR_FRAGMENTATION";
+ case VK_ERROR_FRAGMENTED_POOL:
+ return "VK_ERROR_FRAGMENTED_POOL";
+ case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
+ return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
+ case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
+ return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
+ case VK_ERROR_INCOMPATIBLE_DRIVER:
+ return "VK_ERROR_INCOMPATIBLE_DRIVER";
+ case VK_ERROR_INITIALIZATION_FAILED:
+ return "VK_ERROR_INITIALIZATION_FAILED";
+ case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
+ return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
+ case VK_ERROR_INVALID_EXTERNAL_HANDLE:
+ return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
+ case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS:
+ return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS";
+ case VK_ERROR_INVALID_SHADER_NV:
+ return "VK_ERROR_INVALID_SHADER_NV";
+ case VK_ERROR_LAYER_NOT_PRESENT:
+ return "VK_ERROR_LAYER_NOT_PRESENT";
+ case VK_ERROR_MEMORY_MAP_FAILED:
+ return "VK_ERROR_MEMORY_MAP_FAILED";
+ case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
+ return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
+ case VK_ERROR_NOT_PERMITTED_EXT:
+ return "VK_ERROR_NOT_PERMITTED_EXT";
+ case VK_ERROR_OUT_OF_DATE_KHR:
+ return "VK_ERROR_OUT_OF_DATE_KHR";
+ case VK_ERROR_OUT_OF_DEVICE_MEMORY:
+ return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
+ case VK_ERROR_OUT_OF_HOST_MEMORY:
+ return "VK_ERROR_OUT_OF_HOST_MEMORY";
+ case VK_ERROR_OUT_OF_POOL_MEMORY:
+ return "VK_ERROR_OUT_OF_POOL_MEMORY";
+ case VK_ERROR_SURFACE_LOST_KHR:
+ return "VK_ERROR_SURFACE_LOST_KHR";
+ case VK_ERROR_TOO_MANY_OBJECTS:
+ return "VK_ERROR_TOO_MANY_OBJECTS";
+ case VK_ERROR_UNKNOWN:
+ return "VK_ERROR_UNKNOWN";
+ case VK_ERROR_VALIDATION_FAILED_EXT:
+ return "VK_ERROR_VALIDATION_FAILED_EXT";
+ case VK_EVENT_RESET:
+ return "VK_EVENT_RESET";
+ case VK_EVENT_SET:
+ return "VK_EVENT_SET";
+ case VK_INCOMPLETE:
+ return "VK_INCOMPLETE";
+ case VK_NOT_READY:
+ return "VK_NOT_READY";
+ case VK_SUBOPTIMAL_KHR:
+ return "VK_SUBOPTIMAL_KHR";
+ case VK_SUCCESS:
+ return "VK_SUCCESS";
+ case VK_TIMEOUT:
+ return "VK_TIMEOUT";
+ default:
+ return "Unhandled VkResult";
+ }
+}
+
+static inline const char* string_VkStructureType(VkStructureType input_value)
+{
+ switch ((VkStructureType)input_value)
+ {
+ case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV";
+ case VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV:
+ return "VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV";
+ case VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR";
+ case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID:
+ return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID";
+ case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID:
+ return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID";
+ case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID:
+ return "VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID";
+ case VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_APPLICATION_INFO:
+ return "VK_STRUCTURE_TYPE_APPLICATION_INFO";
+ case VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2:
+ return "VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2";
+ case VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT:
+ return "VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT";
+ case VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2:
+ return "VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2";
+ case VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT:
+ return "VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT";
+ case VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV:
+ return "VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV";
+ case VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO:
+ return "VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO";
+ case VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO:
+ return "VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO";
+ case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO:
+ return "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO";
+ case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO:
+ return "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO";
+ case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR";
+ case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO:
+ return "VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO";
+ case VK_STRUCTURE_TYPE_BIND_SPARSE_INFO:
+ return "VK_STRUCTURE_TYPE_BIND_SPARSE_INFO";
+ case VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO:
+ return "VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO";
+ case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER:
+ return "VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER";
+ case VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2:
+ return "VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2";
+ case VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT";
+ case VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV:
+ return "VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV";
+ case VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX:
+ return "VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX";
+ case VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX:
+ return "VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX";
+ case VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO:
+ return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO";
+ case VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO:
+ return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO";
+ case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT";
+ case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO:
+ return "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO";
+ case VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT";
+ case VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV:
+ return "VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV";
+ case VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET:
+ return "VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET";
+ case VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR";
+ case VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT:
+ return "VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT";
+ case VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT:
+ return "VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT";
+ case VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO:
+ return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT:
+ return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO:
+ return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT:
+ return "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT";
+ case VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX:
+ return "VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX";
+ case VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX:
+ return "VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX";
+ case VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO:
+ return "VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO:
+ return "VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR:
+ return "VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR";
+ case VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR";
+ case VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO:
+ return "VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO:
+ return "VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO:
+ return "VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD:
+ return "VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD";
+ case VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2:
+ return "VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2";
+ case VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR:
+ return "VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR";
+ case VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD:
+ return "VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD";
+ case VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR:
+ return "VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR";
+ case VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR:
+ return "VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR";
+ case VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR:
+ return "VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR";
+ case VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT";
+ case VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR";
+ case VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR:
+ return "VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR";
+ case VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT:
+ return "VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT";
+ case VK_STRUCTURE_TYPE_EVENT_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_EVENT_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
+ return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO";
+ case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV";
+ case VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES";
+ case VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES";
+ case VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID:
+ return "VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID";
+ case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES";
+ case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES";
+ case VK_STRUCTURE_TYPE_FENCE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_FENCE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR";
+ case VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2:
+ return "VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2";
+ case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO:
+ return "VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO";
+ case VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV:
+ return "VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV";
+ case VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV:
+ return "VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV";
+ case VK_STRUCTURE_TYPE_GEOMETRY_NV:
+ return "VK_STRUCTURE_TYPE_GEOMETRY_NV";
+ case VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV:
+ return "VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV";
+ case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_HDR_METADATA_EXT:
+ return "VK_STRUCTURE_TYPE_HDR_METADATA_EXT";
+ case VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA:
+ return "VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA";
+ case VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2:
+ return "VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2";
+ case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER:
+ return "VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER";
+ case VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2:
+ return "VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2";
+ case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO:
+ return "VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO";
+ case VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2:
+ return "VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2";
+ case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT:
+ return "VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT";
+ case VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX:
+ return "VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX";
+ case VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID:
+ return "VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID";
+ case VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR";
+ case VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR";
+ case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT";
+ case VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV";
+ case VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR";
+ case VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX:
+ return "VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX";
+ case VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL:
+ return "VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL";
+ case VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK:
+ return "VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK";
+ case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK:
+ return "VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK";
+ case VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE:
+ return "VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE";
+ case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO:
+ return "VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO";
+ case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO:
+ return "VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO";
+ case VK_STRUCTURE_TYPE_MEMORY_BARRIER:
+ return "VK_STRUCTURE_TYPE_MEMORY_BARRIER";
+ case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
+ return "VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO";
+ case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS:
+ return "VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS";
+ case VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR:
+ return "VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR";
+ case VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID:
+ return "VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID";
+ case VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR";
+ case VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO:
+ return "VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO";
+ case VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2:
+ return "VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2";
+ case VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR:
+ return "VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR";
+ case VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX:
+ return "VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX";
+ case VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL:
+ return "VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL";
+ case VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR:
+ return "VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR";
+ case VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR:
+ return "VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR";
+ case VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL:
+ return "VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL";
+ case VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL:
+ return "VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL";
+ case VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR";
+ case VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL:
+ return "VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES";
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD:
+ return "VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD";
+ case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR:
+ return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR";
+ case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR:
+ return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR";
+ case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR:
+ return "VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR";
+ case VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD:
+ return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD";
+ case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP:
+ return "VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP";
+ case VK_STRUCTURE_TYPE_PRESENT_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR";
+ case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
+ return "VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR";
+ case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE:
+ return "VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE";
+ case VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO:
+ return "VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO";
+ case VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL:
+ return "VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL";
+ case VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV:
+ return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV";
+ case VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2:
+ return "VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2";
+ case VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV";
+ case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO:
+ return "VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO";
+ case VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO:
+ return "VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO";
+ case VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2:
+ return "VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2";
+ case VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT";
+ case VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
+ return "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES";
+ case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO:
+ return "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO";
+ case VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT";
+ case VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR";
+ case VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO:
+ return "VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO";
+ case VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO:
+ return "VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO";
+ case VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO:
+ return "VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO";
+ case VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR:
+ return "VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR";
+ case VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2:
+ return "VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2";
+ case VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2:
+ return "VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2";
+ case VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP:
+ return "VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP";
+ case VK_STRUCTURE_TYPE_SUBMIT_INFO:
+ return "VK_STRUCTURE_TYPE_SUBMIT_INFO";
+ case VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO:
+ return "VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO";
+ case VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2:
+ return "VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2";
+ case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2:
+ return "VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2";
+ case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE:
+ return "VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE";
+ case VK_STRUCTURE_TYPE_SUBPASS_END_INFO:
+ return "VK_STRUCTURE_TYPE_SUBPASS_END_INFO";
+ case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT:
+ return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT";
+ case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR:
+ return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR";
+ case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT:
+ return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT";
+ case VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR:
+ return "VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR";
+ case VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT";
+ case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR:
+ return "VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR";
+ case VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD:
+ return "VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD";
+ case VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD:
+ return "VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD";
+ case VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO:
+ return "VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO";
+ case VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT:
+ return "VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT";
+ case VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT:
+ return "VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT";
+ case VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT:
+ return "VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT";
+ case VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN:
+ return "VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN";
+ case VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV:
+ return "VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV";
+ case VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET:
+ return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET";
+ case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV:
+ return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV";
+ case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT:
+ return "VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT";
+ case VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR";
+ case VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR:
+ return "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR";
+ default:
+ return "Unhandled VkStructureType";
+ }
+}
+
+static inline const char* string_VkSystemAllocationScope(VkSystemAllocationScope input_value)
+{
+ switch ((VkSystemAllocationScope)input_value)
+ {
+ case VK_SYSTEM_ALLOCATION_SCOPE_CACHE:
+ return "VK_SYSTEM_ALLOCATION_SCOPE_CACHE";
+ case VK_SYSTEM_ALLOCATION_SCOPE_COMMAND:
+ return "VK_SYSTEM_ALLOCATION_SCOPE_COMMAND";
+ case VK_SYSTEM_ALLOCATION_SCOPE_DEVICE:
+ return "VK_SYSTEM_ALLOCATION_SCOPE_DEVICE";
+ case VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE:
+ return "VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE";
+ case VK_SYSTEM_ALLOCATION_SCOPE_OBJECT:
+ return "VK_SYSTEM_ALLOCATION_SCOPE_OBJECT";
+ default:
+ return "Unhandled VkSystemAllocationScope";
+ }
+}
+
+static inline const char* string_VkInternalAllocationType(VkInternalAllocationType input_value)
+{
+ switch ((VkInternalAllocationType)input_value)
+ {
+ case VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE:
+ return "VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE";
+ default:
+ return "Unhandled VkInternalAllocationType";
+ }
+}
+
+static inline const char* string_VkFormat(VkFormat input_value)
+{
+ switch ((VkFormat)input_value)
+ {
+ case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
+ return "VK_FORMAT_A1R5G5B5_UNORM_PACK16";
+ case VK_FORMAT_A2B10G10R10_SINT_PACK32:
+ return "VK_FORMAT_A2B10G10R10_SINT_PACK32";
+ case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
+ return "VK_FORMAT_A2B10G10R10_SNORM_PACK32";
+ case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
+ return "VK_FORMAT_A2B10G10R10_SSCALED_PACK32";
+ case VK_FORMAT_A2B10G10R10_UINT_PACK32:
+ return "VK_FORMAT_A2B10G10R10_UINT_PACK32";
+ case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+ return "VK_FORMAT_A2B10G10R10_UNORM_PACK32";
+ case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
+ return "VK_FORMAT_A2B10G10R10_USCALED_PACK32";
+ case VK_FORMAT_A2R10G10B10_SINT_PACK32:
+ return "VK_FORMAT_A2R10G10B10_SINT_PACK32";
+ case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
+ return "VK_FORMAT_A2R10G10B10_SNORM_PACK32";
+ case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
+ return "VK_FORMAT_A2R10G10B10_SSCALED_PACK32";
+ case VK_FORMAT_A2R10G10B10_UINT_PACK32:
+ return "VK_FORMAT_A2R10G10B10_UINT_PACK32";
+ case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
+ return "VK_FORMAT_A2R10G10B10_UNORM_PACK32";
+ case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
+ return "VK_FORMAT_A2R10G10B10_USCALED_PACK32";
+ case VK_FORMAT_A8B8G8R8_SINT_PACK32:
+ return "VK_FORMAT_A8B8G8R8_SINT_PACK32";
+ case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
+ return "VK_FORMAT_A8B8G8R8_SNORM_PACK32";
+ case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
+ return "VK_FORMAT_A8B8G8R8_SRGB_PACK32";
+ case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
+ return "VK_FORMAT_A8B8G8R8_SSCALED_PACK32";
+ case VK_FORMAT_A8B8G8R8_UINT_PACK32:
+ return "VK_FORMAT_A8B8G8R8_UINT_PACK32";
+ case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
+ return "VK_FORMAT_A8B8G8R8_UNORM_PACK32";
+ case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
+ return "VK_FORMAT_A8B8G8R8_USCALED_PACK32";
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_10x10_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_10x10_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_10x5_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_10x5_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_10x6_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_10x6_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_10x8_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_10x8_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_12x10_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_12x10_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_12x12_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_12x12_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_4x4_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_4x4_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_5x4_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_5x4_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_5x5_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_5x5_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_6x5_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_6x5_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_6x6_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_6x6_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_8x5_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_8x5_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_8x6_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_8x6_UNORM_BLOCK";
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
+ return "VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT";
+ case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ return "VK_FORMAT_ASTC_8x8_SRGB_BLOCK";
+ case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
+ return "VK_FORMAT_ASTC_8x8_UNORM_BLOCK";
+ case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
+ return "VK_FORMAT_B10G11R11_UFLOAT_PACK32";
+ case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
+ return "VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16";
+ case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
+ return "VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16";
+ case VK_FORMAT_B16G16R16G16_422_UNORM:
+ return "VK_FORMAT_B16G16R16G16_422_UNORM";
+ case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
+ return "VK_FORMAT_B4G4R4A4_UNORM_PACK16";
+ case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
+ return "VK_FORMAT_B5G5R5A1_UNORM_PACK16";
+ case VK_FORMAT_B5G6R5_UNORM_PACK16:
+ return "VK_FORMAT_B5G6R5_UNORM_PACK16";
+ case VK_FORMAT_B8G8R8A8_SINT:
+ return "VK_FORMAT_B8G8R8A8_SINT";
+ case VK_FORMAT_B8G8R8A8_SNORM:
+ return "VK_FORMAT_B8G8R8A8_SNORM";
+ case VK_FORMAT_B8G8R8A8_SRGB:
+ return "VK_FORMAT_B8G8R8A8_SRGB";
+ case VK_FORMAT_B8G8R8A8_SSCALED:
+ return "VK_FORMAT_B8G8R8A8_SSCALED";
+ case VK_FORMAT_B8G8R8A8_UINT:
+ return "VK_FORMAT_B8G8R8A8_UINT";
+ case VK_FORMAT_B8G8R8A8_UNORM:
+ return "VK_FORMAT_B8G8R8A8_UNORM";
+ case VK_FORMAT_B8G8R8A8_USCALED:
+ return "VK_FORMAT_B8G8R8A8_USCALED";
+ case VK_FORMAT_B8G8R8G8_422_UNORM:
+ return "VK_FORMAT_B8G8R8G8_422_UNORM";
+ case VK_FORMAT_B8G8R8_SINT:
+ return "VK_FORMAT_B8G8R8_SINT";
+ case VK_FORMAT_B8G8R8_SNORM:
+ return "VK_FORMAT_B8G8R8_SNORM";
+ case VK_FORMAT_B8G8R8_SRGB:
+ return "VK_FORMAT_B8G8R8_SRGB";
+ case VK_FORMAT_B8G8R8_SSCALED:
+ return "VK_FORMAT_B8G8R8_SSCALED";
+ case VK_FORMAT_B8G8R8_UINT:
+ return "VK_FORMAT_B8G8R8_UINT";
+ case VK_FORMAT_B8G8R8_UNORM:
+ return "VK_FORMAT_B8G8R8_UNORM";
+ case VK_FORMAT_B8G8R8_USCALED:
+ return "VK_FORMAT_B8G8R8_USCALED";
+ case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
+ return "VK_FORMAT_BC1_RGBA_SRGB_BLOCK";
+ case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
+ return "VK_FORMAT_BC1_RGBA_UNORM_BLOCK";
+ case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
+ return "VK_FORMAT_BC1_RGB_SRGB_BLOCK";
+ case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
+ return "VK_FORMAT_BC1_RGB_UNORM_BLOCK";
+ case VK_FORMAT_BC2_SRGB_BLOCK:
+ return "VK_FORMAT_BC2_SRGB_BLOCK";
+ case VK_FORMAT_BC2_UNORM_BLOCK:
+ return "VK_FORMAT_BC2_UNORM_BLOCK";
+ case VK_FORMAT_BC3_SRGB_BLOCK:
+ return "VK_FORMAT_BC3_SRGB_BLOCK";
+ case VK_FORMAT_BC3_UNORM_BLOCK:
+ return "VK_FORMAT_BC3_UNORM_BLOCK";
+ case VK_FORMAT_BC4_SNORM_BLOCK:
+ return "VK_FORMAT_BC4_SNORM_BLOCK";
+ case VK_FORMAT_BC4_UNORM_BLOCK:
+ return "VK_FORMAT_BC4_UNORM_BLOCK";
+ case VK_FORMAT_BC5_SNORM_BLOCK:
+ return "VK_FORMAT_BC5_SNORM_BLOCK";
+ case VK_FORMAT_BC5_UNORM_BLOCK:
+ return "VK_FORMAT_BC5_UNORM_BLOCK";
+ case VK_FORMAT_BC6H_SFLOAT_BLOCK:
+ return "VK_FORMAT_BC6H_SFLOAT_BLOCK";
+ case VK_FORMAT_BC6H_UFLOAT_BLOCK:
+ return "VK_FORMAT_BC6H_UFLOAT_BLOCK";
+ case VK_FORMAT_BC7_SRGB_BLOCK:
+ return "VK_FORMAT_BC7_SRGB_BLOCK";
+ case VK_FORMAT_BC7_UNORM_BLOCK:
+ return "VK_FORMAT_BC7_UNORM_BLOCK";
+ case VK_FORMAT_D16_UNORM:
+ return "VK_FORMAT_D16_UNORM";
+ case VK_FORMAT_D16_UNORM_S8_UINT:
+ return "VK_FORMAT_D16_UNORM_S8_UINT";
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ return "VK_FORMAT_D24_UNORM_S8_UINT";
+ case VK_FORMAT_D32_SFLOAT:
+ return "VK_FORMAT_D32_SFLOAT";
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ return "VK_FORMAT_D32_SFLOAT_S8_UINT";
+ case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
+ return "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32";
+ case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
+ return "VK_FORMAT_EAC_R11G11_SNORM_BLOCK";
+ case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
+ return "VK_FORMAT_EAC_R11G11_UNORM_BLOCK";
+ case VK_FORMAT_EAC_R11_SNORM_BLOCK:
+ return "VK_FORMAT_EAC_R11_SNORM_BLOCK";
+ case VK_FORMAT_EAC_R11_UNORM_BLOCK:
+ return "VK_FORMAT_EAC_R11_UNORM_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
+ return "VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
+ return "VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
+ return "VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
+ return "VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
+ return "VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK";
+ case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
+ return "VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK";
+ case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
+ return "VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16";
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+ return "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16";
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
+ return "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16";
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
+ return "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16";
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
+ return "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16";
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
+ return "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16";
+ case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
+ return "VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16";
+ case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
+ return "VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16";
+ case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
+ return "VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16";
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
+ return "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16";
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
+ return "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16";
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
+ return "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16";
+ case VK_FORMAT_G16B16G16R16_422_UNORM:
+ return "VK_FORMAT_G16B16G16R16_422_UNORM";
+ case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
+ return "VK_FORMAT_G16_B16R16_2PLANE_420_UNORM";
+ case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
+ return "VK_FORMAT_G16_B16R16_2PLANE_422_UNORM";
+ case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
+ return "VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM";
+ case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
+ return "VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM";
+ case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
+ return "VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM";
+ case VK_FORMAT_G8B8G8R8_422_UNORM:
+ return "VK_FORMAT_G8B8G8R8_422_UNORM";
+ case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ return "VK_FORMAT_G8_B8R8_2PLANE_420_UNORM";
+ case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
+ return "VK_FORMAT_G8_B8R8_2PLANE_422_UNORM";
+ case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+ return "VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM";
+ case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
+ return "VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM";
+ case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
+ return "VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM";
+ case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG:
+ return "VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG";
+ case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG:
+ return "VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG";
+ case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG:
+ return "VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG";
+ case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG:
+ return "VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG";
+ case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG:
+ return "VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG";
+ case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG:
+ return "VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG";
+ case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG:
+ return "VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG";
+ case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG:
+ return "VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG";
+ case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
+ return "VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16";
+ case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
+ return "VK_FORMAT_R10X6G10X6_UNORM_2PACK16";
+ case VK_FORMAT_R10X6_UNORM_PACK16:
+ return "VK_FORMAT_R10X6_UNORM_PACK16";
+ case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
+ return "VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16";
+ case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
+ return "VK_FORMAT_R12X4G12X4_UNORM_2PACK16";
+ case VK_FORMAT_R12X4_UNORM_PACK16:
+ return "VK_FORMAT_R12X4_UNORM_PACK16";
+ case VK_FORMAT_R16G16B16A16_SFLOAT:
+ return "VK_FORMAT_R16G16B16A16_SFLOAT";
+ case VK_FORMAT_R16G16B16A16_SINT:
+ return "VK_FORMAT_R16G16B16A16_SINT";
+ case VK_FORMAT_R16G16B16A16_SNORM:
+ return "VK_FORMAT_R16G16B16A16_SNORM";
+ case VK_FORMAT_R16G16B16A16_SSCALED:
+ return "VK_FORMAT_R16G16B16A16_SSCALED";
+ case VK_FORMAT_R16G16B16A16_UINT:
+ return "VK_FORMAT_R16G16B16A16_UINT";
+ case VK_FORMAT_R16G16B16A16_UNORM:
+ return "VK_FORMAT_R16G16B16A16_UNORM";
+ case VK_FORMAT_R16G16B16A16_USCALED:
+ return "VK_FORMAT_R16G16B16A16_USCALED";
+ case VK_FORMAT_R16G16B16_SFLOAT:
+ return "VK_FORMAT_R16G16B16_SFLOAT";
+ case VK_FORMAT_R16G16B16_SINT:
+ return "VK_FORMAT_R16G16B16_SINT";
+ case VK_FORMAT_R16G16B16_SNORM:
+ return "VK_FORMAT_R16G16B16_SNORM";
+ case VK_FORMAT_R16G16B16_SSCALED:
+ return "VK_FORMAT_R16G16B16_SSCALED";
+ case VK_FORMAT_R16G16B16_UINT:
+ return "VK_FORMAT_R16G16B16_UINT";
+ case VK_FORMAT_R16G16B16_UNORM:
+ return "VK_FORMAT_R16G16B16_UNORM";
+ case VK_FORMAT_R16G16B16_USCALED:
+ return "VK_FORMAT_R16G16B16_USCALED";
+ case VK_FORMAT_R16G16_SFLOAT:
+ return "VK_FORMAT_R16G16_SFLOAT";
+ case VK_FORMAT_R16G16_SINT:
+ return "VK_FORMAT_R16G16_SINT";
+ case VK_FORMAT_R16G16_SNORM:
+ return "VK_FORMAT_R16G16_SNORM";
+ case VK_FORMAT_R16G16_SSCALED:
+ return "VK_FORMAT_R16G16_SSCALED";
+ case VK_FORMAT_R16G16_UINT:
+ return "VK_FORMAT_R16G16_UINT";
+ case VK_FORMAT_R16G16_UNORM:
+ return "VK_FORMAT_R16G16_UNORM";
+ case VK_FORMAT_R16G16_USCALED:
+ return "VK_FORMAT_R16G16_USCALED";
+ case VK_FORMAT_R16_SFLOAT:
+ return "VK_FORMAT_R16_SFLOAT";
+ case VK_FORMAT_R16_SINT:
+ return "VK_FORMAT_R16_SINT";
+ case VK_FORMAT_R16_SNORM:
+ return "VK_FORMAT_R16_SNORM";
+ case VK_FORMAT_R16_SSCALED:
+ return "VK_FORMAT_R16_SSCALED";
+ case VK_FORMAT_R16_UINT:
+ return "VK_FORMAT_R16_UINT";
+ case VK_FORMAT_R16_UNORM:
+ return "VK_FORMAT_R16_UNORM";
+ case VK_FORMAT_R16_USCALED:
+ return "VK_FORMAT_R16_USCALED";
+ case VK_FORMAT_R32G32B32A32_SFLOAT:
+ return "VK_FORMAT_R32G32B32A32_SFLOAT";
+ case VK_FORMAT_R32G32B32A32_SINT:
+ return "VK_FORMAT_R32G32B32A32_SINT";
+ case VK_FORMAT_R32G32B32A32_UINT:
+ return "VK_FORMAT_R32G32B32A32_UINT";
+ case VK_FORMAT_R32G32B32_SFLOAT:
+ return "VK_FORMAT_R32G32B32_SFLOAT";
+ case VK_FORMAT_R32G32B32_SINT:
+ return "VK_FORMAT_R32G32B32_SINT";
+ case VK_FORMAT_R32G32B32_UINT:
+ return "VK_FORMAT_R32G32B32_UINT";
+ case VK_FORMAT_R32G32_SFLOAT:
+ return "VK_FORMAT_R32G32_SFLOAT";
+ case VK_FORMAT_R32G32_SINT:
+ return "VK_FORMAT_R32G32_SINT";
+ case VK_FORMAT_R32G32_UINT:
+ return "VK_FORMAT_R32G32_UINT";
+ case VK_FORMAT_R32_SFLOAT:
+ return "VK_FORMAT_R32_SFLOAT";
+ case VK_FORMAT_R32_SINT:
+ return "VK_FORMAT_R32_SINT";
+ case VK_FORMAT_R32_UINT:
+ return "VK_FORMAT_R32_UINT";
+ case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
+ return "VK_FORMAT_R4G4B4A4_UNORM_PACK16";
+ case VK_FORMAT_R4G4_UNORM_PACK8:
+ return "VK_FORMAT_R4G4_UNORM_PACK8";
+ case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
+ return "VK_FORMAT_R5G5B5A1_UNORM_PACK16";
+ case VK_FORMAT_R5G6B5_UNORM_PACK16:
+ return "VK_FORMAT_R5G6B5_UNORM_PACK16";
+ case VK_FORMAT_R64G64B64A64_SFLOAT:
+ return "VK_FORMAT_R64G64B64A64_SFLOAT";
+ case VK_FORMAT_R64G64B64A64_SINT:
+ return "VK_FORMAT_R64G64B64A64_SINT";
+ case VK_FORMAT_R64G64B64A64_UINT:
+ return "VK_FORMAT_R64G64B64A64_UINT";
+ case VK_FORMAT_R64G64B64_SFLOAT:
+ return "VK_FORMAT_R64G64B64_SFLOAT";
+ case VK_FORMAT_R64G64B64_SINT:
+ return "VK_FORMAT_R64G64B64_SINT";
+ case VK_FORMAT_R64G64B64_UINT:
+ return "VK_FORMAT_R64G64B64_UINT";
+ case VK_FORMAT_R64G64_SFLOAT:
+ return "VK_FORMAT_R64G64_SFLOAT";
+ case VK_FORMAT_R64G64_SINT:
+ return "VK_FORMAT_R64G64_SINT";
+ case VK_FORMAT_R64G64_UINT:
+ return "VK_FORMAT_R64G64_UINT";
+ case VK_FORMAT_R64_SFLOAT:
+ return "VK_FORMAT_R64_SFLOAT";
+ case VK_FORMAT_R64_SINT:
+ return "VK_FORMAT_R64_SINT";
+ case VK_FORMAT_R64_UINT:
+ return "VK_FORMAT_R64_UINT";
+ case VK_FORMAT_R8G8B8A8_SINT:
+ return "VK_FORMAT_R8G8B8A8_SINT";
+ case VK_FORMAT_R8G8B8A8_SNORM:
+ return "VK_FORMAT_R8G8B8A8_SNORM";
+ case VK_FORMAT_R8G8B8A8_SRGB:
+ return "VK_FORMAT_R8G8B8A8_SRGB";
+ case VK_FORMAT_R8G8B8A8_SSCALED:
+ return "VK_FORMAT_R8G8B8A8_SSCALED";
+ case VK_FORMAT_R8G8B8A8_UINT:
+ return "VK_FORMAT_R8G8B8A8_UINT";
+ case VK_FORMAT_R8G8B8A8_UNORM:
+ return "VK_FORMAT_R8G8B8A8_UNORM";
+ case VK_FORMAT_R8G8B8A8_USCALED:
+ return "VK_FORMAT_R8G8B8A8_USCALED";
+ case VK_FORMAT_R8G8B8_SINT:
+ return "VK_FORMAT_R8G8B8_SINT";
+ case VK_FORMAT_R8G8B8_SNORM:
+ return "VK_FORMAT_R8G8B8_SNORM";
+ case VK_FORMAT_R8G8B8_SRGB:
+ return "VK_FORMAT_R8G8B8_SRGB";
+ case VK_FORMAT_R8G8B8_SSCALED:
+ return "VK_FORMAT_R8G8B8_SSCALED";
+ case VK_FORMAT_R8G8B8_UINT:
+ return "VK_FORMAT_R8G8B8_UINT";
+ case VK_FORMAT_R8G8B8_UNORM:
+ return "VK_FORMAT_R8G8B8_UNORM";
+ case VK_FORMAT_R8G8B8_USCALED:
+ return "VK_FORMAT_R8G8B8_USCALED";
+ case VK_FORMAT_R8G8_SINT:
+ return "VK_FORMAT_R8G8_SINT";
+ case VK_FORMAT_R8G8_SNORM:
+ return "VK_FORMAT_R8G8_SNORM";
+ case VK_FORMAT_R8G8_SRGB:
+ return "VK_FORMAT_R8G8_SRGB";
+ case VK_FORMAT_R8G8_SSCALED:
+ return "VK_FORMAT_R8G8_SSCALED";
+ case VK_FORMAT_R8G8_UINT:
+ return "VK_FORMAT_R8G8_UINT";
+ case VK_FORMAT_R8G8_UNORM:
+ return "VK_FORMAT_R8G8_UNORM";
+ case VK_FORMAT_R8G8_USCALED:
+ return "VK_FORMAT_R8G8_USCALED";
+ case VK_FORMAT_R8_SINT:
+ return "VK_FORMAT_R8_SINT";
+ case VK_FORMAT_R8_SNORM:
+ return "VK_FORMAT_R8_SNORM";
+ case VK_FORMAT_R8_SRGB:
+ return "VK_FORMAT_R8_SRGB";
+ case VK_FORMAT_R8_SSCALED:
+ return "VK_FORMAT_R8_SSCALED";
+ case VK_FORMAT_R8_UINT:
+ return "VK_FORMAT_R8_UINT";
+ case VK_FORMAT_R8_UNORM:
+ return "VK_FORMAT_R8_UNORM";
+ case VK_FORMAT_R8_USCALED:
+ return "VK_FORMAT_R8_USCALED";
+ case VK_FORMAT_S8_UINT:
+ return "VK_FORMAT_S8_UINT";
+ case VK_FORMAT_UNDEFINED:
+ return "VK_FORMAT_UNDEFINED";
+ case VK_FORMAT_X8_D24_UNORM_PACK32:
+ return "VK_FORMAT_X8_D24_UNORM_PACK32";
+ default:
+ return "Unhandled VkFormat";
+ }
+}
+
+static inline const char* string_VkFormatFeatureFlagBits(VkFormatFeatureFlagBits input_value)
+{
+ switch ((VkFormatFeatureFlagBits)input_value)
+ {
+ case VK_FORMAT_FEATURE_BLIT_DST_BIT:
+ return "VK_FORMAT_FEATURE_BLIT_DST_BIT";
+ case VK_FORMAT_FEATURE_BLIT_SRC_BIT:
+ return "VK_FORMAT_FEATURE_BLIT_SRC_BIT";
+ case VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT:
+ return "VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT";
+ case VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT:
+ return "VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT";
+ case VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT:
+ return "VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT";
+ case VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT:
+ return "VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT";
+ case VK_FORMAT_FEATURE_DISJOINT_BIT:
+ return "VK_FORMAT_FEATURE_DISJOINT_BIT";
+ case VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT:
+ return "VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT";
+ case VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT:
+ return "VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT";
+ case VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT:
+ return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT";
+ case VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG:
+ return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG";
+ case VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT:
+ return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT";
+ case VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT:
+ return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT";
+ case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT:
+ return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT";
+ case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT:
+ return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT";
+ case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT:
+ return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT";
+ case VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT:
+ return "VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT";
+ case VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT:
+ return "VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT";
+ case VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT:
+ return "VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT";
+ case VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT:
+ return "VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT";
+ case VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT:
+ return "VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT";
+ case VK_FORMAT_FEATURE_TRANSFER_DST_BIT:
+ return "VK_FORMAT_FEATURE_TRANSFER_DST_BIT";
+ case VK_FORMAT_FEATURE_TRANSFER_SRC_BIT:
+ return "VK_FORMAT_FEATURE_TRANSFER_SRC_BIT";
+ case VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT:
+ return "VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT";
+ case VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT:
+ return "VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT";
+ default:
+ return "Unhandled VkFormatFeatureFlagBits";
+ }
+}
+
+static inline std::string string_VkFormatFeatureFlags(VkFormatFeatureFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkFormatFeatureFlagBits(static_cast<VkFormatFeatureFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkFormatFeatureFlagBits(static_cast<VkFormatFeatureFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkImageType(VkImageType input_value)
+{
+ switch ((VkImageType)input_value)
+ {
+ case VK_IMAGE_TYPE_1D:
+ return "VK_IMAGE_TYPE_1D";
+ case VK_IMAGE_TYPE_2D:
+ return "VK_IMAGE_TYPE_2D";
+ case VK_IMAGE_TYPE_3D:
+ return "VK_IMAGE_TYPE_3D";
+ default:
+ return "Unhandled VkImageType";
+ }
+}
+
+static inline const char* string_VkImageTiling(VkImageTiling input_value)
+{
+ switch ((VkImageTiling)input_value)
+ {
+ case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
+ return "VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT";
+ case VK_IMAGE_TILING_LINEAR:
+ return "VK_IMAGE_TILING_LINEAR";
+ case VK_IMAGE_TILING_OPTIMAL:
+ return "VK_IMAGE_TILING_OPTIMAL";
+ default:
+ return "Unhandled VkImageTiling";
+ }
+}
+
+static inline const char* string_VkImageUsageFlagBits(VkImageUsageFlagBits input_value)
+{
+ switch ((VkImageUsageFlagBits)input_value)
+ {
+ case VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:
+ return "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT";
+ case VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT:
+ return "VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT";
+ case VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT:
+ return "VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT";
+ case VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT:
+ return "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT";
+ case VK_IMAGE_USAGE_SAMPLED_BIT:
+ return "VK_IMAGE_USAGE_SAMPLED_BIT";
+ case VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV:
+ return "VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV";
+ case VK_IMAGE_USAGE_STORAGE_BIT:
+ return "VK_IMAGE_USAGE_STORAGE_BIT";
+ case VK_IMAGE_USAGE_TRANSFER_DST_BIT:
+ return "VK_IMAGE_USAGE_TRANSFER_DST_BIT";
+ case VK_IMAGE_USAGE_TRANSFER_SRC_BIT:
+ return "VK_IMAGE_USAGE_TRANSFER_SRC_BIT";
+ case VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT:
+ return "VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT";
+ default:
+ return "Unhandled VkImageUsageFlagBits";
+ }
+}
+
+static inline std::string string_VkImageUsageFlags(VkImageUsageFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkImageUsageFlagBits(static_cast<VkImageUsageFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkImageUsageFlagBits(static_cast<VkImageUsageFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkImageCreateFlagBits(VkImageCreateFlagBits input_value)
+{
+ switch ((VkImageCreateFlagBits)input_value)
+ {
+ case VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT:
+ return "VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT";
+ case VK_IMAGE_CREATE_ALIAS_BIT:
+ return "VK_IMAGE_CREATE_ALIAS_BIT";
+ case VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT:
+ return "VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT";
+ case VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV:
+ return "VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV";
+ case VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT:
+ return "VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT";
+ case VK_IMAGE_CREATE_DISJOINT_BIT:
+ return "VK_IMAGE_CREATE_DISJOINT_BIT";
+ case VK_IMAGE_CREATE_EXTENDED_USAGE_BIT:
+ return "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT";
+ case VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT:
+ return "VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT";
+ case VK_IMAGE_CREATE_PROTECTED_BIT:
+ return "VK_IMAGE_CREATE_PROTECTED_BIT";
+ case VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT:
+ return "VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT";
+ case VK_IMAGE_CREATE_SPARSE_ALIASED_BIT:
+ return "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT";
+ case VK_IMAGE_CREATE_SPARSE_BINDING_BIT:
+ return "VK_IMAGE_CREATE_SPARSE_BINDING_BIT";
+ case VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT:
+ return "VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT";
+ case VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT:
+ return "VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT";
+ case VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT:
+ return "VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT";
+ default:
+ return "Unhandled VkImageCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkImageCreateFlags(VkImageCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkImageCreateFlagBits(static_cast<VkImageCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkImageCreateFlagBits(static_cast<VkImageCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkSampleCountFlagBits(VkSampleCountFlagBits input_value)
+{
+ switch ((VkSampleCountFlagBits)input_value)
+ {
+ case VK_SAMPLE_COUNT_16_BIT:
+ return "VK_SAMPLE_COUNT_16_BIT";
+ case VK_SAMPLE_COUNT_1_BIT:
+ return "VK_SAMPLE_COUNT_1_BIT";
+ case VK_SAMPLE_COUNT_2_BIT:
+ return "VK_SAMPLE_COUNT_2_BIT";
+ case VK_SAMPLE_COUNT_32_BIT:
+ return "VK_SAMPLE_COUNT_32_BIT";
+ case VK_SAMPLE_COUNT_4_BIT:
+ return "VK_SAMPLE_COUNT_4_BIT";
+ case VK_SAMPLE_COUNT_64_BIT:
+ return "VK_SAMPLE_COUNT_64_BIT";
+ case VK_SAMPLE_COUNT_8_BIT:
+ return "VK_SAMPLE_COUNT_8_BIT";
+ default:
+ return "Unhandled VkSampleCountFlagBits";
+ }
+}
+
+static inline std::string string_VkSampleCountFlags(VkSampleCountFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSampleCountFlagBits(static_cast<VkSampleCountFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSampleCountFlagBits(static_cast<VkSampleCountFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPhysicalDeviceType(VkPhysicalDeviceType input_value)
+{
+ switch ((VkPhysicalDeviceType)input_value)
+ {
+ case VK_PHYSICAL_DEVICE_TYPE_CPU:
+ return "VK_PHYSICAL_DEVICE_TYPE_CPU";
+ case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
+ return "VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU";
+ case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
+ return "VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU";
+ case VK_PHYSICAL_DEVICE_TYPE_OTHER:
+ return "VK_PHYSICAL_DEVICE_TYPE_OTHER";
+ case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
+ return "VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU";
+ default:
+ return "Unhandled VkPhysicalDeviceType";
+ }
+}
+
+static inline const char* string_VkQueueFlagBits(VkQueueFlagBits input_value)
+{
+ switch ((VkQueueFlagBits)input_value)
+ {
+ case VK_QUEUE_COMPUTE_BIT:
+ return "VK_QUEUE_COMPUTE_BIT";
+ case VK_QUEUE_GRAPHICS_BIT:
+ return "VK_QUEUE_GRAPHICS_BIT";
+ case VK_QUEUE_PROTECTED_BIT:
+ return "VK_QUEUE_PROTECTED_BIT";
+ case VK_QUEUE_SPARSE_BINDING_BIT:
+ return "VK_QUEUE_SPARSE_BINDING_BIT";
+ case VK_QUEUE_TRANSFER_BIT:
+ return "VK_QUEUE_TRANSFER_BIT";
+ default:
+ return "Unhandled VkQueueFlagBits";
+ }
+}
+
+static inline std::string string_VkQueueFlags(VkQueueFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkQueueFlagBits(static_cast<VkQueueFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkQueueFlagBits(static_cast<VkQueueFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkMemoryPropertyFlagBits(VkMemoryPropertyFlagBits input_value)
+{
+ switch ((VkMemoryPropertyFlagBits)input_value)
+ {
+ case VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD:
+ return "VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD";
+ case VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT:
+ return "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT";
+ case VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD:
+ return "VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD";
+ case VK_MEMORY_PROPERTY_HOST_CACHED_BIT:
+ return "VK_MEMORY_PROPERTY_HOST_CACHED_BIT";
+ case VK_MEMORY_PROPERTY_HOST_COHERENT_BIT:
+ return "VK_MEMORY_PROPERTY_HOST_COHERENT_BIT";
+ case VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT:
+ return "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT";
+ case VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT:
+ return "VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT";
+ case VK_MEMORY_PROPERTY_PROTECTED_BIT:
+ return "VK_MEMORY_PROPERTY_PROTECTED_BIT";
+ default:
+ return "Unhandled VkMemoryPropertyFlagBits";
+ }
+}
+
+static inline std::string string_VkMemoryPropertyFlags(VkMemoryPropertyFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkMemoryPropertyFlagBits(static_cast<VkMemoryPropertyFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkMemoryPropertyFlagBits(static_cast<VkMemoryPropertyFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkMemoryHeapFlagBits(VkMemoryHeapFlagBits input_value)
+{
+ switch ((VkMemoryHeapFlagBits)input_value)
+ {
+ case VK_MEMORY_HEAP_DEVICE_LOCAL_BIT:
+ return "VK_MEMORY_HEAP_DEVICE_LOCAL_BIT";
+ case VK_MEMORY_HEAP_MULTI_INSTANCE_BIT:
+ return "VK_MEMORY_HEAP_MULTI_INSTANCE_BIT";
+ default:
+ return "Unhandled VkMemoryHeapFlagBits";
+ }
+}
+
+static inline std::string string_VkMemoryHeapFlags(VkMemoryHeapFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkMemoryHeapFlagBits(static_cast<VkMemoryHeapFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkMemoryHeapFlagBits(static_cast<VkMemoryHeapFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDeviceQueueCreateFlagBits(VkDeviceQueueCreateFlagBits input_value)
+{
+ switch ((VkDeviceQueueCreateFlagBits)input_value)
+ {
+ case VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT:
+ return "VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT";
+ default:
+ return "Unhandled VkDeviceQueueCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkDeviceQueueCreateFlags(VkDeviceQueueCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDeviceQueueCreateFlagBits(static_cast<VkDeviceQueueCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDeviceQueueCreateFlagBits(static_cast<VkDeviceQueueCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPipelineStageFlagBits(VkPipelineStageFlagBits input_value)
+{
+ switch ((VkPipelineStageFlagBits)input_value)
+ {
+ case VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV:
+ return "VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV";
+ case VK_PIPELINE_STAGE_ALL_COMMANDS_BIT:
+ return "VK_PIPELINE_STAGE_ALL_COMMANDS_BIT";
+ case VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT:
+ return "VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT";
+ case VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT:
+ return "VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT";
+ case VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT:
+ return "VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT";
+ case VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX:
+ return "VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX";
+ case VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT:
+ return "VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT";
+ case VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT:
+ return "VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT";
+ case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT:
+ return "VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT";
+ case VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT:
+ return "VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT";
+ case VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT:
+ return "VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT";
+ case VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT:
+ return "VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT";
+ case VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT:
+ return "VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT";
+ case VK_PIPELINE_STAGE_HOST_BIT:
+ return "VK_PIPELINE_STAGE_HOST_BIT";
+ case VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT:
+ return "VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT";
+ case VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV:
+ return "VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV";
+ case VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV:
+ return "VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV";
+ case VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV:
+ return "VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV";
+ case VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV:
+ return "VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV";
+ case VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT:
+ return "VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT";
+ case VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT:
+ return "VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT";
+ case VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT:
+ return "VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT";
+ case VK_PIPELINE_STAGE_TRANSFER_BIT:
+ return "VK_PIPELINE_STAGE_TRANSFER_BIT";
+ case VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT:
+ return "VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT";
+ case VK_PIPELINE_STAGE_VERTEX_INPUT_BIT:
+ return "VK_PIPELINE_STAGE_VERTEX_INPUT_BIT";
+ case VK_PIPELINE_STAGE_VERTEX_SHADER_BIT:
+ return "VK_PIPELINE_STAGE_VERTEX_SHADER_BIT";
+ default:
+ return "Unhandled VkPipelineStageFlagBits";
+ }
+}
+
+static inline std::string string_VkPipelineStageFlags(VkPipelineStageFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkPipelineStageFlagBits(static_cast<VkPipelineStageFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkPipelineStageFlagBits(static_cast<VkPipelineStageFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkImageAspectFlagBits(VkImageAspectFlagBits input_value)
+{
+ switch ((VkImageAspectFlagBits)input_value)
+ {
+ case VK_IMAGE_ASPECT_COLOR_BIT:
+ return "VK_IMAGE_ASPECT_COLOR_BIT";
+ case VK_IMAGE_ASPECT_DEPTH_BIT:
+ return "VK_IMAGE_ASPECT_DEPTH_BIT";
+ case VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT:
+ return "VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT";
+ case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT:
+ return "VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT";
+ case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT:
+ return "VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT";
+ case VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT:
+ return "VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT";
+ case VK_IMAGE_ASPECT_METADATA_BIT:
+ return "VK_IMAGE_ASPECT_METADATA_BIT";
+ case VK_IMAGE_ASPECT_PLANE_0_BIT:
+ return "VK_IMAGE_ASPECT_PLANE_0_BIT";
+ case VK_IMAGE_ASPECT_PLANE_1_BIT:
+ return "VK_IMAGE_ASPECT_PLANE_1_BIT";
+ case VK_IMAGE_ASPECT_PLANE_2_BIT:
+ return "VK_IMAGE_ASPECT_PLANE_2_BIT";
+ case VK_IMAGE_ASPECT_STENCIL_BIT:
+ return "VK_IMAGE_ASPECT_STENCIL_BIT";
+ default:
+ return "Unhandled VkImageAspectFlagBits";
+ }
+}
+
+static inline std::string string_VkImageAspectFlags(VkImageAspectFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkImageAspectFlagBits(static_cast<VkImageAspectFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkImageAspectFlagBits(static_cast<VkImageAspectFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkSparseImageFormatFlagBits(VkSparseImageFormatFlagBits input_value)
+{
+ switch ((VkSparseImageFormatFlagBits)input_value)
+ {
+ case VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT:
+ return "VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT";
+ case VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT:
+ return "VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT";
+ case VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT:
+ return "VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT";
+ default:
+ return "Unhandled VkSparseImageFormatFlagBits";
+ }
+}
+
+static inline std::string string_VkSparseImageFormatFlags(VkSparseImageFormatFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSparseImageFormatFlagBits(static_cast<VkSparseImageFormatFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSparseImageFormatFlagBits(static_cast<VkSparseImageFormatFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkSparseMemoryBindFlagBits(VkSparseMemoryBindFlagBits input_value)
+{
+ switch ((VkSparseMemoryBindFlagBits)input_value)
+ {
+ case VK_SPARSE_MEMORY_BIND_METADATA_BIT:
+ return "VK_SPARSE_MEMORY_BIND_METADATA_BIT";
+ default:
+ return "Unhandled VkSparseMemoryBindFlagBits";
+ }
+}
+
+static inline std::string string_VkSparseMemoryBindFlags(VkSparseMemoryBindFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSparseMemoryBindFlagBits(static_cast<VkSparseMemoryBindFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSparseMemoryBindFlagBits(static_cast<VkSparseMemoryBindFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkFenceCreateFlagBits(VkFenceCreateFlagBits input_value)
+{
+ switch ((VkFenceCreateFlagBits)input_value)
+ {
+ case VK_FENCE_CREATE_SIGNALED_BIT:
+ return "VK_FENCE_CREATE_SIGNALED_BIT";
+ default:
+ return "Unhandled VkFenceCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkFenceCreateFlags(VkFenceCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkFenceCreateFlagBits(static_cast<VkFenceCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkFenceCreateFlagBits(static_cast<VkFenceCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkQueryType(VkQueryType input_value)
+{
+ switch ((VkQueryType)input_value)
+ {
+ case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV:
+ return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV";
+ case VK_QUERY_TYPE_OCCLUSION:
+ return "VK_QUERY_TYPE_OCCLUSION";
+ case VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL:
+ return "VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL";
+ case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
+ return "VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR";
+ case VK_QUERY_TYPE_PIPELINE_STATISTICS:
+ return "VK_QUERY_TYPE_PIPELINE_STATISTICS";
+ case VK_QUERY_TYPE_TIMESTAMP:
+ return "VK_QUERY_TYPE_TIMESTAMP";
+ case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
+ return "VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT";
+ default:
+ return "Unhandled VkQueryType";
+ }
+}
+
+static inline const char* string_VkQueryPipelineStatisticFlagBits(VkQueryPipelineStatisticFlagBits input_value)
+{
+ switch ((VkQueryPipelineStatisticFlagBits)input_value)
+ {
+ case VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT";
+ case VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT";
+ case VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT";
+ case VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT";
+ case VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT";
+ case VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT";
+ case VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT";
+ case VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT";
+ case VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT";
+ case VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT";
+ case VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT:
+ return "VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT";
+ default:
+ return "Unhandled VkQueryPipelineStatisticFlagBits";
+ }
+}
+
+static inline std::string string_VkQueryPipelineStatisticFlags(VkQueryPipelineStatisticFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkQueryPipelineStatisticFlagBits(static_cast<VkQueryPipelineStatisticFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkQueryPipelineStatisticFlagBits(static_cast<VkQueryPipelineStatisticFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkQueryResultFlagBits(VkQueryResultFlagBits input_value)
+{
+ switch ((VkQueryResultFlagBits)input_value)
+ {
+ case VK_QUERY_RESULT_64_BIT:
+ return "VK_QUERY_RESULT_64_BIT";
+ case VK_QUERY_RESULT_PARTIAL_BIT:
+ return "VK_QUERY_RESULT_PARTIAL_BIT";
+ case VK_QUERY_RESULT_WAIT_BIT:
+ return "VK_QUERY_RESULT_WAIT_BIT";
+ case VK_QUERY_RESULT_WITH_AVAILABILITY_BIT:
+ return "VK_QUERY_RESULT_WITH_AVAILABILITY_BIT";
+ default:
+ return "Unhandled VkQueryResultFlagBits";
+ }
+}
+
+static inline std::string string_VkQueryResultFlags(VkQueryResultFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkQueryResultFlagBits(static_cast<VkQueryResultFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkQueryResultFlagBits(static_cast<VkQueryResultFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkBufferCreateFlagBits(VkBufferCreateFlagBits input_value)
+{
+ switch ((VkBufferCreateFlagBits)input_value)
+ {
+ case VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT:
+ return "VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT";
+ case VK_BUFFER_CREATE_PROTECTED_BIT:
+ return "VK_BUFFER_CREATE_PROTECTED_BIT";
+ case VK_BUFFER_CREATE_SPARSE_ALIASED_BIT:
+ return "VK_BUFFER_CREATE_SPARSE_ALIASED_BIT";
+ case VK_BUFFER_CREATE_SPARSE_BINDING_BIT:
+ return "VK_BUFFER_CREATE_SPARSE_BINDING_BIT";
+ case VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT:
+ return "VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT";
+ default:
+ return "Unhandled VkBufferCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkBufferCreateFlags(VkBufferCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkBufferCreateFlagBits(static_cast<VkBufferCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkBufferCreateFlagBits(static_cast<VkBufferCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkBufferUsageFlagBits(VkBufferUsageFlagBits input_value)
+{
+ switch ((VkBufferUsageFlagBits)input_value)
+ {
+ case VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT:
+ return "VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT";
+ case VK_BUFFER_USAGE_INDEX_BUFFER_BIT:
+ return "VK_BUFFER_USAGE_INDEX_BUFFER_BIT";
+ case VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT:
+ return "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT";
+ case VK_BUFFER_USAGE_RAY_TRACING_BIT_NV:
+ return "VK_BUFFER_USAGE_RAY_TRACING_BIT_NV";
+ case VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT:
+ return "VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT";
+ case VK_BUFFER_USAGE_STORAGE_BUFFER_BIT:
+ return "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT";
+ case VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT:
+ return "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT";
+ case VK_BUFFER_USAGE_TRANSFER_DST_BIT:
+ return "VK_BUFFER_USAGE_TRANSFER_DST_BIT";
+ case VK_BUFFER_USAGE_TRANSFER_SRC_BIT:
+ return "VK_BUFFER_USAGE_TRANSFER_SRC_BIT";
+ case VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT:
+ return "VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT";
+ case VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT:
+ return "VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT";
+ case VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT:
+ return "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT";
+ case VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT:
+ return "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT";
+ case VK_BUFFER_USAGE_VERTEX_BUFFER_BIT:
+ return "VK_BUFFER_USAGE_VERTEX_BUFFER_BIT";
+ default:
+ return "Unhandled VkBufferUsageFlagBits";
+ }
+}
+
+static inline std::string string_VkBufferUsageFlags(VkBufferUsageFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkBufferUsageFlagBits(static_cast<VkBufferUsageFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkBufferUsageFlagBits(static_cast<VkBufferUsageFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkSharingMode(VkSharingMode input_value)
+{
+ switch ((VkSharingMode)input_value)
+ {
+ case VK_SHARING_MODE_CONCURRENT:
+ return "VK_SHARING_MODE_CONCURRENT";
+ case VK_SHARING_MODE_EXCLUSIVE:
+ return "VK_SHARING_MODE_EXCLUSIVE";
+ default:
+ return "Unhandled VkSharingMode";
+ }
+}
+
+static inline const char* string_VkImageLayout(VkImageLayout input_value)
+{
+ switch ((VkImageLayout)input_value)
+ {
+ case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL";
+ case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL";
+ case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL";
+ case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL";
+ case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL";
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL";
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL";
+ case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT:
+ return "VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT";
+ case VK_IMAGE_LAYOUT_GENERAL:
+ return "VK_IMAGE_LAYOUT_GENERAL";
+ case VK_IMAGE_LAYOUT_PREINITIALIZED:
+ return "VK_IMAGE_LAYOUT_PREINITIALIZED";
+ case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
+ return "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR";
+ case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL";
+ case VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV:
+ return "VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV";
+ case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
+ return "VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR";
+ case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL";
+ case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL";
+ case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL";
+ case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
+ return "VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL";
+ case VK_IMAGE_LAYOUT_UNDEFINED:
+ return "VK_IMAGE_LAYOUT_UNDEFINED";
+ default:
+ return "Unhandled VkImageLayout";
+ }
+}
+
+static inline const char* string_VkImageViewCreateFlagBits(VkImageViewCreateFlagBits input_value)
+{
+ switch ((VkImageViewCreateFlagBits)input_value)
+ {
+ case VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT:
+ return "VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT";
+ default:
+ return "Unhandled VkImageViewCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkImageViewCreateFlags(VkImageViewCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkImageViewCreateFlagBits(static_cast<VkImageViewCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkImageViewCreateFlagBits(static_cast<VkImageViewCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkImageViewType(VkImageViewType input_value)
+{
+ switch ((VkImageViewType)input_value)
+ {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ return "VK_IMAGE_VIEW_TYPE_1D";
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ return "VK_IMAGE_VIEW_TYPE_1D_ARRAY";
+ case VK_IMAGE_VIEW_TYPE_2D:
+ return "VK_IMAGE_VIEW_TYPE_2D";
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ return "VK_IMAGE_VIEW_TYPE_2D_ARRAY";
+ case VK_IMAGE_VIEW_TYPE_3D:
+ return "VK_IMAGE_VIEW_TYPE_3D";
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ return "VK_IMAGE_VIEW_TYPE_CUBE";
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ return "VK_IMAGE_VIEW_TYPE_CUBE_ARRAY";
+ default:
+ return "Unhandled VkImageViewType";
+ }
+}
+
+static inline const char* string_VkComponentSwizzle(VkComponentSwizzle input_value)
+{
+ switch ((VkComponentSwizzle)input_value)
+ {
+ case VK_COMPONENT_SWIZZLE_A:
+ return "VK_COMPONENT_SWIZZLE_A";
+ case VK_COMPONENT_SWIZZLE_B:
+ return "VK_COMPONENT_SWIZZLE_B";
+ case VK_COMPONENT_SWIZZLE_G:
+ return "VK_COMPONENT_SWIZZLE_G";
+ case VK_COMPONENT_SWIZZLE_IDENTITY:
+ return "VK_COMPONENT_SWIZZLE_IDENTITY";
+ case VK_COMPONENT_SWIZZLE_ONE:
+ return "VK_COMPONENT_SWIZZLE_ONE";
+ case VK_COMPONENT_SWIZZLE_R:
+ return "VK_COMPONENT_SWIZZLE_R";
+ case VK_COMPONENT_SWIZZLE_ZERO:
+ return "VK_COMPONENT_SWIZZLE_ZERO";
+ default:
+ return "Unhandled VkComponentSwizzle";
+ }
+}
+
+static inline const char* string_VkPipelineCreateFlagBits(VkPipelineCreateFlagBits input_value)
+{
+ switch ((VkPipelineCreateFlagBits)input_value)
+ {
+ case VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT:
+ return "VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT";
+ case VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR:
+ return "VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR";
+ case VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR:
+ return "VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR";
+ case VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV:
+ return "VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV";
+ case VK_PIPELINE_CREATE_DERIVATIVE_BIT:
+ return "VK_PIPELINE_CREATE_DERIVATIVE_BIT";
+ case VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT:
+ return "VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT";
+ case VK_PIPELINE_CREATE_DISPATCH_BASE_BIT:
+ return "VK_PIPELINE_CREATE_DISPATCH_BASE_BIT";
+ case VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT:
+ return "VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT";
+ default:
+ return "Unhandled VkPipelineCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkPipelineCreateFlags(VkPipelineCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkPipelineCreateFlagBits(static_cast<VkPipelineCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkPipelineCreateFlagBits(static_cast<VkPipelineCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPipelineShaderStageCreateFlagBits(VkPipelineShaderStageCreateFlagBits input_value)
+{
+ switch ((VkPipelineShaderStageCreateFlagBits)input_value)
+ {
+ case VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT:
+ return "VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT";
+ case VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT:
+ return "VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT";
+ default:
+ return "Unhandled VkPipelineShaderStageCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkPipelineShaderStageCreateFlags(VkPipelineShaderStageCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkPipelineShaderStageCreateFlagBits(static_cast<VkPipelineShaderStageCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkPipelineShaderStageCreateFlagBits(static_cast<VkPipelineShaderStageCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkShaderStageFlagBits(VkShaderStageFlagBits input_value)
+{
+ switch ((VkShaderStageFlagBits)input_value)
+ {
+ case VK_SHADER_STAGE_ALL:
+ return "VK_SHADER_STAGE_ALL";
+ case VK_SHADER_STAGE_ALL_GRAPHICS:
+ return "VK_SHADER_STAGE_ALL_GRAPHICS";
+ case VK_SHADER_STAGE_ANY_HIT_BIT_NV:
+ return "VK_SHADER_STAGE_ANY_HIT_BIT_NV";
+ case VK_SHADER_STAGE_CALLABLE_BIT_NV:
+ return "VK_SHADER_STAGE_CALLABLE_BIT_NV";
+ case VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV:
+ return "VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV";
+ case VK_SHADER_STAGE_COMPUTE_BIT:
+ return "VK_SHADER_STAGE_COMPUTE_BIT";
+ case VK_SHADER_STAGE_FRAGMENT_BIT:
+ return "VK_SHADER_STAGE_FRAGMENT_BIT";
+ case VK_SHADER_STAGE_GEOMETRY_BIT:
+ return "VK_SHADER_STAGE_GEOMETRY_BIT";
+ case VK_SHADER_STAGE_INTERSECTION_BIT_NV:
+ return "VK_SHADER_STAGE_INTERSECTION_BIT_NV";
+ case VK_SHADER_STAGE_MESH_BIT_NV:
+ return "VK_SHADER_STAGE_MESH_BIT_NV";
+ case VK_SHADER_STAGE_MISS_BIT_NV:
+ return "VK_SHADER_STAGE_MISS_BIT_NV";
+ case VK_SHADER_STAGE_RAYGEN_BIT_NV:
+ return "VK_SHADER_STAGE_RAYGEN_BIT_NV";
+ case VK_SHADER_STAGE_TASK_BIT_NV:
+ return "VK_SHADER_STAGE_TASK_BIT_NV";
+ case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
+ return "VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT";
+ case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
+ return "VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT";
+ case VK_SHADER_STAGE_VERTEX_BIT:
+ return "VK_SHADER_STAGE_VERTEX_BIT";
+ default:
+ return "Unhandled VkShaderStageFlagBits";
+ }
+}
+
+static inline std::string string_VkShaderStageFlags(VkShaderStageFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkShaderStageFlagBits(static_cast<VkShaderStageFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkShaderStageFlagBits(static_cast<VkShaderStageFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkVertexInputRate(VkVertexInputRate input_value)
+{
+ switch ((VkVertexInputRate)input_value)
+ {
+ case VK_VERTEX_INPUT_RATE_INSTANCE:
+ return "VK_VERTEX_INPUT_RATE_INSTANCE";
+ case VK_VERTEX_INPUT_RATE_VERTEX:
+ return "VK_VERTEX_INPUT_RATE_VERTEX";
+ default:
+ return "Unhandled VkVertexInputRate";
+ }
+}
+
+static inline const char* string_VkPrimitiveTopology(VkPrimitiveTopology input_value)
+{
+ switch ((VkPrimitiveTopology)input_value)
+ {
+ case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
+ return "VK_PRIMITIVE_TOPOLOGY_LINE_LIST";
+ case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
+ return "VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY";
+ case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
+ return "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP";
+ case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
+ return "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY";
+ case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
+ return "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST";
+ case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
+ return "VK_PRIMITIVE_TOPOLOGY_POINT_LIST";
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
+ return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN";
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
+ return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST";
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
+ return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY";
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
+ return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP";
+ case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
+ return "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY";
+ default:
+ return "Unhandled VkPrimitiveTopology";
+ }
+}
+
+static inline const char* string_VkPolygonMode(VkPolygonMode input_value)
+{
+ switch ((VkPolygonMode)input_value)
+ {
+ case VK_POLYGON_MODE_FILL:
+ return "VK_POLYGON_MODE_FILL";
+ case VK_POLYGON_MODE_FILL_RECTANGLE_NV:
+ return "VK_POLYGON_MODE_FILL_RECTANGLE_NV";
+ case VK_POLYGON_MODE_LINE:
+ return "VK_POLYGON_MODE_LINE";
+ case VK_POLYGON_MODE_POINT:
+ return "VK_POLYGON_MODE_POINT";
+ default:
+ return "Unhandled VkPolygonMode";
+ }
+}
+
+static inline const char* string_VkCullModeFlagBits(VkCullModeFlagBits input_value)
+{
+ switch ((VkCullModeFlagBits)input_value)
+ {
+ case VK_CULL_MODE_BACK_BIT:
+ return "VK_CULL_MODE_BACK_BIT";
+ case VK_CULL_MODE_FRONT_AND_BACK:
+ return "VK_CULL_MODE_FRONT_AND_BACK";
+ case VK_CULL_MODE_FRONT_BIT:
+ return "VK_CULL_MODE_FRONT_BIT";
+ case VK_CULL_MODE_NONE:
+ return "VK_CULL_MODE_NONE";
+ default:
+ return "Unhandled VkCullModeFlagBits";
+ }
+}
+
+static inline std::string string_VkCullModeFlags(VkCullModeFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkCullModeFlagBits(static_cast<VkCullModeFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkCullModeFlagBits(static_cast<VkCullModeFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkFrontFace(VkFrontFace input_value)
+{
+ switch ((VkFrontFace)input_value)
+ {
+ case VK_FRONT_FACE_CLOCKWISE:
+ return "VK_FRONT_FACE_CLOCKWISE";
+ case VK_FRONT_FACE_COUNTER_CLOCKWISE:
+ return "VK_FRONT_FACE_COUNTER_CLOCKWISE";
+ default:
+ return "Unhandled VkFrontFace";
+ }
+}
+
+static inline const char* string_VkCompareOp(VkCompareOp input_value)
+{
+ switch ((VkCompareOp)input_value)
+ {
+ case VK_COMPARE_OP_ALWAYS:
+ return "VK_COMPARE_OP_ALWAYS";
+ case VK_COMPARE_OP_EQUAL:
+ return "VK_COMPARE_OP_EQUAL";
+ case VK_COMPARE_OP_GREATER:
+ return "VK_COMPARE_OP_GREATER";
+ case VK_COMPARE_OP_GREATER_OR_EQUAL:
+ return "VK_COMPARE_OP_GREATER_OR_EQUAL";
+ case VK_COMPARE_OP_LESS:
+ return "VK_COMPARE_OP_LESS";
+ case VK_COMPARE_OP_LESS_OR_EQUAL:
+ return "VK_COMPARE_OP_LESS_OR_EQUAL";
+ case VK_COMPARE_OP_NEVER:
+ return "VK_COMPARE_OP_NEVER";
+ case VK_COMPARE_OP_NOT_EQUAL:
+ return "VK_COMPARE_OP_NOT_EQUAL";
+ default:
+ return "Unhandled VkCompareOp";
+ }
+}
+
+static inline const char* string_VkStencilOp(VkStencilOp input_value)
+{
+ switch ((VkStencilOp)input_value)
+ {
+ case VK_STENCIL_OP_DECREMENT_AND_CLAMP:
+ return "VK_STENCIL_OP_DECREMENT_AND_CLAMP";
+ case VK_STENCIL_OP_DECREMENT_AND_WRAP:
+ return "VK_STENCIL_OP_DECREMENT_AND_WRAP";
+ case VK_STENCIL_OP_INCREMENT_AND_CLAMP:
+ return "VK_STENCIL_OP_INCREMENT_AND_CLAMP";
+ case VK_STENCIL_OP_INCREMENT_AND_WRAP:
+ return "VK_STENCIL_OP_INCREMENT_AND_WRAP";
+ case VK_STENCIL_OP_INVERT:
+ return "VK_STENCIL_OP_INVERT";
+ case VK_STENCIL_OP_KEEP:
+ return "VK_STENCIL_OP_KEEP";
+ case VK_STENCIL_OP_REPLACE:
+ return "VK_STENCIL_OP_REPLACE";
+ case VK_STENCIL_OP_ZERO:
+ return "VK_STENCIL_OP_ZERO";
+ default:
+ return "Unhandled VkStencilOp";
+ }
+}
+
+static inline const char* string_VkLogicOp(VkLogicOp input_value)
+{
+ switch ((VkLogicOp)input_value)
+ {
+ case VK_LOGIC_OP_AND:
+ return "VK_LOGIC_OP_AND";
+ case VK_LOGIC_OP_AND_INVERTED:
+ return "VK_LOGIC_OP_AND_INVERTED";
+ case VK_LOGIC_OP_AND_REVERSE:
+ return "VK_LOGIC_OP_AND_REVERSE";
+ case VK_LOGIC_OP_CLEAR:
+ return "VK_LOGIC_OP_CLEAR";
+ case VK_LOGIC_OP_COPY:
+ return "VK_LOGIC_OP_COPY";
+ case VK_LOGIC_OP_COPY_INVERTED:
+ return "VK_LOGIC_OP_COPY_INVERTED";
+ case VK_LOGIC_OP_EQUIVALENT:
+ return "VK_LOGIC_OP_EQUIVALENT";
+ case VK_LOGIC_OP_INVERT:
+ return "VK_LOGIC_OP_INVERT";
+ case VK_LOGIC_OP_NAND:
+ return "VK_LOGIC_OP_NAND";
+ case VK_LOGIC_OP_NOR:
+ return "VK_LOGIC_OP_NOR";
+ case VK_LOGIC_OP_NO_OP:
+ return "VK_LOGIC_OP_NO_OP";
+ case VK_LOGIC_OP_OR:
+ return "VK_LOGIC_OP_OR";
+ case VK_LOGIC_OP_OR_INVERTED:
+ return "VK_LOGIC_OP_OR_INVERTED";
+ case VK_LOGIC_OP_OR_REVERSE:
+ return "VK_LOGIC_OP_OR_REVERSE";
+ case VK_LOGIC_OP_SET:
+ return "VK_LOGIC_OP_SET";
+ case VK_LOGIC_OP_XOR:
+ return "VK_LOGIC_OP_XOR";
+ default:
+ return "Unhandled VkLogicOp";
+ }
+}
+
+static inline const char* string_VkBlendFactor(VkBlendFactor input_value)
+{
+ switch ((VkBlendFactor)input_value)
+ {
+ case VK_BLEND_FACTOR_CONSTANT_ALPHA:
+ return "VK_BLEND_FACTOR_CONSTANT_ALPHA";
+ case VK_BLEND_FACTOR_CONSTANT_COLOR:
+ return "VK_BLEND_FACTOR_CONSTANT_COLOR";
+ case VK_BLEND_FACTOR_DST_ALPHA:
+ return "VK_BLEND_FACTOR_DST_ALPHA";
+ case VK_BLEND_FACTOR_DST_COLOR:
+ return "VK_BLEND_FACTOR_DST_COLOR";
+ case VK_BLEND_FACTOR_ONE:
+ return "VK_BLEND_FACTOR_ONE";
+ case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
+ return "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA";
+ case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
+ return "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR";
+ case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
+ return "VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA";
+ case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
+ return "VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR";
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:
+ return "VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA";
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
+ return "VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR";
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
+ return "VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA";
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
+ return "VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR";
+ case VK_BLEND_FACTOR_SRC1_ALPHA:
+ return "VK_BLEND_FACTOR_SRC1_ALPHA";
+ case VK_BLEND_FACTOR_SRC1_COLOR:
+ return "VK_BLEND_FACTOR_SRC1_COLOR";
+ case VK_BLEND_FACTOR_SRC_ALPHA:
+ return "VK_BLEND_FACTOR_SRC_ALPHA";
+ case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE:
+ return "VK_BLEND_FACTOR_SRC_ALPHA_SATURATE";
+ case VK_BLEND_FACTOR_SRC_COLOR:
+ return "VK_BLEND_FACTOR_SRC_COLOR";
+ case VK_BLEND_FACTOR_ZERO:
+ return "VK_BLEND_FACTOR_ZERO";
+ default:
+ return "Unhandled VkBlendFactor";
+ }
+}
+
+static inline const char* string_VkBlendOp(VkBlendOp input_value)
+{
+ switch ((VkBlendOp)input_value)
+ {
+ case VK_BLEND_OP_ADD:
+ return "VK_BLEND_OP_ADD";
+ case VK_BLEND_OP_BLUE_EXT:
+ return "VK_BLEND_OP_BLUE_EXT";
+ case VK_BLEND_OP_COLORBURN_EXT:
+ return "VK_BLEND_OP_COLORBURN_EXT";
+ case VK_BLEND_OP_COLORDODGE_EXT:
+ return "VK_BLEND_OP_COLORDODGE_EXT";
+ case VK_BLEND_OP_CONTRAST_EXT:
+ return "VK_BLEND_OP_CONTRAST_EXT";
+ case VK_BLEND_OP_DARKEN_EXT:
+ return "VK_BLEND_OP_DARKEN_EXT";
+ case VK_BLEND_OP_DIFFERENCE_EXT:
+ return "VK_BLEND_OP_DIFFERENCE_EXT";
+ case VK_BLEND_OP_DST_ATOP_EXT:
+ return "VK_BLEND_OP_DST_ATOP_EXT";
+ case VK_BLEND_OP_DST_EXT:
+ return "VK_BLEND_OP_DST_EXT";
+ case VK_BLEND_OP_DST_IN_EXT:
+ return "VK_BLEND_OP_DST_IN_EXT";
+ case VK_BLEND_OP_DST_OUT_EXT:
+ return "VK_BLEND_OP_DST_OUT_EXT";
+ case VK_BLEND_OP_DST_OVER_EXT:
+ return "VK_BLEND_OP_DST_OVER_EXT";
+ case VK_BLEND_OP_EXCLUSION_EXT:
+ return "VK_BLEND_OP_EXCLUSION_EXT";
+ case VK_BLEND_OP_GREEN_EXT:
+ return "VK_BLEND_OP_GREEN_EXT";
+ case VK_BLEND_OP_HARDLIGHT_EXT:
+ return "VK_BLEND_OP_HARDLIGHT_EXT";
+ case VK_BLEND_OP_HARDMIX_EXT:
+ return "VK_BLEND_OP_HARDMIX_EXT";
+ case VK_BLEND_OP_HSL_COLOR_EXT:
+ return "VK_BLEND_OP_HSL_COLOR_EXT";
+ case VK_BLEND_OP_HSL_HUE_EXT:
+ return "VK_BLEND_OP_HSL_HUE_EXT";
+ case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
+ return "VK_BLEND_OP_HSL_LUMINOSITY_EXT";
+ case VK_BLEND_OP_HSL_SATURATION_EXT:
+ return "VK_BLEND_OP_HSL_SATURATION_EXT";
+ case VK_BLEND_OP_INVERT_EXT:
+ return "VK_BLEND_OP_INVERT_EXT";
+ case VK_BLEND_OP_INVERT_OVG_EXT:
+ return "VK_BLEND_OP_INVERT_OVG_EXT";
+ case VK_BLEND_OP_INVERT_RGB_EXT:
+ return "VK_BLEND_OP_INVERT_RGB_EXT";
+ case VK_BLEND_OP_LIGHTEN_EXT:
+ return "VK_BLEND_OP_LIGHTEN_EXT";
+ case VK_BLEND_OP_LINEARBURN_EXT:
+ return "VK_BLEND_OP_LINEARBURN_EXT";
+ case VK_BLEND_OP_LINEARDODGE_EXT:
+ return "VK_BLEND_OP_LINEARDODGE_EXT";
+ case VK_BLEND_OP_LINEARLIGHT_EXT:
+ return "VK_BLEND_OP_LINEARLIGHT_EXT";
+ case VK_BLEND_OP_MAX:
+ return "VK_BLEND_OP_MAX";
+ case VK_BLEND_OP_MIN:
+ return "VK_BLEND_OP_MIN";
+ case VK_BLEND_OP_MINUS_CLAMPED_EXT:
+ return "VK_BLEND_OP_MINUS_CLAMPED_EXT";
+ case VK_BLEND_OP_MINUS_EXT:
+ return "VK_BLEND_OP_MINUS_EXT";
+ case VK_BLEND_OP_MULTIPLY_EXT:
+ return "VK_BLEND_OP_MULTIPLY_EXT";
+ case VK_BLEND_OP_OVERLAY_EXT:
+ return "VK_BLEND_OP_OVERLAY_EXT";
+ case VK_BLEND_OP_PINLIGHT_EXT:
+ return "VK_BLEND_OP_PINLIGHT_EXT";
+ case VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT:
+ return "VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT";
+ case VK_BLEND_OP_PLUS_CLAMPED_EXT:
+ return "VK_BLEND_OP_PLUS_CLAMPED_EXT";
+ case VK_BLEND_OP_PLUS_DARKER_EXT:
+ return "VK_BLEND_OP_PLUS_DARKER_EXT";
+ case VK_BLEND_OP_PLUS_EXT:
+ return "VK_BLEND_OP_PLUS_EXT";
+ case VK_BLEND_OP_RED_EXT:
+ return "VK_BLEND_OP_RED_EXT";
+ case VK_BLEND_OP_REVERSE_SUBTRACT:
+ return "VK_BLEND_OP_REVERSE_SUBTRACT";
+ case VK_BLEND_OP_SCREEN_EXT:
+ return "VK_BLEND_OP_SCREEN_EXT";
+ case VK_BLEND_OP_SOFTLIGHT_EXT:
+ return "VK_BLEND_OP_SOFTLIGHT_EXT";
+ case VK_BLEND_OP_SRC_ATOP_EXT:
+ return "VK_BLEND_OP_SRC_ATOP_EXT";
+ case VK_BLEND_OP_SRC_EXT:
+ return "VK_BLEND_OP_SRC_EXT";
+ case VK_BLEND_OP_SRC_IN_EXT:
+ return "VK_BLEND_OP_SRC_IN_EXT";
+ case VK_BLEND_OP_SRC_OUT_EXT:
+ return "VK_BLEND_OP_SRC_OUT_EXT";
+ case VK_BLEND_OP_SRC_OVER_EXT:
+ return "VK_BLEND_OP_SRC_OVER_EXT";
+ case VK_BLEND_OP_SUBTRACT:
+ return "VK_BLEND_OP_SUBTRACT";
+ case VK_BLEND_OP_VIVIDLIGHT_EXT:
+ return "VK_BLEND_OP_VIVIDLIGHT_EXT";
+ case VK_BLEND_OP_XOR_EXT:
+ return "VK_BLEND_OP_XOR_EXT";
+ case VK_BLEND_OP_ZERO_EXT:
+ return "VK_BLEND_OP_ZERO_EXT";
+ default:
+ return "Unhandled VkBlendOp";
+ }
+}
+
+static inline const char* string_VkColorComponentFlagBits(VkColorComponentFlagBits input_value)
+{
+ switch ((VkColorComponentFlagBits)input_value)
+ {
+ case VK_COLOR_COMPONENT_A_BIT:
+ return "VK_COLOR_COMPONENT_A_BIT";
+ case VK_COLOR_COMPONENT_B_BIT:
+ return "VK_COLOR_COMPONENT_B_BIT";
+ case VK_COLOR_COMPONENT_G_BIT:
+ return "VK_COLOR_COMPONENT_G_BIT";
+ case VK_COLOR_COMPONENT_R_BIT:
+ return "VK_COLOR_COMPONENT_R_BIT";
+ default:
+ return "Unhandled VkColorComponentFlagBits";
+ }
+}
+
+static inline std::string string_VkColorComponentFlags(VkColorComponentFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkColorComponentFlagBits(static_cast<VkColorComponentFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkColorComponentFlagBits(static_cast<VkColorComponentFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDynamicState(VkDynamicState input_value)
+{
+ switch ((VkDynamicState)input_value)
+ {
+ case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
+ return "VK_DYNAMIC_STATE_BLEND_CONSTANTS";
+ case VK_DYNAMIC_STATE_DEPTH_BIAS:
+ return "VK_DYNAMIC_STATE_DEPTH_BIAS";
+ case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
+ return "VK_DYNAMIC_STATE_DEPTH_BOUNDS";
+ case VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT:
+ return "VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT";
+ case VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV:
+ return "VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV";
+ case VK_DYNAMIC_STATE_LINE_STIPPLE_EXT:
+ return "VK_DYNAMIC_STATE_LINE_STIPPLE_EXT";
+ case VK_DYNAMIC_STATE_LINE_WIDTH:
+ return "VK_DYNAMIC_STATE_LINE_WIDTH";
+ case VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT:
+ return "VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT";
+ case VK_DYNAMIC_STATE_SCISSOR:
+ return "VK_DYNAMIC_STATE_SCISSOR";
+ case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
+ return "VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK";
+ case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
+ return "VK_DYNAMIC_STATE_STENCIL_REFERENCE";
+ case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
+ return "VK_DYNAMIC_STATE_STENCIL_WRITE_MASK";
+ case VK_DYNAMIC_STATE_VIEWPORT:
+ return "VK_DYNAMIC_STATE_VIEWPORT";
+ case VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV:
+ return "VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV";
+ case VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV:
+ return "VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV";
+ case VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV:
+ return "VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV";
+ default:
+ return "Unhandled VkDynamicState";
+ }
+}
+
+static inline const char* string_VkSamplerCreateFlagBits(VkSamplerCreateFlagBits input_value)
+{
+ switch ((VkSamplerCreateFlagBits)input_value)
+ {
+ case VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT:
+ return "VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT";
+ case VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT:
+ return "VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT";
+ default:
+ return "Unhandled VkSamplerCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkSamplerCreateFlags(VkSamplerCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSamplerCreateFlagBits(static_cast<VkSamplerCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSamplerCreateFlagBits(static_cast<VkSamplerCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkFilter(VkFilter input_value)
+{
+ switch ((VkFilter)input_value)
+ {
+ case VK_FILTER_CUBIC_IMG:
+ return "VK_FILTER_CUBIC_IMG";
+ case VK_FILTER_LINEAR:
+ return "VK_FILTER_LINEAR";
+ case VK_FILTER_NEAREST:
+ return "VK_FILTER_NEAREST";
+ default:
+ return "Unhandled VkFilter";
+ }
+}
+
+static inline const char* string_VkSamplerMipmapMode(VkSamplerMipmapMode input_value)
+{
+ switch ((VkSamplerMipmapMode)input_value)
+ {
+ case VK_SAMPLER_MIPMAP_MODE_LINEAR:
+ return "VK_SAMPLER_MIPMAP_MODE_LINEAR";
+ case VK_SAMPLER_MIPMAP_MODE_NEAREST:
+ return "VK_SAMPLER_MIPMAP_MODE_NEAREST";
+ default:
+ return "Unhandled VkSamplerMipmapMode";
+ }
+}
+
+static inline const char* string_VkSamplerAddressMode(VkSamplerAddressMode input_value)
+{
+ switch ((VkSamplerAddressMode)input_value)
+ {
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:
+ return "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER";
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
+ return "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE";
+ case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
+ return "VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT";
+ case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
+ return "VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE";
+ case VK_SAMPLER_ADDRESS_MODE_REPEAT:
+ return "VK_SAMPLER_ADDRESS_MODE_REPEAT";
+ default:
+ return "Unhandled VkSamplerAddressMode";
+ }
+}
+
+static inline const char* string_VkBorderColor(VkBorderColor input_value)
+{
+ switch ((VkBorderColor)input_value)
+ {
+ case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
+ return "VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK";
+ case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
+ return "VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE";
+ case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
+ return "VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK";
+ case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
+ return "VK_BORDER_COLOR_INT_OPAQUE_BLACK";
+ case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
+ return "VK_BORDER_COLOR_INT_OPAQUE_WHITE";
+ case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
+ return "VK_BORDER_COLOR_INT_TRANSPARENT_BLACK";
+ default:
+ return "Unhandled VkBorderColor";
+ }
+}
+
+static inline const char* string_VkDescriptorSetLayoutCreateFlagBits(VkDescriptorSetLayoutCreateFlagBits input_value)
+{
+ switch ((VkDescriptorSetLayoutCreateFlagBits)input_value)
+ {
+ case VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR:
+ return "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR";
+ case VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT:
+ return "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT";
+ default:
+ return "Unhandled VkDescriptorSetLayoutCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkDescriptorSetLayoutCreateFlags(VkDescriptorSetLayoutCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDescriptorSetLayoutCreateFlagBits(static_cast<VkDescriptorSetLayoutCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDescriptorSetLayoutCreateFlagBits(static_cast<VkDescriptorSetLayoutCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDescriptorType(VkDescriptorType input_value)
+{
+ switch ((VkDescriptorType)input_value)
+ {
+ case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
+ return "VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV";
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ return "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER";
+ case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
+ return "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT";
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ return "VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT";
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ return "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE";
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ return "VK_DESCRIPTOR_TYPE_SAMPLER";
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ return "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER";
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ return "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC";
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ return "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE";
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ return "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER";
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ return "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER";
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ return "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC";
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ return "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER";
+ default:
+ return "Unhandled VkDescriptorType";
+ }
+}
+
+static inline const char* string_VkDescriptorPoolCreateFlagBits(VkDescriptorPoolCreateFlagBits input_value)
+{
+ switch ((VkDescriptorPoolCreateFlagBits)input_value)
+ {
+ case VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT:
+ return "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT";
+ case VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT:
+ return "VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT";
+ default:
+ return "Unhandled VkDescriptorPoolCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkDescriptorPoolCreateFlags(VkDescriptorPoolCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDescriptorPoolCreateFlagBits(static_cast<VkDescriptorPoolCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDescriptorPoolCreateFlagBits(static_cast<VkDescriptorPoolCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkFramebufferCreateFlagBits(VkFramebufferCreateFlagBits input_value)
+{
+ switch ((VkFramebufferCreateFlagBits)input_value)
+ {
+ case VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT:
+ return "VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT";
+ default:
+ return "Unhandled VkFramebufferCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkFramebufferCreateFlags(VkFramebufferCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkFramebufferCreateFlagBits(static_cast<VkFramebufferCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkFramebufferCreateFlagBits(static_cast<VkFramebufferCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkAttachmentDescriptionFlagBits(VkAttachmentDescriptionFlagBits input_value)
+{
+ switch ((VkAttachmentDescriptionFlagBits)input_value)
+ {
+ case VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT:
+ return "VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT";
+ default:
+ return "Unhandled VkAttachmentDescriptionFlagBits";
+ }
+}
+
+static inline std::string string_VkAttachmentDescriptionFlags(VkAttachmentDescriptionFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkAttachmentDescriptionFlagBits(static_cast<VkAttachmentDescriptionFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkAttachmentDescriptionFlagBits(static_cast<VkAttachmentDescriptionFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkAttachmentLoadOp(VkAttachmentLoadOp input_value)
+{
+ switch ((VkAttachmentLoadOp)input_value)
+ {
+ case VK_ATTACHMENT_LOAD_OP_CLEAR:
+ return "VK_ATTACHMENT_LOAD_OP_CLEAR";
+ case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
+ return "VK_ATTACHMENT_LOAD_OP_DONT_CARE";
+ case VK_ATTACHMENT_LOAD_OP_LOAD:
+ return "VK_ATTACHMENT_LOAD_OP_LOAD";
+ default:
+ return "Unhandled VkAttachmentLoadOp";
+ }
+}
+
+static inline const char* string_VkAttachmentStoreOp(VkAttachmentStoreOp input_value)
+{
+ switch ((VkAttachmentStoreOp)input_value)
+ {
+ case VK_ATTACHMENT_STORE_OP_DONT_CARE:
+ return "VK_ATTACHMENT_STORE_OP_DONT_CARE";
+ case VK_ATTACHMENT_STORE_OP_STORE:
+ return "VK_ATTACHMENT_STORE_OP_STORE";
+ default:
+ return "Unhandled VkAttachmentStoreOp";
+ }
+}
+
+static inline const char* string_VkSubpassDescriptionFlagBits(VkSubpassDescriptionFlagBits input_value)
+{
+ switch ((VkSubpassDescriptionFlagBits)input_value)
+ {
+ case VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX:
+ return "VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX";
+ case VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX:
+ return "VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX";
+ default:
+ return "Unhandled VkSubpassDescriptionFlagBits";
+ }
+}
+
+static inline std::string string_VkSubpassDescriptionFlags(VkSubpassDescriptionFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSubpassDescriptionFlagBits(static_cast<VkSubpassDescriptionFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSubpassDescriptionFlagBits(static_cast<VkSubpassDescriptionFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPipelineBindPoint(VkPipelineBindPoint input_value)
+{
+ switch ((VkPipelineBindPoint)input_value)
+ {
+ case VK_PIPELINE_BIND_POINT_COMPUTE:
+ return "VK_PIPELINE_BIND_POINT_COMPUTE";
+ case VK_PIPELINE_BIND_POINT_GRAPHICS:
+ return "VK_PIPELINE_BIND_POINT_GRAPHICS";
+ case VK_PIPELINE_BIND_POINT_RAY_TRACING_NV:
+ return "VK_PIPELINE_BIND_POINT_RAY_TRACING_NV";
+ default:
+ return "Unhandled VkPipelineBindPoint";
+ }
+}
+
+static inline const char* string_VkAccessFlagBits(VkAccessFlagBits input_value)
+{
+ switch ((VkAccessFlagBits)input_value)
+ {
+ case VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV:
+ return "VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV";
+ case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV:
+ return "VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV";
+ case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT:
+ return "VK_ACCESS_COLOR_ATTACHMENT_READ_BIT";
+ case VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT:
+ return "VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT";
+ case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT:
+ return "VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT";
+ case VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX:
+ return "VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX";
+ case VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX:
+ return "VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX";
+ case VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT:
+ return "VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT";
+ case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT:
+ return "VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT";
+ case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT:
+ return "VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT";
+ case VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT:
+ return "VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT";
+ case VK_ACCESS_HOST_READ_BIT:
+ return "VK_ACCESS_HOST_READ_BIT";
+ case VK_ACCESS_HOST_WRITE_BIT:
+ return "VK_ACCESS_HOST_WRITE_BIT";
+ case VK_ACCESS_INDEX_READ_BIT:
+ return "VK_ACCESS_INDEX_READ_BIT";
+ case VK_ACCESS_INDIRECT_COMMAND_READ_BIT:
+ return "VK_ACCESS_INDIRECT_COMMAND_READ_BIT";
+ case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT:
+ return "VK_ACCESS_INPUT_ATTACHMENT_READ_BIT";
+ case VK_ACCESS_MEMORY_READ_BIT:
+ return "VK_ACCESS_MEMORY_READ_BIT";
+ case VK_ACCESS_MEMORY_WRITE_BIT:
+ return "VK_ACCESS_MEMORY_WRITE_BIT";
+ case VK_ACCESS_SHADER_READ_BIT:
+ return "VK_ACCESS_SHADER_READ_BIT";
+ case VK_ACCESS_SHADER_WRITE_BIT:
+ return "VK_ACCESS_SHADER_WRITE_BIT";
+ case VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV:
+ return "VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV";
+ case VK_ACCESS_TRANSFER_READ_BIT:
+ return "VK_ACCESS_TRANSFER_READ_BIT";
+ case VK_ACCESS_TRANSFER_WRITE_BIT:
+ return "VK_ACCESS_TRANSFER_WRITE_BIT";
+ case VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT:
+ return "VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT";
+ case VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT:
+ return "VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT";
+ case VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT:
+ return "VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT";
+ case VK_ACCESS_UNIFORM_READ_BIT:
+ return "VK_ACCESS_UNIFORM_READ_BIT";
+ case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT:
+ return "VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT";
+ default:
+ return "Unhandled VkAccessFlagBits";
+ }
+}
+
+static inline std::string string_VkAccessFlags(VkAccessFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkAccessFlagBits(static_cast<VkAccessFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkAccessFlagBits(static_cast<VkAccessFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDependencyFlagBits(VkDependencyFlagBits input_value)
+{
+ switch ((VkDependencyFlagBits)input_value)
+ {
+ case VK_DEPENDENCY_BY_REGION_BIT:
+ return "VK_DEPENDENCY_BY_REGION_BIT";
+ case VK_DEPENDENCY_DEVICE_GROUP_BIT:
+ return "VK_DEPENDENCY_DEVICE_GROUP_BIT";
+ case VK_DEPENDENCY_VIEW_LOCAL_BIT:
+ return "VK_DEPENDENCY_VIEW_LOCAL_BIT";
+ default:
+ return "Unhandled VkDependencyFlagBits";
+ }
+}
+
+static inline std::string string_VkDependencyFlags(VkDependencyFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDependencyFlagBits(static_cast<VkDependencyFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDependencyFlagBits(static_cast<VkDependencyFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkCommandPoolCreateFlagBits(VkCommandPoolCreateFlagBits input_value)
+{
+ switch ((VkCommandPoolCreateFlagBits)input_value)
+ {
+ case VK_COMMAND_POOL_CREATE_PROTECTED_BIT:
+ return "VK_COMMAND_POOL_CREATE_PROTECTED_BIT";
+ case VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT:
+ return "VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT";
+ case VK_COMMAND_POOL_CREATE_TRANSIENT_BIT:
+ return "VK_COMMAND_POOL_CREATE_TRANSIENT_BIT";
+ default:
+ return "Unhandled VkCommandPoolCreateFlagBits";
+ }
+}
+
+static inline std::string string_VkCommandPoolCreateFlags(VkCommandPoolCreateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkCommandPoolCreateFlagBits(static_cast<VkCommandPoolCreateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkCommandPoolCreateFlagBits(static_cast<VkCommandPoolCreateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkCommandPoolResetFlagBits(VkCommandPoolResetFlagBits input_value)
+{
+ switch ((VkCommandPoolResetFlagBits)input_value)
+ {
+ case VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT:
+ return "VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT";
+ default:
+ return "Unhandled VkCommandPoolResetFlagBits";
+ }
+}
+
+static inline std::string string_VkCommandPoolResetFlags(VkCommandPoolResetFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkCommandPoolResetFlagBits(static_cast<VkCommandPoolResetFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkCommandPoolResetFlagBits(static_cast<VkCommandPoolResetFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkCommandBufferLevel(VkCommandBufferLevel input_value)
+{
+ switch ((VkCommandBufferLevel)input_value)
+ {
+ case VK_COMMAND_BUFFER_LEVEL_PRIMARY:
+ return "VK_COMMAND_BUFFER_LEVEL_PRIMARY";
+ case VK_COMMAND_BUFFER_LEVEL_SECONDARY:
+ return "VK_COMMAND_BUFFER_LEVEL_SECONDARY";
+ default:
+ return "Unhandled VkCommandBufferLevel";
+ }
+}
+
+static inline const char* string_VkCommandBufferUsageFlagBits(VkCommandBufferUsageFlagBits input_value)
+{
+ switch ((VkCommandBufferUsageFlagBits)input_value)
+ {
+ case VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT:
+ return "VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT";
+ case VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT:
+ return "VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT";
+ case VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT:
+ return "VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT";
+ default:
+ return "Unhandled VkCommandBufferUsageFlagBits";
+ }
+}
+
+static inline std::string string_VkCommandBufferUsageFlags(VkCommandBufferUsageFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkCommandBufferUsageFlagBits(static_cast<VkCommandBufferUsageFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkCommandBufferUsageFlagBits(static_cast<VkCommandBufferUsageFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkQueryControlFlagBits(VkQueryControlFlagBits input_value)
+{
+ switch ((VkQueryControlFlagBits)input_value)
+ {
+ case VK_QUERY_CONTROL_PRECISE_BIT:
+ return "VK_QUERY_CONTROL_PRECISE_BIT";
+ default:
+ return "Unhandled VkQueryControlFlagBits";
+ }
+}
+
+static inline std::string string_VkQueryControlFlags(VkQueryControlFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkQueryControlFlagBits(static_cast<VkQueryControlFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkQueryControlFlagBits(static_cast<VkQueryControlFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkCommandBufferResetFlagBits(VkCommandBufferResetFlagBits input_value)
+{
+ switch ((VkCommandBufferResetFlagBits)input_value)
+ {
+ case VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT:
+ return "VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT";
+ default:
+ return "Unhandled VkCommandBufferResetFlagBits";
+ }
+}
+
+static inline std::string string_VkCommandBufferResetFlags(VkCommandBufferResetFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkCommandBufferResetFlagBits(static_cast<VkCommandBufferResetFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkCommandBufferResetFlagBits(static_cast<VkCommandBufferResetFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkStencilFaceFlagBits(VkStencilFaceFlagBits input_value)
+{
+ switch ((VkStencilFaceFlagBits)input_value)
+ {
+ case VK_STENCIL_FACE_BACK_BIT:
+ return "VK_STENCIL_FACE_BACK_BIT";
+ case VK_STENCIL_FACE_FRONT_AND_BACK:
+ return "VK_STENCIL_FACE_FRONT_AND_BACK";
+ case VK_STENCIL_FACE_FRONT_BIT:
+ return "VK_STENCIL_FACE_FRONT_BIT";
+ default:
+ return "Unhandled VkStencilFaceFlagBits";
+ }
+}
+
+static inline std::string string_VkStencilFaceFlags(VkStencilFaceFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkStencilFaceFlagBits(static_cast<VkStencilFaceFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkStencilFaceFlagBits(static_cast<VkStencilFaceFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkIndexType(VkIndexType input_value)
+{
+ switch ((VkIndexType)input_value)
+ {
+ case VK_INDEX_TYPE_NONE_NV:
+ return "VK_INDEX_TYPE_NONE_NV";
+ case VK_INDEX_TYPE_UINT16:
+ return "VK_INDEX_TYPE_UINT16";
+ case VK_INDEX_TYPE_UINT32:
+ return "VK_INDEX_TYPE_UINT32";
+ case VK_INDEX_TYPE_UINT8_EXT:
+ return "VK_INDEX_TYPE_UINT8_EXT";
+ default:
+ return "Unhandled VkIndexType";
+ }
+}
+
+static inline const char* string_VkSubpassContents(VkSubpassContents input_value)
+{
+ switch ((VkSubpassContents)input_value)
+ {
+ case VK_SUBPASS_CONTENTS_INLINE:
+ return "VK_SUBPASS_CONTENTS_INLINE";
+ case VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS:
+ return "VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS";
+ default:
+ return "Unhandled VkSubpassContents";
+ }
+}
+
+static inline const char* string_VkObjectType(VkObjectType input_value)
+{
+ switch ((VkObjectType)input_value)
+ {
+ case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV:
+ return "VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV";
+ case VK_OBJECT_TYPE_BUFFER:
+ return "VK_OBJECT_TYPE_BUFFER";
+ case VK_OBJECT_TYPE_BUFFER_VIEW:
+ return "VK_OBJECT_TYPE_BUFFER_VIEW";
+ case VK_OBJECT_TYPE_COMMAND_BUFFER:
+ return "VK_OBJECT_TYPE_COMMAND_BUFFER";
+ case VK_OBJECT_TYPE_COMMAND_POOL:
+ return "VK_OBJECT_TYPE_COMMAND_POOL";
+ case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT:
+ return "VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT";
+ case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT:
+ return "VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT";
+ case VK_OBJECT_TYPE_DESCRIPTOR_POOL:
+ return "VK_OBJECT_TYPE_DESCRIPTOR_POOL";
+ case VK_OBJECT_TYPE_DESCRIPTOR_SET:
+ return "VK_OBJECT_TYPE_DESCRIPTOR_SET";
+ case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT:
+ return "VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT";
+ case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE:
+ return "VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE";
+ case VK_OBJECT_TYPE_DEVICE:
+ return "VK_OBJECT_TYPE_DEVICE";
+ case VK_OBJECT_TYPE_DEVICE_MEMORY:
+ return "VK_OBJECT_TYPE_DEVICE_MEMORY";
+ case VK_OBJECT_TYPE_DISPLAY_KHR:
+ return "VK_OBJECT_TYPE_DISPLAY_KHR";
+ case VK_OBJECT_TYPE_DISPLAY_MODE_KHR:
+ return "VK_OBJECT_TYPE_DISPLAY_MODE_KHR";
+ case VK_OBJECT_TYPE_EVENT:
+ return "VK_OBJECT_TYPE_EVENT";
+ case VK_OBJECT_TYPE_FENCE:
+ return "VK_OBJECT_TYPE_FENCE";
+ case VK_OBJECT_TYPE_FRAMEBUFFER:
+ return "VK_OBJECT_TYPE_FRAMEBUFFER";
+ case VK_OBJECT_TYPE_IMAGE:
+ return "VK_OBJECT_TYPE_IMAGE";
+ case VK_OBJECT_TYPE_IMAGE_VIEW:
+ return "VK_OBJECT_TYPE_IMAGE_VIEW";
+ case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX:
+ return "VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX";
+ case VK_OBJECT_TYPE_INSTANCE:
+ return "VK_OBJECT_TYPE_INSTANCE";
+ case VK_OBJECT_TYPE_OBJECT_TABLE_NVX:
+ return "VK_OBJECT_TYPE_OBJECT_TABLE_NVX";
+ case VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL:
+ return "VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL";
+ case VK_OBJECT_TYPE_PHYSICAL_DEVICE:
+ return "VK_OBJECT_TYPE_PHYSICAL_DEVICE";
+ case VK_OBJECT_TYPE_PIPELINE:
+ return "VK_OBJECT_TYPE_PIPELINE";
+ case VK_OBJECT_TYPE_PIPELINE_CACHE:
+ return "VK_OBJECT_TYPE_PIPELINE_CACHE";
+ case VK_OBJECT_TYPE_PIPELINE_LAYOUT:
+ return "VK_OBJECT_TYPE_PIPELINE_LAYOUT";
+ case VK_OBJECT_TYPE_QUERY_POOL:
+ return "VK_OBJECT_TYPE_QUERY_POOL";
+ case VK_OBJECT_TYPE_QUEUE:
+ return "VK_OBJECT_TYPE_QUEUE";
+ case VK_OBJECT_TYPE_RENDER_PASS:
+ return "VK_OBJECT_TYPE_RENDER_PASS";
+ case VK_OBJECT_TYPE_SAMPLER:
+ return "VK_OBJECT_TYPE_SAMPLER";
+ case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION:
+ return "VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION";
+ case VK_OBJECT_TYPE_SEMAPHORE:
+ return "VK_OBJECT_TYPE_SEMAPHORE";
+ case VK_OBJECT_TYPE_SHADER_MODULE:
+ return "VK_OBJECT_TYPE_SHADER_MODULE";
+ case VK_OBJECT_TYPE_SURFACE_KHR:
+ return "VK_OBJECT_TYPE_SURFACE_KHR";
+ case VK_OBJECT_TYPE_SWAPCHAIN_KHR:
+ return "VK_OBJECT_TYPE_SWAPCHAIN_KHR";
+ case VK_OBJECT_TYPE_UNKNOWN:
+ return "VK_OBJECT_TYPE_UNKNOWN";
+ case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT:
+ return "VK_OBJECT_TYPE_VALIDATION_CACHE_EXT";
+ default:
+ return "Unhandled VkObjectType";
+ }
+}
+
+static inline const char* string_VkVendorId(VkVendorId input_value)
+{
+ switch ((VkVendorId)input_value)
+ {
+ case VK_VENDOR_ID_KAZAN:
+ return "VK_VENDOR_ID_KAZAN";
+ case VK_VENDOR_ID_VIV:
+ return "VK_VENDOR_ID_VIV";
+ case VK_VENDOR_ID_VSI:
+ return "VK_VENDOR_ID_VSI";
+ default:
+ return "Unhandled VkVendorId";
+ }
+}
+
+static inline const char* string_VkSubgroupFeatureFlagBits(VkSubgroupFeatureFlagBits input_value)
+{
+ switch ((VkSubgroupFeatureFlagBits)input_value)
+ {
+ case VK_SUBGROUP_FEATURE_ARITHMETIC_BIT:
+ return "VK_SUBGROUP_FEATURE_ARITHMETIC_BIT";
+ case VK_SUBGROUP_FEATURE_BALLOT_BIT:
+ return "VK_SUBGROUP_FEATURE_BALLOT_BIT";
+ case VK_SUBGROUP_FEATURE_BASIC_BIT:
+ return "VK_SUBGROUP_FEATURE_BASIC_BIT";
+ case VK_SUBGROUP_FEATURE_CLUSTERED_BIT:
+ return "VK_SUBGROUP_FEATURE_CLUSTERED_BIT";
+ case VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV:
+ return "VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV";
+ case VK_SUBGROUP_FEATURE_QUAD_BIT:
+ return "VK_SUBGROUP_FEATURE_QUAD_BIT";
+ case VK_SUBGROUP_FEATURE_SHUFFLE_BIT:
+ return "VK_SUBGROUP_FEATURE_SHUFFLE_BIT";
+ case VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT:
+ return "VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT";
+ case VK_SUBGROUP_FEATURE_VOTE_BIT:
+ return "VK_SUBGROUP_FEATURE_VOTE_BIT";
+ default:
+ return "Unhandled VkSubgroupFeatureFlagBits";
+ }
+}
+
+static inline std::string string_VkSubgroupFeatureFlags(VkSubgroupFeatureFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSubgroupFeatureFlagBits(static_cast<VkSubgroupFeatureFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSubgroupFeatureFlagBits(static_cast<VkSubgroupFeatureFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPeerMemoryFeatureFlagBits(VkPeerMemoryFeatureFlagBits input_value)
+{
+ switch ((VkPeerMemoryFeatureFlagBits)input_value)
+ {
+ case VK_PEER_MEMORY_FEATURE_COPY_DST_BIT:
+ return "VK_PEER_MEMORY_FEATURE_COPY_DST_BIT";
+ case VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT:
+ return "VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT";
+ case VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT:
+ return "VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT";
+ case VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT:
+ return "VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT";
+ default:
+ return "Unhandled VkPeerMemoryFeatureFlagBits";
+ }
+}
+
+static inline std::string string_VkPeerMemoryFeatureFlags(VkPeerMemoryFeatureFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkPeerMemoryFeatureFlagBits(static_cast<VkPeerMemoryFeatureFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkPeerMemoryFeatureFlagBits(static_cast<VkPeerMemoryFeatureFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkMemoryAllocateFlagBits(VkMemoryAllocateFlagBits input_value)
+{
+ switch ((VkMemoryAllocateFlagBits)input_value)
+ {
+ case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT:
+ return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT";
+ case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT:
+ return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT";
+ case VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT:
+ return "VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT";
+ default:
+ return "Unhandled VkMemoryAllocateFlagBits";
+ }
+}
+
+static inline std::string string_VkMemoryAllocateFlags(VkMemoryAllocateFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkMemoryAllocateFlagBits(static_cast<VkMemoryAllocateFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkMemoryAllocateFlagBits(static_cast<VkMemoryAllocateFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPointClippingBehavior(VkPointClippingBehavior input_value)
+{
+ switch ((VkPointClippingBehavior)input_value)
+ {
+ case VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES:
+ return "VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES";
+ case VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY:
+ return "VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY";
+ default:
+ return "Unhandled VkPointClippingBehavior";
+ }
+}
+
+static inline const char* string_VkTessellationDomainOrigin(VkTessellationDomainOrigin input_value)
+{
+ switch ((VkTessellationDomainOrigin)input_value)
+ {
+ case VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT:
+ return "VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT";
+ case VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT:
+ return "VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT";
+ default:
+ return "Unhandled VkTessellationDomainOrigin";
+ }
+}
+
+static inline const char* string_VkSamplerYcbcrModelConversion(VkSamplerYcbcrModelConversion input_value)
+{
+ switch ((VkSamplerYcbcrModelConversion)input_value)
+ {
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY:
+ return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020:
+ return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601:
+ return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709:
+ return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY:
+ return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY";
+ default:
+ return "Unhandled VkSamplerYcbcrModelConversion";
+ }
+}
+
+static inline const char* string_VkSamplerYcbcrRange(VkSamplerYcbcrRange input_value)
+{
+ switch ((VkSamplerYcbcrRange)input_value)
+ {
+ case VK_SAMPLER_YCBCR_RANGE_ITU_FULL:
+ return "VK_SAMPLER_YCBCR_RANGE_ITU_FULL";
+ case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW:
+ return "VK_SAMPLER_YCBCR_RANGE_ITU_NARROW";
+ default:
+ return "Unhandled VkSamplerYcbcrRange";
+ }
+}
+
+static inline const char* string_VkChromaLocation(VkChromaLocation input_value)
+{
+ switch ((VkChromaLocation)input_value)
+ {
+ case VK_CHROMA_LOCATION_COSITED_EVEN:
+ return "VK_CHROMA_LOCATION_COSITED_EVEN";
+ case VK_CHROMA_LOCATION_MIDPOINT:
+ return "VK_CHROMA_LOCATION_MIDPOINT";
+ default:
+ return "Unhandled VkChromaLocation";
+ }
+}
+
+static inline const char* string_VkDescriptorUpdateTemplateType(VkDescriptorUpdateTemplateType input_value)
+{
+ switch ((VkDescriptorUpdateTemplateType)input_value)
+ {
+ case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET:
+ return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET";
+ case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR:
+ return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR";
+ default:
+ return "Unhandled VkDescriptorUpdateTemplateType";
+ }
+}
+
+static inline const char* string_VkExternalMemoryHandleTypeFlagBits(VkExternalMemoryHandleTypeFlagBits input_value)
+{
+ switch ((VkExternalMemoryHandleTypeFlagBits)input_value)
+ {
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT";
+ default:
+ return "Unhandled VkExternalMemoryHandleTypeFlagBits";
+ }
+}
+
+static inline std::string string_VkExternalMemoryHandleTypeFlags(VkExternalMemoryHandleTypeFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalMemoryHandleTypeFlagBits(static_cast<VkExternalMemoryHandleTypeFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalMemoryHandleTypeFlagBits(static_cast<VkExternalMemoryHandleTypeFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalMemoryFeatureFlagBits(VkExternalMemoryFeatureFlagBits input_value)
+{
+ switch ((VkExternalMemoryFeatureFlagBits)input_value)
+ {
+ case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT:
+ return "VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT";
+ case VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT:
+ return "VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT";
+ case VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT:
+ return "VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT";
+ default:
+ return "Unhandled VkExternalMemoryFeatureFlagBits";
+ }
+}
+
+static inline std::string string_VkExternalMemoryFeatureFlags(VkExternalMemoryFeatureFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalMemoryFeatureFlagBits(static_cast<VkExternalMemoryFeatureFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalMemoryFeatureFlagBits(static_cast<VkExternalMemoryFeatureFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalFenceHandleTypeFlagBits(VkExternalFenceHandleTypeFlagBits input_value)
+{
+ switch ((VkExternalFenceHandleTypeFlagBits)input_value)
+ {
+ case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
+ return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT";
+ case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
+ return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT";
+ case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
+ return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT";
+ case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
+ return "VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT";
+ default:
+ return "Unhandled VkExternalFenceHandleTypeFlagBits";
+ }
+}
+
+static inline std::string string_VkExternalFenceHandleTypeFlags(VkExternalFenceHandleTypeFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalFenceHandleTypeFlagBits(static_cast<VkExternalFenceHandleTypeFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalFenceHandleTypeFlagBits(static_cast<VkExternalFenceHandleTypeFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalFenceFeatureFlagBits(VkExternalFenceFeatureFlagBits input_value)
+{
+ switch ((VkExternalFenceFeatureFlagBits)input_value)
+ {
+ case VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT:
+ return "VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT";
+ case VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT:
+ return "VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT";
+ default:
+ return "Unhandled VkExternalFenceFeatureFlagBits";
+ }
+}
+
+static inline std::string string_VkExternalFenceFeatureFlags(VkExternalFenceFeatureFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalFenceFeatureFlagBits(static_cast<VkExternalFenceFeatureFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalFenceFeatureFlagBits(static_cast<VkExternalFenceFeatureFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkFenceImportFlagBits(VkFenceImportFlagBits input_value)
+{
+ switch ((VkFenceImportFlagBits)input_value)
+ {
+ case VK_FENCE_IMPORT_TEMPORARY_BIT:
+ return "VK_FENCE_IMPORT_TEMPORARY_BIT";
+ default:
+ return "Unhandled VkFenceImportFlagBits";
+ }
+}
+
+static inline std::string string_VkFenceImportFlags(VkFenceImportFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkFenceImportFlagBits(static_cast<VkFenceImportFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkFenceImportFlagBits(static_cast<VkFenceImportFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkSemaphoreImportFlagBits(VkSemaphoreImportFlagBits input_value)
+{
+ switch ((VkSemaphoreImportFlagBits)input_value)
+ {
+ case VK_SEMAPHORE_IMPORT_TEMPORARY_BIT:
+ return "VK_SEMAPHORE_IMPORT_TEMPORARY_BIT";
+ default:
+ return "Unhandled VkSemaphoreImportFlagBits";
+ }
+}
+
+static inline std::string string_VkSemaphoreImportFlags(VkSemaphoreImportFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSemaphoreImportFlagBits(static_cast<VkSemaphoreImportFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSemaphoreImportFlagBits(static_cast<VkSemaphoreImportFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalSemaphoreHandleTypeFlagBits(VkExternalSemaphoreHandleTypeFlagBits input_value)
+{
+ switch ((VkExternalSemaphoreHandleTypeFlagBits)input_value)
+ {
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT";
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT";
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT";
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT";
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT";
+ default:
+ return "Unhandled VkExternalSemaphoreHandleTypeFlagBits";
+ }
+}
+
+static inline std::string string_VkExternalSemaphoreHandleTypeFlags(VkExternalSemaphoreHandleTypeFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalSemaphoreHandleTypeFlagBits(static_cast<VkExternalSemaphoreHandleTypeFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalSemaphoreHandleTypeFlagBits(static_cast<VkExternalSemaphoreHandleTypeFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalSemaphoreFeatureFlagBits(VkExternalSemaphoreFeatureFlagBits input_value)
+{
+ switch ((VkExternalSemaphoreFeatureFlagBits)input_value)
+ {
+ case VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT";
+ case VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT";
+ default:
+ return "Unhandled VkExternalSemaphoreFeatureFlagBits";
+ }
+}
+
+static inline std::string string_VkExternalSemaphoreFeatureFlags(VkExternalSemaphoreFeatureFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalSemaphoreFeatureFlagBits(static_cast<VkExternalSemaphoreFeatureFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalSemaphoreFeatureFlagBits(static_cast<VkExternalSemaphoreFeatureFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDriverId(VkDriverId input_value)
+{
+ switch ((VkDriverId)input_value)
+ {
+ case VK_DRIVER_ID_AMD_OPEN_SOURCE:
+ return "VK_DRIVER_ID_AMD_OPEN_SOURCE";
+ case VK_DRIVER_ID_AMD_PROPRIETARY:
+ return "VK_DRIVER_ID_AMD_PROPRIETARY";
+ case VK_DRIVER_ID_ARM_PROPRIETARY:
+ return "VK_DRIVER_ID_ARM_PROPRIETARY";
+ case VK_DRIVER_ID_BROADCOM_PROPRIETARY:
+ return "VK_DRIVER_ID_BROADCOM_PROPRIETARY";
+ case VK_DRIVER_ID_GGP_PROPRIETARY:
+ return "VK_DRIVER_ID_GGP_PROPRIETARY";
+ case VK_DRIVER_ID_GOOGLE_SWIFTSHADER:
+ return "VK_DRIVER_ID_GOOGLE_SWIFTSHADER";
+ case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
+ return "VK_DRIVER_ID_IMAGINATION_PROPRIETARY";
+ case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA:
+ return "VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA";
+ case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS:
+ return "VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS";
+ case VK_DRIVER_ID_MESA_RADV:
+ return "VK_DRIVER_ID_MESA_RADV";
+ case VK_DRIVER_ID_NVIDIA_PROPRIETARY:
+ return "VK_DRIVER_ID_NVIDIA_PROPRIETARY";
+ case VK_DRIVER_ID_QUALCOMM_PROPRIETARY:
+ return "VK_DRIVER_ID_QUALCOMM_PROPRIETARY";
+ default:
+ return "Unhandled VkDriverId";
+ }
+}
+
+static inline const char* string_VkShaderFloatControlsIndependence(VkShaderFloatControlsIndependence input_value)
+{
+ switch ((VkShaderFloatControlsIndependence)input_value)
+ {
+ case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY:
+ return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY";
+ case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL:
+ return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL";
+ case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE:
+ return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE";
+ default:
+ return "Unhandled VkShaderFloatControlsIndependence";
+ }
+}
+
+static inline const char* string_VkResolveModeFlagBits(VkResolveModeFlagBits input_value)
+{
+ switch ((VkResolveModeFlagBits)input_value)
+ {
+ case VK_RESOLVE_MODE_AVERAGE_BIT:
+ return "VK_RESOLVE_MODE_AVERAGE_BIT";
+ case VK_RESOLVE_MODE_MAX_BIT:
+ return "VK_RESOLVE_MODE_MAX_BIT";
+ case VK_RESOLVE_MODE_MIN_BIT:
+ return "VK_RESOLVE_MODE_MIN_BIT";
+ case VK_RESOLVE_MODE_NONE:
+ return "VK_RESOLVE_MODE_NONE";
+ case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT:
+ return "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT";
+ default:
+ return "Unhandled VkResolveModeFlagBits";
+ }
+}
+
+static inline std::string string_VkResolveModeFlags(VkResolveModeFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkResolveModeFlagBits(static_cast<VkResolveModeFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkResolveModeFlagBits(static_cast<VkResolveModeFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDescriptorBindingFlagBits(VkDescriptorBindingFlagBits input_value)
+{
+ switch ((VkDescriptorBindingFlagBits)input_value)
+ {
+ case VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT:
+ return "VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT";
+ case VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT:
+ return "VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT";
+ case VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT:
+ return "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT";
+ case VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT:
+ return "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT";
+ default:
+ return "Unhandled VkDescriptorBindingFlagBits";
+ }
+}
+
+static inline std::string string_VkDescriptorBindingFlags(VkDescriptorBindingFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDescriptorBindingFlagBits(static_cast<VkDescriptorBindingFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDescriptorBindingFlagBits(static_cast<VkDescriptorBindingFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkSamplerReductionMode(VkSamplerReductionMode input_value)
+{
+ switch ((VkSamplerReductionMode)input_value)
+ {
+ case VK_SAMPLER_REDUCTION_MODE_MAX:
+ return "VK_SAMPLER_REDUCTION_MODE_MAX";
+ case VK_SAMPLER_REDUCTION_MODE_MIN:
+ return "VK_SAMPLER_REDUCTION_MODE_MIN";
+ case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE:
+ return "VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE";
+ default:
+ return "Unhandled VkSamplerReductionMode";
+ }
+}
+
+static inline const char* string_VkSemaphoreType(VkSemaphoreType input_value)
+{
+ switch ((VkSemaphoreType)input_value)
+ {
+ case VK_SEMAPHORE_TYPE_BINARY:
+ return "VK_SEMAPHORE_TYPE_BINARY";
+ case VK_SEMAPHORE_TYPE_TIMELINE:
+ return "VK_SEMAPHORE_TYPE_TIMELINE";
+ default:
+ return "Unhandled VkSemaphoreType";
+ }
+}
+
+static inline const char* string_VkSemaphoreWaitFlagBits(VkSemaphoreWaitFlagBits input_value)
+{
+ switch ((VkSemaphoreWaitFlagBits)input_value)
+ {
+ case VK_SEMAPHORE_WAIT_ANY_BIT:
+ return "VK_SEMAPHORE_WAIT_ANY_BIT";
+ default:
+ return "Unhandled VkSemaphoreWaitFlagBits";
+ }
+}
+
+static inline std::string string_VkSemaphoreWaitFlags(VkSemaphoreWaitFlags input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSemaphoreWaitFlagBits(static_cast<VkSemaphoreWaitFlagBits>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSemaphoreWaitFlagBits(static_cast<VkSemaphoreWaitFlagBits>(0)));
+ return ret;
+}
+
+static inline const char* string_VkSurfaceTransformFlagBitsKHR(VkSurfaceTransformFlagBitsKHR input_value)
+{
+ switch ((VkSurfaceTransformFlagBitsKHR)input_value)
+ {
+ case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
+ return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR";
+ case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
+ return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR";
+ case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
+ return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR";
+ case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
+ return "VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR";
+ case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+ return "VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR";
+ case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
+ return "VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR";
+ case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+ return "VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR";
+ case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+ return "VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR";
+ case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+ return "VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR";
+ default:
+ return "Unhandled VkSurfaceTransformFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkSurfaceTransformFlagsKHR(VkSurfaceTransformFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSurfaceTransformFlagBitsKHR(static_cast<VkSurfaceTransformFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSurfaceTransformFlagBitsKHR(static_cast<VkSurfaceTransformFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkCompositeAlphaFlagBitsKHR(VkCompositeAlphaFlagBitsKHR input_value)
+{
+ switch ((VkCompositeAlphaFlagBitsKHR)input_value)
+ {
+ case VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR:
+ return "VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR";
+ case VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR:
+ return "VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR";
+ case VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR:
+ return "VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR";
+ case VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR:
+ return "VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR";
+ default:
+ return "Unhandled VkCompositeAlphaFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkCompositeAlphaFlagsKHR(VkCompositeAlphaFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkCompositeAlphaFlagBitsKHR(static_cast<VkCompositeAlphaFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkCompositeAlphaFlagBitsKHR(static_cast<VkCompositeAlphaFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkColorSpaceKHR(VkColorSpaceKHR input_value)
+{
+ switch ((VkColorSpaceKHR)input_value)
+ {
+ case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT:
+ return "VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT";
+ case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT:
+ return "VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT";
+ case VK_COLOR_SPACE_BT2020_LINEAR_EXT:
+ return "VK_COLOR_SPACE_BT2020_LINEAR_EXT";
+ case VK_COLOR_SPACE_BT709_LINEAR_EXT:
+ return "VK_COLOR_SPACE_BT709_LINEAR_EXT";
+ case VK_COLOR_SPACE_BT709_NONLINEAR_EXT:
+ return "VK_COLOR_SPACE_BT709_NONLINEAR_EXT";
+ case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT:
+ return "VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT";
+ case VK_COLOR_SPACE_DISPLAY_NATIVE_AMD:
+ return "VK_COLOR_SPACE_DISPLAY_NATIVE_AMD";
+ case VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT:
+ return "VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT";
+ case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT:
+ return "VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT";
+ case VK_COLOR_SPACE_DOLBYVISION_EXT:
+ return "VK_COLOR_SPACE_DOLBYVISION_EXT";
+ case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
+ return "VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT";
+ case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT:
+ return "VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT";
+ case VK_COLOR_SPACE_HDR10_HLG_EXT:
+ return "VK_COLOR_SPACE_HDR10_HLG_EXT";
+ case VK_COLOR_SPACE_HDR10_ST2084_EXT:
+ return "VK_COLOR_SPACE_HDR10_ST2084_EXT";
+ case VK_COLOR_SPACE_PASS_THROUGH_EXT:
+ return "VK_COLOR_SPACE_PASS_THROUGH_EXT";
+ case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR:
+ return "VK_COLOR_SPACE_SRGB_NONLINEAR_KHR";
+ default:
+ return "Unhandled VkColorSpaceKHR";
+ }
+}
+
+static inline const char* string_VkPresentModeKHR(VkPresentModeKHR input_value)
+{
+ switch ((VkPresentModeKHR)input_value)
+ {
+ case VK_PRESENT_MODE_FIFO_KHR:
+ return "VK_PRESENT_MODE_FIFO_KHR";
+ case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
+ return "VK_PRESENT_MODE_FIFO_RELAXED_KHR";
+ case VK_PRESENT_MODE_IMMEDIATE_KHR:
+ return "VK_PRESENT_MODE_IMMEDIATE_KHR";
+ case VK_PRESENT_MODE_MAILBOX_KHR:
+ return "VK_PRESENT_MODE_MAILBOX_KHR";
+ case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR:
+ return "VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR";
+ case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR:
+ return "VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR";
+ default:
+ return "Unhandled VkPresentModeKHR";
+ }
+}
+
+static inline const char* string_VkSwapchainCreateFlagBitsKHR(VkSwapchainCreateFlagBitsKHR input_value)
+{
+ switch ((VkSwapchainCreateFlagBitsKHR)input_value)
+ {
+ case VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR:
+ return "VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR";
+ case VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR:
+ return "VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR";
+ case VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR:
+ return "VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR";
+ default:
+ return "Unhandled VkSwapchainCreateFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkSwapchainCreateFlagsKHR(VkSwapchainCreateFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSwapchainCreateFlagBitsKHR(static_cast<VkSwapchainCreateFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSwapchainCreateFlagBitsKHR(static_cast<VkSwapchainCreateFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDeviceGroupPresentModeFlagBitsKHR(VkDeviceGroupPresentModeFlagBitsKHR input_value)
+{
+ switch ((VkDeviceGroupPresentModeFlagBitsKHR)input_value)
+ {
+ case VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR:
+ return "VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR";
+ case VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR:
+ return "VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR";
+ case VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR:
+ return "VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR";
+ case VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR:
+ return "VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR";
+ default:
+ return "Unhandled VkDeviceGroupPresentModeFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkDeviceGroupPresentModeFlagsKHR(VkDeviceGroupPresentModeFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDeviceGroupPresentModeFlagBitsKHR(static_cast<VkDeviceGroupPresentModeFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDeviceGroupPresentModeFlagBitsKHR(static_cast<VkDeviceGroupPresentModeFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDisplayPlaneAlphaFlagBitsKHR(VkDisplayPlaneAlphaFlagBitsKHR input_value)
+{
+ switch ((VkDisplayPlaneAlphaFlagBitsKHR)input_value)
+ {
+ case VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR:
+ return "VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR";
+ case VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR:
+ return "VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR";
+ case VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR:
+ return "VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR";
+ case VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR:
+ return "VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR";
+ default:
+ return "Unhandled VkDisplayPlaneAlphaFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkDisplayPlaneAlphaFlagsKHR(VkDisplayPlaneAlphaFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDisplayPlaneAlphaFlagBitsKHR(static_cast<VkDisplayPlaneAlphaFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDisplayPlaneAlphaFlagBitsKHR(static_cast<VkDisplayPlaneAlphaFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPeerMemoryFeatureFlagBitsKHR(VkPeerMemoryFeatureFlagBitsKHR input_value)
+{
+ switch ((VkPeerMemoryFeatureFlagBitsKHR)input_value)
+ {
+ case VK_PEER_MEMORY_FEATURE_COPY_DST_BIT:
+ return "VK_PEER_MEMORY_FEATURE_COPY_DST_BIT";
+ case VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT:
+ return "VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT";
+ case VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT:
+ return "VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT";
+ case VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT:
+ return "VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT";
+ default:
+ return "Unhandled VkPeerMemoryFeatureFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkPeerMemoryFeatureFlagsKHR(VkPeerMemoryFeatureFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkPeerMemoryFeatureFlagBitsKHR(static_cast<VkPeerMemoryFeatureFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkPeerMemoryFeatureFlagBitsKHR(static_cast<VkPeerMemoryFeatureFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkMemoryAllocateFlagBitsKHR(VkMemoryAllocateFlagBitsKHR input_value)
+{
+ switch ((VkMemoryAllocateFlagBitsKHR)input_value)
+ {
+ case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT:
+ return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT";
+ case VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT:
+ return "VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT";
+ case VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT:
+ return "VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT";
+ default:
+ return "Unhandled VkMemoryAllocateFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkMemoryAllocateFlagsKHR(VkMemoryAllocateFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkMemoryAllocateFlagBitsKHR(static_cast<VkMemoryAllocateFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkMemoryAllocateFlagBitsKHR(static_cast<VkMemoryAllocateFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalMemoryHandleTypeFlagBitsKHR(VkExternalMemoryHandleTypeFlagBitsKHR input_value)
+{
+ switch ((VkExternalMemoryHandleTypeFlagBitsKHR)input_value)
+ {
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT";
+ default:
+ return "Unhandled VkExternalMemoryHandleTypeFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkExternalMemoryHandleTypeFlagsKHR(VkExternalMemoryHandleTypeFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalMemoryHandleTypeFlagBitsKHR(static_cast<VkExternalMemoryHandleTypeFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalMemoryHandleTypeFlagBitsKHR(static_cast<VkExternalMemoryHandleTypeFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalMemoryFeatureFlagBitsKHR(VkExternalMemoryFeatureFlagBitsKHR input_value)
+{
+ switch ((VkExternalMemoryFeatureFlagBitsKHR)input_value)
+ {
+ case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT:
+ return "VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT";
+ case VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT:
+ return "VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT";
+ case VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT:
+ return "VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT";
+ default:
+ return "Unhandled VkExternalMemoryFeatureFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkExternalMemoryFeatureFlagsKHR(VkExternalMemoryFeatureFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalMemoryFeatureFlagBitsKHR(static_cast<VkExternalMemoryFeatureFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalMemoryFeatureFlagBitsKHR(static_cast<VkExternalMemoryFeatureFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalSemaphoreHandleTypeFlagBitsKHR(VkExternalSemaphoreHandleTypeFlagBitsKHR input_value)
+{
+ switch ((VkExternalSemaphoreHandleTypeFlagBitsKHR)input_value)
+ {
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT";
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT";
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT";
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT";
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT";
+ default:
+ return "Unhandled VkExternalSemaphoreHandleTypeFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkExternalSemaphoreHandleTypeFlagsKHR(VkExternalSemaphoreHandleTypeFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalSemaphoreHandleTypeFlagBitsKHR(static_cast<VkExternalSemaphoreHandleTypeFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalSemaphoreHandleTypeFlagBitsKHR(static_cast<VkExternalSemaphoreHandleTypeFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalSemaphoreFeatureFlagBitsKHR(VkExternalSemaphoreFeatureFlagBitsKHR input_value)
+{
+ switch ((VkExternalSemaphoreFeatureFlagBitsKHR)input_value)
+ {
+ case VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT";
+ case VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT:
+ return "VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT";
+ default:
+ return "Unhandled VkExternalSemaphoreFeatureFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkExternalSemaphoreFeatureFlagsKHR(VkExternalSemaphoreFeatureFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalSemaphoreFeatureFlagBitsKHR(static_cast<VkExternalSemaphoreFeatureFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalSemaphoreFeatureFlagBitsKHR(static_cast<VkExternalSemaphoreFeatureFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkSemaphoreImportFlagBitsKHR(VkSemaphoreImportFlagBitsKHR input_value)
+{
+ switch ((VkSemaphoreImportFlagBitsKHR)input_value)
+ {
+ case VK_SEMAPHORE_IMPORT_TEMPORARY_BIT:
+ return "VK_SEMAPHORE_IMPORT_TEMPORARY_BIT";
+ default:
+ return "Unhandled VkSemaphoreImportFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkSemaphoreImportFlagsKHR(VkSemaphoreImportFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSemaphoreImportFlagBitsKHR(static_cast<VkSemaphoreImportFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSemaphoreImportFlagBitsKHR(static_cast<VkSemaphoreImportFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDescriptorUpdateTemplateTypeKHR(VkDescriptorUpdateTemplateTypeKHR input_value)
+{
+ switch ((VkDescriptorUpdateTemplateTypeKHR)input_value)
+ {
+ case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET:
+ return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET";
+ case VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR:
+ return "VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR";
+ default:
+ return "Unhandled VkDescriptorUpdateTemplateTypeKHR";
+ }
+}
+
+static inline const char* string_VkExternalFenceHandleTypeFlagBitsKHR(VkExternalFenceHandleTypeFlagBitsKHR input_value)
+{
+ switch ((VkExternalFenceHandleTypeFlagBitsKHR)input_value)
+ {
+ case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
+ return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT";
+ case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
+ return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT";
+ case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
+ return "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT";
+ case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
+ return "VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT";
+ default:
+ return "Unhandled VkExternalFenceHandleTypeFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkExternalFenceHandleTypeFlagsKHR(VkExternalFenceHandleTypeFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalFenceHandleTypeFlagBitsKHR(static_cast<VkExternalFenceHandleTypeFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalFenceHandleTypeFlagBitsKHR(static_cast<VkExternalFenceHandleTypeFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalFenceFeatureFlagBitsKHR(VkExternalFenceFeatureFlagBitsKHR input_value)
+{
+ switch ((VkExternalFenceFeatureFlagBitsKHR)input_value)
+ {
+ case VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT:
+ return "VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT";
+ case VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT:
+ return "VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT";
+ default:
+ return "Unhandled VkExternalFenceFeatureFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkExternalFenceFeatureFlagsKHR(VkExternalFenceFeatureFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalFenceFeatureFlagBitsKHR(static_cast<VkExternalFenceFeatureFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalFenceFeatureFlagBitsKHR(static_cast<VkExternalFenceFeatureFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkFenceImportFlagBitsKHR(VkFenceImportFlagBitsKHR input_value)
+{
+ switch ((VkFenceImportFlagBitsKHR)input_value)
+ {
+ case VK_FENCE_IMPORT_TEMPORARY_BIT:
+ return "VK_FENCE_IMPORT_TEMPORARY_BIT";
+ default:
+ return "Unhandled VkFenceImportFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkFenceImportFlagsKHR(VkFenceImportFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkFenceImportFlagBitsKHR(static_cast<VkFenceImportFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkFenceImportFlagBitsKHR(static_cast<VkFenceImportFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPerformanceCounterUnitKHR(VkPerformanceCounterUnitKHR input_value)
+{
+ switch ((VkPerformanceCounterUnitKHR)input_value)
+ {
+ case VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR";
+ case VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR";
+ case VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR";
+ case VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR";
+ case VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR";
+ case VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR";
+ case VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR";
+ case VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR";
+ case VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR";
+ case VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR";
+ case VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR:
+ return "VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR";
+ default:
+ return "Unhandled VkPerformanceCounterUnitKHR";
+ }
+}
+
+static inline const char* string_VkPerformanceCounterScopeKHR(VkPerformanceCounterScopeKHR input_value)
+{
+ switch ((VkPerformanceCounterScopeKHR)input_value)
+ {
+ case VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR:
+ return "VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR";
+ case VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR:
+ return "VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR";
+ case VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR:
+ return "VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR";
+ default:
+ return "Unhandled VkPerformanceCounterScopeKHR";
+ }
+}
+
+static inline const char* string_VkPerformanceCounterStorageKHR(VkPerformanceCounterStorageKHR input_value)
+{
+ switch ((VkPerformanceCounterStorageKHR)input_value)
+ {
+ case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR:
+ return "VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR";
+ case VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR:
+ return "VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR";
+ case VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR:
+ return "VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR";
+ case VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR:
+ return "VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR";
+ case VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR:
+ return "VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR";
+ case VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR:
+ return "VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR";
+ default:
+ return "Unhandled VkPerformanceCounterStorageKHR";
+ }
+}
+
+static inline const char* string_VkPerformanceCounterDescriptionFlagBitsKHR(VkPerformanceCounterDescriptionFlagBitsKHR input_value)
+{
+ switch ((VkPerformanceCounterDescriptionFlagBitsKHR)input_value)
+ {
+ case VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR:
+ return "VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR";
+ case VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR:
+ return "VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR";
+ default:
+ return "Unhandled VkPerformanceCounterDescriptionFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkPerformanceCounterDescriptionFlagsKHR(VkPerformanceCounterDescriptionFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkPerformanceCounterDescriptionFlagBitsKHR(static_cast<VkPerformanceCounterDescriptionFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkPerformanceCounterDescriptionFlagBitsKHR(static_cast<VkPerformanceCounterDescriptionFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPointClippingBehaviorKHR(VkPointClippingBehaviorKHR input_value)
+{
+ switch ((VkPointClippingBehaviorKHR)input_value)
+ {
+ case VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES:
+ return "VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES";
+ case VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY:
+ return "VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY";
+ default:
+ return "Unhandled VkPointClippingBehaviorKHR";
+ }
+}
+
+static inline const char* string_VkTessellationDomainOriginKHR(VkTessellationDomainOriginKHR input_value)
+{
+ switch ((VkTessellationDomainOriginKHR)input_value)
+ {
+ case VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT:
+ return "VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT";
+ case VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT:
+ return "VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT";
+ default:
+ return "Unhandled VkTessellationDomainOriginKHR";
+ }
+}
+
+static inline const char* string_VkSamplerYcbcrModelConversionKHR(VkSamplerYcbcrModelConversionKHR input_value)
+{
+ switch ((VkSamplerYcbcrModelConversionKHR)input_value)
+ {
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY:
+ return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020:
+ return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601:
+ return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709:
+ return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY:
+ return "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY";
+ default:
+ return "Unhandled VkSamplerYcbcrModelConversionKHR";
+ }
+}
+
+static inline const char* string_VkSamplerYcbcrRangeKHR(VkSamplerYcbcrRangeKHR input_value)
+{
+ switch ((VkSamplerYcbcrRangeKHR)input_value)
+ {
+ case VK_SAMPLER_YCBCR_RANGE_ITU_FULL:
+ return "VK_SAMPLER_YCBCR_RANGE_ITU_FULL";
+ case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW:
+ return "VK_SAMPLER_YCBCR_RANGE_ITU_NARROW";
+ default:
+ return "Unhandled VkSamplerYcbcrRangeKHR";
+ }
+}
+
+static inline const char* string_VkChromaLocationKHR(VkChromaLocationKHR input_value)
+{
+ switch ((VkChromaLocationKHR)input_value)
+ {
+ case VK_CHROMA_LOCATION_COSITED_EVEN:
+ return "VK_CHROMA_LOCATION_COSITED_EVEN";
+ case VK_CHROMA_LOCATION_MIDPOINT:
+ return "VK_CHROMA_LOCATION_MIDPOINT";
+ default:
+ return "Unhandled VkChromaLocationKHR";
+ }
+}
+
+static inline const char* string_VkDriverIdKHR(VkDriverIdKHR input_value)
+{
+ switch ((VkDriverIdKHR)input_value)
+ {
+ case VK_DRIVER_ID_AMD_OPEN_SOURCE:
+ return "VK_DRIVER_ID_AMD_OPEN_SOURCE";
+ case VK_DRIVER_ID_AMD_PROPRIETARY:
+ return "VK_DRIVER_ID_AMD_PROPRIETARY";
+ case VK_DRIVER_ID_ARM_PROPRIETARY:
+ return "VK_DRIVER_ID_ARM_PROPRIETARY";
+ case VK_DRIVER_ID_BROADCOM_PROPRIETARY:
+ return "VK_DRIVER_ID_BROADCOM_PROPRIETARY";
+ case VK_DRIVER_ID_GGP_PROPRIETARY:
+ return "VK_DRIVER_ID_GGP_PROPRIETARY";
+ case VK_DRIVER_ID_GOOGLE_SWIFTSHADER:
+ return "VK_DRIVER_ID_GOOGLE_SWIFTSHADER";
+ case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
+ return "VK_DRIVER_ID_IMAGINATION_PROPRIETARY";
+ case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA:
+ return "VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA";
+ case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS:
+ return "VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS";
+ case VK_DRIVER_ID_MESA_RADV:
+ return "VK_DRIVER_ID_MESA_RADV";
+ case VK_DRIVER_ID_NVIDIA_PROPRIETARY:
+ return "VK_DRIVER_ID_NVIDIA_PROPRIETARY";
+ case VK_DRIVER_ID_QUALCOMM_PROPRIETARY:
+ return "VK_DRIVER_ID_QUALCOMM_PROPRIETARY";
+ default:
+ return "Unhandled VkDriverIdKHR";
+ }
+}
+
+static inline const char* string_VkShaderFloatControlsIndependenceKHR(VkShaderFloatControlsIndependenceKHR input_value)
+{
+ switch ((VkShaderFloatControlsIndependenceKHR)input_value)
+ {
+ case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY:
+ return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY";
+ case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL:
+ return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL";
+ case VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE:
+ return "VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE";
+ default:
+ return "Unhandled VkShaderFloatControlsIndependenceKHR";
+ }
+}
+
+static inline const char* string_VkResolveModeFlagBitsKHR(VkResolveModeFlagBitsKHR input_value)
+{
+ switch ((VkResolveModeFlagBitsKHR)input_value)
+ {
+ case VK_RESOLVE_MODE_AVERAGE_BIT:
+ return "VK_RESOLVE_MODE_AVERAGE_BIT";
+ case VK_RESOLVE_MODE_MAX_BIT:
+ return "VK_RESOLVE_MODE_MAX_BIT";
+ case VK_RESOLVE_MODE_MIN_BIT:
+ return "VK_RESOLVE_MODE_MIN_BIT";
+ case VK_RESOLVE_MODE_NONE:
+ return "VK_RESOLVE_MODE_NONE";
+ case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT:
+ return "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT";
+ default:
+ return "Unhandled VkResolveModeFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkResolveModeFlagsKHR(VkResolveModeFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkResolveModeFlagBitsKHR(static_cast<VkResolveModeFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkResolveModeFlagBitsKHR(static_cast<VkResolveModeFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkSemaphoreTypeKHR(VkSemaphoreTypeKHR input_value)
+{
+ switch ((VkSemaphoreTypeKHR)input_value)
+ {
+ case VK_SEMAPHORE_TYPE_BINARY:
+ return "VK_SEMAPHORE_TYPE_BINARY";
+ case VK_SEMAPHORE_TYPE_TIMELINE:
+ return "VK_SEMAPHORE_TYPE_TIMELINE";
+ default:
+ return "Unhandled VkSemaphoreTypeKHR";
+ }
+}
+
+static inline const char* string_VkSemaphoreWaitFlagBitsKHR(VkSemaphoreWaitFlagBitsKHR input_value)
+{
+ switch ((VkSemaphoreWaitFlagBitsKHR)input_value)
+ {
+ case VK_SEMAPHORE_WAIT_ANY_BIT:
+ return "VK_SEMAPHORE_WAIT_ANY_BIT";
+ default:
+ return "Unhandled VkSemaphoreWaitFlagBitsKHR";
+ }
+}
+
+static inline std::string string_VkSemaphoreWaitFlagsKHR(VkSemaphoreWaitFlagsKHR input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSemaphoreWaitFlagBitsKHR(static_cast<VkSemaphoreWaitFlagBitsKHR>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSemaphoreWaitFlagBitsKHR(static_cast<VkSemaphoreWaitFlagBitsKHR>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPipelineExecutableStatisticFormatKHR(VkPipelineExecutableStatisticFormatKHR input_value)
+{
+ switch ((VkPipelineExecutableStatisticFormatKHR)input_value)
+ {
+ case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
+ return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR";
+ case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
+ return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR";
+ case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
+ return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR";
+ case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
+ return "VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR";
+ default:
+ return "Unhandled VkPipelineExecutableStatisticFormatKHR";
+ }
+}
+
+static inline const char* string_VkDebugReportObjectTypeEXT(VkDebugReportObjectTypeEXT input_value)
+{
+ switch ((VkDebugReportObjectTypeEXT)input_value)
+ {
+ case VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT";
+ case VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT:
+ return "VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT";
+ default:
+ return "Unhandled VkDebugReportObjectTypeEXT";
+ }
+}
+
+static inline const char* string_VkDebugReportFlagBitsEXT(VkDebugReportFlagBitsEXT input_value)
+{
+ switch ((VkDebugReportFlagBitsEXT)input_value)
+ {
+ case VK_DEBUG_REPORT_DEBUG_BIT_EXT:
+ return "VK_DEBUG_REPORT_DEBUG_BIT_EXT";
+ case VK_DEBUG_REPORT_ERROR_BIT_EXT:
+ return "VK_DEBUG_REPORT_ERROR_BIT_EXT";
+ case VK_DEBUG_REPORT_INFORMATION_BIT_EXT:
+ return "VK_DEBUG_REPORT_INFORMATION_BIT_EXT";
+ case VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT:
+ return "VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT";
+ case VK_DEBUG_REPORT_WARNING_BIT_EXT:
+ return "VK_DEBUG_REPORT_WARNING_BIT_EXT";
+ default:
+ return "Unhandled VkDebugReportFlagBitsEXT";
+ }
+}
+
+static inline std::string string_VkDebugReportFlagsEXT(VkDebugReportFlagsEXT input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDebugReportFlagBitsEXT(static_cast<VkDebugReportFlagBitsEXT>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDebugReportFlagBitsEXT(static_cast<VkDebugReportFlagBitsEXT>(0)));
+ return ret;
+}
+
+static inline const char* string_VkRasterizationOrderAMD(VkRasterizationOrderAMD input_value)
+{
+ switch ((VkRasterizationOrderAMD)input_value)
+ {
+ case VK_RASTERIZATION_ORDER_RELAXED_AMD:
+ return "VK_RASTERIZATION_ORDER_RELAXED_AMD";
+ case VK_RASTERIZATION_ORDER_STRICT_AMD:
+ return "VK_RASTERIZATION_ORDER_STRICT_AMD";
+ default:
+ return "Unhandled VkRasterizationOrderAMD";
+ }
+}
+
+static inline const char* string_VkShaderInfoTypeAMD(VkShaderInfoTypeAMD input_value)
+{
+ switch ((VkShaderInfoTypeAMD)input_value)
+ {
+ case VK_SHADER_INFO_TYPE_BINARY_AMD:
+ return "VK_SHADER_INFO_TYPE_BINARY_AMD";
+ case VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD:
+ return "VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD";
+ case VK_SHADER_INFO_TYPE_STATISTICS_AMD:
+ return "VK_SHADER_INFO_TYPE_STATISTICS_AMD";
+ default:
+ return "Unhandled VkShaderInfoTypeAMD";
+ }
+}
+
+static inline const char* string_VkExternalMemoryHandleTypeFlagBitsNV(VkExternalMemoryHandleTypeFlagBitsNV input_value)
+{
+ switch ((VkExternalMemoryHandleTypeFlagBitsNV)input_value)
+ {
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV";
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV:
+ return "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV";
+ default:
+ return "Unhandled VkExternalMemoryHandleTypeFlagBitsNV";
+ }
+}
+
+static inline std::string string_VkExternalMemoryHandleTypeFlagsNV(VkExternalMemoryHandleTypeFlagsNV input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalMemoryHandleTypeFlagBitsNV(static_cast<VkExternalMemoryHandleTypeFlagBitsNV>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalMemoryHandleTypeFlagBitsNV(static_cast<VkExternalMemoryHandleTypeFlagBitsNV>(0)));
+ return ret;
+}
+
+static inline const char* string_VkExternalMemoryFeatureFlagBitsNV(VkExternalMemoryFeatureFlagBitsNV input_value)
+{
+ switch ((VkExternalMemoryFeatureFlagBitsNV)input_value)
+ {
+ case VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV:
+ return "VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV";
+ case VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV:
+ return "VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV";
+ case VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV:
+ return "VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV";
+ default:
+ return "Unhandled VkExternalMemoryFeatureFlagBitsNV";
+ }
+}
+
+static inline std::string string_VkExternalMemoryFeatureFlagsNV(VkExternalMemoryFeatureFlagsNV input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkExternalMemoryFeatureFlagBitsNV(static_cast<VkExternalMemoryFeatureFlagBitsNV>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkExternalMemoryFeatureFlagBitsNV(static_cast<VkExternalMemoryFeatureFlagBitsNV>(0)));
+ return ret;
+}
+
+static inline const char* string_VkValidationCheckEXT(VkValidationCheckEXT input_value)
+{
+ switch ((VkValidationCheckEXT)input_value)
+ {
+ case VK_VALIDATION_CHECK_ALL_EXT:
+ return "VK_VALIDATION_CHECK_ALL_EXT";
+ case VK_VALIDATION_CHECK_SHADERS_EXT:
+ return "VK_VALIDATION_CHECK_SHADERS_EXT";
+ default:
+ return "Unhandled VkValidationCheckEXT";
+ }
+}
+
+static inline const char* string_VkConditionalRenderingFlagBitsEXT(VkConditionalRenderingFlagBitsEXT input_value)
+{
+ switch ((VkConditionalRenderingFlagBitsEXT)input_value)
+ {
+ case VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT:
+ return "VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT";
+ default:
+ return "Unhandled VkConditionalRenderingFlagBitsEXT";
+ }
+}
+
+static inline std::string string_VkConditionalRenderingFlagsEXT(VkConditionalRenderingFlagsEXT input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkConditionalRenderingFlagBitsEXT(static_cast<VkConditionalRenderingFlagBitsEXT>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkConditionalRenderingFlagBitsEXT(static_cast<VkConditionalRenderingFlagBitsEXT>(0)));
+ return ret;
+}
+
+static inline const char* string_VkIndirectCommandsLayoutUsageFlagBitsNVX(VkIndirectCommandsLayoutUsageFlagBitsNVX input_value)
+{
+ switch ((VkIndirectCommandsLayoutUsageFlagBitsNVX)input_value)
+ {
+ case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX:
+ return "VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX";
+ case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX:
+ return "VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX";
+ case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX:
+ return "VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX";
+ case VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX:
+ return "VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX";
+ default:
+ return "Unhandled VkIndirectCommandsLayoutUsageFlagBitsNVX";
+ }
+}
+
+static inline std::string string_VkIndirectCommandsLayoutUsageFlagsNVX(VkIndirectCommandsLayoutUsageFlagsNVX input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkIndirectCommandsLayoutUsageFlagBitsNVX(static_cast<VkIndirectCommandsLayoutUsageFlagBitsNVX>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkIndirectCommandsLayoutUsageFlagBitsNVX(static_cast<VkIndirectCommandsLayoutUsageFlagBitsNVX>(0)));
+ return ret;
+}
+
+static inline const char* string_VkObjectEntryUsageFlagBitsNVX(VkObjectEntryUsageFlagBitsNVX input_value)
+{
+ switch ((VkObjectEntryUsageFlagBitsNVX)input_value)
+ {
+ case VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX:
+ return "VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX";
+ case VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX:
+ return "VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX";
+ default:
+ return "Unhandled VkObjectEntryUsageFlagBitsNVX";
+ }
+}
+
+static inline std::string string_VkObjectEntryUsageFlagsNVX(VkObjectEntryUsageFlagsNVX input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkObjectEntryUsageFlagBitsNVX(static_cast<VkObjectEntryUsageFlagBitsNVX>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkObjectEntryUsageFlagBitsNVX(static_cast<VkObjectEntryUsageFlagBitsNVX>(0)));
+ return ret;
+}
+
+static inline const char* string_VkIndirectCommandsTokenTypeNVX(VkIndirectCommandsTokenTypeNVX input_value)
+{
+ switch ((VkIndirectCommandsTokenTypeNVX)input_value)
+ {
+ case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX:
+ return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX";
+ case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX:
+ return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX";
+ case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX:
+ return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX";
+ case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX:
+ return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX";
+ case VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX:
+ return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX";
+ case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX:
+ return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX";
+ case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX:
+ return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX";
+ case VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX:
+ return "VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX";
+ default:
+ return "Unhandled VkIndirectCommandsTokenTypeNVX";
+ }
+}
+
+static inline const char* string_VkObjectEntryTypeNVX(VkObjectEntryTypeNVX input_value)
+{
+ switch ((VkObjectEntryTypeNVX)input_value)
+ {
+ case VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX:
+ return "VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX";
+ case VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX:
+ return "VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX";
+ case VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX:
+ return "VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX";
+ case VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX:
+ return "VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX";
+ case VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX:
+ return "VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX";
+ default:
+ return "Unhandled VkObjectEntryTypeNVX";
+ }
+}
+
+static inline const char* string_VkSurfaceCounterFlagBitsEXT(VkSurfaceCounterFlagBitsEXT input_value)
+{
+ switch ((VkSurfaceCounterFlagBitsEXT)input_value)
+ {
+ case VK_SURFACE_COUNTER_VBLANK_EXT:
+ return "VK_SURFACE_COUNTER_VBLANK_EXT";
+ default:
+ return "Unhandled VkSurfaceCounterFlagBitsEXT";
+ }
+}
+
+static inline std::string string_VkSurfaceCounterFlagsEXT(VkSurfaceCounterFlagsEXT input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkSurfaceCounterFlagBitsEXT(static_cast<VkSurfaceCounterFlagBitsEXT>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkSurfaceCounterFlagBitsEXT(static_cast<VkSurfaceCounterFlagBitsEXT>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDisplayPowerStateEXT(VkDisplayPowerStateEXT input_value)
+{
+ switch ((VkDisplayPowerStateEXT)input_value)
+ {
+ case VK_DISPLAY_POWER_STATE_OFF_EXT:
+ return "VK_DISPLAY_POWER_STATE_OFF_EXT";
+ case VK_DISPLAY_POWER_STATE_ON_EXT:
+ return "VK_DISPLAY_POWER_STATE_ON_EXT";
+ case VK_DISPLAY_POWER_STATE_SUSPEND_EXT:
+ return "VK_DISPLAY_POWER_STATE_SUSPEND_EXT";
+ default:
+ return "Unhandled VkDisplayPowerStateEXT";
+ }
+}
+
+static inline const char* string_VkDeviceEventTypeEXT(VkDeviceEventTypeEXT input_value)
+{
+ switch ((VkDeviceEventTypeEXT)input_value)
+ {
+ case VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT:
+ return "VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT";
+ default:
+ return "Unhandled VkDeviceEventTypeEXT";
+ }
+}
+
+static inline const char* string_VkDisplayEventTypeEXT(VkDisplayEventTypeEXT input_value)
+{
+ switch ((VkDisplayEventTypeEXT)input_value)
+ {
+ case VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT:
+ return "VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT";
+ default:
+ return "Unhandled VkDisplayEventTypeEXT";
+ }
+}
+
+static inline const char* string_VkViewportCoordinateSwizzleNV(VkViewportCoordinateSwizzleNV input_value)
+{
+ switch ((VkViewportCoordinateSwizzleNV)input_value)
+ {
+ case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV:
+ return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV";
+ case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV:
+ return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV";
+ case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV:
+ return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV";
+ case VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV:
+ return "VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV";
+ case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV:
+ return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV";
+ case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV:
+ return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV";
+ case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV:
+ return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV";
+ case VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV:
+ return "VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV";
+ default:
+ return "Unhandled VkViewportCoordinateSwizzleNV";
+ }
+}
+
+static inline const char* string_VkDiscardRectangleModeEXT(VkDiscardRectangleModeEXT input_value)
+{
+ switch ((VkDiscardRectangleModeEXT)input_value)
+ {
+ case VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT:
+ return "VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT";
+ case VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT:
+ return "VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT";
+ default:
+ return "Unhandled VkDiscardRectangleModeEXT";
+ }
+}
+
+static inline const char* string_VkConservativeRasterizationModeEXT(VkConservativeRasterizationModeEXT input_value)
+{
+ switch ((VkConservativeRasterizationModeEXT)input_value)
+ {
+ case VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT:
+ return "VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT";
+ case VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT:
+ return "VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT";
+ case VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT:
+ return "VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT";
+ default:
+ return "Unhandled VkConservativeRasterizationModeEXT";
+ }
+}
+
+static inline const char* string_VkDebugUtilsMessageSeverityFlagBitsEXT(VkDebugUtilsMessageSeverityFlagBitsEXT input_value)
+{
+ switch ((VkDebugUtilsMessageSeverityFlagBitsEXT)input_value)
+ {
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
+ return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT";
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
+ return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT";
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
+ return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT";
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
+ return "VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT";
+ default:
+ return "Unhandled VkDebugUtilsMessageSeverityFlagBitsEXT";
+ }
+}
+
+static inline std::string string_VkDebugUtilsMessageSeverityFlagsEXT(VkDebugUtilsMessageSeverityFlagsEXT input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDebugUtilsMessageSeverityFlagBitsEXT(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDebugUtilsMessageSeverityFlagBitsEXT(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(0)));
+ return ret;
+}
+
+static inline const char* string_VkDebugUtilsMessageTypeFlagBitsEXT(VkDebugUtilsMessageTypeFlagBitsEXT input_value)
+{
+ switch ((VkDebugUtilsMessageTypeFlagBitsEXT)input_value)
+ {
+ case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT:
+ return "VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT";
+ case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT:
+ return "VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT";
+ case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT:
+ return "VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT";
+ default:
+ return "Unhandled VkDebugUtilsMessageTypeFlagBitsEXT";
+ }
+}
+
+static inline std::string string_VkDebugUtilsMessageTypeFlagsEXT(VkDebugUtilsMessageTypeFlagsEXT input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDebugUtilsMessageTypeFlagBitsEXT(static_cast<VkDebugUtilsMessageTypeFlagBitsEXT>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDebugUtilsMessageTypeFlagBitsEXT(static_cast<VkDebugUtilsMessageTypeFlagBitsEXT>(0)));
+ return ret;
+}
+
+static inline const char* string_VkSamplerReductionModeEXT(VkSamplerReductionModeEXT input_value)
+{
+ switch ((VkSamplerReductionModeEXT)input_value)
+ {
+ case VK_SAMPLER_REDUCTION_MODE_MAX:
+ return "VK_SAMPLER_REDUCTION_MODE_MAX";
+ case VK_SAMPLER_REDUCTION_MODE_MIN:
+ return "VK_SAMPLER_REDUCTION_MODE_MIN";
+ case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE:
+ return "VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE";
+ default:
+ return "Unhandled VkSamplerReductionModeEXT";
+ }
+}
+
+static inline const char* string_VkBlendOverlapEXT(VkBlendOverlapEXT input_value)
+{
+ switch ((VkBlendOverlapEXT)input_value)
+ {
+ case VK_BLEND_OVERLAP_CONJOINT_EXT:
+ return "VK_BLEND_OVERLAP_CONJOINT_EXT";
+ case VK_BLEND_OVERLAP_DISJOINT_EXT:
+ return "VK_BLEND_OVERLAP_DISJOINT_EXT";
+ case VK_BLEND_OVERLAP_UNCORRELATED_EXT:
+ return "VK_BLEND_OVERLAP_UNCORRELATED_EXT";
+ default:
+ return "Unhandled VkBlendOverlapEXT";
+ }
+}
+
+static inline const char* string_VkCoverageModulationModeNV(VkCoverageModulationModeNV input_value)
+{
+ switch ((VkCoverageModulationModeNV)input_value)
+ {
+ case VK_COVERAGE_MODULATION_MODE_ALPHA_NV:
+ return "VK_COVERAGE_MODULATION_MODE_ALPHA_NV";
+ case VK_COVERAGE_MODULATION_MODE_NONE_NV:
+ return "VK_COVERAGE_MODULATION_MODE_NONE_NV";
+ case VK_COVERAGE_MODULATION_MODE_RGBA_NV:
+ return "VK_COVERAGE_MODULATION_MODE_RGBA_NV";
+ case VK_COVERAGE_MODULATION_MODE_RGB_NV:
+ return "VK_COVERAGE_MODULATION_MODE_RGB_NV";
+ default:
+ return "Unhandled VkCoverageModulationModeNV";
+ }
+}
+
+static inline const char* string_VkValidationCacheHeaderVersionEXT(VkValidationCacheHeaderVersionEXT input_value)
+{
+ switch ((VkValidationCacheHeaderVersionEXT)input_value)
+ {
+ case VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT:
+ return "VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT";
+ default:
+ return "Unhandled VkValidationCacheHeaderVersionEXT";
+ }
+}
+
+static inline const char* string_VkDescriptorBindingFlagBitsEXT(VkDescriptorBindingFlagBitsEXT input_value)
+{
+ switch ((VkDescriptorBindingFlagBitsEXT)input_value)
+ {
+ case VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT:
+ return "VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT";
+ case VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT:
+ return "VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT";
+ case VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT:
+ return "VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT";
+ case VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT:
+ return "VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT";
+ default:
+ return "Unhandled VkDescriptorBindingFlagBitsEXT";
+ }
+}
+
+static inline std::string string_VkDescriptorBindingFlagsEXT(VkDescriptorBindingFlagsEXT input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkDescriptorBindingFlagBitsEXT(static_cast<VkDescriptorBindingFlagBitsEXT>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkDescriptorBindingFlagBitsEXT(static_cast<VkDescriptorBindingFlagBitsEXT>(0)));
+ return ret;
+}
+
+static inline const char* string_VkShadingRatePaletteEntryNV(VkShadingRatePaletteEntryNV input_value)
+{
+ switch ((VkShadingRatePaletteEntryNV)input_value)
+ {
+ case VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV";
+ case VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV:
+ return "VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV";
+ default:
+ return "Unhandled VkShadingRatePaletteEntryNV";
+ }
+}
+
+static inline const char* string_VkCoarseSampleOrderTypeNV(VkCoarseSampleOrderTypeNV input_value)
+{
+ switch ((VkCoarseSampleOrderTypeNV)input_value)
+ {
+ case VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV:
+ return "VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV";
+ case VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV:
+ return "VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV";
+ case VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV:
+ return "VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV";
+ case VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV:
+ return "VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV";
+ default:
+ return "Unhandled VkCoarseSampleOrderTypeNV";
+ }
+}
+
+static inline const char* string_VkAccelerationStructureTypeNV(VkAccelerationStructureTypeNV input_value)
+{
+ switch ((VkAccelerationStructureTypeNV)input_value)
+ {
+ case VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV:
+ return "VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV";
+ case VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV:
+ return "VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV";
+ default:
+ return "Unhandled VkAccelerationStructureTypeNV";
+ }
+}
+
+static inline const char* string_VkRayTracingShaderGroupTypeNV(VkRayTracingShaderGroupTypeNV input_value)
+{
+ switch ((VkRayTracingShaderGroupTypeNV)input_value)
+ {
+ case VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV:
+ return "VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV";
+ case VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV:
+ return "VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV";
+ case VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV:
+ return "VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV";
+ default:
+ return "Unhandled VkRayTracingShaderGroupTypeNV";
+ }
+}
+
+static inline const char* string_VkGeometryTypeNV(VkGeometryTypeNV input_value)
+{
+ switch ((VkGeometryTypeNV)input_value)
+ {
+ case VK_GEOMETRY_TYPE_AABBS_NV:
+ return "VK_GEOMETRY_TYPE_AABBS_NV";
+ case VK_GEOMETRY_TYPE_TRIANGLES_NV:
+ return "VK_GEOMETRY_TYPE_TRIANGLES_NV";
+ default:
+ return "Unhandled VkGeometryTypeNV";
+ }
+}
+
+static inline const char* string_VkGeometryFlagBitsNV(VkGeometryFlagBitsNV input_value)
+{
+ switch ((VkGeometryFlagBitsNV)input_value)
+ {
+ case VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV:
+ return "VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV";
+ case VK_GEOMETRY_OPAQUE_BIT_NV:
+ return "VK_GEOMETRY_OPAQUE_BIT_NV";
+ default:
+ return "Unhandled VkGeometryFlagBitsNV";
+ }
+}
+
+static inline std::string string_VkGeometryFlagsNV(VkGeometryFlagsNV input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkGeometryFlagBitsNV(static_cast<VkGeometryFlagBitsNV>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkGeometryFlagBitsNV(static_cast<VkGeometryFlagBitsNV>(0)));
+ return ret;
+}
+
+static inline const char* string_VkGeometryInstanceFlagBitsNV(VkGeometryInstanceFlagBitsNV input_value)
+{
+ switch ((VkGeometryInstanceFlagBitsNV)input_value)
+ {
+ case VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV:
+ return "VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV";
+ case VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV:
+ return "VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV";
+ case VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV:
+ return "VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV";
+ case VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV:
+ return "VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV";
+ default:
+ return "Unhandled VkGeometryInstanceFlagBitsNV";
+ }
+}
+
+static inline std::string string_VkGeometryInstanceFlagsNV(VkGeometryInstanceFlagsNV input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkGeometryInstanceFlagBitsNV(static_cast<VkGeometryInstanceFlagBitsNV>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkGeometryInstanceFlagBitsNV(static_cast<VkGeometryInstanceFlagBitsNV>(0)));
+ return ret;
+}
+
+static inline const char* string_VkBuildAccelerationStructureFlagBitsNV(VkBuildAccelerationStructureFlagBitsNV input_value)
+{
+ switch ((VkBuildAccelerationStructureFlagBitsNV)input_value)
+ {
+ case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV:
+ return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV";
+ case VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV:
+ return "VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV";
+ case VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV:
+ return "VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV";
+ case VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV:
+ return "VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV";
+ case VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV:
+ return "VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV";
+ default:
+ return "Unhandled VkBuildAccelerationStructureFlagBitsNV";
+ }
+}
+
+static inline std::string string_VkBuildAccelerationStructureFlagsNV(VkBuildAccelerationStructureFlagsNV input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkBuildAccelerationStructureFlagBitsNV(static_cast<VkBuildAccelerationStructureFlagBitsNV>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkBuildAccelerationStructureFlagBitsNV(static_cast<VkBuildAccelerationStructureFlagBitsNV>(0)));
+ return ret;
+}
+
+static inline const char* string_VkCopyAccelerationStructureModeNV(VkCopyAccelerationStructureModeNV input_value)
+{
+ switch ((VkCopyAccelerationStructureModeNV)input_value)
+ {
+ case VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV:
+ return "VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV";
+ case VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV:
+ return "VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV";
+ default:
+ return "Unhandled VkCopyAccelerationStructureModeNV";
+ }
+}
+
+static inline const char* string_VkAccelerationStructureMemoryRequirementsTypeNV(VkAccelerationStructureMemoryRequirementsTypeNV input_value)
+{
+ switch ((VkAccelerationStructureMemoryRequirementsTypeNV)input_value)
+ {
+ case VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV:
+ return "VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV";
+ case VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV:
+ return "VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV";
+ case VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV:
+ return "VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV";
+ default:
+ return "Unhandled VkAccelerationStructureMemoryRequirementsTypeNV";
+ }
+}
+
+static inline const char* string_VkQueueGlobalPriorityEXT(VkQueueGlobalPriorityEXT input_value)
+{
+ switch ((VkQueueGlobalPriorityEXT)input_value)
+ {
+ case VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT:
+ return "VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT";
+ case VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT:
+ return "VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT";
+ case VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT:
+ return "VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT";
+ case VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT:
+ return "VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT";
+ default:
+ return "Unhandled VkQueueGlobalPriorityEXT";
+ }
+}
+
+static inline const char* string_VkTimeDomainEXT(VkTimeDomainEXT input_value)
+{
+ switch ((VkTimeDomainEXT)input_value)
+ {
+ case VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT:
+ return "VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT";
+ case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT:
+ return "VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT";
+ case VK_TIME_DOMAIN_DEVICE_EXT:
+ return "VK_TIME_DOMAIN_DEVICE_EXT";
+ case VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT:
+ return "VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT";
+ default:
+ return "Unhandled VkTimeDomainEXT";
+ }
+}
+
+static inline const char* string_VkMemoryOverallocationBehaviorAMD(VkMemoryOverallocationBehaviorAMD input_value)
+{
+ switch ((VkMemoryOverallocationBehaviorAMD)input_value)
+ {
+ case VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD:
+ return "VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD";
+ case VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD:
+ return "VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD";
+ case VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD:
+ return "VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD";
+ default:
+ return "Unhandled VkMemoryOverallocationBehaviorAMD";
+ }
+}
+
+static inline const char* string_VkPipelineCreationFeedbackFlagBitsEXT(VkPipelineCreationFeedbackFlagBitsEXT input_value)
+{
+ switch ((VkPipelineCreationFeedbackFlagBitsEXT)input_value)
+ {
+ case VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT:
+ return "VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT";
+ case VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT:
+ return "VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT";
+ case VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT:
+ return "VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT";
+ default:
+ return "Unhandled VkPipelineCreationFeedbackFlagBitsEXT";
+ }
+}
+
+static inline std::string string_VkPipelineCreationFeedbackFlagsEXT(VkPipelineCreationFeedbackFlagsEXT input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkPipelineCreationFeedbackFlagBitsEXT(static_cast<VkPipelineCreationFeedbackFlagBitsEXT>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkPipelineCreationFeedbackFlagBitsEXT(static_cast<VkPipelineCreationFeedbackFlagBitsEXT>(0)));
+ return ret;
+}
+
+static inline const char* string_VkPerformanceConfigurationTypeINTEL(VkPerformanceConfigurationTypeINTEL input_value)
+{
+ switch ((VkPerformanceConfigurationTypeINTEL)input_value)
+ {
+ case VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL:
+ return "VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL";
+ default:
+ return "Unhandled VkPerformanceConfigurationTypeINTEL";
+ }
+}
+
+static inline const char* string_VkQueryPoolSamplingModeINTEL(VkQueryPoolSamplingModeINTEL input_value)
+{
+ switch ((VkQueryPoolSamplingModeINTEL)input_value)
+ {
+ case VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL:
+ return "VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL";
+ default:
+ return "Unhandled VkQueryPoolSamplingModeINTEL";
+ }
+}
+
+static inline const char* string_VkPerformanceOverrideTypeINTEL(VkPerformanceOverrideTypeINTEL input_value)
+{
+ switch ((VkPerformanceOverrideTypeINTEL)input_value)
+ {
+ case VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL:
+ return "VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL";
+ case VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL:
+ return "VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL";
+ default:
+ return "Unhandled VkPerformanceOverrideTypeINTEL";
+ }
+}
+
+static inline const char* string_VkPerformanceParameterTypeINTEL(VkPerformanceParameterTypeINTEL input_value)
+{
+ switch ((VkPerformanceParameterTypeINTEL)input_value)
+ {
+ case VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL:
+ return "VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL";
+ case VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL:
+ return "VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL";
+ default:
+ return "Unhandled VkPerformanceParameterTypeINTEL";
+ }
+}
+
+static inline const char* string_VkPerformanceValueTypeINTEL(VkPerformanceValueTypeINTEL input_value)
+{
+ switch ((VkPerformanceValueTypeINTEL)input_value)
+ {
+ case VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL:
+ return "VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL";
+ case VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL:
+ return "VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL";
+ case VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL:
+ return "VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL";
+ case VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL:
+ return "VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL";
+ case VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL:
+ return "VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL";
+ default:
+ return "Unhandled VkPerformanceValueTypeINTEL";
+ }
+}
+
+static inline const char* string_VkToolPurposeFlagBitsEXT(VkToolPurposeFlagBitsEXT input_value)
+{
+ switch ((VkToolPurposeFlagBitsEXT)input_value)
+ {
+ case VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT:
+ return "VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT";
+ case VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT:
+ return "VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT";
+ case VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT:
+ return "VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT";
+ case VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT:
+ return "VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT";
+ case VK_TOOL_PURPOSE_PROFILING_BIT_EXT:
+ return "VK_TOOL_PURPOSE_PROFILING_BIT_EXT";
+ case VK_TOOL_PURPOSE_TRACING_BIT_EXT:
+ return "VK_TOOL_PURPOSE_TRACING_BIT_EXT";
+ case VK_TOOL_PURPOSE_VALIDATION_BIT_EXT:
+ return "VK_TOOL_PURPOSE_VALIDATION_BIT_EXT";
+ default:
+ return "Unhandled VkToolPurposeFlagBitsEXT";
+ }
+}
+
+static inline std::string string_VkToolPurposeFlagsEXT(VkToolPurposeFlagsEXT input_value)
+{
+ std::string ret;
+ int index = 0;
+ while(input_value) {
+ if (input_value & 1) {
+ if( !ret.empty()) ret.append("|");
+ ret.append(string_VkToolPurposeFlagBitsEXT(static_cast<VkToolPurposeFlagBitsEXT>(1 << index)));
+ }
+ ++index;
+ input_value >>= 1;
+ }
+ if( ret.empty()) ret.append(string_VkToolPurposeFlagBitsEXT(static_cast<VkToolPurposeFlagBitsEXT>(0)));
+ return ret;
+}
+
+static inline const char* string_VkValidationFeatureEnableEXT(VkValidationFeatureEnableEXT input_value)
+{
+ switch ((VkValidationFeatureEnableEXT)input_value)
+ {
+ case VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT:
+ return "VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT";
+ case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
+ return "VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT";
+ case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
+ return "VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT";
+ default:
+ return "Unhandled VkValidationFeatureEnableEXT";
+ }
+}
+
+static inline const char* string_VkValidationFeatureDisableEXT(VkValidationFeatureDisableEXT input_value)
+{
+ switch ((VkValidationFeatureDisableEXT)input_value)
+ {
+ case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
+ return "VK_VALIDATION_FEATURE_DISABLE_ALL_EXT";
+ case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
+ return "VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT";
+ case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
+ return "VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT";
+ case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
+ return "VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT";
+ case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
+ return "VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT";
+ case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
+ return "VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT";
+ case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
+ return "VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT";
+ default:
+ return "Unhandled VkValidationFeatureDisableEXT";
+ }
+}
+
+static inline const char* string_VkComponentTypeNV(VkComponentTypeNV input_value)
+{
+ switch ((VkComponentTypeNV)input_value)
+ {
+ case VK_COMPONENT_TYPE_FLOAT16_NV:
+ return "VK_COMPONENT_TYPE_FLOAT16_NV";
+ case VK_COMPONENT_TYPE_FLOAT32_NV:
+ return "VK_COMPONENT_TYPE_FLOAT32_NV";
+ case VK_COMPONENT_TYPE_FLOAT64_NV:
+ return "VK_COMPONENT_TYPE_FLOAT64_NV";
+ case VK_COMPONENT_TYPE_SINT16_NV:
+ return "VK_COMPONENT_TYPE_SINT16_NV";
+ case VK_COMPONENT_TYPE_SINT32_NV:
+ return "VK_COMPONENT_TYPE_SINT32_NV";
+ case VK_COMPONENT_TYPE_SINT64_NV:
+ return "VK_COMPONENT_TYPE_SINT64_NV";
+ case VK_COMPONENT_TYPE_SINT8_NV:
+ return "VK_COMPONENT_TYPE_SINT8_NV";
+ case VK_COMPONENT_TYPE_UINT16_NV:
+ return "VK_COMPONENT_TYPE_UINT16_NV";
+ case VK_COMPONENT_TYPE_UINT32_NV:
+ return "VK_COMPONENT_TYPE_UINT32_NV";
+ case VK_COMPONENT_TYPE_UINT64_NV:
+ return "VK_COMPONENT_TYPE_UINT64_NV";
+ case VK_COMPONENT_TYPE_UINT8_NV:
+ return "VK_COMPONENT_TYPE_UINT8_NV";
+ default:
+ return "Unhandled VkComponentTypeNV";
+ }
+}
+
+static inline const char* string_VkScopeNV(VkScopeNV input_value)
+{
+ switch ((VkScopeNV)input_value)
+ {
+ case VK_SCOPE_DEVICE_NV:
+ return "VK_SCOPE_DEVICE_NV";
+ case VK_SCOPE_QUEUE_FAMILY_NV:
+ return "VK_SCOPE_QUEUE_FAMILY_NV";
+ case VK_SCOPE_SUBGROUP_NV:
+ return "VK_SCOPE_SUBGROUP_NV";
+ case VK_SCOPE_WORKGROUP_NV:
+ return "VK_SCOPE_WORKGROUP_NV";
+ default:
+ return "Unhandled VkScopeNV";
+ }
+}
+
+static inline const char* string_VkCoverageReductionModeNV(VkCoverageReductionModeNV input_value)
+{
+ switch ((VkCoverageReductionModeNV)input_value)
+ {
+ case VK_COVERAGE_REDUCTION_MODE_MERGE_NV:
+ return "VK_COVERAGE_REDUCTION_MODE_MERGE_NV";
+ case VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV:
+ return "VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV";
+ default:
+ return "Unhandled VkCoverageReductionModeNV";
+ }
+}
+
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+static inline const char* string_VkFullScreenExclusiveEXT(VkFullScreenExclusiveEXT input_value)
+{
+ switch ((VkFullScreenExclusiveEXT)input_value)
+ {
+ case VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT:
+ return "VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT";
+ case VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT:
+ return "VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT";
+ case VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT:
+ return "VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT";
+ case VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT:
+ return "VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT";
+ default:
+ return "Unhandled VkFullScreenExclusiveEXT";
+ }
+}
+#endif // VK_USE_PLATFORM_WIN32_KHR
+
+static inline const char* string_VkLineRasterizationModeEXT(VkLineRasterizationModeEXT input_value)
+{
+ switch ((VkLineRasterizationModeEXT)input_value)
+ {
+ case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT:
+ return "VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT";
+ case VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT:
+ return "VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT";
+ case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT:
+ return "VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT";
+ case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT:
+ return "VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT";
+ default:
+ return "Unhandled VkLineRasterizationModeEXT";
+ }
+}
+
+static inline const char * GetPhysDevFeatureString(uint32_t index) {
+ const char * IndexToPhysDevFeatureString[] = {
+ "robustBufferAccess",
+ "fullDrawIndexUint32",
+ "imageCubeArray",
+ "independentBlend",
+ "geometryShader",
+ "tessellationShader",
+ "sampleRateShading",
+ "dualSrcBlend",
+ "logicOp",
+ "multiDrawIndirect",
+ "drawIndirectFirstInstance",
+ "depthClamp",
+ "depthBiasClamp",
+ "fillModeNonSolid",
+ "depthBounds",
+ "wideLines",
+ "largePoints",
+ "alphaToOne",
+ "multiViewport",
+ "samplerAnisotropy",
+ "textureCompressionETC2",
+ "textureCompressionASTC_LDR",
+ "textureCompressionBC",
+ "occlusionQueryPrecise",
+ "pipelineStatisticsQuery",
+ "vertexPipelineStoresAndAtomics",
+ "fragmentStoresAndAtomics",
+ "shaderTessellationAndGeometryPointSize",
+ "shaderImageGatherExtended",
+ "shaderStorageImageExtendedFormats",
+ "shaderStorageImageMultisample",
+ "shaderStorageImageReadWithoutFormat",
+ "shaderStorageImageWriteWithoutFormat",
+ "shaderUniformBufferArrayDynamicIndexing",
+ "shaderSampledImageArrayDynamicIndexing",
+ "shaderStorageBufferArrayDynamicIndexing",
+ "shaderStorageImageArrayDynamicIndexing",
+ "shaderClipDistance",
+ "shaderCullDistance",
+ "shaderFloat64",
+ "shaderInt64",
+ "shaderInt16",
+ "shaderResourceResidency",
+ "shaderResourceMinLod",
+ "sparseBinding",
+ "sparseResidencyBuffer",
+ "sparseResidencyImage2D",
+ "sparseResidencyImage3D",
+ "sparseResidency2Samples",
+ "sparseResidency4Samples",
+ "sparseResidency8Samples",
+ "sparseResidency16Samples",
+ "sparseResidencyAliased",
+ "variableMultisampleRate",
+ "inheritedQueries",
+ };
+
+ return IndexToPhysDevFeatureString[index];
+}
diff --git a/thirdparty/vulkan/vk_mem_alloc.cpp b/thirdparty/vulkan/vk_mem_alloc.cpp
new file mode 100644
index 0000000000..529f5b5d5c
--- /dev/null
+++ b/thirdparty/vulkan/vk_mem_alloc.cpp
@@ -0,0 +1,7 @@
+#define VMA_IMPLEMENTATION
+#ifdef DEBUG_ENABLED
+#ifndef _MSC_VER
+#define _DEBUG
+#endif
+#endif
+#include "vk_mem_alloc.h"
diff --git a/thirdparty/vulkan/vk_mem_alloc.h b/thirdparty/vulkan/vk_mem_alloc.h
new file mode 100644
index 0000000000..0dfb66efc6
--- /dev/null
+++ b/thirdparty/vulkan/vk_mem_alloc.h
@@ -0,0 +1,17764 @@
+//
+// Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#ifndef AMD_VULKAN_MEMORY_ALLOCATOR_H
+#define AMD_VULKAN_MEMORY_ALLOCATOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \mainpage Vulkan Memory Allocator
+
+<b>Version 2.3.0</b> (2019-12-04)
+
+Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved. \n
+License: MIT
+
+Documentation of all members: vk_mem_alloc.h
+
+\section main_table_of_contents Table of contents
+
+- <b>User guide</b>
+ - \subpage quick_start
+ - [Project setup](@ref quick_start_project_setup)
+ - [Initialization](@ref quick_start_initialization)
+ - [Resource allocation](@ref quick_start_resource_allocation)
+ - \subpage choosing_memory_type
+ - [Usage](@ref choosing_memory_type_usage)
+ - [Required and preferred flags](@ref choosing_memory_type_required_preferred_flags)
+ - [Explicit memory types](@ref choosing_memory_type_explicit_memory_types)
+ - [Custom memory pools](@ref choosing_memory_type_custom_memory_pools)
+ - [Dedicated allocations](@ref choosing_memory_type_dedicated_allocations)
+ - \subpage memory_mapping
+ - [Mapping functions](@ref memory_mapping_mapping_functions)
+ - [Persistently mapped memory](@ref memory_mapping_persistently_mapped_memory)
+ - [Cache flush and invalidate](@ref memory_mapping_cache_control)
+ - [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable)
+ - \subpage staying_within_budget
+ - [Querying for budget](@ref staying_within_budget_querying_for_budget)
+ - [Controlling memory usage](@ref staying_within_budget_controlling_memory_usage)
+ - \subpage custom_memory_pools
+ - [Choosing memory type index](@ref custom_memory_pools_MemTypeIndex)
+ - [Linear allocation algorithm](@ref linear_algorithm)
+ - [Free-at-once](@ref linear_algorithm_free_at_once)
+ - [Stack](@ref linear_algorithm_stack)
+ - [Double stack](@ref linear_algorithm_double_stack)
+ - [Ring buffer](@ref linear_algorithm_ring_buffer)
+ - [Buddy allocation algorithm](@ref buddy_algorithm)
+ - \subpage defragmentation
+ - [Defragmenting CPU memory](@ref defragmentation_cpu)
+ - [Defragmenting GPU memory](@ref defragmentation_gpu)
+ - [Additional notes](@ref defragmentation_additional_notes)
+ - [Writing custom allocation algorithm](@ref defragmentation_custom_algorithm)
+ - \subpage lost_allocations
+ - \subpage statistics
+ - [Numeric statistics](@ref statistics_numeric_statistics)
+ - [JSON dump](@ref statistics_json_dump)
+ - \subpage allocation_annotation
+ - [Allocation user data](@ref allocation_user_data)
+ - [Allocation names](@ref allocation_names)
+ - \subpage debugging_memory_usage
+ - [Memory initialization](@ref debugging_memory_usage_initialization)
+ - [Margins](@ref debugging_memory_usage_margins)
+ - [Corruption detection](@ref debugging_memory_usage_corruption_detection)
+ - \subpage record_and_replay
+- \subpage usage_patterns
+ - [Common mistakes](@ref usage_patterns_common_mistakes)
+ - [Simple patterns](@ref usage_patterns_simple)
+ - [Advanced patterns](@ref usage_patterns_advanced)
+- \subpage configuration
+ - [Pointers to Vulkan functions](@ref config_Vulkan_functions)
+ - [Custom host memory allocator](@ref custom_memory_allocator)
+ - [Device memory allocation callbacks](@ref allocation_callbacks)
+ - [Device heap memory limit](@ref heap_memory_limit)
+ - \subpage vk_khr_dedicated_allocation
+- \subpage general_considerations
+ - [Thread safety](@ref general_considerations_thread_safety)
+ - [Validation layer warnings](@ref general_considerations_validation_layer_warnings)
+ - [Allocation algorithm](@ref general_considerations_allocation_algorithm)
+ - [Features not supported](@ref general_considerations_features_not_supported)
+
+\section main_see_also See also
+
+- [Product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/)
+- [Source repository on GitHub](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
+
+
+
+
+\page quick_start Quick start
+
+\section quick_start_project_setup Project setup
+
+Vulkan Memory Allocator comes in form of a "stb-style" single header file.
+You don't need to build it as a separate library project.
+You can add this file directly to your project and submit it to code repository next to your other source files.
+
+"Single header" doesn't mean that everything is contained in C/C++ declarations,
+like it tends to be in case of inline functions or C++ templates.
+It means that implementation is bundled with interface in a single file and needs to be extracted using preprocessor macro.
+If you don't do it properly, you will get linker errors.
+
+To do it properly:
+
+-# Include "vk_mem_alloc.h" file in each CPP file where you want to use the library.
+ This includes declarations of all members of the library.
+-# In exacly one CPP file define following macro before this include.
+ It enables also internal definitions.
+
+\code
+#define VMA_IMPLEMENTATION
+#include "vk_mem_alloc.h"
+\endcode
+
+It may be a good idea to create dedicated CPP file just for this purpose.
+
+Note on language: This library is written in C++, but has C-compatible interface.
+Thus you can include and use vk_mem_alloc.h in C or C++ code, but full
+implementation with `VMA_IMPLEMENTATION` macro must be compiled as C++, NOT as C.
+
+Please note that this library includes header `<vulkan/vulkan.h>`, which in turn
+includes `<windows.h>` on Windows. If you need some specific macros defined
+before including these headers (like `WIN32_LEAN_AND_MEAN` or
+`WINVER` for Windows, `VK_USE_PLATFORM_WIN32_KHR` for Vulkan), you must define
+them before every `#include` of this library.
+
+
+\section quick_start_initialization Initialization
+
+At program startup:
+
+-# Initialize Vulkan to have `VkPhysicalDevice` and `VkDevice` object.
+-# Fill VmaAllocatorCreateInfo structure and create #VmaAllocator object by
+ calling vmaCreateAllocator().
+
+\code
+VmaAllocatorCreateInfo allocatorInfo = {};
+allocatorInfo.physicalDevice = physicalDevice;
+allocatorInfo.device = device;
+
+VmaAllocator allocator;
+vmaCreateAllocator(&allocatorInfo, &allocator);
+\endcode
+
+\section quick_start_resource_allocation Resource allocation
+
+When you want to create a buffer or image:
+
+-# Fill `VkBufferCreateInfo` / `VkImageCreateInfo` structure.
+-# Fill VmaAllocationCreateInfo structure.
+-# Call vmaCreateBuffer() / vmaCreateImage() to get `VkBuffer`/`VkImage` with memory
+ already allocated and bound to it.
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufferInfo.size = 65536;
+bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+Don't forget to destroy your objects when no longer needed:
+
+\code
+vmaDestroyBuffer(allocator, buffer, allocation);
+vmaDestroyAllocator(allocator);
+\endcode
+
+
+\page choosing_memory_type Choosing memory type
+
+Physical devices in Vulkan support various combinations of memory heaps and
+types. Help with choosing correct and optimal memory type for your specific
+resource is one of the key features of this library. You can use it by filling
+appropriate members of VmaAllocationCreateInfo structure, as described below.
+You can also combine multiple methods.
+
+-# If you just want to find memory type index that meets your requirements, you
+ can use function: vmaFindMemoryTypeIndex(), vmaFindMemoryTypeIndexForBufferInfo(),
+ vmaFindMemoryTypeIndexForImageInfo().
+-# If you want to allocate a region of device memory without association with any
+ specific image or buffer, you can use function vmaAllocateMemory(). Usage of
+ this function is not recommended and usually not needed.
+ vmaAllocateMemoryPages() function is also provided for creating multiple allocations at once,
+ which may be useful for sparse binding.
+-# If you already have a buffer or an image created, you want to allocate memory
+ for it and then you will bind it yourself, you can use function
+ vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage().
+ For binding you should use functions: vmaBindBufferMemory(), vmaBindImageMemory()
+ or their extended versions: vmaBindBufferMemory2(), vmaBindImageMemory2().
+-# If you want to create a buffer or an image, allocate memory for it and bind
+ them together, all in one call, you can use function vmaCreateBuffer(),
+ vmaCreateImage(). This is the easiest and recommended way to use this library.
+
+When using 3. or 4., the library internally queries Vulkan for memory types
+supported for that buffer or image (function `vkGetBufferMemoryRequirements()`)
+and uses only one of these types.
+
+If no memory type can be found that meets all the requirements, these functions
+return `VK_ERROR_FEATURE_NOT_PRESENT`.
+
+You can leave VmaAllocationCreateInfo structure completely filled with zeros.
+It means no requirements are specified for memory type.
+It is valid, although not very useful.
+
+\section choosing_memory_type_usage Usage
+
+The easiest way to specify memory requirements is to fill member
+VmaAllocationCreateInfo::usage using one of the values of enum #VmaMemoryUsage.
+It defines high level, common usage types.
+For more details, see description of this enum.
+
+For example, if you want to create a uniform buffer that will be filled using
+transfer only once or infrequently and used for rendering every frame, you can
+do it using following code:
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufferInfo.size = 65536;
+bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+\section choosing_memory_type_required_preferred_flags Required and preferred flags
+
+You can specify more detailed requirements by filling members
+VmaAllocationCreateInfo::requiredFlags and VmaAllocationCreateInfo::preferredFlags
+with a combination of bits from enum `VkMemoryPropertyFlags`. For example,
+if you want to create a buffer that will be persistently mapped on host (so it
+must be `HOST_VISIBLE`) and preferably will also be `HOST_COHERENT` and `HOST_CACHED`,
+use following code:
+
+\code
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+allocInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+A memory type is chosen that has all the required flags and as many preferred
+flags set as possible.
+
+If you use VmaAllocationCreateInfo::usage, it is just internally converted to
+a set of required and preferred flags.
+
+\section choosing_memory_type_explicit_memory_types Explicit memory types
+
+If you inspected memory types available on the physical device and you have
+a preference for memory types that you want to use, you can fill member
+VmaAllocationCreateInfo::memoryTypeBits. It is a bit mask, where each bit set
+means that a memory type with that index is allowed to be used for the
+allocation. Special value 0, just like `UINT32_MAX`, means there are no
+restrictions to memory type index.
+
+Please note that this member is NOT just a memory type index.
+Still you can use it to choose just one, specific memory type.
+For example, if you already determined that your buffer should be created in
+memory type 2, use following code:
+
+\code
+uint32_t memoryTypeIndex = 2;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.memoryTypeBits = 1u << memoryTypeIndex;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+\section choosing_memory_type_custom_memory_pools Custom memory pools
+
+If you allocate from custom memory pool, all the ways of specifying memory
+requirements described above are not applicable and the aforementioned members
+of VmaAllocationCreateInfo structure are ignored. Memory type is selected
+explicitly when creating the pool and then used to make all the allocations from
+that pool. For further details, see \ref custom_memory_pools.
+
+\section choosing_memory_type_dedicated_allocations Dedicated allocations
+
+Memory for allocations is reserved out of larger block of `VkDeviceMemory`
+allocated from Vulkan internally. That's the main feature of this whole library.
+You can still request a separate memory block to be created for an allocation,
+just like you would do in a trivial solution without using any allocator.
+In that case, a buffer or image is always bound to that memory at offset 0.
+This is called a "dedicated allocation".
+You can explicitly request it by using flag #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+The library can also internally decide to use dedicated allocation in some cases, e.g.:
+
+- When the size of the allocation is large.
+- When [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension is enabled
+ and it reports that dedicated allocation is required or recommended for the resource.
+- When allocation of next big memory block fails due to not enough device memory,
+ but allocation with the exact requested size succeeds.
+
+
+\page memory_mapping Memory mapping
+
+To "map memory" in Vulkan means to obtain a CPU pointer to `VkDeviceMemory`,
+to be able to read from it or write to it in CPU code.
+Mapping is possible only of memory allocated from a memory type that has
+`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag.
+Functions `vkMapMemory()`, `vkUnmapMemory()` are designed for this purpose.
+You can use them directly with memory allocated by this library,
+but it is not recommended because of following issue:
+Mapping the same `VkDeviceMemory` block multiple times is illegal - only one mapping at a time is allowed.
+This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan.
+Because of this, Vulkan Memory Allocator provides following facilities:
+
+\section memory_mapping_mapping_functions Mapping functions
+
+The library provides following functions for mapping of a specific #VmaAllocation: vmaMapMemory(), vmaUnmapMemory().
+They are safer and more convenient to use than standard Vulkan functions.
+You can map an allocation multiple times simultaneously - mapping is reference-counted internally.
+You can also map different allocations simultaneously regardless of whether they use the same `VkDeviceMemory` block.
+The way it's implemented is that the library always maps entire memory block, not just region of the allocation.
+For further details, see description of vmaMapMemory() function.
+Example:
+
+\code
+// Having these objects initialized:
+
+struct ConstantBuffer
+{
+ ...
+};
+ConstantBuffer constantBufferData;
+
+VmaAllocator allocator;
+VkBuffer constantBuffer;
+VmaAllocation constantBufferAllocation;
+
+// You can map and fill your buffer using following code:
+
+void* mappedData;
+vmaMapMemory(allocator, constantBufferAllocation, &mappedData);
+memcpy(mappedData, &constantBufferData, sizeof(constantBufferData));
+vmaUnmapMemory(allocator, constantBufferAllocation);
+\endcode
+
+When mapping, you may see a warning from Vulkan validation layer similar to this one:
+
+<i>Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.</i>
+
+It happens because the library maps entire `VkDeviceMemory` block, where different
+types of images and buffers may end up together, especially on GPUs with unified memory like Intel.
+You can safely ignore it if you are sure you access only memory of the intended
+object that you wanted to map.
+
+
+\section memory_mapping_persistently_mapped_memory Persistently mapped memory
+
+Kepping your memory persistently mapped is generally OK in Vulkan.
+You don't need to unmap it before using its data on the GPU.
+The library provides a special feature designed for that:
+Allocations made with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag set in
+VmaAllocationCreateInfo::flags stay mapped all the time,
+so you can just access CPU pointer to it any time
+without a need to call any "map" or "unmap" function.
+Example:
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = sizeof(ConstantBuffer);
+bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+// Buffer is already mapped. You can access its memory.
+memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
+\endcode
+
+There are some exceptions though, when you should consider mapping memory only for a short period of time:
+
+- When operating system is Windows 7 or 8.x (Windows 10 is not affected because it uses WDDM2),
+ device is discrete AMD GPU,
+ and memory type is the special 256 MiB pool of `DEVICE_LOCAL + HOST_VISIBLE` memory
+ (selected when you use #VMA_MEMORY_USAGE_CPU_TO_GPU),
+ then whenever a memory block allocated from this memory type stays mapped
+ for the time of any call to `vkQueueSubmit()` or `vkQueuePresentKHR()`, this
+ block is migrated by WDDM to system RAM, which degrades performance. It doesn't
+ matter if that particular memory block is actually used by the command buffer
+ being submitted.
+- On Mac/MoltenVK there is a known bug - [Issue #175](https://github.com/KhronosGroup/MoltenVK/issues/175)
+ which requires unmapping before GPU can see updated texture.
+- Keeping many large memory blocks mapped may impact performance or stability of some debugging tools.
+
+\section memory_mapping_cache_control Cache flush and invalidate
+
+Memory in Vulkan doesn't need to be unmapped before using it on GPU,
+but unless a memory types has `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag set,
+you need to manually **invalidate** cache before reading of mapped pointer
+and **flush** cache after writing to mapped pointer.
+Map/unmap operations don't do that automatically.
+Vulkan provides following functions for this purpose `vkFlushMappedMemoryRanges()`,
+`vkInvalidateMappedMemoryRanges()`, but this library provides more convenient
+functions that refer to given allocation object: vmaFlushAllocation(),
+vmaInvalidateAllocation().
+
+Regions of memory specified for flush/invalidate must be aligned to
+`VkPhysicalDeviceLimits::nonCoherentAtomSize`. This is automatically ensured by the library.
+In any memory type that is `HOST_VISIBLE` but not `HOST_COHERENT`, all allocations
+within blocks are aligned to this value, so their offsets are always multiply of
+`nonCoherentAtomSize` and two different allocations never share same "line" of this size.
+
+Please note that memory allocated with #VMA_MEMORY_USAGE_CPU_ONLY is guaranteed to be `HOST_COHERENT`.
+
+Also, Windows drivers from all 3 **PC** GPU vendors (AMD, Intel, NVIDIA)
+currently provide `HOST_COHERENT` flag on all memory types that are
+`HOST_VISIBLE`, so on this platform you may not need to bother.
+
+\section memory_mapping_finding_if_memory_mappable Finding out if memory is mappable
+
+It may happen that your allocation ends up in memory that is `HOST_VISIBLE` (available for mapping)
+despite it wasn't explicitly requested.
+For example, application may work on integrated graphics with unified memory (like Intel) or
+allocation from video memory might have failed, so the library chose system memory as fallback.
+
+You can detect this case and map such allocation to access its memory on CPU directly,
+instead of launching a transfer operation.
+In order to do that: inspect `allocInfo.memoryType`, call vmaGetMemoryTypeProperties(),
+and look for `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag in properties of that memory type.
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = sizeof(ConstantBuffer);
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+VkMemoryPropertyFlags memFlags;
+vmaGetMemoryTypeProperties(allocator, allocInfo.memoryType, &memFlags);
+if((memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+{
+ // Allocation ended up in mappable memory. You can map it and access it directly.
+ void* mappedData;
+ vmaMapMemory(allocator, alloc, &mappedData);
+ memcpy(mappedData, &constantBufferData, sizeof(constantBufferData));
+ vmaUnmapMemory(allocator, alloc);
+}
+else
+{
+ // Allocation ended up in non-mappable memory.
+ // You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.
+}
+\endcode
+
+You can even use #VMA_ALLOCATION_CREATE_MAPPED_BIT flag while creating allocations
+that are not necessarily `HOST_VISIBLE` (e.g. using #VMA_MEMORY_USAGE_GPU_ONLY).
+If the allocation ends up in memory type that is `HOST_VISIBLE`, it will be persistently mapped and you can use it directly.
+If not, the flag is just ignored.
+Example:
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = sizeof(ConstantBuffer);
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+if(allocInfo.pUserData != nullptr)
+{
+ // Allocation ended up in mappable memory.
+ // It's persistently mapped. You can access it directly.
+ memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
+}
+else
+{
+ // Allocation ended up in non-mappable memory.
+ // You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.
+}
+\endcode
+
+
+\page staying_within_budget Staying within budget
+
+When developing a graphics-intensive game or program, it is important to avoid allocating
+more GPU memory than it's physically available. When the memory is over-committed,
+various bad things can happen, depending on the specific GPU, graphics driver, and
+operating system:
+
+- It may just work without any problems.
+- The application may slow down because some memory blocks are moved to system RAM
+ and the GPU has to access them through PCI Express bus.
+- A new allocation may take very long time to complete, even few seconds, and possibly
+ freeze entire system.
+- The new allocation may fail with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+- It may even result in GPU crash (TDR), observed as `VK_ERROR_DEVICE_LOST`
+ returned somewhere later.
+
+\section staying_within_budget_querying_for_budget Querying for budget
+
+To query for current memory usage and available budget, use function vmaGetBudget().
+Returned structure #VmaBudget contains quantities expressed in bytes, per Vulkan memory heap.
+
+Please note that this function returns different information and works faster than
+vmaCalculateStats(). vmaGetBudget() can be called every frame or even before every
+allocation, while vmaCalculateStats() is intended to be used rarely,
+only to obtain statistical information, e.g. for debugging purposes.
+
+It is recommended to use <b>VK_EXT_memory_budget</b> device extension to obtain information
+about the budget from Vulkan device. VMA is able to use this extension automatically.
+When not enabled, the allocator behaves same way, but then it estimates current usage
+and available budget based on its internal information and Vulkan memory heap sizes,
+which may be less precise. In order to use this extension:
+
+1. Make sure extensions VK_EXT_memory_budget and VK_KHR_get_physical_device_properties2
+ required by it are available and enable them. Please note that the first is a device
+ extension and the second is instance extension!
+2. Use flag #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT when creating #VmaAllocator object.
+3. Make sure to call vmaSetCurrentFrameIndex() every frame. Budget is queried from
+ Vulkan inside of it to avoid overhead of querying it with every allocation.
+
+\section staying_within_budget_controlling_memory_usage Controlling memory usage
+
+There are many ways in which you can try to stay within the budget.
+
+First, when making new allocation requires allocating a new memory block, the library
+tries not to exceed the budget automatically. If a block with default recommended size
+(e.g. 256 MB) would go over budget, a smaller block is allocated, possibly even
+dedicated memory for just this resource.
+
+If the size of the requested resource plus current memory usage is more than the
+budget, by default the library still tries to create it, leaving it to the Vulkan
+implementation whether the allocation succeeds or fails. You can change this behavior
+by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is
+not made if it would exceed the budget or if the budget is already exceeded.
+Some other allocations become lost instead to make room for it, if the mechanism of
+[lost allocations](@ref lost_allocations) is used.
+If that is not possible, the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag
+when creating resources that are not essential for the application (e.g. the texture
+of a specific object) and not to pass it when creating critically important resources
+(e.g. render targets).
+
+Finally, you can also use #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT flag to make sure
+a new allocation is created only when it fits inside one of the existing memory blocks.
+If it would require to allocate a new block, if fails instead with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+This also ensures that the function call is very fast because it never goes to Vulkan
+to obtain a new block.
+
+Please note that creating \ref custom_memory_pools with VmaPoolCreateInfo::minBlockCount
+set to more than 0 will try to allocate memory blocks without checking whether they
+fit within budget.
+
+
+\page custom_memory_pools Custom memory pools
+
+A memory pool contains a number of `VkDeviceMemory` blocks.
+The library automatically creates and manages default pool for each memory type available on the device.
+Default memory pool automatically grows in size.
+Size of allocated blocks is also variable and managed automatically.
+
+You can create custom pool and allocate memory out of it.
+It can be useful if you want to:
+
+- Keep certain kind of allocations separate from others.
+- Enforce particular, fixed size of Vulkan memory blocks.
+- Limit maximum amount of Vulkan memory allocated for that pool.
+- Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool.
+
+To use custom memory pools:
+
+-# Fill VmaPoolCreateInfo structure.
+-# Call vmaCreatePool() to obtain #VmaPool handle.
+-# When making an allocation, set VmaAllocationCreateInfo::pool to this handle.
+ You don't need to specify any other parameters of this structure, like `usage`.
+
+Example:
+
+\code
+// Create a pool that can have at most 2 blocks, 128 MiB each.
+VmaPoolCreateInfo poolCreateInfo = {};
+poolCreateInfo.memoryTypeIndex = ...
+poolCreateInfo.blockSize = 128ull * 1024 * 1024;
+poolCreateInfo.maxBlockCount = 2;
+
+VmaPool pool;
+vmaCreatePool(allocator, &poolCreateInfo, &pool);
+
+// Allocate a buffer out of it.
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = 1024;
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.pool = pool;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+\endcode
+
+You have to free all allocations made from this pool before destroying it.
+
+\code
+vmaDestroyBuffer(allocator, buf, alloc);
+vmaDestroyPool(allocator, pool);
+\endcode
+
+\section custom_memory_pools_MemTypeIndex Choosing memory type index
+
+When creating a pool, you must explicitly specify memory type index.
+To find the one suitable for your buffers or images, you can use helper functions
+vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo().
+You need to provide structures with example parameters of buffers or images
+that you are going to create in that pool.
+
+\code
+VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+exampleBufCreateInfo.size = 1024; // Whatever.
+exampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; // Change if needed.
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; // Change if needed.
+
+uint32_t memTypeIndex;
+vmaFindMemoryTypeIndexForBufferInfo(allocator, &exampleBufCreateInfo, &allocCreateInfo, &memTypeIndex);
+
+VmaPoolCreateInfo poolCreateInfo = {};
+poolCreateInfo.memoryTypeIndex = memTypeIndex;
+// ...
+\endcode
+
+When creating buffers/images allocated in that pool, provide following parameters:
+
+- `VkBufferCreateInfo`: Prefer to pass same parameters as above.
+ Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior.
+ Using different `VK_BUFFER_USAGE_` flags may work, but you shouldn't create images in a pool intended for buffers
+ or the other way around.
+- VmaAllocationCreateInfo: You don't need to pass same parameters. Fill only `pool` member.
+ Other members are ignored anyway.
+
+\section linear_algorithm Linear allocation algorithm
+
+Each Vulkan memory block managed by this library has accompanying metadata that
+keeps track of used and unused regions. By default, the metadata structure and
+algorithm tries to find best place for new allocations among free regions to
+optimize memory usage. This way you can allocate and free objects in any order.
+
+![Default allocation algorithm](../gfx/Linear_allocator_1_algo_default.png)
+
+Sometimes there is a need to use simpler, linear allocation algorithm. You can
+create custom pool that uses such algorithm by adding flag
+#VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating
+#VmaPool object. Then an alternative metadata management is used. It always
+creates new allocations after last one and doesn't reuse free regions after
+allocations freed in the middle. It results in better allocation performance and
+less memory consumed by metadata.
+
+![Linear allocation algorithm](../gfx/Linear_allocator_2_algo_linear.png)
+
+With this one flag, you can create a custom pool that can be used in many ways:
+free-at-once, stack, double stack, and ring buffer. See below for details.
+
+\subsection linear_algorithm_free_at_once Free-at-once
+
+In a pool that uses linear algorithm, you still need to free all the allocations
+individually, e.g. by using vmaFreeMemory() or vmaDestroyBuffer(). You can free
+them in any order. New allocations are always made after last one - free space
+in the middle is not reused. However, when you release all the allocation and
+the pool becomes empty, allocation starts from the beginning again. This way you
+can use linear algorithm to speed up creation of allocations that you are going
+to release all at once.
+
+![Free-at-once](../gfx/Linear_allocator_3_free_at_once.png)
+
+This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount
+value that allows multiple memory blocks.
+
+\subsection linear_algorithm_stack Stack
+
+When you free an allocation that was created last, its space can be reused.
+Thanks to this, if you always release allocations in the order opposite to their
+creation (LIFO - Last In First Out), you can achieve behavior of a stack.
+
+![Stack](../gfx/Linear_allocator_4_stack.png)
+
+This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount
+value that allows multiple memory blocks.
+
+\subsection linear_algorithm_double_stack Double stack
+
+The space reserved by a custom pool with linear algorithm may be used by two
+stacks:
+
+- First, default one, growing up from offset 0.
+- Second, "upper" one, growing down from the end towards lower offsets.
+
+To make allocation from upper stack, add flag #VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT
+to VmaAllocationCreateInfo::flags.
+
+![Double stack](../gfx/Linear_allocator_7_double_stack.png)
+
+Double stack is available only in pools with one memory block -
+VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.
+
+When the two stacks' ends meet so there is not enough space between them for a
+new allocation, such allocation fails with usual
+`VK_ERROR_OUT_OF_DEVICE_MEMORY` error.
+
+\subsection linear_algorithm_ring_buffer Ring buffer
+
+When you free some allocations from the beginning and there is not enough free space
+for a new one at the end of a pool, allocator's "cursor" wraps around to the
+beginning and starts allocation there. Thanks to this, if you always release
+allocations in the same order as you created them (FIFO - First In First Out),
+you can achieve behavior of a ring buffer / queue.
+
+![Ring buffer](../gfx/Linear_allocator_5_ring_buffer.png)
+
+Pools with linear algorithm support [lost allocations](@ref lost_allocations) when used as ring buffer.
+If there is not enough free space for a new allocation, but existing allocations
+from the front of the queue can become lost, they become lost and the allocation
+succeeds.
+
+![Ring buffer with lost allocations](../gfx/Linear_allocator_6_ring_buffer_lost.png)
+
+Ring buffer is available only in pools with one memory block -
+VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.
+
+\section buddy_algorithm Buddy allocation algorithm
+
+There is another allocation algorithm that can be used with custom pools, called
+"buddy". Its internal data structure is based on a tree of blocks, each having
+size that is a power of two and a half of its parent's size. When you want to
+allocate memory of certain size, a free node in the tree is located. If it's too
+large, it is recursively split into two halves (called "buddies"). However, if
+requested allocation size is not a power of two, the size of a tree node is
+aligned up to the nearest power of two and the remaining space is wasted. When
+two buddy nodes become free, they are merged back into one larger node.
+
+![Buddy allocator](../gfx/Buddy_allocator.png)
+
+The advantage of buddy allocation algorithm over default algorithm is faster
+allocation and deallocation, as well as smaller external fragmentation. The
+disadvantage is more wasted space (internal fragmentation).
+
+For more information, please read ["Buddy memory allocation" on Wikipedia](https://en.wikipedia.org/wiki/Buddy_memory_allocation)
+or other sources that describe this concept in general.
+
+To use buddy allocation algorithm with a custom pool, add flag
+#VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating
+#VmaPool object.
+
+Several limitations apply to pools that use buddy algorithm:
+
+- It is recommended to use VmaPoolCreateInfo::blockSize that is a power of two.
+ Otherwise, only largest power of two smaller than the size is used for
+ allocations. The remaining space always stays unused.
+- [Margins](@ref debugging_memory_usage_margins) and
+ [corruption detection](@ref debugging_memory_usage_corruption_detection)
+ don't work in such pools.
+- [Lost allocations](@ref lost_allocations) don't work in such pools. You can
+ use them, but they never become lost. Support may be added in the future.
+- [Defragmentation](@ref defragmentation) doesn't work with allocations made from
+ such pool.
+
+\page defragmentation Defragmentation
+
+Interleaved allocations and deallocations of many objects of varying size can
+cause fragmentation over time, which can lead to a situation where the library is unable
+to find a continuous range of free memory for a new allocation despite there is
+enough free space, just scattered across many small free ranges between existing
+allocations.
+
+To mitigate this problem, you can use defragmentation feature:
+structure #VmaDefragmentationInfo2, function vmaDefragmentationBegin(), vmaDefragmentationEnd().
+Given set of allocations,
+this function can move them to compact used memory, ensure more continuous free
+space and possibly also free some `VkDeviceMemory` blocks.
+
+What the defragmentation does is:
+
+- Updates #VmaAllocation objects to point to new `VkDeviceMemory` and offset.
+ After allocation has been moved, its VmaAllocationInfo::deviceMemory and/or
+ VmaAllocationInfo::offset changes. You must query them again using
+ vmaGetAllocationInfo() if you need them.
+- Moves actual data in memory.
+
+What it doesn't do, so you need to do it yourself:
+
+- Recreate buffers and images that were bound to allocations that were defragmented and
+ bind them with their new places in memory.
+ You must use `vkDestroyBuffer()`, `vkDestroyImage()`,
+ `vkCreateBuffer()`, `vkCreateImage()`, vmaBindBufferMemory(), vmaBindImageMemory()
+ for that purpose and NOT vmaDestroyBuffer(),
+ vmaDestroyImage(), vmaCreateBuffer(), vmaCreateImage(), because you don't need to
+ destroy or create allocation objects!
+- Recreate views and update descriptors that point to these buffers and images.
+
+\section defragmentation_cpu Defragmenting CPU memory
+
+Following example demonstrates how you can run defragmentation on CPU.
+Only allocations created in memory types that are `HOST_VISIBLE` can be defragmented.
+Others are ignored.
+
+The way it works is:
+
+- It temporarily maps entire memory blocks when necessary.
+- It moves data using `memmove()` function.
+
+\code
+// Given following variables already initialized:
+VkDevice device;
+VmaAllocator allocator;
+std::vector<VkBuffer> buffers;
+std::vector<VmaAllocation> allocations;
+
+
+const uint32_t allocCount = (uint32_t)allocations.size();
+std::vector<VkBool32> allocationsChanged(allocCount);
+
+VmaDefragmentationInfo2 defragInfo = {};
+defragInfo.allocationCount = allocCount;
+defragInfo.pAllocations = allocations.data();
+defragInfo.pAllocationsChanged = allocationsChanged.data();
+defragInfo.maxCpuBytesToMove = VK_WHOLE_SIZE; // No limit.
+defragInfo.maxCpuAllocationsToMove = UINT32_MAX; // No limit.
+
+VmaDefragmentationContext defragCtx;
+vmaDefragmentationBegin(allocator, &defragInfo, nullptr, &defragCtx);
+vmaDefragmentationEnd(allocator, defragCtx);
+
+for(uint32_t i = 0; i < allocCount; ++i)
+{
+ if(allocationsChanged[i])
+ {
+ // Destroy buffer that is immutably bound to memory region which is no longer valid.
+ vkDestroyBuffer(device, buffers[i], nullptr);
+
+ // Create new buffer with same parameters.
+ VkBufferCreateInfo bufferInfo = ...;
+ vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]);
+
+ // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.
+
+ // Bind new buffer to new memory region. Data contained in it is already moved.
+ VmaAllocationInfo allocInfo;
+ vmaGetAllocationInfo(allocator, allocations[i], &allocInfo);
+ vmaBindBufferMemory(allocator, allocations[i], buffers[i]);
+ }
+}
+\endcode
+
+Setting VmaDefragmentationInfo2::pAllocationsChanged is optional.
+This output array tells whether particular allocation in VmaDefragmentationInfo2::pAllocations at the same index
+has been modified during defragmentation.
+You can pass null, but you then need to query every allocation passed to defragmentation
+for new parameters using vmaGetAllocationInfo() if you might need to recreate and rebind a buffer or image associated with it.
+
+If you use [Custom memory pools](@ref choosing_memory_type_custom_memory_pools),
+you can fill VmaDefragmentationInfo2::poolCount and VmaDefragmentationInfo2::pPools
+instead of VmaDefragmentationInfo2::allocationCount and VmaDefragmentationInfo2::pAllocations
+to defragment all allocations in given pools.
+You cannot use VmaDefragmentationInfo2::pAllocationsChanged in that case.
+You can also combine both methods.
+
+\section defragmentation_gpu Defragmenting GPU memory
+
+It is also possible to defragment allocations created in memory types that are not `HOST_VISIBLE`.
+To do that, you need to pass a command buffer that meets requirements as described in
+VmaDefragmentationInfo2::commandBuffer. The way it works is:
+
+- It creates temporary buffers and binds them to entire memory blocks when necessary.
+- It issues `vkCmdCopyBuffer()` to passed command buffer.
+
+Example:
+
+\code
+// Given following variables already initialized:
+VkDevice device;
+VmaAllocator allocator;
+VkCommandBuffer commandBuffer;
+std::vector<VkBuffer> buffers;
+std::vector<VmaAllocation> allocations;
+
+
+const uint32_t allocCount = (uint32_t)allocations.size();
+std::vector<VkBool32> allocationsChanged(allocCount);
+
+VkCommandBufferBeginInfo cmdBufBeginInfo = ...;
+vkBeginCommandBuffer(commandBuffer, &cmdBufBeginInfo);
+
+VmaDefragmentationInfo2 defragInfo = {};
+defragInfo.allocationCount = allocCount;
+defragInfo.pAllocations = allocations.data();
+defragInfo.pAllocationsChanged = allocationsChanged.data();
+defragInfo.maxGpuBytesToMove = VK_WHOLE_SIZE; // Notice it's "GPU" this time.
+defragInfo.maxGpuAllocationsToMove = UINT32_MAX; // Notice it's "GPU" this time.
+defragInfo.commandBuffer = commandBuffer;
+
+VmaDefragmentationContext defragCtx;
+vmaDefragmentationBegin(allocator, &defragInfo, nullptr, &defragCtx);
+
+vkEndCommandBuffer(commandBuffer);
+
+// Submit commandBuffer.
+// Wait for a fence that ensures commandBuffer execution finished.
+
+vmaDefragmentationEnd(allocator, defragCtx);
+
+for(uint32_t i = 0; i < allocCount; ++i)
+{
+ if(allocationsChanged[i])
+ {
+ // Destroy buffer that is immutably bound to memory region which is no longer valid.
+ vkDestroyBuffer(device, buffers[i], nullptr);
+
+ // Create new buffer with same parameters.
+ VkBufferCreateInfo bufferInfo = ...;
+ vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]);
+
+ // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.
+
+ // Bind new buffer to new memory region. Data contained in it is already moved.
+ VmaAllocationInfo allocInfo;
+ vmaGetAllocationInfo(allocator, allocations[i], &allocInfo);
+ vmaBindBufferMemory(allocator, allocations[i], buffers[i]);
+ }
+}
+\endcode
+
+You can combine these two methods by specifying non-zero `maxGpu*` as well as `maxCpu*` parameters.
+The library automatically chooses best method to defragment each memory pool.
+
+You may try not to block your entire program to wait until defragmentation finishes,
+but do it in the background, as long as you carefully fullfill requirements described
+in function vmaDefragmentationBegin().
+
+\section defragmentation_additional_notes Additional notes
+
+It is only legal to defragment allocations bound to:
+
+- buffers
+- images created with `VK_IMAGE_CREATE_ALIAS_BIT`, `VK_IMAGE_TILING_LINEAR`, and
+ being currently in `VK_IMAGE_LAYOUT_GENERAL` or `VK_IMAGE_LAYOUT_PREINITIALIZED`.
+
+Defragmentation of images created with `VK_IMAGE_TILING_OPTIMAL` or in any other
+layout may give undefined results.
+
+If you defragment allocations bound to images, new images to be bound to new
+memory region after defragmentation should be created with `VK_IMAGE_LAYOUT_PREINITIALIZED`
+and then transitioned to their original layout from before defragmentation if
+needed using an image memory barrier.
+
+While using defragmentation, you may experience validation layer warnings, which you just need to ignore.
+See [Validation layer warnings](@ref general_considerations_validation_layer_warnings).
+
+Please don't expect memory to be fully compacted after defragmentation.
+Algorithms inside are based on some heuristics that try to maximize number of Vulkan
+memory blocks to make totally empty to release them, as well as to maximimze continuous
+empty space inside remaining blocks, while minimizing the number and size of allocations that
+need to be moved. Some fragmentation may still remain - this is normal.
+
+\section defragmentation_custom_algorithm Writing custom defragmentation algorithm
+
+If you want to implement your own, custom defragmentation algorithm,
+there is infrastructure prepared for that,
+but it is not exposed through the library API - you need to hack its source code.
+Here are steps needed to do this:
+
+-# Main thing you need to do is to define your own class derived from base abstract
+ class `VmaDefragmentationAlgorithm` and implement your version of its pure virtual methods.
+ See definition and comments of this class for details.
+-# Your code needs to interact with device memory block metadata.
+ If you need more access to its data than it's provided by its public interface,
+ declare your new class as a friend class e.g. in class `VmaBlockMetadata_Generic`.
+-# If you want to create a flag that would enable your algorithm or pass some additional
+ flags to configure it, add them to `VmaDefragmentationFlagBits` and use them in
+ VmaDefragmentationInfo2::flags.
+-# Modify function `VmaBlockVectorDefragmentationContext::Begin` to create object
+ of your new class whenever needed.
+
+
+\page lost_allocations Lost allocations
+
+If your game oversubscribes video memory, if may work OK in previous-generation
+graphics APIs (DirectX 9, 10, 11, OpenGL) because resources are automatically
+paged to system RAM. In Vulkan you can't do it because when you run out of
+memory, an allocation just fails. If you have more data (e.g. textures) that can
+fit into VRAM and you don't need it all at once, you may want to upload them to
+GPU on demand and "push out" ones that are not used for a long time to make room
+for the new ones, effectively using VRAM (or a cartain memory pool) as a form of
+cache. Vulkan Memory Allocator can help you with that by supporting a concept of
+"lost allocations".
+
+To create an allocation that can become lost, include #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT
+flag in VmaAllocationCreateInfo::flags. Before using a buffer or image bound to
+such allocation in every new frame, you need to query it if it's not lost.
+To check it, call vmaTouchAllocation().
+If the allocation is lost, you should not use it or buffer/image bound to it.
+You mustn't forget to destroy this allocation and this buffer/image.
+vmaGetAllocationInfo() can also be used for checking status of the allocation.
+Allocation is lost when returned VmaAllocationInfo::deviceMemory == `VK_NULL_HANDLE`.
+
+To create an allocation that can make some other allocations lost to make room
+for it, use #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag. You will
+usually use both flags #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT and
+#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT at the same time.
+
+Warning! Current implementation uses quite naive, brute force algorithm,
+which can make allocation calls that use #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT
+flag quite slow. A new, more optimal algorithm and data structure to speed this
+up is planned for the future.
+
+<b>Q: When interleaving creation of new allocations with usage of existing ones,
+how do you make sure that an allocation won't become lost while it's used in the
+current frame?</b>
+
+It is ensured because vmaTouchAllocation() / vmaGetAllocationInfo() not only returns allocation
+status/parameters and checks whether it's not lost, but when it's not, it also
+atomically marks it as used in the current frame, which makes it impossible to
+become lost in that frame. It uses lockless algorithm, so it works fast and
+doesn't involve locking any internal mutex.
+
+<b>Q: What if my allocation may still be in use by the GPU when it's rendering a
+previous frame while I already submit new frame on the CPU?</b>
+
+You can make sure that allocations "touched" by vmaTouchAllocation() / vmaGetAllocationInfo() will not
+become lost for a number of additional frames back from the current one by
+specifying this number as VmaAllocatorCreateInfo::frameInUseCount (for default
+memory pool) and VmaPoolCreateInfo::frameInUseCount (for custom pool).
+
+<b>Q: How do you inform the library when new frame starts?</b>
+
+You need to call function vmaSetCurrentFrameIndex().
+
+Example code:
+
+\code
+struct MyBuffer
+{
+ VkBuffer m_Buf = nullptr;
+ VmaAllocation m_Alloc = nullptr;
+
+ // Called when the buffer is really needed in the current frame.
+ void EnsureBuffer();
+};
+
+void MyBuffer::EnsureBuffer()
+{
+ // Buffer has been created.
+ if(m_Buf != VK_NULL_HANDLE)
+ {
+ // Check if its allocation is not lost + mark it as used in current frame.
+ if(vmaTouchAllocation(allocator, m_Alloc))
+ {
+ // It's all OK - safe to use m_Buf.
+ return;
+ }
+ }
+
+ // Buffer not yet exists or lost - destroy and recreate it.
+
+ vmaDestroyBuffer(allocator, m_Buf, m_Alloc);
+
+ VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+ bufCreateInfo.size = 1024;
+ bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+ VmaAllocationCreateInfo allocCreateInfo = {};
+ allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+ allocCreateInfo.flags = VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT |
+ VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
+
+ vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &m_Buf, &m_Alloc, nullptr);
+}
+\endcode
+
+When using lost allocations, you may see some Vulkan validation layer warnings
+about overlapping regions of memory bound to different kinds of buffers and
+images. This is still valid as long as you implement proper handling of lost
+allocations (like in the example above) and don't use them.
+
+You can create an allocation that is already in lost state from the beginning using function
+vmaCreateLostAllocation(). It may be useful if you need a "dummy" allocation that is not null.
+
+You can call function vmaMakePoolAllocationsLost() to set all eligible allocations
+in a specified custom pool to lost state.
+Allocations that have been "touched" in current frame or VmaPoolCreateInfo::frameInUseCount frames back
+cannot become lost.
+
+<b>Q: Can I touch allocation that cannot become lost?</b>
+
+Yes, although it has no visible effect.
+Calls to vmaGetAllocationInfo() and vmaTouchAllocation() update last use frame index
+also for allocations that cannot become lost, but the only way to observe it is to dump
+internal allocator state using vmaBuildStatsString().
+You can use this feature for debugging purposes to explicitly mark allocations that you use
+in current frame and then analyze JSON dump to see for how long each allocation stays unused.
+
+
+\page statistics Statistics
+
+This library contains functions that return information about its internal state,
+especially the amount of memory allocated from Vulkan.
+Please keep in mind that these functions need to traverse all internal data structures
+to gather these information, so they may be quite time-consuming.
+Don't call them too often.
+
+\section statistics_numeric_statistics Numeric statistics
+
+You can query for overall statistics of the allocator using function vmaCalculateStats().
+Information are returned using structure #VmaStats.
+It contains #VmaStatInfo - number of allocated blocks, number of allocations
+(occupied ranges in these blocks), number of unused (free) ranges in these blocks,
+number of bytes used and unused (but still allocated from Vulkan) and other information.
+They are summed across memory heaps, memory types and total for whole allocator.
+
+You can query for statistics of a custom pool using function vmaGetPoolStats().
+Information are returned using structure #VmaPoolStats.
+
+You can query for information about specific allocation using function vmaGetAllocationInfo().
+It fill structure #VmaAllocationInfo.
+
+\section statistics_json_dump JSON dump
+
+You can dump internal state of the allocator to a string in JSON format using function vmaBuildStatsString().
+The result is guaranteed to be correct JSON.
+It uses ANSI encoding.
+Any strings provided by user (see [Allocation names](@ref allocation_names))
+are copied as-is and properly escaped for JSON, so if they use UTF-8, ISO-8859-2 or any other encoding,
+this JSON string can be treated as using this encoding.
+It must be freed using function vmaFreeStatsString().
+
+The format of this JSON string is not part of official documentation of the library,
+but it will not change in backward-incompatible way without increasing library major version number
+and appropriate mention in changelog.
+
+The JSON string contains all the data that can be obtained using vmaCalculateStats().
+It can also contain detailed map of allocated memory blocks and their regions -
+free and occupied by allocations.
+This allows e.g. to visualize the memory or assess fragmentation.
+
+
+\page allocation_annotation Allocation names and user data
+
+\section allocation_user_data Allocation user data
+
+You can annotate allocations with your own information, e.g. for debugging purposes.
+To do that, fill VmaAllocationCreateInfo::pUserData field when creating
+an allocation. It's an opaque `void*` pointer. You can use it e.g. as a pointer,
+some handle, index, key, ordinal number or any other value that would associate
+the allocation with your custom metadata.
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+// Fill bufferInfo...
+
+MyBufferMetadata* pMetadata = CreateBufferMetadata();
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.pUserData = pMetadata;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, nullptr);
+\endcode
+
+The pointer may be later retrieved as VmaAllocationInfo::pUserData:
+
+\code
+VmaAllocationInfo allocInfo;
+vmaGetAllocationInfo(allocator, allocation, &allocInfo);
+MyBufferMetadata* pMetadata = (MyBufferMetadata*)allocInfo.pUserData;
+\endcode
+
+It can also be changed using function vmaSetAllocationUserData().
+
+Values of (non-zero) allocations' `pUserData` are printed in JSON report created by
+vmaBuildStatsString(), in hexadecimal form.
+
+\section allocation_names Allocation names
+
+There is alternative mode available where `pUserData` pointer is used to point to
+a null-terminated string, giving a name to the allocation. To use this mode,
+set #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT flag in VmaAllocationCreateInfo::flags.
+Then `pUserData` passed as VmaAllocationCreateInfo::pUserData or argument to
+vmaSetAllocationUserData() must be either null or pointer to a null-terminated string.
+The library creates internal copy of the string, so the pointer you pass doesn't need
+to be valid for whole lifetime of the allocation. You can free it after the call.
+
+\code
+VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+// Fill imageInfo...
+
+std::string imageName = "Texture: ";
+imageName += fileName;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
+allocCreateInfo.pUserData = imageName.c_str();
+
+VkImage image;
+VmaAllocation allocation;
+vmaCreateImage(allocator, &imageInfo, &allocCreateInfo, &image, &allocation, nullptr);
+\endcode
+
+The value of `pUserData` pointer of the allocation will be different than the one
+you passed when setting allocation's name - pointing to a buffer managed
+internally that holds copy of the string.
+
+\code
+VmaAllocationInfo allocInfo;
+vmaGetAllocationInfo(allocator, allocation, &allocInfo);
+const char* imageName = (const char*)allocInfo.pUserData;
+printf("Image name: %s\n", imageName);
+\endcode
+
+That string is also printed in JSON report created by vmaBuildStatsString().
+
+
+\page debugging_memory_usage Debugging incorrect memory usage
+
+If you suspect a bug with memory usage, like usage of uninitialized memory or
+memory being overwritten out of bounds of an allocation,
+you can use debug features of this library to verify this.
+
+\section debugging_memory_usage_initialization Memory initialization
+
+If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used,
+you can enable automatic memory initialization to verify this.
+To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1.
+
+\code
+#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1
+#include "vk_mem_alloc.h"
+\endcode
+
+It makes memory of all new allocations initialized to bit pattern `0xDCDCDCDC`.
+Before an allocation is destroyed, its memory is filled with bit pattern `0xEFEFEFEF`.
+Memory is automatically mapped and unmapped if necessary.
+
+If you find these values while debugging your program, good chances are that you incorrectly
+read Vulkan memory that is allocated but not initialized, or already freed, respectively.
+
+Memory initialization works only with memory types that are `HOST_VISIBLE`.
+It works also with dedicated allocations.
+It doesn't work with allocations created with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
+as they cannot be mapped.
+
+\section debugging_memory_usage_margins Margins
+
+By default, allocations are laid out in memory blocks next to each other if possible
+(considering required alignment, `bufferImageGranularity`, and `nonCoherentAtomSize`).
+
+![Allocations without margin](../gfx/Margins_1.png)
+
+Define macro `VMA_DEBUG_MARGIN` to some non-zero value (e.g. 16) to enforce specified
+number of bytes as a margin before and after every allocation.
+
+\code
+#define VMA_DEBUG_MARGIN 16
+#include "vk_mem_alloc.h"
+\endcode
+
+![Allocations with margin](../gfx/Margins_2.png)
+
+If your bug goes away after enabling margins, it means it may be caused by memory
+being overwritten outside of allocation boundaries. It is not 100% certain though.
+Change in application behavior may also be caused by different order and distribution
+of allocations across memory blocks after margins are applied.
+
+The margin is applied also before first and after last allocation in a block.
+It may occur only once between two adjacent allocations.
+
+Margins work with all types of memory.
+
+Margin is applied only to allocations made out of memory blocks and not to dedicated
+allocations, which have their own memory block of specific size.
+It is thus not applied to allocations made using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag
+or those automatically decided to put into dedicated allocations, e.g. due to its
+large size or recommended by VK_KHR_dedicated_allocation extension.
+Margins are also not active in custom pools created with #VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag.
+
+Margins appear in [JSON dump](@ref statistics_json_dump) as part of free space.
+
+Note that enabling margins increases memory usage and fragmentation.
+
+\section debugging_memory_usage_corruption_detection Corruption detection
+
+You can additionally define macro `VMA_DEBUG_DETECT_CORRUPTION` to 1 to enable validation
+of contents of the margins.
+
+\code
+#define VMA_DEBUG_MARGIN 16
+#define VMA_DEBUG_DETECT_CORRUPTION 1
+#include "vk_mem_alloc.h"
+\endcode
+
+When this feature is enabled, number of bytes specified as `VMA_DEBUG_MARGIN`
+(it must be multiply of 4) before and after every allocation is filled with a magic number.
+This idea is also know as "canary".
+Memory is automatically mapped and unmapped if necessary.
+
+This number is validated automatically when the allocation is destroyed.
+If it's not equal to the expected value, `VMA_ASSERT()` is executed.
+It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation,
+which indicates a serious bug.
+
+You can also explicitly request checking margins of all allocations in all memory blocks
+that belong to specified memory types by using function vmaCheckCorruption(),
+or in memory blocks that belong to specified custom pool, by using function
+vmaCheckPoolCorruption().
+
+Margin validation (corruption detection) works only for memory types that are
+`HOST_VISIBLE` and `HOST_COHERENT`.
+
+
+\page record_and_replay Record and replay
+
+\section record_and_replay_introduction Introduction
+
+While using the library, sequence of calls to its functions together with their
+parameters can be recorded to a file and later replayed using standalone player
+application. It can be useful to:
+
+- Test correctness - check if same sequence of calls will not cause crash or
+ failures on a target platform.
+- Gather statistics - see number of allocations, peak memory usage, number of
+ calls etc.
+- Benchmark performance - see how much time it takes to replay the whole
+ sequence.
+
+\section record_and_replay_usage Usage
+
+Recording functionality is disabled by default.
+To enable it, define following macro before every include of this library:
+
+\code
+#define VMA_RECORDING_ENABLED 1
+\endcode
+
+<b>To record sequence of calls to a file:</b> Fill in
+VmaAllocatorCreateInfo::pRecordSettings member while creating #VmaAllocator
+object. File is opened and written during whole lifetime of the allocator.
+
+<b>To replay file:</b> Use VmaReplay - standalone command-line program.
+Precompiled binary can be found in "bin" directory.
+Its source can be found in "src/VmaReplay" directory.
+Its project is generated by Premake.
+Command line syntax is printed when the program is launched without parameters.
+Basic usage:
+
+ VmaReplay.exe MyRecording.csv
+
+<b>Documentation of file format</b> can be found in file: "docs/Recording file format.md".
+It's a human-readable, text file in CSV format (Comma Separated Values).
+
+\section record_and_replay_additional_considerations Additional considerations
+
+- Replaying file that was recorded on a different GPU (with different parameters
+ like `bufferImageGranularity`, `nonCoherentAtomSize`, and especially different
+ set of memory heaps and types) may give different performance and memory usage
+ results, as well as issue some warnings and errors.
+- Current implementation of recording in VMA, as well as VmaReplay application, is
+ coded and tested only on Windows. Inclusion of recording code is driven by
+ `VMA_RECORDING_ENABLED` macro. Support for other platforms should be easy to
+ add. Contributions are welcomed.
+
+
+\page usage_patterns Recommended usage patterns
+
+See also slides from talk:
+[Sawicki, Adam. Advanced Graphics Techniques Tutorial: Memory management in Vulkan and DX12. Game Developers Conference, 2018](https://www.gdcvault.com/play/1025458/Advanced-Graphics-Techniques-Tutorial-New)
+
+
+\section usage_patterns_common_mistakes Common mistakes
+
+<b>Use of CPU_TO_GPU instead of CPU_ONLY memory</b>
+
+#VMA_MEMORY_USAGE_CPU_TO_GPU is recommended only for resources that will be
+mapped and written by the CPU, as well as read directly by the GPU - like some
+buffers or textures updated every frame (dynamic). If you create a staging copy
+of a resource to be written by CPU and then used as a source of transfer to
+another resource placed in the GPU memory, that staging resource should be
+created with #VMA_MEMORY_USAGE_CPU_ONLY. Please read the descriptions of these
+enums carefully for details.
+
+<b>Unnecessary use of custom pools</b>
+
+\ref custom_memory_pools may be useful for special purposes - when you want to
+keep certain type of resources separate e.g. to reserve minimum amount of memory
+for them, limit maximum amount of memory they can occupy, or make some of them
+push out the other through the mechanism of \ref lost_allocations. For most
+resources this is not needed and so it is not recommended to create #VmaPool
+objects and allocations out of them. Allocating from the default pool is sufficient.
+
+\section usage_patterns_simple Simple patterns
+
+\subsection usage_patterns_simple_render_targets Render targets
+
+<b>When:</b>
+Any resources that you frequently write and read on GPU,
+e.g. images used as color attachments (aka "render targets"), depth-stencil attachments,
+images/buffers used as storage image/buffer (aka "Unordered Access View (UAV)").
+
+<b>What to do:</b>
+Create them in video memory that is fastest to access from GPU using
+#VMA_MEMORY_USAGE_GPU_ONLY.
+
+Consider using [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension
+and/or manually creating them as dedicated allocations using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
+especially if they are large or if you plan to destroy and recreate them e.g. when
+display resolution changes.
+Prefer to create such resources first and all other GPU resources (like textures and vertex buffers) later.
+
+\subsection usage_patterns_simple_immutable_resources Immutable resources
+
+<b>When:</b>
+Any resources that you fill on CPU only once (aka "immutable") or infrequently
+and then read frequently on GPU,
+e.g. textures, vertex and index buffers, constant buffers that don't change often.
+
+<b>What to do:</b>
+Create them in video memory that is fastest to access from GPU using
+#VMA_MEMORY_USAGE_GPU_ONLY.
+
+To initialize content of such resource, create a CPU-side (aka "staging") copy of it
+in system memory - #VMA_MEMORY_USAGE_CPU_ONLY, map it, fill it,
+and submit a transfer from it to the GPU resource.
+You can keep the staging copy if you need it for another upload transfer in the future.
+If you don't, you can destroy it or reuse this buffer for uploading different resource
+after the transfer finishes.
+
+Prefer to create just buffers in system memory rather than images, even for uploading textures.
+Use `vkCmdCopyBufferToImage()`.
+Dont use images with `VK_IMAGE_TILING_LINEAR`.
+
+\subsection usage_patterns_dynamic_resources Dynamic resources
+
+<b>When:</b>
+Any resources that change frequently (aka "dynamic"), e.g. every frame or every draw call,
+written on CPU, read on GPU.
+
+<b>What to do:</b>
+Create them using #VMA_MEMORY_USAGE_CPU_TO_GPU.
+You can map it and write to it directly on CPU, as well as read from it on GPU.
+
+This is a more complex situation. Different solutions are possible,
+and the best one depends on specific GPU type, but you can use this simple approach for the start.
+Prefer to write to such resource sequentially (e.g. using `memcpy`).
+Don't perform random access or any reads from it on CPU, as it may be very slow.
+
+\subsection usage_patterns_readback Readback
+
+<b>When:</b>
+Resources that contain data written by GPU that you want to read back on CPU,
+e.g. results of some computations.
+
+<b>What to do:</b>
+Create them using #VMA_MEMORY_USAGE_GPU_TO_CPU.
+You can write to them directly on GPU, as well as map and read them on CPU.
+
+\section usage_patterns_advanced Advanced patterns
+
+\subsection usage_patterns_integrated_graphics Detecting integrated graphics
+
+You can support integrated graphics (like Intel HD Graphics, AMD APU) better
+by detecting it in Vulkan.
+To do it, call `vkGetPhysicalDeviceProperties()`, inspect
+`VkPhysicalDeviceProperties::deviceType` and look for `VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU`.
+When you find it, you can assume that memory is unified and all memory types are comparably fast
+to access from GPU, regardless of `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.
+
+You can then sum up sizes of all available memory heaps and treat them as useful for
+your GPU resources, instead of only `DEVICE_LOCAL` ones.
+You can also prefer to create your resources in memory types that are `HOST_VISIBLE` to map them
+directly instead of submitting explicit transfer (see below).
+
+\subsection usage_patterns_direct_vs_transfer Direct access versus transfer
+
+For resources that you frequently write on CPU and read on GPU, many solutions are possible:
+
+-# Create one copy in video memory using #VMA_MEMORY_USAGE_GPU_ONLY,
+ second copy in system memory using #VMA_MEMORY_USAGE_CPU_ONLY and submit explicit tranfer each time.
+-# Create just single copy using #VMA_MEMORY_USAGE_CPU_TO_GPU, map it and fill it on CPU,
+ read it directly on GPU.
+-# Create just single copy using #VMA_MEMORY_USAGE_CPU_ONLY, map it and fill it on CPU,
+ read it directly on GPU.
+
+Which solution is the most efficient depends on your resource and especially on the GPU.
+It is best to measure it and then make the decision.
+Some general recommendations:
+
+- On integrated graphics use (2) or (3) to avoid unnecesary time and memory overhead
+ related to using a second copy and making transfer.
+- For small resources (e.g. constant buffers) use (2).
+ Discrete AMD cards have special 256 MiB pool of video memory that is directly mappable.
+ Even if the resource ends up in system memory, its data may be cached on GPU after first
+ fetch over PCIe bus.
+- For larger resources (e.g. textures), decide between (1) and (2).
+ You may want to differentiate NVIDIA and AMD, e.g. by looking for memory type that is
+ both `DEVICE_LOCAL` and `HOST_VISIBLE`. When you find it, use (2), otherwise use (1).
+
+Similarly, for resources that you frequently write on GPU and read on CPU, multiple
+solutions are possible:
+
+-# Create one copy in video memory using #VMA_MEMORY_USAGE_GPU_ONLY,
+ second copy in system memory using #VMA_MEMORY_USAGE_GPU_TO_CPU and submit explicit tranfer each time.
+-# Create just single copy using #VMA_MEMORY_USAGE_GPU_TO_CPU, write to it directly on GPU,
+ map it and read it on CPU.
+
+You should take some measurements to decide which option is faster in case of your specific
+resource.
+
+If you don't want to specialize your code for specific types of GPUs, you can still make
+an simple optimization for cases when your resource ends up in mappable memory to use it
+directly in this case instead of creating CPU-side staging copy.
+For details see [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable).
+
+
+\page configuration Configuration
+
+Please check "CONFIGURATION SECTION" in the code to find macros that you can define
+before each include of this file or change directly in this file to provide
+your own implementation of basic facilities like assert, `min()` and `max()` functions,
+mutex, atomic etc.
+The library uses its own implementation of containers by default, but you can switch to using
+STL containers instead.
+
+For example, define `VMA_ASSERT(expr)` before including the library to provide
+custom implementation of the assertion, compatible with your project.
+By default it is defined to standard C `assert(expr)` in `_DEBUG` configuration
+and empty otherwise.
+
+\section config_Vulkan_functions Pointers to Vulkan functions
+
+The library uses Vulkan functions straight from the `vulkan.h` header by default.
+If you want to provide your own pointers to these functions, e.g. fetched using
+`vkGetInstanceProcAddr()` and `vkGetDeviceProcAddr()`:
+
+-# Define `VMA_STATIC_VULKAN_FUNCTIONS 0`.
+-# Provide valid pointers through VmaAllocatorCreateInfo::pVulkanFunctions.
+
+\section custom_memory_allocator Custom host memory allocator
+
+If you use custom allocator for CPU memory rather than default operator `new`
+and `delete` from C++, you can make this library using your allocator as well
+by filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These
+functions will be passed to Vulkan, as well as used by the library itself to
+make any CPU-side allocations.
+
+\section allocation_callbacks Device memory allocation callbacks
+
+The library makes calls to `vkAllocateMemory()` and `vkFreeMemory()` internally.
+You can setup callbacks to be informed about these calls, e.g. for the purpose
+of gathering some statistics. To do it, fill optional member
+VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
+
+\section heap_memory_limit Device heap memory limit
+
+When device memory of certain heap runs out of free space, new allocations may
+fail (returning error code) or they may succeed, silently pushing some existing
+memory blocks from GPU VRAM to system RAM (which degrades performance). This
+behavior is implementation-dependant - it depends on GPU vendor and graphics
+driver.
+
+On AMD cards it can be controlled while creating Vulkan device object by using
+VK_AMD_memory_overallocation_behavior extension, if available.
+
+Alternatively, if you want to test how your program behaves with limited amount of Vulkan device
+memory available without switching your graphics card to one that really has
+smaller VRAM, you can use a feature of this library intended for this purpose.
+To do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit.
+
+
+
+\page vk_khr_dedicated_allocation VK_KHR_dedicated_allocation
+
+VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve
+performance on some GPUs. It augments Vulkan API with possibility to query
+driver whether it prefers particular buffer or image to have its own, dedicated
+allocation (separate `VkDeviceMemory` block) for better efficiency - to be able
+to do some internal optimizations.
+
+The extension is supported by this library. It will be used automatically when
+enabled. To enable it:
+
+1 . When creating Vulkan device, check if following 2 device extensions are
+supported (call `vkEnumerateDeviceExtensionProperties()`).
+If yes, enable them (fill `VkDeviceCreateInfo::ppEnabledExtensionNames`).
+
+- VK_KHR_get_memory_requirements2
+- VK_KHR_dedicated_allocation
+
+If you enabled these extensions:
+
+2 . Use #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag when creating
+your #VmaAllocator`to inform the library that you enabled required extensions
+and you want the library to use them.
+
+\code
+allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
+
+vmaCreateAllocator(&allocatorInfo, &allocator);
+\endcode
+
+That's all. The extension will be automatically used whenever you create a
+buffer using vmaCreateBuffer() or image using vmaCreateImage().
+
+When using the extension together with Vulkan Validation Layer, you will receive
+warnings like this:
+
+ vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer.
+
+It is OK, you should just ignore it. It happens because you use function
+`vkGetBufferMemoryRequirements2KHR()` instead of standard
+`vkGetBufferMemoryRequirements()`, while the validation layer seems to be
+unaware of it.
+
+To learn more about this extension, see:
+
+- [VK_KHR_dedicated_allocation in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VK_KHR_dedicated_allocation)
+- [VK_KHR_dedicated_allocation unofficial manual](http://asawicki.info/articles/VK_KHR_dedicated_allocation.php5)
+
+
+
+\page general_considerations General considerations
+
+\section general_considerations_thread_safety Thread safety
+
+- The library has no global state, so separate #VmaAllocator objects can be used
+ independently.
+ There should be no need to create multiple such objects though - one per `VkDevice` is enough.
+- By default, all calls to functions that take #VmaAllocator as first parameter
+ are safe to call from multiple threads simultaneously because they are
+ synchronized internally when needed.
+- When the allocator is created with #VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT
+ flag, calls to functions that take such #VmaAllocator object must be
+ synchronized externally.
+- Access to a #VmaAllocation object must be externally synchronized. For example,
+ you must not call vmaGetAllocationInfo() and vmaMapMemory() from different
+ threads at the same time if you pass the same #VmaAllocation object to these
+ functions.
+
+\section general_considerations_validation_layer_warnings Validation layer warnings
+
+When using this library, you can meet following types of warnings issued by
+Vulkan validation layer. They don't necessarily indicate a bug, so you may need
+to just ignore them.
+
+- *vkBindBufferMemory(): Binding memory to buffer 0xeb8e4 but vkGetBufferMemoryRequirements() has not been called on that buffer.*
+ - It happens when VK_KHR_dedicated_allocation extension is enabled.
+ `vkGetBufferMemoryRequirements2KHR` function is used instead, while validation layer seems to be unaware of it.
+- *Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.*
+ - It happens when you map a buffer or image, because the library maps entire
+ `VkDeviceMemory` block, where different types of images and buffers may end
+ up together, especially on GPUs with unified memory like Intel.
+- *Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug.*
+ - It happens when you use lost allocations, and a new image or buffer is
+ created in place of an existing object that bacame lost.
+ - It may happen also when you use [defragmentation](@ref defragmentation).
+
+\section general_considerations_allocation_algorithm Allocation algorithm
+
+The library uses following algorithm for allocation, in order:
+
+-# Try to find free range of memory in existing blocks.
+-# If failed, try to create a new block of `VkDeviceMemory`, with preferred block size.
+-# If failed, try to create such block with size/2, size/4, size/8.
+-# If failed and #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag was
+ specified, try to find space in existing blocks, possilby making some other
+ allocations lost.
+-# If failed, try to allocate separate `VkDeviceMemory` for this allocation,
+ just like when you use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+-# If failed, choose other memory type that meets the requirements specified in
+ VmaAllocationCreateInfo and go to point 1.
+-# If failed, return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+
+\section general_considerations_features_not_supported Features not supported
+
+Features deliberately excluded from the scope of this library:
+
+- Data transfer. Uploading (straming) and downloading data of buffers and images
+ between CPU and GPU memory and related synchronization is responsibility of the user.
+ Defining some "texture" object that would automatically stream its data from a
+ staging copy in CPU memory to GPU memory would rather be a feature of another,
+ higher-level library implemented on top of VMA.
+- Allocations for imported/exported external memory. They tend to require
+ explicit memory type index and dedicated allocation anyway, so they don't
+ interact with main features of this library. Such special purpose allocations
+ should be made manually, using `vkCreateBuffer()` and `vkAllocateMemory()`.
+- Recreation of buffers and images. Although the library has functions for
+ buffer and image creation (vmaCreateBuffer(), vmaCreateImage()), you need to
+ recreate these objects yourself after defragmentation. That's because the big
+ structures `VkBufferCreateInfo`, `VkImageCreateInfo` are not stored in
+ #VmaAllocation object.
+- Handling CPU memory allocation failures. When dynamically creating small C++
+ objects in CPU memory (not Vulkan memory), allocation failures are not checked
+ and handled gracefully, because that would complicate code significantly and
+ is usually not needed in desktop PC applications anyway.
+- Code free of any compiler warnings. Maintaining the library to compile and
+ work correctly on so many different platforms is hard enough. Being free of
+ any warnings, on any version of any compiler, is simply not feasible.
+- This is a C++ library with C interface.
+ Bindings or ports to any other programming languages are welcomed as external projects and
+ are not going to be included into this repository.
+
+*/
+
+/*
+Define this macro to 0/1 to disable/enable support for recording functionality,
+available through VmaAllocatorCreateInfo::pRecordSettings.
+*/
+#ifndef VMA_RECORDING_ENABLED
+ #define VMA_RECORDING_ENABLED 0
+#endif
+
+#ifndef NOMINMAX
+ #define NOMINMAX // For windows.h
+#endif
+
+#ifndef VULKAN_H_
+ #include <vulkan/vulkan.h>
+#endif
+
+#if VMA_RECORDING_ENABLED
+ #include <windows.h>
+#endif
+
+// Define this macro to declare maximum supported Vulkan version in format AAABBBCCC,
+// where AAA = major, BBB = minor, CCC = patch.
+// If you want to use version > 1.0, it still needs to be enabled via VmaAllocatorCreateInfo::vulkanApiVersion.
+#if !defined(VMA_VULKAN_VERSION)
+ #if defined(VK_VERSION_1_1)
+ #define VMA_VULKAN_VERSION 1001000
+ #else
+ #define VMA_VULKAN_VERSION 1000000
+ #endif
+#endif
+
+#if !defined(VMA_DEDICATED_ALLOCATION)
+ #if VK_KHR_get_memory_requirements2 && VK_KHR_dedicated_allocation
+ #define VMA_DEDICATED_ALLOCATION 1
+ #else
+ #define VMA_DEDICATED_ALLOCATION 0
+ #endif
+#endif
+
+#if !defined(VMA_BIND_MEMORY2)
+ #if VK_KHR_bind_memory2
+ #define VMA_BIND_MEMORY2 1
+ #else
+ #define VMA_BIND_MEMORY2 0
+ #endif
+#endif
+
+#if !defined(VMA_MEMORY_BUDGET)
+ #if VK_EXT_memory_budget && (VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000)
+ #define VMA_MEMORY_BUDGET 1
+ #else
+ #define VMA_MEMORY_BUDGET 0
+ #endif
+#endif
+
+// Define these macros to decorate all public functions with additional code,
+// before and after returned type, appropriately. This may be useful for
+// exporing the functions when compiling VMA as a separate library. Example:
+// #define VMA_CALL_PRE __declspec(dllexport)
+// #define VMA_CALL_POST __cdecl
+#ifndef VMA_CALL_PRE
+ #define VMA_CALL_PRE
+#endif
+#ifndef VMA_CALL_POST
+ #define VMA_CALL_POST
+#endif
+
+/** \struct VmaAllocator
+\brief Represents main object of this library initialized.
+
+Fill structure #VmaAllocatorCreateInfo and call function vmaCreateAllocator() to create it.
+Call function vmaDestroyAllocator() to destroy it.
+
+It is recommended to create just one object of this type per `VkDevice` object,
+right after Vulkan is initialized and keep it alive until before Vulkan device is destroyed.
+*/
+VK_DEFINE_HANDLE(VmaAllocator)
+
+/// Callback function called after successful vkAllocateMemory.
+typedef void (VKAPI_PTR *PFN_vmaAllocateDeviceMemoryFunction)(
+ VmaAllocator allocator,
+ uint32_t memoryType,
+ VkDeviceMemory memory,
+ VkDeviceSize size);
+/// Callback function called before vkFreeMemory.
+typedef void (VKAPI_PTR *PFN_vmaFreeDeviceMemoryFunction)(
+ VmaAllocator allocator,
+ uint32_t memoryType,
+ VkDeviceMemory memory,
+ VkDeviceSize size);
+
+/** \brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`.
+
+Provided for informative purpose, e.g. to gather statistics about number of
+allocations or total amount of memory allocated in Vulkan.
+
+Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
+*/
+typedef struct VmaDeviceMemoryCallbacks {
+ /// Optional, can be null.
+ PFN_vmaAllocateDeviceMemoryFunction pfnAllocate;
+ /// Optional, can be null.
+ PFN_vmaFreeDeviceMemoryFunction pfnFree;
+} VmaDeviceMemoryCallbacks;
+
+/// Flags for created #VmaAllocator.
+typedef enum VmaAllocatorCreateFlagBits {
+ /** \brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you.
+
+ Using this flag may increase performance because internal mutexes are not used.
+ */
+ VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001,
+ /** \brief Enables usage of VK_KHR_dedicated_allocation extension.
+
+ The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`.
+ When it's `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.
+
+ Using this extenion will automatically allocate dedicated blocks of memory for
+ some buffers and images instead of suballocating place for them out of bigger
+ memory blocks (as if you explicitly used #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT
+ flag) when it is recommended by the driver. It may improve performance on some
+ GPUs.
+
+ You may set this flag only if you found out that following device extensions are
+ supported, you enabled them while creating Vulkan device passed as
+ VmaAllocatorCreateInfo::device, and you want them to be used internally by this
+ library:
+
+ - VK_KHR_get_memory_requirements2 (device extension)
+ - VK_KHR_dedicated_allocation (device extension)
+
+ When this flag is set, you can experience following warnings reported by Vulkan
+ validation layer. You can ignore them.
+
+ > vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer.
+ */
+ VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT = 0x00000002,
+ /**
+ Enables usage of VK_KHR_bind_memory2 extension.
+
+ The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`.
+ When it's `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.
+
+ You may set this flag only if you found out that this device extension is supported,
+ you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
+ and you want it to be used internally by this library.
+
+ The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`,
+ which allow to pass a chain of `pNext` structures while binding.
+ This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2().
+ */
+ VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT = 0x00000004,
+ /**
+ Enables usage of VK_EXT_memory_budget extension.
+
+ You may set this flag only if you found out that this device extension is supported,
+ you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
+ and you want it to be used internally by this library, along with another instance extension
+ VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted).
+
+ The extension provides query for current memory usage and budget, which will probably
+ be more accurate than an estimation used by the library otherwise.
+ */
+ VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT = 0x00000008,
+
+ VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaAllocatorCreateFlagBits;
+typedef VkFlags VmaAllocatorCreateFlags;
+
+/** \brief Pointers to some Vulkan functions - a subset used by the library.
+
+Used in VmaAllocatorCreateInfo::pVulkanFunctions.
+*/
+typedef struct VmaVulkanFunctions {
+ PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
+ PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
+ PFN_vkAllocateMemory vkAllocateMemory;
+ PFN_vkFreeMemory vkFreeMemory;
+ PFN_vkMapMemory vkMapMemory;
+ PFN_vkUnmapMemory vkUnmapMemory;
+ PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;
+ PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges;
+ PFN_vkBindBufferMemory vkBindBufferMemory;
+ PFN_vkBindImageMemory vkBindImageMemory;
+ PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
+ PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
+ PFN_vkCreateBuffer vkCreateBuffer;
+ PFN_vkDestroyBuffer vkDestroyBuffer;
+ PFN_vkCreateImage vkCreateImage;
+ PFN_vkDestroyImage vkDestroyImage;
+ PFN_vkCmdCopyBuffer vkCmdCopyBuffer;
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+ PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;
+ PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;
+#endif
+#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
+ PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR;
+ PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR;
+#endif
+#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000
+ PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR;
+#endif
+} VmaVulkanFunctions;
+
+/// Flags to be used in VmaRecordSettings::flags.
+typedef enum VmaRecordFlagBits {
+ /** \brief Enables flush after recording every function call.
+
+ Enable it if you expect your application to crash, which may leave recording file truncated.
+ It may degrade performance though.
+ */
+ VMA_RECORD_FLUSH_AFTER_CALL_BIT = 0x00000001,
+
+ VMA_RECORD_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaRecordFlagBits;
+typedef VkFlags VmaRecordFlags;
+
+/// Parameters for recording calls to VMA functions. To be used in VmaAllocatorCreateInfo::pRecordSettings.
+typedef struct VmaRecordSettings
+{
+ /// Flags for recording. Use #VmaRecordFlagBits enum.
+ VmaRecordFlags flags;
+ /** \brief Path to the file that should be written by the recording.
+
+ Suggested extension: "csv".
+ If the file already exists, it will be overwritten.
+ It will be opened for the whole time #VmaAllocator object is alive.
+ If opening this file fails, creation of the whole allocator object fails.
+ */
+ const char* pFilePath;
+} VmaRecordSettings;
+
+/// Description of a Allocator to be created.
+typedef struct VmaAllocatorCreateInfo
+{
+ /// Flags for created allocator. Use #VmaAllocatorCreateFlagBits enum.
+ VmaAllocatorCreateFlags flags;
+ /// Vulkan physical device.
+ /** It must be valid throughout whole lifetime of created allocator. */
+ VkPhysicalDevice physicalDevice;
+ /// Vulkan device.
+ /** It must be valid throughout whole lifetime of created allocator. */
+ VkDevice device;
+ /// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB. Optional.
+ /** Set to 0 to use default, which is currently 256 MiB. */
+ VkDeviceSize preferredLargeHeapBlockSize;
+ /// Custom CPU memory allocation callbacks. Optional.
+ /** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */
+ const VkAllocationCallbacks* pAllocationCallbacks;
+ /// Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional.
+ /** Optional, can be null. */
+ const VmaDeviceMemoryCallbacks* pDeviceMemoryCallbacks;
+ /** \brief Maximum number of additional frames that are in use at the same time as current frame.
+
+ This value is used only when you make allocations with
+ VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocation cannot become
+ lost if allocation.lastUseFrameIndex >= allocator.currentFrameIndex - frameInUseCount.
+
+ For example, if you double-buffer your command buffers, so resources used for
+ rendering in previous frame may still be in use by the GPU at the moment you
+ allocate resources needed for the current frame, set this value to 1.
+
+ If you want to allow any allocations other than used in the current frame to
+ become lost, set this value to 0.
+ */
+ uint32_t frameInUseCount;
+ /** \brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap.
+
+ If not NULL, it must be a pointer to an array of
+ `VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on
+ maximum number of bytes that can be allocated out of particular Vulkan memory
+ heap.
+
+ Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that
+ heap. This is also the default in case of `pHeapSizeLimit` = NULL.
+
+ If there is a limit defined for a heap:
+
+ - If user tries to allocate more memory from that heap using this allocator,
+ the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+ - If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the
+ value of this limit will be reported instead when using vmaGetMemoryProperties().
+
+ Warning! Using this feature may not be equivalent to installing a GPU with
+ smaller amount of memory, because graphics driver doesn't necessary fail new
+ allocations with `VK_ERROR_OUT_OF_DEVICE_MEMORY` result when memory capacity is
+ exceeded. It may return success and just silently migrate some device memory
+ blocks to system RAM. This driver behavior can also be controlled using
+ VK_AMD_memory_overallocation_behavior extension.
+ */
+ const VkDeviceSize* pHeapSizeLimit;
+ /** \brief Pointers to Vulkan functions. Can be null if you leave define `VMA_STATIC_VULKAN_FUNCTIONS 1`.
+
+ If you leave define `VMA_STATIC_VULKAN_FUNCTIONS 1` in configuration section,
+ you can pass null as this member, because the library will fetch pointers to
+ Vulkan functions internally in a static way, like:
+
+ vulkanFunctions.vkAllocateMemory = &vkAllocateMemory;
+
+ Fill this member if you want to provide your own pointers to Vulkan functions,
+ e.g. fetched using `vkGetInstanceProcAddr()` and `vkGetDeviceProcAddr()`.
+ */
+ const VmaVulkanFunctions* pVulkanFunctions;
+ /** \brief Parameters for recording of VMA calls. Can be null.
+
+ If not null, it enables recording of calls to VMA functions to a file.
+ If support for recording is not enabled using `VMA_RECORDING_ENABLED` macro,
+ creation of the allocator object fails with `VK_ERROR_FEATURE_NOT_PRESENT`.
+ */
+ const VmaRecordSettings* pRecordSettings;
+ /** \brief Optional handle to Vulkan instance object.
+
+ Optional, can be null. Must be set if #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT flas is used
+ or if `vulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)`.
+ */
+ VkInstance instance;
+ /** \brief Optional. The highest version of Vulkan that the application is designed to use.
+
+ It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`.
+ The patch version number specified is ignored. Only the major and minor versions are considered.
+ It must be less or euqal (preferably equal) to value as passed to `vkCreateInstance` as `VkApplicationInfo::apiVersion`.
+ Only versions 1.0 and 1.1 are supported by the current implementation.
+ Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`.
+ */
+ uint32_t vulkanApiVersion;
+} VmaAllocatorCreateInfo;
+
+/// Creates Allocator object.
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
+ const VmaAllocatorCreateInfo* pCreateInfo,
+ VmaAllocator* pAllocator);
+
+/// Destroys allocator object.
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator(
+ VmaAllocator allocator);
+
+/**
+PhysicalDeviceProperties are fetched from physicalDevice by the allocator.
+You can access it here, without fetching it again on your own.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties(
+ VmaAllocator allocator,
+ const VkPhysicalDeviceProperties** ppPhysicalDeviceProperties);
+
+/**
+PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator.
+You can access it here, without fetching it again on your own.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties(
+ VmaAllocator allocator,
+ const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties);
+
+/**
+\brief Given Memory Type Index, returns Property Flags of this memory type.
+
+This is just a convenience function. Same information can be obtained using
+vmaGetMemoryProperties().
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties(
+ VmaAllocator allocator,
+ uint32_t memoryTypeIndex,
+ VkMemoryPropertyFlags* pFlags);
+
+/** \brief Sets index of the current frame.
+
+This function must be used if you make allocations with
+#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT and
+#VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flags to inform the allocator
+when a new frame begins. Allocations queried using vmaGetAllocationInfo() cannot
+become lost in the current frame.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex(
+ VmaAllocator allocator,
+ uint32_t frameIndex);
+
+/** \brief Calculated statistics of memory usage in entire allocator.
+*/
+typedef struct VmaStatInfo
+{
+ /// Number of `VkDeviceMemory` Vulkan memory blocks allocated.
+ uint32_t blockCount;
+ /// Number of #VmaAllocation allocation objects allocated.
+ uint32_t allocationCount;
+ /// Number of free ranges of memory between allocations.
+ uint32_t unusedRangeCount;
+ /// Total number of bytes occupied by all allocations.
+ VkDeviceSize usedBytes;
+ /// Total number of bytes occupied by unused ranges.
+ VkDeviceSize unusedBytes;
+ VkDeviceSize allocationSizeMin, allocationSizeAvg, allocationSizeMax;
+ VkDeviceSize unusedRangeSizeMin, unusedRangeSizeAvg, unusedRangeSizeMax;
+} VmaStatInfo;
+
+/// General statistics from current state of Allocator.
+typedef struct VmaStats
+{
+ VmaStatInfo memoryType[VK_MAX_MEMORY_TYPES];
+ VmaStatInfo memoryHeap[VK_MAX_MEMORY_HEAPS];
+ VmaStatInfo total;
+} VmaStats;
+
+/** \brief Retrieves statistics from current state of the Allocator.
+
+This function is called "calculate" not "get" because it has to traverse all
+internal data structures, so it may be quite slow. For faster but more brief statistics
+suitable to be called every frame or every allocation, use vmaGetBudget().
+
+Note that when using allocator from multiple threads, returned information may immediately
+become outdated.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStats(
+ VmaAllocator allocator,
+ VmaStats* pStats);
+
+/** \brief Statistics of current memory usage and available budget, in bytes, for specific memory heap.
+*/
+typedef struct VmaBudget
+{
+ /** \brief Sum size of all `VkDeviceMemory` blocks allocated from particular heap, in bytes.
+ */
+ VkDeviceSize blockBytes;
+
+ /** \brief Sum size of all allocations created in particular heap, in bytes.
+
+ Usually less or equal than `blockBytes`.
+ Difference `blockBytes - allocationBytes` is the amount of memory allocated but unused -
+ available for new allocations or wasted due to fragmentation.
+
+ It might be greater than `blockBytes` if there are some allocations in lost state, as they account
+ to this value as well.
+ */
+ VkDeviceSize allocationBytes;
+
+ /** \brief Estimated current memory usage of the program, in bytes.
+
+ Fetched from system using `VK_EXT_memory_budget` extension if enabled.
+
+ It might be different than `blockBytes` (usually higher) due to additional implicit objects
+ also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or
+ `VkDeviceMemory` blocks allocated outside of this library, if any.
+ */
+ VkDeviceSize usage;
+
+ /** \brief Estimated amount of memory available to the program, in bytes.
+
+ Fetched from system using `VK_EXT_memory_budget` extension if enabled.
+
+ It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors
+ external to the program, like other programs also consuming system resources.
+ Difference `budget - usage` is the amount of additional memory that can probably
+ be allocated without problems. Exceeding the budget may result in various problems.
+ */
+ VkDeviceSize budget;
+} VmaBudget;
+
+/** \brief Retrieves information about current memory budget for all memory heaps.
+
+\param[out] pBudget Must point to array with number of elements at least equal to number of memory heaps in physical device used.
+
+This function is called "get" not "calculate" because it is very fast, suitable to be called
+every frame or every allocation. For more detailed statistics use vmaCalculateStats().
+
+Note that when using allocator from multiple threads, returned information may immediately
+become outdated.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetBudget(
+ VmaAllocator allocator,
+ VmaBudget* pBudget);
+
+#ifndef VMA_STATS_STRING_ENABLED
+#define VMA_STATS_STRING_ENABLED 1
+#endif
+
+#if VMA_STATS_STRING_ENABLED
+
+/// Builds and returns statistics as string in JSON format.
+/** @param[out] ppStatsString Must be freed using vmaFreeStatsString() function.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString(
+ VmaAllocator allocator,
+ char** ppStatsString,
+ VkBool32 detailedMap);
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
+ VmaAllocator allocator,
+ char* pStatsString);
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+/** \struct VmaPool
+\brief Represents custom memory pool
+
+Fill structure VmaPoolCreateInfo and call function vmaCreatePool() to create it.
+Call function vmaDestroyPool() to destroy it.
+
+For more information see [Custom memory pools](@ref choosing_memory_type_custom_memory_pools).
+*/
+VK_DEFINE_HANDLE(VmaPool)
+
+typedef enum VmaMemoryUsage
+{
+ /** No intended memory usage specified.
+ Use other members of VmaAllocationCreateInfo to specify your requirements.
+ */
+ VMA_MEMORY_USAGE_UNKNOWN = 0,
+ /** Memory will be used on device only, so fast access from the device is preferred.
+ It usually means device-local GPU (video) memory.
+ No need to be mappable on host.
+ It is roughly equivalent of `D3D12_HEAP_TYPE_DEFAULT`.
+
+ Usage:
+
+ - Resources written and read by device, e.g. images used as attachments.
+ - Resources transferred from host once (immutable) or infrequently and read by
+ device multiple times, e.g. textures to be sampled, vertex buffers, uniform
+ (constant) buffers, and majority of other types of resources used on GPU.
+
+ Allocation may still end up in `HOST_VISIBLE` memory on some implementations.
+ In such case, you are free to map it.
+ You can use #VMA_ALLOCATION_CREATE_MAPPED_BIT with this usage type.
+ */
+ VMA_MEMORY_USAGE_GPU_ONLY = 1,
+ /** Memory will be mappable on host.
+ It usually means CPU (system) memory.
+ Guarantees to be `HOST_VISIBLE` and `HOST_COHERENT`.
+ CPU access is typically uncached. Writes may be write-combined.
+ Resources created in this pool may still be accessible to the device, but access to them can be slow.
+ It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`.
+
+ Usage: Staging copy of resources used as transfer source.
+ */
+ VMA_MEMORY_USAGE_CPU_ONLY = 2,
+ /**
+ Memory that is both mappable on host (guarantees to be `HOST_VISIBLE`) and preferably fast to access by GPU.
+ CPU access is typically uncached. Writes may be write-combined.
+
+ Usage: Resources written frequently by host (dynamic), read by device. E.g. textures, vertex buffers, uniform buffers updated every frame or every draw call.
+ */
+ VMA_MEMORY_USAGE_CPU_TO_GPU = 3,
+ /** Memory mappable on host (guarantees to be `HOST_VISIBLE`) and cached.
+ It is roughly equivalent of `D3D12_HEAP_TYPE_READBACK`.
+
+ Usage:
+
+ - Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping.
+ - Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection.
+ */
+ VMA_MEMORY_USAGE_GPU_TO_CPU = 4,
+ /** CPU memory - memory that is preferably not `DEVICE_LOCAL`, but also not guaranteed to be `HOST_VISIBLE`.
+
+ Usage: Staging copy of resources moved from GPU memory to CPU memory as part
+ of custom paging/residency mechanism, to be moved back to GPU memory when needed.
+ */
+ VMA_MEMORY_USAGE_CPU_COPY = 5,
+ /** Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`.
+ Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation.
+
+ Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`.
+
+ Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+ */
+ VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6,
+
+ VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF
+} VmaMemoryUsage;
+
+/// Flags to be passed as VmaAllocationCreateInfo::flags.
+typedef enum VmaAllocationCreateFlagBits {
+ /** \brief Set this flag if the allocation should have its own memory block.
+
+ Use it for special, big resources, like fullscreen images used as attachments.
+
+ You should not use this flag if VmaAllocationCreateInfo::pool is not null.
+ */
+ VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001,
+
+ /** \brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block.
+
+ If new allocation cannot be placed in any of the existing blocks, allocation
+ fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error.
+
+ You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and
+ #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense.
+
+ If VmaAllocationCreateInfo::pool is not null, this flag is implied and ignored. */
+ VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002,
+ /** \brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.
+
+ Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData.
+
+ Is it valid to use this flag for allocation made from memory type that is not
+ `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is
+ useful if you need an allocation that is efficient to use on GPU
+ (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that
+ support it (e.g. Intel GPU).
+
+ You should not use this flag together with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT.
+ */
+ VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004,
+ /** Allocation created with this flag can become lost as a result of another
+ allocation with #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag, so you
+ must check it before use.
+
+ To check if allocation is not lost, call vmaGetAllocationInfo() and check if
+ VmaAllocationInfo::deviceMemory is not `VK_NULL_HANDLE`.
+
+ For details about supporting lost allocations, see Lost Allocations
+ chapter of User Guide on Main Page.
+
+ You should not use this flag together with #VMA_ALLOCATION_CREATE_MAPPED_BIT.
+ */
+ VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT = 0x00000008,
+ /** While creating allocation using this flag, other allocations that were
+ created with flag #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT can become lost.
+
+ For details about supporting lost allocations, see Lost Allocations
+ chapter of User Guide on Main Page.
+ */
+ VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT = 0x00000010,
+ /** Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a
+ null-terminated string. Instead of copying pointer value, a local copy of the
+ string is made and stored in allocation's `pUserData`. The string is automatically
+ freed together with the allocation. It is also used in vmaBuildStatsString().
+ */
+ VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020,
+ /** Allocation will be created from upper stack in a double stack pool.
+
+ This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag.
+ */
+ VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040,
+ /** Create both buffer/image and allocation, but don't bind them together.
+ It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions.
+ The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage().
+ Otherwise it is ignored.
+ */
+ VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 0x00000080,
+ /** Create allocation only if additional device memory required for it, if any, won't exceed
+ memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+ */
+ VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100,
+
+ /** Allocation strategy that chooses smallest possible free range for the
+ allocation.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT = 0x00010000,
+ /** Allocation strategy that chooses biggest possible free range for the
+ allocation.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT = 0x00020000,
+ /** Allocation strategy that chooses first suitable free range for the
+ allocation.
+
+ "First" doesn't necessarily means the one with smallest offset in memory,
+ but rather the one that is easiest and fastest to find.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = 0x00040000,
+
+ /** Allocation strategy that tries to minimize memory usage.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT,
+ /** Allocation strategy that tries to minimize allocation time.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT,
+ /** Allocation strategy that tries to minimize memory fragmentation.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT = VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT,
+
+ /** A bit mask to extract only `STRATEGY` bits from entire set of flags.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MASK =
+ VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT |
+ VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT |
+ VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT,
+
+ VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaAllocationCreateFlagBits;
+typedef VkFlags VmaAllocationCreateFlags;
+
+typedef struct VmaAllocationCreateInfo
+{
+ /// Use #VmaAllocationCreateFlagBits enum.
+ VmaAllocationCreateFlags flags;
+ /** \brief Intended usage of memory.
+
+ You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n
+ If `pool` is not null, this member is ignored.
+ */
+ VmaMemoryUsage usage;
+ /** \brief Flags that must be set in a Memory Type chosen for an allocation.
+
+ Leave 0 if you specify memory requirements in other way. \n
+ If `pool` is not null, this member is ignored.*/
+ VkMemoryPropertyFlags requiredFlags;
+ /** \brief Flags that preferably should be set in a memory type chosen for an allocation.
+
+ Set to 0 if no additional flags are prefered. \n
+ If `pool` is not null, this member is ignored. */
+ VkMemoryPropertyFlags preferredFlags;
+ /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation.
+
+ Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if
+ it meets other requirements specified by this structure, with no further
+ restrictions on memory type index. \n
+ If `pool` is not null, this member is ignored.
+ */
+ uint32_t memoryTypeBits;
+ /** \brief Pool that this allocation should be created in.
+
+ Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members:
+ `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored.
+ */
+ VmaPool pool;
+ /** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().
+
+ If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either
+ null or pointer to a null-terminated string. The string will be then copied to
+ internal buffer, so it doesn't need to be valid after allocation call.
+ */
+ void* pUserData;
+} VmaAllocationCreateInfo;
+
+/**
+\brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo.
+
+This algorithm tries to find a memory type that:
+
+- Is allowed by memoryTypeBits.
+- Contains all the flags from pAllocationCreateInfo->requiredFlags.
+- Matches intended usage.
+- Has as many flags from pAllocationCreateInfo->preferredFlags as possible.
+
+\return Returns VK_ERROR_FEATURE_NOT_PRESENT if not found. Receiving such result
+from this function or any other allocating function probably means that your
+device doesn't support any memory type with requested features for the specific
+type of resource you want to use it for. Please check parameters of your
+resource, like image layout (OPTIMAL versus LINEAR) or mip level count.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex(
+ VmaAllocator allocator,
+ uint32_t memoryTypeBits,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex);
+
+/**
+\brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo.
+
+It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex.
+It internally creates a temporary, dummy buffer that never has memory bound.
+It is just a convenience function, equivalent to calling:
+
+- `vkCreateBuffer`
+- `vkGetBufferMemoryRequirements`
+- `vmaFindMemoryTypeIndex`
+- `vkDestroyBuffer`
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo(
+ VmaAllocator allocator,
+ const VkBufferCreateInfo* pBufferCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex);
+
+/**
+\brief Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo.
+
+It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex.
+It internally creates a temporary, dummy image that never has memory bound.
+It is just a convenience function, equivalent to calling:
+
+- `vkCreateImage`
+- `vkGetImageMemoryRequirements`
+- `vmaFindMemoryTypeIndex`
+- `vkDestroyImage`
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo(
+ VmaAllocator allocator,
+ const VkImageCreateInfo* pImageCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex);
+
+/// Flags to be passed as VmaPoolCreateInfo::flags.
+typedef enum VmaPoolCreateFlagBits {
+ /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored.
+
+ This is an optional optimization flag.
+
+ If you always allocate using vmaCreateBuffer(), vmaCreateImage(),
+ vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator
+ knows exact type of your allocations so it can handle Buffer-Image Granularity
+ in the optimal way.
+
+ If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(),
+ exact type of such allocations is not known, so allocator must be conservative
+ in handling Buffer-Image Granularity, which can lead to suboptimal allocation
+ (wasted memory). In that case, if you can make sure you always allocate only
+ buffers and linear images or only optimal images out of this pool, use this flag
+ to make allocator disregard Buffer-Image Granularity and so make allocations
+ faster and more optimal.
+ */
+ VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002,
+
+ /** \brief Enables alternative, linear allocation algorithm in this pool.
+
+ Specify this flag to enable linear allocation algorithm, which always creates
+ new allocations after last one and doesn't reuse space from allocations freed in
+ between. It trades memory consumption for simplified algorithm and data
+ structure, which has better performance and uses less memory for metadata.
+
+ By using this flag, you can achieve behavior of free-at-once, stack,
+ ring buffer, and double stack. For details, see documentation chapter
+ \ref linear_algorithm.
+
+ When using this flag, you must specify VmaPoolCreateInfo::maxBlockCount == 1 (or 0 for default).
+
+ For more details, see [Linear allocation algorithm](@ref linear_algorithm).
+ */
+ VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004,
+
+ /** \brief Enables alternative, buddy allocation algorithm in this pool.
+
+ It operates on a tree of blocks, each having size that is a power of two and
+ a half of its parent's size. Comparing to default algorithm, this one provides
+ faster allocation and deallocation and decreased external fragmentation,
+ at the expense of more memory wasted (internal fragmentation).
+
+ For more details, see [Buddy allocation algorithm](@ref buddy_algorithm).
+ */
+ VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT = 0x00000008,
+
+ /** Bit mask to extract only `ALGORITHM` bits from entire set of flags.
+ */
+ VMA_POOL_CREATE_ALGORITHM_MASK =
+ VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT |
+ VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT,
+
+ VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaPoolCreateFlagBits;
+typedef VkFlags VmaPoolCreateFlags;
+
+/** \brief Describes parameter of created #VmaPool.
+*/
+typedef struct VmaPoolCreateInfo {
+ /** \brief Vulkan memory type index to allocate this pool from.
+ */
+ uint32_t memoryTypeIndex;
+ /** \brief Use combination of #VmaPoolCreateFlagBits.
+ */
+ VmaPoolCreateFlags flags;
+ /** \brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional.
+
+ Specify nonzero to set explicit, constant size of memory blocks used by this
+ pool.
+
+ Leave 0 to use default and let the library manage block sizes automatically.
+ Sizes of particular blocks may vary.
+ */
+ VkDeviceSize blockSize;
+ /** \brief Minimum number of blocks to be always allocated in this pool, even if they stay empty.
+
+ Set to 0 to have no preallocated blocks and allow the pool be completely empty.
+ */
+ size_t minBlockCount;
+ /** \brief Maximum number of blocks that can be allocated in this pool. Optional.
+
+ Set to 0 to use default, which is `SIZE_MAX`, which means no limit.
+
+ Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated
+ throughout whole lifetime of this pool.
+ */
+ size_t maxBlockCount;
+ /** \brief Maximum number of additional frames that are in use at the same time as current frame.
+
+ This value is used only when you make allocations with
+ #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocation cannot become
+ lost if allocation.lastUseFrameIndex >= allocator.currentFrameIndex - frameInUseCount.
+
+ For example, if you double-buffer your command buffers, so resources used for
+ rendering in previous frame may still be in use by the GPU at the moment you
+ allocate resources needed for the current frame, set this value to 1.
+
+ If you want to allow any allocations other than used in the current frame to
+ become lost, set this value to 0.
+ */
+ uint32_t frameInUseCount;
+} VmaPoolCreateInfo;
+
+/** \brief Describes parameter of existing #VmaPool.
+*/
+typedef struct VmaPoolStats {
+ /** \brief Total amount of `VkDeviceMemory` allocated from Vulkan for this pool, in bytes.
+ */
+ VkDeviceSize size;
+ /** \brief Total number of bytes in the pool not used by any #VmaAllocation.
+ */
+ VkDeviceSize unusedSize;
+ /** \brief Number of #VmaAllocation objects created from this pool that were not destroyed or lost.
+ */
+ size_t allocationCount;
+ /** \brief Number of continuous memory ranges in the pool not used by any #VmaAllocation.
+ */
+ size_t unusedRangeCount;
+ /** \brief Size of the largest continuous free memory region available for new allocation.
+
+ Making a new allocation of that size is not guaranteed to succeed because of
+ possible additional margin required to respect alignment and buffer/image
+ granularity.
+ */
+ VkDeviceSize unusedRangeSizeMax;
+ /** \brief Number of `VkDeviceMemory` blocks allocated for this pool.
+ */
+ size_t blockCount;
+} VmaPoolStats;
+
+/** \brief Allocates Vulkan device memory and creates #VmaPool object.
+
+@param allocator Allocator object.
+@param pCreateInfo Parameters of pool to create.
+@param[out] pPool Handle to created pool.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool(
+ VmaAllocator allocator,
+ const VmaPoolCreateInfo* pCreateInfo,
+ VmaPool* pPool);
+
+/** \brief Destroys #VmaPool object and frees Vulkan device memory.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(
+ VmaAllocator allocator,
+ VmaPool pool);
+
+/** \brief Retrieves statistics of existing #VmaPool object.
+
+@param allocator Allocator object.
+@param pool Pool object.
+@param[out] pPoolStats Statistics of specified pool.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStats(
+ VmaAllocator allocator,
+ VmaPool pool,
+ VmaPoolStats* pPoolStats);
+
+/** \brief Marks all allocations in given pool as lost if they are not used in current frame or VmaPoolCreateInfo::frameInUseCount back from now.
+
+@param allocator Allocator object.
+@param pool Pool.
+@param[out] pLostAllocationCount Number of allocations marked as lost. Optional - pass null if you don't need this information.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaMakePoolAllocationsLost(
+ VmaAllocator allocator,
+ VmaPool pool,
+ size_t* pLostAllocationCount);
+
+/** \brief Checks magic number in margins around all allocations in given memory pool in search for corruptions.
+
+Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,
+`VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is
+`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection).
+
+Possible return values:
+
+- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool.
+- `VK_SUCCESS` - corruption detection has been performed and succeeded.
+- `VK_ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations.
+ `VMA_ASSERT` is also fired in that case.
+- Other value: Error returned by Vulkan, e.g. memory mapping failure.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool);
+
+/** \brief Retrieves name of a custom pool.
+
+After the call `ppName` is either null or points to an internally-owned null-terminated string
+containing name of the pool that was previously set. The pointer becomes invalid when the pool is
+destroyed or its name is changed using vmaSetPoolName().
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName(
+ VmaAllocator allocator,
+ VmaPool pool,
+ const char** ppName);
+
+/** \brief Sets name of a custom pool.
+
+`pName` can be either null or pointer to a null-terminated string with new name for the pool.
+Function makes internal copy of the string, so it can be changed or freed immediately after this call.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName(
+ VmaAllocator allocator,
+ VmaPool pool,
+ const char* pName);
+
+/** \struct VmaAllocation
+\brief Represents single memory allocation.
+
+It may be either dedicated block of `VkDeviceMemory` or a specific region of a bigger block of this type
+plus unique offset.
+
+There are multiple ways to create such object.
+You need to fill structure VmaAllocationCreateInfo.
+For more information see [Choosing memory type](@ref choosing_memory_type).
+
+Although the library provides convenience functions that create Vulkan buffer or image,
+allocate memory for it and bind them together,
+binding of the allocation to a buffer or an image is out of scope of the allocation itself.
+Allocation object can exist without buffer/image bound,
+binding can be done manually by the user, and destruction of it can be done
+independently of destruction of the allocation.
+
+The object also remembers its size and some other information.
+To retrieve this information, use function vmaGetAllocationInfo() and inspect
+returned structure VmaAllocationInfo.
+
+Some kinds allocations can be in lost state.
+For more information, see [Lost allocations](@ref lost_allocations).
+*/
+VK_DEFINE_HANDLE(VmaAllocation)
+
+/** \brief Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().
+*/
+typedef struct VmaAllocationInfo {
+ /** \brief Memory type index that this allocation was allocated from.
+
+ It never changes.
+ */
+ uint32_t memoryType;
+ /** \brief Handle to Vulkan memory object.
+
+ Same memory object can be shared by multiple allocations.
+
+ It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost.
+
+ If the allocation is lost, it is equal to `VK_NULL_HANDLE`.
+ */
+ VkDeviceMemory deviceMemory;
+ /** \brief Offset into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory, offset) pair is unique to this allocation.
+
+ It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost.
+ */
+ VkDeviceSize offset;
+ /** \brief Size of this allocation, in bytes.
+
+ It never changes, unless allocation is lost.
+ */
+ VkDeviceSize size;
+ /** \brief Pointer to the beginning of this allocation as mapped data.
+
+ If the allocation hasn't been mapped using vmaMapMemory() and hasn't been
+ created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value null.
+
+ It can change after call to vmaMapMemory(), vmaUnmapMemory().
+ It can also change after call to vmaDefragment() if this allocation is passed to the function.
+ */
+ void* pMappedData;
+ /** \brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData().
+
+ It can change after call to vmaSetAllocationUserData() for this allocation.
+ */
+ void* pUserData;
+} VmaAllocationInfo;
+
+/** \brief General purpose memory allocation.
+
+@param[out] pAllocation Handle to allocated memory.
+@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+
+You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages().
+
+It is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(),
+vmaCreateBuffer(), vmaCreateImage() instead whenever possible.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory(
+ VmaAllocator allocator,
+ const VkMemoryRequirements* pVkMemoryRequirements,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief General purpose memory allocation for multiple allocation objects at once.
+
+@param allocator Allocator object.
+@param pVkMemoryRequirements Memory requirements for each allocation.
+@param pCreateInfo Creation parameters for each alloction.
+@param allocationCount Number of allocations to make.
+@param[out] pAllocations Pointer to array that will be filled with handles to created allocations.
+@param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations.
+
+You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages().
+
+Word "pages" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding.
+It is just a general purpose allocation function able to make multiple allocations at once.
+It may be internally optimized to be more efficient than calling vmaAllocateMemory() `allocationCount` times.
+
+All allocations are made using same parameters. All of them are created out of the same memory pool and type.
+If any allocation fails, all allocations already made within this function call are also freed, so that when
+returned result is not `VK_SUCCESS`, `pAllocation` array is always entirely filled with `VK_NULL_HANDLE`.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages(
+ VmaAllocator allocator,
+ const VkMemoryRequirements* pVkMemoryRequirements,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ size_t allocationCount,
+ VmaAllocation* pAllocations,
+ VmaAllocationInfo* pAllocationInfo);
+
+/**
+@param[out] pAllocation Handle to allocated memory.
+@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+
+You should free the memory using vmaFreeMemory().
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer(
+ VmaAllocator allocator,
+ VkBuffer buffer,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/// Function similar to vmaAllocateMemoryForBuffer().
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage(
+ VmaAllocator allocator,
+ VkImage image,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage().
+
+Passing `VK_NULL_HANDLE` as `allocation` is valid. Such function call is just skipped.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation);
+
+/** \brief Frees memory and destroys multiple allocations.
+
+Word "pages" is just a suggestion to use this function to free pieces of memory used for sparse binding.
+It is just a general purpose function to free memory and destroy allocations made using e.g. vmaAllocateMemory(),
+vmaAllocateMemoryPages() and other functions.
+It may be internally optimized to be more efficient than calling vmaFreeMemory() `allocationCount` times.
+
+Allocations in `pAllocations` array can come from any memory pools and types.
+Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entries are just skipped.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages(
+ VmaAllocator allocator,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+/** \brief Deprecated.
+
+In version 2.2.0 it used to try to change allocation's size without moving or reallocating it.
+In current version it returns `VK_SUCCESS` only if `newSize` equals current allocation's size.
+Otherwise returns `VK_ERROR_OUT_OF_POOL_MEMORY`, indicating that allocation's size could not be changed.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaResizeAllocation(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkDeviceSize newSize);
+
+/** \brief Returns current information about specified allocation and atomically marks it as used in current frame.
+
+Current paramters of given allocation are returned in `pAllocationInfo`.
+
+This function also atomically "touches" allocation - marks it as used in current frame,
+just like vmaTouchAllocation().
+If the allocation is in lost state, `pAllocationInfo->deviceMemory == VK_NULL_HANDLE`.
+
+Although this function uses atomics and doesn't lock any mutex, so it should be quite efficient,
+you can avoid calling it too often.
+
+- You can retrieve same VmaAllocationInfo structure while creating your resource, from function
+ vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change
+ (e.g. due to defragmentation or allocation becoming lost).
+- If you just want to check if allocation is not lost, vmaTouchAllocation() will work faster.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Returns `VK_TRUE` if allocation is not lost and atomically marks it as used in current frame.
+
+If the allocation has been created with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
+this function returns `VK_TRUE` if it's not in lost state, so it can still be used.
+It then also atomically "touches" the allocation - marks it as used in current frame,
+so that you can be sure it won't become lost in current frame or next `frameInUseCount` frames.
+
+If the allocation is in lost state, the function returns `VK_FALSE`.
+Memory of such allocation, as well as buffer or image bound to it, should not be used.
+Lost allocation and the buffer/image still need to be destroyed.
+
+If the allocation has been created without #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
+this function always returns `VK_TRUE`.
+*/
+VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaTouchAllocation(
+ VmaAllocator allocator,
+ VmaAllocation allocation);
+
+/** \brief Sets pUserData in given allocation to new value.
+
+If the allocation was created with VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT,
+pUserData must be either null, or pointer to a null-terminated string. The function
+makes local copy of the string and sets it as allocation's `pUserData`. String
+passed as pUserData doesn't need to be valid for whole lifetime of the allocation -
+you can free it after this call. String previously pointed by allocation's
+pUserData is freed from memory.
+
+If the flag was not used, the value of pointer `pUserData` is just copied to
+allocation's `pUserData`. It is opaque, so you can use it however you want - e.g.
+as a pointer, ordinal number or some handle to you own data.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ void* pUserData);
+
+/** \brief Creates new allocation that is in lost state from the beginning.
+
+It can be useful if you need a dummy, non-null allocation.
+
+You still need to destroy created object using vmaFreeMemory().
+
+Returned allocation is not tied to any specific memory pool or memory type and
+not bound to any image or buffer. It has size = 0. It cannot be turned into
+a real, non-empty allocation.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaCreateLostAllocation(
+ VmaAllocator allocator,
+ VmaAllocation* pAllocation);
+
+/** \brief Maps memory represented by given allocation and returns pointer to it.
+
+Maps memory represented by given allocation to make it accessible to CPU code.
+When succeeded, `*ppData` contains pointer to first byte of this memory.
+If the allocation is part of bigger `VkDeviceMemory` block, the pointer is
+correctly offseted to the beginning of region assigned to this particular
+allocation.
+
+Mapping is internally reference-counted and synchronized, so despite raw Vulkan
+function `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory`
+multiple times simultaneously, it is safe to call this function on allocations
+assigned to the same memory block. Actual Vulkan memory will be mapped on first
+mapping and unmapped on last unmapping.
+
+If the function succeeded, you must call vmaUnmapMemory() to unmap the
+allocation when mapping is no longer needed or before freeing the allocation, at
+the latest.
+
+It also safe to call this function multiple times on the same allocation. You
+must call vmaUnmapMemory() same number of times as you called vmaMapMemory().
+
+It is also safe to call this function on allocation created with
+#VMA_ALLOCATION_CREATE_MAPPED_BIT flag. Its memory stays mapped all the time.
+You must still call vmaUnmapMemory() same number of times as you called
+vmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the
+"0-th" mapping made automatically due to #VMA_ALLOCATION_CREATE_MAPPED_BIT flag.
+
+This function fails when used on allocation made in memory type that is not
+`HOST_VISIBLE`.
+
+This function always fails when called for allocation that was created with
+#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocations cannot be
+mapped.
+
+This function doesn't automatically flush or invalidate caches.
+If the allocation is made from a memory types that is not `HOST_COHERENT`,
+you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ void** ppData);
+
+/** \brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().
+
+For details, see description of vmaMapMemory().
+
+This function doesn't automatically flush or invalidate caches.
+If the allocation is made from a memory types that is not `HOST_COHERENT`,
+you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation);
+
+/** \brief Flushes memory of given allocation.
+
+Calls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation.
+It needs to be called after writing to a mapped memory for memory types that are not `HOST_COHERENT`.
+Unmap operation doesn't do that automatically.
+
+- `offset` must be relative to the beginning of allocation.
+- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.
+- `offset` and `size` don't have to be aligned.
+ They are internally rounded down/up to multiply of `nonCoherentAtomSize`.
+- If `size` is 0, this call is ignored.
+- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,
+ this call is ignored.
+
+Warning! `offset` and `size` are relative to the contents of given `allocation`.
+If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively.
+Do not pass allocation's offset as `offset`!!!
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+
+/** \brief Invalidates memory of given allocation.
+
+Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation.
+It needs to be called before reading from a mapped memory for memory types that are not `HOST_COHERENT`.
+Map operation doesn't do that automatically.
+
+- `offset` must be relative to the beginning of allocation.
+- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.
+- `offset` and `size` don't have to be aligned.
+ They are internally rounded down/up to multiply of `nonCoherentAtomSize`.
+- If `size` is 0, this call is ignored.
+- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,
+ this call is ignored.
+
+Warning! `offset` and `size` are relative to the contents of given `allocation`.
+If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively.
+Do not pass allocation's offset as `offset`!!!
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+
+/** \brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions.
+
+@param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked.
+
+Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,
+`VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are
+`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection).
+
+Possible return values:
+
+- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types.
+- `VK_SUCCESS` - corruption detection has been performed and succeeded.
+- `VK_ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations.
+ `VMA_ASSERT` is also fired in that case.
+- Other value: Error returned by Vulkan, e.g. memory mapping failure.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(VmaAllocator allocator, uint32_t memoryTypeBits);
+
+/** \struct VmaDefragmentationContext
+\brief Represents Opaque object that represents started defragmentation process.
+
+Fill structure #VmaDefragmentationInfo2 and call function vmaDefragmentationBegin() to create it.
+Call function vmaDefragmentationEnd() to destroy it.
+*/
+VK_DEFINE_HANDLE(VmaDefragmentationContext)
+
+/// Flags to be used in vmaDefragmentationBegin(). None at the moment. Reserved for future use.
+typedef enum VmaDefragmentationFlagBits {
+ VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaDefragmentationFlagBits;
+typedef VkFlags VmaDefragmentationFlags;
+
+/** \brief Parameters for defragmentation.
+
+To be used with function vmaDefragmentationBegin().
+*/
+typedef struct VmaDefragmentationInfo2 {
+ /** \brief Reserved for future use. Should be 0.
+ */
+ VmaDefragmentationFlags flags;
+ /** \brief Number of allocations in `pAllocations` array.
+ */
+ uint32_t allocationCount;
+ /** \brief Pointer to array of allocations that can be defragmented.
+
+ The array should have `allocationCount` elements.
+ The array should not contain nulls.
+ Elements in the array should be unique - same allocation cannot occur twice.
+ It is safe to pass allocations that are in the lost state - they are ignored.
+ All allocations not present in this array are considered non-moveable during this defragmentation.
+ */
+ VmaAllocation* pAllocations;
+ /** \brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation.
+
+ The array should have `allocationCount` elements.
+ You can pass null if you are not interested in this information.
+ */
+ VkBool32* pAllocationsChanged;
+ /** \brief Numer of pools in `pPools` array.
+ */
+ uint32_t poolCount;
+ /** \brief Either null or pointer to array of pools to be defragmented.
+
+ All the allocations in the specified pools can be moved during defragmentation
+ and there is no way to check if they were really moved as in `pAllocationsChanged`,
+ so you must query all the allocations in all these pools for new `VkDeviceMemory`
+ and offset using vmaGetAllocationInfo() if you might need to recreate buffers
+ and images bound to them.
+
+ The array should have `poolCount` elements.
+ The array should not contain nulls.
+ Elements in the array should be unique - same pool cannot occur twice.
+
+ Using this array is equivalent to specifying all allocations from the pools in `pAllocations`.
+ It might be more efficient.
+ */
+ VmaPool* pPools;
+ /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`.
+
+ `VK_WHOLE_SIZE` means no limit.
+ */
+ VkDeviceSize maxCpuBytesToMove;
+ /** \brief Maximum number of allocations that can be moved to a different place using transfers on CPU side, like `memcpy()`, `memmove()`.
+
+ `UINT32_MAX` means no limit.
+ */
+ uint32_t maxCpuAllocationsToMove;
+ /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to `commandBuffer`.
+
+ `VK_WHOLE_SIZE` means no limit.
+ */
+ VkDeviceSize maxGpuBytesToMove;
+ /** \brief Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to `commandBuffer`.
+
+ `UINT32_MAX` means no limit.
+ */
+ uint32_t maxGpuAllocationsToMove;
+ /** \brief Optional. Command buffer where GPU copy commands will be posted.
+
+ If not null, it must be a valid command buffer handle that supports Transfer queue type.
+ It must be in the recording state and outside of a render pass instance.
+ You need to submit it and make sure it finished execution before calling vmaDefragmentationEnd().
+
+ Passing null means that only CPU defragmentation will be performed.
+ */
+ VkCommandBuffer commandBuffer;
+} VmaDefragmentationInfo2;
+
+/** \brief Deprecated. Optional configuration parameters to be passed to function vmaDefragment().
+
+\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead.
+*/
+typedef struct VmaDefragmentationInfo {
+ /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places.
+
+ Default is `VK_WHOLE_SIZE`, which means no limit.
+ */
+ VkDeviceSize maxBytesToMove;
+ /** \brief Maximum number of allocations that can be moved to different place.
+
+ Default is `UINT32_MAX`, which means no limit.
+ */
+ uint32_t maxAllocationsToMove;
+} VmaDefragmentationInfo;
+
+/** \brief Statistics returned by function vmaDefragment(). */
+typedef struct VmaDefragmentationStats {
+ /// Total number of bytes that have been copied while moving allocations to different places.
+ VkDeviceSize bytesMoved;
+ /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects.
+ VkDeviceSize bytesFreed;
+ /// Number of allocations that have been moved to different places.
+ uint32_t allocationsMoved;
+ /// Number of empty `VkDeviceMemory` objects that have been released to the system.
+ uint32_t deviceMemoryBlocksFreed;
+} VmaDefragmentationStats;
+
+/** \brief Begins defragmentation process.
+
+@param allocator Allocator object.
+@param pInfo Structure filled with parameters of defragmentation.
+@param[out] pStats Optional. Statistics of defragmentation. You can pass null if you are not interested in this information.
+@param[out] pContext Context object that must be passed to vmaDefragmentationEnd() to finish defragmentation.
+@return `VK_SUCCESS` and `*pContext == null` if defragmentation finished within this function call. `VK_NOT_READY` and `*pContext != null` if defragmentation has been started and you need to call vmaDefragmentationEnd() to finish it. Negative value in case of error.
+
+Use this function instead of old, deprecated vmaDefragment().
+
+Warning! Between the call to vmaDefragmentationBegin() and vmaDefragmentationEnd():
+
+- You should not use any of allocations passed as `pInfo->pAllocations` or
+ any allocations that belong to pools passed as `pInfo->pPools`,
+ including calling vmaGetAllocationInfo(), vmaTouchAllocation(), or access
+ their data.
+- Some mutexes protecting internal data structures may be locked, so trying to
+ make or free any allocations, bind buffers or images, map memory, or launch
+ another simultaneous defragmentation in between may cause stall (when done on
+ another thread) or deadlock (when done on the same thread), unless you are
+ 100% sure that defragmented allocations are in different pools.
+- Information returned via `pStats` and `pInfo->pAllocationsChanged` are undefined.
+ They become valid after call to vmaDefragmentationEnd().
+- If `pInfo->commandBuffer` is not null, you must submit that command buffer
+ and make sure it finished execution before calling vmaDefragmentationEnd().
+
+For more information and important limitations regarding defragmentation, see documentation chapter:
+[Defragmentation](@ref defragmentation).
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationBegin(
+ VmaAllocator allocator,
+ const VmaDefragmentationInfo2* pInfo,
+ VmaDefragmentationStats* pStats,
+ VmaDefragmentationContext *pContext);
+
+/** \brief Ends defragmentation process.
+
+Use this function to finish defragmentation started by vmaDefragmentationBegin().
+It is safe to pass `context == null`. The function then does nothing.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationEnd(
+ VmaAllocator allocator,
+ VmaDefragmentationContext context);
+
+/** \brief Deprecated. Compacts memory by moving allocations.
+
+@param pAllocations Array of allocations that can be moved during this compation.
+@param allocationCount Number of elements in pAllocations and pAllocationsChanged arrays.
+@param[out] pAllocationsChanged Array of boolean values that will indicate whether matching allocation in pAllocations array has been moved. This parameter is optional. Pass null if you don't need this information.
+@param pDefragmentationInfo Configuration parameters. Optional - pass null to use default values.
+@param[out] pDefragmentationStats Statistics returned by the function. Optional - pass null if you don't need this information.
+@return `VK_SUCCESS` if completed, negative error code in case of error.
+
+\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead.
+
+This function works by moving allocations to different places (different
+`VkDeviceMemory` objects and/or different offsets) in order to optimize memory
+usage. Only allocations that are in `pAllocations` array can be moved. All other
+allocations are considered nonmovable in this call. Basic rules:
+
+- Only allocations made in memory types that have
+ `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`
+ flags can be compacted. You may pass other allocations but it makes no sense -
+ these will never be moved.
+- Custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT or
+ #VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag are not defragmented. Allocations
+ passed to this function that come from such pools are ignored.
+- Allocations created with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT or
+ created as dedicated allocations for any other reason are also ignored.
+- Both allocations made with or without #VMA_ALLOCATION_CREATE_MAPPED_BIT
+ flag can be compacted. If not persistently mapped, memory will be mapped
+ temporarily inside this function if needed.
+- You must not pass same #VmaAllocation object multiple times in `pAllocations` array.
+
+The function also frees empty `VkDeviceMemory` blocks.
+
+Warning: This function may be time-consuming, so you shouldn't call it too often
+(like after every resource creation/destruction).
+You can call it on special occasions (like when reloading a game level or
+when you just destroyed a lot of objects). Calling it every frame may be OK, but
+you should measure that on your platform.
+
+For more information, see [Defragmentation](@ref defragmentation) chapter.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment(
+ VmaAllocator allocator,
+ VmaAllocation* pAllocations,
+ size_t allocationCount,
+ VkBool32* pAllocationsChanged,
+ const VmaDefragmentationInfo *pDefragmentationInfo,
+ VmaDefragmentationStats* pDefragmentationStats);
+
+/** \brief Binds buffer to allocation.
+
+Binds specified buffer to region of memory represented by specified allocation.
+Gets `VkDeviceMemory` handle and offset from the allocation.
+If you want to create a buffer, allocate memory for it and bind them together separately,
+you should use this function for binding instead of standard `vkBindBufferMemory()`,
+because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple
+allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously
+(which is illegal in Vulkan).
+
+It is recommended to use function vmaCreateBuffer() instead of this one.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkBuffer buffer);
+
+/** \brief Binds buffer to allocation with additional parameters.
+
+@param allocationLocalOffset Additional offset to be added while binding, relative to the beginnig of the `allocation`. Normally it should be 0.
+@param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null.
+
+This function is similar to vmaBindBufferMemory(), but it provides additional parameters.
+
+If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag
+or with VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_1`. Otherwise the call fails.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkDeviceSize allocationLocalOffset,
+ VkBuffer buffer,
+ const void* pNext);
+
+/** \brief Binds image to allocation.
+
+Binds specified image to region of memory represented by specified allocation.
+Gets `VkDeviceMemory` handle and offset from the allocation.
+If you want to create an image, allocate memory for it and bind them together separately,
+you should use this function for binding instead of standard `vkBindImageMemory()`,
+because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple
+allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously
+(which is illegal in Vulkan).
+
+It is recommended to use function vmaCreateImage() instead of this one.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkImage image);
+
+/** \brief Binds image to allocation with additional parameters.
+
+@param allocationLocalOffset Additional offset to be added while binding, relative to the beginnig of the `allocation`. Normally it should be 0.
+@param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null.
+
+This function is similar to vmaBindImageMemory(), but it provides additional parameters.
+
+If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag
+or with VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_1`. Otherwise the call fails.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkDeviceSize allocationLocalOffset,
+ VkImage image,
+ const void* pNext);
+
+/**
+@param[out] pBuffer Buffer that was created.
+@param[out] pAllocation Allocation that was created.
+@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+
+This function automatically:
+
+-# Creates buffer.
+-# Allocates appropriate memory for it.
+-# Binds the buffer with the memory.
+
+If any of these operations fail, buffer and allocation are not created,
+returned value is negative error code, *pBuffer and *pAllocation are null.
+
+If the function succeeded, you must destroy both buffer and allocation when you
+no longer need them using either convenience function vmaDestroyBuffer() or
+separately, using `vkDestroyBuffer()` and vmaFreeMemory().
+
+If VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used,
+VK_KHR_dedicated_allocation extension is used internally to query driver whether
+it requires or prefers the new buffer to have dedicated allocation. If yes,
+and if dedicated allocation is possible (VmaAllocationCreateInfo::pool is null
+and VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated
+allocation for this buffer, just like when using
+VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer(
+ VmaAllocator allocator,
+ const VkBufferCreateInfo* pBufferCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkBuffer* pBuffer,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Destroys Vulkan buffer and frees allocated memory.
+
+This is just a convenience function equivalent to:
+
+\code
+vkDestroyBuffer(device, buffer, allocationCallbacks);
+vmaFreeMemory(allocator, allocation);
+\endcode
+
+It it safe to pass null as buffer and/or allocation.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(
+ VmaAllocator allocator,
+ VkBuffer buffer,
+ VmaAllocation allocation);
+
+/// Function similar to vmaCreateBuffer().
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
+ VmaAllocator allocator,
+ const VkImageCreateInfo* pImageCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkImage* pImage,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Destroys Vulkan image and frees allocated memory.
+
+This is just a convenience function equivalent to:
+
+\code
+vkDestroyImage(device, image, allocationCallbacks);
+vmaFreeMemory(allocator, allocation);
+\endcode
+
+It it safe to pass null as image and/or allocation.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
+ VmaAllocator allocator,
+ VkImage image,
+ VmaAllocation allocation);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AMD_VULKAN_MEMORY_ALLOCATOR_H
+
+// For Visual Studio IntelliSense.
+#if defined(__cplusplus) && defined(__INTELLISENSE__)
+#define VMA_IMPLEMENTATION
+#endif
+
+#ifdef VMA_IMPLEMENTATION
+#undef VMA_IMPLEMENTATION
+
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+
+/*******************************************************************************
+CONFIGURATION SECTION
+
+Define some of these macros before each #include of this header or change them
+here if you need other then default behavior depending on your environment.
+*/
+
+/*
+Define this macro to 1 to make the library fetch pointers to Vulkan functions
+internally, like:
+
+ vulkanFunctions.vkAllocateMemory = &vkAllocateMemory;
+
+Define to 0 if you are going to provide you own pointers to Vulkan functions via
+VmaAllocatorCreateInfo::pVulkanFunctions.
+*/
+#if !defined(VMA_STATIC_VULKAN_FUNCTIONS) && !defined(VK_NO_PROTOTYPES)
+#define VMA_STATIC_VULKAN_FUNCTIONS 1
+#endif
+
+// Define this macro to 1 to make the library use STL containers instead of its own implementation.
+//#define VMA_USE_STL_CONTAINERS 1
+
+/* Set this macro to 1 to make the library including and using STL containers:
+std::pair, std::vector, std::list, std::unordered_map.
+
+Set it to 0 or undefined to make the library using its own implementation of
+the containers.
+*/
+#if VMA_USE_STL_CONTAINERS
+ #define VMA_USE_STL_VECTOR 1
+ #define VMA_USE_STL_UNORDERED_MAP 1
+ #define VMA_USE_STL_LIST 1
+#endif
+
+#ifndef VMA_USE_STL_SHARED_MUTEX
+ // Compiler conforms to C++17.
+ #if __cplusplus >= 201703L
+ #define VMA_USE_STL_SHARED_MUTEX 1
+ // Visual studio defines __cplusplus properly only when passed additional parameter: /Zc:__cplusplus
+ // Otherwise it's always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2.
+ // See: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
+ #elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918 && __cplusplus == 199711L && _MSVC_LANG >= 201703L
+ #define VMA_USE_STL_SHARED_MUTEX 1
+ #else
+ #define VMA_USE_STL_SHARED_MUTEX 0
+ #endif
+#endif
+
+/*
+THESE INCLUDES ARE NOT ENABLED BY DEFAULT.
+Library has its own container implementation.
+*/
+#if VMA_USE_STL_VECTOR
+ #include <vector>
+#endif
+
+#if VMA_USE_STL_UNORDERED_MAP
+ #include <unordered_map>
+#endif
+
+#if VMA_USE_STL_LIST
+ #include <list>
+#endif
+
+/*
+Following headers are used in this CONFIGURATION section only, so feel free to
+remove them if not needed.
+*/
+#include <cassert> // for assert
+#include <algorithm> // for min, max
+#include <mutex>
+
+#ifndef VMA_NULL
+ // Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.
+ #define VMA_NULL nullptr
+#endif
+
+#if defined(__ANDROID_API__) && (__ANDROID_API__ < 16)
+#include <cstdlib>
+void *aligned_alloc(size_t alignment, size_t size)
+{
+ // alignment must be >= sizeof(void*)
+ if(alignment < sizeof(void*))
+ {
+ alignment = sizeof(void*);
+ }
+
+ return memalign(alignment, size);
+}
+#elif defined(__APPLE__) || defined(__ANDROID__) || (defined(__linux__) && defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC))
+#include <cstdlib>
+void *aligned_alloc(size_t alignment, size_t size)
+{
+ // alignment must be >= sizeof(void*)
+ if(alignment < sizeof(void*))
+ {
+ alignment = sizeof(void*);
+ }
+
+ void *pointer;
+ if(posix_memalign(&pointer, alignment, size) == 0)
+ return pointer;
+ return VMA_NULL;
+}
+#endif
+
+// If your compiler is not compatible with C++11 and definition of
+// aligned_alloc() function is missing, uncommeting following line may help:
+
+//#include <malloc.h>
+
+// Normal assert to check for programmer's errors, especially in Debug configuration.
+#ifndef VMA_ASSERT
+ #ifdef _DEBUG
+ #define VMA_ASSERT(expr) assert(expr)
+ #else
+ #define VMA_ASSERT(expr)
+ #endif
+#endif
+
+// Assert that will be called very often, like inside data structures e.g. operator[].
+// Making it non-empty can make program slow.
+#ifndef VMA_HEAVY_ASSERT
+ #ifdef _DEBUG
+ #define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr)
+ #else
+ #define VMA_HEAVY_ASSERT(expr)
+ #endif
+#endif
+
+#ifndef VMA_ALIGN_OF
+ #define VMA_ALIGN_OF(type) (__alignof(type))
+#endif
+
+#ifndef VMA_SYSTEM_ALIGNED_MALLOC
+ #if defined(_WIN32)
+ #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (_aligned_malloc((size), (alignment)))
+ #else
+ #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (aligned_alloc((alignment), (size) ))
+ #endif
+#endif
+
+#ifndef VMA_SYSTEM_FREE
+ #if defined(_WIN32)
+ #define VMA_SYSTEM_FREE(ptr) _aligned_free(ptr)
+ #else
+ #define VMA_SYSTEM_FREE(ptr) free(ptr)
+ #endif
+#endif
+
+#ifndef VMA_MIN
+ #define VMA_MIN(v1, v2) (std::min((v1), (v2)))
+#endif
+
+#ifndef VMA_MAX
+ #define VMA_MAX(v1, v2) (std::max((v1), (v2)))
+#endif
+
+#ifndef VMA_SWAP
+ #define VMA_SWAP(v1, v2) std::swap((v1), (v2))
+#endif
+
+#ifndef VMA_SORT
+ #define VMA_SORT(beg, end, cmp) std::sort(beg, end, cmp)
+#endif
+
+#ifndef VMA_DEBUG_LOG
+ #define VMA_DEBUG_LOG(format, ...)
+ /*
+ #define VMA_DEBUG_LOG(format, ...) do { \
+ printf(format, __VA_ARGS__); \
+ printf("\n"); \
+ } while(false)
+ */
+#endif
+
+// Define this macro to 1 to enable functions: vmaBuildStatsString, vmaFreeStatsString.
+#if VMA_STATS_STRING_ENABLED
+ static inline void VmaUint32ToStr(char* outStr, size_t strLen, uint32_t num)
+ {
+ snprintf(outStr, strLen, "%u", static_cast<unsigned int>(num));
+ }
+ static inline void VmaUint64ToStr(char* outStr, size_t strLen, uint64_t num)
+ {
+ snprintf(outStr, strLen, "%llu", static_cast<unsigned long long>(num));
+ }
+ static inline void VmaPtrToStr(char* outStr, size_t strLen, const void* ptr)
+ {
+ snprintf(outStr, strLen, "%p", ptr);
+ }
+#endif
+
+#ifndef VMA_MUTEX
+ class VmaMutex
+ {
+ public:
+ void Lock() { m_Mutex.lock(); }
+ void Unlock() { m_Mutex.unlock(); }
+ private:
+ std::mutex m_Mutex;
+ };
+ #define VMA_MUTEX VmaMutex
+#endif
+
+// Read-write mutex, where "read" is shared access, "write" is exclusive access.
+#ifndef VMA_RW_MUTEX
+ #if VMA_USE_STL_SHARED_MUTEX
+ // Use std::shared_mutex from C++17.
+ #include <shared_mutex>
+ class VmaRWMutex
+ {
+ public:
+ void LockRead() { m_Mutex.lock_shared(); }
+ void UnlockRead() { m_Mutex.unlock_shared(); }
+ void LockWrite() { m_Mutex.lock(); }
+ void UnlockWrite() { m_Mutex.unlock(); }
+ private:
+ std::shared_mutex m_Mutex;
+ };
+ #define VMA_RW_MUTEX VmaRWMutex
+ #elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600
+ // Use SRWLOCK from WinAPI.
+ // Minimum supported client = Windows Vista, server = Windows Server 2008.
+ class VmaRWMutex
+ {
+ public:
+ VmaRWMutex() { InitializeSRWLock(&m_Lock); }
+ void LockRead() { AcquireSRWLockShared(&m_Lock); }
+ void UnlockRead() { ReleaseSRWLockShared(&m_Lock); }
+ void LockWrite() { AcquireSRWLockExclusive(&m_Lock); }
+ void UnlockWrite() { ReleaseSRWLockExclusive(&m_Lock); }
+ private:
+ SRWLOCK m_Lock;
+ };
+ #define VMA_RW_MUTEX VmaRWMutex
+ #else
+ // Less efficient fallback: Use normal mutex.
+ class VmaRWMutex
+ {
+ public:
+ void LockRead() { m_Mutex.Lock(); }
+ void UnlockRead() { m_Mutex.Unlock(); }
+ void LockWrite() { m_Mutex.Lock(); }
+ void UnlockWrite() { m_Mutex.Unlock(); }
+ private:
+ VMA_MUTEX m_Mutex;
+ };
+ #define VMA_RW_MUTEX VmaRWMutex
+ #endif // #if VMA_USE_STL_SHARED_MUTEX
+#endif // #ifndef VMA_RW_MUTEX
+
+/*
+If providing your own implementation, you need to implement a subset of std::atomic.
+*/
+#ifndef VMA_ATOMIC_UINT32
+ #include <atomic>
+ #define VMA_ATOMIC_UINT32 std::atomic<uint32_t>
+#endif
+
+#ifndef VMA_ATOMIC_UINT64
+ #include <atomic>
+ #define VMA_ATOMIC_UINT64 std::atomic<uint64_t>
+#endif
+
+#ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY
+ /**
+ Every allocation will have its own memory block.
+ Define to 1 for debugging purposes only.
+ */
+ #define VMA_DEBUG_ALWAYS_DEDICATED_MEMORY (0)
+#endif
+
+#ifndef VMA_DEBUG_ALIGNMENT
+ /**
+ Minimum alignment of all allocations, in bytes.
+ Set to more than 1 for debugging purposes only. Must be power of two.
+ */
+ #define VMA_DEBUG_ALIGNMENT (1)
+#endif
+
+#ifndef VMA_DEBUG_MARGIN
+ /**
+ Minimum margin before and after every allocation, in bytes.
+ Set nonzero for debugging purposes only.
+ */
+ #define VMA_DEBUG_MARGIN (0)
+#endif
+
+#ifndef VMA_DEBUG_INITIALIZE_ALLOCATIONS
+ /**
+ Define this macro to 1 to automatically fill new allocations and destroyed
+ allocations with some bit pattern.
+ */
+ #define VMA_DEBUG_INITIALIZE_ALLOCATIONS (0)
+#endif
+
+#ifndef VMA_DEBUG_DETECT_CORRUPTION
+ /**
+ Define this macro to 1 together with non-zero value of VMA_DEBUG_MARGIN to
+ enable writing magic value to the margin before and after every allocation and
+ validating it, so that memory corruptions (out-of-bounds writes) are detected.
+ */
+ #define VMA_DEBUG_DETECT_CORRUPTION (0)
+#endif
+
+#ifndef VMA_DEBUG_GLOBAL_MUTEX
+ /**
+ Set this to 1 for debugging purposes only, to enable single mutex protecting all
+ entry calls to the library. Can be useful for debugging multithreading issues.
+ */
+ #define VMA_DEBUG_GLOBAL_MUTEX (0)
+#endif
+
+#ifndef VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY
+ /**
+ Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity.
+ Set to more than 1 for debugging purposes only. Must be power of two.
+ */
+ #define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1)
+#endif
+
+#ifndef VMA_SMALL_HEAP_MAX_SIZE
+ /// Maximum size of a memory heap in Vulkan to consider it "small".
+ #define VMA_SMALL_HEAP_MAX_SIZE (1024ull * 1024 * 1024)
+#endif
+
+#ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE
+ /// Default size of a block allocated as single VkDeviceMemory from a "large" heap.
+ #define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ull * 1024 * 1024)
+#endif
+
+#ifndef VMA_CLASS_NO_COPY
+ #define VMA_CLASS_NO_COPY(className) \
+ private: \
+ className(const className&) = delete; \
+ className& operator=(const className&) = delete;
+#endif
+
+static const uint32_t VMA_FRAME_INDEX_LOST = UINT32_MAX;
+
+// Decimal 2139416166, float NaN, little-endian binary 66 E6 84 7F.
+static const uint32_t VMA_CORRUPTION_DETECTION_MAGIC_VALUE = 0x7F84E666;
+
+static const uint8_t VMA_ALLOCATION_FILL_PATTERN_CREATED = 0xDC;
+static const uint8_t VMA_ALLOCATION_FILL_PATTERN_DESTROYED = 0xEF;
+
+/*******************************************************************************
+END OF CONFIGURATION
+*/
+
+static const uint32_t VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET = 0x10000000u;
+
+static VkAllocationCallbacks VmaEmptyAllocationCallbacks = {
+ VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL };
+
+// Returns number of bits set to 1 in (v).
+static inline uint32_t VmaCountBitsSet(uint32_t v)
+{
+ uint32_t c = v - ((v >> 1) & 0x55555555);
+ c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
+ c = ((c >> 4) + c) & 0x0F0F0F0F;
+ c = ((c >> 8) + c) & 0x00FF00FF;
+ c = ((c >> 16) + c) & 0x0000FFFF;
+ return c;
+}
+
+// Aligns given value up to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 16.
+// Use types like uint32_t, uint64_t as T.
+template <typename T>
+static inline T VmaAlignUp(T val, T align)
+{
+ return (val + align - 1) / align * align;
+}
+// Aligns given value down to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 8.
+// Use types like uint32_t, uint64_t as T.
+template <typename T>
+static inline T VmaAlignDown(T val, T align)
+{
+ return val / align * align;
+}
+
+// Division with mathematical rounding to nearest number.
+template <typename T>
+static inline T VmaRoundDiv(T x, T y)
+{
+ return (x + (y / (T)2)) / y;
+}
+
+/*
+Returns true if given number is a power of two.
+T must be unsigned integer number or signed integer but always nonnegative.
+For 0 returns true.
+*/
+template <typename T>
+inline bool VmaIsPow2(T x)
+{
+ return (x & (x-1)) == 0;
+}
+
+// Returns smallest power of 2 greater or equal to v.
+static inline uint32_t VmaNextPow2(uint32_t v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+ return v;
+}
+static inline uint64_t VmaNextPow2(uint64_t v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v |= v >> 32;
+ v++;
+ return v;
+}
+
+// Returns largest power of 2 less or equal to v.
+static inline uint32_t VmaPrevPow2(uint32_t v)
+{
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v = v ^ (v >> 1);
+ return v;
+}
+static inline uint64_t VmaPrevPow2(uint64_t v)
+{
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v |= v >> 32;
+ v = v ^ (v >> 1);
+ return v;
+}
+
+static inline bool VmaStrIsEmpty(const char* pStr)
+{
+ return pStr == VMA_NULL || *pStr == '\0';
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+static const char* VmaAlgorithmToStr(uint32_t algorithm)
+{
+ switch(algorithm)
+ {
+ case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
+ return "Linear";
+ case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT:
+ return "Buddy";
+ case 0:
+ return "Default";
+ default:
+ VMA_ASSERT(0);
+ return "";
+ }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+#ifndef VMA_SORT
+
+template<typename Iterator, typename Compare>
+Iterator VmaQuickSortPartition(Iterator beg, Iterator end, Compare cmp)
+{
+ Iterator centerValue = end; --centerValue;
+ Iterator insertIndex = beg;
+ for(Iterator memTypeIndex = beg; memTypeIndex < centerValue; ++memTypeIndex)
+ {
+ if(cmp(*memTypeIndex, *centerValue))
+ {
+ if(insertIndex != memTypeIndex)
+ {
+ VMA_SWAP(*memTypeIndex, *insertIndex);
+ }
+ ++insertIndex;
+ }
+ }
+ if(insertIndex != centerValue)
+ {
+ VMA_SWAP(*insertIndex, *centerValue);
+ }
+ return insertIndex;
+}
+
+template<typename Iterator, typename Compare>
+void VmaQuickSort(Iterator beg, Iterator end, Compare cmp)
+{
+ if(beg < end)
+ {
+ Iterator it = VmaQuickSortPartition<Iterator, Compare>(beg, end, cmp);
+ VmaQuickSort<Iterator, Compare>(beg, it, cmp);
+ VmaQuickSort<Iterator, Compare>(it + 1, end, cmp);
+ }
+}
+
+#define VMA_SORT(beg, end, cmp) VmaQuickSort(beg, end, cmp)
+
+#endif // #ifndef VMA_SORT
+
+/*
+Returns true if two memory blocks occupy overlapping pages.
+ResourceA must be in less memory offset than ResourceB.
+
+Algorithm is based on "Vulkan 1.0.39 - A Specification (with all registered Vulkan extensions)"
+chapter 11.6 "Resource Memory Association", paragraph "Buffer-Image Granularity".
+*/
+static inline bool VmaBlocksOnSamePage(
+ VkDeviceSize resourceAOffset,
+ VkDeviceSize resourceASize,
+ VkDeviceSize resourceBOffset,
+ VkDeviceSize pageSize)
+{
+ VMA_ASSERT(resourceAOffset + resourceASize <= resourceBOffset && resourceASize > 0 && pageSize > 0);
+ VkDeviceSize resourceAEnd = resourceAOffset + resourceASize - 1;
+ VkDeviceSize resourceAEndPage = resourceAEnd & ~(pageSize - 1);
+ VkDeviceSize resourceBStart = resourceBOffset;
+ VkDeviceSize resourceBStartPage = resourceBStart & ~(pageSize - 1);
+ return resourceAEndPage == resourceBStartPage;
+}
+
+enum VmaSuballocationType
+{
+ VMA_SUBALLOCATION_TYPE_FREE = 0,
+ VMA_SUBALLOCATION_TYPE_UNKNOWN = 1,
+ VMA_SUBALLOCATION_TYPE_BUFFER = 2,
+ VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3,
+ VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4,
+ VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5,
+ VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF
+};
+
+/*
+Returns true if given suballocation types could conflict and must respect
+VkPhysicalDeviceLimits::bufferImageGranularity. They conflict if one is buffer
+or linear image and another one is optimal image. If type is unknown, behave
+conservatively.
+*/
+static inline bool VmaIsBufferImageGranularityConflict(
+ VmaSuballocationType suballocType1,
+ VmaSuballocationType suballocType2)
+{
+ if(suballocType1 > suballocType2)
+ {
+ VMA_SWAP(suballocType1, suballocType2);
+ }
+
+ switch(suballocType1)
+ {
+ case VMA_SUBALLOCATION_TYPE_FREE:
+ return false;
+ case VMA_SUBALLOCATION_TYPE_UNKNOWN:
+ return true;
+ case VMA_SUBALLOCATION_TYPE_BUFFER:
+ return
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;
+ case VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN:
+ return
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR ||
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;
+ case VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR:
+ return
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;
+ case VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL:
+ return false;
+ default:
+ VMA_ASSERT(0);
+ return true;
+ }
+}
+
+static void VmaWriteMagicValue(void* pData, VkDeviceSize offset)
+{
+#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION
+ uint32_t* pDst = (uint32_t*)((char*)pData + offset);
+ const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);
+ for(size_t i = 0; i < numberCount; ++i, ++pDst)
+ {
+ *pDst = VMA_CORRUPTION_DETECTION_MAGIC_VALUE;
+ }
+#else
+ // no-op
+#endif
+}
+
+static bool VmaValidateMagicValue(const void* pData, VkDeviceSize offset)
+{
+#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION
+ const uint32_t* pSrc = (const uint32_t*)((const char*)pData + offset);
+ const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);
+ for(size_t i = 0; i < numberCount; ++i, ++pSrc)
+ {
+ if(*pSrc != VMA_CORRUPTION_DETECTION_MAGIC_VALUE)
+ {
+ return false;
+ }
+ }
+#endif
+ return true;
+}
+
+/*
+Fills structure with parameters of an example buffer to be used for transfers
+during GPU memory defragmentation.
+*/
+static void VmaFillGpuDefragmentationBufferCreateInfo(VkBufferCreateInfo& outBufCreateInfo)
+{
+ memset(&outBufCreateInfo, 0, sizeof(outBufCreateInfo));
+ outBufCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ outBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ outBufCreateInfo.size = (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE; // Example size.
+}
+
+// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope).
+struct VmaMutexLock
+{
+ VMA_CLASS_NO_COPY(VmaMutexLock)
+public:
+ VmaMutexLock(VMA_MUTEX& mutex, bool useMutex = true) :
+ m_pMutex(useMutex ? &mutex : VMA_NULL)
+ { if(m_pMutex) { m_pMutex->Lock(); } }
+ ~VmaMutexLock()
+ { if(m_pMutex) { m_pMutex->Unlock(); } }
+private:
+ VMA_MUTEX* m_pMutex;
+};
+
+// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading.
+struct VmaMutexLockRead
+{
+ VMA_CLASS_NO_COPY(VmaMutexLockRead)
+public:
+ VmaMutexLockRead(VMA_RW_MUTEX& mutex, bool useMutex) :
+ m_pMutex(useMutex ? &mutex : VMA_NULL)
+ { if(m_pMutex) { m_pMutex->LockRead(); } }
+ ~VmaMutexLockRead() { if(m_pMutex) { m_pMutex->UnlockRead(); } }
+private:
+ VMA_RW_MUTEX* m_pMutex;
+};
+
+// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing.
+struct VmaMutexLockWrite
+{
+ VMA_CLASS_NO_COPY(VmaMutexLockWrite)
+public:
+ VmaMutexLockWrite(VMA_RW_MUTEX& mutex, bool useMutex) :
+ m_pMutex(useMutex ? &mutex : VMA_NULL)
+ { if(m_pMutex) { m_pMutex->LockWrite(); } }
+ ~VmaMutexLockWrite() { if(m_pMutex) { m_pMutex->UnlockWrite(); } }
+private:
+ VMA_RW_MUTEX* m_pMutex;
+};
+
+#if VMA_DEBUG_GLOBAL_MUTEX
+ static VMA_MUTEX gDebugGlobalMutex;
+ #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true);
+#else
+ #define VMA_DEBUG_GLOBAL_MUTEX_LOCK
+#endif
+
+// Minimum size of a free suballocation to register it in the free suballocation collection.
+static const VkDeviceSize VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER = 16;
+
+/*
+Performs binary search and returns iterator to first element that is greater or
+equal to (key), according to comparison (cmp).
+
+Cmp should return true if first argument is less than second argument.
+
+Returned value is the found element, if present in the collection or place where
+new element with value (key) should be inserted.
+*/
+template <typename CmpLess, typename IterT, typename KeyT>
+static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT &key, const CmpLess& cmp)
+{
+ size_t down = 0, up = (end - beg);
+ while(down < up)
+ {
+ const size_t mid = (down + up) / 2;
+ if(cmp(*(beg+mid), key))
+ {
+ down = mid + 1;
+ }
+ else
+ {
+ up = mid;
+ }
+ }
+ return beg + down;
+}
+
+template<typename CmpLess, typename IterT, typename KeyT>
+IterT VmaBinaryFindSorted(const IterT& beg, const IterT& end, const KeyT& value, const CmpLess& cmp)
+{
+ IterT it = VmaBinaryFindFirstNotLess<CmpLess, IterT, KeyT>(
+ beg, end, value, cmp);
+ if(it == end ||
+ (!cmp(*it, value) && !cmp(value, *it)))
+ {
+ return it;
+ }
+ return end;
+}
+
+/*
+Returns true if all pointers in the array are not-null and unique.
+Warning! O(n^2) complexity. Use only inside VMA_HEAVY_ASSERT.
+T must be pointer type, e.g. VmaAllocation, VmaPool.
+*/
+template<typename T>
+static bool VmaValidatePointerArray(uint32_t count, const T* arr)
+{
+ for(uint32_t i = 0; i < count; ++i)
+ {
+ const T iPtr = arr[i];
+ if(iPtr == VMA_NULL)
+ {
+ return false;
+ }
+ for(uint32_t j = i + 1; j < count; ++j)
+ {
+ if(iPtr == arr[j])
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Memory allocation
+
+static void* VmaMalloc(const VkAllocationCallbacks* pAllocationCallbacks, size_t size, size_t alignment)
+{
+ if((pAllocationCallbacks != VMA_NULL) &&
+ (pAllocationCallbacks->pfnAllocation != VMA_NULL))
+ {
+ return (*pAllocationCallbacks->pfnAllocation)(
+ pAllocationCallbacks->pUserData,
+ size,
+ alignment,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ }
+ else
+ {
+ return VMA_SYSTEM_ALIGNED_MALLOC(size, alignment);
+ }
+}
+
+static void VmaFree(const VkAllocationCallbacks* pAllocationCallbacks, void* ptr)
+{
+ if((pAllocationCallbacks != VMA_NULL) &&
+ (pAllocationCallbacks->pfnFree != VMA_NULL))
+ {
+ (*pAllocationCallbacks->pfnFree)(pAllocationCallbacks->pUserData, ptr);
+ }
+ else
+ {
+ VMA_SYSTEM_FREE(ptr);
+ }
+}
+
+template<typename T>
+static T* VmaAllocate(const VkAllocationCallbacks* pAllocationCallbacks)
+{
+ return (T*)VmaMalloc(pAllocationCallbacks, sizeof(T), VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static T* VmaAllocateArray(const VkAllocationCallbacks* pAllocationCallbacks, size_t count)
+{
+ return (T*)VmaMalloc(pAllocationCallbacks, sizeof(T) * count, VMA_ALIGN_OF(T));
+}
+
+#define vma_new(allocator, type) new(VmaAllocate<type>(allocator))(type)
+
+#define vma_new_array(allocator, type, count) new(VmaAllocateArray<type>((allocator), (count)))(type)
+
+template<typename T>
+static void vma_delete(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr)
+{
+ ptr->~T();
+ VmaFree(pAllocationCallbacks, ptr);
+}
+
+template<typename T>
+static void vma_delete_array(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr, size_t count)
+{
+ if(ptr != VMA_NULL)
+ {
+ for(size_t i = count; i--; )
+ {
+ ptr[i].~T();
+ }
+ VmaFree(pAllocationCallbacks, ptr);
+ }
+}
+
+static char* VmaCreateStringCopy(const VkAllocationCallbacks* allocs, const char* srcStr)
+{
+ if(srcStr != VMA_NULL)
+ {
+ const size_t len = strlen(srcStr);
+ char* const result = vma_new_array(allocs, char, len + 1);
+ memcpy(result, srcStr, len + 1);
+ return result;
+ }
+ else
+ {
+ return VMA_NULL;
+ }
+}
+
+static void VmaFreeString(const VkAllocationCallbacks* allocs, char* str)
+{
+ if(str != VMA_NULL)
+ {
+ const size_t len = strlen(str);
+ vma_delete_array(allocs, str, len + 1);
+ }
+}
+
+// STL-compatible allocator.
+template<typename T>
+class VmaStlAllocator
+{
+public:
+ const VkAllocationCallbacks* const m_pCallbacks;
+ typedef T value_type;
+
+ VmaStlAllocator(const VkAllocationCallbacks* pCallbacks) : m_pCallbacks(pCallbacks) { }
+ template<typename U> VmaStlAllocator(const VmaStlAllocator<U>& src) : m_pCallbacks(src.m_pCallbacks) { }
+
+ T* allocate(size_t n) { return VmaAllocateArray<T>(m_pCallbacks, n); }
+ void deallocate(T* p, size_t n) { VmaFree(m_pCallbacks, p); }
+
+ template<typename U>
+ bool operator==(const VmaStlAllocator<U>& rhs) const
+ {
+ return m_pCallbacks == rhs.m_pCallbacks;
+ }
+ template<typename U>
+ bool operator!=(const VmaStlAllocator<U>& rhs) const
+ {
+ return m_pCallbacks != rhs.m_pCallbacks;
+ }
+
+ VmaStlAllocator& operator=(const VmaStlAllocator& x) = delete;
+};
+
+#if VMA_USE_STL_VECTOR
+
+#define VmaVector std::vector
+
+template<typename T, typename allocatorT>
+static void VmaVectorInsert(std::vector<T, allocatorT>& vec, size_t index, const T& item)
+{
+ vec.insert(vec.begin() + index, item);
+}
+
+template<typename T, typename allocatorT>
+static void VmaVectorRemove(std::vector<T, allocatorT>& vec, size_t index)
+{
+ vec.erase(vec.begin() + index);
+}
+
+#else // #if VMA_USE_STL_VECTOR
+
+/* Class with interface compatible with subset of std::vector.
+T must be POD because constructors and destructors are not called and memcpy is
+used for these objects. */
+template<typename T, typename AllocatorT>
+class VmaVector
+{
+public:
+ typedef T value_type;
+
+ VmaVector(const AllocatorT& allocator) :
+ m_Allocator(allocator),
+ m_pArray(VMA_NULL),
+ m_Count(0),
+ m_Capacity(0)
+ {
+ }
+
+ VmaVector(size_t count, const AllocatorT& allocator) :
+ m_Allocator(allocator),
+ m_pArray(count ? (T*)VmaAllocateArray<T>(allocator.m_pCallbacks, count) : VMA_NULL),
+ m_Count(count),
+ m_Capacity(count)
+ {
+ }
+
+ // This version of the constructor is here for compatibility with pre-C++14 std::vector.
+ // value is unused.
+ VmaVector(size_t count, const T& value, const AllocatorT& allocator)
+ : VmaVector(count, allocator) {}
+
+ VmaVector(const VmaVector<T, AllocatorT>& src) :
+ m_Allocator(src.m_Allocator),
+ m_pArray(src.m_Count ? (T*)VmaAllocateArray<T>(src.m_Allocator.m_pCallbacks, src.m_Count) : VMA_NULL),
+ m_Count(src.m_Count),
+ m_Capacity(src.m_Count)
+ {
+ if(m_Count != 0)
+ {
+ memcpy(m_pArray, src.m_pArray, m_Count * sizeof(T));
+ }
+ }
+
+ ~VmaVector()
+ {
+ VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+ }
+
+ VmaVector& operator=(const VmaVector<T, AllocatorT>& rhs)
+ {
+ if(&rhs != this)
+ {
+ resize(rhs.m_Count);
+ if(m_Count != 0)
+ {
+ memcpy(m_pArray, rhs.m_pArray, m_Count * sizeof(T));
+ }
+ }
+ return *this;
+ }
+
+ bool empty() const { return m_Count == 0; }
+ size_t size() const { return m_Count; }
+ T* data() { return m_pArray; }
+ const T* data() const { return m_pArray; }
+
+ T& operator[](size_t index)
+ {
+ VMA_HEAVY_ASSERT(index < m_Count);
+ return m_pArray[index];
+ }
+ const T& operator[](size_t index) const
+ {
+ VMA_HEAVY_ASSERT(index < m_Count);
+ return m_pArray[index];
+ }
+
+ T& front()
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ return m_pArray[0];
+ }
+ const T& front() const
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ return m_pArray[0];
+ }
+ T& back()
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ return m_pArray[m_Count - 1];
+ }
+ const T& back() const
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ return m_pArray[m_Count - 1];
+ }
+
+ void reserve(size_t newCapacity, bool freeMemory = false)
+ {
+ newCapacity = VMA_MAX(newCapacity, m_Count);
+
+ if((newCapacity < m_Capacity) && !freeMemory)
+ {
+ newCapacity = m_Capacity;
+ }
+
+ if(newCapacity != m_Capacity)
+ {
+ T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator, newCapacity) : VMA_NULL;
+ if(m_Count != 0)
+ {
+ memcpy(newArray, m_pArray, m_Count * sizeof(T));
+ }
+ VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+ m_Capacity = newCapacity;
+ m_pArray = newArray;
+ }
+ }
+
+ void resize(size_t newCount, bool freeMemory = false)
+ {
+ size_t newCapacity = m_Capacity;
+ if(newCount > m_Capacity)
+ {
+ newCapacity = VMA_MAX(newCount, VMA_MAX(m_Capacity * 3 / 2, (size_t)8));
+ }
+ else if(freeMemory)
+ {
+ newCapacity = newCount;
+ }
+
+ if(newCapacity != m_Capacity)
+ {
+ T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator.m_pCallbacks, newCapacity) : VMA_NULL;
+ const size_t elementsToCopy = VMA_MIN(m_Count, newCount);
+ if(elementsToCopy != 0)
+ {
+ memcpy(newArray, m_pArray, elementsToCopy * sizeof(T));
+ }
+ VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+ m_Capacity = newCapacity;
+ m_pArray = newArray;
+ }
+
+ m_Count = newCount;
+ }
+
+ void clear(bool freeMemory = false)
+ {
+ resize(0, freeMemory);
+ }
+
+ void insert(size_t index, const T& src)
+ {
+ VMA_HEAVY_ASSERT(index <= m_Count);
+ const size_t oldCount = size();
+ resize(oldCount + 1);
+ if(index < oldCount)
+ {
+ memmove(m_pArray + (index + 1), m_pArray + index, (oldCount - index) * sizeof(T));
+ }
+ m_pArray[index] = src;
+ }
+
+ void remove(size_t index)
+ {
+ VMA_HEAVY_ASSERT(index < m_Count);
+ const size_t oldCount = size();
+ if(index < oldCount - 1)
+ {
+ memmove(m_pArray + index, m_pArray + (index + 1), (oldCount - index - 1) * sizeof(T));
+ }
+ resize(oldCount - 1);
+ }
+
+ void push_back(const T& src)
+ {
+ const size_t newIndex = size();
+ resize(newIndex + 1);
+ m_pArray[newIndex] = src;
+ }
+
+ void pop_back()
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ resize(size() - 1);
+ }
+
+ void push_front(const T& src)
+ {
+ insert(0, src);
+ }
+
+ void pop_front()
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ remove(0);
+ }
+
+ typedef T* iterator;
+
+ iterator begin() { return m_pArray; }
+ iterator end() { return m_pArray + m_Count; }
+
+private:
+ AllocatorT m_Allocator;
+ T* m_pArray;
+ size_t m_Count;
+ size_t m_Capacity;
+};
+
+template<typename T, typename allocatorT>
+static void VmaVectorInsert(VmaVector<T, allocatorT>& vec, size_t index, const T& item)
+{
+ vec.insert(index, item);
+}
+
+template<typename T, typename allocatorT>
+static void VmaVectorRemove(VmaVector<T, allocatorT>& vec, size_t index)
+{
+ vec.remove(index);
+}
+
+#endif // #if VMA_USE_STL_VECTOR
+
+template<typename CmpLess, typename VectorT>
+size_t VmaVectorInsertSorted(VectorT& vector, const typename VectorT::value_type& value)
+{
+ const size_t indexToInsert = VmaBinaryFindFirstNotLess(
+ vector.data(),
+ vector.data() + vector.size(),
+ value,
+ CmpLess()) - vector.data();
+ VmaVectorInsert(vector, indexToInsert, value);
+ return indexToInsert;
+}
+
+template<typename CmpLess, typename VectorT>
+bool VmaVectorRemoveSorted(VectorT& vector, const typename VectorT::value_type& value)
+{
+ CmpLess comparator;
+ typename VectorT::iterator it = VmaBinaryFindFirstNotLess(
+ vector.begin(),
+ vector.end(),
+ value,
+ comparator);
+ if((it != vector.end()) && !comparator(*it, value) && !comparator(value, *it))
+ {
+ size_t indexToRemove = it - vector.begin();
+ VmaVectorRemove(vector, indexToRemove);
+ return true;
+ }
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaPoolAllocator
+
+/*
+Allocator for objects of type T using a list of arrays (pools) to speed up
+allocation. Number of elements that can be allocated is not bounded because
+allocator can create multiple blocks.
+*/
+template<typename T>
+class VmaPoolAllocator
+{
+ VMA_CLASS_NO_COPY(VmaPoolAllocator)
+public:
+ VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity);
+ ~VmaPoolAllocator();
+ T* Alloc();
+ void Free(T* ptr);
+
+private:
+ union Item
+ {
+ uint32_t NextFreeIndex;
+ alignas(T) char Value[sizeof(T)];
+ };
+
+ struct ItemBlock
+ {
+ Item* pItems;
+ uint32_t Capacity;
+ uint32_t FirstFreeIndex;
+ };
+
+ const VkAllocationCallbacks* m_pAllocationCallbacks;
+ const uint32_t m_FirstBlockCapacity;
+ VmaVector< ItemBlock, VmaStlAllocator<ItemBlock> > m_ItemBlocks;
+
+ ItemBlock& CreateNewBlock();
+};
+
+template<typename T>
+VmaPoolAllocator<T>::VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity) :
+ m_pAllocationCallbacks(pAllocationCallbacks),
+ m_FirstBlockCapacity(firstBlockCapacity),
+ m_ItemBlocks(VmaStlAllocator<ItemBlock>(pAllocationCallbacks))
+{
+ VMA_ASSERT(m_FirstBlockCapacity > 1);
+}
+
+template<typename T>
+VmaPoolAllocator<T>::~VmaPoolAllocator()
+{
+ for(size_t i = m_ItemBlocks.size(); i--; )
+ vma_delete_array(m_pAllocationCallbacks, m_ItemBlocks[i].pItems, m_ItemBlocks[i].Capacity);
+ m_ItemBlocks.clear();
+}
+
+template<typename T>
+T* VmaPoolAllocator<T>::Alloc()
+{
+ for(size_t i = m_ItemBlocks.size(); i--; )
+ {
+ ItemBlock& block = m_ItemBlocks[i];
+ // This block has some free items: Use first one.
+ if(block.FirstFreeIndex != UINT32_MAX)
+ {
+ Item* const pItem = &block.pItems[block.FirstFreeIndex];
+ block.FirstFreeIndex = pItem->NextFreeIndex;
+ T* result = (T*)&pItem->Value;
+ new(result)T(); // Explicit constructor call.
+ return result;
+ }
+ }
+
+ // No block has free item: Create new one and use it.
+ ItemBlock& newBlock = CreateNewBlock();
+ Item* const pItem = &newBlock.pItems[0];
+ newBlock.FirstFreeIndex = pItem->NextFreeIndex;
+ T* result = (T*)&pItem->Value;
+ new(result)T(); // Explicit constructor call.
+ return result;
+}
+
+template<typename T>
+void VmaPoolAllocator<T>::Free(T* ptr)
+{
+ // Search all memory blocks to find ptr.
+ for(size_t i = m_ItemBlocks.size(); i--; )
+ {
+ ItemBlock& block = m_ItemBlocks[i];
+
+ // Casting to union.
+ Item* pItemPtr;
+ memcpy(&pItemPtr, &ptr, sizeof(pItemPtr));
+
+ // Check if pItemPtr is in address range of this block.
+ if((pItemPtr >= block.pItems) && (pItemPtr < block.pItems + block.Capacity))
+ {
+ ptr->~T(); // Explicit destructor call.
+ const uint32_t index = static_cast<uint32_t>(pItemPtr - block.pItems);
+ pItemPtr->NextFreeIndex = block.FirstFreeIndex;
+ block.FirstFreeIndex = index;
+ return;
+ }
+ }
+ VMA_ASSERT(0 && "Pointer doesn't belong to this memory pool.");
+}
+
+template<typename T>
+typename VmaPoolAllocator<T>::ItemBlock& VmaPoolAllocator<T>::CreateNewBlock()
+{
+ const uint32_t newBlockCapacity = m_ItemBlocks.empty() ?
+ m_FirstBlockCapacity : m_ItemBlocks.back().Capacity * 3 / 2;
+
+ const ItemBlock newBlock = {
+ vma_new_array(m_pAllocationCallbacks, Item, newBlockCapacity),
+ newBlockCapacity,
+ 0 };
+
+ m_ItemBlocks.push_back(newBlock);
+
+ // Setup singly-linked list of all free items in this block.
+ for(uint32_t i = 0; i < newBlockCapacity - 1; ++i)
+ newBlock.pItems[i].NextFreeIndex = i + 1;
+ newBlock.pItems[newBlockCapacity - 1].NextFreeIndex = UINT32_MAX;
+ return m_ItemBlocks.back();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaRawList, VmaList
+
+#if VMA_USE_STL_LIST
+
+#define VmaList std::list
+
+#else // #if VMA_USE_STL_LIST
+
+template<typename T>
+struct VmaListItem
+{
+ VmaListItem* pPrev;
+ VmaListItem* pNext;
+ T Value;
+};
+
+// Doubly linked list.
+template<typename T>
+class VmaRawList
+{
+ VMA_CLASS_NO_COPY(VmaRawList)
+public:
+ typedef VmaListItem<T> ItemType;
+
+ VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks);
+ ~VmaRawList();
+ void Clear();
+
+ size_t GetCount() const { return m_Count; }
+ bool IsEmpty() const { return m_Count == 0; }
+
+ ItemType* Front() { return m_pFront; }
+ const ItemType* Front() const { return m_pFront; }
+ ItemType* Back() { return m_pBack; }
+ const ItemType* Back() const { return m_pBack; }
+
+ ItemType* PushBack();
+ ItemType* PushFront();
+ ItemType* PushBack(const T& value);
+ ItemType* PushFront(const T& value);
+ void PopBack();
+ void PopFront();
+
+ // Item can be null - it means PushBack.
+ ItemType* InsertBefore(ItemType* pItem);
+ // Item can be null - it means PushFront.
+ ItemType* InsertAfter(ItemType* pItem);
+
+ ItemType* InsertBefore(ItemType* pItem, const T& value);
+ ItemType* InsertAfter(ItemType* pItem, const T& value);
+
+ void Remove(ItemType* pItem);
+
+private:
+ const VkAllocationCallbacks* const m_pAllocationCallbacks;
+ VmaPoolAllocator<ItemType> m_ItemAllocator;
+ ItemType* m_pFront;
+ ItemType* m_pBack;
+ size_t m_Count;
+};
+
+template<typename T>
+VmaRawList<T>::VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks) :
+ m_pAllocationCallbacks(pAllocationCallbacks),
+ m_ItemAllocator(pAllocationCallbacks, 128),
+ m_pFront(VMA_NULL),
+ m_pBack(VMA_NULL),
+ m_Count(0)
+{
+}
+
+template<typename T>
+VmaRawList<T>::~VmaRawList()
+{
+ // Intentionally not calling Clear, because that would be unnecessary
+ // computations to return all items to m_ItemAllocator as free.
+}
+
+template<typename T>
+void VmaRawList<T>::Clear()
+{
+ if(IsEmpty() == false)
+ {
+ ItemType* pItem = m_pBack;
+ while(pItem != VMA_NULL)
+ {
+ ItemType* const pPrevItem = pItem->pPrev;
+ m_ItemAllocator.Free(pItem);
+ pItem = pPrevItem;
+ }
+ m_pFront = VMA_NULL;
+ m_pBack = VMA_NULL;
+ m_Count = 0;
+ }
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushBack()
+{
+ ItemType* const pNewItem = m_ItemAllocator.Alloc();
+ pNewItem->pNext = VMA_NULL;
+ if(IsEmpty())
+ {
+ pNewItem->pPrev = VMA_NULL;
+ m_pFront = pNewItem;
+ m_pBack = pNewItem;
+ m_Count = 1;
+ }
+ else
+ {
+ pNewItem->pPrev = m_pBack;
+ m_pBack->pNext = pNewItem;
+ m_pBack = pNewItem;
+ ++m_Count;
+ }
+ return pNewItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushFront()
+{
+ ItemType* const pNewItem = m_ItemAllocator.Alloc();
+ pNewItem->pPrev = VMA_NULL;
+ if(IsEmpty())
+ {
+ pNewItem->pNext = VMA_NULL;
+ m_pFront = pNewItem;
+ m_pBack = pNewItem;
+ m_Count = 1;
+ }
+ else
+ {
+ pNewItem->pNext = m_pFront;
+ m_pFront->pPrev = pNewItem;
+ m_pFront = pNewItem;
+ ++m_Count;
+ }
+ return pNewItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushBack(const T& value)
+{
+ ItemType* const pNewItem = PushBack();
+ pNewItem->Value = value;
+ return pNewItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushFront(const T& value)
+{
+ ItemType* const pNewItem = PushFront();
+ pNewItem->Value = value;
+ return pNewItem;
+}
+
+template<typename T>
+void VmaRawList<T>::PopBack()
+{
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ ItemType* const pBackItem = m_pBack;
+ ItemType* const pPrevItem = pBackItem->pPrev;
+ if(pPrevItem != VMA_NULL)
+ {
+ pPrevItem->pNext = VMA_NULL;
+ }
+ m_pBack = pPrevItem;
+ m_ItemAllocator.Free(pBackItem);
+ --m_Count;
+}
+
+template<typename T>
+void VmaRawList<T>::PopFront()
+{
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ ItemType* const pFrontItem = m_pFront;
+ ItemType* const pNextItem = pFrontItem->pNext;
+ if(pNextItem != VMA_NULL)
+ {
+ pNextItem->pPrev = VMA_NULL;
+ }
+ m_pFront = pNextItem;
+ m_ItemAllocator.Free(pFrontItem);
+ --m_Count;
+}
+
+template<typename T>
+void VmaRawList<T>::Remove(ItemType* pItem)
+{
+ VMA_HEAVY_ASSERT(pItem != VMA_NULL);
+ VMA_HEAVY_ASSERT(m_Count > 0);
+
+ if(pItem->pPrev != VMA_NULL)
+ {
+ pItem->pPrev->pNext = pItem->pNext;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(m_pFront == pItem);
+ m_pFront = pItem->pNext;
+ }
+
+ if(pItem->pNext != VMA_NULL)
+ {
+ pItem->pNext->pPrev = pItem->pPrev;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(m_pBack == pItem);
+ m_pBack = pItem->pPrev;
+ }
+
+ m_ItemAllocator.Free(pItem);
+ --m_Count;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertBefore(ItemType* pItem)
+{
+ if(pItem != VMA_NULL)
+ {
+ ItemType* const prevItem = pItem->pPrev;
+ ItemType* const newItem = m_ItemAllocator.Alloc();
+ newItem->pPrev = prevItem;
+ newItem->pNext = pItem;
+ pItem->pPrev = newItem;
+ if(prevItem != VMA_NULL)
+ {
+ prevItem->pNext = newItem;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(m_pFront == pItem);
+ m_pFront = newItem;
+ }
+ ++m_Count;
+ return newItem;
+ }
+ else
+ return PushBack();
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertAfter(ItemType* pItem)
+{
+ if(pItem != VMA_NULL)
+ {
+ ItemType* const nextItem = pItem->pNext;
+ ItemType* const newItem = m_ItemAllocator.Alloc();
+ newItem->pNext = nextItem;
+ newItem->pPrev = pItem;
+ pItem->pNext = newItem;
+ if(nextItem != VMA_NULL)
+ {
+ nextItem->pPrev = newItem;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(m_pBack == pItem);
+ m_pBack = newItem;
+ }
+ ++m_Count;
+ return newItem;
+ }
+ else
+ return PushFront();
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertBefore(ItemType* pItem, const T& value)
+{
+ ItemType* const newItem = InsertBefore(pItem);
+ newItem->Value = value;
+ return newItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertAfter(ItemType* pItem, const T& value)
+{
+ ItemType* const newItem = InsertAfter(pItem);
+ newItem->Value = value;
+ return newItem;
+}
+
+template<typename T, typename AllocatorT>
+class VmaList
+{
+ VMA_CLASS_NO_COPY(VmaList)
+public:
+ class iterator
+ {
+ public:
+ iterator() :
+ m_pList(VMA_NULL),
+ m_pItem(VMA_NULL)
+ {
+ }
+
+ T& operator*() const
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ return m_pItem->Value;
+ }
+ T* operator->() const
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ return &m_pItem->Value;
+ }
+
+ iterator& operator++()
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ m_pItem = m_pItem->pNext;
+ return *this;
+ }
+ iterator& operator--()
+ {
+ if(m_pItem != VMA_NULL)
+ {
+ m_pItem = m_pItem->pPrev;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
+ m_pItem = m_pList->Back();
+ }
+ return *this;
+ }
+
+ iterator operator++(int)
+ {
+ iterator result = *this;
+ ++*this;
+ return result;
+ }
+ iterator operator--(int)
+ {
+ iterator result = *this;
+ --*this;
+ return result;
+ }
+
+ bool operator==(const iterator& rhs) const
+ {
+ VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+ return m_pItem == rhs.m_pItem;
+ }
+ bool operator!=(const iterator& rhs) const
+ {
+ VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+ return m_pItem != rhs.m_pItem;
+ }
+
+ private:
+ VmaRawList<T>* m_pList;
+ VmaListItem<T>* m_pItem;
+
+ iterator(VmaRawList<T>* pList, VmaListItem<T>* pItem) :
+ m_pList(pList),
+ m_pItem(pItem)
+ {
+ }
+
+ friend class VmaList<T, AllocatorT>;
+ };
+
+ class const_iterator
+ {
+ public:
+ const_iterator() :
+ m_pList(VMA_NULL),
+ m_pItem(VMA_NULL)
+ {
+ }
+
+ const_iterator(const iterator& src) :
+ m_pList(src.m_pList),
+ m_pItem(src.m_pItem)
+ {
+ }
+
+ const T& operator*() const
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ return m_pItem->Value;
+ }
+ const T* operator->() const
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ return &m_pItem->Value;
+ }
+
+ const_iterator& operator++()
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ m_pItem = m_pItem->pNext;
+ return *this;
+ }
+ const_iterator& operator--()
+ {
+ if(m_pItem != VMA_NULL)
+ {
+ m_pItem = m_pItem->pPrev;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
+ m_pItem = m_pList->Back();
+ }
+ return *this;
+ }
+
+ const_iterator operator++(int)
+ {
+ const_iterator result = *this;
+ ++*this;
+ return result;
+ }
+ const_iterator operator--(int)
+ {
+ const_iterator result = *this;
+ --*this;
+ return result;
+ }
+
+ bool operator==(const const_iterator& rhs) const
+ {
+ VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+ return m_pItem == rhs.m_pItem;
+ }
+ bool operator!=(const const_iterator& rhs) const
+ {
+ VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+ return m_pItem != rhs.m_pItem;
+ }
+
+ private:
+ const_iterator(const VmaRawList<T>* pList, const VmaListItem<T>* pItem) :
+ m_pList(pList),
+ m_pItem(pItem)
+ {
+ }
+
+ const VmaRawList<T>* m_pList;
+ const VmaListItem<T>* m_pItem;
+
+ friend class VmaList<T, AllocatorT>;
+ };
+
+ VmaList(const AllocatorT& allocator) : m_RawList(allocator.m_pCallbacks) { }
+
+ bool empty() const { return m_RawList.IsEmpty(); }
+ size_t size() const { return m_RawList.GetCount(); }
+
+ iterator begin() { return iterator(&m_RawList, m_RawList.Front()); }
+ iterator end() { return iterator(&m_RawList, VMA_NULL); }
+
+ const_iterator cbegin() const { return const_iterator(&m_RawList, m_RawList.Front()); }
+ const_iterator cend() const { return const_iterator(&m_RawList, VMA_NULL); }
+
+ void clear() { m_RawList.Clear(); }
+ void push_back(const T& value) { m_RawList.PushBack(value); }
+ void erase(iterator it) { m_RawList.Remove(it.m_pItem); }
+ iterator insert(iterator it, const T& value) { return iterator(&m_RawList, m_RawList.InsertBefore(it.m_pItem, value)); }
+
+private:
+ VmaRawList<T> m_RawList;
+};
+
+#endif // #if VMA_USE_STL_LIST
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaMap
+
+// Unused in this version.
+#if 0
+
+#if VMA_USE_STL_UNORDERED_MAP
+
+#define VmaPair std::pair
+
+#define VMA_MAP_TYPE(KeyT, ValueT) \
+ std::unordered_map< KeyT, ValueT, std::hash<KeyT>, std::equal_to<KeyT>, VmaStlAllocator< std::pair<KeyT, ValueT> > >
+
+#else // #if VMA_USE_STL_UNORDERED_MAP
+
+template<typename T1, typename T2>
+struct VmaPair
+{
+ T1 first;
+ T2 second;
+
+ VmaPair() : first(), second() { }
+ VmaPair(const T1& firstSrc, const T2& secondSrc) : first(firstSrc), second(secondSrc) { }
+};
+
+/* Class compatible with subset of interface of std::unordered_map.
+KeyT, ValueT must be POD because they will be stored in VmaVector.
+*/
+template<typename KeyT, typename ValueT>
+class VmaMap
+{
+public:
+ typedef VmaPair<KeyT, ValueT> PairType;
+ typedef PairType* iterator;
+
+ VmaMap(const VmaStlAllocator<PairType>& allocator) : m_Vector(allocator) { }
+
+ iterator begin() { return m_Vector.begin(); }
+ iterator end() { return m_Vector.end(); }
+
+ void insert(const PairType& pair);
+ iterator find(const KeyT& key);
+ void erase(iterator it);
+
+private:
+ VmaVector< PairType, VmaStlAllocator<PairType> > m_Vector;
+};
+
+#define VMA_MAP_TYPE(KeyT, ValueT) VmaMap<KeyT, ValueT>
+
+template<typename FirstT, typename SecondT>
+struct VmaPairFirstLess
+{
+ bool operator()(const VmaPair<FirstT, SecondT>& lhs, const VmaPair<FirstT, SecondT>& rhs) const
+ {
+ return lhs.first < rhs.first;
+ }
+ bool operator()(const VmaPair<FirstT, SecondT>& lhs, const FirstT& rhsFirst) const
+ {
+ return lhs.first < rhsFirst;
+ }
+};
+
+template<typename KeyT, typename ValueT>
+void VmaMap<KeyT, ValueT>::insert(const PairType& pair)
+{
+ const size_t indexToInsert = VmaBinaryFindFirstNotLess(
+ m_Vector.data(),
+ m_Vector.data() + m_Vector.size(),
+ pair,
+ VmaPairFirstLess<KeyT, ValueT>()) - m_Vector.data();
+ VmaVectorInsert(m_Vector, indexToInsert, pair);
+}
+
+template<typename KeyT, typename ValueT>
+VmaPair<KeyT, ValueT>* VmaMap<KeyT, ValueT>::find(const KeyT& key)
+{
+ PairType* it = VmaBinaryFindFirstNotLess(
+ m_Vector.data(),
+ m_Vector.data() + m_Vector.size(),
+ key,
+ VmaPairFirstLess<KeyT, ValueT>());
+ if((it != m_Vector.end()) && (it->first == key))
+ {
+ return it;
+ }
+ else
+ {
+ return m_Vector.end();
+ }
+}
+
+template<typename KeyT, typename ValueT>
+void VmaMap<KeyT, ValueT>::erase(iterator it)
+{
+ VmaVectorRemove(m_Vector, it - m_Vector.begin());
+}
+
+#endif // #if VMA_USE_STL_UNORDERED_MAP
+
+#endif // #if 0
+
+////////////////////////////////////////////////////////////////////////////////
+
+class VmaDeviceMemoryBlock;
+
+enum VMA_CACHE_OPERATION { VMA_CACHE_FLUSH, VMA_CACHE_INVALIDATE };
+
+struct VmaAllocation_T
+{
+private:
+ static const uint8_t MAP_COUNT_FLAG_PERSISTENT_MAP = 0x80;
+
+ enum FLAGS
+ {
+ FLAG_USER_DATA_STRING = 0x01,
+ };
+
+public:
+ enum ALLOCATION_TYPE
+ {
+ ALLOCATION_TYPE_NONE,
+ ALLOCATION_TYPE_BLOCK,
+ ALLOCATION_TYPE_DEDICATED,
+ };
+
+ /*
+ This struct is allocated using VmaPoolAllocator.
+ */
+
+ void Ctor(uint32_t currentFrameIndex, bool userDataString)
+ {
+ m_Alignment = 1;
+ m_Size = 0;
+ m_MemoryTypeIndex = 0;
+ m_pUserData = VMA_NULL;
+ m_LastUseFrameIndex = currentFrameIndex;
+ m_Type = (uint8_t)ALLOCATION_TYPE_NONE;
+ m_SuballocationType = (uint8_t)VMA_SUBALLOCATION_TYPE_UNKNOWN;
+ m_MapCount = 0;
+ m_Flags = userDataString ? (uint8_t)FLAG_USER_DATA_STRING : 0;
+
+#if VMA_STATS_STRING_ENABLED
+ m_CreationFrameIndex = currentFrameIndex;
+ m_BufferImageUsage = 0;
+#endif
+ }
+
+ void Dtor()
+ {
+ VMA_ASSERT((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) == 0 && "Allocation was not unmapped before destruction.");
+
+ // Check if owned string was freed.
+ VMA_ASSERT(m_pUserData == VMA_NULL);
+ }
+
+ void InitBlockAllocation(
+ VmaDeviceMemoryBlock* block,
+ VkDeviceSize offset,
+ VkDeviceSize alignment,
+ VkDeviceSize size,
+ uint32_t memoryTypeIndex,
+ VmaSuballocationType suballocationType,
+ bool mapped,
+ bool canBecomeLost)
+ {
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+ VMA_ASSERT(block != VMA_NULL);
+ m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;
+ m_Alignment = alignment;
+ m_Size = size;
+ m_MemoryTypeIndex = memoryTypeIndex;
+ m_MapCount = mapped ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0;
+ m_SuballocationType = (uint8_t)suballocationType;
+ m_BlockAllocation.m_Block = block;
+ m_BlockAllocation.m_Offset = offset;
+ m_BlockAllocation.m_CanBecomeLost = canBecomeLost;
+ }
+
+ void InitLost()
+ {
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+ VMA_ASSERT(m_LastUseFrameIndex.load() == VMA_FRAME_INDEX_LOST);
+ m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;
+ m_MemoryTypeIndex = 0;
+ m_BlockAllocation.m_Block = VMA_NULL;
+ m_BlockAllocation.m_Offset = 0;
+ m_BlockAllocation.m_CanBecomeLost = true;
+ }
+
+ void ChangeBlockAllocation(
+ VmaAllocator hAllocator,
+ VmaDeviceMemoryBlock* block,
+ VkDeviceSize offset);
+
+ void ChangeOffset(VkDeviceSize newOffset);
+
+ // pMappedData not null means allocation is created with MAPPED flag.
+ void InitDedicatedAllocation(
+ uint32_t memoryTypeIndex,
+ VkDeviceMemory hMemory,
+ VmaSuballocationType suballocationType,
+ void* pMappedData,
+ VkDeviceSize size)
+ {
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+ VMA_ASSERT(hMemory != VK_NULL_HANDLE);
+ m_Type = (uint8_t)ALLOCATION_TYPE_DEDICATED;
+ m_Alignment = 0;
+ m_Size = size;
+ m_MemoryTypeIndex = memoryTypeIndex;
+ m_SuballocationType = (uint8_t)suballocationType;
+ m_MapCount = (pMappedData != VMA_NULL) ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0;
+ m_DedicatedAllocation.m_hMemory = hMemory;
+ m_DedicatedAllocation.m_pMappedData = pMappedData;
+ }
+
+ ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }
+ VkDeviceSize GetAlignment() const { return m_Alignment; }
+ VkDeviceSize GetSize() const { return m_Size; }
+ bool IsUserDataString() const { return (m_Flags & FLAG_USER_DATA_STRING) != 0; }
+ void* GetUserData() const { return m_pUserData; }
+ void SetUserData(VmaAllocator hAllocator, void* pUserData);
+ VmaSuballocationType GetSuballocationType() const { return (VmaSuballocationType)m_SuballocationType; }
+
+ VmaDeviceMemoryBlock* GetBlock() const
+ {
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+ return m_BlockAllocation.m_Block;
+ }
+ VkDeviceSize GetOffset() const;
+ VkDeviceMemory GetMemory() const;
+ uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+ bool IsPersistentMap() const { return (m_MapCount & MAP_COUNT_FLAG_PERSISTENT_MAP) != 0; }
+ void* GetMappedData() const;
+ bool CanBecomeLost() const;
+
+ uint32_t GetLastUseFrameIndex() const
+ {
+ return m_LastUseFrameIndex.load();
+ }
+ bool CompareExchangeLastUseFrameIndex(uint32_t& expected, uint32_t desired)
+ {
+ return m_LastUseFrameIndex.compare_exchange_weak(expected, desired);
+ }
+ /*
+ - If hAllocation.LastUseFrameIndex + frameInUseCount < allocator.CurrentFrameIndex,
+ makes it lost by setting LastUseFrameIndex = VMA_FRAME_INDEX_LOST and returns true.
+ - Else, returns false.
+
+ If hAllocation is already lost, assert - you should not call it then.
+ If hAllocation was not created with CAN_BECOME_LOST_BIT, assert.
+ */
+ bool MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+ void DedicatedAllocCalcStatsInfo(VmaStatInfo& outInfo)
+ {
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_DEDICATED);
+ outInfo.blockCount = 1;
+ outInfo.allocationCount = 1;
+ outInfo.unusedRangeCount = 0;
+ outInfo.usedBytes = m_Size;
+ outInfo.unusedBytes = 0;
+ outInfo.allocationSizeMin = outInfo.allocationSizeMax = m_Size;
+ outInfo.unusedRangeSizeMin = UINT64_MAX;
+ outInfo.unusedRangeSizeMax = 0;
+ }
+
+ void BlockAllocMap();
+ void BlockAllocUnmap();
+ VkResult DedicatedAllocMap(VmaAllocator hAllocator, void** ppData);
+ void DedicatedAllocUnmap(VmaAllocator hAllocator);
+
+#if VMA_STATS_STRING_ENABLED
+ uint32_t GetCreationFrameIndex() const { return m_CreationFrameIndex; }
+ uint32_t GetBufferImageUsage() const { return m_BufferImageUsage; }
+
+ void InitBufferImageUsage(uint32_t bufferImageUsage)
+ {
+ VMA_ASSERT(m_BufferImageUsage == 0);
+ m_BufferImageUsage = bufferImageUsage;
+ }
+
+ void PrintParameters(class VmaJsonWriter& json) const;
+#endif
+
+private:
+ VkDeviceSize m_Alignment;
+ VkDeviceSize m_Size;
+ void* m_pUserData;
+ VMA_ATOMIC_UINT32 m_LastUseFrameIndex;
+ uint32_t m_MemoryTypeIndex;
+ uint8_t m_Type; // ALLOCATION_TYPE
+ uint8_t m_SuballocationType; // VmaSuballocationType
+ // Bit 0x80 is set when allocation was created with VMA_ALLOCATION_CREATE_MAPPED_BIT.
+ // Bits with mask 0x7F are reference counter for vmaMapMemory()/vmaUnmapMemory().
+ uint8_t m_MapCount;
+ uint8_t m_Flags; // enum FLAGS
+
+ // Allocation out of VmaDeviceMemoryBlock.
+ struct BlockAllocation
+ {
+ VmaDeviceMemoryBlock* m_Block;
+ VkDeviceSize m_Offset;
+ bool m_CanBecomeLost;
+ };
+
+ // Allocation for an object that has its own private VkDeviceMemory.
+ struct DedicatedAllocation
+ {
+ VkDeviceMemory m_hMemory;
+ void* m_pMappedData; // Not null means memory is mapped.
+ };
+
+ union
+ {
+ // Allocation out of VmaDeviceMemoryBlock.
+ BlockAllocation m_BlockAllocation;
+ // Allocation for an object that has its own private VkDeviceMemory.
+ DedicatedAllocation m_DedicatedAllocation;
+ };
+
+#if VMA_STATS_STRING_ENABLED
+ uint32_t m_CreationFrameIndex;
+ uint32_t m_BufferImageUsage; // 0 if unknown.
+#endif
+
+ void FreeUserDataString(VmaAllocator hAllocator);
+};
+
+/*
+Represents a region of VmaDeviceMemoryBlock that is either assigned and returned as
+allocated memory block or free.
+*/
+struct VmaSuballocation
+{
+ VkDeviceSize offset;
+ VkDeviceSize size;
+ VmaAllocation hAllocation;
+ VmaSuballocationType type;
+};
+
+// Comparator for offsets.
+struct VmaSuballocationOffsetLess
+{
+ bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const
+ {
+ return lhs.offset < rhs.offset;
+ }
+};
+struct VmaSuballocationOffsetGreater
+{
+ bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const
+ {
+ return lhs.offset > rhs.offset;
+ }
+};
+
+typedef VmaList< VmaSuballocation, VmaStlAllocator<VmaSuballocation> > VmaSuballocationList;
+
+// Cost of one additional allocation lost, as equivalent in bytes.
+static const VkDeviceSize VMA_LOST_ALLOCATION_COST = 1048576;
+
+enum class VmaAllocationRequestType
+{
+ Normal,
+ // Used by "Linear" algorithm.
+ UpperAddress,
+ EndOf1st,
+ EndOf2nd,
+};
+
+/*
+Parameters of planned allocation inside a VmaDeviceMemoryBlock.
+
+If canMakeOtherLost was false:
+- item points to a FREE suballocation.
+- itemsToMakeLostCount is 0.
+
+If canMakeOtherLost was true:
+- item points to first of sequence of suballocations, which are either FREE,
+ or point to VmaAllocations that can become lost.
+- itemsToMakeLostCount is the number of VmaAllocations that need to be made lost for
+ the requested allocation to succeed.
+*/
+struct VmaAllocationRequest
+{
+ VkDeviceSize offset;
+ VkDeviceSize sumFreeSize; // Sum size of free items that overlap with proposed allocation.
+ VkDeviceSize sumItemSize; // Sum size of items to make lost that overlap with proposed allocation.
+ VmaSuballocationList::iterator item;
+ size_t itemsToMakeLostCount;
+ void* customData;
+ VmaAllocationRequestType type;
+
+ VkDeviceSize CalcCost() const
+ {
+ return sumItemSize + itemsToMakeLostCount * VMA_LOST_ALLOCATION_COST;
+ }
+};
+
+/*
+Data structure used for bookkeeping of allocations and unused ranges of memory
+in a single VkDeviceMemory block.
+*/
+class VmaBlockMetadata
+{
+public:
+ VmaBlockMetadata(VmaAllocator hAllocator);
+ virtual ~VmaBlockMetadata() { }
+ virtual void Init(VkDeviceSize size) { m_Size = size; }
+
+ // Validates all data structures inside this object. If not valid, returns false.
+ virtual bool Validate() const = 0;
+ VkDeviceSize GetSize() const { return m_Size; }
+ virtual size_t GetAllocationCount() const = 0;
+ virtual VkDeviceSize GetSumFreeSize() const = 0;
+ virtual VkDeviceSize GetUnusedRangeSizeMax() const = 0;
+ // Returns true if this block is empty - contains only single free suballocation.
+ virtual bool IsEmpty() const = 0;
+
+ virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const = 0;
+ // Shouldn't modify blockCount.
+ virtual void AddPoolStats(VmaPoolStats& inoutStats) const = 0;
+
+#if VMA_STATS_STRING_ENABLED
+ virtual void PrintDetailedMap(class VmaJsonWriter& json) const = 0;
+#endif
+
+ // Tries to find a place for suballocation with given parameters inside this block.
+ // If succeeded, fills pAllocationRequest and returns true.
+ // If failed, returns false.
+ virtual bool CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ // Always one of VMA_ALLOCATION_CREATE_STRATEGY_* or VMA_ALLOCATION_INTERNAL_STRATEGY_* flags.
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest) = 0;
+
+ virtual bool MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest) = 0;
+
+ virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) = 0;
+
+ virtual VkResult CheckCorruption(const void* pBlockData) = 0;
+
+ // Makes actual allocation based on request. Request must already be checked and valid.
+ virtual void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ VmaAllocation hAllocation) = 0;
+
+ // Frees suballocation assigned to given memory region.
+ virtual void Free(const VmaAllocation allocation) = 0;
+ virtual void FreeAtOffset(VkDeviceSize offset) = 0;
+
+protected:
+ const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; }
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap_Begin(class VmaJsonWriter& json,
+ VkDeviceSize unusedBytes,
+ size_t allocationCount,
+ size_t unusedRangeCount) const;
+ void PrintDetailedMap_Allocation(class VmaJsonWriter& json,
+ VkDeviceSize offset,
+ VmaAllocation hAllocation) const;
+ void PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,
+ VkDeviceSize offset,
+ VkDeviceSize size) const;
+ void PrintDetailedMap_End(class VmaJsonWriter& json) const;
+#endif
+
+private:
+ VkDeviceSize m_Size;
+ const VkAllocationCallbacks* m_pAllocationCallbacks;
+};
+
+#define VMA_VALIDATE(cond) do { if(!(cond)) { \
+ VMA_ASSERT(0 && "Validation failed: " #cond); \
+ return false; \
+ } } while(false)
+
+class VmaBlockMetadata_Generic : public VmaBlockMetadata
+{
+ VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic)
+public:
+ VmaBlockMetadata_Generic(VmaAllocator hAllocator);
+ virtual ~VmaBlockMetadata_Generic();
+ virtual void Init(VkDeviceSize size);
+
+ virtual bool Validate() const;
+ virtual size_t GetAllocationCount() const { return m_Suballocations.size() - m_FreeCount; }
+ virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; }
+ virtual VkDeviceSize GetUnusedRangeSizeMax() const;
+ virtual bool IsEmpty() const;
+
+ virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
+ virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
+
+#if VMA_STATS_STRING_ENABLED
+ virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
+#endif
+
+ virtual bool CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual bool MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+ virtual VkResult CheckCorruption(const void* pBlockData);
+
+ virtual void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ VmaAllocation hAllocation);
+
+ virtual void Free(const VmaAllocation allocation);
+ virtual void FreeAtOffset(VkDeviceSize offset);
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // For defragmentation
+
+ bool IsBufferImageGranularityConflictPossible(
+ VkDeviceSize bufferImageGranularity,
+ VmaSuballocationType& inOutPrevSuballocType) const;
+
+private:
+ friend class VmaDefragmentationAlgorithm_Generic;
+ friend class VmaDefragmentationAlgorithm_Fast;
+
+ uint32_t m_FreeCount;
+ VkDeviceSize m_SumFreeSize;
+ VmaSuballocationList m_Suballocations;
+ // Suballocations that are free and have size greater than certain threshold.
+ // Sorted by size, ascending.
+ VmaVector< VmaSuballocationList::iterator, VmaStlAllocator< VmaSuballocationList::iterator > > m_FreeSuballocationsBySize;
+
+ bool ValidateFreeSuballocationList() const;
+
+ // Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem.
+ // If yes, fills pOffset and returns true. If no, returns false.
+ bool CheckAllocation(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ VmaSuballocationList::const_iterator suballocItem,
+ bool canMakeOtherLost,
+ VkDeviceSize* pOffset,
+ size_t* itemsToMakeLostCount,
+ VkDeviceSize* pSumFreeSize,
+ VkDeviceSize* pSumItemSize) const;
+ // Given free suballocation, it merges it with following one, which must also be free.
+ void MergeFreeWithNext(VmaSuballocationList::iterator item);
+ // Releases given suballocation, making it free.
+ // Merges it with adjacent free suballocations if applicable.
+ // Returns iterator to new free suballocation at this place.
+ VmaSuballocationList::iterator FreeSuballocation(VmaSuballocationList::iterator suballocItem);
+ // Given free suballocation, it inserts it into sorted list of
+ // m_FreeSuballocationsBySize if it's suitable.
+ void RegisterFreeSuballocation(VmaSuballocationList::iterator item);
+ // Given free suballocation, it removes it from sorted list of
+ // m_FreeSuballocationsBySize if it's suitable.
+ void UnregisterFreeSuballocation(VmaSuballocationList::iterator item);
+};
+
+/*
+Allocations and their references in internal data structure look like this:
+
+if(m_2ndVectorMode == SECOND_VECTOR_EMPTY):
+
+ 0 +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount]
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount + 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 1st[1st.size() - 1]
+ +-------+
+ | |
+ | |
+ | |
+GetSize() +-------+
+
+if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER):
+
+ 0 +-------+
+ | Alloc | 2nd[0]
+ +-------+
+ | Alloc | 2nd[1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 2nd[2nd.size() - 1]
+ +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount]
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount + 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 1st[1st.size() - 1]
+ +-------+
+ | |
+GetSize() +-------+
+
+if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK):
+
+ 0 +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount]
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount + 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 1st[1st.size() - 1]
+ +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 2nd[2nd.size() - 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 2nd[1]
+ +-------+
+ | Alloc | 2nd[0]
+GetSize() +-------+
+
+*/
+class VmaBlockMetadata_Linear : public VmaBlockMetadata
+{
+ VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear)
+public:
+ VmaBlockMetadata_Linear(VmaAllocator hAllocator);
+ virtual ~VmaBlockMetadata_Linear();
+ virtual void Init(VkDeviceSize size);
+
+ virtual bool Validate() const;
+ virtual size_t GetAllocationCount() const;
+ virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; }
+ virtual VkDeviceSize GetUnusedRangeSizeMax() const;
+ virtual bool IsEmpty() const { return GetAllocationCount() == 0; }
+
+ virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
+ virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
+
+#if VMA_STATS_STRING_ENABLED
+ virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
+#endif
+
+ virtual bool CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual bool MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+ virtual VkResult CheckCorruption(const void* pBlockData);
+
+ virtual void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ VmaAllocation hAllocation);
+
+ virtual void Free(const VmaAllocation allocation);
+ virtual void FreeAtOffset(VkDeviceSize offset);
+
+private:
+ /*
+ There are two suballocation vectors, used in ping-pong way.
+ The one with index m_1stVectorIndex is called 1st.
+ The one with index (m_1stVectorIndex ^ 1) is called 2nd.
+ 2nd can be non-empty only when 1st is not empty.
+ When 2nd is not empty, m_2ndVectorMode indicates its mode of operation.
+ */
+ typedef VmaVector< VmaSuballocation, VmaStlAllocator<VmaSuballocation> > SuballocationVectorType;
+
+ enum SECOND_VECTOR_MODE
+ {
+ SECOND_VECTOR_EMPTY,
+ /*
+ Suballocations in 2nd vector are created later than the ones in 1st, but they
+ all have smaller offset.
+ */
+ SECOND_VECTOR_RING_BUFFER,
+ /*
+ Suballocations in 2nd vector are upper side of double stack.
+ They all have offsets higher than those in 1st vector.
+ Top of this stack means smaller offsets, but higher indices in this vector.
+ */
+ SECOND_VECTOR_DOUBLE_STACK,
+ };
+
+ VkDeviceSize m_SumFreeSize;
+ SuballocationVectorType m_Suballocations0, m_Suballocations1;
+ uint32_t m_1stVectorIndex;
+ SECOND_VECTOR_MODE m_2ndVectorMode;
+
+ SuballocationVectorType& AccessSuballocations1st() { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }
+ SuballocationVectorType& AccessSuballocations2nd() { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }
+ const SuballocationVectorType& AccessSuballocations1st() const { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }
+ const SuballocationVectorType& AccessSuballocations2nd() const { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }
+
+ // Number of items in 1st vector with hAllocation = null at the beginning.
+ size_t m_1stNullItemsBeginCount;
+ // Number of other items in 1st vector with hAllocation = null somewhere in the middle.
+ size_t m_1stNullItemsMiddleCount;
+ // Number of items in 2nd vector with hAllocation = null.
+ size_t m_2ndNullItemsCount;
+
+ bool ShouldCompact1st() const;
+ void CleanupAfterFree();
+
+ bool CreateAllocationRequest_LowerAddress(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest);
+ bool CreateAllocationRequest_UpperAddress(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest);
+};
+
+/*
+- GetSize() is the original size of allocated memory block.
+- m_UsableSize is this size aligned down to a power of two.
+ All allocations and calculations happen relative to m_UsableSize.
+- GetUnusableSize() is the difference between them.
+ It is repoted as separate, unused range, not available for allocations.
+
+Node at level 0 has size = m_UsableSize.
+Each next level contains nodes with size 2 times smaller than current level.
+m_LevelCount is the maximum number of levels to use in the current object.
+*/
+class VmaBlockMetadata_Buddy : public VmaBlockMetadata
+{
+ VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy)
+public:
+ VmaBlockMetadata_Buddy(VmaAllocator hAllocator);
+ virtual ~VmaBlockMetadata_Buddy();
+ virtual void Init(VkDeviceSize size);
+
+ virtual bool Validate() const;
+ virtual size_t GetAllocationCount() const { return m_AllocationCount; }
+ virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize + GetUnusableSize(); }
+ virtual VkDeviceSize GetUnusedRangeSizeMax() const;
+ virtual bool IsEmpty() const { return m_Root->type == Node::TYPE_FREE; }
+
+ virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
+ virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
+
+#if VMA_STATS_STRING_ENABLED
+ virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
+#endif
+
+ virtual bool CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual bool MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+ virtual VkResult CheckCorruption(const void* pBlockData) { return VK_ERROR_FEATURE_NOT_PRESENT; }
+
+ virtual void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ VmaAllocation hAllocation);
+
+ virtual void Free(const VmaAllocation allocation) { FreeAtOffset(allocation, allocation->GetOffset()); }
+ virtual void FreeAtOffset(VkDeviceSize offset) { FreeAtOffset(VMA_NULL, offset); }
+
+private:
+ static const VkDeviceSize MIN_NODE_SIZE = 32;
+ static const size_t MAX_LEVELS = 30;
+
+ struct ValidationContext
+ {
+ size_t calculatedAllocationCount;
+ size_t calculatedFreeCount;
+ VkDeviceSize calculatedSumFreeSize;
+
+ ValidationContext() :
+ calculatedAllocationCount(0),
+ calculatedFreeCount(0),
+ calculatedSumFreeSize(0) { }
+ };
+
+ struct Node
+ {
+ VkDeviceSize offset;
+ enum TYPE
+ {
+ TYPE_FREE,
+ TYPE_ALLOCATION,
+ TYPE_SPLIT,
+ TYPE_COUNT
+ } type;
+ Node* parent;
+ Node* buddy;
+
+ union
+ {
+ struct
+ {
+ Node* prev;
+ Node* next;
+ } free;
+ struct
+ {
+ VmaAllocation alloc;
+ } allocation;
+ struct
+ {
+ Node* leftChild;
+ } split;
+ };
+ };
+
+ // Size of the memory block aligned down to a power of two.
+ VkDeviceSize m_UsableSize;
+ uint32_t m_LevelCount;
+
+ Node* m_Root;
+ struct {
+ Node* front;
+ Node* back;
+ } m_FreeList[MAX_LEVELS];
+ // Number of nodes in the tree with type == TYPE_ALLOCATION.
+ size_t m_AllocationCount;
+ // Number of nodes in the tree with type == TYPE_FREE.
+ size_t m_FreeCount;
+ // This includes space wasted due to internal fragmentation. Doesn't include unusable size.
+ VkDeviceSize m_SumFreeSize;
+
+ VkDeviceSize GetUnusableSize() const { return GetSize() - m_UsableSize; }
+ void DeleteNode(Node* node);
+ bool ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const;
+ uint32_t AllocSizeToLevel(VkDeviceSize allocSize) const;
+ inline VkDeviceSize LevelToNodeSize(uint32_t level) const { return m_UsableSize >> level; }
+ // Alloc passed just for validation. Can be null.
+ void FreeAtOffset(VmaAllocation alloc, VkDeviceSize offset);
+ void CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const;
+ // Adds node to the front of FreeList at given level.
+ // node->type must be FREE.
+ // node->free.prev, next can be undefined.
+ void AddToFreeListFront(uint32_t level, Node* node);
+ // Removes node from FreeList at given level.
+ // node->type must be FREE.
+ // node->free.prev, next stay untouched.
+ void RemoveFromFreeList(uint32_t level, Node* node);
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const;
+#endif
+};
+
+/*
+Represents a single block of device memory (`VkDeviceMemory`) with all the
+data about its regions (aka suballocations, #VmaAllocation), assigned and free.
+
+Thread-safety: This class must be externally synchronized.
+*/
+class VmaDeviceMemoryBlock
+{
+ VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock)
+public:
+ VmaBlockMetadata* m_pMetadata;
+
+ VmaDeviceMemoryBlock(VmaAllocator hAllocator);
+
+ ~VmaDeviceMemoryBlock()
+ {
+ VMA_ASSERT(m_MapCount == 0 && "VkDeviceMemory block is being destroyed while it is still mapped.");
+ VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
+ }
+
+ // Always call after construction.
+ void Init(
+ VmaAllocator hAllocator,
+ VmaPool hParentPool,
+ uint32_t newMemoryTypeIndex,
+ VkDeviceMemory newMemory,
+ VkDeviceSize newSize,
+ uint32_t id,
+ uint32_t algorithm);
+ // Always call before destruction.
+ void Destroy(VmaAllocator allocator);
+
+ VmaPool GetParentPool() const { return m_hParentPool; }
+ VkDeviceMemory GetDeviceMemory() const { return m_hMemory; }
+ uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+ uint32_t GetId() const { return m_Id; }
+ void* GetMappedData() const { return m_pMappedData; }
+
+ // Validates all data structures inside this object. If not valid, returns false.
+ bool Validate() const;
+
+ VkResult CheckCorruption(VmaAllocator hAllocator);
+
+ // ppData can be null.
+ VkResult Map(VmaAllocator hAllocator, uint32_t count, void** ppData);
+ void Unmap(VmaAllocator hAllocator, uint32_t count);
+
+ VkResult WriteMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);
+ VkResult ValidateMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);
+
+ VkResult BindBufferMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkBuffer hBuffer,
+ const void* pNext);
+ VkResult BindImageMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkImage hImage,
+ const void* pNext);
+
+private:
+ VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
+ uint32_t m_MemoryTypeIndex;
+ uint32_t m_Id;
+ VkDeviceMemory m_hMemory;
+
+ /*
+ Protects access to m_hMemory so it's not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.
+ Also protects m_MapCount, m_pMappedData.
+ Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex.
+ */
+ VMA_MUTEX m_Mutex;
+ uint32_t m_MapCount;
+ void* m_pMappedData;
+};
+
+struct VmaPointerLess
+{
+ bool operator()(const void* lhs, const void* rhs) const
+ {
+ return lhs < rhs;
+ }
+};
+
+struct VmaDefragmentationMove
+{
+ size_t srcBlockIndex;
+ size_t dstBlockIndex;
+ VkDeviceSize srcOffset;
+ VkDeviceSize dstOffset;
+ VkDeviceSize size;
+};
+
+class VmaDefragmentationAlgorithm;
+
+/*
+Sequence of VmaDeviceMemoryBlock. Represents memory blocks allocated for a specific
+Vulkan memory type.
+
+Synchronized internally with a mutex.
+*/
+struct VmaBlockVector
+{
+ VMA_CLASS_NO_COPY(VmaBlockVector)
+public:
+ VmaBlockVector(
+ VmaAllocator hAllocator,
+ VmaPool hParentPool,
+ uint32_t memoryTypeIndex,
+ VkDeviceSize preferredBlockSize,
+ size_t minBlockCount,
+ size_t maxBlockCount,
+ VkDeviceSize bufferImageGranularity,
+ uint32_t frameInUseCount,
+ bool explicitBlockSize,
+ uint32_t algorithm);
+ ~VmaBlockVector();
+
+ VkResult CreateMinBlocks();
+
+ VmaAllocator GetAllocator() const { return m_hAllocator; }
+ VmaPool GetParentPool() const { return m_hParentPool; }
+ bool IsCustomPool() const { return m_hParentPool != VMA_NULL; }
+ uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+ VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; }
+ VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; }
+ uint32_t GetFrameInUseCount() const { return m_FrameInUseCount; }
+ uint32_t GetAlgorithm() const { return m_Algorithm; }
+
+ void GetPoolStats(VmaPoolStats* pStats);
+
+ bool IsEmpty();
+ bool IsCorruptionDetectionEnabled() const;
+
+ VkResult Allocate(
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ void Free(const VmaAllocation hAllocation);
+
+ // Adds statistics of this BlockVector to pStats.
+ void AddStats(VmaStats* pStats);
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap(class VmaJsonWriter& json);
+#endif
+
+ void MakePoolAllocationsLost(
+ uint32_t currentFrameIndex,
+ size_t* pLostAllocationCount);
+ VkResult CheckCorruption();
+
+ // Saves results in pCtx->res.
+ void Defragment(
+ class VmaBlockVectorDefragmentationContext* pCtx,
+ VmaDefragmentationStats* pStats,
+ VkDeviceSize& maxCpuBytesToMove, uint32_t& maxCpuAllocationsToMove,
+ VkDeviceSize& maxGpuBytesToMove, uint32_t& maxGpuAllocationsToMove,
+ VkCommandBuffer commandBuffer);
+ void DefragmentationEnd(
+ class VmaBlockVectorDefragmentationContext* pCtx,
+ VmaDefragmentationStats* pStats);
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // To be used only while the m_Mutex is locked. Used during defragmentation.
+
+ size_t GetBlockCount() const { return m_Blocks.size(); }
+ VmaDeviceMemoryBlock* GetBlock(size_t index) const { return m_Blocks[index]; }
+ size_t CalcAllocationCount() const;
+ bool IsBufferImageGranularityConflictPossible() const;
+
+private:
+ friend class VmaDefragmentationAlgorithm_Generic;
+
+ const VmaAllocator m_hAllocator;
+ const VmaPool m_hParentPool;
+ const uint32_t m_MemoryTypeIndex;
+ const VkDeviceSize m_PreferredBlockSize;
+ const size_t m_MinBlockCount;
+ const size_t m_MaxBlockCount;
+ const VkDeviceSize m_BufferImageGranularity;
+ const uint32_t m_FrameInUseCount;
+ const bool m_ExplicitBlockSize;
+ const uint32_t m_Algorithm;
+ VMA_RW_MUTEX m_Mutex;
+
+ /* There can be at most one allocation that is completely empty (except when minBlockCount > 0) -
+ a hysteresis to avoid pessimistic case of alternating creation and destruction of a VkDeviceMemory. */
+ bool m_HasEmptyBlock;
+ // Incrementally sorted by sumFreeSize, ascending.
+ VmaVector< VmaDeviceMemoryBlock*, VmaStlAllocator<VmaDeviceMemoryBlock*> > m_Blocks;
+ uint32_t m_NextBlockId;
+
+ VkDeviceSize CalcMaxBlockSize() const;
+
+ // Finds and removes given block from vector.
+ void Remove(VmaDeviceMemoryBlock* pBlock);
+
+ // Performs single step in sorting m_Blocks. They may not be fully sorted
+ // after this call.
+ void IncrementallySortBlocks();
+
+ VkResult AllocatePage(
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ VmaAllocation* pAllocation);
+
+ // To be used only without CAN_MAKE_OTHER_LOST flag.
+ VkResult AllocateFromBlock(
+ VmaDeviceMemoryBlock* pBlock,
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ VmaAllocationCreateFlags allocFlags,
+ void* pUserData,
+ VmaSuballocationType suballocType,
+ uint32_t strategy,
+ VmaAllocation* pAllocation);
+
+ VkResult CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex);
+
+ // Saves result to pCtx->res.
+ void ApplyDefragmentationMovesCpu(
+ class VmaBlockVectorDefragmentationContext* pDefragCtx,
+ const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves);
+ // Saves result to pCtx->res.
+ void ApplyDefragmentationMovesGpu(
+ class VmaBlockVectorDefragmentationContext* pDefragCtx,
+ const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkCommandBuffer commandBuffer);
+
+ /*
+ Used during defragmentation. pDefragmentationStats is optional. It's in/out
+ - updated with new data.
+ */
+ void FreeEmptyBlocks(VmaDefragmentationStats* pDefragmentationStats);
+
+ void UpdateHasEmptyBlock();
+};
+
+struct VmaPool_T
+{
+ VMA_CLASS_NO_COPY(VmaPool_T)
+public:
+ VmaBlockVector m_BlockVector;
+
+ VmaPool_T(
+ VmaAllocator hAllocator,
+ const VmaPoolCreateInfo& createInfo,
+ VkDeviceSize preferredBlockSize);
+ ~VmaPool_T();
+
+ uint32_t GetId() const { return m_Id; }
+ void SetId(uint32_t id) { VMA_ASSERT(m_Id == 0); m_Id = id; }
+
+ const char* GetName() const { return m_Name; }
+ void SetName(const char* pName);
+
+#if VMA_STATS_STRING_ENABLED
+ //void PrintDetailedMap(class VmaStringBuilder& sb);
+#endif
+
+private:
+ uint32_t m_Id;
+ char* m_Name;
+};
+
+/*
+Performs defragmentation:
+
+- Updates `pBlockVector->m_pMetadata`.
+- Updates allocations by calling ChangeBlockAllocation() or ChangeOffset().
+- Does not move actual data, only returns requested moves as `moves`.
+*/
+class VmaDefragmentationAlgorithm
+{
+ VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm)
+public:
+ VmaDefragmentationAlgorithm(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex) :
+ m_hAllocator(hAllocator),
+ m_pBlockVector(pBlockVector),
+ m_CurrentFrameIndex(currentFrameIndex)
+ {
+ }
+ virtual ~VmaDefragmentationAlgorithm()
+ {
+ }
+
+ virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) = 0;
+ virtual void AddAll() = 0;
+
+ virtual VkResult Defragment(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove) = 0;
+
+ virtual VkDeviceSize GetBytesMoved() const = 0;
+ virtual uint32_t GetAllocationsMoved() const = 0;
+
+protected:
+ VmaAllocator const m_hAllocator;
+ VmaBlockVector* const m_pBlockVector;
+ const uint32_t m_CurrentFrameIndex;
+
+ struct AllocationInfo
+ {
+ VmaAllocation m_hAllocation;
+ VkBool32* m_pChanged;
+
+ AllocationInfo() :
+ m_hAllocation(VK_NULL_HANDLE),
+ m_pChanged(VMA_NULL)
+ {
+ }
+ AllocationInfo(VmaAllocation hAlloc, VkBool32* pChanged) :
+ m_hAllocation(hAlloc),
+ m_pChanged(pChanged)
+ {
+ }
+ };
+};
+
+class VmaDefragmentationAlgorithm_Generic : public VmaDefragmentationAlgorithm
+{
+ VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Generic)
+public:
+ VmaDefragmentationAlgorithm_Generic(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex,
+ bool overlappingMoveSupported);
+ virtual ~VmaDefragmentationAlgorithm_Generic();
+
+ virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
+ virtual void AddAll() { m_AllAllocations = true; }
+
+ virtual VkResult Defragment(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove);
+
+ virtual VkDeviceSize GetBytesMoved() const { return m_BytesMoved; }
+ virtual uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; }
+
+private:
+ uint32_t m_AllocationCount;
+ bool m_AllAllocations;
+
+ VkDeviceSize m_BytesMoved;
+ uint32_t m_AllocationsMoved;
+
+ struct AllocationInfoSizeGreater
+ {
+ bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const
+ {
+ return lhs.m_hAllocation->GetSize() > rhs.m_hAllocation->GetSize();
+ }
+ };
+
+ struct AllocationInfoOffsetGreater
+ {
+ bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const
+ {
+ return lhs.m_hAllocation->GetOffset() > rhs.m_hAllocation->GetOffset();
+ }
+ };
+
+ struct BlockInfo
+ {
+ size_t m_OriginalBlockIndex;
+ VmaDeviceMemoryBlock* m_pBlock;
+ bool m_HasNonMovableAllocations;
+ VmaVector< AllocationInfo, VmaStlAllocator<AllocationInfo> > m_Allocations;
+
+ BlockInfo(const VkAllocationCallbacks* pAllocationCallbacks) :
+ m_OriginalBlockIndex(SIZE_MAX),
+ m_pBlock(VMA_NULL),
+ m_HasNonMovableAllocations(true),
+ m_Allocations(pAllocationCallbacks)
+ {
+ }
+
+ void CalcHasNonMovableAllocations()
+ {
+ const size_t blockAllocCount = m_pBlock->m_pMetadata->GetAllocationCount();
+ const size_t defragmentAllocCount = m_Allocations.size();
+ m_HasNonMovableAllocations = blockAllocCount != defragmentAllocCount;
+ }
+
+ void SortAllocationsBySizeDescending()
+ {
+ VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoSizeGreater());
+ }
+
+ void SortAllocationsByOffsetDescending()
+ {
+ VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoOffsetGreater());
+ }
+ };
+
+ struct BlockPointerLess
+ {
+ bool operator()(const BlockInfo* pLhsBlockInfo, const VmaDeviceMemoryBlock* pRhsBlock) const
+ {
+ return pLhsBlockInfo->m_pBlock < pRhsBlock;
+ }
+ bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const
+ {
+ return pLhsBlockInfo->m_pBlock < pRhsBlockInfo->m_pBlock;
+ }
+ };
+
+ // 1. Blocks with some non-movable allocations go first.
+ // 2. Blocks with smaller sumFreeSize go first.
+ struct BlockInfoCompareMoveDestination
+ {
+ bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const
+ {
+ if(pLhsBlockInfo->m_HasNonMovableAllocations && !pRhsBlockInfo->m_HasNonMovableAllocations)
+ {
+ return true;
+ }
+ if(!pLhsBlockInfo->m_HasNonMovableAllocations && pRhsBlockInfo->m_HasNonMovableAllocations)
+ {
+ return false;
+ }
+ if(pLhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize() < pRhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize())
+ {
+ return true;
+ }
+ return false;
+ }
+ };
+
+ typedef VmaVector< BlockInfo*, VmaStlAllocator<BlockInfo*> > BlockInfoVector;
+ BlockInfoVector m_Blocks;
+
+ VkResult DefragmentRound(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove);
+
+ size_t CalcBlocksWithNonMovableCount() const;
+
+ static bool MoveMakesSense(
+ size_t dstBlockIndex, VkDeviceSize dstOffset,
+ size_t srcBlockIndex, VkDeviceSize srcOffset);
+};
+
+class VmaDefragmentationAlgorithm_Fast : public VmaDefragmentationAlgorithm
+{
+ VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Fast)
+public:
+ VmaDefragmentationAlgorithm_Fast(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex,
+ bool overlappingMoveSupported);
+ virtual ~VmaDefragmentationAlgorithm_Fast();
+
+ virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) { ++m_AllocationCount; }
+ virtual void AddAll() { m_AllAllocations = true; }
+
+ virtual VkResult Defragment(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove);
+
+ virtual VkDeviceSize GetBytesMoved() const { return m_BytesMoved; }
+ virtual uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; }
+
+private:
+ struct BlockInfo
+ {
+ size_t origBlockIndex;
+ };
+
+ class FreeSpaceDatabase
+ {
+ public:
+ FreeSpaceDatabase()
+ {
+ FreeSpace s = {};
+ s.blockInfoIndex = SIZE_MAX;
+ for(size_t i = 0; i < MAX_COUNT; ++i)
+ {
+ m_FreeSpaces[i] = s;
+ }
+ }
+
+ void Register(size_t blockInfoIndex, VkDeviceSize offset, VkDeviceSize size)
+ {
+ if(size < VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ return;
+ }
+
+ // Find first invalid or the smallest structure.
+ size_t bestIndex = SIZE_MAX;
+ for(size_t i = 0; i < MAX_COUNT; ++i)
+ {
+ // Empty structure.
+ if(m_FreeSpaces[i].blockInfoIndex == SIZE_MAX)
+ {
+ bestIndex = i;
+ break;
+ }
+ if(m_FreeSpaces[i].size < size &&
+ (bestIndex == SIZE_MAX || m_FreeSpaces[bestIndex].size > m_FreeSpaces[i].size))
+ {
+ bestIndex = i;
+ }
+ }
+
+ if(bestIndex != SIZE_MAX)
+ {
+ m_FreeSpaces[bestIndex].blockInfoIndex = blockInfoIndex;
+ m_FreeSpaces[bestIndex].offset = offset;
+ m_FreeSpaces[bestIndex].size = size;
+ }
+ }
+
+ bool Fetch(VkDeviceSize alignment, VkDeviceSize size,
+ size_t& outBlockInfoIndex, VkDeviceSize& outDstOffset)
+ {
+ size_t bestIndex = SIZE_MAX;
+ VkDeviceSize bestFreeSpaceAfter = 0;
+ for(size_t i = 0; i < MAX_COUNT; ++i)
+ {
+ // Structure is valid.
+ if(m_FreeSpaces[i].blockInfoIndex != SIZE_MAX)
+ {
+ const VkDeviceSize dstOffset = VmaAlignUp(m_FreeSpaces[i].offset, alignment);
+ // Allocation fits into this structure.
+ if(dstOffset + size <= m_FreeSpaces[i].offset + m_FreeSpaces[i].size)
+ {
+ const VkDeviceSize freeSpaceAfter = (m_FreeSpaces[i].offset + m_FreeSpaces[i].size) -
+ (dstOffset + size);
+ if(bestIndex == SIZE_MAX || freeSpaceAfter > bestFreeSpaceAfter)
+ {
+ bestIndex = i;
+ bestFreeSpaceAfter = freeSpaceAfter;
+ }
+ }
+ }
+ }
+
+ if(bestIndex != SIZE_MAX)
+ {
+ outBlockInfoIndex = m_FreeSpaces[bestIndex].blockInfoIndex;
+ outDstOffset = VmaAlignUp(m_FreeSpaces[bestIndex].offset, alignment);
+
+ if(bestFreeSpaceAfter >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ // Leave this structure for remaining empty space.
+ const VkDeviceSize alignmentPlusSize = (outDstOffset - m_FreeSpaces[bestIndex].offset) + size;
+ m_FreeSpaces[bestIndex].offset += alignmentPlusSize;
+ m_FreeSpaces[bestIndex].size -= alignmentPlusSize;
+ }
+ else
+ {
+ // This structure becomes invalid.
+ m_FreeSpaces[bestIndex].blockInfoIndex = SIZE_MAX;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private:
+ static const size_t MAX_COUNT = 4;
+
+ struct FreeSpace
+ {
+ size_t blockInfoIndex; // SIZE_MAX means this structure is invalid.
+ VkDeviceSize offset;
+ VkDeviceSize size;
+ } m_FreeSpaces[MAX_COUNT];
+ };
+
+ const bool m_OverlappingMoveSupported;
+
+ uint32_t m_AllocationCount;
+ bool m_AllAllocations;
+
+ VkDeviceSize m_BytesMoved;
+ uint32_t m_AllocationsMoved;
+
+ VmaVector< BlockInfo, VmaStlAllocator<BlockInfo> > m_BlockInfos;
+
+ void PreprocessMetadata();
+ void PostprocessMetadata();
+ void InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, const VmaSuballocation& suballoc);
+};
+
+struct VmaBlockDefragmentationContext
+{
+ enum BLOCK_FLAG
+ {
+ BLOCK_FLAG_USED = 0x00000001,
+ };
+ uint32_t flags;
+ VkBuffer hBuffer;
+};
+
+class VmaBlockVectorDefragmentationContext
+{
+ VMA_CLASS_NO_COPY(VmaBlockVectorDefragmentationContext)
+public:
+ VkResult res;
+ bool mutexLocked;
+ VmaVector< VmaBlockDefragmentationContext, VmaStlAllocator<VmaBlockDefragmentationContext> > blockContexts;
+
+ VmaBlockVectorDefragmentationContext(
+ VmaAllocator hAllocator,
+ VmaPool hCustomPool, // Optional.
+ VmaBlockVector* pBlockVector,
+ uint32_t currFrameIndex);
+ ~VmaBlockVectorDefragmentationContext();
+
+ VmaPool GetCustomPool() const { return m_hCustomPool; }
+ VmaBlockVector* GetBlockVector() const { return m_pBlockVector; }
+ VmaDefragmentationAlgorithm* GetAlgorithm() const { return m_pAlgorithm; }
+
+ void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
+ void AddAll() { m_AllAllocations = true; }
+
+ void Begin(bool overlappingMoveSupported);
+
+private:
+ const VmaAllocator m_hAllocator;
+ // Null if not from custom pool.
+ const VmaPool m_hCustomPool;
+ // Redundant, for convenience not to fetch from m_hCustomPool->m_BlockVector or m_hAllocator->m_pBlockVectors.
+ VmaBlockVector* const m_pBlockVector;
+ const uint32_t m_CurrFrameIndex;
+ // Owner of this object.
+ VmaDefragmentationAlgorithm* m_pAlgorithm;
+
+ struct AllocInfo
+ {
+ VmaAllocation hAlloc;
+ VkBool32* pChanged;
+ };
+ // Used between constructor and Begin.
+ VmaVector< AllocInfo, VmaStlAllocator<AllocInfo> > m_Allocations;
+ bool m_AllAllocations;
+};
+
+struct VmaDefragmentationContext_T
+{
+private:
+ VMA_CLASS_NO_COPY(VmaDefragmentationContext_T)
+public:
+ VmaDefragmentationContext_T(
+ VmaAllocator hAllocator,
+ uint32_t currFrameIndex,
+ uint32_t flags,
+ VmaDefragmentationStats* pStats);
+ ~VmaDefragmentationContext_T();
+
+ void AddPools(uint32_t poolCount, VmaPool* pPools);
+ void AddAllocations(
+ uint32_t allocationCount,
+ VmaAllocation* pAllocations,
+ VkBool32* pAllocationsChanged);
+
+ /*
+ Returns:
+ - `VK_SUCCESS` if succeeded and object can be destroyed immediately.
+ - `VK_NOT_READY` if succeeded but the object must remain alive until vmaDefragmentationEnd().
+ - Negative value if error occured and object can be destroyed immediately.
+ */
+ VkResult Defragment(
+ VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove,
+ VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove,
+ VkCommandBuffer commandBuffer, VmaDefragmentationStats* pStats);
+
+private:
+ const VmaAllocator m_hAllocator;
+ const uint32_t m_CurrFrameIndex;
+ const uint32_t m_Flags;
+ VmaDefragmentationStats* const m_pStats;
+ // Owner of these objects.
+ VmaBlockVectorDefragmentationContext* m_DefaultPoolContexts[VK_MAX_MEMORY_TYPES];
+ // Owner of these objects.
+ VmaVector< VmaBlockVectorDefragmentationContext*, VmaStlAllocator<VmaBlockVectorDefragmentationContext*> > m_CustomPoolContexts;
+};
+
+#if VMA_RECORDING_ENABLED
+
+class VmaRecorder
+{
+public:
+ VmaRecorder();
+ VkResult Init(const VmaRecordSettings& settings, bool useMutex);
+ void WriteConfiguration(
+ const VkPhysicalDeviceProperties& devProps,
+ const VkPhysicalDeviceMemoryProperties& memProps,
+ uint32_t vulkanApiVersion,
+ bool dedicatedAllocationExtensionEnabled,
+ bool bindMemory2ExtensionEnabled,
+ bool memoryBudgetExtensionEnabled);
+ ~VmaRecorder();
+
+ void RecordCreateAllocator(uint32_t frameIndex);
+ void RecordDestroyAllocator(uint32_t frameIndex);
+ void RecordCreatePool(uint32_t frameIndex,
+ const VmaPoolCreateInfo& createInfo,
+ VmaPool pool);
+ void RecordDestroyPool(uint32_t frameIndex, VmaPool pool);
+ void RecordAllocateMemory(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation);
+ void RecordAllocateMemoryPages(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ const VmaAllocationCreateInfo& createInfo,
+ uint64_t allocationCount,
+ const VmaAllocation* pAllocations);
+ void RecordAllocateMemoryForBuffer(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation);
+ void RecordAllocateMemoryForImage(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation);
+ void RecordFreeMemory(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordFreeMemoryPages(uint32_t frameIndex,
+ uint64_t allocationCount,
+ const VmaAllocation* pAllocations);
+ void RecordSetAllocationUserData(uint32_t frameIndex,
+ VmaAllocation allocation,
+ const void* pUserData);
+ void RecordCreateLostAllocation(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordMapMemory(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordUnmapMemory(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordFlushAllocation(uint32_t frameIndex,
+ VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+ void RecordInvalidateAllocation(uint32_t frameIndex,
+ VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+ void RecordCreateBuffer(uint32_t frameIndex,
+ const VkBufferCreateInfo& bufCreateInfo,
+ const VmaAllocationCreateInfo& allocCreateInfo,
+ VmaAllocation allocation);
+ void RecordCreateImage(uint32_t frameIndex,
+ const VkImageCreateInfo& imageCreateInfo,
+ const VmaAllocationCreateInfo& allocCreateInfo,
+ VmaAllocation allocation);
+ void RecordDestroyBuffer(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordDestroyImage(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordTouchAllocation(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordGetAllocationInfo(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordMakePoolAllocationsLost(uint32_t frameIndex,
+ VmaPool pool);
+ void RecordDefragmentationBegin(uint32_t frameIndex,
+ const VmaDefragmentationInfo2& info,
+ VmaDefragmentationContext ctx);
+ void RecordDefragmentationEnd(uint32_t frameIndex,
+ VmaDefragmentationContext ctx);
+ void RecordSetPoolName(uint32_t frameIndex,
+ VmaPool pool,
+ const char* name);
+
+private:
+ struct CallParams
+ {
+ uint32_t threadId;
+ double time;
+ };
+
+ class UserDataString
+ {
+ public:
+ UserDataString(VmaAllocationCreateFlags allocFlags, const void* pUserData);
+ const char* GetString() const { return m_Str; }
+
+ private:
+ char m_PtrStr[17];
+ const char* m_Str;
+ };
+
+ bool m_UseMutex;
+ VmaRecordFlags m_Flags;
+ FILE* m_File;
+ VMA_MUTEX m_FileMutex;
+ int64_t m_Freq;
+ int64_t m_StartCounter;
+
+ void GetBasicParams(CallParams& outParams);
+
+ // T must be a pointer type, e.g. VmaAllocation, VmaPool.
+ template<typename T>
+ void PrintPointerList(uint64_t count, const T* pItems)
+ {
+ if(count)
+ {
+ fprintf(m_File, "%p", pItems[0]);
+ for(uint64_t i = 1; i < count; ++i)
+ {
+ fprintf(m_File, " %p", pItems[i]);
+ }
+ }
+ }
+
+ void PrintPointerList(uint64_t count, const VmaAllocation* pItems);
+ void Flush();
+};
+
+#endif // #if VMA_RECORDING_ENABLED
+
+/*
+Thread-safe wrapper over VmaPoolAllocator free list, for allocation of VmaAllocation_T objects.
+*/
+class VmaAllocationObjectAllocator
+{
+ VMA_CLASS_NO_COPY(VmaAllocationObjectAllocator)
+public:
+ VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks);
+
+ VmaAllocation Allocate();
+ void Free(VmaAllocation hAlloc);
+
+private:
+ VMA_MUTEX m_Mutex;
+ VmaPoolAllocator<VmaAllocation_T> m_Allocator;
+};
+
+struct VmaCurrentBudgetData
+{
+ VMA_ATOMIC_UINT64 m_BlockBytes[VK_MAX_MEMORY_HEAPS];
+ VMA_ATOMIC_UINT64 m_AllocationBytes[VK_MAX_MEMORY_HEAPS];
+
+#if VMA_MEMORY_BUDGET
+ VMA_ATOMIC_UINT32 m_OperationsSinceBudgetFetch;
+ VMA_RW_MUTEX m_BudgetMutex;
+ uint64_t m_VulkanUsage[VK_MAX_MEMORY_HEAPS];
+ uint64_t m_VulkanBudget[VK_MAX_MEMORY_HEAPS];
+ uint64_t m_BlockBytesAtBudgetFetch[VK_MAX_MEMORY_HEAPS];
+#endif // #if VMA_MEMORY_BUDGET
+
+ VmaCurrentBudgetData()
+ {
+ for(uint32_t heapIndex = 0; heapIndex < VK_MAX_MEMORY_HEAPS; ++heapIndex)
+ {
+ m_BlockBytes[heapIndex] = 0;
+ m_AllocationBytes[heapIndex] = 0;
+#if VMA_MEMORY_BUDGET
+ m_VulkanUsage[heapIndex] = 0;
+ m_VulkanBudget[heapIndex] = 0;
+ m_BlockBytesAtBudgetFetch[heapIndex] = 0;
+#endif
+ }
+
+#if VMA_MEMORY_BUDGET
+ m_OperationsSinceBudgetFetch = 0;
+#endif
+ }
+
+ void AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)
+ {
+ m_AllocationBytes[heapIndex] += allocationSize;
+#if VMA_MEMORY_BUDGET
+ ++m_OperationsSinceBudgetFetch;
+#endif
+ }
+
+ void RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)
+ {
+ VMA_ASSERT(m_AllocationBytes[heapIndex] >= allocationSize); // DELME
+ m_AllocationBytes[heapIndex] -= allocationSize;
+#if VMA_MEMORY_BUDGET
+ ++m_OperationsSinceBudgetFetch;
+#endif
+ }
+};
+
+// Main allocator object.
+struct VmaAllocator_T
+{
+ VMA_CLASS_NO_COPY(VmaAllocator_T)
+public:
+ bool m_UseMutex;
+ uint32_t m_VulkanApiVersion;
+ bool m_UseKhrDedicatedAllocation; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0).
+ bool m_UseKhrBindMemory2; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0).
+ bool m_UseExtMemoryBudget;
+ VkDevice m_hDevice;
+ VkInstance m_hInstance;
+ bool m_AllocationCallbacksSpecified;
+ VkAllocationCallbacks m_AllocationCallbacks;
+ VmaDeviceMemoryCallbacks m_DeviceMemoryCallbacks;
+ VmaAllocationObjectAllocator m_AllocationObjectAllocator;
+
+ // Each bit (1 << i) is set if HeapSizeLimit is enabled for that heap, so cannot allocate more than the heap size.
+ uint32_t m_HeapSizeLimitMask;
+
+ VkPhysicalDeviceProperties m_PhysicalDeviceProperties;
+ VkPhysicalDeviceMemoryProperties m_MemProps;
+
+ // Default pools.
+ VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES];
+
+ // Each vector is sorted by memory (handle value).
+ typedef VmaVector< VmaAllocation, VmaStlAllocator<VmaAllocation> > AllocationVectorType;
+ AllocationVectorType* m_pDedicatedAllocations[VK_MAX_MEMORY_TYPES];
+ VMA_RW_MUTEX m_DedicatedAllocationsMutex[VK_MAX_MEMORY_TYPES];
+
+ VmaCurrentBudgetData m_Budget;
+
+ VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo);
+ VkResult Init(const VmaAllocatorCreateInfo* pCreateInfo);
+ ~VmaAllocator_T();
+
+ const VkAllocationCallbacks* GetAllocationCallbacks() const
+ {
+ return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : 0;
+ }
+ const VmaVulkanFunctions& GetVulkanFunctions() const
+ {
+ return m_VulkanFunctions;
+ }
+
+ VkDeviceSize GetBufferImageGranularity() const
+ {
+ return VMA_MAX(
+ static_cast<VkDeviceSize>(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY),
+ m_PhysicalDeviceProperties.limits.bufferImageGranularity);
+ }
+
+ uint32_t GetMemoryHeapCount() const { return m_MemProps.memoryHeapCount; }
+ uint32_t GetMemoryTypeCount() const { return m_MemProps.memoryTypeCount; }
+
+ uint32_t MemoryTypeIndexToHeapIndex(uint32_t memTypeIndex) const
+ {
+ VMA_ASSERT(memTypeIndex < m_MemProps.memoryTypeCount);
+ return m_MemProps.memoryTypes[memTypeIndex].heapIndex;
+ }
+ // True when specific memory type is HOST_VISIBLE but not HOST_COHERENT.
+ bool IsMemoryTypeNonCoherent(uint32_t memTypeIndex) const
+ {
+ return (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ }
+ // Minimum alignment for all allocations in specific memory type.
+ VkDeviceSize GetMemoryTypeMinAlignment(uint32_t memTypeIndex) const
+ {
+ return IsMemoryTypeNonCoherent(memTypeIndex) ?
+ VMA_MAX((VkDeviceSize)VMA_DEBUG_ALIGNMENT, m_PhysicalDeviceProperties.limits.nonCoherentAtomSize) :
+ (VkDeviceSize)VMA_DEBUG_ALIGNMENT;
+ }
+
+ bool IsIntegratedGpu() const
+ {
+ return m_PhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
+ }
+
+#if VMA_RECORDING_ENABLED
+ VmaRecorder* GetRecorder() const { return m_pRecorder; }
+#endif
+
+ void GetBufferMemoryRequirements(
+ VkBuffer hBuffer,
+ VkMemoryRequirements& memReq,
+ bool& requiresDedicatedAllocation,
+ bool& prefersDedicatedAllocation) const;
+ void GetImageMemoryRequirements(
+ VkImage hImage,
+ VkMemoryRequirements& memReq,
+ bool& requiresDedicatedAllocation,
+ bool& prefersDedicatedAllocation) const;
+
+ // Main allocation function.
+ VkResult AllocateMemory(
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ // Main deallocation function.
+ void FreeMemory(
+ size_t allocationCount,
+ const VmaAllocation* pAllocations);
+
+ VkResult ResizeAllocation(
+ const VmaAllocation alloc,
+ VkDeviceSize newSize);
+
+ void CalculateStats(VmaStats* pStats);
+
+ void GetBudget(
+ VmaBudget* outBudget, uint32_t firstHeap, uint32_t heapCount);
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap(class VmaJsonWriter& json);
+#endif
+
+ VkResult DefragmentationBegin(
+ const VmaDefragmentationInfo2& info,
+ VmaDefragmentationStats* pStats,
+ VmaDefragmentationContext* pContext);
+ VkResult DefragmentationEnd(
+ VmaDefragmentationContext context);
+
+ void GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo);
+ bool TouchAllocation(VmaAllocation hAllocation);
+
+ VkResult CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool);
+ void DestroyPool(VmaPool pool);
+ void GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats);
+
+ void SetCurrentFrameIndex(uint32_t frameIndex);
+ uint32_t GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); }
+
+ void MakePoolAllocationsLost(
+ VmaPool hPool,
+ size_t* pLostAllocationCount);
+ VkResult CheckPoolCorruption(VmaPool hPool);
+ VkResult CheckCorruption(uint32_t memoryTypeBits);
+
+ void CreateLostAllocation(VmaAllocation* pAllocation);
+
+ // Call to Vulkan function vkAllocateMemory with accompanying bookkeeping.
+ VkResult AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory);
+ // Call to Vulkan function vkFreeMemory with accompanying bookkeeping.
+ void FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory);
+ // Call to Vulkan function vkBindBufferMemory or vkBindBufferMemory2KHR.
+ VkResult BindVulkanBuffer(
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset,
+ VkBuffer buffer,
+ const void* pNext);
+ // Call to Vulkan function vkBindImageMemory or vkBindImageMemory2KHR.
+ VkResult BindVulkanImage(
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset,
+ VkImage image,
+ const void* pNext);
+
+ VkResult Map(VmaAllocation hAllocation, void** ppData);
+ void Unmap(VmaAllocation hAllocation);
+
+ VkResult BindBufferMemory(
+ VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkBuffer hBuffer,
+ const void* pNext);
+ VkResult BindImageMemory(
+ VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkImage hImage,
+ const void* pNext);
+
+ void FlushOrInvalidateAllocation(
+ VmaAllocation hAllocation,
+ VkDeviceSize offset, VkDeviceSize size,
+ VMA_CACHE_OPERATION op);
+
+ void FillAllocation(const VmaAllocation hAllocation, uint8_t pattern);
+
+ /*
+ Returns bit mask of memory types that can support defragmentation on GPU as
+ they support creation of required buffer for copy operations.
+ */
+ uint32_t GetGpuDefragmentationMemoryTypeBits();
+
+private:
+ VkDeviceSize m_PreferredLargeHeapBlockSize;
+
+ VkPhysicalDevice m_PhysicalDevice;
+ VMA_ATOMIC_UINT32 m_CurrentFrameIndex;
+ VMA_ATOMIC_UINT32 m_GpuDefragmentationMemoryTypeBits; // UINT32_MAX means uninitialized.
+
+ VMA_RW_MUTEX m_PoolsMutex;
+ // Protected by m_PoolsMutex. Sorted by pointer value.
+ VmaVector<VmaPool, VmaStlAllocator<VmaPool> > m_Pools;
+ uint32_t m_NextPoolId;
+
+ VmaVulkanFunctions m_VulkanFunctions;
+
+#if VMA_RECORDING_ENABLED
+ VmaRecorder* m_pRecorder;
+#endif
+
+ void ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions);
+
+ VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);
+
+ VkResult AllocateMemoryOfType(
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ bool dedicatedAllocation,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ const VmaAllocationCreateInfo& createInfo,
+ uint32_t memTypeIndex,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ // Helper function only to be used inside AllocateDedicatedMemory.
+ VkResult AllocateDedicatedMemoryPage(
+ VkDeviceSize size,
+ VmaSuballocationType suballocType,
+ uint32_t memTypeIndex,
+ const VkMemoryAllocateInfo& allocInfo,
+ bool map,
+ bool isUserDataString,
+ void* pUserData,
+ VmaAllocation* pAllocation);
+
+ // Allocates and registers new VkDeviceMemory specifically for dedicated allocations.
+ VkResult AllocateDedicatedMemory(
+ VkDeviceSize size,
+ VmaSuballocationType suballocType,
+ uint32_t memTypeIndex,
+ bool withinBudget,
+ bool map,
+ bool isUserDataString,
+ void* pUserData,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ void FreeDedicatedMemory(const VmaAllocation allocation);
+
+ /*
+ Calculates and returns bit mask of memory types that can support defragmentation
+ on GPU as they support creation of required buffer for copy operations.
+ */
+ uint32_t CalculateGpuDefragmentationMemoryTypeBits() const;
+
+#if VMA_MEMORY_BUDGET
+ void UpdateVulkanBudget();
+#endif // #if VMA_MEMORY_BUDGET
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Memory allocation #2 after VmaAllocator_T definition
+
+static void* VmaMalloc(VmaAllocator hAllocator, size_t size, size_t alignment)
+{
+ return VmaMalloc(&hAllocator->m_AllocationCallbacks, size, alignment);
+}
+
+static void VmaFree(VmaAllocator hAllocator, void* ptr)
+{
+ VmaFree(&hAllocator->m_AllocationCallbacks, ptr);
+}
+
+template<typename T>
+static T* VmaAllocate(VmaAllocator hAllocator)
+{
+ return (T*)VmaMalloc(hAllocator, sizeof(T), VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static T* VmaAllocateArray(VmaAllocator hAllocator, size_t count)
+{
+ return (T*)VmaMalloc(hAllocator, sizeof(T) * count, VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static void vma_delete(VmaAllocator hAllocator, T* ptr)
+{
+ if(ptr != VMA_NULL)
+ {
+ ptr->~T();
+ VmaFree(hAllocator, ptr);
+ }
+}
+
+template<typename T>
+static void vma_delete_array(VmaAllocator hAllocator, T* ptr, size_t count)
+{
+ if(ptr != VMA_NULL)
+ {
+ for(size_t i = count; i--; )
+ ptr[i].~T();
+ VmaFree(hAllocator, ptr);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaStringBuilder
+
+#if VMA_STATS_STRING_ENABLED
+
+class VmaStringBuilder
+{
+public:
+ VmaStringBuilder(VmaAllocator alloc) : m_Data(VmaStlAllocator<char>(alloc->GetAllocationCallbacks())) { }
+ size_t GetLength() const { return m_Data.size(); }
+ const char* GetData() const { return m_Data.data(); }
+
+ void Add(char ch) { m_Data.push_back(ch); }
+ void Add(const char* pStr);
+ void AddNewLine() { Add('\n'); }
+ void AddNumber(uint32_t num);
+ void AddNumber(uint64_t num);
+ void AddPointer(const void* ptr);
+
+private:
+ VmaVector< char, VmaStlAllocator<char> > m_Data;
+};
+
+void VmaStringBuilder::Add(const char* pStr)
+{
+ const size_t strLen = strlen(pStr);
+ if(strLen > 0)
+ {
+ const size_t oldCount = m_Data.size();
+ m_Data.resize(oldCount + strLen);
+ memcpy(m_Data.data() + oldCount, pStr, strLen);
+ }
+}
+
+void VmaStringBuilder::AddNumber(uint32_t num)
+{
+ char buf[11];
+ buf[10] = '\0';
+ char *p = &buf[10];
+ do
+ {
+ *--p = '0' + (num % 10);
+ num /= 10;
+ }
+ while(num);
+ Add(p);
+}
+
+void VmaStringBuilder::AddNumber(uint64_t num)
+{
+ char buf[21];
+ buf[20] = '\0';
+ char *p = &buf[20];
+ do
+ {
+ *--p = '0' + (num % 10);
+ num /= 10;
+ }
+ while(num);
+ Add(p);
+}
+
+void VmaStringBuilder::AddPointer(const void* ptr)
+{
+ char buf[21];
+ VmaPtrToStr(buf, sizeof(buf), ptr);
+ Add(buf);
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaJsonWriter
+
+#if VMA_STATS_STRING_ENABLED
+
+class VmaJsonWriter
+{
+ VMA_CLASS_NO_COPY(VmaJsonWriter)
+public:
+ VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb);
+ ~VmaJsonWriter();
+
+ void BeginObject(bool singleLine = false);
+ void EndObject();
+
+ void BeginArray(bool singleLine = false);
+ void EndArray();
+
+ void WriteString(const char* pStr);
+ void BeginString(const char* pStr = VMA_NULL);
+ void ContinueString(const char* pStr);
+ void ContinueString(uint32_t n);
+ void ContinueString(uint64_t n);
+ void ContinueString_Pointer(const void* ptr);
+ void EndString(const char* pStr = VMA_NULL);
+
+ void WriteNumber(uint32_t n);
+ void WriteNumber(uint64_t n);
+ void WriteBool(bool b);
+ void WriteNull();
+
+private:
+ static const char* const INDENT;
+
+ enum COLLECTION_TYPE
+ {
+ COLLECTION_TYPE_OBJECT,
+ COLLECTION_TYPE_ARRAY,
+ };
+ struct StackItem
+ {
+ COLLECTION_TYPE type;
+ uint32_t valueCount;
+ bool singleLineMode;
+ };
+
+ VmaStringBuilder& m_SB;
+ VmaVector< StackItem, VmaStlAllocator<StackItem> > m_Stack;
+ bool m_InsideString;
+
+ void BeginValue(bool isString);
+ void WriteIndent(bool oneLess = false);
+};
+
+const char* const VmaJsonWriter::INDENT = " ";
+
+VmaJsonWriter::VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb) :
+ m_SB(sb),
+ m_Stack(VmaStlAllocator<StackItem>(pAllocationCallbacks)),
+ m_InsideString(false)
+{
+}
+
+VmaJsonWriter::~VmaJsonWriter()
+{
+ VMA_ASSERT(!m_InsideString);
+ VMA_ASSERT(m_Stack.empty());
+}
+
+void VmaJsonWriter::BeginObject(bool singleLine)
+{
+ VMA_ASSERT(!m_InsideString);
+
+ BeginValue(false);
+ m_SB.Add('{');
+
+ StackItem item;
+ item.type = COLLECTION_TYPE_OBJECT;
+ item.valueCount = 0;
+ item.singleLineMode = singleLine;
+ m_Stack.push_back(item);
+}
+
+void VmaJsonWriter::EndObject()
+{
+ VMA_ASSERT(!m_InsideString);
+
+ WriteIndent(true);
+ m_SB.Add('}');
+
+ VMA_ASSERT(!m_Stack.empty() && m_Stack.back().type == COLLECTION_TYPE_OBJECT);
+ m_Stack.pop_back();
+}
+
+void VmaJsonWriter::BeginArray(bool singleLine)
+{
+ VMA_ASSERT(!m_InsideString);
+
+ BeginValue(false);
+ m_SB.Add('[');
+
+ StackItem item;
+ item.type = COLLECTION_TYPE_ARRAY;
+ item.valueCount = 0;
+ item.singleLineMode = singleLine;
+ m_Stack.push_back(item);
+}
+
+void VmaJsonWriter::EndArray()
+{
+ VMA_ASSERT(!m_InsideString);
+
+ WriteIndent(true);
+ m_SB.Add(']');
+
+ VMA_ASSERT(!m_Stack.empty() && m_Stack.back().type == COLLECTION_TYPE_ARRAY);
+ m_Stack.pop_back();
+}
+
+void VmaJsonWriter::WriteString(const char* pStr)
+{
+ BeginString(pStr);
+ EndString();
+}
+
+void VmaJsonWriter::BeginString(const char* pStr)
+{
+ VMA_ASSERT(!m_InsideString);
+
+ BeginValue(true);
+ m_SB.Add('"');
+ m_InsideString = true;
+ if(pStr != VMA_NULL && pStr[0] != '\0')
+ {
+ ContinueString(pStr);
+ }
+}
+
+void VmaJsonWriter::ContinueString(const char* pStr)
+{
+ VMA_ASSERT(m_InsideString);
+
+ const size_t strLen = strlen(pStr);
+ for(size_t i = 0; i < strLen; ++i)
+ {
+ char ch = pStr[i];
+ if(ch == '\\')
+ {
+ m_SB.Add("\\\\");
+ }
+ else if(ch == '"')
+ {
+ m_SB.Add("\\\"");
+ }
+ else if(ch >= 32)
+ {
+ m_SB.Add(ch);
+ }
+ else switch(ch)
+ {
+ case '\b':
+ m_SB.Add("\\b");
+ break;
+ case '\f':
+ m_SB.Add("\\f");
+ break;
+ case '\n':
+ m_SB.Add("\\n");
+ break;
+ case '\r':
+ m_SB.Add("\\r");
+ break;
+ case '\t':
+ m_SB.Add("\\t");
+ break;
+ default:
+ VMA_ASSERT(0 && "Character not currently supported.");
+ break;
+ }
+ }
+}
+
+void VmaJsonWriter::ContinueString(uint32_t n)
+{
+ VMA_ASSERT(m_InsideString);
+ m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::ContinueString(uint64_t n)
+{
+ VMA_ASSERT(m_InsideString);
+ m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::ContinueString_Pointer(const void* ptr)
+{
+ VMA_ASSERT(m_InsideString);
+ m_SB.AddPointer(ptr);
+}
+
+void VmaJsonWriter::EndString(const char* pStr)
+{
+ VMA_ASSERT(m_InsideString);
+ if(pStr != VMA_NULL && pStr[0] != '\0')
+ {
+ ContinueString(pStr);
+ }
+ m_SB.Add('"');
+ m_InsideString = false;
+}
+
+void VmaJsonWriter::WriteNumber(uint32_t n)
+{
+ VMA_ASSERT(!m_InsideString);
+ BeginValue(false);
+ m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::WriteNumber(uint64_t n)
+{
+ VMA_ASSERT(!m_InsideString);
+ BeginValue(false);
+ m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::WriteBool(bool b)
+{
+ VMA_ASSERT(!m_InsideString);
+ BeginValue(false);
+ m_SB.Add(b ? "true" : "false");
+}
+
+void VmaJsonWriter::WriteNull()
+{
+ VMA_ASSERT(!m_InsideString);
+ BeginValue(false);
+ m_SB.Add("null");
+}
+
+void VmaJsonWriter::BeginValue(bool isString)
+{
+ if(!m_Stack.empty())
+ {
+ StackItem& currItem = m_Stack.back();
+ if(currItem.type == COLLECTION_TYPE_OBJECT &&
+ currItem.valueCount % 2 == 0)
+ {
+ VMA_ASSERT(isString);
+ }
+
+ if(currItem.type == COLLECTION_TYPE_OBJECT &&
+ currItem.valueCount % 2 != 0)
+ {
+ m_SB.Add(": ");
+ }
+ else if(currItem.valueCount > 0)
+ {
+ m_SB.Add(", ");
+ WriteIndent();
+ }
+ else
+ {
+ WriteIndent();
+ }
+ ++currItem.valueCount;
+ }
+}
+
+void VmaJsonWriter::WriteIndent(bool oneLess)
+{
+ if(!m_Stack.empty() && !m_Stack.back().singleLineMode)
+ {
+ m_SB.AddNewLine();
+
+ size_t count = m_Stack.size();
+ if(count > 0 && oneLess)
+ {
+ --count;
+ }
+ for(size_t i = 0; i < count; ++i)
+ {
+ m_SB.Add(INDENT);
+ }
+ }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+
+void VmaAllocation_T::SetUserData(VmaAllocator hAllocator, void* pUserData)
+{
+ if(IsUserDataString())
+ {
+ VMA_ASSERT(pUserData == VMA_NULL || pUserData != m_pUserData);
+
+ FreeUserDataString(hAllocator);
+
+ if(pUserData != VMA_NULL)
+ {
+ m_pUserData = VmaCreateStringCopy(hAllocator->GetAllocationCallbacks(), (const char*)pUserData);
+ }
+ }
+ else
+ {
+ m_pUserData = pUserData;
+ }
+}
+
+void VmaAllocation_T::ChangeBlockAllocation(
+ VmaAllocator hAllocator,
+ VmaDeviceMemoryBlock* block,
+ VkDeviceSize offset)
+{
+ VMA_ASSERT(block != VMA_NULL);
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+
+ // Move mapping reference counter from old block to new block.
+ if(block != m_BlockAllocation.m_Block)
+ {
+ uint32_t mapRefCount = m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP;
+ if(IsPersistentMap())
+ ++mapRefCount;
+ m_BlockAllocation.m_Block->Unmap(hAllocator, mapRefCount);
+ block->Map(hAllocator, mapRefCount, VMA_NULL);
+ }
+
+ m_BlockAllocation.m_Block = block;
+ m_BlockAllocation.m_Offset = offset;
+}
+
+void VmaAllocation_T::ChangeOffset(VkDeviceSize newOffset)
+{
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+ m_BlockAllocation.m_Offset = newOffset;
+}
+
+VkDeviceSize VmaAllocation_T::GetOffset() const
+{
+ switch(m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_Offset;
+ case ALLOCATION_TYPE_DEDICATED:
+ return 0;
+ default:
+ VMA_ASSERT(0);
+ return 0;
+ }
+}
+
+VkDeviceMemory VmaAllocation_T::GetMemory() const
+{
+ switch(m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_Block->GetDeviceMemory();
+ case ALLOCATION_TYPE_DEDICATED:
+ return m_DedicatedAllocation.m_hMemory;
+ default:
+ VMA_ASSERT(0);
+ return VK_NULL_HANDLE;
+ }
+}
+
+void* VmaAllocation_T::GetMappedData() const
+{
+ switch(m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ if(m_MapCount != 0)
+ {
+ void* pBlockData = m_BlockAllocation.m_Block->GetMappedData();
+ VMA_ASSERT(pBlockData != VMA_NULL);
+ return (char*)pBlockData + m_BlockAllocation.m_Offset;
+ }
+ else
+ {
+ return VMA_NULL;
+ }
+ break;
+ case ALLOCATION_TYPE_DEDICATED:
+ VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0));
+ return m_DedicatedAllocation.m_pMappedData;
+ default:
+ VMA_ASSERT(0);
+ return VMA_NULL;
+ }
+}
+
+bool VmaAllocation_T::CanBecomeLost() const
+{
+ switch(m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_CanBecomeLost;
+ case ALLOCATION_TYPE_DEDICATED:
+ return false;
+ default:
+ VMA_ASSERT(0);
+ return false;
+ }
+}
+
+bool VmaAllocation_T::MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+ VMA_ASSERT(CanBecomeLost());
+
+ /*
+ Warning: This is a carefully designed algorithm.
+ Do not modify unless you really know what you're doing :)
+ */
+ uint32_t localLastUseFrameIndex = GetLastUseFrameIndex();
+ for(;;)
+ {
+ if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
+ {
+ VMA_ASSERT(0);
+ return false;
+ }
+ else if(localLastUseFrameIndex + frameInUseCount >= currentFrameIndex)
+ {
+ return false;
+ }
+ else // Last use time earlier than current time.
+ {
+ if(CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, VMA_FRAME_INDEX_LOST))
+ {
+ // Setting hAllocation.LastUseFrameIndex atomic to VMA_FRAME_INDEX_LOST is enough to mark it as LOST.
+ // Calling code just needs to unregister this allocation in owning VmaDeviceMemoryBlock.
+ return true;
+ }
+ }
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+// Correspond to values of enum VmaSuballocationType.
+static const char* VMA_SUBALLOCATION_TYPE_NAMES[] = {
+ "FREE",
+ "UNKNOWN",
+ "BUFFER",
+ "IMAGE_UNKNOWN",
+ "IMAGE_LINEAR",
+ "IMAGE_OPTIMAL",
+};
+
+void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const
+{
+ json.WriteString("Type");
+ json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[m_SuballocationType]);
+
+ json.WriteString("Size");
+ json.WriteNumber(m_Size);
+
+ if(m_pUserData != VMA_NULL)
+ {
+ json.WriteString("UserData");
+ if(IsUserDataString())
+ {
+ json.WriteString((const char*)m_pUserData);
+ }
+ else
+ {
+ json.BeginString();
+ json.ContinueString_Pointer(m_pUserData);
+ json.EndString();
+ }
+ }
+
+ json.WriteString("CreationFrameIndex");
+ json.WriteNumber(m_CreationFrameIndex);
+
+ json.WriteString("LastUseFrameIndex");
+ json.WriteNumber(GetLastUseFrameIndex());
+
+ if(m_BufferImageUsage != 0)
+ {
+ json.WriteString("Usage");
+ json.WriteNumber(m_BufferImageUsage);
+ }
+}
+
+#endif
+
+void VmaAllocation_T::FreeUserDataString(VmaAllocator hAllocator)
+{
+ VMA_ASSERT(IsUserDataString());
+ VmaFreeString(hAllocator->GetAllocationCallbacks(), (char*)m_pUserData);
+ m_pUserData = VMA_NULL;
+}
+
+void VmaAllocation_T::BlockAllocMap()
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);
+
+ if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F)
+ {
+ ++m_MapCount;
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Allocation mapped too many times simultaneously.");
+ }
+}
+
+void VmaAllocation_T::BlockAllocUnmap()
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);
+
+ if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0)
+ {
+ --m_MapCount;
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Unmapping allocation not previously mapped.");
+ }
+}
+
+VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppData)
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
+
+ if(m_MapCount != 0)
+ {
+ if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F)
+ {
+ VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);
+ *ppData = m_DedicatedAllocation.m_pMappedData;
+ ++m_MapCount;
+ return VK_SUCCESS;
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Dedicated allocation mapped too many times simultaneously.");
+ return VK_ERROR_MEMORY_MAP_FAILED;
+ }
+ }
+ else
+ {
+ VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)(
+ hAllocator->m_hDevice,
+ m_DedicatedAllocation.m_hMemory,
+ 0, // offset
+ VK_WHOLE_SIZE,
+ 0, // flags
+ ppData);
+ if(result == VK_SUCCESS)
+ {
+ m_DedicatedAllocation.m_pMappedData = *ppData;
+ m_MapCount = 1;
+ }
+ return result;
+ }
+}
+
+void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator)
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
+
+ if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0)
+ {
+ --m_MapCount;
+ if(m_MapCount == 0)
+ {
+ m_DedicatedAllocation.m_pMappedData = VMA_NULL;
+ (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(
+ hAllocator->m_hDevice,
+ m_DedicatedAllocation.m_hMemory);
+ }
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Unmapping dedicated allocation not previously mapped.");
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+static void VmaPrintStatInfo(VmaJsonWriter& json, const VmaStatInfo& stat)
+{
+ json.BeginObject();
+
+ json.WriteString("Blocks");
+ json.WriteNumber(stat.blockCount);
+
+ json.WriteString("Allocations");
+ json.WriteNumber(stat.allocationCount);
+
+ json.WriteString("UnusedRanges");
+ json.WriteNumber(stat.unusedRangeCount);
+
+ json.WriteString("UsedBytes");
+ json.WriteNumber(stat.usedBytes);
+
+ json.WriteString("UnusedBytes");
+ json.WriteNumber(stat.unusedBytes);
+
+ if(stat.allocationCount > 1)
+ {
+ json.WriteString("AllocationSize");
+ json.BeginObject(true);
+ json.WriteString("Min");
+ json.WriteNumber(stat.allocationSizeMin);
+ json.WriteString("Avg");
+ json.WriteNumber(stat.allocationSizeAvg);
+ json.WriteString("Max");
+ json.WriteNumber(stat.allocationSizeMax);
+ json.EndObject();
+ }
+
+ if(stat.unusedRangeCount > 1)
+ {
+ json.WriteString("UnusedRangeSize");
+ json.BeginObject(true);
+ json.WriteString("Min");
+ json.WriteNumber(stat.unusedRangeSizeMin);
+ json.WriteString("Avg");
+ json.WriteNumber(stat.unusedRangeSizeAvg);
+ json.WriteString("Max");
+ json.WriteNumber(stat.unusedRangeSizeMax);
+ json.EndObject();
+ }
+
+ json.EndObject();
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+struct VmaSuballocationItemSizeLess
+{
+ bool operator()(
+ const VmaSuballocationList::iterator lhs,
+ const VmaSuballocationList::iterator rhs) const
+ {
+ return lhs->size < rhs->size;
+ }
+ bool operator()(
+ const VmaSuballocationList::iterator lhs,
+ VkDeviceSize rhsSize) const
+ {
+ return lhs->size < rhsSize;
+ }
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata
+
+VmaBlockMetadata::VmaBlockMetadata(VmaAllocator hAllocator) :
+ m_Size(0),
+ m_pAllocationCallbacks(hAllocator->GetAllocationCallbacks())
+{
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockMetadata::PrintDetailedMap_Begin(class VmaJsonWriter& json,
+ VkDeviceSize unusedBytes,
+ size_t allocationCount,
+ size_t unusedRangeCount) const
+{
+ json.BeginObject();
+
+ json.WriteString("TotalBytes");
+ json.WriteNumber(GetSize());
+
+ json.WriteString("UnusedBytes");
+ json.WriteNumber(unusedBytes);
+
+ json.WriteString("Allocations");
+ json.WriteNumber((uint64_t)allocationCount);
+
+ json.WriteString("UnusedRanges");
+ json.WriteNumber((uint64_t)unusedRangeCount);
+
+ json.WriteString("Suballocations");
+ json.BeginArray();
+}
+
+void VmaBlockMetadata::PrintDetailedMap_Allocation(class VmaJsonWriter& json,
+ VkDeviceSize offset,
+ VmaAllocation hAllocation) const
+{
+ json.BeginObject(true);
+
+ json.WriteString("Offset");
+ json.WriteNumber(offset);
+
+ hAllocation->PrintParameters(json);
+
+ json.EndObject();
+}
+
+void VmaBlockMetadata::PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,
+ VkDeviceSize offset,
+ VkDeviceSize size) const
+{
+ json.BeginObject(true);
+
+ json.WriteString("Offset");
+ json.WriteNumber(offset);
+
+ json.WriteString("Type");
+ json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[VMA_SUBALLOCATION_TYPE_FREE]);
+
+ json.WriteString("Size");
+ json.WriteNumber(size);
+
+ json.EndObject();
+}
+
+void VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json) const
+{
+ json.EndArray();
+ json.EndObject();
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata_Generic
+
+VmaBlockMetadata_Generic::VmaBlockMetadata_Generic(VmaAllocator hAllocator) :
+ VmaBlockMetadata(hAllocator),
+ m_FreeCount(0),
+ m_SumFreeSize(0),
+ m_Suballocations(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
+ m_FreeSuballocationsBySize(VmaStlAllocator<VmaSuballocationList::iterator>(hAllocator->GetAllocationCallbacks()))
+{
+}
+
+VmaBlockMetadata_Generic::~VmaBlockMetadata_Generic()
+{
+}
+
+void VmaBlockMetadata_Generic::Init(VkDeviceSize size)
+{
+ VmaBlockMetadata::Init(size);
+
+ m_FreeCount = 1;
+ m_SumFreeSize = size;
+
+ VmaSuballocation suballoc = {};
+ suballoc.offset = 0;
+ suballoc.size = size;
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ suballoc.hAllocation = VK_NULL_HANDLE;
+
+ VMA_ASSERT(size > VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
+ m_Suballocations.push_back(suballoc);
+ VmaSuballocationList::iterator suballocItem = m_Suballocations.end();
+ --suballocItem;
+ m_FreeSuballocationsBySize.push_back(suballocItem);
+}
+
+bool VmaBlockMetadata_Generic::Validate() const
+{
+ VMA_VALIDATE(!m_Suballocations.empty());
+
+ // Expected offset of new suballocation as calculated from previous ones.
+ VkDeviceSize calculatedOffset = 0;
+ // Expected number of free suballocations as calculated from traversing their list.
+ uint32_t calculatedFreeCount = 0;
+ // Expected sum size of free suballocations as calculated from traversing their list.
+ VkDeviceSize calculatedSumFreeSize = 0;
+ // Expected number of free suballocations that should be registered in
+ // m_FreeSuballocationsBySize calculated from traversing their list.
+ size_t freeSuballocationsToRegister = 0;
+ // True if previous visited suballocation was free.
+ bool prevFree = false;
+
+ for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();
+ suballocItem != m_Suballocations.cend();
+ ++suballocItem)
+ {
+ const VmaSuballocation& subAlloc = *suballocItem;
+
+ // Actual offset of this suballocation doesn't match expected one.
+ VMA_VALIDATE(subAlloc.offset == calculatedOffset);
+
+ const bool currFree = (subAlloc.type == VMA_SUBALLOCATION_TYPE_FREE);
+ // Two adjacent free suballocations are invalid. They should be merged.
+ VMA_VALIDATE(!prevFree || !currFree);
+
+ VMA_VALIDATE(currFree == (subAlloc.hAllocation == VK_NULL_HANDLE));
+
+ if(currFree)
+ {
+ calculatedSumFreeSize += subAlloc.size;
+ ++calculatedFreeCount;
+ if(subAlloc.size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ ++freeSuballocationsToRegister;
+ }
+
+ // Margin required between allocations - every free space must be at least that large.
+ VMA_VALIDATE(subAlloc.size >= VMA_DEBUG_MARGIN);
+ }
+ else
+ {
+ VMA_VALIDATE(subAlloc.hAllocation->GetOffset() == subAlloc.offset);
+ VMA_VALIDATE(subAlloc.hAllocation->GetSize() == subAlloc.size);
+
+ // Margin required between allocations - previous allocation must be free.
+ VMA_VALIDATE(VMA_DEBUG_MARGIN == 0 || prevFree);
+ }
+
+ calculatedOffset += subAlloc.size;
+ prevFree = currFree;
+ }
+
+ // Number of free suballocations registered in m_FreeSuballocationsBySize doesn't
+ // match expected one.
+ VMA_VALIDATE(m_FreeSuballocationsBySize.size() == freeSuballocationsToRegister);
+
+ VkDeviceSize lastSize = 0;
+ for(size_t i = 0; i < m_FreeSuballocationsBySize.size(); ++i)
+ {
+ VmaSuballocationList::iterator suballocItem = m_FreeSuballocationsBySize[i];
+
+ // Only free suballocations can be registered in m_FreeSuballocationsBySize.
+ VMA_VALIDATE(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE);
+ // They must be sorted by size ascending.
+ VMA_VALIDATE(suballocItem->size >= lastSize);
+
+ lastSize = suballocItem->size;
+ }
+
+ // Check if totals match calculacted values.
+ VMA_VALIDATE(ValidateFreeSuballocationList());
+ VMA_VALIDATE(calculatedOffset == GetSize());
+ VMA_VALIDATE(calculatedSumFreeSize == m_SumFreeSize);
+ VMA_VALIDATE(calculatedFreeCount == m_FreeCount);
+
+ return true;
+}
+
+VkDeviceSize VmaBlockMetadata_Generic::GetUnusedRangeSizeMax() const
+{
+ if(!m_FreeSuballocationsBySize.empty())
+ {
+ return m_FreeSuballocationsBySize.back()->size;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+bool VmaBlockMetadata_Generic::IsEmpty() const
+{
+ return (m_Suballocations.size() == 1) && (m_FreeCount == 1);
+}
+
+void VmaBlockMetadata_Generic::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
+{
+ outInfo.blockCount = 1;
+
+ const uint32_t rangeCount = (uint32_t)m_Suballocations.size();
+ outInfo.allocationCount = rangeCount - m_FreeCount;
+ outInfo.unusedRangeCount = m_FreeCount;
+
+ outInfo.unusedBytes = m_SumFreeSize;
+ outInfo.usedBytes = GetSize() - outInfo.unusedBytes;
+
+ outInfo.allocationSizeMin = UINT64_MAX;
+ outInfo.allocationSizeMax = 0;
+ outInfo.unusedRangeSizeMin = UINT64_MAX;
+ outInfo.unusedRangeSizeMax = 0;
+
+ for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();
+ suballocItem != m_Suballocations.cend();
+ ++suballocItem)
+ {
+ const VmaSuballocation& suballoc = *suballocItem;
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+ outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, suballoc.size);
+ }
+ else
+ {
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, suballoc.size);
+ outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, suballoc.size);
+ }
+ }
+}
+
+void VmaBlockMetadata_Generic::AddPoolStats(VmaPoolStats& inoutStats) const
+{
+ const uint32_t rangeCount = (uint32_t)m_Suballocations.size();
+
+ inoutStats.size += GetSize();
+ inoutStats.unusedSize += m_SumFreeSize;
+ inoutStats.allocationCount += rangeCount - m_FreeCount;
+ inoutStats.unusedRangeCount += m_FreeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, GetUnusedRangeSizeMax());
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockMetadata_Generic::PrintDetailedMap(class VmaJsonWriter& json) const
+{
+ PrintDetailedMap_Begin(json,
+ m_SumFreeSize, // unusedBytes
+ m_Suballocations.size() - (size_t)m_FreeCount, // allocationCount
+ m_FreeCount); // unusedRangeCount
+
+ size_t i = 0;
+ for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();
+ suballocItem != m_Suballocations.cend();
+ ++suballocItem, ++i)
+ {
+ if(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ PrintDetailedMap_UnusedRange(json, suballocItem->offset, suballocItem->size);
+ }
+ else
+ {
+ PrintDetailedMap_Allocation(json, suballocItem->offset, suballocItem->hAllocation);
+ }
+ }
+
+ PrintDetailedMap_End(json);
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+bool VmaBlockMetadata_Generic::CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ VMA_ASSERT(allocSize > 0);
+ VMA_ASSERT(!upperAddress);
+ VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(pAllocationRequest != VMA_NULL);
+ VMA_HEAVY_ASSERT(Validate());
+
+ pAllocationRequest->type = VmaAllocationRequestType::Normal;
+
+ // There is not enough total free space in this block to fullfill the request: Early return.
+ if(canMakeOtherLost == false &&
+ m_SumFreeSize < allocSize + 2 * VMA_DEBUG_MARGIN)
+ {
+ return false;
+ }
+
+ // New algorithm, efficiently searching freeSuballocationsBySize.
+ const size_t freeSuballocCount = m_FreeSuballocationsBySize.size();
+ if(freeSuballocCount > 0)
+ {
+ if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+ {
+ // Find first free suballocation with size not less than allocSize + 2 * VMA_DEBUG_MARGIN.
+ VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(
+ m_FreeSuballocationsBySize.data(),
+ m_FreeSuballocationsBySize.data() + freeSuballocCount,
+ allocSize + 2 * VMA_DEBUG_MARGIN,
+ VmaSuballocationItemSizeLess());
+ size_t index = it - m_FreeSuballocationsBySize.data();
+ for(; index < freeSuballocCount; ++index)
+ {
+ if(CheckAllocation(
+ currentFrameIndex,
+ frameInUseCount,
+ bufferImageGranularity,
+ allocSize,
+ allocAlignment,
+ allocType,
+ m_FreeSuballocationsBySize[index],
+ false, // canMakeOtherLost
+ &pAllocationRequest->offset,
+ &pAllocationRequest->itemsToMakeLostCount,
+ &pAllocationRequest->sumFreeSize,
+ &pAllocationRequest->sumItemSize))
+ {
+ pAllocationRequest->item = m_FreeSuballocationsBySize[index];
+ return true;
+ }
+ }
+ }
+ else if(strategy == VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET)
+ {
+ for(VmaSuballocationList::iterator it = m_Suballocations.begin();
+ it != m_Suballocations.end();
+ ++it)
+ {
+ if(it->type == VMA_SUBALLOCATION_TYPE_FREE && CheckAllocation(
+ currentFrameIndex,
+ frameInUseCount,
+ bufferImageGranularity,
+ allocSize,
+ allocAlignment,
+ allocType,
+ it,
+ false, // canMakeOtherLost
+ &pAllocationRequest->offset,
+ &pAllocationRequest->itemsToMakeLostCount,
+ &pAllocationRequest->sumFreeSize,
+ &pAllocationRequest->sumItemSize))
+ {
+ pAllocationRequest->item = it;
+ return true;
+ }
+ }
+ }
+ else // WORST_FIT, FIRST_FIT
+ {
+ // Search staring from biggest suballocations.
+ for(size_t index = freeSuballocCount; index--; )
+ {
+ if(CheckAllocation(
+ currentFrameIndex,
+ frameInUseCount,
+ bufferImageGranularity,
+ allocSize,
+ allocAlignment,
+ allocType,
+ m_FreeSuballocationsBySize[index],
+ false, // canMakeOtherLost
+ &pAllocationRequest->offset,
+ &pAllocationRequest->itemsToMakeLostCount,
+ &pAllocationRequest->sumFreeSize,
+ &pAllocationRequest->sumItemSize))
+ {
+ pAllocationRequest->item = m_FreeSuballocationsBySize[index];
+ return true;
+ }
+ }
+ }
+ }
+
+ if(canMakeOtherLost)
+ {
+ // Brute-force algorithm. TODO: Come up with something better.
+
+ bool found = false;
+ VmaAllocationRequest tmpAllocRequest = {};
+ tmpAllocRequest.type = VmaAllocationRequestType::Normal;
+ for(VmaSuballocationList::iterator suballocIt = m_Suballocations.begin();
+ suballocIt != m_Suballocations.end();
+ ++suballocIt)
+ {
+ if(suballocIt->type == VMA_SUBALLOCATION_TYPE_FREE ||
+ suballocIt->hAllocation->CanBecomeLost())
+ {
+ if(CheckAllocation(
+ currentFrameIndex,
+ frameInUseCount,
+ bufferImageGranularity,
+ allocSize,
+ allocAlignment,
+ allocType,
+ suballocIt,
+ canMakeOtherLost,
+ &tmpAllocRequest.offset,
+ &tmpAllocRequest.itemsToMakeLostCount,
+ &tmpAllocRequest.sumFreeSize,
+ &tmpAllocRequest.sumItemSize))
+ {
+ if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
+ {
+ *pAllocationRequest = tmpAllocRequest;
+ pAllocationRequest->item = suballocIt;
+ break;
+ }
+ if(!found || tmpAllocRequest.CalcCost() < pAllocationRequest->CalcCost())
+ {
+ *pAllocationRequest = tmpAllocRequest;
+ pAllocationRequest->item = suballocIt;
+ found = true;
+ }
+ }
+ }
+ }
+
+ return found;
+ }
+
+ return false;
+}
+
+bool VmaBlockMetadata_Generic::MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ VMA_ASSERT(pAllocationRequest && pAllocationRequest->type == VmaAllocationRequestType::Normal);
+
+ while(pAllocationRequest->itemsToMakeLostCount > 0)
+ {
+ if(pAllocationRequest->item->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ ++pAllocationRequest->item;
+ }
+ VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end());
+ VMA_ASSERT(pAllocationRequest->item->hAllocation != VK_NULL_HANDLE);
+ VMA_ASSERT(pAllocationRequest->item->hAllocation->CanBecomeLost());
+ if(pAllocationRequest->item->hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ {
+ pAllocationRequest->item = FreeSuballocation(pAllocationRequest->item);
+ --pAllocationRequest->itemsToMakeLostCount;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ VMA_HEAVY_ASSERT(Validate());
+ VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end());
+ VMA_ASSERT(pAllocationRequest->item->type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ return true;
+}
+
+uint32_t VmaBlockMetadata_Generic::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+ uint32_t lostAllocationCount = 0;
+ for(VmaSuballocationList::iterator it = m_Suballocations.begin();
+ it != m_Suballocations.end();
+ ++it)
+ {
+ if(it->type != VMA_SUBALLOCATION_TYPE_FREE &&
+ it->hAllocation->CanBecomeLost() &&
+ it->hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ {
+ it = FreeSuballocation(it);
+ ++lostAllocationCount;
+ }
+ }
+ return lostAllocationCount;
+}
+
+VkResult VmaBlockMetadata_Generic::CheckCorruption(const void* pBlockData)
+{
+ for(VmaSuballocationList::iterator it = m_Suballocations.begin();
+ it != m_Suballocations.end();
+ ++it)
+ {
+ if(it->type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ if(!VmaValidateMagicValue(pBlockData, it->offset - VMA_DEBUG_MARGIN))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ if(!VmaValidateMagicValue(pBlockData, it->offset + it->size))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaBlockMetadata_Generic::Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ VmaAllocation hAllocation)
+{
+ VMA_ASSERT(request.type == VmaAllocationRequestType::Normal);
+ VMA_ASSERT(request.item != m_Suballocations.end());
+ VmaSuballocation& suballoc = *request.item;
+ // Given suballocation is a free block.
+ VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+ // Given offset is inside this suballocation.
+ VMA_ASSERT(request.offset >= suballoc.offset);
+ const VkDeviceSize paddingBegin = request.offset - suballoc.offset;
+ VMA_ASSERT(suballoc.size >= paddingBegin + allocSize);
+ const VkDeviceSize paddingEnd = suballoc.size - paddingBegin - allocSize;
+
+ // Unregister this free suballocation from m_FreeSuballocationsBySize and update
+ // it to become used.
+ UnregisterFreeSuballocation(request.item);
+
+ suballoc.offset = request.offset;
+ suballoc.size = allocSize;
+ suballoc.type = type;
+ suballoc.hAllocation = hAllocation;
+
+ // If there are any free bytes remaining at the end, insert new free suballocation after current one.
+ if(paddingEnd)
+ {
+ VmaSuballocation paddingSuballoc = {};
+ paddingSuballoc.offset = request.offset + allocSize;
+ paddingSuballoc.size = paddingEnd;
+ paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ VmaSuballocationList::iterator next = request.item;
+ ++next;
+ const VmaSuballocationList::iterator paddingEndItem =
+ m_Suballocations.insert(next, paddingSuballoc);
+ RegisterFreeSuballocation(paddingEndItem);
+ }
+
+ // If there are any free bytes remaining at the beginning, insert new free suballocation before current one.
+ if(paddingBegin)
+ {
+ VmaSuballocation paddingSuballoc = {};
+ paddingSuballoc.offset = request.offset - paddingBegin;
+ paddingSuballoc.size = paddingBegin;
+ paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ const VmaSuballocationList::iterator paddingBeginItem =
+ m_Suballocations.insert(request.item, paddingSuballoc);
+ RegisterFreeSuballocation(paddingBeginItem);
+ }
+
+ // Update totals.
+ m_FreeCount = m_FreeCount - 1;
+ if(paddingBegin > 0)
+ {
+ ++m_FreeCount;
+ }
+ if(paddingEnd > 0)
+ {
+ ++m_FreeCount;
+ }
+ m_SumFreeSize -= allocSize;
+}
+
+void VmaBlockMetadata_Generic::Free(const VmaAllocation allocation)
+{
+ for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
+ suballocItem != m_Suballocations.end();
+ ++suballocItem)
+ {
+ VmaSuballocation& suballoc = *suballocItem;
+ if(suballoc.hAllocation == allocation)
+ {
+ FreeSuballocation(suballocItem);
+ VMA_HEAVY_ASSERT(Validate());
+ return;
+ }
+ }
+ VMA_ASSERT(0 && "Not found!");
+}
+
+void VmaBlockMetadata_Generic::FreeAtOffset(VkDeviceSize offset)
+{
+ for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
+ suballocItem != m_Suballocations.end();
+ ++suballocItem)
+ {
+ VmaSuballocation& suballoc = *suballocItem;
+ if(suballoc.offset == offset)
+ {
+ FreeSuballocation(suballocItem);
+ return;
+ }
+ }
+ VMA_ASSERT(0 && "Not found!");
+}
+
+bool VmaBlockMetadata_Generic::ValidateFreeSuballocationList() const
+{
+ VkDeviceSize lastSize = 0;
+ for(size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i)
+ {
+ const VmaSuballocationList::iterator it = m_FreeSuballocationsBySize[i];
+
+ VMA_VALIDATE(it->type == VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_VALIDATE(it->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
+ VMA_VALIDATE(it->size >= lastSize);
+ lastSize = it->size;
+ }
+ return true;
+}
+
+bool VmaBlockMetadata_Generic::CheckAllocation(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ VmaSuballocationList::const_iterator suballocItem,
+ bool canMakeOtherLost,
+ VkDeviceSize* pOffset,
+ size_t* itemsToMakeLostCount,
+ VkDeviceSize* pSumFreeSize,
+ VkDeviceSize* pSumItemSize) const
+{
+ VMA_ASSERT(allocSize > 0);
+ VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(suballocItem != m_Suballocations.cend());
+ VMA_ASSERT(pOffset != VMA_NULL);
+
+ *itemsToMakeLostCount = 0;
+ *pSumFreeSize = 0;
+ *pSumItemSize = 0;
+
+ if(canMakeOtherLost)
+ {
+ if(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ *pSumFreeSize = suballocItem->size;
+ }
+ else
+ {
+ if(suballocItem->hAllocation->CanBecomeLost() &&
+ suballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+ {
+ ++*itemsToMakeLostCount;
+ *pSumItemSize = suballocItem->size;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Remaining size is too small for this request: Early return.
+ if(GetSize() - suballocItem->offset < allocSize)
+ {
+ return false;
+ }
+
+ // Start from offset equal to beginning of this suballocation.
+ *pOffset = suballocItem->offset;
+
+ // Apply VMA_DEBUG_MARGIN at the beginning.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
+ *pOffset += VMA_DEBUG_MARGIN;
+ }
+
+ // Apply alignment.
+ *pOffset = VmaAlignUp(*pOffset, allocAlignment);
+
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if(bufferImageGranularity > 1)
+ {
+ bool bufferImageGranularityConflict = false;
+ VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
+ while(prevSuballocItem != m_Suballocations.cbegin())
+ {
+ --prevSuballocItem;
+ const VmaSuballocation& prevSuballoc = *prevSuballocItem;
+ if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
+ }
+ else
+ // Already on previous page.
+ break;
+ }
+ if(bufferImageGranularityConflict)
+ {
+ *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity);
+ }
+ }
+
+ // Now that we have final *pOffset, check if we are past suballocItem.
+ // If yes, return false - this function should be called for another suballocItem as starting point.
+ if(*pOffset >= suballocItem->offset + suballocItem->size)
+ {
+ return false;
+ }
+
+ // Calculate padding at the beginning based on current offset.
+ const VkDeviceSize paddingBegin = *pOffset - suballocItem->offset;
+
+ // Calculate required margin at the end.
+ const VkDeviceSize requiredEndMargin = VMA_DEBUG_MARGIN;
+
+ const VkDeviceSize totalSize = paddingBegin + allocSize + requiredEndMargin;
+ // Another early return check.
+ if(suballocItem->offset + totalSize > GetSize())
+ {
+ return false;
+ }
+
+ // Advance lastSuballocItem until desired size is reached.
+ // Update itemsToMakeLostCount.
+ VmaSuballocationList::const_iterator lastSuballocItem = suballocItem;
+ if(totalSize > suballocItem->size)
+ {
+ VkDeviceSize remainingSize = totalSize - suballocItem->size;
+ while(remainingSize > 0)
+ {
+ ++lastSuballocItem;
+ if(lastSuballocItem == m_Suballocations.cend())
+ {
+ return false;
+ }
+ if(lastSuballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ *pSumFreeSize += lastSuballocItem->size;
+ }
+ else
+ {
+ VMA_ASSERT(lastSuballocItem->hAllocation != VK_NULL_HANDLE);
+ if(lastSuballocItem->hAllocation->CanBecomeLost() &&
+ lastSuballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+ {
+ ++*itemsToMakeLostCount;
+ *pSumItemSize += lastSuballocItem->size;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ remainingSize = (lastSuballocItem->size < remainingSize) ?
+ remainingSize - lastSuballocItem->size : 0;
+ }
+ }
+
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, we must mark more allocations lost or fail.
+ if(bufferImageGranularity > 1)
+ {
+ VmaSuballocationList::const_iterator nextSuballocItem = lastSuballocItem;
+ ++nextSuballocItem;
+ while(nextSuballocItem != m_Suballocations.cend())
+ {
+ const VmaSuballocation& nextSuballoc = *nextSuballocItem;
+ if(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+ {
+ VMA_ASSERT(nextSuballoc.hAllocation != VK_NULL_HANDLE);
+ if(nextSuballoc.hAllocation->CanBecomeLost() &&
+ nextSuballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+ {
+ ++*itemsToMakeLostCount;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
+ ++nextSuballocItem;
+ }
+ }
+ }
+ else
+ {
+ const VmaSuballocation& suballoc = *suballocItem;
+ VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ *pSumFreeSize = suballoc.size;
+
+ // Size of this suballocation is too small for this request: Early return.
+ if(suballoc.size < allocSize)
+ {
+ return false;
+ }
+
+ // Start from offset equal to beginning of this suballocation.
+ *pOffset = suballoc.offset;
+
+ // Apply VMA_DEBUG_MARGIN at the beginning.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
+ *pOffset += VMA_DEBUG_MARGIN;
+ }
+
+ // Apply alignment.
+ *pOffset = VmaAlignUp(*pOffset, allocAlignment);
+
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if(bufferImageGranularity > 1)
+ {
+ bool bufferImageGranularityConflict = false;
+ VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
+ while(prevSuballocItem != m_Suballocations.cbegin())
+ {
+ --prevSuballocItem;
+ const VmaSuballocation& prevSuballoc = *prevSuballocItem;
+ if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
+ }
+ else
+ // Already on previous page.
+ break;
+ }
+ if(bufferImageGranularityConflict)
+ {
+ *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity);
+ }
+ }
+
+ // Calculate padding at the beginning based on current offset.
+ const VkDeviceSize paddingBegin = *pOffset - suballoc.offset;
+
+ // Calculate required margin at the end.
+ const VkDeviceSize requiredEndMargin = VMA_DEBUG_MARGIN;
+
+ // Fail if requested size plus margin before and after is bigger than size of this suballocation.
+ if(paddingBegin + allocSize + requiredEndMargin > suballoc.size)
+ {
+ return false;
+ }
+
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, allocation cannot be made here.
+ if(bufferImageGranularity > 1)
+ {
+ VmaSuballocationList::const_iterator nextSuballocItem = suballocItem;
+ ++nextSuballocItem;
+ while(nextSuballocItem != m_Suballocations.cend())
+ {
+ const VmaSuballocation& nextSuballoc = *nextSuballocItem;
+ if(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
+ ++nextSuballocItem;
+ }
+ }
+ }
+
+ // All tests passed: Success. pOffset is already filled.
+ return true;
+}
+
+void VmaBlockMetadata_Generic::MergeFreeWithNext(VmaSuballocationList::iterator item)
+{
+ VMA_ASSERT(item != m_Suballocations.end());
+ VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ VmaSuballocationList::iterator nextItem = item;
+ ++nextItem;
+ VMA_ASSERT(nextItem != m_Suballocations.end());
+ VMA_ASSERT(nextItem->type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ item->size += nextItem->size;
+ --m_FreeCount;
+ m_Suballocations.erase(nextItem);
+}
+
+VmaSuballocationList::iterator VmaBlockMetadata_Generic::FreeSuballocation(VmaSuballocationList::iterator suballocItem)
+{
+ // Change this suballocation to be marked as free.
+ VmaSuballocation& suballoc = *suballocItem;
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ suballoc.hAllocation = VK_NULL_HANDLE;
+
+ // Update totals.
+ ++m_FreeCount;
+ m_SumFreeSize += suballoc.size;
+
+ // Merge with previous and/or next suballocation if it's also free.
+ bool mergeWithNext = false;
+ bool mergeWithPrev = false;
+
+ VmaSuballocationList::iterator nextItem = suballocItem;
+ ++nextItem;
+ if((nextItem != m_Suballocations.end()) && (nextItem->type == VMA_SUBALLOCATION_TYPE_FREE))
+ {
+ mergeWithNext = true;
+ }
+
+ VmaSuballocationList::iterator prevItem = suballocItem;
+ if(suballocItem != m_Suballocations.begin())
+ {
+ --prevItem;
+ if(prevItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ mergeWithPrev = true;
+ }
+ }
+
+ if(mergeWithNext)
+ {
+ UnregisterFreeSuballocation(nextItem);
+ MergeFreeWithNext(suballocItem);
+ }
+
+ if(mergeWithPrev)
+ {
+ UnregisterFreeSuballocation(prevItem);
+ MergeFreeWithNext(prevItem);
+ RegisterFreeSuballocation(prevItem);
+ return prevItem;
+ }
+ else
+ {
+ RegisterFreeSuballocation(suballocItem);
+ return suballocItem;
+ }
+}
+
+void VmaBlockMetadata_Generic::RegisterFreeSuballocation(VmaSuballocationList::iterator item)
+{
+ VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(item->size > 0);
+
+ // You may want to enable this validation at the beginning or at the end of
+ // this function, depending on what do you want to check.
+ VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+
+ if(item->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ if(m_FreeSuballocationsBySize.empty())
+ {
+ m_FreeSuballocationsBySize.push_back(item);
+ }
+ else
+ {
+ VmaVectorInsertSorted<VmaSuballocationItemSizeLess>(m_FreeSuballocationsBySize, item);
+ }
+ }
+
+ //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+}
+
+
+void VmaBlockMetadata_Generic::UnregisterFreeSuballocation(VmaSuballocationList::iterator item)
+{
+ VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(item->size > 0);
+
+ // You may want to enable this validation at the beginning or at the end of
+ // this function, depending on what do you want to check.
+ VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+
+ if(item->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(
+ m_FreeSuballocationsBySize.data(),
+ m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(),
+ item,
+ VmaSuballocationItemSizeLess());
+ for(size_t index = it - m_FreeSuballocationsBySize.data();
+ index < m_FreeSuballocationsBySize.size();
+ ++index)
+ {
+ if(m_FreeSuballocationsBySize[index] == item)
+ {
+ VmaVectorRemove(m_FreeSuballocationsBySize, index);
+ return;
+ }
+ VMA_ASSERT((m_FreeSuballocationsBySize[index]->size == item->size) && "Not found.");
+ }
+ VMA_ASSERT(0 && "Not found.");
+ }
+
+ //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+}
+
+bool VmaBlockMetadata_Generic::IsBufferImageGranularityConflictPossible(
+ VkDeviceSize bufferImageGranularity,
+ VmaSuballocationType& inOutPrevSuballocType) const
+{
+ if(bufferImageGranularity == 1 || IsEmpty())
+ {
+ return false;
+ }
+
+ VkDeviceSize minAlignment = VK_WHOLE_SIZE;
+ bool typeConflictFound = false;
+ for(VmaSuballocationList::const_iterator it = m_Suballocations.cbegin();
+ it != m_Suballocations.cend();
+ ++it)
+ {
+ const VmaSuballocationType suballocType = it->type;
+ if(suballocType != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ minAlignment = VMA_MIN(minAlignment, it->hAllocation->GetAlignment());
+ if(VmaIsBufferImageGranularityConflict(inOutPrevSuballocType, suballocType))
+ {
+ typeConflictFound = true;
+ }
+ inOutPrevSuballocType = suballocType;
+ }
+ }
+
+ return typeConflictFound || minAlignment >= bufferImageGranularity;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata_Linear
+
+VmaBlockMetadata_Linear::VmaBlockMetadata_Linear(VmaAllocator hAllocator) :
+ VmaBlockMetadata(hAllocator),
+ m_SumFreeSize(0),
+ m_Suballocations0(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
+ m_Suballocations1(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
+ m_1stVectorIndex(0),
+ m_2ndVectorMode(SECOND_VECTOR_EMPTY),
+ m_1stNullItemsBeginCount(0),
+ m_1stNullItemsMiddleCount(0),
+ m_2ndNullItemsCount(0)
+{
+}
+
+VmaBlockMetadata_Linear::~VmaBlockMetadata_Linear()
+{
+}
+
+void VmaBlockMetadata_Linear::Init(VkDeviceSize size)
+{
+ VmaBlockMetadata::Init(size);
+ m_SumFreeSize = size;
+}
+
+bool VmaBlockMetadata_Linear::Validate() const
+{
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ VMA_VALIDATE(suballocations2nd.empty() == (m_2ndVectorMode == SECOND_VECTOR_EMPTY));
+ VMA_VALIDATE(!suballocations1st.empty() ||
+ suballocations2nd.empty() ||
+ m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER);
+
+ if(!suballocations1st.empty())
+ {
+ // Null item at the beginning should be accounted into m_1stNullItemsBeginCount.
+ VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].hAllocation != VK_NULL_HANDLE);
+ // Null item at the end should be just pop_back().
+ VMA_VALIDATE(suballocations1st.back().hAllocation != VK_NULL_HANDLE);
+ }
+ if(!suballocations2nd.empty())
+ {
+ // Null item at the end should be just pop_back().
+ VMA_VALIDATE(suballocations2nd.back().hAllocation != VK_NULL_HANDLE);
+ }
+
+ VMA_VALIDATE(m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount <= suballocations1st.size());
+ VMA_VALIDATE(m_2ndNullItemsCount <= suballocations2nd.size());
+
+ VkDeviceSize sumUsedSize = 0;
+ const size_t suballoc1stCount = suballocations1st.size();
+ VkDeviceSize offset = VMA_DEBUG_MARGIN;
+
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ const size_t suballoc2ndCount = suballocations2nd.size();
+ size_t nullItem2ndCount = 0;
+ for(size_t i = 0; i < suballoc2ndCount; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[i];
+ const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+ VMA_VALIDATE(suballoc.offset >= offset);
+
+ if(!currFree)
+ {
+ VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
+ VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+ sumUsedSize += suballoc.size;
+ }
+ else
+ {
+ ++nullItem2ndCount;
+ }
+
+ offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+ }
+
+ VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);
+ }
+
+ for(size_t i = 0; i < m_1stNullItemsBeginCount; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[i];
+ VMA_VALIDATE(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE &&
+ suballoc.hAllocation == VK_NULL_HANDLE);
+ }
+
+ size_t nullItem1stCount = m_1stNullItemsBeginCount;
+
+ for(size_t i = m_1stNullItemsBeginCount; i < suballoc1stCount; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[i];
+ const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+ VMA_VALIDATE(suballoc.offset >= offset);
+ VMA_VALIDATE(i >= m_1stNullItemsBeginCount || currFree);
+
+ if(!currFree)
+ {
+ VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
+ VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+ sumUsedSize += suballoc.size;
+ }
+ else
+ {
+ ++nullItem1stCount;
+ }
+
+ offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+ }
+ VMA_VALIDATE(nullItem1stCount == m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount);
+
+ if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ const size_t suballoc2ndCount = suballocations2nd.size();
+ size_t nullItem2ndCount = 0;
+ for(size_t i = suballoc2ndCount; i--; )
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[i];
+ const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+ VMA_VALIDATE(suballoc.offset >= offset);
+
+ if(!currFree)
+ {
+ VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
+ VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+ sumUsedSize += suballoc.size;
+ }
+ else
+ {
+ ++nullItem2ndCount;
+ }
+
+ offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+ }
+
+ VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);
+ }
+
+ VMA_VALIDATE(offset <= GetSize());
+ VMA_VALIDATE(m_SumFreeSize == GetSize() - sumUsedSize);
+
+ return true;
+}
+
+size_t VmaBlockMetadata_Linear::GetAllocationCount() const
+{
+ return AccessSuballocations1st().size() - (m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount) +
+ AccessSuballocations2nd().size() - m_2ndNullItemsCount;
+}
+
+VkDeviceSize VmaBlockMetadata_Linear::GetUnusedRangeSizeMax() const
+{
+ const VkDeviceSize size = GetSize();
+
+ /*
+ We don't consider gaps inside allocation vectors with freed allocations because
+ they are not suitable for reuse in linear allocator. We consider only space that
+ is available for new allocations.
+ */
+ if(IsEmpty())
+ {
+ return size;
+ }
+
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+
+ switch(m_2ndVectorMode)
+ {
+ case SECOND_VECTOR_EMPTY:
+ /*
+ Available space is after end of 1st, as well as before beginning of 1st (which
+ whould make it a ring buffer).
+ */
+ {
+ const size_t suballocations1stCount = suballocations1st.size();
+ VMA_ASSERT(suballocations1stCount > m_1stNullItemsBeginCount);
+ const VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];
+ const VmaSuballocation& lastSuballoc = suballocations1st[suballocations1stCount - 1];
+ return VMA_MAX(
+ firstSuballoc.offset,
+ size - (lastSuballoc.offset + lastSuballoc.size));
+ }
+ break;
+
+ case SECOND_VECTOR_RING_BUFFER:
+ /*
+ Available space is only between end of 2nd and beginning of 1st.
+ */
+ {
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ const VmaSuballocation& lastSuballoc2nd = suballocations2nd.back();
+ const VmaSuballocation& firstSuballoc1st = suballocations1st[m_1stNullItemsBeginCount];
+ return firstSuballoc1st.offset - (lastSuballoc2nd.offset + lastSuballoc2nd.size);
+ }
+ break;
+
+ case SECOND_VECTOR_DOUBLE_STACK:
+ /*
+ Available space is only between end of 1st and top of 2nd.
+ */
+ {
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ const VmaSuballocation& topSuballoc2nd = suballocations2nd.back();
+ const VmaSuballocation& lastSuballoc1st = suballocations1st.back();
+ return topSuballoc2nd.offset - (lastSuballoc1st.offset + lastSuballoc1st.size);
+ }
+ break;
+
+ default:
+ VMA_ASSERT(0);
+ return 0;
+ }
+}
+
+void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
+{
+ const VkDeviceSize size = GetSize();
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ const size_t suballoc1stCount = suballocations1st.size();
+ const size_t suballoc2ndCount = suballocations2nd.size();
+
+ outInfo.blockCount = 1;
+ outInfo.allocationCount = (uint32_t)GetAllocationCount();
+ outInfo.unusedRangeCount = 0;
+ outInfo.usedBytes = 0;
+ outInfo.allocationSizeMin = UINT64_MAX;
+ outInfo.allocationSizeMax = 0;
+ outInfo.unusedRangeSizeMin = UINT64_MAX;
+ outInfo.unusedRangeSizeMax = 0;
+
+ VkDeviceSize lastOffset = 0;
+
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+ size_t nextAlloc2ndIndex = 0;
+ while(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex < suballoc2ndCount)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ outInfo.usedBytes += suballoc.size;
+ outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+ outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+ if(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace2ndTo1stEnd;
+ }
+ }
+ }
+
+ size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
+ const VkDeviceSize freeSpace1stTo2ndEnd =
+ m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
+ while(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc1stIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc1stIndex < suballoc1stCount)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ outInfo.usedBytes += suballoc.size;
+ outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+ outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc1stIndex;
+ }
+ // We are at the end.
+ else
+ {
+ // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+ if(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace1stTo2ndEnd;
+ }
+ }
+
+ if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+ while(lastOffset < size)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ --nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex != SIZE_MAX)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ outInfo.usedBytes += suballoc.size;
+ outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+ outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ --nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ // There is free space from lastOffset to size.
+ if(lastOffset < size)
+ {
+ const VkDeviceSize unusedRangeSize = size - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = size;
+ }
+ }
+ }
+
+ outInfo.unusedBytes = size - outInfo.usedBytes;
+}
+
+void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const
+{
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ const VkDeviceSize size = GetSize();
+ const size_t suballoc1stCount = suballocations1st.size();
+ const size_t suballoc2ndCount = suballocations2nd.size();
+
+ inoutStats.size += size;
+
+ VkDeviceSize lastOffset = 0;
+
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+ size_t nextAlloc2ndIndex = m_1stNullItemsBeginCount;
+ while(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex < suballoc2ndCount)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++inoutStats.allocationCount;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+ const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace2ndTo1stEnd;
+ }
+ }
+ }
+
+ size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
+ const VkDeviceSize freeSpace1stTo2ndEnd =
+ m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
+ while(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc1stIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc1stIndex < suballoc1stCount)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++inoutStats.allocationCount;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc1stIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+ const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace1stTo2ndEnd;
+ }
+ }
+
+ if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+ while(lastOffset < size)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ --nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex != SIZE_MAX)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++inoutStats.allocationCount;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ --nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < size)
+ {
+ // There is free space from lastOffset to size.
+ const VkDeviceSize unusedRangeSize = size - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = size;
+ }
+ }
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
+{
+ const VkDeviceSize size = GetSize();
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ const size_t suballoc1stCount = suballocations1st.size();
+ const size_t suballoc2ndCount = suballocations2nd.size();
+
+ // FIRST PASS
+
+ size_t unusedRangeCount = 0;
+ VkDeviceSize usedBytes = 0;
+
+ VkDeviceSize lastOffset = 0;
+
+ size_t alloc2ndCount = 0;
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+ size_t nextAlloc2ndIndex = 0;
+ while(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex < suballoc2ndCount)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ ++unusedRangeCount;
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++alloc2ndCount;
+ usedBytes += suballoc.size;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+ ++unusedRangeCount;
+ }
+
+ // End of loop.
+ lastOffset = freeSpace2ndTo1stEnd;
+ }
+ }
+ }
+
+ size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
+ size_t alloc1stCount = 0;
+ const VkDeviceSize freeSpace1stTo2ndEnd =
+ m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
+ while(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc1stIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc1stIndex < suballoc1stCount)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ ++unusedRangeCount;
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++alloc1stCount;
+ usedBytes += suballoc.size;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc1stIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < size)
+ {
+ // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+ ++unusedRangeCount;
+ }
+
+ // End of loop.
+ lastOffset = freeSpace1stTo2ndEnd;
+ }
+ }
+
+ if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+ while(lastOffset < size)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ --nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex != SIZE_MAX)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ ++unusedRangeCount;
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++alloc2ndCount;
+ usedBytes += suballoc.size;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ --nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < size)
+ {
+ // There is free space from lastOffset to size.
+ ++unusedRangeCount;
+ }
+
+ // End of loop.
+ lastOffset = size;
+ }
+ }
+ }
+
+ const VkDeviceSize unusedBytes = size - usedBytes;
+ PrintDetailedMap_Begin(json, unusedBytes, alloc1stCount + alloc2ndCount, unusedRangeCount);
+
+ // SECOND PASS
+ lastOffset = 0;
+
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+ size_t nextAlloc2ndIndex = 0;
+ while(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex < suballoc2ndCount)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+ const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace2ndTo1stEnd;
+ }
+ }
+ }
+
+ nextAlloc1stIndex = m_1stNullItemsBeginCount;
+ while(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc1stIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc1stIndex < suballoc1stCount)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc1stIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+ const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace1stTo2ndEnd;
+ }
+ }
+
+ if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+ while(lastOffset < size)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ --nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex != SIZE_MAX)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ --nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < size)
+ {
+ // There is free space from lastOffset to size.
+ const VkDeviceSize unusedRangeSize = size - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = size;
+ }
+ }
+ }
+
+ PrintDetailedMap_End(json);
+}
+#endif // #if VMA_STATS_STRING_ENABLED
+
+bool VmaBlockMetadata_Linear::CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ VMA_ASSERT(allocSize > 0);
+ VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(pAllocationRequest != VMA_NULL);
+ VMA_HEAVY_ASSERT(Validate());
+ return upperAddress ?
+ CreateAllocationRequest_UpperAddress(
+ currentFrameIndex, frameInUseCount, bufferImageGranularity,
+ allocSize, allocAlignment, allocType, canMakeOtherLost, strategy, pAllocationRequest) :
+ CreateAllocationRequest_LowerAddress(
+ currentFrameIndex, frameInUseCount, bufferImageGranularity,
+ allocSize, allocAlignment, allocType, canMakeOtherLost, strategy, pAllocationRequest);
+}
+
+bool VmaBlockMetadata_Linear::CreateAllocationRequest_UpperAddress(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ const VkDeviceSize size = GetSize();
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ VMA_ASSERT(0 && "Trying to use pool with linear algorithm as double stack, while it is already being used as ring buffer.");
+ return false;
+ }
+
+ // Try to allocate before 2nd.back(), or end of block if 2nd.empty().
+ if(allocSize > size)
+ {
+ return false;
+ }
+ VkDeviceSize resultBaseOffset = size - allocSize;
+ if(!suballocations2nd.empty())
+ {
+ const VmaSuballocation& lastSuballoc = suballocations2nd.back();
+ resultBaseOffset = lastSuballoc.offset - allocSize;
+ if(allocSize > lastSuballoc.offset)
+ {
+ return false;
+ }
+ }
+
+ // Start from offset equal to end of free space.
+ VkDeviceSize resultOffset = resultBaseOffset;
+
+ // Apply VMA_DEBUG_MARGIN at the end.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
+ if(resultOffset < VMA_DEBUG_MARGIN)
+ {
+ return false;
+ }
+ resultOffset -= VMA_DEBUG_MARGIN;
+ }
+
+ // Apply alignment.
+ resultOffset = VmaAlignDown(resultOffset, allocAlignment);
+
+ // Check next suballocations from 2nd for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if(bufferImageGranularity > 1 && !suballocations2nd.empty())
+ {
+ bool bufferImageGranularityConflict = false;
+ for(size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )
+ {
+ const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];
+ if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(nextSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
+ }
+ else
+ // Already on previous page.
+ break;
+ }
+ if(bufferImageGranularityConflict)
+ {
+ resultOffset = VmaAlignDown(resultOffset, bufferImageGranularity);
+ }
+ }
+
+ // There is enough free space.
+ const VkDeviceSize endOf1st = !suballocations1st.empty() ?
+ suballocations1st.back().offset + suballocations1st.back().size :
+ 0;
+ if(endOf1st + VMA_DEBUG_MARGIN <= resultOffset)
+ {
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, allocation cannot be made here.
+ if(bufferImageGranularity > 1)
+ {
+ for(size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )
+ {
+ const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];
+ if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(allocType, prevSuballoc.type))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
+ }
+ }
+
+ // All tests passed: Success.
+ pAllocationRequest->offset = resultOffset;
+ pAllocationRequest->sumFreeSize = resultBaseOffset + allocSize - endOf1st;
+ pAllocationRequest->sumItemSize = 0;
+ // pAllocationRequest->item unused.
+ pAllocationRequest->itemsToMakeLostCount = 0;
+ pAllocationRequest->type = VmaAllocationRequestType::UpperAddress;
+ return true;
+ }
+
+ return false;
+}
+
+bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ const VkDeviceSize size = GetSize();
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ if(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ // Try to allocate at the end of 1st vector.
+
+ VkDeviceSize resultBaseOffset = 0;
+ if(!suballocations1st.empty())
+ {
+ const VmaSuballocation& lastSuballoc = suballocations1st.back();
+ resultBaseOffset = lastSuballoc.offset + lastSuballoc.size;
+ }
+
+ // Start from offset equal to beginning of free space.
+ VkDeviceSize resultOffset = resultBaseOffset;
+
+ // Apply VMA_DEBUG_MARGIN at the beginning.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
+ resultOffset += VMA_DEBUG_MARGIN;
+ }
+
+ // Apply alignment.
+ resultOffset = VmaAlignUp(resultOffset, allocAlignment);
+
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if(bufferImageGranularity > 1 && !suballocations1st.empty())
+ {
+ bool bufferImageGranularityConflict = false;
+ for(size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )
+ {
+ const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];
+ if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
+ }
+ else
+ // Already on previous page.
+ break;
+ }
+ if(bufferImageGranularityConflict)
+ {
+ resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);
+ }
+ }
+
+ const VkDeviceSize freeSpaceEnd = m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ?
+ suballocations2nd.back().offset : size;
+
+ // There is enough free space at the end after alignment.
+ if(resultOffset + allocSize + VMA_DEBUG_MARGIN <= freeSpaceEnd)
+ {
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, allocation cannot be made here.
+ if(bufferImageGranularity > 1 && m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ for(size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )
+ {
+ const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];
+ if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Already on previous page.
+ break;
+ }
+ }
+ }
+
+ // All tests passed: Success.
+ pAllocationRequest->offset = resultOffset;
+ pAllocationRequest->sumFreeSize = freeSpaceEnd - resultBaseOffset;
+ pAllocationRequest->sumItemSize = 0;
+ // pAllocationRequest->item, customData unused.
+ pAllocationRequest->type = VmaAllocationRequestType::EndOf1st;
+ pAllocationRequest->itemsToMakeLostCount = 0;
+ return true;
+ }
+ }
+
+ // Wrap-around to end of 2nd vector. Try to allocate there, watching for the
+ // beginning of 1st vector as the end of free space.
+ if(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ VMA_ASSERT(!suballocations1st.empty());
+
+ VkDeviceSize resultBaseOffset = 0;
+ if(!suballocations2nd.empty())
+ {
+ const VmaSuballocation& lastSuballoc = suballocations2nd.back();
+ resultBaseOffset = lastSuballoc.offset + lastSuballoc.size;
+ }
+
+ // Start from offset equal to beginning of free space.
+ VkDeviceSize resultOffset = resultBaseOffset;
+
+ // Apply VMA_DEBUG_MARGIN at the beginning.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
+ resultOffset += VMA_DEBUG_MARGIN;
+ }
+
+ // Apply alignment.
+ resultOffset = VmaAlignUp(resultOffset, allocAlignment);
+
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if(bufferImageGranularity > 1 && !suballocations2nd.empty())
+ {
+ bool bufferImageGranularityConflict = false;
+ for(size_t prevSuballocIndex = suballocations2nd.size(); prevSuballocIndex--; )
+ {
+ const VmaSuballocation& prevSuballoc = suballocations2nd[prevSuballocIndex];
+ if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
+ }
+ else
+ // Already on previous page.
+ break;
+ }
+ if(bufferImageGranularityConflict)
+ {
+ resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);
+ }
+ }
+
+ pAllocationRequest->itemsToMakeLostCount = 0;
+ pAllocationRequest->sumItemSize = 0;
+ size_t index1st = m_1stNullItemsBeginCount;
+
+ if(canMakeOtherLost)
+ {
+ while(index1st < suballocations1st.size() &&
+ resultOffset + allocSize + VMA_DEBUG_MARGIN > suballocations1st[index1st].offset)
+ {
+ // Next colliding allocation at the beginning of 1st vector found. Try to make it lost.
+ const VmaSuballocation& suballoc = suballocations1st[index1st];
+ if(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ // No problem.
+ }
+ else
+ {
+ VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE);
+ if(suballoc.hAllocation->CanBecomeLost() &&
+ suballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+ {
+ ++pAllocationRequest->itemsToMakeLostCount;
+ pAllocationRequest->sumItemSize += suballoc.size;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ ++index1st;
+ }
+
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, we must mark more allocations lost or fail.
+ if(bufferImageGranularity > 1)
+ {
+ while(index1st < suballocations1st.size())
+ {
+ const VmaSuballocation& suballoc = suballocations1st[index1st];
+ if(VmaBlocksOnSamePage(resultOffset, allocSize, suballoc.offset, bufferImageGranularity))
+ {
+ if(suballoc.hAllocation != VK_NULL_HANDLE)
+ {
+ // Not checking actual VmaIsBufferImageGranularityConflict(allocType, suballoc.type).
+ if(suballoc.hAllocation->CanBecomeLost() &&
+ suballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+ {
+ ++pAllocationRequest->itemsToMakeLostCount;
+ pAllocationRequest->sumItemSize += suballoc.size;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
+ ++index1st;
+ }
+ }
+
+ // Special case: There is not enough room at the end for this allocation, even after making all from the 1st lost.
+ if(index1st == suballocations1st.size() &&
+ resultOffset + allocSize + VMA_DEBUG_MARGIN > size)
+ {
+ // TODO: This is a known bug that it's not yet implemented and the allocation is failing.
+ VMA_DEBUG_LOG("Unsupported special case in custom pool with linear allocation algorithm used as ring buffer with allocations that can be lost.");
+ }
+ }
+
+ // There is enough free space at the end after alignment.
+ if((index1st == suballocations1st.size() && resultOffset + allocSize + VMA_DEBUG_MARGIN <= size) ||
+ (index1st < suballocations1st.size() && resultOffset + allocSize + VMA_DEBUG_MARGIN <= suballocations1st[index1st].offset))
+ {
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, allocation cannot be made here.
+ if(bufferImageGranularity > 1)
+ {
+ for(size_t nextSuballocIndex = index1st;
+ nextSuballocIndex < suballocations1st.size();
+ nextSuballocIndex++)
+ {
+ const VmaSuballocation& nextSuballoc = suballocations1st[nextSuballocIndex];
+ if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
+ }
+ }
+
+ // All tests passed: Success.
+ pAllocationRequest->offset = resultOffset;
+ pAllocationRequest->sumFreeSize =
+ (index1st < suballocations1st.size() ? suballocations1st[index1st].offset : size)
+ - resultBaseOffset
+ - pAllocationRequest->sumItemSize;
+ pAllocationRequest->type = VmaAllocationRequestType::EndOf2nd;
+ // pAllocationRequest->item, customData unused.
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool VmaBlockMetadata_Linear::MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ if(pAllocationRequest->itemsToMakeLostCount == 0)
+ {
+ return true;
+ }
+
+ VMA_ASSERT(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER);
+
+ // We always start from 1st.
+ SuballocationVectorType* suballocations = &AccessSuballocations1st();
+ size_t index = m_1stNullItemsBeginCount;
+ size_t madeLostCount = 0;
+ while(madeLostCount < pAllocationRequest->itemsToMakeLostCount)
+ {
+ if(index == suballocations->size())
+ {
+ index = 0;
+ // If we get to the end of 1st, we wrap around to beginning of 2nd of 1st.
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ suballocations = &AccessSuballocations2nd();
+ }
+ // else: m_2ndVectorMode == SECOND_VECTOR_EMPTY:
+ // suballocations continues pointing at AccessSuballocations1st().
+ VMA_ASSERT(!suballocations->empty());
+ }
+ VmaSuballocation& suballoc = (*suballocations)[index];
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE);
+ VMA_ASSERT(suballoc.hAllocation->CanBecomeLost());
+ if(suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ {
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ suballoc.hAllocation = VK_NULL_HANDLE;
+ m_SumFreeSize += suballoc.size;
+ if(suballocations == &AccessSuballocations1st())
+ {
+ ++m_1stNullItemsMiddleCount;
+ }
+ else
+ {
+ ++m_2ndNullItemsCount;
+ }
+ ++madeLostCount;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ ++index;
+ }
+
+ CleanupAfterFree();
+ //VMA_HEAVY_ASSERT(Validate()); // Already called by ClanupAfterFree().
+
+ return true;
+}
+
+uint32_t VmaBlockMetadata_Linear::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+ uint32_t lostAllocationCount = 0;
+
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ for(size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i)
+ {
+ VmaSuballocation& suballoc = suballocations1st[i];
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE &&
+ suballoc.hAllocation->CanBecomeLost() &&
+ suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ {
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ suballoc.hAllocation = VK_NULL_HANDLE;
+ ++m_1stNullItemsMiddleCount;
+ m_SumFreeSize += suballoc.size;
+ ++lostAllocationCount;
+ }
+ }
+
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ for(size_t i = 0, count = suballocations2nd.size(); i < count; ++i)
+ {
+ VmaSuballocation& suballoc = suballocations2nd[i];
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE &&
+ suballoc.hAllocation->CanBecomeLost() &&
+ suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ {
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ suballoc.hAllocation = VK_NULL_HANDLE;
+ ++m_2ndNullItemsCount;
+ m_SumFreeSize += suballoc.size;
+ ++lostAllocationCount;
+ }
+ }
+
+ if(lostAllocationCount)
+ {
+ CleanupAfterFree();
+ }
+
+ return lostAllocationCount;
+}
+
+VkResult VmaBlockMetadata_Linear::CheckCorruption(const void* pBlockData)
+{
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ for(size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[i];
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ if(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ if(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ }
+ }
+
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ for(size_t i = 0, count = suballocations2nd.size(); i < count; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[i];
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ if(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ if(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaBlockMetadata_Linear::Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ VmaAllocation hAllocation)
+{
+ const VmaSuballocation newSuballoc = { request.offset, allocSize, hAllocation, type };
+
+ switch(request.type)
+ {
+ case VmaAllocationRequestType::UpperAddress:
+ {
+ VMA_ASSERT(m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER &&
+ "CRITICAL ERROR: Trying to use linear allocator as double stack while it was already used as ring buffer.");
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ suballocations2nd.push_back(newSuballoc);
+ m_2ndVectorMode = SECOND_VECTOR_DOUBLE_STACK;
+ }
+ break;
+ case VmaAllocationRequestType::EndOf1st:
+ {
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+
+ VMA_ASSERT(suballocations1st.empty() ||
+ request.offset >= suballocations1st.back().offset + suballocations1st.back().size);
+ // Check if it fits before the end of the block.
+ VMA_ASSERT(request.offset + allocSize <= GetSize());
+
+ suballocations1st.push_back(newSuballoc);
+ }
+ break;
+ case VmaAllocationRequestType::EndOf2nd:
+ {
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ // New allocation at the end of 2-part ring buffer, so before first allocation from 1st vector.
+ VMA_ASSERT(!suballocations1st.empty() &&
+ request.offset + allocSize <= suballocations1st[m_1stNullItemsBeginCount].offset);
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ switch(m_2ndVectorMode)
+ {
+ case SECOND_VECTOR_EMPTY:
+ // First allocation from second part ring buffer.
+ VMA_ASSERT(suballocations2nd.empty());
+ m_2ndVectorMode = SECOND_VECTOR_RING_BUFFER;
+ break;
+ case SECOND_VECTOR_RING_BUFFER:
+ // 2-part ring buffer is already started.
+ VMA_ASSERT(!suballocations2nd.empty());
+ break;
+ case SECOND_VECTOR_DOUBLE_STACK:
+ VMA_ASSERT(0 && "CRITICAL ERROR: Trying to use linear allocator as ring buffer while it was already used as double stack.");
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+
+ suballocations2nd.push_back(newSuballoc);
+ }
+ break;
+ default:
+ VMA_ASSERT(0 && "CRITICAL INTERNAL ERROR.");
+ }
+
+ m_SumFreeSize -= newSuballoc.size;
+}
+
+void VmaBlockMetadata_Linear::Free(const VmaAllocation allocation)
+{
+ FreeAtOffset(allocation->GetOffset());
+}
+
+void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset)
+{
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ if(!suballocations1st.empty())
+ {
+ // First allocation: Mark it as next empty at the beginning.
+ VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];
+ if(firstSuballoc.offset == offset)
+ {
+ firstSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ firstSuballoc.hAllocation = VK_NULL_HANDLE;
+ m_SumFreeSize += firstSuballoc.size;
+ ++m_1stNullItemsBeginCount;
+ CleanupAfterFree();
+ return;
+ }
+ }
+
+ // Last allocation in 2-part ring buffer or top of upper stack (same logic).
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ||
+ m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ VmaSuballocation& lastSuballoc = suballocations2nd.back();
+ if(lastSuballoc.offset == offset)
+ {
+ m_SumFreeSize += lastSuballoc.size;
+ suballocations2nd.pop_back();
+ CleanupAfterFree();
+ return;
+ }
+ }
+ // Last allocation in 1st vector.
+ else if(m_2ndVectorMode == SECOND_VECTOR_EMPTY)
+ {
+ VmaSuballocation& lastSuballoc = suballocations1st.back();
+ if(lastSuballoc.offset == offset)
+ {
+ m_SumFreeSize += lastSuballoc.size;
+ suballocations1st.pop_back();
+ CleanupAfterFree();
+ return;
+ }
+ }
+
+ // Item from the middle of 1st vector.
+ {
+ VmaSuballocation refSuballoc;
+ refSuballoc.offset = offset;
+ // Rest of members stays uninitialized intentionally for better performance.
+ SuballocationVectorType::iterator it = VmaBinaryFindSorted(
+ suballocations1st.begin() + m_1stNullItemsBeginCount,
+ suballocations1st.end(),
+ refSuballoc,
+ VmaSuballocationOffsetLess());
+ if(it != suballocations1st.end())
+ {
+ it->type = VMA_SUBALLOCATION_TYPE_FREE;
+ it->hAllocation = VK_NULL_HANDLE;
+ ++m_1stNullItemsMiddleCount;
+ m_SumFreeSize += it->size;
+ CleanupAfterFree();
+ return;
+ }
+ }
+
+ if(m_2ndVectorMode != SECOND_VECTOR_EMPTY)
+ {
+ // Item from the middle of 2nd vector.
+ VmaSuballocation refSuballoc;
+ refSuballoc.offset = offset;
+ // Rest of members stays uninitialized intentionally for better performance.
+ SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?
+ VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) :
+ VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater());
+ if(it != suballocations2nd.end())
+ {
+ it->type = VMA_SUBALLOCATION_TYPE_FREE;
+ it->hAllocation = VK_NULL_HANDLE;
+ ++m_2ndNullItemsCount;
+ m_SumFreeSize += it->size;
+ CleanupAfterFree();
+ return;
+ }
+ }
+
+ VMA_ASSERT(0 && "Allocation to free not found in linear allocator!");
+}
+
+bool VmaBlockMetadata_Linear::ShouldCompact1st() const
+{
+ const size_t nullItemCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;
+ const size_t suballocCount = AccessSuballocations1st().size();
+ return suballocCount > 32 && nullItemCount * 2 >= (suballocCount - nullItemCount) * 3;
+}
+
+void VmaBlockMetadata_Linear::CleanupAfterFree()
+{
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ if(IsEmpty())
+ {
+ suballocations1st.clear();
+ suballocations2nd.clear();
+ m_1stNullItemsBeginCount = 0;
+ m_1stNullItemsMiddleCount = 0;
+ m_2ndNullItemsCount = 0;
+ m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+ }
+ else
+ {
+ const size_t suballoc1stCount = suballocations1st.size();
+ const size_t nullItem1stCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;
+ VMA_ASSERT(nullItem1stCount <= suballoc1stCount);
+
+ // Find more null items at the beginning of 1st vector.
+ while(m_1stNullItemsBeginCount < suballoc1stCount &&
+ suballocations1st[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE)
+ {
+ ++m_1stNullItemsBeginCount;
+ --m_1stNullItemsMiddleCount;
+ }
+
+ // Find more null items at the end of 1st vector.
+ while(m_1stNullItemsMiddleCount > 0 &&
+ suballocations1st.back().hAllocation == VK_NULL_HANDLE)
+ {
+ --m_1stNullItemsMiddleCount;
+ suballocations1st.pop_back();
+ }
+
+ // Find more null items at the end of 2nd vector.
+ while(m_2ndNullItemsCount > 0 &&
+ suballocations2nd.back().hAllocation == VK_NULL_HANDLE)
+ {
+ --m_2ndNullItemsCount;
+ suballocations2nd.pop_back();
+ }
+
+ // Find more null items at the beginning of 2nd vector.
+ while(m_2ndNullItemsCount > 0 &&
+ suballocations2nd[0].hAllocation == VK_NULL_HANDLE)
+ {
+ --m_2ndNullItemsCount;
+ VmaVectorRemove(suballocations2nd, 0);
+ }
+
+ if(ShouldCompact1st())
+ {
+ const size_t nonNullItemCount = suballoc1stCount - nullItem1stCount;
+ size_t srcIndex = m_1stNullItemsBeginCount;
+ for(size_t dstIndex = 0; dstIndex < nonNullItemCount; ++dstIndex)
+ {
+ while(suballocations1st[srcIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++srcIndex;
+ }
+ if(dstIndex != srcIndex)
+ {
+ suballocations1st[dstIndex] = suballocations1st[srcIndex];
+ }
+ ++srcIndex;
+ }
+ suballocations1st.resize(nonNullItemCount);
+ m_1stNullItemsBeginCount = 0;
+ m_1stNullItemsMiddleCount = 0;
+ }
+
+ // 2nd vector became empty.
+ if(suballocations2nd.empty())
+ {
+ m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+ }
+
+ // 1st vector became empty.
+ if(suballocations1st.size() - m_1stNullItemsBeginCount == 0)
+ {
+ suballocations1st.clear();
+ m_1stNullItemsBeginCount = 0;
+
+ if(!suballocations2nd.empty() && m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ // Swap 1st with 2nd. Now 2nd is empty.
+ m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+ m_1stNullItemsMiddleCount = m_2ndNullItemsCount;
+ while(m_1stNullItemsBeginCount < suballocations2nd.size() &&
+ suballocations2nd[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE)
+ {
+ ++m_1stNullItemsBeginCount;
+ --m_1stNullItemsMiddleCount;
+ }
+ m_2ndNullItemsCount = 0;
+ m_1stVectorIndex ^= 1;
+ }
+ }
+ }
+
+ VMA_HEAVY_ASSERT(Validate());
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata_Buddy
+
+VmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(VmaAllocator hAllocator) :
+ VmaBlockMetadata(hAllocator),
+ m_Root(VMA_NULL),
+ m_AllocationCount(0),
+ m_FreeCount(1),
+ m_SumFreeSize(0)
+{
+ memset(m_FreeList, 0, sizeof(m_FreeList));
+}
+
+VmaBlockMetadata_Buddy::~VmaBlockMetadata_Buddy()
+{
+ DeleteNode(m_Root);
+}
+
+void VmaBlockMetadata_Buddy::Init(VkDeviceSize size)
+{
+ VmaBlockMetadata::Init(size);
+
+ m_UsableSize = VmaPrevPow2(size);
+ m_SumFreeSize = m_UsableSize;
+
+ // Calculate m_LevelCount.
+ m_LevelCount = 1;
+ while(m_LevelCount < MAX_LEVELS &&
+ LevelToNodeSize(m_LevelCount) >= MIN_NODE_SIZE)
+ {
+ ++m_LevelCount;
+ }
+
+ Node* rootNode = vma_new(GetAllocationCallbacks(), Node)();
+ rootNode->offset = 0;
+ rootNode->type = Node::TYPE_FREE;
+ rootNode->parent = VMA_NULL;
+ rootNode->buddy = VMA_NULL;
+
+ m_Root = rootNode;
+ AddToFreeListFront(0, rootNode);
+}
+
+bool VmaBlockMetadata_Buddy::Validate() const
+{
+ // Validate tree.
+ ValidationContext ctx;
+ if(!ValidateNode(ctx, VMA_NULL, m_Root, 0, LevelToNodeSize(0)))
+ {
+ VMA_VALIDATE(false && "ValidateNode failed.");
+ }
+ VMA_VALIDATE(m_AllocationCount == ctx.calculatedAllocationCount);
+ VMA_VALIDATE(m_SumFreeSize == ctx.calculatedSumFreeSize);
+
+ // Validate free node lists.
+ for(uint32_t level = 0; level < m_LevelCount; ++level)
+ {
+ VMA_VALIDATE(m_FreeList[level].front == VMA_NULL ||
+ m_FreeList[level].front->free.prev == VMA_NULL);
+
+ for(Node* node = m_FreeList[level].front;
+ node != VMA_NULL;
+ node = node->free.next)
+ {
+ VMA_VALIDATE(node->type == Node::TYPE_FREE);
+
+ if(node->free.next == VMA_NULL)
+ {
+ VMA_VALIDATE(m_FreeList[level].back == node);
+ }
+ else
+ {
+ VMA_VALIDATE(node->free.next->free.prev == node);
+ }
+ }
+ }
+
+ // Validate that free lists ar higher levels are empty.
+ for(uint32_t level = m_LevelCount; level < MAX_LEVELS; ++level)
+ {
+ VMA_VALIDATE(m_FreeList[level].front == VMA_NULL && m_FreeList[level].back == VMA_NULL);
+ }
+
+ return true;
+}
+
+VkDeviceSize VmaBlockMetadata_Buddy::GetUnusedRangeSizeMax() const
+{
+ for(uint32_t level = 0; level < m_LevelCount; ++level)
+ {
+ if(m_FreeList[level].front != VMA_NULL)
+ {
+ return LevelToNodeSize(level);
+ }
+ }
+ return 0;
+}
+
+void VmaBlockMetadata_Buddy::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
+{
+ const VkDeviceSize unusableSize = GetUnusableSize();
+
+ outInfo.blockCount = 1;
+
+ outInfo.allocationCount = outInfo.unusedRangeCount = 0;
+ outInfo.usedBytes = outInfo.unusedBytes = 0;
+
+ outInfo.allocationSizeMax = outInfo.unusedRangeSizeMax = 0;
+ outInfo.allocationSizeMin = outInfo.unusedRangeSizeMin = UINT64_MAX;
+ outInfo.allocationSizeAvg = outInfo.unusedRangeSizeAvg = 0; // Unused.
+
+ CalcAllocationStatInfoNode(outInfo, m_Root, LevelToNodeSize(0));
+
+ if(unusableSize > 0)
+ {
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusableSize;
+ outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusableSize);
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusableSize);
+ }
+}
+
+void VmaBlockMetadata_Buddy::AddPoolStats(VmaPoolStats& inoutStats) const
+{
+ const VkDeviceSize unusableSize = GetUnusableSize();
+
+ inoutStats.size += GetSize();
+ inoutStats.unusedSize += m_SumFreeSize + unusableSize;
+ inoutStats.allocationCount += m_AllocationCount;
+ inoutStats.unusedRangeCount += m_FreeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, GetUnusedRangeSizeMax());
+
+ if(unusableSize > 0)
+ {
+ ++inoutStats.unusedRangeCount;
+ // Not updating inoutStats.unusedRangeSizeMax with unusableSize because this space is not available for allocations.
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockMetadata_Buddy::PrintDetailedMap(class VmaJsonWriter& json) const
+{
+ // TODO optimize
+ VmaStatInfo stat;
+ CalcAllocationStatInfo(stat);
+
+ PrintDetailedMap_Begin(
+ json,
+ stat.unusedBytes,
+ stat.allocationCount,
+ stat.unusedRangeCount);
+
+ PrintDetailedMapNode(json, m_Root, LevelToNodeSize(0));
+
+ const VkDeviceSize unusableSize = GetUnusableSize();
+ if(unusableSize > 0)
+ {
+ PrintDetailedMap_UnusedRange(json,
+ m_UsableSize, // offset
+ unusableSize); // size
+ }
+
+ PrintDetailedMap_End(json);
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+bool VmaBlockMetadata_Buddy::CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ VMA_ASSERT(!upperAddress && "VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm.");
+
+ // Simple way to respect bufferImageGranularity. May be optimized some day.
+ // Whenever it might be an OPTIMAL image...
+ if(allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN ||
+ allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
+ allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL)
+ {
+ allocAlignment = VMA_MAX(allocAlignment, bufferImageGranularity);
+ allocSize = VMA_MAX(allocSize, bufferImageGranularity);
+ }
+
+ if(allocSize > m_UsableSize)
+ {
+ return false;
+ }
+
+ const uint32_t targetLevel = AllocSizeToLevel(allocSize);
+ for(uint32_t level = targetLevel + 1; level--; )
+ {
+ for(Node* freeNode = m_FreeList[level].front;
+ freeNode != VMA_NULL;
+ freeNode = freeNode->free.next)
+ {
+ if(freeNode->offset % allocAlignment == 0)
+ {
+ pAllocationRequest->type = VmaAllocationRequestType::Normal;
+ pAllocationRequest->offset = freeNode->offset;
+ pAllocationRequest->sumFreeSize = LevelToNodeSize(level);
+ pAllocationRequest->sumItemSize = 0;
+ pAllocationRequest->itemsToMakeLostCount = 0;
+ pAllocationRequest->customData = (void*)(uintptr_t)level;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool VmaBlockMetadata_Buddy::MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ /*
+ Lost allocations are not supported in buddy allocator at the moment.
+ Support might be added in the future.
+ */
+ return pAllocationRequest->itemsToMakeLostCount == 0;
+}
+
+uint32_t VmaBlockMetadata_Buddy::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+ /*
+ Lost allocations are not supported in buddy allocator at the moment.
+ Support might be added in the future.
+ */
+ return 0;
+}
+
+void VmaBlockMetadata_Buddy::Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ VmaAllocation hAllocation)
+{
+ VMA_ASSERT(request.type == VmaAllocationRequestType::Normal);
+
+ const uint32_t targetLevel = AllocSizeToLevel(allocSize);
+ uint32_t currLevel = (uint32_t)(uintptr_t)request.customData;
+
+ Node* currNode = m_FreeList[currLevel].front;
+ VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
+ while(currNode->offset != request.offset)
+ {
+ currNode = currNode->free.next;
+ VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
+ }
+
+ // Go down, splitting free nodes.
+ while(currLevel < targetLevel)
+ {
+ // currNode is already first free node at currLevel.
+ // Remove it from list of free nodes at this currLevel.
+ RemoveFromFreeList(currLevel, currNode);
+
+ const uint32_t childrenLevel = currLevel + 1;
+
+ // Create two free sub-nodes.
+ Node* leftChild = vma_new(GetAllocationCallbacks(), Node)();
+ Node* rightChild = vma_new(GetAllocationCallbacks(), Node)();
+
+ leftChild->offset = currNode->offset;
+ leftChild->type = Node::TYPE_FREE;
+ leftChild->parent = currNode;
+ leftChild->buddy = rightChild;
+
+ rightChild->offset = currNode->offset + LevelToNodeSize(childrenLevel);
+ rightChild->type = Node::TYPE_FREE;
+ rightChild->parent = currNode;
+ rightChild->buddy = leftChild;
+
+ // Convert current currNode to split type.
+ currNode->type = Node::TYPE_SPLIT;
+ currNode->split.leftChild = leftChild;
+
+ // Add child nodes to free list. Order is important!
+ AddToFreeListFront(childrenLevel, rightChild);
+ AddToFreeListFront(childrenLevel, leftChild);
+
+ ++m_FreeCount;
+ //m_SumFreeSize -= LevelToNodeSize(currLevel) % 2; // Useful only when level node sizes can be non power of 2.
+ ++currLevel;
+ currNode = m_FreeList[currLevel].front;
+
+ /*
+ We can be sure that currNode, as left child of node previously split,
+ also fullfills the alignment requirement.
+ */
+ }
+
+ // Remove from free list.
+ VMA_ASSERT(currLevel == targetLevel &&
+ currNode != VMA_NULL &&
+ currNode->type == Node::TYPE_FREE);
+ RemoveFromFreeList(currLevel, currNode);
+
+ // Convert to allocation node.
+ currNode->type = Node::TYPE_ALLOCATION;
+ currNode->allocation.alloc = hAllocation;
+
+ ++m_AllocationCount;
+ --m_FreeCount;
+ m_SumFreeSize -= allocSize;
+}
+
+void VmaBlockMetadata_Buddy::DeleteNode(Node* node)
+{
+ if(node->type == Node::TYPE_SPLIT)
+ {
+ DeleteNode(node->split.leftChild->buddy);
+ DeleteNode(node->split.leftChild);
+ }
+
+ vma_delete(GetAllocationCallbacks(), node);
+}
+
+bool VmaBlockMetadata_Buddy::ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const
+{
+ VMA_VALIDATE(level < m_LevelCount);
+ VMA_VALIDATE(curr->parent == parent);
+ VMA_VALIDATE((curr->buddy == VMA_NULL) == (parent == VMA_NULL));
+ VMA_VALIDATE(curr->buddy == VMA_NULL || curr->buddy->buddy == curr);
+ switch(curr->type)
+ {
+ case Node::TYPE_FREE:
+ // curr->free.prev, next are validated separately.
+ ctx.calculatedSumFreeSize += levelNodeSize;
+ ++ctx.calculatedFreeCount;
+ break;
+ case Node::TYPE_ALLOCATION:
+ ++ctx.calculatedAllocationCount;
+ ctx.calculatedSumFreeSize += levelNodeSize - curr->allocation.alloc->GetSize();
+ VMA_VALIDATE(curr->allocation.alloc != VK_NULL_HANDLE);
+ break;
+ case Node::TYPE_SPLIT:
+ {
+ const uint32_t childrenLevel = level + 1;
+ const VkDeviceSize childrenLevelNodeSize = levelNodeSize / 2;
+ const Node* const leftChild = curr->split.leftChild;
+ VMA_VALIDATE(leftChild != VMA_NULL);
+ VMA_VALIDATE(leftChild->offset == curr->offset);
+ if(!ValidateNode(ctx, curr, leftChild, childrenLevel, childrenLevelNodeSize))
+ {
+ VMA_VALIDATE(false && "ValidateNode for left child failed.");
+ }
+ const Node* const rightChild = leftChild->buddy;
+ VMA_VALIDATE(rightChild->offset == curr->offset + childrenLevelNodeSize);
+ if(!ValidateNode(ctx, curr, rightChild, childrenLevel, childrenLevelNodeSize))
+ {
+ VMA_VALIDATE(false && "ValidateNode for right child failed.");
+ }
+ }
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+uint32_t VmaBlockMetadata_Buddy::AllocSizeToLevel(VkDeviceSize allocSize) const
+{
+ // I know this could be optimized somehow e.g. by using std::log2p1 from C++20.
+ uint32_t level = 0;
+ VkDeviceSize currLevelNodeSize = m_UsableSize;
+ VkDeviceSize nextLevelNodeSize = currLevelNodeSize >> 1;
+ while(allocSize <= nextLevelNodeSize && level + 1 < m_LevelCount)
+ {
+ ++level;
+ currLevelNodeSize = nextLevelNodeSize;
+ nextLevelNodeSize = currLevelNodeSize >> 1;
+ }
+ return level;
+}
+
+void VmaBlockMetadata_Buddy::FreeAtOffset(VmaAllocation alloc, VkDeviceSize offset)
+{
+ // Find node and level.
+ Node* node = m_Root;
+ VkDeviceSize nodeOffset = 0;
+ uint32_t level = 0;
+ VkDeviceSize levelNodeSize = LevelToNodeSize(0);
+ while(node->type == Node::TYPE_SPLIT)
+ {
+ const VkDeviceSize nextLevelSize = levelNodeSize >> 1;
+ if(offset < nodeOffset + nextLevelSize)
+ {
+ node = node->split.leftChild;
+ }
+ else
+ {
+ node = node->split.leftChild->buddy;
+ nodeOffset += nextLevelSize;
+ }
+ ++level;
+ levelNodeSize = nextLevelSize;
+ }
+
+ VMA_ASSERT(node != VMA_NULL && node->type == Node::TYPE_ALLOCATION);
+ VMA_ASSERT(alloc == VK_NULL_HANDLE || node->allocation.alloc == alloc);
+
+ ++m_FreeCount;
+ --m_AllocationCount;
+ m_SumFreeSize += alloc->GetSize();
+
+ node->type = Node::TYPE_FREE;
+
+ // Join free nodes if possible.
+ while(level > 0 && node->buddy->type == Node::TYPE_FREE)
+ {
+ RemoveFromFreeList(level, node->buddy);
+ Node* const parent = node->parent;
+
+ vma_delete(GetAllocationCallbacks(), node->buddy);
+ vma_delete(GetAllocationCallbacks(), node);
+ parent->type = Node::TYPE_FREE;
+
+ node = parent;
+ --level;
+ //m_SumFreeSize += LevelToNodeSize(level) % 2; // Useful only when level node sizes can be non power of 2.
+ --m_FreeCount;
+ }
+
+ AddToFreeListFront(level, node);
+}
+
+void VmaBlockMetadata_Buddy::CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const
+{
+ switch(node->type)
+ {
+ case Node::TYPE_FREE:
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += levelNodeSize;
+ outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, levelNodeSize);
+ outInfo.unusedRangeSizeMin = VMA_MAX(outInfo.unusedRangeSizeMin, levelNodeSize);
+ break;
+ case Node::TYPE_ALLOCATION:
+ {
+ const VkDeviceSize allocSize = node->allocation.alloc->GetSize();
+ ++outInfo.allocationCount;
+ outInfo.usedBytes += allocSize;
+ outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, allocSize);
+ outInfo.allocationSizeMin = VMA_MAX(outInfo.allocationSizeMin, allocSize);
+
+ const VkDeviceSize unusedRangeSize = levelNodeSize - allocSize;
+ if(unusedRangeSize > 0)
+ {
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ outInfo.unusedRangeSizeMin = VMA_MAX(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ }
+ }
+ break;
+ case Node::TYPE_SPLIT:
+ {
+ const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
+ const Node* const leftChild = node->split.leftChild;
+ CalcAllocationStatInfoNode(outInfo, leftChild, childrenNodeSize);
+ const Node* const rightChild = leftChild->buddy;
+ CalcAllocationStatInfoNode(outInfo, rightChild, childrenNodeSize);
+ }
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+}
+
+void VmaBlockMetadata_Buddy::AddToFreeListFront(uint32_t level, Node* node)
+{
+ VMA_ASSERT(node->type == Node::TYPE_FREE);
+
+ // List is empty.
+ Node* const frontNode = m_FreeList[level].front;
+ if(frontNode == VMA_NULL)
+ {
+ VMA_ASSERT(m_FreeList[level].back == VMA_NULL);
+ node->free.prev = node->free.next = VMA_NULL;
+ m_FreeList[level].front = m_FreeList[level].back = node;
+ }
+ else
+ {
+ VMA_ASSERT(frontNode->free.prev == VMA_NULL);
+ node->free.prev = VMA_NULL;
+ node->free.next = frontNode;
+ frontNode->free.prev = node;
+ m_FreeList[level].front = node;
+ }
+}
+
+void VmaBlockMetadata_Buddy::RemoveFromFreeList(uint32_t level, Node* node)
+{
+ VMA_ASSERT(m_FreeList[level].front != VMA_NULL);
+
+ // It is at the front.
+ if(node->free.prev == VMA_NULL)
+ {
+ VMA_ASSERT(m_FreeList[level].front == node);
+ m_FreeList[level].front = node->free.next;
+ }
+ else
+ {
+ Node* const prevFreeNode = node->free.prev;
+ VMA_ASSERT(prevFreeNode->free.next == node);
+ prevFreeNode->free.next = node->free.next;
+ }
+
+ // It is at the back.
+ if(node->free.next == VMA_NULL)
+ {
+ VMA_ASSERT(m_FreeList[level].back == node);
+ m_FreeList[level].back = node->free.prev;
+ }
+ else
+ {
+ Node* const nextFreeNode = node->free.next;
+ VMA_ASSERT(nextFreeNode->free.prev == node);
+ nextFreeNode->free.prev = node->free.prev;
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+void VmaBlockMetadata_Buddy::PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const
+{
+ switch(node->type)
+ {
+ case Node::TYPE_FREE:
+ PrintDetailedMap_UnusedRange(json, node->offset, levelNodeSize);
+ break;
+ case Node::TYPE_ALLOCATION:
+ {
+ PrintDetailedMap_Allocation(json, node->offset, node->allocation.alloc);
+ const VkDeviceSize allocSize = node->allocation.alloc->GetSize();
+ if(allocSize < levelNodeSize)
+ {
+ PrintDetailedMap_UnusedRange(json, node->offset + allocSize, levelNodeSize - allocSize);
+ }
+ }
+ break;
+ case Node::TYPE_SPLIT:
+ {
+ const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
+ const Node* const leftChild = node->split.leftChild;
+ PrintDetailedMapNode(json, leftChild, childrenNodeSize);
+ const Node* const rightChild = leftChild->buddy;
+ PrintDetailedMapNode(json, rightChild, childrenNodeSize);
+ }
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+}
+#endif // #if VMA_STATS_STRING_ENABLED
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaDeviceMemoryBlock
+
+VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) :
+ m_pMetadata(VMA_NULL),
+ m_MemoryTypeIndex(UINT32_MAX),
+ m_Id(0),
+ m_hMemory(VK_NULL_HANDLE),
+ m_MapCount(0),
+ m_pMappedData(VMA_NULL)
+{
+}
+
+void VmaDeviceMemoryBlock::Init(
+ VmaAllocator hAllocator,
+ VmaPool hParentPool,
+ uint32_t newMemoryTypeIndex,
+ VkDeviceMemory newMemory,
+ VkDeviceSize newSize,
+ uint32_t id,
+ uint32_t algorithm)
+{
+ VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
+
+ m_hParentPool = hParentPool;
+ m_MemoryTypeIndex = newMemoryTypeIndex;
+ m_Id = id;
+ m_hMemory = newMemory;
+
+ switch(algorithm)
+ {
+ case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
+ m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator);
+ break;
+ case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT:
+ m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Buddy)(hAllocator);
+ break;
+ default:
+ VMA_ASSERT(0);
+ // Fall-through.
+ case 0:
+ m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Generic)(hAllocator);
+ }
+ m_pMetadata->Init(newSize);
+}
+
+void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator)
+{
+ // This is the most important assert in the entire library.
+ // Hitting it means you have some memory leak - unreleased VmaAllocation objects.
+ VMA_ASSERT(m_pMetadata->IsEmpty() && "Some allocations were not freed before destruction of this memory block!");
+
+ VMA_ASSERT(m_hMemory != VK_NULL_HANDLE);
+ allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory);
+ m_hMemory = VK_NULL_HANDLE;
+
+ vma_delete(allocator, m_pMetadata);
+ m_pMetadata = VMA_NULL;
+}
+
+bool VmaDeviceMemoryBlock::Validate() const
+{
+ VMA_VALIDATE((m_hMemory != VK_NULL_HANDLE) &&
+ (m_pMetadata->GetSize() != 0));
+
+ return m_pMetadata->Validate();
+}
+
+VkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator)
+{
+ void* pData = nullptr;
+ VkResult res = Map(hAllocator, 1, &pData);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+
+ res = m_pMetadata->CheckCorruption(pData);
+
+ Unmap(hAllocator, 1);
+
+ return res;
+}
+
+VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void** ppData)
+{
+ if(count == 0)
+ {
+ return VK_SUCCESS;
+ }
+
+ VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ if(m_MapCount != 0)
+ {
+ m_MapCount += count;
+ VMA_ASSERT(m_pMappedData != VMA_NULL);
+ if(ppData != VMA_NULL)
+ {
+ *ppData = m_pMappedData;
+ }
+ return VK_SUCCESS;
+ }
+ else
+ {
+ VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)(
+ hAllocator->m_hDevice,
+ m_hMemory,
+ 0, // offset
+ VK_WHOLE_SIZE,
+ 0, // flags
+ &m_pMappedData);
+ if(result == VK_SUCCESS)
+ {
+ if(ppData != VMA_NULL)
+ {
+ *ppData = m_pMappedData;
+ }
+ m_MapCount = count;
+ }
+ return result;
+ }
+}
+
+void VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator, uint32_t count)
+{
+ if(count == 0)
+ {
+ return;
+ }
+
+ VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ if(m_MapCount >= count)
+ {
+ m_MapCount -= count;
+ if(m_MapCount == 0)
+ {
+ m_pMappedData = VMA_NULL;
+ (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);
+ }
+ }
+ else
+ {
+ VMA_ASSERT(0 && "VkDeviceMemory block is being unmapped while it was not previously mapped.");
+ }
+}
+
+VkResult VmaDeviceMemoryBlock::WriteMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)
+{
+ VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION);
+ VMA_ASSERT(allocOffset >= VMA_DEBUG_MARGIN);
+
+ void* pData;
+ VkResult res = Map(hAllocator, 1, &pData);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+
+ VmaWriteMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN);
+ VmaWriteMagicValue(pData, allocOffset + allocSize);
+
+ Unmap(hAllocator, 1);
+
+ return VK_SUCCESS;
+}
+
+VkResult VmaDeviceMemoryBlock::ValidateMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)
+{
+ VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION);
+ VMA_ASSERT(allocOffset >= VMA_DEBUG_MARGIN);
+
+ void* pData;
+ VkResult res = Map(hAllocator, 1, &pData);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+
+ if(!VmaValidateMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE FREED ALLOCATION!");
+ }
+ else if(!VmaValidateMagicValue(pData, allocOffset + allocSize))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER FREED ALLOCATION!");
+ }
+
+ Unmap(hAllocator, 1);
+
+ return VK_SUCCESS;
+}
+
+VkResult VmaDeviceMemoryBlock::BindBufferMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkBuffer hBuffer,
+ const void* pNext)
+{
+ VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &&
+ hAllocation->GetBlock() == this);
+ VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() &&
+ "Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?");
+ const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset;
+ // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.
+ VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ return hAllocator->BindVulkanBuffer(m_hMemory, memoryOffset, hBuffer, pNext);
+}
+
+VkResult VmaDeviceMemoryBlock::BindImageMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkImage hImage,
+ const void* pNext)
+{
+ VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &&
+ hAllocation->GetBlock() == this);
+ VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() &&
+ "Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?");
+ const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset;
+ // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.
+ VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext);
+}
+
+static void InitStatInfo(VmaStatInfo& outInfo)
+{
+ memset(&outInfo, 0, sizeof(outInfo));
+ outInfo.allocationSizeMin = UINT64_MAX;
+ outInfo.unusedRangeSizeMin = UINT64_MAX;
+}
+
+// Adds statistics srcInfo into inoutInfo, like: inoutInfo += srcInfo.
+static void VmaAddStatInfo(VmaStatInfo& inoutInfo, const VmaStatInfo& srcInfo)
+{
+ inoutInfo.blockCount += srcInfo.blockCount;
+ inoutInfo.allocationCount += srcInfo.allocationCount;
+ inoutInfo.unusedRangeCount += srcInfo.unusedRangeCount;
+ inoutInfo.usedBytes += srcInfo.usedBytes;
+ inoutInfo.unusedBytes += srcInfo.unusedBytes;
+ inoutInfo.allocationSizeMin = VMA_MIN(inoutInfo.allocationSizeMin, srcInfo.allocationSizeMin);
+ inoutInfo.allocationSizeMax = VMA_MAX(inoutInfo.allocationSizeMax, srcInfo.allocationSizeMax);
+ inoutInfo.unusedRangeSizeMin = VMA_MIN(inoutInfo.unusedRangeSizeMin, srcInfo.unusedRangeSizeMin);
+ inoutInfo.unusedRangeSizeMax = VMA_MAX(inoutInfo.unusedRangeSizeMax, srcInfo.unusedRangeSizeMax);
+}
+
+static void VmaPostprocessCalcStatInfo(VmaStatInfo& inoutInfo)
+{
+ inoutInfo.allocationSizeAvg = (inoutInfo.allocationCount > 0) ?
+ VmaRoundDiv<VkDeviceSize>(inoutInfo.usedBytes, inoutInfo.allocationCount) : 0;
+ inoutInfo.unusedRangeSizeAvg = (inoutInfo.unusedRangeCount > 0) ?
+ VmaRoundDiv<VkDeviceSize>(inoutInfo.unusedBytes, inoutInfo.unusedRangeCount) : 0;
+}
+
+VmaPool_T::VmaPool_T(
+ VmaAllocator hAllocator,
+ const VmaPoolCreateInfo& createInfo,
+ VkDeviceSize preferredBlockSize) :
+ m_BlockVector(
+ hAllocator,
+ this, // hParentPool
+ createInfo.memoryTypeIndex,
+ createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize,
+ createInfo.minBlockCount,
+ createInfo.maxBlockCount,
+ (createInfo.flags & VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
+ createInfo.frameInUseCount,
+ createInfo.blockSize != 0, // explicitBlockSize
+ createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK), // algorithm
+ m_Id(0),
+ m_Name(VMA_NULL)
+{
+}
+
+VmaPool_T::~VmaPool_T()
+{
+}
+
+void VmaPool_T::SetName(const char* pName)
+{
+ const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks();
+ VmaFreeString(allocs, m_Name);
+
+ if(pName != VMA_NULL)
+ {
+ m_Name = VmaCreateStringCopy(allocs, pName);
+ }
+ else
+ {
+ m_Name = VMA_NULL;
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+VmaBlockVector::VmaBlockVector(
+ VmaAllocator hAllocator,
+ VmaPool hParentPool,
+ uint32_t memoryTypeIndex,
+ VkDeviceSize preferredBlockSize,
+ size_t minBlockCount,
+ size_t maxBlockCount,
+ VkDeviceSize bufferImageGranularity,
+ uint32_t frameInUseCount,
+ bool explicitBlockSize,
+ uint32_t algorithm) :
+ m_hAllocator(hAllocator),
+ m_hParentPool(hParentPool),
+ m_MemoryTypeIndex(memoryTypeIndex),
+ m_PreferredBlockSize(preferredBlockSize),
+ m_MinBlockCount(minBlockCount),
+ m_MaxBlockCount(maxBlockCount),
+ m_BufferImageGranularity(bufferImageGranularity),
+ m_FrameInUseCount(frameInUseCount),
+ m_ExplicitBlockSize(explicitBlockSize),
+ m_Algorithm(algorithm),
+ m_HasEmptyBlock(false),
+ m_Blocks(VmaStlAllocator<VmaDeviceMemoryBlock*>(hAllocator->GetAllocationCallbacks())),
+ m_NextBlockId(0)
+{
+}
+
+VmaBlockVector::~VmaBlockVector()
+{
+ for(size_t i = m_Blocks.size(); i--; )
+ {
+ m_Blocks[i]->Destroy(m_hAllocator);
+ vma_delete(m_hAllocator, m_Blocks[i]);
+ }
+}
+
+VkResult VmaBlockVector::CreateMinBlocks()
+{
+ for(size_t i = 0; i < m_MinBlockCount; ++i)
+ {
+ VkResult res = CreateBlock(m_PreferredBlockSize, VMA_NULL);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+ }
+ return VK_SUCCESS;
+}
+
+void VmaBlockVector::GetPoolStats(VmaPoolStats* pStats)
+{
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+ const size_t blockCount = m_Blocks.size();
+
+ pStats->size = 0;
+ pStats->unusedSize = 0;
+ pStats->allocationCount = 0;
+ pStats->unusedRangeCount = 0;
+ pStats->unusedRangeSizeMax = 0;
+ pStats->blockCount = blockCount;
+
+ for(uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pBlock);
+ VMA_HEAVY_ASSERT(pBlock->Validate());
+ pBlock->m_pMetadata->AddPoolStats(*pStats);
+ }
+}
+
+bool VmaBlockVector::IsEmpty()
+{
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+ return m_Blocks.empty();
+}
+
+bool VmaBlockVector::IsCorruptionDetectionEnabled() const
+{
+ const uint32_t requiredMemFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ return (VMA_DEBUG_DETECT_CORRUPTION != 0) &&
+ (VMA_DEBUG_MARGIN > 0) &&
+ (m_Algorithm == 0 || m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) &&
+ (m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & requiredMemFlags) == requiredMemFlags;
+}
+
+static const uint32_t VMA_ALLOCATION_TRY_COUNT = 32;
+
+VkResult VmaBlockVector::Allocate(
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ size_t allocIndex;
+ VkResult res = VK_SUCCESS;
+
+ if(IsCorruptionDetectionEnabled())
+ {
+ size = VmaAlignUp<VkDeviceSize>(size, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE));
+ alignment = VmaAlignUp<VkDeviceSize>(alignment, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE));
+ }
+
+ {
+ VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+ for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+ {
+ res = AllocatePage(
+ currentFrameIndex,
+ size,
+ alignment,
+ createInfo,
+ suballocType,
+ pAllocations + allocIndex);
+ if(res != VK_SUCCESS)
+ {
+ break;
+ }
+ }
+ }
+
+ if(res != VK_SUCCESS)
+ {
+ // Free all already created allocations.
+ while(allocIndex--)
+ {
+ Free(pAllocations[allocIndex]);
+ }
+ memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+ }
+
+ return res;
+}
+
+VkResult VmaBlockVector::AllocatePage(
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ VmaAllocation* pAllocation)
+{
+ const bool isUpperAddress = (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0;
+ bool canMakeOtherLost = (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT) != 0;
+ const bool mapped = (createInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
+ const bool isUserDataString = (createInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0;
+
+ const bool withinBudget = (createInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0;
+ VkDeviceSize freeMemory;
+ {
+ const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);
+ VmaBudget heapBudget = {};
+ m_hAllocator->GetBudget(&heapBudget, heapIndex, 1);
+ freeMemory = (heapBudget.usage < heapBudget.budget) ? (heapBudget.budget - heapBudget.usage) : 0;
+ }
+
+ const bool canFallbackToDedicated = !IsCustomPool();
+ const bool canCreateNewBlock =
+ ((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0) &&
+ (m_Blocks.size() < m_MaxBlockCount) &&
+ (freeMemory >= size || !canFallbackToDedicated);
+ uint32_t strategy = createInfo.flags & VMA_ALLOCATION_CREATE_STRATEGY_MASK;
+
+ // If linearAlgorithm is used, canMakeOtherLost is available only when used as ring buffer.
+ // Which in turn is available only when maxBlockCount = 1.
+ if(m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT && m_MaxBlockCount > 1)
+ {
+ canMakeOtherLost = false;
+ }
+
+ // Upper address can only be used with linear allocator and within single memory block.
+ if(isUpperAddress &&
+ (m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT || m_MaxBlockCount > 1))
+ {
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+ }
+
+ // Validate strategy.
+ switch(strategy)
+ {
+ case 0:
+ strategy = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT;
+ break;
+ case VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT:
+ case VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT:
+ case VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT:
+ break;
+ default:
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+ }
+
+ // Early reject: requested allocation size is larger that maximum block size for this block vector.
+ if(size + 2 * VMA_DEBUG_MARGIN > m_PreferredBlockSize)
+ {
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+
+ /*
+ Under certain condition, this whole section can be skipped for optimization, so
+ we move on directly to trying to allocate with canMakeOtherLost. That's the case
+ e.g. for custom pools with linear algorithm.
+ */
+ if(!canMakeOtherLost || canCreateNewBlock)
+ {
+ // 1. Search existing allocations. Try to allocate without making other allocations lost.
+ VmaAllocationCreateFlags allocFlagsCopy = createInfo.flags;
+ allocFlagsCopy &= ~VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
+
+ if(m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
+ {
+ // Use only last block.
+ if(!m_Blocks.empty())
+ {
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks.back();
+ VMA_ASSERT(pCurrBlock);
+ VkResult res = AllocateFromBlock(
+ pCurrBlock,
+ currentFrameIndex,
+ size,
+ alignment,
+ allocFlagsCopy,
+ createInfo.pUserData,
+ suballocType,
+ strategy,
+ pAllocation);
+ if(res == VK_SUCCESS)
+ {
+ VMA_DEBUG_LOG(" Returned from last block #%u", pCurrBlock->GetId());
+ return VK_SUCCESS;
+ }
+ }
+ }
+ else
+ {
+ if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+ {
+ // Forward order in m_Blocks - prefer blocks with smallest amount of free space.
+ for(size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex )
+ {
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pCurrBlock);
+ VkResult res = AllocateFromBlock(
+ pCurrBlock,
+ currentFrameIndex,
+ size,
+ alignment,
+ allocFlagsCopy,
+ createInfo.pUserData,
+ suballocType,
+ strategy,
+ pAllocation);
+ if(res == VK_SUCCESS)
+ {
+ VMA_DEBUG_LOG(" Returned from existing block #%u", pCurrBlock->GetId());
+ return VK_SUCCESS;
+ }
+ }
+ }
+ else // WORST_FIT, FIRST_FIT
+ {
+ // Backward order in m_Blocks - prefer blocks with largest amount of free space.
+ for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+ {
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pCurrBlock);
+ VkResult res = AllocateFromBlock(
+ pCurrBlock,
+ currentFrameIndex,
+ size,
+ alignment,
+ allocFlagsCopy,
+ createInfo.pUserData,
+ suballocType,
+ strategy,
+ pAllocation);
+ if(res == VK_SUCCESS)
+ {
+ VMA_DEBUG_LOG(" Returned from existing block #%u", pCurrBlock->GetId());
+ return VK_SUCCESS;
+ }
+ }
+ }
+ }
+
+ // 2. Try to create new block.
+ if(canCreateNewBlock)
+ {
+ // Calculate optimal size for new block.
+ VkDeviceSize newBlockSize = m_PreferredBlockSize;
+ uint32_t newBlockSizeShift = 0;
+ const uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3;
+
+ if(!m_ExplicitBlockSize)
+ {
+ // Allocate 1/8, 1/4, 1/2 as first blocks.
+ const VkDeviceSize maxExistingBlockSize = CalcMaxBlockSize();
+ for(uint32_t i = 0; i < NEW_BLOCK_SIZE_SHIFT_MAX; ++i)
+ {
+ const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
+ if(smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= size * 2)
+ {
+ newBlockSize = smallerNewBlockSize;
+ ++newBlockSizeShift;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ size_t newBlockIndex = 0;
+ VkResult res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ?
+ CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ // Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize.
+ if(!m_ExplicitBlockSize)
+ {
+ while(res < 0 && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX)
+ {
+ const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
+ if(smallerNewBlockSize >= size)
+ {
+ newBlockSize = smallerNewBlockSize;
+ ++newBlockSizeShift;
+ res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ?
+ CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ if(res == VK_SUCCESS)
+ {
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex];
+ VMA_ASSERT(pBlock->m_pMetadata->GetSize() >= size);
+
+ res = AllocateFromBlock(
+ pBlock,
+ currentFrameIndex,
+ size,
+ alignment,
+ allocFlagsCopy,
+ createInfo.pUserData,
+ suballocType,
+ strategy,
+ pAllocation);
+ if(res == VK_SUCCESS)
+ {
+ VMA_DEBUG_LOG(" Created new block #%u Size=%llu", pBlock->GetId(), newBlockSize);
+ return VK_SUCCESS;
+ }
+ else
+ {
+ // Allocation from new block failed, possibly due to VMA_DEBUG_MARGIN or alignment.
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ }
+ }
+ }
+
+ // 3. Try to allocate from existing blocks with making other allocations lost.
+ if(canMakeOtherLost)
+ {
+ uint32_t tryIndex = 0;
+ for(; tryIndex < VMA_ALLOCATION_TRY_COUNT; ++tryIndex)
+ {
+ VmaDeviceMemoryBlock* pBestRequestBlock = VMA_NULL;
+ VmaAllocationRequest bestRequest = {};
+ VkDeviceSize bestRequestCost = VK_WHOLE_SIZE;
+
+ // 1. Search existing allocations.
+ if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+ {
+ // Forward order in m_Blocks - prefer blocks with smallest amount of free space.
+ for(size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex )
+ {
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pCurrBlock);
+ VmaAllocationRequest currRequest = {};
+ if(pCurrBlock->m_pMetadata->CreateAllocationRequest(
+ currentFrameIndex,
+ m_FrameInUseCount,
+ m_BufferImageGranularity,
+ size,
+ alignment,
+ (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0,
+ suballocType,
+ canMakeOtherLost,
+ strategy,
+ &currRequest))
+ {
+ const VkDeviceSize currRequestCost = currRequest.CalcCost();
+ if(pBestRequestBlock == VMA_NULL ||
+ currRequestCost < bestRequestCost)
+ {
+ pBestRequestBlock = pCurrBlock;
+ bestRequest = currRequest;
+ bestRequestCost = currRequestCost;
+
+ if(bestRequestCost == 0)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ else // WORST_FIT, FIRST_FIT
+ {
+ // Backward order in m_Blocks - prefer blocks with largest amount of free space.
+ for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+ {
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pCurrBlock);
+ VmaAllocationRequest currRequest = {};
+ if(pCurrBlock->m_pMetadata->CreateAllocationRequest(
+ currentFrameIndex,
+ m_FrameInUseCount,
+ m_BufferImageGranularity,
+ size,
+ alignment,
+ (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0,
+ suballocType,
+ canMakeOtherLost,
+ strategy,
+ &currRequest))
+ {
+ const VkDeviceSize currRequestCost = currRequest.CalcCost();
+ if(pBestRequestBlock == VMA_NULL ||
+ currRequestCost < bestRequestCost ||
+ strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
+ {
+ pBestRequestBlock = pCurrBlock;
+ bestRequest = currRequest;
+ bestRequestCost = currRequestCost;
+
+ if(bestRequestCost == 0 ||
+ strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if(pBestRequestBlock != VMA_NULL)
+ {
+ if(mapped)
+ {
+ VkResult res = pBestRequestBlock->Map(m_hAllocator, 1, VMA_NULL);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+ }
+
+ if(pBestRequestBlock->m_pMetadata->MakeRequestedAllocationsLost(
+ currentFrameIndex,
+ m_FrameInUseCount,
+ &bestRequest))
+ {
+ // Allocate from this pBlock.
+ *pAllocation = m_hAllocator->m_AllocationObjectAllocator.Allocate();
+ (*pAllocation)->Ctor(currentFrameIndex, isUserDataString);
+ pBestRequestBlock->m_pMetadata->Alloc(bestRequest, suballocType, size, *pAllocation);
+ UpdateHasEmptyBlock();
+ (*pAllocation)->InitBlockAllocation(
+ pBestRequestBlock,
+ bestRequest.offset,
+ alignment,
+ size,
+ m_MemoryTypeIndex,
+ suballocType,
+ mapped,
+ (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
+ VMA_HEAVY_ASSERT(pBestRequestBlock->Validate());
+ VMA_DEBUG_LOG(" Returned from existing block");
+ (*pAllocation)->SetUserData(m_hAllocator, createInfo.pUserData);
+ m_hAllocator->m_Budget.AddAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), size);
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+ {
+ m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
+ }
+ if(IsCorruptionDetectionEnabled())
+ {
+ VkResult res = pBestRequestBlock->WriteMagicValueAroundAllocation(m_hAllocator, bestRequest.offset, size);
+ VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
+ }
+ return VK_SUCCESS;
+ }
+ // else: Some allocations must have been touched while we are here. Next try.
+ }
+ else
+ {
+ // Could not find place in any of the blocks - break outer loop.
+ break;
+ }
+ }
+ /* Maximum number of tries exceeded - a very unlike event when many other
+ threads are simultaneously touching allocations making it impossible to make
+ lost at the same time as we try to allocate. */
+ if(tryIndex == VMA_ALLOCATION_TRY_COUNT)
+ {
+ return VK_ERROR_TOO_MANY_OBJECTS;
+ }
+ }
+
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+}
+
+void VmaBlockVector::Free(
+ const VmaAllocation hAllocation)
+{
+ VmaDeviceMemoryBlock* pBlockToDelete = VMA_NULL;
+
+ bool budgetExceeded = false;
+ {
+ const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);
+ VmaBudget heapBudget = {};
+ m_hAllocator->GetBudget(&heapBudget, heapIndex, 1);
+ budgetExceeded = heapBudget.usage >= heapBudget.budget;
+ }
+
+ // Scope for lock.
+ {
+ VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+ VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();
+
+ if(IsCorruptionDetectionEnabled())
+ {
+ VkResult res = pBlock->ValidateMagicValueAroundAllocation(m_hAllocator, hAllocation->GetOffset(), hAllocation->GetSize());
+ VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to validate magic value.");
+ }
+
+ if(hAllocation->IsPersistentMap())
+ {
+ pBlock->Unmap(m_hAllocator, 1);
+ }
+
+ pBlock->m_pMetadata->Free(hAllocation);
+ VMA_HEAVY_ASSERT(pBlock->Validate());
+
+ VMA_DEBUG_LOG(" Freed from MemoryTypeIndex=%u", m_MemoryTypeIndex);
+
+ const bool canDeleteBlock = m_Blocks.size() > m_MinBlockCount;
+ // pBlock became empty after this deallocation.
+ if(pBlock->m_pMetadata->IsEmpty())
+ {
+ // Already has empty block. We don't want to have two, so delete this one.
+ if((m_HasEmptyBlock || budgetExceeded) && canDeleteBlock)
+ {
+ pBlockToDelete = pBlock;
+ Remove(pBlock);
+ }
+ // else: We now have an empty block - leave it.
+ }
+ // pBlock didn't become empty, but we have another empty block - find and free that one.
+ // (This is optional, heuristics.)
+ else if(m_HasEmptyBlock && canDeleteBlock)
+ {
+ VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back();
+ if(pLastBlock->m_pMetadata->IsEmpty())
+ {
+ pBlockToDelete = pLastBlock;
+ m_Blocks.pop_back();
+ }
+ }
+
+ UpdateHasEmptyBlock();
+ IncrementallySortBlocks();
+ }
+
+ // Destruction of a free block. Deferred until this point, outside of mutex
+ // lock, for performance reason.
+ if(pBlockToDelete != VMA_NULL)
+ {
+ VMA_DEBUG_LOG(" Deleted empty block");
+ pBlockToDelete->Destroy(m_hAllocator);
+ vma_delete(m_hAllocator, pBlockToDelete);
+ }
+}
+
+VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const
+{
+ VkDeviceSize result = 0;
+ for(size_t i = m_Blocks.size(); i--; )
+ {
+ result = VMA_MAX(result, m_Blocks[i]->m_pMetadata->GetSize());
+ if(result >= m_PreferredBlockSize)
+ {
+ break;
+ }
+ }
+ return result;
+}
+
+void VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock)
+{
+ for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+ {
+ if(m_Blocks[blockIndex] == pBlock)
+ {
+ VmaVectorRemove(m_Blocks, blockIndex);
+ return;
+ }
+ }
+ VMA_ASSERT(0);
+}
+
+void VmaBlockVector::IncrementallySortBlocks()
+{
+ if(m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
+ {
+ // Bubble sort only until first swap.
+ for(size_t i = 1; i < m_Blocks.size(); ++i)
+ {
+ if(m_Blocks[i - 1]->m_pMetadata->GetSumFreeSize() > m_Blocks[i]->m_pMetadata->GetSumFreeSize())
+ {
+ VMA_SWAP(m_Blocks[i - 1], m_Blocks[i]);
+ return;
+ }
+ }
+ }
+}
+
+VkResult VmaBlockVector::AllocateFromBlock(
+ VmaDeviceMemoryBlock* pBlock,
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ VmaAllocationCreateFlags allocFlags,
+ void* pUserData,
+ VmaSuballocationType suballocType,
+ uint32_t strategy,
+ VmaAllocation* pAllocation)
+{
+ VMA_ASSERT((allocFlags & VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT) == 0);
+ const bool isUpperAddress = (allocFlags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0;
+ const bool mapped = (allocFlags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
+ const bool isUserDataString = (allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0;
+
+ VmaAllocationRequest currRequest = {};
+ if(pBlock->m_pMetadata->CreateAllocationRequest(
+ currentFrameIndex,
+ m_FrameInUseCount,
+ m_BufferImageGranularity,
+ size,
+ alignment,
+ isUpperAddress,
+ suballocType,
+ false, // canMakeOtherLost
+ strategy,
+ &currRequest))
+ {
+ // Allocate from pCurrBlock.
+ VMA_ASSERT(currRequest.itemsToMakeLostCount == 0);
+
+ if(mapped)
+ {
+ VkResult res = pBlock->Map(m_hAllocator, 1, VMA_NULL);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+ }
+
+ *pAllocation = m_hAllocator->m_AllocationObjectAllocator.Allocate();
+ (*pAllocation)->Ctor(currentFrameIndex, isUserDataString);
+ pBlock->m_pMetadata->Alloc(currRequest, suballocType, size, *pAllocation);
+ UpdateHasEmptyBlock();
+ (*pAllocation)->InitBlockAllocation(
+ pBlock,
+ currRequest.offset,
+ alignment,
+ size,
+ m_MemoryTypeIndex,
+ suballocType,
+ mapped,
+ (allocFlags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
+ VMA_HEAVY_ASSERT(pBlock->Validate());
+ (*pAllocation)->SetUserData(m_hAllocator, pUserData);
+ m_hAllocator->m_Budget.AddAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), size);
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+ {
+ m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
+ }
+ if(IsCorruptionDetectionEnabled())
+ {
+ VkResult res = pBlock->WriteMagicValueAroundAllocation(m_hAllocator, currRequest.offset, size);
+ VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
+ }
+ return VK_SUCCESS;
+ }
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+}
+
+VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex)
+{
+ VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
+ allocInfo.memoryTypeIndex = m_MemoryTypeIndex;
+ allocInfo.allocationSize = blockSize;
+ VkDeviceMemory mem = VK_NULL_HANDLE;
+ VkResult res = m_hAllocator->AllocateVulkanMemory(&allocInfo, &mem);
+ if(res < 0)
+ {
+ return res;
+ }
+
+ // New VkDeviceMemory successfully created.
+
+ // Create new Allocation for it.
+ VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator);
+ pBlock->Init(
+ m_hAllocator,
+ m_hParentPool,
+ m_MemoryTypeIndex,
+ mem,
+ allocInfo.allocationSize,
+ m_NextBlockId++,
+ m_Algorithm);
+
+ m_Blocks.push_back(pBlock);
+ if(pNewBlockIndex != VMA_NULL)
+ {
+ *pNewBlockIndex = m_Blocks.size() - 1;
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaBlockVector::ApplyDefragmentationMovesCpu(
+ class VmaBlockVectorDefragmentationContext* pDefragCtx,
+ const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves)
+{
+ const size_t blockCount = m_Blocks.size();
+ const bool isNonCoherent = m_hAllocator->IsMemoryTypeNonCoherent(m_MemoryTypeIndex);
+
+ enum BLOCK_FLAG
+ {
+ BLOCK_FLAG_USED = 0x00000001,
+ BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION = 0x00000002,
+ };
+
+ struct BlockInfo
+ {
+ uint32_t flags;
+ void* pMappedData;
+ };
+ VmaVector< BlockInfo, VmaStlAllocator<BlockInfo> >
+ blockInfo(blockCount, BlockInfo(), VmaStlAllocator<BlockInfo>(m_hAllocator->GetAllocationCallbacks()));
+ memset(blockInfo.data(), 0, blockCount * sizeof(BlockInfo));
+
+ // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.
+ const size_t moveCount = moves.size();
+ for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ {
+ const VmaDefragmentationMove& move = moves[moveIndex];
+ blockInfo[move.srcBlockIndex].flags |= BLOCK_FLAG_USED;
+ blockInfo[move.dstBlockIndex].flags |= BLOCK_FLAG_USED;
+ }
+
+ VMA_ASSERT(pDefragCtx->res == VK_SUCCESS);
+
+ // Go over all blocks. Get mapped pointer or map if necessary.
+ for(size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex)
+ {
+ BlockInfo& currBlockInfo = blockInfo[blockIndex];
+ VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+ if((currBlockInfo.flags & BLOCK_FLAG_USED) != 0)
+ {
+ currBlockInfo.pMappedData = pBlock->GetMappedData();
+ // It is not originally mapped - map it.
+ if(currBlockInfo.pMappedData == VMA_NULL)
+ {
+ pDefragCtx->res = pBlock->Map(m_hAllocator, 1, &currBlockInfo.pMappedData);
+ if(pDefragCtx->res == VK_SUCCESS)
+ {
+ currBlockInfo.flags |= BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION;
+ }
+ }
+ }
+ }
+
+ // Go over all moves. Do actual data transfer.
+ if(pDefragCtx->res == VK_SUCCESS)
+ {
+ const VkDeviceSize nonCoherentAtomSize = m_hAllocator->m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
+ VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
+
+ for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ {
+ const VmaDefragmentationMove& move = moves[moveIndex];
+
+ const BlockInfo& srcBlockInfo = blockInfo[move.srcBlockIndex];
+ const BlockInfo& dstBlockInfo = blockInfo[move.dstBlockIndex];
+
+ VMA_ASSERT(srcBlockInfo.pMappedData && dstBlockInfo.pMappedData);
+
+ // Invalidate source.
+ if(isNonCoherent)
+ {
+ VmaDeviceMemoryBlock* const pSrcBlock = m_Blocks[move.srcBlockIndex];
+ memRange.memory = pSrcBlock->GetDeviceMemory();
+ memRange.offset = VmaAlignDown(move.srcOffset, nonCoherentAtomSize);
+ memRange.size = VMA_MIN(
+ VmaAlignUp(move.size + (move.srcOffset - memRange.offset), nonCoherentAtomSize),
+ pSrcBlock->m_pMetadata->GetSize() - memRange.offset);
+ (*m_hAllocator->GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hAllocator->m_hDevice, 1, &memRange);
+ }
+
+ // THE PLACE WHERE ACTUAL DATA COPY HAPPENS.
+ memmove(
+ reinterpret_cast<char*>(dstBlockInfo.pMappedData) + move.dstOffset,
+ reinterpret_cast<char*>(srcBlockInfo.pMappedData) + move.srcOffset,
+ static_cast<size_t>(move.size));
+
+ if(IsCorruptionDetectionEnabled())
+ {
+ VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset - VMA_DEBUG_MARGIN);
+ VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset + move.size);
+ }
+
+ // Flush destination.
+ if(isNonCoherent)
+ {
+ VmaDeviceMemoryBlock* const pDstBlock = m_Blocks[move.dstBlockIndex];
+ memRange.memory = pDstBlock->GetDeviceMemory();
+ memRange.offset = VmaAlignDown(move.dstOffset, nonCoherentAtomSize);
+ memRange.size = VMA_MIN(
+ VmaAlignUp(move.size + (move.dstOffset - memRange.offset), nonCoherentAtomSize),
+ pDstBlock->m_pMetadata->GetSize() - memRange.offset);
+ (*m_hAllocator->GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hAllocator->m_hDevice, 1, &memRange);
+ }
+ }
+ }
+
+ // Go over all blocks in reverse order. Unmap those that were mapped just for defragmentation.
+ // Regardless of pCtx->res == VK_SUCCESS.
+ for(size_t blockIndex = blockCount; blockIndex--; )
+ {
+ const BlockInfo& currBlockInfo = blockInfo[blockIndex];
+ if((currBlockInfo.flags & BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION) != 0)
+ {
+ VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+ pBlock->Unmap(m_hAllocator, 1);
+ }
+ }
+}
+
+void VmaBlockVector::ApplyDefragmentationMovesGpu(
+ class VmaBlockVectorDefragmentationContext* pDefragCtx,
+ const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkCommandBuffer commandBuffer)
+{
+ const size_t blockCount = m_Blocks.size();
+
+ pDefragCtx->blockContexts.resize(blockCount);
+ memset(pDefragCtx->blockContexts.data(), 0, blockCount * sizeof(VmaBlockDefragmentationContext));
+
+ // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.
+ const size_t moveCount = moves.size();
+ for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ {
+ const VmaDefragmentationMove& move = moves[moveIndex];
+ pDefragCtx->blockContexts[move.srcBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED;
+ pDefragCtx->blockContexts[move.dstBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED;
+ }
+
+ VMA_ASSERT(pDefragCtx->res == VK_SUCCESS);
+
+ // Go over all blocks. Create and bind buffer for whole block if necessary.
+ {
+ VkBufferCreateInfo bufCreateInfo;
+ VmaFillGpuDefragmentationBufferCreateInfo(bufCreateInfo);
+
+ for(size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex)
+ {
+ VmaBlockDefragmentationContext& currBlockCtx = pDefragCtx->blockContexts[blockIndex];
+ VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+ if((currBlockCtx.flags & VmaBlockDefragmentationContext::BLOCK_FLAG_USED) != 0)
+ {
+ bufCreateInfo.size = pBlock->m_pMetadata->GetSize();
+ pDefragCtx->res = (*m_hAllocator->GetVulkanFunctions().vkCreateBuffer)(
+ m_hAllocator->m_hDevice, &bufCreateInfo, m_hAllocator->GetAllocationCallbacks(), &currBlockCtx.hBuffer);
+ if(pDefragCtx->res == VK_SUCCESS)
+ {
+ pDefragCtx->res = (*m_hAllocator->GetVulkanFunctions().vkBindBufferMemory)(
+ m_hAllocator->m_hDevice, currBlockCtx.hBuffer, pBlock->GetDeviceMemory(), 0);
+ }
+ }
+ }
+ }
+
+ // Go over all moves. Post data transfer commands to command buffer.
+ if(pDefragCtx->res == VK_SUCCESS)
+ {
+ for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ {
+ const VmaDefragmentationMove& move = moves[moveIndex];
+
+ const VmaBlockDefragmentationContext& srcBlockCtx = pDefragCtx->blockContexts[move.srcBlockIndex];
+ const VmaBlockDefragmentationContext& dstBlockCtx = pDefragCtx->blockContexts[move.dstBlockIndex];
+
+ VMA_ASSERT(srcBlockCtx.hBuffer && dstBlockCtx.hBuffer);
+
+ VkBufferCopy region = {
+ move.srcOffset,
+ move.dstOffset,
+ move.size };
+ (*m_hAllocator->GetVulkanFunctions().vkCmdCopyBuffer)(
+ commandBuffer, srcBlockCtx.hBuffer, dstBlockCtx.hBuffer, 1, &region);
+ }
+ }
+
+ // Save buffers to defrag context for later destruction.
+ if(pDefragCtx->res == VK_SUCCESS && moveCount > 0)
+ {
+ pDefragCtx->res = VK_NOT_READY;
+ }
+}
+
+void VmaBlockVector::FreeEmptyBlocks(VmaDefragmentationStats* pDefragmentationStats)
+{
+ for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+ {
+ VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+ if(pBlock->m_pMetadata->IsEmpty())
+ {
+ if(m_Blocks.size() > m_MinBlockCount)
+ {
+ if(pDefragmentationStats != VMA_NULL)
+ {
+ ++pDefragmentationStats->deviceMemoryBlocksFreed;
+ pDefragmentationStats->bytesFreed += pBlock->m_pMetadata->GetSize();
+ }
+
+ VmaVectorRemove(m_Blocks, blockIndex);
+ pBlock->Destroy(m_hAllocator);
+ vma_delete(m_hAllocator, pBlock);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ UpdateHasEmptyBlock();
+}
+
+void VmaBlockVector::UpdateHasEmptyBlock()
+{
+ m_HasEmptyBlock = false;
+ for(size_t index = 0, count = m_Blocks.size(); index < count; ++index)
+ {
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[index];
+ if(pBlock->m_pMetadata->IsEmpty())
+ {
+ m_HasEmptyBlock = true;
+ break;
+ }
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json)
+{
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+ json.BeginObject();
+
+ if(IsCustomPool())
+ {
+ const char* poolName = m_hParentPool->GetName();
+ if(poolName != VMA_NULL && poolName[0] != '\0')
+ {
+ json.WriteString("Name");
+ json.WriteString(poolName);
+ }
+
+ json.WriteString("MemoryTypeIndex");
+ json.WriteNumber(m_MemoryTypeIndex);
+
+ json.WriteString("BlockSize");
+ json.WriteNumber(m_PreferredBlockSize);
+
+ json.WriteString("BlockCount");
+ json.BeginObject(true);
+ if(m_MinBlockCount > 0)
+ {
+ json.WriteString("Min");
+ json.WriteNumber((uint64_t)m_MinBlockCount);
+ }
+ if(m_MaxBlockCount < SIZE_MAX)
+ {
+ json.WriteString("Max");
+ json.WriteNumber((uint64_t)m_MaxBlockCount);
+ }
+ json.WriteString("Cur");
+ json.WriteNumber((uint64_t)m_Blocks.size());
+ json.EndObject();
+
+ if(m_FrameInUseCount > 0)
+ {
+ json.WriteString("FrameInUseCount");
+ json.WriteNumber(m_FrameInUseCount);
+ }
+
+ if(m_Algorithm != 0)
+ {
+ json.WriteString("Algorithm");
+ json.WriteString(VmaAlgorithmToStr(m_Algorithm));
+ }
+ }
+ else
+ {
+ json.WriteString("PreferredBlockSize");
+ json.WriteNumber(m_PreferredBlockSize);
+ }
+
+ json.WriteString("Blocks");
+ json.BeginObject();
+ for(size_t i = 0; i < m_Blocks.size(); ++i)
+ {
+ json.BeginString();
+ json.ContinueString(m_Blocks[i]->GetId());
+ json.EndString();
+
+ m_Blocks[i]->m_pMetadata->PrintDetailedMap(json);
+ }
+ json.EndObject();
+
+ json.EndObject();
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+void VmaBlockVector::Defragment(
+ class VmaBlockVectorDefragmentationContext* pCtx,
+ VmaDefragmentationStats* pStats,
+ VkDeviceSize& maxCpuBytesToMove, uint32_t& maxCpuAllocationsToMove,
+ VkDeviceSize& maxGpuBytesToMove, uint32_t& maxGpuAllocationsToMove,
+ VkCommandBuffer commandBuffer)
+{
+ pCtx->res = VK_SUCCESS;
+
+ const VkMemoryPropertyFlags memPropFlags =
+ m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags;
+ const bool isHostVisible = (memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
+
+ const bool canDefragmentOnCpu = maxCpuBytesToMove > 0 && maxCpuAllocationsToMove > 0 &&
+ isHostVisible;
+ const bool canDefragmentOnGpu = maxGpuBytesToMove > 0 && maxGpuAllocationsToMove > 0 &&
+ !IsCorruptionDetectionEnabled() &&
+ ((1u << m_MemoryTypeIndex) & m_hAllocator->GetGpuDefragmentationMemoryTypeBits()) != 0;
+
+ // There are options to defragment this memory type.
+ if(canDefragmentOnCpu || canDefragmentOnGpu)
+ {
+ bool defragmentOnGpu;
+ // There is only one option to defragment this memory type.
+ if(canDefragmentOnGpu != canDefragmentOnCpu)
+ {
+ defragmentOnGpu = canDefragmentOnGpu;
+ }
+ // Both options are available: Heuristics to choose the best one.
+ else
+ {
+ defragmentOnGpu = (memPropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0 ||
+ m_hAllocator->IsIntegratedGpu();
+ }
+
+ bool overlappingMoveSupported = !defragmentOnGpu;
+
+ if(m_hAllocator->m_UseMutex)
+ {
+ m_Mutex.LockWrite();
+ pCtx->mutexLocked = true;
+ }
+
+ pCtx->Begin(overlappingMoveSupported);
+
+ // Defragment.
+
+ const VkDeviceSize maxBytesToMove = defragmentOnGpu ? maxGpuBytesToMove : maxCpuBytesToMove;
+ const uint32_t maxAllocationsToMove = defragmentOnGpu ? maxGpuAllocationsToMove : maxCpuAllocationsToMove;
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> > moves =
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >(VmaStlAllocator<VmaDefragmentationMove>(m_hAllocator->GetAllocationCallbacks()));
+ pCtx->res = pCtx->GetAlgorithm()->Defragment(moves, maxBytesToMove, maxAllocationsToMove);
+
+ // Accumulate statistics.
+ if(pStats != VMA_NULL)
+ {
+ const VkDeviceSize bytesMoved = pCtx->GetAlgorithm()->GetBytesMoved();
+ const uint32_t allocationsMoved = pCtx->GetAlgorithm()->GetAllocationsMoved();
+ pStats->bytesMoved += bytesMoved;
+ pStats->allocationsMoved += allocationsMoved;
+ VMA_ASSERT(bytesMoved <= maxBytesToMove);
+ VMA_ASSERT(allocationsMoved <= maxAllocationsToMove);
+ if(defragmentOnGpu)
+ {
+ maxGpuBytesToMove -= bytesMoved;
+ maxGpuAllocationsToMove -= allocationsMoved;
+ }
+ else
+ {
+ maxCpuBytesToMove -= bytesMoved;
+ maxCpuAllocationsToMove -= allocationsMoved;
+ }
+ }
+
+ if(pCtx->res >= VK_SUCCESS)
+ {
+ if(defragmentOnGpu)
+ {
+ ApplyDefragmentationMovesGpu(pCtx, moves, commandBuffer);
+ }
+ else
+ {
+ ApplyDefragmentationMovesCpu(pCtx, moves);
+ }
+ }
+ }
+}
+
+void VmaBlockVector::DefragmentationEnd(
+ class VmaBlockVectorDefragmentationContext* pCtx,
+ VmaDefragmentationStats* pStats)
+{
+ // Destroy buffers.
+ for(size_t blockIndex = pCtx->blockContexts.size(); blockIndex--; )
+ {
+ VmaBlockDefragmentationContext& blockCtx = pCtx->blockContexts[blockIndex];
+ if(blockCtx.hBuffer)
+ {
+ (*m_hAllocator->GetVulkanFunctions().vkDestroyBuffer)(
+ m_hAllocator->m_hDevice, blockCtx.hBuffer, m_hAllocator->GetAllocationCallbacks());
+ }
+ }
+
+ if(pCtx->res >= VK_SUCCESS)
+ {
+ FreeEmptyBlocks(pStats);
+ }
+
+ if(pCtx->mutexLocked)
+ {
+ VMA_ASSERT(m_hAllocator->m_UseMutex);
+ m_Mutex.UnlockWrite();
+ }
+}
+
+size_t VmaBlockVector::CalcAllocationCount() const
+{
+ size_t result = 0;
+ for(size_t i = 0; i < m_Blocks.size(); ++i)
+ {
+ result += m_Blocks[i]->m_pMetadata->GetAllocationCount();
+ }
+ return result;
+}
+
+bool VmaBlockVector::IsBufferImageGranularityConflictPossible() const
+{
+ if(m_BufferImageGranularity == 1)
+ {
+ return false;
+ }
+ VmaSuballocationType lastSuballocType = VMA_SUBALLOCATION_TYPE_FREE;
+ for(size_t i = 0, count = m_Blocks.size(); i < count; ++i)
+ {
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[i];
+ VMA_ASSERT(m_Algorithm == 0);
+ VmaBlockMetadata_Generic* const pMetadata = (VmaBlockMetadata_Generic*)pBlock->m_pMetadata;
+ if(pMetadata->IsBufferImageGranularityConflictPossible(m_BufferImageGranularity, lastSuballocType))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void VmaBlockVector::MakePoolAllocationsLost(
+ uint32_t currentFrameIndex,
+ size_t* pLostAllocationCount)
+{
+ VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+ size_t lostAllocationCount = 0;
+ for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+ {
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pBlock);
+ lostAllocationCount += pBlock->m_pMetadata->MakeAllocationsLost(currentFrameIndex, m_FrameInUseCount);
+ }
+ if(pLostAllocationCount != VMA_NULL)
+ {
+ *pLostAllocationCount = lostAllocationCount;
+ }
+}
+
+VkResult VmaBlockVector::CheckCorruption()
+{
+ if(!IsCorruptionDetectionEnabled())
+ {
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+ }
+
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+ for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+ {
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pBlock);
+ VkResult res = pBlock->CheckCorruption(m_hAllocator);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+ }
+ return VK_SUCCESS;
+}
+
+void VmaBlockVector::AddStats(VmaStats* pStats)
+{
+ const uint32_t memTypeIndex = m_MemoryTypeIndex;
+ const uint32_t memHeapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(memTypeIndex);
+
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+ for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+ {
+ const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pBlock);
+ VMA_HEAVY_ASSERT(pBlock->Validate());
+ VmaStatInfo allocationStatInfo;
+ pBlock->m_pMetadata->CalcAllocationStatInfo(allocationStatInfo);
+ VmaAddStatInfo(pStats->total, allocationStatInfo);
+ VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo);
+ VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaDefragmentationAlgorithm_Generic members definition
+
+VmaDefragmentationAlgorithm_Generic::VmaDefragmentationAlgorithm_Generic(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex,
+ bool overlappingMoveSupported) :
+ VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
+ m_AllocationCount(0),
+ m_AllAllocations(false),
+ m_BytesMoved(0),
+ m_AllocationsMoved(0),
+ m_Blocks(VmaStlAllocator<BlockInfo*>(hAllocator->GetAllocationCallbacks()))
+{
+ // Create block info for each block.
+ const size_t blockCount = m_pBlockVector->m_Blocks.size();
+ for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ BlockInfo* pBlockInfo = vma_new(m_hAllocator, BlockInfo)(m_hAllocator->GetAllocationCallbacks());
+ pBlockInfo->m_OriginalBlockIndex = blockIndex;
+ pBlockInfo->m_pBlock = m_pBlockVector->m_Blocks[blockIndex];
+ m_Blocks.push_back(pBlockInfo);
+ }
+
+ // Sort them by m_pBlock pointer value.
+ VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockPointerLess());
+}
+
+VmaDefragmentationAlgorithm_Generic::~VmaDefragmentationAlgorithm_Generic()
+{
+ for(size_t i = m_Blocks.size(); i--; )
+ {
+ vma_delete(m_hAllocator, m_Blocks[i]);
+ }
+}
+
+void VmaDefragmentationAlgorithm_Generic::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged)
+{
+ // Now as we are inside VmaBlockVector::m_Mutex, we can make final check if this allocation was not lost.
+ if(hAlloc->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST)
+ {
+ VmaDeviceMemoryBlock* pBlock = hAlloc->GetBlock();
+ BlockInfoVector::iterator it = VmaBinaryFindFirstNotLess(m_Blocks.begin(), m_Blocks.end(), pBlock, BlockPointerLess());
+ if(it != m_Blocks.end() && (*it)->m_pBlock == pBlock)
+ {
+ AllocationInfo allocInfo = AllocationInfo(hAlloc, pChanged);
+ (*it)->m_Allocations.push_back(allocInfo);
+ }
+ else
+ {
+ VMA_ASSERT(0);
+ }
+
+ ++m_AllocationCount;
+ }
+}
+
+VkResult VmaDefragmentationAlgorithm_Generic::DefragmentRound(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove)
+{
+ if(m_Blocks.empty())
+ {
+ return VK_SUCCESS;
+ }
+
+ // This is a choice based on research.
+ // Option 1:
+ uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT;
+ // Option 2:
+ //uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT;
+ // Option 3:
+ //uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT;
+
+ size_t srcBlockMinIndex = 0;
+ // When FAST_ALGORITHM, move allocations from only last out of blocks that contain non-movable allocations.
+ /*
+ if(m_AlgorithmFlags & VMA_DEFRAGMENTATION_FAST_ALGORITHM_BIT)
+ {
+ const size_t blocksWithNonMovableCount = CalcBlocksWithNonMovableCount();
+ if(blocksWithNonMovableCount > 0)
+ {
+ srcBlockMinIndex = blocksWithNonMovableCount - 1;
+ }
+ }
+ */
+
+ size_t srcBlockIndex = m_Blocks.size() - 1;
+ size_t srcAllocIndex = SIZE_MAX;
+ for(;;)
+ {
+ // 1. Find next allocation to move.
+ // 1.1. Start from last to first m_Blocks - they are sorted from most "destination" to most "source".
+ // 1.2. Then start from last to first m_Allocations.
+ while(srcAllocIndex >= m_Blocks[srcBlockIndex]->m_Allocations.size())
+ {
+ if(m_Blocks[srcBlockIndex]->m_Allocations.empty())
+ {
+ // Finished: no more allocations to process.
+ if(srcBlockIndex == srcBlockMinIndex)
+ {
+ return VK_SUCCESS;
+ }
+ else
+ {
+ --srcBlockIndex;
+ srcAllocIndex = SIZE_MAX;
+ }
+ }
+ else
+ {
+ srcAllocIndex = m_Blocks[srcBlockIndex]->m_Allocations.size() - 1;
+ }
+ }
+
+ BlockInfo* pSrcBlockInfo = m_Blocks[srcBlockIndex];
+ AllocationInfo& allocInfo = pSrcBlockInfo->m_Allocations[srcAllocIndex];
+
+ const VkDeviceSize size = allocInfo.m_hAllocation->GetSize();
+ const VkDeviceSize srcOffset = allocInfo.m_hAllocation->GetOffset();
+ const VkDeviceSize alignment = allocInfo.m_hAllocation->GetAlignment();
+ const VmaSuballocationType suballocType = allocInfo.m_hAllocation->GetSuballocationType();
+
+ // 2. Try to find new place for this allocation in preceding or current block.
+ for(size_t dstBlockIndex = 0; dstBlockIndex <= srcBlockIndex; ++dstBlockIndex)
+ {
+ BlockInfo* pDstBlockInfo = m_Blocks[dstBlockIndex];
+ VmaAllocationRequest dstAllocRequest;
+ if(pDstBlockInfo->m_pBlock->m_pMetadata->CreateAllocationRequest(
+ m_CurrentFrameIndex,
+ m_pBlockVector->GetFrameInUseCount(),
+ m_pBlockVector->GetBufferImageGranularity(),
+ size,
+ alignment,
+ false, // upperAddress
+ suballocType,
+ false, // canMakeOtherLost
+ strategy,
+ &dstAllocRequest) &&
+ MoveMakesSense(
+ dstBlockIndex, dstAllocRequest.offset, srcBlockIndex, srcOffset))
+ {
+ VMA_ASSERT(dstAllocRequest.itemsToMakeLostCount == 0);
+
+ // Reached limit on number of allocations or bytes to move.
+ if((m_AllocationsMoved + 1 > maxAllocationsToMove) ||
+ (m_BytesMoved + size > maxBytesToMove))
+ {
+ return VK_SUCCESS;
+ }
+
+ VmaDefragmentationMove move;
+ move.srcBlockIndex = pSrcBlockInfo->m_OriginalBlockIndex;
+ move.dstBlockIndex = pDstBlockInfo->m_OriginalBlockIndex;
+ move.srcOffset = srcOffset;
+ move.dstOffset = dstAllocRequest.offset;
+ move.size = size;
+ moves.push_back(move);
+
+ pDstBlockInfo->m_pBlock->m_pMetadata->Alloc(
+ dstAllocRequest,
+ suballocType,
+ size,
+ allocInfo.m_hAllocation);
+ pSrcBlockInfo->m_pBlock->m_pMetadata->FreeAtOffset(srcOffset);
+
+ allocInfo.m_hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlockInfo->m_pBlock, dstAllocRequest.offset);
+
+ if(allocInfo.m_pChanged != VMA_NULL)
+ {
+ *allocInfo.m_pChanged = VK_TRUE;
+ }
+
+ ++m_AllocationsMoved;
+ m_BytesMoved += size;
+
+ VmaVectorRemove(pSrcBlockInfo->m_Allocations, srcAllocIndex);
+
+ break;
+ }
+ }
+
+ // If not processed, this allocInfo remains in pBlockInfo->m_Allocations for next round.
+
+ if(srcAllocIndex > 0)
+ {
+ --srcAllocIndex;
+ }
+ else
+ {
+ if(srcBlockIndex > 0)
+ {
+ --srcBlockIndex;
+ srcAllocIndex = SIZE_MAX;
+ }
+ else
+ {
+ return VK_SUCCESS;
+ }
+ }
+ }
+}
+
+size_t VmaDefragmentationAlgorithm_Generic::CalcBlocksWithNonMovableCount() const
+{
+ size_t result = 0;
+ for(size_t i = 0; i < m_Blocks.size(); ++i)
+ {
+ if(m_Blocks[i]->m_HasNonMovableAllocations)
+ {
+ ++result;
+ }
+ }
+ return result;
+}
+
+VkResult VmaDefragmentationAlgorithm_Generic::Defragment(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove)
+{
+ if(!m_AllAllocations && m_AllocationCount == 0)
+ {
+ return VK_SUCCESS;
+ }
+
+ const size_t blockCount = m_Blocks.size();
+ for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ BlockInfo* pBlockInfo = m_Blocks[blockIndex];
+
+ if(m_AllAllocations)
+ {
+ VmaBlockMetadata_Generic* pMetadata = (VmaBlockMetadata_Generic*)pBlockInfo->m_pBlock->m_pMetadata;
+ for(VmaSuballocationList::const_iterator it = pMetadata->m_Suballocations.begin();
+ it != pMetadata->m_Suballocations.end();
+ ++it)
+ {
+ if(it->type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ AllocationInfo allocInfo = AllocationInfo(it->hAllocation, VMA_NULL);
+ pBlockInfo->m_Allocations.push_back(allocInfo);
+ }
+ }
+ }
+
+ pBlockInfo->CalcHasNonMovableAllocations();
+
+ // This is a choice based on research.
+ // Option 1:
+ pBlockInfo->SortAllocationsByOffsetDescending();
+ // Option 2:
+ //pBlockInfo->SortAllocationsBySizeDescending();
+ }
+
+ // Sort m_Blocks this time by the main criterium, from most "destination" to most "source" blocks.
+ VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockInfoCompareMoveDestination());
+
+ // This is a choice based on research.
+ const uint32_t roundCount = 2;
+
+ // Execute defragmentation rounds (the main part).
+ VkResult result = VK_SUCCESS;
+ for(uint32_t round = 0; (round < roundCount) && (result == VK_SUCCESS); ++round)
+ {
+ result = DefragmentRound(moves, maxBytesToMove, maxAllocationsToMove);
+ }
+
+ return result;
+}
+
+bool VmaDefragmentationAlgorithm_Generic::MoveMakesSense(
+ size_t dstBlockIndex, VkDeviceSize dstOffset,
+ size_t srcBlockIndex, VkDeviceSize srcOffset)
+{
+ if(dstBlockIndex < srcBlockIndex)
+ {
+ return true;
+ }
+ if(dstBlockIndex > srcBlockIndex)
+ {
+ return false;
+ }
+ if(dstOffset < srcOffset)
+ {
+ return true;
+ }
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaDefragmentationAlgorithm_Fast
+
+VmaDefragmentationAlgorithm_Fast::VmaDefragmentationAlgorithm_Fast(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex,
+ bool overlappingMoveSupported) :
+ VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
+ m_OverlappingMoveSupported(overlappingMoveSupported),
+ m_AllocationCount(0),
+ m_AllAllocations(false),
+ m_BytesMoved(0),
+ m_AllocationsMoved(0),
+ m_BlockInfos(VmaStlAllocator<BlockInfo>(hAllocator->GetAllocationCallbacks()))
+{
+ VMA_ASSERT(VMA_DEBUG_MARGIN == 0);
+
+}
+
+VmaDefragmentationAlgorithm_Fast::~VmaDefragmentationAlgorithm_Fast()
+{
+}
+
+VkResult VmaDefragmentationAlgorithm_Fast::Defragment(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove)
+{
+ VMA_ASSERT(m_AllAllocations || m_pBlockVector->CalcAllocationCount() == m_AllocationCount);
+
+ const size_t blockCount = m_pBlockVector->GetBlockCount();
+ if(blockCount == 0 || maxBytesToMove == 0 || maxAllocationsToMove == 0)
+ {
+ return VK_SUCCESS;
+ }
+
+ PreprocessMetadata();
+
+ // Sort blocks in order from most destination.
+
+ m_BlockInfos.resize(blockCount);
+ for(size_t i = 0; i < blockCount; ++i)
+ {
+ m_BlockInfos[i].origBlockIndex = i;
+ }
+
+ VMA_SORT(m_BlockInfos.begin(), m_BlockInfos.end(), [this](const BlockInfo& lhs, const BlockInfo& rhs) -> bool {
+ return m_pBlockVector->GetBlock(lhs.origBlockIndex)->m_pMetadata->GetSumFreeSize() <
+ m_pBlockVector->GetBlock(rhs.origBlockIndex)->m_pMetadata->GetSumFreeSize();
+ });
+
+ // THE MAIN ALGORITHM
+
+ FreeSpaceDatabase freeSpaceDb;
+
+ size_t dstBlockInfoIndex = 0;
+ size_t dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex;
+ VmaDeviceMemoryBlock* pDstBlock = m_pBlockVector->GetBlock(dstOrigBlockIndex);
+ VmaBlockMetadata_Generic* pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock->m_pMetadata;
+ VkDeviceSize dstBlockSize = pDstMetadata->GetSize();
+ VkDeviceSize dstOffset = 0;
+
+ bool end = false;
+ for(size_t srcBlockInfoIndex = 0; !end && srcBlockInfoIndex < blockCount; ++srcBlockInfoIndex)
+ {
+ const size_t srcOrigBlockIndex = m_BlockInfos[srcBlockInfoIndex].origBlockIndex;
+ VmaDeviceMemoryBlock* const pSrcBlock = m_pBlockVector->GetBlock(srcOrigBlockIndex);
+ VmaBlockMetadata_Generic* const pSrcMetadata = (VmaBlockMetadata_Generic*)pSrcBlock->m_pMetadata;
+ for(VmaSuballocationList::iterator srcSuballocIt = pSrcMetadata->m_Suballocations.begin();
+ !end && srcSuballocIt != pSrcMetadata->m_Suballocations.end(); )
+ {
+ VmaAllocation_T* const pAlloc = srcSuballocIt->hAllocation;
+ const VkDeviceSize srcAllocAlignment = pAlloc->GetAlignment();
+ const VkDeviceSize srcAllocSize = srcSuballocIt->size;
+ if(m_AllocationsMoved == maxAllocationsToMove ||
+ m_BytesMoved + srcAllocSize > maxBytesToMove)
+ {
+ end = true;
+ break;
+ }
+ const VkDeviceSize srcAllocOffset = srcSuballocIt->offset;
+
+ // Try to place it in one of free spaces from the database.
+ size_t freeSpaceInfoIndex;
+ VkDeviceSize dstAllocOffset;
+ if(freeSpaceDb.Fetch(srcAllocAlignment, srcAllocSize,
+ freeSpaceInfoIndex, dstAllocOffset))
+ {
+ size_t freeSpaceOrigBlockIndex = m_BlockInfos[freeSpaceInfoIndex].origBlockIndex;
+ VmaDeviceMemoryBlock* pFreeSpaceBlock = m_pBlockVector->GetBlock(freeSpaceOrigBlockIndex);
+ VmaBlockMetadata_Generic* pFreeSpaceMetadata = (VmaBlockMetadata_Generic*)pFreeSpaceBlock->m_pMetadata;
+
+ // Same block
+ if(freeSpaceInfoIndex == srcBlockInfoIndex)
+ {
+ VMA_ASSERT(dstAllocOffset <= srcAllocOffset);
+
+ // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
+
+ VmaSuballocation suballoc = *srcSuballocIt;
+ suballoc.offset = dstAllocOffset;
+ suballoc.hAllocation->ChangeOffset(dstAllocOffset);
+ m_BytesMoved += srcAllocSize;
+ ++m_AllocationsMoved;
+
+ VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
+ ++nextSuballocIt;
+ pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
+ srcSuballocIt = nextSuballocIt;
+
+ InsertSuballoc(pFreeSpaceMetadata, suballoc);
+
+ VmaDefragmentationMove move = {
+ srcOrigBlockIndex, freeSpaceOrigBlockIndex,
+ srcAllocOffset, dstAllocOffset,
+ srcAllocSize };
+ moves.push_back(move);
+ }
+ // Different block
+ else
+ {
+ // MOVE OPTION 2: Move the allocation to a different block.
+
+ VMA_ASSERT(freeSpaceInfoIndex < srcBlockInfoIndex);
+
+ VmaSuballocation suballoc = *srcSuballocIt;
+ suballoc.offset = dstAllocOffset;
+ suballoc.hAllocation->ChangeBlockAllocation(m_hAllocator, pFreeSpaceBlock, dstAllocOffset);
+ m_BytesMoved += srcAllocSize;
+ ++m_AllocationsMoved;
+
+ VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
+ ++nextSuballocIt;
+ pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
+ srcSuballocIt = nextSuballocIt;
+
+ InsertSuballoc(pFreeSpaceMetadata, suballoc);
+
+ VmaDefragmentationMove move = {
+ srcOrigBlockIndex, freeSpaceOrigBlockIndex,
+ srcAllocOffset, dstAllocOffset,
+ srcAllocSize };
+ moves.push_back(move);
+ }
+ }
+ else
+ {
+ dstAllocOffset = VmaAlignUp(dstOffset, srcAllocAlignment);
+
+ // If the allocation doesn't fit before the end of dstBlock, forward to next block.
+ while(dstBlockInfoIndex < srcBlockInfoIndex &&
+ dstAllocOffset + srcAllocSize > dstBlockSize)
+ {
+ // But before that, register remaining free space at the end of dst block.
+ freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, dstBlockSize - dstOffset);
+
+ ++dstBlockInfoIndex;
+ dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex;
+ pDstBlock = m_pBlockVector->GetBlock(dstOrigBlockIndex);
+ pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock->m_pMetadata;
+ dstBlockSize = pDstMetadata->GetSize();
+ dstOffset = 0;
+ dstAllocOffset = 0;
+ }
+
+ // Same block
+ if(dstBlockInfoIndex == srcBlockInfoIndex)
+ {
+ VMA_ASSERT(dstAllocOffset <= srcAllocOffset);
+
+ const bool overlap = dstAllocOffset + srcAllocSize > srcAllocOffset;
+
+ bool skipOver = overlap;
+ if(overlap && m_OverlappingMoveSupported && dstAllocOffset < srcAllocOffset)
+ {
+ // If destination and source place overlap, skip if it would move it
+ // by only < 1/64 of its size.
+ skipOver = (srcAllocOffset - dstAllocOffset) * 64 < srcAllocSize;
+ }
+
+ if(skipOver)
+ {
+ freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, srcAllocOffset - dstOffset);
+
+ dstOffset = srcAllocOffset + srcAllocSize;
+ ++srcSuballocIt;
+ }
+ // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
+ else
+ {
+ srcSuballocIt->offset = dstAllocOffset;
+ srcSuballocIt->hAllocation->ChangeOffset(dstAllocOffset);
+ dstOffset = dstAllocOffset + srcAllocSize;
+ m_BytesMoved += srcAllocSize;
+ ++m_AllocationsMoved;
+ ++srcSuballocIt;
+ VmaDefragmentationMove move = {
+ srcOrigBlockIndex, dstOrigBlockIndex,
+ srcAllocOffset, dstAllocOffset,
+ srcAllocSize };
+ moves.push_back(move);
+ }
+ }
+ // Different block
+ else
+ {
+ // MOVE OPTION 2: Move the allocation to a different block.
+
+ VMA_ASSERT(dstBlockInfoIndex < srcBlockInfoIndex);
+ VMA_ASSERT(dstAllocOffset + srcAllocSize <= dstBlockSize);
+
+ VmaSuballocation suballoc = *srcSuballocIt;
+ suballoc.offset = dstAllocOffset;
+ suballoc.hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlock, dstAllocOffset);
+ dstOffset = dstAllocOffset + srcAllocSize;
+ m_BytesMoved += srcAllocSize;
+ ++m_AllocationsMoved;
+
+ VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
+ ++nextSuballocIt;
+ pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
+ srcSuballocIt = nextSuballocIt;
+
+ pDstMetadata->m_Suballocations.push_back(suballoc);
+
+ VmaDefragmentationMove move = {
+ srcOrigBlockIndex, dstOrigBlockIndex,
+ srcAllocOffset, dstAllocOffset,
+ srcAllocSize };
+ moves.push_back(move);
+ }
+ }
+ }
+ }
+
+ m_BlockInfos.clear();
+
+ PostprocessMetadata();
+
+ return VK_SUCCESS;
+}
+
+void VmaDefragmentationAlgorithm_Fast::PreprocessMetadata()
+{
+ const size_t blockCount = m_pBlockVector->GetBlockCount();
+ for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ VmaBlockMetadata_Generic* const pMetadata =
+ (VmaBlockMetadata_Generic*)m_pBlockVector->GetBlock(blockIndex)->m_pMetadata;
+ pMetadata->m_FreeCount = 0;
+ pMetadata->m_SumFreeSize = pMetadata->GetSize();
+ pMetadata->m_FreeSuballocationsBySize.clear();
+ for(VmaSuballocationList::iterator it = pMetadata->m_Suballocations.begin();
+ it != pMetadata->m_Suballocations.end(); )
+ {
+ if(it->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ VmaSuballocationList::iterator nextIt = it;
+ ++nextIt;
+ pMetadata->m_Suballocations.erase(it);
+ it = nextIt;
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ }
+}
+
+void VmaDefragmentationAlgorithm_Fast::PostprocessMetadata()
+{
+ const size_t blockCount = m_pBlockVector->GetBlockCount();
+ for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ VmaBlockMetadata_Generic* const pMetadata =
+ (VmaBlockMetadata_Generic*)m_pBlockVector->GetBlock(blockIndex)->m_pMetadata;
+ const VkDeviceSize blockSize = pMetadata->GetSize();
+
+ // No allocations in this block - entire area is free.
+ if(pMetadata->m_Suballocations.empty())
+ {
+ pMetadata->m_FreeCount = 1;
+ //pMetadata->m_SumFreeSize is already set to blockSize.
+ VmaSuballocation suballoc = {
+ 0, // offset
+ blockSize, // size
+ VMA_NULL, // hAllocation
+ VMA_SUBALLOCATION_TYPE_FREE };
+ pMetadata->m_Suballocations.push_back(suballoc);
+ pMetadata->RegisterFreeSuballocation(pMetadata->m_Suballocations.begin());
+ }
+ // There are some allocations in this block.
+ else
+ {
+ VkDeviceSize offset = 0;
+ VmaSuballocationList::iterator it;
+ for(it = pMetadata->m_Suballocations.begin();
+ it != pMetadata->m_Suballocations.end();
+ ++it)
+ {
+ VMA_ASSERT(it->type != VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(it->offset >= offset);
+
+ // Need to insert preceding free space.
+ if(it->offset > offset)
+ {
+ ++pMetadata->m_FreeCount;
+ const VkDeviceSize freeSize = it->offset - offset;
+ VmaSuballocation suballoc = {
+ offset, // offset
+ freeSize, // size
+ VMA_NULL, // hAllocation
+ VMA_SUBALLOCATION_TYPE_FREE };
+ VmaSuballocationList::iterator precedingFreeIt = pMetadata->m_Suballocations.insert(it, suballoc);
+ if(freeSize >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ pMetadata->m_FreeSuballocationsBySize.push_back(precedingFreeIt);
+ }
+ }
+
+ pMetadata->m_SumFreeSize -= it->size;
+ offset = it->offset + it->size;
+ }
+
+ // Need to insert trailing free space.
+ if(offset < blockSize)
+ {
+ ++pMetadata->m_FreeCount;
+ const VkDeviceSize freeSize = blockSize - offset;
+ VmaSuballocation suballoc = {
+ offset, // offset
+ freeSize, // size
+ VMA_NULL, // hAllocation
+ VMA_SUBALLOCATION_TYPE_FREE };
+ VMA_ASSERT(it == pMetadata->m_Suballocations.end());
+ VmaSuballocationList::iterator trailingFreeIt = pMetadata->m_Suballocations.insert(it, suballoc);
+ if(freeSize > VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ pMetadata->m_FreeSuballocationsBySize.push_back(trailingFreeIt);
+ }
+ }
+
+ VMA_SORT(
+ pMetadata->m_FreeSuballocationsBySize.begin(),
+ pMetadata->m_FreeSuballocationsBySize.end(),
+ VmaSuballocationItemSizeLess());
+ }
+
+ VMA_HEAVY_ASSERT(pMetadata->Validate());
+ }
+}
+
+void VmaDefragmentationAlgorithm_Fast::InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, const VmaSuballocation& suballoc)
+{
+ // TODO: Optimize somehow. Remember iterator instead of searching for it linearly.
+ VmaSuballocationList::iterator it = pMetadata->m_Suballocations.begin();
+ while(it != pMetadata->m_Suballocations.end())
+ {
+ if(it->offset < suballoc.offset)
+ {
+ ++it;
+ }
+ }
+ pMetadata->m_Suballocations.insert(it, suballoc);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaBlockVectorDefragmentationContext
+
+VmaBlockVectorDefragmentationContext::VmaBlockVectorDefragmentationContext(
+ VmaAllocator hAllocator,
+ VmaPool hCustomPool,
+ VmaBlockVector* pBlockVector,
+ uint32_t currFrameIndex) :
+ res(VK_SUCCESS),
+ mutexLocked(false),
+ blockContexts(VmaStlAllocator<VmaBlockDefragmentationContext>(hAllocator->GetAllocationCallbacks())),
+ m_hAllocator(hAllocator),
+ m_hCustomPool(hCustomPool),
+ m_pBlockVector(pBlockVector),
+ m_CurrFrameIndex(currFrameIndex),
+ m_pAlgorithm(VMA_NULL),
+ m_Allocations(VmaStlAllocator<AllocInfo>(hAllocator->GetAllocationCallbacks())),
+ m_AllAllocations(false)
+{
+}
+
+VmaBlockVectorDefragmentationContext::~VmaBlockVectorDefragmentationContext()
+{
+ vma_delete(m_hAllocator, m_pAlgorithm);
+}
+
+void VmaBlockVectorDefragmentationContext::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged)
+{
+ AllocInfo info = { hAlloc, pChanged };
+ m_Allocations.push_back(info);
+}
+
+void VmaBlockVectorDefragmentationContext::Begin(bool overlappingMoveSupported)
+{
+ const bool allAllocations = m_AllAllocations ||
+ m_Allocations.size() == m_pBlockVector->CalcAllocationCount();
+
+ /********************************
+ HERE IS THE CHOICE OF DEFRAGMENTATION ALGORITHM.
+ ********************************/
+
+ /*
+ Fast algorithm is supported only when certain criteria are met:
+ - VMA_DEBUG_MARGIN is 0.
+ - All allocations in this block vector are moveable.
+ - There is no possibility of image/buffer granularity conflict.
+ */
+ if(VMA_DEBUG_MARGIN == 0 &&
+ allAllocations &&
+ !m_pBlockVector->IsBufferImageGranularityConflictPossible())
+ {
+ m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Fast)(
+ m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);
+ }
+ else
+ {
+ m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Generic)(
+ m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);
+ }
+
+ if(allAllocations)
+ {
+ m_pAlgorithm->AddAll();
+ }
+ else
+ {
+ for(size_t i = 0, count = m_Allocations.size(); i < count; ++i)
+ {
+ m_pAlgorithm->AddAllocation(m_Allocations[i].hAlloc, m_Allocations[i].pChanged);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaDefragmentationContext
+
+VmaDefragmentationContext_T::VmaDefragmentationContext_T(
+ VmaAllocator hAllocator,
+ uint32_t currFrameIndex,
+ uint32_t flags,
+ VmaDefragmentationStats* pStats) :
+ m_hAllocator(hAllocator),
+ m_CurrFrameIndex(currFrameIndex),
+ m_Flags(flags),
+ m_pStats(pStats),
+ m_CustomPoolContexts(VmaStlAllocator<VmaBlockVectorDefragmentationContext*>(hAllocator->GetAllocationCallbacks()))
+{
+ memset(m_DefaultPoolContexts, 0, sizeof(m_DefaultPoolContexts));
+}
+
+VmaDefragmentationContext_T::~VmaDefragmentationContext_T()
+{
+ for(size_t i = m_CustomPoolContexts.size(); i--; )
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[i];
+ pBlockVectorCtx->GetBlockVector()->DefragmentationEnd(pBlockVectorCtx, m_pStats);
+ vma_delete(m_hAllocator, pBlockVectorCtx);
+ }
+ for(size_t i = m_hAllocator->m_MemProps.memoryTypeCount; i--; )
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[i];
+ if(pBlockVectorCtx)
+ {
+ pBlockVectorCtx->GetBlockVector()->DefragmentationEnd(pBlockVectorCtx, m_pStats);
+ vma_delete(m_hAllocator, pBlockVectorCtx);
+ }
+ }
+}
+
+void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, VmaPool* pPools)
+{
+ for(uint32_t poolIndex = 0; poolIndex < poolCount; ++poolIndex)
+ {
+ VmaPool pool = pPools[poolIndex];
+ VMA_ASSERT(pool);
+ // Pools with algorithm other than default are not defragmented.
+ if(pool->m_BlockVector.GetAlgorithm() == 0)
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
+
+ for(size_t i = m_CustomPoolContexts.size(); i--; )
+ {
+ if(m_CustomPoolContexts[i]->GetCustomPool() == pool)
+ {
+ pBlockVectorDefragCtx = m_CustomPoolContexts[i];
+ break;
+ }
+ }
+
+ if(!pBlockVectorDefragCtx)
+ {
+ pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
+ m_hAllocator,
+ pool,
+ &pool->m_BlockVector,
+ m_CurrFrameIndex);
+ m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
+ }
+
+ pBlockVectorDefragCtx->AddAll();
+ }
+ }
+}
+
+void VmaDefragmentationContext_T::AddAllocations(
+ uint32_t allocationCount,
+ VmaAllocation* pAllocations,
+ VkBool32* pAllocationsChanged)
+{
+ // Dispatch pAllocations among defragmentators. Create them when necessary.
+ for(uint32_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+ {
+ const VmaAllocation hAlloc = pAllocations[allocIndex];
+ VMA_ASSERT(hAlloc);
+ // DedicatedAlloc cannot be defragmented.
+ if((hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK) &&
+ // Lost allocation cannot be defragmented.
+ (hAlloc->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST))
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
+
+ const VmaPool hAllocPool = hAlloc->GetBlock()->GetParentPool();
+ // This allocation belongs to custom pool.
+ if(hAllocPool != VK_NULL_HANDLE)
+ {
+ // Pools with algorithm other than default are not defragmented.
+ if(hAllocPool->m_BlockVector.GetAlgorithm() == 0)
+ {
+ for(size_t i = m_CustomPoolContexts.size(); i--; )
+ {
+ if(m_CustomPoolContexts[i]->GetCustomPool() == hAllocPool)
+ {
+ pBlockVectorDefragCtx = m_CustomPoolContexts[i];
+ break;
+ }
+ }
+ if(!pBlockVectorDefragCtx)
+ {
+ pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
+ m_hAllocator,
+ hAllocPool,
+ &hAllocPool->m_BlockVector,
+ m_CurrFrameIndex);
+ m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
+ }
+ }
+ }
+ // This allocation belongs to default pool.
+ else
+ {
+ const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex();
+ pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex];
+ if(!pBlockVectorDefragCtx)
+ {
+ pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
+ m_hAllocator,
+ VMA_NULL, // hCustomPool
+ m_hAllocator->m_pBlockVectors[memTypeIndex],
+ m_CurrFrameIndex);
+ m_DefaultPoolContexts[memTypeIndex] = pBlockVectorDefragCtx;
+ }
+ }
+
+ if(pBlockVectorDefragCtx)
+ {
+ VkBool32* const pChanged = (pAllocationsChanged != VMA_NULL) ?
+ &pAllocationsChanged[allocIndex] : VMA_NULL;
+ pBlockVectorDefragCtx->AddAllocation(hAlloc, pChanged);
+ }
+ }
+ }
+}
+
+VkResult VmaDefragmentationContext_T::Defragment(
+ VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove,
+ VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove,
+ VkCommandBuffer commandBuffer, VmaDefragmentationStats* pStats)
+{
+ if(pStats)
+ {
+ memset(pStats, 0, sizeof(VmaDefragmentationStats));
+ }
+
+ if(commandBuffer == VK_NULL_HANDLE)
+ {
+ maxGpuBytesToMove = 0;
+ maxGpuAllocationsToMove = 0;
+ }
+
+ VkResult res = VK_SUCCESS;
+
+ // Process default pools.
+ for(uint32_t memTypeIndex = 0;
+ memTypeIndex < m_hAllocator->GetMemoryTypeCount() && res >= VK_SUCCESS;
+ ++memTypeIndex)
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];
+ if(pBlockVectorCtx)
+ {
+ VMA_ASSERT(pBlockVectorCtx->GetBlockVector());
+ pBlockVectorCtx->GetBlockVector()->Defragment(
+ pBlockVectorCtx,
+ pStats,
+ maxCpuBytesToMove, maxCpuAllocationsToMove,
+ maxGpuBytesToMove, maxGpuAllocationsToMove,
+ commandBuffer);
+ if(pBlockVectorCtx->res != VK_SUCCESS)
+ {
+ res = pBlockVectorCtx->res;
+ }
+ }
+ }
+
+ // Process custom pools.
+ for(size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();
+ customCtxIndex < customCtxCount && res >= VK_SUCCESS;
+ ++customCtxIndex)
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];
+ VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector());
+ pBlockVectorCtx->GetBlockVector()->Defragment(
+ pBlockVectorCtx,
+ pStats,
+ maxCpuBytesToMove, maxCpuAllocationsToMove,
+ maxGpuBytesToMove, maxGpuAllocationsToMove,
+ commandBuffer);
+ if(pBlockVectorCtx->res != VK_SUCCESS)
+ {
+ res = pBlockVectorCtx->res;
+ }
+ }
+
+ return res;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaRecorder
+
+#if VMA_RECORDING_ENABLED
+
+VmaRecorder::VmaRecorder() :
+ m_UseMutex(true),
+ m_Flags(0),
+ m_File(VMA_NULL),
+ m_Freq(INT64_MAX),
+ m_StartCounter(INT64_MAX)
+{
+}
+
+VkResult VmaRecorder::Init(const VmaRecordSettings& settings, bool useMutex)
+{
+ m_UseMutex = useMutex;
+ m_Flags = settings.flags;
+
+ QueryPerformanceFrequency((LARGE_INTEGER*)&m_Freq);
+ QueryPerformanceCounter((LARGE_INTEGER*)&m_StartCounter);
+
+ // Open file for writing.
+ errno_t err = fopen_s(&m_File, settings.pFilePath, "wb");
+ if(err != 0)
+ {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ // Write header.
+ fprintf(m_File, "%s\n", "Vulkan Memory Allocator,Calls recording");
+ fprintf(m_File, "%s\n", "1,8");
+
+ return VK_SUCCESS;
+}
+
+VmaRecorder::~VmaRecorder()
+{
+ if(m_File != VMA_NULL)
+ {
+ fclose(m_File);
+ }
+}
+
+void VmaRecorder::RecordCreateAllocator(uint32_t frameIndex)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaCreateAllocator\n", callParams.threadId, callParams.time, frameIndex);
+ Flush();
+}
+
+void VmaRecorder::RecordDestroyAllocator(uint32_t frameIndex)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDestroyAllocator\n", callParams.threadId, callParams.time, frameIndex);
+ Flush();
+}
+
+void VmaRecorder::RecordCreatePool(uint32_t frameIndex, const VmaPoolCreateInfo& createInfo, VmaPool pool)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaCreatePool,%u,%u,%llu,%llu,%llu,%u,%p\n", callParams.threadId, callParams.time, frameIndex,
+ createInfo.memoryTypeIndex,
+ createInfo.flags,
+ createInfo.blockSize,
+ (uint64_t)createInfo.minBlockCount,
+ (uint64_t)createInfo.maxBlockCount,
+ createInfo.frameInUseCount,
+ pool);
+ Flush();
+}
+
+void VmaRecorder::RecordDestroyPool(uint32_t frameIndex, VmaPool pool)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDestroyPool,%p\n", callParams.threadId, callParams.time, frameIndex,
+ pool);
+ Flush();
+}
+
+void VmaRecorder::RecordAllocateMemory(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemory,%llu,%llu,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ vkMemReq.size,
+ vkMemReq.alignment,
+ vkMemReq.memoryTypeBits,
+ createInfo.flags,
+ createInfo.usage,
+ createInfo.requiredFlags,
+ createInfo.preferredFlags,
+ createInfo.memoryTypeBits,
+ createInfo.pool,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordAllocateMemoryPages(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ const VmaAllocationCreateInfo& createInfo,
+ uint64_t allocationCount,
+ const VmaAllocation* pAllocations)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryPages,%llu,%llu,%u,%u,%u,%u,%u,%u,%p,", callParams.threadId, callParams.time, frameIndex,
+ vkMemReq.size,
+ vkMemReq.alignment,
+ vkMemReq.memoryTypeBits,
+ createInfo.flags,
+ createInfo.usage,
+ createInfo.requiredFlags,
+ createInfo.preferredFlags,
+ createInfo.memoryTypeBits,
+ createInfo.pool);
+ PrintPointerList(allocationCount, pAllocations);
+ fprintf(m_File, ",%s\n", userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordAllocateMemoryForBuffer(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryForBuffer,%llu,%llu,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ vkMemReq.size,
+ vkMemReq.alignment,
+ vkMemReq.memoryTypeBits,
+ requiresDedicatedAllocation ? 1 : 0,
+ prefersDedicatedAllocation ? 1 : 0,
+ createInfo.flags,
+ createInfo.usage,
+ createInfo.requiredFlags,
+ createInfo.preferredFlags,
+ createInfo.memoryTypeBits,
+ createInfo.pool,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordAllocateMemoryForImage(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryForImage,%llu,%llu,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ vkMemReq.size,
+ vkMemReq.alignment,
+ vkMemReq.memoryTypeBits,
+ requiresDedicatedAllocation ? 1 : 0,
+ prefersDedicatedAllocation ? 1 : 0,
+ createInfo.flags,
+ createInfo.usage,
+ createInfo.requiredFlags,
+ createInfo.preferredFlags,
+ createInfo.memoryTypeBits,
+ createInfo.pool,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordFreeMemory(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaFreeMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordFreeMemoryPages(uint32_t frameIndex,
+ uint64_t allocationCount,
+ const VmaAllocation* pAllocations)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaFreeMemoryPages,", callParams.threadId, callParams.time, frameIndex);
+ PrintPointerList(allocationCount, pAllocations);
+ fprintf(m_File, "\n");
+ Flush();
+}
+
+void VmaRecorder::RecordSetAllocationUserData(uint32_t frameIndex,
+ VmaAllocation allocation,
+ const void* pUserData)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(
+ allocation->IsUserDataString() ? VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT : 0,
+ pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaSetAllocationUserData,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordCreateLostAllocation(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaCreateLostAllocation,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordMapMemory(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaMapMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordUnmapMemory(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaUnmapMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordFlushAllocation(uint32_t frameIndex,
+ VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaFlushAllocation,%p,%llu,%llu\n", callParams.threadId, callParams.time, frameIndex,
+ allocation,
+ offset,
+ size);
+ Flush();
+}
+
+void VmaRecorder::RecordInvalidateAllocation(uint32_t frameIndex,
+ VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaInvalidateAllocation,%p,%llu,%llu\n", callParams.threadId, callParams.time, frameIndex,
+ allocation,
+ offset,
+ size);
+ Flush();
+}
+
+void VmaRecorder::RecordCreateBuffer(uint32_t frameIndex,
+ const VkBufferCreateInfo& bufCreateInfo,
+ const VmaAllocationCreateInfo& allocCreateInfo,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(allocCreateInfo.flags, allocCreateInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaCreateBuffer,%u,%llu,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ bufCreateInfo.flags,
+ bufCreateInfo.size,
+ bufCreateInfo.usage,
+ bufCreateInfo.sharingMode,
+ allocCreateInfo.flags,
+ allocCreateInfo.usage,
+ allocCreateInfo.requiredFlags,
+ allocCreateInfo.preferredFlags,
+ allocCreateInfo.memoryTypeBits,
+ allocCreateInfo.pool,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordCreateImage(uint32_t frameIndex,
+ const VkImageCreateInfo& imageCreateInfo,
+ const VmaAllocationCreateInfo& allocCreateInfo,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(allocCreateInfo.flags, allocCreateInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaCreateImage,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ imageCreateInfo.flags,
+ imageCreateInfo.imageType,
+ imageCreateInfo.format,
+ imageCreateInfo.extent.width,
+ imageCreateInfo.extent.height,
+ imageCreateInfo.extent.depth,
+ imageCreateInfo.mipLevels,
+ imageCreateInfo.arrayLayers,
+ imageCreateInfo.samples,
+ imageCreateInfo.tiling,
+ imageCreateInfo.usage,
+ imageCreateInfo.sharingMode,
+ imageCreateInfo.initialLayout,
+ allocCreateInfo.flags,
+ allocCreateInfo.usage,
+ allocCreateInfo.requiredFlags,
+ allocCreateInfo.preferredFlags,
+ allocCreateInfo.memoryTypeBits,
+ allocCreateInfo.pool,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordDestroyBuffer(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDestroyBuffer,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordDestroyImage(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDestroyImage,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordTouchAllocation(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaTouchAllocation,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordGetAllocationInfo(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaGetAllocationInfo,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordMakePoolAllocationsLost(uint32_t frameIndex,
+ VmaPool pool)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaMakePoolAllocationsLost,%p\n", callParams.threadId, callParams.time, frameIndex,
+ pool);
+ Flush();
+}
+
+void VmaRecorder::RecordDefragmentationBegin(uint32_t frameIndex,
+ const VmaDefragmentationInfo2& info,
+ VmaDefragmentationContext ctx)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDefragmentationBegin,%u,", callParams.threadId, callParams.time, frameIndex,
+ info.flags);
+ PrintPointerList(info.allocationCount, info.pAllocations);
+ fprintf(m_File, ",");
+ PrintPointerList(info.poolCount, info.pPools);
+ fprintf(m_File, ",%llu,%u,%llu,%u,%p,%p\n",
+ info.maxCpuBytesToMove,
+ info.maxCpuAllocationsToMove,
+ info.maxGpuBytesToMove,
+ info.maxGpuAllocationsToMove,
+ info.commandBuffer,
+ ctx);
+ Flush();
+}
+
+void VmaRecorder::RecordDefragmentationEnd(uint32_t frameIndex,
+ VmaDefragmentationContext ctx)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDefragmentationEnd,%p\n", callParams.threadId, callParams.time, frameIndex,
+ ctx);
+ Flush();
+}
+
+void VmaRecorder::RecordSetPoolName(uint32_t frameIndex,
+ VmaPool pool,
+ const char* name)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaSetPoolName,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ pool, name != VMA_NULL ? name : "");
+ Flush();
+}
+
+VmaRecorder::UserDataString::UserDataString(VmaAllocationCreateFlags allocFlags, const void* pUserData)
+{
+ if(pUserData != VMA_NULL)
+ {
+ if((allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0)
+ {
+ m_Str = (const char*)pUserData;
+ }
+ else
+ {
+ sprintf_s(m_PtrStr, "%p", pUserData);
+ m_Str = m_PtrStr;
+ }
+ }
+ else
+ {
+ m_Str = "";
+ }
+}
+
+void VmaRecorder::WriteConfiguration(
+ const VkPhysicalDeviceProperties& devProps,
+ const VkPhysicalDeviceMemoryProperties& memProps,
+ uint32_t vulkanApiVersion,
+ bool dedicatedAllocationExtensionEnabled,
+ bool bindMemory2ExtensionEnabled,
+ bool memoryBudgetExtensionEnabled)
+{
+ fprintf(m_File, "Config,Begin\n");
+
+ fprintf(m_File, "VulkanApiVersion,%u,%u\n", VK_VERSION_MAJOR(vulkanApiVersion), VK_VERSION_MINOR(vulkanApiVersion));
+
+ fprintf(m_File, "PhysicalDevice,apiVersion,%u\n", devProps.apiVersion);
+ fprintf(m_File, "PhysicalDevice,driverVersion,%u\n", devProps.driverVersion);
+ fprintf(m_File, "PhysicalDevice,vendorID,%u\n", devProps.vendorID);
+ fprintf(m_File, "PhysicalDevice,deviceID,%u\n", devProps.deviceID);
+ fprintf(m_File, "PhysicalDevice,deviceType,%u\n", devProps.deviceType);
+ fprintf(m_File, "PhysicalDevice,deviceName,%s\n", devProps.deviceName);
+
+ fprintf(m_File, "PhysicalDeviceLimits,maxMemoryAllocationCount,%u\n", devProps.limits.maxMemoryAllocationCount);
+ fprintf(m_File, "PhysicalDeviceLimits,bufferImageGranularity,%llu\n", devProps.limits.bufferImageGranularity);
+ fprintf(m_File, "PhysicalDeviceLimits,nonCoherentAtomSize,%llu\n", devProps.limits.nonCoherentAtomSize);
+
+ fprintf(m_File, "PhysicalDeviceMemory,HeapCount,%u\n", memProps.memoryHeapCount);
+ for(uint32_t i = 0; i < memProps.memoryHeapCount; ++i)
+ {
+ fprintf(m_File, "PhysicalDeviceMemory,Heap,%u,size,%llu\n", i, memProps.memoryHeaps[i].size);
+ fprintf(m_File, "PhysicalDeviceMemory,Heap,%u,flags,%u\n", i, memProps.memoryHeaps[i].flags);
+ }
+ fprintf(m_File, "PhysicalDeviceMemory,TypeCount,%u\n", memProps.memoryTypeCount);
+ for(uint32_t i = 0; i < memProps.memoryTypeCount; ++i)
+ {
+ fprintf(m_File, "PhysicalDeviceMemory,Type,%u,heapIndex,%u\n", i, memProps.memoryTypes[i].heapIndex);
+ fprintf(m_File, "PhysicalDeviceMemory,Type,%u,propertyFlags,%u\n", i, memProps.memoryTypes[i].propertyFlags);
+ }
+
+ fprintf(m_File, "Extension,VK_KHR_dedicated_allocation,%u\n", dedicatedAllocationExtensionEnabled ? 1 : 0);
+ fprintf(m_File, "Extension,VK_KHR_bind_memory2,%u\n", bindMemory2ExtensionEnabled ? 1 : 0);
+ fprintf(m_File, "Extension,VK_EXT_memory_budget,%u\n", memoryBudgetExtensionEnabled ? 1 : 0);
+
+ fprintf(m_File, "Macro,VMA_DEBUG_ALWAYS_DEDICATED_MEMORY,%u\n", VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ? 1 : 0);
+ fprintf(m_File, "Macro,VMA_DEBUG_ALIGNMENT,%llu\n", (VkDeviceSize)VMA_DEBUG_ALIGNMENT);
+ fprintf(m_File, "Macro,VMA_DEBUG_MARGIN,%llu\n", (VkDeviceSize)VMA_DEBUG_MARGIN);
+ fprintf(m_File, "Macro,VMA_DEBUG_INITIALIZE_ALLOCATIONS,%u\n", VMA_DEBUG_INITIALIZE_ALLOCATIONS ? 1 : 0);
+ fprintf(m_File, "Macro,VMA_DEBUG_DETECT_CORRUPTION,%u\n", VMA_DEBUG_DETECT_CORRUPTION ? 1 : 0);
+ fprintf(m_File, "Macro,VMA_DEBUG_GLOBAL_MUTEX,%u\n", VMA_DEBUG_GLOBAL_MUTEX ? 1 : 0);
+ fprintf(m_File, "Macro,VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY,%llu\n", (VkDeviceSize)VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY);
+ fprintf(m_File, "Macro,VMA_SMALL_HEAP_MAX_SIZE,%llu\n", (VkDeviceSize)VMA_SMALL_HEAP_MAX_SIZE);
+ fprintf(m_File, "Macro,VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE,%llu\n", (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);
+
+ fprintf(m_File, "Config,End\n");
+}
+
+void VmaRecorder::GetBasicParams(CallParams& outParams)
+{
+ outParams.threadId = GetCurrentThreadId();
+
+ LARGE_INTEGER counter;
+ QueryPerformanceCounter(&counter);
+ outParams.time = (double)(counter.QuadPart - m_StartCounter) / (double)m_Freq;
+}
+
+void VmaRecorder::PrintPointerList(uint64_t count, const VmaAllocation* pItems)
+{
+ if(count)
+ {
+ fprintf(m_File, "%p", pItems[0]);
+ for(uint64_t i = 1; i < count; ++i)
+ {
+ fprintf(m_File, " %p", pItems[i]);
+ }
+ }
+}
+
+void VmaRecorder::Flush()
+{
+ if((m_Flags & VMA_RECORD_FLUSH_AFTER_CALL_BIT) != 0)
+ {
+ fflush(m_File);
+ }
+}
+
+#endif // #if VMA_RECORDING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaAllocationObjectAllocator
+
+VmaAllocationObjectAllocator::VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks) :
+ m_Allocator(pAllocationCallbacks, 1024)
+{
+}
+
+VmaAllocation VmaAllocationObjectAllocator::Allocate()
+{
+ VmaMutexLock mutexLock(m_Mutex);
+ return m_Allocator.Alloc();
+}
+
+void VmaAllocationObjectAllocator::Free(VmaAllocation hAlloc)
+{
+ VmaMutexLock mutexLock(m_Mutex);
+ m_Allocator.Free(hAlloc);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaAllocator_T
+
+VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
+ m_UseMutex((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) == 0),
+ m_VulkanApiVersion(pCreateInfo->vulkanApiVersion != 0 ? pCreateInfo->vulkanApiVersion : VK_API_VERSION_1_0),
+ m_UseKhrDedicatedAllocation((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0),
+ m_UseKhrBindMemory2((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0),
+ m_UseExtMemoryBudget((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0),
+ m_hDevice(pCreateInfo->device),
+ m_hInstance(pCreateInfo->instance),
+ m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL),
+ m_AllocationCallbacks(pCreateInfo->pAllocationCallbacks ?
+ *pCreateInfo->pAllocationCallbacks : VmaEmptyAllocationCallbacks),
+ m_AllocationObjectAllocator(&m_AllocationCallbacks),
+ m_HeapSizeLimitMask(0),
+ m_PreferredLargeHeapBlockSize(0),
+ m_PhysicalDevice(pCreateInfo->physicalDevice),
+ m_CurrentFrameIndex(0),
+ m_GpuDefragmentationMemoryTypeBits(UINT32_MAX),
+ m_Pools(VmaStlAllocator<VmaPool>(GetAllocationCallbacks())),
+ m_NextPoolId(0)
+#if VMA_RECORDING_ENABLED
+ ,m_pRecorder(VMA_NULL)
+#endif
+{
+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+ {
+ m_UseKhrDedicatedAllocation = false;
+ m_UseKhrBindMemory2 = false;
+ }
+
+ if(VMA_DEBUG_DETECT_CORRUPTION)
+ {
+ // Needs to be multiply of uint32_t size because we are going to write VMA_CORRUPTION_DETECTION_MAGIC_VALUE to it.
+ VMA_ASSERT(VMA_DEBUG_MARGIN % sizeof(uint32_t) == 0);
+ }
+
+ VMA_ASSERT(pCreateInfo->physicalDevice && pCreateInfo->device);
+
+ if(m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0))
+ {
+#if !(VMA_DEDICATED_ALLOCATION)
+ if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT set but required extensions are disabled by preprocessor macros.");
+ }
+#endif
+#if !(VMA_BIND_MEMORY2)
+ if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT set but required extension is disabled by preprocessor macros.");
+ }
+#endif
+ }
+#if !(VMA_MEMORY_BUDGET)
+ if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros.");
+ }
+#endif
+#if VMA_VULKAN_VERSION < 1001000
+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+ {
+ VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_1 but required Vulkan version is disabled by preprocessor macros.");
+ }
+#endif
+
+ memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks));
+ memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties));
+ memset(&m_MemProps, 0, sizeof(m_MemProps));
+
+ memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors));
+ memset(&m_pDedicatedAllocations, 0, sizeof(m_pDedicatedAllocations));
+ memset(&m_VulkanFunctions, 0, sizeof(m_VulkanFunctions));
+
+ if(pCreateInfo->pDeviceMemoryCallbacks != VMA_NULL)
+ {
+ m_DeviceMemoryCallbacks.pfnAllocate = pCreateInfo->pDeviceMemoryCallbacks->pfnAllocate;
+ m_DeviceMemoryCallbacks.pfnFree = pCreateInfo->pDeviceMemoryCallbacks->pfnFree;
+ }
+
+ ImportVulkanFunctions(pCreateInfo->pVulkanFunctions);
+
+ (*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties);
+ (*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps);
+
+ VMA_ASSERT(VmaIsPow2(VMA_DEBUG_ALIGNMENT));
+ VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY));
+ VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.bufferImageGranularity));
+ VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.nonCoherentAtomSize));
+
+ m_PreferredLargeHeapBlockSize = (pCreateInfo->preferredLargeHeapBlockSize != 0) ?
+ pCreateInfo->preferredLargeHeapBlockSize : static_cast<VkDeviceSize>(VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);
+
+ if(pCreateInfo->pHeapSizeLimit != VMA_NULL)
+ {
+ for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex)
+ {
+ const VkDeviceSize limit = pCreateInfo->pHeapSizeLimit[heapIndex];
+ if(limit != VK_WHOLE_SIZE)
+ {
+ m_HeapSizeLimitMask |= 1u << heapIndex;
+ if(limit < m_MemProps.memoryHeaps[heapIndex].size)
+ {
+ m_MemProps.memoryHeaps[heapIndex].size = limit;
+ }
+ }
+ }
+ }
+
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex);
+
+ m_pBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)(
+ this,
+ VK_NULL_HANDLE, // hParentPool
+ memTypeIndex,
+ preferredBlockSize,
+ 0,
+ SIZE_MAX,
+ GetBufferImageGranularity(),
+ pCreateInfo->frameInUseCount,
+ false, // explicitBlockSize
+ false); // linearAlgorithm
+ // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here,
+ // becase minBlockCount is 0.
+ m_pDedicatedAllocations[memTypeIndex] = vma_new(this, AllocationVectorType)(VmaStlAllocator<VmaAllocation>(GetAllocationCallbacks()));
+
+ }
+}
+
+VkResult VmaAllocator_T::Init(const VmaAllocatorCreateInfo* pCreateInfo)
+{
+ VkResult res = VK_SUCCESS;
+
+ if(pCreateInfo->pRecordSettings != VMA_NULL &&
+ !VmaStrIsEmpty(pCreateInfo->pRecordSettings->pFilePath))
+ {
+#if VMA_RECORDING_ENABLED
+ m_pRecorder = vma_new(this, VmaRecorder)();
+ res = m_pRecorder->Init(*pCreateInfo->pRecordSettings, m_UseMutex);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+ m_pRecorder->WriteConfiguration(
+ m_PhysicalDeviceProperties,
+ m_MemProps,
+ m_VulkanApiVersion,
+ m_UseKhrDedicatedAllocation,
+ m_UseKhrBindMemory2,
+ m_UseExtMemoryBudget);
+ m_pRecorder->RecordCreateAllocator(GetCurrentFrameIndex());
+#else
+ VMA_ASSERT(0 && "VmaAllocatorCreateInfo::pRecordSettings used, but not supported due to VMA_RECORDING_ENABLED not defined to 1.");
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+#endif
+ }
+
+#if VMA_MEMORY_BUDGET
+ if(m_UseExtMemoryBudget)
+ {
+ UpdateVulkanBudget();
+ }
+#endif // #if VMA_MEMORY_BUDGET
+
+ return res;
+}
+
+VmaAllocator_T::~VmaAllocator_T()
+{
+#if VMA_RECORDING_ENABLED
+ if(m_pRecorder != VMA_NULL)
+ {
+ m_pRecorder->RecordDestroyAllocator(GetCurrentFrameIndex());
+ vma_delete(this, m_pRecorder);
+ }
+#endif
+
+ VMA_ASSERT(m_Pools.empty());
+
+ for(size_t i = GetMemoryTypeCount(); i--; )
+ {
+ if(m_pDedicatedAllocations[i] != VMA_NULL && !m_pDedicatedAllocations[i]->empty())
+ {
+ VMA_ASSERT(0 && "Unfreed dedicated allocations found.");
+ }
+
+ vma_delete(this, m_pDedicatedAllocations[i]);
+ vma_delete(this, m_pBlockVectors[i]);
+ }
+}
+
+void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions)
+{
+#if VMA_STATIC_VULKAN_FUNCTIONS == 1
+ m_VulkanFunctions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetPhysicalDeviceProperties;
+ m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)vkGetPhysicalDeviceMemoryProperties;
+ m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory;
+ m_VulkanFunctions.vkFreeMemory = (PFN_vkFreeMemory)vkFreeMemory;
+ m_VulkanFunctions.vkMapMemory = (PFN_vkMapMemory)vkMapMemory;
+ m_VulkanFunctions.vkUnmapMemory = (PFN_vkUnmapMemory)vkUnmapMemory;
+ m_VulkanFunctions.vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)vkFlushMappedMemoryRanges;
+ m_VulkanFunctions.vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)vkInvalidateMappedMemoryRanges;
+ m_VulkanFunctions.vkBindBufferMemory = (PFN_vkBindBufferMemory)vkBindBufferMemory;
+ m_VulkanFunctions.vkBindImageMemory = (PFN_vkBindImageMemory)vkBindImageMemory;
+ m_VulkanFunctions.vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)vkGetBufferMemoryRequirements;
+ m_VulkanFunctions.vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)vkGetImageMemoryRequirements;
+ m_VulkanFunctions.vkCreateBuffer = (PFN_vkCreateBuffer)vkCreateBuffer;
+ m_VulkanFunctions.vkDestroyBuffer = (PFN_vkDestroyBuffer)vkDestroyBuffer;
+ m_VulkanFunctions.vkCreateImage = (PFN_vkCreateImage)vkCreateImage;
+ m_VulkanFunctions.vkDestroyImage = (PFN_vkDestroyImage)vkDestroyImage;
+ m_VulkanFunctions.vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)vkCmdCopyBuffer;
+#if VMA_VULKAN_VERSION >= 1001000
+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+ {
+ VMA_ASSERT(m_hInstance != VK_NULL_HANDLE);
+ m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR =
+ (PFN_vkGetBufferMemoryRequirements2KHR)vkGetDeviceProcAddr(m_hDevice, "vkGetBufferMemoryRequirements2");
+ m_VulkanFunctions.vkGetImageMemoryRequirements2KHR =
+ (PFN_vkGetImageMemoryRequirements2KHR)vkGetDeviceProcAddr(m_hDevice, "vkGetImageMemoryRequirements2");
+ m_VulkanFunctions.vkBindBufferMemory2KHR =
+ (PFN_vkBindBufferMemory2KHR)vkGetDeviceProcAddr(m_hDevice, "vkBindBufferMemory2");
+ m_VulkanFunctions.vkBindImageMemory2KHR =
+ (PFN_vkBindImageMemory2KHR)vkGetDeviceProcAddr(m_hDevice, "vkBindImageMemory2");
+ m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR =
+ (PFN_vkGetPhysicalDeviceMemoryProperties2KHR)vkGetInstanceProcAddr(m_hInstance, "vkGetPhysicalDeviceMemoryProperties2");
+ }
+#endif
+#if VMA_DEDICATED_ALLOCATION
+ if(m_UseKhrDedicatedAllocation)
+ {
+ m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR =
+ (PFN_vkGetBufferMemoryRequirements2KHR)vkGetDeviceProcAddr(m_hDevice, "vkGetBufferMemoryRequirements2KHR");
+ m_VulkanFunctions.vkGetImageMemoryRequirements2KHR =
+ (PFN_vkGetImageMemoryRequirements2KHR)vkGetDeviceProcAddr(m_hDevice, "vkGetImageMemoryRequirements2KHR");
+ }
+#endif
+#if VMA_BIND_MEMORY2
+ if(m_UseKhrBindMemory2)
+ {
+ m_VulkanFunctions.vkBindBufferMemory2KHR =
+ (PFN_vkBindBufferMemory2KHR)vkGetDeviceProcAddr(m_hDevice, "vkBindBufferMemory2KHR");
+ m_VulkanFunctions.vkBindImageMemory2KHR =
+ (PFN_vkBindImageMemory2KHR)vkGetDeviceProcAddr(m_hDevice, "vkBindImageMemory2KHR");
+ }
+#endif // #if VMA_BIND_MEMORY2
+#if VMA_MEMORY_BUDGET
+ if(m_UseExtMemoryBudget && m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0))
+ {
+ VMA_ASSERT(m_hInstance != VK_NULL_HANDLE);
+ m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR =
+ (PFN_vkGetPhysicalDeviceMemoryProperties2KHR)vkGetInstanceProcAddr(m_hInstance, "vkGetPhysicalDeviceMemoryProperties2KHR");
+ }
+#endif // #if VMA_MEMORY_BUDGET
+#endif // #if VMA_STATIC_VULKAN_FUNCTIONS == 1
+
+#define VMA_COPY_IF_NOT_NULL(funcName) \
+ if(pVulkanFunctions->funcName != VMA_NULL) m_VulkanFunctions.funcName = pVulkanFunctions->funcName;
+
+ if(pVulkanFunctions != VMA_NULL)
+ {
+ VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties);
+ VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties);
+ VMA_COPY_IF_NOT_NULL(vkAllocateMemory);
+ VMA_COPY_IF_NOT_NULL(vkFreeMemory);
+ VMA_COPY_IF_NOT_NULL(vkMapMemory);
+ VMA_COPY_IF_NOT_NULL(vkUnmapMemory);
+ VMA_COPY_IF_NOT_NULL(vkFlushMappedMemoryRanges);
+ VMA_COPY_IF_NOT_NULL(vkInvalidateMappedMemoryRanges);
+ VMA_COPY_IF_NOT_NULL(vkBindBufferMemory);
+ VMA_COPY_IF_NOT_NULL(vkBindImageMemory);
+ VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements);
+ VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements);
+ VMA_COPY_IF_NOT_NULL(vkCreateBuffer);
+ VMA_COPY_IF_NOT_NULL(vkDestroyBuffer);
+ VMA_COPY_IF_NOT_NULL(vkCreateImage);
+ VMA_COPY_IF_NOT_NULL(vkDestroyImage);
+ VMA_COPY_IF_NOT_NULL(vkCmdCopyBuffer);
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+ VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements2KHR);
+ VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements2KHR);
+#endif
+#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
+ VMA_COPY_IF_NOT_NULL(vkBindBufferMemory2KHR);
+ VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR);
+#endif
+#if VMA_MEMORY_BUDGET
+ VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR);
+#endif
+ }
+
+#undef VMA_COPY_IF_NOT_NULL
+
+ // If these asserts are hit, you must either #define VMA_STATIC_VULKAN_FUNCTIONS 1
+ // or pass valid pointers as VmaAllocatorCreateInfo::pVulkanFunctions.
+ VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceProperties != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkAllocateMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkFreeMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkMapMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkUnmapMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkFlushMappedMemoryRanges != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkInvalidateMappedMemoryRanges != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkCreateBuffer != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkDestroyBuffer != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkCreateImage != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkDestroyImage != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkCmdCopyBuffer != VMA_NULL);
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrDedicatedAllocation)
+ {
+ VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements2KHR != VMA_NULL);
+ }
+#endif
+#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrBindMemory2)
+ {
+ VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL);
+ }
+#endif
+#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000
+ if(m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+ {
+ VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);
+ }
+#endif
+}
+
+VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)
+{
+ const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
+ const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;
+ const bool isSmallHeap = heapSize <= VMA_SMALL_HEAP_MAX_SIZE;
+ return VmaAlignUp(isSmallHeap ? (heapSize / 8) : m_PreferredLargeHeapBlockSize, (VkDeviceSize)32);
+}
+
+VkResult VmaAllocator_T::AllocateMemoryOfType(
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ bool dedicatedAllocation,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ const VmaAllocationCreateInfo& createInfo,
+ uint32_t memTypeIndex,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ VMA_ASSERT(pAllocations != VMA_NULL);
+ VMA_DEBUG_LOG(" AllocateMemory: MemoryTypeIndex=%u, AllocationCount=%zu, Size=%llu", memTypeIndex, allocationCount, size);
+
+ VmaAllocationCreateInfo finalCreateInfo = createInfo;
+
+ // If memory type is not HOST_VISIBLE, disable MAPPED.
+ if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
+ (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ {
+ finalCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT;
+ }
+ // If memory is lazily allocated, it should be always dedicated.
+ if(finalCreateInfo.usage == VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED)
+ {
+ finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+ }
+
+ VmaBlockVector* const blockVector = m_pBlockVectors[memTypeIndex];
+ VMA_ASSERT(blockVector);
+
+ const VkDeviceSize preferredBlockSize = blockVector->GetPreferredBlockSize();
+ bool preferDedicatedMemory =
+ VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ||
+ dedicatedAllocation ||
+ // Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size.
+ size > preferredBlockSize / 2;
+
+ if(preferDedicatedMemory &&
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 &&
+ finalCreateInfo.pool == VK_NULL_HANDLE)
+ {
+ finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+ }
+
+ if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)
+ {
+ if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ {
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ else
+ {
+ return AllocateDedicatedMemory(
+ size,
+ suballocType,
+ memTypeIndex,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
+ finalCreateInfo.pUserData,
+ dedicatedBuffer,
+ dedicatedImage,
+ allocationCount,
+ pAllocations);
+ }
+ }
+ else
+ {
+ VkResult res = blockVector->Allocate(
+ m_CurrentFrameIndex.load(),
+ size,
+ alignment,
+ finalCreateInfo,
+ suballocType,
+ allocationCount,
+ pAllocations);
+ if(res == VK_SUCCESS)
+ {
+ return res;
+ }
+
+ // 5. Try dedicated memory.
+ if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ {
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ else
+ {
+ res = AllocateDedicatedMemory(
+ size,
+ suballocType,
+ memTypeIndex,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
+ finalCreateInfo.pUserData,
+ dedicatedBuffer,
+ dedicatedImage,
+ allocationCount,
+ pAllocations);
+ if(res == VK_SUCCESS)
+ {
+ // Succeeded: AllocateDedicatedMemory function already filld pMemory, nothing more to do here.
+ VMA_DEBUG_LOG(" Allocated as DedicatedMemory");
+ return VK_SUCCESS;
+ }
+ else
+ {
+ // Everything failed: Return error code.
+ VMA_DEBUG_LOG(" vkAllocateMemory FAILED");
+ return res;
+ }
+ }
+ }
+}
+
+VkResult VmaAllocator_T::AllocateDedicatedMemory(
+ VkDeviceSize size,
+ VmaSuballocationType suballocType,
+ uint32_t memTypeIndex,
+ bool withinBudget,
+ bool map,
+ bool isUserDataString,
+ void* pUserData,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ VMA_ASSERT(allocationCount > 0 && pAllocations);
+
+ if(withinBudget)
+ {
+ const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
+ VmaBudget heapBudget = {};
+ GetBudget(&heapBudget, heapIndex, 1);
+ if(heapBudget.usage + size * allocationCount > heapBudget.budget)
+ {
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ }
+
+ VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
+ allocInfo.memoryTypeIndex = memTypeIndex;
+ allocInfo.allocationSize = size;
+
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+ VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR };
+ if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+ {
+ if(dedicatedBuffer != VK_NULL_HANDLE)
+ {
+ VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE);
+ dedicatedAllocInfo.buffer = dedicatedBuffer;
+ allocInfo.pNext = &dedicatedAllocInfo;
+ }
+ else if(dedicatedImage != VK_NULL_HANDLE)
+ {
+ dedicatedAllocInfo.image = dedicatedImage;
+ allocInfo.pNext = &dedicatedAllocInfo;
+ }
+ }
+#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+
+ size_t allocIndex;
+ VkResult res = VK_SUCCESS;
+ for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+ {
+ res = AllocateDedicatedMemoryPage(
+ size,
+ suballocType,
+ memTypeIndex,
+ allocInfo,
+ map,
+ isUserDataString,
+ pUserData,
+ pAllocations + allocIndex);
+ if(res != VK_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ if(res == VK_SUCCESS)
+ {
+ // Register them in m_pDedicatedAllocations.
+ {
+ VmaMutexLockWrite lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+ AllocationVectorType* pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex];
+ VMA_ASSERT(pDedicatedAllocations);
+ for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+ {
+ VmaVectorInsertSorted<VmaPointerLess>(*pDedicatedAllocations, pAllocations[allocIndex]);
+ }
+ }
+
+ VMA_DEBUG_LOG(" Allocated DedicatedMemory Count=%zu, MemoryTypeIndex=#%u", allocationCount, memTypeIndex);
+ }
+ else
+ {
+ // Free all already created allocations.
+ while(allocIndex--)
+ {
+ VmaAllocation currAlloc = pAllocations[allocIndex];
+ VkDeviceMemory hMemory = currAlloc->GetMemory();
+
+ /*
+ There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory
+ before vkFreeMemory.
+
+ if(currAlloc->GetMappedData() != VMA_NULL)
+ {
+ (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory);
+ }
+ */
+
+ FreeVulkanMemory(memTypeIndex, currAlloc->GetSize(), hMemory);
+ m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), currAlloc->GetSize());
+ currAlloc->SetUserData(this, VMA_NULL);
+ currAlloc->Dtor();
+ m_AllocationObjectAllocator.Free(currAlloc);
+ }
+
+ memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+ }
+
+ return res;
+}
+
+VkResult VmaAllocator_T::AllocateDedicatedMemoryPage(
+ VkDeviceSize size,
+ VmaSuballocationType suballocType,
+ uint32_t memTypeIndex,
+ const VkMemoryAllocateInfo& allocInfo,
+ bool map,
+ bool isUserDataString,
+ void* pUserData,
+ VmaAllocation* pAllocation)
+{
+ VkDeviceMemory hMemory = VK_NULL_HANDLE;
+ VkResult res = AllocateVulkanMemory(&allocInfo, &hMemory);
+ if(res < 0)
+ {
+ VMA_DEBUG_LOG(" vkAllocateMemory FAILED");
+ return res;
+ }
+
+ void* pMappedData = VMA_NULL;
+ if(map)
+ {
+ res = (*m_VulkanFunctions.vkMapMemory)(
+ m_hDevice,
+ hMemory,
+ 0,
+ VK_WHOLE_SIZE,
+ 0,
+ &pMappedData);
+ if(res < 0)
+ {
+ VMA_DEBUG_LOG(" vkMapMemory FAILED");
+ FreeVulkanMemory(memTypeIndex, size, hMemory);
+ return res;
+ }
+ }
+
+ *pAllocation = m_AllocationObjectAllocator.Allocate();
+ (*pAllocation)->Ctor(m_CurrentFrameIndex.load(), isUserDataString);
+ (*pAllocation)->InitDedicatedAllocation(memTypeIndex, hMemory, suballocType, pMappedData, size);
+ (*pAllocation)->SetUserData(this, pUserData);
+ m_Budget.AddAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), size);
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+ {
+ FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaAllocator_T::GetBufferMemoryRequirements(
+ VkBuffer hBuffer,
+ VkMemoryRequirements& memReq,
+ bool& requiresDedicatedAllocation,
+ bool& prefersDedicatedAllocation) const
+{
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+ if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+ {
+ VkBufferMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR };
+ memReqInfo.buffer = hBuffer;
+
+ VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };
+
+ VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
+ memReq2.pNext = &memDedicatedReq;
+
+ (*m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2);
+
+ memReq = memReq2.memoryRequirements;
+ requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE);
+ prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE);
+ }
+ else
+#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+ {
+ (*m_VulkanFunctions.vkGetBufferMemoryRequirements)(m_hDevice, hBuffer, &memReq);
+ requiresDedicatedAllocation = false;
+ prefersDedicatedAllocation = false;
+ }
+}
+
+void VmaAllocator_T::GetImageMemoryRequirements(
+ VkImage hImage,
+ VkMemoryRequirements& memReq,
+ bool& requiresDedicatedAllocation,
+ bool& prefersDedicatedAllocation) const
+{
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+ if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+ {
+ VkImageMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR };
+ memReqInfo.image = hImage;
+
+ VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };
+
+ VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
+ memReq2.pNext = &memDedicatedReq;
+
+ (*m_VulkanFunctions.vkGetImageMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2);
+
+ memReq = memReq2.memoryRequirements;
+ requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE);
+ prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE);
+ }
+ else
+#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+ {
+ (*m_VulkanFunctions.vkGetImageMemoryRequirements)(m_hDevice, hImage, &memReq);
+ requiresDedicatedAllocation = false;
+ prefersDedicatedAllocation = false;
+ }
+}
+
+VkResult VmaAllocator_T::AllocateMemory(
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+
+ VMA_ASSERT(VmaIsPow2(vkMemReq.alignment));
+
+ if(vkMemReq.size == 0)
+ {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ if((createInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&
+ (createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense.");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ if((createInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
+ (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_MAPPED_BIT together with VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT is invalid.");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ if(requiresDedicatedAllocation)
+ {
+ if((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT specified while dedicated allocation is required.");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ if(createInfo.pool != VK_NULL_HANDLE)
+ {
+ VMA_ASSERT(0 && "Pool specified while dedicated allocation is required.");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ }
+ if((createInfo.pool != VK_NULL_HANDLE) &&
+ ((createInfo.flags & (VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT)) != 0))
+ {
+ VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT when pool != null is invalid.");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+
+ if(createInfo.pool != VK_NULL_HANDLE)
+ {
+ const VkDeviceSize alignmentForPool = VMA_MAX(
+ vkMemReq.alignment,
+ GetMemoryTypeMinAlignment(createInfo.pool->m_BlockVector.GetMemoryTypeIndex()));
+
+ VmaAllocationCreateInfo createInfoForPool = createInfo;
+ // If memory type is not HOST_VISIBLE, disable MAPPED.
+ if((createInfoForPool.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
+ (m_MemProps.memoryTypes[createInfo.pool->m_BlockVector.GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ {
+ createInfoForPool.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT;
+ }
+
+ return createInfo.pool->m_BlockVector.Allocate(
+ m_CurrentFrameIndex.load(),
+ vkMemReq.size,
+ alignmentForPool,
+ createInfoForPool,
+ suballocType,
+ allocationCount,
+ pAllocations);
+ }
+ else
+ {
+ // Bit mask of memory Vulkan types acceptable for this allocation.
+ uint32_t memoryTypeBits = vkMemReq.memoryTypeBits;
+ uint32_t memTypeIndex = UINT32_MAX;
+ VkResult res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex);
+ if(res == VK_SUCCESS)
+ {
+ VkDeviceSize alignmentForMemType = VMA_MAX(
+ vkMemReq.alignment,
+ GetMemoryTypeMinAlignment(memTypeIndex));
+
+ res = AllocateMemoryOfType(
+ vkMemReq.size,
+ alignmentForMemType,
+ requiresDedicatedAllocation || prefersDedicatedAllocation,
+ dedicatedBuffer,
+ dedicatedImage,
+ createInfo,
+ memTypeIndex,
+ suballocType,
+ allocationCount,
+ pAllocations);
+ // Succeeded on first try.
+ if(res == VK_SUCCESS)
+ {
+ return res;
+ }
+ // Allocation from this memory type failed. Try other compatible memory types.
+ else
+ {
+ for(;;)
+ {
+ // Remove old memTypeIndex from list of possibilities.
+ memoryTypeBits &= ~(1u << memTypeIndex);
+ // Find alternative memTypeIndex.
+ res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex);
+ if(res == VK_SUCCESS)
+ {
+ alignmentForMemType = VMA_MAX(
+ vkMemReq.alignment,
+ GetMemoryTypeMinAlignment(memTypeIndex));
+
+ res = AllocateMemoryOfType(
+ vkMemReq.size,
+ alignmentForMemType,
+ requiresDedicatedAllocation || prefersDedicatedAllocation,
+ dedicatedBuffer,
+ dedicatedImage,
+ createInfo,
+ memTypeIndex,
+ suballocType,
+ allocationCount,
+ pAllocations);
+ // Allocation from this alternative memory type succeeded.
+ if(res == VK_SUCCESS)
+ {
+ return res;
+ }
+ // else: Allocation from this memory type failed. Try next one - next loop iteration.
+ }
+ // No other matching memory type index could be found.
+ else
+ {
+ // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ }
+ }
+ }
+ // Can't find any single memory type maching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.
+ else
+ return res;
+ }
+}
+
+void VmaAllocator_T::FreeMemory(
+ size_t allocationCount,
+ const VmaAllocation* pAllocations)
+{
+ VMA_ASSERT(pAllocations);
+
+ for(size_t allocIndex = allocationCount; allocIndex--; )
+ {
+ VmaAllocation allocation = pAllocations[allocIndex];
+
+ if(allocation != VK_NULL_HANDLE)
+ {
+ if(TouchAllocation(allocation))
+ {
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+ {
+ FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);
+ }
+
+ switch(allocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaBlockVector* pBlockVector = VMA_NULL;
+ VmaPool hPool = allocation->GetBlock()->GetParentPool();
+ if(hPool != VK_NULL_HANDLE)
+ {
+ pBlockVector = &hPool->m_BlockVector;
+ }
+ else
+ {
+ const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
+ pBlockVector = m_pBlockVectors[memTypeIndex];
+ }
+ pBlockVector->Free(allocation);
+ }
+ break;
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ FreeDedicatedMemory(allocation);
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+ }
+
+ // Do this regardless of whether the allocation is lost. Lost allocations still account to Budget.AllocationBytes.
+ m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize());
+ allocation->SetUserData(this, VMA_NULL);
+ allocation->Dtor();
+ m_AllocationObjectAllocator.Free(allocation);
+ }
+ }
+}
+
+VkResult VmaAllocator_T::ResizeAllocation(
+ const VmaAllocation alloc,
+ VkDeviceSize newSize)
+{
+ // This function is deprecated and so it does nothing. It's left for backward compatibility.
+ if(newSize == 0 || alloc->GetLastUseFrameIndex() == VMA_FRAME_INDEX_LOST)
+ {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ if(newSize == alloc->GetSize())
+ {
+ return VK_SUCCESS;
+ }
+ return VK_ERROR_OUT_OF_POOL_MEMORY;
+}
+
+void VmaAllocator_T::CalculateStats(VmaStats* pStats)
+{
+ // Initialize.
+ InitStatInfo(pStats->total);
+ for(size_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i)
+ InitStatInfo(pStats->memoryType[i]);
+ for(size_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i)
+ InitStatInfo(pStats->memoryHeap[i]);
+
+ // Process default pools.
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];
+ VMA_ASSERT(pBlockVector);
+ pBlockVector->AddStats(pStats);
+ }
+
+ // Process custom pools.
+ {
+ VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
+ for(size_t poolIndex = 0, poolCount = m_Pools.size(); poolIndex < poolCount; ++poolIndex)
+ {
+ m_Pools[poolIndex]->m_BlockVector.AddStats(pStats);
+ }
+ }
+
+ // Process dedicated allocations.
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
+ VmaMutexLockRead dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+ AllocationVectorType* const pDedicatedAllocVector = m_pDedicatedAllocations[memTypeIndex];
+ VMA_ASSERT(pDedicatedAllocVector);
+ for(size_t allocIndex = 0, allocCount = pDedicatedAllocVector->size(); allocIndex < allocCount; ++allocIndex)
+ {
+ VmaStatInfo allocationStatInfo;
+ (*pDedicatedAllocVector)[allocIndex]->DedicatedAllocCalcStatsInfo(allocationStatInfo);
+ VmaAddStatInfo(pStats->total, allocationStatInfo);
+ VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo);
+ VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo);
+ }
+ }
+
+ // Postprocess.
+ VmaPostprocessCalcStatInfo(pStats->total);
+ for(size_t i = 0; i < GetMemoryTypeCount(); ++i)
+ VmaPostprocessCalcStatInfo(pStats->memoryType[i]);
+ for(size_t i = 0; i < GetMemoryHeapCount(); ++i)
+ VmaPostprocessCalcStatInfo(pStats->memoryHeap[i]);
+}
+
+void VmaAllocator_T::GetBudget(VmaBudget* outBudget, uint32_t firstHeap, uint32_t heapCount)
+{
+#if VMA_MEMORY_BUDGET
+ if(m_UseExtMemoryBudget)
+ {
+ if(m_Budget.m_OperationsSinceBudgetFetch < 30)
+ {
+ VmaMutexLockRead lockRead(m_Budget.m_BudgetMutex, m_UseMutex);
+ for(uint32_t i = 0; i < heapCount; ++i, ++outBudget)
+ {
+ const uint32_t heapIndex = firstHeap + i;
+
+ outBudget->blockBytes = m_Budget.m_BlockBytes[heapIndex];
+ outBudget->allocationBytes = m_Budget.m_AllocationBytes[heapIndex];
+
+ if(m_Budget.m_VulkanUsage[heapIndex] + outBudget->blockBytes > m_Budget.m_BlockBytesAtBudgetFetch[heapIndex])
+ {
+ outBudget->usage = m_Budget.m_VulkanUsage[heapIndex] +
+ outBudget->blockBytes - m_Budget.m_BlockBytesAtBudgetFetch[heapIndex];
+ }
+ else
+ {
+ outBudget->usage = 0;
+ }
+
+ // Have to take MIN with heap size because explicit HeapSizeLimit is included in it.
+ outBudget->budget = VMA_MIN(
+ m_Budget.m_VulkanBudget[heapIndex], m_MemProps.memoryHeaps[heapIndex].size);
+ }
+ }
+ else
+ {
+ UpdateVulkanBudget(); // Outside of mutex lock
+ GetBudget(outBudget, firstHeap, heapCount); // Recursion
+ }
+ }
+ else
+#endif
+ {
+ for(uint32_t i = 0; i < heapCount; ++i, ++outBudget)
+ {
+ const uint32_t heapIndex = firstHeap + i;
+
+ outBudget->blockBytes = m_Budget.m_BlockBytes[heapIndex];
+ outBudget->allocationBytes = m_Budget.m_AllocationBytes[heapIndex];
+
+ outBudget->usage = outBudget->blockBytes;
+ outBudget->budget = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics.
+ }
+ }
+}
+
+static const uint32_t VMA_VENDOR_ID_AMD = 4098;
+
+VkResult VmaAllocator_T::DefragmentationBegin(
+ const VmaDefragmentationInfo2& info,
+ VmaDefragmentationStats* pStats,
+ VmaDefragmentationContext* pContext)
+{
+ if(info.pAllocationsChanged != VMA_NULL)
+ {
+ memset(info.pAllocationsChanged, 0, info.allocationCount * sizeof(VkBool32));
+ }
+
+ *pContext = vma_new(this, VmaDefragmentationContext_T)(
+ this, m_CurrentFrameIndex.load(), info.flags, pStats);
+
+ (*pContext)->AddPools(info.poolCount, info.pPools);
+ (*pContext)->AddAllocations(
+ info.allocationCount, info.pAllocations, info.pAllocationsChanged);
+
+ VkResult res = (*pContext)->Defragment(
+ info.maxCpuBytesToMove, info.maxCpuAllocationsToMove,
+ info.maxGpuBytesToMove, info.maxGpuAllocationsToMove,
+ info.commandBuffer, pStats);
+
+ if(res != VK_NOT_READY)
+ {
+ vma_delete(this, *pContext);
+ *pContext = VMA_NULL;
+ }
+
+ return res;
+}
+
+VkResult VmaAllocator_T::DefragmentationEnd(
+ VmaDefragmentationContext context)
+{
+ vma_delete(this, context);
+ return VK_SUCCESS;
+}
+
+void VmaAllocator_T::GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo)
+{
+ if(hAllocation->CanBecomeLost())
+ {
+ /*
+ Warning: This is a carefully designed algorithm.
+ Do not modify unless you really know what you're doing :)
+ */
+ const uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+ uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+ for(;;)
+ {
+ if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
+ {
+ pAllocationInfo->memoryType = UINT32_MAX;
+ pAllocationInfo->deviceMemory = VK_NULL_HANDLE;
+ pAllocationInfo->offset = 0;
+ pAllocationInfo->size = hAllocation->GetSize();
+ pAllocationInfo->pMappedData = VMA_NULL;
+ pAllocationInfo->pUserData = hAllocation->GetUserData();
+ return;
+ }
+ else if(localLastUseFrameIndex == localCurrFrameIndex)
+ {
+ pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex();
+ pAllocationInfo->deviceMemory = hAllocation->GetMemory();
+ pAllocationInfo->offset = hAllocation->GetOffset();
+ pAllocationInfo->size = hAllocation->GetSize();
+ pAllocationInfo->pMappedData = VMA_NULL;
+ pAllocationInfo->pUserData = hAllocation->GetUserData();
+ return;
+ }
+ else // Last use time earlier than current time.
+ {
+ if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+ {
+ localLastUseFrameIndex = localCurrFrameIndex;
+ }
+ }
+ }
+ }
+ else
+ {
+#if VMA_STATS_STRING_ENABLED
+ uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+ uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+ for(;;)
+ {
+ VMA_ASSERT(localLastUseFrameIndex != VMA_FRAME_INDEX_LOST);
+ if(localLastUseFrameIndex == localCurrFrameIndex)
+ {
+ break;
+ }
+ else // Last use time earlier than current time.
+ {
+ if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+ {
+ localLastUseFrameIndex = localCurrFrameIndex;
+ }
+ }
+ }
+#endif
+
+ pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex();
+ pAllocationInfo->deviceMemory = hAllocation->GetMemory();
+ pAllocationInfo->offset = hAllocation->GetOffset();
+ pAllocationInfo->size = hAllocation->GetSize();
+ pAllocationInfo->pMappedData = hAllocation->GetMappedData();
+ pAllocationInfo->pUserData = hAllocation->GetUserData();
+ }
+}
+
+bool VmaAllocator_T::TouchAllocation(VmaAllocation hAllocation)
+{
+ // This is a stripped-down version of VmaAllocator_T::GetAllocationInfo.
+ if(hAllocation->CanBecomeLost())
+ {
+ uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+ uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+ for(;;)
+ {
+ if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
+ {
+ return false;
+ }
+ else if(localLastUseFrameIndex == localCurrFrameIndex)
+ {
+ return true;
+ }
+ else // Last use time earlier than current time.
+ {
+ if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+ {
+ localLastUseFrameIndex = localCurrFrameIndex;
+ }
+ }
+ }
+ }
+ else
+ {
+#if VMA_STATS_STRING_ENABLED
+ uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+ uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+ for(;;)
+ {
+ VMA_ASSERT(localLastUseFrameIndex != VMA_FRAME_INDEX_LOST);
+ if(localLastUseFrameIndex == localCurrFrameIndex)
+ {
+ break;
+ }
+ else // Last use time earlier than current time.
+ {
+ if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+ {
+ localLastUseFrameIndex = localCurrFrameIndex;
+ }
+ }
+ }
+#endif
+
+ return true;
+ }
+}
+
+VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool)
+{
+ VMA_DEBUG_LOG(" CreatePool: MemoryTypeIndex=%u, flags=%u", pCreateInfo->memoryTypeIndex, pCreateInfo->flags);
+
+ VmaPoolCreateInfo newCreateInfo = *pCreateInfo;
+
+ if(newCreateInfo.maxBlockCount == 0)
+ {
+ newCreateInfo.maxBlockCount = SIZE_MAX;
+ }
+ if(newCreateInfo.minBlockCount > newCreateInfo.maxBlockCount)
+ {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex);
+
+ *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize);
+
+ VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks();
+ if(res != VK_SUCCESS)
+ {
+ vma_delete(this, *pPool);
+ *pPool = VMA_NULL;
+ return res;
+ }
+
+ // Add to m_Pools.
+ {
+ VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);
+ (*pPool)->SetId(m_NextPoolId++);
+ VmaVectorInsertSorted<VmaPointerLess>(m_Pools, *pPool);
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaAllocator_T::DestroyPool(VmaPool pool)
+{
+ // Remove from m_Pools.
+ {
+ VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);
+ bool success = VmaVectorRemoveSorted<VmaPointerLess>(m_Pools, pool);
+ VMA_ASSERT(success && "Pool not found in Allocator.");
+ }
+
+ vma_delete(this, pool);
+}
+
+void VmaAllocator_T::GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats)
+{
+ pool->m_BlockVector.GetPoolStats(pPoolStats);
+}
+
+void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)
+{
+ m_CurrentFrameIndex.store(frameIndex);
+
+#if VMA_MEMORY_BUDGET
+ if(m_UseExtMemoryBudget)
+ {
+ UpdateVulkanBudget();
+ }
+#endif // #if VMA_MEMORY_BUDGET
+}
+
+void VmaAllocator_T::MakePoolAllocationsLost(
+ VmaPool hPool,
+ size_t* pLostAllocationCount)
+{
+ hPool->m_BlockVector.MakePoolAllocationsLost(
+ m_CurrentFrameIndex.load(),
+ pLostAllocationCount);
+}
+
+VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool)
+{
+ return hPool->m_BlockVector.CheckCorruption();
+}
+
+VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)
+{
+ VkResult finalRes = VK_ERROR_FEATURE_NOT_PRESENT;
+
+ // Process default pools.
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ if(((1u << memTypeIndex) & memoryTypeBits) != 0)
+ {
+ VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];
+ VMA_ASSERT(pBlockVector);
+ VkResult localRes = pBlockVector->CheckCorruption();
+ switch(localRes)
+ {
+ case VK_ERROR_FEATURE_NOT_PRESENT:
+ break;
+ case VK_SUCCESS:
+ finalRes = VK_SUCCESS;
+ break;
+ default:
+ return localRes;
+ }
+ }
+ }
+
+ // Process custom pools.
+ {
+ VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
+ for(size_t poolIndex = 0, poolCount = m_Pools.size(); poolIndex < poolCount; ++poolIndex)
+ {
+ if(((1u << m_Pools[poolIndex]->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0)
+ {
+ VkResult localRes = m_Pools[poolIndex]->m_BlockVector.CheckCorruption();
+ switch(localRes)
+ {
+ case VK_ERROR_FEATURE_NOT_PRESENT:
+ break;
+ case VK_SUCCESS:
+ finalRes = VK_SUCCESS;
+ break;
+ default:
+ return localRes;
+ }
+ }
+ }
+ }
+
+ return finalRes;
+}
+
+void VmaAllocator_T::CreateLostAllocation(VmaAllocation* pAllocation)
+{
+ *pAllocation = m_AllocationObjectAllocator.Allocate();
+ (*pAllocation)->Ctor(VMA_FRAME_INDEX_LOST, false);
+ (*pAllocation)->InitLost();
+}
+
+VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory)
+{
+ const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(pAllocateInfo->memoryTypeIndex);
+
+ // HeapSizeLimit is in effect for this heap.
+ if((m_HeapSizeLimitMask & (1u << heapIndex)) != 0)
+ {
+ const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;
+ VkDeviceSize blockBytes = m_Budget.m_BlockBytes[heapIndex];
+ for(;;)
+ {
+ const VkDeviceSize blockBytesAfterAllocation = blockBytes + pAllocateInfo->allocationSize;
+ if(blockBytesAfterAllocation > heapSize)
+ {
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ if(m_Budget.m_BlockBytes[heapIndex].compare_exchange_strong(blockBytes, blockBytesAfterAllocation))
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ m_Budget.m_BlockBytes[heapIndex] += pAllocateInfo->allocationSize;
+ }
+
+ // VULKAN CALL vkAllocateMemory.
+ VkResult res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory);
+
+ if(res == VK_SUCCESS)
+ {
+#if VMA_MEMORY_BUDGET
+ ++m_Budget.m_OperationsSinceBudgetFetch;
+#endif
+
+ // Informative callback.
+ if(m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL)
+ {
+ (*m_DeviceMemoryCallbacks.pfnAllocate)(this, pAllocateInfo->memoryTypeIndex, *pMemory, pAllocateInfo->allocationSize);
+ }
+ }
+ else
+ {
+ m_Budget.m_BlockBytes[heapIndex] -= pAllocateInfo->allocationSize;
+ }
+
+ return res;
+}
+
+void VmaAllocator_T::FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory)
+{
+ // Informative callback.
+ if(m_DeviceMemoryCallbacks.pfnFree != VMA_NULL)
+ {
+ (*m_DeviceMemoryCallbacks.pfnFree)(this, memoryType, hMemory, size);
+ }
+
+ // VULKAN CALL vkFreeMemory.
+ (*m_VulkanFunctions.vkFreeMemory)(m_hDevice, hMemory, GetAllocationCallbacks());
+
+ m_Budget.m_BlockBytes[MemoryTypeIndexToHeapIndex(memoryType)] -= size;
+}
+
+VkResult VmaAllocator_T::BindVulkanBuffer(
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset,
+ VkBuffer buffer,
+ const void* pNext)
+{
+ if(pNext != VMA_NULL)
+ {
+#if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2
+ if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) &&
+ m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL)
+ {
+ VkBindBufferMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR };
+ bindBufferMemoryInfo.pNext = pNext;
+ bindBufferMemoryInfo.buffer = buffer;
+ bindBufferMemoryInfo.memory = memory;
+ bindBufferMemoryInfo.memoryOffset = memoryOffset;
+ return (*m_VulkanFunctions.vkBindBufferMemory2KHR)(m_hDevice, 1, &bindBufferMemoryInfo);
+ }
+ else
+#endif // #if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2
+ {
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+ }
+ else
+ {
+ return (*m_VulkanFunctions.vkBindBufferMemory)(m_hDevice, buffer, memory, memoryOffset);
+ }
+}
+
+VkResult VmaAllocator_T::BindVulkanImage(
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset,
+ VkImage image,
+ const void* pNext)
+{
+ if(pNext != VMA_NULL)
+ {
+#if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2
+ if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) &&
+ m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL)
+ {
+ VkBindImageMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR };
+ bindBufferMemoryInfo.pNext = pNext;
+ bindBufferMemoryInfo.image = image;
+ bindBufferMemoryInfo.memory = memory;
+ bindBufferMemoryInfo.memoryOffset = memoryOffset;
+ return (*m_VulkanFunctions.vkBindImageMemory2KHR)(m_hDevice, 1, &bindBufferMemoryInfo);
+ }
+ else
+#endif // #if VMA_BIND_MEMORY2
+ {
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+ }
+ else
+ {
+ return (*m_VulkanFunctions.vkBindImageMemory)(m_hDevice, image, memory, memoryOffset);
+ }
+}
+
+VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData)
+{
+ if(hAllocation->CanBecomeLost())
+ {
+ return VK_ERROR_MEMORY_MAP_FAILED;
+ }
+
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();
+ char *pBytes = VMA_NULL;
+ VkResult res = pBlock->Map(this, 1, (void**)&pBytes);
+ if(res == VK_SUCCESS)
+ {
+ *ppData = pBytes + (ptrdiff_t)hAllocation->GetOffset();
+ hAllocation->BlockAllocMap();
+ }
+ return res;
+ }
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ return hAllocation->DedicatedAllocMap(this, ppData);
+ default:
+ VMA_ASSERT(0);
+ return VK_ERROR_MEMORY_MAP_FAILED;
+ }
+}
+
+void VmaAllocator_T::Unmap(VmaAllocation hAllocation)
+{
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();
+ hAllocation->BlockAllocUnmap();
+ pBlock->Unmap(this, 1);
+ }
+ break;
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ hAllocation->DedicatedAllocUnmap(this);
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+}
+
+VkResult VmaAllocator_T::BindBufferMemory(
+ VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkBuffer hBuffer,
+ const void* pNext)
+{
+ VkResult res = VK_SUCCESS;
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ res = BindVulkanBuffer(hAllocation->GetMemory(), allocationLocalOffset, hBuffer, pNext);
+ break;
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();
+ VMA_ASSERT(pBlock && "Binding buffer to allocation that doesn't belong to any block. Is the allocation lost?");
+ res = pBlock->BindBufferMemory(this, hAllocation, allocationLocalOffset, hBuffer, pNext);
+ break;
+ }
+ default:
+ VMA_ASSERT(0);
+ }
+ return res;
+}
+
+VkResult VmaAllocator_T::BindImageMemory(
+ VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkImage hImage,
+ const void* pNext)
+{
+ VkResult res = VK_SUCCESS;
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ res = BindVulkanImage(hAllocation->GetMemory(), allocationLocalOffset, hImage, pNext);
+ break;
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();
+ VMA_ASSERT(pBlock && "Binding image to allocation that doesn't belong to any block. Is the allocation lost?");
+ res = pBlock->BindImageMemory(this, hAllocation, allocationLocalOffset, hImage, pNext);
+ break;
+ }
+ default:
+ VMA_ASSERT(0);
+ }
+ return res;
+}
+
+void VmaAllocator_T::FlushOrInvalidateAllocation(
+ VmaAllocation hAllocation,
+ VkDeviceSize offset, VkDeviceSize size,
+ VMA_CACHE_OPERATION op)
+{
+ const uint32_t memTypeIndex = hAllocation->GetMemoryTypeIndex();
+ if(size > 0 && IsMemoryTypeNonCoherent(memTypeIndex))
+ {
+ const VkDeviceSize allocationSize = hAllocation->GetSize();
+ VMA_ASSERT(offset <= allocationSize);
+
+ const VkDeviceSize nonCoherentAtomSize = m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
+
+ VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
+ memRange.memory = hAllocation->GetMemory();
+
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ memRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);
+ if(size == VK_WHOLE_SIZE)
+ {
+ memRange.size = allocationSize - memRange.offset;
+ }
+ else
+ {
+ VMA_ASSERT(offset + size <= allocationSize);
+ memRange.size = VMA_MIN(
+ VmaAlignUp(size + (offset - memRange.offset), nonCoherentAtomSize),
+ allocationSize - memRange.offset);
+ }
+ break;
+
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ // 1. Still within this allocation.
+ memRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);
+ if(size == VK_WHOLE_SIZE)
+ {
+ size = allocationSize - offset;
+ }
+ else
+ {
+ VMA_ASSERT(offset + size <= allocationSize);
+ }
+ memRange.size = VmaAlignUp(size + (offset - memRange.offset), nonCoherentAtomSize);
+
+ // 2. Adjust to whole block.
+ const VkDeviceSize allocationOffset = hAllocation->GetOffset();
+ VMA_ASSERT(allocationOffset % nonCoherentAtomSize == 0);
+ const VkDeviceSize blockSize = hAllocation->GetBlock()->m_pMetadata->GetSize();
+ memRange.offset += allocationOffset;
+ memRange.size = VMA_MIN(memRange.size, blockSize - memRange.offset);
+
+ break;
+ }
+
+ default:
+ VMA_ASSERT(0);
+ }
+
+ switch(op)
+ {
+ case VMA_CACHE_FLUSH:
+ (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, 1, &memRange);
+ break;
+ case VMA_CACHE_INVALIDATE:
+ (*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, 1, &memRange);
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+ }
+ // else: Just ignore this call.
+}
+
+void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)
+{
+ VMA_ASSERT(allocation && allocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
+
+ const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
+ {
+ VmaMutexLockWrite lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+ AllocationVectorType* const pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex];
+ VMA_ASSERT(pDedicatedAllocations);
+ bool success = VmaVectorRemoveSorted<VmaPointerLess>(*pDedicatedAllocations, allocation);
+ VMA_ASSERT(success);
+ }
+
+ VkDeviceMemory hMemory = allocation->GetMemory();
+
+ /*
+ There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory
+ before vkFreeMemory.
+
+ if(allocation->GetMappedData() != VMA_NULL)
+ {
+ (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory);
+ }
+ */
+
+ FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);
+
+ VMA_DEBUG_LOG(" Freed DedicatedMemory MemoryTypeIndex=%u", memTypeIndex);
+}
+
+uint32_t VmaAllocator_T::CalculateGpuDefragmentationMemoryTypeBits() const
+{
+ VkBufferCreateInfo dummyBufCreateInfo;
+ VmaFillGpuDefragmentationBufferCreateInfo(dummyBufCreateInfo);
+
+ uint32_t memoryTypeBits = 0;
+
+ // Create buffer.
+ VkBuffer buf = VK_NULL_HANDLE;
+ VkResult res = (*GetVulkanFunctions().vkCreateBuffer)(
+ m_hDevice, &dummyBufCreateInfo, GetAllocationCallbacks(), &buf);
+ if(res == VK_SUCCESS)
+ {
+ // Query for supported memory types.
+ VkMemoryRequirements memReq;
+ (*GetVulkanFunctions().vkGetBufferMemoryRequirements)(m_hDevice, buf, &memReq);
+ memoryTypeBits = memReq.memoryTypeBits;
+
+ // Destroy buffer.
+ (*GetVulkanFunctions().vkDestroyBuffer)(m_hDevice, buf, GetAllocationCallbacks());
+ }
+
+ return memoryTypeBits;
+}
+
+#if VMA_MEMORY_BUDGET
+
+void VmaAllocator_T::UpdateVulkanBudget()
+{
+ VMA_ASSERT(m_UseExtMemoryBudget);
+
+ VkPhysicalDeviceMemoryProperties2KHR memProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR };
+
+ VkPhysicalDeviceMemoryBudgetPropertiesEXT budgetProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT };
+ memProps.pNext = &budgetProps;
+
+ GetVulkanFunctions().vkGetPhysicalDeviceMemoryProperties2KHR(m_PhysicalDevice, &memProps);
+
+ {
+ VmaMutexLockWrite lockWrite(m_Budget.m_BudgetMutex, m_UseMutex);
+
+ for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex)
+ {
+ m_Budget.m_VulkanUsage[heapIndex] = budgetProps.heapUsage[heapIndex];
+ m_Budget.m_VulkanBudget[heapIndex] = budgetProps.heapBudget[heapIndex];
+ m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] = m_Budget.m_BlockBytes[heapIndex].load();
+ }
+ m_Budget.m_OperationsSinceBudgetFetch = 0;
+ }
+}
+
+#endif // #if VMA_MEMORY_BUDGET
+
+void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern)
+{
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS &&
+ !hAllocation->CanBecomeLost() &&
+ (m_MemProps.memoryTypes[hAllocation->GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
+ {
+ void* pData = VMA_NULL;
+ VkResult res = Map(hAllocation, &pData);
+ if(res == VK_SUCCESS)
+ {
+ memset(pData, (int)pattern, (size_t)hAllocation->GetSize());
+ FlushOrInvalidateAllocation(hAllocation, 0, VK_WHOLE_SIZE, VMA_CACHE_FLUSH);
+ Unmap(hAllocation);
+ }
+ else
+ {
+ VMA_ASSERT(0 && "VMA_DEBUG_INITIALIZE_ALLOCATIONS is enabled, but couldn't map memory to fill allocation.");
+ }
+ }
+}
+
+uint32_t VmaAllocator_T::GetGpuDefragmentationMemoryTypeBits()
+{
+ uint32_t memoryTypeBits = m_GpuDefragmentationMemoryTypeBits.load();
+ if(memoryTypeBits == UINT32_MAX)
+ {
+ memoryTypeBits = CalculateGpuDefragmentationMemoryTypeBits();
+ m_GpuDefragmentationMemoryTypeBits.store(memoryTypeBits);
+ }
+ return memoryTypeBits;
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
+{
+ bool dedicatedAllocationsStarted = false;
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ VmaMutexLockRead dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+ AllocationVectorType* const pDedicatedAllocVector = m_pDedicatedAllocations[memTypeIndex];
+ VMA_ASSERT(pDedicatedAllocVector);
+ if(pDedicatedAllocVector->empty() == false)
+ {
+ if(dedicatedAllocationsStarted == false)
+ {
+ dedicatedAllocationsStarted = true;
+ json.WriteString("DedicatedAllocations");
+ json.BeginObject();
+ }
+
+ json.BeginString("Type ");
+ json.ContinueString(memTypeIndex);
+ json.EndString();
+
+ json.BeginArray();
+
+ for(size_t i = 0; i < pDedicatedAllocVector->size(); ++i)
+ {
+ json.BeginObject(true);
+ const VmaAllocation hAlloc = (*pDedicatedAllocVector)[i];
+ hAlloc->PrintParameters(json);
+ json.EndObject();
+ }
+
+ json.EndArray();
+ }
+ }
+ if(dedicatedAllocationsStarted)
+ {
+ json.EndObject();
+ }
+
+ {
+ bool allocationsStarted = false;
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ if(m_pBlockVectors[memTypeIndex]->IsEmpty() == false)
+ {
+ if(allocationsStarted == false)
+ {
+ allocationsStarted = true;
+ json.WriteString("DefaultPools");
+ json.BeginObject();
+ }
+
+ json.BeginString("Type ");
+ json.ContinueString(memTypeIndex);
+ json.EndString();
+
+ m_pBlockVectors[memTypeIndex]->PrintDetailedMap(json);
+ }
+ }
+ if(allocationsStarted)
+ {
+ json.EndObject();
+ }
+ }
+
+ // Custom pools
+ {
+ VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
+ const size_t poolCount = m_Pools.size();
+ if(poolCount > 0)
+ {
+ json.WriteString("Pools");
+ json.BeginObject();
+ for(size_t poolIndex = 0; poolIndex < poolCount; ++poolIndex)
+ {
+ json.BeginString();
+ json.ContinueString(m_Pools[poolIndex]->GetId());
+ json.EndString();
+
+ m_Pools[poolIndex]->m_BlockVector.PrintDetailedMap(json);
+ }
+ json.EndObject();
+ }
+ }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// Public interface
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
+ const VmaAllocatorCreateInfo* pCreateInfo,
+ VmaAllocator* pAllocator)
+{
+ VMA_ASSERT(pCreateInfo && pAllocator);
+ VMA_ASSERT(pCreateInfo->vulkanApiVersion == 0 ||
+ (VK_VERSION_MAJOR(pCreateInfo->vulkanApiVersion) == 1 && VK_VERSION_MINOR(pCreateInfo->vulkanApiVersion) <= 1));
+ VMA_DEBUG_LOG("vmaCreateAllocator");
+ *pAllocator = vma_new(pCreateInfo->pAllocationCallbacks, VmaAllocator_T)(pCreateInfo);
+ return (*pAllocator)->Init(pCreateInfo);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator(
+ VmaAllocator allocator)
+{
+ if(allocator != VK_NULL_HANDLE)
+ {
+ VMA_DEBUG_LOG("vmaDestroyAllocator");
+ VkAllocationCallbacks allocationCallbacks = allocator->m_AllocationCallbacks;
+ vma_delete(&allocationCallbacks, allocator);
+ }
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties(
+ VmaAllocator allocator,
+ const VkPhysicalDeviceProperties **ppPhysicalDeviceProperties)
+{
+ VMA_ASSERT(allocator && ppPhysicalDeviceProperties);
+ *ppPhysicalDeviceProperties = &allocator->m_PhysicalDeviceProperties;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties(
+ VmaAllocator allocator,
+ const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties)
+{
+ VMA_ASSERT(allocator && ppPhysicalDeviceMemoryProperties);
+ *ppPhysicalDeviceMemoryProperties = &allocator->m_MemProps;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties(
+ VmaAllocator allocator,
+ uint32_t memoryTypeIndex,
+ VkMemoryPropertyFlags* pFlags)
+{
+ VMA_ASSERT(allocator && pFlags);
+ VMA_ASSERT(memoryTypeIndex < allocator->GetMemoryTypeCount());
+ *pFlags = allocator->m_MemProps.memoryTypes[memoryTypeIndex].propertyFlags;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex(
+ VmaAllocator allocator,
+ uint32_t frameIndex)
+{
+ VMA_ASSERT(allocator);
+ VMA_ASSERT(frameIndex != VMA_FRAME_INDEX_LOST);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ allocator->SetCurrentFrameIndex(frameIndex);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStats(
+ VmaAllocator allocator,
+ VmaStats* pStats)
+{
+ VMA_ASSERT(allocator && pStats);
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+ allocator->CalculateStats(pStats);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetBudget(
+ VmaAllocator allocator,
+ VmaBudget* pBudget)
+{
+ VMA_ASSERT(allocator && pBudget);
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+ allocator->GetBudget(pBudget, 0, allocator->GetMemoryHeapCount());
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString(
+ VmaAllocator allocator,
+ char** ppStatsString,
+ VkBool32 detailedMap)
+{
+ VMA_ASSERT(allocator && ppStatsString);
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VmaStringBuilder sb(allocator);
+ {
+ VmaJsonWriter json(allocator->GetAllocationCallbacks(), sb);
+ json.BeginObject();
+
+ VmaBudget budget[VK_MAX_MEMORY_HEAPS];
+ allocator->GetBudget(budget, 0, allocator->GetMemoryHeapCount());
+
+ VmaStats stats;
+ allocator->CalculateStats(&stats);
+
+ json.WriteString("Total");
+ VmaPrintStatInfo(json, stats.total);
+
+ for(uint32_t heapIndex = 0; heapIndex < allocator->GetMemoryHeapCount(); ++heapIndex)
+ {
+ json.BeginString("Heap ");
+ json.ContinueString(heapIndex);
+ json.EndString();
+ json.BeginObject();
+
+ json.WriteString("Size");
+ json.WriteNumber(allocator->m_MemProps.memoryHeaps[heapIndex].size);
+
+ json.WriteString("Flags");
+ json.BeginArray(true);
+ if((allocator->m_MemProps.memoryHeaps[heapIndex].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
+ {
+ json.WriteString("DEVICE_LOCAL");
+ }
+ json.EndArray();
+
+ json.WriteString("Budget");
+ json.BeginObject();
+ {
+ json.WriteString("BlockBytes");
+ json.WriteNumber(budget[heapIndex].blockBytes);
+ json.WriteString("AllocationBytes");
+ json.WriteNumber(budget[heapIndex].allocationBytes);
+ json.WriteString("Usage");
+ json.WriteNumber(budget[heapIndex].usage);
+ json.WriteString("Budget");
+ json.WriteNumber(budget[heapIndex].budget);
+ }
+ json.EndObject();
+
+ if(stats.memoryHeap[heapIndex].blockCount > 0)
+ {
+ json.WriteString("Stats");
+ VmaPrintStatInfo(json, stats.memoryHeap[heapIndex]);
+ }
+
+ for(uint32_t typeIndex = 0; typeIndex < allocator->GetMemoryTypeCount(); ++typeIndex)
+ {
+ if(allocator->MemoryTypeIndexToHeapIndex(typeIndex) == heapIndex)
+ {
+ json.BeginString("Type ");
+ json.ContinueString(typeIndex);
+ json.EndString();
+
+ json.BeginObject();
+
+ json.WriteString("Flags");
+ json.BeginArray(true);
+ VkMemoryPropertyFlags flags = allocator->m_MemProps.memoryTypes[typeIndex].propertyFlags;
+ if((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
+ {
+ json.WriteString("DEVICE_LOCAL");
+ }
+ if((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
+ {
+ json.WriteString("HOST_VISIBLE");
+ }
+ if((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0)
+ {
+ json.WriteString("HOST_COHERENT");
+ }
+ if((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0)
+ {
+ json.WriteString("HOST_CACHED");
+ }
+ if((flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0)
+ {
+ json.WriteString("LAZILY_ALLOCATED");
+ }
+ json.EndArray();
+
+ if(stats.memoryType[typeIndex].blockCount > 0)
+ {
+ json.WriteString("Stats");
+ VmaPrintStatInfo(json, stats.memoryType[typeIndex]);
+ }
+
+ json.EndObject();
+ }
+ }
+
+ json.EndObject();
+ }
+ if(detailedMap == VK_TRUE)
+ {
+ allocator->PrintDetailedMap(json);
+ }
+
+ json.EndObject();
+ }
+
+ const size_t len = sb.GetLength();
+ char* const pChars = vma_new_array(allocator, char, len + 1);
+ if(len > 0)
+ {
+ memcpy(pChars, sb.GetData(), len);
+ }
+ pChars[len] = '\0';
+ *ppStatsString = pChars;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
+ VmaAllocator allocator,
+ char* pStatsString)
+{
+ if(pStatsString != VMA_NULL)
+ {
+ VMA_ASSERT(allocator);
+ size_t len = strlen(pStatsString);
+ vma_delete_array(allocator, pStatsString, len + 1);
+ }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+/*
+This function is not protected by any mutex because it just reads immutable data.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex(
+ VmaAllocator allocator,
+ uint32_t memoryTypeBits,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex)
+{
+ VMA_ASSERT(allocator != VK_NULL_HANDLE);
+ VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);
+ VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
+
+ if(pAllocationCreateInfo->memoryTypeBits != 0)
+ {
+ memoryTypeBits &= pAllocationCreateInfo->memoryTypeBits;
+ }
+
+ uint32_t requiredFlags = pAllocationCreateInfo->requiredFlags;
+ uint32_t preferredFlags = pAllocationCreateInfo->preferredFlags;
+ uint32_t notPreferredFlags = 0;
+
+ // Convert usage to requiredFlags and preferredFlags.
+ switch(pAllocationCreateInfo->usage)
+ {
+ case VMA_MEMORY_USAGE_UNKNOWN:
+ break;
+ case VMA_MEMORY_USAGE_GPU_ONLY:
+ if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ {
+ preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ break;
+ case VMA_MEMORY_USAGE_CPU_ONLY:
+ requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ break;
+ case VMA_MEMORY_USAGE_CPU_TO_GPU:
+ requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ {
+ preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ break;
+ case VMA_MEMORY_USAGE_GPU_TO_CPU:
+ requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ preferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ break;
+ case VMA_MEMORY_USAGE_CPU_COPY:
+ notPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ break;
+ case VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED:
+ requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
+ break;
+ default:
+ VMA_ASSERT(0);
+ break;
+ }
+
+ *pMemoryTypeIndex = UINT32_MAX;
+ uint32_t minCost = UINT32_MAX;
+ for(uint32_t memTypeIndex = 0, memTypeBit = 1;
+ memTypeIndex < allocator->GetMemoryTypeCount();
+ ++memTypeIndex, memTypeBit <<= 1)
+ {
+ // This memory type is acceptable according to memoryTypeBits bitmask.
+ if((memTypeBit & memoryTypeBits) != 0)
+ {
+ const VkMemoryPropertyFlags currFlags =
+ allocator->m_MemProps.memoryTypes[memTypeIndex].propertyFlags;
+ // This memory type contains requiredFlags.
+ if((requiredFlags & ~currFlags) == 0)
+ {
+ // Calculate cost as number of bits from preferredFlags not present in this memory type.
+ uint32_t currCost = VmaCountBitsSet(preferredFlags & ~currFlags) +
+ VmaCountBitsSet(currFlags & notPreferredFlags);
+ // Remember memory type with lowest cost.
+ if(currCost < minCost)
+ {
+ *pMemoryTypeIndex = memTypeIndex;
+ if(currCost == 0)
+ {
+ return VK_SUCCESS;
+ }
+ minCost = currCost;
+ }
+ }
+ }
+ }
+ return (*pMemoryTypeIndex != UINT32_MAX) ? VK_SUCCESS : VK_ERROR_FEATURE_NOT_PRESENT;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo(
+ VmaAllocator allocator,
+ const VkBufferCreateInfo* pBufferCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex)
+{
+ VMA_ASSERT(allocator != VK_NULL_HANDLE);
+ VMA_ASSERT(pBufferCreateInfo != VMA_NULL);
+ VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);
+ VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
+
+ const VkDevice hDev = allocator->m_hDevice;
+ VkBuffer hBuffer = VK_NULL_HANDLE;
+ VkResult res = allocator->GetVulkanFunctions().vkCreateBuffer(
+ hDev, pBufferCreateInfo, allocator->GetAllocationCallbacks(), &hBuffer);
+ if(res == VK_SUCCESS)
+ {
+ VkMemoryRequirements memReq = {};
+ allocator->GetVulkanFunctions().vkGetBufferMemoryRequirements(
+ hDev, hBuffer, &memReq);
+
+ res = vmaFindMemoryTypeIndex(
+ allocator,
+ memReq.memoryTypeBits,
+ pAllocationCreateInfo,
+ pMemoryTypeIndex);
+
+ allocator->GetVulkanFunctions().vkDestroyBuffer(
+ hDev, hBuffer, allocator->GetAllocationCallbacks());
+ }
+ return res;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo(
+ VmaAllocator allocator,
+ const VkImageCreateInfo* pImageCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex)
+{
+ VMA_ASSERT(allocator != VK_NULL_HANDLE);
+ VMA_ASSERT(pImageCreateInfo != VMA_NULL);
+ VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);
+ VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
+
+ const VkDevice hDev = allocator->m_hDevice;
+ VkImage hImage = VK_NULL_HANDLE;
+ VkResult res = allocator->GetVulkanFunctions().vkCreateImage(
+ hDev, pImageCreateInfo, allocator->GetAllocationCallbacks(), &hImage);
+ if(res == VK_SUCCESS)
+ {
+ VkMemoryRequirements memReq = {};
+ allocator->GetVulkanFunctions().vkGetImageMemoryRequirements(
+ hDev, hImage, &memReq);
+
+ res = vmaFindMemoryTypeIndex(
+ allocator,
+ memReq.memoryTypeBits,
+ pAllocationCreateInfo,
+ pMemoryTypeIndex);
+
+ allocator->GetVulkanFunctions().vkDestroyImage(
+ hDev, hImage, allocator->GetAllocationCallbacks());
+ }
+ return res;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool(
+ VmaAllocator allocator,
+ const VmaPoolCreateInfo* pCreateInfo,
+ VmaPool* pPool)
+{
+ VMA_ASSERT(allocator && pCreateInfo && pPool);
+
+ VMA_DEBUG_LOG("vmaCreatePool");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkResult res = allocator->CreatePool(pCreateInfo, pPool);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordCreatePool(allocator->GetCurrentFrameIndex(), *pCreateInfo, *pPool);
+ }
+#endif
+
+ return res;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(
+ VmaAllocator allocator,
+ VmaPool pool)
+{
+ VMA_ASSERT(allocator);
+
+ if(pool == VK_NULL_HANDLE)
+ {
+ return;
+ }
+
+ VMA_DEBUG_LOG("vmaDestroyPool");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordDestroyPool(allocator->GetCurrentFrameIndex(), pool);
+ }
+#endif
+
+ allocator->DestroyPool(pool);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStats(
+ VmaAllocator allocator,
+ VmaPool pool,
+ VmaPoolStats* pPoolStats)
+{
+ VMA_ASSERT(allocator && pool && pPoolStats);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ allocator->GetPoolStats(pool, pPoolStats);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaMakePoolAllocationsLost(
+ VmaAllocator allocator,
+ VmaPool pool,
+ size_t* pLostAllocationCount)
+{
+ VMA_ASSERT(allocator && pool);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordMakePoolAllocationsLost(allocator->GetCurrentFrameIndex(), pool);
+ }
+#endif
+
+ allocator->MakePoolAllocationsLost(pool, pLostAllocationCount);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool)
+{
+ VMA_ASSERT(allocator && pool);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VMA_DEBUG_LOG("vmaCheckPoolCorruption");
+
+ return allocator->CheckPoolCorruption(pool);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName(
+ VmaAllocator allocator,
+ VmaPool pool,
+ const char** ppName)
+{
+ VMA_ASSERT(allocator && pool);
+
+ VMA_DEBUG_LOG("vmaGetPoolName");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ *ppName = pool->GetName();
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName(
+ VmaAllocator allocator,
+ VmaPool pool,
+ const char* pName)
+{
+ VMA_ASSERT(allocator && pool);
+
+ VMA_DEBUG_LOG("vmaSetPoolName");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ pool->SetName(pName);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordSetPoolName(allocator->GetCurrentFrameIndex(), pool, pName);
+ }
+#endif
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory(
+ VmaAllocator allocator,
+ const VkMemoryRequirements* pVkMemoryRequirements,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocation);
+
+ VMA_DEBUG_LOG("vmaAllocateMemory");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkResult result = allocator->AllocateMemory(
+ *pVkMemoryRequirements,
+ false, // requiresDedicatedAllocation
+ false, // prefersDedicatedAllocation
+ VK_NULL_HANDLE, // dedicatedBuffer
+ VK_NULL_HANDLE, // dedicatedImage
+ *pCreateInfo,
+ VMA_SUBALLOCATION_TYPE_UNKNOWN,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordAllocateMemory(
+ allocator->GetCurrentFrameIndex(),
+ *pVkMemoryRequirements,
+ *pCreateInfo,
+ *pAllocation);
+ }
+#endif
+
+ if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return result;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages(
+ VmaAllocator allocator,
+ const VkMemoryRequirements* pVkMemoryRequirements,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ size_t allocationCount,
+ VmaAllocation* pAllocations,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ if(allocationCount == 0)
+ {
+ return VK_SUCCESS;
+ }
+
+ VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocations);
+
+ VMA_DEBUG_LOG("vmaAllocateMemoryPages");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkResult result = allocator->AllocateMemory(
+ *pVkMemoryRequirements,
+ false, // requiresDedicatedAllocation
+ false, // prefersDedicatedAllocation
+ VK_NULL_HANDLE, // dedicatedBuffer
+ VK_NULL_HANDLE, // dedicatedImage
+ *pCreateInfo,
+ VMA_SUBALLOCATION_TYPE_UNKNOWN,
+ allocationCount,
+ pAllocations);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordAllocateMemoryPages(
+ allocator->GetCurrentFrameIndex(),
+ *pVkMemoryRequirements,
+ *pCreateInfo,
+ (uint64_t)allocationCount,
+ pAllocations);
+ }
+#endif
+
+ if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS)
+ {
+ for(size_t i = 0; i < allocationCount; ++i)
+ {
+ allocator->GetAllocationInfo(pAllocations[i], pAllocationInfo + i);
+ }
+ }
+
+ return result;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer(
+ VmaAllocator allocator,
+ VkBuffer buffer,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && buffer != VK_NULL_HANDLE && pCreateInfo && pAllocation);
+
+ VMA_DEBUG_LOG("vmaAllocateMemoryForBuffer");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkMemoryRequirements vkMemReq = {};
+ bool requiresDedicatedAllocation = false;
+ bool prefersDedicatedAllocation = false;
+ allocator->GetBufferMemoryRequirements(buffer, vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation);
+
+ VkResult result = allocator->AllocateMemory(
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ buffer, // dedicatedBuffer
+ VK_NULL_HANDLE, // dedicatedImage
+ *pCreateInfo,
+ VMA_SUBALLOCATION_TYPE_BUFFER,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordAllocateMemoryForBuffer(
+ allocator->GetCurrentFrameIndex(),
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ *pCreateInfo,
+ *pAllocation);
+ }
+#endif
+
+ if(pAllocationInfo && result == VK_SUCCESS)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return result;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage(
+ VmaAllocator allocator,
+ VkImage image,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && image != VK_NULL_HANDLE && pCreateInfo && pAllocation);
+
+ VMA_DEBUG_LOG("vmaAllocateMemoryForImage");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkMemoryRequirements vkMemReq = {};
+ bool requiresDedicatedAllocation = false;
+ bool prefersDedicatedAllocation = false;
+ allocator->GetImageMemoryRequirements(image, vkMemReq,
+ requiresDedicatedAllocation, prefersDedicatedAllocation);
+
+ VkResult result = allocator->AllocateMemory(
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ VK_NULL_HANDLE, // dedicatedBuffer
+ image, // dedicatedImage
+ *pCreateInfo,
+ VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordAllocateMemoryForImage(
+ allocator->GetCurrentFrameIndex(),
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ *pCreateInfo,
+ *pAllocation);
+ }
+#endif
+
+ if(pAllocationInfo && result == VK_SUCCESS)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return result;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator);
+
+ if(allocation == VK_NULL_HANDLE)
+ {
+ return;
+ }
+
+ VMA_DEBUG_LOG("vmaFreeMemory");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordFreeMemory(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ allocator->FreeMemory(
+ 1, // allocationCount
+ &allocation);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages(
+ VmaAllocator allocator,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ if(allocationCount == 0)
+ {
+ return;
+ }
+
+ VMA_ASSERT(allocator);
+
+ VMA_DEBUG_LOG("vmaFreeMemoryPages");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordFreeMemoryPages(
+ allocator->GetCurrentFrameIndex(),
+ (uint64_t)allocationCount,
+ pAllocations);
+ }
+#endif
+
+ allocator->FreeMemory(allocationCount, pAllocations);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaResizeAllocation(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkDeviceSize newSize)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_LOG("vmaResizeAllocation");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ return allocator->ResizeAllocation(allocation, newSize);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && allocation && pAllocationInfo);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordGetAllocationInfo(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ allocator->GetAllocationInfo(allocation, pAllocationInfo);
+}
+
+VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaTouchAllocation(
+ VmaAllocator allocator,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordTouchAllocation(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ return allocator->TouchAllocation(allocation);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ void* pUserData)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ allocation->SetUserData(allocator, pUserData);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordSetAllocationUserData(
+ allocator->GetCurrentFrameIndex(),
+ allocation,
+ pUserData);
+ }
+#endif
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaCreateLostAllocation(
+ VmaAllocator allocator,
+ VmaAllocation* pAllocation)
+{
+ VMA_ASSERT(allocator && pAllocation);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+
+ allocator->CreateLostAllocation(pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordCreateLostAllocation(
+ allocator->GetCurrentFrameIndex(),
+ *pAllocation);
+ }
+#endif
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ void** ppData)
+{
+ VMA_ASSERT(allocator && allocation && ppData);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkResult res = allocator->Map(allocation, ppData);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordMapMemory(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ return res;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordUnmapMemory(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ allocator->Unmap(allocation);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_LOG("vmaFlushAllocation");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordFlushAllocation(
+ allocator->GetCurrentFrameIndex(),
+ allocation, offset, size);
+ }
+#endif
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_LOG("vmaInvalidateAllocation");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordInvalidateAllocation(
+ allocator->GetCurrentFrameIndex(),
+ allocation, offset, size);
+ }
+#endif
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(VmaAllocator allocator, uint32_t memoryTypeBits)
+{
+ VMA_ASSERT(allocator);
+
+ VMA_DEBUG_LOG("vmaCheckCorruption");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ return allocator->CheckCorruption(memoryTypeBits);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment(
+ VmaAllocator allocator,
+ VmaAllocation* pAllocations,
+ size_t allocationCount,
+ VkBool32* pAllocationsChanged,
+ const VmaDefragmentationInfo *pDefragmentationInfo,
+ VmaDefragmentationStats* pDefragmentationStats)
+{
+ // Deprecated interface, reimplemented using new one.
+
+ VmaDefragmentationInfo2 info2 = {};
+ info2.allocationCount = (uint32_t)allocationCount;
+ info2.pAllocations = pAllocations;
+ info2.pAllocationsChanged = pAllocationsChanged;
+ if(pDefragmentationInfo != VMA_NULL)
+ {
+ info2.maxCpuAllocationsToMove = pDefragmentationInfo->maxAllocationsToMove;
+ info2.maxCpuBytesToMove = pDefragmentationInfo->maxBytesToMove;
+ }
+ else
+ {
+ info2.maxCpuAllocationsToMove = UINT32_MAX;
+ info2.maxCpuBytesToMove = VK_WHOLE_SIZE;
+ }
+ // info2.flags, maxGpuAllocationsToMove, maxGpuBytesToMove, commandBuffer deliberately left zero.
+
+ VmaDefragmentationContext ctx;
+ VkResult res = vmaDefragmentationBegin(allocator, &info2, pDefragmentationStats, &ctx);
+ if(res == VK_NOT_READY)
+ {
+ res = vmaDefragmentationEnd( allocator, ctx);
+ }
+ return res;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationBegin(
+ VmaAllocator allocator,
+ const VmaDefragmentationInfo2* pInfo,
+ VmaDefragmentationStats* pStats,
+ VmaDefragmentationContext *pContext)
+{
+ VMA_ASSERT(allocator && pInfo && pContext);
+
+ // Degenerate case: Nothing to defragment.
+ if(pInfo->allocationCount == 0 && pInfo->poolCount == 0)
+ {
+ return VK_SUCCESS;
+ }
+
+ VMA_ASSERT(pInfo->allocationCount == 0 || pInfo->pAllocations != VMA_NULL);
+ VMA_ASSERT(pInfo->poolCount == 0 || pInfo->pPools != VMA_NULL);
+ VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->allocationCount, pInfo->pAllocations));
+ VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->poolCount, pInfo->pPools));
+
+ VMA_DEBUG_LOG("vmaDefragmentationBegin");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkResult res = allocator->DefragmentationBegin(*pInfo, pStats, pContext);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordDefragmentationBegin(
+ allocator->GetCurrentFrameIndex(), *pInfo, *pContext);
+ }
+#endif
+
+ return res;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationEnd(
+ VmaAllocator allocator,
+ VmaDefragmentationContext context)
+{
+ VMA_ASSERT(allocator);
+
+ VMA_DEBUG_LOG("vmaDefragmentationEnd");
+
+ if(context != VK_NULL_HANDLE)
+ {
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordDefragmentationEnd(
+ allocator->GetCurrentFrameIndex(), context);
+ }
+#endif
+
+ return allocator->DefragmentationEnd(context);
+ }
+ else
+ {
+ return VK_SUCCESS;
+ }
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkBuffer buffer)
+{
+ VMA_ASSERT(allocator && allocation && buffer);
+
+ VMA_DEBUG_LOG("vmaBindBufferMemory");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ return allocator->BindBufferMemory(allocation, 0, buffer, VMA_NULL);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkDeviceSize allocationLocalOffset,
+ VkBuffer buffer,
+ const void* pNext)
+{
+ VMA_ASSERT(allocator && allocation && buffer);
+
+ VMA_DEBUG_LOG("vmaBindBufferMemory2");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ return allocator->BindBufferMemory(allocation, allocationLocalOffset, buffer, pNext);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkImage image)
+{
+ VMA_ASSERT(allocator && allocation && image);
+
+ VMA_DEBUG_LOG("vmaBindImageMemory");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ return allocator->BindImageMemory(allocation, 0, image, VMA_NULL);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkDeviceSize allocationLocalOffset,
+ VkImage image,
+ const void* pNext)
+{
+ VMA_ASSERT(allocator && allocation && image);
+
+ VMA_DEBUG_LOG("vmaBindImageMemory2");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ return allocator->BindImageMemory(allocation, allocationLocalOffset, image, pNext);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer(
+ VmaAllocator allocator,
+ const VkBufferCreateInfo* pBufferCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkBuffer* pBuffer,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && pBuffer && pAllocation);
+
+ if(pBufferCreateInfo->size == 0)
+ {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+
+ VMA_DEBUG_LOG("vmaCreateBuffer");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ *pBuffer = VK_NULL_HANDLE;
+ *pAllocation = VK_NULL_HANDLE;
+
+ // 1. Create VkBuffer.
+ VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)(
+ allocator->m_hDevice,
+ pBufferCreateInfo,
+ allocator->GetAllocationCallbacks(),
+ pBuffer);
+ if(res >= 0)
+ {
+ // 2. vkGetBufferMemoryRequirements.
+ VkMemoryRequirements vkMemReq = {};
+ bool requiresDedicatedAllocation = false;
+ bool prefersDedicatedAllocation = false;
+ allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq,
+ requiresDedicatedAllocation, prefersDedicatedAllocation);
+
+ // Make sure alignment requirements for specific buffer usages reported
+ // in Physical Device Properties are included in alignment reported by memory requirements.
+ if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) != 0)
+ {
+ VMA_ASSERT(vkMemReq.alignment %
+ allocator->m_PhysicalDeviceProperties.limits.minTexelBufferOffsetAlignment == 0);
+ }
+ if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) != 0)
+ {
+ VMA_ASSERT(vkMemReq.alignment %
+ allocator->m_PhysicalDeviceProperties.limits.minUniformBufferOffsetAlignment == 0);
+ }
+ if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) != 0)
+ {
+ VMA_ASSERT(vkMemReq.alignment %
+ allocator->m_PhysicalDeviceProperties.limits.minStorageBufferOffsetAlignment == 0);
+ }
+
+ // 3. Allocate memory using allocator.
+ res = allocator->AllocateMemory(
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ *pBuffer, // dedicatedBuffer
+ VK_NULL_HANDLE, // dedicatedImage
+ *pAllocationCreateInfo,
+ VMA_SUBALLOCATION_TYPE_BUFFER,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordCreateBuffer(
+ allocator->GetCurrentFrameIndex(),
+ *pBufferCreateInfo,
+ *pAllocationCreateInfo,
+ *pAllocation);
+ }
+#endif
+
+ if(res >= 0)
+ {
+ // 3. Bind buffer with memory.
+ if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)
+ {
+ res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL);
+ }
+ if(res >= 0)
+ {
+ // All steps succeeded.
+ #if VMA_STATS_STRING_ENABLED
+ (*pAllocation)->InitBufferImageUsage(pBufferCreateInfo->usage);
+ #endif
+ if(pAllocationInfo != VMA_NULL)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return VK_SUCCESS;
+ }
+ allocator->FreeMemory(
+ 1, // allocationCount
+ pAllocation);
+ *pAllocation = VK_NULL_HANDLE;
+ (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());
+ *pBuffer = VK_NULL_HANDLE;
+ return res;
+ }
+ (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());
+ *pBuffer = VK_NULL_HANDLE;
+ return res;
+ }
+ return res;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(
+ VmaAllocator allocator,
+ VkBuffer buffer,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator);
+
+ if(buffer == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE)
+ {
+ return;
+ }
+
+ VMA_DEBUG_LOG("vmaDestroyBuffer");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordDestroyBuffer(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ if(buffer != VK_NULL_HANDLE)
+ {
+ (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, buffer, allocator->GetAllocationCallbacks());
+ }
+
+ if(allocation != VK_NULL_HANDLE)
+ {
+ allocator->FreeMemory(
+ 1, // allocationCount
+ &allocation);
+ }
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
+ VmaAllocator allocator,
+ const VkImageCreateInfo* pImageCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkImage* pImage,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && pImageCreateInfo && pAllocationCreateInfo && pImage && pAllocation);
+
+ if(pImageCreateInfo->extent.width == 0 ||
+ pImageCreateInfo->extent.height == 0 ||
+ pImageCreateInfo->extent.depth == 0 ||
+ pImageCreateInfo->mipLevels == 0 ||
+ pImageCreateInfo->arrayLayers == 0)
+ {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+
+ VMA_DEBUG_LOG("vmaCreateImage");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ *pImage = VK_NULL_HANDLE;
+ *pAllocation = VK_NULL_HANDLE;
+
+ // 1. Create VkImage.
+ VkResult res = (*allocator->GetVulkanFunctions().vkCreateImage)(
+ allocator->m_hDevice,
+ pImageCreateInfo,
+ allocator->GetAllocationCallbacks(),
+ pImage);
+ if(res >= 0)
+ {
+ VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ?
+ VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL :
+ VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR;
+
+ // 2. Allocate memory using allocator.
+ VkMemoryRequirements vkMemReq = {};
+ bool requiresDedicatedAllocation = false;
+ bool prefersDedicatedAllocation = false;
+ allocator->GetImageMemoryRequirements(*pImage, vkMemReq,
+ requiresDedicatedAllocation, prefersDedicatedAllocation);
+
+ res = allocator->AllocateMemory(
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ VK_NULL_HANDLE, // dedicatedBuffer
+ *pImage, // dedicatedImage
+ *pAllocationCreateInfo,
+ suballocType,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordCreateImage(
+ allocator->GetCurrentFrameIndex(),
+ *pImageCreateInfo,
+ *pAllocationCreateInfo,
+ *pAllocation);
+ }
+#endif
+
+ if(res >= 0)
+ {
+ // 3. Bind image with memory.
+ if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)
+ {
+ res = allocator->BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL);
+ }
+ if(res >= 0)
+ {
+ // All steps succeeded.
+ #if VMA_STATS_STRING_ENABLED
+ (*pAllocation)->InitBufferImageUsage(pImageCreateInfo->usage);
+ #endif
+ if(pAllocationInfo != VMA_NULL)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return VK_SUCCESS;
+ }
+ allocator->FreeMemory(
+ 1, // allocationCount
+ pAllocation);
+ *pAllocation = VK_NULL_HANDLE;
+ (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks());
+ *pImage = VK_NULL_HANDLE;
+ return res;
+ }
+ (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks());
+ *pImage = VK_NULL_HANDLE;
+ return res;
+ }
+ return res;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
+ VmaAllocator allocator,
+ VkImage image,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator);
+
+ if(image == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE)
+ {
+ return;
+ }
+
+ VMA_DEBUG_LOG("vmaDestroyImage");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordDestroyImage(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ if(image != VK_NULL_HANDLE)
+ {
+ (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, image, allocator->GetAllocationCallbacks());
+ }
+ if(allocation != VK_NULL_HANDLE)
+ {
+ allocator->FreeMemory(
+ 1, // allocationCount
+ &allocation);
+ }
+}
+
+#endif // #ifdef VMA_IMPLEMENTATION
diff --git a/thirdparty/xatlas/LICENSE b/thirdparty/xatlas/LICENSE
index 94d0c60485..9e61e15fb7 100644
--- a/thirdparty/xatlas/LICENSE
+++ b/thirdparty/xatlas/LICENSE
@@ -1,14 +1,21 @@
-xatlas
-https://github.com/jpcy/xatlas
-Copyright (c) 2018 Jonathan Young
+MIT License
-thekla_atlas
-https://github.com/Thekla/thekla_atlas
-Copyright (c) 2013 Thekla, Inc
-Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
+Copyright (c) 2018-2019 Jonathan Young
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE. \ No newline at end of file
diff --git a/thirdparty/xatlas/xatlas.cpp b/thirdparty/xatlas/xatlas.cpp
index 56794211a6..b1cbeb980f 100644
--- a/thirdparty/xatlas/xatlas.cpp
+++ b/thirdparty/xatlas/xatlas.cpp
@@ -33,20 +33,19 @@ https://github.com/brandonpelfrey/Fast-BVH
MIT License
Copyright (c) 2012 Brandon Pelfrey
*/
-#include <algorithm>
-#include <atomic>
-#include <condition_variable>
-#include <mutex>
-#include <thread>
#include <assert.h>
#include <float.h> // FLT_MAX
#include <limits.h>
#include <math.h>
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
#define __STDC_LIMIT_MACROS
+#include "xatlas.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
-#include "xatlas.h"
#ifndef XA_DEBUG
#ifdef NDEBUG
@@ -71,7 +70,10 @@ Copyright (c) 2012 Brandon Pelfrey
#define XA_XSTR(x) XA_STR(x)
#ifndef XA_ASSERT
-#define XA_ASSERT(exp) if (!(exp)) { XA_PRINT_WARNING("\rASSERT: %s %s %d\n", XA_XSTR(exp), __FILE__, __LINE__); }
+#define XA_ASSERT(exp) \
+ if (!(exp)) { \
+ XA_PRINT_WARNING("\rASSERT: %s %s %d\n", XA_XSTR(exp), __FILE__, __LINE__); \
+ }
#endif
#ifndef XA_DEBUG_ASSERT
@@ -79,13 +81,13 @@ Copyright (c) 2012 Brandon Pelfrey
#endif
#ifndef XA_PRINT
-#define XA_PRINT(...) \
+#define XA_PRINT(...) \
if (xatlas::internal::s_print && xatlas::internal::s_printVerbose) \
xatlas::internal::s_print(__VA_ARGS__);
#endif
#ifndef XA_PRINT_WARNING
-#define XA_PRINT_WARNING(...) \
+#define XA_PRINT_WARNING(...) \
if (xatlas::internal::s_print) \
xatlas::internal::s_print(__VA_ARGS__);
#endif
@@ -114,39 +116,36 @@ Copyright (c) 2012 Brandon Pelfrey
#define XA_UNUSED(a) ((void)(a))
-#define XA_GROW_CHARTS_COPLANAR 1
#define XA_MERGE_CHARTS 1
#define XA_MERGE_CHARTS_MIN_NORMAL_DEVIATION 0.5f
#define XA_RECOMPUTE_CHARTS 1
-#define XA_SKIP_PARAMETERIZATION 0 // Use the orthogonal parameterization from segment::Atlas
#define XA_CLOSE_HOLES_CHECK_EDGE_INTERSECTION 0
+#define XA_FIX_INTERNAL_BOUNDARY_LOOPS 1
+#define XA_PRINT_CHART_WARNINGS 0
#define XA_DEBUG_HEAP 0
#define XA_DEBUG_SINGLE_CHART 0
#define XA_DEBUG_EXPORT_ATLAS_IMAGES 0
+#define XA_DEBUG_EXPORT_ATLAS_IMAGES_PER_CHART 0 // Export an atlas image after each chart is added.
+#define XA_DEBUG_EXPORT_BOUNDARY_GRID 0
+#define XA_DEBUG_EXPORT_TGA (XA_DEBUG_EXPORT_ATLAS_IMAGES || XA_DEBUG_EXPORT_BOUNDARY_GRID)
#define XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES 0
#define XA_DEBUG_EXPORT_OBJ_CHART_GROUPS 0
+#define XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS 0
#define XA_DEBUG_EXPORT_OBJ_CHARTS 0
#define XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION 0
#define XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR 0
-#define XA_DEBUG_EXPORT_OBJ_NOT_DISK 0
#define XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION 0
#define XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION 0
#define XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS 0
-#define XA_DEBUG_EXPORT_OBJ (0 \
- || XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES \
- || XA_DEBUG_EXPORT_OBJ_CHART_GROUPS \
- || XA_DEBUG_EXPORT_OBJ_CHARTS \
- || XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION \
- || XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR \
- || XA_DEBUG_EXPORT_OBJ_NOT_DISK \
- || XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION \
- || XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION \
- || XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS)
+#define XA_DEBUG_EXPORT_OBJ (0 || XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES || XA_DEBUG_EXPORT_OBJ_CHART_GROUPS || XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS || XA_DEBUG_EXPORT_OBJ_CHARTS || XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION || XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR || XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION || XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION || XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS)
#ifdef _MSC_VER
-#define XA_FOPEN(_file, _filename, _mode) { if (fopen_s(&_file, _filename, _mode) != 0) _file = NULL; }
+#define XA_FOPEN(_file, _filename, _mode) \
+ { \
+ if (fopen_s(&_file, _filename, _mode) != 0) _file = NULL; \
+ }
#define XA_SPRINTF(_buffer, _size, _format, ...) sprintf_s(_buffer, _size, _format, __VA_ARGS__)
#else
#define XA_FOPEN(_file, _filename, _mode) _file = fopen(_filename, _mode)
@@ -161,11 +160,13 @@ static FreeFunc s_free = free;
static PrintFunc s_print = printf;
static bool s_printVerbose = false;
-struct MemTag
-{
- enum
- {
+struct MemTag {
+ enum {
Default,
+ BitImage,
+ BVH,
+ FullVector,
+ Matrix,
Mesh,
MeshBoundaries,
MeshColocals,
@@ -174,13 +175,16 @@ struct MemTag
MeshNormals,
MeshPositions,
MeshTexcoords,
+ SegmentAtlasChartCandidates,
+ SegmentAtlasChartFaces,
+ SegmentAtlasMeshData,
+ SegmentAtlasPlanarRegions,
Count
};
};
#if XA_DEBUG_HEAP
-struct AllocHeader
-{
+struct AllocHeader {
size_t size;
const char *file;
int line;
@@ -192,12 +196,11 @@ struct AllocHeader
static std::mutex s_allocMutex;
static AllocHeader *s_allocRoot = nullptr;
-static size_t s_allocTotalSize = 0, s_allocPeakSize = 0, s_allocTotalTagSize[MemTag::Count] = { 0 }, s_allocPeakTagSize[MemTag::Count] = { 0 };
-static uint32_t s_allocId =0 ;
+static size_t s_allocTotalCount = 0, s_allocTotalSize = 0, s_allocPeakSize = 0, s_allocCount[MemTag::Count] = { 0 }, s_allocTotalTagSize[MemTag::Count] = { 0 }, s_allocPeakTagSize[MemTag::Count] = { 0 };
+static uint32_t s_allocId = 0;
static constexpr uint32_t kAllocRedzone = 0x12345678;
-static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line)
-{
+static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line) {
std::unique_lock<std::mutex> lock(s_allocMutex);
if (!size && !ptr)
return nullptr;
@@ -245,9 +248,11 @@ static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line
s_allocRoot = header;
header->next->prev = header;
}
+ s_allocTotalCount++;
s_allocTotalSize += size;
if (s_allocTotalSize > s_allocPeakSize)
s_allocPeakSize = s_allocTotalSize;
+ s_allocCount[tag]++;
s_allocTotalTagSize[tag] += size;
if (s_allocTotalTagSize[tag] > s_allocPeakTagSize[tag])
s_allocPeakTagSize[tag] = s_allocTotalTagSize[tag];
@@ -256,8 +261,7 @@ static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line
return newPtr + sizeof(AllocHeader);
}
-static void ReportLeaks()
-{
+static void ReportLeaks() {
printf("Checking for memory leaks...\n");
bool anyLeaks = false;
AllocHeader *header = s_allocRoot;
@@ -285,11 +289,15 @@ static void ReportLeaks()
s_allocTotalTagSize[i] = s_allocPeakTagSize[i] = 0;
}
-static void PrintMemoryUsage()
-{
+static void PrintMemoryUsage() {
+ XA_PRINT("Total allocations: %zu\n", s_allocTotalCount);
XA_PRINT("Memory usage: %0.2fMB current, %0.2fMB peak\n", internal::s_allocTotalSize / 1024.0f / 1024.0f, internal::s_allocPeakSize / 1024.0f / 1024.0f);
static const char *labels[] = { // Sync with MemTag
"Default",
+ "BitImage",
+ "BVH",
+ "FullVector",
+ "Matrix",
"Mesh",
"MeshBoundaries",
"MeshColocals",
@@ -297,18 +305,23 @@ static void PrintMemoryUsage()
"MeshIndices",
"MeshNormals",
"MeshPositions",
- "MeshTexcoords"
+ "MeshTexcoords",
+ "SegmentAtlasChartCandidates",
+ "SegmentAtlasChartFaces",
+ "SegmentAtlasMeshData",
+ "SegmentAtlasPlanarRegions"
};
for (int i = 0; i < MemTag::Count; i++) {
- XA_PRINT(" %s: %0.2fMB current, %0.2fMB peak\n", labels[i], internal::s_allocTotalTagSize[i] / 1024.0f / 1024.0f, internal::s_allocPeakTagSize[i] / 1024.0f / 1024.0f);
+ XA_PRINT(" %s: %zu allocations, %0.2fMB current, %0.2fMB peak\n", labels[i], internal::s_allocCount[i], internal::s_allocTotalTagSize[i] / 1024.0f / 1024.0f, internal::s_allocPeakTagSize[i] / 1024.0f / 1024.0f);
}
}
#define XA_PRINT_MEM_USAGE internal::PrintMemoryUsage();
#else
-static void *Realloc(void *ptr, size_t size, int /*tag*/, const char * /*file*/, int /*line*/)
-{
- if (ptr && size == 0 && s_free) {
+static void *Realloc(void *ptr, size_t size, int /*tag*/, const char * /*file*/, int /*line*/) {
+ if (size == 0 && !ptr)
+ return nullptr;
+ if (size == 0 && s_free) {
s_free(ptr);
return nullptr;
}
@@ -324,16 +337,16 @@ static void *Realloc(void *ptr, size_t size, int /*tag*/, const char * /*file*/,
#if XA_PROFILE
#define XA_PROFILE_START(var) const clock_t var##Start = clock();
#define XA_PROFILE_END(var) internal::s_profile.var += clock() - var##Start;
-#define XA_PROFILE_PRINT_AND_RESET(label, var) XA_PRINT("%s%.2f seconds (%g ms)\n", label, internal::clockToSeconds(internal::s_profile.var), internal::clockToMs(internal::s_profile.var)); internal::s_profile.var = 0;
+#define XA_PROFILE_PRINT_AND_RESET(label, var) \
+ XA_PRINT("%s%.2f seconds (%g ms)\n", label, internal::clockToSeconds(internal::s_profile.var), internal::clockToMs(internal::s_profile.var)); \
+ internal::s_profile.var = 0;
-struct ProfileData
-{
+struct ProfileData {
clock_t addMeshReal;
clock_t addMeshCopyData;
std::atomic<clock_t> addMeshThread;
std::atomic<clock_t> addMeshCreateColocals;
std::atomic<clock_t> addMeshCreateFaceGroups;
- std::atomic<clock_t> addMeshCreateBoundaries;
std::atomic<clock_t> addMeshCreateChartGroupsReal;
std::atomic<clock_t> addMeshCreateChartGroupsThread;
clock_t computeChartsReal;
@@ -362,20 +375,17 @@ struct ProfileData
clock_t packChartsRasterize;
clock_t packChartsDilate;
clock_t packChartsFindLocation;
- std::atomic<clock_t> packChartsFindLocationThread;
clock_t packChartsBlit;
clock_t buildOutputMeshes;
};
static ProfileData s_profile;
-static double clockToMs(clock_t c)
-{
+static double clockToMs(clock_t c) {
return c * 1000.0 / CLOCKS_PER_SEC;
}
-static double clockToSeconds(clock_t c)
-{
+static double clockToSeconds(clock_t c) {
return c / (double)CLOCKS_PER_SEC;
}
#else
@@ -386,95 +396,80 @@ static double clockToSeconds(clock_t c)
static constexpr float kPi = 3.14159265358979323846f;
static constexpr float kPi2 = 6.28318530717958647692f;
+static constexpr float kPi4 = 12.56637061435917295384f;
static constexpr float kEpsilon = 0.0001f;
static constexpr float kAreaEpsilon = FLT_EPSILON;
static constexpr float kNormalEpsilon = 0.001f;
-static int align(int x, int a)
-{
+static int align(int x, int a) {
return (x + a - 1) & ~(a - 1);
}
template <typename T>
-static T max(const T &a, const T &b)
-{
+static T max(const T &a, const T &b) {
return a > b ? a : b;
}
template <typename T>
-static T min(const T &a, const T &b)
-{
+static T min(const T &a, const T &b) {
return a < b ? a : b;
}
template <typename T>
-static T max3(const T &a, const T &b, const T &c)
-{
+static T max3(const T &a, const T &b, const T &c) {
return max(a, max(b, c));
}
/// Return the maximum of the three arguments.
template <typename T>
-static T min3(const T &a, const T &b, const T &c)
-{
+static T min3(const T &a, const T &b, const T &c) {
return min(a, min(b, c));
}
/// Clamp between two values.
template <typename T>
-static T clamp(const T &x, const T &a, const T &b)
-{
+static T clamp(const T &x, const T &a, const T &b) {
return min(max(x, a), b);
}
template <typename T>
-static void swap(T &a, T &b)
-{
- T temp;
- temp = a;
+static void swap(T &a, T &b) {
+ T temp = a;
a = b;
b = temp;
- temp = T();
}
-union FloatUint32
-{
+union FloatUint32 {
float f;
uint32_t u;
};
-static bool isFinite(float f)
-{
+static bool isFinite(float f) {
FloatUint32 fu;
fu.f = f;
return fu.u != 0x7F800000u && fu.u != 0x7F800001u;
}
-static bool isNan(float f)
-{
+static bool isNan(float f) {
return f != f;
}
// Robust floating point comparisons:
// http://realtimecollisiondetection.net/blog/?p=89
-static bool equal(const float f0, const float f1, const float epsilon)
-{
+static bool equal(const float f0, const float f1, const float epsilon) {
//return fabs(f0-f1) <= epsilon;
return fabs(f0 - f1) <= epsilon * max3(1.0f, fabsf(f0), fabsf(f1));
}
-static int ftoi_ceil(float val)
-{
+static int ftoi_ceil(float val) {
return (int)ceilf(val);
}
-static bool isZero(const float f, const float epsilon)
-{
+static bool isZero(const float f, const float epsilon) {
return fabs(f) <= epsilon;
}
-static float square(float f)
-{
+static float square(float f) {
return f * f;
}
@@ -484,9 +479,8 @@ static float square(float f)
* @note isPowerOfTwo(x) == true -> nextPowerOfTwo(x) == x
* @note nextPowerOfTwo(x) = 2 << log2(x-1)
*/
-static uint32_t nextPowerOfTwo(uint32_t x)
-{
- XA_DEBUG_ASSERT( x != 0 );
+static uint32_t nextPowerOfTwo(uint32_t x) {
+ XA_DEBUG_ASSERT(x != 0);
// On modern CPUs this is supposed to be as fast as using the bsr instruction.
x--;
x |= x >> 1;
@@ -497,65 +491,59 @@ static uint32_t nextPowerOfTwo(uint32_t x)
return x + 1;
}
-static uint32_t sdbmHash(const void *data_in, uint32_t size, uint32_t h = 5381)
-{
- const uint8_t *data = (const uint8_t *) data_in;
+static uint32_t sdbmHash(const void *data_in, uint32_t size, uint32_t h = 5381) {
+ const uint8_t *data = (const uint8_t *)data_in;
uint32_t i = 0;
while (i < size) {
- h = (h << 16) + (h << 6) - h + (uint32_t ) data[i++];
+ h = (h << 16) + (h << 6) - h + (uint32_t)data[i++];
}
return h;
}
template <typename T>
-static uint32_t hash(const T &t, uint32_t h = 5381)
-{
+static uint32_t hash(const T &t, uint32_t h = 5381) {
return sdbmHash(&t, sizeof(T), h);
}
// Functors for hash table:
-template <typename Key> struct Hash
-{
+template <typename Key>
+struct Hash {
uint32_t operator()(const Key &k) const { return hash(k); }
};
-template <typename Key> struct Equal
-{
+template <typename Key>
+struct Equal {
bool operator()(const Key &k0, const Key &k1) const { return k0 == k1; }
};
-class Vector2
-{
+class Vector2 {
public:
Vector2() {}
- explicit Vector2(float f) : x(f), y(f) {}
- Vector2(float x, float y): x(x), y(y) {}
+ explicit Vector2(float f) :
+ x(f), y(f) {}
+ Vector2(float x, float y) :
+ x(x), y(y) {}
- Vector2 operator-() const
- {
+ Vector2 operator-() const {
return Vector2(-x, -y);
}
- void operator+=(const Vector2 &v)
- {
+ void operator+=(const Vector2 &v) {
x += v.x;
y += v.y;
}
- void operator-=(const Vector2 &v)
- {
+ void operator-=(const Vector2 &v) {
x -= v.x;
y -= v.y;
}
- void operator*=(float s)
- {
+ void operator*=(float s) {
x *= s;
y *= s;
}
- void operator*=(const Vector2 &v)
- {
+ void operator*=(const Vector2 &v) {
x *= v.x;
y *= v.y;
}
@@ -563,13 +551,11 @@ public:
float x, y;
};
-static bool operator==(const Vector2 &a, const Vector2 &b)
-{
+static bool operator==(const Vector2 &a, const Vector2 &b) {
return a.x == b.x && a.y == b.y;
}
-static bool operator!=(const Vector2 &a, const Vector2 &b)
-{
+static bool operator!=(const Vector2 &a, const Vector2 &b) {
return a.x != b.x || a.y != b.y;
}
@@ -578,40 +564,33 @@ static bool operator!=(const Vector2 &a, const Vector2 &b)
return Vector2(a.x + b.x, a.y + b.y);
}*/
-static Vector2 operator-(const Vector2 &a, const Vector2 &b)
-{
+static Vector2 operator-(const Vector2 &a, const Vector2 &b) {
return Vector2(a.x - b.x, a.y - b.y);
}
-static Vector2 operator*(const Vector2 &v, float s)
-{
+static Vector2 operator*(const Vector2 &v, float s) {
return Vector2(v.x * s, v.y * s);
}
-static float dot(const Vector2 &a, const Vector2 &b)
-{
+static float dot(const Vector2 &a, const Vector2 &b) {
return a.x * b.x + a.y * b.y;
}
-static float lengthSquared(const Vector2 &v)
-{
+static float lengthSquared(const Vector2 &v) {
return v.x * v.x + v.y * v.y;
}
-static float length(const Vector2 &v)
-{
+static float length(const Vector2 &v) {
return sqrtf(lengthSquared(v));
}
#if XA_DEBUG
-static bool isNormalized(const Vector2 &v, float epsilon = kNormalEpsilon)
-{
+static bool isNormalized(const Vector2 &v, float epsilon = kNormalEpsilon) {
return equal(length(v), 1, epsilon);
}
#endif
-static Vector2 normalize(const Vector2 &v, float epsilon)
-{
+static Vector2 normalize(const Vector2 &v, float epsilon) {
float l = length(v);
XA_DEBUG_ASSERT(!isZero(l, epsilon));
XA_UNUSED(epsilon);
@@ -620,47 +599,44 @@ static Vector2 normalize(const Vector2 &v, float epsilon)
return n;
}
-static bool equal(const Vector2 &v1, const Vector2 &v2, float epsilon)
-{
+static Vector2 normalizeSafe(const Vector2 &v, const Vector2 &fallback, float epsilon) {
+ float l = length(v);
+ if (isZero(l, epsilon))
+ return fallback;
+ return v * (1.0f / l);
+}
+
+static bool equal(const Vector2 &v1, const Vector2 &v2, float epsilon) {
return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon);
}
-static Vector2 min(const Vector2 &a, const Vector2 &b)
-{
+static Vector2 min(const Vector2 &a, const Vector2 &b) {
return Vector2(min(a.x, b.x), min(a.y, b.y));
}
-static Vector2 max(const Vector2 &a, const Vector2 &b)
-{
+static Vector2 max(const Vector2 &a, const Vector2 &b) {
return Vector2(max(a.x, b.x), max(a.y, b.y));
}
-static bool isFinite(const Vector2 &v)
-{
+static bool isFinite(const Vector2 &v) {
return isFinite(v.x) && isFinite(v.y);
}
-// Note, this is the area scaled by 2!
-static float triangleArea(const Vector2 &v0, const Vector2 &v1)
-{
- return (v0.x * v1.y - v0.y * v1.x); // * 0.5f;
-}
-
-static float triangleArea(const Vector2 &a, const Vector2 &b, const Vector2 &c)
-{
+static float triangleArea(const Vector2 &a, const Vector2 &b, const Vector2 &c) {
// IC: While it may be appealing to use the following expression:
- //return (c.x * a.y + a.x * b.y + b.x * c.y - b.x * a.y - c.x * b.y - a.x * c.y); // * 0.5f;
+ //return (c.x * a.y + a.x * b.y + b.x * c.y - b.x * a.y - c.x * b.y - a.x * c.y) * 0.5f;
// That's actually a terrible idea. Small triangles far from the origin can end up producing fairly large floating point
// numbers and the results becomes very unstable and dependent on the order of the factors.
// Instead, it's preferable to subtract the vertices first, and multiply the resulting small values together. The result
// in this case is always much more accurate (as long as the triangle is small) and less dependent of the location of
// the triangle.
- //return ((a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x)); // * 0.5f;
- return triangleArea(a - c, b - c);
+ //return ((a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x)) * 0.5f;
+ const Vector2 v0 = a - c;
+ const Vector2 v1 = b - c;
+ return (v0.x * v1.y - v0.y * v1.x) * 0.5f;
}
-static bool linesIntersect(const Vector2 &a1, const Vector2 &a2, const Vector2 &b1, const Vector2 &b2, float epsilon)
-{
+static bool linesIntersect(const Vector2 &a1, const Vector2 &a2, const Vector2 &b1, const Vector2 &b2, float epsilon) {
const Vector2 v0 = a2 - a1;
const Vector2 v1 = b2 - b1;
const float denom = -v1.x * v0.y + v0.x * v1.y;
@@ -668,76 +644,70 @@ static bool linesIntersect(const Vector2 &a1, const Vector2 &a2, const Vector2 &
return false;
const float s = (-v0.y * (a1.x - b1.x) + v0.x * (a1.y - b1.y)) / denom;
if (s > epsilon && s < 1.0f - epsilon) {
- const float t = ( v1.x * (a1.y - b1.y) - v1.y * (a1.x - b1.x)) / denom;
+ const float t = (v1.x * (a1.y - b1.y) - v1.y * (a1.x - b1.x)) / denom;
return t > epsilon && t < 1.0f - epsilon;
}
return false;
}
-struct Vector2i
-{
+struct Vector2i {
Vector2i() {}
- Vector2i(int32_t x, int32_t y) : x(x), y(y) {}
+ Vector2i(int32_t x, int32_t y) :
+ x(x), y(y) {}
int32_t x, y;
};
-class Vector3
-{
+class Vector3 {
public:
Vector3() {}
- explicit Vector3(float f) : x(f), y(f), z(f) {}
- Vector3(float x, float y, float z) : x(x), y(y), z(z) {}
- Vector3(const Vector2 &v, float z) : x(v.x), y(v.y), z(z) {}
-
- Vector2 xy() const
- {
+ explicit Vector3(float f) :
+ x(f), y(f), z(f) {}
+ Vector3(float x, float y, float z) :
+ x(x), y(y), z(z) {}
+ Vector3(const Vector2 &v, float z) :
+ x(v.x), y(v.y), z(z) {}
+
+ Vector2 xy() const {
return Vector2(x, y);
}
- Vector3 operator-() const
- {
+ Vector3 operator-() const {
return Vector3(-x, -y, -z);
}
- void operator+=(const Vector3 &v)
- {
+ void operator+=(const Vector3 &v) {
x += v.x;
y += v.y;
z += v.z;
}
- void operator-=(const Vector3 &v)
- {
+ void operator-=(const Vector3 &v) {
x -= v.x;
y -= v.y;
z -= v.z;
}
- void operator*=(float s)
- {
+ void operator*=(float s) {
x *= s;
y *= s;
z *= s;
}
- void operator/=(float s)
- {
+ void operator/=(float s) {
float is = 1.0f / s;
x *= is;
y *= is;
z *= is;
}
- void operator*=(const Vector3 &v)
- {
+ void operator*=(const Vector3 &v) {
x *= v.x;
y *= v.y;
z *= v.z;
}
- void operator/=(const Vector3 &v)
- {
+ void operator/=(const Vector3 &v) {
x /= v.x;
y /= v.y;
z /= v.z;
@@ -746,58 +716,43 @@ public:
float x, y, z;
};
-static bool operator!=(const Vector3 &a, const Vector3 &b)
-{
- return a.x != b.x || a.y != b.y || a.z != b.z;
-}
-
-static Vector3 operator+(const Vector3 &a, const Vector3 &b)
-{
+static Vector3 operator+(const Vector3 &a, const Vector3 &b) {
return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
}
-static Vector3 operator-(const Vector3 &a, const Vector3 &b)
-{
+static Vector3 operator-(const Vector3 &a, const Vector3 &b) {
return Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
}
-static Vector3 cross(const Vector3 &a, const Vector3 &b)
-{
+static Vector3 cross(const Vector3 &a, const Vector3 &b) {
return Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
}
-static Vector3 operator*(const Vector3 &v, float s)
-{
+static Vector3 operator*(const Vector3 &v, float s) {
return Vector3(v.x * s, v.y * s, v.z * s);
}
-static Vector3 operator/(const Vector3 &v, float s)
-{
+static Vector3 operator/(const Vector3 &v, float s) {
return v * (1.0f / s);
}
-static float dot(const Vector3 &a, const Vector3 &b)
-{
+static float dot(const Vector3 &a, const Vector3 &b) {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
-static float lengthSquared(const Vector3 &v)
-{
+static float lengthSquared(const Vector3 &v) {
return v.x * v.x + v.y * v.y + v.z * v.z;
}
-static float length(const Vector3 &v)
-{
+static float length(const Vector3 &v) {
return sqrtf(lengthSquared(v));
}
-static bool isNormalized(const Vector3 &v, float epsilon = kNormalEpsilon)
-{
+static bool isNormalized(const Vector3 &v, float epsilon = kNormalEpsilon) {
return equal(length(v), 1, epsilon);
}
-static Vector3 normalize(const Vector3 &v, float epsilon)
-{
+static Vector3 normalize(const Vector3 &v, float epsilon) {
float l = length(v);
XA_DEBUG_ASSERT(!isZero(l, epsilon));
XA_UNUSED(epsilon);
@@ -806,8 +761,7 @@ static Vector3 normalize(const Vector3 &v, float epsilon)
return n;
}
-static Vector3 normalizeSafe(const Vector3 &v, const Vector3 &fallback, float epsilon)
-{
+static Vector3 normalizeSafe(const Vector3 &v, const Vector3 &fallback, float epsilon) {
float l = length(v);
if (isZero(l, epsilon)) {
return fallback;
@@ -815,45 +769,59 @@ static Vector3 normalizeSafe(const Vector3 &v, const Vector3 &fallback, float ep
return v * (1.0f / l);
}
-static bool equal(const Vector3 &v0, const Vector3 &v1, float epsilon)
-{
+static bool equal(const Vector3 &v0, const Vector3 &v1, float epsilon) {
return fabs(v0.x - v1.x) <= epsilon && fabs(v0.y - v1.y) <= epsilon && fabs(v0.z - v1.z) <= epsilon;
}
-static Vector3 min(const Vector3 &a, const Vector3 &b)
-{
+static Vector3 min(const Vector3 &a, const Vector3 &b) {
return Vector3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
}
-static Vector3 max(const Vector3 &a, const Vector3 &b)
-{
+static Vector3 max(const Vector3 &a, const Vector3 &b) {
return Vector3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
}
#if XA_DEBUG
-bool isFinite(const Vector3 &v)
-{
+bool isFinite(const Vector3 &v) {
return isFinite(v.x) && isFinite(v.y) && isFinite(v.z);
}
#endif
-struct Plane
-{
+struct Extents2 {
+ Vector2 min, max;
+
+ void reset() {
+ min.x = min.y = FLT_MAX;
+ max.x = max.y = -FLT_MAX;
+ }
+
+ void add(Vector2 p) {
+ min = xatlas::internal::min(min, p);
+ max = xatlas::internal::max(max, p);
+ }
+
+ Vector2 midpoint() const {
+ return Vector2(min.x + (max.x - min.x) * 0.5f, min.y + (max.y - min.y) * 0.5f);
+ }
+
+ static bool intersect(Extents2 e1, Extents2 e2) {
+ return e1.min.x <= e2.max.x && e1.max.x >= e2.min.x && e1.min.y <= e2.max.y && e1.max.y >= e2.min.y;
+ }
+};
+
+struct Plane {
Plane() = default;
-
- Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3)
- {
+
+ Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3) {
normal = cross(p2 - p1, p3 - p1);
dist = dot(normal, p1);
}
- float distance(const Vector3 &p) const
- {
+ float distance(const Vector3 &p) const {
return dot(normal, p) - dist;
}
- void normalize()
- {
+ void normalize() {
const float len = length(normal);
if (len > 0.0f) {
const float il = 1.0f / len;
@@ -866,8 +834,7 @@ struct Plane
float dist;
};
-static bool lineIntersectsPoint(const Vector3 &point, const Vector3 &lineStart, const Vector3 &lineEnd, float *t, float epsilon)
-{
+static bool lineIntersectsPoint(const Vector3 &point, const Vector3 &lineStart, const Vector3 &lineEnd, float *t, float epsilon) {
float tt;
if (!t)
t = &tt;
@@ -884,22 +851,19 @@ static bool lineIntersectsPoint(const Vector3 &point, const Vector3 &lineStart,
return *t > kEpsilon && *t < 1.0f - kEpsilon;
}
-static bool sameSide(const Vector3 &p1, const Vector3 &p2, const Vector3 &a, const Vector3 &b)
-{
+static bool sameSide(const Vector3 &p1, const Vector3 &p2, const Vector3 &a, const Vector3 &b) {
const Vector3 &ab = b - a;
return dot(cross(ab, p1 - a), cross(ab, p2 - a)) >= 0.0f;
}
// http://blackpawn.com/texts/pointinpoly/default.html
-static bool pointInTriangle(const Vector3 &p, const Vector3 &a, const Vector3 &b, const Vector3 &c)
-{
+static bool pointInTriangle(const Vector3 &p, const Vector3 &a, const Vector3 &b, const Vector3 &c) {
return sameSide(p, a, b, c) && sameSide(p, b, a, c) && sameSide(p, c, a, b);
}
#if XA_CLOSE_HOLES_CHECK_EDGE_INTERSECTION
// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
-static bool rayIntersectsTriangle(const Vector3 &rayOrigin, const Vector3 &rayDir, const Vector3 *tri, float *t)
-{
+static bool rayIntersectsTriangle(const Vector3 &rayOrigin, const Vector3 &rayDir, const Vector3 *tri, float *t) {
*t = 0.0f;
const Vector3 &edge1 = tri[1] - tri[0];
const Vector3 &edge2 = tri[2] - tri[0];
@@ -926,50 +890,47 @@ static bool rayIntersectsTriangle(const Vector3 &rayOrigin, const Vector3 &rayDi
#endif
// From Fast-BVH
-struct AABB
-{
- AABB() : min(FLT_MAX, FLT_MAX, FLT_MAX), max(-FLT_MAX, -FLT_MAX, -FLT_MAX) {}
- AABB(const Vector3 &min, const Vector3 &max) : min(min), max(max) { }
- AABB(const Vector3 &p, float radius = 0.0f) : min(p), max(p) { if (radius > 0.0f) expand(radius); }
+struct AABB {
+ AABB() :
+ min(FLT_MAX, FLT_MAX, FLT_MAX), max(-FLT_MAX, -FLT_MAX, -FLT_MAX) {}
+ AABB(const Vector3 &min, const Vector3 &max) :
+ min(min), max(max) {}
+ AABB(const Vector3 &p, float radius = 0.0f) :
+ min(p), max(p) {
+ if (radius > 0.0f) expand(radius);
+ }
- bool intersect(const AABB &other) const
- {
+ bool intersect(const AABB &other) const {
return min.x <= other.max.x && max.x >= other.min.x && min.y <= other.max.y && max.y >= other.min.y && min.z <= other.max.z && max.z >= other.min.z;
}
- void expandToInclude(const Vector3 &p)
- {
+ void expandToInclude(const Vector3 &p) {
min = internal::min(min, p);
max = internal::max(max, p);
}
- void expandToInclude(const AABB &aabb)
- {
+ void expandToInclude(const AABB &aabb) {
min = internal::min(min, aabb.min);
max = internal::max(max, aabb.max);
}
- void expand(float amount)
- {
+ void expand(float amount) {
min -= Vector3(amount);
max += Vector3(amount);
}
- Vector3 centroid() const
- {
+ Vector3 centroid() const {
return min + (max - min) * 0.5f;
}
- uint32_t maxDimension() const
- {
+ uint32_t maxDimension() const {
const Vector3 extent = max - min;
uint32_t result = 0;
if (extent.y > extent.x) {
result = 1;
if (extent.z > extent.y)
result = 2;
- }
- else if(extent.z > extent.x)
+ } else if (extent.z > extent.x)
result = 2;
return result;
}
@@ -977,29 +938,36 @@ struct AABB
Vector3 min, max;
};
-struct ArrayBase
-{
- ArrayBase(uint32_t elementSize, int memTag = MemTag::Default) : buffer(nullptr), elementSize(elementSize), size(0), capacity(0), memTag(memTag) {}
+struct ArrayBase {
+ ArrayBase(uint32_t elementSize, int memTag = MemTag::Default) :
+ buffer(nullptr), elementSize(elementSize), size(0), capacity(0) {
+#if XA_DEBUG_HEAP
+ this->memTag = memTag;
+#else
+ XA_UNUSED(memTag);
+#endif
+ }
- ~ArrayBase()
- {
+ ~ArrayBase() {
XA_FREE(buffer);
}
- XA_INLINE void clear()
- {
+ XA_INLINE void clear() {
size = 0;
}
- void copyTo(ArrayBase &other) const
- {
+ void copyFrom(const uint8_t *data, uint32_t length) {
+ resize(length, true);
+ memcpy(buffer, data, length * elementSize);
+ }
+
+ void copyTo(ArrayBase &other) const {
XA_DEBUG_ASSERT(elementSize == other.elementSize);
other.resize(size, true);
memcpy(other.buffer, buffer, size * elementSize);
}
- void destroy()
- {
+ void destroy() {
size = 0;
XA_FREE(buffer);
buffer = nullptr;
@@ -1008,8 +976,7 @@ struct ArrayBase
}
// Insert the given element at the given index shifting all the elements up.
- void insertAt(uint32_t index, const uint8_t *value)
- {
+ void insertAt(uint32_t index, const uint8_t *value) {
XA_DEBUG_ASSERT(index >= 0 && index <= size);
resize(size + 1, false);
if (index < size - 1)
@@ -1017,49 +984,54 @@ struct ArrayBase
memcpy(&buffer[index * elementSize], value, elementSize);
}
- void moveTo(ArrayBase &other)
- {
+ void moveTo(ArrayBase &other) {
XA_DEBUG_ASSERT(elementSize == other.elementSize);
other.destroy();
other.buffer = buffer;
other.elementSize = elementSize;
other.size = size;
other.capacity = capacity;
+#if XA_DEBUG_HEAP
other.memTag = memTag;
+#endif
buffer = nullptr;
elementSize = size = capacity = 0;
}
- void pop_back()
- {
+ void pop_back() {
XA_DEBUG_ASSERT(size > 0);
resize(size - 1, false);
}
- void push_back(const uint8_t *value)
- {
+ void push_back(const uint8_t *value) {
XA_DEBUG_ASSERT(value < buffer || value >= buffer + size);
resize(size + 1, false);
memcpy(&buffer[(size - 1) * elementSize], value, elementSize);
}
+ void push_back(const ArrayBase &other) {
+ XA_DEBUG_ASSERT(elementSize == other.elementSize);
+ if (other.size == 0)
+ return;
+ const uint32_t oldSize = size;
+ resize(size + other.size, false);
+ memcpy(buffer + oldSize * elementSize, other.buffer, other.size * other.elementSize);
+ }
+
// Remove the element at the given index. This is an expensive operation!
- void removeAt(uint32_t index)
- {
+ void removeAt(uint32_t index) {
XA_DEBUG_ASSERT(index >= 0 && index < size);
if (size != 1)
memmove(buffer + elementSize * index, buffer + elementSize * (index + 1), elementSize * (size - 1 - index));
size--;
}
- void reserve(uint32_t desiredSize)
- {
+ void reserve(uint32_t desiredSize) {
if (desiredSize > capacity)
setArrayCapacity(desiredSize);
}
- void resize(uint32_t newSize, bool exact)
- {
+ void resize(uint32_t newSize, bool exact) {
size = newSize;
if (size > capacity) {
// First allocation is always exact. Otherwise, following allocations grow array to 150% of desired size.
@@ -1072,8 +1044,7 @@ struct ArrayBase
}
}
- void setArrayCapacity(uint32_t newCapacity)
- {
+ void setArrayCapacity(uint32_t newCapacity) {
XA_DEBUG_ASSERT(newCapacity >= size);
if (newCapacity == 0) {
// free the buffer.
@@ -1083,46 +1054,65 @@ struct ArrayBase
}
} else {
// realloc the buffer
+#if XA_DEBUG_HEAP
buffer = XA_REALLOC_SIZE(memTag, buffer, newCapacity * elementSize);
+#else
+ buffer = XA_REALLOC_SIZE(MemTag::Default, buffer, newCapacity * elementSize);
+#endif
}
capacity = newCapacity;
}
+#if XA_DEBUG_HEAP
+ void setMemTag(int memTag) {
+ this->memTag = memTag;
+ }
+#endif
+
uint8_t *buffer;
uint32_t elementSize;
uint32_t size;
uint32_t capacity;
+#if XA_DEBUG_HEAP
int memTag;
+#endif
};
-template<typename T>
-class Array
-{
+template <typename T>
+class Array {
public:
- Array(int memTag = MemTag::Default) : m_base(sizeof(T), memTag) {}
- Array(const Array&) = delete;
- const Array &operator=(const Array &) = delete;
+ Array(int memTag = MemTag::Default) :
+ m_base(sizeof(T), memTag) {}
+ Array(const Array &) = delete;
+ Array &operator=(const Array &) = delete;
- XA_INLINE const T &operator[](uint32_t index) const
- {
+ XA_INLINE const T &operator[](uint32_t index) const {
XA_DEBUG_ASSERT(index < m_base.size);
return ((const T *)m_base.buffer)[index];
}
- XA_INLINE T &operator[](uint32_t index)
- {
+ XA_INLINE T &operator[](uint32_t index) {
XA_DEBUG_ASSERT(index < m_base.size);
return ((T *)m_base.buffer)[index];
}
- XA_INLINE const T &back() const
- {
+ XA_INLINE const T &back() const {
XA_DEBUG_ASSERT(!isEmpty());
return ((const T *)m_base.buffer)[m_base.size - 1];
}
XA_INLINE T *begin() { return (T *)m_base.buffer; }
XA_INLINE void clear() { m_base.clear(); }
+
+ bool contains(const T &value) const {
+ for (uint32_t i = 0; i < m_base.size; i++) {
+ if (((const T *)m_base.buffer)[i] == value)
+ return true;
+ }
+ return false;
+ }
+
+ void copyFrom(const T *data, uint32_t length) { m_base.copyFrom((const uint8_t *)data, length); }
void copyTo(Array &other) const { m_base.copyTo(other.m_base); }
XA_INLINE const T *data() const { return (const T *)m_base.buffer; }
XA_INLINE T *data() { return (T *)m_base.buffer; }
@@ -1131,18 +1121,32 @@ public:
void insertAt(uint32_t index, const T &value) { m_base.insertAt(index, (const uint8_t *)&value); }
void moveTo(Array &other) { m_base.moveTo(other.m_base); }
void push_back(const T &value) { m_base.push_back((const uint8_t *)&value); }
+ void push_back(const Array &other) { m_base.push_back(other.m_base); }
void pop_back() { m_base.pop_back(); }
void removeAt(uint32_t index) { m_base.removeAt(index); }
void reserve(uint32_t desiredSize) { m_base.reserve(desiredSize); }
void resize(uint32_t newSize) { m_base.resize(newSize, true); }
- void setAll(const T &value)
- {
+ void runCtors() {
+ for (uint32_t i = 0; i < m_base.size; i++)
+ new (&((T *)m_base.buffer)[i]) T;
+ }
+
+ void runDtors() {
+ for (uint32_t i = 0; i < m_base.size; i++)
+ ((T *)m_base.buffer)[i].~T();
+ }
+
+ void setAll(const T &value) {
auto buffer = (T *)m_base.buffer;
for (uint32_t i = 0; i < m_base.size; i++)
buffer[i] = value;
}
+#if XA_DEBUG_HEAP
+ void setMemTag(int memTag) { m_base.setMemTag(memTag); }
+#endif
+
XA_INLINE uint32_t size() const { return m_base.size; }
XA_INLINE void zeroOutMemory() { memset(m_base.buffer, 0, m_base.elementSize * m_base.size); }
@@ -1150,11 +1154,47 @@ private:
ArrayBase m_base;
};
+template <typename T>
+struct ArrayView {
+ ArrayView(Array<T> &a) :
+ data(a.data()), length(a.size()) {}
+ ArrayView(T *data, uint32_t length) :
+ data(data), length(length) {}
+ ArrayView &operator=(Array<T> &a) {
+ data = a.data();
+ length = a.size();
+ return *this;
+ }
+ XA_INLINE const T &operator[](uint32_t index) const {
+ XA_DEBUG_ASSERT(index < length);
+ return data[index];
+ }
+ T *data;
+ uint32_t length;
+};
+
+template <typename T>
+struct ConstArrayView {
+ ConstArrayView(const Array<T> &a) :
+ data(a.data()), length(a.size()) {}
+ ConstArrayView(const T *data, uint32_t length) :
+ data(data), length(length) {}
+ ConstArrayView &operator=(const Array<T> &a) {
+ data = a.data();
+ length = a.size();
+ return *this;
+ }
+ XA_INLINE const T &operator[](uint32_t index) const {
+ XA_DEBUG_ASSERT(index < length);
+ return data[index];
+ }
+ const T *data;
+ uint32_t length;
+};
+
/// Basis class to compute tangent space basis, ortogonalizations and to transform vectors from one space to another.
-struct Basis
-{
- XA_NODISCARD static Vector3 computeTangent(const Vector3 &normal)
- {
+struct Basis {
+ XA_NODISCARD static Vector3 computeTangent(const Vector3 &normal) {
XA_ASSERT(isNormalized(normal));
// Choose minimum axis.
Vector3 tangent;
@@ -1170,8 +1210,7 @@ struct Basis
return tangent;
}
- XA_NODISCARD static Vector3 computeBitangent(const Vector3 &normal, const Vector3 &tangent)
- {
+ XA_NODISCARD static Vector3 computeBitangent(const Vector3 &normal, const Vector3 &tangent) {
return cross(normal, tangent);
}
@@ -1181,77 +1220,64 @@ struct Basis
};
// Simple bit array.
-class BitArray
-{
+class BitArray {
public:
- BitArray() : m_size(0) {}
+ BitArray() :
+ m_size(0) {}
- BitArray(uint32_t sz)
- {
+ BitArray(uint32_t sz) {
resize(sz);
}
- void resize(uint32_t new_size)
- {
+ void resize(uint32_t new_size) {
m_size = new_size;
m_wordArray.resize((m_size + 31) >> 5);
}
- /// Get bit.
- bool bitAt(uint32_t b) const
- {
- XA_DEBUG_ASSERT( b < m_size );
- return (m_wordArray[b >> 5] & (1 << (b & 31))) != 0;
+ bool get(uint32_t index) const {
+ XA_DEBUG_ASSERT(index < m_size);
+ return (m_wordArray[index >> 5] & (1 << (index & 31))) != 0;
}
- // Set a bit.
- void setBitAt(uint32_t idx)
- {
- XA_DEBUG_ASSERT(idx < m_size);
- m_wordArray[idx >> 5] |= (1 << (idx & 31));
+ void set(uint32_t index) {
+ XA_DEBUG_ASSERT(index < m_size);
+ m_wordArray[index >> 5] |= (1 << (index & 31));
}
- // Clear all the bits.
- void clearAll()
- {
- memset(m_wordArray.data(), 0, m_wordArray.size() * sizeof(uint32_t));
+ void zeroOutMemory() {
+ m_wordArray.zeroOutMemory();
}
private:
- // Number of bits stored.
- uint32_t m_size;
-
- // Array of bits.
+ uint32_t m_size; // Number of bits stored.
Array<uint32_t> m_wordArray;
};
-class BitImage
-{
+class BitImage {
public:
- BitImage() : m_width(0), m_height(0), m_rowStride(0) {}
+ BitImage() :
+ m_width(0), m_height(0), m_rowStride(0), m_data(MemTag::BitImage) {}
- BitImage(uint32_t w, uint32_t h) : m_width(w), m_height(h)
- {
+ BitImage(uint32_t w, uint32_t h) :
+ m_width(w), m_height(h), m_data(MemTag::BitImage) {
m_rowStride = (m_width + 63) >> 6;
m_data.resize(m_rowStride * m_height);
m_data.zeroOutMemory();
}
BitImage(const BitImage &other) = delete;
- const BitImage &operator=(const BitImage &other) = delete;
+ BitImage &operator=(const BitImage &other) = delete;
uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; }
- void copyTo(BitImage &other)
- {
+ void copyTo(BitImage &other) {
other.m_width = m_width;
other.m_height = m_height;
other.m_rowStride = m_rowStride;
m_data.copyTo(other.m_data);
}
- void resize(uint32_t w, uint32_t h, bool discard)
- {
+ void resize(uint32_t w, uint32_t h, bool discard) {
const uint32_t rowStride = (w + 63) >> 6;
if (discard) {
m_data.resize(rowStride * h);
@@ -1275,28 +1301,24 @@ public:
m_rowStride = rowStride;
}
- bool bitAt(uint32_t x, uint32_t y) const
- {
+ bool get(uint32_t x, uint32_t y) const {
XA_DEBUG_ASSERT(x < m_width && y < m_height);
const uint32_t index = (x >> 6) + y * m_rowStride;
return (m_data[index] & (UINT64_C(1) << (uint64_t(x) & UINT64_C(63)))) != 0;
}
- void setBitAt(uint32_t x, uint32_t y)
- {
+ void set(uint32_t x, uint32_t y) {
XA_DEBUG_ASSERT(x < m_width && y < m_height);
const uint32_t index = (x >> 6) + y * m_rowStride;
m_data[index] |= UINT64_C(1) << (uint64_t(x) & UINT64_C(63));
- XA_DEBUG_ASSERT(bitAt(x, y));
+ XA_DEBUG_ASSERT(get(x, y));
}
- void clearAll()
- {
+ void zeroOutMemory() {
m_data.zeroOutMemory();
}
- bool canBlit(const BitImage &image, uint32_t offsetX, uint32_t offsetY) const
- {
+ bool canBlit(const BitImage &image, uint32_t offsetX, uint32_t offsetY) const {
for (uint32_t y = 0; y < image.m_height; y++) {
const uint32_t thisY = y + offsetY;
if (thisY >= m_height)
@@ -1320,30 +1342,29 @@ public:
return true;
}
- void dilate(uint32_t padding)
- {
+ void dilate(uint32_t padding) {
BitImage tmp(m_width, m_height);
for (uint32_t p = 0; p < padding; p++) {
- tmp.clearAll();
+ tmp.zeroOutMemory();
for (uint32_t y = 0; y < m_height; y++) {
for (uint32_t x = 0; x < m_width; x++) {
- bool b = bitAt(x, y);
+ bool b = get(x, y);
if (!b) {
if (x > 0) {
- b |= bitAt(x - 1, y);
- if (y > 0) b |= bitAt(x - 1, y - 1);
- if (y < m_height - 1) b |= bitAt(x - 1, y + 1);
+ b |= get(x - 1, y);
+ if (y > 0) b |= get(x - 1, y - 1);
+ if (y < m_height - 1) b |= get(x - 1, y + 1);
}
- if (y > 0) b |= bitAt(x, y - 1);
- if (y < m_height - 1) b |= bitAt(x, y + 1);
+ if (y > 0) b |= get(x, y - 1);
+ if (y < m_height - 1) b |= get(x, y + 1);
if (x < m_width - 1) {
- b |= bitAt(x + 1, y);
- if (y > 0) b |= bitAt(x + 1, y - 1);
- if (y < m_height - 1) b |= bitAt(x + 1, y + 1);
+ b |= get(x + 1, y);
+ if (y > 0) b |= get(x + 1, y - 1);
+ if (y < m_height - 1) b |= get(x + 1, y + 1);
}
}
if (b)
- tmp.setBitAt(x, y);
+ tmp.set(x, y);
}
}
tmp.m_data.copyTo(m_data);
@@ -1358,11 +1379,10 @@ private:
};
// From Fast-BVH
-class BVH
-{
+class BVH {
public:
- BVH(const Array<AABB> &objectAabbs, uint32_t leafSize = 4)
- {
+ BVH(const Array<AABB> &objectAabbs, uint32_t leafSize = 4) :
+ m_objectIds(MemTag::BVH), m_nodes(MemTag::BVH) {
m_objectAabbs = &objectAabbs;
if (m_objectAabbs->isEmpty())
return;
@@ -1382,7 +1402,7 @@ public:
Node node;
m_nodes.reserve(objectAabbs.size() * 2);
uint32_t nNodes = 0;
- while(stackptr > 0) {
+ while (stackptr > 0) {
// Pop the next item off of the stack
const BuildEntry &bnode = todo[--stackptr];
const uint32_t start = bnode.start;
@@ -1395,7 +1415,7 @@ public:
// Calculate the bounding box for this node
AABB bb(objectAabbs[m_objectIds[start]]);
AABB bc(objectAabbs[m_objectIds[start]].centroid());
- for(uint32_t p = start + 1; p < end; ++p) {
+ for (uint32_t p = start + 1; p < end; ++p) {
bb.expandToInclude(objectAabbs[m_objectIds[p]]);
bc.expandToInclude(objectAabbs[m_objectIds[p]].centroid());
}
@@ -1411,7 +1431,7 @@ public:
m_nodes[bnode.parent].rightOffset--;
// When this is the second touch, this is the right child.
// The right child sets up the offset for the flat tree.
- if (m_nodes[bnode.parent].rightOffset == kTouchedTwice )
+ if (m_nodes[bnode.parent].rightOffset == kTouchedTwice)
m_nodes[bnode.parent].rightOffset = nNodes - 1 - bnode.parent;
}
// If this is a leaf, no need to subdivide.
@@ -1446,21 +1466,20 @@ public:
}
}
- void query(const AABB &queryAabb, Array<uint32_t> &result) const
- {
+ void query(const AABB &queryAabb, Array<uint32_t> &result) const {
result.clear();
// Working set
uint32_t todo[64];
int32_t stackptr = 0;
// "Push" on the root node to the working set
todo[stackptr] = 0;
- while(stackptr >= 0) {
+ while (stackptr >= 0) {
// Pop off the next node to work on.
const int ni = todo[stackptr--];
const Node &node = m_nodes[ni];
// Is leaf -> Intersect
if (node.rightOffset == 0) {
- for(uint32_t o = 0; o < node.nPrims; ++o) {
+ for (uint32_t o = 0; o < node.nPrims; ++o) {
const uint32_t obj = node.start + o;
if (queryAabb.intersect((*m_objectAabbs)[m_objectIds[obj]]))
result.push_back(m_objectIds[obj]);
@@ -1477,14 +1496,12 @@ public:
}
private:
- struct BuildEntry
- {
+ struct BuildEntry {
uint32_t parent; // If non-zero then this is the index of the parent. (used in offsets)
uint32_t start, end; // The range of objects in the object list covered by this node.
};
- struct Node
- {
+ struct Node {
AABB aabb;
uint32_t start, nPrims, rightOffset;
};
@@ -1494,11 +1511,115 @@ private:
Array<Node> m_nodes;
};
-class Fit
-{
-public:
- static Vector3 computeCentroid(int n, const Vector3 * points)
- {
+struct Fit {
+ static bool computeBasis(const Vector3 *points, uint32_t pointsCount, Basis *basis) {
+ if (computeLeastSquaresNormal(points, pointsCount, &basis->normal)) {
+ basis->tangent = Basis::computeTangent(basis->normal);
+ basis->bitangent = Basis::computeBitangent(basis->normal, basis->tangent);
+ return true;
+ }
+ return computeEigen(points, pointsCount, basis);
+ }
+
+private:
+ // Fit a plane to a collection of points.
+ // Fast, and accurate to within a few degrees.
+ // Returns None if the points do not span a plane.
+ // https://www.ilikebigbits.com/2015_03_04_plane_from_points.html
+ static bool computeLeastSquaresNormal(const Vector3 *points, uint32_t pointsCount, Vector3 *normal) {
+ XA_DEBUG_ASSERT(pointsCount >= 3);
+ if (pointsCount == 3) {
+ *normal = normalize(cross(points[2] - points[0], points[1] - points[0]), kEpsilon);
+ return true;
+ }
+ const float invN = 1.0f / float(pointsCount);
+ Vector3 centroid(0.0f);
+ for (uint32_t i = 0; i < pointsCount; i++)
+ centroid += points[i];
+ centroid *= invN;
+ // Calculate full 3x3 covariance matrix, excluding symmetries:
+ float xx = 0.0f, xy = 0.0f, xz = 0.0f, yy = 0.0f, yz = 0.0f, zz = 0.0f;
+ for (uint32_t i = 0; i < pointsCount; i++) {
+ Vector3 r = points[i] - centroid;
+ xx += r.x * r.x;
+ xy += r.x * r.y;
+ xz += r.x * r.z;
+ yy += r.y * r.y;
+ yz += r.y * r.z;
+ zz += r.z * r.z;
+ }
+#if 0
+ xx *= invN;
+ xy *= invN;
+ xz *= invN;
+ yy *= invN;
+ yz *= invN;
+ zz *= invN;
+ Vector3 weighted_dir(0.0f);
+ {
+ float det_x = yy * zz - yz * yz;
+ const Vector3 axis_dir(det_x, xz * yz - xy * zz, xy * yz - xz * yy);
+ float weight = det_x * det_x;
+ if (dot(weighted_dir, axis_dir) < 0.0f)
+ weight = -weight;
+ weighted_dir += axis_dir * weight;
+ }
+ {
+ float det_y = xx * zz - xz * xz;
+ const Vector3 axis_dir(xz * yz - xy * zz, det_y, xy * xz - yz * xx);
+ float weight = det_y * det_y;
+ if (dot(weighted_dir, axis_dir) < 0.0f)
+ weight = -weight;
+ weighted_dir += axis_dir * weight;
+ }
+ {
+ float det_z = xx * yy - xy * xy;
+ const Vector3 axis_dir(xy * yz - xz * yy, xy * xz - yz * xx, det_z);
+ float weight = det_z * det_z;
+ if (dot(weighted_dir, axis_dir) < 0.0f)
+ weight = -weight;
+ weighted_dir += axis_dir * weight;
+ }
+ *normal = normalize(weighted_dir, kEpsilon);
+#else
+ const float det_x = yy * zz - yz * yz;
+ const float det_y = xx * zz - xz * xz;
+ const float det_z = xx * yy - xy * xy;
+ const float det_max = max(det_x, max(det_y, det_z));
+ if (det_max <= 0.0f)
+ return false; // The points don't span a plane
+ // Pick path with best conditioning:
+ Vector3 dir(0.0f);
+ if (det_max == det_x)
+ dir = Vector3(det_x, xz * yz - xy * zz, xy * yz - xz * yy);
+ else if (det_max == det_y)
+ dir = Vector3(xz * yz - xy * zz, det_y, xy * xz - yz * xx);
+ else if (det_max == det_z)
+ dir = Vector3(xy * yz - xz * yy, xy * xz - yz * xx, det_z);
+ const float len = length(dir);
+ if (isZero(len, kEpsilon))
+ return false;
+ *normal = dir * (1.0f / len);
+#endif
+ return isNormalized(*normal);
+ }
+
+ static bool computeEigen(const Vector3 *points, uint32_t pointsCount, Basis *basis) {
+ float matrix[6];
+ computeCovariance(pointsCount, points, matrix);
+ if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0)
+ return false;
+ float eigenValues[3];
+ Vector3 eigenVectors[3];
+ if (!eigenSolveSymmetric3(matrix, eigenValues, eigenVectors))
+ return false;
+ basis->normal = normalize(eigenVectors[2], kEpsilon);
+ basis->tangent = normalize(eigenVectors[0], kEpsilon);
+ basis->bitangent = normalize(eigenVectors[1], kEpsilon);
+ return true;
+ }
+
+ static Vector3 computeCentroid(int n, const Vector3 *points) {
Vector3 centroid(0.0f);
for (int i = 0; i < n; i++) {
centroid += points[i];
@@ -1507,8 +1628,7 @@ public:
return centroid;
}
- static Vector3 computeCovariance(int n, const Vector3 * points, float * covariance)
- {
+ static Vector3 computeCovariance(int n, const Vector3 *points, float *covariance) {
// compute the centroid
Vector3 centroid = computeCentroid(n, points);
// compute covariance matrix
@@ -1530,8 +1650,7 @@ public:
// Tridiagonal solver from Charles Bloom.
// Householder transforms followed by QL decomposition.
// Seems to be based on the code from Numerical Recipes in C.
- static bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3])
- {
+ static bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3]) {
XA_DEBUG_ASSERT(matrix != nullptr && eigenValues != nullptr && eigenVectors != nullptr);
float subd[3];
float diag[3];
@@ -1556,7 +1675,7 @@ public:
// eigenvectors are the columns; make them the rows :
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- (&eigenVectors[j].x)[i] = (float) work[i][j];
+ (&eigenVectors[j].x)[i] = (float)work[i][j];
}
}
// shuffle to sort by singular value :
@@ -1578,8 +1697,7 @@ public:
}
private:
- static void EigenSolver3_Tridiagonal(float mat[3][3], float *diag, float *subd)
- {
+ static void EigenSolver3_Tridiagonal(float mat[3][3], float *diag, float *subd) {
// Householder reduction T = Q^t M Q
// Input:
// mat, symmetric 3x3 matrix M
@@ -1631,8 +1749,7 @@ private:
}
}
- static bool EigenSolver3_QLAlgorithm(float mat[3][3], float *diag, float *subd)
- {
+ static bool EigenSolver3_QLAlgorithm(float mat[3][3], float *diag, float *subd) {
// QL iteration with implicit shifting to reduce matrix from tridiagonal
// to diagonal
const int maxiter = 32;
@@ -1642,21 +1759,21 @@ private:
int m;
for (m = ell; m <= 1; m++) {
float dd = fabsf(diag[m]) + fabsf(diag[m + 1]);
- if ( fabsf(subd[m]) + dd == dd )
+ if (fabsf(subd[m]) + dd == dd)
break;
}
- if ( m == ell )
+ if (m == ell)
break;
float g = (diag[ell + 1] - diag[ell]) / (2 * subd[ell]);
float r = sqrtf(g * g + 1);
- if ( g < 0 )
+ if (g < 0)
g = diag[m] - diag[ell] + subd[ell] / (g - r);
else
g = diag[m] - diag[ell] + subd[ell] / (g + r);
float s = 1, c = 1, p = 0;
for (int i = m - 1; i >= ell; i--) {
float f = s * subd[i], b = c * subd[i];
- if ( fabsf(f) >= fabsf(g) ) {
+ if (fabsf(f) >= fabsf(g)) {
c = g / f;
r = sqrtf(c * c + 1);
subd[i + 1] = f * r;
@@ -1682,7 +1799,7 @@ private:
subd[ell] = g;
subd[m] = 0;
}
- if ( iter == maxiter )
+ if (iter == maxiter)
// should not get here under normal circumstances
return false;
}
@@ -1691,18 +1808,18 @@ private:
};
/// Fixed size vector class.
-class FullVector
-{
+class FullVector {
public:
- FullVector(uint32_t dim) { m_array.resize(dim); }
- FullVector(const FullVector &v) { v.m_array.copyTo(m_array); }
- const FullVector &operator=(const FullVector &v) = delete;
+ FullVector(uint32_t dim) :
+ m_array(MemTag::FullVector) { m_array.resize(dim); }
+ FullVector(const FullVector &v) :
+ m_array(MemTag::FullVector) { v.m_array.copyTo(m_array); }
+ FullVector &operator=(const FullVector &v) = delete;
XA_INLINE uint32_t dimension() const { return m_array.size(); }
XA_INLINE const float &operator[](uint32_t index) const { return m_array[index]; }
XA_INLINE float &operator[](uint32_t index) { return m_array[index]; }
- void fill(float f)
- {
+ void fill(float f) {
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++)
m_array[i] = f;
@@ -1712,22 +1829,19 @@ private:
Array<float> m_array;
};
-template<typename Key, typename H = Hash<Key>, typename E = Equal<Key> >
-class HashMap
-{
+template <typename Key, typename H = Hash<Key>, typename E = Equal<Key>>
+class HashMap {
public:
- HashMap(int memTag, uint32_t size) : m_memTag(memTag), m_size(size), m_numSlots(0), m_slots(nullptr), m_keys(memTag), m_next(memTag)
- {
+ HashMap(int memTag, uint32_t size) :
+ m_memTag(memTag), m_size(size), m_numSlots(0), m_slots(nullptr), m_keys(memTag), m_next(memTag) {
}
- ~HashMap()
- {
+ ~HashMap() {
if (m_slots)
XA_FREE(m_slots);
}
- void add(const Key &key)
- {
+ void add(const Key &key) {
if (!m_slots)
alloc();
const uint32_t hash = computeHash(key);
@@ -1736,8 +1850,7 @@ public:
m_slots[hash] = m_next.size() - 1;
}
- uint32_t get(const Key &key) const
- {
+ uint32_t get(const Key &key) const {
if (!m_slots)
return UINT32_MAX;
const uint32_t hash = computeHash(key);
@@ -1751,8 +1864,7 @@ public:
return UINT32_MAX;
}
- uint32_t getNext(uint32_t current) const
- {
+ uint32_t getNext(uint32_t current) const {
uint32_t i = m_next[current];
E equal;
while (i != UINT32_MAX) {
@@ -1764,10 +1876,12 @@ public:
}
private:
- void alloc()
- {
+ void alloc() {
XA_DEBUG_ASSERT(m_size > 0);
- m_numSlots = (uint32_t)(m_size * 1.3);
+ m_numSlots = nextPowerOfTwo(m_size);
+ auto minNumSlots = uint32_t(m_size * 1.3);
+ if (m_numSlots < minNumSlots)
+ m_numSlots = nextPowerOfTwo(minNumSlots);
m_slots = XA_ALLOC_ARRAY(m_memTag, uint32_t, m_numSlots);
for (uint32_t i = 0; i < m_numSlots; i++)
m_slots[i] = UINT32_MAX;
@@ -1775,10 +1889,9 @@ private:
m_next.reserve(m_size);
}
- uint32_t computeHash(const Key &key) const
- {
+ uint32_t computeHash(const Key &key) const {
H hash;
- return hash(key) % m_numSlots;
+ return hash(key) & (m_numSlots - 1);
}
int m_memTag;
@@ -1789,9 +1902,8 @@ private:
Array<uint32_t> m_next;
};
-template<typename T>
-static void insertionSort(T *data, uint32_t length)
-{
+template <typename T>
+static void insertionSort(T *data, uint32_t length) {
for (int32_t i = 1; i < (int32_t)length; i++) {
T x = data[i];
int32_t j = i - 1;
@@ -1803,11 +1915,18 @@ static void insertionSort(T *data, uint32_t length)
}
}
-class KISSRng
-{
+class KISSRng {
public:
- uint32_t getRange(uint32_t range)
- {
+ KISSRng() { reset(); }
+
+ void reset() {
+ x = 123456789;
+ y = 362436000;
+ z = 521288629;
+ c = 7654321;
+ }
+
+ uint32_t getRange(uint32_t range) {
if (range == 0)
return 0;
x = 69069 * x + 12345;
@@ -1820,26 +1939,24 @@ public:
}
private:
- uint32_t x = 123456789, y = 362436000, z = 521288629, c = 7654321;
+ uint32_t x, y, z, c;
};
// Based on Pierre Terdiman's and Michael Herf's source code.
// http://www.codercorner.com/RadixSortRevisited.htm
// http://www.stereopsis.com/radix.html
-class RadixSort
-{
+class RadixSort {
public:
- RadixSort() : m_size(0), m_ranks(nullptr), m_ranks2(nullptr), m_validRanks(false) {}
+ RadixSort() :
+ m_size(0), m_ranks(nullptr), m_ranks2(nullptr), m_validRanks(false) {}
- ~RadixSort()
- {
+ ~RadixSort() {
// Release everything
XA_FREE(m_ranks2);
XA_FREE(m_ranks);
}
- RadixSort &sort(const float *input, uint32_t count)
- {
+ RadixSort &sort(const float *input, uint32_t count) {
if (input == nullptr || count == 0) return *this;
// Resize lists if needed
if (count != m_size) {
@@ -1865,20 +1982,17 @@ public:
return *this;
}
- RadixSort &sort(const Array<float> &input)
- {
+ RadixSort &sort(const Array<float> &input) {
return sort(input.data(), input.size());
}
// Access to results. m_ranks is a list of indices in sorted order, i.e. in the order you may further process your data
- const uint32_t *ranks() const
- {
+ const uint32_t *ranks() const {
XA_DEBUG_ASSERT(m_validRanks);
return m_ranks;
}
- uint32_t *ranks()
- {
+ uint32_t *ranks() {
XA_DEBUG_ASSERT(m_validRanks);
return m_ranks;
}
@@ -1889,21 +2003,18 @@ private:
uint32_t *m_ranks2;
bool m_validRanks;
- void FloatFlip(uint32_t &f)
- {
+ void FloatFlip(uint32_t &f) {
int32_t mask = (int32_t(f) >> 31) | 0x80000000; // Warren Hunt, Manchor Ko.
f ^= mask;
}
- void IFloatFlip(uint32_t &f)
- {
+ void IFloatFlip(uint32_t &f) {
uint32_t mask = ((f >> 31) - 1) | 0x80000000; // Michael Herf.
f ^= mask;
}
- template<typename T>
- void createHistograms(const T *buffer, uint32_t count, uint32_t *histogram)
- {
+ template <typename T>
+ void createHistograms(const T *buffer, uint32_t count, uint32_t *histogram) {
const uint32_t bucketCount = sizeof(T); // (8 * sizeof(T)) / log2(radix)
// Init bucket pointers.
uint32_t *h[bucketCount];
@@ -1911,10 +2022,10 @@ private:
h[i] = histogram + 256 * i;
}
// Clear histograms.
- memset(histogram, 0, 256 * bucketCount * sizeof(uint32_t ));
+ memset(histogram, 0, 256 * bucketCount * sizeof(uint32_t));
// @@ Add support for signed integers.
// Build histograms.
- const uint8_t *p = (const uint8_t *)buffer; // @@ Does this break aliasing rules?
+ const uint8_t *p = (const uint8_t *)buffer; // @@ Does this break aliasing rules?
const uint8_t *pe = p + count * sizeof(T);
while (p != pe) {
h[0][*p++]++, h[1][*p++]++, h[2][*p++]++, h[3][*p++]++;
@@ -1929,8 +2040,8 @@ private:
}
}
- template <typename T> void insertionSort(const T *input, uint32_t count)
- {
+ template <typename T>
+ void insertionSort(const T *input, uint32_t count) {
if (!m_validRanks) {
m_ranks[0] = 0;
for (uint32_t i = 1; i != count; ++i) {
@@ -1960,8 +2071,8 @@ private:
}
}
- template <typename T> void radixSort(const T *input, uint32_t count)
- {
+ template <typename T>
+ void radixSort(const T *input, uint32_t count) {
const uint32_t P = sizeof(T); // pass count
// Allocate histograms & offsets on the stack
uint32_t histogram[256 * P];
@@ -1979,7 +2090,8 @@ private:
}
// Create offsets
link[0] = m_ranks2;
- for (uint32_t i = 1; i < 256; i++) link[i] = link[i - 1] + h[i - 1];
+ for (uint32_t i = 1; i < 256; i++)
+ link[i] = link[i - 1] + h[i - 1];
// Perform Radix Sort
if (!m_validRanks) {
for (uint32_t i = 0; i < count; i++) {
@@ -2006,18 +2118,26 @@ private:
};
// Wrapping this in a class allows temporary arrays to be re-used.
-class BoundingBox2D
-{
+class BoundingBox2D {
public:
- Vector2 majorAxis() const { return m_majorAxis; }
- Vector2 minorAxis() const { return m_minorAxis; }
- Vector2 minCorner() const { return m_minCorner; }
- Vector2 maxCorner() const { return m_maxCorner; }
+ Vector2 majorAxis, minorAxis, minCorner, maxCorner;
+
+ void clear() {
+ m_boundaryVertices.clear();
+ }
+
+ void appendBoundaryVertex(Vector2 v) {
+ m_boundaryVertices.push_back(v);
+ }
// This should compute convex hull and use rotating calipers to find the best box. Currently it uses a brute force method.
- void compute(const Vector2 *boundaryVertices, uint32_t boundaryVertexCount, const Vector2 *vertices, uint32_t vertexCount)
- {
- convexHull(boundaryVertices, boundaryVertexCount, m_hull, 0.00001f);
+ // If vertices is null or vertexCount is 0, the boundary vertices are used.
+ void compute(const Vector2 *vertices = nullptr, uint32_t vertexCount = 0) {
+ if (!vertices || vertexCount == 0) {
+ vertices = m_boundaryVertices.data();
+ vertexCount = m_boundaryVertices.size();
+ }
+ convexHull(m_boundaryVertices.data(), m_boundaryVertices.size(), m_hull, 0.00001f);
// @@ Ideally I should use rotating calipers to find the best box. Using brute force for now.
float best_area = FLT_MAX;
Vector2 best_min(0);
@@ -2051,17 +2171,16 @@ public:
best_axis = axis;
}
}
- m_majorAxis = best_axis;
- m_minorAxis = Vector2(-best_axis.y, best_axis.x);
- m_minCorner = best_min;
- m_maxCorner = best_max;
- XA_ASSERT(isFinite(m_majorAxis) && isFinite(m_minorAxis) && isFinite(m_minCorner));
+ majorAxis = best_axis;
+ minorAxis = Vector2(-best_axis.y, best_axis.x);
+ minCorner = best_min;
+ maxCorner = best_max;
+ XA_ASSERT(isFinite(majorAxis) && isFinite(minorAxis) && isFinite(minCorner));
}
private:
// Compute the convex hull using Graham Scan.
- void convexHull(const Vector2 *input, uint32_t inputCount, Array<Vector2> &output, float epsilon)
- {
+ void convexHull(const Vector2 *input, uint32_t inputCount, Array<Vector2> &output, float epsilon) {
m_coords.resize(inputCount);
for (uint32_t i = 0; i < inputCount; i++)
m_coords[i] = input[i].x;
@@ -2088,9 +2207,10 @@ private:
}
// Filter top list.
output.clear();
+ XA_DEBUG_ASSERT(m_top.size() >= 2);
output.push_back(m_top[0]);
output.push_back(m_top[1]);
- for (uint32_t i = 2; i < m_top.size(); ) {
+ for (uint32_t i = 2; i < m_top.size();) {
Vector2 a = output[output.size() - 2];
Vector2 b = output[output.size() - 1];
Vector2 c = m_top[i];
@@ -2103,9 +2223,10 @@ private:
}
}
uint32_t top_count = output.size();
+ XA_DEBUG_ASSERT(m_bottom.size() >= 2);
output.push_back(m_bottom[1]);
// Filter bottom list.
- for (uint32_t i = 2; i < m_bottom.size(); ) {
+ for (uint32_t i = 2; i < m_bottom.size();) {
Vector2 a = output[output.size() - 2];
Vector2 b = output[output.size() - 1];
Vector2 c = m_bottom[i];
@@ -2122,38 +2243,38 @@ private:
output.pop_back();
}
+ Array<Vector2> m_boundaryVertices;
Array<float> m_coords;
Array<Vector2> m_top, m_bottom, m_hull;
- Vector2 m_majorAxis, m_minorAxis, m_minCorner, m_maxCorner;
};
-static uint32_t meshEdgeFace(uint32_t edge) { return edge / 3; }
-static uint32_t meshEdgeIndex0(uint32_t edge) { return edge; }
+static uint32_t meshEdgeFace(uint32_t edge) {
+ return edge / 3;
+}
+static uint32_t meshEdgeIndex0(uint32_t edge) {
+ return edge;
+}
-static uint32_t meshEdgeIndex1(uint32_t edge)
-{
+static uint32_t meshEdgeIndex1(uint32_t edge) {
const uint32_t faceFirstEdge = edge / 3 * 3;
return faceFirstEdge + (edge - faceFirstEdge + 1) % 3;
}
-struct MeshFlags
-{
- enum
- {
- HasFaceGroups = 1<<0,
- HasIgnoredFaces = 1<<1,
- HasNormals = 1<<2
+struct MeshFlags {
+ enum {
+ HasFaceGroups = 1 << 0,
+ HasIgnoredFaces = 1 << 1,
+ HasNormals = 1 << 2
};
};
class Mesh;
static void meshGetBoundaryLoops(const Mesh &mesh, Array<uint32_t> &boundaryLoops);
-class Mesh
-{
+class Mesh {
public:
- Mesh(float epsilon, uint32_t approxVertexCount, uint32_t approxFaceCount, uint32_t flags = 0, uint32_t id = UINT32_MAX) : m_epsilon(epsilon), m_flags(flags), m_id(id), m_faceIgnore(MemTag::Mesh), m_faceGroups(MemTag::Mesh), m_indices(MemTag::MeshIndices), m_positions(MemTag::MeshPositions), m_normals(MemTag::MeshNormals), m_texcoords(MemTag::MeshTexcoords), m_colocalVertexCount(0), m_nextColocalVertex(MemTag::MeshColocals), m_boundaryVertices(MemTag::MeshBoundaries), m_oppositeEdges(MemTag::MeshBoundaries), m_nextBoundaryEdges(MemTag::MeshBoundaries), m_edgeMap(MemTag::MeshEdgeMap, approxFaceCount * 3)
- {
+ Mesh(float epsilon, uint32_t approxVertexCount, uint32_t approxFaceCount, uint32_t flags = 0, uint32_t id = UINT32_MAX) :
+ m_epsilon(epsilon), m_flags(flags), m_id(id), m_faceIgnore(MemTag::Mesh), m_ignoredFaceCount(0), m_indices(MemTag::MeshIndices), m_positions(MemTag::MeshPositions), m_normals(MemTag::MeshNormals), m_texcoords(MemTag::MeshTexcoords), m_faceGroups(MemTag::Mesh), m_faceGroupFirstFace(MemTag::Mesh), m_faceGroupNextFace(MemTag::Mesh), m_faceGroupFaceCounts(MemTag::Mesh), m_colocalVertexCount(0), m_nextColocalVertex(MemTag::MeshColocals), m_boundaryEdges(MemTag::MeshBoundaries), m_oppositeEdges(MemTag::MeshBoundaries), m_nextBoundaryEdges(MemTag::MeshBoundaries), m_edgeMap(MemTag::MeshEdgeMap, approxFaceCount * 3) {
m_indices.reserve(approxFaceCount * 3);
m_positions.reserve(approxVertexCount);
m_texcoords.reserve(approxVertexCount);
@@ -2165,11 +2286,11 @@ public:
m_normals.reserve(approxVertexCount);
}
+ static constexpr uint16_t kInvalidFaceGroup = UINT16_MAX;
uint32_t flags() const { return m_flags; }
uint32_t id() const { return m_id; }
- void addVertex(const Vector3 &pos, const Vector3 &normal = Vector3(0.0f), const Vector2 &texcoord = Vector2(0.0f))
- {
+ void addVertex(const Vector3 &pos, const Vector3 &normal = Vector3(0.0f), const Vector2 &texcoord = Vector2(0.0f)) {
XA_DEBUG_ASSERT(isFinite(pos));
m_positions.push_back(pos);
if (m_flags & MeshFlags::HasNormals)
@@ -2177,17 +2298,14 @@ public:
m_texcoords.push_back(texcoord);
}
- struct AddFaceResult
- {
- enum Enum
- {
+ struct AddFaceResult {
+ enum Enum {
OK,
DuplicateEdge = 1
};
};
- AddFaceResult::Enum addFace(uint32_t v0, uint32_t v1, uint32_t v2, bool ignore = false, bool hashEdge = true)
- {
+ AddFaceResult::Enum addFace(uint32_t v0, uint32_t v1, uint32_t v2, bool ignore = false, bool hashEdge = true) {
uint32_t indexArray[3];
indexArray[0] = v0;
indexArray[1] = v1;
@@ -2195,13 +2313,15 @@ public:
return addFace(indexArray, ignore, hashEdge);
}
- AddFaceResult::Enum addFace(const uint32_t *indices, bool ignore = false, bool hashEdge = true)
- {
+ AddFaceResult::Enum addFace(const uint32_t *indices, bool ignore = false, bool hashEdge = true) {
AddFaceResult::Enum result = AddFaceResult::OK;
if (m_flags & MeshFlags::HasFaceGroups)
- m_faceGroups.push_back(UINT32_MAX);
- if (m_flags & MeshFlags::HasIgnoredFaces)
+ m_faceGroups.push_back(kInvalidFaceGroup);
+ if (m_flags & MeshFlags::HasIgnoredFaces) {
m_faceIgnore.push_back(ignore);
+ if (ignore)
+ m_ignoredFaceCount++;
+ }
const uint32_t firstIndex = m_indices.size();
for (uint32_t i = 0; i < 3; i++)
m_indices.push_back(indices[i]);
@@ -2218,16 +2338,15 @@ public:
return result;
}
- void createColocals()
- {
+ void createColocals() {
const uint32_t vertexCount = m_positions.size();
- Array<AABB> aabbs;
+ Array<AABB> aabbs(MemTag::BVH);
aabbs.resize(vertexCount);
for (uint32_t i = 0; i < m_positions.size(); i++)
aabbs[i] = AABB(m_positions[i], m_epsilon);
BVH bvh(aabbs);
- Array<uint32_t> colocals;
- Array<uint32_t> potential;
+ Array<uint32_t> colocals(MemTag::MeshColocals);
+ Array<uint32_t> potential(MemTag::MeshColocals);
m_colocalVertexCount = 0;
m_nextColocalVertex.resize(vertexCount);
for (uint32_t i = 0; i < vertexCount; i++)
@@ -2247,7 +2366,7 @@ public:
if (colocals.size() == 1) {
// No colocals for this vertex.
m_nextColocalVertex[i] = i;
- continue;
+ continue;
}
m_colocalVertexCount += colocals.size();
// Link in ascending order.
@@ -2259,8 +2378,7 @@ public:
}
// Check if the face duplicates any edges of any face already in the group.
- bool faceDuplicatesGroupEdge(uint32_t group, uint32_t face) const
- {
+ bool faceDuplicatesGroupEdge(uint16_t group, uint32_t face) const {
for (FaceEdgeIterator edgeIt(this, face); !edgeIt.isDone(); edgeIt.advance()) {
for (ColocalEdgeIterator colocalEdgeIt(this, edgeIt.vertex0(), edgeIt.vertex1()); !colocalEdgeIt.isDone(); colocalEdgeIt.advance()) {
if (m_faceGroups[meshEdgeFace(colocalEdgeIt.edge())] == group)
@@ -2270,55 +2388,30 @@ public:
return false;
}
- // Check if the face mirrors any face already in the group.
- // i.e. don't want two-sided faces in the same group.
- // A face mirrors another face if all edges match with opposite winding.
- bool faceMirrorsGroupFace(uint32_t group, uint32_t face) const
- {
- FaceEdgeIterator edgeIt(this, face);
- for (ColocalEdgeIterator colocalEdgeIt(this, edgeIt.vertex1(), edgeIt.vertex0()); !colocalEdgeIt.isDone(); colocalEdgeIt.advance()) {
- const uint32_t candidateFace = meshEdgeFace(colocalEdgeIt.edge());
- if (m_faceGroups[candidateFace] == group) {
- // Found a match for mirrored first edge, try the other edges.
- bool match = false;
- for (; !edgeIt.isDone(); edgeIt.advance()) {
- match = false;
- for (ColocalEdgeIterator colocalEdgeIt2(this, edgeIt.vertex1(), edgeIt.vertex0()); !colocalEdgeIt2.isDone(); colocalEdgeIt2.advance()) {
- if (meshEdgeFace(colocalEdgeIt2.edge()) == candidateFace) {
- match = true;
- break;
- }
- }
- if (!match)
- break;
- }
- if (match)
- return true; // All edges are mirrored in this face.
- // Try the next face.
- edgeIt = FaceEdgeIterator(this, candidateFace);
- }
- }
- return false;
- }
-
- void createFaceGroups()
- {
- uint32_t group = 0;
+ void createFaceGroups() {
+ uint32_t firstUnassignedFace = 0;
+ uint16_t group = 0;
Array<uint32_t> growFaces;
+ const uint32_t n = faceCount();
+ m_faceGroupNextFace.resize(n);
for (;;) {
// Find an unassigned face.
uint32_t face = UINT32_MAX;
- for (uint32_t f = 0; f < faceCount(); f++) {
- if (m_faceGroups[f] == UINT32_MAX && !isFaceIgnored(f)) {
+ for (uint32_t f = firstUnassignedFace; f < n; f++) {
+ if (m_faceGroups[f] == kInvalidFaceGroup && !isFaceIgnored(f)) {
face = f;
+ firstUnassignedFace = f + 1;
break;
}
}
if (face == UINT32_MAX)
break; // All faces assigned to a group (except ignored faces).
m_faceGroups[face] = group;
+ m_faceGroupNextFace[face] = UINT32_MAX;
+ m_faceGroupFirstFace.push_back(face);
growFaces.clear();
growFaces.push_back(face);
+ uint32_t prevFace = face, groupFaceCount = 1;
// Find faces connected to the face and assign them to the same group as the face, unless they are already assigned to another group.
for (;;) {
if (growFaces.isEmpty())
@@ -2340,62 +2433,72 @@ public:
alreadyAssignedToThisGroup = true;
break;
}
- if (m_faceGroups[oppositeFace] != UINT32_MAX)
+ if (m_faceGroups[oppositeFace] != kInvalidFaceGroup)
continue; // Connected face is already assigned to another group.
if (faceDuplicatesGroupEdge(group, oppositeFace))
continue; // Don't want duplicate edges in a group.
- if (faceMirrorsGroupFace(group, oppositeFace))
- continue; // Don't want two-sided faces in a group.
const uint32_t oppositeVertex0 = m_indices[meshEdgeIndex0(oppositeEdge)];
const uint32_t oppositeVertex1 = m_indices[meshEdgeIndex1(oppositeEdge)];
if (bestConnectedFace == UINT32_MAX || (oppositeVertex0 == edgeIt.vertex1() && oppositeVertex1 == edgeIt.vertex0()))
bestConnectedFace = oppositeFace;
+#if 0
+ else {
+ // Choose the opposite face with the smallest dihedral angle.
+ const float d1 = 1.0f - dot(computeFaceNormal(f), computeFaceNormal(bestConnectedFace));
+ const float d2 = 1.0f - dot(computeFaceNormal(f), computeFaceNormal(oppositeFace));
+ if (d2 < d1)
+ bestConnectedFace = oppositeFace;
+ }
+#endif
}
if (!alreadyAssignedToThisGroup && bestConnectedFace != UINT32_MAX) {
m_faceGroups[bestConnectedFace] = group;
+ m_faceGroupNextFace[bestConnectedFace] = UINT32_MAX;
+ if (prevFace != UINT32_MAX)
+ m_faceGroupNextFace[prevFace] = bestConnectedFace;
+ prevFace = bestConnectedFace;
+ groupFaceCount++;
growFaces.push_back(bestConnectedFace);
}
}
}
+ m_faceGroupFaceCounts.push_back(groupFaceCount);
group++;
+ XA_ASSERT(group < kInvalidFaceGroup);
}
}
- void createBoundaries()
- {
+ void createBoundaries() {
const uint32_t edgeCount = m_indices.size();
const uint32_t vertexCount = m_positions.size();
m_oppositeEdges.resize(edgeCount);
- m_boundaryVertices.resize(vertexCount);
+ m_boundaryEdges.reserve(uint32_t(edgeCount * 0.1f));
+ m_isBoundaryVertex.resize(vertexCount);
+ m_isBoundaryVertex.zeroOutMemory();
for (uint32_t i = 0; i < edgeCount; i++)
m_oppositeEdges[i] = UINT32_MAX;
- for (uint32_t i = 0; i < vertexCount; i++)
- m_boundaryVertices[i] = false;
- const bool hasFaceGroups = m_flags & MeshFlags::HasFaceGroups;
- for (uint32_t i = 0; i < faceCount(); i++) {
+ const uint32_t faceCount = m_indices.size() / 3;
+ for (uint32_t i = 0; i < faceCount; i++) {
if (isFaceIgnored(i))
continue;
for (uint32_t j = 0; j < 3; j++) {
- const uint32_t vertex0 = m_indices[i * 3 + j];
+ const uint32_t edge = i * 3 + j;
+ const uint32_t vertex0 = m_indices[edge];
const uint32_t vertex1 = m_indices[i * 3 + (j + 1) % 3];
// If there is an edge with opposite winding to this one, the edge isn't on a boundary.
- const uint32_t oppositeEdge = findEdge(hasFaceGroups ? m_faceGroups[i] : UINT32_MAX, vertex1, vertex0);
+ const uint32_t oppositeEdge = findEdge(vertex1, vertex0);
if (oppositeEdge != UINT32_MAX) {
-#if XA_DEBUG
- if (hasFaceGroups)
- XA_DEBUG_ASSERT(m_faceGroups[meshEdgeFace(oppositeEdge)] == m_faceGroups[i]);
-#endif
- XA_DEBUG_ASSERT(!isFaceIgnored(meshEdgeFace(oppositeEdge)));
- m_oppositeEdges[i * 3 + j] = oppositeEdge;
+ m_oppositeEdges[edge] = oppositeEdge;
} else {
- m_boundaryVertices[vertex0] = m_boundaryVertices[vertex1] = true;
+ m_boundaryEdges.push_back(edge);
+ m_isBoundaryVertex.set(vertex0);
+ m_isBoundaryVertex.set(vertex1);
}
}
}
}
- void linkBoundaries()
- {
+ void linkBoundaries() {
const uint32_t edgeCount = m_indices.size();
HashMap<uint32_t> vertexToEdgeMap(MemTag::Mesh, edgeCount); // Edge is index / 2
for (uint32_t i = 0; i < edgeCount; i++) {
@@ -2407,12 +2510,12 @@ public:
m_nextBoundaryEdges[i] = UINT32_MAX;
uint32_t numBoundaryLoops = 0, numUnclosedBoundaries = 0;
BitArray linkedEdges(edgeCount);
- linkedEdges.clearAll();
+ linkedEdges.zeroOutMemory();
for (;;) {
// Find the first boundary edge that hasn't been linked yet.
uint32_t firstEdge = UINT32_MAX;
for (uint32_t i = 0; i < edgeCount; i++) {
- if (m_oppositeEdges[i] == UINT32_MAX && !linkedEdges.bitAt(i)) {
+ if (m_oppositeEdges[i] == UINT32_MAX && !linkedEdges.get(i)) {
firstEdge = i;
break;
}
@@ -2430,12 +2533,8 @@ public:
const uint32_t otherEdge = mapIndex / 2; // Two vertices added per edge.
if (m_oppositeEdges[otherEdge] != UINT32_MAX)
goto next; // Not a boundary edge.
- if (linkedEdges.bitAt(otherEdge))
+ if (linkedEdges.get(otherEdge))
goto next; // Already linked.
- if (m_flags & MeshFlags::HasFaceGroups && m_faceGroups[meshEdgeFace(currentEdge)] != m_faceGroups[meshEdgeFace(otherEdge)])
- goto next; // Don't cross face groups.
- if (isFaceIgnored(meshEdgeFace(otherEdge)))
- goto next; // Face is ignored.
if (m_indices[meshEdgeIndex0(otherEdge)] != it.vertex())
goto next; // Edge contains the vertex, but it's the wrong one.
// First edge (closing the boundary loop) has the highest priority.
@@ -2449,11 +2548,11 @@ public:
if (bestNextEdge == UINT32_MAX) {
numUnclosedBoundaries++;
if (currentEdge == firstEdge)
- linkedEdges.setBitAt(firstEdge); // Only 1 edge in this boundary "loop".
+ linkedEdges.set(firstEdge); // Only 1 edge in this boundary "loop".
break; // Can't find a next edge.
}
m_nextBoundaryEdges[currentEdge] = bestNextEdge;
- linkedEdges.setBitAt(bestNextEdge);
+ linkedEdges.set(bestNextEdge);
currentEdge = bestNextEdge;
if (currentEdge == firstEdge) {
numBoundaryLoops++;
@@ -2461,6 +2560,7 @@ public:
}
}
}
+#if XA_FIX_INTERNAL_BOUNDARY_LOOPS
// Find internal boundary loops and separate them.
// Detect by finding two edges in a boundary loop that have a colocal end vertex.
// Fix by swapping their next boundary edge.
@@ -2469,36 +2569,36 @@ public:
fixInternalBoundary:
meshGetBoundaryLoops(*this, boundaryLoops);
for (uint32_t loop = 0; loop < boundaryLoops.size(); loop++) {
- linkedEdges.clearAll();
- for (Mesh::BoundaryEdgeIterator it1(this, boundaryLoops[loop]); !it1.isDone(); it1.advance()) {
+ linkedEdges.zeroOutMemory();
+ for (Mesh::BoundaryLoopEdgeIterator it1(this, boundaryLoops[loop]); !it1.isDone(); it1.advance()) {
const uint32_t e1 = it1.edge();
- if (linkedEdges.bitAt(e1))
+ if (linkedEdges.get(e1))
continue;
- for (Mesh::BoundaryEdgeIterator it2(this, boundaryLoops[loop]); !it2.isDone(); it2.advance()) {
+ for (Mesh::BoundaryLoopEdgeIterator it2(this, boundaryLoops[loop]); !it2.isDone(); it2.advance()) {
const uint32_t e2 = it2.edge();
- if (e1 == e2 || !isBoundaryEdge(e2) || linkedEdges.bitAt(e2))
+ if (e1 == e2 || !isBoundaryEdge(e2) || linkedEdges.get(e2))
continue;
if (!areColocal(m_indices[meshEdgeIndex1(e1)], m_indices[meshEdgeIndex1(e2)]))
continue;
swap(m_nextBoundaryEdges[e1], m_nextBoundaryEdges[e2]);
- linkedEdges.setBitAt(e1);
- linkedEdges.setBitAt(e2);
+ linkedEdges.set(e1);
+ linkedEdges.set(e2);
goto fixInternalBoundary; // start over
}
}
}
+#endif
}
/// Find edge, test all colocals.
- uint32_t findEdge(uint32_t faceGroup, uint32_t vertex0, uint32_t vertex1) const
- {
+ uint32_t findEdge(uint32_t vertex0, uint32_t vertex1) const {
uint32_t result = UINT32_MAX;
if (m_nextColocalVertex.isEmpty()) {
EdgeKey key(vertex0, vertex1);
uint32_t edge = m_edgeMap.get(key);
while (edge != UINT32_MAX) {
// Don't find edges of ignored faces.
- if ((faceGroup == UINT32_MAX || m_faceGroups[meshEdgeFace(edge)] == faceGroup) && !isFaceIgnored(meshEdgeFace(edge))) {
+ if (!isFaceIgnored(meshEdgeFace(edge))) {
//XA_DEBUG_ASSERT(m_id != UINT32_MAX || (m_id == UINT32_MAX && result == UINT32_MAX)); // duplicate edge - ignore on initial meshes
result = edge;
#if !XA_DEBUG
@@ -2514,7 +2614,7 @@ public:
uint32_t edge = m_edgeMap.get(key);
while (edge != UINT32_MAX) {
// Don't find edges of ignored faces.
- if ((faceGroup == UINT32_MAX || m_faceGroups[meshEdgeFace(edge)] == faceGroup) && !isFaceIgnored(meshEdgeFace(edge))) {
+ if (!isFaceIgnored(meshEdgeFace(edge))) {
XA_DEBUG_ASSERT(m_id != UINT32_MAX || (m_id == UINT32_MAX && result == UINT32_MAX)); // duplicate edge - ignore on initial meshes
result = edge;
#if !XA_DEBUG
@@ -2530,8 +2630,7 @@ public:
}
#if XA_DEBUG_EXPORT_OBJ
- void writeObjVertices(FILE *file) const
- {
+ void writeObjVertices(FILE *file) const {
for (uint32_t i = 0; i < m_positions.size(); i++)
fprintf(file, "v %g %g %g\n", m_positions[i].x, m_positions[i].y, m_positions[i].z);
if (m_flags & MeshFlags::HasNormals) {
@@ -2542,8 +2641,7 @@ public:
fprintf(file, "vt %g %g\n", m_texcoords[i].x, m_texcoords[i].y);
}
- void writeObjFace(FILE *file, uint32_t face) const
- {
+ void writeObjFace(FILE *file, uint32_t face) const {
fprintf(file, "f ");
for (uint32_t j = 0; j < 3; j++) {
const uint32_t index = m_indices[face * 3 + j] + 1; // 1-indexed
@@ -2551,8 +2649,7 @@ public:
}
}
- void writeObjBoundaryEges(FILE *file) const
- {
+ void writeObjBoundaryEges(FILE *file) const {
if (m_oppositeEdges.isEmpty())
return; // Boundaries haven't been created.
fprintf(file, "o boundary_edges\n");
@@ -2563,8 +2660,7 @@ public:
}
}
- void writeObjLinkedBoundaries(FILE *file) const
- {
+ void writeObjLinkedBoundaries(FILE *file) const {
if (m_oppositeEdges.isEmpty() || m_nextBoundaryEdges.isEmpty())
return; // Boundaries haven't been created and/or linked.
Array<uint32_t> boundaryLoops;
@@ -2586,8 +2682,7 @@ public:
}
}
- void writeObjFile(const char *filename) const
- {
+ void writeObjFile(const char *filename) const {
FILE *file;
XA_FOPEN(file, filename, "w");
if (!file)
@@ -2603,56 +2698,38 @@ public:
}
#endif
- float computeSurfaceArea() const
- {
+ float computeSurfaceArea() const {
float area = 0;
for (uint32_t f = 0; f < faceCount(); f++)
- area += faceArea(f);
+ area += computeFaceArea(f);
XA_DEBUG_ASSERT(area >= 0);
return area;
}
- float computeParametricArea() const
- {
+ float computeParametricArea() const {
float area = 0;
for (uint32_t f = 0; f < faceCount(); f++)
- area += faceParametricArea(f);
+ area += computeFaceParametricArea(f);
return fabsf(area); // May be negative, depends on texcoord winding.
}
- float faceArea(uint32_t face) const
- {
+ float computeFaceArea(uint32_t face) const {
const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]];
const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]];
const Vector3 &p2 = m_positions[m_indices[face * 3 + 2]];
return length(cross(p1 - p0, p2 - p0)) * 0.5f;
}
- Vector3 faceCentroid(uint32_t face) const
- {
+ Vector3 computeFaceCentroid(uint32_t face) const {
Vector3 sum(0.0f);
for (uint32_t i = 0; i < 3; i++)
sum += m_positions[m_indices[face * 3 + i]];
return sum / 3.0f;
}
- Vector3 calculateFaceNormal(uint32_t face) const
- {
- return normalizeSafe(triangleNormalAreaScaled(face), Vector3(0, 0, 1), 0.0f);
- }
-
- float faceParametricArea(uint32_t face) const
- {
- const Vector2 &t0 = m_texcoords[m_indices[face * 3 + 0]];
- const Vector2 &t1 = m_texcoords[m_indices[face * 3 + 1]];
- const Vector2 &t2 = m_texcoords[m_indices[face * 3 + 2]];
- return triangleArea(t0, t1, t2) * 0.5f;
- }
-
// Average of the edge midpoints weighted by the edge length.
// I want a point inside the triangle, but closer to the cirumcenter.
- Vector3 triangleCenter(uint32_t face) const
- {
+ Vector3 computeFaceCenter(uint32_t face) const {
const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]];
const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]];
const Vector3 &p2 = m_positions[m_indices[face * 3 + 2]];
@@ -2665,25 +2742,25 @@ public:
return m0 + m1 + m2;
}
- // Unnormalized face normal assuming it's a triangle.
- Vector3 triangleNormal(uint32_t face) const
- {
- return normalizeSafe(triangleNormalAreaScaled(face), Vector3(0), 0.0f);
- }
-
- Vector3 triangleNormalAreaScaled(uint32_t face) const
- {
+ Vector3 computeFaceNormal(uint32_t face) const {
const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]];
const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]];
const Vector3 &p2 = m_positions[m_indices[face * 3 + 2]];
const Vector3 e0 = p2 - p0;
const Vector3 e1 = p1 - p0;
- return cross(e0, e1);
+ const Vector3 normalAreaScaled = cross(e0, e1);
+ return normalizeSafe(normalAreaScaled, Vector3(0, 0, 1), 0.0f);
+ }
+
+ float computeFaceParametricArea(uint32_t face) const {
+ const Vector2 &t0 = m_texcoords[m_indices[face * 3 + 0]];
+ const Vector2 &t1 = m_texcoords[m_indices[face * 3 + 1]];
+ const Vector2 &t2 = m_texcoords[m_indices[face * 3 + 2]];
+ return triangleArea(t0, t1, t2);
}
// @@ This is not exactly accurate, we should compare the texture coordinates...
- bool isSeam(uint32_t edge) const
- {
+ bool isSeam(uint32_t edge) const {
const uint32_t oppositeEdge = m_oppositeEdges[edge];
if (oppositeEdge == UINT32_MAX)
return false; // boundary edge
@@ -2694,8 +2771,7 @@ public:
return m_indices[e0] != m_indices[oe1] || m_indices[e1] != m_indices[oe0];
}
- bool isTextureSeam(uint32_t edge) const
- {
+ bool isTextureSeam(uint32_t edge) const {
const uint32_t oppositeEdge = m_oppositeEdges[edge];
if (oppositeEdge == UINT32_MAX)
return false; // boundary edge
@@ -2706,8 +2782,7 @@ public:
return m_texcoords[m_indices[e0]] != m_texcoords[m_indices[oe1]] || m_texcoords[m_indices[e1]] != m_texcoords[m_indices[oe0]];
}
- uint32_t firstColocal(uint32_t vertex) const
- {
+ uint32_t firstColocal(uint32_t vertex) const {
for (ColocalVertexIterator it(this, vertex); !it.isDone(); it.advance()) {
if (it.vertex() < vertex)
vertex = it.vertex();
@@ -2715,8 +2790,7 @@ public:
return vertex;
}
- bool areColocal(uint32_t vertex0, uint32_t vertex1) const
- {
+ bool areColocal(uint32_t vertex0, uint32_t vertex1) const {
if (vertex0 == vertex1)
return true;
if (m_nextColocalVertex.isEmpty())
@@ -2732,18 +2806,38 @@ public:
XA_INLINE uint32_t edgeCount() const { return m_indices.size(); }
XA_INLINE uint32_t oppositeEdge(uint32_t edge) const { return m_oppositeEdges[edge]; }
XA_INLINE bool isBoundaryEdge(uint32_t edge) const { return m_oppositeEdges[edge] == UINT32_MAX; }
- XA_INLINE bool isBoundaryVertex(uint32_t vertex) const { return m_boundaryVertices[vertex]; }
+ XA_INLINE const Array<uint32_t> &boundaryEdges() const { return m_boundaryEdges; }
+ XA_INLINE bool isBoundaryVertex(uint32_t vertex) const { return m_isBoundaryVertex.get(vertex); }
XA_INLINE uint32_t colocalVertexCount() const { return m_colocalVertexCount; }
XA_INLINE uint32_t vertexCount() const { return m_positions.size(); }
XA_INLINE uint32_t vertexAt(uint32_t i) const { return m_indices[i]; }
XA_INLINE const Vector3 &position(uint32_t vertex) const { return m_positions[vertex]; }
- XA_INLINE const Vector3 &normal(uint32_t vertex) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasNormals); return m_normals[vertex]; }
+ XA_INLINE const Vector3 &normal(uint32_t vertex) const {
+ XA_DEBUG_ASSERT(m_flags & MeshFlags::HasNormals);
+ return m_normals[vertex];
+ }
XA_INLINE const Vector2 &texcoord(uint32_t vertex) const { return m_texcoords[vertex]; }
XA_INLINE Vector2 &texcoord(uint32_t vertex) { return m_texcoords[vertex]; }
+ XA_INLINE const Vector2 *texcoords() const { return m_texcoords.data(); }
XA_INLINE Vector2 *texcoords() { return m_texcoords.data(); }
+ XA_INLINE uint32_t ignoredFaceCount() const { return m_ignoredFaceCount; }
XA_INLINE uint32_t faceCount() const { return m_indices.size() / 3; }
- XA_INLINE uint32_t faceGroupCount() const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroups.size(); }
- XA_INLINE uint32_t faceGroupAt(uint32_t face) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups); return m_faceGroups[face]; }
+ XA_INLINE uint16_t faceGroupAt(uint32_t face) const {
+ XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups);
+ return m_faceGroups[face];
+ }
+ XA_INLINE uint32_t faceGroupCount() const {
+ XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups);
+ return m_faceGroupFaceCounts.size();
+ }
+ XA_INLINE uint32_t faceGroupNextFace(uint32_t face) const {
+ XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups);
+ return m_faceGroupNextFace[face];
+ }
+ XA_INLINE uint32_t faceGroupFaceCount(uint32_t group) const {
+ XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups);
+ return m_faceGroupFaceCounts[group];
+ }
XA_INLINE const uint32_t *indices() const { return m_indices.data(); }
XA_INLINE uint32_t indexCount() const { return m_indices.size(); }
@@ -2754,70 +2848,69 @@ private:
uint32_t m_flags;
uint32_t m_id;
Array<bool> m_faceIgnore;
- Array<uint32_t> m_faceGroups;
+ uint32_t m_ignoredFaceCount;
Array<uint32_t> m_indices;
Array<Vector3> m_positions;
Array<Vector3> m_normals;
Array<Vector2> m_texcoords;
+ // Populated by createFaceGroups
+ Array<uint16_t> m_faceGroups;
+ Array<uint32_t> m_faceGroupFirstFace;
+ Array<uint32_t> m_faceGroupNextFace; // In: face. Out: the next face in the same group.
+ Array<uint32_t> m_faceGroupFaceCounts; // In: face group. Out: number of faces in the group.
+
// Populated by createColocals
uint32_t m_colocalVertexCount;
Array<uint32_t> m_nextColocalVertex; // In: vertex index. Out: the vertex index of the next colocal position.
// Populated by createBoundaries
- Array<bool> m_boundaryVertices;
+ BitArray m_isBoundaryVertex;
+ Array<uint32_t> m_boundaryEdges;
Array<uint32_t> m_oppositeEdges; // In: edge index. Out: the index of the opposite edge (i.e. wound the opposite direction). UINT32_MAX if the input edge is a boundary edge.
// Populated by linkBoundaries
Array<uint32_t> m_nextBoundaryEdges; // The index of the next boundary edge. UINT32_MAX if the edge is not a boundary edge.
- struct EdgeKey
- {
+ struct EdgeKey {
EdgeKey() {}
- EdgeKey(const EdgeKey &k) : v0(k.v0), v1(k.v1) {}
- EdgeKey(uint32_t v0, uint32_t v1) : v0(v0), v1(v1) {}
-
- void operator=(const EdgeKey &k)
- {
- v0 = k.v0;
- v1 = k.v1;
- }
- bool operator==(const EdgeKey &k) const
- {
- return v0 == k.v0 && v1 == k.v1;
- }
+ EdgeKey(const EdgeKey &k) :
+ v0(k.v0), v1(k.v1) {}
+ EdgeKey(uint32_t v0, uint32_t v1) :
+ v0(v0), v1(v1) {}
+ bool operator==(const EdgeKey &k) const { return v0 == k.v0 && v1 == k.v1; }
uint32_t v0;
uint32_t v1;
};
- HashMap<EdgeKey> m_edgeMap;
+ struct EdgeHash {
+ uint32_t operator()(const EdgeKey &k) const { return k.v0 * 32768u + k.v1; }
+ };
+
+ HashMap<EdgeKey, EdgeHash> m_edgeMap;
public:
- class BoundaryEdgeIterator
- {
+ class BoundaryLoopEdgeIterator {
public:
- BoundaryEdgeIterator(const Mesh *mesh, uint32_t edge) : m_mesh(mesh), m_first(UINT32_MAX), m_current(edge) {}
+ BoundaryLoopEdgeIterator(const Mesh *mesh, uint32_t edge) :
+ m_mesh(mesh), m_first(UINT32_MAX), m_current(edge) {}
- void advance()
- {
+ void advance() {
if (m_first == UINT32_MAX)
m_first = m_current;
m_current = m_mesh->m_nextBoundaryEdges[m_current];
}
- bool isDone() const
- {
+ bool isDone() const {
return m_first == m_current || m_current == UINT32_MAX;
}
- uint32_t edge() const
- {
+ uint32_t edge() const {
return m_current;
}
- uint32_t nextEdge() const
- {
+ uint32_t nextEdge() const {
return m_mesh->m_nextBoundaryEdges[m_current];
}
@@ -2827,31 +2920,27 @@ public:
uint32_t m_current;
};
- class ColocalVertexIterator
- {
+ class ColocalVertexIterator {
public:
- ColocalVertexIterator(const Mesh *mesh, uint32_t v) : m_mesh(mesh), m_first(UINT32_MAX), m_current(v) {}
+ ColocalVertexIterator(const Mesh *mesh, uint32_t v) :
+ m_mesh(mesh), m_first(UINT32_MAX), m_current(v) {}
- void advance()
- {
+ void advance() {
if (m_first == UINT32_MAX)
m_first = m_current;
if (!m_mesh->m_nextColocalVertex.isEmpty())
m_current = m_mesh->m_nextColocalVertex[m_current];
}
- bool isDone() const
- {
+ bool isDone() const {
return m_first == m_current;
}
- uint32_t vertex() const
- {
+ uint32_t vertex() const {
return m_current;
}
- const Vector3 *pos() const
- {
+ const Vector3 *pos() const {
return &m_mesh->m_positions[m_current];
}
@@ -2861,44 +2950,46 @@ public:
uint32_t m_current;
};
- class ColocalEdgeIterator
- {
+ class ColocalEdgeIterator {
public:
- ColocalEdgeIterator(const Mesh *mesh, uint32_t vertex0, uint32_t vertex1) : m_mesh(mesh), m_vertex0It(mesh, vertex0), m_vertex1It(mesh, vertex1), m_vertex1(vertex1)
- {
- resetElement();
+ ColocalEdgeIterator(const Mesh *mesh, uint32_t vertex0, uint32_t vertex1) :
+ m_mesh(mesh), m_vertex0It(mesh, vertex0), m_vertex1It(mesh, vertex1), m_vertex1(vertex1) {
+ do {
+ if (!resetElement()) {
+ advanceVertex1();
+ } else {
+ break;
+ }
+ } while (!isDone());
}
- void advance()
- {
+ void advance() {
advanceElement();
}
- bool isDone() const
- {
+ bool isDone() const {
return m_vertex0It.isDone() && m_vertex1It.isDone() && m_edge == UINT32_MAX;
}
- uint32_t edge() const
- {
+ uint32_t edge() const {
return m_edge;
}
private:
- void resetElement()
- {
+ bool resetElement() {
m_edge = m_mesh->m_edgeMap.get(Mesh::EdgeKey(m_vertex0It.vertex(), m_vertex1It.vertex()));
while (m_edge != UINT32_MAX) {
if (!isIgnoredFace())
break;
m_edge = m_mesh->m_edgeMap.getNext(m_edge);
}
- if (m_edge == UINT32_MAX)
- advanceVertex1();
+ if (m_edge == UINT32_MAX) {
+ return false;
+ }
+ return true;
}
- void advanceElement()
- {
+ void advanceElement() {
for (;;) {
m_edge = m_mesh->m_edgeMap.getNext(m_edge);
if (m_edge == UINT32_MAX)
@@ -2910,26 +3001,23 @@ public:
advanceVertex1();
}
- void advanceVertex0()
- {
- m_vertex0It.advance();
- if (m_vertex0It.isDone())
- return;
- m_vertex1It = ColocalVertexIterator(m_mesh, m_vertex1);
- resetElement();
- }
-
- void advanceVertex1()
- {
- m_vertex1It.advance();
- if (m_vertex1It.isDone())
- advanceVertex0();
- else
- resetElement();
+ void advanceVertex1() {
+ auto successful = false;
+ while (!successful) {
+ m_vertex1It.advance();
+ if (m_vertex1It.isDone()) {
+ if (!m_vertex0It.isDone()) {
+ m_vertex0It.advance();
+ m_vertex1It = ColocalVertexIterator(m_mesh, m_vertex1);
+ } else {
+ return;
+ }
+ }
+ successful = resetElement();
+ }
}
- bool isIgnoredFace() const
- {
+ bool isIgnoredFace() const {
return m_mesh->m_faceIgnore[meshEdgeFace(m_edge)];
}
@@ -2939,24 +3027,21 @@ public:
uint32_t m_edge;
};
- class FaceEdgeIterator
- {
+ class FaceEdgeIterator {
public:
- FaceEdgeIterator (const Mesh *mesh, uint32_t face) : m_mesh(mesh), m_face(face), m_relativeEdge(0)
- {
+ FaceEdgeIterator(const Mesh *mesh, uint32_t face) :
+ m_mesh(mesh), m_face(face), m_relativeEdge(0) {
m_edge = m_face * 3;
}
- void advance()
- {
+ void advance() {
if (m_relativeEdge < 3) {
m_edge++;
m_relativeEdge++;
}
}
- bool isDone() const
- {
+ bool isDone() const {
return m_relativeEdge == 3;
}
@@ -2967,25 +3052,16 @@ public:
uint32_t relativeEdge() const { return m_relativeEdge; }
uint32_t face() const { return m_face; }
uint32_t oppositeEdge() const { return m_mesh->m_oppositeEdges[m_edge]; }
-
- uint32_t oppositeFace() const
- {
+
+ uint32_t oppositeFace() const {
const uint32_t oedge = m_mesh->m_oppositeEdges[m_edge];
if (oedge == UINT32_MAX)
return UINT32_MAX;
return meshEdgeFace(oedge);
}
- uint32_t vertex0() const
- {
- return m_mesh->m_indices[m_face * 3 + m_relativeEdge];
- }
-
- uint32_t vertex1() const
- {
- return m_mesh->m_indices[m_face * 3 + (m_relativeEdge + 1) % 3];
- }
-
+ uint32_t vertex0() const { return m_mesh->m_indices[m_face * 3 + m_relativeEdge]; }
+ uint32_t vertex1() const { return m_mesh->m_indices[m_face * 3 + (m_relativeEdge + 1) % 3]; }
const Vector3 &position0() const { return m_mesh->m_positions[vertex0()]; }
const Vector3 &position1() const { return m_mesh->m_positions[vertex1()]; }
const Vector3 &normal0() const { return m_mesh->m_normals[vertex0()]; }
@@ -2999,10 +3075,36 @@ public:
uint32_t m_edge;
uint32_t m_relativeEdge;
};
+
+ class GroupFaceIterator {
+ public:
+ GroupFaceIterator(const Mesh *mesh, uint32_t group) :
+ m_mesh(mesh) {
+ XA_DEBUG_ASSERT(group != UINT32_MAX);
+ m_current = mesh->m_faceGroupFirstFace[group];
+ }
+
+ void advance() {
+ m_current = m_mesh->m_faceGroupNextFace[m_current];
+ }
+
+ bool isDone() const {
+ return m_current == UINT32_MAX;
+ }
+
+ uint32_t face() const {
+ return m_current;
+ }
+
+ private:
+ const Mesh *m_mesh;
+ uint32_t m_current;
+ };
};
-static bool meshCloseHole(Mesh *mesh, const Array<uint32_t> &holeVertices, const Vector3 &normal)
-{
+constexpr uint16_t Mesh::kInvalidFaceGroup;
+
+static bool meshCloseHole(Mesh *mesh, const Array<uint32_t> &holeVertices, const Vector3 &normal) {
#if XA_CLOSE_HOLES_CHECK_EDGE_INTERSECTION
const uint32_t faceCount = mesh->faceCount();
#endif
@@ -3027,15 +3129,15 @@ static bool meshCloseHole(Mesh *mesh, const Array<uint32_t> &holeVertices, const
const uint32_t i3 = (i + 1) % frontCount;
const Vector3 edge1 = frontPoints[i1] - frontPoints[i2];
const Vector3 edge2 = frontPoints[i3] - frontPoints[i2];
- frontAngles[i] = acosf(dot(edge1, edge2) / (length(edge1) * length(edge2)));
+ frontAngles[i] = atan2f(length(cross(edge1, edge2)), dot(edge1, edge2));
if (frontAngles[i] >= smallestAngle || isNan(frontAngles[i]))
continue;
// Don't duplicate edges.
- if (mesh->findEdge(UINT32_MAX, frontVertices[i1], frontVertices[i2]) != UINT32_MAX)
+ if (mesh->findEdge(frontVertices[i1], frontVertices[i2]) != UINT32_MAX)
continue;
- if (mesh->findEdge(UINT32_MAX, frontVertices[i2], frontVertices[i3]) != UINT32_MAX)
+ if (mesh->findEdge(frontVertices[i2], frontVertices[i3]) != UINT32_MAX)
continue;
- if (mesh->findEdge(UINT32_MAX, frontVertices[i3], frontVertices[i1]) != UINT32_MAX)
+ if (mesh->findEdge(frontVertices[i3], frontVertices[i1]) != UINT32_MAX)
continue;
/*
Make sure he new edge that would be formed by (i3, i1) doesn't intersect any vertices. This often happens when fixing t-junctions.
@@ -3128,9 +3230,9 @@ static bool meshCloseHole(Mesh *mesh, const Array<uint32_t> &holeVertices, const
return true;
}
-static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, const Vector3 &normal, Array<uint32_t> &holeFaceCounts)
-{
- holeFaceCounts.clear();
+static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, const Vector3 &normal, uint32_t *holeCount, Array<uint32_t> *holeFaceCounts) {
+ if (holeFaceCounts)
+ holeFaceCounts->clear();
// Compute lengths.
const uint32_t boundaryCount = boundaryLoops.size();
Array<float> boundaryLengths;
@@ -3139,7 +3241,7 @@ static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, con
for (uint32_t i = 0; i < boundaryCount; i++) {
float boundaryLength = 0.0f;
boundaryEdgeCounts[i] = 0;
- for (Mesh::BoundaryEdgeIterator it(mesh, boundaryLoops[i]); !it.isDone(); it.advance()) {
+ for (Mesh::BoundaryLoopEdgeIterator it(mesh, boundaryLoops[i]); !it.isDone(); it.advance()) {
const Vector3 &t0 = mesh->position(mesh->vertexAt(meshEdgeIndex0(it.edge())));
const Vector3 &t1 = mesh->position(mesh->vertexAt(meshEdgeIndex1(it.edge())));
boundaryLength += length(t1 - t0);
@@ -3167,7 +3269,7 @@ static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, con
holePoints.resize(boundaryEdgeCounts[i]);
// Winding is backwards for internal boundaries.
uint32_t e = 0;
- for (Mesh::BoundaryEdgeIterator it(mesh, boundaryLoops[i]); !it.isDone(); it.advance()) {
+ for (Mesh::BoundaryLoopEdgeIterator it(mesh, boundaryLoops[i]); !it.isDone(); it.advance()) {
const uint32_t vertex = mesh->vertexAt(meshEdgeIndex0(it.edge()));
holeVertices[boundaryEdgeCounts[i] - 1 - e] = vertex;
holePoints[boundaryEdgeCounts[i] - 1 - e] = mesh->position(vertex);
@@ -3176,13 +3278,15 @@ static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, con
const uint32_t oldFaceCount = mesh->faceCount();
if (!meshCloseHole(mesh, holeVertices, normal))
result = false; // Return false if any hole failed to close, but keep trying to close other holes.
- holeFaceCounts.push_back(mesh->faceCount() - oldFaceCount);
+ if (holeCount)
+ (*holeCount)++;
+ if (holeFaceCounts)
+ holeFaceCounts->push_back(mesh->faceCount() - oldFaceCount);
}
return result;
}
-static bool meshIsPlanar(const Mesh &mesh)
-{
+static bool meshIsPlanar(const Mesh &mesh) {
const Vector3 p1 = mesh.position(mesh.vertexAt(0));
const Vector3 p2 = mesh.position(mesh.vertexAt(1));
const Vector3 p3 = mesh.position(mesh.vertexAt(2));
@@ -3208,14 +3312,12 @@ Fixing T-junctions.
- Split edge.
*/
-struct SplitEdge
-{
+struct SplitEdge {
uint32_t edge;
float t;
uint32_t vertex;
- bool operator<(const SplitEdge &other) const
- {
+ bool operator<(const SplitEdge &other) const {
if (edge < other.edge)
return true;
else if (edge == other.edge) {
@@ -3227,8 +3329,7 @@ struct SplitEdge
};
// Returns nullptr if there were no t-junctions to fix.
-static Mesh *meshFixTJunctions(const Mesh &inputMesh, bool *duplicatedEdge, bool *failed, uint32_t *fixedTJunctionsCount)
-{
+static Mesh *meshFixTJunctions(const Mesh &inputMesh, bool *duplicatedEdge, bool *failed, uint32_t *fixedTJunctionsCount) {
if (duplicatedEdge)
*duplicatedEdge = false;
if (failed)
@@ -3303,128 +3404,38 @@ static Mesh *meshFixTJunctions(const Mesh &inputMesh, bool *duplicatedEdge, bool
}
// boundaryLoops are the first edges for each boundary loop.
-static void meshGetBoundaryLoops(const Mesh &mesh, Array<uint32_t> &boundaryLoops)
-{
+static void meshGetBoundaryLoops(const Mesh &mesh, Array<uint32_t> &boundaryLoops) {
const uint32_t edgeCount = mesh.edgeCount();
BitArray bitFlags(edgeCount);
- bitFlags.clearAll();
+ bitFlags.zeroOutMemory();
boundaryLoops.clear();
// Search for boundary edges. Mark all the edges that belong to the same boundary.
for (uint32_t e = 0; e < edgeCount; e++) {
- if (bitFlags.bitAt(e) || !mesh.isBoundaryEdge(e))
+ if (bitFlags.get(e) || !mesh.isBoundaryEdge(e))
continue;
- for (Mesh::BoundaryEdgeIterator it(&mesh, e); !it.isDone(); it.advance())
- bitFlags.setBitAt(it.edge());
+ for (Mesh::BoundaryLoopEdgeIterator it(&mesh, e); !it.isDone(); it.advance())
+ bitFlags.set(it.edge());
boundaryLoops.push_back(e);
}
}
-class MeshTopology
-{
-public:
- MeshTopology(const Mesh *mesh)
- {
- const uint32_t vertexCount = mesh->colocalVertexCount();
- const uint32_t faceCount = mesh->faceCount();
- const uint32_t edgeCount = mesh->edgeCount();
- Array<uint32_t> stack(MemTag::Default);
- stack.reserve(faceCount);
- BitArray bitFlags(faceCount);
- bitFlags.clearAll();
- // Compute connectivity.
- m_connectedCount = 0;
- for (uint32_t f = 0; f < faceCount; f++ ) {
- if (bitFlags.bitAt(f) == false) {
- m_connectedCount++;
- stack.push_back(f);
- while (!stack.isEmpty()) {
- const uint32_t top = stack.back();
- XA_ASSERT(top != uint32_t(~0));
- stack.pop_back();
- if (bitFlags.bitAt(top) == false) {
- bitFlags.setBitAt(top);
- for (Mesh::FaceEdgeIterator it(mesh, top); !it.isDone(); it.advance()) {
- const uint32_t oppositeFace = it.oppositeFace();
- if (oppositeFace != UINT32_MAX)
- stack.push_back(oppositeFace);
- }
- }
- }
- }
- }
- XA_ASSERT(stack.isEmpty());
- // Count boundary loops.
- m_boundaryCount = 0;
- bitFlags.resize(edgeCount);
- bitFlags.clearAll();
- // Don't forget to link the boundary otherwise this won't work.
- for (uint32_t e = 0; e < edgeCount; e++) {
- if (bitFlags.bitAt(e) || !mesh->isBoundaryEdge(e))
- continue;
- m_boundaryCount++;
- for (Mesh::BoundaryEdgeIterator it(mesh, e); !it.isDone(); it.advance())
- bitFlags.setBitAt(it.edge());
- }
- // Compute euler number.
- m_eulerNumber = vertexCount - edgeCount + faceCount;
- // Compute genus. (only valid on closed connected surfaces)
- m_genus = -1;
- if (isClosed() && isConnected())
- m_genus = (2 - m_eulerNumber) / 2;
- }
-
- /// Determine if the mesh is connected.
- bool isConnected() const
- {
- return m_connectedCount == 1;
- }
-
- /// Determine if the mesh is closed. (Each edge is shared by two faces)
- bool isClosed() const
- {
- return m_boundaryCount == 0;
- }
-
- /// Return true if the mesh has the topology of a disk.
- bool isDisk() const
- {
- return isConnected() && m_boundaryCount == 1/* && m_eulerNumber == 1*/;
- }
-
-private:
- ///< Number of boundary loops.
- int m_boundaryCount;
-
- ///< Number of connected components.
- int m_connectedCount;
-
- ///< Euler number.
- int m_eulerNumber;
-
- /// Mesh genus.
- int m_genus;
-};
-
-struct Progress
-{
- Progress(ProgressCategory::Enum category, ProgressFunc func, void *userData, uint32_t maxValue) : value(0), cancel(false), m_category(category), m_func(func), m_userData(userData), m_maxValue(maxValue), m_progress(0)
- {
+struct Progress {
+ Progress(ProgressCategory::Enum category, ProgressFunc func, void *userData, uint32_t maxValue) :
+ value(0), cancel(false), m_category(category), m_func(func), m_userData(userData), m_maxValue(maxValue), m_progress(0) {
if (m_func) {
if (!m_func(category, 0, userData))
cancel = true;
}
}
- ~Progress()
- {
+ ~Progress() {
if (m_func) {
if (!m_func(m_category, 100, m_userData))
cancel = true;
}
}
- void update()
- {
+ void update() {
if (!m_func)
return;
m_mutex.lock();
@@ -3437,8 +3448,7 @@ struct Progress
m_mutex.unlock();
}
- void setMaxValue(uint32_t maxValue)
- {
+ void setMaxValue(uint32_t maxValue) {
m_mutex.lock();
m_maxValue = maxValue;
m_mutex.unlock();
@@ -3456,32 +3466,32 @@ private:
std::mutex m_mutex;
};
-struct Spinlock
-{
- void lock() { while(m_lock.test_and_set(std::memory_order_acquire)) {} }
+struct Spinlock {
+ void lock() {
+ while (m_lock.test_and_set(std::memory_order_acquire)) {
+ }
+ }
void unlock() { m_lock.clear(std::memory_order_release); }
private:
std::atomic_flag m_lock = ATOMIC_FLAG_INIT;
};
-struct TaskGroupHandle
-{
+struct TaskGroupHandle {
uint32_t value = UINT32_MAX;
};
-struct Task
-{
+struct Task {
void (*func)(void *userData);
void *userData;
};
#if XA_MULTITHREADED
-class TaskScheduler
-{
+class TaskScheduler {
public:
- TaskScheduler() : m_shutdown(false)
- {
+ TaskScheduler() :
+ m_shutdown(false) {
+ m_threadIndex = 0;
// Max with current task scheduler usage is 1 per thread + 1 deep nesting, but allow for some slop.
m_maxGroups = std::thread::hardware_concurrency() * 4;
m_groups = XA_ALLOC_ARRAY(MemTag::Default, TaskGroup, m_maxGroups);
@@ -3494,12 +3504,11 @@ public:
for (uint32_t i = 0; i < m_workers.size(); i++) {
new (&m_workers[i]) Worker();
m_workers[i].wakeup = false;
- m_workers[i].thread = XA_NEW_ARGS(MemTag::Default, std::thread, workerThread, this, &m_workers[i]);
+ m_workers[i].thread = XA_NEW_ARGS(MemTag::Default, std::thread, workerThread, this, &m_workers[i], i + 1);
}
}
- ~TaskScheduler()
- {
+ ~TaskScheduler() {
m_shutdown = true;
for (uint32_t i = 0; i < m_workers.size(); i++) {
Worker &worker = m_workers[i];
@@ -3517,8 +3526,11 @@ public:
XA_FREE(m_groups);
}
- TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0)
- {
+ uint32_t threadCount() const {
+ return max(1u, std::thread::hardware_concurrency()); // Including the main thread.
+ }
+
+ TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0) {
// Claim the first free group.
for (uint32_t i = 0; i < m_maxGroups; i++) {
TaskGroup &group = m_groups[i];
@@ -3540,8 +3552,7 @@ public:
return handle;
}
- void run(TaskGroupHandle handle, Task task)
- {
+ void run(TaskGroupHandle handle, Task task) {
XA_DEBUG_ASSERT(handle.value != UINT32_MAX);
TaskGroup &group = m_groups[handle.value];
group.queueLock.lock();
@@ -3555,8 +3566,7 @@ public:
}
}
- void wait(TaskGroupHandle *handle)
- {
+ void wait(TaskGroupHandle *handle) {
if (handle->value == UINT32_MAX) {
XA_DEBUG_ASSERT(false);
return;
@@ -3581,9 +3591,10 @@ public:
handle->value = UINT32_MAX;
}
+ static uint32_t currentThreadIndex() { return m_threadIndex; }
+
private:
- struct TaskGroup
- {
+ struct TaskGroup {
std::atomic<bool> free;
Array<Task> queue; // Items are never removed. queueHead is incremented to pop items.
uint32_t queueHead = 0;
@@ -3591,8 +3602,7 @@ private:
std::atomic<uint32_t> ref; // Increment when a task is enqueued, decrement when a task finishes.
};
- struct Worker
- {
+ struct Worker {
std::thread *thread = nullptr;
std::mutex mutex;
std::condition_variable cv;
@@ -3603,12 +3613,13 @@ private:
uint32_t m_maxGroups;
Array<Worker> m_workers;
std::atomic<bool> m_shutdown;
+ static thread_local uint32_t m_threadIndex;
- static void workerThread(TaskScheduler *scheduler, Worker *worker)
- {
+ static void workerThread(TaskScheduler *scheduler, Worker *worker, uint32_t threadIndex) {
+ m_threadIndex = threadIndex;
std::unique_lock<std::mutex> lock(worker->mutex);
for (;;) {
- worker->cv.wait(lock, [=]{ return worker->wakeup.load(); });
+ worker->cv.wait(lock, [=] { return worker->wakeup.load(); });
worker->wakeup = false;
for (;;) {
if (scheduler->m_shutdown)
@@ -3636,18 +3647,21 @@ private:
}
}
};
+
+thread_local uint32_t TaskScheduler::m_threadIndex;
#else
-class TaskScheduler
-{
+class TaskScheduler {
public:
- ~TaskScheduler()
- {
+ ~TaskScheduler() {
for (uint32_t i = 0; i < m_groups.size(); i++)
destroyGroup({ i });
}
- TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0)
- {
+ uint32_t threadCount() const {
+ return 1;
+ }
+
+ TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0) {
TaskGroup *group = XA_NEW(MemTag::Default, TaskGroup);
group->queue.reserve(reserveSize);
m_groups.push_back(group);
@@ -3656,13 +3670,11 @@ public:
return handle;
}
- void run(TaskGroupHandle handle, Task task)
- {
+ void run(TaskGroupHandle handle, Task task) {
m_groups[handle.value]->queue.push_back(task);
}
- void wait(TaskGroupHandle *handle)
- {
+ void wait(TaskGroupHandle *handle) {
if (handle->value == UINT32_MAX) {
XA_DEBUG_ASSERT(false);
return;
@@ -3675,9 +3687,10 @@ public:
handle->value = UINT32_MAX;
}
+ static uint32_t currentThreadIndex() { return 0; }
+
private:
- void destroyGroup(TaskGroupHandle handle)
- {
+ void destroyGroup(TaskGroupHandle handle) {
TaskGroup *group = m_groups[handle.value];
if (group) {
group->~TaskGroup();
@@ -3686,8 +3699,7 @@ private:
}
}
- struct TaskGroup
- {
+ struct TaskGroup {
Array<Task> queue;
};
@@ -3695,34 +3707,369 @@ private:
};
#endif
-struct UvMeshChart
-{
+#if XA_DEBUG_EXPORT_TGA
+const uint8_t TGA_TYPE_RGB = 2;
+const uint8_t TGA_ORIGIN_UPPER = 0x20;
+
+#pragma pack(push, 1)
+struct TgaHeader {
+ uint8_t id_length;
+ uint8_t colormap_type;
+ uint8_t image_type;
+ uint16_t colormap_index;
+ uint16_t colormap_length;
+ uint8_t colormap_size;
+ uint16_t x_origin;
+ uint16_t y_origin;
+ uint16_t width;
+ uint16_t height;
+ uint8_t pixel_size;
+ uint8_t flags;
+ enum { Size = 18 };
+};
+#pragma pack(pop)
+
+static void WriteTga(const char *filename, const uint8_t *data, uint32_t width, uint32_t height) {
+ XA_DEBUG_ASSERT(sizeof(TgaHeader) == TgaHeader::Size);
+ FILE *f;
+ XA_FOPEN(f, filename, "wb");
+ if (!f)
+ return;
+ TgaHeader tga;
+ tga.id_length = 0;
+ tga.colormap_type = 0;
+ tga.image_type = TGA_TYPE_RGB;
+ tga.colormap_index = 0;
+ tga.colormap_length = 0;
+ tga.colormap_size = 0;
+ tga.x_origin = 0;
+ tga.y_origin = 0;
+ tga.width = (uint16_t)width;
+ tga.height = (uint16_t)height;
+ tga.pixel_size = 24;
+ tga.flags = TGA_ORIGIN_UPPER;
+ fwrite(&tga, sizeof(TgaHeader), 1, f);
+ fwrite(data, sizeof(uint8_t), width * height * 3, f);
+ fclose(f);
+}
+#endif
+
+template <typename T>
+class ThreadLocal {
+public:
+ ThreadLocal() {
+#if XA_MULTITHREADED
+ const uint32_t n = std::thread::hardware_concurrency();
+#else
+ const uint32_t n = 1;
+#endif
+ m_array = XA_ALLOC_ARRAY(MemTag::Default, T, n);
+ for (uint32_t i = 0; i < n; i++)
+ new (&m_array[i]) T;
+ }
+
+ ~ThreadLocal() {
+#if XA_MULTITHREADED
+ const uint32_t n = std::thread::hardware_concurrency();
+#else
+ const uint32_t n = 1;
+#endif
+ for (uint32_t i = 0; i < n; i++)
+ m_array[i].~T();
+ XA_FREE(m_array);
+ }
+
+ T &get() const {
+ return m_array[TaskScheduler::currentThreadIndex()];
+ }
+
+private:
+ T *m_array;
+};
+
+class UniformGrid2 {
+public:
+ void reset(const Vector2 *positions, const uint32_t *indices = nullptr, uint32_t reserveEdgeCount = 0) {
+ m_edges.clear();
+ if (reserveEdgeCount > 0)
+ m_edges.reserve(reserveEdgeCount);
+ m_positions = positions;
+ m_indices = indices;
+ m_cellDataOffsets.clear();
+ }
+
+ void append(uint32_t edge) {
+ XA_DEBUG_ASSERT(m_cellDataOffsets.isEmpty());
+ m_edges.push_back(edge);
+ }
+
+ bool intersect(Vector2 v1, Vector2 v2, float epsilon) {
+ const uint32_t edgeCount = m_edges.size();
+ bool bruteForce = edgeCount <= 64;
+ if (!bruteForce && m_cellDataOffsets.isEmpty())
+ bruteForce = !createGrid();
+ if (bruteForce) {
+ for (uint32_t j = 0; j < edgeCount; j++) {
+ const uint32_t edge = m_edges[j];
+ if (linesIntersect(v1, v2, edgePosition0(edge), edgePosition1(edge), epsilon))
+ return true;
+ }
+ } else {
+ computePotentialEdges(v1, v2);
+ uint32_t prevEdge = UINT32_MAX;
+ for (uint32_t j = 0; j < m_potentialEdges.size(); j++) {
+ const uint32_t edge = m_potentialEdges[j];
+ if (edge == prevEdge)
+ continue;
+ if (linesIntersect(v1, v2, edgePosition0(edge), edgePosition1(edge), epsilon))
+ return true;
+ prevEdge = edge;
+ }
+ }
+ return false;
+ }
+
+ bool intersectSelf(float epsilon) {
+ const uint32_t edgeCount = m_edges.size();
+ bool bruteForce = edgeCount <= 64;
+ if (!bruteForce && m_cellDataOffsets.isEmpty())
+ bruteForce = !createGrid();
+ for (uint32_t i = 0; i < edgeCount; i++) {
+ const uint32_t edge1 = m_edges[i];
+ if (bruteForce) {
+ for (uint32_t j = 0; j < edgeCount; j++) {
+ const uint32_t edge2 = m_edges[j];
+ if (edgesIntersect(edge1, edge2, epsilon))
+ return true;
+ }
+ } else {
+ computePotentialEdges(edgePosition0(edge1), edgePosition1(edge1));
+ uint32_t prevEdge = UINT32_MAX;
+ for (uint32_t j = 0; j < m_potentialEdges.size(); j++) {
+ const uint32_t edge2 = m_potentialEdges[j];
+ if (edge2 == prevEdge)
+ continue;
+ if (edgesIntersect(edge1, edge2, epsilon))
+ return true;
+ prevEdge = edge2;
+ }
+ }
+ }
+ return false;
+ }
+
+#if XA_DEBUG_EXPORT_BOUNDARY_GRID
+ void debugExport(const char *filename) {
+ Array<uint8_t> image;
+ image.resize(m_gridWidth * m_gridHeight * 3);
+ for (uint32_t y = 0; y < m_gridHeight; y++) {
+ for (uint32_t x = 0; x < m_gridWidth; x++) {
+ uint8_t *bgr = &image[(x + y * m_gridWidth) * 3];
+ bgr[0] = bgr[1] = bgr[2] = 32;
+ uint32_t offset = m_cellDataOffsets[x + y * m_gridWidth];
+ while (offset != UINT32_MAX) {
+ const uint32_t edge2 = m_cellData[offset];
+ srand(edge2);
+ for (uint32_t i = 0; i < 3; i++)
+ bgr[i] = uint8_t(bgr[i] * 0.5f + (rand() % 255) * 0.5f);
+ offset = m_cellData[offset + 1];
+ }
+ }
+ }
+ WriteTga(filename, image.data(), m_gridWidth, m_gridHeight);
+ }
+#endif
+
+private:
+ bool createGrid() {
+ // Compute edge extents. Min will be the grid origin.
+ const uint32_t edgeCount = m_edges.size();
+ Extents2 edgeExtents;
+ edgeExtents.reset();
+ for (uint32_t i = 0; i < edgeCount; i++) {
+ const uint32_t edge = m_edges[i];
+ edgeExtents.add(edgePosition0(edge));
+ edgeExtents.add(edgePosition1(edge));
+ }
+ m_gridOrigin = edgeExtents.min;
+ // Size grid to approximately one edge per cell.
+ const Vector2 extentsSize(edgeExtents.max - edgeExtents.min);
+ m_cellSize = min(extentsSize.x, extentsSize.y) / sqrtf((float)edgeCount);
+ if (m_cellSize <= 0.0f)
+ return false;
+ m_gridWidth = uint32_t(ceilf(extentsSize.x / m_cellSize));
+ m_gridHeight = uint32_t(ceilf(extentsSize.y / m_cellSize));
+ if (m_gridWidth == 0 || m_gridHeight == 0)
+ return false;
+ // Insert edges into cells.
+ m_cellDataOffsets.resize(m_gridWidth * m_gridHeight);
+ for (uint32_t i = 0; i < m_cellDataOffsets.size(); i++)
+ m_cellDataOffsets[i] = UINT32_MAX;
+ m_cellData.clear();
+ m_cellData.reserve(edgeCount * 2);
+ for (uint32_t i = 0; i < edgeCount; i++) {
+ const uint32_t edge = m_edges[i];
+ traverse(edgePosition0(edge), edgePosition1(edge));
+ XA_DEBUG_ASSERT(!m_traversedCellOffsets.isEmpty());
+ for (uint32_t j = 0; j < m_traversedCellOffsets.size(); j++) {
+ const uint32_t cell = m_traversedCellOffsets[j];
+ uint32_t offset = m_cellDataOffsets[cell];
+ if (offset == UINT32_MAX)
+ m_cellDataOffsets[cell] = m_cellData.size();
+ else {
+ for (;;) {
+ uint32_t &nextOffset = m_cellData[offset + 1];
+ if (nextOffset == UINT32_MAX) {
+ nextOffset = m_cellData.size();
+ break;
+ }
+ offset = nextOffset;
+ }
+ }
+ m_cellData.push_back(edge);
+ m_cellData.push_back(UINT32_MAX);
+ }
+ }
+ return true;
+ }
+
+ void computePotentialEdges(Vector2 p1, Vector2 p2) {
+ m_potentialEdges.clear();
+ traverse(p1, p2);
+ for (uint32_t j = 0; j < m_traversedCellOffsets.size(); j++) {
+ const uint32_t cell = m_traversedCellOffsets[j];
+ uint32_t offset = m_cellDataOffsets[cell];
+ while (offset != UINT32_MAX) {
+ const uint32_t edge2 = m_cellData[offset];
+ m_potentialEdges.push_back(edge2);
+ offset = m_cellData[offset + 1];
+ }
+ }
+ if (m_potentialEdges.isEmpty())
+ return;
+ insertionSort(m_potentialEdges.data(), m_potentialEdges.size());
+ }
+
+ // "A Fast Voxel Traversal Algorithm for Ray Tracing"
+ void traverse(Vector2 p1, Vector2 p2) {
+ const Vector2 dir = p2 - p1;
+ const Vector2 normal = normalizeSafe(dir, Vector2(0.0f), kEpsilon);
+ const int stepX = dir.x >= 0 ? 1 : -1;
+ const int stepY = dir.y >= 0 ? 1 : -1;
+ const uint32_t firstCell[2] = { cellX(p1.x), cellY(p1.y) };
+ const uint32_t lastCell[2] = { cellX(p2.x), cellY(p2.y) };
+ float distToNextCellX;
+ if (stepX == 1)
+ distToNextCellX = (firstCell[0] + 1) * m_cellSize - (p1.x - m_gridOrigin.x);
+ else
+ distToNextCellX = (p1.x - m_gridOrigin.x) - firstCell[0] * m_cellSize;
+ float distToNextCellY;
+ if (stepY == 1)
+ distToNextCellY = (firstCell[1] + 1) * m_cellSize - (p1.y - m_gridOrigin.y);
+ else
+ distToNextCellY = (p1.y - m_gridOrigin.y) - firstCell[1] * m_cellSize;
+ float tMaxX, tMaxY, tDeltaX, tDeltaY;
+ if (normal.x > kEpsilon || normal.x < -kEpsilon) {
+ tMaxX = (distToNextCellX * stepX) / normal.x;
+ tDeltaX = (m_cellSize * stepX) / normal.x;
+ } else
+ tMaxX = tDeltaX = FLT_MAX;
+ if (normal.y > kEpsilon || normal.y < -kEpsilon) {
+ tMaxY = (distToNextCellY * stepY) / normal.y;
+ tDeltaY = (m_cellSize * stepY) / normal.y;
+ } else
+ tMaxY = tDeltaY = FLT_MAX;
+ m_traversedCellOffsets.clear();
+ m_traversedCellOffsets.push_back(firstCell[0] + firstCell[1] * m_gridWidth);
+ uint32_t currentCell[2] = { firstCell[0], firstCell[1] };
+ while (!(currentCell[0] == lastCell[0] && currentCell[1] == lastCell[1])) {
+ if (tMaxX < tMaxY) {
+ tMaxX += tDeltaX;
+ currentCell[0] += stepX;
+ } else {
+ tMaxY += tDeltaY;
+ currentCell[1] += stepY;
+ }
+ if (currentCell[0] >= m_gridWidth || currentCell[1] >= m_gridHeight)
+ break;
+ if (stepX == 0 && currentCell[0] < lastCell[0])
+ break;
+ if (stepX == 1 && currentCell[0] > lastCell[0])
+ break;
+ if (stepY == 0 && currentCell[1] < lastCell[1])
+ break;
+ if (stepY == 1 && currentCell[1] > lastCell[1])
+ break;
+ m_traversedCellOffsets.push_back(currentCell[0] + currentCell[1] * m_gridWidth);
+ }
+ }
+
+ bool edgesIntersect(uint32_t edge1, uint32_t edge2, float epsilon) const {
+ if (edge1 == edge2)
+ return false;
+ const uint32_t ai[2] = { vertexAt(meshEdgeIndex0(edge1)), vertexAt(meshEdgeIndex1(edge1)) };
+ const uint32_t bi[2] = { vertexAt(meshEdgeIndex0(edge2)), vertexAt(meshEdgeIndex1(edge2)) };
+ // Ignore connected edges, since they can't intersect (only overlap), and may be detected as false positives.
+ if (ai[0] == bi[0] || ai[0] == bi[1] || ai[1] == bi[0] || ai[1] == bi[1])
+ return false;
+ return linesIntersect(m_positions[ai[0]], m_positions[ai[1]], m_positions[bi[0]], m_positions[bi[1]], epsilon);
+ }
+
+ uint32_t cellX(float x) const {
+ return min((uint32_t)max(0.0f, (x - m_gridOrigin.x) / m_cellSize), m_gridWidth - 1u);
+ }
+
+ uint32_t cellY(float y) const {
+ return min((uint32_t)max(0.0f, (y - m_gridOrigin.y) / m_cellSize), m_gridHeight - 1u);
+ }
+
+ Vector2 edgePosition0(uint32_t edge) const {
+ return m_positions[vertexAt(meshEdgeIndex0(edge))];
+ }
+
+ Vector2 edgePosition1(uint32_t edge) const {
+ return m_positions[vertexAt(meshEdgeIndex1(edge))];
+ }
+
+ uint32_t vertexAt(uint32_t index) const {
+ return m_indices ? m_indices[index] : index;
+ }
+
+ Array<uint32_t> m_edges;
+ const Vector2 *m_positions;
+ const uint32_t *m_indices; // Optional
+ float m_cellSize;
+ Vector2 m_gridOrigin;
+ uint32_t m_gridWidth, m_gridHeight; // in cells
+ Array<uint32_t> m_cellDataOffsets;
+ Array<uint32_t> m_cellData;
+ Array<uint32_t> m_potentialEdges;
+ Array<uint32_t> m_traversedCellOffsets;
+};
+
+struct UvMeshChart {
Array<uint32_t> faces;
Array<uint32_t> indices;
uint32_t material;
};
-struct UvMesh
-{
+struct UvMesh {
UvMeshDecl decl;
Array<uint32_t> indices;
Array<UvMeshChart *> charts;
Array<uint32_t> vertexToChartMap;
};
-struct UvMeshInstance
-{
+struct UvMeshInstance {
UvMesh *mesh;
Array<Vector2> texcoords;
bool rotateCharts;
};
namespace raster {
-class ClippedTriangle
-{
+class ClippedTriangle {
public:
- ClippedTriangle(const Vector2 &a, const Vector2 &b, const Vector2 &c)
- {
+ ClippedTriangle(const Vector2 &a, const Vector2 &b, const Vector2 &c) {
m_numVertices = 3;
m_activeVertexBuffer = 0;
m_verticesA[0] = a;
@@ -3732,20 +4079,19 @@ public:
m_vertexBuffers[1] = m_verticesB;
}
- void clipHorizontalPlane(float offset, float clipdirection)
- {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void clipHorizontalPlane(float offset, float clipdirection) {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
m_activeVertexBuffer ^= 1;
Vector2 *v2 = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
- float dy2, dy1 = offset - v[0].y;
- int dy2in, dy1in = clipdirection * dy1 >= 0;
- uint32_t p = 0;
+ float dy2, dy1 = offset - v[0].y;
+ int dy2in, dy1in = clipdirection * dy1 >= 0;
+ uint32_t p = 0;
for (uint32_t k = 0; k < m_numVertices; k++) {
- dy2 = offset - v[k + 1].y;
+ dy2 = offset - v[k + 1].y;
dy2in = clipdirection * dy2 >= 0;
if (dy1in) v2[p++] = v[k];
- if ( dy1in + dy2in == 1 ) { // not both in/out
+ if (dy1in + dy2in == 1) { // not both in/out
float dx = v[k + 1].x - v[k].x;
float dy = v[k + 1].y - v[k].y;
v2[p++] = Vector2(v[k].x + dy1 * (dx / dy), offset);
@@ -3756,20 +4102,19 @@ public:
m_numVertices = p;
}
- void clipVerticalPlane(float offset, float clipdirection)
- {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void clipVerticalPlane(float offset, float clipdirection) {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
m_activeVertexBuffer ^= 1;
Vector2 *v2 = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
- float dx2, dx1 = offset - v[0].x;
- int dx2in, dx1in = clipdirection * dx1 >= 0;
- uint32_t p = 0;
+ float dx2, dx1 = offset - v[0].x;
+ int dx2in, dx1in = clipdirection * dx1 >= 0;
+ uint32_t p = 0;
for (uint32_t k = 0; k < m_numVertices; k++) {
dx2 = offset - v[k + 1].x;
dx2in = clipdirection * dx2 >= 0;
if (dx1in) v2[p++] = v[k];
- if ( dx1in + dx2in == 1 ) { // not both in/out
+ if (dx1in + dx2in == 1) { // not both in/out
float dx = v[k + 1].x - v[k].x;
float dy = v[k + 1].y - v[k].y;
v2[p++] = Vector2(offset, v[k].y + dx1 * (dy / dx));
@@ -3780,9 +4125,8 @@ public:
m_numVertices = p;
}
- void computeArea()
- {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void computeArea() {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
m_area = 0;
float centroidx = 0, centroidy = 0;
@@ -3796,8 +4140,7 @@ public:
m_area = 0.5f * fabsf(m_area);
}
- void clipAABox(float x0, float y0, float x1, float y1)
- {
+ void clipAABox(float x0, float y0, float x1, float y1) {
clipVerticalPlane(x0, -1);
clipHorizontalPlane(y0, -1);
clipVerticalPlane(x1, 1);
@@ -3805,8 +4148,7 @@ public:
computeArea();
}
- float area() const
- {
+ float area() const {
return m_area;
}
@@ -3823,10 +4165,8 @@ private:
typedef bool (*SamplingCallback)(void *param, int x, int y);
/// A triangle for rasterization.
-struct Triangle
-{
- Triangle(const Vector2 &v0, const Vector2 &v1, const Vector2 &v2)
- {
+struct Triangle {
+ Triangle(const Vector2 &v0, const Vector2 &v1, const Vector2 &v2) {
// Init vertices.
this->v1 = v0;
this->v2 = v2;
@@ -3834,30 +4174,29 @@ struct Triangle
// make sure every triangle is front facing.
flipBackface();
// Compute deltas.
- computeUnitInwardNormals();
+ if (isValid())
+ computeUnitInwardNormals();
}
- bool isValid()
- {
+ bool isValid() {
const Vector2 e0 = v3 - v1;
const Vector2 e1 = v2 - v1;
- const float denom = 1.0f / (e0.y * e1.x - e1.y * e0.x);
- return isFinite(denom);
+ const float area = e0.y * e1.x - e1.y * e0.x;
+ return area != 0.0f;
}
// extents has to be multiple of BK_SIZE!!
- bool drawAA(const Vector2 &extents, SamplingCallback cb, void *param)
- {
- const float PX_INSIDE = 1.0f/sqrtf(2.0f);
- const float PX_OUTSIDE = -1.0f/sqrtf(2.0f);
+ bool drawAA(const Vector2 &extents, SamplingCallback cb, void *param) {
+ const float PX_INSIDE = 1.0f / sqrtf(2.0f);
+ const float PX_OUTSIDE = -1.0f / sqrtf(2.0f);
const float BK_SIZE = 8;
- const float BK_INSIDE = sqrtf(BK_SIZE*BK_SIZE/2.0f);
- const float BK_OUTSIDE = -sqrtf(BK_SIZE*BK_SIZE/2.0f);
+ const float BK_INSIDE = sqrtf(BK_SIZE * BK_SIZE / 2.0f);
+ const float BK_OUTSIDE = -sqrtf(BK_SIZE * BK_SIZE / 2.0f);
// Bounding rectangle
float minx = floorf(max(min3(v1.x, v2.x, v3.x), 0.0f));
float miny = floorf(max(min3(v1.y, v2.y, v3.y), 0.0f));
- float maxx = ceilf( min(max3(v1.x, v2.x, v3.x), extents.x - 1.0f));
- float maxy = ceilf( min(max3(v1.y, v2.y, v3.y), extents.y - 1.0f));
+ float maxx = ceilf(min(max3(v1.x, v2.x, v3.x), extents.x - 1.0f));
+ float maxy = ceilf(min(max3(v1.y, v2.y, v3.y), extents.y - 1.0f));
// There's no reason to align the blocks to the viewport, instead we align them to the origin of the triangle bounds.
minx = floorf(minx);
miny = floorf(miny);
@@ -3882,9 +4221,9 @@ struct Triangle
float bC = C2 + n2.x * xc + n2.y * yc;
float cC = C3 + n3.x * xc + n3.y * yc;
// Skip block when outside an edge
- if ( (aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE) ) continue;
+ if ((aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE)) continue;
// Accept whole block when totally covered
- if ( (aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE) ) {
+ if ((aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE)) {
for (float y = y0; y < y0 + BK_SIZE; y++) {
for (float x = x0; x < x0 + BK_SIZE; x++) {
if (!cb(param, (int)x, (int)y))
@@ -3926,10 +4265,10 @@ struct Triangle
return true;
}
- void flipBackface()
- {
+private:
+ void flipBackface() {
// check if triangle is backfacing, if so, swap two vertices
- if ( ((v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)) < 0 ) {
+ if (((v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)) < 0) {
Vector2 hv = v1;
v1 = v2;
v2 = hv; // swap pos
@@ -3937,17 +4276,16 @@ struct Triangle
}
// compute unit inward normals for each edge.
- void computeUnitInwardNormals()
- {
+ void computeUnitInwardNormals() {
n1 = v1 - v2;
n1 = Vector2(-n1.y, n1.x);
- n1 = n1 * (1.0f / sqrtf(n1.x * n1.x + n1.y * n1.y));
+ n1 = n1 * (1.0f / sqrtf(dot(n1, n1)));
n2 = v2 - v3;
n2 = Vector2(-n2.y, n2.x);
- n2 = n2 * (1.0f / sqrtf(n2.x * n2.x + n2.y * n2.y));
+ n2 = n2 * (1.0f / sqrtf(dot(n2, n2)));
n3 = v3 - v1;
n3 = Vector2(-n3.y, n3.x);
- n3 = n3 * (1.0f / sqrtf(n3.x * n3.x + n3.y * n3.y));
+ n3 = n3 * (1.0f / sqrtf(dot(n3, n3)));
}
// Vertices.
@@ -3956,8 +4294,7 @@ struct Triangle
};
// Process the given triangle. Returns false if rasterization was interrupted by the callback.
-static bool drawTriangle(const Vector2 &extents, const Vector2 v[3], SamplingCallback cb, void *param)
-{
+static bool drawTriangle(const Vector2 &extents, const Vector2 v[3], SamplingCallback cb, void *param) {
Triangle tri(v[0], v[1], v[2]);
// @@ It would be nice to have a conservative drawing mode that enlarges the triangle extents by one texel and is able to handle degenerate triangles.
// @@ Maybe the simplest thing to do would be raster triangle edges.
@@ -3980,47 +4317,48 @@ namespace sparse {
* elements for each row of the matrix. As with the FullVector the
* dimension of the matrix is constant.
**/
-class Matrix
-{
+class Matrix {
public:
// An element of the sparse array.
- struct Coefficient
- {
- uint32_t x; // column
+ struct Coefficient {
+ uint32_t x; // column
float v; // value
};
- Matrix(uint32_t d) : m_width(d)
- {
+ Matrix(uint32_t d) :
+ m_width(d), m_array(MemTag::Matrix) {
m_array.resize(d);
- for (uint32_t i = 0; i < m_array.size(); i++)
- new (&m_array[i]) Array<Coefficient>();
+ m_array.runCtors();
+#if XA_DEBUG_HEAP
+ for (uint32_t i = 0; i < d; i++)
+ m_array[i].setMemTag(MemTag::Matrix);
+#endif
}
-
- Matrix(uint32_t w, uint32_t h) : m_width(w)
- {
+
+ Matrix(uint32_t w, uint32_t h) :
+ m_width(w), m_array(MemTag::Matrix) {
m_array.resize(h);
- for (uint32_t i = 0; i < m_array.size(); i++)
- new (&m_array[i]) Array<Coefficient>();
+ m_array.runCtors();
+#if XA_DEBUG_HEAP
+ for (uint32_t i = 0; i < h; i++)
+ m_array[i].setMemTag(MemTag::Matrix);
+#endif
}
-
- ~Matrix()
- {
- for (uint32_t i = 0; i < m_array.size(); i++)
- m_array[i].~Array();
+
+ ~Matrix() {
+ m_array.runDtors();
}
Matrix(const Matrix &m) = delete;
- const Matrix &operator=(const Matrix &m) = delete;
+ Matrix &operator=(const Matrix &m) = delete;
uint32_t width() const { return m_width; }
uint32_t height() const { return m_array.size(); }
bool isSquare() const { return width() == height(); }
// x is column, y is row
- float getCoefficient(uint32_t x, uint32_t y) const
- {
- XA_DEBUG_ASSERT( x < width() );
- XA_DEBUG_ASSERT( y < height() );
+ float getCoefficient(uint32_t x, uint32_t y) const {
+ XA_DEBUG_ASSERT(x < width());
+ XA_DEBUG_ASSERT(y < height());
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
if (m_array[y][i].x == x) return m_array[y][i].v;
@@ -4028,10 +4366,9 @@ public:
return 0.0f;
}
- void setCoefficient(uint32_t x, uint32_t y, float f)
- {
- XA_DEBUG_ASSERT( x < width() );
- XA_DEBUG_ASSERT( y < height() );
+ void setCoefficient(uint32_t x, uint32_t y, float f) {
+ XA_DEBUG_ASSERT(x < width());
+ XA_DEBUG_ASSERT(y < height());
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
if (m_array[y][i].x == x) {
@@ -4041,13 +4378,12 @@ public:
}
if (f != 0.0f) {
Coefficient c = { x, f };
- m_array[y].push_back( c );
+ m_array[y].push_back(c);
}
}
- float dotRow(uint32_t y, const FullVector &v) const
- {
- XA_DEBUG_ASSERT( y < height() );
+ float dotRow(uint32_t y, const FullVector &v) const {
+ XA_DEBUG_ASSERT(y < height());
const uint32_t count = m_array[y].size();
float sum = 0;
for (uint32_t i = 0; i < count; i++) {
@@ -4056,8 +4392,7 @@ public:
return sum;
}
- void madRow(uint32_t y, float alpha, FullVector &v) const
- {
+ void madRow(uint32_t y, float alpha, FullVector &v) const {
XA_DEBUG_ASSERT(y < height());
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
@@ -4065,9 +4400,8 @@ public:
}
}
- void clearRow(uint32_t y)
- {
- XA_DEBUG_ASSERT( y < height() );
+ void clearRow(uint32_t y) {
+ XA_DEBUG_ASSERT(y < height());
m_array[y].clear();
}
@@ -4078,12 +4412,11 @@ private:
const uint32_t m_width;
/// Array of matrix elements.
- Array< Array<Coefficient> > m_array;
+ Array<Array<Coefficient>> m_array;
};
// y = a * x + y
-static void saxpy(float a, const FullVector &x, FullVector &y)
-{
+static void saxpy(float a, const FullVector &x, FullVector &y) {
XA_DEBUG_ASSERT(x.dimension() == y.dimension());
const uint32_t dim = x.dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -4091,8 +4424,7 @@ static void saxpy(float a, const FullVector &x, FullVector &y)
}
}
-static void copy(const FullVector &x, FullVector &y)
-{
+static void copy(const FullVector &x, FullVector &y) {
XA_DEBUG_ASSERT(x.dimension() == y.dimension());
const uint32_t dim = x.dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -4100,16 +4432,14 @@ static void copy(const FullVector &x, FullVector &y)
}
}
-static void scal(float a, FullVector &x)
-{
+static void scal(float a, FullVector &x) {
const uint32_t dim = x.dimension();
for (uint32_t i = 0; i < dim; i++) {
x[i] *= a;
}
}
-static float dot(const FullVector &x, const FullVector &y)
-{
+static float dot(const FullVector &x, const FullVector &y) {
XA_DEBUG_ASSERT(x.dimension() == y.dimension());
const uint32_t dim = x.dimension();
float sum = 0;
@@ -4120,24 +4450,22 @@ static float dot(const FullVector &x, const FullVector &y)
}
// y = M * x
-static void mult(const Matrix &M, const FullVector &x, FullVector &y)
-{
+static void mult(const Matrix &M, const FullVector &x, FullVector &y) {
uint32_t w = M.width();
uint32_t h = M.height();
- XA_DEBUG_ASSERT( w == x.dimension() );
+ XA_DEBUG_ASSERT(w == x.dimension());
XA_UNUSED(w);
- XA_DEBUG_ASSERT( h == y.dimension() );
+ XA_DEBUG_ASSERT(h == y.dimension());
for (uint32_t i = 0; i < h; i++)
y[i] = M.dotRow(i, x);
}
// y = alpha*A*x + beta*y
-static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta, FullVector &y)
-{
+static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta, FullVector &y) {
const uint32_t w = A.width();
const uint32_t h = A.height();
- XA_DEBUG_ASSERT( w == x.dimension() );
- XA_DEBUG_ASSERT( h == y.dimension() );
+ XA_DEBUG_ASSERT(w == x.dimension());
+ XA_DEBUG_ASSERT(h == y.dimension());
XA_UNUSED(w);
XA_UNUSED(h);
for (uint32_t i = 0; i < h; i++)
@@ -4145,8 +4473,7 @@ static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta,
}
// dot y-row of A by x-column of B
-static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B)
-{
+static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B) {
const Array<Matrix::Coefficient> &row = A.getRow(y);
const uint32_t count = row.size();
float sum = 0.0f;
@@ -4157,8 +4484,7 @@ static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B)
return sum;
}
-static void transpose(const Matrix &A, Matrix &B)
-{
+static void transpose(const Matrix &A, Matrix &B) {
XA_DEBUG_ASSERT(A.width() == B.height());
XA_DEBUG_ASSERT(B.width() == A.height());
const uint32_t w = A.width();
@@ -4177,8 +4503,7 @@ static void transpose(const Matrix &A, Matrix &B)
}
}
-static void sgemm(float alpha, const Matrix &A, const Matrix &B, float beta, Matrix &C)
-{
+static void sgemm(float alpha, const Matrix &A, const Matrix &B, float beta, Matrix &C) {
const uint32_t w = C.width();
const uint32_t h = C.height();
#if XA_DEBUG
@@ -4202,8 +4527,7 @@ static void sgemm(float alpha, const Matrix &A, const Matrix &B, float beta, Mat
}
// C = A * B
-static void mult(const Matrix &A, const Matrix &B, Matrix &C)
-{
+static void mult(const Matrix &A, const Matrix &B, Matrix &C) {
sgemm(1.0f, A, B, 0.0f, C);
}
@@ -4211,164 +4535,155 @@ static void mult(const Matrix &A, const Matrix &B, Matrix &C)
namespace segment {
-// Dummy implementation of a priority queue using sort at insertion.
// - Insertion is o(n)
// - Smallest element goes at the end, so that popping it is o(1).
-// - Resorting is n*log(n)
-// @@ Number of elements in the queue is usually small, and we'd have to rebalance often. I'm not sure it's worth implementing a heap.
-// @@ Searcing at removal would remove the need for sorting when priorities change.
-struct PriorityQueue
-{
- PriorityQueue(uint32_t size = UINT32_MAX) : maxSize(size) {}
+struct CostQueue {
+ CostQueue(uint32_t size = UINT32_MAX) :
+ m_maxSize(size), m_pairs(MemTag::SegmentAtlasChartCandidates) {}
- void push(float priority, uint32_t face)
- {
- uint32_t i = 0;
- const uint32_t count = pairs.size();
- for (; i < count; i++) {
- if (pairs[i].priority > priority) break;
- }
- Pair p = { priority, face };
- pairs.insertAt(i, p);
- if (pairs.size() > maxSize)
- pairs.removeAt(0);
+ float peekCost() const {
+ return m_pairs.back().cost;
}
- // push face out of order, to be sorted later.
- void push(uint32_t face)
- {
- Pair p = { 0.0f, face };
- pairs.push_back(p);
+ uint32_t peekFace() const {
+ return m_pairs.back().face;
}
- uint32_t pop()
- {
- XA_DEBUG_ASSERT(!pairs.isEmpty());
- uint32_t f = pairs.back().face;
- pairs.pop_back();
- return f;
- }
-
- void sort()
- {
- //sort(pairs); // @@ My intro sort appears to be much slower than it should!
- std::sort(pairs.begin(), pairs.end());
+ void push(float cost, uint32_t face) {
+ const Pair p = { cost, face };
+ if (m_pairs.isEmpty() || cost < peekCost())
+ m_pairs.push_back(p);
+ else {
+ uint32_t i = 0;
+ const uint32_t count = m_pairs.size();
+ for (; i < count; i++) {
+ if (m_pairs[i].cost < cost)
+ break;
+ }
+ m_pairs.insertAt(i, p);
+ if (m_pairs.size() > m_maxSize)
+ m_pairs.removeAt(0);
+ }
}
- XA_INLINE void clear()
- {
- pairs.clear();
+ uint32_t pop() {
+ XA_DEBUG_ASSERT(!m_pairs.isEmpty());
+ uint32_t f = m_pairs.back().face;
+ m_pairs.pop_back();
+ return f;
}
- XA_INLINE uint32_t count() const
- {
- return pairs.size();
+ XA_INLINE void clear() {
+ m_pairs.clear();
}
- float firstPriority() const
- {
- return pairs.back().priority;
+ XA_INLINE uint32_t count() const {
+ return m_pairs.size();
}
- const uint32_t maxSize;
-
- struct Pair
- {
- bool operator<(const Pair &p) const
- {
- return priority > p.priority; // !! Sort in inverse priority order!
- }
+private:
+ const uint32_t m_maxSize;
- float priority;
+ struct Pair {
+ float cost;
uint32_t face;
};
- Array<Pair> pairs;
+ Array<Pair> m_pairs;
};
-struct Chart
-{
+struct Chart {
+ Chart() :
+ faces(MemTag::SegmentAtlasChartFaces) {}
+
int id = -1;
- Vector3 averageNormal = Vector3(0.0f);
+ Basis basis; // Best fit normal.
float area = 0.0f;
float boundaryLength = 0.0f;
- Vector3 normalSum = Vector3(0.0f);
Vector3 centroidSum = Vector3(0.0f); // Sum of chart face centroids.
Vector3 centroid = Vector3(0.0f); // Average centroid of chart faces.
Array<uint32_t> seeds;
Array<uint32_t> faces;
- PriorityQueue candidates;
- Basis basis; // Of first face.
+ Array<uint32_t> failedPlanarRegions;
+ CostQueue candidates;
};
-struct Atlas
-{
- // @@ Hardcoded to 10?
- Atlas(const Mesh *mesh, Array<uint32_t> *meshFaces, const ChartOptions &options) : m_mesh(mesh), m_meshFaces(meshFaces), m_facesLeft(mesh->faceCount()), m_bestTriangles(10), m_options(options)
- {
+struct Atlas {
+ Atlas() :
+ m_edgeLengths(MemTag::SegmentAtlasMeshData), m_faceAreas(MemTag::SegmentAtlasMeshData), m_faceNormals(MemTag::SegmentAtlasMeshData), m_texcoords(MemTag::SegmentAtlasMeshData), m_bestTriangles(10), m_nextPlanarRegionFace(MemTag::SegmentAtlasPlanarRegions), m_facePlanarRegionId(MemTag::SegmentAtlasPlanarRegions) {}
+
+ ~Atlas() {
+ const uint32_t chartCount = m_charts.size();
+ for (uint32_t i = 0; i < chartCount; i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
+ }
+ }
+
+ uint32_t facesLeft() const { return m_facesLeft; }
+ uint32_t chartCount() const { return m_charts.size(); }
+ const Array<uint32_t> &chartFaces(uint32_t i) const { return m_charts[i]->faces; }
+ const Basis &chartBasis(uint32_t chartIndex) const { return m_charts[chartIndex]->basis; }
+
+ void reset(uint32_t meshId, uint32_t chartGroupId, const Mesh *mesh, const ChartOptions &options) {
+ XA_UNUSED(meshId);
+ XA_UNUSED(chartGroupId);
XA_PROFILE_START(buildAtlasInit)
+ m_mesh = mesh;
const uint32_t faceCount = m_mesh->faceCount();
- if (meshFaces) {
- m_ignoreFaces.resize(faceCount);
- m_ignoreFaces.setAll(true);
- for (uint32_t f = 0; f < meshFaces->size(); f++)
- m_ignoreFaces[(*meshFaces)[f]] = false;
- m_facesLeft = meshFaces->size();
- } else {
- m_ignoreFaces.resize(faceCount);
- m_ignoreFaces.setAll(false);
+ m_facesLeft = faceCount;
+ m_options = options;
+ m_rand.reset();
+ const uint32_t chartCount = m_charts.size();
+ for (uint32_t i = 0; i < chartCount; i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
}
- m_faceChartArray.resize(faceCount);
- m_faceChartArray.setAll(-1);
- m_faceCandidateCharts.resize(faceCount);
- m_faceCandidateCosts.resize(faceCount);
+ m_charts.clear();
+ m_faceCharts.resize(faceCount);
+ m_faceCharts.setAll(-1);
m_texcoords.resize(faceCount * 3);
- // @@ Floyd for the whole mesh is too slow. We could compute floyd progressively per patch as the patch grows. We need a better solution to compute most central faces.
- //computeShortestPaths();
// Precompute edge lengths and face areas.
const uint32_t edgeCount = m_mesh->edgeCount();
m_edgeLengths.resize(edgeCount);
- m_edgeLengths.zeroOutMemory();
m_faceAreas.resize(faceCount);
- m_faceAreas.zeroOutMemory();
m_faceNormals.resize(faceCount);
- m_faceTangents.resize(faceCount);
- m_faceBitangents.resize(faceCount);
for (uint32_t f = 0; f < faceCount; f++) {
- if (m_ignoreFaces[f])
- continue;
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- m_edgeLengths[it.edge()] = internal::length(it.position1() - it.position0());
- XA_DEBUG_ASSERT(m_edgeLengths[it.edge()] > 0.0f);
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t edge = f * 3 + i;
+ const Vector3 &p0 = mesh->position(m_mesh->vertexAt(meshEdgeIndex0(edge)));
+ const Vector3 &p1 = mesh->position(m_mesh->vertexAt(meshEdgeIndex1(edge)));
+ m_edgeLengths[edge] = length(p1 - p0);
+ XA_DEBUG_ASSERT(m_edgeLengths[edge] > 0.0f);
}
- m_faceAreas[f] = mesh->faceArea(f);
+ m_faceAreas[f] = m_mesh->computeFaceArea(f);
XA_DEBUG_ASSERT(m_faceAreas[f] > 0.0f);
- m_faceNormals[f] = m_mesh->triangleNormal(f);
- m_faceTangents[f] = Basis::computeTangent(m_faceNormals[f]);
- m_faceBitangents[f] = Basis::computeBitangent(m_faceNormals[f], m_faceTangents[f]);
+ m_faceNormals[f] = m_mesh->computeFaceNormal(f);
}
-#if XA_GROW_CHARTS_COPLANAR
// Precompute regions of coplanar incident faces.
m_nextPlanarRegionFace.resize(faceCount);
- for (uint32_t f = 0; f < faceCount; f++)
+ m_facePlanarRegionId.resize(faceCount);
+ for (uint32_t f = 0; f < faceCount; f++) {
m_nextPlanarRegionFace[f] = f;
+ m_facePlanarRegionId[f] = UINT32_MAX;
+ }
Array<uint32_t> faceStack;
faceStack.reserve(min(faceCount, 16u));
+ uint32_t planarRegionCount = 0;
for (uint32_t f = 0; f < faceCount; f++) {
if (m_nextPlanarRegionFace[f] != f)
continue; // Already assigned.
- if (m_ignoreFaces[f])
- continue;
faceStack.clear();
faceStack.push_back(f);
for (;;) {
if (faceStack.isEmpty())
break;
const uint32_t face = faceStack.back();
+ m_facePlanarRegionId[face] = planarRegionCount;
faceStack.pop_back();
for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
const uint32_t oface = it.oppositeFace();
- if (it.isBoundary() || m_ignoreFaces[oface])
+ if (it.isBoundary())
continue;
if (m_nextPlanarRegionFace[oface] != oface)
continue; // Already assigned.
@@ -4377,31 +4692,34 @@ struct Atlas
const uint32_t next = m_nextPlanarRegionFace[face];
m_nextPlanarRegionFace[face] = oface;
m_nextPlanarRegionFace[oface] = next;
+ m_facePlanarRegionId[oface] = planarRegionCount;
faceStack.push_back(oface);
}
}
+ planarRegionCount++;
+ }
+#if XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS
+ char filename[256];
+ XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_planar_regions.obj", meshId, chartGroupId);
+ FILE *file;
+ XA_FOPEN(file, filename, "w");
+ if (file) {
+ m_mesh->writeObjVertices(file);
+ fprintf(file, "s off\n");
+ for (uint32_t i = 0; i < planarRegionCount; i++) {
+ fprintf(file, "o region%u\n", i);
+ for (uint32_t j = 0; j < faceCount; j++) {
+ if (m_facePlanarRegionId[j] == i)
+ m_mesh->writeObjFace(file, j);
+ }
+ }
+ fclose(file);
}
#endif
XA_PROFILE_END(buildAtlasInit)
}
- ~Atlas()
- {
- const uint32_t chartCount = m_chartArray.size();
- for (uint32_t i = 0; i < chartCount; i++) {
- m_chartArray[i]->~Chart();
- XA_FREE(m_chartArray[i]);
- }
- }
-
- uint32_t facesLeft() const { return m_facesLeft; }
- uint32_t chartCount() const { return m_chartArray.size(); }
- const Array<uint32_t> &chartFaces(uint32_t i) const { return m_chartArray[i]->faces; }
- const Basis &chartBasis(uint32_t chartIndex) const { return m_chartArray[chartIndex]->basis; }
- const Vector2 *faceTexcoords(uint32_t face) const { return &m_texcoords[face * 3]; }
-
- void placeSeeds(float threshold)
- {
+ void placeSeeds(float threshold) {
XA_PROFILE_START(buildAtlasPlaceSeeds)
// Instead of using a predefiened number of seeds:
// - Add seeds one by one, growing chart until a certain treshold.
@@ -4415,82 +4733,83 @@ struct Atlas
}
// Returns true if any of the charts can grow more.
- bool growCharts(float threshold)
- {
+ void growCharts(float threshold) {
XA_PROFILE_START(buildAtlasGrowCharts)
- // Build global candidate list.
- m_faceCandidateCharts.zeroOutMemory();
- for (uint32_t i = 0; i < m_chartArray.size(); i++)
- addChartCandidateToGlobalCandidates(m_chartArray[i]);
- // Add one candidate face per chart (threshold permitting).
- const uint32_t faceCount = m_mesh->faceCount();
- bool canAddAny = false;
- for (uint32_t f = 0; f < faceCount; f++) {
- Chart *chart = m_faceCandidateCharts[f];
- if (!chart || m_faceCandidateCosts[f] > threshold)
- continue;
- createFaceTexcoords(chart, f);
- if (!canAddFaceToChart(chart, f))
- continue;
- addFaceToChart(chart, f);
- canAddAny = true;
+ for (;;) {
+ if (m_facesLeft == 0)
+ break;
+ // Get the single best candidate out of the chart best candidates.
+ uint32_t bestFace = UINT32_MAX, bestChart = UINT32_MAX;
+ float lowestCost = FLT_MAX;
+ for (uint32_t i = 0; i < m_charts.size(); i++) {
+ Chart *chart = m_charts[i];
+ // Get the best candidate from the chart.
+ // Cleanup any best candidates that have been claimed by another chart.
+ uint32_t face = UINT32_MAX;
+ float cost = FLT_MAX;
+ for (;;) {
+ if (chart->candidates.count() == 0)
+ break;
+ cost = chart->candidates.peekCost();
+ face = chart->candidates.peekFace();
+ if (m_faceCharts[face] == -1)
+ break;
+ else {
+ // Face belongs to another chart. Pop from queue so the next best candidate can be retrieved.
+ chart->candidates.pop();
+ face = UINT32_MAX;
+ }
+ }
+ if (face == UINT32_MAX)
+ continue; // No candidates for this chart.
+ // See if best candidate overall.
+ if (cost < lowestCost) {
+ lowestCost = cost;
+ bestFace = face;
+ bestChart = i;
+ }
+ }
+ if (bestFace == UINT32_MAX || lowestCost > threshold)
+ break;
+ Chart *chart = m_charts[bestChart];
+ chart->candidates.pop(); // Pop the selected candidate from the queue.
+ if (!addFaceToChart(chart, bestFace))
+ chart->failedPlanarRegions.push_back(m_facePlanarRegionId[bestFace]);
}
XA_PROFILE_END(buildAtlasGrowCharts)
- return canAddAny && m_facesLeft != 0; // Can continue growing.
}
- void resetCharts()
- {
+ void resetCharts() {
XA_PROFILE_START(buildAtlasResetCharts)
const uint32_t faceCount = m_mesh->faceCount();
for (uint32_t i = 0; i < faceCount; i++)
- m_faceChartArray[i] = -1;
- m_facesLeft = m_meshFaces ? m_meshFaces->size() : faceCount;
- const uint32_t chartCount = m_chartArray.size();
+ m_faceCharts[i] = -1;
+ m_facesLeft = faceCount;
+ const uint32_t chartCount = m_charts.size();
for (uint32_t i = 0; i < chartCount; i++) {
- Chart *chart = m_chartArray[i];
+ Chart *chart = m_charts[i];
const uint32_t seed = chart->seeds.back();
chart->area = 0.0f;
chart->boundaryLength = 0.0f;
- chart->normalSum = Vector3(0.0f);
+ chart->basis.normal = Vector3(0.0f);
+ chart->basis.tangent = Vector3(0.0f);
+ chart->basis.bitangent = Vector3(0.0f);
chart->centroidSum = Vector3(0.0f);
chart->centroid = Vector3(0.0f);
chart->faces.clear();
chart->candidates.clear();
+ chart->failedPlanarRegions.clear();
addFaceToChart(chart, seed);
}
-#if XA_GROW_CHARTS_COPLANAR
- for (uint32_t i = 0; i < chartCount; i++) {
- Chart *chart = m_chartArray[i];
- growChartCoplanar(chart);
- }
-#endif
XA_PROFILE_END(buildAtlasResetCharts)
}
- void updateChartCandidates(Chart *chart, uint32_t f)
- {
- // Traverse neighboring faces, add the ones that do not belong to any chart yet.
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- if (!it.isBoundary() && !m_ignoreFaces[it.oppositeFace()] && m_faceChartArray[it.oppositeFace()] == -1)
- chart->candidates.push(it.oppositeFace());
- }
- // Re-evaluate all candidate priorities.
- uint32_t candidateCount = chart->candidates.count();
- for (uint32_t i = 0; i < candidateCount; i++) {
- PriorityQueue::Pair &pair = chart->candidates.pairs[i];
- pair.priority = evaluateCost(chart, pair.face);
- }
- chart->candidates.sort();
- }
-
- bool relocateSeeds()
- {
+ bool relocateSeeds() {
XA_PROFILE_START(buildAtlasRelocateSeeds)
bool anySeedChanged = false;
- const uint32_t chartCount = m_chartArray.size();
+ const uint32_t chartCount = m_charts.size();
for (uint32_t i = 0; i < chartCount; i++) {
- if (relocateSeed(m_chartArray[i])) {
+ if (relocateSeed(m_charts[i])) {
anySeedChanged = true;
}
}
@@ -4498,8 +4817,7 @@ struct Atlas
return anySeedChanged;
}
- void fillHoles(float threshold)
- {
+ void fillHoles(float threshold) {
XA_PROFILE_START(buildAtlasFillHoles)
while (m_facesLeft > 0)
createRandomChart(threshold);
@@ -4507,48 +4825,40 @@ struct Atlas
}
#if XA_MERGE_CHARTS
- void mergeCharts()
- {
+ void mergeCharts() {
XA_PROFILE_START(buildAtlasMergeCharts)
- Array<float> sharedBoundaryLengths;
- Array<float> sharedBoundaryLengthsNoSeams;
- Array<uint32_t> sharedBoundaryEdgeCountNoSeams;
- Array<Vector2> tempTexcoords;
- const uint32_t chartCount = m_chartArray.size();
+ const uint32_t chartCount = m_charts.size();
// Merge charts progressively until there's none left to merge.
for (;;) {
bool merged = false;
for (int c = chartCount - 1; c >= 0; c--) {
- Chart *chart = m_chartArray[c];
+ Chart *chart = m_charts[c];
if (chart == nullptr)
continue;
float externalBoundaryLength = 0.0f;
- sharedBoundaryLengths.clear();
- sharedBoundaryLengths.resize(chartCount);
- sharedBoundaryLengths.zeroOutMemory();
- sharedBoundaryLengthsNoSeams.clear();
- sharedBoundaryLengthsNoSeams.resize(chartCount);
- sharedBoundaryLengthsNoSeams.zeroOutMemory();
- sharedBoundaryEdgeCountNoSeams.clear();
- sharedBoundaryEdgeCountNoSeams.resize(chartCount);
- sharedBoundaryEdgeCountNoSeams.zeroOutMemory();
+ m_sharedBoundaryLengths.resize(chartCount);
+ m_sharedBoundaryLengths.zeroOutMemory();
+ m_sharedBoundaryLengthsNoSeams.resize(chartCount);
+ m_sharedBoundaryLengthsNoSeams.zeroOutMemory();
+ m_sharedBoundaryEdgeCountNoSeams.resize(chartCount);
+ m_sharedBoundaryEdgeCountNoSeams.zeroOutMemory();
const uint32_t faceCount = chart->faces.size();
for (uint32_t i = 0; i < faceCount; i++) {
const uint32_t f = chart->faces[i];
for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
const float l = m_edgeLengths[it.edge()];
- if (it.isBoundary() || m_ignoreFaces[it.oppositeFace()]) {
+ if (it.isBoundary()) {
externalBoundaryLength += l;
} else {
- const int neighborChart = m_faceChartArray[it.oppositeFace()];
- if (m_chartArray[neighborChart] != chart) {
+ const int neighborChart = m_faceCharts[it.oppositeFace()];
+ if (m_charts[neighborChart] != chart) {
if ((it.isSeam() && (isNormalSeam(it.edge()) || it.isTextureSeam()))) {
externalBoundaryLength += l;
} else {
- sharedBoundaryLengths[neighborChart] += l;
+ m_sharedBoundaryLengths[neighborChart] += l;
}
- sharedBoundaryLengthsNoSeams[neighborChart] += l;
- sharedBoundaryEdgeCountNoSeams[neighborChart]++;
+ m_sharedBoundaryLengthsNoSeams[neighborChart] += l;
+ m_sharedBoundaryEdgeCountNoSeams[neighborChart]++;
}
}
}
@@ -4556,50 +4866,38 @@ struct Atlas
for (int cc = chartCount - 1; cc >= 0; cc--) {
if (cc == c)
continue;
- Chart *chart2 = m_chartArray[cc];
+ Chart *chart2 = m_charts[cc];
if (chart2 == nullptr)
continue;
+ // Must share a boundary.
+ if (m_sharedBoundaryLengths[cc] <= 0.0f)
+ continue;
// Compare proxies.
- if (dot(chart2->averageNormal, chart->averageNormal) < XA_MERGE_CHARTS_MIN_NORMAL_DEVIATION)
+ if (dot(chart2->basis.normal, chart->basis.normal) < XA_MERGE_CHARTS_MIN_NORMAL_DEVIATION)
continue;
// Obey max chart area and boundary length.
if (m_options.maxChartArea > 0.0f && chart->area + chart2->area > m_options.maxChartArea)
continue;
- if (m_options.maxBoundaryLength > 0.0f && chart->boundaryLength + chart2->boundaryLength - sharedBoundaryLengthsNoSeams[cc] > m_options.maxBoundaryLength)
+ if (m_options.maxBoundaryLength > 0.0f && chart->boundaryLength + chart2->boundaryLength - m_sharedBoundaryLengthsNoSeams[cc] > m_options.maxBoundaryLength)
continue;
// Merge if chart2 has a single face.
// chart1 must have more than 1 face.
// chart2 area must be <= 10% of chart1 area.
- if (sharedBoundaryLengthsNoSeams[cc] > 0.0f && chart->faces.size() > 1 && chart2->faces.size() == 1 && chart2->area <= chart->area * 0.1f)
+ if (m_sharedBoundaryLengthsNoSeams[cc] > 0.0f && chart->faces.size() > 1 && chart2->faces.size() == 1 && chart2->area <= chart->area * 0.1f)
goto merge;
// Merge if chart2 has two faces (probably a quad), and chart1 bounds at least 2 of its edges.
- if (chart2->faces.size() == 2 && sharedBoundaryEdgeCountNoSeams[cc] >= 2)
+ if (chart2->faces.size() == 2 && m_sharedBoundaryEdgeCountNoSeams[cc] >= 2)
goto merge;
// Merge if chart2 is wholely inside chart1, ignoring seams.
- if (sharedBoundaryLengthsNoSeams[cc] > 0.0f && equal(sharedBoundaryLengthsNoSeams[cc], chart2->boundaryLength, kEpsilon))
+ if (m_sharedBoundaryLengthsNoSeams[cc] > 0.0f && equal(m_sharedBoundaryLengthsNoSeams[cc], chart2->boundaryLength, kEpsilon))
goto merge;
- if (sharedBoundaryLengths[cc] > 0.2f * max(0.0f, chart->boundaryLength - externalBoundaryLength) ||
- sharedBoundaryLengths[cc] > 0.75f * chart2->boundaryLength)
+ if (m_sharedBoundaryLengths[cc] > 0.2f * max(0.0f, chart->boundaryLength - externalBoundaryLength) ||
+ m_sharedBoundaryLengths[cc] > 0.75f * chart2->boundaryLength)
goto merge;
continue;
merge:
- // Create texcoords for chart 2 using chart 1 basis. Backup chart 2 texcoords for restoration if charts cannot be merged.
- tempTexcoords.resize(chart2->faces.size() * 3);
- for (uint32_t i = 0; i < chart2->faces.size(); i++) {
- const uint32_t face = chart2->faces[i];
- for (uint32_t j = 0; j < 3; j++)
- tempTexcoords[i * 3 + j] = m_texcoords[face * 3 + j];
- createFaceTexcoords(chart, face);
- }
- if (!canMergeCharts(chart, chart2)) {
- // Restore chart 2 texcoords.
- for (uint32_t i = 0; i < chart2->faces.size(); i++) {
- for (uint32_t j = 0; j < 3; j++)
- m_texcoords[chart2->faces[i] * 3 + j] = tempTexcoords[i * 3 + j];
- }
+ if (!mergeChart(chart, chart2, m_sharedBoundaryLengthsNoSeams[cc]))
continue;
- }
- mergeChart(chart, chart2, sharedBoundaryLengthsNoSeams[cc]);
merged = true;
break;
}
@@ -4610,20 +4908,20 @@ struct Atlas
break;
}
// Remove deleted charts.
- for (int c = 0; c < int32_t(m_chartArray.size()); /*do not increment if removed*/) {
- if (m_chartArray[c] == nullptr) {
- m_chartArray.removeAt(c);
- // Update m_faceChartArray.
- const uint32_t faceCount = m_faceChartArray.size();
+ for (int c = 0; c < int32_t(m_charts.size()); /*do not increment if removed*/) {
+ if (m_charts[c] == nullptr) {
+ m_charts.removeAt(c);
+ // Update m_faceCharts.
+ const uint32_t faceCount = m_faceCharts.size();
for (uint32_t i = 0; i < faceCount; i++) {
- XA_DEBUG_ASSERT(m_faceChartArray[i] != c);
- XA_DEBUG_ASSERT(m_faceChartArray[i] <= int32_t(m_chartArray.size()));
- if (m_faceChartArray[i] > c) {
- m_faceChartArray[i]--;
+ XA_DEBUG_ASSERT(m_faceCharts[i] != c);
+ XA_DEBUG_ASSERT(m_faceCharts[i] <= int32_t(m_charts.size()));
+ if (m_faceCharts[i] > c) {
+ m_faceCharts[i]--;
}
}
} else {
- m_chartArray[c]->id = c;
+ m_charts[c]->id = c;
c++;
}
}
@@ -4632,267 +4930,199 @@ struct Atlas
#endif
private:
- void createRandomChart(float threshold)
- {
+ void createRandomChart(float threshold) {
Chart *chart = XA_NEW(MemTag::Default, Chart);
- chart->id = (int)m_chartArray.size();
- m_chartArray.push_back(chart);
+ chart->id = (int)m_charts.size();
+ m_charts.push_back(chart);
// Pick random face that is not used by any chart yet.
uint32_t face = m_rand.getRange(m_mesh->faceCount() - 1);
- while (m_ignoreFaces[face] || m_faceChartArray[face] != -1) {
+ while (m_faceCharts[face] != -1) {
if (++face >= m_mesh->faceCount())
face = 0;
}
chart->seeds.push_back(face);
addFaceToChart(chart, face);
-#if XA_GROW_CHARTS_COPLANAR
- growChartCoplanar(chart);
-#endif
// Grow the chart as much as possible within the given threshold.
- for (uint32_t i = 0; i < m_facesLeft; ) {
- if (chart->candidates.count() == 0 || chart->candidates.firstPriority() > threshold)
+ for (;;) {
+ if (chart->candidates.count() == 0 || chart->candidates.peekCost() > threshold)
break;
const uint32_t f = chart->candidates.pop();
- if (m_faceChartArray[f] != -1)
+ if (m_faceCharts[f] != -1)
continue;
- createFaceTexcoords(chart, f);
- if (!canAddFaceToChart(chart, f))
+ if (!addFaceToChart(chart, f)) {
+ chart->failedPlanarRegions.push_back(m_facePlanarRegionId[f]);
continue;
- addFaceToChart(chart, f);
- i++;
- }
- }
-
- void addChartCandidateToGlobalCandidates(Chart *chart)
- {
- if (chart->candidates.count() == 0)
- return;
- const float cost = chart->candidates.firstPriority();
- const uint32_t face = chart->candidates.pop();
- if (m_faceChartArray[face] != -1) {
- addChartCandidateToGlobalCandidates(chart);
- } else if (!m_faceCandidateCharts[face]) {
- // No candidate assigned to this face yet.
- m_faceCandidateCharts[face] = chart;
- m_faceCandidateCosts[face] = cost;
- } else {
- if (cost < m_faceCandidateCosts[face]) {
- // This is a better candidate for this face (lower cost). The other chart can choose another candidate.
- Chart *otherChart = m_faceCandidateCharts[face];
- m_faceCandidateCharts[face] = chart;
- m_faceCandidateCosts[face] = cost;
- addChartCandidateToGlobalCandidates(otherChart);
- } else {
- // Existing candidate is better. This chart can choose another candidate.
- addChartCandidateToGlobalCandidates(chart);
}
}
}
- void createFaceTexcoords(Chart *chart, uint32_t face)
- {
- for (uint32_t i = 0; i < 3; i++) {
- const Vector3 &pos = m_mesh->position(m_mesh->vertexAt(face * 3 + i));
- m_texcoords[face * 3 + i] = Vector2(dot(chart->basis.tangent, pos), dot(chart->basis.bitangent, pos));
- }
- }
-
- bool isChartBoundaryEdge(const Chart *chart, uint32_t edge) const
- {
+ bool isChartBoundaryEdge(const Chart *chart, uint32_t edge) const {
const uint32_t oppositeEdge = m_mesh->oppositeEdge(edge);
const uint32_t oppositeFace = meshEdgeFace(oppositeEdge);
- return oppositeEdge == UINT32_MAX || m_ignoreFaces[oppositeFace] || m_faceChartArray[oppositeFace] != chart->id;
+ return oppositeEdge == UINT32_MAX || m_faceCharts[oppositeFace] != chart->id;
}
- bool edgeArraysIntersect(const uint32_t *edges1, uint32_t edges1Count, const uint32_t *edges2, uint32_t edges2Count)
- {
- for (uint32_t i = 0; i < edges1Count; i++) {
- const uint32_t edge1 = edges1[i];
- for (uint32_t j = 0; j < edges2Count; j++) {
- const uint32_t edge2 = edges2[j];
- const Vector2 &a1 = m_texcoords[meshEdgeIndex0(edge1)];
- const Vector2 &a2 = m_texcoords[meshEdgeIndex1(edge1)];
- const Vector2 &b1 = m_texcoords[meshEdgeIndex0(edge2)];
- const Vector2 &b2 = m_texcoords[meshEdgeIndex1(edge2)];
- if (linesIntersect(a1, a2, b1, b2, m_mesh->epsilon()))
- return true;
- }
+ bool computeChartBasis(Chart *chart, Basis *basis) {
+ const uint32_t faceCount = chart->faces.size();
+ m_tempPoints.resize(chart->faces.size() * 3);
+ for (uint32_t i = 0; i < faceCount; i++) {
+ const uint32_t f = chart->faces[i];
+ for (uint32_t j = 0; j < 3; j++)
+ m_tempPoints[i * 3 + j] = m_mesh->position(m_mesh->vertexAt(f * 3 + j));
}
- return false;
+ return Fit::computeBasis(m_tempPoints.data(), m_tempPoints.size(), basis);
}
- bool isFaceFlipped(uint32_t face) const
- {
- const float t1 = m_texcoords[face * 3 + 0].x;
- const float s1 = m_texcoords[face * 3 + 0].y;
- const float t2 = m_texcoords[face * 3 + 1].x;
- const float s2 = m_texcoords[face * 3 + 1].y;
- const float t3 = m_texcoords[face * 3 + 2].x;
- const float s3 = m_texcoords[face * 3 + 2].y;
- const float parametricArea = ((s2 - s1) * (t3 - t1) - (s3 - s1) * (t2 - t1)) / 2;
+ bool isFaceFlipped(uint32_t face) const {
+ const Vector2 &v1 = m_texcoords[face * 3 + 0];
+ const Vector2 &v2 = m_texcoords[face * 3 + 1];
+ const Vector2 &v3 = m_texcoords[face * 3 + 2];
+ const float parametricArea = ((v2.x - v1.x) * (v3.y - v1.y) - (v3.x - v1.x) * (v2.y - v1.y)) * 0.5f;
return parametricArea < 0.0f;
}
- void computeChartBoundaryEdges(const Chart *chart, Array<uint32_t> *dest) const
- {
- dest->clear();
- for (uint32_t f = 0; f < chart->faces.size(); f++) {
- const uint32_t face = chart->faces[f];
- for (uint32_t i = 0; i < 3; i++) {
- const uint32_t edge = face * 3 + i;
- if (isChartBoundaryEdge(chart, edge))
- dest->push_back(edge);
+ void parameterizeChart(const Chart *chart) {
+ const uint32_t faceCount = chart->faces.size();
+ for (uint32_t i = 0; i < faceCount; i++) {
+ const uint32_t face = chart->faces[i];
+ for (uint32_t j = 0; j < 3; j++) {
+ const uint32_t offset = face * 3 + j;
+ const Vector3 &pos = m_mesh->position(m_mesh->vertexAt(offset));
+ m_texcoords[offset] = Vector2(dot(chart->basis.tangent, pos), dot(chart->basis.bitangent, pos));
}
}
}
- bool canAddFaceToChart(Chart *chart, uint32_t face)
- {
- // Check for flipped triangles.
- if (isFaceFlipped(face))
+ // m_faceCharts for the chart faces must be set to the chart ID. Needed to compute boundary edges.
+ bool isChartParameterizationValid(const Chart *chart) {
+ const uint32_t faceCount = chart->faces.size();
+ // Check for flipped faces in the parameterization. OK if all are flipped.
+ uint32_t flippedFaceCount = 0;
+ for (uint32_t i = 0; i < faceCount; i++) {
+ if (isFaceFlipped(chart->faces[i]))
+ flippedFaceCount++;
+ }
+ if (flippedFaceCount != 0 && flippedFaceCount != faceCount)
return false;
- // Find face edges that don't border this chart.
- m_tempEdges1.clear();
- for (uint32_t i = 0; i < 3; i++) {
- const uint32_t edge = face * 3 + i;
- if (isChartBoundaryEdge(chart, edge))
- m_tempEdges1.push_back(edge);
- }
- if (m_tempEdges1.isEmpty())
- return true; // This can happen if the face is surrounded by the chart.
- // Get chart boundary edges, except those that border the face.
- m_tempEdges2.clear();
- for (uint32_t i = 0; i < chart->faces.size(); i++) {
- const uint32_t chartFace = chart->faces[i];
+ // Check for boundary intersection in the parameterization.
+ m_boundaryGrid.reset(m_texcoords.data());
+ for (uint32_t i = 0; i < faceCount; i++) {
+ const uint32_t f = chart->faces[i];
for (uint32_t j = 0; j < 3; j++) {
- const uint32_t chartEdge = chartFace * 3 + j;
- if (!isChartBoundaryEdge(chart, chartEdge))
- continue;
- // Don't check chart boundary edges that border the face.
- const uint32_t oppositeChartEdge = m_mesh->oppositeEdge(chartEdge);
- if (meshEdgeFace(oppositeChartEdge) == face)
- continue;
- m_tempEdges2.push_back(chartEdge);
- }
- }
- const bool intersect = edgeArraysIntersect(m_tempEdges1.data(), m_tempEdges1.size(), m_tempEdges2.data(), m_tempEdges2.size());
-#if 0
- if (intersect) {
- static std::atomic<uint32_t> count = 0;
- char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "intersect%04u.obj", count.fetch_add(1));
- FILE *file;
- XA_FOPEN(file, filename, "w");
- if (file) {
- for (uint32_t i = 0; i < m_texcoords.size(); i++)
- fprintf(file, "v %g %g 0.0\n", m_texcoords[i].x, m_texcoords[i].y);
- fprintf(file, "s off\n");
- fprintf(file, "o face\n");
- {
- fprintf(file, "f ");
- for (uint32_t j = 0; j < 3; j++) {
- const uint32_t index = face * 3 + j + 1; // 1-indexed
- fprintf(file, "%d/%d/%d%c", index, index, index, j == 2 ? '\n' : ' ');
- }
- }
- fprintf(file, "s off\n");
- fprintf(file, "o chart\n");
- for (uint32_t i = 0; i < chart->faces.size(); i++) {
- const uint32_t chartFace = chart->faces[i];
- fprintf(file, "f ");
- for (uint32_t j = 0; j < 3; j++) {
- const uint32_t index = chartFace * 3 + j + 1; // 1-indexed
- fprintf(file, "%d/%d/%d%c", index, index, index, j == 2 ? '\n' : ' ');
- }
- }
- fclose(file);
+ const uint32_t edge = f * 3 + j;
+ if (isChartBoundaryEdge(chart, edge))
+ m_boundaryGrid.append(edge);
}
}
-#endif
- return !intersect;
+ if (m_boundaryGrid.intersectSelf(m_mesh->epsilon()))
+ return false;
+ return true;
}
- bool canMergeCharts(Chart *chart1, Chart *chart2)
- {
- for (uint32_t i = 0; i < chart2->faces.size(); i++) {
- if (isFaceFlipped(chart2->faces[i]))
- return false;
+ bool addFaceToChart(Chart *chart, uint32_t face) {
+ XA_DEBUG_ASSERT(m_faceCharts[face] == -1);
+ const uint32_t oldFaceCount = chart->faces.size();
+ const bool firstFace = oldFaceCount == 0;
+ // Append the face and any coplanar connected faces to the chart faces array.
+ chart->faces.push_back(face);
+ uint32_t coplanarFace = m_nextPlanarRegionFace[face];
+ while (coplanarFace != face) {
+ XA_DEBUG_ASSERT(m_faceCharts[coplanarFace] == -1);
+ chart->faces.push_back(coplanarFace);
+ coplanarFace = m_nextPlanarRegionFace[coplanarFace];
}
- computeChartBoundaryEdges(chart1, &m_tempEdges1);
- computeChartBoundaryEdges(chart2, &m_tempEdges2);
- return !edgeArraysIntersect(m_tempEdges1.data(), m_tempEdges1.size(), m_tempEdges2.data(), m_tempEdges2.size());
- }
-
- void addFaceToChart(Chart *chart, uint32_t f)
- {
- const bool firstFace = chart->faces.isEmpty();
- // Use the first face normal as the chart basis.
+ const uint32_t faceCount = chart->faces.size();
+ // Compute basis.
+ Basis basis;
if (firstFace) {
- chart->basis.normal = m_faceNormals[f];
- chart->basis.tangent = m_faceTangents[f];
- chart->basis.bitangent = m_faceBitangents[f];
- createFaceTexcoords(chart, f);
- }
- // Add face to chart.
- chart->faces.push_back(f);
- XA_DEBUG_ASSERT(m_faceChartArray[f] == -1);
- m_faceChartArray[f] = chart->id;
- m_facesLeft--;
- // Update area and boundary length.
- chart->area = chart->area + m_faceAreas[f];
- chart->boundaryLength = computeBoundaryLength(chart, f);
- chart->normalSum += m_mesh->triangleNormalAreaScaled(f);
- chart->averageNormal = normalizeSafe(chart->normalSum, Vector3(0), 0.0f);
- chart->centroidSum += m_mesh->triangleCenter(f);
+ // Use the first face normal.
+ // Use any edge as the tangent vector.
+ basis.normal = m_faceNormals[face];
+ basis.tangent = normalize(m_mesh->position(m_mesh->vertexAt(face * 3 + 0)) - m_mesh->position(m_mesh->vertexAt(face * 3 + 1)), 0);
+ basis.bitangent = cross(basis.normal, basis.tangent);
+ } else {
+ // Use best fit normal.
+ if (!computeChartBasis(chart, &basis)) {
+ chart->faces.resize(oldFaceCount);
+ return false;
+ }
+ if (dot(basis.normal, m_faceNormals[face]) < 0.0f) // Flip normal if oriented in the wrong direction.
+ basis.normal = -basis.normal;
+ }
+ if (!firstFace) {
+ // Compute orthogonal parameterization and check that it is valid.
+ parameterizeChart(chart);
+ for (uint32_t i = oldFaceCount; i < faceCount; i++)
+ m_faceCharts[chart->faces[i]] = chart->id;
+ if (!isChartParameterizationValid(chart)) {
+ for (uint32_t i = oldFaceCount; i < faceCount; i++)
+ m_faceCharts[chart->faces[i]] = -1;
+ chart->faces.resize(oldFaceCount);
+ return false;
+ }
+ }
+ // Add face(s) to chart.
+ chart->basis = basis;
+ chart->area = computeArea(chart, face);
+ chart->boundaryLength = computeBoundaryLength(chart, face);
+ for (uint32_t i = oldFaceCount; i < faceCount; i++) {
+ const uint32_t f = chart->faces[i];
+ m_faceCharts[f] = chart->id;
+ m_facesLeft--;
+ chart->centroidSum += m_mesh->computeFaceCenter(f);
+ }
chart->centroid = chart->centroidSum / float(chart->faces.size());
- // Update candidates.
- updateChartCandidates(chart, f);
- }
-
-#if XA_GROW_CHARTS_COPLANAR
- void growChartCoplanar(Chart *chart)
- {
- XA_DEBUG_ASSERT(!chart->faces.isEmpty());
- for (uint32_t i = 0; i < chart->faces.size(); i++) {
- const uint32_t chartFace = chart->faces[i];
- uint32_t face = m_nextPlanarRegionFace[chartFace];
- while (face != chartFace) {
- // Not assigned to a chart?
- if (m_faceChartArray[face] == -1) {
- createFaceTexcoords(chart, face);
- addFaceToChart(chart, face);
- }
- face = m_nextPlanarRegionFace[face];
+ // Refresh candidates.
+ chart->candidates.clear();
+ for (uint32_t i = 0; i < faceCount; i++) {
+ // Traverse neighboring faces, add the ones that do not belong to any chart yet.
+ const uint32_t f = chart->faces[i];
+ for (uint32_t j = 0; j < 3; j++) {
+ const uint32_t edge = f * 3 + j;
+ const uint32_t oedge = m_mesh->oppositeEdge(edge);
+ if (oedge == UINT32_MAX)
+ continue; // Boundary edge.
+ const uint32_t oface = meshEdgeFace(oedge);
+ if (m_faceCharts[oface] != -1)
+ continue; // Face belongs to another chart.
+ if (chart->failedPlanarRegions.contains(m_facePlanarRegionId[oface]))
+ continue; // Failed to add this faces planar region to the chart before.
+ const float cost = evaluateCost(chart, oface);
+ if (cost < FLT_MAX)
+ chart->candidates.push(cost, oface);
}
}
+ return true;
}
-#endif
- bool relocateSeed(Chart *chart)
- {
+ // Returns true if the seed has changed.
+ bool relocateSeed(Chart *chart) {
// Find the first N triangles that fit the proxy best.
const uint32_t faceCount = chart->faces.size();
m_bestTriangles.clear();
for (uint32_t i = 0; i < faceCount; i++) {
- float priority = evaluateProxyFitMetric(chart, chart->faces[i]);
- m_bestTriangles.push(priority, chart->faces[i]);
+ const float cost = evaluateProxyFitMetric(chart, chart->faces[i]);
+ m_bestTriangles.push(cost, chart->faces[i]);
}
// Of those, choose the least central triangle.
uint32_t leastCentral = 0;
float maxDistance = -1;
- const uint32_t bestCount = m_bestTriangles.count();
- for (uint32_t i = 0; i < bestCount; i++) {
- Vector3 faceCentroid = m_mesh->triangleCenter(m_bestTriangles.pairs[i].face);
- float distance = length(chart->centroid - faceCentroid);
+ for (;;) {
+ if (m_bestTriangles.count() == 0)
+ break;
+ const uint32_t face = m_bestTriangles.pop();
+ Vector3 faceCentroid = m_mesh->computeFaceCenter(face);
+ const float distance = length(chart->centroid - faceCentroid);
if (distance > maxDistance) {
maxDistance = distance;
- leastCentral = m_bestTriangles.pairs[i].face;
+ leastCentral = face;
}
}
XA_DEBUG_ASSERT(maxDistance >= 0);
// In order to prevent k-means cyles we record all the previously chosen seeds.
for (uint32_t i = 0; i < chart->seeds.size(); i++) {
- if (chart->seeds[i] == leastCentral) {
+ // Treat seeds belong to the same planar region as equal.
+ if (chart->seeds[i] == leastCentral || m_facePlanarRegionId[chart->seeds[i]] == m_facePlanarRegionId[leastCentral]) {
// Move new seed to the end of the seed array.
uint32_t last = chart->seeds.size() - 1;
swap(chart->seeds[i], chart->seeds[last]);
@@ -4905,28 +5135,33 @@ private:
}
// Evaluate combined metric.
- float evaluateCost(Chart *chart, uint32_t face) const
- {
+ float evaluateCost(Chart *chart, uint32_t face) const {
+ if (dot(m_faceNormals[face], chart->basis.normal) <= 0.26f) // ~75 degrees
+ return FLT_MAX;
// Estimate boundary length and area:
- const float newChartArea = chart->area + m_faceAreas[face];
- const float newBoundaryLength = computeBoundaryLength(chart, face);
+ float newChartArea = 0.0f, newBoundaryLength = 0.0f;
+ if (m_options.maxChartArea > 0.0f || m_options.roundnessMetricWeight > 0.0f)
+ newChartArea = computeArea(chart, face);
+ if (m_options.maxBoundaryLength > 0.0f || m_options.roundnessMetricWeight > 0.0f)
+ newBoundaryLength = computeBoundaryLength(chart, face);
// Enforce limits strictly:
if (m_options.maxChartArea > 0.0f && newChartArea > m_options.maxChartArea)
return FLT_MAX;
if (m_options.maxBoundaryLength > 0.0f && newBoundaryLength > m_options.maxBoundaryLength)
return FLT_MAX;
- if (dot(m_faceNormals[face], chart->averageNormal) < 0.5f)
- return FLT_MAX;
- // Penalize faces that cross seams, reward faces that close seams or reach boundaries.
- // Make sure normal seams are fully respected:
- const float N = evaluateNormalSeamMetric(chart, face);
- if (m_options.normalSeamMetricWeight >= 1000.0f && N > 0.0f)
- return FLT_MAX;
- float cost = m_options.normalSeamMetricWeight * N;
+ float cost = 0.0f;
+ if (m_options.normalSeamMetricWeight > 0.0f) {
+ // Penalize faces that cross seams, reward faces that close seams or reach boundaries.
+ // Make sure normal seams are fully respected:
+ const float N = evaluateNormalSeamMetric(chart, face);
+ if (m_options.normalSeamMetricWeight >= 1000.0f && N > 0.0f)
+ return FLT_MAX;
+ cost += m_options.normalSeamMetricWeight * N;
+ }
if (m_options.proxyFitMetricWeight > 0.0f)
cost += m_options.proxyFitMetricWeight * evaluateProxyFitMetric(chart, face);
if (m_options.roundnessMetricWeight > 0.0f)
- cost += m_options.roundnessMetricWeight * evaluateRoundnessMetric(chart, face, newBoundaryLength, newChartArea);
+ cost += m_options.roundnessMetricWeight * evaluateRoundnessMetric(chart, newBoundaryLength, newChartArea);
if (m_options.straightnessMetricWeight > 0.0f)
cost += m_options.straightnessMetricWeight * evaluateStraightnessMetric(chart, face);
if (m_options.textureSeamMetricWeight > 0.0f)
@@ -4941,48 +5176,49 @@ private:
}
// Returns a value in [0-1].
- float evaluateProxyFitMetric(Chart *chart, uint32_t f) const
- {
- const Vector3 faceNormal = m_faceNormals[f];
+ float evaluateProxyFitMetric(Chart *chart, uint32_t face) const {
+ // All faces in coplanar regions have the same normal, can use any face.
+ const Vector3 faceNormal = m_faceNormals[face];
// Use plane fitting metric for now:
- return 1 - dot(faceNormal, chart->averageNormal); // @@ normal deviations should be weighted by face area
+ return 1 - dot(faceNormal, chart->basis.normal); // @@ normal deviations should be weighted by face area
}
- float evaluateRoundnessMetric(Chart *chart, uint32_t /*face*/, float newBoundaryLength, float newChartArea) const
- {
- float roundness = square(chart->boundaryLength) / chart->area;
- float newRoundness = square(newBoundaryLength) / newChartArea;
- if (newRoundness > roundness) {
- return square(newBoundaryLength) / (newChartArea * 4.0f * kPi);
- } else {
- // Offer no impedance to faces that improve roundness.
- return 0;
- }
+ float evaluateRoundnessMetric(Chart *chart, float newBoundaryLength, float newChartArea) const {
+ const float roundness = square(chart->boundaryLength) / chart->area;
+ const float newBoundaryLengthSq = square(newBoundaryLength);
+ const float newRoundness = newBoundaryLengthSq / newChartArea;
+ if (newRoundness > roundness)
+ return newBoundaryLengthSq / (newChartArea * kPi4);
+ // Offer no impedance to faces that improve roundness.
+ return 0;
}
- float evaluateStraightnessMetric(Chart *chart, uint32_t f) const
- {
- float l_out = 0.0f;
- float l_in = 0.0f;
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- float l = m_edgeLengths[it.edge()];
- if (it.isBoundary() || m_ignoreFaces[it.oppositeFace()]) {
- l_out += l;
- } else {
- if (m_faceChartArray[it.oppositeFace()] != chart->id) {
+ float evaluateStraightnessMetric(Chart *chart, uint32_t firstFace) const {
+ float l_out = 0.0f, l_in = 0.0f;
+ const uint32_t planarRegionId = m_facePlanarRegionId[firstFace];
+ uint32_t face = firstFace;
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ const float l = m_edgeLengths[it.edge()];
+ if (it.isBoundary()) {
l_out += l;
- } else {
- l_in += l;
+ } else if (m_facePlanarRegionId[it.oppositeFace()] != planarRegionId) {
+ if (m_faceCharts[it.oppositeFace()] != chart->id)
+ l_out += l;
+ else
+ l_in += l;
}
}
+ face = m_nextPlanarRegionFace[face];
+ if (face == firstFace)
+ break;
}
XA_DEBUG_ASSERT(l_in != 0.0f); // Candidate face must be adjacent to chart. @@ This is not true if the input mesh has zero-length edges.
float ratio = (l_out - l_in) / (l_out + l_in);
return min(ratio, 0.0f); // Only use the straightness metric to close gaps.
}
- bool isNormalSeam(uint32_t edge) const
- {
+ bool isNormalSeam(uint32_t edge) const {
const uint32_t oppositeEdge = m_mesh->oppositeEdge(edge);
if (oppositeEdge == UINT32_MAX)
return false; // boundary edge
@@ -4991,139 +5227,189 @@ private:
const uint32_t v1 = m_mesh->vertexAt(meshEdgeIndex1(edge));
const uint32_t ov0 = m_mesh->vertexAt(meshEdgeIndex0(oppositeEdge));
const uint32_t ov1 = m_mesh->vertexAt(meshEdgeIndex1(oppositeEdge));
- return m_mesh->normal(v0) != m_mesh->normal(ov1) || m_mesh->normal(v1) != m_mesh->normal(ov0);
+ if (v0 == ov1 && v1 == ov0)
+ return false;
+ return !equal(m_mesh->normal(v0), m_mesh->normal(ov1), kNormalEpsilon) || !equal(m_mesh->normal(v1), m_mesh->normal(ov0), kNormalEpsilon);
}
- return m_faceNormals[meshEdgeFace(edge)] != m_faceNormals[meshEdgeFace(oppositeEdge)];
+ const uint32_t f0 = meshEdgeFace(edge);
+ const uint32_t f1 = meshEdgeFace(oppositeEdge);
+ if (m_facePlanarRegionId[f0] == m_facePlanarRegionId[f1])
+ return false;
+ return !equal(m_faceNormals[f0], m_faceNormals[f1], kNormalEpsilon);
}
- float evaluateNormalSeamMetric(Chart *chart, uint32_t f) const
- {
- float seamFactor = 0.0f;
- float totalLength = 0.0f;
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- if (it.isBoundary() || m_ignoreFaces[it.oppositeFace()])
- continue;
- if (m_faceChartArray[it.oppositeFace()] != chart->id)
- continue;
- float l = m_edgeLengths[it.edge()];
- totalLength += l;
- if (!it.isSeam())
- continue;
- // Make sure it's a normal seam.
- if (isNormalSeam(it.edge())) {
- float d;
- if (m_mesh->flags() & MeshFlags::HasNormals) {
- const Vector3 &n0 = m_mesh->normal(it.vertex0());
- const Vector3 &n1 = m_mesh->normal(it.vertex1());
- const Vector3 &on0 = m_mesh->normal(m_mesh->vertexAt(meshEdgeIndex0(it.oppositeEdge())));
- const Vector3 &on1 = m_mesh->normal(m_mesh->vertexAt(meshEdgeIndex1(it.oppositeEdge())));
- const float d0 = clamp(dot(n0, on1), 0.0f, 1.0f);
- const float d1 = clamp(dot(n1, on0), 0.0f, 1.0f);
- d = (d0 + d1) * 0.5f;
- } else {
- d = clamp(dot(m_faceNormals[f], m_faceNormals[meshEdgeFace(it.oppositeEdge())]), 0.0f, 1.0f);
+ float evaluateNormalSeamMetric(Chart *chart, uint32_t firstFace) const {
+ float seamFactor = 0.0f, totalLength = 0.0f;
+ uint32_t face = firstFace;
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ if (it.isBoundary())
+ continue;
+ if (m_faceCharts[it.oppositeFace()] != chart->id)
+ continue;
+ float l = m_edgeLengths[it.edge()];
+ totalLength += l;
+ if (!it.isSeam())
+ continue;
+ // Make sure it's a normal seam.
+ if (isNormalSeam(it.edge())) {
+ float d;
+ if (m_mesh->flags() & MeshFlags::HasNormals) {
+ const Vector3 &n0 = m_mesh->normal(it.vertex0());
+ const Vector3 &n1 = m_mesh->normal(it.vertex1());
+ const Vector3 &on0 = m_mesh->normal(m_mesh->vertexAt(meshEdgeIndex0(it.oppositeEdge())));
+ const Vector3 &on1 = m_mesh->normal(m_mesh->vertexAt(meshEdgeIndex1(it.oppositeEdge())));
+ const float d0 = clamp(dot(n0, on1), 0.0f, 1.0f);
+ const float d1 = clamp(dot(n1, on0), 0.0f, 1.0f);
+ d = (d0 + d1) * 0.5f;
+ } else {
+ d = clamp(dot(m_faceNormals[face], m_faceNormals[meshEdgeFace(it.oppositeEdge())]), 0.0f, 1.0f);
+ }
+ l *= 1 - d;
+ seamFactor += l;
}
- l *= 1 - d;
- seamFactor += l;
}
+ face = m_nextPlanarRegionFace[face];
+ if (face == firstFace)
+ break;
}
if (seamFactor <= 0.0f)
return 0.0f;
return seamFactor / totalLength;
}
- float evaluateTextureSeamMetric(Chart *chart, uint32_t f) const
- {
- float seamLength = 0.0f;
- float totalLength = 0.0f;
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- if (it.isBoundary() || m_ignoreFaces[it.oppositeFace()])
- continue;
- if (m_faceChartArray[it.oppositeFace()] != chart->id)
- continue;
- float l = m_edgeLengths[it.edge()];
- totalLength += l;
- if (!it.isSeam())
- continue;
- // Make sure it's a texture seam.
- if (it.isTextureSeam())
- seamLength += l;
+ float evaluateTextureSeamMetric(Chart *chart, uint32_t firstFace) const {
+ float seamLength = 0.0f, totalLength = 0.0f;
+ uint32_t face = firstFace;
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ if (it.isBoundary())
+ continue;
+ if (m_faceCharts[it.oppositeFace()] != chart->id)
+ continue;
+ float l = m_edgeLengths[it.edge()];
+ totalLength += l;
+ if (!it.isSeam())
+ continue;
+ // Make sure it's a texture seam.
+ if (it.isTextureSeam())
+ seamLength += l;
+ }
+ face = m_nextPlanarRegionFace[face];
+ if (face == firstFace)
+ break;
}
- if (seamLength == 0.0f)
+ if (seamLength <= 0.0f)
return 0.0f; // Avoid division by zero.
return seamLength / totalLength;
}
- float computeBoundaryLength(Chart *chart, uint32_t f) const
- {
+ float computeArea(Chart *chart, uint32_t firstFace) const {
+ float area = chart->area;
+ uint32_t face = firstFace;
+ for (;;) {
+ area += m_faceAreas[face];
+ face = m_nextPlanarRegionFace[face];
+ if (face == firstFace)
+ break;
+ }
+ return area;
+ }
+
+ float computeBoundaryLength(Chart *chart, uint32_t firstFace) const {
float boundaryLength = chart->boundaryLength;
// Add new edges, subtract edges shared with the chart.
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- const float edgeLength = m_edgeLengths[it.edge()];
- if (it.isBoundary() || m_ignoreFaces[it.oppositeFace()]) {
- boundaryLength += edgeLength;
- } else {
- if (m_faceChartArray[it.oppositeFace()] != chart->id)
+ const uint32_t planarRegionId = m_facePlanarRegionId[firstFace];
+ uint32_t face = firstFace;
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ const float edgeLength = m_edgeLengths[it.edge()];
+ if (it.isBoundary()) {
boundaryLength += edgeLength;
- else
- boundaryLength -= edgeLength;
+ } else if (m_facePlanarRegionId[it.oppositeFace()] != planarRegionId) {
+ if (m_faceCharts[it.oppositeFace()] != chart->id)
+ boundaryLength += edgeLength;
+ else
+ boundaryLength -= edgeLength;
+ }
}
+ face = m_nextPlanarRegionFace[face];
+ if (face == firstFace)
+ break;
}
- return max(0.0f, boundaryLength); // @@ Hack!
+ return max(0.0f, boundaryLength); // @@ Hack!
}
- void mergeChart(Chart *owner, Chart *chart, float sharedBoundaryLength)
- {
- const uint32_t faceCount = chart->faces.size();
- for (uint32_t i = 0; i < faceCount; i++) {
- uint32_t f = chart->faces[i];
- XA_DEBUG_ASSERT(m_faceChartArray[f] == chart->id);
- m_faceChartArray[f] = owner->id;
- owner->faces.push_back(f);
+ bool mergeChart(Chart *owner, Chart *chart, float sharedBoundaryLength) {
+ const uint32_t oldOwnerFaceCount = owner->faces.size();
+ const uint32_t chartFaceCount = chart->faces.size();
+ owner->faces.push_back(chart->faces);
+ for (uint32_t i = 0; i < chartFaceCount; i++) {
+ XA_DEBUG_ASSERT(m_faceCharts[chart->faces[i]] == chart->id);
+ m_faceCharts[chart->faces[i]] = owner->id;
+ }
+ // Compute basis using best fit normal.
+ Basis basis;
+ if (!computeChartBasis(owner, &basis)) {
+ owner->faces.resize(oldOwnerFaceCount);
+ for (uint32_t i = 0; i < chartFaceCount; i++)
+ m_faceCharts[chart->faces[i]] = chart->id;
+ return false;
+ }
+ if (dot(basis.normal, m_faceNormals[owner->faces[0]]) < 0.0f) // Flip normal if oriented in the wrong direction.
+ basis.normal = -basis.normal;
+ // Compute orthogonal parameterization and check that it is valid.
+ parameterizeChart(owner);
+ if (!isChartParameterizationValid(owner)) {
+ owner->faces.resize(oldOwnerFaceCount);
+ for (uint32_t i = 0; i < chartFaceCount; i++)
+ m_faceCharts[chart->faces[i]] = chart->id;
+ return false;
}
+ // Merge chart.
+ owner->basis = basis;
+ owner->failedPlanarRegions.push_back(chart->failedPlanarRegions);
// Update adjacencies?
owner->area += chart->area;
owner->boundaryLength += chart->boundaryLength - sharedBoundaryLength;
- owner->normalSum += chart->normalSum;
- owner->averageNormal = normalizeSafe(owner->normalSum, Vector3(0), 0.0f);
// Delete chart.
- m_chartArray[chart->id] = nullptr;
+ m_charts[chart->id] = nullptr;
chart->~Chart();
XA_FREE(chart);
+ return true;
}
const Mesh *m_mesh;
- const Array<uint32_t> *m_meshFaces;
- Array<bool> m_ignoreFaces;
Array<float> m_edgeLengths;
Array<float> m_faceAreas;
Array<Vector3> m_faceNormals;
- Array<Vector3> m_faceTangents;
- Array<Vector3> m_faceBitangents;
Array<Vector2> m_texcoords;
uint32_t m_facesLeft;
- Array<int> m_faceChartArray;
- Array<Chart *> m_chartArray;
- PriorityQueue m_bestTriangles;
+ Array<int> m_faceCharts;
+ Array<Chart *> m_charts;
+ CostQueue m_bestTriangles;
KISSRng m_rand;
ChartOptions m_options;
- Array<Chart *> m_faceCandidateCharts;
- Array<float> m_faceCandidateCosts;
-#if XA_GROW_CHARTS_COPLANAR
Array<uint32_t> m_nextPlanarRegionFace;
+ Array<uint32_t> m_facePlanarRegionId;
+ Array<Vector3> m_tempPoints;
+ UniformGrid2 m_boundaryGrid;
+#if XA_MERGE_CHARTS
+ // mergeCharts
+ Array<float> m_sharedBoundaryLengths;
+ Array<float> m_sharedBoundaryLengthsNoSeams;
+ Array<uint32_t> m_sharedBoundaryEdgeCountNoSeams;
#endif
- Array<uint32_t> m_tempEdges1, m_tempEdges2;
};
} // namespace segment
namespace param {
-class JacobiPreconditioner
-{
+class JacobiPreconditioner {
public:
- JacobiPreconditioner(const sparse::Matrix &M, bool symmetric) : m_inverseDiagonal(M.width())
- {
+ JacobiPreconditioner(const sparse::Matrix &M, bool symmetric) :
+ m_inverseDiagonal(M.width()) {
XA_ASSERT(M.isSquare());
for (uint32_t x = 0; x < M.width(); x++) {
float elem = M.getCoefficient(x, x);
@@ -5136,8 +5422,7 @@ public:
}
}
- void apply(const FullVector &x, FullVector &y) const
- {
+ void apply(const FullVector &x, FullVector &y) const {
XA_DEBUG_ASSERT(x.dimension() == m_inverseDiagonal.dimension());
XA_DEBUG_ASSERT(y.dimension() == m_inverseDiagonal.dimension());
// @@ Wrap vector component-wise product into a separate function.
@@ -5152,12 +5437,10 @@ private:
};
// Linear solvers.
-class Solver
-{
+class Solver {
public:
// Solve the symmetric system: At·A·x = At·b
- static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f)
- {
+ static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) {
XA_DEBUG_ASSERT(A.width() == x.dimension());
XA_DEBUG_ASSERT(A.height() == b.dimension());
XA_DEBUG_ASSERT(A.height() >= A.width()); // @@ If height == width we could solve it directly...
@@ -5172,8 +5455,7 @@ public:
}
// See section 10.4.3 in: Mesh Parameterization: Theory and Practice, Siggraph Course Notes, August 2007
- static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, const uint32_t *lockedParameters, uint32_t lockedCount, float epsilon = 1e-5f)
- {
+ static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, const uint32_t *lockedParameters, uint32_t lockedCount, float epsilon = 1e-5f) {
XA_DEBUG_ASSERT(A.width() == x.dimension());
XA_DEBUG_ASSERT(A.height() == b.dimension());
XA_DEBUG_ASSERT(A.height() >= A.width() - lockedCount);
@@ -5272,18 +5554,17 @@ private:
*
**/
// Conjugate gradient with preconditioner.
- static bool ConjugateGradientSolver(const JacobiPreconditioner &preconditioner, const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon)
- {
- XA_DEBUG_ASSERT( A.isSquare() );
- XA_DEBUG_ASSERT( A.width() == b.dimension() );
- XA_DEBUG_ASSERT( A.width() == x.dimension() );
+ static bool ConjugateGradientSolver(const JacobiPreconditioner &preconditioner, const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon) {
+ XA_DEBUG_ASSERT(A.isSquare());
+ XA_DEBUG_ASSERT(A.width() == b.dimension());
+ XA_DEBUG_ASSERT(A.width() == x.dimension());
int i = 0;
const int D = A.width();
- const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
- FullVector r(D); // residual
- FullVector p(D); // search direction
- FullVector q(D); //
- FullVector s(D); // preconditioned
+ const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
+ FullVector r(D); // residual
+ FullVector p(D); // search direction
+ FullVector q(D); //
+ FullVector s(D); // preconditioned
float delta_0;
float delta_old;
float delta_new;
@@ -5301,11 +5582,15 @@ private:
// q = A·p
sparse::mult(A, p, q);
// alpha = delta_new / p·q
- alpha = delta_new / sparse::dot(p, q);
+ const float pdotq = sparse::dot(p, q);
+ if (!isFinite(pdotq) || isNan(pdotq))
+ alpha = 0.0f;
+ else
+ alpha = delta_new / pdotq;
// x = alfa·p + x
sparse::saxpy(alpha, p, x);
if ((i & 31) == 0) { // recompute r after 32 steps
- // r = b - A·x
+ // r = b - A·x
sparse::copy(b, r);
sparse::sgemv(-1, A, x, 1, r);
} else {
@@ -5315,7 +5600,7 @@ private:
// s = M^-1 · r
preconditioner.apply(r, s);
delta_old = delta_new;
- delta_new = sparse::dot( r, s );
+ delta_new = sparse::dot(r, s);
beta = delta_new / delta_old;
// p = s + beta·p
sparse::scal(beta, p);
@@ -5324,8 +5609,7 @@ private:
return delta_new <= epsilon * epsilon * delta_0;
}
- static bool SymmetricSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f)
- {
+ static bool SymmetricSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) {
XA_DEBUG_ASSERT(A.height() == A.width());
XA_DEBUG_ASSERT(A.height() == b.dimension());
XA_DEBUG_ASSERT(b.dimension() == x.dimension());
@@ -5335,8 +5619,7 @@ private:
};
// Fast sweep in 3 directions
-static bool findApproximateDiameterVertices(Mesh *mesh, uint32_t *a, uint32_t *b)
-{
+static bool findApproximateDiameterVertices(Mesh *mesh, uint32_t *a, uint32_t *b) {
XA_DEBUG_ASSERT(a != nullptr);
XA_DEBUG_ASSERT(b != nullptr);
const uint32_t vertexCount = mesh->vertexCount();
@@ -5393,28 +5676,24 @@ static bool findApproximateDiameterVertices(Mesh *mesh, uint32_t *a, uint32_t *b
// Conformal relations from Brecht Van Lommel (based on ABF):
-static float vec_angle_cos(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3)
-{
+static float vec_angle_cos(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) {
Vector3 d1 = v1 - v2;
Vector3 d2 = v3 - v2;
return clamp(dot(d1, d2) / (length(d1) * length(d2)), -1.0f, 1.0f);
}
-static float vec_angle(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3)
-{
+static float vec_angle(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) {
float dot = vec_angle_cos(v1, v2, v3);
return acosf(dot);
}
-static void triangle_angles(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, float *a1, float *a2, float *a3)
-{
+static void triangle_angles(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, float *a1, float *a2, float *a3) {
*a1 = vec_angle(v3, v1, v2);
*a2 = vec_angle(v1, v2, v3);
*a3 = kPi - *a2 - *a1;
}
-static void setup_abf_relations(sparse::Matrix &A, int row, int id0, int id1, int id2, const Vector3 &p0, const Vector3 &p1, const Vector3 &p2)
-{
+static void setup_abf_relations(sparse::Matrix &A, int row, int id0, int id1, int id2, const Vector3 &p0, const Vector3 &p1, const Vector3 &p2) {
// @@ IC: Wouldn't it be more accurate to return cos and compute 1-cos^2?
// It does indeed seem to be a little bit more robust.
// @@ Need to revisit this more carefully!
@@ -5464,8 +5743,7 @@ static void setup_abf_relations(sparse::Matrix &A, int row, int id0, int id1, in
A.setCoefficient(v2_id, 2 * row + 1, 1);
}
-static bool computeLeastSquaresConformalMap(Mesh *mesh)
-{
+static bool computeLeastSquaresConformalMap(Mesh *mesh) {
// For this to work properly, mesh should not have colocals that have the same
// attributes, unless you want the vertices to actually have different texcoords.
const uint32_t vertexCount = mesh->vertexCount();
@@ -5514,216 +5792,537 @@ static bool computeLeastSquaresConformalMap(Mesh *mesh)
// Solve
Solver::LeastSquaresSolver(A, b, x, lockedParameters, 4, 0.000001f);
// Map x back to texcoords:
- for (uint32_t v = 0; v < vertexCount; v++)
+ for (uint32_t v = 0; v < vertexCount; v++) {
mesh->texcoord(v) = Vector2(x[2 * v + 0], x[2 * v + 1]);
+ XA_DEBUG_ASSERT(!isNan(mesh->texcoord(v).x));
+ XA_DEBUG_ASSERT(!isNan(mesh->texcoord(v).y));
+ }
return true;
}
-static bool computeOrthogonalProjectionMap(Mesh *mesh)
-{
- uint32_t vertexCount = mesh->vertexCount();
- // Avoid redundant computations.
- float matrix[6];
- Fit::computeCovariance(vertexCount, &mesh->position(0), matrix);
- if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0)
- return false;
- float eigenValues[3];
- Vector3 eigenVectors[3];
- if (!Fit::eigenSolveSymmetric3(matrix, eigenValues, eigenVectors))
- return false;
- Vector3 axis[2];
- axis[0] = normalize(eigenVectors[0], kEpsilon);
- axis[1] = normalize(eigenVectors[1], kEpsilon);
- // Project vertices to plane.
- for (uint32_t i = 0; i < vertexCount; i++)
- mesh->texcoord(i) = Vector2(dot(axis[0], mesh->position(i)), dot(axis[1], mesh->position(i)));
- return true;
-}
+#if XA_RECOMPUTE_CHARTS
+struct PiecewiseParam {
+ void reset(const Mesh *mesh, uint32_t faceCount) {
+ m_mesh = mesh;
+ m_faceCount = faceCount;
+ const uint32_t vertexCount = m_mesh->vertexCount();
+ m_texcoords.resize(vertexCount);
+ m_patch.reserve(m_faceCount);
+ m_faceAssigned.resize(m_faceCount);
+ m_faceAssigned.zeroOutMemory();
+ m_faceInvalid.resize(m_faceCount);
+ m_faceInPatch.resize(m_faceCount);
+ m_vertexInPatch.resize(vertexCount);
+ m_faceInCandidates.resize(m_faceCount);
+ }
+
+ ConstArrayView<uint32_t> chartFaces() const { return m_patch; }
+ const Vector2 *texcoords() const { return m_texcoords.data(); }
+
+ bool computeChart() {
+ m_patch.clear();
+ m_faceInvalid.zeroOutMemory();
+ m_faceInPatch.zeroOutMemory();
+ m_vertexInPatch.zeroOutMemory();
+ // Add the seed face (first unassigned face) to the patch.
+ uint32_t seed = UINT32_MAX;
+ for (uint32_t f = 0; f < m_faceCount; f++) {
+ if (m_faceAssigned.get(f))
+ continue;
+ seed = f;
+ m_patch.push_back(seed);
+ m_faceInPatch.set(seed);
+ m_faceAssigned.set(seed);
+ Vector2 texcoords[3];
+ orthoProjectFace(seed, texcoords);
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = m_mesh->vertexAt(seed * 3 + i);
+ m_vertexInPatch.set(vertex);
+ m_texcoords[vertex] = texcoords[i];
+ }
+ break;
+ }
+ if (seed == UINT32_MAX)
+ return false;
+ for (;;) {
+ findCandidates();
+ if (m_candidates.isEmpty())
+ break;
+ for (;;) {
+ // Find the candidate with the lowest cost.
+ float lowestCost = FLT_MAX;
+ uint32_t bestCandidate = UINT32_MAX;
+ for (uint32_t i = 0; i < m_candidates.size(); i++) {
+ const Candidate &candidate = m_candidates[i];
+ if (m_faceInvalid.get(candidate.face)) // A candidate face may be invalidated after is was added.
+ continue;
+ if (candidate.maxCost < lowestCost) {
+ lowestCost = candidate.maxCost;
+ bestCandidate = i;
+ }
+ }
+ if (bestCandidate == UINT32_MAX)
+ break;
+ // Compute the position by averaging linked candidates (candidates that share the same free vertex).
+ Vector2 position(0.0f);
+ uint32_t n = 0;
+ for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance()) {
+ position += it.current().position;
+ n++;
+ }
+ position *= 1.0f / (float)n;
+ const uint32_t freeVertex = m_candidates[bestCandidate].vertex;
+ XA_DEBUG_ASSERT(!isNan(position.x));
+ XA_DEBUG_ASSERT(!isNan(position.y));
+ m_texcoords[freeVertex] = position;
+ // Check for flipped faces. This is also done when candidates are first added, but the averaged position of the free vertex is different now, so check again.
+ bool invalid = false;
+ for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance()) {
+ const uint32_t vertex0 = m_mesh->vertexAt(meshEdgeIndex0(it.current().patchEdge));
+ const uint32_t vertex1 = m_mesh->vertexAt(meshEdgeIndex1(it.current().patchEdge));
+ const float freeVertexOrient = orientToEdge(m_texcoords[vertex0], m_texcoords[vertex1], position);
+ if ((it.current().patchVertexOrient < 0.0f && freeVertexOrient < 0.0f) || (it.current().patchVertexOrient > 0.0f && freeVertexOrient > 0.0f)) {
+ invalid = true;
+ break;
+ }
+ }
+ // Check for boundary intersection.
+ if (!invalid) {
+ m_boundaryGrid.reset(m_texcoords.data(), m_mesh->indices());
+ // Add edges on the patch boundary to the grid.
+ // Temporarily adding candidate faces to the patch makes it simpler to detect which edges are on the boundary.
+ const uint32_t oldPatchSize = m_patch.size();
+ for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance())
+ m_patch.push_back(it.current().face);
+ for (uint32_t i = 0; i < m_patch.size(); i++) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, m_patch[i]); !it.isDone(); it.advance()) {
+ const uint32_t oface = it.oppositeFace();
+ if (oface == UINT32_MAX || oface >= m_faceCount || !m_faceInPatch.get(oface))
+ m_boundaryGrid.append(it.edge());
+ }
+ }
+ invalid = m_boundaryGrid.intersectSelf(m_mesh->epsilon());
+ m_patch.resize(oldPatchSize);
+ }
+ if (invalid) {
+ // Mark all faces of linked candidates as invalid.
+ for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance())
+ m_faceInvalid.set(it.current().face);
+ continue;
+ }
+ // Add faces to the patch.
+ for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance()) {
+ m_patch.push_back(it.current().face);
+ m_faceInPatch.set(it.current().face);
+ m_faceAssigned.set(it.current().face);
+ }
+ // Add vertex to the patch.
+ m_vertexInPatch.set(freeVertex);
+ // Successfully added candidate face(s) to patch.
+ break;
+ }
+ }
+ return true;
+ }
+
+private:
+ struct Candidate {
+ uint32_t face, vertex;
+ uint32_t next; // The next candidate with the same vertex.
+ Vector2 position;
+ float cost;
+ float maxCost; // Of all linked candidates.
+ uint32_t patchEdge;
+ float patchVertexOrient;
+ };
+
+ struct CandidateIterator {
+ CandidateIterator(Array<Candidate> &candidates, uint32_t first) :
+ m_candidates(candidates), m_current(first) {}
+ void advance() {
+ if (m_current != UINT32_MAX) m_current = m_candidates[m_current].next;
+ }
+ bool isDone() const { return m_current == UINT32_MAX; }
+ Candidate &current() { return m_candidates[m_current]; }
+
+ private:
+ Array<Candidate> &m_candidates;
+ uint32_t m_current;
+ };
+
+ const Mesh *m_mesh;
+ uint32_t m_faceCount;
+ Array<Vector2> m_texcoords;
+ Array<Candidate> m_candidates;
+ BitArray m_faceInCandidates;
+ Array<uint32_t> m_patch;
+ BitArray m_faceAssigned; // Face is assigned to a previous chart or the current patch.
+ BitArray m_faceInPatch, m_vertexInPatch;
+ BitArray m_faceInvalid; // Face cannot be added to the patch - flipped, cost too high or causes boundary intersection.
+ UniformGrid2 m_boundaryGrid;
+
+ // Find candidate faces on the patch front.
+ void findCandidates() {
+ m_candidates.clear();
+ m_faceInCandidates.zeroOutMemory();
+ for (uint32_t i = 0; i < m_patch.size(); i++) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, m_patch[i]); !it.isDone(); it.advance()) {
+ const uint32_t oface = it.oppositeFace();
+ if (oface == UINT32_MAX || oface >= m_faceCount || m_faceAssigned.get(oface) || m_faceInCandidates.get(oface))
+ continue;
+ // Found an active edge on the patch front.
+ // Find the free vertex (the vertex that isn't on the active edge).
+ // Compute the orientation of the other patch face vertex to the active edge.
+ uint32_t freeVertex = UINT32_MAX;
+ float orient = 0.0f;
+ for (uint32_t j = 0; j < 3; j++) {
+ const uint32_t vertex = m_mesh->vertexAt(oface * 3 + j);
+ if (vertex != it.vertex0() && vertex != it.vertex1()) {
+ freeVertex = vertex;
+ orient = orientToEdge(m_texcoords[it.vertex0()], m_texcoords[it.vertex1()], m_texcoords[m_mesh->vertexAt(m_patch[i] * 3 + j)]);
+ break;
+ }
+ }
+ XA_DEBUG_ASSERT(freeVertex != UINT32_MAX);
+ // If the free vertex is already in the patch, the face is enclosed by the patch. Add the face to the patch - don't need to assign texcoords.
+ if (m_vertexInPatch.get(freeVertex)) {
+ freeVertex = UINT32_MAX;
+ m_patch.push_back(oface);
+ m_faceAssigned.set(oface);
+ continue;
+ }
+ // Check this here rather than above so faces enclosed by the patch are always added.
+ if (m_faceInvalid.get(oface))
+ continue;
+ addCandidateFace(it.edge(), orient, oface, it.oppositeEdge(), freeVertex);
+ }
+ }
+ // Link candidates that share the same vertex.
+ for (uint32_t i = 0; i < m_candidates.size(); i++) {
+ if (m_candidates[i].next != UINT32_MAX)
+ continue;
+ uint32_t current = i;
+ for (uint32_t j = i + 1; j < m_candidates.size(); j++) {
+ if (m_candidates[j].vertex == m_candidates[current].vertex) {
+ m_candidates[current].next = j;
+ current = j;
+ }
+ }
+ }
+ // Set max cost for linked candidates.
+ for (uint32_t i = 0; i < m_candidates.size(); i++) {
+ float maxCost = 0.0f;
+ for (CandidateIterator it(m_candidates, i); !it.isDone(); it.advance())
+ maxCost = max(maxCost, it.current().cost);
+ for (CandidateIterator it(m_candidates, i); !it.isDone(); it.advance())
+ it.current().maxCost = maxCost;
+ }
+ }
+
+ void addCandidateFace(uint32_t patchEdge, float patchVertexOrient, uint32_t face, uint32_t edge, uint32_t freeVertex) {
+ Vector2 texcoords[3];
+ orthoProjectFace(face, texcoords);
+ // Find corresponding vertices between the patch edge and candidate edge.
+ const uint32_t vertex0 = m_mesh->vertexAt(meshEdgeIndex0(patchEdge));
+ const uint32_t vertex1 = m_mesh->vertexAt(meshEdgeIndex1(patchEdge));
+ uint32_t localVertex0 = UINT32_MAX, localVertex1 = UINT32_MAX, localFreeVertex = UINT32_MAX;
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = m_mesh->vertexAt(face * 3 + i);
+ if (vertex == m_mesh->vertexAt(meshEdgeIndex1(edge)))
+ localVertex0 = i;
+ else if (vertex == m_mesh->vertexAt(meshEdgeIndex0(edge)))
+ localVertex1 = i;
+ else
+ localFreeVertex = i;
+ }
+ // Scale orthogonal projection to match the patch edge.
+ const Vector2 patchEdgeVec = m_texcoords[vertex1] - m_texcoords[vertex0];
+ const Vector2 localEdgeVec = texcoords[localVertex1] - texcoords[localVertex0];
+ const float len1 = length(patchEdgeVec);
+ const float len2 = length(localEdgeVec);
+ const float scale = len1 / len2;
+ XA_ASSERT(scale > 0.0f);
+ for (uint32_t i = 0; i < 3; i++)
+ texcoords[i] *= scale;
+ // Translate to the first vertex on the patch edge.
+ const Vector2 translate = m_texcoords[vertex0] - texcoords[localVertex0];
+ for (uint32_t i = 0; i < 3; i++)
+ texcoords[i] += translate;
+ // Compute the angle between the patch edge and the corresponding local edge.
+ const float angle = atan2f(patchEdgeVec.y, patchEdgeVec.x) - atan2f(localEdgeVec.y, localEdgeVec.x);
+ // Rotate so the patch edge and the corresponding local edge occupy the same space.
+ for (uint32_t i = 0; i < 3; i++) {
+ if (i == localVertex0)
+ continue;
+ Vector2 &uv = texcoords[i];
+ uv -= texcoords[localVertex0]; // Rotate around the first vertex.
+ const float c = cosf(angle);
+ const float s = sinf(angle);
+ const float x = uv.x * c - uv.y * s;
+ const float y = uv.y * c + uv.x * s;
+ uv.x = x + texcoords[localVertex0].x;
+ uv.y = y + texcoords[localVertex0].y;
+ }
+ // Check for local overlap (flipped triangle).
+ // The patch face vertex that isn't on the active edge and the free vertex should be oriented on opposite sides to the active edge.
+ const float freeVertexOrient = orientToEdge(m_texcoords[vertex0], m_texcoords[vertex1], texcoords[localFreeVertex]);
+ if ((patchVertexOrient < 0.0f && freeVertexOrient < 0.0f) || (patchVertexOrient > 0.0f && freeVertexOrient > 0.0f)) {
+ m_faceInvalid.set(face);
+ return;
+ }
+ const float stretch = computeStretch(m_mesh->position(vertex0), m_mesh->position(vertex1), m_mesh->position(freeVertex), texcoords[0], texcoords[1], texcoords[2]);
+ if (stretch >= FLT_MAX) {
+ m_faceInvalid.set(face);
+ return;
+ }
+ const float cost = fabsf(stretch - 1.0f);
+#if 0
+ if (cost > 0.25f) {
+ m_faceInvalid.set(face);
+ return;
+ }
+#endif
+ // Add the candidate.
+ Candidate candidate;
+ candidate.face = face;
+ candidate.vertex = freeVertex;
+ candidate.position = texcoords[localFreeVertex];
+ candidate.next = UINT32_MAX;
+ candidate.cost = cost;
+ candidate.patchEdge = patchEdge;
+ candidate.patchVertexOrient = patchVertexOrient;
+ m_candidates.push_back(candidate);
+ m_faceInCandidates.set(face);
+ }
+
+ void orthoProjectFace(uint32_t face, Vector2 *texcoords) const {
+ const Vector3 normal = m_mesh->computeFaceNormal(face);
+ const Vector3 tangent = normalize(m_mesh->position(m_mesh->vertexAt(face * 3 + 1)) - m_mesh->position(m_mesh->vertexAt(face * 3 + 0)), kEpsilon);
+ const Vector3 bitangent = cross(normal, tangent);
+ for (uint32_t i = 0; i < 3; i++) {
+ const Vector3 &pos = m_mesh->position(m_mesh->vertexAt(face * 3 + i));
+ texcoords[i] = Vector2(dot(tangent, pos), dot(bitangent, pos));
+ }
+ }
+
+ float parametricArea(const Vector2 *texcoords) const {
+ const Vector2 &v1 = texcoords[0];
+ const Vector2 &v2 = texcoords[1];
+ const Vector2 &v3 = texcoords[2];
+ return ((v2.x - v1.x) * (v3.y - v1.y) - (v3.x - v1.x) * (v2.y - v1.y)) * 0.5f;
+ }
+
+ float computeStretch(Vector3 p1, Vector3 p2, Vector3 p3, Vector2 t1, Vector2 t2, Vector2 t3) const {
+ float parametricArea = ((t2.y - t1.y) * (t3.x - t1.x) - (t3.y - t1.y) * (t2.x - t1.x)) * 0.5f;
+ if (isZero(parametricArea, kAreaEpsilon))
+ return FLT_MAX;
+ if (parametricArea < 0.0f)
+ parametricArea = fabsf(parametricArea);
+ const float geometricArea = length(cross(p2 - p1, p3 - p1)) * 0.5f;
+ if (parametricArea <= geometricArea)
+ return parametricArea / geometricArea;
+ else
+ return geometricArea / parametricArea;
+ }
+
+ // Return value is positive if the point is one side of the edge, negative if on the other side.
+ float orientToEdge(Vector2 edgeVertex0, Vector2 edgeVertex1, Vector2 point) const {
+ return (edgeVertex0.x - point.x) * (edgeVertex1.y - point.y) - (edgeVertex0.y - point.y) * (edgeVertex1.x - point.x);
+ }
+};
+#endif
// Estimate quality of existing parameterization.
-struct ParameterizationQuality
-{
+struct Quality {
+ // computeBoundaryIntersection
+ bool boundaryIntersection = false;
+
+ // computeFlippedFaces
uint32_t totalTriangleCount = 0;
uint32_t flippedTriangleCount = 0;
uint32_t zeroAreaTriangleCount = 0;
- float parametricArea = 0.0f;
- float geometricArea = 0.0f;
+
+ // computeMetrics
+ float totalParametricArea = 0.0f;
+ float totalGeometricArea = 0.0f;
float stretchMetric = 0.0f;
float maxStretchMetric = 0.0f;
float conformalMetric = 0.0f;
float authalicMetric = 0.0f;
- bool boundaryIntersection = false;
-};
-static ParameterizationQuality calculateParameterizationQuality(const Mesh *mesh, uint32_t faceCount, Array<uint32_t> *flippedFaces)
-{
- XA_DEBUG_ASSERT(mesh != nullptr);
- ParameterizationQuality quality;
- uint32_t firstBoundaryEdge = UINT32_MAX;
- for (uint32_t e = 0; e < mesh->edgeCount(); e++) {
- if (mesh->isBoundaryEdge(e)) {
- firstBoundaryEdge = e;
- break;
- }
+ void computeBoundaryIntersection(const Mesh *mesh, UniformGrid2 &boundaryGrid) {
+ const Array<uint32_t> &boundaryEdges = mesh->boundaryEdges();
+ const uint32_t boundaryEdgeCount = boundaryEdges.size();
+ boundaryGrid.reset(mesh->texcoords(), mesh->indices(), boundaryEdgeCount);
+ for (uint32_t i = 0; i < boundaryEdgeCount; i++)
+ boundaryGrid.append(boundaryEdges[i]);
+ boundaryIntersection = boundaryGrid.intersectSelf(mesh->epsilon());
+#if XA_DEBUG_EXPORT_BOUNDARY_GRID
+ static int exportIndex = 0;
+ char filename[256];
+ XA_SPRINTF(filename, sizeof(filename), "debug_boundary_grid_%03d.tga", exportIndex);
+ boundaryGrid.debugExport(filename);
+ exportIndex++;
+#endif
}
- XA_DEBUG_ASSERT(firstBoundaryEdge != UINT32_MAX);
- for (Mesh::BoundaryEdgeIterator it1(mesh, firstBoundaryEdge); !it1.isDone(); it1.advance()) {
- const uint32_t edge1 = it1.edge();
- for (Mesh::BoundaryEdgeIterator it2(mesh, firstBoundaryEdge); !it2.isDone(); it2.advance()) {
- const uint32_t edge2 = it2.edge();
- // Skip self and edges directly connected to edge1.
- if (edge1 == edge2 || it1.nextEdge() == edge2 || it2.nextEdge() == edge1)
+
+ void computeFlippedFaces(const Mesh *mesh, uint32_t faceCount, Array<uint32_t> *flippedFaces) {
+ totalTriangleCount = flippedTriangleCount = zeroAreaTriangleCount = 0;
+ if (flippedFaces)
+ flippedFaces->clear();
+ for (uint32_t f = 0; f < faceCount; f++) {
+ Vector2 texcoord[3];
+ for (int i = 0; i < 3; i++) {
+ const uint32_t v = mesh->vertexAt(f * 3 + i);
+ texcoord[i] = mesh->texcoord(v);
+ }
+ totalTriangleCount++;
+ const float t1 = texcoord[0].x;
+ const float s1 = texcoord[0].y;
+ const float t2 = texcoord[1].x;
+ const float s2 = texcoord[1].y;
+ const float t3 = texcoord[2].x;
+ const float s3 = texcoord[2].y;
+ const float parametricArea = ((s2 - s1) * (t3 - t1) - (s3 - s1) * (t2 - t1)) * 0.5f;
+ if (isZero(parametricArea, kAreaEpsilon)) {
+ zeroAreaTriangleCount++;
continue;
- const Vector2 &a1 = mesh->texcoord(mesh->vertexAt(meshEdgeIndex0(edge1)));
- const Vector2 &a2 = mesh->texcoord(mesh->vertexAt(meshEdgeIndex1(edge1)));
- const Vector2 &b1 = mesh->texcoord(mesh->vertexAt(meshEdgeIndex0(edge2)));
- const Vector2 &b2 = mesh->texcoord(mesh->vertexAt(meshEdgeIndex1(edge2)));
- if (linesIntersect(a1, a2, b1, b2, mesh->epsilon())) {
- quality.boundaryIntersection = true;
- break;
+ }
+ if (parametricArea < 0.0f) {
+ // Count flipped triangles.
+ flippedTriangleCount++;
+ if (flippedFaces)
+ flippedFaces->push_back(f);
}
}
- if (quality.boundaryIntersection)
- break;
- }
- if (flippedFaces)
- flippedFaces->clear();
- for (uint32_t f = 0; f < faceCount; f++) {
- Vector3 pos[3];
- Vector2 texcoord[3];
- for (int i = 0; i < 3; i++) {
- const uint32_t v = mesh->vertexAt(f * 3 + i);
- pos[i] = mesh->position(v);
- texcoord[i] = mesh->texcoord(v);
- }
- quality.totalTriangleCount++;
- // Evaluate texture stretch metric. See:
- // - "Texture Mapping Progressive Meshes", Sander, Snyder, Gortler & Hoppe
- // - "Mesh Parameterization: Theory and Practice", Siggraph'07 Course Notes, Hormann, Levy & Sheffer.
- const float t1 = texcoord[0].x;
- const float s1 = texcoord[0].y;
- const float t2 = texcoord[1].x;
- const float s2 = texcoord[1].y;
- const float t3 = texcoord[2].x;
- const float s3 = texcoord[2].y;
- float parametricArea = ((s2 - s1) * (t3 - t1) - (s3 - s1) * (t2 - t1)) / 2;
- if (isZero(parametricArea, kAreaEpsilon)) {
- quality.zeroAreaTriangleCount++;
- continue;
- }
- if (parametricArea < 0.0f) {
- // Count flipped triangles.
- quality.flippedTriangleCount++;
+ if (flippedTriangleCount + zeroAreaTriangleCount == totalTriangleCount) {
+ // If all triangles are flipped, then none are.
if (flippedFaces)
- flippedFaces->push_back(f);
- parametricArea = fabsf(parametricArea);
- }
- const float geometricArea = length(cross(pos[1] - pos[0], pos[2] - pos[0])) / 2;
- const Vector3 Ss = (pos[0] * (t2 - t3) + pos[1] * (t3 - t1) + pos[2] * (t1 - t2)) / (2 * parametricArea);
- const Vector3 St = (pos[0] * (s3 - s2) + pos[1] * (s1 - s3) + pos[2] * (s2 - s1)) / (2 * parametricArea);
- const float a = dot(Ss, Ss); // E
- const float b = dot(Ss, St); // F
- const float c = dot(St, St); // G
- // Compute eigen-values of the first fundamental form:
- const float sigma1 = sqrtf(0.5f * max(0.0f, a + c - sqrtf(square(a - c) + 4 * square(b)))); // gamma uppercase, min eigenvalue.
- const float sigma2 = sqrtf(0.5f * max(0.0f, a + c + sqrtf(square(a - c) + 4 * square(b)))); // gamma lowercase, max eigenvalue.
- XA_ASSERT(sigma2 > sigma1 || equal(sigma1, sigma2, kEpsilon));
- // isometric: sigma1 = sigma2 = 1
- // conformal: sigma1 / sigma2 = 1
- // authalic: sigma1 * sigma2 = 1
- const float rmsStretch = sqrtf((a + c) * 0.5f);
- const float rmsStretch2 = sqrtf((square(sigma1) + square(sigma2)) * 0.5f);
- XA_DEBUG_ASSERT(equal(rmsStretch, rmsStretch2, 0.01f));
- XA_UNUSED(rmsStretch2);
- quality.stretchMetric += square(rmsStretch) * geometricArea;
- quality.maxStretchMetric = max(quality.maxStretchMetric, sigma2);
- if (!isZero(sigma1, 0.000001f)) {
- // sigma1 is zero when geometricArea is zero.
- quality.conformalMetric += (sigma2 / sigma1) * geometricArea;
- }
- quality.authalicMetric += (sigma1 * sigma2) * geometricArea;
- // Accumulate total areas.
- quality.geometricArea += geometricArea;
- quality.parametricArea += parametricArea;
- //triangleConformalEnergy(q, p);
- }
- if (quality.flippedTriangleCount + quality.zeroAreaTriangleCount == quality.totalTriangleCount) {
- // If all triangles are flipped, then none are.
- if (flippedFaces)
- flippedFaces->clear();
- quality.flippedTriangleCount = 0;
- }
- if (quality.flippedTriangleCount > quality.totalTriangleCount / 2)
- {
- // If more than half the triangles are flipped, reverse the flipped / not flipped classification.
- quality.flippedTriangleCount = quality.totalTriangleCount - quality.flippedTriangleCount;
- if (flippedFaces) {
- Array<uint32_t> temp;
- flippedFaces->copyTo(temp);
- flippedFaces->clear();
- for (uint32_t f = 0; f < faceCount; f++) {
- bool match = false;
- for (uint32_t ff = 0; ff < temp.size(); ff++) {
- if (temp[ff] == f) {
- match = true;
- break;
+ flippedFaces->clear();
+ flippedTriangleCount = 0;
+ }
+ if (flippedTriangleCount > totalTriangleCount / 2) {
+ // If more than half the triangles are flipped, reverse the flipped / not flipped classification.
+ flippedTriangleCount = totalTriangleCount - flippedTriangleCount;
+ if (flippedFaces) {
+ Array<uint32_t> temp;
+ flippedFaces->copyTo(temp);
+ flippedFaces->clear();
+ for (uint32_t f = 0; f < faceCount; f++) {
+ bool match = false;
+ for (uint32_t ff = 0; ff < temp.size(); ff++) {
+ if (temp[ff] == f) {
+ match = true;
+ break;
+ }
}
+ if (!match)
+ flippedFaces->push_back(f);
}
- if (!match)
- flippedFaces->push_back(f);
}
}
}
- XA_DEBUG_ASSERT(isFinite(quality.parametricArea) && quality.parametricArea >= 0);
- XA_DEBUG_ASSERT(isFinite(quality.geometricArea) && quality.geometricArea >= 0);
- XA_DEBUG_ASSERT(isFinite(quality.stretchMetric));
- XA_DEBUG_ASSERT(isFinite(quality.maxStretchMetric));
- XA_DEBUG_ASSERT(isFinite(quality.conformalMetric));
- XA_DEBUG_ASSERT(isFinite(quality.authalicMetric));
- if (quality.geometricArea <= 0.0f) {
- quality.stretchMetric = 0.0f;
- quality.maxStretchMetric = 0.0f;
- quality.conformalMetric = 0.0f;
- quality.authalicMetric = 0.0f;
- } else {
- const float normFactor = sqrtf(quality.parametricArea / quality.geometricArea);
- quality.stretchMetric = sqrtf(quality.stretchMetric / quality.geometricArea) * normFactor;
- quality.maxStretchMetric *= normFactor;
- quality.conformalMetric = sqrtf(quality.conformalMetric / quality.geometricArea);
- quality.authalicMetric = sqrtf(quality.authalicMetric / quality.geometricArea);
+
+ void computeMetrics(const Mesh *mesh, uint32_t faceCount) {
+ totalGeometricArea = totalParametricArea = 0.0f;
+ stretchMetric = maxStretchMetric = conformalMetric = authalicMetric = 0.0f;
+ for (uint32_t f = 0; f < faceCount; f++) {
+ Vector3 pos[3];
+ Vector2 texcoord[3];
+ for (int i = 0; i < 3; i++) {
+ const uint32_t v = mesh->vertexAt(f * 3 + i);
+ pos[i] = mesh->position(v);
+ texcoord[i] = mesh->texcoord(v);
+ }
+ // Evaluate texture stretch metric. See:
+ // - "Texture Mapping Progressive Meshes", Sander, Snyder, Gortler & Hoppe
+ // - "Mesh Parameterization: Theory and Practice", Siggraph'07 Course Notes, Hormann, Levy & Sheffer.
+ const float t1 = texcoord[0].x;
+ const float s1 = texcoord[0].y;
+ const float t2 = texcoord[1].x;
+ const float s2 = texcoord[1].y;
+ const float t3 = texcoord[2].x;
+ const float s3 = texcoord[2].y;
+ float parametricArea = ((s2 - s1) * (t3 - t1) - (s3 - s1) * (t2 - t1)) * 0.5f;
+ if (isZero(parametricArea, kAreaEpsilon))
+ continue;
+ if (parametricArea < 0.0f)
+ parametricArea = fabsf(parametricArea);
+ const float geometricArea = length(cross(pos[1] - pos[0], pos[2] - pos[0])) / 2;
+ const Vector3 Ss = (pos[0] * (t2 - t3) + pos[1] * (t3 - t1) + pos[2] * (t1 - t2)) / (2 * parametricArea);
+ const Vector3 St = (pos[0] * (s3 - s2) + pos[1] * (s1 - s3) + pos[2] * (s2 - s1)) / (2 * parametricArea);
+ const float a = dot(Ss, Ss); // E
+ const float b = dot(Ss, St); // F
+ const float c = dot(St, St); // G
+ // Compute eigen-values of the first fundamental form:
+ const float sigma1 = sqrtf(0.5f * max(0.0f, a + c - sqrtf(square(a - c) + 4 * square(b)))); // gamma uppercase, min eigenvalue.
+ const float sigma2 = sqrtf(0.5f * max(0.0f, a + c + sqrtf(square(a - c) + 4 * square(b)))); // gamma lowercase, max eigenvalue.
+ XA_ASSERT(sigma2 > sigma1 || equal(sigma1, sigma2, kEpsilon));
+ // isometric: sigma1 = sigma2 = 1
+ // conformal: sigma1 / sigma2 = 1
+ // authalic: sigma1 * sigma2 = 1
+ const float rmsStretch = sqrtf((a + c) * 0.5f);
+ const float rmsStretch2 = sqrtf((square(sigma1) + square(sigma2)) * 0.5f);
+ XA_DEBUG_ASSERT(equal(rmsStretch, rmsStretch2, 0.01f));
+ XA_UNUSED(rmsStretch2);
+ stretchMetric += square(rmsStretch) * geometricArea;
+ maxStretchMetric = max(maxStretchMetric, sigma2);
+ if (!isZero(sigma1, 0.000001f)) {
+ // sigma1 is zero when geometricArea is zero.
+ conformalMetric += (sigma2 / sigma1) * geometricArea;
+ }
+ authalicMetric += (sigma1 * sigma2) * geometricArea;
+ // Accumulate total areas.
+ totalGeometricArea += geometricArea;
+ totalParametricArea += parametricArea;
+ }
+ XA_DEBUG_ASSERT(isFinite(totalParametricArea) && totalParametricArea >= 0);
+ XA_DEBUG_ASSERT(isFinite(totalGeometricArea) && totalGeometricArea >= 0);
+ XA_DEBUG_ASSERT(isFinite(stretchMetric));
+ XA_DEBUG_ASSERT(isFinite(maxStretchMetric));
+ XA_DEBUG_ASSERT(isFinite(conformalMetric));
+ XA_DEBUG_ASSERT(isFinite(authalicMetric));
+ if (totalGeometricArea > 0.0f) {
+ const float normFactor = sqrtf(totalParametricArea / totalGeometricArea);
+ stretchMetric = sqrtf(stretchMetric / totalGeometricArea) * normFactor;
+ maxStretchMetric *= normFactor;
+ conformalMetric = sqrtf(conformalMetric / totalGeometricArea);
+ authalicMetric = sqrtf(authalicMetric / totalGeometricArea);
+ }
}
- return quality;
-}
+};
-struct ChartWarningFlags
-{
- enum Enum
- {
- CloseHolesFailed = 1<<1,
- FixTJunctionsDuplicatedEdge = 1<<2,
- FixTJunctionsFailed = 1<<3,
- TriangulateDuplicatedEdge = 1<<4,
+struct ChartWarningFlags {
+ enum Enum {
+ CloseHolesFailed = 1 << 1,
+ FixTJunctionsDuplicatedEdge = 1 << 2,
+ FixTJunctionsFailed = 1 << 3,
+ TriangulateDuplicatedEdge = 1 << 4,
};
};
+struct ChartCtorBuffers {
+ Array<uint32_t> chartMeshIndices;
+ Array<uint32_t> unifiedMeshIndices;
+ Array<uint32_t> boundaryLoops;
+};
+
/// A chart is a connected set of faces with a certain topology (usually a disk).
-class Chart
-{
+class Chart {
public:
- Chart(const segment::Atlas *atlas, const Mesh *originalMesh, uint32_t chartIndex, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) : m_mesh(nullptr), m_unifiedMesh(nullptr), m_isDisk(false), m_isOrtho(false), m_isPlanar(false), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0)
- {
+ Chart(ChartCtorBuffers &buffers, const Basis &basis, ConstArrayView<uint32_t> faces, const Mesh *originalMesh, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) :
+ m_basis(basis), m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::LSCM), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0) {
XA_UNUSED(meshId);
XA_UNUSED(chartGroupId);
XA_UNUSED(chartId);
- m_basis = atlas->chartBasis(chartIndex);
- atlas->chartFaces(chartIndex).copyTo(m_faceArray);
+ m_faceArray.copyFrom(faces.data, faces.length);
// Copy face indices.
m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
m_unifiedMesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
- Array<uint32_t> chartMeshIndices;
+ Array<uint32_t> &chartMeshIndices = buffers.chartMeshIndices;
chartMeshIndices.resize(originalMesh->vertexCount());
chartMeshIndices.setAll(UINT32_MAX);
- Array<uint32_t> unifiedMeshIndices;
+ Array<uint32_t> &unifiedMeshIndices = buffers.unifiedMeshIndices;
unifiedMeshIndices.resize(originalMesh->vertexCount());
unifiedMeshIndices.setAll(UINT32_MAX);
// Add vertices.
@@ -5735,11 +6334,7 @@ public:
if (unifiedMeshIndices[unifiedVertex] == (uint32_t)~0) {
unifiedMeshIndices[unifiedVertex] = m_unifiedMesh->vertexCount();
XA_DEBUG_ASSERT(equal(originalMesh->position(vertex), originalMesh->position(unifiedVertex), originalMesh->epsilon()));
-#if XA_SKIP_PARAMETERIZATION
- m_unifiedMesh->addVertex(originalMesh->position(vertex), Vector3(0.0f), atlas->faceTexcoords(m_faceArray[f])[i]);
-#else
m_unifiedMesh->addVertex(originalMesh->position(vertex));
-#endif
}
if (chartMeshIndices[vertex] == (uint32_t)~0) {
chartMeshIndices[vertex] = m_mesh->vertexCount();
@@ -5774,11 +6369,10 @@ public:
}
m_mesh->createBoundaries(); // For AtlasPacker::computeBoundingBox
m_unifiedMesh->createBoundaries();
- m_unifiedMesh->linkBoundaries();
- m_isPlanar = meshIsPlanar(*m_unifiedMesh);
- if (m_isPlanar) {
- m_isDisk = true;
- } else {
+ if (meshIsPlanar(*m_unifiedMesh))
+ m_type = ChartType::Planar;
+ else {
+ m_unifiedMesh->linkBoundaries();
#if XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION
m_unifiedMesh->writeObjFile("debug_before_fix_tjunction.obj");
#endif
@@ -5791,15 +6385,14 @@ public:
m_warningFlags |= ChartWarningFlags::FixTJunctionsDuplicatedEdge;
if (failed)
m_warningFlags |= ChartWarningFlags::FixTJunctionsFailed;
- m_unifiedMesh->~Mesh();
- XA_FREE(m_unifiedMesh);
+ m_unmodifiedUnifiedMesh = m_unifiedMesh;
m_unifiedMesh = fixedUnifiedMesh;
m_unifiedMesh->createBoundaries();
m_unifiedMesh->linkBoundaries();
m_initialFaceCount = m_unifiedMesh->faceCount(); // Fixing t-junctions rewrites faces.
}
// See if there are any holes that need closing.
- Array<uint32_t> boundaryLoops;
+ Array<uint32_t> &boundaryLoops = buffers.boundaryLoops;
meshGetBoundaryLoops(*m_unifiedMesh, boundaryLoops);
if (boundaryLoops.size() > 1) {
#if XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR
@@ -5810,16 +6403,21 @@ public:
// - Find cuts that reduce genus.
// - Find cuts to connect holes.
// - Use minimal spanning trees or seamster.
- Array<uint32_t> holeFaceCounts;
XA_PROFILE_START(closeChartMeshHoles)
- failed = !meshCloseHoles(m_unifiedMesh, boundaryLoops, m_basis.normal, holeFaceCounts);
+ uint32_t holeCount = 0;
+#if XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR
+ Array<uint32_t> holeFaceCounts;
+ failed = !meshCloseHoles(m_unifiedMesh, boundaryLoops, m_basis.normal, &holeFaceCounts);
+#else
+ failed = !meshCloseHoles(m_unifiedMesh, boundaryLoops, m_basis.normal, &holeCount, nullptr);
+#endif
XA_PROFILE_END(closeChartMeshHoles)
m_unifiedMesh->createBoundaries();
m_unifiedMesh->linkBoundaries();
meshGetBoundaryLoops(*m_unifiedMesh, boundaryLoops);
if (failed || boundaryLoops.size() > 1)
m_warningFlags |= ChartWarningFlags::CloseHolesFailed;
- m_closedHolesCount = holeFaceCounts.size();
+ m_closedHolesCount = holeCount;
#if XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR
if (m_warningFlags & ChartWarningFlags::CloseHolesFailed) {
char filename[256];
@@ -5848,21 +6446,77 @@ public:
}
#endif
}
- // Note: MeshTopology needs linked boundaries.
- MeshTopology topology(m_unifiedMesh);
- m_isDisk = topology.isDisk();
-#if XA_DEBUG_EXPORT_OBJ_NOT_DISK
- if (!m_isDisk) {
- char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_chart_%03u_not_disk.obj", meshId, chartGroupId, chartId);
- m_unifiedMesh->writeObjFile(filename);
+ }
+ }
+
+#if XA_RECOMPUTE_CHARTS
+ Chart(ChartCtorBuffers &buffers, const Chart *parent, const Mesh *parentMesh, ConstArrayView<uint32_t> faces, const Vector2 *texcoords, const Mesh *originalMesh, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) :
+ m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::Piecewise), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0) {
+ XA_UNUSED(meshId);
+ XA_UNUSED(chartGroupId);
+ XA_UNUSED(chartId);
+ const uint32_t faceCount = m_initialFaceCount = faces.length;
+ m_faceArray.resize(faceCount);
+ for (uint32_t i = 0; i < faceCount; i++)
+ m_faceArray[i] = parent->m_faceArray[faces[i]]; // Map faces to parent chart original mesh.
+ // Copy face indices.
+ m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
+ m_unifiedMesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
+ Array<uint32_t> &chartMeshIndices = buffers.chartMeshIndices;
+ chartMeshIndices.resize(originalMesh->vertexCount());
+ chartMeshIndices.setAll(UINT32_MAX);
+ Array<uint32_t> &unifiedMeshIndices = buffers.unifiedMeshIndices;
+ unifiedMeshIndices.resize(originalMesh->vertexCount());
+ unifiedMeshIndices.setAll(UINT32_MAX);
+ // Add vertices.
+ for (uint32_t f = 0; f < faceCount; f++) {
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = originalMesh->vertexAt(m_faceArray[f] * 3 + i);
+ const uint32_t unifiedVertex = originalMesh->firstColocal(vertex);
+ const uint32_t parentVertex = parentMesh->vertexAt(faces[f] * 3 + i);
+ if (unifiedMeshIndices[unifiedVertex] == (uint32_t)~0) {
+ unifiedMeshIndices[unifiedVertex] = m_unifiedMesh->vertexCount();
+ XA_DEBUG_ASSERT(equal(originalMesh->position(vertex), originalMesh->position(unifiedVertex), originalMesh->epsilon()));
+ m_unifiedMesh->addVertex(originalMesh->position(vertex), Vector3(0.0f), texcoords[parentVertex]);
+ }
+ if (chartMeshIndices[vertex] == (uint32_t)~0) {
+ chartMeshIndices[vertex] = m_mesh->vertexCount();
+ m_chartToOriginalMap.push_back(vertex);
+ m_chartToUnifiedMap.push_back(unifiedMeshIndices[unifiedVertex]);
+ m_mesh->addVertex(originalMesh->position(vertex), Vector3(0.0f), texcoords[parentVertex]);
+ }
+ }
+ }
+ // Add faces.
+ for (uint32_t f = 0; f < faceCount; f++) {
+ uint32_t indices[3], unifiedIndices[3];
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = originalMesh->vertexAt(m_faceArray[f] * 3 + i);
+ indices[i] = chartMeshIndices[vertex];
+ unifiedIndices[i] = unifiedMeshIndices[originalMesh->firstColocal(vertex)];
+ }
+ Mesh::AddFaceResult::Enum result = m_mesh->addFace(indices);
+ XA_UNUSED(result);
+ XA_DEBUG_ASSERT(result == Mesh::AddFaceResult::OK);
+#if XA_DEBUG
+ // Unifying colocals may create degenerate edges. e.g. if two triangle vertices are colocal.
+ for (int i = 0; i < 3; i++) {
+ const uint32_t index1 = unifiedIndices[i];
+ const uint32_t index2 = unifiedIndices[(i + 1) % 3];
+ XA_DEBUG_ASSERT(index1 != index2);
}
#endif
+ result = m_unifiedMesh->addFace(unifiedIndices);
+ XA_UNUSED(result);
+ XA_DEBUG_ASSERT(result == Mesh::AddFaceResult::OK);
}
+ m_mesh->createBoundaries(); // For AtlasPacker::computeBoundingBox
+ m_unifiedMesh->createBoundaries();
+ m_unifiedMesh->linkBoundaries();
}
+#endif
- ~Chart()
- {
+ ~Chart() {
if (m_mesh) {
m_mesh->~Mesh();
XA_FREE(m_mesh);
@@ -5871,16 +6525,19 @@ public:
m_unifiedMesh->~Mesh();
XA_FREE(m_unifiedMesh);
}
+ if (m_unmodifiedUnifiedMesh) {
+ m_unmodifiedUnifiedMesh->~Mesh();
+ XA_FREE(m_unmodifiedUnifiedMesh);
+ }
}
const Basis &basis() const { return m_basis; }
- bool isDisk() const { return m_isDisk; }
- bool isOrtho() const { return m_isOrtho; }
- bool isPlanar() const { return m_isPlanar; }
+ ChartType::Enum type() const { return m_type; }
uint32_t warningFlags() const { return m_warningFlags; }
uint32_t closedHolesCount() const { return m_closedHolesCount; }
uint32_t fixedTJunctionsCount() const { return m_fixedTJunctionsCount; }
- const ParameterizationQuality &paramQuality() const { return m_paramQuality; }
+ const Quality &quality() const { return m_quality; }
+ uint32_t initialFaceCount() const { return m_initialFaceCount; }
#if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION
const Array<uint32_t> &paramFlippedFaces() const { return m_paramFlippedFaces; }
#endif
@@ -5889,49 +6546,40 @@ public:
Mesh *mesh() { return m_mesh; }
const Mesh *unifiedMesh() const { return m_unifiedMesh; }
Mesh *unifiedMesh() { return m_unifiedMesh; }
+ const Mesh *unmodifiedUnifiedMesh() const { return m_unmodifiedUnifiedMesh; }
uint32_t mapChartVertexToOriginalVertex(uint32_t i) const { return m_chartToOriginalMap[i]; }
- void evaluateOrthoParameterizationQuality()
- {
+ void evaluateOrthoQuality(UniformGrid2 &boundaryGrid) {
XA_PROFILE_START(parameterizeChartsEvaluateQuality)
- m_paramQuality = calculateParameterizationQuality(m_unifiedMesh, m_initialFaceCount, nullptr);
+ m_quality.computeBoundaryIntersection(m_unifiedMesh, boundaryGrid);
+ m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, nullptr);
+ m_quality.computeMetrics(m_unifiedMesh, m_initialFaceCount);
XA_PROFILE_END(parameterizeChartsEvaluateQuality)
// Use orthogonal parameterization if quality is acceptable.
- if (!m_paramQuality.boundaryIntersection && m_paramQuality.geometricArea > 0.0f && m_paramQuality.stretchMetric <= 1.1f && m_paramQuality.maxStretchMetric <= 1.25f)
- m_isOrtho = true;
+ if (!m_quality.boundaryIntersection && m_quality.totalGeometricArea > 0.0f && m_quality.stretchMetric <= 1.1f && m_quality.maxStretchMetric <= 1.25f)
+ m_type = ChartType::Ortho;
}
- void evaluateParameterizationQuality()
- {
+ void evaluateQuality(UniformGrid2 &boundaryGrid) {
XA_PROFILE_START(parameterizeChartsEvaluateQuality)
+ m_quality.computeBoundaryIntersection(m_unifiedMesh, boundaryGrid);
#if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION
- m_paramQuality = calculateParameterizationQuality(m_unifiedMesh, m_initialFaceCount, &m_paramFlippedFaces);
+ m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, &m_paramFlippedFaces);
#else
- m_paramQuality = calculateParameterizationQuality(m_unifiedMesh, m_initialFaceCount, nullptr);
+ m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, nullptr);
#endif
+ // Don't need to call computeMetrics here, that's only used in evaluateOrthoQuality to determine if quality is acceptable enough to use ortho projection.
XA_PROFILE_END(parameterizeChartsEvaluateQuality)
}
// Transfer parameterization from unified mesh to chart mesh.
- void transferParameterization()
- {
+ void transferParameterization() {
const uint32_t vertexCount = m_mesh->vertexCount();
for (uint32_t v = 0; v < vertexCount; v++)
m_mesh->texcoord(v) = m_unifiedMesh->texcoord(m_chartToUnifiedMap[v]);
}
- float computeSurfaceArea() const
- {
- return m_mesh->computeSurfaceArea();
- }
-
- float computeParametricArea() const
- {
- return m_mesh->computeParametricArea();
- }
-
- Vector2 computeParametricBounds() const
- {
+ Vector2 computeParametricBounds() const {
Vector2 minCorner(FLT_MAX, FLT_MAX);
Vector2 maxCorner(-FLT_MAX, -FLT_MAX);
const uint32_t vertexCount = m_mesh->vertexCount();
@@ -5946,7 +6594,8 @@ private:
Basis m_basis;
Mesh *m_mesh;
Mesh *m_unifiedMesh;
- bool m_isDisk, m_isOrtho, m_isPlanar;
+ Mesh *m_unmodifiedUnifiedMesh; // Unified mesh before fixing t-junctions. Null if no t-junctions were fixed
+ ChartType::Enum m_type;
uint32_t m_warningFlags;
uint32_t m_initialFaceCount; // Before fixing T-junctions and/or closing holes.
uint32_t m_closedHolesCount, m_fixedTJunctionsCount;
@@ -5959,89 +6608,93 @@ private:
Array<uint32_t> m_chartToUnifiedMap;
- ParameterizationQuality m_paramQuality;
+ Quality m_quality;
#if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION
Array<uint32_t> m_paramFlippedFaces;
#endif
};
-struct CreateChartTaskArgs
-{
- const segment::Atlas *atlas;
+struct CreateChartTaskArgs {
const Mesh *mesh;
- uint32_t chartIndex; // In the atlas.
+ const Basis *basis;
+ ConstArrayView<uint32_t> faces;
uint32_t meshId;
uint32_t chartGroupId;
uint32_t chartId;
+ ThreadLocal<ChartCtorBuffers> *chartBuffers;
Chart **chart;
};
-static void runCreateChartTask(void *userData)
-{
+static void runCreateChartTask(void *userData) {
XA_PROFILE_START(createChartMeshesThread)
auto args = (CreateChartTaskArgs *)userData;
- *(args->chart) = XA_NEW_ARGS(MemTag::Default, Chart, args->atlas, args->mesh, args->chartIndex, args->meshId, args->chartGroupId, args->chartId);
+ *(args->chart) = XA_NEW_ARGS(MemTag::Default, Chart, args->chartBuffers->get(), *(args->basis), args->faces, args->mesh, args->meshId, args->chartGroupId, args->chartId);
XA_PROFILE_END(createChartMeshesThread)
}
-struct ParameterizeChartTaskArgs
-{
+struct ParameterizeChartTaskArgs {
Chart *chart;
ParameterizeFunc func;
+ ThreadLocal<UniformGrid2> *boundaryGrid;
};
-static void runParameterizeChartTask(void *userData)
-{
+static void runParameterizeChartTask(void *userData) {
auto args = (ParameterizeChartTaskArgs *)userData;
Mesh *mesh = args->chart->unifiedMesh();
- XA_PROFILE_START(parameterizeChartsOrthogonal)
-#if 1
- computeOrthogonalProjectionMap(mesh);
-#else
- for (uint32_t i = 0; i < vertexCount; i++)
- mesh->texcoord(i) = Vector2(dot(args->chart->basis().tangent, mesh->position(i)), dot(args->chart->basis().bitangent, mesh->position(i)));
-#endif
+ XA_PROFILE_START(parameterizeChartsOrthogonal) {
+ // Project vertices to plane.
+ const uint32_t vertexCount = mesh->vertexCount();
+ const Basis &basis = args->chart->basis();
+ for (uint32_t i = 0; i < vertexCount; i++)
+ mesh->texcoord(i) = Vector2(dot(basis.tangent, mesh->position(i)), dot(basis.bitangent, mesh->position(i)));
+ }
XA_PROFILE_END(parameterizeChartsOrthogonal)
- args->chart->evaluateOrthoParameterizationQuality();
- if (!args->chart->isOrtho() && !args->chart->isPlanar()) {
+ // Computing charts checks for flipped triangles and boundary intersection. Don't need to do that again here if chart is planar.
+ if (args->chart->type() != ChartType::Planar)
+ args->chart->evaluateOrthoQuality(args->boundaryGrid->get());
+ if (args->chart->type() == ChartType::LSCM) {
XA_PROFILE_START(parameterizeChartsLSCM)
if (args->func)
args->func(&mesh->position(0).x, &mesh->texcoord(0).x, mesh->vertexCount(), mesh->indices(), mesh->indexCount());
- else if (args->chart->isDisk())
+ else
computeLeastSquaresConformalMap(mesh);
XA_PROFILE_END(parameterizeChartsLSCM)
- args->chart->evaluateParameterizationQuality();
+ args->chart->evaluateQuality(args->boundaryGrid->get());
}
- // @@ Check that parameterization quality is above a certain threshold.
// Transfer parameterization from unified mesh to chart mesh.
args->chart->transferParameterization();
}
// Set of charts corresponding to mesh faces in the same face group.
-class ChartGroup
-{
+class ChartGroup {
public:
- ChartGroup(uint32_t id, const Mesh *sourceMesh, uint32_t faceGroup) : m_sourceId(sourceMesh->id()), m_id(id), m_isVertexMap(faceGroup == UINT32_MAX), m_paramAddedChartsCount(0), m_paramDeletedChartsCount(0)
- {
+ ChartGroup(uint32_t id, const Mesh *sourceMesh, uint16_t faceGroup) :
+ m_sourceId(sourceMesh->id()), m_id(id), m_isVertexMap(faceGroup == Mesh::kInvalidFaceGroup), m_paramAddedChartsCount(0), m_paramDeletedChartsCount(0) {
// Create new mesh from the source mesh, using faces that belong to this group.
const uint32_t sourceFaceCount = sourceMesh->faceCount();
- for (uint32_t f = 0; f < sourceFaceCount; f++) {
- if (sourceMesh->faceGroupAt(f) == faceGroup)
- m_faceToSourceFaceMap.push_back(f);
+ if (!m_isVertexMap) {
+ m_faceToSourceFaceMap.reserve(sourceMesh->faceGroupFaceCount(faceGroup));
+ for (Mesh::GroupFaceIterator it(sourceMesh, faceGroup); !it.isDone(); it.advance())
+ m_faceToSourceFaceMap.push_back(it.face());
+ } else {
+ for (uint32_t f = 0; f < sourceFaceCount; f++) {
+ if (sourceMesh->faceGroupAt(f) == faceGroup)
+ m_faceToSourceFaceMap.push_back(f);
+ }
}
// Only initial meshes have face groups and ignored faces. The only flag we care about is HasNormals.
const uint32_t faceCount = m_faceToSourceFaceMap.size();
- m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, sourceMesh->epsilon(), faceCount * 3, faceCount, sourceMesh->flags() & MeshFlags::HasNormals);
XA_DEBUG_ASSERT(faceCount > 0);
- Array<uint32_t> meshIndices;
- meshIndices.resize(sourceMesh->vertexCount());
- meshIndices.setAll((uint32_t)~0);
+ const uint32_t approxVertexCount = faceCount * 3;
+ m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, sourceMesh->epsilon(), approxVertexCount, faceCount, sourceMesh->flags() & MeshFlags::HasNormals);
+ m_vertexToSourceVertexMap.reserve(approxVertexCount);
+ HashMap<uint32_t> sourceVertexToVertexMap(MemTag::Mesh, approxVertexCount);
for (uint32_t f = 0; f < faceCount; f++) {
const uint32_t face = m_faceToSourceFaceMap[f];
for (uint32_t i = 0; i < 3; i++) {
const uint32_t vertex = sourceMesh->vertexAt(face * 3 + i);
- if (meshIndices[vertex] == (uint32_t)~0) {
- meshIndices[vertex] = m_mesh->vertexCount();
+ if (sourceVertexToVertexMap.get(vertex) == UINT32_MAX) {
+ sourceVertexToVertexMap.add(vertex);
m_vertexToSourceVertexMap.push_back(vertex);
Vector3 normal(0.0f);
if (sourceMesh->flags() & MeshFlags::HasNormals)
@@ -6056,8 +6709,8 @@ public:
uint32_t indices[3];
for (uint32_t i = 0; i < 3; i++) {
const uint32_t vertex = sourceMesh->vertexAt(face * 3 + i);
- XA_DEBUG_ASSERT(meshIndices[vertex] != (uint32_t)~0);
- indices[i] = meshIndices[vertex];
+ indices[i] = sourceVertexToVertexMap.get(vertex);
+ XA_DEBUG_ASSERT(indices[i] != UINT32_MAX);
}
// Don't copy flags, it doesn't matter if a face is ignored after this point. All ignored faces get their own vertex map (m_isVertexMap) ChartGroup.
// Don't hash edges if m_isVertexMap, they may be degenerate.
@@ -6068,7 +6721,6 @@ public:
if (!m_isVertexMap) {
m_mesh->createColocals();
m_mesh->createBoundaries();
- m_mesh->linkBoundaries();
}
#if XA_DEBUG_EXPORT_OBJ_CHART_GROUPS
char filename[256];
@@ -6079,18 +6731,17 @@ public:
#endif
}
- ~ChartGroup()
- {
+ ~ChartGroup() {
m_mesh->~Mesh();
XA_FREE(m_mesh);
- for (uint32_t i = 0; i < m_chartArray.size(); i++) {
- m_chartArray[i]->~Chart();
- XA_FREE(m_chartArray[i]);
+ for (uint32_t i = 0; i < m_charts.size(); i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
}
}
- uint32_t chartCount() const { return m_chartArray.size(); }
- Chart *chartAt(uint32_t i) const { return m_chartArray[i]; }
+ uint32_t chartCount() const { return m_charts.size(); }
+ Chart *chartAt(uint32_t i) const { return m_charts[i]; }
uint32_t paramAddedChartsCount() const { return m_paramAddedChartsCount; }
uint32_t paramDeletedChartsCount() const { return m_paramDeletedChartsCount; }
bool isVertexMap() const { return m_isVertexMap; }
@@ -6158,40 +6809,40 @@ public:
- emphasize roundness metrics to prevent those cases.
- If interior self-overlaps: preserve boundary parameterization and use mean-value map.
*/
- void computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options)
- {
+ void computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, segment::Atlas &atlas, ThreadLocal<ChartCtorBuffers> *chartBuffers) {
m_chartOptions = options;
// This function may be called multiple times, so destroy existing charts.
- for (uint32_t i = 0; i < m_chartArray.size(); i++) {
- m_chartArray[i]->~Chart();
- XA_FREE(m_chartArray[i]);
+ for (uint32_t i = 0; i < m_charts.size(); i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
}
- m_chartArray.clear();
+ m_charts.clear();
#if XA_DEBUG_SINGLE_CHART
Array<uint32_t> chartFaces;
chartFaces.resize(m_mesh->faceCount());
for (uint32_t i = 0; i < chartFaces.size(); i++)
chartFaces[i] = i;
Chart *chart = XA_NEW_ARGS(MemTag::Default, Chart, m_mesh, chartFaces, m_sourceId, m_id, 0);
- m_chartArray.push_back(chart);
+ m_charts.push_back(chart);
#else
XA_PROFILE_START(buildAtlas)
- segment::Atlas atlas(m_mesh, nullptr, options);
+ atlas.reset(m_sourceId, m_id, m_mesh, options);
buildAtlas(atlas, options);
XA_PROFILE_END(buildAtlas)
const uint32_t chartCount = atlas.chartCount();
- m_chartArray.resize(chartCount);
+ m_charts.resize(chartCount);
Array<CreateChartTaskArgs> taskArgs;
taskArgs.resize(chartCount);
for (uint32_t i = 0; i < chartCount; i++) {
CreateChartTaskArgs &args = taskArgs[i];
- args.atlas = &atlas;
+ args.basis = &atlas.chartBasis(i);
+ args.faces = atlas.chartFaces(i);
args.mesh = m_mesh;
- args.chartIndex = i;
args.meshId = m_sourceId;
args.chartGroupId = m_id;
args.chartId = i;
- args.chart = &m_chartArray[i];
+ args.chartBuffers = chartBuffers;
+ args.chart = &m_charts[i];
}
XA_PROFILE_START(createChartMeshesReal)
TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartCount);
@@ -6225,26 +6876,22 @@ public:
#endif
}
- void parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func)
- {
- const uint32_t chartCount = m_chartArray.size();
-#if XA_SKIP_PARAMETERIZATION
- XA_UNUSED(taskScheduler);
- XA_UNUSED(func);
- for (uint32_t i = 0; i < chartCount; i++) {
- Chart *chart = m_chartArray[i];
- chart->evaluateOrthoParameterizationQuality();
- chart->evaluateParameterizationQuality();
- chart->transferParameterization();
- }
+#if XA_RECOMPUTE_CHARTS
+ void parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ThreadLocal<UniformGrid2> *boundaryGrid, ThreadLocal<ChartCtorBuffers> *chartBuffers, ThreadLocal<PiecewiseParam> *piecewiseParam)
#else
+ void parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ThreadLocal<UniformGrid2> *boundaryGrid, ThreadLocal<ChartCtorBuffers> * /*chartBuffers*/)
+#endif
+ {
+ m_paramAddedChartsCount = 0;
+ const uint32_t chartCount = m_charts.size();
Array<ParameterizeChartTaskArgs> taskArgs;
taskArgs.resize(chartCount);
TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartCount);
for (uint32_t i = 0; i < chartCount; i++) {
ParameterizeChartTaskArgs &args = taskArgs[i];
- args.chart = m_chartArray[i];
+ args.chart = m_charts[i];
args.func = func;
+ args.boundaryGrid = boundaryGrid;
Task task;
task.userData = &args;
task.func = runParameterizeChartTask;
@@ -6255,67 +6902,65 @@ public:
// Find charts with invalid parameterizations.
Array<Chart *> invalidCharts;
for (uint32_t i = 0; i < chartCount; i++) {
- Chart *chart = m_chartArray[i];
- const ParameterizationQuality &quality = chart->paramQuality();
+ Chart *chart = m_charts[i];
+ const Quality &quality = chart->quality();
if (quality.boundaryIntersection || quality.flippedTriangleCount > 0)
invalidCharts.push_back(chart);
}
if (invalidCharts.isEmpty())
return;
// Recompute charts with invalid parameterizations.
- Array<uint32_t> meshFaces;
+ PiecewiseParam &pp = piecewiseParam->get();
for (uint32_t i = 0; i < invalidCharts.size(); i++) {
Chart *invalidChart = invalidCharts[i];
- const Mesh *invalidMesh = invalidChart->mesh();
- const uint32_t faceCount = invalidMesh->faceCount();
- meshFaces.resize(faceCount);
- float invalidChartArea = 0.0f;
- for (uint32_t j = 0; j < faceCount; j++) {
- meshFaces[j] = invalidChart->mapFaceToSourceFace(j);
- invalidChartArea += invalidMesh->faceArea(j);
- }
- ChartOptions options = m_chartOptions;
- options.maxChartArea = invalidChartArea * 0.2f;
- options.maxThreshold = 0.25f;
- options.maxIterations = 3;
- segment::Atlas atlas(m_mesh, &meshFaces, options);
- buildAtlas(atlas, options);
- for (uint32_t j = 0; j < atlas.chartCount(); j++) {
- Chart *chart = XA_NEW_ARGS(MemTag::Default, Chart, &atlas, m_mesh, j, m_sourceId, m_id, m_chartArray.size());
- m_chartArray.push_back(chart);
- m_paramAddedChartsCount++;
+ // Fixing t-junctions rewrites unified mesh faces, and we need to map faces back to input mesh. So use the unmodified unified mesh.
+ const Mesh *invalidMesh = invalidChart->unmodifiedUnifiedMesh();
+ uint32_t faceCount = 0;
+ if (invalidMesh) {
+ faceCount = invalidMesh->faceCount();
+ } else {
+ invalidMesh = invalidChart->unifiedMesh();
+ faceCount = invalidChart->initialFaceCount(); // Not invalidMesh->faceCount(). Don't want faces added by hole closing.
}
+ pp.reset(invalidMesh, faceCount);
#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_recomputed_chart_%u.obj", m_sourceId, m_id, i);
+ XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_recomputed_chart_%03u.obj", m_sourceId, m_id, m_paramAddedChartsCount);
FILE *file;
XA_FOPEN(file, filename, "w");
- if (file) {
- m_mesh->writeObjVertices(file);
- for (uint32_t j = 0; j < builder.chartCount(); j++) {
- fprintf(file, "o chart_%04d\n", j);
+ uint32_t subChartIndex = 0;
+#endif
+ for (;;) {
+ if (!pp.computeChart())
+ break;
+ Chart *chart = XA_NEW_ARGS(MemTag::Default, Chart, chartBuffers->get(), invalidChart, invalidMesh, pp.chartFaces(), pp.texcoords(), m_mesh, m_sourceId, m_id, m_charts.size());
+ m_charts.push_back(chart);
+#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
+ if (file) {
+ for (uint32_t j = 0; j < invalidMesh->vertexCount(); j++) {
+ fprintf(file, "v %g %g %g\n", invalidMesh->position(j).x, invalidMesh->position(j).y, invalidMesh->position(j).z);
+ fprintf(file, "vt %g %g\n", pp.texcoords()[j].x, pp.texcoords()[j].y);
+ }
+ fprintf(file, "o chart%03u\n", subChartIndex);
fprintf(file, "s off\n");
- const Array<uint32_t> &faces = builder.chartFaces(j);
- for (uint32_t f = 0; f < faces.size(); f++)
- m_mesh->writeObjFace(file, faces[f]);
+ for (uint32_t f = 0; f < pp.chartFaces().length; f++) {
+ fprintf(file, "f ");
+ const uint32_t face = pp.chartFaces()[f];
+ for (uint32_t j = 0; j < 3; j++) {
+ const uint32_t index = invalidMesh->vertexCount() * subChartIndex + invalidMesh->vertexAt(face * 3 + j) + 1; // 1-indexed
+ fprintf(file, "%d/%d/%c", index, index, j == 2 ? '\n' : ' ');
+ }
+ }
}
- fclose(file);
+ subChartIndex++;
+#endif
+ m_paramAddedChartsCount++;
}
+#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
+ if (file)
+ fclose(file);
#endif
}
- // Parameterize the new charts.
- taskGroup = taskScheduler->createTaskGroup(m_chartArray.size() - chartCount);
- taskArgs.resize(m_chartArray.size() - chartCount);
- for (uint32_t i = chartCount; i < m_chartArray.size(); i++) {
- ParameterizeChartTaskArgs &args = taskArgs[i - chartCount];
- args.chart = m_chartArray[i];
- args.func = func;
- Task task;
- task.userData = &args;
- task.func = runParameterizeChartTask;
- taskScheduler->run(taskGroup, task);
- }
- taskScheduler->wait(&taskGroup);
// Remove and delete the invalid charts.
for (uint32_t i = 0; i < invalidCharts.size(); i++) {
Chart *chart = invalidCharts[i];
@@ -6325,12 +6970,10 @@ public:
m_paramDeletedChartsCount++;
}
#endif // XA_RECOMPUTE_CHARTS
-#endif // XA_SKIP_PARAMETERIZATION
}
private:
- void buildAtlas(segment::Atlas &atlas, const ChartOptions &options)
- {
+ void buildAtlas(segment::Atlas &atlas, const ChartOptions &options) {
if (atlas.facesLeft() == 0)
return;
// Create initial charts greedely.
@@ -6343,29 +6986,27 @@ private:
atlas.resetCharts();
// Restart process growing charts in parallel.
uint32_t iteration = 0;
- while (true) {
- if (!atlas.growCharts(options.maxThreshold)) {
- // If charts cannot grow more: fill holes, merge charts, relocate seeds and start new iteration.
- atlas.fillHoles(options.maxThreshold * 0.5f);
+ for (;;) {
+ atlas.growCharts(options.maxThreshold);
+ // When charts cannot grow more: fill holes, merge charts, relocate seeds and start new iteration.
+ atlas.fillHoles(options.maxThreshold * 0.5f);
#if XA_MERGE_CHARTS
- atlas.mergeCharts();
+ atlas.mergeCharts();
#endif
- if (++iteration == options.maxIterations)
- break;
- if (!atlas.relocateSeeds())
- break;
- atlas.resetCharts();
- }
+ if (++iteration == options.maxIterations)
+ break;
+ if (!atlas.relocateSeeds())
+ break;
+ atlas.resetCharts();
}
// Make sure no holes are left!
XA_DEBUG_ASSERT(atlas.facesLeft() == 0);
}
- void removeChart(const Chart *chart)
- {
- for (uint32_t i = 0; i < m_chartArray.size(); i++) {
- if (m_chartArray[i] == chart) {
- m_chartArray.removeAt(i);
+ void removeChart(const Chart *chart) {
+ for (uint32_t i = 0; i < m_charts.size(); i++) {
+ if (m_charts[i] == chart) {
+ m_charts.removeAt(i);
return;
}
}
@@ -6376,76 +7017,80 @@ private:
Mesh *m_mesh;
Array<uint32_t> m_faceToSourceFaceMap; // List of faces of the source mesh that belong to this chart group.
Array<uint32_t> m_vertexToSourceVertexMap; // Map vertices of the mesh to vertices of the source mesh.
- Array<Chart *> m_chartArray;
+ Array<Chart *> m_charts;
ChartOptions m_chartOptions;
uint32_t m_paramAddedChartsCount; // Number of new charts added by recomputing charts with invalid parameterizations.
uint32_t m_paramDeletedChartsCount; // Number of charts with invalid parameterizations that were deleted, after charts were recomputed.
};
-struct CreateChartGroupTaskArgs
-{
- uint32_t faceGroup;
+struct CreateChartGroupTaskArgs {
+ uint16_t faceGroup;
uint32_t groupId;
const Mesh *mesh;
ChartGroup **chartGroup;
};
-static void runCreateChartGroupTask(void *userData)
-{
+static void runCreateChartGroupTask(void *userData) {
XA_PROFILE_START(addMeshCreateChartGroupsThread)
auto args = (CreateChartGroupTaskArgs *)userData;
*(args->chartGroup) = XA_NEW_ARGS(MemTag::Default, ChartGroup, args->groupId, args->mesh, args->faceGroup);
XA_PROFILE_END(addMeshCreateChartGroupsThread)
}
-struct ComputeChartsTaskArgs
-{
+struct ComputeChartsTaskArgs {
TaskScheduler *taskScheduler;
ChartGroup *chartGroup;
+ ThreadLocal<segment::Atlas> *atlas;
+ ThreadLocal<ChartCtorBuffers> *chartBuffers;
const ChartOptions *options;
Progress *progress;
};
-static void runComputeChartsJob(void *userData)
-{
+static void runComputeChartsJob(void *userData) {
auto args = (ComputeChartsTaskArgs *)userData;
if (args->progress->cancel)
return;
XA_PROFILE_START(computeChartsThread)
- args->chartGroup->computeCharts(args->taskScheduler, *args->options);
+ args->chartGroup->computeCharts(args->taskScheduler, *args->options, args->atlas->get(), args->chartBuffers);
XA_PROFILE_END(computeChartsThread)
args->progress->value++;
args->progress->update();
}
-struct ParameterizeChartsTaskArgs
-{
+struct ParameterizeChartsTaskArgs {
TaskScheduler *taskScheduler;
ChartGroup *chartGroup;
ParameterizeFunc func;
+ ThreadLocal<UniformGrid2> *boundaryGrid;
+ ThreadLocal<ChartCtorBuffers> *chartBuffers;
+#if XA_RECOMPUTE_CHARTS
+ ThreadLocal<PiecewiseParam> *piecewiseParam;
+#endif
Progress *progress;
};
-static void runParameterizeChartsJob(void *userData)
-{
+static void runParameterizeChartsJob(void *userData) {
auto args = (ParameterizeChartsTaskArgs *)userData;
if (args->progress->cancel)
return;
XA_PROFILE_START(parameterizeChartsThread)
- args->chartGroup->parameterizeCharts(args->taskScheduler, args->func);
+#if XA_RECOMPUTE_CHARTS
+ args->chartGroup->parameterizeCharts(args->taskScheduler, args->func, args->boundaryGrid, args->chartBuffers, args->piecewiseParam);
+#else
+ args->chartGroup->parameterizeCharts(args->taskScheduler, args->func, args->boundaryGrid, args->chartBuffers);
+#endif
XA_PROFILE_END(parameterizeChartsThread)
args->progress->value++;
args->progress->update();
}
/// An atlas is a set of chart groups.
-class Atlas
-{
+class Atlas {
public:
- Atlas() : m_meshCount(0), m_chartsComputed(false), m_chartsParameterized(false) {}
+ Atlas() :
+ m_meshCount(0), m_chartsComputed(false), m_chartsParameterized(false) {}
- ~Atlas()
- {
+ ~Atlas() {
for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
m_chartGroups[i]->~ChartGroup();
XA_FREE(m_chartGroups[i]);
@@ -6457,8 +7102,7 @@ public:
uint32_t chartGroupCount() const { return m_chartGroups.size(); }
const ChartGroup *chartGroupAt(uint32_t index) const { return m_chartGroups[index]; }
- uint32_t chartGroupCount(uint32_t mesh) const
- {
+ uint32_t chartGroupCount(uint32_t mesh) const {
uint32_t count = 0;
for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
if (m_chartGroupSourceMeshes[i] == mesh)
@@ -6467,8 +7111,7 @@ public:
return count;
}
- const ChartGroup *chartGroupAt(uint32_t mesh, uint32_t group) const
- {
+ const ChartGroup *chartGroupAt(uint32_t mesh, uint32_t group) const {
for (uint32_t c = 0; c < m_chartGroups.size(); c++) {
if (m_chartGroupSourceMeshes[c] != mesh)
continue;
@@ -6480,33 +7123,18 @@ public:
}
// This function is thread safe.
- void addMesh(TaskScheduler *taskScheduler, const Mesh *mesh)
- {
- // Get list of face groups.
- const uint32_t faceCount = mesh->faceCount();
- Array<uint32_t> faceGroups;
- for (uint32_t f = 0; f < faceCount; f++) {
- const uint32_t group = mesh->faceGroupAt(f);
- bool exists = false;
- for (uint32_t g = 0; g < faceGroups.size(); g++) {
- if (faceGroups[g] == group) {
- exists = true;
- break;
- }
- }
- if (!exists)
- faceGroups.push_back(group);
- }
+ void addMesh(TaskScheduler *taskScheduler, const Mesh *mesh) {
// Create one chart group per face group.
+ // If there's any ignored faces in the mesh, create an extra face group for that (vertex map).
// Chart group creation is slow since it copies a chunk of the source mesh, so use tasks.
Array<ChartGroup *> chartGroups;
- chartGroups.resize(faceGroups.size());
+ chartGroups.resize(mesh->faceGroupCount() + (mesh->ignoredFaceCount() > 0 ? 1 : 0));
Array<CreateChartGroupTaskArgs> taskArgs;
taskArgs.resize(chartGroups.size());
for (uint32_t g = 0; g < chartGroups.size(); g++) {
CreateChartGroupTaskArgs &args = taskArgs[g];
args.chartGroup = &chartGroups[g];
- args.faceGroup = faceGroups[g];
+ args.faceGroup = uint16_t(g < mesh->faceGroupCount() ? g : Mesh::kInvalidFaceGroup);
args.groupId = g;
args.mesh = mesh;
}
@@ -6530,8 +7158,7 @@ public:
// Chart id/index is determined by depth-first hierarchy of mesh -> chart group -> chart.
// For chart index to be consistent here, chart groups needs to sorted by mesh index. Since addMesh is called by multithreaded tasks, order is indeterminate, so chart groups need to be explicitly sorted after all meshes are added.
- void sortChartGroups()
- {
+ void sortChartGroups() {
Array<ChartGroup *> oldChartGroups;
oldChartGroups.resize(m_chartGroups.size());
memcpy(oldChartGroups.data(), m_chartGroups.data(), sizeof(ChartGroup *) * m_chartGroups.size());
@@ -6550,8 +7177,7 @@ public:
}
}
- bool computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, ProgressFunc progressFunc, void *progressUserData)
- {
+ bool computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, ProgressFunc progressFunc, void *progressUserData) {
m_chartsComputed = false;
m_chartsParameterized = false;
// Ignore vertex maps.
@@ -6561,6 +7187,8 @@ public:
chartGroupCount++;
}
Progress progress(ProgressCategory::ComputeCharts, progressFunc, progressUserData, chartGroupCount);
+ ThreadLocal<segment::Atlas> atlas;
+ ThreadLocal<ChartCtorBuffers> chartBuffers;
Array<ComputeChartsTaskArgs> taskArgs;
taskArgs.reserve(chartGroupCount);
for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
@@ -6568,6 +7196,8 @@ public:
ComputeChartsTaskArgs args;
args.taskScheduler = taskScheduler;
args.chartGroup = m_chartGroups[i];
+ args.atlas = &atlas;
+ args.chartBuffers = &chartBuffers;
args.options = &options;
args.progress = &progress;
taskArgs.push_back(args);
@@ -6595,8 +7225,7 @@ public:
return true;
}
- bool parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ProgressFunc progressFunc, void *progressUserData)
- {
+ bool parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ProgressFunc progressFunc, void *progressUserData) {
m_chartsParameterized = false;
// Ignore vertex maps.
uint32_t chartGroupCount = 0;
@@ -6605,6 +7234,11 @@ public:
chartGroupCount++;
}
Progress progress(ProgressCategory::ParameterizeCharts, progressFunc, progressUserData, chartGroupCount);
+ ThreadLocal<UniformGrid2> boundaryGrid; // For Quality boundary intersection.
+ ThreadLocal<ChartCtorBuffers> chartBuffers;
+#if XA_RECOMPUTE_CHARTS
+ ThreadLocal<PiecewiseParam> piecewiseParam;
+#endif
Array<ParameterizeChartsTaskArgs> taskArgs;
taskArgs.reserve(chartGroupCount);
for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
@@ -6613,6 +7247,11 @@ public:
args.taskScheduler = taskScheduler;
args.chartGroup = m_chartGroups[i];
args.func = func;
+ args.boundaryGrid = &boundaryGrid;
+ args.chartBuffers = &chartBuffers;
+#if XA_RECOMPUTE_CHARTS
+ args.piecewiseParam = &piecewiseParam;
+#endif
args.progress = &progress;
taskArgs.push_back(args);
}
@@ -6646,66 +7285,15 @@ private:
namespace pack {
-#if XA_DEBUG_EXPORT_ATLAS_IMAGES
-const uint8_t TGA_TYPE_RGB = 2;
-const uint8_t TGA_ORIGIN_UPPER = 0x20;
-
-#pragma pack(push, 1)
-struct TgaHeader
-{
- uint8_t id_length;
- uint8_t colormap_type;
- uint8_t image_type;
- uint16_t colormap_index;
- uint16_t colormap_length;
- uint8_t colormap_size;
- uint16_t x_origin;
- uint16_t y_origin;
- uint16_t width;
- uint16_t height;
- uint8_t pixel_size;
- uint8_t flags;
- enum { Size = 18 };
-};
-#pragma pack(pop)
-
-static void WriteTga(const char *filename, const uint8_t *data, uint32_t width, uint32_t height)
-{
- XA_DEBUG_ASSERT(sizeof(TgaHeader) == TgaHeader::Size);
- FILE *f;
- XA_FOPEN(f, filename, "wb");
- if (!f)
- return;
- TgaHeader tga;
- tga.id_length = 0;
- tga.colormap_type = 0;
- tga.image_type = TGA_TYPE_RGB;
- tga.colormap_index = 0;
- tga.colormap_length = 0;
- tga.colormap_size = 0;
- tga.x_origin = 0;
- tga.y_origin = 0;
- tga.width = (uint16_t)width;
- tga.height = (uint16_t)height;
- tga.pixel_size = 24;
- tga.flags = TGA_ORIGIN_UPPER;
- fwrite(&tga, sizeof(TgaHeader), 1, f);
- fwrite(data, sizeof(uint8_t), width * height * 3, f);
- fclose(f);
-}
-#endif
-
-class AtlasImage
-{
+class AtlasImage {
public:
- AtlasImage(uint32_t width, uint32_t height) : m_width(width), m_height(height)
- {
+ AtlasImage(uint32_t width, uint32_t height) :
+ m_width(width), m_height(height) {
m_data.resize(m_width * m_height);
memset(m_data.data(), 0, sizeof(uint32_t) * m_data.size());
}
- void resize(uint32_t width, uint32_t height)
- {
+ void resize(uint32_t width, uint32_t height) {
Array<uint32_t> data;
data.resize(width * height);
memset(data.data(), 0, sizeof(uint32_t) * data.size());
@@ -6716,8 +7304,7 @@ public:
data.moveTo(m_data);
}
- void addChart(uint32_t chartIndex, const BitImage *image, const BitImage *imageBilinear, const BitImage *imagePadding, int atlas_w, int atlas_h, int offset_x, int offset_y)
- {
+ void addChart(uint32_t chartIndex, const BitImage *image, const BitImage *imageBilinear, const BitImage *imagePadding, int atlas_w, int atlas_h, int offset_x, int offset_y) {
const int w = image->width();
const int h = image->height();
for (int y = 0; y < h; y++) {
@@ -6728,13 +7315,13 @@ public:
const int xx = x + offset_x;
if (xx >= 0 && xx < atlas_w && yy < atlas_h) {
const uint32_t dataOffset = xx + yy * m_width;
- if (image->bitAt(x, y)) {
+ if (image->get(x, y)) {
XA_DEBUG_ASSERT(m_data[dataOffset] == 0);
m_data[dataOffset] = chartIndex | kImageHasChartIndexBit;
- } else if (imageBilinear && imageBilinear->bitAt(x, y)) {
+ } else if (imageBilinear && imageBilinear->get(x, y)) {
XA_DEBUG_ASSERT(m_data[dataOffset] == 0);
m_data[dataOffset] = chartIndex | kImageHasChartIndexBit | kImageIsBilinearBit;
- } else if (imagePadding && imagePadding->bitAt(x, y)) {
+ } else if (imagePadding && imagePadding->get(x, y)) {
XA_DEBUG_ASSERT(m_data[dataOffset] == 0);
m_data[dataOffset] = chartIndex | kImageHasChartIndexBit | kImageIsPaddingBit;
}
@@ -6743,15 +7330,13 @@ public:
}
}
- void copyTo(uint32_t *dest, uint32_t destWidth, uint32_t destHeight, int padding) const
- {
+ void copyTo(uint32_t *dest, uint32_t destWidth, uint32_t destHeight, int padding) const {
for (uint32_t y = 0; y < destHeight; y++)
memcpy(&dest[y * destWidth], &m_data[padding + (y + padding) * m_width], destWidth * sizeof(uint32_t));
}
#if XA_DEBUG_EXPORT_ATLAS_IMAGES
- void writeTga(const char *filename, uint32_t width, uint32_t height) const
- {
+ void writeTga(const char *filename, uint32_t width, uint32_t height) const {
Array<uint8_t> image;
image.resize(width * height * 3);
for (uint32_t y = 0; y < height; y++) {
@@ -6793,8 +7378,7 @@ private:
Array<uint32_t> m_data;
};
-struct Chart
-{
+struct Chart {
int32_t atlasIndex;
uint32_t material;
uint32_t indexCount;
@@ -6807,6 +7391,8 @@ struct Chart
bool allowRotate;
// bounding box
Vector2 majorAxis, minorAxis, minCorner, maxCorner;
+ // Mesh only
+ const Array<uint32_t> *boundaryEdges;
// UvMeshChart only
Array<uint32_t> faces;
@@ -6814,14 +7400,13 @@ struct Chart
uint32_t uniqueVertexCount() const { return uniqueVertices.isEmpty() ? vertexCount : uniqueVertices.size(); }
};
-struct AddChartTaskArgs
-{
+struct AddChartTaskArgs {
+ ThreadLocal<BoundingBox2D> *boundingBox;
param::Chart *paramChart;
Chart *chart; // out
};
-static void runAddChartTask(void *userData)
-{
+static void runAddChartTask(void *userData) {
XA_PROFILE_START(packChartsAddChartsThread)
auto args = (AddChartTaskArgs *)userData;
param::Chart *paramChart = args->paramChart;
@@ -6834,106 +7419,34 @@ static void runAddChartTask(void *userData)
chart->material = 0;
chart->indexCount = mesh->indexCount();
chart->indices = mesh->indices();
- chart->parametricArea = paramChart->computeParametricArea();
+ chart->parametricArea = mesh->computeParametricArea();
if (chart->parametricArea < kAreaEpsilon) {
// When the parametric area is too small we use a rough approximation to prevent divisions by very small numbers.
const Vector2 bounds = paramChart->computeParametricBounds();
chart->parametricArea = bounds.x * bounds.y;
}
- chart->surfaceArea = paramChart->computeSurfaceArea();
+ chart->surfaceArea = mesh->computeSurfaceArea();
chart->vertices = mesh->texcoords();
chart->vertexCount = mesh->vertexCount();
chart->allowRotate = true;
- // Compute list of boundary vertices.
- Array<Vector2> boundary;
- boundary.reserve(16);
+ chart->boundaryEdges = &mesh->boundaryEdges();
+ // Compute bounding box of chart.
+ BoundingBox2D &bb = args->boundingBox->get();
+ bb.clear();
for (uint32_t v = 0; v < chart->vertexCount; v++) {
if (mesh->isBoundaryVertex(v))
- boundary.push_back(mesh->texcoord(v));
+ bb.appendBoundaryVertex(mesh->texcoord(v));
}
- XA_DEBUG_ASSERT(boundary.size() > 0);
- // Compute bounding box of chart.
- static thread_local BoundingBox2D boundingBox;
- boundingBox.compute(boundary.data(), boundary.size(), mesh->texcoords(), mesh->vertexCount());
- chart->majorAxis = boundingBox.majorAxis();
- chart->minorAxis = boundingBox.minorAxis();
- chart->minCorner = boundingBox.minCorner();
- chart->maxCorner = boundingBox.maxCorner();
+ bb.compute(mesh->texcoords(), mesh->vertexCount());
+ chart->majorAxis = bb.majorAxis;
+ chart->minorAxis = bb.minorAxis;
+ chart->minCorner = bb.minCorner;
+ chart->maxCorner = bb.maxCorner;
XA_PROFILE_END(packChartsAddChartsThread)
}
-struct FindChartLocationBruteForceTaskArgs
-{
- std::atomic<bool> *finished; // One of the tasks found a location that doesn't expand the atlas.
- Vector2i startPosition;
- const BitImage *atlasBitImage;
- const BitImage *chartBitImage;
- const BitImage *chartBitImageRotated;
- int w, h;
- bool blockAligned, allowRotate;
- uint32_t maxResolution;
- // out
- bool best_insideAtlas;
- int best_metric, best_x, best_y, best_w, best_h, best_r;
-};
-
-static void runFindChartLocationBruteForceTask(void *userData)
-{
- XA_PROFILE_START(packChartsFindLocationThread)
- auto args = (FindChartLocationBruteForceTaskArgs *)userData;
- args->best_metric = INT_MAX;
- if (args->finished->load())
- return;
- // Try two different orientations.
- for (int r = 0; r < 2; r++) {
- if (args->finished->load())
- break;
- int cw = args->chartBitImage->width();
- int ch = args->chartBitImage->height();
- if (r == 1) {
- if (args->allowRotate)
- swap(cw, ch);
- else
- break;
- }
- const int y = args->startPosition.y;
- const int stepSize = args->blockAligned ? 4 : 1;
- for (int x = args->startPosition.x; x <= args->w + stepSize; x += stepSize) {
- if (args->maxResolution > 0 && (x > (int)args->maxResolution - cw || y > (int)args->maxResolution - ch))
- continue;
- if (args->finished->load())
- break;
- // Early out if metric not better.
- const int area = max(args->w, x + cw) * max(args->h, y + ch);
- const int extents = max(max(args->w, x + cw), max(args->h, y + ch));
- const int metric = extents * extents + area;
- if (metric > args->best_metric)
- continue;
- // If metric is the same, pick the one closest to the origin.
- if (metric == args->best_metric && max(x, y) >= max(args->best_x, args->best_y))
- continue;
- if (!args->atlasBitImage->canBlit(r == 1 ? *(args->chartBitImageRotated) : *(args->chartBitImage), x, y))
- continue;
- args->best_metric = metric;
- args->best_insideAtlas = area == args->w * args->h;
- args->best_x = x;
- args->best_y = y;
- args->best_w = cw;
- args->best_h = ch;
- args->best_r = r;
- if (args->best_insideAtlas) {
- args->finished->store(true);
- break;
- }
- }
- }
- XA_PROFILE_END(packChartsFindLocationThread)
-}
-
-struct Atlas
-{
- ~Atlas()
- {
+struct Atlas {
+ ~Atlas() {
for (uint32_t i = 0; i < m_atlasImages.size(); i++) {
m_atlasImages[i]->~AtlasImage();
XA_FREE(m_atlasImages[i]);
@@ -6957,8 +7470,7 @@ struct Atlas
const Array<AtlasImage *> &getImages() const { return m_atlasImages; }
float getUtilization(uint32_t atlas) const { return m_utilization[atlas]; }
- void addCharts(TaskScheduler *taskScheduler, param::Atlas *paramAtlas)
- {
+ void addCharts(TaskScheduler *taskScheduler, param::Atlas *paramAtlas) {
// Count charts.
uint32_t chartCount = 0;
const uint32_t chartGroupsCount = paramAtlas->chartGroupCount();
@@ -6975,6 +7487,7 @@ struct Atlas
taskArgs.resize(chartCount);
TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartCount);
uint32_t chartIndex = 0;
+ ThreadLocal<BoundingBox2D> boundingBox;
for (uint32_t i = 0; i < chartGroupsCount; i++) {
const param::ChartGroup *chartGroup = paramAtlas->chartGroupAt(i);
if (chartGroup->isVertexMap())
@@ -6982,6 +7495,7 @@ struct Atlas
const uint32_t count = chartGroup->chartCount();
for (uint32_t j = 0; j < count; j++) {
AddChartTaskArgs &args = taskArgs[chartIndex];
+ args.boundingBox = &boundingBox;
args.paramChart = chartGroup->chartAt(j);
Task task;
task.userData = &taskArgs[chartIndex];
@@ -6997,11 +7511,8 @@ struct Atlas
m_charts[i] = taskArgs[i].chart;
}
- void addUvMeshCharts(UvMeshInstance *mesh)
- {
+ void addUvMeshCharts(UvMeshInstance *mesh) {
BitArray vertexUsed(mesh->texcoords.size());
- Array<Vector2> boundary;
- boundary.reserve(16);
BoundingBox2D boundingBox;
for (uint32_t c = 0; c < mesh->mesh->charts.size(); c++) {
UvMeshChart *uvChart = mesh->mesh->charts[c];
@@ -7013,14 +7524,15 @@ struct Atlas
chart->vertices = mesh->texcoords.data();
chart->vertexCount = mesh->texcoords.size();
chart->allowRotate = mesh->rotateCharts;
+ chart->boundaryEdges = nullptr;
chart->faces.resize(uvChart->faces.size());
memcpy(chart->faces.data(), uvChart->faces.data(), sizeof(uint32_t) * uvChart->faces.size());
// Find unique vertices.
- vertexUsed.clearAll();
+ vertexUsed.zeroOutMemory();
for (uint32_t i = 0; i < chart->indexCount; i++) {
const uint32_t vertex = chart->indices[i];
- if (!vertexUsed.bitAt(vertex)) {
- vertexUsed.setBitAt(vertex);
+ if (!vertexUsed.get(vertex)) {
+ vertexUsed.set(vertex);
chart->uniqueVertices.push_back(vertex);
}
}
@@ -7045,25 +7557,22 @@ struct Atlas
const Vector2 bounds = (maxCorner - minCorner) * 0.5f;
chart->parametricArea = bounds.x * bounds.y;
}
- // Compute list of boundary vertices.
+ // Compute bounding box of chart.
// Using all unique vertices for simplicity, can compute real boundaries if this is too slow.
- boundary.clear();
+ boundingBox.clear();
for (uint32_t v = 0; v < chart->uniqueVertexCount(); v++)
- boundary.push_back(chart->uniqueVertexAt(v));
- XA_DEBUG_ASSERT(boundary.size() > 0);
- // Compute bounding box of chart.
- boundingBox.compute(boundary.data(), boundary.size(), boundary.data(), boundary.size());
- chart->majorAxis = boundingBox.majorAxis();
- chart->minorAxis = boundingBox.minorAxis();
- chart->minCorner = boundingBox.minCorner();
- chart->maxCorner = boundingBox.maxCorner();
+ boundingBox.appendBoundaryVertex(chart->uniqueVertexAt(v));
+ boundingBox.compute();
+ chart->majorAxis = boundingBox.majorAxis;
+ chart->minorAxis = boundingBox.minorAxis;
+ chart->minCorner = boundingBox.minCorner;
+ chart->maxCorner = boundingBox.maxCorner;
m_charts.push_back(chart);
}
}
// Pack charts in the smallest possible rectangle.
- bool packCharts(TaskScheduler *taskScheduler, const PackOptions &options, ProgressFunc progressFunc, void *progressUserData)
- {
+ bool packCharts(const PackOptions &options, ProgressFunc progressFunc, void *progressUserData) {
if (progressFunc) {
if (!progressFunc(ProgressCategory::PackCharts, 0, progressUserData))
return false;
@@ -7107,10 +7616,11 @@ struct Atlas
for (uint32_t c = 0; c < chartCount; c++) {
Chart *chart = m_charts[c];
// Compute chart scale
- float scale = (chart->surfaceArea / chart->parametricArea) * m_texelsPerUnit;
- if (chart->parametricArea == 0.0f)
- scale = 0;
- XA_ASSERT(isFinite(scale));
+ float scale = 1.0f;
+ if (chart->parametricArea != 0.0f) {
+ scale = (chart->surfaceArea / chart->parametricArea) * m_texelsPerUnit;
+ XA_ASSERT(isFinite(scale));
+ }
// Translate, rotate and scale vertices. Compute extents.
Vector2 minCorner(FLT_MAX, FLT_MAX);
if (!chart->allowRotate) {
@@ -7181,6 +7691,8 @@ struct Atlas
texcoord.y += 0.5f + options.padding;
extents = max(extents, texcoord);
}
+ if (extents.x > resolution || extents.y > resolution)
+ XA_PRINT(" Chart %u extents are large (%gx%g)\n", c, extents.x, extents.y);
chartExtents[c] = extents;
chartOrderArray[c] = extents.x + extents.y; // Use perimeter for chart sort key.
minChartPerimeter = min(minChartPerimeter, chartOrderArray[c]);
@@ -7207,6 +7719,7 @@ struct Atlas
// Rotated versions swap x and y.
BitImage chartImage, chartImageBilinear, chartImagePadding;
BitImage chartImageRotated, chartImageBilinearRotated, chartImagePaddingRotated;
+ UniformGrid2 boundaryEdgeGrid;
Array<Vector2i> atlasSizes;
atlasSizes.push_back(Vector2i(0, 0));
int progress = 0;
@@ -7249,7 +7762,7 @@ struct Atlas
}
// Expand chart by pixels sampled by bilinear interpolation.
if (options.bilinear)
- bilinearExpand(chart, &chartImage, &chartImageBilinear, chart->allowRotate ? &chartImageBilinearRotated : nullptr);
+ bilinearExpand(chart, &chartImage, &chartImageBilinear, chart->allowRotate ? &chartImageBilinearRotated : nullptr, boundaryEdgeGrid);
// Expand chart by padding pixels (dilation).
if (options.padding > 0) {
// Copy into the same BitImage instances for every chart to avoid reallocating BitImage buffers (largest chart is packed first).
@@ -7294,8 +7807,7 @@ struct Atlas
int best_x = 0, best_y = 0;
int best_cw = 0, best_ch = 0;
int best_r = 0;
- for (;;)
- {
+ for (;;) {
bool firstChartInBitImage = false;
XA_UNUSED(firstChartInBitImage);
if (currentAtlas + 1 > m_bitImages.size()) {
@@ -7310,7 +7822,7 @@ struct Atlas
chartStartPositions.push_back(Vector2i(0, 0));
}
XA_PROFILE_START(packChartsFindLocation)
- const bool foundLocation = findChartLocation(taskScheduler, chartStartPositions[currentAtlas], options.bruteForce, m_bitImages[currentAtlas], chartImageToPack, chartImageToPackRotated, atlasSizes[currentAtlas].x, atlasSizes[currentAtlas].y, &best_x, &best_y, &best_cw, &best_ch, &best_r, options.blockAlign, maxResolution, chart->allowRotate);
+ const bool foundLocation = findChartLocation(chartStartPositions[currentAtlas], options.bruteForce, m_bitImages[currentAtlas], chartImageToPack, chartImageToPackRotated, atlasSizes[currentAtlas].x, atlasSizes[currentAtlas].y, &best_x, &best_y, &best_cw, &best_ch, &best_r, options.blockAlign, maxResolution, chart->allowRotate);
XA_PROFILE_END(packChartsFindLocation)
XA_DEBUG_ASSERT(!(firstChartInBitImage && !foundLocation)); // Chart doesn't fit in an empty, newly allocated bitImage. Shouldn't happen, since charts are resized if they are too big to fit in the atlas.
if (maxResolution == 0) {
@@ -7328,8 +7840,7 @@ struct Atlas
if (best_x + best_cw > atlasSizes[currentAtlas].x || best_y + best_ch > atlasSizes[currentAtlas].y) {
for (uint32_t j = 0; j < chartStartPositions.size(); j++)
chartStartPositions[j] = Vector2i(0, 0);
- }
- else {
+ } else {
chartStartPositions[currentAtlas] = Vector2i(best_x, best_y);
}
}
@@ -7359,6 +7870,13 @@ struct Atlas
} else {
m_atlasImages[currentAtlas]->addChart(c, &chartImageRotated, options.bilinear ? &chartImageBilinearRotated : nullptr, options.padding > 0 ? &chartImagePaddingRotated : nullptr, atlasSizes[currentAtlas].x, atlasSizes[currentAtlas].y, best_x, best_y);
}
+#if XA_DEBUG_EXPORT_ATLAS_IMAGES && XA_DEBUG_EXPORT_ATLAS_IMAGES_PER_CHART
+ for (uint32_t j = 0; j < m_atlasImages.size(); j++) {
+ char filename[256];
+ XA_SPRINTF(filename, sizeof(filename), "debug_atlas_image%02u_chart%04u.tga", j, i);
+ m_atlasImages[j]->writeTga(filename, (uint32_t)atlasSizes[j].x, (uint32_t)atlasSizes[j].y);
+ }
+#endif
}
chart->atlasIndex = (int32_t)currentAtlas;
// Modify texture coordinates:
@@ -7415,14 +7933,13 @@ struct Atlas
uint32_t count = 0;
for (uint32_t y = 0; y < m_height; y++) {
for (uint32_t x = 0; x < m_width; x++)
- count += m_bitImages[i]->bitAt(x, y);
+ count += m_bitImages[i]->get(x, y);
}
m_utilization[i] = float(count) / (m_width * m_height);
}
if (m_utilization.size() > 1) {
XA_PRINT(" %u: %f%% utilization\n", i, m_utilization[i] * 100.0f);
- }
- else {
+ } else {
XA_PRINT(" %f%% utilization\n", m_utilization[i] * 100.0f);
}
}
@@ -7445,76 +7962,59 @@ private:
// is occupied at this point. At the end we have many small charts and a large atlas with sparse holes. Finding those holes randomly is slow. A better approach would be to
// start stacking large charts as if they were tetris pieces. Once charts get small try to place them randomly. It may be interesting to try a intermediate strategy, first try
// along one axis and then try exhaustively along that axis.
- bool findChartLocation(TaskScheduler *taskScheduler, const Vector2i &startPosition, bool bruteForce, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate)
- {
+ bool findChartLocation(const Vector2i &startPosition, bool bruteForce, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate) {
const int attempts = 4096;
if (bruteForce || attempts >= w * h)
- return findChartLocation_bruteForce(taskScheduler, startPosition, atlasBitImage, chartBitImage, chartBitImageRotated, w, h, best_x, best_y, best_w, best_h, best_r, blockAligned, maxResolution, allowRotate);
+ return findChartLocation_bruteForce(startPosition, atlasBitImage, chartBitImage, chartBitImageRotated, w, h, best_x, best_y, best_w, best_h, best_r, blockAligned, maxResolution, allowRotate);
return findChartLocation_random(atlasBitImage, chartBitImage, chartBitImageRotated, w, h, best_x, best_y, best_w, best_h, best_r, attempts, blockAligned, maxResolution, allowRotate);
}
- bool findChartLocation_bruteForce(TaskScheduler *taskScheduler, const Vector2i &startPosition, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate)
- {
+ bool findChartLocation_bruteForce(const Vector2i &startPosition, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate) {
const int stepSize = blockAligned ? 4 : 1;
- const int chartMinHeight = min(chartBitImage->height(), chartBitImageRotated->height());
- uint32_t taskCount = 0;
- for (int y = startPosition.y; y <= h + stepSize; y += stepSize) {
- if (maxResolution > 0 && y > (int)maxResolution - chartMinHeight)
- break;
- taskCount++;
- }
- m_bruteForceTaskArgs.clear();
- m_bruteForceTaskArgs.resize(taskCount);
- TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(taskCount);
- std::atomic<bool> finished(false); // One of the tasks found a location that doesn't expand the atlas.
- uint32_t i = 0;
- for (int y = startPosition.y; y <= h + stepSize; y += stepSize) {
- if (maxResolution > 0 && y > (int)maxResolution - chartMinHeight)
- break;
- FindChartLocationBruteForceTaskArgs &args = m_bruteForceTaskArgs[i];
- args.finished = &finished;
- args.startPosition = Vector2i(y == startPosition.y ? startPosition.x : 0, y);
- args.atlasBitImage = atlasBitImage;
- args.chartBitImage = chartBitImage;
- args.chartBitImageRotated = chartBitImageRotated;
- args.w = w;
- args.h = h;
- args.blockAligned = blockAligned;
- args.allowRotate = allowRotate;
- args.maxResolution = maxResolution;
- Task task;
- task.userData = &m_bruteForceTaskArgs[i];
- task.func = runFindChartLocationBruteForceTask;
- taskScheduler->run(taskGroup, task);
- i++;
- }
- taskScheduler->wait(&taskGroup);
- // Find the task result with the best metric.
int best_metric = INT_MAX;
- bool best_insideAtlas = false;
- for (i = 0; i < taskCount; i++) {
- FindChartLocationBruteForceTaskArgs &args = m_bruteForceTaskArgs[i];
- if (args.best_metric > best_metric)
- continue;
- // A location that doesn't expand the atlas is always preferred.
- if (!args.best_insideAtlas && best_insideAtlas)
- continue;
- // If metric is the same, pick the one closest to the origin.
- if (args.best_insideAtlas == best_insideAtlas && args.best_metric == best_metric && max(args.best_x, args.best_y) >= max(*best_x, *best_y))
- continue;
- best_metric = args.best_metric;
- best_insideAtlas = args.best_insideAtlas;
- *best_x = args.best_x;
- *best_y = args.best_y;
- *best_w = args.best_w;
- *best_h = args.best_h;
- *best_r = args.best_r;
+ // Try two different orientations.
+ for (int r = 0; r < 2; r++) {
+ int cw = chartBitImage->width();
+ int ch = chartBitImage->height();
+ if (r == 1) {
+ if (allowRotate)
+ swap(cw, ch);
+ else
+ break;
+ }
+ for (int y = startPosition.y; y <= h + stepSize; y += stepSize) {
+ if (maxResolution > 0 && y > (int)maxResolution - ch)
+ break;
+ for (int x = (y == startPosition.y ? startPosition.x : 0); x <= w + stepSize; x += stepSize) {
+ if (maxResolution > 0 && x > (int)maxResolution - cw)
+ break;
+ // Early out if metric is not better.
+ const int extentX = max(w, x + cw), extentY = max(h, y + ch);
+ const int area = extentX * extentY;
+ const int extents = max(extentX, extentY);
+ const int metric = extents * extents + area;
+ if (metric > best_metric)
+ continue;
+ // If metric is the same, pick the one closest to the origin.
+ if (metric == best_metric && max(x, y) >= max(*best_x, *best_y))
+ continue;
+ if (!atlasBitImage->canBlit(r == 1 ? *chartBitImageRotated : *chartBitImage, x, y))
+ continue;
+ best_metric = metric;
+ *best_x = x;
+ *best_y = y;
+ *best_w = cw;
+ *best_h = ch;
+ *best_r = r;
+ if (area == w * h)
+ return true; // Chart is completely inside, do not look at any other location.
+ }
+ }
}
return best_metric != INT_MAX;
}
- bool findChartLocation_random(const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, int minTrialCount, bool blockAligned, uint32_t maxResolution, bool allowRotate)
- {
+ bool findChartLocation_random(const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, int minTrialCount, bool blockAligned, uint32_t maxResolution, bool allowRotate) {
bool result = false;
const int BLOCK_SIZE = 4;
int best_metric = INT_MAX;
@@ -7569,8 +8069,7 @@ private:
return result;
}
- void addChart(BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int atlas_w, int atlas_h, int offset_x, int offset_y, int r)
- {
+ void addChart(BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int atlas_w, int atlas_h, int offset_x, int offset_y, int r) {
XA_DEBUG_ASSERT(r == 0 || r == 1);
const BitImage *image = r == 0 ? chartBitImage : chartBitImageRotated;
const int w = image->width();
@@ -7581,10 +8080,10 @@ private:
for (int x = 0; x < w; x++) {
int xx = x + offset_x;
if (xx >= 0) {
- if (image->bitAt(x, y)) {
+ if (image->get(x, y)) {
if (xx < atlas_w && yy < atlas_h) {
- XA_DEBUG_ASSERT(atlasBitImage->bitAt(xx, yy) == false);
- atlasBitImage->setBitAt(xx, yy);
+ XA_DEBUG_ASSERT(atlasBitImage->get(xx, yy) == false);
+ atlasBitImage->set(xx, yy);
}
}
}
@@ -7593,14 +8092,22 @@ private:
}
}
- void bilinearExpand(const Chart *chart, BitImage *source, BitImage *dest, BitImage *destRotated) const
- {
+ void bilinearExpand(const Chart *chart, BitImage *source, BitImage *dest, BitImage *destRotated, UniformGrid2 &boundaryEdgeGrid) const {
+ boundaryEdgeGrid.reset(chart->vertices, chart->indices);
+ if (chart->boundaryEdges) {
+ const uint32_t edgeCount = chart->boundaryEdges->size();
+ for (uint32_t i = 0; i < edgeCount; i++)
+ boundaryEdgeGrid.append((*chart->boundaryEdges)[i]);
+ } else {
+ for (uint32_t i = 0; i < chart->indexCount; i++)
+ boundaryEdgeGrid.append(i);
+ }
const int xOffsets[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
const int yOffsets[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
for (uint32_t y = 0; y < source->height(); y++) {
for (uint32_t x = 0; x < source->width(); x++) {
// Copy pixels from source.
- if (source->bitAt(x, y))
+ if (source->get(x, y))
goto setPixel;
// Empty pixel. If none of of the surrounding pixels are set, this pixel can't be sampled by bilinear interpolation.
{
@@ -7610,59 +8117,45 @@ private:
const int sy = (int)y + yOffsets[s];
if (sx < 0 || sy < 0 || sx >= (int)source->width() || sy >= (int)source->height())
continue;
- if (source->bitAt((uint32_t)sx, (uint32_t)sy))
+ if (source->get((uint32_t)sx, (uint32_t)sy))
break;
}
if (s == 8)
continue;
}
- // If a 2x2 square centered on the pixels centroid intersects the triangle, this pixel will be sampled by bilinear interpolation.
- // See "Precomputed Global Illumination in Frostbite (GDC 2018)" page 95
- for (uint32_t f = 0; f < chart->indexCount / 3; f++) {
+ {
+ // If a 2x2 square centered on the pixels centroid intersects the triangle, this pixel will be sampled by bilinear interpolation.
+ // See "Precomputed Global Illumination in Frostbite (GDC 2018)" page 95
const Vector2 centroid((float)x + 0.5f, (float)y + 0.5f);
- Vector2 vertices[3];
- for (uint32_t i = 0; i < 3; i++)
- vertices[i] = chart->vertices[chart->indices[f * 3 + i]];
- // Test for triangle vertex in square bounds.
- for (uint32_t i = 0; i < 3; i++) {
- const Vector2 &v = vertices[i];
- if (v.x > centroid.x - 1.0f && v.x < centroid.x + 1.0f && v.y > centroid.y - 1.0f && v.y < centroid.y + 1.0f)
- goto setPixel;
- }
- // Test for triangle edge intersection with square edge.
const Vector2 squareVertices[4] = {
Vector2(centroid.x - 1.0f, centroid.y - 1.0f),
Vector2(centroid.x + 1.0f, centroid.y - 1.0f),
Vector2(centroid.x + 1.0f, centroid.y + 1.0f),
Vector2(centroid.x - 1.0f, centroid.y + 1.0f)
};
- for (uint32_t i = 0; i < 3; i++) {
- for (uint32_t j = 0; j < 4; j++) {
- if (linesIntersect(vertices[i], vertices[(i + 1) % 3], squareVertices[j], squareVertices[(j + 1) % 4], 0.0f))
- goto setPixel;
- }
+ for (uint32_t j = 0; j < 4; j++) {
+ if (boundaryEdgeGrid.intersect(squareVertices[j], squareVertices[(j + 1) % 4], 0.0f))
+ goto setPixel;
}
}
continue;
setPixel:
- dest->setBitAt(x, y);
+ dest->set(x, y);
if (destRotated)
- destRotated->setBitAt(y, x);
+ destRotated->set(y, x);
}
}
}
- struct DrawTriangleCallbackArgs
- {
+ struct DrawTriangleCallbackArgs {
BitImage *chartBitImage, *chartBitImageRotated;
};
- static bool drawTriangleCallback(void *param, int x, int y)
- {
+ static bool drawTriangleCallback(void *param, int x, int y) {
auto args = (DrawTriangleCallbackArgs *)param;
- args->chartBitImage->setBitAt(x, y);
+ args->chartBitImage->set(x, y);
if (args->chartBitImageRotated)
- args->chartBitImageRotated->setBitAt(y, x);
+ args->chartBitImageRotated->set(y, x);
return true;
}
@@ -7670,7 +8163,6 @@ private:
Array<float> m_utilization;
Array<BitImage *> m_bitImages;
Array<Chart *> m_charts;
- Array<FindChartLocationBruteForceTaskArgs> m_bruteForceTaskArgs;
RadixSort m_radix;
uint32_t m_width = 0;
uint32_t m_height = 0;
@@ -7681,8 +8173,7 @@ private:
} // namespace pack
} // namespace internal
-struct Context
-{
+struct Context {
Atlas atlas;
uint32_t meshCount = 0;
internal::Progress *addMeshProgress = nullptr;
@@ -7695,16 +8186,14 @@ struct Context
internal::Array<internal::UvMeshInstance *> uvMeshInstances;
};
-Atlas *Create()
-{
+Atlas *Create() {
Context *ctx = XA_NEW(internal::MemTag::Default, Context);
memset(&ctx->atlas, 0, sizeof(Atlas));
ctx->taskScheduler = XA_NEW(internal::MemTag::Default, internal::TaskScheduler);
return &ctx->atlas;
}
-static void DestroyOutputMeshes(Context *ctx)
-{
+static void DestroyOutputMeshes(Context *ctx) {
if (!ctx->atlas.meshes)
return;
for (int i = 0; i < (int)ctx->atlas.meshCount; i++) {
@@ -7725,8 +8214,7 @@ static void DestroyOutputMeshes(Context *ctx)
ctx->atlas.meshes = nullptr;
}
-void Destroy(Atlas *atlas)
-{
+void Destroy(Atlas *atlas) {
XA_DEBUG_ASSERT(atlas);
Context *ctx = (Context *)atlas;
if (atlas->utilization)
@@ -7761,14 +8249,12 @@ void Destroy(Atlas *atlas)
#endif
}
-struct AddMeshTaskArgs
-{
+struct AddMeshTaskArgs {
Context *ctx;
internal::Mesh *mesh;
};
-static void runAddMeshTask(void *userData)
-{
+static void runAddMeshTask(void *userData) {
XA_PROFILE_START(addMeshThread)
auto args = (AddMeshTaskArgs *)userData; // Responsible for freeing this.
internal::Mesh *mesh = args->mesh;
@@ -7789,13 +8275,6 @@ static void runAddMeshTask(void *userData)
}
if (progress->cancel)
goto cleanup;
- {
- XA_PROFILE_START(addMeshCreateBoundaries)
- mesh->createBoundaries();
- XA_PROFILE_END(addMeshCreateBoundaries)
- }
- if (progress->cancel)
- goto cleanup;
#if XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES
char filename[256];
XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u.obj", mesh->id());
@@ -7805,22 +8284,22 @@ static void runAddMeshTask(void *userData)
mesh->writeObjVertices(file);
// groups
uint32_t numGroups = 0;
- for (uint32_t i = 0; i < mesh->faceGroupCount(); i++) {
- if (mesh->faceGroupAt(i) != UINT32_MAX)
+ for (uint32_t i = 0; i < mesh->faceCount(); i++) {
+ if (mesh->faceGroupAt(i) != Mesh::kInvalidFaceGroup)
numGroups = internal::max(numGroups, mesh->faceGroupAt(i) + 1);
}
for (uint32_t i = 0; i < numGroups; i++) {
fprintf(file, "o group_%04d\n", i);
fprintf(file, "s off\n");
- for (uint32_t f = 0; f < mesh->faceGroupCount(); f++) {
+ for (uint32_t f = 0; f < mesh->faceCount(); f++) {
if (mesh->faceGroupAt(f) == i)
mesh->writeObjFace(file, f);
}
}
fprintf(file, "o group_ignored\n");
fprintf(file, "s off\n");
- for (uint32_t f = 0; f < mesh->faceGroupCount(); f++) {
- if (mesh->faceGroupAt(f) == UINT32_MAX)
+ for (uint32_t f = 0; f < mesh->faceCount(); f++) {
+ if (mesh->faceGroupAt(f) == Mesh::kInvalidFaceGroup)
mesh->writeObjFace(file, f);
}
mesh->writeObjBoundaryEges(file);
@@ -7844,37 +8323,32 @@ cleanup:
XA_PROFILE_END(addMeshThread)
}
-static internal::Vector3 DecodePosition(const MeshDecl &meshDecl, uint32_t index)
-{
+static internal::Vector3 DecodePosition(const MeshDecl &meshDecl, uint32_t index) {
XA_DEBUG_ASSERT(meshDecl.vertexPositionData);
XA_DEBUG_ASSERT(meshDecl.vertexPositionStride > 0);
return *((const internal::Vector3 *)&((const uint8_t *)meshDecl.vertexPositionData)[meshDecl.vertexPositionStride * index]);
}
-static internal::Vector3 DecodeNormal(const MeshDecl &meshDecl, uint32_t index)
-{
+static internal::Vector3 DecodeNormal(const MeshDecl &meshDecl, uint32_t index) {
XA_DEBUG_ASSERT(meshDecl.vertexNormalData);
XA_DEBUG_ASSERT(meshDecl.vertexNormalStride > 0);
return *((const internal::Vector3 *)&((const uint8_t *)meshDecl.vertexNormalData)[meshDecl.vertexNormalStride * index]);
}
-static internal::Vector2 DecodeUv(const MeshDecl &meshDecl, uint32_t index)
-{
+static internal::Vector2 DecodeUv(const MeshDecl &meshDecl, uint32_t index) {
XA_DEBUG_ASSERT(meshDecl.vertexUvData);
XA_DEBUG_ASSERT(meshDecl.vertexUvStride > 0);
return *((const internal::Vector2 *)&((const uint8_t *)meshDecl.vertexUvData)[meshDecl.vertexUvStride * index]);
}
-static uint32_t DecodeIndex(IndexFormat::Enum format, const void *indexData, int32_t offset, uint32_t i)
-{
+static uint32_t DecodeIndex(IndexFormat::Enum format, const void *indexData, int32_t offset, uint32_t i) {
XA_DEBUG_ASSERT(indexData);
if (format == IndexFormat::UInt16)
return uint16_t((int32_t)((const uint16_t *)indexData)[i] + offset);
return uint32_t((int32_t)((const uint32_t *)indexData)[i] + offset);
}
-AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint)
-{
+AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint) {
XA_DEBUG_ASSERT(atlas);
if (!atlas) {
XA_PRINT_WARNING("AddMesh: atlas is null.\n");
@@ -7892,8 +8366,7 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh
// Don't know how many times AddMesh will be called, so progress needs to adjusted each time.
if (!ctx->addMeshProgress) {
ctx->addMeshProgress = XA_NEW_ARGS(internal::MemTag::Default, internal::Progress, ProgressCategory::AddMesh, ctx->progressFunc, ctx->progressUserData, 1);
- }
- else {
+ } else {
ctx->addMeshProgress->setMaxValue(internal::max(ctx->meshCount + 1, meshCountHint));
}
XA_PROFILE_START(addMeshCopyData)
@@ -8009,8 +8482,7 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh
return AddMeshError::Success;
}
-void AddMeshJoin(Atlas *atlas)
-{
+void AddMeshJoin(Atlas *atlas) {
XA_DEBUG_ASSERT(atlas);
if (!atlas) {
XA_PRINT_WARNING("AddMeshJoin: atlas is null.\n");
@@ -8033,34 +8505,24 @@ void AddMeshJoin(Atlas *atlas)
XA_PROFILE_PRINT_AND_RESET(" Total (thread): ", addMeshThread)
XA_PROFILE_PRINT_AND_RESET(" Create colocals: ", addMeshCreateColocals)
XA_PROFILE_PRINT_AND_RESET(" Create face groups: ", addMeshCreateFaceGroups)
- XA_PROFILE_PRINT_AND_RESET(" Create boundaries: ", addMeshCreateBoundaries)
XA_PROFILE_PRINT_AND_RESET(" Create chart groups (real): ", addMeshCreateChartGroupsReal)
XA_PROFILE_PRINT_AND_RESET(" Create chart groups (thread): ", addMeshCreateChartGroupsThread)
XA_PRINT_MEM_USAGE
}
-struct EdgeKey
-{
+struct EdgeKey {
EdgeKey() {}
- EdgeKey(const EdgeKey &k) : v0(k.v0), v1(k.v1) {}
- EdgeKey(uint32_t v0, uint32_t v1) : v0(v0), v1(v1) {}
-
- void operator=(const EdgeKey &k)
- {
- v0 = k.v0;
- v1 = k.v1;
- }
- bool operator==(const EdgeKey &k) const
- {
- return v0 == k.v0 && v1 == k.v1;
- }
+ EdgeKey(const EdgeKey &k) :
+ v0(k.v0), v1(k.v1) {}
+ EdgeKey(uint32_t v0, uint32_t v1) :
+ v0(v0), v1(v1) {}
+ bool operator==(const EdgeKey &k) const { return v0 == k.v0 && v1 == k.v1; }
uint32_t v0;
uint32_t v1;
};
-AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl)
-{
+AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl) {
XA_DEBUG_ASSERT(atlas);
if (!atlas) {
XA_PRINT_WARNING("AddUvMesh: atlas is null.\n");
@@ -8119,15 +8581,15 @@ AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl)
for (uint32_t i = 0; i < indexCount; i++)
vertexToFaceMap.add(meshInstance->texcoords[mesh->indices[i]]);
internal::BitArray faceAssigned(faceCount);
- faceAssigned.clearAll();
+ faceAssigned.zeroOutMemory();
for (uint32_t f = 0; f < faceCount; f++) {
- if (faceAssigned.bitAt(f))
+ if (faceAssigned.get(f))
continue;
// Found an unassigned face, create a new chart.
internal::UvMeshChart *chart = XA_NEW(internal::MemTag::Default, internal::UvMeshChart);
chart->material = decl.faceMaterialData ? decl.faceMaterialData[f] : 0;
// Walk incident faces and assign them to the chart.
- faceAssigned.setBitAt(f);
+ faceAssigned.set(f);
chart->faces.push_back(f);
for (;;) {
bool newFaceAssigned = false;
@@ -8140,8 +8602,8 @@ AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl)
while (mapIndex != UINT32_MAX) {
const uint32_t face2 = mapIndex / 3; // 3 vertices added per face.
// Materials must match.
- if (!faceAssigned.bitAt(face2) && (!decl.faceMaterialData || decl.faceMaterialData[face] == decl.faceMaterialData[face2])) {
- faceAssigned.setBitAt(face2);
+ if (!faceAssigned.get(face2) && (!decl.faceMaterialData || decl.faceMaterialData[face] == decl.faceMaterialData[face2])) {
+ faceAssigned.set(face2);
chart->faces.push_back(face2);
newFaceAssigned = true;
}
@@ -8170,8 +8632,7 @@ AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl)
return AddMeshError::Success;
}
-void ComputeCharts(Atlas *atlas, ChartOptions chartOptions)
-{
+void ComputeCharts(Atlas *atlas, ChartOptions chartOptions) {
if (!atlas) {
XA_PRINT_WARNING("ComputeCharts: atlas is null.\n");
return;
@@ -8202,6 +8663,7 @@ void ComputeCharts(Atlas *atlas, ChartOptions chartOptions)
continue;
for (uint32_t k = 0; k < chartGroup->chartCount(); k++) {
const internal::param::Chart *chart = chartGroup->chartAt(k);
+#if XA_PRINT_CHART_WARNINGS
if (chart->warningFlags() & internal::param::ChartWarningFlags::CloseHolesFailed)
XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): failed to close holes\n", chartCount, i, j, k);
if (chart->warningFlags() & internal::param::ChartWarningFlags::FixTJunctionsDuplicatedEdge)
@@ -8210,8 +8672,7 @@ void ComputeCharts(Atlas *atlas, ChartOptions chartOptions)
XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): fixing t-junctions failed\n", chartCount, i, j, k);
if (chart->warningFlags() & internal::param::ChartWarningFlags::TriangulateDuplicatedEdge)
XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): triangulation created non-manifold geometry\n", chartCount, i, j, k);
- if (!chart->isDisk())
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): doesn't have disk topology\n", chartCount, i, j, k);
+#endif
holesCount += chart->closedHolesCount();
if (chart->closedHolesCount() > 0)
chartsWithHolesCount++;
@@ -8244,8 +8705,7 @@ void ComputeCharts(Atlas *atlas, ChartOptions chartOptions)
XA_PRINT_MEM_USAGE
}
-void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func)
-{
+void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) {
if (!atlas) {
XA_PRINT_WARNING("ParameterizeCharts: atlas is null.\n");
return;
@@ -8276,10 +8736,10 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func)
XA_PROFILE_START(parameterizeChartsReal)
if (!ctx->paramAtlas.parameterizeCharts(ctx->taskScheduler, func, ctx->progressFunc, ctx->progressUserData)) {
XA_PRINT(" Cancelled by user\n");
- return;
+ return;
}
XA_PROFILE_END(parameterizeChartsReal)
- uint32_t chartCount = 0, orthoChartsCount = 0, planarChartsCount = 0, chartsAddedCount = 0, chartsDeletedCount = 0;
+ uint32_t chartCount = 0, orthoChartsCount = 0, planarChartsCount = 0, lscmChartsCount = 0, piecewiseChartsCount = 0, chartsAddedCount = 0, chartsDeletedCount = 0;
for (uint32_t i = 0; i < ctx->meshCount; i++) {
for (uint32_t j = 0; j < ctx->paramAtlas.chartGroupCount(i); j++) {
const internal::param::ChartGroup *chartGroup = ctx->paramAtlas.chartGroupAt(i, j);
@@ -8287,19 +8747,23 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func)
continue;
for (uint32_t k = 0; k < chartGroup->chartCount(); k++) {
const internal::param::Chart *chart = chartGroup->chartAt(k);
- if (chart->isPlanar())
+ if (chart->type() == ChartType::Planar)
planarChartsCount++;
- else if (chart->isOrtho())
+ else if (chart->type() == ChartType::Ortho)
orthoChartsCount++;
+ else if (chart->type() == ChartType::LSCM)
+ lscmChartsCount++;
+ else if (chart->type() == ChartType::Piecewise)
+ piecewiseChartsCount++;
}
chartCount += chartGroup->chartCount();
chartsAddedCount += chartGroup->paramAddedChartsCount();
chartsDeletedCount += chartGroup->paramDeletedChartsCount();
}
}
- XA_PRINT(" %u planar charts, %u ortho charts, %u other\n", planarChartsCount, orthoChartsCount, chartCount - (planarChartsCount + orthoChartsCount));
+ XA_PRINT(" %u planar charts, %u ortho charts, %u LSCM charts, %u piecewise charts\n", planarChartsCount, orthoChartsCount, lscmChartsCount, piecewiseChartsCount);
if (chartsDeletedCount > 0) {
- XA_PRINT(" %u charts deleted due to invalid parameterizations, %u new charts added\n", chartsDeletedCount, chartsAddedCount);
+ XA_PRINT(" %u charts with invalid parameterizations replaced with %u new charts\n", chartsDeletedCount, chartsAddedCount);
XA_PRINT(" %u charts\n", chartCount);
}
uint32_t chartIndex = 0, invalidParamCount = 0;
@@ -8310,7 +8774,7 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func)
continue;
for (uint32_t k = 0; k < chartGroup->chartCount(); k++) {
const internal::param::Chart *chart = chartGroup->chartAt(k);
- const internal::param::ParameterizationQuality &quality = chart->paramQuality();
+ const internal::param::Quality &quality = chart->quality();
#if XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION
{
char filename[256];
@@ -8319,13 +8783,20 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func)
}
#endif
bool invalid = false;
+ const char *type = "LSCM";
+ if (chart->type() == ChartType::Planar)
+ type = "planar";
+ else if (chart->type() == ChartType::Ortho)
+ type = "ortho";
+ else if (chart->type() == ChartType::Piecewise)
+ type = "piecewise";
if (quality.boundaryIntersection) {
invalid = true;
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, self-intersecting boundary.\n", chartIndex, i, j, k, chart->isPlanar() ? "planar" : chart->isOrtho() ? "ortho" : "other");
+ XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, self-intersecting boundary.\n", chartIndex, i, j, k, type);
}
if (quality.flippedTriangleCount > 0) {
invalid = true;
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, %u / %u flipped triangles.\n", chartIndex, i, j, k, chart->isPlanar() ? "planar" : chart->isOrtho() ? "ortho" : "other", quality.flippedTriangleCount, quality.totalTriangleCount);
+ XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, %u / %u flipped triangles.\n", chartIndex, i, j, k, type, quality.flippedTriangleCount, quality.totalTriangleCount);
}
if (invalid)
invalidParamCount++;
@@ -8367,8 +8838,7 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func)
XA_PRINT_MEM_USAGE
}
-void PackCharts(Atlas *atlas, PackOptions packOptions)
-{
+void PackCharts(Atlas *atlas, PackOptions packOptions) {
// Validate arguments and context state.
if (!atlas) {
XA_PRINT_WARNING("PackCharts: atlas is null.\n");
@@ -8410,12 +8880,11 @@ void PackCharts(Atlas *atlas, PackOptions packOptions)
if (!ctx->uvMeshInstances.isEmpty()) {
for (uint32_t i = 0; i < ctx->uvMeshInstances.size(); i++)
packAtlas.addUvMeshCharts(ctx->uvMeshInstances[i]);
- }
- else
+ } else
packAtlas.addCharts(ctx->taskScheduler, &ctx->paramAtlas);
XA_PROFILE_END(packChartsAddCharts)
XA_PROFILE_START(packCharts)
- if (!packAtlas.packCharts(ctx->taskScheduler, packOptions, ctx->progressFunc, ctx->progressUserData))
+ if (!packAtlas.packCharts(packOptions, ctx->progressFunc, ctx->progressUserData))
return;
XA_PROFILE_END(packCharts)
// Populate atlas object with pack results.
@@ -8440,8 +8909,7 @@ void PackCharts(Atlas *atlas, PackOptions packOptions)
XA_PROFILE_PRINT_AND_RESET(" Restore texcoords: ", packChartsAddChartsRestoreTexcoords)
XA_PROFILE_PRINT_AND_RESET(" Rasterize: ", packChartsRasterize)
XA_PROFILE_PRINT_AND_RESET(" Dilate (padding): ", packChartsDilate)
- XA_PROFILE_PRINT_AND_RESET(" Find location (real): ", packChartsFindLocation)
- XA_PROFILE_PRINT_AND_RESET(" Find location (thread): ", packChartsFindLocationThread)
+ XA_PROFILE_PRINT_AND_RESET(" Find location: ", packChartsFindLocation)
XA_PROFILE_PRINT_AND_RESET(" Blit: ", packChartsBlit)
XA_PRINT_MEM_USAGE
XA_PRINT("Building output meshes\n");
@@ -8527,9 +8995,7 @@ void PackCharts(Atlas *atlas, PackOptions packOptions)
const int32_t atlasIndex = packAtlas.getChart(chartIndex)->atlasIndex;
XA_DEBUG_ASSERT(atlasIndex >= 0);
outputChart->atlasIndex = (uint32_t)atlasIndex;
- outputChart->flags = 0;
- if (chart->paramQuality().boundaryIntersection || chart->paramQuality().flippedTriangleCount > 0)
- outputChart->flags |= ChartFlags::Invalid;
+ outputChart->type = chart->type();
outputChart->faceCount = mesh->faceCount();
outputChart->faceArray = XA_ALLOC_ARRAY(internal::MemTag::Default, uint32_t, outputChart->faceCount);
for (uint32_t f = 0; f < outputChart->faceCount; f++)
@@ -8615,8 +9081,7 @@ void PackCharts(Atlas *atlas, PackOptions packOptions)
XA_PRINT_MEM_USAGE
}
-void Generate(Atlas *atlas, ChartOptions chartOptions, ParameterizeFunc paramFunc, PackOptions packOptions)
-{
+void Generate(Atlas *atlas, ChartOptions chartOptions, ParameterizeFunc paramFunc, PackOptions packOptions) {
if (!atlas) {
XA_PRINT_WARNING("Generate: atlas is null.\n");
return;
@@ -8635,8 +9100,7 @@ void Generate(Atlas *atlas, ChartOptions chartOptions, ParameterizeFunc paramFun
PackCharts(atlas, packOptions);
}
-void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc, void *progressUserData)
-{
+void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc, void *progressUserData) {
if (!atlas) {
XA_PRINT_WARNING("SetProgressCallback: atlas is null.\n");
return;
@@ -8646,20 +9110,17 @@ void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc, void *progress
ctx->progressUserData = progressUserData;
}
-void SetAlloc(ReallocFunc reallocFunc, FreeFunc freeFunc)
-{
+void SetAlloc(ReallocFunc reallocFunc, FreeFunc freeFunc) {
internal::s_realloc = reallocFunc;
internal::s_free = freeFunc;
}
-void SetPrint(PrintFunc print, bool verbose)
-{
+void SetPrint(PrintFunc print, bool verbose) {
internal::s_print = print;
internal::s_printVerbose = verbose;
}
-const char *StringForEnum(AddMeshError::Enum error)
-{
+const char *StringForEnum(AddMeshError::Enum error) {
if (error == AddMeshError::Error)
return "Unspecified error";
if (error == AddMeshError::IndexOutOfRange)
@@ -8669,8 +9130,7 @@ const char *StringForEnum(AddMeshError::Enum error)
return "Success";
}
-const char *StringForEnum(ProgressCategory::Enum category)
-{
+const char *StringForEnum(ProgressCategory::Enum category) {
if (category == ProgressCategory::AddMesh)
return "Adding mesh(es)";
if (category == ProgressCategory::ComputeCharts)
diff --git a/thirdparty/xatlas/xatlas.h b/thirdparty/xatlas/xatlas.h
index 7be165e7e5..e59f493287 100644
--- a/thirdparty/xatlas/xatlas.h
+++ b/thirdparty/xatlas/xatlas.h
@@ -35,11 +35,14 @@ Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
namespace xatlas {
-struct ChartFlags
+struct ChartType
{
- enum
+ enum Enum
{
- Invalid = 1 << 0
+ Planar,
+ Ortho,
+ LSCM,
+ Piecewise
};
};
@@ -47,10 +50,10 @@ struct ChartFlags
struct Chart
{
uint32_t atlasIndex; // Sub-atlas index.
- uint32_t flags;
uint32_t *faceArray;
uint32_t faceCount;
uint32_t material;
+ ChartType::Enum type;
};
// Output vertex.